summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1997-04-18 00:57:04 +0000
committerUlrich Drepper <drepper@redhat.com>1997-04-18 00:57:04 +0000
commitf0a39e37f1bd7bcc8d6988345df5870d91c92cce (patch)
tree063fa517655b571179bcd74d8719409852b25477
parent2b385e3555b76372ce8e19020673854a46a5ac63 (diff)
downloademacs-f0a39e37f1bd7bcc8d6988345df5870d91c92cce.tar.gz
update from main archive 970417libc20x-970417glibc-2_0_4
-rw-r--r--=PROBLEMS744
-rw-r--r--GETTING.GNU.SOFTWARE112
-rw-r--r--INSTALL615
-rw-r--r--Makefile.in539
-rwxr-xr-xbuild-ins.in136
-rw-r--r--config.bat218
-rwxr-xr-xconfig.guess32
-rw-r--r--configure.in1758
-rwxr-xr-xconfigure1.in1812
-rw-r--r--etc/=MACHINES894
-rw-r--r--etc/=TO-DO83
-rw-r--r--etc/=news.texi3380
-rw-r--r--etc/FAQ3168
-rw-r--r--etc/Makefile33
-rw-r--r--etc/README7
-rw-r--r--etc/TUTORIAL1014
-rw-r--r--etc/enriched.doc263
-rw-r--r--etc/rgb.txt788
-rw-r--r--etc/sex.6115
-rw-r--r--etc/spook.linesbin950 -> 0 bytes
-rw-r--r--etc/tasks.texi433
-rw-r--r--etc/termcap.dat1246
-rw-r--r--etc/yow.linesbin52472 -> 0 bytes
-rw-r--r--lib-src/=aixcc.lex301
-rw-r--r--lib-src/=etags-vmslib.c155
-rw-r--r--lib-src/=rcs2log612
-rw-r--r--lib-src/=timer.c368
-rw-r--r--lib-src/=wakeup.c53
-rw-r--r--lib-src/Makefile.in419
-rw-r--r--lib-src/b2m.c267
-rw-r--r--lib-src/cvtmail.c179
-rw-r--r--lib-src/digest-doc.c49
-rw-r--r--lib-src/emacsclient.c494
-rw-r--r--lib-src/emacsserver.c564
-rw-r--r--lib-src/emacstool.c500
-rw-r--r--lib-src/env.c353
-rw-r--r--lib-src/etags.c4577
-rw-r--r--lib-src/fakemail.c751
-rw-r--r--lib-src/hexl.c262
-rw-r--r--lib-src/leditcfns.c18
-rw-r--r--lib-src/make-docfile.c887
-rw-r--r--lib-src/make-path.c105
-rw-r--r--lib-src/makefile.nt357
-rw-r--r--lib-src/movemail.c752
-rw-r--r--lib-src/ntlib.c216
-rw-r--r--lib-src/ntlib.h46
-rw-r--r--lib-src/pop.c1555
-rw-r--r--lib-src/pop.h82
-rw-r--r--lib-src/profile.c104
-rwxr-xr-xlib-src/rcs-checkin98
-rwxr-xr-xlib-src/rcs2log612
-rw-r--r--lib-src/sorted-doc.c254
-rw-r--r--lib-src/tcp.c242
-rw-r--r--lib-src/test-distrib.c84
-rwxr-xr-xlib-src/vcdiff93
-rw-r--r--lib-src/yow.c165
-rw-r--r--lisp/=ada.el734
-rw-r--r--lisp/=batmode.el165
-rw-r--r--lisp/=bytecpat.el15
-rw-r--r--lisp/=cl.el3162
-rw-r--r--lisp/=cmulisp.el694
-rw-r--r--lisp/=custom.el2472
-rw-r--r--lisp/=diary-ins.el251
-rw-r--r--lisp/=diary-lib.el1919
-rw-r--r--lisp/=ftp.el392
-rw-r--r--lisp/=gnus-uu.el3057
-rw-r--r--lisp/=gnus.el7243
-rw-r--r--lisp/=gnusmail.el220
-rw-r--r--lisp/=gnusmisc.el294
-rw-r--r--lisp/=gnuspost.el842
-rw-r--r--lisp/=gosmacs.el117
-rw-r--r--lisp/=grow-vers.el41
-rw-r--r--lisp/=inc-vers.el54
-rw-r--r--lisp/=isearch-old.el608
-rw-r--r--lisp/=iso8859-1.el104
-rw-r--r--lisp/=man.el181
-rw-r--r--lisp/=medit.el123
-rw-r--r--lisp/=mh-e.el2933
-rw-r--r--lisp/=mhspool.el490
-rw-r--r--lisp/=mim-mode.el848
-rw-r--r--lisp/=mim-syntax.el95
-rw-r--r--lisp/=netunam.el160
-rw-r--r--lisp/=nnspool.el409
-rw-r--r--lisp/=nntp.el698
-rw-r--r--lisp/=old-shell.el399
-rw-r--r--lisp/=sc-alist.el134
-rw-r--r--lisp/=sc-elec.el198
-rw-r--r--lisp/=sc.el1547
-rw-r--r--lisp/=sun-keys.el77
-rw-r--r--lisp/=superyank.el1243
-rw-r--r--lisp/=term-nasty.el12
-rw-r--r--lisp/=timer.el223
-rw-r--r--lisp/=tpu-doc.el469
-rw-r--r--lisp/=vmsx.el144
-rw-r--r--lisp/=word-help.el970
-rw-r--r--lisp/abbrev.el299
-rw-r--r--lisp/abbrevlist.el53
-rw-r--r--lisp/add-log.el596
-rw-r--r--lisp/allout.el4339
-rw-r--r--lisp/ange-ftp.el5479
-rw-r--r--lisp/apropos.el603
-rw-r--r--lisp/arc-mode.el1482
-rw-r--r--lisp/array.el949
-rw-r--r--lisp/auto-show.el114
-rw-r--r--lisp/autoinsert.el255
-rw-r--r--lisp/avoid.el359
-rw-r--r--lisp/bindings.el554
-rw-r--r--lisp/bookmark.el2214
-rw-r--r--lisp/browse-url.el764
-rw-r--r--lisp/buff-menu.el550
-rw-r--r--lisp/byte-run.el161
-rw-r--r--lisp/calendar/appt.el600
-rw-r--r--lisp/calendar/cal-china.el455
-rw-r--r--lisp/calendar/cal-coptic.el234
-rw-r--r--lisp/calendar/cal-dst.el397
-rw-r--r--lisp/calendar/cal-french.el244
-rw-r--r--lisp/calendar/cal-hebrew.el1180
-rw-r--r--lisp/calendar/cal-islam.el492
-rw-r--r--lisp/calendar/cal-iso.el126
-rw-r--r--lisp/calendar/cal-julian.el207
-rw-r--r--lisp/calendar/cal-mayan.el382
-rw-r--r--lisp/calendar/cal-menu.el523
-rw-r--r--lisp/calendar/cal-move.el315
-rw-r--r--lisp/calendar/cal-persia.el206
-rw-r--r--lisp/calendar/cal-tex.el1608
-rw-r--r--lisp/calendar/cal-x.el143
-rw-r--r--lisp/calendar/calendar.el2336
-rw-r--r--lisp/calendar/diary-lib.el1392
-rw-r--r--lisp/calendar/holidays.el384
-rw-r--r--lisp/calendar/lunar.el391
-rw-r--r--lisp/calendar/solar.el1045
-rw-r--r--lisp/case-table.el121
-rw-r--r--lisp/cdl.el44
-rw-r--r--lisp/chistory.el174
-rw-r--r--lisp/cmuscheme.el413
-rw-r--r--lisp/comint.el2213
-rw-r--r--lisp/compare-w.el173
-rw-r--r--lisp/complete.el898
-rw-r--r--lisp/completion.el2683
-rw-r--r--lisp/dabbrev.el867
-rw-r--r--lisp/delsel.el119
-rw-r--r--lisp/derived.el352
-rw-r--r--lisp/desktop.el587
-rw-r--r--lisp/diff.el303
-rw-r--r--lisp/dired-aux.el1894
-rw-r--r--lisp/dired-x.el1698
-rw-r--r--lisp/dired.el2506
-rw-r--r--lisp/dirtrack.el244
-rw-r--r--lisp/disp-table.el198
-rw-r--r--lisp/docref.el282
-rw-r--r--lisp/dos-fns.el208
-rw-r--r--lisp/dos-w32.el169
-rw-r--r--lisp/dos-win32.el170
-rw-r--r--lisp/double.el200
-rw-r--r--lisp/ebuff-menu.el265
-rw-r--r--lisp/echistory.el150
-rw-r--r--lisp/ediff-diff.el1210
-rw-r--r--lisp/ediff-help.el311
-rw-r--r--lisp/ediff-hook.el352
-rw-r--r--lisp/ediff-init.el1612
-rw-r--r--lisp/ediff-merg.el275
-rw-r--r--lisp/ediff-mult.el1724
-rw-r--r--lisp/ediff-ptch.el630
-rw-r--r--lisp/ediff-util.el3599
-rw-r--r--lisp/ediff-vers.el367
-rw-r--r--lisp/ediff-wind.el1210
-rw-r--r--lisp/ediff.el1279
-rw-r--r--lisp/edmacro.el723
-rw-r--r--lisp/ehelp.el396
-rw-r--r--lisp/electric.el178
-rw-r--r--lisp/emacs-lisp/advice.el3960
-rw-r--r--lisp/emacs-lisp/assoc.el140
-rw-r--r--lisp/emacs-lisp/autoload.el416
-rw-r--r--lisp/emacs-lisp/backquote.el212
-rw-r--r--lisp/emacs-lisp/byte-opt.el1872
-rw-r--r--lisp/emacs-lisp/bytecomp.el3427
-rw-r--r--lisp/emacs-lisp/cl-compat.el192
-rw-r--r--lisp/emacs-lisp/cl-extra.el924
-rw-r--r--lisp/emacs-lisp/cl-indent.el474
-rw-r--r--lisp/emacs-lisp/cl-macs.el2635
-rw-r--r--lisp/emacs-lisp/cl-seq.el919
-rw-r--r--lisp/emacs-lisp/cl-specs.el472
-rw-r--r--lisp/emacs-lisp/cl.el765
-rw-r--r--lisp/emacs-lisp/copyright.el143
-rw-r--r--lisp/emacs-lisp/cust-print.el725
-rw-r--r--lisp/emacs-lisp/debug.el491
-rw-r--r--lisp/emacs-lisp/disass.el266
-rw-r--r--lisp/emacs-lisp/easymenu.el244
-rw-r--r--lisp/emacs-lisp/edebug.el4515
-rw-r--r--lisp/emacs-lisp/eldoc.el458
-rw-r--r--lisp/emacs-lisp/elp.el563
-rw-r--r--lisp/emacs-lisp/eval-reg.el219
-rw-r--r--lisp/emacs-lisp/float.el458
-rw-r--r--lisp/emacs-lisp/gulp.el152
-rw-r--r--lisp/emacs-lisp/helper.el157
-rw-r--r--lisp/emacs-lisp/levents.el233
-rw-r--r--lisp/emacs-lisp/lisp-mnt.el554
-rw-r--r--lisp/emacs-lisp/lisp-mode.el838
-rw-r--r--lisp/emacs-lisp/lisp.el316
-rw-r--r--lisp/emacs-lisp/lmenu.el506
-rw-r--r--lisp/emacs-lisp/lselect.el230
-rw-r--r--lisp/emacs-lisp/lucid.el223
-rw-r--r--lisp/emacs-lisp/pp.el181
-rw-r--r--lisp/emacs-lisp/profile.el325
-rw-r--r--lisp/emacs-lisp/ring.el135
-rw-r--r--lisp/emacs-lisp/shadow.el203
-rw-r--r--lisp/emacs-lisp/tq.el123
-rw-r--r--lisp/emacs-lisp/trace.el314
-rw-r--r--lisp/emacs-lock.el68
-rw-r--r--lisp/emerge.el3173
-rw-r--r--lisp/emulation/edt-lk201.el55
-rw-r--r--lisp/emulation/edt-mapper.el405
-rw-r--r--lisp/emulation/edt-pc.el85
-rw-r--r--lisp/emulation/edt-vt100.el44
-rw-r--r--lisp/emulation/edt.el2018
-rw-r--r--lisp/emulation/mlconvert.el288
-rw-r--r--lisp/emulation/mlsupport.el435
-rw-r--r--lisp/emulation/pc-mode.el52
-rw-r--r--lisp/emulation/pc-select.el689
-rw-r--r--lisp/emulation/tpu-edt.el2490
-rw-r--r--lisp/emulation/tpu-extras.el477
-rw-r--r--lisp/emulation/tpu-mapper.el395
-rw-r--r--lisp/emulation/vi.el1467
-rw-r--r--lisp/emulation/vip.el3045
-rw-r--r--lisp/emulation/viper-ex.el2029
-rw-r--r--lisp/emulation/viper-keym.el584
-rw-r--r--lisp/emulation/viper-macs.el943
-rw-r--r--lisp/emulation/viper-mous.el459
-rw-r--r--lisp/emulation/viper-util.el1269
-rw-r--r--lisp/emulation/viper.el5892
-rw-r--r--lisp/emulation/ws-mode.el753
-rw-r--r--lisp/enriched.el447
-rw-r--r--lisp/env.el114
-rw-r--r--lisp/expand.el496
-rw-r--r--lisp/facemenu.el658
-rw-r--r--lisp/faces.el1313
-rw-r--r--lisp/fast-lock.el735
-rw-r--r--lisp/ffap.el1433
-rw-r--r--lisp/files.el2863
-rw-r--r--lisp/find-dired.el212
-rw-r--r--lisp/find-file.el913
-rw-r--r--lisp/find-gc.el152
-rw-r--r--lisp/finder.el299
-rw-r--r--lisp/float-sup.el60
-rw-r--r--lisp/flow-ctrl.el126
-rw-r--r--lisp/foldout.el570
-rw-r--r--lisp/follow.el2430
-rw-r--r--lisp/font-lock.el2409
-rw-r--r--lisp/format.el813
-rw-r--r--lisp/forms-pass.el25
-rw-r--r--lisp/forms.el2049
-rw-r--r--lisp/frame.el727
-rw-r--r--lisp/gnus-cache.el623
-rw-r--r--lisp/gnus-cite.el732
-rw-r--r--lisp/gnus-cus.el683
-rw-r--r--lisp/gnus-demon.el222
-rw-r--r--lisp/gnus-edit.el630
-rw-r--r--lisp/gnus-ems.el242
-rw-r--r--lisp/gnus-gl.el872
-rw-r--r--lisp/gnus-kill.el655
-rw-r--r--lisp/gnus-mh.el105
-rw-r--r--lisp/gnus-msg.el929
-rw-r--r--lisp/gnus-nocem.el247
-rw-r--r--lisp/gnus-salt.el654
-rw-r--r--lisp/gnus-scomo.el110
-rw-r--r--lisp/gnus-score.el2258
-rw-r--r--lisp/gnus-setup.el210
-rw-r--r--lisp/gnus-soup.el563
-rw-r--r--lisp/gnus-srvr.el708
-rw-r--r--lisp/gnus-topic.el1057
-rw-r--r--lisp/gnus-uu.el1951
-rw-r--r--lisp/gnus-vis.el1615
-rw-r--r--lisp/gnus-vm.el111
-rw-r--r--lisp/gnus.el17270
-rw-r--r--lisp/goto-addr.el241
-rw-r--r--lisp/gud.el1628
-rw-r--r--lisp/help-macro.el177
-rw-r--r--lisp/help.el705
-rw-r--r--lisp/hexl.el789
-rw-r--r--lisp/hilit19.el1512
-rw-r--r--lisp/hippie-exp.el1127
-rw-r--r--lisp/hscroll.el233
-rw-r--r--lisp/icomplete.el287
-rw-r--r--lisp/ielm.el472
-rw-r--r--lisp/imenu.el920
-rw-r--r--lisp/indent.el467
-rw-r--r--lisp/info.el1968
-rw-r--r--lisp/informat.el429
-rw-r--r--lisp/international/iso-acc.el419
-rw-r--r--lisp/international/iso-ascii.el146
-rw-r--r--lisp/international/iso-cvt.el717
-rw-r--r--lisp/international/iso-insert.el629
-rw-r--r--lisp/international/iso-swed.el151
-rw-r--r--lisp/international/iso-transl.el259
-rw-r--r--lisp/international/latin-2.el94
-rw-r--r--lisp/international/swedish.el154
-rw-r--r--lisp/isearch.el1451
-rw-r--r--lisp/iso02-acc.el124
-rw-r--r--lisp/jka-compr.el842
-rw-r--r--lisp/kermit.el149
-rw-r--r--lisp/lazy-lock.el1047
-rw-r--r--lisp/ledit.el155
-rw-r--r--lisp/loadhist.el149
-rw-r--r--lisp/loadup.el253
-rw-r--r--lisp/locate.el365
-rw-r--r--lisp/lpr.el188
-rw-r--r--lisp/ls-lisp.el270
-rw-r--r--lisp/macros.el306
-rw-r--r--lisp/mail/blessmail.el69
-rw-r--r--lisp/mail/emacsbug.el153
-rw-r--r--lisp/mail/mail-extr.el1987
-rw-r--r--lisp/mail/mail-hist.el302
-rw-r--r--lisp/mail/mail-utils.el254
-rw-r--r--lisp/mail/mailabbrev.el576
-rw-r--r--lisp/mail/mailalias.el441
-rw-r--r--lisp/mail/mailheader.el183
-rw-r--r--lisp/mail/mailpost.el103
-rw-r--r--lisp/mail/metamail.el200
-rw-r--r--lisp/mail/mh-comp.el1052
-rw-r--r--lisp/mail/mh-e.el1484
-rw-r--r--lisp/mail/mh-funcs.el354
-rw-r--r--lisp/mail/mh-mime.el236
-rw-r--r--lisp/mail/mh-pick.el195
-rw-r--r--lisp/mail/mh-seq.el237
-rw-r--r--lisp/mail/mh-utils.el953
-rw-r--r--lisp/mail/reporter.el437
-rw-r--r--lisp/mail/rfc822.el319
-rw-r--r--lisp/mail/rmail.el2715
-rw-r--r--lisp/mail/rmailedit.el121
-rw-r--r--lisp/mail/rmailkwd.el269
-rw-r--r--lisp/mail/rmailmsc.el55
-rw-r--r--lisp/mail/rmailout.el322
-rw-r--r--lisp/mail/rmailsort.el245
-rw-r--r--lisp/mail/rmailsum.el1531
-rw-r--r--lisp/mail/rnews.el989
-rw-r--r--lisp/mail/rnewspost.el439
-rw-r--r--lisp/mail/sendmail.el1228
-rw-r--r--lisp/mail/smtpmail.el525
-rw-r--r--lisp/mail/supercite.el2020
-rw-r--r--lisp/mail/undigest.el184
-rw-r--r--lisp/mail/unrmail.el66
-rw-r--r--lisp/mail/vms-pmail.el117
-rw-r--r--lisp/makefile.nt42
-rw-r--r--lisp/makesum.el114
-rw-r--r--lisp/man.el1062
-rw-r--r--lisp/map-ynp.el255
-rw-r--r--lisp/menu-bar.el700
-rw-r--r--lisp/message.el2996
-rw-r--r--lisp/misc.el58
-rw-r--r--lisp/mldrag.el228
-rw-r--r--lisp/mouse-copy.el249
-rw-r--r--lisp/mouse-drag.el345
-rw-r--r--lisp/mouse-sel.el646
-rw-r--r--lisp/mouse.el1845
-rw-r--r--lisp/msb.el1002
-rw-r--r--lisp/nnbabyl.el625
-rw-r--r--lisp/nndb.el229
-rw-r--r--lisp/nndir.el99
-rw-r--r--lisp/nndoc.el482
-rw-r--r--lisp/nneething.el356
-rw-r--r--lisp/nnfolder.el784
-rw-r--r--lisp/nnheader.el620
-rw-r--r--lisp/nnheaderems.el201
-rw-r--r--lisp/nnkiboze.el388
-rw-r--r--lisp/nnmail.el1201
-rw-r--r--lisp/nnmbox.el533
-rw-r--r--lisp/nnmh.el520
-rw-r--r--lisp/nnml.el764
-rw-r--r--lisp/nnoo.el251
-rw-r--r--lisp/nnsoup.el747
-rw-r--r--lisp/nnspool.el511
-rw-r--r--lisp/nntp.el1336
-rw-r--r--lisp/nnvirtual.el409
-rw-r--r--lisp/novice.el145
-rw-r--r--lisp/options.el142
-rw-r--r--lisp/paren.el181
-rw-r--r--lisp/patcomp.el15
-rw-r--r--lisp/paths.el155
-rw-r--r--lisp/play/blackbox.el421
-rw-r--r--lisp/play/cookie1.el165
-rw-r--r--lisp/play/decipher.el1057
-rw-r--r--lisp/play/dissociate.el101
-rw-r--r--lisp/play/doctor.el1614
-rw-r--r--lisp/play/dunnet.el3343
-rw-r--r--lisp/play/gomoku.el1182
-rw-r--r--lisp/play/handwrite.el1376
-rw-r--r--lisp/play/hanoi.el227
-rw-r--r--lisp/play/life.el283
-rw-r--r--lisp/play/meese.el27
-rw-r--r--lisp/play/morse.el121
-rw-r--r--lisp/play/mpuz.el443
-rw-r--r--lisp/play/solitaire.el455
-rw-r--r--lisp/play/spook.el69
-rw-r--r--lisp/play/studly.el63
-rw-r--r--lisp/play/yow.el130
-rw-r--r--lisp/progmodes/ada-mode.el3741
-rw-r--r--lisp/progmodes/asm-mode.el231
-rw-r--r--lisp/progmodes/awk-mode.el153
-rw-r--r--lisp/progmodes/c-mode.el1650
-rw-r--r--lisp/progmodes/cmacexp.el371
-rw-r--r--lisp/progmodes/compile.el1583
-rw-r--r--lisp/progmodes/cplus-md.el1061
-rw-r--r--lisp/progmodes/cpp.el782
-rw-r--r--lisp/progmodes/etags.el1606
-rw-r--r--lisp/progmodes/executable.el235
-rw-r--r--lisp/progmodes/f90.el1697
-rw-r--r--lisp/progmodes/fortran.el1589
-rw-r--r--lisp/progmodes/hideif.el1048
-rw-r--r--lisp/progmodes/hideshow.el492
-rw-r--r--lisp/progmodes/icon.el556
-rw-r--r--lisp/progmodes/inf-lisp.el642
-rw-r--r--lisp/progmodes/m4-mode.el152
-rw-r--r--lisp/progmodes/make-mode.el1396
-rw-r--r--lisp/progmodes/modula2.el454
-rw-r--r--lisp/progmodes/pascal.el1560
-rw-r--r--lisp/progmodes/perl-mode.el732
-rw-r--r--lisp/progmodes/prolog.el273
-rw-r--r--lisp/progmodes/scheme.el515
-rw-r--r--lisp/progmodes/sh-script.el1388
-rw-r--r--lisp/progmodes/simula.el1773
-rw-r--r--lisp/progmodes/tcl.el2227
-rw-r--r--lisp/ps-print.el2931
-rw-r--r--lisp/rcompile.el163
-rw-r--r--lisp/rect.el246
-rw-r--r--lisp/regi.el255
-rw-r--r--lisp/register.el272
-rw-r--r--lisp/replace.el741
-rw-r--r--lisp/reposition.el198
-rw-r--r--lisp/resume.el128
-rw-r--r--lisp/rlogin.el335
-rw-r--r--lisp/rot13.el67
-rw-r--r--lisp/rsz-mini.el254
-rw-r--r--lisp/s-region.el124
-rw-r--r--lisp/saveplace.el229
-rw-r--r--lisp/score-mode.el110
-rw-r--r--lisp/scroll-bar.el241
-rw-r--r--lisp/select.el310
-rw-r--r--lisp/server.el445
-rw-r--r--lisp/shadowfile.el843
-rw-r--r--lisp/shell.el853
-rw-r--r--lisp/simple.el3269
-rw-r--r--lisp/skeleton.el592
-rw-r--r--lisp/sort.el523
-rw-r--r--lisp/soundex.el74
-rw-r--r--lisp/startup.el968
-rw-r--r--lisp/subr.el975
-rw-r--r--lisp/sun-curs.el217
-rw-r--r--lisp/sun-fns.el642
-rw-r--r--lisp/tabify.el75
-rw-r--r--lisp/talk.el101
-rw-r--r--lisp/tar-mode.el1207
-rw-r--r--lisp/tcp.el75
-rw-r--r--lisp/telnet.el237
-rw-r--r--lisp/tempo.el764
-rw-r--r--lisp/term.el3261
-rw-r--r--lisp/term/README214
-rw-r--r--lisp/term/apollo.el1
-rw-r--r--lisp/term/bg-mouse.el313
-rw-r--r--lisp/term/bobcat.el2
-rw-r--r--lisp/term/internal.el91
-rw-r--r--lisp/term/keyswap.el41
-rw-r--r--lisp/term/lk201.el68
-rw-r--r--lisp/term/news.el73
-rw-r--r--lisp/term/pc-win.el329
-rw-r--r--lisp/term/sun-mouse.el681
-rw-r--r--lisp/term/sun.el280
-rw-r--r--lisp/term/sup-mouse.el208
-rw-r--r--lisp/term/tvi970.el126
-rw-r--r--lisp/term/vt100.el56
-rw-r--r--lisp/term/vt200.el6
-rw-r--r--lisp/term/vt201.el7
-rw-r--r--lisp/term/vt220.el7
-rw-r--r--lisp/term/vt240.el6
-rw-r--r--lisp/term/w32-win.el669
-rw-r--r--lisp/term/wyse50.el151
-rw-r--r--lisp/term/x-win.el711
-rw-r--r--lisp/term/xterm.el47
-rw-r--r--lisp/terminal.el1320
-rw-r--r--lisp/textmodes/=ispell4.el1091
-rw-r--r--lisp/textmodes/bib-mode.el241
-rw-r--r--lisp/textmodes/bibtex.el2450
-rw-r--r--lisp/textmodes/fill.el858
-rw-r--r--lisp/textmodes/ispell.el2412
-rw-r--r--lisp/textmodes/makeinfo.el247
-rw-r--r--lisp/textmodes/nroff-mode.el270
-rw-r--r--lisp/textmodes/ooutline.el573
-rw-r--r--lisp/textmodes/outline.el651
-rw-r--r--lisp/textmodes/page-ext.el772
-rw-r--r--lisp/textmodes/page.el161
-rw-r--r--lisp/textmodes/paragraphs.el389
-rw-r--r--lisp/textmodes/picture.el646
-rw-r--r--lisp/textmodes/refbib.el730
-rw-r--r--lisp/textmodes/refer.el387
-rw-r--r--lisp/textmodes/scribe.el325
-rw-r--r--lisp/textmodes/sgml-mode.el1262
-rw-r--r--lisp/textmodes/spell.el154
-rw-r--r--lisp/textmodes/tex-mode.el1239
-rw-r--r--lisp/textmodes/texinfmt.el3058
-rw-r--r--lisp/textmodes/texinfo.el752
-rw-r--r--lisp/textmodes/texnfo-upd.el2049
-rw-r--r--lisp/textmodes/text-mode.el172
-rw-r--r--lisp/textmodes/two-column.el624
-rw-r--r--lisp/textmodes/underline.el63
-rw-r--r--lisp/thingatpt.el256
-rw-r--r--lisp/time-stamp.el346
-rw-r--r--lisp/time.el220
-rw-r--r--lisp/timer.el453
-rw-r--r--lisp/timezone.el397
-rw-r--r--lisp/tmm.el471
-rw-r--r--lisp/type-break.el688
-rw-r--r--lisp/uncompress.el97
-rw-r--r--lisp/uniquify.el384
-rw-r--r--lisp/unused.el44
-rw-r--r--lisp/userlock.el149
-rw-r--r--lisp/vc-hooks.el1075
-rw-r--r--lisp/vc.el2792
-rw-r--r--lisp/view.el469
-rw-r--r--lisp/vms-patch.el192
-rw-r--r--lisp/vmsproc.el146
-rw-r--r--lisp/vt-control.el107
-rw-r--r--lisp/vt100-led.el68
-rw-r--r--lisp/w32-fns.el88
-rw-r--r--lisp/webjump.el427
-rw-r--r--lisp/window.el298
-rw-r--r--lisp/x-apollo.el90
-rw-r--r--lisp/x-menu.el145
-rw-r--r--lisp/xscheme.el878
-rw-r--r--lisp/xt-mouse.el190
-rw-r--r--lispref/=buffer-local.texi94
-rw-r--r--lispref/Makefile.in129
-rw-r--r--lispref/README50
-rw-r--r--lispref/abbrevs.texi344
-rw-r--r--lispref/anti.texi619
-rw-r--r--lispref/backups.texi648
-rw-r--r--lispref/book-spine.texinfo25
-rw-r--r--lispref/buffers.texi911
-rw-r--r--lispref/calendar.texi908
-rw-r--r--lispref/commands.texi2493
-rw-r--r--lispref/compile.texi731
-rw-r--r--lispref/control.texi1157
-rw-r--r--lispref/debugging.texi724
-rw-r--r--lispref/display.texi1464
-rw-r--r--lispref/edebug.texi1545
-rw-r--r--lispref/elisp-covers.texi248
-rw-r--r--lispref/elisp-vol1.texi1047
-rw-r--r--lispref/elisp-vol2.texi1046
-rw-r--r--lispref/elisp.texi942
-rw-r--r--lispref/errors.texi158
-rw-r--r--lispref/eval.texi706
-rw-r--r--lispref/files.texi2254
-rw-r--r--lispref/frames.texi1363
-rw-r--r--lispref/front-cover-1.texi52
-rw-r--r--lispref/functions.texi1138
-rw-r--r--lispref/help.texi627
-rw-r--r--lispref/hooks.texi129
-rw-r--r--lispref/internals.texi960
-rw-r--r--lispref/intro.texi866
-rw-r--r--lispref/keymaps.texi1776
-rw-r--r--lispref/lists.texi1416
-rw-r--r--lispref/loading.texi680
-rw-r--r--lispref/locals.texi150
-rw-r--r--lispref/macros.texi579
-rw-r--r--lispref/maps.texi190
-rw-r--r--lispref/markers.texi579
-rw-r--r--lispref/minibuf.texi1452
-rw-r--r--lispref/modes.texi1425
-rw-r--r--lispref/numbers.texi1034
-rw-r--r--lispref/objects.texi1592
-rw-r--r--lispref/os.texi1700
-rw-r--r--lispref/positions.texi897
-rw-r--r--lispref/processes.texi1233
-rw-r--r--lispref/searching.texi1368
-rw-r--r--lispref/sequences.texi493
-rw-r--r--lispref/streams.texi735
-rw-r--r--lispref/strings.texi828
-rw-r--r--lispref/symbols.texi528
-rw-r--r--lispref/syntax.texi723
-rw-r--r--lispref/text.texi3016
-rw-r--r--lispref/tips.texi683
-rw-r--r--lispref/variables.texi1427
-rw-r--r--lispref/windows.texi1817
-rw-r--r--lwlib/Makefile.in79
-rw-r--r--lwlib/dispatch.c271
-rw-r--r--lwlib/lwlib-Xaw.c648
-rw-r--r--lwlib/lwlib-Xaw.h29
-rw-r--r--lwlib/lwlib-Xlw.c228
-rw-r--r--lwlib/lwlib-Xlw.h29
-rw-r--r--lwlib/lwlib-Xm.c1779
-rw-r--r--lwlib/lwlib-Xm.h40
-rw-r--r--lwlib/lwlib-Xol.c317
-rw-r--r--lwlib/lwlib-Xol.h29
-rw-r--r--lwlib/lwlib-Xolmb.c371
-rw-r--r--lwlib/lwlib-Xolmb.h26
-rw-r--r--lwlib/lwlib-XolmbP.h50
-rw-r--r--lwlib/lwlib-int.h55
-rw-r--r--lwlib/lwlib-utils.c180
-rw-r--r--lwlib/lwlib-utils.h20
-rw-r--r--lwlib/lwlib.c1386
-rw-r--r--lwlib/lwlib.h122
-rw-r--r--lwlib/xlwmenu.c1584
-rw-r--r--lwlib/xlwmenu.h56
-rw-r--r--lwlib/xlwmenuP.h91
-rwxr-xr-xmake-dist495
-rw-r--r--man/Makefile.in166
-rw-r--r--msdos/mainmake76
-rw-r--r--msdos/mainmake.v298
-rw-r--r--msdos/sed1.inp38
-rw-r--r--msdos/sed1v2.inp25
-rw-r--r--msdos/sed1x.inp8
-rw-r--r--msdos/sed2.inp49
-rw-r--r--msdos/sed2x.inp9
-rw-r--r--msdos/sed3.inp29
-rw-r--r--msdos/sed3v2.inp25
-rw-r--r--msdos/sed4.inp7
-rw-r--r--msdos/sed5x.inp11
-rw-r--r--nt/_emacs3
-rw-r--r--nt/addpm.c144
-rw-r--r--nt/config.nt349
-rw-r--r--nt/config.w95349
-rwxr-xr-xnt/ebuild.bat1
-rwxr-xr-xnt/emacs.bat44
-rw-r--r--nt/emacs.bat.in38
-rw-r--r--nt/emacs.rc1
-rwxr-xr-xnt/fast-install.bat1
-rw-r--r--nt/inc/arpa/inet.h1
-rw-r--r--nt/inc/netdb.h1
-rw-r--r--nt/inc/netinet/in.h1
-rw-r--r--nt/inc/pwd.h18
-rw-r--r--nt/inc/sys/dir.h5
-rw-r--r--nt/inc/sys/file.h8
-rw-r--r--nt/inc/sys/ioctl.h5
-rw-r--r--nt/inc/sys/param.h10
-rw-r--r--nt/inc/sys/socket.h119
-rw-r--r--nt/inc/sys/time.h18
-rw-r--r--nt/inc/unistd.h1
-rw-r--r--nt/install88
-rwxr-xr-xnt/install.bat7
-rw-r--r--nt/makefile.def200
-rw-r--r--nt/makefile.nt156
-rw-r--r--nt/paths.h46
-rw-r--r--nt/runemacs.c130
-rw-r--r--src/.gdbinit272
-rw-r--r--src/=Makefile.in100
-rw-r--r--src/=XTests.c179
-rw-r--r--src/=XTests.h7
-rw-r--r--src/=convexos.h10
-rw-r--r--src/=environ.c316
-rw-r--r--src/=mach2.h48
-rw-r--r--src/=old-ralloc.c1069
-rw-r--r--src/=sol2-2.h18
-rw-r--r--src/=unexelf1.c952
-rw-r--r--src/=unexsgi.c888
-rw-r--r--src/=x11term.h24
-rw-r--r--src/=xscrollbar.h123
-rw-r--r--src/=xselect.c.old950
-rw-r--r--src/Makefile.in1067
-rw-r--r--src/abbrev.c579
-rw-r--r--src/acldef.h40
-rw-r--r--src/alloc.c2688
-rw-r--r--src/alloca.c504
-rw-r--r--src/alloca.s350
-rw-r--r--src/blockinput.h78
-rw-r--r--src/buffer.c4109
-rw-r--r--src/buffer.h532
-rw-r--r--src/bytecode.c1198
-rw-r--r--src/callint.c824
-rw-r--r--src/callproc.c1182
-rw-r--r--src/casefiddle.c313
-rw-r--r--src/casetab.c252
-rw-r--r--src/chpdef.h38
-rw-r--r--src/cm.c445
-rw-r--r--src/cm.h177
-rw-r--r--src/cmds.c446
-rw-r--r--src/commands.h92
-rw-r--r--src/config.in375
-rw-r--r--src/data.c2723
-rw-r--r--src/dired.c730
-rw-r--r--src/dispextern.h181
-rw-r--r--src/dispnew.c2619
-rw-r--r--src/disptab.h99
-rw-r--r--src/doc.c702
-rw-r--r--src/doprnt.c270
-rw-r--r--src/dosfns.c407
-rw-r--r--src/dosfns.h39
-rw-r--r--src/editfns.c2653
-rw-r--r--src/emacs.c1600
-rw-r--r--src/epaths.in42
-rw-r--r--src/eval.c3008
-rw-r--r--src/fileio.c4774
-rw-r--r--src/filelock.c488
-rw-r--r--src/floatfns.c1032
-rw-r--r--src/fns.c1923
-rw-r--r--src/frame.c2153
-rw-r--r--src/frame.h485
-rw-r--r--src/getloadavg.c1022
-rw-r--r--src/getpagesize.h41
-rw-r--r--src/gnu.h33
-rw-r--r--src/hftctl.c341
-rw-r--r--src/indent.c1431
-rw-r--r--src/indent.h50
-rw-r--r--src/insdel.c1044
-rw-r--r--src/intervals.c1961
-rw-r--r--src/intervals.h255
-rw-r--r--src/ioctl.h1
-rw-r--r--src/keyboard.c8294
-rw-r--r--src/keyboard.h259
-rw-r--r--src/keymap.c2838
-rw-r--r--src/lastfile.c40
-rw-r--r--src/line.h7
-rw-r--r--src/lisp.h1857
-rw-r--r--src/lread.c2604
-rw-r--r--src/m/7300.h100
-rw-r--r--src/m/=dos386.h115
-rw-r--r--src/m/acorn.h198
-rw-r--r--src/m/alliant-2800.h136
-rw-r--r--src/m/alliant.h134
-rw-r--r--src/m/alliant1.h9
-rw-r--r--src/m/alliant4.h24
-rw-r--r--src/m/alpha.h309
-rw-r--r--src/m/altos.h64
-rw-r--r--src/m/amdahl.h156
-rw-r--r--src/m/apollo.h96
-rw-r--r--src/m/att3b.h157
-rw-r--r--src/m/aviion.h132
-rw-r--r--src/m/celerity.h60
-rw-r--r--src/m/clipper.h103
-rw-r--r--src/m/cnvrgnt.h111
-rw-r--r--src/m/convex.h191
-rw-r--r--src/m/cydra5.h126
-rw-r--r--src/m/delta.h206
-rw-r--r--src/m/delta88k.h178
-rw-r--r--src/m/dpx2.h240
-rw-r--r--src/m/dual.h69
-rw-r--r--src/m/elxsi.h139
-rw-r--r--src/m/gec63.h70
-rw-r--r--src/m/gould-np1.h87
-rw-r--r--src/m/gould.h195
-rw-r--r--src/m/hp800.h183
-rw-r--r--src/m/hp9000s300.h230
-rw-r--r--src/m/i860.h107
-rw-r--r--src/m/ibm370aix.h38
-rw-r--r--src/m/ibmps2-aix.h244
-rw-r--r--src/m/ibmrs6000.h186
-rw-r--r--src/m/ibmrt-aix.h173
-rw-r--r--src/m/ibmrt.h128
-rw-r--r--src/m/intel386.h235
-rw-r--r--src/m/iris4d.h194
-rw-r--r--src/m/iris5d.h190
-rw-r--r--src/m/irist.h142
-rw-r--r--src/m/is386.h27
-rw-r--r--src/m/isi-ov.h93
-rw-r--r--src/m/m68k.h89
-rw-r--r--src/m/masscomp.h137
-rw-r--r--src/m/mega68.h49
-rw-r--r--src/m/mg1.h113
-rw-r--r--src/m/mips-siemens.h187
-rw-r--r--src/m/mips.h225
-rw-r--r--src/m/mips4.h59
-rw-r--r--src/m/ncr386.h15
-rw-r--r--src/m/news-risc.h51
-rw-r--r--src/m/news.h66
-rw-r--r--src/m/next.h125
-rw-r--r--src/m/nh3000.h115
-rw-r--r--src/m/nh4000.h114
-rw-r--r--src/m/ns16000.h100
-rw-r--r--src/m/ns32000.h112
-rw-r--r--src/m/nu.h71
-rw-r--r--src/m/orion.h71
-rw-r--r--src/m/orion105.h70
-rw-r--r--src/m/paragon.h10
-rw-r--r--src/m/pfa50.h94
-rw-r--r--src/m/plexus.h115
-rw-r--r--src/m/pmax.h108
-rw-r--r--src/m/pyramid.h63
-rw-r--r--src/m/sequent-ptx.h141
-rw-r--r--src/m/sequent.h175
-rw-r--r--src/m/sgi3000.h1
-rw-r--r--src/m/sparc.h121
-rw-r--r--src/m/sps7.h118
-rw-r--r--src/m/sr2k.h185
-rw-r--r--src/m/stride.h122
-rw-r--r--src/m/sun1.h76
-rw-r--r--src/m/sun2.h97
-rw-r--r--src/m/sun3-68881.h28
-rw-r--r--src/m/sun3-fpa.h28
-rw-r--r--src/m/sun3-soft.h29
-rw-r--r--src/m/sun3.h50
-rw-r--r--src/m/sun386.h82
-rw-r--r--src/m/symmetry.h101
-rw-r--r--src/m/tad68k.h119
-rw-r--r--src/m/tahoe.h72
-rw-r--r--src/m/tandem-s2.h21
-rw-r--r--src/m/targon31.h104
-rw-r--r--src/m/tek4300.h106
-rw-r--r--src/m/tekxd88.h127
-rw-r--r--src/m/template.h121
-rw-r--r--src/m/tower32.h121
-rw-r--r--src/m/tower32v3.h121
-rw-r--r--src/m/ustation.h143
-rw-r--r--src/m/vax.h124
-rw-r--r--src/m/wicat.h155
-rw-r--r--src/m/windowsnt.h129
-rw-r--r--src/m/xps100.h105
-rw-r--r--src/macros.c327
-rw-r--r--src/macros.h41
-rw-r--r--src/makefile.nt1127
-rw-r--r--src/marker.c352
-rw-r--r--src/mem-limits.h185
-rw-r--r--src/minibuf.c2002
-rw-r--r--src/mocklisp.c244
-rw-r--r--src/mocklisp.h32
-rw-r--r--src/msdos.c3334
-rw-r--r--src/msdos.h130
-rw-r--r--src/ndir.h55
-rw-r--r--src/param.h2
-rw-r--r--src/point.h5
-rw-r--r--src/pre-crt0.c9
-rw-r--r--src/print.c1491
-rw-r--r--src/process.c4141
-rw-r--r--src/process.h112
-rw-r--r--src/puresize.h97
-rw-r--r--src/ralloc.c1234
-rw-r--r--src/regex.c5512
-rw-r--r--src/regex.h496
-rw-r--r--src/region-cache.c834
-rw-r--r--src/region-cache.h112
-rw-r--r--src/s/3700.h0
-rw-r--r--src/s/386-ix.h15
-rw-r--r--src/s/386bsd.h24
-rw-r--r--src/s/aix3-1.h229
-rw-r--r--src/s/aix3-2-5.h29
-rw-r--r--src/s/aix3-2.h49
-rw-r--r--src/s/aix4-1.h31
-rw-r--r--src/s/aix4.h6
-rw-r--r--src/s/alliant-2800.h0
-rw-r--r--src/s/alliant.h0
-rw-r--r--src/s/altos.h0
-rw-r--r--src/s/amdahl.h0
-rw-r--r--src/s/bsd386.h51
-rw-r--r--src/s/bsd4-1.h137
-rw-r--r--src/s/bsd4-2.h128
-rw-r--r--src/s/bsd4-3.h127
-rw-r--r--src/s/bsdos2-1.h6
-rw-r--r--src/s/bsdos2.h8
-rw-r--r--src/s/cxux.h238
-rw-r--r--src/s/cxux7.h7
-rw-r--r--src/s/dgux.h370
-rw-r--r--src/s/dgux5-4-3.h60
-rw-r--r--src/s/dgux5-4R2.h46
-rw-r--r--src/s/dgux5-4R3.h59
-rw-r--r--src/s/dgux5-4r2.h47
-rw-r--r--src/s/esix.h24
-rw-r--r--src/s/esix5r4.h24
-rw-r--r--src/s/freebsd.h99
-rw-r--r--src/s/gnu-linux.h295
-rw-r--r--src/s/gnu.h73
-rw-r--r--src/s/hiuxmpp.h53
-rw-r--r--src/s/hpux.h240
-rw-r--r--src/s/hpux10.h38
-rw-r--r--src/s/hpux8.h67
-rw-r--r--src/s/hpux9-x11r4.h10
-rw-r--r--src/s/hpux9.h58
-rw-r--r--src/s/hpux9shr.h13
-rw-r--r--src/s/iris3-5.h180
-rw-r--r--src/s/iris3-6.h180
-rw-r--r--src/s/irix3-3.h174
-rw-r--r--src/s/irix4-0.h57
-rw-r--r--src/s/irix5-0.h129
-rw-r--r--src/s/irix5-2.h13
-rw-r--r--src/s/irix6-0.h28
-rw-r--r--src/s/isc2-2.h77
-rw-r--r--src/s/isc3-0.h45
-rw-r--r--src/s/isc4-0.h25
-rw-r--r--src/s/isc4-1.h29
-rw-r--r--src/s/mach-bsd4-3.h5
-rw-r--r--src/s/ms-w32.h374
-rw-r--r--src/s/msdos.h269
-rw-r--r--src/s/netbsd.h63
-rw-r--r--src/s/newsos5.h49
-rw-r--r--src/s/nextstep.h111
-rw-r--r--src/s/osf1.h34
-rw-r--r--src/s/ptx.h171
-rw-r--r--src/s/ptx4.h15
-rw-r--r--src/s/riscix1-1.h25
-rw-r--r--src/s/riscix12.h25
-rw-r--r--src/s/riscos5.h11
-rw-r--r--src/s/rtu.h168
-rw-r--r--src/s/sco4.h145
-rw-r--r--src/s/sco5.h166
-rw-r--r--src/s/sol2-3.h50
-rw-r--r--src/s/sol2-4.h28
-rw-r--r--src/s/sol2-5.h25
-rw-r--r--src/s/sol2.h28
-rw-r--r--src/s/sunos4-0.h28
-rw-r--r--src/s/sunos4-1.h44
-rw-r--r--src/s/sunos413.h11
-rw-r--r--src/s/sunos4shr.h58
-rw-r--r--src/s/template.h175
-rw-r--r--src/s/ultrix4-3.h8
-rw-r--r--src/s/umax.h174
-rw-r--r--src/s/umips.h77
-rw-r--r--src/s/unipl5-0.h180
-rw-r--r--src/s/unipl5-2.h174
-rw-r--r--src/s/usg5-0.h171
-rw-r--r--src/s/usg5-2-2.h174
-rw-r--r--src/s/usg5-2.h174
-rw-r--r--src/s/usg5-3.h223
-rw-r--r--src/s/usg5-4-2.h59
-rw-r--r--src/s/usg5-4-3.h8
-rw-r--r--src/s/usg5-4.h203
-rw-r--r--src/s/vms.h248
-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/windows95.h5
-rw-r--r--src/s/xenix.h226
-rw-r--r--src/scroll.c1058
-rw-r--r--src/search.c2125
-rw-r--r--src/sink.h91
-rw-r--r--src/sink11.h51
-rw-r--r--src/sink11mask.h51
-rw-r--r--src/sinkmask.h27
-rw-r--r--src/sunfns.c512
-rw-r--r--src/syntax.c1823
-rw-r--r--src/syntax.h182
-rw-r--r--src/sysdep.c5143
-rw-r--r--src/sysselect.h45
-rw-r--r--src/syssignal.h148
-rw-r--r--src/systime.h149
-rw-r--r--src/systty.h419
-rw-r--r--src/syswait.h106
-rw-r--r--src/term.c1817
-rw-r--r--src/termcap.c784
-rw-r--r--src/termchar.h46
-rw-r--r--src/termhooks.h361
-rw-r--r--src/terminfo.c59
-rw-r--r--src/termopts.h41
-rw-r--r--src/textprop.c1790
-rw-r--r--src/tparam.c324
-rw-r--r--src/uaf.h296
-rw-r--r--src/undo.c519
-rw-r--r--src/unexaix.c883
-rw-r--r--src/unexalpha.c495
-rw-r--r--src/unexconvex.c602
-rw-r--r--src/unexec.c1238
-rw-r--r--src/unexelf.c952
-rw-r--r--src/unexencap.c116
-rw-r--r--src/unexenix.c260
-rw-r--r--src/unexfx2800.c16
-rw-r--r--src/unexhp9k800.c319
-rw-r--r--src/unexmips.c361
-rw-r--r--src/unexnext.c431
-rw-r--r--src/unexsni.c836
-rw-r--r--src/unexsunos4.c378
-rw-r--r--src/unexw32.c584
-rw-r--r--src/vlimit.h2
-rw-r--r--src/vm-limit.c133
-rw-r--r--src/vms-pp.c243
-rw-r--r--src/vms-pwd.h35
-rw-r--r--src/vmsdir.h98
-rw-r--r--src/vmsfns.c962
-rw-r--r--src/vmsgmalloc.c2012
-rw-r--r--src/vmsmap.c225
-rw-r--r--src/vmspaths.h32
-rw-r--r--src/vmsproc.c795
-rw-r--r--src/vmsproc.h21
-rw-r--r--src/vmstime.c377
-rw-r--r--src/vmstime.h35
-rw-r--r--src/w32.c2259
-rw-r--r--src/w32.h127
-rw-r--r--src/w32console.c635
-rw-r--r--src/w32faces.c1047
-rw-r--r--src/w32fns.c5165
-rw-r--r--src/w32gui.h84
-rw-r--r--src/w32heap.c284
-rw-r--r--src/w32heap.h73
-rw-r--r--src/w32inevt.c580
-rw-r--r--src/w32inevt.h33
-rw-r--r--src/w32menu.c1967
-rw-r--r--src/w32proc.c1326
-rw-r--r--src/w32reg.c97
-rw-r--r--src/w32select.c299
-rw-r--r--src/w32term.c3891
-rw-r--r--src/w32term.h658
-rw-r--r--src/w32xfns.c366
-rw-r--r--src/widget.c978
-rw-r--r--src/widget.h100
-rw-r--r--src/widgetprv.h79
-rw-r--r--src/window.c3720
-rw-r--r--src/window.h343
-rw-r--r--src/xdisp.c4616
-rw-r--r--src/xfaces.c1277
-rw-r--r--src/xfns.c5249
-rw-r--r--src/xmenu.c2740
-rw-r--r--src/xrdb.c734
-rw-r--r--src/xselect.c2209
-rw-r--r--src/xterm.c6354
-rw-r--r--src/xterm.h769
-rw-r--r--tparam.c324
-rw-r--r--vpath.sed7
1001 files changed, 25 insertions, 641116 deletions
diff --git a/=PROBLEMS b/=PROBLEMS
deleted file mode 100644
index 7172c0b99dc..00000000000
--- a/=PROBLEMS
+++ /dev/null
@@ -1,744 +0,0 @@
-This file describes various problems that have been encountered
-in compiling, installing and running GNU Emacs.
-
-* `Pid xxx killed due to text modification or page I/O error'
-
-On HP/UX, you can get that error when the Emacs executable is on an NFS
-file system. HP/UX responds this way if it tries to swap in a page and
-does not get a response from the server within a timeout whose default
-value is just ten seconds.
-
-If this happens to you, extend the timeout period.
-
-* `expand-file-name' fails to work on any but the machine you dumped Emacs on.
-
-On Ultrix, if you use any of the functions which look up information
-in the passwd database before dumping Emacs (say, by using
-expand-file-name in site-init.el), then those functions will not work
-in the dumped Emacs on any host but the one Emacs was dumped on.
-
-The solution? Don't use expand-file-name in site-init.el, or in
-anything it loads. Yuck - some solution.
-
-I'm not sure why this happens; if you can find out exactly what is
-going on, and perhaps find a fix or a workaround, please let us know.
-Perhaps the YP functions cache some information, the cache is included
-in the dumped Emacs, and is then inaccurate on any other host.
-
-* 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.
-
-* 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
-similar 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.
-
-* Trouble using ptys on AIX.
-
-People often install 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 starts in a directory other than the one that is current in the shell.
-
-If the PWD environment variable exists, Emacs uses this variable as
-the initial working directory.
-
-Some shells automatically update this variable, while other shells fail
-to do so. If you use two such shells in combination, the variable can
-end up wrong. This confuses Emacs.
-
-The solution is to put something in the start-up file for the shell
-that does not update PWD, to get rid of that environment variable.
-For example, in csh, use `unsetenv PWD'.
-
-* 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: -fsoft.
-
-* 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.
-
-* 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.
-
-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 puresize.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.
-
-Emacs should print a warning when loading a .elc file which is older
-than the corresponding .el file.
-
-* 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. To make
-such an adjustment, you need only invoke the function
-enable-flow-control-on with a list of terminal types in your own
-.emacs file. As arguments, give it the names of one or more terminal
-types you use which require flow control adjustments.
-Here's an example:
-
-(enable-flow-control-on "vt200" "vt300" "vt101" "vt131")
-
-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 redesigning 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
- {
-
-* 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
-defined as a union on some rare architectures.
-
-This problem will not happen if the m-...h file for your type
-of machine defines NO_UNION_TYPE.
-
diff --git a/GETTING.GNU.SOFTWARE b/GETTING.GNU.SOFTWARE
deleted file mode 100644
index 3652f504dcb..00000000000
--- a/GETTING.GNU.SOFTWARE
+++ /dev/null
@@ -1,112 +0,0 @@
--*- text -*-
- Getting GNU Software, 21 Mar 93
-Copyright (C) 1986, 1987, 1988, 1989, 1990, 1992, 1993 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/GNUinfo/GNU' (all files referred to are on the Internet host
-prep.ai.mit.edu).
-
-Information on GNU Internet mailing lists and gnUSENET newsgroups can
-be found in `/pub/gnu/GNUinfo/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 `/pub/gnu/GNUinfo/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 `/pub/gnu/GNUinfo/DISTRIB' and
-`/pub/gnu/GNUinfo/ORDERS'.
-
-* What format are the *.gz files in?
-
-Because the unix `compress' utility is patented (by two separate
-patents, in fact), we cannot use it; it's not free software.
-
-Therefore, the GNU Project has chosen a new compression utility,
-`gzip', which is free of any known software patents and which tends to
-compress better anyway. As of March 1993, all compressed files in the
-GNU anonymous FTP area, `prep.ai.mit.edu:/pub/gnu', have been
-converted to the new format. Files compressed with this new
-compression program end in `.gz' (as opposed to `compress'-compressed
-files, which end in `.Z').
-
-Gzip can uncompress `compress'-compressed files and `pack' files
-(which end in `.z'). This is possible because the various
-decompression algorithms are not patented---only compression is.
-
-The gzip program is available from any GNU mirror site in shar, tar,
-or gzipped tar format (for those who already have a prior version of
-gzip and want faster data transmission). It works on virtually every
-unix system, MSDOS, OS/2, and VMS.
-
-* Available Software
-
-** GNU Emacs
-
-The GNU Emacs distribution includes:
- - manual source in TeX format.
- - an enhanced regex (regular expression) library.
-
-See `/pub/gnu/GNUinfo/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 its ftp distribution
-should be referred to: <bug-cscheme@martigny.ai.mit.edu>. There are
-two general mailing lists: <info-cscheme@martigny.ai.mit.edu>and
-<scheme@mc.lcs.mit.edu>. Send requests to join either list to:
-<info-cscheme-request@martigny.ai.mit.edu> or
-<scheme-request@mc.lcs.mit.edu>.
-
-** Other GNU Software
-
-A full list of available software are in `/pub/gnu/GNUinfo/ORDERS' and
-`/pub/gnu/GNUinfo/DESCRIPTIONS'.
-
-* 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. Please note that donations and funds raise by selling
-tapes, cd-roms, and floppy diskettes are the major source of funding
-for our work.
-
-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/GNUinfo/DISTRIB'.
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index 7b243f9561a..00000000000
--- a/INSTALL
+++ /dev/null
@@ -1,615 +0,0 @@
-GNU Emacs Installation Guide
-Copyright (c) 1992, 1994, 1996 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.
-
-
-BUILDING AND INSTALLATION:
-
-(This is for a Unix or Unix-like system. For MSDOS, see below; search
-for MSDOG. For Windows NT or Windows 95, see the file nt/INSTALL.)
-
-1) Make sure your system has enough swapping space allocated to handle
-a program whose pure code is 900k bytes and whose data area is at
-least 400k and can reach 8Mb or more. If the swapping space is
-insufficient, you will get an error in the command `temacs -batch -l
-loadup dump', found in `./src/Makefile.in', or possibly when
-running the final dumped Emacs.
-
-Building Emacs requires about 70 Mb of disk space (including the Emacs
-sources). Once installed, Emacs occupies about 35 Mb in the file
-system where it is installed; this includes the executable files, Lisp
-libraries, miscellaneous data files, and on-line documentation. If
-the building and installation take place in different directories,
-then the installation procedure momentarily requires 70+35 Mb.
-
-2) Consult `./etc/MACHINES' to see what configuration name you should
-give to the `configure' program. That file offers hints for
-getting around some possible installation problems.
-
-3) You can build Emacs in the top-level Emacs source directory
-or in a separate directory.
-
-3a) To build in the top-level Emacs source directory, go to that
-directory and run the program `configure' as follows:
-
- ./configure CONFIGURATION-NAME [--OPTION[=VALUE]] ...
-
-The CONFIGURATION-NAME argument should be a configuration name given
-in `./etc/MACHINES'. If omitted, `configure' will try to guess your
-system type; if it cannot, you must find the appropriate configuration
-name in `./etc/MACHINES' and specify it explicitly.
-
-If you don't want X support, specify `--with-x=no'. If you omit this
-option, `configure' will try to figure out for itself whether your
-system has X, and arrange to use it if present.
-
-The `--x-includes=DIR' and `--x-libraries=DIR' options tell the build
-process where the compiler should look for the include files and
-object libraries used with the X Window System. Normally, `configure'
-is able to find them; these options are necessary if you have your X
-Window System files installed in unusual places. These options also
-accept a list of directories, separated with colons.
-
-To get more attractive menus, you can specify an X toolkit when you
-configure Emacs; use the option `--with-x-toolkit=TOOLKIT', where
-TOOLKIT is `athena' or `motif' (`yes' and `lucid' are synonyms for
-`athena'). On some systems, it does not work to use a toolkit with
-shared libraries.
-
-The `--with-gcc' option specifies that the build process should
-compile Emacs using GCC. If you don't want to use GCC, specify
-`--with-gcc=no'. If you omit this option, `configure' will search
-for GCC in your path, and use it if present.
-
-If you want the Emacs mail reader RMAIL to read mail from a POP
-server, you must specify `--with-pop'. This provides support for the
-POP3 protocol; older versions are not supported. For
-Kerberos-authenticated POP add `--with-kerberos', for Hesiod support
-add `--with-hesiod'. These options enable Emacs to use POP; whether
-Emacs uses POP is controlled by individual users--see the Rmail
-chapter of the Emacs manual.
-
-The `--prefix=PREFIXDIR' option specifies where the installation process
-should put emacs and its data files. This defaults to `/usr/local'.
-- Emacs (and the other utilities users run) go in PREFIXDIR/bin
- (unless the `--exec-prefix' option says otherwise).
-- The architecture-independent files go in PREFIXDIR/share/emacs/VERSION
- (where VERSION is the version number of Emacs, like `19.27').
-- The architecture-dependent files go in
- PREFIXDIR/libexec/emacs/VERSION/CONFIGURATION
- (where CONFIGURATION is the configuration name, like mips-dec-ultrix4.2),
- unless the `--exec-prefix' option says otherwise.
-
-The `--exec-prefix=EXECDIR' option allows you to specify a separate
-portion of the directory tree for installing architecture-specific
-files, like executables and utility programs. If specified,
-- Emacs (and the other utilities users run) go in EXECDIR/bin, and
-- The architecture-dependent files go in
- EXECDIR/libexec/emacs/VERSION/CONFIGURATION.
-EXECDIR/bin should be a directory that is normally in users' PATHs.
-
-For example, the command
-
- ./configure mips-dec-ultrix --with-x11
-
-configures Emacs to build for a DECstation running Ultrix, with
-support for the X11 window system.
-
-`configure' doesn't do any compilation or installation
-itself. It just creates the files that influence those things:
-`./Makefile', `lib-src/Makefile', `oldXMenu/Makefile',
-`lwlib/Makefile', `src/Makefile', and `./src/config.h'. For details
-on exactly what it does, see the section called `CONFIGURATION BY
-HAND', below.
-
-When it is done, `configure' prints a description of what it did and
-creates a shell script `config.status' which, when run, recreates the
-same configuration. If `configure' exits with an error after
-disturbing the status quo, it removes `config.status'. `configure'
-also creates a file `config.cache' that saves the results of its tests
-to make reconfiguring faster, and a file `config.log' containing compiler
-output (useful mainly for debugging `configure'). You can give
-`configure' the option `--cache-file=FILE' to use the results of the
-tests in FILE instead of `config.cache'. Set FILE to `/dev/null' to
-disable caching, for debugging `configure'.
-
-The work of `configure' can be done by editing various files in the
-distribution, but using `configure' is easier. See the section called
-"CONFIGURATION BY HAND" below if you want to do the configuration
-yourself.
-
-3b) To build in a separate directory, go to that directory
-and run the program `configure' as follows:
-
- SOURCE-DIR/configure CONFIGURATION-NAME [--OPTION[=VALUE]] ...
-
-SOURCE-DIR refers to the top-level Emacs source directory which is
-where Emacs's configure script is located. `configure' looks for the
-Emacs source code in the directory that `configure' is in.
-
-To build in a separate directory, you must use a version of `make'
-that supports the `VPATH' variable, such as GNU `make'.
-
-4) Look at `./lisp/paths.el'; if some of those values are not right
-for your system, set up the file `./lisp/site-init.el' with Emacs
-Lisp code to override them; it is not a good idea to edit paths.el
-itself. YOU MUST USE THE LISP FUNCTION `setq' TO ASSIGN VALUES,
-rather than `defvar', as used by `./lisp/paths.el'. 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").
-
-Before you override a variable this way, *look at the value* that the
-variable gets by default! Make sure you know what kind of value the
-variable should have. If you don't pay attention to what you are
-doing, you'll make a mistake.
-
-5) Put into `./lisp/site-init.el' or `./lisp/site-load.el' any Emacs
-Lisp code you want Emacs to load before it is dumped out. Use
-site-load.el for additional libraries if you arrange for their
-documentation strings to be in the etc/DOC file (see
-src/Makefile.in if you wish to figure out how to do that). For all
-else, use site-init.el.
-
-If you set load-path to a different value in site-init.el or
-site-load.el, Emacs will use *precisely* that value when it starts up
-again. If you do this, you are on your own!
-
-Note that, on some systems, the code you place in site-init.el must
-not use expand-file-name or any other function which may look
-something up in the system's password and user information database.
-See `./PROBLEMS' for more details on which systems this affects.
-
-The `site-*.el' files are nonexistent in the distribution. You do not
-need to create them if you have nothing to put in them.
-
-6) Refer to the file `./etc/TERMS' for information on fields you may
-wish to add to various termcap entries. The files `./etc/termcap.ucb'
-and `./etc/termcap.dat' may already contain appropriately-modified
-entries.
-
-7) Run `make' in the top directory of the Emacs distribution to finish
-building Emacs in the standard way. The final executable file is
-named `src/emacs'. You can execute this file "in place" without
-copying it, if you wish; then it automatically uses the sibling
-directories ../lisp, ../lib-src, ../info.
-
-Or you can "install" the executable and the other Emacs into their
-installed locations, with `make install'. By default, Emacs's files
-are installed in the following directories:
-
-`/usr/local/bin' holds the executable programs users normally run -
- `emacs', `etags', `ctags', `b2m', `emacsclient',
- and `rcs-checkin'.
-
-`/usr/local/share/emacs/VERSION/lisp' holds the Emacs Lisp library;
- `VERSION' stands for the number of the Emacs version
- you are installing, like `18.59' or `19.27'. Since the
- Lisp library changes from one version of Emacs to
- another, including the version number in the path
- allows you to have several versions of Emacs installed
- at the same time; in particular, you don't have to
- make Emacs unavailable while installing a new version.
-
-`/usr/local/share/emacs/VERSION/site-lisp' holds the local Emacs Lisp
- files installed for Emacs version VERSION only.
-
-`/usr/local/share/emacs/site-lisp' holds the local Emacs Lisp
- files installed for all Emacs versions.
-
- When Emacs is installed, it searches for its Lisp files
- in `/usr/local/share/emacs/VERSION/site-lisp', then in
- `/usr/local/share/emacs/site-lisp', and finally in
- `/usr/local/share/emacs/VERSION/lisp'.
-
-`/usr/local/share/emacs/VERSION/etc' holds the Emacs tutorial, the DOC
- file, the `yow' database, and other
- architecture-independent files Emacs might need while
- running. VERSION is as specified for `.../lisp'.
-
-`/usr/local/com/emacs/lock' contains files indicating who is editing
- what, so Emacs can detect editing clashes between
- users.
-
-`/usr/local/libexec/emacs/VERSION/CONFIGURATION-NAME' contains executable
- programs used by Emacs that users are not expected to
- run themselves.
- `VERSION' is the number of the Emacs version you are
- installing, and `CONFIGURATION-NAME' is the argument
- you gave to the `configure' program to identify the
- architecture and operating system of your machine,
- like `mips-dec-ultrix' or `sparc-sun-sunos'. Since
- these files are specific to the version of Emacs,
- operating system, and architecture in use, including
- the configuration name in the path allows you to have
- several versions of Emacs for any mix of machines and
- operating systems installed at the same time; this is
- useful for sites at which different kinds of machines
- share the file system Emacs is installed on.
-
-`/usr/local/info' holds the on-line documentation for Emacs, known as
- "info files". Many other GNU programs are documented
- using info files as well, so this directory stands
- apart from the other, Emacs-specific directories.
-
-`/usr/local/man/man1' holds the man pages for the programs installed
- in `/usr/local/bin'.
-
-If these directories are not what you want, you can specify where to
-install Emacs's libraries and data files or where Emacs should search
-for its Lisp files by giving values for `make' variables as part of
-the command. See the section below called `MAKE VARIABLES' for more
-information on this.
-
-8) Check the file `dir' in your site's info directory (usually
-/usr/local/info) to make sure that it has a menu entry for the Emacs
-info files.
-
-9) If your system uses lock files to interlock access to mailer inbox files,
-then you might need to make the movemail program setuid or setgid
-to enable it to write the lock files. We believe this is safe.
-
-10) You are done! You can remove executables and object files from
-the build directory by typing `make clean'. To also remove the files
-that `configure' created (so you can compile Emacs for a different
-configuration), type `make distclean'.
-
-
-
-MAKE VARIABLES
-
-You can change where the build process installs Emacs and its data
-files by specifying values for `make' variables as part of the `make'
-command line. For example, if you type
-
- make install bindir=/usr/local/gnubin
-
-the `bindir=/usr/local/gnubin' argument indicates that the Emacs
-executable files should go in `/usr/local/gnubin', not
-`/usr/local/bin'.
-
-Here is a complete list of the variables you may want to set.
-
-`bindir' indicates where to put executable programs that users can
- run. This defaults to /usr/local/bin.
-
-`datadir' indicates where to put the architecture-independent
- read-only data files that Emacs refers to while it runs; it
- defaults to /usr/local/share. We create the following
- subdirectories under `datadir':
- - `emacs/VERSION/lisp', containing the Emacs Lisp library, and
- - `emacs/VERSION/etc', containing the Emacs tutorial, the DOC
- file, and the `yow' database.
- `VERSION' is the number of the Emacs version you are installing,
- like `18.59' or `19.0'. Since these files vary from one version
- of Emacs to another, including the version number in the path
- allows you to have several versions of Emacs installed at the
- same time; this means that you don't have to make Emacs
- unavailable while installing a new version.
-
-`sharedstatedir' indicates where to put architecture-independent data files
- that Emacs modifies while it runs; it defaults to
- /usr/local/com. We create the following
- subdirectories under `sharedstatedir':
- - `emacs/lock', containing files indicating who is editing
- what, so Emacs can detect editing clashes between
- users.
-
-`libexecdir' indicates where to put architecture-specific data files that
- Emacs refers to as it runs; it defaults to `/usr/local/libexec'.
- We create the following subdirectories under `libexecdir':
- - `emacs/VERSION/CONFIGURATION-NAME', containing executable
- programs used by Emacs that users are not expected to run
- themselves.
- `VERSION' is the number of the Emacs version you are installing,
- and `CONFIGURATION-NAME' is the argument you gave to the
- `configure' program to identify the architecture and operating
- system of your machine, like `mips-dec-ultrix' or
- `sparc-sun-sunos'. Since these files are specific to the version
- of Emacs, operating system, and architecture in use, including
- the configuration name in the path allows you to have several
- versions of Emacs for any mix of machines and operating systems
- installed at the same time; this is useful for sites at which
- different kinds of machines share the file system Emacs is
- installed on.
-
-`infodir' indicates where to put the info files distributed with
- Emacs; it defaults to `/usr/local/info'.
-
-`mandir' indicates where to put the man pages for Emacs and its
- utilities (like `etags'); it defaults to
- `/usr/local/man/man1'.
-
-`manext' gives the extension the man pages should be installed with.
- It should contain a period, followed by the appropriate
- digit. It defaults to `.1'. For example given the default
- values for `mandir' and `manext', the Emacs man page would be
- installed as `/usr/local/man/man1/emacs.1'.
-
-`prefix' doesn't give a path for any specific part of Emacs; instead,
- its value is used to determine the defaults for all the
- architecture-independent path variables - `datadir',
- `sharedstatedir', `infodir', and `mandir'. Its default value is
- `/usr/local'; the other variables add on `lib' or `man' to it
- by default.
-
- For example, suppose your site generally places GNU software
- under `/usr/users/software/gnusoft' instead of `/usr/local'.
- By including
- `prefix=/usr/users/software/gnusoft'
- in the arguments to `make', you can instruct the build process
- to place all of the Emacs data files in the appropriate
- directories under that path.
-
-`exec_prefix' serves the same purpose as `prefix', but instead
- determines the default values for the architecture-dependent
- path variables - `bindir' and `libexecdir'.
-
-The above variables serve analogous purposes in the makefiles for all
-GNU software; here are some variables specific to Emacs.
-
-`lispdir' indicates where Emacs installs and expects its Lisp library.
- Its default value, based on `datadir' (see above), is
- `/usr/local/share/emacs/VERSION/lisp' (where `VERSION' is as
- described above).
-
-`locallisppath' indicates where Emacs should search for Lisp files
- specific to your site. It should be a colon-separated list of
- directories; Emacs checks them in order before checking
- `lispdir'. Its default value, based on `datadir' (see above), is
- `/usr/local/share/emacs/VERSION/site-lisp:/usr/local/share/emacs/site-lisp'.
-
-`lisppath' is the complete list of directories Emacs should search for
- its Lisp files; its default value is the concatenation of
- `locallisppath' and `lispdir'. It should be a colon-separated
- list of directories; Emacs checks them in the order they
- appear.
-
-`etcdir' indicates where Emacs should install and expect the rest of
- its architecture-independent data, like the tutorial, DOC
- file, and yow database. Its default value, based on `datadir'
- (which see), is `/usr/local/share/emacs/VERSION/etc'.
-
-`lockdir' indicates the directory where Emacs keeps track of its
- locking information. Its default value, based on
- `sharedstatedir' (which see), is `/usr/local/com/emacs/lock'.
-
-`archlibdir' indicates where Emacs installs and expects the executable
- files and other architecture-dependent data it uses while
- running. Its default value, based on `libexecdir' (which
- see), is `/usr/local/libexec/emacs/VERSION/CONFIGURATION-NAME'
- (where VERSION and CONFIGURATION-NAME are as described above).
-
-Remember that you must specify any variable values you need each time
-you run `make' in the top directory. If you run `make' once to build
-emacs, test it, and then run `make' again to install the files, you
-must provide the same variable settings each time. To make the
-settings persist, you can edit them into the `Makefile' in the top
-directory, but be aware that running the `configure' program erases
-`Makefile' and rebuilds it from `Makefile.in'.
-
-The top-level Makefile stores the variable settings it used in the
-Makefiles for the subdirectories, so you don't have to specify them
-when running make in the subdirectories.
-
-
-CONFIGURATION BY HAND
-
-Instead of running the `configure' program, you have to perform the
-following steps.
-
-1) Copy `./src/config.in' to `./src/config.h'.
-
-2) Consult `./etc/MACHINES' to see what configuration name you should
-use for your system. Look at the code of the `configure' script to
-see which operating system and architecture description files from
-`src/s' and `src/m' should be used for that configuration name. Edit
-`src/config.h', and change the two `#include' directives to include
-the appropriate system and architecture description files.
-
-2) Edit `./src/config.h' to set the right options for your system. If
-you need to override any of the definitions in the s/*.h and m/*.h
-files for your system and machine, do so by editing config.h, not by
-changing the s/*.h and m/*.h files. Occasionally you may need to
-redefine parameters used in `./lib-src/movemail.c'.
-
-3) Create src/Makefile and lib-src/Makefile from the corresponding
-`Makefile.in' files. First copy `Makefile.in' to `Makefile.c',
-then edit in appropriate substitutions for the @...@ constructs,
-and then copy the shell commands near the end of `configure'
-that run cpp to construct `Makefile'.
-
-4) Create `Makefile' files in various other directories
-from the corresponding `Makefile.in' files. This isn't so hard,
-just a matter of substitution.
-
-The `configure' script is built from `configure.in' by the `autoconf'
-program. You need version 2.0 or newer of `autoconf' to rebuild `configure'.
-
-BUILDING GNU EMACS BY HAND
-
-Once Emacs is configured, running `make' in the top directory performs
-the following steps.
-
-1) Run `make src/paths.h' in the top directory. This produces
-`./src/paths.h' from the template file `./src/paths.in', changing
-the paths to the values specified in `./Makefile'.
-
-2) Go to directory `./lib-src' and run `make'. This creates
-executables named `ctags' and `etags' and `wakeup' and `make-docfile'
-and `digest-doc' and `test-distrib'. And others.
-
-3) Go to directory `./src' and Run `make'. This refers to files in
-the `./lisp' and `./lib-src' subdirectories using names `../lisp' and
-`../lib-src'.
-
-This creates a file `./src/emacs' which is the runnable Emacs,
-which has another name that contains a version number.
-Each time you do this, that version number increments in the last place.
-
-It also creates a file in `./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
-emacs, 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 BY HAND
-
-The steps below are done by running `make install' in the main
-directory of the Emacs distribution.
-
-1) Copy `./lisp' and its subdirectories, `./etc', and the executables
-in `./lib-src' to their final destinations, as selected in `./src/paths.h'.
-
-Strictly speaking, not all of the executables in `./lib-src' need be copied.
-- The programs `cvtmail', `emacsserver', `fakemail', `hexl',
- `movemail', `profile', `rcs2log', `timer', `vcdiff', `wakeup',
- and `yow' are used by Emacs; they do need to be copied.
-- The programs `etags', `ctags', `emacsclient', `b2m', and `rcs-checkin'
- are intended to be run by users; they are handled below.
-- The programs `make-docfile' and `test-distrib' were
- used in building Emacs, and are not needed any more.
-- The programs `digest-doc' and `sorted-doc' convert a `DOC' file into
- a file for users to read. There is no important reason to move them.
-
-2) Copy the files in `./info' to the place specified in
-`./lisp/site-init.el' or `./lisp/paths.el'. Note that if the
-destination directory already contains a file named `dir', you
-probably don't want to replace it with the `dir' file in the Emacs
-distribution. Instead, you should make sure that the existing `dir'
-file contains an appropriate menu entry for the Emacs info.
-
-3) Create a directory for Emacs to use for clash detection, named as
-indicated by the PATH_LOCK macro in `./src/paths.h'.
-
-4) Copy `./src/emacs' to `/usr/local/bin', or to some other directory
-in users' search paths. `./src/emacs' has an alternate name
-`./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 `./src/temacs'.
-
-5) Copy the programs `b2m', `emacsclient', `ctags', `etags', and
-`rcs-checkin' from `./lib-src' to `/usr/local/bin'. These programs are
-intended for users to run.
-
-6) Copy the man pages in `./etc' for emacs, ctags, and etags into the
-appropriate man directories.
-
-7) The files in the `./src' subdirectory, except for `emacs', are not
-used by Emacs once it is built. However, it is very desirable to keep
-the source on line for debugging.
-
-
-PROBLEMS
-
-See the file PROBLEMS in this directory for a list of various
-problems sometimes encountered, and what to do about them.
-
-
-Installation on MSDOG (a.k.a. MSDOS)
-
-To install on MSDOG, you need to have the GNU C compiler for MSDOG
-(also known as djgpp), GNU Make, rm, mv, and sed. See the remarks in
-config.bat for more information about locations and versions. The
-file etc/FAQ includes pointers to Internet sites where you can find
-the necessary utilities; search for "MS-DOS". The configuration step
-(see below) will test for these utilities and will refuse to continue
-if any of them isn't found.
-
-If you are building the MSDOG version of Emacs on an MSDOG-like system
-which supports long file names (e.g. Windows 95), you need to make
-sure that long file names are handled consistently both when you
-unpack the distribution and compile it. If you intend to compile with
-DJGPP v2.0 or later, and long file names support is enabled (LFN=y in
-the environment), you need to unpack Emacs distribution in a way that
-doesn't truncate the original long filenames to the DOS 8.3 namespace;
-the easiest way to do this is to use djtar program which comes with
-DJGPP, since it will note the LFN setting and behave accordingly.
-DJGPP v1 doesn't support long filenames, so you must unpack Emacs with
-a program that truncates the filenames to 8.3 naming as it extracts
-files; again, using djtar after setting LFN=n is the recommended way.
-You can build Emacs with LFN=n even if you use DJGPP v2, if some of
-your tools don't support long file names: just ensure that LFN is set
-to `n' during both unpacking and compiling.
-
-(By the time you read this, you have already unpacked the Emacs
-distribution, but if the explanations above imply that you should have
-done it differently, it's safer to delete the directory tree created
-by the unpacking program and unpack Emacs again, than to risk running
-into problems during the build process.)
-
-It is important to understand that the runtime support of long file
-names by the Emacs binary is NOT affected by the LFN setting during
-compilation; Emacs compiled with DJGPP v2.0 or later will always
-support long file names on Windows 95 no matter what was the setting
-of LFN at compile time. However, if you compiled with LFN disabled
-and want to enable LFN support after Emacs was already built, you need
-to make sure that the support files in the lisp, etc and info
-directories are called by their original long names as found in the
-distribution. You can do this either by renaming the files manually,
-or by extracting them from the original distribution archive with
-djtar after you set LFN=y in the environment.
-
-To unpack Emacs with djtar, type this command:
-
- djtar -x emacs.tgz
-
-(This assumes that the Emacs distribution is called `emacs.tgz' on
-your system.) There are a few files in the archive whose names
-collide with other files under the 8.3 DOS naming. On native MSDOS,
-or if you have set LFN=n on Windows 95, djtar will ask you to supply
-alternate names for these files; you can just press `Enter' when this
-happens (which makes djtar skip these files) because they aren't
-required for MS-DOS.
-
-When unpacking is done, a directory called `emacs-XX.YY' will be
-created, where XX.YY is the Emacs version. To build and install
-Emacs, chdir to that directory and type these commands:
-
- config msdos
- make install
-
-Building Emacs creates executable files in the src and lib-src
-directories. Installing Emacs on MSDOS moves these executables to a
-sibling directory called bin. For example, if you build in directory
-/emacs, installing moves the executables from /emacs/src and
-/emacs/lib-src to the directory /emacs/bin, so you can then delete the
-subdirectories /emacs/src and /emacs/lib-src if you wish. The only
-subdirectories you need to keep are bin, lisp, etc and info. The bin
-subdirectory should be added to your PATH. The msdos subdirectory
-includes a PIF and an icon file for Emacs which you might find useful
-if you run Emacs under MS Windows.
-
-Emacs on MSDOS finds the lisp, etc and info directories by looking in
-../lisp, ../etc and ../info, starting from the directory where the
-Emacs executable was run from. You can override this by setting the
-environment variable HOME; if you do that, the directories lisp, etc
-and info are accessed as subdirectories of the HOME directory.
-
-MSDOG is a not a multitasking operating system, so Emacs features such
-as asynchronous subprocesses that depend on multitasking will not
-work. Synchronous subprocesses do work.
-
-The current version of djgpp 2.0 (as of August 1996) has two bugs that
-affect Emacs. We've included corrected versions of two files from
-djgpp in the msdos subdirectory: is_exec.c and sigaction.c. To work
-around the bugs, compile these files and link them into temacs. The
-next version of djgpp should have these bugs fixed.
diff --git a/Makefile.in b/Makefile.in
deleted file mode 100644
index 0ba54180838..00000000000
--- a/Makefile.in
+++ /dev/null
@@ -1,539 +0,0 @@
-# DIST: This is the distribution Makefile for Emacs. configure can
-# DIST: make most of the changes to this file you might want, so try
-# DIST: that first.
-
-# make all to compile and build Emacs.
-# make install to install it.
-# make TAGS to update tags tables.
-#
-# make clean or make mostlyclean
-# Delete all files from the current directory that are normally
-# created by building the program. Don't delete the files that
-# record the configuration. Also preserve files that could be made
-# by building, but normally aren't because the distribution comes
-# with them.
-#
-# Delete `.dvi' files here if they are not part of the distribution.
-#
-# make distclean
-# Delete all files from the current directory that are created by
-# configuring or building the program. If you have unpacked the
-# source and built the program without creating any other files,
-# `make distclean' should leave only the files that were in the
-# distribution.
-#
-# make maintainer-clean
-# Delete everything from the current directory that can be
-# reconstructed with this Makefile. This typically includes
-# everything deleted by distclean, plus more: C source files
-# produced by Bison, tags tables, info files, and so on.
-#
-# make extraclean
-# Still more severe - delete backup and autosave files, too.
-
-SHELL = /bin/sh
-
-# If Make doesn't predefine MAKE, set it here.
-@SET_MAKE@
-
-# ==================== Things `configure' Might Edit ====================
-
-CC=@CC@
-CPP=@CPP@
-C_SWITCH_SYSTEM=@c_switch_system@
-ALLOCA=@ALLOCA@
-LN_S=@LN_S@
-CFLAGS=@CFLAGS@
-C_SWITCH_X_SITE=@C_SWITCH_X_SITE@
-LD_SWITCH_X_SITE=@LD_SWITCH_X_SITE@
-YACC=@YACC@
-
-### These help us choose version- and architecture-specific directories
-### to install files in.
-
-### This should be the number of the Emacs version we're building,
-### like `18.59' or `19.0'.
-version=@version@
-
-### This should be the name of the configuration we're building Emacs
-### for, like `mips-dec-ultrix' or `sparc-sun-sunos'.
-configuration=@configuration@
-
-# ==================== Where To Install Things ====================
-
-# The default location for installation. Everything is placed in
-# subdirectories of this directory. The default values for many of
-# the variables below are expressed in terms of this one, so you may
-# not need to change them. This defaults to /usr/local.
-prefix=@prefix@
-
-# Like `prefix', but used for architecture-specific files.
-exec_prefix=@exec_prefix@
-
-# Where to install Emacs and other binaries that people will want to
-# run directly (like etags).
-bindir=@bindir@
-
-# Where to install architecture-independent data files. ${lispdir}
-# and ${etcdir} are subdirectories of this.
-datadir=@datadir@
-
-# Where to install and expect the files that Emacs modifies as it
-# runs. These files are all architecture-independent. Right now, the
-# only such data is the locking directory; ${lockdir} is a
-# subdirectory of this.
-sharedstatedir=@sharedstatedir@
-
-# Where to install and expect executable files to be run by Emacs
-# rather than directly by users, and other architecture-dependent
-# data. ${archlibdir} is a subdirectory of this.
-libexecdir=@libexecdir@
-
-# Where to install Emacs's man pages, and what extension they should have.
-mandir=@mandir@
-manext=.1
-man1dir=$(mandir)/man1
-
-# Where to install and expect the info files describing Emacs. In the
-# past, this defaulted to a subdirectory of ${prefix}/lib/emacs, but
-# since there are now many packages documented with the texinfo
-# system, it is inappropriate to imply that it is part of Emacs.
-infodir=@infodir@
-
-# Where to look for bitmap files.
-bitmapdir=@bitmapdir@
-
-# Where to find the source code. The source code for Emacs's C kernel is
-# expected to be in ${srcdir}/src, and the source code for Emacs's
-# utility programs is expected to be in ${srcdir}/lib-src. This is
-# set by the configure script's `--srcdir' option.
-srcdir=@srcdir@
-
-# Tell make where to find source files; this is needed for the makefiles.
-VPATH=@srcdir@
-
-# ==================== Emacs-specific directories ====================
-
-# These variables hold the values Emacs will actually use. They are
-# based on the values of the standard Make variables above.
-
-# Where to install the lisp files distributed with
-# Emacs. This includes the Emacs version, so that the
-# lisp files for different versions of Emacs will install
-# themselves in separate directories.
-lispdir=@lispdir@
-
-# Directories Emacs should search for lisp files specific
-# to this site (i.e. customizations), before consulting
-# ${lispdir}. This should be a colon-separated list of
-# directories.
-locallisppath=@locallisppath@
-
-# Where Emacs will search to find its lisp files. Before
-# changing this, check to see if your purpose wouldn't
-# better be served by changing locallisppath. This
-# should be a colon-separated list of directories.
-lisppath=@lisppath@
-
-# Where Emacs will search for its lisp files while
-# building. This is only used during the process of
-# compiling Emacs, to help Emacs find its lisp files
-# before they've been installed in their final location.
-# It's usually identical to lisppath, except that
-# it does not include locallisppath, and the
-# entry for the directory containing the installed lisp
-# files has been replaced with ../lisp. This should be a
-# colon-separated list of directories.
-buildlisppath=${srcdir}/lisp
-
-# Where to install the other architecture-independent
-# data files distributed with Emacs (like the tutorial,
-# the cookie recipes and the Zippy database). This path
-# usually contains the Emacs version number, so the data
-# files for multiple versions of Emacs may be installed
-# at once.
-etcdir=@etcdir@
-
-# Where to create and expect the locking directory, where
-# the Emacs locking code keeps track of which files are
-# currently being edited.
-lockdir=@lockdir@
-
-# Where to put executables to be run by Emacs rather than
-# the user. This path usually includes the Emacs version
-# and configuration name, so that multiple configurations
-# for multiple versions of Emacs may be installed at
-# once.
-archlibdir=@archlibdir@
-
-# Where to put the docstring file.
-docdir=@docdir@
-
-# ==================== Utility Programs for the Build ====================
-
-# Allow the user to specify the install program.
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-# By default, we uphold the dignity of our programs.
-INSTALL_STRIP =
-
-# ============================= Targets ==============================
-
-# What emacs should be called when installed.
-EMACS = emacs
-
-# 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 = lib-src src
-
-# The makefiles of the directories in $SUBDIR.
-SUBDIR_MAKEFILES = lib-src/Makefile man/Makefile src/Makefile oldXMenu/Makefile lwlib/Makefile
-
-# Subdirectories to install, and where they'll go.
-# lib-src's makefile knows how to install it, so we don't do that here.
-# When installing the info files, we need to do special things to
-# avoid nuking an existing dir file, so we don't do that here;
-# instead, we have written out explicit code in the `install' targets.
-COPYDIR = ${srcdir}/etc ${srcdir}/lisp
-COPYDESTS = ${etcdir} ${lispdir}
-
-all: ${SUBDIR}
-
-removenullpaths=sed -e 's/^://g' -e 's/:$$//g' -e 's/::/:/g'
-
-# Generate paths.h from paths.in. This target is invoked by `configure'.
-paths-force: FRC
- @(lisppath=`echo ${lisppath} | ${removenullpaths}` ; \
- buildlisppath=`echo ${buildlisppath} | ${removenullpaths}` ; \
- sed < ${srcdir}/src/paths.in > paths.h.$$$$ \
- -e 's;\(#.*PATH_LOADSEARCH\).*$$;\1 "'$${lisppath}'";' \
- -e 's;\(#.*PATH_DUMPLOADSEARCH\).*$$;\1 "'$${buildlisppath}'";' \
- -e 's;\(#.*PATH_EXEC\).*$$;\1 "${archlibdir}";' \
- -e 's;\(#.*PATH_INFO\).*$$;\1 "${infodir}";' \
- -e 's;\(#.*PATH_DATA\).*$$;\1 "${etcdir}";' \
- -e 's;\(#.*PATH_BITMAPS\).*$$;\1 "${bitmapdir}";' \
- -e 's;\(#.*PATH_DOC\).*$$;\1 "${docdir}";' \
- -e 's;\(#.*PATH_LOCK\).*$$;\1 "${lockdir}/";') && \
- ${srcdir}/move-if-change paths.h.$$$$ src/paths.h
-
-src: lib-src FRC
-
-lib-src: FRC
-
-.RECURSIVE: ${SUBDIR}
-
-${SUBDIR}: ${SUBDIR_MAKEFILES} FRC
- cd $@; $(MAKE) all $(MFLAGS) \
- CC='${CC}' CFLAGS='${CFLAGS}' CPPFLAGS='${CPPFLAGS}' \
- LDFLAGS='${LDFLAGS}' MAKE='${MAKE}'
-
-blessmail: ${SUBDIR_MAKEFILES} src FRC
- cd lib-src; $(MAKE) maybe-blessmail $(MFLAGS) \
- MAKE='${MAKE}' archlibdir='$(archlibdir)'
-
-Makefile: Makefile.in config.status
- ./config.status
-
-src/Makefile: src/Makefile.in config.status
- ./config.status
-
-lib-src/Makefile: lib-src/Makefile.in config.status
- ./config.status
-
-oldXMenu/Makefile: oldXMenu/Makefile.in config.status
- ./config.status
-
-lwlib/Makefile: lwlib/Makefile.in config.status
- ./config.status
-
-# ==================== Installation ====================
-
-## If we let lib-src do its own installation, that means we
-## don't have to duplicate the list of utilities to install in
-## this Makefile as well.
-
-## On AIX, use tar xBf.
-## On Xenix, use tar xpf.
-
-.PHONY: install mkdir
-
-## We delete each directory in ${COPYDESTS} before we copy into it;
-## that way, we can reinstall over directories that have been put in
-## place with their files read-only (perhaps because they are checked
-## into RCS). In order to make this safe, we make sure that the
-## source exists and is distinct from the destination.
-### We do install-arch-indep first because
-### the executable needs the Lisp files and DOC file to work properly.
-install: all install-arch-indep install-arch-dep blessmail
- @true
-
-### Install the executables that were compiled specifically for this machine.
-### It would be nice to do something for a parallel make
-### to ensure that install-arch-indep finishes before this starts.
-install-arch-dep: mkdir
- (cd lib-src; \
- $(MAKE) install $(MFLAGS) prefix=${prefix} \
- exec_prefix=${exec_prefix} bindir=${bindir} \
- libexecdir=${libexecdir} archlibdir=${archlibdir} \
- INSTALL_STRIP=${INSTALL_STRIP})
- ${INSTALL_PROGRAM} $(INSTALL_STRIP) src/emacs ${bindir}/emacs-${version}
- -chmod 1755 ${bindir}/emacs-${version}
- rm -f ${bindir}/$(EMACS)
- -ln ${bindir}/emacs-${version} ${bindir}/$(EMACS)
-
-### Install the files that are machine-independent.
-### Most of them come straight from the distribution;
-### the exception is the DOC-* files, which are copied
-### from the build directory.
-
-### Note that we copy DOC* and then delete DOC
-### as a workaround for a bug in tar on Ultrix 4.2.
-install-arch-indep: mkdir
- -set ${COPYDESTS} ; \
- for dir in ${COPYDIR} ; do \
- if [ `(cd $$1 && /bin/pwd)` != `(cd $${dir} && /bin/pwd)` ] ; then \
- rm -rf $$1 ; \
- fi ; \
- shift ; \
- done
- -set ${COPYDESTS} ; \
- mkdir ${COPYDESTS} ; \
- chmod ugo+rx ${COPYDESTS} ; \
- for dir in ${COPYDIR} ; do \
- dest=$$1 ; shift ; \
- [ -d $${dir} ] \
- && [ `(cd $${dir} && /bin/pwd)` != `(cd $${dest} && /bin/pwd)` ] \
- && (echo "Copying $${dir} to $${dest}..." ; \
- (cd $${dir}; tar -cf - . )|(cd $${dest};umask 022; tar -xvf - ); \
- for subdir in `find $${dest} -type d ! -name RCS -print` ; do \
- rm -rf $${subdir}/RCS ; \
- rm -rf $${subdir}/CVS ; \
- rm -f $${subdir}/\#* ; \
- rm -f $${subdir}/.\#* ; \
- rm -f $${subdir}/*~ ; \
- rm -f $${subdir}/*.orig ; \
- rm -f $${subdir}/[mM]akefile* ; \
- rm -f $${subdir}/ChangeLog* ; \
- rm -f $${subdir}/dired.todo ; \
- done) ; \
- done
- -rm -f ${lispdir}/subdirs.el
- $(srcdir)/update-subdirs ${lispdir}
- -chmod -R a+r ${COPYDESTS}
- if [ `(cd ./etc; /bin/pwd)` != `(cd ${docdir}; /bin/pwd)` ]; \
- then \
- echo "Copying etc/DOC-* to ${docdir} ..." ; \
- (cd ./etc; tar -cf - DOC*)|(cd ${docdir}; umask 0; tar -xvf - ); \
- (cd $(docdir); chmod a+r DOC*; rm DOC) \
- else true; fi
- if [ -r ./lisp ] \
- && [ x`(cd ./lisp; /bin/pwd)` != x`(cd ${lispdir}; /bin/pwd)` ] \
- && [ x`(cd ${srcdir}/lisp; /bin/pwd)` != x`(cd ./lisp; /bin/pwd)` ]; \
- then \
- echo "Copying lisp/*.el and lisp/*.elc to ${lispdir} ..." ; \
- (cd lisp; tar -cf - *.el *.elc)|(cd ${lispdir}; umask 0; tar -xvf - ); \
- else true; fi
- thisdir=`/bin/pwd`; \
- if [ `(cd ${srcdir}/info && /bin/pwd)` != `(cd ${infodir} && /bin/pwd)` ]; \
- then \
- (cd ${infodir}; \
- if [ -f dir ]; then \
- if [ ! -f dir.old ]; then mv -f dir dir.old; \
- else mv -f dir dir.bak; fi; \
- fi; \
- cd ${srcdir}/info ; \
- (cd $${thisdir}; ${INSTALL_DATA} ${srcdir}/info/dir ${infodir}/dir); \
- (cd $${thisdir}; chmod a+r ${infodir}/dir); \
- for f in ccmode* cl* dired-x* ediff* emacs* forms* gnus* info* message* mh-e* sc* vip*; do \
- (cd $${thisdir}; \
- ${INSTALL_DATA} ${srcdir}/info/$$f ${infodir}/$$f; \
- chmod a+r ${infodir}/$$f); \
- done); \
- else true; fi
- thisdir=`/bin/pwd`; \
- cd ${srcdir}/etc; \
- for page in emacs etags ctags ; do \
- (cd $${thisdir}; \
- ${INSTALL_DATA} ${srcdir}/etc/$${page}.1 ${man1dir}/$${page}${manext}; \
- chmod a+r ${man1dir}/$${page}${manext}); \
- done
-
-### Build Emacs and install it, stripping binaries while installing them.
-install-strip:
- $(MAKE) INSTALL_STRIP=-s
-
-### Build all the directories we're going to install Emacs in. Since
-### we may be creating several layers of directories (for example,
-### /usr/local/lib/emacs/19.0/mips-dec-ultrix4.2), we use mkinstalldirs
-### instead of mkdir. Not all systems' mkdir programs have the `-p' flag.
-mkdir: FRC
- $(srcdir)/mkinstalldirs ${COPYDESTS} ${lockdir} ${infodir} ${man1dir} \
- ${bindir} ${datadir} ${docdir} ${libexecdir} \
- `echo ${locallisppath} | sed 's/:/ /g'`
- -chmod a+rwx ${lockdir}
-
-### Delete all the installed files that the `install' target would
-### create (but not the noninstalled files such as `make all' would
-### create).
-###
-### Don't delete the lisp and etc directories if they're in the source tree.
-uninstall:
- (cd lib-src; \
- $(MAKE) $(MFLAGS) uninstall \
- prefix=${prefix} exec_prefix=${exec_prefix} \
- bindir=${bindir} libexecdir=${libexecdir} archlibdir=${archlibdir})
- for dir in ${lispdir} ${etcdir} ; do \
- if [ -d $${dir} ]; then \
- case `(cd $${dir} ; /bin/pwd)` in \
- `(cd ${srcdir} ; /bin/pwd)`* ) ;; \
- * ) rm -rf $${dir} ;; \
- esac ; \
- case $${dir} in \
- ${datadir}/emacs/${version}/* ) \
- rm -rf ${datadir}/emacs/${version} \
- ;; \
- esac ; \
- fi ; \
- done
- (cd ${infodir} && rm -f cl* dired-x* ediff* emacs* forms* gnus* info* mh-e* sc* vip*)
- (cd ${man1dir} && rm -f emacs.1 etags.1 ctags.1)
- (cd ${bindir} && rm -f emacs-${version} $(EMACS))
-
-
-FRC:
-
-# ==================== Cleaning up and miscellanea ====================
-
-.PHONY: mostlyclean clean distclean maintainer-clean extraclean
-
-### `mostlyclean'
-### Like `clean', but may refrain from deleting a few files that people
-### normally don't want to recompile. For example, the `mostlyclean'
-### target for GCC does not delete `libgcc.a', because recompiling it
-### is rarely necessary and takes a lot of time.
-mostlyclean: FRC
- (cd src; $(MAKE) $(MFLAGS) mostlyclean)
- (cd oldXMenu; $(MAKE) $(MFLAGS) mostlyclean)
- (cd lwlib; $(MAKE) $(MFLAGS) mostlyclean)
- (cd lib-src; $(MAKE) $(MFLAGS) mostlyclean)
- -(cd man && $(MAKE) $(MFLAGS) mostlyclean)
-
-### `clean'
-### Delete all files from the current directory that are normally
-### created by building the program. Don't delete the files that
-### record the configuration. Also preserve files that could be made
-### by building, but normally aren't because the distribution comes
-### with them.
-###
-### Delete `.dvi' files here if they are not part of the distribution.
-clean: FRC
- (cd src; $(MAKE) $(MFLAGS) clean)
- (cd oldXMenu; $(MAKE) $(MFLAGS) clean)
- (cd lwlib; $(MAKE) $(MFLAGS) clean)
- (cd lib-src; $(MAKE) $(MFLAGS) clean)
- -(cd man && $(MAKE) $(MFLAGS) clean)
-
-### `distclean'
-### Delete all files from the current directory that are created by
-### configuring or building the program. If you have unpacked the
-### source and built the program without creating any other files,
-### `make distclean' should leave only the files that were in the
-### distribution.
-top_distclean=\
- rm -f config.status config.cache config.log ; \
- rm -f Makefile ${SUBDIR_MAKEFILES} ; \
- (cd lock && (rm * || true))
-distclean: FRC
- (cd src; $(MAKE) $(MFLAGS) distclean)
- (cd oldXMenu; $(MAKE) $(MFLAGS) distclean)
- (cd lwlib; $(MAKE) $(MFLAGS) distclean)
- (cd lib-src; $(MAKE) $(MFLAGS) distclean)
- (cd man && $(MAKE) $(MFLAGS) distclean)
- ${top_distclean}
-
-### `maintainer-clean'
-### Delete everything from the current directory that can be
-### reconstructed with this Makefile. This typically includes
-### everything deleted by distclean, plus more: C source files
-### produced by Bison, tags tables, info files, and so on.
-###
-### One exception, however: `make maintainer-clean' should not delete
-### `configure' even if `configure' can be remade using a rule in the
-### Makefile. More generally, `make maintainer-clean' should not delete
-### anything that needs to exist in order to run `configure' and then
-### begin to build the program.
-maintainer-clean: FRC
- (cd src; $(MAKE) $(MFLAGS) maintainer-clean)
- (cd oldXMenu; $(MAKE) $(MFLAGS) maintainer-clean)
- (cd lwlib; $(MAKE) $(MFLAGS) maintainer-clean)
- (cd lib-src; $(MAKE) $(MFLAGS) maintainer-clean)
- -(cd man && $(MAKE) $(MFLAGS) maintainer-clean)
- ${top_distclean}
-
-### This doesn't actually appear in the coding standards, but Karl
-### says GCC supports it, and that's where the configuration part of
-### the coding standards seem to come from. It's like distclean, but
-### it deletes backup and autosave files too.
-extraclean:
- for i in ${SUBDIR}; do (cd $$i; $(MAKE) $(MFLAGS) extraclean); done
- ${top_distclean}
- -rm config-tmp-*
- -rm -f *~ \#*
-
-### Unlocking and relocking. The idea of these productions is to reduce
-### hassles when installing an incremental tar of Emacs. Do `make unlock'
-### before unlocking the file to take the write locks off all sources so
-### that tar xvof will overwrite them without fuss. Then do `make relock'
-### afterward so that VC mode will know which files should be checked in
-### if you want to mung them.
-###
-### Note: it's no disaster if these productions miss a file or two; tar
-### and VC will swiftly let you know if this happens, and it is easily
-### corrected.
-SOURCES = ChangeLog GETTING.GNU.SOFTWARE INSTALL Makefile.in PROBLEMS \
- README configure make-dist move-if-change
-
-.PHONY: unlock relock
-
-unlock:
- chmod u+w $(SOURCES) cpp/*
- -(cd elisp; chmod u+w Makefile README *.texi)
- (cd etc; $(MAKE) $(MFLAGS) unlock)
- (cd lib-src; $(MAKE) $(MFLAGS) unlock)
- (cd lisp; $(MAKE) $(MFLAGS) unlock)
- (cd lisp/term; chmod u+w README *.el)
- (cd man; chmod u+w *texi* ChangeLog split-man)
- (cd oldXMenu; chmod u+w *.[ch] Makefile README)
- (cd lwlib; chmod u+w *.[ch] Makefile README)
- (cd src; $(MAKE) $(MFLAGS) unlock)
-
-relock:
- chmod u-w $(SOURCES) cpp/*
- -(cd elisp; chmod u-w Makefile README *.texi)
- (cd etc; $(MAKE) $(MFLAGS) relock)
- (cd lib-src; $(MAKE) $(MFLAGS) relock)
- (cd lisp; $(MAKE) $(MFLAGS) relock)
- (cd lisp/term; chmod u+w README *.el)
- (cd man; chmod u+w *texi* ChangeLog split-man)
- (cd oldXMenu; chmod u+w *.[ch] Makefile README)
- (cd lwlib; chmod u+w *.[ch] Makefile README)
- (cd src; $(MAKE) $(MFLAGS) relock)
-
-TAGS tags: lib-src
- cd ${srcdir}/src; $(MAKE) tags
-
-check:
- @echo "We don't have any tests for GNU Emacs yet."
-
-dist:
- $(srcdir)/update-subdirs ${srcdir}/lisp
- cd ${srcdir}; make-dist
-
-.PHONY: info dvi dist check
-force-info:
-info: force-info
- (cd ${srcdir}/man; $(MAKE) $(MFLAGS) info)
-dvi:
- (cd man; $(MAKE) $(MFLAGS) dvi)
diff --git a/build-ins.in b/build-ins.in
deleted file mode 100755
index acca27689c1..00000000000
--- a/build-ins.in
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/bin/sh -x
-#
-#Shell script for building and installing Emacs.
-
-# ==================== Where To Install Things ====================
-
-# The default location for installation. Everything is placed in
-# subdirectories of this directory. This directory must exist when
-# you start installation. The default values for many of the
-# variables below are expressed in terms of this one, so you may not
-# need to change them.
-prefix=/usr/local
-
-# Where to install Emacs and other binaries that people will want to
-# run directly (like etags).
-bindir=${prefix}/bin
-
-# A directory under which we will install many of Emacs's files. The
-# default values for many of the variables below are expressed in
-# terms of this one, so you may not need to change them.
-emacsdir=${prefix}/emacs-19.0
-
-# Where to install and expect the architecture-independent data files
-# (like the tutorial and the Zippy database).
-datadir=${emacsdir}/etc
-
-# Where to install the elisp files distributed with Emacs. Strictly
-# speaking, all the elisp files should go under datadir (above), since
-# both elisp source and compiled elisp are completely portable, but
-# it's traditional to give the lisp files their own subdirectory.
-lispdir=${emacsdir}/lisp
-
-# Directories Emacs should search for elisp files specific to this
-# site (i.e. customizations), before consulting ${lispdir}. This
-# should be a colon-separated list of directories.
-locallisppath=${emacsdir}/local-lisp
-
-# Where Emacs will search to find its elisp files. Before changing
-# this, check to see if your purpose wouldn't better be served by
-# changing locallisppath. This should be a colon-separated list of
-# directories.
-lisppath=${locallisppath}:${lispdir}
-
-# Where Emacs will search for its elisp files before dumping. This is
-# only used during the process of compiling Emacs, to help Emacs find
-# its lisp files before they've been installed in their final
-# location. It's usually identical to lisppath, except that the entry
-# for the directory containing the installed lisp files has been
-# replaced with ../lisp. This should be a colon-separated list of
-# directories.
-dumplisppath=../lisp
-
-# Where to install and expect the files that Emacs modifies as it
-# runs. These files are all architecture-independent. Right now,
-# the only such data is the locking directory.
-statedir=${emacsdir}
-
-# Where to create and expect the locking directory, where the Emacs
-# locking code keeps track of which files are currently being edited.
-lockdir=${statedir}/lock
-
-# Where to install and expect executable files to be run by Emacs
-# rather than directly by users, and other architecture-dependent
-# data.
-libdir=${emacsdir}/arch-lib
-
-# Where to install Emacs's man pages.
-mandir=/usr/man/man1
-
-# Where to install and expect the info files describing Emacs. In the
-# past, this defaulted to a subdirectory of ${prefix}/lib/emacs, but
-# since there are now many packages documented with the texinfo
-# system, it is inappropriate to imply that it is part of Emacs.
-infodir=${prefix}/info
-
-removenullpaths="sed -e 's/^://' -e 's/:"'$'"//' -e 's/::/:/'"
-
-lisppath=`echo ${lisppath} | ${removenullpaths}` ; \
-dumplisppath=`echo ${dumplisppath} | ${removenullpaths}` ; \
-/bin/sed < src/paths.h.in > src/paths.h \
--e 's;\(#.*PATH_LOADSEARCH\).*$$;\1 "'$${lisppath}'";' \
--e 's;\(#.*PATH_DUMPLOADSEARCH\).*$$;\1 "'$${dumplisppath}'";' \
--e 's;\(#.*PATH_EXEC\).*$$;\1 "${libdir}";' \
--e 's;\(#.*PATH_DATA\).*$$;\1 "${datadir}";' \
--e 's;\(#.*PATH_LOCK\).*$$;\1 "${lockdir}/";'
-
-(cd lib-src; make) || exit 1
-(cd src; make) || exit 1
-
-# Subdirectories to install, and where they'll go.
-copydir=arch-lib etc info lisp
-copydests=${libdir} ${datadir} ${infodir} ${lispdir}
-
-# If any of the directories are below ${emacsdir} or ${statedir}, create them.
-for dir in ${copydests}; do
- case "${dir}" in
- ${emacsdir}/* )
- if [ ! -d ${emacsdir} ]; then
- mkdir ${emacsdir}
- chmod 777 ${emacsdir}
- fi
- ;;
- ${statedir}/* )
- if [ ! -d ${statedir} ]; then
- mkdir ${statedir}
- chmod 777 ${statedir}
- fi
- ;;
- esac
-done
-
-set ${copydests}
-for dir in ${copydir} ; do
- dest=$1 ; shift
- mv ${dir} ${dest}
- if [ $? != 0 ]; then
- echo mv ${dir} to ${dest} failed -- using tar to copy.
- if [ `/bin/pwd`/${dir} != `(cd ${dest}; /bin/pwd)` ] ; then
- (cd ${dir}; tar cf - . ) | (cd ${dest}; umask 0; tar xf - )
- if [ $? != 0 ]; then
- echo "tar-copying ${dir} to ${dest} failed too. I give up."
- exit 1
- fi
- for subdir in `find ${dest} -type d ! -name RCS -print` ; do
- rm -rf ${subdir}/RCS
- rm -f ${subdir}/\#*
- rm -f ${subdir}/*~
- done
- fi
- fi
-done
-
-cp ${libdir}/[ce]tags ${bindir}
-mv src/emacs ${BINDIR}/emacs
-rm src/temacs
-chmod 777 ${bindir}/[ce]tags ${bindir}/emacs
diff --git a/config.bat b/config.bat
deleted file mode 100644
index dfd7505d39d..00000000000
--- a/config.bat
+++ /dev/null
@@ -1,218 +0,0 @@
-@echo off
-rem ----------------------------------------------------------------------
-rem Configuration script for MSDOS
-rem Copyright (C) 1994 Free Software Foundation, Inc.
-
-rem This file is part of GNU Emacs.
-
-rem GNU Emacs is free software; you can redistribute it and/or modify
-rem it under the terms of the GNU General Public License as published by
-rem the Free Software Foundation; either version 2, or (at your option)
-rem any later version.
-
-rem GNU Emacs is distributed in the hope that it will be useful,
-rem but WITHOUT ANY WARRANTY; without even the implied warranty of
-rem MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-rem GNU General Public License for more details.
-
-rem You should have received a copy of the GNU General Public License
-rem along with GNU Emacs; see the file COPYING. If not, write to the
-rem Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-rem Boston, MA 02111-1307, USA.
-rem ----------------------------------------------------------------------
-rem YOU'LL NEED THE FOLLOWING UTILITIES TO MAKE EMACS:
-rem
-rem + msdos version 3 or better.
-rem + djgpp version 1.12maint1 or later (version 2.0 or later recommended).
-rem + make utility that allows breaking of the 128 chars limit on
-rem command lines. ndmake (as of version 4.5) won't work due to a
-rem line length limit. The make that comes with djgpp does work.
-rem + rm and mv (from GNU file utilities).
-rem + sed (you can use the port that comes with DJGPP).
-rem
-rem You should be able to get all the above utilities from any SimTel
-rem repository, e.g. ftp.coast.net, in the directories
-rem "SimTel/vendors/djgpp" and "SimTel/vendors/gnu/gnuish/dos_only". As
-rem usual, please use your local mirroring site to reduce trans-Atlantic
-rem traffic.
-rem ----------------------------------------------------------------------
-set X11=
-set nodebug=
-set djgpp_ver=
-:again
-if "%1" == "" goto usage
-if "%1" == "--with-x" goto withx
-if "%1" == "--no-debug" goto nodebug
-if "%1" == "msdos" goto msdos
-:usage
-echo Usage: config [--with-x] [--no-debug] msdos
-echo [Read the script before you run it.]
-goto end
-rem ----------------------------------------------------------------------
-:withx
-set X11=Y
-shift
-goto again
-rem ----------------------------------------------------------------------
-:nodebug
-set nodebug=Y
-shift
-goto again
-rem ----------------------------------------------------------------------
-:msdos
-Echo Checking whether 'sed' is available...
-sed -e "w junk.$$$" <Nul
-If Exist junk.$$$ Goto sedOk
-Echo To configure 'Emacs' you need to have 'sed'!
-Goto End
-:sedOk
-Echo Checking whether 'rm' is available...
-rm -f junk.$$$
-If Not Exist junk.$$$ Goto rmOk
-Echo To configure 'Emacs' you need to have 'rm'!
-Goto End
-:rmOk
-Echo Checking whether 'mv' is available...
-rm -f junk.1 junk.2
-echo foo >junk.1
-mv junk.1 ./junk.2
-If Exist junk.2 Goto mvOk
-Echo To configure 'Emacs' you need to have 'mv'!
-rm -f junk.1
-Goto End
-:mvOk
-rm -f junk.2
-Echo Checking whether 'gcc' is available...
-echo main(){} >junk.c
-gcc -c junk.c
-if exist junk.o goto gccOk
-Echo To configure 'Emacs' you need to have 'gcc'!
-rm -f junk.c
-Goto End
-:gccOk
-rm -f junk.c junk.o junk junk.exe
-Echo Checking what version of DJGPP is installed...
-If Not "%DJGPP%" == "" goto djgppOk
-Echo To compile 'Emacs' under MS-DOS you MUST have DJGPP installed!
-Goto End
-:djgppOk
-echo int main() >junk.c
-echo #ifdef __DJGPP__ >>junk.c
-echo {return (__DJGPP__)*10;} >>junk.c
-echo #else >>junk.c
-echo #ifdef __GO32__ >>junk.c
-echo {return 10;} >>junk.c
-echo #else >>junk.c
-echo {return 0;} >>junk.c
-echo #endif >>junk.c
-echo #endif >>junk.c
-gcc -o junk junk.c
-if not exist junk.exe coff2exe junk
-junk
-If ErrorLevel 10 Goto go32Ok
-rm -f junk.c junk junk.exe
-Echo To compile 'Emacs' under MS-DOS you MUST have DJGPP installed!
-Goto End
-:go32Ok
-set djgpp_ver=1
-If ErrorLevel 20 set djgpp_ver=2
-rm -f junk.c junk junk.exe
-Echo Configuring for DJGPP Version %DJGPP_VER% ...
-Rem ----------------------------------------------------------------------
-Echo Configuring the source directory...
-cd src
-
-rem Create "paths.h"
-sed -f ../msdos/sed4.inp <paths.in >paths.tmp
-update paths.tmp paths.h >nul
-rm -f paths.tmp
-
-rem Create "config.h"
-rm -f config.h2 config.tmp
-cp config.in config.tmp
-if "%X11%" == "" goto src4
-sed -f ../msdos/sed2x.inp <config.in >config.tmp
-:src4
-sed -f ../msdos/sed2.inp <config.tmp >config.h2
-update config.h2 config.h >nul
-rm -f config.tmp config.h2
-
-rem On my system dir.h gets in the way. It's a VMS file so who cares.
-if exist dir.h ren dir.h vmsdir.h
-
-rem Create "makefile" from "makefile.in".
-rm -f makefile junk.c
-sed -e "1,/cpp stuff/s@^# .*$@@" <makefile.in >junk.c
-If "%DJGPP_VER%" == "1" Goto mfV1
-gcc -E junk.c | sed -f ../msdos/sed1v2.inp >makefile
-goto mfDone
-:mfV1
-gcc -E junk.c | sed -f ../msdos/sed1.inp >makefile
-:mfDone
-rm -f junk.c
-
-if "%X11%" == "" goto src5
-mv makefile makefile.tmp
-sed -f ../msdos/sed1x.inp <makefile.tmp >makefile
-rm -f makefile.tmp
-:src5
-
-if "%nodebug%" == "" goto src6
-sed -e "/^CFLAGS *=/s/ *-g//" <makefile >makefile.tmp
-sed -e "/^LDFLAGS *=/s/=/=-s/" <makefile.tmp >makefile
-rm -f makefile.tmp
-:src6
-cd ..
-rem ----------------------------------------------------------------------
-Echo Configuring the library source directory...
-cd lib-src
-rem Create "makefile" from "makefile.in".
-sed -e "1,/cpp stuff/s@^# .*$@@" <makefile.in >junk.c
-gcc -E -I. -I../src junk.c | sed -e "s/^ / /" -e "/^#/d" -e "/^[ ]*$/d" >makefile.new
-If "%DJGPP_VER%" == "2" goto libsrc-v2
-sed -f ../msdos/sed3.inp <makefile.new >makefile
-Goto libsrc2
-:libsrc-v2
-sed -f ../msdos/sed3v2.inp <makefile.new >makefile
-:libsrc2
-rm -f makefile.new junk.c
-if "%nodebug%" == "" goto libsrc3
-sed -e "/^CFLAGS *=/s/ *-g//" <makefile >makefile.tmp
-sed -e "/^ALL_CFLAGS *=/s/=/= -s/" <makefile.tmp >makefile
-rm -f makefile.tmp
-:libsrc3
-cd ..
-rem ----------------------------------------------------------------------
-if "%X11%" == "" goto oldx1
-Echo Configuring the oldxmenu directory...
-cd oldxmenu
-sed -f ../msdos/sed5x.inp <makefile.in >makefile
-if "%nodebug%" == "" goto oldx2
-sed -e "/^CFLAGS *=/s/ *-g//" <makefile >makefile.tmp
-mv -f makefile.tmp makefile
-:oldx2
-cd ..
-:oldx1
-rem ----------------------------------------------------------------------
-Echo Configuring the main directory...
-If "%DJGPP_VER%" == "1" goto mainv1
-Echo Looking for the GDB init file...
-If Exist src\_gdbinit goto gdbinitOk
-Echo ERROR:
-Echo I cannot find the GDB init file. It was called ".gdbinit" in
-Echo the Emacs distribution, but was probably renamed to some other
-Echo name without the leading dot when you untarred the archive.
-Echo It should be in the "src/" subdirectory. Please make sure this
-Echo file exists and is called "_gdbinit" with a leading underscore.
-Echo Then run CONFIG.BAT again with the same arguments you did now.
-goto End
-:gdbinitOk
-Echo Looking for the GDB init file...found
-copy msdos\mainmake.v2 makefile >nul
-:mainv1
-If "%DJGPP_VER%" == "1" copy msdos\mainmake makefile >nul
-rem ----------------------------------------------------------------------
-:end
-set X11=
-set nodebug=
-set djgpp_ver=
diff --git a/config.guess b/config.guess
index a33514f2462..5ef19b5a18a 100755
--- a/config.guess
+++ b/config.guess
@@ -68,8 +68,20 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
echo m68k-cbm-netbsd${UNAME_RELEASE}
exit 0 ;;
amiga:OpenBSD:*:*)
- echo m68k-cbm-openbsd${UNAME_RELEASE}
- exit 0 ;;
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mips64el-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ laguna:OpenBSD:*:*)
+ echo mips64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mips64el-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mips64el-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit 0;;
@@ -118,19 +130,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
echo m68k-atari-netbsd${UNAME_RELEASE}
exit 0 ;;
atari*:OpenBSD:*:*)
- echo m68k-atari-openbsd${UNAME_RELEASE}
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
sun3*:NetBSD:*:*)
echo m68k-sun-netbsd${UNAME_RELEASE}
exit 0 ;;
sun3*:OpenBSD:*:*)
- echo m68k-sun-openbsd${UNAME_RELEASE}
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
mac68k:NetBSD:*:*)
echo m68k-apple-netbsd${UNAME_RELEASE}
exit 0 ;;
mac68k:OpenBSD:*:*)
- echo m68k-apple-openbsd${UNAME_RELEASE}
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
powerpc:machten:*:*)
echo powerpc-apple-machten${UNAME_RELEASE}
@@ -378,8 +396,8 @@ EOF
hp3[0-9][05]:NetBSD:*:*)
echo m68k-hp-netbsd${UNAME_RELEASE}
exit 0 ;;
- hp3[0-9][05]:OpenBSD:*:*)
- echo m68k-hp-openbsd${UNAME_RELEASE}
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
i?86:BSD/386:*:* | *:BSD/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
diff --git a/configure.in b/configure.in
deleted file mode 100644
index 4aa2d9c38de..00000000000
--- a/configure.in
+++ /dev/null
@@ -1,1758 +0,0 @@
-dnl Autoconf script for GNU Emacs
-dnl To rebuild the `configure' script from this, execute the command
-dnl autoconf
-dnl in the directory containing this script.
-dnl
-dnl Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-dnl
-dnl This file is part of GNU Emacs.
-dnl
-dnl GNU Emacs is free software; you can redistribute it and/or modify
-dnl it under the terms of the GNU General Public License as published by
-dnl the Free Software Foundation; either version 2, or (at your option)
-dnl any later version.
-dnl
-dnl GNU Emacs is distributed in the hope that it will be useful,
-dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
-dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-dnl GNU General Public License for more details.
-dnl
-dnl You should have received a copy of the GNU General Public License
-dnl along with GNU Emacs; see the file COPYING. If not, write to the
-dnl Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-dnl Boston, MA 02111-1307, USA.
-
-AC_PREREQ(2.8)dnl
-AC_INIT(src/lisp.h)
-AC_CONFIG_HEADER(src/config.h:src/config.in)
-
-lispdir='${datadir}/emacs/${version}/lisp'
-locallisppath='${datadir}/emacs/${version}/site-lisp:'\
-'${datadir}/emacs/site-lisp:${datadir}/emacs/${version}/leim'
-lisppath='${locallisppath}:${lispdir}'
-etcdir='${datadir}/emacs/${version}/etc'
-lockdir='${sharedstatedir}/emacs/lock'
-archlibdir='${libexecdir}/emacs/${version}/${configuration}'
-docdir='${datadir}/emacs/${version}/etc'
-
-AC_ARG_WITH(gcc,
-[ --with-gcc use GCC to compile Emacs])
-AC_ARG_WITH(pop,
-[ --with-pop support POP for mail retrieval],
-[AC_DEFINE(MAIL_USE_POP)])
-AC_ARG_WITH(kerberos,
-[ --with-kerberos support Kerberos-authenticated POP],
-[AC_DEFINE(KERBEROS)])
-AC_ARG_WITH(hesiod,
-[ --with-hesiod support Hesiod to get the POP server host],
-[AC_DEFINE(HESIOD)])
-dnl This should be the last --with option, because --with-x is
-dnl added later on when we find the path of X, and it's best to
-dnl keep them together visually.
-AC_ARG_WITH(x-toolkit,
-[ --with-x-toolkit=KIT use an X toolkit (KIT = yes/lucid/athena/motif/no)],
-[ case "${withval}" in
- y | ye | yes ) val=athena ;;
- n | no ) val=no ;;
- l | lu | luc | luci | lucid ) val=lucid ;;
- a | at | ath | athe | athen | athena ) val=athena ;;
- m | mo | mot | moti | motif ) val=motif ;;
-dnl These don't currently work.
-dnl o | op | ope | open | open- | open-l | open-lo \
-dnl | open-loo | open-look ) val=open-look ;;
- * )
-dnl AC_MSG_ERROR([the \`--with-x-toolkit' option is supposed to have a value
-dnl which is \`yes', \`no', \`lucid', \`athena', \`motif' or \`open-look'.])
-AC_MSG_ERROR([\`--with-x-toolkit=$withval' is invalid\;
-this option's value should be \`yes', \`no', \`lucid', \`athena', or \`motif'.
-Currently, \`yes', \`athena' and \`lucid' are synonyms.])
- ;;
- esac
- with_x_toolkit=$val
-])
-
-#### Make srcdir absolute, if it isn't already. It's important to
-#### avoid running the path through pwd unnecessary, since pwd can
-#### give you automounter prefixes, which can go away. We do all this
-#### so Emacs can find its files when run uninstalled.
-case "${srcdir}" in
- /* ) ;;
- . )
- ## We may be able to use the $PWD environment variable to make this
- ## absolute. But sometimes PWD is inaccurate.
- ## Make sure CDPATH doesn't affect cd (in case PWD is relative).
- CDPATH=
- if test "${PWD}" != "" && test "`(cd ${PWD} ; sh -c pwd)`" = "`pwd`" ;
- then
- srcdir="$PWD"
- else
- srcdir="`(cd ${srcdir}; pwd)`"
- fi
- ;;
- * ) srcdir="`(cd ${srcdir}; pwd)`" ;;
-esac
-
-#### Check if the source directory already has a configured system in it.
-if test `pwd` != `(cd ${srcdir} && pwd)` \
- && test -f "${srcdir}/src/config.h" ; then
- AC_MSG_WARN([The directory tree \`${srcdir}' is being used
- as a build directory right now; it has been configured in its own
- right. To configure in another directory as well, you MUST
- use GNU make. If you do not have GNU make, then you must
- now do \`make distclean' in ${srcdir},
- and then run $0 again.])
-
-changequote(, )dnl
- extrasub='/^VPATH[ ]*=/c\
-changequote([, ])dnl
-vpath %.c $(srcdir)\
-vpath %.h $(srcdir)\
-vpath %.y $(srcdir)\
-vpath %.l $(srcdir)\
-vpath %.s $(srcdir)\
-vpath %.in $(srcdir)\
-vpath %.texi $(srcdir)'
-fi
-
-#### Given the configuration name, set machfile and opsysfile to the
-#### names of the m/*.h and s/*.h files we should use.
-
-### Canonicalize the configuration name.
-
-AC_CANONICAL_HOST
-canonical=$host
-configuration=$host_alias
-
-changequote(, )dnl
-
-### If you add support for a new configuration, add code to this
-### switch statement to recognize your configuration name and select
-### the appropriate operating system and machine description files.
-
-### You would hope that you could choose an m/*.h file pretty much
-### based on the machine portion of the configuration name, and an s-
-### file based on the operating system portion. However, it turns out
-### that each m/*.h file is pretty manufacturer-specific - for
-### example, apollo.h, hp9000s300.h, mega68k, news.h, and tad68k are
-### all 68000 machines; mips.h, pmax.h, and news-risc are all MIPS
-### machines. So we basically have to have a special case for each
-### configuration name.
-###
-### As far as handling version numbers on operating systems is
-### concerned, make sure things will fail in a fixable way. If
-### /etc/MACHINES doesn't say anything about version numbers, be
-### prepared to handle anything reasonably. If version numbers
-### matter, be sure /etc/MACHINES says something about it.
-###
-### Eric Raymond says we should accept strings like "sysvr4" to mean
-### "System V Release 4"; he writes, "The old convention encouraged
-### confusion between `system' and `release' levels'."
-
-machine='' opsys='' unported=no
-case "${canonical}" in
-
- ## NetBSD ports
- *-*-netbsd* )
- opsys=netbsd
- case "${canonical}" in
- i[3456]86-*-netbsd*) machine=intel386 ;;
- m68k-*-netbsd*)
- # This is somewhat bogus.
- machine=hp9000s300 ;;
- mips-*-netbsd*) machine=pmax ;;
- ns32k-*-netbsd*) machine=ns32000 ;;
- sparc-*-netbsd*) machine=sparc ;;
- vax-*-netbsd*) machine=vax ;;
- esac
- ;;
-
- ## Acorn RISCiX:
- arm-acorn-riscix1.1* )
- machine=acorn opsys=riscix1-1
- ;;
- arm-acorn-riscix1.2* | arm-acorn-riscix )
- ## This name is riscix12 instead of riscix1.2
- ## to avoid a file name conflict on MSDOS.
- machine=acorn opsys=riscix12
- ;;
-
- ## Alliant machines
- ## Strictly speaking, we need the version of the alliant operating
- ## system to choose the right machine file, but currently the
- ## configuration name doesn't tell us enough to choose the right
- ## one; we need to give alliants their own operating system name to
- ## do this right. When someone cares, they can help us.
- fx80-alliant-* )
- machine=alliant4 opsys=bsd4-2
- ;;
- i860-alliant-* )
- machine=alliant-2800 opsys=bsd4-3
- ;;
-
- ## Alpha (DEC) machines.
- alpha-dec-osf* )
- machine=alpha opsys=osf1
- # This is needed to find X11R6.1 libraries for certain tests.
- NON_GCC_LINK_TEST_OPTIONS=-Wl,-rpath,/usr/X11R6/lib
- GCC_LINK_TEST_OPTIONS=-Wl,-rpath,/usr/X11R6/lib
- ;;
-
- alpha-*-linux-gnu* )
- machine=alpha opsys=gnu-linux
- ;;
-
- ## Altos 3068
- m68*-altos-sysv* )
- machine=altos opsys=usg5-2
- ;;
-
- ## Amdahl UTS
- 580-amdahl-sysv* )
- machine=amdahl opsys=usg5-2-2
- ;;
-
- ## Apollo, Domain/OS
- m68*-apollo-* )
- machine=apollo opsys=bsd4-3
- ;;
-
- ## AT&T 3b2, 3b5, 3b15, 3b20
- we32k-att-sysv* )
- machine=att3b opsys=usg5-2-2
- ;;
-
- ## AT&T 3b1 - The Mighty Unix PC!
- m68*-att-sysv* )
- machine=7300 opsys=usg5-2-2
- ;;
-
- ## Bull dpx20
- rs6000-bull-bosx* )
- machine=ibmrs6000 opsys=aix3-2
- ;;
-
- ## Bull dpx2
- m68*-bull-sysv3* )
- machine=dpx2 opsys=usg5-3
- ;;
-
- ## Bull sps7
- m68*-bull-sysv2* )
- machine=sps7 opsys=usg5-2
- ;;
-
- ## CCI 5/32, 6/32 -- see "Tahoe".
-
- ## Celerity
- ## I don't know what configuration name to use for this; config.sub
- ## doesn't seem to know anything about it. Hey, Celerity users, get
- ## in touch with us!
- celerity-celerity-bsd* )
- machine=celerity opsys=bsd4-2
- ;;
-
- ## Clipper
- ## What operating systems does this chip run that Emacs has been
- ## tested on?
- clipper-* )
- machine=clipper
- ## We'll use the catch-all code at the bottom to guess the
- ## operating system.
- ;;
-
- ## Convex
- *-convex-bsd* | *-convex-convexos* )
- machine=convex opsys=bsd4-3
- ## Prevents spurious white space in makefiles - d.m.cooke@larc.nasa.gov
- NON_GNU_CPP="cc -E -P"
- ;;
-
- ## Cubix QBx/386
- i[3456]86-cubix-sysv* )
- machine=intel386 opsys=usg5-3
- ;;
-
- ## Cydra 5
- cydra*-cydrome-sysv* )
- machine=cydra5 opsys=usg5-3
- ;;
-
- ## Data General AViiON Machines
- m88k-dg-dgux5.4R3* | m88k-dg-dgux5.4.3* )
- ## This name is dgux5-4-3 instead of dgux5-4r3
- ## to avoid a file name conflict on MSDOS.
- machine=aviion opsys=dgux5-4-3
- ;;
- m88k-dg-dgux5.4R2* | m88k-dg-dgux5.4.2* )
- machine=aviion opsys=dgux5-4r2
- ;;
- m88k-dg-dgux* )
- machine=aviion opsys=dgux
- ;;
-
- ## DECstations
- mips-dec-ultrix[0-3].* | mips-dec-ultrix4.0* | mips-dec-bsd4.2* )
- machine=pmax opsys=bsd4-2
- ;;
- mips-dec-ultrix4.[12]* | mips-dec-bsd* )
- machine=pmax opsys=bsd4-3
- ;;
- mips-dec-ultrix* )
- machine=pmax opsys=ultrix4-3
- ;;
- mips-dec-osf* )
- machine=pmax opsys=osf1
- ;;
- mips-dec-mach_bsd4.3* )
- machine=pmax opsys=mach-bsd4-3
- ;;
-
- ## Motorola Delta machines
- m68k-motorola-sysv* | m68000-motorola-sysv* )
- machine=delta opsys=usg5-3
- if test -z "`type gnucc | grep 'not found'`"
- then
- if test -s /etc/167config
- then CC="gnucc -m68040"
- else CC="gnucc -m68881"
- fi
- else
- if test -z "`type gcc | grep 'not found'`"
- then CC=gcc
- else CC=cc
- fi
- fi
- ;;
- m88k-motorola-sysv4* )
- # jbotte@bnr.ca says that UNIX_System_V <hostName> 4.0 R40V4.3 m88k mc88110
- # needs POSIX_SIGNALS and therefore needs usg5-4-2.
- # I hope there are not other 4.0 versions for this machine
- # which really need usg5-4 instead.
- machine=delta88k opsys=usg5-4-2
- ;;
- m88k-motorola-sysv* | m88k-motorola-m88kbcs* )
- machine=delta88k opsys=usg5-3
- ;;
-
- ## Dual machines
- m68*-dual-sysv* )
- machine=dual opsys=usg5-2
- ;;
- m68*-dual-uniplus* )
- machine=dual opsys=unipl5-2
- ;;
-
- ## Elxsi 6400
- elxsi-elxsi-sysv* )
- machine=elxsi opsys=usg5-2
- ;;
-
- ## Encore machines
- ns16k-encore-bsd* )
- machine=ns16000 opsys=umax
- ;;
-
- ## The GEC 93 - apparently, this port isn't really finished yet.
-
- ## Gould Power Node and NP1
- pn-gould-bsd4.2* )
- machine=gould opsys=bsd4-2
- ;;
- pn-gould-bsd4.3* )
- machine=gould opsys=bsd4-3
- ;;
- np1-gould-bsd* )
- machine=gould-np1 opsys=bsd4-3
- ;;
-
- ## Harris Night Hawk machines running CX/UX (a 5000 looks just like a 4000
- ## as far as Emacs is concerned).
- m88k-harris-cxux* )
- # Build needs to be different on 7.0 and later releases
- case "`uname -r`" in
- [56].[0-9] ) machine=nh4000 opsys=cxux ;;
- [7].[0-9] ) machine=nh4000 opsys=cxux7 ;;
- esac
- NON_GNU_CPP="/lib/cpp"
- ;;
- ## Harris ecx or gcx running CX/UX (Series 1200, Series 3000)
- m68k-harris-cxux* )
- machine=nh3000 opsys=cxux
- ;;
- ## Harris power pc NightHawk running Power UNIX (Series 6000)
- powerpc-harris-powerunix )
- machine=nh6000 opsys=powerunix
- NON_GNU_CPP="cc -Xo -E -P"
- ;;
- ## SR2001/SR2201 running HI-UX/MPP
- hppa1.1-hitachi-hiuxmpp* )
- machine=sr2k opsys=hiuxmpp
- ;;
- ## Honeywell XPS100
- xps*-honeywell-sysv* )
- machine=xps100 opsys=usg5-2
- ;;
-
- ## HP 9000 series 200 or 300
- m68*-hp-bsd* )
- machine=hp9000s300 opsys=bsd4-3
- ;;
- ## HP/UX 7, 8, 9, and 10 are supported on these machines.
- m68*-hp-hpux* )
- case "`uname -r`" in
- ## Someone's system reports A.B8.05 for this.
- ## I wonder what other possibilities there are.
- *.B8.* ) machine=hp9000s300 opsys=hpux8 ;;
- *.08.* ) machine=hp9000s300 opsys=hpux8 ;;
- *.09.* ) machine=hp9000s300 opsys=hpux9 ;;
- *.10.* ) machine=hp9000s300 opsys=hpux9shr ;;
- *) machine=hp9000s300 opsys=hpux ;;
- esac
- ;;
-
- ## HP 9000 series 700 and 800, running HP/UX
- hppa*-hp-hpux7* )
- machine=hp800 opsys=hpux
- ;;
- hppa*-hp-hpux8* )
- machine=hp800 opsys=hpux8
- ;;
- hppa*-hp-hpux9shr* )
- machine=hp800 opsys=hpux9shr
- ;;
- hppa*-hp-hpux9* )
- machine=hp800 opsys=hpux9
- ;;
- hppa*-hp-hpux10* )
- machine=hp800 opsys=hpux10
- ;;
-
- ## HP 9000 series 700 and 800, running HP/UX
- hppa*-hp-hpux* )
- ## Cross-compilation? Nah!
- case "`uname -r`" in
- ## Someone's system reports A.B8.05 for this.
- ## I wonder what other possibilities there are.
- *.B8.* ) machine=hp800 opsys=hpux8 ;;
- *.08.* ) machine=hp800 opsys=hpux8 ;;
- *.09.* ) machine=hp800 opsys=hpux9 ;;
- *) machine=hp800 opsys=hpux ;;
- esac
- ;;
- hppa*-*-nextstep* )
- machine=hp800 opsys=nextstep
- ;;
-
- ## Orion machines
- orion-orion-bsd* )
- machine=orion opsys=bsd4-2
- ;;
- clipper-orion-bsd* )
- machine=orion105 opsys=bsd4-2
- ;;
-
- ## IBM machines
- i[3456]86-ibm-aix1.1* )
- machine=ibmps2-aix opsys=usg5-2-2
- ;;
- i[3456]86-ibm-aix1.[23]* | i[3456]86-ibm-aix* )
- machine=ibmps2-aix opsys=usg5-3
- ;;
- i370-ibm-aix*)
- machine=ibm370aix opsys=usg5-3
- ;;
- rs6000-ibm-aix3.1* | powerpc-ibm-aix3.1* )
- machine=ibmrs6000 opsys=aix3-1
- ;;
- rs6000-ibm-aix3.2.5 | powerpc-ibm-aix3.2.5 )
- machine=ibmrs6000 opsys=aix3-2-5
- ;;
- rs6000-ibm-aix4.1* | powerpc-ibm-aix4.1* )
- machine=ibmrs6000 opsys=aix4-1
- ;;
- rs6000-ibm-aix4.2* | powerpc-ibm-aix4.2* )
- machine=ibmrs6000 opsys=aix4-2
- ;;
- rs6000-ibm-aix4.0* | powerpc-ibm-aix4.0* )
- machine=ibmrs6000 opsys=aix4
- ;;
- rs6000-ibm-aix4* | powerpc-ibm-aix4* )
- machine=ibmrs6000 opsys=aix4-1
- ;;
- rs6000-ibm-aix* | powerpc-ibm-aix* )
- machine=ibmrs6000 opsys=aix3-2
- ;;
- romp-ibm-bsd4.3* )
- machine=ibmrt opsys=bsd4-3
- ;;
- romp-ibm-bsd4.2* )
- machine=ibmrt opsys=bsd4-2
- ;;
- romp-ibm-aos4.3* )
- machine=ibmrt opsys=bsd4-3
- ;;
- romp-ibm-aos4.2* )
- machine=ibmrt opsys=bsd4-2
- ;;
- romp-ibm-aos* )
- machine=ibmrt opsys=bsd4-3
- ;;
- romp-ibm-bsd* )
- machine=ibmrt opsys=bsd4-3
- ;;
- romp-ibm-aix* )
- machine=ibmrt-aix opsys=usg5-2-2
- ;;
-
- ## Integrated Solutions `Optimum V'
- m68*-isi-bsd4.2* )
- machine=isi-ov opsys=bsd4-2
- ;;
- m68*-isi-bsd4.3* )
- machine=isi-ov opsys=bsd4-3
- ;;
-
- ## Intel 386 machines where we do care about the manufacturer
- i[3456]86-intsys-sysv* )
- machine=is386 opsys=usg5-2-2
- ;;
-
- ## Prime EXL
- i[3456]86-prime-sysv* )
- machine=i386 opsys=usg5-3
- ;;
-
- ## Sequent Symmetry running Dynix
- i[3456]86-sequent-bsd* )
- machine=symmetry opsys=bsd4-3
- ;;
-
- ## Sequent Symmetry running ptx 4, which is a modified SVR4.
- i[3456]86-sequent-ptx4* | i[3456]86-sequent-sysv4* )
- machine=sequent-ptx opsys=ptx4
- NON_GNU_CPP=/lib/cpp
- ;;
-
- ## Sequent Symmetry running DYNIX/ptx
- ## Use the old cpp rather than the newer ANSI one.
- i[3456]86-sequent-ptx* )
- machine=sequent-ptx opsys=ptx
- NON_GNU_CPP="/lib/cpp"
- ;;
-
- ## ncr machine running svr4.3.
- i[3456]86-ncr-sysv4.3 )
- machine=ncr386 opsys=usg5-4-3
- ;;
-
- ## Unspecified sysv on an ncr machine defaults to svr4.2.
- ## (Plain usg5-4 doesn't turn on POSIX signals, which we need.)
- i[3456]86-ncr-sysv* )
- machine=ncr386 opsys=usg5-4-2
- ;;
-
- ## Intel Paragon OSF/1
- i860-intel-osf1* )
- machine=paragon opsys=osf1 NON_GNU_CPP=/usr/mach/lib/cpp
- ;;
-
- ## Intel 860
- i860-*-sysv4* )
- machine=i860 opsys=usg5-4
- NON_GNU_CC="/bin/cc" # Ie, not the one in /usr/ucb/cc.
- NON_GNU_CPP="/usr/ccs/lib/cpp" # cc -E tokenizes macro expansion.
- ;;
-
- ## Masscomp machines
- m68*-masscomp-rtu* )
- machine=masscomp opsys=rtu
- ;;
-
- ## Megatest machines
- m68*-megatest-bsd* )
- machine=mega68 opsys=bsd4-2
- ;;
-
- ## Workstations sold by MIPS
- ## This is not necessarily all workstations using the MIPS processor -
- ## Irises are produced by SGI, and DECstations by DEC.
-
- ## etc/MACHINES lists mips.h and mips4.h as possible machine files,
- ## and usg5-2-2 and bsd4-3 as possible OS files. The only guidance
- ## it gives for choosing between the alternatives seems to be "Use
- ## -machine=mips4 for RISCOS version 4; use -opsystem=bsd4-3 with
- ## the BSD world." I'll assume that these are instructions for
- ## handling two odd situations, and that every other situation
- ## should use mips.h and usg5-2-2, they being listed first.
- mips-mips-usg* )
- machine=mips4
- ## Fall through to the general code at the bottom to decide on the OS.
- ;;
- mips-mips-riscos4* )
- machine=mips4 opsys=bsd4-3
- NON_GNU_CC="cc -systype bsd43"
- NON_GNU_CPP="cc -systype bsd43 -E"
- ;;
- mips-mips-riscos5* )
- machine=mips4 opsys=riscos5
- NON_GNU_CC="cc -systype bsd43"
- NON_GNU_CPP="cc -systype bsd43 -E"
- ;;
- mips-mips-bsd* )
- machine=mips opsys=bsd4-3
- ;;
- mips-mips-* )
- machine=mips opsys=usg5-2-2
- ;;
-
- ## NeXT
- m68*-next-* | m68k-*-nextstep* )
- machine=m68k opsys=nextstep
- ;;
-
- ## The complete machine from National Semiconductor
- ns32k-ns-genix* )
- machine=ns32000 opsys=usg5-2
- ;;
-
- ## NCR machines
- m68*-ncr-sysv2* | m68*-ncr-sysvr2* )
- machine=tower32 opsys=usg5-2-2
- ;;
- m68*-ncr-sysv3* | m68*-ncr-sysvr3* )
- machine=tower32v3 opsys=usg5-3
- ;;
-
- ## Nixdorf Targon 31
- m68*-nixdorf-sysv* )
- machine=targon31 opsys=usg5-2-2
- ;;
-
- ## Nu (TI or LMI)
- m68*-nu-sysv* )
- machine=nu opsys=usg5-2
- ;;
-
- ## Plexus
- m68*-plexus-sysv* )
- machine=plexus opsys=usg5-2
- ;;
-
- ## Pyramid machines
- ## I don't really have any idea what sort of processor the Pyramid has,
- ## so I'm assuming it is its own architecture.
- pyramid-pyramid-bsd* )
- machine=pyramid opsys=bsd4-2
- ;;
-
- ## Sequent Balance
- ns32k-sequent-bsd4.2* )
- machine=sequent opsys=bsd4-2
- ;;
- ns32k-sequent-bsd4.3* )
- machine=sequent opsys=bsd4-3
- ;;
-
- ## Siemens Nixdorf
- mips-siemens-sysv* | mips-sni-sysv*)
- machine=mips-siemens opsys=usg5-4
- NON_GNU_CC=/usr/ccs/bin/cc
- NON_GNU_CPP=/usr/ccs/lib/cpp
- ;;
-
- ## Silicon Graphics machines
- ## Iris 2500 and Iris 2500 Turbo (aka the Iris 3030)
- m68*-sgi-iris3.5* )
- machine=irist opsys=iris3-5
- ;;
- m68*-sgi-iris3.6* | m68*-sgi-iris*)
- machine=irist opsys=iris3-6
- ;;
- ## Iris 4D
- mips-sgi-irix3* )
- machine=iris4d opsys=irix3-3
- ;;
- mips-sgi-irix4* )
- machine=iris4d opsys=irix4-0
- ;;
- mips-sgi-irix6* )
- machine=iris4d opsys=irix6-0
- NON_GNU_CPP=/lib/cpp
- NON_GCC_TEST_OPTIONS=-32
- ;;
- mips-sgi-irix5.[01]* )
- machine=iris4d opsys=irix5-0
- ;;
- mips-sgi-irix5* | mips-sgi-irix* )
- machine=iris4d opsys=irix5-2
- ;;
-
- ## SONY machines
- m68*-sony-bsd4.2* )
- machine=news opsys=bsd4-2
- ;;
- m68*-sony-bsd4.3* )
- machine=news opsys=bsd4-3
- ;;
- m68*-sony-newsos3* | m68*-sony-news3*)
- machine=news opsys=bsd4-3
- ;;
- mips-sony-bsd* | mips-sony-newsos4* | mips-sony-news4*)
- machine=news-risc opsys=bsd4-3
- ;;
- mips-sony-news* )
- machine=news-risc opsys=newsos5
- ;;
-
- ## Stride
- m68*-stride-sysv* )
- machine=stride opsys=usg5-2
- ;;
-
- ## Suns
- sparc-*-linux-gnu* )
- machine=sparc opsys=gnu-linux
- ;;
-
- *-sun-sunos* | *-sun-bsd* | *-sun-solaris* \
- | i[3456]86-*-solaris2* | i[3456]86-*-sunos5* | powerpc*-*-solaris2* \
- | rs6000-*-solaris2*)
- case "${canonical}" in
- m68*-sunos1* ) machine=sun1 ;;
- m68*-sunos2* ) machine=sun2 ;;
- m68* ) machine=sun3 ;;
- i[3456]86-sun-sunos[34]* ) machine=sun386 ;;
- i[3456]86-*-* ) machine=intel386 ;;
- powerpc* | rs6000* ) machine=ibmrs6000 ;;
- sparc* ) machine=sparc ;;
- * ) unported=yes ;;
- esac
- case "${canonical}" in
- ## The Sun386 didn't get past 4.0.
- i[3456]86-*-sunos4 ) opsys=sunos4-0 ;;
- *-sunos4.0* ) opsys=sunos4-0 ;;
- *-sunos4.1.[3-9]*noshare )
- ## This name is sunos413 instead of sunos4-1-3
- ## to avoid a file name conflict on MSDOS.
- opsys=sunos413
- NON_GNU_CPP=/usr/lib/cpp
- NON_GCC_TEST_OPTIONS=-Bstatic
- GCC_TEST_OPTIONS=-static
- ;;
- *-sunos4.1.[3-9]* | *-sunos4shr*)
- opsys=sunos4shr
- NON_GNU_CPP=/usr/lib/cpp
- ;;
- *-sunos4* | *-sunos )
- opsys=sunos4-1
- NON_GCC_TEST_OPTIONS=-Bstatic
- GCC_TEST_OPTIONS=-static
- ;;
- *-sunos5.3* | *-solaris2.3* )
- opsys=sol2-3
- NON_GNU_CPP=/usr/ccs/lib/cpp
- ;;
- *-sunos5.4* | *-solaris2.4* )
- opsys=sol2-4
- NON_GNU_CPP=/usr/ccs/lib/cpp
- RANLIB="ar -ts"
- ;;
- *-sunos5.5* | *-solaris2.5* )
- opsys=sol2-5
- NON_GNU_CPP=/usr/ccs/lib/cpp
- RANLIB="ar -ts"
- ;;
- *-sunos5* | *-solaris* )
- opsys=sol2-4
- NON_GNU_CPP=/usr/ccs/lib/cpp
- ;;
- * ) opsys=bsd4-2 ;;
- esac
- ## Watch out for a compiler that we know will not work.
- case "${canonical}" in
- *-solaris* | *-sunos5* )
- if [ "x$CC" = x/usr/ucb/cc ]; then
- ## /usr/ucb/cc doesn't work;
- ## we should find some other compiler that does work.
- unset CC
- fi
- ;;
- *) ;;
- esac
- ;;
- sparc-*-nextstep* )
- machine=sparc opsys=nextstep
- ;;
-
- ## Tadpole 68k
- m68*-tadpole-sysv* )
- machine=tad68k opsys=usg5-3
- ;;
-
- ## Tahoe machines
- tahoe-tahoe-bsd4.2* )
- machine=tahoe opsys=bsd4-2
- ;;
- tahoe-tahoe-bsd4.3* )
- machine=tahoe opsys=bsd4-3
- ;;
-
- ## Tandem Integrity S2
- mips-tandem-sysv* )
- machine=tandem-s2 opsys=usg5-3
- ;;
-
- ## Tektronix XD88
- m88k-tektronix-sysv3* )
- machine=tekxd88 opsys=usg5-3
- ;;
-
- ## Tektronix 16000 box (6130?)
- ns16k-tektronix-bsd* )
- machine=ns16000 opsys=bsd4-2
- ;;
- ## Tektronix 4300
- ## src/m/tek4300.h hints that this is a m68k machine.
- m68*-tektronix-bsd* )
- machine=tek4300 opsys=bsd4-3
- ;;
-
- ## Titan P2 or P3
- ## We seem to have lost the machine-description file titan.h!
- titan-titan-sysv* )
- machine=titan opsys=usg5-3
- ;;
-
- ## Ustation E30 (SS5E)
- m68*-unisys-uniplus* )
- machine=ustation opsystem=unipl5-2
- ;;
-
- ## Vaxen.
- vax-dec-* )
- machine=vax
- case "${canonical}" in
- *-bsd4.1* ) opsys=bsd4-1 ;;
- *-bsd4.2* | *-ultrix[0-3].* | *-ultrix4.0* ) opsys=bsd4-2 ;;
- *-bsd4.3* | *-ultrix* ) opsys=bsd4-3 ;;
- *-sysv[01]* | *-sysvr[01]* ) opsys=usg5-0 ;;
- *-sysv2* | *-sysvr2* ) opsys=usg5-2 ;;
- *-vms* ) opsys=vms ;;
- * ) unported=yes
- esac
- ;;
-
- ## Whitechapel MG1
- ns16k-whitechapel-* )
- machine=mg1
- ## We don't know what sort of OS runs on these; we'll let the
- ## operating system guessing code below try.
- ;;
-
- ## Wicat
- m68*-wicat-sysv* )
- machine=wicat opsys=usg5-2
- ;;
-
- ## Intel 386 machines where we don't care about the manufacturer
- i[3456]86-*-* )
- machine=intel386
- case "${canonical}" in
- *-isc1.* | *-isc2.[01]* ) opsys=386-ix ;;
- *-isc2.2* ) opsys=isc2-2 ;;
- *-isc4.0* ) opsys=isc4-0 ;;
- *-isc4.* ) opsys=isc4-1
- GCC_TEST_OPTIONS=-posix
- NON_GCC_TEST_OPTIONS=-Xp
- ;;
- *-isc* ) opsys=isc3-0 ;;
- *-esix5* ) opsys=esix5r4; NON_GNU_CPP=/usr/lib/cpp ;;
- *-esix* ) opsys=esix ;;
- *-xenix* ) opsys=xenix ;;
- *-linux-gnu* ) opsys=gnu-linux ;;
- *-sco3.2v4* ) opsys=sco4 ; NON_GNU_CPP=/lib/cpp ;;
- *-sco3.2v5* ) opsys=sco5
- NON_GNU_CPP=/lib/cpp
- # Prevent -belf from being passed to $CPP.
- # /lib/cpp does not accept it.
- OVERRIDE_CPPFLAGS=" "
- ;;
- *-bsd386* | *-bsdi1* ) opsys=bsd386 ;;
- *-bsdi2.0* ) opsys=bsdos2 ;;
- *-bsdi2* ) opsys=bsdos2-1 ;;
- *-386bsd* ) opsys=386bsd ;;
- *-freebsd* ) opsys=freebsd ;;
- *-nextstep* ) opsys=nextstep ;;
- ## Otherwise, we'll fall through to the generic opsys code at the bottom.
- esac
- ;;
-
- ## Linux/68k-based GNU system
- m68k-*-linux-gnu* )
- machine=m68k opsys=gnu-linux
- ;;
-
- * )
- unported=yes
- ;;
-esac
-
-### If the code above didn't choose an operating system, just choose
-### an operating system based on the configuration name. You really
-### only want to use this when you have no idea what the right
-### operating system is; if you know what operating systems a machine
-### runs, it's cleaner to make it explicit in the case statement
-### above.
-if test x"${opsys}" = x; then
- case "${canonical}" in
- *-gnu* ) opsys=gnu ;;
- *-bsd4.[01] ) opsys=bsd4-1 ;;
- *-bsd4.2 ) opsys=bsd4-2 ;;
- *-bsd4.3 ) opsys=bsd4-3 ;;
- *-sysv0 | *-sysvr0 ) opsys=usg5-0 ;;
- *-sysv2 | *-sysvr2 ) opsys=usg5-2 ;;
- *-sysv2.2 | *-sysvr2.2 ) opsys=usg5-2-2 ;;
- *-sysv3* | *-sysvr3* ) opsys=usg5-3 ;;
- *-sysv4.1* | *-sysvr4.1* )
- NON_GNU_CPP=/usr/lib/cpp
- opsys=usg5-4 ;;
- *-sysv4.[2-9]* | *-sysvr4.[2-9]* )
- if [ x$NON_GNU_CPP = x ]; then
- if [ -f /usr/ccs/lib/cpp ]; then
- NON_GNU_CPP=/usr/ccs/lib/cpp
- else
- NON_GNU_CPP=/lib/cpp
- fi
- fi
- opsys=usg5-4-2 ;;
- *-sysv4* | *-sysvr4* ) opsys=usg5-4 ;;
- * )
- unported=yes
- ;;
- esac
-fi
-
-if test "x$RANLIB" = x; then
- RANLIB=ranlib
-fi
-
-changequote([, ])dnl
-
-if test $unported = yes; then
- AC_MSG_ERROR([Emacs hasn't been ported to \`${canonical}' systems.
-Check \`etc/MACHINES' for recognized configuration names.])
-fi
-
-machfile="m/${machine}.h"
-opsysfile="s/${opsys}.h"
-
-
-#### Choose a compiler.
-test -n "$CC" && cc_specified=yes
-
-# Save the value of CFLAGS that the user specified.
-SPECIFIED_CFLAGS="$CFLAGS"
-
-case ${with_gcc} in
- "yes" ) CC="gcc" GCC=yes ;;
- "no" ) : ${CC=cc} ;;
- * ) AC_PROG_CC
-esac
-
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-
-#### Some systems specify a CPP to use unless we are using GCC.
-#### Now that we know whether we are using GCC, we can decide whether
-#### to use that one.
-if test "x$NON_GNU_CPP" != x && test x$GCC != xyes && test "x$CPP" = x
-then
- CPP="$NON_GNU_CPP"
-fi
-
-#### Some systems specify a CC to use unless we are using GCC.
-#### Now that we know whether we are using GCC, we can decide whether
-#### to use that one.
-if test "x$NON_GNU_CC" != x && test x$GCC != xyes &&
- test x$cc_specified != xyes
-then
- CC="$NON_GNU_CC"
-fi
-
-if test x$GCC = xyes && test "x$GCC_TEST_OPTIONS" != x
-then
- CC="$CC $GCC_TEST_OPTIONS"
-fi
-
-if test x$GCC = x && test "x$NON_GCC_TEST_OPTIONS" != x
-then
- CC="$CC $NON_GCC_TEST_OPTIONS"
-fi
-
-if test x$GCC = xyes && test "x$GCC_LINK_TEST_OPTIONS" != x
-then
- ac_link="$ac_link $GCC_LINK_TEST_OPTIONS"
-fi
-
-if test x$GCC = x && test "x$NON_GCC_LINK_TEST_OPTIONS" != x
-then
- ac_link="$ac_link $NON_GCC_LINK_TEST_OPTIONS"
-fi
-
-#### Some other nice autoconf tests. If you add a test here which
-#### should make an entry in src/config.h, don't forget to add an
-#### #undef clause to src/config.h.in for autoconf to modify.
-
-dnl checks for programs
-AC_PROG_LN_S
-AC_PROG_CPP
-AC_PROG_INSTALL
-AC_PROG_YACC
-
-dnl checks for Unix variants
-AC_AIX
-
-dnl checks for header files
-AC_CHECK_HEADERS(sys/select.h sys/timeb.h sys/time.h unistd.h utime.h linux/version.h sys/systeminfo.h termios.h limits.h)
-AC_HEADER_STDC
-AC_HEADER_TIME
-AC_DECL_SYS_SIGLIST
-
-dnl Some systems have utime.h but don't declare the struct anyplace.
-AC_MSG_CHECKING(for struct utimbuf)
-AC_TRY_COMPILE([#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif], [static struct utimbuf x; x.actime = x.modtime;],
- [AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_STRUCT_UTIMBUF)],
- AC_MSG_RESULT(no))
-
-dnl checks for typedefs
-AC_TYPE_SIGNAL
-
-AC_MSG_CHECKING(for struct timeval)
-AC_TRY_COMPILE([#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif], [static struct timeval x; x.tv_sec = x.tv_usec;],
- [AC_MSG_RESULT(yes)
- HAVE_TIMEVAL=yes
- AC_DEFINE(HAVE_TIMEVAL)],
- [AC_MSG_RESULT(no)
- HAVE_TIMEVAL=no])
-
-dnl checks for structure members
-AC_STRUCT_TM
-AC_STRUCT_TIMEZONE
-
-dnl checks for compiler characteristics
-AC_C_CONST
-
-dnl check for Make feature
-AC_PROG_MAKE_SET
-
-dnl checks for operating system services
-AC_SYS_LONG_FILE_NAMES
-
-#### Choose a window system.
-
-AC_PATH_X
-if test "$no_x" = yes; then
- window_system=none
-else
- window_system=x11
-fi
-
-if test "${x_libraries}" != NONE && test -n "${x_libraries}"; then
- LD_SWITCH_X_SITE=-L`echo ${x_libraries} | sed -e "s/:/ -L/g"`
- LD_SWITCH_X_SITE_AUX=-R`echo ${x_libraries} | sed -e "s/:/ -R/g"`
-fi
-if test "${x_includes}" != NONE && test -n "${x_includes}"; then
- C_SWITCH_X_SITE=-I`echo ${x_includes} | sed -e "s/:/ -I/g"`
-fi
-
-if test x"${x_includes}" = x; then
- bitmapdir=/usr/include/X11/bitmaps
-else
- # accumulate include directories that have X11 bitmap subdirectories
- bmd_acc="dummyval"
- for bmd in `echo ${x_includes} | sed -e "s/:/ /g"`; do
- if test -d "${bmd}/X11/bitmaps"; then
- bmd_acc="${bmd_acc}:${bmd}/X11/bitmaps"
- elif test -d "${bmd}/bitmaps"; then
- bmd_acc="${bmd_acc}:${bmd}/bitmaps"
- fi
- done
- if test ${bmd_acc} != "dummyval"; then
- bitmapdir=`echo ${bmd_acc} | sed -e "s/^dummyval://"`
- fi
-fi
-
-case "${window_system}" in
- x11 )
- HAVE_X_WINDOWS=yes
- HAVE_X11=yes
- case "${with_x_toolkit}" in
- athena | lucid ) USE_X_TOOLKIT=LUCID ;;
- motif ) USE_X_TOOLKIT=MOTIF ;;
-dnl open-look ) USE_X_TOOLKIT=OPEN_LOOK ;;
- no ) USE_X_TOOLKIT=none ;;
-dnl If user did not say whether to use a toolkit,
-dnl make this decision later: use the toolkit if we have X11R5 or newer.
- * ) USE_X_TOOLKIT=maybe ;;
- esac
- ;;
- none )
- HAVE_X_WINDOWS=no
- HAVE_X11=no
- USE_X_TOOLKIT=none
- ;;
-esac
-
-### If we're using X11, we should use the X menu package.
-HAVE_MENUS=no
-case ${HAVE_X11} in
- yes ) HAVE_MENUS=yes ;;
-esac
-
-if test "${opsys}" = "hpux9"; then
- case "${x_libraries}" in
- *X11R4* )
- opsysfile="s/hpux9-x11r4.h"
- ;;
- esac
-fi
-
-if test "${opsys}" = "hpux9shr"; then
- case "${x_libraries}" in
- *X11R4* )
- opsysfile="s/hpux9shxr4.h"
- ;;
- esac
-fi
-
-#### Extract some information from the operating system and machine files.
-
-AC_CHECKING([the machine- and system-dependent files to find out
- - which libraries the lib-src programs will want, and
- - whether the GNU malloc routines are usable])
-
-### First figure out CFLAGS (which we use for running the compiler here)
-### and REAL_CFLAGS (which we use for real compilation).
-### The two are the same except on a few systems, where they are made
-### different to work around various lossages. For example,
-### GCC 2.5 on GNU/Linux needs them to be different because it treats -g
-### as implying static linking.
-
-### If the CFLAGS env var is specified, we use that value
-### instead of the default.
-
-### It's not important that this name contain the PID; you can't run
-### two configures in the same directory and have anything work
-### anyway.
-tempcname="conftest.c"
-
-echo '
-#include "'${srcdir}'/src/'${opsysfile}'"
-#include "'${srcdir}'/src/'${machfile}'"
-#ifndef LIBS_MACHINE
-#define LIBS_MACHINE
-#endif
-#ifndef LIBS_SYSTEM
-#define LIBS_SYSTEM
-#endif
-#ifndef C_SWITCH_SYSTEM
-#define C_SWITCH_SYSTEM
-#endif
-#ifndef C_SWITCH_MACHINE
-#define C_SWITCH_MACHINE
-#endif
-configure___ libsrc_libs=LIBS_MACHINE LIBS_SYSTEM
-configure___ c_switch_system=C_SWITCH_SYSTEM
-configure___ c_switch_machine=C_SWITCH_MACHINE
-
-#ifndef LIB_X11_LIB
-#define LIB_X11_LIB -lX11
-#endif
-
-#ifndef LIBX11_MACHINE
-#define LIBX11_MACHINE
-#endif
-
-#ifndef LIBX11_SYSTEM
-#define LIBX11_SYSTEM
-#endif
-configure___ LIBX=LIB_X11_LIB LIBX11_MACHINE LIBX11_SYSTEM
-
-#ifdef UNEXEC
-configure___ unexec=UNEXEC
-#else
-configure___ unexec=unexec.o
-#endif
-
-#ifdef SYSTEM_MALLOC
-configure___ system_malloc=yes
-#else
-configure___ system_malloc=no
-#endif
-
-#ifndef C_DEBUG_SWITCH
-#define C_DEBUG_SWITCH -g
-#endif
-
-#ifndef C_OPTIMIZE_SWITCH
-#define C_OPTIMIZE_SWITCH -O
-#endif
-
-#ifndef LD_SWITCH_MACHINE
-#define LD_SWITCH_MACHINE
-#endif
-
-#ifndef LD_SWITCH_SYSTEM
-#define LD_SWITCH_SYSTEM
-#endif
-
-#ifndef LD_SWITCH_X_SITE_AUX
-#define LD_SWITCH_X_SITE_AUX
-#endif
-
-configure___ ld_switch_system=LD_SWITCH_SYSTEM
-configure___ ld_switch_machine=LD_SWITCH_MACHINE
-
-#ifdef THIS_IS_CONFIGURE
-
-/* Get the CFLAGS for tests in configure. */
-#ifdef __GNUC__
-configure___ CFLAGS=C_DEBUG_SWITCH C_OPTIMIZE_SWITCH '${SPECIFIED_CFLAGS}'
-#else
-configure___ CFLAGS=C_DEBUG_SWITCH '${SPECIFIED_CFLAGS}'
-#endif
-
-#else /* not THIS_IS_CONFIGURE */
-
-/* Get the CFLAGS for real compilation. */
-#ifdef __GNUC__
-configure___ REAL_CFLAGS=C_DEBUG_SWITCH C_OPTIMIZE_SWITCH '${SPECIFIED_CFLAGS}'
-#else
-configure___ REAL_CFLAGS=C_DEBUG_SWITCH '${SPECIFIED_CFLAGS}'
-#endif
-
-#endif /* not THIS_IS_CONFIGURE */
-' > ${tempcname}
-
-# The value of CPP is a quoted variable reference, so we need to do this
-# to get its actual value...
-CPP=`eval "echo $CPP"`
-changequote(, )dnl
-eval `${CPP} -Isrc ${tempcname} \
- | sed -n -e 's/^configure___ \([^=]*=\)\(.*\)$/\1"\2"/p'`
-if test "x$SPECIFIED_CFLAGS" = x; then
- eval `${CPP} -Isrc -DTHIS_IS_CONFIGURE ${tempcname} \
- | sed -n -e 's/^configure___ \([^=]*=\)\(.*\)$/\1"\2"/p'`
-else
- REAL_CFLAGS="$CFLAGS"
-fi
-changequote([, ])dnl
-rm ${tempcname}
-
-ac_link="$ac_link $ld_switch_machine $ld_switch_system"
-
-### Compute the unexec source name from the object name.
-UNEXEC_SRC="`echo ${unexec} | sed 's/\.o/.c/'`"
-
-# Do the opsystem or machine files prohibit the use of the GNU malloc?
-# Assume not, until told otherwise.
-GNU_MALLOC=yes
-if test "${system_malloc}" = "yes"; then
- GNU_MALLOC=no
- GNU_MALLOC_reason="
- (The GNU allocators don't work with this system configuration.)"
-fi
-
-if test x"${REL_ALLOC}" = x; then
- REL_ALLOC=${GNU_MALLOC}
-fi
-
-LISP_FLOAT_TYPE=yes
-
-
-#### Add the libraries to LIBS and check for some functions.
-
-if test x"${OVERRIDE_CPPFLAGS}" != x; then
- CPPFLAGS="${OVERRIDE_CPPFLAGS}"
-else
- CPPFLAGS="$c_switch_system $c_switch_machine $CPPFLAGS"
-fi
-
-LIBS="$libsrc_libs $LIBS"
-
-dnl If found, this defines HAVE_LIBDNET, which m/pmax.h checks,
-dnl and also adds -ldnet to LIBS, which Autoconf uses for checks.
-AC_CHECK_LIB(dnet, dnet_ntoa)
-dnl This causes -lresolv to get used in subsequent tests,
-dnl which causes failures on some systems such as HPUX 9.
-dnl AC_CHECK_LIB(resolv, gethostbyname)
-
-dnl FIXME replace main with a function we actually want from this library.
-AC_CHECK_LIB(Xbsd, main, LD_SWITCH_X_SITE="$LD_SWITCH_X_SITE -lXbsd")
-
-AC_CHECK_LIB(pthreads, cma_open)
-
-AC_MSG_CHECKING(for XFree86)
-if test -d /usr/X386/include; then
- HAVE_XFREE386=yes
- : ${C_SWITCH_X_SITE="-I/usr/X386/include"}
-else
- HAVE_XFREE386=no
-fi
-AC_MSG_RESULT($HAVE_XFREE386)
-
-# Change CFLAGS temporarily so that C_SWITCH_X_SITE gets used
-# for the tests that follow. We set it back to REAL_CFLAGS later on.
-
-if test "${HAVE_X11}" = "yes"; then
- DEFS="$C_SWITCH_X_SITE $DEFS"
- LDFLAGS="$LDFLAGS $LD_SWITCH_X_SITE"
- LIBS="$LIBX $LIBS"
- CFLAGS="$C_SWITCH_X_SITE $CFLAGS"
-
- # On Solaris, arrange for LD_RUN_PATH to point to the X libraries for tests.
- # This is handled by LD_SWITCH_X_SITE_AUX during the real build,
- # but it's more convenient here to set LD_RUN_PATH
- # since this also works on hosts that don't understand LD_SWITCH_X_SITE_AUX.
- if test "${x_libraries}" != NONE && test -n "${x_libraries}"; then
- LD_RUN_PATH=$x_libraries${LD_RUN_PATH+:}$LD_RUN_PATH
- export LD_RUN_PATH
- fi
-
- if test "${opsys}" = "gnu-linux"; then
- AC_MSG_CHECKING(whether X on GNU/Linux needs -b to link)
- AC_TRY_LINK([],
- [XOpenDisplay ("foo");],
- [xlinux_first_failure=no],
- [xlinux_first_failure=yes])
- if test "${xlinux_first_failure}" = "yes"; then
- OLD_LD_SWITCH_X_SITE="$LD_SWITCH_X_SITE"
- OLD_C_SWITCH_X_SITE="$C_SWITCH_X_SITE"
- OLD_CPPFLAGS="$CPPFLAGS"
- OLD_LIBS="$LIBS"
- LD_SWITCH_X_SITE="$LD_SWITCH_X_SITE -b i486-linuxaout"
- C_SWITCH_X_SITE="$C_SWITCH_X_SITE -b i486-linuxaout"
- CPPFLAGS="$CPPFLAGS -b i486-linuxaout"
- LIBS="$LIBS -b i486-linuxaout"
- AC_TRY_LINK([],
- [XOpenDisplay ("foo");],
- [xlinux_second_failure=no],
- [xlinux_second_failure=yes])
- if test "${xlinux_second_failure}" = "yes"; then
- # If we get the same failure with -b, there is no use adding -b.
- # So take it out. This plays safe.
- LD_SWITCH_X_SITE="$OLD_LD_SWITCH_X_SITE"
- C_SWITCH_X_SITE="$OLD_C_SWITCH_X_SITE"
- CPPFLAGS="$OLD_CPPFLAGS"
- LIBS="$OLD_LIBS"
- AC_MSG_RESULT(no)
- else
- AC_MSG_RESULT(yes)
- fi
- else
- AC_MSG_RESULT(no)
- fi
- fi
-
- AC_CHECK_FUNCS(XrmSetDatabase XScreenResourceString \
-XScreenNumberOfScreen XSetWMProtocols)
-fi
-
-if test "${window_system}" = "x11"; then
- AC_MSG_CHECKING(X11 version 6)
- AC_TRY_LINK([#include <X11/Xlib.h>],
-[#if XlibSpecificationRelease < 6
-fail;
-#endif
-], [AC_MSG_RESULT(6 or newer)
- AC_DEFINE(HAVE_X11R6)],
- [AC_MSG_RESULT(before 6)])
-fi
-
-if test "${window_system}" = "x11"; then
- AC_MSG_CHECKING(X11 version 5)
- AC_TRY_LINK([#include <X11/Xlib.h>],
-[#if XlibSpecificationRelease < 5
-fail;
-#endif
-], [AC_MSG_RESULT(5 or newer)
- HAVE_X11R5=yes
- AC_DEFINE(HAVE_X11R5)],
- [
- HAVE_X11R5=no
- AC_MSG_RESULT(before 5)])
-fi
-
-dnl Do not put whitespace before the #include statements below.
-dnl Older compilers (eg sunos4 cc) choke on it.
-if test x"${USE_X_TOOLKIT}" = xmaybe; then
- if test x"${HAVE_X11R5}" = xyes; then
- AC_MSG_CHECKING(X11 version 5 with Xaw)
- AC_TRY_LINK([
-#include <X11/Intrinsic.h>
-#include <X11/Xaw/Simple.h>],
- [],
- [AC_MSG_RESULT(5 or newer, with Xaw; use toolkit by default)
- USE_X_TOOLKIT=LUCID],
- [AC_MSG_RESULT(before 5 or no Xaw; do not use toolkit by default)
- USE_X_TOOLKIT=none])
- else
- USE_X_TOOLKIT=none
- fi
-fi
-
-X_TOOLKIT_TYPE=$USE_X_TOOLKIT
-
-if test "${USE_X_TOOLKIT}" != "none"; then
- AC_MSG_CHECKING(X11 toolkit version)
- AC_TRY_LINK([#include <X11/Intrinsic.h>],
-[#if XtSpecificationRelease < 6
-fail;
-#endif
-], [AC_MSG_RESULT(6 or newer)
- HAVE_X11XTR6=yes
- AC_DEFINE(HAVE_X11XTR6)],
- [AC_MSG_RESULT(before 6)
- HAVE_X11XTR6=no])
-
-dnl If using toolkit, check whether libXmu.a exists.
-dnl tranle@intellicorp.com says libXmu.a can need XtMalloc in libXt.a to link.
- OLDLIBS="$LIBS"
- if test x$HAVE_X11XTR6 = xyes; then
- LIBS="-lXt -lSM -lICE $LIBS"
- else
- LIBS="-lXt $LIBS"
- fi
- AC_CHECK_LIB(Xmu, XmuConvertStandardSelection)
- LIBS="$OLDLIBS"
-fi
-
-# If netdb.h doesn't declare h_errno, we must declare it by hand.
-AC_MSG_CHECKING(whether netdb declares h_errno)
-AC_TRY_LINK([#include <netdb.h>],
- [return h_errno;],
- [AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_H_ERRNO)],
- [AC_MSG_RESULT(no)])
-
-AC_FUNC_ALLOCA
-
-# fmod, logb, and frexp are found in -lm on most systems.
-# On HPUX 9.01, -lm does not contain logb, so check for sqrt.
-AC_CHECK_LIB(m, sqrt)
-
-# Check for mail-locking functions in a "mail" library
-AC_CHECK_LIB(mail, maillock,
- AC_DEFINE(HAVE_LIBMAIL)
- AC_CHECK_FUNCS(touchlock)
- AC_CHECK_HEADERS(maillock.h))
-
-AC_CHECK_FUNCS(gettimeofday gethostname getdomainname dup2 \
-rename closedir mkdir rmdir sysinfo \
-random lrand48 bcopy bcmp logb frexp fmod ftime res_init setsid \
-strerror fpathconf select mktime euidaccess getpagesize tzset setlocale \
-utimes setrlimit setpgid getcwd)
-
-# Check this now, so that we will NOT find the above functions in ncurses.
-# That is because we have not set up to link ncurses in lib-src.
-# It's better to believe a function is not available
-# than to expect to find it in ncurses.
-AC_CHECK_LIB(ncurses, tparm)
-
-# These tell us which Kerberos-related libraries to use.
-if test "${with_kerberos+set}" = set; then
- AC_CHECK_LIB(krb, krb_get_cred)
- AC_CHECK_LIB(des, des_cbc_encrypt)
- AC_CHECK_LIB(com_err, com_err)
-fi
-
-AC_MSG_CHECKING(whether localtime caches TZ)
-AC_CACHE_VAL(emacs_cv_localtime_cache,
-[if test x$ac_cv_func_tzset = xyes; then
-AC_TRY_RUN([#include <time.h>
-#if STDC_HEADERS
-# include <stdlib.h>
-#endif
-extern char **environ;
-unset_TZ ()
-{
- char **from, **to;
- for (to = from = environ; (*to = *from); from++)
- if (! (to[0][0] == 'T' && to[0][1] == 'Z' && to[0][2] == '='))
- to++;
-}
-char TZ_GMT0[] = "TZ=GMT0";
-char TZ_PST8[] = "TZ=PST8";
-main()
-{
- time_t now = time ((time_t *) 0);
- int hour_GMT0, hour_unset;
- if (putenv (TZ_GMT0) != 0)
- exit (1);
- hour_GMT0 = localtime (&now)->tm_hour;
- unset_TZ ();
- hour_unset = localtime (&now)->tm_hour;
- if (putenv (TZ_PST8) != 0)
- exit (1);
- if (localtime (&now)->tm_hour == hour_GMT0)
- exit (1);
- unset_TZ ();
- if (localtime (&now)->tm_hour != hour_unset)
- exit (1);
- exit (0);
-}], emacs_cv_localtime_cache=no, emacs_cv_localtime_cache=yes,
-[# If we have tzset, assume the worst when cross-compiling.
-emacs_cv_localtime_cache=yes])
-else
- # If we lack tzset, report that localtime does not cache TZ,
- # since we can't invalidate the cache if we don't have tzset.
- emacs_cv_localtime_cache=no
-fi])dnl
-AC_MSG_RESULT($emacs_cv_localtime_cache)
-if test $emacs_cv_localtime_cache = yes; then
- AC_DEFINE(LOCALTIME_CACHE)
-fi
-
-if test "x$HAVE_TIMEVAL" = xyes; then
-AC_MSG_CHECKING(whether gettimeofday can't accept two arguments)
-AC_TRY_LINK([
-#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
- ],
- [
- struct timeval time;
- struct timezone dummy;
- gettimeofday (&time, &dummy);
-],
- [AC_MSG_RESULT(no)],
- [AC_MSG_RESULT(yes)
- AC_DEFINE(GETTIMEOFDAY_ONE_ARGUMENT)])
-fi
-
-ok_so_far=yes
-AC_CHECK_FUNC(socket, , ok_so_far=no)
-if test $ok_so_far = yes; then
- AC_CHECK_HEADER(netinet/in.h, , ok_so_far=no)
-fi
-if test $ok_so_far = yes; then
- AC_CHECK_HEADER(arpa/inet.h, , ok_so_far=no)
-fi
-if test $ok_so_far = yes; then
- AC_DEFINE(HAVE_INET_SOCKETS)
-fi
-
-if test -f /usr/lpp/X11/bin/smt.exp; then
- AC_DEFINE(HAVE_AIX_SMT_EXP)
-fi
-
-# Set up the CFLAGS for real compilation, so we can substitute it.
-CFLAGS="$REAL_CFLAGS"
-
-changequote(, )dnl
-#### Find out which version of Emacs this is.
-version=`grep 'defconst[ ]*emacs-version' ${srcdir}/lisp/version.el \
- | sed -e 's/^[^"]*"\([^"]*\)".*$/\1/'`
-changequote([, ])dnl
-if test x"${version}" = x; then
- AC_MSG_ERROR(can't find current emacs version in \`${srcdir}/lisp/version.el'.)
-fi
-
-### Specify what sort of things we'll be editing into Makefile and config.h.
-### Use configuration here uncanonicalized to avoid exceeding size limits.
-AC_SUBST(version)
-AC_SUBST(configuration)
-AC_SUBST(canonical)
-AC_SUBST(srcdir)
-AC_SUBST(prefix)
-AC_SUBST(exec_prefix)
-AC_SUBST(bindir)
-AC_SUBST(datadir)
-AC_SUBST(sharedstatedir)
-AC_SUBST(libexecdir)
-AC_SUBST(mandir)
-AC_SUBST(infodir)
-AC_SUBST(lispdir)
-AC_SUBST(locallisppath)
-AC_SUBST(lisppath)
-AC_SUBST(etcdir)
-AC_SUBST(lockdir)
-AC_SUBST(archlibdir)
-AC_SUBST(docdir)
-AC_SUBST(bitmapdir)
-AC_SUBST(c_switch_system)
-AC_SUBST(c_switch_machine)
-AC_SUBST(LD_SWITCH_X_SITE)
-AC_SUBST(LD_SWITCH_X_SITE_AUX)
-AC_SUBST(C_SWITCH_X_SITE)
-AC_SUBST(CFLAGS)
-AC_SUBST(X_TOOLKIT_TYPE)
-AC_SUBST(machfile)
-AC_SUBST(opsysfile)
-AC_SUBST(RANLIB)
-
-AC_DEFINE_UNQUOTED(EMACS_CONFIGURATION, "${canonical}")
-AC_DEFINE_UNQUOTED(EMACS_CONFIG_OPTIONS, "${ac_configure_args}")
-AC_DEFINE_UNQUOTED(config_machfile, "${machfile}")
-AC_DEFINE_UNQUOTED(config_opsysfile, "${opsysfile}")
-AC_DEFINE_UNQUOTED(LD_SWITCH_X_SITE, ${LD_SWITCH_X_SITE})
-AC_DEFINE_UNQUOTED(LD_SWITCH_X_SITE_AUX, ${LD_SWITCH_X_SITE_AUX})
-AC_DEFINE_UNQUOTED(C_SWITCH_X_SITE, ${C_SWITCH_X_SITE})
-AC_DEFINE_UNQUOTED(UNEXEC_SRC, ${UNEXEC_SRC})
-
-if test "${HAVE_X_WINDOWS}" = "yes" ; then
- AC_DEFINE(HAVE_X_WINDOWS)
-fi
-if test "${USE_X_TOOLKIT}" != "none" ; then
- AC_DEFINE(USE_X_TOOLKIT)
-fi
-if test "${HAVE_X11}" = "yes" ; then
- AC_DEFINE(HAVE_X11)
-fi
-if test "${HAVE_XFREE386}" = "yes" ; then
- AC_DEFINE(HAVE_XFREE386)
-fi
-if test "${HAVE_MENUS}" = "yes" ; then
- AC_DEFINE(HAVE_MENUS)
-fi
-if test "${GNU_MALLOC}" = "yes" ; then
- AC_DEFINE(GNU_MALLOC)
-fi
-if test "${REL_ALLOC}" = "yes" ; then
- AC_DEFINE(REL_ALLOC)
-fi
-if test "${LISP_FLOAT_TYPE}" = "yes" ; then
- AC_DEFINE(LISP_FLOAT_TYPE)
-fi
-
-#### Report on what we decided to do.
-echo "
-Configured for \`${canonical}'.
-
- Where should the build process find the source code? ${srcdir}
- What operating system and machine description files should Emacs use?
- \`${opsysfile}' and \`${machfile}'
- What compiler should emacs be built with? ${CC} ${CFLAGS}
- Should Emacs use the GNU version of malloc? ${GNU_MALLOC}${GNU_MALLOC_reason}
- Should Emacs use the relocating allocator for buffers? ${REL_ALLOC}
- What window system should Emacs use? ${window_system}
- What toolkit should Emacs use? ${USE_X_TOOLKIT}"
-
-if test -n "${x_includes}"; then
-echo " Where do we find X Windows header files? ${x_includes}"
-else
-echo " Where do we find X Windows header files? Standard dirs"
-fi
-if test -n "${x_libraries}"; then
-echo " Where do we find X Windows libraries? ${x_libraries}"
-else
-echo " Where do we find X Windows libraries? Standard dirs"
-fi
-
-echo
-
-# Remove any trailing slashes in these variables.
-changequote(, )dnl
-test "${prefix}" != NONE &&
- prefix=`echo "${prefix}" | sed 's,\([^/]\)/*$,\1,'`
-test "${exec_prefix}" != NONE &&
- exec_prefix=`echo "${exec_prefix}" | sed 's,\([^/]\)/*$,\1,'`
-changequote([, ])dnl
-
-AC_OUTPUT(Makefile lib-src/Makefile.c:lib-src/Makefile.in oldXMenu/Makefile \
- man/Makefile lwlib/Makefile src/Makefile.c:src/Makefile.in, [
-
-### Make the necessary directories, if they don't exist.
-for dir in cpp etc lisp ; do
- test -d ${dir} || mkdir ${dir}
-done
-
-# Build src/Makefile from ${srcdir}/src/Makefile.c
-# and lib-src/Makefile from ${srcdir}/lib-src/Makefile.c
-# This must be done after src/config.h is built, since we rely on that file.
-
-changequote(, )dnl The horror, the horror.
-# Now get this: Some word that is part of the ${srcdir} directory name
-# or the ${configuration} value might, just might, happen to be an
-# identifier like `sun4' or `i386' or something, and be predefined by
-# the C preprocessor to some helpful value like 1, or maybe the empty
-# string. Needless to say consequent macro substitutions are less
-# than conducive to the makefile finding the correct directory.
-undefs="`echo $top_srcdir $configuration $canonical |
-sed -e 's/[^a-zA-Z0-9_]/ /g' -e 's/^/ /' -e 's/ *$//' \
- -e 's/ */ -U/g' -e 's/-U[0-9][^ ]*//g' \
-`"
-changequote([, ])dnl
-
-echo creating src/paths.h
-make paths-force
-
-echo creating lib-src/Makefile
-( cd lib-src
- rm -f junk.c junk1.c junk2.c
- sed -e '/start of cpp stuff/q' \
- < Makefile.c > junk1.c
- sed -e '1,/start of cpp stuff/d'\
- -e 's@/\*\*/#\(.*\)$@/* \1 */@' \
- < Makefile.c > junk.c
- $CPP $undefs -I. -I$top_srcdir/src $CPPFLAGS junk.c | \
- sed -e 's/^ / /' -e '/^#/d' -e '/^[ ]*$/d' > junk2.c
- cat junk1.c junk2.c > Makefile.new
- rm -f junk.c junk1.c junk2.c
- chmod 444 Makefile.new
- mv -f Makefile.new Makefile
-)
-
-echo creating src/Makefile
-( cd src
- rm -f junk.c junk1.c junk2.c
- sed -e '/start of cpp stuff/q' \
- < Makefile.c > junk1.c
- sed -e '1,/start of cpp stuff/d'\
- -e 's@/\*\*/#\(.*\)$@/* \1 */@' \
- < Makefile.c > junk.c
- $CPP $undefs -I. -I$top_srcdir/src $CPPFLAGS junk.c | \
- sed -e 's/^ / /' -e '/^#/d' -e '/^[ ]*$/d' > junk2.c
- cat junk1.c junk2.c > Makefile.new
- rm -f junk.c junk1.c junk2.c
- chmod 444 Makefile.new
- mv -f Makefile.new Makefile
-)
-
-if test ! -f src/.gdbinit && test -f $top_srcdir/src/.gdbinit; then
- echo creating src/.gdbinit
- echo source $top_srcdir/src/.gdbinit > src/.gdbinit
-fi
-
-], [CPP="$CPP" CPPFLAGS="$CPPFLAGS"])
diff --git a/configure1.in b/configure1.in
deleted file mode 100755
index 6e4cf079a26..00000000000
--- a/configure1.in
+++ /dev/null
@@ -1,1812 +0,0 @@
-dnl This is an autoconf script.
-dnl To rebuild the `configure' script from this, execute the command
-dnl autoconf
-dnl in the directory containing this script.
-[#!/bin/sh
-#### Configuration script for GNU Emacs
-#### Copyright (C) 1992, 1994 Free Software Foundation, Inc.
-#### This script requires autoconf version 1.9 or later.
-
-### Don't edit this script!
-### This script was automatically generated by the `autoconf' program
-### from the file `./configure.in'.
-### To rebuild it, execute the command
-### autoconf
-### in the this directory.
-
-### This file is part of GNU Emacs.
-
-### GNU Emacs is free software; you can redistribute it and/or modify
-### it under the terms of the GNU General Public License as published by
-### the Free Software Foundation; either version 2, or (at your option)
-### any later version.
-
-### GNU Emacs is distributed in the hope that it will be useful,
-### but WITHOUT ANY WARRANTY; without even the implied warranty of
-### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-### GNU General Public License for more details.
-
-### You should have received a copy of the GNU General Public License
-### along with GNU Emacs; see the file COPYING. If not, write to
-### the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-### Since Emacs has configuration requirements that autoconf can't
-### meet, this file is an unholy marriage of custom-baked
-### configuration code and autoconf macros.
-###
-### We use the m4 quoting characters [ ] (as established by the
-### autoconf system) to include large sections of raw sewage - Oops, I
-### mean, shell code - in the final configuration script.
-###
-### Usage: configure config_name
-###
-### If configure succeeds, it leaves its status in config.status.
-### If configure fails after disturbing the status quo,
-### config.status is removed.
-
-### Remove any more than one leading "." element from the path name.
-### If we don't remove them, then another "./" will be prepended to
-### the file name each time we use config.status, and the program name
-### will get larger and larger. This wouldn't be a problem, except
-### that since progname gets recorded in all the Makefiles this script
-### produces, move-if-change thinks they're different when they're
-### not.
-###
-### It would be nice if we could put the ./ in a \( \) group and then
-### apply the * operator to that, so we remove as many leading ./././'s
-### as are present, but some seds (like Ultrix's sed) don't allow you to
-### apply * to a \( \) group. Bleah.
-progname="`echo $0 | sed 's:^\./\./:\./:'`"
-
-
-### Establish some default values.
-run_in_place=
-single_tree=
-prefix='/usr/local'
-exec_prefix='${prefix}'
-bindir='${exec_prefix}/bin'
-datadir='${prefix}/share'
-sharedstatedir='${prefix}/com'
-libexecdir='${exec_prefix}/libexec'
-mandir='${prefix}/man/man1'
-infodir='${prefix}/info'
-lispdir='${datadir}/emacs/${version}/lisp'
-locallisppath='${datadir}/emacs/site-lisp'
-lisppath='${locallisppath}:${lispdir}'
-etcdir='${datadir}/emacs/${version}/etc'
-lockdir='${sharedstatedir}/emacs/lock'
-archlibdir='${libexecdir}/emacs/${version}/${configuration}'
-docdir='${datadir}/emacs/${version}/etc'
-
-# On Sun systems, people sometimes set up the variable CPP
-# with a value that is a directory, not an executable at all.
-# Detect that case, and ignore that value.
-if [ "x$CPP" != x ] && [ -d "$CPP" ];
-then
- CPP=
-fi
-
-# We cannot use this variable in the case statement below, because many
-# /bin/sh's have broken semantics for "case". Unfortunately, you must
-# actually edit the clause itself.
-# path_options="prefix | exec_prefix | bindir | libexecdir | etcdir | datadir"
-# path_options="$path_options | archlibdir | sharedstatedir | mandir | infodir"
-# path_options="$path_options | lispdir | lockdir | lisppath | locallisppath"
-
-#### Usage messages.
-
-short_usage="Usage: ${progname} CONFIGURATION [-OPTION[=VALUE] ...]
-
-Set compilation and installation parameters for GNU Emacs, and report.
-CONFIGURATION specifies the machine and operating system to build for.
---with-x Support the X Window System.
---with-x=no Don't support X.
---with-x-toolkit=yes Use the X toolkit. Default to Lucid/Athena widgets.
---with-x-toolkit=athena Use the X toolkit with Athena widgets.
---with-x-toolkit=lucid Use the X toolkit with Lucid widgets.
---with-x-toolkit=motif Use the X toolkit with Motif widgets.
---with-x-toolkit=no Don't use an X toolkit.
---with-gcc Use GCC to compile Emacs.
---with-gcc=no Don't use GCC to compile Emacs.
---x-includes=DIR Search for X header files in DIR.
---x-libraries=DIR Search for X libraries in DIR.
---run-in-place Use libraries and data files directly out of the
- source tree.
---single-tree=DIR Has the effect of creating a directory tree at DIR
- which looks like:
- .../DIR/bin/CONFIGNAME (emacs, etags, etc.)
- .../DIR/bin/CONFIGNAME/etc (movemail, etc.)
- .../DIR/common/lisp (emacs' lisp files)
- .../DIR/common/site-lisp (local lisp files)
- .../DIR/common/lib (DOC, TUTORIAL, etc.)
- .../DIR/common/lock (lockfiles)
---srcdir=DIR Look for the Emacs source files in DIR.
---prefix=DIR Install files below DIR. Defaults to \`${prefix}'.
-
-You may also specify any of the \`path' variables found in Makefile.in,
-including --bindir, --libexecdir, --etcdir, --infodir, and so on. This allows
-you to override a single default location when configuring.
-
-If successful, ${progname} leaves its status in config.status. If
-unsuccessful after disturbing the status quo, it removes config.status."
-
-
-#### Option processing.
-
-### Record all the arguments, so we can save them in config.status.
-arguments="$@"
-
-### Shell Magic: Quote the quoted arguments in ARGUMENTS. At a later date,
-### in order to get the arguments back in $@, we have to do an
-### `eval set x "$quoted_arguments"; shift'.
-quoted_arguments=
-for i in "$@"; do
- quoted_arguments="$quoted_arguments '$i'"
-done
-
-### Don't use shift -- that destroys the argument list, which autoconf needs
-### to produce config.status. It turns out that "set - ${arguments}" doesn't
-### work portably.
-### However, it also turns out that many shells cannot expand ${10} at all.
-### So using an index variable doesn't work either. It is possible to use
-### some shell magic to make 'set x "$arguments"; shift' work portably.
-config_options="$*"
-while [ $# != 0 ]; do
- arg="$1"; shift
- case "${arg}" in
-
- ## Anything starting with a hyphen we assume is an option.
- -* )
- ## Separate the switch name from the value it's being given.
- case "${arg}" in
- -*=*)
- opt=`echo ${arg} | sed 's:^-*\([^=]*\)=.*$:\1:'`
- val=`echo ${arg} | sed 's:^-*[^=]*=\(.*\)$:\1:'`
- valomitted=no
- ;;
- -*)
- ## If FOO is a boolean argument, --FOO is equivalent to
- ## --FOO=yes. Otherwise, the value comes from the next
- ## argument - see below.
- opt=`echo ${arg} | sed 's:^-*::'`
- val="yes"
- valomitted=yes
- ;;
- esac
-
- ## Change `-' in the option name to `_'.
- optname="${opt}"
- opt="`echo ${opt} | tr - _`"
-
- ## Process the option.
- case "${opt}" in
-
- ## Has the user specified which window systems they want to support?
- "with_x" | "with_x11" | "with_x10" )
- ## Make sure the value given was either "yes" or "no".
- case "${val}" in
- y | ye | yes ) val=yes ;;
- n | no ) val=no ;;
- * )
- (echo "${progname}: the \`--${optname}' option is supposed to have a boolean value.
-Set it to either \`yes' or \`no'."
- echo "${short_usage}") >&2
- exit 1
- ;;
- esac
- eval "${opt}=\"${val}\""
- ;;
-
- ## Has the user specified which toolkit they want to support?
- "with_x_toolkit" )
- case "${val}" in
- y | ye | yes ) val=athena ;;
- n | no ) val=no ;;
- l | lu | luc | luci | lucid ) val=lucid ;;
- a | at | ath | athe | athena ) val=athena ;;
- m | mo | mot | moti | motif ) val=motif ;;
-# These don't currently work.
-# o | op | ope | open | open- | open-l | open-lo \
-# | open-loo | open-look ) val=open-look ;;
- * )
- (
-#echo "${progname}: the \`--${optname}' option is supposed to have a value
-#which is \`yes', \`no', \`lucid', \`athena', \`motif' or \`open-look'."
-echo "${progname}: the \`--${optname}' option is supposed to have a value
-which is \`yes', \`no', \`lucid', \`athena', or \`motif'.
-Currently, \`yes', \`athena' and \`lucid' are synonyms."
- echo "${short_usage}") >&2
- exit 1
- ;;
- esac
- eval "${opt}=\"${val}\""
- ;;
-
- ## Has the user specified whether or not they want GCC?
- "with_gcc" | "with_gnu_cc" )
- ## Make sure the value given was either "yes" or "no".
- case "${val}" in
- y | ye | yes ) val=yes ;;
- n | no ) val=no ;;
- * )
- (echo "${progname}: the \`--${optname}' option is supposed to have a boolean value.
-Set it to either \`yes' or \`no'."
- echo "${short_usage}") >&2
- exit 1
- ;;
- esac
- eval "${opt}=\"${val}\""
- ;;
-
- ## Has the user specified a source directory?
- "srcdir" )
- ## If the value was omitted, get it from the next argument.
- if [ "${valomitted}" = "yes" ]; then
- ## Get the next argument from the argument list, if there is one.
- if [ $# = 0 ]; then
- (echo "${progname}: You must give a value for the \`--${optname}' option, as in
- \`--${optname}=FOO'."
- echo "${short_usage}") >&2
- exit 1
- fi
- val="$1"; shift
- fi
- srcdir="${val}"
- ;;
-
- ## Has the user tried to tell us where the X files are?
- ## I think these are dopey, but no less than three alpha
- ## testers, at large sites, have said they have their X files
- ## installed in odd places.
- "x_includes" )
- ## If the value was omitted, get it from the next argument.
- if [ "${valomitted}" = "yes" ]; then
- ## Get the next argument from the argument list, if there is one.
- if [ $# = 0 ]; then
- (echo "${progname}: You must give a value for the \`--${optname}' option, as in
- \`--${optname}=/usr/local/X11/include'."
- echo "${short_usage}") >&2
- exit 1
- fi
- val="$1"; shift
- fi
- x_includes="${val}"
- ;;
- "x_libraries" )
- ## If the value was omitted, get it from the next argument.
- if [ "${valomitted}" = "yes" ]; then
- ## Get the next argument from the argument list, if there is one.
- if [ $# = 0 ]; then
- (echo "${progname}: You must give a value for the \`--${optname}' option, as in
- \`--${optname}=/usr/local/X11/lib'."
- echo "${short_usage}") >&2
- exit 1
- fi
- val="$1"; shift
- fi
- x_libraries="${val}"
- ;;
-
- ## Should this use the "development" file organization?
- "run_in_place" )
- single_tree=
- run_in_place=1
- ;;
-
- ## Should this use the "single tree" file organization?
- "single_tree" )
- run_in_place=
- single_tree=1
- ;;
-
- ## Has the user specified one of the path options?
- prefix | exec_prefix | bindir | libexecdir | etcdir | datadir | \
- archlibdir | sharedstatedir | mandir | infodir | lispdir | lockdir | \
- lisppath | locallisppath | docdir )
- ## If the value was omitted, get it from the next argument.
- if [ "${valomitted}" = "yes" ]; then
- if [ $# = 0 ]; then
- (echo \
-"$progname: You must give a value for the \`--${optname}' option,";
- echo \
-"as in \`--${optname}=`eval echo '$'$optname`.'"
- echo "$short_usage") >&2
- exit 1
- fi
- val="$1"; shift
- fi
- eval "${opt}=\"${val}\""
- eval "${opt}_specified=1"
- ;;
-
- ## Verbose flag, tested by autoconf macros.
- "verbose" )
- verbose=yes
- ;;
-
- ## Has the user asked for some help?
- "usage" | "help" )
- if [ "x$PAGER" = x ]
- then
- echo "${short_usage}" | more
- else
- echo "${short_usage}" | $PAGER
- fi
- exit
- ;;
-
- ## We ignore all other options silently.
- esac
- ;;
-
- ## Anything not starting with a hyphen we assume is a
- ## configuration name.
- *)
- configuration=${arg}
- ;;
-
- esac
-done
-
-### Get the arguments back. See the diatribe on Shell Magic above.
-eval set x "$quoted_arguments"; shift
-
-if [ "${configuration}" = "" ]; then
- echo '- You did not tell me what kind of host system you want to configure.
-- I will attempt to guess the kind of system this is.' 1>&2
- guesssys=`echo ${progname} | sed 's/configure$/config.guess/'`
- if configuration=`${guesssys}` ; then
- echo "- Looks like this is a ${configuration}" 1>&2
- else
- echo '- Failed to guess the system type. You need to tell me.' 1>&2
- echo "${short_usage}" >&2
- exit 1
- fi
-fi
-
-#### Decide where the source is.
-case "${srcdir}" in
-
- ## If it's not specified, see if `.' or `..' might work.
- "" )
- confdir=`echo $0 | sed 's|//|/|' | sed 's|/[^/]*$||'`
- if [ -f $confdir/src/lisp.h -a -f $confdir/lisp/version.el ]; then
- srcdir="${confdir}"
- else
- if [ -f "./src/lisp.h" -a -f "./lisp/version.el" ]; then
- srcdir='.'
- else
- if [ -f "../src/lisp.h" -a -f "../lisp/version.el" ]; then
- srcdir='..'
- else
- (echo "\
-${progname}: Neither the current directory nor its parent seem to
-contain the Emacs sources. If you do not want to build Emacs in its
-source tree, you should run \`${progname}' in the directory in which
-you wish to build Emacs, using its \`--srcdir' option to say where the
-sources may be found."
- echo "${short_usage}") >&2
- exit 1
- fi
- fi
- fi
- ;;
-
- ## Otherwise, check if the directory they specified is okay.
- * )
- if [ ! -d "${srcdir}" -o ! -f "${srcdir}/src/lisp.h" -o ! -f "${srcdir}/lisp/version.el" ]; then
- (echo "\
-${progname}: The directory specified with the \`--srcdir' option,
-\`${srcdir}', doesn't seem to contain the Emacs sources. You should
-either run the \`${progname}' script at the top of the Emacs source
-tree, or use the \`--srcdir' option to specify where the Emacs sources
-are."
- echo "${short_usage}") >&2
- exit 1
- fi
- ;;
-esac
-
-#### Make srcdir absolute, if it isn't already. It's important to
-#### avoid running the path through pwd unnecessary, since pwd can
-#### give you automounter prefixes, which can go away.
-case "${srcdir}" in
- /* ) ;;
- . )
- ## We may be able to use the $PWD environment variable to make this
- ## absolute. But sometimes PWD is inaccurate.
- if [ "${PWD}" != "" ] && [ "`(cd ${PWD} ; sh -c pwd)`" = "`pwd`" ] ; then
- srcdir="$PWD"
- else
- srcdir="`(cd ${srcdir}; pwd)`"
- fi
- ;;
- * ) srcdir="`(cd ${srcdir}; pwd)`" ;;
-esac
-
-### Remove trailing slashes.
-srcdir=`echo "${srcdir}" | sed 's,\([^/]\)/*$,\1,'`
-
-#### Check if the source directory already has a configured system in it.
-if [ `pwd` != `(cd ${srcdir} && pwd)` ] \
- && [ -f "${srcdir}/src/config.h" ] ; then
- (echo "${progname}: WARNING: The directory tree \`${srcdir}' is being used"
- echo " as a build directory right now; it has been configured in its own"
- echo " right. To configure in another directory as well, you MUST"
- echo " use GNU make. If you do not have GNU make, then you must"
- echo " now do \`make distclean' in ${srcdir},"
- echo " and then run ${progname} again.") >&2
- extrasub='/^VPATH[ ]*=/c\
-vpath %.c $(srcdir)\
-vpath %.h $(srcdir)\
-vpath %.y $(srcdir)\
-vpath %.l $(srcdir)\
-vpath %.s $(srcdir)\
-vpath %.in $(srcdir)'
-fi
-
-### Make the necessary directories, if they don't exist.
-for dir in ./src ./lib-src ./cpp ./oldXMenu ./lwlib ./etc ; do
- if [ ! -d ${dir} ]; then
- mkdir ${dir}
- fi
-done
-
-#### Given the configuration name, set machfile and opsysfile to the
-#### names of the m/*.h and s/*.h files we should use.
-
-### Canonicalize the configuration name.
-echo "Checking the configuration name"
-if canonical=`${srcdir}/config.sub "${configuration}"` ; then : ; else
- exit $?
-fi
-
-### If you add support for a new configuration, add code to this
-### switch statement to recognize your configuration name and select
-### the appropriate operating system and machine description files.
-
-### You would hope that you could choose an m/*.h file pretty much
-### based on the machine portion of the configuration name, and an s-
-### file based on the operating system portion. However, it turns out
-### that each m/*.h file is pretty manufacturer-specific - for
-### example, apollo.h, hp9000s300.h, mega68k, news.h, and tad68k are
-### all 68000 machines; mips.h, pmax.h, and news-risc are all MIPS
-### machines. So we basically have to have a special case for each
-### configuration name.
-###
-### As far as handling version numbers on operating systems is
-### concerned, make sure things will fail in a fixable way. If
-### /etc/MACHINES doesn't say anything about version numbers, be
-### prepared to handle anything reasonably. If version numbers
-### matter, be sure /etc/MACHINES says something about it.
-###
-### Eric Raymond says we should accept strings like "sysvr4" to mean
-### "System V Release 4"; he writes, "The old convention encouraged
-### confusion between `system' and `release' levels'."
-
-machine='' opsys='' unported='false'
-case "${canonical}" in
-
- ## NetBSD ports
- *-*-netbsd* )
- opsys=netbsd
- case "${canonical}" in
- i[345]86-*-netbsd*) machine=intel386 ;;
- m68k-*-netbsd*)
- # This is somewhat bogus.
- machine=hp9000s300 ;;
- mips-*-netbsd*) machine=pmax ;;
- ns32k-*-netbsd*) machine=ns32000 ;;
- sparc-*-netbsd*) machine=sparc ;;
- esac
- ;;
-
- ## Acorn RISCiX:
- arm-acorn-riscix1.1* )
- machine=acorn opsys=riscix1-1
- ;;
- arm-acorn-riscix1.2* | arm-acorn-riscix )
- machine=acorn opsys=riscix1-2
- ;;
-
- ## Alliant machines
- ## Strictly speaking, we need the version of the alliant operating
- ## system to choose the right machine file, but currently the
- ## configuration name doesn't tell us enough to choose the right
- ## one; we need to give alliants their own operating system name to
- ## do this right. When someone cares, they can help us.
- fx80-alliant-* )
- machine=alliant4 opsys=bsd4-2
- ;;
- i860-alliant-* )
- machine=alliant-2800 opsys=bsd4-3
- ;;
-
- alpha-dec-osf* )
- machine=alpha opsys=osf1
- ;;
-
- ## Altos 3068
- m68*-altos-sysv* )
- machine=altos opsys=usg5-2
- ;;
-
- ## Amdahl UTS
- 580-amdahl-sysv* )
- machine=amdahl opsys=usg5-2-2
- ;;
-
- ## Appallings - I mean, Apollos - running Domain
- m68*-apollo* )
- machine=apollo opsys=bsd4-2
- ;;
-
- ## AT&T 3b2, 3b5, 3b15, 3b20
- we32k-att-sysv* )
- machine=att3b opsys=usg5-2-2
- ;;
-
- ## AT&T 3b1 - The Mighty Unix PC!
- m68*-att-sysv* )
- machine=7300 opsys=usg5-2-2
- ;;
-
- ## Bull dpx20
- rs6000-bull-bosx* )
- machine=ibmrs6000 opsys=aix3-2
- ;;
-
- ## Bull dpx2
- m68*-bull-sysv3* )
- machine=dpx2 opsys=usg5-3
- ;;
-
- ## Bull sps7
- m68*-bull-sysv2* )
- machine=sps7 opsys=usg5-2
- ;;
-
- ## CCI 5/32, 6/32 -- see "Tahoe".
-
- ## Celerity
- ## I don't know what configuration name to use for this; config.sub
- ## doesn't seem to know anything about it. Hey, Celerity users, get
- ## in touch with us!
- celerity-celerity-bsd* )
- machine=celerity opsys=bsd4-2
- ;;
-
- ## Clipper
- ## What operating systems does this chip run that Emacs has been
- ## tested on?
- clipper-* )
- machine=clipper
- ## We'll use the catch-all code at the bottom to guess the
- ## operating system.
- ;;
-
- ## Convex
- *-convex-bsd* | *-convex-convexos* )
- machine=convex opsys=bsd4-3
- ## Prevents suprious white space in makefiles - d.m.cooke@larc.nasa.gov
- NON_GNU_CPP="cc -E -P"
- ;;
-
- ## Cubix QBx/386
- i[345]86-cubix-sysv* )
- machine=intel386 opsys=usg5-3
- ;;
-
- ## Cydra 5
- cydra*-cydrome-sysv* )
- machine=cydra5 opsys=usg5-3
- ;;
-
- ## Data General AViiON Machines
- m88k-dg-dgux5.4R3* | m88k-dg-dgux5.4.3* )
- machine=aviion opsys=dgux5-4r3
- ;;
- m88k-dg-dgux5.4R2* | m88k-dg-dgux5.4.2* )
- machine=aviion opsys=dgux5-4r2
- ;;
- m88k-dg-dgux* )
- machine=aviion opsys=dgux
- ;;
-
- ## DECstations
- mips-dec-ultrix[0-3].* | mips-dec-ultrix4.0* | mips-dec-bsd4.2* )
- machine=pmax opsys=bsd4-2
- ;;
- mips-dec-ultrix* | mips-dec-bsd* )
- machine=pmax opsys=bsd4-3
- ;;
- mips-dec-osf* )
- machine=pmax opsys=osf1
- ;;
-
- ## Motorola Delta machines
- m68k-motorola-sysv* | m68000-motorola-sysv* )
- machine=delta opsys=usg5-3
- if [ -z "`type gnucc | grep 'not found'`" ]
- then CC=gnucc
- else
- if [ -z "`type gcc | grep 'not found'`" ]
- then CC=gcc
- else CC=cc
- fi
- fi
- ;;
- m88k-motorola-sysv4* )
- machine=delta88k opsys=usg5-4
- ;;
- m88k-motorola-sysv* | m88k-motorola-m88kbcs* )
- machine=delta88k opsys=usg5-3
- ;;
-
- ## Dual machines
- m68*-dual-sysv* )
- machine=dual opsys=usg5-2
- ;;
- m68*-dual-uniplus* )
- machine=dual opsys=unipl5-2
- ;;
-
- ## Elxsi 6400
- elxsi-elxsi-sysv* )
- machine=elxsi opsys=usg5-2
- ;;
-
- ## Encore machines
- ns16k-encore-bsd* )
- machine=ns16000 opsys=umax
- ;;
-
- ## The GEC 93 - apparently, this port isn't really finished yet.
-
- ## Gould Power Node and NP1
- pn-gould-bsd4.2* )
- machine=gould opsys=bsd4-2
- ;;
- pn-gould-bsd4.3* )
- machine=gould opsys=bsd4-3
- ;;
- np1-gould-bsd* )
- machine=gould-np1 opsys=bsd4-3
- ;;
-
- ## Harris Night Hawk machines running CX/UX (a 5000 looks just like a 4000
- ## as far as Emacs is concerned).
- m88k-harris-cxux* )
- # Build needs to be different on 7.0 and later releases
- case "`uname -r`" in
- [56].[0-9] ) machine=nh4000 opsys=cxux ;;
- [7].[0-9] ) machine=nh4000 opsys=cxux7 ;;
- esac
- ;;
- ## Harris ecx or gcx running CX/UX (Series 1200, Series 3000)
- m68k-harris-cxux* )
- machine=nh3000 opsys=cxux
- ;;
-
- ## Honeywell XPS100
- xps*-honeywell-sysv* )
- machine=xps100 opsys=usg5-2
- ;;
-
- ## HP 9000 series 200 or 300
- m68*-hp-bsd* )
- machine=hp9000s300 opsys=bsd4-3
- ;;
- ## HP/UX 7, 8 and 9 are supported on these machines.
- m68*-hp-hpux* )
- case "`uname -r`" in
- ## Someone's system reports A.B8.05 for this.
- ## I wonder what other possibilities there are.
- *.B8.* ) machine=hp9000s300 opsys=hpux8 ;;
- *.08.* ) machine=hp9000s300 opsys=hpux8 ;;
- *.09.* ) machine=hp9000s300 opsys=hpux9 ;;
- *) machine=hp9000s300 opsys=hpux ;;
- esac
- ;;
-
- ## HP 9000 series 700 and 800, running HP/UX
- hppa*-hp-hpux7* )
- machine=hp800 opsys=hpux
- ;;
- hppa*-hp-hpux8* )
- machine=hp800 opsys=hpux8
- ;;
- hppa*-hp-hpux9shr* )
- machine=hp800 opsys=hpux9shr
- ;;
- hppa*-hp-hpux9* )
- machine=hp800 opsys=hpux9
- ;;
-
- ## HP 9000 series 700 and 800, running HP/UX
- hppa*-hp-hpux* )
- ## Cross-compilation? Nah!
- case "`uname -r`" in
- ## Someone's system reports A.B8.05 for this.
- ## I wonder what other possibilities there are.
- *.B8.* ) machine=hp800 opsys=hpux8 ;;
- *.08.* ) machine=hp800 opsys=hpux8 ;;
- *.09.* ) machine=hp800 opsys=hpux9 ;;
- *) machine=hp800 opsys=hpux ;;
- esac
- ;;
-
- ## Orion machines
- orion-orion-bsd* )
- machine=orion opsys=bsd4-2
- ;;
- clipper-orion-bsd* )
- machine=orion105 opsys=bsd4-2
- ;;
-
- ## IBM machines
- i[345]86-ibm-aix1.1* )
- machine=ibmps2-aix opsys=usg5-2-2
- ;;
- i[345]86-ibm-aix1.[23]* | i[345]86-ibm-aix* )
- machine=ibmps2-aix opsys=usg5-3
- ;;
- i370-ibm-aix*)
- machine=ibm370aix opsys=usg5-3
- ;;
- rs6000-ibm-aix3.1* | powerpc-ibm-aix3.1* )
- machine=ibmrs6000 opsys=aix3-1
- ;;
- rs6000-ibm-aix3.2.5 | powerpc-ibm-aix3.2.5 )
- machine=ibmrs6000 opsys=aix3-2-5
- ;;
- rs6000-ibm-aix* | powerpc-ibm-aix* )
- machine=ibmrs6000 opsys=aix3-2
- ;;
- romp-ibm-bsd4.3* )
- machine=ibmrt opsys=bsd4-3
- ;;
- romp-ibm-bsd4.2* )
- machine=ibmrt opsys=bsd4-2
- ;;
- romp-ibm-aos4.3* )
- machine=ibmrt opsys=bsd4-3
- ;;
- romp-ibm-aos4.2* )
- machine=ibmrt opsys=bsd4-2
- ;;
- romp-ibm-aos* )
- machine=ibmrt opsys=bsd4-3
- ;;
- romp-ibm-bsd* )
- machine=ibmrt opsys=bsd4-3
- ;;
- romp-ibm-aix* )
- machine=ibmrt-aix opsys=usg5-2-2
- ;;
-
- ## Integrated Solutions `Optimum V'
- m68*-isi-bsd4.2* )
- machine=isi-ov opsys=bsd4-2
- ;;
- m68*-isi-bsd4.3* )
- machine=isi-ov opsys=bsd4-3
- ;;
-
- ## Intel 386 machines where we do care about the manufacturer
- i[345]86-intsys-sysv* )
- machine=is386 opsys=usg5-2-2
- ;;
-
- ## Prime EXL
- i[345]86-prime-sysv* )
- machine=i386 opsys=usg5-3
- ;;
-
- ## Sequent Symmetry running Dynix
- i[345]86-sequent-bsd* )
- machine=symmetry opsys=bsd4-3
- ;;
-
- ## Sequent Symmetry running DYNIX/ptx
- ## Use the old cpp rather than the newer ANSI one.
- i[345]86-sequent-ptx* )
- machine=sequent-ptx opsys=ptx
- NON_GNU_CPP="/lib/cpp"
- ;;
-
- ## Unspecified sysv on an ncr machine defaults to svr4.2.
- ## (Plain usg5-4 doesn't turn on POSIX signals, which we need.)
- i[345]86-ncr-sysv* )
- machine=intel386 opsys=usg5-4-2
- ;;
-
- ## Intel 860
- i860-*-sysv4* )
- machine=i860 opsys=usg5-4
- NON_GNU_CC="/bin/cc" # Ie, not the one in /usr/ucb/cc.
- NON_GNU_CPP="/usr/ccs/lib/cpp" # cc -E tokenizes macro expansion.
- ;;
-
- ## Masscomp machines
- m68*-masscomp-rtu* )
- machine=masscomp opsys=rtu
- ;;
-
- ## Megatest machines
- m68*-megatest-bsd* )
- machine=mega68 opsys=bsd4-2
- ;;
-
- ## Workstations sold by MIPS
- ## This is not necessarily all workstations using the MIPS processor -
- ## Irises are produced by SGI, and DECstations by DEC.
-
- ## etc/MACHINES lists mips.h and mips4.h as possible machine files,
- ## and usg5-2-2 and bsd4-3 as possible OS files. The only guidance
- ## it gives for choosing between the alternatives seems to be "Use
- ## -machine=mips4 for RISCOS version 4; use -opsystem=bsd4-3 with
- ## the BSD world." I'll assume that these are instructions for
- ## handling two odd situations, and that every other situation
- ## should use mips.h and usg5-2-2, they being listed first.
- mips-mips-usg* )
- machine=mips4
- ## Fall through to the general code at the bottom to decide on the OS.
- ;;
- mips-mips-riscos4* )
- machine=mips4 opsys=bsd4-3
- NON_GNU_CC="cc -systype bsd43"
- NON_GNU_CPP="cc -systype bsd43 -E"
- ;;
- mips-mips-bsd* )
- machine=mips opsys=bsd4-3
- ;;
- mips-mips-* )
- machine=mips opsys=usg5-2-2
- ;;
-
- ## NeXT
- m68*-next-* | i[345]86-next-* )
- machine=next opsys=mach2
- ;;
-
- ## The complete machine from National Semiconductor
- ns32k-ns-genix* )
- machine=ns32000 opsys=usg5-2
- ;;
-
- ## NCR machines
- m68*-ncr-sysv2* | m68*-ncr-sysvr2* )
- machine=tower32 opsys=usg5-2-2
- ;;
- m68*-ncr-sysv3* | m68*-ncr-sysvr3* )
- machine=tower32v3 opsys=usg5-3
- ;;
-
- ## Nixdorf Targon 31
- m68*-nixdorf-sysv* )
- machine=targon31 opsys=usg5-2-2
- ;;
-
- ## Nu (TI or LMI)
- m68*-nu-sysv* )
- machine=nu opsys=usg5-2
- ;;
-
- ## Plexus
- m68*-plexus-sysv* )
- machine=plexus opsys=usg5-2
- ;;
-
- ## Pyramid machines
- ## I don't really have any idea what sort of processor the Pyramid has,
- ## so I'm assuming it is its own architecture.
- pyramid-pyramid-bsd* )
- machine=pyramid opsys=bsd4-2
- ;;
-
- ## Sequent Balance
- ns32k-sequent-bsd4.2* )
- machine=sequent opsys=bsd4-2
- ;;
- ns32k-sequent-bsd4.3* )
- machine=sequent opsys=bsd4-3
- ;;
-
- ## Siemens Nixdorf
- mips-siemens-sysv* )
- machine=mips-siemens opsys=usg5-4
- NON_GNU_CC=/usr/ccs/bin/cc
- NON_GNU_CPP=/usr/ccs/lib/cpp
- ;;
-
- ## Silicon Graphics machines
- ## Iris 2500 and Iris 2500 Turbo (aka the Iris 3030)
- m68*-sgi-iris3.5* )
- machine=irist opsys=iris3-5
- ;;
- m68*-sgi-iris3.6* | m68*-sgi-iris*)
- machine=irist opsys=iris3-6
- ;;
- ## Iris 4D
- mips-sgi-irix3* )
- machine=iris4d opsys=irix3-3
- ;;
- mips-sgi-irix5* )
- machine=iris4d opsys=irix5-0
- ;;
- mips-sgi-irix4* | mips-sgi-irix* )
- machine=iris4d opsys=irix4-0
- ;;
-
- ## SONY machines
- m68*-sony-bsd4.2* )
- machine=news opsys=bsd4-2
- ;;
- m68*-sony-bsd4.3* )
- machine=news opsys=bsd4-3
- ;;
- m68*-sony-newsos3*)
- machine=news opsys=bsd4-3
- ;;
- mips-sony-bsd* | mips-sony-newsos4* )
- machine=news-risc opsys=bsd4-3
- ;;
- mips-sony-newsos* )
- machine=news-risc opsys=newsos5
- ;;
-
- ## Stride
- m68*-stride-sysv* )
- machine=stride opsys=usg5-2
- ;;
-
- ## Suns
- *-sun-sunos* | *-sun-bsd* | *-sun-solaris* | i[345]86-*-solaris2* | i[345]86-*-sunos5* )
- case "${canonical}" in
- m68*-sunos1* ) machine=sun1 ;;
- m68*-sunos2* ) machine=sun2 ;;
- m68* ) machine=sun3 ;;
- i[345]86-sun-sunos[34]* ) machine=sun386 ;;
- i[345]86-*-* ) machine=intel386 ;;
- sparc* ) machine=sparc ;;
- * ) unported=true ;;
- esac
- case "${canonical}" in
- ## The Sun386 didn't get past 4.0.
- i[345]86-*-sunos4 ) opsys=sunos4-0 ;;
- *-sunos4.0* ) opsys=sunos4-0 ;;
- *-sunos4.1.3* ) opsys=sunos4-1-3
- NON_GCC_TEST_OPTIONS=-Bstatic
- GCC_TEST_OPTIONS=-static
- ;;
- *-sunos4shr* ) opsys=sunos4shr ;;
- *-sunos4* | *-sunos ) opsys=sunos4-1
- NON_GCC_TEST_OPTIONS=-Bstatic
- GCC_TEST_OPTIONS=-static
- ;;
- *-sunos5.3* | *-solaris2.3* )
- opsys=sol2-3
- NON_GNU_CPP=/usr/ccs/lib/cpp
- ;;
- *-sunos5.4* | *-solaris2.4* )
- opsys=sol2-4
- NON_GNU_CPP=/usr/ccs/lib/cpp
- ;;
- *-sunos5* | *-solaris* )
- opsys=sol2
- NON_GNU_CPP=/usr/ccs/lib/cpp
- ;;
- * ) opsys=bsd4-2 ;;
- esac
- ;;
-
- ## Tadpole 68k
- m68*-tadpole-sysv* )
- machine=tad68k opsys=usg5-3
- ;;
-
- ## Tahoe machines
- tahoe-tahoe-bsd4.2* )
- machine=tahoe opsys=bsd4-2
- ;;
- tahoe-tahoe-bsd4.3* )
- machine=tahoe opsys=bsd4-3
- ;;
-
- ## Tandem Integrity S2
- mips-tandem-sysv* )
- machine=tandem-s2 opsys=usg5-3
- ;;
-
- ## Tektronix XD88
- m88k-tektronix-sysv3* )
- machine=tekxd88 opsys=usg5-3
- ;;
-
- ## Tektronix 16000 box (6130?)
- ns16k-tektronix-bsd* )
- machine=ns16000 opsys=bsd4-2
- ;;
- ## Tektronix 4300
- ## src/m/tek4300.h hints that this is a m68k machine.
- m68*-tektronix-bsd* )
- machine=tek4300 opsys=bsd4-3
- ;;
-
- ## Titan P2 or P3
- ## We seem to have lost the machine-description file titan.h!
- titan-titan-sysv* )
- machine=titan opsys=usg5-3
- ;;
-
- ## Ustation E30 (SS5E)
- m68*-unisys-uniplus* )
- machine=ustation opsystem=unipl5-2
- ;;
-
- ## Vaxen.
- vax-dec-* )
- machine=vax
- case "${canonical}" in
- *-bsd4.1* ) opsys=bsd4-1 ;;
- *-bsd4.2* | *-ultrix[0-3].* | *-ultrix4.0* ) opsys=bsd4-2 ;;
- *-bsd4.3* | *-ultrix* ) opsys=bsd4-3 ;;
- *-bsd386* | *-bsdi* ) opsys=bsd386 ;;
- *-sysv[01]* | *-sysvr[01]* ) opsys=usg5-0 ;;
- *-sysv2* | *-sysvr2* ) opsys=usg5-2 ;;
- *-vms* ) opsys=vms ;;
- * ) unported=true
- esac
- ;;
-
- ## Whitechapel MG1
- ns16k-whitechapel-* )
- machine=mg1
- ## We don't know what sort of OS runs on these; we'll let the
- ## operating system guessing code below try.
- ;;
-
- ## Wicat
- m68*-wicat-sysv* )
- machine=wicat opsys=usg5-2
- ;;
-
- ## Intel 386 machines where we don't care about the manufacturer
- i[345]86-*-* )
- machine=intel386
- case "${canonical}" in
- *-isc1.* | *-isc2.[01]* ) opsys=386-ix ;;
- *-isc2.2* ) opsys=isc2-2 ;;
- *-isc4.0* ) opsys=isc4-0 ;;
- *-isc* ) opsys=isc3-0 ;;
- *-esix5* ) opsys=esix5r4; NON_GNU_CPP=/usr/lib/cpp ;;
- *-esix* ) opsys=esix ;;
- *-xenix* ) opsys=xenix ;;
- *-linux* ) opsys=linux ;;
- *-sco3.2v4* ) opsys=sco4 ; NON_GNU_CPP=/lib/cpp ;;
- *-bsd386* | *-bsdi* ) opsys=bsd386 ;;
- *-386bsd* ) opsys=386bsd ;;
- *-freebsd* ) opsys=freebsd ;;
- *-nextstep* ) opsys=mach2 ;;
- ## Otherwise, we'll fall through to the generic opsys code at the bottom.
- esac
- ;;
-
- * )
- unported=true
- ;;
-esac
-
-### If the code above didn't choose an operating system, just choose
-### an operating system based on the configuration name. You really
-### only want to use this when you have no idea what the right
-### operating system is; if you know what operating systems a machine
-### runs, it's cleaner to make it explicit in the case statement
-### above.
-if [ x"${opsys}" = x ]; then
- case "${canonical}" in
- *-gnu* ) opsys=gnu ;;
- *-bsd4.[01] ) opsys=bsd4-1 ;;
- *-bsd4.2 ) opsys=bsd4-2 ;;
- *-bsd4.3 ) opsys=bsd4-3 ;;
- *-sysv0 | *-sysvr0 ) opsys=usg5-0 ;;
- *-sysv2 | *-sysvr2 ) opsys=usg5-2 ;;
- *-sysv2.2 | *-sysvr2.2 ) opsys=usg5-2-2 ;;
- *-sysv3 | *-sysvr3 ) opsys=usg5-3 ;;
- *-sysv4 | *-sysvr4 ) opsys=usg5-4 ;;
- *-sysv4.1 | *-sysvr4.1 )
- NON_GNU_CPP=/usr/lib/cpp
- opsys=usg5-4 ;;
- *-sysv4.2 | *-sysvr4.2 ) opsys=usg5-4-2 ;;
- * )
- unported=true
- ;;
- esac
-fi
-
-if $unported ; then
- (echo "${progname}: Emacs hasn't been ported to \`${canonical}' systems."
- echo "${progname}: Check \`etc/MACHINES' for recognized configuration names."
- ) >&2
- exit 1
-fi
-
-machfile="m/${machine}.h"
-opsysfile="s/${opsys}.h"
-
-]
-AC_PREPARE(lisp)
-AC_CONFIG_HEADER(src/config.h)
-[
-
-#### Choose a compiler.
-if [ "x$CC" = x ]
-then true
-else cc_specified=1
-fi
-
-case ${with_gcc} in
- "yes" ) CC="gcc" GCC=1 ;;
- "no" )
- if [ "x$CC" = x ]
- then CC=cc;
- else true;
- fi
- ;;
- * )
- ] AC_PROG_CC [
-esac
-
-#### Some systems specify a CPP to use unless we are using GCC.
-#### Now that we know whether we are using GCC, we can decide whether
-#### to use that one.
-if [ "x$NON_GNU_CPP" = x ] || [ x$GCC = x1 ] || [ "x$CPP" != x ]
-then true
-else
- CPP="$NON_GNU_CPP"
-fi
-
-#### Some systems specify a CC to use unless we are using GCC.
-#### Now that we know whether we are using GCC, we can decide whether
-#### to use that one.
-if [ "x$NON_GNU_CC" = x ] || [ x$GCC = x1 ] || [ x$cc_specified = x1 ]
-then true
-else
- CC="$NON_GNU_CC"
-fi
-
-if [ x$GCC = x1 ] && [ "x$GCC_TEST_OPTIONS" != x ]
-then
- CC="$CC $GCC_TEST_OPTIONS"
-fi
-
-if [ x$GCC = x ] && [ "x$NON_GCC_TEST_OPTIONS" != x ]
-then
- CC="$CC $NON_GCC_TEST_OPTIONS"
-fi
-
-#### Some other nice autoconf tests. If you add a test here which
-#### should make an entry in src/config.h, don't forget to add an
-#### #undef clause to src/config.h.in for autoconf to modify.
-]
-dnl checks for programs
-AC_LN_S
-AC_PROG_CPP
-AC_PROG_INSTALL
-AC_PROG_YACC
-
-dnl checks for UNIX variants that set `DEFS'
-AC_AIX
-
-dnl checks for header files
-AC_HAVE_HEADERS(sys/timeb.h sys/time.h unistd.h utime.h)
-AC_STDC_HEADERS
-AC_TIME_WITH_SYS_TIME
-dnl In Autoconf 1.8 use AC_SYS_SIGLIST_DECLARED instead of this.
-AC_COMPILE_CHECK(sys_siglist declaration in signal.h or unistd.h,
- [#include <signal.h>
-/* NetBSD declares sys_siglist in <unistd.h>. */
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif], [char *msg = *(sys_siglist + 1);],
- AC_DEFINE(SYS_SIGLIST_DECLARED))
-dnl Some systems have utime.h but don't declare the struct anyplace.
-AC_COMPILE_CHECK(struct utimbuf, [#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif], [static struct utimbuf x; x.actime = x.modtime;],
- AC_DEFINE(HAVE_STRUCT_UTIMBUF))
-
-dnl checks for typedefs
-AC_RETSIGTYPE
-AC_COMPILE_CHECK(struct timeval, [#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif], [static struct timeval x; x.tv_sec = x.tv_usec;],
- AC_DEFINE(HAVE_TIMEVAL))
-
-dnl checks for structure members
-AC_STRUCT_TM
-AC_TIMEZONE
-
-dnl checks for compiler characteristics
-AC_CONST
-
-dnl check for Make feature
-AC_SET_MAKE
-
-dnl checks for operating system services
-AC_LONG_FILE_NAMES
-
-dnl other checks for UNIX variants
-[
-
-#### Choose a window system.
-echo "checking for specified window system"
-
-window_system=''
-case "${with_x}" in
- yes )
- window_system=${window_system}x11
- ;;
- no )
- window_system=${window_system}none
- ;;
-esac
-case "${window_system}" in
- .* )
- ;;
- * )
- case "${with_x11}" in
- yes )
- window_system=x11
- ;;
- no )
- window_system=none
- ;;
- esac
- case "${with_x10}" in
- yes )
- window_system=x10
- ;;
- no )
- window_system=none
- ;;
- esac
- ;;
-esac
-
-case "${window_system}" in
- "none" | "x11" | "x10" ) ;;
- "" )
- # --x-includes or --x-libraries implies --with-x11.
- if [ -n "${x_includes}" ] || [ -n "${x_libraries}" ]; then
- window_system=x11
- else
- echo " No window system specified. Looking for X11."
- # If the user didn't specify a window system and we found X11, use it.
- if [ -r /usr/lib/libX11.a \
- -o -d /usr/include/X11 \
- -o -d /usr/X386/include \
- -o -d ${x_includes}/X11 ]; then
- window_system=x11
- fi
- fi
- ;;
- * )
- echo "Don't specify a window system more than once." >&2
- exit 1
- ;;
-esac
-
-case "${window_system}" in
- "" | "x11" )
- ### If the user hasn't specified where we should find X, try
- ### letting autoconf figure that out.
- if [ -z "${x_includes}" ] && [ -z "${x_libraries}" ]; then
- ]
- AC_FIND_X
- [
- fi
- if [ -n "${x_includes}" ] || [ -n "${x_libraries}" ]; then
- window_system=x11
- fi
- ;;
-esac
-
-[ -z "${window_system}" ] && window_system=none
-
-[ -n "${x_libraries}" ] && LD_SWITCH_X_SITE="-L${x_libraries}"
-[ -n "${x_libraries}" ] && LD_SWITCH_X_SITE_AUX="-R${x_libraries}"
-[ -n "${x_includes}" ] && C_SWITCH_X_SITE="-I${x_includes}"
-
-if [ x"${x_includes}" = x ]; then
- bitmapdir=/usr/include/X11/bitmaps;
-else
- bitmapdir="${x_includes}/bitmaps";
-fi
-
-# Avoid forcing the search of /usr/include before fixed include files.
-if [ "$C_SWITCH_X_SITE" = "-I/usr/include" ]; then
- C_SWITCH_X_SITE=" "
-fi
-
-case "${window_system}" in
- x11 )
- HAVE_X_WINDOWS=yes
- HAVE_X11=yes
- echo " Using X11."
- case "${with_x_toolkit}" in
- athena | lucid )
- USE_X_TOOLKIT=LUCID
- echo " Using Xt toolkit."
- ;;
- motif )
- USE_X_TOOLKIT=MOTIF
- echo " Using Motif toolkit."
- ;;
- open-look )
- USE_X_TOOLKIT=OPEN_LOOK
- echo " Using Open-Look toolkit."
- ;;
- * )
- USE_X_TOOLKIT=none
- echo " Using Xlib directly."
- ;;
- esac
- ;;
- x10 )
- HAVE_X_WINDOWS=yes
- HAVE_X11=no
- USE_X_TOOLKIT=none
- echo " Using X10."
- ;;
- none )
- HAVE_X_WINDOWS=no
- HAVE_X11=no
- USE_X_TOOLKIT=none
- echo " Using no window system."
- ;;
-esac
-X_TOOLKIT_TYPE=$USE_X_TOOLKIT
-
-### If we're using X11, we should use the X menu package.
-HAVE_X_MENU=no
-case ${HAVE_X11} in
- yes )
- HAVE_X_MENU=yes
- ;;
-esac
-
-#### Extract some information from the operating system and machine files.
-
-echo "examining the machine- and system-dependent files to find out"
-echo " - which libraries the lib-src programs will want, and"
-echo " - whether the GNU malloc routines are usable"
-
-### First figure out CFLAGS (which we use for running the compiler here)
-### and REAL_CFLAGS (which we use for real compilation).
-### The two are the same except on a few systems, where they are made
-### different to work around various lossages. For example,
-### GCC 2.5 on Linux needs them to be different because it treats -g
-### as implying static linking.
-
-### If the CFLAGS env var is specified, we use that value
-### instead of the default.
-
-### It's not important that this name contain the PID; you can't run
-### two configures in the same directory and have anything work
-### anyway.
-tempcname="conftest.c"
-
-echo '
-#include "'${srcdir}'/src/'${opsysfile}'"
-#include "'${srcdir}'/src/'${machfile}'"
-#ifndef LIBS_MACHINE
-#define LIBS_MACHINE
-#endif
-#ifndef LIBS_SYSTEM
-#define LIBS_SYSTEM
-#endif
-#ifndef C_SWITCH_SYSTEM
-#define C_SWITCH_SYSTEM
-#endif
-#ifndef C_SWITCH_MACHINE
-#define C_SWITCH_MACHINE
-#endif
-configure___ libsrc_libs=LIBS_MACHINE LIBS_SYSTEM
-configure___ c_switch_system=C_SWITCH_SYSTEM
-configure___ c_switch_machine=C_SWITCH_MACHINE
-
-#ifndef LIB_X11_LIB
-#define LIB_X11_LIB -lX11
-#endif
-
-#ifndef LIBX11_MACHINE
-#define LIBX11_MACHINE
-#endif
-
-#ifndef LIBX11_SYSTEM
-#define LIBX11_SYSTEM
-#endif
-configure___ LIBX=LIB_X11_LIB LIBX11_MACHINE LIBX11_SYSTEM
-
-#ifdef UNEXEC
-configure___ unexec=UNEXEC
-#else
-configure___ unexec=unexec.o
-#endif
-
-#ifdef SYSTEM_MALLOC
-configure___ system_malloc=yes
-#else
-configure___ system_malloc=no
-#endif
-
-#ifndef C_DEBUG_SWITCH
-#define C_DEBUG_SWITCH -g
-#endif
-
-#ifndef C_OPTIMIZE_SWITCH
-#define C_OPTIMIZE_SWITCH -O
-#endif
-
-#ifdef THIS_IS_CONFIGURE
-
-/* Get the CFLAGS for tests in configure. */
-#ifdef __GNUC__
-configure___ CFLAGS=C_DEBUG_SWITCH C_OPTIMIZE_SWITCH '${CFLAGS}'
-#else
-configure___ CFLAGS=C_DEBUG_SWITCH '${CFLAGS}'
-#endif
-
-#else /* not THIS_IS_CONFIGURE */
-
-/* Get the CFLAGS for real compilation. */
-#ifdef __GNUC__
-configure___ REAL_CFLAGS=C_DEBUG_SWITCH C_OPTIMIZE_SWITCH '${CFLAGS}'
-#else
-configure___ REAL_CFLAGS=C_DEBUG_SWITCH '${CFLAGS}'
-#endif
-
-#endif /* not THIS_IS_CONFIGURE */
-' > ${tempcname}
-# The value of CPP is a quoted variable reference, so we need to do this
-# to get its actual value...
-CPP=`eval "echo $CPP"`
-eval `${CPP} -Isrc ${tempcname} \
- | grep 'configure___' \
- | sed -e 's/^configure___ \([^=]*=\)\(.*\)$/\1"\2"/'`
-if [ "x$CFLAGS" = x ]; then
- eval `${CPP} -Isrc -DTHIS_IS_CONFIGURE ${tempcname} \
- | grep 'configure___' \
- | sed -e 's/^configure___ \([^=]*=\)\(.*\)$/\1"\2"/'`
-else
- REAL_CFLAGS="$CFLAGS"
-fi
-rm ${tempcname}
-
-### Compute the unexec source name from the object name.
-UNEXEC_SRC="`echo ${unexec} | sed 's/\.o/.c/'`"
-
-# Do the opsystem or machine files prohibit the use of the GNU malloc?
-# Assume not, until told otherwise.
-GNU_MALLOC=yes
-if [ "${system_malloc}" = "yes" ]; then
- GNU_MALLOC=no
- GNU_MALLOC_reason="
- (The GNU allocators don't work with this system configuration.)"
-fi
-
-if [ x"${REL_ALLOC}" = x ]; then
- REL_ALLOC=${GNU_MALLOC}
-fi
-
-LISP_FLOAT_TYPE=yes
-
-
-#### Add the libraries to LIBS and check for some functions.
-
-]
-DEFS="$c_switch_system $c_switch_machine $DEFS"
-LIBS="$libsrc_libs"
-
-dnl If found, this defines HAVE_LIBDNET, which m/pmax.h checks,
-dnl and also adds -ldnet to LIBS, which Autoconf uses for checks.
-AC_HAVE_LIBRARY(-ldnet)
-dnl This causes -lresolv to get used in subsequent tests,
-dnl which causes failures on some systems such as HPUX 9.
-dnl AC_HAVE_LIBRARY(-lresolv)
-
-AC_HAVE_LIBRARY(-lXbsd, LD_SWITCH_X_SITE="$LD_SWITCH_X_SITE -lXbsd")
-
-echo checking for XFree86
-if test -d /usr/X386/include; then
- HAVE_XFREE386=yes
- test -z "${C_SWITCH_X_SITE}" && C_SWITCH_X_SITE="-I/usr/X386/include"
-fi
-
-# We change CFLAGS temporarily so that C_SWITCH_X_SITE gets used
-# for the tests that follow.
-
-if test "${HAVE_X11}" = "yes"; then
- DEFS="$C_SWITCH_X_SITE $DEFS"
- LIBS="$LD_SWITCH_X_SITE $LIBX $LIBS"
- CFLAGS="$C_SWITCH_X_SITE $CFLAGS"
- AC_HAVE_FUNCS(XrmSetDatabase XScreenResourceString \
-XScreenNumberOfScreen XSetWMProtocols)
-fi
-
-if test "${USE_X_TOOLKIT}" != "none"; then
- AC_COMPILE_CHECK(X11 toolkit version,
- [#include <X11/Intrinsic.h>],
- [
-#if XtSpecificationRelease < 6
-fail;
-#endif
-],
- AC_DEFINE(HAVE_X11XTR6))
-fi
-
-# If netdb.h doesn't declare h_errno, we must declare it by hand.
-AC_COMPILE_CHECK(declaration of h_errno in netdb.h,
- [#include <netdb.h>],
- [
-int
-foo ()
-{
- return h_errno;
-}
-],
- AC_DEFINE(HAVE_H_ERRNO))
-
-AC_ALLOCA
-
-# logb and frexp are found in -lm on most systems.
-AC_HAVE_LIBRARY(-lm)
-AC_HAVE_FUNCS(gettimeofday gethostname dup2 rename closedir mkdir rmdir \
-random lrand48 bcopy bcmp logb frexp fmod drem ftime res_init setsid \
-strerror fpathconf select mktime eaccess getpagesize)
-
-ok_so_far=true
-AC_FUNC_CHECK(socket, , ok_so_far=)
-if test -n "$ok_so_far"; then
- AC_HEADER_CHECK(netinet/in.h, , ok_so_far=)
-fi
-if test -n "$ok_so_far"; then
- AC_HEADER_CHECK(arpa/inet.h, , ok_so_far=)
-fi
-if test -n "$ok_so_far"; then
- AC_DEFINE(HAVE_INET_SOCKETS)
-fi
-
-# Set up the CFLAGS for real compilation, so we can substitute it.
-CFLAGS="$REAL_CFLAGS"
-
-[
-#### Find out which version of Emacs this is.
-version=`grep 'defconst[ ]*emacs-version' ${srcdir}/lisp/version.el \
- | sed -e 's/^[^"]*"\([^"]*\)".*$/\1/'`
-if [ x"${version}" = x ]; then
- echo "${progname}: can't find current emacs version in
- \`${srcdir}/lisp/version.el'." >&2
- exit 1
-fi
-
-if [ -f /usr/lpp/X11/bin/smt.exp ]; then
- ]
- AC_DEFINE(HAVE_AIX_SMT_EXP)
- [
-fi
-
-#### Specify what sort of things we'll be editing into Makefile and config.h.
-### Use configuration here uncanonicalized to avoid exceeding size limits.
-]
-AC_SUBST(version)
-AC_SUBST(configuration)
-AC_SUBST(canonical)
-AC_SUBST(srcdir)
-AC_SUBST(prefix)
-AC_SUBST(exec_prefix)
-AC_SUBST(bindir)
-AC_SUBST(datadir)
-AC_SUBST(sharedstatedir)
-AC_SUBST(libexecdir)
-AC_SUBST(mandir)
-AC_SUBST(infodir)
-AC_SUBST(lispdir)
-AC_SUBST(locallisppath)
-AC_SUBST(lisppath)
-AC_SUBST(etcdir)
-AC_SUBST(lockdir)
-AC_SUBST(archlibdir)
-AC_SUBST(docdir)
-AC_SUBST(bitmapdir)
-AC_SUBST(c_switch_system)
-AC_SUBST(c_switch_machine)
-AC_SUBST(LD_SWITCH_X_SITE)
-AC_SUBST(LD_SWITCH_X_SITE_AUX)
-AC_SUBST(C_SWITCH_X_SITE)
-AC_SUBST(CFLAGS)
-AC_SUBST(X_TOOLKIT_TYPE)
-AC_SUBST(machfile)
-AC_SUBST(opsysfile)
-
-AC_DEFINE_UNQUOTED(EMACS_CONFIGURATION, "\"${canonical}\"")
-AC_DEFINE_UNQUOTED(EMACS_CONFIG_OPTIONS, "\"${config_options}\"")
-AC_DEFINE_UNQUOTED(config_machfile, "\"${machfile}\"")
-AC_DEFINE_UNQUOTED(config_opsysfile, "\"${opsysfile}\"")
-AC_DEFINE_UNQUOTED(LD_SWITCH_X_SITE, ${LD_SWITCH_X_SITE})
-AC_DEFINE_UNQUOTED(LD_SWITCH_X_SITE_AUX, ${LD_SWITCH_X_SITE_AUX})
-AC_DEFINE_UNQUOTED(C_SWITCH_X_SITE, ${C_SWITCH_X_SITE})
-AC_DEFINE_UNQUOTED(UNEXEC_SRC, ${UNEXEC_SRC})
-
-[
-if [ "${HAVE_X_WINDOWS}" = "yes" ] ; then
- ] AC_DEFINE(HAVE_X_WINDOWS) [
-fi
-if [ "${USE_X_TOOLKIT}" != "none" ] ; then
- ] AC_DEFINE(USE_X_TOOLKIT) [
-fi
-if [ "${HAVE_X11}" = "yes" ] ; then
- ] AC_DEFINE(HAVE_X11) [
-fi
-if [ "${HAVE_XFREE386}" = "yes" ] ; then
- ] AC_DEFINE(HAVE_XFREE386) [
-fi
-if [ "${HAVE_X_MENU}" = "yes" ] ; then
- ] AC_DEFINE(HAVE_X_MENU) [
-fi
-if [ "${GNU_MALLOC}" = "yes" ] ; then
- ] AC_DEFINE(GNU_MALLOC) [
-fi
-if [ "${REL_ALLOC}" = "yes" ] ; then
- ] AC_DEFINE(REL_ALLOC) [
-fi
-if [ "${LISP_FLOAT_TYPE}" = "yes" ] ; then
- ] AC_DEFINE(LISP_FLOAT_TYPE) [
-fi
-
-# ====================== Developer's configuration =======================
-
-# The following assignments make sense if you're running Emacs on a single
-# machine, one version at a time, and you want changes to the lisp and etc
-# directories in the source tree to show up immediately in your working
-# environment. It saves a great deal of disk space by not duplicating the
-# lisp and etc directories.
-
-if [ "$run_in_place" = "1" ]; then
- lispdir='${srcdir}/lisp'
- locallisppath='${srcdir}/site-lisp'
- etcdir='${srcdir}/etc'
- lockdir='${srcdir}/lock'
- # We used to make archlibdir and docdir absolute,
- # but that caused trouble with automounters.
- archlibdir='${srcdir}/lib-src'
- docdir='${srcdir}/etc'
- infodir='${srcdir}/info'
-elif [ "$single_tree" = "1" ]; then
- if [ "$exec_prefix_specified" = "" ]; then
- exec_prefix='${prefix}'
- fi
- if [ "$bindir_specified" = "" ]; then
- bindir='${exec_prefix}/bin/${configuration}'
- fi
- if [ "$datadir_specified" = "" ]; then
- datadir='${prefix}/common'
- fi
- if [ "$sharedstatedir_specified" = "" ]; then
- sharedstatedir='${prefix}/common'
- fi
- if [ "$libexecdir_specified" = "" ]; then
- libexecdir='${bindir}'
- fi
- if [ "$lispdir_specified" = "" ]; then
- lispdir='${prefix}/common/lisp'
- fi
- if [ "$locallisppath_specified" = "" ]; then
- locallisppath='${prefix}/common/site-lisp'
- fi
- if [ "$lockdir_specified" = "" ]; then
- lockdir='${prefix}/common/lock'
- fi
- if [ "$archlibdir_specified" = "" ]; then
- archlibdir='${libexecdir}/etc'
- fi
- if [ "$etcdir_specified" = "" ]; then
- etcdir='${prefix}/common/data'
- fi
- if [ "$docdir_specified" = "" ]; then
- docdir='${prefix}/common/data'
- fi
-fi
-
-#### Report on what we decided to do.
-echo "
-
-Configured for \`${canonical}'.
-
- Where should the build process find the source code? ${srcdir}
- What operating system and machine description files should Emacs use?
- \`${opsysfile}' and \`${machfile}'
- What compiler should emacs be built with? ${CC} ${CFLAGS}
- Should Emacs use the GNU version of malloc? ${GNU_MALLOC}${GNU_MALLOC_reason}
- Should Emacs use the relocating allocator for buffers? ${REL_ALLOC}
- What window system should Emacs use? ${window_system}
- What toolkit should Emacs use? ${USE_X_TOOLKIT}${x_includes+
- Where do we find X Windows header files? }${x_includes}${x_libraries+
- Where do we find X Windows libraries? }${x_libraries}
-
-"
-
-# Remove any trailing slashes in these variables.
-test -n "${prefix}" &&
- prefix=`echo "${prefix}" | sed 's,\([^/]\)/*$,\1,'`
-test -n "${exec_prefix}" &&
- exec_prefix=`echo "${exec_prefix}" | sed 's,\([^/]\)/*$,\1,'`
-]
-AC_OUTPUT(Makefile lib-src/Makefile.in oldXMenu/Makefile lwlib/Makefile src/Makefile.in, [
-
-# Build src/Makefile from ${srcdir}/src/Makefile.in. This must be done
-# after src/config.h is built, since we rely on that file.
-
-changequote(,)dnl The horror, the horror.
-# Now get this: Some word that is part of the ${srcdir} directory name
-# or the ${configuration} value might, just might, happen to be an
-# identifier like `sun4' or `i386' or something, and be predefined by
-# the C preprocessor to some helpful value like 1, or maybe the empty
-# string. Needless to say consequent macro substitutions are less
-# than conducive to the makefile finding the correct directory.
-undefs="`echo $top_srcdir $configuration $canonical |
-sed -e 's/[^a-zA-Z0-9_]/ /g' -e 's/^/ /' -e 's/ *$//' \
- -e 's/ */ -U/g' -e 's/-U[0-9][^ ]*//g' \
-`"
-changequote([,])dnl
-
-echo creating lib-src/Makefile
-( cd lib-src
- rm -f junk.c junk1.c junk2.c
- sed -e '/start of cpp stuff/q' \
- < Makefile.in > junk1.c
- sed -e '1,/start of cpp stuff/d'\
- -e 's@/\*\*/#\(.*\)$@/* \1 */@' \
- < Makefile.in > junk.c
- $CPP $undefs -I. -I$top_srcdir/src $CPPFLAGS junk.c | \
- sed -e 's/^ / /' -e '/^#/d' -e '/^[ ]*$/d' > junk2.c
- cat junk1.c junk2.c > Makefile.new
- rm -f junk.c junk1.c junk2.c
- chmod 444 Makefile.new
- mv -f Makefile.new Makefile
-)
-
-echo creating src/Makefile
-( cd src
- rm -f junk.c junk1.c junk2.c
- sed -e '/start of cpp stuff/q' \
- < Makefile.in > junk1.c
- sed -e '1,/start of cpp stuff/d'\
- -e 's@/\*\*/#\(.*\)$@/* \1 */@' \
- < Makefile.in > junk.c
- $CPP $undefs -I. -I$top_srcdir/src $CPPFLAGS junk.c | \
- sed -e 's/^ / /' -e '/^#/d' -e '/^[ ]*$/d' > junk2.c
- cat junk1.c junk2.c > Makefile.new
- rm -f junk.c junk1.c junk2.c
- chmod 444 Makefile.new
- mv -f Makefile.new Makefile
-)])
diff --git a/etc/=MACHINES b/etc/=MACHINES
deleted file mode 100644
index eb86f4c1aa0..00000000000
--- a/etc/=MACHINES
+++ /dev/null
@@ -1,894 +0,0 @@
-This is a list of the status of GNU Emacs on various machines and systems.
-
-For each system and machine, we give the configuration name you should
-pass to the `configure' script to prepare to build Emacs for that
-system/machine.
-
-The `configure' script uses the configuration name to decide which
-machine and operating system description files `src/config.h' should
-include. The machine description files are all in `src/m', and have
-names similar to, but not identical to, the machine names used in
-configuration names. The operating system files are all in `src/s',
-and are named similarly. See the `configure' script if you need to
-know which configuration names use which machine and operating system
-description files.
-
-If you add support for a new configuration, add a section to this
-file, and then edit the `configure' script to tell it which
-configuration name(s) should select your new machine description and
-system description files.
-
-
-Here are the configurations Emacs is intended to work with, with the
-corresponding configuration names. You can postpend version numbers
-to operating system names (i.e. sunos4.1) or architecture names (i.e.
-hppa1.1). If you leave out the version number, the `configure' script
-will configure Emacs for the latest version it knows about.
-
-Alliant (fx80-alliant-bsd):
-
- 18.52 worked on system version 4. Previous Emacs versions were
- known to work on previous system versions.
-
- If you are using older versions of their operating system, you may
- need to edit `src/config.h' to use `m/alliant1.h' (on version 1) or
- `m/alliant.h' (on versions 2 and 3).
-
-Alliant FX/2800 (i860-alliant-bsd)
-
- Known to work with 18.58 and OS version 2.2, compiler version 1.3.
-
-Altos 3068 (m68k-altos-sysv)
-
- 18.52 was said to work, provided you don't compile unexec.c with -O.
-
-Amdahl UTS (580-amdahl-sysv)
-
- 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.
-
- The 5.2u370 compiler is so brain damaged that it is not
- even worth trying to use it. Success was obtained with the
- uts native C compiler on uts version 5.2.5.
-
-Apollo running Domain (m68k-apollo-bsd)
-
- 18.52 works, to some extent.
- Code for dumping Emacs has been written, but we cannot distribute it yet.
- There are reports of bugs in cc -O on this system.
-
- In `lib-src/Makefile', don't expect emacsclient and emacsserver to
- compile. You might want to remove them from your makefile.
-
- Supposedly something in dired.c runs into a compiler bug.
- Paraphrasing the statement should avoid the problem. I have not yet
- received word as to the exact statement this is.
-
- 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.
-
- 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.
-
-AT&T 3b2, 3b5, 3b15, 3b20 (we32k-att-sysv)
-
- Emacs will probably not work with certain kernel constants too small.
-
- In param.h CDLIMIT should be at least (1L << 12) in order to allow
- processes to write up to 2 Mbyte files. This parameter is configurable
- by normal means in /etc/master.d/kernel; examine that file for the
- symbol CDLIMIT or ULIMIT, and raise it by several powers of 2. Then
- do normal kernel rebuild things via "cd /boot; mkboot -k KERNEL" and so
- forth.
-
- In seg.h NSEGP and STACKSEG should be at least 16 and 4 respectively
- to allow processes with total size of up to 2Mbytes.
- However, I'm told it is unlikely this would fail to be true.
-
- The MAXMEM may also prevent Emacs from running. The file
- 3B-MAXMEM in this directory explains how to increase MAXMEM.
-
-AT&T 7300 or 3b1 (m68k-att-sysv)
-
- 18.52 worked. If you have strange troubles with dumping
- Emacs, delete the last few lines from `src/m/7300.h' and recompile.
- These lines are supposed to produce a sharable executable.
-
- `src/m/7300.h' defines SHORTNAMES because operating system versions
- 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 (m68k-bull-sysv)
-
- Changes partially merged in version 19, but some fixes are probably required.
-
-CCI 5/32, 6/32
-
- See "Tahoe".
-
-Celerity (celerity-celerity-bsd4.2)
-
- Version 18.49 worked. This configuration name is a hack, because we
- don't know the processor used by Celerities. If someone
- who uses a Celerity could get in touch with us, we can teach
- config.sub a better name for the configuration.
-
-Clipper (clipper-???)
-
- Version 19 has support for some brand of clipper system. If you
- have successfully built Emacs 19 on some sort of clipper system, let
- us know so we can flesh out this entry.
-
- Note that the Orion 105 is also a clipper, but some system-related
- parameters are different.
-
-Convex (c1-convex-bsd, c2-convex-bsd, c32-convex-bsd, c34-convex-bsd,
- c38-convex-bsd)
-
- 18.53 supposedly to work.
-
-Cubix QBx/386 (i386-cubix-sysv)
-
- Changes merged in 19.1. Systems before 2/A/0 may fail to compile etags.c
- due to a compiler bug.
-
-Cydra 5 (cydra-cydrome-sysv)
-
- 18.51 worked in one version of their operating system but stopped
- working in a newer version. This has not been fixed.
-
-DECstation (mips-dec-ultrix or mips-dec-osf)
-
- Version 19 works under Ultrix.
-
- See under Ultrix for problems using X windows on Ultrix.
- Note that this is a MIPS machine.
-
- For Ultrix versions 4.1 or earlier, you may need to define
- SYSTEM_MALLOC in `src/m/pmax.h', because XvmsAlloc.o in libX11.a seems
- to insist on defining malloc itself.
-
- For Ultrix versions prior to 4.0, you may need to delete
- the definition of START_FILES from `src/m/pmax.h'.
-
-Motorola Delta 147 (m68k-motorola-sysv)
-
- Motorola Delta boxes running System V/68 release 3.
- (tested on sys1147 with SVR3V5). Changes merged in 19.1.
-
-Motorola Delta 187 (m88k-motorola-sysv or m88k-motorola-m88kbcs)
-
- Machine support added in version 19.
- HAVE_X_MENU does not work due to lack of insque.
-
-Dual running System V (m68k-dual-sysv)
-
- As of 17.46, this worked except for a few changes
- needed in unexec.c.
-
-Dual running Uniplus (m68k-dual-uniplus)
-
- Worked, as of 17.51.
-
-Elxsi 6400 (elxsi-elxsi-sysv)
-
- Changes for 12.0 release are in 19.1.
- Dumping should work now.
-
-Encore machine (ns16k-encore-bsd)
-
- This machine bizarrely uses 4.2BSD modified to use the COFF format
- for object files. Works (as of 18.40). For the APC processor you
- must enable two lines at the end of `src/s/umax.h', which are commented
- out in the file as distributed.
-
- WARNING: If you compile Emacs with the "-O" compiler switch, you
- must also use the "-q enter_exits" switch so that all functions have
- stack frames. Otherwise routines that call `alloca' all lose.
-
- A kernel bug in some system versions causes input characters to be lost
- occasionally.
-
-GEC 63 (local-gec63-usg5.2)
-
- Changes are partially merged in version 18, but certainly require
- more work. Let us know if you get this working, and we'll give it a
- real configuration name.
-
-Gould Power Node (pn-gould-bsd4.2 or pn-gould-bsd4.3)
-
- 18.36 worked on versions 1.2 and 2.0 of the operating system.
-
- On UTX/32 2.0, use pn-gould-bsd4.3.
-
- On UTX/32 1.2 and UTX/32S 1.0, use pn-gould-bsd4.2 and note that
- compiling `lib-src/sorted-doc' tickles a compiler bug: remove the -g
- flag to cc in the makefile.
-
- UTX/32 1.3 has a bug in the bcopy library routine. Fix it by
- #undef BSTRING in `src/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 (np1-gould-bsd)
-
- Version 19 supposedly works.
-
-Honeywell XPS100 (xps100-honeywell-sysv)
-
- Config file added in version 19.
-
-HP 9000 series 200 or 300 (m68k-hp-bsd or m68k-hp-hpux7.)
-
- Version 19 works under BSD.
-
- 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 operating system suffix determines which system Emacs is built for.
-
- Series 200 HPUX runs Emacs only if it has the "HP-UX upgrade".
-
- 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.
-
- 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
- assembler and new function-entry sequence. You may need to define
- OLD_HP_ASSEMBLER if you are using an older hpux version. If you
- have an official (bought from HP) series 300 machine you have
- the new assembler. Kernels that are 5.+ or later have new
- assembler. A Series 200 that has been upgraded to a 68010
- processor and a 5.+ kernel has the new compiler.
-
- Define C_SWITCH_MACHINE to be +X to make a version of Emacs that
- runs on both 68010 and 68020 based hp-ux's.
-
- Define HPUX_68010 if you are using the new assembler, for
- a system that has a 68010 without a 68881. This is to say,
- a s200 (upgraded) or s310.
-
- Define the symbol HPUX_NET if you have the optional network features
- that include the `netunam' system call. This is refered to as
- Network Services (NS/9000) in HP literature.
-
-HP 9000 series 500: not supported.
-
- 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.
-
-HP 9000 series 800 (Spectrum) (hppa1.0-hp-hpux)
-
- These files support HP's Precision Architecture machines
- running HP-UX. It has been moderately tested on the Series
- 840.
-
- 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.
-
-High Level Hardware Orion (orion-highlevel-bsd)
-
- This is the original microprogrammed hardware.
- Machine description file ought to work.
-
-High Level Hardware Orion 1/05 (clipper-highlevel-bsd)
-
- 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'.
-
- C compiler has a bug; it loops compiling eval.c.
- Compile it by hand without optimization.
-
-IBM PS/2 (i386-ibm-aix1.1 or i386-ibm-aix1.2)
-
- Changes merged in version 19. You may need to copy
- /usr/lib/samples/hft/hftctl.c to the Emacs src directory.
-
- i386-ibm-aix1.1 may not work with certain new X window managers, and
- may be suboptimal.
-
-IBM RS/6000 (rs6000-ibm-aix)
-
- Changes merged in version 19. Currently the configuration
- does not actually depend on the version of AIX.
-
- Compiling with -O using the IBM compiler has been known
- to make Emacs work incorrectly.
-
-IBM RT/PC (romp-ibm-bsd or romp-ibm-aix)
-
- 18.52 worked on both operating systems.
- Use romp-ibm-bsd for the 4.2-like system and romp-ibm-aix for AIX.
-
- On BSD, if you have trouble, try compiling with a different compiler.
-
- On AIX, the file /usr/lib/samples/hft/hftctl.c must be compiled into
- hftctl.o, with this result left in the src directory (hftctl.c is
- part of the standard AIX distribution).
-
- window.c must not be compiled with -O on AIX.
-
-Integrated Solutions `Optimum V' (m68k-isi-bsd4.2 or -bsd4.3)
-
- 18.52 said to work on some sort of ISI machine.
- Version 18.45 worked (running on a Optimum V (VME bus, 68020)
- BSD 4.2 (3.05e) system). 18.42 is reported to work on
- a Qbus 68010 system. Has not been tried on `WorkStation' `Cluster
- Compute Node' `Cluster WorkStation' or `Server Node' (Love the
- StudLYCaps)
-
- Compilation with -O is rumored to break something.
-
- On recent system versions, you may need to undefine the macro UMAX
- in `lib-src/loadst.c' and `src/getpagesize.h'. They stupidly defined this
- in a system header file, which confuses Emacs (which thinks that UMAX
- indicates the Umax operating system).
-
-Intel 386 (i386-unknown-isc, i386-unknown-esix, i386-unknown-xenix,
- i386-intsys-sysv, i386-unknown-sysv5.2.2, i386-unknown-sysv5.3,
- and i386-unknown-bsd4.2)
-
- 18.58 should support a wide variety of operating systems.
- Make sure to use i386-unknown-isc2.2 for Interactive 386/ix version
- 2.2 or later.
- Use i386-unknown-esix for Esix.
- Use i386-intsys-sysv for Integrated Solutions 386 machines.
- It may also be correct for Microport systems.
- It isn't clear what to do on an SCO system. The system's C
- preprocessor doesn't seem to handle the src subdirectory's Make
- trickery, so you will probably need to install the GNU C preprocessor.
-
- If you are using Xenix, see notes above under Xenix.
-
- Some sysV.3 systems seem to have bugs in `opendir';
- for them, alter `config.h' to define NONSYSTEM_DIR_LIBRARY
- 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.
-
- On 386/ix, to link with shared libraries, add #define USG_SHARED_LIBRARIES
- to config.h.
-
- There is no consistency in the handling of certain system header files
- on V.3.
-
- Some versions have sys/sioctl.h, and require it in sysdep.c.
- But some versions do not have sys/sioctl.h.
- For a given version of the system, this may depend on whether you have
- X Windows or TCP/IP. Define or undefine NO_SIOCTL_H in config.h
- according to whether you have the file.
-
- Likewise, some versions have been known to need sys/ttold.h, sys/stream.h,
- and sys/ptem.h included in sysdep.c. If your system has these files,
- try defining NEED_PTEM_H in config.h if you have trouble without it.
-
- You may find that adding -I/usr/X/include or -I/usr/netinclude or both
- to CFLAGS avoids compilation errors on certain systems.
-
- 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.
-
-Iris 2500 and Iris 2500 Turbo (m68k-sgi-iris3.5 or m68k-sgi-iris3.6)
-
- Version 18 was said to work; use m68k-sgi-iris3.5 for system version 2.5
- and m68k-sgi-iris3.6 for system version 3.6.
- Note that the 3030 is the same as the Iris 2500 Turbo.
-
-Iris 4D (mips-sgi-irix3.3 or mips-sgi-irix4.0)
-
- 18.58 is known to work on Silicon Graphics 4D series machines
- with IRIX 3.3 or IRIX 4.0. Version 19 should support the
- ANSI C compiler version 3.10.
-
- 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.
-
- 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.
-
-Macintosh
-
- We are boycotting Apple because of Apple's efforts to take away
- our freedom to write compatible imitations of existing software.
- If you value your freedom to write such programs, we urge you
- not to buy from Apple, not to develop software for Apple, and
- certainly not to accept a job with Apple.
-
- See the file APPLE in this directory for more information.
-
-Masscomp (m68k-masscomp-rtu)
-
- 18.36 worked on a 5500DP running RTU v3.1a and compiler version 3.2
- with minor fixes that are included in 18.37. However, bizarre behavior
- was reported for 18.36 on a Masscomp (model and version unknown but probably
- a 68020 system). The report sounds like a compiler bug.
-
- A compiler bug affecting statements like
- unsigned char k; unsigned char *p;... x = p[k];
- has been reported for "C version 1.2 under RTU 3.1". We do not wish
- to take the time to install the numerous workarounds required to
- compensate for this bug; go complain to Masscomp.
-
- For RTU version 3.1, define FIRST_PTY_LETTER to be 'p' in `src/s/rtu.h'
- (or #undef and redefine it in config.h) so that ptys will be used.
-
- GNU Emacs is said to have no chance of compiling on RTU versions
- prior to v3.0.
-
-Megatest (m68k-megatest-bsd)
-
- Emacs 15 worked; do not have any reports about Emacs 16 or 17
- but any new bugs are probably not difficult.
-
-Mips (mips-mips-riscos, mips-mips-riscos4.0, or mips-mips-bsd)
-
- Changes merged in 18.39. Some fixes in 18.56.
-
- Use mips-mips-riscos4.0 for RISCOS version 4.
- Use mips-mips-bsd with the BSD world.
-
- Note that the proper configuration names for DECstations are
- mips-dec-ultrix and mips-dec-osf.
-
- 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.
-
-National Semiconductor 32000 (ns32k-ns-genix)
-
- This is for a complete machine from National Semiconductor,
- running Genix. Changes merged in version 19.
-
-NCR Tower 32 (m68k-ncr-sysv2 or m68k-ncr-sysv3)
-
- If you are running System V release 2, use m68k-ncr-sysv2.
- If you are running System V release 3, use m68k-ncr-sysv3.
-
- These both worked as of 18.56. If you change `src/ymakefile' so that
- CFLAGS includes C_OPTIMIZE_SWITCH rather than C_DEBUG_SWITCH, check
- out the comments in `src/m/tower32.h' (for System V release 2) or
- `src/m/tower32v3.h' (for System V release 3) about this.
-
- There is a report that compilation with -O did not work with 18.54
- under System V release 2.
-
-Nixdorf Targon 31 (m68k-nixdorf-sysv)
-
- Machine description file for version 17 is included in 18
- but whether it works is not known.
- `src/unexec.c' bombs if compiled with -O.
- Note that the "Targon 35" is really a Pyramid.
-
-Nu (TI or LMI) (m68k-nu-sysv)
-
- Version 18 is believed to work.
-
-Plexus (m68k-plexus-sysv)
-
- Worked as of 17.56.
-
-Pmax (DEC Mips) (mips-dec-ultrix or mips-dec-osf1)
-
- See under DECstation, above.
-
-Prime EXL (i386-prime-sysv)
-
- Minor changes merged in 19.1.
-
-Pyramid (pyramid-pyramid-bsd)
-
- 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 `src/m/pyramid.h':
- #define _longjmp longjmp
- #define _setjmp setjmp
-
- In Pyramid system 2.5 there has been a compiler bug making
- Emacs crash just after screen-splitting with Qnil containing 0.
- A compiler that fixes this is Pyramid customer number 8494,
- internal number 1923.
-
- Some versions of the pyramid compiler get fatal
- errors when the -gx compiler switch is used; if this
- happens to you, change `src/m/pyramid.h' to define
- C_DEBUG_SWITCH with an empty definition.
-
- 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 (ns32k-sequent-bsd4.2 or ns32k-sequent-bsd4.3)
-
- Emacs 18.51 worked on system version 3.0. 18.52 is said to work.
- Delete some lines at the end of `src/m/sequent.h' for earlier system
- versions.
-
-Sequent Symmetry (i386-sequent-bsd)
-
- Emacs 19 should work.
-
-SONY News (m68k-sony-bsd4.2 or m68k-sony-bsd4.3)
-
- 18.52 worked. Use m68k-sony-bsd4.3 for system release 3.
-
-SONY News 3000 series (RISC NEWS) (mips-sony-bsd)
-
- Worked, as of 18.56. Note that this is a MIPS architecture machine.
-
- 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.
-
-Stardent 1500 or 3000
-
- See Titan.
-
-Stride (m68k-stride-sysv)
-
- Works (most recent news for 18.30) on their release 2.0.
- For release 2.2, see the end of `src/m/stride.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 (m68k-sun-sunos, sparc-sun-sunos, i386-sun-sunos)
-
- It's important to include the SunOS version number in the
- configuration name. For example, for SunOS release 4.0 on a Sun 3,
- use `m68k-sun-sunos4.0'; for SunOS release 4.1 on a Sparc, use
- `sparc-sun-sunos4.1'.
-
- Use `m68k' for the 68000-based Sun boxes, `sparc' for Sparcstations,
- and `i386' for Sun Roadrunners.
-
- There are three machine files for the different versions of SunOS
- that run on the Motorola 68000 processors. All are derived from
- Berkeley 4.2. Emacs 17 has run on all of them.
-
- 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 want to use SunWindows, define HAVE_SUN_WINDOWS
- in config.h to enable a special interface called `emacstool'.
- The definition must *precede* the #include "machine.h".
- System version 3.2 is required for this facility to work.
-
- We recommend that you instead use the X window system, which
- has technical advantages, is an industry standard, and is also
- free software.
-
- If you are compiling for X windows, and the X window library was
- compiled to use the 68881, then you must edit config.h according
- the comments at the end of `src/m/sun3.h'.
-
- 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
- (now remapped as part of the text). These are never
- swapped in.
-
- To build a single Emacs that will run on Sun 2 and Sun 3
- HARDWARE, just build it on the Sun 2.
-
- Changes for the Sparc architecture were merged in 18.50. Some
- people say optimizing compilation does not work; some say that -O2
- (whatever that is) works perhaps with a small change.
-
- Changes for the Roadrunner architecture were merged in 18.51.
-
- There is a bug in the Export version of SunOS 4.0 shipped outsde the
- US; it has something to do with Pentagon export restrictions on the
- DES chips in Suns. The symptom 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
- cause cc -Bstatic to die with these 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, these may
- not be all of them. You will find them quick enough by trying to
- compile ANY C program, even one which does NOTHING.
-
-Tadpole 68K (m68k-tadpole-sysv)
-
- Changes merged in 19.1.
-
- 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 (tahoe-tahoe-bsd4.2 or tahoe-tahoe-bsd4.3)
-
- 18.52 was known to work on some Tahoes, but a compiler bug intervenes
- on others. Some Emacs versions have worked in Unisys 1r4
- (not in 1r3) and CCI I.21.
-
- If you have trouble compiling `lib-src/loadst.c', turn off the definition
- of DKSTAT_HEADER_FILE in `src/m/tahoe.h'.
-
-Tandem Integrity S2 (mips-tandem-sysv)
-
- Changes merged in 18.56 but subprocess support is turned off.
- You will probably want to see if you can make subprocesses work.
-
- You must edit `lib-src/Makefile' to define LOADLIBES = -mld.
-
-Tektronix 16000 box (6130?) (ns16k-tektronix-bsd)
-
- Emacs 17.61 worked.
-
-Tektronix 4300 (m68k-tektronix-bsd)
-
- Emacs 18.51 worked.
-
-Titan P2 or P3 (titan-titan-sysv)
-
- Changes probably merged in version 19.
-
-Ustation E30 (SS5E) (m68k-unisys-unipl)
-
- Changes merged in 18.52; don't know whether they work.
-
-Vaxen running Berkeley Unix (vax-dec-bsd4.1, vax-dec-bsd4.2, vax-dec-bsd4.3),
- Ultrix (vax-dec-ultrix),
- System V (vax-dec-sysv0, vax-dec-sysv2), or
- VMS (vax-dec-vms)
-
- Works.
-
- See under Ultrix for problems using X windows on Ultrix (vax-dec-ultrix).
-
- 18.27 worked on System V rel 2 (vax-dec-sysv2).
-
- 18.36 worked on System V rel 0 (vax-dec-sysv0).
-
- 18.36 was believed to work on VMS. Addition of features is necessary
- to make this Emacs version more usable.
-
-Whitechapel MG1 (ns16k-whitechapel-?)
-
- May work. Supposedly no changes were needed except in `src/m/mg1.h'
- file. I do not know what Unix version runs on them.
-
-Wicat (m68k-wicat-sysv)
-
- Changes merged as of 18.6; whether they work is unknown.
- See comments in `src/m/wicat.h' for things you should change
- depending on the system and compiler version you have.
-
-Here is a summary of the systems supported:
-
-Berkeley 4.1 (bsd4.1)
-
- Works on vaxes.
-
-Berkeley 4.2 (bsd4.2)
-
- Works on several machines.
-
-Berkeley 4.3 (bsd4.3)
-
- Works, on Vaxes at least.
-
-Microport
-
- See under "Intel 386".
-
-System V rel 0 (usg5.0)
-
- Works, on Vaxes and 3bxxx's.
- There are some problems in 18.37 due to shortnames/cccp problems:
- use the emacs 17 cpp if you have it.
-
-System V rel 2 (usg5.2)
-
- Works on various machines.
- On some (maybe all) machines the library -lPW exists and contains
- a version of `alloca'. On these machines, to use it, put
- #define HAVE_ALLOCA
- #define LIB_STANDARD -lPW -lc
- in the `src/m/MACHINENAME.h' file for the machine.
-
- If you find that the character Meta-DEL makes Emacs crash,
- find where function init_sys_modes in sysdep.c sets sg.c_cc[VQUIT]
- 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.
-
-System V rel 2.2 (usg5.2.2)
-
- In 5.2.2 AT&T undid, incompatibly, their previous incompatible
- change to the way the nlist library is called. A different s- file
- is used to enable the other interface.
-
- They call themselves the right choice--can't they choose?
-
- Emacs version 18 unexec is currently not working properly
- on 5.2.2. Nobody knows why yet. A workaround is to define
- NO_REMAP. It is not yet known whether this applies to all
- machines running 5.2.2.
-
-System V rel 3 (usg5.3)
-
- 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 want to link Emacs with shared libraries, define
- USG_SHARED_LIBRARIES.
-
- You may have to add ANSI idempotence #-lines to your sys/types.h
- file to get Emacs to compile correctly. This may be necessary on
- other pre-ANSI systems as well.
-
- On an AT&T 6386WGS using System V Release 3.2 and X11R3, the X support
- cannot be made to work. Whether or not the GNU relocating malloc is
- used, the symptom is that the first call Emacs makes to sbrk(0) returns
- (char *)-1. Sorry, you're stuck with character-only mode. Try
- installing Xfree86 to fix this.
-
-System V rel 4.0.3 and 4.0.4 (usg5.4)
-
- Supported, including shared libraries for ELF, but ptys do not work
- because TIOCGPGRP fails to work on ptys (but Dell 2.2 seems to have
- fixed this). 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.
-
- The standard C preprocessor may generate xmakefile incorrectly. However,
- /lib/cpp will work, so use `make CPP=/lib/cpp'. Standard cpp
- seems to work OK under Dell 2.2.
-
- Some 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, or is Dell's 2.2 (which is a 4.0.3).
- Unfortunately, the only way you can tell whether your X11 library is
- new enough is to try compiling Emacs to use X. If emacs runs, your
- X11 library is new enough.
-
- 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.
-
- 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, after the inclusion of s-usg5-4.h.
- (Any system that supports Internet should implement sockets.)
-
-Ultrix (bsd4.3)
-
- 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
- prevent XvmsAlloc.o in Xlib from being used. Israel Pinkas says:
-
- I added the following lines to config.h after the X defines:
-
- #if defined(ultrix) && defined(X11)
- #define OBJECTS_SYSTEM calloc.o
- #endif
-
- Then I ran the following:
-
- ar x /usr/lib/libc.a calloc.o
-
- The problem is said to be gone in UWS version 2.1.
-
-Uniplus 5.2 (unipl5.2)
-
- Works, on Dual machines at least.
-
-VMS (vmsM.N)
-
- The config file 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 ../vms/VMSINSTALL for info on moving
- Unix distributions to VMS, and other VMS-related topics.
-
-Xenix (xenix)
-
- Should work in 18.50, but you will need to edit the files
- `lib-src/Makefile' and `src/ymakefile'
- (see the comments that mention "Xenix" for what to change.)
- Compiling Emacs with -O is said not to work.
-
- If you want Emacs to work with Smail (installed as /usr/bin/smail)
- then add the line #define SMAIL to config.h.
-
- The file etc/XENIX suggests some useful things to do to Xenix
- to make the Emacs meta key work.
-
-Local variables:
-mode: text
-fill-prefix: " "
-End:
diff --git a/etc/=TO-DO b/etc/=TO-DO
deleted file mode 100644
index e5b9a49599b..00000000000
--- a/etc/=TO-DO
+++ /dev/null
@@ -1,83 +0,0 @@
-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.
-
-Long range:
-
- 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/=news.texi b/etc/=news.texi
deleted file mode 100644
index cad097889c0..00000000000
--- a/etc/=news.texi
+++ /dev/null
@@ -1,3380 +0,0 @@
-@setfilename LNEWS
-
-@section New Features in the Lisp Language
-
-@end itemize
-@itemize @bullet
-@item
-The new function @code{delete} is a traditional Lisp function. It takes
-two arguments, @var{elt} and @var{list}, and deletes from @var{list} any
-elements that are equal to @var{elt}. It uses the function @code{equal}
-to compare elements with @var{elt}.
-
-@item
-The new function @code{member} is a traditional Lisp function. It takes
-two arguments, @var{elt} and @var{list}, and finds the first element of
-@var{list} that is equal to @var{elt}. It uses the function
-@code{equal} to compare each list element with @var{elt}.
-
-The value is a sublist of @var{list}, whose first element is the one
-that was found. If no matching element is found, the value is
-@code{nil}.
-
-@ignore @c Seems not to be true, from looking at the code.
-@item
-The function @code{equal} is now more robust: it does not crash due to
-circular list structure.
-@end ignore
-
-@item
-The new function @code{indirect-function} finds the effective function
-definition of an object called as a function. If the object is a
-symbol, @code{indirect-function} looks in the function definition of the
-symbol. It keeps doing this until it finds something that is not a
-symbol.
-
-@item
-There are new escape sequences for use in character and string
-constants. The escape sequence @samp{\a} is equivalent to @samp{\C-g},
-the @sc{ASCII} @sc{BEL} character (code 7). The escape sequence
-@samp{\x} followed by a hexidecimal number represents the character
-whose @sc{ASCII} code is that number. There is no limit on the number
-of digits in the hexidecimal value.
-
-@item
-The function @code{read} when reading from a buffer now does not skip a
-terminator character that terminates a symbol. It leaves that character
-to be read (or just skipped, if it is whitespace) next time.
-
-@item
-When you use a function @var{function} as the input stream for
-@code{read}, it is usually called with no arguments, and should return
-the next character. In Emacs 19, sometimes @var{function} is called
-with one argument (always a character). When that happens,
-@var{function} should save the argument and arrange to return it when
-called next time.
-
-@item
-@code{random} with integer argument @var{n} returns a random number
-between 0 and @var{n}@minus{}1.
-
-@item
-The functions @code{documentation} and @code{documentation-property} now
-take an additional optional argument which, if non-@code{nil}, says to
-refrain from calling @code{substitute-command-keys}. This way, you get
-the exact text of the documentation string as written, without the usual
-substitutions. Make sure to call @code{substitute-command-keys}
-yourself if you decide to display the string.
-
-@ignore
-@item
-The new function @code{invocation-name} returns as a string the program
-name that was used to run Emacs, with any directory names discarded.
-@c ??? This hasn't been written yet. ???
-@end ignore
-
-@item
-The new function @code{map-y-or-n-p} makes it convenient to ask a series
-of similar questions. The arguments are @var{prompter}, @var{actor},
-@var{list}, and optional @var{help}.
-
-The value of @var{list} is a list of objects, or a function of no
-arguments to return either the next object or @code{nil} meaning there
-are no more.
-
-The argument @var{prompter} specifies how to ask each question. If
-@var{prompter} is a string, the question text is computed like this:
-
-@example
-(format @var{prompter} @var{object})
-@end example
-
-@noindent
-where @var{object} is the next object to ask about.
-
-If not a string, @var{prompter} should be a function of one argument
-(the next object to ask about) and should return the question text.
-
-The argument @var{actor} should be a function of one argument, which is
-called with each object that the user says yes for. Its argument is
-always one object from @var{list}.
-
-If @var{help} is given, it is a list @code{(@var{object} @var{objects}
-@var{action})}, where @var{object} is a string containing a singular
-noun that describes the objects conceptually being acted on;
-@var{objects} is the corresponding plural noun and @var{action} is a
-transitive verb describing @var{actor}. The default is @code{("object"
-"objects" "act on")}.
-
-Each time a question is asked, the user may enter @kbd{y}, @kbd{Y}, or
-@key{SPC} to act on that object; @kbd{n}, @kbd{N}, or @key{DEL} to skip
-that object; @kbd{!} to act on all following objects; @key{ESC} or
-@kbd{q} to exit (skip all following objects); @kbd{.} (period) to act on
-the current object and then exit; or @kbd{C-h} to get help.
-
-@code{map-y-or-n-p} returns the number of objects acted on.
-
-@item
-You can now ``set'' environment variables with the @code{setenv}
-command. This works by setting the variable @code{process-environment},
-which @code{getenv} now examines in preference to the environment Emacs
-received from its parent.
-@end itemize
-
-@section New Features for Loading Libraries
-
-You can now arrange to run a hook if a particular Lisp library is
-loaded.
-
-The variable @code{after-load-alist} is an alist of expressions to be
-evalled when particular files are loaded. Each element looks like
-@code{(@var{filename} @var{forms}@dots{})}.
-
-When @code{load} is run and the file name argument equals
-@var{filename}, the @var{forms} in the corresponding element are
-executed at the end of loading. @var{filename} must match exactly!
-Normally @var{filename} is the name of a library, with no directory
-specified, since that is how @code{load} is normally called.
-
-An error in @var{forms} does not undo the load, but does prevent
-execution of the rest of the @var{forms}.
-
-The function @code{eval-after-load} provides a convenient way to add
-entries to the alist. Call it with two arguments, @var{file} and a
-form to execute.
-
-The function @code{autoload} now supports autoloading a keymap.
-Use @code{keymap} as the fourth argument if the autoloaded function
-will become a keymap when loaded.
-
-There is a new feature for specifying which functions in a library should
-be autoloaded by writing special ``magic'' comments in that library itself.
-
- Write @samp{;;;###autoload} on a line by itself before a function
-definition before the real definition of the function, in its
-autoloadable source file; then the command @kbd{M-x
-update-file-autoloads} automatically puts the @code{autoload} call into
-@file{loaddefs.el}.
-
- You can also put other kinds of forms into @file{loaddefs.el}, by
-writing @samp{;;;###autoload} followed on the same line by the form.
-@kbd{M-x update-file-autoloads} copies the form from that line.
-
-@section Compilation Features
-
-@itemize @bullet
-@item
-Inline functions.
-
-You can define an @dfn{inline function} with @code{defsubst}. Use
-@code{defsubst} just like @code{defun}, and it defines a function which
-you can call in all the usual ways. Whenever the function thus defined
-is used in compiled code, the compiler will open code it.
-
-You can get somewhat the same effects with a macro, but a macro has the
-limitation that you can use it only explicitly; a macro cannot be called
-with @code{apply}, @code{mapcar} and so on. Also, it takes some work to
-convert an ordinary function into a macro. To convert it into an inline
-function, simply replace @code{defun} with @code{defsubst}.
-
-Making a function inline makes explicit calls run faster. But it also
-has disadvantages. For one thing, it reduces flexibility; if you change
-the definition of the function, calls already inlined still use the old
-definition until you recompile them.
-
-Another disadvantage is that making a large function inline can increase
-the size of compiled code both in files and in memory. Since the
-advantages of inline functions are greatest for small functions, you
-generally should not make large functions inline.
-
-Inline functions can be used and open coded later on in the same file,
-following the definition, just like macros.
-
-@item
-The command @code{byte-compile-file} now offers to save any buffer
-visiting the file you are compiling.
-
-@item
-The new command @code{compile-defun} reads, compiles and executes the
-defun containing point. If you use this on a defun that is actually a
-function definition, the effect is to install a compiled version of
-that function.
-
-@item
-Whenever you load a Lisp file or library, you now receive a warning if
-the directory contains both a @samp{.el} file and a @samp{.elc} file,
-and the @samp{.el} file is newer. This typically indicates that someone
-has updated the Lisp code but forgotten to recompile it, so the changes
-do not take effect. The warning is a reminder to recompile.
-
-@item
-The special form @code{eval-when-compile} marks the forms it contains to
-be evaluated at compile time @emph{only}. At top-level, this is
-analogous to the Common Lisp idiom @code{(eval-when (compile)
-@dots{})}. Elsewhere, it is similar to the Common Lisp @samp{#.} reader
-macro (but not when interpreting).
-
-If you're thinking of using this feature, we recommend you consider whether
-@code{provide} and @code{require} might do the job as well.
-
-@item
-The special form @code{eval-and-compile} is similar to
-@code{eval-when-compile}, but the whole form is evaluated both at
-compile time and at run time.
-
-If you're thinking of using this feature, we recommend you consider
-whether @code{provide} and @code{require} might do the job as well.
-
-@item
-Emacs Lisp has a new data type for byte-code functions. This makes
-them faster to call, and also saves space. Internally, a byte-code
-function object is much like a vector; however, the evaluator handles
-this data type specially when it appears as a function to be called.
-
-The printed representation for a byte-code function object is like that
-for a vector, except that it starts with @samp{#} before the opening
-@samp{[}. A byte-code function object must have at least four elements;
-there is no maximum number, but only the first six elements are actually
-used. They are:
-
-@table @var
-@item arglist
-The list of argument symbols.
-
-@item byte-code
-The string containing the byte-code instructions.
-
-@item constants
-The vector of constants referenced by the byte code.
-
-@item stacksize
-The maximum stack size this function needs.
-
-@item docstring
-The documentation string (if any); otherwise, @code{nil}.
-
-@item interactive
-The interactive spec (if any). This can be a string or a Lisp
-expression. It is @code{nil} for a function that isn't interactive.
-@end table
-
-The predicate @code{byte-code-function-p} tests whether a given object
-is a byte-code function.
-
-You can create a byte-code function object in a Lisp program
-with the function @code{make-byte-code}. Its arguments are the elements
-to put in the byte-code function object.
-
-You should not try to come up with the elements for a byte-code function
-yourself, because if they are inconsistent, Emacs may crash when you
-call the function. Always leave it to the byte compiler to create these
-objects; it, we hope, always makes the elements consistent.
-@end itemize
-
-@section Floating Point Numbers
-
-You can now use floating point numbers in Emacs, if you define the macro
-@code{LISP_FLOAT_TYPE} when you compile Emacs.
-
-The printed representation for floating point numbers requires either a
-decimal point surrounded by digits, or an exponent, or both. For
-example, @samp{1500.0}, @samp{15e2}, @samp{15.0e2} and @samp{1.5e3} are
-four ways of writing a floating point number whose value is 1500.
-
-The existing predicate @code{numberp} now returns @code{t} if the
-argument is any kind of number---either integer or floating. The new
-predicates @code{integerp} and @code{floatp} check for specific types of
-numbers.
-
-You can do arithmetic on floating point numbers with the ordinary
-arithmetic functions, @code{+}, @code{-}, @code{*} and @code{/}. If you
-call one of these functions with both integers and floating point
-numbers among the arguments, the arithmetic is done in floating point.
-The same applies to the numeric comparison functions such as @code{=}
-and @code{<}. The remainder function @code{%} does not accept floating
-point arguments, and neither do the bitwise boolean operations such as
-@code{logand} or the shift functions such as @code{ash}.
-
-There is a new arithmetic function, @code{abs}, which returns the absolute
-value of its argument. It handles both integers and floating point
-numbers.
-
-To convert an integer to floating point, use the function @code{float}.
-There are four functions to convert floating point numbers to integers;
-they differ in how they round. @code{truncate} rounds toward 0,
-@code{floor} rounds down, @code{ceil} rounds up, and @code{round}
-produces the nearest integer.
-
-You can use @code{logb} to extract the binary exponent of a floating
-point number. More precisely, it is the logarithm base 2, rounded down
-to an integer.
-
-Emacs has several new mathematical functions that accept any kind of
-number as argument, but always return floating point numbers.
-
-@table @code
-@item cos
-@findex cos
-@itemx sin
-@findex sin
-@itemx tan
-@findex tan
-Trigonometric functions.
-@item acos
-@findex acos
-@itemx asin
-@findex asin
-@itemx atan
-@findex atan
-Inverse trigonometric functions.
-@item exp
-@findex exp
-The exponential function (power of @var{e}).
-@item log
-@findex log
-Logarithm base @var{e}.
-@item expm1
-@findex expm1
-Power of @var{e}, minus 1.
-@item log1p
-@findex log1p
-Add 1, then take the logarithm.
-@item log10
-@findex log10
-Logarithm base 10
-@item expt
-@findex expt
-Raise @var{x} to power @var{y}.
-@item sqrt
-@findex sqrt
-The square root function.
-@end table
-
-The new function @code{string-to-number} now parses a string containing
-either an integer or a floating point number, returning the number.
-
-The @code{format} function now handles the specifications @samp{%e},
-@samp{%f} and @samp{%g} for printing floating point numbers; likewise
-@code{message}.
-
-The new variable @code{float-output-format} controls how Lisp prints
-floating point numbers. Its value should be @code{nil} or a string.
-
-If it is a string, it should contain a @samp{%}-spec like those accepted
-by @code{printf} in C, but with some restrictions. It must start with
-the two characters @samp{%.}. After that comes an integer which is the
-precision specification, and then a letter which controls the format.
-
-The letters allowed are @samp{e}, @samp{f} and @samp{g}. Use @samp{e}
-for exponential notation (@samp{@var{dig}.@var{digits}e@var{expt}}).
-Use @samp{f} for decimal point notation
-(@samp{@var{digits}.@var{digits}}). Use @samp{g} to choose the shorter
-of those two formats for the number at hand.
-
-The precision in any of these cases is the number of digits following
-the decimal point. With @samp{f}, a precision of 0 means to omit the
-decimal point. 0 is not allowed with @samp{f} or @samp{g}.
-
-A value of @code{nil} means to use the format @samp{%.20g}.
-
-No matter what the value of @code{float-output-format}, printing ensures
-that the result fits the syntax rules for a floating point number. If
-it doesn't fit (for example, if it looks like an integer), it is
-modified to fit. By contrast, the @code{format} function formats
-floating point numbers without requiring the output to fit the
-syntax rules for floating point number.
-
-@section New Features for Printing And Formatting Output
-
-@itemize @bullet
-@item
-The @code{format} function has a new feature: @samp{%S}. This print
-spec prints any kind of Lisp object, even a string, using its Lisp
-printed representation.
-
-By contrast, @samp{%s} prints everything without quotation.
-
-@item
-@code{prin1-to-string} now takes an optional second argument which says
-not to print the Lisp quotation characters. (In other words, to use
-@code{princ} instead of @code{prin1}.)
-
-@item
-The new variable @code{print-level} specifies the maximum depth of list
-nesting to print before cutting off all deeper structure. A value of
-@code{nil} means no limit.
-@end itemize
-
-@section Changes in Basic Editing Functions
-
-@itemize @bullet
-@item
-There are two new primitives for putting text in the kill ring:
-@code{kill-new} and @code{kill-append}.
-
-The function @code{kill-new} adds a string to the front of the kill ring.
-
-Use @code{kill-append} to add a string to a previous kill. The second
-argument @var{before-p}, if non-@code{nil}, says to add the string at
-the beginning; otherwise, it goes at the end.
-
-Both of these functions apply @code{interprogram-cut-function} to the
-entire string of killed text that ends up at the beginning of the kill
-ring.
-
-@item
-The new function @code{current-kill} rotates the yanking pointer in the
-kill ring by @var{n} places, and returns the text at that place in the
-ring. If the optional second argument @var{do-not-move} is
-non-@code{nil}, it doesn't actually move the yanking point; it just
-returns the @var{n}th kill forward. If @var{n} is zero, indicating a
-request for the latest kill, @code{current-kill} calls
-@code{interprogram-paste-function} (documented below) before consulting
-the kill ring.
-
-All Emacs Lisp programs should either use @code{current-kill},
-@code{kill-new}, and @code{kill-append} to manipulate the kill ring, or
-be sure to call @code{interprogram-paste-function} and
-@code{interprogram-cut-function} as appropriate.
-
-@item
-The variables @code{interprogram-paste-function} and
-@code{interprogram-cut-function} exist so that you can provide functions
-to transfer killed text to and from other programs.
-
-@item
-The @code{kill-region} function can now be used in read-only buffers.
-It beeps, but adds the region to the kill ring without deleting it.
-
-@item
-The new function @code{compare-buffer-substrings} lets you compare two
-substrings of the same buffer or two different buffers. Its arguments
-look like this:
-
-@example
-(compare-buffer-substrings @var{buf1} @var{beg1} @var{end1} @var{buf2} @var{beg2} @var{end2})
-@end example
-
-The first three arguments specify one substring, giving a buffer and two
-positions within the buffer. The last three arguments specify the other
-substring in the same way.
-
-The value is negative if the first substring is less, positive if the
-first is greater, and zero if they are equal. The absolute value of
-the result is one plus the index of the first different characters.
-
-@item
-Overwrite mode treats tab and newline characters specially. You can now
-turn off this special treatment by setting @code{overwrite-binary-mode}
-to @code{t}.
-
-@item
-Once the mark ``exists'' in a buffer, it normally never ceases to
-exist. However, it may become @dfn{inactive}. The variable
-@code{mark-active}, which is always local in all buffers, indicates
-whether the mark is active: non-@code{nil} means yes.
-
-A command can request deactivation of the mark upon return to the editor
-command loop by setting @code{deactivate-mark} to a non-@code{nil}
-value. Transient Mark mode works by causing the buffer modification
-primitives to set @code{deactivate-mark}.
-
-The variables @code{activate-mark-hook} and @code{deactivate-mark-hook}
-are normal hooks run, respectively, when the mark becomes active andwhen
-it becomes inactive. The hook @code{activate-mark-hook} is also run at
-the end of a command if the mark is active and the region may have
-changed.
-
-@item
-The function @code{move-to-column} now accepts a second optional
-argument @var{force}, in addition to @var{column}; if the requested
-column @var{column} is in the middle of a tab character and @var{force}
-is non-@code{nil}, @code{move-to-column} replaces the tab with the
-appropriate sequence of spaces so that it can place point exactly at
-@var{column}.
-
-@item
-The search functions when successful now return the value of point
-rather than just @code{t}. This affects the functions
-@code{search-forward}, @code{search-backward},
-@code{word-search-forward}, @code{word-search-backward},
-@code{re-search-forward}, and @code{re-search-backward}.
-
-@item
-When you do regular expression searching or matching, there is no longer
-a limit to how many @samp{\(@dots{}\)} pairs you can get information
-about with @code{match-beginning} and @code{match-end}. Also, these
-parenthetical groupings may now be nested to any degree.
-
-@item
-The new special form @code{save-match-data} preserves the regular
-expression match status. Usage: @code{(save-match-data
-@var{body}@dots{})}.
-
-@item
-The function @code{translate-region} applies a translation table to the
-characters in a part of the buffer. Invoke it as
-@code{(translate-region @var{start} @var{end} @var{table})}; @var{start}
-and @var{end} bound the region to translate.
-
-The translation table @var{table} is a string; @code{(aref @var{table}
-@var{ochar})} gives the translated character corresponding to
-@var{ochar}. If the length of @var{table} is less than 256, any
-characters with codes larger than the length of @var{table} are not
-altered by the translation.
-
-@code{translate-region} returns the number of characters which were
-actually changed by the translation. This does not count characters
-which were mapped into themselves in the translation table.
-
-@item
-There are two new hook variables that let you notice all changes in all
-buffers (or in a particular buffer, if you make them buffer-local):
-@code{before-change-function} and @code{after-change-function}.
-
-If @code{before-change-function} is non-@code{nil}, then it is called
-before any buffer modification. Its arguments are the beginning and end
-of the region that is going to change, represented as integers. The
-buffer that's about to change is always the current buffer.
-
-If @code{after-change-function} is non-@code{nil}, then it is called
-after any buffer modification. It takes three arguments: the beginning
-and end of the region just changed, and the length of the text that
-existed before the change. (To get the current length, subtract the
-rrgion beginning from the region end.) All three arguments are
-integers. The buffer that's about to change is always the current
-buffer.
-
-Both of these variables are temporarily bound to @code{nil} during the
-time that either of these hooks is running. This means that if one of
-these functions changes the buffer, that change won't run these
-functions. If you do want hooks to be run recursively, write your hook
-functions to bind these variables back to their usual values.
-
-@item
-The hook @code{first-change-hook} is run using @code{run-hooks} whenever
-a buffer is changed that was previously in the unmodified state.
-
-@item
-The second argument to @code{insert-abbrev-table-description} is
-now optional.
-@end itemize
-
-@section Text Properties
-
- Each character in a buffer or a string can have a @dfn{text property
-list}, much like the property list of a symbol. The properties belong
-to a particular character at a particular place, such as, the letter
-@samp{T} at the beginning of this sentence. Each property has a name,
-which is usually a symbol, and an associated value, which can be any
-Lisp object---just as for properties of symbols (@pxref{Property Lists}).
-
- You can use the property @code{face-code} to control the font and
-color of text. That is the only property name which currently has a
-special meaning, but you can create properties of any name and examine
-them later for your own purposes.
-
- Copying text between strings and buffers preserves the properties
-along with the characters; this includes such diverse functions as
-@code{substring}, @code{insert}, and @code{buffer-substring}.
-
- Since text properties are considered part of the buffer contents,
-changing properties in a buffer ``modifies'' the buffer, and you can
-also undo such changes.
-
- Strings with text properties have a special printed representation
-which describes all the properties. This representation is also the
-read syntax for such a string. It looks like this:
-
-@example
-#("@var{characters}" @var{property-data}...)
-@end example
-
-@noindent
-where @var{property-data} is zero or more elements in groups of three as
-follows:
-
-@example
-@var{beg} @var{end} @var{plist}
-@end example
-
-@noindent
-The elements @var{beg} and @var{end} are integers, and together specify
-a portion of the string; @var{plist} is the property list for that
-portion.
-
-@subsection Examining Text Properties
-
- The simplest way to examine text properties is to ask for the value of
-a particular property of a particular character. For that, use
-@code{get-text-property}. Use @code{text-properties-at} to get the
-entire property list of a character. @xref{Property Search}, for
-functions to examine the properties of a number of characters at once.
-
-@code{(get-text-property @var{pos} @var{prop} @var{object})} returns the
-@var{prop} property of the character after @var{pos} in @var{object} (a
-buffer or string). The argument @var{object} is optional and defaults
-to the current buffer.
-
-@code{(text-properties-at @var{pos} @var{object})} returns the entire
-property list of the character after @var{pos} in the string or buffer
-@var{object} (which defaults to the current buffer).
-
-@subsection Changing Text Properties
-
- There are three primitives for changing properties of a specified
-range of text:
-
-@table @code
-@item add-text-properties
-This function puts on specified properties, leaving other existing
-properties unaltered.
-
-@item put-text-property
-This function puts on a single specified property, leaving others
-unaltered.
-
-@item remove-text-properties
-This function removes specified properties, leaving other
-properties unaltered.
-
-@item set-text-properties
-This function replaces the entire property list, leaving no vessage of
-the properties that that text used to have.
-@end table
-
-All these functions take four arguments: @var{start}, @var{end},
-@var{props}, and @var{object}. The last argument is optional and
-defaults to the current buffer. The argument @var{props} has the form
-of a property list.
-
-@subsection Property Search Functions
-
-In typical use of text properties, most of the time several or many
-consecutive characters have the same value for a property. Rather than
-writing your programs to examine characters one by one, it is much
-faster to process chunks of text that have the same property value.
-
-The functions @code{next-property-change} and
-@code{previous-property-change} scan forward or backward from position
-@var{pos} in @var{object}, looking for a change in any property between
-two characters scanned. They returns the position between those two
-characters, or @code{nil} if no change is found.
-
-The functions @code{next-single-property-change} and
-@code{previous-single-property-change} are similar except that you
-specify a particular property and they look for changes in the value of
-that property only. The property is the second argument, and
-@var{object} is third.
-
-@subsection Special Properties
-
- If a character has a @code{category} property, we call it the
-@dfn{category} of the character. It should be a symbol. The properties
-of the symbol serve as defaults for the properties of the character.
-
- You can use the property @code{face-code} to control the font and
-color of text. That is the only property name which currently has a
-special meaning, but you can create properties of any name and examine
-them later for your own purposes.
-about face codes.
-
- You can specify a different keymap for a portion of the text by means
-of a @code{local-map} property. The property's value, for the character
-after point, replaces the buffer's local map.
-
- If a character has the property @code{read-only}, then modifying that
-character is not allowed. Any command that would do so gets an error.
-
- If a character has the property @code{modification-hooks}, then its
-value should be a list of functions; modifying that character calls all
-of those functions. Each function receives two arguments: the beginning
-and end of the part of the buffer being modified. Note that if a
-particular modification hook function appears on several characters
-being modified by a single primitive, you can't predict how many times
-the function will be called.
-
- Insertion of text does not, strictly speaking, change any existing
-character, so there is a special rule for insertion. It compares the
-@code{read-only} properties of the two surrounding characters; if they
-are @code{eq}, then the insertion is not allowed. Assuming insertion is
-allowed, it then gets the @code{modification-hooks} properties of those
-characters and calls all the functions in each of them. (If a function
-appears on both characters, it may be called once or twice.)
-
- The special properties @code{point-entered} and @code{point-left}
-record hook functions that report motion of point. Each time point
-moves, Emacs compares these two property values:
-
-@itemize @bullet
-@item
-the @code{point-left} property of the character after the old location,
-and
-@item
-the @code{point-entered} property of the character after the new
-location.
-@end itemize
-
-@noindent
-If these two values differ, each of them is called (if not @code{nil})
-with two arguments: the old value of point, and the new one.
-
- The same comparison is made for the characters before the old and new
-locations. The result may be to execute two @code{point-left} functions
-(which may be the same function) and/or two @code{point-entered}
-functions (which may be the same function). The @code{point-left}
-functions are always called before the @code{point-entered} functions.
-
- A primitive function may examine characters at various positions
-without moving point to those positions. Only an actual change in the
-value of point runs these hook functions.
-
-@section New Features for Files
-
-@itemize @bullet
-@item
-The new function @code{file-accessible-directory-p} tells you whether
-you can open files in a particular directory. Specify as an argument
-either a directory name or a file name which names a directory file.
-The function returns @code{t} if you can open existing files in that
-directory.
-
-@item
-The new function @code{file-executable-p} returns @code{t} if its
-argument is the name of a file you have permission to execute.
-
-@item
-The function @code{file-truename} returns the ``true name'' of a
-specified file. This is the name that you get by following symbolic
-links until none remain. The argument must be an absolute file name.
-
-@item
-New functions @code{make-directory} and @code{delete-directory} create and
-delete directories. They both take one argument, which is the name of
-the directory as a file.
-
-@item
-The function @code{read-file-name} now takes an additional argument
-which specifies an initial file name. If you specify this argument,
-@code{read-file-name} inserts it along with the directory name. It puts
-the cursor between the directory and the initial file name.
-
-The user can then use the initial file name unchanged, modify it, or
-simply kill it with @kbd{C-k}.
-
-If the variable @code{insert-default-directory} is @code{nil}, then the
-default directory is not inserted, and the new argument is ignored.
-
-@item
-The function @code{file-relative-name} does the inverse of
-expansion---it tries to return a relative name which is equivalent to
-@var{filename} when interpreted relative to @var{directory}. (If such a
-relative name would be longer than the absolute name, it returns the
-absolute name instead.)
-
-@item
-The function @code{file-newest-backup} returns the name of the most
-recent backup file for @var{filename}, or @code{nil} that file has no
-backup files.
-
-@item
-The list returned by @code{file-attributes} now has 12 elements. The
-12th element is the file system number of the file system that the file
-is in. This element together with the file's inode number, which is the
-11th element, give enough information to distinguish any two files on
-the system---no two files can have the same values for both of these
-numbers.
-
-@item
-The new function @code{set-visited-file-modtime} updates the current
-buffer's recorded modification time from the visited file's time.
-
-This is useful if the buffer was not read from the file normally, or
-if the file itself has been changed for some known benign reason.
-
-If you give the function an argument, that argument specifies the new
-value for the recorded modification time. The argument should be a list
-of the form @code{(@var{high} . @var{low})} or @code{(@var{high}
-@var{low})} containing two integers, each of which holds 16 bits of the
-time. (This is the same format that @code[file-attributes} uses to
-return time values.)
-
-The new function @code{visited-file-modtime} returns the recorded last
-modification time, in that same format.
-
-@item
-The function @code{directory-files} now takes an optional fourth
-argument which, if non-@code{nil}, inhibits sorting the file names.
-Use this if you want the utmost possible speed and don't care what order
-the files are processed in.
-
-If the order of processing is at all visible to the user, then the user
-will probably be happier if you do sort the names.
-
-@item
-The variable @code{directory-abbrev-alist} contains an alist of
-abbreviations to use for file directories. Each element has the form
-@code{(@var{from} . @var{to})}, and says to replace @var{from} with
-@var{to} when it appears in a directory name. This replacement is done
-when setting up the default directory of a newly visited file. The
-@var{from} string is actually a regular expression; it should always
-start with @samp{^}.
-
-You can set this variable in @file{site-init.el} to describe the
-abbreviations appropriate for your site.
-
-@item
-The function @code{abbreviate-file-name} applies abbreviations from
-@code{directory-abbrev-alist} to its argument, and substitutes @samp{~}
-for the user's home directory.
-
-Abbreviated directory names are useful for directories that are normally
-accessed through symbolic links. If you think of the link's name as
-``the name'' of the directory, you can define it as an abbreviation for
-the directory's official name; then ordinarily Emacs will call that
-directory by the link name you normally use.
-
-@item
-@code{write-region} can write a given string instead of text from the
-buffer. Use the string as the first argument (in place of the
-starting character position).
-
-You can supply a second file name as the fifth argument (@var{visit}).
-Use this to write the data to one file (the first argument,
-@var{filename}) while nominally visiting a different file (the fifth
-argument, @var{visit}). The argument @var{visit} is used in the echo
-area message and also for file locking; @var{visit} is stored in
-@code{buffer-file-name}.
-
-@item
-The value of @code{write-file-hooks} does not change when you switch to
-a new major mode. The intention is that these hooks have to do with
-where the file came from, and not with what it contains.
-
-@item
-There is a new hook variable for saving files:
-@code{write-contents-hooks}. It works just like @code{write-file-hooks}
-except that switching to a new major mode clears it back to @code{nil}.
-Major modes should use this hook variable rather than
-@code{write-file-hooks}.
-
-@item
-The hook @code{after-save-hook} runs just after a buffer has been saved
-in its visited file.
-
-@item
-The new function @code{set-default-file-modes} sets the file protection
-for new files created with Emacs. The argument must be an integer. (It
-would be better to permit symbolic arguments like the @code{chmod}
-program, but that would take more work than this function merits.)
-
-Use the new function @code{default-file-modes} to read the current
-default file mode.
-
-@item
-Call the new function @code{unix-sync} to force all pending disk output
-to happen as soon as possible.
-@end itemize
-
-@section Making Certain File Names ``Magic''
-
-You can implement special handling for a class of file names. You must
-supply a regular expression to define the class of names (all those
-which match the regular expression), plus a handler that implements all
-the primitive Emacs file operations for file names that do match.
-
-The value of @code{file-name-handler-alist} is a list of handlers,
-together with regular expressions that decide when to apply each
-handler. Each element has the form @code{(@var{regexp}
-. @var{handler})}. If a file name matches @var{regexp}, then all work
-on that file is done by calling @var{handler}.
-
-All the Emacs primitives for file access and file name transformation
-check the given file name against @code{file-name-handler-alist}, and
-call @var{handler} to do the work if appropriate. The first argument
-given to @var{handler} is the name of the primitive; the remaining
-arguments are the arguments that were passed to that primitive. (The
-first of these arguments is typically the file name itself.) For
-example, if you do this:
-
-@example
-(file-exists-p @var{filename})
-@end example
-
-@noindent
-and @var{filename} has handler @var{handler}, then @var{handler} is
-called like this:
-
-@example
-(funcall @var{handler} 'file-exists-p @var{filename})
-@end example
-
-Here are the primitives that you can handle in this way:
-
-@quotation
-@code{add-name-to-file}, @code{copy-file}, @code{delete-directory},
-@code{delete-file}, @code{directory-file-name}, @code{directory-files},
-@code{dired-compress-file}, @code{dired-uncache},
-@code{expand-file-name}, @code{file-accessible-directory-p},
-@code{file-attributes}, @code{file-directory-p},
-@code{file-executable-p}, @code{file-exists-p}, @code{file-local-copy},
-@code{file-modes}, @code{file-name-all-completions},
-@code{file-name-as-directory}, @code{file-name-completion},
-@code{file-name-directory}, @code{file-name-nondirectory},
-@code{file-name-sans-versions}, @code{file-newer-than-file-p},
-@code{file-readable-p}, @code{file-symlink-p}, @code{file-writable-p},
-@code{insert-directory}, @code{insert-file-contents},
-@code{make-directory}, @code{make-symbolic-link}, @code{rename-file},
-@code{set-file-modes}, @code{verify-visited-file-modtime},
-@code{write-region}.
-@end quotation
-
-The handler function must handle all of the above operations, and
-possibly others to be added in the future. Therefore, it should always
-reinvoke the ordinary Lisp primitive when it receives an operation it
-does not recognize. Here's one way to do this:
-
-@smallexample
-(defun my-file-handler (primitive &rest args)
- ;; @r{First check for the specific operations}
- ;; @r{that we have special handling for.}
- (cond ((eq operation 'insert-file-contents) @dots{})
- ((eq operation 'write-region) @dots{})
- @dots{}
- ;; @r{Handle any operation we don't know about.}
- (t (let (file-name-handler-alist)
- (apply operation args)))))
-@end smallexample
-
-The function @code{file-local-copy} copies file @var{filename} to the
-local site, if it isn't there already. If @var{filename} specifies a
-``magic'' file name which programs outside Emacs cannot directly read or
-write, this copies the contents to an ordinary file and returns that
-file's name.
-
-If @var{filename} is an ordinary file name, not magic, then this function
-does nothing and returns @code{nil}.
-
-The function @code{unhandled-file-name-directory} is used to get a
-non-magic directory name from an arbitrary file name. It uses the
-directory part of the specified file name if that is not magic.
-Otherwise, it asks the file name's handler what to do.
-
-@section Frames
-@cindex frame
-
-Emacs now supports multiple X windows via a new data type known as a
-@dfn{frame}.
-
-A frame is a rectangle on the screen that contains one or more Emacs
-windows. Subdividing a frame works just like subdividing the screen in
-earlier versions of Emacs.
-
-@cindex terminal frame
-There are two kinds of frames: terminal frames and X window frames.
-Emacs creates one terminal frame when it starts up with no X display; it
-uses Termcap or Terminfo to display using characters. There is no way
-to create another terminal frame after startup. If Emacs has an X
-display, it does not make a terminal frame, and there is none.
-
-@cindex X window frame
-When you are using X windows, Emacs starts out with a single X window
-frame. You can create any number of X window frames using
-@code{make-frame}.
-
-Use the predicate @code{framep} to determine whether a given Lisp object
-is a frame.
-
-The function @code{redraw-frame} redisplays the entire contents of a
-given frame.
-
-@subsection Creating and Deleting Frames
-
-Use @code{make-frame} to create a new frame (supported under X Windows
-only). This is the only primitive for creating frames.
-
-@code{make-frame} takes just one argument, which is an alist
-specifying frame parameters. Any parameters not mentioned in the
-argument alist default based on the value of @code{default-frame-alist};
-parameters not specified there default from the standard X defaults file
-and X resources.
-
-When you invoke Emacs, if you specify arguments for window appearance
-and so forth, these go into @code{default-frame-alist} and that is how
-they have their effect.
-
-You can specify the parameters for the initial startup X window frame by
-setting @code{initial-frame-alist} in your @file{.emacs} file. If these
-parameters specify a separate minibuffer-only frame, and you have not
-created one, Emacs creates one for you, using the parameter values
-specified in @code{minibuffer-frame-alist}.
-
-You can specify the size and position of a frame using the frame
-parameters @code{left}, @code{top}, @code{height} and @code{width}. You
-must specify either both size parameters or neither. You must specify
-either both position parameters or neither. The geometry parameters
-that you don't specify are chosen by the window manager in its usual
-fashion.
-
-The function @code{x-parse-geometry} converts a standard X windows
-geometry string to an alist which you can use as part of the argument to
-@code{make-frame}.
-
-Use the function @code{delete-frame} to eliminate a frame. Frames are
-like buffers where deletion is concerned; a frame actually continues to
-exist as a Lisp object until it is deleted @emph{and} there are no
-references to it, but once it is deleted, it has no further effect on
-the screen.
-
-The function @code{frame-live-p} returns non-@code{nil} if the argument
-(a frame) has not been deleted.
-
-@subsection Finding All Frames
-
-The function @code{frame-list} returns a list of all the frames that have
-not been deleted. It is analogous to @code{buffer-list}. The list that
-you get is newly created, so modifying the list doesn't have any effect
-on the internals of Emacs. The function @code{visible-frame-list} returns
-the list of just the frames that are visible.
-
-@code{next-frame} lets you cycle conveniently through all the frames from an
-arbitrary starting point. Its first argument is a frame. Its second
-argument @var{minibuf} says what to do about minibuffers:
-
-@table @asis
-@item @code{nil}
-Exclude minibuffer-only frames.
-@item a window
-Consider only the frames using that particular window as their
-minibuffer.
-@item anything else
-Consider all frames.
-@end table
-
-@subsection Frames and Windows
-
-All the non-minibuffer windows in a frame are arranged in a tree of
-subdivisions; the root of this tree is available via the function
-@code{frame-root-window}. Each window is part of one and only one
-frame; you can get the frame with @code{window-frame}.
-
-At any time, exactly one window on any frame is @dfn{selected within the
-frame}. You can get the frame's current selected window with
-@code{frame-selected-window}. The significance of this designation is
-that selecting the frame selects for Emacs as a whole the window
-currently selected within that frame.
-
-Conversely, selecting a window for Emacs with @code{select-window} also
-makes that window selected within its frame.
-
-@subsection Frame Visibility
-
-A frame may be @dfn{visible}, @dfn{invisible}, or @dfn{iconified}. If
-it is invisible, it doesn't show in the screen, not even as an icon.
-You can set the visibility status of a frame with
-@code{make-frame-visible}, @code{make-frame-invisible}, and
-@code{iconify-frame}. You can examine the visibility status with
-@code{frame-visible-p}---it returns @code{t} for a visible frame,
-@code{nil} for an invisible frame, and @code{icon} for an iconified
-frame.
-
-@subsection Selected Frame
-
-At any time, one frame in Emacs is the @dfn{selected frame}. The selected
-window always resides on the selected frame.
-
-@defun selected-frame
-This function returns the selected frame.
-@end defun
-
-The X server normally directs keyboard input to the X window that the
-mouse is in. Some window managers use mouse clicks or keyboard events
-to @dfn{shift the focus} to various X windows, overriding the normal
-behavior of the server.
-
-Lisp programs can switch frames ``temporarily'' by calling the function
-@code{select-frame}. This does not override the window manager; rather,
-it escapes from the window manager's control until that control is
-somehow reasserted. The function takes one argument, a frame, and
-selects that frame. The selection lasts until the next time the user
-does something to select a different frame, or until the next time this
-function is called.
-
-Emacs cooperates with the X server and the window managers by arranging
-to select frames according to what the server and window manager ask
-for. It does so by generating a special kind of input event, called a
-@dfn{focus} event. The command loop handles a focus event by calling
-@code{internal-select-frame}. @xref{Focus Events}.
-
-@subsection Frame Size and Position
-
-The new functions @code{frame-height} and @code{frame-width} return the
-height and width of a specified frame (or of the selected frame),
-measured in characters.
-
-The new functions @code{frame-pixel-height} and @code{frame-pixel-width}
-return the height and width of a specified frame (or of the selected
-frame), measured in pixels.
-
-The new functions @code{frame-char-height} and @code{frame-char-width}
-return the height and width of a character in a specified frame (or in
-the selected frame), measured in pixels.
-
-@code{set-frame-size} sets the size of a frame, measured in characters;
-its arguments are @var{frame}, @var{cols} and @var{rows}. To set the
-size with values measured in pixels, you can use
-@code{modify-frame-parameters}.
-
-The function @code{set-frame-position} sets the position of the top left
-corner of a frame. Its arguments are @var{frame}, @var{left} and
-@var{top}.
-
-@ignore
-New functions @code{set-frame-height} and @code{set-frame-width} set the
-size of a specified frame. The frame is the first argument; the size is
-the second.
-@end ignore
-
-@subsection Frame Parameters
-
-A frame has many parameters that affect how it displays. Use the
-function @code{frame-parameters} to get an alist of all the parameters
-of a given frame. To alter parameters, use
-@code{modify-frame-parameters}, which takes two arguments: the frame to
-modify, and an alist of parameters to change and their new values. Each
-element of @var{alist} has the form @code{(@var{parm} . @var{value})},
-where @var{parm} is a symbol. Parameters that aren't meaningful are
-ignored. If you don't mention a parameter in @var{alist}, its value
-doesn't change.
-
-Just what parameters a frame has depends on what display mechanism it
-uses. Here is a table of the parameters of an X
-window frame:
-
-@table @code
-@item name
-The name of the frame.
-
-@item left
-The screen position of the left edge.
-
-@item top
-The screen position of the top edge.
-
-@item height
-The height of the frame contents, in pixels.
-
-@item width
-The width of the frame contents, in pixels.
-
-@item window-id
-The number of the X window for the frame.
-
-@item minibuffer
-Whether this frame has its own minibuffer.
-@code{t} means yes, @code{none} means no,
-@code{only} means this frame is just a minibuffer,
-a minibuffer window (in some other frame)
-means the new frame uses that minibuffer.
-
-@item font
-The name of the font for the text.
-
-@item foreground-color
-The color to use for the inside of a character.
-Use strings to designate colors;
-X windows defines the meaningful color names.
-
-@item background-color
-The color to use for the background of text.
-
-@item mouse-color
-The color for the mouse cursor.
-
-@item cursor-color
-The color for the cursor that shows point.
-
-@item border-color
-The color for the border of the frame.
-
-@item cursor-type
-The way to display the cursor. There are two legitimate values:
-@code{bar} and @code{box}. The value @code{bar} specifies a vertical
-bar between characters as the cursor. The value @code{box} specifies an
-ordinary black box overlaying the character after point; that is the
-default.
-
-@item icon-type
-Non-@code{nil} for a bitmap icon, @code{nil} for a text icon.
-
-@item border-width
-The width in pixels of the window border.
-
-@item internal-border-width
-The distance in pixels between text and border.
-
-@item auto-raise
-Non-@code{nil} means selecting the frame raises it.
-
-@item auto-lower
-Non-@code{nil} means deselecting the frame lowers it.
-
-@item vertical-scrollbar
-Non-@code{nil} gives the frame a scroll bar
-for vertical scrolling.
-
-@item horizontal-scrollbar
-Non-@code{nil} gives the frame a scroll bar
-for horizontal scrolling.
-@end table
-
-@subsection Minibufferless Frames
-
-Normally, each frame has its own minibuffer window at the bottom, which
-is used whenever that frame is selected. However, you can also create
-frames with no minibuffers. These frames must use the minibuffer window
-of some other frame.
-
-The variable @code{default-minibuffer-frame} specifies where to find a
-minibuffer for frames created without minibuffers of their own. Its
-value should be a frame which does have a minibuffer.
-
-You can also specify a minibuffer window explicitly when you create a
-frame; then @code{default-minibuffer-frame} is not used.
-
-@section X Windows Features
-
-@itemize @bullet
-@item
-The new functions @code{mouse-position} and @code{set-mouse-position} give
-access to the current position of the mouse.
-
-@code{mouse-position} returns a description of the position of the mouse.
-The value looks like @code{(@var{frame} @var{x} . @var{y})}, where @var{x}
-and @var{y} are measured in pixels relative to the top left corner of
-the inside of @var{frame}.
-
-@code{set-mouse-position} takes three arguments, @var{frame}, @var{x}
-and @var{y}, and warps the mouse cursor to that location on the screen.
-
-@item
-@code{track-mouse} is a new special form for tracking mouse motion.
-Use it in definitions of mouse clicks that want pay to attention to
-the motion of the mouse, not just where the buttons are pressed and
-released. Here is how to use it:
-
-@example
-(track-mouse @var{body}@dots{})
-@end example
-
-While @var{body} executes, mouse motion generates input events just as mouse
-clicks do. @var{body} can read them with @code{read-event} or
-@code{read-key-sequence}.
-
-@code{track-mouse} returns the value of the last form in @var{body}.
-
-The format of these events is described under ``New features for key
-bindings and input.''
-@c ???
-
-@item
-@code{x-set-selection} sets a ``selection'' in the X Windows server.
-It takes two arguments: a selection type @var{type}, and the value to
-assign to it, @var{data}. If @var{data} is @code{nil}, it means to
-clear out the selection. Otherwise, @var{data} may be a string, a
-symbol, an integer (or a cons of two integers or list of two integers),
-or a cons of two markers pointing to the same buffer. In the last case,
-the selection is considered to be the text between the markers. The
-data may also be a vector of valid non-vector selection values.
-
-Each possible @var{type} has its own selection value, which changes
-independently. The usual values of @var{type} are @code{PRIMARY} and
-@code{SECONDARY}; these are symbols with upper-case names, in accord
-with X Windows conventions. The default is @code{PRIMARY}.
-
-To get the value of the selection, call @code{x-get-selection}. This
-function accesses selections set up by Emacs and those set up by other X
-clients. It takes two optional arguments, @var{type} and
-@var{data-type}. The default for @var{type} is @code{PRIMARY}.
-
-The @var{data-type} argument specifies the form of data conversion to
-use; meaningful values include @code{TEXT}, @code{STRING},
-@code{TARGETS}, @code{LENGTH}, @code{DELETE}, @code{FILE_NAME},
-@code{CHARACTER_POSITION}, @code{LINE_NUMBER}, @code{COLUMN_NUMBER},
-@code{OWNER_OS}, @code{HOST_NAME}, @code{USER}, @code{CLASS},
-@code{NAME}, @code{ATOM}, and @code{INTEGER}. (These are symbols with
-upper-case names in accord with X Windows conventions.)
-The default for @var{data-type} is @code{STRING}.
-
-@item
-X Windows has a set of numbered @dfn{cut buffers} which can store text
-or other data being moved between applications. Use
-@code{x-get-cut-buffer} to get the contents of a cut buffer; specify the
-cut buffer number as argument. Use @code{x-set-cut-buffer} with
-argument @var{string} to store a new string into the first cut buffer
-(moving the other values down through the series of cut buffers,
-kill-ring-style).
-
-Cut buffers are considered obsolete in X Windows, but Emacs supports
-them for the sake of X clients that still use them.
-
-@item
-You can close the connection with the X Windows server with
-the function @code{x-close-current-connection}. This takes no arguments.
-
-Then you can connect to a different X Windows server with
-@code{x-open-connection}. The first argument, @var{display}, is the
-name of the display to connect to.
-
-The optional second argument @var{xrm-string} is a string of resource
-names and values, in the same format used in the @file{.Xresources}
-file. The values you specify override the resource values recorded in
-the X Windows server itself. Here's an example of what this string
-might look like:
-
-@example
-"*BorderWidth: 3\n*InternalBorder: 2\n"
-@end example
-
-@item
-A series of new functions give you information about the X server and
-the screen you are using.
-
-@table @code
-@item x-display-screens
-The number of screens associated with the current display.
-
-@item x-server-version
-The version numbers of the X server in use.
-
-@item x-server-vendor
-The vendor supporting the X server in use.
-
-@item x-display-pixel-height
-The height of this X screen in pixels.
-
-@item x-display-mm-height
-The height of this X screen in millimeters.
-
-@item x-display-pixel-width
-The width of this X screen in pixels.
-
-@item x-display-mm-width
-The width of this X screen in millimeters.
-
-@item x-display-backing-store
-The backing store capability of this screen. Values can be the symbols
-@code{always}, @code{when-mapped}, or @code{not-useful}.
-
-@item x-display-save-under
-Non-@code{nil} if this X screen supports the SaveUnder feature.
-
-@item x-display-planes
-The number of planes this display supports.
-
-@item x-display-visual-class
-The visual class for this X screen. The value is one of the symbols
-@code{static-gray}, @code{gray-scale}, @code{static-color},
-@code{pseudo-color}, @code{true-color}, and @code{direct-color}.
-
-@item x-display-color-p
-@code{t} if the X screen in use is a color screen.
-
-@item x-display-color-cells
-The number of color cells this X screen supports.
-@end table
-
-There is also a variable @code{x-no-window-manager}, whose value is
-@code{t} if no X window manager is in use.
-
-@item
-The function @code{x-synchronize} enables or disables an X Windows
-debugging mode: synchronous communication. It takes one argument,
-non-@code{nil} to enable the mode and @code{nil} to disable.
-
-In synchronous mode, Emacs waits for a response to each X protocol
-command before doing anything else. This means that errors are reported
-right away, and you can directly find the erroneous command.
-Synchronous mode is not the default because it is much slower.
-
-@item
-The function @code{x-get-resource} retrieves a resource value from the X
-Windows defaults database. Its three arguments are @var{attribute},
-@var{name} and @var{class}. It searches using a key of the form
-@samp{@var{instance}.@var{attribute}}, with class @samp{Emacs}, where
-@var{instance} is the name under which Emacs was invoked.
-
-The optional arguments @var{component} and @var{subclass} add to the key
-and the class, respectively. You must specify both of them or neither.
-If you specify them, the key is
-@samp{@var{instance}.@var{component}.@var{attribute}}, and the class is
-@samp{Emacs.@var{subclass}}.
-
-@item
-@code{x-color-display-p} returns @code{t} if you are using an X Window
-server with a color display, and @code{nil} otherwise.
-
-@c ??? Name being changed from x-defined-color.
-@code{x-color-defined-p} takes as argument a string describing a color; it
-returns @code{t} if the display supports that color. (If the color is
-@code{"black"} or @code{"white"} then even black-and-white displays
-support it.)
-
-@item
-@code{x-popup-menu} has been generalized. It now accepts a keymap as
-the @var{menu} argument. Then the menu items are the prompt strings of
-individual key bindings, and the item values are the keys which have
-those bindings.
-
-You can also supply a list of keymaps as the first argument; then each
-keymap makes one menu pane (but keymaps that don't provide any menu
-items don't appear in the menu at all).
-
-@code{x-popup-menu} also accepts a mouse button event as the
-@var{position} argument. Then it displays the menu at the location at
-which the event took place. This is convenient for mouse-invoked
-commands that pop up menus.
-
-@ignore
-@item
-x-pointer-shape, x-nontext-pointer-shape, x-mode-pointer-shape.
-@end ignore
-
-@item
-You can use the function @code{x-rebind-key} to change the sequence
-of characters generated by one of the keyboard keys. This works
-only with X Windows.
-
-The first two arguments, @var{keycode} and @var{shift-mask}, should be
-numbers representing the keyboard code and shift mask respectively.
-They specify what key to change.
-
-The third argument, @var{newstring}, is the new definition of the key.
-It is a sequence of characters that the key should produce as input.
-
-The shift mask value is a combination of bits according to this table:
-
-@table @asis
-@item 8
-Control
-@item 4
-Meta
-@item 2
-Shift
-@item 1
-Shift Lock
-@end table
-
-If you specify @code{nil} for @var{shift-mask}, then the key specified
-by @var{keycode} is redefined for all possible shift combinations.
-
-For the possible values of @var{keycode} and their meanings, see the
-file @file{/usr/lib/Xkeymap.txt}. Keep in mind that the codes in that
-file are in octal!
-
-@ignore @c Presumably this is already fixed
-NOTE: due to an X bug, this function will not take effect unless the
-user has a @file{~/.Xkeymap} file. (See the documentation for the
-@code{keycomp} program.) This problem will be fixed in X version 11.
-@end ignore
-
-The related function @code{x-rebind-keys} redefines a single keyboard
-key, specifying the behavior for each of the 16 shift masks
-independently. The first argument is @var{keycode}, as in
-@code{x-rebind-key}. The second argument @var{strings} is a list of 16
-elements, one for each possible shift mask value; each element says how
-to redefine the key @var{keycode} with the corresponding shift mask
-value. If an element is a string, it is the new definition. If an
-element is @code{nil}, the definition does not change for that shift
-mask.
-
-@item
-The function @code{x-geometry} parses a string specifying window size
-and position in the usual fashion for X windows. It returns an alist
-describing which parameters were specified, and the values that were
-given for them.
-
-The elements of the alist look like @code{(@var{parameter} .
-@var{value})}. The possible @var{parameter} values are @code{left},
-@code{top}, @code{width}, and @code{height}.
-@end itemize
-
-@section New Window Features
-
-@itemize @bullet
-@item
-The new function @code{window-at} tells you which window contains a
-given horizontal and vertical position on a specified frame. Call it
-with three arguments, like this:
-
-@example
-(window-at @var{x} @var{column} @var{frame})
-@end example
-
-The function returns the window which contains that cursor position in
-the frame @var{frame}. If you omit @var{frame}, the selected frame is
-used.
-
-@item
-The function @code{coordinates-in-window-p} takes two arguments and
-checks whether a particular frame position falls within a particular
-window.
-
-@example
-(coordinates-in-window-p @var{coordinates} @var{window})
-@end example
-
-The argument @var{coordinates} is a cons cell of this form:
-
-@example
-(@var{x} . @var{y})
-@end example
-
-@noindent
-The two coordinates are measured in characters, and count from the top
-left corner of the screen or frame.
-
-The value of the function tells you what part of the window the position
-is in. The possible values are:
-
-@table @code
-@item (@var{relx} . @var{rely})
-The coordinates are inside @var{window}. The numbers @var{relx} and
-@var{rely} are equivalent window-relative coordinates, counting from 0
-at the top left corner of the window.
-
-@item mode-line
-The coordinates are in the mode line of @var{window}.
-
-@item vertical-split
-The coordinates are in the vertical line between @var{window} and its
-neighbor to the right.
-
-@item nil
-The coordinates are not in any sense within @var{window}.
-@end table
-
-You need not specify a frame when you call
-@code{coordinates-in-window-p}, because it assumes you mean the frame
-which window @var{window} is on.
-
-@item
-The function @code{minibuffer-window} now accepts a frame as argument
-and returns the minibuffer window used for that frame. If you don't
-specify a frame, the currently selected frame is used. The minibuffer
-window may be on the frame in question, but if that frame has no
-minibuffer of its own, it uses the minibuffer window of some other
-frame, and @code{minibuffer-window} returns that window.
-
-@item
-Use @code{window-live-p} to test whether a window is still alive (that
-is, not deleted).
-
-@item
-Use @code{window-minibuffer-p} to determine whether a given window is a
-minibuffer or not. It no longer works to do this by comparing the
-window with the result of @code{(minibuffer-window)}, because there can
-be more than one minibuffer window at a time (if you have multiple
-frames).
-
-@item
-If you set the variable @code{pop-up-frames} non-@code{nil}, then the
-functions to show something ``in another window'' actually create a new
-frame for the new window. Thus, you will tend to have a frame for each
-window, and you can easily have a frame for each buffer.
-
-The value of the variable @code{pop-up-frame-function} controls how new
-frames are made. The value should be a function which takes no
-arguments and returns a frame. The default value is a function which
-creates a frame using parameters from @code{pop-up-frame-alist}.
-
-@item
-@code{display-buffer} is the basic primitive for finding a way to show a
-buffer on the screen. You can customize its behavior by storing a
-function in the variable @code{display-buffer-function}. If this
-variable is non-@code{nil}, then @code{display-buffer} calls it to do
-the work. Your function should accept two arguments, as follows:
-
-@table @var
-@item buffer
-The buffer to be displayed.
-
-@item flag
-A flag which, if non-@code{nil}, means you should find another window to
-display @var{buffer} in, even if it is already visible in the selected
-window.
-@end table
-
-The function you supply will be used by commands such as
-@code{switch-to-buffer-other-window} and @code{find-file-other-window}
-as well as for your own calls to @code{display-buffer}.
-
-@item
-@code{delete-window} now gives all of the deleted window's screen space
-to a single neighboring window. Likewise, @code{enlarge-window} takes
-space from only one neighboring window until that window disappears;
-only then does it take from another window.
-
-@item
-@code{next-window} and @code{previous-window} accept another argument,
-@var{all-frames}.
-
-These functions now take three optional arguments: @var{window},
-@var{minibuf} and @var{all-frames}. @var{window} is the window to start
-from (@code{nil} means use the selected window). @var{minibuf} says
-whether to include the minibuffer in the windows to cycle through:
-@code{t} means yes, @code{nil} means yes if it is active, and anything
-else means no.
-
-Normally, these functions cycle through all the windows in the
-selected frame, plus the minibuffer used by the selected frame even if
-it lies in some other frame.
-
-If @var{all-frames} is @code{t}, then these functions cycle through
-all the windows in all the frames that currently exist. If
-@var{all-frames} is neither @code{t} nor @code{nil}, then they limit
-themselves strictly to the windows in the selected frame, excluding the
-minibuffer in use if it lies in some other frame.
-
-@item
-The functions @code{get-lru-window} and @code{get-largest-window} now
-take an optional argument @var{all-frames}. If it is non-@code{nil},
-the functions consider all windows on all frames. Otherwise, they
-consider just the windows on the selected frame.
-
-Likewise, @code{get-buffer-window} takes an optional second argument
-@var{all-frames}.
-
-@item
-The variable @code{other-window-scroll-buffer} specifies which buffer
-@code{scroll-other-window} should scroll.
-
-@item
-You can now mark a window as ``dedicated'' to its buffer.
-Then Emacs will not try to use that window for any other buffer
-unless you explicitly request it.
-
-Use the new function @code{set-window-dedicated-p} to set the dedication
-flag of a window @var{window} to the value @var{flag}. If @var{flag} is
-@code{t}, this makes the window dedicated. If @var{flag} is
-@code{nil}, this makes the window non-dedicated.
-
-Use @code{window-dedicated-p} to examine the dedication flag of a
-specified window.
-
-@item
-The new function @code{walk-windows} cycles through all visible
-windows, calling @code{proc} once for each window with the window as
-its sole argument.
-
-The optional second argument @var{minibuf} says whether to include minibuffer
-windows. A value of @code{t} means count the minibuffer window even if
-not active. A value of @code{nil} means count it only if active. Any
-other value means not to count the minibuffer even if it is active.
-
-If the optional third argument @var{all-frames} is @code{t}, that means
-include all windows in all frames. If @var{all-frames} is @code{nil},
-it means to cycle within the selected frame, but include the minibuffer
-window (if @var{minibuf} says so) that that frame uses, even if it is on
-another frame. If @var{all-frames} is neither @code{nil} nor @code{t},
-@code{walk-windows} sticks strictly to the selected frame.
-
-@item
-The function @code{window-end} is a counterpart to @code{window-start}:
-it returns the buffer position of the end of the display in a given
-window (or the selected window).
-
-@item
-The function @code{window-configuration-p} returns non-@code{nil} when
-given an object that is a window configuration (such as is returned by
-@code{current-window-configuration}).
-@end itemize
-
-@section Display Features
-
-@itemize @bullet
-@item
-@samp{%l} as a mode line item displays the current line number.
-
-If the buffer is longer than @code{line-number-display-limit}
-characters, or if lines are too long in the viscinity of the current
-displayed text, then line number display is inhibited to save time.
-
-The default contents of the mode line include the line number if
-@code{line-number-mode} is non-@code{nil}.
-
-@item
-@code{baud-rate} is now a variable rather than a function. This is so
-you can set it to reflect the effective speed of your terminal, when the
-system doesn't accurately know the speed.
-
-@item
-You can now remove any echo area message and make the minibuffer
-visible. To do this, call @code{message} with @code{nil} as the only
-argument. This clears any existing message, and lets the current
-minibuffer contents show through. Previously, there was no reliable way
-to make sure that the minibuffer contents were visible.
-
-@item
-The variable @code{temp-buffer-show-hook} has been renamed
-@code{temp-buffer-show-function}, because its value is a single function
-(of one argument), not a normal hook.
-
-@item
-The new function @code{force-mode-line-update} causes redisplay
-of the current buffer's mode line.
-@end itemize
-
-@section Display Tables
-
-@cindex display table
-You can use the @dfn{display table} feature to control how all 256
-possible character codes display on the screen. This is useful for
-displaying European languages that have letters not in the ASCII
-character set.
-
-The display table maps each character code into a sequence of
-@dfn{glyphs}, each glyph being an image that takes up one character
-position on the screen. You can also define how to display each glyph
-on your terminal, using the @dfn{glyph table}.
-
-@subsection Display Tables
-
-Use @code{make-display-table} to create a display table. The table
-initially has @code{nil} in all elements.
-
-A display table is actually an array of 261 elements. The first 256
-elements of a display table control how to display each possible text
-character. The value should be @code{nil} or a vector (which is a
-sequence of glyphs; see below). @code{nil} as an element means to
-display that character following the usual display conventions.
-
-The remaining five elements of a display table serve special purposes
-(@code{nil} means use the default stated below):
-
-@table @asis
-@item 256
-The glyph for the end of a truncated screen line (the default for this
-is @samp{\}).
-@item 257
-The glyph for the end of a continued line (the default is @samp{$}).
-@item 258
-The glyph for the indicating an octal character code (the default is
-@samp{\}).
-@item 259
-The glyph for indicating a control characters (the default is @samp{^}).
-@item 260
-The vector of glyphs for indicating the presence of invisible lines (the
-default is @samp{...}).
-@end table
-
-Each buffer typically has its own display table. The display table for
-the current buffer is stored in @code{buffer-display-table}. (This
-variable automatically becomes local if you set it.) If this variable
-is @code{nil}, the value of @code{standard-display-table} is used in
-that buffer.
-
-Each window can have its own display table, which overrides the display
-table of the buffer it is showing.
-
-If neither the selected window nor the current buffer has a display
-table, and if @code{standard-display-table} is @code{nil}, then Emacs
-uses the usual display conventions:
-
-@itemize @bullet
-@item
-Character codes 32 through 127 map to glyph codes 32 through 127.
-@item
-Codes 0 through 31 map to sequences of two glyphs, where the first glyph
-is the ASCII code for @samp{^}.
-@item
-Character codes 128 through 255 map to sequences of four glyphs, where
-the first glyph is the ASCII code for @samp{\}, and the others represent
-digits.
-@end itemize
-
-The usual display conventions are also used for any character whose
-entry in the active display table is @code{nil}. This means that when
-you set up a display table, you need not specify explicitly what to do
-with each character, only the characters for which you want unusual
-behavior.
-
-@subsection Glyphs
-
-@cindex glyph
-A glyph stands for an image that takes up a single character position on
-the screen. A glyph is represented in Lisp as an integer.
-
-@cindex glyph table
-The meaning of each integer, as a glyph, is defined by the glyph table,
-which is the value of the variable @code{glyph-table}. It should be a
-vector; the @var{g}th element defines glyph code @var{g}. The possible
-definitions of a glyph code are:
-
-@table @var
-@item integer
-Define this glyph code as an alias for code @var{integer}.
-This is used with X windows to specify a face code.
-
-@item string
-Send the characters in @var{string} to the terminal to output
-this glyph. This alternative is not available with X Windows.
-
-@item @code{nil}
-This glyph is simple. On an ordinary terminal, the glyph code mod 256
-is the character to output. With X, the glyph code mod 256 is character
-to output, and the glyph code divided by 256 specifies the @dfn{face
-code} to use while outputting it.
-@end table
-
-Any glyph code beyond the length of the glyph table is automatically simple.
-
-A face code for X windows is the combination of a font and a color.
-Emacs uses integers to identify face codes. You can define a new face
-code with @code{(x-set-face @var{face-code} @var{font} @var{foreground}
-@var{background})}. @var{face-code} is an integer from 0 to 255; it
-specifies which face to define. The other three arguments are strings:
-@var{font} is the name of the font to use, and @var{foreground} and
-@var{background} specify the colors to use.
-
-If @code{glyph-table} is @code{nil}, then all possible glyph codes are
-simple.
-
-@subsection ISO Latin 1
-
-If you have a terminal that can handle the entire ISO Latin 1 character
-set, you can arrange to use that character set as follows:
-
-@example
-(require 'disp-table)
-(standard-display-8bit 0 255)
-@end example
-
-If you are editing buffers written in the ISO Latin 1 character set and
-your terminal doesn't handle anything but ASCII, you can load the file
-@code{iso-ascii} to set up a display table which makes the other ISO
-characters display as sequences of ASCII characters. For example, the
-character ``o with umlaut'' displays as @samp{@{"o@}}.
-
-Some European countries have terminals that don't support ISO Latin 1
-but do support the special characters for that country's language. You
-can define a display table to work one language using such terminals.
-For an example, see @file{lisp/iso-swed.el}, which handles certain
-Swedish terminals.
-
-You can load the appropriate display table for your terminal
-automatically by writing a terminal-specific Lisp file for the terminal
-type.
-
-@section New Input Event Formats
-
-Mouse clicks, mouse movements and function keys no longer appear in the
-input stream as characters; instead, other kinds of Lisp objects
-represent them as input.
-
-@itemize @bullet
-@item
-An ordinary input character event consists of a @dfn{basic code} between
-0 and 255, plus any or all of these @dfn{modifier bits}:
-
-@table @asis
-@item meta
-The 2**23 bit in the character code indicates a character
-typed with the meta key held down.
-
-@item control
-The 2**22 bit in the character code indicates a non-@sc{ASCII}
-control character.
-
-@sc{ASCII} control characters such as @kbd{C-a} have special basic
-codes of their own, so Emacs needs no special bit to indicate them.
-Thus, the code for @kbd{C-a} is just 1.
-
-But if you type a control combination not in @sc{ASCII}, such as
-@kbd{%} with the control key, the numeric value you get is the code
-for @kbd{%} plus 2**22 (assuming the terminal supports non-@sc{ASCII}
-control characters).
-
-@item shift
-The 2**21 bit in the character code indicates an @sc{ASCII} control
-character typed with the shift key held down.
-
-For letters, the basic code indicates upper versus lower case; for
-digits and punctuation, the shift key selects an entirely different
-character with a different basic code. In order to keep within
-the @sc{ASCII} character set whenever possible, Emacs avoids using
-the 2**21 bit for those characters.
-
-However, @sc{ASCII} provides no way to distinguish @kbd{C-A} from
-@kbd{C-A}, so Emacs uses the 2**21 bit in @kbd{C-A} and not in
-@kbd{C-a}.
-
-@item hyper
-The 2**20 bit in the character code indicates a character
-typed with the hyper key held down.
-
-@item super
-The 2**19 bit in the character code indicates a character
-typed with the super key held down.
-
-@item alt
-The 2**18 bit in the character code indicates a character typed with
-the alt key held down. (On some terminals, the key labeled @key{ALT}
-is actually the meta key.)
-@end table
-
-In the future, Emacs may support a larger range of basic codes. We may
-also move the modifier bits to larger bit numbers. Therefore, you
-should avoid mentioning specific bit numbers in your program. Instead,
-the way to test the modifier bits of a character is with the function
-@code{event-modifiers} (see below).
-
-@item
-Function keys are represented as symbols. The symbol's name is
-the function key's label. For example, pressing a key labeled @key{F1}
-places the symbol @code{f1} in the input stream.
-
-There are a few exceptions to the symbol naming convention:
-
-@table @asis
-@item @code{kp-add}, @code{kp-decimal}, @code{kp-divide}, @dots{}
-Keypad keys (to the right of the regular keyboard).
-@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
-
-You can use the modifier keys @key{CTRL}, @key{META}, @key{HYPER},
-@key{SUPER}, @key{ALT} and @key{SHIFT} with function keys. The way
-to represent them is with prefixes in the symbol name:
-
-@table @samp
-@item A-
-The alt modifier.
-@item C-
-The control modifier.
-@item H-
-The hyper modifier.
-@item M-
-The meta modifier.
-@item s-
-The super modifier.
-@item S-
-The shift modifier.
-@end table
-
-Thus, the symbol for the key @key{F3} with @key{META} held down is
-kbd{M-@key{F3}}. When you use more than one prefix, we recommend you
-write them in alphabetical order (though the order does not matter in
-arguments to the key-binding lookup and modification functions).
-
-@item
-Mouse events are represented as lists.
-
-If you press a mouse button and release it at the same location, this
-generates a ``click'' event. Mouse click events have this form:
-
-@example
-(@var{button-symbol}
- (@var{window} (@var{column} . @var{row})
- @var{buffer-pos} @var{timestamp}))
-@end example
-
-Here is what the elements normally mean:
-
-@table @var
-@item button-symbol
-indicates which mouse button was used. It is one of the symbols
-@code{mouse-1}, @code{mouse-2}, @dots{}, where the buttons are numbered
-numbered left to right.
-
-You can also use prefixes @samp{A-}, @samp{C-}, @samp{H-}, @samp{M-},
-@samp{S-} and @samp{s-} for modifiers alt, control, hyper, meta, shift
-and super, just as you would with function keys.
-
-@item window
-is the window in which the click occurred.
-
-@item column
-@itemx row
-are the column and row of the click, relative to the top left corner of
-@var{window}, which is @code{(0 . 0)}.
-
-@item buffer-pos
-is the buffer position of the character clicked on.
-
-@item timestamp
-is the time at which the event occurred, in milliseconds. (Since this
-value wraps around the entire range of Emacs Lisp integers in about five
-hours, it is useful only for relating the times of nearby events.)
-@end table
-
-The meanings of @var{buffer-pos}, @var{row} and @var{column} are
-somewhat different when the event location is in a special part of the
-screen, such as the mode line or a scroll bar.
-
-If the position is in the window's scroll bar, then @var{buffer-pos} is
-the symbol @code{vertical-scrollbar} or @code{horizontal-scrollbar}, and
-the pair @code{(@var{column} . @var{row})} is instead a pair
-@code{(@var{portion} . @var{whole})}, where @var{portion} is the
-distance of the click from the top or left end of the scroll bar, and
-@var{whole} is the length of the entire scroll bar.
-
-If the position is on a mode line or the vertical line separating
-@var{window} from its neighbor to the right, then @var{buffer-pos} is
-the symbol @code{mode-line} or @code{vertical-line}. In this case
-@var{row} and @var{column} do not have meaningful data.
-
-@item
-Releasing a mouse button above a different character position
-generates a ``drag'' event, which looks like this:
-
-@example
-(@var{button-symbol}
- (@var{window1} (@var{column1} . @var{row1})
- @var{buffer-pos1} @var{timestamp1})
- (@var{window2} (@var{column2} . @var{row2})
- @var{buffer-pos2} @var{timestamp2}))
-@end example
-
-The name of @var{button-symbol} contains the prefix @samp{drag-}. The
-second and third elements of the event give the starting and ending
-position of the drag.
-
-The @samp{drag-} prefix follows the modifier key prefixes such as
-@samp{C-} and @samp{M-}.
-
-If @code{read-key-sequence} receives a drag event which has no key
-binding, and the corresponding click event does have a binding, it
-changes the drag event into a click event at the drag's starting
-position. This means that you don't have to distinguish between click
-and drag events unless you want to.
-
-@item
-Click and drag events happen when you release a mouse button. Another
-kind of event happens when you press a button. It looks just like a
-click event, except that the name of @var{button-symbol} contains the
-prefix @samp{down-}. The @samp{down-} prefix follows the modifier key
-prefixes such as @samp{C-} and @samp{M-}.
-
-The function @code{read-key-sequence}, and the Emacs command loop,
-ignore any down events that don't have command bindings. This means
-that you need not worry about defining down events unless you want them
-to do something. The usual reason to define a down event is so that you
-can track mouse motion until the button is released.
-
-@item
-For example, if the user presses and releases the left mouse button over
-the same location, Emacs generates a sequence of events like this:
-
-@smallexample
-(down-mouse-1 (#<window 18 on NEWS> 2613 (0 . 38) -864320))
-(mouse-1 (#<window 18 on NEWS> 2613 (0 . 38) -864180))
-@end smallexample
-
-Or, while holding the control key down, the user might hold down the
-second mouse button, and drag the mouse from one line to the next.
-That produces two events, as shown here:
-
-@smallexample
-(C-down-mouse-2 (#<window 18 on NEWS> 3440 (0 . 27) -731219))
-(C-drag-mouse-2 (#<window 18 on NEWS> 3440 (0 . 27) -731219)
- (#<window 18 on NEWS> 3510 (0 . 28) -729648))
-@end smallexample
-
-Or, while holding down the meta and shift keys, the user might press
-the second mouse button on the window's mode line, and then drag the
-mouse into another window. That produces an event like this:
-
-@smallexample
-(M-S-down-mouse-2 (#<window 18 on NEWS> mode-line (33 . 31) -457844))
-(M-S-drag-mouse-2 (#<window 18 on NEWS> mode-line (33 . 31) -457844)
- (#<window 20 on carlton-sanskrit.tex> 161 (33 . 3)
- -453816))
-@end smallexample
-
-@item
-A key sequence that starts with a mouse click is read using the keymaps
-of the buffer in the window clicked on, not the current buffer.
-
-This does not imply that clicking in a window selects that window or its
-buffer. The execution of the command begins with no change in the
-selected window or current buffer. However, the command can switch
-windows or buffers if programmed to do so.
-
-@item
-Mouse motion events are represented by lists. During the execution of
-the body of a @code{track-mouse} form, moving the mouse generates events
-that look like this:
-
-@example
-(mouse-movement (@var{window} (@var{column} . @var{row})
- @var{buffer-pos} @var{timestamp}))
-@end example
-
-The second element of the list describes the current position of the
-mouse, just as in a mouse click event.
-
-Outside of @code{track-mouse} forms, Emacs does not generate events for
-mere motion of the mouse, and these events do not appear.
-
-@item
-Focus shifts between frames are represented by lists.
-
-When the mouse shifts temporary input focus from one frame to another,
-Emacs generates an event like this:
-
-@example
-(switch-frame @var{new-frame})
-@end example
-
-@noindent
-where @var{new-frame} is the frame switched to.
-
-In X windows, most window managers are set up so that just moving the
-mouse into a window is enough to set the focus there. As far as the
-user concern, Emacs behaves consistently with this. However, there is
-no need for the Lisp program to know about the focus change until some
-other kind of input arrives. So Emacs generates the focus event only
-when the user actually types a keyboard key or presses a mouse button in
-the new frame; just moving the mouse between frames does not generate a
-focus event.
-
-The global key map usually binds this event to the
-@code{internal-select-frame} function, so that characters typed at a
-frame apply to that frame's selected window.
-
-If the user switches frames in the middle of a key sequence, then Emacs
-delays the @code{switch-frame} event until the key sequence is over.
-For example, suppose @kbd{C-c C-a} is a key sequence in the current
-buffer's keymaps. If the user types @kbd{C-c}, moves the mouse to
-another frame, and then types @kbd{C-a}, @code{read-key-sequence}
-returns the sequence @code{"\C-c\C-a"}, and the next call to
-@code{read-event} or @code{read-key-sequence} will return the
-@code{switch-frame} event.
-@end itemize
-
-@section Working with Input Events
-
-@itemize @bullet
-@item
-Functions which work with key sequences now handle non-character
-events. Functions like @code{define-key}, @code{global-set-key}, and
-@code{local-set-key} used to accept strings representing key sequences;
-now, since events may be arbitrary lisp objects, they also accept
-vectors. The function @code{read-key-sequence} may return a string or a
-vector, depending on whether or not the sequence read contains only
-characters.
-
-List events may be represented by the symbols at their head; to bind
-clicks of the left mouse button, you need only present the symbol
-@code{mouse-1}, not an entire mouse click event. If you do put an event
-which is a list in a key sequence, only the event's head symbol is used
-in key lookups.
-
-For example, to globally bind the left mouse button to the function
-@code{mouse-set-point}, you could evaluate this:
-
-@example
-(global-set-key [mouse-1] 'mouse-set-point)
-@end example
-
-To bind the sequence @kbd{C-c @key{F1}} to the command @code{tex-view}
-in @code{tex-mode-map}, you could evaluate this:
-
-@example
-(define-key tex-mode-map [?\C-c f1] 'tex-view)
-@end example
-
-To find the binding for the function key labeled @key{NEXT} in
-@code{minibuffer-local-map}, you could evaluate this:
-
-@example
-(lookup-key minibuffer-local-map [next])
- @result{} next-history-element
-@end example
-
-If you call the function @code{read-key-sequence} and then press
-@kbd{C-x C-@key{F5}}, here is how it behaves:
-
-@example
-(read-key-sequence "Press `C-x C-F5': ")
- @result{} [24 C-f5]
-@end example
-
-Note that @samp{24} is the character @kbd{C-x}.
-
-@item
-The documentation functions (@code{single-key-description},
-@code{key-description}, etc.) now handle the new event types. Wherever
-a string of keyboard input characters was acceptable in previous
-versions of Emacs, a vector of events should now work.
-
-@item
-Special parts of a window can have their own bindings for mouse events.
-
-When mouse events occur in special parts of a window, such as a mode
-line or a scroll bar, the event itself shows nothing special---only the
-symbol that would normally represent that mouse button and modifier
-keys. The information about the screen region is kept in other parts
-of the event list. But @code{read-key-sequence} translates this
-information into imaginary prefix keys, all of which are symbols:
-@code{mode-line}, @code{vertical-line}, @code{horizontal-scrollbar} and
-@code{vertical-scrollbar}.
-
-For example, if you call @code{read-key-sequence} and then click the
-mouse on the window's mode line, this is what happens:
-
-@smallexample
-(read-key-sequence "Click on the mode line: ")
- @result{} [mode-line (mouse-1 (#<window 6 on NEWS> mode-line
- (40 . 63) 5959987))]
-@end smallexample
-
-You can define meanings for mouse clicks in special window regions by
-defining key sequences using these imaginary prefix keys. For example,
-here is how to bind the third mouse button on a window's mode line
-delete the window:
-
-@example
-(global-set-key [mode-line mouse-3] 'mouse-delete-window)
-@end example
-
-Here's how to bind the middle button (modified by @key{META}) on the
-vertical line at the right of a window to scroll the window to the
-left.
-
-@example
-(global-set-key [vertical-line M-mouse-2] 'scroll-left)
-@end example
-
-@item
-Decomposing an event symbol.
-
-Each symbol used to identify a function key or mouse button has a
-property named @code{event-symbol-elements}, which is a list containing
-an unmodified version of the symbol, followed by modifiers the symbol
-name contains. The modifiers are symbols; they include @code{shift},
-@code{control}, and @code{meta}. In addition, a mouse event symbol has
-one of @code{click}, @code{drag}, and @code{down}. For example:
-
-@example
-(get 'f5 'event-symbol-elements)
- @result{} (f5)
-(get 'C-f5 'event-symbol-elements)
- @result{} (f5 control)
-(get 'M-S-f5 'event-symbol-elements)
- @result{} (f5 meta shift)
-(get 'mouse-1 'event-symbol-elements)
- @result{} (mouse-1 click)
-(get 'down-mouse-1 'event-symbol-elements)
- @result{} (mouse-1 down)
-@end example
-
-Note that the @code{event-symbol-elements} property for a mouse click
-explicitly contains @code{click}, but the event symbol name itself does
-not contain @samp{click}.
-
-@item
-Use @code{read-event} to read input if you want to accept any kind of
-event. The old function @code{read-char} now discards events other than
-keyboard characters.
-
-@item
-@code{last-command-char} and @code{last-input-char} can now hold any
-kind of event.
-
-@item
-The new variable @code{unread-command-events} is much like
-@code{unread-command-char}. Its value is a list of events of any type,
-to be processed as command input in order of appearance in the list.
-
-@item
-The function @code{this-command-keys} may return a string or a vector,
-depending on whether or not the sequence read contains only characters.
-You may need to upgrade code which uses this function.
-
-The function @code{recent-keys} now returns a vector of events.
-You may need to upgrade code which uses this function.
-
-@item
-A keyboard macro's definition can now be either a string or a vector.
-All that really matters is what elements it has. If the elements are
-all characters, then the macro can be a string; otherwise, it has to be
-a vector.
-
-@item
-The variable @code{last-event-frame} records which frame the last input
-event was directed to. Usually this is the frame that was selected when
-the event was generated, but if that frame has redirected input focus to
-another frame, @code{last-event-frame} is the frame to which the event
-was redirected.
-
-@item
-The interactive specification now allows a new code letter @samp{e} to
-simplify commands bound to events which are lists. This code supplies
-as an argument the complete event object.
-
-You can use @samp{e} more than once in a single command's interactive
-specification. If the key sequence which invoked the command has
-@var{n} events with parameters, the @var{n}th @samp{e} provides the
-@var{n}th parameterized event. Events which are not lists, such as
-function keys and ASCII keystrokes, do not count where @samp{e} is
-concerned.
-
-@item
-You can extract the starting and ending position values from a mouse
-button or motion event using the two functions @code{event-start} and
-@code{event-end}. These two functions return different values for drag
-and motion events; for click and button-down events, they both return
-the position of the event.
-
-@item
-The position, a returned by @code{event-start} and @code{event-end}, is
-a list of this form:
-
-@example
-(@var{window} @var{buffer-position} (@var{col} . @var{row}) @var{timestamp})
-@end example
-
-You can extract parts of this list with the functions
-@code{posn-window}, @code{posn-point}, @code{posn-col-row}, and
-@code{posn-timestamp}.
-
-@item
-The function @code{scroll-bar-scale} is useful for computing where to
-scroll to in response to a mouse button event from a scroll bar. It
-takes two arguments, @var{ratio} and @var{total}, and in effect
-multiplies them. We say ``in effect'' because @var{ratio} is not a
-number; rather a pair @code{(@var{num} . @var{denom}).
-
-Here's the usual way to use @code{scroll-bar-scale}:
-
-@example
-(scroll-bar-scale (posn-col-row (event-start event))
- (buffer-size))
-@end example
-@end itemize
-
-@section Putting Keyboard Events in Strings
-
- In most of the places where strings are used, we conceptualize the
-string as containing text characters---the same kind of characters found
-in buffers or files. Occasionally Lisp programs use strings which
-conceptually contain keyboard characters; for example, they may be key
-sequences or keyboard macro definitions. There are special rules for
-how to put keyboard characters into a string, because they are not
-limited to the range of 0 to 255 as text characters are.
-
- A keyboard character typed using the @key{META} key is called a
-@dfn{meta character}. The numeric code for such an event includes the
-2**23 bit; it does not even come close to fitting in a string. However,
-earlier Emacs versions used a different representation for these
-characters, which gave them codes in the range of 128 to 255. That did
-fit in a string, and many Lisp programs contain string constants that
-use @samp{\M-} to express meta characters, especially as the argument to
-@code{define-key} and similar functions.
-
- We provide backward compatibility to run those programs with special
-rules for how to put a keyboard character event in a string. Here are
-the rules:
-
-@itemize @bullet
-@item
-If the keyboard event value is in the range of 0 to 127, it can go in the
-string unchanged.
-
-@item
-The meta variants of those events, with codes in the range of 2**23 to
-2**23+127, can also go in the string, but you must change their numeric
-values. You must set the 2**7 bit instead of the 2**23 bit, resulting
-in a value between 128 and 255.
-
-@item
-Other keyboard character events cannot fit in a string. This includes
-keyboard events in the range of 128 to 255.
-@end itemize
-
- Functions such as @code{read-key-sequence} that can construct strings
-containing events follow these rules.
-
- When you use the read syntax @samp{\M-} in a string, it produces a
-code in the range of 128 to 255---the same code that you get if you
-modify the corresponding keyboard event to put it in the string. Thus,
-meta events in strings work consistently regardless of how they get into
-the strings.
-
- New programs can avoid dealing with these rules by using vectors
-instead of strings for key sequences when there is any possibility that
-these issues might arise.
-
- The reason we changed the representation of meta characters as
-keyboard events is to make room for basic character codes beyond 127,
-and support meta variants of such larger character codes.
-
-@section Menus
-
-You can now define menus conveniently as keymaps. Menus are normally
-used with the mouse, but they can work with the keyboard also.
-
-@subsection Defining Menus
-
-A keymap is suitable for menu use if it has an @dfn{overall prompt
-string}, which is a string that appears as an element of the keymap. It
-should describes the purpose of the menu. The easiest way to construct
-a keymap with a prompt string is to specify the string as an argument
-when you run @code{make-keymap} or @code{make-sparse-keymap}.
-
-The individual bindings in the menu keymap should also have prompt
-strings; these strings are the items in the menu. A binding with a
-prompt string looks like this:
-
-@example
-(@var{char} @var{string} . @var{real-binding})
-@end example
-
-As far as @code{define-key} is concerned, the string is part of the
-character's binding---the binding looks like this:
-
-@example
-(@var{string} . @var{real-binding}).
-@end example
-
-However, only @var{real-binding} is used for executing the key.
-
-You can also supply a second string, called the help string, as follows:
-
-@example
-(@var{char} @var{string} @var{help-string} . @var{real-binding})
-@end example
-
-Currently Emacs does not actually use @var{help-string}; it knows only
-how to ignore @var{help-string} in order to extract @var{real-binding}.
-In the future we hope to make @var{help-string} serve as longer
-documentation for the menu item, available on request.
-
-The prompt string for a binding should be short---one or two words. Its
-meaning should describe the command it corresponds to.
-
-If @var{real-binding} is @code{nil}, then @var{string} appears in the
-menu but cannot be selected.
-
-If @var{real-binding} is a symbol, and has a non-@code{nil}
-@code{menu-enable} property, that property is an expression which
-controls whether the menu item is enabled. Every time the keymap is
-used to display a menu, Emacs evaluates the expression, and it enables
-the menu item only if the expression's value is non-@code{nil}. When a
-menu item is disabled, it is displayed in a ``fuzzy'' fashion, and
-cannot be selected with the mouse.
-
-@subsection Menus and the Mouse
-
-The way to make a menu keymap produce a menu is to make it the
-definition of a prefix key.
-
-When the prefix key ends with a mouse event, Emacs handles the menu
-keymap by popping up a visible menu that you can select from with the
-mouse. When you click on a menu item, the event generated is whatever
-character or symbol has the binding which brought about that menu item.
-
-A single keymap can appear as multiple panes, if you explicitly
-arrange for this. The way to do this is to make a keymap for each
-pane, then create a binding for each of those maps in the main keymap
-of the menu. Give each of these bindings a prompt string that starts
-with @samp{@@}. The rest of the prompt string becomes the name of the
-pane. See the file @file{lisp/mouse.el} for an example of this. Any
-ordinary bindings with prompt strings are grouped into one pane, which
-appears along with the other panes explicitly created for the
-submaps.
-
-You can also get multiple panes from separate keymaps. The full
-definition of a prefix key always comes from merging the definitions
-supplied by the various active keymaps (minor modes, local, and
-global). When more than one of these keymaps is a menu, each of them
-makes a separate pane or panes.
-
-@subsection Menus and the Keyboard
-
-When a prefix key ending with a keyboard event (a character or function
-key) has a definition that is a menu keymap, you can use the keyboard
-to choose a menu item.
-
-Emacs displays the menu alternatives in the echo area. If they don't
-all fit at once, type @key{SPC} to see the next line of alternatives.
-If you keep typing @key{SPC}, you eventually get to the end of the menu
-and then cycle around to the beginning again.
-
-When you have found the alternative you want, type the corresponding
-character---the one whose binding is that alternative.
-
-In a menu intended for keyboard use, each menu item must clearly
-indicate what character to type. The best convention to use is to make
-the character the first letter of the menu item prompt string. That is
-something users will understand without being told.
-
-@subsection The Menu Bar
-
- Under X Windows, each frame can have a @dfn{menu bar}---a permanently
-displayed menu stretching horizontally across the top of the frame. The
-items of the menu bar are the subcommands of the fake ``function key''
-@code{menu-bar}, as defined by all the active keymaps.
-
- To add an item to the menu bar, invent a fake ``function key'' of your
-own (let's call it @var{key}), and make a binding for the key sequence
-@code{[menu-bar @var{key}]}. Most often, the binding is a menu keymap,
-so that pressing a button on the menu bar item leads to another menu.
-
- In order for a frame to display a menu bar, its @code{menu-bar-lines}
-property must be greater than zero. Emacs uses just one line for the
-menu bar itself; if you specify more than one line, the other lines
-serve to separate the menu bar from the windows in the frame. We
-recommend you try one or two as the @code{menu-bar-lines} value.
-
-@section Keymaps
-
-@itemize @bullet
-@item
-The representation of keymaps has changed to support the new event
-types. All keymaps now have the form @code{(keymap @var{element}
-@var{element} @dots{})}. Each @var{element} takes one of the following
-forms:
-
-@table @asis
-@item @var{prompt-string}
-A string as an element of the keymap marks the keymap as a menu, and
-serves as the overal prompt string for it.
-
-@item @code{(@var{key} . @var{binding})}
-A cons cell binds @var{key} to @var{definition}. Here @var{key} may be
-any sort of event head---a character, a function key symbol, or a mouse
-button symbol.
-
-@item @var{vector}
-A vector of 128 elements binds all the ASCII characters; the @var{n}th
-element holds the binding for character number @var{n}.
-
-@item @code{(t . @var{binding})}
-A cons cell whose @sc{car} is @code{t} is a default binding; anything
-not bound by previous keymap elements is given @var{binding} as its
-binding.
-
-Default bindings are important because they allow a keymap to bind all
-possible events without having to enumerate all the possible function
-keys and mouse clicks, with all possible modifier prefixes.
-
-The function @code{lookup-key} (and likewise other functions for
-examining a key binding) normally report only explicit bindings of the
-specified key sequence; if there is none, they return @code{nil}, even
-if there is a default binding that would apply to that key sequence if
-it were actually typed in. However, these functions now take an
-optional argument @var{accept-defaults} which, if non-@code{nil}, says
-to consider default bindings.
-
-Note that if a vector in the keymap binds an ASCII character to
-@code{nil} (thus making it ``unbound''), the default binding does not
-apply to the character. Think of the vector element as an explicit
-binding of @code{nil}.
-
-Note also that if the keymap for a minor or major mode contains a
-default binding, it completely masks out any lower-priority keymaps.
-@end table
-
-@item
-A keymap can now inherit from another keymap. Do do this, make the
-latter keymap the ``tail'' of the new one. Such a keymap looks like
-this:
-
-@example
-(keymap @var{bindings}@dots{} . @var{other-keymap})
-@end example
-
-The effect is that this keymap inherits all the bindings of
-@var{other-keymap}, but can add to them or override them with
-@var{bindings}. Subsequent changes in the bindings of
-@var{other-keymap} @emph{do} affect this keymap.
-
-For example,
-
-@example
-(setq my-mode-map (cons 'keymap text-mode-map))
-@end example
-
-@noindent
-makes a keymap that by default inherits all the bindings of Text
-mode---whatever they may be at the time a key is looked up. Any
-bindings made explicitly in @code{my-mode-map} override the bindings
-inherited from Text mode, however.
-
-@item
-Minor modes can now have local keymaps. Thus, a key can act a special
-way when a minor mode is in effect, and then revert to the major mode or
-global definition when the minor mode is no longer in effect. The
-precedence of keymaps is now: minor modes (in no particular order), then
-major mode, and lastly the global map.
-
-The new @code{current-minor-mode-maps} function returns a list of all
-the keymaps of currently enabled minor modes, in the other that they
-apply.
-
-To set up a keymap for a minor mode, add an element to the alist
-@code{minor-mode-map-alist}. Its elements look like this:
-
-@example
-(@var{symbol} . @var{keymap})
-@end example
-
-The keymap @var{keymap} is active whenever @var{symbol} has a
-non-@code{nil} value. Use for @var{symbol} the variable which indicates
-whether the minor mode is enabled.
-
-When more than one minor mode keymap is active, their order of
-precedence is the order of @code{minor-mode-map-alist}. But you should
-design minor modes so that they don't interfere with each other, and if
-you do this properly, the order will not matter.
-
-The function @code{minor-mode-key-binding} returns a list of all the
-active minor mode bindings of @var{key}. More precisely, it returns an
-alist of pairs @code{(@var{modename} . @var{binding})}, where
-@var{modename} is the the variable which enables the minor mode, and
-@var{binding} is @var{key}'s definition in that mode. If @var{key} has
-no minor-mode bindings, the value is @code{nil}.
-
-If the first binding is a non-prefix, all subsequent bindings from other
-minor modes are omitted, since they would be completely shadowed.
-Similarly, the list omits non-prefix bindings that follow prefix
-bindings.
-
-@item
-The new function @code{copy-keymap} copies a keymap, producing a new
-keymap with the same key bindings in it. If the keymap contains other
-keymaps directly, these subkeymaps are copied recursively.
-
-If you want to, you can define a prefix key with a binding that is a
-symbol whose function definition is another keymap. In this case,
-@code{copy-keymap} does not look past the symbol; it doesn't copy the
-keymap inside the symbol.
-
-@item
-@code{substitute-key-definition} now accepts an optional fourth
-argument, which is a keymap to use as a template.
-
-@example
-(substitute-key-definition olddef newdef keymap oldmap)
-@end example
-
-@noindent
-finds all characters defined in @var{oldmap} as @var{olddef},
-and defines them in @var{keymap} as @var{newdef}.
-
-In addition, this function now operates recursively on the keymaps that
-define prefix keys within @var{keymap} and @var{oldmap}.
-@end itemize
-
-@section Minibuffer Features
-
-The minibuffer input functions @code{read-from-minibuffer} and
-@code{completing-read} have new features.
-
-@subsection Minibuffer History
-
-A new optional argument @var{hist} specifies which history list to use.
-If you specify a variable (a symbol), that variable is the history
-list. If you specify a cons cell @code{(@var{variable}
-. @var{startpos})}, then @var{variable} is the history list variable,
-and @var{startpos} specifies the initial history position (an integer,
-counting from zero which specifies the most recent element of the
-history).
-
-If you specify @var{startpos}, then you should also specify that element
-of the history as @var{initial-input}, for consistency.
-
-If you don't specify @var{hist}, then the default history list
-@code{minibuffer-history} is used. Other standard history lists that
-you can use when appropriate include @code{query-replace-history},
-@code{command-history}, and @code{file-name-history}.
-
-The value of the history list variable is a list of strings, most recent
-first. You should set a history list variable to @code{nil} before
-using it for the first time.
-
-@code{read-from-minibuffer} and @code{completing-read} add new elements
-to the history list automatically, and provide commands to allow the
-user to reuse items on the list. The only thing your program needs to
-do to use a history list is to initialize it and to pass its name to the
-input functions when you wish. But it is safe to modify the list by
-hand when the minibuffer input functions are not using it.
-
-@subsection Other Minibuffer Features
-
-The @var{initial} argument to @code{read-from-minibufer} and other
-minibuffer input functions can now be a cons cell @code{(@var{string}
-. @var{position})}. This means to start off with @var{string} in the
-minibuffer, but put the cursor @var{position} characters from the
-beginning, rather than at the end.
-
-In @code{read-no-blanks-input}, the @var{initial} argument is now
-optional; if it is omitted, the initial input string is the empty
-string.
-
-@section New Features for Defining Commands
-
-@itemize @bullet
-@item
-If the interactive specification begins with @samp{@@}, this means to
-select the window under the mouse. This selection takes place before
-doing anything else with the command.
-
-You can use both @samp{@@} and @samp{*} together in one command; they
-are processed in order of appearance.
-
-@item
-Prompts in an interactive specification can incorporate the values of
-the preceding arguments. Emacs replaces @samp{%}-sequences (as used
-with the @code{format} function) in the prompt with the interactive
-arguments that have been read so far. For example, a command with this
-interactive specification
-
-@example
-(interactive "sReplace: \nsReplace %s with: ")
-@end example
-
-@noindent
-prompts for the first argument with @samp{Replace: }, and then prompts
-for the second argument with @samp{Replace @var{foo} with: }, where
-@var{foo} is the string read as the first argument.
-
-@item
-If a command name has a property @code{enable-recursive-minibuffers}
-which is non-@code{nil}, then the command can use the minibuffer to read
-arguments even if it is invoked from the minibuffer. The minibuffer
-command @code{next-matching-history-element} (normally bound to
-@kbd{M-s} in the minibuffer) uses this feature.
-@end itemize
-
-@section New Features for Reading Input
-
-@itemize @bullet
-@item
-The function @code{set-input-mode} now takes four arguments. The last
-argument is optional. Their names are @var{interrupt}, @var{flow},
-@var{meta} and @var{quit}.
-
-The argument @var{interrupt} says whether to use interrupt-driven
-input. Non-@code{nil} means yes, and @code{nil} means no (use CBREAK
-mode).
-
-The argument @var{flow} says whether to enable terminal flow control.
-Non-@code{nil} means yes.
-
-The argument @var{meta} says whether to enable the use of a Meta key.
-Non-@code{nil} means yes.
-
-If @var{quit} non-@code{nil}, it is the character to use for quitting.
-(Normally this is @kbd{C-g}.)
-
-@item
-The variable @code{meta-flag} has been deleted; use
-@code{set-input-mode} to enable or disable support for a @key{META}
-key. This change was made because @code{set-input-mode} can send the
-terminal the appropriate commands to enable or disable operation of the
-@key{META} key.
-
-@item
-The new variable @code{extra-keyboard-modifiers} lets Lisp programs
-``press'' the modifier keys on the keyboard.
-The value is a bit mask:
-
-@table @asis
-@item 1
-The @key{SHIFT} key.
-@item 2
-The @key{LOCK} key.
-@item 4
-The @key{CTL} key.
-@item 8
-The @key{META} key.
-@end table
-
-When you use X windows, the program can press any of the modifier keys
-in this way. Otherwise, only the @key{CTL} and @key{META} keys can be
-virtually pressed.
-
-@item
-You can use the new function @code{keyboard-translate} to set up
-@code{keyboard-translate-table} conveniently.
-
-@item
-Y-or-n questions using the @code{y-or-n-p} function now accept @kbd{C-]}
-(usually mapped to @code{abort-recursive-edit}) as well as @kbd{C-g} to
-quit.
-
-@item
-The variable @code{num-input-keys} is the total number of key sequences
-that the user has typed during this Emacs session.
-
-@item
-A new Lisp variable, @code{function-key-map}, holds a keymap which
-describes the character sequences sent by function keys on an ordinary
-character terminal. This uses the same keymap data structure that is
-used to hold bindings of key sequences, but it has a different meaning:
-it specifies translations to make while reading a key sequence.
-
-If @code{function-key-map} ``binds'' a key sequence @var{k} to a vector
-@var{v}, then when @var{k} appears as a subsequence @emph{anywhere} in a
-key sequence, it is replaced with @var{v}.
-
-For example, VT100 terminals send @kbd{@key{ESC} O P} when the ``keypad''
-PF1 key is pressed. Thus, on a VT100, @code{function-key-map} should
-``bind'' that sequence to @code{[pf1]}. This specifies translation of
-@kbd{@key{ESC} O P} into @key{PF1} anywhere in a key sequence.
-
-Thus, typing @kbd{C-c @key{PF1}} sends the character sequence @kbd{C-c
-@key{ESC} O P}, but @code{read-key-sequence} translates this back into
-@kbd{C-c @key{PF1}}, which it returns as the vector @code{[?\C-c PF1]}.
-
-Entries in @code{function-key-map} are ignored if they conflict with
-bindings made in the minor mode, local, or global keymaps.
-
-The value of @code{function-key-map} is usually set up automatically
-according to the terminal's Terminfo or Termcap entry, and the
-terminal-specific Lisp files. Emacs comes with a number of
-terminal-specific files for many common terminals; their main purpose is
-to make entries in @code{function-key-map} beyond those that can be
-deduced from Termcap and Terminfo.
-
-@item
-The variable @code{key-translation-map} works like @code{function-key-map}
-except for two things:
-
-@itemize @bullet
-@item
-@code{key-translation-map} goes to work after @code{function-key-map} is
-finished; it receives the results of translation by
-@code{function-key-map}.
-
-@item
-@code{key-translation-map} overrides actual key bindings.
-@end itemize
-
-The intent of @code{key-translation-map} is for users to map one
-character set to another, including ordinary characters normally bound
-to @code{self-insert-command}.
-@end itemize
-
-@section New Syntax Table Features
-
-@itemize @bullet
-@item
-You can use two new functions to move across characters in certain
-syntax classes.
-
-@code{skip-syntax-forward} moves point forward across characters whose
-syntax classes are mentioned in its first argument, a string. It stops
-when it encounters the end of the buffer, or position @var{lim} (the
-optional second argument), or a character it is not supposed to skip.
-The function @code{skip-syntax-backward} is similar but moves backward.
-
-@item
-The new function @code{forward-comment} moves point by comments. It
-takes one argument, @var{count}; it moves point forward across
-@var{count} comments (backward, if @var{count} is negative). If it
-finds anything other than a comment or whitespace, it stops, leaving
-point at the far side of the last comment found. It also stops after
-satisfying @var{count}.
-
-@item
-The new variable @code{words-include-escapes} affects the behavior of
-@code{forward-word} and everything that uses it. If it is
-non-@code{nil}, then characters in the ``escape'' and ``character
-quote'' syntax classes count as part of words.
-
-@item
-There are two new syntax flags for use in syntax tables.
-
-@itemize -
-@item
-The prefix flag.
-
-The @samp{p} flag identifies additional ``prefix characters'' in Lisp
-syntax. You can set this flag with @code{modify-syntax-entry} by
-including the letter @samp{p} in the syntax specification.
-
-These characters are treated as whitespace when they appear between
-expressions. When they appear withing an expression, they are handled
-according to their usual syntax codes.
-
-The function @code{backward-prefix-chars} moves back over these
-characters, as well as over characters whose primary syntax class is
-prefix (@samp{'}).
-
-@item
-The @samp{b} comment style flag.
-
-Emacs can now supports two comment styles simultaneously. (This is for
-the sake of C++.) More specifically, it can recognize two different
-comment-start sequences. Both must share the same first character; only
-the second character may differ. Mark the second character of the
-@samp{b}-style comment start sequence with the @samp{b} flag. You can
-set this flag with @code{modify-syntax-entry} by including the letter
-@samp{b} in the syntax specification.
-
-The two styles of comment can have different comment-end sequences. A
-comment-end sequence (one or two characters) applies to the @samp{b}
-style if its first character has the @samp{b} flag set; otherwise, it
-applies to the @samp{a} style.
-
-The appropriate comment syntax settings for C++ are as follows:
-
-@table @asis
-@item @samp{/}
-@samp{124b}
-@item @samp{*}
-@samp{23}
-@item newline
-@samp{>b}
-@end table
-
-Thus @samp{/*} is a comment-start sequence for @samp{a} style, @samp{//}
-is a comment-start sequence for @samp{b} style, @samp{*/} is a
-comment-end sequence for @samp{a} style, and newline is a comment-end
-sequence for @samp{b} style.
-@end itemize
-@end itemize
-
-@section The Case Table
-
-You can customize case conversion using the new case table feature. A
-case table is a collection of strings that specifies the mapping between
-upper case and lower case letters. Each buffer has its own case table.
-You need a case table if you are using a language which has letters that
-are not standard ASCII letters.
-
-A case table is a list of this form:
-
-@example
-(@var{downcase} @var{upcase} @var{canonicalize} @var{equivalences})
-@end example
-
-@noindent
-where each element is either @code{nil} or a string of length 256. The
-element @var{downcase} says how to map each character to its lower-case
-equivalent. The element @var{upcase} maps each character to its
-upper-case equivalent. If lower and upper case characters are in 1-1
-correspondence, use @code{nil} for @var{upcase}; then Emacs deduces the
-upcase table from @var{downcase}.
-
-For some languages, upper and lower case letters are not in 1-1
-correspondence. There may be two different lower case letters with the
-same upper case equivalent. In these cases, you need to specify the
-maps for both directions.
-
-The element @var{canonicalize} maps each character to a canonical
-equivalent; any two characters that are related by case-conversion have
-the same canonical equivalent character.
-
-The element @var{equivalences} is a map that cyclicly permutes each
-equivalence class (of characters with the same canonical equivalent).
-
-You can provide @code{nil} for both @var{canonicalize} and
-@var{equivalences}, in which case both are deduced from @var{downcase}
-and @var{upcase}.
-
-Here are the functions for working with case tables:
-
-@code{case-table-p} is a predicate that says whether a Lisp object is a
-valid case table.
-
-@code{set-standard-case-table} takes one argument and makes that
-argument the case table for new buffers created subsequently.
-@code{standard-case-table} returns the current value of the new buffer
-case table.
-
-@code{current-case-table} returns the case table of the current buffer.
-@code{set-case-table} sets the current buffer's case table to the
-argument.
-
-@code{set-case-syntax-pair} is a convenient function for specifying a
-pair of letters, upper case and lower case. Call it with two arguments,
-the upper case letter and the lower case letter. It modifies the
-standard case table and a few syntax tables that are predefined in
-Emacs. This function is intended as a subroutine for packages that
-define non-ASCII character sets.
-
-Load the library @file{iso-syntax} to set up the syntax and case table for
-the 256 bit ISO Latin 1 character set.
-
-@section New Features for Dealing with Buffers
-
-@itemize @bullet
-@item
-The new function @code{buffer-modified-tick} returns a buffer's
-modification-count that ticks every time the buffer is modified. It
-takes one optional argument, which is the buffer you want to examine.
-If the argument is @code{nil} (or omitted), the current buffer is used.
-
-@item
-@code{buffer-disable-undo} is a new name for the function
-formerly known as @code{buffer-flush-undo}. This turns off recording
-of undo information in the buffer given as argument.
-
-@item
-The new function @code{generate-new-buffer-name} chooses a name that
-would be unique for a new buffer---but does not create the buffer. Give
-it one argument, a starting name. It produces a name not in use for a
-buffer by appending a number inside of @samp{<@dots{}>}.
-
-@item
-The function @code{rename-buffer} now takes an option second argument
-which tells it that if the specified new name corresponds to an existing
-buffer, it should use @code{generate-new-buffer-name} to modify the name
-to be unique, rather than signaling an error.
-
-@code{rename-buffer} now returns the name to which the buffer was
-renamed.
-
-@item
-The function @code{list-buffers} now looks at the local variable
-@code{list-buffers-directory} in each non-file-visiting buffer, and
-shows its value where the file would normally go. Dired sets this
-variable in each Dired buffer, so the buffer list now shows which
-directory each Dired buffer is editing.
-
-@item
-The function @code{other-buffer} now takes an optional second argument
-@var{visible-ok} which, if non-@code{nil}, indicates that buffers
-currently being displayed in windows may be returned even if there are
-other buffers not visible. Normally, @code{other-buffer} returns a
-currently visible buffer only as a last resort, if there are no suitable
-nonvisible buffers.
-
-@item
-The hook @code{kill-buffer-hook} now runs whenever a buffer is killed.
-@end itemize
-
-@section Local Variables Features
-
-@itemize @bullet
-@item
-If a local variable name has a non-@code{nil} @code{permanent-local}
-property, then @code{kill-all-local-variables} does not kill it. Such
-local variables are ``permanent''---they remain unchanged even if you
-select a different major mode.
-
-Permanent locals are useful when they have to do with where the file
-came from or how to save it, rather than with how to edit the contents.
-
-@item
-The function @code{make-local-variable} now never changes the value of the variable
-that it makes local. If the variable had no value before, it still has
-no value after becoming local.
-
-@item
-The new function @code{default-boundp} tells you whether a variable has
-a default value (as opposed to being unbound in its default value). If
-@code{(default-boundp 'foo)} returns @code{nil}, then
-@code{(default-value 'foo)} would get an error.
-
-@code{default-boundp} is to @code{default-value} as @code{boundp} is to
-@code{symbol-value}.
-
-@item
-The special forms @code{defconst} and @code{defvar}, when the variable
-is local in the current buffer, now set the variable's default value
-rather than its local value.
-@end itemize
-
-@section New Features for Subprocesses
-
-@itemize @bullet
-@item
-@code{call-process} and @code{call-process-region} now return a value
-that indicates how the synchronous subprocess terminated. It is either
-a number, which is the exit status of a process, or a signal name
-represented as a string.
-
-@item
-@code{process-status} now returns @code{open} and @code{closed} as the
-status values for network connections.
-
-@item
-The standard asynchronous subprocess features work on VMS now,
-and the special VMS asynchronous subprocess functions have been deleted.
-
-@item
-You can use the transaction queue feature for more convenient
-communication with subprocesses using transactions.
-
-Call @code{tq-create} to create a transaction queue communicating with a
-specified process. Then you can call @code{tq-enqueue} to send a
-transaction. @code{tq-enqueue} takes these five arguments:
-
-@example
-(tq-enqueue @var{tq} @var{question} @var{regexp} @var{closure} @var{fn})
-@end example
-
-@var{tq} is the queue to use. (Specifying the queue has the effect of
-specifying the process to talk to.) The argument @var{question} is the
-outgoing message which starts the transaction. The argument @var{fn} is
-the function to call when the corresponding answer comes back; it is
-called with two arguments: @var{closure}, and the answer received.
-
-The argument @var{regexp} is a regular expression to match the entire
-answer; that's how @code{tq-enqueue} tells where the answer ends.
-
-Call @code{tq-close} to shut down a transaction queue and terminate its
-subprocess.
-
-@item
-The function @code{signal-process} sends a signal to process @var{pid},
-which need not be a child of Emacs. The second argument @var{signal}
-specifies which signal to send; it should be an integer.
-@end itemize
-
-@section New Features for Dealing with Times And Time Delays
-
-@itemize @bullet
-@item
-The new function @code{current-time} returns the system's time value as
-a list of three integers: @code{(@var{high} @var{low} @var{microsec})}.
-The integers @var{high} and @var{low} combine to give the number of
-seconds since 0:00 January 1, 1970, which is @var{high} * 2**16 +
-@var{low}.
-
-@var{microsec} gives the microseconds since the start of the current
-second (or 0 for systems that return time only on the resolution of a
-second).
-
-@item
-The function @code{current-time-string} accepts an optional argument
-@var{time-value}. If given, this specifies a time to format instead of
-the current time. The argument should be a cons cell containing two
-integers, or a list whose first two elements are integers. Thus, you
-can use times obtained from @code{current-time} (see above) and from
-@code{file-attributes}.
-
-@item
-You can now find out the user's time zone using @code{current-time-zone}.
-It takes no arguments, and returns a list of this form:
-
-@example
-(@var{offset} @var{savings-flag} @var{standard} @var{savings})
-@end example
-
-@var{offset} is an integer specifying how many minutes east of Greenwich
-the current time zone is located. A negative value means west of
-Greenwich. Note that this describes the standard time; if daylight
-savings time is in effect, it does not affect this value.
-
-@var{savings-flag} is non-@code{nil} iff daylight savings time or some other
-sort of seasonal time adjustment is in effect.
-
-@var{standard} is a string giving the name of the time zone when no
-seasonal time adjustment is in effect.
-
-@var{savings} is a string giving the name of the time zone when there is a
-seasonal time adjustment in effect.
-
-If the user has specified a region that does not use a seasonal time
-adjustment, @var{savings-flag} is always @code{nil}, and @var{standard}
-and @var{savings} are equal.
-
-@item
-@code{sit-for}, @code{sleep-for} now let you specify the time period in
-milliseconds as well as in seconds. The first argument gives the number
-of seconds, as before, and the optional second argument gives additional
-milliseconds. The time periods specified by these two arguments are
-added together.
-
-Not all systems support this; you get an error if you specify nonzero
-milliseconds and it isn't supported.
-
-@code{sit-for} also accepts an optional third argument @var{nodisp}. If
-this is non-@code{nil}, @code{sit-for} does not redisplay. It still
-waits for the specified time or until input is available.
-
-@item
-@code{accept-process-output} now accepts a timeout specified by optional
-second and third arguments. The second argument specifies the number of
-seconds, while the third specifies the number of milliseconds. The time
-periods specified by these two arguments are added together.
-
-Not all systems support this; you get an error if you specify nonzero
-milliseconds and it isn't supported.
-
-The function returns @code{nil} if the timeout expired before output
-arrived, or non-@code{nil} if it did get some output.
-
-@item
-You can set up a timer to call a function at a specified future time.
-To do so, call @code{run-at-time}, like this:
-
-@example
-(run-at-time @var{time} @var{repeat} @var{function} @var{args}@dots{})
-@end example
-
-Here, @var{time} is a string saying when to call the function. The
-argument @var{function} is the function to call later, and @var{args}
-are the arguments to give it when it is called.
-
-The argument @var{repeat} specifies how often to repeat the call. If
-@var{repeat} is @code{nil}, there are no repetitions; @var{function} is
-called just once, at @var{time}. If @var{repeat} is an integer, it
-specifies a repetition period measured in seconds.
-
-Absolute times may be specified in a wide variety of formats; The form
-@samp{@var{hour}:@var{min}:@var{sec} @var{timezone}
-@var{month}/@var{day}/@var{year}}, where all fields are numbers, works;
-the format that @code{current-time-string} returns is also allowed.
-
-To specify a relative time, use numbers followed by units.
-For example:
-
-@table @samp
-@item 1 min
-denotes 1 minute from now.
-@item 1 min 5 sec
-denotes 65 seconds from now.
-@item 1 min 2 sec 3 hour 4 day 5 week 6 fortnight 7 month 8 year
-denotes exactly 103 months, 123 days, and 10862 seconds from now.
-@end table
-
-If @var{time} is an integer, that specifies a relative time measured in
-seconds.
-@end itemize
-
-To cancel the requested future action, pass the value that @code{run-at-time}
-returned to the function @code{cancel-timer}.
-
-@section Profiling Lisp Programs
-
-You can now make execution-time profiles of Emacs Lisp programs using
-the @file{profile} library. See the file @file{profile.el} for
-instructions; if you have written a Lisp program big enough to be worth
-profiling, you can surely understand them.
-
-@section New Features for Lisp Debuggers
-
-@itemize @bullet
-@item
-You can now specify which kinds of errors should invoke the Lisp
-debugger by setting the variable @code{debug-on-error} to a list of error
-conditions. For example, if you set it to the list @code{(void-variable)},
-then only errors about a variable that has no value invoke the
-debugger.
-
-@item
-The variable @code{command-debug-status} is used by Lisp debuggers. It
-records the debugging status of current interactive command. Each time
-a command is called interactively, this variable is bound to
-@code{nil}. The debugger can set this variable to leave information for
-future debugger invocations during the same command.
-
-The advantage of this variable over some other variable in the debugger
-itself is that the data will not be visible for any other command
-invocation.
-
-@item
-The function @code{backtrace-frame} is intended for use in Lisp
-debuggers. It returns information about what a frame on the Lisp call
-stack is doing. You specify one argument, which is the number of stack
-frames to count up from the current execution point.
-
-If that stack frame has not evaluated the arguments yet (or is a special
-form), the value is @code{(nil @var{function} @var{arg-forms}@dots{})}.
-
-If that stack frame has evaluated its arguments and called its function
-already, the value is @code{(t @var{function}
-@var{arg-values}@dots{})}.
-
-In the return value, @var{function} is whatever was supplied as @sc{car}
-of evaluated list, or a @code{lambda} expression in the case of a macro
-call. If the function has a @code{&rest} argument, that is represented
-as the tail of the list @var{arg-values}.
-
-If the argument is out of range, @code{backtrace-frame} returns
-@code{nil}.
-@end itemize
-
-@ignore
-
-@item
-@code{kill-ring-save} now gives visual feedback to indicate the region
-of text being added to the kill ring. If the opposite end of the
-region is visible in the current window, the cursor blinks there.
-Otherwise, some text from the other end of the region is displayed in
-the message area.
-@end ignore
-
-@section Memory Allocation Changes
-
-The list that @code{garbage-collect} returns now has one additional
-element. This is a cons cell containing two numbers. It gives
-information about the number of used and free floating point numbers,
-much as the first element gives such information about the number of
-used and free cons cells.
-
-The new function @code{memory-limit} returns an indication of the last
-address allocated by Emacs. More precisely, it returns that address
-divided by 1024. You can use this to get a general idea of how your
-actions affect the memory usage.
-
-@section Hook Changes
-
-@itemize @bullet
-@item
-Expanding an abbrev first runs the new hook
-@code{pre-abbrev-expand-hook}.
-
-@item
-The editor command loop runs the normal hook @code{pre-command-hook}
-before each command, and runs @code{post-command-hook} after each
-command.
-
-@item
-Auto-saving runs the new hook @code{auto-save-hook} before actually
-starting to save any files.
-
-@item
-The new variable @code{revert-buffer-insert-file-contents-function}
-holds a function that @code{revert-buffer} now uses to read in the
-contents of the reverted buffer---instead of calling
-@code{insert-file-contents}.
-
-@item
-The variable @code{lisp-indent-hook} has been renamed to
-@code{lisp-indent-function}.
-
-@item
-The variable @code{auto-fill-hook} has been renamed to
-@code{auto-fill-function}.
-
-@item
-The variable @code{blink-paren-hook} has been renamed to
-@code{blink-paren-function}.
-
-@item
-The variable @code{temp-buffer-show-hook} has been renamed to
-@code{temp-buffer-show-function}.
-
-@item
-The variable @code{suspend-hook} has been renamed to
-@code{suspend-hooks}, because it is a list of functions but is not a
-normal hook.
-
-@item
-The new function @code{add-hook} provides a handy way to add a function
-to a hook variable. For example,
-
-@example
-(add-hook 'text-mode-hook 'my-text-hook-function)
-@end example
-
-@noindent
-arranges to call @code{my-text-hook-function}
-when entering Text mode or related modes.
-@end itemize
-
-@bye
diff --git a/etc/FAQ b/etc/FAQ
deleted file mode 100644
index f2b316da0e5..00000000000
--- a/etc/FAQ
+++ /dev/null
@@ -1,3168 +0,0 @@
- GNU Emacs FAQ: Introduction
-
-This is the introduction to a list of frequently asked questions (FAQ)
-about GNU Emacs with answers.
-
-The FAQ 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 to a question in the FAQ list, please reply to the
-question by e-mail instead of posting. Help reduce noise!
-
-The FAQ is crossposted to `comp.emacs' because some sites do not receive
-the `gnu.*' newsgroups. The FAQ is also crossposted to `news.answers'.
-
-Full instructions for getting the latest FAQ are in question 22.
-
-It has been so long since the FAQ was last edited and released that the
-maintainers decided to take a two-step approach. This edition corrects
-many basic inaccuracies in the old FAQ, most of them having to do with ftp
-sites and version numbers. In addition, we have deleted a number of
-questions that are no longer relevant with the release of GNU Emacs 19.
-
-Many questions specific to recent releases of GNU Emacs 19 remain
-unanswered in this version of the FAQ; the maintainers will spend time over
-the next month or two adding new questions (and answers), based in no small
-part on the questions that have come across help-gnu-emacs in recent
-months.
-
-There is no diff file for this version of the FAQ, as many things have
-changed since it was last updated.
-
-Please suggest new questions, answers, wording changes, deletions, etc.
-The most helpful form for suggestions is a context diff (i.e., 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. :-(
-
---
-Reuven M. Lerner <reuven@the-tech.mit.edu> and the FAQ team (a full list is
-at the bottom of the FAQ).
-
-----------------------------------------------------------------------
-
-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?
-
-General Questions
-
-6: What is the LPF?
-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?
-
-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: What is different about GNU Emacs 19?
-
-Common Things People Want To Do
-
-26: How do I set up a .emacs file properly?
-27: How do I debug a .emacs file?
-28: How do I make Emacs display the current line (or column) number?
-29: How do I turn on abbrevs by default just in mode XXX?
-30: How do I turn on auto-fill mode by default?
-31: How do I make Emacs use a certain major mode for certain files?
-32: How do I search for, delete, or replace unprintable (8-bit or control)
- characters?
-33: How can I highlight a region of text in Emacs?
-34: How do I control Emacs's case-sensitivity when searching/replacing?
-35: How do I make Emacs wrap words for me?
-36: Where can I get a better spelling checker for Emacs?
-37: How can I spell-check TeX or *roff documents?
-38: How do I change load-path?
-39: How do I use an already running Emacs from another window?
-40: How do I make Emacs recognize my compiler's funny error messages?
-41: How do I indent switch statements like this?
-42: How can I make Emacs automatically scroll horizontally?
-43: How do I make Emacs "typeover" or "overwrite" instead of inserting?
-44: How do I stop Emacs from beeping on a terminal?
-45: How do I turn down the bell volume in Emacs running under X Windows?
-46: How do I tell Emacs to automatically indent a new line to the
- indentation of the previous line?
-47: How do I show which parenthesis matches the one I'm looking at?
-48: In C mode, can I show just the lines that will be left after #ifdef
- commands are handled by the compiler?
-49: Is there an equivalent to the `.' (dot) command of vi?
-50: What are the valid X resource settings (i.e., stuff in .Xdefaults)?
-51: How do I execute a piece of Emacs Lisp code?
-52: How do I change Emacs's idea of the tab character's length?
-53: How do I insert `>' at the beginning of every line?
-54: How do I insert `_^H' before each character in a paragraph to get an
- underlined paragraph?
-55: How do I repeat a command as many times as possible?
-56: 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?
-57: How do I tell Emacs to iconify itself?
-58: How do I use regexps (regular expressions) in Emacs?
-59: How do I perform a replace operation across more than one file?
-60: Where is the documentation for `etags'?
-
-Bugs/Problems
-
-61: Does Emacs have problems with files larger than 8 megabytes?
-62: How do I get rid of the ^M junk in my shell buffer?
-63: Why do I get `Process shell exited abnormally with code 1'?
-64: Where is the termcap/terminfo entry for terminal type `emacs'?
-65: Why does Emacs spontaneously start displaying `I-search:' and beeping?
-66: Why can't Emacs talk to certain hosts (or certain hostnames)?
-67: Why does Emacs say `Error in init file'?
-68: Why does Emacs ignore my X resources (my .Xdefaults file)?
-69: Why does Emacs take 20 seconds to visit a file?
-70: How do I edit a file with a `$' in its name?
-71: Why does shell mode lose track of the shell's current directory?
-72: Are there any security risks in GNU Emacs?
-
-Difficulties Building/Installing/Porting Emacs
-
-73: What should I do if I have trouble building Emacs?
-74: How do I stop Emacs from failing when the executable is stripped?
-75: Why does linking Emacs with -lX11 fail?
-
-Finding/Getting Emacs and Related Packages
-
-76: Where can I get GNU Emacs on the net (or by snail mail)?
-77: How do I find a GNU Emacs Lisp package that does XXX?
-78: Where can I get GNU Emacs Lisp packages that don't come with Emacs?
-79: How do I submit code to the Emacs Lisp Archive?
-80: Where can I get other up-to-date GNU stuff?
-81: What is the difference between GNU Emacs and Epoch?
-82: What is the difference between GNU Emacs and XEmacs (formerly "Lucid
- Emacs")?
-83: Where can I get Emacs for my PC running MS-DOS?
-84: Where can I get Emacs for my PC running Microsoft Windows?
-85: Where can I get Emacs for my PC running OS/2?
-86: Where can I get Emacs for my Atari ST?
-87: Where can I get Emacs for my Amiga?
-88: Where can I get Emacs for my Apple computer?
-89: Where do I get Emacs that runs on VMS under DECwindows?
-90: Where can I get modes for Lex, Yacc/Bison, Bourne shell, Csh, C++,
- Objective C, Pascal, and Awk?
-91: What is the IP address of XXX.YYY.ZZZ?
-
-Major Emacs Lisp Packages, Emacs Extensions, and Related Programs
-
-92: VM (View Mail) -- another mail reader within Emacs
-93: Supercite -- mail and news citation package within Emacs
-94: Gnus -- news reader within Emacs
-95: Calc -- poor man's Mathematica within Emacs
-96: Ange-FTP -- transparent FTP access for Emacs's file access routines
-97: VIP -- vi emulation for Emacs
-98: AUC TeX -- enhanced LaTeX mode with debugging facilities
-99: Hyperbole -- extensible hypertext management system within Emacs
-100: BBDB -- personal Info Rolodex integrated with mail/news readers
-101: Ispell -- spell checker in C with interface for Emacs
-102: XEmacs -- alternative Emacs 19 with better X interface; formerly
- known as Lucid Emacs or lemacs.
-103: Patch -- program to apply "diffs" for updating files
-
-Changing Key Bindings and Handling Key Binding Problems
-
-104: How do I bind keys (including function keys) to commands?
-105: Why does Emacs say `Key sequence XXX uses invalid prefix characters'?
-106: Why doesn't this [terminal or window-system setup] code work in my
- .emacs file, but it works just fine after Emacs starts up?
-107: How do I use function keys under X Windows?
-108: How do I tell what characters or symbols my function or arrow keys
- emit?
-109: How do I set the X key "translations" for Emacs?
-110: How do I handle C-s and C-q being used for flow control?
-111: How do I bind `C-s' and `C-q' (or any key) if these keys are filtered
- out?
-112: Why does the `Backspace' key invoke help?
-113: Why doesn't Emacs look at the stty settings for Backspace vs. Delete?
-114: How do I "swap" two keys?
-115: How do I produce C-XXX with my keyboard?
-116: What if I don't have a Meta key?
-117: What if I don't have an Escape key?
-118: Can I make my `Compose Character' key behave like a Meta key?
-119: How do I bind a combination of modifier key and function key?
-120: Why doesn't my Meta key work in an xterm window?
-121: Why doesn't my ExtendChar key work as a Meta key under HP-UX 8.0?
-122: Where can I get key bindings to make Emacs emulate WordStar?
-123: Where can I get an XEDIT emulator for Emacs?
-
-Using Emacs with Alternate Character Sets
-
-124: How do I make Emacs display 8-bit characters?
-125: How do I input 8-bit characters?
-126: Where can I get an Emacs that can handle kanji characters?
-127: Where can I get an Emacs that can handle Chinese?
-128: Where is an Emacs that can handle Semitic (right-to-left) alphabets?
-
-Mail and News
-
-129: How do I change the included text prefix in mail/news followups?
-130: How do I save a copy of outgoing mail?
-131: Why doesn't Emacs expand my aliases when sending mail?
-132: Why does Rmail think all my saved messages are one big message?
-133: How can I sort the messages in my Rmail folder?
-134: Why does Rmail need to write to /usr/spool/mail?
-135: How do I recover my mail files after Rmail munges their format?
-136: How do I make Emacs automatically start my mail/news reader?
-137: How do I read news under Emacs?
-138: Why doesn't Gnus work via NNTP?
-139: How do I view text with embedded underlining (e.g., ClariNews)?
-140: How do I save all the items of a multi-part posting in Gnus?
-141: Why does Gnus put the subjects in replies beyond the 80th column?
-142: How do I make Gnus start up faster?
-143: How do I catch up all newsgroups in Gnus?
-144: Why can't I kill in Gnus on the Newsgroups/Keywords/Control line?
-145: How do I get rid of flashing messages in Gnus for slow connections?
-146: Why is catch up slow in Gnus?
-147: Why does Gnus hang for a long time when posting?
-148: Why don't my news postings in Gnus get past the local machine?
-149: Why doesn't Gnus generate the `Lines:' header?
-150: How do I kill all articles in Gnus but those matching a pattern?
-
-------------------------------------------------------------
-
-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.
-
-Full instructions for getting the latest FAQ are in question 22, or use
-anonymous FTP to the-tech.mit.edu.
-
-Notation Used in FAQ
-
- Skip this section and then come back if you don't understand some of the
- later answers.
-
-1: What do these mean: C-h, M-C-a, RET, "ESC a", etc.?
-
- 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.
-
- Key sequences longer than one key (and some single-key sequences) are
- inside double quotes or on lines by themselves. Any real spaces in such
- a key sequence should be ignored; only SPC really means press the space
- key.
-
- 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.
-
- For further information, see `Characters' and `Keys' in the on-line
- manual.
-
- 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.
-
-2: What does "M-x command" mean?
-
- "M-x command" means type M-x, then type the name of the command, then
- type RET.
-
- 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, "?" for a list of possibilities, and M-p and
- M-n to see previous commands entered. An Emacs "command" is any
- "interactive" Emacs function.
-
- 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.
-
- To run non-interactive Emacs functions, see question 51.
-
-3: How do I read topic XXX in the on-line manual?
-
- When we 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:
-
- C-h i m emacs RET m XXX RET
-
- This invokes Info, the GNU hypertext documentation browser. If you don't
- already know how to use Info, type "?" from within Info.
-
- If we refer to topic XXX:YYY, type this:
-
- C-h i m emacs RET m XXX RET m YYY RET
-
- WARNING: Your system administrator may not have installed the Info files,
- or may have installed them improperly. In this case you should complain.
-
-4: What do these mean: etc/SERVICE, src/config.h, lisp/default.el?
-
- 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 data-directory RET". The directory name
- 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 20. All are available in the source distribution.
-
- WARNING: Your system administrator may have removed the src directory and
- many files from the etc directory.
-
-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 Matthew Stallman
- FTP == File Transfer Protocol
- GPL == GNU General Public Licence
-
- 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 consortium of
- computer vendors which develops commercial software for Unix systems.
-
- 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.
-
-
-General Questions
-
-6: What is the LPF?
-
- 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 Joe Wells
- <jbw@cs.bu.edu>; he will be happy to talk with you about the LPF.
-
- You can find more information about the LPF in the file etc/LPF. More
- 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) will
- only be known if and when a judge rules on its validity and scope. There
- has never been a copyright infringement 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.
-
- RMS writes:
-
- 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.
-
-8: What are appropriate messages for gnu.emacs.help, gnu.emacs.bug,
- comp.emacs, etc.?
-
- 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.
-
- 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, and Epsilon..
-
- 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.
-
- 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.
-
- gnu.emacs.bug is a place where bug reports appear, but avoid posting bug
- reports to this newsgroup (see question 10).
-
-9: Where can I get old postings to gnu.emacs.help and other GNU groups?
-
- 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. The archive is
- available via anonymous ftp at
-
- /prep.ai.mit.edu:pub/gnu/MailingListArchives/
-
-10: Where should I report bugs and other problems with 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.
-
- RMS explains:
-
- 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.
-
- However, RMS says there are circumstances when it is okay to post to
- gnu.emacs.help:
-
- 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.
-
- If you are unsure whether you have a bug, RMS describes how to tell:
-
- ... 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.
-
-11: How do I unsubscribe to this mailing list?
-
- 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 receive 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.
-
-12: What is the current address of the FSF?
-
- E-mail address: gnu@prep.ai.mit.edu
- Phone number: (617) 542-5942
- Postal address:
- Free Software Foundation, Inc.
- 59 Temple Place - Suite 330
- Boston, MA 02111-1307, USA.
-
- For details on how to order, see the file etc/ORDERS.
-
-
-On-line Help, Printed Manuals, Other Sources of Help
-
-13: I'm just starting GNU Emacs; how do I do basic editing?
-
- Type "C-h t" to invoke the self-paced tutorial. Typing just C-h is how
- to enter the help system.
-
- WARNING: Your system administrator may have changed C-h to act like DEL
- to deal with 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.
-
- NOTE: Emacs help works best if it 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.
-
-14: How do I find out how to do something in GNU Emacs?
-
- There are several methods for finding out how to do things in Emacs.
-
- * The complete text of the Emacs manual is available on-line 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 or etc/refcard.ps files
- in the Emacs distribution.
-
- * 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).
-
- * You can list all of the functions and variables whose names contain a
- certain word using M-x apropos.
-
- * 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: 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
- details see the file etc/ORDERS.
-
- 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
- 420 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:
-
- /ftp.cs.ubc.ca:pub/archive/gnu/manuals_ps/emacs-19.21.ps.gz
-
- This 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.gz
-
- and all prep mirrors (See question 80 for a list).
-
- A WWW version of the Emacs manual is available on the World-Wide Web at
- URL
-
- http://asis01.cern.ch/infohtml/emacs/emacs.html
-
- See also question 14 for how to view the manual on-line.
-
-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.
- Details on ordering it from FSF are in file etc/ORDERS.
-
- For on-line use, a set of pregenerated Info files is available with the
- Texinfo source for the Emacs Lisp manual via anonymous FTP at
-
- /prep.ai.mit.edu:pub/gnu/elisp-manual-19-2.3.tar.gz
-
- and all prep mirrors (See question 80 for a list).
-
- You can also create the Info files from the Texinfo source. See question
- 17 for details on how to install these files on-line.
-
- A WWW version of the Emacs Lisp Reference Manual is available at
-
- http://www.cs.indiana.edu/usr/local/www/elisp/lispref/elisp_toc.html
-
- An introduction to Emacs Lisp is available at
-
- http://www.cs.indiana.edu/usr/local/www/elisp/elisp-intro.html
-
- Of course, you can also print this 760-page manual yourself. For
- instructions on how to do this, see question 18.
-
-17: How do I install a piece of Texinfo documentation?
-
- First, you must turn the Texinfo files into Info files. You may do this
- within Emacs, using "M-x texinfo-format-buffer", or with the standalone
- `makeinfo' program, available as part of the latest Texinfo package via
- anonymous ftp from:
-
- /prep.ai.mit.edu:pub/gnu/texinfo-3.1.tar.gz
-
- and all prep mirrors (See question 80 for a list).
-
- 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 on-line.
-
- Neither texinfo-format-buffer nor makeinfo installs the resulting Info
- files in Emacs's Info tree. To install Info files:
-
- 1. Move the files to the `info' directory in the installed Emacs
- distribution. See question 4 if you don't know where that is.
-
- 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 already in this file. The format is:
-
- * Topic: (relative-pathname). Short description of topic.
-
- If you want to install Info files and you don't have the necessary
- privileges, you have several options:
-
- * 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 adding its pathname to the value of the variable
- Info-default-directory-list. For example, to use a private Info
- directory which is a subdirectory of your home directory named `Info',
- you could put this in your .emacs file:
-
- (setq Info-default-directory-list
- (cons "~/Info" Info-default-directory-list))
-
- You will need a top-level Info file named `dir' in this directory which
- has everything the system dir file has in it, except it should list
- only entries for Info files in that directory. You might not need it
- if all files in this directory were referenced by other `dir' files.
- The node lists from all dir files in Info-default-directory-list are
- merged by the Info system.
-
-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).
-
- 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', `tkinfo', and `ivinfo' programs do this. Info
- uses curses, xinfo uses standard X11 libraries, tkinfo uses Tk/Tcl 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.gz
-
- and all prep mirrors (See question 80 for a list).
-
- ivinfo is available in a comp.sources.misc archive or from Tom Horsley
- <tom@ssd.csd.harris.com>. tkinfo is available by anonymous ftp from:
-
- /ptolemy.eecs.berkeley.edu:pub/misc/tkinfo-0.6.tar.Z
- /ftp.aud.alcatel.com:tcl/code/tkinfo-0.6.tar.gz
-
- For ivinfo, you need Stanford's InterViews C++ X library, available via
- anonymous ftp from interviews.stanford.edu. (A FAQ on InterViews is
- available at that site in pub/FAQ.)
-
-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 doesn'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
- GNU -- The GNU Manifesto
- INTERVIEW -- Richard Stallman discusses his public-domain
- UNIX-compatible software system with BYTE editors
- MACHINES -- Status of GNU Emacs on Various Machines and Systems
- MAILINGLISTS -- GNU Project Electronic Mailing Lists
- SERVICE -- GNU Service Directory
- SUN-SUPPORT -- including "Using Emacstool with GNU Emacs"
-
- These files are available in the `etc' directory of the GNU Emacs
- distribution:
-
- 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)
-
- 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
- (See question 80 for a list).
-
- These additional files are available from the FSF via e-mail:
-
- * GNU's Bulletin, January 1994
- GNU's Who
- GNU's Bulletin
- What Is the Free Software Foundation?
- What Is Copyleft?
- Donations Translate Into Free Software
- Cygnus Matches Donations!
- GNUs Flashes
- What Is the LPF?
- News from the LPF
- Free Software Support
- Project GNU Wish List
- Towards a New Strategy of OS Design
- Part 1: A More Usable Approach to OS Design
- Part 2: A Look at Some of the Hurd's Beasts
- Second Annual GNU Seminar in Japan
- GNU and other Free Software in Japan
- Freely Available Texts
- OCEAN Integrated-Circuit Design System
- Hundred Acre Consulting Expands
- Project GNU Status Report
- GNU Documentation
- GNU Software Available Now
- Source Code CD-ROM
- Compiler Tools Binaries CD-ROM
- Tape & CD-ROM Subscription Service
- How to Get GNU Software
- The Deluxe Distribution
- MS-DOS Distribution
- Free Software for Microcomputers
- FSF T-shirt
- Thank GNUs
- Free Software Foundation Order Form
- * Legal issues about contributing code to GNU
- * GNU Project Status Report
-
- A collection of past GNU's Bulletins is available via anonymous FTP from:
-
- /ftp.funet.fi:pub/gnu/Bulletins/
-
- The latest bulletin is available on the World-Wide Web at URL:
-
- http://info.desy.de/gnu/www/gnu_bulletin_9401/gnu_bulletin_9401_toc.html
-
-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).
-
- You might also try the help-gnu-emacs mailing list, which is also known
- as the gnu.emacs.help newsgroup, although many installation questions can
- easily be answered by looking at the PROBLEMS file (in the top-level
- directory when you unpack the Emacs source).
-
-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 should 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 c-x c-s" from the *Summary* buffer or
- "C-u SPC" from the *Newsgroup* buffer to view all articles in a
- newsgroup.
-
- 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 for
- a while.
-
- * Via anonymous FTP. You can fetch the FAQ articles via anonymous FTP
- from the-tech.mit.edu, in ~ftp/pub/GNU-Emacs/.
-
- * 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.
-
- * Via the World-Wide Web. Point your favorite Web browser (Mosaic, Lynx,
- w3-mode) to one of the following URLs:
-
- http://www.cis.ohio-state.edu/hypertext/faq/usenet/GNU-Emacs-FAQ/top.html
- http://scwww.ucs.indiana.edu/FAQ/Emacs/
-
- * If all goes well, this FAQ should also be available via anonymous ftp
- and e-mail from rtfm.mit.edu, the main repository for FAQs and other
- items posted to news.answers. However, we are omitting explicit
- directions on how to retrieve the FAQ from rtfm.mit.edu, since it's
- possible that it won't end up there right away. (We're new at this
- FAQ-posting business.) Instructions on how to retrieve the FAQ from
- rtfm.mit.edu should be in the next version of the FAQ.
-
- * 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.
-
-Status of Emacs
-
-23: Where does the name "Emacs" come from?
-
- 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 key bindings at MIT.
-
- Many people have said that TECO code looks a lot like line noise. See
- alt.lang.teco if you are interested. 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.
-
-24: What is the latest version of GNU Emacs?
-
- GNU Emacs 19.27 is the current version as of 6 September, 1994.
-
-25: What is different about GNU Emacs 19?
-
- To find out what has changed in recent versions, type C-h n (M-x
- view-emacs-news). The oldest changes are at the bottom of the file, so
- you might want to read it starting there, rather than at the top.
-
- The most obvious changes have to do with the user interface -- GNU Emacs
- 19 is fully X-aware, and provides pull-down menus and scroll bars. Emacs
- 19 also supports fonts and colors, including context-specific
- highlighting of source code and other types of buffers.
-
- Other changes include a line number mode, which displays the current line
- number in the mode line, and default bindings for arrow and paging keys
- that work.
-
- Lower-level changes include a smarter memory allocation scheme (Emacs now
- returns memory to the operating system when you kill buffers), a better
- byte-compiler, and a source-level Emacs Lisp debugger.
-
- There are also a number of new Lisp packages, ranging from dunnet (an
- Adventure-like program) to mldrag (allows you to drag the mode line up
- and down with the mouse buttons) to gud (Grand Unified Debugger mode, for
- many flavors of debuggers). A number of popular Lisp packages, such as
- SuperCite and the calendar/diary, are also included.
-
-Common Things People Want To Do
-
-26: How do I set up a .emacs file properly?
-
- See `Init File' in the on-line manual.
-
- 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. :-)
-
-27: How do I debug a .emacs file?
-
- First start Emacs with the `-debug-init' command-line option. This
- option enables the Emacs Lisp debugger before evaluating your .emacs
- file, and places you in the debugger if something goes wrong. The top
- line in the trace-back buffer will be the error message, and the second
- or third line of that buffer will display the Lisp code from your .emacs
- that caused the problem.
-
- You can also evaluate an individual function or argument to a function in
- your .emacs file by moving the cursor to the end of the function or
- argument and typing "C-x C-e" (M-x eval-last-sexp).
-
- Use "C-h v" (M-x describe-variable) to check the value of variables which
- you are trying to set or use.
-
-28: How do I make Emacs display the current line (or column) number?
-
- 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)".
-
- If you use these commands often, you might want to bind them to a key.
- See question 104 for instructions on how to do that.
-
- Typing "C-x l" (or M-x count-lines-page) 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.
-
- To have Emacs automatically display the current line number of the point
- in the mode line, do "M-x line-number-mode". You can also put the form
-
- (setq line-number-mode t)
-
- in your .emacs file to achieve this whenever you start Emacs. Note that
- Emacs will not display the line number if the buffer is larger than the
- value of the variable line-number-display-limit.
-
- None of the vi emulation modes provide the `set number' capability of vi
- (as far as we know).
-
-29: How do I turn on abbrevs by default just in mode XXX?
-
- Put this in your .emacs file:
-
- (condition-case ()
- (quietly-read-abbrev-file)
- (file-error nil))
-
- (add-hook 'XXX-mode-hook
- (function
- (lambda ()
- (setq abbrev-mode t))))
-
-30: How do I turn on auto-fill mode by default?
-
- 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:
-
- (add-hook 'text-mode-hook 'turn-on-auto-fill)
-
- If you want auto-fill mode on in all major modes, do this:
-
- (setq-default auto-fill-hook 'do-auto-fill)
-
-31: How do I make Emacs use a certain major mode for certain files?
-
- If you want to use XXX mode for all files which end with the extension
- `.YYY', this will do it for you:
-
- (setq auto-mode-alist (cons '("\\.YYY\\'" . XXX-mode) auto-mode-alist))
-
- Otherwise put this somewhere in the first line of any file you want to
- edit in XXX mode:
-
- -*-XXX-*-
-
- Emacs 19 also includes a new variable, interpreter-mode-alist, that
- specifies which mode to use when loading a shell script. (Emacs
- determines which interpreter you're using by examining the first line of
- the file.) This feature only applies when the file name doesn't indicate
- which mode to use. Use "C-h v" (or M-x describe-variable) to learn more
- about this variable.
-
-32: 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 (i.e., 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 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. To replace all unprintable characters
- with a colon, use:
-
- M-x replace-regexp RET [^ TAB C-q LFD C-q RET C-q C-l SPC -~] RET : RET
-
- NOTE: * You don't need to quote TAB with either isearch or typing
- something in the minibuffer.
-
-33: How can I highlight a region of text in Emacs?
-
- If you are using a windowing system such as X, you can cause the region
- to be highlighted when the mark is active by including
-
- (transient-mark-mode t)
-
- in your .emacs. There are also the following packages for content- based
- highlighting:
-
- hilit19.el
- font-lock.el
-
-34: 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:
-
- (add-hook 'XXX-mode-hook
- (function
- (lambda ()
- (setq case-fold-search nil))))
-
-35: How do I make Emacs wrap words for me?
-
- Use auto-fill mode, activated by typing "M-x auto-fill-mode". The
- default maximum line width is 70, determined by the variable fill-column.
- To learn how to turn this on automatically, see question 30.
-
-36: Where can I get a better spelling checker for Emacs?
-
- Use Ispell. See question 101.
-
-37: How can I spell-check TeX or *roff documents?
-
- Use Ispell. See question 101. Ispell can handle TeX and *roff
- documents.
-
-38: 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 (cons "/XXX/YYY/" load-path))
-
- To do this relative to your home directory:
-
- (setq load-path (cons "~/YYY/" load-path)
-
-39: 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 #" (or M-x server-edit) to indicate this.
- If there is another buffer requested by emacsclient, Emacs will switch
- to it; otherwise emacsclient will exit, signaling the calling program
- to continue.
-
- 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).
-
-40: How do I make Emacs recognize my compiler's funny error messages?
-
- The variable compilation-error-regexp-alist helps control how Emacs
- parses your compiler output. It is a list of triples of the form:
-
- (REGEXP FILE-IDX LINE-IDX)
-
- where REGEXP, FILE-IDX and LINE-IDX are strings. To help determine what
- the constituent elements should be, load compile.el and then use
-
- C-h v compilation-error-regexp-alist RET
-
- to see the current value. A good idea is to look at compile.el itself as
- the comments included for this variable are quite useful -- the regular
- expressions required for your compiler's output may be very close to one
- already provided. Once you have determined the proper regexps, use the
- following to inform Emacs of your changes:
-
- (setq compilation-error-regexp-alist
- (cons '(REGEXP FILE-IDX LINE-IDX)
- compilation-error-regexp-alist))
-
-41: 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;
- }
- }
-
- The solution at first appears to be: set c-indent-level to 4 and
- c-label-offset to -2. However, this will give you an indentation spacing
- of four instead of two.
-
- The solution is to use cc-mode (available from the Emacs Lisp Archive)
- and add the following line:
-
- (c-set-offset 'case-label '+)
-
- There appears to be no way to do this with the old c-mode.
-
-42: How can I make Emacs automatically scroll horizontally?
-
- Use hscroll.el by Wayne Mesard <wmesard@esd.sgi.com>.
-
-43: How do I make Emacs "typeover" or "overwrite" instead of inserting?
-
- M-x overwrite-mode (a minor mode).
-
- On some workstations, the "Insert" key toggles insert and overwrite
- modes.
-
-44: 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)
-
-45: How do I turn down the bell volume in Emacs running under X Windows?
-
- You can adjust the bell volume and duration for all programs with the
- shell command xset.
-
- Invoking xset without any arguments produces some basic information,
- including the following:
-
- usage: xset [-display host:dpy] option ...
- To turn bell off:
- -b b off b 0
- To set bell volume, pitch and duration:
- b [vol [pitch [dur]]] b on
-
-46: 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 30), 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.
-
-47: How do I show which parenthesis matches the one I'm looking at?
-
- GNU Emacs 19 comes with paren.el, which (when loaded) will automatically
- highlight matching parentheses whenever point (i.e., the cursor) is
- located over one. To load paren automatically, include the line
-
- (require 'paren)
-
- in your .emacs file.
-
- Alternatives to paren include:
-
- * 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 one set
- of 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)))))
-
-48: 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.)
-
-49: 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 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, use keyboard macros. (See `Keyboard
- Macros' in the on-line manual.)
-
-50: What are the valid X resource settings (i.e., stuff in .Xdefaults)?
-
- See Emacs man page, or "Resources X" in the on-line manual.
-
- You can also use a resource editor, such as editres (for X11R5 and
- onwards), to look at the resource names for the menu bar, assuming Emacs
- was compiled with the X toolkit.
-
-51: 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
-
-52: How do I change Emacs's idea of the tab character's length?
-
- Set the variable default-tab-width. For example, to set tab stops every
- 10 characters, insert the following in your .emacs file:
-
- (setq default-tab-width 10)
-
-53: 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 n M-x replace-regexp RET ^ RET
- > RET C-x w".
-
- WARNING: The command narrow-to-region (C-x n n) is disabled by default
- because it can be very confusing (i.e., "Oh no! Where did my file go?").
-
-54: How do I insert `_^H' before each character in a paragraph to get an
- underlined paragraph?
-
- M-x underline-region.
-
-55: 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.
-
-56: 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 ...)
-
-57: How do I tell Emacs to iconify itself?
-
- "C-z" iconifies Emacs when running in X and suspends Emacs otherwise.
- See `Misc X' in the on-line manual.
-
-58: How do I use regexps (regular expressions) in Emacs?
-
- See `Regexps' in the on-line 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 (e.g., `\sw') are not meaningful
- inside character set regexps (e.g., `[aeiou]'). (This is actually
- typical for regexp syntax.)
-
-59: 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 on-line 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
-
- NOTE: These files are compressed using GNU zip ("gzip"); you can get a
- copy from gzip from prep and its mirrors (see question 80).
-
-60: Where is the documentation for `etags'?
-
- The `etags' man page should be in the same place as the `emacs' man page.
-
- Quick command-line switch descriptions are also available. For example,
- `etags -H'.
-
-
-Bugs/Problems
-
-61: Does Emacs have problems with files larger than 8 megabytes?
-[This problem has been solved better in Emacs 19.29 because the buffer
-size limit is now 16 times as large.]
-
- 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
-
- WARNING: This method may result in `ILLEGAL DATATYPE' and other random
- errors on some machines.
-
- David Gillespie <daveg@csvax.cs.caltech.edu> gives an explanation of why
- Emacs uses 24 bit integers and pointers:
-
- 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.
-
- 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.
-
-62: How do I get rid of the ^M junk in my shell buffer?
-
- Try typing "M-x shell-strip-ctrl-m RET" while in shell-mode to make them
- go away. If that doesn't work, you have several options:
-
- 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.)
-
-63: 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. Compile this program for your architecture, and
- install it with a+x permission in the architecture-dependent Emacs
- program directory. (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".)
-
- You should also check for other programs named `env' in your path (e.g.,
- SunOS has a program named /usr/bin/env). We don't understand why this
- can cause a failure and 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.
-
- It has been reported that this sometimes happened when Emacs was started
- as an X client from an xterm window (i.e., had a controlling tty) but the
- xterm was later terminated.
-
- See also PROBLEMS (in the top-level directory when you unpack the Emacs
- source) for other possible causes of this message.
-
-64: 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 (e.g., 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
-
-65: 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 110.
-
-66: 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 gethostbyname 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.
-
-67: 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 27.
-
- 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 106.
-
-68: Why does Emacs ignore my X resources (my .Xdefaults file)?
-
- As of version 19, Emacs searches for X resources in the files specified
- by the XFILESEARCHPATH, XUSERFILESEARCHPATH, and XAPPLRESDIR environment
- variables, emulating the functionality provided by programs written using
- Xt.
-
- XFILESEARCHPATH and XUSERFILESEARCHPATH should be a list of file names
- separated by colons; XAPPLRESDIR should be a list of directory names
- separated by colons.
-
- Emacs searches for X resources
-
- + specified on the command line, with the `-xrm RESOURCESTRING'
- option,
- + then in the value of the XENVIRONMENT environment variable,
- - or if that is unset, in the file named ~/.Xdefaults-HOSTNAME if it
- exists
- (where HOSTNAME is the hostname of the machine Emacs is running on),
- + then in the screen-specific and server-wide resource properties
- provided by the server,
- - or if those properties are unset, in the file named ~/.Xdefaults
- if it exists,
- + then in the files listed in XUSERFILESEARCHPATH,
- - or in files named LANG/Emacs in directories listed in XAPPLRESDIR
- (where LANG is the value of the LANG environment variable), if
- the LANG environment variable is set,
- - or in files named Emacs in the directories listed in XAPPLRESDIR
- - or in ~/LANG/Emacs (if the LANG environment variable is set),
- - or in ~/Emacs,
- + then in the files listed in XFILESEARCHPATH.
-
-69: 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.
-
-70: 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.
-
-71: 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 77).
-
- You can tell Emacs the shell's current directory with the command "M-x
- dirs".
-
-72: Are there any security risks in GNU Emacs?
-
- * the `movemail' incident (No, this is not a risk.)
-
- In his book "The Cuckoo's Egg," Cliff Stoll describes this in chapter
- 4. The site at LBL had installed the `etc/movemail' program setuid
- root. (As of version 19, movemail is in your architecture-specific
- directory; type "C-h v directory RET" to see what it is.) Since
- `movemail' had not been designed for this situation, a security hole
- was created and users could get root privileges.
-
- `movemail' has since been changed so that even if it is installed
- setuid root this security hole will not be a result.
-
- We 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 on-line manual
- (which, incidentally, does not describe how to disable the feature).
-
- * 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 workstation can make your Emacs process do
- anything, including run other processes with your privileges.
-
- 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.
-
-
-Difficulties Building/Installing/Porting Emacs
-
-73: What should I do if I have trouble building Emacs?
-
- First look in the file PROBLEMS (in the top-level directory when you
- unpack the Emacs source) 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.
-
-74: 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.
-
-75: 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.
-
-
-Finding/Getting Emacs and Related Packages
-
-76: 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 and etc/ORDERS for mail orders. If you don't already have
- GNU Emacs, see question 20 for how to get these files.
-
- The latest version is always available via anonymous FTP at MIT:
-
- /prep.ai.mit.edu:pub/gnu/emacs-19.27.tar.gz
-
- See question 80 for information on where to get other GNU software.
-
-77: 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>. You can search
- through this list to learn if someone has written something that fits
- your needs.
-
- This list is file LCD-datafile.Z in the Emacs Lisp Archive (see the next
- question for retrieval instructions). The files lispdir.el.Z and
- lispdir.doc in the archive contain Lisp code and 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 search the listing.
- For example, the command `M-x lisp-dir-apropos RET ange-ftp RET' produces
- this output:
-
- GNU Emacs Lisp Code Directory Apropos -- "ange-ftp"
- "~/" refers to archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/
-
- ange-ftp (4.18) 15-Jul-1992
- Andy Norman, <ange@hplb.hpl.hp.com>
- ~/packages/ange-ftp.tar.Z
- transparent FTP Support for GNU Emacs
- auto-save (1.19) 01-May-1992
- Sebastian Kremer, <sk@thp.uni-koeln.de>
- ~/misc/auto-save.el.Z
- Safer autosaving with support for ange-ftp and /tmp
- ftp-quik (1.0) 28-Jul-1993
- Terrence Brannon, <tb06@pl122f.eecs.lehigh.edu>
- ~/modes/ftp-quik.el.Z
- Quik access to dired'ing of ange-ftp and normal paths
-
-78: 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 77). Next, check local archives and the
- Emacs Lisp Archive to find a copy of the relevant files. 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/
- /ftp.cs.umn.edu:pub/elisp-archive/
- /calypso-2.oit.unc.edu:pub/gnu/elisp-archive/
- /ftp.uu.net:packages/gnu/emacs-lisp/
- /gatekeeper.dec.com:pub/GNU/elisp-archive/
- /nic.switch.ch:mirror/elisp-archive/
- /ftp.diku.dk:pub/elisp-archive/
- /quepasa.cs.tu-berlin.de:pub/gnu/elisp/
- /faui43.informatik.uni-erlangen.de:pub/gnu/elisp-archive/
- /ftp.uni-mainz.de:pub/gnu/elisp-archive/
- /nic.funet.fi:pub/gnu/emacs/elisp-archive/
- /src.doc.ic.ac.uk:gnu/EmacsBits/elisp-archive/
-
- Retrieve and read 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.
-
- * Any files with names ending in `.Z', `.z', or `.gz' are
- compressed, so 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'.
-
-79: How do I submit code to the Emacs Lisp Archive?
-
- Guidelines and procedures for submission to the archive can be found in
- the file GUIDELINES in the archive directory (see question 78). It
- covers documentation, copyrights, packaging, submission, and the Lisp
- Code Directory Record. Anonymous FTP uploads are not permitted.
- Instead, all submissions are 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.
-
-80: 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. Read the files etc/DISTRIB and etc/FTP for more information
- (see question 20 for retrieval instructions).
-
- The following sites are all mirror images of the GNU distribution area:
-
- /col.hp.com:mirrors/gnu/
- /ftp.uu.net:packages/gnu/
- /ftp.win.tue.nl:pub/gnu/
- /gatekeeper.dec.com:pub/GNU/
- /nic.funet.fi:pub/gnu/
- /src.doc.ic.ac.uk:gnu/ (available via FTP, NIFTP, FTAM)
- /utsun.s.u-tokyo.ac.jp:ftpsync/prep/
- /wuarchive.wustl.edu:systems/gnu/
-
- The directory at ftp.uu.net is a mirror of prep.ai.mit.edu:pub/gnu,
- except that files larger than one megabyte are 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.
-
-81: What is the difference between Emacs and Epoch?
-
- Epoch was a modified version of GNU Emacs. It was merged
- into XEmacs (formerly "Lucid Emacs"), and the Epoch redisplay, now
- being totally rewritten, is slated to be merged into Emacs when the
- rewrite is done.
-
-82: What is the difference between Emacs and XEmacs (formerly "Lucid
- Emacs")?
-
- XEmacs is a modified version of GNU Emacs.
-
- A comparison between the two versions, written by the XEmacs
- maintainers, had been included here. Richard Stallman removed it
- from this copy of the FAQ because it was unfair. It was (1)
- one-sided, listing only advantages of XEmacs and not advantages of
- the principal version of Emacs, (2) biased, stating the opinions
- of the XEmacs maintainers, and (3) out of date, listing as advantages of
- XEmacs features which in fact both versions have.
-
-83: Where can I get Emacs for my PC running MS-DOS?
-
- Recent releases of GNU Emacs 19 should compile right out of the box on
- PCs with a 386 or better, running MS-DOS 3.0 or later. You will need the
- following to compile it:
-
- Compiler: djgpp version 1.12 maint 1 or later. Djgpp v2.0 or later is
- recommended, since v1.x is being phased out--if you'll have any
- djgpp-related problem for which there is no known solution, you
- are on your own when you use djgpp v1.x.
-
- You can get the latest release of either v1.x or v2.0 by
- grabbing everything in the following directory (using anonymous
- ftp):
-
- ftp.simtel.net:/pub/simtelnet/gnu/djgpp
-
- There are a few directories under djgpp whose names begin with
- `v1' or `v2'; get the contents of `v2' and `v2gnu' (for djgpp
- v2) or `v1' and `v1gnu' (for djgpp v1).
-
- GUnZip and Tar:
-
- The easiest way is to use `djtar' which comes with DJGPP v2.x,
- because it can unzip .tar.gz archives on-the-fly (so you won't
- need twice the required disk space while untarring the
- archive). You get `djtar' with the `v2/djdev201.zip' file from
- the above FTP server.
-
- Another (slower) version of Tar which unzips automatically is
- available by anonymous ftp on this site:
-
- ftp.kiae.su:msdos/arcers/tar320fp.zip
-
- Or you can unZip the archive with the DJGPP port of GZip (from
- the above directory at ftp.simtel.net look for v2/gzp124b.zip),
- then unTar it with any of the Tar ports floating around. A
- DOS version of GNU tar is available via anonymous ftp from
-
- ftp.unipg.it:/pub/msdos/aspi/gtar-exe.zip
-
- Note that DOS ports of GNU Tar usually cannot unzip compressed
- archives.
-
- Another version of Tar for DOS can be found at
-
- ftp.urc.tue.nl:pub/unixtools/dos
-
- However, be warned that not all DOS versions of tar work
- equally well, so you might have to try others if this one gives
- you trouble.
-
- Utilities: chmod, make, mv, sed, rm.
-
- All of these utilities are available via anonymous ftp from
- the site
-
- ftp.simtel.net:/pub/simtelnet/gnu/djgpp/v2gnu
-
- You should grab the file fil313b.zip (contains chmod.exe,
- mv.exe, and rm.exe).
-
- A port of GNU Sed is available in the djgpp archives in the
- above directory on ftp.coast.net. Look for a file named
- v2/sed118b.zip or v1/sed118bn.zip.
-
- The file etc/MSDOS contains some information on the differences between
- the Unix and MS-DOS versions of GNU Emacs.
-
- MS-DOS systems are notorious in the problems they present when installing
- programs, due to a great variability in both hardware and software. If
- you have any unusual problems compiling or using Emacs, please consult
- the latest version of the djgpp FAQ list, available as v2/faqNNNb.zip,
- where `NNN' is the version number. For v1, get the file v1/faq102.zip.
-
- If you would prefer not to compile Emacs by yourself, you can get
- binaries for Emacs via anonymous ftp from many sites; use your Archie
- client to search for them.
-
- You might also be interested in Demacs, which runs under MS-DOS (*not*
- Microsoft Windows; see question 84) on 386- and 486-based PCs. Demacs is
- a port of Nemacs (see question 126), rather than a straight port of GNU
- Emacs 18 or 19.
-
- Demacs was developed using an MS-DOS version of gcc called djgpp by
- DJ Delorie <dj@delorie.com> which can compile and run large programs
- under MS-DOS and under MS Windows. Demacs was derived from Nemacs
- rather than straight from GNU Emacs. You can get the most recent version
- of Demacs via anonymous ftp from ftp.sigmath.osaka-u.ac.jp in
- pub/Msdos/Demacs/*.
-
- For a list of other MS-DOS implementations of Emacs (and Emacs
- look-alikes), consult the list of "Emacs implementations and literature,"
- available via anonymous ftp from rtfm.mit.edu in pub/usenet/comp.emacs.
-
-84: Where can I get Emacs for my PC running Microsoft Windows?
-
- * If you compile GNU Emacs with the tools listed above, it will run under
- Microsoft Windows in a DOS box.
-
- There are currently two other ports of Emacs that runs under Microsoft
- Windows:
-
- * Oemacs
-
- Current version of Oemacs4.1 is based on Emacs-19.19 and runs in either
- MS-DOS or Microsoft Windows. There is rumor that the author Darryl
- Okahata <darrylo@sr.hp.com> would not update unless there is
- demonstrated interest. It is nearly a full porting of GNU Emacs except
- that shell-mode does not work due to the limitation of MS-DOS.
- Anonymous ftp information:
-
- ftp.coast.net:SimTel/vendors/gnu/oemacs/
-
- * The other uses a proprietary X Windows emulator and therefore
- the FSF does not think it deserves publicity.
-
-85: Where can I get Emacs for my PC running OS/2?
-
- Emacs 19.27 is ported for emx on OS/2 2.0 or 2.1.
-
- Anonymous FTP info:
-
- hobbes.nmsu.edu:os2/2_x/unix/emacs27
-
-86: Where can I get Emacs for my Atari ST?
-
- (does anyone know?)
-
-87: Where can I get Emacs for my Amiga?
-
- Amiga software is available through Aminet, a set of interconnected FTP
- sites and other file accessing services for Amiga software. The primary
- sites for Aminet are ftp.wustl.edu (128.252.135.4) and ftp.cdrom.com
- (192.153.46.2). In the directory pub/aminet/util/gnu, there are
-
- a1.26-emacs-bin.lha -- Amiga GNU Emacs V1.26, binaries
- a1.26-emacs-src.lha -- Amiga GNU Emacs V1.26, sources
-
- There are also quite a few Emacs related files/programs. Please search
- the index of Aminet.
-
- We have no access to an Amiga, so please send in your experience and
- comments on the implementation.
-
-88: 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.
-
-89: Where do I get Emacs that runs on VMS under DECwindows?
-
- Version 19.27 has a VMS directory containing installation instructions, a
- makefile, and various .com files. But according to Richard Levitte
- <levitte@e.kth.se>, it does not run out of the box. Even if it does, the
- VMSNOTES indicates that the Emacs on VMS is going to have much more
- limited functionality. Richard Levitte has a patched 19.22 that
- supposedly has subprocess and networking functionality just as on Unix,
- with virtually the same lisp interface. The source is available via
- anonymous ftp at
-
- ftp.vms.stacken.kth.se:GNU-VMS/Beta/EMACS-19_22-********.TAR-GZ
-
- where ******** is the release date of the kit. You should also read
- http://www.e.kth.se/elev/levitte/gnu/emacs.html for more information.
-
-90: Where can I get modes for Lex, Yacc/Bison, Bourne shell, Csh, C++,
- Objective C, Pascal, and Awk?
-
- Most of these modes are now available in standard Emacs distribution. To
- get additional modes, look in the Lisp Code Directory (see question 77).
- For C++, if you use lisp-dir-apropos, you must specify the pattern like
- this:
-
- M-x lisp-dir-apropos RET c\+\+ RET
-
- Note that Barry Warsaw's cc-mode now works for C, C++, and Objective-C
- code. You can get the latest version (4.85, as of this writing) from the
- Emacs Lisp Archive.
-
-91: What is the IP address of XXX.YYY.ZZZ?
-
- 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:
-
- * By telnet:
-
- telnet nic.ddn.mil hostnames (or `telnet 192.112.36.5 101')
- @ whois
- Whois: host XXX.YYY.ZZZ
-
- * 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 let us know. Having its own mailing
- list or newsgroup or more than half a megabyte of source code are good
- signs.
-
-92: VM (View Mail) -- another mail reader within Emacs
-
- Author: Kyle Jones <kyle@uunet.uu.net>
- Latest version: 5.72 (beta)
- Anonymous FTP:
- /ftp.uu.net:networking/mail/vm-5.72beta.tar.gz
- Newsgroups and mailing lists:
- Info-VM:
- gnu.emacs.vm.info (newsgroup)
- info-vm-request@uunet.uu.net (for subscriptions)
- info-vm@uunet.uu.net (for submissions)
- Bug-VM:
- gnu.emacs.vm.bug (newsgroup)
- bug-vm-request@uunet.uu.net (for subscriptions)
- bug-vm@uunet.uu.net (for submissions)
-
-93: Supercite -- mail and news citation package within Emacs
-
- Author: Barry Warsaw <bwarsaw@cen.com>
- Latest version: 3.54 (comes with GNU Emacs 19)
- 3.1 (available from the Emacs Lisp Archive)
- Anonymous FTP:
- /archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/packages/sc3.1.tar.Z
- Mailing list: supercite-request@anthem.nlm.nih.gov (for subscriptions)
- supercite@anthem.nlm.nih.gov (for submissions)
- NOTE: Superyank is an old version of Supercite.
-
-94: Gnus -- news reader within Emacs
-
- Author: Masanobu Umeda <umerin@mse.kyutech.ac.jp>
- Latest version: 4.1 (comes with GNU Emacs 19)
- Anonymous FTP:
- /src.doc.ic.ac.uk:gnu/EmacsBits/elisp-archive/packages/gnus-4.1.tar.Z
- /archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/packages/gnus-4.1.tar.Z
- Newsgroups and mailing lists:
- English-only:
- gnu.emacs.gnus (newsgroup)
- 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)
-
-95: Calc -- poor man's Mathematica within Emacs
-
- Author: Dave Gillespie <daveg@csvax.cs.caltech.edu>
- Latest version: 2.02c
- Anonymous FTP:
- /prep.ai.mit.edu:pub/gnu/calc-2.02c.tar.gz
- NOTE: Unlike Wolfram Research, Dave has never threatened to sue
- anyone for having a program with a similar command language to
- Calc. :-)
-
-96: Ange-FTP -- transparent FTP access for Emacs's file access routines
-
- Author: Andy Norman <ange@hplb.hpl.hp.com>
- Latest version: 1.56 (comes with GNU Emacs 19)
- Anonymous FTP:
- /archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/packages/ange-ftp.tar.Z
- Mailing lists:
- Ange-FTP Lovers:
- ange-ftp-lovers-request@anorman.hpl.hp.com (for subscriptions)
- 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 supports VMS, CMS, and MTS ftp servers
-
-97: VIP -- vi emulation for Emacs
-
- Author: Aamod Sane <sane@cs.uiuc.edu>
- Latest 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.
-
-98: AUC TeX -- enhanced LaTeX mode with debugging facilities
-
- Author: Kresten Krab Thorup <krab@iesd.auc.dk>
- Latest version: 9.1i
- Anonymous FTP:
- /iesd.auc.dk:pub/emacs-lisp/auctex-9.1i.tar.gz
- 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)
-
-99: Hyperbole -- extensible hypertext management system within Emacs
-
- Author: Bob Weiner <rsw@cs.brown.edu>
- Latest version: 3.15
- Anonymous FTP:
- /wilma.cs.brown.edu:pub/hyperbole/h3.15.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.
-
-100: BBDB -- personal Info Rolodex integrated with mail/news readers
-
- Author: Jamie Zawinski <jwz@lucid.com>
- Latest released version: 1.50
- Anonymous FTP:
- /archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/packages/bbdb-1.50.tar.Z
- Mailing lists:
- info-bbdb-request@cs.uiuc.edu (for subscriptions)
- info-bbdb@cs.uiuc.edu (for submissions)
- bbdb-announce-request@cs.uiuc.edu (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.
-
-101: Ispell -- spell checker in C with interface for Emacs
-
- Author: Geoff Kuenning <geoff@itcorp.com>
- Latest released version: 3.1.08
- Anonymous FTP:
- Master Sites:
- /ftp.cs.ucla.edu:pub/ispell/ispell-3.1.08.tar.gz
- /ftp.math.orst.edu:pub/ispell/ispell-3.1.08.tar.gz
- Known Mirror Sites: (only directory names shown)
- /ftp.th-darmstadt.de:pub/dicts/ispell/
- /ftp.nl.net:pub/textproc/ispell/
-
- NOTE: * Do not ask Geoff to send you the latest version of Ispell.
- He does not have free e-mail.
-
- * This Ispell program is distinct from GNU Ispell 4.0. GNU
- Ispell 4.0 is no longer a supported product.
-
-102: XEmacs -- alternative Emacs 19 with better X interface; formerly
- known as Lucid Emacs or lemacs.
-
- Primary Maintainer: Chuck Thompson <cthomp@cs.uiuc.edu>
- Other Developers: Ben Wing <wing@netcom.com>
- Richard Mlynarik <mly@adoc.xerox.com>
- Jamie Zawinski <jwz@mcom.com>
- Latest released version: 19.11
- Anonymous FTP:
- /ftp.cs.uiuc.edu:pub/xemacs/xemacs-19.11.tar.gz
- Newsgroup and mailing lists:
- Bugs:
- alt.lucid-emacs.bug
- bug-lucid-emacs-request@cs.uiuc.edu (for subscriptions)
- bug-lucid-emacs@cs.uiuc.edu (for submissions)
- Help:
- alt.lucid-emacs.help
- help-lucid-emacs-request@cs.uiuc.edu (for subscriptions)
- help-lucid-emacs@cs.uiuc.edu (for submissions)
- NOTE: The XEmacs FAQ is available via the World-Wide Web at URL
- http://xemacs.cs.uiuc.edu/.
-
-103: Patch -- program to apply "diffs" for updating files
-
- Author: Larry Wall <lwall@netlabs.com>
- Latest version: 2.1
- Anonymous FTP:
- /prep.ai.mit.edu:pub/gnu/patch-2.1.tar.gz
- /ftp.funet.fi:pub/gnu/patch-2.1.tar.gz
- /ftp.uni-stuttgart.de:pub/unix/gnu/patch-2.1.tar.gz
- NOTE: See question 80 for other GNU distribution sites.
-
-
-Changing Key Bindings and Handling Key Binding Problems
-
-104: How do I bind keys (including function keys) to commands?
-
- Keys can be bound to commands either interactively or by predefinition
- (e.g. in the .emacs file). To interactively bind keys for all modes,
- type `M-x global-set-key RET KEY CMD RET'; for the current major mode
- only, type `M-x local-set-key RET KEY CMD RET' (see the Emacs on-line
- documentation for further details).
-
- To bind keys on starting Emacs or on starting any given mode, you can use
- the following "trick." First bind the key interactively, then
- immediately afterwards type `C-x ESC ESC C-a C-k C-g'. Now, the command
- needed to bind the key is in the kill ring and can be yanked into the
- .emacs file. If the key binding is global, no changes to the command are
- required. For example,
-
- (global-set-key (quote [f1]) (quote help-for-help))
-
- can be place directly into the .emacs file. If the key binding is local,
- the command is used in conjunction with the `add-hook' command. For
- example, in tex-mode, a local binding might be
-
- (add-hook 'tex-mode-hook
- (function (lambda ()
- (local-set-key (quote [f1]) (quote help-for-help))))
-
- NOTE: * Control characters in key sequence position of the form yanked
- from the kill ring are given in their graphic form - i.e. CTRL is
- shown as `^', TAB as a set of spaces (usually 8), etc. You may
- want to convert these into their vector or string forms.
-
- * If some prefix key of the character sequence to be bound is
- already bound as a complete key, then you must unbind it before
- the new binding. For example, if `ESC {' is previously bound:
-
- (global-unset-key [?\e ?{]) ;; or
- (local-unset-key [?\e ?{])
-
- * Aside from commands and "lambda lists," a vector or string also
- can be bound to a key and thus treated as a macro. For example:
-
- (global-set-key [f10] [?\C-x?\e?\e?\C-a?\C-k?\C-g]) ;; or
- (global-set-key [f10] "\C-x\e\e\C-a\C-k\C-g")
-
- See `Key Bindings' in the Emacs on-line documentation for further
- details.
-
-105: Why does Emacs say `Key sequence XXX uses invalid prefix characters'?
-
- Usually one of two things has happened. In one case, the control
- character in the key sequence has been misspecified (e.g. `C-f' used
- instead of `\C-f' within a Lisp expression). In the other case, a
- "prefix key" in the keystroke sequence you were trying to bind was
- already bound as a "complete key." Historically, the `ESC [' prefix was
- usually the problem, in which case you should evaluate either of these
- forms before attempting to bind the key sequence:
-
- (global-unset-key [?\e ?[]) ;; or
- (global-unset-key "\e[")
-
-106: Why doesn't this [terminal or window-system setup] code work in my
- .emacs file, but it works just fine after Emacs starts up?
-
- During startup, Emacs initializes itself according to a given code/file
- order. If some of the code executed in your .emacs file needs to be
- postponed until the initial terminal or window-system setup code has been
- executed but is not, then you will experience this problem (this
- code/file execution order is not enforced after startup).
-
- To postpone the execution of Emacs Lisp code until after terminal or
- window-system setup, treat the code as a "lambda list" and set the value
- of either the `term-setup-hook' or `window-setup-hook' variable to this
- "lambda function." For example,
-
- (setq term-setup-hook
- (function
- (lambda ()
- (cond ((string-match "\\`vt220" (or (getenv "TERM") ""))
- ;; Make vt220's "Do" key behave like M-x:
- (global-set-key [do] 'execute-extended-command))
- ))))
-
- For information on what Emacs does every time it is started, see the
- lisp/startup.el file.
-
-107: How do I use function keys under X Windows?
-
- With Emacs 19, functions keys under X are bound like any other key. See
- question 104 for details.
-
-108: How do I tell what characters or symbols my function or arrow keys
- emit?
-
- Put the following in your .emacs file and type `M-x see-chars' to use:
-
- (defun see-chars ()
- "Display events received, terminated by a 3-second timeout."
- (interactive)
- (let (chars
- (inhibit-quit t))
- (message "Enter characters or other events, terminated by a 3-second
- timeout.")
- (while (not (sit-for 3))
- (setq chars (nconc chars (list (read-event)))
- quit-flag nil) ; quit-flag might be set by C-g.
- (if (not (input-pending-p))
- (message "Events received until now: %s..."
- (key-description chars))))
- (message "Events received: %s" (key-description chars))))
-
- Alternatively, type "C-h c" then the function or arrow keys. The command
- will return either a function key symbol or character sequence (see the
- Emacs on-line documentation for an explanation). This works for other
- keys as well.
-
-109: How do I set the X key "translations" for Emacs?
-
- 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). The `define-key' command should be used in conjunction
- with the `function-key-map' map. For instance,
-
- (define-key function-key-map [M-tab] [?\M-\t])
-
- defines the `META TAB' key sequence.
-
-110: How do I handle C-s and C-q being used for flow control?
-
- 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.
-
- Possible solutions:
-
- * Disable the use of C-s and C-q for flow control.
-
- You need to determine the cause of the flow control.
-
- * your terminal
-
- 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.
-
- 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.
-
- 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.
-
- * a modem
-
- If you are using a dialup connection, the modems may be using
- XON/XOFF flow control. It's not clear how to get around this.
-
- * a router or terminal server
-
- 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.
-
- * tty and/or pty devices
-
- 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.
-
- Eirik Fuller <eirik@theory.tn.cornell.edu> writes:
-
- 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.
-
- 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.
-
- Use `stty -ixon' instead of `stty start u stop u' on some systems.
-
- * Make Emacs speak the XON/XOFF flow control protocol.
-
- You can make Emacs treat C-s and C-q as flow control characters by
- evaluating the form
-
- (enable-flow-control)
-
- to unconditionally enable flow control or
-
- (enable-flow-control-on "vt100" "h19")
-
- (using your terminal names instead of "vt100" or "h19") to enable
- selectively. These commands will automatically swap `C-s' and `C-q' to
- `C-\' and `C-^'. Variables can be used to change the default swap keys
- (`flow-control-c-s-replacement' and `flow-control-c-q-replacement').
-
- 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 in the lisp/site-start.el file. 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).
-
- For further discussion of this issue, read the file PROBLEMS (in the
- top-level directory when you unpack the Emacs source).
-
-111: How do I bind `C-s' and `C-q' (or any key) if these keys are filtered
- out?
-
- To bind `C-s' and `C-q', use either `enable-flow-control' or
- `enable-flow-control-on'. See question 110 for usage and implementation
- details.
-
- To bind other keys, use `keyboard-translate'. See question 114 for usage
- details. To do this for an entire site, you should swap the keys in
- lisp/site-start.el. See question 110 for an explanation of why
- lisp/default.el should not be used.
-
- NOTE: * 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.
-
-112: Why does the `Backspace' key invoke help?
-
- The `Backspace' key (on most keyboards) 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.
-
- For many people this solution may be problematic:
-
- * 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 '^?'
-
- * 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.
-
- * Some terminals (e.g., VT3## terminals) allow the character generated by
- the Backspace key to be changed from a setup menu.
-
- * You may be able to get a keyboard that is completely programmable.
-
- * Under X or on a dumb terminal, it is possible to swap the Backspace and
- Delete keys inside Emacs:
-
- (keyboard-translate ?\C-h ?\C-?)
-
- See question 114 for further details of `keyboard-translate'.
-
- * Another approach is to switch key bindings and put help on "C-x h"
- instead:
-
- (global-set-key [?\C-h] 'delete-backward-char)
- (global-set-key [?\C-x ?h] 'help-command)
- ;; overrides mark-whole-buffer
-
- Other popular key bindings for help are M-? and "C-x ?".
-
- NOTE: * Don't try to bind DEL to help-command, because there are many
- modes that have local bindings of DEL that will interfere.
-
-113: Why doesn't Emacs look at the stty settings for Backspace vs. Delete?
-
- Good question!
-
-114: How do I "swap" two keys?
-
- In Emacs 19, you can swap two keys (or key sequences) by using the
- `keyboard-translate' function. For example, to turn `C-h' into DEL and
- DEL to `C-h', use
-
- (keyboard-translate ?\C-h ?\C-?) ; translate `C-h' to DEL
- (keyboard-translate ?\C-? ?\C-h) ; translate DEL to `C-h'.
-
- The first key sequence of the pair after the function identifies what is
- produced by the keyboard; the second, what is matched for in the keymaps.
-
- Keyboard translations are not the same as key bindings in keymaps. Emacs
- contains numerous keymaps that apply in different situations, but there
- is only one set of keyboard translations, and it applies to every
- character that Emacs reads from the terminal. Keyboard translations take
- place at the lowest level of input processing; the keys that are looked
- up in keymaps contain the characters that result from keyboard
- translation.
-
- Also see `Keyboard Translations' in the on-line manual.
-
-115: How do I produce C-XXX with my keyboard?
-
- On terminals (but not under X), some common "aliases" are:
-
- CTRL-2 or CTRL-SPC for C-@
- CTRL-6 for C-^
- CTRL-7 or CTRL-SHIFT-- for C-_
- CTRL-4 for C-\
- CTRL-5 for C-]
- CTRL-/ for C-?
-
- Often other aliases exist; use the `C-h c' command and try `CTRL' with
- all of the digits on your keyboard to see what gets generated. You can
- also try the `C-h w' command if you know the name of the command.
-
-116: What if I don't have a Meta key?
-
- Instead of typing "M-a", you can type "ESC a". In fact, Emacs converts
- M-a internally into "ESC a" anyway (depending on the value of
- meta-prefix-char). Note that you press "Meta" and "a" together, while
- you press "ESC", release it, and then press "a".
-
-117: What if I don't have an Escape key?
-
- Type "C-[" instead. This should send ASCII code 27 just like an Escape
- key would. "C-3" may also work on some terminal (but not under X). For
- many terminals (notably DEC terminals) "F11" generates the "ESC" key. If
- not, the following form can be used bind it:
-
- (define-key function-key-map [f11] [?\e]) ; F11 is the documented ESC
- ; replacement on DEC terminals.
-
-118: Can I make my `Compose Character' key behave like a Meta key?
-
- 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.
-
-119: How do I bind a combination of modifier key and function key?
-
- With Emacs 19 you can indicate modified function keys in vector format
- through multi-prefixing the function key symbol. For example (from the
- Emacs on-line documentation):
-
- (global-set-key [?\C-x right] 'forward-page)
-
- where "?\C-x" is the Lisp character constant for the character "C-x".
-
- You can use the modifier keys CTRL, META, HYPER, SUPER, ALT and SHIFT
- with function keys. To represent these modifiers, prepend the strings
- "C-", "M-", "H-", "s-", "A-" and "S-" to the symbol name. Thus, here is
- how to make "Hyper-Meta-RIGHT" move forward a word:
-
- (global-set-key [H-M-right] 'forward-word)
-
- NOTE: * Not all modifiers are permitted in all situations. HYPER, SUPER,
- and ALT are available only under X (provided there are such
- keys). Non-ASCII keys and mouse events (e.g. "C-=" and
- "mouse-1") also fall under this category.
-
- See question 104 for general key binding instructions.
-
-120: Why doesn't my Meta key work in an xterm window?
-
- Try all of these methods before asking for further help:
-
- * 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?}
-
- * For X11: 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.
-
- * 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.
-
- * 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.
-
- * If the Emacs is running under Ultrix, it is reported that evaluating
- (set-input-mode t nil) helps.
-
- * 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:
-
- XTerm.VT100.EightBitInput: false
-
- (This changes the behavior of the insert-eight-bit action.)
-
- With older xterms, you can specify this behavior with a translation:
-
- XTerm.VT100.Translations: #override \
- Meta<KeyPress>: string(0x1b) insert()
-
- You might have to replace `Meta' with `Alt'.
-
-121: Why doesn't my ExtendChar key work as a Meta key under HP-UX 8.0?
-
- 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:
-
- xmodmap -e 'remove mod1 = Mode_switch'
-
- NOTE: This will disable the use of the extra keysyms systemwide, which
- may be undesirable if you actually intend to use them.
-
-122: Where can I get key bindings to make Emacs emulate WordStar?
-
- There is a package `wordstar' by Jim Frost <jimf@saber.com> located under
- the "misc" directory at the Emacs Lisp Archive.
-
-123: Where can I get an XEDIT emulator for Emacs?
-
- This question comes up once every couple of months. Searing for "xedit"
- through most recent Lisp Code Directory fails to match any entries.
-
-Using Emacs with Alternate Character Sets
-
-124: How do I make Emacs display 8-bit characters?
-
- GNU Emacs 19 has built-in support for 8-bit characters. Here is an
- excerpt from the `European Display' page of the on-line manual:
-
- Some European languages use accented letters and other special symbols.
- The ISO 8859 Latin-1 character set defines character codes for many
- European languages in the range 160 to 255.
-
- Emacs can display those characters according to Latin-1, provided the
- terminal or font in use supports them. The `M-x
- standard-display-european' command toggles European character display
- mode. With a numeric argument, `M-x standard-display-european' enables
- European character display if and only if the argument is positive.
-
- Some operating systems let you specify the language you are using by
- setting a locale. Emacs handles one common special case of this: if
- your locale name for character types contains the string `8859-1' or
- `88591', Emacs automatically enables European character display mode
- when it starts up.
-
-125: How do I input 8-bit characters?
-
- Again, from the `European Display' page of the on-line manual:
-
- If you enter non-ASCII ISO Latin-1 characters often, you might find ISO
- Accents mode convenient. When this minor mode is enabled, the
- characters ``', `'', `"', `^', `/' and `~' modify the following letter
- by adding the corresponding diacritical mark to it, if possible. To
- enable or disable ISO Accents mode, use the command `M-x
- iso-accents-mode'. This command affects only the current buffer.
-
- To enter one of those six special characters, type the character,
- followed by a space. Some of those characters have a corresponding
- "dead key" accent character in the ISO Latin-1 character set; to enter
- that character, type the corresponding ASCII character twice. For
- example, `''' enters the Latin-1 character acute-accent (character code
- 0264).
-
-126: 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
- /ftp.cs.titech.ac.jp:pub/gnu-rel/nemacs/nemacs-3.3.2.tar.gz
-
- 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
- Windows client.
-
-127: 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:
-
- /cs.purdue.edu:pub/ygz/cemacs.tar.Z
-
- Cxterm, a patch to Emacs 18.57 that allows you to enter Chinese
- characters, is available from the same place:
-
- /cs.purdue.edu:pub/ygz/cxterm-11.5.1.tar.Z
-
-128: 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.
-
- Anonymous FTP:
- /israel.nysernet.org:israel/computers/software/msdos/ibelbe.zip
- /israel.nysernet.org:israel/computers/software/msdos/hebfont.zip
-
- 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.
-
- 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."
-
- A good suggestion is to query archie for files named with `hebrew'.
-
-
-Mail and News
-
-129: How do I change the included text prefix in mail/news followups?
-
- If you read mail with Rmail or news with Gnus, set the variable
- mail-yank-prefix. For VM, set vm-included-text-prefix. For mh-e, set
- mh-ins-buf-prefix.
-
- For fancier control of citations, use Supercite. See question 93.
-
- 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.
-
-130: How do I save a copy of outgoing mail?
-
- You can either mail yourself a copy by including a `BCC:' header in the
- mail message, or store a copy of the message directly to a file by
- including an `FCC:' header.
-
- If you use standard mail, you can automatically create a `BCC:' to
- yourself by putting
-
- (setq mail-self-blind t)
-
- in your .emacs. You can automatically include an `FCC:' field by putting
- something like the following in your .emacs file:
-
- (setq mail-archive-file-name (expand-file-name "~/outgoing"))
-
- The output file will be in Unix mail format, which can be read directly
- by VM, but not always by Rmail. See question 132.
-
- If you use mh-e add an FCC: or BCC: field to your components file.
-
- It does not work to put `set record filename' in the .mailrc file.
-
-131: Why doesn't Emacs expand my aliases when sending mail?
-
- * 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:
-
- To: Willy Smith <wks@xpnsv.lwyrs.com>
-
- However, you do not need to separate addresses with commas in your
- .mailrc file.
-
- 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.
-
- * 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!)
-
- * 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.
-
- * If you like, you can expand mail aliases as abbrevs, as soon as you
- type them in. To enable this feature, execute the following:
-
- (add-hook 'mail-setup-hook 'mail-abbrevs-setup)
-
-132: Why does Rmail think all my saved messages are one big message?
-
- A file created through the FCC: field in a message is in Unix Mail
- format, not the format that Rmail uses (BABYL format). Rmail will try to
- convert a Unix mail file into BABYL format on input, but sometimes it
- makes errors. For guaranteed safety, you can make the saved- messages
- file be an inbox for your Rmail file by using the function
- set-rmail-inbox-list.
-
-133: How can I sort the messages in my Rmail folder?
-
- In Rmail, type C-c C-s C-h to get a list of sorting functions and their
- key bindings.
-
-134: Why does Rmail need to write to /usr/spool/mail?
-
- This is the behavior of the `movemail' program which Rmail uses. This
- indicates that movemail is configured to use lock files.
-
- RMS 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.
-
- Other systems use the flock system call to interlock access. On these
- systems, you should configure movemail to use flock.
-
-135: How do I recover my mail files after Rmail munges their format?
-
- If you have just done rmail-input on a file and you don't want to save it
- in Rmail's format (called BABYL), just kill the buffer (with C-x k).
-
- If you typed M-x rmail and it read some messages out of your inbox and
- you want to put them in a Unix mail file, use C-o on each message.
-
- If you want to convert an existing file from BABYL format to Unix mail
- format, use the command M-x unrmail: it will prompt you for the input and
- output file names.
-
-136: How do I make Emacs automatically start my mail/news reader?
-
- To start Emacs in Gnus:
-
- emacs -f gnus
-
- in Rmail:
-
- emacs -f rmail
-
- A more convenient way to start with Gnus:
-
- alias gnus 'emacs -f gnus'
- gnus
-
- 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.
-
-137: How do I read news under Emacs?
-
- Use M-x gnus. It is documented in Info (see question 14).
-
-138: Why doesn't Gnus work via NNTP?
-
- 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.
-
- You can work around the bug inside Emacs like this:
-
- (setq nntp-maximum-request 1)
-
- 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
- (i.e., `telnet server-machine 119'). The server should give its version
- number in the welcome message. Type `quit' to get out.
-
-139: How do I view text with embedded underlining (e.g., ClariNews)?
-
- Underlining appears like this:
-
- _^Hu_^Hn_^Hd_^He_^Hr_^Hl_^Hi_^Hn_^Hi_^Hn_^Hg
-
- You can destructively remove underlining with M-x ununderline-region.
-
- For ClariNews articles, clari-clean.el by David N. Blank-Edelman
- <dnb@meshugge.media.mit.edu> will remove both underlining and
- overstriking automatically. It is available on the Lisp Code Directory
- (see question 77).
-
-140: How do I save all the items of a multi-part posting in Gnus?
-
- Use gnus-uu. Type C-c C-v C-h in the Gnus summary buffer to see a list
- of available commands.
-
-141: Why does Gnus put the subjects in replies beyond the 80th column?
-
- 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 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.
-
-142: How do I make Gnus start up faster?
-
- Remove all the newsgroups in which you have no interest from your .newsrc
- file by using Gnus's C-k or C-w commands in the `*Newsgroup*' buffer,
- perhaps after displaying all newsgroups with the L command.
- Unsubscribing will not speed up Gnus.
-
-143: How do I catch up all newsgroups in Gnus?
-
- In the `*Newsgroup*' buffer, type the following magical incantation:
-
- M-< C-x ( c y M-0 C-x )
-
- Leave off the "M-<" if you only want to catch up from point to the end of
- the `*Newsgroup' buffer.
-
-144: Why can't I kill in Gnus on the Newsgroups/Keywords/Control line?
-
- Gnus will complain that the `Newsgroups:', `Keywords:', and `Control:'
- headers are `Unknown header field's.
-
- For the `Newsgroups:' header, there is an easy workaround: kill on the
- `Xref' header instead, which will be present on any cross-posted article
- (as long as your site carries the cross-post group).
-
- If you really want to kill on one of these headers, you can do it like
- this:
-
- (gnus-kill nil "^Newsgroups: .*\\(bad\\.group\\|worse\\.group\\)")
-
-145: How do I get rid of flashing messages in Gnus for slow connections?
-
- Set nntp-debug-read to nil.
-
-146: Why is catch up slow in Gnus?
-
- Because Gnus is marking crosspostings read. You can control this with
- the variable gnus-use-cross-reference.
-
-147: Why does Gnus hang for a long time when posting?
-
- 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.
-
-148: Why don't my news postings in Gnus get past the local machine?
-
- It could be that your Distribution: field is "local" or a synonym, or
- your Path: field may be wrong. This piece of code may fix the latter
- problem:
-
- (setq gnus-use-generic-path t)
-
-149: Why doesn't Gnus generate the `Lines:' header?
-
- The posting software down the line from Gnus often generates a "Lines:"
- header so Gnus doesn't have to. If you want it to, just add Lines to the
- list in gnus-required-headers:
-
- (add-hook 'gnus-startup-hook
- '(lambda ()
- (setq gnus-required-headers (cons 'Lines gnus-required-headers))))
-
-150: How do I kill all articles in Gnus but those matching a pattern?
-
- Example kill file code:
-
- ;; 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-summary-clear-mark-forward 1))))
- t)
-
-
-------------------------------------------------------------
-Slightly modified by Richard Stallman
-Copyright 1994 Reuven M. Lerner
-Copyright 1992, 1993 Steven Byrnes
-Copyright 1990, 1991, 1992 Joseph Brian Wells
-
-This list of frequently asked questions about GNU Emacs with answers
-("FAQ") may be translated into other languages, transformed into other
-formats (e.g. Texinfo, Info, WWW, WAIS), and updated with new information.
-
-The same conditions apply to any derivative of the FAQ as apply to the FAQ
-itself. Every copy of the FAQ must include this notice or an approved
-translation, information on who is currently maintaining the FAQ and how to
-contact them (including their e-mail address), and information on where the
-latest version of the FAQ is archived (including FTP information).
-
-The FAQ may be copied and redistributed under these conditions, except that
-the FAQ may not be embedded in a larger literary work unless that work
-itself allows free copying and redistribution.
-
-------------------------------------------------------------
-
-Special thanks to members of the FAQ team, who worked hard to ensure that
-answers were up-to-date:
-
-Ethan Bradford <ethanb@u.washington.edu>, Luis Fernandes
-<elf@eccles.ee.ryerson.ca>, Denby Wong <3dw16@qlink.QueensU.CA>, Yair
-Friedman <yair@cs.huji.ac.il>, Thi <ttn@netcom.com>, Richard Levitte
-<levitte@e.kth.se>, "William G. Dubuque" <wgd@martigny.ai.mit.edu>,
-and Guan-Hsong Hsu <ghsu@relay.nswc.navy.mil>.
-
-
-
-
diff --git a/etc/Makefile b/etc/Makefile
deleted file mode 100644
index 65581ba2d3e..00000000000
--- a/etc/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-DESTDIR=
-LIBDIR=/usr/local/lib
-BINDIR=/usr/local/bin
-MANDIR=/usr/man/man1
-MANEXT=1
-
-all:
-
-mostlyclean:
- -rm -f core
-
-clean distclean maintainer-clean:
- -rm -f DOC* core
-
-SOURCES = [0-9A-QS-Z]* README *.[ch16] emacs.* etags.* ledit.l ms-* \
- news.texi rc2log refcard.tex spook-lines termcap.* ulimit.hack \
- vcdiff vipcard.tex xmouse.doc
-
-unlock:
- chmod u+w $(SOURCES)
-
-relock:
- chmod u-w $(SOURCES)
-
-# ${etcdir}/e/eterm is used by ../lisp/term.el.
-# TERMINFO systems use terminfo files compiled by the Terminfo Compiler (tic).
-# These files are binary, and depend on the version of tic, but they seem
-# to be system-independent and backwardly compatible.
-# So there should be no need to recompile the distributed binary version.
-TIC=tic
-e/eterm: e/eterm.ti
- TERMINFO=`pwd`; export TERMINFO; $(TIC) e/eterm.ti
-
diff --git a/etc/README b/etc/README
deleted file mode 100644
index 5d8f0db5bdb..00000000000
--- a/etc/README
+++ /dev/null
@@ -1,7 +0,0 @@
-This directory contains the architecture-independent files used by or
-with Emacs. This includes some text files of documentation for GNU
-Emacs or of interest to Emacs users, and the file of dumped docstrings
-for Emacs functions and variables.
-
-`termcap.src' is included mainly for VMS. It is a copy of the
-`/etc/termcap' file used on Unix.
diff --git a/etc/TUTORIAL b/etc/TUTORIAL
deleted file mode 100644
index 8b39e544d91..00000000000
--- a/etc/TUTORIAL
+++ /dev/null
@@ -1,1014 +0,0 @@
-Copyright (c) 1985 Free Software Foundation, Inc; See end for conditions.
-You are looking at the Emacs tutorial.
-
-Emacs commands generally involve the CONTROL key (sometimes labeled
-CTRL or CTL) or the META key (sometimes labeled EDIT or ALT). Rather than
-write that in full each time, we'll use the following abbreviations:
-
- C-<chr> means hold the CONTROL key while typing the character <chr>
- Thus, C-f would be: hold the CONTROL key and type f.
- M-<chr> means hold the META or EDIT or ALT key down while typing <chr>.
- If there is no META, EDIT or ALT key, instead press and release the
- ESC key and then type <chr>. We write <ESC> for the ESC key.
-
-Important note: to end the Emacs session, type C-x C-c. (Two characters.)
-The characters ">>" at the left margin indicate directions for you to
-try using a command. For instance:
-<<Blank lines inserted here by startup of help-with-tutorial>>
->> Now type C-v (View next screen) to move to the next screen.
- (go ahead, do it by holding down the control key while typing v).
- From now on, you should do this again whenever you finish
- reading the screen.
-
-Note that there is an overlap of two lines when you move from screen
-to screen; this provides some continuity so you can continue reading
-the text.
-
-The first thing that you need to know is how to move around from place
-to place in the text. You already know how to move forward one screen,
-with C-v. To move backwards one screen, type M-v (hold down the META key
-and type v, or type <ESC>v if you do not have a META or EDIT key).
-
->> Try typing M-v and then C-v, a few times.
-
-
-* SUMMARY
----------
-
-The following commands are useful for viewing screenfuls:
-
- C-v Move forward one screenful
- M-v Move backward one screenful
- C-l Clear screen and redisplay all the text,
- moving the text around the cursor
- to the center of the screen.
- (That's control-L, not control-1.)
-
->> Find the cursor, and note what text is near it.
- Then type C-l.
- Find the cursor again and notice that the same text
- is near the cursor now.
-
-
-* BASIC CURSOR CONTROL
-----------------------
-
-Moving from screenful to screenful is useful, but how do you
-move to a specific place within the text on the screen?
-
-There are several ways you can do this. The most basic way is to use
-the commands C-p, C-b, C-f, and C-n. Each of these commands moves the
-cursor one row or column in a particular direction on the screen.
-Here is a table showing these four commands and shows the directions
-they move:
-
- Previous line, C-p
- :
- :
- Backward, C-b .... Current cursor position .... Forward, C-f
- :
- :
- Next line, C-n
-
->> Move the cursor to the line in the middle of that diagram
- using C-n or C-p. Then type C-l to see the whole diagram
- centered in the screen.
-
-You'll probably find it easy to think of these by letter: P for
-previous, N for next, B for backward and F for forward. These are the
-basic cursor positioning commands, and you'll be using them ALL the
-time, so it would be of great benefit if you learn them now.
-
->> Do a few C-n's to bring the cursor down to this line.
-
->> Move into the line with C-f's and then up with C-p's.
- See what C-p does when the cursor is in the middle of the line.
-
-Each of text line ends with a Newline character, which serves to
-separate it from the following line. The last line in your file ought
-to have a Newline at the end (but Emacs does not require have one).
-
->> Try to C-b at the beginning of a line. It should move to
- the end of the previous line. This is because it moves back
- across the Newline character.
-
-C-f can move across a Newline just like C-b.
-
->> Do a few more C-b's, so you get a feel for where the cursor is.
- Then do C-f's to return to the end of the line.
- Then do one more C-f to move to the following line.
-
-When you move past the top or bottom of the screen, the text beyond
-the edge shifts onto the screen. This is called "scrolling". It
-enables Emacs to move the cursor to the specified place in the text
-without moving it off the screen.
-
->> Try to move the cursor off the bottom of the screen with C-n, and
- see what happens.
-
-If moving by characters is too slow, you can move by words. M-f
-(Meta-f) moves forward a word and M-b moves back a word.
-
->> Type a few M-f's and M-b's.
-
-When you are in the middle of a word, M-f moves to the end of the word.
-When you are in whitespace between words, M-f moves to the end of the
-following word. M-b works likewise in the opposite direction.
-
->> Type M-f and M-b a few times, interspersed with C-f's and C-b's
- so that you can observe the action of M-f and M-b from various
- places inside and between words.
-
-Notice the parallel between C-f and C-b on the one hand, and M-f and
-M-b on the other hand. Very often Meta characters are used for
-operations related to the units defined by language (words, sentences,
-paragraphs), while Control characters operate on basic units that are
-independent of what you are editing (characters, lines, etc).
-
-This parallel applies between lines and sentences: C-a and C-e move to
-the beginning or end of a line, and M-a and M-e move to the beginning
-or end of a sentence.
-
->> Try a couple of C-a's, and then a couple of C-e's.
- Try a couple of M-a's, and then a couple of M-e's.
-
-See how repeated C-a's do nothing, but repeated M-a's keep moving one
-more sentence. Although these are not quite analogous, each one seems
-natural.
-
-The location of the cursor in the text is also called "point". To
-paraphrase, the cursor shows on the screen where point is located in
-the text.
-
-Here is a summary of simple cursor-moving operations, including the
-word and sentence moving commands:
-
- C-f Move forward a character
- C-b Move backward a character
-
- M-f Move forward a word
- M-b Move backward a word
-
- C-n Move to next line
- C-p Move to previous line
-
- C-a Move to beginning of line
- C-e Move to end of line
-
- M-a Move back to beginning of sentence
- M-e Move forward to end of sentence
-
->> Try all of these commands now a few times for practice.
- These are the most often used commands.
-
-Two other important cursor motion commands are M-< (Meta Less-than),
-which moves to the beginning of the whole text, and M-> (Meta
-Greater-than), which moves to the end of the whole text.
-
-On most terminals, the "<" is above the comma, so you must use the
-shift key to type it. On these terminals you must use the shift key
-to type M-< also; without the shift key, you would be typing M-comma.
-
->> Try M-< now, to move to the beginning of the tutorial.
- Then use C-v repeatedly to move back here.
-
->> Try M-> now, to move to the end of the tutorial.
- Then use M-v repeatedly to move back here.
-
-You can also move the cursor with the arrow keys, if your terminal has
-arrow keys. We recommend learning C-b, C-f, C-n and C-p for three
-reasons. First, they work on all kinds of terminals. Second, once
-you gain practice at using Emacs, you will find that typing these CTRL
-characters is faster than typing the arrow keys (because you do not
-have to move your hands away from touch-typing position). Third, once
-you form the habit of using these CTRL character commands, you can
-easily learn to use other advanced cursor motion commands as well.
-
-Most Emacs commands accept a numeric argument; for most commands, this
-serves as a repeat-count. The way you give a command a repeat count
-is by typing C-u and then the digits before you type the command. If
-you have a META or EDIT key, there is another alternative way to enter
-a numeric argument: type the digits while holding down the META or
-EDIT key. We recommend learning the C-u method because it works on
-any terminal.
-
-For instance, C-u 8 C-f moves forward eight characters.
-
->> Try using C-n or C-p with a numeric argument, to move the cursor
- to a line near this one with just one command.
-
-Most commands use the numeric argument as a repeat count. Certain
-exceptional commands use it differently. C-v and M-v are among the
-exceptions. When given an argument, they scroll the screen up or down
-by that many lines, rather than by a screenfuls. For example, C-u 4
-C-v scrolls the screen by 4 lines.
-
->> Try typing C-u 8 C-v now.
-
-This should have scrolled the screen up by 8 lines. If you would like
-to scroll it down again, you can give an argument to M-v.
-
-If you are using X Windows, there should be a tall rectangular area
-called a scroll bar at the left hand side of the Emacs window. You
-can scroll the text by clicking the mouse in the scroll bar.
-
->> Try pressing the middle button at the top of the highlighted area
- within the scroll bar. This should scroll the text to a position
- determined by how high or low you click.
-
->> Try moving the mouse up and down, while holding the middle button
- pressed down. You'll see that the text scrolls up and down as
- you move the mouse.
-
-
-* WHEN EMACS IS HUNG
---------------------
-
-If Emacs stops responding to your commands, you can stop it safely by
-typing C-g. You can use C-g to stop a command which is taking too
-long to execute.
-
-You can also use C-g to discard a numeric argument or the beginning of
-a command that you do not want to finish.
-
->> Type C-u 100 to make a numeric arg of 100, then type C-g.
- Now type C-f. It should move just one character,
- because you canceled the argument with C-g.
-
-If you have typed an <ESC> by mistake, you can get rid of it
-with a C-g.
-
-
-* DISABLED COMMANDS
--------------------
-
-Some Emacs commands are "disabled" so that beginning users cannot use
-them by accident.
-
-If you type one of the disabled commands, Emacs displays a message
-saying what the command was, and asking you whether you want to go
-ahead and execute the command.
-
-If you really want to try the command, type Space in answer to the
-question. Normally, if you do not want to execute the disabled
-command, answer the question with "n".
-
->> Type <ESC> : (which is a disabled command),
- then type n to answer the question.
-
-
-* WINDOWS
----------
-
-Emacs can have several windows, each displaying its own text. We will
-explain later on how to use multiple windows. Right now we want to
-explain how to get rid of extra windows and go back to basic
-one-window editing. It is simple:
-
- C-x 1 One window (i.e., kill all other windows).
-
-That is Control-x followed by the digit 1. C-x 1 expands the window
-which contains the cursor, to occupy the full screen. It deletes all
-other windows.
-
->> Move the cursor to this line and type C-u 0 C-l.
->> Type Control-h k Control-f.
- See how this window shrinks, while a new one appears
- to display documentation on the Control-f command.
-
->> Type C-x 1 and see the documentation listing window disappear.
-
-
-* INSERTING AND DELETING
-------------------------
-
-If you want to insert text, just type the text. Characters which you
-can see, such as A, 7, *, etc. are taken by Emacs as text and inserted
-immediately. Type <Return> (the carriage-return key) to insert a
-Newline character.
-
-You can delete the last character you typed by typing <Delete>.
-<Delete> is a key on the keyboard, which may be labeled "Del". In
-some cases, the "Backspace" key serves as <Delete>, but not always!
-
-More generally, <Delete> deletes the character immediately before the
-current cursor position.
-
->> Do this now--type a few characters, then delete them
- by typing <Delete> a few times. Don't worry about this file
- being changed; you will not alter the master tutorial. This is
- your personal copy of it.
-
-When a line of text gets too big for one line on the screen, the line
-of text is "continued" onto a second screen line. A backslash ("\")
-at the right margin indicates a line which has been continued.
-
->> Insert text until you reach the right margin, and keep on inserting.
- You'll see a continuation line appear.
-
->> Use <Delete>s to delete the text until the line fits on one screen
- line again. The continuation line goes away.
-
-You can delete a Newline character just like any other character.
-Deleting the Newline character between two lines merges them into
-one line. If the resulting combined line is too long to fit in the
-screen width, it will be displayed with a continuation line.
-
->> Move the cursor to the beginning of a line and type <Delete>. This
- merges that line with the previous line.
-
->> Type <Return> to reinsert the Newline you deleted.
-
-Remember that most Emacs commands can be given a repeat count;
-this includes text characters. Repeating a text character inserts
-it several times.
-
->> Try that now -- type C-u 8 * to insert ********.
-
-You've now learned the most basic way of typing something in
-Emacs and correcting errors. You can delete by words or lines
-as well. Here is a summary of the delete operations:
-
- <Delete> delete the character just before the cursor
- C-d delete the next character after the cursor
-
- M-<Delete> kill the word immediately before the cursor
- M-d kill the next word after the cursor
-
- C-k kill from the cursor position to end of line
- M-k kill to the end of the current sentence
-
-Notice that <Delete> and C-d vs M-<Delete> and M-d extend the parallel
-started by C-f and M-f (well, <Delete> is not really a control
-character, but let's not worry about that). C-k and M-k are like C-e
-and M-e, sort of, in that lines are opposite sentences.
-
-When you delete more than one character at a time, Emacs saves the
-deleted text so that you can bring it back. Bringing back killed text
-is called "yanking". You can yank the killed text either at the same
-place where it was killed, or at some other place in the text. You
-can yank the text several times in order to make multiple copies of
-it. The command to yank is C-y.
-
-Note that the difference between "Killing" and "Deleting" something is
-that "Killed" things can be yanked back, and "Deleted" things cannot.
-Generally, the commands that can remove a lot of text save the text,
-while the commands that delete just one character, or just blank lines
-and spaces, do not save the deleted text.
-
->> Move the cursor to the beginning of a line which is not empty.
- Then type C-k to kill the text on that line.
->> Type C-k a second time. You'll see that it kills the Newline
- which follows that line.
-
-Note that a single C-k kills the contents of the line, and a second
-C-k kills the line itself, and make all the other lines move up. C-k
-treats a numeric argument specially: it kills that many lines AND
-their contents. This is not mere repetition. C-u 2 C-k kills two
-lines and their newlines; typing C-k twice would not do that.
-
-To retrieve the last killed text and put it where the cursor currently
-is, type C-y.
-
->> Try it; type C-y to yank the text back.
-
-Think of C-y as if you were yanking something back that someone took
-away from you. Notice that if you do several C-k's in a row, all of
-the killed text is saved together, so that one C-y will yank all of
-the lines.
-
->> Do this now, type C-k several times.
-
-Now to retrieve that killed text:
-
->> Type C-y. Then move the cursor down a few lines and type C-y
- again. You now see how to copy some text.
-
-What do you do if you have some text you want to yank back, and then
-you kill something else? C-y would yank the more recent kill. But
-the previous text is not lost. You can get back to it using the M-y
-command. After you have done C-y to get the most recent kill, typing
-M-Y replaces that yanked text with the previous kill. Typing M-y
-again and again brings in earlier and earlier kills. When you have
-reached the text you are looking for, you do not have to do anything to
-keep it. Just go on with your editing, leaving the yanked text where
-it is.
-
-If you M-y enough times, you come back to the starting point (the most
-recent kill).
-
->> Kill a line, move around, kill another line.
- Then do C-y to get back the second killed line.
- Then do M-y and it will be replaced by the first killed line.
- Do more M-y's and see what you get. Keep doing them until
- the second kill line comes back, and then a few more.
- If you like, you can try giving M-y positive and negative
- arguments.
-
-
-* UNDO
-------
-
-If you make a change to the text, and then decide that it was a
-mistake, you can undo the change with the undo command, C-x u.
-
-Normally, C-x u undoes the changes made by one command; if you repeat
-the C-x u several times in a row, each repetition undoes one
-additional command.
-
-But there are two exceptions: commands that do not change the text do
-not count (this includes cursor motion commands and scrolling
-command), and self-inserting characters are usually handled in groups
-of up to 20. (This is to reduce the number of C-x u's you have to
-type to undo insertion of text.)
-
->> Kill this line with C-k, then type C-x u and it should reappear.
-
-C-_ is an alternative undo command; it works just the same as C-x u,
-but it is easier to type several times in a row. The disadvantage of
-C-_ is that on some keyboards it is not obvious how to type it. That
-is why we provide C-x u as well. On some terminals, you can type C-_
-by typing / while holding down CTRL.
-
-A numeric argument to C-_ or C-x u acts as a repeat count.
-
-
-* FILES
--------
-
-In order to make the text you edit permanent, you must put it in a
-file. Otherwise, it will go away when your invocation of Emacs goes
-away. You put your editing in a file by "finding" the file. (This is
-also called "visiting" the file.)
-
-Finding a file means that you see the contents of the file within
-Emacs. In many ways, it is as if you were editing the file itself.
-However, the changes you make using Emacs do not become permanent
-until you "save" the file. This is so you can avoid leaving a
-half-changed file on the system when you do not want to. Even when
-you save, Emacs leaves the original file under a changed name in case
-you later decide that your changes were a mistake.
-
-If you look near the bottom of the screen you will see a line that
-begins and ends with dashes, and contains the string "Emacs:
-TUTORIAL". This part of the screen always shows the name of the file
-that you are visiting. Right now, you are visiting a file called
-"TUTORIAL" which is your personal scratch copy of the Emacs tutorial.
-Whatever file you find, that file's name will appear in that precise
-spot.
-
-The commands for finding and saving files are unlike the other
-commands you have learned in that they consist of two characters.
-They both start with the character Control-x. There is a whole series
-of commands that start with Control-x; many of them have to do with
-files, buffers, and related things. These commands are two, three or
-four characters long.
-
-Another thing about the command for finding a file is that you have
-to say what file name you want. We say the command "reads an argument
-from the terminal" (in this case, the argument is the name of the
-file). After you type the command
-
- C-x C-f Find a file
-
-Emacs asks you to type the file name. The file name you type appears
-on the bottom line of the screen. The bottom line is called the
-minibuffer when it is used for this sort of input. You can use
-ordinary Emacs editing commands to edit the file name.
-
-While you are entering the file name (or any minibuffer input),
-you can cancel the command with C-g.
-
->> Type C-x C-f, then type C-g. This cancels the minibuffer,
- and also cancels the C-x C-f command that was using the
- minibuffer. So you do not find any file.
-
-When you have finished entering the file name, type <Return> to
-terminate it. Then C-x C-f command goes to work, and finds the file
-you chose. The minibuffer disappears when the C-x C-f command is
-finished.
-
-In a little while the file contents appear on the screen, and you can
-edit the contents. When you wish to make your changes permanent,
-type the command
-
- C-x C-s Save the file
-
-This copies the text within Emacs into the file. The first time you
-do this, Emacs renames the original file to a new name so that it is
-not lost. The new name is made by adding "~" to the end of the
-original file's name.
-
-When saving is finished, Emacs prints the name of the file written.
-You should save fairly often, so that you will not lose very much
-work if the system should crash.
-
->> Type C-x C-s, saving your copy of the tutorial.
- This should print "Wrote ...TUTORIAL" at the bottom of the screen.
-
-NOTE: On some systems, typing C-x C-s will freeze the screen and you
-will see no further output from Emacs. This indicates that an
-operating system "feature" called "flow control" is intercepting the
-C-s and not letting it get through to Emacs. To unfreeze the screen,
-type C-q. Then see the section "Spontaneous Entry to Incremental
-Search" in the Emacs manual for advice on dealing with this "feature".
-
-You can find an existing file, to view it or edit it. You can also
-find a file which does not already exist. This is the way to create a
-file with Emacs: find the file, which will start out empty, and then
-begin inserting the text for the file. When you ask to "save" the
-file, Emacs will really create the file with the text that you have
-inserted. From then on, you can consider yourself to be editing an
-already existing file.
-
-
-* BUFFERS
----------
-
-If you find a second file with C-x C-f, the first file remains
-inside Emacs. You can switch back to it by finding it again with
-C-x C-f. This way you can get quite a number of files inside Emacs.
-
->> Create a file named "foo" by typing C-x C-f foo <Return>.
- Then insert some text, edit it, and save "foo" by typing C-x C-s.
- Finally, type C-x C-f TUTORIAL <Return>
- to come back to the tutorial.
-
-Emacs stores each file's text inside an object called a "buffer."
-Finding a file makes a new buffer inside Emacs. To see a list of the
-buffers that current exist in your Emacs job, type
-
- C-x C-b List buffers
-
->> Try C-x C-b now.
-
-See how each buffer has a name, and it may also have a file name
-for the file whose contents it holds. Some buffers do not correspond
-to files. For example, the buffer named "*Buffer List*" does
-not have any file. It is the buffer which contains the buffer
-list that was made by C-x C-b. ANY text you see in an Emacs window
-is always part of some buffer.
-
->> Type C-x 1 to get rid of the buffer list.
-
-If you make changes to the text of one file, then find another file,
-this does not save the first file. Its changes remain inside Emacs,
-in that file's buffer. The creation or editing of the second file's
-buffer has no effect on the first file's buffer. This is very useful,
-but it also means that you need a convenient way to save the first
-file's buffer. It would be a nuisance to have to switch back to
-it with C-x C-f in order to save it with C-x C-s. So we have
-
- C-x s Save some buffers
-
-C-x s asks you about each buffer which contains changes that you have
-not saved. It asks you, for each such buffer, whether to save the
-buffer.
-
->> Insert a line of text, then type C-x s.
- It should ask you whether to save the buffer named TUTORIAL.
- Answer yes to the question by typing "y".
-
-* EXTENDING THE COMMAND SET
----------------------------
-
-There are many, many more Emacs commands than could possibly be put
-on all the control and meta characters. Emacs gets around this with
-the X (eXtend) command. This comes in two flavors:
-
- C-x Character eXtend. Followed by one character.
- M-x Named command eXtend. Followed by a long name.
-
-These are commands that are generally useful but used less than the
-commands you have already learned about. You have already seen two of
-them: the file commands C-x C-f to Find and C-x C-s to Save. Another
-example is the command to end the Emacs session--this is the command
-C-x C-c. (Do not worry about losing changes you have made; C-x C-c
-offers to save each changed file before it kills the Emacs.)
-
-C-z is the command to exit Emacs *temporarily*--so that you can go
-back to the same Emacs session afterward.
-
-On systems which allow it, C-z "suspends" Emacs; that is, it returns
-to the shell but does not destroy the Emacs. In the most common
-shells, you can resume Emacs with the `fg' command or with `%emacs'.
-
-On systems which do not implement suspending, C-z creates a subshell
-running under Emacs to give you the chance to run other programs and
-return to Emacs afterward; it does not truly "exit" from Emacs. In
-this case, the shell command `exit' is the usual way to get back to
-Emacs from the subshell.
-
-The time to use C-x C-c is when you are about to log out. It's also
-the right thing to use to exit an Emacs invoked under mail handling
-programs and other miscellaneous utilities, since they may not know
-how to cope with suspension of Emacs. In ordinary circumstances,
-though, if you are not about to log out, it is better to suspend Emacs
-with C-z instead of exiting Emacs.
-
-There are many C-x commands. Here is a list of the ones you have learned:
-
- C-x C-f Find file.
- C-x C-s Save file.
- C-x C-b List buffers.
- C-x C-c Quit Emacs.
- C-x u Undo.
-
-Named eXtended commands are commands which are used even less
-frequently, or commands which are used only in certain modes. An
-example is the command replace-string, which globally replaces one
-string with another. When you type M-x, Emacs prompts you at the
-bottom of the screen with M-x and you should type the name of the
-command; in this case, "replace-string". Just type "repl s<TAB>" and
-Emacs will complete the name. End the command name with <Return>.
-
-The replace-string command requires two arguments--the string to be
-replaced, and the string to replace it with. You must end each
-argument with <Return>.
-
->> Move the cursor to the blank line two lines below this one.
- 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,
- after the initial position of the cursor.
-
-
-* AUTO SAVE
------------
-
-When you have made changes in a file, but you have not saved them yet,
-they could be lost if your computer crashes. To protect you from
-this, Emacs periodically writes an "auto save" file for each file that
-you are editing. The auto save file name has a # at the beginning and
-the end; for example, if your file is named "hello.c", its auto save
-file's name is "#hello.c#". When you save the file in the normal way,
-Emacs deletes its auto save file.
-
-If the computer crashes, you can recover your auto-saved editing by
-finding the file normally (the file you were editing, not the auto
-save file) and then typing M-x recover file<return>. When it asks for
-confirmation, type yes<return> to go ahead and recover the auto-save
-data.
-
-
-* ECHO AREA
------------
-
-If Emacs sees that you are typing commands slowly it shows them to you
-at the bottom of the screen in an area called the "echo area." The echo
-area contains the bottom line of the screen.
-
-
-* MODE LINE
------------
-
-The line immediately above the echo area it is called the "mode line".
-The mode line says something like this:
-
---**-Emacs: TUTORIAL (Fundamental)--L670--58%----------------
-
-This line gives useful information about the status of Emacs and
-the text you are editing.
-
-You already know what the filename means--it is the file you have
-found. -NN%-- indicates your current position in the text; it means
-that NN percent of the text is above the top of the screen. If the
-top of the file is on the screen, it will say --Top-- instead of
---00%--. If the bottom of the text is on the screen, it will say
---Bot--. If you are looking at text so small that all of it fits on
-the screen, the mode line says --All--.
-
-The stars near the front mean that you have made changes to the text.
-Right after you visit or save a file, that part of the mode line shows
-no stars, just dashes.
-
-The part of the mode line inside the parentheses is to tell you what
-editing modes you are in. The default mode is Fundamental which is
-what you are using now. It is an example of a "major mode".
-
-Emacs has many different major modes. Some of them are meant for
-editing different languages and or kinds of text, such as Lisp mode,
-Text mode, etc. At any time one and only one major mode is active,
-and its name can always be found in the mode line just where
-"Fundamental" is now.
-
-Each major mode makes a few commands behave differently. For example,
-there are commands for creating comments in a program, and since each
-programming language has a different idea of what a comment should
-look like, each major mode has to insert comments differently. Each
-major mode is the name of an extended command, which is how you can
-switchto that mode. For example, M-x fundamental-mode is a command to
-switch to Fundamental mode.
-
-If you are going to be editing English text, such as this file, you
-should probably use Text Mode.
->> Type M-x text-mode<Return>.
-
-Don't worry, none of the commands you have learned changes Emacs in
-any great way. But you can observe that M-f and M-b now treat
-apostrophes as part of words. Previously, in Fundamental mode,
-M-f and M-b treated apostrophes as word-separators.
-
-Major modes usually make subtle changes like that one: most commands
-do "the same job" in each major mode, but they work a little bit
-differently.
-
-To view documentation on your current major mode, type C-h m.
-
->> Use C-u C-v once or more to bring this line near the top of screen.
->> Type C-h m, to see how Text mode differs from Fundamental mode.
->> Type C-x 1 to remove the documentation from the screen.
-
-Major modes are called major because there are also minor modes.
-Minor modes are not to the major modes, just minor modifications of
-them. Each minor mode can be turned on or off by itself, independent
-of all other minor modes, and independent of your major mode. So you
-can use no minor modes, or one minor mode, or any combination of
-several minor modes.
-
-One minor mode which is very useful, especially for editing English
-text, is Auto Fill mode. When this mode is on, Emacs breaks the line
-in between words automatically whenever you insert text and make a
-line that is too wide.
-
-You can turn Auto Fill mode on by doing M-x auto-fill-mode<Return>.
-When the mode is on, you can turn it off by doing M-x
-auto-fill-mode<Return>. If the mode is off, this command turns it on,
-and if the mode is on, this command turns it off. We say that the
-command "toggles the mode".
-
->> Type M-x auto-fill-mode<Return> now. Then insert a line of "asdf "
- over again until you see it divide into two lines. You must put in
- spaces between them because Auto Fill breaks lines only at spaces.
-
-The margin is usually set at 70 characters, but you can change it
-with the C-x f command. You should give the margin setting you want
-as a numeric argument.
-
->> Type C-x f with an argument of 20. (C-u 2 0 C-x f).
- Then type in some text and see Emacs fill lines of 20
- characters with it. Then set the margin back to 70 using
- C-x f again.
-
-If you makes changes in the middle of a paragraph, Auto Fill mode
-does not re-fill it for you.
-To re-fill the paragraph, type M-q (Meta-q) with the cursor inside
-that paragraph.
-
->> Move the cursor into the previous paragraph and type M-q.
-
-* SEARCHING
------------
-
-Emacs can do searches for strings (these are groups of contiguous
-characters or words) either forward through the text or backward
-through it. Searching for a string is a cursor motion command;
-it moves the cursor to the next place where that string appears.
-
-The Emacs search command is different from the search commands
-of most editors, in that it is "incremental". This means that the
-search happens while you type in the string to search for.
-
-The command to initiate a search is C-s for forward search, and C-r
-for reverse search. BUT WAIT! Don't try them now.
-
-When you type C-s you'll notice that the string "I-search" appears as
-a prompt in the echo area. This tells you that Emacs is in what is
-called an incremental search waiting for you to type the thing that
-you want to search for. <RET> terminates a search.
-
->> Now type C-s to start a search. SLOWLY, one letter at a time,
- type the word 'cursor', pausing after you type each
- character to notice what happens to the cursor.
- Now you have searched for "cursor", once.
->> Type C-s again, to search for the next occurrence of "cursor".
->> Now type <Delete> four times and see how the cursor moves.
->> Type <RET> to terminate the search.
-
-Did you see what happened? Emacs, in an incremental search, tries to
-go to the occurrence of the string that you've typed out so far. To
-go to the next occurrence of 'cursor' just type C-s again. If no such
-occurrence exists Emacs beeps and tells you the search is currently
-"failing", C-g would also terminate the search.
-
-NOTE: On some systems, typing C-s will freeze the screen and you will
-see no further output from Emacs. This indicates that an operating
-system "feature" called "flow control" is intercepting the C-s and not
-letting it get through to Emacs. To unfreeze the screen, type C-q.
-Then see the section "Spontaneous Entry to Incremental Search" in the
-Emacs manual for advice on dealing with this "feature".
-
-If you are in the middle of an incremental search and type <Delete>,
-you'll notice that the last character in the search string is erased
-and the search backs up to the last place of the search. For
-instance, suppose you have typed "c", to search for the first
-occurrence of "c". Now if you type "u", the cursor will move
-to the first occurrence of "cu". Now type <Delete>. This erases
-the "u" from the search string, and the cursor moves back to
-the first occurrence of "c".
-
-If you are in the middle of a search and type a control or meta
-character (with a few exceptions--characters that are special in
-a search, such as C-s and C-r), the search is terminated.
-
-The C-s starts a search that looks for any occurrence of the search
-string AFTER the current cursor position. If you want to search for
-something earlier in the text, type C-r instead. Everything that we
-have said about C-s also applies to C-r, except that the direction of
-the search is reversed.
-
-
-* MULTIPLE WINDOWS
-------------------
-
-One of the nice features of Emacs is that you can display more than one
-window on the screen at the same time.
-
->> Move the cursor to this line and type C-u 0 C-l.
-
->> Now type C-x 2 which splits the screen into two windows.
- Both windows display this tutorial. The cursor stays in the top window.
-
->> Type C-M-v to scroll the bottom window.
- (If you do not have a real Meta key, type ESC C-v.)
-
->> Type C-x o ("o" for "other") to move the cursor to the bottom window.
->> Use C-v and M-v in the bottom window to scroll it.
- Keep reading these directions in the top window.
-
->> Type C-x o again to move the cursor back to the top window.
- The cursor in the top window is just where it was before.
-
-You can keep using C-x o to switch between the windows. Each
-window has its own cursor position, but only one window actually
-shows the cursor. All the ordinary editing commands apply to the
-window that the cursor is in. We call this the "selected window".
-
-The command C-M-v is very useful when you are editing text in one
-window and using the other window just for reference. You can keep
-the cursor always in the window where you are editing, and advance
-through the other window sequentially with C-M-v.
-
-C-M-v is an example of a CONTROL-META character. If you have a real
-META key, you can type C-M-v by holding down both CTRL and META while
-typing v. It does not matter whether CTRL or META "comes first,"
-because both of these keys act by modifying the characters you type.
-
-If you do not have a real META key, and you use ESC instead, the order
-does matter: you must type ESC followed by CTRL-v; CTRL-ESC v will not
-work. This is because ESC is a character in its own right, not a
-modifier key.
-
->> Type C-x 1 (in the top window) to get rid of the bottom window.
-
-(If you had typed C-x 1 in the bottom window, that would get rid
-of the top one. Think of this command as "Keep just one
-window--the window I am already in.")
-
-You do not have to display the same buffer in both windows. If you
-use C-x C-f to find a file in one window, the other window does not
-change. You can find a file in each window independently.
-
-Here is another way to use two windows to display two different
-things:
-
->> Type C-x 4 C-f followed by the name of one of your files.
- End with <Return>. See the specified file appear in the bottom
- window. The cursor goes there, too.
-
->> Type C-x o to go back to the top window, and C-x 1 to delete
- the bottom window.
-
-
-* RECURSIVE EDITING LEVELS
---------------------------
-
-Sometimes you will get into what is called a "recursive editing
-level". This is indicated by square brackets in the mode line,
-surrounding the parentheses around the major mode name. For
-example, you might see [(Fundamental)] instead of (Fundamental).
-
-To get out of the recursive editing level, type ESC ESC ESC. That is
-an all-purpose "get out" command. You can also use it for eliminating
-extra windows, and getting out of the minibuffer.
-
->> Type M-x to get into a minibuffer; then type ESC ESC ESC to get out.
-
-You cannot use C-g to get out of a recursive editing level. This is
-because C-g is used for canceling commands and arguments WITHIN the
-recursive editing level.
-
-
-* GETTING MORE HELP
--------------------
-
-In this tutorial we have tried to supply just enough information to
-get you started using Emacs. There is so much available in Emacs that
-it would be impossible to explain it all here. However, you may want
-to learn more about Emacs since it has many other useful features.
-Emacs provides commands for reading documentation about Emacs
-commands. These "help" commands all start with the character
-Control-h, which is called "the Help character".
-
-To use the Help features, type the C-h character, and then a
-character saying what kind of help you want. If you are REALLY lost,
-type C-h ? and Emacs will tell you what kinds of help it can give.
-If you have typed C-h and decide you do not want any help, just
-type C-g to cancel it.
-
-(Some sites rebind the character C-h. They really should not do this
-as a blanket measure, so complain to the system administrator.
-Meanwhile, if C-h does not display a message about help at the bottom
-of the screen, try typing M-x help RET instead.)
-
-The most basic HELP feature is C-h c. Type C-h, a c, and a
-command character or sequence, and Emacs displays a very brief
-description of the command.
-
->> Type C-h c Control-p.
- The message should be something like
-
- C-p runs the command previous-line
-
-This tells you the "name of the function". Function names are used
-mainly for customizing and extending Emacs. But since function names
-are chosen to indicate what the command does, they can serve also as
-very brief documentation--sufficient to remind you of commands you
-have already learned.
-
-Multi-character commands such as C-x C-s and (if you have no META or
-EDIT key) <ESC>v are also allowed after C-h c.
-
-To get more information about a command, use C-h k instead of C-h c.
-
->> Type C-h k Control-p.
-
-This displays the documentation of the function, as well as its
-name, in an Emacs window. When you are finished reading the
-output, type C-x 1 to get rid of the help text. You do not have
-to do this right away. You can do some editing while referring
-to the help text, and then type C-x 1.
-
-Here are some other useful C-h options:
-
- C-h f Describe a function. You type in the name of the
- function.
-
->> Try typing C-h f previous-line<Return>.
- This prints all the information Emacs has about the
- function which implements the C-p command.
-
- C-h a Command Apropos. Type in a keyword and Emacs will list
- all the commands whose names contain that keyword.
- These commands can all be invoked with Meta-x.
- For some commands, Command Apropos will also list a one
- or two character sequence runs the same command.
-
->> Type C-h a file<Return>.
-
-This displays in another window a list of all M-x commands with "file"
-in their names. You will see character-commands like C-x C-f listed
-beside the corresponding command names such as find-file.
-
->> Type C-M-v to scroll the help window. Do this a few times.
-
->> Type C-x 1 to delete the help window.
-
-
-* CONCLUSION
-------------
-
-Remember, to exit Emacs permanently use C-x C-c. To exit to a shell
-temporarily, so that you can come back to Emacs afterward, use C-z.
-
-This tutorial is meant to be understandable to all new users, so if
-you found something unclear, don't sit and blame yourself - complain!
-
-
-COPYING
--------
-
-This tutorial descends from a long line of Emacs tutorials
-starting with the one written by Stuart Cracraft for the original Emacs.
-
-This version of the tutorial, like GNU Emacs, is copyrighted, and
-comes with permission to distribute copies on certain conditions:
-
-Copyright (c) 1985, 1996 Free Software Foundation
-
- 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 altered them.
-
-The conditions for copying Emacs itself are more complex, but in the
-same spirit. Please read the file COPYING and then do give copies of
-GNU Emacs to your friends. Help stamp out software obstructionism
-("ownership") by using, writing, and sharing free software!
diff --git a/etc/enriched.doc b/etc/enriched.doc
deleted file mode 100644
index f13962fe379..00000000000
--- a/etc/enriched.doc
+++ /dev/null
@@ -1,263 +0,0 @@
-Content-Type: text/enriched
-Text-Width: 70
-
-<center><x-bg-color><param>blue</param><x-color><param>white</param><bold><fixed>enriched.el:</fixed></bold></x-color></x-bg-color>
-
-<x-bg-color><param>blue</param><x-color><param>white</param><bold>WYSIWYG rich text editing for GNU Emacs</bold></x-color></x-bg-color>
-
-
-</center><bold><x-bg-color><param>blue</param><x-color><param>white</param>INTRODUCTION
-
-</x-color></x-bg-color>
-
-</bold><indent>Emacs now has the ability to edit <italic>enriched text</italic>, which is text
-containing faces, colors, indentation, and other properties.
-This document is a quick introduction to some of the new features,
-and is also an example file in the <italic>text/enriched </italic>format.
-
-
-</indent><x-bg-color><param>blue</param><x-color><param>white</param><bold>INSTALLATION and STARTUP
-
-</bold></x-color></x-bg-color>
-
-<indent>Most of the time, you need not do anything to get these features
-to work. If you visit a file that has been written out in
-<italic>text/enriched</italic> format, it will automatically be decoded, Emacs will
-enter `enriched-mode' while visiting it, and whenever you save it
-it will be saved in the same format it was read in.
-
-
-If you wish to create a new file, however, you will need to turn
-on enriched-mode yourself:
-
-
-<fixed><indent>M-x enriched-mode RET</indent></fixed>
-
-
-Or, if you get a <italic>text/enriched </italic>file that Emacs does not
-automatically recognize and decode, you can tell Emacs to decode
-it (which also turns on enriched-mode automatically):
-
-
- <fixed>M-x format-decode-buffer RET text/enriched RET</fixed>
-
-
-
-</indent><x-bg-color><param>blue</param><x-color><param>white</param><bold><flushleft>WHAT IS ENCODED
-
-</flushleft></bold></x-color></x-bg-color><flushleft>
-
-</flushleft><indent>Here is the current list of text-properties that are saved; they
-are discussed in more detail below.
-Most of these can be added or changed with the "Text Properties"
-menu, available under the "Edit" item in the menu-bar, or on
-C-mouse-2 (Control + the middle mouse button).
-
-<bold>Faces:</bold> default, <bold>bold</bold>, <italic>italic</italic>, <underline>underline</underline>, <fixed>fixed</fixed>, etc.
-
-<bold>Colors:</bold> <x-color><param>red</param><x-bg-color><param>DarkSlateGray</param>any</x-bg-color></x-color><x-bg-color><param>DarkSlateGray</param><x-color><param>orange</param>thing</x-color> <x-color><param>yellow</param>your</x-color><x-color><param>green</param> screen</x-color><x-color><param>blue</param> </x-color><x-color><param>light blue</param>can</x-color><x-color><param>violet</param> display...</x-color></x-bg-color>
-
-<bold>Newlines:</bold> <indent>Which ones are real ("hard") newlines, and which can be
-changed to fit lines into the ma</indent>rgins.
-
-<bold>Margins:</bold> can be indented on the left or right.
-
-<bold>Justification </bold><indent>(whether lines should be flush with the left margin,
-the right margin, fully justified, centered, or left alo</indent>ne).
-
-<bold>Excerpts: "</bold><excerpt>For quoted material."</excerpt>
-
-<bold>Read-only</bold> regions.
-
-
-</indent><x-bg-color><param>blue</param><x-color><param>white</param><bold>FACES and COLORS
-
-</bold></x-color></x-bg-color><bold>
-
-</bold><indent>You can add faces either with the menu or with <fixed>M-g.</fixed> The face is
-applied to the current region. If you are using
-`transient-mark-mode' and the region is not active, then the face
-applies to whatever you type next. Any face can have colors, but
-faces have no other attributes are put on the color submenus of
-the "Text Properties" menu.
-
-
-</indent><x-bg-color><param>blue</param><x-color><param>white</param><bold>NEWLINES and PARAGRAPHS
-
-</bold></x-color></x-bg-color><bold>
-
-</bold><indent><italic>Text/enriched</italic> format distinguishes between <underline>hard</underline> and <underline>soft</underline> newlines.
-Hard newlines are used to separate paragraphs, or items in a list,
-or anywhere that must be a line break no matter what the margins
-are. Soft newlines are the ones inserted in order to fit text
-between the margins. The fill and auto-fill functions insert soft
-newlines as necessary, but hard newlines are only inserted by
-direct request, such as using the return key or the <fixed>C-o
-(open-line)</fixed> function.
-
-
-</indent><x-bg-color><param>blue</param><x-color><param>white</param><bold>INDENTATION
-
-</bold></x-color></x-bg-color><bold>
-
-</bold><indent><indentright>The fill functions also understand margins, which can be set
-for any region of a document. In addition to the menu items,
-which increase or decrease the margins, there are two commands
-for setting the margins absolutely: <fixed>C-c l (set-left-margin)</fixed>
-and <fixed>C-c r (set-right-margin)</fixed>.
-<flushleft>
-
-</flushleft></indentright><flushleft>You <indent>can change indentation at any point in a</indent></flushleft></indent> <indent><indent><flushleft>paragraph, which
-makes it possible to do interesting things like</flushleft>
-<flushleft>hanging-indents: this paragraph was indented by selecting the
-region from the second word to the end of the paragraph, and
-indenting only that part.<indent>
-
-</indent></flushleft></indent></indent><flushleft>
-
-<x-bg-color><param>blue</param><x-color><param>white</param><bold>JUSTIFICATION<indent>
-
-</indent></bold></x-color></x-bg-color><bold><indent>
-
-</indent></bold></flushleft><indent><nofill>Several styles of justification are possible, the simplest being <italic>unfilled.
-</italic>This means that your lines will be left as you write them.
-This paragraph is unfilled.
-
-The most common (for English) style is <italic>FlushLeft. </italic>This means
-lines are aligned at the left margin but left uneven at the
-right.
-
-
- </nofill><italic><flushright>FlushRight</flushright></italic><flushright> makes each line flush with the right margin instead.
-
-
-
-</flushright><italic><flushboth>FlushBoth </flushboth></italic><flushboth>regions, which are sometimes called "fully justified"
-are aligned evenly on both edges, so that the text on the page has
-a smooth appearance as in a book or newspaper article.
-Unfortunately this does not look as nice with a fixed-width font
-as it does in a proportionally-spaced printed document; the extra
-spaces that are needed on the screen can make it hard to read. <indentright><indentright><indentright><indentright>
-
-
- </indentright></indentright></indentright></indentright></flushboth><bold><center>Center
-
- </center></bold><center>Finally, there is <italic>center </italic>justification.
- The normal center-paragraph key, M-S, can be used to turn on
- center justification in enriched-mode.
-
- M-j or the "Text Properties" menu also can be used to change
- justification.
-
-
-
-</center><flushboth>Note that justification can only change at hard newlines, because
-that is the unit over which filling gets done.
-
-
-</flushboth></indent><x-bg-color><param>blue</param><x-color><param>white</param><bold>EXCERPTS
-
-</bold></x-color></x-bg-color>
-
-<excerpt><indent>This is an example of an excerpt. You can use them for quoted
-parts of other people's email messages and the like. It is just a
-face, which is the same as the `italic' face by default.
- </indent></excerpt>
-
-<x-bg-color><param>blue</param><x-color><param>white</param><bold>THE FILE FORMAT<indent>
-
-</indent></bold></x-color></x-bg-color><indent>
-
-Enriched-mode documents are saved in an extended version of a
-format called <italic>text/enriched</italic>, which is defined as part of the MIME
-standard. This means that your documents are transportable (even
-through email) to many</indent> <indent>other systems. In the future other file
-formats may be supported as well.
-
-
-Since Emacs adds some non-standard features to the format (colors
-
-and read-only regions), not all systems will be able to recreate
-all of the features of your document, but they will get as close
-as possible.
-
-
-The MIME standard is defined in internet RFC 1521; text/enriched
-is defined in RFC 1563. Details on obtaining these documents via
-FTP or email may be obtained by sending an email message to
-<fixed>rfc-info@isi.edu</fixed> with the message body:
-
-<fixed><indent>help: ways_to_get_rfcs
-
-
-</indent></fixed>See also the newsgroup comp.mail.mime.
-
-
-</indent><x-bg-color><param>blue</param><x-color><param>white</param><bold>CUSTOMIZATION
-
-</bold></x-color></x-bg-color><bold>
-
-</bold><indent>-<indent> The <fixed>fixed </fixed>and <excerpt>excerpt </excerpt>faces should be set to your liking.</indent>
-
-- <indent>User-preference variables: <fixed>default-justification, enriched-verbose.
-</fixed></indent>- <indent>You can add annotations for your own text properties by making
-additions to <fixed>enriched-annotation-alist</fixed>. Note that the
-standard requires you to name your annotation starting<italic> "x-"
-</italic>(as in <italic>"x-read-only"</italic>). Please send me any such additions that
-you think might be of general interest so that I can include
-them in the distribution.
-
-
-</indent></indent><x-bg-color><param>blue</param><x-color><param>white</param><bold>TO-DO LIST
-
-</bold></x-color></x-bg-color><bold>
-
-</bold><indent><italic>[Feel free to work on these and send me the results!]</italic>
-
-- Be smarter about fixing malformed files.
-
-- Make the indentation work more seamlessly and robustly:
-
-<indent>+ Create<indent> an aggressive auto-fill function that will keep the
-paragraph properly filled all the time, without slowing
-down editing too much.</indent>
-
-+ Refill after yank.
-
-+ <indent>Make deleting a newline also delete the indentation
-following it.</indent>
-
-+ Never let point enter indentation??
-
-</indent>- Notice and re-fill when window changes widths (optionally).
-
-- Deal with the `category' text-property in a smart way.
-
-- Interface w/ GNUS, VM, RMAIL. Maybe Info too?
-
--<indent> Support more formats: RTF, HTML...
-
-
-</indent></indent><x-bg-color><param>blue</param><x-color><param>white</param><bold>Final Notes:
-
-</bold></x-color></x-bg-color><bold>
-
-</bold><indent>This code and documentation is under development.
- </indent>Comments and bug reports are welcome.
-
-
-<bold><x-color><param>white</param><x-bg-color><param>blue</param>Boris Goldowsky</x-bg-color></x-color><x-color><param>light blue</param> </x-color></bold><x-color><param>light blue</param><fixed><<boris@gnu.ai.mit.edu></fixed></x-color><x-color><param>blue</param>
-
-</x-color><x-bg-color><param>blue</param><x-color><param>white</param> April 1995 </x-color></x-bg-color><x-color><param>blue</param>
-
-
-
-
-
-
-
-
-
-
-
-</x-color>
diff --git a/etc/rgb.txt b/etc/rgb.txt
deleted file mode 100644
index 095ae41979c..00000000000
--- a/etc/rgb.txt
+++ /dev/null
@@ -1,788 +0,0 @@
-#
-# This file is not a part of GNU Emacs. It is from xc/programs/rgb/rgb.txt
-# of the X11R6 X Consortium distribution, and is included here to support the
-# mapping of color names to RGB values on Windows NT and Windows 95.
-#
-# The following copyright notice applies to this file, and was taken from
-# xc/RELNOTES.TXT of the same distribution.
-#
-#
-# Copyright (C) 1994 X Consortium
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
-# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Except as contained in this notice, the name of the X Consortium shall not
-# be used in advertising or otherwise to promote the sale, use or other deal-
-# ings in this Software without prior written authorization from the X Consor-
-# tium.
-#
-# X Window System is a trademark of X Consortium, Inc.
-#
-
-255 250 250 snow
-248 248 255 ghost white
-248 248 255 GhostWhite
-245 245 245 white smoke
-245 245 245 WhiteSmoke
-220 220 220 gainsboro
-255 250 240 floral white
-255 250 240 FloralWhite
-253 245 230 old lace
-253 245 230 OldLace
-250 240 230 linen
-250 235 215 antique white
-250 235 215 AntiqueWhite
-255 239 213 papaya whip
-255 239 213 PapayaWhip
-255 235 205 blanched almond
-255 235 205 BlanchedAlmond
-255 228 196 bisque
-255 218 185 peach puff
-255 218 185 PeachPuff
-255 222 173 navajo white
-255 222 173 NavajoWhite
-255 228 181 moccasin
-255 248 220 cornsilk
-255 255 240 ivory
-255 250 205 lemon chiffon
-255 250 205 LemonChiffon
-255 245 238 seashell
-240 255 240 honeydew
-245 255 250 mint cream
-245 255 250 MintCream
-240 255 255 azure
-240 248 255 alice blue
-240 248 255 AliceBlue
-230 230 250 lavender
-255 240 245 lavender blush
-255 240 245 LavenderBlush
-255 228 225 misty rose
-255 228 225 MistyRose
-255 255 255 white
- 0 0 0 black
- 47 79 79 dark slate gray
- 47 79 79 DarkSlateGray
- 47 79 79 dark slate grey
- 47 79 79 DarkSlateGrey
-105 105 105 dim gray
-105 105 105 DimGray
-105 105 105 dim grey
-105 105 105 DimGrey
-112 128 144 slate gray
-112 128 144 SlateGray
-112 128 144 slate grey
-112 128 144 SlateGrey
-119 136 153 light slate gray
-119 136 153 LightSlateGray
-119 136 153 light slate grey
-119 136 153 LightSlateGrey
-190 190 190 gray
-190 190 190 grey
-211 211 211 light grey
-211 211 211 LightGrey
-211 211 211 light gray
-211 211 211 LightGray
- 25 25 112 midnight blue
- 25 25 112 MidnightBlue
- 0 0 128 navy
- 0 0 128 navy blue
- 0 0 128 NavyBlue
-100 149 237 cornflower blue
-100 149 237 CornflowerBlue
- 72 61 139 dark slate blue
- 72 61 139 DarkSlateBlue
-106 90 205 slate blue
-106 90 205 SlateBlue
-123 104 238 medium slate blue
-123 104 238 MediumSlateBlue
-132 112 255 light slate blue
-132 112 255 LightSlateBlue
- 0 0 205 medium blue
- 0 0 205 MediumBlue
- 65 105 225 royal blue
- 65 105 225 RoyalBlue
- 0 0 255 blue
- 30 144 255 dodger blue
- 30 144 255 DodgerBlue
- 0 191 255 deep sky blue
- 0 191 255 DeepSkyBlue
-135 206 235 sky blue
-135 206 235 SkyBlue
-135 206 250 light sky blue
-135 206 250 LightSkyBlue
- 70 130 180 steel blue
- 70 130 180 SteelBlue
-176 196 222 light steel blue
-176 196 222 LightSteelBlue
-173 216 230 light blue
-173 216 230 LightBlue
-176 224 230 powder blue
-176 224 230 PowderBlue
-175 238 238 pale turquoise
-175 238 238 PaleTurquoise
- 0 206 209 dark turquoise
- 0 206 209 DarkTurquoise
- 72 209 204 medium turquoise
- 72 209 204 MediumTurquoise
- 64 224 208 turquoise
- 0 255 255 cyan
-224 255 255 light cyan
-224 255 255 LightCyan
- 95 158 160 cadet blue
- 95 158 160 CadetBlue
-102 205 170 medium aquamarine
-102 205 170 MediumAquamarine
-127 255 212 aquamarine
- 0 100 0 dark green
- 0 100 0 DarkGreen
- 85 107 47 dark olive green
- 85 107 47 DarkOliveGreen
-143 188 143 dark sea green
-143 188 143 DarkSeaGreen
- 46 139 87 sea green
- 46 139 87 SeaGreen
- 60 179 113 medium sea green
- 60 179 113 MediumSeaGreen
- 32 178 170 light sea green
- 32 178 170 LightSeaGreen
-152 251 152 pale green
-152 251 152 PaleGreen
- 0 255 127 spring green
- 0 255 127 SpringGreen
-124 252 0 lawn green
-124 252 0 LawnGreen
- 0 255 0 green
-127 255 0 chartreuse
- 0 250 154 medium spring green
- 0 250 154 MediumSpringGreen
-173 255 47 green yellow
-173 255 47 GreenYellow
- 50 205 50 lime green
- 50 205 50 LimeGreen
-154 205 50 yellow green
-154 205 50 YellowGreen
- 34 139 34 forest green
- 34 139 34 ForestGreen
-107 142 35 olive drab
-107 142 35 OliveDrab
-189 183 107 dark khaki
-189 183 107 DarkKhaki
-240 230 140 khaki
-238 232 170 pale goldenrod
-238 232 170 PaleGoldenrod
-250 250 210 light goldenrod yellow
-250 250 210 LightGoldenrodYellow
-255 255 224 light yellow
-255 255 224 LightYellow
-255 255 0 yellow
-255 215 0 gold
-238 221 130 light goldenrod
-238 221 130 LightGoldenrod
-218 165 32 goldenrod
-184 134 11 dark goldenrod
-184 134 11 DarkGoldenrod
-188 143 143 rosy brown
-188 143 143 RosyBrown
-205 92 92 indian red
-205 92 92 IndianRed
-139 69 19 saddle brown
-139 69 19 SaddleBrown
-160 82 45 sienna
-205 133 63 peru
-222 184 135 burlywood
-245 245 220 beige
-245 222 179 wheat
-244 164 96 sandy brown
-244 164 96 SandyBrown
-210 180 140 tan
-210 105 30 chocolate
-178 34 34 firebrick
-165 42 42 brown
-233 150 122 dark salmon
-233 150 122 DarkSalmon
-250 128 114 salmon
-255 160 122 light salmon
-255 160 122 LightSalmon
-255 165 0 orange
-255 140 0 dark orange
-255 140 0 DarkOrange
-255 127 80 coral
-240 128 128 light coral
-240 128 128 LightCoral
-255 99 71 tomato
-255 69 0 orange red
-255 69 0 OrangeRed
-255 0 0 red
-255 105 180 hot pink
-255 105 180 HotPink
-255 20 147 deep pink
-255 20 147 DeepPink
-255 192 203 pink
-255 182 193 light pink
-255 182 193 LightPink
-219 112 147 pale violet red
-219 112 147 PaleVioletRed
-176 48 96 maroon
-199 21 133 medium violet red
-199 21 133 MediumVioletRed
-208 32 144 violet red
-208 32 144 VioletRed
-255 0 255 magenta
-238 130 238 violet
-221 160 221 plum
-218 112 214 orchid
-186 85 211 medium orchid
-186 85 211 MediumOrchid
-153 50 204 dark orchid
-153 50 204 DarkOrchid
-148 0 211 dark violet
-148 0 211 DarkViolet
-138 43 226 blue violet
-138 43 226 BlueViolet
-160 32 240 purple
-147 112 219 medium purple
-147 112 219 MediumPurple
-216 191 216 thistle
-255 250 250 snow1
-238 233 233 snow2
-205 201 201 snow3
-139 137 137 snow4
-255 245 238 seashell1
-238 229 222 seashell2
-205 197 191 seashell3
-139 134 130 seashell4
-255 239 219 AntiqueWhite1
-238 223 204 AntiqueWhite2
-205 192 176 AntiqueWhite3
-139 131 120 AntiqueWhite4
-255 228 196 bisque1
-238 213 183 bisque2
-205 183 158 bisque3
-139 125 107 bisque4
-255 218 185 PeachPuff1
-238 203 173 PeachPuff2
-205 175 149 PeachPuff3
-139 119 101 PeachPuff4
-255 222 173 NavajoWhite1
-238 207 161 NavajoWhite2
-205 179 139 NavajoWhite3
-139 121 94 NavajoWhite4
-255 250 205 LemonChiffon1
-238 233 191 LemonChiffon2
-205 201 165 LemonChiffon3
-139 137 112 LemonChiffon4
-255 248 220 cornsilk1
-238 232 205 cornsilk2
-205 200 177 cornsilk3
-139 136 120 cornsilk4
-255 255 240 ivory1
-238 238 224 ivory2
-205 205 193 ivory3
-139 139 131 ivory4
-240 255 240 honeydew1
-224 238 224 honeydew2
-193 205 193 honeydew3
-131 139 131 honeydew4
-255 240 245 LavenderBlush1
-238 224 229 LavenderBlush2
-205 193 197 LavenderBlush3
-139 131 134 LavenderBlush4
-255 228 225 MistyRose1
-238 213 210 MistyRose2
-205 183 181 MistyRose3
-139 125 123 MistyRose4
-240 255 255 azure1
-224 238 238 azure2
-193 205 205 azure3
-131 139 139 azure4
-131 111 255 SlateBlue1
-122 103 238 SlateBlue2
-105 89 205 SlateBlue3
- 71 60 139 SlateBlue4
- 72 118 255 RoyalBlue1
- 67 110 238 RoyalBlue2
- 58 95 205 RoyalBlue3
- 39 64 139 RoyalBlue4
- 0 0 255 blue1
- 0 0 238 blue2
- 0 0 205 blue3
- 0 0 139 blue4
- 30 144 255 DodgerBlue1
- 28 134 238 DodgerBlue2
- 24 116 205 DodgerBlue3
- 16 78 139 DodgerBlue4
- 99 184 255 SteelBlue1
- 92 172 238 SteelBlue2
- 79 148 205 SteelBlue3
- 54 100 139 SteelBlue4
- 0 191 255 DeepSkyBlue1
- 0 178 238 DeepSkyBlue2
- 0 154 205 DeepSkyBlue3
- 0 104 139 DeepSkyBlue4
-135 206 255 SkyBlue1
-126 192 238 SkyBlue2
-108 166 205 SkyBlue3
- 74 112 139 SkyBlue4
-176 226 255 LightSkyBlue1
-164 211 238 LightSkyBlue2
-141 182 205 LightSkyBlue3
- 96 123 139 LightSkyBlue4
-198 226 255 SlateGray1
-185 211 238 SlateGray2
-159 182 205 SlateGray3
-108 123 139 SlateGray4
-202 225 255 LightSteelBlue1
-188 210 238 LightSteelBlue2
-162 181 205 LightSteelBlue3
-110 123 139 LightSteelBlue4
-191 239 255 LightBlue1
-178 223 238 LightBlue2
-154 192 205 LightBlue3
-104 131 139 LightBlue4
-224 255 255 LightCyan1
-209 238 238 LightCyan2
-180 205 205 LightCyan3
-122 139 139 LightCyan4
-187 255 255 PaleTurquoise1
-174 238 238 PaleTurquoise2
-150 205 205 PaleTurquoise3
-102 139 139 PaleTurquoise4
-152 245 255 CadetBlue1
-142 229 238 CadetBlue2
-122 197 205 CadetBlue3
- 83 134 139 CadetBlue4
- 0 245 255 turquoise1
- 0 229 238 turquoise2
- 0 197 205 turquoise3
- 0 134 139 turquoise4
- 0 255 255 cyan1
- 0 238 238 cyan2
- 0 205 205 cyan3
- 0 139 139 cyan4
-151 255 255 DarkSlateGray1
-141 238 238 DarkSlateGray2
-121 205 205 DarkSlateGray3
- 82 139 139 DarkSlateGray4
-127 255 212 aquamarine1
-118 238 198 aquamarine2
-102 205 170 aquamarine3
- 69 139 116 aquamarine4
-193 255 193 DarkSeaGreen1
-180 238 180 DarkSeaGreen2
-155 205 155 DarkSeaGreen3
-105 139 105 DarkSeaGreen4
- 84 255 159 SeaGreen1
- 78 238 148 SeaGreen2
- 67 205 128 SeaGreen3
- 46 139 87 SeaGreen4
-154 255 154 PaleGreen1
-144 238 144 PaleGreen2
-124 205 124 PaleGreen3
- 84 139 84 PaleGreen4
- 0 255 127 SpringGreen1
- 0 238 118 SpringGreen2
- 0 205 102 SpringGreen3
- 0 139 69 SpringGreen4
- 0 255 0 green1
- 0 238 0 green2
- 0 205 0 green3
- 0 139 0 green4
-127 255 0 chartreuse1
-118 238 0 chartreuse2
-102 205 0 chartreuse3
- 69 139 0 chartreuse4
-192 255 62 OliveDrab1
-179 238 58 OliveDrab2
-154 205 50 OliveDrab3
-105 139 34 OliveDrab4
-202 255 112 DarkOliveGreen1
-188 238 104 DarkOliveGreen2
-162 205 90 DarkOliveGreen3
-110 139 61 DarkOliveGreen4
-255 246 143 khaki1
-238 230 133 khaki2
-205 198 115 khaki3
-139 134 78 khaki4
-255 236 139 LightGoldenrod1
-238 220 130 LightGoldenrod2
-205 190 112 LightGoldenrod3
-139 129 76 LightGoldenrod4
-255 255 224 LightYellow1
-238 238 209 LightYellow2
-205 205 180 LightYellow3
-139 139 122 LightYellow4
-255 255 0 yellow1
-238 238 0 yellow2
-205 205 0 yellow3
-139 139 0 yellow4
-255 215 0 gold1
-238 201 0 gold2
-205 173 0 gold3
-139 117 0 gold4
-255 193 37 goldenrod1
-238 180 34 goldenrod2
-205 155 29 goldenrod3
-139 105 20 goldenrod4
-255 185 15 DarkGoldenrod1
-238 173 14 DarkGoldenrod2
-205 149 12 DarkGoldenrod3
-139 101 8 DarkGoldenrod4
-255 193 193 RosyBrown1
-238 180 180 RosyBrown2
-205 155 155 RosyBrown3
-139 105 105 RosyBrown4
-255 106 106 IndianRed1
-238 99 99 IndianRed2
-205 85 85 IndianRed3
-139 58 58 IndianRed4
-255 130 71 sienna1
-238 121 66 sienna2
-205 104 57 sienna3
-139 71 38 sienna4
-255 211 155 burlywood1
-238 197 145 burlywood2
-205 170 125 burlywood3
-139 115 85 burlywood4
-255 231 186 wheat1
-238 216 174 wheat2
-205 186 150 wheat3
-139 126 102 wheat4
-255 165 79 tan1
-238 154 73 tan2
-205 133 63 tan3
-139 90 43 tan4
-255 127 36 chocolate1
-238 118 33 chocolate2
-205 102 29 chocolate3
-139 69 19 chocolate4
-255 48 48 firebrick1
-238 44 44 firebrick2
-205 38 38 firebrick3
-139 26 26 firebrick4
-255 64 64 brown1
-238 59 59 brown2
-205 51 51 brown3
-139 35 35 brown4
-255 140 105 salmon1
-238 130 98 salmon2
-205 112 84 salmon3
-139 76 57 salmon4
-255 160 122 LightSalmon1
-238 149 114 LightSalmon2
-205 129 98 LightSalmon3
-139 87 66 LightSalmon4
-255 165 0 orange1
-238 154 0 orange2
-205 133 0 orange3
-139 90 0 orange4
-255 127 0 DarkOrange1
-238 118 0 DarkOrange2
-205 102 0 DarkOrange3
-139 69 0 DarkOrange4
-255 114 86 coral1
-238 106 80 coral2
-205 91 69 coral3
-139 62 47 coral4
-255 99 71 tomato1
-238 92 66 tomato2
-205 79 57 tomato3
-139 54 38 tomato4
-255 69 0 OrangeRed1
-238 64 0 OrangeRed2
-205 55 0 OrangeRed3
-139 37 0 OrangeRed4
-255 0 0 red1
-238 0 0 red2
-205 0 0 red3
-139 0 0 red4
-255 20 147 DeepPink1
-238 18 137 DeepPink2
-205 16 118 DeepPink3
-139 10 80 DeepPink4
-255 110 180 HotPink1
-238 106 167 HotPink2
-205 96 144 HotPink3
-139 58 98 HotPink4
-255 181 197 pink1
-238 169 184 pink2
-205 145 158 pink3
-139 99 108 pink4
-255 174 185 LightPink1
-238 162 173 LightPink2
-205 140 149 LightPink3
-139 95 101 LightPink4
-255 130 171 PaleVioletRed1
-238 121 159 PaleVioletRed2
-205 104 137 PaleVioletRed3
-139 71 93 PaleVioletRed4
-255 52 179 maroon1
-238 48 167 maroon2
-205 41 144 maroon3
-139 28 98 maroon4
-255 62 150 VioletRed1
-238 58 140 VioletRed2
-205 50 120 VioletRed3
-139 34 82 VioletRed4
-255 0 255 magenta1
-238 0 238 magenta2
-205 0 205 magenta3
-139 0 139 magenta4
-255 131 250 orchid1
-238 122 233 orchid2
-205 105 201 orchid3
-139 71 137 orchid4
-255 187 255 plum1
-238 174 238 plum2
-205 150 205 plum3
-139 102 139 plum4
-224 102 255 MediumOrchid1
-209 95 238 MediumOrchid2
-180 82 205 MediumOrchid3
-122 55 139 MediumOrchid4
-191 62 255 DarkOrchid1
-178 58 238 DarkOrchid2
-154 50 205 DarkOrchid3
-104 34 139 DarkOrchid4
-155 48 255 purple1
-145 44 238 purple2
-125 38 205 purple3
- 85 26 139 purple4
-171 130 255 MediumPurple1
-159 121 238 MediumPurple2
-137 104 205 MediumPurple3
- 93 71 139 MediumPurple4
-255 225 255 thistle1
-238 210 238 thistle2
-205 181 205 thistle3
-139 123 139 thistle4
- 0 0 0 gray0
- 0 0 0 grey0
- 3 3 3 gray1
- 3 3 3 grey1
- 5 5 5 gray2
- 5 5 5 grey2
- 8 8 8 gray3
- 8 8 8 grey3
- 10 10 10 gray4
- 10 10 10 grey4
- 13 13 13 gray5
- 13 13 13 grey5
- 15 15 15 gray6
- 15 15 15 grey6
- 18 18 18 gray7
- 18 18 18 grey7
- 20 20 20 gray8
- 20 20 20 grey8
- 23 23 23 gray9
- 23 23 23 grey9
- 26 26 26 gray10
- 26 26 26 grey10
- 28 28 28 gray11
- 28 28 28 grey11
- 31 31 31 gray12
- 31 31 31 grey12
- 33 33 33 gray13
- 33 33 33 grey13
- 36 36 36 gray14
- 36 36 36 grey14
- 38 38 38 gray15
- 38 38 38 grey15
- 41 41 41 gray16
- 41 41 41 grey16
- 43 43 43 gray17
- 43 43 43 grey17
- 46 46 46 gray18
- 46 46 46 grey18
- 48 48 48 gray19
- 48 48 48 grey19
- 51 51 51 gray20
- 51 51 51 grey20
- 54 54 54 gray21
- 54 54 54 grey21
- 56 56 56 gray22
- 56 56 56 grey22
- 59 59 59 gray23
- 59 59 59 grey23
- 61 61 61 gray24
- 61 61 61 grey24
- 64 64 64 gray25
- 64 64 64 grey25
- 66 66 66 gray26
- 66 66 66 grey26
- 69 69 69 gray27
- 69 69 69 grey27
- 71 71 71 gray28
- 71 71 71 grey28
- 74 74 74 gray29
- 74 74 74 grey29
- 77 77 77 gray30
- 77 77 77 grey30
- 79 79 79 gray31
- 79 79 79 grey31
- 82 82 82 gray32
- 82 82 82 grey32
- 84 84 84 gray33
- 84 84 84 grey33
- 87 87 87 gray34
- 87 87 87 grey34
- 89 89 89 gray35
- 89 89 89 grey35
- 92 92 92 gray36
- 92 92 92 grey36
- 94 94 94 gray37
- 94 94 94 grey37
- 97 97 97 gray38
- 97 97 97 grey38
- 99 99 99 gray39
- 99 99 99 grey39
-102 102 102 gray40
-102 102 102 grey40
-105 105 105 gray41
-105 105 105 grey41
-107 107 107 gray42
-107 107 107 grey42
-110 110 110 gray43
-110 110 110 grey43
-112 112 112 gray44
-112 112 112 grey44
-115 115 115 gray45
-115 115 115 grey45
-117 117 117 gray46
-117 117 117 grey46
-120 120 120 gray47
-120 120 120 grey47
-122 122 122 gray48
-122 122 122 grey48
-125 125 125 gray49
-125 125 125 grey49
-127 127 127 gray50
-127 127 127 grey50
-130 130 130 gray51
-130 130 130 grey51
-133 133 133 gray52
-133 133 133 grey52
-135 135 135 gray53
-135 135 135 grey53
-138 138 138 gray54
-138 138 138 grey54
-140 140 140 gray55
-140 140 140 grey55
-143 143 143 gray56
-143 143 143 grey56
-145 145 145 gray57
-145 145 145 grey57
-148 148 148 gray58
-148 148 148 grey58
-150 150 150 gray59
-150 150 150 grey59
-153 153 153 gray60
-153 153 153 grey60
-156 156 156 gray61
-156 156 156 grey61
-158 158 158 gray62
-158 158 158 grey62
-161 161 161 gray63
-161 161 161 grey63
-163 163 163 gray64
-163 163 163 grey64
-166 166 166 gray65
-166 166 166 grey65
-168 168 168 gray66
-168 168 168 grey66
-171 171 171 gray67
-171 171 171 grey67
-173 173 173 gray68
-173 173 173 grey68
-176 176 176 gray69
-176 176 176 grey69
-179 179 179 gray70
-179 179 179 grey70
-181 181 181 gray71
-181 181 181 grey71
-184 184 184 gray72
-184 184 184 grey72
-186 186 186 gray73
-186 186 186 grey73
-189 189 189 gray74
-189 189 189 grey74
-191 191 191 gray75
-191 191 191 grey75
-194 194 194 gray76
-194 194 194 grey76
-196 196 196 gray77
-196 196 196 grey77
-199 199 199 gray78
-199 199 199 grey78
-201 201 201 gray79
-201 201 201 grey79
-204 204 204 gray80
-204 204 204 grey80
-207 207 207 gray81
-207 207 207 grey81
-209 209 209 gray82
-209 209 209 grey82
-212 212 212 gray83
-212 212 212 grey83
-214 214 214 gray84
-214 214 214 grey84
-217 217 217 gray85
-217 217 217 grey85
-219 219 219 gray86
-219 219 219 grey86
-222 222 222 gray87
-222 222 222 grey87
-224 224 224 gray88
-224 224 224 grey88
-227 227 227 gray89
-227 227 227 grey89
-229 229 229 gray90
-229 229 229 grey90
-232 232 232 gray91
-232 232 232 grey91
-235 235 235 gray92
-235 235 235 grey92
-237 237 237 gray93
-237 237 237 grey93
-240 240 240 gray94
-240 240 240 grey94
-242 242 242 gray95
-242 242 242 grey95
-245 245 245 gray96
-245 245 245 grey96
-247 247 247 gray97
-247 247 247 grey97
-250 250 250 gray98
-250 250 250 grey98
-252 252 252 gray99
-252 252 252 grey99
-255 255 255 gray100
-255 255 255 grey100
-169 169 169 dark grey
-169 169 169 DarkGrey
-169 169 169 dark gray
-169 169 169 DarkGray
-0 0 139 dark blue
-0 0 139 DarkBlue
-0 139 139 dark cyan
-0 139 139 DarkCyan
-139 0 139 dark magenta
-139 0 139 DarkMagenta
-139 0 0 dark red
-139 0 0 DarkRed
-144 238 144 light green
-144 238 144 LightGreen
diff --git a/etc/sex.6 b/etc/sex.6
deleted file mode 100644
index edff05c1e6b..00000000000
--- a/etc/sex.6
+++ /dev/null
@@ -1,115 +0,0 @@
-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
-
- -T<number>
- voice-net sex via standard uucp autodialer facilities;
- area code prefix of 900 is assumed.
-
- -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/etc/spook.lines b/etc/spook.lines
deleted file mode 100644
index 01ad7e2996c..00000000000
--- a/etc/spook.lines
+++ /dev/null
Binary files differ
diff --git a/etc/tasks.texi b/etc/tasks.texi
deleted file mode 100644
index db76b8c02a8..00000000000
--- a/etc/tasks.texi
+++ /dev/null
@@ -1,433 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-@c %**start of header
-@setfilename tasks.info
-@settitle GNU Task List
-@c UPDATE THIS DATE WHENEVER YOU MAKE CHANGES!
-@set lastupdate 7 December 1996
-@c %**end of header
-
-@setchapternewpage off
-
-@titlepage
-@title GNU Task List
-@author Free Software Foundation
-@author last updated @value{lastupdate}
-@end titlepage
-
-@ifinfo
-@node Top, Preface, (dir), (dir)
-@top GNU Task List
-
-This file is updated automatically from @file{tasks.texi}, which was
-last updated on @value{lastupdate}.
-@end ifinfo
-
-@menu
-* Preface::
-* Documentation::
-* Unix-Related Projects::
-* Kernel Projects::
-* Extensions::
-* X Windows Projects::
-* Other Projects::
-* Compilers::
-* Games and Recreations::
-@end menu
-
-@node Preface, Documentation, Top, Top
-@chapter About the GNU Task List
-
-Check with @code{gnu@@prep.ai.mit.edu}, for a possibly more current
-copy. You can also ftp it from a GNU FTP host in directory
-@file{/pub/gnu/tasks} - These files in different formats are available:
-@file{tasks.text}, @file{tasks.texi}, @file{tasks.info}, and
-@file{tasks.dvi}. It is also available on the GNU World Wide Web
-server: @file{http://www.gnu.ai.mit.edu}.
-
-If you start working steadily on a project, please let @code{gnu@@prep}
-know. We might have information that could help you; we'd also like to
-send you the GNU coding standards.
-
-Because of the natural tendency for most volunteers to write programming
-tools or programming languages, we have a comparative shortage of
-applications useful for non-programmer users. Therefore, we ask you to
-consider writing such a program.
-
-In general, a new program that does a completely new job advances the
-GNU project more than an improvement to an existing program.
-
-@node Documentation
-@chapter Documentation
-
-We very urgently need documentation for some parts of the system
-that already exist or will exist very soon:
-
-@itemize @bullet
-@item
-Completion of the documentation for CC-mode, a new Emacs mode for
-C, C++ and other languages.
-
-@item
-A C reference manual. (RMS made a try at one, which you could start
-with).
-
-@item
-A manual for Ghostscript.
-
-
-@item
-A manual for TCSH.
-
-@item
-A manual for PIC (the graphics formatting language).
-
-@item
-A manual for Oleo.
-
-@item
-A book on how GCC works and why various machine descriptions
-are written as they are.
-
-@item
-A manual for programming X-window applications.
-
-@item
-Manuals for various X window managers.
-
-@item
-Reference cards for those manuals that don't have them: C
-Compiler, Make, Texinfo, Termcap, and maybe the C Library.
-
-@item
-Many utilities need documentation, including @code{grep} and others.
-@end itemize
-
-@node Unix-Related Projects
-@chapter Unix-Related Projects
-
-@itemize @bullet
-@item
-We could use an emulation of Unix @code{spell}, which would run by
-invoking @code{ispell}.
-
-@item
-An improved version of the POSIX utility @code{pax}. There is one on
-Usenet, but it is said to be poorly written. Talk with
-@code{mib@@gnu.ai.mit.edu} about this project.
-
-@ignore
-@item
-Modify the GNU @code{dc} program to use the math routines of GNU
-@code{bc}.
-@end ignore
-
-@item
-A @code{grap} preprocessor program for @code{troff}.
-
-@item
-Various other libraries.
-
-@item
-An emulation of SCCS that works using RCS.
-
-@item
-Less urgent: @code{diction}, @code{explain}, and @code{style}, or
-something to do the same kind of job. Compatibility with Unix is not
-especially important for these programs.
-@end itemize
-
-@node Kernel Projects
-@chapter Kernel-Related Projects
-
-@itemize @bullet
-@item
-An over-the-ethernet debugger stub that will allow the kernel to be
-debugged from GDB running on another machine.
-
-This stub needs its own self-contained implementation of all protocols
-to be used, since the GNU system will use user processes to implement
-all but the lowest levels, and the stub won't be able to use those
-processes. If a simple self-contained implementation of IP and TCP is
-impractical, it might be necessary to design a new, simple protocol
-based directly on ethernet. It's not crucial to support high speed or
-communicating across gateways.
-
-It might be possible to use the Mach ethernet driver code, but it would
-need some changes.
-
-@item
-A shared memory X11 server to run under MACH is very desirable. The
-machine specific parts should be kept well separated.
-
-@item
-An implementation of CIFS, the ``Common Internet File System,'' for the
-HURD. This protocol is an offshoot of SMB.
-@end itemize
-
-@node Extensions
-@chapter Extensions to Existing GNU Software
-
-@itemize @bullet
-@item
-Enhance GCC. See files @file{PROJECTS} and @file{PROBLEMS} in the GCC
-distribution.
-
-@item
-GNU @code{sed} probably needs to be rewritten completely just to make it
-cleaner.
-
-@item
-Work on the partially-implemented C interpreter project.
-
-@item
-Help with the development of GNUStep, a GNU implementation of the
-OpenStep specification.
-
-@item
-Add features to GNU Make to record the precise rule with which each file
-was last recompiled; then recompile any file if its rule in the makefile
-has changed.
-
-@item
-Add a few features to GNU @code{diff}, such as handling large input
-files without reading entire files into core.
-
-@item
-An @code{nroff} macro package to simplify @code{texi2roff}.
-
-@item
-A queueing system for the mailer Smail that groups pending work by
-destination rather than by original message. This makes it possible
-to schedule retries coherently for each destination. Talk to
-@code{tron@@veritas.com} about this.
-
-Smail also needs a new chief maintainer.
-
-@item
-Enhanced cross-reference browsing tools. (We now have something at
-about the level of @code{cxref}.) We also could use something like
-@code{ctrace}. (Some people are now working on this project.)
-@end itemize
-
-@node X Windows Projects
-@chapter X Windows Projects
-
-@itemize @bullet
-@item
-An emulator for Macintosh graphics calls on top of X Windows.
-
-@item
-A music playing and editing system.
-
-@item
-A program to edit dance notation (such as labanotation) and display
-dancers moving on the screen.
-
-@item
-Port the Vibrant toolkit to work on X without using Motif.
-
-@item
-A program to display and edit Hypercard stacks.
-
-@item
-A paint program, supporting both bitmap-oriented operations and
-component-oriented operations. @code{xpaint} exists, but isn't very
-usable.
-
-@item
-A vector-based drawing program in the spirit of Adobe Illustrator
-and Corel Draw.
-
-@item
-An interactive 3D modeling utility with rendering/raytracing capabilities.
-
-@item
-A program for graphic morphing of scanned photographs.
-@end itemize
-
-@node Other Projects
-@chapter Other Projects
-
-If you think of others that should be added, please
-send them to @code{gnu@@prep.ai.mit.edu}.
-
-@itemize @bullet
-@item
-A free program for public-key encryption.
-
-This program should use the Diffie-Helman algorithm for public key
-encryption, not the RSA algorithm, because the Diffie-Helman patent in
-the US will expire in 1997. It should use triple-DES, not IDEA, for
-block encryption because IDEA is patented in many countries and the
-patents will not expire soon. In other respects, it should be like PGP.
-
-This program needs to be written by someone who is not a US citizen,
-outside the US, to avoid problems with US export control law.
-
-Many people believe that PGP is free software, but that is not actually
-true. The distribution terms set by the copyright holders do not allow
-everyone to use and redistribute it.
-
-@item
-A program to convert compiled programs represented in OSF ANDF
-(``Architecture Neutral Distribution Format'') into ANSI C.
-
-@item
-An imitation of Page Maker or Ventura Publisher.
-
-@item
-An imitation of @code{dbase2} or @code{dbase3} (How dbased!)
-
-@item
-A program to reformat Fortran programs in a way that is pretty.
-
-@item
-A bulletin board system. There are a few free ones, but they don't have
-all the features that people want in such systems. It would make sense
-to start with an existing one and add the other features.
-
-@item
-A general ledger program, including support for accounts payable,
-account receivables, payroll, inventory control, order processing, etc.
-
-@item
-A teleconferencing program which does the job of CU-SeeMe (which is,
-alas, not free software).
-
-@item
-A program to typeset C code for printing.
-For ideas on what to do, see the book,
-
-@display
-Human Factors and Typography for More Readable Programs,
-Ronald M. Baecker and Aaron Marcus,
-Addison-Wesley, ISBN 0-201-10745-7
-@end display
-
-(I don't quite agree with a few of the details they propose.)
-
-@item
-Speech-generation programs (there is a program from Brown U that you
-could improve).
-
-@item
-Speech-recognition programs (single-speaker, disconnected speech is sufficient).
-
-@item
-A program to play sound distributed in ``Real Audio'' format.
-
-@item
-A program to generate ``Real Audio'' format from audio input.
-
-@item
-Scientific mathematical subroutines, including clones of SPSS.
-
-@item
-Statistical tools.
-
-@item
-Software to replace card catalogues in libraries.
-
-@item
-Grammar and style checking programs.
-
-@item
-An implementation of the S language (an interpreted language used for
-statistics).
-
-@item
-A translator from Scheme to C.
-
-@item
-Optical character recognition programs; especially if suitable for
-scanning documents with multiple fonts and capturing font info as well
-as character codes. Work is being done on this, but more help is needed.
-
-@item
-A program to scan a line drawing and convert it to Postscript.
-
-@item
-A program to recognize handwriting.
-
-@item
-A pen based interface.
-
-@item
-CAD software, such as a vague imitation of Autocad.
-
-@item
-Software for comparing DNA sequences, and finding matches and
-alignments.
-@end itemize
-
-@node Compilers
-@chapter Compilers for Other Batch Languages
-
-Volunteers are needed to write parsers/front ends for languages such as
-Algol 60, Algol 68, PL/I, Cobol, Fortran 90, or whatever, to be used
-with the code generation phases of the GNU C compiler. (C, C++, and
-Objective-C are done; Fortran 77 is mostly done; Ada, Pascal, and Java
-are being worked on.)
-
-@c Fortran status is here so gnu@prep and the volunteer coordinators
-@c don't have to answer the question -len
-You can get the status of the Fortran front end with this command:
-
-@example
-finger -l fortran@@gnu.ai.mit.edu
-@end example
-
-@node Games and Recreations
-@chapter Games and Recreations
-
-Video-oriented games that work with the X window system.
-
-@itemize @bullet
-@item
-A Doom-compatible display game engine, for running the many free
-levels people have written for Doom.
-
-@item
-Empire (there is a free version but it needs upgrading)
-
-@item
-An ``empire builder'' system that makes it easy to write various kinds of
-simulation games.
-
-@item
-Improve GnuGo, which is not yet very sophisticated.
-
-@item
-Imitations of popular video games:
-
-@itemize -
-@item
-Space war, Asteroids, Pong, Columns.
-@item
-Defending cities from missiles.
-@item
-Plane shoots at lots of other planes, tanks, etc.
-@item
-Wizard fights fanciful monster.
-@item
-A golf game.
-@item
-Program a robot by sticking building blocks together,
-then watch it explore a world.
-@item
-Biomorph evolution (as in Scientific American).
-@item
-A program to display effects of moving at relativistic speeds.
-@end itemize
-
-@item
-Intriguing screen-saver programs to make interesting pictures.
-Other such programs that are simply entertaining to watch.
-For example, an aquarium.
-@end itemize
-
-We do not need @code{rogue}, as we have @code{hack}.
-
-@contents
-
-@bye
diff --git a/etc/termcap.dat b/etc/termcap.dat
deleted file mode 100644
index b86869c1fa7..00000000000
--- a/etc/termcap.dat
+++ /dev/null
@@ -1,1246 +0,0 @@
-
-# This is termcap.dat, a copy of the /etc/termcap file included here
-# for use on VMS.
-
-# I know that many terminals are missing from this version of the file
-# because they were deleted at MIT.
-# I hope that someone will add in all the missing terminal types
-# and send me a corrected, larger file.
-
-# These are local terminals.
-
-v1|tvi912|912|920|tvi920|old televideo:\
- :ct=\E3:st=\E1:cr=^M:do=^J:nl=^J:bl=^G:\
- :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=^A@\r:k1=^AA\r:k2=^AB\r:k3=^AC\r:\
- :bs:am:k4=^AD\r:k5=^AE\r:k6=^AF\r:k7=^AG\r:k8=^AH\r:k9=^AI\r:\
- :ho=^^:im=:ic=\EQ:li#24:nd=^L:ta=^I:pt:se=\Ek:so=\Ej:up=^K:us=\El:ue=\Em:\
- :ma=^K^P^L :sg#1:ug#1:
-ZV|bobcat|sbobcat|HP 9000 model 300 console:\
- :al=10*\EL:am:bs:\
- :cd=\EJ:ce=\EK:ch=6\E&a%dC:cl=\EH\EJ:\
- :co#128:da:db:dc=\EP:dl=10*\EM:do=\EB:ei=\ER:\
- :kb=^H:kd=\EB:kh=\Eh:kl=\ED:kr=\EC:ku=\EA:\
- :ke=\E&s0A:ks=\E&s1A:\
- :li#47:mi:nd=\EC:pt:\
- :se=\E&d@:so=\E&dB:\
- :up=\EA:xs:\
- :cm=6\E&a%dy%dC:cv=6\E&a%dY:\
- :im=\EQ:ml=\El:mu=\Em:\
- :ue=\E&d@:us=\E&dD:bt=\Ei:sg#0:
-ZX|gator-t|HP 9000 model 237 emulating extra-tall AAA:\
- :cr=^M:do=^J:nl=^J:bl=^G:al=\E[L:le=^H:bs:\
- :cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:co#128:li#94:\
- :dc=\E[P:dl=\E[M:ho=\E[H:ic=\E[@:\
- :AL=1*\E[%dL:DL=1*\E[%dM:IC=4\E[%d@:DC=4\E[%dP:rp=1*%.\E[%db:mr=\E[7m:me=\E[m:\
- :km: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:
-ZW|gator|HP 9000 model 237 emulating AAA:\
- :cr=^M:do=^J:nl=^J:bl=^G:al=\E[L:le=^H:bs:\
- :cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:co#128:li#47:\
- :dc=\E[P:dl=\E[M:ho=\E[H:ic=\E[@:\
- :AL=1*\E[%dL:DL=1*\E[%dM:IC=4\E[%d@:DC=4\E[%dP:rp=1*%.\E[%db:mr=\E[7m:me=\E[m:\
- :km: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:
-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:\
- :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:\
- :ce=\EK:ho=\EH:
-#
-# N: ANN ARBOR
-#
-N0|aa|annarbor|4080|ann arbor 4080:\
- :cr=^M:do=^J:nl=^J:bl=^G: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:
-# 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 irrelevant 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 separators 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 preceding 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
-#
-N1|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:
-N2|aaa-unk|ann arbor ambassador (internal - don't use this directly):\
- :cr=^M:do=^J:nl=^J:bl=^G:al=1*\E[L:am:le=^H:bs:km:\
- :cd=7.2*\E[J:ce=5\E[K:cl=7.2*\E[H\E[J:cm=\E[%i%d;%dH:co#80:\
- :dc=4\E[P:dl=1*\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:ce=\E[K:\
- :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`:\
- :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:\
- :AL=1*\E[%dL:DL=1*\E[%dM:IC=4\E[%d@:DC=4\E[%dP:\
- :cS=\E[%d;%d;%d;%dp:\
- :vs=\E[>52;54h\E[>30;37;38;39l:ve=\E[>52l\E[>37h:
-# All the ti strings used to start with \E[2J, which cleared the screen.
-# But this was so slow that it caused ^S/^Q lossage.
-# So I removed the \E[2J's. -- rms, 1/29/86
-N3|aaa-18|ann arbor ambassador/18 lines:\
- :ti=\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:
-N4|aaa-20|ann arbor ambassador/20 lines:\
- :ti=\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:
-N5|aaa-22|ann arbor ambassador/22 lines:\
- :ti=\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:
-N6|aaa-24|ann arbor ambassador/24 lines:\
- :ti=\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:
-N7|aaa-26|ann arbor ambassador/26 lines:\
- :ti=\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:
-N8|aaa-28|ann arbor ambassador/28 lines:\
- :ti=\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:
-N9|aaa|ambassador|aaa-30|ann arbor ambassador/30 lines:\
- :ti=\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[30;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:
-NA|aaa-36|ann arbor ambassador/36 lines:\
- :ti=\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:
-NB|aaa-40|ann arbor ambassador/40 lines:\
- :ti=\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:
-NC|aaa-48|ann arbor ambassador/48 lines:\
- :ti=\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:
-ND|aaa-60|ann arbor ambassador/60 lines:\
- :ti=\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:
-NE|aaa-unk-s|ann arbor ambassador unknown with/status:\
- :hs:es: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:
-NF|aaa-18-s|ann arbor ambassador/18 lines + status line:\
- :ti=\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:
-NG|aaa-20-s|ann arbor ambassador/20 lines + status line:\
- :ti=\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:
-NH|aaa-22-s|ann arbor ambassador/22 lines + status line:\
- :ti=\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:
-NI|aaa-24-s|ann arbor ambassador/24 lines + status line:\
- :ti=\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:
-NJ|aaa-26-s|ann arbor ambassador/26 lines + status line:\
- :ti=\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:
-NK|aaa-28-s|ann arbor ambassador/28 lines + status line:\
- :ti=\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:
-NL|aaa-30-s|ann arbor ambassador/30 lines + status line:\
- :ti=\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:
-NM|aaa-36-s|ann arbor ambassador/36 lines + status line:\
- :ti=\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:
-NN|aaa-40-s|ann arbor ambassador/40 lines + status line:\
- :ti=\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:
-NO|aaa-48-s|ann arbor ambassador/48 lines+sl:\
- :ti=\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:
-NP|aaa-60-s|ann arbor ambassador/60 lines + status line:\
- :ti=\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:
-NQ|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:
-NR|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:
-NS|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:
-NT|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:
-NU|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:
-NV|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:
-NW|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:
-NX|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:
-NY|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:
-NZ|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:
-Na|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:
-Nb|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:\
- :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-18-s:
-Nc|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:\
- :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-20-s:
-Nd|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:\
- :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-22-s:
-Ne|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:\
- :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-24-s:
-Nf|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:\
- :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-26-s:
-Ng|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:\
- :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-28-s:
-Nh|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:\
- :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-30-s:
-Ni|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:\
- :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-36-s:
-Nj|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:\
- :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-40-s:
-Nk|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:\
- :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-48-s:
-Nl|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:\
- :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-60-s:
-Nm|aaa-24-ctxt:\
- :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:
-Nn|aaa-24-rv-ctxt:\
- :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:
-No|aaa-30-s-ctxt:\
- :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:
-Np|aaa-30-s-rv-ctxt:\
- :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-rv:
-Nq|aaa-ctxt|aaa-30-ctxt:\
- :ti=\E[30;0;0;30p:te=\E[60;0;0;30p\E[60;1H\E[K:tc=aaa-30:
-Nr|aaa-rv-ctxt|aaa-30-rv-ctxt:\
- :ti=\E[30;0;0;30p:te=\E[60;0;0;30p\E[60;1H\E[K:tc=aaa-30-rv:
-Ns|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:
-#Kludge for supdup
-aaa-supdup|ann arbor ambassador 30/ for supdup :\
- :ns:tc=aaa-30:
-
-#
-# yet another attempt at the aaa terminal from CCA:
-#
-ZJ|aaax|ambasx|ambassadorx|ann arbor ambassador base descriptor/:\
- :al=\E[L:bs:bt=\E[Z:bw:\
- :cd=\E[J:ce=\E[K:ch=\E[%i%d`:cl=\E[H\E[2J:cm=\E[%i%d;%dH:co#80:\
- :cv=\E[%i%dd:da:db:dc=\E[P:dl=\E[M:ho=\E[H:ic=\E[@:\
- :mi:nd=\E[C:pt:sf=\E[S:sr=\E[T:se=\E[m:so=\E[7m:\
- :km:mm=\E[>52h:mo=\E[>52l:\
- :ue=\E[m:up=\E[A:us=\E[4m:
-ZK|aaa48|ambas|ambassador|ann arbor ambassador/48 lines:\
- :is=\E[48;0;0;48p\E[H\E[J\E[1Q\E[m\E[>30l\E[>26l\E[>32h\E[>33h\E[>52h:\
- :li#48:mi:tc=aaax:
-ZL|aaa24|ambas24|ambassador24|ann arbor ambassador/24 lines:\
- :is=\E[24;0;0;24p\E[H\E[J\E[1Q\E[m\E[>30l\E[>26l\E[>32h\E[>33h\E[>52h:\
- :li#24:mi:tc=aaax:
-ZM|aaa30|ambas30|ambassador30|ann arbor ambassador/30 lines:\
- :is=\E[30;0;0;30p\E[H\E[J\E[1Q\E[m\E[>30l\E[>26l\E[>32h\E[>33h\E[>52h:\
- :li#30:mi:tc=aaax:
-ZN|aaa60|ambas60|ambassador60|ann arbor ambassador/60 lines:\
- :is=\E[60;0;0;60p\E[H\E[J\E[1Q\E[m\E[>30l\E[>26l\E[>32h\E[>33h\E[>52h:\
- :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:\
- :co#132:tc=vt100:
-d0|vt100|vt100-am|vt100-80|vt125|vt125-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:\
- :md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:\
- :is=\E<\E[m\E>\E[?7h\E[?3;4;6l\200\200\200\200\200\200\200\200:\
- :rs=\E<\E[m\E>\E[?7h\E[?3;4;6l\200\200\200\200\200\200\200\200:\
- :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
- :cs=\E[%i%d;%dr:ks=\E[?1h\E=:ke=\E[?1l\E>:\
- :kh=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:ta=^I:sf=5\ED:sr=5\EM:xn:\
- :dN#4:vt#3:sc=\E7:rc=\E8:
-d0|vt132-132|dec vt132 with 132 columns:\
- :al=99\E[L:dl=99\E[M:ip=7:dc=7\E[P:ei=\E[4l:im=\E[4h:xn:dN#30:\
- :co#132:tc=vt100:
-d0|vt132|vt132-80|dec vt132 with 80 columns:\
- :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:
-
-dw|vt52|vt52-80|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:
-
-# Sun workstation consoles
-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:km:mi:ms:pt:\
- :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:rs=\E[s:\
- :kd=\E[B:kl=\E[D:ku=\E[A:kr=\E[C:kh=\E[H:\
- :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:\
- :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:
-# From john@ucbrenoir Tue Sep 24 13:14:44 1985
-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:
-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:
-M6|sun-e|sun-nic|sune|Sun Microsystems Workstation without insert character:\
- :ic@:im@:ei@:tc=sun:
-
-# Nu machine parameters taken from mit-vax.
-# smc - 5/21/85
-#
-dg|nuterminal:\
- :al=1*\EL:am:bs:cd=60\EJ:ce=10\EK:cl=60\EE:cm=10\EY%+ %+ :\
- co#80:dc=2.5*\EN:\
- :dl=1*\EM:do=\EB:ei=\EO:ho=\EH:im=\E@:ip=2.5*: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:\
- :k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:\
- :l6=blue:l7=red:l8=white:k6=\EP:k7=\EQ:k8=\ER:
-nu|nu24|nuwindow:\
- :al=1*\EL:bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#86:\
- :dl=1*\EM:do=\EB:ei=\EO:ho=\EH:im=\E@:ip=2.5*: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:
-bnu|nu51|bnuwindow:\
- :co#86:li#51:tc=nu:
-fnu|nu61|fnuwindow:\
- :co#86:li#61:tc=nu:
-nunix-30|nu-telnet-30|nu-half: Half nu screen thru telnet:\
- :am:al=\EL:bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#78:\
- :dl=\EM:do=\EB:ip=2.5*:ho=\EH:li#30:nd=\EC:\
- :pt:sr=\EI:se=\Eq:so=\Ep:up=\EA:
-nunix-61|nu-telnet-61|nu-full| Full nu screen thru telnet:\
- :co#78:li#61:tc=nunix-30:
-
-## VT200 entry for VMS. Also for VT300.
-# Make sure not to use \n for nl or anything else.
-# 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:\
- :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:\
- :cm=%i\E[%d;%dH:co#80:cr=\r:cs=\E[%i%d;%dr:ct=\E[3g:\
- :dc=\E[P:dl=\E[M:dm=:do=\ED:ec=\E[%dX:ed=:ei=\E[4l:\
- :ho=\E[H:ic:im=\E[4h:it#8:k1=\EOP:k2=\EOQ:k3=\EOR:\
- :k4=\EOS:kd=\E[B:ke=\E[?1l\E>:kl=\E[D:kn#4:kr=\E[C:ks=\E[?1h\E=:\
- :ku=\E[A:le=^H:li#24:mb=\E[5m:md=\E[1m:me=\E[0m:mi:\
- :mr=\E[7m:ms:nd=\E[C:nl=\ED:nw=\EE:pf=\E[?4i:po=\E[?5i:\
- :ps=\E[i:rc=\E8:sc=\E7:se=\E[27m:sf=1*\ED:so=\E[7m:\
- :sr=1*\EM:st=\EH:ue=\E[24m:up=\EM:us=\E[4m:xn:
-d0|vt200-132|vt300-132|VT 200 with 132 columns, on VMS:\
- :co#132:tc=vt200-80:
-
-aP|apollo_15P|apollo 15 inch display:\
- :dN@:tc=vt132:
-aQ|apollo_19L|apollo 19 inch display:\
- :dN@:tc=vt132:
-aR|apollo_color|apollo color display:\
- :dN@:tc=vt132:
-aS|apollo_800_color|apollo 800 line color display:\
- :dN@:tc=vt132:
-d3|vt132|vt-132:\
- :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:
-d0|vt100|vt100n|vt100 with no init:\
- :co#80:li#24:am:bs:pt:xn:cl=45\E[H\E[2J:\
- :cm=%i\E[%d;%dH:nd=\E[C:up=\EM:ho=\E[H:ce=2\E[K:cd=2*\E[J:\
- :nl=\EE:cr=\r:sr=5\EM:sf=30\E7\E[200H\ED\E8:\
- :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:LC:\
- :kl=\E[D:kr=\E[C:ku=\E[A:kd=\E[B:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:
-# *************************************************************************
-# Added for del to use a 132 char width terminal
-#
-d0|vt100l|vt100n|vt100 with no init:\
- :co#132:li#24:am:bs:pt:xn:cl=45\E[H\E[2J:\
- :cm=%i\E[%d;%dH:nd=\E[C:up=\EM:ho=\E[H:ce=2\E[K:cd=2*\E[J:\
- :nl=\EE:cr=\r:sr=5\EM:sf=30\E7\E[200H\ED\E8:\
- :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:LC:\
- :kl=\E[D:kr=\E[C:ku=\E[A:kd=\E[B:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:
-#
-# End of "Add for del"
-# **************************************************************************
-df|vt100|vt-100|vt100f|pt100|pt-100|dec vt100 (fast scroll, reverse video):\
- :is=\E>\E[?4l\E[?5h\E[?7h\E[?8h:\
- :if=/usr/lib/tabset/vt100:tc=vt100n:
-d1|vt100|vt100fnv|dec vt100 (fast scroll, normal video):\
- :is=\E>\E[?4l\E[?5l\E[?7h\E[?8h:\
- :if=/usr/lib/tabset/vt100:tc=vt100n:
-ds|vt100|vt100s|dec vt100 (smooth scroll, reverse video):\
- :is=\E>\E[?4h\E[?5h\E[?7h\E[?8h:\
- :if=/usr/lib/tabset/vt100:tc=vt100n:
-dn|vt100|vt100snv|dec vt100 (smooth scroll, normal video):\
- :is=\E>\E[?4h\E[?5l\E[?7h\E[?8h:\
- :if=/usr/lib/tabset/vt100:tc=vt100n:
-# This was designed for a VT320 emulator, but it is probably a good start
-# at support for the VT320 itself.
-# Please send changes with explanations to bug-gnu-emacs@prep.ai.mit.edu.
-k3|vt320|vt320-k3|kermit|MS-Kermit 3.00's vt320 emulation:\
- :AL=\E[%dL:CC=\E:DL=\E[%dM:IC=\E[%d@:DC=\E[%dP:DO=\E[%dB:LE=\E[%dD:\
- :RI=\E[%dC:SR=\E[%dL:UP=\E[%dA:ae=\E(B:al=\E[L:am:as=\E(0:bl=^G:\
- :cd=\E[J:ce=\E[K:ch=\E[%i%dG:cl=\E[H\E[J:cm=\E[%i%d;%dH:co#80:cr=^M:\
- :cs=\E[%i%d;%dr:ct=\E[3g:cv=\E[%i%dd:dc=\E[P:do=^J:dl=\E[M:ds=\E[0$~:\
- :ec=\E[%dX:ei=\E[4l:es:fs=\E[0$}:ho=\E[H:hs:im=\E[4h:\
- :is=\E>\E F\E[?1l\E[?7h\E[r\E[2$~:k1=\EOP:k2=\EOQ:\
- :k3=\EOR:k4=\EOS:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:k0=\E[21~:\
- :kI=\E[2~:kL=\E[3~:kN=\E[6~:kP=\E[5~:kb=^H:kd=\EOB:ke=\E[?1l\E>:\
- :kl=\EOD:km:kn#20:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:\
- :le=^H:li#49:mb=\E[5m:md=\E[1m:me=\E[m:mi:mr=\E[7m:ms:nd=\E[C:\
- :nl=^J:pb#9600:po=\E[5i:pf=\E[4i:ps=\E[0i:pt:rc=\E8:\
- :rs=\E(B\E)B\E>\E F\E[4;20l\E[12h\E[?1;5;6;38;42l\E[?7;25h\E4i\E?4i\E[m\E[r\E[2$~:\
- :sc=\E7:se=\E[27m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
- :ts=\E[1$}^M\E[K:ue=\E[24m:\
- :up=\E[A:us=\E[4m:vb=\E[?5h\E[?5l\E[?5h\E[?5l\E[?5h\E[?5l:ve=\E[?25h:\
- :vi=\E[?25l:vt#3:xn:
-sw|switch|intelligent switch:co#80:os:am:
-su|dumb|un|unknown:co#80:os:am:
-sp|plugboard:co#80:os:am:
-sa|arpanet|network:co#80:os:am:
-sd|du|dialup:co#80:os:am:
-sb|bussiplexer:co#80:os:am:
-# Note that all of these claim to be "c100" in order to please the
-# pen and emacs editors. If the user does a "tset c100" he will get co.
-co|c100|concept|concept100|concept 100:\
- :is=\EU\Ef\E7\E5\E8\El\ENH\EK\E\200\Eo&\200\Eo\47\E:\
- :al=3*\E^R:am:bs:cd=16*\E^C:ce=16\E^S:cl=2*^L:cm=\Ea%+ %+ :co#80:\
- :dc=16\E^A:dl=3*\E^B:ei=\E\200:eo:im=\E^P:in:ip=16*:li#24:mi:nd=\E=:\
- :pt:kb=^h:so=\ENh:se=\ENH:ta=8\t:ul:up=\E;:db:xn:vs=\EW:ve=\Ew:\
- :vb=\Ek\200\200\200\200\200\200\200\200\200\200\200\200\200\200\EK:\
- :us=\EG:ue=\Eg:ks=\EX\ES:ke=\Ex\Es:ku=\E;:kd=\E<:kl=\E>:kr=\E=:kh=\E?:\
- :k1=\E5:k2=\E6:k3=\E7:.dN#9:dC#9:
-c4|c100|c1004p|c100 w/4 pages:\
- :ti=\EU\Ev 8p\Ep\r:te=\Ev ~p\Ep\r\n:vs@:ve@:tc=concept:
-cP|c100|c100rv4ppp|c100 with printer port:\
- :is=\EU\Ef\E7\E5\E8\El\ENH\Ek\E\200\Eo&\200\Eo!\200\EQ"\EY(^W\Eo\47\E:\
- :tc=c100rv4p:
-cR|c100|c100rv4p|c100 w/4 pages:\
- :ti=\EU\Ev 8p\Ep\r:te=\Ev ~p\Ep\r\n:tc=c100rv:
-# Some tty drivers use cr3 for concept, others use nl3, hence dN/dC below.
-cd|c100|c100rvs|slow reverse concept 100:\
- :vb=\EK\200\Ek:pt:dC@:dN@:tc=c100rv:
-cn|c100|c100rv4pna|c100 with no arrows:ks@:ke@:tc=c100rv4p:
-cr|c100|c100rv|c100 rev video:\
- :is=\EU\Ef\E7\E5\E8\El\ENH\Ek\E\200\Eo&\200\Eo\47\E:vs@:ve@:\
- :vb=\EK\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ek:\
- :tc=concept:
-cs|c100|c100s|slowconcept|slowconcept100|slow concept 100:\
- :vb=\Ek\200\EK:pt:dC@:dN@:tc=concept:
-# vt100 and vt132 are still untested
-# Note that all of these claim to be "vt100", so the first one wins.
-dG|gigi|GIGI|dec gigi (naively treated as a straight vt100):\
- :tc=vt100n:
-dR|vt125|dec vt125 (naively treated as a straight vt100; R for ReGIS):\
- :tc=vt100n:
-kA|h19A|heathA|h19A|heathkitA|heathkit h19 ansi mode:\
- :al=1*\E[1L:am:bs:cd=\E[J:ce=\E[K:cl=\E[2J:cm=\E[%i%2;%2H:co#80:\
- :dc=\E[1P:dl=1*\E[1M:dn=\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|h19bs|heathkit w/keypad shifted:ks=\Et:ke=\Eu:tc=h19b:
-kU|h19us|heathkit w/keypad shifted/underscore cursor:ks=\Et:ke=\Eu:tc=h19u:
-kb|h19|heath|h19b|heathkit|heath-19|z19|zenith|heathkit h19:\
- :al=1*\EL:am: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:\
- :k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:\
- :l6=blue:l7=red:l8=white:k6=\EP:k7=\EQ:k8=\ER:
-ke|e19|winston edmond special:vb=\Eg\Eh:tc=h19:
-ku|h19u|heathkit with underscore cursor:vs@:ve@:tc=h19b:
-Ma|aa|annarbor|ann arbor:\
- :cm=^O%r%B%.%>^S^L%+@:co#80:li#40:bs:cl=2^L:up=^N:nd=^_:ho=^K:am:\
- :kb=^^:kd=^J:ku=^N:kl=^H:kr=^_:kh=^K:ma=^_ ^N^P:
-# 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.
-# 1620 uses all 132 columns, 1640 sets left margin to 8 and uses snazzy
-# binary tabset file. Both should work on both terminals.
-A6|1620|450|diablo 1620:\
- :if=/usr/lib/tabset/std:\
- :kb=^H:bs:co#132:ff=^L:hc:hu=\EU:hd=\ED:os:pt:up=\E\n:
-A7|1640|diablo 1640:\
- :co#124:if=/usr/lib/tabset/diablo:tc=1620:
-Ad|dtc300s|300|300s|gsi|dtc|dtc 300s:\
- :if=/usr/lib/tabset/std:\
- :kb=^h:bs:co#132:ff=^L:hc:hu=\EH:hd=\Eh:os:pt:up=^Z:
-Ag|gsi:bs:co#132:hc:hd=\Eh:hu=\EH:os:pt:up=^Z:
-Aj|aj830|aj832|aj|anderson jacobson:\
- :bs:hc:hd=\E9:hu=\E8:os:pl:up=\E7:
-Aq|qume5|qume|Qume Sprint 5:\
- :if=/usr/lib/tabset/std:\
- :kb=^h:bs:co#80:ff=^L:hc:hu=\EH:hd=\Eh:os:pt:up=^Z:
-Ax|x1720|xerox 1720:co#132:bs:ff=^L:hc:os:pt:if=/usr/lib/tabset/xerox1720
-Ca|cdc456|cdc:\
- :li#24:co#80:cl=^Y^X:nd=^L:up=^Z:bs:\
- :cm=\E1%+ %+ :ho=^Y:al=\E\114:dl=\E\112:ce=^V:cd=^X:am:
-Cc|cdc456tst:\
- :li#24:co#80:cl=^y^x:bs:cm=\E1%+ %+ :am:
-D0|dm1520|1520|datamedia 1520:\
- :am: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:
-D1|dm1521|1521|datamedia 1521:\
- :am: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:\
- :al=15^P\n^X^]^X^]:bs:ce=^W:cl=^^^^\177:cm=^L%r%n%.%.:co#80:\
- :dc=10*\b:dl=10*^P^Z^X^]:dm=^P:ed=^X^]:ei=10\377\377^X^]:ho=^B:ic10*^\:\
- :im=^P:li#24:nc:nd=^\:pc=\377:so=^N:se=^X^]:up=^Z:
-D3|dm3025|datamedia 3025a:is=\EQ\EU\EV:\
- :al=130\EP\n\EQ: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=\EOA:se=\EO@:up=\EA:
-D4|3045|dm3045|datamedia 3045a:is=\EU\EV:\
- :am: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:
-D5|dt80|dmdt80|dm80|datamedia dt80/1:\
- :is=\E<\E[2J\E[H\E[?1;3;5;6;9l\E[?7;8h:\
- :am:bs:cd=\E[J:co#80:li#24:ce=\E[K:cl=\E[2J\E[H:\
- :cm=%i\E[%d;%dH:ho=\E[H:nd=\E[C:\
- :so=\E[7m:se=\E[m:\
- :up=\E[A:us=\E[4m:ue=\E[m:\
- :vb=\E[?5h\E[?5l:\
- :vs=\E[1;2;3;4q\E[?4l:ve=\E[0q\E?4h:\
- :kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:\
- :sr=\EM:\
- :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:
-D6|dt80132|dmdt80132|datamedia dt80/1 in 132 char mode:\
- :bs:cd=20^[[0J:co#132:ce=20^[[0K:kd=^[[B:kl=^[[D:kr=^[[C:ku=^[[A:\
- :li#24:cm=5^[[%i%d;%dH:cl=50^[[H^[[2J:nd=^[[C:up=5^[[A:
-ED|delta|dd5000|delta data 5000:\
- :am:bs:cl=^NR:cm=^O%D%+9%D%+9:co#80:li#27:ho=^NQ:nc:nd=^Y:\
- :up=^Z:ce=^NU:dc=^NV:ma=^K^J^Z^P^Y :xr:
-# 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:\
- :al=\EE:dl=\EO:f1=\EP:l1=blue:f2=\EQ:l2=red:f3=\ER:l3=green:tc=vt52:
-H3|h1552rv|hazeltine 1552 reverse video:\
- :so=\ES:se=\ET:tc=h1552:
-H5|h1500|hazeltine 1500:\
- :al=40~^Z:am:bs:cd=10~^X:ce=~^O:cl=~^\:cm=~^Q%r%.%.:co#80:\
- :dl=40~^S:do=~^K:hz:li#24:nd=^P:.se=~^_:.so=~^Y:up=~^L:
-H6|h1510|hazeltine 1510:\
- :al=\E^Z:am:bs:cd=\E^X:ce=\E^O:cl=\E^\:cm=\E^Q%r%.%.:co#80:\
- :dl=\E^S:do=\E^K:hz:li#24:nd=^P:.se=\E^_:.so=\E^Y:up=\E^L:
-H8|h1520|hazeltine 1520:\
- :al=~^Z:am: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 because of a clash between upper case and ~'s.
-H7|h2000|hazeltine 2000:\
- :al=6~^z:am:bs:cl=6~^\:cm=~^q%r%.%.:co#74:\
- :dl=6~^s:ho=~^r:li#27:nc:pc=\177:
-# One of these should go in the misc category, IBM and ISC can't
-# both have I. I will wait to see who comes out with more terminals.
-I8|8001|ISC8001:al=\EU:am: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=^@:
-It|intext|ISC modified owl 1200:\
- :al=5.5*\020:am:bc=\037:bs:cd=5.5*\026J:cl=132\014:\
- :cm=\017%+ %+ :co#80:dc=5.5*\022:dl=5.5*\021:\
- :ei=\026\074:im=\026\073:ip=5.5*:in:li#24:nd=\036:up=\034:\
- :ma=^K^P^R^L^L :kl=^H:kd=^J:kr=^L:ku=^K:
-I9|ibm|ibm3101|3101|i3101|IBM 3101-10:\
- :if=/usr/lib/tabset/3101:\
- :am:bs:cl=^[K:li#24:co#80:nd=^[C:up=^[A:cd=^[J:ce=^[I:\
- :kd=\EB:kl=\ED:kr=\EC:ku=\EA:ho=^[H:cm=\EY%+\40%+\40:
-L3|digilog|333|digilog 333:bs:co#80:ce=\030:ho=^n:li#16:nd=^i:up=^o:
-MA|ampex|d80|dialogue|dialogue80|ampex dialogue 80:\
- :am:bs:pt:if=/usr/lib/tabset/stdcrt:cl=\E*:cm=\E=%+ %+ :\
- :al=\EE:bt=\EI:ic=\EQ:im=:ei=:dl=\ER:dc=\EW:\
- :ce=\Et:cd=\Ey:so=\Ej:se=\Ek:li#24:co#80:nd=^L:up=^K:
-MB|aaadb|ann arbor ambassador 48/destructive backspace:\
- :is=\E[48;0;0;48p\E[H\E[J\E[>30h\E[1Q\E[m:bs@:\
- :vs=\E[>30l:ve=\E[>30h:tc=aaa:
-MC|compucolor|compucolorII:\
- :pt:am:cm=%r^C%.%.:bc=^Z:li#32:co#64:\
- :cl=^L:ho=^H:nd=^Y:up=^\:
-MD|d132|datagraphix|datagraphix 132a:\
- :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:
-MS|soroc|Soroc 120:\
- :cd=\EY:ce=\ET:cl=2\E*:ma=^K^P^R^L^L :\
- :kl=^H:ku=^K:kr=^L:kd=^J:tc=adm3a:
-# Needs function keys added. Also can't use 60 line mode because it needs
-# too much nl delay - can fix for nl but not out of vi.
-# The cl delay is sufficient, but a smaller one could do.
-# This entry is merged from Mike O'Brien@Rand and Howard Katseff at
-# Bell Labs, and is untested.
-Mb|aaa|ambas|ambassador|ann arbor ambassador/48 lines:\
- :al=\E[L:am:bs:\
- :cd=\E[0J:ce=\E[0K:cl=400\E[;H\E[0J:cm=\E[%i%d;%dH:co#80:\
- :da:db:dc=\E[4h\E[1Q\E[P\E[4l\E[0Q:dc=\E[P:dl=\E[M:dm=\E[1Q:\
- :ed=\E[0Q:ei=\E[0Q:ho=\E[;H:ic=\E[@:if=/usr/lib/tabset/aa:im=\E[1Q:\
- :is=\E[48;0;0;48p\E[H\E[J\E[1Q\E[m:li#48:mi:\
- :nd=\E[C:nl=\ED:pt:sf=\E[S:sr=\E[T:se=\E[m:so=\E[7m:up=\E[A:
-Md|datapoint|dp3|dp3360|datapoint 3360:\
- :am:bs:cd^_:ce=^^:cl=^]^_:co#82:ho=^]:li#25:nd=^x:up=^z:
-Mg|dg|dg6053|data general 6053:\
- ca:am:bs:cm=^P%r%.%.:cl=^L:ho=^H:nd=^S\
- up=^W:ce=^K:co#80:li#24:
-Mi|cdi|cdi1203:am:bs:hc:os:co#80:cD#200:
-Mk|teletec|tec|Teletec Datascreen:\
- :am:bs:co#80:cl=^l:ho=^^:li#24:nd=^_:up=^k:
-# ^S is an arrow key! Boy is this guy in for a surprise on v7!
-Ml|sol:\
- :am: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:
-Mo|omron|Omron 8025AG:\
- :al=\EL:am: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:bs:cl=^L:co#85:ho=^^:li#45:nd=\030:up=\026:
-Ms|swtp|ct82|southwest technical products ct82:\
- :am:bs: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:
-My|mdl110|cybernex mdl-110:cm=^P%+ %+ :co#80:li#24:am:cl=70^X:bs:\
- :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:\
- :mi:co#80:li#24:ma=^L ^R^L^K^P:ul:\
- :al=1.5*\EE: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:
-T3|33|tty33|tty|model 33 teletype:\
- :co#72:hc:os:
-T4|43|tty43|model 43 teletype:\
- :kb=^h:am:bs:hc:os:co#132:
-T7|37|tty37|model 37 teletype:\
- :bs:hc:hu=\E8:hd=\E9:up=\E7:os:
-# 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!)
-V2|vi200|v200|visual 200 with function keys:\
- :al=\EL:am: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:\
- :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|vi200rvic|visual 200 reverse video using insert char:\
- :ei=\Ej:im=\Ei:ic@:tc=vi200rv:
-# 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|vi200f|visual|visual 200 no function keys:\
- :al=\EL:am: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|vi200rv|visual 200 reverse video:\
- :so=\E4:se=\E3:sr@:vs@:ve@:tc=vi200:
-Vt|vi200ic|visual 200 using insert char:\
- :ei=\Ej:im=\Ei:ic@:tc=vi200:
-Xa|tek4012|4012|tektronix 4012:\
- :is=\E^O:bs:cl=1000\E^L:co#75:ns:li#35:os:
-Xb|tek4013|4013|tektronix 4013:\
- :as=\E^N:ae=\E^O: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|tek4014sm|4014sm|tektronix 4014 in small font:\
- :is=\E^O\E\072:co#121:li#58:tc=tek4014:
-Xf|tek4015sm|4015sm|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|tektronix 4023:\
- :so=^_P:se=^_@:cm=\034%r%+ %+ :nd=\t:bs:cl=4\E^L:co#80:li#24:am:\
- :up=1000UP:
-# 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.
-X5|tek|4025|4027|4024|tek4025|tek4027|tek4024|4025cu|4027cu|tektronix 4024/4025/4027:\
- :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:\
- :ke=^_lea p2\r^_lea p4\r^_lea p6\r^_lea p8\r^_lea f5\r:\
- :am:bs:da:db:pt:li#34:co#80:cl=^_era\r\n\n:up=^K:nd=^_rig\r:\
- :al=145^_up\r^_ili\r:dl=^_dli\r:\
- :dc=^_dch\r:im=^_ich\r:ei=^F\n^K:nl=^F\n:\
- :ce=^_dch 80\r:cd=^_dli 50\r:CC=^_:
-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:
-Xe|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:
-# Regent: lowest common denominator, works on all regents.
-a0|regent|adds regent series:\
- :am:bs:cl=^L:cm=^K%+ ^P%B%.:co#80:ho=^A:li#24:ll=^A^Z:nd=^F:up=^Z:
-# 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:\
- :cm=^K%+ ^P%B%.:k1=^B1\r:k2=^B2\r:k3=^B3\r:k4=^B4\r:\
- :k5=^B5\r:k6=^B6\r:k7=^B7\r:k8=^B8\r:\
- :kh=^A:kl=^U:kr=^F:ku=^Z:kd=^J:tc=regent:
-# Regent 20, untested
-a2|regent20|adds regent 20:\
- :cd=\Ek:ce=\EK:cm=\EY%+ %+ :tc=regent:
-a3|regent25|adds regent 25:\
- :k0=^B0\r:k1=^B1\r:k2=^B2\r:k3=^B3\r:k4=^B4\r:\
- :k5=^B5\r:k6=^B6\r:k7=^B7\r:k8=^B8\r:k9=^B9\r:\
- :kh=^A:kl=^U:kr=^F:ku=^Z:kd=^J:tc=regent20:
-# Regent 40: untested
-a4|regent40|adds regent 40:\
- :al=\EM:dl=\El:is=\EB:se=\E0@:so=\EOP:ue=\EO@:us=\E0`:vb=\ED\Ed:\
- :tc=regent25:
-# If you have standout problem with regent 200, try so=\ER\EOP:se=\E0@\EV:
-a6|regent60|regent200|adds Regent 60:\
- :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:\
- :al=13\E^N:am: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:
-b2|sb2|sb3|fixed superbee:xb@:tc=superbee:
-bh|bh3m|beehiveIIIm:if=/usr/lib/tabset/beehive:\
- :al=160^S:am:bs:cd=^R:ce=^P:cl=^E^R:co#80:dl=300^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:\
- :am: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:if=/usr/lib/tabset/stdcrt:is=\EE:\
- :am: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_0:\
- :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:
-d2|gt42|dec gt42:\
- :bs:co#72:ns:li#40:os:
-d4|gt40|dec gt40:\
- :bs:co#72:ns:li#30:os:
-d5|vt50|dec vt50:\
- :bs:cd=\EJ:ce=\EK:cl=\EH\EJ:co#80:li#12:nd=\EC:pt:up=\EA:
-dI|dw1|decwriter I:\
- :bs:co#72:hc:os:
-dh|vt50h|dec vt50h:\
- :bs:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :co#80:li#12:nd=\EC:\
- :pt:sr=\EI:up=\EA:
-#
-# ds|vt100s|vt-100s|pt100s|pt-100s|dec vt100 132 cols 14 lines:\
-# :li#14:tc=vt100w:
-#
-dt|vt100w|vt-100w|pt100w|pt-100w|dec vt100 132 cols:\
- :co#128:li#24:is=\E>\E[?3h\E[?4l\E[?5l\E[?7h\E[?8h:tc=vt100:
-dv|vt52|dec vt52:\
- :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:
-dw|dw2|dw3|dw4|decwriter II:\
- :kb=^h:bs:co#132:hc:os:
-e1|ep48|ep4080|execuport 4080:am:bs:os:co#80:hu=\036:hd=\034:
-e2|ep40|ep4000|execuport 4000:am:bs:os:co#136:hu=\036:hd=\034:
-g2|1200|tn1200|terminet 1200:\
- :co#120:hc:os:
-g3|300|tn300|terminet 300:\
- :co#120:hc:os:
-# Note: no "ho" on HP's since that homes to top of memory, not screen.
-# Due to severe 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
-# 2621nl or 2621wl labels to the front using reorder.
-# 2621k45: untested
-h2|2621|hp2621|hp2621a|hp2621p|2621|2621a|2621p|hp 2621:\
- :is=\E&j@\r\E3\r:bt=\Ei:cm=\E&a%r%dc%dY:dc=2\EP:ip=2:\
- :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:
-h3|2621k45|hp2621k45|k45|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:
-h4|hp|hp2645|2645|hp 264x series:\
- :if=/usr/lib/tabset/stdcrt:\
- :al=\EL:am: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:ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\Eh:ks=\E&s1A:ke=\E&s0A:\
- :li#24:mi:ml=\El:mu=\Em:nd=\EC:pt:se=\E&d@:so=\E&dJ:\
- :us=\E&dD:ue=\E&d@:up=\EA:xs:
-h6|hp2626|hp2626a|hp2626p|2626|2626a|2626p|hp 2626:\
- :is=\E&j@\r\E3\r:if=/usr/lib/tabset/stdcrt:\
- :al=\EL:am:bs:bt=\Ei:cd=\EJ:ce=\EK:cl=\EH\EJ:\
- :cm=\E&a%r%dc%dY:co#80:da:db:dc=2\EP:dl=\EM:ei=\ER:\
- :im=\EQ:ip=2:li#24:mi:nd=\EC:pt:se=\E&d@:so=\E&dB:up=\EA:\
- :kh=\Eh:ku=\EA:kl=\ED:kr=\EC:kd=\EB:\
- :ma=j^Jk^P^K^Pl :sf=\ES:\
- :ta=2^I:xs:
-# cD a pain - only screw up at 9600 baud.
-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:is=130\Eg:tc=2645:
-# 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.
-hb|big2621|48 line 2621:li#48:ho=\EH:cm=\E&a%r%dc%dR:tc=2621:
-hn|2621nl|hp2621nl|2621|hp 2621 with no labels:ks@:ke@:kh@:ku@:kl@:kr@:kd@:tc=hp2621:
-hw|2621wl|hp2621wl|2621|hp 2621 with labels:is=\E&jA\r\E3\r:ke=\E&jA:tc=hp2621:
-# 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):\
- :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:bs:\
- :so=\Eb:se=\Ea:
-i4|i400|400|infoton 400:\
- :if=/usr/lib/tabset/infoton_tabs:\
- :al=\E[L:am: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:\
- :li#24:co#80:cl=^L:ho=^H:nd=^Y:cd=^K:\
- :up=^\:am:bc=^Z:cm=\037%+\377%+\377:ll=^H^\:
-ik|infotonKAS:\
- :am:bc=^Z:cd=^K:cl=^L:co#80:li#24:nd=^Y:up=^\:ll=^H^\:
-l1|adm31|31|lsi adm31:is=\Eu\E0:\
- :al=\EE:am:bs:ce=\ET:cm=\E=%+ %+ :cl=\E*:co#80:dc=\EW:dl=\ER:\
- :ei=\Er:ho=^^:im=\Eq:li#24:mi:nd=^L:se=\EG0:so=\EG4:up=^K:\
- :kl=^H:kd=^J:ku=^K:kr=^L:ma=^K^P^L :
-l2|adm2|lsi adm2:\
- :al=\EE:am: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:
-l3|adm3|3|lsi adm3:\
- :am:bs:cl=^Z:li#24:ma=^K^P:co#80:
-l4|adm42|42|lsi adm42:vs=\EC\E3 \E3(:\
- :al=270\EE:am: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:ta=\t:up=^k:\
- :ma=^K^P:pc=\177:
-la|adm3a|3a|lsi adm3a:\
- :am:bs:cm=\E=%+ %+ :cl=1^Z:co#80:ho=^^:li#24:ma=^K^P:nd=^L:up=^K:
-lb|adm3a+|3a+:kl=^H:kd=^J:ku=^K:kr=^L:tc=adm3a:
-# 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: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.
-m5|microterm5|act5|microterm act v:\
- :uc=\EA:pt:ta=2^I:sr=3\EH:ku=^Z:kd=^K:kl=^H:kr=^X:ma=^Z^P^Xl^Kj:tc=act4:
-# 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, and should be put back in someday.
-mf|mimefb|full bright mime1:so=^Y:se=^S:uc@:is=^S\E:tc=mime:
-mh|mimehb|half bright mime1:so=^S:se=^Y:uc@:is=^Y\E:tc=mime:
-mm|mime|mime1|mime2|mimei|mimeii|microterm mime1:\
- :al=80^A:am: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:\
- :ma=^X ^K^J^Z^P:ku=^Z:kd=^K:kl=^H:kr=^X:sr=3^R:
-# These termcaps (for mime 2a) put the terminal in low intensity mode
-# since high intensity mode is so obnoxious.
-ms|mime2as|microterm mime2a (emulating an enhanced soroc iq120):\
- :al=20*^A:am: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|mime2av|microterm mime2a (emulating an enhanced vt52):\
- :al=20*^A:bs:cd=20*\EQ:co#80:ce=\EP:cl=\EL:cm=\EY%+ %+ :is=^Y\
- :dc=^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|mime3ax|mime1 emulating enhanced 3a:\
- :al=80^A:dl=80^W:pt:ce=^X:cd=^_:tc=mime3a:
-n2|spin|nec spinwriter 5525|spinwriter:\
- :bs:co#136:hc:hd=\EU:hu=\ED:os:pt:so=\EA:se=\EB:\
- :if=/usr/lib/tabset/spinwriter:
-pf|fox|perkin elmer 1100:if=/usr/lib/tabset/stdcrt:\
- :am: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:if=/usr/lib/tabset/stdcrt:\
- :al=5.5*\EL:am: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:
-#
-# qB|bc|bill croft homebrew:\
-# :am:bs:cm=\E=%+ %+ :cl=^Z:co#96:ho=^^:li#72:\
-# :nd=^L:up=^K:vb=:
-#
-#NOTE: bg can scroll, it just would rather not (ns) - rwells 3/13/81.
-qB|bg|bg2.0|bgn|BBN BitGraph Terminal (no init):\
- :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:cs=\E[%i%d;%dr:dl=2*\E[M:\
- :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
- :kd=\E[B:ke=\E>:kl=\E[D:kr=\E[C:ks=\E=:ku=\E[A:\
- :l1=PF1:l2=PF2:l3=PF3:l4=PF4:\
- :li#64:nd=\E[C:ns:pt:se=\E[0m:so=\E[7m:up=\E[A:\
- :sc=\E7:rc=\E8:xn:
-qB|bg|bg2.0nv|bgnv:BBN BitGraph Terminal (normal video):\
- :is=\E>\E[?5l\E[?7h:\
- :if=/usr/lib/tabset/vt100:tc=bgn:
-qB|bg|bg2.0rv|bgrv:BBN BitGraph Terminal (reverse video):\
- :is=\E>\E[?5h\E[?7h:\
- :if=/usr/lib/tabset/vt100:tc=bgn:
-qB|bg|bg1.25|BBN BitGraph terminal:\
- :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:\
- :is=\E<:\
- :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
- :kd=\E[B:ke=\E>:kl=\E[D:kr=\E[C:ks=\E=:ku=\E[A:\
- :l1=PF1:l2=PF2:l3=PF3:l4=PF4:\
- :li#64:nd=\E[C:ns:pt:se=\E[0m:so=\E[7m:up=\E[A:
-qB|bg|bg1.25nv|:BBN BitGraph Terminal (normal video):\
- :is=\E<\E>\E[?5l\E[?7h:tc=bg1.25:
-qB|bg|bg1.25rv|:BBN BitGraph Terminal (reverse video):\
- :is=\E<\E>\E[?5h\E[?7h:tc=bg1.25:
-qN|nucterm|rayterm|NUC homebrew:\
- :am:bs:cl=1^L:li#24:co#80:nd=^C:up=^N:ho=^B:ll=^K:ce=^A:cd=^E:
-qb|ex3000:\
- :li#24:co#80:ho=^Q:
-qc|carlock|klc:\
- :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:\
- :al=^P^J^X:am: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:\
- :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:\
- :li#24:co#64:cl=^l:ho=^q:nd=^s:up=^w:bs:bc=^a:ma=^x^J:kd=^S:
-qu|ubell|ubellchar:if=/usr/staff/michael/term/startup:\
- :am: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:\
- :co#80:li#12:bc=^Y:do=^K:up=^Z:cl=^^:ce=^_:am:ho=^]:nd=^X:
-qx|xitex|xitex sct-100:\
- :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:
-t3|ti|ti700|ti733|735|ti735|ti silent 700:\
- :bs:co#80:hc:os:dC#162:
-t4|ti745|745|743|ti silent 745:\
- :bs:co#80:hc:os:
-# 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:if=/usr/lib/tabset/stdcrt:\
- :al=33*\EE:am:bs: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=^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:\
- :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:
-v2|912b|912c|920b|920c|tvi|new televideo:\
- :al=5*\EE:dl=5*\ER:tc=912:
-# 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:\
- :bs:cl=^L:co#80:li#24:
-y3|t3800|teleray 3800 series: \
- :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|t10|teleray|teleray 1061:if=/usr/lib/tabset/teleray:\
- :al=2*\EL:am: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:
-yf|t1061f|teleray 1061 with fast PROMs:\
- al=\EL:ip@:dl=\EM:tc=t1061:
-rv|vidtx|Radio Shack VIDEOTEX:\
- :cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :co#32:li#16:nd=\EC:up=\EA:
-ae|apple2e|Apple ][e with 80 column card:\
- :am: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:
-#
-# ----
-# Convention: First entry is two chars, first char is manufacturer,
-# second char is canonical abbreviation for model or mode.
-# Second entry is canonical abbreviation.
-# Third entry is the one the editor will print with "set" command.
-# Last entry is verbose description.
-# Others are mnemonic synonyms for the terminal.
-#
-# 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.
-#
-# Special manufacturer codes:
-# M: Misc. (with only a few terminals)
-# q: Homemade
-# s: special (dialup, etc.)
-#
-# This file is to be installed with an editor script 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.
diff --git a/etc/yow.lines b/etc/yow.lines
deleted file mode 100644
index 5e3b56ab1d1..00000000000
--- a/etc/yow.lines
+++ /dev/null
Binary files differ
diff --git a/lib-src/=aixcc.lex b/lib-src/=aixcc.lex
deleted file mode 100644
index b7b44701b18..00000000000
--- a/lib-src/=aixcc.lex
+++ /dev/null
@@ -1,301 +0,0 @@
-%Start ErrorText ErrorMessage OtherText
-
-EC [0-9][0-9][0-9][0-9]-[0-9][0-9][0-9]
-D [0-9]
-D3 [0-9 ][0-9 ][0-9]
-D4 [0-9 ][0-9 ][0-9 ][0-9]
-D5 [0-9 ][0-9 ][0-9 ][0-9 ][0-9]
-DS [0-9 ]
-
-%{
-/* moore@wilma.cs.utk.edu
-
- * Hack to work around the AIX C compiler's brain-damaged error messages
- * so that emacs can parse them. It runs /bin/cc as a subprocess, and
- * tries to rearrange the error messages so that (a) each message contains
- * both the filename and line number where the error occurred, and (b)
- * the error message(s) for a particular line get displayed *before* the
- * line itself.
- *
- * to compile:
- * lex aixcc.lex
- * cc -o aixcc lex.yy.c
- *
- *
- * Copyright December 1991 by Keith Moore
- *
- * 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 2 of the License, 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.
- *
- *
- * TODO: figure out how the compiler counts file numbers for included
- * files, keep track of which file corresponds to which number, and
- * always output the right file name.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-char *current_file;
-int line;
-int debug = 0;
-char bigbuf[10240];
-char *bufptr = bigbuf;
-int last_line_was_error = 0;
-
-spaces (s)
-char *s;
-{
- while (*s++)
- *bufptr++ = ' ';
-}
-
-char *
-strsave (s)
-char *s;
-{
- char *ptr = malloc (strlen (s) + 1);
- strcpy (ptr, s);
- return ptr;
-}
-
-yywrap ()
-{
- *bufptr = '\0';
- bufptr = bigbuf;
- while (*bufptr)
- putc (*bufptr++, yyout);
- return 1;
-}
-
-%}
-%%
-^File\ Line\ Column\ Message\ text[^\n]* {
- /*
- * ignore this. don't treat it as error text
- */
-}
-
-^{DS}{DS}{DS}\ {D5}\ \| {
- /*
- * (optional) nesting level, followed by line number, followed
- * by the source code fragment that caused the error
- */
-
- /*
- * save the line number for later
- */
- line = atoi (yytext+4);
-
- if (debug) {
- fprintf (yyout, "line <= %d\n", line);
- fprintf (yyout, "%s\n", yytext);
- }
-
- /*
- * if the last line was an error message, to flush out all of
- * the old source text before starting to save the new source text.
- */
- if (last_line_was_error) {
- *bufptr = '\0';
- bufptr = bigbuf;
- while (*bufptr)
- putc (*bufptr++, yyout);
- bufptr = bigbuf;
- last_line_was_error = 0;
- }
- /*
- * stuff enough spaces in the text buffer so that the
- * saved text will line up properly when displayed.
- */
- spaces (yytext);
-
- BEGIN ErrorText; /* continue below */
-}
-
-<ErrorText>[^\n]*$ {
- char *ptr;
-
- /*
- * Save the text until we see the error message(s), then print it.
- * This because emacs puts the error message at the top of the
- * window, and it's nice to be able to see the text below it.
- */
-
- ptr = yytext;
- while (*ptr)
- *bufptr++ = *ptr++;
- *bufptr++ = '\n';
-
- BEGIN 0;
-}
-
-^Processing\ include\ file\ .*$ {
- /*
- * name of a new include file being processed. Increment file number
- * and remember the file name corresponding to this file number.
- */
-
- current_file = strsave (yytext+24);
-
- if (debug) {
- fprintf (yyout, "current_file <= %s\n", current_file);
- fprintf (yyout, "%s\n", yytext);
- }
-}
-
-^([a-z]\ -)?\ *{EC}: {
- /*
- * error message (which we print immediately) preceded by an
- * error code (which we ignore)
- */
-
- fprintf (yyout, "\"%s\", line %d: %c -", current_file, line, *yytext);
- last_line_was_error = 1;
- BEGIN ErrorMessage;
-}
-
-^{D3}\ {D5}\ {D4}\ {EC}: {
- /*
- * (optional) nesting level, followed by line number, followed
- * by column number, followed by error message text.
- */
-
- /*
- * save the line number for later
- */
- line = atoi (yytext+4);
-
- if (debug) {
- fprintf (yyout, "line <= %d\n", line);
- fprintf (yyout, "%s\n", yytext);
- }
-
- /*
- * if the last line was an error message, flush out all of
- * the old source text before printing this error message.
- */
- if (last_line_was_error) {
- *bufptr = '\0';
- bufptr = bigbuf;
- while (*bufptr)
- putc (*bufptr++, yyout);
- bufptr = bigbuf;
- last_line_was_error = 0;
- }
- fprintf (yyout, "\"%s\", line %d:", current_file, line);
- last_line_was_error = 1;
- BEGIN ErrorMessage;
-}
-
-<ErrorMessage>[^\n]*$ {
- fprintf (yyout, "%s\n", yytext);
- BEGIN 0;
-}
-
-
-^[^ :]+".c:"\ *$ {
- /* name of new source file being processed */
-
- char *ptr;
-
- if (current_file)
- free (current_file);
- ptr = strchr (yytext, ':');
- *ptr = '\0';
- current_file = strsave (yytext);
-}
-
-^[^\n] {
- /*
- * other text starting with a newline. We have to break it up this
- * way to keep this rule from matching any of the above patterns
- */
-
- if (last_line_was_error) {
- *bufptr = '\0';
- bufptr = bigbuf;
- while (*bufptr)
- putc (*bufptr++, yyout);
- bufptr = bigbuf;
- last_line_was_error = 0;
- }
-
- *bufptr++ = *yytext;
- BEGIN OtherText;
-}
-
-<OtherText>[^\n]*$ {
- char *ptr;
-
- ptr = yytext;
- while (*ptr)
- *bufptr++ = *ptr++;
- *bufptr++ = '\n';
-
- BEGIN 0;
-}
-
-\n ;
-
-%%
-
-main (argc, argv)
-char **argv;
-{
- int pfd[2];
- int child_pid;
- int i;
-
- current_file = strsave ("/dev/null");
-
- line = 0;
-
- for (i = 1; i < argc; ++i) {
- char *ptr = strrchr (argv[i], '.');
- if (ptr && ptr[1] == 'c' && ptr[2] == '\0') {
- current_file = strsave (argv[i]);
- break;
- }
- }
-
- if (pipe (pfd) < 0) {
- perror ("pipe");
- exit (1);
- }
- if ((child_pid = fork()) > 0) {
- int status;
-
- close (pfd[1]);
- yyin = fdopen (pfd[0], "r");
- yyout = stderr;
- yylex();
-
- wait (&status);
- exit ((status >> 8) & 0xff);
- }
- else if (child_pid == 0) {
- dup2 (pfd[1], 2);
- close (pfd[0]);
- close (pfd[1]);
- argv[0] = "cc";
- execv ("/bin/cc", argv);
- perror ("/bin/cc");
- exit (1);
- }
- else {
- perror ("fork");
- exit (1);
- }
-}
diff --git a/lib-src/=etags-vmslib.c b/lib-src/=etags-vmslib.c
deleted file mode 100644
index cddb68085f8..00000000000
--- a/lib-src/=etags-vmslib.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/* File name wild card expansion for VMS.
- This file is part of the etags program.
- 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 2, 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. */
-
-#include <stdio.h>
-typedef char tbool;
-
-/* This is a BUG! ANY arbitrary limit is a BUG!
- Won't someone please fix this? */
-#define MAX_FILE_SPEC_LEN 255
-typedef struct {
- short curlen;
- char body[MAX_FILE_SPEC_LEN + 1];
-} vspec;
-#define EOS '\0'
-#define NO 0
-#define YES 1
-#define NULL 0
-
-/* gfnames - return in successive calls the
- name of each file specified by all the remaining args in the command-line
- expanding wild cards and
- stepping over arguments when they have been processed completely
-*/
-char*
-gfnames(pac, pav, p_error)
- int *pac;
- char **pav[];
- tbool *p_error;
-{
- static vspec filename = {MAX_FILE_SPEC_LEN, "\0"};
- short fn_exp();
-
- while (1)
- if (*pac == 0)
- {
- *p_error = NO;
- return(NULL);
- }
- else switch(fn_exp(&filename, **pav))
- {
- case 1:
- *p_error = NO;
- return(filename.body);
- break;
- case 0:
- --*pac;
- ++*pav;
- break;
- default:
- *p_error = YES;
- return(filename.body);
- break;
- }
-
-}
-
-/* fn_exp - expand specification of list of file names
- returning in each successive call the next filename matching the input
- spec. The function expects that each in_spec passed
- to it will be processed to completion; in particular, up to and
- including the call following that in which the last matching name
- is returned, the function ignores the value of in_spec, and will
- only start processing a new spec with the following call.
- If an error occurs, on return out_spec contains the value
- of in_spec when the error occurred.
-
- With each successive filename returned in out_spec, the
- function's return value is one. When there are no more matching
- names the function returns zero. If on the first call no file
- matches in_spec, or there is any other error, -1 is returned.
-*/
-
-#include <rmsdef.h>
-#include <descrip.h>
-#define OUTSIZE MAX_FILE_SPEC_LEN
-short
-fn_exp(out, in)
- vspec *out;
- char *in;
-{
- static long context = 0;
- static struct dsc$descriptor_s o;
- static struct dsc$descriptor_s i;
- static tbool pass1 = YES;
- long status;
- short retval;
-
- if (pass1)
- {
- pass1 = NO;
- o.dsc$a_pointer = (char *) out;
- o.dsc$w_length = (short)OUTSIZE;
- i.dsc$a_pointer = in;
- i.dsc$w_length = (short)strlen(in);
- i.dsc$b_dtype = DSC$K_DTYPE_T;
- i.dsc$b_class = DSC$K_CLASS_S;
- o.dsc$b_dtype = DSC$K_DTYPE_VT;
- o.dsc$b_class = DSC$K_CLASS_VS;
- }
- if ( (status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL)
- {
- out->body[out->curlen] = EOS;
- return(1);
- }
- else if (status == RMS$_NMF)
- retval = 0;
- else
- {
- strcpy(out->body, in);
- retval = -1;
- }
- lib$find_file_end(&context);
- pass1 = YES;
- return(retval);
-}
-
-#ifndef OLD /* Newer versions of VMS do provide `system'. */
-system(cmd)
- char *cmd;
-{
- fprintf(stderr, "system() function not implemented under VMS\n");
-}
-#endif
-
-#define VERSION_DELIM ';'
-char *massage_name(s)
- char *s;
-{
- char *start = s;
-
- for ( ; *s; s++)
- if (*s == VERSION_DELIM)
- {
- *s = EOS;
- break;
- }
- else
- *s = tolower(*s);
- return(start);
-}
diff --git a/lib-src/=rcs2log b/lib-src/=rcs2log
deleted file mode 100644
index 44a12bd3da8..00000000000
--- a/lib-src/=rcs2log
+++ /dev/null
@@ -1,612 +0,0 @@
-#! /bin/sh
-
-# RCS to ChangeLog generator
-
-# Generate a change log prefix from RCS files and the ChangeLog (if any).
-# Output the new prefix to standard output.
-# You can edit this prefix by hand, and then prepend it to ChangeLog.
-
-# Ignore log entries that start with `#'.
-# Clump together log entries that start with `{topic} ',
-# where `topic' contains neither white space nor `}'.
-
-# Author: Paul Eggert <eggert@twinsun.com>
-
-# $Id: rcs2log,v 1.34 1996/10/13 05:59:42 eggert Exp eggert $
-
-# Copyright 1992, 1993, 1994, 1995, 1996 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 2, 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, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-tab=' '
-nl='
-'
-
-# Parse options.
-
-# defaults
-: ${AWK=awk}
-: ${TMPDIR=/tmp}
-changelog=ChangeLog # change log file name
-datearg= # rlog date option
-hostname= # name of local host (if empty, will deduce it later)
-indent=8 # indent of log line
-length=79 # suggested max width of log line
-logins= # login names for people we know fullnames and mailaddrs of
-loginFullnameMailaddrs= # login<tab>fullname<tab>mailaddr triplets
-logTZ= # time zone for log dates (if empty, use local time)
-recursive= # t if we want recursive rlog
-revision= # t if we want revision numbers
-rlog_options= # options to pass to rlog
-tabwidth=8 # width of horizontal tab
-
-while :
-do
- case $1 in
- -c) changelog=${2?}; shift;;
- -i) indent=${2?}; shift;;
- -h) hostname=${2?}; shift;;
- -l) length=${2?}; shift;;
- -[nu]) # -n is obsolescent; it is replaced by -u.
- case $1 in
- -n) case ${2?}${3?}${4?} in
- *"$tab"* | *"$nl"*)
- echo >&2 "$0: -n '$2' '$3' '$4': tabs, newlines not allowed"
- exit 1
- esac
- loginFullnameMailaddrs=$loginFullnameMailaddrs$nl$2$tab$3$tab$4
- shift; shift; shift;;
- -u)
- # If $2 is not tab-separated, use colon for separator.
- case ${2?} in
- *"$nl"*)
- echo >&2 "$0: -u '$2': newlines not allowed"
- exit 1;;
- *"$tab"*)
- t=$tab;;
- *)
- t=:
- esac
- case $2 in
- *"$t"*"$t"*"$t"*)
- echo >&2 "$0: -u '$2': too many fields"
- exit 1;;
- *"$t"*"$t"*)
- ;;
- *)
- echo >&2 "$0: -u '$2': not enough fields"
- exit 1
- esac
- loginFullnameMailaddrs=$loginFullnameMailaddrs$nl$2
- shift
- esac
- logins=$logins$nl$login
- ;;
- -r) rlog_options=$rlog_options$nl${2?}; shift;;
- -R) recursive=t;;
- -t) tabwidth=${2?}; shift;;
- -v) revision=t;;
- -*) echo >&2 "$0: usage: $0 [options] [file ...]
-Options:
- [-c changelog] [-h hostname] [-i indent] [-l length] [-R]
- [-r rlog_option] [-t tabwidth] [-v]
- [-u 'login<TAB>fullname<TAB>mailaddr']..."
- exit 1;;
- *) break
- esac
- shift
-done
-
-month_data='
- m[0]="Jan"; m[1]="Feb"; m[2]="Mar"
- m[3]="Apr"; m[4]="May"; m[5]="Jun"
- m[6]="Jul"; m[7]="Aug"; m[8]="Sep"
- m[9]="Oct"; m[10]="Nov"; m[11]="Dec"
-'
-
-
-# Put rlog output into $rlogout.
-
-# If no rlog options are given,
-# log the revisions checked in since the first ChangeLog entry.
-# Since ChangeLog is only by date, some of these revisions may be duplicates of
-# what's already in ChangeLog; it's the user's responsibility to remove them.
-case $rlog_options in
-'')
- if test -s "$changelog"
- then
- e='
- /^[0-9]+-[0-9][0-9]-[0-9][0-9]/{
- # ISO 8601 date
- print $1
- exit
- }
- /^... ... [ 0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]+ /{
- # old-fashioned date and time (Emacs 19.31 and earlier)
- '"$month_data"'
- year = $5
- for (i=0; i<=11; i++) if (m[i] == $2) break
- dd = $3
- printf "%d-%02d-%02d\n", year, i+1, dd
- exit
- }
- '
- d=`$AWK "$e" <"$changelog"` || exit
- case $d in
- ?*) datearg="-d>$d"
- esac
- fi
-esac
-
-# Use TZ specified by ChangeLog local variable, if any.
-if test -s "$changelog"
-then
- extractTZ='
- /^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*"\([^"]*\)".*/{
- s//\1/; p; q
- }
- /^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*t.*/{
- s//UTC0/; p; q
- }
- '
- logTZ=`tail "$changelog" | sed -n "$extractTZ"`
- case $logTZ in
- ?*) TZ=$logTZ; export TZ
- esac
-fi
-
-# If CVS is in use, examine its repository, not the normal RCS files.
-if test ! -f CVS/Repository
-then
- rlog=rlog
- repository=
-else
- rlog='cvs log'
- repository=`sed 1q <CVS/Repository` || exit
- test ! -f CVS/Root || CVSROOT=`cat <CVS/Root` || exit
- case $CVSROOT in
- *:/*)
- # remote repository
- ;;
- *)
- # local repository
- case $repository in
- /*) ;;
- *) repository=${CVSROOT?}/$repository
- esac
- if test ! -d "$repository"
- then
- echo >&2 "$0: $repository: bad repository (see CVS/Repository)"
- exit 1
- fi
- esac
-fi
-
-# Use $rlog's -zLT option, if $rlog supports it.
-case `$rlog -zLT 2>&1` in
-*' option'*) ;;
-*) rlog_options=-zLT$nl$rlog_options
-esac
-
-# With no arguments, examine all files under the RCS directory.
-case $# in
-0)
- case $repository in
- '')
- oldIFS=$IFS
- IFS=$nl
- case $recursive in
- t)
- RCSdirs=`find . -name RCS -type d -print`
- filesFromRCSfiles='s|,v$||; s|/RCS/|/|; s|^\./||'
- files=`
- {
- case $RCSdirs in
- ?*) find $RCSdirs -type f -print
- esac
- find . -name '*,v' -print
- } |
- sort -u |
- sed "$filesFromRCSfiles"
- `;;
- *)
- files=
- for file in RCS/.* RCS/* .*,v *,v
- do
- case $file in
- RCS/. | RCS/..) continue;;
- RCS/.\* | RCS/\* | .\*,v | \*,v) test -f "$file" || continue
- esac
- files=$files$nl$file
- done
- case $files in
- '') exit 0
- esac
- esac
- set x $files
- shift
- IFS=$oldIFS
- esac
-esac
-
-llogout=$TMPDIR/rcs2log$$l
-rlogout=$TMPDIR/rcs2log$$r
-trap exit 1 2 13 15
-trap "rm -f $llogout $rlogout; exit 1" 0
-
-case $datearg in
-?*) $rlog $rlog_options "$datearg" ${1+"$@"} >$rlogout;;
-'') $rlog $rlog_options ${1+"$@"} >$rlogout
-esac || exit
-
-
-# Get the full name of each author the logs mention, and set initialize_fullname
-# to awk code that initializes the `fullname' awk associative array.
-# Warning: foreign authors (i.e. not known in the passwd file) are mishandled;
-# you have to fix the resulting output by hand.
-
-initialize_fullname=
-initialize_mailaddr=
-
-case $loginFullnameMailaddrs in
-?*)
- case $loginFullnameMailaddrs in
- *\"* | *\\*)
- sed 's/["\\]/\\&/g' >$llogout <<EOF || exit
-$loginFullnameMailaddrs
-EOF
- loginFullnameMailaddrs=`cat $llogout`
- esac
-
- oldIFS=$IFS
- IFS=$nl
- for loginFullnameMailaddr in $loginFullnameMailaddrs
- do
- case $loginFullnameMailaddr in
- *"$tab"*) IFS=$tab;;
- *) IFS=:
- esac
- set x $loginFullnameMailaddr
- login=$2
- fullname=$3
- mailaddr=$4
- initialize_fullname="$initialize_fullname
- fullname[\"$login\"] = \"$fullname\""
- initialize_mailaddr="$initialize_mailaddr
- mailaddr[\"$login\"] = \"$mailaddr\""
- done
- IFS=$oldIFS
-esac
-
-case $llogout in
-?*) sort -u -o $llogout <<EOF || exit
-$logins
-EOF
-esac
-output_authors='/^date: / {
- if ($2 ~ /^[0-9]*[-\/][0-9][0-9][-\/][0-9][0-9]$/ && $3 ~ /^[0-9][0-9]:[0-9][0-9]:[0-9][0-9][-+0-9:]*;$/ && $4 == "author:" && $5 ~ /^[^;]*;$/) {
- print substr($5, 1, length($5)-1)
- }
-}'
-authors=`
- $AWK "$output_authors" <$rlogout |
- case $llogout in
- '') sort -u;;
- ?*) sort -u | comm -23 - $llogout
- esac
-`
-case $authors in
-?*)
- cat >$llogout <<EOF || exit
-$authors
-EOF
- initialize_author_script='s/["\\]/\\&/g; s/.*/author[\"&\"] = 1/'
- initialize_author=`sed -e "$initialize_author_script" <$llogout`
- awkscript='
- BEGIN {
- alphabet = "abcdefghijklmnopqrstuvwxyz"
- ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- '"$initialize_author"'
- }
- {
- if (author[$1]) {
- fullname = $5
- if (fullname ~ /[0-9]+-[^(]*\([0-9]+\)$/) {
- # Remove the junk from fullnames like "0000-Admin(0000)".
- fullname = substr(fullname, index(fullname, "-") + 1)
- fullname = substr(fullname, 1, index(fullname, "(") - 1)
- }
- if (fullname ~ /,[^ ]/) {
- # Some sites put comma-separated junk after the fullname.
- # Remove it, but leave "Bill Gates, Jr" alone.
- fullname = substr(fullname, 1, index(fullname, ",") - 1)
- }
- abbr = index(fullname, "&")
- if (abbr) {
- a = substr($1, 1, 1)
- A = a
- i = index(alphabet, a)
- if (i) A = substr(ALPHABET, i, 1)
- fullname = substr(fullname, 1, abbr-1) A substr($1, 2) substr(fullname, abbr+1)
- }
-
- # Quote quotes and backslashes properly in full names.
- # Do not use gsub; traditional awk lacks it.
- quoted = ""
- rest = fullname
- for (;;) {
- p = index(rest, "\\")
- q = index(rest, "\"")
- if (p) {
- if (q && q<p) p = q
- } else {
- if (!q) break
- p = q
- }
- quoted = quoted substr(rest, 1, p-1) "\\" substr(rest, p, 1)
- rest = substr(rest, p+1)
- }
-
- printf "fullname[\"%s\"] = \"%s%s\"\n", $1, quoted, rest
- author[$1] = 0
- }
- }
- '
-
- initialize_fullname=`
- (
- cat /etc/passwd
- for author in $authors
- do nismatch $author passwd.org_dir
- done
- ypmatch $authors passwd
- ) 2>/dev/null |
- $AWK -F: "$awkscript"
- `$initialize_fullname
-esac
-
-
-# Function to print a single log line.
-# We don't use awk functions, to stay compatible with old awk versions.
-# `Log' is the log message (with \n replaced by \r).
-# `files' contains the affected files.
-printlogline='{
-
- # Following the GNU coding standards, rewrite
- # * file: (function): comment
- # to
- # * file (function): comment
- if (Log ~ /^\([^)]*\): /) {
- i = index(Log, ")")
- files = files " " substr(Log, 1, i)
- Log = substr(Log, i+3)
- }
-
- # If "label: comment" is too long, break the line after the ":".
- sep = " "
- if ('"$length"' <= '"$indent"' + 1 + length(files) + index(Log, CR)) sep = "\n" indent_string
-
- # Print the label.
- printf "%s*%s:", indent_string, files
-
- # Print each line of the log, transliterating \r to \n.
- while ((i = index(Log, CR)) != 0) {
- logline = substr(Log, 1, i-1)
- if (logline ~ /[^'"$tab"' ]/) {
- printf "%s%s\n", sep, logline
- } else {
- print ""
- }
- sep = indent_string
- Log = substr(Log, i+1)
- }
-}'
-
-# Pattern to match the `revision' line of rlog output.
-rlog_revision_pattern='^revision [0-9]+\.[0-9]+(\.[0-9]+\.[0-9]+)*(['"$tab"' ]+locked by: [^'"$tab"' $,.0-9:;@]*[^'"$tab"' $,:;@][^'"$tab"' $,.0-9:;@]*;)?['"$tab"' ]*$'
-
-case $hostname in
-'')
- hostname=`(
- hostname || uname -n || uuname -l || cat /etc/whoami
- ) 2>/dev/null` || {
- echo >&2 "$0: cannot deduce hostname"
- exit 1
- }
-
- case $hostname in
- *.*) ;;
- *)
- domainname=`(domainname) 2>/dev/null` &&
- case $domainname in
- *.*) hostname=$hostname.$domainname
- esac
- esac
-esac
-
-
-# Process the rlog output, generating ChangeLog style entries.
-
-# First, reformat the rlog output so that each line contains one log entry.
-# Transliterate \n to \r so that multiline entries fit on a single line.
-# Discard irrelevant rlog output.
-$AWK <$rlogout '
- BEGIN { repository = "'"$repository"'" }
- /^RCS file:/ {
- if (repository != "") {
- filename = $3
- if (substr(filename, 1, length(repository) + 1) == repository "/") {
- filename = substr(filename, length(repository) + 2)
- }
- if (filename ~ /,v$/) {
- filename = substr(filename, 1, length(filename) - 2)
- }
- if (filename ~ /(^|\/)Attic\/[^\/]*$/) {
- i = length(filename)
- while (substr(filename, i, 1) != "/") i--
- filename = substr(filename, 1, i - 6) substr(filename, i + 1)
- }
- }
- rev = "?"
- }
- /^Working file:/ { if (repository == "") filename = $3 }
- /'"$rlog_revision_pattern"'/, /^(-----------*|===========*)$/ {
- if ($0 ~ /'"$rlog_revision_pattern"'/) {
- rev = $2
- next
- }
- if ($0 ~ /^date: [0-9][- +\/0-9:]*;/) {
- date = $2
- if (date ~ /\//) {
- # This is a traditional RCS format date YYYY/MM/DD.
- # Replace "/"s with "-"s to get ISO format.
- newdate = ""
- while ((i = index(date, "/")) != 0) {
- newdate = newdate substr(date, 1, i-1) "-"
- date = substr(date, i+1)
- }
- date = newdate date
- }
- time = substr($3, 1, length($3) - 1)
- author = substr($5, 1, length($5)-1)
- printf "%s %s %s %s %s %c", filename, rev, date, time, author, 13
- rev = "?"
- next
- }
- if ($0 ~ /^branches: /) { next }
- if ($0 ~ /^(-----------*|===========*)$/) { print ""; next }
- printf "%s%c", $0, 13
- }
-' |
-
-# Now each line is of the form
-# FILENAME REVISION YYYY-MM-DD HH:MM:SS[+-TIMEZONE] AUTHOR \rLOG
-# where \r stands for a carriage return,
-# and each line of the log is terminated by \r instead of \n.
-# Sort the log entries, first by date+time (in reverse order),
-# then by author, then by log entry, and finally by file name and revision
-# (just in case).
-sort +2 -4r +4 +0 |
-
-# Finally, reformat the sorted log entries.
-$AWK '
- BEGIN {
- logTZ = "'"$logTZ"'"
- revision = "'"$revision"'"
-
- # Some awk variants do not understand "\r" or "\013", so we have to
- # put a carriage return directly in the file.
- CR=" " # <-- There is a single CR between the " chars here.
-
- # Initialize the fullname and mailaddr associative arrays.
- '"$initialize_fullname"'
- '"$initialize_mailaddr"'
-
- # Initialize indent string.
- indent_string = ""
- i = '"$indent"'
- if (0 < '"$tabwidth"')
- for (; '"$tabwidth"' <= i; i -= '"$tabwidth"')
- indent_string = indent_string "\t"
- while (1 <= i--)
- indent_string = indent_string " "
- }
-
- {
- newlog = substr($0, 1 + index($0, CR))
-
- # Ignore log entries prefixed by "#".
- if (newlog ~ /^#/) { next }
-
- if (Log != newlog || date != $3 || author != $5) {
-
- # The previous log and this log differ.
-
- # Print the old log.
- if (date != "") '"$printlogline"'
-
- # Logs that begin with "{clumpname} " should be grouped together,
- # and the clumpname should be removed.
- # Extract the new clumpname from the log header,
- # and use it to decide whether to output a blank line.
- newclumpname = ""
- sep = "\n"
- if (date == "") sep = ""
- if (newlog ~ /^\{[^'"$tab"' }]*}['"$tab"' ]/) {
- i = index(newlog, "}")
- newclumpname = substr(newlog, 1, i)
- while (substr(newlog, i+1) ~ /^['"$tab"' ]/) i++
- newlog = substr(newlog, i+1)
- if (clumpname == newclumpname) sep = ""
- }
- printf sep
- clumpname = newclumpname
-
- # Get ready for the next log.
- Log = newlog
- if (files != "")
- for (i in filesknown)
- filesknown[i] = 0
- files = ""
- }
- if (date != $3 || author != $5) {
- # The previous date+author and this date+author differ.
- # Print the new one.
- date = $3
- time = $4
- author = $5
-
- zone = ""
- if (logTZ && ((i = index(time, "-")) || (i = index(time, "+"))))
- zone = " " substr(time, i)
-
- # Print "date[ timezone] fullname <email address>".
- # Get fullname and email address from associative arrays;
- # default to author and author@hostname if not in arrays.
- if (fullname[author])
- auth = fullname[author]
- else
- auth = author
- printf "%s%s %s ", date, zone, auth
- if (mailaddr[author])
- printf "<%s>\n\n", mailaddr[author]
- else
- printf "<%s@%s>\n\n", author, "'"$hostname"'"
- }
- if (! filesknown[$1]) {
- filesknown[$1] = 1
- if (files == "") files = " " $1
- else files = files ", " $1
- if (revision && $2 != "?") files = files " " $2
- }
- }
- END {
- # Print the last log.
- if (date != "") {
- '"$printlogline"'
- printf "\n"
- }
- }
-' &&
-
-
-# Exit successfully.
-
-exec rm -f $llogout $rlogout
-
-# Local Variables:
-# tab-width:4
-# End:
diff --git a/lib-src/=timer.c b/lib-src/=timer.c
deleted file mode 100644
index 9bd547ce8f2..00000000000
--- a/lib-src/=timer.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/* timer.c --- daemon to provide a tagged interval timer service
-
- This little daemon runs forever waiting for commands to schedule events.
- SIGALRM causes
- it to check its queue for events attached to the current second; if
- one is found, its label is written to stdout. SIGTERM causes it to
- terminate, printing a list of pending events.
-
- This program is intended to be used with the lisp package called
- timer.el. The first such program was written anonymously in 1990.
- This version was documented and rewritten for portability by
- esr@snark.thyrsus.com, Aug 7 1992. */
-
-#include <stdio.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/types.h> /* time_t */
-
-#include <../src/config.h>
-#undef read
-
-#ifdef LINUX
-/* Perhaps this is correct unconditionally. */
-#undef signal
-#endif
-#ifdef _CX_UX
-/* I agree with the comment above, this probably should be unconditional (it
- * is already unconditional in a couple of other files in this directory),
- * but in the spirit of minimizing the effects of my port, I am making it
- * conditional on _CX_UX.
- */
-#undef signal
-#endif
-
-
-extern int errno;
-extern char *strerror ();
-extern time_t time ();
-
-/*
- * The field separator for input. This character shouldn't occur in dates,
- * and should be printable so event strings are readable by people.
- */
-#define FS '@'
-
-struct event
- {
- char *token;
- time_t reply_at;
- };
-int events_size; /* How many slots have we allocated? */
-int num_events; /* How many are actually scheduled? */
-struct event *events; /* events[0 .. num_events-1] are the
- valid events. */
-
-char *pname; /* program name for error messages */
-
-/* This buffer is used for reading commands.
- We make it longer when necessary, but we never free it. */
-char *buf;
-/* This is the allocated size of buf. */
-int buf_size;
-
-/* Non-zero means don't handle an alarm now;
- instead, just set alarm_deferred if an alarm happens.
- We set this around parts of the program that call malloc and free. */
-int defer_alarms;
-
-/* Non-zero if an alarm came in during the reading of a command. */
-int alarm_deferred;
-
-/* Schedule one event, and arrange an alarm for it.
- STR is a string of two fields separated by FS.
- First field is string for get_date, saying when to wake-up.
- Second field is a token to identify the request. */
-
-void
-schedule (str)
- char *str;
-{
- extern time_t get_date ();
- extern char *strcpy ();
- time_t now;
- register char *p;
- static struct event *ep;
-
- /* check entry format */
- for (p = str; *p && *p != FS; p++)
- continue;
- if (!*p)
- {
- fprintf (stderr, "%s: bad input format: %s\n", pname, str);
- return;
- }
- *p++ = 0;
-
- /* allocate an event slot */
- ep = events + num_events;
-
- /* If the event array is full, stretch it. After stretching, we know
- that ep will be pointing to an available event spot. */
- if (ep == events + events_size)
- {
- int old_size = events_size;
-
- events_size *= 2;
- events = ((struct event *)
- realloc (events, events_size * sizeof (struct event)));
- if (! events)
- {
- fprintf (stderr, "%s: virtual memory exhausted.\n", pname);
- /* Since there is so much virtual memory, and running out
- almost surely means something is very very wrong,
- it is best to exit rather than continue. */
- exit (1);
- }
-
- while (old_size < events_size)
- events[old_size++].token = NULL;
- }
-
- /* Don't allow users to schedule events in past time. */
- ep->reply_at = get_date (str, NULL);
- if (ep->reply_at - time (&now) < 0)
- {
- fprintf (stderr, "%s: bad time spec: %s%c%s\n", pname, str, FS, p);
- return;
- }
-
- /* save the event description */
- ep->token = (char *) malloc ((unsigned) strlen (p) + 1);
- if (! ep->token)
- {
- fprintf (stderr, "%s: malloc %s: %s%c%s\n",
- pname, strerror (errno), str, FS, p);
- return;
- }
-
- strcpy (ep->token, p);
- num_events++;
-}
-
-/* Print the notification for the alarmed event just arrived if any,
- and schedule an alarm for the next event if any. */
-
-void
-notify ()
-{
- time_t now, tdiff, waitfor = -1;
- register struct event *ep;
-
- /* Inhibit interference with alarms while changing global vars. */
- defer_alarms = 1;
- alarm_deferred = 0;
-
- now = time ((time_t *) NULL);
-
- for (ep = events; ep < events + num_events; ep++)
- /* Are any events ready to fire? */
- if (ep->reply_at <= now)
- {
- fputs (ep->token, stdout);
- putc ('\n', stdout);
- fflush (stdout);
- free (ep->token);
-
- /* We now have a hole in the event array; fill it with the last
- event. */
- ep->token = events[num_events - 1].token;
- ep->reply_at = events[num_events - 1].reply_at;
- num_events--;
-
- /* We ought to scan this event again. */
- ep--;
- }
- else
- {
- /* next timeout should be the soonest of any remaining */
- if ((tdiff = ep->reply_at - now) < waitfor || waitfor < 0)
- waitfor = (long)tdiff;
- }
-
- /* If there are no more events, we needn't bother setting an alarm. */
- if (num_events > 0)
- alarm (waitfor);
-
- /* Now check if there was another alarm
- while we were handling an explicit request. */
- defer_alarms = 0;
- if (alarm_deferred)
- notify ();
- alarm_deferred = 0;
-}
-
-/* Read one command from command from standard input
- and schedule the event for it. */
-
-void
-getevent ()
-{
- int i;
-
- /* 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 (buf == 0)
- {
- buf_size = 80;
- buf = (char *) malloc (buf_size);
- }
-
- /* Read a line from standard input, expanding buf if it is too short
- to hold the line. */
- for (i = 0; ; i++)
- {
- char c;
- int nread;
-
- if (i >= buf_size)
- {
- buf_size *= 2;
- alarm_deferred = 0;
- defer_alarms = 1;
- buf = (char *) realloc (buf, buf_size);
- defer_alarms = 0;
- if (alarm_deferred)
- notify ();
- alarm_deferred = 0;
- }
-
- /* Read one character into c. */
- while (1)
- {
- nread = read (fileno (stdin), &c, 1);
-
- /* Retry after transient error. */
- if (nread < 0
- && (1
-#ifdef EINTR
- || errno == EINTR
-#endif
-#ifdef EAGAIN
- || errno == EAGAIN
-#endif
- ))
- continue;
-
- /* Report serious errors. */
- if (nread < 0)
- {
- perror ("read");
- exit (1);
- }
-
- /* On eof, exit. */
- if (nread == 0)
- exit (0);
-
- break;
- }
-
- if (c == '\n')
- {
- buf[i] = '\0';
- break;
- }
-
- buf[i] = c;
- }
-
- /* Register the event. */
- alarm_deferred = 0;
- defer_alarms = 1;
- schedule (buf);
- defer_alarms = 0;
- notify ();
- alarm_deferred = 0;
-}
-
-/* Handle incoming signal SIG. */
-
-SIGTYPE
-sigcatch (sig)
- int sig;
-{
- struct event *ep;
-
- /* required on older UNIXes; harmless on newer ones */
- signal (sig, sigcatch);
-
- switch (sig)
- {
- case SIGALRM:
- if (defer_alarms)
- alarm_deferred = 1;
- else
- notify ();
- break;
- case SIGTERM:
- fprintf (stderr, "Events still queued:\n");
- for (ep = events; ep < events + num_events; ep++)
- fprintf (stderr, "%d = %ld @ %s\n",
- ep - events, ep->reply_at, ep->token);
- exit (0);
- break;
- }
-}
-
-/*ARGSUSED*/
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- for (pname = argv[0] + strlen (argv[0]);
- *pname != '/' && pname != argv[0];
- pname--);
- if (*pname == '/')
- pname++;
-
- events_size = 16;
- events = ((struct event *) malloc (events_size * sizeof (*events)));
- num_events = 0;
-
- signal (SIGALRM, sigcatch);
- signal (SIGTERM, sigcatch);
-
- /* Loop reading commands from standard input
- and scheduling alarms accordingly.
- The alarms are handled asynchronously, while we wait for commands. */
- while (1)
- getevent ();
-}
-
-#ifndef HAVE_STRERROR
-char *
-strerror (errnum)
- int errnum;
-{
- extern char *sys_errlist[];
- extern int sys_nerr;
-
- if (errnum >= 0 && errnum < sys_nerr)
- return sys_errlist[errnum];
- return (char *) "Unknown error";
-}
-
-#endif /* ! HAVE_STRERROR */
-
-long *
-xmalloc (size)
- int size;
-{
- register long *val;
-
- val = (long *) malloc (size);
-
- if (!val && size)
- {
- fprintf (stderr, "timer: virtual memory exceeded\n");
- exit (1);
- }
-
- return val;
-}
-
-/* timer.c ends here */
diff --git a/lib-src/=wakeup.c b/lib-src/=wakeup.c
deleted file mode 100644
index 389519ba1f7..00000000000
--- a/lib-src/=wakeup.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Program to produce output at regular intervals. */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <sys/types.h>
-
-#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-
-struct tm *localtime ();
-
-void
-main (argc, argv)
- int argc;
- char **argv;
-{
- int period = 60;
- time_t when;
- struct tm *tp;
-
- if (argc > 1)
- period = atoi (argv[1]);
-
- 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
- changes. */
- if (period == 60)
- {
- time (&when);
- tp = localtime (&when);
- sleep (60 - tp->tm_sec);
- }
- else
- sleep (period);
- }
-}
diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in
deleted file mode 100644
index 24eec646375..00000000000
--- a/lib-src/Makefile.in
+++ /dev/null
@@ -1,419 +0,0 @@
-# Makefile for lib-src subdirectory in GNU Emacs.
-# Copyright (C) 1985, 1987, 1988, 1993, 1994 Free Software Foundation, Inc.
-
-# This file is part of GNU Emacs.
-
-# GNU Emacs is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-
-# GNU Emacs is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with GNU Emacs; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-# Avoid trouble on systems where the `SHELL' variable might be
-# inherited from the environment.
-SHELL = /bin/sh
-
-# ==================== Things `configure' will edit ====================
-
-CC=@CC@
-CFLAGS=@CFLAGS@
-ALLOCA=@ALLOCA@
-YACC=@YACC@
-version=@version@
-configuration=@configuration@
-
-# ==================== Where To Install Things ====================
-
-# The default location for installation. Everything is placed in
-# subdirectories of this directory. The default values for many of
-# the variables below are expressed in terms of this one, so you may
-# not need to change them. This is set with the --prefix option to
-# `../configure'.
-prefix=@prefix@
-
-# Like `prefix', but used for architecture-specific files. This is
-# set with the --exec-prefix option to `../configure'.
-exec_prefix=@exec_prefix@
-
-# Where to install Emacs and other binaries that people will want to
-# run directly (like etags). This is set with the --bindir option
-# to `../configure'.
-bindir=@bindir@
-
-# Where to install and expect executable files to be run by Emacs
-# rather than directly by users, and other architecture-dependent
-# data. ${archlibdir} is usually below this. This is set with the
-# --libexecdir option to `../configure'.
-libexecdir=@libexecdir@
-
-# Where to find the source code. This is set by the configure
-# script's `--srcdir' option. However, the value of ${srcdir} in
-# this makefile is not identical to what was specified with --srcdir,
-# since the variable here has `/lib-src' added at the end.
-srcdir=@srcdir@
-VPATH=@srcdir@
-
-# The top-level source directory, also set by configure.
-top_srcdir=@top_srcdir@
-
-# ==================== Emacs-specific directories ====================
-
-# These variables hold the values Emacs will actually use. They are
-# based on the values of the standard Make variables above.
-
-# Where to put executables to be run by Emacs rather than the user.
-# This path usually includes the Emacs version and configuration name,
-# so that multiple configurations for multiple versions of Emacs may
-# be installed at once. This can be set with the --archlibdir option
-# to `../configure'.
-archlibdir=@archlibdir@
-
-# ==================== Utility Programs for the Build =================
-
-# ../configure figures out the correct values for these.
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-# By default, we uphold the dignity of our programs.
-INSTALL_STRIP =
-
-# ========================== Lists of Files ===========================
-
-# Things that a user might actually run,
-# which should be installed in bindir.
-INSTALLABLES = etags ctags emacsclient b2m
-INSTALLABLE_SCRIPTS = rcs-checkin
-
-# Things that Emacs runs internally, or during the build process,
-# which should not be installed in bindir.
-UTILITIES= profile digest-doc \
- sorted-doc movemail cvtmail fakemail yow emacsserver hexl
-
-DONT_INSTALL= test-distrib make-docfile
-
-# Like UTILITIES, but they're not system-dependent, and should not be
-# deleted by the distclean target.
-SCRIPTS= rcs2log vcdiff
-
-EXECUTABLES= ${UTILITIES} ${INSTALLABLES} ${SCRIPTS} ${INSTALLABLE_SCRIPTS}
-
-SOURCES = COPYING ChangeLog Makefile.in README emacs.csh \
- makedoc.com *.[chy] rcs2log vcdiff
-
-# Additional -D flags for movemail (add to MOVE_FLAGS if desired):
-# MAIL_USE_POP Support mail retrieval from a POP mailbox.
-# MAIL_USE_MMDF Support MMDF mailboxes.
-# MAIL_USE_FLOCK Use flock for file locking (see the comments
-# about locking in movemail.c)
-# MAIL_UNLINK_SPOOL Unlink the user's spool mailbox after reading
-# it (instead of just emptying it).
-# KERBEROS Support Kerberized POP.
-# KRB5 Support Kerberos Version 5 pop instead of
-# Version 4 (define this in addition to
-# KERBEROS).
-# HESIOD Support Hesiod lookups of user mailboxes.
-# MAILHOST A string, the host name of the default POP
-# mail host for the site.
-MOVE_FLAGS=
-
-# ========================== start of cpp stuff =======================
-/* From here on, comments must be done in C syntax. */
-
-#define NO_SHORTNAMES
-#define THIS_IS_MAKEFILE
-#define NOT_C_CODE
-#include "../src/config.h"
-
-/* We won't really call alloca;
- don't let the file name alloca.c get messed up. */
-#ifdef alloca
-#undef alloca
-#endif
-
-/* Some machines don't find the standard C libraries in the usual place. */
-#ifndef ORDINARY_LINK
-#ifndef LIB_STANDARD_LIBSRC
-#define LIB_STANDARD_LIBSRC -lc
-#endif
-#else
-#ifndef LIB_STANDARD_LIBSRC
-#define LIB_STANDARD_LIBSRC
-#endif
-#endif
-
-/* Some s/SYSTEM.h files define this to request special libraries. */
-#ifndef LIBS_SYSTEM
-#define LIBS_SYSTEM
-#endif
-
-/* Some m/MACHINE.h files define this to request special libraries. */
-#ifndef LIBS_MACHINE
-#define LIBS_MACHINE
-#endif
-
-#ifndef C_SWITCH_SYSTEM
-#define C_SWITCH_SYSTEM
-#endif
-
-#ifndef C_SWITCH_MACHINE
-#define C_SWITCH_MACHINE
-#endif
-
-#undef MOVEMAIL_NEEDS_BLESSING
-#ifndef MAIL_USE_FLOCK
-#ifndef MAIL_USE_LOCKF
-#define MOVEMAIL_NEEDS_BLESSING
-#endif
-#endif
-
-#ifdef MOVEMAIL_NEEDS_BLESSING
-#define BLESSMAIL blessmail
-#else
-#define BLESSMAIL
-#endif
-
-#ifdef KERBEROS
-#ifdef HAVE_LIBKRB
- /* For krb5, use -lkrb5 */
- KRBLIB=-lkrb
-#endif
-#ifdef HAVE_LIBDES
- /* For krb4, use -lcrypto */
- DESLIB=-ldes
-#endif
-#ifdef HAVE_LIBCOM_ERR
- COM_ERRLIB=-lcom_err
-#endif
-#endif /* KERBEROS */
-
-/* If HESIOD is defined, set this to "-lhesiod". */
-HESIODLIB=
-
-MOVE_LIBS=$(KRBLIB) $(DESLIB) $(COM_ERRLIB) $(HESIODLIB)
-
-#ifdef HAVE_LIBMAIL
-LIBMAIL=-lmail
-#endif
-
-LOADLIBES=LIBS_SYSTEM LIBS_MACHINE LIB_STANDARD_LIBSRC
-
-/* We need to #define emacs to get the right versions of some files.
- Some other files - those shared with other GNU utilities - need
- HAVE_CONFIG_H #defined before they know they can take advantage of
- the information in ../src/config.h. */
-ALL_CFLAGS = C_SWITCH_SYSTEM C_SWITCH_MACHINE -DHAVE_CONFIG_H \
- -I. -I../src -I${srcdir} -I${srcdir}/../src ${LDFLAGS} ${CPPFLAGS} ${CFLAGS}
-LINK_CFLAGS = C_SWITCH_SYSTEM C_SWITCH_MACHINE -DHAVE_CONFIG_H \
- -I. -I../src -I${srcdir} -I${srcdir}/../src ${LDFLAGS} ${CFLAGS}
-CPP_CFLAGS = C_SWITCH_SYSTEM C_SWITCH_MACHINE -DHAVE_CONFIG_H \
- -I. -I../src -I${srcdir} -I${srcdir}/../src ${CPPFLAGS} ${CFLAGS}
-/* This was all of CPP_CFLAGS except -Demacs.
- Now that -Demacs has been deleted from CPP_CFLAGS,
- this is actually the same as CPP_CFLAGS, but let's not delete it yet. */
-BASE_CFLAGS = C_SWITCH_SYSTEM C_SWITCH_MACHINE -DHAVE_CONFIG_H \
- -I. -I../src -I${srcdir} -I${srcdir}/../src ${CPPFLAGS} ${CFLAGS}
-
-/* This is the default compilation command.
- But we should never rely on it, because some make version
- failed to find it for getopt.o.
- Using an explicit command made it work. */
-.c.o:
- ${CC} -c ${CPP_CFLAGS} $<
-
-all: ${DONT_INSTALL} ${UTILITIES} ${INSTALLABLES}
-
-#ifdef MOVEMAIL_NEEDS_BLESSING
-blessmail:
- ../src/emacs -batch -l $(srcdir)/../lisp/blessmail.el
- chmod +x blessmail
-#endif
-
-maybe-blessmail: BLESSMAIL
-#ifdef MOVEMAIL_NEEDS_BLESSING
-/* Don't charge ahead and do it! Let the installer decide.
- ./blessmail ${archlibdir}/movemail */
- @if [ `wc -l <blessmail` != 2 ] ; then \
- dir=`sed -n -e 's/echo mail directory = \(.*\)/\1/p' blessmail`; \
- echo Assuming $$dir is really the mail spool directory, you should; \
- echo run lib-src/blessmail ${archlibdir}/movemail; \
- echo as root, to give movemail appropriate permissions.; \
- echo Do that after running make install.; \
- fi
-#endif
-
-/* Install the internal utilities. Until they are installed, we can
- just run them directly from lib-src. */
-${archlibdir}: all
- @echo
- @echo "Installing utilities run internally by Emacs."
- $(top_srcdir)/mkinstalldirs ${archlibdir}
- if [ `(cd ${archlibdir} && /bin/pwd)` != `/bin/pwd` ]; then \
- for file in ${UTILITIES}; do \
- $(INSTALL_PROGRAM) $(INSTALL_STRIP) $$file ${archlibdir}/$$file ; \
- done ; \
- fi
- if [ `(cd ${archlibdir} && /bin/pwd)` \
- != `(cd ${srcdir} && /bin/pwd)` ]; then \
- for file in ${SCRIPTS}; do \
- $(INSTALL_PROGRAM) ${srcdir}/$$file ${archlibdir}/$$file; \
- done ; \
- fi
-
-install: ${archlibdir}
- @echo
- @echo "Installing utilities for users to run."
- for file in ${INSTALLABLES} ; do \
- $(INSTALL_PROGRAM) $${file} ${bindir}/$${file} ; \
- chmod a+rx ${bindir}/$${file}; \
- done
- for file in ${INSTALLABLE_SCRIPTS} ; do \
- $(INSTALL_PROGRAM) ${srcdir}/$${file} ${bindir}/$${file} ; \
- chmod a+rx ${bindir}/$${file}; \
- done
-
-uninstall:
- (cd ${bindir}; \
- rm -f ${INSTALLABLES} ${INSTALLABLE_SCRIPTS})
- (cd ${archlibdir}; \
- rm -f ${UTILITIES} ${INSTALLABLES} ${SCRIPTS} ${INSTALLABLE_SCRIPTS})
-
-mostlyclean:
- -rm -f core *.o
-
-clean: mostlyclean
- -rm -f ${INSTALLABLES} ${UTILITIES} ${DONT_INSTALL}
- -rm -f ../etc/DOC* *.tab.c *.tab.h
-
-distclean: clean
- -rm -f TAGS
- -rm -f Makefile Makefile.c blessmail
-
-maintainer-clean: distclean
- true
-
-extraclean: maintainer-clean
- -rm -f *~ \#*
-
-unlock:
- chmod u+w $(SOURCES)
-
-relock:
- chmod u-w $(SOURCES)
-
-/* Test the contents of the directory. */
-check:
- @echo "We don't have any tests for GNU Emacs yet."
-
-tags: TAGS
-TAGS: etags
- etags *.[ch]
-
-/* This verifies that the non-ASCII characters in the file `testfile'
- have not 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: ${srcdir}/test-distrib.c
- $(CC) ${ALL_CFLAGS} -o test-distrib ${srcdir}/test-distrib.c
- ./test-distrib ${srcdir}/testfile
-
-GETOPTOBJS = getopt.o getopt1.o $(ALLOCA)
-GETOPTDEPS = $(GETOPTOBJS) ${srcdir}/getopt.h
-getopt.o: ${srcdir}/getopt.c ${srcdir}/getopt.h
- ${CC} -c ${CPP_CFLAGS} ${srcdir}/getopt.c
-getopt1.o: ${srcdir}/getopt1.c ${srcdir}/getopt.h
- ${CC} -c ${CPP_CFLAGS} ${srcdir}/getopt1.c
-alloca.o: ${srcdir}/alloca.c
- ${CC} -c ${BASE_CFLAGS} ${srcdir}/alloca.c
-
-#ifdef REGEXP_IN_LIBC
-REGEXPOBJ =
-REGEXPDEPS =
-#else
-REGEXPOBJ = regex.o
-REGEXPDEPS = $(REGEXPOBJ) ../src/regex.h
-#endif
-
-regex.o: ../src/regex.c ../src/regex.h ../src/config.h
- ${CC} -c ${BASE_CFLAGS} -DCONFIG_BROKETS -DINHIBIT_STRING_HEADER ${srcdir}/../src/regex.c
-
-etags: ${srcdir}/etags.c $(GETOPTDEPS) $(REGEXPDEPS) ../src/config.h
- $(CC) ${ALL_CFLAGS} -DVERSION="\"${version}\"" -DETAGS_REGEXPS ${srcdir}/etags.c $(GETOPTOBJS) $(REGEXPOBJ) $(LOADLIBES) -o etags
-
-/* We depend on etags to assure that parallel makes don't write two
- etags.o files on top of each other. */
-ctags: etags
- $(CC) ${ALL_CFLAGS} -DCTAGS -DVERSION="\"${version}\"" -DETAGS_REGEXPS ${srcdir}/etags.c $(GETOPTOBJS) $(REGEXPOBJ) $(LOADLIBES) -o ctags
-
-profile: ${srcdir}/profile.c
- $(CC) ${ALL_CFLAGS} ${srcdir}/profile.c $(LOADLIBES) -o profile
-
-make-docfile: ${srcdir}/make-docfile.c
- $(CC) ${ALL_CFLAGS} ${srcdir}/make-docfile.c $(LOADLIBES) -o make-docfile
-
-digest-doc: ${srcdir}/digest-doc.c
- $(CC) ${ALL_CFLAGS} ${srcdir}/digest-doc.c $(LOADLIBES) -o digest-doc
-
-sorted-doc: ${srcdir}/sorted-doc.c ${ALLOCA}
- $(CC) ${ALL_CFLAGS} ${srcdir}/sorted-doc.c ${ALLOCA} $(LOADLIBES) -o sorted-doc
-
-b2m: ${srcdir}/b2m.c ../src/config.h
- $(CC) ${ALL_CFLAGS} ${srcdir}/b2m.c $(LOADLIBES) -o b2m
-
-movemail: movemail.o pop.o
- $(CC) ${LINK_CFLAGS} ${MOVE_FLAGS} movemail.o pop.o $(LOADLIBES) $(LIBMAIL) $(MOVE_LIBS) -o movemail
-
-movemail.o: ${srcdir}/movemail.c ../src/config.h
- $(CC) -c ${CPP_CFLAGS} -Demacs ${MOVE_FLAGS} ${srcdir}/movemail.c
-
-pop.o: ${srcdir}/pop.c
- $(CC) -c ${CPP_CFLAGS} ${MOVE_FLAGS} ${srcdir}/pop.c
-
-cvtmail: ${srcdir}/cvtmail.c
- $(CC) ${ALL_CFLAGS} ${srcdir}/cvtmail.c $(LOADLIBES) -o cvtmail
-
-fakemail: ${srcdir}/fakemail.c ../src/config.h
- $(CC) ${ALL_CFLAGS} ${srcdir}/fakemail.c $(LOADLIBES) -o fakemail
-
-yow: ${srcdir}/yow.c ../src/paths.h
- $(CC) ${ALL_CFLAGS} ${srcdir}/yow.c $(LOADLIBES) -o yow
-
-emacsserver: ${srcdir}/emacsserver.c ../src/config.h
- $(CC) ${ALL_CFLAGS} ${srcdir}/emacsserver.c $(LOADLIBES) -o emacsserver
-
-emacsclient: ${srcdir}/emacsclient.c ../src/config.h $(GETOPTDEPS)
- $(CC) ${ALL_CFLAGS} ${srcdir}/emacsclient.c $(GETOPTOBJS) \
- -DVERSION=`sed -n -e '/(defconst emacs-version/ s/^[^"]*\("[^"]*"\).*/\1/p' ${srcdir}/../lisp/version.el` \
- $(LOADLIBES) -o emacsclient
-
-hexl: ${srcdir}/hexl.c
- $(CC) ${ALL_CFLAGS} ${srcdir}/hexl.c $(LOADLIBES) -o hexl
-
-/* These are NOT included in INSTALLABLES or UTILITIES.
- See ../src/Makefile.in. */
-emacstool: ${srcdir}/emacstool.c
- $(CC) ${srcdir}/emacstool.c -o emacstool ${ALL_CFLAGS} \
- -lsuntool -lsunwindow -lpixrect $(LOADLIBES)
-
-/* For SUN Japanese Language Environment. */
-nemacstool: ${srcdir}/emacstool.c
- $(CC) -o nemacstool -DJLE ${ALL_CFLAGS} ${srcdir}/emacstool.c \
- -lsuntool -lmle -lsunwindow -lpixrect $(LOADLIBES)
-
-xvetool: ${srcdir}/emacstool.c
- $(CC) -o xvetool -DXVIEW ${ALL_CFLAGS} ${srcdir}/emacstool.c \
- -lxview -lX -I$(OPENWINHOME)/include -L$(OPENWINHOME)/lib \
- $(LOADLIBES)
-
-xveterm: ${srcdir}/emacstool.c
- $(CC) -o xveterm -DXVIEW -DTTERM ${ALL_CFLAGS} ${srcdir}/emacstool.c \
- -lxview -lolgx -lX -I$(OPENWINHOME)/include -L$(OPENWINHOME)/lib \
- $(LOADLIBES)
diff --git a/lib-src/b2m.c b/lib-src/b2m.c
deleted file mode 100644
index 88d0acd5cd8..00000000000
--- a/lib-src/b2m.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * b2m - a filter for Babyl -> Unix mail files
- *
- * usage: b2m < babyl > mailbox
- *
- * I find this useful whenever I have to use a
- * system which - shock horror! - doesn't run
- * Gnu emacs. At least now I can read all my
- * Gnumacs Babyl format mail files!
- *
- * it's not much but it's free!
- *
- * Ed Wilkinson
- * E.Wilkinson@massey.ac.nz
- * Mon Nov 7 15:54:06 PDT 1988
- */
-
-/* Made conformant to the GNU coding standards January, 1995
- by Francesco Potorti` <pot@cnuce.cnr.it>. */
-
-#include <stdio.h>
-#include <time.h>
-#include <sys/types.h>
-#ifdef MSDOS
-#include <fcntl.h>
-#endif
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-/* On some systems, Emacs defines static as nothing for the sake
- of unexec. We don't want that here since we don't use unexec. */
-#undef static
-#endif
-
-#undef TRUE
-#define TRUE 1
-#undef FALSE
-#define FALSE 0
-
-/* Exit codes for success and failure. */
-#ifdef VMS
-#define GOOD 1
-#define BAD 0
-#else
-#define GOOD 0
-#define BAD 1
-#endif
-
-#define streq(s,t) (strcmp (s, t) == 0)
-#define strneq(s,t,n) (strncmp (s, t, n) == 0)
-
-typedef int logical;
-
-/*
- * 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;
-};
-
-extern char *strtok();
-
-long *xmalloc (), *xrealloc ();
-char *concat ();
-long readline ();
-void fatal ();
-
-/*
- * xnew -- allocate storage. SYNOPSIS: Type *xnew (int n, Type);
- */
-#define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
-
-
-
-char *progname;
-
-main (argc, argv)
- int argc;
- char **argv;
-{
- logical labels_saved, printing, header;
- time_t ltoday;
- char *labels, *p, *today;
- struct linebuffer data;
-
-#ifdef MSDOS
- _fmode = O_BINARY; /* all of files are treated as binary files */
-#if __DJGPP__ > 1
- if (!isatty (fileno (stdout)))
- setmode (fileno (stdout), O_BINARY);
- if (!isatty (fileno (stdin)))
- setmode (fileno (stdin), O_BINARY);
-#else /* not __DJGPP__ > 1 */
- (stdout)->_flag &= ~_IOTEXT;
- (stdin)->_flag &= ~_IOTEXT;
-#endif /* not __DJGPP__ > 1 */
-#endif
- progname = argv[0];
-
- if (argc != 1)
- {
- fprintf (stderr, "Usage: %s <babylmailbox >unixmailbox\n", progname);
- exit (GOOD);
- }
- labels_saved = printing = header = FALSE;
- ltoday = time (0);
- today = ctime (&ltoday);
- data.size = 200;
- data.buffer = xnew (200, char);
-
- if (readline (&data, stdin) == 0
- || !strneq (data.buffer, "BABYL OPTIONS:", 14))
- fatal ("standard input is not a Babyl mailfile.");
-
- while (readline (&data, stdin) > 0)
- {
- if (streq (data.buffer, "*** EOOH ***") && !printing)
- {
- printing = header = TRUE;
- printf ("From \"Babyl to mail by %s\" %s", progname, today);
- continue;
- }
-
- if (data.buffer[0] == '\037')
- {
- if (data.buffer[1] == '\0')
- continue;
- else if (data.buffer[1] == '\f')
- {
- /* Save labels. */
- readline (&data, stdin);
- p = strtok (data.buffer, " ,\r\n\t");
- labels = "X-Babyl-Labels: ";
-
- while (p = strtok (NULL, " ,\r\n\t"))
- labels = concat (labels, p, ", ");
-
- p = &labels[strlen (labels) - 2];
- if (*p == ',')
- *p = '\0';
- printing = header = FALSE;
- labels_saved = TRUE;
- continue;
- }
- }
-
- if ((data.buffer[0] == '\0') && header)
- {
- header = FALSE;
- if (labels_saved)
- puts (labels);
- }
-
- if (printing)
- puts (data.buffer);
- }
-}
-
-
-
-/*
- * 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 = xnew (len1 + len2 + len3 + 1, char);
-
- strcpy (result, s1);
- strcpy (result + len1, s2);
- strcpy (result + len1 + len2, s3);
- result[len1 + len2 + len3] = '\0';
-
- return result;
-}
-
-/*
- * Read a line of text from `stream' into `linebuffer'.
- * Return the number of characters read from `stream',
- * which is the length of the line including the newline, if any.
- */
-long
-readline (linebuffer, stream)
- struct linebuffer *linebuffer;
- register FILE *stream;
-{
- char *buffer = linebuffer->buffer;
- register char *p = linebuffer->buffer;
- register char *pend;
- int chars_deleted;
-
- pend = p + linebuffer->size; /* Separate to avoid 386/IX compiler bug. */
-
- while (1)
- {
- register 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 == EOF)
- {
- chars_deleted = 0;
- break;
- }
- if (c == '\n')
- {
- if (p[-1] == '\r' && p > buffer)
- {
- *--p = '\0';
- chars_deleted = 2;
- }
- else
- {
- *p = '\0';
- chars_deleted = 1;
- }
- break;
- }
- *p++ = c;
- }
-
- return (p - buffer + chars_deleted);
-}
-
-/*
- * Like malloc but get fatal error if memory is exhausted.
- */
-long *
-xmalloc (size)
- unsigned int size;
-{
- long *result = (long *) malloc (size);
- if (result == NULL)
- fatal ("virtual memory exhausted");
- return result;
-}
-
-long *
-xrealloc (ptr, size)
- char *ptr;
- unsigned int size;
-{
- long *result = (long *) realloc (ptr, size);
- if (result == NULL)
- fatal ("virtual memory exhausted");
- return result;
-}
-
-void
-fatal (message)
-{
- fprintf (stderr, "%s: %s\n", progname, message);
- exit (BAD);
-}
-
diff --git a/lib-src/cvtmail.c b/lib-src/cvtmail.c
deleted file mode 100644
index 20ef3412439..00000000000
--- a/lib-src/cvtmail.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (C) 1985, 1994 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* cvtmail:
- * Program to convert oldstyle goslings emacs mail directories into
- * gnu-rmail format. Program expects a directory called Messages to
- * exist in your home directory, containing individual mail messages in
- * separate files in the standard gosling emacs mail reader format.
- *
- * Program takes one argument: an output file. This file will contain
- * all the messages in Messages directory, in berkeley mail format.
- * If no output file is mentioned, messages are put in ~/OMAIL.
- *
- * In order to get rmail to read the messages, the resulting file must
- * be mv'ed to ~/mbox, and then have rmail invoked on them.
- *
- * Author: Larry Kolodney, 1985
- */
-
-
-#include <stdio.h>
-
-char *malloc ();
-char *realloc ();
-char *getenv ();
-
-char *xmalloc ();
-char *xrealloc ();
-void skip_to_lf ();
-void sysfail ();
-
-int
-main (argc, argv)
- int argc;
- char *argv[];
-{
- char *hd;
- char *md;
- char *mdd;
- char *mfile;
- char *cf;
- int cflen;
- FILE *mddf;
- FILE *mfilef;
- FILE *cff;
- char pre[10];
- char name[14];
- int c;
-
- hd = (char *) getenv ("HOME");
-
- md = (char *) xmalloc (strlen (hd) + 10);
- strcpy (md, hd);
- strcat (md, "/Messages");
-
- mdd = (char *) xmalloc (strlen (md) + 11);
- strcpy (mdd, md);
- strcat (mdd, "/Directory");
-
- cflen = 100;
- cf = (char *) xmalloc (cflen);
-
- mddf = fopen (mdd, "r");
- if (!mddf)
- sysfail (mdd);
- if (argc > 1)
- mfile = argv[1];
- else
- {
- mfile = (char *) xmalloc (strlen (hd) + 7);
- strcpy (mfile, hd);
- strcat (mfile, "/OMAIL");
- }
- mfilef = fopen (mfile, "w");
- if (!mfilef)
- sysfail (mfile);
-
- skip_to_lf (mddf);
- while (fscanf (mddf, "%4c%14[0123456789]", pre, name) != EOF)
- {
- if (cflen < strlen (md) + strlen (name) + 2)
- {
- cflen = strlen (md) + strlen (name) + 2;
- cf = (char *) xrealloc (cf, cflen);
- }
- strcpy (cf, md);
- strcat (cf,"/");
- strcat (cf, name);
- cff = fopen (cf, "r");
- if (!cff)
- perror (cf);
- else
- {
- while ((c = getc(cff)) != EOF)
- putc (c, mfilef);
- putc ('\n', mfilef);
- skip_to_lf (mddf);
- fclose (cff);
- }
- }
- fclose (mddf);
- fclose (mfilef);
- return 0;
-}
-
-void
-skip_to_lf (stream)
- FILE *stream;
-{
- register int c;
- while ((c = getc(stream)) != EOF && c != '\n')
- ;
-}
-
-
-void
-error (s1, s2)
- char *s1, *s2;
-{
- fprintf (stderr, "cvtmail: ");
- fprintf (stderr, s1, s2);
- fprintf (stderr, "\n");
-}
-
-/* Print error message and exit. */
-
-void
-fatal (s1, s2)
- char *s1, *s2;
-{
- error (s1, s2);
- exit (1);
-}
-
-void
-sysfail (s)
- char *s;
-{
- fprintf (stderr, "cvtmail: ");
- perror (s);
- exit (1);
-}
-
-char *
-xmalloc (size)
- unsigned size;
-{
- char *result = malloc (size);
- if (!result)
- fatal ("virtual memory exhausted", 0);
- return result;
-}
-
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
-{
- char *result = realloc (ptr, size);
- if (!result)
- fatal ("virtual memory exhausted");
- return result;
-}
diff --git a/lib-src/digest-doc.c b/lib-src/digest-doc.c
deleted file mode 100644
index 1d47ce0a0ce..00000000000
--- a/lib-src/digest-doc.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Give this program DOCSTR.mm.nn as standard input
- and it outputs to standard output
- a file of nroff output containing the doc strings.
-
- See also sorted-doc.c, which produces similar output
- but in texinfo format and sorted by function/variable name. */
-
-#include <stdio.h>
-
-int
-main ()
-{
- register int ch;
- register int notfirst = 0;
-
- printf (".TL\n");
- printf ("Command Summary for GNU Emacs\n");
- printf (".AU\nRichard M. Stallman\n");
- while ((ch = getchar ()) != EOF)
- {
- if (ch == '\037')
- {
- if (notfirst)
- printf ("\n.DE");
- else
- notfirst = 1;
-
- printf ("\n.SH\n");
-
- ch = getchar ();
- printf (ch == 'F' ? "Function " : "Variable ");
-
- while ((ch = getchar ()) != '\n') /* Changed this line */
- {
- if (ch != EOF)
- putchar (ch);
- else
- {
- ungetc (ch, stdin);
- break;
- }
- }
- printf ("\n.DS L\n");
- }
- else
- putchar (ch);
- }
- return 0;
-}
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
deleted file mode 100644
index 2e99e9d34ad..00000000000
--- a/lib-src/emacsclient.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/* Client process that communicates with GNU Emacs acting as server.
- Copyright (C) 1986, 1987, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#define NO_SHORTNAMES
-#include <../src/config.h>
-#undef read
-#undef write
-#undef open
-#undef close
-#undef signal
-
-#include <stdio.h>
-#include <getopt.h>
-
-char *getenv (), *getwd ();
-char *getcwd ();
-int geteuid ();
-
-/* This is defined with -D from the compilation command,
- which extracts it from ../lisp/version.el. */
-
-#ifndef VERSION
-#define VERSION "unspecified"
-#endif
-
-/* Name used to invoke this program. */
-char *progname;
-
-/* Nonzero means don't wait for a response from Emacs. --no-wait. */
-int nowait = 0;
-
-struct option longopts[] =
-{
- { "no-wait", no_argument, NULL, 'n' },
- { "help", no_argument, NULL, 'H' },
- { "version", no_argument, NULL, 'V' },
- { 0 }
-};
-
-/* Decode the options from argv and argc.
- The global variable `optind' will say how many arguments we used up. */
-
-void
-decode_options (argc, argv)
- int argc;
- char **argv;
-{
- while (1)
- {
- int opt = getopt_long (argc, argv,
- "VHn", longopts, 0);
-
- if (opt == EOF)
- break;
-
- switch (opt)
- {
- case 0:
- /* If getopt returns 0, then it has already processed a
- long-named option. We should do nothing. */
- break;
-
- case 'n':
- nowait = 1;
- break;
-
- case 'V':
- fprintf (stderr, "Version %s\n", VERSION);
- exit (1);
- break;
-
- case 'H':
- default:
- print_help_and_exit ();
- }
- }
-}
-
-print_help_and_exit ()
-{
- fprintf (stderr,
- "Usage: %s [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
- progname);
- fprintf (stderr,
- "Report bugs to bug-gnu-emacs@prep.ai.mit.edu.\n");
- exit (1);
-}
-
-/* Return a copy of NAME, inserting a &
- before each &, each space, and any initial -.
- Change spaces to underscores, too, so that the
- return value never contains a space. */
-
-char *
-quote_file_name (name)
- char *name;
-{
- char *copy = (char *) malloc (strlen (name) * 2 + 1);
- char *p, *q;
-
- p = name;
- q = copy;
- while (*p)
- {
- if (*p == ' ')
- {
- *q++ = '&';
- *q++ = '_';
- p++;
- }
- else
- {
- if (*p == '&' || (*p == '-' && p == name))
- *q++ = '&';
- *q++ = *p++;
- }
- }
- *q++ = 0;
-
- return copy;
-}
-
-#if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
-
-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 /* HAVE_SOCKETS or HAVE_SYSVIPC */
-
-#if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
-/* BSD code is very different from SYSV IPC code */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-extern char *strerror ();
-extern int errno;
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- char system_name[32];
- int s, i;
- FILE *out, *in;
- struct sockaddr_un server;
- char *homedir, *cwd, *str;
- char string[BUFSIZ];
-
- progname = argv[0];
-
- /* Process options. */
- decode_options (argc, argv);
-
- if (argc - optind < 1)
- print_help_and_exit ();
-
- /*
- * 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
- {
- struct stat statbfr;
-
- gethostname (system_name, sizeof (system_name));
- sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
-
- if (stat (server.sun_path, &statbfr) == -1)
- {
- if (errno == ENOENT)
- fprintf (stderr,
- "%s: can't find socket; have you started the server?\n",
- argv[0]);
- else
- fprintf (stderr, "%s: can't stat %s: %s\n",
- argv[0], server.sun_path, strerror (errno));
- exit (1);
- }
- if (statbfr.st_uid != geteuid ())
- {
- fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
- 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-");
- gethostname (system_name, sizeof (system_name));
- strcat (server.sun_path, system_name);
-#endif
-
- if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
- < 0)
- {
- fprintf (stderr, "%s: ", argv[0]);
- perror ("connect");
- exit (1);
- }
-
- /* We use the stream OUT to send our command to the server. */
- if ((out = fdopen (s, "r+")) == NULL)
- {
- fprintf (stderr, "%s: ", argv[0]);
- perror ("fdopen");
- exit (1);
- }
-
- /* We use the stream IN to read the response.
- We used to use just one stream for both output and input
- on the socket, but reversing direction works nonportably:
- on some systems, the output appears as the first input;
- on other systems it does not. */
- if ((in = fdopen (s, "r+")) == NULL)
- {
- fprintf (stderr, "%s: ", argv[0]);
- perror ("fdopen");
- exit (1);
- }
-
-#ifdef BSD_SYSTEM
- cwd = getwd (string);
-#else
- cwd = getcwd (string, sizeof string);
-#endif
- if (cwd == 0)
- {
- /* getwd puts message in STRING if it fails. */
- fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
- exit (1);
- }
-
- if (nowait)
- fprintf (out, "-nowait ");
-
- for (i = optind; 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 ", quote_file_name (argv[i]));
- }
- fprintf (out, "\n");
- fflush (out);
-
- /* Maybe wait for an answer. */
- if (nowait)
- return 0;
-
- printf ("Waiting for Emacs...");
- fflush (stdout);
-
- /* Now, wait for an answer and print any messages. On some systems,
- the first line we read will actually be the output we just sent.
- We can't predict whether that will happen, so if it does, we
- detect it by recognizing `Client: ' at the beginning. */
-
- while (str = fgets (string, BUFSIZ, in))
- printf ("%s", str);
-
- return 0;
-}
-
-#else /* This is the SYSV IPC section */
-
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include <sys/utsname.h>
-#include <stdio.h>
-
-char *getwd (), *getcwd (), *getenv ();
-struct utsname system_name;
-
-main (argc, argv)
- int argc;
- char **argv;
-{
- int s;
- key_t key;
- /* Size of text allocated in MSGP. */
- int size_allocated = BUFSIZ;
- /* Amount of text used in MSGP. */
- int used;
- struct msgbuf *msgp
- = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
- struct msqid_ds * msg_st;
- char *homedir, buf[BUFSIZ];
- char gwdirb[BUFSIZ];
- char *cwd;
- char *temp;
-
- progname = argv[0];
-
- /* Process options. */
- decode_options (argc, argv);
-
- if (argc - optind < 1)
- print_help_and_exit ();
-
- /*
- * 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);
-#ifndef HAVE_LONG_FILE_NAMES
- /* If file names are short, we can't fit the host name. */
- strcat (buf, "/.emacs-server");
-#else
- strcat (buf, "/.emacs-server-");
- uname (&system_name);
- strcat (buf, system_name.nodename);
-#endif
- 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_SYSTEM
- 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, "%s: %s\n", argv[0], cwd);
- exit (1);
- }
-
- msgp->mtext[0] = 0;
- used = 0;
-
- if (nowait)
- {
- strcat (msgp->mtext, "-nowait ");
- used += 8;
- }
-
- argc -= optind;
- argv += optind;
-
- while (argc)
- {
- int need_cwd = 0;
- char *modified_arg = argv[0];
-
- if (*modified_arg == '+')
- {
- char *p = modified_arg + 1;
- while (*p >= '0' && *p <= '9') p++;
- if (*p != 0)
- need_cwd = 1;
- }
- else if (*modified_arg != '/')
- need_cwd = 1;
-
- modified_arg = quote_file_name (modified_arg);
-
- if (need_cwd)
- used += strlen (cwd);
- used += strlen (modified_arg) + 1;
- while (used + 2 > size_allocated)
- {
- size_allocated *= 2;
- msgp = (struct msgbuf *) realloc (msgp,
- (sizeof (struct msgbuf)
- + size_allocated));
- }
-
- if (need_cwd)
- strcat (msgp->mtext, cwd);
-
- strcat (msgp->mtext, modified_arg);
- strcat (msgp->mtext, " ");
- argv++; argc--;
- }
- strcat (msgp->mtext, "\n");
-#ifdef HPUX /* HPUX has a bug. */
- if (strlen (msgp->mtext) >= 512)
- {
- fprintf (stderr, "%s: args too long for msgsnd\n", progname);
- exit (1);
- }
-#endif
- msgp->mtype = 1;
- if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
- {
- fprintf (stderr, "%s: ", progname);
- perror ("msgsnd");
- exit (1);
- }
-
- /* Maybe wait for an answer. */
- if (nowait)
- return 0;
-
- printf ("Waiting for Emacs...");
- fflush (stdout);
-
- msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
- strcpy (buf, msgp->mtext);
-
- printf ("\n");
- if (*buf)
- printf ("%s\n", buf);
- exit (0);
-}
-
-#endif /* HAVE_SYSVIPC */
-
-#endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
-
-#ifndef HAVE_STRERROR
-char *
-strerror (errnum)
- int errnum;
-{
- extern char *sys_errlist[];
- extern int sys_nerr;
-
- if (errnum >= 0 && errnum < sys_nerr)
- return sys_errlist[errnum];
- return (char *) "Unknown error";
-}
-
-#endif /* ! HAVE_STRERROR */
diff --git a/lib-src/emacsserver.c b/lib-src/emacsserver.c
deleted file mode 100644
index 9fbf3e86516..00000000000
--- a/lib-src/emacsserver.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/* Communication subprocess for GNU Emacs acting as server.
- Copyright (C) 1986, 1987, 1992, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The GNU Emacs edit server process is run as a subprocess of Emacs
- under control of the file lisp/server.el.
- This program accepts communication from client (program emacsclient.c)
- and passes their commands (consisting of keyboard characters)
- up to the Emacs which then executes them. */
-
-#define NO_SHORTNAMES
-#include <signal.h>
-#include <../src/config.h>
-#undef read
-#undef write
-#undef open
-#undef close
-#undef signal
-
-#if !defined (HAVE_SOCKETS) && !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");
- exit (1);
-}
-
-#else /* HAVE_SOCKETS or HAVE_SYSVIPC */
-
-#if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
-/* BSD code is very different from SYSV IPC code */
-
-#include <sys/types.h>
-#include <sys/file.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/stat.h>
-
-extern int errno;
-
-/* Copied from src/process.c */
-#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. */
-#ifdef FD_SETSIZE
-#define MAXDESC FD_SETSIZE
-#else
-#define MAXDESC 64
-#endif
-#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 */
-
-/* This is the file name of the socket that we made. */
-
-char *socket_name;
-
-/* Name of this program. */
-
-char *progname;
-
-/* Handle fatal signals. */
-
-/* This is the handler. */
-
-SIGTYPE
-delete_socket (sig)
- int sig;
-{
- signal (sig, SIG_DFL);
- unlink (socket_name);
- kill (getpid (), sig);
-}
-
-/* Set up to handle all the signals. */
-
-handle_signals ()
-{
- signal (SIGHUP, delete_socket);
- signal (SIGINT, delete_socket);
- signal (SIGQUIT, delete_socket);
- signal (SIGILL, delete_socket);
- signal (SIGTRAP, delete_socket);
-#ifdef SIGABRT
- signal (SIGABRT, delete_socket);
-#endif
-#ifdef SIGHWE
- signal (SIGHWE, delete_socket);
-#endif
-#ifdef SIGPRE
- signal (SIGPRE, delete_socket);
-#endif
-#ifdef SIGORE
- signal (SIGORE, delete_socket);
-#endif
-#ifdef SIGUME
- signal (SIGUME, delete_socket);
-#endif
-#ifdef SIGDLK
- signal (SIGDLK, delete_socket);
-#endif
-#ifdef SIGCPULIM
- signal (SIGCPULIM, delete_socket);
-#endif
-#ifdef SIGIOT
- /* This is missing on some systems - OS/2, for example. */
- signal (SIGIOT, delete_socket);
-#endif
-#ifdef SIGEMT
- signal (SIGEMT, delete_socket);
-#endif
- signal (SIGFPE, delete_socket);
-#ifdef SIGBUS
- signal (SIGBUS, delete_socket);
-#endif
- signal (SIGSEGV, delete_socket);
-#ifdef SIGSYS
- signal (SIGSYS, delete_socket);
-#endif
- signal (SIGTERM, delete_socket);
-#ifdef SIGXCPU
- signal (SIGXCPU, delete_socket);
-#endif
-#ifdef SIGXFSZ
- signal (SIGXFSZ, delete_socket);
-#endif /* SIGXFSZ */
-
-#ifdef AIX
-/* 20 is SIGCHLD, 21 is SIGTTIN, 22 is SIGTTOU. */
- signal (SIGXCPU, delete_socket);
-#ifndef _I386
- signal (SIGIOINT, delete_socket);
-#endif
- signal (SIGGRANT, delete_socket);
- signal (SIGRETRACT, delete_socket);
- signal (SIGSOUND, delete_socket);
- signal (SIGMSG, delete_socket);
-#endif /* AIX */
-}
-
-/* Print error message. `s1' is printf control string, `s2' is arg for it. */
-void
-error (s1, s2)
- char *s1, *s2;
-{
- fprintf (stderr, "%s: ", progname);
- fprintf (stderr, s1, s2);
- fprintf (stderr, "\n");
-}
-
-/* Print error message and exit. */
-void
-fatal (s1, s2)
- char *s1, *s2;
-{
- error (s1, s2);
- exit (1);
-}
-
-/* Like malloc but get fatal error if memory is exhausted. */
-
-long *
-xmalloc (size)
- unsigned int size;
-{
- long *result = (long *) malloc (size);
- if (result == NULL)
- fatal ("virtual memory exhausted", 0);
- return result;
-}
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- char system_name[32];
- int s, infd;
- size_t fromlen;
- struct sockaddr_un server, fromunix;
- char *homedir;
- char *str, string[BUFSIZ], code[BUFSIZ];
- FILE *infile;
- FILE **openfiles;
- int openfiles_size;
- struct stat statbuf;
-
-#ifndef convex
- char *getenv ();
-#endif
-
- progname = argv[0];
-
- openfiles_size = 20;
- openfiles = (FILE **) malloc (openfiles_size * sizeof (FILE *));
- if (openfiles == 0)
- abort ();
-
- /*
- * Open up an AF_UNIX socket in this person's home directory
- */
-
- if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
- {
- perror_1 ("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 (unlink (server.sun_path) == -1 && errno != ENOENT)
- {
- perror_1 ("unlink");
- exit (1);
- }
-#else
- if ((homedir = getenv ("HOME")) == NULL)
- fatal_error ("No home directory\n");
-
- strcpy (server.sun_path, homedir);
- strcat (server.sun_path, "/.emacs-server-");
- gethostname (system_name, sizeof (system_name));
- strcat (server.sun_path, system_name);
- /* Delete anyone else's old server. */
- unlink (server.sun_path);
-#endif
-
- /* Save the socket name so we can delete it. */
- socket_name = (char *) xmalloc (strlen (server.sun_path) + 1);
- strcpy (socket_name, server.sun_path);
-
- handle_signals ();
-
- if (bind (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2) < 0)
- {
- perror_1 ("bind");
- exit (1);
- }
- /* Only this user can send commands to this Emacs. */
- if (stat (server.sun_path, &statbuf) < 0)
- {
- perror_1 ("bind");
- exit (1);
- }
-
- chmod (server.sun_path, statbuf.st_mode & 0600);
- /*
- * Now, just wait for everything to come in..
- */
- if (listen (s, 5) < 0)
- {
- perror_1 ("listen");
- exit (1);
- }
-
- /* Disable sigpipes in case luser kills client... */
- signal (SIGPIPE, SIG_IGN);
- for (;;)
- {
- SELECT_TYPE rmask;
- FD_ZERO (&rmask);
- FD_SET (0, &rmask);
- FD_SET (s, &rmask);
- if (select (s + 1, &rmask, 0, 0, 0) < 0)
- perror_1 ("select");
- if (FD_ISSET (s, &rmask)) /* client sends list of filenames */
- {
- fromlen = sizeof (fromunix);
- fromunix.sun_family = AF_UNIX;
- infd = accept (s, (struct sockaddr *) &fromunix, &fromlen);
- if (infd < 0)
- {
- if (errno == EMFILE || errno == ENFILE)
- fprintf (stderr, "Error: too many clients.\n");
- else
- perror_1 ("accept");
- continue;
- }
-
- if (infd >= openfiles_size)
- {
- openfiles_size *= 2;
- openfiles = (FILE **) realloc (openfiles,
- openfiles_size * sizeof (FILE *));
- if (openfiles == 0)
- abort ();
- }
-
- infile = fdopen (infd, "r+"); /* open stream */
- if (infile == NULL)
- {
- fprintf (stderr, "Error: too many clients.\n");
- write (infd, "Too many clients.\n", 18);
- close (infd); /* Prevent descriptor leak.. */
- continue;
- }
- str = fgets (string, BUFSIZ, infile);
- if (str == NULL)
- {
- perror_1 ("fgets");
- close (infd); /* Prevent descriptor leak.. */
- continue;
- }
- openfiles[infd] = infile;
- printf ("Client: %d %s", infd, string);
- /* If what we read did not end in a newline,
- it means there is more. Keep reading from the socket
- and outputting to Emacs, until we get the newline. */
- while (string[strlen (string) - 1] != '\n')
- {
- if (fgets (string, BUFSIZ, infile) == 0)
- break;
- printf ("%s", string);
- }
- fflush (stdout);
- fflush (infile);
- continue;
- }
- else if (FD_ISSET (0, &rmask)) /* emacs sends codeword, fd, and string message */
- {
- /* Read command codeword and fd */
- clearerr (stdin);
- scanf ("%s %d%*c", code, &infd);
- if (ferror (stdin) || feof (stdin))
- fatal_error ("server: error reading from standard input\n");
-
- /* Transfer text from Emacs to the client, up to a newline. */
- infile = openfiles[infd];
- rewind (infile);
- while (1)
- {
- if (fgets (string, BUFSIZ, stdin) == 0)
- break;
- fprintf (infile, "%s", string);
- if (string[strlen (string) - 1] == '\n')
- break;
- }
- fflush (infile);
-
- /* If command is close, close connection to client. */
- if (strncmp (code, "Close:", 6) == 0)
- if (infd > 2)
- {
- fclose (infile);
- close (infd);
- }
- continue;
- }
- }
-}
-
-#else /* This is the SYSV IPC section */
-
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include <setjmp.h>
-#include <errno.h>
-#include <sys/utsname.h>
-
-struct utsname system_name;
-
-#ifndef errno
-extern int errno;
-#endif
-
-jmp_buf msgenv;
-
-SIGTYPE
-msgcatch ()
-{
- longjmp (msgenv, 1);
-}
-
-
-/* "THIS has to be fixed. Remember, stderr may not exist...-rlk."
- Incorrect. This program runs as an inferior of Emacs.
- Its stderr always exists--rms. */
-#include <stdio.h>
-
-main ()
-{
- int s, infd, fromlen, ioproc;
- key_t key;
- struct msgbuf * msgp =
- (struct msgbuf *) malloc (sizeof *msgp + BUFSIZ);
- struct msqid_ds msg_st;
- int p;
- char *homedir, *getenv ();
- char string[BUFSIZ];
- FILE *infile;
-
- /*
- * Create a message queue using ~/.emacs-server as the path for ftok
- */
- if ((homedir = getenv ("HOME")) == NULL)
- fatal_error ("No home directory\n");
-
- strcpy (string, homedir);
-#ifndef HAVE_LONG_FILE_NAMES
- /* If file names are short, we can't fit the host name. */
- strcat (string, "/.emacs-server");
-#else
- strcat (string, "/.emacs-server-");
- uname (&system_name);
- strcat (string, system_name.nodename);
-#endif
- creat (string, 0600);
- key = ftok (string, 1); /* unlikely to be anyone else using it */
- s = msgget (key, 0600 | IPC_CREAT);
- if (s == -1)
- {
- perror_1 ("msgget");
- exit (1);
- }
-
- /* Fork so we can close connection even if parent dies */
- p = fork ();
- if (setjmp (msgenv))
- {
- msgctl (s, IPC_RMID, 0);
- if (p > 0)
- kill (p, SIGKILL);
- exit (0);
- }
- signal (SIGTERM, msgcatch);
- signal (SIGINT, msgcatch);
- signal (SIGHUP, msgcatch);
- if (p > 0)
- {
- /* This is executed in the original process that did the fork above. */
- /* Get pid of Emacs itself. */
- p = getppid ();
- setpgrp (); /* Gnu kills process group on exit */
- while (1)
- {
- /* Is Emacs still alive? */
- if (kill (p, 0) < 0)
- {
- msgctl (s, IPC_RMID, 0);
- exit (0);
- }
- sleep (10);
- }
- }
-
- /* This is executed in the child made by forking above.
- Call it c1. Make another process, ioproc. */
-
- ioproc = fork ();
- if (ioproc == 0)
- {
- /* In process ioproc, wait for text from Emacs,
- and send it to the process c1.
- This way, c1 only has to wait for one source of input. */
- while (fgets (msgp->mtext, BUFSIZ, stdin))
- {
- msgp->mtype = 1;
- msgsnd (s, msgp, strlen (msgp->mtext) + 1, 0);
- }
- exit (1);
- }
-
- /* In the process c1,
- listen for messages from clients and pass them to Emacs. */
- while (1)
- {
- if ((fromlen = msgrcv (s, msgp, BUFSIZ - 1, 1, 0)) < 0)
- {
-#ifdef EINTR
- if (errno == EINTR)
- continue;
-#endif
- perror_1 ("msgrcv");
- exit (1);
- }
- else
- {
- msgctl (s, IPC_STAT, &msg_st);
-
- /* Distinguish whether the message came from a client, or from
- ioproc. */
- if (msg_st.msg_lspid == ioproc)
- {
- char code[BUFSIZ];
- int inproc;
-
- /* Message from ioproc: tell a client we are done. */
- msgp->mtext[strlen (msgp->mtext)-1] = 0;
- sscanf (msgp->mtext, "%s %d", code, &inproc);
- msgp->mtype = inproc;
- msgsnd (s, msgp, strlen (msgp->mtext) + 1, 0);
- continue;
- }
-
- /* This is a request from a client: copy to stdout
- so that Emacs will get it. Include msg_lspid
- so server.el can tell us where to send the reply. */
- strncpy (string, msgp->mtext, fromlen);
- string[fromlen] = 0; /* make sure */
- /* Newline is part of string.. */
- printf ("Client: %d %s", msg_st.msg_lspid, string);
- fflush (stdout);
- }
- }
-}
-
-#endif /* HAVE_SYSVIPC */
-
-#endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
-
-/* This is like perror but puts `Error: ' at the beginning. */
-
-perror_1 (string)
- char *string;
-{
- char *copy = (char *) malloc (strlen (string) + 8);
- if (copy == 0)
- fatal_error ("Virtual memory exhausted");
-
- strcpy (copy, "Error: ");
- strcat (copy, string);
- perror (copy);
-}
-
-fatal_error (string)
- char *string;
-{
- fprintf (stderr, "%s", "Error: ");
- fprintf (stderr, string);
- exit (1);
-}
diff --git a/lib-src/emacstool.c b/lib-src/emacstool.c
deleted file mode 100644
index a246e1faacb..00000000000
--- a/lib-src/emacstool.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/*
- * 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 10-Mar-91, Jeff Peck, et al: support for TERMSW (TTERM)
- * allows point-to-type even in OW2
- *
- * [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 indicator 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 ignoring 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
- Window window;
-#endif XVIEW
- 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(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;
-
- 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 (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
- 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;
- }
- }
- 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
-#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_is_ascii(event) && event_meta_is_down(event))
- event_set_id(event, 128 | event_id(event));
-#endif
- 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
- int i, font_width_adjust = 1; /* hackery, and heuristics */
- /* if -Wt is not supplied, then font comes out as lucida-14 (width=8)
- * rather than the screen.r.12 (width=7) typically used
- * this hack attempts to workaround it.
- * could use a env var EMACSTOOL_DEFAULT_FONT_WIDTH instead */
- for (i = 1; argv[i]; i++) {
- if (!(strcmp ("-Wt", argv[i])))
- {font_width_adjust = 0;
- if (console_fd) fprintf(console, "-Wt = %d\n", font_width_adjust);
- break;}
- }
-#endif 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
- font_width -= font_width_adjust; /* A guess! font bug in ttysw*/
-#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
-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/lib-src/env.c b/lib-src/env.c
deleted file mode 100644
index 2ae81a630b8..00000000000
--- a/lib-src/env.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/* env - manipulate environment and execute a program in that environment
- Copyright (C) 1986, 1994 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 2, 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. */
-
-/* Mly 861126 */
-
-/* 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" (i.e., 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 resulting environment is printed.
- This 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 environment
- { USER=rms EDITOR=emacs PATH=.:/gnubin:/hacks DISPLAY=gnu:0 }
-
- * "env - USER=foo /hacks/hack bar baz"
- calls the "hack" program on arguments "bar" and "baz"
- in an environment in which the only variable is "USER".
- Note that the "-" option clears 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>
-
-extern int execvp ();
-
-char *xmalloc (), *xrealloc ();
-char *concat ();
-
-extern char **environ;
-
-char **nenv;
-int nenv_size;
-
-char *progname;
-void setenv ();
-void fatal ();
-char *myindex ();
-
-extern char *strerror ();
-
-
-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 = myindex (*envp, '=');
- if (tem)
- {
- *tem = '\000';
- setenv (*envp, tem + 1);
- }
- }
-
- while (argc > 0)
- {
- tem = myindex (*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 for `%s' option", *argv);
- if (!strcmp (*argv, "-u")
- || !strcmp (*argv, "-unset"))
- /* Unset a variable */
- {
- argc--;
- argv++;
- setenv (*argv, (char *) 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 ("unrecognized option `%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;
- extern char *strerror ();
-
- environ = nenv;
- (void) execvp (*argv, argv);
-
- fprintf (stderr, "%s: cannot execute `%s': %s\n",
- progname, *argv, strerror (errno));
- exit (errno != 0 ? errno : 1);
- }
-}
-
-void
-setenv (var, val)
- register char *var, *val;
-{
- register char **e;
- int len = strlen (var);
-
- {
- register char *tem = myindex (var, '=');
- if (tem)
- fatal ("environment variable names can 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 ("virtual memory exhausted");
-}
-
-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;
-}
-
-/* Return a pointer to the first occurrence in STR of C,
- or 0 if C does not occur. */
-
-char *
-myindex (str, c)
- char *str;
- char c;
-{
- char *s = str;
-
- while (*s)
- {
- if (*s == c)
- return s;
- s++;
- }
- return 0;
-}
-
-#ifndef HAVE_STRERROR
-char *
-strerror (errnum)
- int errnum;
-{
- extern char *sys_errlist[];
- extern int sys_nerr;
-
- if (errnum >= 0 && errnum < sys_nerr)
- return sys_errlist[errnum];
- return (char *) "Unknown error";
-}
-
-#endif /* ! HAVE_STRERROR */
diff --git a/lib-src/etags.c b/lib-src/etags.c
deleted file mode 100644
index 0120226b38c..00000000000
--- a/lib-src/etags.c
+++ /dev/null
@@ -1,4577 +0,0 @@
-/* Tags file maker to go with GNU Emacs
- Copyright (C) 1984, 87, 88, 89, 93, 94, 95
- Free Software Foundation, Inc. and Ken Arnold
-
-This file is not considered 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 2 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/*
- * Authors:
- * Ctags originally by Ken Arnold.
- * Fortran added by Jim Kleckner.
- * Ed Pelegri-Llopart added C typedefs.
- * Gnu Emacs TAGS format and modifications by RMS?
- * Sam Kendall added C++.
- * Francesco Potorti` reorganised C and C++ based on work by Joe Wells.
- * Regexp tags by Tom Tromey.
- *
- * Francesco Potorti` (F.Potorti@cnuce.cnr.it) is the current maintainer.
- */
-
-char pot_etags_version[] = "@(#) pot revision number is 11.80";
-
-#define TRUE 1
-#define FALSE 0
-
-#ifndef DEBUG
-# define DEBUG FALSE
-#endif
-
-#ifdef MSDOS
-# include <string.h>
-# include <fcntl.h>
-# include <sys/param.h>
-#endif /* MSDOS */
-
-#ifdef WINDOWSNT
-# include <stdlib.h>
-# include <fcntl.h>
-# include <string.h>
-# include <io.h>
-# define MAXPATHLEN _MAX_PATH
-#endif
-
-#if !defined (MSDOS) && !defined (WINDOWSNT) && defined (STDC_HEADERS)
-#include <stdlib.h>
-#include <string.h>
-#endif
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
- /* On some systems, Emacs defines static as nothing for the sake
- of unexec. We don't want that here since we don't use unexec. */
-# undef static
-#endif
-
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-#ifndef errno
-extern int errno;
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#if !defined (S_ISREG) && defined (S_IFREG)
-# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#endif
-
-#include <getopt.h>
-
-#ifdef ETAGS_REGEXPS
-# include <regex.h>
-#endif /* ETAGS_REGEXPS */
-
-/* Define CTAGS to make the program "ctags" compatible with the usual one.
- Let it undefined to make the program "etags", which makes emacs-style
- tag tables and tags typedefs, #defines and struct/union/enum by default. */
-#ifdef CTAGS
-# undef CTAGS
-# define CTAGS TRUE
-#else
-# define CTAGS FALSE
-#endif
-
-/* Exit codes for success and failure. */
-#ifdef VMS
-# define GOOD 1
-# define BAD 0
-#else
-# define GOOD 0
-# define BAD 1
-#endif
-
-/* C extensions. */
-#define C_PLPL 0x00001 /* C++ */
-#define C_STAR 0x00003 /* C* */
-#define YACC 0x10000 /* yacc file */
-
-#define streq(s,t) ((DEBUG && (s) == NULL && (t) == NULL \
- && (abort (), 1)) || !strcmp (s, t))
-#define strneq(s,t,n) ((DEBUG && (s) == NULL && (t) == NULL \
- && (abort (), 1)) || !strncmp (s, t, n))
-
-#define lowcase(c) tolower ((char)c)
-
-#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 */
-
-#ifdef DOS_NT
-# define absolutefn(fn) (fn[0] == '/' \
- || (fn[1] == ':' && fn[2] == '/'))
-#else
-# define absolutefn(fn) (fn[0] == '/')
-#endif
-
-
-/*
- * xnew -- allocate storage
- *
- * SYNOPSIS: Type *xnew (int n, Type);
- */
-#define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
-
-typedef int logical;
-
-typedef struct nd_st
-{ /* sorting structure */
- char *name; /* function or type name */
- char *file; /* file name */
- logical is_func; /* use pattern or line no */
- logical been_warned; /* set if noticed dup */
- int lno; /* line number tag is on */
- long cno; /* character number line starts on */
- char *pat; /* search pattern */
- struct nd_st *left, *right; /* left and right sons */
-} NODE;
-
-extern char *getenv ();
-
-char *concat ();
-char *savenstr (), *savestr ();
-char *etags_strchr (), *etags_strrchr ();
-char *etags_getcwd ();
-char *relative_filename (), *absolute_filename (), *absolute_dirname ();
-void grow_linebuffer ();
-long *xmalloc (), *xrealloc ();
-
-typedef void Lang_function ();
-#if FALSE /* many compilers barf on this */
-Lang_function Asm_labels;
-Lang_function default_C_entries;
-Lang_function C_entries;
-Lang_function Cplusplus_entries;
-Lang_function Cstar_entries;
-Lang_function Erlang_functions;
-Lang_function Fortran_functions;
-Lang_function Yacc_entries;
-Lang_function Lisp_functions;
-Lang_function Pascal_functions;
-Lang_function Perl_functions;
-Lang_function Prolog_functions;
-Lang_function Scheme_functions;
-Lang_function TeX_functions;
-Lang_function just_read_file;
-#else /* so let's write it this way */
-void Asm_labels ();
-void C_entries ();
-void default_C_entries ();
-void plain_C_entries ();
-void Cplusplus_entries ();
-void Cstar_entries ();
-void Erlang_functions ();
-void Fortran_functions ();
-void Yacc_entries ();
-void Lisp_functions ();
-void Pascal_functions ();
-void Perl_functions ();
-void Prolog_functions ();
-void Scheme_functions ();
-void TeX_functions ();
-void just_read_file ();
-#endif
-
-Lang_function *get_language_from_name ();
-Lang_function *get_language_from_interpreter ();
-Lang_function *get_language_from_suffix ();
-int total_size_of_entries ();
-long readline ();
-long readline_internal ();
-#ifdef ETAGS_REGEXPS
-void add_regex ();
-#endif
-void add_node ();
-void error ();
-void suggest_asking_for_help ();
-void fatal (), pfatal ();
-void find_entries ();
-void free_tree ();
-void getit ();
-void init ();
-void initbuffer ();
-void pfnote ();
-void process_file ();
-void put_entries ();
-void takeprec ();
-
-
-char searchar = '/'; /* use /.../ searches */
-
-int lineno; /* line number of current line */
-long charno; /* current character number */
-long linecharno; /* charno of start of line */
-
-char *curfile; /* current input file name */
-char *tagfile; /* output file */
-char *progname; /* name this program was invoked with */
-char *cwd; /* current working directory */
-char *tagfiledir; /* directory of tagfile */
-
-FILE *tagf; /* ioptr for tags file */
-NODE *head; /* the head of the binary tree of tags */
-
-/*
- * 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; /* the current line */
-struct linebuffer token_name; /* used by C_entries as a temporary area */
-struct
-{
- long linepos;
- struct linebuffer lb; /* used by C_entries instead of lb */
-} lbs[2];
-
-/* boolean "functions" (see init) */
-logical _wht[0177], _etk[0177], _itk[0177], _btk[0177];
-char
- /* white chars */
- *white = " \f\t\n\013",
- /* token ending chars */
- *endtk = " \t\n\013\"'#()[]{}=-+%*/&|^~!<>;,.:?",
- /* token starting chars */
- *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
- /* valid in-token chars */
- *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
-
-logical append_to_tagfile; /* -a: append to tags */
-/* The following three default to TRUE for etags, but to FALSE for ctags. */
-logical typedefs; /* -t: create tags for typedefs */
-logical typedefs_and_cplusplus; /* -T: create tags for typedefs, level */
- /* 0 struct/enum/union decls, and C++ */
- /* member functions. */
-logical constantypedefs; /* -d: create tags for C #define and enum */
- /* constants. */
- /* -D: opposite of -d. Default under ctags. */
-logical update; /* -u: update tags */
-logical vgrind_style; /* -v: create vgrind style index output */
-logical no_warnings; /* -w: suppress warnings */
-logical cxref_style; /* -x: create cxref style output */
-logical cplusplus; /* .[hc] means C++, not C */
-logical noindentypedefs; /* -I: ignore indentation in C */
-
-struct option longopts[] =
-{
- { "append", no_argument, NULL, 'a' },
- { "backward-search", no_argument, NULL, 'B' },
- { "c++", no_argument, NULL, 'C' },
- { "cxref", no_argument, NULL, 'x' },
- { "defines", no_argument, NULL, 'd' },
- { "help", no_argument, NULL, 'h' },
- { "help", no_argument, NULL, 'H' },
- { "ignore-indentation", no_argument, NULL, 'I' },
- { "include", required_argument, NULL, 'i' },
- { "language", required_argument, NULL, 'l' },
- { "no-defines", no_argument, NULL, 'D' },
- { "no-regex", no_argument, NULL, 'R' },
- { "no-warn", no_argument, NULL, 'w' },
- { "output", required_argument, NULL, 'o' },
- { "regex", required_argument, NULL, 'r' },
- { "typedefs", no_argument, NULL, 't' },
- { "typedefs-and-c++", no_argument, NULL, 'T' },
- { "update", no_argument, NULL, 'u' },
- { "version", no_argument, NULL, 'V' },
- { "vgrind", no_argument, NULL, 'v' },
- { 0 }
-};
-
-#ifdef ETAGS_REGEXPS
-/* Structure defining a regular expression. Elements are
- the compiled pattern, and the name string. */
-struct pattern
-{
- struct re_pattern_buffer *pattern;
- struct re_registers regs;
- char *name_pattern;
- logical error_signaled;
-};
-
-/* Number of regexps found. */
-int num_patterns = 0;
-
-/* Array of all regexps. */
-struct pattern *patterns = NULL;
-#endif /* ETAGS_REGEXPS */
-
-/*
- * Language stuff.
- */
-
-/* Non-NULL if language fixed. */
-Lang_function *lang_func = NULL;
-
-/* Assembly code */
-char *Asm_suffixes [] = { "a", /* Unix assembler */
- "asm", /* Microcontroller assembly */
- "def", /* BSO/Tasking definition includes */
- "inc", /* Microcontroller include files */
- "ins", /* Microcontroller include files */
- "s", "sa", /* Unix assembler */
- "src", /* BSO/Tasking C compiler output */
- NULL
- };
-
-/* Note that .c and .h can be considered C++, if the --c++ flag was
- given. That is why default_C_entries is called here. */
-char *default_C_suffixes [] =
- { "c", "h", NULL };
-
-/* .M is for Objective C++ files. */
-char *Cplusplus_suffixes [] =
- { "C", "H", "c++", "cc", "cpp", "cxx", "h++", "hh", "hpp", "hxx", "M", NULL};
-
-char *Cstar_suffixes [] =
- { "cs", "hs", NULL };
-
-char *Erlang_suffixes [] =
- { "erl", "hrl", NULL };
-
-char *Fortran_suffixes [] =
- { "F", "f", "f90", "for", NULL };
-
-char *Lisp_suffixes [] =
- { "cl", "clisp", "el", "l", "lisp", "lsp", "ml", NULL };
-
-char *Pascal_suffixes [] =
- { "p", "pas", NULL };
-
-char *Perl_suffixes [] =
- { "pl", "pm", NULL };
-char *Perl_interpreters [] =
- { "perl", "@PERL@", NULL };
-
-char *plain_C_suffixes [] =
- { "pc", /* Pro*C file */
- "m", /* Objective C file */
- "lm", /* Objective lex file */
- NULL };
-
-char *Prolog_suffixes [] =
- { "prolog", NULL };
-
-/* Can't do the `SCM' or `scm' prefix with a version number. */
-char *Scheme_suffixes [] =
- { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "t", NULL };
-
-char *TeX_suffixes [] =
- { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL };
-
-char *Yacc_suffixes [] =
- { "y", "ym", NULL }; /* .ym is Objective yacc file */
-
-/* Table of language names and corresponding functions, file suffixes
- and interpreter names.
- It is ok for a given function to be listed under more than one
- name. I just didn't. */
-struct lang_entry
-{
- char *name;
- Lang_function *function;
- char **suffixes;
- char **interpreters;
-};
-
-struct lang_entry lang_names [] =
-{
- { "asm", Asm_labels, Asm_suffixes, NULL },
- { "c", default_C_entries, default_C_suffixes, NULL },
- { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL },
- { "c*", Cstar_entries, Cstar_suffixes, NULL },
- { "erlang", Erlang_functions, Erlang_suffixes, NULL },
- { "fortran", Fortran_functions, Fortran_suffixes, NULL },
- { "lisp", Lisp_functions, Lisp_suffixes, NULL },
- { "pascal", Pascal_functions, Pascal_suffixes, NULL },
- { "perl", Perl_functions, Perl_suffixes, Perl_interpreters },
- { "proc", plain_C_entries, plain_C_suffixes, NULL },
- { "prolog", Prolog_functions, Prolog_suffixes, NULL },
- { "scheme", Scheme_functions, Scheme_suffixes, NULL },
- { "tex", TeX_functions, TeX_suffixes, NULL },
- { "yacc", Yacc_entries, Yacc_suffixes, NULL },
- { "auto", NULL }, /* default guessing scheme */
- { "none", just_read_file }, /* regexp matching only */
- { NULL, NULL } /* end of list */
-};
-
-
-void
-print_language_names ()
-{
- struct lang_entry *lang;
- char **ext;
-
- puts ("\nThese are the currently supported languages, along with the\n\
-default file name suffixes:");
- for (lang = lang_names; lang->name != NULL; lang++)
- {
- printf ("\t%s\t", lang->name);
- if (lang->suffixes != NULL)
- for (ext = lang->suffixes; *ext != NULL; ext++)
- printf (" .%s", *ext);
- puts ("");
- }
- puts ("Where `auto' means use default language for files based on file\n\
-name suffix, and `none' means only do regexp processing on files.\n\
-If no language is specified and no matching suffix is found,\n\
-the first line of the file is read for a sharp-bang (#!) sequence\n\
-followed by the name of an interpreter. If no such sequence is found,\n\
-Fortran is tried first; if no tags are found, C is tried next.");
-}
-
-#ifndef VERSION
-# define VERSION "19"
-#endif
-void
-print_version ()
-{
- printf ("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION);
- puts ("Copyright (C) 1996 Free Software Foundation, Inc. and Ken Arnold");
- puts ("This program is distributed under the same terms as Emacs");
-
- exit (GOOD);
-}
-
-void
-print_help ()
-{
- printf ("These are the options accepted by %s. You may use unambiguous\n\
-abbreviations for the long option names. A - as file name means read\n\
-names from stdin.", progname);
- if (!CTAGS)
- printf (" Absolute names are stored in the output file as they\n\
-are. Relative ones are stored relative to the output file's directory.");
- puts ("\n");
-
- puts ("-a, --append\n\
- Append tag entries to existing tags file.");
-
- if (CTAGS)
- puts ("-B, --backward-search\n\
- Write the search commands for the tag entries using '?', the\n\
- backward-search command instead of '/', the forward-search command.");
-
- puts ("-C, --c++\n\
- Treat files whose name suffix defaults to C language as C++ files.");
-
- if (CTAGS)
- puts ("-d, --defines\n\
- Create tag entries for C #define constants and enum constants, too.");
- else
- puts ("-D, --no-defines\n\
- Don't create tag entries for C #define constants and enum constants.\n\
- This makes the tags file smaller.");
-
- if (!CTAGS)
- {
- puts ("-i FILE, --include=FILE\n\
- Include a note in tag file indicating that, when searching for\n\
- a tag, one should also consult the tags file FILE after\n\
- checking the current file.");
- puts ("-l LANG, --language=LANG\n\
- Force the following files to be considered as written in the\n\
- named language up to the next --language=LANG option.");
- }
-
-#ifdef ETAGS_REGEXPS
- puts ("-r /REGEXP/, --regex=/REGEXP/\n\
- Make a tag for each line matching pattern REGEXP in the\n\
- following files. REGEXP is anchored (as if preceded by ^).\n\
- The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
- named tags can be created with:\n\
- --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
- puts ("-R, --no-regex\n\
- Don't create tags from regexps for the following files.");
-#endif /* ETAGS_REGEXPS */
- puts ("-o FILE, --output=FILE\n\
- Write the tags to FILE.");
- puts ("-I, --ignore-indentation\n\
- Don't rely on indentation quite as much as normal. Currently,\n\
- this means not to assume that a closing brace in the first\n\
- column is the final brace of a function or structure\n\
- definition in C and C++.");
-
- if (CTAGS)
- {
- puts ("-t, --typedefs\n\
- Generate tag entries for C typedefs.");
- puts ("-T, --typedefs-and-c++\n\
- Generate tag entries for C typedefs, C struct/enum/union tags,\n\
- and C++ member functions.");
- puts ("-u, --update\n\
- Update the tag entries for the given files, leaving tag\n\
- entries for other files in place. Currently, this is\n\
- implemented by deleting the existing entries for the given\n\
- files and then rewriting the new entries at the end of the\n\
- tags file. It is often faster to simply rebuild the entire\n\
- tag file than to use this.");
- puts ("-v, --vgrind\n\
- Generates an index of items intended for human consumption,\n\
- similar to the output of vgrind. The index is sorted, and\n\
- gives the page number of each item.");
- puts ("-w, --no-warn\n\
- Suppress warning messages about entries defined in multiple\n\
- files.");
- puts ("-x, --cxref\n\
- Like --vgrind, but in the style of cxref, rather than vgrind.\n\
- The output uses line numbers instead of page numbers, but\n\
- beyond that the differences are cosmetic; try both to see\n\
- which you like.");
- }
-
- puts ("-V, --version\n\
- Print the version of the program.\n\
--h, --help\n\
- Print this help message.");
-
- print_language_names ();
-
- puts ("");
- puts ("Report bugs to bug-gnu-emacs@prep.ai.mit.edu");
-
- exit (GOOD);
-}
-
-
-enum argument_type
-{
- at_language,
- at_regexp,
- at_filename
-};
-
-/* This structure helps us allow mixing of --lang and filenames. */
-typedef struct
-{
- enum argument_type arg_type;
- char *what;
- Lang_function *function;
-} argument;
-
-#ifdef VMS /* VMS specific functions */
-
-#define EOS '\0'
-
-/* This is a BUG! ANY arbitrary limit is a BUG!
- Won't someone please fix this? */
-#define MAX_FILE_SPEC_LEN 255
-typedef struct {
- short curlen;
- char body[MAX_FILE_SPEC_LEN + 1];
-} vspec;
-
-/*
- v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
- returning in each successive call the next filename matching the input
- spec. The function expects that each in_spec passed
- to it will be processed to completion; in particular, up to and
- including the call following that in which the last matching name
- is returned, the function ignores the value of in_spec, and will
- only start processing a new spec with the following call.
- If an error occurs, on return out_spec contains the value
- of in_spec when the error occurred.
-
- With each successive filename returned in out_spec, the
- function's return value is one. When there are no more matching
- names the function returns zero. If on the first call no file
- matches in_spec, or there is any other error, -1 is returned.
-*/
-
-#include <rmsdef.h>
-#include <descrip.h>
-#define OUTSIZE MAX_FILE_SPEC_LEN
-short
-fn_exp (out, in)
- vspec *out;
- char *in;
-{
- static long context = 0;
- static struct dsc$descriptor_s o;
- static struct dsc$descriptor_s i;
- static logical pass1 = TRUE;
- long status;
- short retval;
-
- if (pass1)
- {
- pass1 = FALSE;
- o.dsc$a_pointer = (char *) out;
- o.dsc$w_length = (short)OUTSIZE;
- i.dsc$a_pointer = in;
- i.dsc$w_length = (short)strlen(in);
- i.dsc$b_dtype = DSC$K_DTYPE_T;
- i.dsc$b_class = DSC$K_CLASS_S;
- o.dsc$b_dtype = DSC$K_DTYPE_VT;
- o.dsc$b_class = DSC$K_CLASS_VS;
- }
- if ((status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL)
- {
- out->body[out->curlen] = EOS;
- return 1;
- }
- else if (status == RMS$_NMF)
- retval = 0;
- else
- {
- strcpy(out->body, in);
- retval = -1;
- }
- lib$find_file_end(&context);
- pass1 = TRUE;
- return retval;
-}
-
-/*
- v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
- name of each file specified by the provided arg expanding wildcards.
-*/
-char *
-gfnames (arg, p_error)
- char *arg;
- logical *p_error;
-{
- static vspec filename = {MAX_FILE_SPEC_LEN, "\0"};
-
- switch (fn_exp (&filename, arg))
- {
- case 1:
- *p_error = FALSE;
- return filename.body;
- case 0:
- *p_error = FALSE;
- return NULL;
- default:
- *p_error = TRUE;
- return filename.body;
- }
-}
-
-#ifndef OLD /* Newer versions of VMS do provide `system'. */
-system (cmd)
- char *cmd;
-{
- fprintf (stderr, "system() function not implemented under VMS\n");
-}
-#endif
-
-#define VERSION_DELIM ';'
-char *massage_name (s)
- char *s;
-{
- char *start = s;
-
- for ( ; *s; s++)
- if (*s == VERSION_DELIM)
- {
- *s = EOS;
- break;
- }
- else
- *s = lowcase (*s);
- return start;
-}
-#endif /* VMS */
-
-
-int
-main (argc, argv)
- int argc;
- char *argv[];
-{
- int i;
- unsigned int nincluded_files = 0;
- char **included_files = xnew (argc, char *);
- char *this_file;
- argument *argbuffer;
- int current_arg = 0, file_count = 0;
- struct linebuffer filename_lb;
-#ifdef VMS
- logical got_err;
-#endif
-
-#ifdef DOS_NT
- _fmode = O_BINARY; /* all of files are treated as binary files */
-#endif /* DOS_NT */
-
- progname = argv[0];
-
- /* Allocate enough no matter what happens. Overkill, but each one
- is small. */
- argbuffer = xnew (argc, argument);
-
-#ifdef ETAGS_REGEXPS
- /* Set syntax for regular expression routines. */
- re_set_syntax (RE_SYNTAX_EMACS);
-#endif /* ETAGS_REGEXPS */
-
- /*
- * If etags, always find typedefs and structure tags. Why not?
- * Also default is to find macro constants and enum constants.
- */
- if (!CTAGS)
- typedefs = typedefs_and_cplusplus = constantypedefs = TRUE;
-
- while (1)
- {
- int opt = getopt_long (argc, argv,
- "-aCdDf:Il:o:r:RStTi:BuvxwVhH", longopts, 0);
-
- if (opt == EOF)
- break;
-
- switch (opt)
- {
- case 0:
- /* If getopt returns 0, then it has already processed a
- long-named option. We should do nothing. */
- break;
-
- case 1:
- /* This means that a filename has been seen. Record it. */
- argbuffer[current_arg].arg_type = at_filename;
- argbuffer[current_arg].what = optarg;
- ++current_arg;
- ++file_count;
- break;
-
- /* Common options. */
- case 'a':
- append_to_tagfile = TRUE;
- break;
- case 'C':
- cplusplus = TRUE;
- break;
- case 'd':
- constantypedefs = TRUE;
- break;
- case 'D':
- constantypedefs = FALSE;
- break;
- case 'f': /* for compatibility with old makefiles */
- case 'o':
- if (tagfile)
- {
- fprintf (stderr, "%s: -%c option may only be given once.\n",
- progname, opt);
- suggest_asking_for_help ();
- }
- tagfile = optarg;
- break;
- case 'I':
- case 'S': /* for backward compatibility */
- noindentypedefs = TRUE;
- break;
- case 'l':
- argbuffer[current_arg].function = get_language_from_name (optarg);
- argbuffer[current_arg].arg_type = at_language;
- ++current_arg;
- break;
-#ifdef ETAGS_REGEXPS
- case 'r':
- argbuffer[current_arg].arg_type = at_regexp;
- argbuffer[current_arg].what = optarg;
- ++current_arg;
- break;
- case 'R':
- argbuffer[current_arg].arg_type = at_regexp;
- argbuffer[current_arg].what = NULL;
- ++current_arg;
- break;
-#endif /* ETAGS_REGEXPS */
- case 'V':
- print_version ();
- break;
- case 'h':
- case 'H':
- print_help ();
- break;
- case 't':
- typedefs = TRUE;
- break;
- case 'T':
- typedefs = typedefs_and_cplusplus = TRUE;
- break;
-#if (!CTAGS)
- /* Etags options */
- case 'i':
- included_files[nincluded_files++] = optarg;
- break;
-#else /* CTAGS */
- /* Ctags options. */
- case 'B':
- searchar = '?';
- break;
- case 'u':
- update = TRUE;
- break;
- case 'v':
- vgrind_style = TRUE;
- /*FALLTHRU*/
- case 'x':
- cxref_style = TRUE;
- break;
- case 'w':
- no_warnings = TRUE;
- break;
-#endif /* CTAGS */
- default:
- suggest_asking_for_help ();
- }
- }
-
- for (; optind < argc; ++optind)
- {
- argbuffer[current_arg].arg_type = at_filename;
- argbuffer[current_arg].what = argv[optind];
- ++current_arg;
- ++file_count;
- }
-
- if (nincluded_files == 0 && file_count == 0)
- {
- fprintf (stderr, "%s: No input files specified.\n", progname);
- suggest_asking_for_help ();
- }
-
- if (tagfile == NULL)
- tagfile = CTAGS ? "tags" : "TAGS";
- cwd = etags_getcwd (); /* the current working directory */
- if (cwd[strlen (cwd) - 1] != '/')
- cwd = concat (cwd, "/", "");
- if (streq (tagfile, "-"))
- tagfiledir = cwd;
- else
- tagfiledir = absolute_dirname (tagfile, cwd);
-
- init (); /* set up boolean "functions" */
-
- initbuffer (&lb);
- initbuffer (&token_name);
- initbuffer (&lbs[0].lb);
- initbuffer (&lbs[1].lb);
- initbuffer (&filename_lb);
-
- if (!CTAGS)
- {
- if (streq (tagfile, "-"))
- {
- tagf = stdout;
-#ifdef DOS_NT
- /* Switch redirected `stdout' to binary mode (setting `_fmode'
- doesn't take effect until after `stdout' is already open). */
- if (!isatty (fileno (stdout)))
- setmode (fileno (stdout), O_BINARY);
-#endif /* DOS_NT */
- }
- else
- tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
- if (tagf == NULL)
- pfatal (tagfile);
- }
-
- /*
- * Loop through files finding functions.
- */
- for (i = 0; i < current_arg; ++i)
- {
- switch (argbuffer[i].arg_type)
- {
- case at_language:
- lang_func = argbuffer[i].function;
- break;
-#ifdef ETAGS_REGEXPS
- case at_regexp:
- add_regex (argbuffer[i].what);
- break;
-#endif
- case at_filename:
-#ifdef VMS
- while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL)
- {
- if (got_err)
- {
- error ("Can't find file %s\n", this_file);
- argc--, argv++;
- }
- else
- {
- this_file = massage_name (this_file);
- }
-#else
- this_file = argbuffer[i].what;
-#endif
- /* Input file named "-" means read file names from stdin
- and use them. */
- if (streq (this_file, "-"))
- while (readline_internal (&filename_lb, stdin) > 0)
- process_file (filename_lb.buffer);
- else
- process_file (this_file);
-#ifdef VMS
- }
-#endif
- break;
- }
- }
-
- if (!CTAGS)
- {
- while (nincluded_files-- > 0)
- fprintf (tagf, "\f\n%s,include\n", *included_files++);
-
- fclose (tagf);
- exit (GOOD);
- }
-
- /* If CTAGS, we are here. process_file did not write the tags yet,
- because we want them ordered. Let's do it now. */
- if (cxref_style)
- {
- put_entries (head);
- exit (GOOD);
- }
-
- if (update)
- {
- char cmd[BUFSIZ];
- for (i = 0; i < current_arg; ++i)
- {
- if (argbuffer[i].arg_type != at_filename)
- continue;
- sprintf (cmd,
- "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
- tagfile, argbuffer[i].what, tagfile);
- if (system (cmd) != GOOD)
- fatal ("failed to execute shell command", (char *)NULL);
- }
- append_to_tagfile = TRUE;
- }
-
- tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
- if (tagf == NULL)
- pfatal (tagfile);
- put_entries (head);
- fclose (tagf);
-
- if (update)
- {
- char cmd[BUFSIZ];
- sprintf (cmd, "sort %s -o %s", tagfile, tagfile);
- exit (system (cmd));
- }
- return GOOD;
-}
-
-
-/*
- * Return a Lang_function given the name.
- */
-Lang_function *
-get_language_from_name (name)
- char *name;
-{
- struct lang_entry *lang;
-
- if (name != NULL)
- for (lang = lang_names; lang->name != NULL; lang++)
- {
- if (streq (name, lang->name))
- return lang->function;
- }
-
- fprintf (stderr, "%s: language \"%s\" not recognized.\n",
- progname, optarg);
- suggest_asking_for_help ();
-
- /* This point should never be reached. The function should either
- return a function pointer or never return. Note that a NULL
- pointer cannot be considered as an error, as it means that the
- language has not been explicitely imposed by the user ("auto"). */
- return NULL; /* avoid warnings from compiler */
-}
-
-
-/*
- * Return a Lang_function given the interpreter name.
- */
-Lang_function *
-get_language_from_interpreter (interpreter)
- char *interpreter;
-{
- struct lang_entry *lang;
- char **iname;
-
- if (interpreter == NULL)
- return NULL;
- for (lang = lang_names; lang->name != NULL; lang++)
- if (lang->interpreters != NULL)
- for (iname = lang->interpreters; *iname != NULL; iname++)
- if (streq (*iname, interpreter))
- return lang->function;
-
- return NULL;
-}
-
-
-
-/*
- * Return a Lang_function given the file suffix.
- */
-Lang_function *
-get_language_from_suffix (suffix)
- char *suffix;
-{
- struct lang_entry *lang;
- char **ext;
-
- if (suffix == NULL)
- return NULL;
- for (lang = lang_names; lang->name != NULL; lang++)
- if (lang->suffixes != NULL)
- for (ext = lang->suffixes; *ext != NULL; ext++)
- if (streq (*ext, suffix))
- return lang->function;
-
- return NULL;
-}
-
-
-/*
- * This routine is called on each file argument.
- */
-void
-process_file (file)
- char *file;
-{
- struct stat stat_buf;
- FILE *inf;
-#ifdef DOS_NT
- char *p;
-
- for (p = file; *p != '\0'; p++)
- if (*p == '\\')
- *p = '/';
-#endif
-
- if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode))
- {
- fprintf (stderr, "Skipping %s: it is not a regular file.\n", file);
- return;
- }
- if (streq (file, tagfile) && !streq (tagfile, "-"))
- {
- fprintf (stderr, "Skipping inclusion of %s in self.\n", file);
- return;
- }
- inf = fopen (file, "r");
- if (inf == NULL)
- {
- perror (file);
- return;
- }
-
- find_entries (file, inf);
-
- if (!CTAGS)
- {
- char *filename;
-
- if (absolutefn (file))
- {
- /* file is an absolute filename. Canonicalise it. */
- filename = absolute_filename (file, cwd);
- }
- else
- {
- /* file is a filename relative to cwd. Make it relative
- to the directory of the tags file. */
- filename = relative_filename (file, tagfiledir);
- }
- fprintf (tagf, "\f\n%s,%d\n", filename, total_size_of_entries (head));
- free (filename);
- put_entries (head);
- free_tree (head);
- head = NULL;
- }
-}
-
-/*
- * This routine sets up the boolean pseudo-functions which work
- * by setting 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.
- */
-void
-init ()
-{
- register char *sp;
- register int i;
-
- for (i = 0; i < 0177; i++)
- _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
- 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;
- _wht[0] = _wht['\n'];
- _etk[0] = _etk['\n'];
- _btk[0] = _btk['\n'];
- _itk[0] = _itk['\n'];
-}
-
-/*
- * This routine opens the specified file and calls the function
- * which finds the function and type definitions.
- */
-void
-find_entries (file, inf)
- char *file;
- FILE *inf;
-{
- char *cp;
- Lang_function *function;
- NODE *old_last_node;
- extern NODE *last_node;
-
-
- /* Memory leakage here: the memory block pointed by curfile is never
- released. The amount of memory leaked here is the sum of the
- lengths of the input file names. */
- curfile = savestr (file);
-
- /* If user specified a language, use it. */
- function = lang_func;
- if (function != NULL)
- {
- function (inf);
- fclose (inf);
- return;
- }
-
- cp = etags_strrchr (file, '.');
- if (cp != NULL)
- {
- cp += 1;
- function = get_language_from_suffix (cp);
- if (function != NULL)
- {
- function (inf);
- fclose (inf);
- return;
- }
- }
-
- /* Look for sharp-bang as the first two characters. */
- if (readline_internal (&lb, inf) > 2
- && lb.buffer[0] == '#'
- && lb.buffer[1] == '!')
- {
- char *lp;
-
- /* Set lp to point at the first char after the last slash in the
- line or, if no slashes, at the first nonblank. Then set cp to
- the first successive blank and terminate the string. */
- lp = etags_strrchr (lb.buffer+2, '/');
- if (lp != NULL)
- lp += 1;
- else
- for (lp = lb.buffer+2; *lp != '\0' && isspace (*lp); lp++)
- continue;
- for (cp = lp; *cp != '\0' && !isspace (*cp); cp++)
- continue;
- *cp = '\0';
-
- if (strlen (lp) > 0)
- {
- function = get_language_from_interpreter (lp);
- if (function != NULL)
- {
- function (inf);
- fclose (inf);
- return;
- }
- }
- }
- rewind (inf);
-
- /* Try Fortran. */
- old_last_node = last_node;
- Fortran_functions (inf);
-
- /* No Fortran entries found. Try C. */
- if (old_last_node == last_node)
- {
- rewind (inf);
- default_C_entries (inf);
- }
- fclose (inf);
- return;
-}
-
-/* Record a tag. */
-void
-pfnote (name, is_func, linestart, linelen, lno, cno)
- char *name; /* tag name, or NULL if unnamed */
- logical is_func; /* tag is a function */
- char *linestart; /* start of the line where tag is */
- int linelen; /* length of the line where tag is */
- int lno; /* line number */
- long cno; /* character number */
-{
- register NODE *np;
-
- if (CTAGS && name == NULL)
- return;
-
- np = xnew (1, NODE);
-
- /* If ctags mode, change name "main" to M<thisfilename>. */
- if (CTAGS && !cxref_style && streq (name, "main"))
- {
- register char *fp = etags_strrchr (curfile, '/');
- np->name = concat ("M", fp == 0 ? curfile : fp + 1, "");
- fp = etags_strrchr (np->name, '.');
- if (fp && fp[1] != '\0' && fp[2] == '\0')
- fp[0] = 0;
- }
- else
- np->name = name;
- np->been_warned = FALSE;
- np->file = curfile;
- np->is_func = is_func;
- np->lno = lno;
- /* Our char numbers are 0-base, because of C language tradition?
- ctags compatibility? old versions compatibility? I don't know.
- Anyway, since emacs's are 1-base we expect etags.el to take care
- of the difference. If we wanted to have 1-based numbers, we would
- uncomment the +1 below. */
- np->cno = cno /* + 1 */ ;
- np->left = np->right = NULL;
- if (CTAGS && !cxref_style)
- {
- if (strlen (linestart) < 50)
- np->pat = concat (linestart, "$", "");
- else
- np->pat = savenstr (linestart, 50);
- }
- else
- np->pat = savenstr (linestart, linelen);
-
- add_node (np, &head);
-}
-
-/*
- * free_tree ()
- * recurse on left children, iterate on right children.
- */
-void
-free_tree (node)
- register NODE *node;
-{
- while (node)
- {
- register NODE *node_right = node->right;
- free_tree (node->left);
- if (node->name != NULL)
- free (node->name);
- free (node->pat);
- free ((char *) node);
- node = node_right;
- }
-}
-
-/*
- * add_node ()
- * Adds a node to the tree of nodes. In etags mode, we don't keep
- * it sorted; we just keep a linear list. In ctags mode, maintain
- * an ordered tree, with no attempt at balancing.
- *
- * add_node is the only function allowed to add nodes, so it can
- * maintain state.
- */
-NODE *last_node = NULL;
-void
-add_node (node, cur_node_p)
- NODE *node, **cur_node_p;
-{
- register int dif;
- register NODE *cur_node = *cur_node_p;
-
- if (cur_node == NULL)
- {
- *cur_node_p = node;
- last_node = node;
- return;
- }
-
- if (!CTAGS)
- {
- /* Etags Mode */
- if (last_node == NULL)
- fatal ("internal error in add_node", (char *)NULL);
- last_node->right = node;
- last_node = node;
- }
- else
- {
- /* Ctags Mode */
- dif = strcmp (node->name, cur_node->name);
-
- /*
- * If this tag name matches an existing one, then
- * do not add the node, but maybe print a warning.
- */
- if (!dif)
- {
- if (streq (node->file, cur_node->file))
- {
- if (!no_warnings)
- {
- fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
- node->file, lineno, node->name);
- fprintf (stderr, "Second entry ignored\n");
- }
- }
- else if (!cur_node->been_warned && !no_warnings)
- {
- fprintf
- (stderr,
- "Duplicate entry in files %s and %s: %s (Warning only)\n",
- node->file, cur_node->file, node->name);
- cur_node->been_warned = TRUE;
- }
- return;
- }
-
- /* Actually add the node */
- add_node (node, dif < 0 ? &cur_node->left : &cur_node->right);
- }
-}
-
-void
-put_entries (node)
- register NODE *node;
-{
- register char *sp;
-
- if (node == NULL)
- return;
-
- /* Output subentries that precede this one */
- put_entries (node->left);
-
- /* Output this entry */
-
- if (!CTAGS)
- {
- if (node->name != NULL)
- fprintf (tagf, "%s\177%s\001%d,%d\n",
- node->pat, node->name, node->lno, node->cno);
- else
- fprintf (tagf, "%s\177%d,%d\n",
- node->pat, node->lno, node->cno);
- }
- else
- {
- if (node->name == NULL)
- error ("internal error: NULL name in ctags mode.", (char *)NULL);
-
- if (cxref_style)
- {
- if (vgrind_style)
- fprintf (stdout, "%s %s %d\n",
- node->name, node->file, (node->lno + 63) / 64);
- else
- fprintf (stdout, "%-16s %3d %-16s %s\n",
- node->name, node->lno, node->file, node->pat);
- }
- else
- {
- fprintf (tagf, "%s\t%s\t", node->name, node->file);
-
- if (node->is_func)
- { /* a function */
- putc (searchar, tagf);
- putc ('^', tagf);
-
- for (sp = node->pat; *sp; sp++)
- {
- if (*sp == '\\' || *sp == searchar)
- putc ('\\', tagf);
- putc (*sp, tagf);
- }
- putc (searchar, tagf);
- }
- else
- { /* a typedef; text pattern inadequate */
- fprintf (tagf, "%d", node->lno);
- }
- putc ('\n', tagf);
- }
- }
-
- /* Output subentries that follow this one */
- put_entries (node->right);
-}
-
-/* Length of a number's decimal representation. */
-int
-number_len (num)
- long num;
-{
- int len = 0;
- if (!num)
- return 1;
- for (; num; num /= 10)
- ++len;
- return len;
-}
-
-/*
- * Return total number of characters that put_entries will output for
- * the nodes in the subtree of the specified node. Works only if
- * we are not ctags, but called only in that case. This count
- * is irrelevant with the new tags.el, but is still supplied for
- * backward compatibility.
- */
-int
-total_size_of_entries (node)
- register NODE *node;
-{
- register int total;
-
- if (node == NULL)
- return 0;
-
- total = 0;
- for (; node; node = node->right)
- {
- /* Count left subentries. */
- total += total_size_of_entries (node->left);
-
- /* Count this entry */
- total += strlen (node->pat) + 1;
- total += number_len ((long) node->lno) + 1 + number_len (node->cno) + 1;
- if (node->name != NULL)
- total += 1 + strlen (node->name); /* \001name */
- }
-
- return total;
-}
-
-/*
- * The C symbol tables.
- */
-enum sym_type
-{
- st_none, st_C_objprot, st_C_objimpl, st_C_objend, st_C_gnumacro,
- st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
-};
-
-/* Feed stuff between (but not including) %[ and %] lines to:
- gperf -c -k 1,3 -o -p -r -t
-%[
-struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
-%%
-@interface, 0, st_C_objprot
-@protocol, 0, st_C_objprot
-@implementation,0, st_C_objimpl
-@end, 0, st_C_objend
-class, C_PLPL, st_C_struct
-namespace, C_PLPL, st_C_struct
-domain, C_STAR, st_C_struct
-union, 0, st_C_struct
-struct, 0, st_C_struct
-enum, 0, st_C_enum
-typedef, 0, st_C_typedef
-define, 0, st_C_define
-bool, C_PLPL, st_C_typespec
-long, 0, st_C_typespec
-short, 0, st_C_typespec
-int, 0, st_C_typespec
-char, 0, st_C_typespec
-float, 0, st_C_typespec
-double, 0, st_C_typespec
-signed, 0, st_C_typespec
-unsigned, 0, st_C_typespec
-auto, 0, st_C_typespec
-void, 0, st_C_typespec
-extern, 0, st_C_typespec
-static, 0, st_C_typespec
-const, 0, st_C_typespec
-volatile, 0, st_C_typespec
-explicit, C_PLPL, st_C_typespec
-mutable, C_PLPL, st_C_typespec
-typename, C_PLPL, st_C_typespec
-# DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
-DEFUN, 0, st_C_gnumacro
-SYSCALL, 0, st_C_gnumacro
-ENTRY, 0, st_C_gnumacro
-PSEUDO, 0, st_C_gnumacro
-# These are defined inside C functions, so currently they are not met.
-# EXFUN used in glibc, DEFVAR_* in emacs.
-#EXFUN, 0, st_C_gnumacro
-#DEFVAR_, 0, st_C_gnumacro
-%]
-and replace lines between %< and %> with its output. */
-/*%<*/
-/* C code produced by gperf version 2.1 (K&R C version) */
-/* Command-line: gperf -c -k 1,3 -o -p -r -t */
-
-
-struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
-
-#define MIN_WORD_LENGTH 3
-#define MAX_WORD_LENGTH 15
-#define MIN_HASH_VALUE 34
-#define MAX_HASH_VALUE 121
-/*
- 34 keywords
- 88 is the maximum key range
-*/
-
-static int
-hash (str, len)
- register char *str;
- register unsigned int len;
-{
- static unsigned char hash_table[] =
- {
- 121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
- 121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
- 121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
- 121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
- 121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
- 121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
- 121, 121, 121, 121, 45, 121, 121, 121, 16, 19,
- 61, 121, 121, 121, 121, 121, 121, 121, 121, 121,
- 10, 121, 121, 20, 53, 121, 121, 121, 121, 121,
- 121, 121, 121, 121, 121, 121, 121, 41, 45, 22,
- 60, 47, 37, 28, 121, 55, 121, 121, 20, 14,
- 29, 30, 5, 121, 50, 59, 30, 54, 6, 121,
- 121, 121, 121, 121, 121, 121, 121, 121,
- };
- return len + hash_table[str[2]] + hash_table[str[0]];
-}
-
-struct C_stab_entry *
-in_word_set (str, len)
- register char *str;
- register unsigned int len;
-{
-
- static struct C_stab_entry wordlist[] =
- {
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"volatile", 0, st_C_typespec},
- {"PSEUDO", 0, st_C_gnumacro},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"typedef", 0, st_C_typedef},
- {"typename", C_PLPL, st_C_typespec},
- {"",}, {"",}, {"",},
- {"SYSCALL", 0, st_C_gnumacro},
- {"",}, {"",}, {"",},
- {"mutable", C_PLPL, st_C_typespec},
- {"namespace", C_PLPL, st_C_struct},
- {"long", 0, st_C_typespec},
- {"",}, {"",},
- {"const", 0, st_C_typespec},
- {"",}, {"",}, {"",},
- {"explicit", C_PLPL, st_C_typespec},
- {"",}, {"",}, {"",}, {"",},
- {"void", 0, st_C_typespec},
- {"",},
- {"char", 0, st_C_typespec},
- {"class", C_PLPL, st_C_struct},
- {"",}, {"",}, {"",},
- {"float", 0, st_C_typespec},
- {"",},
- {"@implementation", 0, st_C_objimpl},
- {"auto", 0, st_C_typespec},
- {"",},
- {"ENTRY", 0, st_C_gnumacro},
- {"@end", 0, st_C_objend},
- {"bool", C_PLPL, st_C_typespec},
- {"domain", C_STAR, st_C_struct},
- {"",},
- {"DEFUN", 0, st_C_gnumacro},
- {"extern", 0, st_C_typespec},
- {"@interface", 0, st_C_objprot},
- {"",}, {"",}, {"",},
- {"int", 0, st_C_typespec},
- {"",}, {"",}, {"",}, {"",},
- {"signed", 0, st_C_typespec},
- {"short", 0, st_C_typespec},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"define", 0, st_C_define},
- {"@protocol", 0, st_C_objprot},
- {"enum", 0, st_C_enum},
- {"static", 0, st_C_typespec},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"union", 0, st_C_struct},
- {"struct", 0, st_C_struct},
- {"",}, {"",}, {"",}, {"",},
- {"double", 0, st_C_typespec},
- {"unsigned", 0, st_C_typespec},
- };
-
- if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
- {
- register int key = hash (str, len);
-
- if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)
- {
- register char *s = wordlist[key].name;
-
- if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
- return &wordlist[key];
- }
- }
- return 0;
-}
-/*%>*/
-
-enum sym_type
-C_symtype (str, len, c_ext)
- char *str;
- int len;
- int c_ext;
-{
- register struct C_stab_entry *se = in_word_set (str, len);
-
- if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
- return st_none;
- return se->type;
-}
-
- /*
- * C functions are recognized using a simple finite automaton.
- * funcdef is its state variable.
- */
-enum
-{
- fnone, /* nothing seen */
- ftagseen, /* function-like tag seen */
- fstartlist, /* just after open parenthesis */
- finlist, /* in parameter list */
- flistseen, /* after parameter list */
- fignore /* before open brace */
-} funcdef;
-
-
- /*
- * typedefs are recognized using a simple finite automaton.
- * typdef is its state variable.
- */
-enum
-{
- tnone, /* nothing seen */
- ttypedseen, /* typedef keyword seen */
- tinbody, /* inside typedef body */
- tend, /* just before typedef tag */
- tignore /* junk after typedef tag */
-} typdef;
-
-
- /*
- * struct-like structures (enum, struct and union) are recognized
- * using another simple finite automaton. `structdef' is its state
- * variable.
- */
-enum
-{
- snone, /* nothing seen yet */
- skeyseen, /* struct-like keyword seen */
- stagseen, /* struct-like tag seen */
- scolonseen, /* colon seen after struct-like tag */
- sinbody /* in struct body: recognize member func defs*/
-} structdef;
-
-/*
- * When structdef is stagseen, scolonseen, or sinbody, structtag is the
- * struct tag, and structtype is the type of the preceding struct-like
- * keyword.
- */
-char *structtag = "<uninited>";
-enum sym_type structtype;
-
-/*
- * When objdef is different from onone, objtag is the name of the class.
- */
-char *objtag = "<uninited>";
-
-/*
- * Yet another little state machine to deal with preprocessor lines.
- */
-enum
-{
- dnone, /* nothing seen */
- dsharpseen, /* '#' seen as first char on line */
- ddefineseen, /* '#' and 'define' seen */
- dignorerest /* ignore rest of line */
-} definedef;
-
-/*
- * State machine for Objective C protocols and implementations.
- */
-enum
-{
- onone, /* nothing seen */
- oprotocol, /* @interface or @protocol seen */
- oimplementation, /* @implementations seen */
- otagseen, /* class name seen */
- oparenseen, /* parenthesis before category seen */
- ocatseen, /* category name seen */
- oinbody, /* in @implementation body */
- omethodsign, /* in @implementation body, after +/- */
- omethodtag, /* after method name */
- omethodcolon, /* after method colon */
- omethodparm, /* after method parameter */
- oignore /* wait for @end */
-} objdef;
-
-/*
- * Set this to TRUE, and the next token considered is called a function.
- * Used only for GNU emacs's function-defining macros.
- */
-logical next_token_is_func;
-
-/*
- * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
- */
-logical yacc_rules;
-
-/*
- * methodlen is the length of the method name stored in token_name.
- */
-int methodlen;
-
-/*
- * consider_token ()
- * checks to see if the current token is at the start of a
- * function, or corresponds to a typedef, or is a struct/union/enum
- * tag, or #define, or an enum constant.
- *
- * *IS_FUNC gets TRUE iff the token is a function or #define macro
- * with args. C_EXT is which language we are looking at.
- *
- * In the future we will need some way to adjust where the end of
- * the token is; for instance, implementing the C++ keyword
- * `operator' properly will adjust the end of the token to be after
- * whatever follows `operator'.
- *
- * Globals
- * funcdef IN OUT
- * structdef IN OUT
- * definedef IN OUT
- * typdef IN OUT
- * objdef IN OUT
- * next_token_is_func IN OUT
- */
-
-logical
-consider_token (str, len, c, c_ext, cblev, parlev, is_func)
- register char *str; /* IN: token pointer */
- register int len; /* IN: token length */
- register char c; /* IN: first char after the token */
- int c_ext; /* IN: C extensions mask */
- int cblev; /* IN: curly brace level */
- int parlev; /* IN: parenthesis level */
- logical *is_func; /* OUT: function found */
-{
- enum sym_type toktype = C_symtype (str, len, c_ext);
-
- /*
- * Advance the definedef state machine.
- */
- switch (definedef)
- {
- case dnone:
- /* We're not on a preprocessor line. */
- break;
- case dsharpseen:
- if (toktype == st_C_define)
- {
- definedef = ddefineseen;
- }
- else
- {
- definedef = dignorerest;
- }
- return FALSE;
- case ddefineseen:
- /*
- * Make a tag for any macro, unless it is a constant
- * and constantypedefs is FALSE.
- */
- definedef = dignorerest;
- *is_func = (c == '(');
- if (!*is_func && !constantypedefs)
- return FALSE;
- else
- return TRUE;
- case dignorerest:
- return FALSE;
- default:
- error ("internal error: definedef value.", (char *)NULL);
- }
-
- /*
- * Now typedefs
- */
- switch (typdef)
- {
- case tnone:
- if (toktype == st_C_typedef)
- {
- if (typedefs)
- typdef = ttypedseen;
- funcdef = fnone;
- return FALSE;
- }
- break;
- case ttypedseen:
- switch (toktype)
- {
- case st_none:
- case st_C_typespec:
- typdef = tend;
- break;
- case st_C_struct:
- case st_C_enum:
- break;
- }
- /* Do not return here, so the structdef stuff has a chance. */
- break;
- case tend:
- switch (toktype)
- {
- case st_C_typespec:
- case st_C_struct:
- case st_C_enum:
- return FALSE;
- }
- return TRUE;
- }
-
- /*
- * This structdef business is currently only invoked when cblev==0.
- * It should be recursively invoked whatever the curly brace level,
- * and a stack of states kept, to allow for definitions of structs
- * within structs.
- *
- * This structdef business is NOT invoked when we are ctags and the
- * file is plain C. This is because a struct tag may have the same
- * name as another tag, and this loses with ctags.
- */
- switch (toktype)
- {
- case st_C_struct:
- case st_C_enum:
- if (typdef == ttypedseen
- || (typedefs_and_cplusplus && cblev == 0 && structdef == snone))
- {
- structdef = skeyseen;
- structtype = toktype;
- }
- return FALSE;
- }
-
- if (structdef == skeyseen)
- {
- /* Save the tag for struct/union/class, for functions that may be
- defined inside. */
- if (structtype == st_C_struct)
- structtag = savenstr (str, len);
- else
- structtag = "<enum>";
- structdef = stagseen;
- return TRUE;
- }
-
- /* Avoid entering funcdef stuff if typdef is going on. */
- if (typdef != tnone)
- {
- definedef = dnone;
- return FALSE;
- }
-
- /* Detect GNU macros.
-
- DEFUN note for writers of emacs C code:
- The DEFUN macro, used in emacs C source code, has a first arg
- that is a string (the lisp function name), and a second arg that
- is a C function name. Since etags skips strings, the second arg
- is tagged. This is unfortunate, as it would be better to tag the
- first arg. The simplest way to deal with this problem would be
- to name the tag with a name built from the function name, by
- removing the initial 'F' character and substituting '-' for '_'.
- Anyway, this assumes that the conventions of naming lisp
- functions will never change. Currently, this method is not
- implemented, so writers of emacs code are recommended to put the
- first two args of a DEFUN on the same line. */
- if (definedef == dnone && toktype == st_C_gnumacro)
- {
- next_token_is_func = TRUE;
- return FALSE;
- }
- if (next_token_is_func)
- {
- next_token_is_func = FALSE;
- funcdef = fignore;
- *is_func = TRUE;
- return TRUE;
- }
-
- /* Detect Objective C constructs. */
- switch (objdef)
- {
- case onone:
- switch (toktype)
- {
- case st_C_objprot:
- objdef = oprotocol;
- return FALSE;
- case st_C_objimpl:
- objdef = oimplementation;
- return FALSE;
- }
- break;
- case oimplementation:
- /* Save the class tag for functions that may be defined inside. */
- objtag = savenstr (str, len);
- objdef = oinbody;
- return FALSE;
- case oprotocol:
- /* Save the class tag for categories. */
- objtag = savenstr (str, len);
- objdef = otagseen;
- *is_func = TRUE;
- return TRUE;
- case oparenseen:
- objdef = ocatseen;
- *is_func = TRUE;
- return TRUE;
- case oinbody:
- break;
- case omethodsign:
- if (parlev == 0)
- {
- objdef = omethodtag;
- methodlen = len;
- grow_linebuffer (&token_name, methodlen+1);
- strncpy (token_name.buffer, str, len);
- token_name.buffer[methodlen] = '\0';
- return TRUE;
- }
- return FALSE;
- case omethodcolon:
- if (parlev == 0)
- objdef = omethodparm;
- return FALSE;
- case omethodparm:
- if (parlev == 0)
- {
- objdef = omethodtag;
- methodlen += len;
- grow_linebuffer (&token_name, methodlen+1);
- strncat (token_name.buffer, str, len);
- return TRUE;
- }
- return FALSE;
- case oignore:
- if (toktype == st_C_objend)
- {
- /* Memory leakage here: the string pointed by objtag is
- never released, because many tests would be needed to
- avoid breaking on incorrect input code. The amount of
- memory leaked here is the sum of the lengths of the
- class tags.
- free (objtag); */
- objdef = onone;
- }
- return FALSE;
- }
-
- /* A function or enum constant? */
- switch (toktype)
- {
- case st_C_typespec:
- if (funcdef != finlist && funcdef != fignore)
- funcdef = fnone; /* should be useless */
- return FALSE;
- case st_none:
- if (constantypedefs && structdef == sinbody && structtype == st_C_enum)
- return TRUE;
- if (funcdef == fnone)
- {
- funcdef = ftagseen;
- *is_func = TRUE;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/*
- * C_entries ()
- * This routine finds functions, typedefs, #define's, enum
- * constants and struct/union/enum definitions in C syntax
- * and adds them to the list.
- */
-typedef struct
-{
- logical valid;
- char *str;
- logical named;
- int linelen;
- int lineno;
- long linepos;
- char *buffer;
-} TOKEN;
-
-#define current_lb_is_new (newndx == curndx)
-#define switch_line_buffers() (curndx = 1 - curndx)
-
-#define curlb (lbs[curndx].lb)
-#define othlb (lbs[1-curndx].lb)
-#define newlb (lbs[newndx].lb)
-#define curlinepos (lbs[curndx].linepos)
-#define othlinepos (lbs[1-curndx].linepos)
-#define newlinepos (lbs[newndx].linepos)
-
-#define CNL_SAVE_DEFINEDEF \
-do { \
- curlinepos = charno; \
- lineno++; \
- linecharno = charno; \
- charno += readline (&curlb, inf); \
- lp = curlb.buffer; \
- quotednl = FALSE; \
- newndx = curndx; \
-} while (0)
-
-#define CNL \
-do { \
- CNL_SAVE_DEFINEDEF; \
- if (savetok.valid) \
- { \
- tok = savetok; \
- savetok.valid = FALSE; \
- } \
- definedef = dnone; \
-} while (0)
-
-
-void
-make_C_tag (isfun, tokp)
- logical isfun;
- TOKEN *tokp;
-{
- char *name = NULL;
-
- /* This function should never be called when tok.valid is FALSE, but
- we must protect against invalid input or internal errors. */
- if (tokp->valid)
- {
- if (CTAGS || tokp->named)
- name = savestr (token_name.buffer);
- pfnote (name, isfun,
- tokp->buffer, tokp->linelen, tokp->lineno, tokp->linepos);
- tokp->valid = FALSE;
- }
- else if (DEBUG)
- abort ();
-}
-
-
-void
-C_entries (c_ext, inf)
- int c_ext; /* extension of C */
- FILE *inf; /* input file */
-{
- register char c; /* latest char read; '\0' for end of line */
- register char *lp; /* pointer one beyond the character `c' */
- int curndx, newndx; /* indices for current and new lb */
- TOKEN tok; /* latest token read */
- register int tokoff; /* offset in line of start of current token */
- register int toklen; /* length of current token */
- int cblev; /* current curly brace level */
- int parlev; /* current parenthesis level */
- logical incomm, inquote, inchar, quotednl, midtoken;
- logical cplpl;
- TOKEN savetok; /* token saved during preprocessor handling */
-
-
- curndx = newndx = 0;
- lineno = 0;
- charno = 0;
- lp = curlb.buffer;
- *lp = 0;
-
- funcdef = fnone; typdef = tnone; structdef = snone;
- definedef = dnone; objdef = onone;
- next_token_is_func = yacc_rules = FALSE;
- midtoken = inquote = inchar = incomm = quotednl = FALSE;
- tok.valid = savetok.valid = FALSE;
- cblev = 0;
- parlev = 0;
- cplpl = c_ext & C_PLPL;
-
- while (!feof (inf))
- {
- c = *lp++;
- if (c == '\\')
- {
- /* If we're at the end of the line, the next character is a
- '\0'; don't skip it, because it's the thing that tells us
- to read the next line. */
- if (*lp == '\0')
- {
- quotednl = TRUE;
- continue;
- }
- lp++;
- c = ' ';
- }
- else if (incomm)
- {
- switch (c)
- {
- case '*':
- if (*lp == '/')
- {
- c = *lp++;
- incomm = FALSE;
- }
- break;
- case '\0':
- /* Newlines inside comments do not end macro definitions in
- traditional cpp. */
- CNL_SAVE_DEFINEDEF;
- break;
- }
- continue;
- }
- else if (inquote)
- {
- switch (c)
- {
- case '"':
- inquote = FALSE;
- break;
- case '\0':
- /* Newlines inside strings do not end macro definitions
- in traditional cpp, even though compilers don't
- usually accept them. */
- CNL_SAVE_DEFINEDEF;
- break;
- }
- continue;
- }
- else if (inchar)
- {
- switch (c)
- {
- case '\0':
- /* Hmmm, something went wrong. */
- CNL;
- /* FALLTHRU */
- case '\'':
- inchar = FALSE;
- break;
- }
- continue;
- }
- else
- switch (c)
- {
- case '"':
- inquote = TRUE;
- if (funcdef != finlist && funcdef != fignore)
- funcdef = fnone;
- continue;
- case '\'':
- inchar = TRUE;
- if (funcdef != finlist && funcdef != fignore)
- funcdef = fnone;
- continue;
- case '/':
- if (*lp == '*')
- {
- lp++;
- incomm = TRUE;
- continue;
- }
- else if (/* cplpl && */ *lp == '/')
- {
- c = '\0';
- break;
- }
- else
- break;
- case '%':
- if ((c_ext & YACC) && *lp == '%')
- {
- /* entering or exiting rules section in yacc file */
- lp++;
- definedef = dnone; funcdef = fnone;
- typdef = tnone; structdef = snone;
- next_token_is_func = FALSE;
- midtoken = inquote = inchar = incomm = quotednl = FALSE;
- cblev = 0;
- yacc_rules = !yacc_rules;
- continue;
- }
- else
- break;
- case '#':
- if (definedef == dnone)
- {
- char *cp;
- logical cpptoken = TRUE;
-
- /* Look back on this line. If all blanks, or nonblanks
- followed by an end of comment, this is a preprocessor
- token. */
- for (cp = newlb.buffer; cp < lp-1; cp++)
- if (!iswhite (*cp))
- {
- if (*cp == '*' && *(cp+1) == '/')
- {
- cp++;
- cpptoken = TRUE;
- }
- else
- cpptoken = FALSE;
- }
- if (cpptoken)
- definedef = dsharpseen;
- } /* if (definedef == dnone) */
-
- continue;
- } /* switch (c) */
-
-
- /* Consider token only if some complicated conditions are satisfied. */
- if ((definedef != dnone
- || (cblev == 0 && structdef != scolonseen)
- || (cblev == 1 && cplpl && structdef == sinbody)
- || (structdef == sinbody && structtype == st_C_enum))
- && typdef != tignore
- && definedef != dignorerest
- && funcdef != finlist)
- {
- if (midtoken)
- {
- if (endtoken (c))
- {
- if (c == ':' && cplpl && *lp == ':' && begtoken(*(lp + 1)))
- {
- /*
- * This handles :: in the middle, but not at the
- * beginning of an identifier.
- */
- lp += 2;
- toklen += 3;
- }
- else
- {
- logical is_func = FALSE;
-
- if (yacc_rules
- || consider_token (newlb.buffer + tokoff, toklen, c,
- c_ext, cblev, parlev, &is_func))
- {
- if (structdef == sinbody
- && definedef == dnone
- && is_func)
- /* function defined in C++ class body */
- {
- grow_linebuffer (&token_name,
- strlen(structtag)+2+toklen+1);
- strcpy (token_name.buffer, structtag);
- strcat (token_name.buffer, "::");
- strncat (token_name.buffer,
- newlb.buffer+tokoff, toklen);
- tok.named = TRUE;
- }
- else if (objdef == ocatseen)
- /* Objective C category */
- {
- grow_linebuffer (&token_name,
- strlen(objtag)+2+toklen+1);
- strcpy (token_name.buffer, objtag);
- strcat (token_name.buffer, "(");
- strncat (token_name.buffer,
- newlb.buffer+tokoff, toklen);
- strcat (token_name.buffer, ")");
- tok.named = TRUE;
- }
- else if (objdef == omethodtag
- || objdef == omethodparm)
- /* Objective C method */
- {
- tok.named = TRUE;
- }
- else
- {
- grow_linebuffer (&token_name, toklen+1);
- strncpy (token_name.buffer,
- newlb.buffer+tokoff, toklen);
- token_name.buffer[toklen] = '\0';
- if (structdef == stagseen
- || typdef == tend
- || (is_func
- && definedef == dignorerest)) /* macro */
- tok.named = TRUE;
- else
- tok.named = FALSE;
- }
- tok.lineno = lineno;
- tok.linelen = tokoff + toklen + 1;
- tok.buffer = newlb.buffer;
- tok.linepos = newlinepos;
- tok.valid = TRUE;
-
- if (definedef == dnone
- && (funcdef == ftagseen
- || structdef == stagseen
- || typdef == tend
- || objdef != onone))
- {
- if (current_lb_is_new)
- switch_line_buffers ();
- }
- else
- make_C_tag (is_func, &tok);
- }
- midtoken = FALSE;
- }
- } /* if (endtoken (c)) */
- else if (intoken (c))
- {
- toklen++;
- continue;
- }
- } /* if (midtoken) */
- else if (begtoken (c))
- {
- switch (definedef)
- {
- case dnone:
- switch (funcdef)
- {
- case fstartlist:
- funcdef = finlist;
- continue;
- case flistseen:
- make_C_tag (TRUE, &tok);
- funcdef = fignore;
- break;
- case ftagseen:
- funcdef = fnone;
- break;
- }
- if (structdef == stagseen)
- structdef = snone;
- break;
- case dsharpseen:
- savetok = tok;
- }
- if (!yacc_rules || lp == newlb.buffer + 1)
- {
- tokoff = lp - 1 - newlb.buffer;
- toklen = 1;
- midtoken = TRUE;
- }
- continue;
- } /* if (begtoken) */
- } /* if must look at token */
-
-
- /* Detect end of line, colon, comma, semicolon and various braces
- after having handled a token.*/
- switch (c)
- {
- case ':':
- if (definedef != dnone)
- break;
- switch (objdef)
- {
- case otagseen:
- objdef = oignore;
- make_C_tag (TRUE, &tok);
- break;
- case omethodtag:
- case omethodparm:
- objdef = omethodcolon;
- methodlen += 1;
- grow_linebuffer (&token_name, methodlen+1);
- strcat (token_name.buffer, ":");
- break;
- }
- if (structdef == stagseen)
- structdef = scolonseen;
- else
- switch (funcdef)
- {
- case ftagseen:
- if (yacc_rules)
- {
- make_C_tag (FALSE, &tok);
- funcdef = fignore;
- }
- break;
- case fstartlist:
- funcdef = fnone;
- break;
- }
- break;
- case ';':
- if (definedef != dnone)
- break;
- if (cblev == 0)
- switch (typdef)
- {
- case tend:
- make_C_tag (FALSE, &tok);
- /* FALLTHRU */
- default:
- typdef = tnone;
- }
- if (funcdef != fignore)
- {
- funcdef = fnone;
- /* The following instruction invalidates the token.
- Probably the token should be invalidated in all
- other cases where some state machine is reset. */
- tok.valid = FALSE;
- }
- if (structdef == stagseen)
- structdef = snone;
- break;
- case ',':
- if (definedef != dnone)
- break;
- switch (objdef)
- {
- case omethodtag:
- case omethodparm:
- make_C_tag (TRUE, &tok);
- objdef = oinbody;
- break;
- }
- if (funcdef != finlist && funcdef != fignore)
- funcdef = fnone;
- if (structdef == stagseen)
- structdef = snone;
- break;
- case '[':
- if (definedef != dnone)
- break;
- if (cblev == 0 && typdef == tend)
- {
- typdef = tignore;
- make_C_tag (FALSE, &tok);
- break;
- }
- if (funcdef != finlist && funcdef != fignore)
- funcdef = fnone;
- if (structdef == stagseen)
- structdef = snone;
- break;
- case '(':
- if (definedef != dnone)
- break;
- if (objdef == otagseen && parlev == 0)
- objdef = oparenseen;
- switch (funcdef)
- {
- case fnone:
- switch (typdef)
- {
- case ttypedseen:
- case tend:
- /* Make sure that the next char is not a '*'.
- This handles constructs like:
- typedef void OperatorFun (int fun); */
- if (tok.valid && *lp != '*')
- {
- typdef = tignore;
- make_C_tag (FALSE, &tok);
- }
- break;
- } /* switch (typdef) */
- break;
- case ftagseen:
- funcdef = fstartlist;
- break;
- case flistseen:
- funcdef = finlist;
- break;
- }
- parlev++;
- break;
- case ')':
- if (definedef != dnone)
- break;
- if (objdef == ocatseen && parlev == 1)
- {
- make_C_tag (TRUE, &tok);
- objdef = oignore;
- }
- if (--parlev == 0)
- {
- switch (funcdef)
- {
- case fstartlist:
- case finlist:
- funcdef = flistseen;
- break;
- }
- if (cblev == 0 && typdef == tend)
- {
- typdef = tignore;
- make_C_tag (FALSE, &tok);
- }
- }
- else if (parlev < 0) /* can happen due to ill-conceived #if's. */
- parlev = 0;
- break;
- case '{':
- if (definedef != dnone)
- break;
- if (typdef == ttypedseen)
- typdef = tinbody;
- switch (structdef)
- {
- case skeyseen: /* unnamed struct */
- structdef = sinbody;
- structtag = "_anonymous_";
- break;
- case stagseen:
- case scolonseen: /* named struct */
- structdef = sinbody;
- make_C_tag (FALSE, &tok);
- break;
- }
- switch (funcdef)
- {
- case flistseen:
- make_C_tag (TRUE, &tok);
- /* FALLTHRU */
- case fignore:
- funcdef = fnone;
- break;
- case fnone:
- switch (objdef)
- {
- case otagseen:
- make_C_tag (TRUE, &tok);
- objdef = oignore;
- break;
- case omethodtag:
- case omethodparm:
- make_C_tag (TRUE, &tok);
- objdef = oinbody;
- break;
- default:
- /* Neutralize `extern "C" {' grot. */
- if (cblev == 0 && structdef == snone && typdef == tnone)
- cblev = -1;
- }
- }
- cblev++;
- break;
- case '*':
- if (definedef != dnone)
- break;
- if (funcdef == fstartlist)
- funcdef = fnone; /* avoid tagging `foo' in `foo (*bar()) ()' */
- break;
- case '}':
- if (definedef != dnone)
- break;
- if (!noindentypedefs && lp == newlb.buffer + 1)
- {
- cblev = 0; /* reset curly brace level if first column */
- parlev = 0; /* also reset paren level, just in case... */
- }
- else if (cblev > 0)
- cblev--;
- if (cblev == 0)
- {
- if (typdef == tinbody)
- typdef = tend;
- /* Memory leakage here: the string pointed by structtag is
- never released, because I fear to miss something and
- break things while freeing the area. The amount of
- memory leaked here is the sum of the lengths of the
- struct tags.
- if (structdef == sinbody)
- free (structtag); */
-
- structdef = snone;
- structtag = "<error>";
- }
- break;
- case '+':
- case '-':
- if (objdef == oinbody && cblev == 0)
- {
- objdef = omethodsign;
- break;
- }
- /* FALLTHRU */
- case '=': case '#': case '~': case '&': case '%': case '/':
- case '|': case '^': case '!': case '<': case '>': case '.': case '?':
- if (definedef != dnone)
- break;
- /* These surely cannot follow a function tag. */
- if (funcdef != finlist && funcdef != fignore)
- funcdef = fnone;
- break;
- case '\0':
- if (objdef == otagseen)
- {
- make_C_tag (TRUE, &tok);
- objdef = oignore;
- }
- /* If a macro spans multiple lines don't reset its state. */
- if (quotednl)
- CNL_SAVE_DEFINEDEF;
- else
- CNL;
- break;
- } /* switch (c) */
-
- } /* while not eof */
-}
-
-/*
- * Process either a C++ file or a C file depending on the setting
- * of a global flag.
- */
-void
-default_C_entries (inf)
- FILE *inf;
-{
- C_entries (cplusplus ? C_PLPL : 0, inf);
-}
-
-/* Always do plain ANSI C. */
-void
-plain_C_entries (inf)
- FILE *inf;
-{
- C_entries (0, inf);
-}
-
-/* Always do C++. */
-void
-Cplusplus_entries (inf)
- FILE *inf;
-{
- C_entries (C_PLPL, inf);
-}
-
-/* Always do C*. */
-void
-Cstar_entries (inf)
- FILE *inf;
-{
- C_entries (C_STAR, inf);
-}
-
-/* Always do Yacc. */
-void
-Yacc_entries (inf)
- FILE *inf;
-{
- C_entries (YACC, inf);
-}
-
-/* Fortran parsing */
-
-char *dbp;
-
-logical
-tail (cp)
- char *cp;
-{
- register int len = 0;
-
- while (*cp && lowcase(*cp) == lowcase(dbp[len]))
- cp++, len++;
- if (*cp == '\0' && !intoken(dbp[len]))
- {
- dbp += len;
- return TRUE;
- }
- return FALSE;
-}
-
-void
-takeprec ()
-{
- while (isspace (*dbp))
- dbp++;
- if (*dbp != '*')
- return;
- dbp++;
- while (isspace (*dbp))
- dbp++;
- if (strneq (dbp, "(*)", 3))
- {
- dbp += 3;
- return;
- }
- if (!isdigit (*dbp))
- {
- --dbp; /* force failure */
- return;
- }
- do
- dbp++;
- while (isdigit (*dbp));
-}
-
-void
-getit (inf)
- FILE *inf;
-{
- register char *cp;
-
- while (isspace (*dbp))
- dbp++;
- if (*dbp == '\0')
- {
- lineno++;
- linecharno = charno;
- charno += readline (&lb, inf);
- dbp = lb.buffer;
- if (dbp[5] != '&')
- return;
- dbp += 6;
- while (isspace (*dbp))
- dbp++;
- }
- if (!isalpha (*dbp)
- && *dbp != '_'
- && *dbp != '$')
- return;
- for (cp = dbp + 1;
- (*cp
- && (isalpha (*cp) || isdigit (*cp) || (*cp == '_') || (*cp == '$')));
- cp++)
- continue;
- pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
-}
-
-void
-Fortran_functions (inf)
- FILE *inf;
-{
- lineno = 0;
- charno = 0;
-
- while (!feof (inf))
- {
- lineno++;
- linecharno = charno;
- charno += readline (&lb, inf);
- dbp = lb.buffer;
- if (*dbp == '%')
- dbp++; /* Ratfor escape to fortran */
- while (isspace (*dbp))
- dbp++;
- if (*dbp == '\0')
- continue;
- switch (lowcase (*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 (lowcase (*dbp))
- {
- case 'f':
- if (tail ("function"))
- getit (inf);
- continue;
- case 's':
- if (tail ("subroutine"))
- getit (inf);
- continue;
- case 'e':
- if (tail ("entry"))
- getit (inf);
- continue;
- case 'p':
- if (tail ("program"))
- {
- getit (inf);
- continue;
- }
- if (tail ("procedure"))
- getit (inf);
- continue;
- }
- }
-}
-
-/*
- * Bob Weiner, Motorola Inc., 4/3/94
- * Unix and microcontroller assembly tag handling
- * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
- */
-void
-Asm_labels (inf)
- FILE *inf;
-{
- register char *cp;
-
- lineno = 0;
- charno = 0;
-
- while (!feof (inf))
- {
- lineno++;
- linecharno = charno;
- charno += readline (&lb, inf);
- cp = lb.buffer;
-
- /* If first char is alphabetic or one of [_.$], test for colon
- following identifier. */
- if (isalpha (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
- {
- /* Read past label. */
- cp++;
- while (isalnum (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
- cp++;
- if (*cp == ':' || isspace (*cp))
- {
- /* Found end of label, so copy it and add it to the table. */
- pfnote ((CTAGS) ? savenstr(lb.buffer, cp-lb.buffer) : NULL, TRUE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
- }
- }
- }
-}
-
-/*
- * Perl support by Bart Robinson <lomew@cs.utah.edu>
- * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/
- */
-void
-Perl_functions (inf)
- FILE *inf;
-{
- register char *cp;
-
- lineno = 0;
- charno = 0;
-
- while (!feof (inf))
- {
- lineno++;
- linecharno = charno;
- charno += readline (&lb, inf);
- cp = lb.buffer;
-
- if (*cp++ == 's' && *cp++ == 'u' && *cp++ == 'b' && isspace(*cp++))
- {
- while (*cp && isspace(*cp))
- cp++;
- while (*cp && ! isspace(*cp) && *cp != '{')
- cp++;
- pfnote ((CTAGS) ? savenstr (lb.buffer, cp-lb.buffer) : NULL, TRUE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
- }
- }
-}
-
-/* Added by Mosur Mohan, 4/22/88 */
-/* Pascal parsing */
-
-/*
- * Locates tags for procedures & functions. Doesn't do any type- or
- * var-definitions. It does look for the keyword "extern" or
- * "forward" immediately following the procedure statement; if found,
- * the tag is skipped.
- */
-void
-Pascal_functions (inf)
- FILE *inf;
-{
- struct linebuffer tline; /* mostly copied from C_entries */
- long save_lcno;
- int save_lineno, save_len;
- char c, *cp, *namebuf;
-
- logical /* each of these flags is TRUE iff: */
- incomment, /* point is inside a comment */
- inquote, /* point is inside '..' string */
- get_tagname, /* point is after PROCEDURE/FUNCTION
- keyword, so next item = potential tag */
- found_tag, /* point is after a potential tag */
- inparms, /* point is within parameter-list */
- verify_tag; /* point has passed the parm-list, so the
- next token will determine whether this
- is a FORWARD/EXTERN to be ignored, or
- whether it is a real tag */
-
- lineno = 0;
- charno = 0;
- dbp = lb.buffer;
- *dbp = '\0';
- save_len = 0;
- initbuffer (&tline);
-
- incomment = inquote = FALSE;
- found_tag = FALSE; /* have a proc name; check if extern */
- get_tagname = FALSE; /* have found "procedure" keyword */
- inparms = FALSE; /* found '(' after "proc" */
- verify_tag = FALSE; /* check if "extern" is ahead */
-
- /* long main loop to get next char */
- while (!feof (inf))
- {
- c = *dbp++;
- if (c == '\0') /* if end of line */
- {
- lineno++;
- linecharno = charno;
- charno += readline (&lb, inf);
- dbp = lb.buffer;
- if (*dbp == '\0')
- continue;
- if (!((found_tag && verify_tag) ||
- get_tagname))
- c = *dbp++; /* only if don't need *dbp pointing
- to the beginning of the name of
- the procedure or function */
- }
- if (incomment)
- {
- if (c == '}') /* within { } comments */
- incomment = FALSE;
- else if (c == '*' && *dbp == ')') /* within (* *) comments */
- {
- dbp++;
- incomment = FALSE;
- }
- continue;
- }
- else if (inquote)
- {
- if (c == '\'')
- inquote = FALSE;
- continue;
- }
- else
- switch (c)
- {
- case '\'':
- inquote = TRUE; /* found first quote */
- continue;
- case '{': /* found open { comment */
- incomment = TRUE;
- continue;
- case '(':
- if (*dbp == '*') /* found open (* comment */
- {
- incomment = TRUE;
- dbp++;
- }
- else if (found_tag) /* found '(' after tag, i.e., parm-list */
- inparms = TRUE;
- continue;
- case ')': /* end of parms list */
- if (inparms)
- inparms = FALSE;
- continue;
- case ';':
- if (found_tag && !inparms) /* end of proc or fn stmt */
- {
- verify_tag = TRUE;
- break;
- }
- continue;
- }
- if (found_tag && verify_tag && (*dbp != ' '))
- {
- /* check if this is an "extern" declaration */
- if (*dbp == '\0')
- continue;
- if (lowcase (*dbp == 'e'))
- {
- if (tail ("extern")) /* superfluous, really! */
- {
- found_tag = FALSE;
- verify_tag = FALSE;
- }
- }
- else if (lowcase (*dbp) == 'f')
- {
- if (tail ("forward")) /* check for forward reference */
- {
- found_tag = FALSE;
- verify_tag = FALSE;
- }
- }
- if (found_tag && verify_tag) /* not external proc, so make tag */
- {
- found_tag = FALSE;
- verify_tag = FALSE;
- pfnote (namebuf, TRUE,
- tline.buffer, save_len, save_lineno, save_lcno);
- continue;
- }
- }
- if (get_tagname) /* grab name of proc or fn */
- {
- if (*dbp == '\0')
- continue;
-
- /* save all values for later tagging */
- grow_linebuffer (&tline, strlen (lb.buffer) + 1);
- strcpy (tline.buffer, lb.buffer);
- save_lineno = lineno;
- save_lcno = linecharno;
-
- /* grab block name */
- for (cp = dbp + 1; *cp && (!endtoken (*cp)); cp++)
- continue;
- namebuf = (CTAGS) ? savenstr (dbp, cp-dbp) : NULL;
- dbp = cp; /* set dbp to e-o-token */
- save_len = dbp - lb.buffer + 1;
- get_tagname = FALSE;
- found_tag = TRUE;
- continue;
-
- /* and proceed to check for "extern" */
- }
- else if (!incomment && !inquote && !found_tag)
- {
- /* check for proc/fn keywords */
- switch (lowcase (c))
- {
- case 'p':
- if (tail ("rocedure")) /* c = 'p', dbp has advanced */
- get_tagname = TRUE;
- continue;
- case 'f':
- if (tail ("unction"))
- get_tagname = TRUE;
- continue;
- }
- }
- } /* while not eof */
-
- free (tline.buffer);
-}
-
-/*
- * lisp tag functions
- * look for (def or (DEF, quote or QUOTE
- */
-int
-L_isdef (strp)
- register char *strp;
-{
- return ((strp[1] == 'd' || strp[1] == 'D')
- && (strp[2] == 'e' || strp[2] == 'E')
- && (strp[3] == 'f' || strp[3] == 'F'));
-}
-
-int
-L_isquote (strp)
- register char *strp;
-{
- return ((*(++strp) == 'q' || *strp == 'Q')
- && (*(++strp) == 'u' || *strp == 'U')
- && (*(++strp) == 'o' || *strp == 'O')
- && (*(++strp) == 't' || *strp == 'T')
- && (*(++strp) == 'e' || *strp == 'E')
- && isspace(*(++strp)));
-}
-
-void
-L_getit ()
-{
- register char *cp;
-
- if (*dbp == '\'') /* Skip prefix quote */
- dbp++;
- else if (*dbp == '(' && L_isquote (dbp)) /* Skip "(quote " */
- {
- dbp += 7;
- while (isspace(*dbp))
- dbp++;
- }
- for (cp = dbp /*+1*/;
- *cp && *cp != '(' && *cp != ' ' && *cp != ')';
- cp++)
- continue;
- if (cp == dbp)
- return;
-
- pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
-}
-
-void
-Lisp_functions (inf)
- FILE *inf;
-{
- lineno = 0;
- charno = 0;
-
- while (!feof (inf))
- {
- lineno++;
- linecharno = charno;
- charno += readline (&lb, inf);
- dbp = lb.buffer;
- if (dbp[0] == '(')
- {
- if (L_isdef (dbp))
- {
- while (!isspace (*dbp))
- dbp++;
- while (isspace (*dbp))
- dbp++;
- L_getit ();
- }
- else
- {
- /* Check for (foo::defmumble name-defined ... */
- do
- dbp++;
- while (*dbp && !isspace (*dbp)
- && *dbp != ':' && *dbp != '(' && *dbp != ')');
- if (*dbp == ':')
- {
- do
- dbp++;
- while (*dbp == ':');
-
- if (L_isdef (dbp - 1))
- {
- while (!isspace (*dbp))
- dbp++;
- while (isspace (*dbp))
- dbp++;
- L_getit ();
- }
- }
- }
- }
- }
-}
-
-/*
- * Scheme tag functions
- * look for (def... xyzzy
- * look for (def... (xyzzy
- * look for (def ... ((...(xyzzy ....
- * look for (set! xyzzy
- */
-
-void get_scheme ();
-
-void
-Scheme_functions (inf)
- FILE *inf;
-{
- lineno = 0;
- charno = 0;
-
- while (!feof (inf))
- {
- lineno++;
- linecharno = charno;
- charno += readline (&lb, inf);
- 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 ();
- }
- }
-}
-
-void
-get_scheme ()
-{
- register char *cp;
-
- 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;
- pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
-}
-
-/* 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.
- CONVERT THIS TO USE THE Stab TYPE!! */
-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. */
-
-char *TEX_defenv = "\
-:chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
-:part:appendix:entry:index";
-
-void TEX_mode ();
-struct TEX_tabent *TEX_decode_env ();
-int TEX_Token ();
-#if TeX_named_tokens
-void TEX_getit ();
-#endif
-
-char TEX_esc = '\\';
-char TEX_opgrp = '{';
-char TEX_clgrp = '}';
-
-/*
- * TeX/LaTeX scanning loop.
- */
-void
-TeX_functions (inf)
- FILE *inf;
-{
- char *lasthit;
-
- lineno = 0;
- charno = 0;
-
- /* Select either \ or ! as escape character. */
- TEX_mode (inf);
-
- /* Initialize token table once from environment. */
- if (!TEX_toktab)
- TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
-
- while (!feof (inf))
- { /* Scan each line in file */
- lineno++;
- linecharno = charno;
- charno += readline (&lb, inf);
- dbp = lb.buffer;
- lasthit = dbp;
- while (dbp = etags_strchr (dbp, TEX_esc)) /* Look at each esc in line */
- {
- register int i;
-
- if (!*(++dbp))
- break;
- linecharno += dbp - lasthit;
- lasthit = dbp;
- i = TEX_Token (lasthit);
- if (0 <= i)
- {
- pfnote ((char *)NULL, TRUE,
- lb.buffer, strlen (lb.buffer), lineno, linecharno);
-#if TeX_named_tokens
- TEX_getit (lasthit, TEX_toktab[i].len);
-#endif
- 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. */
-void
-TEX_mode (inf)
- FILE *inf;
-{
- int c;
-
- while ((c = getc (inf)) != EOF)
- {
- /* Skip to next line if we hit the TeX comment char. */
- if (c == TEX_cmt)
- while (c != '\n')
- c = getc (inf);
- else 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 (inf);
-}
-
-/* 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;
-
- struct TEX_tabent *tab;
- int size, i;
-
- /* Append default string to environment. */
- env = getenv (evarname);
- if (!env)
- env = defenv;
- else
- env = concat (env, defenv, "");
-
- /* Allocate a token table */
- for (size = 1, p = env; p;)
- if ((p = etags_strchr (p, ':')) && *(++p))
- size++;
- /* Add 1 to leave room for null terminator. */
- tab = xnew (size + 1, struct TEX_tabent);
-
- /* Unpack environment string into token table. Be careful about */
- /* zero-length strings (leading ':', "::" and trailing ':') */
- for (i = 0; *env;)
- {
- p = etags_strchr (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;
-}
-
-#if TeX_named_tokens
-/* 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. */
-void
-TEX_getit (name, len)
- char *name;
- int len;
-{
- char *p = name + len;
-
- if (*name == '\0')
- return;
-
- /* Let tag name extend to next group close (or end of line) */
- while (*p && *p != TEX_clgrp)
- p++;
- pfnote (savenstr (name, p-name), TRUE,
- lb.buffer, strlen (lb.buffer), lineno, linecharno);
-}
-#endif
-
-/* If the text at CP matches one of the tag-defining TeX command names,
- return the pointer to the first occurrence 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' */
-int
-TEX_Token (cp)
- char *cp;
-{
- int i;
-
- for (i = 0; TEX_toktab[i].len > 0; i++)
- if (strneq (TEX_toktab[i].name, cp, TEX_toktab[i].len))
- return i;
- return -1;
-}
-
-/*
- * Prolog support (rewritten) by Anders Lindgren, Mar. 96
- *
- * Assumes that the predicate starts at column 0.
- * Only the first clause of a predicate is added.
- */
-void
-Prolog_functions (inf)
- FILE *inf;
-{
- int prolog_pred ();
- void prolog_skip_comment ();
-
- char * last;
- int len;
- int allocated;
-
- allocated = 0;
- len = 0;
- last = NULL;
-
- lineno = 0;
- linecharno = 0;
- charno = 0;
-
- while (!feof (inf))
- {
- lineno++;
- linecharno += charno;
- charno = readline (&lb, inf);
- dbp = lb.buffer;
- if (dbp[0] == '\0') /* Empty line */
- continue;
- else if (isspace (dbp[0])) /* Not a predicate */
- continue;
- else if (dbp[0] == '/' && dbp[1] == '*') /* comment. */
- prolog_skip_comment (&lb, inf);
- else if (len = prolog_pred (dbp, last))
- {
- /* Predicate. Store the function name so that we only
- generate a tag for the first clause. */
- if (last == NULL)
- last = xnew(len + 1, char);
- else if (len + 1 > allocated)
- last = (char *) xrealloc(last, len + 1);
- allocated = len + 1;
- strncpy (last, dbp, len);
- last[len] = '\0';
- }
- }
-}
-
-
-void
-prolog_skip_comment (plb, inf)
- struct linebuffer *plb;
- FILE *inf;
-{
- char *cp;
-
- do
- {
- for (cp = plb->buffer; *cp != '\0'; cp++)
- if (cp[0] == '*' && cp[1] == '/')
- return;
- lineno++;
- linecharno += readline (plb, inf);
- }
- while (!feof(inf));
-}
-
-/*
- * A predicate definition is added if it matches:
- * <beginning of line><Prolog Atom><whitespace>(
- *
- * It is added to the tags database if it doesn't match the
- * name of the previous clause header.
- *
- * Return the size of the name of the predicate, or 0 if no header
- * was found.
- */
-int
-prolog_pred (s, last)
- char *s;
- char *last; /* Name of last clause. */
-{
- int prolog_atom();
- int prolog_white();
-
- int pos;
- int len;
-
- pos = prolog_atom(s, 0);
- if (pos < 1)
- return 0;
-
- len = pos;
- pos += prolog_white(s, pos);
-
- if ((s[pos] == '(') || (s[pos] == '.'))
- {
- if (s[pos] == '(')
- pos++;
-
- /* Save only the first clause. */
- if ((last == NULL) ||
- (len != strlen(last)) ||
- (strncmp(s, last, len) != 0))
- {
- pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
- s, pos, lineno, linecharno);
- return len;
- }
- }
- return 0;
-}
-
-/*
- * Consume a Prolog atom.
- * Return the number of bytes consumed, or -1 if there was an error.
- *
- * A prolog atom, in this context, could be one of:
- * - An alphanumeric sequence, starting with a lower case letter.
- * - A quoted arbitrary string. Single quotes can escape themselves.
- * Backslash quotes everything.
- */
-int
-prolog_atom (s, pos)
- char *s;
- int pos;
-{
- int origpos;
-
- origpos = pos;
-
- if (islower(s[pos]) || (s[pos] == '_'))
- {
- /* The atom is unquoted. */
- pos++;
- while (isalnum(s[pos]) || (s[pos] == '_'))
- {
- pos++;
- }
- return pos - origpos;
- }
- else if (s[pos] == '\'')
- {
- pos++;
-
- while (1)
- {
- if (s[pos] == '\'')
- {
- pos++;
- if (s[pos] != '\'')
- break;
- pos++; /* A double quote */
- }
- else if (s[pos] == '\0')
- /* Multiline quoted atoms are ignored. */
- return -1;
- else if (s[pos] == '\\')
- {
- if (s[pos+1] == '\0')
- return -1;
- pos += 2;
- }
- else
- pos++;
- }
- return pos - origpos;
- }
- else
- return -1;
-}
-
-/* Consume whitespace. Return the number of bytes eaten. */
-int
-prolog_white (s, pos)
- char *s;
- int pos;
-{
- int origpos;
-
- origpos = pos;
-
- while (isspace(s[pos]))
- pos++;
-
- return pos - origpos;
-}
-
-/*
- * Support for Erlang -- Anders Lindgren, Feb 1996.
- *
- * Generates tags for functions, defines, and records.
- *
- * Assumes that Erlang functions start at column 0.
- */
-void
-Erlang_functions (inf)
- FILE *inf;
-{
- int erlang_func ();
- void erlang_attribute ();
-
- char * last;
- int len;
- int allocated;
-
- allocated = 0;
- len = 0;
- last = NULL;
-
- lineno = 0;
- linecharno = 0;
- charno = 0;
-
- while (!feof (inf))
- {
- lineno++;
- linecharno += charno;
- charno = readline (&lb, inf);
- dbp = lb.buffer;
- if (dbp[0] == '\0') /* Empty line */
- continue;
- else if (isspace (dbp[0])) /* Not function nor attribute */
- continue;
- else if (dbp[0] == '%') /* comment */
- continue;
- else if (dbp[0] == '"') /* Sometimes, strings start in column one */
- continue;
- else if (dbp[0] == '-') /* attribute, e.g. "-define" */
- {
- erlang_attribute(dbp);
- last = NULL;
- }
- else if (len = erlang_func (dbp, last))
- {
- /*
- * Function. Store the function name so that we only
- * generates a tag for the first clause.
- */
- if (last == NULL)
- last = xnew(len + 1, char);
- else if (len + 1 > allocated)
- last = (char *) xrealloc(last, len + 1);
- allocated = len + 1;
- strncpy (last, dbp, len);
- last[len] = '\0';
- }
- }
-}
-
-
-/*
- * A function definition is added if it matches:
- * <beginning of line><Erlang Atom><whitespace>(
- *
- * It is added to the tags database if it doesn't match the
- * name of the previous clause header.
- *
- * Return the size of the name of the function, or 0 if no function
- * was found.
- */
-int
-erlang_func (s, last)
- char *s;
- char *last; /* Name of last clause. */
-{
- int erlang_atom ();
- int erlang_white ();
-
- int pos;
- int len;
-
- pos = erlang_atom(s, 0);
- if (pos < 1)
- return 0;
-
- len = pos;
- pos += erlang_white(s, pos);
-
- if (s[pos++] == '(')
- {
- /* Save only the first clause. */
- if ((last == NULL) ||
- (len != strlen(last)) ||
- (strncmp(s, last, len) != 0))
- {
- pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
- s, pos, lineno, linecharno);
- return len;
- }
- }
- return 0;
-}
-
-
-/*
- * Handle attributes. Currently, tags are generated for defines
- * and records.
- *
- * They are on the form:
- * -define(foo, bar).
- * -define(Foo(M, N), M+N).
- * -record(graph, {vtab = notable, cyclic = true}).
- */
-void
-erlang_attribute (s)
- char *s;
-{
- int erlang_atom ();
- int erlang_white ();
-
- int pos;
- int len;
-
- if ((strncmp(s, "-define", 7) == 0) ||
- (strncmp(s, "-record", 7) == 0))
- {
- pos = 7;
- pos += erlang_white(s, pos);
-
- if (s[pos++] == '(')
- {
- pos += erlang_white(s, pos);
-
- if (len = erlang_atom(s, pos))
- {
- pfnote ((CTAGS) ? savenstr (& s[pos], len) : NULL, TRUE,
- s, pos + len, lineno, linecharno);
- }
- }
- }
- return;
-}
-
-
-/*
- * Consume an Erlang atom (or variable).
- * Return the number of bytes consumed, or -1 if there was an error.
- */
-int
-erlang_atom (s, pos)
- char *s;
- int pos;
-{
- int origpos;
-
- origpos = pos;
-
- if (isalpha (s[pos]) || s[pos] == '_')
- {
- /* The atom is unquoted. */
- pos++;
- while (isalnum (s[pos]) || s[pos] == '_')
- pos++;
- return pos - origpos;
- }
- else if (s[pos] == '\'')
- {
- pos++;
-
- while (1)
- {
- if (s[pos] == '\'')
- {
- pos++;
- break;
- }
- else if (s[pos] == '\0')
- /* Multiline quoted atoms are ignored. */
- return -1;
- else if (s[pos] == '\\')
- {
- if (s[pos+1] == '\0')
- return -1;
- pos += 2;
- }
- else
- pos++;
- }
- return pos - origpos;
- }
- else
- return -1;
-}
-
-/* Consume whitespace. Return the number of bytes eaten */
-int
-erlang_white (s, pos)
- char *s;
- int pos;
-{
- int origpos;
-
- origpos = pos;
-
- while (isspace (s[pos]))
- pos++;
-
- return pos - origpos;
-}
-
-#ifdef ETAGS_REGEXPS
-/* Take a string like "/blah/" and turn it into "blah", making sure
- that the first and last characters are the same, and handling
- quoted separator characters. Actually, stops on the occurrence of
- an unquoted separator. Also turns "\t" into a Tab character.
- Returns pointer to terminating separator. Works in place. Null
- terminates name string. */
-char *
-scan_separators (name)
- char *name;
-{
- char sep = name[0];
- char *copyto = name;
- logical quoted = FALSE;
-
- for (++name; *name != '\0'; ++name)
- {
- if (quoted)
- {
- if (*name == 't')
- *copyto++ = '\t';
- else if (*name == sep)
- *copyto++ = sep;
- else
- {
- /* Something else is quoted, so preserve the quote. */
- *copyto++ = '\\';
- *copyto++ = *name;
- }
- quoted = FALSE;
- }
- else if (*name == '\\')
- quoted = TRUE;
- else if (*name == sep)
- break;
- else
- *copyto++ = *name;
- }
-
- /* Terminate copied string. */
- *copyto = '\0';
- return name;
-}
-
-/* Turn a name, which is an ed-style (but Emacs syntax) regular
- expression, into a real regular expression by compiling it. */
-void
-add_regex (regexp_pattern)
- char *regexp_pattern;
-{
- char *name;
- const char *err;
- struct re_pattern_buffer *patbuf;
-
- if (regexp_pattern == NULL)
- {
- /* Remove existing regexps. */
- num_patterns = 0;
- patterns = NULL;
- return;
- }
-
- if (regexp_pattern[0] == '\0')
- {
- error ("missing regexp", (char *)NULL);
- return;
- }
- if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0])
- {
- error ("%s: unterminated regexp", regexp_pattern);
- return;
- }
- name = scan_separators (regexp_pattern);
- if (regexp_pattern[0] == '\0')
- {
- error ("null regexp", (char *)NULL);
- return;
- }
- (void) scan_separators (name);
-
- patbuf = xnew (1, struct re_pattern_buffer);
- patbuf->translate = NULL;
- patbuf->fastmap = NULL;
- patbuf->buffer = NULL;
- patbuf->allocated = 0;
-
- err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf);
- if (err != NULL)
- {
- error ("%s while compiling pattern", err);
- return;
- }
-
- num_patterns += 1;
- if (num_patterns == 1)
- patterns = xnew (1, struct pattern);
- else
- patterns = ((struct pattern *)
- xrealloc (patterns,
- (num_patterns * sizeof (struct pattern))));
- patterns[num_patterns - 1].pattern = patbuf;
- patterns[num_patterns - 1].name_pattern = savestr (name);
- patterns[num_patterns - 1].error_signaled = FALSE;
-}
-
-/*
- * Do the substitutions indicated by the regular expression and
- * arguments.
- */
-char *
-substitute (in, out, regs)
- char *in, *out;
- struct re_registers *regs;
-{
- char *result = NULL, *t;
- int size = 0;
-
- /* Pass 1: figure out how much size to allocate. */
- for (t = out; *t; ++t)
- {
- if (*t == '\\')
- {
- ++t;
- if (!*t)
- {
- fprintf (stderr, "%s: pattern substitution ends prematurely\n",
- progname);
- return NULL;
- }
- if (isdigit (*t))
- {
- int dig = *t - '0';
- size += regs->end[dig] - regs->start[dig];
- }
- }
- }
-
- /* Allocate space and do the substitutions. */
- result = xnew (size + 1, char);
- size = 0;
- for (; *out; ++out)
- {
- if (*out == '\\')
- {
- ++out;
- if (isdigit (*out))
- {
- /* Using "dig2" satisfies my debugger. Bleah. */
- int dig2 = *out - '0';
- strncpy (result + size, in + regs->start[dig2],
- regs->end[dig2] - regs->start[dig2]);
- size += regs->end[dig2] - regs->start[dig2];
- }
- else
- result[size++] = *out;
- }
- else
- result[size++] = *out;
- }
- result[size] = '\0';
-
- return result;
-}
-
-#endif /* ETAGS_REGEXPS */
-/* Initialize a linebuffer for use */
-void
-initbuffer (linebuffer)
- struct linebuffer *linebuffer;
-{
- linebuffer->size = 200;
- linebuffer->buffer = xnew (200, char);
-}
-
-/*
- * Read a line of text from `stream' into `linebuffer'.
- * Return the number of characters read from `stream',
- * which is the length of the line including the newline, if any.
- */
-long
-readline_internal (linebuffer, stream)
- struct linebuffer *linebuffer;
- register FILE *stream;
-{
- char *buffer = linebuffer->buffer;
- register char *p = linebuffer->buffer;
- register char *pend;
- int chars_deleted;
-
- pend = p + linebuffer->size; /* Separate to avoid 386/IX compiler bug. */
-
- while (1)
- {
- register 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 == EOF)
- {
- *p = '\0';
- chars_deleted = 0;
- break;
- }
- if (c == '\n')
- {
- if (p > buffer && p[-1] == '\r')
- {
- *--p = '\0';
-#ifdef DOS_NT
- /* Assume CRLF->LF translation will be performed by Emacs
- when loading this file, so CRs won't appear in the buffer.
- It would be cleaner to compensate within Emacs;
- however, Emacs does not know how many CRs were deleted
- before any given point in the file. */
- chars_deleted = 1;
-#else
- chars_deleted = 2;
-#endif
- }
- else
- {
- *p = '\0';
- chars_deleted = 1;
- }
- break;
- }
- *p++ = c;
- }
-
- return p - buffer + chars_deleted;
-}
-
-/*
- * Like readline_internal, above, but try to match the input
- * line against any existing regular expressions.
- */
-long
-readline (linebuffer, stream)
- struct linebuffer *linebuffer;
- FILE *stream;
-{
- /* Read new line. */
- long result = readline_internal (linebuffer, stream);
-#ifdef ETAGS_REGEXPS
- int i;
-
- /* Match against all listed patterns. */
- for (i = 0; i < num_patterns; ++i)
- {
- int match = re_match (patterns[i].pattern, linebuffer->buffer,
- (int)result, 0, &patterns[i].regs);
- switch (match)
- {
- case -2:
- /* Some error. */
- if (!patterns[i].error_signaled)
- {
- error ("error while matching pattern %d", i);
- patterns[i].error_signaled = TRUE;
- }
- break;
- case -1:
- /* No match. */
- break;
- default:
- /* Match occurred. Construct a tag. */
- if (patterns[i].name_pattern[0] != '\0')
- {
- /* Make a named tag. */
- char *name = substitute (linebuffer->buffer,
- patterns[i].name_pattern,
- &patterns[i].regs);
- if (name != NULL)
- pfnote (name, TRUE,
- linebuffer->buffer, match, lineno, linecharno);
- }
- else
- {
- /* Make an unnamed tag. */
- pfnote ((char *)NULL, TRUE,
- linebuffer->buffer, match, lineno, linecharno);
- }
- break;
- }
- }
-#endif /* ETAGS_REGEXPS */
-
- return result;
-}
-
-/*
- * Read a file, but do no processing. This is used to do regexp
- * matching on files that have no language defined.
- */
-void
-just_read_file (inf)
- FILE *inf;
-{
- lineno = 0;
- charno = 0;
-
- while (!feof (inf))
- {
- ++lineno;
- linecharno = charno;
- charno += readline (&lb, inf) + 1;
- }
-}
-
-
-/*
- * Return a pointer to a space of size strlen(cp)+1 allocated
- * with xnew where the string CP has been copied.
- */
-char *
-savestr (cp)
- char *cp;
-{
- return savenstr (cp, strlen (cp));
-}
-
-/*
- * Return a pointer to a space of size LEN+1 allocated with xnew where
- * the string CP has been copied for at most the first LEN characters.
- */
-char *
-savenstr (cp, len)
- char *cp;
- int len;
-{
- register char *dp;
-
- dp = xnew (len + 1, char);
- 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 System V strrchr, included for portability.
- */
-char *
-etags_strrchr (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 System V strchr, included for portability.
- */
-char *
-etags_strchr (sp, c)
- register char *sp, c;
-{
- do
- {
- if (*sp == c)
- return sp;
- } while (*sp++);
- return NULL;
-}
-
-/* Print error message and exit. */
-void
-fatal (s1, s2)
- char *s1, *s2;
-{
- error (s1, s2);
- exit (BAD);
-}
-
-void
-pfatal (s1)
- char *s1;
-{
- perror (s1);
- exit (BAD);
-}
-
-void
-suggest_asking_for_help ()
-{
- fprintf (stderr, "\tTry `%s --help' for a complete list of options.\n",
- progname);
- exit (BAD);
-}
-
-/* Print error message. `s1' is printf control string, `s2' is arg for it. */
-void
-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 = xnew (len1 + len2 + len3 + 1, char);
-
- strcpy (result, s1);
- strcpy (result + len1, s2);
- strcpy (result + len1 + len2, s3);
- result[len1 + len2 + len3] = '\0';
-
- return result;
-}
-
-/* Does the same work as the system V getcwd, but does not need to
- guess the buffer size in advance. */
-char *
-etags_getcwd ()
-{
-#ifdef HAVE_GETCWD
- int bufsize = 200;
- char *path = xnew (bufsize, char);
-
- while (getcwd (path, bufsize) == NULL)
- {
- if (errno != ERANGE)
- pfatal ("getcwd");
- bufsize *= 2;
- path = xnew (bufsize, char);
- }
-
-#if WINDOWSNT
- {
- /* Convert backslashes to slashes. */
- char *p;
- for (p = path; *p != '\0'; p++)
- if (*p == '\\')
- *p = '/';
- }
-#endif
-
- return path;
-
-#else /* not HAVE_GETCWD */
-#ifdef MSDOS
- char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */
-
- getwd (path);
-
- for (p = path; *p != '\0'; p++)
- if (*p == '\\')
- *p = '/';
- else
- *p = lowcase (*p);
-
- return strdup (path);
-#else /* not MSDOS */
- struct linebuffer path;
- FILE *pipe;
-
- initbuffer (&path);
- pipe = (FILE *) popen ("pwd 2>/dev/null", "r");
- if (pipe == NULL || readline_internal (&path, pipe) == 0)
- pfatal ("pwd");
- pclose (pipe);
-
- return path.buffer;
-#endif /* not MSDOS */
-#endif /* not HAVE_GETCWD */
-}
-
-/* Return a newly allocated string containing the filename
- of FILE relative to the absolute directory DIR (which
- should end with a slash). */
-char *
-relative_filename (file, dir)
- char *file, *dir;
-{
- char *fp, *dp, *abs, *res;
-
- /* Find the common root of file and dir (with a trailing slash). */
- abs = absolute_filename (file, cwd);
- fp = abs;
- dp = dir;
- while (*fp++ == *dp++)
- continue;
- fp--, dp--; /* back to the first differing char */
- do /* look at the equal chars until / */
- fp--, dp--;
- while (*fp != '/');
-
- /* Build a sequence of "../" strings for the resulting relative filename. */
- for (dp = etags_strchr (dp + 1, '/'), res = "";
- dp != NULL;
- dp = etags_strchr (dp + 1, '/'))
- {
- res = concat (res, "../", "");
- }
-
- /* Add the filename relative to the common root of file and dir. */
- res = concat (res, fp + 1, "");
- free (abs);
-
- return res;
-}
-
-/* Return a newly allocated string containing the
- absolute filename of FILE given CWD (which should
- end with a slash). */
-char *
-absolute_filename (file, cwd)
- char *file, *cwd;
-{
- char *slashp, *cp, *res;
-
- if (absolutefn (file))
- res = concat (file, "", "");
-#ifdef DOS_NT
- /* We don't support non-absolute filenames with a drive
- letter, like `d:NAME' (it's too much hassle). */
- else if (file[1] == ':')
- fatal ("%s: relative filenames with drive letters not supported", file);
-#endif
- else
- res = concat (cwd, file, "");
-
- /* Delete the "/dirname/.." and "/." substrings. */
- slashp = etags_strchr (res, '/');
- while (slashp != NULL && slashp[0] != '\0')
- {
- if (slashp[1] == '.')
- {
- if (slashp[2] == '.'
- && (slashp[3] == '/' || slashp[3] == '\0'))
- {
- cp = slashp;
- do
- cp--;
- while (cp >= res && !absolutefn (cp));
- if (*cp == '/')
- {
- strcpy (cp, slashp + 3);
- }
-#ifdef DOS_NT
- /* Under MSDOS and NT we get `d:/NAME' as absolute
- filename, so the luser could say `d:/../NAME'.
- We silently treat this as `d:/NAME'. */
- else if (cp[1] == ':')
- strcpy (cp + 3, slashp + 4);
-#endif
- else /* else (cp == res) */
- {
- if (slashp[3] != '\0')
- strcpy (cp, slashp + 4);
- else
- return ".";
- }
- slashp = cp;
- continue;
- }
- else if (slashp[2] == '/' || slashp[2] == '\0')
- {
- strcpy (slashp, slashp + 2);
- continue;
- }
- }
-
- slashp = etags_strchr (slashp + 1, '/');
- }
-
- return res;
-}
-
-/* Return a newly allocated string containing the absolute
- filename of dir where FILE resides given CWD (which should
- end with a slash). */
-char *
-absolute_dirname (file, cwd)
- char *file, *cwd;
-{
- char *slashp, *res;
- char save;
-#ifdef DOS_NT
- char *p;
-
- for (p = file; *p != '\0'; p++)
- if (*p == '\\')
- *p = '/';
-#endif
-
- slashp = etags_strrchr (file, '/');
- if (slashp == NULL)
- return cwd;
- save = slashp[1];
- slashp[1] = '\0';
- res = absolute_filename (file, cwd);
- slashp[1] = save;
-
- return res;
-}
-
-/* Increase the size of a linebuffer. */
-void
-grow_linebuffer (bufp, toksize)
- struct linebuffer *bufp;
- int toksize;
-{
- while (bufp->size < toksize)
- bufp->size *= 2;
- bufp->buffer = (char *) xrealloc (bufp->buffer, bufp->size);
-}
-
-/* Like malloc but get fatal error if memory is exhausted. */
-long *
-xmalloc (size)
- unsigned int size;
-{
- long *result = (long *) malloc (size);
- if (result == NULL)
- fatal ("virtual memory exhausted", (char *)NULL);
- return result;
-}
-
-long *
-xrealloc (ptr, size)
- char *ptr;
- unsigned int size;
-{
- long *result = (long *) realloc (ptr, size);
- if (result == NULL)
- fatal ("virtual memory exhausted", (char *)NULL);
- return result;
-}
diff --git a/lib-src/fakemail.c b/lib-src/fakemail.c
deleted file mode 100644
index 1deeec352b2..00000000000
--- a/lib-src/fakemail.c
+++ /dev/null
@@ -1,751 +0,0 @@
-/* sendmail-like interface to /bin/mail for system V,
- Copyright (C) 1985, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#define NO_SHORTNAMES
-#include <../src/config.h>
-
-#if defined (BSD_SYSTEM) && !defined (BSD4_1) && !defined (USE_FAKEMAIL)
-/* This program isnot used in BSD, so just avoid loader complaints. */
-int
-main ()
-{
- return 0;
-}
-#else /* not BSD 4.2 (or newer) */
-#ifdef MSDOS
-int
-main ()
-{
- return 0;
-}
-#else /* not MSDOS */
-/* This conditional contains all the rest of the file. */
-
-/* These are defined in config in some versions. */
-
-#ifdef static
-#undef static
-#endif
-
-#ifdef read
-#undef read
-#undef write
-#undef open
-#undef close
-#endif
-
-#ifdef WINDOWSNT
-#include "ntlib.h"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-#include <pwd.h>
-
-/* Type definitions */
-
-#define boolean int
-#define true 1
-#define false 0
-
-/* Various lists */
-
-struct line_record
-{
- char *string;
- struct line_record *continuation;
-};
-typedef struct line_record *line_list;
-
-struct header_record
-{
- line_list text;
- struct header_record *next;
- struct header_record *previous;
-};
-typedef struct header_record *header;
-
-struct stream_record
-{
- FILE *handle;
- int (*action)();
- struct stream_record *rest_streams;
-};
-typedef struct stream_record *stream_list;
-
-/* 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;
-
-#define new_list() \
- ((line_list) xmalloc (sizeof (struct line_record)))
-#define new_header() \
- ((header) xmalloc (sizeof (struct header_record)))
-#define new_stream() \
- ((stream_list) xmalloc (sizeof (struct stream_record)))
-#define alloc_string(nchars) \
- ((char *) xmalloc ((nchars) + 1))
-
-/* Global declarations */
-
-#define BUFLEN 1024
-#define KEYWORD_SIZE 256
-#define FROM_PREFIX "From"
-#define MY_NAME "fakemail"
-#define NIL ((line_list) NULL)
-#define INITIAL_LINE_SIZE 200
-
-#ifndef MAIL_PROGRAM_NAME
-#define MAIL_PROGRAM_NAME "/bin/mail"
-#endif
-
-static char *my_name;
-static char *the_date;
-static char *the_user;
-static line_list file_preface;
-static stream_list the_streams;
-static boolean no_problems = true;
-
-extern FILE *popen ();
-extern int fclose (), pclose ();
-
-#ifdef CURRENT_USER
-extern struct passwd *getpwuid ();
-extern unsigned short geteuid ();
-static struct passwd *my_entry;
-#define cuserid(s) \
-(my_entry = getpwuid (((int) geteuid ())), \
- my_entry->pw_name)
-#endif
-
-/* Utilities */
-
-/* Print error message. `s1' is printf control string, `s2' is arg for it. */
-
-static void
-error (s1, s2)
- char *s1, *s2;
-{
- printf ("%s: ", my_name);
- printf (s1, s2);
- printf ("\n");
- no_problems = false;
-}
-
-/* Print error message and exit. */
-
-static void
-fatal (s1, s2)
- char *s1, *s2;
-{
- error (s1, s2);
- exit (1);
-}
-
-/* Like malloc but get fatal error if memory is exhausted. */
-
-static long *
-xmalloc (size)
- int size;
-{
- long *result = (long *) malloc (((unsigned) size));
- if (result == ((long *) NULL))
- fatal ("virtual memory exhausted", 0);
- return result;
-}
-
-static long *
-xrealloc (ptr, size)
- long *ptr;
- int size;
-{
- long *result = (long *) realloc (ptr, ((unsigned) size));
- if (result == ((long *) NULL))
- fatal ("virtual memory exhausted");
- return result;
-}
-
-/* Initialize a linebuffer for use */
-
-void
-init_linebuffer (linebuffer)
- struct linebuffer *linebuffer;
-{
- linebuffer->size = INITIAL_LINE_SIZE;
- linebuffer->buffer = ((char *) xmalloc (INITIAL_LINE_SIZE));
-}
-
-/* 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 (true)
- {
- int c = getc (stream);
- if (p == end)
- {
- linebuffer->size *= 2;
- buffer = ((char *) xrealloc (buffer, linebuffer->size));
- p = buffer + (p - linebuffer->buffer);
- end = buffer + linebuffer->size;
- linebuffer->buffer = buffer;
- }
- if (c < 0 || c == '\n')
- {
- *p = 0;
- break;
- }
- *p++ = c;
- }
-
- return p - buffer;
-}
-
-/* Extract a colon-terminated keyword from the string FIELD.
- Return that keyword as a string stored in a static buffer.
- Store the address of the rest of the string into *REST.
-
- If there is no keyword, return NULL and don't alter *REST. */
-
-char *
-get_keyword (field, rest)
- register char *field;
- char **rest;
-{
- static char keyword[KEYWORD_SIZE];
- register char *ptr;
- register char c;
-
- ptr = &keyword[0];
- c = *field++;
- if (isspace (c) || c == ':')
- return ((char *) NULL);
- *ptr++ = (islower (c) ? toupper (c) : c);
- while (((c = *field++) != ':') && ! isspace (c))
- *ptr++ = (islower (c) ? toupper (c) : c);
- *ptr++ = '\0';
- while (isspace (c))
- c = *field++;
- if (c != ':')
- return ((char *) NULL);
- *rest = field;
- return &keyword[0];
-}
-
-/* Nonzero if the string FIELD starts with a colon-terminated keyword. */
-
-boolean
-has_keyword (field)
- char *field;
-{
- char *ignored;
- return (get_keyword (field, &ignored) != ((char *) NULL));
-}
-
-/* Store the string FIELD, followed by any lines in THE_LIST,
- into the buffer WHERE.
- Concatenate lines, putting just a space between them.
- Delete everything contained in parentheses.
- When a recipient name contains <...>, we discard
- everything except what is inside the <...>.
-
- We don't pay attention to overflowing WHERE;
- the caller has to make it big enough. */
-
-char *
-add_field (the_list, field, where)
- line_list the_list;
- register char *field, *where;
-{
- register char c;
- while (true)
- {
- char *this_recipient_where;
- int in_quotes = 0;
-
- *where++ = ' ';
- this_recipient_where = where;
-
- while ((c = *field++) != '\0')
- {
- if (c == '\\')
- *where++ = c;
- else if (c == '"')
- {
- in_quotes = ! in_quotes;
- *where++ = c;
- }
- else if (in_quotes)
- *where++ = c;
- else if (c == '(')
- {
- while (*field && *field != ')') ++field;
- if (! (*field++)) break; /* no close */
- continue;
- }
- else if (c == ',')
- {
- *where++ = ' ';
- /* When we get to the end of one recipient,
- don't discard it if the next one has <...>. */
- this_recipient_where = where;
- }
- else if (c == '<')
- /* Discard everything we got before the `<'. */
- where = this_recipient_where;
- else if (c == '>')
- /* Discard the rest of this name that follows the `>'. */
- {
- while (*field && *field != ',') ++field;
- if (! (*field++)) break; /* no comma */
- continue;
- }
- else
- *where++ = c;
- }
- if (the_list == NIL) break;
- field = the_list->string;
- the_list = the_list->continuation;
- }
- return where;
-}
-
-line_list
-make_file_preface ()
-{
- char *the_string, *temp;
- long idiotic_interface;
- long prefix_length;
- long user_length;
- long date_length;
- line_list result;
-
- prefix_length = strlen (FROM_PREFIX);
- time (&idiotic_interface);
- the_date = ctime (&idiotic_interface);
- /* the_date has an unwanted newline at the end */
- date_length = strlen (the_date) - 1;
- the_date[date_length] = '\0';
- temp = cuserid ((char *) NULL);
- user_length = strlen (temp);
- the_user = alloc_string (user_length + 1);
- strcpy (the_user, temp);
- the_string = alloc_string (3 + prefix_length +
- user_length +
- date_length);
- temp = the_string;
- strcpy (temp, FROM_PREFIX);
- temp = &temp[prefix_length];
- *temp++ = ' ';
- strcpy (temp, the_user);
- temp = &temp[user_length];
- *temp++ = ' ';
- strcpy (temp, the_date);
- result = new_list ();
- result->string = the_string;
- result->continuation = ((line_list) NULL);
- return result;
-}
-
-void
-write_line_list (the_list, the_stream)
- register line_list the_list;
- FILE *the_stream;
-{
- for ( ;
- the_list != ((line_list) NULL) ;
- the_list = the_list->continuation)
- {
- fputs (the_list->string, the_stream);
- putc ('\n', the_stream);
- }
- return;
-}
-
-int
-close_the_streams ()
-{
- register stream_list rem;
- for (rem = the_streams;
- rem != ((stream_list) NULL);
- rem = rem->rest_streams)
- no_problems = (no_problems &&
- ((*rem->action) (rem->handle) == 0));
- the_streams = ((stream_list) NULL);
- return (no_problems ? 0 : 1);
-}
-
-void
-add_a_stream (the_stream, closing_action)
- FILE *the_stream;
- int (*closing_action)();
-{
- stream_list old = the_streams;
- the_streams = new_stream ();
- the_streams->handle = the_stream;
- the_streams->action = closing_action;
- the_streams->rest_streams = old;
- return;
-}
-
-int
-my_fclose (the_file)
- FILE *the_file;
-{
- putc ('\n', the_file);
- fflush (the_file);
- return fclose (the_file);
-}
-
-boolean
-open_a_file (name)
- char *name;
-{
- FILE *the_stream = fopen (name, "a");
- if (the_stream != ((FILE *) NULL))
- {
- add_a_stream (the_stream, my_fclose);
- if (the_user == ((char *) NULL))
- file_preface = make_file_preface ();
- write_line_list (file_preface, the_stream);
- return true;
- }
- return false;
-}
-
-void
-put_string (s)
- char *s;
-{
- register stream_list rem;
- for (rem = the_streams;
- rem != ((stream_list) NULL);
- rem = rem->rest_streams)
- fputs (s, rem->handle);
- return;
-}
-
-void
-put_line (string)
- char *string;
-{
- 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++;
- }
- /* If we didn't reach end of line, break the line. */
- if (*breakpos)
- {
- /* 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);
- column = 8;
-
- /* Skip whitespace and prepare to print more addresses. */
- s = breakpos;
- while (*s == ' ' || *s == '\t') ++s;
- if (*s != 0)
- fputs ("\n\t", rem->handle);
- }
- putc ('\n', rem->handle);
- }
- return;
-}
-
-#define mail_error error
-
-/* Handle an FCC field. FIELD is the text of the first line (after
- the header name), and THE_LIST holds the continuation lines if any.
- Call open_a_file for each file. */
-
-void
-setup_files (the_list, field)
- register line_list the_list;
- register char *field;
-{
- register char *start;
- register char c;
- while (true)
- {
- while (((c = *field) != '\0')
- && (c == ' '
- || c == '\t'
- || c == ','))
- field += 1;
- if (c != '\0')
- {
- start = field;
- while (((c = *field) != '\0')
- && c != ' '
- && c != '\t'
- && c != ',')
- field += 1;
- *field = '\0';
- if (!open_a_file (start))
- mail_error ("Could not open file %s", start);
- *field = c;
- if (c != '\0') continue;
- }
- if (the_list == ((line_list) NULL))
- return;
- field = the_list->string;
- the_list = the_list->continuation;
- }
-}
-
-/* Compute the total size of all recipient names stored in THE_HEADER.
- The result says how big to make the buffer to pass to parse_header. */
-
-int
-args_size (the_header)
- header the_header;
-{
- register header old = the_header;
- register line_list rem;
- register int size = 0;
- do
- {
- char *field;
- register char *keyword = get_keyword (the_header->text->string, &field);
- if ((strcmp (keyword, "TO") == 0)
- || (strcmp (keyword, "CC") == 0)
- || (strcmp (keyword, "BCC") == 0))
- {
- size += 1 + strlen (field);
- for (rem = the_header->text->continuation;
- rem != NIL;
- rem = rem->continuation)
- size += 1 + strlen (rem->string);
- }
- the_header = the_header->next;
- } while (the_header != old);
- return size;
-}
-
-/* Scan the header described by the lists THE_HEADER,
- and put all recipient names into the buffer WHERE.
- Precede each recipient name with a space.
-
- Also, if the header has any FCC fields, call setup_files for each one. */
-
-parse_header (the_header, where)
- header the_header;
- register char *where;
-{
- register header old = the_header;
- do
- {
- char *field;
- register char *keyword = get_keyword (the_header->text->string, &field);
- if (strcmp (keyword, "TO") == 0)
- where = add_field (the_header->text->continuation, field, where);
- else if (strcmp (keyword, "CC") == 0)
- where = add_field (the_header->text->continuation, field, where);
- else if (strcmp (keyword, "BCC") == 0)
- {
- where = add_field (the_header->text->continuation, field, where);
- the_header->previous->next = the_header->next;
- the_header->next->previous = the_header->previous;
- }
- else if (strcmp (keyword, "FCC") == 0)
- setup_files (the_header->text->continuation, field);
- the_header = the_header->next;
- } while (the_header != old);
- *where = '\0';
- return;
-}
-
-/* Read lines from the input until we get a blank line.
- Create a list of `header' objects, one for each header field,
- each of which points to a list of `line_list' objects,
- one for each line in that field.
- Continuation lines are grouped in the headers they continue. */
-
-header
-read_header ()
-{
- register header the_header = ((header) NULL);
- register line_list *next_line = ((line_list *) NULL);
-
- init_linebuffer (&lb);
-
- do
- {
- long length;
- register char *line;
-
- readline (&lb, stdin);
- line = lb.buffer;
- length = strlen (line);
- if (length == 0) break;
-
- if (has_keyword (line))
- {
- register header old = the_header;
- the_header = new_header ();
- if (old == ((header) NULL))
- {
- the_header->next = the_header;
- the_header->previous = the_header;
- }
- else
- {
- the_header->previous = old;
- the_header->next = old->next;
- old->next = the_header;
- }
- next_line = &(the_header->text);
- }
-
- if (next_line == ((line_list *) NULL))
- {
- /* Not a valid header */
- exit (1);
- }
- *next_line = new_list ();
- (*next_line)->string = alloc_string (length);
- strcpy (((*next_line)->string), line);
- next_line = &((*next_line)->continuation);
- *next_line = NIL;
-
- } while (true);
-
- return the_header->next;
-}
-
-void
-write_header (the_header)
- header the_header;
-{
- register header old = the_header;
- do
- {
- register line_list the_list;
- for (the_list = the_header->text;
- the_list != NIL;
- the_list = the_list->continuation)
- put_line (the_list->string);
- the_header = the_header->next;
- } while (the_header != old);
- put_line ("");
- return;
-}
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- char *command_line;
- header the_header;
- long name_length;
- char *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);
- the_user = ((char *) NULL);
-
- the_header = read_header ();
- command_line = alloc_string (name_length + args_size (the_header));
- strcpy (command_line, mail_program_name);
- parse_header (the_header, &command_line[name_length]);
-
- the_pipe = popen (command_line, "w");
- if (the_pipe == ((FILE *) NULL))
- fatal ("cannot open pipe to real mailer");
-
- add_a_stream (the_pipe, pclose);
-
- write_header (the_header);
-
- /* Dump the message itself */
-
- while (!feof (stdin))
- {
- size = fread (buf, 1, BUFLEN, stdin);
- buf[size] = '\0';
- put_string (buf);
- }
-
- exit (close_the_streams ());
-}
-
-#endif /* not MSDOS */
-#endif /* not BSD 4.2 (or newer) */
diff --git a/lib-src/hexl.c b/lib-src/hexl.c
deleted file mode 100644
index 9731321d4ae..00000000000
--- a/lib-src/hexl.c
+++ /dev/null
@@ -1,262 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <ctype.h>
-#ifdef DOS_NT
-#include <fcntl.h>
-#if __DJGPP__ >= 2
-#include <io.h>
-#endif
-#endif
-#ifdef WINDOWSNT
-#include <io.h>
-#endif
-
-#define DEFAULT_GROUPING 0x01
-#define DEFAULT_BASE 16
-
-#undef TRUE
-#undef FALSE
-#define TRUE (1)
-#define FALSE (0)
-
-int base = DEFAULT_BASE, un_flag = FALSE, iso_flag = FALSE, endian = 1;
-int group_by = DEFAULT_GROUPING;
-char *progname;
-
-void usage();
-
-int
-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
- {
- 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];
-
-#ifdef DOS_NT
-#if (__DJGPP__ >= 2) || (defined WINDOWSNT)
- if (!isatty (fileno (stdout)))
- setmode (fileno (stdout), O_BINARY);
-#else
- (stdout)->_flag &= ~_IOTEXT; /* print binary */
- _setmode (fileno (stdout), O_BINARY);
-#endif
-#endif
- for (;;)
- {
- register int i, c, d;
-
-#define hexchar(x) (isdigit (x) ? x - '0' : x - 'a' + 10)
-
- 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);
- putchar (c);
-
- if ((i&group_by) == group_by)
- getc (fp);
- }
-
- if (c == ' ')
- {
- while ((c = getc (fp)) != '\n' && c != EOF)
- ;
-
- if (c == EOF)
- break;
- }
- else
- {
- if (i < 16)
- break;
-
- fread (buf, 1, 18, fp); /* skip 18 bytes */
- }
- }
- }
- else
- {
-#ifdef DOS_NT
-#if (__DJGPP__ >= 2) || (defined WINDOWSNT)
- if (!isatty (fileno (fp)))
- setmode (fileno (fp), O_BINARY);
-#else
- (fp)->_flag &= ~_IOTEXT; /* read binary */
- _setmode (fileno (fp), O_BINARY);
-#endif
-#endif
- 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;
-
- fputs (" ", stdout);
- string[i+1] = '\0';
- }
- else
- {
- if (!i)
- 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;
-
- printf ("%02x", c);
- }
-
- if ((i&group_by) == group_by)
- putchar (' ');
- }
-
- if (i)
- puts (string);
-
- if (c == EOF)
- break;
-
- address += 0x10;
-
- }
- }
-
- if (fp != stdin)
- fclose (fp);
-
- } while (*argv != NULL);
- return 0;
-}
-
-void
-usage ()
-{
- fprintf (stderr, "usage: %s [-de] [-iso]\n", progname);
- exit (1);
-}
diff --git a/lib-src/leditcfns.c b/lib-src/leditcfns.c
deleted file mode 100644
index b8a7a6bfe1f..00000000000
--- a/lib-src/leditcfns.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <sgtty.h>
-#include <signal.h>
-#define STRLEN 100
-static char str[STRLEN+1] = "%?emacs"; /* extra char for the null */
-
-switch_to_proc(){
- char *ptr = str;
- while (*ptr) ioctl(0, TIOCSTI, ptr++);
- ioctl(0, TIOCSTI, "\n");
- kill(getpid(), SIGTSTP);
- }
-
-set_proc_str(ptr) char *ptr; {
- if (strlen(ptr) <= STRLEN)
- strcpy(str, ptr);
- else
- printf("string too long for set-proc-str: %s\n", ptr);
- }
diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c
deleted file mode 100644
index b0072672114..00000000000
--- a/lib-src/make-docfile.c
+++ /dev/null
@@ -1,887 +0,0 @@
-/* Generate doc-string file for GNU Emacs from source files.
- Copyright (C) 1985, 1986, 1992, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* The arguments given to this program are all the C and Lisp source files
- of GNU Emacs. .elc and .el and .c files are allowed.
- A .o file can also be specified; the .c file it was made from is used.
- This helps the makefile pass the correct list of files.
-
- The results, which go to standard output or to a file
- specified with -a or -o (-a to append, -o to start from nothing),
- are entries containing function or variable names and their documentation.
- Each entry starts with a ^_ character.
- Then comes F for a function or V for a variable.
- Then comes the function or variable name, terminated with a newline.
- Then comes the documentation for that function or variable.
- */
-
-#define NO_SHORTNAMES /* Tell config not to load remap.h */
-#include <../src/config.h>
-
-#include <stdio.h>
-#ifdef MSDOS
-#include <fcntl.h>
-#endif /* MSDOS */
-#ifdef WINDOWSNT
-#include <stdlib.h>
-#include <fcntl.h>
-#include <direct.h>
-#endif /* WINDOWSNT */
-
-#ifdef DOS_NT
-#define READ_TEXT "rt"
-#define READ_BINARY "rb"
-#else /* not DOS_NT */
-#define READ_TEXT "r"
-#define READ_BINARY "r"
-#endif /* not DOS_NT */
-
-int scan_file ();
-int scan_lisp_file ();
-int scan_c_file ();
-
-#ifdef MSDOS
-/* s/msdos.h defines this as sys_chdir, but we're not linking with the
- file where that function is defined. */
-#undef chdir
-#endif
-
-/* Stdio stream for output to the DOC file. */
-FILE *outfile;
-
-/* Name this program was invoked with. */
-char *progname;
-
-/* Print error message. `s1' is printf control string, `s2' is arg for it. */
-
-/* VARARGS1 */
-void
-error (s1, s2)
- char *s1, *s2;
-{
- fprintf (stderr, "%s: ", progname);
- fprintf (stderr, s1, s2);
- fprintf (stderr, "\n");
-}
-
-/* Print error message and exit. */
-
-/* VARARGS1 */
-void
-fatal (s1, s2)
- char *s1, *s2;
-{
- error (s1, s2);
- exit (1);
-}
-
-/* Like malloc but get fatal error if memory is exhausted. */
-
-long *
-xmalloc (size)
- unsigned int size;
-{
- long *result = (long *) malloc (size);
- if (result == NULL)
- fatal ("virtual memory exhausted", 0);
- return result;
-}
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- int i;
- int err_count = 0;
- int first_infile;
-
- progname = argv[0];
-
- outfile = stdout;
-
- /* Don't put CRs in the DOC file. */
-#ifdef MSDOS
- _fmode = O_BINARY;
-#if 0 /* Suspicion is that this causes hanging.
- So instead we require people to use -o on MSDOS. */
- (stdout)->_flag &= ~_IOTEXT;
- _setmode (fileno (stdout), O_BINARY);
-#endif
- outfile = 0;
-#endif /* MSDOS */
-#ifdef WINDOWSNT
- _fmode = O_BINARY;
- _setmode (fileno (stdout), O_BINARY);
-#endif /* WINDOWSNT */
-
- /* If first two args are -o FILE, output to FILE. */
- i = 1;
- if (argc > i + 1 && !strcmp (argv[i], "-o"))
- {
- outfile = fopen (argv[i + 1], "w");
- i += 2;
- }
- if (argc > i + 1 && !strcmp (argv[i], "-a"))
- {
- outfile = fopen (argv[i + 1], "a");
- i += 2;
- }
- if (argc > i + 1 && !strcmp (argv[i], "-d"))
- {
- chdir (argv[i + 1]);
- i += 2;
- }
-
- if (outfile == 0)
- fatal ("No output file specified", "");
-
- first_infile = i;
- for (; i < argc; i++)
- {
- int j;
- /* Don't process one file twice. */
- for (j = first_infile; j < i; j++)
- if (! strcmp (argv[i], argv[j]))
- break;
- if (j == i)
- err_count += scan_file (argv[i]);
- }
-#ifndef VMS
- exit (err_count > 0);
-#endif /* VMS */
- return err_count > 0;
-}
-
-/* Read file FILENAME and output its doc strings to outfile. */
-/* Return 1 if file is not found, 0 if it is found. */
-
-int
-scan_file (filename)
- char *filename;
-{
- int len = strlen (filename);
- if (len > 4 && !strcmp (filename + len - 4, ".elc"))
- return scan_lisp_file (filename, READ_BINARY);
- else if (len > 3 && !strcmp (filename + len - 3, ".el"))
- return scan_lisp_file (filename, READ_TEXT);
- else
- return scan_c_file (filename, READ_TEXT);
-}
-
-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 it is negative, store contents in buf.
- Convert escape sequences \n and \t to newline and tab;
- discard \ followed by newline. */
-
-int
-read_c_string (infile, printflag)
- FILE *infile;
- int printflag;
-{
- register int c;
- char *p = buf;
-
- c = getc (infile);
- while (c != EOF)
- {
- while (c != '"' && c != EOF)
- {
- if (c == '\\')
- {
- c = getc (infile);
- if (c == '\n')
- {
- c = getc (infile);
- continue;
- }
- if (c == 'n')
- c = '\n';
- if (c == 't')
- c = '\t';
- }
- if (printflag > 0)
- putc (c, outfile);
- else if (printflag < 0)
- *p++ = c;
- c = getc (infile);
- }
- c = getc (infile);
- if (c != '"')
- break;
- /* If we had a "", concatenate the two strings. */
- c = getc (infile);
- }
-
- if (printflag < 0)
- *p = 0;
-
- return c;
-}
-
-/* Write to file OUT the argument names of function FUNC, whose text is in BUF.
- MINARGS and MAXARGS are the minimum and maximum number of arguments. */
-
-void
-write_c_args (out, func, buf, minargs, maxargs)
- FILE *out;
- char *func, *buf;
- int minargs, maxargs;
-{
- register char *p;
- int in_ident = 0;
- int just_spaced = 0;
- int need_space = 1;
-
- fprintf (out, "(%s", func);
-
- if (*buf == '(')
- ++buf;
-
- for (p = buf; *p; p++)
- {
- char c = *p;
- int ident_start = 0;
-
- /* Notice when we start printing a new identifier. */
- if ((('A' <= c && c <= 'Z')
- || ('a' <= c && c <= 'z')
- || ('0' <= c && c <= '9')
- || c == '_')
- != in_ident)
- {
- if (!in_ident)
- {
- in_ident = 1;
- ident_start = 1;
-
- if (need_space)
- putc (' ', out);
-
- if (minargs == 0 && maxargs > 0)
- fprintf (out, "&optional ");
- just_spaced = 1;
-
- minargs--;
- maxargs--;
- }
- else
- in_ident = 0;
- }
-
- /* Print the C argument list as it would appear in lisp:
- print underscores as hyphens, and print commas as spaces.
- Collapse adjacent spaces into one. */
- if (c == '_') c = '-';
- if (c == ',') c = ' ';
-
- /* In C code, `default' is a reserved word, so we spell it
- `defalt'; unmangle that here. */
- if (ident_start
- && strncmp (p, "defalt", 6) == 0
- && ! (('A' <= p[6] && p[6] <= 'Z')
- || ('a' <= p[6] && p[6] <= 'z')
- || ('0' <= p[6] && p[6] <= '9')
- || p[6] == '_'))
- {
- fprintf (out, "DEFAULT");
- p += 5;
- in_ident = 0;
- just_spaced = 0;
- }
- else if (c != ' ' || ! just_spaced)
- {
- if (c >= 'a' && c <= 'z')
- /* Upcase the letter. */
- c += 'A' - 'a';
- putc (c, out);
- }
-
- just_spaced = (c == ' ');
- need_space = 0;
- }
-}
-
-/* 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. */
-
-int
-scan_c_file (filename, mode)
- char *filename, *mode;
-{
- FILE *infile;
- register int c;
- register int commas;
- register int defunflag;
- register int defvarperbufferflag;
- register int defvarflag;
- int minargs, maxargs;
- int extension = filename[strlen (filename) - 1];
-
- if (extension == 'o')
- filename[strlen (filename) - 1] = 'c';
-
- infile = fopen (filename, mode);
-
- /* No error if non-ex input file */
- if (infile == NULL)
- {
- perror (filename);
- return 0;
- }
-
- /* Reset extension to be able to detect duplicate files. */
- filename[strlen (filename) - 1] = extension;
-
- c = '\n';
- while (!feof (infile))
- {
- if (c != '\n')
- {
- c = getc (infile);
- continue;
- }
- c = getc (infile);
- if (c == ' ')
- {
- while (c == ' ')
- c = getc (infile);
- if (c != 'D')
- continue;
- c = getc (infile);
- if (c != 'E')
- continue;
- c = getc (infile);
- if (c != 'F')
- continue;
- c = getc (infile);
- if (c != 'V')
- continue;
- c = getc (infile);
- if (c != 'A')
- continue;
- c = getc (infile);
- if (c != 'R')
- continue;
- c = getc (infile);
- if (c != '_')
- continue;
-
- defvarflag = 1;
- defunflag = 0;
-
- c = getc (infile);
- defvarperbufferflag = (c == 'P');
-
- c = getc (infile);
- }
- else if (c == 'D')
- {
- c = getc (infile);
- if (c != 'E')
- continue;
- c = getc (infile);
- if (c != 'F')
- continue;
- c = getc (infile);
- defunflag = c == 'U';
- defvarflag = 0;
- }
- else continue;
-
- while (c != '(')
- {
- if (c < 0)
- goto eof;
- c = getc (infile);
- }
-
- c = getc (infile);
- if (c != '"')
- continue;
- c = read_c_string (infile, -1);
-
- if (defunflag)
- commas = 5;
- else if (defvarperbufferflag)
- commas = 2;
- else if (defvarflag)
- commas = 1;
- else /* For DEFSIMPLE and DEFPRED */
- commas = 2;
-
- 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 < 0)
- goto eof;
- c = getc (infile);
- }
- while (c == ' ' || c == '\n' || c == '\t')
- c = getc (infile);
- if (c == '"')
- c = read_c_string (infile, 0);
- while (c != ',')
- c = getc (infile);
- c = getc (infile);
- while (c == ' ' || c == '\n' || c == '\t')
- c = getc (infile);
-
- if (c == '"')
- {
- 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, buf, argbuf, minargs, maxargs);
- }
- }
- }
- eof:
- fclose (infile);
- return 0;
-}
-
-/* Read a file of Lisp code, compiled or interpreted.
- Looks for
- (defun NAME ARGS DOCSTRING ...)
- (defmacro NAME ARGS DOCSTRING ...)
- (autoload (quote NAME) FILE DOCSTRING ...)
- (defvar NAME VALUE DOCSTRING)
- (defconst NAME VALUE DOCSTRING)
- (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
- (fset (quote NAME) #[... DOCSTRING ...])
- (defalias (quote NAME) #[... DOCSTRING ...])
- starting in column zero.
- (quote NAME) may appear as 'NAME as well.
-
- We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
- When we find that, we save it for the following defining-form,
- and we use that instead of reading a doc string within that defining-form.
-
- For defun, defmacro, and autoload, we know how to skip over the arglist.
- For defvar, defconst, and fset we skip to the docstring with a kludgy
- formatting convention: all docstrings must appear on the same line as the
- initial open-paren (the one in column zero) and must contain a backslash
- and a double-quote immediately after the initial double-quote. No newlines
- must appear between the beginning of the form and the first double-quote.
- The only source file that must follow this convention is loaddefs.el; aside
- from that, it is always the .elc file that we look at, and they are no
- problem because byte-compiler output follows this convention.
- The NAME and DOCSTRING are output.
- NAME is preceded by `F' for a function or `V' for a variable.
- An entry is output only if DOCSTRING has \ newline just after the opening "
- */
-
-void
-skip_white (infile)
- FILE *infile;
-{
- char c = ' ';
- while (c == ' ' || c == '\t' || c == '\n')
- c = getc (infile);
- ungetc (c, infile);
-}
-
-void
-read_lisp_symbol (infile, buffer)
- FILE *infile;
- char *buffer;
-{
- char c;
- char *fillp = buffer;
-
- skip_white (infile);
- while (1)
- {
- c = getc (infile);
- if (c == '\\')
- *(++fillp) = getc (infile);
- else if (c == ' ' || c == '\t' || c == '\n' || c == '(' || c == ')')
- {
- ungetc (c, infile);
- *fillp = 0;
- break;
- }
- else
- *fillp++ = c;
- }
-
- if (! buffer[0])
- fprintf (stderr, "## expected a symbol, got '%c'\n", c);
-
- skip_white (infile);
-}
-
-int
-scan_lisp_file (filename, mode)
- char *filename, *mode;
-{
- FILE *infile;
- register int c;
- char *saved_string = 0;
-
- infile = fopen (filename, mode);
- if (infile == NULL)
- {
- perror (filename);
- return 0; /* No error */
- }
-
- c = '\n';
- while (!feof (infile))
- {
- char buffer[BUFSIZ];
- char type;
-
- if (c != '\n')
- {
- c = getc (infile);
- continue;
- }
- c = getc (infile);
- /* Detect a dynamic doc string and save it for the next expression. */
- if (c == '#')
- {
- c = getc (infile);
- if (c == '@')
- {
- int length = 0;
- int i;
-
- /* Read the length. */
- while ((c = getc (infile),
- c >= '0' && c <= '9'))
- {
- length *= 10;
- length += c - '0';
- }
-
- /* The next character is a space that is counted in the length
- but not part of the doc string.
- We already read it, so just ignore it. */
- length--;
-
- /* Read in the contents. */
- if (saved_string != 0)
- free (saved_string);
- saved_string = (char *) malloc (length);
- for (i = 0; i < length; i++)
- saved_string[i] = getc (infile);
- /* The last character is a ^_.
- That is needed in the .elc file
- but it is redundant in DOC. So get rid of it here. */
- saved_string[length - 1] = 0;
- /* Skip the newline. */
- c = getc (infile);
- while (c != '\n')
- c = getc (infile);
- }
- continue;
- }
-
- if (c != '(')
- continue;
-
- read_lisp_symbol (infile, buffer);
-
- if (! strcmp (buffer, "defun") ||
- ! strcmp (buffer, "defmacro"))
- {
- type = 'F';
- read_lisp_symbol (infile, buffer);
-
- /* Skip the arguments: either "nil" or a list in parens */
-
- c = getc (infile);
- if (c == 'n') /* nil */
- {
- if ((c = getc (infile)) != 'i' ||
- (c = getc (infile)) != 'l')
- {
- fprintf (stderr, "## unparsable arglist in %s (%s)\n",
- buffer, filename);
- continue;
- }
- }
- else if (c != '(')
- {
- fprintf (stderr, "## unparsable arglist in %s (%s)\n",
- buffer, filename);
- continue;
- }
- else
- while (c != ')')
- c = getc (infile);
- skip_white (infile);
-
- /* If the next three characters aren't `dquote bslash newline'
- then we're not reading a docstring.
- */
- if ((c = getc (infile)) != '"' ||
- (c = getc (infile)) != '\\' ||
- (c = getc (infile)) != '\n')
- {
-#ifdef DEBUG
- fprintf (stderr, "## non-docstring in %s (%s)\n",
- buffer, filename);
-#endif
- continue;
- }
- }
-
- else if (! strcmp (buffer, "defvar") ||
- ! strcmp (buffer, "defconst"))
- {
- char c1 = 0, c2 = 0;
- type = 'V';
- read_lisp_symbol (infile, buffer);
-
- if (saved_string == 0)
- {
-
- /* Skip until the first newline; remember the two previous chars. */
- while (c != '\n' && c >= 0)
- {
- c2 = c1;
- c1 = c;
- c = getc (infile);
- }
-
- /* If two previous characters were " and \,
- this is a doc string. Otherwise, there is none. */
- if (c2 != '"' || c1 != '\\')
- {
-#ifdef DEBUG
- fprintf (stderr, "## non-docstring in %s (%s)\n",
- buffer, filename);
-#endif
- continue;
- }
- }
- }
-
- else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
- {
- char c1 = 0, c2 = 0;
- type = 'F';
-
- c = getc (infile);
- if (c == '\'')
- read_lisp_symbol (infile, buffer);
- else
- {
- if (c != '(')
- {
- fprintf (stderr, "## unparsable name in fset in %s\n",
- filename);
- continue;
- }
- read_lisp_symbol (infile, buffer);
- if (strcmp (buffer, "quote"))
- {
- fprintf (stderr, "## unparsable name in fset in %s\n",
- filename);
- continue;
- }
- read_lisp_symbol (infile, buffer);
- c = getc (infile);
- if (c != ')')
- {
- fprintf (stderr,
- "## unparsable quoted name in fset in %s\n",
- filename);
- continue;
- }
- }
-
- if (saved_string == 0)
- {
- /* Skip until the first newline; remember the two previous chars. */
- while (c != '\n' && c >= 0)
- {
- c2 = c1;
- c1 = c;
- c = getc (infile);
- }
-
- /* If two previous characters were " and \,
- this is a doc string. Otherwise, there is none. */
- if (c2 != '"' || c1 != '\\')
- {
-#ifdef DEBUG
- fprintf (stderr, "## non-docstring in %s (%s)\n",
- buffer, filename);
-#endif
- continue;
- }
- }
- }
-
- else if (! strcmp (buffer, "autoload"))
- {
- type = 'F';
- c = getc (infile);
- if (c == '\'')
- read_lisp_symbol (infile, buffer);
- else
- {
- if (c != '(')
- {
- fprintf (stderr, "## unparsable name in autoload in %s\n",
- filename);
- continue;
- }
- read_lisp_symbol (infile, buffer);
- if (strcmp (buffer, "quote"))
- {
- fprintf (stderr, "## unparsable name in autoload in %s\n",
- filename);
- continue;
- }
- read_lisp_symbol (infile, buffer);
- c = getc (infile);
- if (c != ')')
- {
- fprintf (stderr,
- "## unparsable quoted name in autoload in %s\n",
- filename);
- continue;
- }
- }
- skip_white (infile);
- if ((c = getc (infile)) != '\"')
- {
- fprintf (stderr, "## autoload of %s unparsable (%s)\n",
- buffer, filename);
- continue;
- }
- read_c_string (infile, 0);
- skip_white (infile);
-
- if (saved_string == 0)
- {
- /* If the next three characters aren't `dquote bslash newline'
- then we're not reading a docstring. */
- if ((c = getc (infile)) != '"' ||
- (c = getc (infile)) != '\\' ||
- (c = getc (infile)) != '\n')
- {
-#ifdef DEBUG
- fprintf (stderr, "## non-docstring in %s (%s)\n",
- buffer, filename);
-#endif
- continue;
- }
- }
- }
-
-#ifdef DEBUG
- else if (! strcmp (buffer, "if") ||
- ! strcmp (buffer, "byte-code"))
- ;
-#endif
-
- else
- {
-#ifdef DEBUG
- fprintf (stderr, "## unrecognised top-level form, %s (%s)\n",
- buffer, filename);
-#endif
- continue;
- }
-
- /* At this point, we should either use the previous
- dynamic doc string in saved_string
- or gobble a doc string from the input file.
-
- In the latter case, the opening quote (and leading
- backslash-newline) have already been read. */
-
- putc (037, outfile);
- putc (type, outfile);
- fprintf (outfile, "%s\n", buffer);
- if (saved_string)
- {
- fputs (saved_string, outfile);
- /* Don't use one dynamic doc string twice. */
- free (saved_string);
- saved_string = 0;
- }
- else
- read_c_string (infile, 1);
- }
- fclose (infile);
- return 0;
-}
diff --git a/lib-src/make-path.c b/lib-src/make-path.c
deleted file mode 100644
index c4e5bf93144..00000000000
--- a/lib-src/make-path.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* Make all the directories along a path.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* This program works like mkdir, except that it generates
- intermediate directories if they don't exist. This is just like
- the `mkdir -p' command on most systems; unfortunately, the mkdir
- command on some of the purer BSD systems (like Mt. Xinu) don't have
- that option. */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <errno.h>
-
-extern int errno;
-
-char *prog_name;
-
-/* Create directory DIRNAME if it does not exist already.
- Then give permission for everyone to read and search it.
- Return 0 if successful, 1 if not. */
-
-int
-touchy_mkdir (dirname)
- char *dirname;
-{
- struct stat buf;
-
- /* If DIRNAME already exists and is a directory, don't create. */
- if (! (stat (dirname, &buf) >= 0
- && (buf.st_mode & S_IFMT) == S_IFDIR))
- {
- /* Otherwise, try to make it. If DIRNAME exists but isn't a directory,
- this will signal an error. */
- if (mkdir (dirname, 0777) < 0)
- {
- fprintf (stderr, "%s: ", prog_name);
- perror (dirname);
- return 1;
- }
- }
-
- /* Make sure everyone can look at this directory. */
- if (stat (dirname, &buf) < 0)
- {
- fprintf (stderr, "%s: ", prog_name);
- perror (dirname);
- return 1;
- }
- if (chmod (dirname, 0555 | (buf.st_mode & 0777)) < 0)
- {
- fprintf (stderr, "%s: ", prog_name);
- perror (dirname);
- }
-
- return 0;
-}
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- prog_name = *argv;
-
- for (argc--, argv++; argc > 0; argc--, argv++)
- {
- char *dirname = *argv;
- int i;
-
- /* Stop at each slash in dirname and try to create the directory.
- Skip any initial slash. */
- for (i = (dirname[0] == '/') ? 1 : 0; dirname[i]; i++)
- if (dirname[i] == '/')
- {
- dirname[i] = '\0';
- if (touchy_mkdir (dirname) < 0)
- goto next_dirname;
- dirname[i] = '/';
- }
-
- touchy_mkdir (dirname);
-
- next_dirname:
- ;
- }
-
- return 0;
-}
diff --git a/lib-src/makefile.nt b/lib-src/makefile.nt
deleted file mode 100644
index 29bb209b1ad..00000000000
--- a/lib-src/makefile.nt
+++ /dev/null
@@ -1,357 +0,0 @@
-# Makefile for GNU Emacs lib-src directory.
-# Geoff Voelker (voelker@cs.washington.edu)
-# Copyright (C) 1994 Free Software Foundation, Inc.
-#
-# This file is part of GNU Emacs.
-#
-# GNU Emacs is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# GNU Emacs is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Emacs; see the file COPYING. If not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-
-#
-# Sets up the system dependent macros.
-#
-!include ..\nt\makefile.def
-
-LOCAL_FLAGS = -DWINDOWSNT -DDOS_NT -DSTDC_HEADERS=1 -DNO_LDAV=1 -DNO_ARCHIVES=1 -I..\nt\inc -I..\src
-
-LINK_FLAGS = $(ARCH_LDFLAGS) -debug:PARTIAL -machine:$(ARCH) -subsystem:console -entry:mainCRTStartup setargv.obj
-
-ALL = $(BLD)\make-docfile.exe \
- $(BLD)\hexl.exe \
- $(BLD)\ctags.exe \
- $(BLD)\etags.exe \
- $(BLD)\movemail.exe \
- $(BLD)\fakemail.exe \
-
-
-# don't know what (if) to do with these yet...
-#
-# $(BLD)\sorted-doc.exe \
-# $(BLD)\env.exe \
-# $(BLD)\server.exe \
-# $(BLD)\emacstool.exe \
-# $(BLD)\leditcfns.exe \
-# $(BLD)\emacsclient.exe \
-# $(BLD)\cvtmail.exe \
-# $(BLD)\digest-doc.exe \
-# $(BLD)\test-distrib.exe \
-
-
-LIBS = $(BASE_LIBS)
-
-$(BLD)\make-docfile.exe: $(BLD)\make-docfile.obj $(BLD)\ntlib.obj
- $(LINK) -out:$@ $(LINK_FLAGS) $(BLD)\make-docfile.obj $(BLD)\ntlib.obj $(LIBS)
-$(BLD)\hexl.exe: $(BLD)\hexl.obj
-$(BLD)\movemail.exe: $(BLD)\movemail.obj $(BLD)\pop.obj $(BLD)\ntlib.obj
- $(LINK) -out:$@ $(LINK_FLAGS) -debug:FULL $(BLD)\movemail.obj $(BLD)\pop.obj $(BLD)\ntlib.obj $(LIBS) wsock32.lib
-$(BLD)\fakemail.exe: $(BLD)\fakemail.obj $(BLD)\ntlib.obj
- $(LINK) -out:$@ $(LINK_FLAGS) -debug:full $(BLD)\fakemail.obj $(BLD)\ntlib.obj $(LIBS)
-
-make-docfile: $(BLD) $(BLD)\make-docfile.exe
-etags: $(BLD) $(BLD)\etags.exe
-hexl: $(BLD) $(BLD)\hexl.exe
-movemail: $(BLD) $(BLD)\movemail.exe
-fakemail: $(BLD) $(BLD)\fakemail.exe
-
-ETAGSOBJ = $(BLD)\etags.obj \
- $(BLD)\getopt.obj \
- $(BLD)\getopt1.obj \
- $(BLD)\ntlib.obj \
- $(BLD)\regex.obj \
- $(BLD)\alloca.obj
-
-
-$(BLD)\etags.exe: $(ETAGSOBJ)
- $(LINK) -out:$@ $(LINK_FLAGS) $(ETAGSOBJ) $(LIBS)
-
-
-$(BLD)\regex.obj: ../src/regex.c ../src/regex.h ../src/config.h
- $(CC) $(CFLAGS) -DCONFIG_BROKETS -DINHIBIT_STRING_HEADER \
- ../src/regex.c -Fo$@
-
-ETAGS_CFLAGS = -DETAGS_REGEXPS -DHAVE_GETCWD
-$(BLD)\etags.obj: etags.c
- $(CC) $(CFLAGS) $(ETAGS_CFLAGS) -Fo$@ etags.c
-
-CTAGSOBJ = $(BLD)\ctags.obj \
- $(BLD)\getopt.obj \
- $(BLD)\getopt1.obj \
- $(BLD)\ntlib.obj \
- $(BLD)\regex.obj \
- $(BLD)\alloca.obj
-
-$(BLD)\ctags.exe: ctags.c $(CTAGSOBJ)
- $(LINK) -out:$@ $(LINK_FLAGS) $(CTAGSOBJ) $(LIBS)
-
-ctags.c: etags.c
- - $(DEL) ctags.c
- copy etags.c ctags.c
-
-CTAGS_CFLAGS = -DCTAGS $(ETAGS_CFLAGS)
-$(BLD)\ctags.obj: ctags.c
- $(CC) $(CFLAGS) $(CTAGS_CFLAGS) -Fo$@ ctags.c
-
-#
-# don't know what to do with these yet...
-#
-# $(BLD)\sorted-doc.exe: $(BLD)\sorted-doc.obj
-# $(BLD)\yow.exe: $(BLD)\yow.obj
-# $(BLD)\emacstool.exe: $(BLD)\emacstool.obj
-# $(BLD)\leditcfns.exe: $(BLD)\leditcfns.obj
-# $(BLD)\server.exe: $(BLD)\server.obj
-# $(BLD)\cvtmail.exe: $(BLD)\cvtmail.obj
-# $(BLD)\digest-doc.exe: $(BLD)\digest-doc.obj
-# $(BLD)\emacsclient.exe: $(BLD)\emacsclient.obj
-# $(BLD)\test-distrib.exe: $(BLD)\test-distrib.obj
-
-#
-# From ..\src\makefile.nt.
-#
-obj = abbrev.c alloc.c alloca.c buffer.c bytecode.c callint.c callproc.c casefiddle.c cm.c cmds.c data.c dired.c dispnew.c doc.c doprnt.c editfns.c eval.c fileio.c filelock.c filemode.c fns.c indent.c insdel.c keyboard.c keymap.c lastfile.c lread.c macros.c marker.c minibuf.c xfaces.c mocklisp.c nt.c ntheap.c ntinevt.c ntproc.c ntterm.c print.c process.c regex.c scroll.c search.c syntax.c sysdep.c term.c termcap.c tparam.c undo.c unexnt.c window.c xdisp.c casetab.c floatfns.c frame.c gmalloc.c intervals.c ralloc.c textprop.c vm-limit.c region-cache.c strftime.c w32term.c w32xfns.c w32fns.c w32faces.c w32select.c w32menu.c w32reg.c
-
-lispdir = ..\lisp
-
-#
-# These are the lisp files that are loaded up in loadup.el
-#
-lisp= \
- $(lispdir)\subr.elc \
- $(lispdir)\byte-run.elc \
- $(lispdir)\map-ynp.elc \
- $(lispdir)\loaddefs.el \
- $(lispdir)\simple.elc \
- $(lispdir)\help.elc \
- $(lispdir)\files.elc \
- $(lispdir)\format.elc \
- $(lispdir)\indent.elc \
- $(lispdir)\window.elc \
- $(lispdir)\frame.elc \
- $(lispdir)\mouse.elc \
- $(lispdir)\menu-bar.elc \
- $(lispdir)\scroll-bar.elc \
- $(lispdir)\select.elc \
- $(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)\ls-lisp.elc \
- $(lispdir)\winnt.elc \
- $(lispdir)\float-sup.elc \
- $(lispdir)\vc-hooks.elc \
- $(lispdir)\version.el \
- $(lispdir)\dos-nt.elc
-
-DOC = DOC
-$(DOC): $(BLD)\make-docfile.exe
- - $(DEL) $(DOC)
- $(BLD)\make-docfile -d ..\src $(obj) > $(DOC)
- $(BLD)\make-docfile -d ..\src $(lisp) >> $(DOC)
- $(CP) $(DOC) ..\etc\DOC-X
- - mkdir ..\src\$(OBJDIR)
- - mkdir ..\src\$(OBJDIR)\etc
- $(CP) $(DOC) ..\src\$(OBJDIR)\etc\DOC-X
-
-{$(BLD)}.obj{$(BLD)}.exe:
- $(LINK) -out:$@ $(LINK_FLAGS) $*.obj $(LIBS)
-
-.c{$(BLD)}.obj:
- $(CC) $(CFLAGS) -Fo$@ $<
-
-#
-# Build the executables
-#
-all: $(BLD) $(ALL) $(DOC)
-
-#
-# Assuming INSTALL_DIR is defined, build and install emacs in it.
-#
-INSTALL_FILES = $(ALL)
-install: $(INSTALL_FILES)
- - mkdir $(INSTALL_DIR)\bin
- $(CP) $(BLD)\etags.exe $(INSTALL_DIR)\bin
- $(CP) $(BLD)\ctags.exe $(INSTALL_DIR)\bin
- $(CP) $(BLD)\hexl.exe $(INSTALL_DIR)\bin
- $(CP) $(BLD)\movemail.exe $(INSTALL_DIR)\bin
- $(CP) $(BLD)\fakemail.exe $(INSTALL_DIR)\bin
- - mkdir $(INSTALL_DIR)\etc
- $(CP) $(DOC) $(INSTALL_DIR)\etc
-
-#
-# Maintenance
-#
-clean:; - $(DEL) *~ *.pdb DOC*
- - $(DEL_TREE) deleted
- - $(DEL_TREE) $(OBJDIR)
-
-#
-# Headers we would preprocess if we could.
-#
-..\src\config.h: ..\nt\$(CONFIG_H)
- $(CP) $** $@
-..\src\paths.h: ..\nt\paths.h
- $(CP) $** $@
-
-### DEPENDENCIES ###
-
-EMACS_ROOT = ..
-SRC = .
-
-$(BLD)\alloca.obj : \
- $(SRC)\alloca.c \
- $(EMACS_ROOT)\src\s\windowsnt.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(EMACS_ROOT)\src\blockinput.h
-
-$(BLD)\b2m.obj : \
- $(SRC)\b2m.c \
- $(EMACS_ROOT)\src\s\windowsnt.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\lib-src\..\src\config.h
-
-$(BLD)\cvtmail.obj : \
- $(SRC)\cvtmail.c
-
-$(BLD)\digest-doc.obj : \
- $(SRC)\digest-doc.c
-
-$(BLD)\emacsclient.obj : \
- $(SRC)\emacsclient.c \
- $(EMACS_ROOT)\src\s\windowsnt.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\lib-src\..\src\config.h
-
-$(BLD)\emacsserver.obj : \
- $(SRC)\emacsserver.c \
- $(EMACS_ROOT)\src\s\windowsnt.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\lib-src\..\src\config.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h
-
-$(BLD)\emacstool.obj : \
- $(SRC)\emacstool.c \
- $(EMACS_ROOT)\nt\inc\sys\file.h
-
-$(BLD)\etags.obj : \
- $(SRC)\etags.c \
- $(EMACS_ROOT)\nt\inc\sys\param.h \
- $(EMACS_ROOT)\src\s\windowsnt.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\lib-src\..\src\config.h \
- $(SRC)\getopt.h
-
-$(BLD)\fakemail.obj : \
- $(SRC)\fakemail.c \
- $(SRC)\ntlib.h \
- $(EMACS_ROOT)\src\s\windowsnt.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\lib-src\..\src\config.h \
- $(EMACS_ROOT)\nt\inc\pwd.h
-
-$(BLD)\getdate.obj : \
- $(SRC)\getdate.c \
- $(EMACS_ROOT)\src\s\windowsnt.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(MSTOOLS_SYS)\types.h
-
-$(BLD)\getopt.obj : \
- $(SRC)\getopt.c \
- $(EMACS_ROOT)\src\s\windowsnt.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\getopt.h
-
-$(BLD)\getopt1.obj : \
- $(SRC)\getopt1.c \
- $(EMACS_ROOT)\src\s\windowsnt.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\getopt.h
-
-$(BLD)\hexl.obj : \
- $(SRC)\hexl.c
-
-$(BLD)\leditcfns.obj : \
- $(SRC)\leditcfns.c
-
-$(BLD)\make-docfile.obj : \
- $(SRC)\make-docfile.c \
- $(EMACS_ROOT)\src\config.h
-
-$(BLD)\make-path.obj : \
- $(SRC)\make-path.c
-
-$(BLD)\movemail.obj : \
- $(SRC)\movemail.c \
- $(EMACS_ROOT)\src\s\windowsnt.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\lib-src\..\src\config.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h \
- $(EMACS_ROOT)\src\vmsproc.h \
- $(EMACS_ROOT)\lib-src\..\src\syswait.h \
- $(EMACS_ROOT)\nt\inc\pwd.h
- $(CC) $(CFLAGS) -DUSG -Fo$@ movemail.c
-
-$(BLD)\ntlib.obj : \
- $(SRC)\ntlib.c \
- $(SRC)\ntlib.h \
- $(EMACS_ROOT)\nt\inc\pwd.h
-
-$(BLD)\pop.obj : \
- $(SRC)\pop.c \
- $(SRC)\pop.h \
- $(SRC)\ntlib.h
-
-$(BLD)\profile.obj : \
- $(SRC)\profile.c \
- $(EMACS_ROOT)\src\s\windowsnt.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\lib-src\..\src\config.h \
- $(EMACS_ROOT)\src\vmstime.h \
- $(EMACS_ROOT)\lib-src\..\src\systime.h
-
-$(BLD)\qsort.obj : \
- $(SRC)\qsort.c
-
-$(BLD)\sorted-doc.obj : \
- $(SRC)\sorted-doc.c
-
-$(BLD)\tcp.obj : \
- $(SRC)\tcp.c
-
-$(BLD)\test-distrib.obj : \
- $(SRC)\test-distrib.c
-
-$(BLD)\timer.obj : \
- $(SRC)\timer.c \
- $(EMACS_ROOT)\src\s\windowsnt.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\lib-src\..\src\config.h
-
-$(BLD)\yow.obj : \
- $(SRC)\yow.c \
- $(EMACS_ROOT)\lib-src\..\src\paths.h
diff --git a/lib-src/movemail.c b/lib-src/movemail.c
deleted file mode 100644
index 79ea6dcabab..00000000000
--- a/lib-src/movemail.c
+++ /dev/null
@@ -1,752 +0,0 @@
-/* movemail foo bar -- move file foo to file bar,
- locking file foo the way /bin/mail respects.
- Copyright (C) 1986, 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Important notice: defining MAIL_USE_FLOCK or MAIL_USE_LOCKF *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 and MAIL_USE_LOCKF *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)
- *
- * Added POP (Post Office Protocol) service. When compiled -DMAIL_USE_POP
- * movemail will accept input filename arguments of the form
- * "po:username". This will cause movemail to open a connection to
- * a pop server running on $MAILHOST (environment variable). Movemail
- * must be setuid to root in order to work with POP.
- *
- * New module: popmail.c
- * Modified routines:
- * 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
- *
- * Modified August, 1993 by Jonathan Kamens (OpenVision Technologies)
- *
- * Move all of the POP code into a separate file, "pop.c".
- * Use strerror instead of get_errmsg.
- *
- */
-
-#define NO_SHORTNAMES /* Tell config not to load remap.h */
-#include <../src/config.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <stdio.h>
-#include <errno.h>
-#include <../src/syswait.h>
-#ifdef MAIL_USE_POP
-#include "pop.h"
-#endif
-
-#ifdef MSDOS
-#undef access
-#endif /* MSDOS */
-
-#ifndef DIRECTORY_SEP
-#define DIRECTORY_SEP '/'
-#endif
-#ifndef IS_DIRECTORY_SEP
-#define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
-#endif
-
-#ifdef WINDOWSNT
-#undef access
-#undef unlink
-#define fork() 0
-#define sys_wait(var) (*(var) = 0)
-/* Unfortunately, Samba doesn't seem to properly lock Unix files even
- though the locking call succeeds (and indeed blocks local access from
- other NT programs). If you have direct file access using an NFS
- client or something other than Samba, the locking call might work
- properly - make sure it does before you enable this! */
-#define DISABLE_DIRECT_ACCESS
-#endif /* WINDOWSNT */
-
-#ifdef USG
-#include <fcntl.h>
-#include <unistd.h>
-#ifndef F_OK
-#define F_OK 0
-#define X_OK 1
-#define W_OK 2
-#define R_OK 4
-#endif
-#endif /* USG */
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#if defined (XENIX) || defined (WINDOWSNT)
-#include <sys/locking.h>
-#endif
-
-#ifdef MAIL_USE_LOCKF
-#define MAIL_USE_SYSTEM_LOCK
-#endif
-
-#ifdef MAIL_USE_FLOCK
-#define MAIL_USE_SYSTEM_LOCK
-#endif
-
-#ifdef MAIL_USE_MMDF
-extern int lk_open (), lk_close ();
-#endif
-
-/* Cancel substitutions made by config.h for Emacs. */
-#undef open
-#undef read
-#undef write
-#undef close
-
-#ifndef errno
-extern int errno;
-#endif
-char *strerror ();
-
-void fatal ();
-void error ();
-void pfatal_with_name ();
-void pfatal_and_delete ();
-char *concat ();
-long *xmalloc ();
-int popmail ();
-int pop_retr ();
-int mbx_write ();
-int mbx_delimit_begin ();
-int mbx_delimit_end ();
-
-/* Nonzero means this is name of a lock file to delete on fatal error. */
-char *delete_lockname;
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- char *inname, *outname;
- int indesc, outdesc;
- int nread;
- WAITTYPE status;
-
-#ifndef MAIL_USE_SYSTEM_LOCK
- struct stat st;
- long now;
- int tem;
- char *lockname, *p;
- char *tempname;
- int desc;
-#endif /* not MAIL_USE_SYSTEM_LOCK */
-
- delete_lockname = 0;
-
- if (argc < 3)
- {
- fprintf (stderr, "Usage: movemail inbox destfile [POP-password]\n");
- exit(1);
- }
-
- inname = argv[1];
- outname = argv[2];
-
-#ifdef MAIL_USE_MMDF
- mmdf_init (argv[0]);
-#endif
-
- if (*outname == 0)
- fatal ("Destination file name is empty", 0);
-
- /* Check access to output file. */
- if (access (outname, F_OK) == 0 && access (outname, W_OK) != 0)
- pfatal_with_name (outname);
-
- /* Also check that outname's directory is writable to the real uid. */
- {
- char *buf = (char *) xmalloc (strlen (outname) + 1);
- char *p;
- strcpy (buf, outname);
- p = buf + strlen (buf);
- while (p > buf && !IS_DIRECTORY_SEP (p[-1]))
- *--p = 0;
- if (p == buf)
- *p++ = '.';
- if (access (buf, W_OK) != 0)
- pfatal_with_name (buf);
- free (buf);
- }
-
-#ifdef MAIL_USE_POP
- if (!strncmp (inname, "po:", 3))
- {
- int status;
-
- status = popmail (inname + 3, outname, argc > 3 ? argv[3] : NULL);
- exit (status);
- }
-
- setuid (getuid ());
-#endif /* MAIL_USE_POP */
-
-#ifndef DISABLE_DIRECT_ACCESS
-
- /* Check access to input file. */
- if (access (inname, R_OK | W_OK) != 0)
- pfatal_with_name (inname);
-
-#ifndef MAIL_USE_MMDF
-#ifndef MAIL_USE_SYSTEM_LOCK
- /* Use a lock file named after our first argument with .lock appended:
- 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 the mail spool directory,
- 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_SYSTEM_LOCK in config.h or the s-*.h file
- and recompile movemail. If the s- file for your system
- should define MAIL_USE_SYSTEM_LOCK 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) + strlen ("EXXXXXX") + 1);
- strcpy (tempname, inname);
- p = tempname + strlen (tempname);
- while (p != tempname && !IS_DIRECTORY_SEP (p[-1]))
- p--;
- *p = 0;
- strcpy (p, "EXXXXXX");
- mktemp (tempname);
- unlink (tempname);
-
- while (1)
- {
- /* Create the lock file, but not under the lock file name. */
- /* Give up if cannot do that. */
- desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666);
- if (desc < 0)
- {
- char *message = (char *) xmalloc (strlen (tempname) + 50);
- sprintf (message, "%s--see source file lib-src/movemail.c",
- tempname);
- pfatal_with_name (message);
- }
- close (desc);
-
- tem = link (tempname, lockname);
- unlink (tempname);
- if (tem >= 0)
- break;
- sleep (1);
-
- /* If lock file is five minutes old, unlock it.
- Five minutes should be good enough to cope with crashes
- and wedgitude, and long enough to avoid being fooled
- by time differences between machines. */
- if (stat (lockname, &st) >= 0)
- {
- now = time (0);
- if (st.st_ctime < now - 300)
- unlink (lockname);
- }
- }
-
- delete_lockname = lockname;
-#endif /* not MAIL_USE_SYSTEM_LOCK */
-#endif /* not MAIL_USE_MMDF */
-
- if (fork () == 0)
- {
- int lockcount = 0;
- int status;
-
- setuid (getuid ());
-
-#ifndef MAIL_USE_MMDF
-#ifdef MAIL_USE_SYSTEM_LOCK
- indesc = open (inname, O_RDWR);
-#else /* if not MAIL_USE_SYSTEM_LOCK */
- indesc = open (inname, O_RDONLY);
-#endif /* not MAIL_USE_SYSTEM_LOCK */
-#else /* MAIL_USE_MMDF */
- indesc = lk_open (inname, O_RDONLY, 0, 0, 10);
-#endif /* MAIL_USE_MMDF */
-
- if (indesc < 0)
- pfatal_with_name (inname);
-
-#if defined (BSD_SYSTEM) || defined (XENIX)
- /* In case movemail is setuid to root, make sure the user can
- read the output file. */
- /* This is desirable for all systems
- but I don't want to assume all have the umask system call */
- umask (umask (0) & 0333);
-#endif /* BSD_SYSTEM || XENIX */
- outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666);
- if (outdesc < 0)
- pfatal_with_name (outname);
-
- /* This label exists so we can retry locking
- after a delay, if it got EAGAIN or EBUSY. */
- retry_lock:
-
- /* Try to lock it. */
-#ifdef MAIL_USE_SYSTEM_LOCK
-#ifdef MAIL_USE_LOCKF
- status = lockf (indesc, F_LOCK, 0);
-#else /* not MAIL_USE_LOCKF */
-#ifdef XENIX
- status = locking (indesc, LK_RLCK, 0L);
-#else
-#ifdef WINDOWSNT
- status = locking (indesc, LK_RLCK, -1L);
-#else
- status = flock (indesc, LOCK_EX);
-#endif
-#endif
-#endif /* not MAIL_USE_LOCKF */
-#endif /* MAIL_USE_SYSTEM_LOCK */
-
- /* If it fails, retry up to 5 times
- for certain failure codes. */
- if (status < 0)
- {
- if (++lockcount <= 5)
- {
-#ifdef EAGAIN
- if (errno == EAGAIN)
- {
- sleep (1);
- goto retry_lock;
- }
-#endif
-#ifdef EBUSY
- if (errno == EBUSY)
- {
- sleep (1);
- goto retry_lock;
- }
-#endif
- }
-
- pfatal_with_name (inname);
- }
-
- {
- char buf[1024];
-
- while (1)
- {
- nread = read (indesc, buf, sizeof buf);
- if (nread != write (outdesc, buf, nread))
- {
- int saved_errno = errno;
- unlink (outname);
- errno = saved_errno;
- pfatal_with_name (outname);
- }
- if (nread < sizeof buf)
- break;
- }
- }
-
-#ifdef BSD_SYSTEM
- if (fsync (outdesc) < 0)
- pfatal_and_delete (outname);
-#endif
-
- /* Check to make sure no errors before we zap the inbox. */
- if (close (outdesc) != 0)
- pfatal_and_delete (outname);
-
-#ifdef MAIL_USE_SYSTEM_LOCK
-#if defined (STRIDE) || defined (XENIX) || defined (WINDOWSNT)
- /* Stride, xenix have file locking, but no ftruncate. This mess will do. */
- close (open (inname, O_CREAT | O_TRUNC | O_RDWR, 0666));
-#else
- ftruncate (indesc, 0L);
-#endif /* STRIDE or XENIX */
-#endif /* MAIL_USE_SYSTEM_LOCK */
-
-#ifdef MAIL_USE_MMDF
- lk_close (indesc, 0, 0, 0);
-#else
- close (indesc);
-#endif
-
-#ifndef MAIL_USE_SYSTEM_LOCK
- /* Delete the input file; if we can't, at least get rid of its
- contents. */
-#ifdef MAIL_UNLINK_SPOOL
- /* This is generally bad to do, because it destroys the permissions
- that were set on the file. Better to just empty the file. */
- if (unlink (inname) < 0 && errno != ENOENT)
-#endif /* MAIL_UNLINK_SPOOL */
- creat (inname, 0600);
-#endif /* not MAIL_USE_SYSTEM_LOCK */
-
- exit (0);
- }
-
- wait (&status);
- if (!WIFEXITED (status))
- exit (1);
- else if (WRETCODE (status) != 0)
- exit (WRETCODE (status));
-
-#if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK)
- unlink (lockname);
-#endif /* not MAIL_USE_MMDF and not MAIL_USE_SYSTEM_LOCK */
-
-#endif /* ! DISABLE_DIRECT_ACCESS */
-
- return 0;
-}
-
-/* Print error message and exit. */
-
-void
-fatal (s1, s2)
- char *s1, *s2;
-{
- if (delete_lockname)
- unlink (delete_lockname);
- error (s1, s2);
- exit (1);
-}
-
-/* Print error message. `s1' is printf control string, `s2' is arg for it. */
-
-void
-error (s1, s2, s3)
- char *s1, *s2, *s3;
-{
- fprintf (stderr, "movemail: ");
- fprintf (stderr, s1, s2, s3);
- fprintf (stderr, "\n");
-}
-
-void
-pfatal_with_name (name)
- char *name;
-{
- char *s = concat ("", strerror (errno), " for %s");
- fatal (s, name);
-}
-
-void
-pfatal_and_delete (name)
- char *name;
-{
- char *s = concat ("", strerror (errno), " for %s");
- unlink (name);
- 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. */
-
-long *
-xmalloc (size)
- unsigned size;
-{
- long *result = (long *) malloc (size);
- if (!result)
- fatal ("virtual memory exhausted", 0);
- return result;
-}
-
-/* This is the guts of the interface to the Post Office Protocol. */
-
-#ifdef MAIL_USE_POP
-
-#ifndef WINDOWSNT
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#else
-#undef _WINSOCKAPI_
-#include <winsock.h>
-#endif
-#include <stdio.h>
-#include <pwd.h>
-
-#ifdef USG
-#include <fcntl.h>
-/* Cancel substitutions made by config.h for Emacs. */
-#undef open
-#undef read
-#undef write
-#undef close
-#endif /* USG */
-
-#define NOTOK (-1)
-#define OK 0
-#define DONE 1
-
-char *progname;
-FILE *sfi;
-FILE *sfo;
-char ibuffer[BUFSIZ];
-char obuffer[BUFSIZ];
-char Errmsg[80];
-
-popmail (user, outfile, password)
- char *user;
- char *outfile;
- char *password;
-{
- int nmsgs, nbytes;
- register int i;
- int mbfi;
- FILE *mbf;
- char *getenv ();
- int mbx_write ();
- popserver server;
- extern char *strerror ();
-
- server = pop_open (0, user, password, POP_NO_GETPASS);
- if (! server)
- {
- error (pop_error);
- return (1);
- }
-
- if (pop_stat (server, &nmsgs, &nbytes))
- {
- error (pop_error);
- return (1);
- }
-
- if (!nmsgs)
- {
- pop_close (server);
- return (0);
- }
-
- mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
- if (mbfi < 0)
- {
- pop_close (server);
- error ("Error in open: %s, %s", strerror (errno), outfile);
- return (1);
- }
- fchown (mbfi, getuid (), -1);
-
- if ((mbf = fdopen (mbfi, "wb")) == NULL)
- {
- pop_close (server);
- error ("Error in fdopen: %s", strerror (errno));
- close (mbfi);
- unlink (outfile);
- return (1);
- }
-
- for (i = 1; i <= nmsgs; i++)
- {
- mbx_delimit_begin (mbf);
- if (pop_retr (server, i, mbx_write, mbf) != OK)
- {
- error (Errmsg);
- close (mbfi);
- return (1);
- }
- mbx_delimit_end (mbf);
- fflush (mbf);
- if (ferror (mbf))
- {
- error ("Error in fflush: %s", strerror (errno));
- pop_close (server);
- close (mbfi);
- return (1);
- }
- }
-
- /* On AFS, a call to write only modifies the file in the local
- * workstation's AFS cache. The changes are not written to the server
- * until a call to fsync or close is made. Users with AFS home
- * directories have lost mail when over quota because these checks were
- * not made in previous versions of movemail. */
-
-#ifdef BSD_SYSTEM
- if (fsync (mbfi) < 0)
- {
- error ("Error in fsync: %s", strerror (errno));
- return (1);
- }
-#endif
-
- if (close (mbfi) == -1)
- {
- error ("Error in close: %s", strerror (errno));
- return (1);
- }
-
- for (i = 1; i <= nmsgs; i++)
- {
- if (pop_delete (server, i))
- {
- error (pop_error);
- pop_close (server);
- return (1);
- }
- }
-
- if (pop_quit (server))
- {
- error (pop_error);
- return (1);
- }
-
- return (0);
-}
-
-pop_retr (server, msgno, action, arg)
- popserver server;
- int (*action)();
-{
- extern char *strerror ();
- char *line;
- int ret;
-
- if (pop_retrieve_first (server, msgno, &line))
- {
- strncpy (Errmsg, pop_error, sizeof (Errmsg));
- Errmsg[sizeof (Errmsg)-1] = '\0';
- return (NOTOK);
- }
-
- while (! (ret = pop_retrieve_next (server, &line)))
- {
- if (! line)
- break;
-
- if ((*action)(line, arg) != OK)
- {
- strcpy (Errmsg, strerror (errno));
- pop_close (server);
- return (NOTOK);
- }
- }
-
- if (ret)
- {
- strncpy (Errmsg, pop_error, sizeof (Errmsg));
- Errmsg[sizeof (Errmsg)-1] = '\0';
- return (NOTOK);
- }
-
- return (OK);
-}
-
-/* Do this as a macro instead of using strcmp to save on execution time. */
-#define IS_FROM_LINE(a) ((a[0] == 'F') \
- && (a[1] == 'r') \
- && (a[2] == 'o') \
- && (a[3] == 'm') \
- && (a[4] == ' '))
-
-int
-mbx_write (line, mbf)
- char *line;
- FILE *mbf;
-{
- if (IS_FROM_LINE (line))
- {
- if (fputc ('>', mbf) == EOF)
- return (NOTOK);
- }
- if (fputs (line, mbf) == EOF)
- return (NOTOK);
- if (fputc (0x0a, mbf) == EOF)
- return (NOTOK);
- return (OK);
-}
-
-int
-mbx_delimit_begin (mbf)
- FILE *mbf;
-{
- if (fputs ("\f\n0, unseen,,\n", mbf) == EOF)
- return (NOTOK);
- return (OK);
-}
-
-mbx_delimit_end (mbf)
- FILE *mbf;
-{
- if (putc ('\037', mbf) == EOF)
- return (NOTOK);
- return (OK);
-}
-
-#endif /* MAIL_USE_POP */
-
-#ifndef HAVE_STRERROR
-char *
-strerror (errnum)
- int errnum;
-{
- extern char *sys_errlist[];
- extern int sys_nerr;
-
- if (errnum >= 0 && errnum < sys_nerr)
- return sys_errlist[errnum];
- return (char *) "Unknown error";
-}
-
-#endif /* ! HAVE_STRERROR */
diff --git a/lib-src/ntlib.c b/lib-src/ntlib.c
deleted file mode 100644
index d5f6177f4a2..00000000000
--- a/lib-src/ntlib.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/* Utility and Unix shadow routines for GNU Emacs support programs on NT.
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
- Geoff Voelker (voelker@cs.washington.edu) 10-8-94
-*/
-
-#include <windows.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <direct.h>
-
-#include "ntlib.h"
-
-#define MAXPATHLEN _MAX_PATH
-
-/* Emulate sleep...we could have done this with a define, but that
- would necessitate including windows.h in the files that used it.
- This is much easier. */
-void
-sleep(int seconds)
-{
- Sleep (seconds * 1000);
-}
-
-/* Get the current working directory. */
-char *
-getwd (char *dir)
-{
- if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
- return dir;
- return NULL;
-}
-
-int
-getpid ()
-{
- return _getpid ();
-}
-
-static HANDLE getppid_parent;
-static int getppid_ppid;
-
-int
-getppid(void)
-{
- char *ppid;
- DWORD result;
-
- ppid = getenv ("__PARENT_PROCESS_ID");
- if (!ppid)
- {
- printf("no pid.\n");
- return 0;
- }
- else
- {
- getppid_ppid = atoi (ppid);
- }
-
- if (!getppid_parent)
- {
- getppid_parent = OpenProcess (SYNCHRONIZE, FALSE, atoi(ppid));
- if (!getppid_parent)
- {
- printf ("Failed to open handle to parent process: %d\n",
- GetLastError());
- exit (1);
- }
- }
-
- result = WaitForSingleObject (getppid_parent, 0);
- switch (result)
- {
- case WAIT_TIMEOUT:
- /* The parent is still alive. */
- return getppid_ppid;
- case WAIT_OBJECT_0:
- /* The parent is gone. Return the pid of Unix init (1). */
- return 1;
- case WAIT_FAILED:
- default:
- printf ("Checking parent status failed: %d\n", GetLastError());
- exit (1);
- }
-}
-
-char *
-getlogin ()
-{
- static char user_name[256];
- DWORD length = sizeof (user_name);
-
- if (GetUserName (user_name, &length))
- return user_name;
- return NULL;
-}
-
-char *
-cuserid (char * s)
-{
- char * name = getlogin ();
- if (s)
- return strcpy (s, name ? name : "");
- return name;
-}
-
-int
-getuid ()
-{
- return 0;
-}
-
-int
-setuid (int uid)
-{
- return 0;
-}
-
-struct passwd *
-getpwuid (int uid)
-{
- return NULL;
-}
-
-char *
-getpass (const char * prompt)
-{
- static char input[256];
- HANDLE in;
- HANDLE err;
- DWORD count;
-
- in = GetStdHandle (STD_INPUT_HANDLE);
- err = GetStdHandle (STD_ERROR_HANDLE);
-
- if (in == INVALID_HANDLE_VALUE || err == INVALID_HANDLE_VALUE)
- return NULL;
-
- if (WriteFile (err, prompt, strlen (prompt), &count, NULL))
- {
- int istty = (GetFileType (in) == FILE_TYPE_CHAR);
- DWORD old_flags;
- int rc;
-
- if (istty)
- {
- if (GetConsoleMode (in, &old_flags))
- SetConsoleMode (in, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
- else
- istty = 0;
- }
- rc = ReadFile (in, input, sizeof (input), &count, NULL);
- if (count >= 2 && input[count - 2] == '\r')
- input[count - 2] = '\0';
- else
- {
- char buf[256];
- while (ReadFile (in, buf, sizeof (buf), &count, NULL) > 0)
- if (count >= 2 && buf[count - 2] == '\r')
- break;
- }
- WriteFile (err, "\r\n", 2, &count, NULL);
- if (istty)
- SetConsoleMode (in, old_flags);
- if (rc)
- return input;
- }
-
- return NULL;
-}
-
-int
-fchown (int fd, int uid, int gid)
-{
- return 0;
-}
-
-/* Place a wrapper around the MSVC version of ctime. It returns NULL
- on network directories, so we handle that case here.
- (Ulrich Leodolter, 1/11/95). */
-char *
-sys_ctime (const time_t *t)
-{
- char *str = (char *) ctime (t);
- return (str ? str : "Sun Jan 01 00:00:00 1970");
-}
-
-FILE *
-sys_fopen(const char * path, const char * mode)
-{
- return fopen (path, mode);
-}
-
-int
-sys_chdir (const char * path)
-{
- return _chdir (path);
-}
diff --git a/lib-src/ntlib.h b/lib-src/ntlib.h
deleted file mode 100644
index 6de27d64c67..00000000000
--- a/lib-src/ntlib.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Utility and Unix shadow routines for GNU Emacs support programs on NT.
- Copyright (C) 1994 Free Software Foundation, Inc.
-
- This file is part of GNU Emacs.
-
- GNU Emacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any later
- version.
-
- GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU Emacs; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
-*/
-
-#include <pwd.h>
-#include <malloc.h>
-
-void sleep(int seconds);
-char *getwd (char *dir);
-int getppid(void);
-char * getlogin ();
-char * cuserid (char * s);
-int getuid ();
-int setuid (int uid);
-struct passwd * getpwuid (int uid);
-char * getpass (const char * prompt);
-int fchown (int fd, int uid, int gid);
-
-#ifndef BSTRING
-#define bzero(b, l) memset(b, 0, l)
-#define bcopy(s, d, l) memcpy(d, s, l)
-#define bcmp(a, b, l) memcmp(a, b, l)
-
-#define index strchr
-#define rindex strrchr
-#endif
-
-/* end of ntlib.h */
diff --git a/lib-src/pop.c b/lib-src/pop.c
deleted file mode 100644
index 9292998e288..00000000000
--- a/lib-src/pop.c
+++ /dev/null
@@ -1,1555 +0,0 @@
-/* pop.c: client routines for talking to a POP3-protocol post-office server
- Copyright (c) 1991, 1993, 1996 Free Software Foundation, Inc.
- Written by Jonathan Kamens, jik@security.ov.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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifdef HAVE_CONFIG_H
-#define NO_SHORTNAMES /* Tell config not to load remap.h */
-#include <../src/config.h>
-#else
-#define MAIL_USE_POP
-#endif
-
-#ifdef MAIL_USE_POP
-
-#ifdef HAVE_CONFIG_H
-/* Cancel these substitutions made in config.h */
-#undef open
-#undef read
-#undef write
-#undef close
-#endif
-
-#include <sys/types.h>
-#ifdef WINDOWSNT
-#include "ntlib.h"
-#include <winsock.h>
-#undef SOCKET_ERROR
-#define RECV(s,buf,len,flags) recv(s,buf,len,flags)
-#define SEND(s,buf,len,flags) send(s,buf,len,flags)
-#define CLOSESOCKET(s) closesocket(s)
-#else
-#include <netinet/in.h>
-#include <sys/socket.h>
-#define RECV(s,buf,len,flags) read(s,buf,len)
-#define SEND(s,buf,len,flags) write(s,buf,len)
-#define CLOSESOCKET(s) close(s)
-#endif
-#include <pop.h>
-
-#ifdef sun
-#include <malloc.h>
-#endif /* sun */
-
-#ifdef HESIOD
-#include <hesiod.h>
-/*
- * It really shouldn't be necessary to put this declaration here, but
- * the version of hesiod.h that Athena has installed in release 7.2
- * doesn't declare this function; I don't know if the 7.3 version of
- * hesiod.h does.
- */
-extern struct servent *hes_getservbyname (/* char *, char * */);
-#endif
-
-#include <pwd.h>
-#include <netdb.h>
-#include <errno.h>
-#include <stdio.h>
-
-#ifdef KERBEROS
-#ifndef KRB5
-#ifndef SOLARIS2
-#include <des.h>
-#include <krb.h>
-#else /* not SOLARIS2 */
-#include <kerberos/des.h>
-#include <kerberos/krb.h>
-#endif /* not SOLARIS2 */
-#else /* KRB5 */
-#include <krb5/krb5.h>
-#include <krb5/ext-proto.h>
-#include <ctype.h>
-#endif /* KRB5 */
-#endif /* KERBEROS */
-
-extern char *getenv (/* char * */);
-extern char *getlogin (/* void */);
-extern char *getpass (/* char * */);
-extern char *strerror (/* int */);
-extern char *index ();
-
-#ifdef KERBEROS
-#ifndef KRB5
-extern int krb_sendauth (/* long, int, KTEXT, char *, char *, char *,
- u_long, MSG_DAT *, CREDENTIALS *, Key_schedule,
- struct sockaddr_in *, struct sockaddr_in *,
- char * */);
-extern char *krb_realmofhost (/* char * */);
-#endif /* ! KRB5 */
-#endif /* KERBEROS */
-
-#ifndef WINDOWSNT
-#if !defined(HAVE_H_ERRNO) || !defined(HAVE_CONFIG_H)
-extern int h_errno;
-#endif
-#endif
-
-static int socket_connection (/* char *, int */);
-static char *getline (/* popserver */);
-static int sendline (/* popserver, char * */);
-static int fullwrite (/* int, char *, int */);
-static int getok (/* popserver */);
-#if 0
-static int gettermination (/* popserver */);
-#endif
-static void pop_trash (/* popserver */);
-static char *find_crlf (/* char * */);
-
-#define ERROR_MAX 80 /* a pretty arbitrary size */
-#define POP_PORT 110
-#define KPOP_PORT 1109
-#ifdef WINDOWSNT
-#define POP_SERVICE "pop3" /* we don't want the POP2 port! */
-#else
-#define POP_SERVICE "pop"
-#endif
-#ifdef KERBEROS
-#ifdef KRB5
-#define KPOP_SERVICE "k5pop";
-#else
-#define KPOP_SERVICE "kpop"
-#endif
-#endif
-
-char pop_error[ERROR_MAX];
-int pop_debug = 0;
-
-#ifndef min
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-/*
- * Function: pop_open (char *host, char *username, char *password,
- * int flags)
- *
- * Purpose: Establishes a connection with a post-office server, and
- * completes the authorization portion of the session.
- *
- * Arguments:
- * host The server host with which the connection should be
- * established. Optional. If omitted, internal
- * heuristics will be used to determine the server host,
- * if possible.
- * username
- * The username of the mail-drop to access. Optional.
- * If omitted, internal heuristics will be used to
- * determine the username, if possible.
- * password
- * The password to use for authorization. If omitted,
- * internal heuristics will be used to determine the
- * password, if possible.
- * flags A bit mask containing flags controlling certain
- * functions of the routine. Valid flags are defined in
- * the file pop.h
- *
- * Return value: Upon successful establishment of a connection, a
- * non-null popserver will be returned. Otherwise, null will be
- * returned, and the string variable pop_error will contain an
- * explanation of the error.
- */
-popserver
-pop_open (host, username, password, flags)
- char *host;
- char *username;
- char *password;
- int flags;
-{
- int sock;
- popserver server;
-
- /* Determine the user name */
- if (! username)
- {
- username = getenv ("USER");
- if (! (username && *username))
- {
- username = getlogin ();
- if (! (username && *username))
- {
- struct passwd *passwd;
- passwd = getpwuid (getuid ());
- if (passwd && passwd->pw_name && *passwd->pw_name)
- {
- username = passwd->pw_name;
- }
- else
- {
- strcpy (pop_error, "Could not determine username");
- return (0);
- }
- }
- }
- }
-
- /*
- * Determine the mail host.
- */
-
- if (! host)
- {
- host = getenv ("MAILHOST");
- }
-
-#ifdef HESIOD
- if ((! host) && (! (flags & POP_NO_HESIOD)))
- {
- struct hes_postoffice *office;
- office = hes_getmailhost (username);
- if (office && office->po_type && (! strcmp (office->po_type, "POP"))
- && office->po_name && *office->po_name && office->po_host
- && *office->po_host)
- {
- host = office->po_host;
- username = office->po_name;
- }
- }
-#endif
-
-#ifdef MAILHOST
- if (! host)
- {
- host = MAILHOST;
- }
-#endif
-
- if (! host)
- {
- strcpy (pop_error, "Could not determine POP server");
- return (0);
- }
-
- /* Determine the password */
-#ifdef KERBEROS
-#define DONT_NEED_PASSWORD (! (flags & POP_NO_KERBEROS))
-#else
-#define DONT_NEED_PASSWORD 0
-#endif
-
- if ((! password) && (! DONT_NEED_PASSWORD))
- {
- if (! (flags & POP_NO_GETPASS))
- {
- password = getpass ("Enter POP password:");
- }
- if (! password)
- {
- strcpy (pop_error, "Could not determine POP password");
- return (0);
- }
- }
- if (password)
- flags |= POP_NO_KERBEROS;
- else
- password = username;
-
- sock = socket_connection (host, flags);
- if (sock == -1)
- return (0);
-
- server = (popserver) malloc (sizeof (struct _popserver));
- if (! server)
- {
- strcpy (pop_error, "Out of memory in pop_open");
- return (0);
- }
- server->buffer = (char *) malloc (GETLINE_MIN);
- if (! server->buffer)
- {
- strcpy (pop_error, "Out of memory in pop_open");
- free ((char *) server);
- return (0);
- }
-
- server->file = sock;
- server->data = 0;
- server->buffer_index = 0;
- server->buffer_size = GETLINE_MIN;
- server->in_multi = 0;
- server->trash_started = 0;
-
- if (getok (server))
- return (0);
-
- /*
- * I really shouldn't use the pop_error variable like this, but....
- */
- if (strlen (username) > ERROR_MAX - 6)
- {
- pop_close (server);
- strcpy (pop_error,
- "Username too long; recompile pop.c with larger ERROR_MAX");
- return (0);
- }
- sprintf (pop_error, "USER %s", username);
-
- if (sendline (server, pop_error) || getok (server))
- {
- return (0);
- }
-
- if (strlen (password) > ERROR_MAX - 6)
- {
- pop_close (server);
- strcpy (pop_error,
- "Password too long; recompile pop.c with larger ERROR_MAX");
- return (0);
- }
- sprintf (pop_error, "PASS %s", password);
-
- if (sendline (server, pop_error) || getok (server))
- {
- return (0);
- }
-
- return (server);
-}
-
-/*
- * Function: pop_stat
- *
- * Purpose: Issue the STAT command to the server and return (in the
- * value parameters) the number of messages in the maildrop and
- * the total size of the maildrop.
- *
- * Return value: 0 on success, or non-zero with an error in pop_error
- * in failure.
- *
- * Side effects: On failure, may make further operations on the
- * connection impossible.
- */
-int
-pop_stat (server, count, size)
- popserver server;
- int *count;
- int *size;
-{
- char *fromserver;
-
- if (server->in_multi)
- {
- strcpy (pop_error, "In multi-line query in pop_stat");
- return (-1);
- }
-
- if (sendline (server, "STAT") || (! (fromserver = getline (server))))
- return (-1);
-
- if (strncmp (fromserver, "+OK ", 4))
- {
- if (0 == strncmp (fromserver, "-ERR", 4))
- {
- strncpy (pop_error, fromserver, ERROR_MAX);
- }
- else
- {
- strcpy (pop_error,
- "Unexpected response from POP server in pop_stat");
- pop_trash (server);
- }
- return (-1);
- }
-
- *count = atoi (&fromserver[4]);
-
- fromserver = index (&fromserver[4], ' ');
- if (! fromserver)
- {
- strcpy (pop_error,
- "Badly formatted response from server in pop_stat");
- pop_trash (server);
- return (-1);
- }
-
- *size = atoi (fromserver + 1);
-
- return (0);
-}
-
-/*
- * Function: pop_list
- *
- * Purpose: Performs the POP "list" command and returns (in value
- * parameters) two malloc'd zero-terminated arrays -- one of
- * message IDs, and a parallel one of sizes.
- *
- * Arguments:
- * server The pop connection to talk to.
- * message The number of the one message about which to get
- * information, or 0 to get information about all
- * messages.
- *
- * Return value: 0 on success, non-zero with error in pop_error on
- * failure.
- *
- * Side effects: On failure, may make further operations on the
- * connection impossible.
- */
-int
-pop_list (server, message, IDs, sizes)
- popserver server;
- int message;
- int **IDs;
- int **sizes;
-{
- int how_many, i;
- char *fromserver;
-
- if (server->in_multi)
- {
- strcpy (pop_error, "In multi-line query in pop_list");
- return (-1);
- }
-
- if (message)
- how_many = 1;
- else
- {
- int count, size;
- if (pop_stat (server, &count, &size))
- return (-1);
- how_many = count;
- }
-
- *IDs = (int *) malloc ((how_many + 1) * sizeof (int));
- *sizes = (int *) malloc ((how_many + 1) * sizeof (int));
- if (! (*IDs && *sizes))
- {
- strcpy (pop_error, "Out of memory in pop_list");
- return (-1);
- }
-
- if (message)
- {
- sprintf (pop_error, "LIST %d", message);
- if (sendline (server, pop_error))
- {
- free ((char *) *IDs);
- free ((char *) *sizes);
- return (-1);
- }
- if (! (fromserver = getline (server)))
- {
- free ((char *) *IDs);
- free ((char *) *sizes);
- return (-1);
- }
- if (strncmp (fromserver, "+OK ", 4))
- {
- if (! strncmp (fromserver, "-ERR", 4))
- strncpy (pop_error, fromserver, ERROR_MAX);
- else
- {
- strcpy (pop_error,
- "Unexpected response from server in pop_list");
- pop_trash (server);
- }
- free ((char *) *IDs);
- free ((char *) *sizes);
- return (-1);
- }
- (*IDs)[0] = atoi (&fromserver[4]);
- fromserver = index (&fromserver[4], ' ');
- if (! fromserver)
- {
- strcpy (pop_error,
- "Badly formatted response from server in pop_list");
- pop_trash (server);
- free ((char *) *IDs);
- free ((char *) *sizes);
- return (-1);
- }
- (*sizes)[0] = atoi (fromserver);
- (*IDs)[1] = (*sizes)[1] = 0;
- return (0);
- }
- else
- {
- if (pop_multi_first (server, "LIST", &fromserver))
- {
- free ((char *) *IDs);
- free ((char *) *sizes);
- return (-1);
- }
- for (i = 0; i < how_many; i++)
- {
- if (pop_multi_next (server, &fromserver))
- {
- free ((char *) *IDs);
- free ((char *) *sizes);
- return (-1);
- }
- (*IDs)[i] = atoi (fromserver);
- fromserver = index (fromserver, ' ');
- if (! fromserver)
- {
- strcpy (pop_error,
- "Badly formatted response from server in pop_list");
- free ((char *) *IDs);
- free ((char *) *sizes);
- pop_trash (server);
- return (-1);
- }
- (*sizes)[i] = atoi (fromserver);
- }
- if (pop_multi_next (server, &fromserver))
- {
- free ((char *) *IDs);
- free ((char *) *sizes);
- return (-1);
- }
- else if (fromserver)
- {
- strcpy (pop_error,
- "Too many response lines from server in pop_list");
- free ((char *) *IDs);
- free ((char *) *sizes);
- return (-1);
- }
- (*IDs)[i] = (*sizes)[i] = 0;
- return (0);
- }
-}
-
-/*
- * Function: pop_retrieve
- *
- * Purpose: Retrieve a specified message from the maildrop.
- *
- * Arguments:
- * server The server to retrieve from.
- * message The message number to retrieve.
- * markfrom
- * If true, then mark the string "From " at the beginning
- * of lines with '>'.
- *
- * Return value: A string pointing to the message, if successful, or
- * null with pop_error set if not.
- *
- * Side effects: May kill connection on error.
- */
-char *
-pop_retrieve (server, message, markfrom)
- popserver server;
- int message;
- int markfrom;
-{
- int *IDs, *sizes, bufsize, fromcount = 0, cp = 0;
- char *ptr, *fromserver;
- int ret;
-
- if (server->in_multi)
- {
- strcpy (pop_error, "In multi-line query in pop_retrieve");
- return (0);
- }
-
- if (pop_list (server, message, &IDs, &sizes))
- return (0);
-
- if (pop_retrieve_first (server, message, &fromserver))
- {
- return (0);
- }
-
- /*
- * The "5" below is an arbitrary constant -- I assume that if
- * there are "From" lines in the text to be marked, there
- * probably won't be more than 5 of them. If there are, I
- * allocate more space for them below.
- */
- bufsize = sizes[0] + (markfrom ? 5 : 0);
- ptr = (char *)malloc (bufsize);
- free ((char *) IDs);
- free ((char *) sizes);
-
- if (! ptr)
- {
- strcpy (pop_error, "Out of memory in pop_retrieve");
- pop_retrieve_flush (server);
- return (0);
- }
-
- while (! (ret = pop_retrieve_next (server, &fromserver)))
- {
- int linesize;
-
- if (! fromserver)
- {
- ptr[cp] = '\0';
- return (ptr);
- }
- if (markfrom && fromserver[0] == 'F' && fromserver[1] == 'r' &&
- fromserver[2] == 'o' && fromserver[3] == 'm' &&
- fromserver[4] == ' ')
- {
- if (++fromcount == 5)
- {
- bufsize += 5;
- ptr = (char *)realloc (ptr, bufsize);
- if (! ptr)
- {
- strcpy (pop_error, "Out of memory in pop_retrieve");
- pop_retrieve_flush (server);
- return (0);
- }
- fromcount = 0;
- }
- ptr[cp++] = '>';
- }
- linesize = strlen (fromserver);
- bcopy (fromserver, &ptr[cp], linesize);
- cp += linesize;
- ptr[cp++] = '\n';
- }
-
- if (ret)
- {
- free (ptr);
- return (0);
- }
-}
-
-int
-pop_retrieve_first (server, message, response)
- popserver server;
- int message;
- char **response;
-{
- sprintf (pop_error, "RETR %d", message);
- return (pop_multi_first (server, pop_error, response));
-}
-
-int
-pop_retrieve_next (server, line)
- popserver server;
- char **line;
-{
- return (pop_multi_next (server, line));
-}
-
-int
-pop_retrieve_flush (server)
- popserver server;
-{
- return (pop_multi_flush (server));
-}
-
-int
-pop_top_first (server, message, lines, response)
- popserver server;
- int message, lines;
- char **response;
-{
- sprintf (pop_error, "TOP %d %d", message, lines);
- return (pop_multi_first (server, pop_error, response));
-}
-
-int
-pop_top_next (server, line)
- popserver server;
- char **line;
-{
- return (pop_multi_next (server, line));
-}
-
-int
-pop_top_flush (server)
- popserver server;
-{
- return (pop_multi_flush (server));
-}
-
-int
-pop_multi_first (server, command, response)
- popserver server;
- char *command;
- char **response;
-{
- if (server->in_multi)
- {
- strcpy (pop_error,
- "Already in multi-line query in pop_multi_first");
- return (-1);
- }
-
- if (sendline (server, command) || (! (*response = getline (server))))
- {
- return (-1);
- }
-
- if (0 == strncmp (*response, "-ERR", 4))
- {
- strncpy (pop_error, *response, ERROR_MAX);
- return (-1);
- }
- else if (0 == strncmp (*response, "+OK", 3))
- {
- for (*response += 3; **response == ' '; (*response)++) /* empty */;
- server->in_multi = 1;
- return (0);
- }
- else
- {
- strcpy (pop_error,
- "Unexpected response from server in pop_multi_first");
- return (-1);
- }
-}
-
-int
-pop_multi_next (server, line)
- popserver server;
- char **line;
-{
- char *fromserver;
-
- if (! server->in_multi)
- {
- strcpy (pop_error, "Not in multi-line query in pop_multi_next");
- return (-1);
- }
-
- fromserver = getline (server);
- if (! fromserver)
- {
- return (-1);
- }
-
- if (fromserver[0] == '.')
- {
- if (! fromserver[1])
- {
- *line = 0;
- server->in_multi = 0;
- return (0);
- }
- else
- {
- *line = fromserver + 1;
- return (0);
- }
- }
- else
- {
- *line = fromserver;
- return (0);
- }
-}
-
-int
-pop_multi_flush (server)
- popserver server;
-{
- char *line;
-
- if (! server->in_multi)
- {
- return (0);
- }
-
- while (! pop_multi_next (server, &line))
- {
- if (! line)
- {
- return (0);
- }
- }
-
- return (-1);
-}
-
-/* Function: pop_delete
- *
- * Purpose: Delete a specified message.
- *
- * Arguments:
- * server Server from which to delete the message.
- * message Message to delete.
- *
- * Return value: 0 on success, non-zero with error in pop_error
- * otherwise.
- */
-int
-pop_delete (server, message)
- popserver server;
- int message;
-{
- if (server->in_multi)
- {
- strcpy (pop_error, "In multi-line query in pop_delete");
- return (-1);
- }
-
- sprintf (pop_error, "DELE %d", message);
-
- if (sendline (server, pop_error) || getok (server))
- return (-1);
-
- return (0);
-}
-
-/*
- * Function: pop_noop
- *
- * Purpose: Send a noop command to the server.
- *
- * Argument:
- * server The server to send to.
- *
- * Return value: 0 on success, non-zero with error in pop_error
- * otherwise.
- *
- * Side effects: Closes connection on error.
- */
-int
-pop_noop (server)
- popserver server;
-{
- if (server->in_multi)
- {
- strcpy (pop_error, "In multi-line query in pop_noop");
- return (-1);
- }
-
- if (sendline (server, "NOOP") || getok (server))
- return (-1);
-
- return (0);
-}
-
-/*
- * Function: pop_last
- *
- * Purpose: Find out the highest seen message from the server.
- *
- * Arguments:
- * server The server.
- *
- * Return value: If successful, the highest seen message, which is
- * greater than or equal to 0. Otherwise, a negative number with
- * the error explained in pop_error.
- *
- * Side effects: Closes the connection on error.
- */
-int
-pop_last (server)
- popserver server;
-{
- char *fromserver;
-
- if (server->in_multi)
- {
- strcpy (pop_error, "In multi-line query in pop_last");
- return (-1);
- }
-
- if (sendline (server, "LAST"))
- return (-1);
-
- if (! (fromserver = getline (server)))
- return (-1);
-
- if (! strncmp (fromserver, "-ERR", 4))
- {
- strncpy (pop_error, fromserver, ERROR_MAX);
- return (-1);
- }
- else if (strncmp (fromserver, "+OK ", 4))
- {
- strcpy (pop_error, "Unexpected response from server in pop_last");
- pop_trash (server);
- return (-1);
- }
- else
- {
- return (atoi (&fromserver[4]));
- }
-}
-
-/*
- * Function: pop_reset
- *
- * Purpose: Reset the server to its initial connect state
- *
- * Arguments:
- * server The server.
- *
- * Return value: 0 for success, non-0 with error in pop_error
- * otherwise.
- *
- * Side effects: Closes the connection on error.
- */
-int
-pop_reset (server)
- popserver server;
-{
- if (pop_retrieve_flush (server))
- {
- return (-1);
- }
-
- if (sendline (server, "RSET") || getok (server))
- return (-1);
-
- return (0);
-}
-
-/*
- * Function: pop_quit
- *
- * Purpose: Quit the connection to the server,
- *
- * Arguments:
- * server The server to quit.
- *
- * Return value: 0 for success, non-zero otherwise with error in
- * pop_error.
- *
- * Side Effects: The popserver passed in is unusable after this
- * function is called, even if an error occurs.
- */
-int
-pop_quit (server)
- popserver server;
-{
- int ret = 0;
-
- if (server->file >= 0)
- {
- if (pop_retrieve_flush (server))
- {
- ret = -1;
- }
-
- if (sendline (server, "QUIT") || getok (server))
- {
- ret = -1;
- }
-
- close (server->file);
- }
-
- if (server->buffer)
- free (server->buffer);
- free ((char *) server);
-
- return (ret);
-}
-
-#ifdef WINDOWSNT
-static int have_winsock = 0;
-#endif
-
-/*
- * Function: socket_connection
- *
- * Purpose: Opens the network connection with the mail host, without
- * doing any sort of I/O with it or anything.
- *
- * Arguments:
- * host The host to which to connect.
- * flags Option flags.
- *
- * Return value: A file descriptor indicating the connection, or -1
- * indicating failure, in which case an error has been copied
- * into pop_error.
- */
-static int
-socket_connection (host, flags)
- char *host;
- int flags;
-{
- struct hostent *hostent;
- struct servent *servent;
- struct sockaddr_in addr;
- char found_port = 0;
- char *service;
- int sock;
-#ifdef KERBEROS
-#ifdef KRB5
- krb5_error_code rem;
- krb5_ccache ccdef;
- krb5_principal client, server;
- krb5_error *err_ret;
- register char *cp;
-#else
- KTEXT ticket;
- MSG_DAT msg_data;
- CREDENTIALS cred;
- Key_schedule schedule;
- int rem;
- char *realhost;
-#endif /* KRB5 */
-#endif /* KERBEROS */
-
- int try_count = 0;
-
-#ifdef WINDOWSNT
- {
- WSADATA winsockData;
- if (WSAStartup (0x101, &winsockData) == 0)
- have_winsock = 1;
- }
-#endif
-
- do
- {
- hostent = gethostbyname (host);
- try_count++;
- if ((! hostent) && ((h_errno != TRY_AGAIN) || (try_count == 5)))
- {
- strcpy (pop_error, "Could not determine POP server's address");
- return (-1);
- }
- } while (! hostent);
-
- bzero ((char *) &addr, sizeof (addr));
- addr.sin_family = AF_INET;
-
-#ifdef KERBEROS
- service = (flags & POP_NO_KERBEROS) ? POP_SERVICE : KPOP_SERVICE;
-#else
- service = POP_SERVICE;
-#endif
-
-#ifdef HESIOD
- if (! (flags & POP_NO_HESIOD))
- {
- servent = hes_getservbyname (service, "tcp");
- if (servent)
- {
- addr.sin_port = servent->s_port;
- found_port = 1;
- }
- }
-#endif
- if (! found_port)
- {
- servent = getservbyname (service, "tcp");
- if (servent)
- {
- addr.sin_port = servent->s_port;
- }
- else
- {
-#ifdef KERBEROS
- addr.sin_port = htons ((flags & POP_NO_KERBEROS) ?
- POP_PORT : KPOP_PORT);
-#else
- addr.sin_port = htons (POP_PORT);
-#endif
- }
- }
-
-#define SOCKET_ERROR "Could not create socket for POP connection: "
-
- sock = socket (PF_INET, SOCK_STREAM, 0);
- if (sock < 0)
- {
- strcpy (pop_error, SOCKET_ERROR);
- strncat (pop_error, strerror (errno),
- ERROR_MAX - sizeof (SOCKET_ERROR));
- return (-1);
-
- }
-
- while (*hostent->h_addr_list)
- {
- bcopy (*hostent->h_addr_list, (char *) &addr.sin_addr,
- hostent->h_length);
- if (! connect (sock, (struct sockaddr *) &addr, sizeof (addr)))
- break;
- hostent->h_addr_list++;
- }
-
-#define CONNECT_ERROR "Could not connect to POP server: "
-
- if (! *hostent->h_addr_list)
- {
- CLOSESOCKET (sock);
- strcpy (pop_error, CONNECT_ERROR);
- strncat (pop_error, strerror (errno),
- ERROR_MAX - sizeof (CONNECT_ERROR));
- return (-1);
-
- }
-
-#ifdef KERBEROS
-#define KRB_ERROR "Kerberos error connecting to POP server: "
- if (! (flags & POP_NO_KERBEROS))
- {
-#ifdef KRB5
- krb5_init_ets ();
-
- if (rem = krb5_cc_default (&ccdef))
- {
- krb5error:
- strcpy (pop_error, KRB_ERROR);
- strncat (pop_error, error_message (rem),
- ERROR_MAX - sizeof(KRB_ERROR));
- CLOSESOCKET (sock);
- return (-1);
- }
-
- if (rem = krb5_cc_get_principal (ccdef, &client))
- {
- goto krb5error;
- }
-
- for (cp = hostent->h_name; *cp; cp++)
- {
- if (isupper (*cp))
- {
- *cp = tolower (*cp);
- }
- }
-
- if (rem = krb5_sname_to_principal (hostent->h_name, POP_SERVICE,
- FALSE, &server))
- {
- goto krb5error;
- }
-
- rem = krb5_sendauth ((krb5_pointer) &sock, "KPOPV1.0", client, server,
- AP_OPTS_MUTUAL_REQUIRED,
- 0, /* no checksum */
- 0, /* no creds, use ccache instead */
- ccdef,
- 0, /* don't need seq # */
- 0, /* don't need subsession key */
- &err_ret,
- 0); /* don't need reply */
- krb5_free_principal (server);
- if (rem)
- {
- if (err_ret && err_ret->text.length)
- {
- strcpy (pop_error, KRB_ERROR);
- strncat (pop_error, error_message (rem),
- ERROR_MAX - sizeof (KRB_ERROR));
- strncat (pop_error, " [server says '",
- ERROR_MAX - strlen (pop_error) - 1);
- strncat (pop_error, err_ret->text.data,
- min (ERROR_MAX - strlen (pop_error) - 1,
- err_ret->text.length));
- strncat (pop_error, "']",
- ERROR_MAX - strlen (pop_error) - 1);
- }
- else
- {
- strcpy (pop_error, KRB_ERROR);
- strncat (pop_error, error_message (rem),
- ERROR_MAX - sizeof (KRB_ERROR));
- }
- if (err_ret)
- krb5_free_error (err_ret);
-
- CLOSESOCKET (sock);
- return (-1);
- }
-#else /* ! KRB5 */
- ticket = (KTEXT) malloc (sizeof (KTEXT_ST));
- realhost = strdup (hostent->h_name);
- rem = krb_sendauth (0L, sock, ticket, "pop", realhost,
- (char *) krb_realmofhost (realhost),
- (unsigned long) 0, &msg_data, &cred, schedule,
- (struct sockaddr_in *) 0,
- (struct sockaddr_in *) 0,
- "KPOPV0.1");
- free ((char *) ticket);
- free (realhost);
- if (rem != KSUCCESS)
- {
- strcpy (pop_error, KRB_ERROR);
- strncat (pop_error, krb_err_txt[rem],
- ERROR_MAX - sizeof (KRB_ERROR));
- CLOSESOCKET (sock);
- return (-1);
- }
-#endif /* KRB5 */
- }
-#endif /* KERBEROS */
-
- return (sock);
-} /* socket_connection */
-
-/*
- * Function: getline
- *
- * Purpose: Get a line of text from the connection and return a
- * pointer to it. The carriage return and linefeed at the end of
- * the line are stripped, but periods at the beginnings of lines
- * are NOT dealt with in any special way.
- *
- * Arguments:
- * server The server from which to get the line of text.
- *
- * Returns: A non-null pointer if successful, or a null pointer on any
- * error, with an error message copied into pop_error.
- *
- * Notes: The line returned is overwritten with each call to getline.
- *
- * Side effects: Closes the connection on error.
- */
-static char *
-getline (server)
- popserver server;
-{
-#define GETLINE_ERROR "Error reading from server: "
-
- int ret;
- int search_offset = 0;
-
- if (server->data)
- {
- char *cp = find_crlf (server->buffer + server->buffer_index);
- if (cp)
- {
- int found;
- int data_used;
-
- found = server->buffer_index;
- data_used = (cp + 2) - server->buffer - found;
-
- *cp = '\0'; /* terminate the string to be returned */
- server->data -= data_used;
- server->buffer_index += data_used;
-
- if (pop_debug)
- fprintf (stderr, "<<< %s\n", server->buffer + found);
- return (server->buffer + found);
- }
- else
- {
- bcopy (server->buffer + server->buffer_index,
- server->buffer, server->data);
- /* Record the fact that we've searched the data already in
- the buffer for a CRLF, so that when we search below, we
- don't have to search the same data twice. There's a "-
- 1" here to account for the fact that the last character
- of the data we have may be the CR of a CRLF pair, of
- which we haven't read the second half yet, so we may have
- to search it again when we read more data. */
- search_offset = server->data - 1;
- server->buffer_index = 0;
- }
- }
- else
- {
- server->buffer_index = 0;
- }
-
- while (1)
- {
- /* There's a "- 1" here to leave room for the null that we put
- at the end of the read data below. We put the null there so
- that find_crlf knows where to stop when we call it. */
- if (server->data == server->buffer_size - 1)
- {
- server->buffer_size += GETLINE_INCR;
- server->buffer = (char *)realloc (server->buffer, server->buffer_size);
- if (! server->buffer)
- {
- strcpy (pop_error, "Out of memory in getline");
- pop_trash (server);
- return (0);
- }
- }
- ret = RECV (server->file, server->buffer + server->data,
- server->buffer_size - server->data - 1, 0);
- if (ret < 0)
- {
- strcpy (pop_error, GETLINE_ERROR);
- strncat (pop_error, strerror (errno),
- ERROR_MAX - sizeof (GETLINE_ERROR));
- pop_trash (server);
- return (0);
- }
- else if (ret == 0)
- {
- strcpy (pop_error, "Unexpected EOF from server in getline");
- pop_trash (server);
- return (0);
- }
- else
- {
- char *cp;
- server->data += ret;
- server->buffer[server->data] = '\0';
-
- cp = find_crlf (server->buffer + search_offset);
- if (cp)
- {
- int data_used = (cp + 2) - server->buffer;
- *cp = '\0';
- server->data -= data_used;
- server->buffer_index = data_used;
-
- if (pop_debug)
- fprintf (stderr, "<<< %s\n", server->buffer);
- return (server->buffer);
- }
- search_offset += ret;
- }
- }
-
- /* NOTREACHED */
-}
-
-/*
- * Function: sendline
- *
- * Purpose: Sends a line of text to the POP server. The line of text
- * passed into this function should NOT have the carriage return
- * and linefeed on the end of it. Periods at beginnings of lines
- * will NOT be treated specially by this function.
- *
- * Arguments:
- * server The server to which to send the text.
- * line The line of text to send.
- *
- * Return value: Upon successful completion, a value of 0 will be
- * returned. Otherwise, a non-zero value will be returned, and
- * an error will be copied into pop_error.
- *
- * Side effects: Closes the connection on error.
- */
-static int
-sendline (server, line)
- popserver server;
- char *line;
-{
-#define SENDLINE_ERROR "Error writing to POP server: "
- int ret;
-
- ret = fullwrite (server->file, line, strlen (line));
- if (ret >= 0)
- { /* 0 indicates that a blank line was written */
- ret = fullwrite (server->file, "\r\n", 2);
- }
-
- if (ret < 0)
- {
- pop_trash (server);
- strcpy (pop_error, SENDLINE_ERROR);
- strncat (pop_error, strerror (errno),
- ERROR_MAX - sizeof (SENDLINE_ERROR));
- return (ret);
- }
-
- if (pop_debug)
- fprintf (stderr, ">>> %s\n", line);
-
- return (0);
-}
-
-/*
- * Procedure: fullwrite
- *
- * Purpose: Just like write, but keeps trying until the entire string
- * has been written.
- *
- * Return value: Same as write. Pop_error is not set.
- */
-static int
-fullwrite (fd, buf, nbytes)
- int fd;
- char *buf;
- int nbytes;
-{
- char *cp;
- int ret;
-
- cp = buf;
- while ((ret = SEND (fd, cp, nbytes, 0)) > 0)
- {
- cp += ret;
- nbytes -= ret;
- }
-
- return (ret);
-}
-
-/*
- * Procedure getok
- *
- * Purpose: Reads a line from the server. If the return indicator is
- * positive, return with a zero exit status. If not, return with
- * a negative exit status.
- *
- * Arguments:
- * server The server to read from.
- *
- * Returns: 0 for success, else for failure and puts error in pop_error.
- *
- * Side effects: On failure, may make the connection unusable.
- */
-static int
-getok (server)
- popserver server;
-{
- char *fromline;
-
- if (! (fromline = getline (server)))
- {
- return (-1);
- }
-
- if (! strncmp (fromline, "+OK", 3))
- return (0);
- else if (! strncmp (fromline, "-ERR", 4))
- {
- strncpy (pop_error, fromline, ERROR_MAX);
- pop_error[ERROR_MAX-1] = '\0';
- return (-1);
- }
- else
- {
- strcpy (pop_error,
- "Unexpected response from server; expecting +OK or -ERR");
- pop_trash (server);
- return (-1);
- }
-}
-
-#if 0
-/*
- * Function: gettermination
- *
- * Purpose: Gets the next line and verifies that it is a termination
- * line (nothing but a dot).
- *
- * Return value: 0 on success, non-zero with pop_error set on error.
- *
- * Side effects: Closes the connection on error.
- */
-static int
-gettermination (server)
- popserver server;
-{
- char *fromserver;
-
- fromserver = getline (server);
- if (! fromserver)
- return (-1);
-
- if (strcmp (fromserver, "."))
- {
- strcpy (pop_error,
- "Unexpected response from server in gettermination");
- pop_trash (server);
- return (-1);
- }
-
- return (0);
-}
-#endif
-
-/*
- * Function pop_close
- *
- * Purpose: Close a pop connection, sending a "RSET" command to try to
- * preserve any changes that were made and a "QUIT" command to
- * try to get the server to quit, but ignoring any responses that
- * are received.
- *
- * Side effects: The server is unusable after this function returns.
- * Changes made to the maildrop since the session was started (or
- * since the last pop_reset) may be lost.
- */
-void
-pop_close (server)
- popserver server;
-{
- pop_trash (server);
- free ((char *) server);
-
- return;
-}
-
-/*
- * Function: pop_trash
- *
- * Purpose: Like pop_close or pop_quit, but doesn't deallocate the
- * memory associated with the server. It is legal to call
- * pop_close or pop_quit after this function has been called.
- */
-static void
-pop_trash (server)
- popserver server;
-{
- if (server->file >= 0)
- {
- /* avoid recursion; sendline can call pop_trash */
- if (server->trash_started)
- return;
- server->trash_started = 1;
-
- sendline (server, "RSET");
- sendline (server, "QUIT");
-
- CLOSESOCKET (server->file);
- server->file = -1;
- if (server->buffer)
- {
- free (server->buffer);
- server->buffer = 0;
- }
- }
-
-#ifdef WINDOWSNT
- if (have_winsock)
- WSACleanup ();
-#endif
-}
-
-/* Return a pointer to the first CRLF in IN_STRING,
- or 0 if it does not contain one. */
-
-static char *
-find_crlf (in_string)
- char *in_string;
-{
- while (1)
- {
- if (! *in_string)
- return (0);
- else if (*in_string == '\r')
- {
- if (*++in_string == '\n')
- return (in_string - 1);
- }
- else
- in_string++;
- }
- /* NOTREACHED */
-}
-
-#endif /* MAIL_USE_POP */
diff --git a/lib-src/pop.h b/lib-src/pop.h
deleted file mode 100644
index 9121425661a..00000000000
--- a/lib-src/pop.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* pop.h: Header file for the "pop.c" client POP3 protocol.
- Copyright (c) 1991,1993 Free Software Foundation, Inc.
- Written by Jonathan Kamens, jik@security.ov.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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include <stdio.h>
-
-#define GETLINE_MIN 1024 /* the getline buffer starts out this */
- /* size */
-#define GETLINE_INCR 1024 /* the getline buffer is grown by this */
- /* size when it needs to grow */
-
-extern char pop_error[];
-extern int pop_debug;
-
-struct _popserver
-{
- int file, data;
- char *buffer;
- int buffer_size, buffer_index;
- int in_multi;
- int trash_started;
-};
-
-typedef struct _popserver *popserver;
-
-/*
- * Valid flags for the pop_open function.
- */
-
-#define POP_NO_KERBEROS (1<<0)
-#define POP_NO_HESIOD (1<<1)
-#define POP_NO_GETPASS (1<<2)
-
-#ifdef __STDC__
-#define _ARGS(a) a
-#else
-#define _ARGS(a) ()
-#endif
-
-extern popserver pop_open _ARGS((char *host, char *username, char *password,
- int flags));
-extern int pop_stat _ARGS((popserver server, int *count, int *size));
-extern int pop_list _ARGS((popserver server, int message, int **IDs,
- int **size));
-extern char *pop_retrieve _ARGS((popserver server, int message, int markfrom));
-extern int pop_retrieve_first _ARGS((popserver server, int message,
- char **response));
-extern int pop_retrieve_next _ARGS((popserver server, char **line));
-extern int pop_retrieve_flush _ARGS((popserver server));
-extern int pop_top_first _ARGS((popserver server, int message, int lines,
- char **response));
-extern int pop_top_next _ARGS((popserver server, char **line));
-extern int pop_top_flush _ARGS((popserver server));
-extern int pop_multi_first _ARGS((popserver server, char *command,
- char **response));
-extern int pop_multi_next _ARGS((popserver server, char **line));
-extern int pop_multi_flush _ARGS((popserver server));
-extern int pop_delete _ARGS((popserver server, int message));
-extern int pop_noop _ARGS((popserver server));
-extern int pop_last _ARGS((popserver server));
-extern int pop_reset _ARGS((popserver server));
-extern int pop_quit _ARGS((popserver server));
-extern void pop_close _ARGS((popserver));
-
-#undef _ARGS
diff --git a/lib-src/profile.c b/lib-src/profile.c
deleted file mode 100644
index b0c713e69dd..00000000000
--- a/lib-src/profile.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* profile.c --- generate periodic events for profiling of Emacs Lisp code.
- Copyright (C) 1992, 1994 Free Software Foundation, Inc.
-
- Author: Boaz Ben-Zvi <boaz@lcs.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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/**
- ** To be run as an emacs process. Input string that starts with:
- ** 'z' -- resets the watch (to zero).
- ** 'p' -- return time (on stdout) as string with format <sec>.<micro-sec>
- ** 'q' -- exit.
- **
- ** abstraction : a stopwatch
- ** operations: reset_watch, get_time
- */
-#include <stdio.h>
-#include <../src/config.h>
-#include <../src/systime.h>
-
-static EMACS_TIME TV1, TV2;
-static int watch_not_started = 1; /* flag */
-static char time_string[30];
-
-/* Reset the stopwatch to zero. */
-
-void
-reset_watch ()
-{
- EMACS_GET_TIME (TV1);
- watch_not_started = 0;
-}
-
-/* This call returns the time since the last reset_watch call. The time
- is returned as a string with the format <seconds>.<micro-seconds>
- If reset_watch was not called yet, exit. */
-
-char *
-get_time ()
-{
- if (watch_not_started)
- exit (1); /* call reset_watch first ! */
- EMACS_GET_TIME (TV2);
- EMACS_SUB_TIME (TV2, TV2, TV1);
- sprintf (time_string, "%lu.%06lu", EMACS_SECS (TV2), EMACS_USECS (TV2));
- return time_string;
-}
-
-#if ! defined (HAVE_GETTIMEOFDAY) && defined (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;
- if (tzp != 0)
- tzp->tz_minuteswest = -1;
-}
-
-#endif
-
-int
-main ()
-{
- int c;
- while ((c = getchar ()) != EOF)
- {
- switch (c)
- {
- case 'z':
- reset_watch ();
- break;
- case 'p':
- puts (get_time ());
- break;
- case 'q':
- exit (0);
- }
- /* Anything remaining on the line is ignored. */
- while (c != '\n' && c != EOF)
- c = getchar ();
- }
- exit (1);
-}
diff --git a/lib-src/rcs-checkin b/lib-src/rcs-checkin
deleted file mode 100755
index f954e54bd45..00000000000
--- a/lib-src/rcs-checkin
+++ /dev/null
@@ -1,98 +0,0 @@
-#! /bin/sh
-
-# This script accepts any number of file arguments and checks them into RCS.
-#
-# Arguments which are detectably either RCS masters (with names ending in ,v)
-# or Emacs version files (with names of the form foo.~<number>~) are ignored.
-# For each file foo, the script looks for Emacs version files related to it.
-# These files are checked in as deltas, oldest first, so that the contents of
-# the file itself becomes the latest revision in the master.
-#
-# The first line of each file is used as its description text. The file itself
-# is not deleted, as under VC with vc-keep-workfiles at its default of t, but
-# all the version files are.
-#
-# If an argument file is already version-controlled under RCS, any version
-# files are added to the list of deltas and deleted, and then the workfile
-# is checked in again as the latest version. This is probably not quite
-# what was wanted, and is the main reason VC doesn't simply call this to
-# do checkins.
-#
-# This script is intended to be used to convert files with an old-Emacs-style
-# version history for use with VC (the Emacs 19 version-control interface),
-# which likes to use RCS as its back end. It was written by Paul Eggert
-# and revised/documented for use with VC by Eric S. Raymond, Mar 19 1993.
-
-case $# in
-0)
- echo "rcs-checkin: usage: rcs-checkin file ..."
- echo "rcs-checkin: function: checks file.~*~ and file into a new RCS file"
- echo "rcs-checkin: function: uses the file's first line for the description"
-esac
-
-# expr pattern to extract owner from ls -l output
-ls_owner_pattern='[^ ][^ ]* *[^ ][^ ]* *\([^ ][^ ]*\)'
-
-for file
-do
- # Make it easier to say `rcs-checkin *'
- # by ignoring file names that already contain `~', or end in `,v'.
- case $file in
- *~* | *,v) continue
- esac
- # Ignore non-files too.
- test -f "$file" || continue
-
- # Check that file is readable.
- test -r "$file" || exit
-
- # If the RCS file does not already exist,
- # initialize it with a description from $file's first line.
- rlog -R "$file" >/dev/null 2>&1 ||
- rcs -i -q -t-"`sed 1q $file`" "$file" || exit
-
- # Get list of old files.
- oldfiles=`
- ls $file.~[0-9]*~ 2>/dev/null |
- sort -t~ -n +1
- `
-
- # Check that they are properly sorted by date.
- case $oldfiles in
- ?*)
- oldfiles_by_date=`ls -rt $file $oldfiles`
- test " $oldfiles
-$file" = " $oldfiles_by_date" || {
- echo >&2 "rcs-checkin: skipping $file, because its mod times are out of order.
-
-Sorted by mod time:
-$oldfiles_by_date
-
-Sorted by name:
-$oldfiles
-$file"
- continue
- }
- esac
-
- echo >&2 rcs-checkin: checking in: $oldfiles $file
-
- # Save $file as $file.~-~ temporarily.
- mv "$file" "$file.~-~" || exit
-
- # Rename each old file to $file, and check it in.
- for oldfile in $oldfiles
- do
- mv "$oldfile" "$file" || exit
- ls_l=`ls -l "$file"` || exit
- owner=-w`expr " $ls_l" : " $ls_owner_pattern"` || owner=
- echo "Formerly ${oldfile}" | ci -d -l -q $owner "$file" || exit
- done
-
- # Bring $file back from $file.~-~, and check it in.
- mv "$file.~-~" "$file" || exit
- ls_l=`ls -l "$file"` || exit
- owner=-w`expr " $ls_l" : " $ls_owner_pattern"` || owner=
- ci -d -q -u $owner -m"entered into RCS" "$file" || exit
-done
-
diff --git a/lib-src/rcs2log b/lib-src/rcs2log
deleted file mode 100755
index 44a12bd3da8..00000000000
--- a/lib-src/rcs2log
+++ /dev/null
@@ -1,612 +0,0 @@
-#! /bin/sh
-
-# RCS to ChangeLog generator
-
-# Generate a change log prefix from RCS files and the ChangeLog (if any).
-# Output the new prefix to standard output.
-# You can edit this prefix by hand, and then prepend it to ChangeLog.
-
-# Ignore log entries that start with `#'.
-# Clump together log entries that start with `{topic} ',
-# where `topic' contains neither white space nor `}'.
-
-# Author: Paul Eggert <eggert@twinsun.com>
-
-# $Id: rcs2log,v 1.34 1996/10/13 05:59:42 eggert Exp eggert $
-
-# Copyright 1992, 1993, 1994, 1995, 1996 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 2, 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, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-tab=' '
-nl='
-'
-
-# Parse options.
-
-# defaults
-: ${AWK=awk}
-: ${TMPDIR=/tmp}
-changelog=ChangeLog # change log file name
-datearg= # rlog date option
-hostname= # name of local host (if empty, will deduce it later)
-indent=8 # indent of log line
-length=79 # suggested max width of log line
-logins= # login names for people we know fullnames and mailaddrs of
-loginFullnameMailaddrs= # login<tab>fullname<tab>mailaddr triplets
-logTZ= # time zone for log dates (if empty, use local time)
-recursive= # t if we want recursive rlog
-revision= # t if we want revision numbers
-rlog_options= # options to pass to rlog
-tabwidth=8 # width of horizontal tab
-
-while :
-do
- case $1 in
- -c) changelog=${2?}; shift;;
- -i) indent=${2?}; shift;;
- -h) hostname=${2?}; shift;;
- -l) length=${2?}; shift;;
- -[nu]) # -n is obsolescent; it is replaced by -u.
- case $1 in
- -n) case ${2?}${3?}${4?} in
- *"$tab"* | *"$nl"*)
- echo >&2 "$0: -n '$2' '$3' '$4': tabs, newlines not allowed"
- exit 1
- esac
- loginFullnameMailaddrs=$loginFullnameMailaddrs$nl$2$tab$3$tab$4
- shift; shift; shift;;
- -u)
- # If $2 is not tab-separated, use colon for separator.
- case ${2?} in
- *"$nl"*)
- echo >&2 "$0: -u '$2': newlines not allowed"
- exit 1;;
- *"$tab"*)
- t=$tab;;
- *)
- t=:
- esac
- case $2 in
- *"$t"*"$t"*"$t"*)
- echo >&2 "$0: -u '$2': too many fields"
- exit 1;;
- *"$t"*"$t"*)
- ;;
- *)
- echo >&2 "$0: -u '$2': not enough fields"
- exit 1
- esac
- loginFullnameMailaddrs=$loginFullnameMailaddrs$nl$2
- shift
- esac
- logins=$logins$nl$login
- ;;
- -r) rlog_options=$rlog_options$nl${2?}; shift;;
- -R) recursive=t;;
- -t) tabwidth=${2?}; shift;;
- -v) revision=t;;
- -*) echo >&2 "$0: usage: $0 [options] [file ...]
-Options:
- [-c changelog] [-h hostname] [-i indent] [-l length] [-R]
- [-r rlog_option] [-t tabwidth] [-v]
- [-u 'login<TAB>fullname<TAB>mailaddr']..."
- exit 1;;
- *) break
- esac
- shift
-done
-
-month_data='
- m[0]="Jan"; m[1]="Feb"; m[2]="Mar"
- m[3]="Apr"; m[4]="May"; m[5]="Jun"
- m[6]="Jul"; m[7]="Aug"; m[8]="Sep"
- m[9]="Oct"; m[10]="Nov"; m[11]="Dec"
-'
-
-
-# Put rlog output into $rlogout.
-
-# If no rlog options are given,
-# log the revisions checked in since the first ChangeLog entry.
-# Since ChangeLog is only by date, some of these revisions may be duplicates of
-# what's already in ChangeLog; it's the user's responsibility to remove them.
-case $rlog_options in
-'')
- if test -s "$changelog"
- then
- e='
- /^[0-9]+-[0-9][0-9]-[0-9][0-9]/{
- # ISO 8601 date
- print $1
- exit
- }
- /^... ... [ 0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]+ /{
- # old-fashioned date and time (Emacs 19.31 and earlier)
- '"$month_data"'
- year = $5
- for (i=0; i<=11; i++) if (m[i] == $2) break
- dd = $3
- printf "%d-%02d-%02d\n", year, i+1, dd
- exit
- }
- '
- d=`$AWK "$e" <"$changelog"` || exit
- case $d in
- ?*) datearg="-d>$d"
- esac
- fi
-esac
-
-# Use TZ specified by ChangeLog local variable, if any.
-if test -s "$changelog"
-then
- extractTZ='
- /^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*"\([^"]*\)".*/{
- s//\1/; p; q
- }
- /^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*t.*/{
- s//UTC0/; p; q
- }
- '
- logTZ=`tail "$changelog" | sed -n "$extractTZ"`
- case $logTZ in
- ?*) TZ=$logTZ; export TZ
- esac
-fi
-
-# If CVS is in use, examine its repository, not the normal RCS files.
-if test ! -f CVS/Repository
-then
- rlog=rlog
- repository=
-else
- rlog='cvs log'
- repository=`sed 1q <CVS/Repository` || exit
- test ! -f CVS/Root || CVSROOT=`cat <CVS/Root` || exit
- case $CVSROOT in
- *:/*)
- # remote repository
- ;;
- *)
- # local repository
- case $repository in
- /*) ;;
- *) repository=${CVSROOT?}/$repository
- esac
- if test ! -d "$repository"
- then
- echo >&2 "$0: $repository: bad repository (see CVS/Repository)"
- exit 1
- fi
- esac
-fi
-
-# Use $rlog's -zLT option, if $rlog supports it.
-case `$rlog -zLT 2>&1` in
-*' option'*) ;;
-*) rlog_options=-zLT$nl$rlog_options
-esac
-
-# With no arguments, examine all files under the RCS directory.
-case $# in
-0)
- case $repository in
- '')
- oldIFS=$IFS
- IFS=$nl
- case $recursive in
- t)
- RCSdirs=`find . -name RCS -type d -print`
- filesFromRCSfiles='s|,v$||; s|/RCS/|/|; s|^\./||'
- files=`
- {
- case $RCSdirs in
- ?*) find $RCSdirs -type f -print
- esac
- find . -name '*,v' -print
- } |
- sort -u |
- sed "$filesFromRCSfiles"
- `;;
- *)
- files=
- for file in RCS/.* RCS/* .*,v *,v
- do
- case $file in
- RCS/. | RCS/..) continue;;
- RCS/.\* | RCS/\* | .\*,v | \*,v) test -f "$file" || continue
- esac
- files=$files$nl$file
- done
- case $files in
- '') exit 0
- esac
- esac
- set x $files
- shift
- IFS=$oldIFS
- esac
-esac
-
-llogout=$TMPDIR/rcs2log$$l
-rlogout=$TMPDIR/rcs2log$$r
-trap exit 1 2 13 15
-trap "rm -f $llogout $rlogout; exit 1" 0
-
-case $datearg in
-?*) $rlog $rlog_options "$datearg" ${1+"$@"} >$rlogout;;
-'') $rlog $rlog_options ${1+"$@"} >$rlogout
-esac || exit
-
-
-# Get the full name of each author the logs mention, and set initialize_fullname
-# to awk code that initializes the `fullname' awk associative array.
-# Warning: foreign authors (i.e. not known in the passwd file) are mishandled;
-# you have to fix the resulting output by hand.
-
-initialize_fullname=
-initialize_mailaddr=
-
-case $loginFullnameMailaddrs in
-?*)
- case $loginFullnameMailaddrs in
- *\"* | *\\*)
- sed 's/["\\]/\\&/g' >$llogout <<EOF || exit
-$loginFullnameMailaddrs
-EOF
- loginFullnameMailaddrs=`cat $llogout`
- esac
-
- oldIFS=$IFS
- IFS=$nl
- for loginFullnameMailaddr in $loginFullnameMailaddrs
- do
- case $loginFullnameMailaddr in
- *"$tab"*) IFS=$tab;;
- *) IFS=:
- esac
- set x $loginFullnameMailaddr
- login=$2
- fullname=$3
- mailaddr=$4
- initialize_fullname="$initialize_fullname
- fullname[\"$login\"] = \"$fullname\""
- initialize_mailaddr="$initialize_mailaddr
- mailaddr[\"$login\"] = \"$mailaddr\""
- done
- IFS=$oldIFS
-esac
-
-case $llogout in
-?*) sort -u -o $llogout <<EOF || exit
-$logins
-EOF
-esac
-output_authors='/^date: / {
- if ($2 ~ /^[0-9]*[-\/][0-9][0-9][-\/][0-9][0-9]$/ && $3 ~ /^[0-9][0-9]:[0-9][0-9]:[0-9][0-9][-+0-9:]*;$/ && $4 == "author:" && $5 ~ /^[^;]*;$/) {
- print substr($5, 1, length($5)-1)
- }
-}'
-authors=`
- $AWK "$output_authors" <$rlogout |
- case $llogout in
- '') sort -u;;
- ?*) sort -u | comm -23 - $llogout
- esac
-`
-case $authors in
-?*)
- cat >$llogout <<EOF || exit
-$authors
-EOF
- initialize_author_script='s/["\\]/\\&/g; s/.*/author[\"&\"] = 1/'
- initialize_author=`sed -e "$initialize_author_script" <$llogout`
- awkscript='
- BEGIN {
- alphabet = "abcdefghijklmnopqrstuvwxyz"
- ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- '"$initialize_author"'
- }
- {
- if (author[$1]) {
- fullname = $5
- if (fullname ~ /[0-9]+-[^(]*\([0-9]+\)$/) {
- # Remove the junk from fullnames like "0000-Admin(0000)".
- fullname = substr(fullname, index(fullname, "-") + 1)
- fullname = substr(fullname, 1, index(fullname, "(") - 1)
- }
- if (fullname ~ /,[^ ]/) {
- # Some sites put comma-separated junk after the fullname.
- # Remove it, but leave "Bill Gates, Jr" alone.
- fullname = substr(fullname, 1, index(fullname, ",") - 1)
- }
- abbr = index(fullname, "&")
- if (abbr) {
- a = substr($1, 1, 1)
- A = a
- i = index(alphabet, a)
- if (i) A = substr(ALPHABET, i, 1)
- fullname = substr(fullname, 1, abbr-1) A substr($1, 2) substr(fullname, abbr+1)
- }
-
- # Quote quotes and backslashes properly in full names.
- # Do not use gsub; traditional awk lacks it.
- quoted = ""
- rest = fullname
- for (;;) {
- p = index(rest, "\\")
- q = index(rest, "\"")
- if (p) {
- if (q && q<p) p = q
- } else {
- if (!q) break
- p = q
- }
- quoted = quoted substr(rest, 1, p-1) "\\" substr(rest, p, 1)
- rest = substr(rest, p+1)
- }
-
- printf "fullname[\"%s\"] = \"%s%s\"\n", $1, quoted, rest
- author[$1] = 0
- }
- }
- '
-
- initialize_fullname=`
- (
- cat /etc/passwd
- for author in $authors
- do nismatch $author passwd.org_dir
- done
- ypmatch $authors passwd
- ) 2>/dev/null |
- $AWK -F: "$awkscript"
- `$initialize_fullname
-esac
-
-
-# Function to print a single log line.
-# We don't use awk functions, to stay compatible with old awk versions.
-# `Log' is the log message (with \n replaced by \r).
-# `files' contains the affected files.
-printlogline='{
-
- # Following the GNU coding standards, rewrite
- # * file: (function): comment
- # to
- # * file (function): comment
- if (Log ~ /^\([^)]*\): /) {
- i = index(Log, ")")
- files = files " " substr(Log, 1, i)
- Log = substr(Log, i+3)
- }
-
- # If "label: comment" is too long, break the line after the ":".
- sep = " "
- if ('"$length"' <= '"$indent"' + 1 + length(files) + index(Log, CR)) sep = "\n" indent_string
-
- # Print the label.
- printf "%s*%s:", indent_string, files
-
- # Print each line of the log, transliterating \r to \n.
- while ((i = index(Log, CR)) != 0) {
- logline = substr(Log, 1, i-1)
- if (logline ~ /[^'"$tab"' ]/) {
- printf "%s%s\n", sep, logline
- } else {
- print ""
- }
- sep = indent_string
- Log = substr(Log, i+1)
- }
-}'
-
-# Pattern to match the `revision' line of rlog output.
-rlog_revision_pattern='^revision [0-9]+\.[0-9]+(\.[0-9]+\.[0-9]+)*(['"$tab"' ]+locked by: [^'"$tab"' $,.0-9:;@]*[^'"$tab"' $,:;@][^'"$tab"' $,.0-9:;@]*;)?['"$tab"' ]*$'
-
-case $hostname in
-'')
- hostname=`(
- hostname || uname -n || uuname -l || cat /etc/whoami
- ) 2>/dev/null` || {
- echo >&2 "$0: cannot deduce hostname"
- exit 1
- }
-
- case $hostname in
- *.*) ;;
- *)
- domainname=`(domainname) 2>/dev/null` &&
- case $domainname in
- *.*) hostname=$hostname.$domainname
- esac
- esac
-esac
-
-
-# Process the rlog output, generating ChangeLog style entries.
-
-# First, reformat the rlog output so that each line contains one log entry.
-# Transliterate \n to \r so that multiline entries fit on a single line.
-# Discard irrelevant rlog output.
-$AWK <$rlogout '
- BEGIN { repository = "'"$repository"'" }
- /^RCS file:/ {
- if (repository != "") {
- filename = $3
- if (substr(filename, 1, length(repository) + 1) == repository "/") {
- filename = substr(filename, length(repository) + 2)
- }
- if (filename ~ /,v$/) {
- filename = substr(filename, 1, length(filename) - 2)
- }
- if (filename ~ /(^|\/)Attic\/[^\/]*$/) {
- i = length(filename)
- while (substr(filename, i, 1) != "/") i--
- filename = substr(filename, 1, i - 6) substr(filename, i + 1)
- }
- }
- rev = "?"
- }
- /^Working file:/ { if (repository == "") filename = $3 }
- /'"$rlog_revision_pattern"'/, /^(-----------*|===========*)$/ {
- if ($0 ~ /'"$rlog_revision_pattern"'/) {
- rev = $2
- next
- }
- if ($0 ~ /^date: [0-9][- +\/0-9:]*;/) {
- date = $2
- if (date ~ /\//) {
- # This is a traditional RCS format date YYYY/MM/DD.
- # Replace "/"s with "-"s to get ISO format.
- newdate = ""
- while ((i = index(date, "/")) != 0) {
- newdate = newdate substr(date, 1, i-1) "-"
- date = substr(date, i+1)
- }
- date = newdate date
- }
- time = substr($3, 1, length($3) - 1)
- author = substr($5, 1, length($5)-1)
- printf "%s %s %s %s %s %c", filename, rev, date, time, author, 13
- rev = "?"
- next
- }
- if ($0 ~ /^branches: /) { next }
- if ($0 ~ /^(-----------*|===========*)$/) { print ""; next }
- printf "%s%c", $0, 13
- }
-' |
-
-# Now each line is of the form
-# FILENAME REVISION YYYY-MM-DD HH:MM:SS[+-TIMEZONE] AUTHOR \rLOG
-# where \r stands for a carriage return,
-# and each line of the log is terminated by \r instead of \n.
-# Sort the log entries, first by date+time (in reverse order),
-# then by author, then by log entry, and finally by file name and revision
-# (just in case).
-sort +2 -4r +4 +0 |
-
-# Finally, reformat the sorted log entries.
-$AWK '
- BEGIN {
- logTZ = "'"$logTZ"'"
- revision = "'"$revision"'"
-
- # Some awk variants do not understand "\r" or "\013", so we have to
- # put a carriage return directly in the file.
- CR=" " # <-- There is a single CR between the " chars here.
-
- # Initialize the fullname and mailaddr associative arrays.
- '"$initialize_fullname"'
- '"$initialize_mailaddr"'
-
- # Initialize indent string.
- indent_string = ""
- i = '"$indent"'
- if (0 < '"$tabwidth"')
- for (; '"$tabwidth"' <= i; i -= '"$tabwidth"')
- indent_string = indent_string "\t"
- while (1 <= i--)
- indent_string = indent_string " "
- }
-
- {
- newlog = substr($0, 1 + index($0, CR))
-
- # Ignore log entries prefixed by "#".
- if (newlog ~ /^#/) { next }
-
- if (Log != newlog || date != $3 || author != $5) {
-
- # The previous log and this log differ.
-
- # Print the old log.
- if (date != "") '"$printlogline"'
-
- # Logs that begin with "{clumpname} " should be grouped together,
- # and the clumpname should be removed.
- # Extract the new clumpname from the log header,
- # and use it to decide whether to output a blank line.
- newclumpname = ""
- sep = "\n"
- if (date == "") sep = ""
- if (newlog ~ /^\{[^'"$tab"' }]*}['"$tab"' ]/) {
- i = index(newlog, "}")
- newclumpname = substr(newlog, 1, i)
- while (substr(newlog, i+1) ~ /^['"$tab"' ]/) i++
- newlog = substr(newlog, i+1)
- if (clumpname == newclumpname) sep = ""
- }
- printf sep
- clumpname = newclumpname
-
- # Get ready for the next log.
- Log = newlog
- if (files != "")
- for (i in filesknown)
- filesknown[i] = 0
- files = ""
- }
- if (date != $3 || author != $5) {
- # The previous date+author and this date+author differ.
- # Print the new one.
- date = $3
- time = $4
- author = $5
-
- zone = ""
- if (logTZ && ((i = index(time, "-")) || (i = index(time, "+"))))
- zone = " " substr(time, i)
-
- # Print "date[ timezone] fullname <email address>".
- # Get fullname and email address from associative arrays;
- # default to author and author@hostname if not in arrays.
- if (fullname[author])
- auth = fullname[author]
- else
- auth = author
- printf "%s%s %s ", date, zone, auth
- if (mailaddr[author])
- printf "<%s>\n\n", mailaddr[author]
- else
- printf "<%s@%s>\n\n", author, "'"$hostname"'"
- }
- if (! filesknown[$1]) {
- filesknown[$1] = 1
- if (files == "") files = " " $1
- else files = files ", " $1
- if (revision && $2 != "?") files = files " " $2
- }
- }
- END {
- # Print the last log.
- if (date != "") {
- '"$printlogline"'
- printf "\n"
- }
- }
-' &&
-
-
-# Exit successfully.
-
-exec rm -f $llogout $rlogout
-
-# Local Variables:
-# tab-width:4
-# End:
diff --git a/lib-src/sorted-doc.c b/lib-src/sorted-doc.c
deleted file mode 100644
index 0ba419d4907..00000000000
--- a/lib-src/sorted-doc.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/* Give this program DOCSTR.mm.nn as standard input
- and it outputs to standard output
- a file of texinfo input containing the doc strings.
-
- This version sorts the output by function name.
- */
-
-#include <stdio.h>
-#include <ctype.h>
-
-extern char *malloc ();
-char *xmalloc ();
-
-#define NUL '\0'
-#define MARKER '\037'
-
-#define DEBUG 0
-
-typedef struct line LINE;
-
-struct line
-{
- LINE *next; /* ptr to next or NULL */
- char *line; /* text of the line */
-};
-
-typedef struct docstr DOCSTR;
-
-struct docstr /* Allocated thing for an entry. */
-{
- DOCSTR *next; /* next in the chain */
- char *name; /* name of the function or var */
- LINE *first; /* first line of doc text. */
- char type; /* 'F' for function, 'V' for variable */
-};
-
-
-/* Print error message. `s1' is printf control string, `s2' is arg for it. */
-
-void
-error (s1, s2)
- char *s1, *s2;
-{
- fprintf (stderr, "sorted-doc: ");
- fprintf (stderr, s1, s2);
- fprintf (stderr, "\n");
-}
-
-/* Print error message and exit. */
-
-void
-fatal (s1, s2)
- char *s1, *s2;
-{
- error (s1, s2);
- exit (1);
-}
-
-/* Like malloc but get fatal error if memory is exhausted. */
-
-char *
-xmalloc (size)
- int size;
-{
- char *result = malloc ((unsigned)size);
- if (result == NULL)
- fatal ("%s", "virtual memory exhausted");
- return result;
-}
-
-char *
-xstrdup (str)
- char * str;
-{
- char *buf = xmalloc (strlen (str) + 1);
- (void) strcpy (buf, str);
- return (buf);
-}
-
-/* Comparison function for qsort to call. */
-
-int
-cmpdoc (a, b)
- DOCSTR **a;
- DOCSTR **b;
-{
- register int val = strcmp ((*a)->name, (*b)->name);
- if (val) return val;
- return (*a)->type - (*b)->type;
-}
-
-
-enum state
-{
- WAITING, BEG_NAME, NAME_GET, BEG_DESC, DESC_GET
-};
-
-char *states[] =
-{
- "WAITING", "BEG_NAME", "NAME_GET", "BEG_DESC", "DESC_GET"
-};
-
-int
-main ()
-{
- register DOCSTR *dp = NULL; /* allocated DOCSTR */
- register LINE *lp = NULL; /* allocated line */
- register char *bp; /* ptr inside line buffer */
- register enum state state = WAITING; /* state at start */
- int cnt = 0; /* number of DOCSTRs read */
-
- DOCSTR *docs; /* chain of allocated DOCSTRS */
- char buf[512]; /* line buffer */
-
- while (1) /* process one char at a time */
- {
- /* this char from the DOCSTR file */
- register int ch = getchar ();
-
- /* Beginnings */
-
- if (state == WAITING)
- {
- if (ch == MARKER)
- state = BEG_NAME;
- }
- else if (state == BEG_NAME)
- {
- cnt++;
- if (dp == NULL) /* first dp allocated */
- {
- docs = dp = (DOCSTR*) xmalloc (sizeof (DOCSTR));
- }
- else /* all the rest */
- {
- dp->next = (DOCSTR*) xmalloc (sizeof (DOCSTR));
- dp = dp->next;
- }
- lp = NULL;
- dp->next = NULL;
- bp = buf;
- state = NAME_GET;
- /* Record whether function or variable. */
- dp->type = ch;
- ch = getchar ();
- }
- else if (state == BEG_DESC)
- {
- if (lp == NULL) /* first line for dp */
- {
- dp->first = lp = (LINE*)xmalloc (sizeof (LINE));
- }
- else /* continuing lines */
- {
- lp->next = (LINE*)xmalloc (sizeof (LINE));
- lp = lp->next;
- }
- lp->next = NULL;
- bp = buf;
- state = DESC_GET;
- }
-
- /* process gets */
-
- if (state == NAME_GET || state == DESC_GET)
- {
- if (ch != MARKER && ch != '\n' && ch != EOF)
- {
- *bp++ = ch;
- }
- else /* saving and changing state */
- {
- *bp = NUL;
- bp = xstrdup (buf);
-
- if (state == NAME_GET)
- dp->name = bp;
- else
- lp->line = bp;
-
- bp = buf;
- state = (ch == MARKER) ? BEG_NAME : BEG_DESC;
- }
- } /* NAME_GET || DESC_GET */
- if (ch == EOF)
- break;
- }
-
- {
- DOCSTR **array;
- register int i; /* counter */
-
- /* build array of ptrs to DOCSTRs */
-
- array = (DOCSTR**)xmalloc (cnt * sizeof (*array));
- for (dp = docs, i = 0; dp != NULL ; dp = dp->next)
- array[i++] = dp;
-
- /* sort the array by name; within each name, by type */
-
- qsort ((char*)array, cnt, sizeof (DOCSTR*), cmpdoc);
-
- /* write the output header */
-
- printf ("\\input texinfo @c -*-texinfo-*-\n");
- printf ("@setfilename ../info/summary\n");
- printf ("@settitle Command Summary for GNU Emacs\n");
- printf ("@unnumbered Command Summary for GNU Emacs\n");
- printf ("@table @asis\n");
- printf ("\n");
- printf ("@let@ITEM@item\n");
- printf ("@def@item{@filbreak@vskip5pt@ITEM}\n");
- printf ("@font@tensy cmsy10 scaled @magstephalf\n");
- printf ("@font@teni cmmi10 scaled @magstephalf\n");
- printf ("@def\\{{@tensy@char110}}\n"); /* this backslash goes with cmr10 */
- printf ("@def|{{@tensy@char106}}\n");
- printf ("@def@{{{@tensy@char102}}\n");
- printf ("@def@}{{@tensy@char103}}\n");
- printf ("@def<{{@teni@char62}}\n");
- printf ("@def>{{@teni@char60}}\n");
- printf ("@chardef@@64\n");
- printf ("@catcode43=12\n");
- printf ("@tableindent-0.2in\n");
-
- /* print each function from the array */
-
- for (i = 0; i < cnt; i++)
- {
- printf ("\n@item %s @code{%s}\n@display\n",
- array[i]->type == 'F' ? "Function" : "Variable",
- array[i]->name);
-
- for (lp = array[i]->first; lp != NULL ; lp = lp->next)
- {
- for (bp = lp->line; *bp; bp++)
- {
- /* the characters "@{}" need special treatment */
- if (*bp == '@' || *bp == '{' || *bp == '}')
- {
- putchar('@');
- }
- putchar(*bp);
- }
- putchar ('\n');
- }
- printf("@end display\n");
- }
-
- printf ("@end table\n");
- printf ("@bye\n");
- }
-
- return 0;
-}
diff --git a/lib-src/tcp.c b/lib-src/tcp.c
deleted file mode 100644
index 5741b52d132..00000000000
--- a/lib-src/tcp.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * TCP/IP stream emulation for GNU Emacs.
- * Copyright (C) 1988, 1989, 1992, 1993 Free Software Foundation, Inc.
-
- * Author: Masanobu Umeda
- * Maintainer: umerin@mse.kyutech.ac.jp
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
- *
- * Yasunari, Itoh at PFU limited contributed for Fujitsu UTS and SX/A.
- *
- * Thu Apr 6 13:47:37 JST 1989
- * USG fixes by Sakaeda <saka@mickey.trad.pf.fujitsu.junet>
- *
- * For Fujitsu UTS compile with:
- * cc -O -o tcp tcp.c -DFUJITSU_UTS -lu -lsocket
- */
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <sys/types.h>
-
-#ifdef FUJITSU_UTS
-#define USG
-#include <sys/ucbtypes.h>
-#include <sys/tisp/socket.h>
-#include <netdb.h>
-#include <sys/tisp/in.h>
-#else
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#endif
-
-#ifdef USG
-#include <sys/stat.h>
-#include <signal.h>
-#endif
-
-#ifdef FUJITSU_UTS
-#define bcopy(f, t, n) memcpy (t, f, n)
-#define bcmp(b1, b2, n) (memcmp (b1, b2, n)!=0)
-#define bzero(b, n) memset (b, 0, n)
-#endif
-
-#ifdef USG
-int selectable = 1;
-
-sigout ()
-{
- fcntl (fileno (stdin), F_SETFL, 0);
- exit (-1);
-}
-#endif
-
-main (argc, argv)
- int argc;
- char *argv[];
-{
- struct hostent *host;
- struct sockaddr_in sockin, sockme;
- struct servent *serv;
- char *hostname = NULL;
- char *service = "nntp";
- int port;
- int readfds;
- int writefds;
- int server; /* NNTP Server */
- int emacsIn = fileno (stdin); /* Emacs intput */
- int emacsOut = fileno (stdout); /* Emacs output */
- char buffer[1024];
- int nbuffer; /* Number of bytes in buffer */
- int wret;
- char *retry; /* retry bufferp */
- int false = 0; /* FALSE flag for setsockopt () */
-
- if (argc < 2)
- {
- fprintf (stderr, "Usage: %s HOST [SERVICE]\n", argv[0]);
- exit (1);
- }
- if (argc >= 2)
- hostname = argv[1];
- if (argc >= 3)
- service = argv[2];
-
- if ((host = gethostbyname (hostname)) == NULL)
- {
- perror ("gethostbyname");
- exit (1);
- }
- if (isdigit (service[0]))
- port = atoi (service);
- else
- {
- serv = getservbyname (service, "tcp");
- if (serv == NULL)
- {
- perror ("getservbyname");
- exit (1);
- }
- port = serv->s_port;
- }
-
- bzero (&sockin, sizeof (sockin));
- sockin.sin_family = host->h_addrtype;
- bcopy (host->h_addr, &sockin.sin_addr, host->h_length);
- sockin.sin_port = htons (port);
- if ((server = socket (AF_INET, SOCK_STREAM, 0)) < 0)
- {
- perror ("socket");
- exit (1);
- }
- if (setsockopt (server, SOL_SOCKET, SO_REUSEADDR, &false, sizeof (false)))
- {
- perror ("setsockopt");
- exit (1);
- }
- bzero (&sockme, sizeof (sockme));
- sockme.sin_family = sockin.sin_family;
- sockme.sin_addr.s_addr = INADDR_ANY;
- if (bind (server, &sockme, sizeof (sockme)) < 0)
- {
- perror ("bind");
- exit (1);
- }
- if (connect (server, &sockin, sizeof (sockin)) < 0)
- {
- perror ("connect");
- close (server);
- exit (1);
- }
-
-#ifdef O_NDELAY
- fcntl (server, F_SETFL, O_NDELAY);
-
-#ifdef USG
- /* USG pipe cannot not select emacsIn */
- {
- struct stat statbuf;
- fstat (emacsIn, &statbuf);
- if (statbuf.st_mode & 010000)
- selectable = 0;
- if (!selectable)
- {
- signal (SIGINT, sigout);
- fcntl (emacsIn, F_SETFL, O_NDELAY);
- }
- }
-#endif
-#endif
-
- /* Connection established. */
- while (1)
- {
- readfds = (1 << server) | (1 << emacsIn);
- if (select (32, &readfds, NULL, NULL, (struct timeval *)NULL) == -1)
- {
- perror ("select");
- exit (1);
- }
- if (readfds & (1 << emacsIn))
- {
- /* From Emacs */
- nbuffer = read (emacsIn, buffer, sizeof buffer -1);
-
-#ifdef USG
- if (selectable && nbuffer == 0)
- {
- goto finish;
- }
- else if (!(readfds & (1 << server)) && nbuffer == 0)
- {
- sleep (1);
- }
- else
-#else
- if (nbuffer == 0)
- goto finish;
-#endif
- for (retry = buffer; nbuffer > 0; nbuffer -= wret, retry += wret)
- {
- writefds = 1 << server;
- if (select (server+1, NULL, &writefds, NULL, (struct timeval*)NULL) == -1)
- {
- perror ("select");
- exit (1);
- }
- wret = write (server, retry, nbuffer);
- if (wret < 0) goto finish;
- }
- }
- if (readfds & (1 << server))
- {
- /* From NNTP server */
- nbuffer = read (server, buffer, sizeof buffer -1);
- if (nbuffer == 0)
- goto finish;
- for (retry = buffer; nbuffer > 0; nbuffer -= wret, retry += wret)
- {
- writefds = 1 << emacsOut;
-#ifdef USG
- if (selectable)
-#endif
- if (select (emacsOut+1, NULL, &writefds, NULL, (struct timeval*)NULL) == -1)
- {
- perror ("select");
- exit (1);
- }
- wret = write (emacsOut, retry, nbuffer);
- if (wret < 0) goto finish;
- }
- }
- }
-
- /* End of communication. */
- finish:
- close (server);
-#ifdef USG
- if (!selectable) fcntl (emacsIn, F_SETFL, 0);
-#endif
- close (emacsIn);
- close (emacsOut);
- exit (0);
-}
diff --git a/lib-src/test-distrib.c b/lib-src/test-distrib.c
deleted file mode 100644
index 01897b83a7f..00000000000
--- a/lib-src/test-distrib.c
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-/* Cancel substitutions made by config.h for Emacs. */
-#undef open
-#undef read
-#undef write
-#undef close
-
-#include <stdio.h>
-
-#ifndef O_RDONLY
-#define O_RDONLY 0
-#endif
-
-
-/* Break string in two parts to avoid buggy C compilers that ignore characters
- after nulls in strings. */
-
-char string1[] = "Testing distribution of nonprinting chars:\n\
-Should be 0177: \177 Should be 0377: \377 Should be 0212: \212.\n\
-Should be 0000: ";
-
-char string2[] = ".\n\
-This file is read by the `test-distribution' program.\n\
-If you change it, you will make that program fail.\n";
-
-char buf[300];
-
-/* Like `read' but keeps trying until it gets SIZE bytes or reaches eof. */
-int
-cool_read (fd, buf, size)
- int fd;
- char *buf;
- int size;
-{
- int num, sofar = 0;
-
- while (1)
- {
- if ((num = read (fd, buf + sofar, size - sofar)) == 0)
- return sofar;
- else if (num < 0)
- return num;
- sofar += num;
- }
-}
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- int fd;
-
- if (argc != 2)
- {
- fprintf (stderr, "Usage: %s testfile\n", argv[0]);
- exit (2);
- }
- fd = open (argv[1], O_RDONLY);
- if (fd < 0)
- {
- perror (argv[1]);
- exit (2);
- }
- if (cool_read (fd, buf, sizeof string1) != sizeof string1 ||
- strcmp (buf, string1) ||
- cool_read (fd, buf, sizeof string2) != sizeof string2 - 1 ||
- strncmp (buf, string2, sizeof string2 - 1))
- {
- fprintf (stderr, "Data in file `%s' has been damaged.\n\
-Most likely this means that many nonprinting characters\n\
-have been corrupted in the files of Emacs, and it will not work.\n",
- argv[1]);
- exit (2);
- }
- close (fd);
-#ifdef VMS
- exit (1); /* On VMS, success is 1. */
-#endif
- return (0);
-}
diff --git a/lib-src/vcdiff b/lib-src/vcdiff
deleted file mode 100755
index e2023809e01..00000000000
--- a/lib-src/vcdiff
+++ /dev/null
@@ -1,93 +0,0 @@
-#! /bin/sh
-#
-# Enhanced sccs diff utility for use with vc mode.
-# This version is more compatible with rcsdiff(1).
-#
-# $Id: vcdiff,v 1.5 1995/07/07 22:47:57 eggert Exp $
-#
-
-DIFF="diff"
-usage="$0: Usage: vcdiff [--brief] [-q] [-r<sid1>] [-r<sid2>] [diffopts] sccsfile..."
-
-PATH=$PATH:/usr/ccs/bin:/usr/sccs:/usr/xpg4/bin # common SCCS hangouts
-
-echo=
-sid1= sid2=
-
-for f
-do
- case $f in
- -*)
- case $f in
- --brief)
- DIFF=cmp;;
- -q)
- echo=:;;
- -r?*)
- case $sid1 in
- '')
- sid1=$f
- ;;
- *)
- case $sid2 in
- ?*) echo "$usage" >&2; exit 2 ;;
- esac
- sid2=$f
- ;;
- esac
- ;;
- *)
- options="$options $f"
- ;;
- esac
- shift
- ;;
- *)
- break
- ;;
- esac
-done
-
-case $# in
-0)
- echo "$usage" >&2
- exit 2
-esac
-
-
-rev1= rev2= status=0
-trap 'status=2; exit' 1 2 13 15
-trap 'rm -f $rev1 $rev2 || status=2; exit $status' 0
-
-for f
-do
- s=2
-
- case $f in
- s.* | */s.*)
- if
- rev1=/tmp/geta$$
- get -s -p -k $sid1 "$f" > $rev1 &&
- case $sid2 in
- '')
- workfile=`expr " /$f" : '.*/s.\(.*\)'`
- ;;
- *)
- rev2=/tmp/getb$$
- get -s -p -k $sid2 "$f" > $rev2
- workfile=$rev2
- esac
- then
- $echo $DIFF $options $sid1 $sid2 $workfile >&2
- $DIFF $options $rev1 $workfile
- s=$?
- fi
- ;;
- *)
- echo "$0: $f is not an SCCS file" >&2
- esac
-
- if test $status -lt $s
- then status=$s
- fi
-done
diff --git a/lib-src/yow.c b/lib-src/yow.c
deleted file mode 100644
index b67d2f1eeee..00000000000
--- a/lib-src/yow.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * yow.c
- *
- * Print a quotation from Zippy the Pinhead.
- * Qux <Kaufman-David@Yale> March 6, 1986
- *
- * This file is in the public domain because the author published it
- * with no copyright notice before the US signed the Bern Convention.
- *
- * With dynamic memory allocation.
- */
-
-#include <stdio.h>
-#include <ctype.h>
-#include <../src/paths.h> /* For PATH_DATA. */
-
-#define BUFSIZE 80
-#define SEP '\0'
-
-#ifndef YOW_FILE
-#define YOW_FILE "yow.lines"
-#endif
-
-#ifdef MSDOS
-#define rootrelativepath(rel) \
-({\
- static char res[BUFSIZE], *p;\
- strcpy (res, argv[0]);\
- p = res + strlen (res);\
- while (p != res && *p != '/' && *p != '\\' && *p != ':') p--;\
- strcpy (p + 1, "../");\
- strcpy (p + 4, rel);\
- &res;})
-#endif
-
-char *malloc(), *realloc();
-
-void yow();
-void setup_yow();
-
-int
-main (argc, argv)
- int argc;
- char *argv[];
-{
- FILE *fp;
- char file[BUFSIZ];
-
- if (argc > 2 && !strcmp (argv[1], "-f"))
- strcpy (file, argv[2]);
- else
-#ifdef vms
- sprintf (file, "%s%s", PATH_DATA, YOW_FILE);
-#else
- sprintf (file, "%s/%s", PATH_DATA, YOW_FILE);
-#endif
-
- if ((fp = fopen(file, "r")) == NULL) {
- fprintf(stderr, "yow: ");
- perror(file);
- exit(1);
- }
-
- /* initialize random seed */
- srand((int) (getpid() + time((long *) 0)));
-
- setup_yow(fp);
- yow(fp);
- fclose(fp);
- return 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, "yow: 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("yow");
- 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;
-{
- long offset;
- int c, i = 0;
- char *buf;
- unsigned int bufsize;
-
- offset = rand() % len + header_len;
- if (fseek(fp, offset, 0) == -1) {
- perror("yow");
- exit(1);
- }
-
- /* Read until SEP, read next line, print it.
- (Note that we will never print anything before the first separator.)
- If we hit EOF looking for the first SEP, just recurse. */
- while ((c = getc(fp)) != SEP)
- if (c == EOF) {
- yow(fp);
- return;
- }
-
- /* Skip leading whitespace, then read in a quotation.
- If we hit EOF before we find a non-whitespace char, recurse. */
- while (isspace(c = getc(fp)))
- ;
- if (c == EOF) {
- yow(fp);
- return;
- }
-
- bufsize = BUFSIZE;
- buf = malloc(bufsize);
- if (buf == (char *)0) {
- fprintf(stderr, "yow: virtual memory exhausted\n");
- exit (3);
- }
-
- buf[i++] = c;
- while ((c = getc(fp)) != SEP && c != EOF) {
- buf[i++] = c;
-
- if (i == bufsize-1) {
- /* Yow! Is this quotation too long yet? */
- bufsize *= 2;
- buf = realloc(buf, bufsize);
- if (buf == (char *)0) {
- fprintf(stderr, "yow: virtual memory exhausted\n");
- exit (3);
- }
- }
- }
- buf[i++] = 0;
- printf("%s\n", buf);
-}
-
diff --git a/lisp/=ada.el b/lisp/=ada.el
deleted file mode 100644
index bf7633bf82d..00000000000
--- a/lisp/=ada.el
+++ /dev/null
@@ -1,734 +0,0 @@
-;;; ada.el --- Ada editing support package in GNUlisp. v1.0
-
-;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
-
-;; Author: Vincent Broman <broman@bugs.nosc.mil>
-;; Keywords: languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; Created May 1987.
-;; (borrows heavily from Mick Jordan's Modula-2 package for GNU,
-;; as modified by Peter Robinson, Michael Schmidt, and Tom Perrine.)
-
-;;; Code:
-
-(defvar ada-mode-syntax-table nil
- "Syntax table in use in Ada-mode buffers.")
-
-(let ((table (make-syntax-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 ?- ". 12" 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 ?\\ "." table)
- (modify-syntax-entry ?: "." table)
- (modify-syntax-entry ?\; "." table)
- (modify-syntax-entry ?\' "." table)
- (modify-syntax-entry ?\" "\"" table)
- (modify-syntax-entry ?\n ">" table)
- (setq ada-mode-syntax-table table))
-
-;; Strings are a real pain in Ada because both ' and " can appear in a
-;; non-string quote context (the former as an operator, the latter as a
-;; character string). We follow the least losing solution, in which only " is
-;; a string quote. Therefore a character string of the form '"' will throw
-;; fontification off on the wrong track.
-
-(defconst ada-font-lock-keywords-1
- (list
- ;;
- ;; Function, package (body), pragma, procedure, task (body) plus name.
- (list (concat "\\<\\("
- "function\\|"
- "p\\(ackage\\(\\|[ \t]+body\\)\\|r\\(agma\\|ocedure\\)\\)\\|"
- "task\\(\\|[ \t]+body\\)"
- "\\)\\>[ \t]*\\(\\sw+\\(\\.\\sw*\\)*\\)?")
- '(1 font-lock-keyword-face) '(6 font-lock-function-name-face nil t)))
- "For consideration as a value of `ada-font-lock-keywords'.
-This does fairly subdued highlighting.")
-
-(defconst ada-font-lock-keywords-2
- (append ada-font-lock-keywords-1
- (list
- ;;
- ;; Main keywords, except those treated specially below.
- (concat "\\<\\("
-; ("abort" "abs" "abstract" "accept" "access" "aliased" "all"
-; "and" "array" "at" "begin" "case" "declare" "delay" "delta"
-; "digits" "do" "else" "elsif" "entry" "exception" "exit" "for"
-; "generic" "if" "in" "is" "limited" "loop" "mod" "not"
-; "null" "or" "others" "private" "protected"
-; "range" "record" "rem" "renames" "requeue" "return" "reverse"
-; "select" "separate" "tagged" "task" "terminate" "then" "until"
-; "while" "xor")
- "a\\(b\\(ort\\|s\\(\\|tract\\)\\)\\|cce\\(pt\\|ss\\)\\|"
- "l\\(iased\\|l\\)\\|nd\\|rray\\|t\\)\\|begin\\|case\\|"
- "d\\(e\\(clare\\|l\\(ay\\|ta\\)\\)\\|igits\\|o\\)\\|"
- "e\\(ls\\(e\\|if\\)\\|ntry\\|x\\(ception\\|it\\)\\)\\|for\\|"
- "generic\\|i[fns]\\|l\\(imited\\|oop\\)\\|mod\\|n\\(ot\\|ull\\)\\|"
- "o\\(r\\|thers\\)\\|pr\\(ivate\\|otected\\)\\|"
- "r\\(ange\\|e\\(cord\\|m\\|names\\|queue\\|turn\\|verse\\)\\)\\|"
- "se\\(lect\\|parate\\)\\|"
- "t\\(a\\(gged\\|sk\\)\\|erminate\\|hen\\)\\|until\\|while\\|xor"
- "\\)\\>")
- ;;
- ;; Anything following end and not already fontified is a body name.
- '("\\<\\(end\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))
-; ;;
-; ;; Variable name plus optional keywords followed by a type name. Slow.
-; (list (concat "\\<\\(\\sw+\\)\\>[ \t]*:"
-; "[ \t]*\\(constant\\|in\\|in[ \t]+out\\|out\\)?[ \t]*"
-; "\\(\\sw+\\(\\.\\sw*\\)*\\)?")
-; '(1 font-lock-variable-name-face)
-; '(2 font-lock-keyword-face nil t) '(3 font-lock-type-face nil t))
- ;;
- ;; Optional keywords followed by a type name.
- (list (concat ":[ \t]*\\<\\(constant\\|in\\|in[ \t]+out\\|out\\)\\>?[ \t]*"
- "\\(\\sw+\\(\\.\\sw*\\)*\\)?")
- '(1 font-lock-keyword-face nil t) '(2 font-lock-type-face nil t))
- ;;
- ;; Keywords followed by a type or function name.
- (list (concat "\\<\\("
- "new\\|of\\|subtype\\|type"
- "\\)\\>[ \t]*\\(\\sw+\\(\\.\\sw*\\)*\\)?[ \t]*\\((\\)?")
- '(1 font-lock-keyword-face)
- '(2 (if (match-beginning 4)
- font-lock-function-name-face
- font-lock-type-face) nil t))
- ;;
- ;; Keywords followed by a reference.
- (list (concat "\\<\\(goto\\|raise\\|use\\|when\\|with\\)\\>"
- "[ \t]*\\(\\sw+\\(\\.\\sw*\\)*\\)?")
- '(1 font-lock-keyword-face) '(2 font-lock-reference-face nil t))
- ;;
- ;; Goto tags.
- '("<<\\(\\sw+\\(\\.\\sw*\\)*\\)>>" 1 font-lock-reference-face)
- ))
- "For consideration as a value of `ada-font-lock-keywords'.
-This does a lot more highlighting.")
-
-(defvar ada-font-lock-keywords (if font-lock-maximum-decoration
- ada-font-lock-keywords-2
- ada-font-lock-keywords-1)
- "Additional expressions to highlight in Ada mode.")
-
-(defvar ada-mode-map nil
- "Keymap used in Ada mode.")
-
-(let ((map (make-sparse-keymap)))
- (define-key map "\C-m" 'ada-newline)
- (define-key map "\C-?" 'backward-delete-char-untabify)
- (define-key map "\C-i" 'ada-tab)
- (define-key map "\C-c\C-i" 'ada-untab)
- (define-key map "\C-c<" 'ada-backward-to-same-indent)
- (define-key map "\C-c>" 'ada-forward-to-same-indent)
- (define-key map "\C-ch" 'ada-header)
- (define-key map "\C-c(" 'ada-paired-parens)
- (define-key map "\C-c-" 'ada-inline-comment)
- (define-key map "\C-c\C-a" 'ada-array)
- (define-key map "\C-cb" 'ada-exception-block)
- (define-key map "\C-cd" 'ada-declare-block)
- (define-key map "\C-c\C-e" 'ada-exception)
- (define-key map "\C-cc" 'ada-case)
- (define-key map "\C-c\C-k" 'ada-package-spec)
- (define-key map "\C-ck" 'ada-package-body)
- (define-key map "\C-c\C-p" 'ada-procedure-spec)
- (define-key map "\C-cp" 'ada-subprogram-body)
- (define-key map "\C-c\C-f" 'ada-function-spec)
- (define-key map "\C-cf" 'ada-for-loop)
- (define-key map "\C-cl" 'ada-loop)
- (define-key map "\C-ci" 'ada-if)
- (define-key map "\C-cI" 'ada-elsif)
- (define-key map "\C-ce" 'ada-else)
- (define-key map "\C-c\C-v" 'ada-private)
- (define-key map "\C-c\C-r" 'ada-record)
- (define-key map "\C-c\C-s" 'ada-subtype)
- (define-key map "\C-cs" 'ada-separate)
- (define-key map "\C-c\C-t" 'ada-type)
- (define-key map "\C-ct" 'ada-tabsize)
-;; (define-key map "\C-c\C-u" 'ada-use)
-;; (define-key map "\C-c\C-w" 'ada-with)
- (define-key map "\C-cw" 'ada-while-loop)
- (define-key map "\C-c\C-w" 'ada-when)
- (define-key map "\C-cx" 'ada-exit)
- (define-key map "\C-cC" 'ada-compile)
- (define-key map "\C-cB" 'ada-bind)
- (define-key map "\C-cE" 'ada-find-listing)
- (define-key map "\C-cL" 'ada-library-name)
- (define-key map "\C-cO" 'ada-options-for-bind)
- (setq ada-mode-map map))
-
-(defvar ada-indent 4 "*Value is the number of columns to indent in Ada-Mode.")
-
-(defvar ada-comment-end-column)
-
-(defun ada-mode ()
-"This is a mode intended to support program development in Ada.
-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
-having the same (or lesser) level of indentation.
-
-Variable `ada-indent' controls the number of spaces for indent/undent."
- (interactive)
- (kill-all-local-variables)
- (use-local-map ada-mode-map)
- (setq major-mode 'ada-mode)
- (setq mode-name "Ada")
- (make-local-variable 'comment-column)
- (setq comment-column 41)
- (make-local-variable 'ada-comment-end-column)
- (setq ada-comment-end-column 72)
- (set-syntax-table ada-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 41)
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip "--+ *")
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'c-comment-indent)
- (make-local-variable 'parse-sexp-ignore-comments)
- (setq parse-sexp-ignore-comments t)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(ada-font-lock-keywords nil t ((?\_ . "w"))))
- (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")
- (setq ada-indent s))
-
-(defun ada-newline ()
- "Start new line and indent to current tab stop."
- (interactive)
- (let ((ada-cc (current-indentation)))
- (newline)
- (indent-to ada-cc)))
-
-(defun ada-tab ()
- "Indent to next tab stop."
- (interactive)
- (indent-to (* (1+ (/ (current-indentation) ada-indent)) ada-indent)))
-
-(defun ada-untab ()
- "Delete backwards to previous tab stop."
- (interactive)
- (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."
- (while (and
- (zerop (forward-line step))
- (or (looking-at "^[ ]*$")
- (looking-at "^[ ]*--")
- (looking-at "^<<[A-Za-z0-9_]+>>")
- (looking-at "^[A-Za-z0-9_]+:")
- (> (current-indentation) indent-level)))
- nil))
-
-(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."
- (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."
- (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."
- (interactive)
- (insert "array ()")
- (backward-char)
- (insert (read-string "index subtype[s]: "))
- (end-of-line)
- (insert " of ;")
- (backward-char)
- (insert (read-string "component-type: "))
- (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."
- (interactive)
- (insert "case ")
- (insert (read-string "selector expression: ") " is")
- (ada-newline)
- (ada-newline)
- (insert "end case;")
- (end-of-line 0)
- (ada-tab)
- (ada-tab)
- (ada-when))
-
-(defun ada-declare-block ()
- "Insert a block with a declare part.
-Indent for the first 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)))
- (ada-newline)
- (ada-newline)
- (insert "begin")
- (ada-newline)
- (ada-newline)
- (if (string-equal ada-block-name "")
- (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."
- (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)))
- (ada-newline)
- (ada-newline)
- (insert "exception")
- (ada-newline)
- (ada-newline)
- (cond
- ( (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."
- (interactive)
- (ada-untab)
- (insert "exception")
- (ada-newline)
- (ada-tab))
-
-(defun ada-else ()
- "Add an else clause inside an if-then-end-if clause."
- (interactive)
- (ada-untab)
- (insert "else")
- (ada-newline)
- (ada-tab))
-
-(defun ada-exit ()
- "Insert an exit statement, prompting for loop name and condition."
- (interactive)
- (insert "exit")
- (let ((ada-loop-name (read-string "[name of loop to exit]: ")))
- (if (not (string-equal ada-loop-name "")) (insert " " ada-loop-name)))
- (let ((ada-exit-condition (read-string "[exit condition]: ")))
- (if (not (string-equal ada-exit-condition ""))
- (if (string-match "^ *[Ww][Hh][Ee][Nn] +" ada-exit-condition)
- (insert " " ada-exit-condition)
- (insert " when " ada-exit-condition))))
- (insert ";"))
-
-(defun ada-when ()
- "Start a case statement alternative with a when clause."
- (interactive)
- (ada-untab) ; we were indented in code for the last alternative.
- (insert "when ")
- (insert (read-string "'|'-delimited choice list: ") " =>")
- (ada-newline)
- (ada-tab))
-
-(defun ada-for-loop ()
- "Build a skeleton for-loop statement, prompting for the loop parameters."
- (interactive)
- (insert "for ")
- (let* ((ada-loop-name (read-string "[loop name]: "))
- (ada-loop-is-named (not (string-equal ada-loop-name ""))))
- (if ada-loop-is-named
- (progn
- (beginning-of-line)
- (open-line 1)
- (insert ada-loop-name ":")
- (next-line 1)
- (end-of-line 1)))
- (insert (read-string "loop variable: ") " in ")
- (insert (read-string "range: ") " loop")
- (ada-newline)
- (ada-newline)
- (insert "end loop")
- (if ada-loop-is-named (insert " " ada-loop-name))
- (insert ";"))
- (end-of-line 0)
- (ada-tab))
-
-(defun ada-header ()
- "Insert a comment block containing the module title, author, etc."
- (interactive)
- (insert "--\n-- Title: \t")
- (insert (read-string "Title: "))
- (insert "\n-- Created:\t" (current-time-string))
- (insert "\n-- Author: \t" (user-full-name))
- (insert "\n--\t\t<" (user-login-name) "@" (system-name) ">\n--\n"))
-
-(defun ada-if ()
- "Insert skeleton if statment, prompting for a boolean-expression."
- (interactive)
- (insert "if ")
- (insert (read-string "condition: ") " then")
- (ada-newline)
- (ada-newline)
- (insert "end if;")
- (end-of-line 0)
- (ada-tab))
-
-(defun ada-elsif ()
- "Add an elsif clause to an if statement, prompting for the boolean-expression."
- (interactive)
- (ada-untab)
- (insert "elsif ")
- (insert (read-string "condition: ") " then")
- (ada-newline)
- (ada-tab))
-
-(defun ada-loop ()
- "Insert a skeleton loop statement. The exit statement is added by hand."
- (interactive)
- (insert "loop ")
- (let* ((ada-loop-name (read-string "[loop name]: "))
- (ada-loop-is-named (not (string-equal ada-loop-name ""))))
- (if ada-loop-is-named
- (progn
- (beginning-of-line)
- (open-line 1)
- (insert ada-loop-name ":")
- (forward-line 1)
- (end-of-line 1)))
- (ada-newline)
- (ada-newline)
- (insert "end loop")
- (if ada-loop-is-named (insert " " ada-loop-name))
- (insert ";"))
- (end-of-line 0)
- (ada-tab))
-
-(defun ada-package-spec ()
- "Insert a skeleton package specification."
- (interactive)
- (insert "package ")
- (let ((ada-package-name (read-string "package name: " )))
- (insert ada-package-name " is")
- (ada-newline)
- (ada-newline)
- (insert "end " ada-package-name ";")
- (end-of-line 0)
- (ada-tab)))
-
-(defun ada-package-body ()
- "Insert a skeleton package body -- includes a begin statement."
- (interactive)
- (insert "package body ")
- (let ((ada-package-name (read-string "package name: " )))
- (insert ada-package-name " is")
- (ada-newline)
- (ada-newline)
- (insert "begin")
- (ada-newline)
- (insert "end " ada-package-name ";")
- (end-of-line -1)
- (ada-tab)))
-
-(defun ada-private ()
- "Undent and start a private section of a package spec. Reindent."
- (interactive)
- (ada-untab)
- (insert "private")
- (ada-newline)
- (ada-tab))
-
-(defun ada-get-arg-list ()
- "Read from the 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."
- (insert " (")
- (let ((ada-arg-indent (current-column))
- (ada-args (read-string "[arguments]: ")))
- (if (string-equal ada-args "")
- (backward-delete-char 2)
- (progn
- (while (string-match ";$" ada-args)
- (insert ada-args)
- (newline)
- (indent-to ada-arg-indent)
- (setq ada-args (read-string "next argument: ")))
- (insert ada-args ")")))))
-
-(defun ada-function-spec ()
- "Insert a function specification. Prompts for name and arguments."
- (interactive)
- (insert "function ")
- (insert (read-string "function name: "))
- (ada-get-arg-list)
- (insert " return ")
- (insert (read-string "result type: ")))
-
-(defun ada-procedure-spec ()
- "Insert a procedure specification, prompting for its name and arguments."
- (interactive)
- (insert "procedure ")
- (insert (read-string "procedure name: " ))
- (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."
- (save-excursion
- (let ((ada-proc-indent 0))
- (if (re-search-backward
- ;;;; Unfortunately, comments are not ignored in this string search.
- "[PpFf][RrUu][OoNn][Cc][EeTt][DdIi][UuOo][RrNn]" nil t)
- (if (or (looking-at "\\<[Pp][Rr][Oo][Cc][Ee][Dd][Uu][Rr][Ee]\\>")
- (looking-at "\\<[Ff][Uu][Nn][Cc][Tt][Ii][Oo][Nn]\\>"))
- (progn
- (setq ada-proc-indent (current-column))
- (forward-word 2)
- (let ((p2 (point)))
- (forward-word -1)
- (cons (buffer-substring (point) p2) ada-proc-indent)))
- (get-ada-subprogram-name))
- (cons "NAME?" ada-proc-indent)))))
-
-(defun ada-subprogram-body ()
- "Insert frame for subprogram body.
-Invoke right after `ada-function-spec' or `ada-procedure-spec'."
- (interactive)
- (insert " is")
- (let ((ada-subprogram-name-col (get-ada-subprogram-name)))
- (newline)
- (indent-to (cdr ada-subprogram-name-col))
- (ada-newline)
- (insert "begin")
- (ada-newline)
- (ada-newline)
- (insert "end " (car ada-subprogram-name-col) ";"))
- (end-of-line -2)
- (ada-tab))
-
-(defun ada-separate ()
- "Finish a body stub with `is separate'."
- (interactive)
- (insert " is")
- (ada-newline)
- (ada-tab)
- (insert "separate;")
- (ada-newline)
- (ada-untab))
-
-;(defun ada-with ()
-; "Inserts a with clause, prompting for the list of units depended upon."
-; (interactive)
-; (insert "with ")
-; (insert (read-string "list of units depended upon: ") ";"))
-;
-;(defun ada-use ()
-; "Inserts a use clause, prompting for the list of packages used."
-; (interactive)
-; (insert "use ")
-; (insert (read-string "list of packages to use: ") ";"))
-
-(defun ada-record ()
- "Insert a skeleton record type declaration."
- (interactive)
- (insert "record")
- (ada-newline)
- (ada-newline)
- (insert "end record;")
- (end-of-line 0)
- (ada-tab))
-
-(defun ada-subtype ()
- "Start insertion of a subtype declaration, prompting for the subtype name."
- (interactive)
- (insert "subtype " (read-string "subtype name: ") " is ;")
- (backward-char)
- (message "insert subtype indication."))
-
-(defun ada-type ()
- "Start insertion of a type declaration, prompting for the type name."
- (interactive)
- (insert "type " (read-string "type name: "))
- (let ((disc-part (read-string "discriminant specs: ")))
- (if (not (string-equal disc-part ""))
- (insert "(" disc-part ")")))
- (insert " is ")
- (message "insert type definition."))
-
-(defun ada-while-loop ()
- (interactive)
- (insert "while ")
- (let* ((ada-loop-name (read-string "loop name: "))
- (ada-loop-is-named (not (string-equal ada-loop-name ""))))
- (if ada-loop-is-named
- (progn
- (beginning-of-line)
- (open-line 1)
- (insert ada-loop-name ":")
- (next-line 1)
- (end-of-line 1)))
- (insert (read-string "entry condition: ") " loop")
- (ada-newline)
- (ada-newline)
- (insert "end loop")
- (if ada-loop-is-named (insert " " ada-loop-name))
- (insert ";"))
- (end-of-line 0)
- (ada-tab))
-
-(defun ada-paired-parens ()
- "Insert a pair of round parentheses, placing point between them."
- (interactive)
- (insert "()")
- (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."
- (interactive)
- (end-of-line)
- (if (> (current-column) ada-comment-end-column) (newline))
- (if (< (current-column) comment-column) (indent-to comment-column))
- (insert " -- "))
-
-(defun ada-display-comment ()
-"Inserts three 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-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: ")
- (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': ")))
-
-(defun ada-compile (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 "))
- (ada-source-file (buffer-name)))
- (compile
- (concat "adacomp " ada-init "-l " ada-lib-dir-name " " ada-source-file))))
-
-(defun ada-find-listing ()
- "Find listing file for ada source in current buffer, using other window."
- (interactive)
- (find-file-other-window (concat (substring (buffer-name) 0 -4) ".lis"))
- (search-forward "*** ERROR"))
-
-(defun ada-bind ()
- "Bind the current program library, using the current binding options."
- (interactive)
- (compile (concat "adabind " ada-bind-opts " " ada-lib-dir-name)))
-
-;;; ada.el ends here
diff --git a/lisp/=batmode.el b/lisp/=batmode.el
deleted file mode 100644
index 72a0735c6a6..00000000000
--- a/lisp/=batmode.el
+++ /dev/null
@@ -1,165 +0,0 @@
-;;; batmode.el --- Simple mode for Windows BAT files
-
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Peter Breton <pbreton@i-kinetics.com>
-;; Created: Thu Jul 25 1996
-;; Keywords: BAT, DOS, Windows
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-;;
-;; USAGE: Byte-compile this file, and add the following lines to your
-;; emacs initialization file (.emacs/_emacs):
-;;
-;; (setq auto-mode-alist
-;; (append
-;; (list (cons "\\.[bB][aA][tT]$" 'bat-mode))
-;; ;; For DOS init files
-;; (list (cons "CONFIG\\." 'bat-mode))
-;; (list (cons "AUTOEXEC\\." 'bat-mode))
-;; auto-mode-alist))
-;;
-;; (autoload 'bat-mode "batmode"
-;; "DOS and WIndows BAT files" t)
-
-;; TODO:
-;;
-;; Support "compiles" ?
-;; Imenu? Don't have real functions.....
-
-;;; Change log:
-;; $Log: batmode.el,v $
-;; Revision 1.3 1996/08/22 02:31:47 peter
-;; Added Usage message, credit to folks from NTEmacs mailing list,
-;; Syntax table, New font-lock keywords
-;;
-;; Revision 1.2 1996/08/18 16:27:13 peter
-;; Added preliminary global-font-lock support
-;;
-;; Revision 1.1 1996/08/18 16:14:18 peter
-;; Initial revision
-;;
-
-;; Credit for suggestions, patches and bug-fixes:
-;; Robert Brodersen <rbrodersen@siebel.com>
-;; ACorreir@pervasive-sw.com (Alfred Correira)
-
-;;; Code:
-
-(defvar bat-mode-map nil "Local keymap for bat-mode buffers.")
-
-;; Make this lowercase if you like
-(defvar bat-mode-comment-start "REM "
- "Comment string to use in BAT mode")
-
-(defvar bat-mode-syntax-table nil
- "Syntax table in use in Bat-mode buffers.")
-
-(if bat-mode-map
- nil
- (setq bat-mode-map (copy-keymap global-map))
-)
-
-;; Make underscores count as words
-(if bat-mode-syntax-table
- ()
- (setq bat-mode-syntax-table (make-syntax-table))
- (modify-syntax-entry ?_ "w" bat-mode-syntax-table)
-)
-
-(defun bat-mode ()
- "Mode for DOS and Windows BAT files"
- (interactive)
- (kill-all-local-variables)
- (use-local-map bat-mode-map)
- (set-syntax-table bat-mode-syntax-table)
-
- (make-local-variable 'parse-sexp-ignore-comments)
- (make-local-variable 'comment-start)
- (make-local-variable 'comment-start-skip)
- (make-local-variable 'comment-end)
- (make-local-variable 'executable-command)
- (make-local-variable 'font-lock-defaults)
-
- (setq major-mode 'bat-mode
- mode-name "bat"
-
- comment-end ""
-
- comment-start bat-mode-comment-start
- comment-start-skip "[Rr][Ee][Mm] *"
-
- parse-sexp-ignore-comments t
-
- )
-
- ;; Global font-lock support
- ;; (setq font-lock-defaults (list 'bat-font-lock-keywords nil t nil nil))
- (setq font-lock-defaults (list 'bat-font-lock-keywords nil))
-
- (run-hooks 'bat-mode-hook))
-
-(defvar bat-font-lock-keywords
- (list
- ;; Make this one first in the list, otherwise comments will
- ;; be over-written by other variables
- (list "^[@ \t]*\\([rR][eE][mM].*\\)" 1 'font-lock-comment-face t)
- (list "^[ \t]*\\(::-.*\\)" 1 'font-lock-comment-face t)
- (list
- (concat "\\(\\<"
- (mapconcat 'identity
- '(
- "call"
- "echo"
- "exist"
- "errorlevel"
- "for"
- "goto"
- "if"
- "not"
- "path"
- "pause"
- "prompt"
- "set"
- "start"
- )
- "\\>\\|\\<")
- "\\>\\)") 1 'font-lock-keyword-face)
- (list "^[ \t]*\\(:\\sw+\\)" 1 'font-lock-function-name-face t)
- (list "\\(%\\sw+%\\)" 1 'font-lock-reference-face)
- (list "\\(%[0-9]\\)" 1 'font-lock-reference-face)
- (list "\\(/[^/ \t\n]+\\)" 1 'font-lock-type-face)
- (list "\\<\\(goto\\)\\>[ \t]*\\(\\sw+\\)?"
- '(1 font-lock-keyword-face)
- '(2 font-lock-function-name-face nil t))
-
- )
- "Keywords to hilight in BAT mode")
-
-;;; don't do it in Win-Emacs
-(if (boundp 'font-lock-defaults-alist)
- (add-to-list
- 'font-lock-defaults-alist
- (cons 'bat-mode
- (list 'bat-font-lock-keywords nil t nil nil))))
-
-(provide 'bat-mode)
-
-;;; batmode.el ends here
diff --git a/lisp/=bytecpat.el b/lisp/=bytecpat.el
deleted file mode 100644
index 1698b2659ba..00000000000
--- a/lisp/=bytecpat.el
+++ /dev/null
@@ -1,15 +0,0 @@
-;;; bytecpat.el --- do recompilation for Emacs patch files.
-;;; This function is used by the patch files to update Emacs releases.
-
-(defun batch-byte-recompile-emacs ()
- "Recompile the Emacs `lisp' directory.
-This is used after installing the patches for a new version."
- (let ((load-path (list (expand-file-name "lisp"))))
- (byte-recompile-directory "lisp")))
-
-(defun batch-byte-compile-emacs ()
- "Compile new files installed in the Emacs `lisp' directory.
-This is used after installing the patches for a new version.
-It uses the command line arguments to specify the files to compile."
- (let ((load-path (list (expand-file-name "lisp"))))
- (batch-byte-compile)))
diff --git a/lisp/=cl.el b/lisp/=cl.el
deleted file mode 100644
index 1a6a385e3ee..00000000000
--- a/lisp/=cl.el
+++ /dev/null
@@ -1,3162 +0,0 @@
-;;; cl.el --- Common-Lisp extensions for GNU Emacs Lisp.
-
-;; Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
-
-;; Author: Cesar Quiroz <quiroz@cs.rochester.edu>
-;; Keywords: extensions
-
-(defvar cl-version "3.0 07-February-1993")
-
-;; 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.
-
-;;; Commentary:
-
-;;; Notes from Rob Austein on his mods
-;; yaya:/usr/u/sra/cl/cl.el, 5-May-1991 16:01:34, sra
-;;
-;; Slightly hacked copy of cl.el 2.0 beta 27.
-;;
-;; Various minor performance improvements:
-;; a) Don't use MAPCAR when we're going to discard its results.
-;; b) Make various macros a little more clever about optimizing
-;; generated code in common cases.
-;; c) Fix DEFSETF to expand to the right code at compile-time.
-;; d) Make various macros cleverer about generating reasonable
-;; code when compiled, particularly forms like DEFSTRUCT which
-;; are usually used at top-level and thus are only compiled if
-;; you use Hallvard Furuseth's hacked bytecomp.el.
-;;
-;; New features: GETF, REMF, and REMPROP.
-;;
-;; Notes:
-;; 1) I'm sceptical about the FBOUNDP checks in SETF. Why should
-;; the SETF expansion fail because the SETF method isn't defined
-;; at compile time? Lisp is going to check for a binding at run-time
-;; anyway, so maybe we should just assume the user's right here.
-
-;;;; These are extensions to Emacs Lisp that provide some form of
-;;;; Common Lisp compatibility, beyond what is already built-in
-;;;; in Emacs Lisp.
-;;;;
-;;;; When developing them, I had the code spread among several files.
-;;;; This file 'cl.el' is a concatenation of those original files,
-;;;; minus some declarations that became redundant. The marks between
-;;;; the original files can be found easily, as they are lines that
-;;;; begin with four semicolons (as this does). The names of the
-;;;; original parts follow the four semicolons in uppercase, those
-;;;; names are GLOBAL, SYMBOLS, LISTS, SEQUENCES, CONDITIONALS,
-;;;; ITERATIONS, MULTIPLE VALUES, ARITH, SETF and DEFSTRUCT. If you
-;;;; add functions to this file, you might want to put them in a place
-;;;; that is compatible with the division above (or invent your own
-;;;; categories).
-;;;;
-;;;; To compile this file, make sure you load it first. This is
-;;;; because many things are implemented as macros and now that all
-;;;; the files are concatenated together one cannot ensure that
-;;;; declaration always precedes use.
-;;;;
-;;;; Bug reports, suggestions and comments,
-;;;; to quiroz@cs.rochester.edu
-
-
-;;;; GLOBAL
-;;;; This file provides utilities and declarations that are global
-;;;; to Common Lisp and so might be used by more than one of the
-;;;; other libraries. Especially, I intend to keep here some
-;;;; utilities that help parsing/destructuring some difficult calls.
-;;;;
-;;;;
-;;;; 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.
-
-;;; Code:
-
-;;; This version is due to Hallvard Furuseth (hallvard@ifi.uio.no, 6 Jul 91)
-(defmacro psetq (&rest args)
- "(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'."
- ;; check there is a reasonable number of forms
- (if (/= (% (length args) 2) 0)
- (error "Odd number of arguments to `psetq'"))
- (setq args (copy-sequence args)) ;for safety below
- (prog1 (cons 'setq args)
- (while (progn (if (not (symbolp (car args)))
- (error "`psetq' expected a symbol, found '%s'."
- (prin1-to-string (car args))))
- (cdr (cdr args)))
- (setcdr args (list (list 'prog1 (nth 1 args)
- (cons 'setq
- (setq args (cdr (cdr args))))))))))
-
-;;; utilities
-;;;
-;;; pair-with-newsyms takes a list and returns a list of lists of the
-;;; form (newsym form), such that a let* can then bind the evaluation
-;;; of the forms to the newsyms. The idea is to guarantee correct
-;;; order of evaluation of the subforms of a setf. It also returns a
-;;; list of the newsyms generated, in the corresponding order.
-
-(defun pair-with-newsyms (oldforms)
- "PAIR-WITH-NEWSYMS OLDFORMS
-The top-level components of the list oldforms are paired with fresh
-symbols, the pairings list and the newsyms list are returned."
- (do ((ptr oldforms (cdr ptr))
- (bindings '())
- (newsyms '()))
- ((endp ptr) (values (nreverse bindings) (nreverse newsyms)))
- (let ((newsym (gentemp)))
- (setq bindings (cons (list newsym (car ptr)) bindings))
- (setq newsyms (cons newsym newsyms)))))
-
-(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.
-The construction stops when the shorter list is exhausted."
- (do* ((p0 evens (cdr p0))
- (p1 odds (cdr p1))
- (even (car p0) (car p0))
- (odd (car p1) (car p1))
- (result '()))
- ((or (endp p0) (endp p1))
- (nreverse result))
- (setq result
- (cons odd (cons even result)))))
-
-(defun unzip-list (list)
- "Extract even and odd elements of LIST into two separate lists.
-The argument LIST is separated in two strands, the even and the odd
-numbered elements. Numbering starts with 0, so the first element
-belongs in EVENS. No check is made that there is an even number of
-elements to start with."
- (do* ((ptr list (cddr ptr))
- (this (car ptr) (car ptr))
- (next (cadr ptr) (cadr ptr))
- (evens '())
- (odds '()))
- ((endp ptr)
- (values (nreverse evens) (nreverse odds)))
- (setq evens (cons this evens))
- (setq odds (cons next odds))))
-
-(defun reassemble-argslists (argslists)
- "(reassemble-argslists ARGSLISTS) => a list of lists
-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
-shortest list is exhausted."
- (let* ((minlen (apply 'min (mapcar 'length argslists)))
- (result '()))
- (dotimes (i minlen (nreverse result))
- ;; capture all the elements at index i
- (setq result
- (cons (mapcar (function (lambda (sublist) (elt sublist i)))
- argslists)
- result)))))
-
-
-;;; Checking that a list of symbols contains no duplicates is a common
-;;; task when checking the legality of some macros. The check for 'eq
-;;; pairs can be too expensive, as it is quadratic on the length of
-;;; the list. I use a 4-pass, linear, counting approach. It surely
-;;; loses on small lists (less than 5 elements?), but should win for
-;;; larger lists. The fourth pass could be eliminated.
-;;; 10 dec 1986. Emacs Lisp has no REMPROP, so I just eliminated the
-;;; 4th pass.
-;;;
-;;; [22 April 1991, sra] REMPROP now in library, so restored 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."
- (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"))
- ;; pass 1: mark
- (dolist (x list)
- (put x propname 0))
- ;; pass 2: count
- (dolist (x list)
- (put x propname (1+ (get x propname))))
- ;; pass 3: collect
- (dolist (x list)
- (if (> (get x propname) 1)
- (setq duplicates (cons x duplicates))))
- ;; pass 4: unmark.
- (dolist (x list)
- (remprop x propname))
- ;; return result
- duplicates))
-
-;;;; end of cl-global.el
-
-;;;; SYMBOLS
-;;;; This file provides the gentemp function, which generates fresh
-;;;; symbols, plus some other minor Common Lisp symbol tools.
-;;;;
-;;;; Cesar Quiroz @ UofR DofCSc - Dec. 1986
-;;;; (quiroz@cs.rochester.edu)
-
-;;; Keywords. There are no packages in Emacs Lisp, so this is only a
-;;; kludge around to let things be "as if" a keyword package was around.
-
-(defmacro defkeyword (x &optional docstring)
- "Make symbol X a keyword (symbol whose value is itself).
-Optional second argument 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)))))
-
-(defun keywordp (sym)
- "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))
-
-(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)))))
-
-;;; Temporary symbols.
-;;;
-
-(defvar *gentemp-index* 0
- "Integer used by gentemp to produce new names.")
-
-(defvar *gentemp-prefix* "T$$_"
- "Names generated by gentemp begin with this string by default.")
-
-(defun gentemp (&optional prefix oblist)
- "Generate a fresh interned symbol.
-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)
- (setq oblist obarray)) ;default for the intern functions
- (let ((newsymbol nil)
- (newname))
- (while (not newsymbol)
- (setq newname (concat prefix *gentemp-index*))
- (setq *gentemp-index* (+ *gentemp-index* 1))
- (if (not (intern-soft newname oblist))
- (setq newsymbol (intern newname oblist))))
- newsymbol))
-
-(defvar *gensym-index* 0
- "Integer used by gensym to produce new names.")
-
-(defvar *gensym-prefix* "G$$_"
- "Names generated by gensym begin with this string by default.")
-
-(defun gensym (&optional prefix)
- "Generate a fresh uninterned symbol.
-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)
- (newname ""))
- (while (not newsymbol)
- (setq newname (concat prefix *gensym-index*))
- (setq *gensym-index* (+ *gensym-index* 1))
- (if (not (intern-soft newname))
- (setq newsymbol (make-symbol newname))))
- newsymbol))
-
-;;;; end of cl-symbols.el
-
-;;;; CONDITIONALS
-;;;; This file provides some of the conditional constructs of
-;;;; Common Lisp. Total compatibility is again impossible, as the
-;;;; 'if' form is different in both languages, so only a good
-;;;; approximation is desired.
-;;;;
-;;;; Cesar Quiroz @ UofR DofCSc - Dec. 1986
-;;;; (quiroz@cs.rochester.edu)
-
-;;; indentation info
-(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.
-
-(defmacro when (condition &rest body)
- "(when CONDITION . BODY) => evaluate BODY if CONDITION is true."
- (list* 'if (list 'not condition) '() body))
-
-(defmacro unless (condition &rest body)
- "(unless CONDITION . BODY) => evaluate BODY if CONDITION is false."
- (list* 'if condition '() body))
-
-;;; CASE and ECASE
-;;; CASE selects among several clauses, based on the value (evaluated)
-;;; of a expression and a list of (unevaluated) key values. ECASE is
-;;; the same, but signals an error if no clause is activated.
-
-(defmacro case (expr &rest cases)
- "(case EXPR . CASES) => evals EXPR, chooses from CASES on that value.
-EXPR -> any form
-CASES -> list of clauses, non empty
-CLAUSE -> HEAD . BODY
-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)
-BODY -> list of forms, implicit PROGN is built around it.
-EXPR is evaluated only once."
- (let* ((newsym (gentemp))
- (clauses (case-clausify cases newsym)))
- ;; convert case into a cond inside a let
- (list 'let
- (list (list newsym expr))
- (list* 'cond (nreverse clauses)))))
-
-(defmacro ecase (expr &rest cases)
- "(ecase EXPR . CASES) => like `case', but error if no case fits.
-`t'-clauses are not allowed."
- (let* ((newsym (gentemp))
- (clauses (case-clausify cases newsym)))
- ;; 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'"))
- ;; insert error-catching clause
- (setq clauses
- (cons
- (list 't (list 'error
- "ecase on %s = %s failed to take any branch"
- (list 'quote expr)
- (list 'prin1-to-string newsym)))
- clauses))
- ;; generate code as usual
- (list 'let
- (list (list newsym expr))
- (list* 'cond (nreverse clauses)))))
-
-
-(defun case-clausify (cases newsym)
- "CASE-CLAUSIFY CASES NEWSYM => clauses for a 'cond'
-Converts the CASES of a [e]case macro into cond clauses to be
-evaluated inside a let that binds NEWSYM. Returns the clauses in
-reverse order."
- (do* ((currentpos cases (cdr currentpos))
- (nextpos (cdr cases) (cdr nextpos))
- (curclause (car cases) (car currentpos))
- (result '()))
- ((endp currentpos) result)
- (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)))))))
-
-;;;; end of cl-conditionals.el
-
-;;;; ITERATIONS
-;;;; This file provides simple iterative macros (a la Common Lisp)
-;;;; constructed on the basis of let, let* and while, which are the
-;;;; primitive binding/iteration constructs of Emacs Lisp
-;;;;
-;;;; The Common Lisp iterations use to have a block named nil
-;;;; wrapped around them, and allow declarations at the beginning
-;;;; of their bodies and you can return a value using (return ...).
-;;;; Nothing of the sort exists in Emacs Lisp, so I haven't tried
-;;;; to imitate these behaviors.
-;;;;
-;;;; Other than the above, the semantics of Common Lisp are
-;;;; correctly reproduced to the extent this was reasonable.
-;;;;
-;;;; Cesar Quiroz @ UofR DofCSc - Dec. 1986
-;;;; (quiroz@cs.rochester.edu)
-
-;;; some lisp-indentation information
-(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 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."
- ;; check the syntax of the macro
- (and (check-do-stepforms stepforms)
- (check-do-endforms endforms))
- ;; construct emacs-lisp equivalent
- (let ((initlist (extract-do-inits stepforms))
- (steplist (extract-do-steps stepforms))
- (endcond (car endforms))
- (endbody (cdr endforms)))
- (cons 'let (cons initlist
- (cons (cons 'while (cons (list 'not endcond)
- (append body steplist)))
- (append endbody))))))
-
-
-(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 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 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))
- ;; construct emacs-lisp equivalent
- (let ((initlist (extract-do-inits stepforms))
- (steplist (extract-do*-steps stepforms))
- (endcond (car endforms))
- (endbody (cdr endforms)))
- (cons 'let* (cons initlist
- (cons (cons 'while (cons (list 'not endcond)
- (append body steplist)))
- (append endbody))))))
-
-
-;;; DO and DO* share the syntax checking functions that follow.
-
-(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))
- (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)))
-
-(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))))
-
-(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."
- (mapcar
- (function
- (lambda (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."
- (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."
- (list (cons 'setq (select-stepping-forms forms))))
-
-(defun select-stepping-forms (forms)
- "Separate only the forms that cause stepping."
- (let ((result '()) ;ends up being (... var form ...)
- (ptr forms) ;to traverse the forms
- entry ;to explore each form in turn
- )
- (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))))
- (setq ptr (cdr ptr))) ;step in the list of forms
- (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
-RESULTFORM is evaluated."
- ;; check sanity
- (cond
- ((nlistp stepform)
- (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'"
- (prin1-to-string (car stepform))))
- ((> (length stepform) 3)
- (error "too many components in stepform `%s'"
- (prin1-to-string stepform))))
- ;; generate code
- (let* ((var (car stepform))
- (listform (cadr stepform))
- (resultform (caddr stepform))
- (listsym (gentemp)))
- (nconc
- (list 'let (list var (list listsym listform))
- (nconc
- (list 'while listsym
- (list 'setq
- var (list 'car listsym)
- listsym (list 'cdr listsym)))
- body))
- (and resultform
- (cons (list 'setq var nil)
- (list resultform))))))
-
-(defmacro dotimes (stepform &rest body)
- "(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
-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
-defaults to nil."
- ;; check sanity
- (cond
- ((nlistp stepform)
- (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'"
- (prin1-to-string (car stepform))))
- ((> (length stepform) 3)
- (error "too many components in stepform `%s'"
- (prin1-to-string stepform))))
- ;; generate code
- (let* ((var (car stepform))
- (countform (cadr stepform))
- (resultform (caddr stepform))
- (testsym (if (consp countform) (gentemp) countform)))
- (nconc
- (list
- 'let (cons (list var -1)
- (and (not (eq countform testsym))
- (list (list testsym countform))))
- (nconc
- (list 'while (list '< (list 'setq var (list '1+ var)) testsym))
- body))
- (and resultform (list resultform)))))
-
-(defmacro do-symbols (stepform &rest body)
- "(do_symbols (VAR [OBARRAY [RESULTFORM]]) . BODY)
-The VAR is bound to each of the symbols in OBARRAY (def. obarray) and
-the BODY is repeatedly performed for each of those bindings. At the
-end, RESULTFORM (def. nil) is evaluated and its value returned.
-During this last evaluation, the VAR is still bound and its value is nil.
-See also the function `mapatoms'."
- ;; check sanity
- (cond
- ((nlistp stepform)
- (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'"
- (prin1-to-string (car stepform))))
- ((> (length stepform) 3)
- (error "too many components in stepform `%s'"
- (prin1-to-string stepform))))
- ;; generate code
- (let* ((var (car stepform))
- (oblist (cadr stepform))
- (resultform (caddr stepform)))
- (list 'progn
- (list 'mapatoms
- (list 'function
- (cons 'lambda (cons (list var) body)))
- oblist)
- (list 'let
- (list (list var nil))
- resultform))))
-
-
-(defmacro do-all-symbols (stepform &rest body)
- "(do-all-symbols (VAR [RESULTFORM]) . BODY)
-Is the same as (do-symbols (VAR obarray RESULTFORM) . BODY)."
- (list*
- 'do-symbols
- (list (car stepform) 'obarray (cadr stepform))
- body))
-
-(defmacro loop (&rest body)
- "(loop . BODY) repeats BODY indefinitely and does not return.
-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")
- ;; ok, it is a list, check for atomic components
- (mapcar
- (function (lambda (component)
- (if (nlistp component)
- (error "components of `loop' should be lists"))))
- body)
- ;; build the infinite loop
- (cons 'while (cons 't body))))
-
-;;;; end of cl-iterations.el
-
-;;;; LISTS
-;;;; This file provides some of the lists machinery of Common-Lisp
-;;;; in a way compatible with Emacs Lisp. Especially, see the the
-;;;; typical c[ad]*r functions.
-;;;;
-;;;; Cesar Quiroz @ UofR DofCSc - Dec. 1986
-;;;; (quiroz@cs.rochester.edu)
-
-;;; Synonyms for list functions
-(defsubst first (x)
- "Synonym for `car'"
- (car x))
-
-(defsubst second (x)
- "Return the second element of the list LIST."
- (nth 1 x))
-
-(defsubst third (x)
- "Return the third element of the list LIST."
- (nth 2 x))
-
-(defsubst fourth (x)
- "Return the fourth element of the list LIST."
- (nth 3 x))
-
-(defsubst fifth (x)
- "Return the fifth element of the list LIST."
- (nth 4 x))
-
-(defsubst sixth (x)
- "Return the sixth element of the list LIST."
- (nth 5 x))
-
-(defsubst seventh (x)
- "Return the seventh element of the list LIST."
- (nth 6 x))
-
-(defsubst eighth (x)
- "Return the eighth element of the list LIST."
- (nth 7 x))
-
-(defsubst ninth (x)
- "Return the ninth element of the list LIST."
- (nth 8 x))
-
-(defsubst tenth (x)
- "Return the tenth element of the list LIST."
- (nth 9 x))
-
-(defsubst rest (x)
- "Synonym for `cdr'"
- (cdr x))
-
-(defsubst endp (x)
- "t if X is nil, nil if X is a cons; error otherwise."
- (if (listp x)
- (null x)
- (error "endp received a non-cons, non-null argument `%s'"
- (prin1-to-string x))))
-
-(defun last (x)
- "Returns the last link in the list LIST."
- (if (nlistp x)
- (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)))
-
-(defun list-length (x) ;taken from CLtL sect. 15.2
- "Returns the length of a non-circular list, or `nil' for a circular one."
- (do ((n 0) ;counter
- (fast x (cddr fast)) ;fast pointer, leaps by 2
- (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
-
-(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."
- (if (null n) (setq n 1))
- (nreverse (nthcdr n (reverse list)))) ;optim. due to macrakis@osf.org
-
-;;; This version due to Aaron Larson (alarson@src.honeywell.com, 26 Jul 91)
-(defun list* (arg &rest others)
- "Return a new list containing the first arguments consed onto the last arg.
-Thus, (list* 1 2 3 '(a b)) returns (1 2 3 a b)."
- (if (null others)
- arg
- (let* ((others (cons arg (copy-sequence others)))
- (a others))
- (while (cdr (cdr a))
- (setq a (cdr a)))
- (setcdr a (car (cdr a)))
- others)))
-
-(defun adjoin (item list)
- "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)))
-
-(defun ldiff (list sublist)
- "Return a new list like LIST but sans SUBLIST.
-SUBLIST must be one of the links in LIST; otherwise the value is LIST itself."
- (do ((result '())
- (curcons list (cdr curcons)))
- ((or (endp curcons) (eq curcons sublist))
- (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.
-
-(defsubst caar (X)
- "Return the car of the car of X."
- (car (car X)))
-
-(defsubst cadr (X)
- "Return the car of the cdr of X."
- (car (cdr X)))
-
-(defsubst cdar (X)
- "Return the cdr of the car of X."
- (cdr (car X)))
-
-(defsubst cddr (X)
- "Return the cdr of the cdr of X."
- (cdr (cdr X)))
-
-(defsubst caaar (X)
- "Return the car of the car of the car of X."
- (car (car (car X))))
-
-(defsubst caadr (X)
- "Return the car of the car of the cdr of X."
- (car (car (cdr X))))
-
-(defsubst cadar (X)
- "Return the car of the cdr of the car of X."
- (car (cdr (car X))))
-
-(defsubst cdaar (X)
- "Return the cdr of the car of the car of X."
- (cdr (car (car X))))
-
-(defsubst caddr (X)
- "Return the car of the cdr of the cdr of X."
- (car (cdr (cdr X))))
-
-(defsubst cdadr (X)
- "Return the cdr of the car of the cdr of X."
- (cdr (car (cdr X))))
-
-(defsubst cddar (X)
- "Return the cdr of the cdr of the car of X."
- (cdr (cdr (car X))))
-
-(defsubst cdddr (X)
- "Return the cdr of the cdr of the cdr of X."
- (cdr (cdr (cdr X))))
-
-(defsubst caaaar (X)
- "Return the car of the car of the car of the car of X."
- (car (car (car (car X)))))
-
-(defsubst caaadr (X)
- "Return the car of the car of the car of the cdr of X."
- (car (car (car (cdr X)))))
-
-(defsubst caadar (X)
- "Return the car of the car of the cdr of the car of X."
- (car (car (cdr (car X)))))
-
-(defsubst cadaar (X)
- "Return the car of the cdr of the car of the car of X."
- (car (cdr (car (car X)))))
-
-(defsubst cdaaar (X)
- "Return the cdr of the car of the car of the car of X."
- (cdr (car (car (car X)))))
-
-(defsubst caaddr (X)
- "Return the car of the car of the cdr of the cdr of X."
- (car (car (cdr (cdr X)))))
-
-(defsubst cadadr (X)
- "Return the car of the cdr of the car of the cdr of X."
- (car (cdr (car (cdr X)))))
-
-(defsubst cdaadr (X)
- "Return the cdr of the car of the car of the cdr of X."
- (cdr (car (car (cdr X)))))
-
-(defsubst caddar (X)
- "Return the car of the cdr of the cdr of the car of X."
- (car (cdr (cdr (car X)))))
-
-(defsubst cdadar (X)
- "Return the cdr of the car of the cdr of the car of X."
- (cdr (car (cdr (car X)))))
-
-(defsubst cddaar (X)
- "Return the cdr of the cdr of the car of the car of X."
- (cdr (cdr (car (car X)))))
-
-(defsubst cadddr (X)
- "Return the car of the cdr of the cdr of the cdr of X."
- (car (cdr (cdr (cdr X)))))
-
-(defsubst cddadr (X)
- "Return the cdr of the cdr of the car of the cdr of X."
- (cdr (cdr (car (cdr X)))))
-
-(defsubst cdaddr (X)
- "Return the cdr of the car of the cdr of the cdr of X."
- (cdr (car (cdr (cdr X)))))
-
-(defsubst cdddar (X)
- "Return the cdr of the cdr of the cdr of the car of X."
- (cdr (cdr (cdr (car X)))))
-
-(defsubst cddddr (X)
- "Return the cdr of the cdr of the cdr of the cdr of X."
- (cdr (cdr (cdr (cdr X)))))
-
-;;; some inverses of the accessors are needed for setf purposes
-
-(defsubst setnth (n list newval)
- "Set (nth N LIST) to NEWVAL. Returns NEWVAL."
- (rplaca (nthcdr n list) newval))
-
-(defun setnthcdr (n list newval)
- "(setnthcdr N LIST NEWVAL) => NEWVAL
-As a side effect, sets the Nth cdr of LIST to NEWVAL."
- (when (< n 0)
- (error "N must be 0 or greater, not %d" n))
- (while (> n 0)
- (setq list (cdr list)
- n (- n 1)))
- ;; here only if (zerop n)
- (rplaca list (car newval))
- (rplacd list (cdr newval))
- newval)
-
-;;; A-lists machinery
-
-(defsubst acons (key item alist)
- "Return a new alist with KEY paired with ITEM; otherwise like ALIST.
-Does not copy ALIST."
- (cons (cons key item) alist))
-
-(defun pairlis (keys data &optional alist)
- "Return a new alist with each elt of KEYS paired with an elt of DATA;
-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"))
- (do* ;;collect keys and data in front of alist
- ((kptr keys (cdr kptr)) ;traverses the keys
- (dptr data (cdr dptr)) ;traverses the data
- (key (car kptr) (car kptr)) ;current key
- (item (car dptr) (car dptr)) ;current data item
- (result alist))
- ((endp kptr) result)
- (setq result (acons key item result))))
-
-;;;; end of cl-lists.el
-
-;;;; SEQUENCES
-;;;; Emacs Lisp provides many of the 'sequences' functionality of
-;;;; Common Lisp. This file provides a few things that were left out.
-;;;;
-
-
-(defkeyword :test "Used to designate positive (selection) tests.")
-(defkeyword :test-not "Used to designate negative (rejection) tests.")
-(defkeyword :key "Used to designate component extractions.")
-(defkeyword :predicate "Used to define matching of sequence components.")
-(defkeyword :start "Inclusive low index in sequence")
-(defkeyword :end "Exclusive high index in sequence")
-(defkeyword :start1 "Inclusive low index in first of two sequences.")
-(defkeyword :start2 "Inclusive low index in second of two sequences.")
-(defkeyword :end1 "Exclusive high index in first of two sequences.")
-(defkeyword :end2 "Exclusive high index in second of two sequences.")
-(defkeyword :count "Number of elements to affect.")
-(defkeyword :from-end "T when counting backwards.")
-(defkeyword :initial-value "For the syntax of #'reduce")
-
-(defun some (pred seq &rest moreseqs)
- "Test PREDICATE on each element of SEQUENCE; is it ever non-nil?
-Extra args are additional sequences; PREDICATE gets one arg from each
-sequence and we advance down all the sequences together in lock-step.
-A sequence means either a list or a vector."
- (let ((args (reassemble-argslists (list* seq moreseqs))))
- (do* ((ready nil) ;flag: return when t
- (result nil) ;resulting value
- (applyval nil) ;result of applying pred once
- (remaining args
- (cdr remaining)) ;remaining argument sets
- (current (car remaining) ;current argument set
- (car remaining)))
- ((or ready (endp remaining)) result)
- (setq applyval (apply pred current))
- (when applyval
- (setq ready t)
- (setq result applyval)))))
-
-(defun every (pred seq &rest moreseqs)
- "Test PREDICATE on each element of SEQUENCE; is it always non-nil?
-Extra args are additional sequences; PREDICATE gets one arg from each
-sequence and we advance down all the sequences together in lock-step.
-A sequence means either a list or a vector."
- (let ((args (reassemble-argslists (list* seq moreseqs))))
- (do* ((ready nil) ;flag: return when t
- (result t) ;resulting value
- (applyval nil) ;result of applying pred once
- (remaining args
- (cdr remaining)) ;remaining argument sets
- (current (car remaining) ;current argument set
- (car remaining)))
- ((or ready (endp remaining)) result)
- (setq applyval (apply pred current))
- (unless applyval
- (setq ready t)
- (setq result nil)))))
-
-(defun notany (pred seq &rest moreseqs)
- "Test PREDICATE on each element of SEQUENCE; is it always nil?
-Extra args are additional sequences; PREDICATE gets one arg from each
-sequence and we advance down all the sequences together in lock-step.
-A sequence means either a list or a vector."
- (let ((args (reassemble-argslists (list* seq moreseqs))))
- (do* ((ready nil) ;flag: return when t
- (result t) ;resulting value
- (applyval nil) ;result of applying pred once
- (remaining args
- (cdr remaining)) ;remaining argument sets
- (current (car remaining) ;current argument set
- (car remaining)))
- ((or ready (endp remaining)) result)
- (setq applyval (apply pred current))
- (when applyval
- (setq ready t)
- (setq result nil)))))
-
-(defun notevery (pred seq &rest moreseqs)
- "Test PREDICATE on each element of SEQUENCE; is it sometimes nil?
-Extra args are additional sequences; PREDICATE gets one arg from each
-sequence and we advance down all the sequences together in lock-step.
-A sequence means either a list or a vector."
- (let ((args (reassemble-argslists (list* seq moreseqs))))
- (do* ((ready nil) ;flag: return when t
- (result nil) ;resulting value
- (applyval nil) ;result of applying pred once
- (remaining args
- (cdr remaining)) ;remaining argument sets
- (current (car remaining) ;current argument set
- (car remaining)))
- ((or ready (endp remaining)) result)
- (setq applyval (apply pred current))
- (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
-
-(defun setelt (seq n newval)
- "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)))))))
-
-;;; Testing with keyword arguments.
-;;;
-;;; Many of the sequence functions use keywords to denote some stylized
-;;; form of selecting entries in a sequence. The involved arguments
-;;; are collected with a &rest marker (as Emacs Lisp doesn't have a &key
-;;; marker), then they are passed to build-klist, who
-;;; 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
-Extract value associated with KEY in KLIST (return DEFAULT if nil)."
- (let ((retrieved (cdr (assq 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 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
-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))))))
-
-(defun elt-satisfies-if-p (item klist)
- "(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)))
- (funcall predicate (funcall keyfn item))))
-
-(defun elt-satisfies-if-not-p (item klist)
- "(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)))
- (not (funcall predicate (funcall keyfn item)))))
-
-(defun elts-match-under-klist-p (e1 e2 klist)
- "(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-hook 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 successive 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)))))
-
-;;;; 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 cl-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 allegedly for speed, BLAH
- (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.
-;;;;
-;;;; Cesar Quiroz @ UofR DofCSc - Dec. 1986
-;;;; (quiroz@cs.rochester.edu)
-
-;;; Lisp indentation information
-(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
- "Most recently returned multiple-values")
-(defvar *mvalues-count* nil
- "Count of multiple-values returned, or nil if the mechanism was not used")
-
-;;; values is the standard multiple-value-return form. Must be the
-;;; last thing evaluated inside a function. If the caller is not
-;;; expecting multiple values, only the first one is passed. (values)
-;;; is the same as no-values returned (unaware callers see nil). The
-;;; alternative (values-list <list>) is just a convenient shorthand
-;;; and complements multiple-value-list.
-
-(defun values (&rest val-forms)
- "Produce multiple values (zero or more). Each arg is one value.
-See also `multiple-value-bind', which is one way to examine the
-multiple values produced by a form. If the containing form or caller
-does not check specially to see multiple values, it will see only
-the first value."
- (setq *mvalues-values* val-forms)
- (setq *mvalues-count* (length *mvalues-values*))
- (car *mvalues-values*))
-
-(defun values-list (&optional val-forms)
- "Produce multiple values (zero or more). Each element of LIST is one value.
-This is equivalent to (apply 'values LIST)."
- (cond ((nlistp val-forms)
- (error "Argument to values-list must be a list, not `%s'"
- (prin1-to-string val-forms))))
- (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.
-
-(defmacro multiple-value-list (form)
- "Execute FORM and return a list of all the (multiple) values FORM produces.
-See `values' and `multiple-value-bind'."
- (list 'progn
- (list 'setq '*mvalues-count* nil)
- (list 'let (list (list 'it '(gensym)))
- (list 'set 'it form)
- (list 'if '*mvalues-count*
- (list 'copy-sequence '*mvalues-values*)
- (list 'progn
- (list 'setq '*mvalues-count* 1)
- (list 'setq '*mvalues-values*
- (list 'list (list 'symbol-value 'it)))
- (list 'copy-sequence '*mvalues-values*))))))
-
-(defmacro multiple-value-call (function &rest args)
- "Call FUNCTION on all the values produced by the remaining arguments.
-(multiple-value-call '+ (values 1 2) (values 3 4)) is 10."
- (let* ((result (gentemp))
- (arg (gentemp)))
- (list 'apply (list 'function (eval function))
- (list 'let* (list (list result '()))
- (list 'dolist (list arg (list 'quote args) result)
- (list 'setq result
- (list 'append
- result
- (list 'multiple-value-list
- (list 'eval arg)))))))))
-
-(defmacro multiple-value-bind (vars form &rest body)
- "Bind VARS to the (multiple) values produced by FORM, then do BODY.
-VARS is a list of variables; each is bound to one of FORM's values.
-If FORM doesn't make enough values, the extra variables are bound to nil.
-(Ordinary forms produce only one value; to produce more, use `values'.)
-Extra values are ignored.
-BODY (zero or more forms) is executed with the variables bound,
-then the bindings are unwound."
- (let* ((vals (gentemp)) ;name for intermediate values
- (clauses (mv-bind-clausify ;convert into clauses usable
- vars vals))) ; in a let form
- (list* 'let*
- (cons (list vals (list 'multiple-value-list form))
- clauses)
- body)))
-
-(defmacro multiple-value-setq (vars form)
- "Set VARS to the (multiple) values produced by FORM.
-VARS is a list of variables; each is set to one of FORM's values.
-If FORM doesn't make enough values, the extra variables are set to nil.
-(Ordinary forms produce only one value; to produce more, use `values'.)
-Extra values are ignored."
- (let* ((vals (gentemp)) ;name for intermediate values
- (clauses (mv-bind-clausify ;convert into clauses usable
- vars vals))) ; in a setq (after append).
- (list 'let*
- (list (list vals (list 'multiple-value-list form)))
- (cons 'setq (apply (function append) clauses)))))
-
-(defmacro multiple-value-prog1 (form &rest body)
- "Evaluate FORM, then BODY, then produce the same values FORM produced.
-Thus, (multiple-value-prog1 (values 1 2) (foobar)) produces values 1 and 2.
-This is like `prog1' except that `prog1' would produce only one value,
-which would be the first of FORM's values."
- (let* ((heldvalues (gentemp)))
- (cons 'let*
- (cons (list (list heldvalues (list 'multiple-value-list form)))
- (append body (list (list 'values-list heldvalues)))))))
-
-;;; utility functions
-;;;
-;;; mv-bind-clausify makes the pairs needed to have the variables in
-;;; the variable list correspond with the values returned by the form.
-;;; vals is a fresh symbol that intervenes in all the bindings.
-
-(defun mv-bind-clausify (vars vals)
- "MV-BIND-CLAUSIFY VARS VALS => Auxiliary list
-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'"
- (prin1-to-string vars)))
- (let* ((nvars (length vars))
- (clauses '()))
- (dotimes (n nvars clauses)
- (setq clauses (cons (list (nth n vars)
- (list 'nth n vals)) clauses)))))
-
-;;;; end of cl-multiple-values.el
-
-;;;; ARITH
-;;;; This file provides integer arithmetic extensions. Although
-;;;; Emacs Lisp doesn't really support anything but integers, that
-;;;; has still to be made to look more or less standard.
-;;;;
-;;;;
-;;;; Cesar Quiroz @ UofR DofCSc - Dec. 1986
-;;;; (quiroz@cs.rochester.edu)
-
-
-(defsubst plusp (number)
- "True if NUMBER is strictly greater than zero."
- (> number 0))
-
-(defsubst minusp (number)
- "True if NUMBER is strictly less than zero."
- (< number 0))
-
-(defsubst oddp (number)
- "True if INTEGER is not divisible by 2."
- (/= (% number 2) 0))
-
-(defsubst evenp (number)
- "True if INTEGER is divisible by 2."
- (= (% number 2) 0))
-
-(defsubst abs (number)
- "Return the absolute value of NUMBER."
- (if (< number 0)
- (- number)
- number))
-
-(defsubst signum (number)
- "Return -1, 0 or 1 according to the sign of NUMBER."
- (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)) ;successive 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.
-The arguments must be integers and there must be at least one of them."
- (let ((howmany (length more))
- (a integer)
- (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))))))))
-
-(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)))))
-
-(defun cl-floor (number &optional divisor)
- "Divide DIVIDEND by DIVISOR, rounding toward minus infinity.
-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)
- (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)))))))))))
-
-(defun cl-ceiling (number &optional divisor)
- "Divide DIVIDEND by DIVISOR, rounding toward plus infinity.
-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)
- (cond ((zerop s)
- (values 0 0))
- ((plusp s)
- (values (+ q 1) (- r divisor)))
- (t
- (values (- q) (+ number (* q divisor)))))))))
-
-(defun cl-truncate (number &optional divisor)
- "Divide DIVIDEND by DIVISOR, rounding toward zero.
-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)
- (cond ((zerop s)
- (values 0 0))
- ((plusp s) ;same as floor
- (values q r))
- (t ;same as ceiling
- (values (- q) (+ number (* q divisor)))))))))
-
-(defun cl-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))))))
-
-;;; These two functions access the implementation-dependent representation of
-;;; the multiple value returns.
-
-(defun cl-mod (number divisor)
- "Return remainder of X by Y (rounding quotient toward minus infinity).
-That is, the remainder goes with the quotient produced by `cl-floor'.
-Emacs Lisp hint:
-If you know that both arguments are positive, use `%' instead for speed."
- (cl-floor number divisor)
- (cadr *mvalues-values*))
-
-(defun rem (number divisor)
- "Return remainder of X by Y (rounding quotient toward zero).
-That is, the remainder goes with the quotient produced by `cl-truncate'.
-Emacs Lisp hint:
-If you know that both arguments are positive, use `%' instead for speed."
- (cl-truncate number divisor)
- (cadr *mvalues-values*))
-
-;;; internal utilities
-;;;
-;;; safe-idiv performs an integer division with positive numbers only.
-;;; It is known that some machines/compilers implement weird remainder
-;;; 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|, S is the sign of A/B, R is the rest A - S*Q*B."
- ;; (unless (and (numberp a) (numberp b))
- ;; (error "arguments to `safe-idiv' must be numbers"))
- ;; (when (zerop b)
- ;; (error "cannot divide %d by zero" a))
- (let* ((q (/ (abs a) (abs b)))
- (s (* (signum a) (signum b)))
- (r (- a (* s q b))))
- (values q r s)))
-
-;;;; end of cl-arith.el
-
-;;;; SETF
-;;;; This file provides the setf macro and friends. The purpose has
-;;;; been modest, only the simplest defsetf forms are accepted.
-;;;; Use it and enjoy.
-;;;;
-;;;; Cesar Quiroz @ UofR DofCSc - Dec. 1986
-;;;; (quiroz@cs.rochester.edu)
-
-
-(defkeyword :setf-update-fn
- "Property, its value is the function setf must invoke to update a
-generalized variable whose access form is a function call of the
-symbol that has this property.")
-
-(defkeyword :setf-update-doc
- "Property of symbols that have a `defsetf' update function on them,
-installed by the `defsetf' from its optional third argument.")
-
-(defmacro setf (&rest pairs)
- "Generalized `setq' that can set things other than variable values.
-A use of `setf' looks like (setf {PLACE VALUE}...).
-The behavior of (setf PLACE VALUE) is to access the generalized variable
-at PLACE and store VALUE there. It returns VALUE. If there is more
-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)))
- ;; dispatch on the type of update function
- (cond ((and (consp updatefn) (eq (car updatefn) 'lambda))
- (cons 'funcall
- (cons (list 'function updatefn)
- (append (cdr place) (list value)))))
- ((and (symbolp updatefn)
- (fboundp updatefn)
- (let ((defn (symbol-function updatefn)))
- (or (subrp defn)
- (and (consp defn)
- (or (eq (car defn) 'lambda)
- (eq (car defn) 'macro))))))
- (cons updatefn (append (cdr place) (list value))))
- (t
- (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.
-A use of `defsetf' looks like (defsetf ACCESSFN UPDATEFN [DOCSTRING]).
-ACCESSFN is a symbol. UPDATEFN is a function or macro which takes
-one more argument than ACCESSFN does. DEFSETF defines the translation
-of (SETF (ACCESFN . ARGS) NEWVAL) to be a form like (UPDATEFN ARGS... NEWVAL).
-The function UPDATEFN must return its last arg, after performing the
-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'"
- (prin1-to-string accessfn)))
- ;; update properties
- (list 'progn
- (list 'eval-and-compile
- (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)))
-
-;;; This section provides the "default" setfs for Common-Emacs-Lisp
-;;; The user will not normally add anything to this, although
-;;; defstruct will introduce new ones as a matter of fact.
-;;;
-;;; Apply is a special case. The Common Lisp
-;;; standard makes the case of apply be useful when the user writes
-;;; something like (apply #'name ...), Emacs Lisp doesn't have the #
-;;; stuff, but it has (function ...). Notice that V18 includes a new
-;;; apply: this file is compatible with V18 and pre-V18 Emacses.
-
-;;; INCOMPATIBILITY: the SETF macro evaluates its arguments in the
-;;; (correct) left to right sequence *before* checking for apply
-;;; methods (which should really be an special case inside setf). Due
-;;; to this, the lambda expression defsetf'd to apply will succeed in
-;;; applying the right function even if the name was not quoted, but
-;;; computed! That extension is not Common Lisp (nor is particularly
-;;; useful, I think).
-
-(defsetf apply
- (lambda (&rest args)
- ;; disassemble the calling form
- ;; "(((quote fn) x1 x2 ... xn) val)" (function instead of quote, too)
- (let* ((fnform (car args)) ;functional form
- (applyargs (append ;arguments "to apply fnform"
- (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)))))
- "`apply' is a special case for `setf'")
-
-
-(defsetf aref
- aset
- "`setf' inversion for `aref'")
-
-(defsetf nth
- setnth
- "`setf' inversion for `nth'")
-
-(defsetf nthcdr
- setnthcdr
- "`setf' inversion for `nthcdr'")
-
-(defsetf elt
- setelt
- "`setf' inversion for `elt'")
-
-(defsetf first
- (lambda (list val) (setnth 0 list val))
- "`setf' inversion for `first'")
-
-(defsetf second
- (lambda (list val) (setnth 1 list val))
- "`setf' inversion for `second'")
-
-(defsetf third
- (lambda (list val) (setnth 2 list val))
- "`setf' inversion for `third'")
-
-(defsetf fourth
- (lambda (list val) (setnth 3 list val))
- "`setf' inversion for `fourth'")
-
-(defsetf fifth
- (lambda (list val) (setnth 4 list val))
- "`setf' inversion for `fifth'")
-
-(defsetf sixth
- (lambda (list val) (setnth 5 list val))
- "`setf' inversion for `sixth'")
-
-(defsetf seventh
- (lambda (list val) (setnth 6 list val))
- "`setf' inversion for `seventh'")
-
-(defsetf eighth
- (lambda (list val) (setnth 7 list val))
- "`setf' inversion for `eighth'")
-
-(defsetf ninth
- (lambda (list val) (setnth 8 list val))
- "`setf' inversion for `ninth'")
-
-(defsetf tenth
- (lambda (list val) (setnth 9 list val))
- "`setf' inversion for `tenth'")
-
-(defsetf rest
- (lambda (list val) (setcdr list val))
- "`setf' inversion for `rest'")
-
-(defsetf car setcar "Replace the car of a cons")
-
-(defsetf cdr setcdr "Replace the cdr of a cons")
-
-(defsetf caar
- (lambda (list val) (setcar (nth 0 list) val))
- "`setf' inversion for `caar'")
-
-(defsetf cadr
- (lambda (list val) (setcar (cdr list) val))
- "`setf' inversion for `cadr'")
-
-(defsetf cdar
- (lambda (list val) (setcdr (car list) val))
- "`setf' inversion for `cdar'")
-
-(defsetf cddr
- (lambda (list val) (setcdr (cdr list) val))
- "`setf' inversion for `cddr'")
-
-(defsetf caaar
- (lambda (list val) (setcar (caar list) val))
- "`setf' inversion for `caaar'")
-
-(defsetf caadr
- (lambda (list val) (setcar (cadr list) val))
- "`setf' inversion for `caadr'")
-
-(defsetf cadar
- (lambda (list val) (setcar (cdar list) val))
- "`setf' inversion for `cadar'")
-
-(defsetf cdaar
- (lambda (list val) (setcdr (caar list) val))
- "`setf' inversion for `cdaar'")
-
-(defsetf caddr
- (lambda (list val) (setcar (cddr list) val))
- "`setf' inversion for `caddr'")
-
-(defsetf cdadr
- (lambda (list val) (setcdr (cadr list) val))
- "`setf' inversion for `cdadr'")
-
-(defsetf cddar
- (lambda (list val) (setcdr (cdar list) val))
- "`setf' inversion for `cddar'")
-
-(defsetf cdddr
- (lambda (list val) (setcdr (cddr list) val))
- "`setf' inversion for `cdddr'")
-
-(defsetf caaaar
- (lambda (list val) (setcar (caaar list) val))
- "`setf' inversion for `caaaar'")
-
-(defsetf caaadr
- (lambda (list val) (setcar (caadr list) val))
- "`setf' inversion for `caaadr'")
-
-(defsetf caadar
- (lambda (list val) (setcar (cadar list) val))
- "`setf' inversion for `caadar'")
-
-(defsetf cadaar
- (lambda (list val) (setcar (cdaar list) val))
- "`setf' inversion for `cadaar'")
-
-(defsetf cdaaar
- (lambda (list val) (setcdr (caar list) val))
- "`setf' inversion for `cdaaar'")
-
-(defsetf caaddr
- (lambda (list val) (setcar (caddr list) val))
- "`setf' inversion for `caaddr'")
-
-(defsetf cadadr
- (lambda (list val) (setcar (cdadr list) val))
- "`setf' inversion for `cadadr'")
-
-(defsetf cdaadr
- (lambda (list val) (setcdr (caadr list) val))
- "`setf' inversion for `cdaadr'")
-
-(defsetf caddar
- (lambda (list val) (setcar (cddar list) val))
- "`setf' inversion for `caddar'")
-
-(defsetf cdadar
- (lambda (list val) (setcdr (cadar list) val))
- "`setf' inversion for `cdadar'")
-
-(defsetf cddaar
- (lambda (list val) (setcdr (cdaar list) val))
- "`setf' inversion for `cddaar'")
-
-(defsetf cadddr
- (lambda (list val) (setcar (cdddr list) val))
- "`setf' inversion for `cadddr'")
-
-(defsetf cddadr
- (lambda (list val) (setcdr (cdadr list) val))
- "`setf' inversion for `cddadr'")
-
-(defsetf cdaddr
- (lambda (list val) (setcdr (caddr list) val))
- "`setf' inversion for `cdaddr'")
-
-(defsetf cdddar
- (lambda (list val) (setcdr (cddar list) val))
- "`setf' inversion for `cdddar'")
-
-(defsetf cddddr
- (lambda (list val) (setcdr (cddr list) val))
- "`setf' inversion for `cddddr'")
-
-(defsetf get put "`setf' inversion for `get' is `put'")
-
-(defsetf symbol-function fset
- "`setf' inversion for `symbol-function' is `fset'")
-
-(defsetf symbol-plist setplist
- "`setf' inversion for `symbol-plist' is `setplist'")
-
-(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
-;;;
-;;; It could be nice to implement define-modify-macro, but I don't
-;;; think it really pays.
-
-(defmacro incf (ref &optional delta)
- "(incf REF [DELTA]) -> increment the g.v. REF by DELTA (default 1)"
- (if (null delta)
- (setq delta 1))
- (list 'setf ref (list '+ ref delta)))
-
-(defmacro decf (ref &optional delta)
- "(decf REF [DELTA]) -> decrement the g.v. REF by DELTA (default 1)"
- (if (null delta)
- (setq delta 1))
- (list 'setf ref (list '- ref delta)))
-
-(defmacro push (item ref)
- "(push ITEM REF) -> cons ITEM at the head of the g.v. REF (a list)"
- (list 'setf ref (list 'cons item ref)))
-
-(defmacro pushnew (item ref)
- "(pushnew ITEM REF): adjoin ITEM at the head of the g.v. REF (a list)"
- (list 'setf ref (list 'adjoin item ref)))
-
-(defmacro pop (ref)
- "(pop REF) -> (prog1 (car REF) (setf REF (cdr REF)))"
- (let ((listname (gensym)))
- (list 'let (list (list listname ref))
- (list 'prog1
- (list 'car listname)
- (list 'setf ref (list 'cdr listname))))))
-
-;;; PSETF
-;;;
-;;; Psetf is the generalized variable equivalent of psetq. The right
-;;; hand sides are evaluated and assigned (via setf) to the left hand
-;;; 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))))))
-
-;;; SHIFTF and ROTATEF
-;;;
-
-(defmacro shiftf (&rest forms)
- "(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."
- (unless (> (length forms) 1)
- (error "`shiftf' needs more than one argument"))
- (let ((places (butlast forms))
- (newvalue (car (last forms))))
- ;; the places are accessed to fresh symbols
- (multiple-value-bind
- (bindings newsyms)
- (pair-with-newsyms places)
- (list 'let bindings
- (cons 'setf
- (zip-lists places
- (append (cdr newsyms) (list newvalue))))
- (car newsyms)))))
-
-(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))))
-
-;;; GETF, REMF, and REMPROP
-;;;
-
-(defun getf (place indicator &optional default)
- "Return PLACE's PROPNAME property, or DEFAULT if not present."
- (while (and place (not (eq (car place) indicator)))
- (setq place (cdr (cdr place))))
- (if place
- (car (cdr place))
- default))
-
-(defmacro getf$setf$method (place indicator default &rest newval)
- "SETF method for GETF. Not for public use."
- (case (length newval)
- (0 (setq newval default default nil))
- (1 (setq newval (car newval)))
- (t (error "Wrong number of arguments to (setf (getf ...)) form")))
- (let ((psym (gentemp)) (isym (gentemp)) (vsym (gentemp)))
- (list 'let (list (list psym place)
- (list isym indicator)
- (list vsym newval))
- (list 'while
- (list 'and psym
- (list 'not
- (list 'eq (list 'car psym) isym)))
- (list 'setq psym (list 'cdr (list 'cdr psym))))
- (list 'if psym
- (list 'setcar (list 'cdr psym) vsym)
- (list 'setf place
- (list 'nconc place (list 'list isym newval))))
- vsym)))
-
-(defsetf getf
- getf$setf$method)
-
-(defmacro remf (place indicator)
- "Remove from the property list at PLACE its PROPNAME property.
-Returns non-nil if and only if the property existed."
- (let ((psym (gentemp)) (isym (gentemp)))
- (list 'let (list (list psym place) (list isym indicator))
- (list 'cond
- (list (list 'eq isym (list 'car psym))
- (list 'setf place (list 'cdr (list 'cdr psym)))
- t)
- (list t
- (list 'setq psym (list 'cdr psym))
- (list 'while
- (list 'and (list 'cdr psym)
- (list 'not
- (list 'eq (list 'car (list 'cdr psym))
- isym)))
- (list 'setq psym (list 'cdr (list 'cdr psym))))
- (list 'cond
- (list (list 'cdr psym)
- (list 'setcdr psym
- (list 'cdr
- (list 'cdr (list 'cdr psym))))
- t)))))))
-
-(defun remprop (symbol indicator)
- "Remove SYMBOL's PROPNAME property, returning non-nil if it was present."
- (remf (symbol-plist symbol) indicator))
-
-
-;;;; STRUCTS
-;;;; This file provides the structures mechanism. See the
-;;;; documentation for Common-Lisp's defstruct. Mine doesn't
-;;;; implement all the functionality of the standard, although some
-;;;; more could be grafted if so desired. More details along with
-;;;; the code.
-;;;;
-;;;;
-;;;; Cesar Quiroz @ UofR DofCSc - Dec. 1986
-;;;; (quiroz@cs.rochester.edu)
-
-
-(defkeyword :include "Syntax of `defstruct'")
-(defkeyword :named "Syntax of `defstruct'")
-(defkeyword :conc-name "Syntax of `defstruct'")
-(defkeyword :copier "Syntax of `defstruct'")
-(defkeyword :predicate "Syntax of `defstruct'")
-(defkeyword :print-function "Syntax of `defstruct'")
-(defkeyword :type "Syntax of `defstruct'")
-(defkeyword :initial-offset "Syntax of `defstruct'")
-
-(defkeyword :structure-doc "Documentation string for a structure.")
-(defkeyword :structure-slotsn "Number of slots in structure")
-(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-function, :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.
-
-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
-the slot.
-`defstruct' defines functions `make-NAME', `NAME-p', `copy-NAME' for the
-structure, and functions with the same name as the slots to access
-them. `setf' of the accessors sets their values."
- (multiple-value-bind
- (name options docstring slotsn slots initlist)
- (parse$defstruct$args args)
- ;; 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)
- (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
- (when (and (numberp moreslotsn)
- (> moreslotsn 0))
- (setf slotsn (+ slotsn moreslotsn))
- (setf slots (append moreslots slots))
- (setf initlist (append moreinits initlist)))
- (unless (> slotsn 0)
- (error "%s needs at least one slot"
- (prin1-to-string name)))
- (let ((dups (duplicate-symbols-p slots)))
- (when dups
- (error "`%s' are duplicates"
- (prin1-to-string dups))))
- (setq initlist (simplify$inits slots initlist))
- (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))))))))
-
- ;; Compute functions associated with NAME. This is not
- ;; handling BOA constructors yet, but here would be the place.
- (setq functions
- (list
- (list 'fset (list 'quote constructor)
- (list 'function
- (list 'lambda (list '&rest 'args)
- (list 'make$structure$instance
- (list 'quote name)
- 'args))))
- (list 'fset (list 'quote copier)
- (list 'function 'copy-sequence))
- (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))))))
- )))))
- ;; compute accessors for NAME's slots
- (multiple-value-setq
- (accessors alterators keywords)
- (build$accessors$for name conc-name predicate slots slotsn))
- ;; generate returned value -- not defined by the standard
- (setq returned
- (list
- (cons 'vector
- (mapcar
- (function (lambda (x) (list 'quote x)))
- (cons name slots)))))
- ;; generate code
- (cons 'progn
- (nconc properties functions keywords
- accessors alterators returned))))))
-
-(defun parse$defstruct$args (args)
- "(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...)...)
- options ;args=((symbol . options) ...)
- (docstring "") ;args=(head docstring . slotargs)
- slotargs ;second or third cdr of args
- (slotsn 0) ;number of slots
- (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 ...)")))
- (setq slotargs (cdr args))
- ;; is there a docstring?
- (when (stringp (car slotargs))
- (setq docstring (car slotargs)
- slotargs (cdr slotargs)))
- ;; now for the slots
- (multiple-value-bind
- (slotsn slots initlist)
- (process$slots slotargs)
- (values name options docstring slotsn slots initlist))))
-
-(defun process$slots (slots)
- "(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
- slotslist ;(slot1 slot2 ...)
- initlist) ;((:slot1 . init1) ...)
- (do*
- ((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)))))
- (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"
- (let* ((namestring (symbol-name name))
- ;; to build the return values
- (conc-name (concat namestring "-"))
- (const (intern (concat "make-" namestring)))
- (copier (intern (concat "copy-" namestring)))
- (pred (intern (concat namestring "-p")))
- (moreslotsn 0)
- (moreslots '())
- (moreinits '())
- ;; auxiliaries
- option-head ;When an option is not a plain
- option-second ; keyword, it must be a list of
- option-rest ; the form (head second . rest)
- 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)
- ;; 2 cases arise, as options must be a keyword or a list
- (cond
- ((keywordp option)
- (case option
- (:named
- ) ;ignore silently
- (t
- (error "can't recognize option `%s'"
- (prin1-to-string option)))))
- ((and (listp option)
- (keywordp (setq option-head (car option))))
- (setq option-second (second option))
- (setq option-rest (nthcdr 2 option))
- (case option-head
- (:conc-name
- (setq conc-name
- (cond
- ((stringp option-second)
- option-second)
- ((null option-second)
- "")
- (t
- (error "`%s' is invalid as `conc-name'"
- (prin1-to-string option-second))))))
- (:copier
- (setq copier
- (cond
- ((and (symbolp option-second)
- (null option-rest))
- option-second)
- (t
- (error "can't recognize option `%s'"
- (prin1-to-string option))))))
-
- (:constructor ;no BOA-constructors allowed
- (setq const
- (cond
- ((and (symbolp option-second)
- (null option-rest))
- option-second)
- (t
- (error "can't recognize option `%s'"
- (prin1-to-string option))))))
- (:predicate
- (setq pred
- (cond
- ((and (symbolp option-second)
- (null option-rest))
- option-second)
- (t
- (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'"
- (prin1-to-string option-second)))
- (setq these-slotsn (get option-second :structure-slotsn)
- these-slots (get option-second :structure-slots)
- these-inits (get option-second :structure-initforms))
- (unless (and (numberp these-slotsn)
- (> 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)
- (when (> xtra-slotsn 0)
- (dolist (xslot xtra-slots)
- (unless (memq xslot these-slots)
- (error "`%s' is not a slot of `%s'"
- (prin1-to-string xslot)
- (prin1-to-string option-second))))
- (setq these-inits (append xtra-inits these-inits)))
- (setq moreslotsn (+ moreslotsn these-slotsn))
- (setq moreslots (append these-slots moreslots))
- (setq moreinits (append these-inits moreinits))))
- ((:print-function :type :initial-offset)
- ) ;ignore silently
- (t
- (error "can't recognize option `%s'"
- (prin1-to-string option)))))
- (t
- (error "can't recognize option `%s'"
- (prin1-to-string option)))))
- ;; Return values found
- (values conc-name const copier pred
- moreslotsn moreslots moreinits
- included)))
-
-(defun simplify$inits (slots initlist)
- "(simplify$inits SLOTS INITLIST) => new INITLIST
-Removes from INITLIST - an ALIST - any shadowed bindings."
- (let ((result '()) ;built here
- key ;from the slot
- )
- (dolist (slot slots)
- (setq key (keyword-of slot))
- (setq result (acons key (cdr (assoc key initlist)) result)))
- (nreverse result)))
-
-(defun extract$indices (initlist)
- "(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."
- (let ((result '())
- (index 0))
- (dolist (entry initlist (nreverse result))
- (setq result (acons (car entry) index result)
- index (+ index 1)))))
-
-(defun build$accessors$for (name conc-name predicate slots slotsn)
- "(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."
- (do ((i 0 (1+ i))
- (accessors '())
- (alterators '())
- (keywords '())
- (canonic "")) ;slot name with conc-name prepended
- ((>= i slotsn)
- (values
- (nreverse accessors) (nreverse alterators) (nreverse keywords)))
- (setq canonic (intern (concat conc-name (symbol-name (nth i slots)))))
- (setq accessors
- (cons
- (list 'fset (list 'quote canonic)
- (list 'function
- (list 'lambda (list 'object)
- (list 'cond
- (list (list predicate 'object)
- (list 'aref 'object (1+ i)))
- (list 't
- (list 'error
- "`%s' is not a struct %s"
- (list 'prin1-to-string
- 'object)
- (list 'prin1-to-string
- (list 'quote
- name))))))))
- accessors))
- (setq alterators
- (cons
- (list 'defsetf canonic
- (list 'lambda (list 'object 'newval)
- (list 'cond
- (list (list predicate 'object)
- (list 'aset 'object (1+ i) 'newval))
- (list 't
- (list 'error
- "`%s' not a `%s'"
- (list 'prin1-to-string
- 'object)
- (list 'prin1-to-string
- (list 'quote
- name)))))))
- alterators))
- (setq keywords
- (cons (list 'defkeyword (keyword-of (nth i slots)))
- keywords))))
-
-(defun make$structure$instance (name args)
- "(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)
- (error "`%s' is not a possible name for a structure"
- (prin1-to-string name)))
- (let ((initforms (get name :structure-initforms))
- (slotsn (get name :structure-slotsn))
- (indices (get name :structure-indices))
- initalist ;pairlis'd on initforms
- initializers ;definitive initializers
- )
- ;; check sanity of the request
- (unless (and (numberp slotsn)
- (> slotsn 0))
- (error "`%s' is not a defined structure"
- (prin1-to-string name)))
- (unless (evenp (length args))
- (error "slot initializers `%s' not of even length"
- (prin1-to-string args)))
- ;; analyze the initializers provided by the call
- (multiple-value-bind
- (speckwds specvals) ;keywords and values given
- (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"
- (prin1-to-string speckwds)))
- ;; check that all the keywords are known
- (dolist (kwd speckwds)
- (unless (numberp (cdr (assoc kwd indices)))
- (error "`%s' is not a valid slot name for %s"
- (prin1-to-string kwd) (prin1-to-string name))))
- ;; update initforms
- (setq initalist
- (pairlis speckwds
- (do* ;;protect values from further evaluation
- ((ptr specvals (cdr ptr))
- (val (car ptr) (car ptr))
- (result '()))
- ((endp ptr) (nreverse result))
- (setq result
- (cons (list 'quote val)
- result)))
- (copy-sequence initforms)))
- ;; compute definitive initializers
- (setq initializers
- (do* ;;gather the values of the most definitive forms
- ((ptr indices (cdr ptr))
- (key (caar ptr) (caar ptr))
- (result '()))
- ((endp ptr) (nreverse result))
- (setq result
- (cons (eval (cdr (assoc key initalist))) result))))
- ;; do real initialization
- (apply (function vector)
- (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
-
-(defsubst 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)
-
-;;; Due to Aaron Larson (alarson@src.honeywell.com, 26 Jul 91)
-(put 'progv 'common-lisp-indent-hook '(4 4 &body))
-(defmacro progv (vars vals &rest body)
- "progv vars vals &body forms
-bind vars to vals then execute forms.
-If there are more vars than vals, the extra vars are unbound, if
-there are more vals than vars, the extra vals are just ignored."
- (` (progv$runtime (, vars) (, vals) (function (lambda () (,@ body))))))
-
-;;; To do this efficiently, it really needs to be a special form...
-(defun progv$runtime (vars vals body)
- (eval (let ((vars-n-vals nil)
- (unbind-forms nil))
- (do ((r vars (cdr r))
- (l vals (cdr l)))
- ((endp r))
- (push (list (car r) (list 'quote (car l))) vars-n-vals)
- (if (null l)
- (push (` (makunbound '(, (car r)))) unbind-forms)))
- (` (let (, vars-n-vals) (,@ unbind-forms) (funcall '(, body)))))))
-
-(provide 'cl)
-
-;;;; end of cl.el
diff --git a/lisp/=cmulisp.el b/lisp/=cmulisp.el
deleted file mode 100644
index 1e49da84165..00000000000
--- a/lisp/=cmulisp.el
+++ /dev/null
@@ -1,694 +0,0 @@
-;;; cmulisp.el --- improved version of standard inferior-lisp mode
-
-;;; Copyright Olin Shivers (1988).
-
-;; Keywords: processes, lisp
-
-;;; Please imagine a long, tedious, legalistic 5-page gnu-style copyright
-;;; notice appearing here to the effect that you may use this code any
-;;; way you like, as long as you don't charge money for it, remove this
-;;; notice, or hold me liable for its results.
-
-;;; Commentary:
-
-;;; This replaces the standard inferior-lisp mode.
-;;; Hacked from tea.el by Olin Shivers (shivers@cs.cmu.edu). 8/88
-;;; Please send me bug reports, bug fixes, and extensions, so that I can
-;;; merge them into the master source.
-;;;
-;;; Change log at end of file.
-
-;;; This file defines a a lisp-in-a-buffer package (cmulisp mode) built on top
-;;; of comint mode. Cmulisp mode is similar to, and intended to replace, its
-;;; counterpart in the standard gnu emacs release. This replacements is more
-;;; featureful, robust, and uniform than the released version. The key
-;;; bindings are also more compatible with the bindings of Hemlock and Zwei
-;;; (the Lisp Machine emacs).
-
-;;; 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.
-;;; This makes these modes easier to use.
-
-;;; For documentation on the functionality provided by comint mode, and
-;;; the hooks available for customising it, see the file comint.el.
-;;; For further information on cmulisp mode, see the comments below.
-
-;;; Needs fixin:
-;;; 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, ...).
-;;;
-;;; It would be nice if cmulisp (and inferior scheme, T, ...) modes
-;;; had a verbose minor mode wherein sending or compiling defuns, etc.
-;;; would be reflected in the transcript with suitable comments, e.g.
-;;; ";;; redefining fact". Several ways to do this. Which is right?
-;;;
-;;; 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?
-
-(require 'comint)
-;; YOUR .EMACS FILE
-;;=============================================================================
-;; Some suggestions for your .emacs file.
-;;
-;; ; If cmulisp lives in some non-standard directory, you must tell emacs
-;; ; where to get it. This may or may not be necessary.
-;; (setq load-path (cons (expand-file-name "~jones/lib/emacs") load-path))
-;;
-;; ; Autoload cmulisp from file cmulisp.el
-;; (autoload 'cmulisp "cmulisp"
-;; "Run an inferior Lisp process."
-;; t)
-;;
-;; ; Define C-c t to run my favorite command in cmulisp mode:
-;; (setq cmulisp-load-hook
-;; '((lambda ()
-;; (define-key cmulisp-mode-map "\C-ct" 'favorite-cmd))))
-
-;; Brief Command Documentation:
-;;============================================================================
-;; Comint Mode Commands: (common to cmulisp and all comint-derived modes)
-;;
-;; m-p comint-previous-input Cycle backwards in input history
-;; m-n comint-next-input Cycle forwards
-;; m-c-r comint-previous-input-matching Search backwards in input history
-;; return comint-send-input
-;; c-a comint-bol Beginning of line; skip prompt.
-;; c-d comint-delchar-or-maybe-eof Delete char unless at end of buff.
-;; c-c c-u comint-kill-input ^u
-;; c-c c-w backward-kill-word ^w
-;; c-c c-c comint-interrupt-subjob ^c
-;; c-c c-z comint-stop-subjob ^z
-;; c-c c-\ comint-quit-subjob ^\
-;; c-c c-o comint-kill-output Delete last batch of process output
-;; c-c c-r comint-show-output Show last batch of process output
-;; send-invisible Read line w/o echo & send to proc
-;; comint-continue-subjob Useful if you accidentally suspend
-;; top-level job.
-;; comint-mode-hook is the comint mode hook.
-
-;; CMU Lisp Mode Commands:
-;; c-m-x lisp-send-defun This binding is a gnu convention.
-;; c-c c-l lisp-load-file Prompt for file name; tell Lisp to load it.
-;; c-c c-k lisp-compile-file Prompt for file name; tell Lisp to kompile it.
-;; Filename completion is available, of course.
-;;
-;; Additionally, these commands are added to the key bindings of Lisp mode:
-;; c-m-x lisp-eval-defun This binding is a gnu convention.
-;; c-c c-e lisp-eval-defun Send the current defun to Lisp process.
-;; c-x c-e lisp-eval-last-sexp Send the previous sexp to Lisp process.
-;; c-c c-r lisp-eval-region Send the current region to Lisp process.
-;; c-c c-c lisp-compile-defun Compile the current defun in Lisp process.
-;; c-c c-z switch-to-lisp Switch to the Lisp process buffer.
-;; c-c c-l lisp-load-file (See above. In a Lisp file buffer, default
-;; c-c c-k lisp-compile-file is to load/compile the current file.)
-;; c-c c-d lisp-describe-sym Query Lisp for a symbol's description.
-;; c-c c-a lisp-show-arglist Query Lisp for function's arglist.
-;; c-c c-f lisp-show-function-documentation Query Lisp for a function's doc.
-;; c-c c-v lisp-show-variable-documentation Query Lisp for a variable's doc.
-
-;; cmulisp Fires up the Lisp process.
-;; lisp-compile-region Compile all forms in the current region.
-;;
-;; CMU Lisp Mode Variables:
-;; cmulisp-filter-regexp Match this => don't get saved on input hist
-;; inferior-lisp-program Name of Lisp program run-lisp executes
-;; inferior-lisp-load-command Customises lisp-load-file
-;; cmulisp-mode-hook
-;; inferior-lisp-prompt Initialises comint-prompt-regexp.
-;; Backwards compatibility.
-;; lisp-source-modes Anything loaded into a buffer that's in
-;; one of these modes is considered Lisp
-;; source by lisp-load/compile-file.
-
-;;; Code:
-
-(require 'comint)
-
-;;; Read the rest of this file for more information.
-
-
-;;; Code:
-
-(defvar cmulisp-filter-regexp "\\`\\s *\\(:\\(\\w\\|\\s_\\)\\)?\\s *\\'"
- "*What not to save on inferior Lisp's input history
-Input matching this regexp is not saved on the input history in cmulisp
-mode. Default is whitespace followed by 0 or 1 single-letter :keyword
-(as in :a, :c, etc.)")
-
-(defvar cmulisp-mode-map nil)
-(cond ((not cmulisp-mode-map)
- (setq cmulisp-mode-map
- (nconc (full-copy-sparse-keymap comint-mode-map)
- shared-lisp-mode-map))
- (define-key cmulisp-mode-map "\C-x\C-e" 'lisp-eval-last-sexp)
- (define-key cmulisp-mode-map "\C-c\C-l" 'lisp-load-file)
- (define-key cmulisp-mode-map "\C-c\C-k" 'lisp-compile-file)
- (define-key cmulisp-mode-map "\C-c\C-a" 'lisp-show-arglist)
- (define-key cmulisp-mode-map "\C-c\C-d" 'lisp-describe-sym)
- (define-key cmulisp-mode-map "\C-c\C-f" 'lisp-show-function-documentation)
- (define-key cmulisp-mode-map "\C-c\C-v" 'lisp-show-variable-documentation)))
-
-;;; These commands augment Lisp mode, so you can process Lisp code in
-;;; the source files.
-(define-key lisp-mode-map "\M-\C-x" 'lisp-eval-defun) ; Gnu convention
-(define-key lisp-mode-map "\C-x\C-e" 'lisp-eval-last-sexp) ; Gnu convention
-(define-key lisp-mode-map "\C-c\C-e" 'lisp-eval-defun)
-(define-key lisp-mode-map "\C-c\C-r" 'lisp-eval-region)
-(define-key lisp-mode-map "\C-c\C-c" 'lisp-compile-defun)
-(define-key lisp-mode-map "\C-c\C-z" 'switch-to-lisp)
-(define-key lisp-mode-map "\C-c\C-l" 'lisp-load-file)
-(define-key lisp-mode-map "\C-c\C-k" 'lisp-compile-file) ; "kompile" file
-(define-key lisp-mode-map "\C-c\C-a" 'lisp-show-arglist)
-(define-key lisp-mode-map "\C-c\C-d" 'lisp-describe-sym)
-(define-key lisp-mode-map "\C-c\C-f" 'lisp-show-function-documentation)
-(define-key lisp-mode-map "\C-c\C-v" 'lisp-show-variable-documentation)
-
-(defvar cmulisp-buffer)
-
-;;; This function exists for backwards compatibility.
-;;; Previous versions of this package bound commands to C-c <letter>
-;;; bindings, which is not allowed by the gnumacs standard.
-
-(defun cmulisp-install-letter-bindings ()
- "This function binds many cmulisp commands to C-c <letter> bindings,
-where they are more accessible. C-c <letter> bindings are reserved for the
-user, so these bindings are non-standard. If you want them, you should
-have this function called by the cmulisp-load-hook:
- (setq cmulisp-load-hook '(cmulisp-install-letter-bindings))
-You can modify this function to install just the bindings you want."
-
- (define-key lisp-mode-map "\C-ce" 'lisp-eval-defun-and-go)
- (define-key lisp-mode-map "\C-cr" 'lisp-eval-region-and-go)
- (define-key lisp-mode-map "\C-cc" 'lisp-compile-defun-and-go)
- (define-key lisp-mode-map "\C-cz" 'switch-to-lisp)
- (define-key lisp-mode-map "\C-cl" 'lisp-load-file)
- (define-key lisp-mode-map "\C-ck" 'lisp-compile-file)
- (define-key lisp-mode-map "\C-ca" 'lisp-show-arglist)
- (define-key lisp-mode-map "\C-cd" 'lisp-describe-sym)
- (define-key lisp-mode-map "\C-cf" 'lisp-show-function-documentation)
- (define-key lisp-mode-map "\C-cv" 'lisp-show-variable-documentation)
-
- (define-key cmulisp-mode-map "\C-cl" 'lisp-load-file)
- (define-key cmulisp-mode-map "\C-ck" 'lisp-compile-file)
- (define-key cmulisp-mode-map "\C-ca" 'lisp-show-arglist)
- (define-key cmulisp-mode-map "\C-cd" 'lisp-describe-sym)
- (define-key cmulisp-mode-map "\C-cf" 'lisp-show-function-documentation)
- (define-key cmulisp-mode-map "\C-cv" 'lisp-show-variable-documentation))
-
-
-(defvar inferior-lisp-program "lisp"
- "*Program name for invoking an inferior Lisp with `cmulisp'.")
-
-(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 recognise prompts in the inferior Lisp.
-Defaults to \"^[^> ]*>+:? *\", which works pretty good for Lucid, kcl,
-and franz. This variable is used to initialise comint-prompt-regexp in the
-cmulisp buffer.
-
-More precise choices:
-Lucid Common Lisp: \"^\\(>\\|\\(->\\)+\\) *\"
-franz: \"^\\(->\\|<[0-9]*>:\\) *\"
-kcl: \"^>+ *\"
-
-This is a fine thing to set in your .emacs file.")
-
-(defvar cmulisp-mode-hook '()
- "*Hook for customising cmulisp mode")
-
-(defun cmulisp-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, cmulisp-filter-regexp and
-inferior-lisp-load-command can customize this mode for different Lisp
-interpreters.
-
-For information on running multiple processes in multiple buffers, see
-documentation for variable cmulisp-buffer.
-
-\\{cmulisp-mode-map}
-
-Customisation: Entry to this mode runs the hooks on comint-mode-hook and
-cmulisp-mode-hook (in that order).
-
-You can send text to the inferior Lisp process from other buffers containing
-Lisp source.
- switch-to-lisp switches the current buffer to the Lisp process buffer.
- lisp-eval-defun sends the current defun to the Lisp process.
- lisp-compile-defun compiles the current defun.
- lisp-eval-region sends the current region to the Lisp process.
- lisp-compile-region compiles the current region.
-
- Prefixing the lisp-eval/compile-defun/region commands with
- a \\[universal-argument] causes a switch to the Lisp process buffer after sending
- the text.
-
-Commands:
-Return after the end of the process' output sends the text from the
- end of process to point.
-Return before the end of the process' output copies the sexp ending at point
- to the end of the process' output, and sends it.
-Delete converts tabs to spaces as it moves back.
-Tab indents for Lisp; with argument, shifts rest
- of expression rigidly with the current line.
-C-M-q does Tab on each line starting within following expression.
-Paragraphs are separated only by blank lines. Semicolons start comments.
-If you accidentally suspend your process, use \\[comint-continue-subjob]
-to continue it."
- (interactive)
- (comint-mode)
- (setq comint-prompt-regexp inferior-lisp-prompt)
- (setq major-mode 'cmulisp-mode)
- (setq mode-name "CMU Lisp")
- (setq mode-line-process '(": %s"))
- (lisp-mode-variables t)
- (use-local-map cmulisp-mode-map) ;c-c c-k for "kompile" file
- (setq comint-get-old-input (function lisp-get-old-input))
- (setq comint-input-filter (function lisp-input-filter))
- (setq comint-input-sentinel 'ignore)
- (run-hooks 'cmulisp-mode-hook))
-
-(defun lisp-get-old-input ()
- "Snarf the sexp ending at point"
- (save-excursion
- (let ((end (point)))
- (backward-sexp)
- (buffer-substring (point) end))))
-
-(defun lisp-input-filter (str)
- "Don't save anything matching cmulisp-filter-regexp"
- (not (string-match cmulisp-filter-regexp str)))
-
-(defun cmulisp (cmd)
- "Run an inferior Lisp process, input and output via buffer *cmulisp*.
-If there is a process already running in *cmulisp*, just switch to that buffer.
-With argument, allows you to edit the command line (default is value
-of inferior-lisp-program). Runs the hooks from cmulisp-mode-hook (after the
-comint-mode-hook is run).
-\(Type \\[describe-mode] in the process buffer for a list of commands.)"
- (interactive (list (if current-prefix-arg
- (read-string "Run lisp: " inferior-lisp-program)
- inferior-lisp-program)))
- (if (not (comint-check-proc "*cmulisp*"))
- (let ((cmdlist (cmulisp-args-to-list cmd)))
- (set-buffer (apply (function make-comint) "cmulisp" (car cmdlist) nil
- (cdr cmdlist)))
- (cmulisp-mode)))
- (setq cmulisp-buffer "*cmulisp*")
- (switch-to-buffer "*cmulisp*"))
-
-;;; Break a string up into a list of arguments.
-;;; This will break if you have an argument with whitespace, as in
-;;; string = "-ab +c -x 'you lose'".
-(defun cmulisp-args-to-list (string)
- (let ((where (string-match "[ \t]" string)))
- (cond ((null where) (list string))
- ((not (= where 0))
- (cons (substring string 0 where)
- (tea-args-to-list (substring string (+ 1 where)
- (length string)))))
- (t (let ((pos (string-match "[^ \t]" string)))
- (if (null pos)
- nil
- (cmulisp-args-to-list (substring string pos
- (length string)))))))))
-
-(defun lisp-eval-region (start end &optional and-go)
- "Send the current region to the inferior Lisp process.
-Prefix argument means switch-to-lisp afterwards."
- (interactive "r\nP")
- (comint-send-region (cmulisp-proc) start end)
- (comint-send-string (cmulisp-proc) "\n")
- (if and-go (switch-to-lisp t)))
-
-(defun lisp-eval-defun (&optional and-go)
- "Send the current defun to the inferior Lisp process.
-Prefix argument means switch-to-lisp afterwards."
- (interactive "P")
- (save-excursion
- (end-of-defun)
- (skip-chars-backward " \t\n\r\f") ; Makes allegro happy
- (let ((end (point)))
- (beginning-of-defun)
- (lisp-eval-region (point) end)))
- (if and-go (switch-to-lisp t)))
-
-(defun lisp-eval-last-sexp (&optional and-go)
- "Send the previous sexp to the inferior Lisp process.
-Prefix argument means switch-to-lisp afterwards."
- (interactive "P")
- (lisp-eval-region (save-excursion (backward-sexp) (point)) (point) and-go))
-
-;;; Common Lisp COMPILE sux.
-(defun lisp-compile-region (start end &optional and-go)
- "Compile the current region in the inferior Lisp process.
-Prefix argument means switch-to-lisp afterwards."
- (interactive "r\nP")
- (comint-send-string (cmulisp-proc)
- (format "(funcall (compile nil `(lambda () (progn 'compile %s))))\n"
- (buffer-substring start end)))
- (if and-go (switch-to-lisp t)))
-
-(defun lisp-compile-defun (&optional and-go)
- "Compile the current defun in the inferior Lisp process.
-Prefix argument means switch-to-lisp afterwards."
- (interactive "P")
- (save-excursion
- (end-of-defun)
- (skip-chars-backward " \t\n\r\f") ; Makes allegro happy
- (let ((e (point)))
- (beginning-of-defun)
- (lisp-compile-region (point) e)))
- (if and-go (switch-to-lisp t)))
-
-(defun switch-to-lisp (eob-p)
- "Switch to the inferior Lisp process buffer.
-With argument, positions cursor at end of buffer."
- (interactive "P")
- (if (get-buffer cmulisp-buffer)
- (pop-to-buffer cmulisp-buffer)
- (error "No current process buffer. See variable cmulisp-buffer."))
- (cond (eob-p
- (push-mark)
- (goto-char (point-max)))))
-
-
-;;; Now that lisp-compile/eval-defun/region takes an optional prefix arg,
-;;; these commands are redundant. But they are kept around for the user
-;;; to bind if he wishes, for backwards functionality, and because it's
-;;; easier to type C-c e than C-u C-c C-e.
-
-(defun lisp-eval-region-and-go (start end)
- "Send the current region to the inferior Lisp,
-and switch to the process buffer."
- (interactive "r")
- (lisp-eval-region start end t))
-
-(defun lisp-eval-defun-and-go ()
- "Send the current defun to the inferior Lisp,
-and switch to the process buffer."
- (interactive)
- (lisp-eval-defun t))
-
-(defun lisp-compile-region-and-go (start end)
- "Compile the current region in the inferior Lisp,
-and switch to the process buffer."
- (interactive "r")
- (lisp-compile-region start end t))
-
-(defun lisp-compile-defun-and-go ()
- "Compile the current defun in the inferior Lisp,
-and switch to the process buffer."
- (interactive)
- (lisp-compile-defun t))
-
-;;; A version of the form in H. Shevis' soar-mode.el package. Less robust.
-;(defun lisp-compile-sexp (start end)
-; "Compile the s-expression bounded by START and END in the inferior lisp.
-;If the sexp isn't a DEFUN form, it is evaluated instead."
-; (cond ((looking-at "(defun\\s +")
-; (goto-char (match-end 0))
-; (let ((name-start (point)))
-; (forward-sexp 1)
-; (process-send-string "cmulisp" (format "(compile '%s #'(lambda "
-; (buffer-substring name-start
-; (point)))))
-; (let ((body-start (point)))
-; (goto-char start) (forward-sexp 1) ; Can't use end-of-defun.
-; (process-send-region "cmulisp" (buffer-substring body-start (point))))
-; (process-send-string "cmulisp" ")\n"))
-; (t (lisp-eval-region start end)))))
-;
-;(defun lisp-compile-region (start end)
-; "Each s-expression in the current region is compiled (if a DEFUN)
-;or evaluated (if not) in the inferior lisp."
-; (interactive "r")
-; (save-excursion
-; (goto-char start) (end-of-defun) (beginning-of-defun) ; error check
-; (if (< (point) start) (error "region begins in middle of defun"))
-; (goto-char start)
-; (let ((s start))
-; (end-of-defun)
-; (while (<= (point) end) ; Zip through
-; (lisp-compile-sexp s (point)) ; compiling up defun-sized chunks.
-; (setq s (point))
-; (end-of-defun))
-; (if (< s end) (lisp-compile-sexp s end)))))
-;;;
-;;; End of HS-style code
-
-
-(defvar lisp-prev-l/c-dir/file nil
- "Saves the (directory . file) pair used in the last lisp-load-file or
-lisp-compile-file command. Used for determining the default in the
-next one.")
-
-(defvar lisp-source-modes '(lisp-mode)
- "*Used to determine if a buffer contains Lisp source code.
-If it's loaded into a buffer that is in one of these major modes, it's
-considered a Lisp source file by lisp-load-file and lisp-compile-file.
-Used by these commands to determine defaults.")
-
-(defun lisp-load-file (file-name)
- "Load a Lisp file into the inferior Lisp process."
- (interactive (comint-get-source "Load Lisp file: " lisp-prev-l/c-dir/file
- lisp-source-modes nil)) ; NIL because LOAD
- ; doesn't need an exact name
- (comint-check-source file-name) ; Check to see if buffer needs saved.
- (setq lisp-prev-l/c-dir/file (cons (file-name-directory file-name)
- (file-name-nondirectory file-name)))
- (comint-send-string (cmulisp-proc)
- (format inferior-lisp-load-command file-name))
- (switch-to-lisp t))
-
-
-(defun lisp-compile-file (file-name)
- "Compile a Lisp file in the inferior Lisp process."
- (interactive (comint-get-source "Compile Lisp file: " lisp-prev-l/c-dir/file
- lisp-source-modes nil)) ; NIL = don't need
- ; suffix .lisp
- (comint-check-source file-name) ; Check to see if buffer needs saved.
- (setq lisp-prev-l/c-dir/file (cons (file-name-directory file-name)
- (file-name-nondirectory file-name)))
- (comint-send-string (cmulisp-proc) (concat "(compile-file \""
- file-name
- "\"\)\n"))
- (switch-to-lisp t))
-
-
-
-;;; Documentation functions: function doc, var doc, arglist, and
-;;; describe symbol.
-;;; ===========================================================================
-
-;;; Command strings
-;;; ===============
-
-(defvar lisp-function-doc-command
- "(let ((fn '%s))
- (format t \"Documentation for ~a:~&~a\"
- fn (documentation fn 'function))
- (values))\n"
- "Command to query inferior Lisp for a function's documentation.")
-
-(defvar lisp-var-doc-command
- "(let ((v '%s))
- (format t \"Documentation for ~a:~&~a\"
- v (documentation v 'variable))
- (values))\n"
- "Command to query inferior Lisp for a variable's documentation.")
-
-(defvar lisp-arglist-command
- "(let ((fn '%s))
- (format t \"Arglist for ~a: ~a\" fn (arglist fn))
- (values))\n"
- "Command to query inferior Lisp for a function's arglist.")
-
-(defvar lisp-describe-sym-command
- "(describe '%s)\n"
- "Command to query inferior Lisp for a variable's documentation.")
-
-
-;;; Ancillary functions
-;;; ===================
-
-;;; Reads a string from the user.
-(defun lisp-symprompt (prompt default)
- (list (let* ((prompt (if default
- (format "%s (default %s): " prompt default)
- (concat prompt ": ")))
- (ans (read-string prompt)))
- (if (zerop (length ans)) default ans))))
-
-
-;;; Adapted from function-called-at-point in help.el.
-(defun lisp-fn-called-at-pt ()
- "Returns the name of the function called in the current call.
-Nil if it can't find one."
- (condition-case nil
- (save-excursion
- (save-restriction
- (narrow-to-region (max (point-min) (- (point) 1000)) (point-max))
- (backward-up-list 1)
- (forward-char 1)
- (let ((obj (read (current-buffer))))
- (and (symbolp obj) obj))))
- (error nil)))
-
-
-;;; Adapted from variable-at-point in help.el.
-(defun lisp-var-at-pt ()
- (condition-case ()
- (save-excursion
- (forward-sexp -1)
- (skip-chars-forward "'")
- (let ((obj (read (current-buffer))))
- (and (symbolp obj) obj)))
- (error nil)))
-
-
-;;; Documentation functions: fn and var doc, arglist, and symbol describe.
-;;; ======================================================================
-
-(defun lisp-show-function-documentation (fn)
- "Send a command to the inferior Lisp to give documentation for function FN.
-See variable lisp-function-doc-command."
- (interactive (lisp-symprompt "Function doc" (lisp-fn-called-at-pt)))
- (comint-proc-query (cmulisp-proc) (format lisp-function-doc-command fn)))
-
-(defun lisp-show-variable-documentation (var)
- "Send a command to the inferior Lisp to give documentation for function FN.
-See variable lisp-var-doc-command."
- (interactive (lisp-symprompt "Variable doc" (lisp-var-at-pt)))
- (comint-proc-query (cmulisp-proc) (format lisp-var-doc-command var)))
-
-(defun lisp-show-arglist (fn)
- "Sends an query to the inferior Lisp for the arglist for function FN.
-See variable lisp-arglist-command."
- (interactive (lisp-symprompt "Arglist" (lisp-fn-called-at-pt)))
- (comint-proc-query (cmulisp-proc) (format lisp-arglist-command fn)))
-
-(defun lisp-describe-sym (sym)
- "Send a command to the inferior Lisp to describe symbol SYM.
-See variable lisp-describe-sym-command."
- (interactive (lisp-symprompt "Describe" (lisp-var-at-pt)))
- (comint-proc-query (cmulisp-proc) (format lisp-describe-sym-command sym)))
-
-
-(defvar cmulisp-buffer nil "*The current cmulisp process buffer.
-
-MULTIPLE PROCESS SUPPORT
-===========================================================================
-Cmulisp.el supports, in a fairly simple fashion, running multiple Lisp
-processes. To run multiple Lisp processes, you start the first up with
-\\[cmulisp]. It will be in a buffer named *cmulisp*. Rename this buffer
-with \\[rename-buffer]. You may now start up a new process with another
-\\[cmulisp]. It will be in a new buffer, named *cmulisp*. You can
-switch between the different process buffers with \\[switch-to-buffer].
-
-Commands that send text from source buffers to Lisp processes --
-like lisp-eval-defun or lisp-show-arglist -- have to choose a process
-to send to, when you have more than one Lisp process around. This
-is determined by the global variable cmulisp-buffer. Suppose you
-have three inferior lisps running:
- Buffer Process
- foo cmulisp
- bar cmulisp<2>
- *cmulisp* cmulisp<3>
-If you do a \\[lisp-eval-defun] command on some Lisp source code,
-what process do you send it to?
-
-- If you're in a process buffer (foo, bar, or *cmulisp*),
- you send it to that process.
-- If you're in some other buffer (e.g., a source file), you
- send it to the process attached to buffer cmulisp-buffer.
-This process selection is performed by function cmulisp-proc.
-
-Whenever \\[cmulisp] fires up a new process, it resets cmulisp-buffer
-to be the new process's buffer. If you only run one process, this will
-do the right thing. If you run multiple processes, you can change
-cmulisp-buffer to another process buffer with \\[set-variable].
-
-More sophisticated approaches are, of course, possible. If you find yourself
-needing to switch back and forth between multiple processes frequently,
-you may wish to consider ilisp.el, a larger, more sophisticated package
-for running inferior Lisp processes. The approach taken here is for a
-minimal, simple implementation. Feel free to extend it.")
-
-(defun cmulisp-proc ()
- "Returns the current cmulisp process. See variable cmulisp-buffer."
- (let ((proc (get-buffer-process (if (eq major-mode 'inferior-lisp-mode)
- (current-buffer)
- cmulisp-buffer))))
- (or proc
- (error "No current process. See variable cmulisp-buffer"))))
-
-
-;;; Do the user's customisation...
-;;;===============================
-(defvar cmulisp-load-hook nil
- "This hook is run when cmulisp is loaded in.
-This is a good place to put keybindings.")
-
-(run-hooks 'cmulisp-load-hook)
-
-;;; CHANGE LOG
-;;; ===========================================================================
-;;; 5/24/90 Olin
-;;; - Split cmulisp and cmushell modes into separate files.
-;;; Not only is this a good idea, it's apparently the way it'll be rel 19.
-;;; - Upgraded process sends to use comint-send-string instead of
-;;; process-send-string.
-;;; - Explicit references to process "cmulisp" have been replaced with
-;;; (cmulisp-proc). This allows better handling of multiple process bufs.
-;;; - Added process query and var/function/symbol documentation
-;;; commands. Based on code written by Douglas Roberts.
-;;; - Added lisp-eval-last-sexp, bound to C-x C-e.
-;;;
-;;; 9/20/90 Olin
-;;; Added a save-restriction to lisp-fn-called-at-pt. This bug and fix
-;;; reported by Lennart Staflin.
-;;;
-;;; 3/12/90 Olin
-;;; - lisp-load-file and lisp-compile-file no longer switch-to-lisp.
-;;; Tale suggested this.
-;;; - Reversed this decision 7/15/91. You need the visual feedback.
-;;;
-;;; 7/25/91 Olin
-;;; Changed all keybindings of the form C-c <letter>. These are
-;;; supposed to be reserved for the user to bind. This affected
-;;; mainly the compile/eval-defun/region[-and-go] commands.
-;;; This was painful, but necessary to adhere to the gnumacs standard.
-;;; For some backwards compatibility, see the
-;;; cmulisp-install-letter-bindings
-;;; function.
-;;;
-;;; 8/2/91 Olin
-;;; - The lisp-compile/eval-defun/region commands now take a prefix arg,
-;;; which means switch-to-lisp after sending the text to the Lisp process.
-;;; This obsoletes all the -and-go commands. The -and-go commands are
-;;; kept around for historical reasons, and because the user can bind
-;;; them to key sequences shorter than C-u C-c C-<letter>.
-;;; - If M-x cmulisp is invoked with a prefix arg, it allows you to
-;;; edit the command line.
-
-(provide 'cmulisp)
-
-;;; cmulisp.el ends here
diff --git a/lisp/=custom.el b/lisp/=custom.el
deleted file mode 100644
index e747264583c..00000000000
--- a/lisp/=custom.el
+++ /dev/null
@@ -1,2472 +0,0 @@
-;;; custom.el --- User friendly customization support.
-
-;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Per Abrahamsen <abraham@iesd.auc.dk>
-;; Keywords: help
-;; Version: 0.5
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; WARNING: This package is still under construction and not all of
-;; the features below are implemented.
-;;
-;; This package provides a framework for adding user friendly
-;; customization support to Emacs. Having to do customization by
-;; editing a text file in some arcane syntax is user hostile in the
-;; extreme, and to most users emacs lisp definitely count as arcane.
-;;
-;; The intent is that authors of emacs lisp packages declare the
-;; variables intended for user customization with `custom-declare'.
-;; Custom can then automatically generate a customization buffer with
-;; `custom-buffer-create' where the user can edit the package
-;; variables in a simple and intuitive way, as well as a menu with
-;; `custom-menu-create' where he can set the more commonly used
-;; variables interactively.
-;;
-;; It is also possible to use custom for modifying the properties of
-;; other objects than the package itself, by specifying extra optional
-;; arguments to `custom-buffer-create'.
-;;
-;; Custom is inspired by OPEN LOOK property windows.
-
-;;; Todo:
-;;
-;; - Toggle documentation in three states `none', `one-line', `full'.
-;; - Function to generate an XEmacs menu from a CUSTOM.
-;; - Write TeXinfo documentation.
-;; - Make it possible to hide sections by clicking at the level.
-;; - Declare AUC TeX variables.
-;; - Declare (ding) Gnus variables.
-;; - Declare Emacs variables.
-;; - Implement remaining types.
-;; - XEmacs port.
-;; - Allow `URL', `info', and internal hypertext buttons.
-;; - Support meta-variables and goal directed customization.
-;; - Make it easy to declare custom types independently.
-;; - Make it possible to declare default value and type for a single
-;; variable, storing the data in a symbol property.
-;; - Syntactic sugar for CUSTOM declarations.
-;; - Use W3 for variable documentation.
-
-;;; Code:
-
-(eval-when-compile
- (require 'cl))
-
-;;; Compatibility:
-
-(defun custom-xmas-add-text-properties (start end props &optional object)
- (add-text-properties start end props object)
- (put-text-property start end 'start-open t object)
- (put-text-property start end 'end-open t object))
-
-(defun custom-xmas-put-text-property (start end prop value &optional object)
- (put-text-property start end prop value object)
- (put-text-property start end 'start-open t object)
- (put-text-property start end 'end-open t object))
-
-(defun custom-xmas-extent-start-open ()
- (map-extents (lambda (extent arg)
- (set-extent-property extent 'start-open t))
- nil (point) (min (1+ (point)) (point-max))))
-
-(if (string-match "XEmacs\\|Lucid" emacs-version)
- (progn
- (fset 'custom-add-text-properties 'custom-xmas-add-text-properties)
- (fset 'custom-put-text-property 'custom-xmas-put-text-property)
- (fset 'custom-extent-start-open 'custom-xmas-extent-start-open)
- (fset 'custom-set-text-properties
- (if (fboundp 'set-text-properties)
- 'set-text-properties))
- (fset 'custom-buffer-substring-no-properties
- (if (fboundp 'buffer-substring-no-properties)
- 'buffer-substring-no-properties
- 'custom-xmas-buffer-substring-no-properties)))
- (fset 'custom-add-text-properties 'add-text-properties)
- (fset 'custom-put-text-property 'put-text-property)
- (fset 'custom-extent-start-open 'ignore)
- (fset 'custom-set-text-properties 'set-text-properties)
- (fset 'custom-buffer-substring-no-properties
- 'buffer-substring-no-properties))
-
-(defun custom-xmas-buffer-substring-no-properties (beg end)
- "Return the text from BEG to END, without text properties, as a string."
- (let ((string (buffer-substring beg end)))
- (custom-set-text-properties 0 (length string) nil string)
- string))
-
-(or (fboundp 'add-to-list)
- ;; Introduced in Emacs 19.29.
- (defun add-to-list (list-var element)
- "Add to the value of LIST-VAR the element ELEMENT if it isn't there yet.
-If you want to use `add-to-list' on a variable that is not defined
-until a certain package is loaded, you should put the call to `add-to-list'
-into a hook function that will be run only after loading the package.
-`eval-after-load' provides one way to do this. In some cases
-other hooks, such as major mode hooks, can do the job."
- (or (member element (symbol-value list-var))
- (set list-var (cons element (symbol-value list-var))))))
-
-(or (fboundp 'plist-get)
- ;; Introduced in Emacs 19.29.
- (defun plist-get (plist prop)
- "Extract a value from a property list.
-PLIST is a property list, which is a list of the form
-\(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value
-corresponding to the given PROP, or nil if PROP is not
-one of the properties on the list."
- (let (result)
- (while plist
- (if (eq (car plist) prop)
- (setq result (car (cdr plist))
- plist nil)
- (set plist (cdr (cdr plist)))))
- result)))
-
-(or (fboundp 'plist-put)
- ;; Introduced in Emacs 19.29.
- (defun plist-put (plist prop val)
- "Change value in PLIST of PROP to VAL.
-PLIST is a property list, which is a list of the form
-\(PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol and VAL is any object.
-If PROP is already a property on the list, its value is set to VAL,
-otherwise the new PROP VAL pair is added. The new plist is returned;
-use `(setq x (plist-put x prop val))' to be sure to use the new value.
-The PLIST is modified by side effects."
- (if (null plist)
- (list prop val)
- (let ((current plist))
- (while current
- (cond ((eq (car current) prop)
- (setcar (cdr current) val)
- (setq current nil))
- ((null (cdr (cdr current)))
- (setcdr (cdr current) (list prop val))
- (setq current nil))
- (t
- (setq current (cdr (cdr current)))))))
- plist)))
-
-(or (fboundp 'match-string)
- ;; Introduced in Emacs 19.29.
- (defun match-string (num &optional string)
- "Return string of text matched by last search.
-NUM specifies which parenthesized expression in the last regexp.
- Value is nil if NUMth pair didn't match, or there were less than NUM pairs.
-Zero means the entire text matched by the whole regexp or whole string.
-STRING should be given if the last search was by `string-match' on STRING."
- (if (match-beginning num)
- (if string
- (substring string (match-beginning num) (match-end num))
- (buffer-substring (match-beginning num) (match-end num))))))
-
-(or (fboundp 'facep)
- ;; Introduced in Emacs 19.29.
- (defun facep (x)
- "Return t if X is a face name or an internal face vector."
- (and (or (and (fboundp 'internal-facep) (internal-facep x))
- (and
- (symbolp x)
- (assq x (and (boundp 'global-face-data) global-face-data))))
- t)))
-
-;; XEmacs and Emacs 19.29 facep does different things.
-(if (fboundp 'find-face)
- (fset 'custom-facep 'find-face)
- (fset 'custom-facep 'facep))
-
-(if (custom-facep 'underline)
- ()
- ;; No underline face in XEmacs 19.12.
- (and (fboundp 'make-face)
- (funcall (intern "make-face") 'underline))
- ;; Must avoid calling set-face-underline-p directly, because it
- ;; is a defsubst in emacs19, and will make the .elc files non
- ;; portable!
- (or (and (fboundp 'face-differs-from-default-p)
- (face-differs-from-default-p 'underline))
- (and (fboundp 'set-face-underline-p)
- (funcall 'set-face-underline-p 'underline t))))
-
-(defun custom-xmas-set-text-properties (start end props &optional buffer)
- (if (null buffer)
- (if props
- (while props
- (custom-put-text-property
- start end (car props) (nth 1 props) buffer)
- (setq props (nthcdr 2 props)))
- (remove-text-properties start end ()))))
-
-(or (fboundp 'event-point)
- ;; Missing in Emacs 19.29.
- (defun event-point (event)
- "Return the character position of the given mouse-motion, button-press,
-or button-release event. If the event did not occur over a window, or did
-not occur over text, then this returns nil. Otherwise, it returns an index
-into the buffer visible in the event's window."
- (posn-point (event-start event))))
-
-(eval-when-compile
- (defvar x-colors nil)
- (defvar custom-button-face nil)
- (defvar custom-field-uninitialized-face nil)
- (defvar custom-field-invalid-face nil)
- (defvar custom-field-modified-face nil)
- (defvar custom-field-face nil)
- (defvar custom-mouse-face nil)
- (defvar custom-field-active-face nil))
-
-;; We can't easily check for a working intangible.
-(defconst intangible (if (and (boundp 'emacs-minor-version)
- (or (> emacs-major-version 19)
- (and (> emacs-major-version 18)
- (> emacs-minor-version 28))))
- (setq intangible 'intangible)
- (setq intangible 'intangible-if-it-had-been-working))
- "The symbol making text intangible.")
-
-(defconst rear-nonsticky (if (string-match "XEmacs" emacs-version)
- 'end-open
- 'rear-nonsticky)
- "The symbol making text properties non-sticky in the rear end.")
-
-(defconst front-sticky (if (string-match "XEmacs" emacs-version)
- 'front-closed
- 'front-sticky)
- "The symbol making text properties sticky in the front.")
-
-(defconst mouse-face (if (string-match "XEmacs" emacs-version)
- 'highlight
- 'mouse-face)
- "Symbol used for highlighting text under mouse.")
-
-;; Put it in the Help menu, if possible.
-(if (string-match "XEmacs" emacs-version)
- (if (featurep 'menubar)
- ;; XEmacs (disabled because it doesn't work)
- (and current-menubar
- (add-menu-item '("Help") "Customize..." 'customize t)))
- ;; Emacs 19.28 and earlier
- (global-set-key [ menu-bar help customize ]
- '("Customize..." . customize))
- ;; Emacs 19.29 and later
- (global-set-key [ menu-bar help-menu customize ]
- '("Customize..." . customize)))
-
-;; XEmacs popup-menu stolen from w3.el.
-(defun custom-x-really-popup-menu (pos title menudesc)
- "My hacked up function to do a blocking popup menu..."
- (let ((echo-keystrokes 0)
- event menu)
- (while menudesc
- (setq menu (cons (vector (car (car menudesc))
- (list (car (car menudesc))) t) menu)
- menudesc (cdr menudesc)))
- (setq menu (cons title menu))
- (popup-menu menu)
- (catch 'popup-done
- (while t
- (setq event (next-command-event event))
- (cond ((and (misc-user-event-p event) (stringp (car-safe (event-object event))))
- (throw 'popup-done (event-object event)))
- ((and (misc-user-event-p event)
- (or (eq (event-object event) 'abort)
- (eq (event-object event) 'menu-no-selection-hook)))
- nil)
- ((not (popup-menu-up-p))
- (throw 'popup-done nil))
- ((button-release-event-p event);; don't beep twice
- nil)
- (t
- (beep)
- (message "please make a choice from the menu.")))))))
-
-;;; Categories:
-;;
-;; XEmacs use inheritable extents for the same purpose as Emacs uses
-;; the category text property.
-
-(if (string-match "XEmacs" emacs-version)
- (progn
- ;; XEmacs categories.
- (defun custom-category-create (name)
- (set name (make-extent nil nil))
- "Create a text property category named NAME.")
-
- (defun custom-category-put (name property value)
- "In CATEGORY set PROPERTY to VALUE."
- (set-extent-property (symbol-value name) property value))
-
- (defun custom-category-get (name property)
- "In CATEGORY get PROPERTY."
- (extent-property (symbol-value name) property))
-
- (defun custom-category-set (from to category)
- "Make text between FROM and TWO have category CATEGORY."
- (let ((extent (make-extent from to)))
- (set-extent-parent extent (symbol-value category)))))
-
- ;; Emacs categories.
- (defun custom-category-create (name)
- "Create a text property category named NAME."
- (set name name))
-
- (defun custom-category-put (name property value)
- "In CATEGORY set PROPERTY to VALUE."
- (put name property value))
-
- (defun custom-category-get (name property)
- "In CATEGORY get PROPERTY."
- (get name property))
-
- (defun custom-category-set (from to category)
- "Make text between FROM and TWO have category CATEGORY."
- (custom-put-text-property from to 'category category)))
-
-;;; External Data:
-;;
-;; The following functions and variables defines the interface for
-;; connecting a CUSTOM with an external entity, by default an emacs
-;; lisp variable.
-
-(defvar custom-external 'default-value
- "Function returning the external value of NAME.")
-
-(defvar custom-external-set 'set-default
- "Function setting the external value of NAME to VALUE.")
-
-(defun custom-external (name)
- "Get the external value associated with NAME."
- (funcall custom-external name))
-
-(defun custom-external-set (name value)
- "Set the external value associated with NAME to VALUE."
- (funcall custom-external-set name value))
-
-(defvar custom-name-fields nil
- "Alist of custom names and their associated editing field.")
-(make-variable-buffer-local 'custom-name-fields)
-
-(defun custom-name-enter (name field)
- "Associate NAME with FIELD."
- (if (null name)
- ()
- (custom-assert 'field)
- (setq custom-name-fields (cons (cons name field) custom-name-fields))))
-
-(defun custom-name-field (name)
- "The editing field associated with NAME."
- (cdr (assq name custom-name-fields)))
-
-(defun custom-name-value (name)
- "The value currently displayed for NAME in the customization buffer."
- (let* ((field (custom-name-field name))
- (custom (custom-field-custom field)))
- (custom-field-parse field)
- (funcall (custom-property custom 'export) custom
- (car (custom-field-extract custom field)))))
-
-(defvar custom-save 'custom-save
- "Function that will save current customization buffer.")
-
-;;; Custom Functions:
-;;
-;; The following functions are part of the public interface to the
-;; CUSTOM datastructure. Each CUSTOM describes a group of variables,
-;; a single variable, or a component of a structured variable. The
-;; CUSTOM instances are part of two hierarchies, the first is the
-;; `part-of' hierarchy in which each CUSTOM is a component of another
-;; CUSTOM, except for the top level CUSTOM which is contained in
-;; `custom-data'. The second hierarchy is a `is-a' type hierarchy
-;; where each CUSTOM is a leaf in the hierarchy defined by the `type'
-;; property and `custom-type-properties'.
-
-(defvar custom-file "~/.custom.el"
- "Name of file with customization information.")
-
-(defconst custom-data
- '((tag . "Emacs")
- (doc . "The extensible self-documenting text editor.")
- (type . group)
- (data "\n"
- ((header . nil)
- (compact . t)
- (type . group)
- (doc . "\
-Press [Save] to save any changes permanently after you are done editing.
-You can load customization information from other files by editing the
-`File' field and pressing the [Load] button. When you press [Save] the
-customization information of all files you have loaded, plus any
-changes you might have made manually, will be stored in the file
-specified by the `File' field.")
- (data ((tag . "Load")
- (type . button)
- (query . custom-load))
- ((tag . "Save")
- (type . button)
- (query . custom-save))
- ((name . custom-file)
- (default . "~/.custom.el")
- (doc . "Name of file with customization information.\n")
- (tag . "File")
- (type . file))))))
- "The global customization information.
-A custom association list.")
-
-(defun custom-declare (path custom)
- "Declare variables for customization.
-PATH is a list of tags leading to the place in the customization
-hierarchy the new entry should be added. CUSTOM is the entry to add."
- (custom-initialize custom)
- (let ((current (custom-travel-path custom-data path)))
- (or (member custom (custom-data current))
- (nconc (custom-data current) (list custom)))))
-
-(put 'custom-declare 'lisp-indent-hook 1)
-
-(defconst custom-type-properties
- '((repeat (type . default)
- ;; See `custom-match'.
- (import . custom-repeat-import)
- (eval . custom-repeat-eval)
- (quote . custom-repeat-quote)
- (accept . custom-repeat-accept)
- (extract . custom-repeat-extract)
- (validate . custom-repeat-validate)
- (insert . custom-repeat-insert)
- (match . custom-repeat-match)
- (query . custom-repeat-query)
- (prefix . "")
- (del-tag . "[DEL]")
- (add-tag . "[INS]"))
- (pair (type . group)
- ;; A cons-cell.
- (accept . custom-pair-accept)
- (eval . custom-pair-eval)
- (import . custom-pair-import)
- (quote . custom-pair-quote)
- (valid . (lambda (c d) (consp d)))
- (extract . custom-pair-extract))
- (list (type . group)
- ;; A lisp list.
- (quote . custom-list-quote)
- (valid . (lambda (c d)
- (listp d)))
- (extract . custom-list-extract))
- (group (type . default)
- ;; See `custom-match'.
- (face-tag . nil)
- (eval . custom-group-eval)
- (import . custom-group-import)
- (initialize . custom-group-initialize)
- (apply . custom-group-apply)
- (reset . custom-group-reset)
- (factory-reset . custom-group-factory-reset)
- (extract . nil)
- (validate . custom-group-validate)
- (query . custom-toggle-hide)
- (accept . custom-group-accept)
- (insert . custom-group-insert)
- (find . custom-group-find))
- (toggle (type . choice)
- ;; Booleans.
- (data ((type . const)
- (tag . "On ")
- (default . t))
- ((type . const)
- (tag . "Off")
- (default . nil))))
- (triggle (type . choice)
- ;; On/Off/Default.
- (data ((type . const)
- (tag . "On ")
- (default . t))
- ((type . const)
- (tag . "Off")
- (default . nil))
- ((type . const)
- (tag . "Def")
- (default . custom:asis))))
- (choice (type . default)
- ;; See `custom-match'.
- (query . custom-choice-query)
- (accept . custom-choice-accept)
- (extract . custom-choice-extract)
- (validate . custom-choice-validate)
- (insert . custom-choice-insert)
- (none (tag . "Unknown")
- (default . __uninitialized__)
- (type . const)))
- (const (type . default)
- ;; A `const' only matches a single lisp value.
- (extract . (lambda (c f) (list (custom-default c))))
- (validate . (lambda (c f) nil))
- (valid . custom-const-valid)
- (update . custom-const-update)
- (insert . custom-const-insert))
- (face-doc (type . doc)
- ;; A variable containing a face.
- (doc . "\
-You can customize the look of Emacs by deciding which faces should be
-used when. If you push one of the face buttons below, you will be
-given a choice between a number of standard faces. The name of the
-selected face is shown right after the face button, and it is
-displayed its own face so you can see how it looks. If you know of
-another standard face not listed and want to use it, you can select
-`Other' and write the name in the editing field.
-
-If none of the standard faces suits you, you can select `Customize' to
-create your own face. This will make six fields appear under the face
-button. The `Fg' and `Bg' fields are the foreground and background
-colors for the face, respectively. You should type the name of the
-color in the field. You can use any X11 color name. A list of X11
-color names may be available in the file `/usr/lib/X11/rgb.txt' on
-your system. The special color name `default' means that the face
-will not change the color of the text. The `Stipple' field is weird,
-so just ignore it. The three remaining fields are toggles, which will
-make the text `bold', `italic', or `underline' respectively. For some
-fonts `bold' or `italic' will not make any visible change."))
- (face (type . choice)
- (eval . custom-face-eval)
- (import . custom-face-import)
- (data ((tag . "None")
- (default . nil)
- (type . const))
- ((tag . "Default")
- (default . default)
- (face . custom-const-face)
- (type . const))
- ((tag . "Bold")
- (default . bold)
- (face . custom-const-face)
- (type . const))
- ((tag . "Bold-italic")
- (default . bold-italic)
- (face . custom-const-face)
- (type . const))
- ((tag . "Italic")
- (default . italic)
- (face . custom-const-face)
- (type . const))
- ((tag . "Underline")
- (default . underline)
- (face . custom-const-face)
- (type . const))
- ((tag . "Highlight")
- (default . highlight)
- (face . custom-const-face)
- (type . const))
- ((tag . "Modeline")
- (default . modeline)
- (face . custom-const-face)
- (type . const))
- ((tag . "Region")
- (default . region)
- (face . custom-const-face)
- (type . const))
- ((tag . "Secondary Selection")
- (default . secondary-selection)
- (face . custom-const-face)
- (type . const))
- ((tag . "Customized")
- (compact . t)
- (face-tag . custom-face-hack)
- (eval . custom-face-eval)
- (data ((hidden . t)
- (tag . "")
- (doc . "\
-Select the properties you want this face to have.")
- (default . custom-face-lookup)
- (type . const))
- "\n"
- ((tag . "Fg")
- (hidden . t)
- (default . "default")
- (width . 20)
- (type . string))
- ((tag . "Bg")
- (default . "default")
- (width . 20)
- (type . string))
- ((tag . "Stipple")
- (default . "default")
- (width . 20)
- (type . string))
- "\n"
- ((tag . "Bold")
- (default . custom:asis)
- (type . triggle))
- " "
- ((tag . "Italic")
- (default . custom:asis)
- (type . triggle))
- " "
- ((tag . "Underline")
- (hidden . t)
- (default . custom:asis)
- (type . triggle)))
- (default . (custom-face-lookup "default" "default" "default"
- nil nil nil))
- (type . list))
- ((prompt . "Other")
- (face . custom-field-value)
- (default . __uninitialized__)
- (type . symbol))))
- (file (type . string)
- ;; A string containing a file or directory name.
- (directory . nil)
- (default-file . nil)
- (query . custom-file-query))
- (sexp (type . default)
- ;; Any lisp expression.
- (width . 40)
- (default . (__uninitialized__ . "Uninitialized"))
- (read . custom-sexp-read)
- (write . custom-sexp-write))
- (symbol (type . sexp)
- ;; A lisp symbol.
- (width . 40)
- (valid . (lambda (c d) (symbolp d))))
- (integer (type . sexp)
- ;; A lisp integer.
- (width . 10)
- (valid . (lambda (c d) (integerp d))))
- (string (type . default)
- ;; A lisp string.
- (width . 40)
- (valid . (lambda (c d) (stringp d)))
- (read . custom-string-read)
- (write . custom-string-write))
- (button (type . default)
- ;; Push me.
- (accept . ignore)
- (extract . nil)
- (validate . ignore)
- (insert . custom-button-insert))
- (doc (type . default)
- ;; A documentation only entry with no value.
- (header . nil)
- (reset . ignore)
- (extract . nil)
- (validate . ignore)
- (insert . custom-documentation-insert))
- (default (width . 20)
- (valid . (lambda (c v) t))
- (insert . custom-default-insert)
- (update . custom-default-update)
- (query . custom-default-query)
- (tag . nil)
- (prompt . nil)
- (doc . nil)
- (header . t)
- (padding . ? )
- (quote . custom-default-quote)
- (eval . (lambda (c v) nil))
- (export . custom-default-export)
- (import . (lambda (c v) (list v)))
- (synchronize . ignore)
- (initialize . custom-default-initialize)
- (extract . custom-default-extract)
- (validate . custom-default-validate)
- (apply . custom-default-apply)
- (reset . custom-default-reset)
- (factory-reset . custom-default-factory-reset)
- (accept . custom-default-accept)
- (match . custom-default-match)
- (name . nil)
- (compact . nil)
- (hidden . nil)
- (face . custom-default-face)
- (data . nil)
- (calculate . nil)
- (default . __uninitialized__)))
- "Alist of default properties for type symbols.
-The format is `((SYMBOL (PROPERTY . VALUE)... )... )'.")
-
-(defconst custom-local-type-properties nil
- "Local type properties.
-Entries in this list take precedence over `custom-type-properties'.")
-
-(make-variable-buffer-local 'custom-local-type-properties)
-
-(defconst custom-nil '__uninitialized__
- "Special value representing an uninitialized field.")
-
-(defconst custom-invalid '__invalid__
- "Special value representing an invalid field.")
-
-(defconst custom:asis 'custom:asis)
-;; Bad, ugly, and horrible kludge.
-
-(defun custom-property (custom property)
- "Extract from CUSTOM property PROPERTY."
- (let ((entry (assq property custom)))
- (while (null entry)
- ;; Look in superclass.
- (let ((type (custom-type custom)))
- (setq custom (cdr (or (assq type custom-local-type-properties)
- (assq type custom-type-properties)))
- entry (assq property custom))
- (custom-assert 'custom)))
- (cdr entry)))
-
-(defun custom-super (custom property)
- "Extract from CUSTOM property PROPERTY. Start with CUSTOM's superclass."
- (let ((entry nil))
- (while (null entry)
- ;; Look in superclass.
- (let ((type (custom-type custom)))
- (setq custom (cdr (or (assq type custom-local-type-properties)
- (assq type custom-type-properties)))
- entry (assq property custom))
- (custom-assert 'custom)))
- (cdr entry)))
-
-(defun custom-property-set (custom property value)
- "Set CUSTOM PROPERTY to VALUE by side effect.
-CUSTOM must have at least one property already."
- (let ((entry (assq property custom)))
- (if entry
- (setcdr entry value)
- (setcdr custom (cons (cons property value) (cdr custom))))))
-
-(defun custom-type (custom)
- "Extract `type' from CUSTOM."
- (cdr (assq 'type custom)))
-
-(defun custom-name (custom)
- "Extract `name' from CUSTOM."
- (custom-property custom 'name))
-
-(defun custom-tag (custom)
- "Extract `tag' from CUSTOM."
- (custom-property custom 'tag))
-
-(defun custom-face-tag (custom)
- "Extract `face-tag' from CUSTOM."
- (custom-property custom 'face-tag))
-
-(defun custom-prompt (custom)
- "Extract `prompt' from CUSTOM.
-If none exist, default to `tag' or, failing that, `type'."
- (or (custom-property custom 'prompt)
- (custom-property custom 'tag)
- (capitalize (symbol-name (custom-type custom)))))
-
-(defun custom-default (custom)
- "Extract `default' from CUSTOM."
- (let ((value (custom-property custom 'calculate)))
- (if value
- (eval value)
- (custom-property custom 'default))))
-
-(defun custom-data (custom)
- "Extract the `data' from CUSTOM."
- (custom-property custom 'data))
-
-(defun custom-documentation (custom)
- "Extract `doc' from CUSTOM."
- (custom-property custom 'doc))
-
-(defun custom-width (custom)
- "Extract `width' from CUSTOM."
- (custom-property custom 'width))
-
-(defun custom-compact (custom)
- "Extract `compact' from CUSTOM."
- (custom-property custom 'compact))
-
-(defun custom-padding (custom)
- "Extract `padding' from CUSTOM."
- (custom-property custom 'padding))
-
-(defun custom-valid (custom value)
- "Non-nil if CUSTOM may validly be set to VALUE."
- (and (not (and (listp value) (eq custom-invalid (car value))))
- (funcall (custom-property custom 'valid) custom value)))
-
-(defun custom-import (custom value)
- "Import CUSTOM VALUE from external variable.
-
-This function change VALUE into a form that makes it easier to edit
-internally. What the internal form is exactly depends on CUSTOM.
-The internal form is returned."
- (if (eq custom-nil value)
- (list custom-nil)
- (funcall (custom-property custom 'import) custom value)))
-
-(defun custom-eval (custom value)
- "Return non-nil if CUSTOM's VALUE needs to be evaluated."
- (funcall (custom-property custom 'eval) custom value))
-
-(defun custom-quote (custom value)
- "Quote CUSTOM's VALUE if necessary."
- (funcall (custom-property custom 'quote) custom value))
-
-(defun custom-write (custom value)
- "Convert CUSTOM VALUE to a string."
- (cond ((eq value custom-nil)
- "")
- ((and (listp value) (eq (car value) custom-invalid))
- (cdr value))
- (t
- (funcall (custom-property custom 'write) custom value))))
-
-(defun custom-read (custom string)
- "Convert CUSTOM field content STRING into lisp."
- (condition-case nil
- (funcall (custom-property custom 'read) custom string)
- (error (cons custom-invalid string))))
-
-(defun custom-match (custom values)
- "Match CUSTOM with a list of VALUES.
-
-Return a cons-cell where the car is the sublist of VALUES matching CUSTOM,
-and the cdr is the remaining VALUES.
-
-A CUSTOM is actually a regular expression over the alphabet of lisp
-types. Most CUSTOM types are just doing a literal match, e.g. the
-`symbol' type matches any lisp symbol. The exceptions are:
-
-group: which corresponds to a `(' and `)' group in a regular expression.
-choice: which corresponds to a group of `|' in a regular expression.
-repeat: which corresponds to a `*' in a regular expression.
-optional: which corresponds to a `?', and isn't implemented yet."
- (if (memq values (list custom-nil nil))
- ;; Nothing matches the uninitialized or empty list.
- (cons custom-nil nil)
- (funcall (custom-property custom 'match) custom values)))
-
-(defun custom-initialize (custom)
- "Initialize `doc' and `default' attributes of CUSTOM."
- (funcall (custom-property custom 'initialize) custom))
-
-(defun custom-find (custom tag)
- "Find child in CUSTOM with `tag' TAG."
- (funcall (custom-property custom 'find) custom tag))
-
-(defun custom-travel-path (custom path)
- "Find decedent of CUSTOM by looking through PATH."
- (if (null path)
- custom
- (custom-travel-path (custom-find custom (car path)) (cdr path))))
-
-(defun custom-field-extract (custom field)
- "Extract CUSTOM's value in FIELD."
- (if (stringp custom)
- nil
- (funcall (custom-property (custom-field-custom field) 'extract)
- custom field)))
-
-(defun custom-field-validate (custom field)
- "Validate CUSTOM's value in FIELD.
-Return nil if valid, otherwise return a cons-cell where the car is the
-position of the error, and the cdr is a text describing the error."
- (if (stringp custom)
- nil
- (funcall (custom-property custom 'validate) custom field)))
-
-;;; Field Functions:
-;;
-;; This section defines the public functions for manipulating the
-;; FIELD datatype. The FIELD instance hold information about a
-;; specific editing field in the customization buffer.
-;;
-;; Each FIELD can be seen as an instantiation of a CUSTOM.
-
-(defvar custom-field-last nil)
-;; Last field containing point.
-(make-variable-buffer-local 'custom-field-last)
-
-(defvar custom-modified-list nil)
-;; List of modified fields.
-(make-variable-buffer-local 'custom-modified-list)
-
-(defun custom-field-create (custom value)
- "Create a field structure of type CUSTOM containing VALUE.
-
-A field structure is an array [ CUSTOM VALUE ORIGINAL START END ], where
-CUSTOM defines the type of the field,
-VALUE is the current value of the field,
-ORIGINAL is the original value when created, and
-START and END are markers to the start and end of the field."
- (vector custom value custom-nil nil nil))
-
-(defun custom-field-custom (field)
- "Return the `custom' attribute of FIELD."
- (aref field 0))
-
-(defun custom-field-value (field)
- "Return the `value' attribute of FIELD."
- (aref field 1))
-
-(defun custom-field-original (field)
- "Return the `original' attribute of FIELD."
- (aref field 2))
-
-(defun custom-field-start (field)
- "Return the `start' attribute of FIELD."
- (aref field 3))
-
-(defun custom-field-end (field)
- "Return the `end' attribute of FIELD."
- (aref field 4))
-
-(defun custom-field-value-set (field value)
- "Set the `value' attribute of FIELD to VALUE."
- (aset field 1 value))
-
-(defun custom-field-original-set (field original)
- "Set the `original' attribute of FIELD to ORIGINAL."
- (aset field 2 original))
-
-(defun custom-field-move (field start end)
- "Set the `start'and `end' attributes of FIELD to START and END."
- (set-marker (or (aref field 3) (aset field 3 (make-marker))) start)
- (set-marker (or (aref field 4) (aset field 4 (make-marker))) end))
-
-(defun custom-field-query (field)
- "Query user for content of current field."
- (funcall (custom-property (custom-field-custom field) 'query) field))
-
-(defun custom-field-accept (field value &optional original)
- "Store a new value into field FIELD, taking it from VALUE.
-If optional ORIGINAL is non-nil, consider VALUE for the original value."
- (let ((inhibit-point-motion-hooks t))
- (funcall (custom-property (custom-field-custom field) 'accept)
- field value original)))
-
-(defun custom-field-face (field)
- "The face used for highlighting FIELD."
- (let ((custom (custom-field-custom field)))
- (if (stringp custom)
- nil
- (let ((face (funcall (custom-property custom 'face) field)))
- (if (custom-facep face) face nil)))))
-
-(defun custom-field-update (field)
- "Update the screen appearance of FIELD to correspond with the field's value."
- (let ((custom (custom-field-custom field)))
- (if (stringp custom)
- nil
- (funcall (custom-property custom 'update) field))))
-
-;;; Types:
-;;
-;; The following functions defines type specific actions.
-
-(defun custom-repeat-eval (custom value)
- "Non-nil if CUSTOM's VALUE needs to be evaluated."
- (if (eq value custom-nil)
- nil
- (let ((child (custom-data custom))
- (found nil))
- (mapcar (lambda (v) (if (custom-eval child v) (setq found t)))
- value))))
-
-(defun custom-repeat-quote (custom value)
- "A list of CUSTOM's VALUEs quoted."
- (let ((child (custom-data custom)))
- (apply 'append (mapcar (lambda (v) (custom-quote child v))
- value))))
-
-
-(defun custom-repeat-import (custom value)
- "Modify CUSTOM's VALUE to match internal expectations."
- (let ((child (custom-data custom)))
- (apply 'append (mapcar (lambda (v) (custom-import child v))
- value))))
-
-(defun custom-repeat-accept (field value &optional original)
- "Store a new value into field FIELD, taking it from VALUE."
- (let ((values (copy-sequence (custom-field-value field)))
- (all (custom-field-value field))
- (start (custom-field-start field))
- current new)
- (if original
- (custom-field-original-set field value))
- (while (consp value)
- (setq new (car value)
- value (cdr value))
- (if values
- ;; Change existing field.
- (setq current (car values)
- values (cdr values))
- ;; Insert new field if series has grown.
- (goto-char start)
- (setq current (custom-repeat-insert-entry field))
- (setq all (custom-insert-before all nil current))
- (custom-field-value-set field all))
- (custom-field-accept current new original))
- (while (consp values)
- ;; Delete old field if series has scrunk.
- (setq current (car values)
- values (cdr values))
- (let ((pos (custom-field-start current))
- data)
- (while (not data)
- (setq pos (previous-single-property-change pos 'custom-data))
- (custom-assert 'pos)
- (setq data (get-text-property pos 'custom-data))
- (or (and (arrayp data)
- (> (length data) 1)
- (eq current (aref data 1)))
- (setq data nil)))
- (custom-repeat-delete data)))))
-
-(defun custom-repeat-insert (custom level)
- "Insert field for CUSTOM at nesting LEVEL in customization buffer."
- (let* ((field (custom-field-create custom nil))
- (add-tag (custom-property custom 'add-tag))
- (start (make-marker))
- (data (vector field nil start nil)))
- (custom-text-insert "\n")
- (let ((pos (point)))
- (custom-text-insert (custom-property custom 'prefix))
- (custom-tag-insert add-tag 'custom-repeat-add data)
- (set-marker start pos))
- (custom-field-move field start (point))
- (custom-documentation-insert custom)
- field))
-
-(defun custom-repeat-insert-entry (repeat)
- "Insert entry at point in the REPEAT field."
- (let* ((inhibit-point-motion-hooks t)
- (inhibit-read-only t)
- (before-change-functions nil)
- (after-change-functions nil)
- (custom (custom-field-custom repeat))
- (add-tag (custom-property custom 'add-tag))
- (del-tag (custom-property custom 'del-tag))
- (start (make-marker))
- (end (make-marker))
- (data (vector repeat nil start end))
- field)
- (custom-extent-start-open)
- (insert-before-markers "\n")
- (backward-char 1)
- (set-marker start (point))
- (custom-text-insert " ")
- (aset data 1 (setq field (custom-insert (custom-data custom) nil)))
- (custom-text-insert " ")
- (set-marker end (point))
- (goto-char start)
- (custom-text-insert (custom-property custom 'prefix))
- (custom-tag-insert add-tag 'custom-repeat-add data)
- (custom-text-insert " ")
- (custom-tag-insert del-tag 'custom-repeat-delete data)
- (forward-char 1)
- field))
-
-(defun custom-repeat-add (data)
- "Add list entry."
- (let ((parent (aref data 0))
- (field (aref data 1))
- (at (aref data 2))
- new)
- (goto-char at)
- (setq new (custom-repeat-insert-entry parent))
- (custom-field-value-set parent
- (custom-insert-before (custom-field-value parent)
- field new))))
-
-(defun custom-repeat-delete (data)
- "Delete list entry."
- (let ((inhibit-point-motion-hooks t)
- (inhibit-read-only t)
- (before-change-functions nil)
- (after-change-functions nil)
- (parent (aref data 0))
- (field (aref data 1)))
- (delete-region (aref data 2) (1+ (aref data 3)))
- (custom-field-untouch (aref data 1))
- (custom-field-value-set parent
- (delq field (custom-field-value parent)))))
-
-(defun custom-repeat-match (custom values)
- "Match CUSTOM with VALUES."
- (let* ((child (custom-data custom))
- (match (custom-match child values))
- matches)
- (while (not (eq (car match) custom-nil))
- (setq matches (cons (car match) matches)
- values (cdr match)
- match (custom-match child values)))
- (cons (nreverse matches) values)))
-
-(defun custom-repeat-extract (custom field)
- "Extract list of children's values."
- (let ((values (custom-field-value field))
- (data (custom-data custom))
- result)
- (if (eq values custom-nil)
- ()
- (while values
- (setq result (append result (custom-field-extract data (car values)))
- values (cdr values))))
- result))
-
-(defun custom-repeat-validate (custom field)
- "Validate children."
- (let ((values (custom-field-value field))
- (data (custom-data custom))
- result)
- (if (eq values custom-nil)
- (setq result (cons (custom-field-start field) "Uninitialized list")))
- (while (and values (not result))
- (setq result (custom-field-validate data (car values))
- values (cdr values)))
- result))
-
-(defun custom-pair-accept (field value &optional original)
- "Store a new value into field FIELD, taking it from VALUE."
- (custom-group-accept field (list (car value) (cdr value)) original))
-
-(defun custom-pair-eval (custom value)
- "Non-nil if CUSTOM's VALUE needs to be evaluated."
- (custom-group-eval custom (list (car value) (cdr value))))
-
-(defun custom-pair-import (custom value)
- "Modify CUSTOM's VALUE to match internal expectations."
- (let ((result (car (custom-group-import custom
- (list (car value) (cdr value))))))
- (custom-assert '(eq (length result) 2))
- (list (cons (nth 0 result) (nth 1 result)))))
-
-(defun custom-pair-quote (custom value)
- "Quote CUSTOM's VALUE if necessary."
- (if (custom-eval custom value)
- (let ((v (car (custom-group-quote custom
- (list (car value) (cdr value))))))
- (list (list 'cons (nth 0 v) (nth 1 v))))
- (custom-default-quote custom value)))
-
-(defun custom-pair-extract (custom field)
- "Extract cons of children's values."
- (let ((values (custom-field-value field))
- (data (custom-data custom))
- result)
- (custom-assert '(eq (length values) (length data)))
- (while values
- (setq result (append result
- (custom-field-extract (car data) (car values)))
- data (cdr data)
- values (cdr values)))
- (custom-assert '(null data))
- (list (cons (nth 0 result) (nth 1 result)))))
-
-(defun custom-list-quote (custom value)
- "Quote CUSTOM's VALUE if necessary."
- (if (custom-eval custom value)
- (let ((v (car (custom-group-quote custom value))))
- (list (cons 'list v)))
- (custom-default-quote custom value)))
-
-(defun custom-list-extract (custom field)
- "Extract list of children's values."
- (let ((values (custom-field-value field))
- (data (custom-data custom))
- result)
- (custom-assert '(eq (length values) (length data)))
- (while values
- (setq result (append result
- (custom-field-extract (car data) (car values)))
- data (cdr data)
- values (cdr values)))
- (custom-assert '(null data))
- (list result)))
-
-(defun custom-group-validate (custom field)
- "Validate children."
- (let ((values (custom-field-value field))
- (data (custom-data custom))
- result)
- (if (eq values custom-nil)
- (setq result (cons (custom-field-start field) "Uninitialized list"))
- (custom-assert '(eq (length values) (length data))))
- (while (and values (not result))
- (setq result (custom-field-validate (car data) (car values))
- data (cdr data)
- values (cdr values)))
- result))
-
-(defun custom-group-eval (custom value)
- "Non-nil if CUSTOM's VALUE needs to be evaluated."
- (let ((found nil))
- (mapcar (lambda (c)
- (or (stringp c)
- (let ((match (custom-match c value)))
- (if (custom-eval c (car match))
- (setq found t))
- (setq value (cdr match)))))
- (custom-data custom))
- found))
-
-(defun custom-group-quote (custom value)
- "A list of CUSTOM's VALUE members, quoted."
- (list (apply 'append
- (mapcar (lambda (c)
- (if (stringp c)
- ()
- (let ((match (custom-match c value)))
- (prog1 (custom-quote c (car match))
- (setq value (cdr match))))))
- (custom-data custom)))))
-
-(defun custom-group-import (custom value)
- "Modify CUSTOM's VALUE to match internal expectations."
- (list (apply 'append
- (mapcar (lambda (c)
- (if (stringp c)
- ()
- (let ((match (custom-match c value)))
- (prog1 (custom-import c (car match))
- (setq value (cdr match))))))
- (custom-data custom)))))
-
-(defun custom-group-initialize (custom)
- "Initialize `doc' and `default' entries in CUSTOM."
- (if (custom-name custom)
- (custom-default-initialize custom)
- (mapcar 'custom-initialize (custom-data custom))))
-
-(defun custom-group-apply (field)
- "Reset `value' in FIELD to `original'."
- (let ((custom (custom-field-custom field))
- (values (custom-field-value field)))
- (if (custom-name custom)
- (custom-default-apply field)
- (mapcar 'custom-field-apply values))))
-
-(defun custom-group-reset (field)
- "Reset `value' in FIELD to `original'."
- (let ((custom (custom-field-custom field))
- (values (custom-field-value field)))
- (if (custom-name custom)
- (custom-default-reset field)
- (mapcar 'custom-field-reset values))))
-
-(defun custom-group-factory-reset (field)
- "Reset `value' in FIELD to `default'."
- (let ((custom (custom-field-custom field))
- (values (custom-field-value field)))
- (if (custom-name custom)
- (custom-default-factory-reset field)
- (mapcar 'custom-field-factory-reset values))))
-
-(defun custom-group-find (custom tag)
- "Find child in CUSTOM with `tag' TAG."
- (let ((data (custom-data custom))
- (result nil))
- (while (not result)
- (custom-assert 'data)
- (if (equal (custom-tag (car data)) tag)
- (setq result (car data))
- (setq data (cdr data))))))
-
-(defun custom-group-accept (field value &optional original)
- "Store a new value into field FIELD, taking it from VALUE."
- (let* ((values (custom-field-value field))
- (custom (custom-field-custom field))
- (from (custom-field-start field))
- (face-tag (custom-face-tag custom))
- current)
- (if face-tag
- (custom-put-text-property from (+ from (length (custom-tag custom)))
- 'face (funcall face-tag field value)))
- (if original
- (custom-field-original-set field value))
- (while values
- (setq current (car values)
- values (cdr values))
- (if current
- (let* ((custom (custom-field-custom current))
- (match (custom-match custom value)))
- (setq value (cdr match))
- (custom-field-accept current (car match) original))))))
-
-(defun custom-group-insert (custom level)
- "Insert field for CUSTOM at nesting LEVEL in customization buffer."
- (let* ((field (custom-field-create custom nil))
- fields hidden
- (from (point))
- (compact (custom-compact custom))
- (tag (custom-tag custom))
- (face-tag (custom-face-tag custom)))
- (cond (face-tag (custom-text-insert tag))
- (tag (custom-tag-insert tag field)))
- (or compact (custom-documentation-insert custom))
- (or compact (custom-text-insert "\n"))
- (let ((data (custom-data custom)))
- (while data
- (setq fields (cons (custom-insert (car data) (if level (1+ level)))
- fields))
- (setq hidden (or (stringp (car data))
- (custom-property (car data) 'hidden)))
- (setq data (cdr data))
- (if data (custom-text-insert (cond (hidden "")
- (compact " ")
- (t "\n"))))))
- (if compact (custom-documentation-insert custom))
- (custom-field-value-set field (nreverse fields))
- (custom-field-move field from (point))
- field))
-
-(defun custom-choice-insert (custom level)
- "Insert field for CUSTOM at nesting LEVEL in customization buffer."
- (let* ((field (custom-field-create custom nil))
- (from (point)))
- (custom-text-insert "lars er en nisse")
- (custom-field-move field from (point))
- (custom-documentation-insert custom)
- (custom-field-reset field)
- field))
-
-(defun custom-choice-accept (field value &optional original)
- "Store a new value into field FIELD, taking it from VALUE."
- (let ((custom (custom-field-custom field))
- (start (custom-field-start field))
- (end (custom-field-end field))
- (inhibit-read-only t)
- (before-change-functions nil)
- (after-change-functions nil)
- from)
- (cond (original
- (setq custom-modified-list (delq field custom-modified-list))
- (custom-field-original-set field value))
- ((equal value (custom-field-original field))
- (setq custom-modified-list (delq field custom-modified-list)))
- (t
- (add-to-list 'custom-modified-list field)))
- (custom-field-untouch (custom-field-value field))
- (delete-region start end)
- (goto-char start)
- (setq from (point))
- (insert-before-markers " ")
- (backward-char 1)
- (custom-category-set (point) (1+ (point)) 'custom-hidden-properties)
- (custom-tag-insert (custom-tag custom) field)
- (custom-text-insert ": ")
- (let ((data (custom-data custom))
- found begin)
- (while (and data (not found))
- (if (not (custom-valid (car data) value))
- (setq data (cdr data))
- (setq found (custom-insert (car data) nil))
- (setq data nil)))
- (if found
- ()
- (setq begin (point)
- found (custom-insert (custom-property custom 'none) nil))
- (custom-add-text-properties
- begin (point)
- (list rear-nonsticky t
- 'face custom-field-uninitialized-face)))
- (or original
- (custom-field-original-set found (custom-field-original field)))
- (custom-field-accept found value original)
- (custom-field-value-set field found)
- (custom-field-move field from end))))
-
-(defun custom-choice-extract (custom field)
- "Extract child's value."
- (let ((value (custom-field-value field)))
- (custom-field-extract (custom-field-custom value) value)))
-
-(defun custom-choice-validate (custom field)
- "Validate child's value."
- (let ((value (custom-field-value field))
- (custom (custom-field-custom field)))
- (if (or (eq value custom-nil)
- (eq (custom-field-custom value) (custom-property custom 'none)))
- (cons (custom-field-start field) "Make a choice")
- (custom-field-validate (custom-field-custom value) value))))
-
-(defun custom-choice-query (field)
- "Choose a child."
- (let* ((custom (custom-field-custom field))
- (old (custom-field-custom (custom-field-value field)))
- (default (custom-prompt old))
- (tag (custom-prompt custom))
- (data (custom-data custom))
- current alist)
- (if (eq (length data) 2)
- (custom-field-accept field (custom-default (if (eq (nth 0 data) old)
- (nth 1 data)
- (nth 0 data))))
- (while data
- (setq current (car data)
- data (cdr data))
- (setq alist (cons (cons (custom-prompt current) current) alist)))
- (let ((answer (cond ((and (fboundp 'button-press-event-p)
- (fboundp 'popup-menu)
- (button-press-event-p last-input-event))
- (cdr (assoc (car (custom-x-really-popup-menu
- last-input-event tag
- (reverse alist)))
- alist)))
- ((listp last-input-event)
- (x-popup-menu last-input-event
- (list tag (cons "" (reverse alist)))))
- (t
- (let ((choice (completing-read (concat tag
- " (default "
- default
- "): ")
- alist nil t)))
- (if (or (null choice) (string-equal choice ""))
- (setq choice default))
- (cdr (assoc choice alist)))))))
- (if answer
- (custom-field-accept field (custom-default answer)))))))
-
-(defun custom-file-query (field)
- "Prompt for a file name"
- (let* ((value (custom-field-value field))
- (custom (custom-field-custom field))
- (valid (custom-valid custom value))
- (directory (custom-property custom 'directory))
- (default (and (not valid)
- (custom-property custom 'default-file)))
- (tag (custom-tag custom))
- (prompt (if default
- (concat tag " (" default "): ")
- (concat tag ": "))))
- (custom-field-accept field
- (if (custom-valid custom value)
- (read-file-name prompt
- (if (file-name-absolute-p value)
- ""
- directory)
- default nil value)
- (read-file-name prompt directory default)))))
-
-(defun custom-face-eval (custom value)
- "Return non-nil if CUSTOM's VALUE needs to be evaluated."
- (not (symbolp value)))
-
-(defun custom-face-import (custom value)
- "Modify CUSTOM's VALUE to match internal expectations."
- (let ((name (or (and (facep value) (symbol-name (face-name value)))
- (symbol-name value))))
- (list (if (string-match "\
-custom-face-\\(.*\\)-\\(.*\\)-\\(.*\\)-\\(.*\\)-\\(.*\\)-\\(.*\\)"
- name)
- (list 'custom-face-lookup
- (match-string 1 name)
- (match-string 2 name)
- (match-string 3 name)
- (intern (match-string 4 name))
- (intern (match-string 5 name))
- (intern (match-string 6 name)))
- value))))
-
-(defun custom-face-lookup (&optional fg bg stipple bold italic underline)
- "Lookup or create a face with specified attributes."
- (let ((name (intern (format "custom-face-%s-%s-%s-%S-%S-%S"
- (or fg "default")
- (or bg "default")
- (or stipple "default")
- bold italic underline))))
- (if (and (custom-facep name)
- (fboundp 'make-face))
- ()
- (copy-face 'default name)
- (when (and fg
- (not (string-equal fg "default")))
- (condition-case ()
- (set-face-foreground name fg)
- (error nil)))
- (when (and bg
- (not (string-equal bg "default")))
- (condition-case ()
- (set-face-background name bg)
- (error nil)))
- (when (and stipple
- (not (string-equal stipple "default"))
- (not (eq stipple 'custom:asis))
- (fboundp 'set-face-stipple))
- (set-face-stipple name stipple))
- (when (and bold
- (not (eq bold 'custom:asis)))
- (condition-case ()
- (make-face-bold name)
- (error nil)))
- (when (and italic
- (not (eq italic 'custom:asis)))
- (condition-case ()
- (make-face-italic name)
- (error nil)))
- (when (and underline
- (not (eq underline 'custom:asis)))
- (condition-case ()
- (set-face-underline-p name t)
- (error nil))))
- name))
-
-(defun custom-face-hack (field value)
- "Face that should be used for highlighting FIELD containing VALUE."
- (let* ((custom (custom-field-custom field))
- (form (funcall (custom-property custom 'export) custom value))
- (face (apply (car form) (cdr form))))
- (if (custom-facep face) face nil)))
-
-(defun custom-const-insert (custom level)
- "Insert field for CUSTOM at nesting LEVEL in customization buffer."
- (let* ((field (custom-field-create custom custom-nil))
- (face (custom-field-face field))
- (from (point)))
- (custom-text-insert (custom-tag custom))
- (custom-add-text-properties from (point)
- (list 'face face
- rear-nonsticky t))
- (custom-documentation-insert custom)
- (custom-field-move field from (point))
- field))
-
-(defun custom-const-update (field)
- "Update face of FIELD."
- (let ((from (custom-field-start field))
- (custom (custom-field-custom field)))
- (custom-put-text-property from (+ from (length (custom-tag custom)))
- 'face (custom-field-face field))))
-
-(defun custom-const-valid (custom value)
- "Non-nil if CUSTOM can validly have the value VALUE."
- (equal (custom-default custom) value))
-
-(defun custom-const-face (field)
- "Face used for a FIELD."
- (custom-default (custom-field-custom field)))
-
-(defun custom-sexp-read (custom string)
- "Read from CUSTOM an STRING."
- (save-match-data
- (save-excursion
- (set-buffer (get-buffer-create " *Custom Scratch*"))
- (erase-buffer)
- (insert string)
- (goto-char (point-min))
- (prog1 (read (current-buffer))
- (or (looking-at
- (concat (regexp-quote (char-to-string
- (custom-padding custom)))
- "*\\'"))
- (error "Junk at end of expression"))))))
-
-(autoload 'pp-to-string "pp")
-
-(defun custom-sexp-write (custom sexp)
- "Write CUSTOM SEXP as string."
- (let ((string (prin1-to-string sexp)))
- (if (<= (length string) (custom-width custom))
- string
- (setq string (pp-to-string sexp))
- (string-match "[ \t\n]*\\'" string)
- (concat "\n" (substring string 0 (match-beginning 0))))))
-
-(defun custom-string-read (custom string)
- "Read string by ignoring trailing padding characters."
- (let ((last (length string))
- (padding (custom-padding custom)))
- (while (and (> last 0)
- (eq (aref string (1- last)) padding))
- (setq last (1- last)))
- (substring string 0 last)))
-
-(defun custom-string-write (custom string)
- "Write raw string."
- string)
-
-(defun custom-button-insert (custom level)
- "Insert field for CUSTOM at nesting LEVEL in customization buffer."
- (custom-tag-insert (concat "[" (custom-tag custom) "]")
- (custom-property custom 'query))
- (custom-documentation-insert custom)
- nil)
-
-(defun custom-default-export (custom value)
- ;; Convert CUSTOM's VALUE to external representation.
- ;; See `custom-import'.
- (if (custom-eval custom value)
- (eval (car (custom-quote custom value)))
- value))
-
-(defun custom-default-quote (custom value)
- "Quote CUSTOM's VALUE if necessary."
- (list (if (and (not (custom-eval custom value))
- (or (and (symbolp value)
- value
- (not (eq t value)))
- (and (listp value)
- value
- (not (memq (car value) '(quote function lambda))))))
- (list 'quote value)
- value)))
-
-(defun custom-default-initialize (custom)
- "Initialize `doc' and `default' entries in CUSTOM."
- (let ((name (custom-name custom)))
- (if (null name)
- ()
- (let ((default (custom-default custom))
- (doc (custom-documentation custom))
- (vdoc (documentation-property name 'variable-documentation t)))
- (if doc
- (or vdoc (put name 'variable-documentation doc))
- (if vdoc (custom-property-set custom 'doc vdoc)))
- (if (eq default custom-nil)
- (if (boundp name)
- (custom-property-set custom 'default (symbol-value name)))
- (or (boundp name)
- (set name default)))))))
-
-(defun custom-default-insert (custom level)
- "Insert field for CUSTOM at nesting LEVEL in customization buffer."
- (let ((field (custom-field-create custom custom-nil))
- (tag (custom-tag custom)))
- (if (null tag)
- ()
- (custom-tag-insert tag field)
- (custom-text-insert ": "))
- (custom-field-insert field)
- (custom-documentation-insert custom)
- field))
-
-(defun custom-default-accept (field value &optional original)
- "Store a new value into field FIELD, taking it from VALUE."
- (if original
- (custom-field-original-set field value))
- (custom-field-value-set field value)
- (custom-field-update field))
-
-(defun custom-default-apply (field)
- "Apply any changes in FIELD since the last apply."
- (let* ((custom (custom-field-custom field))
- (name (custom-name custom)))
- (if (null name)
- (error "This field cannot be applied alone"))
- (custom-external-set name (custom-name-value name))
- (custom-field-reset field)))
-
-(defun custom-default-reset (field)
- "Reset content of editing FIELD to `original'."
- (custom-field-accept field (custom-field-original field) t))
-
-(defun custom-default-factory-reset (field)
- "Reset content of editing FIELD to `default'."
- (let* ((custom (custom-field-custom field))
- (default (car (custom-import custom (custom-default custom)))))
- (or (eq default custom-nil)
- (custom-field-accept field default nil))))
-
-(defun custom-default-query (field)
- "Prompt for a FIELD"
- (let* ((custom (custom-field-custom field))
- (value (custom-field-value field))
- (initial (custom-write custom value))
- (prompt (concat (custom-prompt custom) ": ")))
- (custom-field-accept field
- (custom-read custom
- (if (custom-valid custom value)
- (read-string prompt (cons initial 1))
- (read-string prompt))))))
-
-(defun custom-default-match (custom values)
- "Match CUSTOM with VALUES."
- values)
-
-(defun custom-default-extract (custom field)
- "Extract CUSTOM's content in FIELD."
- (list (custom-field-value field)))
-
-(defun custom-default-validate (custom field)
- "Validate FIELD."
- (let ((value (custom-field-value field))
- (start (custom-field-start field)))
- (cond ((eq value custom-nil)
- (cons start "Uninitialized field"))
- ((and (consp value) (eq (car value) custom-invalid))
- (cons start "Unparsable field content"))
- ((custom-valid custom value)
- nil)
- (t
- (cons start "Wrong type of field content")))))
-
-(defun custom-default-face (field)
- "Face used for a FIELD."
- (let ((value (custom-field-value field)))
- (cond ((eq value custom-nil)
- custom-field-uninitialized-face)
- ((not (custom-valid (custom-field-custom field) value))
- custom-field-invalid-face)
- ((not (equal (custom-field-original field) value))
- custom-field-modified-face)
- (t
- custom-field-face))))
-
-(defun custom-default-update (field)
- "Update the content of FIELD."
- (let ((inhibit-point-motion-hooks t)
- (before-change-functions nil)
- (after-change-functions nil)
- (start (custom-field-start field))
- (end (custom-field-end field))
- (pos (point)))
- ;; Keep track of how many modified fields we have.
- (cond ((equal (custom-field-value field) (custom-field-original field))
- (setq custom-modified-list (delq field custom-modified-list)))
- ((memq field custom-modified-list))
- (t
- (setq custom-modified-list (cons field custom-modified-list))))
- ;; Update the field.
- (goto-char end)
- (insert-before-markers " ")
- (delete-region start (1- end))
- (goto-char start)
- (custom-field-insert field)
- (goto-char end)
- (delete-char 1)
- (goto-char pos)
- (and (<= start pos)
- (<= pos end)
- (custom-field-enter field))))
-
-;;; Create Buffer:
-;;
-;; Public functions to create a customization buffer and to insert
-;; various forms of text, fields, and buttons in it.
-
-(defun customize ()
- "Customize GNU Emacs.
-Create a *Customize* buffer with editable customization information
-about GNU Emacs."
- (interactive)
- (custom-buffer-create "*Customize*")
- (custom-reset-all))
-
-(defun custom-buffer-create (name &optional custom types set get save)
- "Create a customization buffer named NAME.
-If the optional argument CUSTOM is non-nil, use that as the custom declaration.
-If the optional argument TYPES is non-nil, use that as the local types.
-If the optional argument SET is non-nil, use that to set external data.
-If the optional argument GET is non-nil, use that to get external data.
-If the optional argument SAVE is non-nil, use that for saving changes."
- (switch-to-buffer name)
- (buffer-disable-undo (current-buffer))
- (custom-mode)
- (setq custom-local-type-properties types)
- (if (null custom)
- ()
- (make-local-variable 'custom-data)
- (setq custom-data custom))
- (if (null set)
- ()
- (make-local-variable 'custom-external-set)
- (setq custom-external-set set))
- (if (null get)
- ()
- (make-local-variable 'custom-external)
- (setq custom-external get))
- (if (null save)
- ()
- (make-local-variable 'custom-save)
- (setq custom-save save))
- (let ((inhibit-point-motion-hooks t)
- (before-change-functions nil)
- (after-change-functions nil))
- (erase-buffer)
- (insert "\n")
- (goto-char (point-min))
- (custom-text-insert "This is a customization buffer.\n")
- (custom-help-insert "\n")
- (custom-help-button 'custom-forward-field)
- (custom-help-button 'custom-backward-field)
- (custom-help-button 'custom-enter-value)
- (custom-help-button 'custom-field-factory-reset)
- (custom-help-button 'custom-field-reset)
- (custom-help-button 'custom-field-apply)
- (custom-help-button 'custom-save-and-exit)
- (custom-help-button 'custom-toggle-documentation)
- (custom-help-insert "\nClick mouse-2 on any button to activate it.\n")
- (custom-text-insert "\n")
- (custom-insert custom-data 0)
- (goto-char (point-min))))
-
-(defun custom-insert (custom level)
- "Insert custom declaration CUSTOM in current buffer at level LEVEL."
- (if (stringp custom)
- (progn
- (custom-text-insert custom)
- nil)
- (and level (null (custom-property custom 'header))
- (setq level nil))
- (and level
- (> level 0)
- (custom-text-insert (concat "\n" (make-string level ?*) " ")))
- (let ((field (funcall (custom-property custom 'insert) custom level)))
- (custom-name-enter (custom-name custom) field)
- field)))
-
-(defun custom-text-insert (text)
- "Insert TEXT in current buffer."
- (insert text))
-
-(defun custom-tag-insert (tag field &optional data)
- "Insert TAG for FIELD in current buffer."
- (let ((from (point)))
- (insert tag)
- (custom-category-set from (point) 'custom-button-properties)
- (custom-put-text-property from (point) 'custom-tag field)
- (if data
- (custom-add-text-properties from (point) (list 'custom-data data)))))
-
-(defun custom-documentation-insert (custom &rest ignore)
- "Insert documentation from CUSTOM in current buffer."
- (let ((doc (custom-documentation custom)))
- (if (null doc)
- ()
- (custom-help-insert "\n" doc))))
-
-(defun custom-help-insert (&rest args)
- "Insert ARGS as documentation text."
- (let ((from (point)))
- (apply 'insert args)
- (custom-category-set from (point) 'custom-documentation-properties)))
-
-(defun custom-help-button (command)
- "Describe how to execute COMMAND."
- (let ((from (point)))
- (insert "`" (key-description (where-is-internal command nil t)) "'")
- (custom-set-text-properties from (point)
- (list 'face custom-button-face
- mouse-face custom-mouse-face
- 'custom-jump t ;Make TAB jump over it.
- 'custom-tag command
- 'start-open t
- 'end-open t))
- (custom-category-set from (point) 'custom-documentation-properties))
- (custom-help-insert ": " (custom-first-line (documentation command)) "\n"))
-
-;;; Mode:
-;;
-;; The Customization major mode and interactive commands.
-
-(defvar custom-mode-map nil
- "Keymap for Custom Mode.")
-(if custom-mode-map
- nil
- (setq custom-mode-map (make-sparse-keymap))
- (define-key custom-mode-map (if (string-match "XEmacs" emacs-version) [button2] [mouse-2]) 'custom-push-button)
- (define-key custom-mode-map "\t" 'custom-forward-field)
- (define-key custom-mode-map "\M-\t" 'custom-backward-field)
- (define-key custom-mode-map "\r" 'custom-enter-value)
- (define-key custom-mode-map "\C-k" 'custom-kill-line)
- (define-key custom-mode-map "\C-c\C-r" 'custom-field-reset)
- (define-key custom-mode-map "\C-c\M-\C-r" 'custom-reset-all)
- (define-key custom-mode-map "\C-c\C-z" 'custom-field-factory-reset)
- (define-key custom-mode-map "\C-c\M-\C-z" 'custom-factory-reset-all)
- (define-key custom-mode-map "\C-c\C-a" 'custom-field-apply)
- (define-key custom-mode-map "\C-c\M-\C-a" 'custom-apply-all)
- (define-key custom-mode-map "\C-c\C-c" 'custom-save-and-exit)
- (define-key custom-mode-map "\C-c\C-d" 'custom-toggle-documentation))
-
-;; C-c keymap ideas: C-a field-beginning, C-e field-end, C-f
-;; forward-field, C-b backward-field, C-n next-field, C-p
-;; previous-field, ? describe-field.
-
-(defun custom-mode ()
- "Major mode for doing customizations.
-
-\\{custom-mode-map}"
- (kill-all-local-variables)
- (setq major-mode 'custom-mode
- mode-name "Custom")
- (use-local-map custom-mode-map)
- (make-local-variable 'before-change-functions)
- (setq before-change-functions '(custom-before-change))
- (make-local-variable 'after-change-functions)
- (setq after-change-functions '(custom-after-change))
- (if (not (fboundp 'make-local-hook))
- ;; Emacs 19.28 and earlier.
- (add-hook 'post-command-hook
- (lambda ()
- (if (eq major-mode 'custom-mode)
- (custom-post-command))))
- ;; Emacs 19.29.
- (make-local-hook 'post-command-hook)
- (add-hook 'post-command-hook 'custom-post-command nil t)))
-
-(defun custom-forward-field (arg)
- "Move point to the next field or button.
-With optional ARG, move across that many fields."
- (interactive "p")
- (while (> arg 0)
- (let ((next (if (get-text-property (point) 'custom-tag)
- (next-single-property-change (point) 'custom-tag)
- (point))))
- (setq next (or (next-single-property-change next 'custom-tag)
- (next-single-property-change (point-min) 'custom-tag)))
- (if next
- (goto-char next)
- (error "No customization fields in this buffer.")))
- (or (get-text-property (point) 'custom-jump)
- (setq arg (1- arg))))
- (while (< arg 0)
- (let ((previous (if (get-text-property (1- (point)) 'custom-tag)
- (previous-single-property-change (point) 'custom-tag)
- (point))))
- (setq previous
- (or (previous-single-property-change previous 'custom-tag)
- (previous-single-property-change (point-max) 'custom-tag)))
- (if previous
- (goto-char previous)
- (error "No customization fields in this buffer.")))
- (or (get-text-property (1- (point)) 'custom-jump)
- (setq arg (1+ arg)))))
-
-(defun custom-backward-field (arg)
- "Move point to the previous field or button.
-With optional ARG, move across that many fields."
- (interactive "p")
- (custom-forward-field (- arg)))
-
-(defun custom-toggle-documentation (&optional arg)
- "Toggle display of documentation text.
-If the optional argument is non-nil, show text iff the argument is positive."
- (interactive "P")
- (let ((hide (or (and (null arg)
- (null (custom-category-get
- 'custom-documentation-properties 'invisible)))
- (<= (prefix-numeric-value arg) 0))))
- (custom-category-put 'custom-documentation-properties 'invisible hide)
- (custom-category-put 'custom-documentation-properties intangible hide))
- (redraw-display))
-
-(defun custom-enter-value (field data)
- "Enter value for current customization field or push button."
- (interactive (list (get-text-property (point) 'custom-tag)
- (get-text-property (point) 'custom-data)))
- (cond (data
- (funcall field data))
- ((eq field 'custom-enter-value)
- (error "Don't be silly"))
- ((and (symbolp field) (fboundp field))
- (call-interactively field))
- (field
- (custom-field-query field))
- (t
- (message "Nothing to enter here"))))
-
-(defun custom-kill-line ()
- "Kill to end of field or end of line, whichever is first."
- (interactive)
- (let ((field (get-text-property (point) 'custom-field))
- (newline (save-excursion (search-forward "\n")))
- (next (next-single-property-change (point) 'custom-field)))
- (if (and field (> newline next))
- (kill-region (point) next)
- (call-interactively 'kill-line))))
-
-(defun custom-push-button (event)
- "Activate button below mouse pointer."
- (interactive "@e")
- (let* ((pos (event-point event))
- (field (get-text-property pos 'custom-field))
- (tag (get-text-property pos 'custom-tag))
- (data (get-text-property pos 'custom-data)))
- (cond (data
- (funcall tag data))
- ((and (symbolp tag) (fboundp tag))
- (call-interactively tag))
- (field
- (call-interactively (lookup-key global-map (this-command-keys))))
- (tag
- (custom-enter-value tag data))
- (t
- (error "Nothing to click on here.")))))
-
-(defun custom-reset-all ()
- "Undo any changes since the last apply in all fields."
- (interactive (and custom-modified-list
- (not (y-or-n-p "Discard all changes? "))
- (error "Reset aborted")))
- (let ((all custom-name-fields)
- current field)
- (while all
- (setq current (car all)
- field (cdr current)
- all (cdr all))
- (custom-field-reset field))))
-
-(defun custom-field-reset (field)
- "Undo any changes in FIELD since the last apply."
- (interactive (list (or (get-text-property (point) 'custom-field)
- (get-text-property (point) 'custom-tag))))
- (if (arrayp field)
- (let* ((custom (custom-field-custom field))
- (name (custom-name custom)))
- (save-excursion
- (if name
- (custom-field-original-set
- field (car (custom-import custom (custom-external name)))))
- (if (not (custom-valid custom (custom-field-original field)))
- (error "This field cannot be reset alone")
- (funcall (custom-property custom 'reset) field)
- (funcall (custom-property custom 'synchronize) field))))))
-
-(defun custom-factory-reset-all ()
- "Reset all field to their default values."
- (interactive (and custom-modified-list
- (not (y-or-n-p "Discard all changes? "))
- (error "Reset aborted")))
- (let ((all custom-name-fields)
- field)
- (while all
- (setq field (cdr (car all))
- all (cdr all))
- (custom-field-factory-reset field))))
-
-(defun custom-field-factory-reset (field)
- "Reset FIELD to its default value."
- (interactive (list (or (get-text-property (point) 'custom-field)
- (get-text-property (point) 'custom-tag))))
- (if (arrayp field)
- (save-excursion
- (funcall (custom-property (custom-field-custom field) 'factory-reset)
- field))))
-
-(defun custom-apply-all ()
- "Apply any changes since the last reset in all fields."
- (interactive (if custom-modified-list
- nil
- (error "No changes to apply.")))
- (custom-field-parse custom-field-last)
- (let ((all custom-name-fields)
- field)
- (while all
- (setq field (cdr (car all))
- all (cdr all))
- (let ((error (custom-field-validate (custom-field-custom field) field)))
- (if (null error)
- ()
- (goto-char (car error))
- (error (cdr error))))))
- (let ((all custom-name-fields)
- field)
- (while all
- (setq field (cdr (car all))
- all (cdr all))
- (custom-field-apply field))))
-
-(defun custom-field-apply (field)
- "Apply any changes in FIELD since the last apply."
- (interactive (list (or (get-text-property (point) 'custom-field)
- (get-text-property (point) 'custom-tag))))
- (custom-field-parse custom-field-last)
- (if (arrayp field)
- (let* ((custom (custom-field-custom field))
- (error (custom-field-validate custom field)))
- (if error
- (error (cdr error)))
- (funcall (custom-property custom 'apply) field))))
-
-(defun custom-toggle-hide (&rest ignore)
- "Hide or show entry."
- (interactive)
- (error "This button is not yet implemented"))
-
-(defun custom-save-and-exit ()
- "Save and exit customization buffer."
- (interactive "@")
- (save-excursion
- (funcall custom-save))
- (kill-buffer (current-buffer)))
-
-(defun custom-save ()
- "Save customization information."
- (interactive)
- (custom-apply-all)
- (let ((new custom-name-fields))
- (set-buffer (find-file-noselect custom-file))
- (goto-char (point-min))
- (save-excursion
- (let ((old (condition-case nil
- (read (current-buffer))
- (end-of-file (append '(setq custom-dummy
- 'custom-dummy) ())))))
- (or (eq (car old) 'setq)
- (error "Invalid customization file: %s" custom-file))
- (while new
- (let* ((field (cdr (car new)))
- (custom (custom-field-custom field))
- (value (custom-field-original field))
- (default (car (custom-import custom (custom-default custom))))
- (name (car (car new))))
- (setq new (cdr new))
- (custom-assert '(eq name (custom-name custom)))
- (if (equal default value)
- (setcdr old (custom-plist-delq name (cdr old)))
- (setcdr old (plist-put (cdr old) name
- (car (custom-quote custom value)))))))
- (erase-buffer)
- (insert ";; " custom-file "\
- --- Automatically generated customization information.
-;;
-;; Feel free to edit by hand, but the entire content should consist of
-;; a single setq. Any other lisp expressions will confuse the
-;; automatic configuration engine.
-
-\(setq ")
- (setq old (cdr old))
- (while old
- (prin1 (car old) (current-buffer))
- (setq old (cdr old))
- (insert " ")
- (pp (car old) (current-buffer))
- (setq old (cdr old))
- (if old (insert "\n ")))
- (insert ")\n")
- (save-buffer)
- (kill-buffer (current-buffer))))))
-
-(defun custom-load ()
- "Save customization information."
- (interactive (and custom-modified-list
- (not (equal (list (custom-name-field 'custom-file))
- custom-modified-list))
- (not (y-or-n-p "Discard all changes? "))
- (error "Load aborted")))
- (load-file (custom-name-value 'custom-file))
- (custom-reset-all))
-
-;;; Field Editing:
-;;
-;; Various internal functions for implementing the direct editing of
-;; fields in the customization buffer.
-
-(defun custom-field-untouch (field)
- ;; Remove FIELD and its children from `custom-modified-list'.
- (setq custom-modified-list (delq field custom-modified-list))
- (if (arrayp field)
- (let ((value (custom-field-value field)))
- (cond ((null (custom-data (custom-field-custom field))))
- ((arrayp value)
- (custom-field-untouch value))
- ((listp value)
- (mapcar 'custom-field-untouch value))))))
-
-
-(defun custom-field-insert (field)
- ;; Insert editing FIELD in current buffer.
- (let ((from (point))
- (custom (custom-field-custom field))
- (value (custom-field-value field)))
- (insert (custom-write custom value))
- (insert-char (custom-padding custom)
- (- (custom-width custom) (- (point) from)))
- (custom-field-move field from (point))
- (custom-set-text-properties
- from (point)
- (list 'custom-field field
- 'custom-tag field
- 'face (custom-field-face field)
- 'start-open t
- 'end-open t))))
-
-(defun custom-field-read (field)
- ;; Read the screen content of FIELD.
- (custom-read (custom-field-custom field)
- (custom-buffer-substring-no-properties (custom-field-start field)
- (custom-field-end field))))
-
-;; Fields are shown in a special `active' face when point is inside
-;; it. You activate the field by moving point inside (entering) it
-;; and deactivate the field by moving point outside (leaving) it.
-
-(defun custom-field-leave (field)
- ;; Deactivate FIELD.
- (let ((before-change-functions nil)
- (after-change-functions nil))
- (custom-put-text-property (custom-field-start field) (custom-field-end field)
- 'face (custom-field-face field))))
-
-(defun custom-field-enter (field)
- ;; Activate FIELD.
- (let* ((start (custom-field-start field))
- (end (custom-field-end field))
- (custom (custom-field-custom field))
- (padding (custom-padding custom))
- (before-change-functions nil)
- (after-change-functions nil))
- (or (eq this-command 'self-insert-command)
- (let ((pos end))
- (while (and (< start pos)
- (eq (char-after (1- pos)) padding))
- (setq pos (1- pos)))
- (if (< pos (point))
- (goto-char pos))))
- (custom-put-text-property start end 'face custom-field-active-face)))
-
-(defun custom-field-resize (field)
- ;; Resize FIELD after change.
- (let* ((custom (custom-field-custom field))
- (begin (custom-field-start field))
- (end (custom-field-end field))
- (pos (point))
- (padding (custom-padding custom))
- (width (custom-width custom))
- (size (- end begin)))
- (cond ((< size width)
- (goto-char end)
- (if (fboundp 'insert-before-markers-and-inherit)
- ;; Emacs 19.
- (insert-before-markers-and-inherit
- (make-string (- width size) padding))
- ;; XEmacs: BUG: Doesn't work!
- (insert-before-markers (make-string (- width size) padding)))
- (goto-char pos))
- ((> size width)
- (let ((start (if (and (< (+ begin width) pos) (<= pos end))
- pos
- (+ begin width))))
- (goto-char end)
- (while (and (< start (point)) (= (preceding-char) padding))
- (backward-delete-char 1))
- (goto-char pos))))))
-
-(defvar custom-field-changed nil)
-;; List of fields changed on the screen but whose VALUE attribute has
-;; not yet been updated to reflect the new screen content.
-(make-variable-buffer-local 'custom-field-changed)
-
-(defun custom-field-parse (field)
- ;; Parse FIELD content iff changed.
- (if (memq field custom-field-changed)
- (progn
- (setq custom-field-changed (delq field custom-field-changed))
- (custom-field-value-set field (custom-field-read field))
- (custom-field-update field))))
-
-(defun custom-post-command ()
- ;; Keep track of their active field.
- (custom-assert '(eq major-mode 'custom-mode))
- (let ((field (custom-field-property (point))))
- (if (eq field custom-field-last)
- (if (memq field custom-field-changed)
- (custom-field-resize field))
- (custom-field-parse custom-field-last)
- (if custom-field-last
- (custom-field-leave custom-field-last))
- (if field
- (custom-field-enter field))
- (setq custom-field-last field))
- (set-buffer-modified-p (or custom-modified-list
- custom-field-changed))))
-
-(defvar custom-field-was nil)
-;; The custom data before the change.
-(make-variable-buffer-local 'custom-field-was)
-
-(defun custom-before-change (begin end)
- ;; Check that we the modification is allowed.
- (if (not (eq major-mode 'custom-mode))
- (message "Aargh! Why is custom-before-change called here?")
- (let ((from (custom-field-property begin))
- (to (custom-field-property end)))
- (cond ((or (null from) (null to))
- (error "You can only modify the fields"))
- ((not (eq from to))
- (error "Changes must be limited to a single field."))
- (t
- (setq custom-field-was from))))))
-
-(defun custom-after-change (begin end length)
- ;; Keep track of field content.
- (if (not (eq major-mode 'custom-mode))
- (message "Aargh! Why is custom-after-change called here?")
- (let ((field custom-field-was))
- (custom-assert '(prog1 field (setq custom-field-was nil)))
- ;; Prevent mixing fields properties.
- (custom-put-text-property begin end 'custom-field field)
- ;; Update the field after modification.
- (if (eq (custom-field-property begin) field)
- (let ((field-end (custom-field-end field)))
- (if (> end field-end)
- (set-marker field-end end))
- (add-to-list 'custom-field-changed field))
- ;; We deleted the entire field, reinsert it.
- (custom-assert '(eq begin end))
- (save-excursion
- (goto-char begin)
- (custom-field-value-set field
- (custom-read (custom-field-custom field) ""))
- (custom-field-insert field))))))
-
-(defun custom-field-property (pos)
- ;; The `custom-field' text property valid for POS.
- (or (get-text-property pos 'custom-field)
- (and (not (eq pos (point-min)))
- (get-text-property (1- pos) 'custom-field))))
-
-;;; Generic Utilities:
-;;
-;; Some utility functions that are not really specific to custom.
-
-(defun custom-assert (expr)
- "Assert that EXPR evaluates to non-nil at this point"
- (or (eval expr)
- (error "Assertion failed: %S" expr)))
-
-(defun custom-first-line (string)
- "Return the part of STRING before the first newline."
- (let ((pos 0)
- (len (length string)))
- (while (and (< pos len) (not (eq (aref string pos) ?\n)))
- (setq pos (1+ pos)))
- (if (eq pos len)
- string
- (substring string 0 pos))))
-
-(defun custom-insert-before (list old new)
- "In LIST insert before OLD a NEW element."
- (cond ((null list)
- (list new))
- ((null old)
- (nconc list (list new)))
- ((eq old (car list))
- (cons new list))
- (t
- (let ((list list))
- (while (not (eq old (car (cdr list))))
- (setq list (cdr list))
- (custom-assert '(cdr list)))
- (setcdr list (cons new (cdr list))))
- list)))
-
-(defun custom-strip-padding (string padding)
- "Remove padding from STRING."
- (let ((regexp (concat (regexp-quote (char-to-string padding)) "+")))
- (while (string-match regexp string)
- (setq string (concat (substring string 0 (match-beginning 0))
- (substring string (match-end 0))))))
- string)
-
-(defun custom-plist-memq (prop plist)
- "Return non-nil if PROP is a property of PLIST. Comparison done with EQ."
- (let (result)
- (while plist
- (if (eq (car plist) prop)
- (setq result plist
- plist nil)
- (setq plist (cdr (cdr plist)))))
- result))
-
-(defun custom-plist-delq (prop plist)
- "Delete property PROP from property list PLIST."
- (while (eq (car plist) prop)
- (setq plist (cdr (cdr plist))))
- (let ((list plist)
- (next (cdr (cdr plist))))
- (while next
- (if (eq (car next) prop)
- (progn
- (setq next (cdr (cdr next)))
- (setcdr (cdr list) next))
- (setq list next
- next (cdr (cdr next))))))
- plist)
-
-;;; Meta Customization:
-
-(custom-declare '()
- '((tag . "Meta Customization")
- (doc . "Customization of the customization support.")
- (type . group)
- (data ((type . face-doc))
- ((tag . "Button Face")
- (default . bold)
- (doc . "Face used for tags in customization buffers.")
- (name . custom-button-face)
- (synchronize . (lambda (f)
- (custom-category-put 'custom-button-properties
- 'face custom-button-face)))
- (type . face))
- ((tag . "Mouse Face")
- (default . highlight)
- (doc . "\
-Face used when mouse is above a button in customization buffers.")
- (name . custom-mouse-face)
- (synchronize . (lambda (f)
- (custom-category-put 'custom-button-properties
- mouse-face
- custom-mouse-face)))
- (type . face))
- ((tag . "Field Face")
- (default . italic)
- (doc . "Face used for customization fields.")
- (name . custom-field-face)
- (type . face))
- ((tag . "Uninitialized Face")
- (default . modeline)
- (doc . "Face used for uninitialized customization fields.")
- (name . custom-field-uninitialized-face)
- (type . face))
- ((tag . "Invalid Face")
- (default . highlight)
- (doc . "\
-Face used for customization fields containing invalid data.")
- (name . custom-field-invalid-face)
- (type . face))
- ((tag . "Modified Face")
- (default . bold-italic)
- (doc . "Face used for modified customization fields.")
- (name . custom-field-modified-face)
- (type . face))
- ((tag . "Active Face")
- (default . underline)
- (doc . "\
-Face used for customization fields while they are being edited.")
- (name . custom-field-active-face)
- (type . face)))))
-
-;; custom.el uses two categories.
-
-(custom-category-create 'custom-documentation-properties)
-(custom-category-put 'custom-documentation-properties rear-nonsticky t)
-
-(custom-category-create 'custom-button-properties)
-(custom-category-put 'custom-button-properties 'face custom-button-face)
-(custom-category-put 'custom-button-properties mouse-face custom-mouse-face)
-(custom-category-put 'custom-button-properties rear-nonsticky t)
-
-(custom-category-create 'custom-hidden-properties)
-(custom-category-put 'custom-hidden-properties 'invisible
- (not (string-match "XEmacs" emacs-version)))
-(custom-category-put 'custom-hidden-properties intangible t)
-
-(and init-file-user ; Don't load any init file if -q was used.
- (file-readable-p custom-file)
- (load-file custom-file))
-
-(provide 'custom)
-
-;;; custom.el ends here
diff --git a/lisp/=diary-ins.el b/lisp/=diary-ins.el
deleted file mode 100644
index d84bb260670..00000000000
--- a/lisp/=diary-ins.el
+++ /dev/null
@@ -1,251 +0,0 @@
-;;; diary-ins.el --- calendar functions for adding diary entries.
-
-;; Copyright (C) 1990, 1994 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: diary, calendar
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the diary insertion features as
-;; described in calendar.el.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(require 'diary-lib)
-
-(defun make-diary-entry (string &optional nonmarking file)
- "Insert a diary entry STRING which may be NONMARKING in FILE.
-If omitted, NONMARKING defaults to nil and FILE defaults to diary-file."
- (find-file-other-window
- (substitute-in-file-name (if file file diary-file)))
- (goto-char (point-max))
- (insert
- (if (bolp) "" "\n")
- (if nonmarking diary-nonmarking-symbol "")
- string " "))
-
-(defun insert-diary-entry (arg)
- "Insert a diary entry for the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (make-diary-entry (calendar-date-string (calendar-cursor-to-date t) t t)
- arg))
-
-(defun insert-weekly-diary-entry (arg)
- "Insert a weekly diary entry for the day of the week indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (make-diary-entry (calendar-day-name (calendar-cursor-to-date t))
- arg))
-
-(defun insert-monthly-diary-entry (arg)
- "Insert a monthly diary entry for the day of the month indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " * ")
- '("* " day))))
- (make-diary-entry (calendar-date-string (calendar-cursor-to-date t) t)
- arg)))
-
-(defun insert-yearly-diary-entry (arg)
- "Insert an annual diary entry for the day of the year indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " " monthname)
- '(monthname " " day))))
- (make-diary-entry (calendar-date-string (calendar-cursor-to-date t) t)
- arg)))
-
-(defun insert-anniversary-diary-entry (arg)
- "Insert an anniversary diary entry for the date given by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " " month " " year)
- '(month " " day " " year))))
- (make-diary-entry
- (format "%s(diary-anniversary %s)"
- sexp-diary-entry-symbol
- (calendar-date-string (calendar-cursor-to-date t) nil t))
- arg)))
-
-(defun insert-block-diary-entry (arg)
- "Insert a block diary entry for the days between the point and marked date.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " " month " " year)
- '(month " " day " " year)))
- (cursor (calendar-cursor-to-date t))
- (mark (or (car calendar-mark-ring)
- (error "No mark set in this buffer")))
- (start)
- (end))
- (if (< (calendar-absolute-from-gregorian mark)
- (calendar-absolute-from-gregorian cursor))
- (setq start mark
- end cursor)
- (setq start cursor
- end mark))
- (make-diary-entry
- (format "%s(diary-block %s %s)"
- sexp-diary-entry-symbol
- (calendar-date-string start nil t)
- (calendar-date-string end nil t))
- arg)))
-
-(defun insert-cyclic-diary-entry (arg)
- "Insert a cyclic diary entry starting at the date given by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " " month " " year)
- '(month " " day " " year))))
- (make-diary-entry
- (format "%s(diary-cyclic %d %s)"
- sexp-diary-entry-symbol
- (calendar-read "Repeat every how many days: "
- '(lambda (x) (> x 0)))
- (calendar-date-string (calendar-cursor-to-date t) nil t))
- arg)))
-
-(defun insert-hebrew-diary-entry (arg)
- "Insert a diary entry.
-For the Hebrew date corresponding to the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-month-name-array
- calendar-hebrew-month-name-array-leap-year))
- (make-diary-entry
- (concat
- hebrew-diary-entry-symbol
- (calendar-date-string
- (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))
- nil t))
- arg)))
-
-(defun insert-monthly-hebrew-diary-entry (arg)
- "Insert a monthly diary entry.
-For the day of the Hebrew month corresponding to the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style '(day " * ") '("* " day )))
- (calendar-month-name-array
- calendar-hebrew-month-name-array-leap-year))
- (make-diary-entry
- (concat
- hebrew-diary-entry-symbol
- (calendar-date-string
- (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))))
- arg)))
-
-(defun insert-yearly-hebrew-diary-entry (arg)
- "Insert an annual diary entry.
-For the day of the Hebrew year corresponding to the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " " monthname)
- '(monthname " " day)))
- (calendar-month-name-array
- calendar-hebrew-month-name-array-leap-year))
- (make-diary-entry
- (concat
- hebrew-diary-entry-symbol
- (calendar-date-string
- (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))))
- arg)))
-
-(defun insert-islamic-diary-entry (arg)
- "Insert a diary entry.
-For the Islamic date corresponding to the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-month-name-array calendar-islamic-month-name-array))
- (make-diary-entry
- (concat
- islamic-diary-entry-symbol
- (calendar-date-string
- (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))
- nil t))
- arg)))
-
-(defun insert-monthly-islamic-diary-entry (arg)
- "Insert a monthly diary entry.
-For the day of the Islamic month corresponding to the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style '(day " * ") '("* " day )))
- (calendar-month-name-array calendar-islamic-month-name-array))
- (make-diary-entry
- (concat
- islamic-diary-entry-symbol
- (calendar-date-string
- (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))))
- arg)))
-
-(defun insert-yearly-islamic-diary-entry (arg)
- "Insert an annual diary entry.
-For the day of the Islamic year corresponding to the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " " monthname)
- '(monthname " " day)))
- (calendar-month-name-array calendar-islamic-month-name-array))
- (make-diary-entry
- (concat
- islamic-diary-entry-symbol
- (calendar-date-string
- (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))))
- arg)))
-
-(provide 'diary-ins)
-
-;;; diary-ins.el ends here
diff --git a/lisp/=diary-lib.el b/lisp/=diary-lib.el
deleted file mode 100644
index a78475bc916..00000000000
--- a/lisp/=diary-lib.el
+++ /dev/null
@@ -1,1919 +0,0 @@
-;;; diary-lib.el --- diary functions.
-
-;; Copyright (C) 1989, 1990, 1992, 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the diary features as described
-;; in calendar.el.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(require 'calendar)
-
-;;;###autoload
-(defun diary (&optional arg)
- "Generate the diary window for ARG days starting with the current date.
-If no argument is provided, the number of days of diary entries is governed
-by the variable `number-of-diary-entries'. This function is suitable for
-execution in a `.emacs' file."
- (interactive "P")
- (let ((d-file (substitute-in-file-name diary-file))
- (date (calendar-current-date)))
- (if (and d-file (file-exists-p d-file))
- (if (file-readable-p d-file)
- (list-diary-entries
- date
- (cond
- (arg (prefix-numeric-value arg))
- ((vectorp number-of-diary-entries)
- (aref number-of-diary-entries (calendar-day-of-week date)))
- (t number-of-diary-entries)))
- (error "Your diary file is not readable!"))
- (error "You don't have a diary file!"))))
-
-(defun view-diary-entries (arg)
- "Prepare and display a buffer with diary entries.
-Searches the file named in `diary-file' for entries that
-match ARG days starting with the date indicated by the cursor position
-in the displayed three-month calendar."
- (interactive "p")
- (let ((d-file (substitute-in-file-name diary-file)))
- (if (and d-file (file-exists-p d-file))
- (if (file-readable-p d-file)
- (list-diary-entries (calendar-cursor-to-date t) arg)
- (error "Diary file is not readable!"))
- (error "You don't have a diary file!"))))
-
-(defun view-other-diary-entries (arg diary-file)
- "Prepare and display buffer of diary entries from an alternative diary file.
-Prompts for a file name and searches that file for entries that match ARG
-days starting with the date indicated by the cursor position in the displayed
-three-month calendar."
- (interactive
- (list (cond ((null current-prefix-arg) 1)
- ((listp current-prefix-arg) (car current-prefix-arg))
- (t current-prefix-arg))
- (setq diary-file (read-file-name "Enter diary file name: "
- default-directory nil t))))
- (view-diary-entries arg))
-
-(autoload 'check-calendar-holidays "holidays"
- "Check the list of holidays for any that occur on DATE.
-The value returned is a list of strings of relevant holiday descriptions.
-The holidays are those in the list `calendar-holidays'."
- t)
-
-(autoload 'calendar-holiday-list "holidays"
- "Form the list of holidays that occur on dates in the calendar window.
-The holidays are those in the list `calendar-holidays'."
- t)
-
-(autoload 'diary-french-date "cal-french"
- "French calendar equivalent of date diary entry."
- t)
-
-(autoload 'diary-mayan-date "cal-mayan"
- "Mayan calendar equivalent of date diary entry."
- t)
-
-(autoload 'diary-phases-of-moon "lunar" "Moon phases diary entry." t)
-
-(autoload 'diary-sunrise-sunset "solar"
- "Local time of sunrise and sunset as a diary entry."
- t)
-
-(autoload 'diary-sabbath-candles "solar"
- "Local time of candle lighting diary entry--applies if date is a Friday.
-No diary entry if there is no sunset on that date."
- t)
-
-(defvar diary-syntax-table (copy-syntax-table (standard-syntax-table))
- "The syntax table used when parsing dates in the diary file.
-It is the standard syntax table used in Fundamental mode, but with the
-syntax of `*' changed to be a word constituent.")
-
-(modify-syntax-entry ?* "w" diary-syntax-table)
-
-(defun list-diary-entries (date number)
- "Create and display a buffer containing the relevant lines in diary-file.
-The arguments are DATE and NUMBER; the entries selected are those
-for NUMBER days starting with date DATE. The other entries are hidden
-using selective display.
-
-Returns a list of all relevant diary entries found, if any, in order by date.
-The list entries have the form ((month day year) string). If the variable
-`diary-list-include-blanks' is t, this list includes a dummy diary entry
-\(consisting of the empty string) for a date with no diary entries.
-
-After the list is prepared, the hooks `nongregorian-diary-listing-hook',
-`list-diary-entries-hook', `diary-display-hook', and `diary-hook' are run.
-These hooks have the following distinct roles:
-
- `nongregorian-diary-listing-hook' can cull dates from the diary
- and each included file. Usually used for Hebrew or Islamic
- diary entries in files. Applied to *each* file.
-
- `list-diary-entries-hook' adds or manipulates diary entries from
- external sources. Used, for example, to include diary entries
- from other files or to sort the diary entries. Invoked *once* only,
- before the display hook is run.
-
- `diary-display-hook' does the actual display of information. If this is
- nil, simple-diary-display will be used. Use add-hook to set this to
- fancy-diary-display, if desired. If you want no diary display, use
- add-hook to set this to ignore.
-
- `diary-hook' is run last. This can be used for an appointment
- notification function."
-
- (if (< 0 number)
- (let* ((original-date date);; save for possible use in the hooks
- (old-diary-syntax-table)
- (diary-entries-list)
- (date-string (calendar-date-string date))
- (d-file (substitute-in-file-name diary-file)))
- (message "Preparing diary...")
- (save-excursion
- (let ((diary-buffer (get-file-buffer d-file)))
- (set-buffer (if diary-buffer
- diary-buffer
- (find-file-noselect d-file t))))
- (setq selective-display t)
- (setq selective-display-ellipses nil)
- (setq old-diary-syntax-table (syntax-table))
- (set-syntax-table diary-syntax-table)
- (unwind-protect
- (let ((buffer-read-only nil)
- (diary-modified (buffer-modified-p))
- (mark (regexp-quote diary-nonmarking-symbol)))
- (goto-char (1- (point-max)))
- (if (not (looking-at "\^M\\|\n"))
- (progn
- (forward-char 1)
- (insert-string "\^M")))
- (goto-char (point-min))
- (if (not (looking-at "\^M\\|\n"))
- (insert-string "\^M"))
- (subst-char-in-region (point-min) (point-max) ?\n ?\^M t)
- (calendar-for-loop i from 1 to number do
- (let ((d diary-date-forms)
- (month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date))
- (entry-found (list-sexp-diary-entries date)))
- (while d
- (let*
- ((date-form (if (equal (car (car d)) 'backup)
- (cdr (car d))
- (car d)))
- (backup (equal (car (car d)) 'backup))
- (dayname
- (concat
- (calendar-day-name date) "\\|"
- (substring (calendar-day-name date) 0 3) ".?"))
- (monthname
- (concat
- "\\*\\|"
- (calendar-month-name month) "\\|"
- (substring (calendar-month-name month) 0 3) ".?"))
- (month (concat "\\*\\|0*" (int-to-string month)))
- (day (concat "\\*\\|0*" (int-to-string day)))
- (year
- (concat
- "\\*\\|0*" (int-to-string year)
- (if abbreviated-calendar-year
- (concat "\\|" (int-to-string (% year 100)))
- "")))
- (regexp
- (concat
- "\\(\\`\\|\^M\\|\n\\)" mark "?\\("
- (mapconcat 'eval date-form "\\)\\(")
- "\\)"))
- (case-fold-search t))
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (if backup (re-search-backward "\\<" nil t))
- (if (and (or (char-equal (preceding-char) ?\^M)
- (char-equal (preceding-char) ?\n))
- (not (looking-at " \\|\^I")))
- ;; Diary entry that consists only of date.
- (backward-char 1)
- ;; Found a nonempty diary entry--make it visible and
- ;; add it to the list.
- (setq entry-found t)
- (let ((entry-start (point))
- (date-start))
- (re-search-backward "\^M\\|\n\\|\\`")
- (setq date-start (point))
- (re-search-forward "\^M\\|\n" nil t 2)
- (while (looking-at " \\|\^I")
- (re-search-forward "\^M\\|\n" nil t))
- (backward-char 1)
- (subst-char-in-region date-start
- (point) ?\^M ?\n t)
- (add-to-diary-list
- date (buffer-substring entry-start (point)))))))
- (setq d (cdr d)))
- (or entry-found
- (not diary-list-include-blanks)
- (setq diary-entries-list
- (append diary-entries-list
- (list (list date "")))))
- (setq date
- (calendar-gregorian-from-absolute
- (1+ (calendar-absolute-from-gregorian date))))
- (setq entry-found nil)))
- (set-buffer-modified-p diary-modified))
- (set-syntax-table old-diary-syntax-table))
- (goto-char (point-min))
- (run-hooks 'nongregorian-diary-listing-hook
- 'list-diary-entries-hook)
- (if diary-display-hook
- (run-hooks 'diary-display-hook)
- (simple-diary-display))
- (run-hooks 'diary-hook)
- diary-entries-list))))
-
-(defun include-other-diary-files ()
- "Include the diary entries from other diary files with those of diary-file.
-This function is suitable for use in `list-diary-entries-hook';
-it enables you to use shared diary files together with your own.
-The files included are specified in the diaryfile by lines of this form:
- #include \"filename\"
-This is recursive; that is, #include directives in diary files thus included
-are obeyed. You can change the `#include' to some other string by
-changing the variable `diary-include-string'."
- (goto-char (point-min))
- (while (re-search-forward
- (concat
- "\\(\\`\\|\^M\\|\n\\)"
- (regexp-quote diary-include-string)
- " \"\\([^\"]*\\)\"")
- nil t)
- (let ((diary-file (substitute-in-file-name
- (buffer-substring (match-beginning 2) (match-end 2))))
- (diary-list-include-blanks nil)
- (list-diary-entries-hook 'include-other-diary-files)
- (diary-display-hook 'ignore)
- (diary-hook nil))
- (if (file-exists-p diary-file)
- (if (file-readable-p diary-file)
- (unwind-protect
- (setq diary-entries-list
- (append diary-entries-list
- (list-diary-entries original-date number)))
- (kill-buffer (get-file-buffer diary-file)))
- (beep)
- (message "Can't read included diary file %s" diary-file)
- (sleep-for 2))
- (beep)
- (message "Can't find included diary file %s" diary-file)
- (sleep-for 2))))
- (goto-char (point-min)))
-
-(defun simple-diary-display ()
- "Display the diary buffer if there are any relevant entries or holidays."
- (let* ((holiday-list (if holidays-in-diary-buffer
- (check-calendar-holidays original-date)))
- (msg (format "No diary entries for %s %s"
- (concat date-string (if holiday-list ":" ""))
- (mapconcat 'identity holiday-list "; "))))
- (if (or (not diary-entries-list)
- (and (not (cdr diary-entries-list))
- (string-equal (car (cdr (car diary-entries-list))) "")))
- (if (<= (length msg) (frame-width))
- (message msg)
- (set-buffer (get-buffer-create holiday-buffer))
- (setq buffer-read-only nil)
- (calendar-set-mode-line date-string)
- (erase-buffer)
- (insert (mapconcat 'identity holiday-list "\n"))
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- (setq buffer-read-only t)
- (display-buffer holiday-buffer)
- (message "No diary entries for %s" date-string))
- (calendar-set-mode-line
- (concat "Diary for " date-string
- (if holiday-list ": " "")
- (mapconcat 'identity holiday-list "; ")))
- (display-buffer (get-file-buffer d-file))
- (message "Preparing diary...done"))))
-
-(defun fancy-diary-display ()
- "Prepare a diary buffer with relevant entries in a fancy, noneditable form.
-This function is provided for optional use as the `diary-display-hook'."
- (save-excursion;; Turn off selective-display in the diary file's buffer.
- (set-buffer (get-file-buffer (substitute-in-file-name diary-file)))
- (let ((diary-modified (buffer-modified-p)))
- (subst-char-in-region (point-min) (point-max) ?\^M ?\n t)
- (setq selective-display nil)
- (kill-local-variable 'mode-line-format)
- (set-buffer-modified-p diary-modified)))
- (if (or (not diary-entries-list)
- (and (not (cdr diary-entries-list))
- (string-equal (car (cdr (car diary-entries-list))) "")))
- (let* ((holiday-list (if holidays-in-diary-buffer
- (check-calendar-holidays original-date)))
- (msg (format "No diary entries for %s %s"
- (concat date-string (if holiday-list ":" ""))
- (mapconcat 'identity holiday-list "; "))))
- (if (<= (length msg) (frame-width))
- (message msg)
- (set-buffer (get-buffer-create holiday-buffer))
- (setq buffer-read-only nil)
- (calendar-set-mode-line date-string)
- (erase-buffer)
- (insert (mapconcat 'identity holiday-list "\n"))
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- (setq buffer-read-only t)
- (display-buffer holiday-buffer)
- (message "No diary entries for %s" date-string)))
- (save-excursion;; Prepare the fancy diary buffer.
- (set-buffer (make-fancy-diary-buffer))
- (setq buffer-read-only nil)
- (let ((entry-list diary-entries-list)
- (holiday-list)
- (holiday-list-last-month 1)
- (holiday-list-last-year 1)
- (date (list 0 0 0)))
- (while entry-list
- (if (not (calendar-date-equal date (car (car entry-list))))
- (progn
- (setq date (car (car entry-list)))
- (and holidays-in-diary-buffer
- (calendar-date-compare
- (list (list holiday-list-last-month
- (calendar-last-day-of-month
- holiday-list-last-month
- holiday-list-last-year)
- holiday-list-last-year))
- (list date))
- ;; We need to get the holidays for the next 3 months.
- (setq holiday-list-last-month
- (extract-calendar-month date))
- (setq holiday-list-last-year
- (extract-calendar-year date))
- (increment-calendar-month
- holiday-list-last-month holiday-list-last-year 1)
- (setq holiday-list
- (let ((displayed-month holiday-list-last-month)
- (displayed-year holiday-list-last-year))
- (calendar-holiday-list)))
- (increment-calendar-month
- holiday-list-last-month holiday-list-last-year 1))
- (let* ((date-string (calendar-date-string date))
- (date-holiday-list
- (let ((h holiday-list)
- (d))
- ;; Make a list of all holidays for date.
- (while h
- (if (calendar-date-equal date (car (car h)))
- (setq d (append d (cdr (car h)))))
- (setq h (cdr h)))
- d)))
- (insert (if (= (point) (point-min)) "" ?\n) date-string)
- (if date-holiday-list (insert ": "))
- (let ((l (current-column)))
- (insert (mapconcat 'identity date-holiday-list
- (concat "\n" (make-string l ? )))))
- (let ((l (current-column)))
- (insert ?\n (make-string l ?=) ?\n)))))
- (if (< 0 (length (car (cdr (car entry-list)))))
- (insert (car (cdr (car entry-list))) ?\n))
- (setq entry-list (cdr entry-list))))
- (set-buffer-modified-p nil)
- (goto-char (point-min))
- (setq buffer-read-only t)
- (display-buffer fancy-diary-buffer)
- (message "Preparing diary...done"))))
-
-(defun make-fancy-diary-buffer ()
- "Create and return the initial fancy diary buffer."
- (save-excursion
- (set-buffer (get-buffer-create fancy-diary-buffer))
- (setq buffer-read-only nil)
- (make-local-variable 'mode-line-format)
- (calendar-set-mode-line "Diary Entries")
- (erase-buffer)
- (set-buffer-modified-p nil)
- (setq buffer-read-only t)
- (get-buffer fancy-diary-buffer)))
-
-(defun print-diary-entries ()
- "Print a hard copy of the diary display.
-
-If the simple diary display is being used, prepare a temp buffer with the
-visible lines of the diary buffer, add a heading line composed from the mode
-line, print the temp buffer, and destroy it.
-
-If the fancy diary display is being used, just print the buffer.
-
-The hooks given by the variable `print-diary-entries-hook' are called to do
-the actual printing."
- (interactive)
- (if (bufferp (get-buffer fancy-diary-buffer))
- (save-excursion
- (set-buffer (get-buffer fancy-diary-buffer))
- (run-hooks 'print-diary-entries-hook))
- (let ((diary-buffer
- (get-file-buffer (substitute-in-file-name diary-file))))
- (if diary-buffer
- (let ((temp-buffer (get-buffer-create "*Printable Diary Entries*"))
- (heading))
- (save-excursion
- (set-buffer diary-buffer)
- (setq heading
- (if (not (stringp mode-line-format))
- "All Diary Entries"
- (string-match "^-*\\([^-].*[^-]\\)-*$" mode-line-format)
- (substring mode-line-format
- (match-beginning 1) (match-end 1))))
- (copy-to-buffer temp-buffer (point-min) (point-max))
- (set-buffer temp-buffer)
- (while (re-search-forward "\^M.*$" nil t)
- (replace-match ""))
- (goto-char (point-min))
- (insert heading "\n"
- (make-string (length heading) ?=) "\n")
- (run-hooks 'print-diary-entries-hook)
- (kill-buffer temp-buffer)))
- (error "You don't have a diary buffer!")))))
-
-(defun show-all-diary-entries ()
- "Show all of the diary entries in the diary file.
-This function gets rid of the selective display of the diary file so that
-all entries, not just some, are visible. If there is no diary buffer, one
-is created."
- (interactive)
- (let ((d-file (substitute-in-file-name diary-file)))
- (if (and d-file (file-exists-p d-file))
- (if (file-readable-p d-file)
- (save-excursion
- (let ((diary-buffer (get-file-buffer d-file)))
- (set-buffer (if diary-buffer
- diary-buffer
- (find-file-noselect d-file t)))
- (let ((buffer-read-only nil)
- (diary-modified (buffer-modified-p)))
- (subst-char-in-region (point-min) (point-max) ?\^M ?\n t)
- (setq selective-display nil)
- (make-local-variable 'mode-line-format)
- (setq mode-line-format default-mode-line-format)
- (display-buffer (current-buffer))
- (set-buffer-modified-p diary-modified))))
- (error "Your diary file is not readable!"))
- (error "You don't have a diary file!"))))
-
-(defun diary-name-pattern (string-array &optional fullname)
- "Convert an STRING-ARRAY, an array of strings to a pattern.
-The pattern will match any of the strings, either entirely or abbreviated
-to three characters. An abbreviated form will match with or without a period;
-If the optional FULLNAME is t, abbreviations will not match, just the full
-name."
- (let ((pattern ""))
- (calendar-for-loop i from 0 to (1- (length string-array)) do
- (setq pattern
- (concat
- pattern
- (if (string-equal pattern "") "" "\\|")
- (aref string-array i)
- (if fullname
- ""
- (concat
- "\\|"
- (substring (aref string-array i) 0 3) ".?")))))
- pattern))
-
-(defun mark-diary-entries ()
- "Mark days in the calendar window that have diary entries.
-Each entry in the diary file visible in the calendar window is marked.
-After the entries are marked, the hooks `nongregorian-diary-marking-hook' and
-`mark-diary-entries-hook' are run."
- (interactive)
- (setq mark-diary-entries-in-calendar t)
- (let ((d-file (substitute-in-file-name diary-file)))
- (if (and d-file (file-exists-p d-file))
- (if (file-readable-p d-file)
- (save-excursion
- (message "Marking diary entries...")
- (set-buffer (find-file-noselect d-file t))
- (let ((d diary-date-forms)
- (old-diary-syntax-table))
- (setq old-diary-syntax-table (syntax-table))
- (set-syntax-table diary-syntax-table)
- (while d
- (let*
- ((date-form (if (equal (car (car d)) 'backup)
- (cdr (car d))
- (car d)));; ignore 'backup directive
- (dayname (diary-name-pattern calendar-day-name-array))
- (monthname
- (concat
- (diary-name-pattern calendar-month-name-array)
- "\\|\\*"))
- (month "[0-9]+\\|\\*")
- (day "[0-9]+\\|\\*")
- (year "[0-9]+\\|\\*")
- (l (length date-form))
- (d-name-pos (- l (length (memq 'dayname date-form))))
- (d-name-pos (if (/= l d-name-pos) (+ 2 d-name-pos)))
- (m-name-pos (- l (length (memq 'monthname date-form))))
- (m-name-pos (if (/= l m-name-pos) (+ 2 m-name-pos)))
- (d-pos (- l (length (memq 'day date-form))))
- (d-pos (if (/= l d-pos) (+ 2 d-pos)))
- (m-pos (- l (length (memq 'month date-form))))
- (m-pos (if (/= l m-pos) (+ 2 m-pos)))
- (y-pos (- l (length (memq 'year date-form))))
- (y-pos (if (/= l y-pos) (+ 2 y-pos)))
- (regexp
- (concat
- "\\(\\`\\|\^M\\|\n\\)\\("
- (mapconcat 'eval date-form "\\)\\(")
- "\\)"))
- (case-fold-search t))
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (let* ((dd-name
- (if d-name-pos
- (buffer-substring
- (match-beginning d-name-pos)
- (match-end d-name-pos))))
- (mm-name
- (if m-name-pos
- (buffer-substring
- (match-beginning m-name-pos)
- (match-end m-name-pos))))
- (mm (string-to-int
- (if m-pos
- (buffer-substring
- (match-beginning m-pos)
- (match-end m-pos))
- "")))
- (dd (string-to-int
- (if d-pos
- (buffer-substring
- (match-beginning d-pos)
- (match-end d-pos))
- "")))
- (y-str (if y-pos
- (buffer-substring
- (match-beginning y-pos)
- (match-end y-pos))))
- (yy (if (not y-str)
- 0
- (if (and (= (length y-str) 2)
- abbreviated-calendar-year)
- (let* ((current-y
- (extract-calendar-year
- (calendar-current-date)))
- (y (+ (string-to-int y-str)
- (* 100
- (/ current-y 100)))))
- (if (> (- y current-y) 50)
- (- y 100)
- (if (> (- current-y y) 50)
- (+ y 100)
- y)))
- (string-to-int y-str)))))
- (if dd-name
- (mark-calendar-days-named
- (cdr (assoc (capitalize (substring dd-name 0 3))
- (calendar-make-alist
- calendar-day-name-array
- 0
- '(lambda (x) (substring x 0 3))))))
- (if mm-name
- (if (string-equal mm-name "*")
- (setq mm 0)
- (setq mm
- (cdr (assoc
- (capitalize
- (substring mm-name 0 3))
- (calendar-make-alist
- calendar-month-name-array
- 1
- '(lambda (x) (substring x 0 3)))
- )))))
- (mark-calendar-date-pattern mm dd yy))))
- (setq d (cdr d))))
- (mark-sexp-diary-entries)
- (run-hooks 'nongregorian-diary-marking-hook
- 'mark-diary-entries-hook)
- (set-syntax-table old-diary-syntax-table)
- (message "Marking diary entries...done")))
- (error "Your diary file is not readable!"))
- (error "You don't have a diary file!"))))
-
-(defun mark-sexp-diary-entries ()
- "Mark days in the calendar window that have sexp diary entries.
-Each entry in the diary file (or included files) visible in the calendar window
-is marked. See the documentation for the function `list-sexp-diary-entries'."
- (let* ((sexp-mark (regexp-quote sexp-diary-entry-symbol))
- (s-entry (concat "\\(\\`\\|\^M\\|\n\\)" sexp-mark "("))
- (m)
- (y)
- (first-date)
- (last-date))
- (save-excursion
- (set-buffer calendar-buffer)
- (setq m displayed-month)
- (setq y displayed-year))
- (increment-calendar-month m y -1)
- (setq first-date
- (calendar-absolute-from-gregorian (list m 1 y)))
- (increment-calendar-month m y 2)
- (setq last-date
- (calendar-absolute-from-gregorian
- (list m (calendar-last-day-of-month m y) y)))
- (goto-char (point-min))
- (while (re-search-forward s-entry nil t)
- (backward-char 1)
- (let ((sexp-start (point))
- (sexp)
- (entry)
- (entry-start)
- (line-start))
- (forward-sexp)
- (setq sexp (buffer-substring sexp-start (point)))
- (save-excursion
- (re-search-backward "\^M\\|\n\\|\\`")
- (setq line-start (point)))
- (forward-char 1)
- (if (and (or (char-equal (preceding-char) ?\^M)
- (char-equal (preceding-char) ?\n))
- (not (looking-at " \\|\^I")))
- (progn;; Diary entry consists only of the sexp
- (backward-char 1)
- (setq entry ""))
- (setq entry-start (point))
- (re-search-forward "\^M\\|\n" nil t)
- (while (looking-at " \\|\^I")
- (re-search-forward "\^M\\|\n" nil t))
- (backward-char 1)
- (setq entry (buffer-substring entry-start (point)))
- (while (string-match "[\^M]" entry)
- (aset entry (match-beginning 0) ?\n )))
- (calendar-for-loop date from first-date to last-date do
- (if (diary-sexp-entry sexp entry
- (calendar-gregorian-from-absolute date))
- (mark-visible-calendar-date
- (calendar-gregorian-from-absolute date))))))))
-
-(defun mark-included-diary-files ()
- "Mark the diary entries from other diary files with those of the diary file.
-This function is suitable for use as the `mark-diary-entries-hook'; it enables
-you to use shared diary files together with your own. The files included are
-specified in the diary-file by lines of this form:
- #include \"filename\"
-This is recursive; that is, #include directives in diary files thus included
-are obeyed. You can change the `#include' to some other string by
-changing the variable `diary-include-string'."
- (goto-char (point-min))
- (while (re-search-forward
- (concat
- "\\(\\`\\|\^M\\|\n\\)"
- (regexp-quote diary-include-string)
- " \"\\([^\"]*\\)\"")
- nil t)
- (let ((diary-file (substitute-in-file-name
- (buffer-substring (match-beginning 2) (match-end 2))))
- (mark-diary-entries-hook 'mark-included-diary-files))
- (if (file-exists-p diary-file)
- (if (file-readable-p diary-file)
- (progn
- (mark-diary-entries)
- (kill-buffer (get-file-buffer diary-file)))
- (beep)
- (message "Can't read included diary file %s" diary-file)
- (sleep-for 2))
- (beep)
- (message "Can't find included diary file %s" diary-file)
- (sleep-for 2))))
- (goto-char (point-min)))
-
-(defun mark-calendar-days-named (dayname)
- "Mark all dates in the calendar window that are day DAYNAME of the week.
-0 means all Sundays, 1 means all Mondays, and so on."
- (save-excursion
- (set-buffer calendar-buffer)
- (let ((prev-month displayed-month)
- (prev-year displayed-year)
- (succ-month displayed-month)
- (succ-year displayed-year)
- (last-day)
- (day))
- (increment-calendar-month succ-month succ-year 1)
- (increment-calendar-month prev-month prev-year -1)
- (setq day (calendar-absolute-from-gregorian
- (calendar-nth-named-day 1 dayname prev-month prev-year)))
- (setq last-day (calendar-absolute-from-gregorian
- (calendar-nth-named-day -1 dayname succ-month succ-year)))
- (while (<= day last-day)
- (mark-visible-calendar-date (calendar-gregorian-from-absolute day))
- (setq day (+ day 7))))))
-
-(defun mark-calendar-date-pattern (month day year)
- "Mark all dates in the calendar window that conform to MONTH/DAY/YEAR.
-A value of 0 in any position is a wildcard."
- (save-excursion
- (set-buffer calendar-buffer)
- (let ((m displayed-month)
- (y displayed-year))
- (increment-calendar-month m y -1)
- (calendar-for-loop i from 0 to 2 do
- (mark-calendar-month m y month day year)
- (increment-calendar-month m y 1)))))
-
-(defun mark-calendar-month (month year p-month p-day p-year)
- "Mark dates in the MONTH/YEAR that conform to pattern P-MONTH/P_DAY/P-YEAR.
-A value of 0 in any position of the pattern is a wildcard."
- (if (or (and (= month p-month)
- (or (= p-year 0) (= year p-year)))
- (and (= p-month 0)
- (or (= p-year 0) (= year p-year))))
- (if (= p-day 0)
- (calendar-for-loop
- i from 1 to (calendar-last-day-of-month month year) do
- (mark-visible-calendar-date (list month i year)))
- (mark-visible-calendar-date (list month p-day year)))))
-
-(defun sort-diary-entries ()
- "Sort the list of diary entries by time of day."
- (setq diary-entries-list (sort diary-entries-list 'diary-entry-compare)))
-
-(defun diary-entry-compare (e1 e2)
- "Returns t if E1 is earlier than E2."
- (or (calendar-date-compare e1 e2)
- (and (calendar-date-equal (car e1) (car e2))
- (< (diary-entry-time (car (cdr e1)))
- (diary-entry-time (car (cdr e2)))))))
-
-(defun diary-entry-time (s)
- "Time at the beginning of the string S in a military-style integer.
-For example, returns 1325 for 1:25pm. Returns -9999 if no time is recognized.
-The recognized forms are XXXX or X:XX or XX:XX (military time), XXam or XXpm,
-and XX:XXam or XX:XXpm."
- (cond ((string-match;; Military time
- "^[ \t]*\\([0-9]?[0-9]\\):?\\([0-9][0-9]\\)\\(\\>\\|[^ap]\\)" s)
- (+ (* 100 (string-to-int
- (substring s (match-beginning 1) (match-end 1))))
- (string-to-int (substring s (match-beginning 2) (match-end 2)))))
- ((string-match;; Hour only XXam or XXpm
- "^[ \t]*\\([0-9]?[0-9]\\)\\([ap]\\)m\\>" s)
- (+ (* 100 (% (string-to-int
- (substring s (match-beginning 1) (match-end 1)))
- 12))
- (if (string-equal "a"
- (substring s (match-beginning 2) (match-end 2)))
- 0 1200)))
- ((string-match;; Hour and minute XX:XXam or XX:XXpm
- "^[ \t]*\\([0-9]?[0-9]\\):\\([0-9][0-9]\\)\\([ap]\\)m\\>" s)
- (+ (* 100 (% (string-to-int
- (substring s (match-beginning 1) (match-end 1)))
- 12))
- (string-to-int (substring s (match-beginning 2) (match-end 2)))
- (if (string-equal "a"
- (substring s (match-beginning 3) (match-end 3)))
- 0 1200)))
- (t -9999)));; Unrecognizable
-
-(defun list-hebrew-diary-entries ()
- "Add any Hebrew date entries from the diary file to `diary-entries-list'.
-Hebrew date diary entries must be prefaced by `hebrew-diary-entry-symbol'
-\(normally an `H'). The same diary date forms govern the style of the Hebrew
-calendar entries, except that the Hebrew month names must be spelled in full.
-The Hebrew months are numbered from 1 to 13 with Nisan being 1, 12 being
-Adar I and 13 being Adar II; you must use `Adar I' if you want Adar of a
-common Hebrew year. If a Hebrew date diary entry begins with a
-`diary-nonmarking-symbol', the entry will appear in the diary listing, but will
-not be marked in the calendar. This function is provided for use with the
-`nongregorian-diary-listing-hook'."
- (if (< 0 number)
- (let ((buffer-read-only nil)
- (diary-modified (buffer-modified-p))
- (gdate original-date)
- (mark (regexp-quote diary-nonmarking-symbol)))
- (calendar-for-loop i from 1 to number do
- (let* ((d diary-date-forms)
- (hdate (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian gdate)))
- (month (extract-calendar-month hdate))
- (day (extract-calendar-day hdate))
- (year (extract-calendar-year hdate)))
- (while d
- (let*
- ((date-form (if (equal (car (car d)) 'backup)
- (cdr (car d))
- (car d)))
- (backup (equal (car (car d)) 'backup))
- (dayname
- (concat
- (calendar-day-name gdate) "\\|"
- (substring (calendar-day-name gdate) 0 3) ".?"))
- (calendar-month-name-array
- calendar-hebrew-month-name-array-leap-year)
- (monthname
- (concat
- "\\*\\|"
- (calendar-month-name month)))
- (month (concat "\\*\\|0*" (int-to-string month)))
- (day (concat "\\*\\|0*" (int-to-string day)))
- (year
- (concat
- "\\*\\|0*" (int-to-string year)
- (if abbreviated-calendar-year
- (concat "\\|" (int-to-string (% year 100)))
- "")))
- (regexp
- (concat
- "\\(\\`\\|\^M\\|\n\\)" mark "?"
- (regexp-quote hebrew-diary-entry-symbol)
- "\\("
- (mapconcat 'eval date-form "\\)\\(")
- "\\)"))
- (case-fold-search t))
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (if backup (re-search-backward "\\<" nil t))
- (if (and (or (char-equal (preceding-char) ?\^M)
- (char-equal (preceding-char) ?\n))
- (not (looking-at " \\|\^I")))
- ;; Diary entry that consists only of date.
- (backward-char 1)
- ;; Found a nonempty diary entry--make it visible and
- ;; add it to the list.
- (let ((entry-start (point))
- (date-start))
- (re-search-backward "\^M\\|\n\\|\\`")
- (setq date-start (point))
- (re-search-forward "\^M\\|\n" nil t 2)
- (while (looking-at " \\|\^I")
- (re-search-forward "\^M\\|\n" nil t))
- (backward-char 1)
- (subst-char-in-region date-start (point) ?\^M ?\n t)
- (add-to-diary-list
- gdate (buffer-substring entry-start (point)))))))
- (setq d (cdr d))))
- (setq gdate
- (calendar-gregorian-from-absolute
- (1+ (calendar-absolute-from-gregorian gdate)))))
- (set-buffer-modified-p diary-modified))
- (goto-char (point-min))))
-
-(defun mark-hebrew-diary-entries ()
- "Mark days in the calendar window that have Hebrew date diary entries.
-Each entry in diary-file (or included files) visible in the calendar window
-is marked. Hebrew date entries are prefaced by a hebrew-diary-entry-symbol
-\(normally an `H'). The same diary-date-forms govern the style of the Hebrew
-calendar entries, except that the Hebrew month names must be spelled in full.
-The Hebrew months are numbered from 1 to 13 with Nisan being 1, 12 being
-Adar I and 13 being Adar II; you must use `Adar I' if you want Adar of a
-common Hebrew year. Hebrew date diary entries that begin with a
-diary-nonmarking symbol will not be marked in the calendar. This function
-is provided for use as part of the nongregorian-diary-marking-hook."
- (let ((d diary-date-forms))
- (while d
- (let*
- ((date-form (if (equal (car (car d)) 'backup)
- (cdr (car d))
- (car d)));; ignore 'backup directive
- (dayname (diary-name-pattern calendar-day-name-array))
- (monthname
- (concat
- (diary-name-pattern calendar-hebrew-month-name-array-leap-year t)
- "\\|\\*"))
- (month "[0-9]+\\|\\*")
- (day "[0-9]+\\|\\*")
- (year "[0-9]+\\|\\*")
- (l (length date-form))
- (d-name-pos (- l (length (memq 'dayname date-form))))
- (d-name-pos (if (/= l d-name-pos) (+ 2 d-name-pos)))
- (m-name-pos (- l (length (memq 'monthname date-form))))
- (m-name-pos (if (/= l m-name-pos) (+ 2 m-name-pos)))
- (d-pos (- l (length (memq 'day date-form))))
- (d-pos (if (/= l d-pos) (+ 2 d-pos)))
- (m-pos (- l (length (memq 'month date-form))))
- (m-pos (if (/= l m-pos) (+ 2 m-pos)))
- (y-pos (- l (length (memq 'year date-form))))
- (y-pos (if (/= l y-pos) (+ 2 y-pos)))
- (regexp
- (concat
- "\\(\\`\\|\^M\\|\n\\)"
- (regexp-quote hebrew-diary-entry-symbol)
- "\\("
- (mapconcat 'eval date-form "\\)\\(")
- "\\)"))
- (case-fold-search t))
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (let* ((dd-name
- (if d-name-pos
- (buffer-substring
- (match-beginning d-name-pos)
- (match-end d-name-pos))))
- (mm-name
- (if m-name-pos
- (buffer-substring
- (match-beginning m-name-pos)
- (match-end m-name-pos))))
- (mm (string-to-int
- (if m-pos
- (buffer-substring
- (match-beginning m-pos)
- (match-end m-pos))
- "")))
- (dd (string-to-int
- (if d-pos
- (buffer-substring
- (match-beginning d-pos)
- (match-end d-pos))
- "")))
- (y-str (if y-pos
- (buffer-substring
- (match-beginning y-pos)
- (match-end y-pos))))
- (yy (if (not y-str)
- 0
- (if (and (= (length y-str) 2)
- abbreviated-calendar-year)
- (let* ((current-y
- (extract-calendar-year
- (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-current-date)))))
- (y (+ (string-to-int y-str)
- (* 100 (/ current-y 100)))))
- (if (> (- y current-y) 50)
- (- y 100)
- (if (> (- current-y y) 50)
- (+ y 100)
- y)))
- (string-to-int y-str)))))
- (if dd-name
- (mark-calendar-days-named
- (cdr (assoc (capitalize (substring dd-name 0 3))
- (calendar-make-alist
- calendar-day-name-array
- 0
- '(lambda (x) (substring x 0 3))))))
- (if mm-name
- (if (string-equal mm-name "*")
- (setq mm 0)
- (setq
- mm
- (cdr
- (assoc
- (capitalize mm-name)
- (calendar-make-alist
- calendar-hebrew-month-name-array-leap-year))))))
- (mark-hebrew-calendar-date-pattern mm dd yy)))))
- (setq d (cdr d)))))
-
-(defun mark-hebrew-calendar-date-pattern (month day year)
- "Mark dates in calendar window that conform to Hebrew date MONTH/DAY/YEAR.
-A value of 0 in any position is a wildcard."
- (save-excursion
- (set-buffer calendar-buffer)
- (if (and (/= 0 month) (/= 0 day))
- (if (/= 0 year)
- ;; Fully specified Hebrew date.
- (let ((date (calendar-gregorian-from-absolute
- (calendar-absolute-from-hebrew
- (list month day year)))))
- (if (calendar-date-is-visible-p date)
- (mark-visible-calendar-date date)))
- ;; Month and day in any year--this taken from the holiday stuff.
- (if (memq displayed-month;; This test is only to speed things up a
- (list ;; bit; it works fine without the test too.
- (if (< 11 month) (- month 11) (+ month 1))
- (if (< 10 month) (- month 10) (+ month 2))
- (if (< 9 month) (- month 9) (+ month 3))
- (if (< 8 month) (- month 8) (+ month 4))
- (if (< 7 month) (- month 7) (+ month 5))))
- (let ((m1 displayed-month)
- (y1 displayed-year)
- (m2 displayed-month)
- (y2 displayed-year)
- (year))
- (increment-calendar-month m1 y1 -1)
- (increment-calendar-month m2 y2 1)
- (let* ((start-date (calendar-absolute-from-gregorian
- (list m1 1 y1)))
- (end-date (calendar-absolute-from-gregorian
- (list m2
- (calendar-last-day-of-month m2 y2)
- y2)))
- (hebrew-start
- (calendar-hebrew-from-absolute start-date))
- (hebrew-end (calendar-hebrew-from-absolute end-date))
- (hebrew-y1 (extract-calendar-year hebrew-start))
- (hebrew-y2 (extract-calendar-year hebrew-end)))
- (setq year (if (< 6 month) hebrew-y2 hebrew-y1))
- (let ((date (calendar-gregorian-from-absolute
- (calendar-absolute-from-hebrew
- (list month day year)))))
- (if (calendar-date-is-visible-p date)
- (mark-visible-calendar-date date)))))))
- ;; Not one of the simple cases--check all visible dates for match.
- ;; Actually, the following code takes care of ALL of the cases, but
- ;; it's much too slow to be used for the simple (common) cases.
- (let ((m displayed-month)
- (y displayed-year)
- (first-date)
- (last-date))
- (increment-calendar-month m y -1)
- (setq first-date
- (calendar-absolute-from-gregorian
- (list m 1 y)))
- (increment-calendar-month m y 2)
- (setq last-date
- (calendar-absolute-from-gregorian
- (list m (calendar-last-day-of-month m y) y)))
- (calendar-for-loop date from first-date to last-date do
- (let* ((h-date (calendar-hebrew-from-absolute date))
- (h-month (extract-calendar-month h-date))
- (h-day (extract-calendar-day h-date))
- (h-year (extract-calendar-year h-date)))
- (and (or (zerop month)
- (= month h-month))
- (or (zerop day)
- (= day h-day))
- (or (zerop year)
- (= year h-year))
- (mark-visible-calendar-date
- (calendar-gregorian-from-absolute date)))))))))
-
-(defun list-sexp-diary-entries (date)
- "Add sexp entries for DATE from the diary file to `diary-entries-list'.
-Also, Make them visible in the diary file. Returns t if any entries were
-found.
-
-Sexp diary entries must be prefaced by a `sexp-diary-entry-symbol' (normally
-`%%'). The form of a sexp diary entry is
-
- %%(SEXP) ENTRY
-
-Both ENTRY and DATE are globally available when the SEXP is evaluated. If the
-SEXP yields the value nil, the diary entry does not apply. If it yields a
-non-nil value, ENTRY will be taken to apply to DATE; if the non-nil value is a
-string, that string will be the diary entry in the fancy diary display.
-
-For example, the following diary entry will apply to the 21st of the month
-if it is a weekday and the Friday before if the 21st is on a weekend:
-
- &%%(let ((dayname (calendar-day-of-week date))
- (day (extract-calendar-day date)))
- (or
- (and (= day 21) (memq dayname '(1 2 3 4 5)))
- (and (memq day '(19 20)) (= dayname 5)))
- ) UIUC pay checks deposited
-
-A number of built-in functions are available for this type of diary entry:
-
- %%(diary-float MONTH DAYNAME N) text
- Entry will appear on the Nth DAYNAME of MONTH.
- (DAYNAME=0 means Sunday, 1 means Monday, and so on;
- if N is negative it counts backward from the end of
- the month. MONTH can be a list of months, a single
- month, or t to specify all months.
-
- %%(diary-block M1 D1 Y1 M2 D2 Y2) text
- Entry will appear on dates between M1/D1/Y1 and M2/D2/Y2,
- inclusive. (If `european-calendar-style' is t, the
- order of the parameters should be changed to D1, M1, Y1,
- D2, M2, Y2.)
-
- %%(diary-anniversary MONTH DAY YEAR) text
- Entry will appear on anniversary dates of MONTH DAY, YEAR.
- (If `european-calendar-style' is t, the order of the
- parameters should be changed to DAY, MONTH, YEAR.) Text
- can contain %d or %d%s; %d will be replaced by the number
- of years since the MONTH DAY, YEAR and %s will be replaced
- by the ordinal ending of that number (that is, `st', `nd',
- `rd' or `th', as appropriate. The anniversary of February
- 29 is considered to be March 1 in a non-leap year.
-
- %%(diary-cyclic N MONTH DAY YEAR) text
- Entry will appear every N days, starting MONTH DAY, YEAR.
- (If `european-calendar-style' is t, the order of the
- parameters should be changed to N, DAY, MONTH, YEAR.) Text
- can contain %d or %d%s; %d will be replaced by the number
- of repetitions since the MONTH DAY, YEAR and %s will
- be replaced by the ordinal ending of that number (that is,
- `st', `nd', `rd' or `th', as appropriate.
-
- %%(diary-day-of-year)
- Diary entries giving the day of the year and the number of
- days remaining in the year will be made every day. Note
- that since there is no text, it makes sense only if the
- fancy diary display is used.
-
- %%(diary-iso-date)
- Diary entries giving the corresponding ISO commercial date
- will be made every day. Note that since there is no text,
- it makes sense only if the fancy diary display is used.
-
- %%(diary-french-date)
- Diary entries giving the corresponding French Revolutionary
- date will be made every day. Note that since there is no
- text, it makes sense only if the fancy diary display is used.
-
- %%(diary-islamic-date)
- Diary entries giving the corresponding Islamic date will be
- made every day. Note that since there is no text, it
- makes sense only if the fancy diary display is used.
-
- %%(diary-hebrew-date)
- Diary entries giving the corresponding Hebrew date will be
- made every day. Note that since there is no text, it
- makes sense only if the fancy diary display is used.
-
- %%(diary-astro-day-number) Diary entries giving the corresponding
- astronomical (Julian) day number will be made every day.
- Note that since there is no text, it makes sense only if the
- fancy diary display is used.
-
- %%(diary-julian-date) Diary entries giving the corresponding
- Julian date will be made every day. Note that since
- there is no text, it makes sense only if the fancy diary
- display is used.
-
- %%(diary-sunrise-sunset)
- Diary entries giving the local times of sunrise and sunset
- will be made every day. Note that since there is no text,
- it makes sense only if the fancy diary display is used.
- Floating point required.
-
- %%(diary-phases-of-moon)
- Diary entries giving the times of the phases of the moon
- will be when appropriate. Note that since there is no text,
- it makes sense only if the fancy diary display is used.
- Floating point required.
-
- %%(diary-yahrzeit MONTH DAY YEAR) text
- Text is assumed to be the name of the person; the date is
- the date of death on the *civil* calendar. The diary entry
- will appear on the proper Hebrew-date anniversary and on the
- day before. (If `european-calendar-style' is t, the order
- of the parameters should be changed to DAY, MONTH, YEAR.)
-
- %%(diary-rosh-hodesh)
- Diary entries will be made on the dates of Rosh Hodesh on
- the Hebrew calendar. Note that since there is no text, it
- makes sense only if the fancy diary display is used.
-
- %%(diary-parasha)
- Diary entries giving the weekly parasha will be made on
- every Saturday. Note that since there is no text, it
- makes sense only if the fancy diary display is used.
-
- %%(diary-omer)
- Diary entries giving the omer count will be made every day
- from Passover to Shavuoth. Note that since there is no text,
- it makes sense only if the fancy diary display is used.
-
-Marking these entries is *extremely* time consuming, so these entries are
-best if they are nonmarking."
- (let* ((mark (regexp-quote diary-nonmarking-symbol))
- (sexp-mark (regexp-quote sexp-diary-entry-symbol))
- (s-entry (concat "\\(\\`\\|\^M\\|\n\\)" mark "?" sexp-mark "("))
- (entry-found))
- (goto-char (point-min))
- (while (re-search-forward s-entry nil t)
- (backward-char 1)
- (let ((sexp-start (point))
- (sexp)
- (entry)
- (entry-start)
- (line-start))
- (forward-sexp)
- (setq sexp (buffer-substring sexp-start (point)))
- (save-excursion
- (re-search-backward "\^M\\|\n\\|\\`")
- (setq line-start (point)))
- (forward-char 1)
- (if (and (or (char-equal (preceding-char) ?\^M)
- (char-equal (preceding-char) ?\n))
- (not (looking-at " \\|\^I")))
- (progn;; Diary entry consists only of the sexp
- (backward-char 1)
- (setq entry ""))
- (setq entry-start (point))
- (re-search-forward "\^M\\|\n" nil t)
- (while (looking-at " \\|\^I")
- (re-search-forward "\^M\\|\n" nil t))
- (backward-char 1)
- (setq entry (buffer-substring entry-start (point)))
- (while (string-match "[\^M]" entry)
- (aset entry (match-beginning 0) ?\n )))
- (let ((diary-entry (diary-sexp-entry sexp entry date)))
- (if diary-entry
- (subst-char-in-region line-start (point) ?\^M ?\n t))
- (add-to-diary-list date diary-entry)
- (setq entry-found (or entry-found diary-entry)))))
- entry-found))
-
-(defun diary-sexp-entry (sexp entry date)
- "Process a SEXP diary ENTRY for DATE."
- (let ((result (if calendar-debug-sexp
- (let ((stack-trace-on-error t))
- (eval (car (read-from-string sexp))))
- (condition-case nil
- (eval (car (read-from-string sexp)))
- (error
- (beep)
- (message "Bad sexp at line %d in %s: %s"
- (save-excursion
- (save-restriction
- (narrow-to-region 1 (point))
- (goto-char (point-min))
- (let ((lines 1))
- (while (re-search-forward "\n\\|\^M" nil t)
- (setq lines (1+ lines)))
- lines)))
- diary-file sexp)
- (sleep-for 2))))))
- (if (stringp result)
- result
- (if result
- entry
- nil))))
-
-(defun diary-block (m1 d1 y1 m2 d2 y2)
- "Block diary entry.
-Entry applies if date is between two dates. Order of the parameters is
-M1, D1, Y1, M2, D2, Y2 `european-calendar-style' is nil, and
-D1, M1, Y1, D2, M2, Y2 if `european-calendar-style' is t."
- (let ((date1 (calendar-absolute-from-gregorian
- (if european-calendar-style
- (list d1 m1 y1)
- (list m1 d1 y1))))
- (date2 (calendar-absolute-from-gregorian
- (if european-calendar-style
- (list d2 m2 y2)
- (list m2 d2 y2))))
- (d (calendar-absolute-from-gregorian date)))
- (if (and (<= date1 d) (<= d date2))
- entry)))
-
-(defun diary-float (month dayname n)
- "Floating diary entry--entry applies if date is the nth dayname of month.
-Parameters are MONTH, DAYNAME, N. MONTH can be a list of months, the constant
-t, or an integer. The constant t means all months. If N is negative, count
-backward from the end of the month."
- (let ((m (extract-calendar-month date))
- (y (extract-calendar-year date)))
- (if (and
- (or (and (listp month) (memq m month))
- (equal m month)
- (eq month t))
- (calendar-date-equal date (calendar-nth-named-day n dayname m y)))
- entry)))
-
-(defun diary-anniversary (month day year)
- "Anniversary diary entry.
-Entry applies if date is the anniversary of MONTH, DAY, YEAR if
-`european-calendar-style' is nil, and DAY, MONTH, YEAR if
-`european-calendar-style' is t. Diary entry can contain `%d' or `%d%s'; the
-%d will be replaced by the number of years since the MONTH DAY, YEAR and the
-%s will be replaced by the ordinal ending of that number (that is, `st', `nd',
-`rd' or `th', as appropriate. The anniversary of February 29 is considered
-to be March 1 in non-leap years."
- (let* ((d (if european-calendar-style
- month
- day))
- (m (if european-calendar-style
- day
- month))
- (y (extract-calendar-year date))
- (diff (- y year)))
- (if (and (= m 2) (= d 29) (not (calendar-leap-year-p y)))
- (setq m 3
- d 1))
- (if (and (> diff 0) (calendar-date-equal (list m d y) date))
- (format entry diff (diary-ordinal-suffix diff)))))
-
-(defun diary-cyclic (n month day year)
- "Cycle diary entry--entry applies every N days starting at MONTH, DAY, YEAR.
-If `european-calendar-style' is t, parameters are N, DAY, MONTH, YEAR.
-ENTRY can contain `%d' or `%d%s'; the %d will be replaced by the number of
-years since the MONTH DAY, YEAR and the %s will be replaced by the ordinal
-ending of that number (that is, `st', `nd', `rd' or `th', as appropriate."
- (let* ((d (if european-calendar-style
- month
- day))
- (m (if european-calendar-style
- day
- month))
- (diff (- (calendar-absolute-from-gregorian date)
- (calendar-absolute-from-gregorian
- (list m d year))))
- (cycle (/ diff n)))
- (if (and (>= diff 0) (zerop (% diff n)))
- (format entry cycle (diary-ordinal-suffix cycle)))))
-
-(defun diary-ordinal-suffix (n)
- "Ordinal suffix for N. (That is, `st', `nd', `rd', or `th', as appropriate.)"
- (if (or (memq (% n 100) '(11 12 13))
- (< 3 (% n 10)))
- "th"
- (aref ["th" "st" "nd" "rd"] (% n 10))))
-
-(defun diary-day-of-year ()
- "Day of year and number of days remaining in the year of date diary entry."
- (calendar-day-of-year-string date))
-
-(defun diary-iso-date ()
- "ISO calendar equivalent of date diary entry."
- (format "ISO date: %s" (calendar-iso-date-string date)))
-
-(defun diary-islamic-date ()
- "Islamic calendar equivalent of date diary entry."
- (let ((i (calendar-islamic-date-string (calendar-cursor-to-date t))))
- (if (string-equal i "")
- "Date is pre-Islamic"
- (format "Islamic date (until sunset): %s" i))))
-
-(defun diary-hebrew-date ()
- "Hebrew calendar equivalent of date diary entry."
- (format "Hebrew date (until sunset): %s" (calendar-hebrew-date-string date)))
-
-(defun diary-julian-date ()
- "Julian calendar equivalent of date diary entry."
- (format "Julian date: %s" (calendar-julian-date-string date)))
-
-(defun diary-astro-day-number ()
- "Astronomical (Julian) day number diary entry."
- (format "Astronomical (Julian) day number %s"
- (calendar-astro-date-string date)))
-
-(defun diary-omer ()
- "Omer count diary entry.
-Entry applies if date is within 50 days after Passover."
- (let* ((passover
- (calendar-absolute-from-hebrew
- (list 1 15 (+ (extract-calendar-year date) 3760))))
- (omer (- (calendar-absolute-from-gregorian date) passover))
- (week (/ omer 7))
- (day (% omer 7)))
- (if (and (> omer 0) (< omer 50))
- (format "Day %d%s of the omer (until sunset)"
- omer
- (if (zerop week)
- ""
- (format ", that is, %d week%s%s"
- week
- (if (= week 1) "" "s")
- (if (zerop day)
- ""
- (format " and %d day%s"
- day (if (= day 1) "" "s")))))))))
-
-(defun diary-yahrzeit (death-month death-day death-year)
- "Yahrzeit diary entry--entry applies if date is yahrzeit or the day before.
-Parameters are DEATH-MONTH, DEATH-DAY, DEATH-YEAR; the diary entry is assumed
-to be the name of the person. Date of death is on the *civil* calendar;
-although the date of death is specified by the civil calendar, the proper
-Hebrew calendar yahrzeit is determined. If `european-calendar-style' is t, the
-order of the parameters is changed to DEATH-DAY, DEATH-MONTH, DEATH-YEAR."
- (let* ((h-date (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (if european-calendar-style
- (list death-day death-month death-year)
- (list death-month death-day death-year)))))
- (h-month (extract-calendar-month h-date))
- (h-day (extract-calendar-day h-date))
- (h-year (extract-calendar-year h-date))
- (d (calendar-absolute-from-gregorian date))
- (yr (extract-calendar-year (calendar-hebrew-from-absolute d)))
- (diff (- yr h-year))
- (y (hebrew-calendar-yahrzeit h-date yr)))
- (if (and (> diff 0) (or (= y d) (= y (1+ d))))
- (format "Yahrzeit of %s%s: %d%s anniversary"
- entry
- (if (= y d) "" " (evening)")
- diff
- (cond ((= (% diff 10) 1) "st")
- ((= (% diff 10) 2) "nd")
- ((= (% diff 10) 3) "rd")
- (t "th"))))))
-
-(defun diary-rosh-hodesh ()
- "Rosh Hodesh diary entry.
-Entry applies if date is Rosh Hodesh, the day before, or the Saturday before."
- (let* ((d (calendar-absolute-from-gregorian date))
- (h-date (calendar-hebrew-from-absolute d))
- (h-month (extract-calendar-month h-date))
- (h-day (extract-calendar-day h-date))
- (h-year (extract-calendar-year h-date))
- (leap-year (hebrew-calendar-leap-year-p h-year))
- (last-day (hebrew-calendar-last-day-of-month h-month h-year))
- (h-month-names
- (if leap-year
- calendar-hebrew-month-name-array-leap-year
- calendar-hebrew-month-name-array-common-year))
- (this-month (aref h-month-names (1- h-month)))
- (h-yesterday (extract-calendar-day
- (calendar-hebrew-from-absolute (1- d)))))
- (if (or (= h-day 30) (and (= h-day 1) (/= h-month 7)))
- (format
- "Rosh Hodesh %s"
- (if (= h-day 30)
- (format
- "%s (first day)"
- ;; next month must be in the same year since this
- ;; month can't be the last month of the year since
- ;; it has 30 days
- (aref h-month-names h-month))
- (if (= h-yesterday 30)
- (format "%s (second day)" this-month)
- this-month)))
- (if (= (% d 7) 6);; Saturday--check for Shabbat Mevarhim
- (cond ((and (> h-day 22) (/= h-month 6) (= 29 last-day))
- (format "Mevarhim Rosh Hodesh %s (%s)"
- (aref h-month-names
- (if (= h-month
- (hebrew-calendar-last-month-of-year
- h-year))
- 0 h-month))
- (aref calendar-day-name-array (- 29 h-day))))
- ((and (< h-day 30) (> h-day 22) (= 30 last-day))
- (format "Mevarhim Rosh Hodesh %s (%s-%s)"
- (aref h-month-names h-month)
- (if (= h-day 29)
- "tomorrow"
- (aref calendar-day-name-array (- 29 h-day)))
- (aref calendar-day-name-array
- (% (- 30 h-day) 7)))))
- (if (and (= h-day 29) (/= h-month 6))
- (format "Erev Rosh Hodesh %s"
- (aref h-month-names
- (if (= h-month
- (hebrew-calendar-last-month-of-year
- h-year))
- 0 h-month))))))))
-
-(defun diary-parasha ()
- "Parasha diary entry--entry applies if date is a Saturday."
- (let ((d (calendar-absolute-from-gregorian date)))
- (if (= (% d 7) 6);; Saturday
- (let*
- ((h-year (extract-calendar-year
- (calendar-hebrew-from-absolute d)))
- (rosh-hashannah
- (calendar-absolute-from-hebrew (list 7 1 h-year)))
- (passover
- (calendar-absolute-from-hebrew (list 1 15 h-year)))
- (rosh-hashannah-day
- (aref calendar-day-name-array (% rosh-hashannah 7)))
- (passover-day
- (aref calendar-day-name-array (% passover 7)))
- (long-h (hebrew-calendar-long-heshvan-p h-year))
- (short-k (hebrew-calendar-short-kislev-p h-year))
- (type (cond ((and long-h (not short-k)) "complete")
- ((and (not long-h) short-k) "incomplete")
- (t "regular")))
- (year-format
- (symbol-value
- (intern (format "hebrew-calendar-year-%s-%s-%s";; keviah
- rosh-hashannah-day type passover-day))))
- (first-saturday;; of Hebrew year
- (calendar-dayname-on-or-before 6 (+ 6 rosh-hashannah)))
- (saturday;; which Saturday of the Hebrew year
- (/ (- d first-saturday) 7))
- (parasha (aref year-format saturday)))
- (if parasha
- (format
- "Parashat %s"
- (if (listp parasha);; Israel differs from diaspora
- (if (car parasha)
- (format "%s (diaspora), %s (Israel)"
- (hebrew-calendar-parasha-name (car parasha))
- (hebrew-calendar-parasha-name (cdr parasha)))
- (format "%s (Israel)"
- (hebrew-calendar-parasha-name (cdr parasha))))
- (hebrew-calendar-parasha-name parasha))))))))
-
-(defun add-to-diary-list (date string)
- "Add the entry (DATE STRING) to `diary-entries-list'.
-Do nothing if DATE or STRING is nil."
- (and date string
- (setq diary-entries-list
- (append diary-entries-list (list (list date string))))))
-
-(defvar hebrew-calendar-parashiot-names
-["Bereshith" "Noah" "Lech L'cha" "Vayera" "Hayei Sarah" "Toledoth"
- "Vayetze" "Vayishlah" "Vayeshev" "Mikketz" "Vayiggash" "Vayhi"
- "Shemoth" "Vaera" "Bo" "Beshallah" "Yithro" "Mishpatim"
- "Terumah" "Tetzavveh" "Ki Tissa" "Vayakhel" "Pekudei" "Vayikra"
- "Tzav" "Shemini" "Tazria" "Metzora" "Aharei Moth" "Kedoshim"
- "Emor" "Behar" "Behukkotai" "Bemidbar" "Naso" "Behaalot'cha"
- "Shelah L'cha" "Korah" "Hukkath" "Balak" "Pinhas" "Mattoth"
- "Masei" "Devarim" "Vaethanan" "Ekev" "Reeh" "Shofetim"
- "Ki Tetze" "Ki Tavo" "Nitzavim" "Vayelech" "Haazinu"]
- "The names of the parashiot in the Torah.")
-
-;; The seven ordinary year types (keviot)
-
-(defconst hebrew-calendar-year-Saturday-incomplete-Sunday
- [nil 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [21 22]
- 23 24 nil 25 [26 27] [28 29] 30 [31 32] 33 34 35 36 37 38 39 40 [41 42]
- 43 44 45 46 47 48 49 50]
- "The structure of the parashiot.
-Hebrew year starts on Saturday, is `incomplete' (Heshvan and Kislev each have
-29 days), and has Passover start on Sunday.")
-
-(defconst hebrew-calendar-year-Saturday-complete-Tuesday
- [nil 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [21 22]
- 23 24 nil 25 [26 27] [28 29] 30 [31 32] 33 34 35 36 37 38 39 40 [41 42]
- 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Saturday, is `complete' (Heshvan and Kislev each
-have 30 days), and has Passover start on Tuesday.")
-
-(defconst hebrew-calendar-year-Monday-incomplete-Tuesday
- [51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [21 22]
- 23 24 nil 25 [26 27] [28 29] 30 [31 32] 33 34 35 36 37 38 39 40 [41 42]
- 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Monday, is `incomplete' (Heshvan and Kislev each
-have 29 days), and has Passover start on Tuesday.")
-
-(defconst hebrew-calendar-year-Monday-complete-Thursday
- [51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [21 22]
- 23 24 nil 25 [26 27] [28 29] 30 [31 32] 33 (nil . 34) (34 . 35) (35 . 36)
- (36 . 37) (37 . 38) ([38 39] . 39) 40 [41 42] 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Monday, is `complete' (Heshvan and Kislev each have
-30 days), and has Passover start on Thursday.")
-
-(defconst hebrew-calendar-year-Tuesday-regular-Thursday
- [51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [21 22]
- 23 24 nil 25 [26 27] [28 29] 30 [31 32] 33 (nil . 34) (34 . 35) (35 . 36)
- (36 . 37) (37 . 38) ([38 39] . 39) 40 [41 42] 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Tuesday, is `regular' (Heshvan has 29 days and
-Kislev has 30 days), and has Passover start on Thursday.")
-
-(defconst hebrew-calendar-year-Thursday-regular-Saturday
- [52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [21 22] 23
- 24 nil (nil . 25) (25 . [26 27]) ([26 27] . [28 29]) ([28 29] . 30)
- (30 . 31) ([31 32] . 32) 33 34 35 36 37 38 39 40 [41 42] 43 44 45 46 47 48
- 49 50]
- "The structure of the parashiot.
-Hebrew year that starts on Thursday, is `regular' (Heshvan has 29 days and
-Kislev has 30 days), and has Passover start on Saturday.")
-
-(defconst hebrew-calendar-year-Thursday-complete-Sunday
- [52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 nil 25 [26 27] [28 29] 30 [31 32] 33 34 35 36 37 38 39 40 [41 42]
- 43 44 45 46 47 48 49 50]
- "The structure of the parashiot.
-Hebrew year that starts on Thursday, is `complete' (Heshvan and Kislev each
-have 30 days), and has Passover start on Sunday.")
-
-;; The seven leap year types (keviot)
-
-(defconst hebrew-calendar-year-Saturday-incomplete-Tuesday
- [nil 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 nil 28 29 30 31 32 33 34 35 36 37 38 39 40 [41 42]
- 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Saturday, is `incomplete' (Heshvan and Kislev each
-have 29 days), and has Passover start on Tuesday.")
-
-(defconst hebrew-calendar-year-Saturday-complete-Thursday
- [nil 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 nil 28 29 30 31 32 33 (nil . 34) (34 . 35) (35 . 36)
- (36 . 37) (37 . 38) ([38 39] . 39) 40 [41 42] 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Saturday, is `complete' (Heshvan and Kislev each
-have 30 days), and has Passover start on Thursday.")
-
-(defconst hebrew-calendar-year-Monday-incomplete-Thursday
- [51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 nil 28 29 30 31 32 33 (nil . 34) (34 . 35) (35 . 36)
- (36 . 37) (37 . 38) ([38 39] . 39) 40 [41 42] 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Monday, is `incomplete' (Heshvan and Kislev each
-have 29 days), and has Passover start on Thursday.")
-
-(defconst hebrew-calendar-year-Monday-complete-Saturday
- [51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 nil (nil . 28) (28 . 29) (29 . 30) (30 . 31) (31 . 32)
- (32 . 33) (33 . 34) (34 . 35) (35 . 36) (36 . 37) (37 . 38) (38 . 39)
- (39 . 40) (40 . 41) ([41 42] . 42) 43 44 45 46 47 48 49 50]
- "The structure of the parashiot.
-Hebrew year that starts on Monday, is `complete' (Heshvan and Kislev each have
-30 days), and has Passover start on Saturday.")
-
-(defconst hebrew-calendar-year-Tuesday-regular-Saturday
- [51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 nil (nil . 28) (28 . 29) (29 . 30) (30 . 31) (31 . 32)
- (32 . 33) (33 . 34) (34 . 35) (35 . 36) (36 . 37) (37 . 38) (38 . 39)
- (39 . 40) (40 . 41) ([41 42] . 42) 43 44 45 46 47 48 49 50]
- "The structure of the parashiot.
-Hebrew year that starts on Tuesday, is `regular' (Heshvan has 29 days and
-Kislev has 30 days), and has Passover start on Saturday.")
-
-(defconst hebrew-calendar-year-Thursday-incomplete-Sunday
- [52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 28 nil 29 30 31 32 33 34 35 36 37 38 39 40 41 42
- 43 44 45 46 47 48 49 50]
- "The structure of the parashiot.
-Hebrew year that starts on Thursday, is `incomplete' (Heshvan and Kislev both
-have 29 days), and has Passover start on Sunday.")
-
-(defconst hebrew-calendar-year-Thursday-complete-Tuesday
- [52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 28 nil 29 30 31 32 33 34 35 36 37 38 39 40 41 42
- 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Thursday, is `complete' (Heshvan and Kislev both
-have 30 days), and has Passover start on Tuesday.")
-
-(defun hebrew-calendar-parasha-name (p)
- "Name(s) corresponding to parasha P."
- (if (arrayp p);; combined parasha
- (format "%s/%s"
- (aref hebrew-calendar-parashiot-names (aref p 0))
- (aref hebrew-calendar-parashiot-names (aref p 1)))
- (aref hebrew-calendar-parashiot-names p)))
-
-(defun list-islamic-diary-entries ()
- "Add any Islamic date entries from the diary file to `diary-entries-list'.
-Islamic date diary entries must be prefaced by an `islamic-diary-entry-symbol'
-\(normally an `I'). The same diary date forms govern the style of the Islamic
-calendar entries, except that the Islamic month names must be spelled in full.
-The Islamic months are numbered from 1 to 12 with Muharram being 1 and 12 being
-Dhu al-Hijjah. If an Islamic date diary entry begins with a
-`diary-nonmarking-symbol', the entry will appear in the diary listing, but will
-not be marked in the calendar. This function is provided for use with the
-`nongregorian-diary-listing-hook'."
- (if (< 0 number)
- (let ((buffer-read-only nil)
- (diary-modified (buffer-modified-p))
- (gdate original-date)
- (mark (regexp-quote diary-nonmarking-symbol)))
- (calendar-for-loop i from 1 to number do
- (let* ((d diary-date-forms)
- (idate (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian gdate)))
- (month (extract-calendar-month idate))
- (day (extract-calendar-day idate))
- (year (extract-calendar-year idate)))
- (while d
- (let*
- ((date-form (if (equal (car (car d)) 'backup)
- (cdr (car d))
- (car d)))
- (backup (equal (car (car d)) 'backup))
- (dayname
- (concat
- (calendar-day-name gdate) "\\|"
- (substring (calendar-day-name gdate) 0 3) ".?"))
- (calendar-month-name-array
- calendar-islamic-month-name-array)
- (monthname
- (concat
- "\\*\\|"
- (calendar-month-name month)))
- (month (concat "\\*\\|0*" (int-to-string month)))
- (day (concat "\\*\\|0*" (int-to-string day)))
- (year
- (concat
- "\\*\\|0*" (int-to-string year)
- (if abbreviated-calendar-year
- (concat "\\|" (int-to-string (% year 100)))
- "")))
- (regexp
- (concat
- "\\(\\`\\|\^M\\|\n\\)" mark "?"
- (regexp-quote islamic-diary-entry-symbol)
- "\\("
- (mapconcat 'eval date-form "\\)\\(")
- "\\)"))
- (case-fold-search t))
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (if backup (re-search-backward "\\<" nil t))
- (if (and (or (char-equal (preceding-char) ?\^M)
- (char-equal (preceding-char) ?\n))
- (not (looking-at " \\|\^I")))
- ;; Diary entry that consists only of date.
- (backward-char 1)
- ;; Found a nonempty diary entry--make it visible and
- ;; add it to the list.
- (let ((entry-start (point))
- (date-start))
- (re-search-backward "\^M\\|\n\\|\\`")
- (setq date-start (point))
- (re-search-forward "\^M\\|\n" nil t 2)
- (while (looking-at " \\|\^I")
- (re-search-forward "\^M\\|\n" nil t))
- (backward-char 1)
- (subst-char-in-region date-start (point) ?\^M ?\n t)
- (add-to-diary-list
- gdate (buffer-substring entry-start (point)))))))
- (setq d (cdr d))))
- (setq gdate
- (calendar-gregorian-from-absolute
- (1+ (calendar-absolute-from-gregorian gdate)))))
- (set-buffer-modified-p diary-modified))
- (goto-char (point-min))))
-
-(defun mark-islamic-diary-entries ()
- "Mark days in the calendar window that have Islamic date diary entries.
-Each entry in diary-file (or included files) visible in the calendar window
-is marked. Islamic date entries are prefaced by a islamic-diary-entry-symbol
-\(normally an `I'). The same diary-date-forms govern the style of the Islamic
-calendar entries, except that the Islamic month names must be spelled in full.
-The Islamic months are numbered from 1 to 12 with Muharram being 1 and 12 being
-Dhu al-Hijjah. Islamic date diary entries that begin with a
-diary-nonmarking-symbol will not be marked in the calendar. This function is
-provided for use as part of the nongregorian-diary-marking-hook."
- (let ((d diary-date-forms))
- (while d
- (let*
- ((date-form (if (equal (car (car d)) 'backup)
- (cdr (car d))
- (car d)));; ignore 'backup directive
- (dayname (diary-name-pattern calendar-day-name-array))
- (monthname
- (concat
- (diary-name-pattern calendar-islamic-month-name-array t)
- "\\|\\*"))
- (month "[0-9]+\\|\\*")
- (day "[0-9]+\\|\\*")
- (year "[0-9]+\\|\\*")
- (l (length date-form))
- (d-name-pos (- l (length (memq 'dayname date-form))))
- (d-name-pos (if (/= l d-name-pos) (+ 2 d-name-pos)))
- (m-name-pos (- l (length (memq 'monthname date-form))))
- (m-name-pos (if (/= l m-name-pos) (+ 2 m-name-pos)))
- (d-pos (- l (length (memq 'day date-form))))
- (d-pos (if (/= l d-pos) (+ 2 d-pos)))
- (m-pos (- l (length (memq 'month date-form))))
- (m-pos (if (/= l m-pos) (+ 2 m-pos)))
- (y-pos (- l (length (memq 'year date-form))))
- (y-pos (if (/= l y-pos) (+ 2 y-pos)))
- (regexp
- (concat
- "\\(\\`\\|\^M\\|\n\\)"
- (regexp-quote islamic-diary-entry-symbol)
- "\\("
- (mapconcat 'eval date-form "\\)\\(")
- "\\)"))
- (case-fold-search t))
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (let* ((dd-name
- (if d-name-pos
- (buffer-substring
- (match-beginning d-name-pos)
- (match-end d-name-pos))))
- (mm-name
- (if m-name-pos
- (buffer-substring
- (match-beginning m-name-pos)
- (match-end m-name-pos))))
- (mm (string-to-int
- (if m-pos
- (buffer-substring
- (match-beginning m-pos)
- (match-end m-pos))
- "")))
- (dd (string-to-int
- (if d-pos
- (buffer-substring
- (match-beginning d-pos)
- (match-end d-pos))
- "")))
- (y-str (if y-pos
- (buffer-substring
- (match-beginning y-pos)
- (match-end y-pos))))
- (yy (if (not y-str)
- 0
- (if (and (= (length y-str) 2)
- abbreviated-calendar-year)
- (let* ((current-y
- (extract-calendar-year
- (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-current-date)))))
- (y (+ (string-to-int y-str)
- (* 100 (/ current-y 100)))))
- (if (> (- y current-y) 50)
- (- y 100)
- (if (> (- current-y y) 50)
- (+ y 100)
- y)))
- (string-to-int y-str)))))
- (if dd-name
- (mark-calendar-days-named
- (cdr (assoc (capitalize (substring dd-name 0 3))
- (calendar-make-alist
- calendar-day-name-array
- 0
- '(lambda (x) (substring x 0 3))))))
- (if mm-name
- (if (string-equal mm-name "*")
- (setq mm 0)
- (setq mm
- (cdr (assoc
- (capitalize mm-name)
- (calendar-make-alist
- calendar-islamic-month-name-array))))))
- (mark-islamic-calendar-date-pattern mm dd yy)))))
- (setq d (cdr d)))))
-
-(defun mark-islamic-calendar-date-pattern (month day year)
- "Mark dates in calendar window that conform to Islamic date MONTH/DAY/YEAR.
-A value of 0 in any position is a wildcard."
- (save-excursion
- (set-buffer calendar-buffer)
- (if (and (/= 0 month) (/= 0 day))
- (if (/= 0 year)
- ;; Fully specified Islamic date.
- (let ((date (calendar-gregorian-from-absolute
- (calendar-absolute-from-islamic
- (list month day year)))))
- (if (calendar-date-is-visible-p date)
- (mark-visible-calendar-date date)))
- ;; Month and day in any year--this taken from the holiday stuff.
- (let* ((islamic-date (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian
- (list displayed-month 15 displayed-year))))
- (m (extract-calendar-month islamic-date))
- (y (extract-calendar-year islamic-date))
- (date))
- (if (< m 1)
- nil;; Islamic calendar doesn't apply.
- (increment-calendar-month m y (- 10 month))
- (if (> m 7);; Islamic date might be visible
- (let ((date (calendar-gregorian-from-absolute
- (calendar-absolute-from-islamic
- (list month day y)))))
- (if (calendar-date-is-visible-p date)
- (mark-visible-calendar-date date)))))))
- ;; Not one of the simple cases--check all visible dates for match.
- ;; Actually, the following code takes care of ALL of the cases, but
- ;; it's much too slow to be used for the simple (common) cases.
- (let ((m displayed-month)
- (y displayed-year)
- (first-date)
- (last-date))
- (increment-calendar-month m y -1)
- (setq first-date
- (calendar-absolute-from-gregorian
- (list m 1 y)))
- (increment-calendar-month m y 2)
- (setq last-date
- (calendar-absolute-from-gregorian
- (list m (calendar-last-day-of-month m y) y)))
- (calendar-for-loop date from first-date to last-date do
- (let* ((i-date (calendar-islamic-from-absolute date))
- (i-month (extract-calendar-month i-date))
- (i-day (extract-calendar-day i-date))
- (i-year (extract-calendar-year i-date)))
- (and (or (zerop month)
- (= month i-month))
- (or (zerop day)
- (= day i-day))
- (or (zerop year)
- (= year i-year))
- (mark-visible-calendar-date
- (calendar-gregorian-from-absolute date)))))))))
-
-(provide 'diary-lib)
-
-;;; diary-lib.el ends here
diff --git a/lisp/=ftp.el b/lisp/=ftp.el
deleted file mode 100644
index 01186dda27a..00000000000
--- a/lisp/=ftp.el
+++ /dev/null
@@ -1,392 +0,0 @@
-;;; ftp.el --- file input and output over Internet using FTP
-
-;; Copyright (C) 1987 Free Software Foundation, Inc.
-
-;; Author: Richard Mlynarik <mly@prep.ai.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Code:
-
-;; 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)
-(defvar ftp-password-alist () "Security sucks")
-
-(defun read-ftp-user-password (host user new)
- (let (tem)
- (if (and (not new)
- (listp ftp-password-alist)
- (setq tem (cdr (assoc host ftp-password-alist)))
- (or (null user)
- (string= user (car tem))))
- tem
- (or user
- (progn
- (setq tem (or (and (listp ftp-password-alist)
- (car (cdr (assoc host ftp-password-alist))))
- (user-login-name)))
- (setq user (read-string (format
- "User-name for %s (default \"%s\"): "
- host tem)))
- (if (equal user "") (setq user tem))))
- (setq tem (cons user
- ;; If you want to use some non-echoing string-reader,
- ;; feel free to write it yourself. I don't care enough.
- (read-string (format "Password for %s@%s: " user host)
- (if (not (listp ftp-password-alist))
- ""
- (or (cdr (cdr (assoc host ftp-password-alist)))
- (let ((l ftp-password-alist))
- (catch 'foo
- (while l
- (if (string= (car (cdr (car l))) user)
- (throw 'foo (cdr (cdr (car l))))
- (setq l (cdr l))))
- nil))
- "")))))
- (message "")
- (if (and (listp ftp-password-alist)
- (not (string= (cdr tem) "")))
- (setq ftp-password-alist (cons (cons host tem)
- ftp-password-alist)))
- tem)))
-
-(defun ftp-read-file-name (prompt)
- (let ((s ""))
- (while (not (string-match "\\`[ \t]*\\([^ \t:]+\\)[ \t]*:\\(.+\\)\\'" s))
- (setq s (read-string prompt s)))
- (list (substring s (match-beginning 1) (match-end 1))
- (substring s (match-beginning 2) (match-end 2)))))
-
-
-;;;###autoload
-(defun ftp-find-file (host file &optional user password)
- "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)"
- (interactive
- (append (ftp-read-file-name "FTP get host:file: ")
- (list nil (not (null current-prefix-arg)))))
- (ftp-find-file-or-directory host file t user password))
-
-;;;###autoload
-(defun ftp-list-directory (host file &optional user password)
- "FTP to HOST to list DIRECTORY, 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)"
- (interactive
- (append (ftp-read-file-name "FTP get host:directory: ")
- (list nil (not (null current-prefix-arg)))))
- (ftp-find-file-or-directory host file nil user password))
-
-(defun ftp-find-file-or-directory (host file filep &optional user password)
- "FTP to HOST to get FILE. Third arg is t for file, nil for directory.
-Log in as USER with PASSWORD. If USER is nil or PASSWORD is nil or t,
-we prompt for the user name and password."
- (or (and user password (not (eq password t)))
- (progn (setq user (read-ftp-user-password host user (eq password t))
- password (cdr user)
- user (car user))))
- (let ((buffer (get-buffer-create (format "*ftp%s %s:%s*"
- (if filep "" "-directory")
- host file))))
- (set-buffer buffer)
- (let ((process nil)
- (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)))))
- (message "Opening %s %s:%s..." (if filep "file" "directory")
- host file)
- (if (ftp-command process
- (format "%s \"%s\" -\nquit\n" (if filep "get" "dir")
- file)
- "\\(150\\|125\\).*\n"
- "200.*\n")
- (progn (forward-line 1)
- (let ((buffer-read-only nil))
- (delete-region (point-min) (point)))
- (message "Retrieving %s:%s in background. Bye!" host file)
- (set-process-sentinel process
- 'ftp-asynchronous-input-sentinel)
- process)
- (switch-to-buffer buffer)
- (let ((buffer-read-only nil))
- (insert-before-markers "<<<Ftp lost>>>"))
- (delete-process process)
- (error "Ftp %s:%s lost" host file)))))
-
-
-;;;###autoload
-(defun ftp-write-file (host file &optional user password)
- "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)"
- (interactive
- (append (ftp-read-file-name "FTP write host:file: ")
- (list nil (not (null current-prefix-arg)))))
- (or (and user password (not (eq password t)))
- (progn (setq user (read-ftp-user-password host user (eq password t))
- password (cdr user)
- user (car user))))
- (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")
- (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\\|125\\).*\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))))))
-
-
-(defun ftp-setup-buffer (host file)
- (fundamental-mode)
- (and (get-buffer-process (current-buffer))
- (progn (discard-input)
- (if (y-or-n-p (format "Kill process \"%s\" in %s? "
- (process-name (get-buffer-process
- (current-buffer)))
- (buffer-name (current-buffer))))
- (while (get-buffer-process (current-buffer))
- (kill-process (get-buffer-process (current-buffer))))
- (error "Foo"))))
- ;(buffer-disable-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"))
-
-
-(defun ftp-login (process host user password)
- (message "FTP logging in as %s@%s..." user host)
- (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")
- t
- (switch-to-buffer (process-buffer process))
- (delete-process process)
- (if (listp ftp-password-alist)
- (setq ftp-password-alist (delq (assoc host ftp-password-alist)
- ftp-password-alist)))
- nil))
-
-(defun ftp-command (process command win ignore)
- (process-send-string process command)
- (let ((p 1))
- (while (numberp p)
- (cond ;((not (bolp)))
- ((looking-at "^[0-9]+-")
- (while (not (re-search-forward "^[0-9]+ " nil t))
- (save-excursion
- (accept-process-output process)))
- (beginning-of-line))
- ((looking-at win)
- (goto-char (point-max))
- (setq p t))
- ((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)
- ;; is really really disgusting.
- (setq p (point))
- (condition-case ()
- (accept-process-output process)
- (error nil))
- (goto-char p))
- (t
- (setq p nil))))
- p))
-
-
-(defun ftp-asynchronous-input-sentinel (process msg)
- (ftp-sentinel process msg t t))
-(defun ftp-synchronous-input-sentinel (process msg)
- (ftp-sentinel process msg nil t))
-(defun ftp-asynchronous-output-sentinel (process msg)
- (ftp-sentinel process msg t nil))
-(defun ftp-synchronous-output-sentinel (process msg)
- (ftp-sentinel process msg nil nil))
-
-(defun ftp-sentinel (process msg asynchronous input)
- (cond ((null (buffer-name (process-buffer process)))
- ;; deleted buffer
- (set-process-buffer process nil))
- ((and (eq (process-status process) 'exit)
- (= (process-exit-status process) 0))
- (save-excursion
- (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.*$")))
- (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)).
- (if (not input)
- (progn
- (condition-case ()
- (and (boundp 'ftp-temp-file-name)
- 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)"
- ftp-host ftp-file))))
- (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)
- )
- (progn (message "%s" msg)
- (sleep-for 2))))))
- ((memq (process-status process) '(exit signal))
- (save-excursion
- (set-buffer (process-buffer process))
- (setq msg (format "Ftp died (buffer %s): %s"
- (buffer-name (current-buffer))
- msg))
- (let ((buffer-read-only nil))
- (goto-char (point-max))
- (insert ?\n ?\n msg))
- (delete-process proc)
- (set-buffer (get-buffer-create "*ftp log*"))
- (let ((buffer-read-only nil))
- (goto-char (point-max))
- (insert msg))
- (if (waiting-for-user-input-p)
- (error "%s" msg))))))
-
-(defun ftp-setup-write-file-hooks ()
- (let ((hooks write-file-hooks))
- (make-local-variable 'write-file-hooks)
- (setq write-file-hooks (append write-file-hooks
- '(ftp-write-file-hook))))
- (make-local-variable 'revert-buffer-function)
- (setq revert-buffer-function 'ftp-revert-buffer)
- (setq default-directory "/tmp/")
- (setq buffer-file-name (concat default-directory
- (make-temp-name
- (buffer-name (current-buffer)))))
- (setq buffer-read-only nil))
-
-(defun ftp-write-file-hook ()
- (let ((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))
- t)
-
-(defun ftp-revert-buffer (&rest ignore)
- (let ((process (ftp-find-file ftp-host ftp-file)))
- (set-process-sentinel process 'ftp-synchronous-input-sentinel)
- (message "FTP reverting %s:%s" ftp-host ftp-file)
- (while (eq (process-status process) 'run)
- (condition-case ()
- (accept-process-output process)
- (error nil)))
- (and (eq (process-status process) 'exit)
- (= (process-exit-status process) 0)
- (set-buffer-modified-p nil))
- (message "Reverted")))
-
-;;; ftp.el ends here
diff --git a/lisp/=gnus-uu.el b/lisp/=gnus-uu.el
deleted file mode 100644
index b85f2e23f89..00000000000
--- a/lisp/=gnus-uu.el
+++ /dev/null
@@ -1,3057 +0,0 @@
-;;; gnus-uu.el --- extract, view or save (uu)encoded files from gnus
-
-;; Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
-;; Created: 2 Oct 1993
-;; Version: v2.8
-;; Last Modified: 1994/06/01
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; All gnus-uu commands start with `C-c C-v'.
-;;
-;; Short user manual for this package:
-;;
-;; Type `C-c C-v C-v' to decode and view all articles of the current
-;; series. The defaults should be reasonable for most systems.
-;;
-;; Type `C-c C-v C-i' to toggle interactive mode. When using
-;; interactive mode, gnus-uu will which display a buffer that will let
-;; you see the suggested commands to be executed.
-;;
-;; To post an uuencoded file, type `C-c C-v p', which will enter you
-;; into a buffer analogous to the one you will get when typing `a'. Do
-;; an `M-x describe-mode' in this buffer to get a description of what
-;; this buffer lets you do.
-;;
-;; Read the documentation of the `gnus-uu' dummy function for a more
-;; complete description of what this package does and how you can
-;; customize it to fit your needs.
-;;
-;;
-;;
-;; History
-;;
-;; v1.0: First version released Oct 2 1992.
-;;
-;; v1.1: Changed `C-c C-r' to `C-c C-e' and `C-c C-p' to `C-c C-k'.
-;; Changed (setq gnus-exit-group-hook) to (add-hook). Removed
-;; checking for "Re:" for finding parts.
-;;
-;; v2.2: Fixed handling of currupted archives. Changed uudecoding to
-;; an asynchronous process to avoid loading tons of data into emacs
-;; buffers. No longer reads articles emacs already have aboard. Fixed
-;; a firmer support for shar files. Made regexp searches for files
-;; more convenient. Added `C-c C-l' for editing uucode begin
-;; lines. Added multi-system decoder entry point. Added interactive
-;; view mode. Added function for decoding and saving all uuencoded
-;; articles in the current newsgroup.
-;;
-;; v2.3: After suggestions I have changed all the gnus-uu key bindings
-;; to avoid hogging all the user keys (C-c LETTER). Also added
-;; (provide) and fixed some saving stuff. First posted version to
-;; gnu.emacs.sources.
-;;
-;; v2.4: Fixed some more in the save-all category. Automatic fixing of
-;; uucode "begin" lines: names on the form of "dir/file" are
-;; translated into "dir-file". Added a function for fixing stripped
-;; uucode articles. Added binhex save.
-;;
-;; v2.5: First version copyrighted by FSF. Changed lots of
-;; documentation strings.
-;;
-;; v2.5.1: Added uuencode/posting code to post binary files.
-;;
-;; v2.6: Thread support. gnus-uu is now able to decode uuencoded files
-;; posted in threads. gnus-uu can also post in threads. I don't know
-;; if this ability is of much use - I've never seen anyone post
-;; uuencoded files in threads.
-;;
-;; v2.7: gnus-uu is now able to decode (and view/save) multiple
-;; encoded files in one big gulp. Also added pseudo-mime support
-;; (users can use metamail to view files), posting uuencoded/mime
-;; files and various other bits and pieces.
-;;
-;; v2.7.1: New functions for decoding/saving threads bound to `C-c
-;; C-v C-j'. Handy to save entire threads, not very useful for
-;; decoding, as nobody posts encoded files in threads...
-;;
-;; v2.7.2: New functions for digesting and forwarding articles added
-;; on the suggestion of Per Abrahamsen. Also added a function for
-;; marking threads.
-;;
-;; v2.8: Fixed saving original files in interactive mode. Fixed ask
-;; before/save after view. Fixed setting up interactive buffers. Added
-;; scanning and rescanning from interactive mode. Added the
-;; `gnus-uu-ignore-file-by-name' and `...-by-type' variables to allow
-;; users to sift files they don't want to view. At the suggestion of
-;; boris@cs.rochester.edu, `C-c C-v C-h' has been undefined to allow
-;; users to view list of binding beginning with `C-c C-v'. Fixed
-;; viewing with `gnus-uu-asynchronous' set. The
-;; "decode-and-save/view-all-articles" functions now accepts the
-;; numeric prefix to delimit the maximum number of files to be
-;; decoded.
-
-;;; Code:
-
-(require 'gnus)
-(require 'gnuspost)
-
-;; Binding of keys to the gnus-uu functions.
-
-(defvar gnus-uu-ctl-map nil)
-(define-prefix-command 'gnus-uu-ctl-map)
-(define-key gnus-summary-mode-map "\C-c\C-v" gnus-uu-ctl-map)
-
-(define-key gnus-uu-ctl-map "\C-v" 'gnus-uu-decode-and-view)
-(define-key gnus-uu-ctl-map "v" 'gnus-uu-decode-and-save)
-(define-key gnus-uu-ctl-map "\C-s" 'gnus-uu-shar-and-view)
-(define-key gnus-uu-ctl-map "s" 'gnus-uu-shar-and-save)
-(define-key gnus-uu-ctl-map "\C-m" 'gnus-uu-multi-decode-and-view)
-(define-key gnus-uu-ctl-map "m" 'gnus-uu-multi-decode-and-save)
-
-(define-key gnus-uu-ctl-map "\C-b" 'gnus-uu-decode-and-show-in-buffer)
-
-(define-key gnus-summary-mode-map "#" 'gnus-uu-mark-article)
-(define-key gnus-summary-mode-map "\M-#" 'gnus-uu-unmark-article)
-(define-key gnus-uu-ctl-map "\C-u" 'gnus-uu-unmark-all-articles)
-(define-key gnus-uu-ctl-map "\C-r" 'gnus-uu-mark-by-regexp)
-(define-key gnus-uu-ctl-map "r" 'gnus-uu-mark-by-regexp)
-(define-key gnus-uu-ctl-map "t" 'gnus-uu-mark-thread)
-
-(define-key gnus-uu-ctl-map "\M-\C-v" 'gnus-uu-marked-decode-and-view)
-(define-key gnus-uu-ctl-map "\M-v" 'gnus-uu-marked-decode-and-save)
-(define-key gnus-uu-ctl-map "\M-\C-s" 'gnus-uu-marked-shar-and-view)
-(define-key gnus-uu-ctl-map "\M-s" 'gnus-uu-marked-shar-and-save)
-(define-key gnus-uu-ctl-map "\M-\C-m" 'gnus-uu-marked-multi-decode-and-view)
-(define-key gnus-uu-ctl-map "\M-m" 'gnus-uu-marked-multi-decode-and-save)
-
-(define-key gnus-uu-ctl-map "f" 'gnus-uu-digest-and-forward)
-(define-key gnus-uu-ctl-map "\M-f" 'gnus-uu-marked-digest-and-forward)
-
-(define-key gnus-uu-ctl-map "\C-i" 'gnus-uu-toggle-interactive-view)
-(define-key gnus-uu-ctl-map "\C-t" 'gnus-uu-toggle-any-variable)
-
-(define-key gnus-uu-ctl-map "\C-l" 'gnus-uu-edit-begin-line)
-
-(define-key gnus-uu-ctl-map "a" 'gnus-uu-decode-and-save-all-unread-articles)
-(define-key gnus-uu-ctl-map "w" 'gnus-uu-decode-and-save-all-articles)
-(define-key gnus-uu-ctl-map "\C-a" 'gnus-uu-decode-and-view-all-unread-articles)
-(define-key gnus-uu-ctl-map "\C-w" 'gnus-uu-decode-and-view-all-articles)
-
-(define-key gnus-uu-ctl-map "\C-j" 'gnus-uu-threaded-multi-decode-and-view)
-(define-key gnus-uu-ctl-map "j" 'gnus-uu-threaded-multi-decode-and-save)
-
-(define-key gnus-uu-ctl-map "p" 'gnus-uu-post-news)
-
-;; Dummy function gnus-uu
-
-(defun gnus-uu ()
- "gnus-uu is a package for uudecoding and viewing articles.
-
-
-Keymap overview:
-
-By default, all gnus-uu keystrokes begin with `C-c C-v'.
-
-There four decoding commands categories:
-All commands for viewing are `C-c C-v C-LETTER'.
-All commands for saving are `C-c C-v LETTER'.
-All commands for marked viewing are `C-c C-v C-M-LETTER'.
-All commands for marked saving are `C-c C-v M-LETTER'.
-
-\\<gnus-summary-mode-map>\\[gnus-uu-decode-and-view]\tDecode and view articles
-\\[gnus-uu-decode-and-save]\tDecode and save articles
-\\[gnus-uu-shar-and-view]\tUnshar and view articles
-\\[gnus-uu-shar-and-save]\tUnshar and save articles
-\\[gnus-uu-multi-decode-and-view]\tChoose a decoding method, decode and view articles
-\\[gnus-uu-multi-decode-and-save]\tChoose a decoding method, decode and save articles
-
-\\[gnus-uu-threaded-multi-decode-and-view]\tDecode a thread and view
-\\[gnus-uu-threaded-multi-decode-and-save]\tDecode a thread and save
-
-\\[gnus-uu-decode-and-show-in-buffer]\tDecode the current article and view the result in a buffer
-\\[gnus-uu-edit-begin-line]\tEdit the 'begin' line of an uuencoded article
-
-\\[gnus-uu-decode-and-save-all-unread-articles]\tDecode and save all unread articles
-\\[gnus-uu-decode-and-save-all-articles]\tDecode and save all articles
-\\[gnus-uu-decode-and-view-all-unread-articles]\tDecode and view all unread articles
-\\[gnus-uu-decode-and-view-all-articles]\tDecode and view all articles
-
-\\[gnus-uu-digest-and-forward]\tDigest and forward a series of articles
-\\[gnus-uu-marked-digest-and-forward]\tDigest and forward all marked articles
-
-\\[gnus-uu-mark-article]\tMark the current article for decoding
-\\[gnus-uu-unmark-article]\tUnmark the current article
-\\[gnus-uu-unmark-all-articles]\tUnmark all articles
-\\[gnus-uu-mark-by-regexp]\tMark articles for decoding by regexp
-\\[gnus-uu-mark-thread]\tMark articles in this thread
-\\[gnus-uu-marked-decode-and-view]\tDecode and view marked articles
-\\[gnus-uu-marked-decode-and-save]\tDecode and save marked articles
-\\[gnus-uu-marked-shar-and-view]\tUnshar and view marked articles
-\\[gnus-uu-marked-shar-and-save]\tUnshar and save marked articles
-\\[gnus-uu-marked-multi-decode-and-view]\tChoose decoding method, decode and view marked articles
-\\[gnus-uu-marked-multi-decode-and-save]\tChoose decoding method, decode and save marked articles
-
-\\[gnus-uu-toggle-asynchronous]\tToggle asynchronous viewing mode
-\\[gnus-uu-toggle-query]\tToggle whether to ask before viewing a file
-\\[gnus-uu-toggle-always-ask]\tToggle whether to ask to save a file after viewing
-\\[gnus-uu-toggle-kill-carriage-return]\tToggle whether to strip trailing carriage returns
-\\[gnus-uu-toggle-interactive-view]\tToggle whether to use interactive viewing mode
-\\[gnus-uu-toggle-correct-stripped-articles]\tToggle whether to 'correct' articles
-\\[gnus-uu-toggle-view-with-metamail]\tToggle whether to use metamail for viewing
-\\[gnus-uu-toggle-any-variable]\tToggle any of the things above
-
-\\[gnus-uu-post-news]\tPost an uuencoded article
-
-Function description:
-
-`gnus-uu-decode-and-view' will try to find all articles in the same
-series, uudecode them and view the resulting file(s).
-
-gnus-uu guesses what articles are in the series according to the
-following simplish rule: The subjects must be (nearly) identical,
-except for the last two numbers of the line. (Spaces are largely
-ignored, however.)
-
-For example: If you choose a subject called
- \"cat.gif (2/3)\"
-gnus-uu will find all the articles that matches
- \"^cat.gif ([0-9]+/[0-9]+).*$\".
-
-Subjects that are nonstandard, like
- \"cat.gif (2/3) Part 6 of a series\",
-will not be properly recognized by any of the automatic viewing
-commands, and you have to mark the articles manually with '#'.
-
-`gnus-uu-decode-and-save' will do the same as
-`gnus-uu-decode-and-view', except that it will not display the
-resulting file, but save it instead.
-
-`gnus-uu-shar-and-view' and `gnus-uu-shar-and-save' are the \"shar\"
-equivalents to the uudecode functions. Instead of feeding the articles
-to uudecode, they are run through /bin/sh. Most shar files can be
-viewed and/or saved with the normal uudecode commands, which is much
-safer, as no foreign code is run.
-
-Instead of having windows popping up automatically, it can be handy to
-view files interactivly, especially when viewing archives. Use
-`gnus-uu-toggle-interactive-mode' to toggle interactive mode.
-
-`gnus-uu-mark-article' marks an article for later
-decoding/unsharing/saving/viewing. The files will be decoded in the
-sequence they were marked. To decode the files after you've marked the
-articles you are interested in, type the corresponding key strokes as
-the normal decoding commands, but put a `M-' in the last
-keystroke. For instance, to perform a standard uudecode and view, you
-would type `C-c C-v C-v'. To perform a marked uudecode and view, say
-`C-v C-v M-C-v'. All the other view and save commands are handled the
-same way; marked uudecode and save is then `C-c C-v M-v'.
-
-`gnus-uu-unmark-article' will remove the mark from a previosly marked
-article.
-
-`gnus-uu-unmark-all-articles' will remove the mark from all marked
-articles.
-
-`gnus-uu-mark-by-regexp' will prompt for a regular expression and mark
-all articles matching that regular expression.
-
-`gnus-uu-mark-thread' will mark all articles downward in the current
-thread.
-
-There's an additional way to reach the decoding functions to make
-future expansions easier: `gnus-uu-multi-decode-and-view' and the
-corresponding save, marked view and marked save functions. You will be
-prompted for a decoding method, like uudecode, shar, binhex or plain
-save. Note that methods like binhex and save doesn't have view modes;
-even if you issue a view command (`C-c C-v C-m' and \"binhex\"),
-gnus-uu will just save the resulting binhex file.
-
-`gnus-uu-decode-and-show-in-buffer' will decode the current article
-and display the results in an emacs buffer. This might be useful if
-there's jsut some text in the current article that has been uuencoded
-by some perverse poster.
-
-`gnus-uu-decode-and-save-all-articles' looks at all the articles in
-the current newsgroup and tries to uudecode everything it can
-find. The user will be prompted for a directory where the resulting
-files (if any) will be
-saved. `gnus-uu-decode-and-save-unread-articles' does only checks
-unread articles.
-
-`gnus-uu-decode-and-view-all-articles' does the same as the function
-above, only viewing files instead of saving them.
-
-`gnus-uu-edit-begin-line' lets you edit the begin line of an uuencoded
-file in the current article. Useful to change a corrupted begin line.
-
-
-When using the view commands, `gnus-uu-decode-and-view' for instance,
-gnus-uu will (normally, see below) try to view the file according to
-the rules given in `gnus-uu-default-view-rules' and
-`gnus-uu-user-view-rules'. If it recognizes the file, it will display
-it immediately. If the file is some sort of archive, gnus-uu will
-attempt to unpack the archive and see if any of the files in the
-archive can be viewed. For instance, if you have a gzipped tar file
-\"pics.tar.gz\" containing the files \"pic1.jpg\" and \"pic2.gif\",
-gnus-uu will uncompress and detar the main file, and then view the two
-pictures. This unpacking process is recursive, so if the archive
-contains archives of archives, it'll all be unpacked.
-
-If the view command doesn't recognise the file type, or can't view it
-because you don't have the viewer, or can't view *any* of the files in
-the archive, the user will be asked if she wishes to have the file
-saved somewhere. Note that if the decoded file is an archive, and
-gnus-uu manages to view some of the files in the archive, it won't
-tell the user that there were some files that were unviewable. Try
-interactive view for a different approach.
-
-
-Note that gnus-uu adds a function to `gnus-exit-group-hook' to clear
-the list of marked articles and check for any generated files that
-might have escaped deletion if the user typed `C-g' during viewing.
-
-
-`gnus-uu-toggle-asynchronous' toggles the `gnus-uu-asynchronous'
-variable.
-
-`gnus-uu-toggle-query' toggles the `gnus-uu-ask-before-view'
-variable.
-
-`gnus-uu-toggle-always-ask' toggles the `gnus-uu-view-and-save'
-variable.
-
-`gnus-uu-toggle-kill-carriage-return' toggles the
-`gnus-uu-kill-carriage-return' variable.
-
-`gnus-uu-toggle-interactive-view' toggles interactive mode. If it is
-turned on, gnus-uu won't view files immediately, but will give you a
-buffer with the default commands and files and let you edit the
-commands and execute them at leisure.
-
-`gnus-uu-toggle-correct-stripped-articles' toggles whether to check
-and correct uuencoded articles that may have had trailing spaces
-stripped by mailers.
-
-`gnus-uu-toggle-view-with-metamail' toggles whether to skip the
-gnus-uu viewing methods and just guess at an content-type based on the
-file name suffix and feed it to metamail.
-
-`gnus-uu-toggle-any-variable' is an interface to the toggle commands
-listed above.
-
-
-Customization
-
- Rule Variables
-
- gnus-uu uses \"rule\" variables to decide how to view a file. All
- these variables are of the form
-
- (list '(regexp1 command2)
- '(regexp2 command2)
- ...)
-
- `gnus-uu-user-view-rules'
- This variable is consulted first when viewing files. If you wish
- to use, for instance, sox to convert an .au sound file, you could
- say something like:
-
- (setq gnus-uu-user-view-rules
- (list '(\"\\\\.au$\" \"sox %s -t .aiff > /dev/audio\")))
-
- `gnus-uu-user-view-rules-end'
- This variable is consulted if gnus-uu couldn't make any matches
- from the user and default view rules.
-
- `gnus-uu-user-interactive-view-rules'
- This is the variable used instead of `gnus-uu-user-view-rules'
- when in interactive mode.
-
- `gnus-uu-user-interactive-view-rules-end'
- This variable is used instead of `gnus-uu-user-view-rules-end'
- when in interactive mode.
-
- `gnus-uu-user-archive-rules`
- This variable can be used to say what comamnds should be used to
- unpack archives.
-
-
- Other Variables
-
- `gnus-uu-ignore-files-by-name'
- Files with name matching this regular expression won't be viewed.
-
- `gnus-uu-ignore-files-by-type'
- Files with a MIME type matching this variable won't be viewed.
- Note that gnus-uu tries to guess what type the file is based on
- the name. gnus-uu is not a MIME package, so this is slightly
- kludgy.
-
- `gnus-uu-tmp-dir'
- Where gnus-uu does its work.
-
- `gnus-uu-do-not-unpack-archives'
- Non-nil means that gnus-uu won't peek inside archives looking for
- files to dispay.
-
- `gnus-uu-view-and-save'
- Non-nil means that the user will always be asked to save a file
- after viewing it.
-
- `gnus-uu-asynchronous'
- Non-nil means that files will be viewed asynchronously. This can
- be useful if you're viewing long .mod files, for instance, which
- often takes several minutes. Note, however, that since gnus-uu
- doesn't ask, and if you are viewing an archive with lots of
- viewable files, you'll get them all up more or less at once,
- which can be confusing, to say the least. To get gnus-uu to ask
- you before viewing a file, set the `gnus-uu-ask-before-view'
- variable.
-
- `gnus-uu-ask-before-view'
- Non-nil means that gnus-uu will ask you before viewing each file
-
- `gnus-uu-ignore-default-view-rules'
- Non-nil means that gnus-uu will ignore the default viewing rules.
-
- `gnus-uu-ignore-default-archive-rules'
- Non-nil means that gnus-uu will ignore the default archive
- unpacking commands.
-
- `gnus-uu-kill-carriage-return'
- Non-nil means that gnus-uu will strip all carriage returns from
- articles.
-
- `gnus-uu-unmark-articles-not-decoded'
- Non-nil means that gnus-uu will mark articles that were
- unsuccessfully decoded as unread.
-
- `gnus-uu-output-window-height'
- This variable says how tall the output buffer window is to be
- when using interactive view mode.
-
- `gnus-uu-correct-stripped-uucode'
- Non-nil means that gnus-uu will *try* to fix uuencoded files that
- have had traling spaces deleted.
-
- `gnus-uu-use-interactive-view'
- Non-nil means that gnus-uu will use interactive viewing mode.
-
- `gnus-uu-view-with-metamail'
- Non-nil means that gnus-uu will ignore the viewing commands
- defined by the rule variables and just fudge a MIME content type
- based on the file name. The result will be fed to metamail for
- viewing.
-
- `gnus-uu-save-in-digest'
- Non-nil means that gnus-uu, when asked to save without decoding,
- will save in digests. If this variable is nil, gnus-uu will just
- save everything in a file without any embellishments. The
- digesting almost conforms to RFC1153 - no easy way to specify any
- meaningful volume and issue numbers were found, so I simply
- dropped them.
-
- `gnus-uu-post-include-before-composing'
- Non-nil means that gnus-uu will ask for a file to encode before
- you compose the article. If this variable is t, you can either
- include an encoded file with \\<gnus-uu-post-reply-mode-map>\\[gnus-uu-post-insert-binary-in-article] or have one included for you when you
- post the article.
-
- `gnus-uu-post-length'
- Maximum length of an article. The encoded file will be split
- into how many articles it takes to post the entire file.
-
- `gnus-uu-post-threaded'
- Non-nil means that gnus-uu will post the encoded file in a
- thread. This may not be smart, as no other decoder I have seen
- are able to follow threads when collecting uuencoded
- articles. (Well, I have seen one package that does that -
- gnus-uu, but somehow, I don't think that counts...) Default is
- nil.
-
- `gnus-uu-post-separate-description'
- Non-nil means that the description will be posted in a separate
- article. The first article will typically be numbered (0/x). If
- this variable is nil, the description the user enters will be
- included at the beginning of the first article, which will be
- numbered (1/x). Default is t.
-"
- (interactive)
- )
-
-;; Default viewing action rules
-
-(defvar gnus-uu-default-view-rules
- (list
- '("\\.\\(jpe?g\\|gif\\|tiff?\\|p[pgb]m\\|xwd\\|xbm\\|pcx\\)$" "xv")
- '("\\.tga$" "tgatoppm %s | xv -")
- '("\\.te?xt$\\|\\.doc$\\|read.*me" "xterm -e less")
- '("\\.\\(wav\\|aiff\\|hcom\\|u[blw]\\|s[bfw]\\|voc\\|smp\\)$"
- "sox -v .5 %s -t .au -u - > /dev/audio")
- '("\\.au$" "cat %s > /dev/audio")
- '("\\.mod$" "str32")
- '("\\.ps$" "ghostview")
- '("\\.dvi$" "xdvi")
- '("\\.[1-6]$" "xterm -e man -l")
- '("\\.html$" "xmosaic")
- '("\\.mpe?g$" "mpeg_play")
- '("\\.\\(flc\\|fli\\|rle\\|iff\\|pfx\\|avi\\|sme\\|rpza\\|dl\\|qt\\|rsrc\\)$" "xanim")
- '("\\.\\(tar\\|arj\\|zip\\|zoo\\|arc\\|gz\\|Z\\|lzh\\|ar\\|lha\\)$"
- "gnus-uu-archive"))
-
- "Default actions to be taken when the user asks to view a file.
-To change the behaviour, you can either edit this variable or set
-`gnus-uu-user-view-rules' to something useful.
-
-For example:
-
-To make gnus-uu use 'xli' to display JPEG and GIF files, put the
-following in your .emacs file
-
- (setq gnus-uu-user-view-rules (list '(\"jpg$\\\\|gif$\" \"xli\")))
-
-Both these variables are lists of lists with two string elements. The
-first string is a regular expression. If the file name matches this
-regular expression, the command in the second string is executed with
-the file as an argument.
-
-If the command string contains \"%s\", the file name will be inserted
-at that point in the command string. If there's no \"%s\" in the
-command string, the file name will be appended to the command string
-before executing.
-
-There are several user variables to tailor the behaviour of gnus-uu to
-your needs. First we have `gnus-uu-user-view-rules', which is the
-variable gnus-uu first consults when trying to decide how to view a
-file. If this variable contains no matches, gnus-uu examines the
-default rule vaiable provided in this package. If gnus-uu finds no
-match here, it uses `gnus-uu-user-view-rules-end' to try to make a
-match.
-
-Unless, of course, you are using the interactive view mode. Then
-`gnus-uu-user-interactive-view-rules' and
-`gnus-uu-user-interactive-view-rules-end' will be used instead.")
-
-(defvar gnus-uu-user-view-rules nil
- "Variable detailing what actions are to be taken to view a file.
-See the documentation on the `gnus-uu-default-view-rules' variable for
-details.")
-
-(defvar gnus-uu-user-view-rules-end nil
- "Variable saying what actions are to be taken if no rule matched the file name.
-See the documentation on the `gnus-uu-default-view-rules' variable for
-details.")
-
-(defvar gnus-uu-user-interactive-view-rules nil
- "Variable detailing what actions are to be taken to view a file when using interactive mode.
-See the documentation on the `gnus-uu-default-view-rules' variable for
-details.")
-
-(defvar gnus-uu-user-interactive-view-rules-end nil
- "Variable saying what actions are to be taken if no rule matched the file name when using interactive mode.
-See the documentation on the `gnus-uu-default-view-rules' variable for
-details.")
-
-(defvar gnus-uu-default-interactive-view-rules-begin
- (list
- '("\\.te?xt$\\|\\.doc$\\|read.*me\\|\\.c?$\\|\\.h$\\|\\.bat$\\|\\.asm$\\|makefile" "cat %s | sed s/\r//g")
- '("\\.pas$" "cat %s | sed s/\r//g")
- ))
-
-(defvar gnus-uu-default-interactive-view-rules-end
- (list
- '(".*" "file")))
-
-;; Default unpacking commands
-
-(defvar gnus-uu-default-archive-rules
- (list '("\\.tar$" "tar xf")
- '("\\.zip$" "unzip -o")
- '("\\.ar$" "ar x")
- '("\\.arj$" "unarj x")
- '("\\.zoo$" "zoo -e")
- '("\\.\\(lzh\\|lha\\)$" "lha x")
- '("\\.Z$" "uncompress")
- '("\\.gz$" "gunzip")
- '("\\.arc$" "arc -x"))
- )
-
-(defvar gnus-uu-destructive-archivers
- (list "uncompress" "gunzip"))
-
-(defvar gnus-uu-user-archive-rules nil
- "A list that can be set to override the default archive unpacking commands.
-To use, for instance, 'untar' to unpack tar files and 'zip -x' to
-unpack zip files, say the following:
- (setq gnus-uu-user-archive-rules
- (list '(\"\\\\.tar$\" \"untar\")
- '(\"\\\\.zip$\" \"zip -x\")))")
-
-(defvar gnus-uu-ignore-files-by-name nil
- "A regular expression saying what files should not be viewed based on name.
-If, for instance, you want gnus-uu to ignore all .au and .wav files,
-you could say something like
-
- (setq gnus-uu-ignore-files-by-name \"\\\\.au$\\\\|\\\\.wav$\")
-
-Note that this variable can be used in conjunction with the
-`gnus-uu-ignore-files-by-type' variable.")
-
-(defvar gnus-uu-ignore-files-by-type nil
- "A regular expression saying what files that shouldn't be viewed, based on MIME file type.
-If, for instance, you want gnus-uu to ignore all audio files and all mpegs,
-you could say something like
-
- (setq gnus-uu-ignore-files-by-type \"audio/\\\\|video/mpeg\")
-
-Note that this variable can be used in conjunction with the
-`gnus-uu-ignore-files-by-name' variable.")
-
-;; Pseudo-MIME support
-
-(defconst gnus-uu-ext-to-mime-list
- (list '("\\.gif$" "image/gif")
- '("\\.jpe?g$" "image/jpeg")
- '("\\.tiff?$" "image/tiff")
- '("\\.xwd$" "image/xwd")
- '("\\.pbm$" "image/pbm")
- '("\\.pgm$" "image/pgm")
- '("\\.ppm$" "image/ppm")
- '("\\.xbm$" "image/xbm")
- '("\\.pcx$" "image/pcx")
- '("\\.tga$" "image/tga")
- '("\\.ps$" "image/postscript")
- '("\\.fli$" "video/fli")
- '("\\.wav$" "audio/wav")
- '("\\.aiff$" "audio/aiff")
- '("\\.hcom$" "audio/hcom")
- '("\\.voc$" "audio/voc")
- '("\\.smp$" "audio/smp")
- '("\\.mod$" "audio/mod")
- '("\\.dvi$" "image/dvi")
- '("\\.mpe?g$" "video/mpeg")
- '("\\.au$" "audio/basic")
- '("\\.\\(te?xt\\|doc\\|c\\|h\\)$" "text/plain")
- '("\\.\\(c\\|h\\)$" "text/source")
- '("read.*me" "text/plain")
- '("\\.html$" "text/html")
- '("\\.bat$" "text/bat")
- '("\\.[1-6]$" "text/man")
- '("\\.flc$" "video/flc")
- '("\\.rle$" "video/rle")
- '("\\.pfx$" "video/pfx")
- '("\\.avi$" "video/avi")
- '("\\.sme$" "video/sme")
- '("\\.rpza$" "video/prza")
- '("\\.dl$" "video/dl")
- '("\\.qt$" "video/qt")
- '("\\.rsrc$" "video/rsrc")
- '("\\..*$" "unknown/unknown")))
-
-;; Various variables users may set
-
-(defvar gnus-uu-tmp-dir "/tmp/"
- "Variable saying where gnus-uu is to do its work.
-Default is \"/tmp/\".")
-
-(defvar gnus-uu-do-not-unpack-archives nil
- "Non-nil means that gnus-uu won't peek inside archives looking for files to dispay.
-Default is nil.")
-
-(defvar gnus-uu-view-and-save nil
- "Non-nil means that the user will always be asked to save a file after viewing it.
-If the variable is nil, the suer will only be asked to save if the
-viewing is unsuccessful. Default is nil.")
-
-(defvar gnus-uu-asynchronous nil
- "Non-nil means that files will be viewed asynchronously.
-Default is nil.")
-
-(defvar gnus-uu-ask-before-view nil
- "Non-nil means that gnus-uu will ask you before viewing each file.
-Especially useful when `gnus-uu-asynchronous' is set. Default is
-nil.")
-
-(defvar gnus-uu-ignore-default-view-rules nil
- "Non-nil means that gnus-uu will ignore the default viewing rules.
-Only the user viewing rules will be consulted. Default is nil.")
-
-(defvar gnus-uu-ignore-default-archive-rules nil
- "Non-nil means that gnus-uu will ignore the default archive unpacking commands.
-Only the user unpacking commands will be consulted. Default is nil.")
-
-(defvar gnus-uu-kill-carriage-return t
- "Non-nil means that gnus-uu will strip all carriage returns from articles.
-Default is t.")
-
-(defvar gnus-uu-view-with-metamail nil
- "Non-nil means that files will be viewed with metamail.
-The gnus-uu viewing functions will be ignored and gnus-uu will try
-to guess at a content-type based on file name suffixes. Default
-it nil.")
-
-(defvar gnus-uu-unmark-articles-not-decoded nil
- "Non-nil means that gnus-uu will mark articles that were unsuccessfully decoded as unread.
-Default is nil.")
-
-(defvar gnus-uu-output-window-height 20
- "This variable says how tall the output buffer window is to be when using interactive view mode.
-Change it at your convenience. Default is 20.")
-
-(defvar gnus-uu-correct-stripped-uucode nil
- "Non-nil means that gnus-uu will *try* to fix uuencoded files that have had traling spaces deleted.
-Default is nil.")
-
-(defvar gnus-uu-use-interactive-view nil
- "Non-nil means that gnus-uu will use interactive viewing mode.
-Gnus-uu will create a special buffer where the user may choose
-interactively which files to view and how. Default is nil.")
-
-(defvar gnus-uu-save-in-digest nil
- "Non-nil means that gnus-uu, when asked to save without decoding, will save in digests.
-If this variable is nil, gnus-uu will just save everything in a
-file without any embellishments. The digesting almost conforms to RFC1153 -
-no easy way to specify any meaningful volume and issue numbers were found,
-so I simply dropped them.")
-
-
-;; Internal variables
-
-(defconst gnus-uu-begin-string "^begin[ \t]+[0-7][0-7][0-7][ \t]+\\(.*\\)$")
-(defconst gnus-uu-end-string "^end[ \t]*$")
-
-(defconst gnus-uu-body-line "^M")
-(let ((i 61))
- (while (> (setq i (1- i)) 0)
- (setq gnus-uu-body-line (concat gnus-uu-body-line "[^a-z]")))
- (setq gnus-uu-body-line (concat gnus-uu-body-line ".?$")))
-
-;"^M.............................................................?$"
-
-(defconst gnus-uu-shar-begin-string "^#! */bin/sh")
-
-(defvar gnus-uu-shar-file-name nil)
-(defconst gnus-uu-shar-name-marker "begin [0-7][0-7][0-7][ \t]+\\(\\(\\w\\|\\.\\)*\\b\\)")
-(defvar gnus-uu-shar-directory nil)
-
-(defvar gnus-uu-file-name nil)
-(defvar gnus-uu-list-of-files-decoded nil)
-(defconst gnus-uu-uudecode-process nil)
-
-(defvar gnus-uu-interactive-file-list nil)
-(defvar gnus-uu-marked-article-list nil)
-(defvar gnus-uu-generated-file-list nil)
-(defvar gnus-uu-work-dir nil)
-
-(defconst gnus-uu-interactive-buffer-name "*gnus-uu interactive*")
-(defconst gnus-uu-output-buffer-name "*Gnus UU Output*")
-(defconst gnus-uu-result-buffer "*Gnus UU Result Buffer*")
-
-(defconst gnus-uu-highest-article-number 1)
-
-;; Interactive functions
-
-;; UUdecode and view
-
-(defun gnus-uu-decode-and-view ()
- "UUdecodes and 'views' (if possible) the resulting file.
-'Viewing' can be any action at all, as defined in the
-`gnus-uu-file-action-list' variable. Running 'xv' on gifs and 'cat
->/dev/audio' on au files are popular actions. If the file can't be
-viewed, the user is asked if she would like to save the file instead."
- (interactive)
- (gnus-uu-decode-and-view-or-save t nil))
-
-(defun gnus-uu-decode-and-save ()
- "Decodes and saves the resulting file."
- (interactive)
- (gnus-uu-decode-and-view-or-save nil nil))
-
-(defun gnus-uu-marked-decode-and-view ()
- "Decodes and views articles marked.
-The marked equivalent to `gnus-uu-decode-and-view'."
- (interactive)
- (gnus-uu-decode-and-view-or-save t t))
-
-(defun gnus-uu-marked-decode-and-save ()
- "Decodes and saves articles marked.
-The marked equivalent to `gnus-uu-decode-and-save'."
- (interactive)
- (gnus-uu-decode-and-view-or-save nil t))
-
-
-;; Unshar and view
-
-(defun gnus-uu-shar-and-view ()
- "Unshars and views articles.
-The shar equivalent of `gnus-uu-decode-and-view'."
- (interactive)
- (gnus-uu-unshar-and-view-or-save t nil))
-
-(defun gnus-uu-shar-and-save ()
- "Unshars and saves files.
-The shar equivalent to `gnus-uu-decode-and-save'."
- (interactive)
- (gnus-uu-unshar-and-view-or-save nil nil))
-
-(defun gnus-uu-marked-shar-and-view ()
- "Unshars and views articles marked.
-The marked equivalent to `gnus-uu-shar-and-view'."
- (interactive)
- (gnus-uu-unshar-and-view-or-save t t))
-
-(defun gnus-uu-marked-shar-and-save ()
- "Unshars and saves articles marked.
-The marked equivalent to `gnus-uu-shar-and-save'."
- (interactive)
- (gnus-uu-unshar-and-view-or-save nil t))
-
-;; Threaded decode
-
-(defun gnus-uu-threaded-decode-and-view ()
- "Decodes and saves the resulting file."
- (interactive)
- (gnus-uu-threaded-decode-and-view-or-save t))
-
-(defun gnus-uu-threaded-decode-and-save ()
- "Decodes and saves the resulting file."
- (interactive)
- (gnus-uu-threaded-decode-and-view-or-save nil))
-
-(defun gnus-uu-threaded-multi-decode-and-view ()
- "Decodes and saves the resulting file."
- (interactive)
- (gnus-uu-threaded-multi-decode-and-view-or-save t))
-
-(defun gnus-uu-threaded-multi-decode-and-save ()
- "Decodes and saves the resulting file."
- (interactive)
- (gnus-uu-threaded-multi-decode-and-view-or-save nil))
-
-(defun gnus-uu-threaded-decode-and-view-or-save (&optional view)
- (gnus-uu-unmark-all-articles)
- (gnus-uu-mark-thread)
- (gnus-uu-decode-and-view-or-save view t))
-
-(defun gnus-uu-threaded-multi-decode-and-view-or-save (view)
- (let (type)
- (message "Decode type: [u]udecode, (s)har, s(a)ve, (b)inhex: ")
- (setq type (read-char))
- (if (not (or (= type ?u) (= type ?s) (= type ?b) (= type ?a)))
- (error "No such decoding method '%c'" type))
-
- (gnus-uu-unmark-all-articles)
- (gnus-uu-mark-thread)
-
- (if (= type ?\r) (setq type ?u))
- (cond ((= type ?u) (gnus-uu-decode-and-view-or-save view t))
- ((= type ?s) (gnus-uu-unshar-and-view-or-save view t))
- ((= type ?b) (gnus-uu-binhex-and-save view t))
- ((= type ?a) (gnus-uu-save-articles view t)))))
-
-
-;; Toggle commands
-
-(defun gnus-uu-toggle-asynchronous ()
- "This function toggles asynchronous viewing."
- (interactive)
- (if (setq gnus-uu-asynchronous (not gnus-uu-asynchronous))
- (message "gnus-uu will now view files asynchronously")
- (message "gnus-uu will now view files synchronously")))
-
-(defun gnus-uu-toggle-query ()
- "This function toggles whether to ask before viewing or not."
- (interactive)
- (if (setq gnus-uu-ask-before-view (not gnus-uu-ask-before-view))
- (message "gnus-uu will now ask before viewing")
- (message "gnus-uu will now view without asking first")))
-
-(defun gnus-uu-toggle-always-ask ()
- "This function toggles whether to always ask to save a file after viewing."
- (interactive)
- (if (setq gnus-uu-view-and-save (not gnus-uu-view-and-save))
- (message "gnus-uu will now ask to save the file after viewing")
- (message "gnus-uu will now not ask to save after successful viewing")))
-
-(defun gnus-uu-toggle-interactive-view ()
- "This function toggles whether to use interactive view."
- (interactive)
- (if (setq gnus-uu-use-interactive-view (not gnus-uu-use-interactive-view))
- (message "gnus-uu will now use interactive view")
- (message "gnus-uu will now use non-interactive view")))
-
-(defun gnus-uu-toggle-unmark-undecoded ()
- "This function toggles whether to unmark articles not decoded."
- (interactive)
- (if (setq gnus-uu-unmark-articles-not-decoded
- (not gnus-uu-unmark-articles-not-decoded))
- (message "gnus-uu will now unmark articles not decoded")
- (message "gnus-uu will now not unmark articles not decoded")))
-
-(defun gnus-uu-toggle-kill-carriage-return ()
- "This function toggles the stripping of carriage returns from the articles."
- (interactive)
- (if (setq gnus-uu-kill-carriage-return (not gnus-uu-kill-carriage-return))
- (message "gnus-uu will now strip carriage returns")
- (message "gnus-uu won't strip carriage returns")))
-
-(defun gnus-uu-toggle-view-with-metamail ()
- "This function toggles whether to view files with metamail."
- (interactive)
- (if (setq gnus-uu-view-with-metamail (not gnus-uu-view-with-metamail))
- (message "gnus-uu will now view with metamail")
- (message "gnus-uu will now view with the gnus-uu viewing functions")))
-
-(defun gnus-uu-toggle-correct-stripped-uucode ()
- "This function toggles whether to correct stripped uucode."
- (interactive)
- (if (setq gnus-uu-correct-stripped-uucode
- (not gnus-uu-correct-stripped-uucode))
- (message "gnus-uu will now correct stripped uucode")
- (message "gnus-uu won't check and correct stripped uucode")))
-
-(defun gnus-uu-toggle-any-variable ()
- "This function ask what variable the user wants to toggle."
- (interactive)
- (let (rep)
- (message "(a)sync, (q)uery, (p)ask, (k)ill CR, (i)nteract, (u)nmark, (c)orrect, (m)eta")
- (setq rep (read-char))
- (if (= rep ?a)
- (gnus-uu-toggle-asynchronous))
- (if (= rep ?q)
- (gnus-uu-toggle-query))
- (if (= rep ?p)
- (gnus-uu-toggle-always-ask))
- (if (= rep ?k)
- (gnus-uu-toggle-kill-carriage-return))
- (if (= rep ?u)
- (gnus-uu-toggle-unmark-undecoded))
- (if (= rep ?c)
- (gnus-uu-toggle-correct-stripped-uucode))
- (if (= rep ?m)
- (gnus-uu-toggle-view-with-metamail))
- (if (= rep ?i)
- (gnus-uu-toggle-interactive-view))))
-
-
-;; Misc interactive functions
-
-(defun gnus-uu-decode-and-show-in-buffer ()
- "Uudecodes the current article and displays the result in a buffer.
-Might be useful if someone has, for instance, some text uuencoded in
-their sigs. (Stranger things have happened.)"
- (interactive)
- (gnus-uu-initialize)
- (let ((uu-buffer (get-buffer-create gnus-uu-output-buffer-name))
- file-name)
- (save-excursion
- (and
- (gnus-summary-select-article)
- (gnus-uu-grab-articles (list gnus-current-article)
- 'gnus-uu-uustrip-article-as)
- (setq file-name (concat gnus-uu-work-dir gnus-uu-file-name))
- (progn
- (save-excursion
- (set-buffer uu-buffer)
- (erase-buffer)
- (insert-file-contents file-name))
- (set-window-buffer (get-buffer-window gnus-article-buffer)
- uu-buffer)
- (message "Showing file %s in buffer" file-name)
- (delete-file file-name))))))
-
-(defun gnus-uu-edit-begin-line ()
- "Edit the begin line of the current article."
- (interactive)
- (let ((buffer-read-only nil)
- begin b)
- (save-excursion
- (gnus-summary-select-article)
- (set-buffer gnus-article-buffer)
- (goto-line 1)
- (if (not (re-search-forward "begin " nil t))
- (error "No begin line in the current article")
- (beginning-of-line)
- (setq b (point))
- (end-of-line)
- (setq begin (buffer-substring b (point)))
- (setq begin (read-string "" begin))
- (setq buffer-read-only nil)
- (delete-region b (point))
- (insert-string begin)))))
-
-
-;; Multi functions
-
-(defun gnus-uu-multi-decode-and-view ()
- "Choose a method of decoding and then decode and view.
-This function lets the user decide what method to use for decoding.
-Other than that, it's equivalent to the other decode-and-view
-functions."
- (interactive)
- (gnus-uu-multi-decode-and-view-or-save t nil))
-
-(defun gnus-uu-multi-decode-and-save ()
- "Choose a method of decoding and then decode and save.
-This function lets the user decide what method to use for decoding.
-Other than that, it's equivalent to the other decode-and-save
-functions."
- (interactive)
- (gnus-uu-multi-decode-and-view-or-save nil nil))
-
-(defun gnus-uu-marked-multi-decode-and-view ()
- "Choose a method of decoding and then decode and view the marked articles.
-This function lets the user decide what method to use for decoding.
-Other than that, it's equivalent to the other marked decode-and-view
-functions."
- (interactive)
- (gnus-uu-multi-decode-and-view-or-save t t))
-
-(defun gnus-uu-marked-multi-decode-and-save ()
- "Choose a method of decoding and then decode and save the marked articles.
-This function lets the user decide what method to use for decoding.
-Other than that, it's equivalent to the other marked decode-and-save
-functions."
- (interactive)
- (gnus-uu-multi-decode-and-view-or-save t t))
-
-(defun gnus-uu-multi-decode-and-view-or-save (view marked)
- (let (type)
- (message "[u]udecode, (s)har, s(a)ve, (b)inhex: ")
- (setq type (read-char))
- (if (= type ?\r) (setq type ?u))
- (cond ((= type ?u) (gnus-uu-decode-and-view-or-save view marked))
- ((= type ?s) (gnus-uu-unshar-and-view-or-save view marked))
- ((= type ?b) (gnus-uu-binhex-and-save view marked))
- ((= type ?a) (gnus-uu-save-articles view marked))
- (t (error "Unknown decode method '%c'." type)))))
-
-
-;; "All articles" commands
-
-(defconst gnus-uu-rest-of-articles nil)
-(defvar gnus-uu-current-save-dir nil)
-
-(defun gnus-uu-decode-and-view-all-articles (arg &optional unread)
- "Try to decode all articles and view the result.
-ARG delimits the number of files to be decoded."
- (interactive "p")
- (if (not (setq gnus-uu-marked-article-list
- (nreverse (gnus-uu-get-list-of-articles
- "^." nil unread t))))
- (error "No%s articles to be decoded" (if unread " unread" "")))
- (gnus-uu-decode-and-view-or-save t t nil (if (> arg 1) arg nil)))
-
-(defun gnus-uu-decode-and-view-all-unread-articles (arg)
- "Try to decode all unread articles and view the result.
-ARG delimits the number of files to be decoded."
- (interactive "p")
- (gnus-uu-decode-and-view-all-articles arg t))
-
-(defun gnus-uu-decode-and-save-all-unread-articles (arg)
- "Try to decode all unread articles and saves the result.
-This function reads all unread articles in the current group and sees
-whether it can uudecode the articles. The user will be prompted for an
-directory to put the resulting (if any) files.
-ARG delimits the number of files to be decoded."
- (interactive "p")
- (gnus-uu-decode-and-save-articles arg t t))
-
-(defun gnus-uu-decode-and-save-all-articles (arg)
- "Try to decode all articles and saves the result.
-Does the same as `gnus-uu-decode-and-save-all-unread-articles', except
-that it grabs all articles visible, unread or not.
-ARG delimits the number of files to be decoded."
- (interactive "p")
- (gnus-uu-decode-and-save-articles arg nil t))
-
-(defun gnus-uu-decode-and-save-articles (arg &optional unread unmark)
- (let (dir)
- (if (not (setq gnus-uu-marked-article-list
- (nreverse (gnus-uu-get-list-of-articles
- "^." nil unread t))))
- (error "No%s articles to be decoded." (if unread " unread" ""))
- (setq dir (gnus-uu-read-directory "Where do you want the files? "))
- (gnus-uu-decode-and-view-or-save nil t dir (if (> arg 1) arg nil))
- (message "Saved."))))
-
-
-;; Work functions
-
-; All the interactive uudecode/view/save/marked functions are interfaces
-; to this function, which does the rest.
-(defun gnus-uu-decode-and-view-or-save (view marked &optional save-dir limit)
- (gnus-uu-initialize)
- (let (decoded)
- (save-excursion
- (if (gnus-uu-decode-and-strip nil marked limit)
- (progn
- (setq decoded t)
- (if view
- (gnus-uu-view-directory gnus-uu-work-dir
- gnus-uu-use-interactive-view)
- (gnus-uu-save-directory gnus-uu-work-dir save-dir save-dir)
- (gnus-uu-check-for-generated-files)))))
-
- (gnus-uu-summary-next-subject)
-
- (if (and gnus-uu-use-interactive-view view decoded)
- (gnus-uu-do-interactive))
-
- (if (or (not view) (not gnus-uu-use-interactive-view) (not decoded))
- (gnus-uu-clean-up))))
-
-; Unshars and views/saves marked/unmarked articles.
-(defun gnus-uu-unshar-and-view-or-save (view marked)
- (gnus-uu-initialize)
- (let (tar-file files decoded)
- (save-excursion
- (setq gnus-uu-shar-directory
- (make-temp-name (concat gnus-uu-tmp-dir "gnusuush")))
- (make-directory gnus-uu-shar-directory)
- (gnus-uu-add-file gnus-uu-shar-directory)
- (if (gnus-uu-decode-and-strip t marked)
- (progn
- (setq decoded t)
- (setq files (directory-files gnus-uu-shar-directory t))
- (setq gnus-uu-generated-file-list
- (append files gnus-uu-generated-file-list))
- (if (> (length files) 3)
- (progn
- (setq tar-file
- (concat
- (make-temp-name (concat gnus-uu-tmp-dir "gnusuuar"))
- ".tar"))
- (gnus-uu-add-file tar-file)
- (call-process
- "sh" nil
- (get-buffer-create gnus-uu-output-buffer-name) nil "-c"
- (format "cd %s ; tar cf %s * ; cd .. ; rm -r %s"
- gnus-uu-shar-directory tar-file
- gnus-uu-shar-directory))
- (if view
- (gnus-uu-view-file tar-file)
- (gnus-uu-save-file tar-file)))
- (if view
- (gnus-uu-view-file (elt files 2))
- (gnus-uu-save-file (elt files 2)))))))
-
- (gnus-uu-summary-next-subject)
-
- (if (and gnus-uu-use-interactive-view view decoded)
- (gnus-uu-do-interactive))
-
- (if (or (not gnus-uu-use-interactive-view) (not decoded))
- (gnus-uu-clean-up))))
-
-
-;; Functions for saving and possibly digesting articles without
-;; any decoding.
-
-(defconst gnus-uu-saved-article-name nil)
-
-; VIEW isn't used, but is here anyway, to provide similar interface to
-; the other related functions. If MARKED is non-nil, the list of
-; marked articles is used. If NO-SAVE is non-nil, the articles aren't
-; actually saved in a permanent location, but the collecting is done
-; and a temporary file with the result is returned.
-(defun gnus-uu-save-articles (view marked &optional no-save)
- (let (list-of-articles)
- (save-excursion
- (gnus-uu-initialize)
- (if (not marked)
- (setq list-of-articles (gnus-uu-get-list-of-articles))
- (setq list-of-articles (reverse gnus-uu-marked-article-list))
- (setq gnus-uu-marked-article-list nil))
-
- (if (not list-of-articles)
- (error "No list of articles"))
-
- (setq gnus-uu-saved-article-name
- (concat gnus-uu-work-dir
- (if no-save
- gnus-newsgroup-name
- (read-file-name "Enter file name: " gnus-newsgroup-name
- gnus-newsgroup-name))))
- (gnus-uu-add-file gnus-uu-saved-article-name)
- (if (and (gnus-uu-grab-articles list-of-articles 'gnus-uu-save-article t)
- (not no-save))
- (gnus-uu-save-file gnus-uu-saved-article-name)
- gnus-uu-saved-article-name))))
-
-; Function called by gnus-uu-grab-articles to treat each article.
-(defun gnus-uu-save-article (buffer in-state)
- (if (not gnus-uu-save-in-digest)
- (save-excursion
- (set-buffer buffer)
- (write-region 1 (point-max) gnus-uu-saved-article-name t)
- (cond ((eq in-state 'first) (list gnus-uu-saved-article-name 'begin))
- ((eq in-state 'first-and-last) (list gnus-uu-saved-article-name 'begin 'end))
- ((eq in-state 'last) (list 'end))
- (t (list 'middle))))
- (let (beg subj name headers headline sorthead body end-string state)
- (string-match "/\\([^/]*\\)$" gnus-uu-saved-article-name)
- (setq name (substring gnus-uu-saved-article-name (match-beginning 1)
- (match-end 1)))
- (if (or (eq in-state 'first)
- (eq in-state 'first-and-last))
- (progn
- (setq state (list 'begin))
- (save-excursion (set-buffer (get-buffer-create "*gnus-uu-body*"))
- (erase-buffer))
- (save-excursion
- (set-buffer (get-buffer-create "*gnus-uu-pre*"))
- (erase-buffer)
- (insert (format
- "Date: %s\nFrom: %s\nSubject: %s Digest\n\nTopics:\n"
- (current-time-string) name name))))
- (if (not (eq in-state 'end))
- (setq state (list 'middle))))
- (save-excursion
- (set-buffer (get-buffer "*gnus-uu-body*"))
- (goto-char (setq beg (point-max)))
- (save-excursion
- (save-restriction
- (set-buffer buffer)
- (goto-char 1)
- (re-search-forward "\n\n")
- (setq body (buffer-substring (1- (point)) (point-max)))
- (narrow-to-region 1 (point))
- (setq headers (list "Date:" "From:" "To:" "Cc:" "Subject:"
- "Message-ID:" "Keywords:" "Summary:"))
- (while headers
- (setq headline (car headers))
- (setq headers (cdr headers))
- (goto-char 1)
- (if (re-search-forward (concat "^" headline ".*$") nil t)
- (setq sorthead
- (concat sorthead (buffer-substring
- (match-beginning 0)
- (match-end 0)) "\n"))))
- (widen)))
- (insert sorthead)(goto-char (point-max))
- (insert body)(goto-char (point-max))
- (insert (concat "\n" (make-string 30 ?-) "\n\n"))
- (goto-char beg)
- (if (re-search-forward "^Subject: \\(.*\\)$" nil t)
- (progn
- (setq subj (buffer-substring (match-beginning 1) (match-end 1)))
- (save-excursion
- (set-buffer (get-buffer "*gnus-uu-pre*"))
- (insert (format " %s\n" subj))))))
- (if (or (eq in-state 'last)
- (eq in-state 'first-and-last))
- (progn
- (save-excursion
- (set-buffer (get-buffer "*gnus-uu-pre*"))
- (insert (format "\n\n%s\n\n" (make-string 70 ?-)))
- (write-region 1 (point-max) gnus-uu-saved-article-name))
- (save-excursion
- (set-buffer (get-buffer "*gnus-uu-body*"))
- (goto-char (point-max))
- (insert
- (concat (setq end-string (format "End of %s Digest" name))
- "\n"))
- (insert (concat (make-string (length end-string) ?*) "\n"))
- (write-region 1 (point-max) gnus-uu-saved-article-name t))
- (kill-buffer (get-buffer "*gnus-uu-pre*"))
- (kill-buffer (get-buffer "*gnus-uu-body*"))
- (setq state (cons 'end state))))
- (if (memq 'begin state)
- (cons gnus-uu-saved-article-name state)
- state))))
-
-
-;; Digest and forward articles
-
-(autoload 'gnus-mail-forward-using-mail "gnusmail"
- "Forward the current message to another user." t)
-(autoload 'gnus-mail-forward-using-mhe "gnusmail"
- "Forward the current message to another user." t)
-
-(defun gnus-uu-digest-and-forward (&optional marked)
- "Digests and forwards all articles in this series."
- (interactive)
- (let ((gnus-uu-save-in-digest t)
- file buf)
- (setq file (gnus-uu-save-articles nil marked t))
- (switch-to-buffer (setq buf (get-buffer-create "*gnus-uu-forward*")))
- (erase-buffer)
- (delete-other-windows)
- (erase-buffer)
- (insert-file file)
- (goto-char 1)
- (bury-buffer buf)
- (funcall gnus-mail-forward-method)))
-
-(defun gnus-uu-marked-digest-and-forward (&optional marked)
- "Digests and forwards all marked articles."
- (interactive)
- (gnus-uu-digest-and-forward t))
-
-
-;; Binhex treatment - not very advanced.
-
-(defconst gnus-uu-binhex-body-line
- "^[^:]...............................................................$")
-(defconst gnus-uu-binhex-begin-line
- "^:...............................................................$")
-(defconst gnus-uu-binhex-end-line
- ":$")
-(defvar gnus-uu-binhex-article-name nil)
-
-; This just concatenates and strips stuff from binhexed articles.
-; No actual unbinhexing takes place. VIEW is ignored.
-(defun gnus-uu-binhex-and-save (view marked)
- (gnus-uu-initialize)
- (let (list-of-articles)
- (save-excursion
- (if (not marked)
- (setq list-of-articles (gnus-uu-get-list-of-articles))
- (setq list-of-articles (reverse gnus-uu-marked-article-list))
- (setq gnus-uu-marked-article-list nil))
- (if (not list-of-articles)
- (error "No list of articles"))
-
- (setq gnus-uu-binhex-article-name
- (concat gnus-uu-work-dir
- (read-file-name "Enter binhex file name: "
- gnus-newsgroup-name
- gnus-newsgroup-name)))
- (gnus-uu-add-file gnus-uu-binhex-article-name)
- (if (gnus-uu-grab-articles list-of-articles 'gnus-uu-binhex-article t)
- (gnus-uu-save-file gnus-uu-binhex-article-name))))
- (gnus-uu-check-for-generated-files)
- (gnus-uu-summary-next-subject))
-
-(defun gnus-uu-binhex-article (buffer in-state)
- (let (state start-char)
- (save-excursion
- (set-buffer buffer)
- (widen)
- (goto-char 1)
- (if (not (re-search-forward gnus-uu-binhex-begin-line nil t))
- (if (not (re-search-forward gnus-uu-binhex-body-line nil t))
- (setq state (list 'wrong-type))))
-
- (if (memq 'wrong-type state)
- ()
- (beginning-of-line)
- (setq start-char (point))
- (if (looking-at gnus-uu-binhex-begin-line)
- (progn
- (setq state (list 'begin))
- (write-region 1 1 gnus-uu-binhex-article-name))
- (setq state (list 'middle)))
- (goto-char (point-max))
- (re-search-backward (concat gnus-uu-binhex-body-line "\\|"
- gnus-uu-binhex-end-line) nil t)
- (if (looking-at gnus-uu-binhex-end-line)
- (setq state (if (memq 'begin state)
- (cons 'end state)
- (list 'end))))
- (beginning-of-line)
- (forward-line 1)
- (if (file-exists-p gnus-uu-binhex-article-name)
- (append-to-file start-char (point) gnus-uu-binhex-article-name))))
- (if (memq 'begin state)
- (cons gnus-uu-binhex-article-name state)
- state)))
-
-
-;; Internal view commands
-
-; This function takes two parameters. The first is name of the file to
-; be viewed. `gnus-uu-view-file' will look for an action associated
-; with the file type of the file. If it finds an appropriate action,
-; the file will be attempted displayed.
-;
-; The second parameter specifies if the user is to be asked whether to
-; save the file if viewing is unsuccessful. t means "do not ask."
-;
-; Note that the file given will be deleted by this function, one way
-; or another. If `gnus-uu-asynchronous' is set, it won't be deleted
-; right away, but sometime later. If the user is offered to save the
-; file, it'll be moved to wherever the user wants it.
-
-; `gnus-uu-view-file' returns t if viewing is successful.
-
-(defun gnus-uu-view-file (file &optional silent)
- (let (action did-view)
- (cond
- ((not (setq action (gnus-uu-get-action file)))
- (if (and (not silent) (not gnus-uu-use-interactive-view))
- (progn
- (message "Couldn't find any rule for file '%s'" file)
- (sleep-for 2)
- (gnus-uu-ask-to-save-file file))))
-
- ((and gnus-uu-use-interactive-view
- (not (string= (or action "") "gnus-uu-archive")))
- (gnus-uu-enter-interactive-file (or action "") file))
-
- (gnus-uu-ask-before-view
- (if (y-or-n-p (format "Do you want to view %s? " file))
- (setq did-view (gnus-uu-call-file-action file action)))
- (message ""))
-
- ((setq did-view (gnus-uu-call-file-action file action)))
-
- ((not silent)
- (gnus-uu-ask-to-save-file file)))
-
- (if (and (file-exists-p file)
- (not gnus-uu-use-interactive-view)
- (or
- (not (and gnus-uu-asynchronous did-view))
- (string= (or action "") "gnus-uu-archive")))
- (delete-file file))
-
- did-view))
-
-(defun gnus-uu-call-file-action (file action)
- (prog1
- (if gnus-uu-asynchronous
- (gnus-uu-call-asynchronous file action)
- (gnus-uu-call-synchronous file action))
- (if gnus-uu-view-and-save
- (gnus-uu-ask-to-save-file file))))
-
-(defun gnus-uu-ask-to-save-file (file)
- (if (y-or-n-p (format "Do you want to save the file %s? " file))
- (gnus-uu-save-file file))
- (message ""))
-
-(defun gnus-uu-get-action (file-name)
- (let (action)
- (setq action
- (gnus-uu-choose-action
- file-name
- (append
- (if (and gnus-uu-use-interactive-view
- gnus-uu-user-interactive-view-rules)
- gnus-uu-user-interactive-view-rules
- gnus-uu-user-view-rules)
- (if (or gnus-uu-ignore-default-view-rules
- (not gnus-uu-use-interactive-view))
- ()
- gnus-uu-default-interactive-view-rules-begin)
- (if gnus-uu-ignore-default-view-rules
- nil
- gnus-uu-default-view-rules)
- (if gnus-uu-use-interactive-view
- (append gnus-uu-user-interactive-view-rules-end
- (if gnus-uu-ignore-default-view-rules
- ()
- gnus-uu-default-interactive-view-rules-end))
- gnus-uu-user-view-rules-end))))
- (if (and (not (string= (or action "") "gnus-uu-archive"))
- gnus-uu-view-with-metamail)
- (if (setq action
- (gnus-uu-choose-action file-name gnus-uu-ext-to-mime-list))
- (setq action (format "metamail -d -b -c \"%s\"" action))))
- action))
-
-; `gnus-uu-call-synchronous' takes two parameters: The name of the
-; file to be displayed and the command to display it with. Returns t
-; on success and nil if the file couldn't be displayed.
-(defun gnus-uu-call-synchronous (file-name action)
- (let (did-view command)
- (save-excursion
- (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
- (erase-buffer)
- (setq command (gnus-uu-command action file-name))
- (message "Viewing with '%s'" command)
- (if (not (= 0 (call-process "sh" nil t nil "-c" command)))
- (progn
- (goto-char 1)
- (while (re-search-forward "\n" nil t)
- (replace-match " "))
- (message (concat "Error: " (buffer-substring 1 (point-max))))
- (sit-for 2))
- (message "")
- (setq did-view t)))
- did-view))
-
-; `gnus-uu-call-asyncronous' takes two parameters: The name of the
-; file to be displayed and the command to display it with. Since the
-; view command is executed asynchronously, it's kinda hard to decide
-; whether the command succeded or not, so this function always returns
-; t. It also adds "; rm -f file-name" to the end of the execution
-; string, so the file will be removed after viewing has ended.
-(defun gnus-uu-call-asynchronous (file-name action)
- (let (command file tmp-file start)
- (while (string-match "/" file-name start)
- (setq start (1+ (match-beginning 0))))
- (setq file (substring file-name start))
- (setq tmp-file (concat gnus-uu-work-dir file))
- (if (string= tmp-file file-name)
- ()
- (rename-file file-name tmp-file t)
- (setq file-name tmp-file))
-
- (setq command (gnus-uu-command action file-name))
- (setq command (format "%s ; rm -f %s" command file-name))
- (message "Viewing with %s" command)
- (start-process "gnus-uu-view" nil "sh" "-c" command)
- t))
-
-; `gnus-uu-decode-and-strip' does all the main work. It finds out what
-; articles to grab, grabs them, strips the result and decodes. If any
-; of these operations fail, it returns nil, t otherwise. If shar is
-; t, it will pass this on to `gnus-uu-grab-articles', which will
-; (probably) unshar the articles. If use-marked is non-nil, it won't
-; try to find articles, but use the marked list.
-(defun gnus-uu-decode-and-strip (&optional shar use-marked limit)
- (let (list-of-articles)
- (save-excursion
-
- (if use-marked
- (if (not gnus-uu-marked-article-list)
- (message "No articles marked")
- (setq list-of-articles (reverse gnus-uu-marked-article-list))
- (setq gnus-uu-marked-article-list nil))
- (setq list-of-articles (gnus-uu-get-list-of-articles)))
-
- (and list-of-articles
- (gnus-uu-grab-articles
- list-of-articles
- (if shar 'gnus-uu-unshar-article 'gnus-uu-uustrip-article-as)
- t limit)))))
-
-; Takes a string and puts a \ in front of every special character;
-; ignores any leading "version numbers" thingies that they use in the
-; comp.binaries groups, and either replaces anything that looks like
-; "2/3" with "[0-9]+/[0-9]+" or, if it can't find something like that,
-; replaces the last two numbers with "[0-9]+". This, in my experience,
-; should get most postings of a series."
-(defun gnus-uu-reginize-string (string)
- (let ((count 2)
- (vernum "v[0-9]+[a-z][0-9]+:")
- reg beg)
- (save-excursion
- (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
- (erase-buffer)
- (insert (regexp-quote string))
- (setq beg 1)
-
- (setq case-fold-search nil)
- (goto-char 1)
- (if (looking-at vernum)
- (progn
- (replace-match vernum t t)
- (setq beg (length vernum))))
-
- (goto-char beg)
- (if (re-search-forward "[ \t]*[0-9]+/[0-9]+" nil t)
- (replace-match " [0-9]+/[0-9]+")
-
- (goto-char beg)
- (if (re-search-forward "[0-9]+[ \t]*of[ \t]*[0-9]+" nil t)
- (replace-match "[0-9]+ of [0-9]+")
-
- (end-of-line)
- (while (and (re-search-backward "[0-9]" nil t) (> count 0))
- (while (and
- (looking-at "[0-9]")
- (< 1 (goto-char (1- (point))))))
- (re-search-forward "[0-9]+" nil t)
- (replace-match "[0-9]+")
- (backward-char 5)
- (setq count (1- count)))))
-
- (goto-char beg)
- (while (re-search-forward "[ \t]+" nil t)
- (replace-match "[ \t]*" t t))
-
- (buffer-substring 1 (point-max)))))
-
-; Finds all articles that matches the regular expression given.
-; Returns the resulting list. SUBJECT is the regular expression to be
-; matched. If it is nil, the current article name will be used. If
-; MARK-ARTICLES is non-nil, articles found are marked. If ONLY-UNREAD
-; is non-nil, only unread articles are chose. If DO-NOT-TRANSLATE is
-; non-nil, article names are not equialized before sorting.
-(defun gnus-uu-get-list-of-articles (&optional subject mark-articles only-unread do-not-translate)
- (let (beg end reg-subject list-of-subjects list-of-numbers art-num)
- (save-excursion
-
-; If the subject is not given, this function looks at the current subject
-; and takes that.
-
- (if subject
- (setq reg-subject subject)
- (end-of-line)
- (setq end (point))
- (beginning-of-line)
- (if (not (re-search-forward "\\] " end t))
- (progn (message "No valid subject chosen") (sit-for 2))
- (setq subject (buffer-substring (point) end))
- (setq reg-subject
- (concat "\\[.*\\] " (gnus-uu-reginize-string subject)))))
-
-; (message reg-subject)(sleep-for 2)
-
- (if reg-subject
- (progn
-
-; Collect all subjects matching reg-subject.
-
- (let ((case-fold-search t))
- (goto-char 1)
- (while (re-search-forward reg-subject nil t)
- (beginning-of-line)
- (setq beg (point))
- (if (or (not only-unread) (looking-at " \\|-"))
- (progn
- (end-of-line)
- (setq list-of-subjects (cons
- (buffer-substring beg (point))
- list-of-subjects)))
- (end-of-line))))
-
-; Expand all numbers in all the subjects: (hi9 -> hi0009, etc).
-
- (setq list-of-subjects (gnus-uu-expand-numbers
- list-of-subjects
- (not do-not-translate)))
-
-; Sort the subjects.
-
- (setq list-of-subjects (sort list-of-subjects 'gnus-uu-string<))
-
-; Get the article numbers from the sorted list of subjects.
-
- (while list-of-subjects
- (setq art-num (gnus-uu-article-number (car list-of-subjects)))
- (if mark-articles (gnus-summary-mark-as-read art-num ?#))
- (setq list-of-numbers (cons art-num list-of-numbers))
- (setq list-of-subjects (cdr list-of-subjects)))
-
- (setq list-of-numbers (nreverse list-of-numbers))))
-
- list-of-numbers)))
-
-; Takes a list of strings and "expands" all numbers in all the
-; strings. That is, this function makes all numbers equal length by
-; prepending lots of zeroes before each number. This is to ease later
-; sorting to find out what sequence the articles are supposed to be
-; decoded in. Returns the list of expanded strings.
-(defun gnus-uu-expand-numbers (string-list &optional translate)
- (let (string out-list pos num)
- (save-excursion
- (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
- (while string-list
- (erase-buffer)
- (setq string (car string-list))
- (setq string-list (cdr string-list))
- (insert string)
- (goto-char 1)
- (while (re-search-forward "[ \t]+" nil t)
- (replace-match " "))
- (goto-char 1)
- (if translate
- (while (re-search-forward "[A-Za-z]" nil t)
- (replace-match "a" t t)))
-
- (goto-char 1)
- (if (not (search-forward "] " nil t))
- ()
- (while (re-search-forward "[0-9]+" nil t)
- (replace-match
- (format "%06d"
- (string-to-int (buffer-substring
- (match-beginning 0) (match-end 0))))))
- (setq string (buffer-substring 1 (point-max)))
- (setq out-list (cons string out-list)))))
- out-list))
-
-; Used in a sort for finding out what string is bigger, but ignoring
-; everything before the subject part.
-(defun gnus-uu-string< (string1 string2)
- (string< (substring string1 (string-match "\\] " string1))
- (substring string2 (string-match "\\] " string2))))
-
-
-;; gnus-uu-grab-article
-;
-; This is the general multi-article treatment function. It takes a
-; list of articles to be grabbed and a function to apply to each
-; article. It puts the result in `gnus-uu-result-buffer'.
-;
-; The function to be called should take two parameters. The first
-; parameter is the article buffer. The function should leave the
-; result, if any, in this buffer. This result is then appended on to
-; the `gnus-uu-result-buffer'. Most treatment functions will just
-; generate files...
-;
-; The second parameter is the state of the list of articles, and can
-; have four values: `first', `middle', `last' and `first-and-last'.
-;
-; The function should return a list. The list may contain the
-; following symbols:
-; `error' if an error occurred
-; `begin' if the beginning of an encoded file has been received
-; If the list returned contains a `begin', the first element of
-; the list *must* be a string with the file name of the decoded
-; file.
-; `end' if the the end of an encoded file has been received
-; `middle' if the article was a body part of an encoded file
-; `wrong-type' if the article was not a part of an encoded file
-; `ok', which can be used everything is ok
-
-(defvar gnus-uu-has-been-grabbed nil)
-
-(defun gnus-uu-unmark-list-of-grabbed (&optional dont-unmark-last-article)
- (let (art)
- (if (not (and gnus-uu-has-been-grabbed
- gnus-uu-unmark-articles-not-decoded))
- ()
- (if dont-unmark-last-article
- (progn
- (setq art (car gnus-uu-has-been-grabbed))
- (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed))))
- (while gnus-uu-has-been-grabbed
- (gnus-summary-mark-as-unread (car gnus-uu-has-been-grabbed) t)
- (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed)))
- (if dont-unmark-last-article
- (setq gnus-uu-has-been-grabbed (list art))))))
-
-
-; This function takes a list of articles and a function to apply to
-; each article grabbed. The result of the function is appended on to
-; `gnus-uu-result-buffer'.
-;
-; This function returns a list of files decoded if the grabbing and
-; the process-function has been successful and nil otherwise.
-(defun gnus-uu-grab-articles (list-of-articles process-function &optional sloppy limit)
- (let ((result-buffer (get-buffer-create gnus-uu-result-buffer))
- (state 'first)
- (wrong-type t)
- has-been-begin has-been-end
- article result-file result-files process-state)
-
- (save-excursion
- (set-buffer result-buffer)
- (erase-buffer))
- (setq gnus-uu-has-been-grabbed nil)
-
- (while (and list-of-articles
- (not (memq 'error process-state))
- (or sloppy
- (not (memq 'end process-state))))
-
- (setq article (car list-of-articles))
- (setq list-of-articles (cdr list-of-articles))
- (setq gnus-uu-has-been-grabbed (cons article gnus-uu-has-been-grabbed))
-
- (if (> article gnus-uu-highest-article-number)
- (setq gnus-uu-highest-article-number article))
-
- (if (eq list-of-articles ())
- (if (eq state 'first)
- (setq state 'first-and-last)
- (setq state 'last)))
-
- (message "Getting article %d" article)
- (if (not (= (or gnus-current-article 0) article))
- (gnus-summary-display-article article))
- (gnus-summary-mark-as-read article)
-
- (save-excursion (set-buffer gnus-article-buffer) (widen))
-
- (setq process-state (funcall process-function gnus-article-buffer state))
-
-; (message "process-state er %s" process-state)(sleep-for 3)
-
- (if (or (memq 'begin process-state)
- (and (or (eq state 'first) (eq state 'first-and-last))
- (memq 'ok process-state)))
- (progn
- (if has-been-begin
- (if (file-exists-p result-file) (delete-file result-file)))
- (setq result-file (car process-state))
- (setq has-been-begin t)
- (setq has-been-end nil)))
-
- (if (memq 'end process-state)
- (progn
- (setq gnus-uu-has-been-grabbed nil)
- (setq result-files (cons result-file result-files))
- (setq has-been-end t)
- (setq has-been-begin nil)
- (if (and limit (= (length result-files) limit))
- (progn
- (setq list-of-articles nil)
- (setq gnus-uu-marked-article-list nil)))))
-
- (if (and (or (eq state 'last) (eq state 'first-and-last))
- (not (memq 'end process-state)))
- (if (and result-file (file-exists-p result-file))
- (delete-file result-file)))
-
- (setq result-file nil)
-
- (if (not (memq 'wrong-type process-state))
- (setq wrong-type nil)
- (if gnus-uu-unmark-articles-not-decoded
- (gnus-summary-mark-as-unread article t)))
-
- (if sloppy (setq wrong-type nil))
-
- (if (and (not has-been-begin)
- (not sloppy)
- (or (memq 'end process-state)
- (memq 'middle process-state)))
- (progn
- (setq process-state (list 'error))
- (message "No begin part at the beginning")
- (sleep-for 2))
- (setq state 'middle)))
-
- (if result-files
- ()
- (if (not has-been-begin)
- (message "Wrong type file")
- (if (memq 'error process-state)
- (setq result-files nil)
- (if (not (or (memq 'ok process-state)
- (memq 'end process-state)))
- (progn
- (message "End of articles reached before end of file")
- (setq result-files nil))
- (gnus-uu-unmark-list-of-grabbed)))))
- (setq gnus-uu-list-of-files-decoded result-files)
- result-files))
-
-(defun gnus-uu-uudecode-sentinel (process event)
- (delete-process (get-process process)))
-
-; Uudecodes a file asynchronously.
-(defun gnus-uu-uustrip-article-as (process-buffer in-state)
- (let ((state (list 'ok))
- (process-connection-type nil)
- start-char pst name-beg name-end)
- (save-excursion
- (set-buffer process-buffer)
- (let ((case-fold-search nil)
- (buffer-read-only nil))
-
- (goto-char 1)
-
- (if gnus-uu-kill-carriage-return
- (progn
- (while (search-forward "\r" nil t)
- (delete-backward-char 1))
- (goto-char 1)))
-
- (if (not (re-search-forward gnus-uu-begin-string nil t))
- (if (not (re-search-forward gnus-uu-body-line nil t))
- (setq state (list 'wrong-type))))
-
- (if (memq 'wrong-type state)
- ()
- (beginning-of-line)
- (setq start-char (point))
-
- (if (looking-at gnus-uu-begin-string)
- (progn
- (setq name-end (match-end 1))
-
- ; Replace any slashes and spaces in file names before decoding
- (goto-char (setq name-beg (match-beginning 1)))
- (while (re-search-forward "/" name-end t)
- (replace-match ","))
- (goto-char name-beg)
- (while (re-search-forward " " name-end t)
- (replace-match "_"))
-
- (setq gnus-uu-file-name (buffer-substring name-beg name-end))
- (and gnus-uu-uudecode-process
- (setq pst (process-status
- (or gnus-uu-uudecode-process "nevair")))
- (if (or (eq pst 'stop) (eq pst 'run))
- (progn
- (delete-process gnus-uu-uudecode-process)
- (gnus-uu-unmark-list-of-grabbed t))))
- (setq gnus-uu-uudecode-process
- (start-process
- "*uudecode*"
- (get-buffer-create gnus-uu-output-buffer-name)
- "sh" "-c"
- (format "cd %s ; uudecode" gnus-uu-work-dir)))
- (set-process-sentinel
- gnus-uu-uudecode-process 'gnus-uu-uudecode-sentinel)
- (setq state (list 'begin))
- (gnus-uu-add-file (concat gnus-uu-work-dir gnus-uu-file-name)))
- (setq state (list 'middle)))
-
- (goto-char (point-max))
-
- (re-search-backward
- (concat gnus-uu-body-line "\\|" gnus-uu-end-string) nil t)
- (beginning-of-line)
-
- (if (looking-at gnus-uu-end-string)
- (setq state (cons 'end state)))
- (forward-line 1)
-
- (and gnus-uu-uudecode-process
- (setq pst (process-status
- (or gnus-uu-uudecode-process "nevair")))
- (if (or (eq pst 'run) (eq pst 'stop))
- (progn
- (if gnus-uu-correct-stripped-uucode
- (progn
- (gnus-uu-check-correct-stripped-uucode
- start-char (point))
- (goto-char (point-max))
- (re-search-backward
- (concat gnus-uu-body-line "\\|"
- gnus-uu-end-string)
- nil t)
- (forward-line 1)))
- (condition-case err
- (process-send-region gnus-uu-uudecode-process
- start-char (point))
- (error
- (progn
- (message "gnus-uu: Couldn't uudecode")
- (sleep-for 2)
- (setq state (list 'wrong-type))
- (delete-process gnus-uu-uudecode-process))))
- (if (memq 'end state)
- (accept-process-output gnus-uu-uudecode-process)))
- (setq state (list 'wrong-type))))
- (if (not gnus-uu-uudecode-process)
- (setq state (list 'wrong-type)))))
-
- (if (memq 'begin state)
- (cons (concat gnus-uu-work-dir gnus-uu-file-name) state)
- state))))
-
-; This function is used by `gnus-uu-grab-articles' to treat
-; a shared article.
-(defun gnus-uu-unshar-article (process-buffer in-state)
- (let ((state (list 'ok))
- start-char)
- (save-excursion
- (set-buffer process-buffer)
- (goto-char 1)
- (if (not (re-search-forward gnus-uu-shar-begin-string nil t))
- (setq state (list 'wrong-type))
- (beginning-of-line)
- (setq start-char (point))
- (call-process-region
- start-char (point-max) "sh" nil
- (get-buffer-create gnus-uu-output-buffer-name) nil
- "-c" (concat "cd " gnus-uu-shar-directory " ; sh"))))
- state))
-
-; Returns the name of what the shar file is going to unpack.
-(defun gnus-uu-find-name-in-shar ()
- (let ((oldpoint (point))
- res)
- (goto-char 1)
- (if (re-search-forward gnus-uu-shar-name-marker nil t)
- (setq res (buffer-substring (match-beginning 1) (match-end 1))))
- (goto-char oldpoint)
- res))
-
-; Returns the article number of the given subject.
-(defun gnus-uu-article-number (subject)
- (let (end)
- (string-match "[0-9]+[^0-9]" subject 1)
- (setq end (match-end 0))
- (string-to-int
- (substring subject (string-match "[0-9]" subject 1) end))))
-
-; `gnus-uu-choose-action' chooses what action to perform given the name
-; and `gnus-uu-file-action-list'. Returns either nil if no action is
-; found, or the name of the command to run if such a rule is found.
-(defun gnus-uu-choose-action (file-name file-action-list &optional no-ignore)
- (let ((action-list (copy-sequence file-action-list))
- rule action)
- (and
- (or no-ignore
- (and (not
- (and gnus-uu-ignore-files-by-name
- (string-match gnus-uu-ignore-files-by-name file-name)))
- (not
- (and gnus-uu-ignore-files-by-type
- (string-match gnus-uu-ignore-files-by-type
- (or (gnus-uu-choose-action
- file-name gnus-uu-ext-to-mime-list t)
- ""))))))
- (while (not (or (eq action-list ()) action))
- (setq rule (car action-list))
- (setq action-list (cdr action-list))
- (if (string-match (car rule) file-name)
- (setq action (car (cdr rule))))))
- action))
-
-(defun gnus-uu-save-directory (from-dir &optional default-dir ignore-existing)
- (let (dir file-name command files file)
- (setq files (directory-files from-dir t))
- (if default-dir
- (setq dir default-dir)
- (setq dir (gnus-uu-read-directory
- (concat "Where do you want the file"
- (if (< 3 (length files)) "s" "") "? "))))
-
- (while files
- (setq file (car files))
- (setq files (cdr files))
- (string-match "/[^/]*$" file)
- (setq file-name (substring file (1+ (match-beginning 0))))
- (if (string-match "^\\.\\.?$" file-name)
- ()
- (if (and (not ignore-existing) (file-exists-p (concat dir file-name)))
- (setq file-name
- (read-file-name "File exists. Enter a new name: " dir
- (concat dir file-name) nil file-name))
- (setq file-name (concat dir file-name)))
- (rename-file file file-name t)))))
-
-; Moves the file from the tmp directory to where the user wants it.
-(defun gnus-uu-save-file (from-file-name &optional default-dir ignore-existing)
- (let (dir file-name command)
- (string-match "/[^/]*$" from-file-name)
- (setq file-name (substring from-file-name (1+ (match-beginning 0))))
- (if default-dir
- (setq dir default-dir)
- (setq dir (gnus-uu-read-directory "Where do you want the file? ")))
- (if (and (not ignore-existing) (file-exists-p (concat dir file-name)))
- (setq file-name
- (read-file-name "File exist. Enter a new name: " dir
- (concat dir file-name) nil file-name))
- (setq file-name (concat dir file-name)))
- (rename-file from-file-name file-name t)))
-
-(defun gnus-uu-read-directory (prompt &optional default)
- (let (dir ok create)
- (while (not ok)
- (setq ok t)
- (setq dir (if default default
- (read-file-name prompt gnus-uu-current-save-dir
- gnus-uu-current-save-dir)))
- (while (string-match "/$" dir)
- (setq dir (substring dir 0 (match-beginning 0))))
- (if (file-exists-p dir)
- (if (not (file-directory-p dir))
- (progn
- (setq ok nil)
- (message "%s is a file" dir)
- (sit-for 2)))
- (setq create ?o)
- (while (not (or (= create ?y) (= create ?n)))
- (message "%s: No such directory. Do you want to create it? (y/n)"
- dir)
- (setq create (read-char)))
- (if (= create ?y) (make-directory dir))))
- (setq gnus-uu-current-save-dir (concat dir "/"))))
-
-; Unpacks an archive and views all the files in it. Returns t if
-; viewing one or more files is successful.
-(defun gnus-uu-treat-archive (file-path)
- (let ((did-unpack t)
- action command files file file-name dir)
- (setq action (gnus-uu-choose-action
- file-path (append gnus-uu-user-archive-rules
- (if gnus-uu-ignore-default-archive-rules
- nil
- gnus-uu-default-archive-rules))))
-
- (if (not action) (error "No unpackers for the file %s" file-path))
-
- (string-match "/[^/]*$" file-path)
- (setq file-name (substring file-path (1+ (match-beginning 0))))
- (setq dir (substring file-path 0 (match-beginning 0)))
-
- (if (gnus-uu-string-in-list action gnus-uu-destructive-archivers)
- (copy-file file-path (concat file-path "~") t))
-
- (setq command (format "cd %s ; %s" dir (gnus-uu-command action file-path)))
-
- (save-excursion
- (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
- (erase-buffer))
-
- (message "Unpacking: %s..." (gnus-uu-command action file-path))
-
- (if (= 0 (call-process "sh" nil
- (get-buffer-create gnus-uu-output-buffer-name)
- nil "-c" command))
- (message "")
- (if (not gnus-uu-use-interactive-view)
- (progn
- (message "Error during unpacking of archive")
- (sleep-for 2)))
- (setq did-unpack nil))
-
- (if (gnus-uu-string-in-list action gnus-uu-destructive-archivers)
- (rename-file (concat file-path "~") file-path t))
-
- did-unpack))
-
-; Tries to view all the files in the given directory. Returns t if
-; viewing one or more files is successful.
-(defun gnus-uu-view-directory (dir &optional dont-delete-files not-top)
- (let ((first t)
- files file did-view ignore-files)
- (setq files (directory-files dir t "[^/][^\\.][^\\.]?$"))
- (gnus-uu-add-file files)
- (setq ignore-files files)
-
- (while (gnus-uu-unpack-archives
- files (if not-top (list ".")
- (if first () ignore-files)))
- (setq first nil)
- (gnus-uu-add-file
- (setq files (directory-files dir t "[^/][^\\.][^\\.]?$"))))
-
- (gnus-uu-add-file (directory-files dir t "[^/][^\\.][^\\.]?$"))
-
- (while files
- (setq file (car files))
- (setq files (cdr files))
- (if (not (string= (or (gnus-uu-get-action file) "") "gnus-uu-archive"))
- (progn
- (set-file-modes file 448)
- (if (file-directory-p file)
- (setq did-view (or (gnus-uu-view-directory file
- dont-delete-files
- t)
- did-view))
- (setq did-view (or (gnus-uu-view-file file t) did-view)))))
- (if (and (not dont-delete-files) (not gnus-uu-asynchronous)
- (file-exists-p file))
- (delete-file file)))
-
- (if (and (not gnus-uu-asynchronous) (not dont-delete-files))
- (if (string-match "/$" dir)
- (delete-directory (substring dir 0 (match-beginning 0)))
- (delete-directory dir)))
- did-view))
-
-(defun gnus-uu-unpack-archives (files &optional ignore)
- (let (path did-unpack)
- (while files
- (setq path (car files))
- (setq files (cdr files))
- (if (not (gnus-uu-string-in-list path ignore))
- (if (string= (or (gnus-uu-get-action
- (gnus-uu-name-from-path path)) "")
- "gnus-uu-archive")
- (progn
- (if (and (not (setq did-unpack (gnus-uu-treat-archive path)))
- gnus-uu-use-interactive-view)
- (gnus-uu-enter-interactive-file
- "# error during unpacking of" path))
- (if ignore (delete-file path))))))
- did-unpack))
-
-
-;; Manual marking
-
-(defun gnus-uu-enter-mark-in-list ()
- (let (article beg)
- (save-excursion
- (beginning-of-line)
- (setq beg (point))
- (end-of-line)
- (setq article (gnus-uu-article-number
- (buffer-substring beg (point))))
- (message "Adding article %d to list" article)
- (setq gnus-uu-marked-article-list
- (cons article gnus-uu-marked-article-list)))))
-
-(defun gnus-uu-mark-article (&optional dont-move)
- "Marks the current article to be decoded later."
- (interactive)
- (gnus-uu-enter-mark-in-list)
- (gnus-summary-mark-as-read nil ?#)
- (gnus-summary-next-subject 1 nil))
-
-(defun gnus-uu-unmark-article ()
- "Unmarks the current article."
- (interactive)
- (let ((in (copy-sequence gnus-uu-marked-article-list))
- out article beg found
- (old-point (point)))
- (beginning-of-line)
- (setq beg (point))
- (end-of-line)
- (setq article (gnus-uu-article-number (buffer-substring beg (point))))
- (message "Removing article %d" article)
- (while in
- (if (not (= (car in) article))
- (setq out (cons (car in) out))
- (setq found t)
- (message "Removing article %d" article))
- (setq in (cdr in)))
- (if (not found) (message "Not a marked article."))
- (setq gnus-uu-marked-article-list (reverse out))
- (gnus-summary-mark-as-unread nil t)
- (gnus-summary-next-subject 1 nil)))
-
-(defun gnus-uu-unmark-all-articles ()
- "Removes the mark from all articles marked for decoding."
- (interactive)
- (while gnus-uu-marked-article-list
- (gnus-summary-goto-subject (car gnus-uu-marked-article-list))
- (gnus-summary-mark-as-unread nil t)
- (setq gnus-uu-marked-article-list (cdr gnus-uu-marked-article-list))))
-
-(defun gnus-uu-mark-by-regexp ()
- "Asks for a regular expression and marks all articles that match."
- (interactive)
- (let (exp)
- (setq exp (read-from-minibuffer "Mark (regexp): "))
- (setq gnus-uu-marked-article-list
- (append gnus-uu-marked-article-list
- (reverse (gnus-uu-get-list-of-articles exp t))))
- (message "")))
-
-(defun gnus-uu-mark-thread ()
- "Marks all articles downwards in this thread."
- (interactive)
- (beginning-of-line)
- (let (level)
- (if (not (search-forward ":" nil t))
- ()
- (setq level (current-column))
- (gnus-uu-enter-mark-in-list)
- (gnus-summary-mark-as-read nil ?#)
- (gnus-summary-search-forward)
- (while (< level (current-column))
- (gnus-uu-enter-mark-in-list)
- (gnus-summary-mark-as-read nil ?#)
- (gnus-summary-search-forward))
- (gnus-summary-search-backward))))
-
-
-;; Various stuff
-
-(defun gnus-uu-string-in-list (string list)
- (while (and list
- (not (string= (car list) string))
- (setq list (cdr list))))
- list)
-
-(defun gnus-uu-name-from-path (path)
- (string-match "/[^/]*$" path)
- (substring path (1+ (match-beginning 0))))
-
-(defun gnus-uu-directory-files (dir)
- (let (files out file)
- (setq files (directory-files dir t))
- (while files
- (setq file (car files))
- (setq files (cdr files))
- (if (not (string-match "/\\.\\.?$" file))
- (setq out (cons file out))))
- (setq out (reverse out))
- out))
-
-(defun gnus-uu-check-correct-stripped-uucode (start end)
- (let (found beg length short)
- (if (not gnus-uu-correct-stripped-uucode)
- ()
- (goto-char start)
-
- (if (re-search-forward " \\|`" end t)
- (progn
- (goto-char start)
- (while (not (eobp))
- (progn
- (if (looking-at "\n") (replace-match ""))
- (forward-line 1))))
-
- (while (not (eobp))
- (if (looking-at (concat gnus-uu-begin-string "\\|"
- gnus-uu-end-string))
- ()
- (if (not found)
- (progn
- (beginning-of-line)
- (setq beg (point))
- (end-of-line)
- (setq length (- (point) beg))))
- (setq found t)
- (beginning-of-line)
- (setq beg (point))
- (end-of-line)
- (if (not (= length (- (point) beg)))
- (insert (make-string (- length (- (point) beg)) ? ))))
- (forward-line 1))))))
-
-(defun gnus-uu-initialize ()
- (setq gnus-uu-highest-article-number 1)
- (gnus-uu-check-for-generated-files)
- (setq gnus-uu-tmp-dir (expand-file-name gnus-uu-tmp-dir))
- (if (string-match "[^/]$" gnus-uu-tmp-dir)
- (setq gnus-uu-tmp-dir (concat gnus-uu-tmp-dir "/")))
- (if (not (file-directory-p gnus-uu-tmp-dir))
- (error "Temp directory %s doesn't exist" gnus-uu-tmp-dir)
- (if (not (file-writable-p gnus-uu-tmp-dir))
- (error "Temp directory %s can't be written to" gnus-uu-tmp-dir)))
- (setq gnus-uu-work-dir
- (concat gnus-uu-tmp-dir (make-temp-name "gnus")))
- (gnus-uu-add-file gnus-uu-work-dir)
- (if (not (file-directory-p gnus-uu-work-dir))
- (make-directory gnus-uu-work-dir))
- (setq gnus-uu-work-dir (concat gnus-uu-work-dir "/"))
- (setq gnus-uu-interactive-file-list nil))
-
-; Kills the temporary uu buffers, kills any processes, etc.
-(defun gnus-uu-clean-up ()
- (let (buf pst)
- (and gnus-uu-uudecode-process
- (setq pst (process-status (or gnus-uu-uudecode-process "nevair")))
- (if (or (eq pst 'stop) (eq pst 'run))
- (delete-process gnus-uu-uudecode-process)))
- (and (not gnus-uu-asynchronous)
- (setq buf (get-buffer gnus-uu-output-buffer-name))
- (kill-buffer buf))
- (and (setq buf (get-buffer gnus-uu-result-buffer))
- (kill-buffer buf))))
-
-; `gnus-uu-check-for-generated-files' deletes any generated files that
-; hasn't been deleted, if, for instance, the user terminated decoding
-; with `C-g'.
-(defun gnus-uu-check-for-generated-files ()
- (let (file dirs)
- (while gnus-uu-generated-file-list
- (setq file (car gnus-uu-generated-file-list))
- (setq gnus-uu-generated-file-list (cdr gnus-uu-generated-file-list))
- (if (not (string-match "/\\.[\\.]?$" file))
- (progn
- (if (file-directory-p file)
- (setq dirs (cons file dirs))
- (if (file-exists-p file)
- (delete-file file))))))
- (setq dirs (nreverse dirs))
- (while dirs
- (setq file (car dirs))
- (setq dirs (cdr dirs))
- (if (file-directory-p file)
- (if (string-match "/$" file)
- (delete-directory (substring file 0 (match-beginning 0)))
- (delete-directory file))))))
-
-; Add a file (or a list of files) to be checked (and deleted if it/they
-; still exists upon exiting the newsgroup).
-(defun gnus-uu-add-file (file)
- (if (stringp file)
- (setq gnus-uu-generated-file-list
- (cons file gnus-uu-generated-file-list))
- (setq gnus-uu-generated-file-list
- (append file gnus-uu-generated-file-list))))
-
-; Go to the next unread subject. If there is no further unread
-; subjects, go to the last subject in the buffer.
-(defun gnus-uu-summary-next-subject ()
- (let (opi)
- (if (not (gnus-summary-search-forward t))
- (progn
- (goto-char 1)
- (sit-for 0)
- (gnus-summary-goto-subject gnus-uu-highest-article-number)))
-
- ; You may well find all this a bit puzzling - so do I, but I seem
- ; to have to do something like this to move to the next unread article,
- ; as `sit-for' seems to do some rather strange things here. Might
- ; be a bug in my head, probably.
- (setq opi (point))
- (sit-for 0)
- (goto-char opi)
- (gnus-summary-recenter)))
-
-; Inputs an action and a file and returns a full command, putting
-; ticks round the file name and escaping any ticks in the file name.
-(defun gnus-uu-command (action file)
- (let ((ofile ""))
- (while (string-match "`\\|\"\\|\\$\\|\\\\" file)
- (progn
- (setq ofile
- (concat ofile (substring file 0 (match-beginning 0)) "\\"
- (substring file (match-beginning 0) (match-end 0))))
- (setq file (substring file (1+ (match-beginning 0))))))
- (setq ofile (concat "\"" ofile file "\""))
- (if (string-match "%s" action)
- (format action ofile)
- (concat action " " ofile))))
-
-
-;; Initializing
-(add-hook 'gnus-exit-group-hook
- '(lambda ()
- (gnus-uu-clean-up)
- (setq gnus-uu-marked-article-list nil)
- (gnus-uu-check-for-generated-files)))
-
-
-;; Interactive exec mode
-
-(defvar gnus-uu-output-window nil)
-(defvar gnus-uu-mode-hook nil)
-
-(defvar gnus-uu-mode-map nil)
-(if gnus-uu-mode-map
- ()
- (setq gnus-uu-mode-map (make-sparse-keymap))
- (define-key gnus-uu-mode-map "\C-c\C-x" 'gnus-uu-interactive-execute)
- (define-key gnus-uu-mode-map "\C-c\C-v" 'gnus-uu-interactive-execute)
- (define-key gnus-uu-mode-map "\C-m" 'gnus-uu-interactive-execute)
- (define-key gnus-uu-mode-map "\C-c\C-c" 'gnus-uu-interactive-end)
- (define-key gnus-uu-mode-map "\C-c\C-z"
- 'gnus-uu-interactive-save-current-file)
- (define-key gnus-uu-mode-map "\C-c\C-s"
- 'gnus-uu-interactive-save-current-file-silent)
- (define-key gnus-uu-mode-map "\C-c\C-w" 'gnus-uu-interactive-save-all-files)
- (define-key gnus-uu-mode-map "\C-c\C-o" 'gnus-uu-interactive-save-original-file)
- (define-key gnus-uu-mode-map "\C-c\C-r" 'gnus-uu-interactive-rescan-directory)
- (define-key gnus-uu-mode-map "\C-c\C-d" 'gnus-uu-interactive-scan-directory)
- )
-
-(defun gnus-uu-interactive-set-up-windows ()
- (let (int-buf out-buf)
- (set-buffer
- (setq int-buf (get-buffer-create gnus-uu-interactive-buffer-name)))
- (if (not (get-buffer-window int-buf))
- (switch-to-buffer-other-window int-buf))
- (pop-to-buffer int-buf)
- (setq out-buf (get-buffer-create gnus-uu-output-buffer-name))
- (if (not (get-buffer-window out-buf))
- (progn
- (setq gnus-uu-output-window
- (split-window nil (- (window-height)
- gnus-uu-output-window-height)))
- (set-window-buffer gnus-uu-output-window out-buf)))))
-
-(defun gnus-uu-do-interactive (&optional dont-do-windows)
- (if (not gnus-uu-interactive-file-list)
- (gnus-uu-enter-interactive-file "#" ""))
- (if (not dont-do-windows) (gnus-uu-interactive-set-up-windows))
- (save-excursion
- (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
- (erase-buffer))
- (set-buffer (get-buffer-create gnus-uu-interactive-buffer-name))
- (goto-char 1)
- (forward-line 3)
- (run-hooks 'gnus-uu-mode-hook))
-
-(defun gnus-uu-enter-interactive-file (action file)
- (let (command)
- (save-excursion
- (set-buffer (get-buffer-create gnus-uu-interactive-buffer-name))
- (if (not gnus-uu-interactive-file-list)
- (progn
- (erase-buffer)
- (gnus-uu-mode)
- (insert
- "# Press return to execute a command.
-# Press `C-c C-c' to exit interactive view.
-
-")))
- (setq gnus-uu-interactive-file-list
- (cons file gnus-uu-interactive-file-list))
-; (if (string-match (concat "^" gnus-uu-work-dir) file)
-; (setq file (substring file (match-end 0))))
- (setq command (gnus-uu-command action file))
- (goto-char (point-max))
- (insert (format "%s\n" command)))))
-
-(defun gnus-uu-interactive-execute ()
- "Executes the command on the current line in interactive mode."
- (interactive)
- (let (beg out-buf command)
- (beginning-of-line)
- (setq beg (point))
- (end-of-line)
- (setq command (buffer-substring beg (point)))
- (setq out-buf (get-buffer-create gnus-uu-output-buffer-name))
- (save-excursion
- (set-buffer out-buf)
- (erase-buffer)
- (insert (format "$ %s \n\n" command)))
- (setq command (format "cd %s ; %s" gnus-uu-work-dir command))
- (message "Executing...")
- (if gnus-uu-asynchronous
- (start-process "gnus-uu-view" out-buf "sh" "-c" command)
- (call-process "sh" nil out-buf nil "-c" command)
- (message ""))
- (end-of-line)
- (if (= (forward-line 1) 1)
- (progn
- (end-of-line)
- (insert "\n")))
- (beginning-of-line)))
-
-(defun gnus-uu-interactive-end ()
- "This function exits interactive view mode and returns to summary mode."
- (interactive)
- (let (buf)
- (delete-window gnus-uu-output-window)
- (gnus-uu-clean-up)
- (if (not gnus-uu-asynchronous) (gnus-uu-check-for-generated-files))
- (setq buf (get-buffer gnus-uu-interactive-buffer-name))
- (if gnus-article-buffer (switch-to-buffer gnus-article-buffer))
- (if buf (kill-buffer buf))
- (pop-to-buffer gnus-summary-buffer)))
-
-
-(defun gnus-uu-interactive-scan-directory (dir)
- "Read any directory and view the files.
-When used in interactive mode, the files and commands will be displayed,
-as usual, in the interactive mode buffer."
- (interactive "DDirectory: ")
- (setq gnus-uu-interactive-file-list nil)
- (gnus-uu-view-directory dir gnus-uu-use-interactive-view)
- (gnus-uu-do-interactive t))
-
-(defun gnus-uu-interactive-rescan-directory ()
- "Reread the directory and view the files.
-When used in interactive mode, the files and commands will be displayed,
-as usual, in the interactive mode buffer."
- (interactive)
- (gnus-uu-interactive-scan-directory gnus-uu-work-dir))
-
-(defun gnus-uu-interactive-save-original-file ()
- "Saves the file from whence the file on the current line came from."
- (interactive)
- (let ((files gnus-uu-list-of-files-decoded)
- (filestr "")
- file did dir)
- (while files
- (setq file (car files))
- (setq files (cdr files))
- (if (file-exists-p file)
- (progn
- (if (not did)
- (progn
- (setq dir (gnus-uu-read-directory
- (format "Where do you want the file%s? "
- (if (> (length files) 1) "s" ""))))
- (setq did t)))
- (setq filestr (concat filestr (gnus-uu-name-from-path file) " "))
- (gnus-uu-save-file file dir t)))
- (if did
- (message "Saved %s" filestr)
- (message "Already saved.")))))
-
-(defun gnus-uu-interactive-save-current-file-silent ()
- "Saves the file referred to on the current line in the current directory."
- (interactive)
- (gnus-uu-interactive-save-current-file t))
-
-(defun gnus-uu-interactive-save-current-file (&optional dont-ask silent)
- "Saves the file referred to on the current line."
- (interactive)
- (let (files beg line file)
- (setq files (copy-sequence gnus-uu-interactive-file-list))
- (beginning-of-line)
- (setq beg (point))
- (end-of-line)
- (setq line (buffer-substring beg (point)))
- (while (and files
- (not (string-match
- (concat "" (regexp-quote (setq file (car files))) "")
- line)))
- (setq files (cdr files)))
- (beginning-of-line)
- (forward-line 1)
- (if (not files)
- (if (not silent)
- (progn (message "Could not find file") (sit-for 2)))
- (gnus-uu-save-file file (if dont-ask gnus-uu-current-save-dir nil) silent)
- (delete-region beg (point)))))
-
-(defun gnus-uu-interactive-save-all-files ()
- "Saves all files referred to in the interactive buffer."
- (interactive)
- (let (dir)
- (goto-char 1)
- (setq dir (gnus-uu-read-directory "Where do you want the files? "))
- (while (not (eobp))
- (gnus-uu-interactive-save-current-file t t))))
-
-(defun gnus-uu-mode ()
- "Major mode for editing view commands in gnus-uu.
-
-Commands:
-\\<gnus-uu-mode-map>Return, C-c C-v, C-c C-x Execute the current command
-\\[gnus-uu-interactive-end]\tEnd interactive mode
-\\[gnus-uu-interactive-save-current-file]\tSave the current file
-\\[gnus-uu-interactive-save-current-file-silent]\tSave the current file without asking
-\twhere to put it
-\\[gnus-uu-interactive-save-all-files]\tSave all files
-\\[gnus-uu-interactive-save-original-file]\tSave the original file: If the files
-\toriginated in an archive, the archive
-\tfile is saved.
-\\[gnus-uu-interactive-rescan-directory]\tRescan the directory
-\\[gnus-uu-interactive-scan-directory]\tScan any directory
-"
- (interactive)
- (kill-all-local-variables)
- (use-local-map gnus-uu-mode-map)
- (setq mode-name "gnus-uu")
- (setq major-mode 'gnus-uu-mode)
-)
-
- (define-key gnus-uu-mode-map "\C-c\C-x" 'gnus-uu-interactive-execute)
- (define-key gnus-uu-mode-map "\C-c\C-v" 'gnus-uu-interactive-execute)
- (define-key gnus-uu-mode-map "\C-m" 'gnus-uu-interactive-execute)
- (define-key gnus-uu-mode-map "\C-c\C-c" 'gnus-uu-interactive-end)
- (define-key gnus-uu-mode-map "\C-cs"
- 'gnus-uu-interactive-save-current-file)
- (define-key gnus-uu-mode-map "\C-c\C-s"
- 'gnus-uu-interactive-save-current-file-silent)
- (define-key gnus-uu-mode-map "\C-c\C-a" 'gnus-uu-interactive-save-all-files)
- (define-key gnus-uu-mode-map "\C-c\C-o" 'gnus-uu-interactive-save-original-file)
-
-
-;; Major mode for posting encoded articles.
-
-(require 'sendmail)
-(require 'rnews)
-
-; Any function that is to be used as and encoding method will take two
-; parameters: PATH-NAME and FILE-NAME. (E.g. "/home/gaga/spiral.jpg"
-; and "spiral.jpg", respectively.) The function should return nil if
-; the encoding wasn't successful.
-(defvar gnus-uu-post-encode-method 'gnus-uu-post-encode-uuencode
- "Function used for encoding binary files.
-There are three functions supplied with gnus-uu for encoding files:
-`gnus-uu-post-encode-uuencode', which does straight uuencoding;
-`gnus-uu-post-encode-mime', which encodes with base64 and adds MIME
-headers; and `gnus-uu-post-encode-mime-uuencode', which encodes with
-uuencode and adds MIME headers.")
-
-(defvar gnus-uu-post-include-before-composing nil
- "Non-nil means that gnus-uu will ask for a file to encode before you compose the article.
-If this variable is t, you can either include an encoded file with
-\\<gnus-uu-post-reply-mode-map>\\[gnus-uu-post-insert-binary-in-article] or have one included for you when you post the article.")
-
-(defvar gnus-uu-post-length 990
- "Maximum length of an article.
-The encoded file will be split into how many articles it takes to
-post the entire file.")
-
-(defvar gnus-uu-post-threaded nil
- "Non-nil means that gnus-uu will post the encoded file in a thread.
-This may not be smart, as no other decoder I have seen are able to
-follow threads when collecting uuencoded articles. (Well, I have seen
-one package that does that - gnus-uu, but somehow, I don't think that
-counts...) Default is nil.")
-
-(defvar gnus-uu-post-separate-description t
- "Non-nil means that the description will be posted in a separate article.
-The first article will typically be numbered (0/x). If this variable
-is nil, the description the user enters will be included at the
-beginning of the first article, which will be numbered (1/x). Default
-is t.")
-
-(defconst gnus-uu-post-binary-separator "--binary follows this line--")
-(defvar gnus-uu-post-message-id nil)
-(defvar gnus-uu-post-inserted-file-name nil)
-(defvar gnus-uu-winconf-post-news nil)
-
-; The following map and mode was taken from rnewspost.el and edited
-; somewhat.
-(defvar gnus-uu-post-reply-mode-map () "Mode map used by gnus-uu-post-reply.")
-(or gnus-uu-post-reply-mode-map
- (progn
- (setq gnus-uu-post-reply-mode-map (make-keymap))
- (define-key gnus-uu-post-reply-mode-map "\C-c?" 'describe-mode)
- (define-key gnus-uu-post-reply-mode-map "\C-c\C-f\C-d"
- 'news-reply-distribution)
- (define-key gnus-uu-post-reply-mode-map "\C-c\C-f\C-k"
- 'news-reply-keywords)
- (define-key gnus-uu-post-reply-mode-map "\C-c\C-f\C-n"
- 'news-reply-newsgroups)
-
- (define-key gnus-uu-post-reply-mode-map "\C-c\C-f\C-f"
- 'news-reply-followup-to)
- (define-key gnus-uu-post-reply-mode-map "\C-c\C-f\C-s" 'mail-subject)
- (define-key gnus-uu-post-reply-mode-map "\C-c\C-f\C-a"
- 'gnus-uu-post-reply-summary)
- (define-key gnus-uu-post-reply-mode-map "\C-c\C-r"
- 'news-caesar-buffer-body)
- (define-key gnus-uu-post-reply-mode-map "\C-c\C-w" 'news-reply-signature)
- (define-key gnus-uu-post-reply-mode-map "\C-c\C-y"
- 'news-reply-yank-original)
- (define-key gnus-uu-post-reply-mode-map "\C-c\C-q"
- 'mail-fill-yanked-message)
- (define-key gnus-uu-post-reply-mode-map "\C-c\C-c"
- 'gnus-uu-post-news-inews)
- (define-key gnus-uu-post-reply-mode-map "\C-c\C-s"
- 'gnus-uu-post-news-inews)
- (define-key gnus-uu-post-reply-mode-map "\C-c\C-i"
- 'gnus-uu-post-insert-binary-in-article)
- ))
-
-; This mode was taken from rnewspost.el and modified slightly.
-(defun gnus-uu-post-reply-mode ()
- "Major mode for editing binary news to be posted on USENET.
-First-time posters are asked to please read the articles in newsgroup:
- news.announce.newusers .
-
-Like news-reply-mode, which is like Text Mode, but with these
-additional commands:
-
-\\<gnus-uu-post-reply-mode-map>\\[gnus-uu-post-news-inews] post the message.
-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).
-\\[gnus-uu-post-insert-binary-in-article] encode and include a file in this article.
-
-This mode is almost identical to news-reply-mode, but has some
-additional commands for treating encoded binary articles. In
-particular, \\[gnus-uu-post-news-inews] will ask for a file to include, if
-one hasn't been included already. It will post, first, the message
-composed, and then it will post as many additional articles it takes
-to post the entire encoded files.
-
- Relevant Variables
-
- `gnus-uu-post-encode-method'
- There are three functions supplied with gnus-uu for encoding files:
- `gnus-uu-post-encode-uuencode', which does straight uuencoding;
- `gnus-uu-post-encode-mime', which encodes with base64 and adds MIME
- headers; and `gnus-uu-post-encode-mime-uuencode', which encodes with
- uuencode and adds MIME headers.
-
- `gnus-uu-post-include-before-composing'
- Non-nil means that gnus-uu will ask for a file to encode before you
- compose the article. If this variable is t, you can either include
- an encoded file with `C-c C-i' or have one included for you when you
- post the article.
-
- `gnus-uu-post-length'
- Maximum length of an article. The encoded file will be split into how
- many articles it takes to post the entire file.
-
- `gnus-uu-post-separate-description'
- Non-nil means that the description will be posted in a separate
- article. The first article will typically be numbered (0/x). If
- this variable is nil, the description the user enters will be
- included at the beginning of the first article, which will be
- numbered (1/x). Default is t.
-
- `gnus-uu-post-threaded'
- Non-nil means that gnus-uu will post the encoded file in a thread.
- This may not be smart, as no other decoder I have seen are able to
- follow threads when collecting uuencoded articles. (Well, I have seen
- one package that does that - gnus-uu, but somehow, I don't think that
- counts...) Default is nil.
-"
- (interactive)
- ;; require...
- (or (fboundp 'mail-setup) (load "sendmail"))
- (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 gnus-uu-post-reply-mode-map)
- (setq local-abbrev-table text-mode-abbrev-table)
- (setq major-mode 'gnus-uu-post-reply-mode)
- (setq mode-name "Gnus UU News")
- (make-local-variable 'paragraph-separate)
- (make-local-variable 'paragraph-start)
- (setq paragraph-start (concat mail-header-separator "$\\|"
- paragraph-start))
- (setq paragraph-separate (concat mail-header-separator "$\\|"
- paragraph-separate))
- (run-hooks 'text-mode-hook 'gnus-uu-post-reply-mode-hook))
-
-(defun gnus-uu-post-news ()
- "Compose an article and post an encoded file."
- (interactive)
- (setq gnus-uu-post-inserted-file-name nil)
- (setq gnus-uu-winconf-post-news (current-window-configuration))
- (let (news-reply-mode)
- (fset 'news-reply-mode 'gnus-uu-post-reply-mode)
- (gnus-summary-post-news)
- (if gnus-uu-post-include-before-composing
- (save-excursion (setq gnus-uu-post-inserted-file-name
- (gnus-uu-post-insert-binary))))))
-
-(defun gnus-uu-post-insert-binary-in-article ()
- "Inserts an encoded file in the buffer.
-The user will be asked for a file name."
- (interactive)
- (if (not (eq (current-buffer) (get-buffer gnus-post-news-buffer)))
- (error "Not in post-news buffer"))
- (save-excursion
- (setq gnus-uu-post-inserted-file-name (gnus-uu-post-insert-binary))))
-
-; Encodes with uuencode and substitutes all spaces with backticks.
-(defun gnus-uu-post-encode-uuencode (path file-name)
- (if (gnus-uu-post-encode-file "uuencode" path file-name)
- (progn
- (goto-char 1)
- (forward-line 1)
- (while (re-search-forward " " nil t)
- (replace-match "`"))
- t)))
-
-; Encodes with uuencode and adds MIME headers.
-(defun gnus-uu-post-encode-mime-uuencode (path file-name)
- (if (gnus-uu-post-encode-uuencode path file-name)
- (progn
- (gnus-uu-post-make-mime file-name "x-uue")
- t)))
-
-; Encodes with base64 and adds MIME headers
-(defun gnus-uu-post-encode-mime (path file-name)
- (if (gnus-uu-post-encode-file "mmencode" path file-name)
- (progn
- (gnus-uu-post-make-mime file-name "base64")
- t)))
-
-; Adds MIME headers.
-(defun gnus-uu-post-make-mime (file-name encoding)
- (goto-char 1)
- (insert (format "Content-Type: %s; name=\"%s\"\n"
- (gnus-uu-choose-action file-name gnus-uu-ext-to-mime-list)
- file-name))
- (insert (format "Content-Transfer-Encoding: %s\n\n" encoding))
- (save-restriction
- (set-buffer gnus-post-news-buffer)
- (goto-char 1)
- (re-search-forward mail-header-separator)
- (beginning-of-line)
- (forward-line -1)
- (narrow-to-region 1 (point))
- (or (mail-fetch-field "mime-version")
- (progn
- (widen)
- (insert "MIME-Version: 1.0\n")))
- (widen)))
-
-; Encodes a file PATH with COMMAND, leaving the result in the
-; current buffer.
-(defun gnus-uu-post-encode-file (command path file-name)
- (= 0 (call-process "sh" nil t nil "-c"
- (format "%s %s %s" command path file-name))))
-
-(defun gnus-uu-post-news-inews ()
- "Posts the composed news article and encoded file.
-If no file has been included, the user will be asked for a file."
- (interactive)
- (if (not (eq (current-buffer) (get-buffer gnus-post-news-buffer)))
- (error "Not in post news buffer"))
-
- (let (file-name)
-
- (if gnus-uu-post-inserted-file-name
- (setq file-name gnus-uu-post-inserted-file-name)
- (setq file-name (gnus-uu-post-insert-binary)))
-
- (if gnus-uu-post-threaded
- (let ((gnus-required-headers
- (if (memq 'Message-ID gnus-required-headers)
- gnus-required-headers
- (cons 'Message-ID gnus-required-headers)))
- gnus-inews-article-hook elem)
-
- (setq gnus-inews-article-hook (if (listp gnus-inews-article-hook)
- gnus-inews-article-hook
- (list gnus-inews-article-hook)))
- (setq gnus-inews-article-hook
- (cons
- '(lambda ()
- (save-excursion
- (goto-char 1)
- (if (re-search-forward "^Message-ID: \\(.*\\)$" nil t)
- (setq gnus-uu-post-message-id
- (buffer-substring
- (match-beginning 1) (match-end 1)))
- (setq gnus-uu-post-message-id nil))))
- gnus-inews-article-hook))
- (gnus-uu-post-encoded file-name t))
- (gnus-uu-post-encoded file-name nil)))
- (setq gnus-uu-post-inserted-file-name nil)
- (and gnus-uu-winconf-post-news
- (set-window-configuration gnus-uu-winconf-post-news)))
-
-; Asks for a file to encode, encodes it and inserts the result in
-; the current buffer. Returns the file name the user gave.
-(defun gnus-uu-post-insert-binary ()
- (let ((uuencode-buffer-name "*uuencode buffer*")
- file-path post-buf uubuf file-name)
-
- (setq file-path (read-file-name
- "What file do you want to encode? "))
- (if (not (file-exists-p file-path))
- (error "%s: No such file" file-path))
-
- (goto-char (point-max))
- (insert (format "\n%s\n" gnus-uu-post-binary-separator))
-
- (if (string-match "^~/" file-path)
- (setq file-path (concat "$HOME" (substring file-path 1))))
- (if (string-match "/[^/]*$" file-path)
- (setq file-name (substring file-path (1+ (match-beginning 0))))
- (setq file-name file-path))
-
- (unwind-protect
- (if (save-excursion
- (set-buffer (setq uubuf
- (get-buffer-create uuencode-buffer-name)))
- (erase-buffer)
- (funcall gnus-uu-post-encode-method file-path file-name))
- (insert-buffer uubuf)
- (error "Encoding unsuccessful"))
- (kill-buffer uubuf))
- file-name))
-
-; Posts the article and all of the encoded file.
-(defun gnus-uu-post-encoded (file-name &optional threaded)
- (let ((send-buffer-name "*uuencode send buffer*")
- (encoded-buffer-name "*encoded buffer*")
- (top-string "[ cut here %s (%s %d/%d) %s gnus-uu ]")
- (separator (concat mail-header-separator "\n\n"))
- file uubuf length parts header i end beg
- beg-line minlen buf post-buf whole-len beg-binary end-binary)
-
- (setq post-buf (current-buffer))
-
- (goto-char 1)
- (if (not (re-search-forward
- (if gnus-uu-post-separate-description
- gnus-uu-post-binary-separator
- mail-header-separator) nil t))
- (error "Internal error: No binary/header separator"))
- (beginning-of-line)
- (forward-line 1)
- (setq beg-binary (point))
- (setq end-binary (point-max))
-
- (save-excursion
- (set-buffer (setq uubuf (get-buffer-create encoded-buffer-name)))
- (erase-buffer)
- (insert-buffer-substring post-buf beg-binary end-binary)
- (goto-char 1)
- (setq length (count-lines 1 (point-max)))
- (setq parts (/ length gnus-uu-post-length))
- (if (not (< (% length gnus-uu-post-length) 4))
- (setq parts (1+ parts))))
-
- (if gnus-uu-post-separate-description
- (forward-line -1))
- (kill-region (point) (point-max))
-
- (goto-char 1)
- (search-forward mail-header-separator nil t)
- (beginning-of-line)
- (setq header (buffer-substring 1 (point)))
-
- (goto-char 1)
- (if (not gnus-uu-post-separate-description)
- ()
- (if (and (not threaded) (re-search-forward "^Subject: " nil t))
- (progn
- (end-of-line)
- (insert (format " (0/%d)" parts))))
- (gnus-inews-news))
-
- (save-excursion
- (setq i 1)
- (setq beg 1)
- (while (not (> i parts))
- (set-buffer (get-buffer-create send-buffer-name))
- (erase-buffer)
- (insert header)
- (if (and threaded gnus-uu-post-message-id)
- (insert (format "References: %s\n" gnus-uu-post-message-id)))
- (insert separator)
- (setq whole-len
- (- 62 (length (format top-string "" file-name i parts ""))))
- (if (> 1 (setq minlen (/ whole-len 2)))
- (setq minlen 1))
- (setq
- beg-line
- (format top-string
- (make-string minlen ?-)
- file-name i parts
- (make-string
- (if (= 0 (% whole-len 2)) (1- minlen) minlen) ?-)))
-
- (goto-char 1)
- (if (not (re-search-forward "^Subject: " nil t))
- ()
- (if (not threaded)
- (progn
- (end-of-line)
- (insert (format " (%d/%d)" i parts)))
- (if (or (and (= i 2) gnus-uu-post-separate-description)
- (and (= i 1) (not gnus-uu-post-separate-description)))
- (replace-match "Subject: Re: "))))
-
- (goto-char (point-max))
- (save-excursion
- (set-buffer uubuf)
- (goto-char beg)
- (if (= i parts)
- (goto-char (point-max))
- (forward-line gnus-uu-post-length))
- (if (and (= (1+ i) parts) (< (count-lines (point) (point-max)) 4))
- (forward-line -4))
- (setq end (point)))
- (insert-buffer-substring uubuf beg end)
- (insert beg-line)
- (insert "\n")
- (setq beg end)
- (setq i (1+ i))
- (goto-char 1)
- (re-search-forward mail-header-separator nil t)
- (beginning-of-line)
- (forward-line 2)
- (if (re-search-forward gnus-uu-post-binary-separator nil t)
- (progn
- (replace-match "")
- (forward-line 1)))
- (insert beg-line)
- (insert "\n")
- (gnus-inews-news)))
-
- (and (setq buf (get-buffer send-buffer-name))
- (kill-buffer buf))
- (and (setq buf (get-buffer encoded-buffer-name))
- (kill-buffer buf))
-
- (if (not gnus-uu-post-separate-description)
- (progn
- (set-buffer-modified-p nil)
- (and (fboundp 'bury-buffer) (bury-buffer))))))
-
-(provide 'gnus-uu)
-
-;; gnus-uu.el ends here
diff --git a/lisp/=gnus.el b/lisp/=gnus.el
deleted file mode 100644
index 0a410e367d7..00000000000
--- a/lisp/=gnus.el
+++ /dev/null
@@ -1,7243 +0,0 @@
-;;; gnus.el --- NNTP-based News Reader for GNU Emacs
-;; Copyright (C) 1987,88,89,90,93,94,95 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; How to Install GNUS:
-;; (0) First of all, remove GNUS related OLD *.elc files (at least
-;; nntp.elc).
-;; (1) Unshar gnus.el, gnuspost.el, gnusmail.el, gnusmisc.el, and
-;; nntp.el.
-;; (2) byte-compile-file nntp.el, gnus.el, gnuspost.el, gnusmail.el,
-;; and gnusmisc.el. If you have a local news spool,
-;; byte-compile-file nnspool.el, too.
-;; (3) Define three environment variables in .login file as follows:
-;;
-;; setenv NNTPSERVER flab
-;; setenv DOMAINNAME "stars.flab.Fujitsu.CO.JP"
-;; setenv ORGANIZATION "Fujitsu Laboratories Ltd., Kawasaki, Japan."
-;;
-;; Or instead, define lisp variables in your .emacs, site-init.el,
-;; or default.el as follows:
-;;
-;; (setq gnus-nntp-server "flab")
-;; (setq gnus-local-domain "stars.flab.Fujitsu.CO.JP")
-;; (setq gnus-local-organization "Fujitsu Laboratories Ltd., ...")
-;;
-;; If the function (system-name) returns the full internet name,
-;; you don't have to define the domain.
-;;
-;; (4) You may have to define NNTP service name as number 119.
-;;
-;; (setq gnus-nntp-service 119)
-;;
-;; Or, if you'd like to use a local news spool directly in stead
-;; of NNTP, set the variable to nil as follows:
-;;
-;; (setq gnus-nntp-service nil)
-;;
-;; (5) If you'd like to use the GENERICFROM feature like the Bnews,
-;; define the variable as follows:
-;;
-;; (setq gnus-use-generic-from t)
-;;
-;; (6) Define autoload entries in .emacs file as follows:
-;;
-;; (autoload 'gnus "gnus" "Read network news." t)
-;; (autoload 'gnus-post-news "gnuspost" "Post a news." t)
-;;
-;; (7) Read nntp.el if you have problems with NNTP or kanji handling.
-;;
-;; (8) Install mhspool.el, tcp.el, and tcp.c if it is necessary.
-;;
-;; mhspool.el is a package for reading articles or mail in your
-;; private directory using GNUS.
-;;
-;; tcp.el and tcp.c are necessary if and only if your Emacs does
-;; not have the function `open-network-stream' which is used for
-;; communicating with NNTP server inside Emacs.
-;;
-;; (9) Install an Info file generated from the texinfo manual gnus.texinfo.
-;;
-;; If you are not allowed to create the Info file to the standard
-;; Info-directory, create it in your private directory and set the
-;; variable gnus-info-directory to that directory.
-;;
-;; For getting more information about GNUS, consult USENET newsgorup
-;; gnu.emacs.gnus.
-
-;; TO DO:
-;; (1) Incremental update of active info.
-;; (2) Asynchronous transmission of large messages.
-
-;;; Code:
-
-(require 'nntp)
-(require 'mail-utils)
-(require 'timezone)
-
-(defvar gnus-default-nntp-server nil
- "*Specify default NNTP server.
-This variable should be defined in `site-init.el'.")
-
-(defvar gnus-nntp-server (or (getenv "NNTPSERVER") gnus-default-nntp-server)
- "*The name of the host running NNTP server.
-If it is a string starting with a colon, as in as `:DIRECTORY', then the
-directory ~/DIRECTORY is used as the news spool.
-This variable is initialized from the NNTPSERVER environment variable
-or from `gnus-default-nntp-server'.")
-
-(defvar gnus-nntp-service "nntp"
- "*NNTP service name (\"nntp\" or 119).
-Go to a local news spool if its value is nil.")
-
-(defvar gnus-startup-file "~/.newsrc"
- "*Your `.newsrc' file. Use `.newsrc-SERVER' instead if exists.")
-
-(defvar gnus-signature-file "~/.signature"
- "*Your `.signature' file. Use `.signature-DISTRIBUTION' instead if exists.")
-
-(defvar gnus-use-cross-reference t
- "*Specifies what to do with cross references (Xref: field).
-If nil, ignore cross references. If t, mark articles as read in
-subscribed newsgroups. Otherwise, if not nil nor t, mark articles as
-read in all newsgroups.")
-
-(defvar gnus-use-followup-to t
- "*Specifies what to do with Followup-To: field.
-If nil, ignore `Followup-to:' field. If t, use its value except for
-`poster'. Otherwise, if not nil nor t, always use its value.")
-
-(defvar gnus-large-newsgroup 50
- "*The number of articles which indicates a large newsgroup.
-If the number of articles in a newsgroup is greater than the value,
-confirmation is required for selecting the newsgroup.")
-
-(defvar gnus-author-copy (getenv "AUTHORCOPY")
- "*File name saving a copy of an article posted using FCC: field.
-Initialized from the AUTHORCOPY environment variable.
-
-Articles are saved using a function specified by the the variable
-`gnus-author-copy-saver' (`rmail-output' is default) if a file name is
-given. Instead, if the first character of the name is `|', the
-contents of the article is piped out to the named program. It is
-possible to save an article in an MH folder as follows:
-
-\(setq gnus-author-copy \"|/usr/local/lib/mh/rcvstore +Article\")")
-
-(defvar gnus-author-copy-saver (function rmail-output)
- "*A function called with a file name to save an author copy to.
-The default function is `rmail-output' which saves in inbox format.")
-
-(defvar gnus-use-long-file-name
- (not (memq system-type '(usg-unix-v xenix)))
- "*Non-nil means that a newsgroup name is used as a default file name
-to save articles to. If it's nil, the directory form of a newsgroup is
-used instead.")
-
-(defvar gnus-article-save-directory (getenv "SAVEDIR")
- "*A directory name to save articles to (default is `~/News').
-Initialized from the SAVEDIR environment variable.")
-
-(defvar gnus-kill-files-directory (getenv "SAVEDIR")
- "*A directory name to save kill files to (default to ~/News).
-Initialized from the SAVEDIR environment variable.")
-
-(defvar gnus-default-article-saver (function gnus-summary-save-in-rmail)
- "*A function to save articles in your favorite format.
-The function must be interactively callable (in other words, it must
-be an Emacs command).
-
-GNUS provides the following functions:
- gnus-summary-save-in-rmail (in Rmail format)
- gnus-summary-save-in-mail (in Unix mail format)
- gnus-summary-save-in-folder (in an MH folder)
- gnus-summary-save-in-file (in article format).")
-
-(defvar gnus-rmail-save-name (function gnus-plain-save-name)
- "*A function generating a file name to save articles in Rmail format.
-The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE.")
-
-(defvar gnus-mail-save-name (function gnus-plain-save-name)
- "*A function generating a file name to save articles in Unix mail format.
-The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE.")
-
-(defvar gnus-folder-save-name (function gnus-folder-save-name)
- "*A function generating a file name to save articles in MH folder.
-The function is called with NEWSGROUP, HEADERS, and optional LAST-FOLDER.")
-
-(defvar gnus-file-save-name (function gnus-numeric-save-name)
- "*A function generating a file name to save articles in article format.
-The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE.")
-
-(defvar gnus-kill-file-name "KILL"
- "*File name of a KILL file.")
-
-(defvar gnus-novice-user t
- "*Non-nil means that you are a novice to USENET.
-If non-nil, verbose messages may be displayed
-or your confirmations may be required.")
-
-(defvar gnus-interactive-catchup t
- "*Require your confirmation when catching up a newsgroup if non-nil.")
-
-(defvar gnus-interactive-post t
- "*Newsgroup, subject, and distribution will be asked for if non-nil.")
-
-(defvar gnus-interactive-exit t
- "*Require your confirmation when exiting GNUS if non-nil.")
-
-(defvar gnus-user-login-name nil
- "*The login name of the user.
-Got from the function `user-login-name' if undefined.")
-
-(defvar gnus-user-full-name nil
- "*The full name of the user.
-Got from the NAME environment variable if undefined.")
-
-(defvar gnus-show-mime nil
- "*Show MIME message if non-nil.")
-
-(defvar gnus-show-threads t
- "*Show conversation threads in Summary Mode if non-nil.")
-
-(defvar gnus-thread-hide-subject t
- "*Non-nil means hide subjects for thread subtrees.")
-
-(defvar gnus-thread-hide-subtree nil
- "*Non-nil means hide thread subtrees initially.
-If non-nil, you have to run the command `gnus-summary-show-thread' by
-hand or by using `gnus-select-article-hook' to show hidden threads.")
-
-(defvar gnus-thread-hide-killed t
- "*Non-nil means hide killed thread subtrees automatically.")
-
-(defvar gnus-thread-ignore-subject nil
- "*Don't take care of subject differences, but only references if non-nil.
-If it is non-nil, some commands work with subjects do not work properly.")
-
-(defvar gnus-thread-indent-level 4
- "*Indentation of thread subtrees.")
-
-(defvar gnus-ignored-newsgroups "^to\\..*$"
- "*A regexp to match uninteresting newsgroups in the active file.
-Any lines in the active file matching this regular expression are
-removed from the newsgroup list before anything else is done to it,
-thus making them effectively invisible.")
-
-(defvar gnus-ignored-headers
- "^Path:\\|^Posting-Version:\\|^Article-I.D.:\\|^Expires:\\|^Date-Received:\\|^References:\\|^Control:\\|^Xref:\\|^Lines:\\|^Posted:\\|^Relay-Version:\\|^Message-ID:\\|^Nf-ID:\\|^Nf-From:\\|^Approved:\\|^Sender:"
- "*Header fields not worth displaying.
-Ordinarily GNUS excludes these when displaying an article.
-If you want to see them, ask to see the message with \"the full header\"
-\(also known as \"the original header\").")
-
-(defvar gnus-required-headers
- '(From Date Newsgroups Subject Message-ID Path Organization Distribution)
- "*All required fields for articles you post.
-RFC977 and RFC1036 require From, Date, Newsgroups, Subject, Message-ID
-and Path fields. Organization, Distribution and Lines are optional.
-If you want GNUS not to insert some field, remove it from this list.")
-
-(defvar gnus-show-all-headers nil
- "*Show all headers of an article if non-nil.")
-
-(defvar gnus-save-all-headers t
- "*Save all headers of an article if non-nil.")
-
-(defvar gnus-optional-headers (function gnus-optional-lines-and-from)
- "*A function generating a optional string displayed in GNUS Summary
-mode buffer. The function is called with an article HEADER. The
-result must be a string excluding `[' and `]'.")
-
-(defvar gnus-auto-extend-newsgroup t
- "*Extend visible articles to forward and backward if non-nil.")
-
-(defvar gnus-auto-select-first t
- "*Select the first unread article automagically if non-nil.
-If you want to prevent automatic selection of the first unread article
-in some newsgroups, set the variable to nil in `gnus-select-group-hook'
-or `gnus-apply-kill-hook'.")
-
-(defvar gnus-auto-select-next t
- "*Select the next newsgroup automagically if non-nil.
-If the value is t and the next newsgroup is empty, GNUS will exit
-Summary mode and go back to Group mode. If the value is neither nil
-nor t, GNUS will select the following unread newsgroup. Especially, if
-the value is the symbol `quietly', the next unread newsgroup will be
-selected without any confirmations.")
-
-(defvar gnus-auto-select-same nil
- "*Select the next article with the same subject automagically if non-nil.")
-
-(defvar gnus-auto-center-summary t
- "*Always center the current summary in GNUS Summary window if non-nil.")
-
-(defvar gnus-auto-mail-to-author nil
- "*Insert `To: author' of the article when following up if non-nil.
-Mail is sent using the function specified by the variable
-`gnus-mail-send-method'.")
-
-(defvar gnus-break-pages t
- "*Break an article into pages if non-nil.
-Page delimiter is specified by the variable `gnus-page-delimiter'.")
-
-(defvar gnus-page-delimiter "^\^L"
- "*Regexp describing line-beginnings that separate pages of news article.")
-
-(defvar gnus-digest-show-summary t
- "*Show a summary of undigestified messages if non-nil.")
-
-(defvar gnus-digest-separator "^Subject:[ \t]"
- "*Regexp that separates messages in a digest article.")
-
-(defvar gnus-use-full-window t
- "*Non-nil means to take up the entire screen of Emacs.")
-
-(defvar gnus-window-configuration
- '((summary (0 1 0))
- (newsgroups (1 0 0))
- (article (0 3 10)))
- "*Specify window configurations for each action.
-The format of the variable is a list of (ACTION (G S A)), where G, S,
-and A are the relative height of Group, Summary, and Article windows,
-respectively. ACTION is `summary', `newsgroups', or `article'.")
-
-(defvar gnus-show-mime-method (function metamail-buffer)
- "*Function to process a MIME message.
-The function is expected to process current buffer as a MIME message.")
-
-(defvar gnus-mail-reply-method
- (function gnus-mail-reply-using-mail)
- "*Function to compose reply mail.
-The function `gnus-mail-reply-using-mail' uses usual sendmail mail
-program. The function `gnus-mail-reply-using-mhe' uses the MH-E mail
-program. You can use yet another program by customizing this variable.")
-
-(defvar gnus-mail-forward-method
- (function gnus-mail-forward-using-mail)
- "*Function to forward current message to another user.
-The function `gnus-mail-reply-using-mail' uses usual sendmail mail
-program. You can use yet another program by customizing this variable.")
-
-(defvar gnus-mail-other-window-method
- (function gnus-mail-other-window-using-mail)
- "*Function to compose mail in other window.
-The function `gnus-mail-other-window-using-mail' uses the usual sendmail
-mail program. The function `gnus-mail-other-window-using-mhe' uses the MH-E
-mail program. You can use yet another program by customizing this variable.")
-
-(defvar gnus-mail-send-method send-mail-function
- "*Function to mail a message too which is being posted as an article.
-The message must have To: or Cc: field. The default is copied from
-the variable `send-mail-function'.")
-
-(defvar gnus-subscribe-newsgroup-method
- (function gnus-subscribe-alphabetically)
- "*Function called with a newsgroup name when new newsgroup is found.
-The function `gnus-subscribe-randomly' inserts a new newsgroup a the
-beginning of newsgroups. The function `gnus-subscribe-alphabetically'
-inserts it in strict alphabetic order. The function
-`gnus-subscribe-hierarchically' inserts it in hierarchical newsgroup
-order. The function `gnus-subscribe-interactively' asks for your decision.")
-
-(defvar gnus-group-mode-hook nil
- "*A hook for GNUS Group Mode.")
-
-(defvar gnus-summary-mode-hook nil
- "*A hook for GNUS Summary Mode.")
-
-(defvar gnus-article-mode-hook nil
- "*A hook for GNUS Article Mode.")
-
-(defvar gnus-kill-file-mode-hook nil
- "*A hook for GNUS KILL File Mode.")
-
-(defvar gnus-open-server-hook nil
- "*A hook called just before opening connection to news server.")
-
-(defvar gnus-startup-hook nil
- "*A hook called at start up time.
-This hook is called after GNUS is connected to the NNTP server. So, it
-is possible to change the behavior of GNUS according to the selected
-NNTP server.")
-
-(defvar gnus-group-prepare-hook nil
- "*A hook called after newsgroup list is created in the Newsgroup buffer.
-If you want to modify the Newsgroup buffer, you can use this hook.")
-
-(defvar gnus-summary-prepare-hook nil
- "*A hook called after summary list is created in the Summary buffer.
-If you want to modify the Summary buffer, you can use this hook.")
-
-(defvar gnus-article-prepare-hook nil
- "*A hook called after an article is prepared in the Article buffer.
-If you want to run a special decoding program like nkf, use this hook.")
-
-(defvar gnus-select-group-hook nil
- "*A hook called when a newsgroup is selected.
-If you want to sort Summary buffer by date and then by subject, you
-can use the following hook:
-
-\(add-hook 'gnus-select-group-hook
- (function
- (lambda ()
- ;; First of all, sort by date.
- (gnus-keysort-headers
- (function string-lessp)
- (function
- (lambda (a)
- (gnus-sortable-date (gnus-header-date a)))))
- ;; Then sort by subject string ignoring `Re:'.
- ;; If case-fold-search is non-nil, case of letters is ignored.
- (gnus-keysort-headers
- (function string-lessp)
- (function
- (lambda (a)
- (if case-fold-search
- (downcase (gnus-simplify-subject (gnus-header-subject a) t))
- (gnus-simplify-subject (gnus-header-subject a) t)))))
- )))
-
-If you'd like to simplify subjects like the
-`gnus-summary-next-same-subject' command does, you can use the
-following hook:
-
-\(add-hook 'gnus-select-group-hook
- (function
- (lambda ()
- (mapcar (function
- (lambda (header)
- (nntp-set-header-subject
- header
- (gnus-simplify-subject
- (gnus-header-subject header) 're-only))))
- gnus-newsgroup-headers))))
-
-In some newsgroups author name is meaningless. It is possible to
-prevent listing author names in GNUS Summary buffer as follows:
-
-\(add-hook 'gnus-select-group-hook
- (function
- (lambda ()
- (cond ((string-equal \"comp.sources.unix\" gnus-newsgroup-name)
- (setq gnus-optional-headers
- (function gnus-optional-lines)))
- (t
- (setq gnus-optional-headers
- (function gnus-optional-lines-and-from)))))))")
-
-(defvar gnus-select-article-hook
- '(gnus-summary-show-thread)
- "*A hook called when an article is selected.
-The default hook shows conversation thread subtrees of the selected
-article automatically using `gnus-summary-show-thread'.
-
-If you'd like to run Rmail on a digest article automagically, you can
-use the following hook:
-
-\(add-hook 'gnus-select-article-hook
- (function
- (lambda ()
- (cond ((string-equal \"comp.sys.sun\" gnus-newsgroup-name)
- (gnus-summary-rmail-digest))
- ((and (string-equal \"comp.text\" gnus-newsgroup-name)
- (string-match \"^TeXhax Digest\"
- (gnus-header-subject gnus-current-headers)))
- (gnus-summary-rmail-digest)
- ))))
- t)")
-
-(defvar gnus-select-digest-hook
- (list
- (function
- (lambda ()
- ;; Reply-To: is required by `undigestify-rmail-message'.
- (or (mail-position-on-field "Reply-to" t)
- (progn
- (mail-position-on-field "Reply-to")
- (insert (gnus-fetch-field "From")))))))
- "*A hook called when reading digest messages using Rmail.
-This hook can be used to modify incomplete digest articles as follows
-\(this is the default):
-
-\(add-hook 'gnus-select-digest-hook
- (function
- (lambda ()
- ;; Reply-To: is required by `undigestify-rmail-message'.
- (or (mail-position-on-field \"Reply-to\" t)
- (progn
- (mail-position-on-field \"Reply-to\")
- (insert (gnus-fetch-field \"From\")))))))")
-
-(defvar gnus-rmail-digest-hook nil
- "*A hook called when reading digest messages using Rmail.
-This hook is intended to customize Rmail mode for reading digest articles.")
-
-(defvar gnus-apply-kill-hook '(gnus-apply-kill-file)
- "*A hook called when a newsgroup is selected and summary list is prepared.
-This hook is intended to apply a KILL file to the selected newsgroup.
-The function `gnus-apply-kill-file' is called by default.
-
-Since a general KILL file is too heavy to use only for a few
-newsgroups, I recommend you to use a lighter hook function. For
-example, if you'd like to apply a KILL file to articles which contains
-a string `rmgroup' in subject in newsgroup `control', you can use the
-following hook:
-
-\(setq gnus-apply-kill-hook
- (list
- (function
- (lambda ()
- (cond ((string-match \"control\" gnus-newsgroup-name)
- (gnus-kill \"Subject\" \"rmgroup\")
- (gnus-expunge \"X\")))))))")
-
-(defvar gnus-mark-article-hook
- (list
- (function
- (lambda ()
- (or (memq gnus-current-article gnus-newsgroup-marked)
- (gnus-summary-mark-as-read gnus-current-article))
- (gnus-summary-set-current-mark "+"))))
- "*A hook called when an article is selected at the first time.
-The hook is intended to mark an article as read (or unread)
-automatically when it is selected.
-
-If you'd like to mark as unread (-) instead, use the following hook:
-
-\(setq gnus-mark-article-hook
- (list
- (function
- (lambda ()
- (gnus-summary-mark-as-unread gnus-current-article)
- (gnus-summary-set-current-mark \"+\")))))")
-
-(defvar gnus-prepare-article-hook (list (function gnus-inews-insert-signature))
- "*A hook called after preparing body, but before preparing header fields.
-The default hook (`gnus-inews-insert-signature') inserts a signature
-file specified by the variable `gnus-signature-file'.")
-
-(defvar gnus-inews-article-hook (list (function gnus-inews-do-fcc))
- "*A hook called before finally posting an article.
-The default hook (`gnus-inews-do-fcc') does FCC processing (save article
-to a file).")
-
-(defvar gnus-exit-group-hook nil
- "*A hook called when exiting (not quitting) Summary mode.
-If your machine is so slow that exiting from Summary mode takes very
-long time, set the variable `gnus-use-cross-reference' to nil. This
-inhibits marking articles as read using cross-reference information.")
-
-(defvar gnus-suspend-gnus-hook nil
- "*A hook called when suspending (not exiting) GNUS.")
-
-(defvar gnus-exit-gnus-hook nil
- "*A hook called when exiting (not suspending) GNUS.")
-
-(defvar gnus-save-newsrc-hook nil
- "*A hook called when saving the newsrc file.
-This hook is called before saving the `.newsrc' file.")
-
-
-;; Site dependent variables. You have to define these variables in
-;; site-init.el, default.el or your .emacs.
-
-(defvar gnus-local-timezone nil
- "*Local time zone.
-This value is used only if `current-time-zone' does not work in your Emacs.
-It specifies the GMT offset, i.e. a decimal integer
-of the form +-HHMM giving the hours and minutes ahead of (i.e. east of) GMT.
-For example, +0900 should be used in Japan, since it is 9 hours ahead of GMT.
-
-For backwards compatibility, it may also be a string like \"JST\",
-but strings are obsolescent: you should use numeric offsets instead.")
-
-(defvar gnus-local-domain nil
- "*Local domain name without a host name like: \"stars.flab.Fujitsu.CO.JP\"
-The `DOMAINNAME' environment variable is used instead if defined. If
-the function (system-name) returns the full internet name, there is no
-need to define the name.")
-
-(defvar gnus-local-organization nil
- "*Local organization like: \"Fujitsu Laboratories Ltd., Kawasaki, Japan.\"
-The `ORGANIZATION' environment variable is used instead if defined.")
-
-(defvar gnus-local-distributions '("local" "world")
- "*List of distributions.
-The first element in the list is used as default. If distributions
-file is available, its content is also used.")
-
-(defvar gnus-use-generic-from nil
- "*If nil, prepend local host name to the defined domain in the From:
-field; if a string, use this; if non-nil, strip off the local host name.")
-
-(defvar gnus-use-generic-path nil
- "*If nil, use the NNTP server name in the Path: field; if stringp,
-use this; if non-nil, use no host name (user name only)")
-
-(defvar gnus-newsgroups-regex "^\\([^ \t\n]+\\)[ \t]+\\(.*\\)$"
- "Regex to retrieve the group name and the group description from
-the output of the newsgroups listing.
-
-If you have ^M at the end of lines try \"^\\([^ \t\n]+\\)[ \t]+\\([^\r]+\\)[\r]*$\"")
-
-(defvar gnus-newsgroups-display t
- "*display the newsgroup description in *Newsgroup* buffer if not nil")
-
-(defvar gnus-newsgroups-alist nil
- "alist (groupname . description)")
-
-(defvar gnus-newsgroups-hashtb nil
- "hashtable of gnus-newsgroups-alist")
-
-(defvar gnus-newsgroups-showall nil
- "non nil if we display all the groups")
-
-
-;; Internal variables.
-
-(defconst gnus-version "GNUS 4.1"
- "Version numbers of this version of GNUS.")
-
-(defconst gnus-emacs-version
- (progn
- (string-match "[0-9]*" emacs-version)
- (string-to-int (substring emacs-version
- (match-beginning 0) (match-end 0))))
- "Major version number of this emacs.")
-
-(defvar gnus-info-nodes
- '((gnus-group-mode "(gnus)Newsgroup Commands")
- (gnus-summary-mode "(gnus)Summary Commands")
- (gnus-article-mode "(gnus)Article Commands")
- (gnus-kill-file-mode "(gnus)Kill File")
- (gnus-browse-killed-mode "(gnus)Maintaining Subscriptions"))
- "Assoc list of major modes and related Info nodes.")
-
-;; Alist syntax is different from that of 3.14.3.
-(defvar gnus-access-methods
- '((nntp
- (gnus-retrieve-headers nntp-retrieve-headers)
- (gnus-open-server nntp-open-server)
- (gnus-close-server nntp-close-server)
- (gnus-server-opened nntp-server-opened)
- (gnus-status-message nntp-status-message)
- (gnus-request-article nntp-request-article)
- (gnus-request-group nntp-request-group)
- (gnus-request-list nntp-request-list)
- (gnus-request-list-newsgroups nntp-request-list-newsgroups)
- (gnus-request-list-distributions nntp-request-list-distributions)
- (gnus-request-post nntp-request-post))
- (nnspool
- (gnus-retrieve-headers nnspool-retrieve-headers)
- (gnus-open-server nnspool-open-server)
- (gnus-close-server nnspool-close-server)
- (gnus-server-opened nnspool-server-opened)
- (gnus-status-message nnspool-status-message)
- (gnus-request-article nnspool-request-article)
- (gnus-request-group nnspool-request-group)
- (gnus-request-list nnspool-request-list)
- (gnus-request-list-newsgroups nnspool-request-list-newsgroups)
- (gnus-request-list-distributions nnspool-request-list-distributions)
- (gnus-request-post nnspool-request-post))
- (mhspool
- (gnus-retrieve-headers mhspool-retrieve-headers)
- (gnus-open-server mhspool-open-server)
- (gnus-close-server mhspool-close-server)
- (gnus-server-opened mhspool-server-opened)
- (gnus-status-message mhspool-status-message)
- (gnus-request-article mhspool-request-article)
- (gnus-request-group mhspool-request-group)
- (gnus-request-list mhspool-request-list)
- (gnus-request-list-newsgroups mhspool-request-list-newsgroups)
- (gnus-request-list-distributions mhspool-request-list-distributions)
- (gnus-request-post mhspool-request-post)))
- "Access method for NNTP, nnspool, and mhspool.")
-
-(defvar gnus-group-buffer "*Newsgroup*")
-(defvar gnus-summary-buffer "*Summary*")
-(defvar gnus-article-buffer "*Article*")
-(defvar gnus-digest-buffer "GNUS Digest")
-(defvar gnus-digest-summary-buffer "GNUS Digest-summary")
-
-(defvar gnus-buffer-list
- (list gnus-group-buffer gnus-summary-buffer gnus-article-buffer
- gnus-digest-buffer gnus-digest-summary-buffer)
- "GNUS buffer names which should be killed when exiting.")
-
-(defvar gnus-variable-list
- '(gnus-newsrc-options
- gnus-newsrc-options-n-yes gnus-newsrc-options-n-no
- gnus-newsrc-assoc gnus-killed-assoc gnus-marked-assoc)
- "GNUS variables saved in the quick startup file.")
-
-(defvar gnus-overload-functions
- '((news-inews gnus-inews-news "rnewspost")
- (caesar-region gnus-caesar-region "rnews"))
- "Functions overloaded by gnus.
-It is a list of `(original overload &optional file)'.")
-
-(defvar gnus-distribution-list nil)
-
-(defvar gnus-newsrc-options nil
- "Options line in the `.newsrc' file.")
-
-(defvar gnus-newsrc-options-n-yes nil
- "Regexp representing subscribed newsgroups.")
-
-(defvar gnus-newsrc-options-n-no nil
- "Regexp representing unsubscribed newsgroups.")
-
-(defvar gnus-newsrc-assoc nil
- "Assoc list of read articles.
-`gnus-newsrc-hashtb' should be kept so that both hold the same information.")
-
-(defvar gnus-newsrc-hashtb nil
- "Hashtable of `gnus-newsrc-assoc'.")
-
-(defvar gnus-killed-assoc nil
- "Assoc list of newsgroups removed from `gnus-newsrc-assoc'.
-`gnus-killed-hashtb' should be kept so that both hold the same information.")
-
-(defvar gnus-killed-hashtb nil
- "Hashtable of `gnus-killed-assoc'.")
-
-(defvar gnus-marked-assoc nil
- "Assoc list of articles marked as unread.
-`gnus-marked-hashtb' should be kept so that both hold the same information.")
-
-(defvar gnus-marked-hashtb nil
- "Hashtable of `gnus-marked-assoc'.")
-
-(defvar gnus-unread-hashtb nil
- "Hashtable of unread articles.")
-
-(defvar gnus-active-hashtb nil
- "Hashtable of active articles.")
-
-(defvar gnus-octive-hashtb nil
- "Hashtable of OLD active articles.")
-
-(defvar gnus-current-startup-file nil
- "Startup file for the current host.")
-
-(defvar gnus-last-search-regexp nil
- "Default regexp for article search command.")
-
-(defvar gnus-last-shell-command nil
- "Default shell command on article.")
-
-(defvar gnus-have-all-newsgroups nil)
-
-(defvar gnus-newsgroup-name nil)
-(defvar gnus-newsgroup-begin nil)
-(defvar gnus-newsgroup-end nil)
-(defvar gnus-newsgroup-last-rmail nil)
-(defvar gnus-newsgroup-last-mail nil)
-(defvar gnus-newsgroup-last-folder nil)
-(defvar gnus-newsgroup-last-file nil)
-
-(defvar gnus-newsgroup-unreads nil
- "List of unread articles in the current newsgroup.")
-
-(defvar gnus-newsgroup-unselected nil
- "List of unselected unread articles in the current newsgroup.")
-
-(defvar gnus-newsgroup-marked nil
- "List of marked articles in the current newsgroup (a subset of unread art).")
-
-(defvar gnus-newsgroup-headers nil
- "List of article headers in the current newsgroup.
-If you modify the variable, you must call the function
-`gnus-clear-hashtables-for-newsgroup-headers' to clear the hash tables.")
-(defvar gnus-newsgroup-headers-hashtb-by-id nil)
-(defvar gnus-newsgroup-headers-hashtb-by-number nil)
-
-(defvar gnus-current-article nil)
-(defvar gnus-current-headers nil)
-(defvar gnus-current-history nil)
-(defvar gnus-have-all-headers nil "Must be either T or NIL.")
-(defvar gnus-last-article nil)
-(defvar gnus-current-kill-article nil)
-
-;; Save window configuration.
-(defvar gnus-winconf-kill-file nil)
-
-(defvar gnus-group-mode-map nil)
-(defvar gnus-summary-mode-map nil)
-(defvar gnus-article-mode-map nil)
-(defvar gnus-kill-file-mode-map nil)
-
-(defvar rmail-default-file (expand-file-name "~/XMBOX"))
-(defvar rmail-default-rmail-file (expand-file-name "~/XNEWS"))
-
-;; Define GNUS Subsystems.
-(autoload 'gnus-group-post-news "gnuspost"
- "Post an article." t)
-(autoload 'gnus-summary-post-news "gnuspost"
- "Post an article." t)
-(autoload 'gnus-summary-followup "gnuspost"
- "Post a reply article." t)
-(autoload 'gnus-summary-followup-with-original "gnuspost"
- "Post a reply article with original article." t)
-(autoload 'gnus-summary-cancel-article "gnuspost"
- "Cancel an article you posted." t)
-
-(autoload 'gnus-summary-reply "gnusmail"
- "Reply mail to news author." t)
-(autoload 'gnus-summary-reply-with-original "gnusmail"
- "Reply mail to news author with original article." t)
-(autoload 'gnus-summary-mail-forward "gnusmail"
- "Forward the current message to another user." t)
-(autoload 'gnus-summary-mail-other-window "gnusmail"
- "Compose mail in other window." t)
-
-(autoload 'gnus-group-kill-group "gnusmisc"
- "Kill newsgroup on current line." t)
-(autoload 'gnus-group-yank-group "gnusmisc"
- "Yank the last killed newsgroup on current line." t)
-(autoload 'gnus-group-kill-region "gnusmisc"
- "Kill newsgroups in current region." t)
-(autoload 'gnus-group-transpose-groups "gnusmisc"
- "Exchange current newsgroup and previous newsgroup." t)
-(autoload 'gnus-list-killed-groups "gnusmisc"
- "List the killed newsgroups." t)
-(autoload 'gnus-gmt-to-local "gnusmisc"
- "Rewrite Date field in GMT to local in current buffer.")
-
-(autoload 'metamail-buffer "metamail"
- "Process current buffer through `metamail'." t)
-
-(autoload 'rmail-output "rmailout"
- "Append this message to Unix mail file named FILE-NAME." t)
-(autoload 'mail-position-on-field "sendmail")
-(autoload 'mh-find-path "mh-e")
-(autoload 'mh-prompt-for-folder "mh-e")
-
-(put 'gnus-group-mode 'mode-class 'special)
-(put 'gnus-summary-mode 'mode-class 'special)
-(put 'gnus-article-mode 'mode-class 'special)
-
-(autoload 'gnus-uu-ctl-map "gnus-uu" nil nil 'keymap)
-(autoload 'gnus-uu-mark-article "gnus-uu" nil t)
-
-;;(put 'gnus-eval-in-buffer-window 'lisp-indent-hook 1)
-
-(defmacro gnus-eval-in-buffer-window (buffer &rest forms)
- "Pop to BUFFER, evaluate FORMS, and then returns to original window."
- (` (let ((GNUSStartBufferWindow (selected-window)))
- (unwind-protect
- (progn
- (pop-to-buffer (, buffer))
- (,@ forms))
- (select-window GNUSStartBufferWindow)))))
-
-(defmacro gnus-make-hashtable (&optional hashsize)
- "Make a hash table (default and minimum size is 200).
-Optional argument HASHSIZE specifies the table size."
- (` (make-vector (, (if hashsize (` (max (, hashsize) 200)) 200)) 0)))
-
-(defmacro gnus-gethash (string hashtable)
- "Get hash value of STRING in HASHTABLE."
- ;;(` (symbol-value (abbrev-symbol (, string) (, hashtable))))
- ;;(` (abbrev-expansion (, string) (, hashtable)))
- (` (symbol-value (intern-soft (, string) (, hashtable)))))
-
-(defmacro gnus-sethash (string value hashtable)
- "Set hash value. Arguments are STRING, VALUE, and HASHTABLE."
- ;; We cannot use define-abbrev since it only accepts string as value.
- (` (set (intern (, string) (, hashtable)) (, value))))
-
-;; Note: Macros defined here are also defined in nntp.el. I don't like
-;; to put them here, but many users got troubled with the old
-;; definitions in nntp.elc. These codes are NNTP 3.10 version.
-
-(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))))
-
-
-;;;
-;;; GNUS Group Mode
-;;;
-
-(if gnus-group-mode-map
- nil
- (setq gnus-group-mode-map (make-keymap))
- (suppress-keymap gnus-group-mode-map)
- (define-key gnus-group-mode-map " " 'gnus-group-read-group)
- (define-key gnus-group-mode-map "=" 'gnus-group-select-group)
- (define-key gnus-group-mode-map "j" 'gnus-group-jump-to-group)
- (define-key gnus-group-mode-map "n" 'gnus-group-next-unread-group)
- (define-key gnus-group-mode-map "p" 'gnus-group-prev-unread-group)
- (define-key gnus-group-mode-map "\177" 'gnus-group-prev-unread-group)
- (define-key gnus-group-mode-map "N" 'gnus-group-next-group)
- (define-key gnus-group-mode-map "P" 'gnus-group-prev-group)
- (define-key gnus-group-mode-map "\C-n" 'gnus-group-next-group)
- (define-key gnus-group-mode-map "\C-p" 'gnus-group-prev-group)
- (define-key gnus-group-mode-map [down] 'gnus-group-next-group)
- (define-key gnus-group-mode-map [up] 'gnus-group-prev-group)
- (define-key gnus-group-mode-map "\r" 'next-line)
- ;;(define-key gnus-group-mode-map "/" 'isearch-forward)
- (define-key gnus-group-mode-map "<" 'beginning-of-buffer)
- (define-key gnus-group-mode-map ">" 'end-of-buffer)
- (define-key gnus-group-mode-map "u" 'gnus-group-unsubscribe-current-group)
- (define-key gnus-group-mode-map "U" 'gnus-group-unsubscribe-group)
- (define-key gnus-group-mode-map "c" 'gnus-group-catchup)
- (define-key gnus-group-mode-map "C" 'gnus-group-catchup-all)
- (define-key gnus-group-mode-map "l" 'gnus-group-list-groups)
- (define-key gnus-group-mode-map "L" 'gnus-group-list-all-groups)
- (define-key gnus-group-mode-map "g" 'gnus-group-get-new-news)
- (define-key gnus-group-mode-map "R" 'gnus-group-restart)
- (define-key gnus-group-mode-map "b" 'gnus-group-check-bogus-groups)
- (define-key gnus-group-mode-map "r" 'gnus-group-restrict-groups)
- (define-key gnus-group-mode-map "a" 'gnus-group-post-news)
- (define-key gnus-group-mode-map "\ek" 'gnus-group-edit-local-kill)
- (define-key gnus-group-mode-map "\eK" 'gnus-group-edit-global-kill)
- (define-key gnus-group-mode-map "\C-k" 'gnus-group-kill-group)
- (define-key gnus-group-mode-map "\C-y" 'gnus-group-yank-group)
- (define-key gnus-group-mode-map "\C-w" 'gnus-group-kill-region)
- (define-key gnus-group-mode-map "\C-x\C-t" 'gnus-group-transpose-groups)
- (define-key gnus-group-mode-map "\C-c\C-l" 'gnus-list-killed-groups)
- (define-key gnus-group-mode-map "V" 'gnus-version)
- ;;(define-key gnus-group-mode-map "x" 'gnus-group-force-update)
- (define-key gnus-group-mode-map "s" 'gnus-group-force-update)
- (define-key gnus-group-mode-map "z" 'gnus-group-suspend)
- (define-key gnus-group-mode-map "q" 'gnus-group-exit)
- (define-key gnus-group-mode-map "Q" 'gnus-group-quit)
- (define-key gnus-group-mode-map "?" 'gnus-group-describe-briefly)
- (define-key gnus-group-mode-map "\C-c\C-i" 'gnus-info-find-node)
- (define-key gnus-group-mode-map [mouse-2] 'gnus-mouse-pick-group)
- (define-key gnus-group-mode-map "t" 'gnus-newsgroups-display-toggle)
-
- ;; Make a menu bar item.
- (define-key gnus-group-mode-map [menu-bar GNUS]
- (cons "GNUS" (make-sparse-keymap "GNUS")))
-
- (define-key gnus-group-mode-map [menu-bar GNUS force-update]
- '("Force Update" . gnus-group-force-update))
- (define-key gnus-group-mode-map [menu-bar GNUS quit]
- '("Quit" . gnus-group-quit))
- (define-key gnus-group-mode-map [menu-bar GNUS exit]
- '("Exit" . gnus-group-exit))
- (define-key gnus-group-mode-map [menu-bar GNUS restart]
- '("Restart" . gnus-group-restart))
- (define-key gnus-group-mode-map [menu-bar GNUS suspend]
- '("Suspend" . gnus-group-suspend))
- (define-key gnus-group-mode-map [menu-bar GNUS get-new-news]
- '("Get New News" . gnus-group-get-new-news))
-
- ;; Make a menu bar item.
- (define-key gnus-group-mode-map [menu-bar groups]
- (cons "Groups" (make-sparse-keymap "Groups")))
-
- (define-key gnus-group-mode-map [menu-bar groups catchup]
- '("Catchup" . gnus-group-catchup))
- (define-key gnus-group-mode-map [menu-bar groups edit-global-kill]
- '("Edit Kill File" . gnus-group-edit-global-kill))
-
- (define-key gnus-group-mode-map [menu-bar groups separator-2]
- '("--"))
-
- (define-key gnus-group-mode-map [menu-bar groups yank-group]
- '("Yank Group" . gnus-group-yank-group))
- (define-key gnus-group-mode-map [menu-bar groups kill-group]
- '("Kill Group" . gnus-group-kill-group))
-
- (define-key gnus-group-mode-map [menu-bar groups separator-1]
- '("--"))
-
- (define-key gnus-group-mode-map [menu-bar groups newsgroups-update-description]
- '("Update descriptions" . gnus-newsgroups-update-description))
- (define-key gnus-group-mode-map [menu-bar groups newsgroups-display-toggle]
- '("Toggle descriptions" . gnus-newsgroups-display-toggle))
- (define-key gnus-group-mode-map [menu-bar groups jump-to-group]
- '("Jump to Group..." . gnus-group-jump-to-group))
- (define-key gnus-group-mode-map [menu-bar groups list-all-groups]
- '("List All Groups" . gnus-group-list-all-groups))
- (define-key gnus-group-mode-map [menu-bar groups list-groups]
- '("List Groups" . gnus-group-list-groups))
- (define-key gnus-group-mode-map [menu-bar groups unsub-current-group]
- '("Unsubscribe Group" . gnus-group-unsubscribe-current-group))
- )
-
-(defun gnus-group-mode ()
- "Major mode for reading network news.
-All normal editing commands are turned off.
-Instead, these commands are available:
-
-SPC Read articles in this newsgroup.
-= Select this newsgroup.
-j Move to the specified newsgroup.
-n Move to the next unread newsgroup.
-p Move to the previous unread newsgroup.
-C-n Move to the next newsgroup.
-C-p Move to the previous newsgroup.
-< Move point to the beginning of this buffer.
-> Move point to the end of this buffer.
-u Unsubscribe from (subscribe to) this newsgroup.
-U Unsubscribe from (subscribe to) the specified newsgroup.
-c Mark all articles as read, preserving marked articles.
-C Mark all articles in this newsgroup as read.
-l Revert this buffer.
-L List all newsgroups.
-g Get new news.
-R Force to read the raw .newsrc file and get new news.
-b Check bogus newsgroups.
-r Restrict visible newsgroups to the current region.
-a Post a new article.
-ESC k Edit a local KILL file applied to this newsgroup.
-ESC K Edit a global KILL file applied to all newsgroups.
-C-k Kill this newsgroup.
-C-y Yank killed newsgroup here.
-C-w Kill newsgroups in current region (excluding current point).
-C-x C-t Exchange this newsgroup and previous newsgroup.
-C-c C-l list killed newsgroups.
-s Save .newsrc file.
-z Suspend reading news.
-q Quit reading news.
-Q Quit reading news without saving .newsrc file.
-V Show the version number of this GNUS.
-? Describe Group Mode commands briefly.
-C-h m Describe Group Mode.
-C-c C-i Read Info about Group Mode.
-t Toggle displaying newsgroup descriptions.
-
- The name of the host running NNTP server is asked for if no default
-host is specified. It is also possible to choose another NNTP server
-even when the default server is defined by giving a prefix argument to
-the command `\\[gnus]'.
-
- If the NNTP server name starts with a colon, as in `:Mail', the user's
-own directory `~/Mail' is used as a news spool. This makes it
-possible to read mail stored in MH folders or articles saved by GNUS.
-File names of mail or articles must consist of only numeric
-characters. Otherwise, they are ignored.
-
- If there is a file named `~/.newsrc-SERVER', it is used as the
-startup file instead of standard one when talking to SERVER. It is
-possible to talk to many hosts by using different startup files for
-each.
-
- Option `-n' of the options line in the startup file is recognized
-properly the same as the Bnews system. For example, if the options
-line is `options -n !talk talk.rumors', newsgroups under the `talk'
-hierarchy except for `talk.rumors' are ignored while checking new
-newsgroups.
-
- If there is a file named `~/.signature-DISTRIBUTION', it is used as
-signature file instead of standard one when posting a news in
-DISTRIBUTION.
-
- If an Info file generated from `gnus.texinfo' is installed, you can
-read an appropriate Info node of the Info file according to the
-current major mode of GNUS by \\[gnus-info-find-node].
-
- The variable `gnus-version', `nntp-version', `nnspool-version', and
-`mhspool-version' have the version numbers of this version of gnus.el,
-nntp.el, nnspool.el, and mhspoo.el, respectively.
-
-User customizable variables:
- gnus-nntp-server
- Specifies the name of the host running the NNTP server. If its
- value is a string such as `:DIRECTORY', the user's private
- DIRECTORY is used as a news spool. The variable is initialized
- from the NNTPSERVER environment variable.
-
- gnus-nntp-service
- Specifies a NNTP service name. It is usually \"nntp\" or 119.
- Nil forces GNUS to use a local news spool if the variable
- `gnus-nntp-server' is set to the local host name.
-
- gnus-startup-file
- Specifies a startup file (.newsrc). If there is a file named
- `.newsrc-SERVER', it's used instead when talking to SERVER. I
- recommend you to use the server specific file, if you'd like to
- talk to many servers. Especially if you'd like to read your
- private directory, the name of the file must be
- `.newsrc-:DIRECTORY'.
-
- gnus-signature-file
- Specifies a signature file (.signature). If there is a file named
- `.signature-DISTRIBUTION', it's used instead when posting an
- article in DISTRIBUTION. Set the variable to nil to prevent
- appending the file automatically. If you use an NNTP inews which
- comes with the NNTP package, you may have to set the variable to
- nil.
-
- gnus-use-cross-reference
- Specifies what to do with cross references (Xref: field). If it
- is nil, cross references are ignored. If it is t, articles in
- subscribed newsgroups are only marked as read. Otherwise, if it
- is not nil nor t, articles in all newsgroups are marked as read.
-
- gnus-use-followup-to
- Specifies what to do with followup-to: field. If it is nil, its
- value is ignored. If it is non-nil, its value is used as followup
- newsgroups. Especially, if it is t and field value is `poster',
- your confirmation is required.
-
- gnus-author-copy
- Specifies a file name to save a copy of article you posted using
- FCC: field. If the first character of the value is `|', the
- contents of the article is piped out to a program specified by the
- rest of the value. The variable is initialized from the
- AUTHORCOPY environment variable.
-
- gnus-author-copy-saver
- Specifies a function to save an author copy. The function is
- called with a file name. The default function `rmail-output'
- saves in Unix mail format.
-
- gnus-kill-file-name
- Use specified file name as a KILL file (default to `KILL').
-
- gnus-novice-user
- Non-nil means that you are a novice to USENET. If non-nil,
- verbose messages may be displayed or your confirmations may be
- required.
-
- gnus-interactive-post
- Non-nil means that newsgroup, subject and distribution are asked
- for interactively when posting a new article.
-
- gnus-use-full-window
- Non-nil means to take up the entire screen of Emacs.
-
- gnus-window-configuration
- Specifies the configuration of Group, Summary, and Article
- windows. It is a list of (ACTION (G S A)), where G, S, and A are
- the relative height of Group, Summary, and Article windows,
- respectively. ACTION is `summary', `newsgroups', or `article'.
-
- gnus-subscribe-newsgroup-method
- Specifies a function called with a newsgroup name when new
- newsgroup is found. The default definition adds new newsgroup at
- the beginning of other newsgroups.
-
- And more and more. Please refer to texinfo documentation.
-
-Various hooks for customization:
- gnus-group-mode-hook
- Entry to this mode calls the value with no arguments, if that
- value is non-nil. This hook is called before GNUS is connected to
- the NNTP server. So, you can change or define the NNTP server in
- this hook.
-
- gnus-startup-hook
- Called with no arguments after the NNTP server is selected. It is
- possible to change the behavior of GNUS or initialize the
- variables according to the selected NNTP server.
-
- gnus-group-prepare-hook
- Called with no arguments after a newsgroup list is created in the
- Newsgroup buffer, if that value is non-nil.
-
- gnus-save-newsrc-hook
- Called with no arguments when saving newsrc file if that value is
- non-nil.
-
- gnus-prepare-article-hook
- Called with no arguments after preparing message body, but before
- preparing header fields which is automatically generated if that
- value is non-nil. The default hook (gnus-inews-insert-signature)
- inserts a signature file.
-
- gnus-inews-article-hook
- Called with no arguments when posting an article if that value is
- non-nil. This hook is called just before posting an article. The
- default hook does FCC (save an article to the specified file).
-
- gnus-suspend-gnus-hook
- Called with no arguments when suspending (not exiting) GNUS, if
- that value is non-nil.
-
- gnus-exit-gnus-hook
- Called with no arguments when exiting (not suspending) GNUS, 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: List of Newsgroups %[(%m)%]----%3p-%-")))
- (setq major-mode 'gnus-group-mode)
- (setq mode-name "Newsgroup")
- (setq mode-line-buffer-identification "GNUS: List of Newsgroups")
- (setq mode-line-process nil)
- (use-local-map gnus-group-mode-map)
- (buffer-flush-undo (current-buffer))
- (setq buffer-read-only t) ;Disable modification
- (setq truncate-lines t) ;In case descriptions are too long.
- (run-hooks 'gnus-group-mode-hook))
-
-(defun gnus-mouse-pick-group (e)
- (interactive "e")
- (mouse-set-point e)
- (gnus-group-read-group nil))
-
-;;;###autoload
-(defun gnus (&optional confirm)
- "Read network news.
-If optional argument CONFIRM is non-nil, ask NNTP server."
- (interactive "P")
- (unwind-protect
- (progn
- (switch-to-buffer (get-buffer-create gnus-group-buffer))
- (gnus-group-mode)
- (gnus-start-news-server confirm))
- (if (not (gnus-server-opened))
- (gnus-group-quit)
- ;; NNTP server is successfully open.
- (setq mode-line-process (format " {%s}" gnus-nntp-server))
- (let ((buffer-read-only nil))
- (erase-buffer)
- (gnus-group-startup-message)
- (sit-for 0))
- (run-hooks 'gnus-startup-hook)
- (gnus-setup-news)
- (if gnus-novice-user
- (gnus-group-describe-briefly)) ;Show brief help message.
- (gnus-group-list-groups nil)
- )))
-
-(defun gnus-group-startup-message ()
- "Insert startup message in current buffer."
- ;; Insert the message.
- (insert
- (format "
- %s
-
- NNTP-based News Reader for GNU Emacs
-
-
-If you have any trouble with this software, please let me
-know. I will fix your problems in the next release.
-
-Comments, suggestions, and bug fixes are welcome.
-
-Masanobu UMEDA
-umerin@mse.kyutech.ac.jp" gnus-version))
- ;; And then hack it.
- ;; 57 is the longest line.
- (indent-rigidly (point-min) (point-max) (/ (max (- (window-width) 57) 0) 2))
- (goto-char (point-min))
- ;; +4 is fuzzy factor.
- (insert-char ?\n (/ (max (- (window-height) 18) 0) 2)))
-
-(defun gnus-group-list-groups (show-all)
- "List newsgroups in the Newsgroup buffer.
-If argument SHOW-ALL is non-nil, unsubscribed groups are also listed."
- (interactive "P")
- (setq gnus-newsgroups-showall show-all)
- (let ((case-fold-search nil)
- (last-group ;Current newsgroup.
- (gnus-group-group-name))
- (next-group ;Next possible newsgroup.
- (progn
- (gnus-group-search-forward nil nil)
- (gnus-group-group-name)))
- (prev-group ;Previous possible newsgroup.
- (progn
- (gnus-group-search-forward t nil)
- (gnus-group-group-name))))
- (set-buffer gnus-group-buffer) ;May call from out of Group buffer
- (gnus-group-prepare show-all)
- (if (zerop (buffer-size))
- (message "No news is good news")
- ;; Go to last newsgroup if possible. If cannot, try next and
- ;; previous. If all fail, go to first unread newsgroup.
- (goto-char (point-min))
- (or (and last-group
- (re-search-forward (gnus-group-make-regexp last-group) nil t))
- (and next-group
- (re-search-forward (gnus-group-make-regexp next-group) nil t))
- (and prev-group
- (re-search-forward (gnus-group-make-regexp prev-group) nil t))
- (gnus-group-search-forward nil nil t))
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t)
- )))
-
-(defun gnus-group-prepare (&optional all)
- "Prepare list of newsgroups in current buffer.
-If optional argument ALL is non-nil, unsubscribed groups are also listed."
- (let ((buffer-read-only nil)
- (newsrc gnus-newsrc-assoc)
- (group-info nil)
- (group-name nil)
- (group-description nil)
- (unread-count 0)
- (nb-tab 0)
- ;; This specifies the format of Group buffer.
- (cntl "%s%s%5d: %s"))
- (erase-buffer)
- ;; List newsgroups.
- (while newsrc
- (setq group-info (car newsrc))
- (setq group-name (car group-info))
- (if gnus-newsgroups-display
- (progn (setq group-description (gnus-gethash group-name gnus-newsgroups-hashtb))
- (setq nb-tab (/ (- 38 (length group-name)) tab-width))))
- (setq unread-count (nth 1 (gnus-gethash group-name gnus-unread-hashtb)))
- (if (or all
- (and (nth 1 group-info) ;Subscribed.
- (> unread-count 0))) ;There are unread articles.
- ;; Yes, I can use gnus-group-prepare-line, but this is faster.
- (insert
- (format (concat cntl (make-string (if (> nb-tab 0) nb-tab 1) ?\t)
- "%s\n")
- ;; Subscribed or not.
- (if (nth 1 group-info) " " "U")
- ;; Has new news?
- (if (and (> unread-count 0)
- (>= 0
- (- unread-count
- (length
- (cdr (gnus-gethash group-name
- gnus-marked-hashtb))))))
- "*" " ")
- ;; Number of unread articles.
- unread-count
- ;; Newsgroup name.
- group-name
- ;; Newsgroup description
- (if group-description (cdr group-description) "")
- ))
- )
- (setq newsrc (cdr newsrc))
- )
- (setq gnus-have-all-newsgroups all)
- (goto-char (point-min))
- (run-hooks 'gnus-group-prepare-hook)
- ))
-
-(defun gnus-group-prepare-line (info)
- "Return a string for the Newsgroup buffer from INFO.
-INFO is an element of `gnus-newsrc-assoc' or `gnus-killed-assoc'."
- (let* ((group-name (car info))
- (group-description nil)
- (nb-tab 0)
- (unread-count
- (or (nth 1 (gnus-gethash group-name gnus-unread-hashtb))
- ;; Not in hash table, so compute it now.
- (gnus-number-of-articles
- (gnus-difference-of-range
- (nth 2 (gnus-gethash group-name gnus-active-hashtb))
- (nthcdr 2 info)))))
- ;; This specifies the format of Group buffer.
- (cntl "%s%s%5d: %s"))
- (if gnus-newsgroups-display
- (progn
- (setq group-description (gnus-gethash group-name gnus-newsgroups-hashtb))
- (setq nb-tab (/ (- 38 (length group-name)) tab-width))))
- (format (concat cntl (make-string (if (> nb-tab 0) nb-tab 1) ?\t)
- "%s\n")
- ;; Subscribed or not.
- (if (nth 1 info) " " "U")
- ;; Has new news?
- (if (and (> unread-count 0)
- (>= 0
- (- unread-count
- (length
- (cdr (gnus-gethash group-name
- gnus-marked-hashtb))))))
- "*" " ")
- ;; Number of unread articles.
- unread-count
- ;; Newsgroup name.
- group-name
- ;; Newsgroup description
- (if group-description (cdr group-description) "")
- )))
-
-(defun gnus-group-update-group (group &optional visible-only)
- "Update newsgroup info of GROUP.
-If optional argument VISIBLE-ONLY is non-nil, non displayed group is ignored."
- (let ((buffer-read-only nil)
- (case-fold-search nil) ;appleIIgs vs. appleiigs
- (regexp (gnus-group-make-regexp group))
- (visible nil))
- ;; Buffer may be narrowed.
- (save-restriction
- (widen)
- ;; Search a line to modify. If the buffer is large, the search
- ;; takes long time. In most cases, current point is on the line
- ;; we are looking for. So, first of all, check current line.
- ;; And then if current point is in the first half, search from
- ;; the beginning. Otherwise, search from the end.
- (if (cond ((progn
- (beginning-of-line)
- (looking-at regexp)))
- ((and (> (/ (buffer-size) 2) (point)) ;In the first half.
- (progn
- (goto-char (point-min))
- (re-search-forward regexp nil t))))
- ((progn
- (goto-char (point-max))
- (re-search-backward regexp nil t))))
- ;; GROUP is listed in current buffer. So, delete old line.
- (progn
- (setq visible t)
- (beginning-of-line)
- (delete-region (point) (progn (forward-line 1) (point)))
- )
- ;; No such line in the buffer, so insert it at the top.
- (goto-char (point-min)))
- (if (or visible (not visible-only))
- (progn
- (insert (gnus-group-prepare-line
- (gnus-gethash group gnus-newsrc-hashtb)))
- (forward-line -1) ;Move point on that line.
- ))
- )))
-
-(defun gnus-group-group-name ()
- "Get newsgroup name around point."
- (save-excursion
- (beginning-of-line)
- (if (looking-at "^..[0-9 \t]+:[ \t]+\\([^ \t\n]+\\)\\([ \t].*\\|$\\)")
- (let ((group-name (buffer-substring (match-beginning 1) (match-end 1))))
- (set-text-properties 0 (length group-name) nil group-name)
- group-name))))
-
-(defun gnus-group-make-regexp (newsgroup)
- "Return regexp that matches for a line of NEWSGROUP."
- (concat "^.+: " (regexp-quote newsgroup) "\\([ \t].*\\|$\\)"))
-
-(defun gnus-group-search-forward (backward norest &optional heretoo)
- "Search for the next (or previous) newsgroup.
-If 1st argument BACKWARD is non-nil, search backward instead.
-If 2nd argument NOREST is non-nil, don't care about newsgroup property.
-If optional argument HERETOO is non-nil, current line is searched for, too."
- (let ((case-fold-search nil)
- (func
- (if backward
- (function re-search-backward) (function re-search-forward)))
- (regexp
- (format "^%s[ \t]*\\(%s\\):"
- (if norest ".." " [ \t]")
- (if norest "[0-9]+" "[1-9][0-9]*")))
- (found nil))
- (if backward
- (if heretoo
- (end-of-line)
- (beginning-of-line))
- (if heretoo
- (beginning-of-line)
- (end-of-line)))
- (setq found (funcall func regexp nil t))
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t)
- ;; Return T if found.
- found
- ))
-
-;; GNUS Group mode command
-
-(defun gnus-group-read-group (all &optional no-article)
- "Read news in this newsgroup.
-If argument ALL is non-nil, already read articles become readable.
-If optional argument NO-ARTICLE is non-nil, no article body is displayed."
- (interactive "P")
- (let ((group (gnus-group-group-name))) ;Newsgroup name to read.
- (if group
- (gnus-summary-read-group
- group
- (or all
- ;;(not (nth 1 (gnus-gethash group gnus-newsrc-hashtb))) ;Unsubscribed
- (zerop
- (nth 1 (gnus-gethash group gnus-unread-hashtb)))) ;No unread
- no-article
- ))
- ))
-
-(defun gnus-group-select-group (all)
- "Select this newsgroup.
-No article is selected automatically.
-If argument ALL is non-nil, already read articles become readable."
- (interactive "P")
- (gnus-group-read-group all t))
-
-(defun gnus-group-jump-to-group (group)
- "Jump to newsgroup GROUP."
- (interactive
- (list (completing-read "Newsgroup: " gnus-newsrc-assoc nil 'require-match)))
- (let ((case-fold-search nil))
- (goto-char (point-min))
- (or (re-search-forward (gnus-group-make-regexp group) nil t)
- (if (gnus-gethash group gnus-newsrc-hashtb)
- ;; Add GROUP entry, then seach again.
- (gnus-group-update-group group)))
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t)
- ))
-
-(defun gnus-group-next-group (n)
- "Go to Nth following newsgroup."
- (interactive "p")
- (while (and (> n 1)
- (gnus-group-search-forward nil t))
- (setq n (1- n)))
- (or (gnus-group-search-forward nil t)
- (message "No more newsgroups")))
-
-(defun gnus-group-next-unread-group (n)
- "Go to Nth following unread newsgroup."
- (interactive "p")
- (while (and (> n 1)
- (gnus-group-search-forward nil nil))
- (setq n (1- n)))
- (or (gnus-group-search-forward nil nil)
- (message "No more unread newsgroups")))
-
-(defun gnus-group-prev-group (n)
- "Go to Nth previous newsgroup."
- (interactive "p")
- (while (and (> n 1)
- (gnus-group-search-forward t t))
- (setq n (1- n)))
- (or (gnus-group-search-forward t t)
- (message "No more newsgroups")))
-
-(defun gnus-group-prev-unread-group (n)
- "Go to Nth previous unread newsgroup."
- (interactive "p")
- (while (and (> n 1)
- (gnus-group-search-forward t nil))
- (setq n (1- n)))
- (or (gnus-group-search-forward t nil)
- (message "No more unread newsgroups")))
-
-(defun gnus-group-catchup (all)
- "Mark all articles not marked as unread in current newsgroup as read.
-If prefix argument ALL is non-nil, all articles are marked as read.
-Cross references (Xref: field) of articles are ignored."
- (interactive "P")
- (let* ((group (gnus-group-group-name))
- (marked (if (not all)
- (cdr (gnus-gethash group gnus-marked-hashtb)))))
- (and group
- (or (not gnus-interactive-catchup) ;Without confirmation?
- (y-or-n-p
- (if all
- "Do you really want to mark everything as read? "
- "Delete all articles not marked as read? ")))
- (progn
- (message "") ;Clear "Yes or No" question.
- ;; Any marked articles will be preserved.
- (gnus-update-unread-articles group marked marked)
- (gnus-group-update-group group)
- (gnus-group-next-group 1)))
- ))
-
-(defun gnus-group-catchup-all ()
- "Mark all articles in current newsgroup as read.
-Cross references (Xref: field) of articles are ignored."
- (interactive)
- (gnus-group-catchup t))
-
-(defun gnus-group-unsubscribe-current-group ()
- "Toggle subscribe from/to unsubscribe current group."
- (interactive)
- (let ((group (gnus-group-group-name)))
- (if group
- (progn
- (gnus-group-unsubscribe-group group)
- (gnus-group-next-group 1))
- (message "No Newsgroup found to \(un\)subscribe"))))
-
-(defun gnus-group-unsubscribe-group (group)
- "Toggle subscribe from/to unsubscribe GROUP.
-\(If GROUP is new, it is added to `.newsrc' automatically.)"
- (interactive
- (list (completing-read "Newsgroup: "
- gnus-active-hashtb nil 'require-match)))
- (let ((newsrc (gnus-gethash group gnus-newsrc-hashtb)))
- (cond ((not (null newsrc))
- ;; Toggle subscription flag.
- (setcar (nthcdr 1 newsrc) (not (nth 1 newsrc)))
- (gnus-update-newsrc-buffer group)
- (gnus-group-update-group group)
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t))
- ((and (stringp group)
- (gnus-gethash group gnus-active-hashtb))
- ;; Add new newsgroup.
- (gnus-add-newsgroup group)
- (gnus-group-update-group group)
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t))
- (t (error "No such newsgroup: %s" group)))
- ))
-
-(defun gnus-group-list-all-groups ()
- "List all of newsgroups in the Newsgroup buffer."
- (interactive)
- (message "Listing all groups...")
- (gnus-group-list-groups t)
- (message "Listing all groups...done"))
-
-(defun gnus-group-get-new-news ()
- "Get newly arrived articles. In fact, read the active file again."
- (interactive)
- (gnus-setup-news)
- (gnus-group-list-groups gnus-have-all-newsgroups))
-
-(defun gnus-group-restart ()
- "Force GNUS to read the raw startup file."
- (interactive)
- (gnus-save-newsrc-file)
- (gnus-setup-news t) ;Force to read the raw startup file.
- (gnus-group-list-groups gnus-have-all-newsgroups))
-
-(defun gnus-group-check-bogus-groups ()
- "Check bogus newsgroups."
- (interactive)
- (gnus-check-bogus-newsgroups t) ;Require confirmation.
- (gnus-group-list-groups gnus-have-all-newsgroups))
-
-(defun gnus-group-restrict-groups (start end)
- "Restrict visible newsgroups to the current region (START and END).
-Type \\[widen] to remove restriction."
- (interactive "r")
- (save-excursion
- (narrow-to-region (progn
- (goto-char start)
- (beginning-of-line)
- (point))
- (progn
- (goto-char end)
- (forward-line 1)
- (point))))
- (message (substitute-command-keys "Type \\[widen] to remove restriction")))
-
-(defun gnus-group-edit-global-kill ()
- "Edit a global KILL file."
- (interactive)
- (setq gnus-current-kill-article nil) ;No articles selected.
- (gnus-kill-file-edit-file nil) ;Nil stands for global KILL file.
- (message
- (substitute-command-keys
- "Editing a global KILL file (Type \\[gnus-kill-file-exit] to exit)")))
-
-(defun gnus-group-edit-local-kill ()
- "Edit a local KILL file."
- (interactive)
- (setq gnus-current-kill-article nil) ;No articles selected.
- (gnus-kill-file-edit-file (gnus-group-group-name))
- (message
- (substitute-command-keys
- "Editing a local KILL file (Type \\[gnus-kill-file-exit] to exit)")))
-
-(defun gnus-group-force-update ()
- "Update `.newsrc' file."
- (interactive)
- (gnus-save-newsrc-file))
-
-(defun gnus-group-suspend ()
- "Suspend the current GNUS session.
-In fact, cleanup buffers except for Group Mode buffer.
-The hook `gnus-suspend-gnus-hook' is called before actually suspending."
- (interactive)
- (run-hooks 'gnus-suspend-gnus-hook)
- ;; Kill GNUS buffers except for Group Mode buffer.
- (let ((buffers gnus-buffer-list)
- (group-buf (get-buffer gnus-group-buffer)))
- (while buffers
- (and (not (eq (car buffers) gnus-group-buffer))
- (get-buffer (car buffers))
- (kill-buffer (car buffers)))
- (setq buffers (cdr buffers))
- )
- (bury-buffer group-buf)
- (delete-windows-on group-buf t)))
-
-(defun gnus-group-exit ()
- "Quit reading news after updating `.newsrc'.
-The hook `gnus-exit-gnus-hook' is called before actually quitting."
- (interactive)
- (if (or noninteractive ;For gnus-batch-kill
- (zerop (buffer-size)) ;No news is good news.
- (not (gnus-server-opened)) ;NNTP connection closed.
- (not gnus-interactive-exit) ;Without confirmation
- (y-or-n-p "Are you sure you want to quit reading news? "))
- (progn
- (message "") ;Erase "Yes or No" question.
- (run-hooks 'gnus-exit-gnus-hook)
- (gnus-save-newsrc-file)
- (gnus-clear-system)
- (gnus-close-server))
- ))
-
-(defun gnus-group-quit ()
- "Quit reading news without updating `.newsrc'.
-The hook `gnus-exit-gnus-hook' is called before actually quitting."
- (interactive)
- (if (or noninteractive ;For gnus-batch-kill
- (zerop (buffer-size))
- (not (gnus-server-opened))
- (yes-or-no-p
- (format "Quit reading news without saving %s? "
- (file-name-nondirectory gnus-current-startup-file))))
- (progn
- (message "") ;Erase "Yes or No" question.
- (run-hooks 'gnus-exit-gnus-hook)
- (gnus-clear-system)
- (gnus-close-server))
- ))
-
-(defun gnus-group-describe-briefly ()
- "Describe Group mode commands briefly."
- (interactive)
- (message
- (concat
- (substitute-command-keys "\\[gnus-group-read-group]:Select ")
- (substitute-command-keys "\\[gnus-group-next-unread-group]:Forward ")
- (substitute-command-keys "\\[gnus-group-prev-unread-group]:Backward ")
- (substitute-command-keys "\\[gnus-group-exit]:Exit ")
- (substitute-command-keys "\\[gnus-info-find-node]:Run Info ")
- (substitute-command-keys "\\[gnus-group-describe-briefly]:This help")
- )))
-
-
-;;;
-;;; GNUS Summary Mode
-;;;
-
-(if gnus-summary-mode-map
- nil
- (setq gnus-summary-mode-map (make-keymap))
- (suppress-keymap gnus-summary-mode-map)
- (define-key gnus-summary-mode-map "\C-c\C-v" 'gnus-uu-ctl-map)
- (define-key gnus-summary-mode-map "#" 'gnus-uu-mark-article)
- (define-key gnus-summary-mode-map " " 'gnus-summary-next-page)
- (define-key gnus-summary-mode-map "\177" 'gnus-summary-prev-page)
- (define-key gnus-summary-mode-map "\r" 'gnus-summary-scroll-up)
- (define-key gnus-summary-mode-map "n" 'gnus-summary-next-unread-article)
- (define-key gnus-summary-mode-map "p" 'gnus-summary-prev-unread-article)
- (define-key gnus-summary-mode-map "N" 'gnus-summary-next-article)
- (define-key gnus-summary-mode-map "P" 'gnus-summary-prev-article)
- (define-key gnus-summary-mode-map "\e\C-n" 'gnus-summary-next-same-subject)
- (define-key gnus-summary-mode-map "\e\C-p" 'gnus-summary-prev-same-subject)
- ;;(define-key gnus-summary-mode-map "\e\C-n" 'gnus-summary-next-unread-same-subject)
- ;;(define-key gnus-summary-mode-map "\e\C-p" 'gnus-summary-prev-unread-same-subject)
- (define-key gnus-summary-mode-map "\C-c\C-n" 'gnus-summary-next-digest)
- (define-key gnus-summary-mode-map "\C-c\C-p" 'gnus-summary-prev-digest)
- (define-key gnus-summary-mode-map "\C-n" 'gnus-summary-next-subject)
- (define-key gnus-summary-mode-map "\C-p" 'gnus-summary-prev-subject)
- (define-key gnus-summary-mode-map [down] 'gnus-summary-next-subject)
- (define-key gnus-summary-mode-map [up] 'gnus-summary-prev-subject)
- (define-key gnus-summary-mode-map "\en" 'gnus-summary-next-unread-subject)
- (define-key gnus-summary-mode-map "\ep" 'gnus-summary-prev-unread-subject)
- ;;(define-key gnus-summary-mode-map "\C-cn" 'gnus-summary-next-group)
- ;;(define-key gnus-summary-mode-map "\C-cp" 'gnus-summary-prev-group)
- (define-key gnus-summary-mode-map "." 'gnus-summary-first-unread-article)
- ;;(define-key gnus-summary-mode-map "/" 'isearch-forward)
- (define-key gnus-summary-mode-map "s" 'gnus-summary-isearch-article)
- (define-key gnus-summary-mode-map "\es" 'gnus-summary-search-article-forward)
- ;;(define-key gnus-summary-mode-map "\eS" 'gnus-summary-search-article-backward)
- (define-key gnus-summary-mode-map "\er" 'gnus-summary-search-article-backward)
- (define-key gnus-summary-mode-map "<" 'gnus-summary-beginning-of-article)
- (define-key gnus-summary-mode-map ">" 'gnus-summary-end-of-article)
- (define-key gnus-summary-mode-map "j" 'gnus-summary-goto-subject)
- ;;(define-key gnus-summary-mode-map "J" 'gnus-summary-goto-article)
- (define-key gnus-summary-mode-map "l" 'gnus-summary-goto-last-article)
- (define-key gnus-summary-mode-map "^" 'gnus-summary-refer-parent-article)
- ;;(define-key gnus-summary-mode-map "\er" 'gnus-summary-refer-article)
- (define-key gnus-summary-mode-map "\e^" 'gnus-summary-refer-article)
- (define-key gnus-summary-mode-map "u" 'gnus-summary-mark-as-unread-forward)
- (define-key gnus-summary-mode-map "U" 'gnus-summary-mark-as-unread-backward)
- (define-key gnus-summary-mode-map "d" 'gnus-summary-mark-as-read-forward)
- (define-key gnus-summary-mode-map "D" 'gnus-summary-mark-as-read-backward)
- (define-key gnus-summary-mode-map "\eu" 'gnus-summary-clear-mark-forward)
- (define-key gnus-summary-mode-map "\eU" 'gnus-summary-clear-mark-backward)
- (define-key gnus-summary-mode-map "k" 'gnus-summary-kill-same-subject-and-select)
- (define-key gnus-summary-mode-map "\C-k" 'gnus-summary-kill-same-subject)
- (define-key gnus-summary-mode-map "\e\C-t" 'gnus-summary-toggle-threads)
- (define-key gnus-summary-mode-map "\e\C-s" 'gnus-summary-show-thread)
- (define-key gnus-summary-mode-map "\e\C-h" 'gnus-summary-hide-thread)
- (define-key gnus-summary-mode-map "\e\C-f" 'gnus-summary-next-thread)
- (define-key gnus-summary-mode-map "\e\C-b" 'gnus-summary-prev-thread)
- (define-key gnus-summary-mode-map "\e\C-u" 'gnus-summary-up-thread)
- (define-key gnus-summary-mode-map "\e\C-d" 'gnus-summary-down-thread)
- (define-key gnus-summary-mode-map "\e\C-k" 'gnus-summary-kill-thread)
- (define-key gnus-summary-mode-map "&" 'gnus-summary-execute-command)
- ;;(define-key gnus-summary-mode-map "c" 'gnus-summary-catchup)
- ;;(define-key gnus-summary-mode-map "c" 'gnus-summary-catchup-all)
- (define-key gnus-summary-mode-map "c" 'gnus-summary-catchup-and-exit)
- ;;(define-key gnus-summary-mode-map "c" 'gnus-summary-catchup-all-and-exit)
- (define-key gnus-summary-mode-map "\C-t" 'gnus-summary-toggle-truncation)
- (define-key gnus-summary-mode-map "x" 'gnus-summary-delete-marked-as-read)
- (define-key gnus-summary-mode-map "X" 'gnus-summary-delete-marked-with)
- (define-key gnus-summary-mode-map "\C-c\C-sn" 'gnus-summary-sort-by-number)
- (define-key gnus-summary-mode-map "\C-c\C-sa" 'gnus-summary-sort-by-author)
- (define-key gnus-summary-mode-map "\C-c\C-ss" 'gnus-summary-sort-by-subject)
- (define-key gnus-summary-mode-map "\C-c\C-sd" 'gnus-summary-sort-by-date)
- (define-key gnus-summary-mode-map "\C-c\C-s\C-n" 'gnus-summary-sort-by-number)
- (define-key gnus-summary-mode-map "\C-c\C-s\C-a" 'gnus-summary-sort-by-author)
- (define-key gnus-summary-mode-map "\C-c\C-s\C-s" 'gnus-summary-sort-by-subject)
- (define-key gnus-summary-mode-map "\C-c\C-s\C-d" 'gnus-summary-sort-by-date)
- (define-key gnus-summary-mode-map "=" 'gnus-summary-expand-window)
- ;;(define-key gnus-summary-mode-map "G" 'gnus-summary-reselect-current-group)
- (define-key gnus-summary-mode-map "\C-x\C-s" 'gnus-summary-reselect-current-group)
- (define-key gnus-summary-mode-map "w" 'gnus-summary-stop-page-breaking)
- (define-key gnus-summary-mode-map "\C-c\C-r" 'gnus-summary-caesar-message)
- (define-key gnus-summary-mode-map "g" 'gnus-summary-show-article)
- (define-key gnus-summary-mode-map "t" 'gnus-summary-toggle-header)
- ;;(define-key gnus-summary-mode-map "v" 'gnus-summary-show-all-headers)
- (define-key gnus-summary-mode-map "\et" 'gnus-summary-toggle-mime)
- (define-key gnus-summary-mode-map "\C-d" 'gnus-summary-rmail-digest)
- (define-key gnus-summary-mode-map "a" 'gnus-summary-post-news)
- (define-key gnus-summary-mode-map "f" 'gnus-summary-followup)
- (define-key gnus-summary-mode-map "F" 'gnus-summary-followup-with-original)
- (define-key gnus-summary-mode-map "C" 'gnus-summary-cancel-article)
- (define-key gnus-summary-mode-map "r" 'gnus-summary-reply)
- (define-key gnus-summary-mode-map "R" 'gnus-summary-reply-with-original)
- (define-key gnus-summary-mode-map "\C-c\C-f" 'gnus-summary-mail-forward)
- (define-key gnus-summary-mode-map "m" 'gnus-summary-mail-other-window)
- (define-key gnus-summary-mode-map "o" 'gnus-summary-save-article)
- (define-key gnus-summary-mode-map "\C-o" 'gnus-summary-save-in-mail)
- (define-key gnus-summary-mode-map "|" 'gnus-summary-pipe-output)
- (define-key gnus-summary-mode-map "\ek" 'gnus-summary-edit-local-kill)
- (define-key gnus-summary-mode-map "\eK" 'gnus-summary-edit-global-kill)
- (define-key gnus-summary-mode-map "V" 'gnus-version)
- (define-key gnus-summary-mode-map "q" 'gnus-summary-exit)
- (define-key gnus-summary-mode-map "Q" 'gnus-summary-quit)
- (define-key gnus-summary-mode-map "?" 'gnus-summary-describe-briefly)
- (define-key gnus-summary-mode-map "\C-c\C-i" 'gnus-info-find-node)
- (define-key gnus-summary-mode-map [mouse-2] 'gnus-mouse-pick-article)
-
- (define-key gnus-summary-mode-map [menu-bar misc]
- (cons "Misc" (make-sparse-keymap "misc")))
-
- (define-key gnus-summary-mode-map [menu-bar misc caesar-message]
- '("Caesar Message" . gnus-summary-caesar-message))
- (define-key gnus-summary-mode-map [menu-bar misc cancel-article]
- '("Cancel Article" . gnus-summary-cancel-article))
- (define-key gnus-summary-mode-map [menu-bar misc edit-local-kill]
- '("Edit Kill File" . gnus-summary-edit-local-kill))
-
- (define-key gnus-summary-mode-map [menu-bar misc mark-as-unread]
- '("Mark as Unread" . gnus-summary-mark-as-unread-forward))
- (define-key gnus-summary-mode-map [menu-bar misc mark-as-read]
- '("Mark as Read" . gnus-summary-mark-as-read))
-
- (define-key gnus-summary-mode-map [menu-bar misc quit]
- '("Quit Group" . gnus-summary-quit))
- (define-key gnus-summary-mode-map [menu-bar misc exit]
- '("Exit Group" . gnus-summary-exit))
-
- (define-key gnus-summary-mode-map [menu-bar sort]
- (cons "Sort" (make-sparse-keymap "sort")))
-
- (define-key gnus-summary-mode-map [menu-bar sort sort-by-author]
- '("Sort by Author" . gnus-summary-sort-by-author))
- (define-key gnus-summary-mode-map [menu-bar sort sort-by-date]
- '("Sort by Date" . gnus-summary-sort-by-date))
- (define-key gnus-summary-mode-map [menu-bar sort sort-by-number]
- '("Sort by Number" . gnus-summary-sort-by-number))
- (define-key gnus-summary-mode-map [menu-bar sort sort-by-subject]
- '("Sort by Subject" . gnus-summary-sort-by-subject))
-
- (define-key gnus-summary-mode-map [menu-bar show/hide]
- (cons "Show/Hide" (make-sparse-keymap "show/hide")))
-
- (define-key gnus-summary-mode-map [menu-bar show/hide hide-all-threads]
- '("Hide All Threads" . gnus-summary-hide-all-threads))
- (define-key gnus-summary-mode-map [menu-bar show/hide hide-thread]
- '("Hide Thread" . gnus-summary-hide-thread))
- (define-key gnus-summary-mode-map [menu-bar show/hide show-all-threads]
- '("Show All Threads" . gnus-summary-show-all-threads))
- (define-key gnus-summary-mode-map [menu-bar show/hide show-all-headers]
- '("Show All Headers" . gnus-summary-show-all-headers))
- (define-key gnus-summary-mode-map [menu-bar show/hide show-thread]
- '("Show Thread" . gnus-summary-show-thread))
- (define-key gnus-summary-mode-map [menu-bar show/hide show-article]
- '("Show Article" . gnus-summary-show-article))
- (define-key gnus-summary-mode-map [menu-bar show/hide toggle-truncation]
- '("Toggle Truncation" . gnus-summary-toggle-truncation))
- (define-key gnus-summary-mode-map [menu-bar show/hide toggle-mime]
- '("Toggle Mime" . gnus-summary-toggle-mime))
- (define-key gnus-summary-mode-map [menu-bar show/hide toggle-header]
- '("Toggle Header" . gnus-summary-toggle-header))
-
- (define-key gnus-summary-mode-map [menu-bar action]
- (cons "Action" (make-sparse-keymap "action")))
-
- (define-key gnus-summary-mode-map [menu-bar action kill-same-subject]
- '("Kill Same Subject" . gnus-summary-kill-same-subject))
- (define-key gnus-summary-mode-map [menu-bar action kill-thread]
- '("Kill Thread" . gnus-summary-kill-thread))
- (define-key gnus-summary-mode-map [menu-bar action delete-marked-with]
- '("Delete Marked With" . gnus-summary-delete-marked-with))
- (define-key gnus-summary-mode-map [menu-bar action delete-marked-as-read]
- '("Delete Marked As Read" . gnus-summary-delete-marked-as-read))
- (define-key gnus-summary-mode-map [menu-bar action catchup-and-exit]
- '("Catchup And Exit" . gnus-summary-catchup-and-exit))
- (define-key gnus-summary-mode-map [menu-bar action catchup-to-here]
- '("Catchup to Here" . gnus-summary-catchup-to-here))
-
- (define-key gnus-summary-mode-map [menu-bar action ignore]
- '("---"))
-
- (define-key gnus-summary-mode-map [menu-bar action save-in-file]
- '("Save in File" . gnus-summary-save-in-file))
- (define-key gnus-summary-mode-map [menu-bar action save-article]
- '("Save Article" . gnus-summary-save-article))
-
- (define-key gnus-summary-mode-map [menu-bar action lambda]
- '("---"))
-
- (define-key gnus-summary-mode-map [menu-bar action forward]
- '("Forward" . gnus-summary-mail-forward))
- (define-key gnus-summary-mode-map [menu-bar action followup-with-original]
- '("Followup with Original" . gnus-summary-followup-with-original))
- (define-key gnus-summary-mode-map [menu-bar action followup]
- '("Followup" . gnus-summary-followup))
- (define-key gnus-summary-mode-map [menu-bar action reply-with-original]
- '("Reply with Original" . gnus-summary-reply-with-original))
- (define-key gnus-summary-mode-map [menu-bar action reply]
- '("Reply" . gnus-summary-reply))
- (define-key gnus-summary-mode-map [menu-bar action post]
- '("Post News" . gnus-summary-post-news))
-
- (define-key gnus-summary-mode-map [menu-bar move]
- (cons "Move" (make-sparse-keymap "move")))
-
- (define-key gnus-summary-mode-map [menu-bar move isearch-article]
- '("Search in Article" . gnus-summary-isearch-article))
- (define-key gnus-summary-mode-map [menu-bar move search-through-articles]
- '("Search through Articles" . gnus-summary-search-article-forward))
- (define-key gnus-summary-mode-map [menu-bar move down-thread]
- '("Down Thread" . gnus-summary-down-thread))
- (define-key gnus-summary-mode-map [menu-bar move prev-same-subject]
- '("Prev Same Subject" . gnus-summary-prev-same-subject))
- (define-key gnus-summary-mode-map [menu-bar move prev-group]
- '("Prev Group" . gnus-summary-prev-group))
- (define-key gnus-summary-mode-map [menu-bar move next-unread-same-subject]
- '("Next Unread Same Subject" . gnus-summary-next-unread-same-subject))
- (define-key gnus-summary-mode-map [menu-bar move next-unread-article]
- '("Next Unread Article" . gnus-summary-next-unread-article))
- (define-key gnus-summary-mode-map [menu-bar move next-thread]
- '("Next Thread" . gnus-summary-next-thread))
- (define-key gnus-summary-mode-map [menu-bar move next-group]
- '("Next Group" . gnus-summary-next-group))
- (define-key gnus-summary-mode-map [menu-bar move first-unread-article]
- '("First Unread Article" . gnus-summary-first-unread-article))
- )
-
-
-(defun gnus-summary-mode ()
- "Major mode for reading articles in this newsgroup.
-All normal editing commands are turned off.
-Instead, these commands are available:
-
-SPC Scroll to the next page of the current article. The next unread
- article is selected automatically at the end of the message.
-DEL Scroll to the previous page of the current article.
-RET Scroll up (or down) one line the current article.
-n Move to the next unread article.
-p Move to the previous unread article.
-N Move to the next article.
-P Move to the previous article.
-ESC C-n Move to the next article which has the same subject as the
- current article.
-ESC C-p Move to the previous article which has the same subject as the
- current article.
-\\[gnus-summary-next-unread-same-subject]
- Move to the next unread article which has the same subject as the
- current article.
-\\[gnus-summary-prev-unread-same-subject]
- Move to the previous unread article which has the same subject as
- the current article.
-C-c C-n Scroll to the next digested message of the current article.
-C-c C-p Scroll to the previous digested message of the current article.
-C-n Move to the next subject.
-C-p Move to the previous subject.
-ESC n Move to the next unread subject.
-ESC p Move to the previous unread subject.
-\\[gnus-summary-next-group]
- Exit the current newsgroup and select the next unread newsgroup.
-\\[gnus-summary-prev-group]
- Exit the current newsgroup and select the previous unread newsgroup.
-. Jump to the first unread article in the current newsgroup.
-s Do an incremental search forward on the current article.
-ESC s Search for an article containing a regexp forward.
-ESC r Search for an article containing a regexp backward.
-< Move point to the beginning of the current article.
-> Move point to the end of the current article.
-j Jump to the article specified by the numeric article ID.
-l Jump to the article you read last.
-^ Refer to parent of the current article.
-ESC ^ Refer to the article specified by the Message-ID.
-u Mark the current article as unread, and go forward.
-U Mark the current article as unread, and go backward.
-d Mark the current article as read, and go forward.
-D Mark the current article as read, and go backward.
-ESC u Clear the current article's mark, and go forward.
-ESC U Clear the current article's mark, and go backward.
-k Mark articles which has the same subject as the current article as
- read, and then select the next unread article.
-C-k Mark articles which has the same subject as the current article as
- read.
-ESC k Edit a local KILL file applied to the current newsgroup.
-ESC K Edit a global KILL file applied to all newsgroups.
-ESC C-t Toggle showing conversation threads.
-ESC C-s Show thread subtrees.
-ESC C-h Hide thread subtrees.
-\\[gnus-summary-show-all-threads] Show all thread subtrees.
-\\[gnus-summary-hide-all-threads] Hide all thread subtrees.
-ESC C-f Go to the same level next thread.
-ESC C-b Go to the same level previous thread.
-ESC C-d Go downward current thread.
-ESC C-u Go upward current thread.
-ESC C-k Mark articles under current thread as read.
-& Execute a command for each article conditionally.
-\\[gnus-summary-catchup]
- Mark all articles as read in the current newsgroup, preserving
- articles marked as unread.
-\\[gnus-summary-catchup-all]
- Mark all articles as read in the current newsgroup.
-\\[gnus-summary-catchup-and-exit]
- Catch up all articles not marked as unread, and then exit the
- current newsgroup.
-\\[gnus-summary-catchup-all-and-exit]
- Catch up all articles, and then exit the current newsgroup.
-C-t Toggle truncations of subject lines.
-x Delete subject lines marked as read.
-X Delete subject lines with the specific marks.
-C-c C-s C-n Sort subjects by article number.
-C-c C-s C-a Sort subjects by article author.
-C-c C-s C-s Sort subjects alphabetically.
-C-c C-s C-d Sort subjects by date.
-= Expand Summary window to show headers full window.
-C-x C-s Reselect the current newsgroup. Prefix argument means to select all.
-w Stop page breaking by linefeed.
-C-c C-r Caesar rotates letters by 13/47 places.
-g Force to show the current article.
-t Show original article header if pruned header currently shown, or
- vice versa.
-ESC-t Toggle MIME processing.
-C-d Run RMAIL on the current digest article.
-a Post a new article.
-f Post a reply article.
-F Post a reply article with original article.
-C Cancel the current article.
-r Mail a message to the author.
-R Mail a message to the author with original author.
-C-c C-f Forward the current message to another user.
-m Mail a message in other window.
-o Save the current article in your favorite format.
-C-o Append the current article to a file in Unix mail format.
-| Pipe the contents of the current article to a subprocess.
-q Quit reading news in the current newsgroup.
-Q Quit reading news without recording unread articles information.
-V Show the version number of this GNUS.
-? Describe Summary mode commands briefly.
-C-h m Describe Summary mode.
-C-c C-i Read Info about Summary mode.
-
-User customizable variables:
- gnus-large-newsgroup
- The number of articles which indicates a large newsgroup. If the
- number of articles in a newsgroup is greater than the value, the
- number of articles to be selected is asked for. If the given value
- N is positive, the last N articles is selected. If N is negative,
- the first N articles are selected. An empty string means to select
- all articles.
-
- gnus-use-long-file-name
- Non-nil means that a newsgroup name is used as a default file name
- to save articles to. If it's nil, the directory form of a
- newsgroup is used instead.
-
- gnus-default-article-saver
- Specifies your favorite article saver which is interactively
- funcallable. Following functions are available:
-
- gnus-summary-save-in-rmail (in Rmail format)
- gnus-summary-save-in-mail (in Unix mail format)
- gnus-summary-save-in-folder (in MH folder)
- gnus-summary-save-in-file (in article format).
-
- gnus-rmail-save-name
- gnus-mail-save-name
- gnus-folder-save-name
- gnus-file-save-name
- Specifies a function generating a file name to save articles in
- specified format. The function is called with NEWSGROUP, HEADERS,
- and optional LAST-FILE. Access macros to the headers are defined
- as `nntp-header-FIELD', and functions are defined as
- `gnus-header-FIELD'.
-
- gnus-article-save-directory
- Specifies a directory name to save articles to using the commands
- `gnus-summary-save-in-rmail', `gnus-summary-save-in-mail' and
- `gnus-summary-save-in-file'. The variable is initialized from the
- SAVEDIR environment variable.
-
- gnus-kill-files-directory
- Specifies a directory name to save KILL files to using the commands
- `gnus-edit-global-kill', and `gnus-edit-local-kill'. The variable is
- initialized from the SAVEDIR environment variable.
-
- gnus-show-all-headers
- Non-nil means that all headers of an article are shown.
-
- gnus-save-all-headers
- Non-nil means that all headers of an article are saved in a file.
-
- gnus-show-mime
- Non-nil means that show a MIME message.
-
- gnus-show-threads
- Non-nil means that conversation threads are shown in tree structure.
-
- gnus-thread-hide-subject
- Non-nil means that subjects for thread subtrees are hidden.
-
- gnus-thread-hide-subtree
- Non-nil means that thread subtrees are hidden initially.
-
- gnus-thread-hide-killed
- Non-nil means that killed thread subtrees are hidden automatically.
-
- gnus-thread-ignore-subject
- Non-nil means that subject differences are ignored in constructing
- thread trees.
-
- gnus-thread-indent-level
- Indentation of thread subtrees.
-
- gnus-optional-headers
- Specifies a function which generates an optional string displayed
- in the Summary buffer. The function is called with an article
- HEADERS. The result must be a string excluding `[' and `]'. The
- default function returns a string like NNN:AUTHOR, where NNN is
- the number of lines in an article and AUTHOR is the name of the
- author.
-
- gnus-auto-extend-newsgroup
- Non-nil means visible articles are extended to forward and
- backward automatically if possible.
-
- gnus-auto-select-first
- Non-nil means the first unread article is selected automagically
- when a newsgroup is selected normally (by `gnus-group-read-group').
- If you'd like to prevent automatic selection of the first unread
- article in some newsgroups, set the variable to nil in
- `gnus-select-group-hook' or `gnus-apply-kill-hook'.
-
- gnus-auto-select-next
- Non-nil means the next newsgroup is selected automagically at the
- end of the newsgroup. If the value is t and the next newsgroup is
- empty (no unread articles), GNUS will exit Summary mode and go
- back to Group mode. If the value is neither nil nor t, GNUS won't
- exit Summary mode but select the following unread newsgroup.
- Especially, if the value is the symbol `quietly', the next unread
- newsgroup will be selected without any confirmations.
-
- gnus-auto-select-same
- Non-nil means an article with the same subject as the current
- article is selected automagically like `rn -S'.
-
- gnus-auto-center-summary
- Non-nil means the point of Summary Mode window is always kept
- centered.
-
- gnus-break-pages
- Non-nil means an article is broken into pages at page delimiters.
- This may not work with some versions of GNU Emacs earlier than
- version 18.50.
-
- gnus-page-delimiter
- Specifies a regexp describing line-beginnings that separate pages
- of news article.
-
- gnus-digest-show-summary
- Non-nil means that a summary of digest messages is shown when
- reading a digest article using `gnus-summary-rmail-digest'
- command.
-
- gnus-digest-separator
- Specifies a regexp separating messages in a digest article.
-
- gnus-mail-reply-method
- gnus-mail-other-window-method
- Specifies a function to begin composing mail message using
- commands `gnus-summary-reply' and `gnus-summary-mail-other-window'.
- Functions `gnus-mail-reply-using-mail' and `gnus-mail-reply-using-mhe'
- are available for the value of `gnus-mail-reply-method'. And
- functions `gnus-mail-other-window-using-mail' and
- `gnus-mail-other-window-using-mhe' are available for the value of
- `gnus-mail-other-window-method'.
-
- gnus-mail-send-method
- Specifies a function to mail a message too which is being posted
- as an article. The message must have To: or Cc: field. The value
- of the variable `send-mail-function' is the default function, which
- uses sendmail mail program.
-
-Various hooks for customization:
- gnus-summary-mode-hook
- Entry to this mode calls the value with no arguments, if that
- value is non-nil.
-
- gnus-select-group-hook
- Called with no arguments when newsgroup is selected, if that value
- is non-nil. It is possible to sort subjects in this hook. See the
- documentation of this variable for more information.
-
- gnus-summary-prepare-hook
- Called with no arguments after a summary list is created in the
- Summary buffer, if that value is non-nil. If you'd like to modify
- the buffer, you can use this hook.
-
- gnus-select-article-hook
- Called with no arguments when an article is selected, if that
- value is non-nil. See the documentation of this variable for more
- information.
-
- gnus-select-digest-hook
- Called with no arguments when reading digest messages using Rmail,
- if that value is non-nil. This hook can be used to modify an
- article so that Rmail can work with it. See the documentation of
- the variable for more information.
-
- gnus-rmail-digest-hook
- Called with no arguments when reading digest messages using Rmail,
- if that value is non-nil. This hook is intended to customize Rmail
- mode.
-
- gnus-apply-kill-hook
- Called with no arguments when a newsgroup is selected and the
- Summary buffer is prepared. This hook is intended to apply a KILL
- file to the selected newsgroup. The format of KILL file is
- completely different from that of version 3.8. You have to rewrite
- them in the new format. See the documentation of Kill file mode
- for more information.
-
- gnus-mark-article-hook
- Called with no arguments when an article is selected at the first
- time. The hook is intended to mark an article as read (or unread)
- automatically when it is selected. See the documentation of the
- variable for more information.
-
- gnus-exit-group-hook
- Called with no arguments when exiting the current newsgroup, if
- that value is non-nil. If your machine is so slow that exiting
- from Summary mode takes very long time, inhibit marking articles
- as read using cross-references by setting the variable
- gnus-use-cross-reference to nil in this hook."
- (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))))))
- ;; To disable display-time facility.
- ;;(make-local-variable 'global-mode-string)
- ;;(setq global-mode-string nil)
- (setq major-mode 'gnus-summary-mode)
- (setq mode-name "Summary")
- ;;(setq mode-line-process '(" " gnus-newsgroup-name))
- (make-local-variable 'minor-mode-alist)
- (or (assq 'gnus-show-threads minor-mode-alist)
- (setq minor-mode-alist
- (cons (list 'gnus-show-threads " Thread") minor-mode-alist)))
- (gnus-summary-set-mode-line)
- (use-local-map gnus-summary-mode-map)
- (buffer-flush-undo (current-buffer))
- (setq buffer-read-only t) ;Disable modification
- (setq truncate-lines t) ;Stop line folding
- (setq selective-display t)
- (setq selective-display-ellipses t) ;Display `...'
- ;;(setq case-fold-search t)
- (run-hooks 'gnus-summary-mode-hook))
-
-(defun gnus-mouse-pick-article (e)
- (interactive "e")
- (mouse-set-point e)
- (gnus-summary-next-page nil))
-
-(defun gnus-summary-setup-buffer ()
- "Initialize Summary buffer."
- (if (get-buffer gnus-summary-buffer)
- (set-buffer gnus-summary-buffer)
- (set-buffer (get-buffer-create gnus-summary-buffer))
- (gnus-summary-mode)
- ))
-
-(defun gnus-summary-read-group (group &optional show-all no-article)
- "Start reading news in newsgroup GROUP.
-If optional 1st argument SHOW-ALL is non-nil, already read articles are
-also listed.
-If optional 2nd argument NO-ARTICLE is non-nil, no article is selected
-initially."
- (message "Retrieving newsgroup: %s..." group)
- (if (gnus-select-newsgroup group show-all)
- (progn
- ;; Don't switch-to-buffer to prevent displaying old contents
- ;; of the buffer until new subjects list is created.
- ;; Suggested by Juha Heinanen <jh@tut.fi>
- (gnus-summary-setup-buffer)
- ;; You can change the order of subjects in this hook.
- (run-hooks 'gnus-select-group-hook)
- (gnus-summary-prepare)
- ;; Function `gnus-apply-kill-file' must be called in this hook.
- (run-hooks 'gnus-apply-kill-hook)
- (if (zerop (buffer-size))
- ;; This newsgroup is empty.
- (progn
- (gnus-summary-catchup-and-exit nil t) ;Without confirmations.
- (message "No unread news"))
- ;; Hide conversation thread subtrees. We cannot do this in
- ;; gnus-summary-prepare-hook since kill processing may not
- ;; work with hidden articles.
- (and gnus-show-threads
- gnus-thread-hide-subtree
- (gnus-summary-hide-all-threads))
- ;; Show first unread article if requested.
- (goto-char (point-min))
- (if (and (not no-article)
- gnus-auto-select-first
- (gnus-summary-first-unread-article))
- ;; Window is configured automatically.
- ;; Current buffer may be changed as a result of hook
- ;; evaluation, especially by gnus-summary-rmail-digest
- ;; command, so we should adjust cursor point carefully.
- (if (eq (current-buffer) (get-buffer gnus-summary-buffer))
- (progn
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t)))
- (gnus-configure-windows 'summary)
- (pop-to-buffer gnus-summary-buffer)
- (gnus-summary-set-mode-line)
- ;; I sometime get confused with the old Article buffer.
- (if (get-buffer gnus-article-buffer)
- (if (get-buffer-window gnus-article-buffer)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil))
- (erase-buffer)))
- (kill-buffer gnus-article-buffer)))
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t))
- ))
- ;; Cannot select newsgroup GROUP.
- (if (gnus-gethash group gnus-active-hashtb)
- (progn
- ;; If NNTP is used, nntp_access file may not be installed
- ;; properly. Otherwise, may be active file problem.
- (ding)
- (message
- (gnus-nntp-message
- (format "Cannot select %s. May be security or active file problem." group)))
- (sit-for 0))
- ;; Check bogus newsgroups.
- ;; We must be in Group Mode buffer.
- (gnus-group-check-bogus-groups))
- ))
-
-(defun gnus-summary-prepare ()
- "Prepare summary list of current newsgroup in Summary buffer."
- (let ((buffer-read-only nil))
- ;; Note: The next codes are not actually used because the user who
- ;; want it can define them in gnus-select-group-hook.
- ;; Print verbose messages if too many articles are selected.
- ;; (and (numberp gnus-large-newsgroup)
- ;; (> (length gnus-newsgroup-headers) gnus-large-newsgroup)
- ;; (message "Preparing headers..."))
- (erase-buffer)
- (gnus-summary-prepare-threads
- (if gnus-show-threads
- (gnus-make-threads gnus-newsgroup-headers)
- gnus-newsgroup-headers) 0)
- ;; Erase header retrieval message.
- (message "")
- ;; Call hooks for modifying Summary buffer.
- ;; Suggested by sven@tde.LTH.Se (Sven Mattisson).
- (goto-char (point-min))
- (run-hooks 'gnus-summary-prepare-hook)
- ))
-
-;; Basic ideas by Paul Dworkin <paul@media-lab.media.mit.edu>
-;; Subject bug fix by jbw@bigbird.bu.edu (Joe Wells)
-
-(defun gnus-summary-prepare-threads (threads level &optional parent-subject)
- "Prepare Summary buffer from THREADS and indentation LEVEL.
-THREADS is a list of `(PARENT [(CHILD1 [(GRANDCHILD ...]...) ...]).'
-Optional PARENT-SUBJECT specifies the subject of the parent."
- (let ((thread nil)
- (header nil)
- (number nil)
- (subject nil)
- (child-subject nil)
- (parent-subject (or parent-subject ""))
- ;; `M Indent NUM: [OPT] SUBJECT'
- (cntl (format "%%s %%s%%%dd: [%%s] %%s\n"
- (length (prin1-to-string gnus-newsgroup-end)))))
- (while threads
- (setq thread (car threads))
- (setq threads (cdr threads))
- ;; If thread is a cons, hierarchical threads is given.
- ;; Otherwise, thread itself is header.
- (if (consp thread)
- (setq header (car thread))
- (setq header thread))
- ;; Print valid header only.
- (if (vectorp header) ;Depends on nntp.el.
- (progn
- (setq number (nntp-header-number header))
- (setq subject (nntp-header-subject header))
- (setq child-subject (gnus-simplify-subject subject 're-only))
- (insert
- (format cntl
- ;; Read or not.
- (cond ((memq number gnus-newsgroup-marked) "-")
- ((memq number gnus-newsgroup-unreads) " ")
- (t "D"))
- ;; Thread level.
- (make-string (* level gnus-thread-indent-level) ? )
- ;; Article number.
- number
- ;; Optional headers.
- (or (and gnus-optional-headers
- (funcall gnus-optional-headers header)) "")
- ;; Its subject string.
- (concat (if (or (zerop level)
- (not gnus-thread-hide-subject)
- ;; Subject is different from the parent.
- (not (string-equal
- parent-subject child-subject)))
- nil
- (make-string (window-width) ? ))
- subject)
- ))
- ))
- ;; Print subthreads.
- (and (consp thread)
- (cdr thread)
- (gnus-summary-prepare-threads
- (cdr thread) (1+ level) child-subject))
- )))
-
-;;(defun gnus-summary-set-mode-line ()
-;; "Set Summary mode line string."
-;; ;; The value must be a string to escape %-constructs.
-;; (let ((subject
-;; (if gnus-current-headers
-;; (nntp-header-subject gnus-current-headers) gnus-newsgroup-name)))
-;; (setq mode-line-buffer-identification
-;; (concat "GNUS: "
-;; subject
-;; ;; Enough spaces to pad subject to 17 positions.
-;; (make-string (max 0 (- 17 (length subject))) ? ))))
-;; (set-buffer-modified-p t))
-
-;; New implementation in gnus 3.14.3
-
-(defun gnus-summary-set-mode-line ()
- "Set Summary mode line string.
-If you don't like it, define your own `gnus-summary-set-mode-line'."
- (let ((unmarked
- (- (length gnus-newsgroup-unreads)
- (length (gnus-intersection
- gnus-newsgroup-unreads gnus-newsgroup-marked))))
- (unselected
- (- (length gnus-newsgroup-unselected)
- (length (gnus-intersection
- gnus-newsgroup-unselected gnus-newsgroup-marked)))))
- (setq mode-line-buffer-identification
- (list 17
- (format "GNUS: %s%s %s"
- gnus-newsgroup-name
- (if gnus-current-article
- (format "/%d" gnus-current-article) "")
- ;; Basic ideas by tale@pawl.rpi.edu.
- (cond ((and (zerop unmarked)
- (zerop unselected))
- "")
- ((zerop unselected)
- (format "{%d more}" unmarked))
- (t
- (format "{%d(+%d) more}" unmarked unselected)))
- ))))
- (set-buffer-modified-p t))
-
-;; GNUS Summary mode command.
-
-(defun gnus-summary-search-group (&optional backward)
- "Search for next unread newsgroup.
-If optional argument BACKWARD is non-nil, search backward instead."
- (save-excursion
- (set-buffer gnus-group-buffer)
- (save-excursion
- ;; We don't want to alter current point of Group mode buffer.
- (if (gnus-group-search-forward backward nil)
- (gnus-group-group-name))
- )))
-
-(defun gnus-summary-search-subject (backward unread subject)
- "Search for article forward.
-If 1st argument BACKWARD is non-nil, search backward.
-If 2nd argument UNREAD is non-nil, only unread article is selected.
-If 3rd argument SUBJECT is non-nil, the article which has
-the same subject will be searched for."
- (let ((func
- (if backward
- (function re-search-backward) (function re-search-forward)))
- (article nil)
- ;; We have to take care of hidden lines.
- (regexp
- (format "^%s[ \t]+\\([0-9]+\\):.\\[[^]\r\n]*\\][ \t]+%s"
- ;;(if unread " " ".")
- (cond ((eq unread t) " ") (unread "[- ]") (t "."))
- (if subject
- (concat "\\([Rr][Ee]:[ \t]+\\)*"
- (regexp-quote (gnus-simplify-subject subject))
- ;; Ignore words in parentheses.
- "\\([ \t]*([^\r\n]*)\\)*[ \t]*\\(\r\\|$\\)")
- "")
- )))
- (if backward
- (beginning-of-line)
- (end-of-line))
- (if (funcall func regexp nil t)
- (setq article
- (string-to-int
- (buffer-substring (match-beginning 1) (match-end 1)))))
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t)
- ;; This is the result.
- article
- ))
-
-(defun gnus-summary-search-forward (&optional unread subject)
- "Search for article forward.
-If 1st optional argument UNREAD is non-nil, only unread article is selected.
-If 2nd optional argument SUBJECT is non-nil, the article which has
-the same subject will be searched for."
- (gnus-summary-search-subject nil unread subject))
-
-(defun gnus-summary-search-backward (&optional unread subject)
- "Search for article backward.
-If 1st optional argument UNREAD is non-nil, only unread article is selected.
-If 2nd optional argument SUBJECT is non-nil, the article which has
-the same subject will be searched for."
- (gnus-summary-search-subject t unread subject))
-
-(defun gnus-summary-article-number ()
- "Return the Article number around point.
-If none, return current article number."
- (save-excursion
- (beginning-of-line)
- (if (looking-at ".[ \t]+\\([0-9]+\\):")
- (string-to-int
- (buffer-substring (match-beginning 1) (match-end 1)))
- ;; If search fail, return current article number.
- gnus-current-article
- )))
-
-(defun gnus-summary-subject-string ()
- "Return current subject string or nil if nothing."
- (save-excursion
- ;; It is possible to implement this function using
- ;; `gnus-summary-article-number' and `gnus-newsgroup-headers'.
- (beginning-of-line)
- ;; We have to take care of hidden lines.
- (if (looking-at ".[ \t]+[0-9]+:.\\[[^]\r\n]*\\][ \t]+\\([^\r\n]*\\)[\r\n]")
- (buffer-substring (match-beginning 1) (match-end 1)))
- ))
-
-(defun gnus-summary-goto-subject (article)
- "Move point to ARTICLE's subject."
- (interactive
- (list
- (string-to-int
- (completing-read "Article number: "
- (mapcar
- (function
- (lambda (headers)
- (list
- (int-to-string (nntp-header-number headers)))))
- gnus-newsgroup-headers)
- nil 'require-match))))
- (let ((current (point)))
- (goto-char (point-min))
- (or (and article (re-search-forward (format "^.[ \t]+%d:" article) nil t))
- (progn (goto-char current) nil))
- ))
-
-(defun gnus-summary-recenter ()
- "Center point in Summary window."
- ;; Scroll window so as to cursor comes center of Summary window
- ;; only when article is displayed.
- ;; Suggested by earle@mahendo.JPL.NASA.GOV (Greg Earle).
- ;; Recenter only when requested.
- ;; Subbested by popovich@park.cs.columbia.edu
- (and gnus-auto-center-summary
- (get-buffer-window gnus-article-buffer)
- (< (/ (- (window-height) 1) 2)
- (count-lines (point) (point-max)))
- (recenter (/ (- (window-height) 2) 2))))
-
-;; Walking around Group mode buffer.
-
-(defun gnus-summary-jump-to-group (newsgroup)
- "Move point to NEWSGROUP in Group mode buffer."
- ;; Keep update point of Group mode buffer if visible.
- (if (eq (current-buffer)
- (get-buffer gnus-group-buffer))
- (save-window-excursion
- ;; Take care of tree window mode.
- (if (get-buffer-window gnus-group-buffer)
- (pop-to-buffer gnus-group-buffer))
- (gnus-group-jump-to-group newsgroup))
- (save-excursion
- ;; Take care of tree window mode.
- (if (get-buffer-window gnus-group-buffer)
- (pop-to-buffer gnus-group-buffer)
- (set-buffer gnus-group-buffer))
- (gnus-group-jump-to-group newsgroup))))
-
-(defun gnus-summary-next-group (no-article)
- "Exit current newsgroup and then select next unread newsgroup.
-If prefix argument NO-ARTICLE is non-nil, no article is selected initially."
- (interactive "P")
- ;; Make sure Group mode buffer point is on current newsgroup.
- (gnus-summary-jump-to-group gnus-newsgroup-name)
- (let ((group (gnus-summary-search-group)))
- (if (null group)
- (progn
- (message "Exiting %s..." gnus-newsgroup-name)
- (gnus-summary-exit)
- (message ""))
- (message "Selecting %s..." group)
- (gnus-summary-exit t) ;Exit Summary mode temporary.
- ;; We are now in Group mode buffer.
- ;; Make sure Group mode buffer point is on GROUP.
- (gnus-summary-jump-to-group group)
- (gnus-summary-read-group group nil no-article)
- (or (eq (current-buffer)
- (get-buffer gnus-summary-buffer))
- (eq gnus-auto-select-next t)
- ;; Expected newsgroup has nothing to read since the articles
- ;; are marked as read by cross-referencing. So, try next
- ;; newsgroup. (Make sure we are in Group mode buffer now.)
- (and (eq (current-buffer)
- (get-buffer gnus-group-buffer))
- (gnus-group-group-name)
- (gnus-summary-read-group
- (gnus-group-group-name) nil no-article))
- )
- )))
-
-(defun gnus-summary-prev-group (no-article)
- "Exit current newsgroup and then select previous unread newsgroup.
-If prefix argument NO-ARTICLE is non-nil, no article is selected initially."
- (interactive "P")
- ;; Make sure Group mode buffer point is on current newsgroup.
- (gnus-summary-jump-to-group gnus-newsgroup-name)
- (let ((group (gnus-summary-search-group t)))
- (if (null group)
- (progn
- (message "Exiting %s..." gnus-newsgroup-name)
- (gnus-summary-exit)
- (message ""))
- (message "Selecting %s..." group)
- (gnus-summary-exit t) ;Exit Summary mode temporary.
- ;; We are now in Group mode buffer.
- ;; We have to adjust point of Group mode buffer because current
- ;; point is moved to next unread newsgroup by exiting.
- (gnus-summary-jump-to-group group)
- (gnus-summary-read-group group nil no-article)
- (or (eq (current-buffer)
- (get-buffer gnus-summary-buffer))
- (eq gnus-auto-select-next t)
- ;; Expected newsgroup has nothing to read since the articles
- ;; are marked as read by cross-referencing. So, try next
- ;; newsgroup. (Make sure we are in Group mode buffer now.)
- (and (eq (current-buffer)
- (get-buffer gnus-group-buffer))
- (gnus-summary-search-group t)
- (gnus-summary-read-group
- (gnus-summary-search-group t) nil no-article))
- )
- )))
-
-;; Walking around summary lines.
-
-(defun gnus-summary-next-subject (n &optional unread)
- "Go to Nth following summary line.
-If optional argument UNREAD is non-nil, only unread article is selected."
- (interactive "p")
- (while (and (> n 1)
- (gnus-summary-search-forward unread))
- (setq n (1- n)))
- (cond ((gnus-summary-search-forward unread)
- (gnus-summary-recenter))
- (unread
- (message "No more unread articles"))
- (t
- (message "No more articles"))
- ))
-
-(defun gnus-summary-next-unread-subject (n)
- "Go to Nth following unread summary line."
- (interactive "p")
- (gnus-summary-next-subject n t))
-
-(defun gnus-summary-prev-subject (n &optional unread)
- "Go to Nth previous summary line.
-If optional argument UNREAD is non-nil, only unread article is selected."
- (interactive "p")
- (while (and (> n 1)
- (gnus-summary-search-backward unread))
- (setq n (1- n)))
- (cond ((gnus-summary-search-backward unread)
- (gnus-summary-recenter))
- (unread
- (message "No more unread articles"))
- (t
- (message "No more articles"))
- ))
-
-(defun gnus-summary-prev-unread-subject (n)
- "Go to Nth previous unread summary line."
- (interactive "p")
- (gnus-summary-prev-subject n t))
-
-;; Walking around summary lines with displaying articles.
-
-(defun gnus-summary-expand-window ()
- "Expand Summary window to show headers full window."
- (interactive)
- (gnus-configure-windows 'summary)
- (pop-to-buffer gnus-summary-buffer))
-
-(defun gnus-summary-display-article (article &optional all-header)
- "Display ARTICLE in Article buffer."
- (if (null article)
- nil
- (gnus-configure-windows 'article)
- (pop-to-buffer gnus-summary-buffer)
- (gnus-article-prepare article all-header)
- (gnus-summary-recenter)
- (gnus-summary-set-mode-line)
- (run-hooks 'gnus-select-article-hook)
- ;; Successfully display article.
- t
- ))
-
-(defun gnus-summary-select-article (&optional all-headers force)
- "Select the current article.
-Optional first argument ALL-HEADERS is non-nil, show all header fields.
-Optional second argument FORCE is nil, the article is only selected
-again when current header does not match with ALL-HEADERS option."
- (let ((article (gnus-summary-article-number))
- (all-headers (not (not all-headers)))) ;Must be T or NIL.
- (if (or (null gnus-current-article)
- (/= article gnus-current-article)
- (and force (not (eq all-headers gnus-have-all-headers))))
- ;; The selected one is different from that of the current article.
- (gnus-summary-display-article article all-headers)
- (gnus-configure-windows 'article)
- (pop-to-buffer gnus-summary-buffer))
- ))
-
-(defun gnus-summary-set-current-mark (&optional current-mark)
- "Put `+' at the current article.
-Optional argument specifies CURRENT-MARK instead of `+'."
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (let ((buffer-read-only nil))
- (goto-char (point-min))
- ;; First of all clear mark at last article.
- (if (re-search-forward "^.[ \t]+[0-9]+:[^ \t]" nil t)
- (progn
- (delete-char -1)
- (insert " ")
- (goto-char (point-min))))
- (if (re-search-forward (format "^.[ \t]+%d:" gnus-current-article) nil t)
- (progn
- (delete-char 1)
- (insert (or current-mark "+"))))
- )))
-
-;;(defun gnus-summary-next-article (unread &optional subject)
-;; "Select article after current one.
-;;If argument UNREAD is non-nil, only unread article is selected."
-;; (interactive "P")
-;; (cond ((gnus-summary-display-article
-;; (gnus-summary-search-forward unread subject)))
-;; (unread
-;; (message "No more unread articles"))
-;; (t
-;; (message "No more articles"))
-;; ))
-
-(defun gnus-summary-next-article (unread &optional subject)
- "Select article after current one.
-If argument UNREAD is non-nil, only unread article is selected."
- (interactive "P")
- (let ((header nil))
- (cond ((gnus-summary-display-article
- (gnus-summary-search-forward unread subject)))
- ((and subject
- gnus-auto-select-same
- (gnus-set-difference gnus-newsgroup-unreads
- gnus-newsgroup-marked)
- (memq this-command
- '(gnus-summary-next-unread-article
- gnus-summary-next-page
- gnus-summary-kill-same-subject-and-select
- ;;gnus-summary-next-article
- ;;gnus-summary-next-same-subject
- ;;gnus-summary-next-unread-same-subject
- )))
- ;; Wrap article pointer if there are unread articles.
- ;; Hook function, such as gnus-summary-rmail-digest, may
- ;; change current buffer, so need check.
- (let ((buffer (current-buffer))
- (last-point (point)))
- ;; No more articles with same subject, so jump to the first
- ;; unread article.
- (gnus-summary-first-unread-article)
- ;;(and (eq buffer (current-buffer))
- ;; (= (point) last-point)
- ;; ;; Ignore given SUBJECT, and try again.
- ;; (gnus-summary-next-article unread nil))
- (and (eq buffer (current-buffer))
- (< (point) last-point)
- (message "Wrapped"))
- ))
- ((and gnus-auto-extend-newsgroup
- (not unread) ;Not unread only
- (not subject) ;Only if subject is not specified.
- (setq header (gnus-more-header-forward)))
- ;; Extend to next article if possible.
- ;; Basic ideas by himacdonald@watdragon.waterloo.edu
- (gnus-extend-newsgroup header nil)
- ;; Threads feature must be turned off.
- (let ((buffer-read-only nil))
- (goto-char (point-max))
- (gnus-summary-prepare-threads (list header) 0))
- (gnus-summary-goto-article gnus-newsgroup-end))
- (t
- ;; Select next newsgroup automatically if requested.
- (let ((cmd (aref (this-command-keys) 0))
- (group (gnus-summary-search-group))
- (auto-select
- (and gnus-auto-select-next
- ;;(null (gnus-set-difference gnus-newsgroup-unreads
- ;; gnus-newsgroup-marked))
- (memq this-command
- '(gnus-summary-next-unread-article
- gnus-summary-next-article
- gnus-summary-next-page
- gnus-summary-next-same-subject
- gnus-summary-next-unread-same-subject
- gnus-summary-kill-same-subject
- gnus-summary-kill-same-subject-and-select
- ))
- ;; Ignore characters typed ahead.
- (not (input-pending-p))
- )))
- ;; Keep just the event type of CMD.
- (if (listp cmd)
- (setq cmd (car cmd)))
- (message "No more%s articles%s"
- (if unread " unread" "")
- (if (and auto-select
- (not (eq gnus-auto-select-next 'quietly)))
- (if group
- (format " (Type %s for %s [%d])"
- (single-key-description cmd)
- group
- (nth 1 (gnus-gethash group
- gnus-unread-hashtb)))
- (format " (Type %s to exit %s)"
- (single-key-description cmd)
- gnus-newsgroup-name))
- ""))
- ;; Select next unread newsgroup automagically.
- (cond ((and auto-select
- (eq gnus-auto-select-next 'quietly))
- ;; Select quietly.
- (gnus-summary-next-group nil))
- (auto-select
- ;; Confirm auto selection.
- (let* ((event (read-event))
- (type
- (if (listp event)
- (car event)
- event)))
- (if (and (eq event type) (eq event cmd))
- (gnus-summary-next-group nil)
- (setq unread-command-events (list event)))))
- )
- ))
- )))
-
-(defun gnus-summary-next-unread-article ()
- "Select unread article after current one."
- (interactive)
- (gnus-summary-next-article t (and gnus-auto-select-same
- (gnus-summary-subject-string))))
-
-(defun gnus-summary-prev-article (unread &optional subject)
- "Select article before current one.
-If argument UNREAD is non-nil, only unread article is selected."
- (interactive "P")
- (let ((header nil))
- (cond ((gnus-summary-display-article
- (gnus-summary-search-backward unread subject)))
- ((and subject
- gnus-auto-select-same
- (gnus-set-difference gnus-newsgroup-unreads
- gnus-newsgroup-marked)
- (memq this-command
- '(gnus-summary-prev-unread-article
- ;;gnus-summary-prev-page
- ;;gnus-summary-prev-article
- ;;gnus-summary-prev-same-subject
- ;;gnus-summary-prev-unread-same-subject
- )))
- ;; Ignore given SUBJECT, and try again.
- (gnus-summary-prev-article unread nil))
- (unread
- (message "No more unread articles"))
- ((and gnus-auto-extend-newsgroup
- (not subject) ;Only if subject is not specified.
- (setq header (gnus-more-header-backward)))
- ;; Extend to previous article if possible.
- ;; Basic ideas by himacdonald@watdragon.waterloo.edu
- (gnus-extend-newsgroup header t)
- (let ((buffer-read-only nil))
- (goto-char (point-min))
- (gnus-summary-prepare-threads (list header) 0))
- (gnus-summary-goto-article gnus-newsgroup-begin))
- (t
- (message "No more articles"))
- )))
-
-(defun gnus-summary-prev-unread-article ()
- "Select unread article before current one."
- (interactive)
- (gnus-summary-prev-article t (and gnus-auto-select-same
- (gnus-summary-subject-string))))
-
-(defun gnus-summary-next-page (lines)
- "Show next page of selected article.
-If end of article, select next article.
-Argument LINES specifies lines to be scrolled up."
- (interactive "P")
- (let ((article (gnus-summary-article-number))
- (endp nil))
- (if (or (null gnus-current-article)
- (/= article gnus-current-article))
- ;; Selected subject is different from current article's.
- (gnus-summary-display-article article)
- (gnus-configure-windows 'article)
- (pop-to-buffer gnus-summary-buffer)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (setq endp (gnus-article-next-page lines)))
- (cond ((and endp lines)
- (message "End of message"))
- ((and endp (null lines))
- (gnus-summary-next-unread-article)))
- )))
-
-(defun gnus-summary-prev-page (lines)
- "Show previous page of selected article.
-Argument LINES specifies lines to be scrolled down."
- (interactive "P")
- (let ((article (gnus-summary-article-number)))
- (if (or (null gnus-current-article)
- (/= article gnus-current-article))
- ;; Selected subject is different from current article's.
- (gnus-summary-display-article article)
- (gnus-configure-windows 'article)
- (pop-to-buffer gnus-summary-buffer)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (gnus-article-prev-page lines))
- )))
-
-(defun gnus-summary-scroll-up (lines)
- "Scroll up (or down) one line current article.
-Argument LINES specifies lines to be scrolled up (or down if negative)."
- (interactive "p")
- (gnus-summary-select-article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (cond ((> lines 0)
- (if (gnus-article-next-page lines)
- (message "End of message")))
- ((< lines 0)
- (gnus-article-prev-page (- 0 lines))))
- ))
-
-(defun gnus-summary-next-same-subject ()
- "Select next article which has the same subject as current one."
- (interactive)
- (gnus-summary-next-article nil (gnus-summary-subject-string)))
-
-(defun gnus-summary-prev-same-subject ()
- "Select previous article which has the same subject as current one."
- (interactive)
- (gnus-summary-prev-article nil (gnus-summary-subject-string)))
-
-(defun gnus-summary-next-unread-same-subject ()
- "Select next unread article which has the same subject as current one."
- (interactive)
- (gnus-summary-next-article t (gnus-summary-subject-string)))
-
-(defun gnus-summary-prev-unread-same-subject ()
- "Select previous unread article which has the same subject as current one."
- (interactive)
- (gnus-summary-prev-article t (gnus-summary-subject-string)))
-
-(defun gnus-summary-refer-parent-article (child)
- "Refer parent article of current article.
-If a prefix argument CHILD is non-nil, go back to the child article
-using internally maintained articles history.
-NOTE: This command may not work with `nnspool.el'."
- (interactive "P")
- (gnus-summary-select-article t t) ;Request all headers.
- (let ((referenced-id nil)) ;Message-id of parent or child article.
- (if child
- ;; Go back to child article using history.
- (gnus-summary-refer-article nil)
- (gnus-eval-in-buffer-window gnus-article-buffer
- ;; Look for parent Message-ID.
- ;; We cannot use gnus-current-headers to get references
- ;; because we may be looking at parent or referred article.
- (let ((references (gnus-fetch-field "References")))
- ;; Get the last message-id in the references.
- (and references
- (string-match "\\(<[^<>]+>\\)[^>]*\\'" references)
- (setq referenced-id
- (substring references
- (match-beginning 1) (match-end 1))))
- ))
- (if (stringp referenced-id)
- (gnus-summary-refer-article referenced-id)
- (error "No more parents"))
- )))
-
-(defun gnus-summary-refer-article (message-id)
- "Refer article specified by MESSAGE-ID.
-If the MESSAGE-ID is nil or an empty string, Message-ID is poped from
-internally maintained articles history.
-NOTE: This command may not work with `nnspool.el' nor `mhspool.el'."
- (interactive "sMessage-ID: ")
- ;; Make sure that this command depends on the fact that article
- ;; related information is not updated when an article is retrieved
- ;; by Message-ID.
- (gnus-summary-select-article t t) ;Request all headers.
- (if (and (stringp message-id)
- (> (length message-id) 0))
- (gnus-eval-in-buffer-window gnus-article-buffer
- ;; Construct the correct Message-ID if necessary.
- ;; Suggested by tale@pawl.rpi.edu.
- (or (string-match "^<" message-id)
- (setq message-id (concat "<" message-id)))
- (or (string-match ">$" message-id)
- (setq message-id (concat message-id ">")))
- ;; Push current message-id on history.
- ;; We cannot use gnus-current-headers to get current
- ;; message-id because we may be looking at parent or referred
- ;; article.
- (let ((current (gnus-fetch-field "Message-ID")))
- (or (equal current message-id) ;Nothing to do.
- (equal current (car gnus-current-history))
- (setq gnus-current-history
- (cons current gnus-current-history)))
- ))
- ;; Pop message-id from history.
- (setq message-id (car gnus-current-history))
- (setq gnus-current-history (cdr gnus-current-history)))
- (if (stringp message-id)
- ;; Retrieve article by message-id. This may not work with
- ;; nnspool nor mhspool.
- (gnus-article-prepare message-id t)
- (error "No such references"))
- )
-
-(defun gnus-summary-next-digest (n)
- "Move to head of Nth next digested message."
- (interactive "p")
- (gnus-summary-select-article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (gnus-article-next-digest (or n 1))
- ))
-
-(defun gnus-summary-prev-digest (n)
- "Move to head of Nth previous digested message."
- (interactive "p")
- (gnus-summary-select-article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (gnus-article-prev-digest (or n 1))))
-
-(defun gnus-summary-first-unread-article ()
- "Select first unread article. Return non-nil if successfully selected."
- (interactive)
- (let ((begin (point)))
- (goto-char (point-min))
- (if (re-search-forward "^ [ \t]+[0-9]+:" nil t)
- (gnus-summary-display-article (gnus-summary-article-number))
- ;; If there is no unread articles, stay there.
- (goto-char begin)
- ;;(gnus-summary-display-article (gnus-summary-article-number))
- (message "No more unread articles")
- nil
- )
- ))
-
-(defun gnus-summary-isearch-article ()
- "Do incremental search forward on current article."
- (interactive)
- (gnus-summary-select-article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (isearch-forward)))
-
-(defun gnus-summary-search-article-forward (regexp)
- "Search for an article containing REGEXP forward.
-`gnus-select-article-hook' is not called for articles examined
-by searching search."
- (interactive
- (list (read-string
- (concat "Search forward (regexp): "
- (if gnus-last-search-regexp
- (concat "(default " gnus-last-search-regexp ") "))))))
- (if (string-equal regexp "")
- (setq regexp (or gnus-last-search-regexp ""))
- (setq gnus-last-search-regexp regexp))
- (if (gnus-summary-search-article regexp nil)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (recenter 0)
- ;;(sit-for 1)
- )
- (error "Search failed: \"%s\"" regexp)
- ))
-
-(defun gnus-summary-search-article-backward (regexp)
- "Search for an article containing REGEXP backward.
-`gnus-select-article-hook' is not called for articles examined
-by searching search."
- (interactive
- (list (read-string
- (concat "Search backward (regexp): "
- (if gnus-last-search-regexp
- (concat "(default " gnus-last-search-regexp ") "))))))
- (if (string-equal regexp "")
- (setq regexp (or gnus-last-search-regexp ""))
- (setq gnus-last-search-regexp regexp))
- (if (gnus-summary-search-article regexp t)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (recenter 0)
- ;;(sit-for 1)
- )
- (error "Search failed: \"%s\"" regexp)
- ))
-
-(defun gnus-summary-search-article (regexp &optional backward)
- "Search for an article containing REGEXP.
-Optional argument BACKWARD means do search for backward.
-`gnus-select-article-hook' is not called for articles examined
-by searching search."
- (let ((gnus-select-article-hook nil) ;Disable hook.
- (gnus-mark-article-hook nil) ;Inhibit marking as read.
- (re-search
- (if backward
- (function re-search-backward) (function re-search-forward)))
- (found nil)
- (last nil))
- ;; Hidden thread subtrees must be searched for ,too.
- (gnus-summary-show-all-threads)
- ;; First of all, search current article.
- ;; We don't want to read article again from NNTP server nor reset
- ;; current point.
- (gnus-summary-select-article)
- (message "Searching article: %d..." gnus-current-article)
- (setq last gnus-current-article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (save-restriction
- (widen)
- ;; Begin search from current point.
- (setq found (funcall re-search regexp nil t))))
- ;; Then search next articles.
- (while (and (not found)
- (gnus-summary-display-article
- (gnus-summary-search-subject backward nil nil)))
- (message "Searching article: %d..." gnus-current-article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (save-restriction
- (widen)
- (goto-char (if backward (point-max) (point-min)))
- (setq found (funcall re-search regexp nil t)))
- ))
- (message "")
- ;; Adjust article pointer.
- (or (eq last gnus-current-article)
- (setq gnus-last-article last))
- ;; Return T if found such article.
- found
- ))
-
-(defun gnus-summary-execute-command (field regexp command &optional backward)
- "If FIELD of article header matches REGEXP, execute a COMMAND string.
-If FIELD is an empty string (or nil), entire article body is searched for.
-If optional (prefix) argument BACKWARD is non-nil, do backward instead."
- (interactive
- (list (let ((completion-ignore-case t))
- (completing-read "Field name: "
- '(("Number")("Subject")("From")
- ("Lines")("Date")("Id")
- ("Xref")("References"))
- nil 'require-match))
- (read-string "Regexp: ")
- (read-key-sequence "Command: ")
- current-prefix-arg))
- ;; Hidden thread subtrees must be searched for ,too.
- (gnus-summary-show-all-threads)
- ;; We don't want to change current point nor window configuration.
- (save-excursion
- (save-window-excursion
- (message "Executing %s..." (key-description command))
- ;; We'd like to execute COMMAND interactively so as to give arguments.
- (gnus-execute field regexp
- (` (lambda ()
- (call-interactively '(, (key-binding command)))))
- backward)
- (message "Executing %s...done" (key-description command)))))
-
-(defun gnus-summary-beginning-of-article ()
- "Go to beginning of article body."
- (interactive)
- (gnus-summary-select-article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (widen)
- (beginning-of-buffer)
- (if gnus-break-pages
- (gnus-narrow-to-page))
- ))
-
-(defun gnus-summary-end-of-article ()
- "Go to end of article body."
- (interactive)
- (gnus-summary-select-article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (widen)
- (end-of-buffer)
- (if gnus-break-pages
- (gnus-narrow-to-page))
- ))
-
-(defun gnus-summary-goto-article (article &optional all-headers)
- "Read article number ARTICLE if it exists.
-Optional argument ALL-HEADERS means show the full header."
- (interactive
- (list
- (string-to-int
- (completing-read "Article number: "
- (mapcar
- (function
- (lambda (headers)
- (list
- (int-to-string (nntp-header-number headers)))))
- gnus-newsgroup-headers)
- nil 'require-match))))
- (if (gnus-summary-goto-subject article)
- (gnus-summary-display-article article all-headers)))
-
-(defun gnus-summary-goto-last-article ()
- "Go to last subject line."
- (interactive)
- (if gnus-last-article
- (gnus-summary-goto-article gnus-last-article)))
-
-(defun gnus-summary-show-article ()
- "Force to show current article."
- (interactive)
- ;; The following is a trick to force to read the current article again.
- (setq gnus-have-all-headers (not gnus-have-all-headers))
- (gnus-summary-select-article (not gnus-have-all-headers) t))
-
-(defun gnus-summary-toggle-header (arg)
- "Show original header if pruned header currently shown, or vice versa.
-With arg, show original header iff arg is positive."
- (interactive "P")
- ;; Variable gnus-show-all-headers must be NIL to toggle really.
- (let ((gnus-show-all-headers nil)
- (all-headers
- (if (null arg) (not gnus-have-all-headers)
- (> (prefix-numeric-value arg) 0))))
- (gnus-summary-select-article all-headers t)))
-
-(defun gnus-summary-show-all-headers ()
- "Show original article header."
- (interactive)
- (gnus-summary-select-article t t))
-
-(defun gnus-summary-toggle-mime (arg)
- "Toggle MIME processing.
-With arg, turn MIME processing on iff arg is positive."
- (interactive "P")
- (setq gnus-show-mime
- (if (null arg) (not gnus-show-mime)
- (> (prefix-numeric-value arg) 0)))
- ;; The following is a trick to force to read the current article again.
- (setq gnus-have-all-headers (not gnus-have-all-headers))
- (gnus-summary-select-article (not gnus-have-all-headers) t))
-
-(defun gnus-summary-stop-page-breaking ()
- "Stop page breaking by linefeed temporary (widen article buffer)."
- (interactive)
- (gnus-summary-select-article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (widen)
- ))
-
-(defun gnus-summary-kill-same-subject-and-select (unmark)
- "Mark articles which has the same subject as read, and then select next.
-If argument UNMARK is positive, remove any kinds of marks.
-If argument UNMARK is negative, mark articles as unread instead."
- (interactive "P")
- (if unmark
- (setq unmark (prefix-numeric-value unmark)))
- (let ((count
- (gnus-summary-mark-same-subject
- (gnus-summary-subject-string) unmark)))
- ;; Select next unread article. If auto-select-same mode, should
- ;; select the first unread article.
- (gnus-summary-next-article t (and gnus-auto-select-same
- (gnus-summary-subject-string)))
- (message "%d articles are marked as %s"
- count (if unmark "unread" "read"))
- ))
-
-(defun gnus-summary-kill-same-subject (unmark)
- "Mark articles which has the same subject as read.
-If argument UNMARK is positive, remove any kinds of marks.
-If argument UNMARK is negative, mark articles as unread instead."
- (interactive "P")
- (if unmark
- (setq unmark (prefix-numeric-value unmark)))
- (let ((count
- (gnus-summary-mark-same-subject
- (gnus-summary-subject-string) unmark)))
- ;; If marked as read, go to next unread subject.
- (if (null unmark)
- ;; Go to next unread subject.
- (gnus-summary-next-subject 1 t))
- (message "%d articles are marked as %s"
- count (if unmark "unread" "read"))
- ))
-
-(defun gnus-summary-mark-same-subject (subject &optional unmark)
- "Mark articles with same SUBJECT as read, and return marked number.
-If optional argument UNMARK is positive, remove any kinds of marks.
-If optional argument UNMARK is negative, mark articles as unread instead."
- (let ((count 1))
- (save-excursion
- (cond ((null unmark)
- (gnus-summary-mark-as-read nil "K"))
- ((> unmark 0)
- (gnus-summary-mark-as-unread nil t))
- (t
- (gnus-summary-mark-as-unread)))
- (while (and subject
- (gnus-summary-search-forward nil subject))
- (cond ((null unmark)
- (gnus-summary-mark-as-read nil "K"))
- ((> unmark 0)
- (gnus-summary-mark-as-unread nil t))
- (t
- (gnus-summary-mark-as-unread)))
- (setq count (1+ count))
- ))
- ;; Hide killed thread subtrees. Does not work properly always.
- ;;(and (null unmark)
- ;; gnus-thread-hide-killed
- ;; (gnus-summary-hide-thread))
- ;; Return number of articles marked as read.
- count
- ))
-
-(defun gnus-summary-mark-as-unread-forward (count)
- "Mark current article as unread, and then go forward.
-Argument COUNT specifies number of articles marked as unread."
- (interactive "p")
- (while (> count 0)
- (gnus-summary-mark-as-unread nil nil)
- (gnus-summary-next-subject 1 nil)
- (setq count (1- count))))
-
-(defun gnus-summary-mark-as-unread-backward (count)
- "Mark current article as unread, and then go backward.
-Argument COUNT specifies number of articles marked as unread."
- (interactive "p")
- (while (> count 0)
- (gnus-summary-mark-as-unread nil nil)
- (gnus-summary-prev-subject 1 nil)
- (setq count (1- count))))
-
-(defun gnus-summary-mark-as-unread (&optional article clear-mark)
- "Mark current article as unread.
-Optional 1st argument ARTICLE specifies article number to be marked as unread.
-Optional 2nd argument CLEAR-MARK remove any kinds of mark."
- (save-excursion
- (set-buffer gnus-summary-buffer)
- ;; First of all, show hidden thread subtrees.
- (gnus-summary-show-thread)
- (let* ((buffer-read-only nil)
- (current (gnus-summary-article-number))
- (article (or article current)))
- (gnus-mark-article-as-unread article clear-mark)
- (if (or (eq article current)
- (gnus-summary-goto-subject article))
- (progn
- (beginning-of-line)
- (delete-char 1)
- (insert (if clear-mark " " "-"))))
- )))
-
-(defun gnus-summary-mark-as-read-forward (count)
- "Mark current article as read, and then go forward.
-Argument COUNT specifies number of articles marked as read."
- (interactive "p")
- (while (> count 0)
- (gnus-summary-mark-as-read)
- (gnus-summary-next-subject 1 'unread-only)
- (setq count (1- count))))
-
-(defun gnus-summary-mark-as-read-backward (count)
- "Mark current article as read, and then go backward.
-Argument COUNT specifies number of articles marked as read."
- (interactive "p")
- (while (> count 0)
- (gnus-summary-mark-as-read)
- (gnus-summary-prev-subject 1 'unread-only)
- (setq count (1- count))))
-
-(defun gnus-summary-mark-as-read (&optional article mark)
- "Mark current article as read.
-Optional 1st argument ARTICLE specifies article number to be marked as read.
-Optional 2nd argument MARK specifies a string inserted at beginning of line.
-Any kind of string (length 1) except for a space and `-' is ok."
- (save-excursion
- (set-buffer gnus-summary-buffer)
- ;; First of all, show hidden thread subtrees.
- (gnus-summary-show-thread)
- (let* ((buffer-read-only nil)
- (mark (or mark "D")) ;Default mark is `D'.
- (current (gnus-summary-article-number))
- (article (or article current)))
- (gnus-mark-article-as-read article)
- (if (or (eq article current)
- (gnus-summary-goto-subject article))
- (progn
- (beginning-of-line)
- (delete-char 1)
- (insert mark)))
- )))
-
-(defun gnus-summary-clear-mark-forward (count)
- "Remove current article's mark, and go forward.
-Argument COUNT specifies number of articles unmarked."
- (interactive "p")
- (while (> count 0)
- (gnus-summary-mark-as-unread nil t)
- (gnus-summary-next-subject 1 nil)
- (setq count (1- count))))
-
-(defun gnus-summary-clear-mark-backward (count)
- "Remove current article's mark, and go backward.
-Argument COUNT specifies number of articles unmarked."
- (interactive "p")
- (while (> count 0)
- (gnus-summary-mark-as-unread nil t)
- (gnus-summary-prev-subject 1 nil)
- (setq count (1- count))))
-
-(defun gnus-summary-delete-marked-as-read ()
- "Delete summary lines for articles that are marked as read."
- (interactive)
- (if gnus-newsgroup-unreads
- (let ((buffer-read-only nil))
- (save-excursion
- (goto-char (point-min))
- (delete-non-matching-lines "^[- ]"))
- ;; Adjust point.
- (if (eobp)
- (gnus-summary-prev-subject 1)
- (beginning-of-line)
- (search-forward ":" nil t)))
- ;; It is not so good idea to make the buffer empty.
- (message "All articles are marked as read")
- ))
-
-(defun gnus-summary-delete-marked-with (marks)
- "Delete lines which are marked with MARKS (e.g. \"DK\")."
- (interactive "sMarks: ")
- (let ((buffer-read-only nil))
- (save-excursion
- (goto-char (point-min))
- (delete-matching-lines (concat "^[" marks "]")))
- ;; Adjust point.
- (or (zerop (buffer-size))
- (if (eobp)
- (gnus-summary-prev-subject 1)
- (beginning-of-line)
- (search-forward ":" nil t)))
- ))
-
-;; Thread-based commands.
-
-(defun gnus-summary-toggle-threads (arg)
- "Toggle showing conversation threads.
-With arg, turn showing conversation threads on iff arg is positive."
- (interactive "P")
- (let ((current (gnus-summary-article-number)))
- (setq gnus-show-threads
- (if (null arg) (not gnus-show-threads)
- (> (prefix-numeric-value arg) 0)))
- (gnus-summary-prepare)
- (gnus-summary-goto-subject current)
- ))
-
-(defun gnus-summary-show-all-threads ()
- "Show all thread subtrees."
- (interactive)
- (if gnus-show-threads
- (save-excursion
- (let ((buffer-read-only nil))
- (subst-char-in-region (point-min) (point-max) ?\^M ?\n t)
- ))))
-
-(defun gnus-summary-show-thread ()
- "Show thread subtrees."
- (interactive)
- (if gnus-show-threads
- (save-excursion
- (let ((buffer-read-only nil))
- (subst-char-in-region (progn
- (beginning-of-line) (point))
- (progn
- (end-of-line) (point))
- ?\^M ?\n t)
- ))))
-
-(defun gnus-summary-hide-all-threads ()
- "Hide all thread subtrees."
- (interactive)
- (if gnus-show-threads
- (save-excursion
- ;; Adjust cursor point.
- (goto-char (point-min))
- (search-forward ":" nil t)
- (let ((level (current-column)))
- (gnus-summary-hide-thread)
- (while (gnus-summary-search-forward)
- (and (>= level (current-column))
- (gnus-summary-hide-thread)))
- ))))
-
-(defun gnus-summary-hide-thread ()
- "Hide thread subtrees."
- (interactive)
- (if gnus-show-threads
- (save-excursion
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t)
- (let ((buffer-read-only nil)
- (init (point))
- (last (point))
- (level (current-column)))
- (while (and (gnus-summary-search-forward)
- (< level (current-column)))
- ;; Interested in lower levels.
- (if (< level (current-column))
- (progn
- (setq last (point))
- ))
- )
- (subst-char-in-region init last ?\n ?\^M t)
- ))))
-
-(defun gnus-summary-next-thread (n)
- "Go to the same level next thread.
-Argument N specifies the number of threads."
- (interactive "p")
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t)
- (let ((init (point))
- (last (point))
- (level (current-column)))
- (while (and (> n 0)
- (gnus-summary-search-forward)
- (<= level (current-column)))
- ;; We have to skip lower levels.
- (if (= level (current-column))
- (progn
- (setq last (point))
- (setq n (1- n))
- ))
- )
- ;; Return non-nil if successfully move to the next.
- (prog1 (not (= init last))
- (goto-char last))
- ))
-
-(defun gnus-summary-prev-thread (n)
- "Go to the same level previous thread.
-Argument N specifies the number of threads."
- (interactive "p")
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t)
- (let ((init (point))
- (last (point))
- (level (current-column)))
- (while (and (> n 0)
- (gnus-summary-search-backward)
- (<= level (current-column)))
- ;; We have to skip lower levels.
- (if (= level (current-column))
- (progn
- (setq last (point))
- (setq n (1- n))
- ))
- )
- ;; Return non-nil if successfully move to the previous.
- (prog1 (not (= init last))
- (goto-char last))
- ))
-
-(defun gnus-summary-down-thread (d)
- "Go downward current thread.
-Argument D specifies the depth goes down."
- (interactive "p")
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t)
- (let ((last (point))
- (level (current-column)))
- (while (and (> d 0)
- (gnus-summary-search-forward)
- (<= level (current-column))) ;<= can be <. Which do you like?
- ;; We have to skip the same levels.
- (if (< level (current-column))
- (progn
- (setq last (point))
- (setq level (current-column))
- (setq d (1- d))
- ))
- )
- (goto-char last)
- ))
-
-(defun gnus-summary-up-thread (d)
- "Go upward current thread.
-Argument D specifies the depth goes up."
- (interactive "p")
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t)
- (let ((last (point))
- (level (current-column)))
- (while (and (> d 0)
- (gnus-summary-search-backward))
- ;; We have to skip the same levels.
- (if (> level (current-column))
- (progn
- (setq last (point))
- (setq level (current-column))
- (setq d (1- d))
- ))
- )
- (goto-char last)
- ))
-
-(defun gnus-summary-kill-thread (unmark)
- "Mark articles under current thread as read.
-If argument UNMARK is positive, remove any kinds of marks.
-If argument UNMARK is negative, mark articles as unread instead."
- (interactive "P")
- (if unmark
- (setq unmark (prefix-numeric-value unmark)))
- ;; Adjust cursor point.
- (beginning-of-line)
- (search-forward ":" nil t)
- (save-excursion
- (let ((level (current-column)))
- ;; Mark current article.
- (cond ((null unmark)
- (gnus-summary-mark-as-read nil "K"))
- ((> unmark 0)
- (gnus-summary-mark-as-unread nil t))
- (t
- (gnus-summary-mark-as-unread))
- )
- ;; Mark following articles.
- (while (and (gnus-summary-search-forward)
- (< level (current-column)))
- (cond ((null unmark)
- (gnus-summary-mark-as-read nil "K"))
- ((> unmark 0)
- (gnus-summary-mark-as-unread nil t))
- (t
- (gnus-summary-mark-as-unread))
- ))
- ))
- ;; Hide killed subtrees.
- (and (null unmark)
- gnus-thread-hide-killed
- (gnus-summary-hide-thread))
- ;; If marked as read, go to next unread subject.
- (if (null unmark)
- ;; Go to next unread subject.
- (gnus-summary-next-subject 1 t))
- )
-
-(defun gnus-summary-toggle-truncation (arg)
- "Toggle truncation of summary lines.
-With arg, turn line truncation on iff arg is positive."
- (interactive "P")
- (setq truncate-lines
- (if (null arg) (not truncate-lines)
- (> (prefix-numeric-value arg) 0)))
- (redraw-display))
-
-(defun gnus-summary-sort-by-number (reverse)
- "Sort Summary buffer by article number.
-Argument REVERSE means reverse order."
- (interactive "P")
- (gnus-summary-keysort-summary
- (function <)
- (function
- (lambda (a)
- (nntp-header-number a)))
- reverse
- ))
-
-(defun gnus-summary-sort-by-author (reverse)
- "Sort Summary buffer by author name alphabetically.
-If case-fold-search is non-nil, case of letters is ignored.
-Argument REVERSE means reverse order."
- (interactive "P")
- (gnus-summary-keysort-summary
- (function string-lessp)
- (function
- (lambda (a)
- (if case-fold-search
- (downcase (nntp-header-from a))
- (nntp-header-from a))))
- reverse
- ))
-
-(defun gnus-summary-sort-by-subject (reverse)
- "Sort Summary buffer by subject alphabetically. `Re:'s are ignored.
-If case-fold-search is non-nil, case of letters is ignored.
-Argument REVERSE means reverse order."
- (interactive "P")
- (gnus-summary-keysort-summary
- (function string-lessp)
- (function
- (lambda (a)
- (if case-fold-search
- (downcase (gnus-simplify-subject (nntp-header-subject a) 're-only))
- (gnus-simplify-subject (nntp-header-subject a) 're-only))))
- reverse
- ))
-
-(defun gnus-summary-sort-by-date (reverse)
- "Sort Summary buffer by date.
-Argument REVERSE means reverse order."
- (interactive "P")
- (gnus-summary-keysort-summary
- (function string-lessp)
- (function
- (lambda (a)
- (gnus-sortable-date (nntp-header-date a))))
- reverse
- ))
-
-(defun gnus-summary-keysort-summary (predicate key &optional reverse)
- "Sort Summary buffer by PREDICATE using a value passed by KEY.
-Optional argument REVERSE means reverse order."
- (let ((current (gnus-summary-article-number)))
- (gnus-keysort-headers predicate key reverse)
- (gnus-summary-prepare)
- (gnus-summary-goto-subject current)
- ))
-
-(defun gnus-summary-sort-summary (predicate &optional reverse)
- "Sort Summary buffer by PREDICATE.
-Optional argument REVERSE means reverse order."
- (let ((current (gnus-summary-article-number)))
- (gnus-sort-headers predicate reverse)
- (gnus-summary-prepare)
- (gnus-summary-goto-subject current)
- ))
-
-(defun gnus-summary-reselect-current-group (show-all)
- "Once exit and then reselect the current newsgroup.
-Prefix argument SHOW-ALL means to select all articles."
- (interactive "P")
- (let ((current-subject (gnus-summary-article-number)))
- (gnus-summary-exit t)
- ;; We have to adjust the point of Group mode buffer because the
- ;; current point was moved to the next unread newsgroup by
- ;; exiting.
- (gnus-summary-jump-to-group gnus-newsgroup-name)
- (gnus-group-read-group show-all t)
- (gnus-summary-goto-subject current-subject)
- ))
-
-(defun gnus-summary-caesar-message (rotnum)
- "Caesar rotates all letters of current message by 13/47 places.
-With prefix arg, specifies the number of places to rotate each letter forward.
-Caesar rotates Japanese letters by 47 places in any case."
- (interactive "P")
- (gnus-summary-select-article)
- (gnus-overload-functions)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (save-restriction
- (widen)
- ;; We don't want to jump to the beginning of the message.
- ;; `save-excursion' does not do its job.
- (move-to-window-line 0)
- (let ((last (point)))
- (news-caesar-buffer-body rotnum)
- (goto-char last)
- (recenter 0)
- ))
- ))
-
-(defun gnus-summary-rmail-digest ()
- "Run RMAIL on current digest article.
-`gnus-select-digest-hook' will be called with no arguments, if that
-value is non-nil. It is possible to modify the article so that Rmail
-can work with it.
-`gnus-rmail-digest-hook' will be called with no arguments, if that value
-is non-nil. The hook is intended to customize Rmail mode."
- (interactive)
- (gnus-summary-select-article)
- (require 'rmail)
- (let ((artbuf gnus-article-buffer)
- (digbuf (get-buffer-create gnus-digest-buffer))
- (mail-header-separator ""))
- (set-buffer digbuf)
- (buffer-flush-undo (current-buffer))
- (setq buffer-read-only nil)
- (erase-buffer)
- (insert-buffer-substring artbuf)
- (run-hooks 'gnus-select-digest-hook)
- (gnus-convert-article-to-rmail)
- (goto-char (point-min))
- ;; Rmail initializations.
- (rmail-insert-rmail-file-header)
- (rmail-mode)
- (rmail-set-message-counters)
- (rmail-show-message)
- (condition-case ()
- (progn
- (undigestify-rmail-message)
- (rmail-expunge) ;Delete original message.
- ;; File name is meaningless but `save-buffer' requires it.
- (setq buffer-file-name "GNUS Digest")
- (setq mode-line-buffer-identification
- (concat "Digest: "
- (nntp-header-subject gnus-current-headers)))
- ;; There is no need to write this buffer to a file.
- (make-local-variable 'write-file-hooks)
- (setq write-file-hooks
- (list (function
- (lambda ()
- (set-buffer-modified-p nil)
- (message "(No changes need to be saved)")
- 'no-need-to-write-this-buffer))))
- ;; Default file name saving digest messages.
- (setq rmail-default-rmail-file
- (funcall gnus-rmail-save-name
- gnus-newsgroup-name
- gnus-current-headers
- gnus-newsgroup-last-rmail
- ))
- (setq rmail-default-file
- (funcall gnus-mail-save-name
- gnus-newsgroup-name
- gnus-current-headers
- gnus-newsgroup-last-mail
- ))
- ;; Prevent generating new buffer named ***<N> each time.
- (setq rmail-summary-buffer
- (get-buffer-create gnus-digest-summary-buffer))
- (run-hooks 'gnus-rmail-digest-hook)
- ;; Take all windows safely.
- (gnus-configure-windows '(1 0 0))
- (pop-to-buffer gnus-group-buffer)
- ;; Use Summary Article windows for Digest summary and
- ;; Digest buffers.
- (if gnus-digest-show-summary
- (let ((gnus-summary-buffer gnus-digest-summary-buffer)
- (gnus-article-buffer gnus-digest-buffer))
- (gnus-configure-windows 'article)
- (pop-to-buffer gnus-digest-buffer)
- (rmail-summary)
- (pop-to-buffer gnus-digest-summary-buffer)
- (message (substitute-command-keys
- "Type \\[rmail-summary-quit] to return to GNUS")))
- (let ((gnus-summary-buffer gnus-digest-buffer))
- (gnus-configure-windows 'summary)
- (pop-to-buffer gnus-digest-buffer)
- (message (substitute-command-keys
- "Type \\[rmail-quit] to return to GNUS")))
- )
- ;; Move the buffers to the end of buffer list.
- (bury-buffer gnus-article-buffer)
- (bury-buffer gnus-group-buffer)
- (bury-buffer gnus-digest-summary-buffer)
- (bury-buffer gnus-digest-buffer))
- (error (set-buffer-modified-p nil)
- (kill-buffer digbuf)
- ;; This command should not signal an error because the
- ;; command is called from hooks.
- (ding) (message "Article is not a digest")))
- ))
-
-(defun gnus-summary-save-article ()
- "Save this article using default saver function.
-The variable `gnus-default-article-saver' specifies the saver function."
- (interactive)
- (gnus-summary-select-article gnus-save-all-headers gnus-save-all-headers)
- (if gnus-default-article-saver
- (call-interactively gnus-default-article-saver)
- (error "No default saver is defined.")))
-
-(defun gnus-summary-save-in-rmail (&optional filename)
- "Append this article to Rmail file.
-Optional argument FILENAME specifies file name.
-Directory to save to is default to `gnus-article-save-directory' which
-is initialized from the SAVEDIR environment variable."
- (interactive)
- (gnus-summary-select-article gnus-save-all-headers gnus-save-all-headers)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (save-excursion
- (save-restriction
- (widen)
- (let ((default-name
- (funcall gnus-rmail-save-name
- gnus-newsgroup-name
- gnus-current-headers
- gnus-newsgroup-last-rmail
- )))
- (or filename
- (setq filename
- (read-file-name
- (concat "Save article in Rmail file: (default "
- (file-name-nondirectory default-name)
- ") ")
- (file-name-directory default-name)
- default-name)))
- (gnus-make-directory (file-name-directory filename))
- (gnus-output-to-rmail filename)
- ;; Remember the directory name to save articles.
- (setq gnus-newsgroup-last-rmail filename)
- )))
- ))
-
-(defun gnus-summary-save-in-mail (&optional filename)
- "Append this article to Unix mail file.
-Optional argument FILENAME specifies file name.
-Directory to save to is default to `gnus-article-save-directory' which
-is initialized from the SAVEDIR environment variable."
- (interactive)
- (gnus-summary-select-article gnus-save-all-headers gnus-save-all-headers)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (save-excursion
- (save-restriction
- (widen)
- (let ((default-name
- (funcall gnus-mail-save-name
- gnus-newsgroup-name
- gnus-current-headers
- gnus-newsgroup-last-mail
- )))
- (or filename
- (setq filename
- (read-file-name
- (concat "Save article in Unix mail file: (default "
- (file-name-nondirectory default-name)
- ") ")
- (file-name-directory default-name)
- default-name)))
- (setq filename
- (expand-file-name filename
- (and default-name
- (file-name-directory default-name))))
- (gnus-make-directory (file-name-directory filename))
- (if (and (file-readable-p filename) (mail-file-babyl-p filename))
- (gnus-output-to-rmail filename)
- (rmail-output filename 1 t t))
- ;; Remember the directory name to save articles.
- (setq gnus-newsgroup-last-mail filename)
- )))
- ))
-
-(defun gnus-summary-save-in-file (&optional filename)
- "Append this article to file.
-Optional argument FILENAME specifies file name.
-Directory to save to is default to `gnus-article-save-directory' which
-is initialized from the SAVEDIR environment variable."
- (interactive)
- (gnus-summary-select-article gnus-save-all-headers gnus-save-all-headers)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (save-excursion
- (save-restriction
- (widen)
- (let ((default-name
- (funcall gnus-file-save-name
- gnus-newsgroup-name
- gnus-current-headers
- gnus-newsgroup-last-file
- )))
- (or filename
- (setq filename
- (read-file-name
- (concat "Save article in file: (default "
- (file-name-nondirectory default-name)
- ") ")
- (file-name-directory default-name)
- default-name)))
- (gnus-make-directory (file-name-directory filename))
- (gnus-output-to-file filename)
- ;; Remember the directory name to save articles.
- (setq gnus-newsgroup-last-file filename)
- )))
- ))
-
-(defun gnus-summary-save-in-folder (&optional folder)
- "Save this article to MH folder (using `rcvstore' in MH library).
-Optional argument FOLDER specifies folder name."
- (interactive)
- (gnus-summary-select-article gnus-save-all-headers gnus-save-all-headers)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (save-restriction
- (widen)
- ;; Thanks to yuki@flab.Fujitsu.JUNET and ohm@kaba.junet.
- (mh-find-path)
- (let ((folder
- (or folder
- (mh-prompt-for-folder "Save article in"
- (funcall gnus-folder-save-name
- gnus-newsgroup-name
- gnus-current-headers
- gnus-newsgroup-last-folder
- )
- t
- )))
- (errbuf (get-buffer-create " *GNUS rcvstore*")))
- (unwind-protect
- (call-process-region (point-min) (point-max)
- (expand-file-name "rcvstore" mh-lib)
- nil errbuf nil folder)
- (set-buffer errbuf)
- (if (zerop (buffer-size))
- (message "Article saved in folder: %s" folder)
- (message "%s" (buffer-string)))
- (kill-buffer errbuf)
- (setq gnus-newsgroup-last-folder folder))
- ))
- ))
-
-(defun gnus-summary-pipe-output ()
- "Pipe this article to subprocess."
- (interactive)
- ;; Ignore `gnus-save-all-headers' since this is not save command.
- ;;(gnus-summary-select-article)
- ;; Huuum. Is this right?
- (gnus-summary-select-article gnus-save-all-headers gnus-save-all-headers)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (save-restriction
- (widen)
- (let ((command (read-string "Shell command on article: "
- gnus-last-shell-command)))
- (if (string-equal command "")
- (setq command gnus-last-shell-command))
- (shell-command-on-region (point-min) (point-max) command nil)
- (setq gnus-last-shell-command command)
- ))
- ))
-
-(defun gnus-summary-catchup (all &optional quietly)
- "Mark all articles not marked as unread in this newsgroup as read.
-If prefix argument ALL is non-nil, all articles are marked as read."
- (interactive "P")
- (if (or quietly
- (not gnus-interactive-catchup) ;Without confirmation?
- (y-or-n-p
- (if all
- "Do you really want to mark everything as read? "
- "Delete all articles not marked as unread? ")))
- (let ((unmarked
- (gnus-set-difference gnus-newsgroup-unreads
- (if (not all) gnus-newsgroup-marked))))
- (message "") ;Erase "Yes or No" question.
- ;; Hidden thread subtrees must be searched for ,too.
- (gnus-summary-show-all-threads)
- (while unmarked
- (gnus-summary-mark-as-read (car unmarked) "C")
- (setq unmarked (cdr unmarked))
- ))
- ))
-
-(defun gnus-summary-catchup-to-here ()
- "Mark all articles before the current one in this newsgroup as read."
- (interactive)
- (beginning-of-line)
- (let ((current (gnus-summary-article-number)))
- (beginning-of-buffer)
- (while (not (= (gnus-summary-article-number) current))
- (gnus-summary-mark-as-read)
- (gnus-summary-next-subject 1))))
-
-(defun gnus-summary-catchup-all (&optional quietly)
- "Mark all articles in this newsgroup as read."
- (interactive)
- (gnus-summary-catchup t quietly))
-
-(defun gnus-summary-catchup-and-exit (all &optional quietly)
- "Mark all articles not marked as unread in this newsgroup as read, then exit.
-If prefix argument ALL is non-nil, all articles are marked as read."
- (interactive "P")
- (if (or quietly
- (not gnus-interactive-catchup) ;Without confirmation?
- (y-or-n-p
- (if all
- "Do you really want to mark everything as read? "
- "Delete all articles not marked as unread? ")))
- (let ((unmarked
- (gnus-set-difference gnus-newsgroup-unreads
- (if (not all) gnus-newsgroup-marked))))
- (message "") ;Erase "Yes or No" question.
- (while unmarked
- (gnus-mark-article-as-read (car unmarked))
- (setq unmarked (cdr unmarked)))
- ;; Select next newsgroup or exit.
- (cond ((eq gnus-auto-select-next 'quietly)
- ;; Select next newsgroup quietly.
- (gnus-summary-next-group nil))
- (t
- (gnus-summary-exit)))
- )))
-
-(defun gnus-summary-catchup-all-and-exit (&optional quietly)
- "Mark all articles in this newsgroup as read, and then exit."
- (interactive)
- (gnus-summary-catchup-and-exit t quietly))
-
-(defun gnus-summary-edit-global-kill ()
- "Edit a global KILL file."
- (interactive)
- (setq gnus-current-kill-article (gnus-summary-article-number))
- (gnus-kill-file-edit-file nil) ;Nil stands for global KILL file.
- (message
- (substitute-command-keys
- "Editing a global KILL file (Type \\[gnus-kill-file-exit] to exit)")))
-
-(defun gnus-summary-edit-local-kill ()
- "Edit a local KILL file applied to the current newsgroup."
- (interactive)
- (setq gnus-current-kill-article (gnus-summary-article-number))
- (gnus-kill-file-edit-file gnus-newsgroup-name)
- (message
- (substitute-command-keys
- "Editing a local KILL file (Type \\[gnus-kill-file-exit] to exit)")))
-
-(defun gnus-summary-exit (&optional temporary)
- "Exit reading current newsgroup, and then return to group selection mode.
-`gnus-exit-group-hook' is called with no arguments if that value is non-nil."
- (interactive)
- (let ((updated nil)
- (gnus-newsgroup-headers gnus-newsgroup-headers)
- (gnus-newsgroup-unreads gnus-newsgroup-unreads)
- (gnus-newsgroup-unselected gnus-newsgroup-unselected)
- (gnus-newsgroup-marked gnus-newsgroup-marked))
- ;; Important internal variables are saved, so we can reenter
- ;; Summary buffer even if hook changes them.
- (run-hooks 'gnus-exit-group-hook)
- (gnus-update-unread-articles gnus-newsgroup-name
- (append gnus-newsgroup-unselected
- gnus-newsgroup-unreads)
- gnus-newsgroup-marked)
- ;; T means ignore unsubscribed newsgroups.
- (if gnus-use-cross-reference
- (setq updated
- (gnus-mark-as-read-by-xref gnus-newsgroup-name
- gnus-newsgroup-headers
- gnus-newsgroup-unreads
- (eq gnus-use-cross-reference t)
- )))
- ;; Do not switch windows but change the buffer to work.
- (set-buffer gnus-group-buffer)
- ;; Update cross referenced group info.
- (while updated
- (gnus-group-update-group (car updated) t) ;Ignore invisible group.
- (setq updated (cdr updated)))
- (gnus-group-update-group gnus-newsgroup-name))
- ;; Make sure where I was, and go to next newsgroup.
- (gnus-group-jump-to-group gnus-newsgroup-name)
- (gnus-group-next-unread-group 1)
- (if temporary
- ;; If exiting temporary, caller should adjust Group mode
- ;; buffer point by itself.
- nil ;Nothing to do.
- ;; Return to Group mode buffer.
- (if (get-buffer gnus-summary-buffer)
- (bury-buffer gnus-summary-buffer))
- (if (get-buffer gnus-article-buffer)
- (bury-buffer gnus-article-buffer))
- (gnus-configure-windows 'newsgroups)
- (pop-to-buffer gnus-group-buffer)))
-
-(defun gnus-summary-quit ()
- "Quit reading current newsgroup without updating read article info."
- (interactive)
- (if (y-or-n-p "Do you really wanna quit reading this group? ")
- (progn
- (message "") ;Erase "Yes or No" question.
- ;; Return to Group selection mode.
- (if (get-buffer gnus-summary-buffer)
- (bury-buffer gnus-summary-buffer))
- (if (get-buffer gnus-article-buffer)
- (bury-buffer gnus-article-buffer))
- (gnus-configure-windows 'newsgroups)
- (pop-to-buffer gnus-group-buffer)
- (gnus-group-jump-to-group gnus-newsgroup-name) ;Make sure where I was.
- (gnus-group-next-group 1) ;(gnus-group-next-unread-group 1)
- )))
-
-(defun gnus-summary-describe-briefly ()
- "Describe Summary mode commands briefly."
- (interactive)
- (message
- (concat
- (substitute-command-keys "\\[gnus-summary-next-page]:Select ")
- (substitute-command-keys "\\[gnus-summary-next-unread-article]:Forward ")
- (substitute-command-keys "\\[gnus-summary-prev-unread-article]:Backward ")
- (substitute-command-keys "\\[gnus-summary-exit]:Exit ")
- (substitute-command-keys "\\[gnus-info-find-node]:Run Info ")
- (substitute-command-keys "\\[gnus-summary-describe-briefly]:This help")
- )))
-
-
-;;;
-;;; GNUS Article Mode
-;;;
-
-(if gnus-article-mode-map
- nil
- (setq gnus-article-mode-map (make-keymap))
- (suppress-keymap gnus-article-mode-map)
- (define-key gnus-article-mode-map " " 'gnus-article-next-page)
- (define-key gnus-article-mode-map "\177" 'gnus-article-prev-page)
- (define-key gnus-article-mode-map "r" 'gnus-article-refer-article)
- (define-key gnus-article-mode-map "o" 'gnus-article-pop-article)
- (define-key gnus-article-mode-map "h" 'gnus-article-show-summary)
- (define-key gnus-article-mode-map "s" 'gnus-article-show-summary)
- (define-key gnus-article-mode-map "?" 'gnus-article-describe-briefly)
- (define-key gnus-article-mode-map "\C-c\C-i" 'gnus-info-find-node))
-
-(defun gnus-article-mode ()
- "Major mode for browsing through an article.
-All normal editing commands are turned off.
-Instead, these commands are available:
-\\{gnus-article-mode-map}
-
-Various hooks for customization:
- gnus-article-mode-hook
- Entry to this mode calls the value with no arguments, if that
- value is non-nil.
-
- gnus-article-prepare-hook
- Called with no arguments after an article is prepared for reading,
- 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))))))
- ;; To disable display-time facility.
- ;;(make-local-variable 'global-mode-string)
- ;;(setq global-mode-string nil)
- (setq major-mode 'gnus-article-mode)
- (setq mode-name "Article")
- (make-local-variable 'minor-mode-alist)
- (or (assq 'gnus-show-mime minor-mode-alist)
- (setq minor-mode-alist
- (cons (list 'gnus-show-mime " MIME") minor-mode-alist)))
- (gnus-article-set-mode-line)
- (use-local-map gnus-article-mode-map)
- (make-local-variable 'page-delimiter)
- (setq page-delimiter gnus-page-delimiter)
- (make-local-variable 'mail-header-separator)
- (setq mail-header-separator "") ;For caesar function.
- (buffer-flush-undo (current-buffer))
- (setq buffer-read-only t) ;Disable modification
- (run-hooks 'gnus-article-mode-hook))
-
-(defun gnus-article-setup-buffer ()
- "Initialize Article mode buffer."
- (or (get-buffer gnus-article-buffer)
- (save-excursion
- (set-buffer (get-buffer-create gnus-article-buffer))
- (gnus-article-mode))
- ))
-
-(defun gnus-article-prepare (article &optional all-headers)
- "Prepare ARTICLE in Article mode buffer.
-ARTICLE can be either a article number or Message-ID.
-If optional argument ALL-HEADERS is non-nil,
-include the article's whole original header."
- ;; Make sure a connection to NNTP server is alive.
- (if (not (gnus-server-opened))
- (progn
- (gnus-start-news-server)
- (gnus-request-group gnus-newsgroup-name)))
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil))
- (erase-buffer)
- ;; mhspool does not work with Message-ID. So, let's translate
- ;; it into an article number as possible as can. This may help
- ;; nnspool too.
- ;; Note: this conversion must be done here since if the article
- ;; is specified by number or message-id has a different meaning
- ;; in the following.
- (if (let* ((header
- (and (stringp article)
- (gnus-get-header-by-id article)))
- (article
- (if header
- (nntp-header-number header) article)))
- (gnus-request-article article))
- (progn
- ;; Prepare article buffer
- (insert-buffer-substring nntp-server-buffer)
- ;; gnus-have-all-headers must be either T or NIL.
- (setq gnus-have-all-headers
- (not (not (or all-headers gnus-show-all-headers))))
- (if (and (numberp article)
- (not (eq article gnus-current-article)))
- ;; Seems me that a new article has been selected.
- (progn
- ;; gnus-current-article must be an article number.
- (setq gnus-last-article gnus-current-article)
- (setq gnus-current-article article)
-;; (setq gnus-current-headers
-;; (gnus-find-header-by-number gnus-newsgroup-headers
-;; gnus-current-article))
- (setq gnus-current-headers
- (gnus-get-header-by-number gnus-current-article))
- (run-hooks 'gnus-mark-article-hook)
- ))
- ;; Clear article history only when the article is
- ;; retrieved by the article number.
- (if (numberp article)
- (setq gnus-current-history nil))
- ;; Hooks for modifying contents of the article. This hook
- ;; must be called before being narrowed.
- (run-hooks 'gnus-article-prepare-hook)
- ;; Decode MIME message.
- (if (and gnus-show-mime
- (gnus-fetch-field "Mime-Version"))
- (funcall gnus-show-mime-method))
- ;; Delete unnecessary headers.
- (or gnus-have-all-headers
- (gnus-article-delete-headers))
- ;; Do page break.
- (goto-char (point-min))
- (if gnus-break-pages
- (gnus-narrow-to-page))
- ;; Next function must be called after setting
- ;; `gnus-current-article' variable and narrowed to page.
- (gnus-article-set-mode-line)
- )
- ;; There is no such article.
- (if (numberp article)
- (gnus-summary-mark-as-read article))
- (ding) (message "No such article (may be canceled)"))
- )))
-
-(defun gnus-article-show-all-headers ()
- "Show all article headers in Article mode buffer."
- (or gnus-have-all-headers
- (gnus-article-prepare gnus-current-article t)))
-
-;;(defun gnus-article-set-mode-line ()
-;; "Set Article mode line string."
-;; (setq mode-line-buffer-identification
-;; (list 17
-;; (format "GNUS: %s {%d-%d} %d"
-;; gnus-newsgroup-name
-;; gnus-newsgroup-begin
-;; gnus-newsgroup-end
-;; gnus-current-article
-;; )))
-;; (set-buffer-modified-p t))
-
-;;(defun gnus-article-set-mode-line ()
-;; "Set Article mode line string."
-;; (let ((unmarked
-;; (- (length gnus-newsgroup-unreads)
-;; (length (gnus-intersection
-;; gnus-newsgroup-unreads gnus-newsgroup-marked))))
-;; (unselected
-;; (- (length gnus-newsgroup-unselected)
-;; (length (gnus-intersection
-;; gnus-newsgroup-unselected gnus-newsgroup-marked)))))
-;; (setq mode-line-buffer-identification
-;; (list 17
-;; (format "GNUS: %s{%d} %s"
-;; gnus-newsgroup-name
-;; gnus-current-article
-;; ;; This is proposed by tale@pawl.rpi.edu.
-;; (cond ((and (zerop unmarked)
-;; (zerop unselected))
-;; " ")
-;; ((zerop unselected)
-;; (format "%d more" unmarked))
-;; (t
-;; (format "%d(+%d) more" unmarked unselected)))
-;; ))))
-;; (set-buffer-modified-p t))
-
-;; New implementation in gnus 3.14.3
-
-(defun gnus-article-set-mode-line ()
- "Set Article mode line string.
-If you don't like it, define your own `gnus-article-set-mode-line'."
- (let ((maxlen 15) ;Maximum subject length
- (subject
- (if gnus-current-headers
- (nntp-header-subject gnus-current-headers) "")))
- ;; The value must be a string to escape %-constructs because of subject.
- (setq mode-line-buffer-identification
- (format "GNUS: %s%s %s%s%s"
- gnus-newsgroup-name
- (if gnus-current-article
- (format "/%d" gnus-current-article) "")
- (substring subject 0 (min (length subject) maxlen))
- (if (> (length subject) maxlen) "..." "")
- (make-string (max 0 (- 17 (length subject))) ? )
- )))
- (set-buffer-modified-p t))
-
-(defun gnus-article-delete-headers ()
- "Delete unnecessary headers."
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (narrow-to-region (point-min)
- (progn (search-forward "\n\n" nil 'move) (point)))
- (goto-char (point-min))
- (and (stringp gnus-ignored-headers)
- (while (re-search-forward gnus-ignored-headers nil t)
- (beginning-of-line)
- (delete-region (point)
- (progn (re-search-forward "\n[^ \t]")
- (forward-char -1)
- (point)))))
- )))
-
-;; Working on article's buffer
-
-(defun gnus-article-next-page (lines)
- "Show next page of current article.
-If end of article, return non-nil. Otherwise return nil.
-Argument LINES specifies lines to be scrolled up."
- (interactive "P")
- (move-to-window-line -1)
- ;; Fixed by enami@ptgd.sony.co.jp (enami tsugutomo)
- (if (save-excursion
- (end-of-line)
- (and (pos-visible-in-window-p) ;Not continuation line.
- (eobp)))
- ;; Nothing in this page.
- (if (or (not gnus-break-pages)
- (save-excursion
- (save-restriction
- (widen) (forward-line 1) (eobp)))) ;Real end-of-buffer?
- t ;Nothing more.
- (gnus-narrow-to-page 1) ;Go to next page.
- nil
- )
- ;; More in this page.
- (condition-case ()
- (scroll-up lines)
- (end-of-buffer
- ;; Long lines may cause an end-of-buffer error.
- (goto-char (point-max))))
- nil
- ))
-
-(defun gnus-article-prev-page (lines)
- "Show previous page of current article.
-Argument LINES specifies lines to be scrolled down."
- (interactive "P")
- (move-to-window-line 0)
- (if (and gnus-break-pages
- (bobp)
- (not (save-restriction (widen) (bobp)))) ;Real beginning-of-buffer?
- (progn
- (gnus-narrow-to-page -1) ;Go to previous page.
- (goto-char (point-max))
- (recenter -1))
- (scroll-down lines)))
-
-(defun gnus-article-next-digest (nth)
- "Move to head of NTH next digested message.
-Set mark at end of digested message."
- ;; Stop page breaking in digest mode.
- (widen)
- (end-of-line)
- ;; Skip NTH - 1 digest.
- ;; Suggested by Khalid Sattar <admin@cs.exeter.ac.uk>.
- ;; Digest separator is customizable.
- ;; Suggested by Skip Montanaro <montanaro@sprite.crd.ge.com>.
- (while (and (> nth 1)
- (re-search-forward gnus-digest-separator nil 'move))
- (setq nth (1- nth)))
- (if (re-search-forward gnus-digest-separator nil t)
- (let ((begin (point)))
- ;; Search for end of this message.
- (end-of-line)
- (if (re-search-forward gnus-digest-separator nil t)
- (progn
- (search-backward "\n\n") ;This may be incorrect.
- (forward-line 1))
- (goto-char (point-max)))
- (push-mark) ;Set mark at end of digested message.
- (goto-char begin)
- (beginning-of-line)
- ;; Show From: and Subject: fields.
- (recenter 1))
- (message "End of message")
- ))
-
-(defun gnus-article-prev-digest (n)
- "Move to head of Nth previous digested message."
- ;; Stop page breaking in digest mode.
- (widen)
- (beginning-of-line)
- ;; Skip N - 1 digest.
- ;; Suggested by Khalid Sattar <admin@cs.exeter.ac.uk>.
- ;; Digest separator is customizable.
- ;; Suggested by Skip Montanaro <montanaro@sprite.crd.ge.com>.
- (while (and (> n 1)
- (re-search-backward gnus-digest-separator nil 'move))
- (setq n (1- n)))
- (if (re-search-backward gnus-digest-separator nil t)
- (let ((begin (point)))
- ;; Search for end of this message.
- (end-of-line)
- (if (re-search-forward gnus-digest-separator nil t)
- (progn
- (search-backward "\n\n") ;This may be incorrect.
- (forward-line 1))
- (goto-char (point-max)))
- (push-mark) ;Set mark at end of digested message.
- (goto-char begin)
- ;; Show From: and Subject: fields.
- (recenter 1))
- (goto-char (point-min))
- (message "Top of message")
- ))
-
-(defun gnus-article-refer-article ()
- "Read article specified by message-id around point."
- (interactive)
- (save-window-excursion
- (save-excursion
- (re-search-forward ">" nil t) ;Move point to end of "<....>".
- (if (re-search-backward "\\(<[^<> \t\n]+>\\)" nil t)
- (let ((message-id
- (buffer-substring (match-beginning 1) (match-end 1))))
- (set-buffer gnus-summary-buffer)
- (gnus-summary-refer-article message-id))
- (error "No references around point"))
- )))
-
-(defun gnus-article-pop-article ()
- "Pop up article history."
- (interactive)
- (save-window-excursion
- (set-buffer gnus-summary-buffer)
- (gnus-summary-refer-article nil)))
-
-(defun gnus-article-show-summary ()
- "Reconfigure windows to show Summary buffer."
- (interactive)
- (gnus-configure-windows 'article)
- (pop-to-buffer gnus-summary-buffer)
- (gnus-summary-goto-subject gnus-current-article))
-
-(defun gnus-article-describe-briefly ()
- "Describe Article mode commands briefly."
- (interactive)
- (message
- (concat
- (substitute-command-keys "\\[gnus-article-next-page]:Next page ")
- (substitute-command-keys "\\[gnus-article-prev-page]:Prev page ")
- (substitute-command-keys "\\[gnus-article-show-summary]:Show Summary ")
- (substitute-command-keys "\\[gnus-info-find-node]:Run Info ")
- (substitute-command-keys "\\[gnus-article-describe-briefly]:This help")
- )))
-
-
-;;;
-;;; GNUS KILL-File Mode
-;;;
-
-(if gnus-kill-file-mode-map
- nil
- (setq gnus-kill-file-mode-map (copy-keymap emacs-lisp-mode-map))
- (define-key gnus-kill-file-mode-map "\C-c\C-k\C-s" 'gnus-kill-file-kill-by-subject)
- (define-key gnus-kill-file-mode-map "\C-c\C-k\C-a" 'gnus-kill-file-kill-by-author)
- (define-key gnus-kill-file-mode-map "\C-c\C-a" 'gnus-kill-file-apply-buffer)
- (define-key gnus-kill-file-mode-map "\C-c\C-e" 'gnus-kill-file-apply-last-sexp)
- (define-key gnus-kill-file-mode-map "\C-c\C-c" 'gnus-kill-file-exit)
- (define-key gnus-kill-file-mode-map "\C-c\C-i" 'gnus-info-find-node))
-
-(defun gnus-kill-file-mode ()
- "Major mode for editing KILL file.
-
-In addition to Emacs-Lisp Mode, the following commands are available:
-
-\\[gnus-kill-file-kill-by-subject] Insert KILL command for current subject.
-\\[gnus-kill-file-kill-by-author] Insert KILL command for current author.
-\\[gnus-kill-file-apply-buffer] Apply current buffer to selected newsgroup.
-\\[gnus-kill-file-apply-last-sexp] Apply sexp before point to selected newsgroup.
-\\[gnus-kill-file-exit] Save file and exit editing KILL file.
-\\[gnus-info-find-node] Read Info about KILL file.
-
- A KILL file contains Lisp expressions to be applied to a selected
-newsgroup. The purpose is to mark articles as read on the basis of
-some set of regexps. A global KILL file is applied to every newsgroup,
-and a local KILL file is applied to a specified newsgroup. Since a
-global KILL file is applied to every newsgroup, for better performance
-use a local one.
-
- A KILL file can contain any kind of Emacs Lisp expressions expected
-to be evaluated in the Summary buffer. Writing Lisp programs for this
-purpose is not so easy because the internal working of GNUS must be
-well-known. For this reason, GNUS provides a general function which
-does this easily for non-Lisp programmers.
-
- The `gnus-kill' function executes commands available in Summary Mode
-by their key sequences. `gnus-kill' should be called with FIELD,
-REGEXP and optional COMMAND and ALL. FIELD is a string representing
-the header field or an empty string. If FIELD is an empty string, the
-entire article body is searched for. REGEXP is a string which is
-compared with FIELD value. COMMAND is a string representing a valid
-key sequence in Summary mode or Lisp expression. COMMAND defaults to
-\(gnus-summary-mark-as-read nil \"X\"). Make sure that COMMAND is
-executed in the Summary buffer. If the second optional argument ALL
-is non-nil, the COMMAND is applied to articles which are already
-marked as read or unread. Articles which are marked are skipped over
-by default.
-
- For example, if you want to mark articles of which subjects contain
-the string `AI' as read, a possible KILL file may look like:
-
- (gnus-kill \"Subject\" \"AI\")
-
- If you want to mark articles with `D' instead of `X', you can use
-the following expression:
-
- (gnus-kill \"Subject\" \"AI\" \"d\")
-
-\(Here we assume the command `gnus-summary-mark-as-read-forward' is
-assigned to `d' in Summary Mode.)
-
- It is possible to delete unnecessary headers which are marked with
-`X' in a KILL file as follows:
-
- (gnus-expunge \"X\")
-
- If the Summary buffer is empty after applying KILL files, GNUS will
-exit the selected newsgroup normally. If headers which are marked
-with `D' are deleted in a KILL file, it is impossible to read articles
-which are marked as read in the previous GNUS sessions. Marks other
-than `D' should be used for articles which should really be deleted.
-
-Entry to this mode calls `emacs-lisp-mode-hook' and
-`gnus-kill-file-mode-hook' with no arguments, if that value is non-nil."
- (interactive)
- (kill-all-local-variables)
- (use-local-map gnus-kill-file-mode-map)
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (setq major-mode 'gnus-kill-file-mode)
- (setq mode-name "KILL-File")
- (lisp-mode-variables nil)
- (run-hooks 'emacs-lisp-mode-hook 'gnus-kill-file-mode-hook))
-
-(defun gnus-kill-file-edit-file (newsgroup)
- "Begin editing a KILL file of NEWSGROUP.
-If NEWSGROUP is nil, the global KILL file is selected."
- (interactive "sNewsgroup: ")
- (let ((file (gnus-newsgroup-kill-file newsgroup)))
- (gnus-make-directory (file-name-directory file))
- ;; Save current window configuration if this is first invocation.
- (or (and (get-file-buffer file)
- (get-buffer-window (get-file-buffer file)))
- (setq gnus-winconf-kill-file (current-window-configuration)))
- ;; Hack windows.
- (let ((buffer (find-file-noselect file)))
- (cond ((get-buffer-window buffer)
- (pop-to-buffer buffer))
- ((eq major-mode 'gnus-group-mode)
- (gnus-configure-windows '(1 0 0)) ;Take all windows.
- (pop-to-buffer gnus-group-buffer)
- (let ((gnus-summary-buffer buffer))
- (gnus-configure-windows '(1 1 0)) ;Split into two.
- (pop-to-buffer buffer)))
- ((eq major-mode 'gnus-summary-mode)
- (gnus-configure-windows 'article)
- (pop-to-buffer gnus-article-buffer)
- (bury-buffer gnus-article-buffer)
- (switch-to-buffer buffer))
- (t ;No good rules.
- (find-file-other-window file))
- ))
- (gnus-kill-file-mode)
- ))
-
-(defun gnus-kill-file-kill-by-subject ()
- "Insert KILL command for current subject."
- (interactive)
- (insert
- (format "(gnus-kill \"Subject\" %s)\n"
- (prin1-to-string
- (if gnus-current-kill-article
- (regexp-quote
- (nntp-header-subject
- ;; No need to speed up this command.
- ;;(gnus-get-header-by-number gnus-current-kill-article)
- (gnus-find-header-by-number gnus-newsgroup-headers
- gnus-current-kill-article)))
- "")))))
-
-(defun gnus-kill-file-kill-by-author ()
- "Insert KILL command for current author."
- (interactive)
- (insert
- (format "(gnus-kill \"From\" %s)\n"
- (prin1-to-string
- (if gnus-current-kill-article
- (regexp-quote
- (nntp-header-from
- ;; No need to speed up this command.
- ;;(gnus-get-header-by-number gnus-current-kill-article)
- (gnus-find-header-by-number gnus-newsgroup-headers
- gnus-current-kill-article)))
- "")))))
-
-(defun gnus-kill-file-apply-buffer ()
- "Apply current buffer to current newsgroup."
- (interactive)
- (if (and gnus-current-kill-article
- (get-buffer gnus-summary-buffer))
- ;; Assume newsgroup is selected.
- (let ((string (concat "(progn \n" (buffer-string) "\n)" )))
- (save-excursion
- (save-window-excursion
- (pop-to-buffer gnus-summary-buffer)
- (eval (car (read-from-string string))))))
- (ding) (message "No newsgroup is selected.")))
-
-(defun gnus-kill-file-apply-last-sexp ()
- "Apply sexp before point in current buffer to current newsgroup."
- (interactive)
- (if (and gnus-current-kill-article
- (get-buffer gnus-summary-buffer))
- ;; Assume newsgroup is selected.
- (let ((string
- (buffer-substring
- (save-excursion (forward-sexp -1) (point)) (point))))
- (save-excursion
- (save-window-excursion
- (pop-to-buffer gnus-summary-buffer)
- (eval (car (read-from-string string))))))
- (ding) (message "No newsgroup is selected.")))
-
-(defun gnus-kill-file-exit ()
- "Save a KILL file, then return to the previous buffer."
- (interactive)
- (save-buffer)
- (let ((killbuf (current-buffer)))
- ;; We don't want to return to Article buffer.
- (and (get-buffer gnus-article-buffer)
- (bury-buffer (get-buffer gnus-article-buffer)))
- ;; Delete the KILL file windows.
- (delete-windows-on killbuf)
- ;; Restore last window configuration if available.
- (and gnus-winconf-kill-file
- (set-window-configuration gnus-winconf-kill-file))
- (setq gnus-winconf-kill-file nil)
- ;; Kill the KILL file buffer. Suggested by tale@pawl.rpi.edu.
- (kill-buffer killbuf)))
-
-
-;;;
-;;; Utility functions
-;;;
-
-;; Basic ideas by emv@math.lsa.umich.edu (Edward Vielmetti)
-
-(defun gnus-batch-kill ()
- "Run batched KILL.
-Usage: emacs -batch -l gnus -f gnus-batch-kill NEWSGROUP ..."
- (if (not noninteractive)
- (error "gnus-batch-kill is to be used only with -batch"))
- (let* ((group nil)
- (subscribed nil)
- (newsrc nil)
- (yes-and-no
- (gnus-parse-n-options
- (apply (function concat)
- (mapcar (function (lambda (g) (concat g " ")))
- command-line-args-left))))
- (yes (car yes-and-no))
- (no (cdr yes-and-no))
- ;; Disable verbose message.
- (gnus-novice-user nil)
- (gnus-large-newsgroup nil)
- (nntp-large-newsgroup nil))
- ;; Eat all arguments.
- (setq command-line-args-left nil)
- ;; Startup GNUS.
- (gnus)
- ;; Apply kills to specified newsgroups in command line arguments.
- (setq newsrc (copy-sequence gnus-newsrc-assoc))
- (while newsrc
- (setq group (car (car newsrc)))
- (setq subscribed (nth 1 (car newsrc)))
- (setq newsrc (cdr newsrc))
- (if (and subscribed
- (not (zerop (nth 1 (gnus-gethash group gnus-unread-hashtb))))
- (if yes
- (string-match yes group) t)
- (or (null no)
- (not (string-match no group))))
- (progn
- (gnus-summary-read-group group nil t)
- (if (eq (current-buffer) (get-buffer gnus-summary-buffer))
- (gnus-summary-exit t))
- ))
- )
- ;; Finally, exit Emacs.
- (set-buffer gnus-group-buffer)
- (gnus-group-exit)
- ))
-
-;; For saving articles
-
-(defun gnus-Numeric-save-name (newsgroup headers &optional last-file)
- "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
-If variable `gnus-use-long-file-name' is nil, it is ~/News/News.group/num.
-Otherwise, it is like ~/News/news/group/num."
- (let ((default
- (expand-file-name
- (concat (if gnus-use-long-file-name
- (gnus-capitalize-newsgroup newsgroup)
- (gnus-newsgroup-directory-form newsgroup))
- "/" (int-to-string (nntp-header-number headers)))
- (or gnus-article-save-directory "~/News"))))
- (if (and last-file
- (string-equal (file-name-directory default)
- (file-name-directory last-file))
- (string-match "^[0-9]+$" (file-name-nondirectory last-file)))
- default
- (or last-file default))))
-
-(defun gnus-numeric-save-name (newsgroup headers &optional last-file)
- "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
-If variable `gnus-use-long-file-name' is nil, it is ~/News/news.group/num.
-Otherwise, it is like ~/News/news/group/num."
- (let ((default
- (expand-file-name
- (concat (if gnus-use-long-file-name
- newsgroup
- (gnus-newsgroup-directory-form newsgroup))
- "/" (int-to-string (nntp-header-number headers)))
- (or gnus-article-save-directory "~/News"))))
- (if (and last-file
- (string-equal (file-name-directory default)
- (file-name-directory last-file))
- (string-match "^[0-9]+$" (file-name-nondirectory last-file)))
- default
- (or last-file default))))
-
-(defun gnus-Plain-save-name (newsgroup headers &optional last-file)
- "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
-If variable `gnus-use-long-file-name' is nil, it is ~/News/News.group.
-Otherwise, it is like ~/News/news/group/news."
- (or last-file
- (expand-file-name
- (if gnus-use-long-file-name
- (gnus-capitalize-newsgroup newsgroup)
- (concat (gnus-newsgroup-directory-form newsgroup) "/news"))
- (or gnus-article-save-directory "~/News"))))
-
-(defun gnus-plain-save-name (newsgroup headers &optional last-file)
- "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
-If variable `gnus-use-long-file-name' is nil, it is ~/News/news.group.
-Otherwise, it is like ~/News/news/group/news."
- (or last-file
- (expand-file-name
- (if gnus-use-long-file-name
- newsgroup
- (concat (gnus-newsgroup-directory-form newsgroup) "/news"))
- (or gnus-article-save-directory "~/News"))))
-
-(defun gnus-Folder-save-name (newsgroup headers &optional last-folder)
- "Generate folder name from NEWSGROUP, HEADERS, and optional LAST-FOLDER.
-If variable `gnus-use-long-file-name' is nil, it is +News.group.
-Otherwise, it is like +news/group."
- (or last-folder
- (concat "+"
- (if gnus-use-long-file-name
- (gnus-capitalize-newsgroup newsgroup)
- (gnus-newsgroup-directory-form newsgroup)))))
-
-(defun gnus-folder-save-name (newsgroup headers &optional last-folder)
- "Generate folder name from NEWSGROUP, HEADERS, and optional LAST-FOLDER.
-If variable `gnus-use-long-file-name' is nil, it is +news.group.
-Otherwise, it is like +news/group."
- (or last-folder
- (concat "+"
- (if gnus-use-long-file-name
- newsgroup
- (gnus-newsgroup-directory-form newsgroup)))))
-
-;; For KILL files
-
-(defun gnus-apply-kill-file ()
- "Apply KILL file to the current newsgroup."
- ;; Apply the global KILL file.
- (load (gnus-newsgroup-kill-file nil) t nil t)
- ;; And then apply the local KILL file.
- (load (gnus-newsgroup-kill-file gnus-newsgroup-name) t nil t))
-
-(defun gnus-Newsgroup-kill-file (newsgroup)
- "Return the name of a KILL file of NEWSGROUP.
-If NEWSGROUP is nil, return the global KILL file instead."
- (cond ((or (null newsgroup)
- (string-equal newsgroup ""))
- ;; The global KILL file is placed at top of the directory.
- (expand-file-name gnus-kill-file-name
- (or gnus-kill-files-directory "~/News")))
- (gnus-use-long-file-name
- ;; Append ".KILL" to capitalized newsgroup name.
- (expand-file-name (concat (gnus-capitalize-newsgroup newsgroup)
- "." gnus-kill-file-name)
- (or gnus-kill-files-directory "~/News")))
- (t
- ;; Place "KILL" under the hierarchical directory.
- (expand-file-name (concat (gnus-newsgroup-directory-form newsgroup)
- "/" gnus-kill-file-name)
- (or gnus-kill-files-directory "~/News")))
- ))
-
-(defun gnus-newsgroup-kill-file (newsgroup)
- "Return the name of a KILL file of NEWSGROUP.
-If NEWSGROUP is nil, return the global KILL file instead."
- (cond ((or (null newsgroup)
- (string-equal newsgroup ""))
- ;; The global KILL file is placed at top of the directory.
- (expand-file-name gnus-kill-file-name
- (or gnus-kill-files-directory "~/News")))
- (gnus-use-long-file-name
- ;; Append ".KILL" to newsgroup name.
- (expand-file-name (concat newsgroup "." gnus-kill-file-name)
- (or gnus-kill-files-directory "~/News")))
- (t
- ;; Place "KILL" under the hierarchical directory.
- (expand-file-name (concat (gnus-newsgroup-directory-form newsgroup)
- "/" gnus-kill-file-name)
- (or gnus-kill-files-directory "~/News")))
- ))
-
-;; For subscribing new newsgroup
-
-(defun gnus-subscribe-randomly (newsgroup)
- "Subscribe new NEWSGROUP and insert it at the beginning of newsgroups."
- (gnus-subscribe-newsgroup newsgroup
- (car (car gnus-newsrc-assoc))))
-
-(defun gnus-subscribe-alphabetically (newgroup)
- "Subscribe new NEWSGROUP and insert it in strict alphabetic order."
- ;; Basic ideas by mike-w@cs.aukuni.ac.nz (Mike Williams)
- (let ((groups gnus-newsrc-assoc)
- (before nil))
- (while (and (not before) groups)
- (if (string< newgroup (car (car groups)))
- (setq before (car (car groups)))
- (setq groups (cdr groups))))
- (gnus-subscribe-newsgroup newgroup before)
- ))
-
-(defun gnus-subscribe-hierarchically (newgroup)
- "Subscribe new NEWSGROUP and insert it in hierarchical newsgroup order."
- ;; Basic ideas by mike-w@cs.aukuni.ac.nz (Mike Williams)
- (save-excursion
- (set-buffer (find-file-noselect gnus-current-startup-file))
- (let ((groupkey newgroup)
- (before nil))
- (while (and (not before) groupkey)
- (goto-char (point-min))
- (let ((groupkey-re
- (concat "^\\(" (regexp-quote groupkey) ".*\\)[!:]")))
- (while (and (re-search-forward groupkey-re nil t)
- (progn
- (setq before (buffer-substring
- (match-beginning 1) (match-end 1)))
- (string< before newgroup)))
- ))
- ;; Remove tail of newsgroup name (eg. a.b.c -> a.b)
- (setq groupkey
- (if (string-match "^\\(.*\\)\\.[^.]+$" groupkey)
- (substring groupkey (match-beginning 1) (match-end 1)))))
- (gnus-subscribe-newsgroup newgroup before)
- )))
-
-(defun gnus-subscribe-interactively (newsgroup)
- "Subscribe new NEWSGROUP interactively.
-It is inserted in hierarchical newsgroup order if subscribed.
-Unless, it is killed."
- (if (y-or-n-p (format "Subscribe new newsgroup: %s " newsgroup))
- (gnus-subscribe-hierarchically newsgroup)
- ;; Save in kill-ring
- (gnus-subscribe-newsgroup newsgroup)
- (gnus-kill-newsgroup newsgroup)))
-
-(defun gnus-subscribe-newsgroup (newsgroup &optional next)
- "Subscribe new NEWSGROUP.
-If optional argument NEXT is non-nil, it is inserted before NEXT."
- (gnus-insert-newsgroup (list newsgroup t) next)
- (message "Subscribe newsgroup: %s" newsgroup))
-
-;; For directories
-
-(defun gnus-newsgroup-directory-form (newsgroup)
- "Make hierarchical directory name from NEWSGROUP name."
- (let ((newsgroup (substring newsgroup 0)) ;Copy string.
- (len (length newsgroup))
- (idx 0))
- ;; Replace all occurrences of `.' with `/'.
- (while (< idx len)
- (if (= (aref newsgroup idx) ?.)
- (aset newsgroup idx ?/))
- (setq idx (1+ idx)))
- newsgroup
- ))
-
-(defun gnus-make-directory (directory)
- "Make DIRECTORY recursively."
- (let ((directory (expand-file-name directory default-directory)))
- (or (file-exists-p directory)
- (gnus-make-directory-1 "" directory))
- ))
-
-(defun gnus-make-directory-1 (head tail)
- (cond ((string-match "^/\\([^/]+\\)" tail)
- ;; ange-ftp interferes with calling match-* after
- ;; calling file-name-as-directory.
- (let ((beg (match-beginning 1))
- (end (match-end 1)))
- (setq head (concat (file-name-as-directory head)
- (substring tail beg end)))
- (or (file-exists-p head)
- (call-process "mkdir" nil nil nil head))
- (gnus-make-directory-1 head (substring tail end))))
- ((string-equal tail "") t)
- ))
-
-(defun gnus-capitalize-newsgroup (newsgroup)
- "Capitalize NEWSGROUP name with treating `.' and `-' as part of words."
- ;; Suggested by "Jonathan I. Kamens" <jik@pit-manager.MIT.EDU>.
- (let ((current-syntax-table (syntax-table)))
- (unwind-protect
- (progn
- (set-syntax-table (copy-syntax-table current-syntax-table))
- (modify-syntax-entry ?- "w")
- (modify-syntax-entry ?. "w")
- (capitalize newsgroup))
- (set-syntax-table current-syntax-table))))
-
-(defun gnus-simplify-subject (subject &optional re-only)
- "Remove `Re:' and words in parentheses.
-If optional argument RE-ONLY is non-nil, strip `Re:' only."
- (let ((case-fold-search t)) ;Ignore case.
- ;; Remove `Re:' and `Re^N:'.
- (if (string-match "\\`\\(re\\(\\^[0-9]+\\)?:[ \t]+\\)+" subject)
- (setq subject (substring subject (match-end 0))))
- ;; Remove words in parentheses from end.
- (or re-only
- (while (string-match "[ \t\n]*([^()]*)[ \t\n]*\\'" subject)
- (setq subject (substring subject 0 (match-beginning 0)))))
- ;; Return subject string.
- subject
- ))
-
-(defun gnus-optional-lines-and-from (header)
- "Return a string like `NNN:AUTHOR' from HEADER."
- (let ((name-length (length "umerin@photon")))
- (substring (format "%3d:%s"
- ;; Lines of the article.
- ;; Suggested by dana@bellcore.com.
- (nntp-header-lines header)
- ;; Its author.
- (concat (mail-strip-quoted-names
- (nntp-header-from header))
- (make-string name-length ? )))
- ;; 4 stands for length of `NNN:'.
- 0 (+ 4 name-length))))
-
-(defun gnus-optional-lines (header)
- "Return a string like `NNN' from HEADER."
- (format "%4d" (nntp-header-lines header)))
-
-;; Basic ideas by flee@cs.psu.edu (Felix Lee)
-
-(defun gnus-keysort-headers (predicate key &optional reverse)
- "Sort current headers by PREDICATE using a value passed by KEY safely.
-*Safely* means C-g quitting is disabled during sort.
-Optional argument REVERSE means reverse order."
- (let ((inhibit-quit t))
- (setq gnus-newsgroup-headers
- (if reverse
- (nreverse
- (gnus-keysort (nreverse gnus-newsgroup-headers) predicate key))
- (gnus-keysort gnus-newsgroup-headers predicate key)))
- ;; Make sure we don't have to call
- ;; gnus-clear-hashtables-for-newsgroup-headers to clear hash
- ;; tables for the variable gnus-newsgroup-headers since no new
- ;; entry is added to nor deleted from the variable.
- ))
-
-(defun gnus-keysort (list predicate key)
- "Sort LIST by PREDICATE using a value passed by KEY."
- (mapcar (function cdr)
- (sort (mapcar (function (lambda (a) (cons (funcall key a) a))) list)
- (function (lambda (a b)
- (funcall predicate (car a) (car b)))))))
-
-(defun gnus-sort-headers (predicate &optional reverse)
- "Sort current headers by PREDICATE safely.
-*Safely* means C-g quitting is disabled during sort.
-Optional argument REVERSE means reverse order."
- (let ((inhibit-quit t))
- (setq gnus-newsgroup-headers
- (if reverse
- (nreverse (sort (nreverse gnus-newsgroup-headers) predicate))
- (sort gnus-newsgroup-headers predicate)))
- ;; Make sure we don't have to call
- ;; gnus-clear-hashtables-for-newsgroup-headers to clear hash
- ;; tables for the variable gnus-newsgroup-headers since no new
- ;; entry is added to nor deleted from the variable.
- ))
-
-(defun gnus-string-lessp (a b)
- "Return T if first arg string is less than second in lexicographic order.
-If `case-fold-search' is non-nil, case of letters is ignored."
- (if case-fold-search
- (string-lessp (downcase a) (downcase b))
- (string-lessp a b)))
-
-(defun gnus-date-lessp (date1 date2)
- "Return T if DATE1 is earlyer than DATE2."
- (string-lessp (gnus-sortable-date date1)
- (gnus-sortable-date date2)))
-
-(defun gnus-sortable-date (date)
- "Convert DATE into a string that can be sorted with `string-lessp'.
-Timezone package is used."
- (let* ((date (timezone-fix-time date nil nil)) ;[Y M D H M S]
- (year (aref date 0))
- (month (aref date 1))
- (day (aref date 2)))
- (timezone-make-sortable-date year month day
- (timezone-make-time-string
- (aref date 3) (aref date 4) (aref date 5)))
- ))
-
-;;(defun gnus-sortable-date (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")))
-;; (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
-;; (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 gnus-fetch-field (field)
- "Return the value of the header FIELD of current article."
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (narrow-to-region (point-min)
- (progn (search-forward "\n\n" nil 'move) (point)))
- (mail-fetch-field field))))
-
-(defalias 'gnus-expunge 'gnus-summary-delete-marked-with)
-
-(defun gnus-kill (field regexp &optional command all)
- "If FIELD of an article matches REGEXP, execute COMMAND.
-Optional 1st argument COMMAND is default to
- (gnus-summary-mark-as-read nil \"X\").
-If optional 2nd argument ALL is non-nil, articles marked are also applied to.
-If FIELD is an empty string (or nil), entire article body is searched for.
-COMMAND must be a Lisp expression or a string representing a key sequence."
- ;; We don't want to change current point nor window configuration.
- (save-excursion
- (save-window-excursion
- ;; Selected window must be Summary buffer to execute keyboard
- ;; macros correctly. See command_loop_1.
- (switch-to-buffer gnus-summary-buffer 'norecord)
- (goto-char (point-min)) ;From the beginning.
- (if (null command)
- (setq command '(gnus-summary-mark-as-read nil "X")))
- (gnus-execute field regexp command nil (not all))
- )))
-
-(defun gnus-execute (field regexp form &optional backward ignore-marked)
- "If FIELD of article header matches REGEXP, execute lisp FORM (or a string).
-If FIELD is an empty string (or nil), entire article body is searched for.
-If optional 1st argument BACKWARD is non-nil, do backward instead.
-If optional 2nd argument IGNORE-MARKED is non-nil, ignore articles
-marked as read or unread."
- (let ((function nil)
- (header nil)
- (article nil))
- (if (string-equal field "")
- (setq field nil))
- (if (null field)
- nil
- (or (stringp field)
- (setq field (symbol-name field)))
- ;; Get access function of header filed.
- (setq function (intern-soft (concat "gnus-header-" (downcase field))))
- (if (and function (fboundp function))
- (setq function (symbol-function function))
- (error "Unknown header field: \"%s\"" field)))
- ;; Make FORM funcallable.
- (if (and (listp form) (not (eq (car form) 'lambda)))
- (setq form (list 'lambda nil form)))
- ;; Starting from the current article.
- (or (and ignore-marked
- ;; Articles marked as read and unread should be ignored.
- (setq article (gnus-summary-article-number))
- (or (not (memq article gnus-newsgroup-unreads)) ;Marked as read.
- (memq article gnus-newsgroup-marked) ;Marked as unread.
- ))
- (gnus-execute-1 function regexp form))
- (while (gnus-summary-search-subject backward ignore-marked nil)
- (gnus-execute-1 function regexp form))
- ))
-
-(defun gnus-execute-1 (function regexp form)
- (save-excursion
- ;; The point of Summary buffer must be saved during execution.
- (let ((article (gnus-summary-article-number)))
- (if (null article)
- nil ;Nothing to do.
- (if function
- ;; Compare with header field.
- (let (;;(header (gnus-find-header-by-number
- ;; gnus-newsgroup-headers article))
- (header (gnus-get-header-by-number article))
- (value nil))
- (and header
- (progn
- (setq value (funcall function header))
- ;; Number (Lines:) or symbol must be converted to string.
- (or (stringp value)
- (setq value (prin1-to-string value)))
- (string-match regexp value))
- (if (stringp form) ;Keyboard macro.
- (execute-kbd-macro form)
- (funcall form))))
- ;; Search article body.
- (let ((gnus-current-article nil) ;Save article pointer.
- (gnus-last-article nil)
- (gnus-break-pages nil) ;No need to break pages.
- (gnus-mark-article-hook nil)) ;Inhibit marking as read.
- (message "Searching for article: %d..." article)
- (gnus-article-setup-buffer)
- (gnus-article-prepare article t)
- (if (save-excursion
- (set-buffer gnus-article-buffer)
- (goto-char (point-min))
- (re-search-forward regexp nil t))
- (if (stringp form) ;Keyboard macro.
- (execute-kbd-macro form)
- (funcall form))))
- ))
- )))
-
-;;; caesar-region written by phr@prep.ai.mit.edu Nov 86
-;;; modified by tower@prep Nov 86
-;;; Modified by umerin@flab.flab.Fujitsu.JUNET for ROT47.
-
-(defun gnus-caesar-region (&optional n)
- "Caesar rotation of region by N, default 13, for decrypting netnews.
-ROT47 will be performed for Japanese text in any case."
- (interactive (if current-prefix-arg ; Was there a prefix arg?
- (list (prefix-numeric-value current-prefix-arg))
- (list nil)))
- (cond ((not (numberp n)) (setq n 13))
- (t (setq n (mod n 26)))) ;canonicalize N
- (if (not (zerop n)) ; no action needed for a rot of 0
- (progn
- (if (or (not (boundp 'caesar-translate-table))
- (/= (aref caesar-translate-table ?a) (+ ?a n)))
- (let ((i 0) (lower "abcdefghijklmnopqrstuvwxyz") upper)
- (message "Building caesar-translate-table...")
- (setq caesar-translate-table (make-vector 256 0))
- (while (< i 256)
- (aset caesar-translate-table i i)
- (setq i (1+ i)))
- (setq lower (concat lower lower) upper (upcase lower) i 0)
- (while (< i 26)
- (aset caesar-translate-table (+ ?a i) (aref lower (+ i n)))
- (aset caesar-translate-table (+ ?A i) (aref upper (+ i n)))
- (setq i (1+ i)))
- ;; ROT47 for Japanese text.
- ;; Thanks to ichikawa@flab.fujitsu.junet.
- (setq i 161)
- (let ((t1 (logior ?O 128))
- (t2 (logior ?! 128))
- (t3 (logior ?~ 128)))
- (while (< i 256)
- (aset caesar-translate-table i
- (let ((v (aref caesar-translate-table i)))
- (if (<= v t1) (if (< v t2) v (+ v 47))
- (if (<= v t3) (- v 47) v))))
- (setq i (1+ i))))
- (message "Building caesar-translate-table...done")))
- (let ((from (region-beginning))
- (to (region-end))
- (i 0) str len)
- (setq str (buffer-substring from to))
- (setq len (length str))
- (while (< i len)
- (aset str i (aref caesar-translate-table (aref str i)))
- (setq i (1+ i)))
- (goto-char from)
- (delete-region from to)
- (insert str)))))
-
-;; Functions accessing headers.
-;; Functions are more convenient than macros in some case.
-
-(defun gnus-header-number (header)
- "Return article number in HEADER."
- (nntp-header-number header))
-
-(defun gnus-header-subject (header)
- "Return subject string in HEADER."
- (nntp-header-subject header))
-
-(defun gnus-header-from (header)
- "Return author string in HEADER."
- (nntp-header-from header))
-
-(defun gnus-header-xref (header)
- "Return xref string in HEADER."
- (nntp-header-xref header))
-
-(defun gnus-header-lines (header)
- "Return lines in HEADER."
- (nntp-header-lines header))
-
-(defun gnus-header-date (header)
- "Return date in HEADER."
- (nntp-header-date header))
-
-(defun gnus-header-id (header)
- "Return Id in HEADER."
- (nntp-header-id header))
-
-(defun gnus-header-references (header)
- "Return references in HEADER."
- (nntp-header-references header))
-
-
-;;;
-;;; Article savers.
-;;;
-
-(defun gnus-output-to-rmail (file-name)
- "Append the current article to an Rmail file named FILE-NAME."
- (require 'rmail)
- ;; Most of these codes are borrowed from rmailout.el.
- (setq file-name (expand-file-name file-name))
- (setq rmail-default-rmail-file file-name)
- (let ((artbuf (current-buffer))
- (tmpbuf (get-buffer-create " *GNUS-output*")))
- (save-excursion
- (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")))
- (set-buffer tmpbuf)
- (buffer-flush-undo (current-buffer))
- (erase-buffer)
- (insert-buffer-substring artbuf)
- (gnus-convert-article-to-rmail)
- ;; Decide whether to append to a file or to an Emacs buffer.
- (let ((outbuf (get-file-buffer file-name)))
- (if (not outbuf)
- (append-to-file (point-min) (point-max) file-name)
- ;; File has been visited, in buffer OUTBUF.
- (set-buffer outbuf)
- (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 (widen)
- (narrow-to-region (point-max) (point-max))))
- (insert-buffer-substring tmpbuf)
- (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))))))
- )
- (kill-buffer tmpbuf)
- ))
-
-(defun gnus-output-to-file (file-name)
- "Append the current article to a file named FILE-NAME."
- (setq file-name (expand-file-name file-name))
- (let ((artbuf (current-buffer))
- (tmpbuf (get-buffer-create " *GNUS-output*")))
- (save-excursion
- (set-buffer tmpbuf)
- (buffer-flush-undo (current-buffer))
- (erase-buffer)
- (insert-buffer-substring artbuf)
- ;; Append newline at end of the buffer as separator, and then
- ;; save it to file.
- (goto-char (point-max))
- (insert "\n")
- (append-to-file (point-min) (point-max) file-name))
- (kill-buffer tmpbuf)
- ))
-
-(defun gnus-convert-article-to-rmail ()
- "Convert article in current buffer to Rmail message format."
- (let ((buffer-read-only nil))
- ;; Convert article directly into Babyl format.
- ;; Suggested by Rob Austein <sra@lcs.mit.edu>
- (goto-char (point-min))
- (insert "\^L\n0, unseen,,\n*** EOOH ***\n")
- (while (search-forward "\n\^_" nil t) ;single char
- (replace-match "\n^_")) ;2 chars: "^" and "_"
- (goto-char (point-max))
- (insert "\^_")))
-
-;;(defun gnus-convert-article-to-rmail ()
-;; "Convert article in current buffer to Rmail message format."
-;; (let ((buffer-read-only nil))
-;; ;; Insert special header of Unix mail.
-;; (goto-char (point-min))
-;; (insert "From "
-;; (or (mail-strip-quoted-names (mail-fetch-field "from"))
-;; "unknown")
-;; " " (current-time-string) "\n")
-;; ;; Stop quoting `From' since this seems unnecessary in most cases.
-;; ;; ``Quote'' "\nFrom " as "\n>From "
-;; ;;(while (search-forward "\nFrom " nil t)
-;; ;; (forward-char -5)
-;; ;; (insert ?>))
-;; ;; Convert article to babyl format.
-;; (rmail-convert-to-babyl-format)
-;; ))
-
-
-;;;
-;;; Internal functions.
-;;;
-
-(defun gnus-start-news-server (&optional confirm)
- "Open network stream to remote NNTP server.
-If optional argument CONFIRM is non-nil, ask you host that NNTP server
-is running even if it is defined.
-Run `gnus-open-server-hook' just before opening news server."
- (if (gnus-server-opened)
- ;; Stream is already opened.
- nil
- ;; Open NNTP server.
- (if (or confirm
- (null gnus-nntp-server))
- ;; If someone has set the service to nil, then this should always
- ;; be the local host.
- (if gnus-nntp-service
- (if (and (boundp 'gnus-secondary-servers) gnus-secondary-servers)
- ;; Read server name with completion.
- (setq gnus-nntp-server
- (completing-read "NNTP server: "
- (cons (list gnus-nntp-server)
- gnus-secondary-servers)
- nil nil gnus-nntp-server))
- (setq gnus-nntp-server
- (read-string "NNTP server: " gnus-nntp-server)))
- (setq gnus-nntp-server "")))
- ;; If no server name is given, local host is assumed.
- (if (or (string-equal gnus-nntp-server "")
- (string-equal gnus-nntp-server "::")) ;RMS preference.
- (setq gnus-nntp-server (system-name)))
- ;; gnus-nntp-server must be either (system-name), ':DIRECTORY', or
- ;; nntp server name. I mean '::' cannot be a value of
- ;; gnus-nntp-server.
- (cond ((and (null gnus-nntp-service)
- (string-equal gnus-nntp-server (system-name)))
- (require 'nnspool)
- (gnus-define-access-method 'nnspool)
- (message "Looking up local news spool..."))
- ((string-match ":" gnus-nntp-server)
- ;; :DIRECTORY
- (require 'mhspool)
- (gnus-define-access-method 'mhspool)
- (message "Looking up private directory..."))
- (t
- (gnus-define-access-method 'nntp)
- (message "Connecting to NNTP server on %s..." gnus-nntp-server)))
- (run-hooks 'gnus-open-server-hook)
- (cond ((gnus-server-opened) ;Maybe opened in gnus-open-server-hook.
- (message ""))
- ((gnus-open-server gnus-nntp-server gnus-nntp-service)
- (message ""))
- (t
- (error "%s"
- (gnus-nntp-message
- (format "Cannot open NNTP server on %s" gnus-nntp-server)))))
- ))
-
-;; Dummy functions used only once. Should return nil.
-(defun gnus-server-opened () nil)
-(defun gnus-close-server () nil)
-
-(defun gnus-nntp-message (&optional message)
- "Return a message returned from NNTP server.
-If no message is available and optional MESSAGE is given, return it."
- (let ((status (gnus-status-message))
- (message (or message "")))
- (if (and (stringp status)
- (> (length status) 0))
- status message)))
-
-(defun gnus-define-access-method (method &optional access-methods)
- "Define access functions for the access METHOD.
-Methods definition is taken from optional argument ACCESS-METHODS or
-the variable `gnus-access-methods'."
- (let ((bindings
- (cdr (assoc method (or access-methods gnus-access-methods)))))
- (if (null bindings)
- (error "Unknown access method: %s" method)
- ;; Should not use symbol-function here since overload does not work.
- (while bindings
- ;; Alist syntax is different from that of 3.14.3.
- (fset (car (car bindings)) (car (cdr (car bindings))))
- (setq bindings (cdr bindings)))
- )))
-
-(defun gnus-select-newsgroup (group &optional show-all)
- "Select newsgroup GROUP.
-If optional argument SHOW-ALL is non-nil, all of articles in the group
-are selected."
- ;; Make sure a connection to NNTP server is alive.
- (gnus-start-news-server)
- (if (gnus-request-group group)
- (let ((articles nil))
- (setq gnus-newsgroup-name group)
- (setq gnus-newsgroup-unreads
- (gnus-uncompress-sequence
- (nthcdr 2 (gnus-gethash group gnus-unread-hashtb))))
- (cond (show-all
- ;; Select all active articles.
- (setq articles
- (gnus-uncompress-sequence
- (nthcdr 2 (gnus-gethash group gnus-active-hashtb)))))
- (t
- ;; Select unread articles only.
- (setq articles gnus-newsgroup-unreads)))
- ;; Require confirmation if selecting large newsgroup.
- (setq gnus-newsgroup-unselected nil)
- (if (not (numberp gnus-large-newsgroup))
- nil
- (let ((selected nil)
- (number (length articles)))
- (if (> number gnus-large-newsgroup)
- (progn
- (condition-case ()
- (let ((input
- (read-string
- (format
- "How many articles from %s (default %d): "
- gnus-newsgroup-name number))))
- (setq selected
- (if (string-equal input "")
- number (string-to-int input))))
- (quit
- (setq selected 0)))
- (cond ((and (> selected 0)
- (< selected number))
- ;; Select last N articles.
- (setq articles (nthcdr (- number selected) articles)))
- ((and (< selected 0)
- (< (- 0 selected) number))
- ;; Select first N articles.
- (setq selected (- 0 selected))
- (setq articles (copy-sequence articles))
- (setcdr (nthcdr (1- selected) articles) nil))
- ((zerop selected)
- (setq articles nil))
- ;; Otherwise select all.
- )
- ;; Get unselected unread articles.
- (setq gnus-newsgroup-unselected
- (gnus-set-difference gnus-newsgroup-unreads articles))
- ))
- ))
- ;; Get headers list.
- (setq gnus-newsgroup-headers (gnus-retrieve-headers articles))
- ;; UNREADS may contain expired articles, so we have to remove
- ;; them from the list.
- (setq gnus-newsgroup-unreads
- (gnus-intersection gnus-newsgroup-unreads
- (mapcar
- (function
- (lambda (header)
- (nntp-header-number header)))
- gnus-newsgroup-headers)))
- ;; Marked article must be a subset of unread articles.
- (setq gnus-newsgroup-marked
- (gnus-intersection (append gnus-newsgroup-unselected
- gnus-newsgroup-unreads)
- (cdr
- (gnus-gethash group gnus-marked-hashtb))))
- ;; First and last article in this newsgroup.
- (setq gnus-newsgroup-begin
- (if gnus-newsgroup-headers
- (nntp-header-number (car gnus-newsgroup-headers))
- 0
- ))
- (setq gnus-newsgroup-end
- (if gnus-newsgroup-headers
- (nntp-header-number
- (gnus-last-element gnus-newsgroup-headers))
- 0
- ))
- ;; File name that an article was saved last.
- (setq gnus-newsgroup-last-rmail nil)
- (setq gnus-newsgroup-last-mail nil)
- (setq gnus-newsgroup-last-folder nil)
- (setq gnus-newsgroup-last-file nil)
- ;; Reset article pointer etc.
- (setq gnus-current-article nil)
- (setq gnus-current-headers nil)
- (setq gnus-current-history nil)
- (setq gnus-have-all-headers nil)
- (setq gnus-last-article nil)
- ;; Clear old hash tables for the variable gnus-newsgroup-headers.
- (gnus-clear-hashtables-for-newsgroup-headers)
- ;; GROUP is successfully selected.
- t
- )
- ))
-
-;; Hacking for making header search much faster.
-
-(defun gnus-get-header-by-number (number)
- "Return a header specified by a NUMBER.
-If you update the variable `gnus-newsgroup-headers', you must set the
-hash table `gnus-newsgroup-headers-hashtb-by-number' to nil to indicate
-rehash is necessary."
- (or gnus-newsgroup-headers-hashtb-by-number
- (gnus-make-headers-hashtable-by-number))
- (gnus-gethash (int-to-string number)
- gnus-newsgroup-headers-hashtb-by-number))
-
-(defun gnus-get-header-by-id (id)
- "Return a header specified by an ID.
-If you update the variable `gnus-newsgroup-headers', you must set the
-hash table `gnus-newsgroup-headers-hashtb-by-id' to nil to indicate
-rehash is necessary."
- (or gnus-newsgroup-headers-hashtb-by-id
- (gnus-make-headers-hashtable-by-id))
- (and (stringp id)
- (gnus-gethash id gnus-newsgroup-headers-hashtb-by-id)))
-
-(defun gnus-make-headers-hashtable-by-number ()
- "Make hashtable for the variable `gnus-newsgroup-headers' by number."
- (let ((header nil)
- (headers gnus-newsgroup-headers))
- (setq gnus-newsgroup-headers-hashtb-by-number
- (gnus-make-hashtable (length headers)))
- (while headers
- (setq header (car headers))
- (gnus-sethash (int-to-string (nntp-header-number header))
- header gnus-newsgroup-headers-hashtb-by-number)
- (setq headers (cdr headers))
- )))
-
-(defun gnus-make-headers-hashtable-by-id ()
- "Make hashtable for the variable `gnus-newsgroup-headers' by id."
- (let ((header nil)
- (headers gnus-newsgroup-headers))
- (setq gnus-newsgroup-headers-hashtb-by-id
- (gnus-make-hashtable (length headers)))
- (while headers
- (setq header (car headers))
- (gnus-sethash (nntp-header-id header)
- header gnus-newsgroup-headers-hashtb-by-id)
- (setq headers (cdr headers))
- )))
-
-(defun gnus-clear-hashtables-for-newsgroup-headers ()
- "Clear hash tables created for the variable `gnus-newsgroup-headers'."
- (setq gnus-newsgroup-headers-hashtb-by-id nil)
- (setq gnus-newsgroup-headers-hashtb-by-number nil))
-
-(defun gnus-more-header-backward ()
- "Find new header backward."
- (let ((first
- (car (nth 2 (gnus-gethash gnus-newsgroup-name gnus-active-hashtb))))
- (artnum gnus-newsgroup-begin)
- (header nil))
- (while (and (not header)
- (> artnum first))
- (setq artnum (1- artnum))
- (setq header (car (gnus-retrieve-headers (list artnum)))))
- header
- ))
-
-(defun gnus-more-header-forward ()
- "Find new header forward."
- (let ((last
- (cdr (nth 2 (gnus-gethash gnus-newsgroup-name gnus-active-hashtb))))
- (artnum gnus-newsgroup-end)
- (header nil))
- (while (and (not header)
- (< artnum last))
- (setq artnum (1+ artnum))
- (setq header (car (gnus-retrieve-headers (list artnum)))))
- header
- ))
-
-(defun gnus-extend-newsgroup (header &optional backward)
- "Extend newsgroup selection with HEADER.
-Optional argument BACKWARD means extend toward backward."
- (if header
- (let ((artnum (nntp-header-number header)))
- (setq gnus-newsgroup-headers
- (if backward
- (cons header gnus-newsgroup-headers)
- (append gnus-newsgroup-headers (list header))))
- ;; Clear current hash tables for the variable gnus-newsgroup-headers.
- (gnus-clear-hashtables-for-newsgroup-headers)
- ;; We have to update unreads and unselected, but don't have to
- ;; care about gnus-newsgroup-marked.
- (if (memq artnum gnus-newsgroup-unselected)
- (setq gnus-newsgroup-unreads
- (cons artnum gnus-newsgroup-unreads)))
- (setq gnus-newsgroup-unselected
- (delq artnum gnus-newsgroup-unselected))
- (setq gnus-newsgroup-begin (min gnus-newsgroup-begin artnum))
- (setq gnus-newsgroup-end (max gnus-newsgroup-end artnum))
- )))
-
-(defun gnus-mark-article-as-read (article)
- "Remember that ARTICLE is marked as read."
- ;; Remove from unread and marked list.
- (setq gnus-newsgroup-unreads
- (delq article gnus-newsgroup-unreads))
- (setq gnus-newsgroup-marked
- (delq article gnus-newsgroup-marked)))
-
-(defun gnus-mark-article-as-unread (article &optional clear-mark)
- "Remember that ARTICLE is marked as unread.
-Optional argument CLEAR-MARK means ARTICLE should not be remembered
-that it was marked as read once."
- ;; Add to unread list.
- (or (memq article gnus-newsgroup-unreads)
- (setq gnus-newsgroup-unreads
- (cons article gnus-newsgroup-unreads)))
- ;; If CLEAR-MARK is non-nil, the article must be removed from marked
- ;; list. Otherwise, it must be added to the list.
- (if clear-mark
- (setq gnus-newsgroup-marked
- (delq article gnus-newsgroup-marked))
- (or (memq article gnus-newsgroup-marked)
- (setq gnus-newsgroup-marked
- (cons article gnus-newsgroup-marked)))))
-
-(defun gnus-clear-system ()
- "Clear all variables and buffer."
- ;; Clear GNUS variables.
- (let ((variables gnus-variable-list))
- (while variables
- (set (car variables) nil)
- (setq variables (cdr variables))))
- ;; Clear other internal variables.
- (setq gnus-newsrc-hashtb nil)
- (setq gnus-marked-hashtb nil)
- (setq gnus-killed-hashtb nil)
- (setq gnus-active-hashtb nil)
- (setq gnus-octive-hashtb nil)
- (setq gnus-unread-hashtb nil)
- (setq gnus-newsgroup-headers nil)
- (setq gnus-newsgroup-headers-hashtb-by-id nil)
- (setq gnus-newsgroup-headers-hashtb-by-number nil)
- ;; Kill the startup file.
- (and gnus-current-startup-file
- (get-file-buffer gnus-current-startup-file)
- (kill-buffer (get-file-buffer gnus-current-startup-file)))
- (setq gnus-current-startup-file nil)
- ;; Kill GNUS buffers.
- (let ((buffers gnus-buffer-list))
- (while buffers
- (if (get-buffer (car buffers))
- (kill-buffer (car buffers)))
- (setq buffers (cdr buffers))
- )))
-
-(defun gnus-configure-windows (action)
- "Configure GNUS windows according to the next ACTION.
-The ACTION is either a symbol, such as `summary', or a
-configuration list such as `(1 1 2)'. If ACTION is not a list,
-configuration list is got from the variable `gnus-window-configuration'."
- (let* ((windows
- (if (listp action)
- action (car (cdr (assq action gnus-window-configuration)))))
- (grpwin (get-buffer-window gnus-group-buffer))
- (subwin (get-buffer-window gnus-summary-buffer))
- (artwin (get-buffer-window gnus-article-buffer))
- (winsum nil)
- (height nil)
- (grpheight 0)
- (subheight 0)
- (artheight 0)
- ;; Make split-window-vertically leave focus in upper window.
- (split-window-keep-point t))
- (if (or (null windows) ;No configuration is specified.
- (and (eq (null grpwin)
- (zerop (nth 0 windows)))
- (eq (null subwin)
- (zerop (nth 1 windows)))
- (eq (null artwin)
- (zerop (nth 2 windows)))))
- ;; No need to change window configuration.
- nil
- (select-window (or grpwin subwin artwin (selected-window)))
- ;; First of all, compute the height of each window.
- (cond (gnus-use-full-window
- ;; Take up the entire screen.
- (delete-other-windows)
- (setq height (window-height (selected-window))))
- (t
- (setq height (+ (if grpwin (window-height grpwin) 0)
- (if subwin (window-height subwin) 0)
- (if artwin (window-height artwin) 0)))))
- ;; The Newsgroup buffer exits always. So, use it to extend the
- ;; Group window so as to get enough window space.
- (switch-to-buffer gnus-group-buffer 'norecord)
- (and (get-buffer gnus-summary-buffer)
- (delete-windows-on gnus-summary-buffer))
- (and (get-buffer gnus-article-buffer)
- (delete-windows-on gnus-article-buffer))
- ;; Compute expected window height.
- (setq winsum (apply (function +) windows))
- (if (not (zerop (nth 0 windows)))
- (setq grpheight (max window-min-height
- (/ (* height (nth 0 windows)) winsum))))
- (if (not (zerop (nth 1 windows)))
- (setq subheight (max window-min-height
- (/ (* height (nth 1 windows)) winsum))))
- (if (not (zerop (nth 2 windows)))
- (setq artheight (max window-min-height
- (/ (* height (nth 2 windows)) winsum))))
- (setq height (+ grpheight subheight artheight))
- (enlarge-window (max 0 (- height (window-height (selected-window)))))
- ;; Then split the window.
- (and (not (zerop artheight))
- (or (not (zerop grpheight))
- (not (zerop subheight)))
- (split-window-vertically (+ grpheight subheight)))
- (and (not (zerop grpheight))
- (not (zerop subheight))
- (split-window-vertically grpheight))
- ;; Then select buffers in each window.
- (and (not (zerop grpheight))
- (progn
- (switch-to-buffer gnus-group-buffer 'norecord)
- (other-window 1)))
- (and (not (zerop subheight))
- (progn
- (switch-to-buffer gnus-summary-buffer 'norecord)
- (other-window 1)))
- (and (not (zerop artheight))
- (progn
- ;; If Article buffer does not exist, it will be created
- ;; and initialized.
- (gnus-article-setup-buffer)
- (switch-to-buffer gnus-article-buffer 'norecord)))
- )
- ))
-
-(defun gnus-find-header-by-number (headers number)
- "Return a header which is a element of HEADERS and has NUMBER."
- (let ((found nil))
- (while (and headers (not found))
- ;; We cannot use `=' to accept non-numeric NUMBER.
- (if (eq number (nntp-header-number (car headers)))
- (setq found (car headers)))
- (setq headers (cdr headers)))
- found
- ))
-
-(defun gnus-find-header-by-id (headers id)
- "Return a header which is a element of HEADERS and has Message-ID."
- (let ((found nil))
- (while (and headers (not found))
- (if (string-equal id (nntp-header-id (car headers)))
- (setq found (car headers)))
- (setq headers (cdr headers)))
- found
- ))
-
-(defun gnus-version ()
- "Version numbers of this version of GNUS."
- (interactive)
- (cond ((and (boundp 'mhspool-version) (boundp 'nnspool-version))
- (message "%s; %s; %s; %s"
- gnus-version nntp-version nnspool-version mhspool-version))
- ((boundp 'mhspool-version)
- (message "%s; %s; %s"
- gnus-version nntp-version mhspool-version))
- ((boundp 'nnspool-version)
- (message "%s; %s; %s"
- gnus-version nntp-version nnspool-version))
- (t
- (message "%s; %s" gnus-version nntp-version))))
-
-(defun gnus-info-find-node ()
- "Find Info documentation of GNUS."
- (interactive)
- (require 'info)
- ;; Enlarge info window if needed.
- (cond ((eq major-mode 'gnus-group-mode)
- (gnus-configure-windows '(1 0 0)) ;Take all windows.
- (pop-to-buffer gnus-group-buffer))
- ((eq major-mode 'gnus-summary-mode)
- (gnus-configure-windows '(0 1 0)) ;Take all windows.
- (pop-to-buffer gnus-summary-buffer)))
- (Info-goto-node (car (cdr (assq major-mode gnus-info-nodes)))))
-
-(defun gnus-overload-functions (&optional overloads)
- "Overload functions specified by optional argument OVERLOADS.
-If nothing is specified, use the variable `gnus-overload-functions'."
- (let ((defs nil)
- (overloads (or overloads gnus-overload-functions)))
- (while overloads
- (setq defs (car overloads))
- (setq overloads (cdr overloads))
- ;; Load file before overloading function if necessary. Make
- ;; sure we cannot use `require' always.
- (and (not (fboundp (car defs)))
- (car (cdr (cdr defs)))
- (load (car (cdr (cdr defs))) nil 'nomessage))
- (fset (car defs) (car (cdr defs)))
- )))
-
-(defun gnus-make-threads (newsgroup-headers)
- "Make conversation threads tree from NEWSGROUP-HEADERS."
- (let ((headers newsgroup-headers)
- (refer nil)
- (h nil)
- (d nil)
- (roots nil)
- (dependencies nil))
- ;; Make message dependency alist.
- (while headers
- (setq h (car headers))
- (setq headers (cdr headers))
- ;; Ignore invalid headers.
- (if (vectorp h) ;Depends on nntp.el.
- (progn
- ;; Ignore broken references, e.g "<123@a.b.c".
- (setq refer (nntp-header-references h))
- (setq d (and refer
- (string-match "\\(<[^<>]+>\\)[^>]*$" refer)
-;; (gnus-find-header-by-id
-;; newsgroup-headers
-;; (substring refer (match-beginning 1) (match-end 1)))
- ;; In fact if the variable newsgroup-headers
- ;; is not 'equal' to the variable
- ;; gnus-newsgroup-headers, the following
- ;; function call may return bogus value.
- (gnus-get-header-by-id
- (substring refer (match-beginning 1) (match-end 1)))
- ))
- ;; Check subject equality.
- (or gnus-thread-ignore-subject
- (null d)
- (string-equal (gnus-simplify-subject
- (nntp-header-subject h) 're)
- (gnus-simplify-subject
- (nntp-header-subject d) 're))
- ;; H should be a thread root.
- (setq d nil))
- ;; H depends on D.
- (setq dependencies
- (cons (cons h d) dependencies))
- ;; H is a thread root.
- (if (null d)
- (setq roots (cons h roots)))
- ))
- )
- ;; Make complete threads from the roots.
- ;; Note: dependencies are in reverse order, but
- ;; gnus-make-threads-1 processes it in reverse order again. So,
- ;; we don't have to worry about it.
- (mapcar
- (function
- (lambda (root)
- (gnus-make-threads-1 root dependencies))) (nreverse roots))
- ))
-
-(defun gnus-make-threads-1 (parent dependencies)
- (let ((children nil)
- (d nil)
- (depends dependencies))
- ;; Find children.
- (while depends
- (setq d (car depends))
- (setq depends (cdr depends))
- (and (cdr d)
- (eq (nntp-header-id parent) (nntp-header-id (cdr d)))
- (setq children (cons (car d) children))))
- ;; Go down.
- (cons parent
- (mapcar
- (function
- (lambda (child)
- (gnus-make-threads-1 child dependencies))) children))
- ))
-
-(defun gnus-narrow-to-page (&optional arg)
- "Make text outside current page invisible except for page delimiter.
-A numeric arg specifies to move forward or backward by that many pages,
-thus showing a page other than the one point was originally in."
- (interactive "P")
- (setq arg (if arg (prefix-numeric-value arg) 0))
- (save-excursion
- (forward-page -1) ;Beginning of current page.
- (widen)
- (if (> arg 0)
- (forward-page arg)
- (if (< arg 0)
- (forward-page (1- arg))))
- ;; Find the end of the page.
- (forward-page)
- ;; If we stopped due to end of buffer, stay there.
- ;; If we stopped after a page delimiter, put end of restriction
- ;; at the beginning of that line.
- ;; These are commented out.
- ;; (if (save-excursion (beginning-of-line)
- ;; (looking-at page-delimiter))
- ;; (beginning-of-line))
- (narrow-to-region (point)
- (progn
- ;; Find the top of the page.
- (forward-page -1)
- ;; If we found beginning of buffer, stay there.
- ;; If extra text follows page delimiter on same line,
- ;; include it.
- ;; Otherwise, show text starting with following line.
- (if (and (eolp) (not (bobp)))
- (forward-line 1))
- (point)))
- ))
-
-;; Create hash table for alist, such as gnus-newsrc-assoc,
-;; gnus-killed-assoc, and gnus-marked-assoc.
-
-(defun gnus-make-hashtable-from-alist (alist &optional hashsize)
- "Return hash table for ALIST.
-Optional argument HASHSIZE specifies the hashtable size.
-Hash key is a car of alist element, which must be a string."
- (let ((hashtb (gnus-make-hashtable (or hashsize (length alist)))))
- (while alist
- (gnus-sethash (car (car alist)) ;Newsgroup name
- (car alist) ;Alist element
- hashtb)
- (setq alist (cdr alist)))
- hashtb
- ))
-
-(defun gnus-last-element (list)
- "Return last element of LIST."
- (let ((last nil))
- (while list
- (if (null (cdr list))
- (setq last (car list)))
- (setq list (cdr list)))
- last
- ))
-
-(defun gnus-set-difference (list1 list2)
- "Return a list of elements of LIST1 that do not appear in LIST2."
- (let ((list1 (copy-sequence list1)))
- (while list2
- (setq list1 (delq (car list2) list1))
- (setq list2 (cdr list2)))
- list1
- ))
-
-(defun gnus-intersection (list1 list2)
- "Return a list of elements that appear in both LIST1 and LIST2."
- (let ((result nil))
- (while list2
- (if (memq (car list2) list1)
- (setq result (cons (car list2) result)))
- (setq list2 (cdr list2)))
- result
- ))
-
-
-;;;
-;;; Get information about active articles, already read articles, and
-;;; still unread articles.
-;;;
-
-;; GNUS internal format of gnus-newsrc-assoc and gnus-killed-assoc:
-;; (("general" t (1 . 1))
-;; ("misc" t (1 . 10) (12 . 15))
-;; ("test" nil (1 . 99)) ...)
-;; GNUS internal format of gnus-marked-assoc:
-;; (("general" 1 2 3)
-;; ("misc" 2) ...)
-;; GNUS internal format of gnus-active-hashtb:
-;; (("general" t (1 . 1))
-;; ("misc" t (1 . 10))
-;; ("test" nil (1 . 99)) ...)
-;; GNUS internal format of gnus-unread-hashtb:
-;; (("general" 1 (1 . 1))
-;; ("misc" 14 (1 . 10) (12 . 15))
-;; ("test" 99 (1 . 99)) ...)
-
-(defun gnus-setup-news (&optional rawfile)
- "Setup news information.
-If optional argument RAWFILE is non-nil, force to read raw startup file."
- (let ((init (not (and gnus-newsrc-assoc
- gnus-active-hashtb
- gnus-unread-hashtb
- (not rawfile)
- ))))
- ;; We have to clear some variables to re-initialize news info.
- (if init
- (setq gnus-newsrc-assoc nil
- gnus-active-hashtb nil
- gnus-unread-hashtb nil))
- (gnus-read-active-file)
- ;; Initialize only once.
- (if init
- (progn
- ;; Get distributions only once.
- (gnus-read-distributions-file)
- ;; newsrc file must be read after reading active file since
- ;; its size is used to guess the size of gnus-newsrc-hashtb.
- (gnus-read-newsrc-file rawfile)
- ))
- (gnus-expire-marked-articles)
- (gnus-get-unread-articles)
-
- ;; newsgroups description
- (if gnus-newsgroups-display
- (if (not gnus-newsgroups-alist)
- ;; Get newsgroups file only once.
- (gnus-newsgroups-retrieve-description)))
-
- (setq gnus-newsgroups-hashtb (gnus-make-hashtable-from-alist gnus-newsgroups-alist))
-
- ;; Check new newsgroups and subscribe them.
- (if init
- (let ((new-newsgroups (gnus-find-new-newsgroups)))
- (while new-newsgroups
- (funcall gnus-subscribe-newsgroup-method (car new-newsgroups))
- (setq new-newsgroups (cdr new-newsgroups))
- )))
- ))
-
-(defun gnus-add-newsgroup (newsgroup)
- "Subscribe new NEWSGROUP safely and put it at top."
- (and (null (gnus-gethash newsgroup gnus-newsrc-hashtb)) ;Really new?
- (gnus-gethash newsgroup gnus-active-hashtb) ;Really exist?
- (gnus-insert-newsgroup (or (gnus-gethash newsgroup gnus-killed-hashtb)
- (list newsgroup t))
- (car (car gnus-newsrc-assoc)))))
-
-(defun gnus-find-new-newsgroups ()
- "Looking for new newsgroups and return names.
-`-n' option of options line in `.newsrc' file is recognized."
- (let ((group nil)
- (new-newsgroups nil))
- (mapatoms
- (function
- (lambda (sym)
- (setq group (symbol-name sym))
- ;; Taking account of `-n' option.
- (and (or (null gnus-newsrc-options-n-no)
- (not (string-match gnus-newsrc-options-n-no group))
- (and gnus-newsrc-options-n-yes
- (string-match gnus-newsrc-options-n-yes group)))
- (null (gnus-gethash group gnus-killed-hashtb)) ;Ignore killed.
- (null (gnus-gethash group gnus-newsrc-hashtb)) ;Really new.
- ;; Find new newsgroup.
- (setq new-newsgroups
- (cons group new-newsgroups)))
- ))
- gnus-active-hashtb)
- ;; Return new newsgroups.
- new-newsgroups
- ))
-
-(defun gnus-kill-newsgroup (group)
- "Kill GROUP from `gnus-newsrc-assoc', `.newsrc' and `gnus-unread-hashtb'."
- (let ((info (gnus-gethash group gnus-newsrc-hashtb)))
- (if (null info)
- nil
- ;; Delete from gnus-newsrc-assoc and gnus-newsrc-hashtb.
- (setq gnus-newsrc-assoc (delq info gnus-newsrc-assoc))
- (gnus-sethash group nil gnus-newsrc-hashtb)
- ;; Add to gnus-killed-assoc and gnus-killed-hashtb.
- (setq gnus-killed-assoc
- (cons info
- (delq (gnus-gethash group gnus-killed-hashtb)
- gnus-killed-assoc)))
- (gnus-sethash group info gnus-killed-hashtb)
- ;; Clear unread hashtable.
- ;; Thanks cwitty@csli.Stanford.EDU (Carl Witty).
- (gnus-sethash group nil gnus-unread-hashtb)
- ;; Then delete from .newsrc
- (gnus-update-newsrc-buffer group 'delete)
- ;; Return the deleted newsrc entry.
- info
- )))
-
-(defun gnus-insert-newsgroup (info &optional next)
- "Insert newsrc INFO entry before NEXT.
-If optional argument NEXT is nil, appended to the last."
- (if (null info)
- (error "Invalid argument: %s" info))
- (let* ((group (car info)) ;Newsgroup name.
- (range
- (gnus-difference-of-range
- (nth 2 (gnus-gethash group gnus-active-hashtb)) (nthcdr 2 info))))
- ;; Check duplication.
- (if (gnus-gethash group gnus-newsrc-hashtb)
- (error "Duplicated: %s" group))
- ;; Insert to gnus-newsrc-assoc and gnus-newsrc-hashtb.
- (if (string-equal next (car (car gnus-newsrc-assoc)))
- (setq gnus-newsrc-assoc
- (cons info gnus-newsrc-assoc))
- (let ((found nil)
- (rest (cdr gnus-newsrc-assoc))
- (tail gnus-newsrc-assoc))
- ;; Seach insertion point.
- (while (and (not found) rest)
- (if (string-equal next (car (car rest)))
- (setq found t)
- (setq rest (cdr rest))
- (setq tail (cdr tail))
- ))
- ;; Find it.
- (if (consp tail)
- (setcdr tail (cons info rest))
- ;; gnus-newsrc-assoc must be nil.
- (setq gnus-newsrc-assoc
- (append gnus-newsrc-assoc (cons info rest))))
- ))
- (gnus-sethash group info gnus-newsrc-hashtb)
- ;; Delete from gnus-killed-assoc and gnus-killed-hashtb.
- (setq gnus-killed-assoc
- (delq (gnus-gethash group gnus-killed-hashtb) gnus-killed-assoc))
- (gnus-sethash group nil gnus-killed-hashtb)
- ;; Then insert to .newsrc.
- (gnus-update-newsrc-buffer group nil next)
- ;; Add to gnus-unread-hashtb.
- (gnus-sethash group
- (cons group ;Newsgroup name.
- (cons (gnus-number-of-articles range) range))
- gnus-unread-hashtb)
- ))
-
-(defun gnus-check-killed-newsgroups ()
- "Update `gnus-killed-assoc' based on `gnus-newsrc-assoc'.
-Update `gnus-killed-hashtb' also."
- (let ((group nil)
- (new-killed nil)
- (old-killed gnus-killed-assoc))
- (while old-killed
- (setq group (car (car old-killed)))
- (and (or (null gnus-newsrc-options-n-no)
- (not (string-match gnus-newsrc-options-n-no group))
- (and gnus-newsrc-options-n-yes
- (string-match gnus-newsrc-options-n-yes group)))
- (null (gnus-gethash group gnus-newsrc-hashtb)) ;No duplication.
- ;; Subscribed in options line and not in gnus-newsrc-assoc.
- (setq new-killed
- (cons (car old-killed) new-killed)))
- (setq old-killed (cdr old-killed))
- )
- (setq gnus-killed-assoc (nreverse new-killed))
- (setq gnus-killed-hashtb
- (gnus-make-hashtable-from-alist gnus-killed-assoc))
- ))
-
-(defun gnus-check-bogus-newsgroups (&optional confirm)
- "Delete bogus newsgroups.
-If optional argument CONFIRM is non-nil, confirm deletion of newsgroups."
- (let ((group nil) ;Newsgroup name temporary used.
- (old-newsrc gnus-newsrc-assoc)
- (new-newsrc nil)
- (bogus nil) ;List of bogus newsgroups.
- (old-killed gnus-killed-assoc)
- (new-killed nil)
- (old-marked gnus-marked-assoc)
- (new-marked nil))
- (message "Checking bogus newsgroups...")
- ;; Update gnus-newsrc-assoc and gnus-newsrc-hashtb.
- (while old-newsrc
- (setq group (car (car old-newsrc)))
- (if (or (gnus-gethash group gnus-active-hashtb)
- (and confirm
- (not (y-or-n-p
- (format "Delete bogus newsgroup: %s " group)))))
- ;; Active newsgroup.
- (setq new-newsrc (cons (car old-newsrc) new-newsrc))
- ;; Found a bogus newsgroup.
- (setq bogus (cons group bogus)))
- (setq old-newsrc (cdr old-newsrc))
- )
- (setq gnus-newsrc-assoc (nreverse new-newsrc))
- (setq gnus-newsrc-hashtb
- (gnus-make-hashtable-from-alist gnus-newsrc-assoc))
- ;; Update gnus-killed-assoc and gnus-killed-hashtb.
- ;; The killed newsgroups are deleted without any confirmations.
- (while old-killed
- (setq group (car (car old-killed)))
- (and (gnus-gethash group gnus-active-hashtb)
- (null (gnus-gethash group gnus-newsrc-hashtb))
- ;; Active and really killed newsgroup.
- (setq new-killed (cons (car old-killed) new-killed)))
- (setq old-killed (cdr old-killed))
- )
- (setq gnus-killed-assoc (nreverse new-killed))
- (setq gnus-killed-hashtb
- (gnus-make-hashtable-from-alist gnus-killed-assoc))
- ;; Remove BOGUS from .newsrc file.
- (while bogus
- (gnus-update-newsrc-buffer (car bogus) 'delete)
- (setq bogus (cdr bogus)))
- ;; Update gnus-marked-assoc and gnus-marked-hashtb.
- (while old-marked
- (setq group (car (car old-marked)))
- (if (and (cdr (car old-marked)) ;Non-empty?
- (gnus-gethash group gnus-newsrc-hashtb)) ;Not bogus?
- (setq new-marked (cons (car old-marked) new-marked)))
- (setq old-marked (cdr old-marked)))
- (setq gnus-marked-assoc new-marked)
- (setq gnus-marked-hashtb
- (gnus-make-hashtable-from-alist gnus-marked-assoc))
- (message "Checking bogus newsgroups...done")
- ))
-
-(defun gnus-get-unread-articles ()
- "Compute diffs between active and read articles."
- (let ((read gnus-newsrc-assoc)
- (group-info nil)
- (group-name nil)
- (active nil)
- (range nil))
- (message "Checking new news...")
- (or gnus-unread-hashtb
- (setq gnus-unread-hashtb
- (gnus-make-hashtable (length gnus-active-hashtb))))
- (while read
- (setq group-info (car read)) ;About one newsgroup
- (setq group-name (car group-info))
- (setq active (nth 2 (gnus-gethash group-name gnus-active-hashtb)))
- (if (and gnus-octive-hashtb
- ;; Is nothing changed?
- (equal active
- (nth 2 (gnus-gethash group-name gnus-octive-hashtb)))
- ;; Is this newsgroup in the unread hash table?
- (gnus-gethash group-name gnus-unread-hashtb)
- )
- nil ;Nothing to do.
- (setq range (gnus-difference-of-range active (nthcdr 2 group-info)))
- (gnus-sethash group-name
- (cons group-name ;Group name
- (cons (gnus-number-of-articles range)
- range)) ;Range of unread articles
- gnus-unread-hashtb)
- )
- (setq read (cdr read))
- )
- (message "Checking new news...done")
- ))
-
-(defun gnus-expire-marked-articles ()
- "Check expired article which is marked as unread."
- (let ((marked-assoc gnus-marked-assoc)
- (updated-assoc nil)
- (marked nil) ;Current marked info.
- (articles nil) ;List of marked articles.
- (updated nil) ;List of real marked.
- (begin nil))
- (while marked-assoc
- (setq marked (car marked-assoc))
- (setq articles (cdr marked))
- (setq updated nil)
- (setq begin
- (car (nth 2 (gnus-gethash (car marked) gnus-active-hashtb))))
- (while (and begin articles)
- (if (>= (car articles) begin)
- ;; This article is still active.
- (setq updated (cons (car articles) updated)))
- (setq articles (cdr articles)))
- (if updated
- (setq updated-assoc
- (cons (cons (car marked) updated) updated-assoc)))
- (setq marked-assoc (cdr marked-assoc)))
- (setq gnus-marked-assoc updated-assoc)
- (setq gnus-marked-hashtb
- (gnus-make-hashtable-from-alist gnus-marked-assoc))
- ))
-
-(defun gnus-mark-as-read-by-xref
- (group headers unreads &optional subscribed-only)
- "Mark articles as read using cross references and return updated newsgroups.
-Arguments are GROUP, HEADERS, UNREADS, and optional SUBSCRIBED-ONLY."
- (let ((xref-list nil)
- (header nil)
- (xrefs nil) ;One Xref: field info.
- (xref nil) ;(NEWSGROUP . ARTICLE)
- (gname nil) ;Newsgroup name
- (article nil)) ;Article number
- (while headers
- (setq header (car headers))
- (if (memq (nntp-header-number header) unreads)
- ;; This article is not yet marked as read.
- nil
- (setq xrefs (gnus-parse-xref-field (nntp-header-xref header)))
- ;; For each cross reference info. in one Xref: field.
- (while xrefs
- (setq xref (car xrefs))
- (setq gname (car xref)) ;Newsgroup name
- (setq article (cdr xref)) ;Article number
- (or (string-equal group gname) ;Ignore current newsgroup.
- ;; Ignore unsubscribed newsgroup if requested.
- (and subscribed-only
- (not (nth 1 (gnus-gethash gname gnus-newsrc-hashtb))))
- ;; Ignore article marked as unread.
- (memq article (cdr (gnus-gethash gname gnus-marked-hashtb)))
- (let ((group-xref (assoc gname xref-list)))
- (if group-xref
- (if (memq article (cdr group-xref))
- nil ;Alread marked.
- (setcdr group-xref (cons article (cdr group-xref))))
- ;; Create new assoc entry for GROUP.
- (setq xref-list (cons (list gname article) xref-list)))
- ))
- (setq xrefs (cdr xrefs))
- ))
- (setq headers (cdr headers)))
- ;; Mark cross referenced articles as read.
- (gnus-mark-xrefed-as-read xref-list)
- ;;(message "%s %s" (prin1-to-string unreads) (prin1-to-string xref-list))
- ;; Return list of updated group name.
- (mapcar (function car) xref-list)
- ))
-
-(defun gnus-parse-xref-field (xref-value)
- "Parse Xref: field value, and return list of `(group . article-id)'."
- (let ((xref-list nil)
- (xref-value (or xref-value "")))
- ;; Remove server host name.
- (if (string-match "^[ \t]*[^ \t,]+[ \t,]+\\(.*\\)$" xref-value)
- (setq xref-value (substring xref-value (match-beginning 1)))
- (setq xref-value nil))
- ;; Process each xref info.
- (while xref-value
- (if (string-match
- "^[ \t,]*\\([^ \t,]+\\):\\([0-9]+\\)[^0-9]*" xref-value)
- (progn
- (setq xref-list
- (cons
- (cons
- ;; Group name
- (substring xref-value (match-beginning 1) (match-end 1))
- ;; Article-ID
- (string-to-int
- (substring xref-value (match-beginning 2) (match-end 2))))
- xref-list))
- (setq xref-value (substring xref-value (match-end 2))))
- (setq xref-value nil)))
- ;; Return alist.
- xref-list
- ))
-
-(defun gnus-mark-xrefed-as-read (xrefs)
- "Update unread article information using XREFS alist."
- (let ((group nil)
- (idlist nil)
- (unread nil))
- (while xrefs
- (setq group (car (car xrefs)))
- (setq idlist (cdr (car xrefs)))
- (setq unread (gnus-uncompress-sequence
- (nthcdr 2 (gnus-gethash group gnus-unread-hashtb))))
- (while idlist
- (setq unread (delq (car idlist) unread))
- (setq idlist (cdr idlist)))
- (gnus-update-unread-articles group unread 'ignore)
- (setq xrefs (cdr xrefs))
- )))
-
-(defun gnus-update-unread-articles (group unread-list marked-list)
- "Update unread articles of GROUP using UNREAD-LIST and MARKED-LIST."
- (let ((active (nth 2 (gnus-gethash group gnus-active-hashtb)))
- (unread (gnus-gethash group gnus-unread-hashtb)))
- (if (or (null active) (null unread))
- ;; Ignore unknown newsgroup.
- nil
- ;; Update gnus-unread-hashtb.
- (if unread-list
- (setcdr (cdr unread)
- (gnus-compress-sequence unread-list))
- ;; All of the articles are read.
- (setcdr (cdr unread) '((0 . 0))))
- ;; Number of unread articles.
- (setcar (cdr unread)
- (gnus-number-of-articles (nthcdr 2 unread)))
- ;; Update gnus-newsrc-assoc.
- (if (> (car active) 0)
- ;; Articles from 1 to N are not active.
- (setq active (cons 1 (cdr active))))
- (setcdr (cdr (gnus-gethash group gnus-newsrc-hashtb))
- (gnus-difference-of-range active (nthcdr 2 unread)))
- ;; Update .newsrc buffer.
- (gnus-update-newsrc-buffer group)
- ;; Update gnus-marked-assoc.
- (if (listp marked-list) ;Includes NIL.
- (let ((marked (gnus-gethash group gnus-marked-hashtb)))
- (cond (marked ;There is an entry.
- (setcdr marked marked-list))
- (marked-list ;Non-NIL.
- (let ((info (cons group marked-list)))
- ;; hashtb must share the same cons cell.
- (setq gnus-marked-assoc
- (cons info gnus-marked-assoc))
- (gnus-sethash group info gnus-marked-hashtb)
- ))
- )))
- )))
-
-(defun gnus-read-active-file ()
- "Get active file from NNTP server."
- ;; Make sure a connection to NNTP server is alive.
- (gnus-start-news-server)
- (message "Reading active file...")
- (if (gnus-request-list) ;Get active file from server
- (save-excursion
- (set-buffer nntp-server-buffer)
- (gnus-active-to-gnus-format)
- (message "Reading active file...done"))
- (error "Cannot read active file from NNTP server.")))
-
-(defun gnus-active-to-gnus-format ()
- "Convert active file format to internal format.
-Lines matching `gnus-ignored-newsgroups' are ignored."
- ;; Delete unnecessary lines.
- (goto-char (point-min))
- ;;(delete-matching-lines "^to\\..*$")
- (delete-matching-lines gnus-ignored-newsgroups)
- ;; Save OLD active info.
- (setq gnus-octive-hashtb gnus-active-hashtb)
- ;; Make large enough hash table.
- (setq gnus-active-hashtb
- (gnus-make-hashtable (count-lines (point-min) (point-max))))
- ;; Store active file in hashtable.
- (goto-char (point-min))
- (while
- (re-search-forward
- "^\\([^ \t]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\([ymn]\\).*$"
- nil t)
- (gnus-sethash
- (buffer-substring (match-beginning 1) (match-end 1))
- (list (buffer-substring (match-beginning 1) (match-end 1))
- (string-equal
- "y" (buffer-substring (match-beginning 4) (match-end 4)))
- (cons (string-to-int
- (buffer-substring (match-beginning 3) (match-end 3)))
- (string-to-int
- (buffer-substring (match-beginning 2) (match-end 2)))))
- gnus-active-hashtb)
- ))
-
-(defun gnus-read-newsrc-file (&optional rawfile)
- "Read startup FILE.
-If optional argument RAWFILE is non-nil, the raw startup file is read."
- (setq gnus-current-startup-file (gnus-make-newsrc-file gnus-startup-file))
- ;; Reset variables which may be included in the quick startup file.
- (let ((variables gnus-variable-list))
- (while variables
- (set (car variables) nil)
- (setq variables (cdr variables))))
- (let* ((newsrc-file gnus-current-startup-file)
- (quick-file (concat newsrc-file ".el"))
- (quick-loaded nil))
- (save-excursion
- ;; Prepare .newsrc buffer.
- (set-buffer (find-file-noselect newsrc-file))
- ;; It is not so good idea turning off undo.
- ;;(buffer-flush-undo (current-buffer))
- ;; Load quick .newsrc to restore gnus-marked-assoc and
- ;; gnus-killed-assoc even if gnus-newsrc-assoc is out of date.
- (condition-case nil
- (progn
- (setq quick-loaded (load quick-file t t t))
- ;; Recreate hashtables.
- (setq gnus-killed-hashtb
- (gnus-make-hashtable-from-alist gnus-killed-assoc))
- (setq gnus-marked-hashtb
- (gnus-make-hashtable-from-alist gnus-marked-assoc))
- )
- (error nil))
- (cond ((and (not rawfile) ;Not forced to read the raw file.
- ;; .newsrc.el is newer than .newsrc.
- ;; Do it this way in case timestamps are identical
- ;; (on fast machines/disks).
- (not (file-newer-than-file-p newsrc-file quick-file))
- quick-loaded
- gnus-newsrc-assoc ;Really loaded?
- )
- ;; We don't have to read the raw startup file.
- ;; gnus-newsrc-assoc may be defined in the quick startup file.
- ;; So, we have to define the hashtable here.
- (setq gnus-newsrc-hashtb
- (gnus-make-hashtable-from-alist gnus-newsrc-assoc)))
- (t
- ;; Since .newsrc file is newer than quick file, read it.
- (message "Reading %s..." newsrc-file)
- (gnus-newsrc-to-gnus-format)
- (gnus-check-killed-newsgroups)
- (message "Reading %s...done" newsrc-file)))
- )))
-
-(defun gnus-make-newsrc-file (file)
- "Make server dependent file name by catenating FILE and server host name."
- (let* ((file (expand-file-name file nil))
- (real-file (concat file "-" gnus-nntp-server)))
- (if (file-exists-p real-file)
- real-file file)
- ))
-
-(defun gnus-newsrc-to-gnus-format ()
- "Parse current buffer as `.newsrc' file."
- (let ((newsgroup nil)
- (subscribe nil)
- (ranges nil)
- (subrange nil)
- (read-list nil))
- ;; We have to re-initialize these variable (except for
- ;; gnus-marked-assoc and gnus-killed-assoc) because quick startup
- ;; file may contain bogus values.
- (setq gnus-newsrc-options nil)
- (setq gnus-newsrc-options-n-yes nil)
- (setq gnus-newsrc-options-n-no nil)
- (setq gnus-newsrc-assoc nil)
- ;; Make large enough hash table.
- (setq gnus-newsrc-hashtb
- (gnus-make-hashtable
- (max (length gnus-active-hashtb)
- (count-lines (point-min) (point-max)))))
- ;; Save options line to variable.
- ;; Lines beginning with white spaces are treated as continuation
- ;; line. Refer man page of newsrc(5).
- (goto-char (point-min))
- (if (re-search-forward
- "^[ \t]*options[ \t]*\\(.*\\(\n[ \t]+.*\\)*\\)[ \t]*$" nil t)
- (progn
- ;; Save entire options line.
- (setq gnus-newsrc-options
- (buffer-substring (match-beginning 1) (match-end 1)))
- ;; Compile "-n" option.
- (if (string-match "\\(^\\|[ \t\n]\\)-n" gnus-newsrc-options)
- (let ((yes-and-no
- (gnus-parse-n-options
- (substring gnus-newsrc-options (match-end 0)))))
- (setq gnus-newsrc-options-n-yes (car yes-and-no))
- (setq gnus-newsrc-options-n-no (cdr yes-and-no))
- ))
- ))
- ;; Parse body of .newsrc file
- ;; Options line continuation lines must be also considered here.
- ;; Before supporting continuation lines, " newsgroup ! 1-5" was
- ;; okay, but now it is invalid. It should be "newsgroup! 1-5".
- (goto-char (point-min))
- ;; We used this regexp, but it caused overflows.
- ;; "^\\([^:! \t\n]+\\)\\([:!]\\)[ \t]*\\(.*\\)$"
- ;; Suggested by composer@bucsf.bu.edu (Jeff Kellem)
- ;; but no longer viable because of extensive backtracking in Emacs 19:
- ;; "^\\([^:! \t\n]+\\)\\([:!]\\)[ \t]*\\(\\(...\\)*.*\\)$"
- ;; but, the following causes trouble on some case:
- ;; "^\\([^:! \t\n]+\\)\\([:!]\\)[ \t]*\\(\\|[^ \t\n].*\\)$"
- ;; So now we don't try to match the tail of the line at all.
- ;; It's just as easy to extract it later.
- (while (re-search-forward "^\\([^:! \t\n]+\\)\\([:!]\\)"
- nil t)
- (setq newsgroup (buffer-substring (match-beginning 1) (match-end 1)))
- ;; Check duplications of newsgroups.
- ;; Note: Checking the duplications takes very long time.
- (if (gnus-gethash newsgroup gnus-newsrc-hashtb)
- (message "Ignore duplicated newsgroup: %s" newsgroup)
- (setq subscribe
- (string-equal
- ":" (buffer-substring (match-beginning 2) (match-end 2))))
- (skip-chars-forward " \t")
- (setq ranges (buffer-substring (point) (save-excursion
- (end-of-line) (point))))
- (setq read-list nil)
- (while (string-match "^[, \t]*\\([0-9-]+\\)" ranges)
- (setq subrange (substring ranges (match-beginning 1) (match-end 1)))
- (setq ranges (substring ranges (match-end 1)))
- (cond ((string-match "^\\([0-9]+\\)-\\([0-9]+\\)$" subrange)
- (setq read-list
- (cons
- (cons (string-to-int
- (substring subrange
- (match-beginning 1) (match-end 1)))
- (string-to-int
- (substring subrange
- (match-beginning 2) (match-end 2))))
- read-list)))
- ((string-match "^[0-9]+$" subrange)
- (setq read-list
- (cons (cons (string-to-int subrange)
- (string-to-int subrange))
- read-list)))
- (t
- (ding) (message "Ignoring bogus lines of %s" newsgroup)
- (sit-for 0))
- ))
- (setq gnus-newsrc-assoc
- (cons (cons newsgroup (cons subscribe (nreverse read-list)))
- gnus-newsrc-assoc))
- ;; Update gnus-newsrc-hashtb one by one.
- (gnus-sethash newsgroup (car gnus-newsrc-assoc) gnus-newsrc-hashtb)
- ))
- (setq gnus-newsrc-assoc (nreverse gnus-newsrc-assoc))
- ))
-
-(defun gnus-parse-n-options (options)
- "Parse -n NEWSGROUPS options and return a cons of YES and NO regexps."
- (let ((yes nil)
- (no nil)
- (yes-or-no nil) ;`!' or not.
- (newsgroup nil))
- ;; Parse each newsgroup description such as "comp.all". Commas
- ;; and white spaces can be a newsgroup separator.
- (while
- (string-match "^[ \t\n,]*\\(!?\\)\\([^- \t\n,][^ \t\n,]*\\)" options)
- (setq yes-or-no
- (substring options (match-beginning 1) (match-end 1)))
- (setq newsgroup
- (regexp-quote
- (substring options
- (match-beginning 2) (match-end 2))))
- (setq options (substring options (match-end 2)))
- ;; Rewrite "all" to ".+" not ".*". ".+" requires at least one
- ;; character.
- (while (string-match "\\(^\\|\\\\[.]\\)all\\(\\\\[.]\\|$\\)" newsgroup)
- (setq newsgroup
- (concat (substring newsgroup 0 (match-end 1))
- ".+"
- (substring newsgroup (match-beginning 2)))))
- ;; It is yes or no.
- (cond ((string-equal yes-or-no "!")
- (setq no (cons newsgroup no)))
- ((string-equal newsgroup ".+")) ;Ignore `all'.
- (t
- (setq yes (cons newsgroup yes))))
- )
- ;; Make a cons of regexps from parsing result.
- ;; We have to append \(\.\|$\) to prevent matching substring of
- ;; newsgroup. For example, "jp.net" should not match with
- ;; "jp.network".
- ;; Fixes for large regexp problems are from yonezu@nak.math.keio.ac.jp.
- (cons (if yes
- (concat "^\\("
- (apply (function concat)
- (mapcar
- (function
- (lambda (newsgroup)
- (concat newsgroup "\\|")))
- (cdr yes)))
- (car yes) "\\)\\(\\.\\|$\\)"))
- (if no
- (concat "^\\("
- (apply (function concat)
- (mapcar
- (function
- (lambda (newsgroup)
- (concat newsgroup "\\|")))
- (cdr no)))
- (car no) "\\)\\(\\.\\|$\\)")))
- ))
-
-(defun gnus-save-newsrc-file ()
- "Save current status in the `.newsrc' file."
- ;; Note: We cannot save .newsrc file if all newsgroups are removed
- ;; from the variable gnus-newsrc-assoc.
- (and (or gnus-newsrc-assoc gnus-killed-assoc)
- gnus-current-startup-file
- (save-excursion
- ;; A buffer containing .newsrc file may be deleted.
- (set-buffer (find-file-noselect gnus-current-startup-file))
- (if (not (buffer-modified-p))
- (message "(No changes need to be saved)")
- (message "Saving %s..." gnus-current-startup-file)
- (let ((make-backup-files t)
- (version-control nil)
- (require-final-newline t)) ;Don't ask even if requested.
- ;; Make backup file of master newsrc.
- ;; You can stop or change version control of backup file.
- ;; Suggested by jason@violet.berkeley.edu.
- (run-hooks 'gnus-save-newsrc-hook)
- (save-buffer))
- ;; Quickly loadable .newsrc.
- (set-buffer (get-buffer-create " *GNUS-newsrc*"))
- (buffer-flush-undo (current-buffer))
- (erase-buffer)
- (gnus-gnus-to-quick-newsrc-format)
- (let ((make-backup-files nil)
- (version-control nil)
- (require-final-newline t)) ;Don't ask even if requested.
- (write-file (concat gnus-current-startup-file ".el")))
- (kill-buffer (current-buffer))
- (message "Saving %s...done" gnus-current-startup-file)
- ))
- ))
-
-(defun gnus-update-newsrc-buffer (group &optional delete next)
- "Incrementally update `.newsrc' buffer about GROUP.
-If optional 1st argument DELETE is non-nil, delete the group.
-If optional 2nd argument NEXT is non-nil, inserted before it."
- (save-excursion
- ;; Taking account of the killed startup file.
- ;; Suggested by tale@pawl.rpi.edu.
- (set-buffer (or (get-file-buffer gnus-current-startup-file)
- (find-file-noselect gnus-current-startup-file)))
- ;; Options line continuation lines must be also considered here.
- ;; Before supporting continuation lines, " newsgroup ! 1-5" was
- ;; okay, but now it is invalid. It should be "newsgroup! 1-5".
- (let ((deleted nil)
- (case-fold-search nil) ;Should NOT ignore case.
- (buffer-read-only nil)) ;May be not modifiable.
- ;; Delete ALL entries which match for GROUP.
- (goto-char (point-min))
- (while (re-search-forward
- (concat "^" (regexp-quote group) "[:!]") nil t)
- (beginning-of-line)
- (delete-region (point) (progn (forward-line 1) (point)))
- (setq deleted t) ;Old entry is deleted.
- )
- (if delete
- nil
- ;; Insert group entry.
- (let ((newsrc (gnus-gethash group gnus-newsrc-hashtb)))
- (if (null newsrc)
- nil
- ;; Find insertion point.
- (cond (deleted nil) ;Insert here.
- ((and (stringp next)
- (progn
- (goto-char (point-min))
- (re-search-forward
- (concat "^" (regexp-quote next) "[:!]") nil t)))
- (beginning-of-line))
- (t
- (goto-char (point-max))
- (or (bolp)
- (insert "\n"))))
- ;; Insert after options line.
- (if (looking-at "^[ \t]*options\\([ \t]\\|$\\)")
- (progn
- (forward-line 1)
- ;; Skip continuation lines.
- (while (and (not (eobp))
- (looking-at "^[ \t]+"))
- (forward-line 1))))
- (insert group ;Group name
- (if (nth 1 newsrc) ": " "! ")) ;Subscribed?
- (gnus-ranges-to-newsrc-format (nthcdr 2 newsrc)) ;Read articles
- (insert "\n")
- )))
- )))
-
-(defun gnus-gnus-to-quick-newsrc-format ()
- "Insert GNUS variables such as `gnus-newsrc-assoc' in Lisp format."
- (insert ";; GNUS internal format of .newsrc.\n")
- (insert ";; Touch .newsrc instead if you think to remove this file.\n")
- (let ((variable nil)
- (variables gnus-variable-list)
- ;; Temporary rebind to make changes
- ;; gnus-check-killed-newsgroups in invisible.
- (gnus-killed-assoc gnus-killed-assoc)
- (gnus-killed-hashtb gnus-killed-hashtb))
- ;; Remove duplicated or unsubscribed newsgroups in
- ;; gnus-killed-assoc (and gnus-killed-hashtb).
- (gnus-check-killed-newsgroups)
- ;; Then, insert lisp expressions.
- (while variables
- (setq variable (car variables))
- (and (boundp variable)
- (symbol-value variable)
- (insert "(setq " (symbol-name variable) " '"
- (prin1-to-string (symbol-value variable))
- ")\n"))
- (setq variables (cdr variables)))
- ))
-
-(defun gnus-ranges-to-newsrc-format (ranges)
- "Insert ranges of read articles."
- (let ((range nil)) ;Range is a pair of BEGIN and END.
- (while ranges
- (setq range (car ranges))
- (setq ranges (cdr ranges))
- (cond ((= (car range) (cdr range))
- (if (= (car range) 0)
- (setq ranges nil) ;No unread articles.
- (insert (int-to-string (car range)))
- (if ranges (insert ","))
- ))
- (t
- (insert (int-to-string (car range))
- "-"
- (int-to-string (cdr range)))
- (if ranges (insert ","))
- ))
- )))
-
-(defun gnus-compress-sequence (numbers)
- "Convert list of sorted numbers to ranges."
- (let* ((numbers (sort (copy-sequence numbers) (function <)))
- (first (car numbers))
- (last (car numbers))
- (result nil))
- (while numbers
- (cond ((= last (car numbers)) nil) ;Omit duplicated number
- ((= (1+ last) (car numbers)) ;Still in sequence
- (setq last (car numbers)))
- (t ;End of one sequence
- (setq result (cons (cons first last) result))
- (setq first (car numbers))
- (setq last (car numbers)))
- )
- (setq numbers (cdr numbers))
- )
- (nreverse (cons (cons first last) result))
- ))
-
-(defun gnus-uncompress-sequence (ranges)
- "Expand compressed format of sequence."
- (let ((first nil)
- (last nil)
- (result nil))
- (while ranges
- (setq first (car (car ranges)))
- (setq last (cdr (car ranges)))
- (while (< first last)
- (setq result (cons first result))
- (setq first (1+ first)))
- (setq result (cons first result))
- (setq ranges (cdr ranges))
- )
- (nreverse result)
- ))
-
-(defun gnus-number-of-articles (range)
- "Compute number of articles from RANGE `((beg1 . end1) (beg2 . end2) ...)'."
- (let ((count 0))
- (while range
- (if (/= (cdr (car range)) 0)
- ;; If end1 is 0, it must be skipped. Usually no articles in
- ;; this group.
- (setq count (+ count 1 (- (cdr (car range)) (car (car range))))))
- (setq range (cdr range))
- )
- count ;Result
- ))
-
-(defun gnus-difference-of-range (src obj)
- "Compute (SRC - OBJ) on range.
-Range of SRC is expressed as `(beg . end)'.
-Range of OBJ is expressed as `((beg1 . end1) (beg2 . end2) ...)."
- (let ((beg (car src))
- (end (cdr src))
- (range nil)) ;This is result.
- ;; Src may be nil.
- (while (and src obj)
- (let ((beg1 (car (car obj)))
- (end1 (cdr (car obj))))
- (cond ((> beg end)
- (setq obj nil)) ;Terminate loop
- ((< beg beg1)
- (setq range (cons (cons beg (min (1- beg1) end)) range))
- (setq beg (1+ end1)))
- ((>= beg beg1)
- (setq beg (max beg (1+ end1))))
- )
- (setq obj (cdr obj)) ;Next OBJ
- ))
- ;; Src may be nil.
- (if (and src (<= beg end))
- (setq range (cons (cons beg end) range)))
- ;; Result
- (if range
- (nreverse range)
- (list (cons 0 0)))
- ))
-
-(defun gnus-read-distributions-file ()
- "Get distributions file from NNTP server (NNTP2 functionality)."
- ;; Make sure a connection to NNTP server is alive.
- (gnus-start-news-server)
- (message "Reading distributions file...")
- (setq gnus-distribution-list nil)
- (if (gnus-request-list-distributions)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (gnus-distributions-to-gnus-format)
- (message "Reading distributions file...done"))
- ;; It's not a fatal error.
- ;;(error "Cannot read distributions file from NNTP server.")
- )
- ;; Merge with user supplied default distributions.
- (let ((defaults (reverse gnus-local-distributions))
- (dist nil))
- (while defaults
- (setq dist (assoc (car defaults) gnus-distribution-list))
- (if dist
- (setq gnus-distribution-list
- (delq dist gnus-distribution-list)))
- (setq gnus-distribution-list
- (cons (list (car defaults)) gnus-distribution-list))
- (setq defaults (cdr defaults))
- )))
-
-(defun gnus-distributions-to-gnus-format ()
- "Convert distributions file format to internal format."
- (setq gnus-distribution-list nil)
- (goto-char (point-min))
- (while (re-search-forward "^\\([^ \t\n]+\\).*$" nil t)
- (setq gnus-distribution-list
- (cons (list (buffer-substring (match-beginning 1) (match-end 1)))
- gnus-distribution-list)))
- (setq gnus-distribution-list
- (nreverse gnus-distribution-list)))
-
-(defun gnus-newsgroups-retrieve-description ()
- "Retrieve newsgroups description and build gnus-newsgroups-alist"
- (message "Reading newsgroups file...")
- (if (gnus-request-list-newsgroups)
- (save-excursion
- (setq gnus-newsgroups-alist nil)
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (while (re-search-forward gnus-newsgroups-regex nil t)
- (setq gnus-newsgroups-alist
- (cons (cons (buffer-substring (match-beginning 1) (match-end 1))
- (buffer-substring (match-beginning 2) (match-end 2)))
- gnus-newsgroups-alist)))
- (message "Reading newsgroups file...done"))
- (message "Cannot read newsgroups file")))
-
-(defun gnus-newsgroups-update-description ()
- "Update the newsgroups description"
- (interactive)
- (gnus-newsgroups-retrieve-description)
- (setq gnus-newsgroups-hashtb (gnus-make-hashtable-from-alist gnus-newsgroups-alist)))
-
-(defun gnus-newsgroups-display-toggle ()
- "Toggle displaying newsgroup descriptions in *Newsgroup* buffer."
- (interactive)
- (setq gnus-newsgroups-display (not gnus-newsgroups-display))
- (if gnus-newsgroups-showall
- (gnus-group-list-groups t)
- (gnus-group-list-groups nil)))
-
-(provide 'gnus)
-
-;;Local variables:
-;;eval: (put 'gnus-eval-in-buffer-window 'lisp-indent-hook 1)
-;;end:
-
-;;; gnus.el ends here
diff --git a/lisp/=gnusmail.el b/lisp/=gnusmail.el
deleted file mode 100644
index 293bde54f4a..00000000000
--- a/lisp/=gnusmail.el
+++ /dev/null
@@ -1,220 +0,0 @@
-;;; gnusmail.el --- mail reply commands for GNUS newsreader
-
-;; Copyright (C) 1990, 1993 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; 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.
-
-;;; Code:
-
-(require 'gnus)
-
-(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 Summary Mode
-
-(defun gnus-summary-reply (yank)
- "Reply mail to news author.
-If prefix argument YANK is non-nil, original article is yanked automatically.
-Customize the variable gnus-mail-reply-method to use another mailer."
- (interactive "P")
- ;; Bug fix by jbw@bigbird.bu.edu (Joe Wells)
- ;; Stripping headers should be specified with mail-yank-ignored-headers.
- (gnus-summary-select-article t t)
- (switch-to-buffer gnus-article-buffer)
- (widen)
- (delete-other-windows)
- (bury-buffer gnus-article-buffer)
- (funcall gnus-mail-reply-method yank))
-
-(defun gnus-summary-reply-with-original ()
- "Reply mail to news author with original article.
-Customize the variable gnus-mail-reply-method to use another mailer."
- (interactive)
- (gnus-summary-reply t))
-
-(defun gnus-summary-mail-forward ()
- "Forward the current message to another user.
-Customize the variable gnus-mail-forward-method to use another mailer."
- (interactive)
- (gnus-summary-select-article)
- (switch-to-buffer gnus-article-buffer)
- (widen)
- (delete-other-windows)
- (bury-buffer gnus-article-buffer)
- (funcall gnus-mail-forward-method))
-
-(defun gnus-summary-mail-other-window ()
- "Compose mail in other window.
-Customize the variable gnus-mail-other-window-method to use another mailer."
- (interactive)
- (gnus-summary-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
- (mail-yank-original nil)))
-
-(defun gnus-mail-forward-using-mail ()
- "Forward the current message to another user using mail."
- ;; This is almost a carbon copy of rmail-forward in rmail.el.
- (let ((forward-buffer (current-buffer))
- (subject
- (concat "[" gnus-newsgroup-name "] "
- ;;(mail-strip-quoted-names (gnus-fetch-field "From")) ": "
- (or (gnus-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))
- (insert "------- Start of forwarded message -------\n")
- (insert-buffer forward-buffer)
- (goto-char (point-max))
- (insert "------- End of forwarded message -------\n")
- ;; You have a chance to arrange the message.
- (run-hooks 'gnus-mail-forward-hook)
- ))))
-
-(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] yank 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 (or (gnus-fetch-field "subject")
- "(None)")))
- (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)
- )))
-
-;; gnus-mail-forward-using-mhe is contributed by Jun-ichiro Itoh
-;; <itojun@ingram.mt.cs.keio.ac.jp>
-
-(defun gnus-mail-forward-using-mhe ()
- "Forward the current message to another user using mh-e."
- ;; First of all, prepare mhe mail buffer.
- (let ((to (read-string "To: "))
- (cc (read-string "Cc: "))
- (buffer (current-buffer))
- subject)
- ;;(gnus-article-show-all-headers)
- (setq subject
- (concat "[" gnus-newsgroup-name "] "
- ;;(mail-strip-quoted-names (gnus-fetch-field "From")) ": "
- (or (gnus-fetch-field "subject") "")))
- (setq mh-show-buffer buffer)
- (mh-find-path)
- (mh-send to (or cc "") subject)
- (save-excursion
- (goto-char (point-max))
- (insert "\n------- Forwarded Message\n\n")
- (insert-buffer buffer)
- (goto-char (point-max))
- (insert "\n------- End of Forwarded Message\n")
- (setq mh-sent-from-folder buffer)
- (setq mh-sent-from-msg 1))))
-
-(defun gnus-mail-other-window-using-mhe ()
- "Compose mail other window using mh-e."
- (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)))
-
-(provide 'gnusmail)
-
-;;; gnusmail.el ends here
diff --git a/lisp/=gnusmisc.el b/lisp/=gnusmisc.el
deleted file mode 100644
index df7b16f48d2..00000000000
--- a/lisp/=gnusmisc.el
+++ /dev/null
@@ -1,294 +0,0 @@
-;;; gnusmisc.el --- miscellaneous commands for GNUS newsreader
-
-;; Copyright (C) 1989, 1990, 1993 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Code:
-
-(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)
-
-(autoload 'timezone-make-date-arpa-standard "timezone")
-
-(put 'gnus-browse-killed-mode 'mode-class 'special)
-
-
-;;;
-;;; GNUS Browse-Killed Mode
-;;;
-
-;; Some ideas are due to roland@wheaties.ai.mit.edu (Roland McGrath).
-;; I'd like to thank him very much.
-
-;; 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-list-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 it against the options line in 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-list-killed-groups ()
- "List the killed newsgroups.
-The keys y and C-y yank 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 (gnus-gethash group gnus-killed-hashtb)))
- (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-transpose-groups (arg)
- "Exchange current newsgroup and previous newsgroup.
-With argument ARG, takes previous newsgroup and moves it past ARG newsgroup."
- (interactive "p")
- ;; BUG: last newsgroup and the last but one cannot be transposed
- ;; since gnus-group-search-forward does not move forward beyond the
- ;; last. If we instead use forward-line, no problem, but I don't
- ;; want to use it for later extension.
- (while (> arg 0)
- (gnus-group-search-forward t t)
- (gnus-group-kill-group 1)
- (gnus-group-search-forward nil t)
- (gnus-group-yank-group)
- (gnus-group-search-forward nil t)
- (setq arg (1- arg))
- ))
-
-(defun gnus-group-kill-region (begin end)
- "Kill newsgroups in current region (excluding current point).
-The killed newsgroups can be yanked by using \\[gnus-group-yank-group]."
- (interactive "r")
- (let ((lines
- ;; Exclude a line where current point is on.
- (1-
- ;; Count lines.
- (save-excursion
- (count-lines
- (progn
- (goto-char begin)
- (beginning-of-line)
- (point))
- (progn
- (goto-char end)
- (end-of-line)
- (point)))))))
- (goto-char begin)
- (beginning-of-line) ;Important when LINES < 1
- (gnus-group-kill-group lines)))
-
-(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 containing 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"))
- ;; Huuum. It this right?
- ;;(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)
- ))
-
-
-;;; Rewrite Date: field in GMT to local
-
-(defun gnus-gmt-to-local ()
- "Rewrite Date: field described in GMT to local in current buffer.
-The variable gnus-local-timezone is used for local time zone.
-Intended to be used with gnus-article-prepare-hook."
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (narrow-to-region (point-min)
- (progn (search-forward "\n\n" nil 'move) (point)))
- (goto-char (point-min))
- (if (re-search-forward "^Date:[ \t]\\(.*\\)$" nil t)
- (let ((buffer-read-only nil)
- (date (buffer-substring (match-beginning 1) (match-end 1))))
- (delete-region (match-beginning 1) (match-end 1))
- (insert
- (timezone-make-date-arpa-standard date nil gnus-local-timezone))
- ))
- )))
-
-(provide 'gnusmisc)
-
-;;; gnusmisc.el ends here
diff --git a/lisp/=gnuspost.el b/lisp/=gnuspost.el
deleted file mode 100644
index 441feb245d2..00000000000
--- a/lisp/=gnuspost.el
+++ /dev/null
@@ -1,842 +0,0 @@
-;;; gnuspost.el --- post news commands for GNUS newsreader
-
-;; Copyright (C) 1989, 1990, 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Code:
-
-(require 'gnus)
-
-(defvar gnus-organization-file "/usr/lib/news/organization"
- "*Local news organization file.")
-
-(defvar gnus-post-news-buffer "*post-news*")
-(defvar gnus-winconf-post-news nil)
-
-(autoload 'news-reply-mode "rnewspost")
-(autoload 'timezone-make-date-arpa-standard "timezone")
-
-;;; Post news commands of GNUS Group Mode and Summary Mode
-
-(defun gnus-group-post-news ()
- "Post an article."
- (interactive)
- ;; Save window configuration.
- (setq gnus-winconf-post-news (current-window-configuration))
- (unwind-protect
- (gnus-post-news)
- (or (and (eq (current-buffer) (get-buffer gnus-post-news-buffer))
- (not (zerop (buffer-size))))
- ;; Restore last window configuration.
- (set-window-configuration gnus-winconf-post-news)))
- ;; We don't want to return to Summary buffer nor Article buffer later.
- (if (get-buffer gnus-summary-buffer)
- (bury-buffer gnus-summary-buffer))
- (if (get-buffer gnus-article-buffer)
- (bury-buffer gnus-article-buffer)))
-
-(defun gnus-summary-post-news ()
- "Post an article."
- (interactive)
- (gnus-summary-select-article t nil)
- ;; Save window configuration.
- (setq gnus-winconf-post-news (current-window-configuration))
- (unwind-protect
- (progn
- (switch-to-buffer gnus-article-buffer)
- (widen)
- (delete-other-windows)
- (gnus-post-news))
- (or (and (eq (current-buffer) (get-buffer gnus-post-news-buffer))
- (not (zerop (buffer-size))))
- ;; Restore last window configuration.
- (set-window-configuration gnus-winconf-post-news)))
- ;; We don't want to return to Article buffer later.
- (bury-buffer gnus-article-buffer))
-
-(defun gnus-summary-followup (yank)
- "Post a reply article.
-If prefix argument YANK is non-nil, original article is yanked automatically."
- (interactive "P")
- (gnus-summary-select-article t nil)
- ;; Check Followup-To: poster.
- (set-buffer gnus-article-buffer)
- (if (and gnus-use-followup-to
- (string-equal "poster" (gnus-fetch-field "followup-to"))
- (or (not (eq gnus-use-followup-to t))
- (not (y-or-n-p "Do you want to ignore `Followup-To: poster'? "))))
- ;; Mail to the poster. GNUS is now RFC1036 compliant.
- (gnus-summary-reply yank)
- ;; Save window configuration.
- (setq gnus-winconf-post-news (current-window-configuration))
- (unwind-protect
- (progn
- (switch-to-buffer gnus-article-buffer)
- (widen)
- (delete-other-windows)
- (gnus-news-reply yank))
- (or (and (eq (current-buffer) (get-buffer gnus-post-news-buffer))
- (not (zerop (buffer-size))))
- ;; Restore last window configuration.
- (set-window-configuration gnus-winconf-post-news)))
- ;; We don't want to return to Article buffer later.
- (bury-buffer gnus-article-buffer)))
-
-(defun gnus-summary-followup-with-original ()
- "Post a reply article with original article."
- (interactive)
- (gnus-summary-followup t))
-
-(defun gnus-summary-cancel-article ()
- "Cancel an article you posted."
- (interactive)
- (gnus-summary-select-article t nil)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (gnus-cancel-news)))
-
-
-;;; Post a News using NNTP
-
-;;;###autoload
-(defalias 'sendnews 'gnus-post-news)
-
-;;;###autoload
-(defalias 'postnews 'gnus-post-news)
-
-;;;###autoload
-(defun gnus-post-news ()
- "Begin editing a new USENET news article to be posted.
-Type \\[describe-mode] once editing the article to get a list of commands."
- (interactive)
- (if (or (not gnus-novice-user)
- (y-or-n-p "Are you sure you want to post to all of USENET? "))
- (let ((artbuf (current-buffer))
- (newsgroups ;Default newsgroup.
- (if (eq major-mode 'gnus-article-mode) gnus-newsgroup-name))
- (subject nil)
- ;; Get default distribution.
- (distribution (car gnus-local-distributions))
- (followup-to nil))
- ;; Connect to NNTP server if not connected yet, and get
- ;; several information.
- (if (not (gnus-server-opened))
- (progn
- (gnus-start-news-server t) ;Confirm server.
- (gnus-setup-news)))
- ;; Get current article information.
- (save-restriction
- (and (not (zerop (buffer-size)))
- ;;(equal major-mode 'news-mode)
- (equal major-mode 'gnus-article-mode)
- (progn
- ;;(news-show-all-headers)
- (gnus-article-show-all-headers)
- (narrow-to-region (point-min)
- (progn (goto-char (point-min))
- (search-forward "\n\n")
- (point)))))
- (setq news-reply-yank-from (mail-fetch-field "from"))
- (setq news-reply-yank-message-id (mail-fetch-field "message-id")))
- (pop-to-buffer gnus-post-news-buffer)
- (news-reply-mode)
- (gnus-overload-functions)
- (if (and (buffer-modified-p)
- (> (buffer-size) 0)
- (not (y-or-n-p "Unsent article being composed; erase it? ")))
- ;; Continue composition.
- ;; Make news-reply-yank-original work on the current article.
- (setq mail-reply-buffer artbuf)
- (erase-buffer)
- (if gnus-interactive-post
- ;; Newsgroups, subject and distribution are asked for.
- ;; Suggested by yuki@flab.fujitsu.junet.
- (progn
- ;; Subscribed newsgroup names are required for
- ;; completing read of newsgroup.
- (or gnus-newsrc-assoc
- (gnus-read-newsrc-file))
- ;; Which do you like? (UMERIN)
- ;; (setq newsgroups (read-string "Newsgroups: " "general"))
- (or newsgroups ;Use the default newsgroup.
- (let (group)
- (while (not
- (string=
- (setq group
- (completing-read "Newsgroup: "
- gnus-newsrc-assoc
- nil 'require-match))
- ""))
- (or followup-to (setq followup-to group))
- (if newsgroups
- (setq newsgroups (concat newsgroups "," group))
- (setq newsgroups group)))))
- (setq subject (read-string "Subject: "))
- ;; Choose a distribution from gnus-distribution-list.
- ;; completing-read should not be used with
- ;; 'require-match functionality in order to allow use
- ;; of unknow distribution.
- (gnus-read-distributions-file)
- (setq distribution
- (if (consp gnus-distribution-list)
- (completing-read "Distribution: "
- gnus-distribution-list
- nil nil ;Never 'require-match
- distribution ;Default distribution.
- )
- (read-string "Distribution: ")))
- ;; Empty string is okay.
- ;;(if (string-equal distribution "")
- ;; (setq distribution nil))
- ))
- (news-setup () subject () newsgroups artbuf)
- ;; Make sure the article is posted by GNUS.
- ;;(mail-position-on-field "Posting-Software")
- ;;(insert "GNUS: NNTP-based News Reader for GNU Emacs")
- ;; Insert Distribution: field.
- ;; Suggested by ichikawa@flab.fujitsu.junet.
- (mail-position-on-field "Distribution")
- (insert (or distribution ""))
- ;; Add Followup-To header
- (if followup-to
- (progn
- (mail-position-on-field "Followup-To")
- (insert followup-to)))
- ;; Handle author copy using FCC field.
- (if gnus-author-copy
- (progn
- (mail-position-on-field "FCC")
- (insert gnus-author-copy)))
- (if gnus-interactive-post
- ;; All fields are filled in.
- (goto-char (point-max))
- ;; Move point to Newsgroup: field.
- (goto-char (point-min))
- (end-of-line))
- ))
- (message "")))
-
-(defun gnus-news-reply (&optional yank)
- "Compose and post a reply (aka a followup) to the current article on USENET.
-While composing the followup, use \\[news-reply-yank-original] to yank the
-original message into it."
- (interactive)
- (if (or (not gnus-novice-user)
- (y-or-n-p "Are you sure you want to followup to all of USENET? "))
- (let (from cc subject date to followup-to newsgroups message-of
- references distribution message-id
- (artbuf (current-buffer)))
- (save-restriction
- (and (not (zerop (buffer-size)))
- ;;(equal major-mode 'news-mode)
- (equal major-mode 'gnus-article-mode)
- (progn
- ;; (news-show-all-headers)
- (gnus-article-show-all-headers)
- (narrow-to-region (point-min)
- (progn (goto-char (point-min))
- (search-forward "\n\n")
- (point)))))
- (setq from (mail-fetch-field "from"))
- ;; Get reply-to working corrrectly for gnus-auto-mail-to-author (jpm)
- (setq reply-to (mail-fetch-field "reply-to"))
- (setq news-reply-yank-from from)
- (setq subject (mail-fetch-field "subject"))
- (setq date (mail-fetch-field "date"))
- (setq followup-to (mail-fetch-field "followup-to"))
- ;; Ignore Followup-To: poster.
- (if (or (null gnus-use-followup-to) ;Ignore followup-to: field.
- (string-equal "" followup-to) ;Bogus header.
- (string-equal "poster" followup-to))
- (setq followup-to nil))
- (setq newsgroups (or followup-to (mail-fetch-field "newsgroups")))
- (setq references (mail-fetch-field "references"))
- (setq distribution (mail-fetch-field "distribution"))
- (setq message-id (mail-fetch-field "message-id"))
- (setq news-reply-yank-message-id message-id))
- (pop-to-buffer gnus-post-news-buffer)
- (news-reply-mode)
- (gnus-overload-functions)
- (if (and (buffer-modified-p)
- (> (buffer-size) 0)
- (not (y-or-n-p "Unsent article being composed; erase it? ")))
- ;; Continue composition.
- ;; Make news-reply-yank-original work on current article.
- (setq mail-reply-buffer artbuf)
- (erase-buffer)
- (and subject
- (setq subject
- (concat "Re: " (gnus-simplify-subject subject 're-only))))
- (and from
- (progn
- (let ((stop-pos
- (string-match " *at \\| *@ \\| *(\\| *<" from)))
- (setq message-of
- (concat
- (if stop-pos (substring from 0 stop-pos) from)
- "'s message of "
- date)))))
- (news-setup nil subject message-of newsgroups artbuf)
- (if followup-to
- (progn (news-reply-followup-to)
- (insert followup-to)))
- ;; Fold long references line to follow RFC1036.
- (mail-position-on-field "References")
- (let ((begin (point))
- (fill-column 79)
- (fill-prefix "\t"))
- (if references
- (insert references))
- (if (and references message-id)
- (insert " "))
- (if message-id
- (insert message-id))
- ;; The region must end with a newline to fill the region
- ;; without inserting extra newline.
- (fill-region-as-paragraph begin (1+ (point))))
- ;; Make sure the article is posted by GNUS.
- ;;(mail-position-on-field "Posting-Software")
- ;;(insert "GNUS: NNTP-based News Reader for GNU Emacs")
- ;; Distribution must be the same as original article.
- (mail-position-on-field "Distribution")
- (insert (or distribution ""))
- ;; Handle author copy using FCC field.
- (if gnus-author-copy
- (progn
- (mail-position-on-field "FCC")
- (insert gnus-author-copy)))
- ;; Insert To: FROM field, which is expected to mail the
- ;; message to the author of the article too. Use Reply-To
- ;; field like gnus-mail-reply-using-m* (jpm).
- (if (and gnus-auto-mail-to-author (or reply-to from))
- (progn
- (goto-char (point-min))
- (insert "To: " (or reply-to from) "\n")))
- (goto-char (point-max)))
- ;; Yank original article automatically.
- (if yank
- (let ((last (point)))
- ;;(goto-char (point-max))
- ;; Insert at current point.
- (news-reply-yank-original nil)
- (goto-char last)))
- )
- (message "")))
-
-(defun gnus-inews-news ()
- "Send a news message."
- (interactive)
- (let* ((case-fold-search nil)
- (server-running (gnus-server-opened)))
- (save-excursion
- ;; Connect to default NNTP server if necessary.
- ;; Suggested by yuki@flab.fujitsu.junet.
- (gnus-start-news-server) ;Use default server.
- ;; NNTP server must be opened before current buffer is modified.
- (widen)
- (goto-char (point-min))
- (run-hooks 'news-inews-hook)
- (save-restriction
- (narrow-to-region
- (point-min)
- (progn
- (goto-char (point-min))
- (search-forward (concat "\n" mail-header-separator "\n"))
- (point)))
-
- ;; Correct newsgroups field: change sequence of spaces to comma and
- ;; eliminate spaces around commas. Eliminate imbedded line breaks.
- (goto-char (point-min))
- (if (search-forward-regexp "^Newsgroups: +" nil t)
- (save-restriction
- (narrow-to-region
- (point)
- (if (re-search-forward "^[^ \t]" nil 'end)
- (match-beginning 0)
- (point-max)))
- (goto-char (point-min))
- (replace-regexp "\n[ \t]+" " ") ;No line breaks (too confusing)
- (goto-char (point-min))
- (replace-regexp "[ \t\n]*,[ \t\n]*\\|[ \t]+" ",")
- ))
-
- ;; Mail the message too if To: or Cc: exists.
- (if (or (mail-fetch-field "to" nil t)
- (mail-fetch-field "cc" nil t))
- (if gnus-mail-send-method
- (progn
- (message "Sending via mail...")
- (widen)
- (funcall gnus-mail-send-method)
- (message "Sending via mail... done"))
- (ding)
- (message "No mailer defined. To: and/or Cc: fields ignored.")
- (sit-for 1))))
-
- ;; Send to NNTP server.
- (message "Posting to USENET...")
- (if (gnus-inews-article)
- (message "Posting to USENET... done")
- ;; We cannot signal an error.
- (ding) (message "Article rejected: %s" (gnus-status-message)))
- (set-buffer-modified-p nil))
- ;; If NNTP server is opened by gnus-inews-news, close it by myself.
- (or server-running
- (gnus-close-server))
- (and (fboundp 'bury-buffer) (bury-buffer))
- ;; Restore last window configuration.
- (and gnus-winconf-post-news
- (set-window-configuration gnus-winconf-post-news))
- (setq gnus-winconf-post-news nil)
- ))
-
-(defun gnus-cancel-news ()
- "Cancel an article you posted."
- (interactive)
- (if (yes-or-no-p "Do you really want to cancel this article? ")
- (let ((from nil)
- (newsgroups nil)
- (message-id nil)
- (distribution nil))
- (save-excursion
- ;; Get header info. from original article.
- (save-restriction
- (gnus-article-show-all-headers)
- (goto-char (point-min))
- (search-forward "\n\n" nil 'move)
- (narrow-to-region (point-min) (point))
- (setq from (mail-fetch-field "from"))
- (setq newsgroups (mail-fetch-field "newsgroups"))
- (setq message-id (mail-fetch-field "message-id"))
- (setq distribution (mail-fetch-field "distribution")))
- ;; Verify if the article is absolutely user's by comparing
- ;; user id with value of its From: field.
- (if (not
- (string-equal
- (downcase (mail-strip-quoted-names from))
- (downcase (mail-strip-quoted-names (gnus-inews-user-name)))))
- (progn
- (ding) (message "This article is not yours."))
- ;; Make control article.
- (set-buffer (get-buffer-create " *GNUS-canceling*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert "Newsgroups: " newsgroups "\n"
- "Subject: cancel " message-id "\n"
- "Control: cancel " message-id "\n"
- ;; We should not use the first value of
- ;; `gnus-distribution-list' as default value,
- ;; because distribution must be as same as original
- ;; article.
- "Distribution: " (or distribution "") "\n"
- mail-header-separator "\n"
- )
- ;; Send the control article to NNTP server.
- (message "Canceling your article...")
- (if (gnus-inews-article)
- (message "Canceling your article... done")
- (ding) (message "Failed to cancel your article"))
- ;; Kill the article buffer.
- (kill-buffer (current-buffer))
- )))
- ))
-
-
-;;; Lowlevel inews interface
-
-(defun gnus-inews-article ()
- "Post an article in current buffer using NNTP protocol."
- (let ((artbuf (current-buffer))
- (tmpbuf (get-buffer-create " *GNUS-posting*")))
- (save-excursion
- (set-buffer tmpbuf)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert-buffer-substring artbuf)
- ;; Remove the header separator.
- (goto-char (point-min))
- (search-forward (concat "\n" mail-header-separator "\n"))
- (replace-match "\n\n")
- (goto-char (point-max))
- ;; require a newline at the end for inews to append .signature to
- (or (= (preceding-char) ?\n)
- (insert ?\n))
- ;; This hook may insert a signature.
- (run-hooks 'gnus-prepare-article-hook)
- ;; Prepare article headers. All message body such as signature
- ;; must be inserted before Lines: field is prepared.
- (save-restriction
- (goto-char (point-min))
- (search-forward "\n\n")
- (narrow-to-region (point-min) (point))
- (gnus-inews-insert-headers))
- ;; Run final inews hooks. This hook may do FCC.
- ;; The article must be saved before being posted because
- ;; `gnus-request-post' modifies the buffer.
- (run-hooks 'gnus-inews-article-hook)
- ;; Post an article to NNTP server.
- ;; Return NIL if post failed.
- (prog1
- (gnus-request-post)
- (kill-buffer (current-buffer)))
- )))
-
-(defun gnus-inews-insert-headers ()
- "Prepare article headers.
-Fields already prepared in the buffer are not modified.
-Fields in gnus-required-headers will be generated."
- (save-excursion
- (let ((date (gnus-inews-date))
- (message-id (gnus-inews-message-id))
- (organization (gnus-inews-organization)))
- (goto-char (point-min))
- (or (mail-fetch-field "path")
- (and (memq 'Path gnus-required-headers)
- (insert "Path: " (gnus-inews-path) "\n")))
- (or (mail-fetch-field "from")
- (and (memq 'From gnus-required-headers)
- (insert "From: " (gnus-inews-user-name) "\n")))
- ;; If there is no subject, make Subject: field.
- (or (mail-fetch-field "subject")
- (and (memq 'Subject gnus-required-headers)
- (insert "Subject: \n")))
- ;; If there is no newsgroups, make Newsgroups: field.
- (or (mail-fetch-field "newsgroups")
- (and (memq 'Newsgroups gnus-required-headers)
- (insert "Newsgroups: \n")))
- (or (mail-fetch-field "message-id")
- (and message-id
- (memq 'Message-ID gnus-required-headers)
- (insert "Message-ID: " message-id "\n")))
- (or (mail-fetch-field "date")
- (and date
- (memq 'Date gnus-required-headers)
- (insert "Date: " date "\n")))
- ;; Optional fields in RFC977 and RFC1036
- (or (mail-fetch-field "organization")
- (and organization
- (memq 'Organization gnus-required-headers)
- (let ((begin (point))
- (fill-column 79)
- (fill-prefix "\t"))
- (insert "Organization: " organization "\n")
- (fill-region-as-paragraph begin (point)))))
- (or (mail-fetch-field "distribution")
- (and (memq 'Distribution gnus-required-headers)
- (insert "Distribution: \n")))
- (or (mail-fetch-field "lines")
- (and (memq 'Lines gnus-required-headers)
- (insert "Lines: " (gnus-inews-lines) "\n")))
- )))
-
-
-;; Utility functions.
-
-(defun gnus-inews-insert-signature ()
- "Insert signature file in current article buffer.
-If there is a file named .signature-DISTRIBUTION, it is used instead
-of usual .signature when the distribution of the article is
-DISTRIBUTION. Set the variable to nil to prevent appending the
-signature file automatically.
-Signature file is specified by the variable gnus-signature-file."
- (save-excursion
- (save-restriction
- ;; Change signature file by distribution.
- ;; Suggested by hyoko@flab.fujitsu.co.jp.
- (let ((signature
- (if gnus-signature-file
- (expand-file-name gnus-signature-file nil)))
- (distribution nil))
- (goto-char (point-min))
- (search-forward "\n\n")
- (narrow-to-region (point-min) (point))
- (setq distribution (mail-fetch-field "distribution"))
- (widen)
- (if signature
- (progn
- (if (file-exists-p (concat signature "-" distribution))
- (setq signature (concat signature "-" distribution)))
- ;; Insert signature.
- (if (file-exists-p signature)
- (progn
- (goto-char (point-max))
- (insert "-- \n")
- (insert-file-contents signature)))
- ))))))
-
-(defun gnus-inews-do-fcc ()
- "Process FCC: fields in current article buffer.
-Unless the first character of the field is `|', the article is saved
-to the specified file using the function specified by the variable
-gnus-author-copy-saver. The default function rmail-output saves in
-Unix mailbox format.
-If the first character is `|', the contents of the article is send to
-a program specified by the rest of the value."
- (let ((fcc-list nil)
- (fcc-file nil)
- (case-fold-search t)) ;Should ignore case.
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (search-forward "\n\n")
- (narrow-to-region (point-min) (point))
- (goto-char (point-min))
- (while (re-search-forward "^FCC:[ \t]*" nil 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))))
- ;; Process FCC operations.
- (widen)
- (while fcc-list
- (setq fcc-file (car fcc-list))
- (setq fcc-list (cdr fcc-list))
- (cond ((string-match "^[ \t]*|[ \t]*\\(.*\\)[ \t]*$" fcc-file)
- (let ((program (substring fcc-file
- (match-beginning 1) (match-end 1))))
- ;; Suggested by yuki@flab.fujitsu.junet.
- ;; Send article to named program.
- (call-process-region (point-min) (point-max) shell-file-name
- nil nil nil "-c" program)
- ))
- (t
- ;; Suggested by hyoko@flab.fujitsu.junet.
- ;; Save article in Unix mail format by default.
- (if (and gnus-author-copy-saver
- (not (eq gnus-author-copy-saver 'rmail-output)))
- (funcall gnus-author-copy-saver fcc-file)
- (if (and (file-readable-p fcc-file)
- (mail-file-babyl-p fcc-file))
- (gnus-output-to-rmail fcc-file)
- (rmail-output fcc-file 1 t t)))
- ))
- )
- ))
- ))
-
-(defun gnus-inews-path ()
- "Return uucp path."
- (let ((login-name (gnus-inews-login-name)))
- (cond ((null gnus-use-generic-path)
- (concat gnus-nntp-server "!" login-name))
- ((stringp gnus-use-generic-path)
- ;; Support GENERICPATH. Suggested by vixie@decwrl.dec.com.
- (concat gnus-use-generic-path "!" login-name))
- (t login-name))
- ))
-
-(defun gnus-inews-user-name ()
- "Return user's network address as `NAME@DOMAIN (FULLNAME)'."
- (let ((full-name (gnus-inews-full-name)))
- (concat (if (or gnus-user-login-name gnus-use-generic-from
- gnus-local-domain (getenv "DOMAINNAME"))
- (concat (gnus-inews-login-name) "@"
- (gnus-inews-domain-name gnus-use-generic-from))
- user-mail-address)
- ;; User's full name.
- (cond ((string-equal full-name "") "")
- ((string-equal full-name "&") ;Unix hack.
- (concat " (" login-name ")"))
- (t
- (concat " (" full-name ")")))
- )))
-
-(defun gnus-inews-login-name ()
- "Return user login name.
-Got from the variable `gnus-user-login-name' and the function
-`user-login-name'."
- (or gnus-user-login-name (user-login-name)))
-
-(defun gnus-inews-full-name ()
- "Return user full name.
-Got from the variable `gnus-user-full-name', the environment variable
-NAME, and the function `user-full-name'."
- (or gnus-user-full-name
- (getenv "NAME") (user-full-name)))
-
-(defun gnus-inews-domain-name (&optional genericfrom)
- "Return user's domain name.
-If optional argument GENERICFROM is a string, use it as the domain
-name; if it is non-nil, strip of local host name from the domain name.
-If the function `system-name' returns full internet name and the
-domain is undefined, the domain name is got from it."
- (and (null gnus-local-domain)
- (boundp 'gnus-your-domain)
- (setq gnus-local-domain gnus-your-domain))
- (if (or genericfrom gnus-local-domain (getenv "DOMAINNAME"))
- (let ((domain (or (if (stringp genericfrom) genericfrom)
- (getenv "DOMAINNAME")
- gnus-local-domain
- ;; Function `system-name' may return full internet name.
- ;; Suggested by Mike DeCorte <mrd@sun.soe.clarkson.edu>.
- (if (string-match "\\." (system-name))
- (substring (system-name) (match-end 0)))
- (read-string "Domain name (no host): ")))
- (host (or (if (string-match "\\." (system-name))
- (substring (system-name) 0 (match-beginning 0)))
- (system-name))))
- (if (string-equal "." (substring domain 0 1))
- (setq domain (substring domain 1)))
- ;; Support GENERICFROM as same as standard Bnews system.
- ;; Suggested by ohm@kaba.junet and vixie@decwrl.dec.com.
- (cond ((null genericfrom)
- (concat host "." domain))
- ;;((stringp genericfrom) genericfrom)
- (t domain)))
- (substring user-mail-address (1+ (string-match "@" user-mail-address)))))
-
-(defun gnus-inews-message-id ()
- "Generate unique Message-ID for user."
- ;; Message-ID should not contain a slash and should be terminated by
- ;; a number. I don't know the reason why it is so.
- (concat "<" (gnus-inews-unique-id) "@" (gnus-inews-domain-name) ">"))
-
-(defun gnus-inews-unique-id ()
- "Generate unique ID from user name and current time."
- (let ((date (current-time-string))
- (name (gnus-inews-login-name)))
- (if (string-match "^[^ ]+ \\([^ ]+\\)[ ]+\\([0-9]+\\) \\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\) [0-9][0-9]\\([0-9][0-9]\\)"
- date)
- (concat (upcase name) "."
- (substring date (match-beginning 6) (match-end 6)) ;Year
- (substring date (match-beginning 1) (match-end 1)) ;Month
- (substring date (match-beginning 2) (match-end 2)) ;Day
- (substring date (match-beginning 3) (match-end 3)) ;Hour
- (substring date (match-beginning 4) (match-end 4)) ;Minute
- (substring date (match-beginning 5) (match-end 5)) ;Second
- )
- (error "Cannot understand current-time-string: %s." date))
- ))
-
-(defun gnus-current-time-zone (time)
- "The local time zone in effect at TIME, or nil if not known."
- (let ((z (and (fboundp 'current-time-zone) (current-time-zone time))))
- (if (and z (car z)) z gnus-local-timezone)))
-
-(defun gnus-inews-date ()
- "Date string of today.
-If `current-time-zone' works, or if `gnus-local-timezone' is set correctly,
-this yields a date that conforms to RFC 822. Otherwise a buggy date will
-be generated; this might work with some older news servers."
- (let* ((now (and (fboundp 'current-time) (current-time)))
- (zone (gnus-current-time-zone now)))
- (if zone
- (gnus-inews-valid-date now zone)
- ;; No timezone info.
- (gnus-inews-buggy-date now))))
-
-(defun gnus-inews-valid-date (&optional time zone)
- "A date string that represents TIME and conforms to the Usenet standard.
-TIME is optional and defaults to the current time.
-Some older versions of Emacs always act as if TIME is nil.
-The optional argument ZONE specifies the local time zone (default GMT)."
- (timezone-make-date-arpa-standard
- (if (fboundp 'current-time)
- (current-time-string time)
- (current-time-string))
- zone "GMT"))
-
-(defun gnus-inews-buggy-date (&optional time)
- "A buggy date string that represents TIME.
-TIME is optional and defaults to the current time.
-Some older versions of Emacs always act as if TIME is nil."
- (let ((date (if (fboundp 'current-time)
- (current-time-string time)
- (current-time-string))))
- (if (string-match "^[^ ]+ \\([^ ]+\\)[ ]+\\([0-9]+\\) \\([0-9:]+\\) [0-9][0-9]\\([0-9][0-9]\\)"
- date)
- (concat (substring date (match-beginning 2) (match-end 2)) ;Day
- " "
- (substring date (match-beginning 1) (match-end 1)) ;Month
- " "
- (substring date (match-beginning 4) (match-end 4)) ;Year
- " "
- (substring date (match-beginning 3) (match-end 3))) ;Time
- (error "Cannot understand current-time-string: %s." date))
- ))
-
-(defun gnus-inews-organization ()
- "Return user's organization.
-The ORGANIZATION environment variable is used if defined.
-If not, the variable gnus-local-organization is used instead.
-If the value begins with a slash, it is taken as the name of a file
-containing the organization."
- ;; The organization must be got in this order since the ORGANIZATION
- ;; environment variable is intended for user specific while
- ;; gnus-local-organization is for machine or organization specific.
-
- ;; Note: compatibility hack. This will be removed in the next version.
- (and (null gnus-local-organization)
- (boundp 'gnus-your-organization)
- (setq gnus-local-organization gnus-your-organization))
- ;; End of compatibility hack.
- (let* ((private-file (expand-file-name "~/.organization" nil))
- (organization (or (getenv "ORGANIZATION")
- gnus-local-organization
- private-file)))
- (and (stringp organization)
- (> (length organization) 0)
- (string-equal (substring organization 0 1) "/")
- ;; Get it from the user and system file.
- ;; Suggested by roland@wheaties.ai.mit.edu (Roland McGrath).
- (let ((dist (mail-fetch-field "distribution")))
- (setq organization
- (cond ((file-exists-p (concat organization "-" dist))
- (concat organization "-" dist))
- ((file-exists-p organization) organization)
- ((file-exists-p gnus-organization-file)
- gnus-organization-file)
- (t organization)))
- ))
- (cond ((not (stringp organization)) nil)
- ((and (string-equal (substring organization 0 1) "/")
- (file-exists-p organization))
- ;; If the first character is `/', assume it is the name of
- ;; a file containing the organization.
- (save-excursion
- (let ((tmpbuf (get-buffer-create " *GNUS organization*")))
- (set-buffer tmpbuf)
- (erase-buffer)
- (insert-file-contents organization)
- (prog1 (buffer-string)
- (kill-buffer tmpbuf))
- )))
- ((string-equal organization private-file) nil) ;No such file
- (t organization))
- ))
-
-(defun gnus-inews-lines ()
- "Count the number of lines and return numeric string."
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (search-forward "\n\n" nil 'move)
- (int-to-string (count-lines (point) (point-max))))))
-
-(provide 'gnuspost)
-
-;;; gnuspost.el ends here
diff --git a/lisp/=gosmacs.el b/lisp/=gosmacs.el
deleted file mode 100644
index 93bbbaa5b80..00000000000
--- a/lisp/=gosmacs.el
+++ /dev/null
@@ -1,117 +0,0 @@
-;;; gosmacs.el --- rebindings to imitate Gosmacs.
-
-;; Copyright (C) 1986 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; Make GNU Emacs look like Gosling Emacs. `M-x set-gosmacs-bindings'
-;; does this change; `M-x set-gnu-bindings' undoes it.
-
-;;; Code:
-
-(require 'mlsupport)
-
-(defvar non-gosmacs-binding-alist nil)
-
-;;;###autoload
-(defun set-gosmacs-bindings ()
- "Rebind some keys globally to make GNU Emacs resemble Gosling Emacs.
-Use \\[set-gnu-bindings] to restore previous global bindings."
- (interactive)
- (setq non-gosmacs-binding-alist
- (rebind-and-record
- '(("\C-x\C-e" compile)
- ("\C-x\C-f" save-buffers-kill-emacs)
- ("\C-x\C-i" insert-file)
- ("\C-x\C-m" save-some-buffers)
- ("\C-x\C-n" next-error)
- ("\C-x\C-o" switch-to-buffer)
- ("\C-x\C-r" insert-file)
- ("\C-x\C-u" undo)
- ("\C-x\C-v" find-file-other-window)
- ("\C-x\C-z" shrink-window)
- ("\C-x!" shell-command)
- ("\C-xd" delete-window)
- ("\C-xn" gosmacs-next-window)
- ("\C-xp" gosmacs-previous-window)
- ("\C-xz" enlarge-window)
- ("\C-z" scroll-one-line-up)
- ("\e\C-c" save-buffers-kill-emacs)
- ("\e!" line-to-top-of-window)
- ("\e(" backward-paragraph)
- ("\e)" forward-paragraph)
- ("\e?" apropos)
- ("\eh" delete-previous-word)
- ("\ej" indent-sexp)
- ("\eq" query-replace)
- ("\er" replace-string)
- ("\ez" scroll-one-line-down)
- ("\C-_" suspend-emacs)))))
-
-(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
-but each with the old definition that was replaced,"
- (let (old)
- (while bindings
- (let* ((this (car bindings))
- (key (car this))
- (newdef (nth 1 this)))
- (setq old (cons (list key (lookup-key global-map key)) old))
- (global-set-key key newdef))
- (setq bindings (cdr bindings)))
- (nreverse old)))
-
-(defun set-gnu-bindings ()
- "Restore the global bindings that were changed by \\[set-gosmacs-bindings]."
- (interactive)
- (rebind-and-record non-gosmacs-binding-alist))
-
-(defun gosmacs-previous-window ()
- "Select the window above or to the left of the window now selected.
-From the window at the upper left corner, select the one at the lower right."
- (interactive)
- (select-window (previous-window)))
-
-(defun gosmacs-next-window ()
- "Select the window below or to the right of the window now selected.
-From the window at the lower right corner, select the one at the upper left."
- (interactive)
- (select-window (next-window)))
-
-(defun scroll-one-line-up (&optional arg)
- "Scroll the selected window up (forward in the text) one line (or N lines)."
- (interactive "p")
- (scroll-up (or arg 1)))
-
-(defun scroll-one-line-down (&optional arg)
- "Scroll the selected window down (backward in the text) one line (or N)."
- (interactive "p")
- (scroll-down (or arg 1)))
-
-(defun line-to-top-of-window ()
- "Scroll the selected window up so that the current line is at the top."
- (interactive)
- (recenter 0))
-
-;;; gosmacs.el ends here
diff --git a/lisp/=grow-vers.el b/lisp/=grow-vers.el
deleted file mode 100644
index a7d03dd00bf..00000000000
--- a/lisp/=grow-vers.el
+++ /dev/null
@@ -1,41 +0,0 @@
-;;; grow-vers.el --- increment Emacs version number
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; Load this file to add a new level (starting at zero)
-;; to the Emacs version number recorded in version.el.
-
-;;; Code:
-
-(insert-file-contents "lisp/version.el")
-
-(re-search-forward "emacs-version \"[0-9.]*")
-(insert ".0")
-
-;; Delete the share-link with the current version
-;; so that we do not alter the current version.
-(delete-file "lisp/version.el")
-(write-region (point-min) (point-max) "lisp/version.el" nil 'nomsg)
-
-;;; grow-vers.el ends here
diff --git a/lisp/=inc-vers.el b/lisp/=inc-vers.el
deleted file mode 100644
index 0a4a43f0ea8..00000000000
--- a/lisp/=inc-vers.el
+++ /dev/null
@@ -1,54 +0,0 @@
-;;; inc-vers.el --- load this to increment the recorded Emacs version number.
-
-;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Code:
-
-(insert-file-contents "../lisp/version.el")
-
-(re-search-forward "emacs-version \"[^\"]*[0-9]+\"")
-(forward-char -1)
-(save-excursion
- (save-restriction
- (narrow-to-region (point)
- (progn (skip-chars-backward "0-9") (point)))
- (goto-char (point-min))
- (let ((version (read (current-buffer))))
- (delete-region (point-min) (point-max))
- (prin1 (1+ version) (current-buffer)))))
-(skip-chars-backward "^\"")
-(message "New Emacs version will be %s"
- (buffer-substring (point)
- (progn (skip-chars-forward "^\"") (point))))
-
-
-(if (and (file-accessible-directory-p "../lisp/")
- (null (file-writable-p "../lisp/version.el")))
- (delete-file "../lisp/version.el"))
-(if (eq system-type 'ms-dos) (setq buffer-file-type t))
-(write-region (point-min) (point-max) "../lisp/version.el" nil 'nomsg)
-(erase-buffer)
-(set-buffer-modified-p nil)
-
-(kill-emacs)
-
-;;; inc-vers.el ends here
diff --git a/lisp/=isearch-old.el b/lisp/=isearch-old.el
deleted file mode 100644
index ee7a1b04476..00000000000
--- a/lisp/=isearch-old.el
+++ /dev/null
@@ -1,608 +0,0 @@
-;;; isearch.el --- incremental search commands
-
-;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Code:
-
-(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 ?\C-m "\
-*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-ring-advance-char ?\M-n "\
-*Character to pull next (more recent) search string from the ring of same.")
-(defconst search-ring-retreat-char ?\M-p "\
-*Character to pull previous (older) search string from the ring of same.")
-
-(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.")
-
-(defconst search-upper-case t
- "*Non-nil means an upper-case letter as search input means case-sensitive.
-Any upper-case letter given explicitly as input to the incremental search
-has the effect of turning off `case-fold-search' for the rest of this search.
-Deleting the letter from the search string cancels the effect.")
-
-(fset 'search-forward-regexp 're-search-forward)
-(fset 'search-backward-regexp 're-search-backward)
-
-(defvar search-ring nil
- "List of recent non-regexp incremental searches.
-Each element is a cons cell of the form (STRING . UPPERCASE-FLAG).")
-
-(defvar regexp-search-ring nil
- "List of recent regexp incremental searches.
-Each element is a cons cell of the form (STRING . UPPERCASE-FLAG).")
-
-(defconst search-ring-max 16
- "*Maximum length of search ring before oldest elements are thrown away.")
-
-(defvar search-ring-yank-pointer nil
- "The tail of the search ring whose car is the last thing searched for.")
-
-(defvar regexp-search-ring-yank-pointer nil
- "The tail of the regular expression search ring whose car is the last
-thing searched for.")
-
-
-(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 RET 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))
-(define-key global-map "\C-s" 'isearch-forward)
-
-(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))
-(define-key esc-map "\C-s" 'isearch-forward-regexp)
-
-(defun isearch-backward ()
- "Do incremental search backward.
-See \\[isearch-forward] for more information."
- (interactive)
- (isearch nil))
-(define-key global-map "\C-r" 'isearch-backward)
-
-(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))
-(define-key esc-map "\C-r" 'isearch-backward-regexp)
-
-
-;; 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.
-
-;; OP-FUN is a function to be called after each input character is processed.
-;; (It is not called after characters that exit the search.)
-
-(defun isearch (forward &optional regexp op-fun)
- (let ((search-string "")
- (search-message "")
- ;; List of previous states during this search.
- (history nil)
- ;; t means search is currently successful.
- (success t)
- ;; Set once the search has wrapped around the end of the buffer.
- (wrapped nil)
- ;; Nominal starting point for searching
- ;; Usually this is the same as the opoint,
- ;; but it is changed by wrapping
- ;; and also by repeating the search.
- (barrier (point))
- ;; Set temporarily when adding a character to a regexp
- ;; enables it to match more rather than fewer places in the buffer.
- liberalized
- ;; Set temporarily by yanking text into the search string.
- yank-flag
- (invalid-regexp nil)
- ;; non-nil means an explicit uppercase letter seen in the input
- (uppercase-flag nil)
- ;; Non-nil means start using a small window
- ;; if the search moves outside what is currently on the frame.
- (slow-terminal-mode (and (<= baud-rate search-slow-speed)
- (> (window-height)
- (* 4 search-slow-window-lines))))
- ;; t means a small window is currently in use.
- (small-window nil) ;if t, using a small window
- ;; These variables preserve information from the small window
- ;; through exit from the save-window-excursion.
- (found-point nil)
- (found-start nil)
- ;; Point is at one end of the last match.
- ;; This variable records the other end of that match.
- (other-end nil)
- ;; Value of point at start of search,
- ;; for moving the cursor back on quitting.
- (opoint (point))
- (inhibit-quit t) ;Prevent ^G from quitting, so we can read it.
- ;; The frame we're working on; if this changes, we exit isearch.
- (frame (if (fboundp 'selected-frame) (selected-frame))))
-
- (isearch-push-state)
- (save-window-excursion
- (catch 'search-done
- (while t
- (or (and (numberp unread-command-char) (>= 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-event))))
- (setq quit-flag nil liberalized nil yank-flag nil)
- (cond ((and (or (not (integerp char))
- (and (>= char 128)
- (not (= char search-ring-advance-char))
- (not (= char search-ring-retreat-char))))
- search-exit-option)
- (setq unread-command-char char)
- (throw 'search-done t))
-
- ;; If the user switches to a different frame, exit.
- ((not (eq frame last-event-frame))
- (setq unread-command-char char)
- (throw 'search-done t))
-
- ((eq char search-exit-char)
- ;; RET 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.
- (isearch-get-string-from-ring)
- ;; 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 "")
- (progn
- ;; If repeating a search that found an empty string,
- ;; ensure we advance. Test history to make sure we
- ;; actually have done a search already; otherwise,
- ;; the match data will be random.
- (if (and (cdr history)
- (= (match-end 0) (match-beginning 0)))
- (forward-char (if forward 1 -1)))
- (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 history))
- (ding)
- (isearch-pop)))
- ((= char search-ring-advance-char)
- (isearch-pop)
- (if regexp
- (let ((length (length regexp-search-ring)))
- (if (zerop length)
- ()
- (setq regexp-search-ring-yank-pointer
- (nthcdr (% (+ 1 (- length (length regexp-search-ring-yank-pointer)))
- length)
- regexp-search-ring))
- (isearch-get-string-from-ring)))
- (let ((length (length search-ring)))
- (if (zerop length)
- ()
- (setq search-ring-yank-pointer
- (nthcdr (% (+ 1 (- length (length search-ring-yank-pointer)))
- length)
- search-ring))
- (isearch-get-string-from-ring))))
- (isearch-push-state)
- (isearch-search))
- ((= char search-ring-retreat-char)
- (isearch-pop)
- (if regexp
- (let ((length (length regexp-search-ring)))
- (if (zerop length)
- ()
- (setq regexp-search-ring-yank-pointer
- (nthcdr (% (+ (- length (length regexp-search-ring-yank-pointer))
- (1- length))
- length)
- regexp-search-ring))
- (isearch-get-string-from-ring)))
- (let ((length (length search-ring)))
- (if (zerop length)
- ()
- (setq search-ring-yank-pointer
- (nthcdr (% (+ (- length (length search-ring-yank-pointer))
- (1- length))
- length)
- search-ring))
- (isearch-get-string-from-ring))))
- (isearch-push-state)
- (isearch-search))
- (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 ""))
- ;; Don't move cursor in reverse search.
- yank-flag t)))
- ;; 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 ?\n))))
- (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)
- ;; RET translates to newline.
- (setq char ?\n)))
- (setq search-string (concat search-string
- (char-to-string char))
- search-message (concat search-message
- (text-char-description char))
- uppercase-flag (or uppercase-flag
- (not (= char (downcase char)))))))
- (if (and (not success)
- ;; unsuccessful regexp search may become
- ;; successful by addition of characters which
- ;; make search-string valid
- (not regexp))
- nil
- ;; Check for chars that can make a regexp more liberal.
- ;; They can make a regexp match sooner
- ;; or make it succeed instead of failing.
- ;; So go back to place last successful search started
- ;; or to the last ^S/^R (barrier), whichever is nearer.
- (and regexp history
- (cond ((and (memq char '(?* ??))
- ;; Don't treat *, ? as special
- ;; within [] or after \.
- (not (nth 6 (car history))))
- (setq liberalized 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 history)))))
- ;; (car history) is after last search;
- ;; (car (cdr history)) is from before it.
- (setq cs (or cs barrier))
- (goto-char
- (if forward
- (max cs barrier)
- (min cs barrier)))))
- ((eq char ?\|)
- (setq liberalized t)
- (goto-char barrier))))
- ;; Turn off case-sensitivity if string requests it.
- (let ((case-fold-search
- (and case-fold-search
- (not (and uppercase-flag
- search-upper-case)))))
- ;; In reverse search, adding stuff at
- ;; the end may cause zero or many more chars to be
- ;; matched, in the string following point.
- ;; Allow all those possibilities without moving point as
- ;; long as the match does not extend past search origin.
- (if (and (not forward) (not liberalized)
- (condition-case ()
- (looking-at (if regexp search-string
- (regexp-quote search-string)))
- (error nil))
- (or yank-flag
- ;; Used to have (min opoint barrier)
- ;; instead of barrier.
- ;; This lost when wrapping.
- (<= (match-end 0) 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 liberalized))
- (goto-char (if forward other-end
- ;; Used to have opoint inside the min.
- ;; This lost when wrapping.
- (min barrier (1+ other-end)))))
- (isearch-search))))
- (isearch-push-state))))
- (if op-fun (funcall op-fun))))
- (setq found-start (window-start (selected-window)))
- (setq found-point (point)))
- (if (> (length search-string) 0)
- (if (and regexp (not (member search-string regexp-search-ring)))
- (progn
- (setq regexp-search-ring (cons (cons search-string uppercase-flag)
- regexp-search-ring)
- regexp-search-ring-yank-pointer regexp-search-ring)
- (if (> (length regexp-search-ring) search-ring-max)
- (setcdr (nthcdr (1- search-ring-max) regexp-search-ring) nil)))
- (if (not (member search-string search-ring))
- (progn
- (setq search-ring (cons (cons search-string uppercase-flag)
- search-ring)
- search-ring-yank-pointer search-ring)
- (if (> (length search-ring) search-ring-max)
- (setcdr (nthcdr (1- search-ring-max) search-ring) nil))))))
- ;; 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 (or (not case-fold-search)
- (and uppercase-flag search-upper-case))
- "case-sensitive ")
- (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)))))
-
-;; Get the search string from the "front" of the ring of previous searches.
-(defun isearch-get-string-from-ring ()
- (let ((elt (car (if regexp
- (or regexp-search-ring-yank-pointer regexp-search-ring)
- (or search-ring-yank-pointer search-ring)))))
- ;; ELT describes the most recent search or where we have rotated the ring.
- (if elt
- (setq search-string (car elt)
- uppercase-flag (cdr elt))
- (setq search-string "" uppercase-flag nil)))
- ;; Let's give this one the benefit of the doubt.
- (setq invalid-regexp nil)
- (setq search-message (mapconcat 'text-char-description search-string "")))
-
-(defun isearch-pop ()
- (setq history (cdr history))
- (let ((cmd (car history)))
- (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)
- uppercase-flag (nth 9 cmd))
- (goto-char (car (cdr (cdr cmd))))))
-
-(defun isearch-push-state ()
- (setq history (cons (list search-string search-message (point)
- success forward other-end invalid-regexp
- wrapped barrier uppercase-flag)
- history)))
-
-(defun isearch-search ()
- (let ((case-fold-search
- (and case-fold-search
- (not (and uppercase-flag
- search-upper-case)))))
- (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 history))
- (ding))
- (goto-char (nth 2 (car history))))))
-
-;; 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-event)))
- (if (and (numberp char) (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))
- ;; Empty means use default.
- (if (= 0 (length string))
- (setq string search-last-string)
- ;; Set last search string now so it is set even if we fail.
- (setq search-last-string 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)))
-
-;;; isearch.el ends here
diff --git a/lisp/=iso8859-1.el b/lisp/=iso8859-1.el
deleted file mode 100644
index 34d0ac0d368..00000000000
--- a/lisp/=iso8859-1.el
+++ /dev/null
@@ -1,104 +0,0 @@
-;;; iso8859-1.el --- set up case-conversion and syntax tables for ISO 8859/1
-
-;; Copyright (C) 1988 Free Software Foundation, Inc.
-
-;; Author: Howard Gayle
-;; Maintainer: FSF
-;; Keywords: i18n
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; Written by Howard Gayle. See case-table.el for details.
-
-;;; Code:
-
-(require 'case-table)
-
-(let ((table (car (standard-case-table))))
- (set-case-syntax 160 " " table) ; NBSP (no-break space)
- (set-case-syntax 161 "." table) ; inverted exclamation mark
- (set-case-syntax 162 "w" table) ; cent sign
- (set-case-syntax 163 "w" table) ; pound sign
- (set-case-syntax 164 "w" table) ; general currency sign
- (set-case-syntax 165 "w" table) ; yen sign
- (set-case-syntax 166 "_" table) ; broken vertical line
- (set-case-syntax 167 "w" table) ; section sign
- (set-case-syntax 168 "w" table) ; diaeresis
- (set-case-syntax 169 "_" table) ; copyright sign
- (set-case-syntax 170 "w" table) ; ordinal indicator, feminine
- (set-case-syntax-delims 171 187 table) ; angle quotation marks
- (set-case-syntax 172 "_" table) ; not sign
- (set-case-syntax 173 "_" table) ; soft hyphen
- (set-case-syntax 174 "_" table) ; registered sign
- (set-case-syntax 175 "w" table) ; macron
- (set-case-syntax 176 "_" table) ; degree sign
- (set-case-syntax 177 "_" table) ; plus or minus sign
- (set-case-syntax 178 "w" table) ; superscript two
- (set-case-syntax 179 "w" table) ; superscript three
- (set-case-syntax 180 "w" table) ; acute accent
- (set-case-syntax 181 "_" table) ; micro sign
- (set-case-syntax 182 "w" table) ; pilcrow
- (set-case-syntax 183 "_" table) ; middle dot
- (set-case-syntax 184 "w" table) ; cedilla
- (set-case-syntax 185 "w" table) ; superscript one
- (set-case-syntax 186 "w" table) ; ordinal indicator, masculine
- ;; 187 ; See 171 above.
- (set-case-syntax 188 "_" table) ; fraction one-quarter
- (set-case-syntax 189 "_" table) ; fraction one-half
- (set-case-syntax 190 "_" table) ; fraction three-quarters
- (set-case-syntax 191 "." table) ; inverted question mark
- (set-case-syntax-pair 192 224 table) ; A with grave accent
- (set-case-syntax-pair 193 225 table) ; A with acute accent
- (set-case-syntax-pair 194 226 table) ; A with circumflex accent
- (set-case-syntax-pair 195 227 table) ; A with tilde
- (set-case-syntax-pair 196 228 table) ; A with diaeresis or umlaut mark
- (set-case-syntax-pair 197 229 table) ; A with ring
- (set-case-syntax-pair 198 230 table) ; AE diphthong
- (set-case-syntax-pair 199 231 table) ; C with cedilla
- (set-case-syntax-pair 200 232 table) ; E with grave accent
- (set-case-syntax-pair 201 233 table) ; E with acute accent
- (set-case-syntax-pair 202 234 table) ; E with circumflex accent
- (set-case-syntax-pair 203 235 table) ; E with diaeresis or umlaut mark
- (set-case-syntax-pair 204 236 table) ; I with grave accent
- (set-case-syntax-pair 205 237 table) ; I with acute accent
- (set-case-syntax-pair 206 238 table) ; I with circumflex accent
- (set-case-syntax-pair 207 239 table) ; I with diaeresis or umlaut mark
- (set-case-syntax-pair 208 240 table) ; D with stroke, Icelandic eth
- (set-case-syntax-pair 209 241 table) ; N with tilde
- (set-case-syntax-pair 210 242 table) ; O with grave accent
- (set-case-syntax-pair 211 243 table) ; O with acute accent
- (set-case-syntax-pair 212 244 table) ; O with circumflex accent
- (set-case-syntax-pair 213 245 table) ; O with tilde
- (set-case-syntax-pair 214 246 table) ; O with diaeresis or umlaut mark
- (set-case-syntax 215 "_" table) ; multiplication sign
- (set-case-syntax-pair 216 248 table) ; O with slash
- (set-case-syntax-pair 217 249 table) ; U with grave accent
- (set-case-syntax-pair 218 250 table) ; U with acute accent
- (set-case-syntax-pair 219 251 table) ; U with circumflex accent
- (set-case-syntax-pair 220 252 table) ; U with diaeresis or umlaut mark
- (set-case-syntax-pair 221 253 table) ; Y with acute accent
- (set-case-syntax-pair 222 254 table) ; thorn, Icelandic
- (set-case-syntax 223 "w" table) ; small sharp s, German
- (set-case-syntax 247 "_" table) ; division sign
- (set-case-syntax 255 "w" table) ; small y with diaeresis or umlaut mark
- (set-standard-case-table (list table)))
-
-(provide 'iso8859-1)
-
-;;; iso8859-1.el ends here
diff --git a/lisp/=man.el b/lisp/=man.el
deleted file mode 100644
index 6461f3f2447..00000000000
--- a/lisp/=man.el
+++ /dev/null
@@ -1,181 +0,0 @@
-;;; man.el --- read in and display parts of Unix manual.
-
-;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: unix
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; This package provides an equivalent of the UNIX man(1) command within
-;; Emacs. The single entry point is `manual-entry'.
-
-;;; Code:
-
-;;;###autoload
-(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)\"."
- (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)
- (save-excursion
- (set-buffer standard-output)
- (message "Looking for formatted entry for %s%s..."
- topic (if section (concat "(" section ")") ""))
- (let ((dirlist manual-formatted-dirlist)
- (case-fold-search nil)
- name)
- (if (and section (or (file-exists-p
- (setq name (concat manual-formatted-dir-prefix
- (substring section 0 1)
- "/"
- topic "." section)))
- (file-exists-p
- (setq name (concat manual-formatted-dir-prefix
- section
- "/"
- topic "." section)))))
- (insert-man-file name)
- (while dirlist
- (let* ((dir (car dirlist))
- (name1 (concat dir "/" topic "."
- (or section
- (substring
- dir
- (1+ (or (string-match "\\.[^./]*$" dir)
- -2))))))
- completions)
- (if (file-exists-p name1)
- (insert-man-file name1)
- (condition-case ()
- (progn
- (setq completions (file-name-all-completions
- (concat topic "." (or section ""))
- dir))
- (while completions
- (insert-man-file (concat dir "/" (car completions)))
- (setq completions (cdr completions))))
- (file-error nil)))
- (goto-char (point-max)))
- (setq dirlist (cdr dirlist)))))
-
- (if (= (buffer-size) 0)
- (progn
- (message "No formatted entry, invoking man %s%s..."
- (if section (concat section " ") "") topic)
- (if section
- (call-process manual-program nil t nil section topic)
- (call-process manual-program nil t nil topic))
- (if (< (buffer-size) 80)
- (progn
- (goto-char (point-min))
- (end-of-line)
- (error (buffer-substring 1 (point)))))))
-
- (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"
-(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.
- ;; These numbers are correct for MORE BSD, at least.
- (setq start (save-excursion (forward-line -9) (point)))
- (setq end (save-excursion (forward-line 3) (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)
- (let* ((preceding (char-after (- (point) 2)))
- (following (following-char)))
- (cond ((= preceding following)
- ;; x\bx
- (delete-char -2))
- ((and (= preceding ?o) (= following ?\+))
- ;; o\b+
- (delete-char -2))
- ((= preceding ?\_)
- ;; _\b
- (delete-char -2))
- ((= following ?\_)
- ;; \b_
- (delete-region (1- (point)) (1+ (point)))))))
-
- ;; Zap ESC7, ESC8, and ESC9.
- ;; This is for Sun man pages like "man 1 csh"
- (goto-char (point-min))
- (while (re-search-forward "\e[789]" nil t)
- (replace-match ""))
-
- ;; Convert o^H+ into o.
- (goto-char (point-min))
- (while (re-search-forward "o\010\\+" nil t)
- (replace-match "o"))
-
- ;; Nuke the dumb reformatting message
- (goto-char (point-min))
- (while (re-search-forward "Reformatting page. Wait... done\n\n" nil t)
- (replace-match ""))
-
- ;; Crunch blank lines
- (goto-char (point-min))
- (while (re-search-forward "\n\n\n\n*" nil t)
- (replace-match "\n\n"))
-
- ;; Nuke blanks lines at start.
- (goto-char (point-min))
- (skip-chars-forward "\n")
- (delete-region (point-min) (point)))
-
-
-(defun insert-man-file (name)
- ;; Insert manual file (unpacked as necessary) into buffer
- (if (or (equal (substring name -2) ".Z")
- (string-match "/cat[0-9][a-z]?\\.Z/" name))
- (call-process "zcat" name t nil)
- (if (equal (substring name -2) ".z")
- (call-process "pcat" nil t nil name)
- (insert-file-contents name))))
-
-;;; man.el ends here
diff --git a/lisp/=medit.el b/lisp/=medit.el
deleted file mode 100644
index 985c9b27344..00000000000
--- a/lisp/=medit.el
+++ /dev/null
@@ -1,123 +0,0 @@
-;;; medit.el --- front-end to the MEDIT package for editing MDL
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Author: K. Shane Hartman
-;; Maintainer: FSF
-;; Keywords: languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; >> This package depends on two MDL packages: MEDIT and FORKS which
-;; >> can be obtained from the public (network) library at mit-ajax.
-
-;;; Code:
-
-(require 'mim-mode)
-
-(defconst medit-zap-file (concat "/tmp/" (user-login-name) ".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.")
-(defconst medit-save-files t
- "If non-nil, Medit offers to save files on return to MDL.")
-
-(defun medit-save-define ()
- "Mark the previous or surrounding toplevel object to be sent back to MDL."
- (interactive)
- (save-excursion
- (beginning-of-DEFINE)
- (let ((start (point)))
- (forward-mim-object 1)
- (append-to-buffer medit-buffer start (point))
- (goto-char start)
- (message "%s" (buffer-substring start (progn (end-of-line) (point)))))))
-
-(defun medit-save-region (start end)
- "Mark the current region to be sent to back to MDL."
- (interactive "r")
- (append-to-buffer medit-buffer start end)
- (message "Current region saved for MDL."))
-
-(defun medit-save-buffer ()
- "Mark the current buffer to be sent back to MDL."
- (interactive)
- (append-to-buffer medit-buffer (point-min) (point-max))
- (message "Current buffer saved for MDL."))
-
-(defun medit-zap-define-to-mdl ()
- "Return to MDL with surrounding or previous toplevel MDL object."
- (interactive)
- (medit-save-define)
- (medit-goto-mdl))
-
-(defun medit-zap-region-mdl (start end)
- "Return to MDL with current region."
- (interactive)
- (medit-save-region start end)
- (medit-goto-mdl))
-
-(defun medit-zap-buffer ()
- "Return to MDL with current buffer."
- (interactive)
- (medit-save-buffer)
- (medit-goto-mdl))
-
-(defun medit-goto-mdl ()
- "Return from Emacs to superior MDL, sending saved code.
-Optionally, offers to save changed files."
- (interactive)
- (let ((buffer (get-buffer medit-buffer)))
- (if buffer
- (save-excursion
- (set-buffer buffer)
- (if (buffer-modified-p buffer)
- (write-region (point-min) (point-max) medit-zap-file))
- (set-buffer-modified-p nil)
- (erase-buffer)))
- (if medit-save-files (save-some-buffers))
- ;; Note could handle parallel fork by giving argument "%xmdl". Then
- ;; mdl would have to invoke with "%emacs".
- (suspend-emacs)))
-
-(defconst medit-mode-map nil)
-(if (not medit-mode-map)
- (progn
- (setq medit-mode-map (copy-keymap 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)
- (define-key medit-mode-map "\^xs" 'medit-zap-buffer)))
-
-(defconst medit-mode-hook (and (boundp 'mim-mode-hook) mim-mode-hook) "")
-(setq mim-mode-hook '(lambda () (medit-mode)))
-
-(defun medit-mode (&optional state)
- "Major mode for editing text and returning it to a superior MDL.
-Like Mim mode, plus these special commands:
-\\{medit-mode-map}"
- (interactive)
- (use-local-map medit-mode-map)
- (run-hooks 'medit-mode-hook)
- (setq major-mode 'medit-mode)
- (setq mode-name "Medit"))
-
-(mim-mode)
-
-;;; medit.el ends here
diff --git a/lisp/=mh-e.el b/lisp/=mh-e.el
deleted file mode 100644
index 619556d260f..00000000000
--- a/lisp/=mh-e.el
+++ /dev/null
@@ -1,2933 +0,0 @@
-;;; mh-e.el --- GNU Emacs interface to the MH mail system
-
-;;; Copyright (C) 1985, 86, 87, 88, 90, 92, 93 Free Software Foundation
-
-(defconst mh-e-time-stamp "Time-stamp: <93/05/30 18:37:43 gildea>")
-
-;; Maintainer: Stephen Gildea <gildea@lcs.mit.edu>
-;; Version: 3.8.2
-;; Keywords: mail
-
-;; 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.
-
-;;; Commentary:
-
-;;; mh-e works with Emacs 18 or 19, and MH 5 or 6.
-
-;;; 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-cr" 'mh-rmail)
-
-;;; MH (Message Handler) is a powerful mail reader. The MH newsgroup
-;;; is comp.mail.mh; the mailing list is mh-users@ics.uci.edu (send to
-;;; mh-users-request to be added). See the monthly Frequently Asked
-;;; Questions posting there for information on getting MH.
-
-;;; 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.
-
-;;; 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 1988. gildea@bbn.com
-(defconst mh-e-RCS-id "$Header: /home/fsf/rms/e19/lisp/RCS/mh-e.el,v 1.15 1993/07/20 04:35:00 rms Exp rms $")
-
-;;; Code:
-
-
-
-;;; 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 t))
- (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.")
-
-(defvar mh-signature-file-name "~/.signature"
- "*Name of file containing the user's signature.
-Inserted into message by \\<mh-letter-mode-map>\\[mh-insert-signature].")
-
-
-;;; 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 specifying 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-searching-folder nil
- "Folder this pick is searching.")
-
-(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 t)))))
-
-
-(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 message 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.
-
- mh-signature-file-name (\"~/.signature\")
- File to be inserted into message by \\[mh-insert-signature].
-
-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 (and (boundp 'auto-fill-hook) auto-fill-hook) ;emacs 18
- (make-local-variable 'auto-fill-hook)
- (setq auto-fill-hook 'mh-auto-fill-for-letter))
- (mh-when (and (boundp 'auto-fill-function) auto-fill-function) ;emacs 19
- (make-local-variable 'auto-fill-function)
- (setq auto-fill-function '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 (point-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 (point-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 named by mh-signature-file-name at the current point."
- (interactive)
- (insert-file-contents mh-signature-file-name)
- (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 msgs
- (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-active
- (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 "\en" 'mh-unshar-msg)
-(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: ***
-
-(provide 'mh-e)
-
-;;; mh-e.el ends here
diff --git a/lisp/=mhspool.el b/lisp/=mhspool.el
deleted file mode 100644
index b81823938f0..00000000000
--- a/lisp/=mhspool.el
+++ /dev/null
@@ -1,490 +0,0 @@
-;;; mhspool.el --- MH folder access using NNTP for GNU Emacs
-
-;; Copyright (C) 1988, 1989, 1990, 1993 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Maintainer: FSF
-;; Keywords: mail, news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; 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'.
-
-;;; Code:
-
-(require 'nntp)
-
-(defvar mhspool-list-folders-method
- (function mhspool-list-folders-using-sh)
- "*Function to list files in folders.
-The function should accept a directory as its argument, and fill the
-current buffer with file and directory names. The output format must
-be the same as that of 'ls -R1'. Two functions
-mhspool-list-folders-using-ls and mhspool-list-folders-using-sh are
-provided now. I suppose the later is faster.")
-
-(defvar mhspool-list-directory-switches '("-R")
- "*Switches for mhspool-list-folders-using-ls to pass to `ls' for getting file lists.
-One entry should appear on one line. You may need to add `-1' option.")
-
-
-
-(defconst mhspool-version "MHSPOOL 1.8"
- "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] ...)'.
-If there is no References: field, In-Reply-To: field is used instead.
-Reader macros for the vector are defined as `nntp-header-FIELD'.
-Writer macros for the vector are defined as `nntp-set-header-FIELD'.
-Newsgroup must be selected before calling this."
- (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)))))
- ;; Count lines since there is no lines field in most cases.
- (setq lines
- (save-restriction
- (goto-char (point-max))
- (widen)
- (count-lines (point) (point-max)))))
- ;; 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))
- ;; Collect valid article only.
- (and article
- message-id
- (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: Receiving headers... %d%%"
- (/ (* count 100) number)))
- )
- (and (numberp nntp-large-newsgroup)
- (> number nntp-large-newsgroup)
- (message "MHSPOOL: Receiving headers... done"))
- (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-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-string
- (format "No such directory: %s. Goodbye."
- mhspool-spool-directory)))
- ((null host)
- (setq nntp-status-string "NNTP server is not specified."))
- (t
- (setq nntp-status-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-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)."
- (setq nntp-status-string "MHSPOOL: STAT is not implemented.")
- nil
- )
-
-(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 active 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 " *MHSPOOL File List*")))
- (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)))
- (funcall mhspool-list-folders-method 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-list-newsgroups ()
- "List newsgoups (defined in NNTP2)."
- (setq nntp-status-string "MHSPOOL: LIST NEWSGROUPS is not implemented.")
- nil
- )
-
-(defun mhspool-request-list-distributions ()
- "List distributions (defined in NNTP2)."
- (setq nntp-status-string "MHSPOOL: LIST DISTRIBUTIONS is not implemented.")
- nil
- )
-
-(defun mhspool-request-last ()
- "Set current article pointer to the previous article
-in the current news group."
- (setq nntp-status-string "MHSPOOL: LAST is not implemented.")
- nil
- )
-
-(defun mhspool-request-next ()
- "Advance current article pointer."
- (setq nntp-status-string "MHSPOOL: NEXT is not implemented.")
- nil
- )
-
-(defun mhspool-request-post ()
- "Post a new news in current buffer."
- (setq nntp-status-string "MHSPOOL: POST: what do you mean?")
- 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 occurrences of FROM with TO.
- (while (< idx len)
- (if (= (aref string idx) from)
- (aset string idx to))
- (setq idx (1+ idx)))
- string
- ))
-
-
-;; Methods for listing files in folders.
-
-(defun mhspool-list-folders-using-ls (directory)
- "List files in folders under DIRECTORY using 'ls'."
- (apply 'call-process
- "ls" nil t nil
- (append mhspool-list-directory-switches (list directory))))
-
-;; Basic ideas by tanaka@flab.fujitsu.co.jp (Hiroshi TANAKA)
-
-(defun mhspool-list-folders-using-sh (directory)
- "List files in folders under DIRECTORY using '/bin/sh'."
- (let ((buffer (current-buffer))
- (script (get-buffer-create " *MHSPOOL Shell Script Buffer*")))
- (save-excursion
- (save-restriction
- (set-buffer script)
- (erase-buffer)
- ;; /bin/sh script which does 'ls -R'.
- (insert
- "PS2=
- ffind() {
- cd $1; echo $1:
- ls -1
- echo
- for j in `echo *[a-zA-Z]*`
- do
- if [ -d $1/$j ]; then
- ffind $1/$j
- fi
- done
- }
- cd " directory "; ffind `pwd`; exit 0\n")
- (call-process-region (point-min) (point-max) "sh" nil buffer nil)
- ))
- (kill-buffer script)
- ))
-
-(provide 'mhspool)
-
-;;; mhspool.el ends here
diff --git a/lisp/=mim-mode.el b/lisp/=mim-mode.el
deleted file mode 100644
index 94e63cb9f48..00000000000
--- a/lisp/=mim-mode.el
+++ /dev/null
@@ -1,848 +0,0 @@
-;;; mim-mode.el --- Mim (MDL in MDL) mode.
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Author: K. Shane Hartman
-;; Maintainer: FSF
-;; Keywords: languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Code:
-
-(autoload 'fast-syntax-check-mim "mim-syntax"
- "Checks Mim syntax quickly.
-Answers correct or incorrect, cannot point out the error context."
- t)
-
-(autoload 'slow-syntax-check-mim "mim-syntax"
- "Check Mim syntax slowly.
-Points out the context of the error, if the syntax is incorrect."
- t)
-
-(defvar mim-mode-hysterical-bindings t
- "*Non-nil means bind list manipulation commands to Meta keys as well as
-Control-Meta keys for historical reasons. Otherwise, only the latter keys
-are bound.")
-
-(defvar mim-mode-map nil)
-
-(defvar mim-mode-syntax-table nil)
-
-(if mim-mode-syntax-table
- ()
- (let ((i -1))
- (setq mim-mode-syntax-table (make-syntax-table))
- (while (< i ?\ )
- (modify-syntax-entry (setq i (1+ i)) " " mim-mode-syntax-table))
- (while (< i 127)
- (modify-syntax-entry (setq i (1+ i)) "_ " mim-mode-syntax-table))
- (setq i (1- ?a))
- (while (< i ?z)
- (modify-syntax-entry (setq i (1+ i)) "w " mim-mode-syntax-table))
- (setq i (1- ?A))
- (while (< i ?Z)
- (modify-syntax-entry (setq i (1+ i)) "w " mim-mode-syntax-table))
- (setq i (1- ?0))
- (while (< i ?9)
- (modify-syntax-entry (setq i (1+ i)) "w " mim-mode-syntax-table))
- (modify-syntax-entry ?: " " mim-mode-syntax-table) ; make : symbol delimiter
- (modify-syntax-entry ?, "' " mim-mode-syntax-table)
- (modify-syntax-entry ?. "' " mim-mode-syntax-table)
- (modify-syntax-entry ?' "' " mim-mode-syntax-table)
- (modify-syntax-entry ?` "' " mim-mode-syntax-table)
- (modify-syntax-entry ?~ "' " mim-mode-syntax-table)
- (modify-syntax-entry ?\; "' " mim-mode-syntax-table) ; comments are prefixed objects
- (modify-syntax-entry ?# "' " mim-mode-syntax-table)
- (modify-syntax-entry ?% "' " mim-mode-syntax-table)
- (modify-syntax-entry ?! "' " mim-mode-syntax-table)
- (modify-syntax-entry ?\" "\" " mim-mode-syntax-table)
- (modify-syntax-entry ?\\ "\\ " mim-mode-syntax-table)
- (modify-syntax-entry ?\( "\() " mim-mode-syntax-table)
- (modify-syntax-entry ?\< "\(> " mim-mode-syntax-table)
- (modify-syntax-entry ?\{ "\(} " mim-mode-syntax-table)
- (modify-syntax-entry ?\[ "\(] " mim-mode-syntax-table)
- (modify-syntax-entry ?\) "\)( " mim-mode-syntax-table)
- (modify-syntax-entry ?\> "\)< " mim-mode-syntax-table)
- (modify-syntax-entry ?\} "\){ " mim-mode-syntax-table)
- (modify-syntax-entry ?\] "\)[ " mim-mode-syntax-table)))
-
-(defconst mim-whitespace "\000- ")
-
-(defvar mim-mode-hook nil
- "*User function run after mim mode initialization. Usage:
-\(setq mim-mode-hook '(lambda () ... your init forms ...)).")
-
-(define-abbrev-table 'mim-mode-abbrev-table nil)
-
-(defconst indent-mim-function 'indent-mim-function
- "Controls (via properties) indenting of special forms.
-\(put 'FOO 'indent-mim-function 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
-value of mim-body-indent as offset from start of form.
-\(put 'FOO 'indent-mim-function <cons>\) where <cons> is a list or pointed 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\)\)
-<FROBIT
- <CHOMP-IT>
- <CHOMP-SOME-MORE>
- <DIGEST>
- <BELCH>
- ...>
-Finally, the property can be a function name (read the code).")
-
-(defvar indent-mim-comment t
- "*Non-nil means indent string comments.")
-
-(defvar mim-body-indent 2
- "*Amount to indent in special forms which have DEFINE property on
-`indent-mim-function'.")
-
-(defvar indent-mim-arglist t
- "*nil means indent arglists like ordinary lists.
-t means strings stack under start of arglist and variables stack to
-right of them. Otherwise, strings stack under last string (or start
-of arglist if none) and variables stack to right of them.
-Examples (for values 'stack, t, nil):
-
-\(FOO \"OPT\" BAR \(FOO \"OPT\" BAR \(FOO \"OPT\" BAR
- BAZ MUMBLE BAZ MUMBLE BAZ MUMBLE
- \"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))
-
-(defvar mim-down-parens-only t
- "*nil means treat ADECLs and ATOM trailers like structures when
-moving down a level of structure.")
-
-(defvar mim-stop-for-slop t
- "*Non-nil means {next previous}-mim-object consider any
-non-whitespace character in column 0 to be a toplevel object, otherwise
-only open paren syntax characters will be considered.")
-
-(defalias 'mdl-mode 'mim-mode)
-
-(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).
-The default action is bind the escape keys.
-\\{mim-mode-map}
-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-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."
- (interactive)
- (kill-all-local-variables)
- (if (not mim-mode-map)
- (progn
- (setq mim-mode-map (make-sparse-keymap))
- (define-key mim-mode-map "\e\^o" 'open-mim-line)
- (define-key mim-mode-map "\e\^q" 'indent-mim-object)
- (define-key mim-mode-map "\e\^p" 'previous-mim-object)
- (define-key mim-mode-map "\e\^n" 'next-mim-object)
- (define-key mim-mode-map "\e\^a" 'beginning-of-DEFINE)
- (define-key mim-mode-map "\e\^e" 'end-of-DEFINE)
- (define-key mim-mode-map "\e\^t" 'transpose-mim-objects)
- (define-key mim-mode-map "\e\^u" 'backward-up-mim-object)
- (define-key mim-mode-map "\e\^d" 'forward-down-mim-object)
- (define-key mim-mode-map "\e\^h" 'mark-mim-object)
- (define-key mim-mode-map "\e\^k" 'forward-kill-mim-object)
- (define-key mim-mode-map "\e\^f" 'forward-mim-object)
- (define-key mim-mode-map "\e\^b" 'backward-mim-object)
- (define-key mim-mode-map "\e^" 'raise-mim-line)
- (define-key mim-mode-map "\e\\" 'fixup-whitespace)
- (define-key mim-mode-map "\177" 'backward-delete-char-untabify)
- (define-key mim-mode-map "\e\177" 'backward-kill-mim-object)
- (define-key mim-mode-map "\^j" 'newline-and-mim-indent)
- (define-key mim-mode-map "\e;" 'begin-mim-comment)
- (define-key mim-mode-map "\t" 'indent-mim-line)
- (define-key mim-mode-map "\e\t" 'indent-mim-object)
- (if (not mim-mode-hysterical-bindings)
- nil
- ;; i really hate this but too many people are accustomed to these.
- (define-key mim-mode-map "\e!" 'line-to-top-of-window)
- (define-key mim-mode-map "\eo" 'open-mim-line)
- (define-key mim-mode-map "\ep" 'previous-mim-object)
- (define-key mim-mode-map "\en" 'next-mim-object)
- (define-key mim-mode-map "\ea" 'beginning-of-DEFINE)
- (define-key mim-mode-map "\ee" 'end-of-DEFINE)
- (define-key mim-mode-map "\et" 'transpose-mim-objects)
- (define-key mim-mode-map "\eu" 'backward-up-mim-object)
- (define-key mim-mode-map "\ed" 'forward-down-mim-object)
- (define-key mim-mode-map "\ek" 'forward-kill-mim-object)
- (define-key mim-mode-map "\ef" 'forward-mim-object)
- (define-key mim-mode-map "\eb" 'backward-mim-object))))
- (use-local-map mim-mode-map)
- (set-syntax-table mim-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)
- ;; Most people use string comments.
- (make-local-variable 'comment-start)
- (setq comment-start ";\"")
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip ";\"")
- (make-local-variable 'comment-end)
- (setq comment-end "\"")
- (make-local-variable 'comment-column)
- (setq comment-column 40)
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'indent-mim-comment)
- ;; tell generic indenter how to indent.
- (make-local-variable 'indent-line-function)
- (setq indent-line-function 'indent-mim-line)
- ;; look for that paren
- (make-local-variable 'blink-matching-paren-distance)
- (setq blink-matching-paren-distance nil)
- ;; so people who dont like tabs can turn them off locally in indenter.
- (make-local-variable 'indent-tabs-mode)
- (setq indent-tabs-mode t)
- (setq local-abbrev-table mim-mode-abbrev-table)
- (setq major-mode 'mim-mode)
- (setq mode-name "Mim")
- (run-hooks 'mim-mode-hook))
-
-(defun line-to-top-of-window ()
- "Move current line to top of window."
- (interactive) ; for lazy people
- (recenter 0))
-
-(defun forward-mim-object (arg)
- "Move forward across Mim object.
-With ARG, move forward that many objects."
- (interactive "p")
- ;; this function is weird because it emulates the behavior of the old
- ;; (gosling) mim-mode - if the arg is 1 and we are `inside' an ADECL,
- ;; more than one character into the ATOM part and not sitting on the
- ;; colon, then we move to the DECL part (just past colon) instead of
- ;; the end of the object (the entire ADECL). otherwise, ADECL's are
- ;; atomic objects. likewise for ATOM trailers.
- (if (= (abs arg) 1)
- (if (inside-atom-p)
- ;; Move to end of ATOM or to trailer (!) or to ADECL (:).
- (forward-sexp arg)
- ;; Either scan an sexp or move over one bracket.
- (forward-mim-objects arg t))
- ;; in the multi-object case, don't perform any magic.
- ;; treats ATOM trailers and ADECLs atomically, stops at unmatched
- ;; brackets with error.
- (forward-mim-objects arg)))
-
-(defun inside-atom-p ()
- ;; Returns t iff inside an atom (takes account of trailers)
- (let ((c1 (preceding-char))
- (c2 (following-char)))
- (and (or (= (char-syntax c1) ?w) (= (char-syntax c1) ?_) (= c1 ?!))
- (or (= (char-syntax c2) ?w) (= (char-syntax c2) ?_) (= c2 ?!)))))
-
-(defun forward-mim-objects (arg &optional skip-bracket-p)
- ;; Move over arg objects ignoring ADECLs and trailers. If
- ;; skip-bracket-p is non-nil, then move over one bracket on error.
- (let ((direction (sign arg)))
- (condition-case conditions
- (while (/= arg 0)
- (forward-sexp direction)
- (if (not (inside-adecl-or-trailer-p direction))
- (setq arg (- arg direction))))
- (error (if (not skip-bracket-p)
- (signal 'error (cdr conditions))
- (skip-mim-whitespace direction)
- (goto-char (+ (point) direction)))))
- ;; If we moved too far move back to first interesting character.
- (if (= (point) (buffer-end direction)) (skip-mim-whitespace (- direction)))))
-
-(defun backward-mim-object (&optional arg)
- "Move backward across Mim object.
-With ARG, move backward that many objects."
- (interactive "p")
- (forward-mim-object (if arg (- arg) -1)))
-
-(defun mark-mim-object (&optional arg)
- "Mark following Mim object.
-With ARG, mark that many following (preceding, ARG < 0) objects."
- (interactive "p")
- (push-mark (save-excursion (forward-mim-object (or arg 1)) (point))))
-
-(defun forward-kill-mim-object (&optional arg)
- "Kill following Mim object.
-With ARG, kill that many objects."
- (interactive "*p")
- (kill-region (point) (progn (forward-mim-object (or arg 1)) (point))))
-
-(defun backward-kill-mim-object (&optional arg)
- "Kill preceding Mim object.
-With ARG, kill that many objects."
- (interactive "*p")
- (forward-kill-mim-object (- (or arg 1))))
-
-(defun raise-mim-line (&optional arg)
- "Raise following line, fixing up whitespace at join.
-With ARG raise that many following lines.
-A negative ARG will raise current line and previous lines."
- (interactive "*p")
- (let* ((increment (sign (or arg (setq arg 1))))
- (direction (if (> arg 0) 1 0)))
- (save-excursion
- (while (/= arg 0)
- ;; move over eol and kill it
- (forward-line direction)
- (delete-region (point) (1- (point)))
- (fixup-whitespace)
- (setq arg (- arg increment))))))
-
-(defun forward-down-mim-object (&optional arg)
- "Move down a level of Mim structure forwards.
-With ARG, move down that many levels forwards (backwards, ARG < 0)."
- (interactive "p")
- ;; another weirdo - going down `inside' an ADECL or ATOM trailer
- ;; depends on the value of mim-down-parens-only. if nil, treat
- ;; ADECLs and trailers as structured objects.
- (let ((direction (sign (or arg (setq arg 1)))))
- (if (and (= (abs arg) 1) (not mim-down-parens-only))
- (goto-char
- (save-excursion
- (skip-mim-whitespace direction)
- (if (> direction 0) (re-search-forward "\\s'*"))
- (or (and (let ((c (next-char direction)))
- (or (= (char-syntax c) ?_)
- (= (char-syntax c) ?w)))
- (progn (forward-sexp direction)
- (if (inside-adecl-or-trailer-p direction)
- (point))))
- (scan-lists (point) direction -1)
- (buffer-end direction))))
- (while (/= arg 0)
- (goto-char (or (scan-lists (point) direction -1) (buffer-end direction)))
- (setq arg (- arg direction))))))
-
-(defun backward-down-mim-object (&optional arg)
- "Move down a level of Mim structure backwards.
-With ARG, move down that many levels backwards (forwards, ARG < 0)."
- (interactive "p")
- (forward-down-mim-object (if arg (- arg) -1)))
-
-(defun forward-up-mim-object (&optional arg)
- "Move up a level of Mim structure forwards
-With ARG, move up that many levels forwards (backwards, ARG < 0)."
- (interactive "p")
- (let ((direction (sign (or arg (setq arg 1)))))
- (while (/= arg 0)
- (goto-char (or (scan-lists (point) direction 1) (buffer-end arg)))
- (setq arg (- arg direction)))
- (if (< direction 0) (backward-prefix-chars))))
-
-(defun backward-up-mim-object (&optional arg)
- "Move up a level of Mim structure backwards
-With ARG, move up that many levels backwards (forwards, ARG > 0)."
- (interactive "p")
- (forward-up-mim-object (if arg (- arg) -1)))
-
-(defun replace-in-mim-object (old new)
- "Replace string in following Mim object."
- (interactive "*sReplace in object: \nsReplace %s with: ")
- (save-restriction
- (narrow-to-region (point) (save-excursion (forward-mim-object 1) (point)))
- (replace-string old new)))
-
-(defun transpose-mim-objects (&optional arg)
- "Transpose Mim objects around point.
-With ARG, transpose preceding object that many times with following objects.
-A negative ARG will transpose backwards."
- (interactive "*p")
- (transpose-subr 'forward-mim-object (or arg 1)))
-
-(defun beginning-of-DEFINE (&optional arg move)
- "Move backward to beginning of surrounding or previous toplevel Mim form.
-With ARG, do it that many times. Stops at last toplevel form seen if buffer
-end is reached."
- (interactive "p")
- (let ((direction (sign (or arg (setq arg 1)))))
- (if (not move) (setq move t))
- (if (< direction 0) (goto-char (1+ (point))))
- (while (and (/= arg 0) (re-search-backward "^<" nil move direction))
- (setq arg (- arg direction)))
- (if (< direction 0)
- (goto-char (1- (point))))))
-
-(defun end-of-DEFINE (&optional arg)
- "Move forward to end of surrounding or next toplevel mim form.
-With ARG, do it that many times. Stops at end of last toplevel form seen
-if buffer end is reached."
- (interactive "p")
- (if (not arg) (setq arg 1))
- (if (< arg 0)
- (beginning-of-DEFINE (- (1- arg)))
- (if (not (looking-at "^<")) (setq arg (1+ arg)))
- (beginning-of-DEFINE (- arg) 'move)
- (beginning-of-DEFINE 1))
- (forward-mim-object 1)
- (forward-line 1))
-
-(defun next-mim-object (&optional arg)
- "Move to beginning of next toplevel Mim object.
-With ARG, do it that many times. Stops at last object seen if buffer end
-is reached."
- (interactive "p")
- (let ((search-string (if mim-stop-for-slop "^\\S " "^\\s("))
- (direction (sign (or arg (setq arg 1)))))
- (if (> direction 0)
- (goto-char (1+ (point)))) ; no error if end of buffer
- (while (and (/= arg 0)
- (re-search-forward search-string nil t direction))
- (setq arg (- arg direction)))
- (if (> direction 0)
- (goto-char (1- (point)))) ; no error if beginning of buffer
- ;; scroll to top of window if moving forward and end not visible.
- (if (not (or (< direction 0)
- (save-excursion (forward-mim-object 1)
- (pos-visible-in-window-p (point)))))
- (recenter 0))))
-
-(defun previous-mim-object (&optional arg)
- "Move to beginning of previous toplevel Mim object.
-With ARG do it that many times. Stops at last object seen if buffer end
-is reached."
- (interactive "p")
- (next-mim-object (- (or arg 1))))
-
-(defun calculate-mim-indent (&optional parse-start)
- "Calculate indentation for Mim line. Returns column."
- (save-excursion ; some excursion, huh, toto?
- (beginning-of-line)
- (let ((indent-point (point)) retry state containing-sexp last-sexp
- desired-indent start peek where paren-depth)
- (if parse-start
- (goto-char parse-start) ; should be containing environment
- (catch 'from-the-top
- ;; find a place to start parsing. going backwards is fastest.
- ;; forward-sexp signals error on encountering unmatched open.
- (setq retry t)
- (while retry
- (condition-case nil (forward-sexp -1) (error (setq retry nil)))
- (if (looking-at ".?[ \t]*\"")
- ;; cant parse backward in presence of strings, go forward.
- (progn
- (goto-char indent-point)
- (re-search-backward "^\\s(" nil 'move 1) ; to top of object
- (throw 'from-the-top nil)))
- (setq retry (and retry (/= (current-column) 0))))
- (skip-chars-backward mim-whitespace)
- (if (not (bobp)) (forward-char -1)) ; onto unclosed open
- (backward-prefix-chars)))
- ;; find outermost containing sexp if we started inside an sexp.
- (while (< (point) indent-point)
- (setq state (parse-partial-sexp (point) indent-point 0)))
- ;; find usual column to indent under (not in string or toplevel).
- ;; on termination, state will correspond to containing environment
- ;; (if retry is nil), where will be position of character to indent
- ;; under normally, and desired-indent will be the column to indent to
- ;; except if inside form, string, or at toplevel. point will be in
- ;; in column to indent to unless inside string.
- (setq retry t)
- (while (and retry (setq paren-depth (car state)) (> paren-depth 0))
- ;; find innermost containing sexp.
- (setq retry nil)
- (setq last-sexp (car (nthcdr 2 state)))
- (setq containing-sexp (car (cdr state)))
- (goto-char (1+ containing-sexp)) ; to last unclosed open
- (if (and last-sexp (> last-sexp (point)))
- ;; is the last sexp a containing sexp?
- (progn (setq peek (parse-partial-sexp last-sexp indent-point 0))
- (if (setq retry (car (cdr peek))) (setq state peek))))
- (if retry
- nil
- (setq where (1+ containing-sexp)) ; innermost containing sexp
- (goto-char where)
- (cond
- ((not last-sexp) ; indent-point after bracket
- (setq desired-indent (current-column)))
- ((= (preceding-char) ?\<) ; it's a form
- (cond ((> (progn (forward-sexp 1) (point)) last-sexp)
- (goto-char where)) ; only one frob
- ((> (save-excursion (forward-line 1) (point)) last-sexp)
- (skip-chars-forward " \t") ; last-sexp is on same line
- (setq where (point))) ; as containing-sexp
- ((progn
- (goto-char last-sexp)
- (beginning-of-line)
- (parse-partial-sexp (point) last-sexp 0 t)
- (or (= (point) last-sexp)
- (save-excursion
- (= (car (parse-partial-sexp (point) last-sexp 0))
- 0))))
- (backward-prefix-chars) ; last-sexp 1st on line or 1st
- (setq where (point))) ; frob on that line level 0
- (t (goto-char where)))) ; punt, should never occur
- ((and indent-mim-arglist ; maybe hack arglist
- (= (preceding-char) ?\() ; its a list
- (save-excursion ; look for magic atoms
- (setq peek 0) ; using peek as counter
- (forward-char -1) ; back over containing paren
- (while (and (< (setq peek (1+ peek)) 6)
- (condition-case nil
- (progn (forward-sexp -1) t)
- (error nil))))
- (and (< peek 6) (looking-at "DEFINE\\|DEFMAC\\|FUNCTION"))))
- ;; frobs stack under strings they belong to or under first
- ;; frob to right of strings they belong to unless luser has
- ;; frob (non-string) on preceding line with different
- ;; indentation. strings stack under start of arglist unless
- ;; mim-indent-arglist is not t, in which case they stack
- ;; under the last string, if any, else the start of the arglist.
- (let ((eol 0) last-string)
- (while (< (point) last-sexp) ; find out where the strings are
- (skip-chars-forward mim-whitespace last-sexp)
- (if (> (setq start (point)) eol)
- (progn ; simultaneously keeping track
- (setq where (min where start))
- (end-of-line) ; of indentation of first frob
- (setq eol (point)) ; on each line
- (goto-char start)))
- (if (= (following-char) ?\")
- (progn (setq last-string (point))
- (forward-sexp 1)
- (if (= last-string last-sexp)
- (setq where last-sexp)
- (skip-chars-forward mim-whitespace last-sexp)
- (setq where (point))))
- (forward-sexp 1)))
- (goto-char indent-point) ; if string is first on
- (skip-chars-forward " \t" (point-max)) ; line we are indenting, it
- (if (= (following-char) ?\") ; goes under arglist start
- (if (and last-string (not (equal indent-mim-arglist t)))
- (setq where last-string) ; or under last string.
- (setq where (1+ containing-sexp)))))
- (goto-char where)
- (setq desired-indent (current-column)))
- (t ; plain vanilla structure
- (cond ((> (save-excursion (forward-line 1) (point)) last-sexp)
- (skip-chars-forward " \t") ; last-sexp is on same line
- (setq where (point))) ; as containing-sexp
- ((progn
- (goto-char last-sexp)
- (beginning-of-line)
- (parse-partial-sexp (point) last-sexp 0 t)
- (or (= (point) last-sexp)
- (save-excursion
- (= (car (parse-partial-sexp (point) last-sexp 0))
- 0))))
- (backward-prefix-chars) ; last-sexp 1st on line or 1st
- (setq where (point))) ; frob on that line level 0
- (t (goto-char where))) ; punt, should never occur
- (setq desired-indent (current-column))))))
- ;; state is innermost containing environment unless toplevel or string.
- (if (car (nthcdr 3 state)) ; inside string
- (progn
- (if last-sexp ; string must be next
- (progn (goto-char last-sexp)
- (forward-sexp 1)
- (search-forward "\"")
- (forward-char -1))
- (goto-char indent-point) ; toplevel string, look for it
- (re-search-backward "[^\\]\"")
- (forward-char 1))
- (setq start (point)) ; opening double quote
- (skip-chars-backward " \t")
- (backward-prefix-chars)
- ;; see if the string is really a comment.
- (if (and (looking-at ";[ \t]*\"") indent-mim-comment)
- ;; it's a comment, line up under the start unless disabled.
- (goto-char (1+ start))
- ;; it's a string, dont mung the indentation.
- (goto-char indent-point)
- (skip-chars-forward " \t"))
- (setq desired-indent (current-column))))
- ;; point is sitting in usual column to indent to and if retry is nil
- ;; 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
- (not retry)
- (setq desired-indent
- (funcall indent-mim-function 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)
- "Compute indentation for Mim special forms. Returns column or nil."
- (let ((containing-sexp (car (cdr state))) (current-indent (point)))
- (save-excursion
- (goto-char (1+ containing-sexp))
- (backward-prefix-chars)
- ;; make sure we are looking at a symbol. if so, see if it is a special
- ;; symbol. if so, add the special indentation to the indentation of
- ;; the start of the special symbol, unless the property is not
- ;; an integer and not nil (in this case, call the property, it must
- ;; be a function which returns the appropriate indentation or nil and
- ;; does not change the buffer).
- (if (looking-at "\\sw\\|\\s_")
- (let* ((start (current-column))
- (function
- (intern-soft (buffer-substring (point)
- (progn (forward-sexp 1)
- (point)))))
- (method (get function 'indent-mim-function)))
- (if (or (if (equal method 'DEFINE) (setq method mim-body-indent))
- (integerp method))
- ;; only use method if its first line after containing-sexp.
- ;; we could have done this in calculate-mim-indent, but someday
- ;; someone might want to format frobs in a special form based
- ;; on position instead of indenting uniformly (like lisp if),
- ;; so preserve right for posterity. if not first line,
- ;; calculate-mim-indent already knows right indentation -
- ;; give luser chance to change indentation manually by changing
- ;; 1st line after containing-sexp.
- (if (> (progn (forward-line 1) (point)) (car (nthcdr 2 state)))
- (+ method start))
- (goto-char current-indent)
- (if (consp method)
- ;; list or pointed list of explicit indentations
- (indent-mim-offset state indent-point)
- (if (and (symbolp method) (fboundp method))
- ;; luser function - s/he better know what's going on.
- ;; should take state and indent-point as arguments - for
- ;; description of state, see parse-partial-sexp
- ;; documentation the function is guaranteed the following:
- ;; (1) state describes the closest surrounding form,
- ;; (2) indent-point is the beginning of the line being
- ;; indented, (3) point points to char in column that would
- ;; normally be used for indentation, (4) function is bound
- ;; to the special ATOM. See indent-mim-offset for example
- ;; of a special function.
- (funcall method state indent-point)))))))))
-
-(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))
- (containing-sexp (car (cdr state)))
- (last-sexp (car (nthcdr 2 state)))
- indentation)
- (goto-char (1+ containing-sexp))
- ;; determine which of the indentations to use.
- (while (and (< (point) indent-point)
- (condition-case nil
- (progn (forward-sexp 1)
- (parse-partial-sexp (point) indent-point 1 t))
- (error nil)))
- (skip-chars-backward " \t")
- (backward-prefix-chars)
- (if (= (following-char) ?\;)
- nil ; ignore comments
- (setq indentation (car indentations))
- (if (integerp (setq indentations (cdr indentations)))
- ;; if last cdr is integer, that is indentation to use for all
- ;; all the rest of the forms.
- (progn (setq mim-body-indent indentations)
- (setq indentations nil)))))
- (goto-char (1+ containing-sexp))
- (+ (current-column) (or indentation mim-body-indent))))
-
-(defun indent-mim-comment (&optional start)
- "Indent a one line (string) Mim comment following object, if any."
- (let* ((old-point (point)) (eol (progn (end-of-line) (point))) state last-sexp)
- ;; this function assumes that comment indenting is enabled. it is caller's
- ;; responsibility to check the indent-mim-comment flag before calling.
- (beginning-of-line)
- (catch 'no-comment
- (setq state (parse-partial-sexp (point) eol))
- ;; determine if there is an existing regular comment. a `regular'
- ;; comment is defined as a commented string which is the last thing
- ;; on the line and does not extend beyond the end of the line.
- (if (or (not (setq last-sexp (car (nthcdr 2 state))))
- (car (nthcdr 3 state)))
- ;; empty line or inside string (multiple line).
- (throw 'no-comment nil))
- ;; could be a comment, but make sure its not the only object.
- (beginning-of-line)
- (parse-partial-sexp (point) eol 0 t)
- (if (= (point) last-sexp)
- ;; only one object on line
- (throw 'no-comment t))
- (goto-char last-sexp)
- (skip-chars-backward " \t")
- (backward-prefix-chars)
- (if (not (looking-at ";[ \t]*\""))
- ;; aint no comment
- (throw 'no-comment nil))
- ;; there is an existing regular comment
- (delete-horizontal-space)
- ;; move it to comment-column if possible else to tab-stop
- (if (< (current-column) comment-column)
- (indent-to comment-column)
- (tab-to-tab-stop)))
- (goto-char old-point)))
-
-(defun indent-mim-line ()
- "Indent line of Mim code."
- (interactive "*")
- (let* ((position (- (point-max) (point)))
- (bol (progn (beginning-of-line) (point)))
- (indent (calculate-mim-indent)))
- (skip-chars-forward " \t")
- (if (/= (current-column) indent)
- (progn (delete-region bol (point)) (indent-to indent)))
- (if (> (- (point-max) position) (point)) (goto-char (- (point-max) position)))))
-
-(defun newline-and-mim-indent ()
- "Insert newline at point and indent."
- (interactive "*")
- ;; commented code would correct indentation of line in arglist which
- ;; starts with string, but it would indent every line twice. luser can
- ;; just say tab after typing string to get same effect.
- ;(if indent-mim-arglist (indent-mim-line))
- (newline)
- (indent-mim-line))
-
-(defun open-mim-line (&optional lines)
- "Insert newline before point and indent.
-With ARG insert that many newlines."
- (interactive "*p")
- (beginning-of-line)
- (let ((indent (calculate-mim-indent)))
- (while (> lines 0)
- (newline)
- (forward-line -1)
- (indent-to indent)
- (setq lines (1- lines)))))
-
-(defun indent-mim-object (&optional dont-indent-first-line)
- "Indent object following point and all lines contained inside it.
-With ARG, idents only contained lines (skips first line)."
- (interactive "*P")
- (let (end bol indent start)
- (save-excursion (parse-partial-sexp (point) (point-max) 0 t)
- (setq start (point))
- (forward-sexp 1)
- (setq end (- (point-max) (point))))
- (save-excursion
- (if (not dont-indent-first-line) (indent-mim-line))
- (while (progn (forward-line 1) (> (- (point-max) (point)) end))
- (setq indent (calculate-mim-indent start))
- (setq bol (point))
- (skip-chars-forward " \t")
- (if (/= indent (current-column))
- (progn (delete-region bol (point)) (indent-to indent)))
- (if indent-mim-comment (indent-mim-comment))))))
-
-(defun find-mim-definition (name)
- "Search for definition of function, macro, or gfcn.
-You need type only enough of the name to be unambiguous."
- (interactive "sName: ")
- (let (where)
- (save-excursion
- (goto-char (point-min))
- (condition-case nil
- (progn
- (re-search-forward
- (concat "^<\\(DEFINE\\|\\DEFMAC\\|FCN\\|GFCN\\)\\([ \t]*\\)"
- name))
- (setq where (point)))
- (error (error "Can't find %s" name))))
- (if where
- (progn (push-mark)
- (goto-char where)
- (beginning-of-line)
- (recenter 0)))))
-
-(defun begin-mim-comment ()
- "Move to existing comment or insert empty comment."
- (interactive "*")
- (let* ((eol (progn (end-of-line) (point)))
- (bol (progn (beginning-of-line) (point))))
- ;; check for existing comment first.
- (if (re-search-forward ";[ \t]*\"" eol t)
- ;; found it. indent if desired and go there.
- (if indent-mim-comment
- (let ((where (- (point-max) (point))))
- (indent-mim-comment)
- (goto-char (- (point-max) where))))
- ;; nothing there, make a comment.
- (let (state last-sexp)
- ;; skip past all the sexps on the line
- (goto-char bol)
- (while (and (equal (car (setq state (parse-partial-sexp (point) eol 0)))
- 0)
- (car (nthcdr 2 state)))
- (setq last-sexp (car (nthcdr 2 state))))
- (if (car (nthcdr 3 state))
- nil ; inside a string, punt
- (delete-region (point) eol) ; flush trailing whitespace
- (if (and (not last-sexp) (equal (car state) 0))
- (indent-to (calculate-mim-indent)) ; empty, indent like code
- (if (> (current-column) comment-column) ; indent to comment column
- (tab-to-tab-stop) ; unless past it, else to
- (indent-to comment-column))) ; tab-stop
- ;; if luser changes comment-{start end} to something besides semi
- ;; followed by zero or more whitespace characters followed by string
- ;; delimiters, the code above fails to find existing comments, but as
- ;; taa says, `let the losers lose'.
- (insert comment-start)
- (save-excursion (insert comment-end)))))))
-
-(defun skip-mim-whitespace (direction)
- (if (>= direction 0)
- (skip-chars-forward mim-whitespace (point-max))
- (skip-chars-backward mim-whitespace (point-min))))
-
-(defun inside-adecl-or-trailer-p (direction)
- (if (>= direction 0)
- (looking-at ":\\|!-")
- (or (= (preceding-char) ?:)
- (looking-at "!-"))))
-
-(defun sign (n)
- "Returns -1 if N < 0, else 1."
- (if (>= n 0) 1 -1))
-
-(defun abs (n)
- "Returns the absolute value of N."
- (if (>= n 0) n (- n)))
-
-(defun next-char (direction)
- "Returns preceding-char if DIRECTION < 0, otherwise following-char."
- (if (>= direction 0) (following-char) (preceding-char)))
-
-(provide 'mim-mode)
-
-;;; mim-mode.el ends here
diff --git a/lisp/=mim-syntax.el b/lisp/=mim-syntax.el
deleted file mode 100644
index beb8d330a35..00000000000
--- a/lisp/=mim-syntax.el
+++ /dev/null
@@ -1,95 +0,0 @@
-;;; mim-syntax.el --- syntax checker for Mim (MDL).
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Author: K. Shane Hartman
-;; Maintainer: FSF
-;; Keywords: languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Code:
-
-(require 'mim-mode)
-
-(defun slow-syntax-check-mim ()
- "Check Mim syntax slowly.
-Points out the context of the error, if the syntax is incorrect."
- (interactive)
- (message "checking syntax...")
- (let ((stop (point-max)) point-stack current last-bracket whoops last-point)
- (save-excursion
- (goto-char (point-min))
- (while (and (not whoops)
- (re-search-forward "\\s(\\|\\s)\\|\"\\|[\\]" stop t))
- (setq current (preceding-char))
- (cond ((= current ?\")
- (condition-case nil
- (progn (re-search-forward "[^\\]\"")
- (setq current nil))
- (error (setq whoops (point)))))
- ((= current ?\\)
- (condition-case nil (forward-char 1) (error nil)))
- ((= (char-syntax current) ?\))
- (if (or (not last-bracket)
- (not (= (logand (lsh (aref (syntax-table) last-bracket) -8)
- ?\177)
- current)))
- (setq whoops (point))
- (setq last-point (car point-stack))
- (setq last-bracket (if last-point (char-after (1- last-point))))
- (setq point-stack (cdr point-stack))))
- (t
- (if last-point (setq point-stack (cons last-point point-stack)))
- (setq last-point (point))
- (setq last-bracket current)))))
- (cond ((not (or whoops last-point))
- (message "Syntax correct"))
- (whoops
- (goto-char whoops)
- (cond ((equal current ?\")
- (error "Unterminated string"))
- ((not last-point)
- (error "Extraneous %s" (char-to-string current)))
- (t
- (error "Mismatched %s with %s"
- (save-excursion
- (setq whoops (1- (point)))
- (goto-char (1- last-point))
- (buffer-substring (point)
- (min (progn (end-of-line) (point))
- whoops)))
- (char-to-string current)))))
- (t
- (goto-char last-point)
- (error "Unmatched %s" (char-to-string last-bracket))))))
-
-(defun fast-syntax-check-mim ()
- "Checks Mim syntax quickly.
-Answers correct or incorrect, cannot point out the error context."
- (interactive)
- (save-excursion
- (goto-char (point-min))
- (let (state)
- (while (and (not (eobp))
- (equal (car (setq state (parse-partial-sexp (point) (point-max) 0)))
- 0)))
- (if (equal (car state) 0)
- (message "Syntax correct")
- (error "Syntax incorrect")))))
-
-;;; mim-syntax.el ends here
diff --git a/lisp/=netunam.el b/lisp/=netunam.el
deleted file mode 100644
index 492ac9b2c12..00000000000
--- a/lisp/=netunam.el
+++ /dev/null
@@ -1,160 +0,0 @@
-;;; netunam.el --- HP-UX RFA Commands
-
-;; Copyright (C) 1988 Free Software Foundation, Inc.
-
-;; Author: Chris Hanson <cph@zurich.ai.mit.edu>
-;; Keywords: comm
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; Use the Remote File Access (RFA) facility of HP-UX from Emacs.
-
-;;; Code:
-
-(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)))
-
-;;; netunam.el ends here
diff --git a/lisp/=nnspool.el b/lisp/=nnspool.el
deleted file mode 100644
index 72cc48bbb5a..00000000000
--- a/lisp/=nnspool.el
+++ /dev/null
@@ -1,409 +0,0 @@
-;;; nnspool.el --- spool access using NNTP for GNU Emacs
-
-;; Copyright (C) 1988, 1989, 1990, 1993 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Code:
-
-(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-newsgroups-file "/usr/lib/news/newsgroups"
- "*Local news newsgroups file.")
-
-(defvar nnspool-distributions-file "/usr/lib/news/distributions"
- "*Local news distributions file.")
-
-(defvar nnspool-history-file "/usr/lib/news/history"
- "*Local news history file.")
-
-
-
-(defconst nnspool-version "NNSPOOL 1.12"
- "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] ...)'.
-If there is no References: field, In-Reply-To: field is used instead.
-Reader macros for the vector are defined as `nntp-header-FIELD'.
-Writer macros for the vector are defined as `nntp-set-header-FIELD'.
-Newsgroup must be selected before calling this."
- (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:
- ;; If no References: field, use In-Reply-To: field instead.
- (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))
- ;; Collect valid article only.
- (and article
- message-id
- (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: Receiving headers... %d%%"
- (/ (* count 100) number)))
- )
- (and (numberp nntp-large-newsgroup)
- (> number nntp-large-newsgroup)
- (message "NNSPOOL: Receiving headers... done"))
- (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-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-string
- (format "%s has no news spool. Goodbye." host)))
- ((null host)
- (setq nntp-status-string "NNTP server is not specified."))
- (t
- (setq nntp-status-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-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)."
- (setq nntp-status-string "NNSPOOL: STAT is not implemented.")
- nil
- )
-
-(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 active newsgoups."
- (save-excursion
- (nnspool-find-file nnspool-active-file)))
-
-(defun nnspool-request-list-newsgroups ()
- "List newsgroups (defined in NNTP2)."
- (save-excursion
- (nnspool-find-file nnspool-newsgroups-file)))
-
-(defun nnspool-request-list-distributions ()
- "List distributions (defined in NNTP2)."
- (save-excursion
- (nnspool-find-file nnspool-distributions-file)))
-
-(defun nnspool-request-last ()
- "Set current article pointer to the previous article
-in the current news group."
- (setq nntp-status-string "NNSPOOL: LAST is not implemented.")
- nil
- )
-
-(defun nnspool-request-next ()
- "Advance current article pointer."
- (setq nntp-status-string "NNSPOOL: NEXT is not implemented.")
- nil
- )
-
-(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 (function 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-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 occurrences of FROM with TO.
- (while (< idx len)
- (if (= (aref string idx) from)
- (aset string idx to))
- (setq idx (1+ idx)))
- string
- ))
-
-(provide 'nnspool)
-
-;;; nnspool.el ends here
diff --git a/lisp/=nntp.el b/lisp/=nntp.el
deleted file mode 100644
index 1c3f0705f44..00000000000
--- a/lisp/=nntp.el
+++ /dev/null
@@ -1,698 +0,0 @@
-;;; nntp.el --- NNTP (RFC977) Interface for GNU Emacs
-
-;; Copyright (C) 1987, 1988, 1989, 1990, 1992, 1993 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-;;; Commentary:
-
-;; 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.
-
-;;; Code:
-
-(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
- (function
- (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-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.")
-
-
-(defvar nntp-buggy-select (memq system-type '(fujitsu-uts))
- "*Non-nil 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-debug-read 10000
- "*Display '...' every 10Kbytes of a message being received if it is non-nil.
-If it is a number, dots are displayed per the number.")
-
-
-(defconst nntp-version "NNTP 3.12"
- "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-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 (or in-reply-to) 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] ...)'.
-If there is no References: field, In-Reply-To: field is used instead.
-Reader macros for the vector are defined as `nntp-header-FIELD'.
-Writer macros for the vector are defined as `nntp-set-header-FIELD'.
-Newsgroup must be selected before calling this."
- (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: Receiving headers... %d%%"
- (/ (* 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: Receiving headers... done"))
- ;; 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\\|In-Reply-To\\):[ \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))
- ;; In-Reply-To: should be used only when
- ;; there is no References: field.
- ((and (char-equal c ?I) ;In-Reply-To:
- (null 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)"))
- ;; Collect valid article only.
- (and article
- message-id
- (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-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
- (progn (set-process-sentinel nntp-server-process
- 'nntp-default-sentinel)
- (nntp-send-command "^[25].*\r$" "MODE" "READER"))
- ;; We have to close connection here, since function
- ;; `nntp-server-opened' may return incorrect status.
- (nntp-close-server-internal)
- ))
- ((null host)
- (setq nntp-status-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-string
- ;; NNN MESSAGE
- (string-match "[0-9][0-9][0-9][ \t]+\\([^\r]*\\).*$"
- nntp-status-string))
- (substring nntp-status-string (match-beginning 1) (match-end 1))
- ;; Empty message if nothing.
- ""
- ))
-
-(defun nntp-request-article (id)
- "Select article by message ID (or number)."
- (if (numberp id)
- (setq id (number-to-string id)))
- (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 active newsgroups."
- (prog1
- (nntp-send-command "^\\.\r$" "LIST")
- (nntp-decode-text)
- ))
-
-(defun nntp-request-list-newsgroups ()
- "List newsgroups (defined in NNTP2)."
- (prog1
- (nntp-send-command "^\\.\r$" "LIST NEWSGROUPS")
- (nntp-decode-text)
- ))
-
-(defun nntp-request-list-distributions ()
- "List distributions (defined in NNTP2)."
- (prog1
- (nntp-send-command "^\\.\r$" "LIST DISTRIBUTIONS")
- (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 ".\r\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)
- (dotnum 0) ;Number of "." being displayed.
- (dotsize ;How often "." displayed.
- (if (numberp nntp-debug-read) nntp-debug-read 10000)))
- (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-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)
- (if nntp-debug-read
- (let ((newnum (/ (buffer-size) dotsize)))
- (if (not (= dotnum newnum))
- (progn
- (setq dotnum newnum)
- (message "NNTP: Reading %s"
- (make-string dotnum ?.))))))
- (nntp-accept-response)
- ;;(if nntp-debug-read (message ""))
- ))
- ;; Remove "...".
- (if (and nntp-debug-read (> dotnum 0))
- (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 separated 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 "\r\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)
- (process-send-region nntp-server-process (point-min) (point-max))
- ;; 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))))
- ))
- ))
-
-(provide 'nntp)
-
-;;; nntp.el ends here
diff --git a/lisp/=old-shell.el b/lisp/=old-shell.el
deleted file mode 100644
index 4c3944a65f4..00000000000
--- a/lisp/=old-shell.el
+++ /dev/null
@@ -1,399 +0,0 @@
-;;; old-shell.el --- run a shell in an Emacs window
-
-;; Copyright (C) 1985, 1986, 1987, 1990 Free Software Foundation, Inc.
-
-;; Keywords: processes
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; 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.
-
-;;; For documentation on the functionality provided by comint mode, and
-;;; the hooks available for customising it, see the file comint.el.
-
-;;; 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?
-
-;;; Code:
-
-(require 'comint)
-(defvar shell-popd-regexp "popd"
- "*Regexp to match subshell commands equivalent to popd.")
-
-(defvar shell-pushd-regexp "pushd"
- "*Regexp to match subshell commands equivalent to pushd.")
-
-(defvar shell-cd-regexp "cd"
- "*Regexp to match subshell commands equivalent to cd.")
-
-(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
-;;; ===========================================================================
-;;;
-
-(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-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."
- (interactive)
- (comint-mode)
- (setq major-mode 'shell-mode
- mode-name "Shell"
- comint-prompt-regexp shell-prompt-pattern
- comint-input-sentinel 'shell-directory-tracker)
- (use-local-map shell-mode-map)
- (make-local-variable 'shell-dirstack)
- (set (make-local-variable 'shell-dirtrackp) t)
- (run-hooks 'shell-mode-hook))
-
-
-(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.
-
-The buffer is put in shell-mode, giving commands for sending input
-and controlling the subjobs of the shell.
-
-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.)"
- (interactive)
- (if (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*"))
-
-
-;;; 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."
- (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."
- (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)))
-
-(provide 'shell)
-
-;;; old-shell.el ends here
diff --git a/lisp/=sc-alist.el b/lisp/=sc-alist.el
deleted file mode 100644
index 31cb0a180ba..00000000000
--- a/lisp/=sc-alist.el
+++ /dev/null
@@ -1,134 +0,0 @@
-;; -*- Mode: Emacs-Lisp -*-
-;; sc-alist.el -- Version 1.0 (used to be baw-alist.el)
-
-;; association list utilities providing insertion, deletion, sorting
-;; fetching off key-value pairs in association lists.
-
-;; ========== Disclaimer ==========
-;; This software 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.
-
-;; This software was written as part of the supercite author's
-;; official duty as an employee of the United States Government and is
-;; thus in the public domain. You are free to use that particular
-;; software as you wish, but WITHOUT ANY WARRANTY WHATSOEVER. It
-;; would be nice, though if when you use any of this code, you give
-;; due credit to the author.
-
-;; ========== Author (unless otherwise stated) ========================
-;; NAME: Barry A. Warsaw USMAIL: Century Computing, Inc.
-;; TELE: (301) 593-3330 1014 West Street
-;; INET: bwarsaw@cen.com Laurel, Md 20707
-;; UUCP: uunet!cen.com!bwarsaw
-;;
-(provide 'sc-alist)
-
-
-(defun asort (alist-symbol key)
- "Move a specified key-value pair to the head of an alist.
-The alist is referenced by ALIST-SYMBOL. Key-value pair to move to
-head is one matching KEY. Returns the sorted list and doesn't affect
-the order of any other key-value pair. Side effect sets alist to new
-sorted list."
- (set alist-symbol
- (sort (copy-alist (eval alist-symbol))
- (function (lambda (a b) (equal (car a) key))))))
-
-
-(defun aelement (key value)
- "Makes a list of a cons cell containing car of KEY and cdr of VALUE.
-The returned list is suitable as an element of an alist."
- (list (cons key value)))
-
-
-(defun aheadsym (alist)
- "Return the key symbol at the head of ALIST."
- (car (car alist)))
-
-
-(defun anot-head-p (alist key)
- "Find out if a specified key-value pair is not at the head of an alist.
-The alist to check is specified by ALIST and the key-value pair is the
-one matching the supplied KEY. Returns nil if ALIST is nil, or if
-key-value pair is at the head of the alist. Returns t if key-value
-pair is not at the head of alist. ALIST is not altered."
- (not (equal (aheadsym alist) key)))
-
-
-(defun aput (alist-symbol key &optional value)
- "Inserts a key-value pair into an alist.
-The alist is referenced by ALIST-SYMBOL. The key-value pair is made
-from KEY and optionally, VALUE. Returns the altered alist or nil if
-ALIST is nil.
-
-If the key-value pair referenced by KEY can be found in the alist, and
-VALUE is supplied non-nil, then the value of KEY will be set to VALUE.
-If VALUE is not supplied, or is nil, the key-value pair will not be
-modified, but will be moved to the head of the alist. If the key-value
-pair cannot be found in the alist, it will be inserted into the head
-of the alist (with value nil if VALUE is nil or not supplied)."
- (let ((elem (aelement key value))
- alist)
- (asort alist-symbol key)
- (setq alist (eval alist-symbol))
- (cond ((null alist) (set alist-symbol elem))
- ((anot-head-p alist key) (set alist-symbol (nconc elem alist)))
- (value (setcar alist (car elem)))
- (t alist))))
-
-
-(defun adelete (alist-symbol key)
- "Delete a key-value pair from the alist.
-Alist is referenced by ALIST-SYMBOL and the key-value pair to remove
-is pair matching KEY. Returns the altered alist."
- (asort alist-symbol key)
- (let ((alist (eval alist-symbol)))
- (cond ((null alist) nil)
- ((anot-head-p alist key) alist)
- (t (set alist-symbol (cdr alist))))))
-
-
-(defun aget (alist key &optional keynil-p)
- "Returns the value in ALIST that is associated with KEY.
-Optional KEYNIL-P describes what to do if the value associated with
-KEY is nil. If KEYNIL-P is not supplied or is nil, and the value is
-nil, then KEY is returned. If KEYNIL-P is non-nil, then nil would be
-returned.
-
-If no key-value pair matching KEY could be found in ALIST, or ALIST is
-nil then nil is returned. ALIST is not altered."
- (let ((copy (copy-alist alist)))
- (cond ((null alist) nil)
- ((progn (asort 'copy key)
- (anot-head-p copy key)) nil)
- ((cdr (car copy)))
- (keynil-p nil)
- ((car (car copy)))
- (t nil))))
-
-
-(defun amake (alist-symbol keylist &optional valuelist)
- "Make an association list.
-The association list is attached to the alist referenced by
-ALIST-SYMBOL. Each element in the KEYLIST becomes a key and is
-associated with the value in VALUELIST with the same index. If
-VALUELIST is not supplied or is nil, then each key in KEYLIST is
-associated with nil.
-
-KEYLIST and VALUELIST should have the same number of elements, but
-this isn't enforced. If VALUELIST is smaller than KEYLIST, remaining
-keys are associated with nil. If VALUELIST is larger than KEYLIST,
-extra values are ignored. Returns the created alist."
- (let ((keycar (car keylist))
- (keycdr (cdr keylist))
- (valcar (car valuelist))
- (valcdr (cdr valuelist)))
- (cond ((null keycdr)
- (aput alist-symbol keycar valcar))
- (t
- (amake alist-symbol keycdr valcdr)
- (aput alist-symbol keycar valcar))))
- (eval alist-symbol))
diff --git a/lisp/=sc-elec.el b/lisp/=sc-elec.el
deleted file mode 100644
index 67f18c66a5e..00000000000
--- a/lisp/=sc-elec.el
+++ /dev/null
@@ -1,198 +0,0 @@
-;; -*- Mode: Emacs-Lisp -*-
-;; sc-elec.el -- Version 2.3
-
-;; ========== Introduction ==========
-;; This file contains sc-electric mode for viewing reference headers.
-;; It is loaded automatically by supercite.el when needed.
-
-;; ========== Disclaimer ==========
-;; This software 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.
-
-;; Some of this software was written as part of the supercite author's
-;; official duty as an employee of the United States Government and is
-;; thus in the public domain. You are free to use that particular
-;; software as you wish, but WITHOUT ANY WARRANTY WHATSOEVER. It
-;; would be nice, though if when you use any of this code, you give
-;; due credit to the author.
-
-;; Other parts of this code were written by other people. Wherever
-;; possible, credit to that author, and the copy* notice supplied by
-;; the author are included with that code. In all cases, the spirit,
-;; if not the letter of the GNU General Public Licence applies.
-
-;; ========== Author (unless otherwise stated) ==========
-;; NAME: Barry A. Warsaw USMAIL: Century Computing, Inc.
-;; TELE: (301) 593-3330 1014 West Street
-;; UUCP: uunet!cen.com!bwarsaw Laurel, MD 20707
-;; INET: bwarsaw@cen.com
-
-;; Want to be on the Supercite mailing list?
-;;
-;; Send articles to:
-;; INET: supercite@anthem.nlm.nih.gov
-;; UUCP: uunet!anthem.nlm.nih.gov!supercite
-;;
-;; Send administrivia (additions/deletions to list, etc) to:
-;; INET: supercite-request@anthem.nlm.nih.gov
-;; UUCP: uunet!anthem.nlm.nih.gov!supercite-request
-;;
-(provide 'sc-elec)
-
-
-;; ======================================================================
-;; set up vars for major mode
-
-(defconst sc-electric-bufname "*sc-erefs*"
- "*Supercite's electric buffer name.")
-
-
-(defvar sc-electric-mode-hook nil
- "*Hook for sc-electric-mode.")
-
-
-
-;; ======================================================================
-;; sc-electric-mode
-
-(defun sc-electric-mode (&optional arg)
- "Quasi major mode for viewing supercite reference headers.
-Commands are: \\{sc-electric-mode-map}
-Sc-electric-mode is not intended to be run interactively, but rather
-accessed through supercite's electric reference feature. See
-sc-insert-reference for more details. Optional ARG is the initial
-header style to use, unless not supplied or invalid, in which case
-sc-preferred-header-style is used."
- (let ((gal sc-gal-information)
- (sc-eref-style (if arg ;; assume passed arg is okay
- arg
- (if (and (natnump sc-preferred-header-style)
- (sc-valid-index-p sc-preferred-header-style))
- sc-preferred-header-style
- 0))))
- (get-buffer-create sc-electric-bufname)
- ;; set up buffer and enter command loop
- (save-excursion
- (save-window-excursion
- (pop-to-buffer sc-electric-bufname)
- (kill-all-local-variables)
- (setq sc-gal-information gal
- buffer-read-only t
- mode-name "Supercite-Electric-References"
- major-mode 'sc-electric-mode)
- (use-local-map sc-electric-mode-map)
- (sc-eref-show sc-eref-style)
- (run-hooks 'sc-electric-mode-hook)
- (recursive-edit)
- ))
- (if sc-eref-style
- (condition-case nil
- (eval (nth sc-eref-style sc-rewrite-header-list))
- (error nil)
- ))
- ;; now restore state
- (kill-buffer sc-electric-bufname)
- ))
-
-
-
-;; ======================================================================
-;; functions for electric mode
-
-(defun sc-eref-index (index)
- "Check INDEX to be sure it is a valid index into sc-rewrite-header-list.
-If sc-electric-circular-p is non-nil, then list is considered circular
-so that movement across the ends of the list wraparound."
- (let ((last (1- (length sc-rewrite-header-list))))
- (cond ((sc-valid-index-p index) index)
- ((< index 0)
- (if sc-electric-circular-p last
- (progn (error "No preceding reference headers in list.") 0)))
- ((> index last)
- (if sc-electric-circular-p 0
- (progn (error "No following reference headers in list.") last)))
- )
- ))
-
-
-(defun sc-eref-show (index)
- "Show reference INDEX in sc-rewrite-header-list."
- (setq sc-eref-style (sc-eref-index index))
- (save-excursion
- (set-buffer sc-electric-bufname)
- (let ((ref (nth sc-eref-style sc-rewrite-header-list))
- (buffer-read-only nil))
- (erase-buffer)
- (goto-char (point-min))
- (condition-case err
- (progn
- (set-mark (point-min))
- (eval ref)
- (message "Showing reference header %d." sc-eref-style)
- (goto-char (point-max))
- )
- (void-function
- (progn (message
- "Symbol's function definition is void: %s (Header %d)"
- (symbol-name (car (cdr err)))
- sc-eref-style)
- (beep)
- ))
- ))))
-
-
-
-;; ======================================================================
-;; interactive commands
-
-(defun sc-eref-next ()
- "Display next reference in other buffer."
- (interactive)
- (sc-eref-show (1+ sc-eref-style)))
-
-
-(defun sc-eref-prev ()
- "Display previous reference in other buffer."
- (interactive)
- (sc-eref-show (1- sc-eref-style)))
-
-
-(defun sc-eref-setn ()
- "Set reference header selected as preferred."
- (interactive)
- (setq sc-preferred-header-style sc-eref-style)
- (message "Preferred reference style set to header %d." sc-eref-style))
-
-
-(defun sc-eref-goto (refnum)
- "Show reference style indexed by REFNUM.
-If REFNUM is an invalid index, don't go to that reference and return
-nil."
- (interactive "NGoto Reference: ")
- (if (sc-valid-index-p refnum)
- (sc-eref-show refnum)
- (error "Invalid reference: %d. (Range: [%d .. %d])"
- refnum 0 (1- (length sc-rewrite-header-list)))
- ))
-
-
-(defun sc-eref-jump ()
- "Set reference header to preferred header."
- (interactive)
- (sc-eref-show sc-preferred-header-style))
-
-
-(defun sc-eref-abort ()
- "Exit from electric reference mode without inserting reference."
- (interactive)
- (setq sc-eref-style nil)
- (exit-recursive-edit))
-
-
-(defun sc-eref-exit ()
- "Exit from electric reference mode and insert selected reference."
- (interactive)
- (exit-recursive-edit))
diff --git a/lisp/=sc.el b/lisp/=sc.el
deleted file mode 100644
index 03eade6cba2..00000000000
--- a/lisp/=sc.el
+++ /dev/null
@@ -1,1547 +0,0 @@
-;; -*- Mode: Emacs-Lisp -*-
-;; sc.el -- Version 2.3 (used to be supercite.el)
-
-;; ========== Introduction ==========
-;; Citation and attribution package for various GNU emacs news and
-;; electronic mail reading subsystems. This version of supercite should
-;; work with Rmail and GNUS as found in Emacs 19. It may also work with
-;; VM 4.40+ and MH-E 3.7.
-
-;; This package does not do any yanking of messages, but instead
-;; massages raw reply buffers set up by the reply/forward functions in
-;; the news/mail subsystems. Therefore, such useful operations as
-;; yanking and citing portions of the original article (instead of the
-;; whole article) are not within the ability or responsibility of
-;; supercite.
-
-;; ========== Disclaimer ==========
-;; This software is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY. No author or distributor, nor any
-;; author's past, present, or future employers 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.
-
-;; Some of this software was written as part of the supercite author's
-;; official duty as an employee of the United States Government and is
-;; thus not subject to copyright. You are free to use that particular
-;; software as you wish, but WITHOUT ANY WARRANTY WHATSOEVER. It
-;; would be nice, though if when you use any of this or other freely
-;; available code, you give due credit to the author.
-
-;; Other parts of this code were written by other people. Wherever
-;; possible, credit to that author, and the copy* notice supplied by
-;; the author are included with that code. The supercite author is no
-;; longer an employee of the U.S. Government so the GNU Public Licence
-;; should be considered in effect for all enhancements and bug fixes
-;; performed by the author.
-
-;; ========== Author (unless otherwise stated) ========================
-;; NAME: Barry A. Warsaw USMAIL: Century Computing, Inc.
-;; TELE: (301) 593-3330 1014 West Street
-;; INET: bwarsaw@cen.com Laurel, Md 20707
-;; UUCP: uunet!cen.com!bwarsaw
-;;
-;; Want to be on the Supercite mailing list?
-;;
-;; Send articles to:
-;; Internet: supercite@anthem.nlm.nih.gov
-;; UUCP: uunet!anthem.nlm.nih.gov!supercite
-;;
-;; Send administrivia (additions/deletions to list, etc) to:
-;; Internet: supercite-request@anthem.nlm.nih.gov
-;; UUCP: uunet!anthem.nlm.nih.gov!supercite-request
-
-;; ========== Credits and Thanks ==========
-;; This package was derived from the Superyank 1.11 package as posted
-;; to the net. Superyank 1.11 was inspired by code and ideas from
-;; Martin Neitzel and Ashwin Ram. Supercite version 2.3 has evolved
-;; through the comments and suggestions of the supercite mailing list
-;; which consists of many authors and users of the various mail and
-;; news reading subsystems.
-
-;; Many folks on the supercite mailing list have contributed their
-;; help in debugging, making suggestions and supplying support code or
-;; bug fixes for the previous versions of supercite. I want to thank
-;; everyone who helped, especially (in no particular order):
-;;
-;; Mark D. Baushke, Khalid Sattar, David Lawrence, Chris Davis, Kyle
-;; Jones, Kayvan Sylvan, Masanobu Umeda, Dan Jacobson, Piet van
-;; Oostrum, Hamish (H.I.) Macdonald, and Joe Wells.
-;;
-;; I don't mean to leave anyone out. All who have helped have been
-;; appreciated.
-
-;; ========== Getting Started ==========
-;; Here is a quick guide to getting started with supercite. The
-;; information contained here is mostly excerpted from the more
-;; detailed explanations given in the accompanying README file.
-;; Naturally, there are many customizations you can do to give your
-;; replies that personalized flair, but the instructions in this
-;; section should be sufficient for getting started.
-
-;; First, to connect supercite to any mail/news reading subsystem, put
-;; this in your .emacs file:
-;;
-;; (setq mail-yank-hooks 'sc-cite-original) ; for old mail agents
-;; (setq mh-yank-hooks 'sc-cite-original) ; for MH-E only
-;; (add-hook 'mail-citation-hook 'sc-cite-original) ; for newer mail agents
-;;
-;; If supercite is not pre-loaded into your emacs session, you should
-;; add the following autoload:
-;;
-;; (autoload 'sc-cite-original "sc" "Supercite 2.3" t)
-;;
-;; Finally, if you want to customize supercite, you should do it in a
-;; function called my-supercite-hook and:
-;;
-;; (setq sc-load-hook 'my-supercite-hook)
-
-(require 'assoc)
-
-
-;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-;; start of user defined variables
-;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-
-(defvar sc-nested-citation-p nil
- "*Controls whether to use nested or non-nested citation style.
-Non-nil uses nested citations, nil uses non-nested citations. Type
-\\[sc-describe] for more information.")
-
-(defvar sc-citation-leader " "
- "*String comprising first part of a citation.")
-
-(defvar sc-citation-delimiter ">"
- "*String comprising third part of a citation.
-This string is used in both nested and non-nested citations.")
-
-(defvar sc-citation-separator " "
- "*String comprising fourth and last part of a citation.")
-
-(defvar sc-default-author-name "Anonymous"
- "*String used when author's name cannot be determined.")
-
-(defvar sc-default-attribution "Anon"
- "*String used when author's attribution cannot be determined.")
-
-;; Noriya KOBAYASHI (nk@ics.osaka-u.ac.jp) writes to the supercite
-;; mailing list:
-;; I use supercite in Nemacs-3.3.2. In order to handle citation using
-;; Kanji, [...set sc-cite-regexp to...]
-;; "\\s *\\([a-zA-Z0-9]\\|\\cc\\|\\cC\\|\\ch\\|\\cH\\|\\ck\\|\\cK\\)*\\s *>+"
-;;
-(defvar sc-cite-regexp "\\s *[-a-zA-Z0-9_.]*>+\\s *"
- "*Regular expression describing how a already cited line begins.
-The regexp is only used at the beginning of a line, so it doesn't need
-to start with a '^'.")
-
-(defvar sc-titlecue-regexp "\\s +-+\\s +"
- "*Regular expression describing the separator between names and titles.
-Set to nil to treat entire field as a name.")
-
-(defvar sc-spacify-name-chars '(?_ ?* ?+ ?=)
- "*List of characters to convert to spaces if found in an author's name.")
-
-(defvar sc-nicknames-alist
- '(("Michael" "Mike")
- ("Daniel" "Dan")
- ("David" "Dave")
- ("Jonathan" "John")
- ("William" "Bill")
- ("Elizabeth" "Beth")
- ("Elizabeth" "Betsy")
- ("Kathleen" "Kathy")
- ("Smith" "Smitty"))
- "*Association list of names and their common nicknames.
-Entries are of the form (NAME NICKNAME), and NAMEs can have more than
-one nickname. Nicknames will not be automatically used as an
-attribution string, since I'm not sure this is really polite, but if a
-name is glommed from the author name and presented in the attribution
-string completion list, the matching nicknames will also be presented.
-Set this variable to nil to defeat nickname expansions. Also note that
-nicknames are not put in the supercite information alist.")
-
-(defvar sc-confirm-always-p t
- "*If non-nil, always confirm attribution string before citing text body.")
-
-(defvar sc-preferred-attribution 'firstname
- "*Specifies which part of the author's name becomes the attribution.
-The value of this variable must be one of the following quoted symbols:
-
- emailname -- email terminus name
- initials -- initials of author
- firstname -- first name of author
- lastname -- last name of author
- middlename1 -- first middle name of author
- middlename2 -- second middle name of author
- ...
-
-Middle name indexes can be any positive integer greater than 0, though
-it is unlikely that many authors will supply more than one middle
-name, if that many.")
-
-(defvar sc-use-only-preference-p nil
- "*Controls what happens when the preferred attribution cannot be found.
-If non-nil, then sc-default-attribution will be used. If nil, then
-some secondary scheme will be employed to find a suitable attribution
-string.")
-
-(defvar sc-downcase-p nil
- "*Non-nil means downcase the attribution and citation strings.")
-
-(defvar sc-rewrite-header-list
- '((sc-no-header)
- (sc-header-on-said)
- (sc-header-inarticle-writes)
- (sc-header-regarding-adds)
- (sc-header-attributed-writes)
- (sc-header-verbose)
- (sc-no-blank-line-or-header)
- )
- "*List of reference header rewrite functions.
-The variable sc-preferred-header-style controls which function in this
-list is chosen for automatic reference header insertions. Electric
-reference mode will cycle through this list of functions. For more
-information, type \\[sc-describe].")
-
-(defvar sc-preferred-header-style 1
- "*Index into sc-rewrite-header-list specifying preferred header style.
-Index zero accesses the first function in the list.")
-
-(defvar sc-electric-references-p t
- "*Use electric references if non-nil.")
-
-(defvar sc-electric-circular-p t
- "*Treat electric references as circular if non-nil.")
-
-(defvar sc-mail-fields-list
- '("date" "message-id" "subject" "newsgroups" "references"
- "from" "return-path" "path" "reply-to" "organization"
- "reply" )
- "*List of mail header whose values will be saved by supercite.
-These values can be used in header rewrite functions by accessing them
-with the sc-field function. Mail headers in this list are case
-insensitive and do not require a trailing colon.")
-
-(defvar sc-mumble-string ""
- "*Value returned by sc-field if chosen field cannot be found.")
-
-(defvar sc-nuke-mail-headers-p t
- "*Nuke or don't nuke mail headers.
-If non-nil, nuke mail headers after gleaning useful information from
-them.")
-
-(defvar sc-reference-tag-string ">>>>> "
- "*String used at the beginning of built-in reference headers.")
-
-(defvar sc-fill-paragraph-hook 'sc-fill-paragraph
- "*Hook for filling a paragraph.
-This hook gets executed when you fill a paragraph either manually or
-automagically. It expects point to be within the extent of the
-paragraph that is going to be filled. This hook allows you to use a
-different paragraph filling package than the one supplied with
-supercite.")
-
-(defvar sc-auto-fill-region-p nil
- "*If non-nil, automatically fill each paragraph after it has been cited.")
-
-(defvar sc-auto-fill-query-each-paragraph-p nil
- "*If non-nil, query before filling each paragraph.
-No querying and no filling will be performed if sc-auto-fill-region-p
-is set to nil.")
-
-(defvar sc-fixup-whitespace-p nil
- "*If non-nil, delete all leading white space before citing.")
-
-(defvar sc-all-but-cite-p nil
- "*If non-nil, sc-cite-original does everything but cite the text.
-This is useful for manually citing large messages, or portions of
-large messages. When non-nil, sc-cite-original will still set up all
-necessary variables and databases, but will skip the citing routine
-which modify the reply buffer's text.")
-
-(defvar sc-load-hook nil
- "*User definable hook.
-Runs after supercite is loaded. Set your customizations here.")
-
-(defvar sc-pre-hook nil
- "*User definable hook.
-Runs before sc-cite-original executes.")
-
-(defvar sc-post-hook nil
- "*User definable hook.
-Runs after sc-cite-original executes.")
-
-(defvar sc-header-nuke-list
- '("via" "origin" "status" "received" "remailed" "cc" "sender" "replied"
- "organization" "keywords" "distribution" "xref" "references" "expires"
- "approved" "summary" "precedence" "subject" "newsgroup[s]?"
- "\\(followup\\|apparently\\|errors\\|\\(\\(in-\\)?reply\\)?-\\)?to"
- "x-[a-z0-9-]+" "[a-z-]*message-id" "\\(summary-\\)?line[s]"
- "\\(\\(return\\|reply\\)-\\)?path" "\\(posted-\\)?date"
- "\\(mail-\\)?from")
- "*List of mail headers to remove from body of reply.")
-
-
-
-;; ======================================================================
-;; keymaps
-
-(defvar sc-default-keymap
- '(lambda ()
- (local-set-key "\C-c\C-r" 'sc-insert-reference)
- (local-set-key "\C-c\C-t" 'sc-cite)
- (local-set-key "\C-c\C-a" 'sc-recite)
- (local-set-key "\C-c\C-u" 'sc-uncite)
- (local-set-key "\C-c\C-i" 'sc-insert-citation)
- (local-set-key "\C-c\C-o" 'sc-open-line)
- (local-set-key "\C-c\C-q" 'sc-fill-paragraph-manually)
- (local-set-key "\C-cq" 'sc-fill-paragraph-manually)
- (local-set-key "\C-c\C-m" 'sc-modify-information)
- (local-set-key "\C-cf" 'sc-view-field)
- (local-set-key "\C-cg" 'sc-glom-headers)
- (local-set-key "\C-c\C-v" 'sc-version)
- (local-set-key "\C-c?" 'sc-describe)
- )
- "*Default keymap if major-mode can't be found in `sc-local-keymaps'.")
-
-(defvar sc-local-keymaps
- '((mail-mode
- (lambda ()
- (local-set-key "\C-c\C-r" 'sc-insert-reference)
- (local-set-key "\C-c\C-t" 'sc-cite)
- (local-set-key "\C-c\C-a" 'sc-recite)
- (local-set-key "\C-c\C-u" 'sc-uncite)
- (local-set-key "\C-c\C-i" 'sc-insert-citation)
- (local-set-key "\C-c\C-o" 'sc-open-line)
- (local-set-key "\C-c\C-q" 'sc-fill-paragraph-manually)
- (local-set-key "\C-cq" 'sc-fill-paragraph-manually)
- (local-set-key "\C-c\C-m" 'sc-modify-information)
- (local-set-key "\C-cf" 'sc-view-field)
- (local-set-key "\C-cg" 'sc-glom-headers)
- (local-set-key "\C-c\C-v" 'sc-version)
- (local-set-key "\C-c?" 'sc-describe)
- ))
- (mh-letter-mode
- (lambda ()
- (local-set-key "\C-c\C-r" 'sc-insert-reference)
- (local-set-key "\C-c\C-t" 'sc-cite)
- (local-set-key "\C-c\C-a" 'sc-recite)
- (local-set-key "\C-c\C-u" 'sc-uncite)
- (local-set-key "\C-ci" 'sc-insert-citation)
- (local-set-key "\C-c\C-o" 'sc-open-line)
- (local-set-key "\C-cq" 'sc-fill-paragraph-manually)
- (local-set-key "\C-c\C-m" 'sc-modify-information)
- (local-set-key "\C-cf" 'sc-view-field)
- (local-set-key "\C-cg" 'sc-glom-headers)
- (local-set-key "\C-c\C-v" 'sc-version)
- (local-set-key "\C-c?" 'sc-describe)
- ))
- (news-reply-mode mail-mode)
- (vm-mail-mode mail-mode)
- (e-reply-mode mail-mode)
- (n-reply-mode mail-mode)
- )
- "*List of keymaps to use with the associated major-mode.")
-
-(defvar sc-electric-mode-map nil
- "*Keymap for sc-electric-mode.")
-
-(if sc-electric-mode-map
- nil
- (setq sc-electric-mode-map (make-sparse-keymap))
- (define-key sc-electric-mode-map "p" 'sc-eref-prev)
- (define-key sc-electric-mode-map "n" 'sc-eref-next)
- (define-key sc-electric-mode-map "s" 'sc-eref-setn)
- (define-key sc-electric-mode-map "j" 'sc-eref-jump)
- (define-key sc-electric-mode-map "x" 'sc-eref-abort)
- (define-key sc-electric-mode-map "\r" 'sc-eref-exit)
- (define-key sc-electric-mode-map "\n" 'sc-eref-exit)
- (define-key sc-electric-mode-map "q" 'sc-eref-exit)
- (define-key sc-electric-mode-map "g" 'sc-eref-goto)
- )
-
-;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-;; end of user defined variables
-;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-
-;; ======================================================================
-;; global variables, not user accessible
-
-(defconst sc-version-number "2.3"
- "Supercite's version number.")
-
-;; when rnewspost.el patch is installed (or function is overloaded)
-;; this should be nil since supercite now does this itself.
-(setq news-reply-header-hook nil)
-
-;; autoload for sc-electric-mode
-(autoload 'sc-electric-mode "sc-elec"
- "Quasi-major mode for viewing supercite reference headers." nil)
-
-;; global alists (gals), misc variables. make new bytecompiler happy
-(defvar sc-gal-information nil
- "Internal global alist variable containing information.")
-(defvar sc-gal-attributions nil
- "Internal global alist variable containing attributions.")
-(defvar sc-fill-arg nil
- "Internal fill argument holder.")
-(defvar sc-cite-context nil
- "Internal citation context holder.")
-(defvar sc-force-confirmation-p nil
- "Internal variable.")
-
-(make-variable-buffer-local 'sc-gal-attributions)
-(make-variable-buffer-local 'sc-gal-information)
-(make-variable-buffer-local 'sc-leached-keymap)
-(make-variable-buffer-local 'sc-fill-arg)
-(make-variable-buffer-local 'sc-cite-context)
-
-(setq-default sc-gal-attributions nil)
-(setq-default sc-gal-information nil)
-(setq-default sc-leached-keymap (current-local-map))
-(setq-default sc-fill-arg nil)
-(setq-default sc-cite-context nil)
-
-
-
-;; ======================================================================
-;; miscellaneous support functions
-
-(defun sc-mark ()
- "Mark compatibility between emacs v18 and v19."
- (let ((zmacs-regions nil))
- (marker-position (mark-marker))))
-
-(defun sc-update-gal (attribution)
- "Update the information alist.
-Add ATTRIBUTION and compose the nested and non-nested citation
-strings."
- (let ((attrib (if sc-downcase-p (downcase attribution) attribution)))
- (aput 'sc-gal-information "sc-attribution" attrib)
- (aput 'sc-gal-information "sc-nested-citation"
- (concat attrib sc-citation-delimiter))
- (aput 'sc-gal-information "sc-citation"
- (concat sc-citation-leader
- attrib
- sc-citation-delimiter
- sc-citation-separator))))
-
-(defun sc-valid-index-p (index)
- "Returns t if INDEX is a valid index into sc-rewrite-header-list."
- (let ((last (1- (length sc-rewrite-header-list))))
- (and (natnump index) ;; a number, and greater than or equal to zero
- (<= index last) ;; less than or equal to the last index
- )))
-
-(defun sc-string-car (namestring)
- "Return the string-equivalent \"car\" of NAMESTRING.
-
- example: (sc-string-car \"John Xavier Doe\")
- => \"John\""
- (substring namestring
- (progn (string-match "\\s *" namestring) (match-end 0))
- (progn (string-match "\\s *\\S +" namestring) (match-end 0))))
-
-(defun sc-string-cdr (namestring)
- "Return the string-equivalent \"cdr\" of NAMESTRING.
-
- example: (sc-string-cdr \"John Xavier Doe\")
- => \"Xavier Doe\""
- (substring namestring
- (progn (string-match "\\s *\\S +\\s *" namestring)
- (match-end 0))))
-
-(defun sc-linepos (&optional position col-p)
- "Return the character position at various line positions.
-Optional POSITION can be one of the following symbols:
- bol == beginning of line
- boi == beginning of indentation
- eol == end of line [default]
-
-Optional COL-P non-nil returns current-column instead of character position."
- (let ((tpnt (point))
- rval)
- (cond
- ((eq position 'bol) (beginning-of-line))
- ((eq position 'boi) (back-to-indentation))
- (t (end-of-line)))
- (setq rval (if col-p (current-column) (point)))
- (goto-char tpnt)
- rval))
-
-
-;; ======================================================================
-;; this section snarfs mail fields and places them in the info alist
-
-(defun sc-build-header-zap-regexp ()
- "Return a regexp for sc-mail-yank-clear-headers."
- (let ((headers sc-header-nuke-list)
- (regexp nil))
- (while headers
- (setq regexp (concat regexp
- "^" (car headers) ":"
- (if (cdr headers) "\\|" nil)))
- (setq headers (cdr headers)))
- regexp))
-
-(defun sc-mail-yank-clear-headers (start end)
- "Nuke mail headers between START and END."
- (if (and sc-nuke-mail-headers-p sc-header-nuke-list)
- (let ((regexp (sc-build-header-zap-regexp)))
- (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 regexp nil t))
- (beginning-of-line)
- (delete-region (point)
- (progn (re-search-forward "\n[^ \t]")
- (forward-char -1)
- (point)))
- )))
- ))))
-
-(defun sc-mail-fetch-field (field)
- "Return the value of the header field FIELD.
-The buffer is expected to be narrowed to just the headers of the
-message."
- (save-excursion
- (goto-char (point-min))
- (let ((case-fold-search t)
- (name (concat "^" (regexp-quote field) "[ \t]*:[ \t]*")))
- (goto-char (point-min))
- (if (re-search-forward name nil t)
- (let ((opoint (point)))
- (while (progn (forward-line 1)
- (looking-at "[ \t]")))
- (buffer-substring opoint (1- (point))))))))
-
-(defun sc-fetch-fields (start end)
- "Fetch the mail fields in the region from START to END.
-These fields can be accessed in header rewrite functions with sc-field."
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (goto-char start)
- (let ((fields sc-mail-fields-list))
- (while fields
- (let ((value (sc-mail-fetch-field (car fields)))
- (next (cdr fields)))
- (and value
- (aput 'sc-gal-information (car fields) value))
- (setq fields next)))
- (if (sc-mail-fetch-field "from")
- (aput 'sc-gal-information "from" (sc-mail-fetch-field "from")))))))
-
-(defun sc-field (field)
- "Return the alist information associated with the FIELD.
-If FIELD is not a valid key, return sc-mumble-string."
- (or (aget sc-gal-information field) sc-mumble-string))
-
-
-;; ======================================================================
-;; built-in reference header rewrite functions
-
-(defun sc-no-header ()
- "Does nothing. Use this instead of nil to get a blank header."
- ())
-
-(defun sc-no-blank-line-or-header()
- "Similar to sc-no-header except it removes the preceding blank line."
- (if (not (bobp))
- (if (and (eolp)
- (progn (forward-line -1)
- (or (looking-at mail-header-separator)
- (and (eq major-mode 'mh-letter-mode)
- (mh-in-header-p)))))
- (progn (forward-line)
- (let ((kill-lines-magic t)) (kill-line))))))
-
-(defun sc-header-on-said ()
- "\"On <date>, <from> said:\", unless 1. the \"from\" field cannot be
-found, in which case nothing is inserted; or 2. the \"date\" field is
-missing in which case only the from part is printed."
- (let* ((sc-mumble-string "")
- (whofrom (sc-field "from"))
- (when (sc-field "date")))
- (if (not (string= whofrom ""))
- (insert sc-reference-tag-string
- (if (not (string= when ""))
- (concat "On " when ", ") "")
- whofrom " said:\n"))))
-
-(defun sc-header-inarticle-writes ()
- "\"In article <message-id>, <from> writes:\"
-Treats \"message-id\" and \"from\" fields similar to sc-header-on-said."
- (let* ((sc-mumble-string "")
- (whofrom (sc-field "from"))
- (msgid (sc-field "message-id")))
- (if (not (string= whofrom ""))
- (insert sc-reference-tag-string
- (if (not (string= msgid ""))
- (concat "In article " msgid ", ") "")
- whofrom " writes:\n"))))
-
-(defun sc-header-regarding-adds ()
- "\"Regarding <subject>; <from> adds:\"
-Treats \"subject\" and \"from\" fields similar to sc-header-on-said."
- (let* ((sc-mumble-string "")
- (whofrom (sc-field "from"))
- (subj (sc-field "subject")))
- (if (not (string= whofrom ""))
- (insert sc-reference-tag-string
- (if (not (string= subj ""))
- (concat "Regarding " subj "; ") "")
- whofrom " adds:\n"))))
-
-(defun sc-header-attributed-writes ()
- "\"<sc-attribution>\" == <sc-author> <address> writes:
-Treats these fields in a similar manner to sc-header-on-said."
- (let* ((sc-mumble-string "")
- (whofrom (sc-field "from"))
- (reply (sc-field "sc-reply-address"))
- (from (sc-field "sc-from-address"))
- (attr (sc-field "sc-attribution"))
- (auth (sc-field "sc-author")))
- (if (not (string= whofrom ""))
- (insert sc-reference-tag-string
- (if (not (string= attr ""))
- (concat "\"" attr "\" == " ) "")
- (if (not (string= auth ""))
- (concat auth " ") "")
- (if (not (string= reply ""))
- (concat "<" reply ">")
- (if (not (string= from ""))
- (concat "<" from ">") ""))
- " writes:\n"))))
-
-(defun sc-header-verbose ()
- "Very verbose, some say gross."
- (let* ((sc-mumble-string "")
- (whofrom (sc-field "from"))
- (reply (sc-field "sc-reply-address"))
- (from (sc-field "sc-from-address"))
- (author (sc-field "sc-author"))
- (date (sc-field "date"))
- (org (sc-field "organization"))
- (msgid (sc-field "message-id"))
- (ngrps (sc-field "newsgroups"))
- (subj (sc-field "subject"))
- (refs (sc-field "references"))
- (cite (sc-field "sc-citation"))
- (nl sc-reference-tag-string))
- (if (not (string= whofrom ""))
- (insert (if (not (string= date ""))
- (concat nl "On " date ",\n") "")
- (concat nl (if (not (string= author ""))
- author
- whofrom) "\n")
- (if (not (string= org ""))
- (concat nl "from the organization of " org "\n") "")
- (if (not (string= reply ""))
- (concat nl "who can be reached at: " reply "\n")
- (if (not (string= from ""))
- (concat nl "who can be reached at: " from "\n") ""))
- (if (not (string= cite ""))
- (concat nl "(whose comments are cited below with \""
- cite "\"),\n") "")
- (if (not (string= msgid ""))
- (concat nl "had this to say in article " msgid "\n") "")
- (if (not (string= ngrps ""))
- (concat nl "in newsgroups " ngrps "\n") "")
- (if (not (string= subj ""))
- (concat nl "concerning the subject of " subj "\n") "")
- (if (not (string= refs ""))
- (concat nl "(see " refs " for more details)\n") "")
- ))))
-
-
-;; ======================================================================
-;; this section queries the user for necessary information
-
-(defun sc-query (&optional default)
- "Query for an attribution string with the optional DEFAULT choice.
-Returns the string entered by the user, if non-empty and non-nil, or
-DEFAULT otherwise. If DEFAULT is not supplied, sc-default-attribution
-is used."
- (if (not default) (setq default sc-default-attribution))
- (let* ((prompt (concat "Enter attribution string: (default " default ") "))
- (query (read-string prompt)))
- (if (or (null query)
- (string= query ""))
- default
- query)))
-
-(defun sc-confirm ()
- "Confirm the preferred attribution with the user."
- (if (or sc-confirm-always-p
- sc-force-confirmation-p)
- (aput 'sc-gal-attributions
- (let* ((default (aheadsym sc-gal-attributions))
- chosen
- (prompt (concat "Complete "
- (cond
- ((eq sc-cite-context 'citing) "cite")
- ((eq sc-cite-context 'reciting) "recite")
- (t ""))
- " attribution string: (default "
- default ") "))
- (minibuffer-local-completion-map
- (copy-keymap minibuffer-local-completion-map)))
- (define-key minibuffer-local-completion-map "\C-g"
- '(lambda () (interactive) (beep) (throw 'select-abort nil)))
- (setq chosen (completing-read prompt sc-gal-attributions))
- (if (or (not chosen)
- (string= chosen ""))
- default
- chosen)))))
-
-
-;; ======================================================================
-;; this section contains primitive functions used in the email address
-;; parsing schemes. they extract name fields from various parts of
-;; the "from:" field.
-
-(defun sc-style1-addresses (from-string &optional delim)
- "Extract the author's email terminus from email address FROM-STRING.
-Match addresses of the style \"name%[stuff].\" when called with DELIM
-of \"%\" and addresses of the style \"[stuff]name@[stuff]\" when
-called with DELIM \"@\". If DELIM is nil or not provided, matches
-addresses of the style \"name\"."
- (and (string-match (concat "[a-zA-Z0-9_-]+" delim) from-string 0)
- (substring from-string
- (match-beginning 0)
- (- (match-end 0) (if (null delim) 0 1)))))
-
-(defun sc-style2-addresses (from-string)
- "Extract the author's email terminus from email address FROM-STRING.
-Match addresses of the style \"[stuff]![stuff]...!name[stuff].\""
- (let ((eos (length from-string))
- (mstart (string-match "![a-zA-Z0-9_-]+\\([^!a-zA-Z0-9_-]\\|$\\)"
- from-string 0))
- (mend (match-end 0)))
- (and mstart
- (substring from-string (1+ mstart) (- mend (if (= mend eos) 0 1)))
- )))
-
-(defun sc-get-address (from-string author)
- "Get the full email address path from FROM-STRING.
-AUTHOR is the author's name (which is removed from the address)."
- (let ((eos (length from-string)))
- (if (string-match (concat "\\(^\\|^\"\\)" author
- "\\(\\s +\\|\"\\s +\\)") from-string 0)
- (let ((addr (substring from-string (match-end 0) eos)))
- (if (and (= (aref addr 0) ?<)
- (= (aref addr (1- (length addr))) ?>))
- (substring addr 1 (1- (length addr)))
- addr))
- (if (string-match "[a-zA-Z0-9!@%._-]+" from-string 0)
- (substring from-string (match-beginning 0) (match-end 0))
- "")
- )))
-
-(defun sc-get-emailname (from-string)
- "Get the email terminus name from FROM-STRING."
- (cond
- ((sc-style1-addresses from-string "%"))
- ((sc-style1-addresses from-string "@"))
- ((sc-style2-addresses from-string))
- ((sc-style1-addresses from-string nil))
- (t (substring from-string 0 10))))
-
-
-;; ======================================================================
-;; this section contains functions that will extract a list of names
-;; from the name field string.
-
-(defun sc-spacify-name-chars (name)
- (let ((len (length name))
- (s 0))
- (while (< s len)
- (if (memq (aref name s) sc-spacify-name-chars)
- (aset name s 32))
- (setq s (1+ s)))
- name))
-
-(defun sc-name-substring (string start end extend)
- "Extract the specified substring of STRING from START to END.
-EXTEND is the number of characters on each side to extend the
-substring."
- (and start
- (let ((sos (+ start extend))
- (eos (- end extend)))
- (substring string sos
- (or (string-match sc-titlecue-regexp string sos) eos)
- ))))
-
-(defun sc-extract-namestring (from-string)
- "Extract the name string from FROM-STRING.
-This should be the author's full name minus an optional title."
- (let ((pstart (string-match "(.*)" from-string 0))
- (pend (match-end 0))
- (qstart (string-match "\".*\"" from-string 0))
- (qend (match-end 0))
- (bstart (string-match "\\([.a-zA-Z0-9_-]+\\s *\\)+" from-string 0))
- (bend (match-end 0)))
- (sc-spacify-name-chars
- (cond
- ((sc-name-substring from-string pstart pend 1))
- ((sc-name-substring from-string qstart qend 1))
- ((sc-name-substring from-string bstart bend 0))
- ))))
-
-(defun sc-chop-namestring (namestring)
- "Convert NAMESTRING to a list of names.
-
- example: (sc-namestring-to-list \"John Xavier Doe\")
- => (\"John\" \"Xavier\" \"Doe\")"
- (if (not (string= namestring ""))
- (append (list (sc-string-car namestring))
- (sc-chop-namestring (sc-string-cdr namestring)))))
-
-(defun sc-strip-initials (namelist)
- "Extract the author's initials from the NAMELIST."
- (if (not namelist)
- nil
- (concat (if (string= (car namelist) "")
- ""
- (substring (car namelist) 0 1))
- (sc-strip-initials (cdr namelist)))))
-
-
-;; ======================================================================
-;; this section handles selection of the attribution and citation strings
-
-(defun sc-populate-alists (from-string)
- "Put important and useful information in the alists using FROM-STRING.
-Return the list of name symbols."
- (let* ((namelist (sc-chop-namestring (sc-extract-namestring from-string)))
- (revnames (reverse (cdr namelist)))
- (midnames (reverse (cdr revnames)))
- (firstname (car namelist))
- (midnames (reverse (cdr revnames)))
- (lastname (car revnames))
- (initials (sc-strip-initials namelist))
- (emailname (sc-get-emailname from-string))
- (n 1)
- (symlist (list 'emailname 'initials 'firstname 'lastname)))
-
- ;; put basic information
- (aput 'sc-gal-attributions 'firstname firstname)
- (aput 'sc-gal-attributions 'lastname lastname)
- (aput 'sc-gal-attributions 'emailname emailname)
- (aput 'sc-gal-attributions 'initials initials)
-
- (aput 'sc-gal-information "sc-firstname" firstname)
- (aput 'sc-gal-information "sc-lastname" lastname)
- (aput 'sc-gal-information "sc-emailname" emailname)
- (aput 'sc-gal-information "sc-initials" initials)
-
- ;; put middle names and build sc-author entry
- (let ((author (concat firstname " ")))
- (while midnames
- (let ((name (car midnames))
- (next (cdr midnames))
- (symbol (intern (format "middlename%d" n)))
- (string (format "sc-middlename-%d" n)))
- ;; first put new middlename
- (aput 'sc-gal-attributions symbol name)
- (aput 'sc-gal-information string name)
- (setq n (1+ n))
- (nconc symlist (list symbol))
-
- ;; now build author name
- (setq author (concat author name " "))
-
- ;; incr loop
- (setq midnames next)
- ))
- (setq author (concat author lastname))
-
- ;; put author name and email address
- (aput 'sc-gal-information "sc-author" author)
- (aput 'sc-gal-information "sc-from-address"
- (sc-get-address from-string author))
- (aput 'sc-gal-information "sc-reply-address"
- (sc-get-address (sc-field "reply-to") author))
- )
- ;; return value
- symlist))
-
-(defun sc-sort-attribution-alist ()
- "Put preferred attribution at head of attributions alist."
- (asort 'sc-gal-attributions sc-preferred-attribution)
-
- ;; use backup scheme if preference is not legal
- (if (or (null sc-preferred-attribution)
- (anot-head-p sc-gal-attributions sc-preferred-attribution)
- (let ((prefval (aget sc-gal-attributions
- sc-preferred-attribution)))
- (or (null prefval)
- (string= prefval ""))))
- ;; no legal attribution
- (if sc-use-only-preference-p
- (aput 'sc-gal-attributions 'sc-user-query
- (sc-query sc-default-attribution))
- ;; else use secondary scheme
- (asort 'sc-gal-attributions 'firstname))))
-
-(defun sc-build-attribution-alist (from-string)
- "Extract attributions from FROM-STRING, applying preferences."
- (let ((symlist (sc-populate-alists from-string))
- (headval (progn (sc-sort-attribution-alist)
- (aget sc-gal-attributions
- (aheadsym sc-gal-attributions) t))))
-
- ;; for each element in the symlist, remove the corresponding
- ;; key-value pair in the alist, then insert just the value.
- (while symlist
- (let ((value (aget sc-gal-attributions (car symlist) t))
- (next (cdr symlist)))
- (if (not (or (null value)
- (string= value "")))
- (aput 'sc-gal-attributions value))
- (adelete 'sc-gal-attributions (car symlist))
- (setq symlist next)))
-
- ;; add nicknames to the completion list
- (let ((gal sc-gal-attributions))
- (while gal
- (let ((nns sc-nicknames-alist)
- (galname (car (car gal))))
- (while nns
- (if (string= galname (car (car nns)))
- (aput 'sc-gal-attributions (car (cdr (car nns)))))
- (setq nns (cdr nns)))
- (setq gal (cdr gal)))))
-
- ;; now reinsert the head (preferred) attribution unless it is nil,
- ;; this effectively just moves the head value to the front of the
- ;; list.
- (if headval
- (aput 'sc-gal-attributions headval))
-
- ;; check to be sure alist is not nil
- (if (null sc-gal-attributions)
- (aput 'sc-gal-attributions sc-default-attribution))))
-
-(defun sc-select ()
- "Select an attribution and create a citation string."
- (cond
- (sc-nested-citation-p
- (sc-update-gal ""))
- ((null (aget sc-gal-information "from" t))
- (aput 'sc-gal-information "sc-author" sc-default-author-name)
- (sc-update-gal (sc-query sc-default-attribution)))
- ((null sc-gal-attributions)
- (sc-build-attribution-alist (aget sc-gal-information "from" t))
- (sc-confirm)
- (sc-update-gal (aheadsym sc-gal-attributions)))
- (t
- (sc-confirm)
- (sc-update-gal (aheadsym sc-gal-attributions))))
- t)
-
-
-;; ======================================================================
-;; region citing and unciting
-
-(defun sc-cite-region (start end)
- "Cite a region delineated by START and END."
- (save-excursion
- ;; set real end-of-region
- (goto-char end)
- (forward-line 1)
- (set-mark (point))
- ;; goto real beginning-of-region
- (goto-char start)
- (beginning-of-line)
- (let ((fstart (point))
- (fend (point)))
- (while (< (point) (sc-mark))
- ;; remove leading whitespace if desired
- (and sc-fixup-whitespace-p
- (fixup-whitespace))
- ;; if end of line then perhaps autofill
- (cond ((eolp)
- (or (= fstart fend)
- (not sc-auto-fill-region-p)
- (and sc-auto-fill-query-each-paragraph-p
- (not (y-or-n-p "Fill this paragraph? ")))
- (save-excursion (set-mark fend)
- (goto-char (/ (+ fstart fend 1) 2))
- (run-hooks 'sc-fill-paragraph-hook)))
- (setq fstart (point)
- fend (point)))
- ;; not end of line so perhaps cite it
- ((not (looking-at sc-cite-regexp))
- (insert (aget sc-gal-information "sc-citation")))
- (sc-nested-citation-p
- (insert (aget sc-gal-information "sc-nested-citation"))))
- (setq fend (point))
- (forward-line 1))
- (and sc-auto-fill-query-each-paragraph-p
- (message " "))
- )))
-
-(defun sc-uncite-region (start end cite-regexp)
- "Uncite a previously cited region delineated by START and END.
-CITE-REGEXP describes how a cited line of texts starts. Unciting also
-auto-fills paragraph if sc-auto-fill-region-p is non-nil."
- (save-excursion
- (set-mark end)
- (goto-char start)
- (beginning-of-line)
- (let ((fstart (point))
- (fend (point)))
- (while (< (point) (sc-mark))
- ;; if end of line, then perhaps autofill
- (cond ((eolp)
- (or (= fstart fend)
- (not sc-auto-fill-region-p)
- (and sc-auto-fill-query-each-paragraph-p
- (not (y-or-n-p "Fill this paragraph? ")))
- (save-excursion (set-mark fend)
- (goto-char (/ (+ fstart fend 1) 2))
- (run-hooks 'sc-fill-paragraph-hook)))
- (setq fstart (point)
- fend (point)))
- ;; not end of line so perhaps uncite it
- ((looking-at cite-regexp)
- (save-excursion
- (save-restriction
- (narrow-to-region (sc-linepos 'bol) (sc-linepos))
- (beginning-of-line)
- (delete-region (point-min)
- (progn (re-search-forward cite-regexp
- (point-max)
- t)
- (match-end 0)))))))
- (setq fend (point))
- (forward-line 1)))))
-
-
-;; ======================================================================
-;; this section contains paragraph filling support
-
-(defun sc-guess-fill-prefix (&optional literalp)
- "Guess the fill prefix used on the current line.
-Use various heuristics to find the fill prefix. Search begins on first
-non-blank line after point.
-
- 1) If fill-prefix is already bound to the empty string, return
- nil.
-
- 2) If fill-prefix is already bound, but not to the empty
- string, return the value of fill-prefix.
-
- 3) If the current line starts with the last chosen citation
- string, then that string is returned.
-
- 4) If the current line starts with a string matching the regular
- expression sc-cite-regexp, return the match. Note that if
- optional LITERALP is provided and non-nil, then the *string*
- that matches the regexp is return. Otherwise, if LITERALP is
- not provided or is nil, the *regexp* sc-cite-regexp is
- returned.
-
- 5) If the current line starts with any number of characters,
- followed by the sc-citation-delimiter and then white space,
- that match is returned. See comment #4 above for handling of
- LITERALP.
-
- 6) Nil is returned."
- (save-excursion
- ;; scan for first non-blank line in the region
- (beginning-of-line)
- (skip-chars-forward "\n\t ")
- (beginning-of-line)
- (let ((citation (aget sc-gal-information "sc-citation"))
- (generic-citation
- (concat "\\s *[^ \t\n" sc-citation-delimiter "]+>\\s +")))
- (cond
- ((string= fill-prefix "") nil) ;; heuristic #1
- (fill-prefix) ;; heuristic #2
- ((looking-at (regexp-quote citation)) citation) ;; heuristic #3
- ((looking-at sc-cite-regexp) ;; heuristic #4
- (if literalp
- (buffer-substring
- (point)
- (progn (re-search-forward (concat sc-cite-regexp "\\s *")
- (point-max) nil)
- (point)))
- sc-cite-regexp))
- ((looking-at generic-citation) ;; heuristic #5
- (if literalp
- (buffer-substring
- (point)
- (progn (re-search-forward generic-citation) (point)))
- generic-citation))
- (t nil))))) ;; heuristic #6
-
-(defun sc-consistent-cite-p (prefix)
- "Check current paragraph for consistent citation.
-Scans to paragraph delineated by (forward|backward)-paragraph to see
-if all lines start with PREFIX. Returns t if entire paragraph is
-consistently cited, nil otherwise."
- (save-excursion
- (let ((end (progn (forward-paragraph)
- (beginning-of-line)
- (or (not (eolp))
- (forward-char -1))
- (point)))
- (start (progn (backward-paragraph)
- (beginning-of-line)
- (or (not (eolp))
- (forward-char 1))
- (point)))
- (badline t))
- (goto-char start)
- (beginning-of-line)
- (while (and (< (point) end)
- badline)
- (setq badline (looking-at prefix))
- (forward-line 1))
- badline)))
-
-(defun sc-fill-start (fill-prefix)
- "Find buffer position of start of region which begins with FILL-PREFIX.
-Restrict scan to current paragraph."
- (save-excursion
- (let ((badline nil)
- (top (save-excursion
- (backward-paragraph)
- (beginning-of-line)
- (or (not (eolp))
- (forward-char 1))
- (point))))
- (while (and (not badline)
- (> (point) top))
- (forward-line -1)
- (setq badline (not (looking-at fill-prefix)))))
- (forward-line 1)
- (point)))
-
-(defun sc-fill-end (fill-prefix)
- "Find the buffer position of end of region which begins with FILL-PREFIX.
-Restrict scan to current paragraph."
- (save-excursion
- (let ((badline nil)
- (bot (save-excursion
- (forward-paragraph)
- (beginning-of-line)
- (or (not (eolp))
- (forward-char -1))
- (point))))
- (while (and (not badline)
- (< (point) bot))
- (beginning-of-line)
- (setq badline (not (looking-at fill-prefix)))
- (forward-line 1)))
- (forward-line -1)
- (point)))
-
-(defun sc-fill-paragraph ()
- "Supercite's paragraph fill function.
-Fill the paragraph containing or following point. Use
-sc-guess-fill-prefix to find the fill-prefix for the paragraph.
-
-If the paragraph is inconsistently cited (mixed fill-prefix), then the
-user is queried to restrict the the fill to only those lines around
-point which begin with the fill prefix.
-
-The variable sc-fill-arg is passed to fill-paragraph and
-fill-region-as-paragraph which controls justification of the
-paragraph. sc-fill-arg is set by sc-fill-paragraph-manually."
- (save-excursion
- (let ((pnt (point))
- (fill-prefix (sc-guess-fill-prefix t)))
- (cond
- ((not fill-prefix)
- (fill-paragraph sc-fill-arg))
- ((sc-consistent-cite-p fill-prefix)
- (fill-paragraph sc-fill-arg))
- ((y-or-n-p "Inconsistent citation found. Restrict? ")
- (message "")
- (fill-region-as-paragraph (progn (goto-char pnt)
- (sc-fill-start fill-prefix))
- (progn (goto-char pnt)
- (sc-fill-end fill-prefix))
- sc-fill-arg))
- (t
- (message "")
- (progn
- (setq fill-prefix (aget sc-gal-information "sc-citation"))
- (fill-paragraph sc-fill-arg)))))))
-
-
-;; ======================================================================
-;; the following functions are the top level, interactive commands that
-;; can be bound to key strokes
-
-(defun sc-insert-reference (arg)
- "Insert, at point, a reference header in the body of the reply.
-Numeric ARG indicates which header style from sc-rewrite-header-list
-to use when rewriting the header. No supplied ARG indicates use of
-sc-preferred-header-style.
-
-With just \\[universal-argument], electric reference insert mode is
-entered, regardless of the value of sc-electric-references-p. See
-sc-electric-mode for more information."
- (interactive "P")
- (if (consp arg)
- (sc-electric-mode)
- (let ((pref (cond ((sc-valid-index-p arg) arg)
- ((sc-valid-index-p sc-preferred-header-style)
- sc-preferred-header-style)
- (t 0))))
- (if sc-electric-references-p (sc-electric-mode pref)
- (condition-case err
- (eval (nth pref sc-rewrite-header-list))
- (void-function
- (progn (message
- "Symbol's function definition is void: %s. (Header %d)."
- (symbol-name (car (cdr err)))
- pref)
- (beep)))
- (error
- (progn (message "Error evaluating rewrite header function %d."
- pref)
- (beep)))
- )))))
-
-(defun sc-cite (arg)
- "Cite the region of text between point and mark.
-Numeric ARG, if supplied, is passed unaltered to sc-insert-reference."
- (interactive "P")
- (if (not (sc-mark))
- (error "Please designate a region to cite (i.e. set the mark)."))
- (catch 'select-abort
- (let ((sc-cite-context 'citing)
- (sc-force-confirmation-p (interactive-p)))
- (sc-select)
- (undo-boundary)
- (let ((xchange (if (> (sc-mark) (point)) nil
- (exchange-point-and-mark)
- t)))
- (sc-insert-reference arg)
- (sc-cite-region (point) (sc-mark))
- ;; leave point on first cited line
- (while (and (< (point) (sc-mark))
- (not (looking-at (aget sc-gal-information
- (if sc-nested-citation-p
- "sc-nested-citation"
- "sc-citation")))))
- (forward-line 1))
- (and xchange
- (exchange-point-and-mark))
- ))))
-
-(defun sc-uncite ()
- "Uncite the region between point and mark."
- (interactive)
- (if (not (sc-mark))
- (error "Please designate a region to uncite (i.e. set the mark)."))
- (undo-boundary)
- (let ((xchange (if (> (sc-mark) (point)) nil
- (exchange-point-and-mark)
- t))
- (fp (or (sc-guess-fill-prefix)
- "")))
- (sc-uncite-region (point) (sc-mark) fp)
- (and xchange
- (exchange-point-and-mark))))
-
-(defun sc-recite ()
- "Recite the region by first unciting then citing the text."
- (interactive)
- (if (not (sc-mark))
- (error "Please designate a region to recite (i.e. set the mark)."))
- (catch 'select-abort
- (let ((sc-cite-context 'reciting)
- (sc-force-confirmation-p t))
- (sc-select)
- (undo-boundary)
- (let ((xchange (if (> (sc-mark) (point)) nil
- (exchange-point-and-mark)
- t))
- (fp (or (sc-guess-fill-prefix)
- "")))
- (sc-uncite-region (point) (sc-mark) fp)
- (sc-cite-region (point) (sc-mark))
- (and xchange
- (exchange-point-and-mark))
- ))))
-
-(defun sc-insert-citation ()
- "Insert citation string at beginning of current line."
- (interactive)
- (save-excursion
- (beginning-of-line)
- (insert (aget sc-gal-information "sc-citation"))))
-
-(defun sc-open-line (arg)
- "Insert a newline and leave point before it.
-Also inserts the guessed prefix at the beginning of the new line. With
-numeric ARG, inserts that many new lines."
- (interactive "p")
- (save-excursion
- (let ((start (point))
- (string (or (sc-guess-fill-prefix t)
- "")))
- (open-line arg)
- (goto-char start)
- (forward-line 1)
- (while (< 0 arg)
- (insert string)
- (forward-line 1)
- (setq arg (- arg 1))))))
-
-(defun sc-fill-paragraph-manually (arg)
- "Fill current cited paragraph.
-Really just runs the hook sc-fill-paragraph-hook, however it does set
-the global variable sc-fill-arg to the value of ARG. This is
-currently the only way to pass an argument to a hookified function."
- (interactive "P")
- (setq sc-fill-arg arg)
- (run-hooks 'sc-fill-paragraph-hook))
-
-(defun sc-modify-information (arg)
- "Interactively modify information in the information alist.
-\\[universal-argument] if supplied, deletes the entry from the alist.
-You can add an entry by supplying a key instead of completing."
- (interactive "P")
- (let* ((delete-p (consp arg))
- (action (if delete-p "delete" "modify"))
- (defaultkey (aheadsym sc-gal-information))
- (prompt (concat "Select information key to "
- action ": (default "
- defaultkey ") "))
- (key (completing-read prompt sc-gal-information))
- )
- (if (or (string= key "")
- (null key))
- (setq key defaultkey))
- (if delete-p (adelete 'sc-gal-information key)
- (let* ((oldval (aget sc-gal-information key t))
- (prompt (concat "Enter new value for key \""
- key "\" (default \"" oldval "\") "))
- (newval (read-input prompt)))
- (if (or (string= newval "")
- (null newval))
- nil
- (aput 'sc-gal-information key newval)
- )))))
-
-(defun sc-view-field (arg)
- "View field values in the information alist.
-This is essentially an interactive version of sc-field, and is similar
-to sc-modify-information, except that the field values can't be
-modified. With \\[universal-argument], if supplied, inserts the value
-into the current buffer as well."
- (interactive "P")
- (let* ((defaultkey (aheadsym sc-gal-information))
- (prompt (concat "View information key: (default "
- defaultkey ") "))
- (key (completing-read prompt sc-gal-information)))
- (if (or (string= key "")
- (null key))
- (setq key defaultkey))
- (let* ((val (aget sc-gal-information key t))
- (pval (if val (concat "\"" val "\"") "nil")))
- (message "value of key %s: %s" key pval)
- (if (and key (consp arg)) (insert val)))))
-
-(defun sc-glom-headers ()
- "Glom information from mail headers in region between point and mark.
-Any old information is lost, unless an error occurs."
- (interactive)
- (let ((attr (copy-sequence sc-gal-attributions))
- (info (copy-sequence sc-gal-information)))
- (setq sc-gal-attributions nil
- sc-gal-information nil)
- (let (start end
- (sc-force-confirmation-p t)
- (sc-cite-context nil))
- (let ((mark-active t))
- (setq start (region-beginning)
- end (region-end)))
- (sc-fetch-fields start end)
- (if (null sc-gal-information)
- (progn
- (message "No mail headers found! Restoring old information.")
- (setq sc-gal-attributions attr
- sc-gal-information info))
- (sc-mail-yank-clear-headers start end)
- (if (not (catch 'select-abort
- (condition-case foo
- (sc-select)
- (quit (beep) (throw 'select-abort nil)))
- ))
- (setq sc-gal-attributions attr
- sc-gal-information info))
- ))))
-
-(defun sc-version (arg)
- "Show supercite version.
-Universal argument (\\[universal-argument]) ARG inserts version
-information in the current buffer instead of printing the message in
-the echo area."
- (interactive "P")
- (if (consp arg)
- (insert "Using Supercite version " sc-version-number)
- (message "Using Supercite version %s" sc-version-number)))
-
-
-;; ======================================================================
-;; leach onto current mode
-
-(defun sc-append-current-keymap ()
- "Append some useful key bindings to the current local key map.
-This searches sc-local-keymap for the keymap to install based on the
-major-mode of the current buffer."
- (let ((hook (car (cdr (assq major-mode sc-local-keymaps)))))
- (cond
- ((not hook)
- (run-hooks 'sc-default-keymap))
- ((not (listp hook))
- (setq hook (car (cdr (assq hook sc-local-keymaps))))
- (run-hooks 'hook))
- (t
- (run-hooks 'hook))))
- (setq sc-leached-keymap (current-local-map)))
-
-(defun sc-snag-all-keybindings ()
- "Snag all keybindings in major-mode's current keymap."
- (let* ((curkeymap (current-local-map))
- (symregexp ".*sc-.*\n")
- (docstring (substitute-command-keys "\\{curkeymap}"))
- (start 0)
- (maxend (length docstring))
- (spooge ""))
- (while (and (< start maxend)
- (string-match symregexp docstring start))
- (setq spooge (concat spooge (substring docstring
- (match-beginning 0)
- (match-end 0))))
- (setq start (match-end 0)))
- spooge))
-
-(defun sc-spoogify-docstring ()
- "Modifies (makes into spooge) the docstring for the current major mode.
-This will leach the keybinding descriptions for supercite onto the end
-of the current major mode's docstring. If major mode is preloaded,
-this function will first make a copy of the list associated with the
-mode, then modify this copy."
- (let* ((symfunc (symbol-function major-mode))
- (doc-cdr (and (listp symfunc) (nthcdr 2 symfunc)))
- (doc-str (documentation major-mode)))
- (cond
- ;; is a docstring even provided?
- ((not (stringp doc-str)))
- ;; have we already leached on?
- ((string-match "Supercite" doc-str))
- ;; lets build the new doc string
- (t
- (let* ((described (sc-snag-all-keybindings))
- (commonstr "
-
-The major mode for this buffer has been modified to include the
-Supercite 2.3 package for handling attributions and citations of
-original messages in email replies. For more information on this
-package, type \"\\[sc-describe]\".")
- (newdoc-str
- (concat doc-str commonstr
- (if (not (string= described ""))
- (concat "\n\nThe following keys are bound "
- "to Supercite commands:\n\n"
- described)))
- ))
- (cond
- (doc-cdr
- (condition-case nil
- (setcar doc-cdr newdoc-str)
- (error
- ;; the major mode must be preloaded, make a copy first
- (setq symfunc (copy-sequence (symbol-function major-mode))
- doc-cdr (nthcdr 2 symfunc))
- (setcar doc-cdr newdoc-str)
- (fset major-mode symfunc))))
- ;; lemacs 19 byte-code.
- ;; Set function to a new byte-code vector with the
- ;; new documentation in the documentation slot (element 4).
- ;; We can't use aset because aset won't allow you to modify
- ;; a byte-code vector.
- ;; Include element 5 if the vector has one.
- (t
- (fset major-mode
- (apply 'make-byte-code
- (aref symfunc 0) (aref symfunc 1)
- (aref symfunc 2) (aref symfunc 3)
- newdoc-str
- (if (> (length symfunc) 5)
- (list (aref symfunc 5)))))
- )))))))
-
-
-;; ======================================================================
-;; this section contains default hooks and hook support for execution
-
-;;;###autoload
-(defun sc-cite-original ()
- "Hook version of sc-cite.
-This is callable from the various mail and news readers' reply
-function according to the agreed upon standard. See \\[sc-describe]
-for more details. Sc-cite-original does not do any yanking of the
-original message but it does require a few things:
-
- 1) The reply buffer is the current buffer.
-
- 2) The original message has been yanked and inserted into the
- reply buffer.
-
- 3) Verbose mail headers from the original message have been
- inserted into the reply buffer directly before the text of the
- original message.
-
- 4) Point is at the beginning of the verbose headers.
-
- 5) Mark is at the end of the body of text to be cited."
- (run-hooks 'sc-pre-hook)
- (setq sc-gal-attributions nil)
- (setq sc-gal-information nil)
- (let (start end)
- (let ((mark-active t))
- (setq start (region-beginning)
- end (region-end)))
- (sc-fetch-fields start end)
- (sc-mail-yank-clear-headers start end)
- (if (not sc-all-but-cite-p)
- (sc-cite sc-preferred-header-style))
- (sc-append-current-keymap)
- (sc-spoogify-docstring)
- (run-hooks 'sc-post-hook)))
-
-
-;; ======================================================================
-;; describe this package
-;;
-(defun sc-describe ()
- "Supercite version 2.3 is now described in a texinfo manual which
-makes the documentation available both for online perusal via emacs'
-info system, or for hard-copy printing using the TeX facility.
-
-To view the online document hit \\[info], then \"mSupercite <RET>\"."
- (interactive)
- (describe-function 'sc-describe))
-
-;; ======================================================================
-;; load hook
-(run-hooks 'sc-load-hook)
-(provide 'sc)
diff --git a/lisp/=sun-keys.el b/lisp/=sun-keys.el
deleted file mode 100644
index f91abc2063f..00000000000
--- a/lisp/=sun-keys.el
+++ /dev/null
@@ -1,77 +0,0 @@
-;;; sun-keys.el --- support for Sun function keys
-
-;;; Copyright (C) 1986 Free Software Foundation, Inc.
-
-;; Author: Ian G. Batten <batten@uk.ac.bham.multics>
-;; Keywords: terminals
-
-;;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;;; Support (cleanly) for Sun function keys. Provides help facilities,
-;;; better diagnostics, etc.
-;;;
-;;; To use: make sure your .ttyswrc binds 'F1' to <ESC> * F1 <CR> and so on.
-;;; load this lot from your start_up
-
-;;; Code:
-
-(defun sun-function-keys-dispatch (arg)
- "Dispatcher for function keys."
- (interactive "p")
- (let* ((key-stroke (read t))
- (command (assq key-stroke sun-function-keys-command-list)))
- (cond (command (funcall (cdr command) arg))
- (t (error "Unbound function key %s" key-stroke)))))
-
-(defvar sun-function-keys-command-list
- '((F1 . sun-function-keys-describe-bindings)
- (R8 . previous-line) ; arrow keys
- (R10 . backward-char)
- (R12 . forward-char)
- (R14 . next-line)))
-
-(defun sun-function-keys-bind-key (arg1 arg2)
- "Bind a specified key."
- (interactive "xFunction Key Cap Label:
-CCommand To Use:")
- (setq sun-function-keys-command-list
- (cons (cons arg1 arg2) sun-function-keys-command-list)))
-
-(defun sun-function-keys-describe-bindings (arg)
- "Describe the function key bindings we're running"
- (interactive)
- (with-output-to-temp-buffer "*Help*"
- (sun-function-keys-write-bindings
- (sort (copy-sequence sun-function-keys-command-list)
- '(lambda (x y) (string-lessp (car x) (car y)))))))
-
-(defun sun-function-keys-write-bindings (list)
- (cond ((null list)
- t)
- (t
- (princ (format "%s: %s\n"
- (car (car list))
- (cdr (car list))))
- (sun-function-keys-write-bindings (cdr list)))))
-
-(global-set-key "\e*" 'sun-function-keys-dispatch)
-
-(make-variable-buffer-local 'sun-function-keys-command-list)
-
-;;; sun-keys.el ends here
diff --git a/lisp/=superyank.el b/lisp/=superyank.el
deleted file mode 100644
index f76e6c7c3bf..00000000000
--- a/lisp/=superyank.el
+++ /dev/null
@@ -1,1243 +0,0 @@
-;;; superyank.el --- smart message-yanking code for GNUS
-
-;; Copyright (C) 1992 Free Software Foundation, Inc.
-
-;; Author: Barry A. Warsaw <warsaw@cme.nist.gov>
-;; Version: 1.1
-;; Adapted-By: ESR
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; 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 Emacs Lisp
-;; 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
-;;
-
-;;; Code:
-
-;; ======================================================================
-;;
-;; require and provide features
-;;
-(require 'sendmail)
-;;
-;; ======================================================================
-;;
-;; 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.
-This automatically finds the sy-cite-regexp and uses 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.
-This inserts the peristant 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 argument, inserts ARG 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))))))
-
-(provide 'superyank)
-
-;;; superyank.el ends here
diff --git a/lisp/=term-nasty.el b/lisp/=term-nasty.el
deleted file mode 100644
index 77a801e2889..00000000000
--- a/lisp/=term-nasty.el
+++ /dev/null
@@ -1,12 +0,0 @@
-;;; term-nasty.el --- Damned Things from terminfo.el
-
-;;; This text is no longer included in Emacs, because it was censored
-;;; by the Communications Decency Act. The law was promoted as a ban
-;;; on pornography, but it bans far more than that. This file did not
-;;; contain pornography, but it was prohibited nonetheless.
-
-;;; For information on US government censorship of the Internet, and
-;;; what you can do to bring back freedom of the press, see the web
-;;; site http://www.vtw.org/
-
-;;; term-nasty.el ends here
diff --git a/lisp/=timer.el b/lisp/=timer.el
deleted file mode 100644
index 3b468023437..00000000000
--- a/lisp/=timer.el
+++ /dev/null
@@ -1,223 +0,0 @@
-;;; timers.el --- run a function with args at some time in future
-
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package gives you the capability to run Emacs Lisp commands at
-;; specified times in the future, either as one-shots or periodically.
-;; The single entry point is `run-at-time'.
-
-;;; Code:
-
-;; Layout of a timer vector:
-;; [triggered-p trigger-high trigger-low delta-secs function args]
-
-(defun timer-create ()
- "Create a timer object."
- (let ((timer (make-vector 7 nil)))
- (aset timer 0 (make-vector 1 'timer-event))
- timer))
-
-(defun timerp (object)
- "Return t if OBJECT is a timer."
- (and (vectorp object) (= (length object) 7)))
-
-(defun timer-set-time (timer time &optional delta)
- "Set the trigger time of TIMER to TIME.
-TIME must be in the internal format returned by, e.g., `current-time'
-If optional third argument DELTA is a non-zero integer make the timer
-fire repeatedly that menu seconds apart."
- (or (timerp timer)
- (error "Invalid timer"))
- (aset timer 1 (car time))
- (aset timer 2 (if (consp (cdr time)) (car (cdr time)) (cdr time)))
- (aset timer 3 (if (consp (cdr time)) (nth 2 time) 0))
- (aset timer 4 (and (integerp delta) (> delta 0) delta))
- timer)
-
-
-(defun timer-inc-time (timer secs &optional usecs)
- "Increment the time set in TIMER by SECS seconds and USECS microseconds.
-SECS may be a fraction."
- (or usecs (setq usecs 0))
- (if (floatp secs)
- (let* ((integer (floor secs))
- (fraction (floor (* 1000000 (- secs integer)))))
- (setq usecs fraction secs integer)))
- (let ((newusecs (+ (aref timer 3) usecs)))
- (aset timer 3 (mod newusecs 1000000))
- (setq secs (+ secs (/ newusecs 1000000))))
- (let ((newlow (+ (aref timer 2) secs))
- (newhigh (aref timer 1)))
- (setq newhigh (+ newhigh (/ newlow 65536))
- newlow (logand newlow 65535))
- (aset timer 1 newhigh)
- (aset timer 2 newlow)))
-
-(defun timer-set-time-with-usecs (timer time usecs &optional delta)
- "Set the trigger time of TIMER to TIME.
-TIME must be in the internal format returned by, e.g., `current-time'
-If optional third argument DELTA is a non-zero integer make the timer
-fire repeatedly that menu seconds apart."
- (or (timerp timer)
- (error "Invalid timer"))
- (aset timer 1 (car time))
- (aset timer 2 (if (consp (cdr time)) (car (cdr time)) (cdr time)))
- (aset timer 3 usecs)
- (aset timer 4 (and (integerp delta) (> delta 0) delta))
- timer)
-
-(defun timer-set-function (timer function &optional args)
- "Make TIMER call FUNCTION with optional ARGS when triggering."
- (or (timerp timer)
- (error "Invalid timer"))
- (aset timer 5 function)
- (aset timer 6 args)
- timer)
-
-(defun timer-activate (timer)
- "Put TIMER on the list of active timers."
- (if (and (timerp timer)
- (integerp (aref timer 1))
- (integerp (aref timer 2))
- (integerp (aref timer 3))
- (aref timer 5))
- (let ((timers timer-list)
- last)
- ;; Skip all timers to trigger before the new one.
- (while (and timers
- (or (> (aref timer 1) (aref (car timers) 1))
- (and (= (aref timer 1) (aref (car timers) 1))
- (> (aref timer 2) (aref (car timers) 2)))
- (and (= (aref timer 1) (aref (car timers) 1))
- (= (aref timer 2) (aref (car timers) 2))
- (> (aref timer 3) (aref (car timers) 3)))))
- (setq last timers
- timers (cdr timers)))
- ;; Insert new timer after last which possibly means in front of queue.
- (if last
- (setcdr last (cons timer timers))
- (setq timer-list (cons timer timers)))
- (aset timer 0 nil)
- nil)
- (error "Invalid or uninitialized timer")))
-
-(defun cancel-timer (timer)
- "Remove TIMER from the list of active timers."
- (or (timerp timer)
- (error "Invalid timer"))
- (setq timer-list (delq timer timer-list))
- nil)
-
-(defun cancel-function-timers (function)
- "Cancel all timers scheduled by `run-at-time' which would run FUNCTION."
- (interactive "aCancel timers of function: ")
- (let ((tail timer-list))
- (while tail
- (if (eq (aref (car tail) 5) function)
- (setq timer-list (delq (car tail) timer-list)))
- (setq tail (cdr tail)))))
-
-;; Set up the common handler for all timer events. Since the event has
-;; the timer as parameter we can still distinguish. Note that using
-;; special-event-map ensures that event timer events that arrive in the
-;; middle of a key sequence being entered are still handled correctly.
-(define-key special-event-map [timer-event] 'timer-event-handler)
-(defun timer-event-handler (event)
- "Call the handler for the timer in the event EVENT."
- (interactive "e")
- (let ((timer (cdr-safe event)))
- (if (timerp timer)
- (progn
- ;; Delete from queue.
- (cancel-timer timer)
- ;; Run handler
- (apply (aref timer 5) (aref timer 6))
- ;; Re-schedule if requested.
- (if (aref timer 4)
- (progn
- (timer-inc-time timer (aref timer 4) 0)
- (timer-activate timer))))
- (error "Bogus timer event"))))
-
-;;;###autoload
-(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 is a string like \"11:23pm\" or a value from `encode-time'.
-REPEAT, an integer number of seconds, is the interval on which to repeat
-the call to the function. If REPEAT is nil or 0, call it just once."
- (interactive "sRun at time: \nNRepeat interval: \naFunction: ")
-
- ;; Handle "11:23pm" and the like. Interpret it as meaning today
- ;; which admittedly is rather stupid if we have passed that time
- ;; already. Unfortunately we don't have a `parse-time' function
- ;; to do the right thing.
- (if (stringp time)
- (progn
- (require 'diary-lib)
- (let ((hhmm (diary-entry-time time))
- (now (decode-time)))
- (if (< hhmm 0)
- (setq time 'bad)
- (setq time
- (encode-time 0 (% hhmm 100) (/ hhmm 100) (nth 3 now)
- (nth 4 now) (nth 5 now) (nth 8 now)))))))
-
- ;; Special case: nil means "now" and is useful when repeting.
- (if (null time)
- (setq time (current-time)))
-
- (or (consp time)
- (error "Invalid time format"))
-
- (or (null repeat)
- (natnump repeat)
- (error "Invalid repetition interval"))
-
- (let ((timer (timer-create)))
- (timer-set-time timer time repeat)
- (timer-set-function timer function args)
- (timer-activate timer)))
-
-;;;###autoload
-(defun run-after-delay (secs repeat function &rest args)
- "Perform an action after a delay of SECS seconds.
-Repeat the action every REPEAT seconds, if REPEAT is non-nil.
-SECS and REPEAT need not be integers.
-The action is to call FUNCTION with arguments ARGS."
- (interactive "sRun after delay (seconds): \nNRepeat interval: \naFunction: ")
-
- (or (null repeat)
- (and (numberp repeat) (>= repeat 0))
- (error "Invalid repetition interval"))
-
- (let ((timer (timer-create)))
- (timer-set-time timer (current-time))
- (timer-inc-time timer secs)
- (timer-set-function timer function args)
- (timer-activate timer)))
-
-(provide 'timers)
-
-;;; timers.el ends here
diff --git a/lisp/=tpu-doc.el b/lisp/=tpu-doc.el
deleted file mode 100644
index ef724ecb6d9..00000000000
--- a/lisp/=tpu-doc.el
+++ /dev/null
@@ -1,469 +0,0 @@
-;;; tpu-doc.el --- Documentation for TPU-edt
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Rob Riepel <riepel@networking.stanford.edu>
-;; Maintainer: Rob Riepel <riepel@networking.stanford.edu>
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-;; This is documentation for the TPU-edt editor for GNU emacs. Major
-;; sections of this document are separated with lines that begin with
-;; ";; %% <topic>", where <topic> is what is discussed in that section.
-
-
-;; %% Contents
-
-;; % Introduction
-;; % Terminal Support
-;; % X-windows Support
-;; % Differences Between TPU-edt and the Real Thing
-;; % Starting TPU-edt
-;; % TPU-edt Default Editing Keypad, Control and Gold Key Bindings
-;; % Optional TPU-edt Extensions
-;; % Customizing TPU-edt using the Emacs Initialization File
-;; % Compiling TPU-edt
-;; % Regular expressions in TPU-edt
-;; % Etcetera
-
-
-;; %% Introduction
-
-;; TPU-edt is based on tpu.el by Jeff Kowalski and Bob Covey. TPU-edt
-;; endeavors to be even more like TPU's EDT emulation than the original
-;; tpu.el. Considerable effort has been expended to that end. Still,
-;; emacs is emacs and there are differences between TPU-edt and the
-;; real thing. Please read the "Differences Between TPU-edt and the
-;; Real Thing" and "Starting TPU-edt" sections before running TPU-edt.
-
-
-;; %% Terminal Support
-
-;; TPU-edt, like it's VMS cousin, works on VT-series terminals with
-;; DEC style keyboards. VT terminal emulators, including xterm with
-;; the appropriate key translations, work just fine too.
-
-
-;; %% X-windows Support
-
-;; Starting with version 19 of emacs, TPU-edt works with X-windows.
-;; This is accomplished through a TPU-edt X keymap. The emacs lisp
-;; program tpu-mapper.el creates this map and stores it in a file.
-;; Tpu-mapper will be run automatically the first time you invoke
-;; the X-windows version of emacs, or you can run it by hand. See
-;; the commentary in tpu-mapper.el for details.
-
-
-;; %% Differences Between TPU-edt and the Real Thing (not Coke (r))
-
-;; Emacs (version 18.58) doesn't support text highlighting, so selected
-;; regions are not shown in inverse video. Emacs uses the concept of
-;; "the mark". The mark is set at one end of a selected region; the
-;; cursor is at the other. The letter "M" appears in the mode line
-;; when the mark is set. The native emacs command ^X^X (Control-X
-;; twice) exchanges the cursor with the mark; this provides a handy
-;; way to find the location of the mark.
-
-;; In TPU the cursor can be either bound or free. Bound means the
-;; cursor cannot wander outside the text of the file being edited.
-;; Free means the arrow keys can move the cursor past the ends of
-;; lines. Free is the default mode in TPU; bound is the only mode
-;; in EDT. Bound is the only mode in the base version of TPU-edt;
-;; optional extensions add an approximation of free mode.
-
-;; Like TPU, emacs uses multiple buffers. Some buffers are used to
-;; hold files you are editing; other "internal" buffers are used for
-;; emacs' own purposes (like showing you help). Here are some commands
-;; for dealing with buffers.
-
-;; Gold-B moves to next buffer, including internal buffers
-;; Gold-N moves to next buffer containing a file
-;; Gold-M brings up a buffer menu (like TPU "show buffers")
-
-;; Emacs is very fond of throwing up new windows. Dealing with all
-;; these windows can be a little confusing at first, so here are a few
-;; commands to that may help:
-
-;; Gold-Next_Scr moves to the next window on the screen
-;; Gold-Prev_Scr moves to the previous window on the screen
-;; Gold-TAB also moves to the next window on the screen
-
-;; Control-x 1 deletes all but the current window
-;; Control-x 0 deletes the current window
-
-;; Note that the buffers associated with deleted windows still exist!
-
-;; Like TPU, TPU-edt has a "command" function, invoked with Gold-KP7 or
-;; Do. Most of the commands available are emacs commands. Some TPU
-;; commands are available, they are: replace, exit, quit, include, and
-;; Get (unfortunately, "get" is an internal emacs function, so we are
-;; stuck with "Get" - to make life easier, Get is available as Gold-g).
-
-;; Support for recall of commands, file names, and search strings was
-;; added to emacs in version 19. For version 18 of emacs, optional
-;; extensions are available to add this recall capability (see "Optional
-;; TPU-edt Extensions" below). The history of strings recalled in both
-;; versions of emacs differs slightly from TPU/edt, but it is still very
-;; convenient.
-
-;; Help is available! The traditional help keys (Help and PF2) display
-;; a three page help file showing the default keypad layout, control key
-;; functions, and Gold key functions. Pressing any key inside of help
-;; splits the screen and prints a description of the function of the
-;; pressed key. Gold-PF2 invokes the native emacs help, with it's
-;; zillions of options. Gold-Help shows all the current key bindings.
-
-;; Thanks to emacs, TPU-edt has some extensions that may make your life
-;; easier, or at least more interesting. For example, Gold-r toggles
-;; TPU-edt rectangular mode. In rectangular mode, Remove and Insert work
-;; on rectangles. Likewise, Gold-* toggles TPU-edt regular expression
-;; mode. In regular expression mode Find, Find Next, and the line-mode
-;; replace command work with regular expressions. [A regular expression
-;; is a pattern that denotes a set of strings; like VMS wildcards.]
-
-;; Emacs also gives TPU-edt the undo and occur functions. Undo does
-;; what it says; it undoes the last change. Multiple undos in a row
-;; undo multiple changes. For your convenience, undo is available on
-;; Gold-u. Occur shows all the lines containing a specific string in
-;; another window. Moving to that window, and typing ^C^C (Control-C
-;; twice) on a particular line moves you back to the original window
-;; at that line. Occur is on Gold-o.
-
-;; Finally, as you edit, remember that all the power of emacs is at
-;; your disposal. It really is a fantastic tool. You may even want to
-;; take some time and read the emacs tutorial; perhaps not to learn the
-;; native emacs key bindings, but to get a feel for all the things
-;; emacs can do for you. The emacs tutorial is available from the
-;; emacs help function: "Gold-PF2 t"
-
-
-;; %% Starting TPU-edt
-
-;; In order to use TPU-edt, the TPU-edt editor definitions, contained
-;; in tpu-edt.el, need to be loaded when emacs is run. This can be
-;; done in a couple of ways. The first is by explicitly requesting
-;; loading of the TPU-edt emacs definition file on the command line:
-
-;; prompt> emacs -l /path/to/definitions/tpu-edt.el
-
-;; If TPU-edt is installed on your system, that is, if tpu-edt.el is in
-;; a directory like /usr/local/emacs/lisp, along with dozens of other
-;; .el files, you should be able to use the command:
-
-;; prompt> emacs -l tpu-edt
-
-;; If you like TPU-edt and want to use it all the time, you can load
-;; the TPU-edt definitions using the emacs initialization file, .emacs.
-;; Simply create a .emacs file in your home directory containing the
-;; line:
-
-;; (load "/path/to/definitions/tpu-edt")
-
-;; or, if (as above) TPU-edt is installed on your system:
-
-;; (load "tpu-edt")
-
-;; Once TPU-edt has been loaded, you will be using an editor with the
-;; interface shown in the next section (A section that is suitable for
-;; cutting out of this document and pasting next to your terminal!).
-
-
-;; %% TPU-edt Default Editing Keypad, Control and Gold Key Bindings
-;;
-;; _______________________ _______________________________
-;; | HELP | Do | | | | | |
-;; |KeyDefs| | | | | | |
-;; |_______|_______________| |_______|_______|_______|_______|
-;; _______________________ _______________________________
-;; | Find |Insert |Remove | | Gold | HELP |FndNxt | Del L |
-;; | | |Sto Tex| | key |E-Help | Find |Undel L|
-;; |_______|_______|_______| |_______|_______|_______|_______|
-;; |Select |Pre Scr|Nex Scr| | Page | Sect |Append | Del W |
-;; | Reset |Pre Win|Nex Win| | Do | Fill |Replace|Undel W|
-;; |_______|_______|_______| |_______|_______|_______|_______|
-;; |Move up| |Forward|Reverse|Remove | Del C |
-;; | Top | |Bottom | Top |Insert |Undel C|
-;; _______|_______|_______ |_______|_______|_______|_______|
-;; |Mov Lef|Mov Dow|Mov Rig| | Word | EOL | Char | |
-;; |StaOfLi|Bottom |EndOfLi| |ChngCas|Del EOL|SpecIns| Enter |
-;; |_______|_______|_______| |_______|_______|_______| |
-;; | Line |Select | Subs |
-;; | Open Line | Reset | |
-;; |_______________|_______|_______|
-;; Control Characters
-;;
-;; ^A toggle insert and overwrite ^L insert page break
-;; ^B recall ^R remember, re-center
-;; ^E end of line ^U delete to beginning of line
-;; ^G cancel current operation ^V quote
-;; ^H beginning of line ^W refresh
-;; ^J delete previous word ^Z exit
-;; ^K learn ^X^X exchange point and mark
-;;
-;;
-;; Gold-<key> Functions
-;; -----------------------------------------------------------------
-;; W Write - save current buffer
-;; K Kill buffer - abandon edits and delete buffer
-;;
-;; E Exit - save current buffer and ask about others
-;; X eXit - save all modified buffers and exit
-;; Q Quit - exit without saving anything
-;;
-;; G Get - load a file into a new edit buffer
-;; I Include - include a file in this buffer
-;;
-;; B next Buffer - display the next buffer (all buffers)
-;; N Next file buffer - display next buffer containing a file
-;; M buffer Menu - display a list of all buffers
-;;
-;; U Undo - undo the last edit
-;; C Recall - edit and possibly repeat previous commands
-;;
-;; O Occur - show following lines containing REGEXP
-;; S Search and substitute - line mode REPLACE command
-;;
-;; ? Spell check - check spelling in a region or entire buffer
-;;
-;; R Toggle Rectangular mode for remove and insert
-;; * Toggle regular expression mode for search and substitute
-;;
-;; V Show TPU-edt version
-;; -----------------------------------------------------------------
-
-
-;; %% Optional TPU-edt Extensions
-
-;; Several optional packages have been included in this distribution
-;; of TPU-edt. The following is a brief description of each package.
-;; See the {package}.el file for more detailed information and usage
-;; instructions.
-
-;; tpu-extras - TPU/edt scroll margins and free cursor mode.
-;; tpu-recall - String, file name, and command history.
-;; vt-control - VTxxx terminal width and keypad controls.
-
-;; Packages are normally loaded from the emacs initialization file
-;; (discussed below). If a package is not installed in the emacs
-;; lisp directory, it can be loaded by specifying the complete path
-;; to the package file. However, it is preferable to modify the
-;; emacs load-path variable to include the directory where packages
-;; are stored. This way, packages can be loaded by name, just as if
-;; they were installed. The first part of the sample .emacs file
-;; below shows how to make such a modification.
-
-
-;; %% Customizing TPU-edt using the Emacs Initialization File
-
-;; .emacs - a sample emacs initialization file
-
-;; This is a sample emacs initialization file. It shows how to invoke
-;; TPU-edt, and how to customize it.
-
-;; The load-path is where emacs looks for files to fulfill load requests.
-;; If TPU-edt is not installed in a standard emacs directory, the load-path
-;; should be updated to include the directory where the TPU-edt files are
-;; stored. Modify and un-comment the following section if TPU-ed is not
-;; installed on your system - be sure to leave the double quotes!
-
-;; (setq load-path
-;; (append (list (expand-file-name "/path/to/tpu-edt/files"))
-;; load-path))
-
-;; Load TPU-edt
-(load "tpu-edt")
-
-;; Load the optional goodies - scroll margins, free cursor mode, command
-;; and string recall. But don't complain if the file aren't available.
-(load "tpu-extras" t)
-(load "tpu-recall" t)
-
-;; Uncomment this line to set scroll margins 10% (top) and 15% (bottom).
-;(and (fboundp 'tpu-set-scroll-margins) (tpu-set-scroll-margins "10%" "15%"))
-
-;; Load the vtxxx terminal control functions, but don't complain if
-;; if the file is not found.
-(load "vt-control" t)
-
-;; TPU-edt treats words like EDT; here's how to add word separators.
-;; Note that backslash (\) and double quote (") are quoted with '\'.
-(tpu-add-word-separators "]\\[-_,.\"=+()'/*#:!&;$")
-
-;; Emacs is happy to save files without a final newline; other Unix programs
-;; hate that! This line will make sure that files end with newlines.
-(setq require-final-newline t)
-
-;; Emacs has the ability to automatically run code embedded in files
-;; you edit. This line makes emacs ask if you want to run the code.
-(if tpu-emacs19-p (setq enable-local-variables "ask")
- (setq inhibit-local-variables t))
-
-;; Emacs uses Control-s and Control-q. Problems can occur when using emacs
-;; on terminals that use these codes for flow control (Xon/Xoff flow control).
-;; These lines disable emacs' use of these characters.
-(global-unset-key "\C-s")
-(global-unset-key "\C-q")
-
-;; top, bottom, bol, eol seem like a waste of Gold-arrow functions. The
-;; following section re-maps up and down arrow keys to top and bottom of
-;; screen, and left and right arrow keys to pan left and right (pan-left,
-;; right moves the screen 16 characters left or right - try it, you'll
-;; like it!).
-
-;; Re-map the Gold-arrow functions
-(define-key GOLD-CSI-map "A" 'tpu-beginning-of-window) ; up-arrow
-(define-key GOLD-CSI-map "B" 'tpu-end-of-window) ; down-arrow
-(define-key GOLD-CSI-map "C" 'tpu-pan-right) ; right-arrow
-(define-key GOLD-CSI-map "D" 'tpu-pan-left) ; left-arrow
-(define-key GOLD-SS3-map "A" 'tpu-beginning-of-window) ; up-arrow
-(define-key GOLD-SS3-map "B" 'tpu-end-of-window) ; down-arrow
-(define-key GOLD-SS3-map "C" 'tpu-pan-right) ; right-arrow
-(define-key GOLD-SS3-map "D" 'tpu-pan-left) ; left-arrow
-
-;; Re-map the Gold-arrow functions for X-windows TPU-edt (emacs version 19)
-(cond
- ((and tpu-emacs19-p window-system)
- (define-key GOLD-map [up] 'tpu-beginning-of-window) ; up-arrow
- (define-key GOLD-map [down] 'tpu-end-of-window) ; down-arrow
- (define-key GOLD-map [right] 'tpu-pan-right) ; right-arrow
- (define-key GOLD-map [left] 'tpu-pan-left))) ; left-arrow
-
-;; The emacs universal-argument function is very useful for native emacs
-;; commands. This line maps universal-argument to Gold-PF1
-(define-key GOLD-SS3-map "P" 'universal-argument) ; Gold-PF1
-
-;; Make KP7 move by paragraphs, instead of pages.
-(define-key SS3-map "w" 'tpu-paragraph) ; KP7
-
-;; TPU-edt assumes you have the ispell spelling checker;
-;; Un-comment this line if you don't.
-;(setq tpu-have-spell nil)
-
-;; Display the TPU-edt version.
-(tpu-version)
-
-;; End of .emacs - a sample emacs initialization file
-
-;; After initialization with the .emacs file shown above, the editing
-;; keys have been re-mapped to look like this:
-
-;; _______________________ _______________________________
-;; | HELP | Do | | | | | |
-;; |KeyDefs| | | | | | |
-;; |_______|_______________| |_______|_______|_______|_______|
-;; _______________________ _______________________________
-;; | Find |Insert |Remove | | Gold | HELP |FndNxt | Del L |
-;; | | |Sto Tex| | U Arg |E-Help | Find |Undel L|
-;; |_______|_______|_______| |_______|_______|_______|_______|
-;; |Select |Pre Scr|Nex Scr| |Paragra| Sect |Append | Del W |
-;; | Reset |Pre Win|Nex Win| | Do | Fill |Replace|Undel W|
-;; |_______|_______|_______| |_______|_______|_______|_______|
-;; |Move up| |Forward|Reverse|Remove | Del C |
-;; |Tscreen| |Bottom | Top |Insert |Undel C|
-;; _______|_______|_______ |_______|_______|_______|_______|
-;; |Mov Lef|Mov Dow|Mov Rig| | Word | EOL | Char | |
-;; |PanLeft|Bscreen|PanRigh| |ChngCas|Del EOL|SpecIns| Enter |
-;; |_______|_______|_______| |_______|_______|_______| |
-;; | Line |Select | Subs |
-;; | Open Line | Reset | |
-;; |_______________|_______|_______|
-
-;; Astute emacs hackers will realize that on systems where TPU-edt is
-;; installed, this documentation file can be loaded to produce the above
-;; editing keypad layout. In fact, to get all the changes in the sample
-;; initialization file, you only need a one line initialization file:
-
-;; (load "tpu-doc")
-
-;; wow!
-
-
-;; %% Compiling TPU-edt
-
-;; It is not necessary to compile (byte-compile in emacs parlance)
-;; TPU-edt to use it. However, byte-compiled code loads and runs
-;; faster, and takes up less memory when loaded. To byte compile
-;; TPU-edt, use the following command.
-
-;; emacs -batch -f batch-byte-compile tpu-edt.el
-
-;; This will produce a file named tpu-edt.elc. This new file can be
-;; used in place of the original tpu-edt.el file. In commands where
-;; the file type is not specified, emacs always attempts to use the
-;; byte-compiled version before resorting to the source.
-
-
-;; %% Regular expressions in TPU-edt
-
-;; Gold-* toggles TPU-edt regular expression mode. In regular expression
-;; mode, find, find next, replace, and substitute accept emacs regular
-;; expressions. A complete list of emacs regular expressions can be
-;; found using the emacs "info" command (it's somewhat like the VMS help
-;; command). Try the following sequence of commands:
-
-;; DO info <enter info mode>
-;; m regex <select the "regular expression" topic>
-;; m directives <select the "directives" topic>
-
-;; Type "q" to quit out of info mode.
-
-;; There is a problem in regular expression mode when searching for
-;; empty strings, like beginning-of-line (^) and end-of-line ($).
-;; When searching for these strings, find-next may find the current
-;; string, instead of the next one. This can cause global replace and
-;; substitute commands to loop forever in the same location. For this
-;; reason, commands like
-
-;; replace "^" "> " <add "> " to beginning of line>
-;; replace "$" "00711" <add "00711" to end of line>
-
-;; may not work properly.
-
-;; Commands like those above are very useful for adding text to the
-;; beginning or end of lines. They might work on a line-by-line basis,
-;; but go into an infinite loop if the "all" response is specified. If
-;; the goal is to add a string to the beginning or end of a particular
-;; set of lines TPU-edt provides functions to do this.
-
-;; Gold-^ Add a string at BOL in region or buffer
-;; Gold-$ Add a string at EOL in region or buffer
-
-;; There is also a TPU-edt interface to the native emacs string
-;; replacement commands. Gold-/ invokes this command. It accepts
-;; regular expressions if TPU-edt is in regular expression mode. Given
-;; a repeat count, it will perform the replacement without prompting
-;; for confirmation.
-
-;; This command replaces empty strings correctly, however, it has its
-;; drawbacks. As a native emacs command, it has a different interface
-;; than the emulated TPU commands. Also, it works only in the forward
-;; direction, regardless of the current TPU-edt direction.
-
-
-;; %% Etcetera
-
-;; That's TPU-edt in a nutshell...
-
-;; Please send any bug reports, feature requests, or cookies to the
-;; author, Rob Riepel, at the address shown by the tpu-version command
-;; (Gold-V).
-
-;; Share and enjoy... Rob Riepel 7/93
-
-;;; tpu-doc.el ends here
diff --git a/lisp/=vmsx.el b/lisp/=vmsx.el
deleted file mode 100644
index b3ab41e51f7..00000000000
--- a/lisp/=vmsx.el
+++ /dev/null
@@ -1,144 +0,0 @@
-;;; vmsx.el --- run asynchronous VMS subprocesses under Emacs
-
-;; Copyright (C) 1986 Free Software Foundation, Inc.
-
-;; Author: Mukesh Prasad
-;; Maintainer: FSF
-;; Keywords: vms
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Code:
-
-(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)
-
-;;; vmsx.el ends here
diff --git a/lisp/=word-help.el b/lisp/=word-help.el
deleted file mode 100644
index f535fd9073c..00000000000
--- a/lisp/=word-help.el
+++ /dev/null
@@ -1,970 +0,0 @@
-;;; word-help.el --- keyword help for any language doc'd in TeXinfo.
-
-;; Copyright (c) 1996 Free Software Foundation, Inc.
-
-;; Maintainer: Jens T. Berger Thielemann, <jensthi@ifi.uio.no>
-;; Keywords: help, keyword, languages, completion
-
-;; 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 2, 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 GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides a rather general interface for doing keyword
-;; help in most languages. In short, it'll determine which TeXinfo
-;; file which is relevant for the current mode; cache the index and
-;; use regexps to give you help on the keyword you're looking at.
-
-;; Installation
-;; ************
-
-;; For the default setup to work for all supported modes, make sure
-;; the Texinfo files from the following packages are installed:
-
-;; Texinfo file | Available in archive or URL | Notes
-;; autoconf.info | autoconf-2.10.tar.gz | -
-;; bison.info | bison-1.25.tar.gz | -
-;; libc.info | glibc-1.09.1.tar.gz | -
-;; elisp.info | elisp-manual-19-2.4.tar.gz | -
-;; latex.info | ftp://ftp.dante.de/pub/tex/info/latex2e-help-texinfo/latex2e.texi
-;; groff.info | groff-1.10.tar.gz | -
-;; m4.info | m4-1.4.tar.gz | -
-;; make.info | make-3.75.tar.gz | -
-;; perl.info | http://www.perl.com/CPAN/doc/manual/info/
-;; simula.info | Mail bjort@ifi.uio.no | Written in Norwegian
-;; texinfo.info | texinfo-3.9.tar.gz | -
-
-;; BTW: We refer to Texinfo files by just their last component, not
-;; with an absolute file name. You must thus set up
-;; `Info-directory-list' and `Info-default-directory-list' so that
-;; these can automatically be located.
-
-;; Usage
-;; *****
-;;
-;; Place the cursor over the function/variable/type/whatever you want
-;; help on. Type "C-h C-i". `word-help' will then make a suggestion
-;; to an index topic; press return to accept this. If not, you may use
-;; tab-completion to find the topic you're interested in.
-
-;; `word-help' is also able to do symbol completion via the
-;; `word-help-complete' function. Bind this function to C-TAB by
-;; adding the following line to your .emacs file:
-;;
-;; (global-set-key [?\M-\t] 'word-help-complete)
-;;
-;; Note that some modes automatically override this key; you may
-;; therefore wish to either put the above statement in a hook or
-;; associate the function with an other key.
-
-;; Usually, `word-help' is able to determine the relevant Texinfo
-;; file from looking at the buffer's `mode-name'; if not, you can use
-;; the interactive function `set-help-file' to set this.
-
-;; Customizing
-;; ***********
-;;
-;; User interface
-;; --------------
-;;
-;; Two variables control the behaviour of the user-interface of
-;; `word-help': `word-help-split-window' and
-;; `word-help-magic-index'. Do C-h v to get more information on
-;; these.
-
-;; Adding more Texinfo files
-;; -------------------------
-;;
-;; Associations between mode-names and Texinfo files can be done
-;; through the `word-help-mode-alist' variable, which defines an
-;; `alist' making `set-help-file' able to initialize the necessary
-;; variable.
-
-;; NOTE: If you have to customize the regexps, it is *CRUCIAL* that
-;; none of your regexps match the empty string! Not adhering to this
-;; restriction will make `word-help' enter an infinite loop.
-
-;; Contacting the author
-;; *********************
-;;
-;; If you wish to contact me for any reason, please feel free to write
-;; to:
-
-;; Jens Berger
-;; Spektrumveien 4
-;; N-0666 Oslo
-;; Norway
-;;
-;; E-mail: <jensthi@ifi.uio.no>
-
-;; Have fun.
-
-;;
-;;; Code:
-;;
-
-(require 'info)
-
-;;;--------------------
-;;; USER OPTIONS
-;;;--------------------
-
-(defvar word-help-split-window t
- "*Non-nil means that the info buffer will pop up in a separate window.
-If nil, we will just switch to it.")
-
-(defvar word-help-magic-index t
- "*Non-nil means that the keyword will be searched for in the requested node.
-This is done by determining whether the line the point is positioned
-on after using `Info-goto-node', actually contains the keyword. If
-not, we will search for the first occurence of the keyword. This may
-help when the info file isn't correctly indexed.")
-
-;;; ---- end of user configurable variables
-
-;;;-------------------------
-;;; ADVANCED USER OPTIONS
-;;;-------------------------
-
-(defvar word-help-mode-alist
- '(
- ("autoconf"
- (("autoconf" "Macro Index") ("m4" "Macro index"))
- (("AC_\\([A-Za-z0-9_]+\\)" 1)
- ("[a-z]+"))
- nil
- nil
- (("AC_\\([A-Za-z0-9_]+\\)" 1 nil (("^[A-Z_]+$")))
- ("[a-z_][a-z_]*" 0 nil (("^[a-z_]+$")))))
-
- ("Bison"
- (("bison" "Index")
- ("libc" "Type Index" "Function Index" "Variable Index"))
- (("%[A-Za-z]*")
- ("[A-Za-z_][A-Za-z0-9_]*"))
- nil
- nil
- (("%[A-Za-z]*" nil nil (("^%")))
- ("[A-Za-z_][A-Za-z0-9_]*" nil nil (("[A-Za-z_][A-Za-z0-9_]*")))))
-
- ("YACC" . "Bison")
-
- ("C" (("libc" "Type Index" "Function Index" "Variable Index")))
- ("C++" . "C")
-
- ("Emacs-Lisp"
- (("elisp" "Index"))
- (("[^][ ()\n\t.\"'#]+"))
- nil
- nil
- lisp-complete-symbol)
-
- ("LaTeX"
- (("latex" "Command Index"))
- (("\\\\\\(begin\\|end\\){\\([^}\n]+\\)}" 2 0)
- ("\\\\[A-Za-z]+")
- ("\\\\[^A-Za-z]")
- ("[A-Za-z]+"))
- nil
- nil
- (("\\\\begin{\\([A-Za-z]*\\)" 1 "}" (("^[A-Za-z]+$")))
- ("\\\\end{\\([A-Za-z]*\\)" 1 "}" (("^[A-Za-z]+$")))
- ("\\\\renewcommand{\\(\\\\?[A-Za-z]*\\)" 1 "}" (("^\\\\[A-Za-z]+")))
- ("\\\\renewcommand\\(\\\\?[A-Za-z]*\\)" 1 "" (("^\\\\[A-Za-z]+")))
- ("\\\\renewenvironment{?\\([A-Za-z]*\\)" 1 "}"(("^[A-Za-z]+$")))
- ("\\\\[A-Za-z]*" 0 "" (("^\\\\[A-Za-z]+")))))
-
- ("latex" . "LaTeX")
-
- ("Nroff"
- (("groff" "Macro Index" "Register Index" "Request Index"))
- (("\\.[^A-Za-z]")
- ("\\.[A-Za-z]+")
- ("\\.\\([A-Za-z]+\\)" 1))
- nil
- nil
- (("\\.[A-Za-z]*" nil nil (("^\\.[A-Za-z]+$")))
- ("\\.\\([A-Za-z]*\\)" 1 nil (("^[A-Za-z]+$")))))
-
- ("Groff" . "Nroff")
-
- ("m4"
- (("m4" "Macro index"))
- (("\\([mM]4_\\)?\\([A-Za-z_][A-Za-z_0-9]*\\)" 2))
- nil
- nil
- (("[mM]4_\\([A-Za-z_]?[A-Za-z_0-9]*\\)" 1)
- ("[A-Za-z_][A-Za-z_0-9]*")))
-
- ("Makefile"
- (("make" "Name Index"))
- (("\\.[A-Za-z]+") ;; .SUFFIXES
- ("\\$[^()]") ;; $@
- ("\\$([^A-Za-z].)") ;; $(<@)
- ("\\$[\(\{]\\([a-zA-Z+]\\)" 1) ;; $(wildcard)
- ("[A-Za-z]+")) ;; foreach
- nil
- nil
- (("\\.[A-Za-z]*" nil ":" (("^\\.[A-Za-z]+$")))
- ("\\$(\\([A-Z]*\\)" 1 ")" (("^[A-Z]")))
- ("[a-z]+" nil nil (("^[a-z]+$")))))
-
- ("Perl"
- (("perl" "Variable Index" "Function Index"))
- (("\\$[^A-Za-z^]") ;; $@
- ("\\$\\^[A-Za-z]?") ;; $^D
- ("\\$[A-Za-z][A-Za-z_0-9]+") ;; $foobar
- ("[A-Za-z_][A-Za-z_0-9]+")) ;; dbmopen
- nil
- nil
- (("\\$[A-Za-z]*" nil nil (("^\\$[A-Za-z]+$"))) ;; $variable
- ("[A-Za-z_][A-Za-z_0-9]*" nil nil
- (("^[A-Za-z_][A-Za-z_0-9]*$"))))) ;; function
-
- ("Simula" (("simula" "Index")) nil t)
- ("Ifi Simula" . "Simula")
- ("SIMULA" . "Simula")
-
- ("Texinfo"
- (("texinfo" "Command and Variable Index"))
- (("@\\([A-Za-z]+\\)" 1))
- nil
- nil
- (("@\\([A-Za-z]*\\)" 1)))
-
- )
- "Assoc list between `mode-name' and Texinfo files.
-The variable should be initialized with a list of elements with the
-following form:
-
-\(mode-name (word-help-info-files) (word-help-keyword-regexps)
- word-help-ignore-case word-help-index-mapper
- word-help-complete-list)
-
-where `word-help-info-files', `word-help-keyword-regexps' and so
-forth of course are the values which should be put in these variables
-for this mode. Note that `mode-name' doesn't have to be a legal
-mode-name; the user may use the call `set-help-file', where
-`mode-name' will be used in the `completing-read'.
-
-Example entry (for C):
-
-\(\"C\" ((\"libc\" \"Type Index\" \"Function Index\" \"Variable Index\"))
- ((\"[A-Za-z_][A-Za-z0-9]+\")))
-
-The two first variables must be initialized; the two remaining will
-get default values if you omit them or set them to nil. The default
-values are:
-
-word-help-keyword-regexps: (\"[A-Za-z_][A-Za-z0-9]+\")
-word-help-ignore-case: nil
-
-More settings may be defined in the future.
-
-You may also define aliases, if there are several relevant mode-names
-to a single entry. These should be of the form:
-
-\(MODE-NAME-ALIAS . MODE-NAME-REAL)
-
-For C++, you would use the alias
-
-\(\"C++\" . \"C\")
-
-to make C++ mode use the same help files as C files do. Please note
-that you can shoot yourself in the foot with this possibility, by
-defining recursive aliases.")
-
-;;; --- end of advanced user options
-
-(defvar word-help-ignore-case nil
- "Non-nil means that case is ignored when doing lookup.")
-(make-variable-buffer-local 'word-help-ignore-case)
-
-(defvar word-help-info-files nil
- "List of info files with respective nodes, for the current mode.
-
-This should be a list of the following form:
-
-\((INFO-FILE-1 NODE-NAME-1 NODE-NAME-2 ...)
- (INFO-FILE-1 NODE-NAME-1 NODE-NAME-2 ...)
- : : :
- (INFO-FILE-1 NODE-NAME-1 NODE-NAME-2 ...))
-
-An example entry for e.g. C would be:
-
-\((\"/local/share/gnu/info/libc\" \"Function Index\" \"Type Index\"
- \"Variable Index\"))
-
-The files and nodes will be searched/cached in the order specified.
-This variable is usually set by the `word-help-switch-help-file'
-function, which utilizes the `word-help-mode-alist'.")
-(make-variable-buffer-local 'word-help-info-files)
-
-(defvar word-help-keyword-regexps nil
- "Regexps for finding keywords in the current mode.
-
-This is constructed as a list of the following form:
-
-\((REGEXP SUBMATCH-LOOKUP SUBMATCH-CURSOR)
- (REGEXP SUBMATCH-LOOKUP SUBMATCH-CURSOR)
- : : :
- (REGEXP SUBMATCH-LOOKUP SUBMATCH-CURSOR))
-
-The regexps will be searched in order for a match which the cursor is
-within.
-
-submatch-lookup is the submatch number which will be looked for in the
-index. May be omitted; defaults to 0 (e.g. the entire pattern). This is
-useful in for instance configure lookup; each command is there prefixed
-with 'AC_', which must be ignored when doing a lookup. Example regexp
-entry for this:
-
-\(\"AC_\\\\([A-Za-z0-9]+\\\\)\" 1)
-
-submatch-cursor is the part of the match which the cursor must be within.
-May be omitted; defaults to 0 (e.g. the entire pattern).")
-(make-variable-buffer-local 'word-help-keyword-regexps)
-(set-default 'word-help-keyword-regexps '(("[A-Za-z_][A-Za-z_0-9]*")))
-
-(defvar word-help-index-mapper nil
- "Regexps to use for massaging index-entries into keywords.
-This variable should contain a list of regexps with sub-expressions,
-where we will only look for the sub-expression in the user text.
-
-The regexp list should be formatted as:
-
- ((REGEXP SUBEXP) (REGEXP SUBEXP) ... )
-
-If the index entry does not match any of the regexps, it will be ignored.
-
-Example:
-
-Perl has index entries of the following form:
-
-* abs VALUE: perlfunc.
-* accept NEWSOCKET,GENERICSOCKET: perlfunc.
-* alarm SECONDS: perlfunc.
-* atan2 Y,X: perlfunc.
-* bind SOCKET,NAME: perlfunc.
- : : :
-
-We will thus try to extract the first word in the index entry -
-\"abs\" from \"abs VALUE\", etc. This is done by the following entry:
-
-\((\"^\\\\([^ \\t\\n]+\\\\)\" 1))
-
-This value is btw. the default one, and works with most Texinfo files")
-(make-variable-buffer-local 'word-help-index-mapper)
-(set-default 'word-help-index-mapper '(("^\\([^ \t\n]+\\)" 1)))
-
-
-(defvar word-help-complete-list nil
- "Regexps or function to use for completion of symbols.
-The list should have the following format:
-
- ((REGEXP SUBMATCH TEXT-APPEND (RE-FILTER-1 REG-FILTER-2 ...)
- : : : : :
- (REGEXP SUBMATCH TEXT-APPEND (RE-FILTER-1 REG-FILTER-2 ...))
-
-The two first entries are similar to `word-help-keyword-regexps',
-REGEXP is a regular expression which should match any relevant
-expression, and where SUBMATCH should be used for look up. By
-specifying non-nil REGEXP-FILTERs, we'll only include entries in the
-index which matches the regexp specified.
-
-If the contents of this variable is a symbol of a function, this
-function will be called instead. This is useful for modes providing
-a more intelligent function (like `lisp-complete-symbol' in Emacs Lisp mode).
-
-If you would like to use another function instead, you may.
-
-Non-nil TEXT-APPEND means that this text will be inserted after the
-completion, if we manage to do make a completion.")
-(make-variable-buffer-local 'word-help-complete-list)
-(set-default 'word-help-complete-list '(("[A-Za-z_][A-Za-z_0-9]*")))
-
-;;; Work variables
-
-
-(defvar word-help-main-index nil
- "List of all index entries.
-
-See `word-help-process-indexes' for structure formatting.
-
-Minor note: This variable is a list if it is initialized, t if
-initializing failed and nil if uninitialized.")
-(make-variable-buffer-local 'word-help-main-index)
-
-(defvar word-help-complete-index nil
- "List of regexps for completion, with matching index entries.
-Value is nil if uninitialized, t if initialized but not accessible,
-a list if we're feeling ok.")
-(make-variable-buffer-local 'word-help-complete-index)
-
-(defvar word-help-main-obarray nil
- "Global work variable for `word-help' system.
-Do Not mess with this!")
-
-(defvar word-help-history nil
- "History for `word-help' minibuffer queries.")
-(make-local-variable 'word-help-history)
-
-(defvar word-help-current-help-file nil
- "Current help file active for this mode.")
-
-(defvar word-help-index-alist nil
- "An assoc list mapping help files to info indexes.
-This means that `word-help-mode-index' can be init'ed faster.")
-
-(defvar word-help-help-mode nil
- "Which mode the help system is bound to for the current mode.")
-(make-variable-buffer-local 'word-help-help-mode)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;; User Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;; Debugging
-
-;;;###autoload
-(defun reset-word-help ()
- "Clear all cached indexes in the `word-help' system.
-You should only need this when installing new info files, and/or
-adding more Texinfo files to the `word-help' system."
- (interactive)
- (setq word-help-index-alist nil
- word-help-main-index nil
- word-help-info-files nil
- word-help-complete-index nil))
-
-
-;;; Changing help file
-
-;;;###autoload
-(defun set-help-file ()
- "Change which set of Texinfo files used for word-help.
-
-`word-help' maintains a list over which Texinfo files which are
-relevant for each programming language (`word-help-mode-alist'). It
-usually selects the correct one, based upon the value of `mode-name'.
-If this guess is incorrect, you may also use this function manually to
-instruct future `word-help' calls which Texinfo files to use."
- (interactive)
- (let (helpfile helpguess (completion-ignore-case t))
-;; Try to make a guess
- (setq helpguess (cond
- (word-help-current-help-file)
- ((word-help-guess-help-file))))
-;; Ask the user
- (setq helpfile (completing-read
- (if helpguess
- (format "Select help mode (default %s): " helpguess)
- "Select help mode: ")
- word-help-mode-alist
- nil t nil nil))
- (if (equal "" helpfile)
- (setq helpfile helpguess))
- (if helpfile
- (word-help-switch-help-file helpfile))))
-
-;;; Main user interface
-
-;;;###autoload
-(defun word-help ()
- "Find documentation on the keyword under the cursor.
-The determination of which language the keyword belongs to, is based upon
-The relevant info file is selected by matching `mode-name' (the major
-mode) against the assoc list `word-help-mode-alist'.
-
-If this is not possible, `set-help-file' will be invoked for selecting
-the relevant info file. `set-help-file' may also be invoked
-interactively by the user.
-
-If the keyword you are looking at is not available in any index, no
-default suggestion will be presented. "
- (interactive)
- (let (myguess guess index-info
- (completion-ignore-case word-help-ignore-case))
-;; Set necessary variables for later lookup
- (word-help-find-help-file)
-;; Have we previously cached datas?
- (word-help-process-indexes)
- (if
- (atom word-help-main-index)
- (message "No help file available for this mode.")
-;; First make a guess at what the user is looking for
- (setq myguess (word-help-guess
- (point)
- (cond
- ((not (atom word-help-main-index))
- (car word-help-main-index)))
- word-help-keyword-regexps))
-;; Ask the user himself
- (setq guess (completing-read
- ; Format string
- (if myguess
- (format "Look up keyword (default %s): " myguess)
- "Look up keyword: ")
- ; Collection
- (car word-help-main-index)
- nil t nil 'word-help-history))
- (if (equal guess "")
- (setq guess myguess))
-;; If we've got anything meaningful to lookup, do so
- (if (not guess)
- (message "Help aborted.")
- (setq index-info (word-help-find-index-node
- guess
- word-help-main-index))
- (if (not index-info)
- (message "Oops, I could not find \"%s\" anyway! Bug?" guess)
- (word-help-goto-index-node (nconc index-info (list guess))))))))
-
-;;;###autoload
-(defun word-help-complete ()
- "Perform completion on the symbol preceding the point.
-The determination of which language the keyword belongs to, is based upon
-The relevant info file is selected by matching `mode-name' (the major
-mode) against the assoc list `word-help-mode-alist'.
-
-If this is not possible, `set-help-file' will be invoked for selecting
-the relevant info file. `set-help-file' may also be invoked
-interactively by the user.
-
-The keywords are extracted from the index of the info file defined for
-this mode, by using the `word-help-complete-list' variable."
- (interactive)
- (word-help-make-complete)
- (cond
- ((not word-help-complete-index)
- (message "No completion available for this mode."))
- ((symbolp word-help-complete-index)
- (call-interactively word-help-complete-index))
- ((listp word-help-complete-index)
- (let ((all-match (word-help-guess-all (point)
- word-help-complete-index t))
- (completion-ignore-case word-help-ignore-case)
- (c-list word-help-complete-index)
- c-entry word-match completion completed)
-;; Loop over and try to find a match
- (while (and all-match (not completed))
- (setq word-match (car all-match)
- c-entry (car c-list)
- c-list (cdr c-list)
- all-match (cdr all-match))
-;; Check whether the current pattern matched
- (if word-match
- (let ((close (nth 3 c-entry))
- (words (nth 4 c-entry)))
-;; Find the maximum completion for this word
-; (print word-match)
-; (print c-entry)
-; (print close)
- (setq completion (try-completion word-match words))
-;; Was the match exact
- (cond ((eq completion t)
- (and close
- (not (looking-at (regexp-quote close)))
- (insert close))
- (setq completed t))
-;; Silently ignore non-matches
- ((not completion))
-;; May we complete more unambiguously
- ((not (string-equal completion word-match))
- (delete-region (- (point) (length word-match))
- (point))
- (insert completion)
- (if (eq t (try-completion completion words))
- (progn
- (and close
- (not (looking-at (regexp-quote close)))
- (insert close))))
- (setq completed t))
- (t
- (message "Making completion list...")
- (let ((list (all-completions word-match words nil)))
- (setq completed list)
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list list)))
- (message "Making completion list...done"))))))
- (if (not completed) (message "No match."))))
- (t (message "No completion available for this mode."))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;; Index mapping ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-(defun word-help-map-index-entries (str re-list)
- "Transform an Info index entry into a programming keyword.
-Uses this by mapping the entries through `word-help-index-mapper'."
- (let ((regexp (car (car re-list)))
- (subexp (car (cdr (car re-list))))
- (next (cdr re-list)))
- (cond
- ((string-match regexp str)
- (substring str (match-beginning subexp) (match-end subexp)))
- (next
- (word-help-map-index-entries str next)))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;; Switch mode files ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;; Mode lookup
-
-(defun word-help-guess-help-file ()
- "Guesses a relevant help file based on mode name.
-Returns nil if no guess could be made. Uses `word-help-mode-alist'."
- (let (guess)
- (cond
- ((setq guess (assoc mode-name word-help-mode-alist))
- (car guess)))))
-
-
-(defun word-help-switch-help-file (helpfile)
- "Changes the help-file to the mode name given.
-Uses `word-help-mode-alist'."
- (if helpfile
- (let (helpdesc)
- (if (not (setq helpdesc (assoc helpfile word-help-mode-alist)))
- (message "No help defined for \"%s\"." helpfile)
- (if (stringp (cdr helpdesc))
- (word-help-switch-help-file (cdr helpdesc))
- (word-help-make-default-map
- helpdesc
- (list 'word-help-help-mode
- 'word-help-info-files
- 'word-help-keyword-regexps
- 'word-help-ignore-case
- 'word-help-index-mapper
- 'word-help-complete-list))))
- (setq word-help-main-index nil
- word-help-complete-index nil))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;; Index collection ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-(defun word-help-extract-index (file-name index-list index-map ignore-case)
- "Extract index from filename and the first node name in index list.
-`file-name' is the name of the info file, while `index-list' is a list
-of node-names to search."
- (let (cmd1 cmdlow nodename ob-array next (case-fold-search word-help-ignore-case))
- (setq nodename (car index-list))
- (setq ob-array (make-vector 211 0))
- (message "Processing \"%s\" in %s..." nodename file-name)
- (save-window-excursion
- (Info-goto-node (concat "(" file-name ")" nodename))
- (end-of-buffer)
- (while (re-search-backward "\\* \\([^\n:]+\\):" nil t)
- (setq cmd1 (buffer-substring (match-beginning 1) (match-end 1)))
- (setq cmdlow (if ignore-case (downcase cmd1) cmd1))
- (if index-map
- (setq cmdlow (word-help-map-index-entries cmdlow
- index-map)))
-;; We have to do this workaround to support case-insensitive matching
- (cond
- (cmdlow
- (put (intern cmdlow ob-array) 'word-help-real-name cmd1)
- (intern cmdlow word-help-main-obarray)))))
- (setq next (cond
- ((cdr index-list)
- (word-help-extract-index file-name (cdr index-list)
- index-map ignore-case))))
- (nconc (list (list nodename ob-array)) next)))
-
-
-(defun word-help-collect-indexes (info-file)
- "Process all the indexes in an info file.
-
-Uses `word-help-extract-index' on each node, and returns an entry
-suitable for merging into `word-help-process-indexes'. `info-file'
-is an entry of the form
-
-\(FILE-NAME INDEX-NAME-1 INDEX-NAME-2 ...)"
- (let ((file (car info-file))
- (nodes (cdr info-file)))
- (nconc (list file) (word-help-extract-index file nodes
- word-help-index-mapper
- word-help-ignore-case))))
-
-(defun word-help-process-indexes ()
- "Process all the entries in the global variable `word-help-info-files'.
-Returns a list formatted as follows:
-
-\(all-entries-ob
- (file-name-1 (node-name-1 this-node-entries-ob)
- (node-name-2 this-node-entries-ob)
- : : :
- (node-name-n this-node-entries-ob))
- (file-name-2 (node-name-1 this-node-entries-ob)
- (node-name-2 this-node-entries-ob)
- : : :
- (node-name-n this-node-entries-ob))
- : : : : : : : : :
- (file-name-n (node-name-1 this-node-entries-ob)
- (node-name-2 this-node-entries-ob)
- : : :
- (node-name-n this-node-entries-ob)))
-
-The symbols in the obarrays may contain the additional property
-`word-help-real-name', which tells the *real* node to go to.
-
-Note that we use `word-help-index-alist' to speed up the process. Note
-that `word-help-switch-help-file' must have been called before this function.
-
-This structure is then later searched by `word-help-find-index-node'."
- (let (index-words old-index)
- (if (not word-help-main-index)
- (cond
- ((setq old-index
- (assoc word-help-help-mode word-help-index-alist))
- (setq word-help-main-index (nth 1 old-index)))
- (word-help-info-files
- (setq word-help-main-obarray (make-vector 307 0)
- index-words (mapcar 'word-help-collect-indexes
- word-help-info-files)
- word-help-main-index
- (append (list word-help-main-obarray) index-words))
- (setq word-help-index-alist (cons (list word-help-help-mode
- word-help-main-index)
- word-help-index-alist)))
- (t (setq word-help-main-index t))))))
-
-(defun word-help-find-help-file ()
- "Tries to find and set a relevant help file for the current mode."
- (let (helpguess)
- (if (not word-help-info-files)
- (if (setq helpguess (word-help-guess-help-file))
- (word-help-switch-help-file helpguess)
- (set-help-file)))))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;; Keyword guess ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun word-help-guess-all (cur-point re-list
- &optional copy-to-point)
- "Guesses *all* keywords the user possibly may be looking at.
-Returns a list of all possible keywords. "
- (let ((regexp (car (car re-list)))
- (submatch (cond ((nth 1 (car re-list))) (0)))
- (cursmatch (cond ((nth 2 (car re-list))) (0)))
- (guess nil)
- (next-guess nil)
- (case-fold-search word-help-ignore-case)
- (end-point nil))
- (save-excursion
- (end-of-line)
- (setq end-point (point))
- ;; Start at the beginning
- (beginning-of-line)
- (while (and (not guess) (re-search-forward regexp end-point t))
- ;; Look whether the cursor is within the match
- (if (and (<= (match-beginning cursmatch) cur-point)
- (>= (match-end cursmatch) cur-point))
- (if (or (not copy-to-point) (<= cur-point (match-end submatch)))
- (setq guess (buffer-substring (match-beginning submatch)
- (if copy-to-point
- cur-point
- (match-end submatch)))))))
- ;; If we found anything, return it and call ourselves again
- (if (cdr re-list)
- (setq next-guess (word-help-guess-all cur-point (cdr re-list)
- copy-to-point))))
- (cons guess next-guess)))
-
-(defun word-help-guess-match (all-match cmd-array)
- (let ((sym (car all-match)))
- (cond
- ((and sym (intern-soft (if word-help-ignore-case
- (downcase sym)
- sym) cmd-array)
- sym))
- ((cdr all-match)
- (word-help-guess-match (cdr all-match) cmd-array)))))
-
-
-(defun word-help-guess (cur-point cmd-array re-list)
- "Guesses what keyword the user is looking at, and returns that.
-CUR-POINT should be the current value of `point', CMD-ARRAY an obarray
-of all the keywords which are defined for the current mode, and
-RE-LIST a list of regexps use for the hunt. See also
-`word-help-keyword-regexps'."
- (let ((all-matches (word-help-guess-all cur-point re-list)))
-; (print all-matches)
- (word-help-guess-match all-matches cmd-array)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;; Show node for keyword ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;; Find an index entry
-
-(defun word-help-find-index-node (node index-reg)
- "Finds the node named `node' in the index-register `index-reg'.
-`index-reg' has the format as returned (and documented) by the
-`word-help-process-indexes' call. In most cases, this will be equal to
-`word-help-main-index'.
-
-Returns a list with format
- (file-name index-node-name index-entry)
-which contains the file and index where the entry can be found.
-Returns nil if the entry can't be found."
- (let (file-info node-name)
- (setq node-name (cond (word-help-ignore-case (downcase node)) (node)))
- (if (intern-soft node-name (car index-reg))
- (setq file-info (word-help-index-search-file node-name
- (cdr index-reg))))
- file-info))
-
-(defun word-help-index-search-file (entry file-data)
- "Searches a cached file for the index-entry `entry'."
- (let (this-file next-files file-name node node-infos)
- (setq this-file (car file-data)
- next-files (cdr file-data)
- file-name (car this-file)
- node-infos (cdr this-file)
- node (word-help-index-search-nodes entry node-infos))
- (cond
- (node
- (cons file-name node))
- (next-files (word-help-index-search-file entry next-files)))))
-
-(defun word-help-index-search-nodes (entry node-info)
- "Searches a cached list of nodes for the entry `entry'."
- (let (this-node next-nodes node-name node-ob node-sym)
- (setq this-node (car node-info)
- next-nodes (cdr node-info)
- node-name (car this-node)
- node-ob (car (cdr this-node))
- node-sym (intern-soft entry node-ob))
- (cond
- (node-sym
- (list node-name (get node-sym 'word-help-real-name)))
- (next-nodes (word-help-index-search-nodes entry next-nodes)))))
-
-;;; Switch to a node in an index
-
-(defun word-help-goto-index-node (index-info)
- "Jumps to an index node.
-`index-info' should be a list with the following format:
-
-\(FILE-NAME INDEX-NODE-NAME INDEX-ENTRY KEYWORD)"
-
- (let* ((file-name (car index-info))
- (node-name (nth 1 index-info))
- (entry-name (nth 2 index-info))
- (kw-name (nth 3 index-info))
- (buffer (current-buffer)))
- (if word-help-split-window
- (pop-to-buffer nil))
- (Info-goto-node (concat "(" file-name ")" node-name))
- (Info-menu entry-name)
-;; Do magic keyword search
- (if word-help-magic-index
- (let (end-point regs this-re found entry-re)
- (setq entry-re (regexp-quote kw-name)
- regs (list (concat
- (if (string-match "^[A-Za-z]" entry-name)
- "\\<" "")
- entry-re
- (if (string-match "[A-Za-z]$" entry-name)
- "\\>" ""))
- (concat "[`\"\(]" entry-re)
- (concat "^" entry-re
- (if (string-match "[A-Za-z]$" entry-name)
- "\\>" ""))))
- (end-of-line)
- (setq end-point (point))
- (beginning-of-line)
- (if (not (re-search-forward (car regs) end-point t))
- (while (and (not found) (car regs))
- (setq this-re (car regs)
- regs (cdr regs)
- found (re-search-forward this-re nil t))))
- (recenter 0)))
- (if word-help-split-window
- (pop-to-buffer buffer))))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Completion ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-
-(defun word-help-extract-matches (from-ob dest-ob re-list)
- "Takes atoms from from-ob, and puts them in dest-ob if they match re-list."
- (let ((regexp (car (car re-list))))
- (mapatoms (lambda (x)
- (if (or (not regexp) (string-match regexp (symbol-name x)))
- (intern (symbol-name x) dest-ob)))
- from-ob)
- (if (cdr re-list)
- (word-help-extract-matches from-ob dest-ob (cdr re-list))))
- dest-ob)
-
-(defun word-help-make-complete ()
- "Generates the `word-help-complete-index'."
- (if word-help-complete-index
- nil
- (word-help-find-help-file)
- (cond
- ((symbolp word-help-complete-list)
- (setq word-help-complete-index word-help-complete-list))
- (t
- (word-help-process-indexes)
- (if (not (atom word-help-main-index))
- (let ((from-ob (car word-help-main-index)))
- (message "Processing keywords...")
- (setq word-help-complete-index
- (mapcar
- (lambda (cmpl)
- (let
- ((regexp (car cmpl))
- (subm (cond ((nth 1 cmpl)) (0)))
- (app (cond ((nth 2 cmpl)) ("")))
- (re-list (cond ((nth 3 cmpl)) ('((".")))))
- (obarr (make-vector 47 0)))
- (list regexp subm subm app
- (word-help-extract-matches from-ob obarr
- re-list))))
- word-help-complete-list))))))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Misc. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-;;; Default mapping
-
-(defun word-help-make-default-map (list vars)
- "Makes a default mapping for `vars', which must be listed in order.
-vars is a list of quoted symbols. If the nth entry in the list is
-non-nil, the nth variable will be given this value. If nil, the var
-will be given the global default value."
- (set (car vars) (cond ((car list)) ((default-value (car vars)))))
- (if (cdr vars)
- (word-help-make-default-map (cdr list) (cdr vars))))
-
-(provide 'word-help)
-
-;;; word-help.el ends here
diff --git a/lisp/abbrev.el b/lisp/abbrev.el
deleted file mode 100644
index ff6ae3ac672..00000000000
--- a/lisp/abbrev.el
+++ /dev/null
@@ -1,299 +0,0 @@
-;;; abbrev.el --- abbrev mode commands for Emacs
-
-;; Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
-
-;; Keywords: abbrev
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This facility is documented in the Emacs Manual.
-
-;;; Code:
-
-(defvar 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.")
-
-(defun abbrev-mode (arg)
- "Toggle abbrev mode.
-With argument 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)))
- (force-mode-line-update))
-
-(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 \\<edit-abbrevs-map>\\[edit-abbrevs-redefine] 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 name hook exp count)
- (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 (&optional file quietly)
- "Read abbrev definitions from file written with `write-abbrev-file'.
-Optional argument FILE is the name of the file to read;
-it defaults to the value of `abbrev-file-name'.
-Optional second argument QUIETLY 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 (&optional file)
- "Read abbrev definitions from file written with write-abbrev-file.
-Optional argument FILE is the name of the file to read;
-it defaults to the value of `abbrev-file-name'.
-Does not print anything."
- ;(interactive "fRead abbrev file: ")
- (read-abbrev-file file t))
-
-(defun write-abbrev-file (file)
- "Write all abbrev definitions to a file of Lisp code.
-The file written can be loaded in another session to define the same abbrevs.
-The argument FILE is the file name to write."
- (interactive
- (list
- (read-file-name "Write abbrev file: "
- (file-name-directory (expand-file-name abbrev-file-name))
- abbrev-file-name)))
- (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.
-
-Don't use this function in a Lisp program; use `define-abbrev' instead."
- (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.
-The prefix argument specifies the number of words before point that form the
-expansion; or zero means the region is the expansion.
-A negative argument means to undefine the specified abbrev.
-This command uses the minibuffer to read the abbreviation.
-
-Don't use this function in a Lisp program; use `define-abbrev' instead."
- (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 (if exp "%s abbrev for \"%s\": "
- "Undefine %s abbrev: ")
- type exp)))
- (set-text-properties 0 (length name) nil name)
- (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 prefix argument N, defines the Nth word before point.
-This command uses the minibuffer to read the expansion.
-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 prefix argument N, defines the Nth word before point.
-This command uses the minibuffer to read the expansion.
-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))))))
- (set-text-properties 0 (length name) nil name)
- (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 prefix argument means don't query; expand all abbrevs.
-If called from a Lisp program, arguments are START END &optional NOQUERY."
- (interactive "r\nP")
- (save-excursion
- (goto-char start)
- (let ((lim (- (point-max) end))
- pnt string)
- (while (and (not (eobp))
- (progn (forward-word 1)
- (<= (setq pnt (point)) (- (point-max) lim))))
- (if (abbrev-expansion
- (setq string
- (buffer-substring
- (save-excursion (forward-word -1) (point))
- pnt)))
- (if (or noquery (y-or-n-p (format "Expand `%s'? " string)))
- (expand-abbrev)))))))
-
-;;; abbrev.el ends here
diff --git a/lisp/abbrevlist.el b/lisp/abbrevlist.el
deleted file mode 100644
index 355e24cf5ec..00000000000
--- a/lisp/abbrevlist.el
+++ /dev/null
@@ -1,53 +0,0 @@
-;;; abbrevlist.el --- list one abbrev table alphabetically ordered.
-
-;; Copyright (C) 1986, 1992 Free Software Foundation, Inc.
-;; Suggested by a previous version by Gildea.
-
-;; Maintainer: FSF
-;; Keywords: abbrev
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(defun list-one-abbrev-table (abbrev-table output-buffer)
- "Display alphabetical listing of ABBREV-TABLE in buffer OUTPUT-BUFFER."
- (with-output-to-temp-buffer output-buffer
- (save-excursion
- (let ((abbrev-list nil) (first-column 0))
- (set-buffer standard-output)
- (mapatoms
- (function (lambda (abbrev)
- (setq abbrev-list (cons abbrev abbrev-list))))
- abbrev-table)
- (setq abbrev-list (sort abbrev-list 'string-lessp))
- (while abbrev-list
- (if (> (+ first-column 40) (frame-width))
- (progn
- (insert "\n")
- (setq first-column 0)))
- (indent-to first-column)
- (insert (symbol-name (car abbrev-list)))
- (indent-to (+ first-column 8))
- (insert (symbol-value (car abbrev-list)))
- (setq first-column (+ first-column 40))
- (setq abbrev-list (cdr abbrev-list)))))))
-
-(provide 'abbrevlist)
-
-;;; abbrevlist.el ends here
diff --git a/lisp/add-log.el b/lisp/add-log.el
deleted file mode 100644
index ef0e83dbca1..00000000000
--- a/lisp/add-log.el
+++ /dev/null
@@ -1,596 +0,0 @@
-;;; add-log.el --- change log maintenance commands for Emacs
-
-;; Copyright (C) 1985, 1986, 1988, 1993, 1994 Free Software Foundation, Inc.
-
-;; Keywords: maint
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This facility is documented in the Emacs Manual.
-
-;;; Code:
-
-(defvar change-log-default-name nil
- "*Name of a change log file for \\[add-change-log-entry].")
-
-(defvar add-log-current-defun-function nil
- "\
-*If non-nil, function to guess name of current function from surrounding text.
-\\[add-change-log-entry] calls this function (if nil, `add-log-current-defun'
-instead) with no arguments. It returns a string or nil if it cannot guess.")
-
-;;;###autoload
-(defvar add-log-full-name nil
- "*Full name of user, for inclusion in ChangeLog daily headers.
-This defaults to the value returned by the `user-full-name' function.")
-
-;;;###autoload
-(defvar add-log-mailing-address nil
- "*Electronic mail address of user, for inclusion in ChangeLog daily headers.
-This defaults to the value of `user-mail-address'.")
-
-(defvar change-log-font-lock-keywords
- '(;;
- ;; Date lines, new and old styles.
- ("^\\sw........."
- (0 font-lock-string-face)
- ("[A-Z][^\n<]+" nil nil (0 font-lock-reference-face)))
- ;;
- ;; File names.
- ("^\t\\* \\([^ ,:([\n]+\\)"
- (1 font-lock-function-name-face)
- ("\\=, \\([^ ,:([\n]+\\)" nil nil (1 font-lock-function-name-face)))
- ;;
- ;; Function or variable names.
- ("(\\([^ ,:\n]+\\)"
- (1 font-lock-keyword-face)
- ("\\=, \\([^ ,:\n]+\\)" nil nil (1 font-lock-keyword-face)))
- ;;
- ;; Conditionals.
- ("\\[!?\\([^]\n]+\\)\\]\\(:\\| (\\)" (1 font-lock-variable-name-face))
- ;;
- ;; Acknowledgments.
- ("^\t\\(From\\|Reported by\\)" 1 font-lock-comment-face)
- )
- "Additional expressions to highlight in Change Log mode.")
-
-(defvar change-log-mode-map nil
- "Keymap for Change Log major mode.")
-(if change-log-mode-map
- nil
- (setq change-log-mode-map (make-sparse-keymap)))
-
-(defvar change-log-time-zone-rule nil
- "Time zone used for calculating change log time stamps.
-It takes the same format as the TZ argument of `set-time-zone-rule'.
-If nil, use local time.")
-
-(defun iso8601-time-zone (time)
- (let* ((utc-offset (or (car (current-time-zone time)) 0))
- (sign (if (< utc-offset 0) ?- ?+))
- (sec (abs utc-offset))
- (ss (% sec 60))
- (min (/ sec 60))
- (mm (% min 60))
- (hh (/ min 60)))
- (format (cond ((not (zerop ss)) "%c%02d:%02d:%02d")
- ((not (zerop mm)) "%c%02d:%02d")
- (t "%c%02d"))
- sign hh mm ss)))
-
-(defun change-log-name ()
- (or change-log-default-name
- (if (eq system-type 'vax-vms)
- "$CHANGE_LOG$.TXT"
- "ChangeLog")))
-
-;;;###autoload
-(defun prompt-for-change-log-name ()
- "Prompt for a change log name."
- (let* ((default (change-log-name))
- (name (expand-file-name
- (read-file-name (format "Log file (default %s): " default)
- nil default))))
- ;; Handle something that is syntactically a directory name.
- ;; Look for ChangeLog or whatever in that directory.
- (if (string= (file-name-nondirectory name) "")
- (expand-file-name (file-name-nondirectory default)
- name)
- ;; Handle specifying a file that is a directory.
- (if (file-directory-p name)
- (expand-file-name (file-name-nondirectory default)
- (file-name-as-directory name))
- name))))
-
-;;;###autoload
-(defun find-change-log (&optional file-name)
- "Find a change log file for \\[add-change-log-entry] and return the name.
-
-Optional arg FILE-NAME specifies the file to use.
-If FILE-NAME is nil, use the value of `change-log-default-name'.
-If 'change-log-default-name' is nil, behave as though it were 'ChangeLog'
-\(or whatever we use on this operating system).
-
-If 'change-log-default-name' contains a leading directory component, then
-simply find it in the current directory. Otherwise, search in the current
-directory and its successive parents for a file so named.
-
-Once a file is found, `change-log-default-name' is set locally in the
-current buffer to the complete file name."
- ;; If user specified a file name or if this buffer knows which one to use,
- ;; just use that.
- (or file-name
- (setq file-name (and change-log-default-name
- (file-name-directory change-log-default-name)
- change-log-default-name))
- (progn
- ;; Chase links in the source file
- ;; and use the change log in the dir where it points.
- (setq file-name (or (and buffer-file-name
- (file-name-directory
- (file-chase-links buffer-file-name)))
- default-directory))
- (if (file-directory-p file-name)
- (setq file-name (expand-file-name (change-log-name) file-name)))
- ;; Chase links before visiting the file.
- ;; This makes it easier to use a single change log file
- ;; for several related directories.
- (setq file-name (file-chase-links file-name))
- (setq file-name (expand-file-name file-name))
- ;; Move up in the dir hierarchy till we find a change log file.
- (let ((file1 file-name)
- parent-dir)
- (while (and (not (or (get-file-buffer file1) (file-exists-p file1)))
- (progn (setq parent-dir
- (file-name-directory
- (directory-file-name
- (file-name-directory file1))))
- ;; Give up if we are already at the root dir.
- (not (string= (file-name-directory file1)
- parent-dir))))
- ;; Move up to the parent dir and try again.
- (setq file1 (expand-file-name
- (file-name-nondirectory (change-log-name))
- parent-dir)))
- ;; If we found a change log in a parent, use that.
- (if (or (get-file-buffer file1) (file-exists-p file1))
- (setq file-name file1)))))
- ;; Make a local variable in this buffer so we needn't search again.
- (set (make-local-variable 'change-log-default-name) file-name)
- file-name)
-
-;;;###autoload
-(defun add-change-log-entry (&optional whoami file-name other-window new-entry)
- "Find change log file and add an entry for today.
-Optional arg (interactive prefix) non-nil means prompt for user name and site.
-Second arg is file name of change log. If nil, uses `change-log-default-name'.
-Third arg OTHER-WINDOW non-nil means visit in other window.
-Fourth arg NEW-ENTRY non-nil means always create a new entry at the front;
-never append to an existing entry. Today's date is calculated according to
-`change-log-time-zone-rule' if non-nil, otherwise in local time."
- (interactive (list current-prefix-arg
- (prompt-for-change-log-name)))
- (or add-log-full-name
- (setq add-log-full-name (user-full-name)))
- (or add-log-mailing-address
- (setq add-log-mailing-address user-mail-address))
- (if whoami
- (progn
- (setq add-log-full-name (read-input "Full name: " add-log-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.
- (setq add-log-mailing-address
- (read-input "Mailing address: " add-log-mailing-address))))
- (let ((defun (funcall (or add-log-current-defun-function
- 'add-log-current-defun)))
- paragraph-end entry)
-
- (setq file-name (expand-file-name (find-change-log file-name)))
-
- ;; Set ENTRY to the file name to use in the new entry.
- (and buffer-file-name
- ;; Never want to add a change log entry for the ChangeLog file itself.
- (not (string= buffer-file-name file-name))
- (setq entry (if (string-match
- (concat "^" (regexp-quote (file-name-directory
- file-name)))
- buffer-file-name)
- (substring buffer-file-name (match-end 0))
- (file-name-nondirectory buffer-file-name))))
-
- (if (and other-window (not (equal file-name buffer-file-name)))
- (find-file-other-window file-name)
- (find-file file-name))
- (or (eq major-mode 'change-log-mode)
- (change-log-mode))
- (undo-boundary)
- (goto-char (point-min))
- (let ((new-entry (concat (if change-log-time-zone-rule
- (let ((tz (getenv "TZ"))
- (now (current-time)))
- (unwind-protect
- (progn
- (set-time-zone-rule
- change-log-time-zone-rule)
- (concat
- (format-time-string "%Y-%m-%d " now)
- (iso8601-time-zone now)))
- (set-time-zone-rule tz)))
- (format-time-string "%Y-%m-%d"))
- " " add-log-full-name
- " <" add-log-mailing-address ">")))
- (if (looking-at (regexp-quote new-entry))
- (forward-line 1)
- (insert new-entry "\n\n")))
-
- ;; Search only within the first paragraph.
- (if (looking-at "\n*[^\n* \t]")
- (skip-chars-forward "\n")
- (forward-paragraph 1))
- (setq paragraph-end (point))
- (goto-char (point-min))
-
- ;; Now insert the new line for this entry.
- (cond ((re-search-forward "^\\s *\\*\\s *$" paragraph-end t)
- ;; Put this file name into the existing empty entry.
- (if entry
- (insert entry)))
- ((and (not new-entry)
- (let (case-fold-search)
- (re-search-forward
- (concat (regexp-quote (concat "* " entry))
- ;; Don't accept `foo.bar' when
- ;; looking for `foo':
- "\\(\\s \\|[(),:]\\)")
- paragraph-end t)))
- ;; Add to the existing entry for the same file.
- (re-search-forward "^\\s *$\\|^\\s \\*")
- (goto-char (match-beginning 0))
- ;; Delete excess empty lines; make just 2.
- (while (and (not (eobp)) (looking-at "^\\s *$"))
- (delete-region (point) (save-excursion (forward-line 1) (point))))
- (insert "\n\n")
- (forward-line -2)
- (indent-relative-maybe))
- (t
- ;; Make a new entry.
- (forward-line 1)
- (while (looking-at "\\sW")
- (forward-line 1))
- (while (and (not (eobp)) (looking-at "^\\s *$"))
- (delete-region (point) (save-excursion (forward-line 1) (point))))
- (insert "\n\n\n")
- (forward-line -2)
- (indent-to left-margin)
- (insert "* " (or entry ""))))
- ;; Now insert the function name, if we have one.
- ;; Point is at the entry for this file,
- ;; either at the end of the line or at the first blank line.
- (if defun
- (progn
- ;; Make it easy to get rid of the function name.
- (undo-boundary)
- (insert (if (save-excursion
- (beginning-of-line 1)
- (looking-at "\\s *$"))
- ""
- " ")
- "(" defun "): "))
- ;; No function name, so put in a colon unless we have just a star.
- (if (not (save-excursion
- (beginning-of-line 1)
- (looking-at "\\s *\\(\\*\\s *\\)?$")))
- (insert ": ")))))
-
-;;;###autoload
-(defun add-change-log-entry-other-window (&optional whoami file-name)
- "Find change log file in other window and add an entry for today.
-Optional arg (interactive prefix) non-nil means prompt for user name and site.
-Second arg is file name of change log. \
-If nil, uses `change-log-default-name'."
- (interactive (if current-prefix-arg
- (list current-prefix-arg
- (prompt-for-change-log-name))))
- (add-change-log-entry whoami file-name t))
-;;;###autoload (define-key ctl-x-4-map "a" 'add-change-log-entry-other-window)
-
-;;;###autoload
-(defun change-log-mode ()
- "Major mode for editing change logs; like Indented Text Mode.
-Prevents numeric backups and sets `left-margin' to 8 and `fill-column' to 74.
-New log entries are usually made with \\[add-change-log-entry] or \\[add-change-log-entry-other-window].
-Each entry behaves as a paragraph, and the entries for one day as a page.
-Runs `change-log-mode-hook'."
- (interactive)
- (kill-all-local-variables)
- (indented-text-mode)
- (setq major-mode 'change-log-mode
- mode-name "Change Log"
- left-margin 8
- fill-column 74
- indent-tabs-mode t
- tab-width 8)
- (use-local-map change-log-mode-map)
- (set (make-local-variable 'fill-paragraph-function)
- 'change-log-fill-paragraph)
- ;; Let each entry behave as one paragraph:
- ;; We really do want "^" in paragraph-start below: it is only the lines that
- ;; begin at column 0 (despite the left-margin of 8) that we are looking for.
- (set (make-local-variable 'paragraph-start) "\\s *$\\|\f\\|^\\<")
- (set (make-local-variable 'paragraph-separate) "\\s *$\\|\f\\|^\\<")
- ;; Let all entries for one day behave as one page.
- ;; Match null string on the date-line so that the date-line
- ;; is grouped with what follows.
- (set (make-local-variable 'page-delimiter) "^\\<\\|^\f")
- (set (make-local-variable 'version-control) 'never)
- (set (make-local-variable 'adaptive-fill-regexp) "\\s *")
- (set (make-local-variable 'font-lock-defaults)
- '(change-log-font-lock-keywords t))
- (run-hooks 'change-log-mode-hook))
-
-;; It might be nice to have a general feature to replace this. The idea I
-;; have is a variable giving a regexp matching text which should not be
-;; moved from bol by filling. change-log-mode would set this to "^\\s *\\s(".
-;; But I don't feel up to implementing that today.
-(defun change-log-fill-paragraph (&optional justify)
- "Fill the paragraph, but preserve open parentheses at beginning of lines.
-Prefix arg means justify as well."
- (interactive "P")
- (let ((end (progn (forward-paragraph) (point)))
- (beg (progn (backward-paragraph) (point)))
- (paragraph-start (concat paragraph-start "\\|\\s *\\s(")))
- (fill-region beg end justify)
- t))
-
-(defvar add-log-current-defun-header-regexp
- "^\\([A-Z][A-Z_ ]*[A-Z_]\\|[-_a-zA-Z]+\\)[ \t]*[:=]"
- "*Heuristic regexp used by `add-log-current-defun' for unknown major modes.")
-
-;;;###autoload
-(defun add-log-current-defun ()
- "Return name of function definition point is in, or nil.
-
-Understands C, Lisp, LaTeX (\"functions\" are chapters, sections, ...),
-Texinfo (@node titles), Perl, and Fortran.
-
-Other modes are handled by a heuristic that looks in the 10K before
-point for uppercase headings starting in the first column or
-identifiers followed by `:' or `=', see variable
-`add-log-current-defun-header-regexp'.
-
-Has a preference of looking backwards."
- (condition-case nil
- (save-excursion
- (let ((location (point)))
- (cond ((memq major-mode '(emacs-lisp-mode lisp-mode scheme-mode
- lisp-interaction-mode))
- ;; If we are now precisely at the beginning of a defun,
- ;; make sure beginning-of-defun finds that one
- ;; rather than the previous one.
- (or (eobp) (forward-char 1))
- (beginning-of-defun)
- ;; Make sure we are really inside the defun found, not after it.
- (if (and (looking-at "\\s(")
- (progn (end-of-defun)
- (< location (point)))
- (progn (forward-sexp -1)
- (>= location (point))))
- (progn
- (if (looking-at "\\s(")
- (forward-char 1))
- (forward-sexp 1)
- (skip-chars-forward " '")
- (buffer-substring (point)
- (progn (forward-sexp 1) (point))))))
- ((and (memq major-mode '(c-mode c++-mode c++-c-mode objc-mode))
- (save-excursion (beginning-of-line)
- ;; Use eq instead of = here to avoid
- ;; error when at bob and char-after
- ;; returns nil.
- (while (eq (char-after (- (point) 2)) ?\\)
- (forward-line -1))
- (looking-at "[ \t]*#[ \t]*define[ \t]")))
- ;; Handle a C macro definition.
- (beginning-of-line)
- (while (eq (char-after (- (point) 2)) ?\\) ;not =; note above
- (forward-line -1))
- (search-forward "define")
- (skip-chars-forward " \t")
- (buffer-substring (point)
- (progn (forward-sexp 1) (point))))
- ((memq major-mode '(c-mode c++-mode c++-c-mode objc-mode))
- (beginning-of-line)
- ;; See if we are in the beginning part of a function,
- ;; before the open brace. If so, advance forward.
- (while (not (looking-at "{\\|\\(\\s *$\\)"))
- (forward-line 1))
- (or (eobp)
- (forward-char 1))
- (beginning-of-defun)
- (if (progn (end-of-defun)
- (< location (point)))
- (progn
- (backward-sexp 1)
- (let (beg tem)
-
- (forward-line -1)
- ;; Skip back over typedefs of arglist.
- (while (and (not (bobp))
- (looking-at "[ \t\n]"))
- (forward-line -1))
- ;; See if this is using the DEFUN macro used in Emacs,
- ;; or the DEFUN macro used by the C library.
- (if (condition-case nil
- (and (save-excursion
- (end-of-line)
- (while (= (preceding-char) ?\\)
- (end-of-line 2))
- (backward-sexp 1)
- (beginning-of-line)
- (setq tem (point))
- (looking-at "DEFUN\\b"))
- (>= location tem))
- (error nil))
- (progn
- (goto-char tem)
- (down-list 1)
- (if (= (char-after (point)) ?\")
- (progn
- (forward-sexp 1)
- (skip-chars-forward " ,")))
- (buffer-substring (point)
- (progn (forward-sexp 1) (point))))
- (if (looking-at "^[+-]")
- (get-method-definition)
- ;; Ordinary C function syntax.
- (setq beg (point))
- (if (and (condition-case nil
- ;; Protect against "Unbalanced parens" error.
- (progn
- (down-list 1) ; into arglist
- (backward-up-list 1)
- (skip-chars-backward " \t")
- t)
- (error nil))
- ;; Verify initial pos was after
- ;; real start of function.
- (save-excursion
- (goto-char beg)
- ;; For this purpose, include the line
- ;; that has the decl keywords. This
- ;; may also include some of the
- ;; comments before the function.
- (while (and (not (bobp))
- (save-excursion
- (forward-line -1)
- (looking-at "[^\n\f]")))
- (forward-line -1))
- (>= location (point)))
- ;; Consistency check: going down and up
- ;; shouldn't take us back before BEG.
- (> (point) beg))
- (let (end middle)
- ;; Don't include any final newline
- ;; in the name we use.
- (if (= (preceding-char) ?\n)
- (forward-char -1))
- (setq end (point))
- (backward-sexp 1)
- ;; Now find the right beginning of the name.
- ;; Include certain keywords if they
- ;; precede the name.
- (setq middle (point))
- (forward-word -1)
- ;; Ignore these subparts of a class decl
- ;; and move back to the class name itself.
- (while (looking-at "public \\|private ")
- (skip-chars-backward " \t:")
- (setq end (point))
- (backward-sexp 1)
- (setq middle (point))
- (forward-word -1))
- (and (bolp)
- (looking-at "struct \\|union \\|class ")
- (setq middle (point)))
- (buffer-substring middle end)))))))))
- ((memq major-mode
- '(TeX-mode plain-TeX-mode LaTeX-mode;; tex-mode.el
- plain-tex-mode latex-mode;; cmutex.el
- ))
- (if (re-search-backward
- "\\\\\\(sub\\)*\\(section\\|paragraph\\|chapter\\)" nil t)
- (progn
- (goto-char (match-beginning 0))
- (buffer-substring (1+ (point));; without initial backslash
- (progn
- (end-of-line)
- (point))))))
- ((eq major-mode 'texinfo-mode)
- (if (re-search-backward "^@node[ \t]+\\([^,\n]+\\)" nil t)
- (buffer-substring (match-beginning 1)
- (match-end 1))))
- ((eq major-mode 'perl-mode)
- (if (re-search-backward "^sub[ \t]+\\([^ \t\n]+\\)" nil t)
- (buffer-substring (match-beginning 1)
- (match-end 1))))
- ((eq major-mode 'fortran-mode)
- ;; must be inside function body for this to work
- (beginning-of-fortran-subprogram)
- (let ((case-fold-search t)) ; case-insensitive
- ;; search for fortran subprogram start
- (if (re-search-forward
- "^[ \t]*\\(program\\|subroutine\\|function\
-\\|[ \ta-z0-9*]*[ \t]+function\\)"
- nil t)
- (progn
- ;; move to EOL or before first left paren
- (if (re-search-forward "[(\n]" nil t)
- (progn (forward-char -1)
- (skip-chars-backward " \t"))
- (end-of-line))
- ;; Use the name preceding that.
- (buffer-substring (point)
- (progn (forward-sexp -1)
- (point)))))))
- (t
- ;; If all else fails, try heuristics
- (let (case-fold-search)
- (end-of-line)
- (if (re-search-backward add-log-current-defun-header-regexp
- (- (point) 10000)
- t)
- (buffer-substring (match-beginning 1)
- (match-end 1))))))))
- (error nil)))
-
-(defvar get-method-definition-md)
-
-;; Subroutine used within get-method-definition.
-;; Add the last match in the buffer to the end of `md',
-;; followed by the string END; move to the end of that match.
-(defun get-method-definition-1 (end)
- (setq get-method-definition-md
- (concat get-method-definition-md
- (buffer-substring (match-beginning 1) (match-end 1))
- end))
- (goto-char (match-end 0)))
-
-;; For objective C, return the method name if we are in a method.
-(defun get-method-definition ()
- (let ((get-method-definition-md "["))
- (save-excursion
- (if (re-search-backward "^@implementation\\s-*\\([A-Za-z_]*\\)" nil t)
- (get-method-definition-1 " ")))
- (save-excursion
- (cond
- ((re-search-forward "^\\([-+]\\)[ \t\n\f\r]*\\(([^)]*)\\)?\\s-*" nil t)
- (get-method-definition-1 "")
- (while (not (looking-at "[{;]"))
- (looking-at
- "\\([A-Za-z_]*:?\\)\\s-*\\(([^)]*)\\)?[A-Za-z_]*[ \t\n\f\r]*")
- (get-method-definition-1 ""))
- (concat get-method-definition-md "]"))))))
-
-
-(provide 'add-log)
-
-;;; add-log.el ends here
diff --git a/lisp/allout.el b/lisp/allout.el
deleted file mode 100644
index a38b9fca4c2..00000000000
--- a/lisp/allout.el
+++ /dev/null
@@ -1,4339 +0,0 @@
-;;; allout.el --- Extensive outline mode for use alone and with other modes.
-
-;; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Ken Manheimer <klm@nist.gov>
-;; Maintainer: Ken Manheimer <klm@nist.gov>
-;; Created: Dec 1991 - first release to usenet
-;; Version: Id: allout.el,v 4.3 1994/05/12 17:43:08 klm Exp ||
-;; Keywords: outline mode
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;;_* Commentary:
-
-;; Allout outline mode provides extensive outline formatting and
-;; manipulation capabilities, subsuming and well beyond that of
-;; standard emacs outline mode. It is specifically aimed at
-;; supporting outline structuring and manipulation of syntax-
-;; sensitive text, eg programming languages. (For an example, see the
-;; allout code itself, which is organized in outline structure.)
-;;
-;; It also includes such things as topic-oriented repositioning, cut, and
-;; paste; integral outline exposure-layout; incremental search with
-;; dynamic exposure/concealment of concealed text; automatic topic-number
-;; maintenance; and many other features.
-;;
-;; See the docstring of the variables `outline-layout' and
-;; `outline-auto-activation' for details on automatic activation of
-;; allout outline-mode as a minor mode. (It has changed since allout
-;; 3.x, for those of you that depend on the old method.)
-;;
-;; Note - the lines beginning with `;;;_' are outline topic headers.
-;; Just `ESC-x eval-current-buffer' to give it a whirl.
-
-;;Ken Manheimer 301 975-3539
-;;ken.manheimer@nist.gov FAX: 301 963-9137
-;;
-;;Computer Systems and Communications Division
-;;
-;; Nat'l Institute of Standards and Technology
-;; Technology A151
-;; Gaithersburg, MD 20899
-
-;;;_* Provide
-(provide 'outline)
-(provide 'allout)
-
-;;;_* USER CUSTOMIZATION VARIABLES:
-
-;;;_ + Layout, Mode, and Topic Header Configuration
-
-;;;_ = outline-auto-activation
-(defvar outline-auto-activation nil
- "*Regulates auto-activation modality of allout outlines - see `outline-init'.
-
-Setq-default by `outline-init' to regulate whether or not allout
-outline mode is automatically activated when the buffer-specific
-variable `outline-layout' is non-nil, and whether or not the layout
-dictated by `outline-layout' should be imposed on mode activation.
-
-With value `t', auto-mode-activation and auto-layout are enabled.
-\(This also depends on `outline-find-file-hooks' being installed in
-`find-file-hooks', which is also done by `outline-init'.)
-
-With value `ask', auto-mode-activation is enabled, and endorsement for
-performing auto-layout is asked of the user each time.
-
-With value `activate', only auto-mode-activation is enabled,
-auto-layout is not.
-
-With value `nil', neither auto-mode-activation nor auto-layout are
-enabled.
-
-See the docstring for `outline-init' for the proper interface to
-this variable.")
-;;;_ = outline-layout
-(defvar outline-layout nil
- "*Layout specification and provisional mode trigger for allout outlines.
-
-Buffer-specific.
-
-A list value specifies a default layout for the current buffer, to be
-applied upon activation of allout outline-mode. Any non-nil value will
-automatically trigger allout outline-mode, provided `outline-init'
-has been called to enable it.
-
-See the docstring for `outline-init' for details on setting up for
-auto-mode-activation, and for `outline-expose-topic' for the format of
-the layout specification.
-
-You can associate a particular outline layout with a file by setting
-this var via the file's local variables. For example, the following
-lines at the bottom of an Emacs Lisp file:
-
-;;;Local variables:
-;;;outline-layout: \(0 : -1 -1 0\)
-;;;End:
-
-will, modulo the above-mentioned conditions, cause the mode to be
-activated when the file is visited, followed by the equivalent of
-`\(outline-expose-topic 0 : -1 -1 0\)'. \(This is the layout used for
-the allout.el, itself.)
-
-Also, allout's mode-specific provisions will make topic prefixes default
-to the comment-start string, if any, of the language of the file. This
-is modulo the setting of `outline-use-mode-specific-leader', which see.")
-(make-variable-buffer-local 'outline-layout)
-
-;;;_ = outline-header-prefix
-(defvar outline-header-prefix "."
- "*Leading string which helps distinguish topic headers.
-
-Outline topic header lines are identified by a leading topic
-header prefix, which mostly have the value of this var at their front.
-\(Level 1 topics are exceptions. They consist of only a single
-character, which is typically set to the outline-primary-bullet. Many
-outlines start at level 2 to avoid this discrepancy.")
-(make-variable-buffer-local 'outline-header-prefix)
-;;;_ = outline-primary-bullet
-(defvar outline-primary-bullet "*"
- "Bullet used for top-level outline topics.
-
-Outline topic header lines are identified by a leading topic header
-prefix, which is concluded by bullets that includes the value of this
-var and the respective outline-*-bullets-string vars.
-
-The value of an asterisk (`*') provides for backwards compatibility
-with the original emacs outline mode. See outline-plain-bullets-string
-and outline-distinctive-bullets-string for the range of available
-bullets.")
-(make-variable-buffer-local 'outline-primary-bullet)
-;;;_ = outline-plain-bullets-string
-(defvar outline-plain-bullets-string (concat outline-primary-bullet
- "+-:.;,")
- "*The bullets normally used in outline topic prefixes.
-
-See `outline-distinctive-bullets-string' for the other kind of
-bullets.
-
-DO NOT include the close-square-bracket, `]', as a bullet.
-
-Outline mode has to be reactivated in order for changes to the value
-of this var to take effect.")
-(make-variable-buffer-local 'outline-plain-bullets-string)
-;;;_ = outline-distinctive-bullets-string
-(defvar outline-distinctive-bullets-string "=>([{}&!?#%\"X@$~\\"
- "*Persistent outline header bullets used to distinguish special topics.
-
-These bullets are not offered among the regular, level-specific
-rotation, and are not altered by automatic rebulleting, as when
-shifting the level of a topic. See `outline-plain-bullets-string' for
-the selection of alternating bullets.
-
-You must run `set-outline-regexp' in order for changes
-to the value of this var to effect outline-mode operation.
-
-DO NOT include the close-square-bracket, `]', on either of the bullet
-strings.")
-(make-variable-buffer-local 'outline-distinctive-bullets-string)
-
-;;;_ = outline-use-mode-specific-leader
-(defvar outline-use-mode-specific-leader t
- "*When non-nil, use mode-specific topic-header prefixes.
-
-Allout outline mode will use the mode-specific `outline-mode-leaders'
-and/or comment-start string, if any, to lead the topic prefix string,
-so topic headers look like comments in the programming language.
-
-String values are used as they stand.
-
-Value `t' means to first check for assoc value in `outline-mode-leaders'
-alist, then use comment-start string, if any, then use default \(`.').
-\(See note about use of comment-start strings, below.\)
-
-Set to the symbol for either of `outline-mode-leaders' or
-`comment-start' to use only one of them, respectively.
-
-Value `nil' means to always use the default \(`.'\).
-
-comment-start strings that do not end in spaces are tripled, and an
-`_' underscore is tacked on the end, to distinguish them from regular
-comment strings. comment-start strings that do end in spaces are not
-tripled, but an underscore is substituted for the space. [This
-presumes that the space is for appearance, not comment syntax. You
-can use `outline-mode-leaders' to override this behavior, when
-incorrect.]")
-;;;_ = outline-mode-leaders
-(defvar outline-mode-leaders '()
- "Specific outline-prefix leading strings per major modes.
-
-Entries will be used in the stead (or lieu) of mode-specific
-comment-start strings. See also `outline-use-mode-specific-leader'.
-
-If you're constructing a string that will comment-out outline
-structuring so it can be included in program code, append an extra
-character, like an \"_\" underscore, to distinguish the lead string
-from regular comments that start at bol.")
-
-;;;_ = outline-old-style-prefixes
-(defvar outline-old-style-prefixes nil
- "*When non-nil, use only old-and-crusty outline-mode `*' topic prefixes.
-
-Non-nil restricts the topic creation and modification
-functions to asterix-padded prefixes, so they look exactly
-like the original emacs-outline style prefixes.
-
-Whatever the setting of this variable, both old and new style prefixes
-are always respected by the topic maneuvering functions.")
-(make-variable-buffer-local 'outline-old-style-prefixes)
-;;;_ = outline-stylish-prefixes - alternating bullets
-(defvar outline-stylish-prefixes t
- "*Do fancy stuff with topic prefix bullets according to level, etc.
-
-Non-nil enables topic creation, modification, and repositioning
-functions to vary the topic bullet char (the char that marks the topic
-depth) just preceding the start of the topic text) according to level.
-Otherwise, only asterisks (`*') and distinctive bullets are used.
-
-This is how an outline can look (but sans indentation) with stylish
-prefixes:
-
- * Top level
- .* A topic
- . + One level 3 subtopic
- . . One level 4 subtopic
- . . A second 4 subtopic
- . + Another level 3 subtopic
- . #1 A numbered level 4 subtopic
- . #2 Another
- . ! Another level 4 subtopic with a different distinctive bullet
- . #4 And another numbered level 4 subtopic
-
-This would be an outline with stylish prefixes inhibited (but the
-numbered and other distinctive bullets retained):
-
- * Top level
- .* A topic
- . * One level 3 subtopic
- . * One level 4 subtopic
- . * A second 4 subtopic
- . * Another level 3 subtopic
- . #1 A numbered level 4 subtopic
- . #2 Another
- . ! Another level 4 subtopic with a different distinctive bullet
- . #4 And another numbered level 4 subtopic
-
-Stylish and constant prefixes (as well as old-style prefixes) are
-always respected by the topic maneuvering functions, regardless of
-this variable setting.
-
-The setting of this var is not relevant when outline-old-style-prefixes
-is non-nil.")
-(make-variable-buffer-local 'outline-stylish-prefixes)
-
-;;;_ = outline-numbered-bullet
-(defvar outline-numbered-bullet "#"
- "*String designating bullet of topics that have auto-numbering; nil for none.
-
-Topics having this bullet have automatic maintenance of a sibling
-sequence-number tacked on, just after the bullet. Conventionally set
-to \"#\", you can set it to a bullet of your choice. A nil value
-disables numbering maintenance.")
-(make-variable-buffer-local 'outline-numbered-bullet)
-;;;_ = outline-file-xref-bullet
-(defvar outline-file-xref-bullet "@"
- "*Bullet signifying file cross-references, for `outline-resolve-xref'.
-
-Set this var to the bullet you want to use for file cross-references.
-Set it to nil if you want to inhibit this capability.")
-
-;;;_ + LaTeX formatting
-;;;_ - outline-number-pages
-(defvar outline-number-pages nil
- "*Non-nil turns on page numbering for LaTeX formatting of an outline.")
-;;;_ - outline-label-style
-(defvar outline-label-style "\\large\\bf"
- "*Font and size of labels for LaTeX formatting of an outline.")
-;;;_ - outline-head-line-style
-(defvar outline-head-line-style "\\large\\sl "
- "*Font and size of entries for LaTeX formatting of an outline.")
-;;;_ - outline-body-line-style
-(defvar outline-body-line-style " "
- "*Font and size of entries for LaTeX formatting of an outline.")
-;;;_ - outline-title-style
-(defvar outline-title-style "\\Large\\bf"
- "*Font and size of titles for LaTeX formatting of an outline.")
-;;;_ - outline-title
-(defvar outline-title '(or buffer-file-name (current-buffer-name))
- "*Expression to be evaluated to determine the title for LaTeX
-formatted copy.")
-;;;_ - outline-line-skip
-(defvar outline-line-skip ".05cm"
- "*Space between lines for LaTeX formatting of an outline.")
-;;;_ - outline-indent
-(defvar outline-indent ".3cm"
- "*LaTeX formatted depth-indent spacing.")
-
-;;;_ + Miscellaneous customization
-
-;;;_ = outline-keybindings-list
-;;; You have to reactivate outline-mode - `(outline-mode t)' - to
-;;; institute changes to this var.
-(defvar outline-keybindings-list ()
- "*List of outline-mode key / function bindings.
-
-These bindings will be locally bound on the outline-mode-map. The
-keys will be prefixed by outline-command-prefix, unless the cell
-contains a third, no-nil element, in which case the initial string
-will be used as is.")
-(setq outline-keybindings-list
- '(
- ; Motion commands:
- ("?t" outline-latexify-exposed)
- ("\C-n" outline-next-visible-heading)
- ("\C-p" outline-previous-visible-heading)
- ("\C-u" outline-up-current-level)
- ("\C-f" outline-forward-current-level)
- ("\C-b" outline-backward-current-level)
- ("\C-a" outline-beginning-of-current-entry)
- ("\C-e" outline-end-of-current-entry)
- ;;("\C-n" outline-next-line-or-topic)
- ;;("\C-p" outline-previous-line-or-topic)
- ; Exposure commands:
- ("\C-i" outline-show-children)
- ("\C-s" outline-show-current-subtree)
- ("\C-h" outline-hide-current-subtree)
- ("\C-o" outline-show-current-entry)
- ("!" outline-show-all)
- ; Alteration commands:
- (" " outline-open-sibtopic)
- ("." outline-open-subtopic)
- ("," outline-open-supertopic)
- ("'" outline-shift-in)
- (">" outline-shift-in)
- ("<" outline-shift-out)
- ("\C-m" outline-rebullet-topic)
- ("*" outline-rebullet-current-heading)
- ("#" outline-number-siblings)
- ("\C-k" outline-kill-line t)
- ("\C-y" outline-yank t)
- ("\M-y" outline-yank-pop t)
- ("\C-k" outline-kill-topic)
- ; Miscellaneous commands:
- ("\C-@" outline-mark-topic)
- ("@" outline-resolve-xref)
- ("?c" outline-copy-exposed)))
-
-;;;_ = outline-command-prefix
-(defvar outline-command-prefix "\C-c"
- "*Key sequence to be used as prefix for outline mode command key bindings.")
-
-;;;_ = outline-enwrap-isearch-mode
-(defvar outline-enwrap-isearch-mode t
- "*Set non-nil to enable automatic exposure of concealed isearch targets.
-
-If non-nil, isearch will expose hidden text encountered in the course
-of a search, and to reconceal it if the search is continued past it.")
-
-;;;_ = outline-use-hanging-indents
-(defvar outline-use-hanging-indents t
- "*If non-nil, topic body text auto-indent defaults to indent of the header.
-Ie, it is indented to be just past the header prefix. This is
-relevant mostly for use with indented-text-mode, or other situations
-where auto-fill occurs.
-
-\[This feature no longer depends in any way on the `filladapt.el'
-lisp-archive package.\]")
-(make-variable-buffer-local 'outline-use-hanging-indents)
-
-;;;_ = outline-reindent-bodies
-(defvar outline-reindent-bodies (if outline-use-hanging-indents
- 'text)
- "*Non-nil enables auto-adjust of topic body hanging indent with depth shifts.
-
-When active, topic body lines that are indented even with or beyond
-their topic header are reindented to correspond with depth shifts of
-the header.
-
-A value of `t' enables reindent in non-programming-code buffers, ie
-those that do not have the variable `comment-start' set. A value of
-`force' enables reindent whether or not `comment-start' is set.")
-
-(make-variable-buffer-local 'outline-reindent-bodies)
-
-;;;_ = outline-inhibit-protection
-(defvar outline-inhibit-protection nil
- "*Non-nil disables warnings and confirmation-checks for concealed-text edits.
-
-Outline mode uses emacs change-triggered functions to detect unruly
-changes to concealed regions. Set this var non-nil to disable the
-protection, potentially increasing text-entry responsiveness a bit.
-
-This var takes effect at outline-mode activation, so you may have to
-deactivate and then reactivate the mode if you want to toggle the
-behavior.")
-
-;;;_* CODE - no user customizations below.
-
-;;;_ #1 Internal Outline Formatting and Configuration
-;;;_ - Version
-;;;_ = outline-version
-(defvar outline-version
- (let ((rcs-rev "Revision: 4.3"))
- (condition-case err
- (save-match-data
- (string-match "Revision: \\([0-9]+\\.[0-9]+\\)" rcs-rev)
- (substring rcs-rev (match-beginning 1) (match-end 1)))
- (error rcs-rev)))
- "Revision number of currently loaded outline package. \(allout.el)")
-;;;_ > outline-version
-(defun outline-version (&optional here)
- "Return string describing the loaded outline version."
- (interactive "P")
- (let ((msg (concat "Allout Outline Mode v " outline-version)))
- (if here (insert-string msg))
- (message "%s" msg)
- msg))
-;;;_ - Topic header format
-;;;_ = outline-regexp
-(defvar outline-regexp ""
- "*Regular expression to match the beginning of a heading line.
-
-Any line whose beginning matches this regexp is considered a
-heading. This var is set according to the user configuration vars
-by set-outline-regexp.")
-(make-variable-buffer-local 'outline-regexp)
-;;;_ = outline-bullets-string
-(defvar outline-bullets-string ""
- "A string dictating the valid set of outline topic bullets.
-
-This var should *not* be set by the user - it is set by `set-outline-regexp',
-and is produced from the elements of `outline-plain-bullets-string'
-and `outline-distinctive-bullets-string'.")
-(make-variable-buffer-local 'outline-bullets-string)
-;;;_ = outline-bullets-string-len
-(defvar outline-bullets-string-len 0
- "Length of current buffers' outline-plain-bullets-string.")
-(make-variable-buffer-local 'outline-bullets-string-len)
-;;;_ = outline-line-boundary-regexp
-(defvar outline-line-boundary-regexp ()
- "Outline-regexp with outline-style beginning-of-line anchor.
-
-\(Ie, C-j, *or* C-m, for prefixes of hidden topics). This is properly
-set when outline-regexp is produced by `set-outline-regexp', so
-that (match-beginning 2) and (match-end 2) delimit the prefix.")
-(make-variable-buffer-local 'outline-line-boundary-regexp)
-;;;_ = outline-bob-regexp
-(defvar outline-bob-regexp ()
- "Like outline-line-boundary-regexp, for headers at beginning of buffer.
-\(match-beginning 2) and (match-end 2) delimit the prefix.")
-(make-variable-buffer-local 'outline-bob-regexp)
-;;;_ = outline-header-subtraction
-(defvar outline-header-subtraction (1- (length outline-header-prefix))
- "Outline-header prefix length to subtract when computing topic depth.")
-(make-variable-buffer-local 'outline-header-subtraction)
-;;;_ = outline-plain-bullets-string-len
-(defvar outline-plain-bullets-string-len (length outline-plain-bullets-string)
- "Length of outline-plain-bullets-string, updated by set-outline-regexp.")
-(make-variable-buffer-local 'outline-plain-bullets-string-len)
-
-
-;;;_ X outline-reset-header-lead (header-lead)
-(defun outline-reset-header-lead (header-lead)
- "*Reset the leading string used to identify topic headers."
- (interactive "sNew lead string: ")
- (setq outline-header-prefix header-lead)
- (setq outline-header-subtraction (1- (length outline-header-prefix)))
- (set-outline-regexp))
-;;;_ X outline-lead-with-comment-string (header-lead)
-(defun outline-lead-with-comment-string (&optional header-lead)
- "*Set the topic-header leading string to specified string.
-
-Useful when for encapsulating outline structure in programming
-language comments. Returns the leading string."
-
- (interactive "P")
- (if (not (stringp header-lead))
- (setq header-lead (read-string
- "String prefix for topic headers: ")))
- (setq outline-reindent-bodies nil)
- (outline-reset-header-lead header-lead)
- header-lead)
-;;;_ > outline-infer-header-lead ()
-(defun outline-infer-header-lead ()
- "Determine appropriate `outline-header-prefix'.
-
-Works according to settings of:
-
- `comment-start'
- `outline-header-prefix' (default)
- `outline-use-mode-specific-leader'
-and `outline-mode-leaders'.
-
-Apply this via \(re\)activation of `outline-mode', rather than
-invoking it directly."
- (let* ((use-leader (and (boundp 'outline-use-mode-specific-leader)
- (if (or (stringp outline-use-mode-specific-leader)
- (memq outline-use-mode-specific-leader
- '(outline-mode-leaders
- comment-start
- t)))
- outline-use-mode-specific-leader
- ;; Oops - garbled value, equate with effect of 't:
- t)))
- (leader
- (cond
- ((not use-leader) nil)
- ;; Use the explicitly designated leader:
- ((stringp use-leader) use-leader)
- (t (or (and (memq use-leader '(t outline-mode-leaders))
- ;; Get it from outline mode leaders?
- (cdr (assq major-mode outline-mode-leaders)))
- ;; ... didn't get from outline-mode-leaders...
- (and (memq use-leader '(t comment-start))
- comment-start
- ;; Use comment-start, maybe tripled, and with
- ;; underscore:
- (concat
- (if (string= " "
- (substring comment-start
- (1- (length comment-start))))
- ;; Use comment-start, sans trailing space:
- (substring comment-start 0 -1)
- (concat comment-start comment-start comment-start))
- ;; ... and append underscore, whichever:
- "_")))))))
- (if (not leader)
- nil
- (if (string= leader outline-header-prefix)
- nil ; no change, nothing to do.
- (setq outline-header-prefix leader)
- outline-header-prefix))))
-;;;_ > outline-infer-body-reindent ()
-(defun outline-infer-body-reindent ()
- "Determine proper setting for `outline-reindent-bodies'.
-
-Depends on default setting of `outline-reindent-bodies' \(which see)
-and presence of setting for `comment-start', to tell whether the
-file is programming code."
- (if (and outline-reindent-bodies
- comment-start
- (not (eq 'force outline-reindent-bodies)))
- (setq outline-reindent-bodies nil)))
-;;;_ > set-outline-regexp ()
-(defun set-outline-regexp ()
- "Generate proper topic-header regexp form for outline functions.
-
-Works with respect to `outline-plain-bullets-string' and
-`outline-distinctive-bullets-string'."
-
- (interactive)
- ;; Derive outline-bullets-string from user configured components:
- (setq outline-bullets-string "")
- (let ((strings (list 'outline-plain-bullets-string
- 'outline-distinctive-bullets-string))
- cur-string
- cur-len
- cur-char
- cur-char-string
- index
- new-string)
- (while strings
- (setq new-string "") (setq index 0)
- (setq cur-len (length (setq cur-string (symbol-value (car strings)))))
- (while (< index cur-len)
- (setq cur-char (aref cur-string index))
- (setq outline-bullets-string
- (concat outline-bullets-string
- (cond
- ; Single dash would denote a
- ; sequence, repeated denotes
- ; a dash:
- ((eq cur-char ?-) "--")
- ; literal close-square-bracket
- ; doesn't work right in the
- ; expr, exclude it:
- ((eq cur-char ?\]) "")
- (t (regexp-quote (char-to-string cur-char))))))
- (setq index (1+ index)))
- (setq strings (cdr strings)))
- )
- ;; Derive next for repeated use in outline-pending-bullet:
- (setq outline-plain-bullets-string-len (length outline-plain-bullets-string))
- (setq outline-header-subtraction (1- (length outline-header-prefix)))
- ;; Produce the new outline-regexp:
- (setq outline-regexp (concat "\\(\\"
- outline-header-prefix
- "[ \t]*["
- outline-bullets-string
- "]\\)\\|\\"
- outline-primary-bullet
- "+\\|\^l"))
- (setq outline-line-boundary-regexp
- (concat "\\([\n\r]\\)\\(" outline-regexp "\\)"))
- (setq outline-bob-regexp
- (concat "\\(\\`\\)\\(" outline-regexp "\\)"))
- )
-;;;_ - Key bindings
-;;;_ = outline-mode-map
-(defvar outline-mode-map nil "Keybindings for (allout) outline minor mode.")
-;;;_ > produce-outline-mode-map (keymap-alist &optional base-map)
-(defun produce-outline-mode-map (keymap-list &optional base-map)
- "Produce keymap for use as outline-mode-map, from keymap-list.
-
-Built on top of optional BASE-MAP, or empty sparse map if none specified.
-See doc string for outline-keybindings-list for format of binding list."
- (let ((map (or base-map (make-sparse-keymap))))
- (mapcar (lambda (cell)
- (apply 'define-key map (if (null (cdr (cdr cell)))
- (cons (concat outline-command-prefix
- (car cell))
- (cdr cell))
- (list (car cell) (car (cdr cell))))))
- keymap-list)
- map))
-;;;_ = outline-prior-bindings - being deprecated.
-(defvar outline-prior-bindings nil
- "Variable for use in V18, with outline-added-bindings, for
-resurrecting, on mode deactivation, bindings that existed before
-activation. Being deprecated.")
-;;;_ = outline-added-bindings - being deprecated
-(defvar outline-added-bindings nil
- "Variable for use in V18, with outline-prior-bindings, for
-resurrecting, on mode deactivation, bindings that existed before
-activation. Being deprecated.")
-;;;_ - Mode-Specific Variable Maintenance Utilities
-;;;_ = outline-mode-prior-settings
-(defvar outline-mode-prior-settings nil
- "Internal outline mode use; settings to be resumed on mode deactivation.")
-(make-variable-buffer-local 'outline-mode-prior-settings)
-;;;_ > outline-resumptions (name &optional value)
-(defun outline-resumptions (name &optional value)
-
- "Registers or resumes settings over outline-mode activation/deactivation.
-
-First arg is NAME of variable affected. Optional second arg is list
-containing outline-mode-specific VALUE to be imposed on named
-variable, and to be registered. (It's a list so you can specify
-registrations of null values.) If no value is specified, the
-registered value is returned (encapsulated in the list, so the caller
-can distinguish nil vs no value), and the registration is popped
-from the list."
-
- (let ((on-list (assq name outline-mode-prior-settings))
- prior-capsule ; By `capsule' i mean a list
- ; containing a value, so we can
- ; distinguish nil from no value.
- )
-
- (if value
-
- ;; Registering:
- (progn
- (if on-list
- nil ; Already preserved prior value - don't mess with it.
- ;; Register the old value, or nil if previously unbound:
- (setq outline-mode-prior-settings
- (cons (list name
- (if (boundp name) (list (symbol-value name))))
- outline-mode-prior-settings)))
- ; And impose the new value, locally:
- (progn (make-local-variable name)
- (set name (car value))))
-
- ;; Relinquishing:
- (if (not on-list)
-
- ;; Oops, not registered - leave it be:
- nil
-
- ;; Some registration:
- ; reestablish it:
- (setq prior-capsule (car (cdr on-list)))
- (if prior-capsule
- (set name (car prior-capsule)) ; Some prior value - reestablish it.
- (makunbound name)) ; Previously unbound - demolish var.
- ; Remove registration:
- (let (rebuild)
- (while outline-mode-prior-settings
- (if (not (eq (car outline-mode-prior-settings)
- on-list))
- (setq rebuild
- (cons (car outline-mode-prior-settings)
- rebuild)))
- (setq outline-mode-prior-settings
- (cdr outline-mode-prior-settings)))
- (setq outline-mode-prior-settings rebuild)))))
- )
-;;;_ - Mode-specific incidentals
-;;;_ = outline-during-write-cue nil
-(defvar outline-during-write-cue nil
- "Used to inhibit outline change-protection during file write.
-
-See also `outline-post-command-business', `outline-write-file-hook',
-`outline-before-change-protect', and `outline-post-command-business'
-functions.")
-;;;_ = outline-override-protect nil
-(defvar outline-override-protect nil
- "Used in outline-mode for regulate of concealed-text protection mechanism.
-
-Allout outline mode regulates alteration of concealed text to protect
-against inadvertent, unnoticed changes. This is for use by specific,
-native outline functions to temporarily override that protection.
-It's automatically reset to nil after every buffer modification.")
-(make-variable-buffer-local 'outline-override-protect)
-;;;_ > outline-unprotected (expr)
-(defmacro outline-unprotected (expr)
- "Evaluate EXPRESSION with `outline-override-protect' let-bound to t."
- (` (let ((outline-override-protect t))
- (, expr))))
-;;;_ = outline-undo-aggregation
-(defvar outline-undo-aggregation 30
- "Amount of successive self-insert actions to bunch together per undo.
-
-This is purely a kludge variable, regulating the compensation for a bug in
-the way that before-change-function and undo interact.")
-(make-variable-buffer-local 'outline-undo-aggregation)
-;;;_ = file-var-bug hack
-(defvar outline-v18/9-file-var-hack nil
- "Horrible hack used to prevent invalid multiple triggering of outline
-mode from prop-line file-var activation. Used by outline-mode function
-to track repeats.")
-;;;_ > outline-write-file-hook ()
-(defun outline-write-file-hook ()
- "In outline mode, run as a local-write-file-hooks activity.
-
-Currently just sets `outline-during-write-cue', so outline-change-protection
-knows to keep inactive during file write."
- (setq outline-during-write-cue t)
- nil)
-
-;;;_ #2 Mode activation
-;;;_ = outline-mode
-(defvar outline-mode () "Allout outline mode minor-mode flag.")
-(make-variable-buffer-local 'outline-mode)
-;;;_ > outline-mode-p ()
-(defmacro outline-mode-p ()
- "Return t if outline-mode is active in current buffer."
- 'outline-mode)
-;;;_ = outline-explicitly-deactivated
-(defvar outline-explicitly-deactivated nil
- "Outline-mode was last deliberately deactivated.
-So outline-post-command-business should not reactivate it...")
-(make-variable-buffer-local 'outline-explicitly-deactivated)
-;;;_ > outline-init (&optional mode)
-(defun outline-init (&optional mode)
- "Prime outline-mode to enable/disable auto-activation, wrt `outline-layout'.
-
-MODE is one of the following symbols:
-
- - nil \(or no argument) deactivate auto-activation/layout;
- - `activate', enable auto-activation only;
- - `ask', enable auto-activation, and enable auto-layout but with
- confirmation for layout operation solicited from user each time;
- - `report', just report and return the current auto-activation state;
- - anything else \(eg, t) for auto-activation and auto-layout, without
- any confirmation check.
-
-Use this function to setup your emacs session for automatic activation
-of allout outline mode, contingent to the buffer-specific setting of
-the `outline-layout' variable. (See `outline-layout' and
-`outline-expose-topic' docstrings for more details on auto layout).
-
-`outline-init' works by setting up (or removing) the outline-mode
-find-file-hook, and giving `outline-auto-activation' a suitable
-setting.
-
-To prime your emacs session for full auto-outline operation, include
-the following two lines in your emacs init file:
-
-\(require 'allout)
-\(outline-init t)"
-
- (interactive)
- (if (interactive-p)
- (progn
- (setq mode
- (completing-read
- (concat "Select outline auto setup mode "
- "(empty for report, ? for options) ")
- '(("nil")("full")("activate")("deactivate")
- ("ask") ("report") (""))
- nil
- t))
- (if (string= mode "")
- (setq mode 'report)
- (setq mode (intern-soft mode)))))
- (let
- ;; convenience aliases, for consistent ref to respective vars:
- ((hook 'outline-find-file-hook)
- (curr-mode 'outline-auto-activation))
-
- (cond ((not mode)
- (setq find-file-hooks (delq hook find-file-hooks))
- (if (interactive-p)
- (message "Allout outline mode auto-activation inhibited.")))
- ((eq mode 'report)
- (if (not (memq hook find-file-hooks))
- (outline-init nil)
- ;; Just punt and use the reports from each of the modes:
- (outline-init (symbol-value curr-mode))))
- (t (add-hook 'find-file-hooks hook)
- (set curr-mode ; `set', not `setq'!
- (cond ((eq mode 'activate)
- (message
- "Outline mode auto-activation enabled.")
- 'activate)
- ((eq mode 'report)
- ;; Return the current mode setting:
- (outline-init mode))
- ((eq mode 'ask)
- (message
- (concat "Outline mode auto-activation and "
- "-layout \(upon confirmation) enabled."))
- 'ask)
- ((message
- "Outline mode auto-activation and -layout enabled.")
- 'full)))))))
-
-;;;_ > outline-mode (&optional toggle)
-;;;_ : Defun:
-(defun outline-mode (&optional toggle)
-;;;_ . Doc string:
- "Toggle minor mode for controlling exposure and editing of text outlines.
-
-Optional arg forces mode reactivation iff arg is positive num or symbol.
-
-Allout outline mode provides extensive outline formatting and
-manipulation capabilities. It is specifically aimed at supporting
-outline structuring and manipulation of syntax-sensitive text, eg
-programming languages. \(For an example, see the allout code itself,
-which is organized in outline structure.\)
-
-It also includes such things as topic-oriented repositioning, cut, and
-paste; integral outline exposure-layout; incremental search with
-dynamic exposure/concealment of concealed text; automatic topic-number
-maintenance; and many other features.
-
-See the docstring of the variable `outline-init' for instructions on
-priming your emacs session for automatic activation of outline-mode,
-according to file-var settings of the `outline-layout' variable.
-
-Below is a description of the bindings, and then explanation of
-special outline-mode features and terminology.
-
-The bindings themselves are established according to the values of
-variables `outline-keybindings-list' and `outline-command-prefix',
-each time the mode is invoked. Prior bindings are resurrected when
-the mode is revoked.
-
- Navigation: Exposure Control:
- ---------- ----------------
-C-c C-n outline-next-visible-heading | C-c C-h outline-hide-current-subtree
-C-c C-p outline-previous-visible-heading | C-c C-i outline-show-children
-C-c C-u outline-up-current-level | C-c C-s outline-show-current-subtree
-C-c C-f outline-forward-current-level | C-c C-o outline-show-current-entry
-C-c C-b outline-backward-current-level | ^U C-c C-s outline-show-all
-C-c C-e outline-end-of-current-entry | outline-hide-current-leaves
-C-c C-a outline-beginning-of-current-entry, alternately, goes to hot-spot
-
- Topic Header Production:
- -----------------------
-C-c<SP> outline-open-sibtopic Create a new sibling after current topic.
-C-c . outline-open-subtopic ... an offspring of current topic.
-C-c , outline-open-supertopic ... a sibling of the current topic's parent.
-
- Topic Level and Prefix Adjustment:
- ---------------------------------
-C-c > outline-shift-in Shift current topic and all offspring deeper.
-C-c < outline-shift-out ... less deep.
-C-c<CR> outline-rebullet-topic Reconcile bullets of topic and its offspring
- - distinctive bullets are not changed, others
- alternated according to nesting depth.
-C-c * outline-rebullet-current-heading Prompt for alternate bullet for
- current topic.
-C-c # outline-number-siblings Number bullets of topic and siblings - the
- offspring are not affected. With repeat
- count, revoke numbering.
-
- Topic-oriented Killing and Yanking:
- ----------------------------------
-C-c C-k outline-kill-topic Kill current topic, including offspring.
-C-k outline-kill-line Like kill-line, but reconciles numbering, etc.
-C-y outline-yank Yank, adjusting depth of yanked topic to
- depth of heading if yanking into bare topic
- heading (ie, prefix sans text).
-M-y outline-yank-pop Is to outline-yank as yank-pop is to yank
-
- Misc commands:
- -------------
-C-c @ outline-resolve-xref pop-to-buffer named by xref (cf
- outline-file-xref-bullet)
-C-c c outline-copy-exposed Copy current topic outline sans concealed
- text, to buffer with name derived from
- current buffer - \"XXX exposed\"
-M-x outlineify-sticky Activate outline mode for current buffer,
- and establish a default file-var setting
- for `outline-layout'.
-ESC ESC (outline-init t) Setup emacs session for outline mode
- auto-activation.
-
- HOT-SPOT Operation
-
-Hot-spot operation provides a means for easy, single-keystroke outline
-navigation and exposure control.
-
-\\<outline-mode-map>
-When the text cursor is positioned directly on the bullet character of
-a topic, regular characters (a to z) invoke the commands of the
-corresponding outline-mode keymap control chars. For example, \"f\"
-would invoke the command typically bound to \"C-c C-f\"
-\(\\[outline-forward-current-level] `outline-forward-current-level').
-
-Thus, by positioning the cursor on a topic bullet, you can execute
-the outline navigation and manipulation commands with a single
-keystroke. Non-literal chars never get this special translation, so
-you can use them to get away from the hot-spot, and back to normal
-operation.
-
-Note that the command `outline-beginning-of-current-entry' \(\\[outline-beginning-of-current-entry]\)
-will move to the hot-spot when the cursor is already located at the
-beginning of the current entry, so you can simply hit \\[outline-beginning-of-current-entry]
-twice in a row to get to the hot-spot.
-
- Terminology
-
-Topic hierarchy constituents - TOPICS and SUBTOPICS:
-
-TOPIC: A basic, coherent component of an emacs outline. It can
- contain other topics, and it can be subsumed by other topics,
-CURRENT topic:
- The visible topic most immediately containing the cursor.
-DEPTH: The degree of nesting of a topic; it increases with
- containment. Also called the:
-LEVEL: The same as DEPTH.
-
-ANCESTORS:
- The topics that contain a topic.
-PARENT: A topic's immediate ancestor. It has a depth one less than
- the topic.
-OFFSPRING:
- The topics contained by a topic;
-SUBTOPIC:
- An immediate offspring of a topic;
-CHILDREN:
- The immediate offspring of a topic.
-SIBLINGS:
- Topics having the same parent and depth.
-
-Topic text constituents:
-
-HEADER: The first line of a topic, include the topic PREFIX and header
- text.
-PREFIX: The leading text of a topic which which distinguishes it from
- normal text. It has a strict form, which consists of a
- prefix-lead string, padding, and a bullet. The bullet may be
- followed by a number, indicating the ordinal number of the
- topic among its siblings, a space, and then the header text.
-
- The relative length of the PREFIX determines the nesting depth
- of the topic.
-PREFIX-LEAD:
- The string at the beginning of a topic prefix, normally a `.'.
- It can be customized by changing the setting of
- `outline-header-prefix' and then reinitializing outline-mode.
-
- By setting the prefix-lead to the comment-string of a
- programming language, you can embed outline-structuring in
- program code without interfering with the language processing
- of that code. See `outline-use-mode-specific-leader'
- docstring for more detail.
-PREFIX-PADDING:
- Spaces or asterisks which separate the prefix-lead and the
- bullet, according to the depth of the topic.
-BULLET: A character at the end of the topic prefix, it must be one of
- the characters listed on `outline-plain-bullets-string' or
- `outline-distinctive-bullets-string'. (See the documentation
- for these variables for more details.) The default choice of
- bullet when generating varies in a cycle with the depth of the
- topic.
-ENTRY: The text contained in a topic before any offspring.
-BODY: Same as ENTRY.
-
-
-EXPOSURE:
- The state of a topic which determines the on-screen visibility
- of its offspring and contained text.
-CONCEALED:
- Topics and entry text whose display is inhibited. Contiguous
- units of concealed text is represented by `...' ellipses.
- (Ref the `selective-display' var.)
-
- Concealed topics are effectively collapsed within an ancestor.
-CLOSED: A topic whose immediate offspring and body-text is concealed.
-OPEN: A topic that is not closed, though its offspring or body may be."
-;;;_ . Code
- (interactive "P")
-
- (let* ((active (and (not (equal major-mode 'outline))
- (outline-mode-p)))
- ; Massage universal-arg `toggle' val:
- (toggle (and toggle
- (or (and (listp toggle)(car toggle))
- toggle)))
- ; Activation specifically demanded?
- (explicit-activation (or
- ;;
- (and toggle
- (or (symbolp toggle)
- (and (natnump toggle)
- (not (zerop toggle)))))))
- ;; outline-mode already called once during this complex command?
- (same-complex-command (eq outline-v18/9-file-var-hack
- (car command-history)))
- do-layout
- )
-
- ; See comments below re v19.18,.19 bug.
- (setq outline-v18/9-file-var-hack (car command-history))
-
- (cond
-
- ;; Provision for v19.18, 19.19 bug -
- ;; Emacs v 19.18, 19.19 file-var code invokes prop-line-designated
- ;; modes twice when file is visited. We have to avoid toggling mode
- ;; off on second invocation, so we detect it as best we can, and
- ;; skip everything.
- ((and same-complex-command ; Still in same complex command
- ; as last time outline-mode invoked.
- active ; Already activated.
- (not explicit-activation) ; Prop-line file-vars don't have args.
- (string-match "^19.1[89]" ; Bug only known to be in v19.18 and
- emacs-version)); 19.19.
- t)
-
- ;; Deactivation:
- ((and (not explicit-activation)
- (or active toggle))
- ; Activation not explicitly
- ; requested, and either in
- ; active state or *de*activation
- ; specifically requested:
- (setq outline-explicitly-deactivated t)
- (if (string-match "^18\." emacs-version)
- ; Revoke those keys that remain
- ; as we set them:
- (let ((curr-loc (current-local-map)))
- (mapcar '(lambda (cell)
- (if (eq (lookup-key curr-loc (car cell))
- (car (cdr cell)))
- (define-key curr-loc (car cell)
- (assq (car cell) outline-prior-bindings))))
- outline-added-bindings)
- (outline-resumptions 'outline-added-bindings)
- (outline-resumptions 'outline-prior-bindings)))
-
- (if outline-old-style-prefixes
- (progn
- (outline-resumptions 'outline-primary-bullet)
- (outline-resumptions 'outline-old-style-prefixes)))
- (outline-resumptions 'selective-display)
- (if (and (boundp 'before-change-function) before-change-function)
- (outline-resumptions 'before-change-function))
- (setq pre-command-hook (delq 'outline-pre-command-business
- pre-command-hook))
- (setq local-write-file-hooks
- (delq 'outline-write-file-hook
- local-write-file-hooks))
- (outline-resumptions 'paragraph-start)
- (outline-resumptions 'paragraph-separate)
- (outline-resumptions (if (string-match "^18" emacs-version)
- 'auto-fill-hook
- 'auto-fill-function))
- (outline-resumptions 'outline-former-auto-filler)
- (setq outline-mode nil))
-
- ;; Activation:
- ((not active)
- (setq outline-explicitly-deactivated nil)
- (if outline-old-style-prefixes
- (progn ; Inhibit all the fancy formatting:
- (outline-resumptions 'outline-primary-bullet '("*"))
- (outline-resumptions 'outline-old-style-prefixes '(()))))
-
- (outline-infer-header-lead)
- (outline-infer-body-reindent)
-
- (set-outline-regexp)
-
- ; Produce map from current version
- ; of outline-keybindings-list:
- (if (boundp 'minor-mode-map-alist)
-
- (progn ; V19, and maybe lucid and
- ; epoch, minor-mode key bindings:
- (setq outline-mode-map
- (produce-outline-mode-map outline-keybindings-list))
- (fset 'outline-mode-map outline-mode-map)
- ; Include on minor-mode-map-alist,
- ; if not already there:
- (if (not (member '(outline-mode . outline-mode-map)
- minor-mode-map-alist))
- (setq minor-mode-map-alist
- (cons '(outline-mode . outline-mode-map)
- minor-mode-map-alist))))
-
- ; V18 minor-mode key bindings:
- ; Stash record of added bindings
- ; for later revocation:
- (outline-resumptions 'outline-added-bindings
- (list outline-keybindings-list))
- (outline-resumptions 'outline-prior-bindings
- (list (current-local-map)))
- ; and add them:
- (use-local-map (produce-outline-mode-map outline-keybindings-list
- (current-local-map)))
- )
-
- ; selective-display is the
- ; emacs conditional exposure
- ; mechanism:
- (outline-resumptions 'selective-display '(t))
- (if outline-inhibit-protection
- t
- (outline-resumptions 'before-change-function
- '(outline-before-change-protect)))
- ; Temporarily set by any outline
- ; functions that can be trusted to
- ; deal properly with concealed text.
- (add-hook 'local-write-file-hooks 'outline-write-file-hook)
- ; Custom auto-fill func, to support
- ; respect for topic headline,
- ; hanging-indents, etc:
- (let* ((fill-func-var (if (string-match "^18" emacs-version)
- 'auto-fill-hook
- 'auto-fill-function))
- (fill-func (symbol-value fill-func-var)))
- ;; Register prevailing fill func for use by outline-auto-fill:
- (outline-resumptions 'outline-former-auto-filler (list fill-func))
- ;; Register outline-auto-fill to be used if filling is active:
- (outline-resumptions fill-func-var '(outline-auto-fill)))
- ;; Paragraphs are broken by topic headlines.
- (make-local-variable 'paragraph-start)
- (outline-resumptions 'paragraph-start
- (list (concat paragraph-start "\\|\\("
- outline-regexp "\\)")))
- (make-local-variable 'paragraph-separate)
- (outline-resumptions 'paragraph-separate
- (list (concat paragraph-separate "\\|\\("
- outline-regexp "\\)")))
-
- (or (assq 'outline-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(outline-mode " Outl") minor-mode-alist)))
-
- (if outline-layout
- (setq do-layout t))
-
- (if outline-enwrap-isearch-mode
- (outline-enwrap-isearch))
-
- (run-hooks 'outline-mode-hook)
- (setq outline-mode t))
-
- ;; Reactivation:
- ((setq do-layout t)
- (outline-infer-body-reindent))
- ) ; cond
-
- (if (and do-layout
- outline-auto-activation
- (listp outline-layout)
- (and (not (eq outline-auto-activation 'activate))
- (if (eq outline-auto-activation 'ask)
- (if (y-or-n-p (format "Expose %s with layout '%s'? "
- (buffer-name)
- outline-layout))
- t
- (message "Skipped %s layout." (buffer-name))
- nil)
- t)))
- (save-excursion
- (message "Adjusting '%s' exposure..." (buffer-name))
- (goto-char 0)
- (outline-this-or-next-heading)
- (condition-case err
- (progn
- (apply 'outline-expose-topic (list outline-layout))
- (message "Adjusting '%s' exposure... done." (buffer-name)))
- ;; Problem applying exposure - notify user, but don't
- ;; interrupt, eg, file visit:
- (error (message "%s" (car (cdr err)))
- (sit-for 1)))))
- outline-mode
- ) ; let*
- ) ; defun
-
-;;;_ #3 Internal Position State-Tracking - "outline-recent-*" funcs
-;;; All the basic outline functions that directly do string matches to
-;;; evaluate heading prefix location set the variables
-;;; `outline-recent-prefix-beginning' and `outline-recent-prefix-end'
-;;; when successful. Functions starting with `outline-recent-' all
-;;; use this state, providing the means to avoid redundant searches
-;;; for just-established data. This optimization can provide
-;;; significant speed improvement, but it must be employed carefully.
-;;;_ = outline-recent-prefix-beginning
-(defvar outline-recent-prefix-beginning 0
- "Buffer point of the start of the last topic prefix encountered.")
-(make-variable-buffer-local 'outline-recent-prefix-beginning)
-;;;_ = outline-recent-prefix-end
-(defvar outline-recent-prefix-end 0
- "Buffer point of the end of the last topic prefix encountered.")
-(make-variable-buffer-local 'outline-recent-prefix-end)
-;;;_ = outline-recent-end-of-subtree
-(defvar outline-recent-end-of-subtree 0
- "Buffer point last returned by outline-end-of-current-subtree.")
-(make-variable-buffer-local 'outline-recent-end-of-subtree)
-;;;_ > outline-prefix-data (beg end)
-(defmacro outline-prefix-data (beg end)
- "Register outline-prefix state data - BEGINNING and END of prefix.
-
-For reference by `outline-recent' funcs. Returns BEGINNING."
- (` (setq outline-recent-prefix-end (, end)
- outline-recent-prefix-beginning (, beg))))
-;;;_ > outline-recent-depth ()
-(defmacro outline-recent-depth ()
- "Return depth of last heading encountered by an outline maneuvering function.
-
-All outline functions which directly do string matches to assess
-headings set the variables outline-recent-prefix-beginning and
-outline-recent-prefix-end if successful. This function uses those settings
-to return the current depth."
-
- '(max 1 (- outline-recent-prefix-end
- outline-recent-prefix-beginning
- outline-header-subtraction)))
-;;;_ > outline-recent-prefix ()
-(defmacro outline-recent-prefix ()
- "Like outline-recent-depth, but returns text of last encountered prefix.
-
-All outline functions which directly do string matches to assess
-headings set the variables outline-recent-prefix-beginning and
-outline-recent-prefix-end if successful. This function uses those settings
-to return the current depth."
- '(buffer-substring outline-recent-prefix-beginning
- outline-recent-prefix-end))
-;;;_ > outline-recent-bullet ()
-(defmacro outline-recent-bullet ()
- "Like outline-recent-prefix, but returns bullet of last encountered prefix.
-
-All outline functions which directly do string matches to assess
-headings set the variables outline-recent-prefix-beginning and
-outline-recent-prefix-end if successful. This function uses those settings
-to return the current depth of the most recently matched topic."
- '(buffer-substring (1- outline-recent-prefix-end)
- outline-recent-prefix-end))
-
-;;;_ #4 Navigation
-
-;;;_ - Position Assessment
-;;;_ : Location Predicates
-;;;_ > outline-on-current-heading-p ()
-(defun outline-on-current-heading-p ()
- "Return non-nil if point is on current visible topics' header line.
-
-Actually, returns prefix beginning point."
- (save-excursion
- (beginning-of-line)
- (and (looking-at outline-regexp)
- (outline-prefix-data (match-beginning 0) (match-end 0)))))
-;;;_ > outline-e-o-prefix-p ()
-(defun outline-e-o-prefix-p ()
- "True if point is located where current topic prefix ends, heading begins."
- (and (save-excursion (beginning-of-line)
- (looking-at outline-regexp))
- (= (point)(save-excursion (outline-end-of-prefix)(point)))))
-;;;_ > outline-hidden-p ()
-(defmacro outline-hidden-p ()
- "True if point is in hidden text."
- '(save-excursion
- (and (re-search-backward "[\n\r]" () t)
- (= ?\r (following-char)))))
-;;;_ > outline-visible-p ()
-(defmacro outline-visible-p ()
- "True if point is not in hidden text."
- (interactive)
- '(not (outline-hidden-p)))
-;;;_ : Location attributes
-;;;_ > outline-depth ()
-(defmacro outline-depth ()
- "Like outline-current-depth, but respects hidden as well as visible topics."
- '(save-excursion
- (if (outline-goto-prefix)
- (outline-recent-depth)
- (progn
- ;; Oops, no prefix, zero prefix data:
- (outline-prefix-data (point)(point))
- ;; ... and return 0:
- 0))))
-;;;_ > outline-current-depth ()
-(defmacro outline-current-depth ()
- "Return nesting depth of visible topic most immediately containing point."
- '(save-excursion
- (if (outline-back-to-current-heading)
- (max 1
- (- outline-recent-prefix-end
- outline-recent-prefix-beginning
- outline-header-subtraction))
- 0)))
-;;;_ > outline-get-current-prefix ()
-(defun outline-get-current-prefix ()
- "Topic prefix of the current topic."
- (save-excursion
- (if (outline-goto-prefix)
- (outline-recent-prefix))))
-;;;_ > outline-get-bullet ()
-(defun outline-get-bullet ()
- "Return bullet of containing topic (visible or not)."
- (save-excursion
- (and (outline-goto-prefix)
- (outline-recent-bullet))))
-;;;_ > outline-current-bullet ()
-(defun outline-current-bullet ()
- "Return bullet of current (visible) topic heading, or none if none found."
- (condition-case err
- (save-excursion
- (outline-back-to-current-heading)
- (buffer-substring (- outline-recent-prefix-end 1)
- outline-recent-prefix-end))
- ;; Quick and dirty provision, ostensibly for missing bullet:
- (args-out-of-range nil))
- )
-;;;_ > outline-get-prefix-bullet (prefix)
-(defun outline-get-prefix-bullet (prefix)
- "Return the bullet of the header prefix string PREFIX."
- ;; Doesn't make sense if we're old-style prefixes, but this just
- ;; oughtn't be called then, so forget about it...
- (if (string-match outline-regexp prefix)
- (substring prefix (1- (match-end 0)) (match-end 0))))
-
-;;;_ - Navigation macros
-;;;_ > outline-next-heading ()
-(defmacro outline-next-heading ()
- "Move to the heading for the topic \(possibly invisible) before this one.
-
-Returns the location of the heading, or nil if none found."
-
- '(if (and (bobp) (not (eobp)))
- (forward-char 1))
-
- '(if (re-search-forward outline-line-boundary-regexp nil 0)
- (progn ; Got valid location state - set vars:
- (outline-prefix-data
- (goto-char (or (match-beginning 2)
- outline-recent-prefix-beginning))
- (or (match-end 2) outline-recent-prefix-end)))))
-;;;_ : outline-this-or-next-heading
-(defun outline-this-or-next-heading ()
- "Position cursor on current or next heading."
- ;; A throwaway non-macro that is defined after outline-next-heading
- ;; and usable by outline-mode.
- (if (not (outline-goto-prefix)) (outline-next-heading)))
-;;;_ > outline-previous-heading ()
-(defmacro outline-previous-heading ()
- "Move to the prior \(possibly invisible) heading line.
-
-Return the location of the beginning of the heading, or nil if not found."
-
- '(if (bobp)
- nil
- (outline-goto-prefix)
- (if
- ;; searches are unbounded and return nil if failed:
- (or (re-search-backward outline-line-boundary-regexp nil 0)
- (looking-at outline-bob-regexp))
- (progn ; Got valid location state - set vars:
- (outline-prefix-data
- (goto-char (or (match-beginning 2)
- outline-recent-prefix-beginning))
- (or (match-end 2) outline-recent-prefix-end))))))
-
-;;;_ - Subtree Charting
-;;;_ " These routines either produce or assess charts, which are
-;;; nested lists of the locations of topics within a subtree.
-;;;
-;;; Use of charts enables efficient navigation of subtrees, by
-;;; requiring only a single regexp-search based traversal, to scope
-;;; out the subtopic locations. The chart then serves as the basis
-;;; for whatever assessment or adjustment of the subtree that is
-;;; required, without requiring redundant topic-traversal procedures.
-
-;;;_ > outline-chart-subtree (&optional levels orig-depth prev-depth)
-(defun outline-chart-subtree (&optional levels orig-depth prev-depth)
- "Produce a location \"chart\" of subtopics of the containing topic.
-
-Optional argument LEVELS specifies the depth \(relative to start
-depth\) for the chart. Subsequent optional args are not for public
-use.
-
-Charts are used to capture outline structure, so that outline-altering
-routines need assess the structure only once, and then use the chart
-for their elaborate manipulations.
-
-Topics are entered in the chart so the last one is at the car.
-The entry for each topic consists of an integer indicating the point
-at the beginning of the topic. Charts for offspring consists of a
-list containing, recursively, the charts for the respective subtopics.
-The chart for a topics' offspring precedes the entry for the topic
-itself.
-
-The other function parameters are for internal recursion, and should
-not be specified by external callers. ORIG-DEPTH is depth of topic at
-starting point, and PREV-DEPTH is depth of prior topic."
-
- (let ((original (not orig-depth)) ; `orig-depth' set only in recursion.
- chart curr-depth)
-
- (if original ; Just starting?
- ; Register initial settings and
- ; position to first offspring:
- (progn (setq orig-depth (outline-depth))
- (or prev-depth (setq prev-depth (1+ orig-depth)))
- (outline-next-heading)))
-
- ;; Loop over the current levels' siblings. Besides being more
- ;; efficient than tail-recursing over a level, it avoids exceeding
- ;; the typically quite constrained emacs max-lisp-eval-depth.
- ;; Probably would speed things up to implement loop-based stack
- ;; operation rather than recursing for lower levels. Bah.
- (while (and (not (eobp))
- ; Still within original topic?
- (< orig-depth (setq curr-depth (outline-recent-depth)))
- (cond ((= prev-depth curr-depth)
- ;; Register this one and move on:
- (setq chart (cons (point) chart))
- (if (and levels (<= levels 1))
- ;; At depth limit - skip sublevels:
- (or (outline-next-sibling curr-depth)
- ;; or no more siblings - proceed to
- ;; next heading at lesser depth:
- (while (and (<= curr-depth
- (outline-recent-depth))
- (outline-next-heading))))
- (outline-next-heading)))
-
- ((and (< prev-depth curr-depth)
- (or (not levels)
- (> levels 0)))
- ;; Recurse on deeper level of curr topic:
- (setq chart
- (cons (outline-chart-subtree (and levels
- (1- levels))
- orig-depth
- curr-depth)
- chart))
- ;; ... then continue with this one.
- )
-
- ;; ... else nil if we've ascended back to prev-depth.
-
- )))
-
- (if original ; We're at the last sibling on
- ; the original level. Position
- ; to the end of it:
- (progn (and (not (eobp)) (forward-char -1))
- (and (memq (preceding-char) '(?\n ?\^M))
- (memq (aref (buffer-substring (max 1 (- (point) 3))
- (point))
- 1)
- '(?\n ?\^M))
- (forward-char -1))
- (setq outline-recent-end-of-subtree (point))))
-
- chart ; (nreverse chart) not necessary,
- ; and maybe not preferable.
- ))
-;;;_ > outline-chart-siblings (&optional start end)
-(defun outline-chart-siblings (&optional start end)
- "Produce a list of locations of this and succeeding sibling topics.
-Effectively a top-level chart of siblings. See `outline-chart-subtree'
-for an explanation of charts."
- (save-excursion
- (if (outline-goto-prefix)
- (let ((chart (list (point))))
- (while (outline-next-sibling)
- (setq chart (cons (point) chart)))
- (if chart (setq chart (nreverse chart)))))))
-;;;_ > outline-chart-to-reveal (chart depth)
-(defun outline-chart-to-reveal (chart depth)
-
- "Return a flat list of hidden points in subtree CHART, up to DEPTH.
-
-Note that point can be left at any of the points on chart, or at the
-start point."
-
- (let (result here)
- (while (and (or (eq depth t) (> depth 0))
- chart)
- (setq here (car chart))
- (if (listp here)
- (let ((further (outline-chart-to-reveal here (or (eq depth t)
- (1- depth)))))
- ;; We're on the start of a subtree - recurse with it, if there's
- ;; more depth to go:
- (if further (setq result (append further result)))
- (setq chart (cdr chart)))
- (goto-char here)
- (if (= (preceding-char) ?\r)
- (setq result (cons here result)))
- (setq chart (cdr chart))))
- result))
-;;;_ X outline-chart-spec (chart spec &optional exposing)
-(defun outline-chart-spec (chart spec &optional exposing)
- "Not yet \(if ever\) implemented.
-
-Produce exposure directives given topic/subtree CHART and an exposure SPEC.
-
-Exposure spec indicates the locations to be exposed and the prescribed
-exposure status. Optional arg EXPOSING is an integer, with 0
-indicating pending concealment, anything higher indicating depth to
-which subtopic headers should be exposed, and negative numbers
-indicating (negative of) the depth to which subtopic headers and
-bodies should be exposed.
-
-The produced list can have two types of entries. Bare numbers
-indicate points in the buffer where topic headers that should be
-exposed reside.
-
- - bare negative numbers indicates that the topic starting at the
- point which is the negative of the number should be opened,
- including their entries.
- - bare positive values indicate that this topic header should be
- opened.
- - Lists signify the beginning and end points of regions that should
- be flagged, and the flag to employ. (For concealment: `\(\?r\)', and
- exposure:"
- (while spec
- (cond ((listp spec)
- )
- )
- (setq spec (cdr spec)))
- )
-
-;;;_ - Within Topic
-;;;_ > outline-goto-prefix ()
-(defun outline-goto-prefix ()
- "Put point at beginning of outline prefix for immediately containing topic.
-
-Goes to first subsequent topic if none immediately containing.
-
-Not sensitive to topic visibility.
-
-Returns a the point at the beginning of the prefix, or nil if none."
-
- (let (done)
- (while (and (not done)
- (re-search-backward "[\n\r]" nil 1))
- (forward-char 1)
- (if (looking-at outline-regexp)
- (setq done (outline-prefix-data (match-beginning 0)
- (match-end 0)))
- (forward-char -1)))
- (if (bobp)
- (cond ((looking-at outline-regexp)
- (outline-prefix-data (match-beginning 0)(match-end 0)))
- ((outline-next-heading)
- (outline-prefix-data (match-beginning 0)(match-end 0)))
- (done))
- done)))
-;;;_ > outline-end-of-prefix ()
-(defun outline-end-of-prefix (&optional ignore-decorations)
- "Position cursor at beginning of header text.
-
-If optional IGNORE-DECORATIONS is non-nil, put just after bullet,
-otherwise skip white space between bullet and ensuing text."
-
- (if (not (outline-goto-prefix))
- nil
- (let ((match-data (match-data)))
- (goto-char (match-end 0))
- (if ignore-decorations
- t
- (while (looking-at "[0-9]") (forward-char 1))
- (if (and (not (eolp)) (looking-at "\\s-")) (forward-char 1)))
- (store-match-data match-data))
- ;; Reestablish where we are:
- (outline-current-depth)))
-;;;_ > outline-current-bullet-pos ()
-(defun outline-current-bullet-pos ()
- "Return position of current \(visible) topic's bullet."
-
- (if (not (outline-current-depth))
- nil
- (1- (match-end 0))))
-;;;_ > outline-back-to-current-heading ()
-(defun outline-back-to-current-heading ()
- "Move to heading line of current topic, or beginning if already on the line."
-
- (beginning-of-line)
- (prog1 (or (outline-on-current-heading-p)
- (and (re-search-backward (concat "^\\(" outline-regexp "\\)")
- nil
- 'move)
- (outline-prefix-data (match-beginning 1)(match-end 1))))
- (if (interactive-p) (outline-end-of-prefix))))
-;;;_ > outline-pre-next-preface ()
-(defun outline-pre-next-preface ()
- "Skip forward to just before the next heading line.
-
-Returns that character position."
-
- (if (re-search-forward outline-line-boundary-regexp nil 'move)
- (prog1 (goto-char (match-beginning 0))
- (outline-prefix-data (match-beginning 2)(match-end 2)))))
-;;;_ > outline-end-of-current-subtree ()
-(defun outline-end-of-current-subtree ()
- "Put point at the end of the last leaf in the currently visible topic."
- (interactive)
- (outline-back-to-current-heading)
- (let ((level (outline-recent-depth)))
- (outline-next-heading)
- (while (and (not (eobp))
- (> (outline-recent-depth) level))
- (outline-next-heading))
- (and (not (eobp)) (forward-char -1))
- (and (memq (preceding-char) '(?\n ?\^M))
- (memq (aref (buffer-substring (max 1 (- (point) 3)) (point)) 1)
- '(?\n ?\^M))
- (forward-char -1))
- (setq outline-recent-end-of-subtree (point))))
-;;;_ > outline-beginning-of-current-entry ()
-(defun outline-beginning-of-current-entry ()
- "When not already there, position point at beginning of current topic's body.
-
-If already there, move cursor to bullet for hot-spot operation.
-\(See outline-mode doc string for details on hot-spot operation.)"
- (interactive)
- (let ((start-point (point)))
- (outline-end-of-prefix)
- (if (and (interactive-p)
- (= (point) start-point))
- (goto-char (outline-current-bullet-pos)))))
-;;;_ > outline-end-of-current-entry ()
-(defun outline-end-of-current-entry ()
- "Position the point at the end of the current topics' entry."
- (interactive)
- (outline-show-entry)
- (prog1 (outline-pre-next-preface)
- (if (and (not (bobp))(looking-at "^$"))
- (forward-char -1))))
-
-;;;_ - Depth-wise
-;;;_ > outline-ascend-to-depth (depth)
-(defun outline-ascend-to-depth (depth)
- "Ascend to depth DEPTH, returning depth if successful, nil if not."
- (if (and (> depth 0)(<= depth (outline-depth)))
- (let ((last-good (point)))
- (while (and (< depth (outline-depth))
- (setq last-good (point))
- (outline-beginning-of-level)
- (outline-previous-heading)))
- (if (= (outline-recent-depth) depth)
- (progn (goto-char outline-recent-prefix-beginning)
- depth)
- (goto-char last-good)
- nil))
- (if (interactive-p) (outline-end-of-prefix))))
-;;;_ > outline-descend-to-depth (depth)
-(defun outline-descend-to-depth (depth)
- "Descend to depth DEPTH within current topic.
-
-Returning depth if successful, nil if not."
- (let ((start-point (point))
- (start-depth (outline-depth)))
- (while
- (and (> (outline-depth) 0)
- (not (= depth (outline-recent-depth))) ; ... not there yet
- (outline-next-heading) ; ... go further
- (< start-depth (outline-recent-depth)))) ; ... still in topic
- (if (and (> (outline-depth) 0)
- (= (outline-recent-depth) depth))
- depth
- (goto-char start-point)
- nil))
- )
-;;;_ > outline-up-current-level (arg &optional dont-complain)
-(defun outline-up-current-level (arg &optional dont-complain)
- "Move out ARG levels from current visible topic.
-
-Positions on heading line of containing topic. Error if unable to
-ascend that far, or nil if unable to ascend but optional arg
-DONT-COMPLAIN is non-nil."
- (interactive "p")
- (outline-back-to-current-heading)
- (let ((present-level (outline-recent-depth))
- (last-good (point))
- failed
- return)
- ;; Loop for iterating arg:
- (while (and (> (outline-recent-depth) 1)
- (> arg 0)
- (not (bobp))
- (not failed))
- (setq last-good (point))
- ;; Loop for going back over current or greater depth:
- (while (and (not (< (outline-recent-depth) present-level))
- (or (outline-previous-visible-heading 1)
- (not (setq failed present-level)))))
- (setq present-level (outline-current-depth))
- (setq arg (- arg 1)))
- (if (or failed
- (> arg 0))
- (progn (goto-char last-good)
- (if (interactive-p) (outline-end-of-prefix))
- (if (not dont-complain)
- (error "Can't ascend past outermost level.")
- (if (interactive-p) (outline-end-of-prefix))
- nil))
- (if (interactive-p) (outline-end-of-prefix))
- outline-recent-prefix-beginning)))
-
-;;;_ - Linear
-;;;_ > outline-next-sibling (&optional depth backward)
-(defun outline-next-sibling (&optional depth backward)
- "Like outline-forward-current-level, but respects invisible topics.
-
-Traverse at optional DEPTH, or current depth if none specified.
-
-Go backward if optional arg BACKWARD is non-nil.
-
-Return depth if successful, nil otherwise."
-
- (if (and backward (bobp))
- nil
- (let ((start-depth (or depth (outline-depth)))
- (start-point (point))
- last-depth)
- (while (and (not (if backward (bobp) (eobp)))
- (if backward (outline-previous-heading)
- (outline-next-heading))
- (> (setq last-depth (outline-recent-depth)) start-depth)))
- (if (and (not (eobp))
- (and (> (or last-depth (outline-depth)) 0)
- (= (outline-recent-depth) start-depth)))
- outline-recent-prefix-beginning
- (goto-char start-point)
- (if depth (outline-depth) start-depth)
- nil))))
-;;;_ > outline-previous-sibling (&optional depth backward)
-(defun outline-previous-sibling (&optional depth backward)
- "Like outline-forward-current-level,but backwards & respect invisible topics.
-
-Optional DEPTH specifies depth to traverse, default current depth.
-
-Optional BACKWARD reverses direction.
-
-Return depth if successful, nil otherwise."
- (outline-next-sibling depth (not backward))
- )
-;;;_ > outline-snug-back ()
-(defun outline-snug-back ()
- "Position cursor at end of previous topic
-
-Presumes point is at the start of a topic prefix."
- (if (or (bobp) (eobp))
- nil
- (forward-char -1))
- (if (or (bobp) (not (memq (preceding-char) '(?\n ?\^M))))
- nil
- (forward-char -1)
- (if (or (bobp) (not (memq (preceding-char) '(?\n ?\^M))))
- (forward-char -1)))
- (point))
-;;;_ > outline-beginning-of-level ()
-(defun outline-beginning-of-level ()
- "Go back to the first sibling at this level, visible or not."
- (outline-end-of-level 'backward))
-;;;_ > outline-end-of-level (&optional backward)
-(defun outline-end-of-level (&optional backward)
- "Go to the last sibling at this level, visible or not."
-
- (let ((depth (outline-depth)))
- (while (outline-previous-sibling depth nil))
- (prog1 (outline-recent-depth)
- (if (interactive-p) (outline-end-of-prefix)))))
-;;;_ > outline-next-visible-heading (arg)
-(defun outline-next-visible-heading (arg)
- "Move to the next ARG'th visible heading line, backward if arg is negative.
-
-Move as far as possible in indicated direction \(beginning or end of
-buffer\) if headings are exhausted."
-
- (interactive "p")
- (let* ((backward (if (< arg 0) (setq arg (* -1 arg))))
- (step (if backward -1 1))
- (start-point (point))
- prev got)
-
- (while (> arg 0) ; limit condition
- (while (and (not (if backward (bobp)(eobp))) ; boundary condition
- ;; Move, skipping over all those concealed lines:
- (< -1 (forward-line step))
- (not (setq got (looking-at outline-regexp)))))
- ;; Register this got, it may be the last:
- (if got (setq prev got))
- (setq arg (1- arg)))
- (cond (got ; Last move was to a prefix:
- (outline-prefix-data (match-beginning 0) (match-end 0))
- (outline-end-of-prefix))
- (prev ; Last move wasn't, but prev was:
- (outline-prefix-data (match-beginning 0) (match-end 0)))
- ((not backward) (end-of-line) nil))))
-;;;_ > outline-previous-visible-heading (arg)
-(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)."
- (interactive "p")
- (outline-next-visible-heading (- arg)))
-;;;_ > outline-forward-current-level (arg)
-(defun outline-forward-current-level (arg)
- "Position point at the next heading of the same level.
-
-Takes optional repeat-count, goes backward if count is negative.
-
-Returns resulting position, else nil if none found."
- (interactive "p")
- (let ((start-depth (outline-current-depth))
- (start-point (point))
- (start-arg arg)
- (backward (> 0 arg))
- last-depth
- (last-good (point))
- at-boundary)
- (if (= 0 start-depth)
- (error "No siblings, not in a topic..."))
- (if backward (setq arg (* -1 arg)))
- (while (not (or (zerop arg)
- at-boundary))
- (while (and (not (if backward (bobp) (eobp)))
- (if backward (outline-previous-visible-heading 1)
- (outline-next-visible-heading 1))
- (> (setq last-depth (outline-recent-depth)) start-depth)))
- (if (and last-depth (= last-depth start-depth)
- (not (if backward (bobp) (eobp))))
- (setq last-good (point)
- arg (1- arg))
- (setq at-boundary t)))
- (if (and (not (eobp))
- (= arg 0)
- (and (> (or last-depth (outline-depth)) 0)
- (= (outline-recent-depth) start-depth)))
- outline-recent-prefix-beginning
- (goto-char last-good)
- (if (not (interactive-p))
- nil
- (outline-end-of-prefix)
- (error "Hit %s level %d topic, traversed %d of %d requested."
- (if backward "first" "last")
- (outline-recent-depth)
- (- (abs start-arg) arg)
- (abs start-arg))))))
-;;;_ > outline-backward-current-level (arg)
-(defun outline-backward-current-level (arg)
- "Inverse of `outline-forward-current-level'."
- (interactive "p")
- (if (interactive-p)
- (let ((current-prefix-arg (* -1 arg)))
- (call-interactively 'outline-forward-current-level))
- (outline-forward-current-level (* -1 arg))))
-
-;;;_ #5 Alteration
-
-;;;_ - Fundamental
-;;;_ > outline-before-change-protect (beg end)
-(defun outline-before-change-protect (beg end)
- "Outline before-change hook, regulates changes to concealed text.
-
-Reveal concealed text that would be changed by current command, and
-offer user choice to commit or forego the change. Unchanged text is
-reconcealed. User has option to have changed text reconcealed.
-
-Undo commands are specially treated - the user is not prompted for
-choice, the undoes are always committed (based on presumption that the
-things being undone were already subject to this regulation routine),
-and undoes always leave the changed stuff exposed.
-
-Changes to concealed regions are ignored while file is being written.
-\(This is for the sake of functions that do change the file during
-writes, like crypt and zip modes.)
-
-Locally bound in outline buffers to `before-change-function', which
-in emacs 19 is run before any change to the buffer. (Has no effect
-in Emacs 18, which doesn't support before-change-function.)
-
-Any functions which set [`this-command' to `undo', or which set]
-`outline-override-protect' non-nil (as does, eg, outline-flag-chars)
-are exempt from this restriction."
- (if (and (outline-mode-p)
- ; outline-override-protect
- ; set by functions that know what
- ; they're doing, eg outline internals:
- (not outline-override-protect)
- (not outline-during-write-cue)
- (save-match-data ; Preserve operation position state.
- ; Both beginning and end chars must
- ; be exposed:
- (save-excursion (if (memq this-command '(newline open-line))
- ;; Compensate for stupid emacs {new,
- ;; open-}line display optimization:
- (setq beg (1+ beg)
- end (1+ end)))
- (goto-char beg)
- (or (outline-hidden-p)
- (and (not (= beg end))
- (goto-char end)
- (outline-hidden-p))))))
- (save-match-data
- (if (equal this-command 'undo)
- ;; Allow undo without inhibition.
- ;; - Undoing new and open-line hits stupid emacs redisplay
- ;; optimization (em 19 cmds.c, ~ line 200).
- ;; - Presumably, undoing what was properly protected when
- ;; done.
- ;; - Undo may be users' only recourse in protection faults.
- ;; So, expose what getting changed:
- (progn (message "Undo! - exposing concealed target...")
- (if (outline-hidden-p)
- (outline-show-children))
- (message "Undo!"))
- (let (response
- (rehide-completely (save-excursion (outline-goto-prefix)
- (outline-hidden-p)))
- rehide-place)
-
- (save-excursion
- (if (condition-case err
- ;; Condition case to catch keyboard quits during reads.
- (progn
- ; Give them a peek where
- (save-excursion
- (if (eolp) (setq rehide-place
- (outline-goto-prefix)))
- (outline-show-entry))
- ; Present the message, but...
- ; leave the cursor at the location
- ; until they respond:
- ; Then interpret the response:
- (while
- (progn
- (message (concat "Change inside concealed"
- " region - do it? "
- "(n or 'y'/'r'eclose)"))
- (setq response (read-char))
- (not
- (cond ((memq response '(?r ?R))
- (setq response 'reclose))
- ((memq response '(?y ?Y ? ))
- (setq response t))
- ((memq response '(?n ?N 127))
- (setq response nil)
- t)
- ((eq response ??)
- (message
- "`r' means `yes, then reclose'")
- nil)
- (t (message "Please answer y, n, or r")
- (sit-for 1)
- nil)))))
- response)
- (quit nil))
- ; Continue:
- (if (eq response 'reclose)
- (save-excursion
- (if rehide-place (goto-char rehide-place))
- (if rehide-completely
- (outline-hide-current-entry-completely)
- (outline-hide-current-entry)))
- (if (outline-ascend-to-depth (1- (outline-recent-depth)))
- (outline-show-children)
- (outline-show-to-offshoot)))
- ; Prevent:
- (if rehide-completely
- (save-excursion
- (if rehide-place (goto-char rehide-place))
- (outline-hide-current-entry-completely))
- (outline-hide-current-entry))
- (error (concat
- "Change within concealed region prevented.")))))))
- ) ; if
- ) ; defun
-;;;_ = outline-post-goto-bullet
-(defvar outline-post-goto-bullet nil
- "Outline internal var, for `outline-pre-command-business' hot-spot operation.
-
-When set, tells post-processing to reposition on topic bullet, and
-then unset it. Set by outline-pre-command-business when implementing
-hot-spot operation, where literal characters typed over a topic bullet
-are mapped to the command of the corresponding control-key on the
-outline-mode-map.")
-(make-variable-buffer-local 'outline-post-goto-bullet)
-;;;_ > outline-post-command-business ()
-(defun outline-post-command-business ()
- "Outline post-command-hook function.
-
-- Null outline-override-protect, so it's not left open.
-
-- Implement (and clear) outline-post-goto-bullet, for hot-spot
- outline commands.
-
-- Massages buffer-undo-list so successive, standard character self-inserts are
- aggregated. This kludge compensates for lack of undo bunching when
- before-change-function is used."
-
- ; Apply any external change func:
- (if (not (outline-mode-p)) ; In outline-mode.
- nil
- (setq outline-override-protect nil)
- (if outline-during-write-cue
- ;; Was used by outline-before-change-protect, done with it now:
- (setq outline-during-write-cue nil))
- ;; Undo bunching business:
- (if (and (listp buffer-undo-list) ; Undo history being kept.
- (equal this-command 'self-insert-command)
- (equal last-command 'self-insert-command))
- (let* ((prev-stuff (cdr buffer-undo-list))
- (before-prev-stuff (cdr (cdr prev-stuff)))
- cur-cell cur-from cur-to
- prev-cell prev-from prev-to)
- (if (and before-prev-stuff ; Goes back far enough to bother,
- (not (car prev-stuff)) ; and break before current,
- (not (car before-prev-stuff)) ; !and break before prev!
- (setq prev-cell (car (cdr prev-stuff))) ; contents now,
- (setq cur-cell (car buffer-undo-list)) ; contents prev.
-
- ;; cur contents denote a single char insertion:
- (numberp (setq cur-from (car cur-cell)))
- (numberp (setq cur-to (cdr cur-cell)))
- (= 1 (- cur-to cur-from))
-
- ;; prev contents denote fewer than aggregate-limit
- ;; insertions:
- (numberp (setq prev-from (car prev-cell)))
- (numberp (setq prev-to (cdr prev-cell)))
- ; Below threshold:
- (> outline-undo-aggregation (- prev-to prev-from)))
- (setq buffer-undo-list
- (cons (cons prev-from cur-to)
- (cdr (cdr (cdr buffer-undo-list))))))))
- ;; Implement -post-goto-bullet, if set: (must be after undo business)
- (if (and outline-post-goto-bullet
- (outline-current-bullet-pos))
- (progn (goto-char (outline-current-bullet-pos))
- (setq outline-post-goto-bullet nil)))
- ))
-;;;_ > outline-pre-command-business ()
-(defun outline-pre-command-business ()
- "Outline pre-command-hook function for outline buffers.
-
-Implements special behavior when cursor is on bullet char.
-
-Self-insert characters are reinterpreted control-character references
-into the outline-mode-map. The outline-mode post-command hook will
-position a cursor that has moved as a result of such reinterpretation,
-on the destination topic's bullet, when the cursor wound up in the
-
-The upshot is that you can get easy, single (unmodified) key outline
-maneuvering and general operations by positioning the cursor on the
-bullet char, and it continues until you deliberately some non-outline
-motion command to relocate the cursor off of a bullet char."
-
- (if (and (boundp 'outline-mode)
- outline-mode
- (eq this-command 'self-insert-command)
- (eq (point)(outline-current-bullet-pos)))
-
- (let* ((this-key-num (if (numberp last-command-event)
- last-command-event))
- mapped-binding)
-
- ; Map upper-register literals
- ; to lower register:
- (if (<= 96 this-key-num)
- (setq this-key-num (- this-key-num 32)))
- ; Check if we have a literal:
- (if (and (<= 64 this-key-num)
- (>= 96 this-key-num))
- (setq mapped-binding
- (lookup-key 'outline-mode-map
- (concat outline-command-prefix
- (char-to-string (- this-key-num 64))))))
- (if mapped-binding
- (setq outline-post-goto-bullet t
- this-command mapped-binding)))))
-;;;_ > outline-find-file-hook ()
-(defun outline-find-file-hook ()
- "Activate outline-mode when `outline-auto-activation' & `outline-layout' are non-nil.
-
-See `outline-init' for setup instructions."
- (if (and outline-auto-activation
- (not (outline-mode-p))
- outline-layout)
- (outline-mode t)))
-;;;_ : Establish the hooks
-(add-hook 'post-command-hook 'outline-post-command-business)
-(add-hook 'pre-command-hook 'outline-pre-command-business)
-
-;;;_ - Topic Format Assessment
-;;;_ > outline-solicit-alternate-bullet (depth &optional current-bullet)
-(defun outline-solicit-alternate-bullet (depth &optional current-bullet)
-
- "Prompt for and return a bullet char as an alternative to the current one.
-
-Offer one suitable for current depth DEPTH as default."
-
- (let* ((default-bullet (or current-bullet
- (outline-bullet-for-depth depth)))
- (sans-escapes (regexp-sans-escapes outline-bullets-string))
- (choice (solicit-char-in-string
- (format "Select bullet: %s ('%s' default): "
- sans-escapes
- default-bullet)
- sans-escapes
- t)))
- (if (string= choice "") default-bullet choice))
- )
-;;;_ > outline-sibling-index (&optional depth)
-(defun outline-sibling-index (&optional depth)
- "Item number of this prospective topic among its siblings.
-
-If optional arg depth is greater than current depth, then we're
-opening a new level, and return 0.
-
-If less than this depth, ascend to that depth and count..."
-
- (save-excursion
- (cond ((and depth (<= depth 0) 0))
- ((or (not depth) (= depth (outline-depth)))
- (let ((index 1))
- (while (outline-previous-sibling (outline-recent-depth) nil)
- (setq index (1+ index)))
- index))
- ((< depth (outline-recent-depth))
- (outline-ascend-to-depth depth)
- (outline-sibling-index))
- (0))))
-;;;_ > outline-distinctive-bullet (bullet)
-(defun outline-distinctive-bullet (bullet)
- "True if bullet is one of those on outline-distinctive-bullets-string."
- (string-match (regexp-quote bullet) outline-distinctive-bullets-string))
-;;;_ > outline-numbered-type-prefix (&optional prefix)
-(defun outline-numbered-type-prefix (&optional prefix)
- "True if current header prefix bullet is numbered bullet."
- (and outline-numbered-bullet
- (string= outline-numbered-bullet
- (if prefix
- (outline-get-prefix-bullet prefix)
- (outline-get-bullet)))))
-;;;_ > outline-bullet-for-depth (&optional depth)
-(defun outline-bullet-for-depth (&optional depth)
- "Return outline topic bullet suited to optional DEPTH, or current depth."
- ;; Find bullet in plain-bullets-string modulo DEPTH.
- (if outline-stylish-prefixes
- (char-to-string (aref outline-plain-bullets-string
- (% (max 0 (- depth 2))
- outline-plain-bullets-string-len)))
- outline-primary-bullet)
- )
-
-;;;_ - Topic Production
-;;;_ > outline-make-topic-prefix (&optional prior-bullet
-(defun outline-make-topic-prefix (&optional prior-bullet
- new
- depth
- solicit
- number-control
- index)
- ;; Depth null means use current depth, non-null means we're either
- ;; opening a new topic after current topic, lower or higher, or we're
- ;; changing level of current topic.
- ;; Solicit dominates specified bullet-char.
-;;;_ . Doc string:
- "Generate a topic prefix suitable for optional arg DEPTH, or current depth.
-
-All the arguments are optional.
-
-PRIOR-BULLET indicates the bullet of the prefix being changed, or
-nil if none. This bullet may be preserved (other options
-notwithstanding) if it is on the outline-distinctive-bullets-string,
-for instance.
-
-Second arg NEW indicates that a new topic is being opened after the
-topic at point, if non-nil. Default bullet for new topics, eg, may
-be set (contingent to other args) to numbered bullets if previous
-sibling is one. The implication otherwise is that the current topic
-is being adjusted - shifted or rebulleted - and we don't consider
-bullet or previous sibling.
-
-Third arg DEPTH forces the topic prefix to that depth, regardless of
-the current topics' depth.
-
-Fourth arg SOLICIT non-nil provokes solicitation from the user of a
-choice among the valid bullets. (This overrides other all the
-options, including, eg, a distinctive PRIOR-BULLET.)
-
-Fifth arg, NUMBER-CONTROL, matters only if `outline-numbered-bullet'
-is non-nil *and* soliciting was not explicitly invoked. Then
-NUMBER-CONTROL non-nil forces prefix to either numbered or
-denumbered format, depending on the value of the sixth arg, INDEX.
-
-\(Note that NUMBER-CONTROL does *not* apply to level 1 topics. Sorry...)
-
-If NUMBER-CONTROL is non-nil and sixth arg INDEX is non-nil then
-the prefix of the topic is forced to be numbered. Non-nil
-NUMBER-CONTROL and nil INDEX forces non-numbered format on the
-bullet. Non-nil NUMBER-CONTROL and non-nil, non-number INDEX means
-that the index for the numbered prefix will be derived, by counting
-siblings back to start of level. If INDEX is a number, then that
-number is used as the index for the numbered prefix (allowing, eg,
-sequential renumbering to not require this function counting back the
-index for each successive sibling)."
-;;;_ . Code:
- ;; The options are ordered in likely frequence of use, most common
- ;; highest, least lowest. Ie, more likely to be doing prefix
- ;; adjustments than soliciting, and yet more than numbering.
- ;; Current prefix is least dominant, but most likely to be commonly
- ;; specified...
-
- (let* (body
- numbering
- denumbering
- (depth (or depth (outline-depth)))
- (header-lead outline-header-prefix)
- (bullet-char
-
- ;; Getting value for bullet char is practically the whole job:
-
- (cond
- ; Simplest situation - level 1:
- ((<= depth 1) (setq header-lead "") outline-primary-bullet)
- ; Simple, too: all asterisks:
- (outline-old-style-prefixes
- ;; Cheat - make body the whole thing, null out header-lead and
- ;; bullet-char:
- (setq body (make-string depth
- (string-to-char outline-primary-bullet)))
- (setq header-lead "")
- "")
-
- ;; (Neither level 1 nor old-style, so we're space padding.
- ;; Sneak it in the condition of the next case, whatever it is.)
-
- ;; Solicitation overrides numbering and other cases:
- ((progn (setq body (make-string (- depth 2) ?\ ))
- ;; The actual condition:
- solicit)
- (let* ((got (outline-solicit-alternate-bullet depth)))
- ;; Gotta check whether we're numbering and got a numbered bullet:
- (setq numbering (and outline-numbered-bullet
- (not (and number-control (not index)))
- (string= got outline-numbered-bullet)))
- ;; Now return what we got, regardless:
- got))
-
- ;; Numbering invoked through args:
- ((and outline-numbered-bullet number-control)
- (if (setq numbering (not (setq denumbering (not index))))
- outline-numbered-bullet
- (if (and prior-bullet
- (not (string= outline-numbered-bullet
- prior-bullet)))
- prior-bullet
- (outline-bullet-for-depth depth))))
-
- ;;; Neither soliciting nor controlled numbering ;;;
- ;;; (may be controlled denumbering, tho) ;;;
-
- ;; Check wrt previous sibling:
- ((and new ; only check for new prefixes
- (<= depth (outline-depth))
- outline-numbered-bullet ; ... & numbering enabled
- (not denumbering)
- (let ((sibling-bullet
- (save-excursion
- ;; Locate correct sibling:
- (or (>= depth (outline-depth))
- (outline-ascend-to-depth depth))
- (outline-get-bullet))))
- (if (and sibling-bullet
- (string= outline-numbered-bullet sibling-bullet))
- (setq numbering sibling-bullet)))))
-
- ;; Distinctive prior bullet?
- ((and prior-bullet
- (outline-distinctive-bullet prior-bullet)
- ;; Either non-numbered:
- (or (not (and outline-numbered-bullet
- (string= prior-bullet outline-numbered-bullet)))
- ;; or numbered, and not denumbering:
- (setq numbering (not denumbering)))
- ;; Here 'tis:
- prior-bullet))
-
- ;; Else, standard bullet per depth:
- ((outline-bullet-for-depth depth)))))
-
- (concat header-lead
- body
- bullet-char
- (if numbering
- (format "%d" (cond ((and index (numberp index)) index)
- (new (1+ (outline-sibling-index depth)))
- ((outline-sibling-index))))))
- )
- )
-;;;_ > outline-open-topic (relative-depth &optional before)
-(defun outline-open-topic (relative-depth &optional before)
- "Open a new topic at depth DEPTH.
-
-New topic is situated after current one, unless optional flag BEFORE
-is non-nil, or unless current line is complete empty (not even
-whitespace), in which case open is done on current line.
-
-Nuances:
-
-- Creation of new topics is with respect to the visible topic
- containing the cursor, regardless of intervening concealed ones.
-
-- New headers are generally created after/before the body of a
- topic. However, they are created right at cursor location if the
- cursor is on a blank line, even if that breaks the current topic
- body. This is intentional, to provide a simple means for
- deliberately dividing topic bodies.
-
-- Double spacing of topic lists is preserved. Also, the first
- level two topic is created double-spaced (and so would be
- subsequent siblings, if that's left intact). Otherwise,
- single-spacing is used.
-
-- Creation of sibling or nested topics is with respect to the topic
- you're starting from, even when creating backwards. This way you
- can easily create a sibling in front of the current topic without
- having to go to its preceding sibling, and then open forward
- from there."
-
- (let* ((depth (+ (outline-current-depth) relative-depth))
- (opening-on-blank (if (looking-at "^\$")
- (not (setq before nil))))
- opening-numbered ; Will get while computing ref-topic, below
- ref-depth ; Will get while computing ref-topic, next
- (ref-topic (save-excursion
- (cond ((< relative-depth 0)
- (outline-ascend-to-depth depth))
- ((>= relative-depth 1) nil)
- (t (outline-back-to-current-heading)))
- (setq ref-depth (outline-recent-depth))
- (setq opening-numbered
- (save-excursion
- (and outline-numbered-bullet
- (or (<= relative-depth 0)
- (outline-descend-to-depth depth))
- (if (outline-numbered-type-prefix)
- outline-numbered-bullet))))
- (point)))
- dbl-space
- doing-beginning)
-
- (if (not opening-on-blank)
- ; Positioning and vertical
- ; padding - only if not
- ; opening-on-blank:
- (progn
- (goto-char ref-topic)
- (setq dbl-space ; Determine double space action:
- (or (and (<= relative-depth 0) ; not descending;
- (save-excursion
- ;; at b-o-b or preceded by a blank line?
- (or (> 0 (forward-line -1))
- (looking-at "^\\s-*$")
- (bobp)))
- (save-excursion
- ;; succeeded by a blank line?
- (outline-end-of-current-subtree)
- (bolp)))
- (and (= ref-depth 1)
- (or before
- (= depth 1)
- (save-excursion
- ;; Don't already have following
- ;; vertical padding:
- (not (outline-pre-next-preface)))))))
-
- ; Position to prior heading,
- ; if inserting backwards, and
- ; not going outwards:
- (if (and before (>= relative-depth 0))
- (progn (outline-back-to-current-heading)
- (setq doing-beginning (bobp))
- (if (not (bobp))
- (outline-previous-heading)))
- (if (and before (bobp))
- (outline-unprotected (open-line 1))))
-
- (if (<= relative-depth 0)
- ;; Not going inwards, don't snug up:
- (if doing-beginning
- (outline-unprotected (open-line (if dbl-space 2 1)))
- (if before
- (progn (end-of-line)
- (outline-pre-next-preface)
- (while (= ?\r (following-char))
- (forward-char 1))
- (if (not (looking-at "^$"))
- (outline-unprotected (open-line 1))))
- (outline-end-of-current-subtree)))
- ;; Going inwards - double-space if first offspring is,
- ;; otherwise snug up.
- (end-of-line) ; So we skip any concealed progeny.
- (outline-pre-next-preface)
- (if (bolp)
- ;; Blank lines between current header body and next
- ;; header - get to last substantive (non-white-space)
- ;; line in body:
- (re-search-backward "[^ \t\n]" nil t))
- (if (save-excursion
- (outline-next-heading)
- (if (> (outline-recent-depth) ref-depth)
- ;; This is an offspring.
- (progn (forward-line -1)
- (looking-at "^\\s-*$"))))
- (progn (forward-line 1)
- (outline-unprotected (open-line 1))))
- (end-of-line))
- ;;(if doing-beginning (goto-char doing-beginning))
- (if (not (bobp))
- (progn (if (and (not (> depth ref-depth))
- (not before))
- (outline-unprotected (open-line 1))
- (if (> depth ref-depth)
- (outline-unprotected (newline 1))
- (if dbl-space
- (outline-unprotected (open-line 1))
- (if (not before)
- (outline-unprotected (newline 1))))))
- (if dbl-space
- (outline-unprotected (newline 1)))
- (if (and (not (eobp))
- (not (bolp)))
- (forward-char 1))))
- ))
- (insert-string (concat (outline-make-topic-prefix opening-numbered
- t
- depth)
- " "))
-
- ;;(if doing-beginning (save-excursion (newline (if dbl-space 2 1))))
-
-
- (outline-rebullet-heading nil ;;; solicit
- depth ;;; depth
- nil ;;; number-control
- nil ;;; index
- t) (end-of-line)
- )
- )
-;;;_ . open-topic contingencies
-;;;_ ; base topic - one from which open was issued
-;;;_ , beginning char
-;;;_ , amount of space before will be used, unless opening in place
-;;;_ , end char will be used, unless opening before (and it still may)
-;;;_ ; absolute depth of new topic
-;;;_ ! insert in place - overrides most stuff
-;;;_ ; relative depth of new re base
-;;;_ ; before or after base topic
-;;;_ ; spacing around topic, if any, prior to new topic and at same depth
-;;;_ ; buffer boundaries - special provisions for beginning and end ob
-;;;_ ; level 1 topics have special provisions also - double space.
-;;;_ ; location of new topic
-;;;_ .
-;;;_ > outline-open-subtopic (arg)
-(defun outline-open-subtopic (arg)
- "Open new topic header at deeper level than the current one.
-
-Negative universal arg means to open deeper, but place the new topic
-prior to the current one."
- (interactive "p")
- (outline-open-topic 1 (> 0 arg)))
-;;;_ > outline-open-sibtopic (arg)
-(defun outline-open-sibtopic (arg)
- "Open new topic header at same level as the current one.
-
-Negative universal arg means to place the new topic prior to the current
-one."
- (interactive "p")
- (outline-open-topic 0 (> 0 arg)))
-;;;_ > outline-open-supertopic (arg)
-(defun outline-open-supertopic (arg)
- "Open new topic header at shallower level than the current one.
-
-Negative universal arg means to open shallower, but place the new
-topic prior to the current one."
-
- (interactive "p")
- (outline-open-topic -1 (> 0 arg)))
-
-;;;_ - Outline Alteration
-;;;_ : Topic Modification
-;;;_ = outline-former-auto-filler
-(defvar outline-former-auto-filler nil
- "Name of modal fill function being wrapped by outline-auto-fill.")
-;;;_ > outline-auto-fill ()
-(defun outline-auto-fill ()
- "Outline-mode autofill function.
-
-Maintains outline hanging topic indentation if
-`outline-use-hanging-indents' is set."
- (let ((fill-prefix (if outline-use-hanging-indents
- ;; Check for topic header indentation:
- (save-excursion
- (beginning-of-line)
- (if (looking-at outline-regexp)
- ;; ... construct indentation to account for
- ;; length of topic prefix:
- (make-string (progn (outline-end-of-prefix)
- (current-column))
- ?\ ))))))
- (if (or outline-former-auto-filler outline-use-hanging-indents)
- (do-auto-fill))))
-;;;_ > outline-reindent-body (old-depth new-depth &optional number)
-(defun outline-reindent-body (old-depth new-depth &optional number)
- "Reindent body lines which were indented at old-depth to new-depth.
-
-Optional arg NUMBER indicates numbering is being added, and it must
-be accommodated.
-
-Note that refill of indented paragraphs is not done."
-
- (save-excursion
- (outline-end-of-prefix)
- (let* ((new-margin (current-column))
- excess old-indent-begin old-indent-end
- curr-ind
- ;; We want the column where the header-prefix text started
- ;; *before* the prefix was changed, so we infer it relative
- ;; to the new margin and the shift in depth:
- (old-margin (+ old-depth (- new-margin new-depth))))
-
- ;; Process lines up to (but excluding) next topic header:
- (outline-unprotected
- (save-match-data
- (while
- (and (re-search-forward "[\n\r]\\(\\s-*\\)"
- nil
- t)
- ;; Register the indent data, before we reset the
- ;; match data with a subsequent `looking-at':
- (setq old-indent-begin (match-beginning 1)
- old-indent-end (match-end 1))
- (not (looking-at outline-regexp)))
- (if (> 0 (setq excess (- (current-column)
- old-margin)))
- ;; Text starts left of old margin - don't adjust:
- nil
- ;; Text was hanging at or right of old left margin -
- ;; reindent it, preserving its existing indentation
- ;; beyond the old margin:
- (delete-region old-indent-begin old-indent-end)
- (indent-to (+ new-margin excess)))))))))
-;;;_ > outline-rebullet-current-heading (arg)
-(defun outline-rebullet-current-heading (arg)
- "Like non-interactive version `outline-rebullet-heading'.
-
-But \(only\) affects visible heading containing point.
-
-With repeat count, solicit for bullet."
- (interactive "P")
- (save-excursion (outline-back-to-current-heading)
- (outline-end-of-prefix)
- (outline-rebullet-heading (not arg) ;;; solicit
- nil ;;; depth
- nil ;;; number-control
- nil ;;; index
- t) ;;; do-successors
- )
- )
-;;;_ > outline-rebullet-heading (&optional solicit ...)
-(defun outline-rebullet-heading (&optional solicit
- new-depth
- number-control
- index
- do-successors)
-
- "Adjust bullet of current topic prefix.
-
-All args are optional.
-
-If SOLICIT is non-nil then the choice of bullet is solicited from
-user. Otherwise the distinctiveness of the bullet or the topic
-depth determines it.
-
-Second arg DEPTH forces the topic prefix to that depth, regardless
-of the topics current depth.
-
-Third arg NUMBER-CONTROL can force the prefix to or away from
-numbered form. It has effect only if `outline-numbered-bullet' is
-non-nil and soliciting was not explicitly invoked (via first arg).
-Its effect, numbering or denumbering, then depends on the setting
-of the forth arg, INDEX.
-
-If NUMBER-CONTROL is non-nil and forth arg INDEX is nil, then the
-prefix of the topic is forced to be non-numbered. Null index and
-non-nil NUMBER-CONTROL forces denumbering. Non-nil INDEX (and
-non-nil NUMBER-CONTROL) forces a numbered-prefix form. If non-nil
-INDEX is a number, then that number is used for the numbered
-prefix. Non-nil and non-number means that the index for the
-numbered prefix will be derived by outline-make-topic-prefix.
-
-Fifth arg DO-SUCCESSORS t means re-resolve count on succeeding
-siblings.
-
-Cf vars `outline-stylish-prefixes', `outline-old-style-prefixes',
-and `outline-numbered-bullet', which all affect the behavior of
-this function."
-
- (let* ((current-depth (outline-depth))
- (new-depth (or new-depth current-depth))
- (mb outline-recent-prefix-beginning)
- (me outline-recent-prefix-end)
- (current-bullet (buffer-substring (- me 1) me))
- (new-prefix (outline-make-topic-prefix current-bullet
- nil
- new-depth
- solicit
- number-control
- index)))
-
- ;; Is new one is identical to old?
- (if (and (= current-depth new-depth)
- (string= current-bullet
- (substring new-prefix (1- (length new-prefix)))))
- ;; Nothing to do:
- t
-
- ;; New prefix probably different from old:
- ; get rid of old one:
- (outline-unprotected (delete-region mb me))
- (goto-char mb)
- ; Dispense with number if
- ; numbered-bullet prefix:
- (if (and outline-numbered-bullet
- (string= outline-numbered-bullet current-bullet)
- (looking-at "[0-9]+"))
- (outline-unprotected
- (delete-region (match-beginning 0)(match-end 0))))
-
- ; Put in new prefix:
- (outline-unprotected (insert-string new-prefix))
-
- ;; Reindent the body if elected and margin changed:
- (if (and outline-reindent-bodies
- (not (= new-depth current-depth)))
- (outline-reindent-body current-depth new-depth))
-
- ;; Recursively rectify successive siblings of orig topic if
- ;; caller elected for it:
- (if do-successors
- (save-excursion
- (while (outline-next-sibling new-depth nil)
- (setq index
- (cond ((numberp index) (1+ index))
- ((not number-control) (outline-sibling-index))))
- (if (outline-numbered-type-prefix)
- (outline-rebullet-heading nil ;;; solicit
- new-depth ;;; new-depth
- number-control;;; number-control
- index ;;; index
- nil))))) ;;;(dont!)do-successors
- ) ; (if (and (= current-depth new-depth)...))
- ) ; let* ((current-depth (outline-depth))...)
- ) ; defun
-;;;_ > outline-rebullet-topic (arg)
-(defun outline-rebullet-topic (arg)
- "Like outline-rebullet-topic-grunt, but start from topic visible at point.
-
-Descends into invisible as well as visible topics, however.
-
-With repeat count, shift topic depth by that amount."
- (interactive "P")
- (let ((start-col (current-column))
- (was-eol (eolp)))
- (save-excursion
- ;; Normalize arg:
- (cond ((null arg) (setq arg 0))
- ((listp arg) (setq arg (car arg))))
- ;; Fill the user in, in case we're shifting a big topic:
- (if (not (zerop arg)) (message "Shifting..."))
- (outline-back-to-current-heading)
- (if (<= (+ (outline-recent-depth) arg) 0)
- (error "Attempt to shift topic below level 1"))
- (outline-rebullet-topic-grunt arg)
- (if (not (zerop arg)) (message "Shifting... done.")))
- (move-to-column (max 0 (+ start-col arg)))))
-;;;_ > outline-rebullet-topic-grunt (&optional relative-depth ...)
-(defun outline-rebullet-topic-grunt (&optional relative-depth
- starting-depth
- starting-point
- index
- do-successors)
-
- "Rebullet the topic at point, visible or invisible, and all
-contained subtopics. See outline-rebullet-heading for rebulleting
-behavior.
-
-All arguments are optional.
-
-First arg RELATIVE-DEPTH means to shift the depth of the entire
-topic that amount.
-
-The rest of the args are for internal recursive use by the function
-itself. The are STARTING-DEPTH, STARTING-POINT, and INDEX."
-
- (let* ((relative-depth (or relative-depth 0))
- (new-depth (outline-depth))
- (starting-depth (or starting-depth new-depth))
- (on-starting-call (null starting-point))
- (index (or index
- ;; Leave index null on starting call, so rebullet-heading
- ;; calculates it at what might be new depth:
- (and (or (zerop relative-depth)
- (not on-starting-call))
- (outline-sibling-index))))
- (moving-outwards (< 0 relative-depth))
- (starting-point (or starting-point (point))))
-
- ;; Sanity check for excessive promotion done only on starting call:
- (and on-starting-call
- moving-outwards
- (> 0 (+ starting-depth relative-depth))
- (error "Attempt to shift topic out beyond level 1.")) ;;; ====>
-
- (cond ((= starting-depth new-depth)
- ;; We're at depth to work on this one:
- (outline-rebullet-heading nil ;;; solicit
- (+ starting-depth ;;; starting-depth
- relative-depth)
- nil ;;; number
- index ;;; index
- ;; Every contained topic will get hit,
- ;; and we have to get to outside ones
- ;; deliberately:
- nil) ;;; do-successors
- ;; ... and work on subsequent ones which are at greater depth:
- (setq index 0)
- (outline-next-heading)
- (while (and (not (eobp))
- (< starting-depth (outline-recent-depth)))
- (setq index (1+ index))
- (outline-rebullet-topic-grunt relative-depth ;;; relative-depth
- (1+ starting-depth);;;starting-depth
- starting-point ;;; starting-point
- index))) ;;; index
-
- ((< starting-depth new-depth)
- ;; Rare case - subtopic more than one level deeper than parent.
- ;; Treat this one at an even deeper level:
- (outline-rebullet-topic-grunt relative-depth ;;; relative-depth
- new-depth ;;; starting-depth
- starting-point ;;; starting-point
- index))) ;;; index
-
- (if on-starting-call
- (progn
- ;; Rectify numbering of former siblings of the adjusted topic,
- ;; if topic has changed depth
- (if (or do-successors
- (and (not (zerop relative-depth))
- (or (= (outline-recent-depth) starting-depth)
- (= (outline-recent-depth) (+ starting-depth
- relative-depth)))))
- (outline-rebullet-heading nil nil nil nil t))
- ;; Now rectify numbering of new siblings of the adjusted topic,
- ;; if depth has been changed:
- (progn (goto-char starting-point)
- (if (not (zerop relative-depth))
- (outline-rebullet-heading nil nil nil nil t)))))
- )
- )
-;;;_ > outline-renumber-to-depth (&optional depth)
-(defun outline-renumber-to-depth (&optional depth)
- "Renumber siblings at current depth.
-
-Affects superior topics if optional arg DEPTH is less than current depth.
-
-Returns final depth."
-
- ;; Proceed by level, processing subsequent siblings on each,
- ;; ascending until we get shallower than the start depth:
-
- (let ((ascender (outline-depth)))
- (while (and (not (eobp))
- (outline-depth)
- (>= (outline-recent-depth) depth)
- (>= ascender depth))
- ; Skip over all topics at
- ; lesser depths, which can not
- ; have been disturbed:
- (while (and (not (eobp))
- (> (outline-recent-depth) ascender))
- (outline-next-heading))
- ; Prime ascender for ascension:
- (setq ascender (1- (outline-recent-depth)))
- (if (>= (outline-recent-depth) depth)
- (outline-rebullet-heading nil ;;; solicit
- nil ;;; depth
- nil ;;; number-control
- nil ;;; index
- t))));;; do-successors
- (outline-recent-depth))
-;;;_ > outline-number-siblings (&optional denumber)
-(defun outline-number-siblings (&optional denumber)
- "Assign numbered topic prefix to this topic and its siblings.
-
-With universal argument, denumber - assign default bullet to this
-topic and its siblings.
-
-With repeated universal argument (`^U^U'), solicit bullet for each
-rebulleting each topic at this level."
-
- (interactive "P")
-
- (save-excursion
- (outline-back-to-current-heading)
- (outline-beginning-of-level)
- (let ((depth (outline-recent-depth))
- (index (if (not denumber) 1))
- (use-bullet (equal '(16) denumber))
- (more t))
- (while more
- (outline-rebullet-heading use-bullet ;;; solicit
- depth ;;; depth
- t ;;; number-control
- index ;;; index
- nil) ;;; do-successors
- (if index (setq index (1+ index)))
- (setq more (outline-next-sibling depth nil))))))
-;;;_ > outline-shift-in (arg)
-(defun outline-shift-in (arg)
- "Increase depth of current heading and any topics collapsed within it."
- (interactive "p")
- (outline-rebullet-topic arg))
-;;;_ > outline-shift-out (arg)
-(defun outline-shift-out (arg)
- "Decrease depth of current heading and any topics collapsed within it."
- (interactive "p")
- (outline-rebullet-topic (* arg -1)))
-;;;_ : Surgery (kill-ring) functions with special provisions for outlines:
-;;;_ > outline-kill-line (&optional arg)
-(defun outline-kill-line (&optional arg)
- "Kill line, adjusting subsequent lines suitably for outline mode."
-
- (interactive "*P")
- (if (not (and (outline-mode-p) ; active outline mode,
- outline-numbered-bullet ; numbers may need adjustment,
- (bolp) ; may be clipping topic head,
- (looking-at outline-regexp))) ; are clipping topic head.
- ;; Above conditions do not obtain - just do a regular kill:
- (kill-line arg)
- ;; Ah, have to watch out for adjustments:
- (let* ((depth (outline-depth)))
- ; Do the kill:
- (kill-line arg)
- ; Provide some feedback:
- (sit-for 0)
- (save-excursion
- ; Start with the topic
- ; following killed line:
- (if (not (looking-at outline-regexp))
- (outline-next-heading))
- (outline-renumber-to-depth depth)))))
-;;;_ > outline-kill-topic ()
-(defun outline-kill-topic ()
- "Kill topic together with subtopics.
-
-Leaves primary topic's trailing vertical whitespace, if any."
-
- ;; Some finagling is done to make complex topic kills appear faster
- ;; than they actually are. A redisplay is performed immediately
- ;; after the region is disposed of, though the renumbering process
- ;; has yet to be performed. This means that there may appear to be
- ;; a lag *after* the kill has been performed.
-
- (interactive)
- (let* ((beg (prog1 (outline-back-to-current-heading)(beginning-of-line)))
- (depth (outline-recent-depth)))
- (outline-end-of-current-subtree)
- (if (not (eobp))
- (if (or (not (looking-at "^$"))
- ;; A blank line - cut it with this topic *unless* this
- ;; is the last topic at this level, in which case
- ;; we'll leave the blank line as part of the
- ;; containing topic:
- (save-excursion
- (and (outline-next-heading)
- (>= (outline-recent-depth) depth))))
- (forward-char 1)))
-
- (kill-region beg (point))
- (sit-for 0)
- (save-excursion
- (outline-renumber-to-depth depth))))
-;;;_ > outline-yank-processing ()
-(defun outline-yank-processing (&optional arg)
-
- "Incidental outline-specific business to be done just after text yanks.
-
-Does depth adjustment of yanked topics, when:
-
-1 the stuff being yanked starts with a valid outline header prefix, and
-2 it is being yanked at the end of a line which consists of only a valid
- topic prefix.
-
-Also, adjusts numbering of subsequent siblings when appropriate.
-
-Depth adjustment alters the depth of all the topics being yanked
-the amount it takes to make the first topic have the depth of the
-header into which it's being yanked.
-
-The point is left in front of yanked, adjusted topics, rather than
-at the end (and vice-versa with the mark). Non-adjusted yanks,
-however, are left exactly like normal, non-outline-specific yanks."
-
- (interactive "*P")
- ; Get to beginning, leaving
- ; region around subject:
- (if (< (mark-marker) (point))
- (exchange-point-and-mark))
- (let* ((subj-beg (point))
- (subj-end (mark-marker))
- ;; `resituate' if yanking an entire topic into topic header:
- (resituate (and (outline-e-o-prefix-p)
- (looking-at (concat "\\(" outline-regexp "\\)"))
- (outline-prefix-data (match-beginning 1)
- (match-end 1))))
- ;; `rectify-numbering' if resituating (where several topics may
- ;; be resituating) or yanking a topic into a topic slot (bol):
- (rectify-numbering (or resituate
- (and (bolp) (looking-at outline-regexp)))))
- (if resituate
- ; The yanked stuff is a topic:
- (let* ((prefix-len (- (match-end 1) subj-beg))
- (subj-depth (outline-recent-depth))
- (prefix-bullet (outline-recent-bullet))
- (adjust-to-depth
- ;; Nil if adjustment unnecessary, otherwise depth to which
- ;; adjustment should be made:
- (save-excursion
- (and (goto-char subj-end)
- (eolp)
- (goto-char subj-beg)
- (and (looking-at outline-regexp)
- (progn
- (beginning-of-line)
- (not (= (point) subj-beg)))
- (looking-at outline-regexp)
- (outline-prefix-data (match-beginning 0)
- (match-end 0)))
- (outline-recent-depth))))
- done
- (more t))
- (setq rectify-numbering outline-numbered-bullet)
- (if adjust-to-depth
- ; Do the adjustment:
- (progn
- (message "... yanking") (sit-for 0)
- (save-restriction
- (narrow-to-region subj-beg subj-end)
- ; Trim off excessive blank
- ; line at end, if any:
- (goto-char (point-max))
- (if (looking-at "^$")
- (outline-unprotected (delete-char -1)))
- ; Work backwards, with each
- ; shallowest level,
- ; successively excluding the
- ; last processed topic from
- ; the narrow region:
- (while more
- (outline-back-to-current-heading)
- ; go as high as we can in each bunch:
- (while (outline-ascend-to-depth (1- (outline-depth))))
- (save-excursion
- (outline-rebullet-topic-grunt (- adjust-to-depth
- subj-depth))
- (outline-depth))
- (if (setq more (not (bobp)))
- (progn (widen)
- (forward-char -1)
- (narrow-to-region subj-beg (point))))))
- (message "")
- ;; Preserve new bullet if it's a distinctive one, otherwise
- ;; use old one:
- (if (string-match (regexp-quote prefix-bullet)
- outline-distinctive-bullets-string)
- ; Delete from bullet of old to
- ; before bullet of new:
- (progn
- (beginning-of-line)
- (delete-region (point) subj-beg)
- (set-marker (mark-marker) subj-end)
- (goto-char subj-beg)
- (outline-end-of-prefix))
- ; Delete base subj prefix,
- ; leaving old one:
- (delete-region (point) (+ (point)
- prefix-len
- (- adjust-to-depth subj-depth)))
- ; and delete residual subj
- ; prefix digits and space:
- (while (looking-at "[0-9]") (delete-char 1))
- (if (looking-at " ") (delete-char 1))))
- (exchange-point-and-mark))))
- (if rectify-numbering
- (progn
- (save-excursion
- ; Give some preliminary feedback:
- (message "... reconciling numbers") (sit-for 0)
- ; ... and renumber, in case necessary:
- (goto-char subj-beg)
- (if (outline-goto-prefix)
- (outline-rebullet-heading nil ;;; solicit
- (outline-depth) ;;; depth
- nil ;;; number-control
- nil ;;; index
- t))
- (message ""))))
- (if (not resituate)
- (exchange-point-and-mark))))
-;;;_ > outline-yank (&optional arg)
-(defun outline-yank (&optional arg)
- "Outline-mode yank, with depth and numbering adjustment of yanked topics.
-
-Non-topic yanks work no differently than normal yanks.
-
-If a topic is being yanked into a bare topic prefix, the depth of the
-yanked topic is adjusted to the depth of the topic prefix.
-
- 1 we're yanking in an outline-mode buffer
- 2 the stuff being yanked starts with a valid outline header prefix, and
- 3 it is being yanked at the end of a line which consists of only a valid
- topic prefix.
-
-If these conditions hold then the depth of the yanked topics are all
-adjusted the amount it takes to make the first one at the depth of the
-header into which it's being yanked.
-
-The point is left in front of yanked, adjusted topics, rather than
-at the end (and vice-versa with the mark). Non-adjusted yanks,
-however, (ones that don't qualify for adjustment) are handled
-exactly like normal yanks.
-
-Numbering of yanked topics, and the successive siblings at the depth
-into which they're being yanked, is adjusted.
-
-Outline-yank-pop works with outline-yank just like normal yank-pop
-works with normal yank in non-outline buffers."
-
- (interactive "*P")
- (setq this-command 'yank)
- (yank arg)
- (if (outline-mode-p)
- (outline-yank-processing)))
-;;;_ > outline-yank-pop (&optional arg)
-(defun outline-yank-pop (&optional arg)
- "Yank-pop like outline-yank when popping to bare outline prefixes.
-
-Adapts level of popped topics to level of fresh prefix.
-
-Note - prefix changes to distinctive bullets will stick, if followed
-by pops to non-distinctive yanks. Bug..."
-
- (interactive "*p")
- (setq this-command 'yank)
- (yank-pop arg)
- (if (outline-mode-p)
- (outline-yank-processing)))
-
-;;;_ - Specialty bullet functions
-;;;_ : File Cross references
-;;;_ > outline-resolve-xref ()
-(defun outline-resolve-xref ()
- "Pop to file associated with current heading, if it has an xref bullet.
-
-\(Works according to setting of `outline-file-xref-bullet')."
- (interactive)
- (if (not outline-file-xref-bullet)
- (error
- "outline cross references disabled - no `outline-file-xref-bullet'")
- (if (not (string= (outline-current-bullet) outline-file-xref-bullet))
- (error "current heading lacks cross-reference bullet `%s'"
- outline-file-xref-bullet)
- (let (file-name)
- (save-excursion
- (let* ((text-start outline-recent-prefix-end)
- (heading-end (progn (end-of-line) (point))))
- (goto-char text-start)
- (setq file-name
- (if (re-search-forward "\\s-\\(\\S-*\\)" heading-end t)
- (buffer-substring (match-beginning 1) (match-end 1))))))
- (setq file-name
- (if (not (= (aref file-name 0) ?:))
- (expand-file-name file-name)
- ; A registry-files ref, strip the `:'
- ; and try to follow it:
- (let ((reg-ref (reference-registered-file
- (substring file-name 1) nil t)))
- (if reg-ref (car (cdr reg-ref))))))
- (if (or (file-exists-p file-name)
- (if (file-writable-p file-name)
- (y-or-n-p (format "%s not there, create one? "
- file-name))
- (error "%s not found and can't be created" file-name)))
- (condition-case failure
- (find-file-other-window file-name)
- (error failure))
- (error "%s not found" file-name))
- )
- )
- )
- )
-
-;;;_ #6 Exposure Control and Processing
-
-;;;_ - Fundamental
-;;;_ > outline-flag-region (from to flag)
-(defmacro outline-flag-region (from to flag)
- "Hide or show lines from FROM to TO, via emacs selective-display FLAG char.
-Ie, text following flag C-m \(carriage-return) is hidden until the
-next C-j (newline) char.
-
-Returns the endpoint of the region."
- (` (let ((buffer-read-only nil)
- (outline-override-protect t))
- (subst-char-in-region (, from) (, to)
- (if (= (, flag) ?\n) ?\r ?\n)
- (, flag) t))))
-;;;_ > outline-flag-current-subtree (flag)
-(defun outline-flag-current-subtree (flag)
- "Hide or show subtree of currently-visible topic.
-
-See `outline-flag-region' for more details."
-
- (save-excursion
- (outline-back-to-current-heading)
- (outline-flag-region (point)
- (progn (outline-end-of-current-subtree) (1- (point)))
- flag)))
-
-;;;_ - Mapping and processing of topics
-;;;_ " See also chart functions, in navigation
-;;;_ > outline-listify-exposed (&optional start end)
-(defun outline-listify-exposed (&optional start end)
-
- "Produce a list representing exposed topics in current region.
-
-This list can then be used by `outline-process-exposed' to manipulate
-the subject region.
-
-List is composed of elements that may themselves be lists representing
-exposed components in subtopic.
-
-Each component list contains:
- - a number representing the depth of the topic,
- - a string representing the header-prefix (ref. `outline-header-prefix'),
- - a string representing the bullet character,
- - and a series of strings, each containing one line of the exposed
- portion of the topic entry."
-
- (interactive "r")
- (save-excursion
- (let* (strings pad result depth bullet beg next done) ; State vars.
- (goto-char start)
- (beginning-of-line)
- (if (not (outline-goto-prefix)) ; Get initial position within a topic:
- (outline-next-visible-heading 1))
- (while (and (not done)
- (not (eobp)) ; Loop until we've covered the region.
- (not (> (point) end)))
- (setq depth (outline-recent-depth) ; Current topics' depth,
- bullet (outline-recent-bullet) ; ... bullet,
- beg (progn (outline-end-of-prefix t) (point))) ; and beginning.
- (setq done ; The boundary for the current topic:
- (not (outline-next-visible-heading 1)))
- (beginning-of-line)
- (setq next (point))
- (goto-char beg)
- (setq strings nil)
- (while (> next (point)) ; Get all the exposed text in
- (setq strings
- (cons (buffer-substring
- beg
- ;To hidden text or end of line:
- (progn
- (search-forward "\r"
- (save-excursion (end-of-line)
- (point))
- 1)
- (if (= (preceding-char) ?\r)
- (1- (point))
- (point))))
- strings))
- (if (< (point) next) ; Resume from after hid text, if any.
- (forward-line 1))
- (setq beg (point)))
- ;; Accumulate list for this topic:
- (setq result
- (cons (append (list depth
- outline-header-prefix
- bullet)
- (nreverse strings))
- result)))
- ;; Put the list with first at front, to last at back:
- (nreverse result))))
-;;;_ > outline-process-exposed (arg &optional tobuf)
-(defun outline-process-exposed (&optional func from to frombuf tobuf)
- "Map function on exposed parts of current topic; results to another buffer.
-
-Apply FUNCTION \(default 'outline-insert-listified) to exposed
-portions FROM position TO position \(default region, or the entire
-buffer if no region active) in buffer FROMBUF \(default current
-buffer) to buffer TOBUF \(default is buffer named like frombuf but
-with \"*\" prepended and \" exposed*\" appended).
-
-The function must as its arguments the elements of the list
-representations of topic entries produced by outline-listify-exposed."
-
- ; Resolve arguments,
- ; defaulting if necessary:
- (if (not func) (setq func 'outline-insert-listified))
- (if (not (and from to))
- (if mark-active
- (setq from (region-beginning) to (region-end))
- (setq from (point-min) to (point-max))))
- (if frombuf
- (if (not (bufferp frombuf))
- ;; Specified but not a buffer - get it:
- (let ((got (get-buffer frombuf)))
- (if (not got)
- (error "outline-process-exposed: source buffer %s not found."
- frombuf)
- (setq frombuf got))))
- ;; not specified - default it:
- (setq frombuf (current-buffer)))
- (if tobuf
- (if (not (bufferp tobuf))
- (setq tobuf (get-buffer-create tobuf)))
- ;; not specified - default it:
- (setq tobuf (concat "*" (buffer-name frombuf) " exposed*")))
-
- (let* ((listified (progn (set-buffer frombuf)
- (outline-listify-exposed from to)))
- (prefix outline-header-prefix) ; ... as set in frombuf.
- curr)
- (set-buffer tobuf)
- (while listified
- (setq curr (car listified))
- (setq listified (cdr listified))
- (apply func (list (car curr) ; depth
- (car (cdr curr)) ; header-prefix
- (car (cdr (cdr curr))) ; bullet
- (cdr (cdr (cdr curr)))))) ; list of text lines
- (pop-to-buffer tobuf)))
-
-;;;_ - Topic-specific
-;;;_ > outline-show-entry ()
-; outline-show-entry basically for isearch dynamic exposure, as is...
-(defun outline-show-entry ()
- "Like `outline-show-current-entry', reveals entries nested in hidden topics.
-
-This is a way to give restricted peek at a concealed locality without the
-expense of exposing its context, but can leave the outline with aberrant
-exposure. outline-hide-current-entry-completely or outline-show-offshoot
-should be used after the peek to rectify the exposure."
-
- (interactive)
- (save-excursion
- (outline-goto-prefix)
- (outline-flag-region (if (bobp) (point) (1- (point)))
- (or (outline-pre-next-preface) (point))
- ?\n)))
-;;;_ > outline-show-children (&optional level strict)
-(defun outline-show-children (&optional level strict)
-
- "If point is visible, show all direct subheadings of this heading.
-
-Otherwise, do outline-show-to-offshoot, and then show subheadings.
-
-Optional LEVEL specifies how many levels below the current level
-should be shown, or all levels if t. Default is 1.
-
-Optional STRICT means don't resort to -show-to-offshoot, no matter
-what. This is basically so -show-to-offshoot, which is called by
-this function, can employ the pure offspring-revealing capabilities of
-it.
-
-Returns point at end of subtree that was opened, if any. (May get a
-point of non-opened subtree?)"
-
- (interactive "p")
- (let (max-pos)
- (if (and (not strict)
- (outline-hidden-p))
-
- (progn (outline-show-to-offshoot) ; Point's concealed, open to
- ; expose it.
- ;; Then recurse, but with "strict" set so we don't
- ;; infinite regress:
- (setq max-pos (outline-show-children level t)))
-
- (save-excursion
- (save-restriction
- (let* ((start-pt (point))
- (chart (outline-chart-subtree (or level 1)))
- (to-reveal (outline-chart-to-reveal chart (or level 1))))
- (goto-char start-pt)
- (if (and strict (= (preceding-char) ?\r))
- ;; Concealed root would already have been taken care of,
- ;; unless strict was set.
- (outline-flag-region (point) (outline-snug-back) ?\n))
- (while to-reveal
- (goto-char (car to-reveal))
- (outline-flag-region (point) (outline-snug-back) ?\n)
- (setq to-reveal (cdr to-reveal)))))))))
-;;;_ x outline-show-current-children (&optional level strict)
-(defun outline-show-current-children (&optional level strict)
- "This command was misnamed, use `outline-show-children' instead.
-
-\(The \"current\" in the name is supposed to imply that it works on
-the visible topic containing point, while it really works with respect
-to the most immediate topic, concealed or not. I'll leave this old
-name around for a bit, but i'll soon activate an annoying message to
-warn people about the change, and then deprecate this alias."
-
- (interactive "p")
- ;;(beep)
- ;;(message (format "Use `%s' instead of `%s' (%s)."
- ;; "outline-show-children"
- ;; "outline-show-current-children"
- ;; (buffer-name (current-buffer))))
- (outline-show-children level strict))
-;;;_ > outline-hide-point-reconcile ()
-(defun outline-hide-reconcile ()
- "Like `outline-hide-current-entry'; hides completely if within hidden region.
-
-Specifically intended for aberrant exposure states, like entries that were
-exposed by outline-show-entry but are within otherwise concealed regions."
- (interactive)
- (save-excursion
- (outline-goto-prefix)
- (outline-flag-region (if (not (bobp)) (1- (point)) (point))
- (progn (outline-pre-next-preface)
- (if (= ?\r (following-char))
- (point)
- (1- (point))))
- ?\r)))
-;;;_ > outline-show-to-offshoot ()
-(defun outline-show-to-offshoot ()
- "Like outline-show-entry, but reveals opens all concealed ancestors, as well.
-
-As with outline-hide-current-entry-completely, useful for rectifying
-aberrant exposure states produced by outline-show-entry."
-
- (interactive)
- (save-excursion
- (let ((orig-pt (point))
- (orig-pref (outline-goto-prefix))
- (last-at (point))
- bag-it)
- (while (or bag-it (= (preceding-char) ?\r))
- (beginning-of-line)
- (if (= last-at (setq last-at (point)))
- ;; Oops, we're not making any progress! Show the current
- ;; topic completely, and bag this try.
- (progn (beginning-of-line)
- (outline-show-current-subtree)
- (goto-char orig-pt)
- (setq bag-it t)
- (beep)
- (message "%s: %s"
- "outline-show-to-offshoot: "
- "Aberrant nesting encountered.")))
- (outline-show-children)
- (goto-char orig-pref))
- (goto-char orig-pt)))
- (if (outline-hidden-p)
- (outline-show-entry)))
-;;;_ > outline-hide-current-entry ()
-(defun outline-hide-current-entry ()
- "Hide the body directly following this heading."
- (interactive)
- (outline-back-to-current-heading)
- (save-excursion
- (outline-flag-region (point)
- (progn (outline-end-of-current-entry) (point))
- ?\^M)))
-;;;_ > outline-show-current-entry (&optional arg)
-(defun outline-show-current-entry (&optional arg)
-
- "Show body following current heading, or hide the entry if repeat count."
-
- (interactive "P")
- (if arg
- (outline-hide-current-entry)
- (save-excursion
- (outline-flag-region (point)
- (progn (outline-end-of-current-entry) (point))
- ?\n))))
-;;;_ > outline-hide-current-entry-completely ()
-; ... outline-hide-current-entry-completely also for isearch dynamic exposure:
-(defun outline-hide-current-entry-completely ()
- "Like outline-hide-current-entry, but conceal topic completely.
-
-Specifically intended for aberrant exposure states, like entries that were
-exposed by outline-show-entry but are within otherwise concealed regions."
- (interactive)
- (save-excursion
- (outline-goto-prefix)
- (outline-flag-region (if (not (bobp)) (1- (point)) (point))
- (progn (outline-pre-next-preface)
- (if (= ?\r (following-char))
- (point)
- (1- (point))))
- ?\r)))
-;;;_ > outline-show-current-subtree (&optional arg)
-(defun outline-show-current-subtree (&optional arg)
- "Show everything within the current topic. With a repeat-count,
-expose this topic and its siblings."
- (interactive "P")
- (save-excursion
- (if (<= (outline-current-depth) 0)
- ;; Outside any topics - try to get to the first:
- (if (not (outline-next-heading))
- (error "No topics.")
- ;; got to first, outermost topic - set to expose it and siblings:
- (message "Above outermost topic - exposing all.")
- (outline-flag-region (point-min)(point-max) ?\n))
- (if (not arg)
- (outline-flag-current-subtree ?\n)
- (outline-beginning-of-level)
- (outline-expose-topic '(* :))))))
-;;;_ > outline-hide-current-subtree (&optional just-close)
-(defun outline-hide-current-subtree (&optional just-close)
- "Close the current topic, or containing topic if this one is already closed.
-
-If this topic is closed and it's a top level topic, close this topic
-and its siblings.
-
-If optional arg JUST-CLOSE is non-nil, do not treat the parent or
-siblings, even if the target topic is already closed."
-
- (interactive)
- (let ((from (point))
- (orig-eol (progn (end-of-line)
- (if (not (outline-goto-prefix))
- (error "No topics found.")
- (end-of-line)(point)))))
- (outline-flag-current-subtree ?\^M)
- (goto-char from)
- (if (and (= orig-eol (progn (goto-char orig-eol)
- (end-of-line)
- (point)))
- (not just-close)
- ;; Structure didn't change - try hiding current level:
- (goto-char from)
- (if (outline-up-current-level 1 t)
- t
- (goto-char 0)
- (let ((msg
- "Top-level topic already closed - closing siblings..."))
- (message msg)
- (outline-expose-topic '(0 :))
- (message (concat msg " Done.")))
- nil)
- (/= (outline-recent-depth) 0))
- (outline-hide-current-subtree))
- (goto-char from)))
-;;;_ > outline-show-current-branches ()
-(defun outline-show-current-branches ()
- "Show all subheadings of this heading, but not their bodies."
- (interactive)
- (beginning-of-line)
- (outline-show-children t))
-;;;_ > outline-hide-current-leaves ()
-(defun outline-hide-current-leaves ()
- "Hide the bodies of the current topic and all its offspring."
- (interactive)
- (outline-back-to-current-heading)
- (outline-hide-region-body (point) (progn (outline-end-of-current-subtree)
- (point))))
-
-;;;_ - Region and beyond
-;;;_ > outline-show-all ()
-(defun outline-show-all ()
- "Show all of the text in the buffer."
- (interactive)
- (message "Exposing entire buffer...")
- (outline-flag-region (point-min) (point-max) ?\n)
- (message "Exposing entire buffer... Done."))
-;;;_ > outline-hide-bodies ()
-(defun outline-hide-bodies ()
- "Hide all of buffer except headings."
- (interactive)
- (outline-hide-region-body (point-min) (point-max)))
-;;;_ > outline-hide-region-body (start end)
-(defun outline-hide-region-body (start end)
- "Hide all body lines in the region, but not headings."
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (goto-char (point-min))
- (while (not (eobp))
- (outline-flag-region (point)
- (progn (outline-pre-next-preface) (point)) ?\^M)
- (if (not (eobp))
- (forward-char
- (if (looking-at "[\n\r][\n\r]")
- 2 1)))))))
-
-;;;_ > outline-expose-topic (spec)
-(defun outline-expose-topic (spec)
- "Apply exposure specs to successive outline topic items.
-
-Use the more convenient frontend, `outline-new-exposure', if you don't
-need evaluation of the arguments, or even better, the `outline-layout'
-variable-keyed mode-activation/auto-exposure feature of allout outline
-mode. See the respective documentation strings for more details.
-
-Cursor is left at start position.
-
-SPEC is either a number or a list.
-
-Successive specs on a list are applied to successive sibling topics.
-
-A simple spec \(either a number, one of a few symbols, or the null
-list) dictates the exposure for the corresponding topic.
-
-Non-null lists recursively designate exposure specs for respective
-subtopics of the current topic.
-
-The `:' repeat spec is used to specify exposure for any number of
-successive siblings, up to the trailing ones for which there are
-explicit specs following the `:'.
-
-Simple (numeric and null-list) specs are interpreted as follows:
-
- Numbers indicate the relative depth to open the corresponding topic.
- - negative numbers force the topic to be closed before opening to the
- absolute value of the number, so all siblings are open only to
- that level.
- - positive numbers open to the relative depth indicated by the
- number, but do not force already opened subtopics to be closed.
- - 0 means to close topic - hide all offspring.
- : - `repeat'
- apply prior element to all siblings at current level, *up to*
- those siblings that would be covered by specs following the `:'
- on the list. Ie, apply to all topics at level but the last
- ones. \(Only first of multiple colons at same level is
- respected - subsequent ones are discarded.)
- * - completely opens the topic, including bodies.
- + - shows all the sub headers, but not the bodies
- - - exposes the body of the corresponding topic.
-
-Examples:
-\(outline-expose-topic '(-1 : 0))
- Close this and all following topics at current level, exposing
- only their immediate children, but close down the last topic
- at this current level completely.
-\(outline-expose-topic '(-1 () : 1 0))
- Close current topic so only the immediate subtopics are shown;
- show the children in the second to last topic, and completely
- close the last one.
-\(outline-expose-topic '(-2 : -1 *))
- Expose children and grandchildren of all topics at current
- level except the last two; expose children of the second to
- last and completely open the last one."
-
- (interactive "xExposure spec: ")
- (if (not (listp spec))
- nil
- (let ((depth (outline-depth))
- (max-pos 0)
- prev-elem curr-elem
- stay done
- snug-back
- )
- (while spec
- (setq prev-elem curr-elem
- curr-elem (car spec)
- spec (cdr spec))
- (cond ; Do current element:
- ((null curr-elem) nil)
- ((symbolp curr-elem)
- (cond ((eq curr-elem '*) (outline-show-current-subtree)
- (if (> outline-recent-end-of-subtree max-pos)
- (setq max-pos outline-recent-end-of-subtree)))
- ((eq curr-elem '+) (outline-show-current-branches)
- (if (> outline-recent-end-of-subtree max-pos)
- (setq max-pos outline-recent-end-of-subtree)))
- ((eq curr-elem '-) (outline-show-current-entry))
- ((eq curr-elem ':)
- (setq stay t)
- ;; Expand the `repeat' spec to an explicit version,
- ;; w.r.t. remaining siblings:
- (let ((residue ; = # of sibs not covered by remaining spec
- ;; Dang - could be nice to make use of the chart, sigh:
- (- (length (outline-chart-siblings))
- (length spec))))
- (if (< 0 residue)
- ;; Some residue - cover it with prev-elem:
- (setq spec (append (make-list residue prev-elem)
- spec)))))))
- ((numberp curr-elem)
- (if (and (>= 0 curr-elem) (outline-visible-p))
- (save-excursion (outline-hide-current-subtree t)
- (if (> 0 curr-elem)
- nil
- (if (> outline-recent-end-of-subtree max-pos)
- (setq max-pos
- outline-recent-end-of-subtree)))))
- (if (> (abs curr-elem) 0)
- (progn (outline-show-children (abs curr-elem))
- (if (> outline-recent-end-of-subtree max-pos)
- (setq max-pos outline-recent-end-of-subtree)))))
- ((listp curr-elem)
- (if (outline-descend-to-depth (1+ depth))
- (let ((got (outline-expose-topic curr-elem)))
- (if (and got (> got max-pos)) (setq max-pos got))))))
- (cond (stay (setq stay nil))
- ((listp (car spec)) nil)
- ((> max-pos (point))
- ;; Capitalize on max-pos state to get us nearer next sibling:
- (progn (goto-char (min (point-max) max-pos))
- (outline-next-heading)))
- ((outline-next-sibling depth))))
- max-pos)))
-;;;_ > outline-old-expose-topic (spec &rest followers)
-(defun outline-old-expose-topic (spec &rest followers)
-
- "Deprecated. Use outline-expose-topic \(with different schema
-format\) instead.
-
-Dictate wholesale exposure scheme for current topic, according to SPEC.
-
-SPEC is either a number or a list. Optional successive args
-dictate exposure for subsequent siblings of current topic.
-
-A simple spec (either a number, a special symbol, or the null list)
-dictates the overall exposure for a topic. Non null lists are
-composite specs whose first element dictates the overall exposure for
-a topic, with the subsequent elements in the list interpreted as specs
-that dictate the exposure for the successive offspring of the topic.
-
-Simple (numeric and null-list) specs are interpreted as follows:
-
- - Numbers indicate the relative depth to open the corresponding topic:
- - negative numbers force the topic to be close before opening to the
- absolute value of the number.
- - positive numbers just open to the relative depth indicated by the number.
- - 0 just closes
- - `*' completely opens the topic, including bodies.
- - `+' shows all the sub headers, but not the bodies
- - `-' exposes the body and immediate offspring of the corresponding topic.
-
-If the spec is a list, the first element must be a number, which
-dictates the exposure depth of the topic as a whole. Subsequent
-elements of the list are nested SPECs, dictating the specific exposure
-for the corresponding offspring of the topic.
-
-Optional FOLLOWER arguments dictate exposure for succeeding siblings."
-
- (interactive "xExposure spec: ")
- (let ((depth (outline-current-depth))
- done
- max-pos)
- (cond ((null spec) nil)
- ((symbolp spec)
- (if (eq spec '*) (outline-show-current-subtree))
- (if (eq spec '+) (outline-show-current-branches))
- (if (eq spec '-) (outline-show-current-entry)))
- ((numberp spec)
- (if (>= 0 spec)
- (save-excursion (outline-hide-current-subtree t)
- (end-of-line)
- (if (or (not max-pos)
- (> (point) max-pos))
- (setq max-pos (point)))
- (if (> 0 spec)
- (setq spec (* -1 spec)))))
- (if (> spec 0)
- (outline-show-children spec)))
- ((listp spec)
- ;(let ((got (outline-old-expose-topic (car spec))))
- ; (if (and got (or (not max-pos) (> got max-pos)))
- ; (setq max-pos got)))
- (let ((new-depth (+ (outline-current-depth) 1))
- got)
- (setq max-pos (outline-old-expose-topic (car spec)))
- (setq spec (cdr spec))
- (if (and spec
- (outline-descend-to-depth new-depth)
- (not (outline-hidden-p)))
- (progn (setq got (apply 'outline-old-expose-topic spec))
- (if (and got (or (not max-pos) (> got max-pos)))
- (setq max-pos got)))))))
- (while (and followers
- (progn (if (and max-pos (< (point) max-pos))
- (progn (goto-char max-pos)
- (setq max-pos nil)))
- (end-of-line)
- (outline-next-sibling depth)))
- (outline-old-expose-topic (car followers))
- (setq followers (cdr followers)))
- max-pos))
-;;;_ > outline-new-exposure '()
-(defmacro outline-new-exposure (&rest spec)
- "Literal frontend for `outline-expose-topic', doesn't evaluate arguments.
-Some arguments that would need to be quoted in outline-expose-topic
-need not be quoted in outline-new-exposure.
-
-Cursor is left at start position.
-
-Use this instead of obsolete `outline-exposure'.
-
-Examples:
-\(outline-exposure (-1 () () () 1) 0)
- Close current topic at current level so only the immediate
- subtopics are shown, except also show the children of the
- third subtopic; and close the next topic at the current level.
-\(outline-exposure : -1 0)
- Close all topics at current level to expose only their
- immediate children, except for the last topic at the current
- level, in which even its immediate children are hidden.
-\(outline-exposure -2 : -1 *)
- Expose children and grandchildren of first topic at current
- level, and expose children of subsequent topics at current
- level *except* for the last, which should be opened completely."
- (list 'save-excursion
- '(if (not (or (outline-goto-prefix)
- (outline-next-heading)))
- (error "outline-new-exposure: Can't find any outline topics."))
- (list 'outline-expose-topic (list 'quote spec))))
-;;;_ > outline-exposure '()
-(defmacro outline-exposure (&rest spec)
- "Being deprecated - use more recent `outline-new-exposure' instead.
-
-Literal frontend for `outline-old-expose-topic', doesn't evaluate arguments
-and retains start position."
- (list 'save-excursion
- '(if (not (or (outline-goto-prefix)
- (outline-next-heading)))
- (error "Can't find any outline topics."))
- (cons 'outline-old-expose-topic
- (mapcar '(lambda (x) (list 'quote x)) spec))))
-
-;;;_ #7 ISearch with Dynamic Exposure
-;;;_ = outline-search-reconceal
-(defvar outline-search-reconceal nil
- "Track whether current search match was concealed outside of search.
-
-The value is the location of the match, if it was concealed, regular
-if the entire topic was concealed, in a list if the entry was concealed.")
-;;;_ = outline-search-quitting
-(defconst outline-search-quitting nil
- "Distinguishes isearch conclusion and cancellation.
-
-Used by isearch-terminate/outline-provisions and
-isearch-done/outline-provisions")
-
-
-;;;_ > outline-enwrap-isearch ()
-(defun outline-enwrap-isearch ()
- "Impose outline-mode isearch-mode wrappers for dynamic exposure in isearch.
-
-Isearch progressively exposes and reconceals hidden topics when
-working in outline mode, but works normally elsewhere.
-
-The function checks to ensure that the rebindings are done only once."
-
- ; Should isearch-mode be employed,
- (if (or (not outline-enwrap-isearch-mode)
- ; or are preparations already done?
- (fboundp 'real-isearch-terminate))
-
- ;; ... no - skip this all:
- nil
-
- ;; ... yes:
-
- ; Ensure load of isearch-mode:
- (if (or (and (fboundp 'isearch-mode)
- (fboundp 'isearch-quote-char))
- (condition-case error
- (load-library outline-enwrap-isearch-mode)
- (file-error (message "Skipping isearch-mode provisions - %s '%s'"
- (car (cdr error))
- (car (cdr (cdr error))))
- (sit-for 1)
- ;; Inhibit subsequent tries and return nil:
- (setq outline-enwrap-isearch-mode nil))))
- ;; Isearch-mode loaded, encapsulate specific entry points for
- ;; outline dynamic-exposure business:
- (progn
-
- ;; stash crucial isearch-mode funcs under known, private
- ;; names, then register wrapper functions under the old
- ;; names, in their stead: `isearch-quit' is pre isearch v 1.2.
- (fset 'real-isearch-terminate
- ; `isearch-quit' is pre v 1.2:
- (or (if (fboundp 'isearch-quit)
- (symbol-function 'isearch-quit))
- (if (fboundp 'isearch-abort)
- ; `isearch-abort' is v 1.2 and on:
- (symbol-function 'isearch-abort))))
- (fset 'isearch-quit 'isearch-terminate/outline-provisions)
- (fset 'isearch-abort 'isearch-terminate/outline-provisions)
- (fset 'real-isearch-done (symbol-function 'isearch-done))
- (fset 'isearch-done 'isearch-done/outline-provisions)
- (fset 'real-isearch-update (symbol-function 'isearch-update))
- (fset 'isearch-update 'isearch-update/outline-provisions)
- (make-variable-buffer-local 'outline-search-reconceal)))))
-;;;_ > outline-isearch-arrival-business ()
-(defun outline-isearch-arrival-business ()
- "Do outline business like exposing current point, if necessary.
-
-Registers reconcealment requirements in outline-search-reconceal
-accordingly.
-
-Set outline-search-reconceal to nil if current point is not
-concealed, to value of point if entire topic is concealed, and a
-list containing point if only the topic body is concealed.
-
-This will be used to determine whether outline-hide-current-entry
-or outline-hide-current-entry-completely will be necessary to
-restore the prior concealment state."
-
- (if (outline-mode-p)
- (setq outline-search-reconceal
- (if (outline-hidden-p)
- (save-excursion
- (if (re-search-backward outline-line-boundary-regexp nil 1)
- ;; Nil value means we got to b-o-b - wouldn't need
- ;; to advance.
- (forward-char 1))
- ; We'll return point or list
- ; containing point, depending
- ; on concealment state of
- ; topic prefix.
- (prog1 (if (outline-hidden-p) (point) (list (point)))
- ; And reveal the current
- ; search target:
- (outline-show-entry)))))))
-;;;_ > outline-isearch-advancing-business ()
-(defun outline-isearch-advancing-business ()
- "Do outline business like deexposing current point, if necessary.
-
-Works according to reconceal state registration."
- (if (and (outline-mode-p) outline-search-reconceal)
- (save-excursion
- (if (listp outline-search-reconceal)
- ;; Leave the topic visible:
- (progn (goto-char (car outline-search-reconceal))
- (outline-hide-current-entry))
- ;; Rehide the entire topic:
- (goto-char outline-search-reconceal)
- (outline-hide-current-entry-completely)))))
-;;;_ > isearch-terminate/outline-provisions ()
-(defun isearch-terminate/outline-provisions ()
- (interactive)
- (if (and (outline-mode-p) outline-enwrap-isearch-mode)
- (outline-isearch-advancing-business))
- (let ((outline-search-quitting t)
- (outline-search-reconceal nil))
- (real-isearch-terminate)))
-;;;_ > isearch-done/outline-provisions ()
-(defun isearch-done/outline-provisions (&optional nopush)
- (interactive)
- (if (and (outline-mode-p) outline-enwrap-isearch-mode)
- (progn (if (and outline-search-reconceal
- (not (listp outline-search-reconceal)))
- ;; The topic was concealed - reveal it, its siblings,
- ;; and any ancestors that are still concealed:
- (save-excursion
- (message "(exposing destination)")(sit-for 0)
- (outline-goto-prefix)
- ; There may be a closed blank
- ; line between prior and
- ; current topic that would be
- ; missed - provide for it:
- (if (not (bobp))
- (progn (forward-char -1) ; newline
- (if (eq ?\r (preceding-char))
- (outline-flag-region (1- (point))
- (point)
- ?\n))
- (forward-char 1)))
- ; Goto parent
- (outline-ascend-to-depth (1- (outline-recent-depth)))
- (outline-show-children)))
- (if (and (boundp 'outline-search-quitting)
- outline-search-quitting)
- nil
- ; We're concluding abort:
- (outline-isearch-arrival-business)
- (outline-show-children))))
- (if nopush
- ;; isearch-done in newer version of isearch mode takes arg:
- (real-isearch-done nopush)
- (real-isearch-done)))
-;;;_ > isearch-update/outline-provisions ()
-(defun isearch-update/outline-provisions ()
- "Wrapper dynamically adjusts isearch target exposure.
-
-Appropriately exposes and reconceals hidden outline portions, as
-necessary, in the course of searching."
- (if (not (and (outline-mode-p) outline-enwrap-isearch-mode))
- ;; Just do the plain business:
- (real-isearch-update)
-
- ;; Ah - provide for outline conditions:
- (outline-isearch-advancing-business)
- (real-isearch-update)
- (cond (isearch-success (outline-isearch-arrival-business))
- ((not isearch-success) (outline-isearch-advancing-business)))))
-
-;;;_ #8 Copying and printing
-
-;;;_ - Copy exposed
-;;;_ > outline-insert-listified (depth prefix bullet text)
-(defun outline-insert-listified (depth prefix bullet text)
- "Insert contents of listified outline portion in current buffer."
- (insert-string (concat (if (> depth 1) prefix "")
- (make-string (1- depth) ?\ )
- bullet))
- (while text
- (insert-string (car text))
- (if (setq text (cdr text))
- (insert-string "\n")))
- (insert-string "\n"))
-;;;_ > outline-copy-exposed (arg &optional tobuf)
-(defun outline-copy-exposed (arg &optional tobuf)
- "Duplicate exposed portions of current topic to another buffer.
-
-Other buffer has current buffers' name with \" exposed\" appended to it.
-
-With repeat count, copy the exposed portions of entire buffer."
-
- (interactive "P")
- (if (not tobuf)
- (setq tobuf (get-buffer-create (concat "*" (buffer-name) " exposed*"))))
- (let* ((start-pt (point))
- (beg (if arg (point-min) (outline-back-to-current-heading)))
- (end (if arg (point-max) (outline-end-of-current-subtree)))
- (buf (current-buffer)))
- (save-excursion (set-buffer tobuf)(erase-buffer))
- (outline-process-exposed 'outline-insert-listified
- beg
- end
- (current-buffer)
- tobuf)
- (goto-char (point-min))
- (pop-to-buffer buf)
- (goto-char start-pt)))
-
-;;;_ - LaTeX formatting
-;;;_ > outline-latex-verb-quote (str &optional flow)
-(defun outline-latex-verb-quote (str &optional flow)
- "Return copy of STRING for literal reproduction across latex processing.
-Expresses the original characters \(including carriage returns) of the
-string across latex processing."
- (mapconcat '(lambda (char)
- ;;;mess: (cond ((memq char '(?"" ?$ ?% ?# ?& ?- ?" ?` ?^ ?- ?*));;;"))))
- (cond ((memq char '(?\\ ?$ ?% ?# ?& ?{ ?} ?_ ?^ ?- ?*))
- (concat "\\char" (number-to-string char) "{}"))
- ((= char ?\n) "\\\\")
- (t (char-to-string char))))
- str
- ""))
-;;;_ > outline-latex-verbatim-quote-curr-line ()
-(defun outline-latex-verbatim-quote-curr-line ()
- "Express line for exact \(literal\) representation across latex processing.
-
-Adjust line contents so it is unaltered \(from the original line)
-across latex processing, within the context of a `verbatim'
-environment. Leaves point at the end of the line."
- (beginning-of-line)
- (let ((beg (point))
- (end (progn (end-of-line)(point))))
- (goto-char beg)
- (while (re-search-forward "\\\\"
- ;;"\\\\\\|\\{\\|\\}\\|\\_\\|\\$\\|\\\"\\|\\&\\|\\^\\|\\-\\|\\*\\|#"
- end ; bounded by end-of-line
- 1) ; no matches, move to end & return nil
- (goto-char (match-beginning 0))
- (insert-string "\\")
- (setq end (1+ end))
- (goto-char (1+ (match-end 0))))))
-;;;_ > outline-insert-latex-header (buf)
-(defun outline-insert-latex-header (buf)
- "Insert initial latex commands at point in BUFFER."
- ;; Much of this is being derived from the stuff in appendix of E in
- ;; the TeXBook, pg 421.
- (set-buffer buf)
- (let ((doc-style (format "\n\\documentstyle{%s}\n"
- "report"))
- (page-numbering (if outline-number-pages
- "\\pagestyle{empty}\n"
- ""))
- (linesdef (concat "\\def\\beginlines{"
- "\\par\\begingroup\\nobreak\\medskip"
- "\\parindent=0pt\n"
- " \\kern1pt\\nobreak \\obeylines \\obeyspaces "
- "\\everypar{\\strut}}\n"
- "\\def\\endlines{"
- "\\kern1pt\\endgroup\\medbreak\\noindent}\n"))
- (titlecmd (format "\\newcommand{\\titlecmd}[1]{{%s #1}}\n"
- outline-title-style))
- (labelcmd (format "\\newcommand{\\labelcmd}[1]{{%s #1}}\n"
- outline-label-style))
- (headlinecmd (format "\\newcommand{\\headlinecmd}[1]{{%s #1}}\n"
- outline-head-line-style))
- (bodylinecmd (format "\\newcommand{\\bodylinecmd}[1]{{%s #1}}\n"
- outline-body-line-style))
- (setlength (format "%s%s%s%s"
- "\\newlength{\\stepsize}\n"
- "\\setlength{\\stepsize}{"
- outline-indent
- "}\n"))
- (oneheadline (format "%s%s%s%s%s%s%s"
- "\\newcommand{\\OneHeadLine}[3]{%\n"
- "\\noindent%\n"
- "\\hspace*{#2\\stepsize}%\n"
- "\\labelcmd{#1}\\hspace*{.2cm}"
- "\\headlinecmd{#3}\\\\["
- outline-line-skip
- "]\n}\n"))
- (onebodyline (format "%s%s%s%s%s%s"
- "\\newcommand{\\OneBodyLine}[2]{%\n"
- "\\noindent%\n"
- "\\hspace*{#1\\stepsize}%\n"
- "\\bodylinecmd{#2}\\\\["
- outline-line-skip
- "]\n}\n"))
- (begindoc "\\begin{document}\n\\begin{center}\n")
- (title (format "%s%s%s%s"
- "\\titlecmd{"
- (outline-latex-verb-quote (if outline-title
- (condition-case err
- (eval outline-title)
- (error "<unnamed buffer>"))
- "Unnamed Outline"))
- "}\n"
- "\\end{center}\n\n"))
- (hsize "\\hsize = 7.5 true in\n")
- (hoffset "\\hoffset = -1.5 true in\n")
- (vspace "\\vspace{.1cm}\n\n"))
- (insert (concat doc-style
- page-numbering
- titlecmd
- labelcmd
- headlinecmd
- bodylinecmd
- setlength
- oneheadline
- onebodyline
- begindoc
- title
- hsize
- hoffset
- vspace)
- )))
-;;;_ > outline-insert-latex-trailer (buf)
-(defun outline-insert-latex-trailer (buf)
- "Insert concluding latex commands at point in BUFFER."
- (set-buffer buf)
- (insert "\n\\end{document}\n"))
-;;;_ > outline-latexify-one-item (depth prefix bullet text)
-(defun outline-latexify-one-item (depth prefix bullet text)
- "Insert LaTeX commands for formatting one outline item.
-
-Args are the topics' numeric DEPTH, the header PREFIX lead string, the
-BULLET string, and a list of TEXT strings for the body."
- (let* ((head-line (if text (car text)))
- (body-lines (cdr text))
- (curr-line)
- body-content bop)
- ; Do the head line:
- (insert-string (concat "\\OneHeadLine{\\verb\1 "
- (outline-latex-verb-quote bullet)
- "\1}{"
- depth
- "}{\\verb\1 "
- (if head-line
- (outline-latex-verb-quote head-line)
- "")
- "\1}\n"))
- (if (not body-lines)
- nil
- ;;(insert-string "\\beginlines\n")
- (insert-string "\\begin{verbatim}\n")
- (while body-lines
- (setq curr-line (car body-lines))
- (if (and (not body-content)
- (not (string-match "^\\s-*$" curr-line)))
- (setq body-content t))
- ; Mangle any occurrences of
- ; "\end{verbatim}" in text,
- ; it's special:
- (if (and body-content
- (setq bop (string-match "\\end{verbatim}" curr-line)))
- (setq curr-line (concat (substring curr-line 0 bop)
- ">"
- (substring curr-line bop))))
- ;;(insert-string "|" (car body-lines) "|")
- (insert-string curr-line)
- (outline-latex-verbatim-quote-curr-line)
- (insert-string "\n")
- (setq body-lines (cdr body-lines)))
- (if body-content
- (setq body-content nil)
- (forward-char -1)
- (insert-string "\\ ")
- (forward-char 1))
- ;;(insert-string "\\endlines\n")
- (insert-string "\\end{verbatim}\n")
- )))
-;;;_ > outline-latexify-exposed (arg &optional tobuf)
-(defun outline-latexify-exposed (arg &optional tobuf)
- "Format current topic's exposed portions to TOBUF for latex processing.
-TOBUF defaults to a buffer named the same as the current buffer, but
-with \"*\" prepended and \" latex-formed*\" appended.
-
-With repeat count, copy the exposed portions of entire buffer."
-
- (interactive "P")
- (if (not tobuf)
- (setq tobuf
- (get-buffer-create (concat "*" (buffer-name) " latexified*"))))
- (let* ((start-pt (point))
- (beg (if arg (point-min) (outline-back-to-current-heading)))
- (end (if arg (point-max) (outline-end-of-current-subtree)))
- (buf (current-buffer)))
- (set-buffer tobuf)
- (erase-buffer)
- (outline-insert-latex-header tobuf)
- (goto-char (point-max))
- (outline-process-exposed 'outline-latexify-one-item
- beg
- end
- buf
- tobuf)
- (goto-char (point-max))
- (outline-insert-latex-trailer tobuf)
- (goto-char (point-min))
- (pop-to-buffer buf)
- (goto-char start-pt)))
-
-;;;_ #9 miscellaneous
-;;;_ > outline-mark-topic ()
-(defun outline-mark-topic ()
- "Put the region around topic currently containing point."
- (interactive)
- (beginning-of-line)
- (outline-goto-prefix)
- (push-mark (point))
- (outline-end-of-current-subtree)
- (exchange-point-and-mark))
-;;;_ > outlineify-sticky ()
-;; outlinify-sticky is correct spelling; provide this alias for sticklers:
-(defalias 'outlinify-sticky 'outlineify-sticky)
-(defun outlineify-sticky (&optional arg)
- "Activate outline mode and establish file var so it is started subsequently.
-
-See doc-string for `outline-layout' and `outline-init' for details on
-setup for auto-startup."
-
- (interactive "P")
-
- (outline-mode t)
-
- (save-excursion
- (goto-char (point-min))
- (if (looking-at outline-regexp)
- t
- (outline-open-topic 2)
- (insert-string (concat "Dummy outline topic header - see"
- "`outline-mode' docstring for info."))
- (next-line 1)
- (goto-char (point-max))
- (next-line 1)
- (outline-open-topic 0)
- (insert-string "Local emacs vars.\n")
- (outline-open-topic 1)
- (insert-string "(`outline-layout' is for allout.el outline-mode)\n")
- (outline-open-topic 0)
- (insert-string "Local variables:\n")
- (outline-open-topic 0)
- (insert-string (format "outline-layout: %s\n"
- (or outline-layout
- '(1 : 0))))
- (outline-open-topic 0)
- (insert-string "End:\n"))))
-;;;_ > solicit-char-in-string (prompt string &optional do-defaulting)
-(defun solicit-char-in-string (prompt string &optional do-defaulting)
- "Solicit (with first arg PROMPT) choice of a character from string STRING.
-
-Optional arg DO-DEFAULTING indicates to accept empty input (CR)."
-
- (let ((new-prompt prompt)
- got)
-
- (while (not got)
- (message "%s" new-prompt)
-
- ;; We do our own reading here, so we can circumvent, eg, special
- ;; treatment for `?' character. (Might oughta change minibuffer
- ;; keymap instead, oh well.)
- (setq got
- (char-to-string (let ((cursor-in-echo-area nil)) (read-char))))
-
- (if (null (string-match (regexp-quote got) string))
- (if (and do-defaulting (string= got "\^M"))
- ;; We're defaulting, return null string to indicate that:
- (setq got "")
- ;; Failed match and not defaulting,
- ;; set the prompt to give feedback,
- (setq new-prompt (concat prompt
- got
- " ...pick from: "
- string
- ""))
- ;; and set loop to try again:
- (setq got nil))
- ;; Got a match - give feedback:
- (message "")))
- ;; got something out of loop - return it:
- got)
- )
-;;;_ > regexp-sans-escapes (string)
-(defun regexp-sans-escapes (regexp &optional successive-backslashes)
- "Return a copy of REGEXP with all character escapes stripped out.
-
-Representations of actual backslashes - '\\\\\\\\' - are left as a
-single backslash.
-
-Optional arg SUCCESSIVE-BACKSLASHES is used internally for recursion."
-
- (if (string= regexp "")
- ""
- ;; Set successive-backslashes to number if current char is
- ;; backslash, or else to nil:
- (setq successive-backslashes
- (if (= (aref regexp 0) ?\\)
- (if successive-backslashes (1+ successive-backslashes) 1)
- nil))
- (if (or (not successive-backslashes) (= 2 successive-backslashes))
- ;; Include first char:
- (concat (substring regexp 0 1)
- (regexp-sans-escapes (substring regexp 1)))
- ;; Exclude first char, but maintain count:
- (regexp-sans-escapes (substring regexp 1) successive-backslashes))))
-;;;_ - add-hook definition for divergent emacsen
-;;;_ > add-hook (hook function &optional append)
-(if (not (fboundp 'add-hook))
- (defun add-hook (hook function &optional append)
- "Add to the value of HOOK the function FUNCTION unless already present.
-\(It becomes the first hook on the list unless optional APPEND is non-nil, in
-which case it becomes the last). 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
- (if append
- (nconc (symbol-value hook) (list function))
- (cons function (symbol-value hook)))))))
-
-;;;_ #10 Under development
-;;;_ > outline-bullet-isearch (&optional bullet)
-(defun outline-bullet-isearch (&optional bullet)
- "Isearch \(regexp\) for topic with bullet BULLET."
- (interactive)
- (if (not bullet)
- (setq bullet (solicit-char-in-string
- "ISearch for topic with bullet: "
- (regexp-sans-escapes outline-bullets-string))))
-
- (let ((isearch-regexp t)
- (isearch-string (concat "^"
- outline-header-prefix
- "[ \t]*"
- bullet)))
- (isearch-repeat 'forward)
- (isearch-mode t)))
-;;;_ ? Re hooking up with isearch - use isearch-op-fun rather than
-;;; wrapping the isearch functions.
-
-;;;_* Local emacs vars.
-;;; The following `outline-layout' local variable setting:
-;;; - closes all topics from the first topic to just before the third-to-last,
-;;; - shows the children of the third to last (config vars)
-;;; - and the second to last (code section),
-;;; - and closes the last topic (this local-variables section).
-;;;Local variables:
-;;;outline-layout: (0 : -1 -1 0)
-;;;End:
-
-;; allout.el ends here
diff --git a/lisp/ange-ftp.el b/lisp/ange-ftp.el
deleted file mode 100644
index 137e63abd79..00000000000
--- a/lisp/ange-ftp.el
+++ /dev/null
@@ -1,5479 +0,0 @@
-;;; ange-ftp.el --- transparent FTP support for GNU Emacs
-
-;; Copyright (C) 1989,90,91,92,93,94,95,96 Free Software Foundation, Inc.
-
-;; Author: Andy Norman (ange@hplb.hpl.hp.com)
-;; Maintainer: FSF
-;; Keywords: comm
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package attempts to make accessing files and directories using FTP
-;; from within GNU Emacs as simple and transparent as possible. A subset of
-;; the common file-handling routines are extended to interact with FTP.
-
-;; Usage:
-;;
-;; Some of the common GNU Emacs file-handling operations have been made
-;; FTP-smart. If one of these routines is given a filename that matches
-;; '/user@host:name' then it will spawn an FTP process connecting to machine
-;; 'host' as account 'user' and perform its operation on the file 'name'.
-;;
-;; For example: if find-file is given a filename of:
-;;
-;; /ange@anorman:/tmp/notes
-;;
-;; then ange-ftp spawns an FTP process, connect to the host 'anorman' as
-;; user 'ange', get the file '/tmp/notes' and pop up a buffer containing the
-;; contents of that file as if it were on the local filesystem. If ange-ftp
-;; needs a password to connect then it reads one in the echo area.
-
-;; Extended filename syntax:
-;;
-;; The default extended filename syntax is '/user@host:name', where the
-;; 'user@' part may be omitted. This syntax can be customised to a certain
-;; extent by changing ange-ftp-name-format. There are limitations.
-;;
-;; If the user part is omitted then ange-ftp generates a default user
-;; instead whose value depends on the variable ange-ftp-default-user.
-
-;; Passwords:
-;;
-;; A password is required for each host/user pair. Ange-ftp reads passwords
-;; as needed. You can also specify a password with ange-ftp-set-passwd, or
-;; in a *valid* ~/.netrc file.
-
-;; Passwords for user "anonymous":
-;;
-;; Passwords for the user "anonymous" (or "ftp") are handled
-;; specially. The variable `ange-ftp-generate-anonymous-password'
-;; controls what happens: if the value of this variable is a string,
-;; then this is used as the password; if non-nil (the default), then
-;; the value of `user-mail-address' is used; if nil then the user
-;; is prompted for a password as normal.
-
-;; "Dumb" UNIX hosts:
-;;
-;; The FTP servers on some UNIX machines have problems if the 'ls' command is
-;; used.
-;;
-;; The routine ange-ftp-add-dumb-unix-host can be called to tell ange-ftp to
-;; limit itself to the DIR command and not 'ls' for a given UNIX host. Note
-;; that this change will take effect for the current GNU Emacs session only.
-;; See below for a discussion of non-UNIX hosts. If a large number of
-;; machines with similar hostnames have this problem then it is easier to set
-;; the value of ange-ftp-dumb-unix-host-regexp in your .emacs file. ange-ftp
-;; is unable to automatically recognize dumb unix hosts.
-
-;; File name completion:
-;;
-;; Full file-name completion is supported on UNIX, VMS, CMS, and MTS hosts.
-;; To do filename completion, ange-ftp needs a listing from the remote host.
-;; Therefore, for very slow connections, it might not save any time.
-
-;; FTP processes:
-;;
-;; When ange-ftp starts up an FTP process, it leaves it running for speed
-;; purposes. Some FTP servers will close the connection after a period of
-;; time, but ange-ftp should be able to quietly reconnect the next time that
-;; the process is needed.
-;;
-;; Killing the "*ftp user@host*" buffer also kills the ftp process.
-;; This should not cause ange-ftp any grief.
-
-;; Binary file transfers:
-;;
-;; By default ange-ftp transfers files in ASCII mode. If a file being
-;; transferred matches the value of ange-ftp-binary-file-name-regexp then
-;; binary mode is used for that transfer.
-
-;; Account passwords:
-;;
-;; Some FTP servers require an additional password which is sent by the
-;; ACCOUNT command. ange-ftp partially supports this by allowing the user to
-;; specify an account password by either calling ange-ftp-set-account, or by
-;; specifying an account token in the .netrc file. If the account password
-;; is set by either of these methods then ange-ftp will issue an ACCOUNT
-;; command upon starting the FTP process.
-
-;; Preloading:
-;;
-;; ange-ftp can be preloaded, but must be put in the site-init.el file and
-;; not the site-load.el file in order for the documentation strings for the
-;; functions being overloaded to be available.
-
-;; Status reports:
-;;
-;; Most ange-ftp commands that talk to the FTP process output a status
-;; message on what they are doing. In addition, ange-ftp can take advantage
-;; of the FTP client's HASH command to display the status of transferring
-;; files and listing directories. See the documentation for the variables
-;; ange-ftp-{ascii,binary}-hash-mark-size, ange-ftp-send-hash and
-;; ange-ftp-process-verbose for more details.
-
-;; Gateways:
-;;
-;; Sometimes it is necessary for the FTP process to be run on a different
-;; machine than the machine running GNU Emacs. This can happen when the
-;; local machine has restrictions on what hosts it can access.
-;;
-;; ange-ftp has support for running the ftp process on a different (gateway)
-;; machine. The way it works is as follows:
-;;
-;; 1) Set the variable 'ange-ftp-gateway-host' to the name of a machine
-;; that doesn't have the access restrictions.
-;;
-;; 2) Set the variable 'ange-ftp-local-host-regexp' to a regular expression
-;; that matches hosts that can be contacted from running a local ftp
-;; process, but fails to match hosts that can't be accessed locally. For
-;; example:
-;;
-;; "\\.hp\\.com$\\|^[^.]*$"
-;;
-;; will match all hosts that are in the .hp.com domain, or don't have an
-;; explicit domain in their name, but will fail to match hosts with
-;; explicit domains or that are specified by their ip address.
-;;
-;; 3) Using NFS and symlinks, make sure that there is a shared directory with
-;; the *same* name between the local machine and the gateway machine.
-;; This directory is necessary for temporary files created by ange-ftp.
-;;
-;; 4) Set the variable 'ange-ftp-gateway-tmp-name-template' to the name of
-;; this directory plus an identifying filename prefix. For example:
-;;
-;; "/nfs/hplose/ange/ange-ftp"
-;;
-;; where /nfs/hplose/ange is a directory that is shared between the
-;; gateway machine and the local machine.
-;;
-;; The simplest way of getting a ftp process running on the gateway machine
-;; is if you can spawn a remote shell using either 'rsh' or 'remsh'. If you
-;; can't do this for some reason such as security then points 7 onwards will
-;; discuss an alternative approach.
-;;
-;; 5) Set the variable ange-ftp-gateway-program to the name of the remote
-;; shell process such as 'remsh' or 'rsh' if the default isn't correct.
-;;
-;; 6) Set the variable ange-ftp-gateway-program-interactive to nil if it
-;; isn't already. This tells ange-ftp that you are using a remote shell
-;; rather than logging in using telnet or rlogin.
-;;
-;; That should be all you need to allow ange-ftp to spawn a ftp process on
-;; the gateway machine. If you have to use telnet or rlogin to get to the
-;; gateway machine then follow the instructions below.
-;;
-;; 7) Set the variable ange-ftp-gateway-program to the name of the program
-;; that lets you log onto the gateway machine. This may be something like
-;; telnet or rlogin.
-;;
-;; 8) Set the variable ange-ftp-gateway-prompt-pattern to a regular
-;; expression that matches the prompt you get when you login to the
-;; gateway machine. Be very specific here; this regexp must not match
-;; *anything* in your login banner except this prompt.
-;; shell-prompt-pattern is far too general as it appears to match some
-;; login banners from Sun machines. For example:
-;;
-;; "^$*$ *"
-;;
-;; 9) Set the variable ange-ftp-gateway-program-interactive to 't' to let
-;; ange-ftp know that it has to "hand-hold" the login to the gateway
-;; machine.
-;;
-;; 10) Set the variable ange-ftp-gateway-setup-term-command to a UNIX command
-;; that will put the pty connected to the gateway machine into a
-;; no-echoing mode, and will strip off carriage-returns from output from
-;; the gateway machine. For example:
-;;
-;; "stty -onlcr -echo"
-;;
-;; will work on HP-UX machines, whereas:
-;;
-;; "stty -echo nl"
-;;
-;; appears to work for some Sun machines.
-;;
-;; That's all there is to it.
-
-;; Smart gateways:
-;;
-;; If you have a "smart" ftp program that allows you to issue commands like
-;; "USER foo@bar" which do nice proxy things, then look at the variables
-;; ange-ftp-smart-gateway and ange-ftp-smart-gateway-port.
-;;
-;; Otherwise, if there is an alternate ftp program that implements proxy in
-;; a transparent way (i.e. w/o specifying the proxy host), that will
-;; connect you directly to the desired destination host:
-;; Set ange-ftp-gateway-ftp-program-name to that program's name.
-;; Set ange-ftp-local-host-regexp to a value as stated earlier on.
-;; Leave ange-ftp-gateway-host set to nil.
-;; Set ange-ftp-smart-gateway to t.
-
-;; Tips for using ange-ftp:
-;;
-;; 1. For dired to work on a host which marks symlinks with a trailing @ in
-;; an ls -alF listing, you need to (setq dired-ls-F-marks-symlinks t).
-;; Most UNIX systems do not do this, but ULTRIX does. If you think that
-;; there is a chance you might connect to an ULTRIX machine (such as
-;; prep.ai.mit.edu), then set this variable accordingly. This will have
-;; the side effect that dired will have problems with symlinks whose names
-;; end in an @. If you get yourself into this situation then editing
-;; dired's ls-switches to remove "F", will temporarily fix things.
-;;
-;; 2. If you know that you are connecting to a certain non-UNIX machine
-;; frequently, and ange-ftp seems to be unable to guess its host-type,
-;; then setting the appropriate host-type regexp
-;; (ange-ftp-vms-host-regexp, ange-ftp-mts-host-regexp, or
-;; ange-ftp-cms-host-regexp) accordingly should help. Also, please report
-;; ange-ftp's inability to recognize the host-type as a bug.
-;;
-;; 3. For slow connections, you might get "listing unreadable" error
-;; messages, or get an empty buffer for a file that you know has something
-;; in it. The solution is to increase the value of ange-ftp-retry-time.
-;; Its default value is 5 which is plenty for reasonable connections.
-;; However, for some transatlantic connections I set this to 20.
-;;
-;; 4. Beware of compressing files on non-UNIX hosts. Ange-ftp will do it by
-;; copying the file to the local machine, compressing it there, and then
-;; sending it back. Binary file transfers between machines of different
-;; architectures can be a risky business. Test things out first on some
-;; test files. See "Bugs" below. Also, note that ange-ftp copies files by
-;; moving them through the local machine. Again, be careful when doing
-;; this with binary files on non-Unix machines.
-;;
-;; 5. Beware that dired over ftp will use your setting of dired-no-confirm
-;; (list of dired commands for which confirmation is not asked). You
-;; might want to reconsider your setting of this variable, because you
-;; might want confirmation for more commands on remote direds than on
-;; local direds. For example, I strongly recommend that you not include
-;; compress and uncompress in this list. If there is enough demand it
-;; might be a good idea to have an alist ange-ftp-dired-no-confirm of
-;; pairs ( TYPE . LIST ), where TYPE is an operating system type and LIST
-;; is a list of commands for which confirmation would be suppressed. Then
-;; remote dired listings would take their (buffer-local) value of
-;; dired-no-confirm from this alist. Who votes for this?
-
-;; ---------------------------------------------------------------------
-;; Non-UNIX support:
-;; ---------------------------------------------------------------------
-
-;; VMS support:
-;;
-;; Ange-ftp has full support for VMS hosts. It
-;; should be able to automatically recognize any VMS machine. However, if it
-;; fails to do this, you can use the command ange-ftp-add-vms-host. As well,
-;; you can set the variable ange-ftp-vms-host-regexp in your .emacs file. We
-;; would be grateful if you would report any failures to automatically
-;; recognize a VMS host as a bug.
-;;
-;; Filename Syntax:
-;;
-;; For ease of *implementation*, the user enters the VMS filename syntax in a
-;; UNIX-y way. For example:
-;; PUB$:[ANONYMOUS.SDSCPUB.NEXT]README.TXT;1
-;; would be entered as:
-;; /PUB$$:/ANONYMOUS/SDSCPUB/NEXT/README.TXT;1
-;; i.e. to log in as anonymous on ymir.claremont.edu and grab the file:
-;; [.CSV.POLICY]RULES.MEM
-;; you would type:
-;; C-x C-f /anonymous@ymir.claremont.edu:CSV/POLICY/RULES.MEM
-;;
-;; A legal VMS filename is of the form: FILE.TYPE;##
-;; where FILE can be up to 39 characters
-;; TYPE can be up to 39 characters
-;; ## is a version number (an integer between 1 and 32,767)
-;; Valid characters in FILE and TYPE are A-Z 0-9 _ - $
-;; $ cannot begin a filename, and - cannot be used as the first or last
-;; character.
-;;
-;; Tips:
-;; 1. Although VMS is not case sensitive, EMACS running under UNIX is.
-;; Therefore, to access a VMS file, you must enter the filename with upper
-;; case letters.
-;; 2. To access the latest version of file under VMS, you use the filename
-;; without the ";" and version number. You should always edit the latest
-;; version of a file. If you want to edit an earlier version, copy it to a
-;; new file first. This has nothing to do with ange-ftp, but is simply
-;; good VMS operating practice. Therefore, to edit FILE.TXT;3 (say 3 is
-;; latest version), do C-x C-f /ymir.claremont.edu:FILE.TXT. If you
-;; inadvertently do C-x C-f /ymir.claremont.edu:FILE.TXT;3, you will find
-;; that VMS will not allow you to save the file because it will refuse to
-;; overwrite FILE.TXT;3, but instead will want to create FILE.TXT;4, and
-;; attach the buffer to this file. To get out of this situation, M-x
-;; write-file /ymir.claremont.edu:FILE.TXT will attach the buffer to
-;; latest version of the file. For this reason, in dired "f"
-;; (dired-find-file), always loads the file sans version, whereas "v",
-;; (dired-view-file), always loads the explicit version number. The
-;; reasoning being that it reasonable to view old versions of a file, but
-;; not to edit them.
-;; 3. EMACS has a feature in which it does environment variable substitution
-;; in filenames. Therefore, to enter a $ in a filename, you must quote it
-;; by typing $$.
-
-;; MTS support:
-;;
-;; Ange-ftp has full support for hosts running
-;; the Michigan terminal system. It should be able to automatically
-;; recognize any MTS machine. However, if it fails to do this, you can use
-;; the command ange-ftp-add-mts-host. As well, you can set the variable
-;; ange-ftp-mts-host-regexp in your .emacs file. We would be grateful if you
-;; would report any failures to automatically recognize a MTS host as a bug.
-;;
-;; Filename syntax:
-;;
-;; MTS filenames are entered in a UNIX-y way. For example, if your account
-;; was YYYY, the file FILE in the account XXXX: on mtsg.ubc.ca would be
-;; entered as
-;; /YYYY@mtsg.ubc.ca:/XXXX:/FILE
-;; In other words, MTS accounts are treated as UNIX directories. Of course,
-;; to access a file in another account, you must have access permission for
-;; it. If FILE were in your own account, then you could enter it in a
-;; relative name fashion as
-;; /YYYY@mtsg.ubc.ca:FILE
-;; MTS filenames can be up to 12 characters. Like UNIX, the structure of the
-;; filename does not contain a TYPE (i.e. it can have as many "."'s as you
-;; like.) MTS filenames are always in upper case, and hence be sure to enter
-;; them as such! MTS is not case sensitive, but an EMACS running under UNIX
-;; is.
-
-;; CMS support:
-;;
-;; Ange-ftp has full support for hosts running
-;; CMS. It should be able to automatically recognize any CMS machine.
-;; However, if it fails to do this, you can use the command
-;; ange-ftp-add-cms-host. As well, you can set the variable
-;; ange-ftp-cms-host-regexp in your .emacs file. We would be grateful if you
-;; would report any failures to automatically recognize a CMS host as a bug.
-;;
-;; Filename syntax:
-;;
-;; CMS filenames are entered in a UNIX-y way. In otherwords, minidisks are
-;; treated as UNIX directories. For example to access the file READ.ME in
-;; minidisk *.311 on cuvmb.cc.columbia.edu, you would enter
-;; /anonymous@cuvmb.cc.columbia.edu:/*.311/READ.ME
-;; If *.301 is the default minidisk for this account, you could access
-;; FOO.BAR on this minidisk as
-;; /anonymous@cuvmb.cc.columbia.edu:FOO.BAR
-;; CMS filenames are of the form FILE.TYPE, where both FILE and TYPE can be
-;; up to 8 characters. Again, beware that CMS filenames are always upper
-;; case, and hence must be entered as such.
-;;
-;; Tips:
-;; 1. CMS machines, with the exception of anonymous accounts, nearly always
-;; need an account password. To have ange-ftp send an account password,
-;; you can either include it in your .netrc file, or use
-;; ange-ftp-set-account.
-;; 2. Ange-ftp cannot send "write passwords" for a minidisk. Hopefully, we
-;; can fix this.
-;;
-;; ------------------------------------------------------------------
-;; Bugs:
-;; ------------------------------------------------------------------
-;;
-;; 1. Umask problems:
-;; Be warned that files created by using ange-ftp will take account of the
-;; umask of the ftp daemon process rather than the umask of the creating
-;; user. This is particularly important when logging in as the root user.
-;; The way that I tighten up the ftp daemon's umask under HP-UX is to make
-;; sure that the umask is changed to 027 before I spawn /etc/inetd. I
-;; suspect that there is something similar on other systems.
-;;
-;; 2. Some combinations of FTP clients and servers break and get out of sync
-;; when asked to list a non-existent directory. Some of the ai.mit.edu
-;; machines cause this problem for some FTP clients. Using
-;; ange-ftp-kill-ftp-process can restart the ftp process, which
-;; should get things back in sync.
-;;
-;; 3. Ange-ftp does not check to make sure that when creating a new file,
-;; you provide a valid filename for the remote operating system.
-;; If you do not, then the remote FTP server will most likely
-;; translate your filename in some way. This may cause ange-ftp to
-;; get confused about what exactly is the name of the file. The
-;; most common causes of this are using lower case filenames on systems
-;; which support only upper case, and using filenames which are too
-;; long.
-;;
-;; 4. Null (blank) passwords confuse both ange-ftp and some FTP daemons.
-;;
-;; 5. Ange-ftp likes to use pty's to talk to its FTP processes. If GNU Emacs
-;; for some reason creates a FTP process that only talks via pipes then
-;; ange-ftp won't be getting the information it requires at the time that
-;; it wants it since pipes flush at different times to pty's. One
-;; disgusting way around this problem is to talk to the FTP process via
-;; rlogin which does the 'right' things with pty's.
-;;
-;; 6. For CMS support, we send too many cd's. Since cd's are cheap, I haven't
-;; worried about this too much. Eventually, we should have some caching
-;; of the current minidisk.
-;;
-;; 7. Some CMS machines do not assign a default minidisk when you ftp them as
-;; anonymous. It is then necessary to guess a valid minidisk name, and cd
-;; to it. This is (understandably) beyond ange-ftp.
-;;
-;; 8. Remote to remote copying of files on non-Unix machines can be risky.
-;; Depending on the variable ange-ftp-binary-file-name-regexp, ange-ftp
-;; will use binary mode for the copy. Between systems of different
-;; architecture, this still may not be enough to guarantee the integrity
-;; of binary files. Binary file transfers from VMS machines are
-;; particularly problematical. Should ange-ftp-binary-file-name-regexp be
-;; an alist of OS type, regexp pairs?
-;;
-;; 9. The code to do compression of files over ftp is not as careful as it
-;; should be. It deletes the old remote version of the file, before
-;; actually checking if the local to remote transfer of the compressed
-;; file succeeds. Of course to delete the original version of the file
-;; after transferring the compressed version back is also dangerous,
-;; because some OS's have severe restrictions on the length of filenames,
-;; and when the compressed version is copied back the "-Z" or ".Z" may be
-;; truncated. Then, ange-ftp would delete the only remaining version of
-;; the file. Maybe ange-ftp should make backups when it compresses files
-;; (of course, the backup "~" could also be truncated off, sigh...).
-;; Suggestions?
-;;
-;; 10. If a dir listing is attempted for an empty directory on (at least
-;; some) VMS hosts, an ftp error is given. This is really an ftp bug, and
-;; I don't know how to get ange-ftp work to around it.
-;;
-;; 11. Bombs on filenames that start with a space. Deals well with filenames
-;; containing spaces, but beware that the remote ftpd may not like them
-;; much.
-;;
-;; 12. The dired support for non-Unix-like systems does not currently work.
-;; It needs to be reimplemented by modifying the parse-...-listing
-;; functions to convert the directory listing to ls -l format.
-;;
-;; 13. The famous @ bug. As mentioned above in TIPS, ULTRIX marks symlinks
-;; with a trailing @ in a ls -alF listing. In order to account for this
-;; ange-ftp looks to chop trailing @'s off of symlink names when it is
-;; parsing a listing with the F switch. This will cause ange-ftp to
-;; incorrectly get the name of a symlink on a non-ULTRIX host if its name
-;; ends in an @. ange-ftp will correct itself if you take F out of the
-;; dired ls switches (C-u s will allow you to edit the switches). The
-;; dired buffer will be automatically reverted, which will allow ange-ftp
-;; to fix its files hashtable. A cookie to anyone who can think of a
-;; fast, sure-fire way to recognize ULTRIX over ftp.
-
-;; If you find any bugs or problems with this package, PLEASE either e-mail
-;; the above author, or send a message to the ange-ftp-lovers mailing list
-;; below. Ideas and constructive comments are especially welcome.
-
-;; ange-ftp-lovers:
-;;
-;; ange-ftp has its own mailing list modestly called ange-ftp-lovers. All
-;; users of ange-ftp are welcome to subscribe (see below) and to discuss
-;; aspects of ange-ftp. New versions of ange-ftp are posted periodically to
-;; the mailing list.
-;;
-;; To [un]subscribe to ange-ftp-lovers, or to report mailer problems with the
-;; list, please mail one of the following addresses:
-;;
-;; ange-ftp-lovers-request@anorman.hpl.hp.com
-;; or
-;; ange-ftp-lovers-request%anorman.hpl.hp.com@hplb.hpl.hp.com
-;;
-;; Please don't forget the -request part.
-;;
-;; For mail to be posted directly to ange-ftp-lovers, send to one of the
-;; following addresses:
-;;
-;; ange-ftp-lovers@anorman.hpl.hp.com
-;; or
-;; ange-ftp-lovers%anorman.hpl.hp.com@hplb.hpl.hp.com
-;;
-;; Alternatively, there is a mailing list that only gets announcements of new
-;; ange-ftp releases. This is called ange-ftp-lovers-announce, and can be
-;; subscribed to by e-mailing to the -request address as above. Please make
-;; it clear in the request which mailing list you wish to join.
-
-;; The latest version of ange-ftp can usually be obtained via anonymous ftp
-;; from:
-;; alpha.gnu.ai.mit.edu:ange-ftp/ange-ftp.tar.Z
-;; or:
-;; ugle.unit.no:/pub/gnu/emacs-lisp/ange-ftp.tar.Z
-;; or:
-;; archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/packages/ange-ftp.tar.Z
-
-;; The archives for ange-ftp-lovers can be found via anonymous ftp under:
-;;
-;; ftp.reed.edu:pub/mailing-lists/ange-ftp/
-
-;; -----------------------------------------------------------
-;; Technical information on this package:
-;; -----------------------------------------------------------
-
-;; ange-ftp works by putting a handler on file-name-handler-alist
-;; which is called by many primitives, and a few non-primitives,
-;; whenever they see a file name of the appropriate sort.
-
-;; Checklist for adding non-UNIX support for TYPE
-;;
-;; The following functions may need TYPE versions:
-;; (not all functions will be needed for every OS)
-;;
-;; ange-ftp-fix-name-for-TYPE
-;; ange-ftp-fix-dir-name-for-TYPE
-;; ange-ftp-TYPE-host
-;; ange-ftp-TYPE-add-host
-;; ange-ftp-parse-TYPE-listing
-;; ange-ftp-TYPE-delete-file-entry
-;; ange-ftp-TYPE-add-file-entry
-;; ange-ftp-TYPE-file-name-as-directory
-;; ange-ftp-TYPE-make-compressed-filename
-;; ange-ftp-TYPE-file-name-sans-versions
-;;
-;; Variables:
-;;
-;; ange-ftp-TYPE-host-regexp
-;; May need to add TYPE to ange-ftp-dumb-host-types
-;;
-;; Check the following functions for OS dependent coding:
-;;
-;; ange-ftp-host-type
-;; ange-ftp-guess-host-type
-;; ange-ftp-allow-child-lookup
-
-;; Host type conventions:
-;;
-;; The function ange-ftp-host-type and the variable ange-ftp-dired-host-type
-;; (mostly) follow the following conventions for remote host types. At
-;; least, I think that future code should try to follow these conventions,
-;; and the current code should eventually be made compliant.
-;;
-;; nil = local host type, whatever that is (probably unix).
-;; Think nil as in "not a remote host". This value is used by
-;; ange-ftp-dired-host-type for local buffers.
-;;
-;; t = a remote host of unknown type. Think t as in true, it's remote.
-;; Currently, 'unix is used as the default remote host type.
-;; Maybe we should use t.
-;;
-;; 'type = a remote host of TYPE type.
-;;
-;; 'type:list = a remote host of TYPE type, using a specialized ftp listing
-;; program called list. This is currently only used for Unix
-;; dl (descriptive listings), when ange-ftp-dired-host-type
-;; is set to 'unix:dl.
-
-;; Bug report codes:
-;;
-;; Because of their naive faith in this code, there are certain situations
-;; which the writers of this program believe could never happen. However,
-;; being realists they have put calls to `error' in the program at these
-;; points. These errors provide a code, which is an integer, greater than 1.
-;; To aid debugging. the error codes, and the functions in which they reside
-;; are listed below.
-;;
-;; 1: See ange-ftp-ls
-;;
-
-;; -----------------------------------------------------------
-;; Hall of fame:
-;; -----------------------------------------------------------
-;;
-;; Thanks to Roland McGrath for improving the filename syntax handling,
-;; for suggesting many enhancements and for numerous cleanups to the code.
-;;
-;; Thanks to Jamie Zawinski for bugfixes and for ideas such as gateways.
-;;
-;; Thanks to Ken Laprade for improved .netrc parsing, password reading, and
-;; dired / shell auto-loading.
-;;
-;; Thanks to Sebastian Kremer for dired support and for many ideas and
-;; bugfixes.
-;;
-;; Thanks to Joe Wells for bugfixes, the original non-UNIX system support,
-;; VOS support, and hostname completion.
-;;
-;; Thanks to Nakagawa Takayuki for many good ideas, filename-completion, help
-;; with file-name expansion, efficiency worries, stylistic concerns and many
-;; bugfixes.
-;;
-;; Thanks to Sandy Rutherford who re-wrote most of ange-ftp to support VMS,
-;; MTS, CMS and UNIX-dls. Sandy also added dired-support for non-UNIX OS and
-;; auto-recognition of the host type.
-;;
-;; Thanks to Dave Smith who wrote the info file for ange-ftp.
-;;
-;; Finally, thanks to Keith Waclena, Mark D. Baushke, Terence Kelleher, Ping
-;; Zhou, Edward Vielmetti, Jack Repenning, Mike Balenger, Todd Kaufmann,
-;; Kjetil Svarstad, Tom Wurgler, Linus Tolke, Niko Makila, Carl Edman, Bill
-;; Trost, Dave Brennan, Dan Jacobson, Andy Scott, Steve Anderson, Sanjay
-;; Mathur, the folks on the ange-ftp-lovers mailing list and many others
-;; whose names I've forgotten who have helped to debug and fix problems with
-;; ange-ftp.el.
-
-;;; Code:
-
-(require 'comint)
-
-;;;; ------------------------------------------------------------
-;;;; User customization variables.
-;;;; ------------------------------------------------------------
-
-(defvar ange-ftp-name-format
- '("^/\\(\\([^@/:]*\\)@\\)?\\([^@/:]*[^@/:.]\\):\\(.*\\)" . (3 2 4))
- "*Format of a fully expanded remote file name.
-This is a list of the form \(REGEXP HOST USER NAME\),
-where REGEXP is a regular expression matching
-the full remote name, and HOST, USER, and NAME are the numbers of
-parenthesized expressions in REGEXP for the components (in that order).")
-
-;; ange-ftp-multi-skip-msgs should only match ###-, where ### is one of
-;; the number codes corresponding to ange-ftp-good-msgs or ange-ftp-fatal-msgs.
-;; Otherwise, ange-ftp will go into multi-skip mode, and never come out.
-
-(defvar ange-ftp-multi-msgs
- "^220-\\|^230-\\|^226\\|^25.-\\|^221-\\|^200-\\|^331-\\|^4[25]1-\\|^530-"
- "*Regular expression matching the start of a multiline ftp reply.")
-
-(defvar ange-ftp-good-msgs
- "^220 \\|^230 \\|^226 \\|^25. \\|^221 \\|^200 \\|^[Hh]ash mark"
- "*Regular expression matching ftp \"success\" messages.")
-
-;; CMS and the odd VMS machine say 200 Port rather than 200 PORT.
-;; Also CMS machines use a multiline 550- reply to say that you
-;; don't have write permission. ange-ftp gets into multi-line skip
-;; mode and hangs. Have it ignore 550- instead. It will then barf
-;; when it gets the 550 line, as it should.
-
-(defvar ange-ftp-skip-msgs
- (concat "^200 \\(PORT\\|Port\\) \\|^331 \\|^150 \\|^350 \\|^[0-9]+ bytes \\|"
- "^Connected \\|^$\\|^Remote system\\|^Using\\|^ \\|Password:\\|"
- "^Data connection \\|"
- "^local:\\|^Trying\\|^125 \\|^550-\\|^221 .*oodbye\\|"
- "^227 .*[Pp]assive")
- "*Regular expression matching ftp messages that can be ignored.")
-
-(defvar ange-ftp-fatal-msgs
- (concat "^ftp: \\|^Not connected\\|^530 \\|^4[25]1 \\|rcmd: \\|"
- "^No control connection\\|unknown host\\|^lost connection")
- "*Regular expression matching ftp messages that indicate serious errors.
-These mean that the FTP process should (or already has) been killed.")
-
-(defvar ange-ftp-gateway-fatal-msgs
- "No route to host\\|Connection closed\\|No such host\\|Login incorrect"
- "*Regular expression matching login failure messages from rlogin/telnet.")
-
-(defvar ange-ftp-xfer-size-msgs
- "^150 .* connection for .* (\\([0-9]+\\) bytes)"
- "*Regular expression used to determine the number of bytes in a FTP transfer.")
-
-(defvar ange-ftp-tmp-name-template "/tmp/ange-ftp"
- "*Template used to create temporary files.")
-
-(defvar ange-ftp-gateway-tmp-name-template "/tmp/ange-ftp"
- "*Template used to create temporary files when ftp-ing through a gateway.
-Files starting with this prefix need to be accessible from BOTH the local
-machine and the gateway machine, and need to have the SAME name on both
-machines, that is, /tmp is probably NOT what you want, since that is rarely
-cross-mounted.")
-
-(defvar ange-ftp-netrc-filename "~/.netrc"
- "*File in .netrc format to search for passwords.")
-
-(defvar ange-ftp-disable-netrc-security-check nil
- "*If non-nil avoid checking permissions on the .netrc file.")
-
-(defvar ange-ftp-default-user nil
- "*User name to use when none is specified in a file name.
-If non-nil but not a string, you are prompted for the name.
-If nil, the value of `ange-ftp-netrc-default-user' is used.
-If that is nil too, then your login name is used.
-
-Once a connection to a given host has been initiated, the user name
-and password information for that host are cached and re-used by
-ange-ftp. Use `ange-ftp-set-user' to change the cached values,
-since setting `ange-ftp-default-user' directly does not affect
-the cached information.")
-
-(defvar ange-ftp-netrc-default-user nil
- "Alternate default user name to use when none is specified.
-This variable is set from the `default' command in your `.netrc' file,
-if there is one.")
-
-(defvar ange-ftp-default-password nil
- "*Password to use when the user name equals `ange-ftp-default-user'.")
-
-(defvar ange-ftp-default-account nil
- "*Account to use when the user name equals `ange-ftp-default-user'.")
-
-(defvar ange-ftp-netrc-default-password nil
- "*Password to use when the user name equals `ange-ftp-netrc-default-user'.")
-
-(defvar ange-ftp-netrc-default-account nil
- "*Account to use when the user name equals `ange-ftp-netrc-default-user'.")
-
-(defvar ange-ftp-generate-anonymous-password t
- "*If t, use value of `user-mail-address' as password for anonymous ftp.
-If a string, then use that string as the password.
-If nil, prompt the user for a password.")
-
-(defvar ange-ftp-dumb-unix-host-regexp nil
- "*If non-nil, regexp matching hosts on which `dir' command lists directory.")
-
-(defvar ange-ftp-binary-file-name-regexp
- (concat "\\.[zZ]$\\|\\.lzh$\\|\\.arc$\\|\\.zip$\\|\\.zoo$\\|\\.tar$\\|"
- "\\.dvi$\\|\\.ps$\\|\\.elc$\\|TAGS$\\|\\.gif$\\|"
- "\\.EXE\\(;[0-9]+\\)?$\\|\\.[zZ]-part-..$\\|\\.gz$\\|"
- "\\.taz$\\|\\.tgz$")
- "*If a file matches this regexp then it is transferred in binary mode.")
-
-(defvar ange-ftp-gateway-host nil
- "*Name of host to use as gateway machine when local FTP isn't possible.")
-
-(defvar ange-ftp-local-host-regexp ".*"
- "*Regexp selecting hosts which can be reached directly with ftp.
-For other hosts the FTP process is started on \`ange-ftp-gateway-host\'
-instead, and/or reached via \`ange-ftp-gateway-ftp-program-name\'.")
-
-(defvar ange-ftp-gateway-program-interactive nil
- "*If non-nil then the gateway program should give a shell prompt.
-Both telnet and rlogin do something like this.")
-
-(defvar ange-ftp-gateway-program remote-shell-program
- "*Name of program to spawn a shell on the gateway machine.
-Valid candidates are rsh (remsh on some systems), telnet and rlogin. See
-also the gateway variable above.")
-
-(defvar ange-ftp-gateway-prompt-pattern "^[^#$%>;\n]*[#$%>;] *"
- "*Regexp matching prompt after complete login sequence on gateway machine.
-A match for this means the shell is now awaiting input. Make this regexp as
-strict as possible; it shouldn't match *anything* at all except the user's
-initial prompt. The above string will fail under most SUN-3's since it
-matches the login banner.")
-
-(defvar ange-ftp-gateway-setup-term-command
- (if (eq system-type 'hpux)
- "stty -onlcr -echo\n"
- "stty -echo nl\n")
- "*Set up terminal after logging in to the gateway machine.
-This command should stop the terminal from echoing each command, and
-arrange to strip out trailing ^M characters.")
-
-(defvar ange-ftp-smart-gateway nil
- "*Non-nil means the ftp gateway and/or the gateway ftp program is smart.
-Don't bother telnetting, etc., already connected to desired host transparently,
-or just issue a user@host command in case \`ange-ftp-gateway-host\' is non-nil.")
-
-(defvar ange-ftp-smart-gateway-port "21"
- "*Port on gateway machine to use when smart gateway is in operation.")
-
-(defvar ange-ftp-send-hash t
- "*If non-nil, send the HASH command to the FTP client.")
-
-(defvar ange-ftp-binary-hash-mark-size nil
- "*Default size, in bytes, between hash-marks when transferring a binary file.
-If NIL, this variable will be locally overridden if the FTP client outputs a
-suitable response to the HASH command. If non-NIL then this value takes
-precedence over the local value.")
-
-(defvar ange-ftp-ascii-hash-mark-size 1024
- "*Default size, in bytes, between hash-marks when transferring an ASCII file.
-This variable is buffer-local and will be locally overridden if the FTP client
-outputs a suitable response to the HASH command.")
-
-(defvar ange-ftp-process-verbose t
- "*If non-NIL then be chatty about interaction with the FTP process.")
-
-(defvar ange-ftp-ftp-program-name "ftp"
- "*Name of FTP program to run.")
-
-(defvar ange-ftp-gateway-ftp-program-name "ftp"
- "*Name of FTP program to run when accessing non-local hosts.
-Some AT&T folks claim to use something called `pftp' here.")
-
-(defvar ange-ftp-ftp-program-args '("-i" "-n" "-g" "-v")
- "*A list of arguments passed to the FTP program when started.")
-
-(defvar ange-ftp-nslookup-program nil
- "*If non-NIL then a string naming nslookup program." )
-
-(defvar ange-ftp-make-backup-files ()
- "*Non-nil means make backup files for \"magic\" remote files.")
-
-(defvar ange-ftp-retry-time 5
- "*Number of seconds to wait before retry if file or listing doesn't arrive.
-This might need to be increased for very slow connections.")
-
-(defvar ange-ftp-auto-save 0
- "If 1, allows ange-ftp files to be auto-saved.
-If 0, suppresses auto-saving of ange-ftp files.
-Don't use any other value.")
-
-;;;; ------------------------------------------------------------
-;;;; Hash table support.
-;;;; ------------------------------------------------------------
-
-(require 'backquote)
-
-(defun ange-ftp-make-hashtable (&optional size)
- "Make an obarray suitable for use as a hashtable.
-SIZE, if supplied, should be a prime number."
- (make-vector (or size 31) 0))
-
-(defun ange-ftp-map-hashtable (fun tbl)
- "Call FUNCTION on each key and value in HASHTABLE."
- (mapatoms
- (function
- (lambda (sym)
- (funcall fun (get sym 'key) (get sym 'val))))
- tbl))
-
-(defmacro ange-ftp-make-hash-key (key)
- "Convert KEY into a suitable key for a hashtable."
- (` (if (stringp (, key))
- (, key)
- (prin1-to-string (, key)))))
-
-(defun ange-ftp-get-hash-entry (key tbl)
- "Return the value associated with KEY in HASHTABLE."
- (let ((sym (intern-soft (ange-ftp-make-hash-key key) tbl)))
- (and sym (get sym 'val))))
-
-(defun ange-ftp-put-hash-entry (key val tbl)
- "Record an association between KEY and VALUE in HASHTABLE."
- (let ((sym (intern (ange-ftp-make-hash-key key) tbl)))
- (put sym 'val val)
- (put sym 'key key)))
-
-(defun ange-ftp-del-hash-entry (key tbl)
- "Copy all symbols except KEY in HASHTABLE and return modified hashtable."
- (let* ((len (length tbl))
- (new-tbl (ange-ftp-make-hashtable len))
- (i (1- len)))
- (ange-ftp-map-hashtable
- (function
- (lambda (k v)
- (or (equal k key)
- (ange-ftp-put-hash-entry k v new-tbl))))
- tbl)
- (while (>= i 0)
- (aset tbl i (aref new-tbl i))
- (setq i (1- i)))
- tbl))
-
-(defun ange-ftp-hash-entry-exists-p (key tbl)
- "Return whether there is an association for KEY in TABLE."
- (intern-soft (ange-ftp-make-hash-key key) tbl))
-
-(defun ange-ftp-hash-table-keys (tbl)
- "Return a sorted list of all the active keys in TABLE, as strings."
- (sort (all-completions "" tbl)
- (function string-lessp)))
-
-;;;; ------------------------------------------------------------
-;;;; Internal variables.
-;;;; ------------------------------------------------------------
-
-(defvar ange-ftp-data-buffer-name " *ftp data*"
- "Buffer name to hold directory listing data received from ftp process.")
-
-(defvar ange-ftp-netrc-modtime nil
- "Last modified time of the netrc file from file-attributes.")
-
-(defvar ange-ftp-user-hashtable (ange-ftp-make-hashtable)
- "Hash table holding associations between HOST, USER pairs.")
-
-(defvar ange-ftp-passwd-hashtable (ange-ftp-make-hashtable)
- "Mapping between a HOST, USER pair and a PASSWORD for them.")
-
-(defvar ange-ftp-account-hashtable (ange-ftp-make-hashtable)
- "Mapping between a HOST, USER pair and a ACCOUNT password for them.")
-
-(defvar ange-ftp-files-hashtable (ange-ftp-make-hashtable 97)
- "Hash table for storing directories and their respective files.")
-
-(defvar ange-ftp-ls-cache-lsargs nil
- "Last set of args used by ange-ftp-ls.")
-
-(defvar ange-ftp-ls-cache-file nil
- "Last file passed to ange-ftp-ls.")
-
-(defvar ange-ftp-ls-cache-res nil
- "Last result returned from ange-ftp-ls.")
-
-(defconst ange-ftp-expand-dir-hashtable (ange-ftp-make-hashtable))
-
-(defconst ange-ftp-expand-dir-regexp "^5.0 \\([^: ]+\\):")
-
-;; These are local variables in each FTP process buffer.
-(defvar ange-ftp-hash-mark-unit nil)
-(defvar ange-ftp-hash-mark-count nil)
-(defvar ange-ftp-xfer-size nil)
-(defvar ange-ftp-process-string nil)
-(defvar ange-ftp-process-result-line nil)
-(defvar ange-ftp-process-busy nil)
-(defvar ange-ftp-process-result nil)
-(defvar ange-ftp-process-multi-skip nil)
-(defvar ange-ftp-process-msg nil)
-(defvar ange-ftp-process-continue nil)
-(defvar ange-ftp-last-percent nil)
-
-;; These variables are bound by one function and examined by another.
-;; Leave them void globally for error checking.
-(defvar ange-ftp-this-file)
-(defvar ange-ftp-this-dir)
-(defvar ange-ftp-this-user)
-(defvar ange-ftp-this-host)
-(defvar ange-ftp-this-msg)
-(defvar ange-ftp-completion-ignored-pattern)
-(defvar ange-ftp-trample-marker)
-
-;; New error symbols.
-(put 'ftp-error 'error-conditions '(ftp-error file-error error))
-;; (put 'ftp-error 'error-message "FTP error")
-
-;;; ------------------------------------------------------------
-;;; Enhanced message support.
-;;; ------------------------------------------------------------
-
-(defun ange-ftp-message (fmt &rest args)
- "Display message in echo area, but indicate if truncated.
-Args are as in `message': a format string, plus arguments to be formatted."
- (let ((msg (apply (function format) fmt args))
- (max (window-width (minibuffer-window))))
- (if noninteractive
- msg
- (if (>= (length msg) max)
- ;; Take just the last MAX - 3 chars of the string.
- (setq msg (concat "> " (substring msg (- 3 max)))))
- (message "%s" msg))))
-
-(defun ange-ftp-abbreviate-filename (file &optional new)
- "Abbreviate the file name FILE relative to the default-directory.
-If the optional parameter NEW is given and the non-directory parts match,
-only return the directory part of FILE."
- (save-match-data
- (if (and default-directory
- (string-match (concat "^"
- (regexp-quote default-directory)
- ".") file))
- (setq file (substring file (1- (match-end 0)))))
- (if (and new
- (string-equal (file-name-nondirectory file)
- (file-name-nondirectory new)))
- (setq file (file-name-directory file)))
- (or file "./")))
-
-;;;; ------------------------------------------------------------
-;;;; User / Host mapping support.
-;;;; ------------------------------------------------------------
-
-(defun ange-ftp-set-user (host user)
- "For a given HOST, set or change the default USER."
- (interactive "sHost: \nsUser: ")
- (ange-ftp-put-hash-entry host user ange-ftp-user-hashtable))
-
-(defun ange-ftp-get-user (host)
- "Given a HOST, return the default USER."
- (ange-ftp-parse-netrc)
- (let ((user (ange-ftp-get-hash-entry host ange-ftp-user-hashtable)))
- (or user
- (prog1
- (setq user
- (cond ((stringp ange-ftp-default-user)
- ;; We have a default name. Use it.
- ange-ftp-default-user)
- (ange-ftp-default-user
- ;; Ask the user.
- (let ((enable-recursive-minibuffers t))
- (read-string (format "User for %s: " host)
- (user-login-name))))
- (ange-ftp-netrc-default-user)
- ;; Default to the user's login name.
- (t
- (user-login-name))))
- (ange-ftp-set-user host user)))))
-
-;;;; ------------------------------------------------------------
-;;;; Password support.
-;;;; ------------------------------------------------------------
-
-(defun ange-ftp-read-passwd (prompt &optional default)
- "Read a password, echoing `.' for each character typed.
-End with RET, LFD, or ESC. DEL or C-h rubs out. C-u kills line.
-Optional DEFAULT is password to start with."
- (let ((pass nil)
- (c 0)
- (echo-keystrokes 0)
- (cursor-in-echo-area t))
- (while (progn (message "%s%s"
- prompt
- (make-string (length pass) ?.))
- (setq c (read-char))
- (and (/= c ?\r) (/= c ?\n) (/= c ?\e)))
- (if (= c ?\C-u)
- (setq pass "")
- (if (and (/= c ?\b) (/= c ?\177))
- (setq pass (concat pass (char-to-string c)))
- (if (> (length pass) 0)
- (setq pass (substring pass 0 -1))))))
- (message "")
- (ange-ftp-repaint-minibuffer)
- (or pass default "")))
-
-(defmacro ange-ftp-generate-passwd-key (host user)
- (` (concat (, host) "/" (, user))))
-
-(defmacro ange-ftp-lookup-passwd (host user)
- (` (ange-ftp-get-hash-entry (ange-ftp-generate-passwd-key (, host) (, user))
- ange-ftp-passwd-hashtable)))
-
-(defun ange-ftp-set-passwd (host user passwd)
- "For a given HOST and USER, set or change the associated PASSWORD."
- (interactive (list (read-string "Host: ")
- (read-string "User: ")
- (ange-ftp-read-passwd "Password: ")))
- (ange-ftp-put-hash-entry (ange-ftp-generate-passwd-key host user)
- passwd
- ange-ftp-passwd-hashtable))
-
-(defun ange-ftp-get-host-with-passwd (user)
- "Given a USER, return a host we know the password for."
- (ange-ftp-parse-netrc)
- (catch 'found-one
- (ange-ftp-map-hashtable
- (function (lambda (host val)
- (if (ange-ftp-lookup-passwd host user)
- (throw 'found-one host))))
- ange-ftp-user-hashtable)
- (save-match-data
- (ange-ftp-map-hashtable
- (function
- (lambda (key value)
- (if (string-match "^[^/]*\\(/\\).*$" key)
- (let ((host (substring key 0 (match-beginning 1))))
- (if (and (string-equal user (substring key (match-end 1)))
- value)
- (throw 'found-one host))))))
- ange-ftp-passwd-hashtable))
- nil))
-
-(defun ange-ftp-get-passwd (host user)
- "Return the password for specified HOST and USER, asking user if necessary."
- (ange-ftp-parse-netrc)
-
- ;; look up password in the hash table first; user might have overridden the
- ;; defaults.
- (cond ((ange-ftp-lookup-passwd host user))
-
- ;; See if default user and password set.
- ((and (stringp ange-ftp-default-user)
- ange-ftp-default-password
- (string-equal user ange-ftp-default-user))
- ange-ftp-default-password)
-
- ;; See if default user and password set from .netrc file.
- ((and (stringp ange-ftp-netrc-default-user)
- ange-ftp-netrc-default-password
- (string-equal user ange-ftp-netrc-default-user))
- ange-ftp-netrc-default-password)
-
- ;; anonymous ftp password is handled specially since there is an
- ;; unwritten rule about how that is used on the Internet.
- ((and (or (string-equal user "anonymous")
- (string-equal user "ftp"))
- ange-ftp-generate-anonymous-password)
- (if (stringp ange-ftp-generate-anonymous-password)
- ange-ftp-generate-anonymous-password
- user-mail-address))
-
- ;; see if same user has logged in to other hosts; if so then prompt
- ;; with the password that was used there.
- (t
- (let* ((other (ange-ftp-get-host-with-passwd user))
- (passwd (if other
-
- ;; found another machine with the same user.
- ;; Try that account.
- (ange-ftp-read-passwd
- (format "passwd for %s@%s (default same as %s@%s): "
- user host user other)
- (ange-ftp-lookup-passwd other user))
-
- ;; I give up. Ask the user for the password.
- (ange-ftp-read-passwd
- (format "Password for %s@%s: " user host)))))
- (ange-ftp-set-passwd host user passwd)
- passwd))))
-
-;;;; ------------------------------------------------------------
-;;;; Account support
-;;;; ------------------------------------------------------------
-
-;; Account passwords must be either specified in the .netrc file, or set
-;; manually by calling ange-ftp-set-account. For the moment, ange-ftp doesn't
-;; check to see whether the FTP process is actually prompting for an account
-;; password.
-
-(defun ange-ftp-set-account (host user account)
- "For a given HOST and USER, set or change the associated ACCOUNT password."
- (interactive (list (read-string "Host: ")
- (read-string "User: ")
- (ange-ftp-read-passwd "Account password: ")))
- (ange-ftp-put-hash-entry (ange-ftp-generate-passwd-key host user)
- account
- ange-ftp-account-hashtable))
-
-(defun ange-ftp-get-account (host user)
- "Given a HOST and USER, return the FTP account."
- (ange-ftp-parse-netrc)
- (or (ange-ftp-get-hash-entry (ange-ftp-generate-passwd-key host user)
- ange-ftp-account-hashtable)
- (and (stringp ange-ftp-default-user)
- (string-equal user ange-ftp-default-user)
- ange-ftp-default-account)
- (and (stringp ange-ftp-netrc-default-user)
- (string-equal user ange-ftp-netrc-default-user)
- ange-ftp-netrc-default-account)))
-
-;;;; ------------------------------------------------------------
-;;;; ~/.netrc support
-;;;; ------------------------------------------------------------
-
-(defun ange-ftp-chase-symlinks (file)
- "Return the filename that FILE references, following all symbolic links."
- (let (temp)
- (while (setq temp (ange-ftp-real-file-symlink-p file))
- (setq file
- (if (file-name-absolute-p temp)
- temp
- (concat (file-name-directory file) temp)))))
- file)
-
-;; Move along current line looking for the value of the TOKEN.
-;; Valid separators between TOKEN and its value are commas and
-;; whitespace. Second arg LIMIT is a limit for the search.
-
-(defun ange-ftp-parse-netrc-token (token limit)
- (if (search-forward token limit t)
- (let (beg)
- (skip-chars-forward ", \t\r\n" limit)
- (if (eq (following-char) ?\") ;quoted token value
- (progn (forward-char 1)
- (setq beg (point))
- (skip-chars-forward "^\"" limit)
- (forward-char 1)
- (buffer-substring beg (1- (point))))
- (setq beg (point))
- (skip-chars-forward "^, \t\r\n" limit)
- (buffer-substring beg (point))))))
-
-;; Extract the values for the tokens `machine', `login',
-;; `password' and `account' in the current buffer. If successful,
-;; record the information found.
-
-(defun ange-ftp-parse-netrc-group ()
- (let ((start (point))
- (end (save-excursion
- (if (looking-at "machine\\>")
- ;; Skip `machine' and the machine name that follows.
- (progn
- (skip-chars-forward "^ \t\n")
- (skip-chars-forward " \t\n")
- (skip-chars-forward "^ \t\n"))
- ;; Skip `default'.
- (skip-chars-forward "^ \t\n"))
- ;; Find start of the next `machine' or `default'
- ;; or the end of the buffer.
- (if (re-search-forward "machine\\>\\|default\\>" nil t)
- (match-beginning 0)
- (point-max))))
- machine login password account)
- (setq machine (ange-ftp-parse-netrc-token "machine" end)
- login (ange-ftp-parse-netrc-token "login" end)
- password (ange-ftp-parse-netrc-token "password" end)
- account (ange-ftp-parse-netrc-token "account" end))
- (if (and machine login)
- ;; found a `machine` token.
- (progn
- (ange-ftp-set-user machine login)
- (ange-ftp-set-passwd machine login password)
- (and account
- (ange-ftp-set-account machine login account)))
- (goto-char start)
- (if (search-forward "default" end t)
- ;; found a `default' token
- (progn
- (setq login (ange-ftp-parse-netrc-token "login" end)
- password (ange-ftp-parse-netrc-token "password" end)
- account (ange-ftp-parse-netrc-token "account" end))
- (and login
- (setq ange-ftp-netrc-default-user login))
- (and password
- (setq ange-ftp-netrc-default-password password))
- (and account
- (setq ange-ftp-netrc-default-account account)))))
- (goto-char end)))
-
-;; Read in ~/.netrc, if one exists. If ~/.netrc file exists and has
-;; the correct permissions then extract the \`machine\', \`login\',
-;; \`password\' and \`account\' information from within.
-
-(defun ange-ftp-parse-netrc ()
- ;; We set this before actually doing it to avoid the possibility
- ;; of an infinite loop if ange-ftp-netrc-filename is an FTP file.
- (interactive)
- (let (file attr)
- (let ((default-directory "/"))
- (setq file (ange-ftp-chase-symlinks
- (ange-ftp-real-expand-file-name ange-ftp-netrc-filename)))
- (setq attr (ange-ftp-real-file-attributes file)))
- (if (and attr ; file exists.
- (not (equal (nth 5 attr) ange-ftp-netrc-modtime))) ; file changed
- (save-match-data
- (if (or ange-ftp-disable-netrc-security-check
- (and (eq (nth 2 attr) (user-uid)) ; Same uids.
- (string-match ".r..------" (nth 8 attr))))
- (save-excursion
- ;; we are cheating a bit here. I'm trying to do the equivalent
- ;; of find-file on the .netrc file, but then nuke it afterwards.
- ;; with the bit of logic below we should be able to have
- ;; encrypted .netrc files.
- (set-buffer (generate-new-buffer "*ftp-.netrc*"))
- (ange-ftp-real-insert-file-contents file)
- (setq buffer-file-name file)
- (setq default-directory (file-name-directory file))
- (normal-mode t)
- (mapcar 'funcall find-file-hooks)
- (setq buffer-file-name nil)
- (goto-char (point-min))
- (skip-chars-forward " \t\n")
- (while (not (eobp))
- (ange-ftp-parse-netrc-group))
- (kill-buffer (current-buffer)))
- (ange-ftp-message "%s either not owned by you or badly protected."
- ange-ftp-netrc-filename)
- (sit-for 1))
- (setq ange-ftp-netrc-modtime (nth 5 attr))))))
-
-;; Return a list of prefixes of the form 'user@host:' to be used when
-;; completion is done in the root directory.
-
-(defun ange-ftp-generate-root-prefixes ()
- (ange-ftp-parse-netrc)
- (save-match-data
- (let (res)
- (ange-ftp-map-hashtable
- (function
- (lambda (key value)
- (if (string-match "^[^/]*\\(/\\).*$" key)
- (let ((host (substring key 0 (match-beginning 1)))
- (user (substring key (match-end 1))))
- (setq res (cons (list (concat user "@" host ":"))
- res))))))
- ange-ftp-passwd-hashtable)
- (ange-ftp-map-hashtable
- (function (lambda (host user)
- (setq res (cons (list (concat host ":"))
- res))))
- ange-ftp-user-hashtable)
- (or res (list nil)))))
-
-;;;; ------------------------------------------------------------
-;;;; Remote file name syntax support.
-;;;; ------------------------------------------------------------
-
-(defmacro ange-ftp-ftp-name-component (n ns name)
- "Extract the Nth ftp file name component from NS."
- (` (let ((elt (nth (, n) (, ns))))
- (if (match-beginning elt)
- (substring (, name) (match-beginning elt) (match-end elt))))))
-
-(defvar ange-ftp-ftp-name-arg "")
-(defvar ange-ftp-ftp-name-res nil)
-
-;; Parse NAME according to `ange-ftp-name-format' (which see).
-;; Returns a list (HOST USER NAME), or nil if NAME does not match the format.
-(defun ange-ftp-ftp-name (name)
- (if (string-equal name ange-ftp-ftp-name-arg)
- ange-ftp-ftp-name-res
- (setq ange-ftp-ftp-name-arg name
- ange-ftp-ftp-name-res
- (save-match-data
- (if (posix-string-match (car ange-ftp-name-format) name)
- (let* ((ns (cdr ange-ftp-name-format))
- (host (ange-ftp-ftp-name-component 0 ns name))
- (user (ange-ftp-ftp-name-component 1 ns name))
- (name (ange-ftp-ftp-name-component 2 ns name)))
- (if (zerop (length user))
- (setq user (ange-ftp-get-user host)))
- (list host user name))
- nil)))))
-
-;; Take a FULLNAME that matches according to ange-ftp-name-format and
-;; replace the name component with NAME.
-(defun ange-ftp-replace-name-component (fullname name)
- (save-match-data
- (if (posix-string-match (car ange-ftp-name-format) fullname)
- (let* ((ns (cdr ange-ftp-name-format))
- (elt (nth 2 ns)))
- (concat (substring fullname 0 (match-beginning elt))
- name
- (substring fullname (match-end elt)))))))
-
-;;;; ------------------------------------------------------------
-;;;; Miscellaneous utils.
-;;;; ------------------------------------------------------------
-
-;; (setq ange-ftp-tmp-keymap (make-sparse-keymap))
-;; (define-key ange-ftp-tmp-keymap "\C-m" 'exit-minibuffer)
-
-(defun ange-ftp-repaint-minibuffer ()
- "Clear any existing minibuffer message; let the minibuffer contents show."
- (message nil))
-
-;; Return the name of the buffer that collects output from the ftp process
-;; connected to the given HOST and USER pair.
-(defun ange-ftp-ftp-process-buffer (host user)
- (concat "*ftp " user "@" host "*"))
-
-;; Display the last chunk of output from the ftp process for the given HOST
-;; USER pair, and signal an error including MSG in the text.
-(defun ange-ftp-error (host user msg)
- (let ((cur (selected-window))
- (pop-up-windows t))
- (pop-to-buffer
- (get-buffer-create
- (ange-ftp-ftp-process-buffer host user)))
- (goto-char (point-max))
- (select-window cur))
- (signal 'ftp-error (list (format "FTP Error: %s" msg))))
-
-(defun ange-ftp-set-buffer-mode ()
- "Set correct modes for the current buffer if visiting a remote file."
- (if (and (stringp buffer-file-name)
- (ange-ftp-ftp-name buffer-file-name))
- (auto-save-mode ange-ftp-auto-save)))
-
-(defun ange-ftp-kill-ftp-process (&optional buffer)
- "Kill the FTP process associated with BUFFER (the current buffer, if nil).
-If the BUFFER's visited filename or default-directory is an ftp filename
-then kill the related ftp process."
- (interactive "bKill FTP process associated with buffer: ")
- (if (null buffer)
- (setq buffer (current-buffer))
- (setq buffer (get-buffer buffer)))
- (let ((file (or (buffer-file-name buffer)
- (save-excursion (set-buffer buffer) default-directory))))
- (if file
- (let ((parsed (ange-ftp-ftp-name (expand-file-name file))))
- (if parsed
- (let ((host (nth 0 parsed))
- (user (nth 1 parsed)))
- (kill-buffer (ange-ftp-ftp-process-buffer host user))))))))
-
-(defun ange-ftp-quote-string (string)
- "Quote any characters in STRING that may confuse the ftp process."
- (apply (function concat)
- (mapcar (function
- (lambda (char)
- (if (or (<= char ? )
- (> char ?\~)
- (= char ?\")
- (= char ?\\))
- (vector ?\\ char)
- (vector char))))
- string)))
-
-(defun ange-ftp-barf-if-not-directory (directory)
- (or (file-directory-p directory)
- (signal 'file-error
- (list "Opening directory"
- (if (file-exists-p directory)
- "not a directory"
- "no such file or directory")
- directory))))
-
-;;;; ------------------------------------------------------------
-;;;; FTP process filter support.
-;;;; ------------------------------------------------------------
-
-(defun ange-ftp-process-handle-line (line proc)
- "Look at the given LINE from the ftp process PROC.
-Try to categorize it into one of four categories:
-good, skip, fatal, or unknown."
- (cond ((string-match ange-ftp-xfer-size-msgs line)
- (setq ange-ftp-xfer-size
- (ash (string-to-int (substring line
- (match-beginning 1)
- (match-end 1)))
- -10)))
- ((string-match ange-ftp-skip-msgs line)
- t)
- ((string-match ange-ftp-good-msgs line)
- (setq ange-ftp-process-busy nil
- ange-ftp-process-result t
- ange-ftp-process-result-line line))
- ;; Check this before checking for errors.
- ;; Otherwise the last line of these three seems to be an error:
- ;; 230-see a significant impact from the move. For those of you who can't
- ;; 230-use DNS to resolve hostnames and get an error message like
- ;; 230-"ftp.stsci.edu: unknown host", the new IP address will be...
- ((string-match ange-ftp-multi-msgs line)
- (setq ange-ftp-process-multi-skip t))
- ((string-match ange-ftp-fatal-msgs line)
- (delete-process proc)
- (setq ange-ftp-process-busy nil
- ange-ftp-process-result-line line))
- (ange-ftp-process-multi-skip
- t)
- (t
- (setq ange-ftp-process-busy nil
- ange-ftp-process-result-line line))))
-
-(defun ange-ftp-set-xfer-size (host user bytes)
- "Set the size of the next FTP transfer in bytes."
- (let ((proc (ange-ftp-get-process host user)))
- (if proc
- (let ((buf (process-buffer proc)))
- (if buf
- (save-excursion
- (set-buffer buf)
- (setq ange-ftp-xfer-size (ash bytes -10))))))))
-
-(defun ange-ftp-process-handle-hash (str)
- "Remove hash marks from STRING and display count so far."
- (setq str (concat (substring str 0 (match-beginning 0))
- (substring str (match-end 0)))
- ange-ftp-hash-mark-count (+ (- (match-end 0)
- (match-beginning 0))
- ange-ftp-hash-mark-count))
- (and ange-ftp-hash-mark-unit
- ange-ftp-process-msg
- ange-ftp-process-verbose
- (not (eq (selected-window) (minibuffer-window)))
- (not (boundp 'search-message)) ;screws up isearch otherwise
- (not cursor-in-echo-area) ;screws up y-or-n-p otherwise
- (let ((kbytes (ash (* ange-ftp-hash-mark-unit
- ange-ftp-hash-mark-count)
- -6)))
- (if (zerop ange-ftp-xfer-size)
- (ange-ftp-message "%s...%dk" ange-ftp-process-msg kbytes)
- (let ((percent (/ (* 100 kbytes) ange-ftp-xfer-size)))
- ;; cut out the redisplay of identical %-age messages.
- (if (not (eq percent ange-ftp-last-percent))
- (progn
- (setq ange-ftp-last-percent percent)
- (ange-ftp-message "%s...%d%%" ange-ftp-process-msg percent)))))))
- str)
-
-;; Call the function specified by CONT. CONT can be either a function
-;; or a list of a function and some args. The first two parameters
-;; passed to the function will be RESULT and LINE. The remaining args
-;; will be taken from CONT if a list was passed.
-
-(defun ange-ftp-call-cont (cont result line)
- (if cont
- (if (and (listp cont)
- (not (eq (car cont) 'lambda)))
- (apply (car cont) result line (cdr cont))
- (funcall cont result line))))
-
-;; Build up a complete line of output from the ftp PROCESS and pass it
-;; on to ange-ftp-process-handle-line to deal with.
-
-(defun ange-ftp-process-filter (proc str)
- (let ((buffer (process-buffer proc))
- (old-buffer (current-buffer)))
-
- ;; Eliminate nulls.
- (while (string-match "\000+" str)
- (setq str (replace-match "" nil nil str)))
-
- ;; see if the buffer is still around... it could have been deleted.
- (if (buffer-name buffer)
- (unwind-protect
- (progn
- (set-buffer (process-buffer proc))
-
- ;; handle hash mark printing
- (and ange-ftp-process-busy
- (string-match "^#+$" str)
- (setq str (ange-ftp-process-handle-hash str)))
- (comint-output-filter proc str)
- ;; Replace STR by the result of the comint processing.
- (setq str (buffer-substring comint-last-output-start
- (process-mark proc)))
- (if ange-ftp-process-busy
- (progn
- (setq ange-ftp-process-string (concat ange-ftp-process-string
- str))
-
- ;; if we gave an empty password to the USER command earlier
- ;; then we should send a null password now.
- (if (string-match "Password: *$" ange-ftp-process-string)
- (send-string proc "\n"))))
- (while (and ange-ftp-process-busy
- (string-match "\n" ange-ftp-process-string))
- (let ((line (substring ange-ftp-process-string
- 0
- (match-beginning 0))))
- (setq ange-ftp-process-string (substring ange-ftp-process-string
- (match-end 0)))
- (while (string-match "^ftp> *" line)
- (setq line (substring line (match-end 0))))
- (ange-ftp-process-handle-line line proc)))
-
- ;; has the ftp client finished? if so then do some clean-up
- ;; actions.
- (if (not ange-ftp-process-busy)
- (progn
- ;; reset the xfer size
- (setq ange-ftp-xfer-size 0)
-
- ;; issue the "done" message since we've finished.
- (if (and ange-ftp-process-msg
- ange-ftp-process-verbose
- ange-ftp-process-result)
- (progn
- (ange-ftp-message "%s...done" ange-ftp-process-msg)
- (ange-ftp-repaint-minibuffer)
- (setq ange-ftp-process-msg nil)))
-
- ;; is there a continuation we should be calling? if so,
- ;; we'd better call it, making sure we only call it once.
- (if ange-ftp-process-continue
- (let ((cont ange-ftp-process-continue))
- (setq ange-ftp-process-continue nil)
- (ange-ftp-call-cont cont
- ange-ftp-process-result
- ange-ftp-process-result-line))))))
- (set-buffer old-buffer)))))
-
-(defun ange-ftp-process-sentinel (proc str)
- "When ftp process changes state, nuke all file-entries in cache."
- (let ((name (process-name proc)))
- (if (string-match "\\*ftp \\([^@]+\\)@\\([^*]+\\)\\*" name)
- (let ((user (substring name (match-beginning 1) (match-end 1)))
- (host (substring name (match-beginning 2) (match-end 2))))
- (ange-ftp-wipe-file-entries host user))))
- (setq ange-ftp-ls-cache-file nil))
-
-;;;; ------------------------------------------------------------
-;;;; Gateway support.
-;;;; ------------------------------------------------------------
-
-(defun ange-ftp-use-gateway-p (host)
- "Returns whether to access this host via a normal (non-smart) gateway."
- ;; yes, I know that I could simplify the following expression, but it is
- ;; clearer (to me at least) this way.
- (and (not ange-ftp-smart-gateway)
- (save-match-data
- (not (string-match ange-ftp-local-host-regexp host)))))
-
-(defun ange-ftp-use-smart-gateway-p (host)
- "Returns whether to access this host via a smart gateway."
- (and ange-ftp-smart-gateway
- (save-match-data
- (not (string-match ange-ftp-local-host-regexp host)))))
-
-
-;;; ------------------------------------------------------------
-;;; Temporary file location and deletion...
-;;; ------------------------------------------------------------
-
-(defvar ange-ftp-tmp-name-files ())
-(defvar ange-ftp-tmp-name-hashtable (ange-ftp-make-hashtable 10))
-(defvar ange-ftp-pid nil)
-
-(defun ange-ftp-get-pid ()
- "Half-hearted attempt to get the current process's id."
- (setq ange-ftp-pid (substring (make-temp-name "") 1)))
-
-(defun ange-ftp-make-tmp-name (host)
- "This routine will return the name of a new file."
- (let* ((template (if (ange-ftp-use-gateway-p host)
- ange-ftp-gateway-tmp-name-template
- ange-ftp-tmp-name-template))
- (pid (or ange-ftp-pid (ange-ftp-get-pid)))
- (start ?a)
- file entry)
- (while
- (progn
- (setq file (format "%s%c%s" template start pid))
- (setq entry (intern file ange-ftp-tmp-name-hashtable))
- (or (memq entry ange-ftp-tmp-name-files)
- (ange-ftp-real-file-exists-p file)))
- (if (> (setq start (1+ start)) ?z)
- (progn
- (setq template (concat template "X"))
- (setq start ?a))))
- (setq ange-ftp-tmp-name-files
- (cons entry ange-ftp-tmp-name-files))
- file))
-
-(defun ange-ftp-del-tmp-name (temp)
- (setq ange-ftp-tmp-name-files
- (delq (intern temp ange-ftp-tmp-name-hashtable)
- ange-ftp-tmp-name-files))
- (condition-case ()
- (ange-ftp-real-delete-file temp)
- (error nil)))
-
-;;;; ------------------------------------------------------------
-;;;; Interactive gateway program support.
-;;;; ------------------------------------------------------------
-
-(defvar ange-ftp-gwp-running t)
-(defvar ange-ftp-gwp-status nil)
-
-(defun ange-ftp-gwp-sentinel (proc str)
- (setq ange-ftp-gwp-running nil))
-
-(defun ange-ftp-gwp-filter (proc str)
- (comint-output-filter proc str)
- (save-excursion
- (set-buffer (process-buffer proc))
- ;; Replace STR by the result of the comint processing.
- (setq str (buffer-substring comint-last-output-start (process-mark proc))))
- (cond ((string-match "login: *$" str)
- (send-string proc
- (concat
- (let ((ange-ftp-default-user t))
- (ange-ftp-get-user ange-ftp-gateway-host))
- "\n")))
- ((string-match "Password: *$" str)
- (send-string proc
- (concat
- (ange-ftp-get-passwd ange-ftp-gateway-host
- (ange-ftp-get-user
- ange-ftp-gateway-host))
- "\n")))
- ((string-match ange-ftp-gateway-fatal-msgs str)
- (delete-process proc)
- (setq ange-ftp-gwp-running nil))
- ((string-match ange-ftp-gateway-prompt-pattern str)
- (setq ange-ftp-gwp-running nil
- ange-ftp-gwp-status t))))
-
-(defun ange-ftp-gwp-start (host user name args)
- "Login to the gateway machine and fire up an ftp process."
- (let* ((gw-user (ange-ftp-get-user ange-ftp-gateway-host))
- ;; It would be nice to make process-connection-type nil,
- ;; but that doesn't work: ftp never responds.
- ;; Can anyone find a fix for that?
- (proc (let ((process-connection-type t))
- (start-process name name
- ange-ftp-gateway-program
- ange-ftp-gateway-host)))
- (ftp (mapconcat (function identity) args " ")))
- (process-kill-without-query proc)
- (set-process-sentinel proc (function ange-ftp-gwp-sentinel))
- (set-process-filter proc (function ange-ftp-gwp-filter))
- (save-excursion
- (set-buffer (process-buffer proc))
- (internal-ange-ftp-mode)
- (set-marker (process-mark proc) (point)))
- (setq ange-ftp-gwp-running t
- ange-ftp-gwp-status nil)
- (ange-ftp-message "Connecting to gateway %s..." ange-ftp-gateway-host)
- (while ange-ftp-gwp-running ;perform login sequence
- (accept-process-output proc))
- (if (not ange-ftp-gwp-status)
- (ange-ftp-error host user "unable to login to gateway"))
- (ange-ftp-message "Connecting to gateway %s...done" ange-ftp-gateway-host)
- (setq ange-ftp-gwp-running t
- ange-ftp-gwp-status nil)
- (process-send-string proc ange-ftp-gateway-setup-term-command)
- (while ange-ftp-gwp-running ;zap ^M's and double echoing.
- (accept-process-output proc))
- (if (not ange-ftp-gwp-status)
- (ange-ftp-error host user "unable to set terminal modes on gateway"))
- (setq ange-ftp-gwp-running t
- ange-ftp-gwp-status nil)
- (process-send-string proc (concat "exec " ftp "\n")) ;spawn ftp process
- proc))
-
-;;;; ------------------------------------------------------------
-;;;; Support for sending commands to the ftp process.
-;;;; ------------------------------------------------------------
-
-(defun ange-ftp-raw-send-cmd (proc cmd &optional msg cont nowait)
- "Low-level routine to send the given ftp CMD to the ftp PROCESS.
-MSG is an optional message to output before and after the command.
-If CONT is non-NIL then it is either a function or a list of function and
-some arguments. The function will be called when the ftp command has completed.
-If CONT is NIL then this routine will return \( RESULT . LINE \) where RESULT
-is whether the command was successful, and LINE is the line from the FTP
-process that caused the command to complete.
-If NOWAIT is given then the routine will return immediately the command has
-been queued with no result. CONT will still be called, however."
- (if (memq (process-status proc) '(run open))
- (save-excursion
- (set-buffer (process-buffer proc))
- (ange-ftp-wait-not-busy proc)
- (setq ange-ftp-process-string ""
- ange-ftp-process-result-line ""
- ange-ftp-process-busy t
- ange-ftp-process-result nil
- ange-ftp-process-multi-skip nil
- ange-ftp-process-msg msg
- ange-ftp-process-continue cont
- ange-ftp-hash-mark-count 0
- ange-ftp-last-percent -1
- cmd (concat cmd "\n"))
- (and msg ange-ftp-process-verbose (ange-ftp-message "%s..." msg))
- (goto-char (point-max))
- (move-marker comint-last-input-start (point))
- ;; don't insert the password into the buffer on the USER command.
- (save-match-data
- (if (string-match "^user \"[^\"]*\"" cmd)
- (insert (substring cmd 0 (match-end 0)) " Turtle Power!\n")
- (insert cmd)))
- (move-marker comint-last-input-end (point))
- (send-string proc cmd)
- (set-marker (process-mark proc) (point))
- (if nowait
- nil
- (ange-ftp-wait-not-busy proc)
- (if cont
- nil ;cont has already been called
- (cons ange-ftp-process-result ange-ftp-process-result-line))))))
-
-;; Wait for the ange-ftp process PROC not to be busy.
-(defun ange-ftp-wait-not-busy (proc)
- (save-excursion
- (set-buffer (process-buffer proc))
- (condition-case nil
- ;; This is a kludge to let user quit in case ftp gets hung.
- ;; It matters because this function can be called from the filter.
- ;; It is bad to allow quitting in a filter, but getting hung
- ;; is worse. By binding quit-flag to nil, we might avoid
- ;; most of the probability of getting screwed because the user
- ;; wants to quit some command.
- (let ((quit-flag nil)
- (inhibit-quit nil))
- (while ange-ftp-process-busy
- (accept-process-output proc)))
- (quit
- ;; If the user does quit out of this,
- ;; kill the process. That stops any transfer in progress.
- ;; The next operation will open a new ftp connection.
- (delete-process proc)
- (signal 'quit nil)))))
-
-(defun ange-ftp-nslookup-host (host)
- "Attempt to resolve the given HOSTNAME using nslookup if possible."
- (interactive "sHost: ")
- (if ange-ftp-nslookup-program
- (let ((default-directory
- (if (file-accessible-directory-p default-directory)
- default-directory
- exec-directory))
- ;; It would be nice to make process-connection-type nil,
- ;; but that doesn't work: ftp never responds.
- ;; Can anyone find a fix for that?
- (proc (let ((process-connection-type t))
- (start-process " *nslookup*" " *nslookup*"
- ange-ftp-nslookup-program host)))
- (res host))
- (process-kill-without-query proc)
- (save-excursion
- (set-buffer (process-buffer proc))
- (while (memq (process-status proc) '(run open))
- (accept-process-output proc))
- (goto-char (point-min))
- (if (re-search-forward "Name:.*\nAddress: *\\(.*\\)$" nil t)
- (setq res (buffer-substring (match-beginning 1)
- (match-end 1))))
- (kill-buffer (current-buffer)))
- res)
- host))
-
-(defun ange-ftp-start-process (host user name)
- "Spawn a new ftp process ready to connect to machine HOST and give it NAME.
-If HOST is only ftp-able through a gateway machine then spawn a shell
-on the gateway machine to do the ftp instead."
- (let* ((use-gateway (ange-ftp-use-gateway-p host))
- (use-smart-ftp (and (not ange-ftp-gateway-host)
- (ange-ftp-use-smart-gateway-p host)))
- (ftp-prog (if (or use-gateway
- use-smart-ftp)
- ange-ftp-gateway-ftp-program-name
- ange-ftp-ftp-program-name))
- (args (append (list ftp-prog) ange-ftp-ftp-program-args))
- ;; Without the following binding, ange-ftp-start-process
- ;; recurses on file-accessible-directory-p, since it needs to
- ;; restart its process in order to determine anything about
- ;; default-directory.
- (file-name-handler-alist)
- (default-directory
- (if (file-accessible-directory-p default-directory)
- default-directory
- exec-directory))
- proc)
- ;; It would be nice to make process-connection-type nil,
- ;; but that doesn't work: ftp never responds.
- ;; Can anyone find a fix for that?
- (let ((process-connection-type t)
- (process-environment process-environment))
- ;; This tells GNU ftp not to output any fancy escape sequences.
- (setenv "TERM" "dumb")
- (if use-gateway
- (if ange-ftp-gateway-program-interactive
- (setq proc (ange-ftp-gwp-start host user name args))
- (setq proc (apply 'start-process name name
- (append (list ange-ftp-gateway-program
- ange-ftp-gateway-host)
- args))))
- (setq proc (apply 'start-process name name args))))
- (process-kill-without-query proc)
- (save-excursion
- (set-buffer (process-buffer proc))
- (internal-ange-ftp-mode))
- (set-process-sentinel proc (function ange-ftp-process-sentinel))
- (set-process-filter proc (function ange-ftp-process-filter))
- (accept-process-output proc) ;wait for ftp startup message
- proc))
-
-(defun internal-ange-ftp-mode ()
- "Major mode for interacting with the FTP process.
-
-\\{comint-mode-map}"
- (interactive)
- (comint-mode)
- (setq major-mode 'internal-ange-ftp-mode)
- (setq mode-name "Internal Ange-ftp")
- (let ((proc (get-buffer-process (current-buffer))))
- (goto-char (point-max))
- (set-marker (process-mark proc) (point))
- (make-local-variable 'ange-ftp-process-string)
- (setq ange-ftp-process-string "")
- (make-local-variable 'ange-ftp-process-busy)
- (make-local-variable 'ange-ftp-process-result)
- (make-local-variable 'ange-ftp-process-msg)
- (make-local-variable 'ange-ftp-process-multi-skip)
- (make-local-variable 'ange-ftp-process-result-line)
- (make-local-variable 'ange-ftp-process-continue)
- (make-local-variable 'ange-ftp-hash-mark-count)
- (make-local-variable 'ange-ftp-binary-hash-mark-size)
- (make-local-variable 'ange-ftp-ascii-hash-mark-size)
- (make-local-variable 'ange-ftp-hash-mark-unit)
- (make-local-variable 'ange-ftp-xfer-size)
- (make-local-variable 'ange-ftp-last-percent)
- (setq ange-ftp-hash-mark-count 0)
- (setq ange-ftp-xfer-size 0)
- (setq ange-ftp-process-result-line "")
-
- (setq comint-prompt-regexp "^ftp> ")
- (make-local-variable 'comint-password-prompt-regexp)
- ;; This is a regexp that can't match anything.
- ;; ange-ftp has its own ways of handling passwords.
- (setq comint-password-prompt-regexp "^a\\'z")
- (make-local-variable 'paragraph-start)
- (setq paragraph-start comint-prompt-regexp)))
-
-(defun ange-ftp-smart-login (host user pass account proc)
- "Connect to the FTP-server on HOST as USER using PASSWORD and ACCOUNT.
-PROC is the FTP-client's process. This routine uses the smart-gateway
-host specified in ``ange-ftp-gateway-host''."
- (let ((result (ange-ftp-raw-send-cmd
- proc
- (format "open %s %s"
- (ange-ftp-nslookup-host ange-ftp-gateway-host)
- ange-ftp-smart-gateway-port)
- (format "Opening FTP connection to %s via %s"
- host
- ange-ftp-gateway-host))))
- (or (car result)
- (ange-ftp-error host user
- (concat "OPEN request failed: "
- (cdr result))))
- (setq result (ange-ftp-raw-send-cmd
- proc (format "user \"%s\"@%s %s %s"
- user
- (ange-ftp-nslookup-host host)
- pass
- account)
- (format "Logging in as user %s@%s"
- user host)))
- (or (car result)
- (progn
- (ange-ftp-set-passwd host user nil) ; reset password
- (ange-ftp-set-account host user nil) ; reset account
- (ange-ftp-error host user
- (concat "USER request failed: "
- (cdr result)))))))
-
-(defun ange-ftp-normal-login (host user pass account proc)
- "Connect to the FTP-server on HOST as USER using PASSWORD and ACCOUNT.
-PROC is the process to the FTP-client."
- (let* ((nshost (ange-ftp-nslookup-host host))
- (result (ange-ftp-raw-send-cmd
- proc
- (format "open %s" nshost)
- (format "Opening FTP connection to %s" host))))
- (or (car result)
- (ange-ftp-error host user
- (concat "OPEN request failed: "
- (cdr result))))
- (setq result (ange-ftp-raw-send-cmd
- proc
- (if (and (ange-ftp-use-smart-gateway-p host)
- ange-ftp-gateway-host)
- (format "user \"%s\"@%s %s %s" user nshost pass account)
- (format "user \"%s\" %s %s" user pass account))
- (format "Logging in as user %s@%s" user host)))
- (or (car result)
- (progn
- (ange-ftp-set-passwd host user nil) ;reset password.
- (ange-ftp-set-account host user nil) ;reset account.
- (ange-ftp-error host user
- (concat "USER request failed: "
- (cdr result)))))))
-
-;; ange@hplb.hpl.hp.com says this should not be changed.
-(defvar ange-ftp-hash-mark-msgs
- "[hH]ash mark [^0-9]*\\([0-9]+\\)"
- "*Regexp matching the FTP client's output upon doing a HASH command.")
-
-(defun ange-ftp-guess-hash-mark-size (proc)
- (if ange-ftp-send-hash
- (save-excursion
- (set-buffer (process-buffer proc))
- (let* ((status (ange-ftp-raw-send-cmd proc "hash"))
- (result (car status))
- (line (cdr status)))
- (save-match-data
- (if (string-match ange-ftp-hash-mark-msgs line)
- (let ((size (string-to-int
- (substring line
- (match-beginning 1)
- (match-end 1)))))
- (setq ange-ftp-ascii-hash-mark-size size
- ange-ftp-hash-mark-unit (ash size -4))
-
- ;; if a default value for this is set, use that value.
- (or ange-ftp-binary-hash-mark-size
- (setq ange-ftp-binary-hash-mark-size size)))))))))
-
-(defun ange-ftp-get-process (host user)
- "Return an FTP subprocess connected to HOST and logged in as USER.
-Create a new process if needed."
- (let* ((name (ange-ftp-ftp-process-buffer host user))
- (proc (get-process name)))
- (if (and proc (memq (process-status proc) '(run open)))
- proc
- (let ((pass (ange-ftp-quote-string
- (ange-ftp-get-passwd host user)))
- (account (ange-ftp-quote-string
- (ange-ftp-get-account host user))))
- ;; grab a suitable process.
- (setq proc (ange-ftp-start-process host user name))
-
- ;; login to FTP server.
- (if (and (ange-ftp-use-smart-gateway-p host)
- ange-ftp-gateway-host)
- (ange-ftp-smart-login host user pass account proc)
- (ange-ftp-normal-login host user pass account proc))
-
- ;; Tell client to send back hash-marks as progress. It isn't usually
- ;; fatal if this command fails.
- (ange-ftp-guess-hash-mark-size proc)
-
- ;; Guess at the host type.
- (ange-ftp-guess-host-type host user)
-
- ;; Run any user-specified hooks. Note that proc, host and user are
- ;; dynamically bound at this point.
- (run-hooks 'ange-ftp-process-startup-hook))
- proc)))
-
-;; Variables for caching host and host-type
-(defvar ange-ftp-host-cache nil)
-(defvar ange-ftp-host-type-cache nil)
-
-;; If ange-ftp-host-type is called with the optional user
-;; argument, it will attempt to guess the host type by connecting
-;; as user, if necessary. For efficiency, I have tried to give this
-;; optional second argument only when necessary. Have I missed any calls
-;; to ange-ftp-host-type where it should have been supplied?
-
-(defun ange-ftp-host-type (host &optional user)
- "Return a symbol which represents the type of the HOST given.
-If the optional argument USER is given, attempts to guess the
-host-type by logging in as USER."
- (if (eq host ange-ftp-host-cache)
- ange-ftp-host-type-cache
- ;; Trigger an ftp connection, in case we need to guess at the host type.
- (if (and user (ange-ftp-get-process host user) (eq host ange-ftp-host-cache))
- ange-ftp-host-type-cache
- (setq ange-ftp-host-cache host
- ange-ftp-host-type-cache
- (cond ((ange-ftp-dumb-unix-host host)
- 'dumb-unix)
-;; ((and (fboundp 'ange-ftp-vos-host)
-;; (ange-ftp-vos-host host))
-;; 'vos)
- ((and (fboundp 'ange-ftp-vms-host)
- (ange-ftp-vms-host host))
- 'vms)
- ((and (fboundp 'ange-ftp-mts-host)
- (ange-ftp-mts-host host))
- 'mts)
- ((and (fboundp 'ange-ftp-cms-host)
- (ange-ftp-cms-host host))
- 'cms)
- (t
- 'unix))))))
-
-;; It would be nice to abstract the functions ange-ftp-TYPE-host and
-;; ange-ftp-add-TYPE-host. The trick is to abstract these functions
-;; without sacrificing speed. Also, having separate variables
-;; ange-ftp-TYPE-regexp is more user friendly then requiring the user to
-;; set an alist to indicate that a host is of a given type. Even with
-;; automatic host type recognition, setting a regexp is still a good idea
-;; (for efficiency) if you log into a particular non-UNIX host frequently.
-
-(defvar ange-ftp-fix-name-func-alist nil
- "Alist saying how to convert file name to the host's syntax.
-Association list of \( TYPE \. FUNC \) pairs, where FUNC is a routine
-which can change a UNIX file name into a name more suitable for a host of type
-TYPE.")
-
-(defvar ange-ftp-fix-dir-name-func-alist nil
- "Alist saying how to convert directory name to the host's syntax.
-Association list of \( TYPE \. FUNC \) pairs, where FUNC is a routine
-which can change UNIX directory name into a directory name more suitable
-for a host of type TYPE.")
-
-;; *** Perhaps the sense of this variable should be inverted, since there
-;; *** is only 1 host type that can take ls-style listing options.
-(defvar ange-ftp-dumb-host-types '(dumb-unix)
- "List of host types that can't take UNIX ls-style listing options.")
-
-(defun ange-ftp-send-cmd (host user cmd &optional msg cont nowait)
- "Find an ftp process connected to HOST logged in as USER and send it CMD.
-MSG is an optional status message to be output before and after issuing the
-command.
-See the documentation for ange-ftp-raw-send-cmd for a description of CONT
-and NOWAIT."
- ;; Handle conversion to remote file name syntax and remote ls option
- ;; capability.
- (let ((cmd0 (car cmd))
- (cmd1 (nth 1 cmd))
- (ange-ftp-this-user user)
- (ange-ftp-this-host host)
- (ange-ftp-this-msg msg)
- cmd2 cmd3 host-type fix-name-func)
-
- (cond
-
- ;; pwd case (We don't care what host-type.)
- ((null cmd1))
-
- ;; cmd == 'dir "remote-name" "local-name" "ls-switches"
- ((progn
- (setq cmd2 (nth 2 cmd)
- host-type (ange-ftp-host-type host user))
- ;; This will trigger an FTP login, if one doesn't exist
- (eq cmd0 'dir))
- (setq cmd1 (funcall
- (or (cdr (assq host-type ange-ftp-fix-dir-name-func-alist))
- 'identity)
- cmd1)
- cmd3 (nth 3 cmd))
- ;; Need to deal with the HP-UX ftp bug. This should also allow
- ;; us to resolve symlinks to directories on SysV machines. (Sebastian will
- ;; be happy.)
- (and (eq host-type 'unix)
- (string-match "/$" cmd1)
- (not (string-match "R" cmd3))
- (setq cmd1 (concat cmd1 ".")))
- ;; If the remote ls can take switches, put them in
- (or (memq host-type ange-ftp-dumb-host-types)
- (setq cmd0 'ls
- cmd1 (format "\"%s %s\"" cmd3 cmd1))))
-
- ;; First argument is the remote name
- ((progn
- (setq fix-name-func (or (cdr (assq host-type
- ange-ftp-fix-name-func-alist))
- 'identity))
- (memq cmd0 '(get delete mkdir rmdir cd)))
- (setq cmd1 (funcall fix-name-func cmd1)))
-
- ;; Second argument is the remote name
- ((memq cmd0 '(append put chmod))
- (setq cmd2 (funcall fix-name-func cmd2)))
-
- ;; Both arguments are remote names
- ((eq cmd0 'rename)
- (setq cmd1 (funcall fix-name-func cmd1)
- cmd2 (funcall fix-name-func cmd2))))
-
- ;; Turn the command into one long string
- (setq cmd0 (symbol-name cmd0))
- (setq cmd (concat cmd0
- (and cmd1 (concat " " cmd1))
- (and cmd2 (concat " " cmd2))))
-
- ;; Actually send the resulting command.
- (let (afsc-result
- afsc-line)
- (ange-ftp-raw-send-cmd
- (ange-ftp-get-process host user)
- cmd
- msg
- (list
- (function (lambda (result line host user
- cmd msg cont nowait)
- (or cont
- (setq afsc-result result
- afsc-line line))
- (if result
- (ange-ftp-call-cont cont result line)
- (ange-ftp-raw-send-cmd
- (ange-ftp-get-process host user)
- cmd
- msg
- (list
- (function (lambda (result line cont)
- (or cont
- (setq afsc-result result
- afsc-line line))
- (ange-ftp-call-cont cont result line)))
- cont)
- nowait))))
- host user cmd msg cont nowait)
- nowait)
-
- (if nowait
- nil
- (if cont
- nil
- (cons afsc-result afsc-line))))))
-
-;; It might be nice to message users about the host type identified,
-;; but there is so much other messaging going on, it would not be
-;; seen. No point in slowing things down just so users can read
-;; a host type message.
-
-(defconst ange-ftp-cms-name-template
- (concat
- "^[-A-Z0-9$*][-A-Z0-9$*]?[-A-Z0-9$*]?[-A-Z0-9$*]?[-A-Z0-9$*]?"
- "[-A-Z0-9$*]?[-A-Z0-9$*]?[-A-Z0-9$*]?\\.[0-9][0-9][0-9A-Z]$"))
-(defconst ange-ftp-vms-name-template
- "^[-A-Z0-9_$]+:\\[[-A-Z0-9_$]+\\(\\.[-A-Z0-9_$]+\\)*\\]$")
-(defconst ange-ftp-mts-name-template
- "^[A-Z0-9._][A-Z0-9._][A-Z0-9._][A-Z0-9._]:$")
-
-(defun ange-ftp-guess-host-type (host user)
- "Guess at the the host type of HOST.
-Works by doing a pwd and examining the directory syntax."
- (let ((host-type (ange-ftp-host-type host))
- (key (concat host "/" user "/~")))
- (if (eq host-type 'unix)
- ;; Note that ange-ftp-host-type returns unix as the default value.
- (save-match-data
- (let* ((result (ange-ftp-get-pwd host user))
- (dir (car result))
- fix-name-func)
- (cond ((null dir)
- (message "Warning! Unable to get home directory")
- (sit-for 1)
- (if (string-match
- "^450 No current working directory defined$"
- (cdr result))
-
- ;; We'll assume that if pwd bombs with this
- ;; error message, then it's CMS.
- (progn
- (ange-ftp-add-cms-host host)
- (setq ange-ftp-host-cache host
- ange-ftp-host-type-cache 'cms))))
-
- ;; try for VMS
- ((string-match ange-ftp-vms-name-template dir)
- (ange-ftp-add-vms-host host)
- ;; The add-host functions clear the host type cache.
- ;; Therefore, need to set the cache afterwards.
- (setq ange-ftp-host-cache host
- ange-ftp-host-type-cache 'vms))
-
- ;; try for MTS
- ((string-match ange-ftp-mts-name-template dir)
- (ange-ftp-add-mts-host host)
- (setq ange-ftp-host-cache host
- ange-ftp-host-type-cache 'mts))
-
- ;; try for CMS
- ((string-match ange-ftp-cms-name-template dir)
- (ange-ftp-add-cms-host host)
- (setq ange-ftp-host-cache host
- ange-ftp-host-type-cache 'cms))
-
- ;; assume UN*X
- (t
- (setq ange-ftp-host-cache host
- ange-ftp-host-type-cache 'unix)))
-
- ;; Now that we have done a pwd, might as well put it in
- ;; the expand-dir hashtable.
- (let ((ange-ftp-this-user user)
- (ange-ftp-this-host host))
- (setq fix-name-func (cdr (assq ange-ftp-host-type-cache
- ange-ftp-fix-name-func-alist)))
- (if fix-name-func
- (setq dir (funcall fix-name-func dir 'reverse))))
- (ange-ftp-put-hash-entry key dir
- ange-ftp-expand-dir-hashtable))))
-
- ;; In the special case of CMS make sure that know the
- ;; expansion of the home minidisk now, because we will
- ;; be doing a lot of cd's.
- (if (and (eq host-type 'cms)
- (not (ange-ftp-hash-entry-exists-p
- key ange-ftp-expand-dir-hashtable)))
- (let ((dir (car (ange-ftp-get-pwd host user))))
- (if dir
- (ange-ftp-put-hash-entry key (concat "/" dir)
- ange-ftp-expand-dir-hashtable)
- (message "Warning! Unable to get home directory")
- (sit-for 1))))))
-
-
-;;;; ------------------------------------------------------------
-;;;; Remote file and directory listing support.
-;;;; ------------------------------------------------------------
-
-;; Returns whether HOST's FTP server doesn't like \'ls\' or \'dir\' commands
-;; to take switch arguments.
-(defun ange-ftp-dumb-unix-host (host)
- (and host ange-ftp-dumb-unix-host-regexp
- (save-match-data
- (string-match ange-ftp-dumb-unix-host-regexp host))))
-
-(defun ange-ftp-add-dumb-unix-host (host)
- "Interactively adds a given HOST to ange-ftp-dumb-unix-host-regexp."
- (interactive
- (list (read-string "Host: "
- (let ((name (or (buffer-file-name) default-directory)))
- (and name (car (ange-ftp-ftp-name name)))))))
- (if (not (ange-ftp-dumb-unix-host host))
- (setq ange-ftp-dumb-unix-host-regexp
- (concat "^" (regexp-quote host) "$"
- (and ange-ftp-dumb-unix-host-regexp "\\|")
- ange-ftp-dumb-unix-host-regexp)
- ange-ftp-host-cache nil)))
-
-(defvar ange-ftp-parse-list-func-alist nil
- "Alist saying how to parse directory listings for certain OS types.
-Association list of \( TYPE \. FUNC \) pairs. The FUNC is a routine
-which can parse the output from a DIR listing for a host of type TYPE.")
-
-;; With no-error nil, this function returns:
-;; an error if file is not an ange-ftp-name
-;; (This should never happen.)
-;; an error if either the listing is unreadable or there is an ftp error.
-;; the listing (a string), if everything works.
-;;
-;; With no-error t, it returns:
-;; an error if not an ange-ftp-name
-;; error if listing is unreadable (most likely caused by a slow connection)
-;; nil if ftp error (this is because although asking to list a nonexistent
-;; directory on a remote unix machine usually (except
-;; maybe for dumb hosts) returns an ls error, but no
-;; ftp error, if the same is done on a VMS machine,
-;; an ftp error is returned. Need to trap the error
-;; so we can go on and try to list the parent.)
-;; the listing, if everything works.
-
-;; If WILDCARD is non-nil, then this implements the guts of insert-directory
-;; in the wildcard case. Then we make a relative directory listing
-;; of FILE within the directory specified by `default-directory'.
-
-(defvar ange-ftp-before-parse-ls-hook nil
- "Normal hook run before parsing the text of an ftp directory listing.")
-
-(defun ange-ftp-ls (file lsargs parse &optional no-error wildcard)
- "Return the output of an `DIR' or `ls' command done over ftp.
-FILE is the full name of the remote file, LSARGS is any args to pass to the
-`ls' command, and PARSE specifies that the output should be parsed and stored
-away in the internal cache."
- ;; If parse is t, we assume that file is a directory. i.e. we only parse
- ;; full directory listings.
- (let* ((ange-ftp-this-file (ange-ftp-expand-file-name file))
- (parsed (ange-ftp-ftp-name ange-ftp-this-file)))
- (if parsed
- (let* ((host (nth 0 parsed))
- (user (nth 1 parsed))
- (name (ange-ftp-quote-string (nth 2 parsed)))
- (key (directory-file-name ange-ftp-this-file))
- (host-type (ange-ftp-host-type host user))
- (dumb (memq host-type ange-ftp-dumb-host-types))
- result
- temp
- lscmd parse-func)
- (if (string-equal name "")
- (setq name
- (ange-ftp-real-file-name-as-directory
- (ange-ftp-expand-dir host user "~"))))
- (if (and ange-ftp-ls-cache-file
- (string-equal key ange-ftp-ls-cache-file)
- ;; Don't care about lsargs for dumb hosts.
- (or dumb (string-equal lsargs ange-ftp-ls-cache-lsargs)))
- ange-ftp-ls-cache-res
- (setq temp (ange-ftp-make-tmp-name host))
- (if wildcard
- (progn
- (ange-ftp-cd host user (file-name-directory name))
- (setq lscmd (list 'dir file temp lsargs)))
- (setq lscmd (list 'dir name temp lsargs)))
- (unwind-protect
- (if (car (setq result (ange-ftp-send-cmd
- host
- user
- lscmd
- (format "Listing %s"
- (ange-ftp-abbreviate-filename
- ange-ftp-this-file)))))
- (save-excursion
- (set-buffer (get-buffer-create
- ange-ftp-data-buffer-name))
- (erase-buffer)
- (if (ange-ftp-real-file-readable-p temp)
- (ange-ftp-real-insert-file-contents temp)
- (sleep-for ange-ftp-retry-time)
- ;wait for file to possibly appear
- (if (ange-ftp-real-file-readable-p temp)
- ;; Try again.
- (ange-ftp-real-insert-file-contents temp)
- (ange-ftp-error host user
- (format
- "list data file %s not readable"
- temp))))
- (run-hooks 'ange-ftp-before-parse-ls-hook)
- (if parse
- (ange-ftp-set-files
- ange-ftp-this-file
- (if (setq
- parse-func
- (cdr (assq host-type
- ange-ftp-parse-list-func-alist)))
- (funcall parse-func)
- (ange-ftp-parse-dired-listing lsargs))))
- (setq ange-ftp-ls-cache-file key
- ange-ftp-ls-cache-lsargs lsargs
- ; For dumb hosts-types this is
- ; meaningless but harmless.
- ange-ftp-ls-cache-res (buffer-string))
- ;; (kill-buffer (current-buffer))
- ange-ftp-ls-cache-res)
- (if no-error
- nil
- (ange-ftp-error host user
- (concat "DIR failed: " (cdr result)))))
- (ange-ftp-del-tmp-name temp))))
- (error "Should never happen. Please report. Bug ref. no.: 1"))))
-
-;;;; ------------------------------------------------------------
-;;;; Directory information caching support.
-;;;; ------------------------------------------------------------
-
-(defconst ange-ftp-date-regexp
- " [A-Za-z\xa0-\xff][A-Za-z\xa0-\xff][A-Za-z\xa0-\xff] [0-3 ][0-9] "
- "Regular expression to recognize the date in a directory listing.
-This regular expression is designed to recognize month names
-regardless of the language.")
-
-(defvar ange-ftp-add-file-entry-alist nil
- "Alist saying how to add file entries on certain OS types.
-Association list of pairs \( TYPE \. FUNC \), where FUNC
-is a function to be used to add a file entry for the OS TYPE. The
-main reason for this alist is to deal with file versions in VMS.")
-
-(defvar ange-ftp-delete-file-entry-alist nil
- "Alist saying how to delete files on certain OS types.
-Association list of pairs \( TYPE \. FUNC \), where FUNC
-is a function to be used to delete a file entry for the OS TYPE.
-The main reason for this alist is to deal with file versions in VMS.")
-
-(defun ange-ftp-add-file-entry (name &optional dir-p)
- "Add a file entry for file NAME, if its directory info exists."
- (funcall (or (cdr (assq (ange-ftp-host-type
- (car (ange-ftp-ftp-name name)))
- ange-ftp-add-file-entry-alist))
- 'ange-ftp-internal-add-file-entry)
- name dir-p)
- (setq ange-ftp-ls-cache-file nil))
-
-(defun ange-ftp-delete-file-entry (name &optional dir-p)
- "Delete the file entry for file NAME, if its directory info exists."
- (funcall (or (cdr (assq (ange-ftp-host-type
- (car (ange-ftp-ftp-name name)))
- ange-ftp-delete-file-entry-alist))
- 'ange-ftp-internal-delete-file-entry)
- name dir-p)
- (setq ange-ftp-ls-cache-file nil))
-
-(defmacro ange-ftp-parse-filename ()
- ;;Extract the filename from the current line of a dired-like listing.
- (` (let ((eol (progn (end-of-line) (point))))
- (beginning-of-line)
- (if (re-search-forward ange-ftp-date-regexp eol t)
- (progn
- (skip-chars-forward " ")
- (skip-chars-forward "^ " eol)
- (skip-chars-forward " " eol)
- ;; We bomb on filenames starting with a space.
- (buffer-substring (point) eol))))))
-
-;; This deals with the F switch. Should also do something about
-;; unquoting names obtained with the SysV b switch and the GNU Q
-;; switch. See Sebastian's dired-get-filename.
-
-(defmacro ange-ftp-ls-parser ()
- ;; Note that switches is dynamically bound.
- ;; Meant to be called by ange-ftp-parse-dired-listing
- (` (let ((tbl (ange-ftp-make-hashtable))
- (used-F (and (stringp switches)
- (string-match "F" switches)))
- file-type symlink directory file)
- (while (setq file (ange-ftp-parse-filename))
- (beginning-of-line)
- (skip-chars-forward "\t 0-9")
- (setq file-type (following-char)
- directory (eq file-type ?d))
- (if (eq file-type ?l)
- (if (string-match " -> " file)
- (setq symlink (substring file (match-end 0))
- file (substring file 0 (match-beginning 0)))
- ;; Shouldn't happen
- (setq symlink ""))
- (setq symlink nil))
- ;; Only do a costly regexp search if the F switch was used.
- (if (and used-F
- (not (string-equal file ""))
- (looking-at
- ".[-r][-w]\\([^ ]\\)[-r][-w]\\([^ ]\\)[-r][-w]\\([^ ]\\)"))
- (let ((socket (eq file-type ?s))
- (executable
- (and (not symlink) ; x bits don't mean a thing for symlinks
- (string-match "[xst]"
- (concat
- (buffer-substring
- (match-beginning 1)
- (match-end 1))
- (buffer-substring
- (match-beginning 2)
- (match-end 2))
- (buffer-substring
- (match-beginning 3)
- (match-end 3)))))))
- ;; Some ls's with the F switch mark symlinks with an @ (ULTRIX)
- ;; and others don't. (sigh...) Beware, that some Unix's don't
- ;; seem to believe in the F-switch
- (if (or (and symlink (string-match "@$" file))
- (and directory (string-match "/$" file))
- (and executable (string-match "*$" file))
- (and socket (string-match "=$" file)))
- (setq file (substring file 0 -1)))))
- (ange-ftp-put-hash-entry file (or symlink directory) tbl)
- (forward-line 1))
- (ange-ftp-put-hash-entry "." t tbl)
- (ange-ftp-put-hash-entry ".." t tbl)
- tbl)))
-
-;;; The dl stuff for descriptive listings
-
-(defvar ange-ftp-dl-dir-regexp nil
- "Regexp matching directories which are listed in dl format.
-This regexp should not be anchored with a trailing `$', because it should
-match subdirectories as well.")
-
-(defun ange-ftp-add-dl-dir (dir)
- "Interactively adds a DIR to ange-ftp-dl-dir-regexp."
- (interactive
- (list (read-string "Directory: "
- (let ((name (or (buffer-file-name) default-directory)))
- (and name (ange-ftp-ftp-name name)
- (file-name-directory name))))))
- (if (not (and ange-ftp-dl-dir-regexp
- (string-match ange-ftp-dl-dir-regexp dir)))
- (setq ange-ftp-dl-dir-regexp
- (concat "^" (regexp-quote dir)
- (and ange-ftp-dl-dir-regexp "\\|")
- ange-ftp-dl-dir-regexp))))
-
-(defmacro ange-ftp-dl-parser ()
- ;; Parse the current buffer, which is assumed to be a descriptive
- ;; listing, and return a hashtable.
- (` (let ((tbl (ange-ftp-make-hashtable)))
- (while (not (eobp))
- (ange-ftp-put-hash-entry
- (buffer-substring (point)
- (progn
- (skip-chars-forward "^ /\n")
- (point)))
- (eq (following-char) ?/)
- tbl)
- (forward-line 1))
- (ange-ftp-put-hash-entry "." t tbl)
- (ange-ftp-put-hash-entry ".." t tbl)
- tbl)))
-
-;; Parse the current buffer which is assumed to be in a dired-like listing
-;; format, and return a hashtable as the result. If the listing is not really
-;; a listing, then return nil.
-
-(defun ange-ftp-parse-dired-listing (&optional switches)
- (save-match-data
- (cond
- ((looking-at "^total [0-9]+$")
- (forward-line 1)
- ;; Some systems put in a blank line here.
- (if (eolp) (forward-line 1))
- (ange-ftp-ls-parser))
- ((looking-at "[^\n]+\\( not found\\|: Not a directory\\)\n\\'")
- ;; It's an ls error message.
- nil)
- ((eobp) ; i.e. (zerop (buffer-size))
- ;; This could be one of:
- ;; (1) An Ultrix ls error message
- ;; (2) A listing with the A switch of an empty directory
- ;; on a machine which doesn't give a total line.
- ;; (3) The twilight zone.
- ;; We'll assume (1) for now.
- nil)
- ((re-search-forward ange-ftp-date-regexp nil t)
- (beginning-of-line)
- (ange-ftp-ls-parser))
- ((re-search-forward "^[^ \n\t]+ +\\([0-9]+\\|-\\|=\\) " nil t)
- ;; It's a dl listing (I hope).
- ;; file is bound by the call to ange-ftp-ls
- (ange-ftp-add-dl-dir ange-ftp-this-file)
- (beginning-of-line)
- (ange-ftp-dl-parser))
- (t nil))))
-
-(defun ange-ftp-set-files (directory files)
- "For a given DIRECTORY, set or change the associated FILES hashtable."
- (and files (ange-ftp-put-hash-entry (file-name-as-directory directory)
- files ange-ftp-files-hashtable)))
-
-(defun ange-ftp-get-files (directory &optional no-error)
- "Given a given DIRECTORY, return a hashtable of file entries.
-This will give an error or return nil, depending on the value of
-NO-ERROR, if a listing for DIRECTORY cannot be obtained."
- (setq directory (file-name-as-directory directory)) ;normalize
- (or (ange-ftp-get-hash-entry directory ange-ftp-files-hashtable)
- (save-match-data
- (and (ange-ftp-ls directory
- ;; This is an efficiency hack. We try to
- ;; anticipate what sort of listing dired
- ;; might want, and cache just such a listing.
- (if (and (boundp 'dired-actual-switches)
- (stringp dired-actual-switches)
- ;; We allow the A switch, which lists
- ;; all files except "." and "..".
- ;; This is OK because we manually
- ;; insert these entries
- ;; in the hash table.
- (string-match
- "[aA]" dired-actual-switches)
- (string-match
- "l" dired-actual-switches)
- (not (string-match
- "R" dired-actual-switches)))
- dired-actual-switches
- (if (and (boundp 'dired-listing-switches)
- (stringp dired-listing-switches)
- (string-match
- "[aA]" dired-listing-switches)
- (string-match
- "l" dired-listing-switches)
- (not (string-match
- "R" dired-listing-switches)))
- dired-listing-switches
- "-al"))
- t no-error)
- (ange-ftp-get-hash-entry
- directory ange-ftp-files-hashtable)))))
-
-;; Given NAME, return the file part that can be used for looking up the
-;; file's entry in a hashtable.
-(defmacro ange-ftp-get-file-part (name)
- (` (let ((file (file-name-nondirectory (, name))))
- (if (string-equal file "")
- "."
- file))))
-
-;; Return whether ange-ftp-file-entry-p and ange-ftp-get-file-entry are
-;; allowed to determine if NAME is a sub-directory by listing it directly,
-;; rather than listing its parent directory. This is used for efficiency so
-;; that a wasted listing is not done:
-;; 1. When looking for a .dired file in dired-x.el.
-;; 2. The syntax of FILE and DIR make it impossible that FILE could be a valid
-;; subdirectory. This is of course an OS dependent judgement.
-
-(defmacro ange-ftp-allow-child-lookup (dir file)
- (` (not
- (let* ((efile (, file)) ; expand once.
- (edir (, dir))
- (parsed (ange-ftp-ftp-name edir))
- (host-type (ange-ftp-host-type
- (car parsed))))
- (or
-;;; This variable seems not to exist in Emacs 19 -- rms.
-;;; ;; Deal with dired
-;;; (and (boundp 'dired-local-variables-file)
-;;; (stringp dired-local-variables-file)
-;;; (string-equal dired-local-variables-file efile))
- ;; No dots in dir names in vms.
- (and (eq host-type 'vms)
- (string-match "\\." efile))
- ;; No subdirs in mts of cms.
- (and (memq host-type '(mts cms))
- (not (string-equal "/" (nth 2 parsed)))))))))
-
-(defun ange-ftp-file-entry-p (name)
- "Given NAME, return whether there is a file entry for it."
- (let* ((name (directory-file-name name))
- (dir (file-name-directory name))
- (ent (ange-ftp-get-hash-entry dir ange-ftp-files-hashtable))
- (file (ange-ftp-get-file-part name)))
- (if ent
- (ange-ftp-hash-entry-exists-p file ent)
- (or (and (ange-ftp-allow-child-lookup dir file)
- (setq ent (ange-ftp-get-files name t))
- ;; Try a child lookup. i.e. try to list file as a
- ;; subdirectory of dir. This is a good idea because
- ;; we may not have read permission for file's parent. Also,
- ;; people tend to work down directory trees anyway. We use
- ;; no-error ;; because if file does not exist as a subdir.,
- ;; then dumb hosts will give an ftp error. Smart unix hosts
- ;; will simply send back the ls
- ;; error message.
- (ange-ftp-get-hash-entry "." ent))
- ;; Child lookup failed. Try the parent. If this bombs,
- ;; we are at wits end -- signal an error.
- ;; Problem: If this signals an error, the error message
- ;; may not have a lot to do with what went wrong.
- (ange-ftp-hash-entry-exists-p file
- (ange-ftp-get-files dir))))))
-
-(defun ange-ftp-get-file-entry (name)
- "Given NAME, return the given file entry.
-The entry will be either t for a directory, nil for a normal file,
-or a string for a symlink. If the file isn't in the hashtable,
-this also returns nil."
- (let* ((name (directory-file-name name))
- (dir (file-name-directory name))
- (ent (ange-ftp-get-hash-entry dir ange-ftp-files-hashtable))
- (file (ange-ftp-get-file-part name)))
- (if ent
- (ange-ftp-get-hash-entry file ent)
- (or (and (ange-ftp-allow-child-lookup dir file)
- (setq ent (ange-ftp-get-files name t))
- (ange-ftp-get-hash-entry "." ent))
- ;; i.e. it's a directory by child lookup
- (ange-ftp-get-hash-entry file
- (ange-ftp-get-files dir))))))
-
-(defun ange-ftp-internal-delete-file-entry (name &optional dir-p)
- (if dir-p
- (progn
- (setq name (file-name-as-directory name))
- (ange-ftp-del-hash-entry name ange-ftp-files-hashtable)
- (setq name (directory-file-name name))))
- ;; Note that file-name-as-directory followed by directory-file-name
- ;; serves to canonicalize directory file names to their unix form.
- ;; i.e. in VMS, FOO.DIR -> FOO/ -> FOO
- (let ((files (ange-ftp-get-hash-entry (file-name-directory name)
- ange-ftp-files-hashtable)))
- (if files
- (ange-ftp-del-hash-entry (ange-ftp-get-file-part name)
- files))))
-
-(defun ange-ftp-internal-add-file-entry (name &optional dir-p)
- (and dir-p
- (setq name (directory-file-name name)))
- (let ((files (ange-ftp-get-hash-entry (file-name-directory name)
- ange-ftp-files-hashtable)))
- (if files
- (ange-ftp-put-hash-entry (ange-ftp-get-file-part name)
- dir-p
- files))))
-
-(defun ange-ftp-wipe-file-entries (host user)
- "Get rid of entry for HOST, USER pair from file entry information hashtable."
- (let ((new-tbl (ange-ftp-make-hashtable (length ange-ftp-files-hashtable))))
- (ange-ftp-map-hashtable
- (function
- (lambda (key val)
- (let ((parsed (ange-ftp-ftp-name key)))
- (if parsed
- (let ((h (nth 0 parsed))
- (u (nth 1 parsed)))
- (or (and (equal host h) (equal user u))
- (ange-ftp-put-hash-entry key val new-tbl)))))))
- ange-ftp-files-hashtable)
- (setq ange-ftp-files-hashtable new-tbl)))
-
-;;;; ------------------------------------------------------------
-;;;; File transfer mode support.
-;;;; ------------------------------------------------------------
-
-(defun ange-ftp-set-binary-mode (host user)
- "Tell the ftp process for the given HOST & USER to switch to binary mode."
- (let ((result (ange-ftp-send-cmd host user '(type "binary"))))
- (if (not (car result))
- (ange-ftp-error host user (concat "BINARY failed: " (cdr result)))
- (save-excursion
- (set-buffer (process-buffer (ange-ftp-get-process host user)))
- (and ange-ftp-binary-hash-mark-size
- (setq ange-ftp-hash-mark-unit
- (ash ange-ftp-binary-hash-mark-size -4)))))))
-
-(defun ange-ftp-set-ascii-mode (host user)
- "Tell the ftp process for the given HOST & USER to switch to ascii mode."
- (let ((result (ange-ftp-send-cmd host user '(type "ascii"))))
- (if (not (car result))
- (ange-ftp-error host user (concat "ASCII failed: " (cdr result)))
- (save-excursion
- (set-buffer (process-buffer (ange-ftp-get-process host user)))
- (and ange-ftp-ascii-hash-mark-size
- (setq ange-ftp-hash-mark-unit
- (ash ange-ftp-ascii-hash-mark-size -4)))))))
-
-(defun ange-ftp-cd (host user dir)
- (let ((result (ange-ftp-send-cmd host user (list 'cd dir) "Doing CD")))
- (or (car result)
- (ange-ftp-error host user (concat "CD failed: " (cdr result))))))
-
-(defun ange-ftp-get-pwd (host user)
- "Attempts to get the current working directory for the given HOST/USER pair.
-Returns \( DIR . LINE \) where DIR is either the directory or NIL if not found,
-and LINE is the relevant success or fail line from the FTP-client."
- (let* ((result (ange-ftp-send-cmd host user '(pwd) "Getting PWD"))
- (line (cdr result))
- dir)
- (if (car result)
- (save-match-data
- (and (or (string-match "\"\\([^\"]*\\)\"" line)
- (string-match " \\([^ ]+\\) " line)) ; stone-age VMS servers!
- (setq dir (substring line
- (match-beginning 1)
- (match-end 1))))))
- (cons dir line)))
-
-;;; ------------------------------------------------------------
-;;; expand-file-name and friends...which currently don't work
-;;; ------------------------------------------------------------
-
-(defun ange-ftp-expand-dir (host user dir)
- "Return the result of doing a PWD in the current FTP session.
-Use the connection to machine HOST
-logged in as user USER and cd'd to directory DIR."
- (let* ((host-type (ange-ftp-host-type host user))
- ;; It is more efficient to call ange-ftp-host-type
- ;; before binding res, because ange-ftp-host-type sometimes
- ;; adds to the info in the expand-dir-hashtable.
- (fix-name-func
- (cdr (assq host-type ange-ftp-fix-name-func-alist)))
- (key (concat host "/" user "/" dir))
- (res (ange-ftp-get-hash-entry key ange-ftp-expand-dir-hashtable)))
- (or res
- (progn
- (or
- (string-equal user "anonymous")
- (string-equal user "ftp")
- (not (eq host-type 'unix))
- (let* ((ange-ftp-good-msgs (concat ange-ftp-expand-dir-regexp
- "\\|"
- ange-ftp-good-msgs))
- (result (ange-ftp-send-cmd host user
- (list 'get dir "/dev/null")
- (format "expanding %s" dir)))
- (line (cdr result)))
- (setq res
- (if (string-match ange-ftp-expand-dir-regexp line)
- (substring line
- (match-beginning 1)
- (match-end 1))))))
- (or res
- (if (string-equal dir "~")
- (setq res (car (ange-ftp-get-pwd host user)))
- (let ((home (ange-ftp-expand-dir host user "~")))
- (unwind-protect
- (and (ange-ftp-cd host user dir)
- (setq res (car (ange-ftp-get-pwd host user))))
- (ange-ftp-cd host user home)))))
- (if res
- (let ((ange-ftp-this-user user)
- (ange-ftp-this-host host))
- (if fix-name-func
- (setq res (funcall fix-name-func res 'reverse)))
- (ange-ftp-put-hash-entry
- key res ange-ftp-expand-dir-hashtable)))
- res))))
-
-(defun ange-ftp-canonize-filename (n)
- "Take a string and short-circuit //, /. and /.."
- (if (string-match "[^:]+//" n) ;don't upset Apollo users
- (setq n (substring n (1- (match-end 0)))))
- (let ((parsed (ange-ftp-ftp-name n)))
- (if parsed
- (let ((host (car parsed))
- (user (nth 1 parsed))
- (name (nth 2 parsed)))
-
- ;; See if remote name is absolute. If so then just expand it and
- ;; replace the name component of the overall name.
- (cond ((string-match "^/" name)
- name)
-
- ;; Name starts with ~ or ~user. Resolve that part of the name
- ;; making it absolute then re-expand it.
- ((string-match "^~[^/]*" name)
- (let* ((tilda (substring name
- (match-beginning 0)
- (match-end 0)))
- (rest (substring name (match-end 0)))
- (dir (ange-ftp-expand-dir host user tilda)))
- (if dir
- (setq name (concat dir rest))
- (error "User \"%s\" is not known"
- (substring tilda 1)))))
-
- ;; relative name. Tack on homedir and re-expand.
- (t
- (let ((dir (ange-ftp-expand-dir host user "~")))
- (if dir
- (setq name (concat
- (ange-ftp-real-file-name-as-directory dir)
- name))
- (error "Unable to obtain CWD")))))
-
- ;; If name starts with //, preserve that, for apollo system.
- (if (not (string-match "^//" name))
- (progn
- (setq name (ange-ftp-real-expand-file-name name))
-
- (if (string-match "^//" name)
- (setq name (substring name 1)))))
-
- ;; Now substitute the expanded name back into the overall filename.
- (ange-ftp-replace-name-component n name))
-
- ;; non-ange-ftp name. Just expand normally.
- (if (eq (string-to-char n) ?/)
- (ange-ftp-real-expand-file-name n)
- (ange-ftp-real-expand-file-name
- (ange-ftp-real-file-name-nondirectory n)
- (ange-ftp-real-file-name-directory n))))))
-
-(defun ange-ftp-expand-file-name (name &optional default)
- "Documented as original."
- (save-match-data
- (if (eq (string-to-char name) ?/)
- (while (cond ((string-match "[^:]+//" name) ;don't upset Apollo users
- (setq name (substring name (1- (match-end 0)))))
- ((string-match "/~" name)
- (setq name (substring name (1- (match-end 0))))))))
- (cond ((eq (string-to-char name) ?~)
- (ange-ftp-real-expand-file-name name))
- ((eq (string-to-char name) ?/)
- (ange-ftp-canonize-filename name))
- ((zerop (length name))
- (ange-ftp-canonize-filename (or default default-directory)))
- ((ange-ftp-canonize-filename
- (concat (file-name-as-directory (or default default-directory))
- name))))))
-
-;;; These are problems--they are currently not enabled.
-
-(defvar ange-ftp-file-name-as-directory-alist nil
- "Association list of \( TYPE \. FUNC \) pairs.
-FUNC converts a filename to a directory name for the operating
-system TYPE.")
-
-(defun ange-ftp-file-name-as-directory (name)
- "Documented as original."
- (let ((parsed (ange-ftp-ftp-name name)))
- (if parsed
- (if (string-equal (nth 2 parsed) "")
- name
- (funcall (or (cdr (assq
- (ange-ftp-host-type (car parsed))
- ange-ftp-file-name-as-directory-alist))
- 'ange-ftp-real-file-name-as-directory)
- name))
- (ange-ftp-real-file-name-as-directory name))))
-
-(defun ange-ftp-file-name-directory (name)
- "Documented as original."
- (let ((parsed (ange-ftp-ftp-name name)))
- (if parsed
- (let ((filename (nth 2 parsed)))
- (if (save-match-data
- (string-match "^~[^/]*$" filename))
- name
- (ange-ftp-replace-name-component
- name
- (ange-ftp-real-file-name-directory filename))))
- (ange-ftp-real-file-name-directory name))))
-
-(defun ange-ftp-file-name-nondirectory (name)
- "Documented as original."
- (let ((parsed (ange-ftp-ftp-name name)))
- (if parsed
- (let ((filename (nth 2 parsed)))
- (if (save-match-data
- (string-match "^~[^/]*$" filename))
- ""
- (ange-ftp-real-file-name-nondirectory name)))
- (ange-ftp-real-file-name-nondirectory name))))
-
-(defun ange-ftp-directory-file-name (dir)
- "Documented as original."
- (let ((parsed (ange-ftp-ftp-name dir)))
- (if parsed
- (ange-ftp-replace-name-component
- dir
- (ange-ftp-real-directory-file-name (nth 2 parsed)))
- (ange-ftp-real-directory-file-name dir))))
-
-
-;;; Hooks that handle Emacs primitives.
-
-;; Returns non-nil if should transfer FILE in binary mode.
-(defun ange-ftp-binary-file (file)
- (save-match-data
- (string-match ange-ftp-binary-file-name-regexp file)))
-
-(defun ange-ftp-write-region (start end filename &optional append visit)
- (setq filename (expand-file-name filename))
- (let ((parsed (ange-ftp-ftp-name filename)))
- (if parsed
- (let* ((host (nth 0 parsed))
- (user (nth 1 parsed))
- (name (ange-ftp-quote-string (nth 2 parsed)))
- (temp (ange-ftp-make-tmp-name host))
- (binary (or (ange-ftp-binary-file filename)
- (eq (ange-ftp-host-type host user) 'unix)))
- (cmd (if append 'append 'put))
- (abbr (ange-ftp-abbreviate-filename filename)))
- (unwind-protect
- (progn
- (let ((executing-kbd-macro t)
- (filename (buffer-file-name))
- (mod-p (buffer-modified-p)))
- (unwind-protect
- (ange-ftp-real-write-region start end temp nil visit)
- ;; cleanup forms
- (setq buffer-file-name filename)
- (set-buffer-modified-p mod-p)))
- (if binary
- (ange-ftp-set-binary-mode host user))
-
- ;; tell the process filter what size the transfer will be.
- (let ((attr (file-attributes temp)))
- (if attr
- (ange-ftp-set-xfer-size host user (nth 7 attr))))
-
- ;; put or append the file.
- (let ((result (ange-ftp-send-cmd host user
- (list cmd temp name)
- (format "Writing %s" abbr))))
- (or (car result)
- (signal 'ftp-error
- (list
- "Opening output file"
- (format "FTP Error: \"%s\"" (cdr result))
- filename)))))
- (ange-ftp-del-tmp-name temp)
- (if binary
- (ange-ftp-set-ascii-mode host user)))
- (if (eq visit t)
- (progn
- (set-visited-file-modtime '(0 0))
- (ange-ftp-set-buffer-mode)
- (setq buffer-file-name filename)
- (set-buffer-modified-p nil)))
- (ange-ftp-message "Wrote %s" abbr)
- (ange-ftp-add-file-entry filename))
- (ange-ftp-real-write-region start end filename append visit))))
-
-(defun ange-ftp-insert-file-contents (filename &optional visit beg end replace)
- (barf-if-buffer-read-only)
- (setq filename (expand-file-name filename))
- (let ((parsed (ange-ftp-ftp-name filename)))
- (if parsed
- (progn
- (if visit
- (setq buffer-file-name filename))
- (if (or (file-exists-p filename)
- (progn
- (setq ange-ftp-ls-cache-file nil)
- (ange-ftp-del-hash-entry (file-name-directory filename)
- ange-ftp-files-hashtable)
- (file-exists-p filename)))
- (let* ((host (nth 0 parsed))
- (user (nth 1 parsed))
- (name (ange-ftp-quote-string (nth 2 parsed)))
- (temp (ange-ftp-make-tmp-name host))
- (binary (or (ange-ftp-binary-file filename)
- (eq (ange-ftp-host-type host user) 'unix)))
- (abbr (ange-ftp-abbreviate-filename filename))
- size)
- (unwind-protect
- (progn
- (if binary
- (ange-ftp-set-binary-mode host user))
- (let ((result (ange-ftp-send-cmd host user
- (list 'get name temp)
- (format "Retrieving %s" abbr))))
- (or (car result)
- (signal 'ftp-error
- (list
- "Opening input file"
- (format "FTP Error: \"%s\"" (cdr result))
- filename))))
- (if (or (ange-ftp-real-file-readable-p temp)
- (sleep-for ange-ftp-retry-time)
- ;; Wait for file to hopefully appear.
- (ange-ftp-real-file-readable-p temp))
- (setq
- size
- (nth 1 (ange-ftp-real-insert-file-contents
- temp visit beg end replace)))
- (signal 'ftp-error
- (list
- "Opening input file:"
- (format
- "FTP Error: %s not arrived or readable"
- filename)))))
- (if binary
- (ange-ftp-set-ascii-mode host user))
- (ange-ftp-del-tmp-name temp))
- (if visit
- (progn
- (set-visited-file-modtime '(0 0))
- (setq buffer-file-name filename)))
- (list filename size))
- (signal 'file-error
- (list
- "Opening input file"
- filename))))
- (ange-ftp-real-insert-file-contents filename visit beg end replace))))
-
-(defun ange-ftp-expand-symlink (file dir)
- (if (file-name-absolute-p file)
- (ange-ftp-replace-name-component dir file)
- (expand-file-name file dir)))
-
-(defun ange-ftp-file-symlink-p (file)
- ;; call ange-ftp-expand-file-name rather than the normal
- ;; expand-file-name to stop loops when using a package that
- ;; redefines both file-symlink-p and expand-file-name.
- (setq file (ange-ftp-expand-file-name file))
- (if (ange-ftp-ftp-name file)
- (let ((file-ent
- (ange-ftp-get-hash-entry
- (ange-ftp-get-file-part file)
- (ange-ftp-get-files (file-name-directory file)))))
- (if (stringp file-ent)
- (if (file-name-absolute-p file-ent)
- (ange-ftp-replace-name-component
- (file-name-directory file) file-ent)
- file-ent)))
- (ange-ftp-real-file-symlink-p file)))
-
-(defun ange-ftp-file-exists-p (name)
- (setq name (expand-file-name name))
- (if (ange-ftp-ftp-name name)
- (if (ange-ftp-file-entry-p name)
- (let ((file-ent (ange-ftp-get-file-entry name)))
- (if (stringp file-ent)
- (file-exists-p
- (ange-ftp-expand-symlink file-ent
- (file-name-directory
- (directory-file-name name))))
- t)))
- (ange-ftp-real-file-exists-p name)))
-
-(defun ange-ftp-file-directory-p (name)
- (setq name (expand-file-name name))
- (if (ange-ftp-ftp-name name)
- ;; We do a file-name-as-directory on name here because some
- ;; machines (VMS) use a .DIR to indicate the filename associated
- ;; with a directory. This needs to be canonicalized.
- (let ((file-ent (ange-ftp-get-file-entry
- (ange-ftp-file-name-as-directory name))))
- (if (stringp file-ent)
- (file-directory-p
- (ange-ftp-expand-symlink file-ent
- (file-name-directory
- (directory-file-name name))))
- file-ent))
- (ange-ftp-real-file-directory-p name)))
-
-(defun ange-ftp-directory-files (directory &optional full match
- &rest v19-args)
- (setq directory (expand-file-name directory))
- (if (ange-ftp-ftp-name directory)
- (progn
- (ange-ftp-barf-if-not-directory directory)
- (let ((tail (ange-ftp-hash-table-keys
- (ange-ftp-get-files directory)))
- files f)
- (setq directory (file-name-as-directory directory))
- (save-match-data
- (while tail
- (setq f (car tail)
- tail (cdr tail))
- (if (or (not match) (string-match match f))
- (setq files
- (cons (if full (concat directory f) f) files)))))
- (nreverse files)))
- (apply 'ange-ftp-real-directory-files directory full match v19-args)))
-
-(defun ange-ftp-file-attributes (file)
- (setq file (expand-file-name file))
- (let ((parsed (ange-ftp-ftp-name file)))
- (if parsed
- (let ((part (ange-ftp-get-file-part file))
- (files (ange-ftp-get-files (file-name-directory file))))
- (if (ange-ftp-hash-entry-exists-p part files)
- (let ((host (nth 0 parsed))
- (user (nth 1 parsed))
- (name (nth 2 parsed))
- (dirp (ange-ftp-get-hash-entry part files)))
- (list (if (and (stringp dirp) (file-name-absolute-p dirp))
- (ange-ftp-expand-symlink dirp
- (file-name-directory file))
- dirp) ;0 file type
- -1 ;1 link count
- -1 ;2 uid
- -1 ;3 gid
- '(0 0) ;4 atime
- '(0 0) ;5 mtime
- '(0 0) ;6 ctime
- -1 ;7 size
- (concat (if (stringp dirp) "l" (if dirp "d" "-"))
- "?????????") ;8 mode
- nil ;9 gid weird
- ;; Hack to give remote files a unique "inode number".
- ;; It's actually the sum of the characters in its name.
- (apply '+ (nconc (mapcar 'identity host)
- (mapcar 'identity user)
- (mapcar 'identity
- (directory-file-name name))))
- -1 ;11 device number [v19 only]
- ))))
- (ange-ftp-real-file-attributes file))))
-
-(defun ange-ftp-file-writable-p (file)
- (setq file (expand-file-name file))
- (if (ange-ftp-ftp-name file)
- (or (file-exists-p file) ;guess here for speed
- (file-directory-p (file-name-directory file)))
- (ange-ftp-real-file-writable-p file)))
-
-(defun ange-ftp-file-readable-p (file)
- (setq file (expand-file-name file))
- (if (ange-ftp-ftp-name file)
- (file-exists-p file)
- (ange-ftp-real-file-readable-p file)))
-
-(defun ange-ftp-file-executable-p (file)
- (setq file (expand-file-name file))
- (if (ange-ftp-ftp-name file)
- (file-exists-p file)
- (ange-ftp-real-file-executable-p file)))
-
-(defun ange-ftp-delete-file (file)
- (interactive "fDelete file: ")
- (setq file (expand-file-name file))
- (let ((parsed (ange-ftp-ftp-name file)))
- (if parsed
- (let* ((host (nth 0 parsed))
- (user (nth 1 parsed))
- (name (ange-ftp-quote-string (nth 2 parsed)))
- (abbr (ange-ftp-abbreviate-filename file))
- (result (ange-ftp-send-cmd host user
- (list 'delete name)
- (format "Deleting %s" abbr))))
- (or (car result)
- (signal 'ftp-error
- (list
- "Removing old name"
- (format "FTP Error: \"%s\"" (cdr result))
- file)))
- (ange-ftp-delete-file-entry file))
- (ange-ftp-real-delete-file file))))
-
-(defun ange-ftp-verify-visited-file-modtime (buf)
- (let ((name (buffer-file-name buf)))
- (if (and (stringp name) (ange-ftp-ftp-name name))
- t
- (ange-ftp-real-verify-visited-file-modtime buf))))
-
-;;;; ------------------------------------------------------------
-;;;; File copying support... totally re-written 6/24/92.
-;;;; ------------------------------------------------------------
-
-(defun ange-ftp-barf-or-query-if-file-exists (absname querystring interactive)
- (if (file-exists-p absname)
- (if (not interactive)
- (signal 'file-already-exists (list absname))
- (if (not (yes-or-no-p (format "File %s already exists; %s anyway? "
- absname querystring)))
- (signal 'file-already-exists (list absname))))))
-
-;; async local copy commented out for now since I don't seem to get
-;; the process sentinel called for some processes.
-;;
-;; (defun ange-ftp-copy-file-locally (filename newname ok-if-already-exists
-;; keep-date cont)
-;; "Kludge to copy a local file and call a continuation when the copy
-;; finishes."
-;; ;; check to see if we can overwrite
-;; (if (or (not ok-if-already-exists)
-;; (numberp ok-if-already-exists))
-;; (ange-ftp-barf-or-query-if-file-exists newname "copy to it"
-;; (numberp ok-if-already-exists)))
-;; (let ((proc (start-process " *copy*"
-;; (generate-new-buffer "*copy*")
-;; "cp"
-;; filename
-;; newname))
-;; res)
-;; (set-process-sentinel proc (function ange-ftp-copy-file-locally-sentinel))
-;; (process-kill-without-query proc)
-;; (save-excursion
-;; (set-buffer (process-buffer proc))
-;; (make-variable-buffer-local 'copy-cont)
-;; (setq copy-cont cont))))
-;;
-;; (defun ange-ftp-copy-file-locally-sentinel (proc status)
-;; (save-excursion
-;; (set-buffer (process-buffer proc))
-;; (let ((cont copy-cont)
-;; (result (buffer-string)))
-;; (unwind-protect
-;; (if (and (string-equal status "finished\n")
-;; (zerop (length result)))
-;; (ange-ftp-call-cont cont t nil)
-;; (ange-ftp-call-cont cont
-;; nil
-;; (if (zerop (length result))
-;; (substring status 0 -1)
-;; (substring result 0 -1))))
-;; (kill-buffer (current-buffer))))))
-
-;; this is the extended version of ange-ftp-copy-file-internal that works
-;; asynchronously if asked nicely.
-(defun ange-ftp-copy-file-internal (filename newname ok-if-already-exists
- keep-date &optional msg cont nowait)
- (setq filename (expand-file-name filename)
- newname (expand-file-name newname))
-
- ;; canonicalize newname if a directory.
- (if (file-directory-p newname)
- (setq newname (expand-file-name (file-name-nondirectory filename) newname)))
-
- (let ((f-parsed (ange-ftp-ftp-name filename))
- (t-parsed (ange-ftp-ftp-name newname)))
-
- ;; local file to local file copy?
- (if (and (not f-parsed) (not t-parsed))
- (progn
- (ange-ftp-real-copy-file filename newname ok-if-already-exists
- keep-date)
- (if cont
- (ange-ftp-call-cont cont t "Copied locally")))
- ;; one or both files are remote.
- (let* ((f-host (and f-parsed (nth 0 f-parsed)))
- (f-user (and f-parsed (nth 1 f-parsed)))
- (f-name (and f-parsed (ange-ftp-quote-string (nth 2 f-parsed))))
- (f-abbr (ange-ftp-abbreviate-filename filename))
- (t-host (and t-parsed (nth 0 t-parsed)))
- (t-user (and t-parsed (nth 1 t-parsed)))
- (t-name (and t-parsed (ange-ftp-quote-string (nth 2 t-parsed))))
- (t-abbr (ange-ftp-abbreviate-filename newname filename))
- (binary (or (ange-ftp-binary-file filename)
- (ange-ftp-binary-file newname)
- (and (eq (ange-ftp-host-type f-host f-user) 'unix)
- (eq (ange-ftp-host-type t-host t-user) 'unix))))
- temp1
- temp2)
-
- ;; check to see if we can overwrite
- (if (or (not ok-if-already-exists)
- (numberp ok-if-already-exists))
- (ange-ftp-barf-or-query-if-file-exists newname "copy to it"
- (numberp ok-if-already-exists)))
-
- ;; do the copying.
- (if f-parsed
-
- ;; filename was remote.
- (progn
- (if (or (ange-ftp-use-gateway-p f-host)
- t-parsed)
- ;; have to use intermediate file if we are getting via
- ;; gateway machine or we are doing a remote to remote copy.
- (setq temp1 (ange-ftp-make-tmp-name f-host)))
-
- (if binary
- (ange-ftp-set-binary-mode f-host f-user))
-
- (ange-ftp-send-cmd
- f-host
- f-user
- (list 'get f-name (or temp1 newname))
- (or msg
- (if (and temp1 t-parsed)
- (format "Getting %s" f-abbr)
- (format "Copying %s to %s" f-abbr t-abbr)))
- (list (function ange-ftp-cf1)
- filename newname binary msg
- f-parsed f-host f-user f-name f-abbr
- t-parsed t-host t-user t-name t-abbr
- temp1 temp2 cont nowait)
- nowait))
-
- ;; filename wasn't remote. newname must be remote. call the
- ;; function which does the remainder of the copying work.
- (ange-ftp-cf1 t nil
- filename newname binary msg
- f-parsed f-host f-user f-name f-abbr
- t-parsed t-host t-user t-name t-abbr
- nil nil cont nowait))))))
-
-;; next part of copying routine.
-(defun ange-ftp-cf1 (result line
- filename newname binary msg
- f-parsed f-host f-user f-name f-abbr
- t-parsed t-host t-user t-name t-abbr
- temp1 temp2 cont nowait)
- (if line
- ;; filename must have been remote, and we must have just done a GET.
- (unwind-protect
- (or result
- ;; GET failed for some reason. Clean up and get out.
- (progn
- (and temp1 (ange-ftp-del-tmp-name temp1))
- (or cont
- (signal 'ftp-error (list "Opening input file"
- (format "FTP Error: \"%s\"" line)
- filename)))))
- ;; cleanup
- (if binary
- (ange-ftp-set-ascii-mode f-host f-user))))
-
- (if result
- ;; We now have to copy either temp1 or filename to newname.
- (if t-parsed
-
- ;; newname was remote.
- (progn
- (if (ange-ftp-use-gateway-p t-host)
- (setq temp2 (ange-ftp-make-tmp-name t-host)))
-
- ;; make sure data is moved into the right place for the
- ;; outgoing transfer. gateway temporary files complicate
- ;; things nicely.
- (if temp1
- (if temp2
- (if (string-equal temp1 temp2)
- (setq temp1 nil)
- (ange-ftp-real-copy-file temp1 temp2 t))
- (setq temp2 temp1 temp1 nil))
- (if temp2
- (ange-ftp-real-copy-file filename temp2 t)))
-
- (if binary
- (ange-ftp-set-binary-mode t-host t-user))
-
- ;; tell the process filter what size the file is.
- (let ((attr (file-attributes (or temp2 filename))))
- (if attr
- (ange-ftp-set-xfer-size t-host t-user (nth 7 attr))))
-
- (ange-ftp-send-cmd
- t-host
- t-user
- (list 'put (or temp2 filename) t-name)
- (or msg
- (if (and temp2 f-parsed)
- (format "Putting %s" newname)
- (format "Copying %s to %s" f-abbr t-abbr)))
- (list (function ange-ftp-cf2)
- newname t-host t-user binary temp1 temp2 cont)
- nowait))
-
- ;; newname wasn't remote.
- (ange-ftp-cf2 t nil newname t-host t-user binary temp1 temp2 cont))
-
- ;; first copy failed, tell caller
- (ange-ftp-call-cont cont result line)))
-
-;; last part of copying routine.
-(defun ange-ftp-cf2 (result line newname t-host t-user binary temp1 temp2 cont)
- (unwind-protect
- (if line
- ;; result from doing a local to remote copy.
- (unwind-protect
- (progn
- (or result
- (or cont
- (signal 'ftp-error
- (list "Opening output file"
- (format "FTP Error: \"%s\"" line)
- newname))))
-
- (ange-ftp-add-file-entry newname))
-
- ;; cleanup.
- (if binary
- (ange-ftp-set-ascii-mode t-host t-user)))
-
- ;; newname was local.
- (if temp1
- (ange-ftp-real-copy-file temp1 newname t)))
-
- ;; clean up
- (and temp1 (ange-ftp-del-tmp-name temp1))
- (and temp2 (ange-ftp-del-tmp-name temp2))
- (ange-ftp-call-cont cont result line)))
-
-(defun ange-ftp-copy-file (filename newname &optional ok-if-already-exists
- keep-date)
- (interactive "fCopy file: \nFCopy %s to file: \np")
- (ange-ftp-copy-file-internal filename
- newname
- ok-if-already-exists
- keep-date
- nil
- nil
- (interactive-p)))
-
-;;;; ------------------------------------------------------------
-;;;; File renaming support.
-;;;; ------------------------------------------------------------
-
-(defun ange-ftp-rename-remote-to-remote (filename newname f-parsed t-parsed)
- "Rename remote file FILE to remote file NEWNAME."
- (let ((f-host (nth 0 f-parsed))
- (f-user (nth 1 f-parsed))
- (t-host (nth 0 t-parsed))
- (t-user (nth 1 t-parsed)))
- (if (and (string-equal f-host t-host)
- (string-equal f-user t-user))
- (let* ((f-name (ange-ftp-quote-string (nth 2 f-parsed)))
- (t-name (ange-ftp-quote-string (nth 2 t-parsed)))
- (cmd (list 'rename f-name t-name))
- (fabbr (ange-ftp-abbreviate-filename filename))
- (nabbr (ange-ftp-abbreviate-filename newname filename))
- (result (ange-ftp-send-cmd f-host f-user cmd
- (format "Renaming %s to %s"
- fabbr
- nabbr))))
- (or (car result)
- (signal 'ftp-error
- (list
- "Renaming"
- (format "FTP Error: \"%s\"" (cdr result))
- filename
- newname)))
- (ange-ftp-add-file-entry newname)
- (ange-ftp-delete-file-entry filename))
- (ange-ftp-copy-file-internal filename newname t nil)
- (delete-file filename))))
-
-(defun ange-ftp-rename-local-to-remote (filename newname)
- "Rename local FILENAME to remote file NEWNAME."
- (let* ((fabbr (ange-ftp-abbreviate-filename filename))
- (nabbr (ange-ftp-abbreviate-filename newname filename))
- (msg (format "Renaming %s to %s" fabbr nabbr)))
- (ange-ftp-copy-file-internal filename newname t nil msg)
- (let (ange-ftp-process-verbose)
- (delete-file filename))))
-
-(defun ange-ftp-rename-remote-to-local (filename newname)
- "Rename remote file FILENAME to local file NEWNAME."
- (let* ((fabbr (ange-ftp-abbreviate-filename filename))
- (nabbr (ange-ftp-abbreviate-filename newname filename))
- (msg (format "Renaming %s to %s" fabbr nabbr)))
- (ange-ftp-copy-file-internal filename newname t nil msg)
- (let (ange-ftp-process-verbose)
- (delete-file filename))))
-
-(defun ange-ftp-rename-file (filename newname &optional ok-if-already-exists)
- (interactive "fRename file: \nFRename %s to file: \np")
- (setq filename (expand-file-name filename))
- (setq newname (expand-file-name newname))
- (let* ((f-parsed (ange-ftp-ftp-name filename))
- (t-parsed (ange-ftp-ftp-name newname)))
- (if (and (or f-parsed t-parsed)
- (or (not ok-if-already-exists)
- (numberp ok-if-already-exists)))
- (ange-ftp-barf-or-query-if-file-exists
- newname
- "rename to it"
- (numberp ok-if-already-exists)))
- (if f-parsed
- (if t-parsed
- (ange-ftp-rename-remote-to-remote filename newname f-parsed
- t-parsed)
- (ange-ftp-rename-remote-to-local filename newname))
- (if t-parsed
- (ange-ftp-rename-local-to-remote filename newname)
- (ange-ftp-real-rename-file filename newname ok-if-already-exists)))))
-
-;;;; ------------------------------------------------------------
-;;;; File name completion support.
-;;;; ------------------------------------------------------------
-
-;; If the file entry SYM is a symlink, returns whether its file exists.
-;; Note that `ange-ftp-this-dir' is used as a free variable.
-(defun ange-ftp-file-entry-active-p (sym)
- (let ((val (get sym 'val)))
- (or (not (stringp val))
- (file-exists-p (ange-ftp-expand-symlink val ange-ftp-this-dir)))))
-
-;; If the file entry is not a directory (nor a symlink pointing to a directory)
-;; returns whether the file (or file pointed to by the symlink) is ignored
-;; by completion-ignored-extensions.
-;; Note that `ange-ftp-this-dir' and `ange-ftp-completion-ignored-pattern'
-;; are used as free variables.
-(defun ange-ftp-file-entry-not-ignored-p (sym)
- (let ((val (get sym 'val))
- (symname (symbol-name sym)))
- (if (stringp val)
- (let ((file (ange-ftp-expand-symlink val ange-ftp-this-dir)))
- (or (file-directory-p file)
- (and (file-exists-p file)
- (not (string-match ange-ftp-completion-ignored-pattern
- symname)))))
- (or val ; is a directory name
- (not (string-match ange-ftp-completion-ignored-pattern symname))))))
-
-(defun ange-ftp-file-name-all-completions (file dir)
- (let ((ange-ftp-this-dir (expand-file-name dir)))
- (if (ange-ftp-ftp-name ange-ftp-this-dir)
- (progn
- (ange-ftp-barf-if-not-directory ange-ftp-this-dir)
- (setq ange-ftp-this-dir
- (ange-ftp-real-file-name-as-directory ange-ftp-this-dir))
- (let* ((tbl (ange-ftp-get-files ange-ftp-this-dir))
- (completions
- (all-completions file tbl
- (function ange-ftp-file-entry-active-p))))
-
- ;; see whether each matching file is a directory or not...
- (mapcar
- (function
- (lambda (file)
- (let ((ent (ange-ftp-get-hash-entry file tbl)))
- (if (and ent
- (or (not (stringp ent))
- (file-directory-p
- (ange-ftp-expand-symlink ent
- ange-ftp-this-dir))))
- (concat file "/")
- file))))
- completions)))
-
- (if (string-equal "/" ange-ftp-this-dir)
- (nconc (all-completions file (ange-ftp-generate-root-prefixes))
- (ange-ftp-real-file-name-all-completions file
- ange-ftp-this-dir))
- (ange-ftp-real-file-name-all-completions file ange-ftp-this-dir)))))
-
-(defun ange-ftp-file-name-completion (file dir)
- (let ((ange-ftp-this-dir (expand-file-name dir)))
- (if (ange-ftp-ftp-name ange-ftp-this-dir)
- (progn
- (ange-ftp-barf-if-not-directory ange-ftp-this-dir)
- (if (equal file "")
- ""
- (setq ange-ftp-this-dir
- (ange-ftp-real-file-name-as-directory ange-ftp-this-dir)) ;real?
- (let* ((tbl (ange-ftp-get-files ange-ftp-this-dir))
- (ange-ftp-completion-ignored-pattern
- (mapconcat (function
- (lambda (s) (if (stringp s)
- (concat (regexp-quote s) "$")
- "/"))) ; / never in filename
- completion-ignored-extensions
- "\\|")))
- (save-match-data
- (or (ange-ftp-file-name-completion-1
- file tbl ange-ftp-this-dir
- (function ange-ftp-file-entry-not-ignored-p))
- (ange-ftp-file-name-completion-1
- file tbl ange-ftp-this-dir
- (function ange-ftp-file-entry-active-p)))))))
-
- (if (string-equal "/" ange-ftp-this-dir)
- (try-completion
- file
- (nconc (ange-ftp-generate-root-prefixes)
- (mapcar 'list
- (ange-ftp-real-file-name-all-completions file "/"))))
- (ange-ftp-real-file-name-completion file ange-ftp-this-dir)))))
-
-
-(defun ange-ftp-file-name-completion-1 (file tbl dir predicate)
- (let ((bestmatch (try-completion file tbl predicate)))
- (if bestmatch
- (if (eq bestmatch t)
- (if (file-directory-p (expand-file-name file dir))
- (concat file "/")
- t)
- (if (and (eq (try-completion bestmatch tbl predicate) t)
- (file-directory-p
- (expand-file-name bestmatch dir)))
- (concat bestmatch "/")
- bestmatch)))))
-
-;; Put these lines uncommmented in your .emacs if you want C-r to refresh
-;; ange-ftp's cache whilst doing filename completion.
-;;
-;;(define-key minibuffer-local-completion-map "\C-r" 'ange-ftp-re-read-dir)
-;;(define-key minibuffer-local-must-match-map "\C-r" 'ange-ftp-re-read-dir)
-
-;; Force a re-read of the directory DIR. If DIR is omitted then it defaults
-;; to the directory part of the contents of the current buffer.
-(defun ange-ftp-re-read-dir (&optional dir)
- (interactive)
- (if dir
- (setq dir (expand-file-name dir))
- (setq dir (file-name-directory (expand-file-name (buffer-string)))))
- (if (ange-ftp-ftp-name dir)
- (progn
- (setq ange-ftp-ls-cache-file nil)
- (ange-ftp-del-hash-entry dir ange-ftp-files-hashtable)
- (ange-ftp-get-files dir t))))
-
-(defun ange-ftp-make-directory (dir &optional parents)
- (interactive (list (expand-file-name (read-file-name "Make directory: "))))
- (if parents
- (let ((parent (file-name-directory (directory-file-name dir))))
- (or (file-exists-p parent)
- (ange-ftp-make-directory parent parents))))
- (if (file-exists-p dir)
- (error "Cannot make directory %s: file already exists" dir)
- (let ((parsed (ange-ftp-ftp-name dir)))
- (if parsed
- (let* ((host (nth 0 parsed))
- (user (nth 1 parsed))
- ;; Some ftp's on unix machines (at least on Suns)
- ;; insist that mkdir take a filename, and not a
- ;; directory-name name as an arg. Argh!! This is a bug.
- ;; Non-unix machines will probably always insist
- ;; that mkdir takes a directory-name as an arg
- ;; (as the ftp man page says it should).
- (name (ange-ftp-quote-string
- (if (eq (ange-ftp-host-type host) 'unix)
- (ange-ftp-real-directory-file-name (nth 2 parsed))
- (ange-ftp-real-file-name-as-directory
- (nth 2 parsed)))))
- (abbr (ange-ftp-abbreviate-filename dir))
- (result (ange-ftp-send-cmd host user
- (list 'mkdir name)
- (format "Making directory %s"
- abbr))))
- (or (car result)
- (ange-ftp-error host user
- (format "Could not make directory %s: %s"
- dir
- (cdr result))))
- (ange-ftp-add-file-entry dir t))
- (ange-ftp-real-make-directory dir)))))
-
-(defun ange-ftp-delete-directory (dir)
- (if (file-directory-p dir)
- (let ((parsed (ange-ftp-ftp-name dir)))
- (if parsed
- (let* ((host (nth 0 parsed))
- (user (nth 1 parsed))
- ;; Some ftp's on unix machines (at least on Suns)
- ;; insist that rmdir take a filename, and not a
- ;; directory-name name as an arg. Argh!! This is a bug.
- ;; Non-unix machines will probably always insist
- ;; that rmdir takes a directory-name as an arg
- ;; (as the ftp man page says it should).
- (name (ange-ftp-quote-string
- (if (eq (ange-ftp-host-type host) 'unix)
- (ange-ftp-real-directory-file-name
- (nth 2 parsed))
- (ange-ftp-real-file-name-as-directory
- (nth 2 parsed)))))
- (abbr (ange-ftp-abbreviate-filename dir))
- (result (ange-ftp-send-cmd host user
- (list 'rmdir name)
- (format "Removing directory %s"
- abbr))))
- (or (car result)
- (ange-ftp-error host user
- (format "Could not remove directory %s: %s"
- dir
- (cdr result))))
- (ange-ftp-delete-file-entry dir t))
- (ange-ftp-real-delete-directory dir)))
- (error "Not a directory: %s" dir)))
-
-;; Make a local copy of FILE and return its name.
-
-(defun ange-ftp-file-local-copy (file)
- (let* ((fn1 (expand-file-name file))
- (pa1 (ange-ftp-ftp-name fn1)))
- (if pa1
- (let ((tmp1 (ange-ftp-make-tmp-name (car pa1))))
- (ange-ftp-copy-file-internal fn1 tmp1 t nil
- (format "Getting %s" fn1))
- tmp1))))
-
-(defun ange-ftp-load (file &optional noerror nomessage nosuffix)
- (if (ange-ftp-ftp-name file)
- (let ((tryfiles (if nosuffix
- (list file)
- (list (concat file ".elc") (concat file ".el") file)))
- copy)
- (while (and tryfiles (not copy))
- (condition-case error
- (setq copy (ange-ftp-file-local-copy (car tryfiles)))
- (ftp-error nil))
- (setq tryfiles (cdr tryfiles)))
- (if copy
- (unwind-protect
- (funcall 'load copy noerror nomessage nosuffix)
- (delete-file copy))
- (or noerror
- (signal 'file-error (list "Cannot open load file" file)))))
- (ange-ftp-real-load file noerror nomessage nosuffix)))
-
-;; Calculate default-unhandled-directory for a given ange-ftp buffer.
-(defun ange-ftp-unhandled-file-name-directory (filename)
- (file-name-directory ange-ftp-tmp-name-template))
-
-
-;; Need the following functions for making filenames of compressed
-;; files, because some OS's (unlike UNIX) do not allow a filename to
-;; have two extensions.
-
-(defvar ange-ftp-make-compressed-filename-alist nil
- "Alist of host-type-specific functions to process file names for compression.
-Each element has the form (TYPE . FUNC).
-FUNC should take one argument, a file name, and return a list
-of the form (COMPRESSING NEWNAME).
-COMPRESSING should be t if the specified file should be compressed,
-and nil if it should be uncompressed (that is, if it is a compressed file).
-NEWNAME should be the name to give the new compressed or uncompressed file.")
-
-(defun ange-ftp-dired-compress-file (name)
- (let ((parsed (ange-ftp-ftp-name name))
- conversion-func)
- (if (and parsed
- (setq conversion-func
- (cdr (assq (ange-ftp-host-type (car parsed))
- ange-ftp-make-compressed-filename-alist))))
- (let* ((decision
- (save-match-data (funcall conversion-func name)))
- (compressing (car decision))
- (newfile (nth 1 decision)))
- (if compressing
- (ange-ftp-compress name newfile)
- (ange-ftp-uncompress name newfile)))
- (let (file-name-handler-alist)
- (dired-compress-file name)))))
-
-;; Copy FILE to this machine, compress it, and copy out to NFILE.
-(defun ange-ftp-compress (file nfile)
- (let* ((parsed (ange-ftp-ftp-name file))
- (tmp1 (ange-ftp-make-tmp-name (car parsed)))
- (tmp2 (ange-ftp-make-tmp-name (car parsed)))
- (abbr (ange-ftp-abbreviate-filename file))
- (nabbr (ange-ftp-abbreviate-filename nfile))
- (msg1 (format "Getting %s" abbr))
- (msg2 (format "Putting %s" nabbr)))
- (unwind-protect
- (progn
- (ange-ftp-copy-file-internal file tmp1 t nil msg1)
- (and ange-ftp-process-verbose
- (ange-ftp-message "Compressing %s..." abbr))
- (call-process-region (point)
- (point)
- shell-file-name
- nil
- t
- nil
- "-c"
- (format "compress -f -c < %s > %s" tmp1 tmp2))
- (and ange-ftp-process-verbose
- (ange-ftp-message "Compressing %s...done" abbr))
- (if (zerop (buffer-size))
- (progn
- (let (ange-ftp-process-verbose)
- (delete-file file))
- (ange-ftp-copy-file-internal tmp2 nfile t nil msg2))))
- (ange-ftp-del-tmp-name tmp1)
- (ange-ftp-del-tmp-name tmp2))))
-
-;; Copy FILE to this machine, uncompress it, and copy out to NFILE.
-(defun ange-ftp-uncompress (file nfile)
- (let* ((parsed (ange-ftp-ftp-name file))
- (tmp1 (ange-ftp-make-tmp-name (car parsed)))
- (tmp2 (ange-ftp-make-tmp-name (car parsed)))
- (abbr (ange-ftp-abbreviate-filename file))
- (nabbr (ange-ftp-abbreviate-filename nfile))
- (msg1 (format "Getting %s" abbr))
- (msg2 (format "Putting %s" nabbr))
-;; ;; Cheap hack because of problems with binary file transfers from
-;; ;; VMS hosts.
-;; (gbinary (not (eq 'vms (ange-ftp-host-type (car parsed)))))
- )
- (unwind-protect
- (progn
- (ange-ftp-copy-file-internal file tmp1 t nil msg1)
- (and ange-ftp-process-verbose
- (ange-ftp-message "Uncompressing %s..." abbr))
- (call-process-region (point)
- (point)
- shell-file-name
- nil
- t
- nil
- "-c"
- (format "uncompress -c < %s > %s" tmp1 tmp2))
- (and ange-ftp-process-verbose
- (ange-ftp-message "Uncompressing %s...done" abbr))
- (if (zerop (buffer-size))
- (progn
- (let (ange-ftp-process-verbose)
- (delete-file file))
- (ange-ftp-copy-file-internal tmp2 nfile t nil msg2))))
- (ange-ftp-del-tmp-name tmp1)
- (ange-ftp-del-tmp-name tmp2))))
-
-(defun ange-ftp-find-backup-file-name (fn)
- ;; Either return the ordinary backup name, etc.,
- ;; or return nil meaning don't make a backup.
- (if ange-ftp-make-backup-files
- (ange-ftp-real-find-backup-file-name fn)))
-
-;;; Define the handler for special file names
-;;; that causes ange-ftp to be invoked.
-
-;;;###autoload
-(defun ange-ftp-hook-function (operation &rest args)
- (let ((fn (get operation 'ange-ftp)))
- (if fn (apply fn args)
- (ange-ftp-run-real-handler operation args))))
-
-
-;;; This regexp takes care of real ange-ftp file names (with a slash
-;;; and colon).
-;;; Don't allow the host name to end in a period--some systems use /.:
-;;;###autoload
-(or (assoc "^/[^/:]*[^/:.]:" file-name-handler-alist)
- (setq file-name-handler-alist
- (cons '("^/[^/:]*[^/:.]:" . ange-ftp-hook-function)
- file-name-handler-alist)))
-
-;;; This regexp recognizes and absolute filenames with only one component,
-;;; for the sake of hostname completion.
-;;;###autoload
-(or (assoc "^/[^/:]*\\'" file-name-handler-alist)
- (setq file-name-handler-alist
- (cons '("^/[^/:]*\\'" . ange-ftp-completion-hook-function)
- file-name-handler-alist)))
-
-;;; The above two forms are sufficient to cause this file to be loaded
-;;; if the user ever uses a file name with a colon in it.
-
-;;; This sets the mode
-(or (memq 'ange-ftp-set-buffer-mode find-file-hooks)
- (setq find-file-hooks
- (cons 'ange-ftp-set-buffer-mode find-file-hooks)))
-
-;;; Now say where to find the handlers for particular operations.
-
-(put 'file-name-directory 'ange-ftp 'ange-ftp-file-name-directory)
-(put 'file-name-nondirectory 'ange-ftp 'ange-ftp-file-name-nondirectory)
-(put 'file-name-as-directory 'ange-ftp 'ange-ftp-file-name-as-directory)
-(put 'directory-file-name 'ange-ftp 'ange-ftp-directory-file-name)
-(put 'expand-file-name 'ange-ftp 'ange-ftp-expand-file-name)
-(put 'make-directory 'ange-ftp 'ange-ftp-make-directory)
-(put 'delete-directory 'ange-ftp 'ange-ftp-delete-directory)
-(put 'insert-file-contents 'ange-ftp 'ange-ftp-insert-file-contents)
-(put 'directory-files 'ange-ftp 'ange-ftp-directory-files)
-(put 'file-directory-p 'ange-ftp 'ange-ftp-file-directory-p)
-(put 'file-writable-p 'ange-ftp 'ange-ftp-file-writable-p)
-(put 'file-readable-p 'ange-ftp 'ange-ftp-file-readable-p)
-(put 'file-executable-p 'ange-ftp 'ange-ftp-file-executable-p)
-(put 'file-symlink-p 'ange-ftp 'ange-ftp-file-symlink-p)
-(put 'delete-file 'ange-ftp 'ange-ftp-delete-file)
-(put 'read-file-name-internal 'ange-ftp 'ange-ftp-read-file-name-internal)
-(put 'verify-visited-file-modtime 'ange-ftp
- 'ange-ftp-verify-visited-file-modtime)
-(put 'file-exists-p 'ange-ftp 'ange-ftp-file-exists-p)
-(put 'write-region 'ange-ftp 'ange-ftp-write-region)
-(put 'backup-buffer 'ange-ftp 'ange-ftp-backup-buffer)
-(put 'copy-file 'ange-ftp 'ange-ftp-copy-file)
-(put 'rename-file 'ange-ftp 'ange-ftp-rename-file)
-(put 'file-attributes 'ange-ftp 'ange-ftp-file-attributes)
-(put 'file-name-all-completions 'ange-ftp 'ange-ftp-file-name-all-completions)
-(put 'file-name-completion 'ange-ftp 'ange-ftp-file-name-completion)
-(put 'insert-directory 'ange-ftp 'ange-ftp-insert-directory)
-(put 'file-local-copy 'ange-ftp 'ange-ftp-file-local-copy)
-(put 'unhandled-file-name-directory 'ange-ftp
- 'ange-ftp-unhandled-file-name-directory)
-(put 'file-name-sans-versions 'ange-ftp 'ange-ftp-file-name-sans-versions)
-(put 'dired-uncache 'ange-ftp 'ange-ftp-dired-uncache)
-(put 'dired-compress-file 'ange-ftp 'ange-ftp-dired-compress-file)
-(put 'load 'ange-ftp 'ange-ftp-load)
-(put 'find-backup-file-name 'ange-ftp 'ange-ftp-find-backup-file-name)
-
-;; Turn off truename processing to save time.
-;; Treat each name as its own truename.
-(put 'file-truename 'ange-ftp 'identity)
-
-;; Turn off RCS/SCCS processing to save time.
-;; This returns nil for any file name as argument.
-(put 'vc-registered 'ange-ftp 'null)
-
-(put 'dired-call-process 'ange-ftp 'ange-ftp-dired-call-process)
-
-;;; Define ways of getting at unmodified Emacs primitives,
-;;; turning off our handler.
-
-(defun ange-ftp-run-real-handler (operation args)
- (let ((inhibit-file-name-handlers
- (cons 'ange-ftp-hook-function
- (cons 'ange-ftp-completion-hook-function
- (and (eq inhibit-file-name-operation operation)
- inhibit-file-name-handlers))))
- (inhibit-file-name-operation operation))
- (apply operation args)))
-
-(defun ange-ftp-real-file-name-directory (&rest args)
- (ange-ftp-run-real-handler 'file-name-directory args))
-(defun ange-ftp-real-file-name-nondirectory (&rest args)
- (ange-ftp-run-real-handler 'file-name-nondirectory args))
-(defun ange-ftp-real-file-name-as-directory (&rest args)
- (ange-ftp-run-real-handler 'file-name-as-directory args))
-(defun ange-ftp-real-directory-file-name (&rest args)
- (ange-ftp-run-real-handler 'directory-file-name args))
-(defun ange-ftp-real-expand-file-name (&rest args)
- (ange-ftp-run-real-handler 'expand-file-name args))
-(defun ange-ftp-real-make-directory (&rest args)
- (ange-ftp-run-real-handler 'make-directory args))
-(defun ange-ftp-real-delete-directory (&rest args)
- (ange-ftp-run-real-handler 'delete-directory args))
-(defun ange-ftp-real-insert-file-contents (&rest args)
- (ange-ftp-run-real-handler 'insert-file-contents args))
-(defun ange-ftp-real-directory-files (&rest args)
- (ange-ftp-run-real-handler 'directory-files args))
-(defun ange-ftp-real-file-directory-p (&rest args)
- (ange-ftp-run-real-handler 'file-directory-p args))
-(defun ange-ftp-real-file-writable-p (&rest args)
- (ange-ftp-run-real-handler 'file-writable-p args))
-(defun ange-ftp-real-file-readable-p (&rest args)
- (ange-ftp-run-real-handler 'file-readable-p args))
-(defun ange-ftp-real-file-executable-p (&rest args)
- (ange-ftp-run-real-handler 'file-executable-p args))
-(defun ange-ftp-real-file-symlink-p (&rest args)
- (ange-ftp-run-real-handler 'file-symlink-p args))
-(defun ange-ftp-real-delete-file (&rest args)
- (ange-ftp-run-real-handler 'delete-file args))
-(defun ange-ftp-real-read-file-name-internal (&rest args)
- (ange-ftp-run-real-handler 'read-file-name-internal args))
-(defun ange-ftp-real-verify-visited-file-modtime (&rest args)
- (ange-ftp-run-real-handler 'verify-visited-file-modtime args))
-(defun ange-ftp-real-file-exists-p (&rest args)
- (ange-ftp-run-real-handler 'file-exists-p args))
-(defun ange-ftp-real-write-region (&rest args)
- (ange-ftp-run-real-handler 'write-region args))
-(defun ange-ftp-real-backup-buffer (&rest args)
- (ange-ftp-run-real-handler 'backup-buffer args))
-(defun ange-ftp-real-copy-file (&rest args)
- (ange-ftp-run-real-handler 'copy-file args))
-(defun ange-ftp-real-rename-file (&rest args)
- (ange-ftp-run-real-handler 'rename-file args))
-(defun ange-ftp-real-file-attributes (&rest args)
- (ange-ftp-run-real-handler 'file-attributes args))
-(defun ange-ftp-real-file-name-all-completions (&rest args)
- (ange-ftp-run-real-handler 'file-name-all-completions args))
-(defun ange-ftp-real-file-name-completion (&rest args)
- (ange-ftp-run-real-handler 'file-name-completion args))
-(defun ange-ftp-real-insert-directory (&rest args)
- (ange-ftp-run-real-handler 'insert-directory args))
-(defun ange-ftp-real-file-name-sans-versions (&rest args)
- (ange-ftp-run-real-handler 'file-name-sans-versions args))
-(defun ange-ftp-real-shell-command (&rest args)
- (ange-ftp-run-real-handler 'shell-command args))
-(defun ange-ftp-real-load (&rest args)
- (ange-ftp-run-real-handler 'load args))
-(defun ange-ftp-real-find-backup-file-name (&rest args)
- (ange-ftp-run-real-handler 'find-backup-file-name args))
-
-;; Here we support using dired on remote hosts.
-;; I have turned off the support for using dired on foreign directory formats.
-;; That involves too many unclean hooks.
-;; It would be cleaner to support such operations by
-;; converting the foreign directory format to something dired can understand;
-;; something close to ls -l output.
-;; The logical place to do this is in the functions ange-ftp-parse-...-listing.
-
-;; Some of the old dired hooks would still be needed even if this is done.
-;; I have preserved (and modernized) those hooks.
-;; So the format conversion should be all that is needed.
-
-(defun ange-ftp-insert-directory (file switches &optional wildcard full)
- (let ((short (ange-ftp-abbreviate-filename file))
- (parsed (ange-ftp-ftp-name (expand-file-name file))))
- (if parsed
- (insert
- (if wildcard
- (let ((default-directory (file-name-directory file)))
- (ange-ftp-ls (file-name-nondirectory file) switches nil nil t))
- (ange-ftp-ls file switches full)))
- (ange-ftp-real-insert-directory file switches wildcard full))))
-
-(defun ange-ftp-dired-uncache (dir)
- (if (ange-ftp-ftp-name (expand-file-name dir))
- (setq ange-ftp-ls-cache-file nil)))
-
-(defvar ange-ftp-sans-version-alist nil
- "Alist of mapping host type into function to remove file version numbers.")
-
-(defun ange-ftp-file-name-sans-versions (file keep-backup-version)
- (setq file (ange-ftp-abbreviate-filename file))
- (let ((parsed (ange-ftp-ftp-name file))
- host-type func)
- (if parsed
- (setq host-type (ange-ftp-host-type (car parsed))
- func (cdr (assq (ange-ftp-host-type (car parsed))
- ange-ftp-sans-version-alist))))
- (if func (funcall func file keep-backup-version)
- (ange-ftp-real-file-name-sans-versions file keep-backup-version))))
-
-;;; This doesn't work yet; a new hook needs to be created.
-;;; Maybe the new hook should be in call-process.
-(defun ange-ftp-shell-command (command)
- (let* ((parsed (ange-ftp-ftp-name default-directory))
- (host (nth 0 parsed))
- (user (nth 1 parsed))
- (name (nth 2 parsed)))
- (if (not parsed)
- (ange-ftp-real-shell-command command)
- (if (> (length name) 0) ; else it's $HOME
- (setq command (concat "cd " name "; " command)))
- (setq command
- (format "%s %s \"%s\"" ; remsh -l USER does not work well
- ; on a hp-ux machine I tried
- remote-shell-program host command))
- (ange-ftp-message "Remote command '%s' ..." command)
- ;; Cannot call ange-ftp-real-dired-run-shell-command here as it
- ;; would prepend "cd default-directory" --- which bombs because
- ;; default-directory is in ange-ftp syntax for remote file names.
- (ange-ftp-real-shell-command command))))
-
-;;; This is the handler for call-process.
-(defun ange-ftp-dired-call-process (program discard &rest arguments)
- ;; PROGRAM is always one of those below in the cond in dired.el.
- ;; The ARGUMENTS are (nearly) always files.
- (if (ange-ftp-ftp-name default-directory)
- ;; Can't use ange-ftp-dired-host-type here because the current
- ;; buffer is *dired-check-process output*
- (condition-case oops
- (cond ((equal "chmod" program)
- (ange-ftp-call-chmod arguments))
- ;; ((equal "chgrp" program))
- ;; ((equal dired-chown-program program))
- (t (error "Unknown remote command: %s" program)))
- (ftp-error (insert (format "%s: %s, %s\n"
- (nth 1 oops)
- (nth 2 oops)
- (nth 3 oops)))
- ;; Caller expects nonzero value to mean failure.
- 1)
- (error (insert (format "%s\n" (nth 1 oops)))
- 1))
- (apply 'call-process program nil (not discard) nil arguments)))
-
-(defvar ange-ftp-remote-shell "rsh"
- "Remote shell to use for chmod, if FTP server rejects the `chmod' command.")
-
-;; Handle an attempt to run chmod on a remote file
-;; by using the ftp chmod command.
-(defun ange-ftp-call-chmod (args)
- (if (< (length args) 2)
- (error "ange-ftp-call-chmod: missing mode and/or filename: %s" args))
- (let ((mode (car args)))
- (mapcar
- (function
- (lambda (file)
- (setq file (expand-file-name file))
- (let ((parsed (ange-ftp-ftp-name file)))
- (if parsed
- (let* ((host (nth 0 parsed))
- (user (nth 1 parsed))
- (name (ange-ftp-quote-string (nth 2 parsed)))
- (abbr (ange-ftp-abbreviate-filename file))
- (result (ange-ftp-send-cmd host user
- (list 'chmod mode name)
- (format "doing chmod %s"
- abbr))))
- (or (car result)
- (call-process
- ange-ftp-remote-shell
- nil t nil host "chmod" mode name)))))))
- (cdr args)))
- (setq ange-ftp-ls-cache-file nil) ;Stop confusing Dired.
- 0)
-
-;;; This is turned off because it has nothing properly to do
-;;; with dired. It could be reasonable to adapt this to
-;;; replace ange-ftp-copy-file.
-
-;;;;; ------------------------------------------------------------
-;;;;; Noddy support for async copy-file within dired.
-;;;;; ------------------------------------------------------------
-
-;;(defun ange-ftp-dired-copy-file (from to ok-flag &optional cont nowait)
-;; "Documented as original."
-;; (dired-handle-overwrite to)
-;; (ange-ftp-copy-file-internal from to ok-flag dired-copy-preserve-time nil
-;; cont nowait))
-
-;;(defun ange-ftp-dired-do-create-files (op-symbol file-creator operation arg
-;; &optional marker-char op1
-;; how-to)
-;; "Documented as original."
-;; ;; we need to let ange-ftp-dired-create-files know that we indirectly
-;; ;; called it rather than somebody else.
-;; (let ((ange-ftp-dired-do-create-files t)) ; tell who caller is
-;; (ange-ftp-real-dired-do-create-files op-symbol file-creator operation
-;; arg marker-char op1 how-to)))
-
-;;(defun ange-ftp-dired-create-files (file-creator operation fn-list name-constructor
-;; &optional marker-char)
-;; "Documented as original."
-;; (if (and (boundp 'ange-ftp-dired-do-create-files)
-;; ;; called from ange-ftp-dired-do-create-files?
-;; ange-ftp-dired-do-create-files
-;; ;; any files worth copying?
-;; fn-list
-;; ;; we only support async copy-file at the mo.
-;; (eq file-creator 'dired-copy-file)
-;; ;; it is only worth calling the alternative function for remote files
-;; ;; as we tie ourself in recursive knots otherwise.
-;; (or (ange-ftp-ftp-name (car fn-list))
-;; ;; we can only call the name constructor for dired-do-create-files
-;; ;; since the one for regexps starts prompting here, there and
-;; ;; everywhere.
-;; (ange-ftp-ftp-name (funcall name-constructor (car fn-list)))))
-;; ;; use the process-filter driven routine rather than the iterative one.
-;; (ange-ftp-dcf-1 file-creator
-;; operation
-;; fn-list
-;; name-constructor
-;; (and (boundp 'target) target) ;dynamically bound
-;; marker-char
-;; (current-buffer)
-;; nil ;overwrite-query
-;; nil ;overwrite-backup-query
-;; nil ;failures
-;; nil ;skipped
-;; 0 ;success-count
-;; (length fn-list) ;total
-;; )
-;; ;; normal case... use the interactive routine... much cheaper.
-;; (ange-ftp-real-dired-create-files file-creator operation fn-list
-;; name-constructor marker-char)))
-
-;;(defun ange-ftp-dcf-1 (file-creator operation fn-list name-constructor
-;; target marker-char buffer overwrite-query
-;; overwrite-backup-query failures skipped
-;; success-count total)
-;; (let ((old-buf (current-buffer)))
-;; (unwind-protect
-;; (progn
-;; (set-buffer buffer)
-;; (if (null fn-list)
-;; (ange-ftp-dcf-3 failures operation total skipped
-;; success-count buffer)
-
-;; (let* ((from (car fn-list))
-;; (to (funcall name-constructor from)))
-;; (if (equal to from)
-;; (progn
-;; (setq to nil)
-;; (dired-log "Cannot %s to same file: %s\n"
-;; (downcase operation) from)))
-;; (if (not to)
-;; (ange-ftp-dcf-1 file-creator
-;; operation
-;; (cdr fn-list)
-;; name-constructor
-;; target
-;; marker-char
-;; buffer
-;; overwrite-query
-;; overwrite-backup-query
-;; failures
-;; (cons (dired-make-relative from) skipped)
-;; success-count
-;; total)
-;; (let* ((overwrite (file-exists-p to))
-;; (overwrite-confirmed ; for dired-handle-overwrite
-;; (and overwrite
-;; (let ((help-form '(format "\
-;;Type SPC or `y' to overwrite file `%s',
-;;DEL or `n' to skip to next,
-;;ESC or `q' to not overwrite any of the remaining files,
-;;`!' to overwrite all remaining files with no more questions." to)))
-;; (dired-query 'overwrite-query
-;; "Overwrite `%s'?" to))))
-;; ;; must determine if FROM is marked before file-creator
-;; ;; gets a chance to delete it (in case of a move).
-;; (actual-marker-char
-;; (cond ((integerp marker-char) marker-char)
-;; (marker-char (dired-file-marker from)) ; slow
-;; (t nil))))
-;; (condition-case err
-;; (funcall file-creator from to overwrite-confirmed
-;; (list (function ange-ftp-dcf-2)
-;; nil ;err
-;; file-creator operation fn-list
-;; name-constructor
-;; target
-;; marker-char actual-marker-char
-;; buffer to from
-;; overwrite
-;; overwrite-confirmed
-;; overwrite-query
-;; overwrite-backup-query
-;; failures skipped success-count
-;; total)
-;; t)
-;; (file-error ; FILE-CREATOR aborted
-;; (ange-ftp-dcf-2 nil ;result
-;; nil ;line
-;; err
-;; file-creator operation fn-list
-;; name-constructor
-;; target
-;; marker-char actual-marker-char
-;; buffer to from
-;; overwrite
-;; overwrite-confirmed
-;; overwrite-query
-;; overwrite-backup-query
-;; failures skipped success-count
-;; total))))))))
-;; (set-buffer old-buf))))
-
-;;(defun ange-ftp-dcf-2 (result line err
-;; file-creator operation fn-list
-;; name-constructor
-;; target
-;; marker-char actual-marker-char
-;; buffer to from
-;; overwrite
-;; overwrite-confirmed
-;; overwrite-query
-;; overwrite-backup-query
-;; failures skipped success-count
-;; total)
-;; (let ((old-buf (current-buffer)))
-;; (unwind-protect
-;; (progn
-;; (set-buffer buffer)
-;; (if (or err (not result))
-;; (progn
-;; (setq failures (cons (dired-make-relative from) failures))
-;; (dired-log "%s `%s' to `%s' failed:\n%s\n"
-;; operation from to (or err line)))
-;; (if overwrite
-;; ;; If we get here, file-creator hasn't been aborted
-;; ;; and the old entry (if any) has to be deleted
-;; ;; before adding the new entry.
-;; (dired-remove-file to))
-;; (setq success-count (1+ success-count))
-;; (message "%s: %d of %d" operation success-count total)
-;; (dired-add-file to actual-marker-char))
-
-;; (ange-ftp-dcf-1 file-creator operation (cdr fn-list)
-;; name-constructor
-;; target
-;; marker-char
-;; buffer
-;; overwrite-query
-;; overwrite-backup-query
-;; failures skipped success-count
-;; total))
-;; (set-buffer old-buf))))
-
-;;(defun ange-ftp-dcf-3 (failures operation total skipped success-count
-;; buffer)
-;; (let ((old-buf (current-buffer)))
-;; (unwind-protect
-;; (progn
-;; (set-buffer buffer)
-;; (cond
-;; (failures
-;; (dired-log-summary
-;; (message "%s failed for %d of %d file%s %s"
-;; operation (length failures) total
-;; (dired-plural-s total) failures)))
-;; (skipped
-;; (dired-log-summary
-;; (message "%s: %d of %d file%s skipped %s"
-;; operation (length skipped) total
-;; (dired-plural-s total) skipped)))
-;; (t
-;; (message "%s: %s file%s."
-;; operation success-count (dired-plural-s success-count))))
-;; (dired-move-to-filename))
-;; (set-buffer old-buf))))
-
-;;;; -----------------------------------------------
-;;;; Unix Descriptive Listing (dl) Support
-;;;; -----------------------------------------------
-
-;; This is turned off because nothing uses it currently
-;; and because I don't understand what it's supposed to be for. --rms.
-
-;;(defconst ange-ftp-dired-dl-re-dir
-;; "^. [^ /]+/[ \n]"
-;; "Regular expression to use to search for dl directories.")
-
-;;(or (assq 'unix:dl ange-ftp-dired-re-dir-alist)
-;; (setq ange-ftp-dired-re-dir-alist
-;; (cons (cons 'unix:dl ange-ftp-dired-dl-re-dir)
-;; ange-ftp-dired-re-dir-alist)))
-
-;;(defun ange-ftp-dired-dl-move-to-filename (&optional raise-error eol)
-;; "In dired, move to the first character of the filename on this line."
-;; ;; This is the Unix dl version.
-;; (or eol (setq eol (progn (end-of-line) (point))))
-;; (let (case-fold-search)
-;; (beginning-of-line)
-;; (if (looking-at ". [^ ]+ +\\([0-9]+\\|-\\|=\\) ")
-;; (goto-char (+ (point) 2))
-;; (if raise-error
-;; (error "No file on this line")
-;; nil))))
-
-;;(or (assq 'unix:dl ange-ftp-dired-move-to-filename-alist)
-;; (setq ange-ftp-dired-move-to-filename-alist
-;; (cons '(unix:dl . ange-ftp-dired-dl-move-to-filename)
-;; ange-ftp-dired-move-to-filename-alist)))
-
-;;(defun ange-ftp-dired-dl-move-to-end-of-filename (&optional no-error eol)
-;; ;; Assumes point is at beginning of filename.
-;; ;; So, it should be called only after (dired-move-to-filename t).
-;; ;; On failure, signals an error or returns nil.
-;; ;; This is the Unix dl version.
-;; (let ((opoint (point))
-;; case-fold-search hidden)
-;; (or eol (setq eol (save-excursion (end-of-line) (point))))
-;; (setq hidden (and selective-display
-;; (save-excursion
-;; (search-forward "\r" eol t))))
-;; (if hidden
-;; (if no-error
-;; nil
-;; (error
-;; (substitute-command-keys
-;; "File line is hidden, type \\[dired-hide-subdir] to unhide")))
-;; (skip-chars-forward "^ /" eol)
-;; (if (eq opoint (point))
-;; (if no-error
-;; nil
-;; (error "No file on this line"))
-;; (point)))))
-
-;;(or (assq 'unix:dl ange-ftp-dired-move-to-end-of-filename-alist)
-;; (setq ange-ftp-dired-move-to-end-of-filename-alist
-;; (cons '(unix:dl . ange-ftp-dired-dl-move-to-end-of-filename)
-;; ange-ftp-dired-move-to-end-of-filename-alist)))
-
-;;;; ------------------------------------------------------------
-;;;; VOS support (VOS support is probably broken,
-;;;; but I don't know anything about VOS.)
-;;;; ------------------------------------------------------------
-;
-;(defun ange-ftp-fix-name-for-vos (name &optional reverse)
-; (setq name (copy-sequence name))
-; (let ((from (if reverse ?\> ?\/))
-; (to (if reverse ?\/ ?\>))
-; (i (1- (length name))))
-; (while (>= i 0)
-; (if (= (aref name i) from)
-; (aset name i to))
-; (setq i (1- i)))
-; name))
-;
-;(or (assq 'vos ange-ftp-fix-name-func-alist)
-; (setq ange-ftp-fix-name-func-alist
-; (cons '(vos . ange-ftp-fix-name-for-vos)
-; ange-ftp-fix-name-func-alist)))
-;
-;(or (memq 'vos ange-ftp-dumb-host-types)
-; (setq ange-ftp-dumb-host-types
-; (cons 'vos ange-ftp-dumb-host-types)))
-;
-;(defun ange-ftp-fix-dir-name-for-vos (dir-name)
-; (ange-ftp-fix-name-for-vos
-; (concat dir-name
-; (if (eq ?/ (aref dir-name (1- (length dir-name))))
-; "" "/")
-; "*")))
-;
-;(or (assq 'vos ange-ftp-fix-dir-name-func-alist)
-; (setq ange-ftp-fix-dir-name-func-alist
-; (cons '(vos . ange-ftp-fix-dir-name-for-vos)
-; ange-ftp-fix-dir-name-func-alist)))
-;
-;(defvar ange-ftp-vos-host-regexp nil
-; "If a host matches this regexp then it is assumed to be running VOS.")
-;
-;(defun ange-ftp-vos-host (host)
-; (and ange-ftp-vos-host-regexp
-; (save-match-data
-; (string-match ange-ftp-vos-host-regexp host))))
-;
-;(defun ange-ftp-parse-vos-listing ()
-; "Parse the current buffer which is assumed to be in VOS list -all
-;format, and return a hashtable as the result."
-; (let ((tbl (ange-ftp-make-hashtable))
-; (type-list
-; '(("^Files: [0-9]+ +Blocks: [0-9]+\n+" nil 40)
-; ("^Dirs: [0-9]+\n+" t 30)))
-; type-regexp type-is-dir type-col file)
-; (goto-char (point-min))
-; (save-match-data
-; (while type-list
-; (setq type-regexp (car (car type-list))
-; type-is-dir (nth 1 (car type-list))
-; type-col (nth 2 (car type-list))
-; type-list (cdr type-list))
-; (if (re-search-forward type-regexp nil t)
-; (while (eq (char-after (point)) ? )
-; (move-to-column type-col)
-; (setq file (buffer-substring (point)
-; (progn
-; (end-of-line 1)
-; (point))))
-; (ange-ftp-put-hash-entry file type-is-dir tbl)
-; (forward-line 1))))
-; (ange-ftp-put-hash-entry "." 'vosdir tbl)
-; (ange-ftp-put-hash-entry ".." 'vosdir tbl))
-; tbl))
-;
-;(or (assq 'vos ange-ftp-parse-list-func-alist)
-; (setq ange-ftp-parse-list-func-alist
-; (cons '(vos . ange-ftp-parse-vos-listing)
-; ange-ftp-parse-list-func-alist)))
-
-;;;; ------------------------------------------------------------
-;;;; VMS support.
-;;;; ------------------------------------------------------------
-
-;; Convert NAME from UNIX-ish to VMS. If REVERSE given then convert from VMS
-;; to UNIX-ish.
-(defun ange-ftp-fix-name-for-vms (name &optional reverse)
- (save-match-data
- (if reverse
- (if (string-match "^\\([^:]+:\\)?\\(\\[.*\\]\\)?\\([^][]*\\)$" name)
- (let (drive dir file)
- (if (match-beginning 1)
- (setq drive (substring name
- (match-beginning 1)
- (match-end 1))))
- (if (match-beginning 2)
- (setq dir
- (substring name (match-beginning 2) (match-end 2))))
- (if (match-beginning 3)
- (setq file
- (substring name (match-beginning 3) (match-end 3))))
- (and dir
- (setq dir (apply (function concat)
- (mapcar (function
- (lambda (char)
- (if (= char ?.)
- (vector ?/)
- (vector char))))
- (substring dir 1 -1)))))
- (concat (and drive
- (concat "/" drive "/"))
- dir (and dir "/")
- file))
- (error "name %s didn't match" name))
- (let (drive dir file tmp)
- (if (string-match "^/[^:]+:/" name)
- (setq drive (substring name 1
- (1- (match-end 0)))
- name (substring name (match-end 0))))
- (setq tmp (file-name-directory name))
- (if tmp
- (setq dir (apply (function concat)
- (mapcar (function
- (lambda (char)
- (if (= char ?/)
- (vector ?.)
- (vector char))))
- (substring tmp 0 -1)))))
- (setq file (file-name-nondirectory name))
- (concat drive
- (and dir (concat "[" (if drive nil ".") dir "]"))
- file)))))
-
-;; (ange-ftp-fix-name-for-vms "/PUB$:/ANONYMOUS/SDSCPUB/NEXT/Readme.txt;1")
-;; (ange-ftp-fix-name-for-vms "/PUB$:[ANONYMOUS.SDSCPUB.NEXT]Readme.txt;1" t)
-
-(or (assq 'vms ange-ftp-fix-name-func-alist)
- (setq ange-ftp-fix-name-func-alist
- (cons '(vms . ange-ftp-fix-name-for-vms)
- ange-ftp-fix-name-func-alist)))
-
-(or (memq 'vms ange-ftp-dumb-host-types)
- (setq ange-ftp-dumb-host-types
- (cons 'vms ange-ftp-dumb-host-types)))
-
-;; It is important that this function barf for directories for which we know
-;; that we cannot possibly get a directory listing, such as "/" and "/DEV:/".
-;; This is because it saves an unnecessary FTP error, or possibly the listing
-;; might succeed, but give erroneous info. This last case is particularly
-;; likely for OS's (like MTS) for which we need to use a wildcard in order
-;; to list a directory.
-
-;; Convert name from UNIX-ish to VMS ready for a DIRectory listing.
-(defun ange-ftp-fix-dir-name-for-vms (dir-name)
- ;; Should there be entries for .. -> [-] and . -> [] below. Don't
- ;; think so, because expand-filename should have already short-circuited
- ;; them.
- (cond ((string-equal dir-name "/")
- (error "Cannot get listing for fictitious \"/\" directory."))
- ((string-match "^/[-A-Z0-9_$]+:/$" dir-name)
- (error "Cannot get listing for device."))
- ((ange-ftp-fix-name-for-vms dir-name))))
-
-(or (assq 'vms ange-ftp-fix-dir-name-func-alist)
- (setq ange-ftp-fix-dir-name-func-alist
- (cons '(vms . ange-ftp-fix-dir-name-for-vms)
- ange-ftp-fix-dir-name-func-alist)))
-
-(defvar ange-ftp-vms-host-regexp nil)
-
-;; Return non-nil if HOST is running VMS.
-(defun ange-ftp-vms-host (host)
- (and ange-ftp-vms-host-regexp
- (save-match-data
- (string-match ange-ftp-vms-host-regexp host))))
-
-;; Because some VMS ftp servers convert filenames to lower case
-;; we allow a-z in the filename regexp. I'm not too happy about this.
-
-(defconst ange-ftp-vms-filename-regexp
- (concat
- "\\(\\([_A-Za-z0-9$]?\\|[_A-Za-z0-9$][-_A-Za-z0-9$]*\\)\\."
- "[-_A-Za-z0-9$]*;+[0-9]*\\)")
- "Regular expression to match for a valid VMS file name in Dired buffer.
-Stupid freaking bug! Position of _ and $ shouldn't matter but they do.
-Having [A-Z0-9$_] bombs on filename _$$CHANGE_LOG$.TXT$ and $CHANGE_LOG$.TX
-Other orders of $ and _ seem to all work just fine.")
-
-;; These parsing functions are as general as possible because the syntax
-;; of ftp listings from VMS hosts is a bit erratic. What saves us is that
-;; the VMS filename syntax is so rigid. If they bomb on a listing in the
-;; standard VMS Multinet format, then this is a bug. If they bomb on a listing
-;; from vms.weird.net, then too bad.
-
-;; Extract the next filename from a VMS dired-like listing.
-(defun ange-ftp-parse-vms-filename ()
- (if (re-search-forward
- ange-ftp-vms-filename-regexp
- nil t)
- (buffer-substring (match-beginning 0) (match-end 0))))
-
-;; Parse the current buffer which is assumed to be in MultiNet FTP dir
-;; format, and return a hashtable as the result.
-(defun ange-ftp-parse-vms-listing ()
- (let ((tbl (ange-ftp-make-hashtable))
- file)
- (goto-char (point-min))
- (save-match-data
- (while (setq file (ange-ftp-parse-vms-filename))
- (if (string-match "\\.\\(DIR\\|dir\\);[0-9]+" file)
- ;; deal with directories
- (ange-ftp-put-hash-entry
- (substring file 0 (match-beginning 0)) t tbl)
- (ange-ftp-put-hash-entry file nil tbl)
- (if (string-match ";[0-9]+$" file) ; deal with extension
- ;; sans extension
- (ange-ftp-put-hash-entry
- (substring file 0 (match-beginning 0)) nil tbl)))
- (forward-line 1))
- ;; Would like to look for a "Total" line, or a "Directory" line to
- ;; make sure that the listing isn't complete garbage before putting
- ;; in "." and "..", but we can't even count on all VAX's giving us
- ;; either of these.
- (ange-ftp-put-hash-entry "." t tbl)
- (ange-ftp-put-hash-entry ".." t tbl))
- tbl))
-
-(or (assq 'vms ange-ftp-parse-list-func-alist)
- (setq ange-ftp-parse-list-func-alist
- (cons '(vms . ange-ftp-parse-vms-listing)
- ange-ftp-parse-list-func-alist)))
-
-;; This version only deletes file entries which have
-;; explicit version numbers, because that is all VMS allows.
-
-;; Can the following two functions be speeded up using file
-;; completion functions?
-
-(defun ange-ftp-vms-delete-file-entry (name &optional dir-p)
- (if dir-p
- (ange-ftp-internal-delete-file-entry name t)
- (save-match-data
- (let ((file (ange-ftp-get-file-part name)))
- (if (string-match ";[0-9]+$" file)
- ;; In VMS you can't delete a file without an explicit
- ;; version number, or wild-card (e.g. FOO;*)
- ;; For now, we give up on wildcards.
- (let ((files (ange-ftp-get-hash-entry
- (file-name-directory name)
- ange-ftp-files-hashtable)))
- (if files
- (let* ((root (substring file 0
- (match-beginning 0)))
- (regexp (concat "^"
- (regexp-quote root)
- ";[0-9]+$"))
- versions)
- (ange-ftp-del-hash-entry file files)
- ;; Now we need to check if there are any
- ;; versions left. If not, then delete the
- ;; root entry.
- (mapatoms
- '(lambda (sym)
- (and (string-match regexp (get sym 'key))
- (setq versions t)))
- files)
- (or versions
- (ange-ftp-del-hash-entry root files))))))))))
-
-(or (assq 'vms ange-ftp-delete-file-entry-alist)
- (setq ange-ftp-delete-file-entry-alist
- (cons '(vms . ange-ftp-vms-delete-file-entry)
- ange-ftp-delete-file-entry-alist)))
-
-(defun ange-ftp-vms-add-file-entry (name &optional dir-p)
- (if dir-p
- (ange-ftp-internal-add-file-entry name t)
- (let ((files (ange-ftp-get-hash-entry
- (file-name-directory name)
- ange-ftp-files-hashtable)))
- (if files
- (let ((file (ange-ftp-get-file-part name)))
- (save-match-data
- (if (string-match ";[0-9]+$" file)
- (ange-ftp-put-hash-entry
- (substring file 0 (match-beginning 0))
- nil files)
- ;; Need to figure out what version of the file
- ;; is being added.
- (let ((regexp (concat "^"
- (regexp-quote file)
- ";\\([0-9]+\\)$"))
- (version 0))
- (mapatoms
- '(lambda (sym)
- (let ((name (get sym 'key)))
- (and (string-match regexp name)
- (setq version
- (max version
- (string-to-int
- (substring name
- (match-beginning 1)
- (match-end 1))))))))
- files)
- (setq version (1+ version))
- (ange-ftp-put-hash-entry
- (concat file ";" (int-to-string version))
- nil files))))
- (ange-ftp-put-hash-entry file nil files))))))
-
-(or (assq 'vms ange-ftp-add-file-entry-alist)
- (setq ange-ftp-add-file-entry-alist
- (cons '(vms . ange-ftp-vms-add-file-entry)
- ange-ftp-add-file-entry-alist)))
-
-
-(defun ange-ftp-add-vms-host (host)
- "Mark HOST as the name of a machine running VMS."
- (interactive
- (list (read-string "Host: "
- (let ((name (or (buffer-file-name) default-directory)))
- (and name (car (ange-ftp-ftp-name name)))))))
- (if (not (ange-ftp-vms-host host))
- (setq ange-ftp-vms-host-regexp
- (concat "^" (regexp-quote host) "$"
- (and ange-ftp-vms-host-regexp "\\|")
- ange-ftp-vms-host-regexp)
- ange-ftp-host-cache nil)))
-
-
-(defun ange-ftp-vms-file-name-as-directory (name)
- (save-match-data
- (if (string-match "\\.\\(DIR\\|dir\\)\\(;[0-9]+\\)?$" name)
- (setq name (substring name 0 (match-beginning 0))))
- (ange-ftp-real-file-name-as-directory name)))
-
-(or (assq 'vms ange-ftp-file-name-as-directory-alist)
- (setq ange-ftp-file-name-as-directory-alist
- (cons '(vms . ange-ftp-vms-file-name-as-directory)
- ange-ftp-file-name-as-directory-alist)))
-
-;;; Tree dired support:
-
-;; For this code I have borrowed liberally from Sebastian Kremer's
-;; dired-vms.el
-
-
-;;;; These regexps must be anchored to beginning of line.
-;;;; Beware that the ftpd may put the device in front of the filename.
-
-;;(defconst ange-ftp-dired-vms-re-exe "^. [^ \t.]+\\.\\(EXE\\|exe\\)[; ]"
-;; "Regular expression to use to search for VMS executable files.")
-
-;;(defconst ange-ftp-dired-vms-re-dir "^. [^ \t.]+\\.\\(DIR\\|dir\\)[; ]"
-;; "Regular expression to use to search for VMS directories.")
-
-;;(or (assq 'vms ange-ftp-dired-re-exe-alist)
-;; (setq ange-ftp-dired-re-exe-alist
-;; (cons (cons 'vms ange-ftp-dired-vms-re-exe)
-;; ange-ftp-dired-re-exe-alist)))
-
-;;(or (assq 'vms ange-ftp-dired-re-dir-alist)
-;; (setq ange-ftp-dired-re-dir-alist
-;; (cons (cons 'vms ange-ftp-dired-vms-re-dir)
-;; ange-ftp-dired-re-dir-alist)))
-
-;;(defun ange-ftp-dired-vms-insert-headerline (dir)
-;; ;; VMS inserts a headerline. I would prefer the headerline
-;; ;; to be in ange-ftp format. This version tries to
-;; ;; be careful, because we can't count on a headerline
-;; ;; over ftp, and we wouldn't want to delete anything
-;; ;; important.
-;; (save-excursion
-;; (if (looking-at "^ wildcard ")
-;; (forward-line 1))
-;; (if (looking-at "^[ \n\t]*[^\n]+\\][ \t]*\n")
-;; (delete-region (point) (match-end 0))))
-;; (ange-ftp-real-dired-insert-headerline dir))
-
-;;(or (assq 'vms ange-ftp-dired-insert-headerline-alist)
-;; (setq ange-ftp-dired-insert-headerline-alist
-;; (cons '(vms . ange-ftp-dired-vms-insert-headerline)
-;; ange-ftp-dired-insert-headerline-alist)))
-
-;;(defun ange-ftp-dired-vms-move-to-filename (&optional raise-error eol)
-;; "In dired, move to first char of filename on this line.
-;;Returns position (point) or nil if no filename on this line."
-;; ;; This is the VMS version.
-;; (let (case-fold-search)
-;; (or eol (setq eol (progn (end-of-line) (point))))
-;; (beginning-of-line)
-;; (if (re-search-forward ange-ftp-vms-filename-regexp eol t)
-;; (goto-char (match-beginning 1))
-;; (if raise-error
-;; (error "No file on this line")
-;; nil))))
-
-;;(or (assq 'vms ange-ftp-dired-move-to-filename-alist)
-;; (setq ange-ftp-dired-move-to-filename-alist
-;; (cons '(vms . ange-ftp-dired-vms-move-to-filename)
-;; ange-ftp-dired-move-to-filename-alist)))
-
-;;(defun ange-ftp-dired-vms-move-to-end-of-filename (&optional no-error eol)
-;; ;; Assumes point is at beginning of filename.
-;; ;; So, it should be called only after (dired-move-to-filename t).
-;; ;; case-fold-search must be nil, at least for VMS.
-;; ;; On failure, signals an error or returns nil.
-;; ;; This is the VMS version.
-;; (let (opoint hidden case-fold-search)
-;; (setq opoint (point))
-;; (or eol (setq eol (save-excursion (end-of-line) (point))))
-;; (setq hidden (and selective-display
-;; (save-excursion (search-forward "\r" eol t))))
-;; (if hidden
-;; nil
-;; (re-search-forward ange-ftp-vms-filename-regexp eol t))
-;; (or no-error
-;; (not (eq opoint (point)))
-;; (error
-;; (if hidden
-;; (substitute-command-keys
-;; "File line is hidden, type \\[dired-hide-subdir] to unhide")
-;; "No file on this line")))
-;; (if (eq opoint (point))
-;; nil
-;; (point))))
-
-;;(or (assq 'vms ange-ftp-dired-move-to-end-of-filename-alist)
-;; (setq ange-ftp-dired-move-to-end-of-filename-alist
-;; (cons '(vms . ange-ftp-dired-vms-move-to-end-of-filename)
-;; ange-ftp-dired-move-to-end-of-filename-alist)))
-
-;;(defun ange-ftp-dired-vms-between-files ()
-;; (save-excursion
-;; (beginning-of-line)
-;; (or (equal (following-char) 10) ; newline
-;; (equal (following-char) 9) ; tab
-;; (progn (forward-char 2)
-;; (or (looking-at "Total of")
-;; (equal (following-char) 32))))))
-
-;;(or (assq 'vms ange-ftp-dired-between-files-alist)
-;; (setq ange-ftp-dired-between-files-alist
-;; (cons '(vms . ange-ftp-dired-vms-between-files)
-;; ange-ftp-dired-between-files-alist)))
-
-;; Beware! In VMS filenames must be of the form "FILE.TYPE".
-;; Therefore, we cannot just append a ".Z" to filenames for
-;; compressed files. Instead, we turn "FILE.TYPE" into
-;; "FILE.TYPE-Z". Hope that this is a reasonable thing to do.
-
-(defun ange-ftp-vms-make-compressed-filename (name &optional reverse)
- (cond
- ((string-match "-Z;[0-9]+$" name)
- (list nil (substring name 0 (match-beginning 0))))
- ((string-match ";[0-9]+$" name)
- (list nil (substring name 0 (match-beginning 0))))
- ((string-match "-Z$" name)
- (list nil (substring name 0 -2)))
- (t
- (list t
- (if (string-match ";[0-9]+$" name)
- (concat (substring name 0 (match-beginning 0))
- "-Z")
- (concat name "-Z"))))))
-
-(or (assq 'vms ange-ftp-make-compressed-filename-alist)
- (setq ange-ftp-make-compressed-filename-alist
- (cons '(vms . ange-ftp-vms-make-compressed-filename)
- ange-ftp-make-compressed-filename-alist)))
-
-;;;; When the filename is too long, VMS will use two lines to list a file
-;;;; (damn them!) This will confuse dired. To solve this, need to convince
-;;;; Sebastian to use a function dired-go-to-end-of-file-line, instead of
-;;;; (forward-line 1). This would require a number of changes to dired.el.
-;;;; If dired gets confused, revert-buffer will fix it.
-
-;;(defun ange-ftp-dired-vms-ls-trim ()
-;; (goto-char (point-min))
-;; (let ((case-fold-search nil))
-;; (re-search-forward ange-ftp-vms-filename-regexp))
-;; (beginning-of-line)
-;; (delete-region (point-min) (point))
-;; (forward-line 1)
-;; (delete-region (point) (point-max)))
-
-
-;;(or (assq 'vms ange-ftp-dired-ls-trim-alist)
-;; (setq ange-ftp-dired-ls-trim-alist
-;; (cons '(vms . ange-ftp-dired-vms-ls-trim)
-;; ange-ftp-dired-ls-trim-alist)))
-
-(defun ange-ftp-vms-sans-version (name &rest args)
- (save-match-data
- (if (string-match ";[0-9]+$" name)
- (substring name 0 (match-beginning 0))
- name)))
-
-(or (assq 'vms ange-ftp-sans-version-alist)
- (setq ange-ftp-sans-version-alist
- (cons '(vms . ange-ftp-vms-sans-version)
- ange-ftp-sans-version-alist)))
-
-;;(defvar ange-ftp-file-version-alist)
-
-;;;;; The vms version of clean-directory has 2 more optional args
-;;;;; than the usual dired version. This is so that it can be used by
-;;;;; ange-ftp-dired-vms-flag-backup-files.
-
-;;(defun ange-ftp-dired-vms-clean-directory (keep &optional marker msg)
-;; "Flag numerical backups for deletion.
-;;Spares `dired-kept-versions' latest versions, and `kept-old-versions' oldest.
-;;Positive prefix arg KEEP overrides `dired-kept-versions';
-;;Negative prefix arg KEEP overrides `kept-old-versions' with KEEP made positive.
-
-;;To clear the flags on these files, you can use \\[dired-flag-backup-files]
-;;with a prefix argument."
-;;; (interactive "P") ; Never actually called interactively.
-;; (setq keep (max 1 (if keep (prefix-numeric-value keep) dired-kept-versions)))
-;; (let ((early-retention (if (< keep 0) (- keep) kept-old-versions))
-;; ;; late-retention must NEVER be allowed to be less than 1 in VMS!
-;; ;; This could wipe ALL copies of the file.
-;; (late-retention (max 1 (if (<= keep 0) dired-kept-versions keep)))
-;; (action (or msg "Cleaning"))
-;; (ange-ftp-trample-marker (or marker dired-del-marker))
-;; (ange-ftp-file-version-alist ()))
-;; (message (concat action
-;; " numerical backups (keeping %d late, %d old)...")
-;; late-retention early-retention)
-;; ;; Look at each file.
-;; ;; If the file has numeric backup versions,
-;; ;; put on ange-ftp-file-version-alist an element of the form
-;; ;; (FILENAME . VERSION-NUMBER-LIST)
-;; (dired-map-dired-file-lines (function
-;; ange-ftp-dired-vms-collect-file-versions))
-;; ;; Sort each VERSION-NUMBER-LIST,
-;; ;; and remove the versions not to be deleted.
-;; (let ((fval ange-ftp-file-version-alist))
-;; (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
-;; (function
-;; ange-ftp-dired-vms-trample-file-versions mark))
-;; (message (concat action " numerical backups...done"))))
-
-;;(or (assq 'vms ange-ftp-dired-clean-directory-alist)
-;; (setq ange-ftp-dired-clean-directory-alist
-;; (cons '(vms . ange-ftp-dired-vms-clean-directory)
-;; ange-ftp-dired-clean-directory-alist)))
-
-;;(defun ange-ftp-dired-vms-collect-file-versions (fn)
-;; ;; "If it looks like file FN has versions, return a list of the versions.
-;; ;;That is a list of strings which are file names.
-;; ;;The caller may want to flag some of these files for deletion."
-;;(let ((name (nth 2 (ange-ftp-ftp-name fn))))
-;; (if (string-match ";[0-9]+$" name)
-;; (let* ((name (substring name 0 (match-beginning 0)))
-;; (fn (ange-ftp-replace-name-component fn name)))
-;; (if (not (assq fn ange-ftp-file-version-alist))
-;; (let* ((base-versions
-;; (concat (file-name-nondirectory name) ";"))
-;; (bv-length (length base-versions))
-;; (possibilities (file-name-all-completions
-;; base-versions
-;; (file-name-directory fn)))
-;; (versions (mapcar
-;; '(lambda (arg)
-;; (if (and (string-match
-;; "[0-9]+$" arg bv-length)
-;; (= (match-beginning 0) bv-length))
-;; (string-to-int (substring arg bv-length))
-;; 0))
-;; possibilities)))
-;; (if versions
-;; (setq
-;; ange-ftp-file-version-alist
-;; (cons (cons fn versions)
-;; ange-ftp-file-version-alist)))))))))
-
-;;(defun ange-ftp-dired-vms-trample-file-versions (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
-;; ange-ftp-file-version-alist)) ; subversion
-;; (not (memq (string-to-int (substring fn (1+ start-vn)))
-;; base-version-list)) ; this one doesn't make the cut
-;; (progn (beginning-of-line)
-;; (delete-char 1)
-;; (insert ange-ftp-trample-marker)))))
-
-;;(defun ange-ftp-dired-vms-flag-backup-files (&optional unflag-p)
-;; (let ((dired-kept-versions 1)
-;; (kept-old-versions 0)
-;; marker msg)
-;; (if unflag-p
-;; (setq marker ?\040 msg "Unflagging")
-;; (setq marker dired-del-marker msg "Cleaning"))
-;; (ange-ftp-dired-vms-clean-directory nil marker msg)))
-
-;;(or (assq 'vms ange-ftp-dired-flag-backup-files-alist)
-;; (setq ange-ftp-dired-flag-backup-files-alist
-;; (cons '(vms . ange-ftp-dired-vms-flag-backup-files)
-;; ange-ftp-dired-flag-backup-files-alist)))
-
-;;(defun ange-ftp-dired-vms-backup-diff (&optional switches)
-;; (let ((file (dired-get-filename 'no-dir))
-;; bak)
-;; (if (and (string-match ";[0-9]+$" file)
-;; ;; Find most recent previous version.
-;; (let ((root (substring file 0 (match-beginning 0)))
-;; (ver
-;; (string-to-int (substring file (1+ (match-beginning 0)))))
-;; found)
-;; (setq ver (1- ver))
-;; (while (and (> ver 0) (not found))
-;; (setq bak (concat root ";" (int-to-string ver)))
-;; (and (file-exists-p bak) (setq found t))
-;; (setq ver (1- ver)))
-;; found))
-;; (if switches
-;; (diff (expand-file-name bak) (expand-file-name file) switches)
-;; (diff (expand-file-name bak) (expand-file-name file)))
-;; (error "No previous version found for %s" file))))
-
-;;(or (assq 'vms ange-ftp-dired-backup-diff-alist)
-;; (setq ange-ftp-dired-backup-diff-alist
-;; (cons '(vms . ange-ftp-dired-vms-backup-diff)
-;; ange-ftp-dired-backup-diff-alist)))
-
-
-;;;; ------------------------------------------------------------
-;;;; MTS support
-;;;; ------------------------------------------------------------
-
-
-;; Convert NAME from UNIX-ish to MTS. If REVERSE given then convert from
-;; MTS to UNIX-ish.
-(defun ange-ftp-fix-name-for-mts (name &optional reverse)
- (save-match-data
- (if reverse
- (if (string-match "^\\([^:]+:\\)?\\(.*\\)$" name)
- (let (acct file)
- (if (match-beginning 1)
- (setq acct (substring name 0 (match-end 1))))
- (if (match-beginning 2)
- (setq file (substring name
- (match-beginning 2) (match-end 2))))
- (concat (and acct (concat "/" acct "/"))
- file))
- (error "name %s didn't match" name))
- (if (string-match "^/\\([^:]+:\\)/\\(.*\\)$" name)
- (concat (substring name 1 (match-end 1))
- (substring name (match-beginning 2) (match-end 2)))
- ;; Let's hope that mts will recognize it anyway.
- name))))
-
-(or (assq 'mts ange-ftp-fix-name-func-alist)
- (setq ange-ftp-fix-name-func-alist
- (cons '(mts . ange-ftp-fix-name-for-mts)
- ange-ftp-fix-name-func-alist)))
-
-;; Convert name from UNIX-ish to MTS ready for a DIRectory listing.
-;; Remember that there are no directories in MTS.
-(defun ange-ftp-fix-dir-name-for-mts (dir-name)
- (if (string-equal dir-name "/")
- (error "Cannot get listing for fictitious \"/\" directory.")
- (let ((dir-name (ange-ftp-fix-name-for-mts dir-name)))
- (cond
- ((string-equal dir-name "")
- "?")
- ((string-match ":$" dir-name)
- (concat dir-name "?"))
- (dir-name))))) ; It's just a single file.
-
-(or (assq 'mts ange-ftp-fix-dir-name-func-alist)
- (setq ange-ftp-fix-dir-name-func-alist
- (cons '(mts . ange-ftp-fix-dir-name-for-mts)
- ange-ftp-fix-dir-name-func-alist)))
-
-(or (memq 'mts ange-ftp-dumb-host-types)
- (setq ange-ftp-dumb-host-types
- (cons 'mts ange-ftp-dumb-host-types)))
-
-(defvar ange-ftp-mts-host-regexp nil)
-
-;; Return non-nil if HOST is running MTS.
-(defun ange-ftp-mts-host (host)
- (and ange-ftp-mts-host-regexp
- (save-match-data
- (string-match ange-ftp-mts-host-regexp host))))
-
-;; Parse the current buffer which is assumed to be in mts ftp dir format.
-(defun ange-ftp-parse-mts-listing ()
- (let ((tbl (ange-ftp-make-hashtable)))
- (goto-char (point-min))
- (save-match-data
- (while (re-search-forward ange-ftp-date-regexp nil t)
- (end-of-line)
- (skip-chars-backward " ")
- (let ((end (point)))
- (skip-chars-backward "-A-Z0-9_.!")
- (ange-ftp-put-hash-entry (buffer-substring (point) end) nil tbl))
- (forward-line 1)))
- ;; Don't need to bother with ..
- (ange-ftp-put-hash-entry "." t tbl)
- tbl))
-
-(or (assq 'mts ange-ftp-parse-list-func-alist)
- (setq ange-ftp-parse-list-func-alist
- (cons '(mts . ange-ftp-parse-mts-listing)
- ange-ftp-parse-list-func-alist)))
-
-(defun ange-ftp-add-mts-host (host)
- "Mark HOST as the name of a machine running MTS."
- (interactive
- (list (read-string "Host: "
- (let ((name (or (buffer-file-name) default-directory)))
- (and name (car (ange-ftp-ftp-name name)))))))
- (if (not (ange-ftp-mts-host host))
- (setq ange-ftp-mts-host-regexp
- (concat "^" (regexp-quote host) "$"
- (and ange-ftp-mts-host-regexp "\\|")
- ange-ftp-mts-host-regexp)
- ange-ftp-host-cache nil)))
-
-;;; Tree dired support:
-
-;;;; There aren't too many systems left that use MTS. This dired support will
-;;;; work for the implementation of ftp on mtsg.ubc.ca. I hope other mts systems
-;;;; implement ftp in the same way. If not, it might be necessary to make the
-;;;; following more flexible.
-
-;;(defun ange-ftp-dired-mts-move-to-filename (&optional raise-error eol)
-;; "In dired, move to first char of filename on this line.
-;;Returns position (point) or nil if no filename on this line."
-;; ;; This is the MTS version.
-;; (or eol (setq eol (progn (end-of-line) (point))))
-;; (beginning-of-line)
-;; (if (re-search-forward
-;; ange-ftp-date-regexp eol t)
-;; (progn
-;; (skip-chars-forward " ") ; Eat blanks after date
-;; (skip-chars-forward "0-9:" eol) ; Eat time or year
-;; (skip-chars-forward " " eol) ; one space before filename
-;; ;; When listing an account other than the users own account it appends
-;; ;; ACCT: to the beginning of the filename. Skip over this.
-;; (and (looking-at "[A-Z0-9_.]+:")
-;; (goto-char (match-end 0)))
-;; (point))
-;; (if raise-error
-;; (error "No file on this line")
-;; nil)))
-
-;;(or (assq 'mts ange-ftp-dired-move-to-filename-alist)
-;; (setq ange-ftp-dired-move-to-filename-alist
-;; (cons '(mts . ange-ftp-dired-mts-move-to-filename)
-;; ange-ftp-dired-move-to-filename-alist)))
-
-;;(defun ange-ftp-dired-mts-move-to-end-of-filename (&optional no-error eol)
-;; ;; Assumes point is at beginning of filename.
-;; ;; So, it should be called only after (dired-move-to-filename t).
-;; ;; On failure, signals an error or returns nil.
-;; ;; This is the MTS version.
-;; (let (opoint hidden case-fold-search)
-;; (setq opoint (point)
-;; eol (save-excursion (end-of-line) (point))
-;; hidden (and selective-display
-;; (save-excursion (search-forward "\r" eol t))))
-;; (if hidden
-;; nil
-;; (skip-chars-forward "-A-Z0-9._!" eol))
-;; (or no-error
-;; (not (eq opoint (point)))
-;; (error
-;; (if hidden
-;; (substitute-command-keys
-;; "File line is hidden, type \\[dired-hide-subdir] to unhide")
-;; "No file on this line")))
-;; (if (eq opoint (point))
-;; nil
-;; (point))))
-
-;;(or (assq 'mts ange-ftp-dired-move-to-end-of-filename-alist)
-;; (setq ange-ftp-dired-move-to-end-of-filename-alist
-;; (cons '(mts . ange-ftp-dired-mts-move-to-end-of-filename)
-;; ange-ftp-dired-move-to-end-of-filename-alist)))
-
-;;;; ------------------------------------------------------------
-;;;; CMS support
-;;;; ------------------------------------------------------------
-
-;; Since CMS doesn't have any full file name syntax, we have to fudge
-;; things with cd's. We actually send too many cd's, but it's dangerous
-;; to try to remember the current minidisk, because if the connection
-;; is closed and needs to be reopened, we will find ourselves back in
-;; the default minidisk. This is fairly likely since CMS ftp servers
-;; usually close the connection after 5 minutes of inactivity.
-
-;; Have I got the filename character set right?
-
-(defun ange-ftp-fix-name-for-cms (name &optional reverse)
- (save-match-data
- (if reverse
- ;; Since we only convert output from a pwd in this direction,
- ;; we'll assume that it's a minidisk, and make it into a
- ;; directory file name. Note that the expand-dir-hashtable
- ;; stores directories without the trailing /. Is this
- ;; consistent?
- (concat "/" name)
- (if (string-match "^/\\([-A-Z0-9$*._]+\\)/\\([-A-Z0-9$._]+\\)?$"
- name)
- (let ((minidisk (substring name 1 (match-end 1))))
- (if (match-beginning 2)
- (let ((file (substring name (match-beginning 2)
- (match-end 2)))
- (cmd (concat "cd " minidisk))
-
- ;; Note that host and user are bound in the call
- ;; to ange-ftp-send-cmd
- (proc (ange-ftp-get-process ange-ftp-this-host
- ange-ftp-this-user)))
-
- ;; Must use ange-ftp-raw-send-cmd here to avoid
- ;; an infinite loop.
- (if (car (ange-ftp-raw-send-cmd proc cmd ange-ftp-this-msg))
- file
- ;; failed... try ONCE more.
- (setq proc (ange-ftp-get-process ange-ftp-this-host
- ange-ftp-this-user))
- (let ((result (ange-ftp-raw-send-cmd proc cmd
- ange-ftp-this-msg)))
- (if (car result)
- file
- ;; failed. give up.
- (ange-ftp-error ange-ftp-this-host ange-ftp-this-user
- (format "cd to minidisk %s failed: %s"
- minidisk (cdr result)))))))
- ;; return the minidisk
- minidisk))
- (error "Invalid CMS filename")))))
-
-(or (assq 'cms ange-ftp-fix-name-func-alist)
- (setq ange-ftp-fix-name-func-alist
- (cons '(cms . ange-ftp-fix-name-for-cms)
- ange-ftp-fix-name-func-alist)))
-
-(or (memq 'cms ange-ftp-dumb-host-types)
- (setq ange-ftp-dumb-host-types
- (cons 'cms ange-ftp-dumb-host-types)))
-
-;; Convert name from UNIX-ish to CMS ready for a DIRectory listing.
-(defun ange-ftp-fix-dir-name-for-cms (dir-name)
- (cond
- ((string-equal "/" dir-name)
- (error "Cannot get listing for fictitious \"/\" directory."))
- ((string-match "^/\\([-A-Z0-9$*._]+\\)/\\([-A-Z0-9$._]+\\)?$" dir-name)
- (let* ((minidisk (substring dir-name (match-beginning 1) (match-end 1)))
- ;; host and user are bound in the call to ange-ftp-send-cmd
- (proc (ange-ftp-get-process ange-ftp-this-host ange-ftp-this-user))
- (cmd (concat "cd " minidisk))
- (file (if (match-beginning 2)
- ;; it's a single file
- (substring dir-name (match-beginning 2)
- (match-end 2))
- ;; use the wild-card
- "*")))
- (if (car (ange-ftp-raw-send-cmd proc cmd))
- file
- ;; try again...
- (setq proc (ange-ftp-get-process ange-ftp-this-host
- ange-ftp-this-user))
- (let ((result (ange-ftp-raw-send-cmd proc cmd)))
- (if (car result)
- file
- ;; give up
- (ange-ftp-error ange-ftp-this-host ange-ftp-this-user
- (format "cd to minidisk %s failed: %s"
- minidisk (cdr result))))))))
- (t (error "Invalid CMS file name"))))
-
-(or (assq 'cms ange-ftp-fix-dir-name-func-alist)
- (setq ange-ftp-fix-dir-name-func-alist
- (cons '(cms . ange-ftp-fix-dir-name-for-cms)
- ange-ftp-fix-dir-name-func-alist)))
-
-(defvar ange-ftp-cms-host-regexp nil
- "Regular expression to match hosts running the CMS operating system.")
-
-;; Return non-nil if HOST is running CMS.
-(defun ange-ftp-cms-host (host)
- (and ange-ftp-cms-host-regexp
- (save-match-data
- (string-match ange-ftp-cms-host-regexp host))))
-
-(defun ange-ftp-add-cms-host (host)
- "Mark HOST as the name of a CMS host."
- (interactive
- (list (read-string "Host: "
- (let ((name (or (buffer-file-name) default-directory)))
- (and name (car (ange-ftp-ftp-name name)))))))
- (if (not (ange-ftp-cms-host host))
- (setq ange-ftp-cms-host-regexp
- (concat "^" (regexp-quote host) "$"
- (and ange-ftp-cms-host-regexp "\\|")
- ange-ftp-cms-host-regexp)
- ange-ftp-host-cache nil)))
-
-(defun ange-ftp-parse-cms-listing ()
- ;; Parse the current buffer which is assumed to be a CMS directory listing.
- ;; If we succeed in getting a listing, then we will assume that the minidisk
- ;; exists. file is bound by the call to ange-ftp-ls. This doesn't work
- ;; because ange-ftp doesn't know that the root hashtable has only part of
- ;; the info. It will assume that if a minidisk isn't in it, then it doesn't
- ;; exist. It would be nice if completion worked for minidisks, as we
- ;; discover them.
-; (let* ((dir-file (directory-file-name file))
-; (root (file-name-directory dir-file))
-; (minidisk (ange-ftp-get-file-part dir-file))
-; (root-tbl (ange-ftp-get-hash-entry root ange-ftp-files-hashtable)))
-; (if root-tbl
-; (ange-ftp-put-hash-entry minidisk t root-tbl)
-; (setq root-tbl (ange-ftp-make-hashtable))
-; (ange-ftp-put-hash-entry minidisk t root-tbl)
-; (ange-ftp-put-hash-entry "." t root-tbl)
-; (ange-ftp-set-files root root-tbl)))
- ;; Now do the usual parsing
- (let ((tbl (ange-ftp-make-hashtable)))
- (goto-char (point-min))
- (save-match-data
- (while
- (re-search-forward
- "^\\([-A-Z0-9$_]+\\) +\\([-A-Z0-9$_]+\\) +[VF] +[0-9]+ " nil t)
- (ange-ftp-put-hash-entry
- (concat (buffer-substring (match-beginning 1)
- (match-end 1))
- "."
- (buffer-substring (match-beginning 2)
- (match-end 2)))
- nil tbl)
- (forward-line 1))
- (ange-ftp-put-hash-entry "." t tbl))
- tbl))
-
-(or (assq 'cms ange-ftp-parse-list-func-alist)
- (setq ange-ftp-parse-list-func-alist
- (cons '(cms . ange-ftp-parse-cms-listing)
- ange-ftp-parse-list-func-alist)))
-
-;;;;; Tree dired support:
-
-;;(defconst ange-ftp-dired-cms-re-exe
-;; "^. [-A-Z0-9$_]+ +EXEC "
-;; "Regular expression to use to search for CMS executables.")
-
-;;(or (assq 'cms ange-ftp-dired-re-exe-alist)
-;; (setq ange-ftp-dired-re-exe-alist
-;; (cons (cons 'cms ange-ftp-dired-cms-re-exe)
-;; ange-ftp-dired-re-exe-alist)))
-
-
-;;(defun ange-ftp-dired-cms-insert-headerline (dir)
-;; ;; CMS has no total line, so we insert a blank line for
-;; ;; aesthetics.
-;; (insert "\n")
-;; (forward-char -1)
-;; (ange-ftp-real-dired-insert-headerline dir))
-
-;;(or (assq 'cms ange-ftp-dired-insert-headerline-alist)
-;; (setq ange-ftp-dired-insert-headerline-alist
-;; (cons '(cms . ange-ftp-dired-cms-insert-headerline)
-;; ange-ftp-dired-insert-headerline-alist)))
-
-;;(defun ange-ftp-dired-cms-move-to-filename (&optional raise-error eol)
-;; "In dired, move to the first char of filename on this line."
-;; ;; This is the CMS version.
-;; (or eol (setq eol (progn (end-of-line) (point))))
-;; (let (case-fold-search)
-;; (beginning-of-line)
-;; (if (re-search-forward " [-A-Z0-9$_]+ +[-A-Z0-9$_]+ +[VF] +[0-9]+ " eol t)
-;; (goto-char (1+ (match-beginning 0)))
-;; (if raise-error
-;; (error "No file on this line")
-;; nil))))
-
-;;(or (assq 'cms ange-ftp-dired-move-to-filename-alist)
-;; (setq ange-ftp-dired-move-to-filename-alist
-;; (cons '(cms . ange-ftp-dired-cms-move-to-filename)
-;; ange-ftp-dired-move-to-filename-alist)))
-
-;;(defun ange-ftp-dired-cms-move-to-end-of-filename (&optional no-error eol)
-;; ;; Assumes point is at beginning of filename.
-;; ;; So, it should be called only after (dired-move-to-filename t).
-;; ;; case-fold-search must be nil, at least for VMS.
-;; ;; On failure, signals an error or returns nil.
-;; ;; This is the CMS version.
-;; (let ((opoint (point))
-;; case-fold-search hidden)
-;; (or eol (setq eol (save-excursion (end-of-line) (point))))
-;; (setq hidden (and selective-display
-;; (save-excursion
-;; (search-forward "\r" eol t))))
-;; (if hidden
-;; (if no-error
-;; nil
-;; (error
-;; (substitute-command-keys
-;; "File line is hidden, type \\[dired-hide-subdir] to unhide")))
-;; (skip-chars-forward "-A-Z0-9$_" eol)
-;; (skip-chars-forward " " eol)
-;; (skip-chars-forward "-A-Z0-9$_" eol)
-;; (if (eq opoint (point))
-;; (if no-error
-;; nil
-;; (error "No file on this line"))
-;; (point)))))
-
-;;(or (assq 'cms ange-ftp-dired-move-to-end-of-filename-alist)
-;; (setq ange-ftp-dired-move-to-end-of-filename-alist
-;; (cons '(cms . ange-ftp-dired-cms-move-to-end-of-filename)
-;; ange-ftp-dired-move-to-end-of-filename-alist)))
-
-(defun ange-ftp-cms-make-compressed-filename (name &optional reverse)
- (if (string-match "-Z$" name)
- (list nil (substring name 0 -2))
- (list t (concat name "-Z"))))
-
-(or (assq 'cms ange-ftp-make-compressed-filename-alist)
- (setq ange-ftp-make-compressed-filename-alist
- (cons '(cms . ange-ftp-cms-make-compressed-filename)
- ange-ftp-make-compressed-filename-alist)))
-
-;;(defun ange-ftp-dired-cms-get-filename (&optional localp no-error-if-not-filep)
-;; (let ((name (ange-ftp-real-dired-get-filename localp no-error-if-not-filep)))
-;; (and name
-;; (if (string-match "^\\([^ ]+\\) +\\([^ ]+\\)$" name)
-;; (concat (substring name 0 (match-end 1))
-;; "."
-;; (substring name (match-beginning 2) (match-end 2)))
-;; name))))
-
-;;(or (assq 'cms ange-ftp-dired-get-filename-alist)
-;; (setq ange-ftp-dired-get-filename-alist
-;; (cons '(cms . ange-ftp-dired-cms-get-filename)
-;; ange-ftp-dired-get-filename-alist)))
-
-;;;; ------------------------------------------------------------
-;;;; Finally provide package.
-;;;; ------------------------------------------------------------
-
-(provide 'ange-ftp)
-
-;;; ange-ftp.el ends here
diff --git a/lisp/apropos.el b/lisp/apropos.el
deleted file mode 100644
index adbc13d0b7d..00000000000
--- a/lisp/apropos.el
+++ /dev/null
@@ -1,603 +0,0 @@
-;;; apropos.el --- apropos commands for users and programmers.
-
-;; Copyright (C) 1989, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Joe Wells <jbw@bigbird.bu.edu>
-;; Rewritten: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389
-;; Keywords: help
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The ideas for this package were derived from the C code in
-;; src/keymap.c and elsewhere. The functions in this file should
-;; always be byte-compiled for speed. Someone should rewrite this in
-;; C (as part of src/keymap.c) for speed.
-
-;; The idea for super-apropos is based on the original implementation
-;; by Lynn Slater <lrs@esl.com>.
-
-;; History:
-;; Fixed bug, current-local-map can return nil.
-;; Change, doesn't calculate key-bindings unless needed.
-;; Added super-apropos capability, changed print functions.
-;;; Made fast-apropos and super-apropos share code.
-;;; Sped up fast-apropos again.
-;; Added apropos-do-all option.
-;;; Added fast-command-apropos.
-;; Changed doc strings to comments for helping functions.
-;;; Made doc file buffer read-only, buried it.
-;; Only call substitute-command-keys if do-all set.
-
-;; Optionally use configurable faces to make the output more legible.
-;; Differentiate between command, function and macro.
-;; Apropos-command (ex command-apropos) does cmd and optionally user var.
-;; Apropos shows all 3 aspects of symbols (fn, var and plist)
-;; Apropos-documentation (ex super-apropos) now finds all it should.
-;; New apropos-value snoops through all values and optionally plists.
-;; Reading DOC file doesn't load nroff.
-;; Added hypertext following of documentation, mouse-2 on variable gives value
-;; from buffer in active window.
-
-;;; Code:
-
-;; I see a degradation of maybe 10-20% only.
-(defvar apropos-do-all nil
- "*Whether the apropos commands should do more.
-Slows them down more or less. Set this non-nil if you have a fast machine.")
-
-
-(defvar apropos-symbol-face (if window-system 'bold)
- "*Face for symbol name in apropos output or `nil'.
-This looks good, but slows down the commands several times.")
-
-(defvar apropos-keybinding-face (if window-system 'underline)
- "*Face for keybinding display in apropos output or `nil'.
-This looks good, but slows down the commands several times.")
-
-(defvar apropos-label-face (if window-system 'italic)
- "*Face for label (Command, Variable ...) in apropos output or `nil'.
-If this is `nil' no mouse highlighting occurs.
-This looks good, but slows down the commands several times.
-When this is a face name, as it is initially, it gets transformed to a
-text-property list for efficiency.")
-
-(defvar apropos-property-face (if window-system 'bold-italic)
- "*Face for property name in apropos output or `nil'.
-This looks good, but slows down the commands several times.")
-
-(defvar apropos-match-face (if window-system 'secondary-selection)
- "*Face for matching part in apropos-documentation/value output or `nil'.
-This looks good, but slows down the commands several times.")
-
-
-(defvar apropos-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-m" 'apropos-follow)
- (define-key map " " 'scroll-up)
- (define-key map "\177" 'scroll-down)
- (define-key map [mouse-2] 'apropos-mouse-follow)
- (define-key map [down-mouse-2] nil)
- map)
- "Keymap used in Apropos mode.")
-
-
-(defvar apropos-regexp nil
- "Regexp used in current apropos run.")
-
-(defvar apropos-files-scanned ()
- "List of elc files already scanned in current run of `apropos-documentation'.")
-
-(defvar apropos-accumulator ()
- "Alist of symbols already found in current apropos run.")
-
-(defvar apropos-item ()
- "Current item in or for apropos-accumulator.")
-
-(defun apropos-mode ()
- "Major mode for following hyperlinks in output of apropos commands.
-
-\\{apropos-mode-map}"
- (interactive)
- (kill-all-local-variables)
- (use-local-map apropos-mode-map)
- (setq major-mode 'apropos-mode
- mode-name "Apropos"))
-
-
-;; For auld lang syne:
-;;;###autoload
-(fset 'command-apropos 'apropos-command)
-;;;###autoload
-(defun apropos-command (apropos-regexp &optional do-all)
- "Shows commands (interactively callable functions) that match REGEXP.
-With optional prefix ARG or if `apropos-do-all' is non-nil, also show
-variables."
- (interactive (list (read-string (concat "Apropos command "
- (if (or current-prefix-arg
- apropos-do-all)
- "or variable ")
- "(regexp): "))
- current-prefix-arg))
- (let ((message
- (let ((standard-output (get-buffer-create "*Apropos*")))
- (print-help-return-message 'identity))))
- (or do-all (setq do-all apropos-do-all))
- (setq apropos-accumulator
- (apropos-internal apropos-regexp
- (if do-all
- (lambda (symbol) (or (commandp symbol)
- (user-variable-p symbol)))
- 'commandp)))
- (if (apropos-print
- t
- (lambda (p)
- (let (doc symbol)
- (while p
- (setcar p (list
- (setq symbol (car p))
- (if (commandp symbol)
- (if (setq doc (documentation symbol t))
- (substring doc 0 (string-match "\n" doc))
- "(not documented)"))
- (and do-all
- (user-variable-p symbol)
- (if (setq doc (documentation-property
- symbol 'variable-documentation t))
- (substring doc 0
- (string-match "\n" doc))))))
- (setq p (cdr p)))))
- nil)
- (and message (message message)))))
-
-
-;;;###autoload
-(defun apropos (apropos-regexp &optional do-all)
- "Show all bound symbols whose names match REGEXP.
-With optional prefix ARG or if `apropos-do-all' is non-nil, also show unbound
-symbols and key bindings, which is a little more time-consuming.
-Returns list of symbols and documentation found."
- (interactive "sApropos symbol (regexp): \nP")
- (setq apropos-accumulator
- (apropos-internal apropos-regexp
- (and (not do-all)
- (not apropos-do-all)
- (lambda (symbol)
- (or (fboundp symbol)
- (boundp symbol)
- (symbol-plist symbol))))))
- (apropos-print
- (or do-all apropos-do-all)
- (lambda (p)
- (let (symbol doc)
- (while p
- (setcar p (list
- (setq symbol (car p))
- (if (fboundp symbol)
- (if (setq doc (documentation symbol t))
- (substring doc 0 (string-match "\n" doc))
- "(not documented)"))
- (if (boundp symbol)
- (if (setq doc (documentation-property
- symbol 'variable-documentation t))
- (substring doc 0
- (string-match "\n" doc))
- "(not documented)"))
- (if (setq doc (symbol-plist symbol))
- (if (eq (/ (length doc) 2) 1)
- (format "1 property (%s)" (car doc))
- (concat (/ (length doc) 2) " properties")))))
- (setq p (cdr p)))))
- nil))
-
-
-;;;###autoload
-(defun apropos-value (apropos-regexp &optional do-all)
- "Show all symbols whose value's printed image matches REGEXP.
-With optional prefix ARG or if `apropos-do-all' is non-nil, also looks
-at the function and at the names and values of properties.
-Returns list of symbols and values found."
- (interactive "sApropos value (regexp): \nP")
- (or do-all (setq do-all apropos-do-all))
- (setq apropos-accumulator ())
- (let (f v p)
- (mapatoms
- (lambda (symbol)
- (setq f nil v nil p nil)
- (or (memq symbol '(apropos-regexp do-all apropos-accumulator
- symbol f v p))
- (setq v (apropos-value-internal 'boundp symbol 'symbol-value)))
- (if do-all
- (setq f (apropos-value-internal 'fboundp symbol 'symbol-function)
- p (apropos-format-plist symbol "\n " t)))
- (if (or f v p)
- (setq apropos-accumulator (cons (list symbol f v p)
- apropos-accumulator))))))
- (apropos-print nil nil t))
-
-
-;;;###autoload
-(defun apropos-documentation (apropos-regexp &optional do-all)
- "Show symbols whose documentation contain matches for REGEXP.
-With optional prefix ARG or if `apropos-do-all' is non-nil, also use
-documentation that is not stored in the documentation file and show key
-bindings.
-Returns list of symbols and documentation found."
- (interactive "sApropos documentation (regexp): \nP")
- (or do-all (setq do-all apropos-do-all))
- (setq apropos-accumulator () apropos-files-scanned ())
- (let ((standard-input (get-buffer-create " apropos-temp"))
- f v)
- (unwind-protect
- (save-excursion
- (set-buffer standard-input)
- (apropos-documentation-check-doc-file)
- (if do-all
- (mapatoms
- (lambda (symbol)
- (setq f (apropos-safe-documentation symbol)
- v (get symbol 'variable-documentation))
- (if (integerp v) (setq v))
- (setq f (apropos-documentation-internal f)
- v (apropos-documentation-internal v))
- (if (or f v)
- (if (setq apropos-item
- (cdr (assq symbol apropos-accumulator)))
- (progn
- (if f
- (setcar apropos-item f))
- (if v
- (setcar (cdr apropos-item) v)))
- (setq apropos-accumulator
- (cons (list symbol f v)
- apropos-accumulator)))))))
- (apropos-print nil nil t))
- (kill-buffer standard-input))))
-
-
-(defun apropos-value-internal (predicate symbol function)
- (if (funcall predicate symbol)
- (progn
- (setq symbol (prin1-to-string (funcall function symbol)))
- (if (string-match apropos-regexp symbol)
- (progn
- (if apropos-match-face
- (put-text-property (match-beginning 0) (match-end 0)
- 'face apropos-match-face
- symbol))
- symbol)))))
-
-(defun apropos-documentation-internal (doc)
- (if (consp doc)
- (apropos-documentation-check-elc-file (car doc))
- (and doc
- (string-match apropos-regexp doc)
- (progn
- (if apropos-match-face
- (put-text-property (match-beginning 0)
- (match-end 0)
- 'face apropos-match-face
- (setq doc (copy-sequence doc))))
- doc))))
-
-(defun apropos-format-plist (pl sep &optional compare)
- (setq pl (symbol-plist pl))
- (let (p p-out)
- (while pl
- (setq p (format "%s %S" (car pl) (nth 1 pl)))
- (if (or (not compare) (string-match apropos-regexp p))
- (if apropos-property-face
- (put-text-property 0 (length (symbol-name (car pl)))
- 'face apropos-property-face p))
- (setq p nil))
- (if p
- (progn
- (and compare apropos-match-face
- (put-text-property (match-beginning 0) (match-end 0)
- 'face apropos-match-face
- p))
- (setq p-out (concat p-out (if p-out sep) p))))
- (setq pl (nthcdr 2 pl)))
- p-out))
-
-
-;; Finds all documentation related to APROPOS-REGEXP in internal-doc-file-name.
-
-(defun apropos-documentation-check-doc-file ()
- (let (type symbol (sepa 2) sepb beg end)
- (insert ?\^_)
- (backward-char)
- (insert-file-contents (concat doc-directory internal-doc-file-name))
- (forward-char)
- (while (save-excursion
- (setq sepb (search-forward "\^_"))
- (not (eobp)))
- (beginning-of-line 2)
- (if (save-restriction
- (narrow-to-region (point) (1- sepb))
- (re-search-forward apropos-regexp nil t))
- (progn
- (setq beg (match-beginning 0)
- end (point))
- (goto-char (1+ sepa))
- (or (setq type (if (eq ?F (preceding-char))
- 1 ; function documentation
- 2) ; variable documentation
- symbol (read)
- beg (- beg (point) 1)
- end (- end (point) 1)
- doc (buffer-substring (1+ (point)) (1- sepb))
- apropos-item (assq symbol apropos-accumulator))
- (setq apropos-item (list symbol nil nil)
- apropos-accumulator (cons apropos-item
- apropos-accumulator)))
- (if apropos-match-face
- (put-text-property beg end 'face apropos-match-face doc))
- (setcar (nthcdr type apropos-item) doc)))
- (setq sepa (goto-char sepb)))))
-
-(defun apropos-documentation-check-elc-file (file)
- (if (member file apropos-files-scanned)
- nil
- (let (symbol doc beg end this-is-a-variable)
- (setq apropos-files-scanned (cons file apropos-files-scanned))
- (erase-buffer)
- (insert-file-contents file)
- (while (search-forward "\n#@" nil t)
- ;; Read the comment length, and advance over it.
- (setq end (read)
- beg (1+ (point))
- end (+ (point) end -1))
- (forward-char)
- (if (save-restriction
- ;; match ^ and $ relative to doc string
- (narrow-to-region beg end)
- (re-search-forward apropos-regexp nil t))
- (progn
- (goto-char (+ end 2))
- (setq doc (buffer-substring beg end)
- end (- (match-end 0) beg)
- beg (- (match-beginning 0) beg)
- this-is-a-variable (looking-at "(def\\(var\\|const\\) ")
- symbol (progn
- (skip-chars-forward "(a-z")
- (forward-char)
- (read))
- symbol (if (consp symbol)
- (nth 1 symbol)
- symbol))
- (if (if this-is-a-variable
- (get symbol 'variable-documentation)
- (and (fboundp symbol) (apropos-safe-documentation symbol)))
- (progn
- (or (setq apropos-item (assq symbol apropos-accumulator))
- (setq apropos-item (list symbol nil nil)
- apropos-accumulator (cons apropos-item
- apropos-accumulator)))
- (if apropos-match-face
- (put-text-property beg end 'face apropos-match-face
- doc))
- (setcar (nthcdr (if this-is-a-variable 2 1)
- apropos-item)
- doc)))))))))
-
-
-
-(defun apropos-safe-documentation (function)
- "Like documentation, except it avoids calling `get_doc_string'.
-Will return nil instead."
- (while (and function (symbolp function))
- (setq function (if (fboundp function)
- (symbol-function function))))
- (if (eq (car-safe function) 'macro)
- (setq function (cdr function)))
- (setq function (if (byte-code-function-p function)
- (if (> (length function) 4)
- (aref function 4))
- (if (eq (car-safe function) 'autoload)
- (nth 2 function)
- (if (eq (car-safe function) 'lambda)
- (if (stringp (nth 2 function))
- (nth 2 function)
- (if (stringp (nth 3 function))
- (nth 3 function)))))))
- (if (integerp function)
- nil
- function))
-
-
-
-(defun apropos-print (do-keys doc-fn spacing)
- "Output result of various apropos commands with `apropos-regexp'.
-APROPOS-ACCUMULATOR is a list. Optional DOC-FN is called for each element
-of apropos-accumulator and may modify it resulting in (symbol fn-doc
-var-doc [plist-doc]). Returns sorted list of symbols and documentation
-found."
- (if (null apropos-accumulator)
- (message "No apropos matches for `%s'" apropos-regexp)
- (if doc-fn
- (funcall doc-fn apropos-accumulator))
- (setq apropos-accumulator
- (sort apropos-accumulator (lambda (a b)
- (string-lessp (car a) (car b)))))
- (and apropos-label-face
- (symbolp apropos-label-face)
- (setq apropos-label-face `(face ,apropos-label-face
- mouse-face highlight)))
- (with-output-to-temp-buffer "*Apropos*"
- (let ((p apropos-accumulator)
- (old-buffer (current-buffer))
- symbol item point1 point2)
- (set-buffer standard-output)
- (apropos-mode)
- (if window-system
- (insert "If you move the mouse over text that changes color,\n"
- (substitute-command-keys
- "you can click \\[apropos-mouse-follow] to get more information.\n")))
- (insert (substitute-command-keys
- "In this buffer, type \\[apropos-follow] to get full documentation.\n\n"))
- (while (consp p)
- (or (not spacing) (bobp) (terpri))
- (setq apropos-item (car p)
- symbol (car apropos-item)
- p (cdr p)
- point1 (point))
- (princ symbol) ; print symbol name
- (setq point2 (point))
- ;; Calculate key-bindings if we want them.
- (and do-keys
- (commandp symbol)
- (indent-to 30 1)
- (if (let ((keys
- (save-excursion
- (set-buffer old-buffer)
- (where-is-internal symbol)))
- filtered)
- ;; Copy over the list of key sequences,
- ;; omitting any that contain a buffer or a frame.
- (while keys
- (let ((key (car keys))
- (i 0)
- loser)
- (while (< i (length key))
- (if (or (framep (aref key i))
- (bufferp (aref key i)))
- (setq loser t))
- (setq i (1+ i)))
- (or loser
- (setq filtered (cons key filtered))))
- (setq keys (cdr keys)))
- (setq item filtered))
- ;; Convert the remaining keys to a string and insert.
- (insert
- (mapconcat
- (lambda (key)
- (setq key (key-description key))
- (if apropos-keybinding-face
- (put-text-property 0 (length key)
- 'face apropos-keybinding-face
- key))
- key)
- item ", "))
- (insert "M-x")
- (put-text-property (- (point) 3) (point)
- 'face apropos-keybinding-face)
- (insert " " (symbol-name symbol) " ")
- (insert "RET")
- (put-text-property (- (point) 3) (point)
- 'face apropos-keybinding-face)))
- (terpri)
- ;; only now so we don't propagate text attributes all over
- (put-text-property point1 point2 'item
- (if (eval `(or ,@(cdr apropos-item)))
- (car apropos-item)
- apropos-item))
- (if apropos-symbol-face
- (put-text-property point1 point2 'face apropos-symbol-face))
- (apropos-print-doc 'describe-function 1
- (if (commandp symbol)
- "Command"
- (if (apropos-macrop symbol)
- "Macro"
- "Function"))
- do-keys)
- (apropos-print-doc 'describe-variable 2
- "Variable" do-keys)
- (apropos-print-doc 'apropos-describe-plist 3
- "Plist" nil)))))
- (prog1 apropos-accumulator
- (setq apropos-accumulator ()))) ; permit gc
-
-
-(defun apropos-macrop (symbol)
- "T if SYMBOL is a Lisp macro."
- (and (fboundp symbol)
- (consp (setq symbol
- (symbol-function symbol)))
- (or (eq (car symbol) 'macro)
- (if (eq (car symbol) 'autoload)
- (memq (nth 4 symbol)
- '(macro t))))))
-
-
-(defun apropos-print-doc (action i str do-keys)
- (if (stringp (setq i (nth i apropos-item)))
- (progn
- (insert " ")
- (put-text-property (- (point) 2) (1- (point))
- 'action action)
- (insert str ": ")
- (if apropos-label-face
- (add-text-properties (- (point) (length str) 2)
- (1- (point))
- apropos-label-face))
- (insert (if do-keys (substitute-command-keys i) i))
- (or (bolp) (terpri)))))
-
-
-(defun apropos-mouse-follow (event)
- (interactive "e")
- (let ((other (if (eq (current-buffer) (get-buffer "*Apropos*"))
- ()
- (current-buffer))))
- (save-excursion
- (set-buffer (window-buffer (posn-window (event-start event))))
- (goto-char (posn-point (event-start event)))
- (or (and (not (eobp)) (get-text-property (point) 'mouse-face))
- (and (not (bobp)) (get-text-property (1- (point)) 'mouse-face))
- (error "There is nothing to follow here"))
- (apropos-follow other))))
-
-
-(defun apropos-follow (&optional other)
- (interactive)
- (let* (;; Properties are always found at the beginning of the line.
- (bol (save-excursion (beginning-of-line) (point)))
- ;; If there is no `item' property here, look behind us.
- (item (get-text-property bol 'item))
- (item-at (if item nil (previous-single-property-change bol 'item)))
- ;; Likewise, if there is no `action' property here, look in front.
- (action (get-text-property bol 'action))
- (action-at (if action nil (next-single-property-change bol 'action))))
- (and (null item) item-at
- (setq item (get-text-property (1- item-at) 'item)))
- (and (null action) action-at
- (setq action (get-text-property action-at 'action)))
- (if (not (and item action))
- (error "There is nothing to follow here"))
- (if (consp item) (error "There is nothing to follow in `%s'" (car item)))
- (if other (set-buffer other))
- (funcall action item)))
-
-
-
-(defun apropos-describe-plist (symbol)
- "Display a pretty listing of SYMBOL's plist."
- (with-output-to-temp-buffer "*Help*"
- (set-buffer standard-output)
- (princ "Symbol ")
- (prin1 symbol)
- (princ "'s plist is\n (")
- (if apropos-symbol-face
- (put-text-property 8 (- (point) 14) 'face apropos-symbol-face))
- (insert (apropos-format-plist symbol "\n "))
- (princ ")")
- (print-help-return-message)))
-
-;;; apropos.el ends here
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
deleted file mode 100644
index 0a63debcd99..00000000000
--- a/lisp/arc-mode.el
+++ /dev/null
@@ -1,1482 +0,0 @@
-;;; arc-mode.el --- simple editing of archives
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Morten Welinder (terra@diku.dk)
-;; Keywords: archives msdog editing major-mode
-;; Favourite-brand-of-beer: None, I hate beer.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; NAMING: "arc" is short for "archive" and does not refer specifically
-;; to files whose name end in ".arc"
-;;
-;; This code does not decode any files internally, although it does
-;; understand the directory level of the archives. For this reason,
-;; you should expect this code to need more fiddling than tar-mode.el
-;; (although it at present has fewer bugs :-) In particular, I have
-;; not tested this under Ms-Dog myself.
-;; -------------------------------------
-;; INTERACTION: arc-mode.el should play together with
-;;
-;; * ange-ftp.el: Remote archives (i.e., ones that ange-ftp has brought
-;; to you) are handled by doing all updates on a local
-;; copy. When you make changes to a remote file the
-;; changes will first take effect when the archive buffer
-;; is saved. You will be warned about this.
-;;
-;; * dos-fns.el: (Part of Emacs 19). You get automatic ^M^J <--> ^J
-;; conversion.
-;;
-;; arc-mode.el does not work well with crypt++.el; for the archives as
-;; such this could be fixed (but wouldn't be useful) by declaring such
-;; archives to be "remote". For the members this is a general Emacs
-;; problem that 19.29's file formats may fix.
-;; -------------------------------------
-;; ARCHIVE TYPES: Currently only the archives below are handled, but the
-;; structure for handling just about anything is in place.
-;;
-;; Arc Lzh Zip Zoo
-;; --------------------------------
-;; View listing Intern Intern Intern Intern
-;; Extract member Y Y Y Y
-;; Save changed member Y Y Y Y
-;; Add new member N N N N
-;; Delete member Y Y Y Y
-;; Rename member Y Y N N
-;; Chmod - Y Y -
-;; Chown - Y - -
-;; Chgrp - Y - -
-;;
-;; Special thanks to Bill Brodie <wbrodie@panix.com> for very useful tips
-;; on the first released version of this package.
-;;
-;; This code is partly based on tar-mode.el from Emacs.
-;; -------------------------------------
-;; ARCHIVE STRUCTURES:
-;; (This is mostly for myself.)
-;;
-;; ARC A series of (header,file). No interactions among members.
-;;
-;; LZH A series of (header,file). Headers are checksummed. No
-;; interaction among members.
-;;
-;; ZIP A series of (lheader,fil) followed by a "central directory"
-;; which is a series of (cheader) followed by an end-of-
-;; central-dir record possibly followed by junk. The e-o-c-d
-;; links to c-d. cheaders link to lheaders which are basically
-;; cut-down versions of the cheaders.
-;;
-;; ZOO An archive header followed by a series of (header,file).
-;; Each member header points to the next. The archive is
-;; terminated by a bogus header with a zero next link.
-;; -------------------------------------
-;; HOOKS: `foo' means one the the supported archive types.
-;;
-;; archive-mode-hook
-;; archive-foo-mode-hook
-;; archive-extract-hooks
-
-;;; Code:
-
-;; -------------------------------------------------------------------------
-;; Section: Configuration.
-
-(defvar archive-dos-members t
- "*If non-nil then recognize member files using ^M^J as line terminator.")
-
-(defvar archive-tmpdir
- (expand-file-name
- (make-temp-name (if (eq system-type 'ms-dos) "ar" "archive.tmp"))
- (or (getenv "TMPDIR") (getenv "TMP") "/tmp"))
- "*Directory for temporary files made by arc-mode.el")
-
-(defvar archive-remote-regexp "^/[^/:]*[^/:.]:"
- "*Regexp recognizing archive files names that are not local.
-A non-local file is one whose file name is not proper outside Emacs.
-A local copy of the archive will be used when updating.")
-
-(defvar archive-extract-hooks nil
- "*Hooks to run when an archive member has been extracted.")
-;; ------------------------------
-;; Arc archive configuration
-
-;; We always go via a local file since there seems to be no reliable way
-;; to extract to stdout without junk getting added.
-(defvar archive-arc-extract
- '("arc" "x")
- "*Program and its options to run in order to extract an arc file member.
-Extraction should happen to the current directory. Archive and member
-name will be added.")
-
-(defvar archive-arc-expunge
- '("arc" "d")
- "*Program and its options to run in order to delete arc file members.
-Archive and member names will be added.")
-
-(defvar archive-arc-write-file-member
- '("arc" "u")
- "*Program and its options to run in order to update an arc file member.
-Archive and member name will be added.")
-;; ------------------------------
-;; Lzh archive configuration
-
-(defvar archive-lzh-extract
- '("lha" "pq")
- "*Program and its options to run in order to extract an lzh file member.
-Extraction should happen to standard output. Archive and member name will
-be added.")
-
-(defvar archive-lzh-expunge
- '("lha" "d")
- "*Program and its options to run in order to delete lzh file members.
-Archive and member names will be added.")
-
-(defvar archive-lzh-write-file-member
- '("lha" "a")
- "*Program and its options to run in order to update an lzh file member.
-Archive and member name will be added.")
-;; ------------------------------
-;; Zip archive configuration
-
-(defvar archive-zip-use-pkzip (memq system-type '(ms-dos windows-nt))
- "*If non-nil then pkzip option are used instead of zip options.
-Only set to true for msdog systems!")
-
-(defvar archive-zip-extract
- (if archive-zip-use-pkzip '("pkunzip" "-e") '("unzip" "-qq" "-c"))
- "*Program and its options to run in order to extract a zip file member.
-Extraction should happen to standard output. Archive and member name will
-be added. If `archive-zip-use-pkzip' is non-nil then this program is
-expected to extract to a file junking the directory part of the name.")
-
-;; For several reasons the latter behaviour is not desirable in general.
-;; (1) It uses more disk space. (2) Error checking is worse or non-
-;; existent. (3) It tends to do funny things with other systems' file
-;; names.
-
-(defvar archive-zip-expunge
- (if archive-zip-use-pkzip '("pkzip" "-d") '("zip" "-d" "-q"))
- "*Program and its options to run in order to delete zip file members.
-Archive and member names will be added.")
-
-(defvar archive-zip-update
- (if archive-zip-use-pkzip '("pkzip" "-u") '("zip" "-q"))
- "*Program and its options to run in order to update a zip file member.
-Options should ensure that specified directory will be put into the zip
-file. Archive and member name will be added.")
-
-(defvar archive-zip-update-case
- (if archive-zip-use-pkzip archive-zip-update '("zip" "-q" "-k"))
- "*Program and its options to run in order to update a case fiddled zip member.
-Options should ensure that specified directory will be put into the zip file.
-Archive and member name will be added.")
-
-(defvar archive-zip-case-fiddle t
- "*If non-nil then zip file members are case fiddled.
-Case fiddling will only happen for members created by a system that
-uses caseless file names.")
-;; ------------------------------
-;; Zoo archive configuration
-
-(defvar archive-zoo-extract
- '("zoo" "xpq")
- "*Program and its options to run in order to extract a zoo file member.
-Extraction should happen to standard output. Archive and member name will
-be added.")
-
-(defvar archive-zoo-expunge
- '("zoo" "DqPP")
- "*Program and its options to run in order to delete zoo file members.
-Archive and member names will be added.")
-
-(defvar archive-zoo-write-file-member
- '("zoo" "a")
- "*Program and its options to run in order to update a zoo file member.
-Archive and member name will be added.")
-;; -------------------------------------------------------------------------
-;; Section: Variables
-
-(defvar archive-subtype nil "*Symbol describing archive type.")
-(defvar archive-file-list-start nil "*Position of first contents line.")
-(defvar archive-file-list-end nil "*Position just after last contents line.")
-(defvar archive-proper-file-start nil "*Position of real archive's start.")
-(defvar archive-read-only nil "*Non-nil if the archive is read-only on disk.")
-(defvar archive-remote nil "*Non-nil if the archive is outside file system.")
-(defvar archive-local-name nil "*Name of local copy of remote archive.")
-(defvar archive-mode-map nil "*Local keymap for archive mode listings.")
-(defvar archive-file-name-indent nil "*Column where file names start.")
-
-(defvar archive-alternate-display nil
- "*Non-nil when alternate information is shown.")
-(make-variable-buffer-local 'archive-alternate-display)
-(put 'archive-alternate-display 'permanent-local t)
-
-(defvar archive-superior-buffer nil "*In archive members, points to archive.")
-(put 'archive-superior-buffer 'permanent-local t)
-
-(defvar archive-subfile-mode nil "*Non-nil in archive member buffers.")
-(make-variable-buffer-local 'archive-subfile-mode)
-(put 'archive-subfile-mode 'permanent-local t)
-
-(defvar archive-subfile-dos nil
- "Negation of `buffer-file-type', which see.")
-(make-variable-buffer-local 'archive-subfile-dos)
-(put 'archive-subfile-dos 'permanent-local t)
-
-(defvar archive-files nil
- "Vector of file descriptors.
-Each descriptor is a vector of the form
- [EXT-FILE-NAME INT-FILE-NAME CASE-FIDDLED MODE ...]")
-(make-variable-buffer-local 'archive-files)
-
-(defvar archive-lemacs
- (string-match "\\(Lucid\\|Xemacs\\)" emacs-version)
- "*Non-nil when running under under Lucid Emacs or Xemacs.")
-;; -------------------------------------------------------------------------
-;; Section: Support functions.
-
-(defsubst archive-name (suffix)
- (intern (concat "archive-" (symbol-name archive-subtype) "-" suffix)))
-
-(defun archive-l-e (str &optional len)
- "Convert little endian string/vector to integer.
-Alternatively, first argument may be a buffer position in the current buffer
-in which case a second argument, length, should be supplied."
- (if (stringp str)
- (setq len (length str))
- (setq str (buffer-substring str (+ str len))))
- (let ((result 0)
- (i 0))
- (while (< i len)
- (setq i (1+ i)
- result (+ (ash result 8) (aref str (- len i)))))
- result))
-
-(defun archive-int-to-mode (mode)
- "Turn an integer like 0700 (i.e., 448) into a mode string like -rwx------"
- (let ((str (make-string 10 ?-)))
- (or (zerop (logand 16384 mode)) (aset str 0 ?d))
- (or (zerop (logand 8192 mode)) (aset str 0 ?c)) ; completeness
- (or (zerop (logand 256 mode)) (aset str 1 ?r))
- (or (zerop (logand 128 mode)) (aset str 2 ?w))
- (or (zerop (logand 64 mode)) (aset str 3 ?x))
- (or (zerop (logand 32 mode)) (aset str 4 ?r))
- (or (zerop (logand 16 mode)) (aset str 5 ?w))
- (or (zerop (logand 8 mode)) (aset str 6 ?x))
- (or (zerop (logand 4 mode)) (aset str 7 ?r))
- (or (zerop (logand 2 mode)) (aset str 8 ?w))
- (or (zerop (logand 1 mode)) (aset str 9 ?x))
- (or (zerop (logand 1024 mode)) (aset str 3 (if (zerop (logand 64 mode))
- ?S ?s)))
- (or (zerop (logand 2048 mode)) (aset str 6 (if (zerop (logand 8 mode))
- ?S ?s)))
- str))
-
-(defun archive-calc-mode (oldmode newmode &optional error)
- "From the integer OLDMODE and the string NEWMODE calculate a new file mode.
-NEWMODE may be an octal number including a leading zero in which case it
-will become the new mode.\n
-NEWMODE may also be a relative specification like \"og-rwx\" in which case
-OLDMODE will be modified accordingly just like chmod(2) would have done.\n
-If optional third argument ERROR is non-nil an error will be signaled if
-the mode is invalid. If ERROR is nil then nil will be returned."
- (cond ((string-match "^0[0-7]*$" newmode)
- (let ((result 0)
- (len (length newmode))
- (i 1))
- (while (< i len)
- (setq result (+ (lsh result 3) (aref newmode i) (- ?0))
- i (1+ i)))
- (logior (logand oldmode 65024) result)))
- ((string-match "^\\([agou]+\\)\\([---+=]\\)\\([rwxst]+\\)$" newmode)
- (let ((who 0)
- (result oldmode)
- (op (aref newmode (match-beginning 2)))
- (bits 0)
- (i (match-beginning 3)))
- (while (< i (match-end 3))
- (let ((rwx (aref newmode i)))
- (setq bits (logior bits (cond ((= rwx ?r) 292)
- ((= rwx ?w) 146)
- ((= rwx ?x) 73)
- ((= rwx ?s) 3072)
- ((= rwx ?t) 512)))
- i (1+ i))))
- (while (< who (match-end 1))
- (let* ((whoc (aref newmode who))
- (whomask (cond ((= whoc ?a) 4095)
- ((= whoc ?u) 1472)
- ((= whoc ?g) 2104)
- ((= whoc ?o) 7))))
- (if (= op ?=)
- (setq result (logand result (lognot whomask))))
- (if (= op ?-)
- (setq result (logand result (lognot (logand whomask bits))))
- (setq result (logior result (logand whomask bits)))))
- (setq who (1+ who)))
- result))
- (t
- (if error
- (error "Invalid mode specification: %s" newmode)))))
-
-(defun archive-dosdate (date)
- "Stringify dos packed DATE record."
- (let ((year (+ 1980 (logand (ash date -9) 127)))
- (month (logand (ash date -5) 15))
- (day (logand date 31)))
- (if (or (> month 12) (< month 1))
- ""
- (format "%2d-%s-%d"
- day
- (aref ["Jan" "Feb" "Mar" "Apr" "May" "Jun"
- "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"] (1- month))
- year))))
-
-(defun archive-dostime (time)
- "Stringify dos packed TIME record."
- (let ((hour (logand (ash time -11) 31))
- (minute (logand (ash time -5) 53))
- (second (* 2 (logand time 31)))) ; 2 seconds resolution
- (format "%02d:%02d:%02d" hour minute second)))
-
-;;(defun archive-unixdate (low high)
-;; "Stringify unix (LOW HIGH) date."
-;; (let ((str (current-time-string (cons high low))))
-;; (format "%s-%s-%s"
-;; (substring str 8 9)
-;; (substring str 4 7)
-;; (substring str 20 24))))
-
-;;(defun archive-unixtime (low high)
-;; "Stringify unix (LOW HIGH) time."
-;; (let ((str (current-time-string (cons high low))))
-;; (substring str 11 19)))
-
-(defun archive-get-lineno ()
- (if (>= (point) archive-file-list-start)
- (count-lines archive-file-list-start
- (save-excursion (beginning-of-line) (point)))
- 0))
-
-(defun archive-get-descr (&optional noerror)
- "Return the descriptor vector for file at point.
-Does not signal an error if optional second argument NOERROR is non-nil."
- (let ((no (archive-get-lineno)))
- (if (and (>= (point) archive-file-list-start)
- (< no (length archive-files)))
- (let ((item (aref archive-files no)))
- (if (vectorp item)
- item
- (if (not noerror)
- (error "Entry is not a regular member of the archive"))))
- (if (not noerror)
- (error "Line does not describe a member of the archive")))))
-;; -------------------------------------------------------------------------
-;; Section: the mode definition
-
-;;;###autoload
-(defun archive-mode (&optional force)
- "Major mode for viewing an archive file in a dired-like way.
-You can move around using the usual cursor motion commands.
-Letters no longer insert themselves.
-Type `e' to pull a file out of the archive and into its own buffer;
-or click mouse-2 on the file's line in the archive mode buffer.
-
-If you edit a sub-file of this archive (as with the `e' command) and
-save it, the contents of that buffer will be saved back into the
-archive.
-
-\\{archive-mode-map}"
- ;; This is not interactive because you shouldn't be turning this
- ;; mode on and off. You can corrupt things that way.
- (if (zerop (buffer-size))
- ;; At present we cannot create archives from scratch
- (funcall default-major-mode)
- (if (and (not force) archive-files) nil
- (let* ((type (archive-find-type))
- (typename (copy-sequence (symbol-name type))))
- (aset typename 0 (upcase (aref typename 0)))
- (kill-all-local-variables)
- (make-local-variable 'archive-subtype)
- (setq archive-subtype type)
-
- ;; Buffer contains treated image of file before the file contents
- (make-local-variable 'revert-buffer-function)
- (setq revert-buffer-function 'archive-mode-revert)
- (auto-save-mode 0)
- (make-local-variable 'local-write-file-hooks)
- (add-hook 'local-write-file-hooks 'archive-write-file)
-
- ;; Real file contents is binary
- (make-local-variable 'require-final-newline)
- (setq require-final-newline nil)
- (make-local-variable 'enable-local-variables)
- (setq enable-local-variables nil)
- (if (boundp 'default-buffer-file-type)
- (setq buffer-file-type t))
-
- (make-local-variable 'archive-read-only)
- (setq archive-read-only (not (file-writable-p (buffer-file-name))))
-
- ;; Should we use a local copy when accessing from outside Emacs?
- (make-local-variable 'archive-local-name)
- (make-local-variable 'archive-remote)
- (setq archive-remote (string-match archive-remote-regexp
- (buffer-file-name)))
-
- (setq major-mode 'archive-mode)
- (setq mode-name (concat typename "-Archive"))
- ;; Run archive-foo-mode-hook and archive-mode-hook
- (run-hooks (archive-name "mode-hook") 'archive-mode-hook)
- (use-local-map archive-mode-map))
-
- (make-local-variable 'archive-proper-file-start)
- (make-local-variable 'archive-file-list-start)
- (make-local-variable 'archive-file-list-end)
- (make-local-variable 'archive-file-name-indent)
- (archive-summarize)
- (setq buffer-read-only t))))
-
-;; Archive mode is suitable only for specially formatted data.
-(put 'archive-mode 'mode-class 'special)
-;; -------------------------------------------------------------------------
-;; Section: Key maps
-
-(if archive-mode-map nil
- (setq archive-mode-map (make-keymap))
- (suppress-keymap archive-mode-map)
- (define-key archive-mode-map " " 'archive-next-line)
- (define-key archive-mode-map "a" 'archive-alternate-display)
- ;;(define-key archive-mode-map "c" 'archive-copy)
- (define-key archive-mode-map "d" 'archive-flag-deleted)
- (define-key archive-mode-map "\C-d" 'archive-flag-deleted)
- (define-key archive-mode-map "e" 'archive-extract)
- (define-key archive-mode-map "f" 'archive-extract)
- (define-key archive-mode-map "\C-m" 'archive-extract)
- (define-key archive-mode-map "g" 'revert-buffer)
- (define-key archive-mode-map "h" 'describe-mode)
- (define-key archive-mode-map "m" 'archive-mark)
- (define-key archive-mode-map "n" 'archive-next-line)
- (define-key archive-mode-map "\C-n" 'archive-next-line)
- (define-key archive-mode-map [down] 'archive-next-line)
- (define-key archive-mode-map "o" 'archive-extract-other-window)
- (define-key archive-mode-map "p" 'archive-previous-line)
- (define-key archive-mode-map "\C-p" 'archive-previous-line)
- (define-key archive-mode-map [up] 'archive-previous-line)
- (define-key archive-mode-map "r" 'archive-rename-entry)
- (define-key archive-mode-map "u" 'archive-unflag)
- (define-key archive-mode-map "\M-\C-?" 'archive-unmark-all-files)
- (define-key archive-mode-map "v" 'archive-view)
- (define-key archive-mode-map "x" 'archive-expunge)
- (define-key archive-mode-map "\177" 'archive-unflag-backwards)
- (define-key archive-mode-map "E" 'archive-extract-other-window)
- (define-key archive-mode-map "M" 'archive-chmod-entry)
- (define-key archive-mode-map "G" 'archive-chgrp-entry)
- (define-key archive-mode-map "O" 'archive-chown-entry)
-
- (if archive-lemacs
- (progn
- ;; Not a nice "solution" but it'll have to do
- (define-key archive-mode-map "\C-xu" 'archive-undo)
- (define-key archive-mode-map "\C-_" 'archive-undo))
- (substitute-key-definition 'undo 'archive-undo
- archive-mode-map global-map))
-
- (define-key archive-mode-map
- (if archive-lemacs 'button2 [mouse-2]) 'archive-mouse-extract)
-
- (if archive-lemacs
- () ; out of luck
- ;; Get rid of the Edit menu bar item to save space.
- (define-key archive-mode-map [menu-bar edit] 'undefined)
-
- (define-key archive-mode-map [menu-bar immediate]
- (cons "Immediate" (make-sparse-keymap "Immediate")))
- (define-key archive-mode-map [menu-bar immediate alternate]
- '("Alternate Display" . archive-alternate-display))
- (put 'archive-alternate-display 'menu-enable
- '(boundp (archive-name "alternate-display")))
- (define-key archive-mode-map [menu-bar immediate view]
- '("View This File" . archive-view))
- (define-key archive-mode-map [menu-bar immediate display]
- '("Display in Other Window" . archive-display-other-window))
- (define-key archive-mode-map [menu-bar immediate find-file-other-window]
- '("Find in Other Window" . archive-extract-other-window))
- (define-key archive-mode-map [menu-bar immediate find-file]
- '("Find This File" . archive-extract))
-
- (define-key archive-mode-map [menu-bar mark]
- (cons "Mark" (make-sparse-keymap "Mark")))
- (define-key archive-mode-map [menu-bar mark unmark-all]
- '("Unmark All" . archive-unmark-all-files))
- (define-key archive-mode-map [menu-bar mark deletion]
- '("Flag" . archive-flag-deleted))
- (define-key archive-mode-map [menu-bar mark unmark]
- '("Unflag" . archive-unflag))
- (define-key archive-mode-map [menu-bar mark mark]
- '("Mark" . archive-mark))
-
- (define-key archive-mode-map [menu-bar operate]
- (cons "Operate" (make-sparse-keymap "Operate")))
- (define-key archive-mode-map [menu-bar operate chown]
- '("Change Owner..." . archive-chown-entry))
- (put 'archive-chown-entry 'menu-enable
- '(fboundp (archive-name "chown-entry")))
- (define-key archive-mode-map [menu-bar operate chgrp]
- '("Change Group..." . archive-chgrp-entry))
- (put 'archive-chgrp-entry 'menu-enable
- '(fboundp (archive-name "chgrp-entry")))
- (define-key archive-mode-map [menu-bar operate chmod]
- '("Change Mode..." . archive-chmod-entry))
- (put 'archive-chmod-entry 'menu-enable
- '(fboundp (archive-name "chmod-entry")))
- (define-key archive-mode-map [menu-bar operate rename]
- '("Rename to..." . archive-rename-entry))
- (put 'archive-rename-entry 'menu-enable
- '(fboundp (archive-name "rename-entry")))
- ;;(define-key archive-mode-map [menu-bar operate copy]
- ;; '("Copy to..." . archive-copy))
- (define-key archive-mode-map [menu-bar operate expunge]
- '("Expunge Marked Files" . archive-expunge))
- ))
-
-(let* ((item1 '(archive-subfile-mode " Archive"))
- (item2 '(archive-subfile-dos " Dos"))
- (items (if (memq system-type '(ms-dos windows-nt))
- (list item1) ; msdog has its own indicator
- (list item1 item2))))
- (or (member item1 minor-mode-alist)
- (setq minor-mode-alist (append items minor-mode-alist))))
-;; -------------------------------------------------------------------------
-(defun archive-find-type ()
- (widen)
- (goto-char (point-min))
- ;; The funny [] here make it unlikely that the .elc file will be treated
- ;; as an archive by other software.
- (let (case-fold-search)
- (cond ((looking-at "[P]K\003\004") 'zip)
- ((looking-at "..-l[hz][0-9]-") 'lzh)
- ((looking-at "....................[\334]\247\304\375") 'zoo)
- ((and (looking-at "\C-z") ; signature too simple, IMHO
- (string-match "\\.[aA][rR][cC]$"
- (or buffer-file-name (buffer-name))))
- 'arc)
- (t (error "Buffer format not recognized.")))))
-;; -------------------------------------------------------------------------
-(defun archive-summarize ()
- "Parse the contents of the archive file in the current buffer.
-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)."
- (widen)
- (let (buffer-read-only)
- (message "Parsing archive file...")
- (buffer-disable-undo (current-buffer))
- (setq archive-files (funcall (archive-name "summarize")))
- (message "Parsing archive file...done.")
- (setq archive-proper-file-start (point-marker))
- (narrow-to-region (point-min) (point))
- (set-buffer-modified-p nil)
- (buffer-enable-undo))
- (goto-char archive-file-list-start)
- (archive-next-line 0))
-
-(defun archive-resummarize ()
- "Recreate the contents listing of an archive."
- (let ((modified (buffer-modified-p))
- (no (archive-get-lineno))
- buffer-read-only)
- (widen)
- (delete-region (point-min) archive-proper-file-start)
- (archive-summarize)
- (set-buffer-modified-p modified)
- (goto-char archive-file-list-start)
- (archive-next-line no)))
-
-(defun archive-summarize-files (files)
- "Insert a description of a list of files annotated with proper mouse face."
- (setq archive-file-list-start (point-marker))
- (setq archive-file-name-indent (if files (aref (car files) 1) 0))
- ;; We don't want to do an insert for each element since that takes too
- ;; long when the archive -- which has to be moved in memory -- is large.
- (insert
- (apply
- (function concat)
- (mapcar
- (function
- (lambda (fil)
- ;; Using `concat' here copies the text also, so we can add
- ;; properties without problems.
- (let ((text (concat (aref fil 0) "\n")))
- (if archive-lemacs
- () ; out of luck
- (put-text-property (aref fil 1) (aref fil 2)
- 'mouse-face 'highlight
- text))
- text)))
- files)))
- (setq archive-file-list-end (point-marker)))
-
-(defun archive-alternate-display ()
- "Toggle alternative display.
-To avoid very long lines some archive mode don't show all information.
-This function changes the set of information shown for each files."
- (interactive)
- (setq archive-alternate-display (not archive-alternate-display))
- (archive-resummarize))
-;; -------------------------------------------------------------------------
-;; Section: Local archive copy handling
-
-(defun archive-maybe-copy (archive)
- (if archive-remote
- (let ((start (point-max)))
- (setq archive-local-name (expand-file-name
- (file-name-nondirectory archive)
- archive-tmpdir))
- (make-directory archive-tmpdir t)
- (save-restriction
- (widen)
- (write-region start (point-max) archive-local-name nil 'nomessage))
- archive-local-name)
- (if (buffer-modified-p) (save-buffer))
- archive))
-
-(defun archive-maybe-update (unchanged)
- (if archive-remote
- (let ((name archive-local-name)
- (modified (buffer-modified-p))
- buffer-read-only)
- (if unchanged nil
- (erase-buffer)
- (insert-file-contents name)
- (archive-mode t))
- (archive-delete-local name)
- (if (not unchanged)
- (message "Archive file must be saved for changes to take effect"))
- (set-buffer-modified-p (or modified (not unchanged))))))
-
-(defun archive-delete-local (name)
- "Delete file NAME and its parents up to and including `archive-tmpdir'."
- (let ((again t)
- (top (directory-file-name (file-name-as-directory archive-tmpdir))))
- (condition-case nil
- (delete-file name)
- (error nil))
- (while again
- (setq name (directory-file-name (file-name-directory name)))
- (condition-case nil
- (delete-directory name)
- (error nil))
- (if (string= name top) (setq again nil)))))
-;; -------------------------------------------------------------------------
-;; Section: Member extraction
-
-(defun archive-mouse-extract (event)
- "Extract a file whose name you click on."
- (interactive "e")
- (mouse-set-point event)
- (switch-to-buffer
- (save-excursion
- (archive-extract)
- (current-buffer))))
-
-(defun archive-extract (&optional other-window-p)
- "In archive mode, extract this entry of the archive into its own buffer."
- (interactive)
- (let* ((view-p (eq other-window-p 'view))
- (descr (archive-get-descr))
- (ename (aref descr 0))
- (iname (aref descr 1))
- (archive-buffer (current-buffer))
- (arcdir default-directory)
- (archive (buffer-file-name))
- (arcname (file-name-nondirectory archive))
- (bufname (concat (file-name-nondirectory iname) " (" arcname ")"))
- (extractor (archive-name "extract"))
- (read-only-p (or archive-read-only view-p))
- (buffer (get-buffer bufname))
- (just-created nil))
- (if buffer
- nil
- (setq archive (archive-maybe-copy archive))
- (setq buffer (get-buffer-create bufname))
- (setq just-created t)
- (save-excursion
- (set-buffer buffer)
- (setq buffer-file-name
- (expand-file-name (concat arcname ":" iname)))
- (setq buffer-file-truename
- (abbreviate-file-name buffer-file-name))
- ;; Set the default-directory to the dir of the superior buffer.
- (setq default-directory arcdir)
- (make-local-variable 'archive-superior-buffer)
- (setq archive-superior-buffer archive-buffer)
- (make-local-variable 'local-write-file-hooks)
- (add-hook 'local-write-file-hooks 'archive-write-file-member)
- (setq archive-subfile-mode descr)
- (setq archive-subfile-dos nil)
- (if (boundp 'default-buffer-file-type)
- (setq buffer-file-type t))
- (if (fboundp extractor)
- (funcall extractor archive ename)
- (archive-*-extract archive ename (symbol-value extractor)))
- (if archive-dos-members (archive-check-dos))
- (goto-char (point-min))
- (rename-buffer bufname)
- (setq buffer-read-only read-only-p)
- (setq buffer-undo-list nil)
- (set-buffer-modified-p nil)
- (setq buffer-saved-size (buffer-size))
- (normal-mode)
- ;; Just in case an archive occurs inside another archive.
- (if (eq major-mode 'archive-mode)
- (setq archive-remote t))
- (run-hooks 'archive-extract-hooks))
- (archive-maybe-update t))
- (if view-p
- (progn
- (view-buffer buffer)
- (and just-created (setq view-exit-action 'kill-buffer)))
- (if (eq other-window-p 'display)
- (display-buffer buffer)
- (if other-window-p
- (switch-to-buffer-other-window buffer)
- (switch-to-buffer buffer))))))
-
-(defun archive-*-extract (archive name command)
- (let* ((default-directory (file-name-as-directory archive-tmpdir))
- (tmpfile (expand-file-name (file-name-nondirectory name)
- default-directory)))
- (make-directory (directory-file-name default-directory) t)
- (apply 'call-process
- (car command)
- nil
- nil
- nil
- (append (cdr command) (list archive name)))
- (insert-file-contents tmpfile)
- (archive-delete-local tmpfile)))
-
-(defun archive-extract-by-stdout (archive name command)
- (let ((binary-process-output t)) ; for Ms-Dos
- (apply 'call-process
- (car command)
- nil
- t
- nil
- (append (cdr command) (list archive name)))))
-
-(defun archive-extract-other-window ()
- "In archive mode, find this member in another window."
- (interactive)
- (archive-extract t))
-
-(defun archive-display-other-window ()
- "In archive mode, display this member in another window."
- (interactive)
- (archive-extract 'display))
-
-(defun archive-view ()
- "In archive mode, view the member on this line."
- (interactive)
- (archive-extract 'view))
-
-(defun archive-add-new-member (arcbuf name)
- "Add current buffer to the archive in ARCBUF naming it NAME."
- (interactive
- (list (get-buffer
- (read-buffer "Buffer containing archive: "
- ;; Find first archive buffer and suggest that
- (let ((bufs (buffer-list)))
- (while (and bufs (not (eq (save-excursion
- (set-buffer (car bufs))
- major-mode)
- 'archive-mode)))
- (setq bufs (cdr bufs)))
- (if bufs
- (car bufs)
- (error "There are no archive buffers")))
- t))
- (read-string "File name in archive: "
- (if buffer-file-name
- (file-name-nondirectory buffer-file-name)
- ""))))
- (save-excursion
- (set-buffer arcbuf)
- (or (eq major-mode 'archive-mode)
- (error "Buffer is not an archive buffer"))
- (if archive-read-only
- (error "Archive is read-only")))
- (if (eq arcbuf (current-buffer))
- (error "An archive buffer cannot be added to itself"))
- (if (string= name "")
- (error "Archive members may not be given empty names"))
- (let ((func (save-excursion (set-buffer arcbuf)
- (archive-name "add-new-member")))
- (membuf (current-buffer)))
- (if (fboundp func)
- (save-excursion
- (set-buffer arcbuf)
- (funcall func buffer-file-name membuf name))
- (error "Adding a new member is not supported for this archive type"))))
-;; -------------------------------------------------------------------------
-;; Section: IO stuff
-
-(defun archive-check-dos (&optional force)
- "*Possibly handle a buffer with ^M^J terminated lines."
- (save-restriction
- (widen)
- (save-excursion
- (goto-char (point-min))
- (setq archive-subfile-dos
- (or force (not (search-forward-regexp "[^\r]\n" nil t))))
- (if (boundp 'default-buffer-file-type)
- (setq buffer-file-type (not archive-subfile-dos)))
- (if archive-subfile-dos
- (let ((modified (buffer-modified-p)))
- (buffer-disable-undo (current-buffer))
- (goto-char (point-min))
- (while (search-forward "\r\n" nil t)
- (replace-match "\n"))
- (buffer-enable-undo)
- (set-buffer-modified-p modified))))))
-
-(defun archive-write-file-member ()
- (if archive-subfile-dos
- (save-restriction
- (widen)
- (save-excursion
- (goto-char (point-min))
- ;; We don't want our ^M^J <--> ^J changes to show in the undo list
- (let ((undo-list buffer-undo-list))
- (unwind-protect
- (progn
- (setq buffer-undo-list t)
- (while (search-forward "\n" nil t)
- (replace-match "\r\n"))
- (setq archive-subfile-dos nil)
- (if (boundp 'default-buffer-file-type)
- (setq buffer-file-type t))
- ;; OK, we're now have explicit ^M^Js -- save and re-unixfy
- (archive-write-file-member))
- (progn
- (archive-check-dos t)
- (setq buffer-undo-list undo-list))))
- t))
- (save-excursion
- (save-restriction
- (message "Updating archive...")
- (widen)
- (let ((writer (save-excursion (set-buffer archive-superior-buffer)
- (archive-name "write-file-member")))
- (archive (save-excursion (set-buffer archive-superior-buffer)
- (buffer-file-name))))
- (if (fboundp writer)
- (funcall writer archive archive-subfile-mode)
- (archive-*-write-file-member archive
- archive-subfile-mode
- (symbol-value writer))))
- (set-buffer-modified-p nil)
- (message "Updating archive...done")
- (set-buffer archive-superior-buffer)
- (revert-buffer)
- t))))
-
-(defun archive-*-write-file-member (archive descr command)
- (let* ((ename (aref descr 0))
- (tmpfile (expand-file-name ename archive-tmpdir))
- (top (directory-file-name (file-name-as-directory archive-tmpdir)))
- (default-directory (file-name-as-directory top)))
- (unwind-protect
- (progn
- (make-directory (file-name-directory tmpfile) t)
- (write-region (point-min) (point-max) tmpfile nil 'nomessage)
- (if (aref descr 3)
- ;; Set the file modes, but make sure we can read it.
- (set-file-modes tmpfile (logior ?\400 (aref descr 3))))
- (let ((exitcode (apply 'call-process
- (car command)
- nil
- nil
- nil
- (append (cdr command) (list archive ename)))))
- (if (equal exitcode 0)
- nil
- (error "Updating was unsuccessful (%S)" exitcode))))
- (archive-delete-local tmpfile))))
-
-(defun archive-write-file ()
- (save-excursion
- (write-region archive-proper-file-start (point-max) buffer-file-name nil t)
- (set-buffer-modified-p nil)
- t))
-;; -------------------------------------------------------------------------
-;; Section: Marking and unmarking.
-
-(defun archive-flag-deleted (p &optional type)
- "In archive mode, mark this member to be deleted from the archive.
-With a prefix argument, mark that many files."
- (interactive "p")
- (or type (setq type ?D))
- (beginning-of-line)
- (let ((sign (if (>= p 0) +1 -1))
- (modified (buffer-modified-p))
- buffer-read-only)
- (while (not (zerop p))
- (if (archive-get-descr t)
- (progn
- (delete-char 1)
- (insert type)))
- (forward-line sign)
- (setq p (- p sign)))
- (set-buffer-modified-p modified))
- (archive-next-line 0))
-
-(defun archive-unflag (p)
- "In archive mode, un-mark this member if it is marked to be deleted.
-With a prefix argument, un-mark that many files forward."
- (interactive "p")
- (archive-flag-deleted p ? ))
-
-(defun archive-unflag-backwards (p)
- "In archive mode, un-mark this member if it is marked to be deleted.
-With a prefix argument, un-mark that many members backward."
- (interactive "p")
- (archive-flag-deleted (- p) ? ))
-
-(defun archive-unmark-all-files ()
- "Remove all marks."
- (interactive)
- (let ((modified (buffer-modified-p))
- buffer-read-only)
- (save-excursion
- (goto-char archive-file-list-start)
- (while (< (point) archive-file-list-end)
- (or (= (following-char) ? )
- (progn (delete-char 1) (insert ? )))
- (forward-line 1)))
- (set-buffer-modified-p modified)))
-
-(defun archive-mark (p)
- "In archive mode, mark this member for group operations.
-With a prefix argument, mark that many members.
-Use \\[archive-unmark-all-files] to remove all marks."
- (interactive "p")
- (archive-flag-deleted p ?*))
-
-(defun archive-get-marked (mark &optional default)
- (let (files)
- (save-excursion
- (goto-char archive-file-list-start)
- (while (< (point) archive-file-list-end)
- (if (= (following-char) mark)
- (setq files (cons (archive-get-descr) files)))
- (forward-line 1)))
- (or (nreverse files)
- (and default
- (list (archive-get-descr))))))
-;; -------------------------------------------------------------------------
-;; Section: Operate
-
-(defun archive-next-line (p)
- (interactive "p")
- (forward-line p)
- (or (eobp)
- (forward-char archive-file-name-indent)))
-
-(defun archive-previous-line (p)
- (interactive "p")
- (archive-next-line (- p)))
-
-(defun archive-chmod-entry (new-mode)
- "Change the protection bits associated with all marked or this member.
-The new protection bits can either be specified as an octal number or
-as a relative change like \"g+rw\" as for chmod(2)"
- (interactive "sNew mode (octal or relative): ")
- (if archive-read-only (error "Archive is read-only"))
- (let ((func (archive-name "chmod-entry")))
- (if (fboundp func)
- (progn
- (funcall func new-mode (archive-get-marked ?* t))
- (archive-resummarize))
- (error "Setting mode bits is not supported for this archive type"))))
-
-(defun archive-chown-entry (new-uid)
- "Change the owner of all marked or this member."
- (interactive "nNew uid: ")
- (if archive-read-only (error "Archive is read-only"))
- (let ((func (archive-name "chown-entry")))
- (if (fboundp func)
- (progn
- (funcall func new-uid (archive-get-marked ?* t))
- (archive-resummarize))
- (error "Setting owner is not supported for this archive type"))))
-
-(defun archive-chgrp-entry (new-gid)
- "Change the group of all marked or this member."
- (interactive "nNew gid: ")
- (if archive-read-only (error "Archive is read-only"))
- (let ((func (archive-name "chgrp-entry")))
- (if (fboundp func)
- (progn
- (funcall func new-gid (archive-get-marked ?* t))
- (archive-resummarize))
- (error "Setting group is not supported for this archive type"))))
-
-(defun archive-expunge ()
- "Do the flagged deletions."
- (interactive)
- (let (files)
- (save-excursion
- (goto-char archive-file-list-start)
- (while (< (point) archive-file-list-end)
- (if (= (following-char) ?D)
- (setq files (cons (aref (archive-get-descr) 0) files)))
- (forward-line 1)))
- (setq files (nreverse files))
- (and files
- (or (not archive-read-only)
- (error "Archive is read-only"))
- (or (yes-or-no-p (format "Really delete %d member%s? "
- (length files)
- (if (null (cdr files)) "" "s")))
- (error "Operation aborted"))
- (let ((archive (archive-maybe-copy (buffer-file-name)))
- (expunger (archive-name "expunge")))
- (if (fboundp expunger)
- (funcall expunger archive files)
- (archive-*-expunge archive files (symbol-value expunger)))
- (archive-maybe-update nil)
- (if archive-remote
- (archive-resummarize)
- (revert-buffer))))))
-
-(defun archive-*-expunge (archive files command)
- (apply 'call-process
- (car command)
- nil
- nil
- nil
- (append (cdr command) (cons archive files))))
-
-(defun archive-rename-entry (newname)
- "Change the name associated with this entry in the tar file."
- (interactive "sNew name: ")
- (if archive-read-only (error "Archive is read-only"))
- (if (string= newname "")
- (error "Archive members may not be given empty names"))
- (let ((func (archive-name "rename-entry"))
- (descr (archive-get-descr)))
- (if (fboundp func)
- (progn
- (funcall func (buffer-file-name) newname descr)
- (archive-resummarize))
- (error "Renaming is not supported for this archive type"))))
-
-;; Revert the buffer and recompute the dired-like listing.
-(defun archive-mode-revert (&optional no-autosave no-confirm)
- (let ((no (archive-get-lineno)))
- (setq archive-files nil)
- (let ((revert-buffer-function nil))
- (revert-buffer t t))
- (archive-mode)
- (goto-char archive-file-list-start)
- (archive-next-line no)))
-
-(defun archive-undo ()
- "Undo in an archive buffer.
-This doesn't recover lost files, it just undoes changes in the buffer itself."
- (interactive)
- (let (buffer-read-only)
- (undo)))
-;; -------------------------------------------------------------------------
-;; Section: Arc Archives
-
-(defun archive-arc-summarize ()
- (let ((p 1)
- (totalsize 0)
- (maxlen 8)
- files
- visual)
- (while (and (< (+ p 29) (point-max))
- (= (char-after p) ?\C-z)
- (> (char-after (1+ p)) 0))
- (let* ((namefld (buffer-substring (+ p 2) (+ p 2 13)))
- (fnlen (or (string-match "\0" namefld) 13))
- (efnname (substring namefld 0 fnlen))
- (csize (archive-l-e (+ p 15) 4))
- (moddate (archive-l-e (+ p 19) 2))
- (modtime (archive-l-e (+ p 21) 2))
- (ucsize (archive-l-e (+ p 25) 4))
- (fiddle (string= efnname (upcase efnname)))
- (ifnname (if fiddle (downcase efnname) efnname))
- (text (format " %8d %-11s %-8s %s"
- ucsize
- (archive-dosdate moddate)
- (archive-dostime modtime)
- ifnname)))
- (setq maxlen (max maxlen fnlen)
- totalsize (+ totalsize ucsize)
- visual (cons (vector text
- (- (length text) (length ifnname))
- (length text))
- visual)
- files (cons (vector efnname ifnname fiddle nil (1- p))
- files)
- p (+ p 29 csize))))
- (goto-char (point-min))
- (let ((dash (concat "- -------- ----------- -------- "
- (make-string maxlen ?-)
- "\n")))
- (insert "M Length Date Time File\n"
- dash)
- (archive-summarize-files (nreverse visual))
- (insert dash
- (format " %8d %d file%s"
- totalsize
- (length files)
- (if (= 1 (length files)) "" "s"))
- "\n"))
- (apply 'vector (nreverse files))))
-
-(defun archive-arc-rename-entry (archive newname descr)
- (if (string-match "[:\\\\/]" newname)
- (error "File names in arc files may not contain a path"))
- (if (> (length newname) 12)
- (error "File names in arc files are limited to 12 characters"))
- (let ((name (concat newname (substring "\0\0\0\0\0\0\0\0\0\0\0\0\0"
- (length newname))))
- buffer-read-only)
- (save-restriction
- (save-excursion
- (widen)
- (goto-char (+ archive-proper-file-start (aref descr 4) 2))
- (delete-char 13)
- (insert name)))))
-;; -------------------------------------------------------------------------
-;; Section: Lzh Archives
-
-(defun archive-lzh-summarize ()
- (let ((p 1)
- (totalsize 0)
- (maxlen 8)
- files
- visual)
- (while (progn (goto-char p) (looking-at "..-l[hz][0-9]-"))
- (let* ((hsize (char-after p))
- (csize (archive-l-e (+ p 7) 4))
- (ucsize (archive-l-e (+ p 11) 4))
- (modtime (archive-l-e (+ p 15) 2))
- (moddate (archive-l-e (+ p 17) 2))
- (fnlen (char-after (+ p 21)))
- (efnname (buffer-substring (+ p 22) (+ p 22 fnlen)))
- (fiddle (string= efnname (upcase efnname)))
- (ifnname (if fiddle (downcase efnname) efnname))
- (p2 (+ p 22 fnlen))
- (creator (if (>= (- hsize fnlen) 24) (char-after (+ p2 2)) 0))
- (mode (if (= creator ?U) (archive-l-e (+ p2 8) 2) ?\666))
- (modestr (if mode (archive-int-to-mode mode) "??????????"))
- (uid (if (= creator ?U) (archive-l-e (+ p2 10) 2)))
- (gid (if (= creator ?U) (archive-l-e (+ p2 12) 2)))
- (text (if archive-alternate-display
- (format " %8d %5S %5S %s"
- ucsize
- (or uid "?")
- (or gid "?")
- ifnname)
- (format " %10s %8d %-11s %-8s %s"
- modestr
- ucsize
- (archive-dosdate moddate)
- (archive-dostime modtime)
- ifnname))))
- (setq maxlen (max maxlen fnlen)
- totalsize (+ totalsize ucsize)
- visual (cons (vector text
- (- (length text) (length ifnname))
- (length text))
- visual)
- files (cons (vector efnname ifnname fiddle mode (1- p))
- files)
- p (+ p hsize 2 csize))))
- (goto-char (point-min))
- (let ((dash (concat (if archive-alternate-display
- "- -------- ----- ----- "
- "- ---------- -------- ----------- -------- ")
- (make-string maxlen ?-)
- "\n"))
- (header (if archive-alternate-display
- "M Length Uid Gid File\n"
- "M Filemode Length Date Time File\n"))
- (sumline (if archive-alternate-display
- " %8d %d file%s"
- " %8d %d file%s")))
- (insert header dash)
- (archive-summarize-files (nreverse visual))
- (insert dash
- (format sumline
- totalsize
- (length files)
- (if (= 1 (length files)) "" "s"))
- "\n"))
- (apply 'vector (nreverse files))))
-
-(defconst archive-lzh-alternate-display t)
-
-(defun archive-lzh-extract (archive name)
- (archive-extract-by-stdout archive name archive-lzh-extract))
-
-(defun archive-lzh-resum (p count)
- (let ((sum 0))
- (while (> count 0)
- (setq count (1- count)
- sum (+ sum (char-after p))
- p (1+ p)))
- (logand sum 255)))
-
-(defun archive-lzh-rename-entry (archive newname descr)
- (save-restriction
- (save-excursion
- (widen)
- (let* ((p (+ archive-proper-file-start (aref descr 4)))
- (oldhsize (char-after p))
- (oldfnlen (char-after (+ p 21)))
- (newfnlen (length newname))
- (newhsize (+ oldhsize newfnlen (- oldfnlen)))
- buffer-read-only)
- (if (> newhsize 255)
- (error "The file name is too long"))
- (goto-char (+ p 21))
- (delete-char (1+ oldfnlen))
- (insert newfnlen newname)
- (goto-char p)
- (delete-char 2)
- (insert newhsize (archive-lzh-resum p newhsize))))))
-
-(defun archive-lzh-ogm (newval files errtxt ofs)
- (save-restriction
- (save-excursion
- (widen)
- (while files
- (let* ((fil (car files))
- (p (+ archive-proper-file-start (aref fil 4)))
- (hsize (char-after p))
- (fnlen (char-after (+ p 21)))
- (p2 (+ p 22 fnlen))
- (creator (if (>= (- hsize fnlen) 24) (char-after (+ p2 2)) 0))
- buffer-read-only)
- (if (= creator ?U)
- (progn
- (or (numberp newval)
- (setq newval (funcall newval (archive-l-e (+ p2 ofs) 2))))
- (goto-char (+ p2 ofs))
- (delete-char 2)
- (insert (logand newval 255) (lsh newval -8))
- (goto-char (1+ p))
- (delete-char 1)
- (insert (archive-lzh-resum (1+ p) hsize)))
- (message "Member %s does not have %s field"
- (aref fil 1) errtxt)))
- (setq files (cdr files))))))
-
-(defun archive-lzh-chown-entry (newuid files)
- (archive-lzh-ogm newuid files "an uid" 10))
-
-(defun archive-lzh-chgrp-entry (newgid files)
- (archive-lzh-ogm newgid files "a gid" 12))
-
-(defun archive-lzh-chmod-entry (newmode files)
- (archive-lzh-ogm
- ;; This should work even though newmode will be dynamically accessed.
- (function (lambda (old) (archive-calc-mode old newmode t)))
- files "a unix-style mode" 8))
-;; -------------------------------------------------------------------------
-;; Section: Zip Archives
-
-(defun archive-zip-summarize ()
- (goto-char (- (point-max) (- 22 18)))
- (search-backward-regexp "[P]K\005\006")
- (let ((p (1+ (archive-l-e (+ (point) 16) 4)))
- (maxlen 8)
- (totalsize 0)
- files
- visual)
- (while (string= "PK\001\002" (buffer-substring p (+ p 4)))
- (let* ((creator (char-after (+ p 5)))
- (method (archive-l-e (+ p 10) 2))
- (modtime (archive-l-e (+ p 12) 2))
- (moddate (archive-l-e (+ p 14) 2))
- (ucsize (archive-l-e (+ p 24) 4))
- (fnlen (archive-l-e (+ p 28) 2))
- (exlen (archive-l-e (+ p 30) 2))
- (fclen (archive-l-e (+ p 32) 2))
- (lheader (archive-l-e (+ p 42) 4))
- (efnname (buffer-substring (+ p 46) (+ p 46 fnlen)))
- (isdir (and (= ucsize 0)
- (string= (file-name-nondirectory efnname) "")))
- (mode (cond ((memq creator '(2 3)) ; Unix + VMS
- (archive-l-e (+ p 40) 2))
- ((memq creator '(0 5 6 7 10 11)) ; Dos etc.
- (logior ?\444
- (if isdir (logior 16384 ?\111) 0)
- (if (zerop
- (logand 1 (char-after (+ p 38))))
- ?\222 0)))
- (t nil)))
- (modestr (if mode (archive-int-to-mode mode) "??????????"))
- (fiddle (and archive-zip-case-fiddle
- (not (not (memq creator '(0 2 4 5 9))))))
- (ifnname (if fiddle (downcase efnname) efnname))
- (text (format " %10s %8d %-11s %-8s %s"
- modestr
- ucsize
- (archive-dosdate moddate)
- (archive-dostime modtime)
- ifnname)))
- (setq maxlen (max maxlen fnlen)
- totalsize (+ totalsize ucsize)
- visual (cons (vector text
- (- (length text) (length ifnname))
- (length text))
- visual)
- files (cons (if isdir
- nil
- (vector efnname ifnname fiddle mode
- (list (1- p) lheader)))
- files)
- p (+ p 46 fnlen exlen fclen))))
- (goto-char (point-min))
- (let ((dash (concat "- ---------- -------- ----------- -------- "
- (make-string maxlen ?-)
- "\n")))
- (insert "M Filemode Length Date Time File\n"
- dash)
- (archive-summarize-files (nreverse visual))
- (insert dash
- (format " %8d %d file%s"
- totalsize
- (length files)
- (if (= 1 (length files)) "" "s"))
- "\n"))
- (apply 'vector (nreverse files))))
-
-(defun archive-zip-extract (archive name)
- (if archive-zip-use-pkzip
- (archive-*-extract archive name archive-zip-extract)
- (archive-extract-by-stdout archive name archive-zip-extract)))
-
-(defun archive-zip-write-file-member (archive descr)
- (archive-*-write-file-member
- archive
- descr
- (if (aref descr 2) archive-zip-update-case archive-zip-update)))
-
-(defun archive-zip-chmod-entry (newmode files)
- (save-restriction
- (save-excursion
- (widen)
- (while files
- (let* ((fil (car files))
- (p (+ archive-proper-file-start (car (aref fil 4))))
- (creator (char-after (+ p 5)))
- (oldmode (aref fil 3))
- (newval (archive-calc-mode oldmode newmode t))
- buffer-read-only)
- (cond ((memq creator '(2 3)) ; Unix + VMS
- (goto-char (+ p 40))
- (delete-char 2)
- (insert (logand newval 255) (lsh newval -8)))
- ((memq creator '(0 5 6 7 10 11)) ; Dos etc.
- (goto-char (+ p 38))
- (insert (logior (logand (char-after (point)) 254)
- (logand (logxor 1 (lsh newval -7)) 1)))
- (delete-char 1))
- (t (message "Don't know how to change mode for this member"))))
- (setq files (cdr files))))))
-;; -------------------------------------------------------------------------
-;; Section: Zoo Archives
-
-(defun archive-zoo-summarize ()
- (let ((p (1+ (archive-l-e 25 4)))
- (maxlen 8)
- (totalsize 0)
- files
- visual)
- (while (and (string= "\334\247\304\375" (buffer-substring p (+ p 4)))
- (> (archive-l-e (+ p 6) 4) 0))
- (let* ((next (1+ (archive-l-e (+ p 6) 4)))
- (moddate (archive-l-e (+ p 14) 2))
- (modtime (archive-l-e (+ p 16) 2))
- (ucsize (archive-l-e (+ p 20) 4))
- (namefld (buffer-substring (+ p 38) (+ p 38 13)))
- (dirtype (char-after (+ p 4)))
- (lfnlen (if (= dirtype 2) (char-after (+ p 56)) 0))
- (ldirlen (if (= dirtype 2) (char-after (+ p 57)) 0))
- (fnlen (+ ldirlen
- (if (> lfnlen 0)
- (1- lfnlen)
- (or (string-match "\0" namefld) 13))))
- (efnname (concat
- (if (> ldirlen 0)
- (concat (buffer-substring
- (+ p 58 lfnlen) (+ p 58 lfnlen ldirlen -1))
- "/")
- "")
- (if (> lfnlen 0)
- (buffer-substring (+ p 58) (+ p 58 lfnlen -1))
- (substring namefld 0 fnlen))))
- (fiddle (and (= lfnlen 0) (string= efnname (upcase efnname))))
- (ifnname (if fiddle (downcase efnname) efnname))
- (text (format " %8d %-11s %-8s %s"
- ucsize
- (archive-dosdate moddate)
- (archive-dostime modtime)
- ifnname)))
- (setq maxlen (max maxlen fnlen)
- totalsize (+ totalsize ucsize)
- visual (cons (vector text
- (- (length text) (length ifnname))
- (length text))
- visual)
- files (cons (vector efnname ifnname fiddle nil (1- p))
- files)
- p next)))
- (goto-char (point-min))
- (let ((dash (concat "- -------- ----------- -------- "
- (make-string maxlen ?-)
- "\n")))
- (insert "M Length Date Time File\n"
- dash)
- (archive-summarize-files (nreverse visual))
- (insert dash
- (format " %8d %d file%s"
- totalsize
- (length files)
- (if (= 1 (length files)) "" "s"))
- "\n"))
- (apply 'vector (nreverse files))))
-
-(defun archive-zoo-extract (archive name)
- (archive-extract-by-stdout archive name archive-zoo-extract))
-;; -------------------------------------------------------------------------
-(provide 'archive-mode)
-
-;; arc-mode.el ends here.
diff --git a/lisp/array.el b/lisp/array.el
deleted file mode 100644
index fab1c1ec59c..00000000000
--- a/lisp/array.el
+++ /dev/null
@@ -1,949 +0,0 @@
-;;; array.el --- array editing commands for Gnu Emacs
-
-;; Copyright (C) 1987 Free Software Foundation, Inc.
-
-;; Author David M. Brown
-;; Maintainer: FSF
-;; Keywords: extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Commands for editing a buffer interpreted as a rectangular array
-;; or matrix of whitespace-separated strings. You specify the array
-;; dimensions and some other parameters at startup time.
-
-;; 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
-
-;; 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.
-
-
-;;; Code:
-
-;;; 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.
- (1+ (floor 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 "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
- (+ (floor (1- temp-max-column) new-columns-per-line)
- (if new-rows-numbered 2 1)))
- (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 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")
- (force-mode-line-update)
- (make-variable-buffer-local 'truncate-lines)
- (setq truncate-lines t)
- (setq overwrite-mode 'overwrite-mode-textual)
- (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
- (+ (floor (1- max-column) columns-per-line)
- (if rows-numbered 2 1)))))
-
-;;; array.el ends here
diff --git a/lisp/auto-show.el b/lisp/auto-show.el
deleted file mode 100644
index 2cae3c334e0..00000000000
--- a/lisp/auto-show.el
+++ /dev/null
@@ -1,114 +0,0 @@
-;;; auto-show.el --- perform automatic horizontal scrolling as point moves
-;;; This file is in the public domain.
-
-;;; Keywords: scroll display minor-mode
-;;; Author: Pete Ware <ware@cis.ohio-state.edu>
-;;; Maintainer: FSF
-
-;;; Commentary:
-
-;;; This file provides functions that
-;;; automatically scroll the window horizontally when the point moves
-;;; off the left or right side of the window.
-
-;;; Once this library is loaded, automatic horizontal scrolling
-;;; occurs whenever long lines are being truncated.
-;;; To request truncation of long lines, set the variable
-;;; Setting the variable `truncate-lines' to non-nil.
-;;; You can do this for all buffers as follows:
-;;;
-;;; (set-default 'truncate-lines t)
-
-;;; Here is how to do it for C mode only:
-;;;
-;;; (set-default 'truncate-lines nil) ; this is the original value
-;;; (defun my-c-mode-hook ()
-;;; "Run when C-mode starts up. Changes ..."
-;;; ... set various personal preferences ...
-;;; (setq truncate-lines t))
-;;; (add-hook 'c-mode-hook 'my-c-mode-hook)
-;;;
-;;;
-;;; As a finer level of control, you can still have truncated lines but
-;;; without the automatic horizontal scrolling by setting the buffer
-;;; local variable `auto-show-mode' to nil. The default value is t.
-;;; The command `auto-show-mode' toggles the value of the variable
-;;; `auto-show-mode'.
-
-;;; Code:
-
-(defvar auto-show-mode t
- "*Non-nil enables automatic horizontal scrolling, when lines are truncated.
-The default value is t. To change the default, do this:
- (set-default 'auto-show-mode nil)
-See also command `auto-show-mode'.
-This variable has no effect when lines are not being truncated.")
-
-(make-variable-buffer-local 'auto-show-mode)
-
-(defvar auto-show-shift-amount 8
- "*Extra columns to scroll. for automatic horizontal scrolling.")
-
-(defvar auto-show-show-left-margin-threshold 50
- "*Threshold column for automatic horizontal scrolling to the right.
-If point is before this column, we try to scroll to make the left margin
-visible. Setting this to 0 disables this feature.")
-
-(defun auto-show-truncationp ()
- "True if line truncation is enabled for the selected window."
- (or truncate-lines
- (and truncate-partial-width-windows
- (< (window-width) (frame-width)))))
-
-;;;###autoload
-(defun auto-show-mode (arg)
- "Turn automatic horizontal scroll mode on or off.
-With arg, turn auto scrolling on if arg is positive, off otherwise."
- (interactive "P")
- (setq auto-show-mode
- (if (null arg)
- (not auto-show-mode)
- (> (prefix-numeric-value arg) 0))))
-
-(defun auto-show-make-point-visible (&optional ignore-arg)
- "Scroll horizontally to make point visible, if that is enabled.
-This function only does something if `auto-show-mode' is non-nil
-and longlines are being truncated in the selected window.
-See also the command `auto-show-toggle'."
- (interactive)
- (if (and auto-show-mode (auto-show-truncationp)
- (equal (window-buffer) (current-buffer)))
- (let* ((col (current-column)) ;column on line point is at
- (scroll (window-hscroll)) ;how far window is scrolled
- (w-width (- (window-width)
- (if (> scroll 0)
- 2 1))) ;how wide window is on the screen
- (right-col (+ scroll w-width)))
- (if (and (< col auto-show-show-left-margin-threshold)
- (< col (window-width))
- (> scroll 0))
- (scroll-right scroll)
- (if (< col scroll) ;to the left of the screen
- (scroll-right (+ (- scroll col) auto-show-shift-amount))
- (if (or (> col right-col) ;to the right of the screen
- (and (= col right-col)
- (not (eolp))))
- (scroll-left (+ auto-show-shift-amount
- (- col (+ scroll w-width))))
- )
- )
- )
- )
- )
- )
-
-;; Do auto-scrolling after commands.
-(add-hook 'post-command-hook 'auto-show-make-point-visible)
-
-;; Do auto-scrolling in comint buffers after process output also.
-(add-hook 'comint-output-filter-functions 'auto-show-make-point-visible t)
-
-(provide 'auto-show)
-
-;; auto-show.el ends here
-
diff --git a/lisp/autoinsert.el b/lisp/autoinsert.el
deleted file mode 100644
index e67ab211aba..00000000000
--- a/lisp/autoinsert.el
+++ /dev/null
@@ -1,255 +0,0 @@
-;;; autoinsert.el --- automatic mode-dependent insertion of text into new files
-
-;; Copyright (C) 1985, 1986, 1987, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Charlie Martin <crm@cs.duke.edu>
-;; Adapted-By: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The following defines an association list for text to be
-;; automatically inserted when a new file is created, and a function
-;; which automatically inserts these files; the idea is to insert
-;; default text much as the mode is automatically set using
-;; auto-mode-alist.
-;;
-;; To use:
-;; (add-hook 'find-file-hooks 'auto-insert)
-;; setq auto-insert-directory to an appropriate slash-terminated value
-;;
-;; Author: Charlie Martin
-;; Department of Computer Science and
-;; National Biomedical Simulation Resource
-;; Box 3709
-;; Duke University Medical Center
-;; Durham, NC 27710
-;; (crm@cs.duke.edu,mcnc!duke!crm)
-
-;;; Code:
-
-(defvar auto-insert 'not-modified
- "*Controls automatic insertion into newly found empty files:
- nil do nothing
- t insert if possible
- other insert if possible, but mark as unmodified.
-Insertion is possible when something appropriate is found in
-`auto-insert-alist'. When the insertion is marked as unmodified, you can
-save it with \\[write-file] RET.
-This variable is used when `auto-insert' is called as a function, e.g.
-when you do (add-hook 'find-file-hooks 'auto-insert).
-With \\[auto-insert], this is always treated as if it were `t'.")
-
-
-(defvar auto-insert-query 'function
- "*If non-`nil', ask user before auto-inserting.
-When this is `function', only ask when called non-interactively.")
-
-
-(defvar auto-insert-prompt "Perform %s auto-insertion? "
- "*Prompt to use when querying whether to auto-insert.
-If this contains a %s, that will be replaced by the matching rule.")
-
-
-(defvar auto-insert-alist
- '((("\\.\\([Hh]\\|hh\\|hpp\\)\\'" . "C / C++ header")
- (upcase (concat (file-name-nondirectory
- (substring buffer-file-name 0 (match-beginning 0)))
- "_"
- (substring buffer-file-name (1+ (match-beginning 0)))))
- "#ifndef " str \n
- "#define " str "\n\n"
- _ "\n\n#endif")
-
- (("\\.\\([Cc]\\|cc\\|cpp\\)\\'" . "C / C++ program")
- nil
- "#include \""
- ;; nop without latest cc-mode
- (and (fboundp 'c-companion-file)
- ;(file-readable-p (c-companion-file 'name))
- (file-name-nondirectory (c-companion-file 'name))) & ?\"
- | -10)
-
- ("[Mm]akefile\\'" . "makefile.inc")
-
- (html-mode . (lambda () (sgml-tag "html")))
-
- (plain-tex-mode . "tex-insert.tex")
- (bibtex-mode . "tex-insert.tex")
- (latex-mode
- ;; should try to offer completing read for these
- "options, RET: "
- "\\documentstyle[" str & ?\] | -1
- ?{ (read-string "class: ") "}\n"
- ("package, %s: "
- "\\usepackage[" (read-string "options, RET: ") & ?\] | -1 ?{ str "}\n")
- _ "\n\\begin{document}\n" _
- "\n\\end{document}")
-
- (("/bin/.*[^/]\\'" . "Shell-Script mode magic number")
- lambda ()
- (if (eq major-mode default-major-mode)
- (sh-mode)))
-
- (ada-mode . ada-header)
-
- (("\\.el\\'" . "Emacs Lisp header")
- "Short description: "
- ";;; " (file-name-nondirectory (buffer-file-name)) " --- " str "
-
-;; Copyright (C) " (substring (current-time-string) -4) " by "
- (getenv "ORGANIZATION") | "Free Software Foundation, Inc." "
-
-;; Author: " (user-full-name)
-'(if (search-backward "&" (save-excursion (beginning-of-line 1) (point)) t)
- (replace-match (capitalize (user-login-name)) t t))
-'(end-of-line 1) " <" (user-login-name) ?@ (system-name) ">
-;; Keywords: "
- '(require 'finder)
- ;;'(setq v1 (apply 'vector (mapcar 'car finder-known-keywords)))
- '(setq v1 (mapcar (lambda (x) (list (symbol-name (car x))))
- finder-known-keywords)
- v2 (mapconcat (lambda (x) (format "%10.0s: %s" (car x) (cdr x)))
- finder-known-keywords
- "\n"))
- ((let ((minibuffer-help-form v2))
- (completing-read "Keyword, C-h: " v1 nil t))
- str ", ") & -2 "
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; " _ "
-
-;;; Code:
-
-
-
-;;; " (file-name-nondirectory (buffer-file-name)) " ends here"))
- "A list specifying text to insert by default into a new file.
-Elements look like (CONDITION . ACTION) or ((CONDITION . DESCRIPTION) . ACTION).
-CONDITION maybe a regexp that must match the new file's name, or it may be
-a symbol that must match the major mode for this element to apply.
-Only the first matching element is effective.
-Optional DESCRIPTION is a string for filling `auto-insert-prompt'.
-ACTION may be a skeleton to insert (see `skeleton-insert'), an absolute
-file-name or one relative to `auto-insert-directory' or a function to call.
-ACTION may also be a vector containing several successive single actions as
-described above, e.g. [\"header.insert\" date-and-author-update].")
-
-
-;; Establish a default value for auto-insert-directory
-(defvar auto-insert-directory "~/insert/"
- "*Directory from which auto-inserted files are taken.")
-
-
-;;;###autoload
-(defun auto-insert ()
- "Insert default contents into a new file if `auto-insert' is non-nil.
-Matches the visited file name against the elements of `auto-insert-alist'."
- (interactive)
- (and (not buffer-read-only)
- (or (eq this-command 'auto-insert)
- (and auto-insert
- (bobp) (eobp)))
- (let ((alist auto-insert-alist)
- case-fold-search cond desc action)
- (goto-char 1)
- ;; find first matching alist entry
- (while alist
- (if (atom (setq cond (car (car alist))))
- (setq desc cond)
- (setq desc (cdr cond)
- cond (car cond)))
- (if (if (symbolp cond)
- (eq cond major-mode)
- (string-match cond buffer-file-name))
- (setq action (cdr (car alist))
- alist nil)
- (setq alist (cdr alist))))
-
- ;; Now, if we found something, do it
- (and action
- (if (stringp action)
- (file-readable-p (concat auto-insert-directory action))
- t)
- (if auto-insert-query
- (or (if (eq auto-insert-query 'function)
- (eq this-command 'auto-insert))
- (y-or-n-p (format auto-insert-prompt desc)))
- t)
- (mapcar
- (lambda (action)
- (if (stringp action)
- (if (file-readable-p
- (setq action (concat auto-insert-directory action)))
- (insert-file-contents action))
- (save-window-excursion
- ;; make buffer visible before skeleton or function
- ;; which might ask the user for something
- (switch-to-buffer (current-buffer))
- (if (and (consp action)
- (not (eq (car action) 'lambda)))
- (skeleton-insert action)
- (funcall action)))))
- (if (vectorp action)
- action
- (vector action))))
- (and (buffer-modified-p)
- (not (eq this-command 'auto-insert))
- (set-buffer-modified-p (eq auto-insert t))))))
-
-
-;;;###autoload
-(defun define-auto-insert (key action &optional after)
- "Associate CONDITION with (additional) ACTION in `auto-insert-alist'.
-Optional AFTER means to insert action after all existing actions for CONDITION,
-or if CONDITION had no actions, after all other CONDITIONs."
- (let ((elt (assoc key auto-insert-alist)))
- (if elt
- (setcdr elt
- (if (vectorp (cdr elt))
- (vconcat (if after (cdr elt))
- (if (vectorp action) action (vector action))
- (if after () (cdr elt)))
- (if after
- (vector (cdr elt) action)
- (vector action (cdr elt)))))
- (if after
- (nconc auto-insert-alist (list (cons key action)))
- (setq auto-insert-alist (cons (cons key action)
- auto-insert-alist))))))
-
-;;; autoinsert.el ends here
diff --git a/lisp/avoid.el b/lisp/avoid.el
deleted file mode 100644
index f95ee81985e..00000000000
--- a/lisp/avoid.el
+++ /dev/null
@@ -1,359 +0,0 @@
-;;; avoid.el --- make mouse pointer stay out of the way of editing
-
-;;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Boris Goldowsky <boris@gnu.ai.mit.edu>
-;; Keywords: mouse
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; For those who are annoyed by the mouse pointer obscuring text,
-;; this mode moves the mouse pointer - either just a little out of
-;; the way, or all the way to the corner of the frame.
-;; To use, load or evaluate this file and type M-x mouse-avoidance-mode .
-;; To set up permanently, put the following in your .emacs:
-;;
-;; (if window-system (mouse-avoidance-mode 'animate))
-;;
-;; The 'animate can be 'jump or 'banish or 'exile or 'protean if you prefer.
-;; See the documentation for function `mouse-avoidance-mode' for
-;; details of the different modes.
-;;
-;; For added silliness, make the animatee animate...
-;; put something similar to the following into your .emacs:
-;;
-;; (if window-system
-;; (mouse-avoidance-set-pointer-shape
-;; (eval (nth (random 4)
-;; '(x-pointer-man x-pointer-spider
-;; x-pointer-gobbler x-pointer-gumby)))))
-;;
-;; For completely random pointer shape, replace the setq above with:
-;; (setq x-pointer-shape (mouse-avoidance-random-shape))
-;;
-;; Bugs / Warnings / To-Do:
-;;
-;; - Using this code does slow emacs down. "banish" mode shouldn't
-;; be too bad, and on my workstation even "animate" is reasonable.
-;;
-;; - It ought to find out where any overlapping frames are and avoid them,
-;; rather than always raising the frame.
-
-;; Credits:
-;; This code was helped by all those who contributed suggestions,
-;; fixes, and additions
-;; Joe Harrington (and his advisor), for the original inspiration.
-;; Ken Manheimer, for dreaming up the Protean mode.
-;; Richard Stallman, for the awful cat-and-mouse pun, among other things.
-;; Mike Williams, Denis Howe, Bill Benedetto, Chris Moore, Don Morris,
-;; Simon Marshall, and M.S. Ashton, for their feedback.
-
-;;; Code:
-
-(provide 'avoid)
-
-(defvar mouse-avoidance-mode nil
- "Value is t or a symbol if the mouse pointer should avoid the cursor.
-See function `mouse-avoidance-mode' for possible values. Changing this
-variable is NOT the recommended way to change modes; use that function
-instead.")
-
-(defvar mouse-avoidance-nudge-dist 15
- "*Average distance that mouse will be moved when approached by cursor.
-Only applies in mouse-avoidance-mode `jump' and its derivatives.
-For best results make this larger than `mouse-avoidance-threshold'.")
-
-(defvar mouse-avoidance-nudge-var 10
- "*Variability of `mouse-avoidance-nudge-dist' (which see).")
-
-(defvar mouse-avoidance-animation-delay .01
- "Delay between animation steps, in seconds.")
-
-(defvar mouse-avoidance-threshold 5
- "*Mouse-pointer's flight distance.
-If the cursor gets closer than this, the mouse pointer will move away.
-Only applies in mouse-avoidance-modes `animate' and `jump'.")
-
-;; Internal variables
-(defvar mouse-avoidance-state nil)
-(defvar mouse-avoidance-pointer-shapes nil)
-(defvar mouse-avoidance-n-pointer-shapes 0)
-(defvar mouse-avoidance-old-pointer-shape nil)
-
-;;; Functions:
-
-(defsubst mouse-avoidance-set-pointer-shape (shape)
- "Set the shape of the mouse pointer to SHAPE."
- (setq x-pointer-shape shape)
- (set-mouse-color nil))
-
-(defun mouse-avoidance-point-position ()
- "Return the position of point as (FRAME X . Y).
-Analogous to mouse-position."
- (let* ((w (selected-window))
- (edges (window-edges w))
- (list
- (compute-motion (max (window-start w) (point-min)) ; start pos
- ;; window-start can be < point-min if the
- ;; latter has changed since the last redisplay
- '(0 . 0) ; start XY
- (point) ; stop pos
- (cons (window-width) (window-height)); stop XY: none
- (1- (window-width)) ; width
- (cons (window-hscroll w) 0) ; 0 may not be right?
- (selected-window))))
- ;; compute-motion returns (pos HPOS VPOS prevhpos contin)
- ;; we want: (frame hpos . vpos)
- (cons (selected-frame)
- (cons (+ (car edges) (car (cdr list)))
- (+ (car (cdr edges)) (car (cdr (cdr list))))))))
-
-;(defun mouse-avoidance-point-position-test ()
-; (interactive)
-; (message (format "point=%s mouse=%s"
-; (cdr (mouse-avoidance-point-position))
-; (cdr (mouse-position)))))
-
-(defun mouse-avoidance-set-mouse-position (pos)
- ;; Carefully set mouse position to given position (X . Y)
- ;; Ideally, should check if X,Y is in the current frame, and if not,
- ;; leave the mouse where it was. However, this is currently
- ;; difficult to do, so we just raise the frame to avoid frame switches.
- ;; Returns t if it moved the mouse.
- (let ((f (selected-frame)))
- (raise-frame f)
- (set-mouse-position f (car pos) (cdr pos))
- t))
-
-(defun mouse-avoidance-too-close-p (mouse)
- ;; Return t if mouse pointer and point cursor are too close.
- ;; Acceptable distance is defined by mouse-avoidance-threshold.
- (let ((point (mouse-avoidance-point-position)))
- (and (eq (car mouse) (car point))
- (car (cdr mouse))
- (< (abs (- (car (cdr mouse)) (car (cdr point))))
- mouse-avoidance-threshold)
- (< (abs (- (cdr (cdr mouse)) (cdr (cdr point))))
- mouse-avoidance-threshold))))
-
-(defun mouse-avoidance-banish-destination ()
- "The position to which mouse-avoidance-mode `banish' moves the mouse.
-You can redefine this if you want the mouse banished to a different corner."
- (cons (1- (frame-width))
- 0))
-
-(defun mouse-avoidance-banish-mouse ()
- ;; Put the mouse pointer in the upper-right corner of the current frame.
- (mouse-avoidance-set-mouse-position (mouse-avoidance-banish-destination)))
-
-(defsubst mouse-avoidance-delta (cur delta dist var min max)
- ;; Decide how far to move in either dimension.
- ;; Args are the CURRENT location, the desired DELTA for
- ;; warp-conservation, the DISTANCE we like to move, the VARIABILITY
- ;; in distance allowed, and the MIN and MAX possible window positions.
- ;; Returns something as close to DELTA as possible within the constraints.
- (let ((L1 (max (- min cur) (+ (- dist) (- var))))
- (R1 (+ (- dist) var ))
- (L2 (+ dist (- var)))
- (R2 (min (- max cur) (+ dist var))))
- (if (< R1 (- min cur)) (setq L1 nil R1 nil))
- (if (> L2 (- max cur)) (setq L2 nil R2 nil))
- (cond ((and L1 (< delta L1)) L1)
- ((and R1 (< delta R1)) delta)
- ((and R1 (< delta 0)) R1)
- ((and L2 (< delta L2)) L2)
- ((and R2 (< delta R2)) delta)
- (R2)
- ((or R1 L2))
- (t 0))))
-
-(defun mouse-avoidance-nudge-mouse ()
- ;; Push the mouse a little way away, possibly animating the move
- ;; For these modes, state keeps track of the total offset that we've
- ;; accumulated, and tries to keep it close to zero.
- (let* ((cur (mouse-position))
- (cur-frame (car cur))
- (cur-pos (cdr cur))
- (deltax (mouse-avoidance-delta
- (car cur-pos) (- (random mouse-avoidance-nudge-var)
- (car mouse-avoidance-state))
- mouse-avoidance-nudge-dist mouse-avoidance-nudge-var
- 0 (frame-width)))
- (deltay (mouse-avoidance-delta
- (cdr cur-pos) (- (random mouse-avoidance-nudge-var)
- (cdr mouse-avoidance-state))
- mouse-avoidance-nudge-dist mouse-avoidance-nudge-var
- 0 (frame-height))))
- (setq mouse-avoidance-state
- (cons (+ (car mouse-avoidance-state) deltax)
- (+ (cdr mouse-avoidance-state) deltay)))
- (if (or (eq mouse-avoidance-mode 'animate)
- (eq mouse-avoidance-mode 'proteus))
- (let ((i 0.0))
- (while (<= i 1)
- (mouse-avoidance-set-mouse-position
- (cons (+ (car cur-pos) (round (* i deltax)))
- (+ (cdr cur-pos) (round (* i deltay)))))
- (setq i (+ i (max .1 (/ 1.0 mouse-avoidance-nudge-dist))))
- (if (eq mouse-avoidance-mode 'proteus)
- (mouse-avoidance-set-pointer-shape
- (mouse-avoidance-random-shape)))
- (sit-for mouse-avoidance-animation-delay)))
- (mouse-avoidance-set-mouse-position (cons (+ (car (cdr cur)) deltax)
- (+ (cdr (cdr cur)) deltay))))))
-
-(defun mouse-avoidance-random-shape ()
- "Return a random cursor shape.
-This assumes that any variable whose name begins with x-pointer- and
-has an integer value is a valid cursor shape. You might want to
-redefine this function to suit your own tastes."
- (if (null mouse-avoidance-pointer-shapes)
- (progn
- (setq mouse-avoidance-pointer-shapes
- (mapcar '(lambda (x) (symbol-value (intern x)))
- (all-completions "x-pointer-" obarray
- '(lambda (x)
- (and (boundp x)
- (integerp (symbol-value x)))))))
- (setq mouse-avoidance-n-pointer-shapes
- (length mouse-avoidance-pointer-shapes))))
- (nth (random mouse-avoidance-n-pointer-shapes)
- mouse-avoidance-pointer-shapes))
-
-(defun mouse-avoidance-banish-hook ()
- (if (and (not executing-kbd-macro) ; don't check inside macro
- (mouse-avoidance-kbd-command (this-command-keys)))
- (mouse-avoidance-banish-mouse)))
-
-(defun mouse-avoidance-exile-hook ()
- ;; For exile mode, the state is nil when the mouse is in its normal
- ;; position, and set to the old mouse-position when the mouse is in exile.
- (if (and (not executing-kbd-macro)
- (mouse-avoidance-kbd-command (this-command-keys)))
- (let ((mp (mouse-position)))
- (cond ((and (not mouse-avoidance-state)
- (mouse-avoidance-too-close-p mp))
- (setq mouse-avoidance-state mp)
- (mouse-avoidance-banish-mouse))
- ((and mouse-avoidance-state
- (not (mouse-avoidance-too-close-p mouse-avoidance-state)))
- (if (and (eq (car mp) (selected-frame))
- (equal (cdr mp) (mouse-avoidance-banish-destination)))
- (mouse-avoidance-set-mouse-position
- ;; move back only if user has not moved mouse
- (cdr mouse-avoidance-state)))
- ;; but clear state anyway, to be ready for another move
- (setq mouse-avoidance-state nil))))))
-
-(defun mouse-avoidance-fancy-hook ()
- ;; Used for the "fancy" modes, ie jump et al.
- (if (and (not executing-kbd-macro) ; don't check inside macro
- (mouse-avoidance-kbd-command (this-command-keys))
- (mouse-avoidance-too-close-p (mouse-position)))
- (let ((old-pos (mouse-position)))
- (mouse-avoidance-nudge-mouse)
- (if (not (eq (selected-frame) (car old-pos)))
- ;; This should never happen.
- (apply 'set-mouse-position old-pos)))))
-
-(defun mouse-avoidance-kbd-command (key)
- "Return t if the KEYSEQENCE is composed of keyboard events only.
-Return nil if there are any lists in the key sequence."
- (cond ((null key) nil) ; Null event seems to be
- ; returned occasionally.
- ((not (vectorp key)) t) ; Strings are keyboard events.
- ((catch 'done
- (let ((i 0)
- (l (length key)))
- (while (< i l)
- (if (listp (aref key i))
- (throw 'done nil))
- (setq i (1+ i))))
- t))))
-
-;;;###autoload
-(defun mouse-avoidance-mode (&optional mode)
- "Set cursor avoidance mode to MODE.
-MODE should be one of the symbols `banish', `exile', `jump', `animate',
-`cat-and-mouse', `proteus', or `none'.
-
-If MODE is nil, toggle mouse avoidance between `none` and `banish'
-modes. Positive numbers and symbols other than the above are treated
-as equivalent to `banish'; negative numbers and `-' are equivalent to `none'.
-
-Effects of the different modes:
- * banish: Move the mouse to the upper-right corner on any keypress.
- * exile: Move the mouse to the corner only if the cursor gets too close,
- and allow it to return once the cursor is out of the way.
- * jump: If the cursor gets too close to the mouse, displace the mouse
- a random distance & direction.
- * animate: As `jump', but shows steps along the way for illusion of motion.
- * cat-and-mouse: Same as `animate'.
- * proteus: As `animate', but changes the shape of the mouse pointer too.
-
-Whenever the mouse is moved, the frame is also raised.
-
-\(see `mouse-avoidance-threshold' for definition of \"too close\",
-and `mouse-avoidance-nudge-dist' and `mouse-avoidance-nudge-var' for
-definition of \"random distance\".)"
- (interactive
- (list (intern (completing-read
- "Select cursor avoidance technique (SPACE for list): "
- '(("banish") ("exile") ("jump") ("animate")
- ("cat-and-mouse") ("proteus") ("none"))
- nil t))))
- (if (eq mode 'cat-and-mouse)
- (setq mode 'animate))
- (remove-hook 'post-command-idle-hook 'mouse-avoidance-banish-hook)
- (remove-hook 'post-command-idle-hook 'mouse-avoidance-exile-hook)
- (remove-hook 'post-command-idle-hook 'mouse-avoidance-fancy-hook)
-
- ;; Restore pointer shape if necessary
- (if (eq mouse-avoidance-mode 'proteus)
- (mouse-avoidance-set-pointer-shape mouse-avoidance-old-pointer-shape))
-
- ;; Do additional setup depending on version of mode requested
- (cond ((eq mode 'none)
- (setq mouse-avoidance-mode nil))
- ((or (eq mode 'jump)
- (eq mode 'animate)
- (eq mode 'proteus))
- (add-hook 'post-command-idle-hook 'mouse-avoidance-fancy-hook)
- (setq mouse-avoidance-mode mode
- mouse-avoidance-state (cons 0 0)
- mouse-avoidance-old-pointer-shape x-pointer-shape))
- ((eq mode 'exile)
- (add-hook 'post-command-idle-hook 'mouse-avoidance-exile-hook)
- (setq mouse-avoidance-mode mode
- mouse-avoidance-state nil))
- ((or (eq mode 'banish)
- (eq mode t)
- (and (null mode) (null mouse-avoidance-mode))
- (and mode (> (prefix-numeric-value mode) 0)))
- (add-hook 'post-command-idle-hook 'mouse-avoidance-banish-hook)
- (setq mouse-avoidance-mode 'banish))
- (t (setq mouse-avoidance-mode nil)))
- (force-mode-line-update))
-
-(or (assq 'mouse-avoidance-mode minor-mode-alist)
- (setq minor-mode-alist (cons '(mouse-avoidance-mode " Avoid")
- minor-mode-alist)))
-
-;;; End of avoid.el
diff --git a/lisp/bindings.el b/lisp/bindings.el
deleted file mode 100644
index 3978afa58e7..00000000000
--- a/lisp/bindings.el
+++ /dev/null
@@ -1,554 +0,0 @@
-;;; bindings.el --- define standard key bindings and some variables.
-
-;; Copyright (C) 1985,86,87,92,93,94,95,96 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-;;; 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.
-;;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-;;; Code:
-
-(defvar mode-line-buffer-identification (purecopy '("%F: %12b"))
- "Mode-line control for identifying the buffer being displayed.
-Its default value is (\"%F: %12b\"). Under X, `%F' is replaced with `Emacs'.
-Major modes that edit things other than ordinary files may change this
-\(e.g. Info, Dired,...)")
-
-(make-variable-buffer-local 'mode-line-buffer-identification)
-
-(defvar 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)
-
-(defvar 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 'mode-line-process 'minor-mode-alist
- (purecopy "%n")
- (purecopy ")%]--")
- (purecopy '(line-number-mode "L%l--"))
- (purecopy '(column-number-mode "C%c--"))
- (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.
-
-Actually, STRING need not be a string; any possible mode-line element
-is okay. See `mode-line-format'.")
-;; Don't use purecopy here--some people want to change these strings.
-(setq minor-mode-alist '((abbrev-mode " Abbrev")
- (overwrite-mode overwrite-mode)
- (auto-fill-function " Fill")
- ;; not really a minor mode...
- (defining-kbd-macro " Def")))
-
-;; These variables are used by autoloadable packages.
-;; They are defined here so that they do not get overridden
-;; by the loading of those packages.
-
-;; 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
- (append
- (cond ((or (eq system-type 'ms-dos) (eq system-type 'windows-nt))
- '(".o" "~" ".bin" ".bak" ".obj" ".map"
- ".a" ".ln" ".blg" ".bbl"))
- ((eq system-type 'vax-vms)
- '(".obj" ".exe" ".bin" ".lbin" ".sbin"
- ".brn" ".rnt" ".mem" ".lni" ".lis"
- ".olb" ".tlb" ".mlb" ".hlb"))
- (t
- '(".o" "~" ".bin" ".lbin" ".fasl"
- ".a" ".ln" ".blg" ".bbl")))
- '(".elc" ".lof"
- ".glo" ".idx" ".lot"
- ;; TeX-related
- ".dvi" ".fmt"
- ;; Texinfo-related
- ".toc" ".log" ".aux"
- ".cp" ".fn" ".ky" ".pg" ".tp" ".vr"
- ".cps" ".fns" ".kys" ".pgs" ".tps" ".vrs")))
-
-(setq debug-ignored-errors
- '(beginning-of-line beginning-of-buffer end-of-line
- end-of-buffer end-of-file buffer-read-only
- "^Previous command was not a yank$"
- "^Minibuffer window is not active$"
- "^End of history; no next item$"
- "^Beginning of history; no preceding item$"
- "^No recursive edit is in progress$"
- "^Changes to be undone are outside visible portion of buffer$"
- "^No undo information in this buffer$"
- "^No further undo information$"
- "^Save not confirmed$"
- "^Recover-file cancelled\\.$"
-
- ;; comint
- "^Not at command line$"
- "^Empty input ring$"
- "^No history$"
- "^Not found$";; To common?
- "^Current buffer has no process$"
-
- ;; dabbrev
- "^No dynamic expansion for \".*\" found\\.$"
- "^No further dynamic expansions for \".*\" found\\.$"
- "^No further dynamic expansions for `.*' found$"
-
- ;; Completion
- "^To complete, the point must be after a symbol at least [0-9]* character long\\.$"
- "^The string \".*\" is too short to be saved as a completion\\.$"
-
- ;; Compile
- "^No more errors\\( yet\\|\\)$"
-
- ;; Gnus
- "^NNTP: Connection closed\\.$"
-
- ;; info
- "^Node has no Previous$"
- "^No \".*\" in index$"
-
- ;; imenu
- "^No items suitable for an index found in this buffer\\.$"
- "^The mode \".*\" does not take full advantage of imenu\\.el yet\\.$"
-
- ;; ispell
- "^No word found to check!$"
-
- ;; mh-e
- "^Cursor not pointing to message$"
- "^There is no other window$"
-
- ;; man
- "^No manpage [0-9]* found$"
-
- ;; etags
- "^No tags table in use! Use .* to select one\\.$"
- "^There is no default tag$"
- "^No previous tag locations$"
- "^File .* is not a valid tags table$"
- "^No \\(more \\|\\)tags \\(matching\\|containing\\) "
- "^Rerun etags: `.*' not found in "
- "^All files processed\\.$"
- "^No .* or .* in progress.$"
- "^File .* not in current tags tables$"
- "No tags table loaded."
- "^Nothing to complete$"
-
- ;; BBDB
- "^no previous record$"
- "^no next record$"))
-
-
-(make-variable-buffer-local 'indent-tabs-mode)
-
-;; This is here to avoid autoloading etags on M-TAB.
-;; M-x visit-tags-table will autoload etags, which will redefine complete-tag.
-(defun complete-tag ()
- "Perform tags completion on the text around point.
-Completes to the set of names listed in the current tags table.
-The string to complete is chosen in the same way as the default
-for \\[find-tag] (which see)."
- (interactive)
- (error (substitute-command-keys
- "No tags table loaded. Try \\[visit-tags-table].")))
-
-;; Reduce total amount of space we must allocate during this function
-;; that we will not need to keep permanently.
-(garbage-collect)
-
-(define-key ctl-x-map "n" (make-sparse-keymap))
-(define-key ctl-x-map "r" (make-sparse-keymap))
-
-(setq help-event-list '(help f1))
-
-;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 "nn" 'narrow-to-region)
-(define-key ctl-x-map "nw" 'widen)
-;; (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 ":" 'eval-expression)
-;; Define ESC ESC : like ESC : for people who type ESC ESC out of habit.
-(define-key esc-map "\M-:" 'eval-expression)
-;; Changed from C-x ESC so that function keys work following C-x.
-(define-key ctl-x-map "\e\e" 'repeat-complex-command)
-;; New binding analogous to M-:.
-(define-key ctl-x-map "\M-:" 'repeat-complex-command)
-(define-key ctl-x-map "u" 'advertised-undo)
-;; Many people are used to typing C-/ on X terminals and getting C-_.
-(define-key global-map [?\C-/] 'undo)
-(define-key global-map "\C-_" 'undo)
-(define-key esc-map "!" 'shell-command)
-(define-key esc-map "|" 'shell-command-on-region)
-
-;; This is an experiment--make up and down arrows do history.
-(define-key minibuffer-local-map [up] 'previous-history-element)
-(define-key minibuffer-local-map [down] 'next-history-element)
-(define-key minibuffer-local-ns-map [up] 'previous-history-element)
-(define-key minibuffer-local-ns-map [down] 'next-history-element)
-(define-key minibuffer-local-completion-map [up] 'previous-history-element)
-(define-key minibuffer-local-completion-map [down] 'next-history-element)
-(define-key minibuffer-local-must-match-map [up] 'previous-history-element)
-(define-key minibuffer-local-must-match-map [down] 'next-history-element)
-
-(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 control-digits.
-(let ((i ?0))
- (while (<= i ?9)
- (define-key global-map (read (format "[?\\C-%c]" i)) 'digit-argument)
- (setq i (1+ i))))
-(define-key global-map [?\C--] 'negative-argument)
-;; Define control-meta-digits.
-(let ((i ?0))
- (while (<= i ?9)
- (define-key esc-map (read (format "[?\\C-%c]" i)) 'digit-argument)
- (setq i (1+ i))))
-(define-key global-map [?\C-\M--] 'negative-argument)
-
-(define-key global-map "\C-k" 'kill-line)
-(define-key global-map "\C-w" 'kill-region)
-(define-key esc-map "w" 'kill-ring-save)
-(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)
-;; Many people are used to typing C-SPC and getting C-@.
-(define-key global-map [?\C-\ ] 'set-mark-command)
-(define-key ctl-x-map "\C-x" 'exchange-point-and-mark)
-(define-key ctl-x-map "\C-@" 'pop-global-mark)
-(define-key ctl-x-map [?\C-\ ] 'pop-global-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)
-
-;;(defun function-key-error ()
-;; (interactive)
-;; (error "That function key is not bound to anything."))
-
-(define-key global-map [menu] 'execute-extended-command)
-(define-key global-map [find] 'search-forward)
-
-;; natural bindings for terminal keycaps --- defined in X keysym order
-(define-key global-map [home] 'beginning-of-buffer)
-(define-key global-map [M-home] 'beginning-of-buffer-other-window)
-(define-key global-map [left] 'backward-char)
-(define-key global-map [up] 'previous-line)
-(define-key global-map [right] 'forward-char)
-(define-key global-map [down] 'next-line)
-(define-key global-map [prior] 'scroll-down)
-(define-key global-map [next] 'scroll-up)
-(define-key global-map [C-up] 'backward-paragraph)
-(define-key global-map [C-down] 'forward-paragraph)
-(define-key global-map [C-prior] 'scroll-right)
-(define-key global-map [C-next] 'scroll-left)
-(define-key global-map [M-next] 'scroll-other-window)
-(define-key global-map [M-prior] 'scroll-other-window-down)
-(define-key global-map [end] 'end-of-buffer)
-(define-key global-map [M-end] 'end-of-buffer-other-window)
-(define-key global-map [begin] 'beginning-of-buffer)
-(define-key global-map [M-begin] 'beginning-of-buffer-other-window)
-;; (define-key global-map [select] 'function-key-error)
-;; (define-key global-map [print] 'function-key-error)
-(define-key global-map [execute] 'execute-extended-command)
-(define-key global-map [insert] 'overwrite-mode)
-(define-key global-map [C-insert] 'kill-ring-save)
-(define-key global-map [S-insert] 'yank)
-(define-key global-map [undo] 'undo)
-(define-key global-map [redo] 'repeat-complex-command)
-;; (define-key global-map [clearline] 'function-key-error)
-(define-key global-map [insertline] 'open-line)
-(define-key global-map [deleteline] 'kill-line)
-;; (define-key global-map [insertchar] 'function-key-error)
-(define-key global-map [deletechar] 'delete-char)
-;; (define-key global-map [backtab] 'function-key-error)
-;; (define-key global-map [f1] 'function-key-error)
-;; (define-key global-map [f2] 'function-key-error)
-;; (define-key global-map [f3] 'function-key-error)
-;; (define-key global-map [f4] 'function-key-error)
-;; (define-key global-map [f5] 'function-key-error)
-;; (define-key global-map [f6] 'function-key-error)
-;; (define-key global-map [f7] 'function-key-error)
-;; (define-key global-map [f8] 'function-key-error)
-;; (define-key global-map [f9] 'function-key-error)
-;; (define-key global-map [f10] 'function-key-error)
-;; (define-key global-map [f11] 'function-key-error)
-;; (define-key global-map [f12] 'function-key-error)
-;; (define-key global-map [f13] 'function-key-error)
-;; (define-key global-map [f14] 'function-key-error)
-;; (define-key global-map [f15] 'function-key-error)
-;; (define-key global-map [f16] 'function-key-error)
-;; (define-key global-map [f17] 'function-key-error)
-;; (define-key global-map [f18] 'function-key-error)
-;; (define-key global-map [f19] 'function-key-error)
-;; (define-key global-map [f20] 'function-key-error)
-;; (define-key global-map [f21] 'function-key-error)
-;; (define-key global-map [f22] 'function-key-error)
-;; (define-key global-map [f23] 'function-key-error)
-;; (define-key global-map [f24] 'function-key-error)
-;; (define-key global-map [f25] 'function-key-error)
-;; (define-key global-map [f26] 'function-key-error)
-;; (define-key global-map [f27] 'function-key-error)
-;; (define-key global-map [f28] 'function-key-error)
-;; (define-key global-map [f29] 'function-key-error)
-;; (define-key global-map [f30] 'function-key-error)
-;; (define-key global-map [f31] 'function-key-error)
-;; (define-key global-map [f32] 'function-key-error)
-;; (define-key global-map [f33] 'function-key-error)
-;; (define-key global-map [f34] 'function-key-error)
-;; (define-key global-map [f35] 'function-key-error)
-;; (define-key global-map [kp-backtab] 'function-key-error)
-;; (define-key global-map [kp-space] 'function-key-error)
-;; (define-key global-map [kp-tab] 'function-key-error)
-;; (define-key global-map [kp-enter] 'function-key-error)
-;; (define-key global-map [kp-f1] 'function-key-error)
-;; (define-key global-map [kp-f2] 'function-key-error)
-;; (define-key global-map [kp-f3] 'function-key-error)
-;; (define-key global-map [kp-f4] 'function-key-error)
-;; (define-key global-map [kp-multiply] 'function-key-error)
-;; (define-key global-map [kp-add] 'function-key-error)
-;; (define-key global-map [kp-separator] 'function-key-error)
-;; (define-key global-map [kp-subtract] 'function-key-error)
-;; (define-key global-map [kp-decimal] 'function-key-error)
-;; (define-key global-map [kp-divide] 'function-key-error)
-;; (define-key global-map [kp-0] 'function-key-error)
-;; (define-key global-map [kp-1] 'function-key-error)
-;; (define-key global-map [kp-2] 'function-key-error)
-;; (define-key global-map [kp-3] 'function-key-error)
-;; (define-key global-map [kp-4] 'function-key-error)
-;; (define-key global-map [kp-5] 'recenter)
-;; (define-key global-map [kp-6] 'function-key-error)
-;; (define-key global-map [kp-7] 'function-key-error)
-;; (define-key global-map [kp-8] 'function-key-error)
-;; (define-key global-map [kp-9] 'function-key-error)
-;; (define-key global-map [kp-equal] 'function-key-error)
-
-;; X11R6 distinguishes these keys from the non-kp keys.
-;; Make them behave like the non-kp keys unless otherwise bound.
-(define-key function-key-map [kp-home] [home])
-(define-key function-key-map [kp-left] [left])
-(define-key function-key-map [kp-up] [up])
-(define-key function-key-map [kp-right] [right])
-(define-key function-key-map [kp-down] [down])
-(define-key function-key-map [kp-prior] [prior])
-(define-key function-key-map [kp-next] [next])
-(define-key function-key-map [M-kp-next] [M-next])
-(define-key function-key-map [kp-end] [end])
-(define-key function-key-map [kp-begin] [begin])
-(define-key function-key-map [kp-insert] [insert])
-(define-key function-key-map [kp-delete] [delete])
-
-(define-key global-map [mouse-movement] 'ignore)
-
-(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)
-
-(defalias 'mode-specific-command-prefix (make-sparse-keymap))
-(defvar 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)
-
-(global-set-key [M-right] 'forward-word)
-(global-set-key [M-left] 'backward-word)
-;; ilya@math.ohio-state.edu says these bindings are standard on PC editors.
-(global-set-key [C-right] 'forward-word)
-(global-set-key [C-left] 'backward-word)
-;; This is not quite compatible, but at least is analogous
-(global-set-key [C-delete] 'backward-kill-word)
-;; This is "move to the clipboard", or as close as we come.
-(global-set-key [S-delete] 'kill-region)
-
-(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-\ ] 'mark-sexp)
-(define-key esc-map "\C-d" 'down-list)
-(define-key esc-map "\C-k" 'kill-sexp)
-(define-key global-map [C-M-delete] 'backward-kill-sexp)
-(define-key global-map [C-M-backspace] 'backward-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 ctl-x-map "nd" 'narrow-to-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 "r\C-@" 'point-to-register)
-(define-key ctl-x-map [?r ?\C-\ ] 'point-to-register)
-(define-key ctl-x-map "r " 'point-to-register)
-(define-key ctl-x-map "rj" 'jump-to-register)
-(define-key ctl-x-map "rs" 'copy-to-register)
-(define-key ctl-x-map "rx" 'copy-to-register)
-(define-key ctl-x-map "ri" 'insert-register)
-(define-key ctl-x-map "rg" 'insert-register)
-(define-key ctl-x-map "rr" 'copy-rectangle-to-register)
-(define-key ctl-x-map "rc" 'clear-rectangle)
-(define-key ctl-x-map "rk" 'kill-rectangle)
-(define-key ctl-x-map "rd" 'delete-rectangle)
-(define-key ctl-x-map "ry" 'yank-rectangle)
-(define-key ctl-x-map "ro" 'open-rectangle)
-(define-key ctl-x-map "rt" 'string-rectangle)
-(define-key ctl-x-map "rw" 'window-configuration-to-register)
-(define-key ctl-x-map "rf" 'frame-configuration-to-register)
-
-;; These key bindings are deprecated; use the above C-x r map instead.
-;; We use these aliases so \[...] will show the C-x r bindings instead.
-(defalias 'point-to-register-compatibility-binding 'point-to-register)
-(defalias 'jump-to-register-compatibility-binding 'jump-to-register)
-(defalias 'copy-to-register-compatibility-binding 'copy-to-register)
-(defalias 'insert-register-compatibility-binding 'insert-register)
-(define-key ctl-x-map "/" 'point-to-register-compatibility-binding)
-(define-key ctl-x-map "j" 'jump-to-register-compatibility-binding)
-(define-key ctl-x-map "x" 'copy-to-register-compatibility-binding)
-(define-key ctl-x-map "g" 'insert-register-compatibility-binding)
-;; (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)
-(define-key ctl-x-map "l" 'count-lines-page)
-(define-key ctl-x-map "np" 'narrow-to-page)
-;; (define-key ctl-x-map "p" 'narrow-to-page)
-
-(define-key ctl-x-map "al" 'add-mode-abbrev)
-(define-key ctl-x-map "a\C-a" 'add-mode-abbrev)
-(define-key ctl-x-map "ag" 'add-global-abbrev)
-(define-key ctl-x-map "a+" 'add-mode-abbrev)
-(define-key ctl-x-map "aig" 'inverse-add-global-abbrev)
-(define-key ctl-x-map "ail" 'inverse-add-mode-abbrev)
-;; (define-key ctl-x-map "a\C-h" 'inverse-add-global-abbrev)
-(define-key ctl-x-map "a-" 'inverse-add-global-abbrev)
-(define-key ctl-x-map "ae" 'expand-abbrev)
-(define-key ctl-x-map "a'" 'expand-abbrev)
-;; (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)
-
-;;; Don't compile this file; it contains no large function definitions.
-;;; Don't look for autoload cookies in this file.
-;;; Local Variables:
-;;; no-byte-compile: t
-;;; no-update-autoloads: t
-;;; End:
-
-;;; bindings.el ends here
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
deleted file mode 100644
index 36bb94464bb..00000000000
--- a/lisp/bookmark.el
+++ /dev/null
@@ -1,2214 +0,0 @@
-;;; bookmark.el --- set bookmarks, maybe annotate them, jump to them later.
-
-;; Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation
-
-;; Author: Karl Fogel <kfogel@red-bean.com>
-;; Maintainer: Karl Fogel <kfogel@red-bean.com>
-;; Created: July, 1993
-;; Author's Update Number: see variable `bookmark-version'.
-;; Keywords: bookmarks, placeholders, annotations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package is for setting "bookmarks" in files. A bookmark
-;; associates a string with a location in a certain file. Thus, you
-;; can navigate your way to that location by providing the string.
-;; See the "User Variables" section for customizations.
-
-;; Thanks to David Bremner <bremner@cs.sfu.ca> for thinking of and
-;; then implementing the bookmark-current-bookmark idea. He even
-;; sent *patches*, bless his soul...
-
-;; Thanks to Gregory M. Saunders <saunders@cis.ohio-state.edu> for
-;; fixing and improving bookmark-time-to-save-p.
-
-;; Thanks go to Andrew V. Klein <avk@cig.mot.com> for the code that
-;; sorts the alist before presenting it to the user (in bookmark-bmenu-list
-;; and the menu-bar).
-
-;; And much thanks to David Hughes <djh@harston.cv.com> for many small
-;; suggestions and the code to implement them (like
-;; bookmark-bmenu-check-position, and some of the Lucid compatibility
-;; stuff).
-
-;; Kudos (whatever they are) go to Jim Blandy <jimb@red-bean.com>
-;; for his eminently sensible suggestion to separate bookmark-jump
-;; into bookmark-jump and bookmark-jump-noselect, which made many
-;; other things cleaner as well.
-
-;; Thanks to Roland McGrath for encouragement and help with defining
-;; autoloads on the menu-bar.
-
-;; Jonathan Stigelman <stig@hackvan.com> gave patches for default
-;; values in bookmark-jump and bookmark-set. Everybody please keep
-;; all the keystrokes they save thereby and send them to him at the
-;; end of each year :-) (No, seriously, thanks Jonathan!)
-
-;; Buckets of gratitude to John Grabowski <johng@media.mit.edu> for
-;; thinking up the annotations feature and implementing it so well.
-
-;; Based on info-bookmark.el, by Karl Fogel and Ken Olstad
-;; <olstad@msc.edu>.
-
-;; Thanks to Mikio Nakajima <PBC01764@niftyserve.or.jp> for many bugs
-;; reported and fixed.
-
-;; Thank you, Michael Kifer, for contributing the XEmacs support.
-
-;; Enough with the credits already, get on to the good stuff:
-
-;; FAVORITE CHINESE RESTAURANT:
-;; Boy, that's a tough one. Probably Hong Min, or maybe Emperor's
-;; Choice (both in Chicago's Chinatown). Well, both. How about you?
-
-;;;; Code:
-
-(require 'pp)
-
-(defconst bookmark-version "2.6.4"
- "Version number of bookmark.el. This is not related to the version
-of Emacs bookmark comes with; it is used solely by bookmark's
-maintainers to avoid version confusion.")
-
-;;; Misc comments:
-;;
-;; If variable bookmark-use-annotations is non-nil, an annotation is
-;; queried for when setting a bookmark.
-;;
-;; The bookmark list is sorted lexically by default, but you can turn
-;; this off by setting bookmark-sort-flag to nil. If it is nil, then
-;; the list will be presented in the order it is recorded
-;; (chronologically), which is actually fairly useful as well.
-
-;;; User Variables
-
-(defvar bookmark-use-annotations nil
- "*If non-nil, saving a bookmark will query for an annotation in a
-buffer.")
-
-
-(defvar bookmark-save-flag t
- "*Controls when Emacs saves bookmarks to a file.
---> Nil means never save bookmarks, except when `bookmark-save' is
- explicitly called \(\\[bookmark-save]\).
---> t means save bookmarks when Emacs is killed.
---> Otherwise, it should be a number that is the frequency with which
- the bookmark list is saved \(i.e.: the number of times which
- Emacs' bookmark list may be modified before it is automatically
- saved.\). If it is a number, Emacs will also automatically save
- bookmarks when it is killed.
-
-Therefore, the way to get it to save every time you make or delete a
-bookmark is to set this variable to 1 \(or 0, which produces the same
-behavior.\)
-
-To specify the file in which to save them, modify the variable
-bookmark-default-file, which is `~/.emacs.bmk' by default.")
-
-
-(defconst bookmark-old-default-file "~/.emacs-bkmrks"
- "*The .emacs.bmk file used to be called this.")
-
-
-;; defvarred to avoid a compilation warning:
-(defvar bookmark-file nil
- "Old name for `bookmark-default-file'.")
-
-(defvar bookmark-default-file
- (if bookmark-file
- ;; In case user set `bookmark-file' in her .emacs:
- bookmark-file
- (convert-standard-filename "~/.emacs.bmk"))
- "*File in which to save bookmarks by default.")
-
-
-(defvar bookmark-version-control 'nospecial
- "*Whether or not to make numbered backups of the bookmark file.
-It can have four values: t, nil, `never', and `nospecial'.
-The first three have the same meaning that they do for the
-variable `version-control', and the final value `nospecial' means just
-use the value of `version-control'.")
-
-
-(defvar bookmark-completion-ignore-case t
- "*Non-nil means bookmark functions ignore case in completion.")
-
-
-(defvar bookmark-sort-flag t
- "*Non-nil means that bookmarks will be displayed sorted by bookmark
-name. Otherwise they will be displayed in LIFO order (that is, most
-recently set ones come first, oldest ones come last).")
-
-
-(defvar bookmark-automatically-show-annotations t
- "*Nil means don't show annotations when jumping to a bookmark.")
-
-
-(defvar bookmark-bmenu-file-column 30
- "*Column at which to display filenames in a buffer listing bookmarks.
-You can toggle whether files are shown with \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-toggle-filenames].")
-
-
-(defvar bookmark-bmenu-toggle-filenames t
- "*Non-nil means show filenames when listing bookmarks.
-This may result in truncated bookmark names. To disable this, put the
-following in your .emacs:
-
-\(setq bookmark-bmenu-toggle-filenames nil\)")
-
-
-(defvar bookmark-menu-length 70
- "*Maximum length of a bookmark name displayed on a popup menu.")
-
-
-;;; No user-serviceable parts beyond this point.
-
-;; Is it XEmacs?
-(defconst bookmark-xemacsp
- (string-match "\\(Lucid\\|Xemacs\\)" emacs-version))
-
-
-;; Added for lucid emacs compatibility, db
-(or (fboundp 'defalias) (fset 'defalias 'fset))
-
-;; suggested for lucid compatibility by david hughes:
-(or (fboundp 'frame-height) (defalias 'frame-height 'screen-height))
-
-;; This variable is probably obsolete now...
-(or (boundp 'baud-rate)
- ;; some random value higher than 9600
- (setq baud-rate 19200))
-
-;; XEmacs apparently call this `buffer-substring-without-properties',
-;; sigh.
-(or (fboundp 'buffer-substring-no-properties)
- (if (fboundp 'buffer-substring-without-properties)
- (fset 'buffer-substring-no-properties
- 'buffer-substring-without-properties)
- (fset 'buffer-substring-no-properties 'buffer-substring)))
-
-
-;;; Keymap stuff:
-;; some people have C-x r set to rmail or whatever. We don't want to
-;; assume that C-x r is a prefix map just because it's distributed
-;; that way...
-;; These are the distribution keybindings suggested by RMS, everything
-;; else will be done with M-x or the menubar:
-;;;###autoload
-(if (symbolp (key-binding "\C-xr"))
- nil
- (progn (define-key ctl-x-map "rb" 'bookmark-jump)
- (define-key ctl-x-map "rm" 'bookmark-set)
- (define-key ctl-x-map "rl" 'bookmark-bmenu-list)))
-
-;; define the map, so it can be bound by those who desire to do so:
-
-;;;###autoload
-(defvar bookmark-map nil
- "Keymap containing bindings to bookmark functions.
-It is not bound to any key by default: to bind it
-so that you have a bookmark prefix, just use `global-set-key' and bind a
-key of your choice to `bookmark-map'. All interactive bookmark
-functions have a binding in this keymap.")
-
-;;;###autoload
-(define-prefix-command 'bookmark-map)
-
-;; Read the help on all of these functions for details...
-;;;###autoload
-(define-key bookmark-map "x" 'bookmark-set)
-;;;###autoload
-(define-key bookmark-map "m" 'bookmark-set) ; "m" for "mark"
-;;;###autoload
-(define-key bookmark-map "j" 'bookmark-jump)
-;;;###autoload
-(define-key bookmark-map "g" 'bookmark-jump) ; "g" for "go"
-;;;###autoload
-(define-key bookmark-map "i" 'bookmark-insert)
-;;;###autoload
-(define-key bookmark-map "e" 'edit-bookmarks)
-;;;###autoload
-(define-key bookmark-map "f" 'bookmark-insert-location) ; "f" for "find"
-;;;###autoload
-(define-key bookmark-map "r" 'bookmark-rename)
-;;;###autoload
-(define-key bookmark-map "d" 'bookmark-delete)
-;;;###autoload
-(define-key bookmark-map "l" 'bookmark-load)
-;;;###autoload
-(define-key bookmark-map "w" 'bookmark-write)
-;;;###autoload
-(define-key bookmark-map "s" 'bookmark-save)
-
-
-;;; The annotation maps.
-(defvar bookmark-read-annotation-mode-map (copy-keymap text-mode-map)
- "Keymap for composing an annotation for a bookmark.")
-
-(define-key bookmark-read-annotation-mode-map "\C-c\C-c"
- 'bookmark-send-annotation)
-
-
-
-;;; Core variables and data structures:
-(defvar bookmark-alist ()
- "Association list of bookmarks and their records.
-You probably don't want to change the value of this alist yourself;
-instead, let the various bookmark functions do it for you.
-
-The format of the alist is
-
- \(BOOKMARK1 BOOKMARK2 ...\)
-
-where each BOOKMARK is of the form
-
-\(NAME
- \(filename . FILE\)
- \(front-context-string . FRONT-STR\)
- \(rear-context-string . REAR-STR\)
- \(position . POS\)
- \(info-node . POS\)
- \(annotation . ANNOTATION\)\)
-
-So the cdr of each bookmark is an alist too.
-`info-node' is optional, by the way.")
-
-
-(defvar bookmarks-already-loaded nil)
-
-
-;; just add the hook to make sure that people don't lose bookmarks
-;; when they kill Emacs, unless they don't want to save them.
-;;;###autoload
-(add-hook 'kill-emacs-hook
- (function
- (lambda () (and (featurep 'bookmark)
- bookmark-alist
- (bookmark-time-to-save-p t)
- (bookmark-save)))))
-
-;; more stuff added by db.
-
-(defvar bookmark-current-bookmark nil
- "Name of bookmark most recently used in the current file.
-It is buffer local, used to make moving a bookmark forward
-through a file easier.")
-
-(make-variable-buffer-local 'bookmark-current-bookmark)
-
-
-(defvar bookmark-alist-modification-count 0
- "Number of modifications to bookmark list since it was last saved.")
-
-
-(defvar bookmark-search-size 16
- "Length of the context strings recorded on either side of a bookmark.")
-
-
-(defvar bookmark-current-point 0)
-(defvar bookmark-yank-point 0)
-(defvar bookmark-current-buffer nil)
-
-
-
-;; Helper functions.
-
-;; Only functions on this page and the next one (file formats) need to
-;; know anything about the format of bookmark-alist entries.
-;; Everyone else should go through them.
-
-(defun bookmark-name-from-full-record (full-record)
- "Return name of FULL-RECORD \(an alist element instead of a string\)."
- (car full-record))
-
-
-(defun bookmark-all-names ()
- "Return a list of all current bookmark names."
- (bookmark-maybe-load-default-file)
- (mapcar
- (lambda (full-record)
- (bookmark-name-from-full-record full-record))
- bookmark-alist))
-
-
-(defun bookmark-get-bookmark (bookmark)
- "Return the full entry for BOOKMARK in bookmark-alist."
- (assoc bookmark bookmark-alist))
-
-
-(defun bookmark-get-bookmark-record (bookmark)
- "Return the guts of the entry for BOOKMARK in bookmark-alist.
-That is, all information but the name."
- (car (cdr (bookmark-get-bookmark bookmark))))
-
-
-(defun bookmark-set-name (bookmark newname)
- "Set BOOKMARK's name to NEWNAME."
- (setcar (bookmark-get-bookmark bookmark) newname))
-
-
-(defun bookmark-get-annotation (bookmark)
- "Return the annotation of BOOKMARK, or nil if none."
- (cdr (assq 'annotation (bookmark-get-bookmark-record bookmark))))
-
-
-(defun bookmark-set-annotation (bookmark ann)
- "Set the annotation of BOOKMARK to ANN."
- (let ((cell (assq 'annotation (bookmark-get-bookmark-record bookmark))))
- (if cell
- (setcdr cell ann)
- (nconc (bookmark-get-bookmark-record bookmark)
- (list (cons 'annotation ann))))))
-
-
-(defun bookmark-get-filename (bookmark)
- "Return the full filename of BOOKMARK."
- (cdr (assq 'filename (bookmark-get-bookmark-record bookmark))))
-
-
-(defun bookmark-set-filename (bookmark filename)
- "Set the full filename of BOOKMARK to FILENAME."
- (let ((cell (assq 'filename (bookmark-get-bookmark-record bookmark))))
- (if cell
- (setcdr cell filename)
- (nconc (bookmark-get-bookmark-record bookmark)
- (list (cons 'filename filename))))))
-
-
-(defun bookmark-get-position (bookmark)
- "Return the position \(i.e.: point\) of BOOKMARK."
- (cdr (assq 'position (bookmark-get-bookmark-record bookmark))))
-
-
-(defun bookmark-set-position (bookmark position)
- "Set the position \(i.e.: point\) of BOOKMARK to POSITION."
- (let ((cell (assq 'position (bookmark-get-bookmark-record bookmark))))
- (if cell
- (setcdr cell position)
- (nconc (bookmark-get-bookmark-record bookmark)
- (list (cons 'position position))))))
-
-
-(defun bookmark-get-front-context-string (bookmark)
- "Return the front-context-string of BOOKMARK."
- (cdr (assq 'front-context-string (bookmark-get-bookmark-record bookmark))))
-
-
-(defun bookmark-set-front-context-string (bookmark string)
- "Set the front-context-string of BOOKMARK to STRING."
- (let ((cell (assq 'front-context-string
- (bookmark-get-bookmark-record bookmark))))
- (if cell
- (setcdr cell string)
- (nconc (bookmark-get-bookmark-record bookmark)
- (list (cons 'front-context-string string))))))
-
-
-(defun bookmark-get-rear-context-string (bookmark)
- "Return the rear-context-string of BOOKMARK."
- (cdr (assq 'rear-context-string (bookmark-get-bookmark-record bookmark))))
-
-
-(defun bookmark-set-rear-context-string (bookmark string)
- "Set the rear-context-string of BOOKMARK to STRING."
- (let ((cell (assq 'rear-context-string
- (bookmark-get-bookmark-record bookmark))))
- (if cell
- (setcdr cell string)
- (nconc (bookmark-get-bookmark-record bookmark)
- (list (cons 'rear-context-string string))))))
-
-
-(defun bookmark-get-info-node (bookmark)
- "Get the info node associated with BOOKMARK."
- (cdr (assq 'info-node (bookmark-get-bookmark-record bookmark))))
-
-
-(defun bookmark-set-info-node (bookmark node)
- "Set the Info node of BOOKMARK to NODE."
- (let ((cell (assq 'info-node
- (bookmark-get-bookmark-record bookmark))))
- (if cell
- (setcdr cell node)
- (nconc (bookmark-get-bookmark-record bookmark)
- (list (cons 'info-node node)))))
-
- (message "%S" (assq 'info-node (bookmark-get-bookmark-record bookmark)))
- (sit-for 4)
- )
-
-
-(defvar bookmark-history nil
- "The history list for bookmark functions.")
-
-
-(defun bookmark-completing-read (prompt &optional default)
- "Prompting with PROMPT, read a bookmark name in completion.
-PROMPT will get a \": \" stuck on the end no matter what, so you
-probably don't want to include one yourself.
-Optional second arg DEFAULT is a string to return if the user enters
-the empty string."
- (bookmark-maybe-load-default-file) ; paranoia
- (let* ((completion-ignore-case bookmark-completion-ignore-case)
- (default default)
- (prompt (if default
- (concat prompt (format " (%s): " default))
- (concat prompt ": ")))
- (str
- (completing-read prompt
- bookmark-alist
- nil
- 0
- nil
- 'bookmark-history)))
- (if (string-equal "" str)
- (list default)
- (list str))))
-
-
-(defmacro bookmark-maybe-historicize-string (string)
- "Put STRING into the bookmark prompt history, if caller non-interactive.
-We need this because sometimes bookmark functions are invoked from
-menus, so `completing-read' never gets a chance to set `bookmark-history'."
- (` (or
- (interactive-p)
- (setq bookmark-history (cons (, string) bookmark-history)))))
-
-
-(defun bookmark-make (name &optional annotation overwrite info-node)
- "Make a bookmark named NAME.
-Optional second arg ANNOTATION gives it an annotation.
-Optional third arg OVERWRITE means replace any existing bookmarks with
-this name.
-Optional fourth arg INFO-NODE means this bookmark is at info node
-INFO-NODE, so record this fact in the bookmark's entry."
- (bookmark-maybe-load-default-file)
- (let ((stripped-name (copy-sequence name)))
- (or bookmark-xemacsp
- ;; XEmacs's `set-text-properties' doesn't work on
- ;; free-standing strings, apparently.
- (set-text-properties 0 (length stripped-name) nil stripped-name))
- (if (and (bookmark-get-bookmark stripped-name) (not overwrite))
- ;; already existing bookmark under that name and
- ;; no prefix arg means just overwrite old bookmark
- (setcdr (bookmark-get-bookmark stripped-name)
- (list (bookmark-make-cell annotation info-node)))
-
- ;; otherwise just cons it onto the front (either the bookmark
- ;; doesn't exist already, or there is no prefix arg. In either
- ;; case, we want the new bookmark consed onto the alist...)
-
- (setq bookmark-alist
- (cons
- (list stripped-name
- (bookmark-make-cell annotation info-node))
- bookmark-alist)))
-
- ;; Added by db
- (setq bookmark-current-bookmark stripped-name)
- (setq bookmark-alist-modification-count
- (1+ bookmark-alist-modification-count))
- (if (bookmark-time-to-save-p)
- (bookmark-save))))
-
-
-(defun bookmark-make-cell (annotation &optional info-node)
- "Return the record part of a new bookmark, given ANNOTATION.
-Must be at the correct position in the buffer in which the bookmark is
-being set. This might change someday.
-Optional second arg INFO-NODE means this bookmark is at info node
-INFO-NODE, so record this fact in the bookmark's entry."
- (let ((the-record
- (` ((filename . (, (bookmark-buffer-file-name)))
- (front-context-string
- . (, (if (>= (- (point-max) (point)) bookmark-search-size)
- (buffer-substring-no-properties
- (point)
- (+ (point) bookmark-search-size))
- nil)))
- (rear-context-string
- . (, (if (>= (- (point) (point-min)) bookmark-search-size)
- (buffer-substring-no-properties
- (point)
- (- (point) bookmark-search-size))
- nil)))
- (position . (, (point)))
- ))))
-
- ;; Now fill in the optional parts:
- (if annotation
- (nconc the-record (list (cons 'annotation annotation))))
- (if info-node
- (nconc the-record (list (cons 'info-node info-node))))
-
- ;; Finally, return the completed record.
- the-record))
-
-
-
-;;; File format stuff
-
-;; The OLD format of the bookmark-alist was:
-;;
-;; ((bookmark-name (filename
-;; string-in-front
-;; string-behind
-;; point))
-;; ...)
-;;
-;; The NEW format of the bookmark-alist is:
-;;
-;; ((bookmark-name ((filename . FILENAME)
-;; (front-context-string . string-in-front)
-;; (rear-context-string . string-behind)
-;; (position . POINT)
-;; (annotation . annotation)
-;; (whatever . VALUE)
-;; ...
-;; ))
-;; ...)
-;;
-;;
-;; I switched to using an internal as well as external alist because I
-;; felt that would be a more flexible framework in which to add
-;; features. It means that the order in which values appear doesn't
-;; matter, and it means that arbitrary values can be added without
-;; risk of interfering with existing ones.
-;;
-;; BOOKMARK-NAME is the string the user gives the bookmark and
-;; accesses it by from then on.
-;;
-;; FILENAME is the location of the file in which the bookmark is set.
-;;
-;; STRING-IN-FRONT is a string of `bookmark-search-size' chars of
-;; context in front of the point at which the bookmark is set.
-;;
-;; STRING-BEHIND is the same thing, but after the point.
-;;
-;; The context strings exist so that modifications to a file don't
-;; necessarily cause a bookmark's position to be invalidated.
-;; bookmark-jump will search for STRING-BEHIND and STRING-IN-FRONT in
-;; case the file has changed since the bookmark was set. It will
-;; attempt to place the user before the changes, if there were any.
-;; ANNOTATION is the annotation for the bookmark; it may not exist
-;; (for backward compatibility), be nil (no annotation), or be a
-;; string.
-
-
-(defconst bookmark-file-format-version 1
- "The current version of the format used by bookmark files.
-You should never need to change this.")
-
-
-(defconst bookmark-end-of-version-stamp-marker
- "-*- End Of Bookmark File Format Version Stamp -*-\n"
- "This string marks the end of the version stamp in a bookmark file.")
-
-
-(defun bookmark-alist-from-buffer ()
- "Return a bookmark-alist (in any format) from the current buffer.
-The buffer must of course contain bookmark format information.
-Does not care from where in the buffer it is called, and does not
-affect point."
- (save-excursion
- (goto-char (point-min))
- (if (search-forward bookmark-end-of-version-stamp-marker nil t)
- (read (current-buffer))
- ;; Else we're dealing with format version 0
- (if (search-forward "(" nil t)
- (progn
- (forward-char -1)
- (read (current-buffer)))
- ;; Else no hope of getting information here.
- (error "Not bookmark format")))))
-
-
-(defun bookmark-upgrade-version-0-alist (old-list)
- "Upgrade a version 0 alist OLD-LIST to the current version."
- (mapcar
- (lambda (bookmark)
- (let* ((name (car bookmark))
- (record (car (cdr bookmark)))
- (filename (nth 0 record))
- (front-str (nth 1 record))
- (rear-str (nth 2 record))
- (position (nth 3 record))
- (ann (nth 4 record)))
- (list
- name
- (` ((filename . (, filename))
- (front-context-string . (, (or front-str "")))
- (rear-context-string . (, (or rear-str "")))
- (position . (, position))
- (annotation . (, ann)))))))
- old-list))
-
-
-(defun bookmark-upgrade-file-format-from-0 ()
- "Upgrade a bookmark file of format 0 (the original format) to format 1.
-This expects to be called from point-min in a bookmark file."
- (message "Upgrading bookmark format from 0 to %d..."
- bookmark-file-format-version)
- (let* ((old-list (bookmark-alist-from-buffer))
- (new-list (bookmark-upgrade-version-0-alist old-list)))
- (delete-region (point-min) (point-max))
- (bookmark-insert-file-format-version-stamp)
- (pp new-list (current-buffer))
- (save-buffer))
- (goto-char (point-min))
- (message "Upgrading bookmark format from 0 to %d...done"
- bookmark-file-format-version)
- )
-
-
-(defun bookmark-grok-file-format-version ()
- "Return an integer which is the file-format version of this bookmark file.
-This expects to be called from point-min in a bookmark file."
- (if (looking-at "^;;;;")
- (save-excursion
- (save-match-data
- (re-search-forward "[0-9]")
- (forward-char -1)
- (read (current-buffer))))
- ;; Else this is format version 0, the original one, which didn't
- ;; even have version stamps.
- 0))
-
-
-(defun bookmark-maybe-upgrade-file-format ()
- "Check the file-format version of this bookmark file.
-If the version is not up-to-date, upgrade it automatically.
-This expects to be called from point-min in a bookmark file."
- (let ((version (bookmark-grok-file-format-version)))
- (cond
- ((= version bookmark-file-format-version)
- ) ; home free -- version is current
- ((= version 0)
- (bookmark-upgrade-file-format-from-0))
- (t
- (error "Bookmark file format version strangeness")))))
-
-
-(defun bookmark-insert-file-format-version-stamp ()
- "Insert text indicating current version of bookmark file format."
- (insert
- (format ";;;; Emacs Bookmark Format Version %d ;;;;\n"
- bookmark-file-format-version))
- (insert ";;; This format is meant to be slightly human-readable;\n"
- ";;; nevertheless, you probably don't want to edit it.\n"
- ";;; "
- bookmark-end-of-version-stamp-marker))
-
-
-;;; end file-format stuff
-
-
-;;; Core code:
-
-;;;###autoload
-(defun bookmark-set (&optional name parg)
- "Set a bookmark named NAME inside a file.
-If name is nil, then the user will be prompted.
-With prefix arg, will not overwrite a bookmark that has the same name
-as NAME if such a bookmark already exists, but instead will \"push\"
-the new bookmark onto the bookmark alist. Thus the most recently set
-bookmark with name NAME would be the one in effect at any given time,
-but the others are still there, should you decide to delete the most
-recent one.
-
-To yank words from the text of the buffer and use them as part of the
-bookmark name, type C-w while setting a bookmark. Successive C-w's
-yank successive words.
-
-Typing C-u inserts the name of the last bookmark used in the buffer
-\(as an aid in using a single bookmark name to track your progress
-through a large file\). If no bookmark was used, then C-u inserts the
-name of the file being visited.
-
-Use \\[bookmark-delete] to remove bookmarks \(you give it a name,
-and it removes only the first instance of a bookmark with that name from
-the list of bookmarks.\)"
- (interactive (list nil current-prefix-arg))
- (or
- (bookmark-buffer-file-name)
- (error "Buffer not visiting a file or directory"))
-
- (bookmark-maybe-load-default-file)
-
- (setq bookmark-current-point (point))
- (setq bookmark-yank-point (point))
- (setq bookmark-current-buffer (current-buffer))
-
- (let* ((default (or bookmark-current-bookmark
- (bookmark-buffer-name)))
- (str
- (or name
- (read-from-minibuffer
- (format "Set bookmark (%s): " default)
- nil
- (let ((now-map (copy-keymap minibuffer-local-map)))
- (progn (define-key now-map "\C-w"
- 'bookmark-yank-word)
- (define-key now-map "\C-u"
- 'bookmark-insert-current-bookmark))
- now-map))))
- (annotation nil))
- (and (string-equal str "") (setq str default))
- ;; Ask for an annotation buffer for this bookmark
- (if bookmark-use-annotations
- (bookmark-read-annotation parg str)
- (progn
- (bookmark-make str annotation parg (bookmark-info-current-node))
- (setq bookmark-current-bookmark str)
- (bookmark-bmenu-surreptitiously-rebuild-list)
- (goto-char bookmark-current-point)))))
-
-
-(defun bookmark-info-current-node ()
- "If in Info-mode, return current node name (a string), else nil."
- (if (eq major-mode 'Info-mode)
- Info-current-node))
-
-
-(defun bookmark-kill-line (&optional newline-too)
- "Kill from point to end of line.
-If optional arg NEWLINE-TOO is non-nil, delete the newline too.
-Does not affect the kill-ring."
- (let ((eol (save-excursion (end-of-line) (point))))
- (delete-region (point) eol)
- (if (and newline-too (looking-at "\n"))
- (delete-char 1))))
-
-
-;; Defvars to avoid compilation warnings:
-(defvar bookmark-annotation-paragraph nil)
-(defvar bookmark-annotation-name nil)
-(defvar bookmark-annotation-buffer nil)
-(defvar bookmark-annotation-file nil)
-(defvar bookmark-annotation-point nil)
-
-
-(defun bookmark-send-annotation ()
- "Use buffer contents as the annotation for a bookmark.
-Exclude lines that begin with `#'.
-Store the annotation text in the bookmark list with
-the bookmark (and file, and point) specified in buffer local variables."
- (interactive)
- (if (not (eq major-mode 'bookmark-read-annotation-mode))
- (error "Not in bookmark-read-annotation-mode"))
- (goto-char (point-min))
- (while (< (point) (point-max))
- (if (looking-at "^#")
- (bookmark-kill-line t)
- (forward-line 1)))
- (let ((annotation (buffer-substring (point-min) (point-max)))
- (parg bookmark-annotation-paragraph)
- (bookmark bookmark-annotation-name)
- (pt bookmark-annotation-point)
- (buf bookmark-annotation-buffer))
- ;; for bookmark-make-cell to work, we need to be
- ;; in the relevant buffer, at the relevant point.
- ;; Actually, bookmark-make-cell should probably be re-written,
- ;; to avoid this need. Should I handle the error if a buffer is
- ;; killed between "C-x r m" and a "C-c C-c" in the annotation buffer?
- (save-excursion
- (pop-to-buffer buf)
- (goto-char pt)
- (bookmark-make bookmark annotation parg (bookmark-info-current-node))
- (setq bookmark-current-bookmark bookmark))
- (bookmark-bmenu-surreptitiously-rebuild-list)
- (goto-char bookmark-current-point))
- (kill-buffer (current-buffer)))
-
-
-(defun bookmark-default-annotation-text (bookmark)
- (concat "# Type the annotation for bookmark '" bookmark "' here.\n"
- "# All lines which start with a '#' will be deleted.\n"
- "# Type C-c C-c when done.\n#\n"
- "# Author: " (user-full-name) " <" (user-login-name) "@"
- (system-name) ">\n"
- "# Date: " (current-time-string) "\n"))
-
-
-(defvar bookmark-read-annotation-text-func 'bookmark-default-annotation-text
- "Function to return default text to use for a bookmark annotation.
-It takes the name of the bookmark, as a string, as an arg.")
-
-(defun bookmark-read-annotation-mode (buf point parg bookmark)
- "Mode for composing annotations for a bookmark.
-Wants BUF POINT PARG and BOOKMARK.
-When you have finished composing, type \\[bookmark-send-annotation] to send
-the annotation.
-
-\\{bookmark-read-annotation-mode-map}
-"
- (interactive)
- (kill-all-local-variables)
- (make-local-variable 'bookmark-annotation-paragraph)
- (make-local-variable 'bookmark-annotation-name)
- (make-local-variable 'bookmark-annotation-buffer)
- (make-local-variable 'bookmark-annotation-file)
- (make-local-variable 'bookmark-annotation-point)
- (setq bookmark-annotation-paragraph parg)
- (setq bookmark-annotation-name bookmark)
- (setq bookmark-annotation-buffer buf)
- (setq bookmark-annotation-file (buffer-file-name buf))
- (setq bookmark-annotation-point point)
- (use-local-map bookmark-read-annotation-mode-map)
- (setq major-mode 'bookmark-read-annotation-mode)
- (insert (funcall bookmark-read-annotation-text-func bookmark))
- (run-hooks 'text-mode-hook))
-
-
-(defun bookmark-read-annotation (parg bookmark)
- "Pop up a buffer for entering a bookmark annotation.
-Text surrounding the bookmark is PARG; the bookmark name is BOOKMARK."
- (let ((buf (current-buffer))
- (point (point)))
- (pop-to-buffer (generate-new-buffer-name "*Bookmark Annotation Compose*"))
- (bookmark-read-annotation-mode buf point parg bookmark)))
-
-
-(defvar bookmark-edit-annotation-mode-map (copy-keymap text-mode-map)
- "Keymap for editing an annotation of a bookmark.")
-
-
-(define-key bookmark-edit-annotation-mode-map "\C-c\C-c"
- 'bookmark-send-edited-annotation)
-
-
-(defun bookmark-edit-annotation-mode (bookmark)
- "Mode for editing the annotation of bookmark BOOKMARK.
-When you have finished composing, type \\[bookmark-send-annotation].
-
-\\{bookmark-edit-annotation-mode-map}
-"
- (interactive)
- (kill-all-local-variables)
- (make-local-variable 'bookmark-annotation-name)
- (setq bookmark-annotation-name bookmark)
- (use-local-map bookmark-edit-annotation-mode-map)
- (setq major-mode 'bookmark-edit-annotation-mode)
- (insert (funcall bookmark-read-annotation-text-func bookmark))
- (let ((annotation (bookmark-get-annotation bookmark)))
- (if (and (not (eq annotation nil))
- (not (string-equal annotation "")))
- (insert annotation)))
- (run-hooks 'text-mode-hook))
-
-
-(defun bookmark-send-edited-annotation ()
- "Use buffer contents (minus beginning with `#' as annotation for a bookmark."
- (interactive)
- (if (not (eq major-mode 'bookmark-edit-annotation-mode))
- (error "Not in bookmark-edit-annotation-mode"))
- (goto-char (point-min))
- (while (< (point) (point-max))
- (if (looking-at "^#")
- (bookmark-kill-line t)
- (forward-line 1)))
- (let ((annotation (buffer-substring (point-min) (point-max)))
- (bookmark bookmark-annotation-name))
- (bookmark-set-annotation bookmark annotation)
- (bookmark-bmenu-surreptitiously-rebuild-list)
- (goto-char bookmark-current-point))
- (kill-buffer (current-buffer)))
-
-
-(defun bookmark-edit-annotation (bookmark)
- "Pop up a buffer for editing bookmark BOOKMARK's annotation."
- (let ((buf (current-buffer))
- (point (point)))
- (pop-to-buffer (generate-new-buffer-name "*Bookmark Annotation Compose*"))
- (bookmark-edit-annotation-mode bookmark)))
-
-
-(defun bookmark-insert-current-bookmark ()
- "Insert this buffer's value of bookmark-current-bookmark.
-Default to file name if it's nil."
- (interactive)
- (let ((str
- (save-excursion
- (set-buffer bookmark-current-buffer)
- bookmark-current-bookmark)))
- (if str (insert str) (bookmark-insert-buffer-name))))
-
-
-(defun bookmark-insert-buffer-name ()
- "Insert the current file name into the bookmark name being set.
-The directory part of the file name is not used."
- (interactive)
- (let ((str
- (save-excursion
- (set-buffer bookmark-current-buffer)
- (bookmark-buffer-name))))
- (insert str)))
-
-
-(defun bookmark-buffer-name ()
- "Return the name of the current buffer's file, non-directory.
-In Info, return the current node."
- (cond
- ;; Are we in Info?
- ((string-equal mode-name "Info") Info-current-node)
- ;; Or are we a file?
- (buffer-file-name (file-name-nondirectory buffer-file-name))
- ;; Or are we a directory?
- ((and (boundp 'dired-directory) dired-directory)
- (let* ((dirname (if (stringp dired-directory)
- dired-directory
- (car dired-directory)))
- (idx (1- (length dirname))))
- ;; Strip the trailing slash.
- (if (= ?/ (aref dirname idx))
- (file-name-nondirectory (substring dirname 0 idx))
- ;; Else return the current-buffer
- (buffer-name (current-buffer)))))
- ;; If all else fails, use the buffer's name.
- (t
- (buffer-name (current-buffer)))))
-
-
-(defun bookmark-yank-word ()
- (interactive)
- ;; get the next word from the buffer and append it to the name of
- ;; the bookmark currently being set.
- (let ((string (save-excursion
- (set-buffer bookmark-current-buffer)
- (goto-char bookmark-yank-point)
- (buffer-substring-no-properties
- (point)
- (save-excursion
- (forward-word 1)
- (setq bookmark-yank-point (point)))))))
- (insert string)))
-
-
-(defun bookmark-buffer-file-name ()
- "Return the current buffer's file in a way useful for bookmarks.
-For example, if this is a Info buffer, return the Info file's name."
- (if (eq major-mode 'Info-mode)
- Info-current-file
- (or
- buffer-file-name
- (if (and (boundp 'dired-directory) dired-directory)
- (if (stringp dired-directory)
- dired-directory
- (car dired-directory))))))
-
-
-(defun bookmark-maybe-load-default-file ()
- (and (not bookmarks-already-loaded)
- (null bookmark-alist)
- (prog2
- (and
- ;; Possibly the old bookmark file, "~/.emacs-bkmrks", needs
- ;; to be renamed.
- (file-exists-p (expand-file-name bookmark-old-default-file))
- (not (file-exists-p (expand-file-name bookmark-default-file)))
- (rename-file (expand-file-name bookmark-old-default-file)
- (expand-file-name bookmark-default-file)))
- ;; return t so the `and' will continue...
- t)
-
- (file-readable-p (expand-file-name bookmark-default-file))
- (progn
- (bookmark-load bookmark-default-file t t)
- (setq bookmarks-already-loaded t))))
-
-
-(defun bookmark-maybe-sort-alist ()
- ;;Return the bookmark-alist for display. If the bookmark-sort-flag
- ;;is non-nil, then return a sorted copy of the alist.
- (if bookmark-sort-flag
- (setq bookmark-alist
- (sort (copy-alist bookmark-alist)
- (function
- (lambda (x y) (string-lessp (car x) (car y))))))))
-
-
-;;;###autoload
-(defun bookmark-jump (bookmark)
- "Jump to bookmark BOOKMARK (a point in some file).
-You may have a problem using this function if the value of variable
-`bookmark-alist' is nil. If that happens, you need to load in some
-bookmarks. See help on function `bookmark-load' for more about
-this.
-
-If the file pointed to by BOOKMARK no longer exists, you will be asked
-if you wish to give the bookmark a new location, and bookmark-jump
-will then jump to the new location, as well as recording it in place
-of the old one in the permanent bookmark record."
- (interactive
- (bookmark-completing-read "Jump to bookmark" bookmark-current-bookmark))
- (bookmark-maybe-historicize-string bookmark)
- (let ((cell (bookmark-jump-noselect bookmark)))
- (and cell
- (switch-to-buffer (car cell))
- (goto-char (cdr cell))
- (if bookmark-automatically-show-annotations
- ;; if there is an annotation for this bookmark,
- ;; show it in a buffer.
- (bookmark-show-annotation bookmark)))))
-
-
-(defun bookmark-jump-noselect (str)
- ;; a leetle helper for bookmark-jump :-)
- ;; returns (BUFFER . POINT)
- (bookmark-maybe-load-default-file)
- (let* ((file (expand-file-name (bookmark-get-filename str)))
- (forward-str (bookmark-get-front-context-string str))
- (behind-str (bookmark-get-rear-context-string str))
- (place (bookmark-get-position str))
- (info-node (bookmark-get-info-node str))
- (orig-file file)
- )
- (if (or
- (file-exists-p file)
- ;; else try some common compression extensions
- ;; and Emacs better handle it right!
- ;; Sigh: I think it may *not* be handled at the moment. What
- ;; to do about this?
- (setq file
- (or
- (let ((altname (concat file ".Z")))
- (and (file-exists-p altname)
- altname))
- (let ((altname (concat file ".gz")))
- (and (file-exists-p altname)
- altname))
- (let ((altname (concat file ".z")))
- (and (file-exists-p altname)
- altname)))))
- (save-excursion
- (if info-node
- ;; Info nodes must be visited with care.
- (progn
- (require 'info)
- (Info-find-node file info-node))
- ;; Else no Info. Can do an ordinary find-file:
- (set-buffer (find-file-noselect file))
- (goto-char place))
-
- ;; Go searching forward first. Then, if forward-str exists and
- ;; was found in the file, we can search backward for behind-str.
- ;; Rationale is that if text was inserted between the two in the
- ;; file, it's better to be put before it so you can read it,
- ;; rather than after and remain perhaps unaware of the changes.
- (if forward-str
- (if (search-forward forward-str (point-max) t)
- (backward-char (length forward-str))))
- (if behind-str
- (if (search-backward behind-str (point-min) t)
- (forward-char (length behind-str))))
- ;; added by db
- (setq bookmark-current-bookmark str)
- (cons (current-buffer) (point)))
- (progn
- (ding)
- (if (y-or-n-p (concat (file-name-nondirectory orig-file)
- " nonexistent. Relocate \""
- str
- "\"? "))
- (progn
- (bookmark-relocate str)
- ;; gasp! It's a recursive function call in Emacs Lisp!
- (bookmark-jump-noselect str))
- (message
- "Bookmark not relocated; consider removing it \(%s\)." str)
- nil)))))
-
-
-;;;###autoload
-(defun bookmark-relocate (bookmark)
- "Relocate BOOKMARK to another file (reading file name with minibuffer).
-This makes an already existing bookmark point to that file, instead of
-the one it used to point at. Useful when a file has been renamed
-after a bookmark was set in it."
- (interactive (bookmark-completing-read "Bookmark to relocate"))
- (bookmark-maybe-historicize-string bookmark)
- (bookmark-maybe-load-default-file)
- (let* ((bmrk-filename (bookmark-get-filename bookmark))
- (newloc (expand-file-name
- (read-file-name
- (format "Relocate %s to: " bookmark)
- (file-name-directory bmrk-filename)))))
- (bookmark-set-filename bookmark newloc)))
-
-
-;;;###autoload
-(defun bookmark-insert-location (bookmark &optional no-history)
- "Insert the name of the file associated with BOOKMARK.
-Optional second arg NO-HISTORY means don't record this in the
-minibuffer history list `bookmark-history'."
- (interactive (bookmark-completing-read "Insert bookmark location"))
- (or no-history (bookmark-maybe-historicize-string bookmark))
- (insert (bookmark-location bookmark)))
-
-;;;###autoload
-(defalias 'bookmark-locate 'bookmark-insert-location)
-
-(defun bookmark-location (bookmark)
- "Return the name of the file associated with BOOKMARK."
- (bookmark-maybe-load-default-file)
- (bookmark-get-filename bookmark))
-
-
-;;;###autoload
-(defun bookmark-rename (old &optional new)
- "Change the name of OLD bookmark to NEW name.
-If called from keyboard, prompt for OLD and NEW. If called from
-menubar, select OLD from a menu and prompt for NEW.
-
-If called from Lisp, prompt for NEW if only OLD was passed as an
-argument. If called with two strings, then no prompting is done. You
-must pass at least OLD when calling from Lisp.
-
-While you are entering the new name, consecutive C-w's insert
-consecutive words from the text of the buffer into the new bookmark
-name."
- (interactive (bookmark-completing-read "Old bookmark name"))
- (bookmark-maybe-historicize-string old)
- (bookmark-maybe-load-default-file)
- (progn
- (setq bookmark-current-point (point))
- (setq bookmark-yank-point (point))
- (setq bookmark-current-buffer (current-buffer))
- (let ((newname
- (or new ; use second arg, if non-nil
- (read-from-minibuffer
- "New name: "
- nil
- (let ((now-map (copy-keymap minibuffer-local-map)))
- (define-key now-map "\C-w" 'bookmark-yank-word)
- now-map)
- nil
- 'bookmark-history))))
- (progn
- (bookmark-set-name old newname)
- (setq bookmark-current-bookmark newname)
- (bookmark-bmenu-surreptitiously-rebuild-list)
- (setq bookmark-alist-modification-count
- (1+ bookmark-alist-modification-count))
- (if (bookmark-time-to-save-p)
- (bookmark-save))))))
-
-
-;;;###autoload
-(defun bookmark-insert (bookmark)
- "Insert the text of the file pointed to by bookmark BOOKMARK.
-You may have a problem using this function if the value of variable
-`bookmark-alist' is nil. If that happens, you need to load in some
-bookmarks. See help on function `bookmark-load' for more about
-this."
- (interactive (bookmark-completing-read "Insert bookmark contents"))
- (bookmark-maybe-historicize-string bookmark)
- (bookmark-maybe-load-default-file)
- (let ((orig-point (point))
- (str-to-insert
- (save-excursion
- (set-buffer (car (bookmark-jump-noselect bookmark)))
- (buffer-substring (point-min) (point-max)))))
- (insert str-to-insert)
- (push-mark)
- (goto-char orig-point)))
-
-
-;;;###autoload
-(defun bookmark-delete (bookmark &optional batch)
- "Delete BOOKMARK from the bookmark list.
-Removes only the first instance of a bookmark with that name. If
-there are one or more other bookmarks with the same name, they will
-not be deleted. Defaults to the \"current\" bookmark \(that is, the
-one most recently used in this file, if any\).
-Optional second arg BATCH means don't update the bookmark list buffer,
-probably because we were called from there."
- (interactive
- (bookmark-completing-read "Delete bookmark" bookmark-current-bookmark))
- (bookmark-maybe-historicize-string bookmark)
- (bookmark-maybe-load-default-file)
- (let ((will-go (bookmark-get-bookmark bookmark)))
- (setq bookmark-alist (delq will-go bookmark-alist))
- ;; Added by db, nil bookmark-current-bookmark if the last
- ;; occurrence has been deleted
- (or (bookmark-get-bookmark bookmark-current-bookmark)
- (setq bookmark-current-bookmark nil)))
- ;; Don't rebuild the list
- (if batch
- nil
- (bookmark-bmenu-surreptitiously-rebuild-list)
- (setq bookmark-alist-modification-count
- (1+ bookmark-alist-modification-count))
- (if (bookmark-time-to-save-p)
- (bookmark-save))))
-
-
-(defun bookmark-time-to-save-p (&optional last-time)
- ;; By Gregory M. Saunders <saunders@cis.ohio-state.edu>
- ;; finds out whether it's time to save bookmarks to a file, by
- ;; examining the value of variable bookmark-save-flag, and maybe
- ;; bookmark-alist-modification-count. Returns t if they should be
- ;; saved, nil otherwise. if last-time is non-nil, then this is
- ;; being called when emacs is killed.
- (cond (last-time
- (and (> bookmark-alist-modification-count 0)
- bookmark-save-flag))
- ((numberp bookmark-save-flag)
- (>= bookmark-alist-modification-count bookmark-save-flag))
- (t
- nil)))
-
-
-;;;###autoload
-(defun bookmark-write ()
- "Write bookmarks to a file (reading the file name with the minibuffer).
-Don't use this in Lisp programs; use `bookmark-save' instead."
- (interactive)
- (bookmark-maybe-load-default-file)
- (bookmark-save t))
-
-
-;;;###autoload
-(defun bookmark-save (&optional parg file)
- "Save currently defined bookmarks.
-Saves by default in the file defined by the variable
-`bookmark-default-file'. With a prefix arg, save it in file FILE
-\(second argument\).
-
-If you are calling this from Lisp, the two arguments are PREFIX-ARG
-and FILE, and if you just want it to write to the default file, then
-pass no arguments. Or pass in nil and FILE, and it will save in FILE
-instead. If you pass in one argument, and it is non-nil, then the
-user will be interactively queried for a file to save in.
-
-When you want to load in the bookmarks from a file, use
-\`bookmark-load\', \\[bookmark-load]. That function will prompt you
-for a file, defaulting to the file defined by variable
-`bookmark-default-file'."
- (interactive "P")
- (bookmark-maybe-load-default-file)
- (cond
- ((and (null parg) (null file))
- ;;whether interactive or not, write to default file
- (bookmark-write-file bookmark-default-file))
- ((and (null parg) file)
- ;;whether interactive or not, write to given file
- (bookmark-write-file file))
- ((and parg (not file))
- ;;have been called interactively w/ prefix arg
- (let ((file (read-file-name "File to save bookmarks in: ")))
- (bookmark-write-file file)))
- (t ; someone called us with prefix-arg *and* a file, so just write to file
- (bookmark-write-file file)))
- ;; signal that we have synced the bookmark file by setting this to
- ;; 0. If there was an error at any point before, it will not get
- ;; set, which is what we want.
- (setq bookmark-alist-modification-count 0))
-
-
-
-(defun bookmark-write-file (file)
- (save-excursion
- (save-window-excursion
- (if (>= baud-rate 9600)
- (message "Saving bookmarks to file %s..." file))
- (set-buffer (let ((enable-local-variables nil))
- (find-file-noselect file)))
- (goto-char (point-min))
- (delete-region (point-min) (point-max))
- (bookmark-insert-file-format-version-stamp)
- (pp bookmark-alist (current-buffer))
- (let ((version-control
- (cond
- ((null bookmark-version-control) nil)
- ((eq 'never bookmark-version-control) 'never)
- ((eq 'nospecial bookmark-version-control) version-control)
- (t
- t))))
- (write-file file)
- (kill-buffer (current-buffer))
- (if (>= baud-rate 9600)
- (message "Saving bookmarks to file %s...done" file))
- ))))
-
-
-;;;###autoload
-(defun bookmark-load (file &optional revert no-msg)
- "Load bookmarks from FILE (which must be in bookmark format).
-Appends loaded bookmarks to the front of the list of bookmarks. If
-optional second argument REVERT is non-nil, existing bookmarks are
-destroyed. Optional third arg NO-MSG means don't display any messages
-while loading.
-
-If you load a file that doesn't contain a proper bookmark alist, you
-will corrupt Emacs's bookmark list. Generally, you should only load
-in files that were created with the bookmark functions in the first
-place. Your own personal bookmark file, `~/.emacs.bmk', is
-maintained automatically by Emacs; you shouldn't need to load it
-explicitly."
- (interactive
- (list (read-file-name
- (format "Load bookmarks from: (%s) "
- bookmark-default-file)
- ;;Default might not be used often,
- ;;but there's no better default, and
- ;;I guess it's better than none at all.
- "~/" bookmark-default-file 'confirm)))
- (setq file (expand-file-name file))
- (if (file-readable-p file)
- (save-excursion
- (save-window-excursion
- (if (and (null no-msg) (>= baud-rate 9600))
- (message "Loading bookmarks from %s..." file))
- (set-buffer (let ((enable-local-variables nil))
- (find-file-noselect file)))
- (goto-char (point-min))
- (bookmark-maybe-upgrade-file-format)
- (let ((blist (bookmark-alist-from-buffer)))
- (if (listp blist)
- (progn
- (if (not revert)
- (setq bookmark-alist-modification-count
- (1+ bookmark-alist-modification-count))
- (setq bookmark-alist-modification-count 0))
- (setq bookmark-alist
- (append blist (if (not revert) bookmark-alist)))
- (bookmark-bmenu-surreptitiously-rebuild-list))
- (error "Invalid bookmark list in %s" file)))
- (kill-buffer (current-buffer)))
- (if (and (null no-msg) (>= baud-rate 9600))
- (message "Loading bookmarks from %s...done" file)))
- (error "Cannot read bookmark file %s" file)))
-
-
-
-;;; Code supporting the dired-like bookmark menu. Prefix is
-;;; "bookmark-bmenu" for "buffer-menu":
-
-
-(defvar bookmark-bmenu-bookmark-column nil)
-
-
-(defvar bookmark-bmenu-hidden-bookmarks ())
-
-
-(defvar bookmark-bmenu-mode-map nil)
-
-
-(if bookmark-bmenu-mode-map
- nil
- (setq bookmark-bmenu-mode-map (make-keymap))
- (suppress-keymap bookmark-bmenu-mode-map t)
- (define-key bookmark-bmenu-mode-map "q" 'bookmark-bmenu-quit)
- (define-key bookmark-bmenu-mode-map "v" 'bookmark-bmenu-select)
- (define-key bookmark-bmenu-mode-map "w" 'bookmark-bmenu-locate)
- (define-key bookmark-bmenu-mode-map "2" 'bookmark-bmenu-2-window)
- (define-key bookmark-bmenu-mode-map "1" 'bookmark-bmenu-1-window)
- (define-key bookmark-bmenu-mode-map "j" 'bookmark-bmenu-this-window)
- (define-key bookmark-bmenu-mode-map "\C-c\C-c" 'bookmark-bmenu-this-window)
- (define-key bookmark-bmenu-mode-map "f" 'bookmark-bmenu-this-window)
- (define-key bookmark-bmenu-mode-map "o" 'bookmark-bmenu-other-window)
- (define-key bookmark-bmenu-mode-map "\C-o"
- 'bookmark-bmenu-switch-other-window)
- (define-key bookmark-bmenu-mode-map "s" 'bookmark-bmenu-save)
- (define-key bookmark-bmenu-mode-map "k" 'bookmark-bmenu-delete)
- (define-key bookmark-bmenu-mode-map "\C-d" 'bookmark-bmenu-delete-backwards)
- (define-key bookmark-bmenu-mode-map "x" 'bookmark-bmenu-execute-deletions)
- (define-key bookmark-bmenu-mode-map "d" 'bookmark-bmenu-delete)
- (define-key bookmark-bmenu-mode-map " " 'next-line)
- (define-key bookmark-bmenu-mode-map "n" 'next-line)
- (define-key bookmark-bmenu-mode-map "p" 'previous-line)
- (define-key bookmark-bmenu-mode-map "\177" 'bookmark-bmenu-backup-unmark)
- (define-key bookmark-bmenu-mode-map "?" 'describe-mode)
- (define-key bookmark-bmenu-mode-map "u" 'bookmark-bmenu-unmark)
- (define-key bookmark-bmenu-mode-map "m" 'bookmark-bmenu-mark)
- (define-key bookmark-bmenu-mode-map "l" 'bookmark-bmenu-load)
- (define-key bookmark-bmenu-mode-map "r" 'bookmark-bmenu-rename)
- (define-key bookmark-bmenu-mode-map "t" 'bookmark-bmenu-toggle-filenames)
- (define-key bookmark-bmenu-mode-map "a" 'bookmark-bmenu-show-annotation)
- (define-key bookmark-bmenu-mode-map "A" 'bookmark-bmenu-show-all-annotations)
- (define-key bookmark-bmenu-mode-map "e" 'bookmark-bmenu-edit-annotation))
-
-
-
-;; Bookmark Buffer Menu mode is suitable only for specially formatted
-;; data.
-(put 'bookmark-bmenu-mode 'mode-class 'special)
-
-
-;; todo: need to display whether or not bookmark exists as a buffer in
-;; flag column.
-
-;; Format:
-;; FLAGS BOOKMARK [ LOCATION ]
-
-
-(defun bookmark-bmenu-surreptitiously-rebuild-list ()
- "Rebuild the Bookmark List if it exists.
-Don't affect the buffer ring order."
- (if (get-buffer "*Bookmark List*")
- (save-excursion
- (save-window-excursion
- (bookmark-bmenu-list)))))
-
-
-;;;###autoload
-(defun bookmark-bmenu-list ()
- "Display a list of existing bookmarks.
-The list is displayed in a buffer named `*Bookmark List*'.
-The leftmost column displays a D if the bookmark is flagged for
-deletion, or > if it is flagged for displaying."
- (interactive)
- (bookmark-maybe-load-default-file)
- (if (interactive-p)
- (switch-to-buffer (get-buffer-create "*Bookmark List*"))
- (set-buffer (get-buffer-create "*Bookmark List*")))
- (let ((buffer-read-only nil))
- (delete-region (point-max) (point-min))
- (goto-char (point-min)) ;sure are playing it safe...
- (insert "% Bookmark\n- --------\n")
- (bookmark-maybe-sort-alist)
- (mapcar
- (lambda (full-record)
- ;; if a bookmark has an annotation, prepend a "*"
- ;; in the list of bookmarks.
- (let ((annotation (bookmark-get-annotation
- (bookmark-name-from-full-record full-record))))
- (if (and (not (eq annotation nil))
- (not (string-equal annotation "")))
- (insert " *")
- (insert " "))
- (insert (concat (bookmark-name-from-full-record full-record) "\n"))))
- bookmark-alist))
- (goto-char (point-min))
- (forward-line 2)
- (bookmark-bmenu-mode)
- (if bookmark-bmenu-toggle-filenames
- (bookmark-bmenu-toggle-filenames t)))
-
-;;;###autoload
-(defalias 'list-bookmarks 'bookmark-bmenu-list)
-;;;###autoload
-(defalias 'edit-bookmarks 'bookmark-bmenu-list)
-
-
-
-(defun bookmark-bmenu-mode ()
- "Major mode for editing a list of bookmarks.
-Each line describes one of the bookmarks in Emacs.
-Letters do not insert themselves; instead, they are commands.
-Bookmark names preceded by a \"*\" have annotations.
-\\<bookmark-bmenu-mode-map>
-\\[bookmark-bmenu-mark] -- mark bookmark to be displayed.
-\\[bookmark-bmenu-select] -- select bookmark of line point is on.
- Also show bookmarks marked using m in other windows.
-\\[bookmark-bmenu-toggle-filenames] -- toggle displaying of filenames (they may obscure long bookmark names).
-\\[bookmark-bmenu-locate] -- display (in minibuffer) location of this bookmark.
-\\[bookmark-bmenu-1-window] -- select this bookmark in full-frame window.
-\\[bookmark-bmenu-2-window] -- select this bookmark in one window,
- together with bookmark selected before this one in another window.
-\\[bookmark-bmenu-this-window] -- select this bookmark in place of the bookmark menu buffer.
-\\[bookmark-bmenu-other-window] -- select this bookmark in another window,
- so the bookmark menu bookmark remains visible in its window.
-\\[bookmark-bmenu-switch-other-window] -- switch the other window to this bookmark.
-\\[bookmark-bmenu-rename] -- rename this bookmark \(prompts for new name\).
-\\[bookmark-bmenu-delete] -- mark this bookmark to be deleted, and move down.
-\\[bookmark-bmenu-delete-backwards] -- mark this bookmark to be deleted, and move up.
-\\[bookmark-bmenu-execute-deletions] -- delete bookmarks marked with `\\[bookmark-bmenu-delete]'.
-\\[bookmark-bmenu-save] -- save the current bookmark list in the default file.
- With a prefix arg, prompts for a file to save in.
-\\[bookmark-bmenu-load] -- load in a file of bookmarks (prompts for file.)
-\\[bookmark-bmenu-unmark] -- remove all kinds of marks from current line.
- With prefix argument, also move up one line.
-\\[bookmark-bmenu-backup-unmark] -- back up a line and remove marks.
-\\[bookmark-bmenu-show-annotation] -- show the annotation, if it exists, for the current bookmark
- in another buffer.
-\\[bookmark-bmenu-show-all-annotations] -- show the annotations of all bookmarks in another buffer.
-\\[bookmark-bmenu-edit-annotation] -- edit the annotation for the current bookmark."
- (kill-all-local-variables)
- (use-local-map bookmark-bmenu-mode-map)
- (setq truncate-lines t)
- (setq buffer-read-only t)
- (setq major-mode 'bookmark-bmenu-mode)
- (setq mode-name "Bookmark Menu")
- (run-hooks 'bookmark-bmenu-mode-hook))
-
-
-(defun bookmark-bmenu-toggle-filenames (&optional show)
- "Toggle whether filenames are shown in the bookmark list.
-Optional argument SHOW means show them unconditionally."
- (interactive)
- (cond
- (show
- (setq bookmark-bmenu-toggle-filenames nil)
- (bookmark-bmenu-show-filenames)
- (setq bookmark-bmenu-toggle-filenames t))
- (bookmark-bmenu-toggle-filenames
- (bookmark-bmenu-hide-filenames)
- (setq bookmark-bmenu-toggle-filenames nil))
- (t
- (bookmark-bmenu-show-filenames)
- (setq bookmark-bmenu-toggle-filenames t))))
-
-
-(defun bookmark-bmenu-show-filenames (&optional force)
- (if (and (not force) bookmark-bmenu-toggle-filenames)
- nil ;already shown, so do nothing
- (save-excursion
- (save-window-excursion
- (goto-char (point-min))
- (forward-line 2)
- (setq bookmark-bmenu-hidden-bookmarks ())
- (let ((buffer-read-only nil))
- (while (< (point) (point-max))
- (let ((bmrk (bookmark-bmenu-bookmark)))
- (setq bookmark-bmenu-hidden-bookmarks
- (cons bmrk bookmark-bmenu-hidden-bookmarks))
- (move-to-column bookmark-bmenu-file-column t)
- (delete-region (point) (progn (end-of-line) (point)))
- (insert " ")
- ;; Pass the NO-HISTORY arg:
- (bookmark-insert-location bmrk t)
- (forward-line 1))))))))
-
-
-(defun bookmark-bmenu-hide-filenames (&optional force)
- (if (and (not force) bookmark-bmenu-toggle-filenames)
- ;; nothing to hide if above is nil
- (save-excursion
- (save-window-excursion
- (goto-char (point-min))
- (forward-line 2)
- (setq bookmark-bmenu-hidden-bookmarks
- (nreverse bookmark-bmenu-hidden-bookmarks))
- (save-excursion
- (goto-char (point-min))
- (search-forward "Bookmark")
- (backward-word 1)
- (setq bookmark-bmenu-bookmark-column (current-column)))
- (save-excursion
- (let ((buffer-read-only nil))
- (while bookmark-bmenu-hidden-bookmarks
- (move-to-column bookmark-bmenu-bookmark-column t)
- (bookmark-kill-line)
- (insert (car bookmark-bmenu-hidden-bookmarks))
- (setq bookmark-bmenu-hidden-bookmarks
- (cdr bookmark-bmenu-hidden-bookmarks))
- (forward-line 1))))))))
-
-
-;; if you look at this next function from far away, it resembles a
-;; gun. But only with this comment above...
-(defun bookmark-bmenu-check-position ()
- ;; Returns t if on a line with a bookmark.
- ;; Otherwise, repositions and returns t.
- ;; written by David Hughes <djh@harston.cv.com>
- ;; Mucho thanks, David! -karl
- (cond ((< (count-lines (point-min) (point)) 2)
- (goto-char (point-min))
- (forward-line 2)
- t)
- ((and (bolp) (eobp))
- (beginning-of-line 0)
- t)
- (t
- t)))
-
-
-(defun bookmark-bmenu-bookmark ()
- ;; return a string which is bookmark of this line.
- (if (bookmark-bmenu-check-position)
- (save-excursion
- (save-window-excursion
- (goto-char (point-min))
- (search-forward "Bookmark")
- (backward-word 1)
- (setq bookmark-bmenu-bookmark-column (current-column)))))
- (if bookmark-bmenu-toggle-filenames
- (bookmark-bmenu-hide-filenames))
- (save-excursion
- (save-window-excursion
- (beginning-of-line)
- (forward-char bookmark-bmenu-bookmark-column)
- (prog1
- (buffer-substring (point)
- (progn
- (end-of-line)
- (point)))
- ;; well, this is certainly crystal-clear:
- (if bookmark-bmenu-toggle-filenames
- (bookmark-bmenu-toggle-filenames t))))))
-
-
-(defun bookmark-show-annotation (bookmark)
- "Display the annotation for bookmark named BOOKMARK in a buffer,
-if an annotation exists."
- (let ((annotation (bookmark-get-annotation bookmark)))
- (if (and (not (eq annotation nil))
- (not (string-equal annotation "")))
- (progn
- (save-excursion
- (let ((old-buf (current-buffer)))
- (pop-to-buffer (get-buffer-create "*Bookmark Annotation*") t)
- (delete-region (point-min) (point-max))
- ; (insert (concat "Annotation for bookmark '" bookmark "':\n\n"))
- (insert annotation)
- (goto-char (point-min))
- (pop-to-buffer old-buf)))))))
-
-
-(defun bookmark-show-all-annotations ()
- "Display the annotations for all bookmarks in a buffer."
- (let ((old-buf (current-buffer)))
- (pop-to-buffer (get-buffer-create "*Bookmark Annotation*") t)
- (delete-region (point-min) (point-max))
- (mapcar
- (lambda (full-record)
- (let* ((name (bookmark-name-from-full-record full-record))
- (ann (bookmark-get-annotation name)))
- (insert (concat name ":\n"))
- (if (and (not (eq ann nil)) (not (string-equal ann "")))
- ;; insert the annotation, indented by 4 spaces.
- (progn
- (save-excursion (insert ann))
- (while (< (point) (point-max))
- (beginning-of-line) ; paranoia
- (insert " ")
- (forward-line)
- (end-of-line))))))
- bookmark-alist)
- (goto-char (point-min))
- (pop-to-buffer old-buf)))
-
-
-(defun bookmark-bmenu-mark ()
- "Mark bookmark on this line to be displayed by \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-select]."
- (interactive)
- (beginning-of-line)
- (if (bookmark-bmenu-check-position)
- (let ((buffer-read-only nil))
- (delete-char 1)
- (insert ?>)
- (forward-line 1))))
-
-
-(defun bookmark-bmenu-select ()
- "Select this line's bookmark; also display bookmarks marked with `>'.
-You can mark bookmarks with the \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-mark] command."
- (interactive)
- (if (bookmark-bmenu-check-position)
- (let ((bmrk (bookmark-bmenu-bookmark))
- (menu (current-buffer))
- (others ())
- tem)
- (goto-char (point-min))
- (while (re-search-forward "^>" nil t)
- (setq tem (bookmark-bmenu-bookmark))
- (let ((buffer-read-only nil))
- (delete-char -1)
- (insert ?\ ))
- (or (string-equal tem bmrk)
- (member tem others)
- (setq others (cons tem others))))
- (setq others (nreverse others)
- tem (/ (1- (frame-height)) (1+ (length others))))
- (delete-other-windows)
- (bookmark-jump bmrk)
- (bury-buffer menu)
- (if others
- (while others
- (split-window nil tem)
- (other-window 1)
- (bookmark-jump (car others))
- (setq others (cdr others)))
- (other-window 1)))))
-
-
-(defun bookmark-bmenu-save (parg)
- "Save the current list into a bookmark file.
-With a prefix arg, prompts for a file to save them in."
- (interactive "P")
- (save-excursion
- (save-window-excursion
- (bookmark-save parg))))
-
-
-(defun bookmark-bmenu-load ()
- "Load the bookmark file and rebuild the bookmark menu-buffer."
- (interactive)
- (if (bookmark-bmenu-check-position)
- (save-excursion
- (save-window-excursion
- ;; This will call `bookmark-bmenu-list'
- (call-interactively 'bookmark-load)))))
-
-
-(defun bookmark-bmenu-1-window ()
- "Select this line's bookmark, alone, in full frame."
- (interactive)
- (if (bookmark-bmenu-check-position)
- (progn
- (bookmark-jump (bookmark-bmenu-bookmark))
- (bury-buffer (other-buffer))
- (delete-other-windows))))
-
-
-(defun bookmark-bmenu-2-window ()
- "Select this line's bookmark, with previous buffer in second window."
- (interactive)
- (if (bookmark-bmenu-check-position)
- (let ((bmrk (bookmark-bmenu-bookmark))
- (menu (current-buffer))
- (pop-up-windows t))
- (delete-other-windows)
- (switch-to-buffer (other-buffer))
- (let* ((pair (bookmark-jump-noselect bmrk))
- (buff (car pair))
- (pos (cdr pair)))
- (pop-to-buffer buff)
- (goto-char pos))
- (bury-buffer menu))))
-
-
-(defun bookmark-bmenu-this-window ()
- "Select this line's bookmark in this window."
- (interactive)
- (if (bookmark-bmenu-check-position)
- (bookmark-jump (bookmark-bmenu-bookmark))))
-
-
-(defun bookmark-bmenu-other-window ()
- "Select this line's bookmark in other window, leaving bookmark menu visible."
- (interactive)
- (let ((bookmark (bookmark-bmenu-bookmark)))
- (if (bookmark-bmenu-check-position)
- (let* ((pair (bookmark-jump-noselect bookmark))
- (buff (car pair))
- (pos (cdr pair)))
- (switch-to-buffer-other-window buff)
- (goto-char pos)
- (set-window-point (get-buffer-window buff) pos)
- (bookmark-show-annotation bookmark)))))
-
-
-(defun bookmark-bmenu-switch-other-window ()
- "Make the other window select this line's bookmark.
-The current window remains selected."
- (interactive)
- (let ((bookmark (bookmark-bmenu-bookmark)))
- (if (bookmark-bmenu-check-position)
- (let* ((pair (bookmark-jump-noselect bookmark))
- (buff (car pair))
- (pos (cdr pair)))
- (display-buffer buff)
- (let ((o-buffer (current-buffer)))
- ;; save-excursion won't do
- (set-buffer buff)
- (goto-char pos)
- (set-window-point (get-buffer-window buff) pos)
- (set-buffer o-buffer))
- (bookmark-show-annotation bookmark)))))
-
-
-(defun bookmark-bmenu-show-annotation ()
- "Show the annotation for the current bookmark in another window."
- (interactive)
- (let ((bookmark (bookmark-bmenu-bookmark)))
- (if (bookmark-bmenu-check-position)
- (bookmark-show-annotation bookmark))))
-
-
-(defun bookmark-bmenu-show-all-annotations ()
- "Show the annotation for all bookmarks in another window."
- (interactive)
- (bookmark-show-all-annotations))
-
-
-(defun bookmark-bmenu-edit-annotation ()
- "Edit the annotation for the current bookmark in another window."
- (interactive)
- (let ((bookmark (bookmark-bmenu-bookmark)))
- (if (bookmark-bmenu-check-position)
- (bookmark-edit-annotation bookmark))))
-
-
-(defun bookmark-bmenu-quit ()
- "Quit the bookmark menu."
- (interactive)
- (let ((buffer (current-buffer)))
- (switch-to-buffer (other-buffer))
- (bury-buffer buffer)))
-
-
-(defun bookmark-bmenu-unmark (&optional backup)
- "Cancel all requested operations on bookmark on this line and move down.
-Optional BACKUP means move up."
- (interactive "P")
- (beginning-of-line)
- (if (bookmark-bmenu-check-position)
- (progn
- (let ((buffer-read-only nil))
- (delete-char 1)
- ;; any flags to reset according to circumstances? How about a
- ;; flag indicating whether this bookmark is being visited?
- ;; well, we don't have this now, so maybe later.
- (insert " "))
- (forward-line (if backup -1 1)))))
-
-
-(defun bookmark-bmenu-backup-unmark ()
- "Move up and cancel all requested operations on bookmark on line above."
- (interactive)
- (forward-line -1)
- (if (bookmark-bmenu-check-position)
- (progn
- (bookmark-bmenu-unmark)
- (forward-line -1))))
-
-
-(defun bookmark-bmenu-delete ()
- "Mark bookmark on this line to be deleted.
-To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-execute-deletions]."
- (interactive)
- (beginning-of-line)
- (if (bookmark-bmenu-check-position)
- (let ((buffer-read-only nil))
- (delete-char 1)
- (insert ?D)
- (forward-line 1))))
-
-
-(defun bookmark-bmenu-delete-backwards ()
- "Mark bookmark on this line to be deleted, then move up one line.
-To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-execute-deletions]."
- (interactive)
- (bookmark-bmenu-delete)
- (forward-line -2)
- (if (bookmark-bmenu-check-position)
- (forward-line 1)))
-
-
-(defun bookmark-bmenu-execute-deletions ()
- "Delete bookmarks marked with \\<Buffer-menu-mode-map>\\[Buffer-menu-delete] commands."
- (interactive)
- (message "Deleting bookmarks...")
- (let ((hide-em bookmark-bmenu-toggle-filenames)
- (o-point (point))
- (o-str (save-excursion
- (beginning-of-line)
- (if (looking-at "^D")
- nil
- (buffer-substring
- (point)
- (progn (end-of-line) (point))))))
- (o-col (current-column)))
- (if hide-em (bookmark-bmenu-hide-filenames))
- (setq bookmark-bmenu-toggle-filenames nil)
- (goto-char (point-min))
- (forward-line 1)
- (while (re-search-forward "^D" (point-max) t)
- (bookmark-delete (bookmark-bmenu-bookmark) t)) ; pass BATCH arg
- (bookmark-bmenu-list)
- (setq bookmark-bmenu-toggle-filenames hide-em)
- (if bookmark-bmenu-toggle-filenames
- (bookmark-bmenu-toggle-filenames t))
- (if o-str
- (progn
- (goto-char (point-min))
- (search-forward o-str)
- (beginning-of-line)
- (forward-char o-col))
- (goto-char o-point))
- (beginning-of-line)
- (setq bookmark-alist-modification-count
- (1+ bookmark-alist-modification-count))
- (if (bookmark-time-to-save-p)
- (bookmark-save))
- (message "Deleting bookmarks...done")
- ))
-
-
-(defun bookmark-bmenu-rename ()
- "Rename bookmark on current line. Prompts for a new name."
- (interactive)
- (if (bookmark-bmenu-check-position)
- (let ((bmrk (bookmark-bmenu-bookmark))
- (thispoint (point)))
- (bookmark-rename bmrk)
- (bookmark-bmenu-list)
- (goto-char thispoint))))
-
-
-(defun bookmark-bmenu-locate ()
- "Display location of this bookmark. Displays in the minibuffer."
- (interactive)
- (if (bookmark-bmenu-check-position)
- (let ((bmrk (bookmark-bmenu-bookmark)))
- (message (bookmark-location bmrk)))))
-
-
-
-;;; Menu bar stuff. Prefix is "bookmark-menu".
-
-(defun bookmark-menu-build-paned-menu (name entries)
- "Build a multi-paned menu named NAME from the strings in ENTRIES.
-That is, ENTRIES is a list of strings which appear as the choices
-in the menu. The number of panes depends on the number of entries.
-The visible entries are truncated to `bookmark-menu-length', but the
-strings returned are not."
- (let* ((f-height (/ (frame-height) 2))
- (pane-list
- (let (temp-pane-list
- (iter 0))
- (while entries
- (let (lst
- (count 0))
- (while (and (< count f-height) entries)
- (let ((str (car entries)))
- (setq lst (cons
- (cons
- (if (> (length str) bookmark-menu-length)
- (substring str 0 bookmark-menu-length)
- str)
- str)
- lst))
- (setq entries (cdr entries))
- (setq count (1+ count))))
- (setq iter (1+ iter))
- (setq
- temp-pane-list
- (cons
- (cons
- (format "-*- %s (%d) -*-" name iter)
- (nreverse lst))
- temp-pane-list))))
- (nreverse temp-pane-list))))
-
- ;; Return the menu:
- (cons (concat "-*- " name " -*-") pane-list)))
-
-
-(defun bookmark-build-xemacs-menu (name entries function)
- "Build a menu named NAME from the strings in ENTRIES.
-That is, ENTRIES is a list of strings that appear as the choices
-in the menu.
-The visible entries are truncated to `bookmark-menu-length', but the
-strings returned are not."
- (let* (lst
- (pane-list
- (progn
- (while entries
- (let ((str (car entries)))
- (setq lst (cons
- (vector
- (if (> (length str) bookmark-menu-length)
- (substring str 0 bookmark-menu-length)
- str)
- (list function str)
- t)
- lst))
- (setq entries (cdr entries))))
- (nreverse lst))))
-
- ;; Return the menu:
- (append (if popup-menu-titles (list (concat "-*- " name " -*-")))
- pane-list)))
-
-
-(defun bookmark-menu-popup-paned-menu (event name entries)
- "Pop up multi-paned menu at EVENT, return string chosen from ENTRIES.
-That is, ENTRIES is a list of strings which appear as the choices
-in the menu.
-The number of panes depends on the number of entries."
- (interactive "e")
- (x-popup-menu event (bookmark-menu-build-paned-menu name entries)))
-
-
-(defun bookmark-menu-popup-paned-bookmark-menu (event name)
- "Pop up menu of bookmarks, return chosen bookmark.
-Pop up at EVENT, menu's name is NAME.
-The number of panes depends on the number of bookmarks."
- (bookmark-menu-popup-paned-menu event name (bookmark-all-names)))
-
-
-(defun bookmark-popup-menu-and-apply-function (func-sym menu-label event)
- ;; help function for making menus that need to apply a bookmark
- ;; function to a string.
- (let* ((choice (bookmark-menu-popup-paned-bookmark-menu
- event menu-label)))
- (if choice (apply func-sym (list choice)))))
-
-
-;;;###autoload
-(defun bookmark-menu-insert (event)
- "Insert the text of the file pointed to by bookmark BOOKMARK.
-You may have a problem using this function if the value of variable
-`bookmark-alist' is nil. If that happens, you need to load in some
-bookmarks. See help on function `bookmark-load' for more about
-this.
-
-Warning: this function only takes an EVENT as argument. Use the
-corresponding bookmark function from Lisp \(the one without the
-\"-menu-\" in its name\)."
- (interactive "e")
- (bookmark-popup-menu-and-apply-function
- 'bookmark-insert "Insert Bookmark Contents" event))
-
-
-;;;###autoload
-(defun bookmark-menu-jump (event)
- "Jump to bookmark BOOKMARK (a point in some file).
-You may have a problem using this function if the value of variable
-`bookmark-alist' is nil. If that happens, you need to load in some
-bookmarks. See help on function `bookmark-load' for more about
-this.
-
-Warning: this function only takes an EVENT as argument. Use the
-corresponding bookmark function from Lisp \(the one without the
-\"-menu-\" in its name\)."
- (interactive "e")
- (bookmark-popup-menu-and-apply-function
- 'bookmark-jump "Jump to Bookmark" event))
-
-
-;;;###autoload
-(defun bookmark-menu-locate (event)
- "Insert the name of the file associated with BOOKMARK.
-\(This is not the same as the contents of that file\).
-
-Warning: this function only takes an EVENT as argument. Use the
-corresponding bookmark function from Lisp \(the one without the
-\"-menu-\" in its name\)."
- (interactive "e")
- (bookmark-popup-menu-and-apply-function
- 'bookmark-insert-location "Insert Bookmark Location" event))
-
-
-;;;###autoload
-(defun bookmark-menu-rename (event)
- "Change the name of OLD-BOOKMARK to NEWNAME.
-If called from keyboard, prompts for OLD-BOOKMARK and NEWNAME.
-If called from menubar, OLD-BOOKMARK is selected from a menu, and
-prompts for NEWNAME.
-If called from Lisp, prompts for NEWNAME if only OLD-BOOKMARK was
-passed as an argument. If called with two strings, then no prompting
-is done. You must pass at least OLD-BOOKMARK when calling from Lisp.
-
-While you are entering the new name, consecutive C-w's insert
-consecutive words from the text of the buffer into the new bookmark
-name.
-
-Warning: this function only takes an EVENT as argument. Use the
-corresponding bookmark function from Lisp \(the one without the
-\"-menu-\" in its name\)."
- (interactive "e")
- (bookmark-popup-menu-and-apply-function
- 'bookmark-rename "Rename Bookmark" event))
-
-
-;;;###autoload
-(defun bookmark-menu-delete (event)
- "Delete the bookmark named NAME from the bookmark list.
-Removes only the first instance of a bookmark with that name. If
-there are one or more other bookmarks with the same name, they will
-not be deleted. Defaults to the \"current\" bookmark \(that is, the
-one most recently used in this file, if any\).
-
-Warning: this function only takes an EVENT as argument. Use the
-corresponding bookmark function from Lisp \(the one without the
-\"-menu-\" in its name\)."
- (interactive "e")
- (bookmark-popup-menu-and-apply-function
- 'bookmark-delete "Delete Bookmark" event))
-
-
-;; Thanks to Roland McGrath for fixing menubar.el so that the
-;; following works, and for explaining what to do to make it work.
-
-;; We MUST autoload EACH form used to set up this variable's value, so
-;; that the whole job is done in loaddefs.el.
-
-;; Emacs menubar stuff.
-
-;;;###autoload
-(defvar menu-bar-bookmark-map (make-sparse-keymap "Bookmark functions"))
-
-;;;###autoload
-(defalias 'menu-bar-bookmark-map (symbol-value 'menu-bar-bookmark-map))
-
-;; make bookmarks appear toward the right side of the menu.
-(if (boundp 'menu-bar-final-items)
- (if menu-bar-final-items
- (setq menu-bar-final-items
- (cons 'bookmark menu-bar-final-items)))
- (setq menu-bar-final-items '(bookmark)))
-
-;;;###autoload
-(define-key menu-bar-bookmark-map [load]
- '("Load a Bookmark File..." . bookmark-load))
-
-;;;###autoload
-(define-key menu-bar-bookmark-map [write]
- '("Save Bookmarks As..." . bookmark-write))
-
-;;;###autoload
-(define-key menu-bar-bookmark-map [save]
- '("Save Bookmarks" . bookmark-save))
-
-;;;###autoload
-(define-key menu-bar-bookmark-map [edit]
- '("Edit Bookmark List" . bookmark-bmenu-list))
-
-;;;###autoload
-(define-key menu-bar-bookmark-map [delete]
- '("Delete Bookmark" . bookmark-menu-delete))
-
-;;;###autoload
-(define-key menu-bar-bookmark-map [rename]
- '("Rename Bookmark" . bookmark-menu-rename))
-
-;;;###autoload
-(define-key menu-bar-bookmark-map [locate]
- '("Insert Location" . bookmark-menu-locate))
-
-;;;###autoload
-(define-key menu-bar-bookmark-map [insert]
- '("Insert Contents" . bookmark-menu-insert))
-
-;;;###autoload
-(define-key menu-bar-bookmark-map [set]
- '("Set Bookmark" . bookmark-set))
-
-;;;###autoload
-(define-key menu-bar-bookmark-map [jump]
- '("Jump to Bookmark" . bookmark-menu-jump))
-
-;;;; end bookmark menu stuff ;;;;
-
-
-;;; Load Hook
-(defvar bookmark-load-hook nil
- "Hook to run at the end of loading bookmark.")
-
-(run-hooks 'bookmark-load-hook)
-
-(provide 'bookmark)
-
-;;; bookmark.el ends here
diff --git a/lisp/browse-url.el b/lisp/browse-url.el
deleted file mode 100644
index d4e6988a387..00000000000
--- a/lisp/browse-url.el
+++ /dev/null
@@ -1,764 +0,0 @@
-;;; browse-url.el --- ask a WWW browser to load a URL
-
-;; Copyright 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Denis Howe <dbh@doc.ic.ac.uk>
-;; Maintainer: Denis Howe <dbh@doc.ic.ac.uk>
-;; Created: 03 Apr 1995
-;; Keywords: hypertext
-;; X-Home page: http://wombat.doc.ic.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The latest version of this package should be available from
-;; <URL:http://wombat.doc.ic.ac.uk/emacs/browse-url.el>.
-
-;; This package provides functions which read a URL (Uniform Resource
-;; Locator) from the minibuffer, defaulting to the URL around point,
-;; and ask a World-Wide Web browser to load it. It can also load the
-;; URL associated with the current buffer. Different browsers use
-;; different methods of remote control so there is one function for
-;; each supported browser. If the chosen browser is not running, it
-;; is started. Currently there is support for:
-
-;; Function Browser Earliest version
-;; browse-url-netscape Netscape 1.1b1
-;; browse-url-mosaic XMosaic <= 2.4
-;; browse-url-cci XMosaic 2.5
-;; browse-url-w3 w3 0
-;; browse-url-iximosaic IXI Mosaic ?
-;; browse-url-lynx-* Lynx 0
-;; browse-url-grail Grail 0.3b1
-
-;; Note that versions of Netscape before 1.1b1 did not have remote
-;; control. <URL:http://www.netscape.com/newsref/std/x-remote.html>
-;; and <URL:http://www.netscape.com/info/APIs/>.
-
-;; Netscape can cache Web pages so it may be necessary to tell it to
-;; reload the current page if it has changed (e.g. if you have edited
-;; it). There is currently no perfect automatic solution to this.
-
-;; Netscape allows you to specify the id of the window you want to
-;; control but which window DO you want to control and how do you
-;; discover its id?
-
-;; If using XMosaic before version 2.5, check the definition of
-;; browse-url-usr1-signal below.
-;; <URL:http://www.ncsa.uiuc.edu/SDG/Software/XMosaic/remote-control.html>
-
-;; XMosaic version 2.5 introduced Common Client Interface allowing you
-;; to control mosaic through Unix sockets.
-;; <URL:http://www.ncsa.uiuc.edu/SDG/Software/XMosaic/CCI/cci-spec.html>
-
-;; William M. Perry's excellent "w3" WWW browser for
-;; Emacs <URL:ftp://cs.indiana.edu/pub/elisp/w3/>
-;; has a function w3-follow-url-at-point, but that
-;; doesn't let you edit the URL like browse-url.
-
-;; I recommend Nelson Minar <nelson@santafe.edu>'s excellent
-;; html-helper-mode.el for editing HTML and thank Nelson for
-;; his many useful comments on this code.
-;; <URL:http://www.santafe.edu/~nelson/hhm-beta/>
-
-;; This package generalises function html-previewer-process in Marc
-;; Andreessen <marca@ncsa.uiuc.edu>'s html-mode (LCD
-;; modes/html-mode.el.Z) and provides better versions of the URL
-;; functions in Michelangelo Grigni <mic@cs.ucsd.edu>'s ffap.el
-;; (find-file-at-point) <URL:ftp://cs.ucsd.edu:/pub/mic/>. The huge
-;; hyperbole package also contains similar functions.
-
-;; Grail is the freely available WWW browser implemented in Python, a
-;; cool object-oriented freely available interpreted language. Grail
-;; 0.3b1 was the first version to have remote control as distributed.
-;; For more information on Grail see
-;; <URL:http://monty.cnri.reston.va.us/> and for more information on
-;; Python see <url:http://www.python.org/>. Grail support in
-;; browse-url.el written by Barry Warsaw <bwarsaw@python.org>.
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Help!
-
-;; Can you write and test some code for the Macintrash and Windoze
-;; Netscape remote control APIs? (See the URL above).
-
-;; Do any other browsers have remote control?
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Usage
-
-;; To display the URL at or before point:
-;; M-x browse-url-at-point RET
-
-;; To display a URL by shift-clicking on it, put this in your ~/.emacs
-;; file:
-;; (global-set-key [S-mouse-2] 'browse-url-at-mouse)
-;; (Note that using Shift-mouse-1 is not desirable because
-;; that event has a standard meaning in Emacs.)
-
-;; To display the current buffer in a web browser:
-;; M-x browse-url-of-buffer RET
-
-;; In Dired, to display the file named on the current line:
-;; M-x browse-url-of-dired-file RET
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Customisation (~/.emacs)
-
-;; To see what variables are available for customization, type
-;; `M-x set-variable browse-url TAB'.
-
-;; Bind the browse-url commands to keys with the `C-c C-z' prefix
-;; (as used by html-helper-mode):
-;; (global-set-key "\C-c\C-z." 'browse-url-at-point)
-;; (global-set-key "\C-c\C-zb" 'browse-url-of-buffer)
-;; (global-set-key "\C-c\C-zu" 'browse-url)
-;; (global-set-key "\C-c\C-zv" 'browse-url-of-file)
-;; (add-hook 'dired-mode-hook
-;; (function (lambda ()
-;; (local-set-key "\C-c\C-zf" 'browse-url-of-dired-file))))
-
-;; Browse URLs in mail messages by clicking mouse-2:
-;; (add-hook 'rmail-mode-hook (function (lambda () ; rmail-mode startup
-;; (define-key rmail-mode-map [mouse-2] 'browse-url-at-mouse))))
-
-;; Browse URLs in Usenet messages by clicking mouse-2:
-;; (eval-after-load "gnus"
-;; '(define-key gnus-article-mode-map [mouse-2] 'browse-url-at-mouse))
-
-;; Use the Emacs w3 browser when not running under X11:
-;; (or (eq window-system 'x)
-;; (setq browse-url-browser-function 'browse-url-w3))
-
-;; To always save modified buffers before displaying the file in a browser:
-;; (setq browse-url-save-file t)
-
-;; To get round the Netscape caching problem, you could EITHER have
-;; write-file in html-helper-mode make Netscape reload the document:
-;;
-;; (autoload 'browse-url-netscape-reload "browse-url"
-;; "Ask a WWW browser to redisplay the current file." t)
-;; (add-hook 'html-helper-mode-hook
-;; (function (lambda ()
-;; (add-hook 'local-write-file-hooks
-;; (function (lambda ()
-;; (let ((local-write-file-hooks))
-;; (save-buffer))
-;; (browse-url-netscape-reload)
-;; t)) ; => file written by hook
-;; t)))) ; append to l-w-f-hooks
-;;
-;; OR have browse-url-of-file ask Netscape to load and then reload the
-;; file:
-;;
-;; (add-hook 'browse-url-of-file-hook 'browse-url-netscape-reload)
-
-;; You may also want to customise browse-url-netscape-arguments, e.g.
-;; (setq browse-url-netscape-arguments '("-install"))
-;;
-;; or similarly for the other browsers.
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Change Log:
-
-;; 0.00 03 Apr 1995 Denis Howe <dbh@doc.ic.ac.uk>
-;; Created.
-
-;; 0.01 04 Apr 1995
-;; All names start with "browse-url-". Added provide.
-
-;; 0.02 05 Apr 1995
-;; Save file at start of browse-url-of-file.
-;; Use start-process instead of start-process-shell-command.
-
-;; 0.03 06 Apr 1995
-;; Add browse-url-netscape-reload, browse-url-netscape-send.
-;; browse-url-of-file save file option.
-
-;; 0.04 08 Apr 1995
-;; b-u-file-url separate function. Change b-u-filename-alist
-;; default.
-
-;; 0.05 09 Apr 1995
-;; Added b-u-of-file-hook.
-
-;; 0.06 11 Apr 1995
-;; Improved .emacs suggestions and documentation.
-
-;; 0.07 13 Apr 1995
-;; Added browse-url-interactive-arg optional prompt.
-
-;; 0.08 18 Apr 1995
-;; Exclude final "." from browse-url-regexp.
-
-;; 0.09 21 Apr 1995
-;; Added mouse-set-point to browse-url-interactive-arg.
-
-;; 0.10 24 Apr 1995
-;; Added Mosaic signal sending variations.
-;; Thanks Brian K Servis <servis@ecn.purdue.edu>.
-;; Don't use xprop for Netscape.
-
-;; 0.11 25 Apr 1995
-;; Fix reading of ~/.mosaicpid. Thanks Dag.H.Wanvik@kvatro.no.
-
-;; 0.12 27 Apr 1995
-;; Interactive prefix arg => URL *after* point.
-;; Thanks Michelangelo Grigni <mic@cs.ucsd.edu>.
-;; Added IXI Mosaic support.
-;; Thanks David Karr <dkarr@nmo.gtegsc.com>.
-
-;; 0.13 28 Apr 1995
-;; Exclude final [,;] from browse-url-regexp.
-
-;; 0.14 02 May 1995
-;; Provide browser argument variables.
-
-;; 0.15 07 May 1995
-;; More Netscape options. Thanks Peter Arius
-;; <arius@immd2.informatik.uni-erlangen.de>.
-
-;; 0.16 17 May 1995
-;; Added browse-url-at-mouse.
-;; Thanks Wayne Mesard <wmesard@sgi.com>
-
-;; 0.17 27 Jun 1995
-;; Renamed browse-url-at-point to browse-url-url-at-point.
-;; Added browse-url-at-point.
-;; Thanks Jonathan Cano <cano@patch.tandem.com>.
-
-;; 0.18 16 Aug 1995
-;; Fixed call to browse-url-url-at-point in browse-url-at-point.
-;; Thanks Eric Ding <ericding@San-Jose.ate.slb.com>.
-
-;; 0.19 24 Aug 1995
-;; Improved documentation.
-;; Thanks Kevin Rodgers <kevin.rodgers@ihs.com>.
-
-;; 0.20 31 Aug 1995
-;; browse-url-of-buffer to handle file-less buffers.
-;; browse-url-of-dired-file browses current file in dired.
-;; Thanks Kevin Rodgers <kevin.rodgers@ihs.com>.
-
-;; 0.21 09 Sep 1995
-;; XMosaic CCI functions.
-;; Thanks Marc Furrer <Marc.Furrer@di.epfl.ch>.
-
-;; 0.22 13 Sep 1995
-;; Fixed new-window documentation and added to browse-url-cci.
-;; Thanks Dilip Sequeira <djs@dcs.ed.ac.uk>.
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Variables
-
-(eval-when-compile (require 'dired))
-
-(defvar browse-url-path-regexp
- "[^]\t\n \"'()<>[^`{}]*[^]\t\n \"'()<>[^`{}.,;]+"
- "A regular expression probably matching the host, path or e-mail
-part of a URL.")
-
-(defvar browse-url-short-regexp
- (concat "[-A-Za-z0-9.]+" browse-url-path-regexp)
- "A regular expression probably matching a URL without an access scheme.
-Hostname matching is stricter in this case than for
-``browse-url-regexp''.")
-
-(defvar browse-url-regexp
- (concat
- "\\(https?://\\|ftp://\\|gopher://\\|telnet://\\|wais://\\|file:/\\|s?news:\\|mailto:\\)"
- browse-url-path-regexp)
- "A regular expression probably matching a complete URL.")
-
-
-;;;###autoload
-(defvar browse-url-browser-function
- 'browse-url-netscape
- "*Function to display the current buffer in a WWW browser.
-Used by the `browse-url-at-point', `browse-url-at-mouse', and
-`browse-url-of-file' commands.")
-
-(defvar browse-url-netscape-command "netscape"
- "*The name by which to invoke Netscape.")
-
-(defvar browse-url-netscape-arguments nil
- "*A list of strings to pass to Netscape as arguments.")
-
-(defvar browse-url-netscape-startup-arguments browse-url-netscape-arguments
- "*A list of strings to pass to Netscape when it starts up.
-Defaults to the value of browse-url-netscape-arguments at the time
-browse-url is loaded.")
-
-(defvar browse-url-new-window-p nil
- "*If non-nil, always open a new browser window.
-Passing an interactive argument to \\[browse-url-netscape] or
-\\[browse-url-cci] reverses the effect of this variable. Requires
-Netscape version 1.1N or later or XMosaic version 2.5 or later.")
-
-(defvar browse-url-mosaic-arguments nil
- "*A list of strings to pass to Mosaic as arguments.")
-
-(defvar browse-url-filename-alist
- '(("^/+" . "file:/"))
- "An alist of (REGEXP . STRING) pairs.
-Any substring of a filename matching one of the REGEXPs is replaced by
-the corresponding STRING. All pairs are applied in the order given.
-The default value prepends `file:' to any path beginning with `/'.
-Used by the `browse-url-of-file' command.")
-
-(defvar browse-url-save-file nil
- "If non-nil, save the buffer before displaying its file.
-Used by the `browse-url-of-file' command.")
-
-(defvar browse-url-of-file-hook nil
- "A hook to be run with run-hook after `browse-url-of-file' has asked
-a browser to load a file.
-
-Set this to `browse-url-netscape-reload' to force Netscape to load the
-file rather than displaying a cached copy.")
-
-(defvar browse-url-usr1-signal
- (if (and (boundp 'emacs-major-version)
- (or (> emacs-major-version 19) (>= emacs-minor-version 29)))
- 'SIGUSR1 ; Why did I think this was in lower case before?
- 30) ; Check /usr/include/signal.h.
- "The argument to `signal-process' for sending SIGUSR1 to XMosaic.
-Emacs 19.29 accepts 'SIGUSR1, earlier versions require an integer
-which is 30 on SunOS and 16 on HP-UX and Solaris.")
-
-(defvar browse-url-CCI-port 3003
- "Port to access XMosaic via CCI.
-This can be any number between 1024 and 65535 but must correspond to
-the value set in the browser.")
-
-(defvar browse-url-CCI-host "localhost"
- "*Host to access XMosaic via CCI.
-This should be the host name of the machine running XMosaic with CCI
-enabled. The port number should be set in `browse-url-CCI-port'.")
-
-(defvar browse-url-temp-file-name nil)
-(make-variable-buffer-local 'browse-url-temp-file-name)
-
-(defvar browse-url-temp-file-list '())
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; URL input
-
-;; thingatpt.el doesn't work for complex regexps
-
-(defun browse-url-url-at-point ()
- "Return the URL around or before point.
-Search backwards for the start of a URL ending at or after
-point. If no URL found, return the empty string.
-A file name is also acceptable, and `http://' will be prepended to it."
- (or (thing-at-point 'url)
- (let ((file (thing-at-point 'filename)))
- (if file (concat "http://" file)))
- ""))
-
-;; Having this as a separate function called by the browser-specific
-;; functions allows them to be stand-alone commands, making it easier
-;; to switch between browsers.
-
-(defun browse-url-interactive-arg (prompt)
- "Read a URL from the minibuffer, prompting with PROMPT.
-Default to the URL at or before point. If invoke with a mouse button,
-set point to the position clicked first. Return a list for use in
-`interactive' containing the URL and browse-url-new-window-p or its
-negation if a prefix argument was given."
- (let ((event (elt (this-command-keys) 0)))
- (and (listp event) (mouse-set-point event)))
- (list (read-string prompt (browse-url-url-at-point))
- (not (eq (null browse-url-new-window-p)
- (null current-prefix-arg)))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Browse current buffer
-
-;;;###autoload
-(defun browse-url-of-file (&optional file)
- "Ask a WWW browser to display FILE.
-Display the current buffer's file if FILE is nil or if called
-interactively. Turn the filename into a URL with function
-browse-url-file-url. Pass the URL to a browser using variable
-`browse-url-browser-function' then run `browse-url-of-file-hook'."
- (interactive)
- (or file
- (setq file (buffer-file-name))
- (error "Current buffer has no file"))
- (let ((buf (get-file-buffer file)))
- (if buf
- (save-excursion
- (set-buffer buf)
- (cond ((not (buffer-modified-p)))
- (browse-url-save-file (save-buffer))
- (t (message "%s modified since last save" file))))))
- (funcall browse-url-browser-function (browse-url-file-url file))
- (run-hooks 'browse-url-of-file-hook))
-
-(defun browse-url-file-url (file)
- "Return the URL corresponding to FILE.
-Use variable `browse-url-filename-alist' to map filenames to URLs.
-Convert EFS file names of the form /USER@HOST:PATH to ftp://HOST/PATH."
- ;; URL-encode special chars, do % first
- (let ((s 0))
- (while (setq s (string-match "%" file s))
- (setq file (replace-match "%25" t t file)
- s (1+ s))))
- (while (string-match "[*\"()',=;? ]" file)
- (let ((enc (format "%%%x" (aref file (match-beginning 0)))))
- (setq file (replace-match enc t t file))))
- (let ((maps browse-url-filename-alist))
- (while maps
- (let* ((map (car maps))
- (from-re (car map))
- (to-string (cdr map)))
- (setq maps (cdr maps))
- (and (string-match from-re file)
- (setq file (replace-match to-string t t file))))))
- ;; Check for EFS path
- (and (string-match "^/\\([^:@]+@\\)?\\([^:]+\\):/*" file)
- (setq file (concat "ftp://"
- (substring file (match-beginning 2) (match-end 2))
- "/" (substring file (match-end 0)))))
- file)
-
-;;;###autoload
-(defun browse-url-of-buffer (&optional buffer)
- "Ask a WWW browser to display BUFFER.
-Display the current buffer if BUFFER is nil."
- (interactive)
- (save-excursion
- (and buffer (set-buffer buffer))
- (let ((file-name
- (or buffer-file-name
- (and (boundp 'dired-directory) dired-directory))))
- (or file-name
- (progn
- (or browse-url-temp-file-name
- (setq browse-url-temp-file-name
- (make-temp-name
- (expand-file-name (buffer-name)
- (or (getenv "TMPDIR") "/tmp")))
- browse-url-temp-file-list
- (cons browse-url-temp-file-name
- browse-url-temp-file-list)))
- (setq file-name browse-url-temp-file-name)
- (write-region (point-min) (point-max) file-name nil 'no-message)))
- (browse-url-of-file file-name))))
-
-(defun browse-url-delete-temp-file (&optional temp-file-name)
- ;; Delete browse-url-temp-file-name from the file system and from
- ;; browse-url-temp-file-list. If optional arg TEMP-FILE-NAME is
- ;; non-nil, delete it instead, but only from the file system --
- ;; browse-url-temp-file-list is not affected.
- (let ((file-name (or temp-file-name browse-url-temp-file-name)))
- (if (and file-name (file-exists-p file-name))
- (progn
- (delete-file file-name)
- (if (null temp-file-name)
- (setq browse-url-temp-file-list
- (delete browse-url-temp-file-name
- browse-url-temp-file-list)))))))
-
-(defun browse-url-delete-temp-file-list ()
- ;; Delete all elements of browse-url-temp-file-list.
- (while browse-url-temp-file-list
- (browse-url-delete-temp-file (car browse-url-temp-file-list))
- (setq browse-url-temp-file-list
- (cdr browse-url-temp-file-list))))
-
-(add-hook 'kill-buffer-hook 'browse-url-delete-temp-file)
-(add-hook 'kill-emacs-hook 'browse-url-delete-temp-file-list)
-
-;;;###autoload
-(defun browse-url-of-dired-file ()
- "In Dired, ask a WWW browser to display the file named on this line."
- (interactive)
- (browse-url-of-file (dired-get-filename)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Browser-independant commands
-
-;; A generic command to call the current b-u-browser-function
-
-(defun browse-url (&rest args)
- "Ask a WWW browser to load URL.
-Prompts for a URL, defaulting to the URL at or before point. Variable
-`browse-url-browser-function' says which browser to use."
- (interactive (browse-url-interactive-arg "URL: "))
- (apply browse-url-browser-function args))
-
-;;;###autoload
-(defun browse-url-at-point ()
- "Ask a WWW browser to load the URL at or before point.
-Doesn't let you edit the URL like browse-url. Variable
-`browse-url-browser-function' says which browser to use."
- (interactive)
- (funcall browse-url-browser-function (browse-url-url-at-point)))
-
-;; Define these if not already defined (XEmacs compatibility)
-
-(eval-and-compile
- (or (fboundp 'event-buffer)
- (defun event-buffer (event)
- (window-buffer (posn-window (event-start event))))))
-
-(eval-and-compile
- (or (fboundp 'event-point)
- (defun event-point (event)
- (posn-point (event-start event)))))
-
-;;;###autoload
-(defun browse-url-at-mouse (event)
- "Ask a WWW browser to load a URL clicked with the mouse.
-The URL is the one around or before the position of the mouse click
-but point is not changed. Doesn't let you edit the URL like
-browse-url. Variable `browse-url-browser-function' says which browser
-to use."
- (interactive "e")
- (save-excursion
- (set-buffer (event-buffer event))
- (goto-char (event-point event))
- (let ((url (browse-url-url-at-point)))
- (if (string-equal url "")
- (error "No URL found"))
- (funcall browse-url-browser-function url))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Browser-specific commands
-
-;; --- Netscape ---
-
-;; Put the correct DISPLAY value in the environment for Netscape
-;; launched from multi-display Emacs.
-
-(defun browse-url-process-environment ()
- (let* ((device (and (fboundp 'selected-device)
- (fboundp 'device-connection)
- (selected-device)))
- (display (and device (fboundp 'device-type)
- (eq (device-type device) 'x)
- (not (equal (device-connection device)
- (getenv "DISPLAY"))))))
- (if display
- ;; Attempt to run on the correct display
- (cons (concat "DISPLAY=" (device-connection device))
- process-environment)
- process-environment)))
-
-
-;;;###autoload
-(defun browse-url-netscape (url &optional new-window)
- "Ask the Netscape WWW browser to load URL.
-
-Default to the URL around or before point. The strings in variable
-`browse-url-netscape-arguments' are also passed to Netscape.
-
-When called interactively, if variable `browse-url-new-window-p' is
-non-nil, load the document in a new Netscape window, otherwise use a
-random existing one. A non-nil interactive prefix argument reverses
-the effect of browse-url-new-window-p.
-
-When called non-interactively, optional second argument NEW-WINDOW is
-used instead of browse-url-new-window-p."
- (interactive (browse-url-interactive-arg "Netscape URL: "))
- ;; URL encode any commas in the URL
- (while (string-match "," url)
- (setq url (replace-match "%2C" t t url)))
- (let* ((process-environment (browse-url-process-environment))
- (process (apply 'start-process
- (concat "netscape " url) nil
- browse-url-netscape-command
- (append browse-url-netscape-arguments
- (if new-window '("-noraise"))
- (list "-remote"
- (concat "openURL(" url
- (if new-window ",new-window")
- ")"))))))
- (set-process-sentinel process
- (list 'lambda '(process change)
- (list 'browse-url-netscape-sentinel 'process url)))))
-
-(defun browse-url-netscape-sentinel (process url)
- "Handle a change to the process communicating with Netscape."
- (or (eq (process-exit-status process) 0)
- (let* ((process-environment (browse-url-process-environment)))
- ;; Netscape not running - start it
- (message "Starting Netscape...")
- (apply 'start-process (concat "netscape" url) nil
- browse-url-netscape-command
- (append browse-url-netscape-startup-arguments (list url))))))
-
-(defun browse-url-netscape-reload ()
- "Ask Netscape to reload its current document."
- (interactive)
- (browse-url-netscape-send "reload"))
-
-(defun browse-url-netscape-send (command)
- "Send a remote control command to Netscape."
- (let* ((process-environment (browse-url-process-environment)))
- (apply 'start-process "netscape" nil
- browse-url-netscape-command
- (append browse-url-netscape-arguments
- (list "-remote" command)))))
-
-;; --- Mosaic ---
-
-;;;###autoload
-(defun browse-url-mosaic (url &optional new-window)
- ;; new-window ignored
- "Ask the XMosaic WWW browser to load URL.
-Default to the URL around or before point."
- (interactive (browse-url-interactive-arg "Mosaic URL: "))
- (let ((pidfile (expand-file-name "~/.mosaicpid"))
- pid pidbuf)
- (if (file-readable-p pidfile)
- (save-excursion
- (find-file pidfile)
- (goto-char (point-min))
- (setq pid (read (current-buffer)))
- (kill-buffer nil)))
- (if (and pid (zerop (signal-process pid 0))) ; Mosaic running
- (save-excursion
- (find-file (format "/tmp/Mosaic.%d" pid))
- (erase-buffer)
- (insert "goto\n" url "\n")
- (save-buffer)
- (kill-buffer nil)
- ;; Send signal SIGUSR to Mosaic
- (message "Signalling Mosaic...")
- (signal-process pid browse-url-usr1-signal)
- ;; Or you could try:
- ;; (call-process "kill" nil 0 nil "-USR1" (int-to-string pid))
- (message "Signalling Mosaic...done")
- )
- ;; Mosaic not running - start it
- (message "Starting Mosaic...")
- (apply 'start-process "xmosaic" nil "xmosaic"
- (append browse-url-mosaic-arguments (list url)))
- (message "Starting Mosaic...done"))))
-
-;; --- Grail ---
-
-;;;###autoload
-(defvar browse-url-grail
- (concat (or (getenv "GRAILDIR") "~/.grail") "/user/rcgrail.py")
- "*Location of Grail remote control client script `rcgrail.py'.
-Typically found in $GRAILDIR/rcgrail.py, or ~/.grail/user/rcgrail.py.")
-
-;;;###autoload
-(defun browse-url-grail (url)
- "Ask the Grail WWW browser to load URL.
-Default to the URL around or before point. Runs the program in the
-variable `browse-url-grail'."
- (interactive (browse-url-interactive-arg "Grail URL: "))
- (message "Sending URL to Grail...")
- (save-excursion
- (set-buffer (get-buffer-create " *Shell Command Output*"))
- (erase-buffer)
- ;; don't worry about this failing.
- (call-process browse-url-grail nil 0 nil url)
- (message "Sending URL to Grail... done")))
-
-;; --- Mosaic using CCI ---
-
-(defun browse-url-cci (url &optional new-window)
- "Ask the XMosaic WWW browser to load URL.
-Default to the URL around or before point.
-
-This function only works for XMosaic version 2.5 or later. You must
-select `CCI' from XMosaic's File menu, set the CCI Port Address to the
-value of variable `browse-url-CCI-port', and enable `Accept requests'.
-
-When called interactively, if variable `browse-url-new-window-p' is
-non-nil, load the document in a new browser window, otherwise use a
-random existing one. A non-nil interactive prefix argument reverses
-the effect of browse-url-new-window-p.
-
-When called non-interactively, optional second argument NEW-WINDOW is
-used instead of browse-url-new-window-p."
- (interactive (browse-url-interactive-arg "Mosaic URL: "))
- (open-network-stream "browse-url" " *browse-url*"
- browse-url-CCI-host browse-url-CCI-port)
- ;; Todo: start browser if fails
- (process-send-string "browse-url"
- (concat "get url (" url ") output "
- (if new-window "new" "current") "\r\n"))
- (process-send-string "browse-url" "disconnect\r\n")
- (delete-process "browse-url"))
-
-;; --- IXI Mosaic ---
-
-;;;###autoload
-(defun browse-url-iximosaic (url &optional new-window)
- ;; new-window ignored
- "Ask the IXIMosaic WWW browser to load URL.
-Default to the URL around or before point."
- (interactive (browse-url-interactive-arg "IXI Mosaic URL: "))
- (start-process "tellw3b" nil "tellw3b"
- "-service WWW_BROWSER ixi_showurl " url))
-
-;; --- W3 ---
-
-;;;###autoload
-(defun browse-url-w3 (url &optional new-window)
- ;; new-window ignored
- "Ask the w3 WWW browser to load URL.
-Default to the URL around or before point."
- (interactive (browse-url-interactive-arg "W3 URL: "))
- (w3-fetch url))
-
-;; --- Lynx in an xterm ---
-
-;;;###autoload
-(defun browse-url-lynx-xterm (url &optional new-window)
- ;; new-window ignored
- "Ask the Lynx WWW browser to load URL.
-Default to the URL around or before point. A new Lynx process is run
-in an Xterm window."
- (interactive (browse-url-interactive-arg "Lynx URL: "))
- (start-process (concat "lynx" url) nil "xterm" "-e" "lynx" url))
-
-(eval-when-compile (require 'term))
-
-;; --- Lynx in an Emacs "term" window ---
-
-;;;###autoload
-(defun browse-url-lynx-emacs (url &optional new-window)
- ;; new-window ignored
- "Ask the Lynx WWW browser to load URL.
-Default to the URL around or before point. Run a new Lynx process in
-an Emacs buffer."
- (interactive (browse-url-interactive-arg "Lynx URL: "))
- (let ((system-uses-terminfo t)) ; Lynx uses terminfo
- (if (fboundp 'make-term)
- (let ((term-term-name "vt100"))
- (set-buffer (make-term "browse-url" "lynx" nil url))
- (term-mode)
- (term-char-mode)
- (switch-to-buffer "*browse-url*"))
- (terminal-emulator "*browse-url*" "lynx" (list url)))))
-
-(provide 'browse-url)
-
-;;; browse-url.el ends here
diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el
deleted file mode 100644
index d25cdbdb8ea..00000000000
--- a/lisp/buff-menu.el
+++ /dev/null
@@ -1,550 +0,0 @@
-;;; buff-menu.el --- buffer menu main function and support functions.
-
-;; Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Edit, delete, or change attributes of all currently active Emacs
-;; buffers from a list summarizing their state. A good way to browse
-;; any special or scratch buffers you have loaded, since you can't find
-;; them by filename. The single entry point is `Buffer-menu-mode',
-;; normally bound to C-x C-b.
-
-;;; Change Log:
-
-;; Merged by esr with recent mods to Emacs 19 buff-menu, 23 Mar 1993
-;;
-;; Modified by Bob Weiner, Motorola, Inc., 4/14/89
-;;
-;; Added optional backup argument to 'Buffer-menu-unmark' to make it undelete
-;; current entry and then move to previous one.
-;;
-;; Based on FSF code dating back to 1985.
-
-;;; Code:
-
-;;;Trying to preserve the old window configuration works well in
-;;;simple scenarios, when you enter the buffer menu, use it, and exit it.
-;;;But it does strange things when you switch back to the buffer list buffer
-;;;with C-x b, later on, when the window configuration is different.
-;;;The choice seems to be, either restore the window configuration
-;;;in all cases, or in no cases.
-;;;I decided it was better not to restore the window config at all. -- rms.
-
-;;;But since then, I changed buffer-menu to use the selected window,
-;;;so q now once again goes back to the previous window configuration.
-
-;;;(defvar Buffer-menu-window-config nil
-;;; "Window configuration saved from entry to `buffer-menu'.")
-
-; Put buffer *Buffer List* into proper mode right away
-; so that from now on even list-buffers is enough to get a buffer menu.
-
-(defvar Buffer-menu-buffer-column nil)
-
-(defvar Buffer-menu-mode-map nil "")
-
-(if Buffer-menu-mode-map
- ()
- (setq Buffer-menu-mode-map (make-keymap))
- (suppress-keymap Buffer-menu-mode-map t)
- (define-key Buffer-menu-mode-map "q" 'Buffer-menu-quit)
- (define-key Buffer-menu-mode-map "v" 'Buffer-menu-select)
- (define-key Buffer-menu-mode-map "2" 'Buffer-menu-2-window)
- (define-key Buffer-menu-mode-map "1" 'Buffer-menu-1-window)
- (define-key Buffer-menu-mode-map "f" 'Buffer-menu-this-window)
- (define-key Buffer-menu-mode-map "\C-m" 'Buffer-menu-this-window)
- (define-key Buffer-menu-mode-map "o" 'Buffer-menu-other-window)
- (define-key Buffer-menu-mode-map "\C-o" 'Buffer-menu-switch-other-window)
- (define-key Buffer-menu-mode-map "s" 'Buffer-menu-save)
- (define-key Buffer-menu-mode-map "d" 'Buffer-menu-delete)
- (define-key Buffer-menu-mode-map "k" 'Buffer-menu-delete)
- (define-key Buffer-menu-mode-map "\C-d" 'Buffer-menu-delete-backwards)
- (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 "%" 'Buffer-menu-toggle-read-only)
- (define-key Buffer-menu-mode-map "g" 'Buffer-menu-revert)
- (define-key Buffer-menu-mode-map [mouse-2] 'Buffer-menu-mouse-select)
-)
-
-;; Buffer Menu mode is suitable only for specially formatted data.
-(put 'Buffer-menu-mode 'mode-class 'special)
-
-(defun 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.
-\\<Buffer-menu-mode-map>
-\\[Buffer-menu-mouse-select] -- select buffer you click on, in place of the buffer menu.
-\\[Buffer-menu-this-window] -- select current line's buffer in place of the buffer menu.
-\\[Buffer-menu-other-window] -- select that buffer in another window,
- so the buffer menu buffer remains visible in its window.
-\\[Buffer-menu-switch-other-window] -- make another window display that buffer.
-\\[Buffer-menu-mark] -- mark current line's buffer to be displayed.
-\\[Buffer-menu-select] -- select current line's buffer.
- Also show buffers marked with m, in other windows.
-\\[Buffer-menu-1-window] -- select that buffer in full-frame window.
-\\[Buffer-menu-2-window] -- select that buffer in one window,
- together with buffer selected before this one in another 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.
- With prefix argument, also move up one line.
-\\[Buffer-menu-backup-unmark] -- back up a line and remove marks.
-\\[Buffer-menu-toggle-read-only] -- toggle read-only status of buffer on this line.
-\\[Buffer-menu-revert] -- update the list of buffers."
- (kill-all-local-variables)
- (use-local-map Buffer-menu-mode-map)
- (setq major-mode 'Buffer-menu-mode)
- (setq mode-name "Buffer Menu")
- (make-local-variable 'revert-buffer-function)
- (setq revert-buffer-function 'Buffer-menu-revert-function)
- (setq truncate-lines t)
- (setq buffer-read-only t)
- (run-hooks 'buffer-menu-mode-hook))
-
-(defun Buffer-menu-revert ()
- "Update the list of buffers."
- (interactive)
- (revert-buffer))
-
-(defun Buffer-menu-revert-function (ignore1 ignore2)
- (list-buffers))
-
-(defun Buffer-menu-buffer (error-if-non-existent-p)
- "Return buffer described by this line of buffer menu."
- (let* ((where (save-excursion
- (beginning-of-line)
- (+ (point) Buffer-menu-buffer-column)))
- (name (and (not (eobp)) (get-text-property where 'buffer-name))))
- (if name
- (or (get-buffer name)
- (if error-if-non-existent-p
- (error "No buffer named `%s'" name)
- nil))
- (if error-if-non-existent-p
- (error "No buffer on this line")
- nil))))
-
-(defun buffer-menu (&optional arg)
- "Make a menu of buffers so you can save, delete or select them.
-With argument, show only buffers that are visiting files.
-Type ? after invocation to get help on commands available.
-Type q immediately to make the buffer menu go away."
- (interactive "P")
-;;; (setq Buffer-menu-window-config (current-window-configuration))
- (switch-to-buffer (list-buffers-noselect arg))
- (message
- "Commands: d, s, x, u; f, o, 1, 2, m, v; ~, %%; q to quit; ? for help."))
-
-(defun buffer-menu-other-window (&optional arg)
- "Display a list of buffers in another window.
-With the buffer list buffer, you can save, delete or select the buffers.
-With argument, show only buffers that are visiting files.
-Type ? after invocation to get help on commands available.
-Type q immediately to make the buffer menu go away."
- (interactive "P")
-;;; (setq Buffer-menu-window-config (current-window-configuration))
- (switch-to-buffer-other-window (list-buffers-noselect arg))
- (message
- "Commands: d, s, x, u; f, o, 1, 2, m, v; ~, %%; q to quit; ? for help."))
-
-(defun Buffer-menu-quit ()
- "Quit the buffer menu."
- (interactive)
- (let ((buffer (current-buffer)))
- ;; Switch away from the buffer menu and bury it.
- (switch-to-buffer (other-buffer))
- (bury-buffer buffer)))
-
-(defun Buffer-menu-mark ()
- "Mark buffer on this line for being displayed by \\<Buffer-menu-mode-map>\\[Buffer-menu-select] command."
- (interactive)
- (beginning-of-line)
- (if (looking-at " [-M]")
- (ding)
- (let ((buffer-read-only nil))
- (delete-char 1)
- (insert ?>)
- (forward-line 1))))
-
-(defun Buffer-menu-unmark (&optional backup)
- "Cancel all requested operations on buffer on this line and move down.
-Optional ARG means move up."
- (interactive "P")
- (beginning-of-line)
- (if (looking-at " [-M]")
- (ding)
- (let* ((buf (Buffer-menu-buffer t))
- (mod (buffer-modified-p buf))
- (readonly (save-excursion (set-buffer buf) buffer-read-only))
- (buffer-read-only nil))
- (delete-char 3)
- (insert (if readonly (if mod " *%" " %") (if mod " * " " ")))))
- (forward-line (if backup -1 1)))
-
-(defun Buffer-menu-backup-unmark ()
- "Move up and cancel all requested operations on buffer on line above."
- (interactive)
- (forward-line -1)
- (Buffer-menu-unmark)
- (forward-line -1))
-
-(defun Buffer-menu-delete (&optional arg)
- "Mark buffer on this line to be deleted by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command.
-Prefix arg is how many buffers to delete.
-Negative arg means delete backwards."
- (interactive "p")
- (beginning-of-line)
- (if (looking-at " [-M]") ;header lines
- (ding)
- (let ((buffer-read-only nil))
- (if (or (null arg) (= arg 0))
- (setq arg 1))
- (while (> arg 0)
- (delete-char 1)
- (insert ?D)
- (forward-line 1)
- (setq arg (1- arg)))
- (while (< arg 0)
- (delete-char 1)
- (insert ?D)
- (forward-line -1)
- (setq arg (1+ arg))))))
-
-(defun Buffer-menu-delete-backwards (&optional arg)
- "Mark buffer on this line to be deleted by \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command
-and then move up one line. Prefix arg means move that many lines."
- (interactive "p")
- (Buffer-menu-delete (- (or arg 1)))
- (while (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."
- (interactive)
- (beginning-of-line)
- (if (looking-at " [-M]") ;header lines
- (ding)
- (let ((buffer-read-only nil))
- (forward-char 1)
- (delete-char 1)
- (insert ?S)
- (forward-line 1))))
-
-(defun Buffer-menu-not-modified (&optional arg)
- "Mark buffer on this line as unmodified (no changes to save)."
- (interactive "P")
- (save-excursion
- (set-buffer (Buffer-menu-buffer t))
- (set-buffer-modified-p arg))
- (save-excursion
- (beginning-of-line)
- (forward-char 1)
- (if (= (char-after (point)) (if arg ? ?*))
- (let ((buffer-read-only nil))
- (delete-char 1)
- (insert (if arg ?* ? ))))))
-
-(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."
- (interactive)
- (save-excursion
- (goto-char (point-min))
- (forward-line 1)
- (while (re-search-forward "^.S" nil t)
- (let ((modp nil))
- (save-excursion
- (set-buffer (Buffer-menu-buffer t))
- (save-buffer)
- (setq modp (buffer-modified-p)))
- (let ((buffer-read-only nil))
- (delete-char -1)
- (insert (if modp ?* ? ))))))
- (save-excursion
- (goto-char (point-min))
- (forward-line 1)
- (let ((buff-menu-buffer (current-buffer))
- (buffer-read-only nil))
- (while (search-forward "\nD" nil t)
- (forward-char -1)
- (let ((buf (Buffer-menu-buffer nil)))
- (or (eq buf nil)
- (eq buf buff-menu-buffer)
- (save-excursion (kill-buffer buf))))
- (if (Buffer-menu-buffer nil)
- (progn (delete-char 1)
- (insert ? ))
- (delete-region (point) (progn (forward-line 1) (point)))
- (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.
-This command deletes and replaces all the previously existing windows
-in the selected frame."
- (interactive)
- (let ((buff (Buffer-menu-buffer t))
- (menu (current-buffer))
- (others ())
- tem)
- (goto-char (point-min))
- (while (search-forward "\n>" nil t)
- (setq tem (Buffer-menu-buffer t))
- (let ((buffer-read-only nil))
- (delete-char -1)
- (insert ?\ ))
- (or (eq tem buff) (memq tem others) (setq others (cons tem others))))
- (setq others (nreverse others)
- tem (/ (1- (frame-height)) (1+ (length others))))
- (delete-other-windows)
- (switch-to-buffer buff)
- (or (eq menu buff)
- (bury-buffer menu))
- (if (equal (length others) 0)
- (progn
-;;; ;; Restore previous window configuration before displaying
-;;; ;; selected buffers.
-;;; (if Buffer-menu-window-config
-;;; (progn
-;;; (set-window-configuration Buffer-menu-window-config)
-;;; (setq Buffer-menu-window-config nil)))
- (switch-to-buffer buff))
- (while others
- (split-window nil tem)
- (other-window 1)
- (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 frame."
- (interactive)
- (switch-to-buffer (Buffer-menu-buffer t))
- (bury-buffer (other-buffer))
- (delete-other-windows))
-
-(defun Buffer-menu-mouse-select (event)
- "Select the buffer whose line you click on."
- (interactive "e")
- (let (buffer)
- (save-excursion
- (set-buffer (window-buffer (posn-window (event-end event))))
- (save-excursion
- (goto-char (posn-point (event-end event)))
- (setq buffer (Buffer-menu-buffer t))))
- (select-window (posn-window (event-end event)))
- (if (and (window-dedicated-p (selected-window))
- (eq (selected-window) (frame-root-window)))
- (switch-to-buffer-other-frame buffer)
- (switch-to-buffer buffer))))
-
-(defun Buffer-menu-this-window ()
- "Select this line's buffer in this window."
- (interactive)
- (switch-to-buffer (Buffer-menu-buffer t)))
-
-(defun Buffer-menu-other-window ()
- "Select this line's buffer in other window, leaving buffer menu visible."
- (interactive)
- (switch-to-buffer-other-window (Buffer-menu-buffer t)))
-
-(defun Buffer-menu-switch-other-window ()
- "Make the other window select this line's buffer.
-The current window remains selected."
- (interactive)
- (display-buffer (Buffer-menu-buffer t)))
-
-(defun Buffer-menu-2-window ()
- "Select this line's buffer, with previous buffer in second window."
- (interactive)
- (let ((buff (Buffer-menu-buffer t))
- (menu (current-buffer))
- (pop-up-windows t))
- (delete-other-windows)
- (switch-to-buffer (other-buffer))
- (pop-to-buffer buff)
- (bury-buffer menu)))
-
-(defun Buffer-menu-toggle-read-only ()
- "Toggle read-only status of buffer on this line, perhaps via version control."
- (interactive)
- (let (char)
- (save-excursion
- (set-buffer (Buffer-menu-buffer t))
- (vc-toggle-read-only)
- (setq char (if buffer-read-only ?% ? )))
- (save-excursion
- (beginning-of-line)
- (forward-char 2)
- (if (/= (following-char) char)
- (let (buffer-read-only)
- (delete-char 1)
- (insert char))))))
-
-
-
-(define-key ctl-x-map "\C-b" 'list-buffers)
-
-(defun list-buffers (&optional files-only)
- "Display a list of names of existing buffers.
-The list is displayed in a buffer named `*Buffer List*'.
-Note that buffers with names starting with spaces are omitted.
-Non-null optional arg FILES-ONLY means mention only file buffers.
-
-The M column contains a * for buffers that are modified.
-The R column contains a % for buffers that are read-only."
- (interactive "P")
- (display-buffer (list-buffers-noselect files-only)))
-
-(defun list-buffers-noselect (&optional files-only)
- "Create and return a buffer with a list of names of existing buffers.
-The buffer is named `*Buffer List*'.
-Note that buffers with names starting with spaces are omitted.
-Non-null optional arg FILES-ONLY means mention only file buffers.
-
-The M column contains a * for buffers that are modified.
-The R column contains a % for buffers that are read-only."
- (let ((old-buffer (current-buffer))
- (standard-output standard-output)
- desired-point)
- (save-excursion
- (set-buffer (get-buffer-create "*Buffer List*"))
- (setq buffer-read-only nil)
- (erase-buffer)
- (setq standard-output (current-buffer))
- (princ "\
- MR Buffer Size Mode File
- -- ------ ---- ---- ----
-")
- ;; Record the column where buffer names start.
- (setq Buffer-menu-buffer-column 4)
- (let ((bl (buffer-list)))
- (while bl
- (let* ((buffer (car bl))
- (name (buffer-name buffer))
- (file (buffer-file-name buffer))
- this-buffer-line-start
- this-buffer-read-only
- this-buffer-size
- this-buffer-mode-name
- this-buffer-directory)
- (save-excursion
- (set-buffer buffer)
- (setq this-buffer-read-only buffer-read-only)
- (setq this-buffer-size (buffer-size))
- (setq this-buffer-mode-name
- (if (eq buffer standard-output)
- "Buffer Menu" mode-name))
- (or file
- ;; No visited file. Check local value of
- ;; list-buffers-directory.
- (if (and (boundp 'list-buffers-directory)
- list-buffers-directory)
- (setq this-buffer-directory list-buffers-directory))))
- (cond
- ;; Don't mention internal buffers.
- ((string= (substring name 0 1) " "))
- ;; Maybe don't mention buffers without files.
- ((and files-only (not file)))
- ;; Otherwise output info.
- (t
- (setq this-buffer-line-start (point))
- ;; Identify current buffer.
- (if (eq buffer old-buffer)
- (progn
- (setq desired-point (point))
- (princ "."))
- (princ " "))
- ;; Identify modified buffers.
- (princ (if (buffer-modified-p buffer) "*" " "))
- ;; Handle readonly status. The output buffer is special
- ;; cased to appear readonly; it is actually made so at a later
- ;; date.
- (princ (if (or (eq buffer standard-output)
- this-buffer-read-only)
- "% "
- " "))
- (princ name)
- ;; Put the buffer name into a text property
- ;; so we don't have to extract it from the text.
- ;; This way we avoid problems with unusual buffer names.
- (setq this-buffer-line-start
- (+ this-buffer-line-start Buffer-menu-buffer-column))
- (let ((name-end (point)))
- (indent-to 17 2)
- (put-text-property this-buffer-line-start name-end
- 'buffer-name name)
- (put-text-property this-buffer-line-start name-end
- 'mouse-face 'highlight))
- (let (size
- mode
- (excess (- (current-column) 17)))
- (setq size (format "%8d" this-buffer-size))
- ;; Ack -- if looking at the *Buffer List* buffer,
- ;; always use "Buffer Menu" mode. Otherwise the
- ;; first time the buffer is created, the mode will be wrong.
- (setq mode this-buffer-mode-name)
- (while (and (> excess 0) (= (aref size 0) ?\ ))
- (setq size (substring size 1))
- (setq excess (1- excess)))
- (princ size)
- (indent-to 27 1)
- (princ mode))
- (indent-to 40 1)
- (or file (setq file this-buffer-directory))
- (if file
- (princ file))
- (princ "\n"))))
- (setq bl (cdr bl))))
- (Buffer-menu-mode)
- ;; DESIRED-POINT doesn't have to be set; it is not when the
- ;; current buffer is not displayed for some reason.
- (and desired-point
- (goto-char desired-point))
- (current-buffer))))
-
-;;; buff-menu.el ends here
diff --git a/lisp/byte-run.el b/lisp/byte-run.el
deleted file mode 100644
index 79b64b241a1..00000000000
--- a/lisp/byte-run.el
+++ /dev/null
@@ -1,161 +0,0 @@
-;;; byte-run.el --- byte-compiler support for inlining
-
-;; Copyright (C) 1992 Free Software Foundation, Inc.
-
-;; Author: Jamie Zawinski <jwz@lucid.com>
-;; Hallvard Furuseth <hbf@ulrik.uio.no>
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; interface to selectively inlining functions.
-;; This only happens when source-code optimization is turned on.
-
-;;; Code:
-
-;; Redefined in byte-optimize.el.
-;; This is not documented--it's not clear that we should promote it.
-(fset 'inline 'progn)
-(put 'inline 'lisp-indent-hook 0)
-
-
-;;; Interface to inline functions.
-
-;; (defmacro proclaim-inline (&rest fns)
-;; "Cause the named functions to be open-coded when called from compiled code.
-;; They will only be compiled open-coded when byte-compile-optimize is true."
-;; (cons 'eval-and-compile
-;; (mapcar '(lambda (x)
-;; (or (memq (get x 'byte-optimizer)
-;; '(nil byte-compile-inline-expand))
-;; (error
-;; "%s already has a byte-optimizer, can't make it inline"
-;; x))
-;; (list 'put (list 'quote x)
-;; ''byte-optimizer ''byte-compile-inline-expand))
-;; fns)))
-
-;; (defmacro proclaim-notinline (&rest fns)
-;; "Cause the named functions to no longer be open-coded."
-;; (cons 'eval-and-compile
-;; (mapcar '(lambda (x)
-;; (if (eq (get x 'byte-optimizer) 'byte-compile-inline-expand)
-;; (put x 'byte-optimizer nil))
-;; (list 'if (list 'eq (list 'get (list 'quote x) ''byte-optimizer)
-;; ''byte-compile-inline-expand)
-;; (list 'put x ''byte-optimizer nil)))
-;; fns)))
-
-;; This has a special byte-hunk-handler in bytecomp.el.
-(defmacro defsubst (name arglist &rest body)
- "Define an inline function. The syntax is just like that of `defun'."
- (or (memq (get name 'byte-optimizer)
- '(nil byte-compile-inline-expand))
- (error "`%s' is a primitive" name))
- (list 'prog1
- (cons 'defun (cons name (cons arglist body)))
- (list 'eval-and-compile
- (list 'put (list 'quote name)
- ''byte-optimizer ''byte-compile-inline-expand))))
-
-(defun make-obsolete (fn new)
- "Make the byte-compiler warn that FUNCTION is obsolete.
-The warning will say that NEW should be used instead.
-If NEW is a string, that is the `use instead' message."
- (interactive "aMake function obsolete: \nxObsoletion replacement: ")
- (let ((handler (get fn 'byte-compile)))
- (if (eq 'byte-compile-obsolete handler)
- (setcar (get fn 'byte-obsolete-info) new)
- (put fn 'byte-obsolete-info (cons new handler))
- (put fn 'byte-compile 'byte-compile-obsolete)))
- fn)
-
-(defun make-obsolete-variable (var new)
- "Make the byte-compiler warn that VARIABLE is obsolete,
-and NEW should be used instead. If NEW is a string, then that is the
-`use instead' message."
- (interactive
- (list
- (let ((str (completing-read "Make variable obsolete: " obarray 'boundp t)))
- (if (equal str "") (error ""))
- (intern str))
- (car (read-from-string (read-string "Obsoletion replacement: ")))))
- (put var 'byte-obsolete-variable new)
- var)
-
-(put 'dont-compile 'lisp-indent-hook 0)
-(defmacro dont-compile (&rest body)
- "Like `progn', but the body always runs interpreted (not compiled).
-If you think you need this, you're probably making a mistake somewhere."
- (list 'eval (list 'quote (if (cdr body) (cons 'progn body) (car body)))))
-
-
-;;; interface to evaluating things at compile time and/or load time
-;;; these macro must come after any uses of them in this file, as their
-;;; definition in the file overrides the magic definitions on the
-;;; byte-compile-macro-environment.
-
-(put 'eval-when-compile 'lisp-indent-hook 0)
-(defmacro eval-when-compile (&rest body)
- "Like `progn', but evaluates the body at compile time.
-The result of the body appears to the compiler as a quoted constant."
- ;; Not necessary because we have it in b-c-initial-macro-environment
- ;; (list 'quote (eval (cons 'progn body)))
- (cons 'progn body))
-
-(put 'eval-and-compile 'lisp-indent-hook 0)
-(defmacro eval-and-compile (&rest body)
- "Like `progn', but evaluates the body at compile time and at load time."
- ;; Remember, it's magic.
- (cons 'progn body))
-
-
-;;; I nuked this because it's not a good idea for users to think of using it.
-;;; These options are a matter of installation preference, and have nothing to
-;;; with particular source files; it's a mistake to suggest to users
-;;; they should associate these with particular source files.
-;;; There is hardly any reason to change these parameters, anyway.
-;;; --rms.
-
-;; (put 'byte-compiler-options 'lisp-indent-hook 0)
-;; (defmacro byte-compiler-options (&rest args)
-;; "Set some compilation-parameters for this file. This will affect only the
-;; file in which it appears; this does nothing when evaluated, and when loaded
-;; from a .el file.
-;;
-;; Each argument to this macro must be a list of a key and a value.
-;;
-;; Keys: Values: Corresponding variable:
-;;
-;; verbose t, nil byte-compile-verbose
-;; optimize t, nil, source, byte byte-compile-optimize
-;; warnings list of warnings byte-compile-warnings
-;; Legal elements: (callargs redefine free-vars unresolved)
-;; file-format emacs18, emacs19 byte-compile-compatibility
-;;
-;; For example, this might appear at the top of a source file:
-;;
-;; (byte-compiler-options
-;; (optimize t)
-;; (warnings (- free-vars)) ; Don't warn about free variables
-;; (file-format emacs19))"
-;; nil)
-
-;;; byte-run.el ends here
diff --git a/lisp/calendar/appt.el b/lisp/calendar/appt.el
deleted file mode 100644
index e5fe7d05428..00000000000
--- a/lisp/calendar/appt.el
+++ /dev/null
@@ -1,600 +0,0 @@
-;;; appt.el --- appointment notification functions.
-
-;; Copyright (C) 1989, 1990, 1994 Free Software Foundation, Inc.
-
-;; Author: Neil Mager <neilm@juliet.ll.mit.edu>
-;; Maintainer: FSF
-;; Keywords: calendar
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;
-;; appt.el - visible and/or audible notification of
-;; appointments from ~/diary file generated from
-;; Edward M. Reingold's calendar.el.
-;;
-;;
-;; 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)
-;;; (add-hook 'diary-hook 'appt-make-list)
-;;;
-;;;
-;;; 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.
-;;;
-;;; You can change the way the appointment window is created/deleted by
-;;; setting the variables
-;;;
-;;; appt-disp-window-function
-;;; and
-;;; appt-delete-window-function
-;;;
-;;; For instance, these variables can be set to functions that display
-;;; appointments in pop-up frames, which are lowered or iconified after
-;;; appt-display-interval seconds.
-;;;
-
-;;; Code:
-
-;; Make sure calendar is loaded when we compile this.
-(require 'calendar)
-
-(provide 'appt)
-
-;;;###autoload
-(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.")
-
-;;;###autoload
-(defvar appt-message-warning-time 12
- "*Time in minutes before an appointment that the warning begins.")
-
-;;;###autoload
-(defvar appt-audible t
- "*Non-nil means beep to indicate appointment.")
-
-;;;###autoload
-(defvar appt-visible t
- "*Non-nil means display appointment message in echo area.")
-
-;;;###autoload
-(defvar appt-display-mode-line t
- "*Non-nil means display minutes to appointment and time on the mode line.")
-
-;;;###autoload
-(defvar appt-msg-window t
- "*Non-nil means display appointment message in another window.")
-
-;;;###autoload
-(defvar appt-display-duration 10
- "*The number of seconds an appointment message is displayed.")
-
-;;;###autoload
-(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.")
-
-(defvar appt-display-interval 3
- "*Number of minutes to wait between checking the appointment list.")
-
-(defvar appt-buffer-name " *appt-buf*"
- "Name of the appointments buffer.")
-
-(defvar appt-disp-window-function 'appt-disp-window
- "Function called to display appointment window.")
-
-(defvar appt-delete-window-function 'appt-delete-window
- "Function called to remove appointment window and buffer.")
-
-(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.
-
-appt-display-interval
- The number of minutes to wait between checking the appointments
- list.
-
-appt-disp-window-function
- Function called to display appointment window. You can customize
- appt.el by setting this variable to a function different from the
- one provided with this package.
-
-appt-delete-window-function
- Function called to remove appointment window and buffer. You can
- customize appt.el by setting this variable to a function different
- from the one provided with this package.
-
-This function is run from the loadst process for display time.
-Therefore, you need to have `(display-time)' in your .emacs file."
-
-
- (if (or (= appt-display-interval 1)
- ;; This is true every appt-display-interval minutes.
- (= 0 (mod (/ (nth 1 (current-time)) 60) appt-display-interval)))
- (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* ((now (decode-time))
- (cur-hour (nth 2 now))
- (cur-min (nth 1 now))
- (cur-comp-time (+ (* cur-hour 60) cur-min)))
-
- ;; At the first check after 12:01am, we should update our
- ;; appointments to today's list.
-
- (if (and (>= cur-comp-time 1)
- (<= cur-comp-time appt-display-interval))
- (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)))
- (funcall
- appt-disp-window-function
- min-to-app new-time
- (car (cdr (car appt-time-msg-list))))
-
- (run-at-time
- (format "%d sec" appt-display-duration)
- nil
- appt-delete-window-function))
- ;;; 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-update t)
- (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)
-
- ;; Make sure we're not in the minibuffer
- ;; before splitting the window.
-
- (if (equal (selected-window) (minibuffer-window))
- (if (other-window 1)
- (select-window (other-window 1))
- (if window-system
- (select-frame (other-frame 1)))))
-
- (let* ((this-buffer (current-buffer))
- (this-window (selected-window))
- (appt-disp-buf (set-buffer (get-buffer-create appt-buffer-name))))
-
- (appt-select-lowest-window)
- (if (cdr (assq 'unsplittable (frame-parameters)))
- ;; In an unsplittable frame, use something somewhere else.
- (display-buffer appt-disp-buf)
- ;; Otherwise, split the bottom window and use the lower part.
- (split-window)
- (pop-to-buffer appt-disp-buf))
- (setq mode-line-format
- (concat "-------------------- Appointment in "
- min-to-app " minutes. " new-time " %-"))
- (insert-string appt-msg)
- (shrink-window-if-larger-than-buffer (get-buffer-window appt-disp-buf t))
- (set-buffer-modified-p nil)
- (raise-frame (selected-frame))
- (select-window this-window)
- (if appt-audible
- (beep 1))))
-
-(defun appt-delete-window ()
- "Function called to undisplay appointment messages.
-Usually just deletes the appointment buffer."
- (let ((window (get-buffer-window appt-buffer-name t)))
- (and window
- (or (and (fboundp 'frame-root-window)
- (eq window (frame-root-window (window-frame window))))
- (delete-window window))))
- (kill-buffer appt-buffer-name)
- (if appt-audible
- (beep 1)))
-
-;; Select the lowest window on the frame.
-(defun appt-select-lowest-window ()
- (let* ((lowest-window (selected-window))
- (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)))))
- (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
-;; We assume that the variables DATE and NUMBER
-;; hold the arguments that list-diary-entries received.
-;; They specify the range of dates that the diary is being processed for.
-
-;;;###autoload
-(defun appt-make-list ()
- ;; We have something to do if the range of dates that the diary is
- ;; considering includes the current date.
- (if (and (not (calendar-date-compare
- (list (calendar-current-date))
- (list original-date)))
- (calendar-date-compare
- (list (calendar-current-date))
- (list (calendar-gregorian-from-absolute
- (+ (calendar-absolute-from-gregorian original-date)
- number)))))
- (save-excursion
- ;; Clear the appointments list, then fill it in from the diary.
- (setq appt-time-msg-list nil)
- (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 ""))
- ;; Skip diary entries for dates before today.
- (while (and entry-list
- (calendar-date-compare
- (car entry-list) (list (calendar-current-date))))
- (setq entry-list (cdr entry-list)))
- ;; Parse the entries for today.
- (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* ((now (decode-time))
- (cur-hour (nth 2 now))
- (cur-min (nth 1 now))
- (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))
-
-(add-hook 'display-time-hook 'appt-check)
-
-;;; appt.el ends here
-
diff --git a/lisp/calendar/cal-china.el b/lisp/calendar/cal-china.el
deleted file mode 100644
index c15f4511c48..00000000000
--- a/lisp/calendar/cal-china.el
+++ /dev/null
@@ -1,455 +0,0 @@
-;;; cal-china.el --- calendar functions for the Chinese calendar.
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: Chinese calendar, calendar, holidays, diary
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the features of calendar.el,
-;; diary.el, and holidays.el that deal with the Chinese calendar. The rules
-;; used for the Chinese calendar are those of Baolin Liu (see L. E. Doggett's
-;; article "Calendars" in the Explanatory Supplement to the Astronomical
-;; Almanac, second edition, 1992) for the calendar as revised at the beginning
-;; of the Qing dynasty in 1644. The nature of the astronomical calculations
-;; is such that precise calculations cannot be made without great expense in
-;; time, so that the calendars produced may not agree perfectly with published
-;; tables--but no two pairs of published tables agree perfectly either! Liu's
-;; rules produce a calendar for 2033 which is not accepted by all authorities.
-;; The date of Chinese New Year is correct from 1644-2051.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(require 'lunar)
-
-(defvar chinese-calendar-celestial-stem
- ["Jia" "Yi" "Bing" "Ding" "Wu" "Ji" "Geng" "Xin" "Ren" "Gui"])
-
-(defvar chinese-calendar-terrestrial-branch
- ["Zi" "Chou" "Yin" "Mao" "Chen" "Si" "Wu" "Wei" "Shen" "You" "Xu" "Hai"])
-
-(defvar chinese-calendar-time-zone
- '(if (< year 1928)
- (+ 465 (/ 40.0 60.0))
- 480)
- "*Number of minutes difference between local standard time for Chinese
-calendar and Coordinated Universal (Greenwich) Time. Default is for Beijing.
-This is an expression in `year' since it changed at 1928-01-01 00:00:00 from
-UT+7:45:40 to UT+8.")
-
-(defvar chinese-calendar-location-name "Beijing"
- "*Name of location used for calculation of Chinese calendar.")
-
-(defvar chinese-calendar-daylight-time-offset 0
-; The correct value is as follows, but the Chinese calendrical
-; authorities do NOT use DST in determining astronomical events:
-; 60
- "*Number of minutes difference between daylight savings and standard time
-for Chinese calendar. Default is for no daylight savings time.")
-
-(defvar chinese-calendar-standard-time-zone-name
- '(if (< year 1928)
- "PMT"
- "CST")
- "*Abbreviated name of standard time zone used for Chinese calendar.")
-
-(defvar chinese-calendar-daylight-time-zone-name "CDT"
- "*Abbreviated name of daylight-savings time zone used for Chinese calendar.")
-
-(defvar chinese-calendar-daylight-savings-starts nil
-; The correct value is as follows, but the Chinese calendrical
-; authorities do NOT use DST in determining astronomical events:
-; '(cond ((< 1986 year) (calendar-nth-named-day 1 0 4 year 10))
-; ((= 1986 year) '(5 4 1986))
-; (t nil))
- "*Sexp giving the date on which daylight savings time starts for Chinese
-calendar. Default is for no daylight savings time. See documentation of
-`calendar-daylight-savings-starts'.")
-
-(defvar chinese-calendar-daylight-savings-ends nil
-; The correct value is as follows, but the Chinese calendrical
-; authorities do NOT use DST in determining astronomical events:
-; '(if (<= 1986 year) (calendar-nth-named-day 1 0 9 year 11))
- "*Sexp giving the date on which daylight savings time ends for Chinese
-calendar. Default is for no daylight savings time. See documentation of
-`calendar-daylight-savings-ends'.")
-
-(defvar chinese-calendar-daylight-savings-starts-time 0
- "*Number of minutes after midnight that daylight savings time starts for
-Chinese calendar. Default is for no daylight savings time.")
-
-(defvar chinese-calendar-daylight-savings-ends-time 0
- "*Number of minutes after midnight that daylight savings time ends for
-Chinese calendar. Default is for no daylight savings time.")
-
-(defun chinese-zodiac-sign-on-or-after (d)
- "Absolute date of first new Zodiac sign on or after absolute date d.
-The Zodiac signs begin when the sun's longitude is a multiple of 30 degrees."
- (let* ((year (extract-calendar-year
- (calendar-gregorian-from-absolute d)))
- (calendar-time-zone (eval chinese-calendar-time-zone))
- (calendar-daylight-time-offset
- chinese-calendar-daylight-time-offset)
- (calendar-standard-time-zone-name
- chinese-calendar-standard-time-zone-name)
- (calendar-daylight-time-zone-name
- chinese-calendar-daylight-time-zone-name)
- (calendar-calendar-daylight-savings-starts
- chinese-calendar-daylight-savings-starts)
- (calendar-daylight-savings-ends
- chinese-calendar-daylight-savings-ends)
- (calendar-daylight-savings-starts-time
- chinese-calendar-daylight-savings-starts-time)
- (calendar-daylight-savings-ends-time
- chinese-calendar-daylight-savings-ends-time))
- (floor
- (calendar-absolute-from-astro
- (solar-date-next-longitude
- (calendar-astro-from-absolute d)
- 30)))))
-
-(defun chinese-new-moon-on-or-after (d)
- "Absolute date of first new moon on or after absolute date d."
- (let* ((year (extract-calendar-year
- (calendar-gregorian-from-absolute d)))
- (calendar-time-zone (eval chinese-calendar-time-zone))
- (calendar-daylight-time-offset
- chinese-calendar-daylight-time-offset)
- (calendar-standard-time-zone-name
- chinese-calendar-standard-time-zone-name)
- (calendar-daylight-time-zone-name
- chinese-calendar-daylight-time-zone-name)
- (calendar-calendar-daylight-savings-starts
- chinese-calendar-daylight-savings-starts)
- (calendar-daylight-savings-ends
- chinese-calendar-daylight-savings-ends)
- (calendar-daylight-savings-starts-time
- chinese-calendar-daylight-savings-starts-time)
- (calendar-daylight-savings-ends-time
- chinese-calendar-daylight-savings-ends-time))
- (floor
- (calendar-absolute-from-astro
- (lunar-new-moon-on-or-after
- (calendar-astro-from-absolute d))))))
-
-(defvar chinese-year-cache
- '((1989 (12 726110) (1 726139) (2 726169) (3 726198) (4 726227) (5 726257)
- (6 726286) (7 726316) (8 726345) (9 726375) (10 726404) (11 726434))
- (1990 (12 726464) (1 726494) (2 726523) (3 726553) (4 726582) (5 726611)
- (5.5 726641) (6 726670) (7 726699) (8 726729) (9 726758) (10 726788)
- (11 726818))
- (1991 (12 726848) (1 726878) (2 726907) (3 726937) (4 726966) (5 726995)
- (6 727025) (7 727054) (8 727083) (9 727113) (10 727142) (11 727172))
- (1992 (12 727202) (1 727232) (2 727261) (3 727291) (4 727321) (5 727350)
- (6 727379) (7 727409) (8 727438) (9 727467) (10 727497) (11 727526))
- (1993 (12 727556) (1 727586) (2 727615) (3 727645) (3.5 727675) (4 727704)
- (5 727734) (6 727763) (7 727793) (8 727822) (9 727851) (10 727881)
- (11 727910))
- (1994 (12 727940) (1 727969) (2 727999) (3 728029) (4 728059) (5 728088)
- (6 728118) (7 728147) (8 728177) (9 728206) (10 728235) (11 728265))
- (1995 (12 728294) (1 728324) (2 728353) (3 728383) (4 728413) (5 728442)
- (6 728472) (7 728501) (8 728531) (8.5 728561) (9 728590) (10 728619)
- (11 728649))
- (1996 (12 728678) (1 728708) (2 728737) (3 728767) (4 728796) (5 728826)
- (6 728856) (7 728885) (8 728915) (9 728944) (10 728974) (11 729004))
- (1997 (12 729033) (1 729062) (2 729092) (3 729121) (4 729151) (5 729180)
- (6 729210) (7 729239) (8 729269) (9 729299) (10 729328) (11 729358))
- (1998 (12 729388) (1 729417) (2 729447) (3 729476) (4 729505) (5 729535)
- (5.5 729564) (6 729593) (7 729623) (8 729653) (9 729682) (10 729712)
- (11 729742))
- (1999 (12 729771) (1 729801) (2 729831) (3 729860) (4 729889) (5 729919)
- (6 729948) (7 729977) (8 730007) (9 730036) (10 730066) (11 730096))
- (2000 (12 730126) (1 730155) (2 730185) (3 730215) (4 730244) (5 730273)
- (6 730303) (7 730332) (8 730361) (9 730391) (10 730420) (11 730450)))
- "An assoc list of Chinese year structures as determined by `chinese-year'.
-
-Values are computed as needed, but to save time, the initial value consists
-of the precomputed years 1989-2000. The code works just as well with this
-set to nil initially (which is how the value for 1989-2000 was computed).")
-
-(defun chinese-year (y)
- "The structure of the Chinese year for Gregorian year Y.
-The result is a list of pairs (i d), where month i begins on absolute date d,
-of the Chinese months from the Chinese month following the solstice in
-Gregorian year Y-1 to the Chinese month of the solstice of Gregorian year Y.
-
-The list is cached for further use."
- (let ((list (cdr (assoc y chinese-year-cache))))
- (if (not list)
- (progn
- (setq list (compute-chinese-year y))
- (setq chinese-year-cache
- (append chinese-year-cache (list (cons y list))))))
- list))
-
-(defun number-chinese-months (list start)
- "Assign month numbers to the lunar months in LIST, starting with START.
-Numbers are assigned sequentially, START, START+1, ..., 11, with half
-numbers used for leap months.
-
-First month of list will never be a leap month, nor will the last."
- (if list
- (if (zerop (- 12 start (length list)))
- ;; List is too short for a leap month
- (cons (list start (car list))
- (number-chinese-months (cdr list) (1+ start)))
- (cons
- ;; First month
- (list start (car list))
- ;; Remaining months
- (if (and (cdr (cdr list));; at least two more months...
- (<= (car (cdr (cdr list)))
- (chinese-zodiac-sign-on-or-after (car (cdr list)))))
- ;; Next month is a leap month
- (cons (list (+ start 0.5) (car (cdr list)))
- (number-chinese-months (cdr (cdr list)) (1+ start)))
- ;; Next month is not a leap month
- (number-chinese-months (cdr list) (1+ start)))))))
-
-(defun chinese-month-list (start end)
- "List of starting dates of Chinese months from START to END."
- (if (<= start end)
- (let ((new-moon (chinese-new-moon-on-or-after start)))
- (if (<= new-moon end)
- (cons new-moon
- (chinese-month-list (1+ new-moon) end))))))
-
-(defun compute-chinese-year (y)
- "Compute the structure of the Chinese year for Gregorian year Y.
-The result is a list of pairs (i d), where month i begins on absolute date d,
-of the Chinese months from the Chinese month following the solstice in
-Gregorian year Y-1 to the Chinese month of the solstice of Gregorian year Y."
- (let* ((next-solstice (chinese-zodiac-sign-on-or-after
- (calendar-absolute-from-gregorian
- (list 12 15 y))))
- (list (chinese-month-list (1+ (chinese-zodiac-sign-on-or-after
- (calendar-absolute-from-gregorian
- (list 12 15 (1- y)))))
- next-solstice))
- (next-sign (chinese-zodiac-sign-on-or-after (car list))))
- (if (= (length list) 12)
- ;; No room for a leap month, just number them 12, 1, 2, ..., 11
- (cons (list 12 (car list))
- (number-chinese-months (cdr list) 1))
- ;; Now we can assign numbers to the list for y
- ;; The first month or two are special
- (if (or (> (car list) next-sign) (>= next-sign (car (cdr list))))
- ;; First month on list is a leap month, second is not
- (append (list (list 11.5 (car list))
- (list 12 (car (cdr list))))
- (number-chinese-months (cdr (cdr list)) 1))
- ;; First month on list is not a leap month
- (append (list (list 12 (car list)))
- (if (>= (chinese-zodiac-sign-on-or-after (car (cdr list)))
- (car (cdr (cdr list))))
- ;; Second month on list is a leap month
- (cons (list 12.5 (car (cdr list)))
- (number-chinese-months (cdr (cdr list)) 1))
- ;; Second month on list is not a leap month
- (number-chinese-months (cdr list) 1)))))))
-
-(defun calendar-absolute-from-chinese (date)
- "The number of days elapsed between the Gregorian date 12/31/1 BC and DATE.
-The Gregorian date Sunday, December 31, 1 BC is imaginary."
- (let* ((cycle (car date))
- (year (car (cdr date)))
- (month (car (cdr (cdr date))))
- (day (car (cdr (cdr (cdr date)))))
- (g-year (+ (* (1- cycle) 60);; years in prior cycles
- (1- year) ;; prior years this cycle
- -2636))) ;; years before absolute date 0
- (+ (1- day);; prior days this month
- (car
- (cdr ;; absolute date of start of this month
- (assoc month (append (memq (assoc 1 (chinese-year g-year))
- (chinese-year g-year))
- (chinese-year (1+ g-year)))))))))
-
-(defun calendar-chinese-from-absolute (date)
- "Compute Chinese date (cycle year month day) corresponding to absolute DATE.
-The absolute date is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
- (let* ((g-year (extract-calendar-year
- (calendar-gregorian-from-absolute date)))
- (c-year (+ g-year 2695))
- (list (append (chinese-year (1- g-year))
- (chinese-year g-year)
- (chinese-year (1+ g-year)))))
- (while (<= (car (cdr (car (cdr list)))) date)
- ;; the first month on the list is in Chinese year c-year
- ;; date is on or after start of second month on list...
- (if (= 1 (car (car (cdr list))))
- ;; second month on list is a new Chinese year
- (setq c-year (1+ c-year)))
- ;; ...so first month on list is of no interest
- (setq list (cdr list)))
- (list (/ (1- c-year) 60)
- (calendar-mod c-year 60)
- (car (car list))
- (1+ (- date (car (cdr (car list))))))))
-
-(defun holiday-chinese-new-year ()
- "Date of Chinese New Year."
- (let ((m displayed-month)
- (y displayed-year))
- (increment-calendar-month m y 1)
- (if (< m 5)
- (let ((chinese-new-year
- (calendar-gregorian-from-absolute
- (car (cdr (assoc 1 (chinese-year y)))))))
- (if (calendar-date-is-visible-p chinese-new-year)
- (list
- (list chinese-new-year
- (format "Chinese New Year (%s)"
- (calendar-chinese-sexagesimal-name (+ y 57))))))))))
-
-(defun calendar-chinese-date-string (&optional date)
- "String of Chinese date of Gregorian DATE.
-Defaults to today's date if DATE is not given."
- (let* ((a-date (calendar-absolute-from-gregorian
- (or date (calendar-current-date))))
- (c-date (calendar-chinese-from-absolute a-date))
- (cycle (car c-date))
- (year (car (cdr c-date)))
- (month (car (cdr (cdr c-date))))
- (day (car (cdr (cdr (cdr c-date)))))
- (this-month (calendar-absolute-from-chinese
- (list cycle year month 1)))
- (next-month (calendar-absolute-from-chinese
- (list (if (= year 60) (1+ cycle) cycle)
- (if (= (floor month) 12) (1+ year) year)
- (calendar-mod (1+ (floor month)) 12)
- 1)))
- (m-cycle (% (+ (* year 5) (floor month)) 60)))
- (format "Cycle %s, year %s (%s), %smonth %s%s, day %s (%s)"
- cycle
- year (calendar-chinese-sexagesimal-name year)
- (if (not (integerp month))
- "second "
- (if (< 30 (- next-month this-month))
- "first "
- ""))
- (floor month)
- (if (integerp month)
- (format " (%s)" (calendar-chinese-sexagesimal-name
- (+ (* 5 year) month 44)))
- "")
- day (calendar-chinese-sexagesimal-name (+ a-date 15)))))
-
-(defun calendar-chinese-sexagesimal-name (n)
- "The N-th name of the Chinese sexagesimal cycle.
-N congruent to 1 gives the first name, N congruent to 2 gives the second name,
-..., N congruent to 60 gives the sixtieth name."
- (format "%s-%s"
- (aref chinese-calendar-celestial-stem (% (1- n) 10))
- (aref chinese-calendar-terrestrial-branch (% (1- n) 12))))
-
-(defun calendar-print-chinese-date ()
- "Show the Chinese date equivalents of date."
- (interactive)
- (message "Computing Chinese date...")
- (message "Chinese date: %s"
- (calendar-chinese-date-string (calendar-cursor-to-date t))))
-
-(defun calendar-goto-chinese-date (date &optional noecho)
- "Move cursor to Chinese date DATE.
-Echo Chinese date unless NOECHO is t."
- (interactive
- (let* ((c (calendar-chinese-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-current-date))))
- (cycle (calendar-read
- "Chinese calendar cycle number (>44): "
- '(lambda (x) (> x 44))
- (int-to-string (car c))))
- (year (calendar-read
- "Year in Chinese cycle (1..60): "
- '(lambda (x) (and (<= 1 x) (<= x 60)))
- (int-to-string (car (cdr c)))))
- (month-list (make-chinese-month-assoc-list
- (chinese-months cycle year)))
- (month (cdr (assoc
- (completing-read "Chinese calendar month: "
- month-list nil t)
- month-list)))
- (last (if (= month
- (car (cdr (cdr
- (calendar-chinese-from-absolute
- (+ 29
- (calendar-absolute-from-chinese
- (list cycle year month 1))))))))
- 30
- 29))
- (day (calendar-read
- (format "Chinese calendar day (1-%d): " last)
- '(lambda (x) (and (<= 1 x) (<= x last))))))
- (list (list cycle year month day))))
- (calendar-goto-date (calendar-gregorian-from-absolute
- (calendar-absolute-from-chinese date)))
- (or noecho (calendar-print-chinese-date)))
-
-(defun chinese-months (c y)
- "A list of the months in cycle C, year Y of the Chinese calendar."
- (let* ((l (memq 1 (append
- (mapcar '(lambda (x)
- (car x))
- (chinese-year (extract-calendar-year
- (calendar-gregorian-from-absolute
- (calendar-absolute-from-chinese
- (list c y 1 1))))))
- (mapcar '(lambda (x)
- (if (> (car x) 11) (car x)))
- (chinese-year (extract-calendar-year
- (calendar-gregorian-from-absolute
- (calendar-absolute-from-chinese
- (list (if (= y 60) (1+ c) c)
- (if (= y 60) 1 y)
- 1 1))))))))))
- l))
-
-(defun make-chinese-month-assoc-list (l)
- "Make list of months L into an assoc list."
- (if (and l (car l))
- (if (and (cdr l) (car (cdr l)))
- (if (= (car l) (floor (car (cdr l))))
- (append
- (list (cons (format "%s (first)" (car l)) (car l))
- (cons (format "%s (second)" (car l)) (car (cdr l))))
- (make-chinese-month-assoc-list (cdr (cdr l))))
- (append
- (list (cons (int-to-string (car l)) (car l)))
- (make-chinese-month-assoc-list (cdr l))))
- (list (cons (int-to-string (car l)) (car l))))))
-
-(defun diary-chinese-date ()
- "Chinese calendar equivalent of date diary entry."
- (format "Chinese date: %s" (calendar-chinese-date-string date)))
-
-(provide 'cal-china)
-
-;;; cal-china.el ends here
diff --git a/lisp/calendar/cal-coptic.el b/lisp/calendar/cal-coptic.el
deleted file mode 100644
index 6fce26c5013..00000000000
--- a/lisp/calendar/cal-coptic.el
+++ /dev/null
@@ -1,234 +0,0 @@
-;;; cal-coptic.el --- calendar functions for the Coptic/Ethiopic calendars.
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: Coptic calendar, Ethiopic calendar, calendar, diary
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the features of calendar.el and
-;; diary.el that deal with the Coptic and Ethiopic calendars.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(require 'cal-julian)
-
-(defvar coptic-calendar-month-name-array
- ["Tut" "Babah" "Hatur" "Kiyahk" "Tubah" "Amshir" "Baramhat" "Barmundah"
- "Bashans" "Baunah" "Abib" "Misra" "al-Nasi"])
-
-(defvar coptic-calendar-epoch (calendar-absolute-from-julian '(8 29 284))
- "Absolute date of start of Coptic calendar = August 29, 284 A.D. (Julian).")
-
-(defconst coptic-name "Coptic")
-
-(defun coptic-calendar-leap-year-p (year)
- "True if YEAR is a leap year on the Coptic calendar."
- (zerop (mod (1+ year) 4)))
-
-(defun coptic-calendar-last-day-of-month (month year)
- "Return last day of MONTH, YEAR on the Coptic calendar.
-The 13th month is not really a month, but the 5 (6 in leap years) day period of
-Nisi (Kebus) at the end of the year."
- (if (< month 13)
- 30
- (if (coptic-calendar-leap-year-p year)
- 6
- 5)))
-
-(defun calendar-absolute-from-coptic (date)
- "Compute absolute date from Coptic date DATE.
-The absolute date is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
- (let ((month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date)))
- (+ (1- coptic-calendar-epoch);; Days before start of calendar
- (* 365 (1- year)) ;; Days in prior years
- (/ year 4) ;; Leap days in prior years
- (* 30 (1- month)) ;; Days in prior months this year
- day))) ;; Days so far this month
-
-
-(defun calendar-coptic-from-absolute (date)
- "Compute the Coptic equivalent for absolute date DATE.
-The result is a list of the form (MONTH DAY YEAR).
-The absolute date is the number of days elapsed since the imaginary
-Gregorian date Sunday, December 31, 1 BC."
- (if (< date coptic-calendar-epoch)
- (list 0 0 0);; pre-Coptic date
- (let* ((approx (/ (- date coptic-calendar-epoch)
- 366)) ;; Approximation from below.
- (year ;; Search forward from the approximation.
- (+ approx
- (calendar-sum y approx
- (>= date (calendar-absolute-from-coptic (list 1 1 (1+ y))))
- 1)))
- (month ;; Search forward from Tot.
- (1+ (calendar-sum m 1
- (> date
- (calendar-absolute-from-coptic
- (list m
- (coptic-calendar-last-day-of-month m year)
- year)))
- 1)))
- (day ;; Calculate the day by subtraction.
- (- date
- (1- (calendar-absolute-from-coptic (list month 1 year))))))
- (list month day year))))
-
-(defun calendar-coptic-date-string (&optional date)
- "String of Coptic date of Gregorian DATE.
-Returns the empty string if DATE is pre-Coptic calendar.
-Defaults to today's date if DATE is not given."
- (let* ((coptic-date (calendar-coptic-from-absolute
- (calendar-absolute-from-gregorian
- (or date (calendar-current-date)))))
- (y (extract-calendar-year coptic-date))
- (m (extract-calendar-month coptic-date)))
- (if (< y 1)
- ""
- (let ((monthname (aref coptic-calendar-month-name-array (1- m)))
- (day (int-to-string (extract-calendar-day coptic-date)))
- (dayname nil)
- (month (int-to-string m))
- (year (int-to-string y)))
- (mapconcat 'eval calendar-date-display-form "")))))
-
-(defun calendar-print-coptic-date ()
- "Show the Coptic calendar equivalent of the selected date."
- (interactive)
- (let ((f (calendar-coptic-date-string (calendar-cursor-to-date t))))
- (if (string-equal f "")
- (message "Date is pre-%s calendar" coptic-name)
- (message f))))
-
-(defun calendar-goto-coptic-date (date &optional noecho)
- "Move cursor to Coptic date DATE.
-Echo Coptic date unless NOECHO is t."
- (interactive (coptic-prompt-for-date))
- (calendar-goto-date (calendar-gregorian-from-absolute
- (calendar-absolute-from-coptic date)))
- (or noecho (calendar-print-coptic-date)))
-
-(defun coptic-prompt-for-date ()
- "Ask for a Coptic date."
- (let* ((today (calendar-current-date))
- (year (calendar-read
- (format "%s calendar year (>0): " coptic-name)
- '(lambda (x) (> x 0))
- (int-to-string
- (extract-calendar-year
- (calendar-coptic-from-absolute
- (calendar-absolute-from-gregorian today))))))
- (completion-ignore-case t)
- (month (cdr (assoc
- (capitalize
- (completing-read
- (format "%s calendar month name: " coptic-name)
- (mapcar 'list
- (append coptic-calendar-month-name-array nil))
- nil t))
- (calendar-make-alist coptic-calendar-month-name-array
- 1 'capitalize))))
- (last (coptic-calendar-last-day-of-month month year))
- (day (calendar-read
- (format "%s calendar day (1-%d): " coptic-name last)
- '(lambda (x) (and (< 0 x) (<= x last))))))
- (list (list month day year))))
-
-(defun diary-coptic-date ()
- "Coptic calendar equivalent of date diary entry."
- (let ((f (calendar-coptic-date-string (calendar-cursor-to-date t))))
- (if (string-equal f "")
- (format "Date is pre-%s calendar" coptic-name)
- f)))
-
-(defconst ethiopic-calendar-month-name-array
- ["Maskaram" "Teqemt" "Khedar" "Takhsas" "Ter" "Yakatit" "Magabit" "Miyazya"
- "Genbot" "Sane" "Hamle" "Nahas" "Paguem"])
-
-(defconst ethiopic-calendar-epoch 2430
- "Absolute date of start of Ethiopic calendar = August 29, 7 C.E. (Julian).")
-
-(defconst ethiopic-name "Ethiopic")
-
-(defun calendar-absolute-from-ethiopic (date)
- "Compute absolute date from Ethiopic date DATE.
-The absolute date is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
- (let ((coptic-calendar-epoch ethiopic-calendar-epoch))
- (calendar-absolute-from-coptic date)))
-
-(defun calendar-ethiopic-from-absolute (date)
- "Compute the Ethiopic equivalent for absolute date DATE.
-The result is a list of the form (MONTH DAY YEAR).
-The absolute date is the number of days elapsed since the imaginary
-Gregorian date Sunday, December 31, 1 BC."
- (let ((coptic-calendar-epoch ethiopic-calendar-epoch))
- (calendar-coptic-from-absolute date)))
-
-(defun calendar-ethiopic-date-string (&optional date)
- "String of Ethiopic date of Gregorian DATE.
-Returns the empty string if DATE is pre-Ethiopic calendar.
-Defaults to today's date if DATE is not given."
- (let ((coptic-calendar-epoch ethiopic-calendar-epoch)
- (coptic-name ethiopic-name)
- (coptic-calendar-month-name-array ethiopic-calendar-month-name-array))
- (calendar-coptic-date-string date)))
-
-(defun calendar-print-ethiopic-date ()
- "Show the Ethiopic calendar equivalent of the selected date."
- (interactive)
- (let ((coptic-calendar-epoch ethiopic-calendar-epoch)
- (coptic-name ethiopic-name)
- (coptic-calendar-month-name-array ethiopic-calendar-month-name-array))
- (call-interactively 'calendar-print-coptic-date)))
-
-(defun calendar-goto-ethiopic-date (date &optional noecho)
- "Move cursor to Ethiopic date DATE.
-Echo Ethiopic date unless NOECHO is t."
- (interactive
- (let ((coptic-calendar-epoch ethiopic-calendar-epoch)
- (coptic-name ethiopic-name)
- (coptic-calendar-month-name-array ethiopic-calendar-month-name-array))
- (coptic-prompt-for-date)))
- (calendar-goto-date (calendar-gregorian-from-absolute
- (calendar-absolute-from-ethiopic date)))
- (or noecho (calendar-print-ethiopic-date)))
-
-(defun diary-ethiopic-date ()
- "Ethiopic calendar equivalent of date diary entry."
- (let ((coptic-calendar-epoch ethiopic-calendar-epoch)
- (coptic-name ethiopic-name)
- (coptic-calendar-month-name-array ethiopic-calendar-month-name-array))
- (diary-coptic-date)))
-
-(provide 'cal-coptic)
-
-;;; cal-coptic.el ends here
diff --git a/lisp/calendar/cal-dst.el b/lisp/calendar/cal-dst.el
deleted file mode 100644
index 3e33f6cb9f3..00000000000
--- a/lisp/calendar/cal-dst.el
+++ /dev/null
@@ -1,397 +0,0 @@
-;;; cal-dst.el --- calendar functions for daylight savings rules.
-
-;; Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Paul Eggert <eggert@twinsun.com>
-;; Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: daylight savings time, calendar, diary, holidays
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the features of calendar.el and
-;; holiday.el that deal with daylight savings time.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(require 'calendar)
-(require 'cal-persia)
-
-(defvar calendar-current-time-zone-cache nil
- "Cache for result of calendar-current-time-zone.")
-
-(defvar calendar-system-time-basis
- (calendar-absolute-from-gregorian '(1 1 1970))
- "Absolute date of starting date of system clock.")
-
-(defun calendar-absolute-from-time (x utc-diff)
- "Absolute local date of time X; local time is UTC-DIFF seconds from UTC.
-
-X is (HIGH . LOW) or (HIGH LOW . IGNORED) where HIGH and LOW are the
-high and low 16 bits, respectively, of the number of seconds since
-1970-01-01 00:00:00 UTC, ignoring leap seconds.
-
-Returns the pair (ABS-DATE . SECONDS) where SECONDS after local midnight on
-absolute date ABS-DATE is the equivalent moment to X."
- (let* ((h (car x))
- (xtail (cdr x))
- (l (+ utc-diff (if (numberp xtail) xtail (car xtail))))
- (u (+ (* 512 (mod h 675)) (floor l 128))))
- ;; Overflow is a terrible thing!
- (cons (+ calendar-system-time-basis
- ;; floor((2^16 h +l) / (60*60*24))
- (* 512 (floor h 675)) (floor u 675))
- ;; (2^16 h +l) mod (60*60*24)
- (+ (* (mod u 675) 128) (mod l 128)))))
-
-(defun calendar-time-from-absolute (abs-date s)
- "Time of absolute date ABS-DATE, S seconds after midnight.
-
-Returns the pair (HIGH . LOW) where HIGH and LOW are the high and low
-16 bits, respectively, of the number of seconds 1970-01-01 00:00:00 UTC,
-ignoring leap seconds, that is the equivalent moment to S seconds after
-midnight UTC on absolute date ABS-DATE."
- (let* ((a (- abs-date calendar-system-time-basis))
- (u (+ (* 163 (mod a 512)) (floor s 128))))
- ;; Overflow is a terrible thing!
- (cons
- ;; floor((60*60*24*a + s) / 2^16)
- (+ a (* 163 (floor a 512)) (floor u 512))
- ;; (60*60*24*a + s) mod 2^16
- (+ (* 128 (mod u 512)) (mod s 128)))))
-
-(defun calendar-next-time-zone-transition (time)
- "Return the time of the next time zone transition after TIME.
-Both TIME and the result are acceptable arguments to current-time-zone.
-Return nil if no such transition can be found."
- (let* ((base 65536);; 2^16 = base of current-time output
- (quarter-multiple 120);; approx = (seconds per quarter year) / base
- (time-zone (current-time-zone time))
- (time-utc-diff (car time-zone))
- hi
- hi-zone
- (hi-utc-diff time-utc-diff)
- (quarters '(2 1 3)))
- ;; Heuristic: probe the time zone offset in the next three calendar
- ;; quarters, looking for a time zone offset different from TIME.
- (while (and quarters (eq time-utc-diff hi-utc-diff))
- (setq hi (cons (+ (car time) (* (car quarters) quarter-multiple)) 0))
- (setq hi-zone (current-time-zone hi))
- (setq hi-utc-diff (car hi-zone))
- (setq quarters (cdr quarters)))
- (and
- time-utc-diff
- hi-utc-diff
- (not (eq time-utc-diff hi-utc-diff))
- ;; Now HI is after the next time zone transition.
- ;; Set LO to TIME, and then binary search to increase LO and decrease HI
- ;; until LO is just before and HI is just after the time zone transition.
- (let* ((tail (cdr time))
- (lo (cons (car time) (if (numberp tail) tail (car tail))))
- probe)
- (while
- ;; Set PROBE to halfway between LO and HI, rounding down.
- ;; If PROBE equals LO, we are done.
- (let* ((lsum (+ (cdr lo) (cdr hi)))
- (hsum (+ (car lo) (car hi) (/ lsum base)))
- (hsumodd (logand 1 hsum)))
- (setq probe (cons (/ (- hsum hsumodd) 2)
- (/ (+ (* hsumodd base) (% lsum base)) 2)))
- (not (equal lo probe)))
- ;; Set either LO or HI to PROBE, depending on probe results.
- (if (eq (car (current-time-zone probe)) hi-utc-diff)
- (setq hi probe)
- (setq lo probe)))
- hi))))
-
-(defun calendar-time-zone-daylight-rules (abs-date utc-diff)
- "Return daylight transition rule for ABS-DATE, UTC-DIFF sec offset from UTC.
-ABS-DATE must specify a day that contains a daylight savings transition.
-The result has the proper form for calendar-daylight-savings-starts'."
- (let* ((date (calendar-gregorian-from-absolute abs-date))
- (weekday (% abs-date 7))
- (m (extract-calendar-month date))
- (d (extract-calendar-day date))
- (y (extract-calendar-year date))
- (last (calendar-last-day-of-month m y))
- (candidate-rules
- (append
- ;; Day D of month M.
- (list (list 'list m d 'year))
- ;; The first WEEKDAY of month M.
- (if (< d 8)
- (list (list 'calendar-nth-named-day 1 weekday m 'year)))
- ;; The last WEEKDAY of month M.
- (if (> d (- last 7))
- (list (list 'calendar-nth-named-day -1 weekday m 'year)))
- ;; The first WEEKDAY after day J of month M, for D-6 < J <= D.
- (let (l)
- (calendar-for-loop j from (max 2 (- d 6)) to (min d (- last 8)) do
- (setq l
- (cons
- (list 'calendar-nth-named-day 1 weekday m 'year j)
- l)))
- l)
- ;; 01-01 and 07-01 for this year's Persian calendar.
- (if (and (= m 3) (<= 20 d) (<= d 21))
- '((calendar-gregorian-from-absolute
- (calendar-absolute-from-persian
- (list 1 1 (- year 621))))))
- (if (and (= m 9) (<= 22 d) (<= d 23))
- '((calendar-gregorian-from-absolute
- (calendar-absolute-from-persian
- (list 7 1 (- year 621))))))))
- (prevday-sec (- -1 utc-diff)) ;; last sec of previous local day
- (year (1+ y)))
- ;; Scan through the next few years until only one rule remains.
- (while
- (let ((rules candidate-rules)
- new-rules)
- (while
- (let*
- ((rule (car rules))
- (date
- ;; The following is much faster than
- ;; (calendar-absolute-from-gregorian (eval rule)).
- (cond ((eq (car rule) 'calendar-nth-named-day)
- (eval (cons 'calendar-nth-named-absday (cdr rule))))
- ((eq (car rule) 'calendar-gregorian-from-absolute)
- (eval (car (cdr rule))))
- (t (let ((g (eval rule)))
- (calendar-absolute-from-gregorian g))))))
- (or (equal
- (current-time-zone
- (calendar-time-from-absolute date prevday-sec))
- (current-time-zone
- (calendar-time-from-absolute (1+ date) prevday-sec)))
- (setq new-rules (cons rule new-rules)))
- (setq rules (cdr rules))))
- ;; If no rules remain, just use the first candidate rule;
- ;; it's wrong in general, but it's right for at least one year.
- (setq candidate-rules (if new-rules (nreverse new-rules)
- (list (car candidate-rules))))
- (setq year (1+ year))
- (cdr candidate-rules)))
- (car candidate-rules)))
-
-(defun calendar-current-time-zone ()
- "Return UTC difference, dst offset, names and rules for current time zone.
-
-Returns (UTC-DIFF DST-OFFSET STD-ZONE DST-ZONE DST-STARTS DST-ENDS
-DST-STARTS-TIME DST-ENDS-TIME), based on a heuristic probing of what the
-system knows:
-
-UTC-DIFF is an integer specifying the number of minutes difference between
- standard time in the current time zone and Coordinated Universal Time
- (Greenwich Mean Time). A negative value means west of Greenwich.
-DST-OFFSET is an integer giving the daylight savings time offset in minutes.
-STD-ZONE is a string giving the name of the time zone when no seasonal time
- adjustment is in effect.
-DST-ZONE is a string giving the name of the time zone when there is a seasonal
- time adjustment in effect.
-DST-STARTS and DST-ENDS are sexps in the variable `year' giving the daylight
- savings time start and end rules, in the form expected by
- `calendar-daylight-savings-starts'.
-DST-STARTS-TIME and DST-ENDS-TIME are integers giving the number of minutes
- after midnight that daylight savings time starts and ends.
-
-If the local area does not use a seasonal time adjustment, STD-ZONE and
-DST-ZONE are equal, and all the DST-* integer variables are 0.
-
-Some operating systems cannot provide all this information to Emacs; in this
-case, `calendar-current-time-zone' returns a list containing nil for the data
-it can't find."
- (or
- calendar-current-time-zone-cache
- (setq
- calendar-current-time-zone-cache
- (let* ((t0 (current-time))
- (t0-zone (current-time-zone t0))
- (t0-utc-diff (car t0-zone))
- (t0-name (car (cdr t0-zone))))
- (if (not t0-utc-diff)
- ;; Little or no time zone information is available.
- (list nil nil t0-name t0-name nil nil nil nil)
- (let* ((t1 (calendar-next-time-zone-transition t0))
- (t2 (and t1 (calendar-next-time-zone-transition t1))))
- (if (not t2)
- ;; This locale does not have daylight savings time.
- (list (/ t0-utc-diff 60) 0 t0-name t0-name nil nil 0 0)
- ;; Use heuristics to find daylight savings parameters.
- (let* ((t1-zone (current-time-zone t1))
- (t1-utc-diff (car t1-zone))
- (t1-name (car (cdr t1-zone)))
- (t1-date-sec (calendar-absolute-from-time t1 t0-utc-diff))
- (t2-date-sec (calendar-absolute-from-time t2 t1-utc-diff))
- (t1-rules (calendar-time-zone-daylight-rules
- (car t1-date-sec) t0-utc-diff))
- (t2-rules (calendar-time-zone-daylight-rules
- (car t2-date-sec) t1-utc-diff))
- (t1-time (/ (cdr t1-date-sec) 60))
- (t2-time (/ (cdr t2-date-sec) 60)))
- (cons
- (/ (min t0-utc-diff t1-utc-diff) 60)
- (cons
- (/ (abs (- t0-utc-diff t1-utc-diff)) 60)
- (if (< t0-utc-diff t1-utc-diff)
- (list t0-name t1-name t1-rules t2-rules t1-time t2-time)
- (list t1-name t0-name t2-rules t1-rules t2-time t1-time)
- )))))))))))
-
-;;; The following eight defvars relating to daylight savings time should NOT be
-;;; marked to go into loaddefs.el where they would be evaluated when Emacs is
-;;; dumped. These variables' appropriate values depend on the conditions under
-;;; which the code is INVOKED; so it's inappropriate to initialize them when
-;;; Emacs is dumped---they should be initialized when calendar.el is loaded.
-;;; They default to US Eastern time if time zone info is not available.
-
-(calendar-current-time-zone)
-
-(defvar calendar-time-zone (or (car calendar-current-time-zone-cache) -300)
- "*Number of minutes difference between local standard time at
-`calendar-location-name' and Coordinated Universal (Greenwich) Time. For
-example, -300 for New York City, -480 for Los Angeles.")
-
-(defvar calendar-daylight-time-offset
- (or (car (cdr calendar-current-time-zone-cache)) 60)
- "*Number of minutes difference between daylight savings and standard time.
-
-If the locale never uses daylight savings time, set this to 0.")
-
-(defvar calendar-standard-time-zone-name
- (or (car (nthcdr 2 calendar-current-time-zone-cache)) "EST")
- "*Abbreviated name of standard time zone at `calendar-location-name'.
-For example, \"EST\" in New York City, \"PST\" for Los Angeles.")
-
-(defvar calendar-daylight-time-zone-name
- (or (car (nthcdr 3 calendar-current-time-zone-cache)) "EDT")
- "*Abbreviated name of daylight-savings time zone at `calendar-location-name'.
-For example, \"EDT\" in New York City, \"PDT\" for Los Angeles.")
-
-;;;###autoload
-(put 'calendar-daylight-savings-starts 'risky-local-variable t)
-(defvar calendar-daylight-savings-starts
- (or (car (nthcdr 4 calendar-current-time-zone-cache))
- (and (not (zerop calendar-daylight-time-offset))
- '(calendar-nth-named-day 1 0 4 year)))
- "*Sexp giving the date on which daylight savings time starts.
-This is an expression in the variable `year' whose value gives the Gregorian
-date in the form (month day year) on which daylight savings time starts. It is
-used to determine the starting date of daylight savings time for the holiday
-list and for correcting times of day in the solar and lunar calculations.
-
-For example, if daylight savings time is mandated to start on October 1,
-you would set `calendar-daylight-savings-starts' to
-
- '(10 1 year)
-
-If it starts on the first Sunday in April, you would set it to
-
- '(calendar-nth-named-day 1 0 4 year)
-
-If the locale never uses daylight savings time, set this to nil.")
-
-;;;###autoload
-(put 'calendar-daylight-savings-ends 'risky-local-variable t)
-(defvar calendar-daylight-savings-ends
- (or (car (nthcdr 5 calendar-current-time-zone-cache))
- (and (not (zerop calendar-daylight-time-offset))
- '(calendar-nth-named-day -1 0 10 year)))
- "*Sexp giving the date on which daylight savings time ends.
-This is an expression in the variable `year' whose value gives the Gregorian
-date in the form (month day year) on which daylight savings time ends. It is
-used to determine the starting date of daylight savings time for the holiday
-list and for correcting times of day in the solar and lunar calculations.
-
-For example, if daylight savings time ends on the last Sunday in October:
-
- '(calendar-nth-named-day -1 0 10 year)
-
-If the locale never uses daylight savings time, set this to nil.")
-
-(defvar calendar-daylight-savings-starts-time
- (or (car (nthcdr 6 calendar-current-time-zone-cache)) 120)
- "*Number of minutes after midnight that daylight savings time starts.")
-
-(defvar calendar-daylight-savings-ends-time
- (or (car (nthcdr 7 calendar-current-time-zone-cache))
- calendar-daylight-savings-starts-time)
- "*Number of minutes after midnight that daylight savings time ends.")
-
-(defun dst-in-effect (date)
- "True if on absolute DATE daylight savings time is in effect.
-Fractional part of DATE is local standard time of day."
- (let* ((year (extract-calendar-year
- (calendar-gregorian-from-absolute (floor date))))
- (dst-starts-gregorian (eval calendar-daylight-savings-starts))
- (dst-ends-gregorian (eval calendar-daylight-savings-ends))
- (dst-starts (and dst-starts-gregorian
- (+ (calendar-absolute-from-gregorian
- dst-starts-gregorian)
- (/ calendar-daylight-savings-starts-time
- 60.0 24.0))))
- (dst-ends (and dst-ends-gregorian
- (+ (calendar-absolute-from-gregorian
- dst-ends-gregorian)
- (/ (- calendar-daylight-savings-ends-time
- calendar-daylight-time-offset)
- 60.0 24.0)))))
- (and dst-starts dst-ends
- (if (< dst-starts dst-ends)
- (and (<= dst-starts date) (< date dst-ends))
- (or (<= dst-starts date) (< date dst-ends))))))
-
-(defun dst-adjust-time (date time &optional style)
- "Adjust, to account for dst on DATE, decimal fraction standard TIME.
-Returns a list (date adj-time zone) where `date' and `adj-time' are the values
-adjusted for `zone'; here `date' is a list (month day year), `adj-time' is a
-decimal fraction time, and `zone' is a string.
-
-Optional parameter STYLE forces the result time to be standard time when its
-value is 'standard and daylight savings time (if available) when its value is
-'daylight.
-
-Conversion to daylight savings time is done according to
-`calendar-daylight-savings-starts', `calendar-daylight-savings-ends',
-`calendar-daylight-savings-starts-time',
-`calendar-daylight-savings-ends-time', and
-`calendar-daylight-savings-offset'."
-
- (let* ((rounded-abs-date (+ (calendar-absolute-from-gregorian date)
- (/ (round (* 60 time)) 60.0 24.0)))
- (dst (dst-in-effect rounded-abs-date))
- (time-zone (if dst
- calendar-daylight-time-zone-name
- calendar-standard-time-zone-name))
- (time (+ rounded-abs-date
- (if dst (/ calendar-daylight-time-offset 24.0 60.0) 0))))
- (list (calendar-gregorian-from-absolute (truncate time))
- (* 24.0 (- time (truncate time)))
- time-zone)))
-
-(provide 'cal-dst)
-
-;;; cal-dst.el ends here
diff --git a/lisp/calendar/cal-french.el b/lisp/calendar/cal-french.el
deleted file mode 100644
index 8f68841d229..00000000000
--- a/lisp/calendar/cal-french.el
+++ /dev/null
@@ -1,244 +0,0 @@
-;;; cal-french.el --- calendar functions for the French Revolutionary calendar.
-
-;; Copyright (C) 1988, 1989, 1992, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: French Revolutionary calendar, calendar, diary
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the features of calendar.el and
-;; diary.el that deal with the French Revolutionary calendar.
-
-;; Technical details of the French Revolutionary calendar can be found in
-;; ``Calendrical Calculations, Part II: Three Historical Calendars'' by
-;; E. M. Reingold, N. Dershowitz, and S. M. Clamen, Software--Practice and
-;; Experience, Volume 23, Number 4 (April, 1993), pages 383-404.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(require 'calendar)
-
-(defvar french-calendar-accents
- (and (char-table-p standard-display-table)
- (equal (aref standard-display-table 161) [161]))
- "True if diacritical marks are available.")
-
-(defconst french-calendar-epoch (calendar-absolute-from-gregorian '(9 22 1792))
- "Absolute date of start of French Revolutionary calendar = September 22, 1792.")
-
-(defconst french-calendar-month-name-array
- (if french-calendar-accents
- ["Vendémiaire" "Brumaire" "Frimaire" "Nivôse" "Pluviôse" "Ventôse"
- "Germinal" "Floréal" "Prairial" "Messidor" "Thermidor" "Fructidor"]
- ["Vende'miaire" "Brumaire" "Frimaire" "Nivo^se" "Pluvio^se" "Vento^se"
- "Germinal" "Flore'al" "Prairial" "Messidor" "Thermidor" "Fructidor"]))
-
-(defconst french-calendar-day-name-array
- ["Primidi" "Duodi" "Tridi" "Quartidi" "Quintidi" "Sextidi" "Septidi"
- "Octidi" "Nonidi" "Decadi"])
-
-(defconst french-calendar-special-days-array
- (if french-calendar-accents
- ["de la Vertu" "du Genie" "du Labour" "de la Raison"
- "de la Récompense" "de la Révolution"]
- ["de la Vertu" "du Genie" "du Labour" "de la Raison" "de la Re'compense"
- "de la Re'volution"]))
-
-(defun french-calendar-leap-year-p (year)
- "True if YEAR is a leap year on the French Revolutionary calendar.
-For Gregorian years 1793 to 1805, the years of actual operation of the
-calendar, uses historical practice based on equinoxes is followed (years 3, 7,
-and 11 were leap years; 15 and 20 would have been leap years). For later
-years uses the proposed rule of Romme (never adopted)--leap years fall every
-four years except century years not divisible 400 and century years that are
-multiples of 4000."
- (or (memq year '(3 7 11));; Actual practice--based on equinoxes
- (memq year '(15 20)) ;; Anticipated practice--based on equinoxes
- (and (> year 20) ;; Romme's proposal--never adopted
- (zerop (% year 4))
- (not (memq (% year 400) '(100 200 300)))
- (not (zerop (% year 4000))))))
-
-(defun french-calendar-last-day-of-month (month year)
- "Return last day of MONTH, YEAR on the French Revolutionary calendar.
-The 13th month is not really a month, but the 5 (6 in leap years) day period of
-`sansculottides' at the end of the year."
- (if (< month 13)
- 30
- (if (french-calendar-leap-year-p year)
- 6
- 5)))
-
-(defun calendar-absolute-from-french (date)
- "Compute absolute date from French Revolutionary date DATE.
-The absolute date is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
- (let ((month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date)))
- (+ (* 365 (1- year));; Days in prior years
- ;; Leap days in prior years
- (if (< year 20)
- (/ year 4);; Actual and anticipated practice (years 3, 7, 11, 15)
- ;; Romme's proposed rule (using the Principle of Inclusion/Exclusion)
- (+ (/ (1- year) 4);; Luckily, there were 4 leap years before year 20
- (- (/ (1- year) 100))
- (/ (1- year) 400)
- (- (/ (1- year) 4000))))
- (* 30 (1- month));; Days in prior months this year
- day;; Days so far this month
- (1- french-calendar-epoch))));; Days before start of calendar
-
-(defun calendar-french-from-absolute (date)
- "Compute the French Revolutionary equivalent for absolute date DATE.
-The result is a list of the form (MONTH DAY YEAR).
-The absolute date is the number of days elapsed since the
-\(imaginary) Gregorian date Sunday, December 31, 1 BC."
- (if (< date french-calendar-epoch)
- (list 0 0 0);; pre-French Revolutionary date
- (let* ((approx ;; Approximation from below.
- (/ (- date french-calendar-epoch) 366))
- (year ;; Search forward from the approximation.
- (+ approx
- (calendar-sum y approx
- (>= date (calendar-absolute-from-french (list 1 1 (1+ y))))
- 1)))
- (month ;; Search forward from Vendemiaire.
- (1+ (calendar-sum m 1
- (> date
- (calendar-absolute-from-french
- (list m
- (french-calendar-last-day-of-month m year)
- year)))
- 1)))
- (day ;; Calculate the day by subtraction.
- (- date
- (1- (calendar-absolute-from-french (list month 1 year))))))
- (list month day year))))
-
-(defun calendar-french-date-string (&optional date)
- "String of French Revolutionary date of Gregorian DATE.
-Returns the empty string if DATE is pre-French Revolutionary.
-Defaults to today's date if DATE is not given."
- (let* ((french-date (calendar-french-from-absolute
- (calendar-absolute-from-gregorian
- (or date (calendar-current-date)))))
- (y (extract-calendar-year french-date))
- (m (extract-calendar-month french-date))
- (d (extract-calendar-day french-date)))
- (cond
- ((< y 1) "")
- ((= m 13) (format (if french-calendar-accents
- "Jour %s de l'Année %d de la Révolution"
- "Jour %s de l'Anne'e %d de la Re'volution")
- (aref french-calendar-special-days-array (1- d))
- y))
- (t (format
- (if french-calendar-accents
- "Décade %s, %s de %s de l'Année %d de la Révolution"
- "De'cade %s, %s de %s de l'Anne'e %d de la Re'volution")
- (make-string (1+ (/ (1- d) 10)) ?I)
- (aref french-calendar-day-name-array (% (1- d) 10))
- (aref french-calendar-month-name-array (1- m))
- y)))))
-
-(defun calendar-print-french-date ()
- "Show the French Revolutionary calendar equivalent of the selected date."
- (interactive)
- (let ((f (calendar-french-date-string (calendar-cursor-to-date t))))
- (if (string-equal f "")
- (message "Date is pre-French Revolution")
- (message f))))
-
-(defun calendar-goto-french-date (date &optional noecho)
- "Move cursor to French Revolutionary date DATE.
-Echo French Revolutionary date unless NOECHO is t."
- (interactive
- (let* ((year (calendar-read
- (if french-calendar-accents
- "Année de la Révolution (>0): "
- "Anne'e de la Re'volution (>0): ")
- '(lambda (x) (> x 0))
- (int-to-string
- (extract-calendar-year
- (calendar-french-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-current-date)))))))
- (month-list
- (mapcar 'list
- (append french-calendar-month-name-array
- (if (french-calendar-leap-year-p year)
- (mapcar
- '(lambda (x) (concat "Jour " x))
- french-calendar-special-days-array)
- (reverse
- (cdr;; we don't want rev. day in a non-leap yr.
- (reverse
- (mapcar
- '(lambda (x) (concat "Jour " x))
- french-calendar-special-days-array))))))))
- (completion-ignore-case t)
- (month (cdr (assoc
- (capitalize
- (completing-read
- "Mois ou Sansculottide: "
- month-list
- nil t))
- (calendar-make-alist
- month-list
- 1
- '(lambda (x) (capitalize (car x)))))))
- (decade (if (> month 12)
- 1
- (calendar-read
- (if french-calendar-accents
- "Décade (1-3): "
- "De'cade (1-3): ")
- '(lambda (x) (memq x '(1 2 3))))))
- (day (if (> month 12)
- (- month 12)
- (calendar-read
- "Jour (1-10): "
- '(lambda (x) (and (<= 1 x) (<= x 10))))))
- (month (if (> month 12) 13 month))
- (day (+ day (* 10 (1- decade)))))
- (list (list month day year))))
- (calendar-goto-date (calendar-gregorian-from-absolute
- (calendar-absolute-from-french date)))
- (or noecho (calendar-print-french-date)))
-
-(defun diary-french-date ()
- "French calendar equivalent of date diary entry."
- (let ((f (calendar-french-date-string (calendar-cursor-to-date t))))
- (if (string-equal f "")
- "Date is pre-French Revolution"
- f)))
-
-(provide 'cal-french)
-
-;;; cal-french.el ends here
diff --git a/lisp/calendar/cal-hebrew.el b/lisp/calendar/cal-hebrew.el
deleted file mode 100644
index 23e6d694b08..00000000000
--- a/lisp/calendar/cal-hebrew.el
+++ /dev/null
@@ -1,1180 +0,0 @@
-;;; cal-hebrew.el --- calendar functions for the Hebrew calendar.
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Nachum Dershowitz <nachum@cs.uiuc.edu>
-;; Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: Hebrew calendar, calendar, diary
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the features of calendar.el and
-;; diary.el that deal with the Hebrew calendar.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(require 'calendar)
-
-(defun calendar-hebrew-from-absolute (date)
- "Compute the Hebrew date (month day year) corresponding to absolute DATE.
-The absolute date is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
- (let* ((greg-date (calendar-gregorian-from-absolute date))
- (month (aref [9 10 11 12 1 2 3 4 7 7 7 8]
- (1- (extract-calendar-month greg-date))))
- (day)
- (year (+ 3760 (extract-calendar-year greg-date))))
- (while (>= date (calendar-absolute-from-hebrew (list 7 1 (1+ year))))
- (setq year (1+ year)))
- (let ((length (hebrew-calendar-last-month-of-year year)))
- (while (> date
- (calendar-absolute-from-hebrew
- (list month
- (hebrew-calendar-last-day-of-month month year)
- year)))
- (setq month (1+ (% month length)))))
- (setq day (1+
- (- date (calendar-absolute-from-hebrew (list month 1 year)))))
- (list month day year)))
-
-(defun hebrew-calendar-leap-year-p (year)
- "t if YEAR is a Hebrew calendar leap year."
- (< (% (1+ (* 7 year)) 19) 7))
-
-(defun hebrew-calendar-last-month-of-year (year)
- "The last month of the Hebrew calendar YEAR."
- (if (hebrew-calendar-leap-year-p year)
- 13
- 12))
-
-(defun hebrew-calendar-last-day-of-month (month year)
- "The last day of MONTH in YEAR."
- (if (or (memq month (list 2 4 6 10 13))
- (and (= month 12) (not (hebrew-calendar-leap-year-p year)))
- (and (= month 8) (not (hebrew-calendar-long-heshvan-p year)))
- (and (= month 9) (hebrew-calendar-short-kislev-p year)))
- 29
- 30))
-
-(defun hebrew-calendar-elapsed-days (year)
- "Days from Sun. prior to start of Hebrew calendar to mean conjunction of Tishri of Hebrew YEAR."
- (let* ((months-elapsed
- (+ (* 235 (/ (1- year) 19));; Months in complete cycles so far.
- (* 12 (% (1- year) 19)) ;; Regular months in this cycle
- (/ (1+ (* 7 (% (1- year) 19))) 19)));; Leap months this cycle
- (parts-elapsed (+ 204 (* 793 (% months-elapsed 1080))))
- (hours-elapsed (+ 5
- (* 12 months-elapsed)
- (* 793 (/ months-elapsed 1080))
- (/ parts-elapsed 1080)))
- (parts ;; Conjunction parts
- (+ (* 1080 (% hours-elapsed 24)) (% parts-elapsed 1080)))
- (day ;; Conjunction day
- (+ 1 (* 29 months-elapsed) (/ hours-elapsed 24)))
- (alternative-day
- (if (or (>= parts 19440) ;; If the new moon is at or after midday,
- (and (= (% day 7) 2);; ...or is on a Tuesday...
- (>= parts 9924) ;; at 9 hours, 204 parts or later...
- (not (hebrew-calendar-leap-year-p year)));; of a
- ;; common year,
- (and (= (% day 7) 1);; ...or is on a Monday...
- (>= parts 16789) ;; at 15 hours, 589 parts or later...
- (hebrew-calendar-leap-year-p (1- year))));; at the end
- ;; of a leap year
- ;; Then postpone Rosh HaShanah one day
- (1+ day)
- ;; Else
- day)))
- (if ;; If Rosh HaShanah would occur on Sunday, Wednesday, or Friday
- (memq (% alternative-day 7) (list 0 3 5))
- ;; Then postpone it one (more) day and return
- (1+ alternative-day)
- ;; Else return
- alternative-day)))
-
-(defun hebrew-calendar-days-in-year (year)
- "Number of days in Hebrew YEAR."
- (- (hebrew-calendar-elapsed-days (1+ year))
- (hebrew-calendar-elapsed-days year)))
-
-(defun hebrew-calendar-long-heshvan-p (year)
- "t if Heshvan is long in Hebrew YEAR."
- (= (% (hebrew-calendar-days-in-year year) 10) 5))
-
-(defun hebrew-calendar-short-kislev-p (year)
- "t if Kislev is short in Hebrew YEAR."
- (= (% (hebrew-calendar-days-in-year year) 10) 3))
-
-(defun calendar-absolute-from-hebrew (date)
- "Absolute date of Hebrew DATE.
-The absolute date is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
- (let* ((month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date)))
- (+ day ;; Days so far this month.
- (if (< month 7);; before Tishri
- ;; Then add days in prior months this year before and after Nisan
- (+ (calendar-sum
- m 7 (<= m (hebrew-calendar-last-month-of-year year))
- (hebrew-calendar-last-day-of-month m year))
- (calendar-sum
- m 1 (< m month)
- (hebrew-calendar-last-day-of-month m year)))
- ;; Else add days in prior months this year
- (calendar-sum
- m 7 (< m month)
- (hebrew-calendar-last-day-of-month m year)))
- (hebrew-calendar-elapsed-days year);; Days in prior years.
- -1373429))) ;; Days elapsed before absolute date 1.
-
-(defvar calendar-hebrew-month-name-array-common-year
- ["Nisan" "Iyar" "Sivan" "Tammuz" "Av" "Elul" "Tishri"
- "Heshvan" "Kislev" "Teveth" "Shevat" "Adar"])
-
-(defvar calendar-hebrew-month-name-array-leap-year
- ["Nisan" "Iyar" "Sivan" "Tammuz" "Av" "Elul" "Tishri"
- "Heshvan" "Kislev" "Teveth" "Shevat" "Adar I" "Adar II"])
-
-(defun calendar-hebrew-date-string (&optional date)
- "String of Hebrew date before sunset of Gregorian DATE.
-Defaults to today's date if DATE is not given.
-Driven by the variable `calendar-date-display-form'."
- (let* ((hebrew-date (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (or date (calendar-current-date)))))
- (calendar-month-name-array
- (if (hebrew-calendar-leap-year-p (extract-calendar-year hebrew-date))
- calendar-hebrew-month-name-array-leap-year
- calendar-hebrew-month-name-array-common-year)))
- (calendar-date-string hebrew-date nil t)))
-
-(defun calendar-print-hebrew-date ()
- "Show the Hebrew calendar equivalent of the date under the cursor."
- (interactive)
- (message "Hebrew date (until sunset): %s"
- (calendar-hebrew-date-string (calendar-cursor-to-date t))))
-
-(defun hebrew-calendar-yahrzeit (death-date year)
- "Absolute date of the anniversary of Hebrew DEATH-DATE in Hebrew YEAR."
- (let* ((death-day (extract-calendar-day death-date))
- (death-month (extract-calendar-month death-date))
- (death-year (extract-calendar-year death-date)))
- (cond
- ;; If it's Heshvan 30 it depends on the first anniversary; if
- ;; that was not Heshvan 30, use the day before Kislev 1.
- ((and (= death-month 8)
- (= death-day 30)
- (not (hebrew-calendar-long-heshvan-p (1+ death-year))))
- (1- (calendar-absolute-from-hebrew (list 9 1 year))))
- ;; If it's Kislev 30 it depends on the first anniversary; if
- ;; that was not Kislev 30, use the day before Teveth 1.
- ((and (= death-month 9)
- (= death-day 30)
- (hebrew-calendar-short-kislev-p (1+ death-year)))
- (1- (calendar-absolute-from-hebrew (list 10 1 year))))
- ;; If it's Adar II, use the same day in last month of
- ;; year (Adar or Adar II).
- ((= death-month 13)
- (calendar-absolute-from-hebrew
- (list (hebrew-calendar-last-month-of-year year) death-day year)))
- ;; If it's the 30th in Adar I and year is not a leap year
- ;; (so Adar has only 29 days), use the last day in Shevat.
- ((and (= death-day 30)
- (= death-month 12)
- (not (hebrew-calendar-leap-year-p year)))
- (calendar-absolute-from-hebrew (list 11 30 year)))
- ;; In all other cases, use the normal anniversary of the date of death.
- (t (calendar-absolute-from-hebrew
- (list death-month death-day year))))))
-
-(defun calendar-goto-hebrew-date (date &optional noecho)
- "Move cursor to Hebrew DATE; echo Hebrew date unless NOECHO is t."
- (interactive
- (let* ((today (calendar-current-date))
- (year (calendar-read
- "Hebrew calendar year (>3760): "
- '(lambda (x) (> x 3760))
- (int-to-string
- (extract-calendar-year
- (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian today))))))
- (month-array (if (hebrew-calendar-leap-year-p year)
- calendar-hebrew-month-name-array-leap-year
- calendar-hebrew-month-name-array-common-year))
- (completion-ignore-case t)
- (month (cdr (assoc
- (capitalize
- (completing-read
- "Hebrew calendar month name: "
- (mapcar 'list (append month-array nil))
- (if (= year 3761)
- '(lambda (x)
- (let ((m (cdr
- (assoc
- (car x)
- (calendar-make-alist
- month-array)))))
- (< 0
- (calendar-absolute-from-hebrew
- (list m
- (hebrew-calendar-last-day-of-month
- m year)
- year))))))
-
- t))
- (calendar-make-alist month-array 1 'capitalize))))
- (last (hebrew-calendar-last-day-of-month month year))
- (first (if (and (= year 3761) (= month 10))
- 18 1))
- (day (calendar-read
- (format "Hebrew calendar day (%d-%d): "
- first last)
- '(lambda (x) (and (<= first x) (<= x last))))))
- (list (list month day year))))
- (calendar-goto-date (calendar-gregorian-from-absolute
- (calendar-absolute-from-hebrew date)))
- (or noecho (calendar-print-hebrew-date)))
-
-(defun holiday-hebrew (month day string)
- "Holiday on MONTH, DAY (Hebrew) called STRING.
-If MONTH, DAY (Hebrew) is visible, the value returned is corresponding
-Gregorian date in the form of the list (((month day year) STRING)). Returns
-nil if it is not visible in the current calendar window."
- (if (memq displayed-month;; This test is only to speed things up a bit;
- (list ;; it works fine without the test too.
- (if (< 11 month) (- month 11) (+ month 1))
- (if (< 10 month) (- month 10) (+ month 2))
- (if (< 9 month) (- month 9) (+ month 3))
- (if (< 8 month) (- month 8) (+ month 4))
- (if (< 7 month) (- month 7) (+ month 5))))
- (let ((m1 displayed-month)
- (y1 displayed-year)
- (m2 displayed-month)
- (y2 displayed-year)
- (year))
- (increment-calendar-month m1 y1 -1)
- (increment-calendar-month m2 y2 1)
- (let* ((start-date (calendar-absolute-from-gregorian
- (list m1 1 y1)))
- (end-date (calendar-absolute-from-gregorian
- (list m2 (calendar-last-day-of-month m2 y2) y2)))
- (hebrew-start (calendar-hebrew-from-absolute start-date))
- (hebrew-end (calendar-hebrew-from-absolute end-date))
- (hebrew-y1 (extract-calendar-year hebrew-start))
- (hebrew-y2 (extract-calendar-year hebrew-end)))
- (setq year (if (< 6 month) hebrew-y2 hebrew-y1))
- (let ((date (calendar-gregorian-from-absolute
- (calendar-absolute-from-hebrew
- (list month day year)))))
- (if (calendar-date-is-visible-p date)
- (list (list date string))))))))
-
-(defun holiday-rosh-hashanah-etc ()
- "List of dates related to Rosh Hashanah, as visible in calendar window."
- (if (or (< displayed-month 8)
- (> displayed-month 11))
- nil;; None of the dates is visible
- (let* ((abs-r-h (calendar-absolute-from-hebrew
- (list 7 1 (+ displayed-year 3761))))
- (mandatory
- (list
- (list (calendar-gregorian-from-absolute abs-r-h)
- (format "Rosh HaShanah %d" (+ 3761 displayed-year)))
- (list (calendar-gregorian-from-absolute (+ abs-r-h 9))
- "Yom Kippur")
- (list (calendar-gregorian-from-absolute (+ abs-r-h 14))
- "Sukkot")
- (list (calendar-gregorian-from-absolute (+ abs-r-h 21))
- "Shemini Atzeret")
- (list (calendar-gregorian-from-absolute (+ abs-r-h 22))
- "Simchat Torah")))
- (optional
- (list
- (list (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before 6 (- abs-r-h 4)))
- "Selichot (night)")
- (list (calendar-gregorian-from-absolute (1- abs-r-h))
- "Erev Rosh HaShanah")
- (list (calendar-gregorian-from-absolute (1+ abs-r-h))
- "Rosh HaShanah (second day)")
- (list (calendar-gregorian-from-absolute
- (if (= (% abs-r-h 7) 4) (+ abs-r-h 3) (+ abs-r-h 2)))
- "Tzom Gedaliah")
- (list (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before 6 (+ 7 abs-r-h)))
- "Shabbat Shuvah")
- (list (calendar-gregorian-from-absolute (+ abs-r-h 8))
- "Erev Yom Kippur")
- (list (calendar-gregorian-from-absolute (+ abs-r-h 13))
- "Erev Sukkot")
- (list (calendar-gregorian-from-absolute (+ abs-r-h 15))
- "Sukkot (second day)")
- (list (calendar-gregorian-from-absolute (+ abs-r-h 16))
- "Hol Hamoed Sukkot (first day)")
- (list (calendar-gregorian-from-absolute (+ abs-r-h 17))
- "Hol Hamoed Sukkot (second day)")
- (list (calendar-gregorian-from-absolute (+ abs-r-h 18))
- "Hol Hamoed Sukkot (third day)")
- (list (calendar-gregorian-from-absolute (+ abs-r-h 19))
- "Hol Hamoed Sukkot (fourth day)")
- (list (calendar-gregorian-from-absolute (+ abs-r-h 20))
- "Hoshannah Rabbah")))
- (output-list
- (filter-visible-calendar-holidays mandatory)))
- (if all-hebrew-calendar-holidays
- (setq output-list
- (append
- (filter-visible-calendar-holidays optional)
- output-list)))
- output-list)))
-
-(defun holiday-hanukkah ()
- "List of dates related to Hanukkah, as visible in calendar window."
- (if (memq displayed-month;; This test is only to speed things up a bit;
- '(10 11 12 1 2));; it works fine without the test too.
- (let ((m displayed-month)
- (y displayed-year))
- (increment-calendar-month m y 1)
- (let* ((h-y (extract-calendar-year
- (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (list m (calendar-last-day-of-month m y) y)))))
- (abs-h (calendar-absolute-from-hebrew (list 9 25 h-y))))
- (filter-visible-calendar-holidays
- (list
- (list (calendar-gregorian-from-absolute (1- abs-h))
- "Erev Hanukkah")
- (list (calendar-gregorian-from-absolute abs-h)
- "Hanukkah (first day)")
- (list (calendar-gregorian-from-absolute (1+ abs-h))
- "Hanukkah (second day)")
- (list (calendar-gregorian-from-absolute (+ abs-h 2))
- "Hanukkah (third day)")
- (list (calendar-gregorian-from-absolute (+ abs-h 3))
- "Hanukkah (fourth day)")
- (list (calendar-gregorian-from-absolute (+ abs-h 4))
- "Hanukkah (fifth day)")
- (list (calendar-gregorian-from-absolute (+ abs-h 5))
- "Hanukkah (sixth day)")
- (list (calendar-gregorian-from-absolute (+ abs-h 6))
- "Hanukkah (seventh day)")
- (list (calendar-gregorian-from-absolute (+ abs-h 7))
- "Hanukkah (eighth day)")))))))
-
-(defun holiday-passover-etc ()
- "List of dates related to Passover, as visible in calendar window."
- (if (< 7 displayed-month)
- nil;; None of the dates is visible
- (let* ((abs-p (calendar-absolute-from-hebrew
- (list 1 15 (+ displayed-year 3760))))
- (mandatory
- (list
- (list (calendar-gregorian-from-absolute abs-p)
- "Passover")
- (list (calendar-gregorian-from-absolute (+ abs-p 50))
- "Shavuot")))
- (optional
- (list
- (list (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before 6 (- abs-p 43)))
- "Shabbat Shekalim")
- (list (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before 6 (- abs-p 30)))
- "Shabbat Zachor")
- (list (calendar-gregorian-from-absolute
- (if (= (% abs-p 7) 2) (- abs-p 33) (- abs-p 31)))
- "Fast of Esther")
- (list (calendar-gregorian-from-absolute (- abs-p 31))
- "Erev Purim")
- (list (calendar-gregorian-from-absolute (- abs-p 30))
- "Purim")
- (list (calendar-gregorian-from-absolute
- (if (zerop (% abs-p 7)) (- abs-p 28) (- abs-p 29)))
- "Shushan Purim")
- (list (calendar-gregorian-from-absolute
- (- (calendar-dayname-on-or-before 6 (- abs-p 14)) 7))
- "Shabbat Parah")
- (list (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before 6 (- abs-p 14)))
- "Shabbat HaHodesh")
- (list (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before 6 (1- abs-p)))
- "Shabbat HaGadol")
- (list (calendar-gregorian-from-absolute (1- abs-p))
- "Erev Passover")
- (list (calendar-gregorian-from-absolute (1+ abs-p))
- "Passover (second day)")
- (list (calendar-gregorian-from-absolute (+ abs-p 2))
- "Hol Hamoed Passover (first day)")
- (list (calendar-gregorian-from-absolute (+ abs-p 3))
- "Hol Hamoed Passover (second day)")
- (list (calendar-gregorian-from-absolute (+ abs-p 4))
- "Hol Hamoed Passover (third day)")
- (list (calendar-gregorian-from-absolute (+ abs-p 5))
- "Hol Hamoed Passover (fourth day)")
- (list (calendar-gregorian-from-absolute (+ abs-p 6))
- "Passover (seventh day)")
- (list (calendar-gregorian-from-absolute (+ abs-p 7))
- "Passover (eighth day)")
- (list (calendar-gregorian-from-absolute (+ abs-p 12))
- "Yom HaShoah")
- (list (calendar-gregorian-from-absolute
- (if (zerop (% abs-p 7))
- (+ abs-p 18)
- (if (= (% abs-p 7) 6)
- (+ abs-p 19)
- (+ abs-p 20))))
- "Yom HaAtzma'ut")
- (list (calendar-gregorian-from-absolute (+ abs-p 33))
- "Lag BaOmer")
- (list (calendar-gregorian-from-absolute (+ abs-p 43))
- "Yom Yerushalim")
- (list (calendar-gregorian-from-absolute (+ abs-p 49))
- "Erev Shavuot")
- (list (calendar-gregorian-from-absolute (+ abs-p 51))
- "Shavuot (second day)")))
- (output-list
- (filter-visible-calendar-holidays mandatory)))
- (if all-hebrew-calendar-holidays
- (setq output-list
- (append
- (filter-visible-calendar-holidays optional)
- output-list)))
- output-list)))
-
-(defun holiday-tisha-b-av-etc ()
- "List of dates around Tisha B'Av, as visible in calendar window."
- (if (or (< displayed-month 5)
- (> displayed-month 9))
- nil;; None of the dates is visible
- (let* ((abs-t-a (calendar-absolute-from-hebrew
- (list 5 9 (+ displayed-year 3760)))))
-
- (filter-visible-calendar-holidays
- (list
- (list (calendar-gregorian-from-absolute
- (if (= (% abs-t-a 7) 6) (- abs-t-a 20) (- abs-t-a 21)))
- "Tzom Tammuz")
- (list (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before 6 abs-t-a))
- "Shabbat Hazon")
- (list (calendar-gregorian-from-absolute
- (if (= (% abs-t-a 7) 6) (1+ abs-t-a) abs-t-a))
- "Tisha B'Av")
- (list (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before 6 (+ abs-t-a 7)))
- "Shabbat Nahamu"))))))
-
-(defun list-hebrew-diary-entries ()
- "Add any Hebrew date entries from the diary file to `diary-entries-list'.
-Hebrew date diary entries must be prefaced by `hebrew-diary-entry-symbol'
-\(normally an `H'). The same diary date forms govern the style of the Hebrew
-calendar entries, except that the Hebrew month names must be spelled in full.
-The Hebrew months are numbered from 1 to 13 with Nisan being 1, 12 being
-Adar I and 13 being Adar II; you must use `Adar I' if you want Adar of a
-common Hebrew year. If a Hebrew date diary entry begins with a
-`diary-nonmarking-symbol', the entry will appear in the diary listing, but will
-not be marked in the calendar. This function is provided for use with the
-`nongregorian-diary-listing-hook'."
- (if (< 0 number)
- (let ((buffer-read-only nil)
- (diary-modified (buffer-modified-p))
- (gdate original-date)
- (mark (regexp-quote diary-nonmarking-symbol)))
- (calendar-for-loop i from 1 to number do
- (let* ((d diary-date-forms)
- (hdate (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian gdate)))
- (month (extract-calendar-month hdate))
- (day (extract-calendar-day hdate))
- (year (extract-calendar-year hdate)))
- (while d
- (let*
- ((date-form (if (equal (car (car d)) 'backup)
- (cdr (car d))
- (car d)))
- (backup (equal (car (car d)) 'backup))
- (dayname
- (concat
- (calendar-day-name gdate) "\\|"
- (substring (calendar-day-name gdate) 0 3) ".?"))
- (calendar-month-name-array
- calendar-hebrew-month-name-array-leap-year)
- (monthname
- (concat
- "\\*\\|"
- (calendar-month-name month)))
- (month (concat "\\*\\|0*" (int-to-string month)))
- (day (concat "\\*\\|0*" (int-to-string day)))
- (year
- (concat
- "\\*\\|0*" (int-to-string year)
- (if abbreviated-calendar-year
- (concat "\\|" (int-to-string (% year 100)))
- "")))
- (regexp
- (concat
- "\\(\\`\\|\^M\\|\n\\)" mark "?"
- (regexp-quote hebrew-diary-entry-symbol)
- "\\("
- (mapconcat 'eval date-form "\\)\\(")
- "\\)"))
- (case-fold-search t))
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (if backup (re-search-backward "\\<" nil t))
- (if (and (or (char-equal (preceding-char) ?\^M)
- (char-equal (preceding-char) ?\n))
- (not (looking-at " \\|\^I")))
- ;; Diary entry that consists only of date.
- (backward-char 1)
- ;; Found a nonempty diary entry--make it visible and
- ;; add it to the list.
- (let ((entry-start (point))
- (date-start))
- (re-search-backward "\^M\\|\n\\|\\`")
- (setq date-start (point))
- (re-search-forward "\^M\\|\n" nil t 2)
- (while (looking-at " \\|\^I")
- (re-search-forward "\^M\\|\n" nil t))
- (backward-char 1)
- (subst-char-in-region date-start (point) ?\^M ?\n t)
- (add-to-diary-list
- gdate (buffer-substring entry-start (point)))))))
- (setq d (cdr d))))
- (setq gdate
- (calendar-gregorian-from-absolute
- (1+ (calendar-absolute-from-gregorian gdate)))))
- (set-buffer-modified-p diary-modified))
- (goto-char (point-min))))
-
-(defun mark-hebrew-diary-entries ()
- "Mark days in the calendar window that have Hebrew date diary entries.
-Each entry in diary-file (or included files) visible in the calendar window
-is marked. Hebrew date entries are prefaced by a hebrew-diary-entry-symbol
-\(normally an `H'). The same diary-date-forms govern the style of the Hebrew
-calendar entries, except that the Hebrew month names must be spelled in full.
-The Hebrew months are numbered from 1 to 13 with Nisan being 1, 12 being
-Adar I and 13 being Adar II; you must use `Adar I' if you want Adar of a
-common Hebrew year. Hebrew date diary entries that begin with a
-diary-nonmarking symbol will not be marked in the calendar. This function
-is provided for use as part of the nongregorian-diary-marking-hook."
- (let ((d diary-date-forms))
- (while d
- (let*
- ((date-form (if (equal (car (car d)) 'backup)
- (cdr (car d))
- (car d)));; ignore 'backup directive
- (dayname (diary-name-pattern calendar-day-name-array))
- (monthname
- (concat
- (diary-name-pattern calendar-hebrew-month-name-array-leap-year t)
- "\\|\\*"))
- (month "[0-9]+\\|\\*")
- (day "[0-9]+\\|\\*")
- (year "[0-9]+\\|\\*")
- (l (length date-form))
- (d-name-pos (- l (length (memq 'dayname date-form))))
- (d-name-pos (if (/= l d-name-pos) (+ 2 d-name-pos)))
- (m-name-pos (- l (length (memq 'monthname date-form))))
- (m-name-pos (if (/= l m-name-pos) (+ 2 m-name-pos)))
- (d-pos (- l (length (memq 'day date-form))))
- (d-pos (if (/= l d-pos) (+ 2 d-pos)))
- (m-pos (- l (length (memq 'month date-form))))
- (m-pos (if (/= l m-pos) (+ 2 m-pos)))
- (y-pos (- l (length (memq 'year date-form))))
- (y-pos (if (/= l y-pos) (+ 2 y-pos)))
- (regexp
- (concat
- "\\(\\`\\|\^M\\|\n\\)"
- (regexp-quote hebrew-diary-entry-symbol)
- "\\("
- (mapconcat 'eval date-form "\\)\\(")
- "\\)"))
- (case-fold-search t))
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (let* ((dd-name
- (if d-name-pos
- (buffer-substring
- (match-beginning d-name-pos)
- (match-end d-name-pos))))
- (mm-name
- (if m-name-pos
- (buffer-substring
- (match-beginning m-name-pos)
- (match-end m-name-pos))))
- (mm (string-to-int
- (if m-pos
- (buffer-substring
- (match-beginning m-pos)
- (match-end m-pos))
- "")))
- (dd (string-to-int
- (if d-pos
- (buffer-substring
- (match-beginning d-pos)
- (match-end d-pos))
- "")))
- (y-str (if y-pos
- (buffer-substring
- (match-beginning y-pos)
- (match-end y-pos))))
- (yy (if (not y-str)
- 0
- (if (and (= (length y-str) 2)
- abbreviated-calendar-year)
- (let* ((current-y
- (extract-calendar-year
- (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-current-date)))))
- (y (+ (string-to-int y-str)
- (* 100 (/ current-y 100)))))
- (if (> (- y current-y) 50)
- (- y 100)
- (if (> (- current-y y) 50)
- (+ y 100)
- y)))
- (string-to-int y-str)))))
- (if dd-name
- (mark-calendar-days-named
- (cdr (assoc (capitalize (substring dd-name 0 3))
- (calendar-make-alist
- calendar-day-name-array
- 0
- '(lambda (x) (substring x 0 3))))))
- (if mm-name
- (if (string-equal mm-name "*")
- (setq mm 0)
- (setq
- mm
- (cdr
- (assoc
- (capitalize mm-name)
- (calendar-make-alist
- calendar-hebrew-month-name-array-leap-year))))))
- (mark-hebrew-calendar-date-pattern mm dd yy)))))
- (setq d (cdr d)))))
-
-(defun mark-hebrew-calendar-date-pattern (month day year)
- "Mark dates in calendar window that conform to Hebrew date MONTH/DAY/YEAR.
-A value of 0 in any position is a wildcard."
- (save-excursion
- (set-buffer calendar-buffer)
- (if (and (/= 0 month) (/= 0 day))
- (if (/= 0 year)
- ;; Fully specified Hebrew date.
- (let ((date (calendar-gregorian-from-absolute
- (calendar-absolute-from-hebrew
- (list month day year)))))
- (if (calendar-date-is-visible-p date)
- (mark-visible-calendar-date date)))
- ;; Month and day in any year--this taken from the holiday stuff.
- (if (memq displayed-month;; This test is only to speed things up a
- (list ;; bit; it works fine without the test too.
- (if (< 11 month) (- month 11) (+ month 1))
- (if (< 10 month) (- month 10) (+ month 2))
- (if (< 9 month) (- month 9) (+ month 3))
- (if (< 8 month) (- month 8) (+ month 4))
- (if (< 7 month) (- month 7) (+ month 5))))
- (let ((m1 displayed-month)
- (y1 displayed-year)
- (m2 displayed-month)
- (y2 displayed-year)
- (year))
- (increment-calendar-month m1 y1 -1)
- (increment-calendar-month m2 y2 1)
- (let* ((start-date (calendar-absolute-from-gregorian
- (list m1 1 y1)))
- (end-date (calendar-absolute-from-gregorian
- (list m2
- (calendar-last-day-of-month m2 y2)
- y2)))
- (hebrew-start
- (calendar-hebrew-from-absolute start-date))
- (hebrew-end (calendar-hebrew-from-absolute end-date))
- (hebrew-y1 (extract-calendar-year hebrew-start))
- (hebrew-y2 (extract-calendar-year hebrew-end)))
- (setq year (if (< 6 month) hebrew-y2 hebrew-y1))
- (let ((date (calendar-gregorian-from-absolute
- (calendar-absolute-from-hebrew
- (list month day year)))))
- (if (calendar-date-is-visible-p date)
- (mark-visible-calendar-date date)))))))
- ;; Not one of the simple cases--check all visible dates for match.
- ;; Actually, the following code takes care of ALL of the cases, but
- ;; it's much too slow to be used for the simple (common) cases.
- (let ((m displayed-month)
- (y displayed-year)
- (first-date)
- (last-date))
- (increment-calendar-month m y -1)
- (setq first-date
- (calendar-absolute-from-gregorian
- (list m 1 y)))
- (increment-calendar-month m y 2)
- (setq last-date
- (calendar-absolute-from-gregorian
- (list m (calendar-last-day-of-month m y) y)))
- (calendar-for-loop date from first-date to last-date do
- (let* ((h-date (calendar-hebrew-from-absolute date))
- (h-month (extract-calendar-month h-date))
- (h-day (extract-calendar-day h-date))
- (h-year (extract-calendar-year h-date)))
- (and (or (zerop month)
- (= month h-month))
- (or (zerop day)
- (= day h-day))
- (or (zerop year)
- (= year h-year))
- (mark-visible-calendar-date
- (calendar-gregorian-from-absolute date)))))))))
-
-(defun insert-hebrew-diary-entry (arg)
- "Insert a diary entry.
-For the Hebrew date corresponding to the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-month-name-array
- calendar-hebrew-month-name-array-leap-year))
- (make-diary-entry
- (concat
- hebrew-diary-entry-symbol
- (calendar-date-string
- (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))
- nil t))
- arg)))
-
-(defun insert-monthly-hebrew-diary-entry (arg)
- "Insert a monthly diary entry.
-For the day of the Hebrew month corresponding to the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style '(day " * ") '("* " day )))
- (calendar-month-name-array
- calendar-hebrew-month-name-array-leap-year))
- (make-diary-entry
- (concat
- hebrew-diary-entry-symbol
- (calendar-date-string
- (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))))
- arg)))
-
-(defun insert-yearly-hebrew-diary-entry (arg)
- "Insert an annual diary entry.
-For the day of the Hebrew year corresponding to the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " " monthname)
- '(monthname " " day)))
- (calendar-month-name-array
- calendar-hebrew-month-name-array-leap-year))
- (make-diary-entry
- (concat
- hebrew-diary-entry-symbol
- (calendar-date-string
- (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))))
- arg)))
-
-;;;###autoload
-(defun list-yahrzeit-dates (death-date start-year end-year)
- "List Yahrzeit dates for *Gregorian* DEATH-DATE from START-YEAR to END-YEAR.
-When called interactively from the calendar window, the date of death is taken
-from the cursor position."
- (interactive
- (let* ((death-date
- (if (equal (current-buffer) (get-buffer calendar-buffer))
- (calendar-cursor-to-date)
- (let* ((today (calendar-current-date))
- (year (calendar-read
- "Year of death (>0): "
- '(lambda (x) (> x 0))
- (int-to-string (extract-calendar-year today))))
- (month-array calendar-month-name-array)
- (completion-ignore-case t)
- (month (cdr (assoc
- (capitalize
- (completing-read
- "Month of death (name): "
- (mapcar 'list (append month-array nil))
- nil t))
- (calendar-make-alist
- month-array 1 'capitalize))))
- (last (calendar-last-day-of-month month year))
- (day (calendar-read
- (format "Day of death (1-%d): " last)
- '(lambda (x) (and (< 0 x) (<= x last))))))
- (list month day year))))
- (death-year (extract-calendar-year death-date))
- (start-year (calendar-read
- (format "Starting year of Yahrzeit table (>%d): "
- death-year)
- '(lambda (x) (> x death-year))
- (int-to-string (1+ death-year))))
- (end-year (calendar-read
- (format "Ending year of Yahrzeit table (>=%d): "
- start-year)
- '(lambda (x) (>= x start-year)))))
- (list death-date start-year end-year)))
- (message "Computing yahrzeits...")
- (let* ((yahrzeit-buffer "*Yahrzeits*")
- (h-date (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian death-date)))
- (h-month (extract-calendar-month h-date))
- (h-day (extract-calendar-day h-date))
- (h-year (extract-calendar-year h-date)))
- (set-buffer (get-buffer-create yahrzeit-buffer))
- (setq buffer-read-only nil)
- (calendar-set-mode-line
- (format "Yahrzeit dates for %s = %s"
- (calendar-date-string death-date)
- (let ((calendar-month-name-array
- (if (hebrew-calendar-leap-year-p h-year)
- calendar-hebrew-month-name-array-leap-year
- calendar-hebrew-month-name-array-common-year)))
- (calendar-date-string h-date nil t))))
- (erase-buffer)
- (goto-char (point-min))
- (calendar-for-loop i from start-year to end-year do
- (insert
- (calendar-date-string
- (calendar-gregorian-from-absolute
- (hebrew-calendar-yahrzeit
- h-date
- (extract-calendar-year
- (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian (list 1 1 i))))))) "\n"))
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- (setq buffer-read-only t)
- (display-buffer yahrzeit-buffer)
- (message "Computing yahrzeits...done")))
-
-(defun diary-hebrew-date ()
- "Hebrew calendar equivalent of date diary entry."
- (format "Hebrew date (until sunset): %s" (calendar-hebrew-date-string date)))
-
-(defun diary-omer ()
- "Omer count diary entry.
-Entry applies if date is within 50 days after Passover."
- (let* ((passover
- (calendar-absolute-from-hebrew
- (list 1 15 (+ (extract-calendar-year date) 3760))))
- (omer (- (calendar-absolute-from-gregorian date) passover))
- (week (/ omer 7))
- (day (% omer 7)))
- (if (and (> omer 0) (< omer 50))
- (format "Day %d%s of the omer (until sunset)"
- omer
- (if (zerop week)
- ""
- (format ", that is, %d week%s%s"
- week
- (if (= week 1) "" "s")
- (if (zerop day)
- ""
- (format " and %d day%s"
- day (if (= day 1) "" "s")))))))))
-
-(defun diary-yahrzeit (death-month death-day death-year)
- "Yahrzeit diary entry--entry applies if date is yahrzeit or the day before.
-Parameters are DEATH-MONTH, DEATH-DAY, DEATH-YEAR; the diary entry is assumed
-to be the name of the person. Date of death is on the *civil* calendar;
-although the date of death is specified by the civil calendar, the proper
-Hebrew calendar yahrzeit is determined. If `european-calendar-style' is t, the
-order of the parameters is changed to DEATH-DAY, DEATH-MONTH, DEATH-YEAR."
- (let* ((h-date (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (if european-calendar-style
- (list death-day death-month death-year)
- (list death-month death-day death-year)))))
- (h-month (extract-calendar-month h-date))
- (h-day (extract-calendar-day h-date))
- (h-year (extract-calendar-year h-date))
- (d (calendar-absolute-from-gregorian date))
- (yr (extract-calendar-year (calendar-hebrew-from-absolute d)))
- (diff (- yr h-year))
- (y (hebrew-calendar-yahrzeit h-date yr)))
- (if (and (> diff 0) (or (= y d) (= y (1+ d))))
- (format "Yahrzeit of %s%s: %d%s anniversary"
- entry
- (if (= y d) "" " (evening)")
- diff
- (cond ((= (% diff 10) 1) "st")
- ((= (% diff 10) 2) "nd")
- ((= (% diff 10) 3) "rd")
- (t "th"))))))
-
-(defun diary-rosh-hodesh ()
- "Rosh Hodesh diary entry.
-Entry applies if date is Rosh Hodesh, the day before, or the Saturday before."
- (let* ((d (calendar-absolute-from-gregorian date))
- (h-date (calendar-hebrew-from-absolute d))
- (h-month (extract-calendar-month h-date))
- (h-day (extract-calendar-day h-date))
- (h-year (extract-calendar-year h-date))
- (leap-year (hebrew-calendar-leap-year-p h-year))
- (last-day (hebrew-calendar-last-day-of-month h-month h-year))
- (h-month-names
- (if leap-year
- calendar-hebrew-month-name-array-leap-year
- calendar-hebrew-month-name-array-common-year))
- (this-month (aref h-month-names (1- h-month)))
- (h-yesterday (extract-calendar-day
- (calendar-hebrew-from-absolute (1- d)))))
- (if (or (= h-day 30) (and (= h-day 1) (/= h-month 7)))
- (format
- "Rosh Hodesh %s"
- (if (= h-day 30)
- (format
- "%s (first day)"
- ;; next month must be in the same year since this
- ;; month can't be the last month of the year since
- ;; it has 30 days
- (aref h-month-names h-month))
- (if (= h-yesterday 30)
- (format "%s (second day)" this-month)
- this-month)))
- (if (= (% d 7) 6);; Saturday--check for Shabbat Mevarhim
- (cond ((and (> h-day 22) (/= h-month 6) (= 29 last-day))
- (format "Mevarhim Rosh Hodesh %s (%s)"
- (aref h-month-names
- (if (= h-month
- (hebrew-calendar-last-month-of-year
- h-year))
- 0 h-month))
- (aref calendar-day-name-array (- 29 h-day))))
- ((and (< h-day 30) (> h-day 22) (= 30 last-day))
- (format "Mevarhim Rosh Hodesh %s (%s-%s)"
- (aref h-month-names h-month)
- (if (= h-day 29)
- "tomorrow"
- (aref calendar-day-name-array (- 29 h-day)))
- (aref calendar-day-name-array
- (% (- 30 h-day) 7)))))
- (if (and (= h-day 29) (/= h-month 6))
- (format "Erev Rosh Hodesh %s"
- (aref h-month-names
- (if (= h-month
- (hebrew-calendar-last-month-of-year
- h-year))
- 0 h-month))))))))
-
-(defun diary-parasha ()
- "Parasha diary entry--entry applies if date is a Saturday."
- (let ((d (calendar-absolute-from-gregorian date)))
- (if (= (% d 7) 6);; Saturday
- (let*
- ((h-year (extract-calendar-year
- (calendar-hebrew-from-absolute d)))
- (rosh-hashanah
- (calendar-absolute-from-hebrew (list 7 1 h-year)))
- (passover
- (calendar-absolute-from-hebrew (list 1 15 h-year)))
- (rosh-hashanah-day
- (aref calendar-day-name-array (% rosh-hashanah 7)))
- (passover-day
- (aref calendar-day-name-array (% passover 7)))
- (long-h (hebrew-calendar-long-heshvan-p h-year))
- (short-k (hebrew-calendar-short-kislev-p h-year))
- (type (cond ((and long-h (not short-k)) "complete")
- ((and (not long-h) short-k) "incomplete")
- (t "regular")))
- (year-format
- (symbol-value
- (intern (format "hebrew-calendar-year-%s-%s-%s";; keviah
- rosh-hashanah-day type passover-day))))
- (first-saturday;; of Hebrew year
- (calendar-dayname-on-or-before 6 (+ 6 rosh-hashanah)))
- (saturday;; which Saturday of the Hebrew year
- (/ (- d first-saturday) 7))
- (parasha (aref year-format saturday)))
- (if parasha
- (format
- "Parashat %s"
- (if (listp parasha);; Israel differs from diaspora
- (if (car parasha)
- (format "%s (diaspora), %s (Israel)"
- (hebrew-calendar-parasha-name (car parasha))
- (hebrew-calendar-parasha-name (cdr parasha)))
- (format "%s (Israel)"
- (hebrew-calendar-parasha-name (cdr parasha))))
- (hebrew-calendar-parasha-name parasha))))))))
-
-(defvar hebrew-calendar-parashiot-names
-["Bereshith" "Noah" "Lech L'cha" "Vayera" "Hayei Sarah" "Toledoth"
- "Vayetze" "Vayishlah" "Vayeshev" "Mikketz" "Vayiggash" "Vayhi"
- "Shemoth" "Vaera" "Bo" "Beshallah" "Yithro" "Mishpatim"
- "Terumah" "Tetzavveh" "Ki Tissa" "Vayakhel" "Pekudei" "Vayikra"
- "Tzav" "Shemini" "Tazria" "Metzora" "Aharei Moth" "Kedoshim"
- "Emor" "Behar" "Behukkotai" "Bemidbar" "Naso" "Behaalot'cha"
- "Shelah L'cha" "Korah" "Hukkath" "Balak" "Pinhas" "Mattoth"
- "Masei" "Devarim" "Vaethanan" "Ekev" "Reeh" "Shofetim"
- "Ki Tetze" "Ki Tavo" "Nitzavim" "Vayelech" "Haazinu"]
- "The names of the parashiot in the Torah.")
-
-;; The seven ordinary year types (keviot)
-
-(defconst hebrew-calendar-year-Saturday-incomplete-Sunday
- [nil 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [21 22]
- 23 24 nil 25 [26 27] [28 29] 30 [31 32] 33 34 35 36 37 38 39 40 [41 42]
- 43 44 45 46 47 48 49 50]
- "The structure of the parashiot.
-Hebrew year starts on Saturday, is `incomplete' (Heshvan and Kislev each have
-29 days), and has Passover start on Sunday.")
-
-(defconst hebrew-calendar-year-Saturday-complete-Tuesday
- [nil 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [21 22]
- 23 24 nil 25 [26 27] [28 29] 30 [31 32] 33 34 35 36 37 38 39 40 [41 42]
- 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Saturday, is `complete' (Heshvan and Kislev each
-have 30 days), and has Passover start on Tuesday.")
-
-(defconst hebrew-calendar-year-Monday-incomplete-Tuesday
- [51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [21 22]
- 23 24 nil 25 [26 27] [28 29] 30 [31 32] 33 34 35 36 37 38 39 40 [41 42]
- 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Monday, is `incomplete' (Heshvan and Kislev each
-have 29 days), and has Passover start on Tuesday.")
-
-(defconst hebrew-calendar-year-Monday-complete-Thursday
- [51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [21 22]
- 23 24 nil 25 [26 27] [28 29] 30 [31 32] 33 (nil . 34) (34 . 35) (35 . 36)
- (36 . 37) (37 . 38) ([38 39] . 39) 40 [41 42] 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Monday, is `complete' (Heshvan and Kislev each have
-30 days), and has Passover start on Thursday.")
-
-(defconst hebrew-calendar-year-Tuesday-regular-Thursday
- [51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [21 22]
- 23 24 nil 25 [26 27] [28 29] 30 [31 32] 33 (nil . 34) (34 . 35) (35 . 36)
- (36 . 37) (37 . 38) ([38 39] . 39) 40 [41 42] 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Tuesday, is `regular' (Heshvan has 29 days and
-Kislev has 30 days), and has Passover start on Thursday.")
-
-(defconst hebrew-calendar-year-Thursday-regular-Saturday
- [52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [21 22] 23
- 24 nil (nil . 25) (25 . [26 27]) ([26 27] . [28 29]) ([28 29] . 30)
- (30 . 31) ([31 32] . 32) 33 34 35 36 37 38 39 40 [41 42] 43 44 45 46 47 48
- 49 50]
- "The structure of the parashiot.
-Hebrew year that starts on Thursday, is `regular' (Heshvan has 29 days and
-Kislev has 30 days), and has Passover start on Saturday.")
-
-(defconst hebrew-calendar-year-Thursday-complete-Sunday
- [52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 nil 25 [26 27] [28 29] 30 [31 32] 33 34 35 36 37 38 39 40 [41 42]
- 43 44 45 46 47 48 49 50]
- "The structure of the parashiot.
-Hebrew year that starts on Thursday, is `complete' (Heshvan and Kislev each
-have 30 days), and has Passover start on Sunday.")
-
-;; The seven leap year types (keviot)
-
-(defconst hebrew-calendar-year-Saturday-incomplete-Tuesday
- [nil 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 nil 28 29 30 31 32 33 34 35 36 37 38 39 40 [41 42]
- 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Saturday, is `incomplete' (Heshvan and Kislev each
-have 29 days), and has Passover start on Tuesday.")
-
-(defconst hebrew-calendar-year-Saturday-complete-Thursday
- [nil 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 nil 28 29 30 31 32 33 (nil . 34) (34 . 35) (35 . 36)
- (36 . 37) (37 . 38) ([38 39] . 39) 40 [41 42] 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Saturday, is `complete' (Heshvan and Kislev each
-have 30 days), and has Passover start on Thursday.")
-
-(defconst hebrew-calendar-year-Monday-incomplete-Thursday
- [51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 nil 28 29 30 31 32 33 (nil . 34) (34 . 35) (35 . 36)
- (36 . 37) (37 . 38) ([38 39] . 39) 40 [41 42] 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Monday, is `incomplete' (Heshvan and Kislev each
-have 29 days), and has Passover start on Thursday.")
-
-(defconst hebrew-calendar-year-Monday-complete-Saturday
- [51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 nil (nil . 28) (28 . 29) (29 . 30) (30 . 31) (31 . 32)
- (32 . 33) (33 . 34) (34 . 35) (35 . 36) (36 . 37) (37 . 38) (38 . 39)
- (39 . 40) (40 . 41) ([41 42] . 42) 43 44 45 46 47 48 49 50]
- "The structure of the parashiot.
-Hebrew year that starts on Monday, is `complete' (Heshvan and Kislev each have
-30 days), and has Passover start on Saturday.")
-
-(defconst hebrew-calendar-year-Tuesday-regular-Saturday
- [51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 nil (nil . 28) (28 . 29) (29 . 30) (30 . 31) (31 . 32)
- (32 . 33) (33 . 34) (34 . 35) (35 . 36) (36 . 37) (37 . 38) (38 . 39)
- (39 . 40) (40 . 41) ([41 42] . 42) 43 44 45 46 47 48 49 50]
- "The structure of the parashiot.
-Hebrew year that starts on Tuesday, is `regular' (Heshvan has 29 days and
-Kislev has 30 days), and has Passover start on Saturday.")
-
-(defconst hebrew-calendar-year-Thursday-incomplete-Sunday
- [52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 28 nil 29 30 31 32 33 34 35 36 37 38 39 40 41 42
- 43 44 45 46 47 48 49 50]
- "The structure of the parashiot.
-Hebrew year that starts on Thursday, is `incomplete' (Heshvan and Kislev both
-have 29 days), and has Passover start on Sunday.")
-
-(defconst hebrew-calendar-year-Thursday-complete-Tuesday
- [52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- 23 24 25 26 27 28 nil 29 30 31 32 33 34 35 36 37 38 39 40 41 42
- 43 44 45 46 47 48 49 [50 51]]
- "The structure of the parashiot.
-Hebrew year that starts on Thursday, is `complete' (Heshvan and Kislev both
-have 30 days), and has Passover start on Tuesday.")
-
-(defun hebrew-calendar-parasha-name (p)
- "Name(s) corresponding to parasha P."
- (if (arrayp p);; combined parasha
- (format "%s/%s"
- (aref hebrew-calendar-parashiot-names (aref p 0))
- (aref hebrew-calendar-parashiot-names (aref p 1)))
- (aref hebrew-calendar-parashiot-names p)))
-
-(provide 'cal-hebrew)
-
-;;; cal-hebrew.el ends here
diff --git a/lisp/calendar/cal-islam.el b/lisp/calendar/cal-islam.el
deleted file mode 100644
index a8e038e52eb..00000000000
--- a/lisp/calendar/cal-islam.el
+++ /dev/null
@@ -1,492 +0,0 @@
-;;; cal-islam.el --- calendar functions for the Islamic calendar.
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: Islamic calendar, calendar, diary
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the features of calendar.el and
-;; diary.el that deal with the Islamic calendar.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(require 'cal-julian)
-
-(defvar calendar-islamic-month-name-array
- ["Muharram" "Safar" "Rabi I" "Rabi II" "Jumada I" "Jumada II"
- "Rajab" "Sha'ban" "Ramadan" "Shawwal" "Dhu al-Qada" "Dhu al-Hijjah"])
-
-(defvar calendar-islamic-epoch (calendar-absolute-from-julian '(7 16 622))
- "Absolute date of start of Islamic calendar = August 29, 284 A.D. (Julian).")
-
-(defun islamic-calendar-leap-year-p (year)
- "Returns t if YEAR is a leap year on the Islamic calendar."
- (memq (% year 30)
- (list 2 5 7 10 13 16 18 21 24 26 29)))
-
-(defun islamic-calendar-last-day-of-month (month year)
- "The last day in MONTH during YEAR on the Islamic calendar."
- (cond
- ((memq month (list 1 3 5 7 9 11)) 30)
- ((memq month (list 2 4 6 8 10)) 29)
- (t (if (islamic-calendar-leap-year-p year) 30 29))))
-
-(defun islamic-calendar-day-number (date)
- "Return the day number within the year of the Islamic date DATE."
- (let* ((month (extract-calendar-month date))
- (day (extract-calendar-day date)))
- (+ (* 30 (/ month 2))
- (* 29 (/ (1- month) 2))
- day)))
-
-(defun calendar-absolute-from-islamic (date)
- "Absolute date of Islamic DATE.
-The absolute date is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
- (let* ((month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date))
- (y (% year 30))
- (leap-years-in-cycle
- (cond
- ((< y 3) 0) ((< y 6) 1) ((< y 8) 2) ((< y 11) 3) ((< y 14) 4)
- ((< y 17) 5) ((< y 19) 6) ((< y 22) 7) ((< y 25) 8) ((< y 27) 9)
- (t 10))))
- (+ (islamic-calendar-day-number date);; days so far this year
- (* (1- year) 354) ;; days in all non-leap years
- (* 11 (/ year 30)) ;; leap days in complete cycles
- leap-years-in-cycle ;; leap days this cycle
- (1- calendar-islamic-epoch)))) ;; days before start of calendar
-
-(defun calendar-islamic-from-absolute (date)
- "Compute the Islamic date (month day year) corresponding to absolute DATE.
-The absolute date is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
- (if (< date calendar-islamic-epoch)
- (list 0 0 0);; pre-Islamic date
- (let* ((approx (/ (- date calendar-islamic-epoch)
- 355));; Approximation from below.
- (year ;; Search forward from the approximation.
- (+ approx
- (calendar-sum y approx
- (>= date (calendar-absolute-from-islamic
- (list 1 1 (1+ y))))
- 1)))
- (month ;; Search forward from Muharram.
- (1+ (calendar-sum m 1
- (> date
- (calendar-absolute-from-islamic
- (list m
- (islamic-calendar-last-day-of-month
- m year)
- year)))
- 1)))
- (day ;; Calculate the day by subtraction.
- (- date
- (1- (calendar-absolute-from-islamic (list month 1 year))))))
- (list month day year))))
-
-(defun calendar-islamic-date-string (&optional date)
- "String of Islamic date before sunset of Gregorian DATE.
-Returns the empty string if DATE is pre-Islamic.
-Defaults to today's date if DATE is not given.
-Driven by the variable `calendar-date-display-form'."
- (let ((calendar-month-name-array calendar-islamic-month-name-array)
- (islamic-date (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian
- (or date (calendar-current-date))))))
- (if (< (extract-calendar-year islamic-date) 1)
- ""
- (calendar-date-string islamic-date nil t))))
-
-(defun calendar-print-islamic-date ()
- "Show the Islamic calendar equivalent of the date under the cursor."
- (interactive)
- (let ((i (calendar-islamic-date-string (calendar-cursor-to-date t))))
- (if (string-equal i "")
- (message "Date is pre-Islamic")
- (message "Islamic date (until sunset): %s" i))))
-
-(defun calendar-goto-islamic-date (date &optional noecho)
- "Move cursor to Islamic DATE; echo Islamic date unless NOECHO is t."
- (interactive
- (let* ((today (calendar-current-date))
- (year (calendar-read
- "Islamic calendar year (>0): "
- '(lambda (x) (> x 0))
- (int-to-string
- (extract-calendar-year
- (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian today))))))
- (month-array calendar-islamic-month-name-array)
- (completion-ignore-case t)
- (month (cdr (assoc
- (capitalize
- (completing-read
- "Islamic calendar month name: "
- (mapcar 'list (append month-array nil))
- nil t))
- (calendar-make-alist month-array 1 'capitalize))))
- (last (islamic-calendar-last-day-of-month month year))
- (day (calendar-read
- (format "Islamic calendar day (1-%d): " last)
- '(lambda (x) (and (< 0 x) (<= x last))))))
- (list (list month day year))))
- (calendar-goto-date (calendar-gregorian-from-absolute
- (calendar-absolute-from-islamic date)))
- (or noecho (calendar-print-islamic-date)))
-
-(defun diary-islamic-date ()
- "Islamic calendar equivalent of date diary entry."
- (let ((i (calendar-islamic-date-string (calendar-cursor-to-date t))))
- (if (string-equal i "")
- "Date is pre-Islamic"
- (format "Islamic date (until sunset): %s" i))))
-
-(defun holiday-islamic (month day string)
- "Holiday on MONTH, DAY (Islamic) called STRING.
-If MONTH, DAY (Islamic) is visible, the value returned is corresponding
-Gregorian date in the form of the list (((month day year) STRING)). Returns
-nil if it is not visible in the current calendar window."
- (let* ((islamic-date (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian
- (list displayed-month 15 displayed-year))))
- (m (extract-calendar-month islamic-date))
- (y (extract-calendar-year islamic-date))
- (date))
- (if (< m 1)
- nil;; Islamic calendar doesn't apply.
- (increment-calendar-month m y (- 10 month))
- (if (> m 7);; Islamic date might be visible
- (let ((date (calendar-gregorian-from-absolute
- (calendar-absolute-from-islamic (list month day y)))))
- (if (calendar-date-is-visible-p date)
- (list (list date string))))))))
-
-(defun list-islamic-diary-entries ()
- "Add any Islamic date entries from the diary file to `diary-entries-list'.
-Islamic date diary entries must be prefaced by an `islamic-diary-entry-symbol'
-\(normally an `I'). The same diary date forms govern the style of the Islamic
-calendar entries, except that the Islamic month names must be spelled in full.
-The Islamic months are numbered from 1 to 12 with Muharram being 1 and 12 being
-Dhu al-Hijjah. If an Islamic date diary entry begins with a
-`diary-nonmarking-symbol', the entry will appear in the diary listing, but will
-not be marked in the calendar. This function is provided for use with the
-`nongregorian-diary-listing-hook'."
- (if (< 0 number)
- (let ((buffer-read-only nil)
- (diary-modified (buffer-modified-p))
- (gdate original-date)
- (mark (regexp-quote diary-nonmarking-symbol)))
- (calendar-for-loop i from 1 to number do
- (let* ((d diary-date-forms)
- (idate (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian gdate)))
- (month (extract-calendar-month idate))
- (day (extract-calendar-day idate))
- (year (extract-calendar-year idate)))
- (while d
- (let*
- ((date-form (if (equal (car (car d)) 'backup)
- (cdr (car d))
- (car d)))
- (backup (equal (car (car d)) 'backup))
- (dayname
- (concat
- (calendar-day-name gdate) "\\|"
- (substring (calendar-day-name gdate) 0 3) ".?"))
- (calendar-month-name-array
- calendar-islamic-month-name-array)
- (monthname
- (concat
- "\\*\\|"
- (calendar-month-name month)))
- (month (concat "\\*\\|0*" (int-to-string month)))
- (day (concat "\\*\\|0*" (int-to-string day)))
- (year
- (concat
- "\\*\\|0*" (int-to-string year)
- (if abbreviated-calendar-year
- (concat "\\|" (int-to-string (% year 100)))
- "")))
- (regexp
- (concat
- "\\(\\`\\|\^M\\|\n\\)" mark "?"
- (regexp-quote islamic-diary-entry-symbol)
- "\\("
- (mapconcat 'eval date-form "\\)\\(")
- "\\)"))
- (case-fold-search t))
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (if backup (re-search-backward "\\<" nil t))
- (if (and (or (char-equal (preceding-char) ?\^M)
- (char-equal (preceding-char) ?\n))
- (not (looking-at " \\|\^I")))
- ;; Diary entry that consists only of date.
- (backward-char 1)
- ;; Found a nonempty diary entry--make it visible and
- ;; add it to the list.
- (let ((entry-start (point))
- (date-start))
- (re-search-backward "\^M\\|\n\\|\\`")
- (setq date-start (point))
- (re-search-forward "\^M\\|\n" nil t 2)
- (while (looking-at " \\|\^I")
- (re-search-forward "\^M\\|\n" nil t))
- (backward-char 1)
- (subst-char-in-region date-start (point) ?\^M ?\n t)
- (add-to-diary-list
- gdate (buffer-substring entry-start (point)))))))
- (setq d (cdr d))))
- (setq gdate
- (calendar-gregorian-from-absolute
- (1+ (calendar-absolute-from-gregorian gdate)))))
- (set-buffer-modified-p diary-modified))
- (goto-char (point-min))))
-
-(defun mark-islamic-diary-entries ()
- "Mark days in the calendar window that have Islamic date diary entries.
-Each entry in diary-file (or included files) visible in the calendar window
-is marked. Islamic date entries are prefaced by a islamic-diary-entry-symbol
-\(normally an `I'). The same diary-date-forms govern the style of the Islamic
-calendar entries, except that the Islamic month names must be spelled in full.
-The Islamic months are numbered from 1 to 12 with Muharram being 1 and 12 being
-Dhu al-Hijjah. Islamic date diary entries that begin with a
-diary-nonmarking-symbol will not be marked in the calendar. This function is
-provided for use as part of the nongregorian-diary-marking-hook."
- (let ((d diary-date-forms))
- (while d
- (let*
- ((date-form (if (equal (car (car d)) 'backup)
- (cdr (car d))
- (car d)));; ignore 'backup directive
- (dayname (diary-name-pattern calendar-day-name-array))
- (monthname
- (concat
- (diary-name-pattern calendar-islamic-month-name-array t)
- "\\|\\*"))
- (month "[0-9]+\\|\\*")
- (day "[0-9]+\\|\\*")
- (year "[0-9]+\\|\\*")
- (l (length date-form))
- (d-name-pos (- l (length (memq 'dayname date-form))))
- (d-name-pos (if (/= l d-name-pos) (+ 2 d-name-pos)))
- (m-name-pos (- l (length (memq 'monthname date-form))))
- (m-name-pos (if (/= l m-name-pos) (+ 2 m-name-pos)))
- (d-pos (- l (length (memq 'day date-form))))
- (d-pos (if (/= l d-pos) (+ 2 d-pos)))
- (m-pos (- l (length (memq 'month date-form))))
- (m-pos (if (/= l m-pos) (+ 2 m-pos)))
- (y-pos (- l (length (memq 'year date-form))))
- (y-pos (if (/= l y-pos) (+ 2 y-pos)))
- (regexp
- (concat
- "\\(\\`\\|\^M\\|\n\\)"
- (regexp-quote islamic-diary-entry-symbol)
- "\\("
- (mapconcat 'eval date-form "\\)\\(")
- "\\)"))
- (case-fold-search t))
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (let* ((dd-name
- (if d-name-pos
- (buffer-substring
- (match-beginning d-name-pos)
- (match-end d-name-pos))))
- (mm-name
- (if m-name-pos
- (buffer-substring
- (match-beginning m-name-pos)
- (match-end m-name-pos))))
- (mm (string-to-int
- (if m-pos
- (buffer-substring
- (match-beginning m-pos)
- (match-end m-pos))
- "")))
- (dd (string-to-int
- (if d-pos
- (buffer-substring
- (match-beginning d-pos)
- (match-end d-pos))
- "")))
- (y-str (if y-pos
- (buffer-substring
- (match-beginning y-pos)
- (match-end y-pos))))
- (yy (if (not y-str)
- 0
- (if (and (= (length y-str) 2)
- abbreviated-calendar-year)
- (let* ((current-y
- (extract-calendar-year
- (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-current-date)))))
- (y (+ (string-to-int y-str)
- (* 100 (/ current-y 100)))))
- (if (> (- y current-y) 50)
- (- y 100)
- (if (> (- current-y y) 50)
- (+ y 100)
- y)))
- (string-to-int y-str)))))
- (if dd-name
- (mark-calendar-days-named
- (cdr (assoc (capitalize (substring dd-name 0 3))
- (calendar-make-alist
- calendar-day-name-array
- 0
- '(lambda (x) (substring x 0 3))))))
- (if mm-name
- (if (string-equal mm-name "*")
- (setq mm 0)
- (setq mm
- (cdr (assoc
- (capitalize mm-name)
- (calendar-make-alist
- calendar-islamic-month-name-array))))))
- (mark-islamic-calendar-date-pattern mm dd yy)))))
- (setq d (cdr d)))))
-
-(defun mark-islamic-calendar-date-pattern (month day year)
- "Mark dates in calendar window that conform to Islamic date MONTH/DAY/YEAR.
-A value of 0 in any position is a wildcard."
- (save-excursion
- (set-buffer calendar-buffer)
- (if (and (/= 0 month) (/= 0 day))
- (if (/= 0 year)
- ;; Fully specified Islamic date.
- (let ((date (calendar-gregorian-from-absolute
- (calendar-absolute-from-islamic
- (list month day year)))))
- (if (calendar-date-is-visible-p date)
- (mark-visible-calendar-date date)))
- ;; Month and day in any year--this taken from the holiday stuff.
- (let* ((islamic-date (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian
- (list displayed-month 15 displayed-year))))
- (m (extract-calendar-month islamic-date))
- (y (extract-calendar-year islamic-date))
- (date))
- (if (< m 1)
- nil;; Islamic calendar doesn't apply.
- (increment-calendar-month m y (- 10 month))
- (if (> m 7);; Islamic date might be visible
- (let ((date (calendar-gregorian-from-absolute
- (calendar-absolute-from-islamic
- (list month day y)))))
- (if (calendar-date-is-visible-p date)
- (mark-visible-calendar-date date)))))))
- ;; Not one of the simple cases--check all visible dates for match.
- ;; Actually, the following code takes care of ALL of the cases, but
- ;; it's much too slow to be used for the simple (common) cases.
- (let ((m displayed-month)
- (y displayed-year)
- (first-date)
- (last-date))
- (increment-calendar-month m y -1)
- (setq first-date
- (calendar-absolute-from-gregorian
- (list m 1 y)))
- (increment-calendar-month m y 2)
- (setq last-date
- (calendar-absolute-from-gregorian
- (list m (calendar-last-day-of-month m y) y)))
- (calendar-for-loop date from first-date to last-date do
- (let* ((i-date (calendar-islamic-from-absolute date))
- (i-month (extract-calendar-month i-date))
- (i-day (extract-calendar-day i-date))
- (i-year (extract-calendar-year i-date)))
- (and (or (zerop month)
- (= month i-month))
- (or (zerop day)
- (= day i-day))
- (or (zerop year)
- (= year i-year))
- (mark-visible-calendar-date
- (calendar-gregorian-from-absolute date)))))))))
-
-(defun insert-islamic-diary-entry (arg)
- "Insert a diary entry.
-For the Islamic date corresponding to the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-month-name-array calendar-islamic-month-name-array))
- (make-diary-entry
- (concat
- islamic-diary-entry-symbol
- (calendar-date-string
- (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))
- nil t))
- arg)))
-
-(defun insert-monthly-islamic-diary-entry (arg)
- "Insert a monthly diary entry.
-For the day of the Islamic month corresponding to the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style '(day " * ") '("* " day )))
- (calendar-month-name-array calendar-islamic-month-name-array))
- (make-diary-entry
- (concat
- islamic-diary-entry-symbol
- (calendar-date-string
- (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))))
- arg)))
-
-(defun insert-yearly-islamic-diary-entry (arg)
- "Insert an annual diary entry.
-For the day of the Islamic year corresponding to the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " " monthname)
- '(monthname " " day)))
- (calendar-month-name-array calendar-islamic-month-name-array))
- (make-diary-entry
- (concat
- islamic-diary-entry-symbol
- (calendar-date-string
- (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))))
- arg)))
-
-(provide 'cal-islam)
-
-;;; cal-islam.el ends here
diff --git a/lisp/calendar/cal-iso.el b/lisp/calendar/cal-iso.el
deleted file mode 100644
index 130f5bc97d8..00000000000
--- a/lisp/calendar/cal-iso.el
+++ /dev/null
@@ -1,126 +0,0 @@
-;;; cal-iso.el --- calendar functions for the ISO calendar.
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: ISO calendar, calendar, diary
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the features of calendar.el and
-;; diary.el that deal with the ISO calendar.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(require 'calendar)
-
-(defun calendar-absolute-from-iso (date)
- "The number of days elapsed between the Gregorian date 12/31/1 BC and DATE.
-The `ISO year' corresponds approximately to the Gregorian year, but
-weeks start on Monday and end on Sunday. The first week of the ISO year is
-the first such week in which at least 4 days are in a year. The ISO
-commercial DATE has the form (week day year) in which week is in the range
-1..52 and day is in the range 0..6 (1 = Monday, 2 = Tuesday, ..., 0 =
-Sunday). The Gregorian date Sunday, December 31, 1 BC is imaginary."
- (let* ((week (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date)))
- (+ (calendar-dayname-on-or-before
- 1 (+ 3 (calendar-absolute-from-gregorian (list 1 1 year))))
- (* 7 (1- week))
- (if (= day 0) 6 (1- day)))))
-
-(defun calendar-iso-from-absolute (date)
- "Compute the `ISO commercial date' corresponding to the absolute DATE.
-The ISO year corresponds approximately to the Gregorian year, but weeks
-start on Monday and end on Sunday. The first week of the ISO year is the
-first such week in which at least 4 days are in a year. The ISO commercial
-date has the form (week day year) in which week is in the range 1..52 and
-day is in the range 0..6 (1 = Monday, 2 = Tuesday, ..., 0 = Sunday). The
-absolute date is the number of days elapsed since the (imaginary) Gregorian
-date Sunday, December 31, 1 BC."
- (let* ((approx (extract-calendar-year
- (calendar-gregorian-from-absolute (- date 3))))
- (year (+ approx
- (calendar-sum y approx
- (>= date (calendar-absolute-from-iso (list 1 1 (1+ y))))
- 1))))
- (list
- (1+ (/ (- date (calendar-absolute-from-iso (list 1 1 year))) 7))
- (% date 7)
- year)))
-
-(defun calendar-iso-date-string (&optional date)
- "String of ISO date of Gregorian DATE.
-Defaults to today's date if DATE is not given."
- (let* ((d (calendar-absolute-from-gregorian
- (or date (calendar-current-date))))
- (day (% d 7))
- (iso-date (calendar-iso-from-absolute d)))
- (format "Day %s of week %d of %d"
- (if (zerop day) 7 day)
- (extract-calendar-month iso-date)
- (extract-calendar-year iso-date))))
-
-(defun calendar-print-iso-date ()
- "Show equivalent ISO date for the date under the cursor."
- (interactive)
- (message "ISO date: %s"
- (calendar-iso-date-string (calendar-cursor-to-date t))))
-
-(defun calendar-goto-iso-date (date &optional noecho)
- "Move cursor to ISO DATE; echo ISO date unless NOECHO is t."
- (interactive
- (let* ((today (calendar-current-date))
- (year (calendar-read
- "ISO calendar year (>0): "
- '(lambda (x) (> x 0))
- (int-to-string (extract-calendar-year today))))
- (no-weeks (extract-calendar-month
- (calendar-iso-from-absolute
- (1-
- (calendar-dayname-on-or-before
- 1 (calendar-absolute-from-gregorian
- (list 1 4 (1+ year))))))))
- (week (calendar-read
- (format "ISO calendar week (1-%d): " no-weeks)
- '(lambda (x) (and (> x 0) (<= x no-weeks)))))
- (day (calendar-read
- "ISO day (1-7): "
- '(lambda (x) (and (<= 1 x) (<= x 7))))))
- (list (list week day year))))
- (calendar-goto-date (calendar-gregorian-from-absolute
- (calendar-absolute-from-iso date)))
- (or noecho (calendar-print-iso-date)))
-
-(defun diary-iso-date ()
- "ISO calendar equivalent of date diary entry."
- (format "ISO date: %s" (calendar-iso-date-string date)))
-
-(provide 'cal-iso)
-
-;;; cal-iso.el ends here
diff --git a/lisp/calendar/cal-julian.el b/lisp/calendar/cal-julian.el
deleted file mode 100644
index 4437789e7fe..00000000000
--- a/lisp/calendar/cal-julian.el
+++ /dev/null
@@ -1,207 +0,0 @@
-;;; cal-julian.el --- calendar functions for the Julian calendar.
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: Julian calendar, Julian day number, calendar, diary
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the features of calendar.el and
-;; diary.el that deal with the Julian calendar.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(require 'calendar)
-
-(defun calendar-julian-from-absolute (date)
- "Compute the Julian (month day year) corresponding to the absolute DATE.
-The absolute date is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
- (let* ((approx (/ (+ date 2) 366));; Approximation from below.
- (year ;; Search forward from the approximation.
- (+ approx
- (calendar-sum y approx
- (>= date (calendar-absolute-from-julian (list 1 1 (1+ y))))
- 1)))
- (month ;; Search forward from January.
- (1+ (calendar-sum m 1
- (> date
- (calendar-absolute-from-julian
- (list m
- (if (and (= m 2) (= (% year 4) 0))
- 29
- (aref [31 28 31 30 31 30 31 31 30 31 30 31]
- (1- m)))
- year)))
- 1)))
- (day ;; Calculate the day by subtraction.
- (- date (1- (calendar-absolute-from-julian (list month 1 year))))))
- (list month day year)))
-
-(defun calendar-absolute-from-julian (date)
- "The number of days elapsed between the Gregorian date 12/31/1 BC and DATE.
-The Gregorian date Sunday, December 31, 1 BC is imaginary."
- (let ((month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date)))
- (+ (calendar-day-number date)
- (if (and (= (% year 100) 0)
- (/= (% year 400) 0)
- (> month 2))
- 1 0);; Correct for Julian but not Gregorian leap year.
- (* 365 (1- year))
- (/ (1- year) 4)
- -2)))
-
-(defun calendar-julian-date-string (&optional date)
- "String of Julian date of Gregorian DATE.
-Defaults to today's date if DATE is not given.
-Driven by the variable `calendar-date-display-form'."
- (calendar-date-string
- (calendar-julian-from-absolute
- (calendar-absolute-from-gregorian
- (or date (calendar-current-date))))
- nil t))
-
-(defun calendar-print-julian-date ()
- "Show the Julian calendar equivalent of the date under the cursor."
- (interactive)
- (message "Julian date: %s"
- (calendar-julian-date-string (calendar-cursor-to-date t))))
-
-(defun calendar-goto-julian-date (date &optional noecho)
- "Move cursor to Julian DATE; echo Julian date unless NOECHO is t."
- (interactive
- (let* ((today (calendar-current-date))
- (year (calendar-read
- "Julian calendar year (>0): "
- '(lambda (x) (> x 0))
- (int-to-string
- (extract-calendar-year
- (calendar-julian-from-absolute
- (calendar-absolute-from-gregorian
- today))))))
- (month-array calendar-month-name-array)
- (completion-ignore-case t)
- (month (cdr (assoc
- (capitalize
- (completing-read
- "Julian calendar month name: "
- (mapcar 'list (append month-array nil))
- nil t))
- (calendar-make-alist month-array 1 'capitalize))))
- (last
- (if (and (zerop (% year 4)) (= month 2))
- 29
- (aref [31 28 31 30 31 30 31 31 30 31 30 31] (1- month))))
- (day (calendar-read
- (format "Julian calendar day (%d-%d): "
- (if (and (= year 1) (= month 1)) 3 1) last)
- '(lambda (x)
- (and (< (if (and (= year 1) (= month 1)) 2 0) x)
- (<= x last))))))
- (list (list month day year))))
- (calendar-goto-date (calendar-gregorian-from-absolute
- (calendar-absolute-from-julian date)))
- (or noecho (calendar-print-julian-date)))
-
-(defun holiday-julian (month day string)
- "Holiday on MONTH, DAY (Julian) called STRING.
-If MONTH, DAY (Julian) is visible, the value returned is corresponding
-Gregorian date in the form of the list (((month day year) STRING)). Returns
-nil if it is not visible in the current calendar window."
- (let ((m1 displayed-month)
- (y1 displayed-year)
- (m2 displayed-month)
- (y2 displayed-year)
- (year))
- (increment-calendar-month m1 y1 -1)
- (increment-calendar-month m2 y2 1)
- (let* ((start-date (calendar-absolute-from-gregorian
- (list m1 1 y1)))
- (end-date (calendar-absolute-from-gregorian
- (list m2 (calendar-last-day-of-month m2 y2) y2)))
- (julian-start (calendar-julian-from-absolute start-date))
- (julian-end (calendar-julian-from-absolute end-date))
- (julian-y1 (extract-calendar-year julian-start))
- (julian-y2 (extract-calendar-year julian-end)))
- (setq year (if (< 10 month) julian-y1 julian-y2))
- (let ((date (calendar-gregorian-from-absolute
- (calendar-absolute-from-julian
- (list month day year)))))
- (if (calendar-date-is-visible-p date)
- (list (list date string)))))))
-
-(defun diary-julian-date ()
- "Julian calendar equivalent of date diary entry."
- (format "Julian date: %s" (calendar-julian-date-string date)))
-
-(defun calendar-absolute-from-astro (d)
- "Absolute date of astronomical (Julian) day number D."
- (- d 1721424.5))
-
-(defun calendar-astro-from-absolute (d)
- "Astronomical (Julian) day number of absolute date D."
- (+ d 1721424.5))
-
-(defun calendar-astro-date-string (&optional date)
- "String of astronomical (Julian) day number after noon UTC of Gregorian DATE.
-Defaults to today's date if DATE is not given."
- (int-to-string
- (ceiling
- (calendar-astro-from-absolute
- (calendar-absolute-from-gregorian
- (or date (calendar-current-date)))))))
-
-(defun calendar-print-astro-day-number ()
- "Show astronomical (Julian) day number after noon UTC on date shown by cursor."
- (interactive)
- (message
- "Astronomical (Julian) day number (at noon UTC): %s.0"
- (calendar-astro-date-string (calendar-cursor-to-date t))))
-
-(defun calendar-goto-astro-day-number (daynumber &optional noecho)
- "Move cursor to astronomical (Julian) DAYNUMBER.
-Echo astronomical (Julian) day number unless NOECHO is t."
- (interactive (list (calendar-read
- "Astronomical (Julian) day number (>1721425): "
- '(lambda (x) (> x 1721425)))))
- (calendar-goto-date
- (calendar-gregorian-from-absolute
- (floor
- (calendar-absolute-from-astro daynumber))))
- (or noecho (calendar-print-astro-day-number)))
-
-(defun diary-astro-day-number ()
- "Astronomical (Julian) day number diary entry."
- (format "Astronomical (Julian) day number %s"
- (calendar-astro-date-string date)))
-
-(provide 'cal-julian)
-
-;;; cal-julian.el ends here
diff --git a/lisp/calendar/cal-mayan.el b/lisp/calendar/cal-mayan.el
deleted file mode 100644
index 6b7b1b70027..00000000000
--- a/lisp/calendar/cal-mayan.el
+++ /dev/null
@@ -1,382 +0,0 @@
-;;; cal-mayan.el --- calendar functions for the Mayan calendars.
-
-;; Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc.
-
-;; Author: Stewart M. Clamen <clamen@cs.cmu.edu>
-;; Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: Mayan calendar, Maya, calendar, diary
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the features of calendar.el and
-;; diary.el that deal with the Mayan calendar. It was written jointly by
-
-;; Stewart M. Clamen School of Computer Science
-;; clamen@cs.cmu.edu Carnegie Mellon University
-;; 5000 Forbes Avenue
-;; Pittsburgh, PA 15213
-
-;; and
-
-;; Edward M. Reingold Department of Computer Science
-;; (217) 333-6733 University of Illinois at Urbana-Champaign
-;; reingold@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;; Comments, improvements, and bug reports should be sent to Reingold.
-
-;; Technical details of the Mayan calendrical calculations can be found in
-;; ``Calendrical Calculations, Part II: Three Historical Calendars''
-;; by E. M. Reingold, N. Dershowitz, and S. M. Clamen,
-;; Software--Practice and Experience, Volume 23, Number 4 (April, 1993),
-;; pages 383-404.
-
-;;; Code:
-
-(require 'calendar)
-
-(defconst calendar-mayan-days-before-absolute-zero 1137140
- "Number of days of the Mayan calendar epoch before absolute day 0.
-According to the Goodman-Martinez-Thompson correlation. This correlation is
-not universally accepted, as it still a subject of astro-archeological
-research. Using 1232041 will give you Spinden's correlation; using
-1142840 will give you Hochleitner's correlation.")
-
-(defconst calendar-mayan-haab-at-epoch '(8 . 18)
- "Mayan haab date at the epoch.")
-
-(defconst calendar-mayan-haab-month-name-array
- ["Pop" "Uo" "Zip" "Zotz" "Tzec" "Xul" "Yaxkin" "Mol" "Chen" "Yax"
- "Zac" "Ceh" "Mac" "Kankin" "Muan" "Pax" "Kayab" "Cumku"])
-
-(defconst calendar-mayan-tzolkin-at-epoch '(4 . 20)
- "Mayan tzolkin date at the epoch.")
-
-(defconst calendar-mayan-tzolkin-names-array
- ["Imix" "Ik" "Akbal" "Kan" "Chicchan" "Cimi" "Manik" "Lamat" "Muluc" "Oc"
- "Chuen" "Eb" "Ben" "Ix" "Men" "Cib" "Caban" "Etznab" "Cauac" "Ahau"])
-
-(defun calendar-mayan-long-count-from-absolute (date)
- "Compute the Mayan long count corresponding to the absolute DATE."
- (let ((long-count (+ date calendar-mayan-days-before-absolute-zero)))
- (let* ((baktun (/ long-count 144000))
- (remainder (% long-count 144000))
- (katun (/ remainder 7200))
- (remainder (% remainder 7200))
- (tun (/ remainder 360))
- (remainder (% remainder 360))
- (uinal (/ remainder 20))
- (kin (% remainder 20)))
- (list baktun katun tun uinal kin))))
-
-(defun calendar-mayan-long-count-to-string (mayan-long-count)
- "Convert MAYAN-LONG-COUNT into traditional written form."
- (apply 'format (cons "%s.%s.%s.%s.%s" mayan-long-count)))
-
-(defun calendar-string-to-mayan-long-count (str)
- "Given STR, a string of format \"%d.%d.%d.%d.%d\", return list of nums."
- (let ((rlc nil)
- (c (length str))
- (cc 0))
- (condition-case condition
- (progn
- (while (< cc c)
- (let* ((start (string-match "[0-9]+" str cc))
- (end (match-end 0))
- datum)
- (setq datum (read (substring str start end)))
- (setq rlc (cons datum rlc))
- (setq cc end)))
- (if (not (= (length rlc) 5)) (signal 'invalid-read-syntax nil)))
- (invalid-read-syntax nil))
- (reverse rlc)))
-
-(defun calendar-mayan-haab-from-absolute (date)
- "Convert absolute DATE into a Mayan haab date (a pair)."
- (let* ((long-count (+ date calendar-mayan-days-before-absolute-zero))
- (day-of-haab
- (% (+ long-count
- (car calendar-mayan-haab-at-epoch)
- (* 20 (1- (cdr calendar-mayan-haab-at-epoch))))
- 365))
- (day (% day-of-haab 20))
- (month (1+ (/ day-of-haab 20))))
- (cons day month)))
-
-(defun calendar-mayan-haab-difference (date1 date2)
- "Number of days from Mayan haab DATE1 to next occurrence of haab date DATE2."
- (mod (+ (* 20 (- (cdr date2) (cdr date1)))
- (- (car date2) (car date1)))
- 365))
-
-(defun calendar-mayan-haab-on-or-before (haab-date date)
- "Absolute date of latest HAAB-DATE on or before absolute DATE."
- (- date
- (% (- date
- (calendar-mayan-haab-difference
- (calendar-mayan-haab-from-absolute 0) haab-date))
- 365)))
-
-(defun calendar-next-haab-date (haab-date &optional noecho)
- "Move cursor to next instance of Mayan HAAB-DATE.
-Echo Mayan date if NOECHO is t."
- (interactive (list (calendar-read-mayan-haab-date)))
- (calendar-goto-date
- (calendar-gregorian-from-absolute
- (calendar-mayan-haab-on-or-before
- haab-date
- (+ 365
- (calendar-absolute-from-gregorian (calendar-cursor-to-date))))))
- (or noecho (calendar-print-mayan-date)))
-
-(defun calendar-previous-haab-date (haab-date &optional noecho)
- "Move cursor to previous instance of Mayan HAAB-DATE.
-Echo Mayan date if NOECHO is t."
- (interactive (list (calendar-read-mayan-haab-date)))
- (calendar-goto-date
- (calendar-gregorian-from-absolute
- (calendar-mayan-haab-on-or-before
- haab-date
- (1- (calendar-absolute-from-gregorian (calendar-cursor-to-date))))))
- (or noecho (calendar-print-mayan-date)))
-
-(defun calendar-mayan-haab-to-string (haab)
- "Convert Mayan haab date (a pair) into its traditional written form."
- (let ((month (cdr haab))
- (day (car haab)))
- ;; 19th month consists of 5 special days
- (if (= month 19)
- (format "%d Uayeb" day)
- (format "%d %s"
- day
- (aref calendar-mayan-haab-month-name-array (1- month))))))
-
-(defun calendar-mayan-tzolkin-from-absolute (date)
- "Convert absolute DATE into a Mayan tzolkin date (a pair)."
- (let* ((long-count (+ date calendar-mayan-days-before-absolute-zero))
- (day (calendar-mod
- (+ long-count (car calendar-mayan-tzolkin-at-epoch))
- 13))
- (name (calendar-mod
- (+ long-count (cdr calendar-mayan-tzolkin-at-epoch))
- 20)))
- (cons day name)))
-
-(defun calendar-mayan-tzolkin-difference (date1 date2)
- "Number of days from Mayan tzolkin DATE1 to next occurrence of tzolkin DATE2."
- (let ((number-difference (- (car date2) (car date1)))
- (name-difference (- (cdr date2) (cdr date1))))
- (mod (+ number-difference
- (* 13 (mod (* 3 (- number-difference name-difference))
- 20)))
- 260)))
-
-(defun calendar-mayan-tzolkin-on-or-before (tzolkin-date date)
- "Absolute date of latest TZOLKIN-DATE on or before absolute DATE."
- (- date
- (% (- date (calendar-mayan-tzolkin-difference
- (calendar-mayan-tzolkin-from-absolute 0)
- tzolkin-date))
- 260)))
-
-(defun calendar-next-tzolkin-date (tzolkin-date &optional noecho)
- "Move cursor to next instance of Mayan TZOLKIN-DATE.
-Echo Mayan date if NOECHO is t."
- (interactive (list (calendar-read-mayan-tzolkin-date)))
- (calendar-goto-date
- (calendar-gregorian-from-absolute
- (calendar-mayan-tzolkin-on-or-before
- tzolkin-date
- (+ 260
- (calendar-absolute-from-gregorian (calendar-cursor-to-date))))))
- (or noecho (calendar-print-mayan-date)))
-
-(defun calendar-previous-tzolkin-date (tzolkin-date &optional noecho)
- "Move cursor to previous instance of Mayan TZOLKIN-DATE.
-Echo Mayan date if NOECHO is t."
- (interactive (list (calendar-read-mayan-tzolkin-date)))
- (calendar-goto-date
- (calendar-gregorian-from-absolute
- (calendar-mayan-tzolkin-on-or-before
- tzolkin-date
- (1- (calendar-absolute-from-gregorian (calendar-cursor-to-date))))))
- (or noecho (calendar-print-mayan-date)))
-
-(defun calendar-mayan-tzolkin-to-string (tzolkin)
- "Convert Mayan tzolkin date (a pair) into its traditional written form."
- (format "%d %s"
- (car tzolkin)
- (aref calendar-mayan-tzolkin-names-array (1- (cdr tzolkin)))))
-
-(defun calendar-mayan-tzolkin-haab-on-or-before (tzolkin-date haab-date date)
- "Absolute date that is Mayan TZOLKIN-DATE and HAAB-DATE.
-Latest such date on or before DATE.
-Returns nil if such a tzolkin-haab combination is impossible."
- (let* ((haab-difference
- (calendar-mayan-haab-difference
- (calendar-mayan-haab-from-absolute 0)
- haab-date))
- (tzolkin-difference
- (calendar-mayan-tzolkin-difference
- (calendar-mayan-tzolkin-from-absolute 0)
- tzolkin-date))
- (difference (- tzolkin-difference haab-difference)))
- (if (= (% difference 5) 0)
- (- date
- (mod (- date
- (+ haab-difference (* 365 difference)))
- 18980))
- nil)))
-
-(defun calendar-read-mayan-haab-date ()
- "Prompt for a Mayan haab date"
- (let* ((completion-ignore-case t)
- (haab-day (calendar-read
- "Haab kin (0-19): "
- '(lambda (x) (and (>= x 0) (< x 20)))))
- (haab-month-list (append calendar-mayan-haab-month-name-array
- (and (< haab-day 5) '("Uayeb"))))
- (haab-month (cdr
- (assoc
- (capitalize
- (completing-read "Haab uinal: "
- (mapcar 'list haab-month-list)
- nil t))
- (calendar-make-alist
- haab-month-list 1 'capitalize)))))
- (cons haab-day haab-month)))
-
-(defun calendar-read-mayan-tzolkin-date ()
- "Prompt for a Mayan tzolkin date"
- (let* ((completion-ignore-case t)
- (tzolkin-count (calendar-read
- "Tzolkin kin (1-13): "
- '(lambda (x) (and (> x 0) (< x 14)))))
- (tzolkin-name-list (append calendar-mayan-tzolkin-names-array nil))
- (tzolkin-name (cdr
- (assoc
- (capitalize
- (completing-read "Tzolkin uinal: "
- (mapcar 'list tzolkin-name-list)
- nil t))
- (calendar-make-alist
- tzolkin-name-list 1 'capitalize)))))
- (cons tzolkin-count tzolkin-name)))
-
-(defun calendar-next-calendar-round-date
- (tzolkin-date haab-date &optional noecho)
- "Move cursor to next instance of Mayan HAAB-DATE TZOLKIN-DATE combination.
-Echo Mayan date if NOECHO is t."
- (interactive (list (calendar-read-mayan-tzolkin-date)
- (calendar-read-mayan-haab-date)))
- (let ((date (calendar-mayan-tzolkin-haab-on-or-before
- tzolkin-date haab-date
- (+ 18980 (calendar-absolute-from-gregorian
- (calendar-cursor-to-date))))))
- (if (not date)
- (error "%s, %s does not exist in the Mayan calendar round"
- (calendar-mayan-tzolkin-to-string tzolkin-date)
- (calendar-mayan-haab-to-string haab-date))
- (calendar-goto-date (calendar-gregorian-from-absolute date))
- (or noecho (calendar-print-mayan-date)))))
-
-(defun calendar-previous-calendar-round-date
- (tzolkin-date haab-date &optional noecho)
- "Move to previous instance of Mayan TZOLKIN-DATE HAAB-DATE combination.
-Echo Mayan date if NOECHO is t."
- (interactive (list (calendar-read-mayan-tzolkin-date)
- (calendar-read-mayan-haab-date)))
- (let ((date (calendar-mayan-tzolkin-haab-on-or-before
- tzolkin-date haab-date
- (1- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date))))))
- (if (not date)
- (error "%s, %s does not exist in the Mayan calendar round"
- (calendar-mayan-tzolkin-to-string tzolkin-date)
- (calendar-mayan-haab-to-string haab-date))
- (calendar-goto-date (calendar-gregorian-from-absolute date))
- (or noecho (calendar-print-mayan-date)))))
-
-(defun calendar-absolute-from-mayan-long-count (c)
- "Compute the absolute date corresponding to the Mayan Long Count C.
-Long count is a list (baktun katun tun uinal kin)"
- (+ (* (nth 0 c) 144000) ; baktun
- (* (nth 1 c) 7200) ; katun
- (* (nth 2 c) 360) ; tun
- (* (nth 3 c) 20) ; uinal
- (nth 4 c) ; kin (days)
- (- ; days before absolute date 0
- calendar-mayan-days-before-absolute-zero)))
-
-(defun calendar-mayan-date-string (&optional date)
- "String of Mayan date of Gregorian DATE.
-Defaults to today's date if DATE is not given."
- (let* ((d (calendar-absolute-from-gregorian
- (or date (calendar-current-date))))
- (tzolkin (calendar-mayan-tzolkin-from-absolute d))
- (haab (calendar-mayan-haab-from-absolute d))
- (long-count (calendar-mayan-long-count-from-absolute d)))
- (format "Long count = %s; tzolkin = %s; haab = %s"
- (calendar-mayan-long-count-to-string long-count)
- (calendar-mayan-tzolkin-to-string tzolkin)
- (calendar-mayan-haab-to-string haab))))
-
-(defun calendar-print-mayan-date ()
- "Show the Mayan long count, tzolkin, and haab equivalents of date."
- (interactive)
- (message "Mayan date: %s"
- (calendar-mayan-date-string (calendar-cursor-to-date t))))
-
-(defun calendar-goto-mayan-long-count-date (date &optional noecho)
- "Move cursor to Mayan long count DATE. Echo Mayan date unless NOECHO is t."
- (interactive
- (let (lc)
- (while (not lc)
- (let ((datum
- (calendar-string-to-mayan-long-count
- (read-string "Mayan long count (baktun.katun.tun.uinal.kin): "
- (calendar-mayan-long-count-to-string
- (calendar-mayan-long-count-from-absolute
- (calendar-absolute-from-gregorian
- (calendar-current-date))))))))
- (if (calendar-mayan-long-count-common-era datum)
- (setq lc datum))))
- (list lc)))
- (calendar-goto-date
- (calendar-gregorian-from-absolute
- (calendar-absolute-from-mayan-long-count date)))
- (or noecho (calendar-print-mayan-date)))
-
-(defun calendar-mayan-long-count-common-era (lc)
- "T if long count represents date in the Common Era."
- (let ((base (calendar-mayan-long-count-from-absolute 1)))
- (while (and (not (null base)) (= (car lc) (car base)))
- (setq lc (cdr lc)
- base (cdr base)))
- (or (null lc) (> (car lc) (car base)))))
-
-(defun diary-mayan-date ()
- "Show the Mayan long count, haab, and tzolkin dates as a diary entry."
- (format "Mayan date: %s" (calendar-mayan-date-string date)))
-
-(provide 'cal-mayan)
-
-;;; cal-mayan.el ends here
diff --git a/lisp/calendar/cal-menu.el b/lisp/calendar/cal-menu.el
deleted file mode 100644
index b8d17ef5597..00000000000
--- a/lisp/calendar/cal-menu.el
+++ /dev/null
@@ -1,523 +0,0 @@
-;;; cal-menu.el --- calendar functions for menu bar and popup menu support
-
-;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Lara Rios <lrios@coewl.cen.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: calendar, popup menus, menu bar
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements menu bar and popup menu support for
-;; calendar.el.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(define-key calendar-mode-map [menu-bar edit] 'undefined)
-(define-key calendar-mode-map [menu-bar search] 'undefined)
-
-(define-key calendar-mode-map [down-mouse-2] 'calendar-mouse-2-date-menu)
-(define-key calendar-mode-map [mouse-2] 'ignore)
-
-(defvar calendar-mouse-3-map (make-sparse-keymap "Calendar"))
-(define-key calendar-mode-map [down-mouse-3] calendar-mouse-3-map)
-(define-key calendar-mode-map [C-down-mouse-3] calendar-mouse-3-map)
-
-(define-key calendar-mode-map [menu-bar moon]
- (cons "Moon" (make-sparse-keymap "Moon")))
-
-(define-key calendar-mode-map [menu-bar moon moon]
- '("Lunar Phases" . calendar-phases-of-moon))
-
-(define-key calendar-mode-map [menu-bar diary]
- (cons "Diary" (make-sparse-keymap "Diary")))
-
-(define-key calendar-mode-map [menu-bar diary heb]
- '("Insert Hebrew" . calendar-mouse-insert-hebrew-diary-entry))
-(define-key calendar-mode-map [menu-bar diary isl]
- '("Insert Islamic" . calendar-mouse-insert-islamic-diary-entry))
-(define-key calendar-mode-map [menu-bar diary cyc]
- '("Insert Cyclic" . insert-cyclic-diary-entry))
-(define-key calendar-mode-map [menu-bar diary blk]
- '("Insert Block" . insert-block-diary-entry))
-(define-key calendar-mode-map [menu-bar diary ann]
- '("Insert Anniversary" . insert-anniversary-diary-entry))
-(define-key calendar-mode-map [menu-bar diary yr]
- '("Insert Yearly" . insert-yearly-diary-entry))
-(define-key calendar-mode-map [menu-bar diary mon]
- '("Insert Monthly" . insert-monthly-diary-entry))
-(define-key calendar-mode-map [menu-bar diary wk]
- '("Insert Weekly" . insert-weekly-diary-entry))
-(define-key calendar-mode-map [menu-bar diary ent]
- '("Insert Daily". insert-diary-entry))
-(define-key calendar-mode-map [menu-bar diary all]
- '("Show All" . show-all-diary-entries))
-(define-key calendar-mode-map [menu-bar diary mark]
- '("Mark All" . mark-diary-entries))
-(define-key calendar-mode-map [menu-bar diary view]
- '("Cursor Date" . view-diary-entries))
-(define-key calendar-mode-map [menu-bar diary view]
- '("Other File" . view-other-diary-entries))
-
-(define-key calendar-mode-map [menu-bar holidays]
- (cons "Holidays" (make-sparse-keymap "Holidays")))
-
-(define-key calendar-mode-map [menu-bar holidays unmark]
- '("Unmark" . calendar-unmark))
-(define-key calendar-mode-map [menu-bar holidays mark]
- '("Mark" . mark-calendar-holidays))
-(define-key calendar-mode-map [menu-bar holidays 3-mon]
- '("3 Months" . list-calendar-holidays))
-(define-key calendar-mode-map [menu-bar holidays 1-day]
- '("One Day" . calendar-cursor-holidays))
-
-(define-key calendar-mode-map [menu-bar goto]
- (cons "Goto" (make-sparse-keymap "Goto")))
-
-(define-key calendar-mode-map [menu-bar goto french]
- '("French Date" . calendar-goto-french-date))
-(define-key calendar-mode-map [menu-bar goto mayan]
- (cons "Mayan Date" (make-sparse-keymap "Mayan")))
-(define-key calendar-mode-map [menu-bar goto ethiopic]
- '("Ethiopic Date" . calendar-goto-ethiopic-date))
-(define-key calendar-mode-map [menu-bar goto coptic]
- '("Coptic Date" . calendar-goto-coptic-date))
-(define-key calendar-mode-map [menu-bar goto chinese]
- '("Chinese Date" . calendar-goto-chinese-date))
-(define-key calendar-mode-map [menu-bar goto julian]
- '("Julian Date" . calendar-goto-julian-date))
-(define-key calendar-mode-map [menu-bar goto islamic]
- '("Islamic Date" . calendar-goto-islamic-date))
-(define-key calendar-mode-map [menu-bar goto persian]
- '("Persian Date" . calendar-goto-persian-date))
-(define-key calendar-mode-map [menu-bar goto hebrew]
- '("Hebrew Date" . calendar-goto-hebrew-date))
-(define-key calendar-mode-map [menu-bar goto astro]
- '("Astronomical Date" . calendar-goto-astro-day-number))
-(define-key calendar-mode-map [menu-bar goto iso]
- '("ISO Date" . calendar-goto-iso-date))
-(define-key calendar-mode-map [menu-bar goto gregorian]
- '("Other Date" . calendar-goto-date))
-(define-key calendar-mode-map [menu-bar goto end-of-year]
- '("End of Year" . calendar-end-of-year))
-(define-key calendar-mode-map [menu-bar goto beginning-of-year]
- '("Beginning of Year" . calendar-beginning-of-year))
-(define-key calendar-mode-map [menu-bar goto end-of-month]
- '("End of Month" . calendar-end-of-month))
-(define-key calendar-mode-map [menu-bar goto beginning-of-month]
- '("Beginning of Month" . calendar-beginning-of-month))
-(define-key calendar-mode-map [menu-bar goto end-of-week]
- '("End of Week" . calendar-end-of-week))
-(define-key calendar-mode-map [menu-bar goto beginning-of-week]
- '("Beginning of Week" . calendar-beginning-of-week))
-(define-key calendar-mode-map [menu-bar goto today]
- '("Today" . calendar-goto-today))
-
-
-(define-key calendar-mode-map [menu-bar goto mayan prev-rnd]
- '("Previous Round" . calendar-previous-calendar-round-date))
-(define-key calendar-mode-map [menu-bar goto mayan nxt-rnd]
- '("Next Round" . calendar-next-calendar-round-date))
-(define-key calendar-mode-map [menu-bar goto mayan prev-haab]
- '("Previous Haab" . calendar-previous-haab-date))
-(define-key calendar-mode-map [menu-bar goto mayan next-haab]
- '("Next Haab" . calendar-next-haab-date))
-(define-key calendar-mode-map [menu-bar goto mayan prev-tzol]
- '("Previous Tzolkin" . calendar-previous-tzolkin-date))
-(define-key calendar-mode-map [menu-bar goto mayan next-tzol]
- '("Next Tzolkin" . calendar-next-tzolkin-date))
-
-(define-key calendar-mode-map [menu-bar scroll]
- (cons "Scroll" (make-sparse-keymap "Scroll")))
-
-(define-key calendar-mode-map [menu-bar scroll bk-12]
- '("Backward 1 Year" . "4\ev"))
-(define-key calendar-mode-map [menu-bar scroll bk-3]
- '("Backward 3 Months" . scroll-calendar-right-three-months))
-(define-key calendar-mode-map [menu-bar scroll bk-1]
- '("Backward 1 Month" . scroll-calendar-right))
-(define-key calendar-mode-map [menu-bar scroll fwd-12]
- '("Forward 1 Year" . "4\C-v"))
-(define-key calendar-mode-map [menu-bar scroll fwd-3]
- '("Forward 3 Months" . scroll-calendar-left-three-months))
-(define-key calendar-mode-map [menu-bar scroll fwd-1]
- '("Forward 1 Month" . scroll-calendar-left))
-
-(put 'calendar-forward-day 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-backward-day 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-forward-week 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-backward-week 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-forward-month 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-backward-month 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-forward-year 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-backward-year 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-beginning-of-year 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-end-of-year 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-beginning-of-month 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-end-of-month 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-end-of-week 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-beginning-of-week 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-mouse-print-dates 'menu-enable '(calendar-event-to-date))
-(put 'calendar-sunrise-sunset 'menu-enable '(calendar-event-to-date))
-(put 'calendar-cursor-holidays 'menu-enable '(calendar-cursor-to-date))
-(put 'view-diary-entries 'menu-enable '(calendar-cursor-to-date))
-(put 'view-other-diary-entries 'menu-enable '(calendar-cursor-to-date))
-(put 'calendar-mouse-insert-hebrew-diary-entry
- 'menu-enable
- '(calendar-cursor-to-date))
-(put 'calendar-mouse-insert-islamic-diary-entry
- 'menu-enable
- '(calendar-cursor-to-date))
-(put 'insert-cyclic-diary-entry 'menu-enable '(calendar-cursor-to-date))
-(put 'insert-block-diary-entry 'menu-enable '(calendar-cursor-to-date))
-(put 'insert-anniversary-diary-entry 'menu-enable '(calendar-cursor-to-date))
-(put 'insert-yearly-diary-entry 'menu-enable '(calendar-cursor-to-date))
-(put 'insert-monthly-diary-entry 'menu-enable '(calendar-cursor-to-date))
-(put 'insert-weekly-diary-entry 'menu-enable '(calendar-cursor-to-date))
-(put 'cal-tex-cursor-day 'menu-enable '(calendar-cursor-to-date))
-(put 'cal-tex-cursor-week 'menu-enable '(calendar-cursor-to-date))
-(put 'cal-tex-cursor-week2 'menu-enable '(calendar-cursor-to-date))
-(put 'cal-tex-cursor-week-iso 'menu-enable '(calendar-cursor-to-date))
-(put 'cal-tex-cursor-week-monday 'menu-enable '(calendar-cursor-to-date))
-(put 'cal-tex-cursor-filofax-2week
- 'menu-enable '(calendar-cursor-to-date))
-(put 'cal-tex-cursor-filofax-week 'menu-enable '(calendar-cursor-to-date))
-(put 'cal-tex-cursor-month 'menu-enable '(calendar-cursor-to-date))
-(put 'cal-tex-cursor-month-landscape 'menu-enable '(calendar-cursor-to-date))
-(put 'cal-tex-cursor-year 'menu-enable '(calendar-cursor-to-date))
-(put 'cal-tex-cursor-filofax-year 'menu-enable '(calendar-cursor-to-date))
-(put 'cal-tex-cursor-year-landscape 'menu-enable '(calendar-cursor-to-date))
-
-(defun calendar-event-to-date (&optional error)
- "Date of last event.
-If event is not on a specific date, signals an error if optional parameter
-ERROR is t, otherwise just returns nil."
- (save-excursion
- (set-buffer (window-buffer (posn-window (event-start last-input-event))))
- (goto-char (posn-point (event-start last-input-event)))
- (calendar-cursor-to-date error)))
-
-(defun calendar-mouse-insert-hebrew-diary-entry (event)
- "Pop up menu to insert a Hebrew-date diary entry."
- (interactive "e")
- (let ((hebrew-selection
- (x-popup-menu
- event
- (list "Hebrew insert menu"
- (list (calendar-hebrew-date-string (calendar-cursor-to-date))
- '("One time" . insert-hebrew-diary-entry)
- '("Monthly" . insert-monthly-hebrew-diary-entry)
- '("Yearly" . insert-yearly-hebrew-diary-entry))))))
- (and hebrew-selection (call-interactively hebrew-selection))))
-
-(defun calendar-mouse-insert-islamic-diary-entry (event)
- "Pop up menu to insert an Islamic-date diary entry."
- (interactive "e")
- (let ((islamic-selection
- (x-popup-menu
- event
- (list "Islamic insert menu"
- (list (calendar-islamic-date-string (calendar-cursor-to-date))
- '("One time" . insert-islamic-diary-entry)
- '("Monthly" . insert-monthly-islamic-diary-entry)
- '("Yearly" . insert-yearly-islamic-diary-entry))))))
- (and islamic-selection (call-interactively islamic-selection))))
-
-(defun calendar-mouse-sunrise/sunset ()
- "Show sunrise/sunset times for mouse-selected date."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (calendar-sunrise-sunset)))
-
-(defun calendar-mouse-holidays ()
- "Show holidays for mouse-selected date."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (calendar-cursor-holidays)))
-
-(defun calendar-mouse-view-diary-entries ()
- "View diary entries on mouse-selected date."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (view-diary-entries 1)))
-
-(defun calendar-mouse-view-other-diary-entries ()
- "View diary entries from alternative file on mouse-selected date."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (call-interactively 'view-other-diary-entries)))
-
-(defun calendar-mouse-insert-diary-entry ()
- "Insert diary entry for mouse-selected date."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (insert-diary-entry nil)))
-
-(defun calendar-mouse-set-mark ()
- "Mark the date under the cursor."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (calendar-set-mark nil)))
-
-(defun cal-tex-mouse-day ()
- "Make a buffer with LaTeX commands for the day mouse is on."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (cal-tex-cursor-day nil)))
-
-(defun cal-tex-mouse-week ()
- "One page calendar for week indicated by cursor.
-Holidays are included if `cal-tex-holidays' is t."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (cal-tex-cursor-week nil)))
-
-(defun cal-tex-mouse-week2 ()
- "Make a buffer with LaTeX commands for the week cursor is on.
-The printed output will be on two pages."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (cal-tex-cursor-week2 nil)))
-
-(defun cal-tex-mouse-week-iso ()
- "One page calendar for week indicated by cursor.
-Holidays are included if `cal-tex-holidays' is t."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (cal-tex-cursor-week-iso nil)))
-
-(defun cal-tex-mouse-week-monday ()
- "One page calendar for week indicated by cursor."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (cal-tex-cursor-week-monday nil)))
-
-(defun cal-tex-mouse-filofax-2week ()
- "One page Filofax calendar for week indicated by cursor."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (cal-tex-cursor-filofax-2week nil)))
-
-(defun cal-tex-mouse-filofax-week ()
- "Two page Filofax calendar for week indicated by cursor."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (cal-tex-cursor-filofax-week nil)))
-
-(defun cal-tex-mouse-month ()
- "Make a buffer with LaTeX commands for the month cursor is on.
-Calendar is condensed onto one page."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (cal-tex-cursor-month nil)))
-
-(defun cal-tex-mouse-month-landscape ()
- "Make a buffer with LaTeX commands for the month cursor is on.
-The output is in landscape format, one month to a page."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (cal-tex-cursor-month-landscape nil)))
-
-(defun cal-tex-mouse-year ()
- "Make a buffer with LaTeX commands for the year cursor is on."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (cal-tex-cursor-year nil)))
-
-(defun cal-tex-mouse-filofax-year ()
- "Make a buffer with LaTeX commands for Filofax calendar of year cursor is on."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (cal-tex-cursor-filofax-year nil)))
-
-(defun cal-tex-mouse-year-landscape ()
- "Make a buffer with LaTeX commands for the year cursor is on."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (cal-tex-cursor-year-landscape nil)))
-
-(defun calendar-mouse-print-dates ()
- "Pop up menu of equivalent dates to mouse selected date."
- (interactive)
- (let ((date (calendar-event-to-date))
- (selection
- (x-popup-menu
- event
- (list
- (concat (calendar-date-string date) " (Gregorian)")
- (append
- (list
- (concat (calendar-date-string date) " (Gregorian)")
- (list (calendar-day-of-year-string date))
- (list (format "ISO date: %s" (calendar-iso-date-string date)))
- (list (format "Julian date: %s"
- (calendar-julian-date-string date)))
- (list
- (format "Astronomical (Julian) day number (at noon UTC): %s.0"
- (calendar-astro-date-string date)))
- (list (format "Hebrew date (before sunset): %s"
- (calendar-hebrew-date-string date)))
- (list (format "Persian date: %s"
- (calendar-persian-date-string date))))
- (let ((i (calendar-islamic-date-string date)))
- (if (not (string-equal i ""))
- (list (list (format "Islamic date (before sunset): %s" i)))))
- (list
- (list (format "Chinese date: %s"
- (calendar-chinese-date-string date))))
-; (list '("Chinese date (select to echo Chinese date)"
-; . calendar-mouse-chinese-date))
- (let ((c (calendar-coptic-date-string date)))
- (if (not (string-equal c ""))
- (list (list (format "Coptic date: %s" c)))))
- (let ((e (calendar-ethiopic-date-string date)))
- (if (not (string-equal e ""))
- (list (list (format "Ethiopic date: %s" e)))))
- (let ((f (calendar-french-date-string date)))
- (if (not (string-equal f ""))
- (list (list (format "French Revolutionary date: %s" f)))))
- (list
- (list
- (format "Mayan date: %s"
- (calendar-mayan-date-string date)))))))))
- (and selection (call-interactively selection))))
-
-(defun calendar-mouse-chinese-date ()
- "Show Chinese equivalent for mouse-selected date."
- (interactive)
- (save-excursion
- (calendar-mouse-goto-date (calendar-event-to-date))
- (calendar-print-chinese-date)))
-
-(defun calendar-mouse-goto-date (date)
- (set-buffer (window-buffer (posn-window (event-start last-input-event))))
- (calendar-goto-date date))
-
-(defun calendar-mouse-2-date-menu (event)
- "Pop up menu for Mouse-2 for selected date in the calendar window."
- (interactive "e")
- (let* ((date (calendar-event-to-date t))
- (selection
- (x-popup-menu
- event
- (list (calendar-date-string date t nil)
- (list
- ""
- '("Holidays" . calendar-mouse-holidays)
- '("Mark date" . calendar-mouse-set-mark)
- '("Sunrise/sunset" . calendar-mouse-sunrise/sunset)
- '("Other calendars" . calendar-mouse-print-dates)
- '("Prepare LaTeX buffer" . calendar-mouse-cal-tex-menu)
- '("Diary entries" . calendar-mouse-view-diary-entries)
- '("Insert diary entry" . calendar-mouse-insert-diary-entry)
- '("Other diary file entries"
- . calendar-mouse-view-other-diary-entries)
- )))))
- (and selection (call-interactively selection))))
-
-(defun calendar-mouse-cal-tex-menu (event)
- "Pop up submenu for Mouse-2 for cal-tex commands for selected date in the calendar window."
- (interactive "e")
- (let* ((selection
- (x-popup-menu
- event
- (list (calendar-date-string date t nil)
- (list
- ""
- '("Daily (1 page)" . cal-tex-mouse-day)
- '("Weekly (1 page)" . cal-tex-mouse-week)
- '("Weekly (2 pages)" . cal-tex-mouse-week2)
- '("Weekly (other style; 1 page)" . cal-tex-mouse-week-iso)
- '("Weekly (yet another style; 1 page)" .
- cal-tex-mouse-week-monday)
- '("Monthly" . cal-tex-mouse-month)
- '("Monthly (landscape)" . cal-tex-mouse-month-landscape)
- '("Yearly" . cal-tex-mouse-year)
- '("Yearly (landscape)" . cal-tex-mouse-year-landscape)
- '("Filofax styles" . cal-tex-mouse-filofax)
- )))))
- (and selection (call-interactively selection))))
-
-(defun cal-tex-mouse-filofax (event)
- "Pop up sub-submenu for Mouse-2 for Filofax cal-tex commands for selected date."
- (interactive "e")
- (let* ((selection
- (x-popup-menu
- event
- (list (calendar-date-string date t nil)
- (list
- ""
- '("Filofax Weekly (2-weeks-at-a-glance)" .
- cal-tex-mouse-filofax-2week)
- '("Filofax Weekly (week-at-a-glance)" .
- cal-tex-mouse-filofax-week)
- '("Filofax Yearly" . cal-tex-mouse-filofax-year)
- )))))
- (and selection (call-interactively selection))))
-
-(define-key calendar-mouse-3-map [exit-calendar]
- '("Exit calendar" . exit-calendar))
-(define-key calendar-mouse-3-map [show-diary]
- '("Show diary" . show-all-diary-entries))
-(define-key calendar-mouse-3-map [lunar-phases]
- '("Lunar phases" . calendar-phases-of-moon))
-(define-key calendar-mouse-3-map [unmark]
- '("Unmark" . calendar-unmark))
-(define-key calendar-mouse-3-map [mark-holidays]
- '("Mark holidays" . mark-calendar-holidays))
-(define-key calendar-mouse-3-map [list-holidays]
- '("List holidays" . list-calendar-holidays))
-(define-key calendar-mouse-3-map [mark-diary-entries]
- '("Mark diary entries" . mark-diary-entries))
-(define-key calendar-mouse-3-map [scroll-backward]
- '("Scroll backward" . scroll-calendar-right-three-months))
-(define-key calendar-mouse-3-map [scroll-forward]
- '("Scroll forward" . scroll-calendar-left-three-months))
-
-(run-hooks 'cal-menu-load-hook)
-
-(provide 'cal-menu)
-
-;;; cal-menu.el ends here
diff --git a/lisp/calendar/cal-move.el b/lisp/calendar/cal-move.el
deleted file mode 100644
index 8ec3295d77a..00000000000
--- a/lisp/calendar/cal-move.el
+++ /dev/null
@@ -1,315 +0,0 @@
-;;; cal-move.el --- calendar functions for movement in the calendar
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: calendar
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements movement in the calendar for
-;; calendar.el.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(defun calendar-goto-today ()
- "Reposition the calendar window so the current date is visible."
- (interactive)
- (let ((today (calendar-current-date)));; The date might have changed.
- (if (not (calendar-date-is-visible-p today))
- (generate-calendar-window)
- (update-calendar-mode-line)
- (calendar-cursor-to-visible-date today))))
-
-(defun calendar-forward-month (arg)
- "Move the cursor forward ARG months.
-Movement is backward if ARG is negative."
- (interactive "p")
- (calendar-cursor-to-nearest-date)
- (let* ((cursor-date (calendar-cursor-to-date t))
- (month (extract-calendar-month cursor-date))
- (day (extract-calendar-day cursor-date))
- (year (extract-calendar-year cursor-date)))
- (increment-calendar-month month year arg)
- (let ((last (calendar-last-day-of-month month year)))
- (if (< last day)
- (setq day last)))
- ;; Put the new month on the screen, if needed, and go to the new date.
- (let ((new-cursor-date (list month day year)))
- (if (not (calendar-date-is-visible-p new-cursor-date))
- (calendar-other-month month year))
- (calendar-cursor-to-visible-date new-cursor-date))))
-
-(defun calendar-forward-year (arg)
- "Move the cursor forward by ARG years.
-Movement is backward if ARG is negative."
- (interactive "p")
- (calendar-forward-month (* 12 arg)))
-
-(defun calendar-backward-month (arg)
- "Move the cursor backward by ARG months.
-Movement is forward if ARG is negative."
- (interactive "p")
- (calendar-forward-month (- arg)))
-
-(defun calendar-backward-year (arg)
- "Move the cursor backward ARG years.
-Movement is forward is ARG is negative."
- (interactive "p")
- (calendar-forward-month (* -12 arg)))
-
-(defun scroll-calendar-left (arg)
- "Scroll the displayed calendar left by ARG months.
-If ARG is negative the calendar is scrolled right. Maintains the relative
-position of the cursor with respect to the calendar as well as possible."
- (interactive "p")
- (calendar-cursor-to-nearest-date)
- (let ((old-date (calendar-cursor-to-date))
- (today (calendar-current-date)))
- (if (/= arg 0)
- (progn
- (increment-calendar-month displayed-month displayed-year arg)
- (generate-calendar-window displayed-month displayed-year)
- (calendar-cursor-to-visible-date
- (cond
- ((calendar-date-is-visible-p old-date) old-date)
- ((calendar-date-is-visible-p today) today)
- (t (list displayed-month 1 displayed-year))))))))
-
-(defun scroll-calendar-right (arg)
- "Scroll the displayed calendar window right by ARG months.
-If ARG is negative the calendar is scrolled left. Maintains the relative
-position of the cursor with respect to the calendar as well as possible."
- (interactive "p")
- (scroll-calendar-left (- arg)))
-
-(defun scroll-calendar-left-three-months (arg)
- "Scroll the displayed calendar window left by 3*ARG months.
-If ARG is negative the calendar is scrolled right. Maintains the relative
-position of the cursor with respect to the calendar as well as possible."
- (interactive "p")
- (scroll-calendar-left (* 3 arg)))
-
-(defun scroll-calendar-right-three-months (arg)
- "Scroll the displayed calendar window right by 3*ARG months.
-If ARG is negative the calendar is scrolled left. Maintains the relative
-position of the cursor with respect to the calendar as well as possible."
- (interactive "p")
- (scroll-calendar-left (* -3 arg)))
-
-(defun calendar-cursor-to-nearest-date ()
- "Move the cursor to the closest date.
-The position of the cursor is unchanged if it is already on a date.
-Returns the list (month day year) giving the cursor position."
- (let ((date (calendar-cursor-to-date))
- (column (current-column)))
- (if date
- date
- (if (> 3 (count-lines (point-min) (point)))
- (progn
- (goto-line 3)
- (move-to-column column)))
- (if (not (looking-at "[0-9]"))
- (if (and (not (looking-at " *$"))
- (or (< column 25)
- (and (> column 27)
- (< column 50))
- (and (> column 52)
- (< column 75))))
- (progn
- (re-search-forward "[0-9]" nil t)
- (backward-char 1))
- (re-search-backward "[0-9]" nil t)))
- (calendar-cursor-to-date))))
-
-(defun calendar-forward-day (arg)
- "Move the cursor forward ARG days.
-Moves backward if ARG is negative."
- (interactive "p")
- (if (/= 0 arg)
- (let*
- ((cursor-date (calendar-cursor-to-date))
- (cursor-date (if cursor-date
- cursor-date
- (if (> arg 0) (setq arg (1- arg)))
- (calendar-cursor-to-nearest-date)))
- (new-cursor-date
- (calendar-gregorian-from-absolute
- (+ (calendar-absolute-from-gregorian cursor-date) arg)))
- (new-display-month (extract-calendar-month new-cursor-date))
- (new-display-year (extract-calendar-year new-cursor-date)))
- ;; Put the new month on the screen, if needed, and go to the new date.
- (if (not (calendar-date-is-visible-p new-cursor-date))
- (calendar-other-month new-display-month new-display-year))
- (calendar-cursor-to-visible-date new-cursor-date))))
-
-(defun calendar-backward-day (arg)
- "Move the cursor back ARG days.
-Moves forward if ARG is negative."
- (interactive "p")
- (calendar-forward-day (- arg)))
-
-(defun calendar-forward-week (arg)
- "Move the cursor forward ARG weeks.
-Moves backward if ARG is negative."
- (interactive "p")
- (calendar-forward-day (* arg 7)))
-
-(defun calendar-backward-week (arg)
- "Move the cursor back ARG weeks.
-Moves forward if ARG is negative."
- (interactive "p")
- (calendar-forward-day (* arg -7)))
-
-(defun calendar-beginning-of-week (arg)
- "Move the cursor back ARG calendar-week-start-day's."
- (interactive "p")
- (calendar-cursor-to-nearest-date)
- (let ((day (calendar-day-of-week (calendar-cursor-to-date))))
- (calendar-backward-day
- (if (= day calendar-week-start-day)
- (* 7 arg)
- (+ (mod (- day calendar-week-start-day) 7)
- (* 7 (1- arg)))))))
-
-(defun calendar-end-of-week (arg)
- "Move the cursor forward ARG calendar-week-start-day+6's."
- (interactive "p")
- (calendar-cursor-to-nearest-date)
- (let ((day (calendar-day-of-week (calendar-cursor-to-date))))
- (calendar-forward-day
- (if (= day (mod (1- calendar-week-start-day) 7))
- (* 7 arg)
- (+ (- 6 (mod (- day calendar-week-start-day) 7))
- (* 7 (1- arg)))))))
-
-(defun calendar-beginning-of-month (arg)
- "Move the cursor backward ARG month beginnings."
- (interactive "p")
- (calendar-cursor-to-nearest-date)
- (let* ((date (calendar-cursor-to-date))
- (month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date)))
- (if (= day 1)
- (calendar-backward-month arg)
- (calendar-cursor-to-visible-date (list month 1 year))
- (calendar-backward-month (1- arg)))))
-
-(defun calendar-end-of-month (arg)
- "Move the cursor forward ARG month ends."
- (interactive "p")
- (calendar-cursor-to-nearest-date)
- (let* ((date (calendar-cursor-to-date))
- (month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date))
- (last-day (calendar-last-day-of-month month year)))
- (if (/= day last-day)
- (progn
- (calendar-cursor-to-visible-date (list month last-day year))
- (setq arg (1- arg))))
- (increment-calendar-month month year arg)
- (let ((last-day (list
- month
- (calendar-last-day-of-month month year)
- year)))
- (if (not (calendar-date-is-visible-p last-day))
- (calendar-other-month month year)
- (calendar-cursor-to-visible-date last-day)))))
-
-(defun calendar-beginning-of-year (arg)
- "Move the cursor backward ARG year beginnings."
- (interactive "p")
- (calendar-cursor-to-nearest-date)
- (let* ((date (calendar-cursor-to-date))
- (month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date))
- (jan-first (list 1 1 year)))
- (if (and (= day 1) (= 1 month))
- (calendar-backward-month (* 12 arg))
- (if (and (= arg 1)
- (calendar-date-is-visible-p jan-first))
- (calendar-cursor-to-visible-date jan-first)
- (calendar-other-month 1 (- year (1- arg)))))))
-
-(defun calendar-end-of-year (arg)
- "Move the cursor forward ARG year beginnings."
- (interactive "p")
- (calendar-cursor-to-nearest-date)
- (let* ((date (calendar-cursor-to-date))
- (month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date))
- (dec-31 (list 12 31 year)))
- (if (and (= day 31) (= 12 month))
- (calendar-forward-month (* 12 arg))
- (if (and (= arg 1)
- (calendar-date-is-visible-p dec-31))
- (calendar-cursor-to-visible-date dec-31)
- (calendar-other-month 12 (- year (1- arg)))
- (calendar-cursor-to-visible-date (list 12 31 displayed-year))))))
-
-(defun calendar-cursor-to-visible-date (date)
- "Move the cursor to DATE that is on the screen."
- (let* ((month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date))
- (first-of-month-weekday (calendar-day-of-week (list month 1 year))))
- (goto-line (+ 3
- (/ (+ day -1
- (mod
- (- (calendar-day-of-week (list month 1 year))
- calendar-week-start-day)
- 7))
- 7)))
- (move-to-column (+ 6
- (* 25
- (1+ (calendar-interval
- displayed-month displayed-year month year)))
- (* 3 (mod
- (- (calendar-day-of-week date)
- calendar-week-start-day)
- 7))))))
-
-(defun calendar-goto-date (date)
- "Move cursor to DATE."
- (interactive (list (calendar-read-date)))
- (let ((month (extract-calendar-month date))
- (year (extract-calendar-year date)))
- (if (not (calendar-date-is-visible-p date))
- (calendar-other-month
- (if (and (= month 1) (= year 1))
- 2
- month)
- year)))
- (calendar-cursor-to-visible-date date))
-
-(provide 'cal-move)
-
-;;; cal-move.el ends here
diff --git a/lisp/calendar/cal-persia.el b/lisp/calendar/cal-persia.el
deleted file mode 100644
index 89269526be8..00000000000
--- a/lisp/calendar/cal-persia.el
+++ /dev/null
@@ -1,206 +0,0 @@
-;;; cal-persia.el --- calendar functions for the Persian calendar.
-
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: Persian calendar, calendar, diary
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the features of calendar.el and
-;; diary.el that deal with the Persian calendar.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(require 'cal-julian)
-
-(defvar persian-calendar-month-name-array
- ["Farvardin" "Ordibehest" "Xordad" "Tir" "Mordad" "Sahrivar" "Mehr" "Aban"
- "Azar" "Dey" "Bahman" "Esfand"])
-
-(defvar persian-calendar-epoch (calendar-absolute-from-julian '(3 19 622))
- "Absolute date of start of Persian calendar = March 19, 622 A.D. (Julian).")
-
-(defun persian-calendar-leap-year-p (year)
- "True if YEAR is a leap year on the Persian calendar."
- (< (mod (* (mod (mod (if (<= 0 year)
- ; No year zero
- (+ year 2346)
- (+ year 2347))
- 2820)
- 768)
- 683)
- 2820)
- 683))
-
-(defun persian-calendar-last-day-of-month (month year)
- "Return last day of MONTH, YEAR on the Persian calendar."
- (cond
- ((< month 7) 31)
- ((or (< month 12) (persian-calendar-leap-year-p year)) 30)
- (t 29)))
-
-(defun calendar-absolute-from-persian (date)
- "Compute absolute date from Persian date DATE.
-The absolute date is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
- (let ((month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date)))
- (if (< year 0)
- (+ (calendar-absolute-from-persian
- (list month day (1+ (mod year 2820))))
- (* 1029983 (floor year 2820)))
- (+ (1- persian-calendar-epoch); Days before epoch
- (* 365 (1- year)) ; Days in prior years.
- (* 683 ; Leap days in prior 2820-year cycles
- (floor (+ year 2345) 2820))
- (* 186 ; Leap days in prior 768 year cycles
- (floor (mod (+ year 2345) 2820) 768))
- (floor; Leap years in current 768 or 516 year cycle
- (* 683 (mod (mod (+ year 2345) 2820) 768))
- 2820)
- -568 ; Leap years in Persian years -2345...-1
- (calendar-sum ; Days in prior months this year.
- m 1 (< m month)
- (persian-calendar-last-day-of-month m year))
- day)))) ; Days so far this month.
-
-(defun calendar-persian-year-from-absolute (date)
- "Persian year corresponding to the absolute DATE."
- (let* ((d0 ; Prior days since start of 2820 cycles
- (- date (calendar-absolute-from-persian (list 1 1 -2345))))
- (n2820 ; Completed 2820-year cycles
- (floor d0 1029983))
- (d1 ; Prior days not in n2820
- (mod d0 1029983))
- (n768 ; 768-year cycles not in n2820
- (floor d1 280506))
- (d2 ; Prior days not in n2820 or n768
- (mod d1 280506))
- (n1 ; Years not in n2820 or n768
- ; we want is
- ; (floor (+ (* 2820 d2) (* 2820 366)) 1029983))
- ; but that causes overflow, so we use
- (let ((a (floor d2 366)); we use 366 as the divisor because
- ; (2820*366 mod 1029983) is small
- (b (mod d2 366)))
- (+ 1 a (floor (+ (* 2137 a) (* 2820 b) 2137) 1029983))))
- (year (+ (* 2820 n2820); Complete 2820 year cycles
- (* 768 n768) ; Complete 768 year cycles
- (if ; Remaining years
- ; Last day of 2820 year cycle
- (= d1 1029617)
- (1- n1)
- n1)
- -2345))) ; Years before year 1
- (if (< year 1)
- (1- year); No year zero
- year)))
-
-(defun calendar-persian-from-absolute (date)
- "Compute the Persian equivalent for absolute date DATE.
-The result is a list of the form (MONTH DAY YEAR).
-The absolute date is the number of days elapsed since the imaginary
-Gregorian date Sunday, December 31, 1 BC."
- (let* ((year (calendar-persian-year-from-absolute date))
- (month ; Search forward from Farvardin
- (1+ (calendar-sum m 1
- (> date
- (calendar-absolute-from-persian
- (list
- m
- (persian-calendar-last-day-of-month m year)
- year)))
- 1)))
- (day ; Calculate the day by subtraction
- (- date (1- (calendar-absolute-from-persian
- (list month 1 year))))))
- (list month day year)))
-
-(defun calendar-persian-date-string (&optional date)
- "String of Persian date of Gregorian DATE.
-Defaults to today's date if DATE is not given."
- (let* ((persian-date (calendar-persian-from-absolute
- (calendar-absolute-from-gregorian
- (or date (calendar-current-date)))))
- (y (extract-calendar-year persian-date))
- (m (extract-calendar-month persian-date)))
- (let ((monthname (aref persian-calendar-month-name-array (1- m)))
- (day (int-to-string (extract-calendar-day persian-date)))
- (dayname nil)
- (month (int-to-string m))
- (year (int-to-string y)))
- (mapconcat 'eval calendar-date-display-form ""))))
-
-(defun calendar-print-persian-date ()
- "Show the Persian calendar equivalent of the selected date."
- (interactive)
- (message "Persian date: %s"
- (calendar-persian-date-string (calendar-cursor-to-date t))))
-
-(defun calendar-goto-persian-date (date &optional noecho)
- "Move cursor to Persian date DATE.
-Echo Persian date unless NOECHO is t."
- (interactive (persian-prompt-for-date))
- (calendar-goto-date (calendar-gregorian-from-absolute
- (calendar-absolute-from-persian date)))
- (or noecho (calendar-print-persian-date)))
-
-(defun persian-prompt-for-date ()
- "Ask for a Persian date."
- (let* ((today (calendar-current-date))
- (year (calendar-read
- "Persian calendar year (not 0): "
- '(lambda (x) (/= x 0))
- (int-to-string
- (extract-calendar-year
- (calendar-persian-from-absolute
- (calendar-absolute-from-gregorian today))))))
- (completion-ignore-case t)
- (month (cdr (assoc
- (capitalize
- (completing-read
- "Persian calendar month name: "
- (mapcar 'list
- (append persian-calendar-month-name-array nil))
- nil t))
- (calendar-make-alist persian-calendar-month-name-array
- 1 'capitalize))))
- (last (persian-calendar-last-day-of-month month year))
- (day (calendar-read
- (format "Persian calendar day (1-%d): " last)
- '(lambda (x) (and (< 0 x) (<= x last))))))
- (list (list month day year))))
-
-(defun diary-persian-date ()
- "Persian calendar equivalent of date diary entry."
- (calendar-persian-date-string (calendar-cursor-to-date t)))
-
-(provide 'cal-persia)
-
-;;; cal-persia.el ends here
diff --git a/lisp/calendar/cal-tex.el b/lisp/calendar/cal-tex.el
deleted file mode 100644
index 315d2b45b4e..00000000000
--- a/lisp/calendar/cal-tex.el
+++ /dev/null
@@ -1,1608 +0,0 @@
-;;; cal-tex.el --- calendar functions for printing calendars with LaTeX.
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Steve Fisk <fisk@bowdoin.edu>
-;; Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: Calendar, LaTeX
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the creation of LaTeX calendars
-;; based on the user's holiday choices and diary file.
-
-;; TO DO
-;;
-;; (*) Add holidays and diary entries to daily calendar.
-;;
-;; (*) Add diary entries to weekly calendar functions.
-;;
-;; (*) Make calendar styles for A4 paper.
-;;
-;; (*) Make daily and monthly styles Filofax paper.
-;;
-;; (*) Improve the LaTeX command that produces the boxes in the monthly
-;; calendar to eliminate slight gap--what causes it?!
-
-;;; Code:
-
-(require 'calendar)
-
-(autoload 'list-diary-entries "diary-lib" nil t)
-(autoload 'calendar-holiday-list "holidays" nil t)
-(autoload 'calendar-iso-from-absolute "cal-iso" nil t)
-
-;;;
-;;; Customizable variables
-;;;
-
-(defvar cal-tex-which-days '(0 1 2 3 4 5 6)
- "*The days of the week that are displayed on the portrait monthly calendar.
-Sunday is 0, Monday is 1, and so on. The default is to print from Sunday to
-Saturday. For example, use
-
- (setq cal-tex-which-days '(1 3 5))
-
-to only print Monday, Wednesday, Friday.")
-
-(defvar cal-tex-holidays t
- "*If t (default), then the holidays are also printed.
-If finding the holidays is too slow, set this to nil.")
-
-(defvar cal-tex-diary nil
- "*If t, the diary entries are printed in the calendar.")
-
-(defvar cal-tex-daily-string
- '(let* ((year (extract-calendar-year date))
- (day (calendar-day-number date))
- (days-remaining (- (calendar-day-number (list 12 31 year)) day)))
- (format "%d/%d" day days-remaining))
- "*An expression in the variable `date' whose value is placed on date.
-The string resulting from evaluating this expression is placed at the bottom
-center of `date' on the monthly calendar, next to the date in the weekly
-calendars, and in the top center of daily calendars.
-
-Default is ordinal day number of the year and the number of days remaining.
-As an example of what you do, setting this to
-
- '(progn
- (require 'cal-hebrew)
- (calendar-hebrew-date-string date))
-
-will put the Hebrew date at the bottom of each day.")
-
-(defvar cal-tex-buffer "calendar.tex"
- "*The name for the tex-ed calendar.")
-
-(defvar cal-tex-24 nil
- "*If t, use a 24 hour clock in the daily calendar.")
-
-(defvar cal-tex-daily-start 8
- "*The first hour of the daily calendar page.")
-
-(defvar cal-tex-daily-end 20
- "*The last hour of the daily calendar page.")
-
-;;;
-;;; Definitions for LaTeX code
-;;;
-
-(defvar cal-tex-day-prefix "\\caldate{%s}{%s}"
- "The initial LaTeX code for a day.
-The holidays, diary entries, bottom string, and the text follow.")
-
-(defvar cal-tex-day-name-format "\\myday{%s}%%"
- "The format for LaTeX code for a day name. The names are taken from
-calendar-day-name-array.")
-
-(defvar cal-tex-cal-one-month
-"\\def\\calmonth#1#2%
-{\\begin{center}%
-\\Huge\\bf\\uppercase{#1} #2 \\\\[1cm]%
-\\end{center}}%
-\\vspace*{-1.5cm}%
-%
-"
- "LaTeX code for the month header")
-
-(defvar cal-tex-cal-multi-month
-"\\def\\calmonth#1#2#3#4%
-{\\begin{center}%
-\\Huge\\bf #1 #2---#3 #4\\\\[1cm]%
-\\end{center}}%
-\\vspace*{-1.5cm}%
-%
-"
- "LaTeX code for the month header")
-
-(defvar cal-tex-myday
-"\\renewcommand{\\myday}[1]%
-{\\makebox[\\cellwidth]{\\hfill\\large\\bf#1\\hfill}}
-%
-"
- "LaTeX code for a day heading")
-
-(defvar cal-tex-caldate
-"\\fboxsep=0pt
-\\long\\def\\caldate#1#2#3#4#5#6{%
- \\fbox{\\hbox to\\cellwidth{%
- \\vbox to\\cellheight{%
- \\hbox to\\cellwidth{%
- {\\hspace*{1mm}\\Large \\bf \\strut #2}\\hspace{.05\\cellwidth}%
- \\raisebox{\\holidaymult\\cellheight}%
- {\\parbox[t]{.75\\cellwidth}{\\tiny \\raggedright #4}}}
- \\hbox to\\cellwidth{%
- \\hspace*{1mm}\\parbox{.95\\cellwidth}{\\tiny \\raggedright #3}}
- \\hspace*{1mm}%
- \\hbox to\\cellwidth{#6}%
- \\vfill%
- \\hbox to\\cellwidth{\\hfill \\tiny #5 \\hfill}%
- \\vskip 1.4pt}%
- \\hskip -0.4pt}}}
-"
- "LaTeX code to insert one box with date info in calendar.
-This definition is the heart of the calendar!")
-
-(defun cal-tex-list-holidays (d1 d2)
- "Generate a list of all holidays from absolute date D1 to D2."
- (let* ((result nil)
- (start (calendar-gregorian-from-absolute d1))
- (start-month (extract-calendar-month start))
- (start-year (extract-calendar-year start)))
- (increment-calendar-month start-month start-year 1)
- (let* ((end (calendar-gregorian-from-absolute d2))
- (end-month (extract-calendar-month end))
- (end-year (extract-calendar-year end)))
- (if (= (extract-calendar-day end) 1)
- (increment-calendar-month end-month end-year -1))
- (let* ((s (calendar-absolute-from-gregorian
- (list start-month 1 start-year)))
- (e (calendar-absolute-from-gregorian
- (list end-month 1 end-year)))
- (d s)
- (never t)
- (displayed-month start-month)
- (displayed-year start-year))
- (while (or never (<= d e))
- (setq result (append result (calendar-holiday-list)))
- (setq never nil)
- (increment-calendar-month displayed-month displayed-year 3)
- (setq d (calendar-absolute-from-gregorian
- (list displayed-month 1 displayed-year))))))
- (let ((in-range)
- (p result))
- (while p
- (and (car (car p))
- (let ((a (calendar-absolute-from-gregorian (car (car p)))))
- (and (<= d1 a) (<= a d2)))
- (setq in-range (append (list (car p)) in-range)))
- (setq p (cdr p)))
- in-range)))
-
-(defun cal-tex-list-diary-entries (d1 d2)
- "Generate a list of all diary-entries from absolute date D1 to D2."
- (let ((diary-display-hook nil))
- (list-diary-entries
- (calendar-gregorian-from-absolute d1)
- (1+ (- d2 d1)))))
-
-(defun cal-tex-preamble (&optional args)
- "Insert the LaTeX preamble.
-Preamble Includes initial definitions for various LaTeX commands.
-Optional ARGS are included."
- (set-buffer (get-buffer-create cal-tex-buffer))
- (erase-buffer)
- (insert "\\documentstyle")
- (if args
- (insert "[" args "]"))
- (insert "{article}\n"
- "\\hbadness 20000
-\\hfuzz=1000pt
-\\vbadness 20000
-\\marginparwidth 0pt
-\\oddsidemargin -2cm
-\\evensidemargin -2cm
-\\marginparsep 0pt
-\\topmargin 0pt
-\\textwidth 7.5in
-\\textheight 9.5in
-\\newlength{\\cellwidth}
-\\newlength{\\cellheight}
-\\newlength{\\boxwidth}
-\\newlength{\\boxheight}
-\\newlength{\\cellsize}
-\\newcommand{\\myday}[1]{}
-\\newcommand{\\caldate}[6]{}
-\\newcommand{\\nocaldate}[6]{}
-\\newcommand{\\calsmall}[6]{}
-%
-"))
-
-;;;
-;;; Yearly calendars
-;;;
-
-(defun cal-tex-cursor-year (&optional arg)
- "Make a buffer with LaTeX commands for the year cursor is on.
-Optional prefix argument specifies number of years."
- (interactive "P")
- (cal-tex-year (extract-calendar-year (calendar-cursor-to-date t))
- (if arg arg 1)))
-
-(defun cal-tex-cursor-year-landscape (&optional arg)
- "Make a buffer with LaTeX commands for the year cursor is on.
-Optional prefix argument specifies number of years."
- (interactive "P")
- (cal-tex-year (extract-calendar-year (calendar-cursor-to-date t))
- (if arg arg 1)
- t))
-
-(defun cal-tex-year (year n &optional landscape)
- "Make a one page yearly calendar of YEAR; do this for N years.
-There are four rows of three months each, unless optional LANDSCAPE is t,
-in which case the calendar isprinted in landscape mode with three rows of
-four months each."
- (cal-tex-insert-preamble 1 landscape "12pt")
- (if landscape
- (cal-tex-vspace "-.6cm")
- (cal-tex-vspace "-3.1cm"))
- (calendar-for-loop j from 1 to n do
- (insert "\\vfill%\n")
- (cal-tex-b-center)
- (cal-tex-Huge (number-to-string year))
- (cal-tex-e-center)
- (cal-tex-vspace "1cm")
- (cal-tex-b-center)
- (cal-tex-b-parbox "l" (if landscape "5.9in" "4.3in"))
- (insert "\n")
- (cal-tex-noindent)
- (cal-tex-nl)
- (calendar-for-loop i from 1 to 12 do
- (insert (cal-tex-mini-calendar i year "month" "1.1in" "1in"))
- (insert "\\month")
- (cal-tex-hspace "0.5in")
- (if (zerop (mod i (if landscape 4 3)))
- (cal-tex-nl "0.5in")))
- (cal-tex-e-parbox)
- (cal-tex-e-center)
- (insert "\\vfill%\n")
- (setq year (1+ year))
- (if (/= j n)
- (cal-tex-newpage)
- (cal-tex-end-document))
- (run-hooks 'cal-tex-year-hook))
- (run-hooks 'cal-tex-hook))
-
-(defun cal-tex-cursor-filofax-year (&optional arg)
- "Make a Filofax one page yearly calendar of year indicated by cursor.
-Optional parameter specifies number of years."
- (interactive "P")
- (let* ((n (if arg arg 1))
- (year (extract-calendar-year (calendar-cursor-to-date t))))
- (cal-tex-preamble "twoside")
- (cal-tex-cmd "\\textwidth 3.25in")
- (cal-tex-cmd "\\textheight 6.5in")
- (cal-tex-cmd "\\oddsidemargin 1.675in")
- (cal-tex-cmd "\\evensidemargin 1.675in")
- (cal-tex-cmd "\\topmargin 0pt")
- (cal-tex-cmd "\\headheight -0.875in")
- (cal-tex-cmd "\\fboxsep 0.5mm")
- (cal-tex-cmd "\\pagestyle{empty}")
- (cal-tex-b-document)
- (cal-tex-cmd "\\vspace*{0.25in}")
- (calendar-for-loop j from 1 to n do
- (insert (format "\\hfil {\\Large \\bf %s} \\hfil\\\\\n" year))
- (cal-tex-b-center)
- (cal-tex-b-parbox "l" "\\textwidth")
- (insert "\n")
- (cal-tex-noindent)
- (cal-tex-nl)
- (calendar-for-loop i from 1 to 12 do
- (insert (cal-tex-mini-calendar i year
- (calendar-month-name i)
- "1in" ".9in" "tiny" "0.6mm")))
- (insert
-"\\noindent\\fbox{\\January}\\fbox{\\February}\\fbox{\\March}\\\\
-\\noindent\\fbox{\\April}\\fbox{\\May}\\fbox{\\June}\\\\
-\\noindent\\fbox{\\July}\\fbox{\\August}\\fbox{\\September}\\\\
-\\noindent\\fbox{\\October}\\fbox{\\November}\\fbox{\\December}
-")
- (cal-tex-e-parbox)
- (cal-tex-e-center)
- (setq year (1+ year))
- (if (= j n)
- (cal-tex-end-document)
- (cal-tex-newpage)
- (cal-tex-cmd "\\vspace*{0.25in}"))
- (run-hooks 'cal-tex-year-hook))
- (run-hooks 'cal-tex-hook)))
-
-;;;
-;;; Monthly calendars
-;;;
-
-(defun cal-tex-cursor-month-landscape (&optional arg)
- "Make a buffer with LaTeX commands for the month cursor is on.
-Optional prefix argument specifies number of months to be produced.
-The output is in landscape format, one month to a page."
- (interactive "P")
- (let* ((n (if arg arg 1))
- (date (calendar-cursor-to-date t))
- (month (extract-calendar-month date))
- (year (extract-calendar-year date))
- (end-month month)
- (end-year year)
- (cal-tex-which-days '(0 1 2 3 4 5 6)))
- (increment-calendar-month end-month end-year (1- n))
- (let ((diary-list (if cal-tex-diary
- (cal-tex-list-diary-entries
- (calendar-absolute-from-gregorian
- (list month 1 year))
- (calendar-absolute-from-gregorian
- (list end-month
- (calendar-last-day-of-month
- end-month end-year)
- end-year)))))
- (holidays (if cal-tex-holidays
- (cal-tex-list-holidays
- (calendar-absolute-from-gregorian
- (list month 1 year))
- (calendar-absolute-from-gregorian
- (list end-month
- (calendar-last-day-of-month end-month end-year)
- end-year)))))
- (other-month)
- (other-year)
- (small-months-at-start))
- (cal-tex-insert-preamble (cal-tex-number-weeks month year 1) t "12pt")
- (cal-tex-cmd cal-tex-cal-one-month)
- (calendar-for-loop i from 1 to n do
- (setq other-month month)
- (setq other-year year)
- (increment-calendar-month other-month other-year -1)
- (insert (cal-tex-mini-calendar other-month other-year "lastmonth"
- "\\cellwidth" "\\cellheight"))
- (increment-calendar-month other-month other-year 2)
- (insert (cal-tex-mini-calendar other-month other-year "nextmonth"
- "\\cellwidth" "\\cellheight"))
- (cal-tex-insert-month-header 1 month year month year)
- (cal-tex-insert-day-names)
- (cal-tex-nl ".2cm")
- (setq small-months-at-start
- (< 1 (mod (- (calendar-day-of-week (list month 1 year))
- calendar-week-start-day)
- 7)))
- (if small-months-at-start
- (insert "\\lastmonth\\nextmonth\\hspace*{-2\\cellwidth}"))
- (cal-tex-insert-blank-days month year cal-tex-day-prefix)
- (cal-tex-insert-days month year diary-list holidays
- cal-tex-day-prefix)
- (cal-tex-insert-blank-days-at-end month year cal-tex-day-prefix)
- (if (and (not small-months-at-start)
- (< 1 (mod (- (1- calendar-week-start-day)
- (calendar-day-of-week
- (list month
- (calendar-last-day-of-month month year)
- year)))
- 7)))
- (insert "\\vspace*{-\\cellwidth}\\hspace*{-2\\cellwidth}"
- "\\lastmonth\\nextmonth"))
- (if (/= i n)
- (progn
- (run-hooks 'cal-tex-month-hook)
- (cal-tex-newpage)
- (increment-calendar-month month year 1)
- (cal-tex-vspace "-2cm")
- (cal-tex-insert-preamble
- (cal-tex-number-weeks month year 1) t "12pt" t))))
- (cal-tex-end-document)
- (run-hooks 'cal-tex-hook))))
-
-(defun cal-tex-cursor-month (arg)
- "Make a buffer with LaTeX commands for the month cursor is on.
-Optional prefix argument specifies number of months to be produced.
-Calendar is condensed onto one page."
- (interactive "P")
- (let* ((date (calendar-cursor-to-date t))
- (month (extract-calendar-month date))
- (year (extract-calendar-year date))
- (end-month month)
- (end-year year)
- (n (if arg arg 1)))
- (increment-calendar-month end-month end-year (1- n))
- (let ((diary-list (if cal-tex-diary
- (cal-tex-list-diary-entries
- (calendar-absolute-from-gregorian
- (list month 1 year))
- (calendar-absolute-from-gregorian
- (list end-month
- (calendar-last-day-of-month
- end-month end-year)
- end-year)))))
- (holidays (if cal-tex-holidays
- (cal-tex-list-holidays
- (calendar-absolute-from-gregorian
- (list month 1 year))
- (calendar-absolute-from-gregorian
- (list end-month
- (calendar-last-day-of-month end-month end-year)
- end-year)))))
- (other-month)
- (other-year))
- (cal-tex-insert-preamble (cal-tex-number-weeks month year n) nil"12pt")
- (if (> n 1)
- (cal-tex-cmd cal-tex-cal-multi-month)
- (cal-tex-cmd cal-tex-cal-one-month))
- (cal-tex-insert-month-header n month year end-month end-year)
- (cal-tex-insert-day-names)
- (cal-tex-nl ".2cm")
- (cal-tex-insert-blank-days month year cal-tex-day-prefix)
- (calendar-for-loop i from 1 to n do
- (setq other-month month)
- (setq other-year year)
- (cal-tex-insert-days month year diary-list holidays
- cal-tex-day-prefix)
- (increment-calendar-month month year 1))
- (cal-tex-insert-blank-days-at-end end-month end-year cal-tex-day-prefix)
- (cal-tex-end-document)))
- (run-hooks 'cal-tex-hook))
-
-(defun cal-tex-insert-days (month year diary-list holidays day-format)
- "Insert LaTeX commands for a range of days in monthly calendars.
-LaTeX commands are inserted for the days of the MONTH in YEAR.
-Diary entries on DIARY-LIST are included. Holidays on HOLIDAYS are included.
-Each day is formatted using format DAY-FORMAT."
- (let* ((blank-days;; at start of month
- (mod
- (- (calendar-day-of-week (list month 1 year))
- calendar-week-start-day)
- 7))
- (date)
- (last (calendar-last-day-of-month month year)))
- (calendar-for-loop i from 1 to last do
- (setq date (list month i year))
- (if (memq (calendar-day-of-week date) cal-tex-which-days)
- (progn
- (insert (format day-format (calendar-month-name month) i))
- (cal-tex-arg (cal-tex-latexify-list diary-list date))
- (cal-tex-arg (cal-tex-latexify-list holidays date))
- (cal-tex-arg (eval cal-tex-daily-string))
- (cal-tex-arg)
- (cal-tex-comment)))
- (if (and (zerop (mod (+ i blank-days) 7))
- (/= i last))
- (progn
- (cal-tex-hfill)
- (cal-tex-nl))))))
-
-(defun cal-tex-insert-day-names ()
- "Insert the names of the days at top of a monthly calendar."
- (calendar-for-loop i from 0 to 6 do
- (if (memq i cal-tex-which-days)
- (insert (format cal-tex-day-name-format
- (aref calendar-day-name-array
- (mod (+ calendar-week-start-day i) 7)))))
- (cal-tex-comment)))
-
-(defun cal-tex-insert-month-header (n month year end-month end-year)
- "Create a title for a calendar.
-A title is inserted for a calendar with N months starting with
-MONTH YEAR and ending with END-MONTH END-YEAR."
- (let ( (month-name (calendar-month-name month))
- (end-month-name (calendar-month-name end-month)))
- (if (= 1 n)
- (insert (format "\\calmonth{%s}{%s}\n\\vspace*{-0.5cm}"
- month-name year) )
- (insert (format "\\calmonth{%s}{%s}{%s}{%s}\n\\vspace*{-0.5cm}"
- month-name year end-month-name end-year))))
- (cal-tex-comment))
-
-(defun cal-tex-insert-blank-days (month year day-format)
- "Insert code for initial days not in calendar.
-Insert LaTeX code for the blank days at the beginning of the MONTH in
-YEAR. The entry is formatted using DAY-FORMAT. If the entire week is
-blank, no days are inserted."
- (if (cal-tex-first-blank-p month year)
- (let* ((blank-days;; at start of month
- (mod
- (- (calendar-day-of-week (list month 1 year))
- calendar-week-start-day)
- 7)))
- (calendar-for-loop i from 0 to (1- blank-days) do
- (if (memq i cal-tex-which-days)
- (insert (format day-format " " " ") "{}{}{}{}%\n"))))))
-
-(defun cal-tex-insert-blank-days-at-end (month year day-format)
- "Insert code for final days not in calendar.
-Insert LaTeX code for the blank days at the end of the MONTH in YEAR.
-The entry is formatted using DAY-FORMAT."
- (if (cal-tex-last-blank-p month year)
- (let* ((last-day (calendar-last-day-of-month month year))
- (blank-days;; at end of month
- (mod
- (- (calendar-day-of-week (list month last-day year))
- calendar-week-start-day)
- 7)))
- (calendar-for-loop i from (1+ blank-days) to 6 do
- (if (memq i cal-tex-which-days)
- (insert (format day-format "" "") "{}{}{}{}%\n"))))))
-
-(defun cal-tex-first-blank-p (month year)
- "Determine if any days of the first week will be printed.
-Return t if there will there be any days of the first week printed
-in the calendar starting in MONTH YEAR."
- (let ((any-days nil)
- (the-saturday)) ;the day of week of 1st Saturday
- (calendar-for-loop i from 1 to 7 do
- (if (= 6 (calendar-day-of-week (list month i year)))
- (setq the-saturday i)))
- (calendar-for-loop i from 1 to the-saturday do
- (if (memq (calendar-day-of-week (list month i year))
- cal-tex-which-days)
- (setq any-days t)))
- any-days))
-
-(defun cal-tex-last-blank-p (month year)
- "Determine if any days of the last week will be printed.
-Return t if there will there be any days of the last week printed
-in the calendar starting in MONTH YEAR."
- (let ((any-days nil)
- (last-day (calendar-last-day-of-month month year))
- (the-sunday)) ;the day of week of last Sunday
- (calendar-for-loop i from (- last-day 6) to last-day do
- (if (= 0 (calendar-day-of-week (list month i year)))
- (setq the-sunday i)))
- (calendar-for-loop i from the-sunday to last-day do
- (if (memq (calendar-day-of-week (list month i year))
- cal-tex-which-days)
- (setq any-days t)))
- any-days))
-
-(defun cal-tex-number-weeks (month year n)
- "Determine the number of weeks in a range of dates.
-Compute the number of weeks in the calendar starting with MONTH and YEAR,
-and lasting N months, including only the days in WHICH-DAYS. As it stands,
-this is only an upper bound."
- (let ((d (list month 1 year)))
- (increment-calendar-month month year (1- n))
- (/ (- (calendar-dayname-on-or-before
- calendar-week-start-day
- (+ 7 (calendar-absolute-from-gregorian
- (list month (calendar-last-day-of-month month year) year))))
- (calendar-dayname-on-or-before
- calendar-week-start-day
- (calendar-absolute-from-gregorian d)))
- 7)))
-
-;;;
-;;; Weekly calendars
-;;;
-
-(defun cal-tex-cursor-week (&optional arg)
- "Make a buffer with LaTeX commands for a two-page one-week calendar.
-It applies to the week that point is in.
-Optional prefix argument specifies number of weeks.
-Holidays are included if `cal-tex-holidays' is t."
- (interactive "P")
- (let* ((n (if arg arg 1))
- (date (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before
- calendar-week-start-day
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))))
- (month (extract-calendar-month date))
- (year (extract-calendar-year date))
- (holidays (if cal-tex-holidays
- (cal-tex-list-holidays
- (calendar-absolute-from-gregorian date)
- (+ (* 7 n)
- (calendar-absolute-from-gregorian date))))))
- (cal-tex-preamble "11pt")
- (cal-tex-cmd "\\textwidth 6.5in")
- (cal-tex-cmd "\\textheight 10.5in")
- (cal-tex-cmd "\\oddsidemargin 0in")
- (cal-tex-cmd "\\evensidemargin 0in")
- (insert cal-tex-LaTeX-hourbox)
- (cal-tex-b-document)
- (cal-tex-cmd "\\pagestyle{empty}")
- (calendar-for-loop i from 1 to n do
- (cal-tex-vspace "-1.5in")
- (cal-tex-b-center)
- (cal-tex-Huge-bf (format "\\uppercase{%s}"
- (calendar-month-name month)))
- (cal-tex-hspace "2em")
- (cal-tex-Huge-bf (number-to-string year))
- (cal-tex-nl ".5cm")
- (cal-tex-e-center)
- (cal-tex-hspace "-.2in")
- (cal-tex-b-parbox "l" "7in")
- (calendar-for-loop j from 1 to 7 do
- (cal-tex-week-hours date holidays "3.1")
- (setq date (cal-tex-incr-date date)))
- (cal-tex-e-parbox)
- (setq month (extract-calendar-month date))
- (setq year (extract-calendar-year date))
- (if (/= i n)
- (progn
- (run-hooks 'cal-tex-week-hook)
- (cal-tex-newpage))))
- (cal-tex-end-document)
- (run-hooks 'cal-tex-hook)))
-
-(defun cal-tex-cursor-week2 (&optional arg)
- "Make a buffer with LaTeX commands for a two-page one-week calendar.
-It applies to the week that point is in.
-Optional prefix argument specifies number of weeks.
-Holidays are included if `cal-tex-holidays' is t."
- (interactive "P")
- (let* ((n (if arg arg 1))
- (date (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before
- calendar-week-start-day
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))))
- (month (extract-calendar-month date))
- (year (extract-calendar-year date))
- (d date)
- (holidays (if cal-tex-holidays
- (cal-tex-list-holidays
- (calendar-absolute-from-gregorian date)
- (+ (* 7 n)
- (calendar-absolute-from-gregorian date))))))
- (cal-tex-preamble "12pt")
- (cal-tex-cmd "\\textwidth 6.5in")
- (cal-tex-cmd "\\textheight 10.5in")
- (cal-tex-cmd "\\oddsidemargin 0in")
- (cal-tex-cmd "\\evensidemargin 0in")
- (insert cal-tex-LaTeX-hourbox)
- (cal-tex-b-document)
- (cal-tex-cmd "\\pagestyle{empty}")
- (calendar-for-loop i from 1 to n do
- (cal-tex-vspace "-1.5in")
- (cal-tex-b-center)
- (cal-tex-Huge-bf (format "\\uppercase{%s}"
- (calendar-month-name month)))
- (cal-tex-hspace "2em")
- (cal-tex-Huge-bf (number-to-string year))
- (cal-tex-nl ".5cm")
- (cal-tex-e-center)
- (cal-tex-hspace "-.2in")
- (cal-tex-b-parbox "l" "\\textwidth")
- (calendar-for-loop j from 1 to 3 do
- (cal-tex-week-hours date holidays "5")
- (setq date (cal-tex-incr-date date)))
- (cal-tex-e-parbox)
- (cal-tex-nl)
- (insert (cal-tex-mini-calendar
- (extract-calendar-month (cal-tex-previous-month date))
- (extract-calendar-year (cal-tex-previous-month date))
- "lastmonth" "1.1in" "1in"))
- (insert (cal-tex-mini-calendar
- (extract-calendar-month date)
- (extract-calendar-year date)
- "thismonth" "1.1in" "1in"))
- (insert (cal-tex-mini-calendar
- (extract-calendar-month (cal-tex-next-month date))
- (extract-calendar-year (cal-tex-next-month date))
- "nextmonth" "1.1in" "1in"))
- (insert "\\hbox to \\textwidth{")
- (cal-tex-hfill)
- (insert "\\lastmonth")
- (cal-tex-hfill)
- (insert "\\thismonth")
- (cal-tex-hfill)
- (insert "\\nextmonth")
- (cal-tex-hfill)
- (insert "}")
- (cal-tex-nl)
- (cal-tex-b-parbox "l" "\\textwidth")
- (calendar-for-loop j from 4 to 7 do
- (cal-tex-week-hours date holidays "5")
- (setq date (cal-tex-incr-date date)))
- (cal-tex-e-parbox)
- (setq month (extract-calendar-month date))
- (setq year (extract-calendar-year date))
- (if (/= i n)
- (progn
- (run-hooks 'cal-tex-week-hook)
- (cal-tex-newpage))))
- (cal-tex-end-document)
- (run-hooks 'cal-tex-hook)))
-
-(defun cal-tex-cursor-week-iso (&optional arg)
- "Make a buffer with LaTeX commands for a one page ISO-style weekly calendar.
-Optional prefix argument specifies number of weeks.
-Diary entries are included if `cal-tex-diary' is t.
-Holidays are included if `cal-tex-holidays' is t."
- (interactive "P")
- (let* ((n (if arg arg 1))
- (date (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before
- 1
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))))
- (month (extract-calendar-month date))
- (year (extract-calendar-year date))
- (day (extract-calendar-day date))
- (holidays (if cal-tex-holidays
- (cal-tex-list-holidays
- (calendar-absolute-from-gregorian date)
- (+ (* 7 n)
- (calendar-absolute-from-gregorian date)))))
- (diary-list (if cal-tex-diary
- (cal-tex-list-diary-entries
- (calendar-absolute-from-gregorian
- (list month 1 year))
- (+ (* 7 n)
- (calendar-absolute-from-gregorian date))))))
- (cal-tex-preamble "11pt")
- (cal-tex-cmd "\\textwidth 6.5in")
- (cal-tex-cmd "\\textheight 10.5in")
- (cal-tex-cmd "\\oddsidemargin 0in")
- (cal-tex-cmd "\\evensidemargin 0in")
- (cal-tex-b-document)
- (cal-tex-cmd "\\pagestyle{empty}")
- (calendar-for-loop i from 1 to n do
- (cal-tex-vspace "-1.5in")
- (cal-tex-b-center)
- (cal-tex-Huge-bf
- (let* ((d (calendar-iso-from-absolute
- (calendar-absolute-from-gregorian date))))
- (format "Week %d of %d"
- (extract-calendar-month d)
- (extract-calendar-year d))))
- (cal-tex-nl ".5cm")
- (cal-tex-e-center)
- (cal-tex-b-parbox "l" "\\textwidth")
- (calendar-for-loop j from 1 to 7 do
- (cal-tex-b-parbox "t" "\\textwidth")
- (cal-tex-b-parbox "t" "\\textwidth")
- (cal-tex-rule "0pt" "\\textwidth" ".2mm")
- (cal-tex-nl)
- (cal-tex-b-parbox "t" "\\textwidth")
- (cal-tex-large-bf (calendar-day-name date))
- (insert ", ")
- (cal-tex-large-bf (calendar-month-name month))
- (insert " ")
- (cal-tex-large-bf (number-to-string day))
- (if (not (string= "" (cal-tex-latexify-list holidays date)))
- (progn
- (insert ": ")
- (cal-tex-large-bf (cal-tex-latexify-list holidays date "; "))))
- (cal-tex-hfill)
- (insert " " (eval cal-tex-daily-string))
- (cal-tex-e-parbox)
- (cal-tex-nl)
- (cal-tex-noindent)
- (cal-tex-b-parbox "t" "\\textwidth")
- (if (not (string= "" (cal-tex-latexify-list diary-list date)))
- (progn
- (insert "\\vbox to 0pt{")
- (cal-tex-large-bf
- (cal-tex-latexify-list diary-list date))
- (insert "}")))
- (cal-tex-e-parbox)
- (cal-tex-nl)
- (setq date (cal-tex-incr-date date))
- (setq month (extract-calendar-month date))
- (setq day (extract-calendar-day date))
- (cal-tex-e-parbox)
- (cal-tex-e-parbox "2cm")
- (cal-tex-nl)
- (setq month (extract-calendar-month date))
- (setq year (extract-calendar-year date)))
- (cal-tex-e-parbox)%
- (if (/= i n)
- (progn
- (run-hooks 'cal-tex-week-hook)
- (cal-tex-newpage))))
- (cal-tex-end-document)
- (run-hooks 'cal-tex-hook)))
-
-(defvar cal-tex-LaTeX-hourbox
- "\\newcommand{\\hourbox}[2]%
-{\\makebox[2em]{\\rule{0cm}{#2ex}#1}\\rule{3in}{.15mm}}\n"
- "One hour and a line on the right.")
-
-(defun cal-tex-week-hours (date holidays height)
- "Insert hourly entries for DATE with HOLIDAYS, with line height HEIGHT."
- (let ((month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date))
- (afternoon))
- (cal-tex-comment "begin cal-tex-week-hours")
- (cal-tex-cmd "\\ \\\\[-.2cm]")
- (cal-tex-cmd "\\noindent")
- (cal-tex-b-parbox "l" "6.8in")
- (cal-tex-large-bf (calendar-day-name date))
- (insert ", ")
- (cal-tex-large-bf (calendar-month-name month))
- (insert " ")
- (cal-tex-large-bf (number-to-string day))
- (if (not (string= "" (cal-tex-latexify-list holidays date)))
- (progn
- (insert ": ")
- (cal-tex-large-bf (cal-tex-latexify-list holidays date "; "))))
- (cal-tex-hfill)
- (insert " " (eval cal-tex-daily-string))
- (cal-tex-e-parbox)
- (cal-tex-nl "-.3cm")
- (cal-tex-rule "0pt" "6.8in" ".2mm")
- (cal-tex-nl "-.1cm")
- (calendar-for-loop i from 8 to 12 do
- (if cal-tex-24
- (setq afternoon (+ i 5))
- (setq afternoon (- i 7)))
- (cal-tex-cmd "\\hourbox" (number-to-string i))
- (cal-tex-arg height)
- (cal-tex-hspace ".4cm")
- (cal-tex-cmd "\\hourbox" (number-to-string afternoon))
- (cal-tex-arg height)
- (cal-tex-nl))))
-
-(defun cal-tex-cursor-week-monday (&optional arg)
- "Make a buffer with LaTeX commands for a two-page one-week calendar.
-It applies to the week that point is in, and starts on Monday.
-Optional prefix argument specifies number of weeks.
-Holidays are included if `cal-tex-holidays' is t."
- (interactive "P")
- (let* ((n (if arg arg 1))
- (date (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before
- 0
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t))))))
- (cal-tex-preamble "11pt")
- (cal-tex-cmd "\\textwidth 6.5in")
- (cal-tex-cmd "\\textheight 10.5in")
- (cal-tex-cmd "\\oddsidemargin 0in")
- (cal-tex-cmd "\\evensidemargin 0in")
- (cal-tex-b-document)
- (calendar-for-loop i from 1 to n do
- (cal-tex-vspace "-1cm")
- (insert "\\noindent ")
- (cal-tex-weekly4-box (cal-tex-incr-date date) nil)
- (cal-tex-weekly4-box (cal-tex-incr-date date 4) nil)
- (cal-tex-nl ".2cm")
- (cal-tex-weekly4-box (cal-tex-incr-date date 2) nil)
- (cal-tex-weekly4-box (cal-tex-incr-date date 5) nil)
- (cal-tex-nl ".2cm")
- (cal-tex-weekly4-box (cal-tex-incr-date date 3) nil)
- (cal-tex-weekly4-box (cal-tex-incr-date date 6) t)
- (if (/= i n)
- (progn
- (run-hooks 'cal-tex-week-hook)
- (setq date (cal-tex-incr-date date 7))
- (cal-tex-newpage))))
- (cal-tex-end-document)
- (run-hooks 'cal-tex-hook)))
-
-(defun cal-tex-weekly4-box (date weekend)
- "Make one box for DATE, different if WEEKEND."
- (let* (
- (day (extract-calendar-day date))
- (month (extract-calendar-month date))
- (year (extract-calendar-year date))
- (dayname (calendar-day-name date))
- (date1 (cal-tex-incr-date date))
- (day1 (extract-calendar-day date1))
- (month1 (extract-calendar-month date1))
- (year1 (extract-calendar-year date1))
- (dayname1 (calendar-day-name date1))
- )
- (cal-tex-b-framebox "8cm" "l")
- (cal-tex-b-parbox "b" "7.5cm")
- (insert (format "{\\Large\\bf %s,} %s/%s/%s\\\\\n" dayname month day year))
- (cal-tex-rule "0pt" "7.5cm" ".5mm")
- (cal-tex-nl)
- (if (not weekend)
- (progn
- (calendar-for-loop i from 8 to 12 do
- (insert (format "{\\large\\sf %d}\\\\\n" i)))
- (calendar-for-loop i from 1 to 5 do
- (insert (format "{\\large\\sf %d}\\\\\n" i)))))
- (cal-tex-nl ".5cm")
- (if weekend
- (progn
- (cal-tex-vspace "1cm")
- (insert "\\ \\vfill")
- (insert (format "{\\Large\\bf %s,} %s/%s/%s\\\\\n"
- dayname1 month1 day1 year1))
- (cal-tex-rule "0pt" "7.5cm" ".5mm")
- (cal-tex-nl "1.5cm")
- (cal-tex-vspace "1cm")))
- (cal-tex-e-parbox)
- (cal-tex-e-framebox)
- (cal-tex-hspace "1cm")))
-
-(defun cal-tex-cursor-filofax-2week (&optional arg)
- "Two-weeks-at-a-glance Filofax style calendar for week indicated by cursor.
-Optional prefix argument specifies number of weeks.
-Diary entries are included if `cal-tex-diary' is t.
-Holidays are included if `cal-tex-holidays' is t."
- (interactive "P")
- (let* ((n (if arg arg 1))
- (date (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before
- calendar-week-start-day
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))))
- (month (extract-calendar-month date))
- (year (extract-calendar-year date))
- (day (extract-calendar-day date))
- (holidays (if cal-tex-holidays
- (cal-tex-list-holidays
- (calendar-absolute-from-gregorian date)
- (+ (* 7 n)
- (calendar-absolute-from-gregorian date)))))
- (diary-list (if cal-tex-diary
- (cal-tex-list-diary-entries
- (calendar-absolute-from-gregorian
- (list month 1 year))
- (+ (* 7 n)
- (calendar-absolute-from-gregorian date))))))
- (cal-tex-preamble "twoside")
- (cal-tex-cmd "\\textwidth 3.25in")
- (cal-tex-cmd "\\textheight 6.5in")
- (cal-tex-cmd "\\oddsidemargin 1.75in")
- (cal-tex-cmd "\\evensidemargin 1.5in")
- (cal-tex-cmd "\\topmargin 0pt")
- (cal-tex-cmd "\\headheight -0.875in")
- (cal-tex-cmd "\\headsep 0.125in")
- (cal-tex-cmd "\\footskip .125in")
- (insert "\\def\\righthead#1{\\hfill {\\normalsize \\bf #1}\\\\[-6pt]}
-\\long\\def\\rightday#1#2#3#4#5{%
- \\rule{\\textwidth}{0.3pt}\\\\%
- \\hbox to \\textwidth{%
- \\vbox to 0.7in{%
- \\vspace*{2pt}%
- \\hbox to \\textwidth{\\small #5 \\hfill #1 {\\normalsize \\bf #2}}%
- \\hbox to \\textwidth{\\vbox {\\raggedleft \\footnotesize \\em #4}}%
- \\hbox to \\textwidth{\\vbox to 0pt {\\noindent \\footnotesize #3}}}}\\\\}
-\\def\\lefthead#1{\\noindent {\\normalsize \\bf #1}\\hfill\\\\[-6pt]}
-\\long\\def\\leftday#1#2#3#4#5{%
- \\rule{\\textwidth}{0.3pt}\\\\%
- \\hbox to \\textwidth{%
- \\vbox to 0.7in{%
- \\vspace*{2pt}%
- \\hbox to \\textwidth{\\noindent {\\normalsize \\bf #2} \\small #1 \\hfill #5}%
- \\hbox to \\textwidth{\\vbox {\\noindent \\footnotesize \\em #4}}%
- \\hbox to \\textwidth{\\vbox to 0pt {\\noindent \\footnotesize #3}}}}\\\\}
-")
- (cal-tex-b-document)
- (cal-tex-cmd "\\pagestyle{empty}")
- (calendar-for-loop i from 1 to n do
- (if (= (mod i 2) 1)
- (insert "\\righthead")
- (insert "\\lefthead"))
- (cal-tex-arg
- (let ((d (cal-tex-incr-date date 6)))
- (if (= (extract-calendar-month date)
- (extract-calendar-month d))
- (format "%s %s"
- (calendar-month-name
- (extract-calendar-month date))
- (extract-calendar-year date))
- (if (= (extract-calendar-year date)
- (extract-calendar-year d))
- (format "%s---%s %s"
- (calendar-month-name
- (extract-calendar-month date))
- (calendar-month-name
- (extract-calendar-month d))
- (extract-calendar-year date))
- (format "%s %s---%s %s"
- (calendar-month-name
- (extract-calendar-month date))
- (extract-calendar-year date)
- (calendar-month-name (extract-calendar-month d))
- (extract-calendar-year d))))))
- (insert "%\n")
- (calendar-for-loop j from 1 to 7 do
- (if (= (mod i 2) 1)
- (insert "\\rightday")
- (insert "\\leftday"))
- (cal-tex-arg (calendar-day-name date))
- (cal-tex-arg (int-to-string (extract-calendar-day date)))
- (cal-tex-arg (cal-tex-latexify-list diary-list date))
- (cal-tex-arg (cal-tex-latexify-list holidays date))
- (cal-tex-arg (eval cal-tex-daily-string))
- (insert "%\n")
- (setq date (cal-tex-incr-date date)))
- (if (/= i n)
- (progn
- (run-hooks 'cal-tex-week-hook)
- (cal-tex-newpage))))
- (cal-tex-end-document)
- (run-hooks 'cal-tex-hook)))
-
-(defun cal-tex-cursor-filofax-week (&optional arg)
- "One-week-at-a-glance Filofax style calendar for week indicated by cursor.
-Optional prefix argument specifies number of weeks.
-Weeks start on Monday.
-Diary entries are included if `cal-tex-diary' is t.
-Holidays are included if `cal-tex-holidays' is t."
- (interactive "P")
- (let* ((n (if arg arg 1))
- (date (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before
- 1
- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t)))))
- (month (extract-calendar-month date))
- (year (extract-calendar-year date))
- (day (extract-calendar-day date))
- (holidays (if cal-tex-holidays
- (cal-tex-list-holidays
- (calendar-absolute-from-gregorian date)
- (+ (* 7 n)
- (calendar-absolute-from-gregorian date)))))
- (diary-list (if cal-tex-diary
- (cal-tex-list-diary-entries
- (calendar-absolute-from-gregorian
- (list month 1 year))
- (+ (* 7 n)
- (calendar-absolute-from-gregorian date))))))
- (cal-tex-preamble "twoside")
- (cal-tex-cmd "\\textwidth 3.25in")
- (cal-tex-cmd "\\textheight 6.5in")
- (cal-tex-cmd "\\oddsidemargin 1.75in")
- (cal-tex-cmd "\\evensidemargin 1.5in")
- (cal-tex-cmd "\\topmargin 0pt")
- (cal-tex-cmd "\\headheight -0.875in")
- (cal-tex-cmd "\\headsep 0.125in")
- (cal-tex-cmd "\\footskip .125in")
- (insert "\\def\\righthead#1{\\hfill {\\normalsize \\bf #1}\\\\[-6pt]}
-\\long\\def\\rightday#1#2#3#4#5{%
- \\rule{\\textwidth}{0.3pt}\\\\%
- \\hbox to \\textwidth{%
- \\vbox to 1.85in{%
- \\vspace*{2pt}%
- \\hbox to \\textwidth{\\small #5 \\hfill #1 {\\normalsize \\bf #2}}%
- \\hbox to \\textwidth{\\vbox {\\raggedleft \\footnotesize \\em #4}}%
- \\hbox to \\textwidth{\\vbox to 0pt {\\noindent \\footnotesize #3}}}}\\\\}
-\\long\\def\\weekend#1#2#3#4#5{%
- \\rule{\\textwidth}{0.3pt}\\\\%
- \\hbox to \\textwidth{%
- \\vbox to .8in{%
- \\vspace*{2pt}%
- \\hbox to \\textwidth{\\small #5 \\hfill #1 {\\normalsize \\bf #2}}%
- \\hbox to \\textwidth{\\vbox {\\raggedleft \\footnotesize \\em #4}}%
- \\hbox to \\textwidth{\\vbox to 0pt {\\noindent \\footnotesize #3}}}}\\\\}
-\\def\\lefthead#1{\\noindent {\\normalsize \\bf #1}\\hfill\\\\[-6pt]}
-\\long\\def\\leftday#1#2#3#4#5{%
- \\rule{\\textwidth}{0.3pt}\\\\%
- \\hbox to \\textwidth{%
- \\vbox to 1.85in{%
- \\vspace*{2pt}%
- \\hbox to \\textwidth{\\noindent {\\normalsize \\bf #2} \\small #1 \\hfill #5}%
- \\hbox to \\textwidth{\\vbox {\\noindent \\footnotesize \\em #4}}%
- \\hbox to \\textwidth{\\vbox to 0pt {\\noindent \\footnotesize #3}}}}\\\\}
-")
- (cal-tex-b-document)
- (cal-tex-cmd "\\pagestyle{empty}\\ ")
- (cal-tex-newpage)
- (calendar-for-loop i from 1 to n do
- (insert "\\lefthead")
- (cal-tex-arg
- (let ((d (cal-tex-incr-date date 2)))
- (if (= (extract-calendar-month date)
- (extract-calendar-month d))
- (format "%s %s"
- (calendar-month-name
- (extract-calendar-month date))
- (extract-calendar-year date))
- (if (= (extract-calendar-year date)
- (extract-calendar-year d))
- (format "%s---%s %s"
- (calendar-month-name
- (extract-calendar-month date))
- (calendar-month-name
- (extract-calendar-month d))
- (extract-calendar-year date))
- (format "%s %s---%s %s"
- (calendar-month-name
- (extract-calendar-month date))
- (extract-calendar-year date)
- (calendar-month-name (extract-calendar-month d))
- (extract-calendar-year d))))))
- (insert "%\n")
- (calendar-for-loop j from 1 to 3 do
- (insert "\\leftday")
- (cal-tex-arg (calendar-day-name date))
- (cal-tex-arg (int-to-string (extract-calendar-day date)))
- (cal-tex-arg (cal-tex-latexify-list diary-list date))
- (cal-tex-arg (cal-tex-latexify-list holidays date))
- (cal-tex-arg (eval cal-tex-daily-string))
- (insert "%\n")
- (setq date (cal-tex-incr-date date)))
- (insert "\\noindent\\rule{\\textwidth}{0.3pt}\\\\%\n")
- (cal-tex-newpage)
- (insert "\\righthead")
- (cal-tex-arg
- (let ((d (cal-tex-incr-date date 3)))
- (if (= (extract-calendar-month date)
- (extract-calendar-month d))
- (format "%s %s"
- (calendar-month-name
- (extract-calendar-month date))
- (extract-calendar-year date))
- (if (= (extract-calendar-year date)
- (extract-calendar-year d))
- (format "%s---%s %s"
- (calendar-month-name
- (extract-calendar-month date))
- (calendar-month-name
- (extract-calendar-month d))
- (extract-calendar-year date))
- (format "%s %s---%s %s"
- (calendar-month-name
- (extract-calendar-month date))
- (extract-calendar-year date)
- (calendar-month-name (extract-calendar-month d))
- (extract-calendar-year d))))))
- (insert "%\n")
- (calendar-for-loop j from 1 to 2 do
- (insert "\\rightday")
- (cal-tex-arg (calendar-day-name date))
- (cal-tex-arg (int-to-string (extract-calendar-day date)))
- (cal-tex-arg (cal-tex-latexify-list diary-list date))
- (cal-tex-arg (cal-tex-latexify-list holidays date))
- (cal-tex-arg (eval cal-tex-daily-string))
- (insert "%\n")
- (setq date (cal-tex-incr-date date)))
- (calendar-for-loop j from 1 to 2 do
- (insert "\\weekend")
- (cal-tex-arg (calendar-day-name date))
- (cal-tex-arg (int-to-string (extract-calendar-day date)))
- (cal-tex-arg (cal-tex-latexify-list diary-list date))
- (cal-tex-arg (cal-tex-latexify-list holidays date))
- (cal-tex-arg (eval cal-tex-daily-string))
- (insert "%\n")
- (setq date (cal-tex-incr-date date)))
- (if (/= i n)
- (progn
- (run-hooks 'cal-tex-week-hook)
- (cal-tex-newpage))))
- (cal-tex-end-document)
- (run-hooks 'cal-tex-hook)))
-;;;
-;;; Daily calendars
-;;;
-
-(defun cal-tex-cursor-day (&optional arg)
- "Make a buffer with LaTeX commands for the day cursor is on.
-Optional prefix argument specifies number of days."
- (interactive "P")
- (let ((n (if arg arg 1))
- (date (calendar-absolute-from-gregorian (calendar-cursor-to-date t))))
- (cal-tex-preamble "12pt")
- (cal-tex-cmd "\\textwidth 6.5in")
- (cal-tex-cmd "\\textheight 10.5in")
- (cal-tex-b-document)
- (cal-tex-cmd "\\pagestyle{empty}")
- (calendar-for-loop i from 1 to n do
- (cal-tex-vspace "-1.7in")
- (cal-tex-daily-page (calendar-gregorian-from-absolute date))
- (setq date (1+ date))
- (if (/= i n)
- (progn
- (cal-tex-newpage)
- (run-hooks 'cal-tex-daily-hook))))
- (cal-tex-end-document)
- (run-hooks 'cal-tex-hook)))
-
-(defun cal-tex-daily-page (date)
- "Make a calendar page for Gregorian DATE on 8.5 by 11 paper."
- (let* ((hour)
- (month-name (calendar-month-name (extract-calendar-month date))))
- (cal-tex-banner "cal-tex-daily-page")
- (cal-tex-b-makebox "4cm" "l")
- (cal-tex-b-parbox "b" "3.8cm")
- (cal-tex-rule "0mm" "0mm" "2cm")
- (cal-tex-Huge (number-to-string (extract-calendar-day date)))
- (cal-tex-nl ".5cm")
- (cal-tex-bf month-name )
- (cal-tex-e-parbox)
- (cal-tex-hspace "1cm")
- (cal-tex-scriptsize (eval cal-tex-daily-string))
- (cal-tex-hspace "3.5cm")
- (cal-tex-e-makebox)
- (cal-tex-hfill)
- (cal-tex-b-makebox "4cm" "r")
- (cal-tex-bf (calendar-day-name date))
- (cal-tex-e-makebox)
- (cal-tex-nl)
- (cal-tex-hspace ".4cm")
- (cal-tex-rule "0mm" "16.1cm" "1mm")
- (cal-tex-nl ".1cm")
- (calendar-for-loop i from cal-tex-daily-start to cal-tex-daily-end do
- (cal-tex-cmd "\\noindent")
- (setq hour (if cal-tex-24
- i
- (mod i 12)))
- (if (= 0 hour) (setq hour 12))
- (cal-tex-b-makebox "1cm" "c")
- (cal-tex-arg (number-to-string hour))
- (cal-tex-e-makebox)
- (cal-tex-rule "0mm" "15.5cm" ".2mm")
- (cal-tex-nl ".2cm")
- (cal-tex-b-makebox "1cm" "c")
- (cal-tex-arg "$\\diamond$" )
- (cal-tex-e-makebox)
- (cal-tex-rule "0mm" "15.5cm" ".2mm")
- (cal-tex-nl ".2cm"))
- (cal-tex-hfill)
- (insert (cal-tex-mini-calendar
- (extract-calendar-month (cal-tex-previous-month date))
- (extract-calendar-year (cal-tex-previous-month date))
- "lastmonth" "1.1in" "1in"))
- (insert (cal-tex-mini-calendar
- (extract-calendar-month date)
- (extract-calendar-year date)
- "thismonth" "1.1in" "1in"))
- (insert (cal-tex-mini-calendar
- (extract-calendar-month (cal-tex-next-month date))
- (extract-calendar-year (cal-tex-next-month date))
- "nextmonth" "1.1in" "1in"))
- (insert "\\hbox to \\textwidth{")
- (cal-tex-hfill)
- (insert "\\lastmonth")
- (cal-tex-hfill)
- (insert "\\thismonth")
- (cal-tex-hfill)
- (insert "\\nextmonth")
- (cal-tex-hfill)
- (insert "}")
- (cal-tex-banner "end of cal-tex-daily-page")))
-
-;;;
-;;; Mini calendars
-;;;
-
-(defun cal-tex-mini-calendar (month year name width height &optional ptsize colsep)
- "Produce mini-calendar for MONTH, YEAR in macro NAME with WIDTH and HEIGHT.
-Optional PTSIZE gives the point ptsize; scriptsize is the default. Optional
-COLSEP gives the column separation; 1mm is the default."
- (let* ((blank-days;; at start of month
- (mod
- (- (calendar-day-of-week (list month 1 year))
- calendar-week-start-day)
- 7))
- (last (calendar-last-day-of-month month year))
- (colsep (if colsep colsep "1mm"))
- (str (concat "\\def\\" name "{\\hbox to" width "{%\n"
- "\\vbox to" height "{%\n"
- "\\vfil \\hbox to" width "{%\n"
- "\\hfil\\"
- (if ptsize ptsize "scriptsize")
- "\\begin{tabular}"
- "{@{\\hspace{0mm}}r@{\\hspace{" colsep
- "}}r@{\\hspace{" colsep "}}r@{\\hspace{" colsep
- "}}r@{\\hspace{" colsep "}}r@{\\hspace{" colsep
- "}}r@{\\hspace{" colsep "}}r@{\\hspace{0mm}}}%\n"
- "\\multicolumn{7}{c}{"
- (calendar-month-name month)
- " "
- (int-to-string year)
- "}\\\\[1mm]\n")))
- (calendar-for-loop i from 0 to 6 do
- (setq str (concat str
- (substring (aref calendar-day-name-array
- (mod (+ calendar-week-start-day i) 7))
- 0 2)
- (if (/= i 6)
- " & "
- "\\\\[0.7mm]\n"))))
- (calendar-for-loop i from 1 to blank-days do
- (setq str (concat str " & ")))
- (calendar-for-loop i from 1 to last do
- (setq str (concat str (int-to-string i)))
- (setq str (concat str (if (zerop (mod (+ i blank-days) 7))
- (if (/= i last) "\\\\[0.5mm]\n" "")
- " & "))))
- (setq str (concat str "\n\\end{tabular}\\hfil}\\vfil}}}%\n"))
- str))
-
-;;;
-;;; Various calendar functions
-;;;
-
-(defun cal-tex-incr-date (date &optional n)
- "The date of the day following DATE.
-If optional N is given, the date of N days after DATE."
- (calendar-gregorian-from-absolute
- (+ (if n n 1) (calendar-absolute-from-gregorian date))))
-
-(defun cal-tex-latexify-list (date-list date &optional separator)
- "Return string with concatenated, LaTeXified entries in DATE_LIST for DATE.
-Use double backslash as a separator unless optional SEPARATOR is given."
- (mapconcat '(lambda (x) (cal-tex-LaTeXify-string x))
- (let ((result)
- (p date-list))
- (while p
- (and (car (car p))
- (calendar-date-equal date (car (car p)))
- (setq result (append (cdr (car p)) result)))
- (setq p (cdr p)))
- result)
- (if separator separator "\\\\")))
-
-(defun cal-tex-previous-month (date)
- "Return the date of the first day in the month previous to DATE."
- (let* ((month (extract-calendar-month date))
- (year (extract-calendar-year date)))
- (increment-calendar-month month year -1)
- (list month 1 year)))
-
-(defun cal-tex-next-month (date)
- "Return the date of the first day in the month following DATE."
- (let* ((month (extract-calendar-month date))
- (year (extract-calendar-year date)))
- (increment-calendar-month month year 1)
- (list month 1 year)))
-
-;;;
-;;; LaTeX Code
-;;;
-
-(defun cal-tex-end-document ()
- "Finish the LaTeX document.
-Insert the trailer to LaTeX document, pop to LaTeX buffer, add
-informative header, and run HOOK."
- (cal-tex-e-document)
- (latex-mode)
- (pop-to-buffer cal-tex-buffer)
- (goto-char (point-min))
- (cal-tex-comment " This buffer was produced by cal-tex.el.")
- (cal-tex-comment " To print a calendar, type")
- (cal-tex-comment " M-x tex-buffer RET")
- (cal-tex-comment " M-x tex-print RET")
- (goto-char (point-min)))
-
-(defun cal-tex-insert-preamble (weeks landscape size &optional append)
- "Initialize the output buffer.
-Select the output buffer, and insert the preamble for a calendar of
-WEEKS weeks. Insert code for landscape mode if LANDSCAPE is true.
-Use pointsize SIZE. Optional argument APPEND, if t, means add to end of
-without erasing current contents."
- (let ((width "18cm")
- (height "24cm"))
- (if landscape
- (progn
- (setq width "24cm")
- (setq height "18cm")))
- (if (not append)
- (progn
- (cal-tex-preamble size)
- (if (not landscape)
- (progn
- (cal-tex-cmd "\\oddsidemargin -1.75cm")
- (cal-tex-cmd "\\def\\holidaymult{.06}"))
- (cal-tex-cmd "\\special{landscape}")
- (cal-tex-cmd "\\textwidth 9.5in")
- (cal-tex-cmd "\\textheight 7in")
- (cal-tex-comment)
- (cal-tex-cmd "\\def\\holidaymult{.08}"))
- (cal-tex-cmd cal-tex-caldate)
- (cal-tex-cmd cal-tex-myday)
- (cal-tex-b-document)
- (cal-tex-cmd "\\pagestyle{empty}")))
- (cal-tex-cmd "\\setlength{\\cellwidth}" width)
- (insert (format "\\setlength{\\cellwidth}{%f\\cellwidth}\n"
- (/ 1.1 (length cal-tex-which-days))))
- (cal-tex-cmd "\\setlength{\\cellheight}" height)
- (insert (format "\\setlength{\\cellheight}{%f\\cellheight}\n"
- (/ 1.0 weeks)))
- (cal-tex-cmd "\\ \\par")
- (cal-tex-vspace "-3cm")))
-
-(defvar cal-tex-LaTeX-subst-list
- '(("\"". "``")
- ("\"". "''");; Quote changes meaning when list is reversed.
- ("@" . "\\verb|@|")
- ("&" . "\\&")
- ("%" . "\\%")
- ("$" . "\\$")
- ("#" . "\\#")
- ("_" . "\\_")
- ("{" . "\\{")
- ("}" . "\\}")
- ("<" . "$<$")
- (">" . "$>$")
- ("\n" . "\\ \\\\")) ;\\ needed for e.g \begin{center}\n AA\end{center}
- "List of symbols and their replacements.")
-
-(defun cal-tex-LaTeXify-string (string)
- "Protect special characters in STRING from LaTeX."
- (if (not string)
- ""
- (let ((head "")
- (tail string)
- (list cal-tex-LaTeX-subst-list))
- (while (not (string-equal tail ""))
- (let* ((ch (substring tail 0 1))
- (pair (assoc ch list)))
- (if (and pair (string-equal ch "\""))
- (setq list (reverse list)));; Quote changes meaning each time.
- (setq tail (substring tail 1))
- (setq head (concat head (if pair (cdr pair) ch)))))
- head)))
-
-(defun cal-tex-hfill () "Insert hfill." (insert "\\hfill"))
-
-(defun cal-tex-newpage () "Insert newpage." (insert "\\newpage%\n"))
-
-(defun cal-tex-noindent () "Insert noindent." (insert "\\noindent"))
-
-(defun cal-tex-vspace (space)
- "Insert vspace command to move SPACE vertically."
- (insert "\\vspace*{" space "}")
- (cal-tex-comment))
-
-(defun cal-tex-hspace (space)
- "Insert hspace command to move SPACE horizontally."
- (insert "\\hspace*{" space "}")
- (cal-tex-comment))
-
-(defun cal-tex-comment (&optional comment)
- "Insert % at end of line, include COMMENT if present, and move
- to next line."
- (insert "% ")
- (if comment
- (insert comment))
- (insert "\n"))
-
-(defun cal-tex-banner (comment)
- "Insert the COMMENT separated by blank lines."
- (cal-tex-comment)
- (cal-tex-comment)
- (cal-tex-comment (concat "\t\t\t" comment))
- (cal-tex-comment))
-
-
-(defun cal-tex-nl (&optional skip comment)
- "End a line with \\. If SKIP, then add that much spacing.
- Add COMMENT if present"
- (insert "\\\\")
- (if skip
- (insert "[" skip "]"))
- (cal-tex-comment comment))
-
-(defun cal-tex-arg (&optional text)
- "Insert optional TEXT surrounded by braces."
- (insert "{")
- (if text (insert text))
- (insert "}"))
-
-(defun cal-tex-cmd (cmd &optional arg)
- "Insert LaTeX CMD, with optional ARG, and end with %"
- (insert cmd)
- (cal-tex-arg arg)
- (cal-tex-comment))
-
-;;;
-;;; Environments
-;;;
-
-(defun cal-tex-b-document ()
- "Insert beginning of document."
- (cal-tex-cmd "\\begin{document}"))
-
-(defun cal-tex-e-document ()
- "Insert end of document."
- (cal-tex-cmd "\\end{document}"))
-
-(defun cal-tex-b-center ()
- "Insert beginning of centered block."
- (cal-tex-cmd "\\begin{center}"))
-
-(defun cal-tex-e-center ()
- "Insert end of centered block."
- (cal-tex-comment)
- (cal-tex-cmd "\\end{center}"))
-
-
-;;;
-;;; Boxes
-;;;
-
-
-(defun cal-tex-b-parbox (position width)
- "Insert parbox with parameters POSITION and WIDTH."
- (insert "\\parbox[" position "]{" width "}{")
- (cal-tex-comment))
-
-(defun cal-tex-e-parbox (&optional height)
- "Insert end of parbox. Force it to be a given HEIGHT."
- (cal-tex-comment)
- (if height
- (cal-tex-rule "0mm" "0mm" height))
- (insert "}")
- (cal-tex-comment "end parbox"))
-
-(defun cal-tex-b-framebox ( width position )
- "Insert framebox with parameters WIDTH and POSITION (clr)."
- (insert "\\framebox[" width "][" position "]{" )
- (cal-tex-comment))
-
-(defun cal-tex-e-framebox ()
- "Insert end of framebox."
- (cal-tex-comment)
- (insert "}")
- (cal-tex-comment "end framebox"))
-
-
-(defun cal-tex-b-makebox ( width position )
- "Insert makebox with parameters WIDTH and POSITION (clr)."
- (insert "\\makebox[" width "][" position "]{" )
- (cal-tex-comment))
-
-(defun cal-tex-e-makebox ()
- "Insert end of makebox."
- (cal-tex-comment)
- (insert "}")
- (cal-tex-comment "end makebox"))
-
-
-(defun cal-tex-rule (lower width height)
- "Insert a rule with parameters LOWER WIDTH HEIGHT."
- (insert "\\rule[" lower "]{" width "}{" height "}"))
-
-;;;
-;;; Fonts
-;;;
-
-(defun cal-tex-em (string)
- "Insert STRING in bf font."
- (insert "{\\em " string "}"))
-
-(defun cal-tex-bf (string)
- "Insert STRING in bf font."
- (insert "{\\bf " string "}"))
-
-(defun cal-tex-scriptsize (string)
- "Insert STRING in scriptsize font."
- (insert "{\\scriptsize " string "}"))
-
-(defun cal-tex-huge (string)
- "Insert STRING in huge size."
- (insert "{\\huge " string "}"))
-
-(defun cal-tex-Huge (string)
- "Insert STRING in Huge size."
- (insert "{\\Huge " string "}"))
-
-(defun cal-tex-Huge-bf (string)
- "Insert STRING in Huge bf size."
- (insert "{\\Huge\\bf " string "}"))
-
-(defun cal-tex-large (string)
- "Insert STRING in large size."
- (insert "{\\large " string "}"))
-
-(defun cal-tex-large-bf (string)
- "Insert STRING in large bf size."
- (insert "{\\large\\bf " string "}"))
-
-(provide 'cal-tex)
-
-;;; cal-tex.el ends here
diff --git a/lisp/calendar/cal-x.el b/lisp/calendar/cal-x.el
deleted file mode 100644
index c12e23cfa26..00000000000
--- a/lisp/calendar/cal-x.el
+++ /dev/null
@@ -1,143 +0,0 @@
-;;; cal-x.el --- calendar windows in dedicated frames in X
-
-;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Michael Kifer <kifer@cs.sunysb.edu>
-;; Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: calendar, dedicated frames, X Window 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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements dedicated frames in X for
-;; calendar.el.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(require 'calendar)
-
-(defvar calendar-frame nil "Frame in which to display the calendar.")
-
-(defvar diary-frame nil "Frame in which to display the diary.")
-
-;; This should not specify the font. That's up to the user.
-;; Certainly it should not specify auto-lower and auto-raise
-;; since most users won't like that.
-(defvar diary-frame-parameters
- '((name . "Diary") (height . 10) (width . 80) (unsplittable . t)
- (minibuffer . nil))
- "Parameters of the diary frame, if the diary is in its own frame.
-Location and color should be set in .Xdefaults.")
-
-(defvar calendar-frame-parameters
- '((name . "Calendar") (minibuffer . nil) (height . 10) (width . 80)
- (unsplittable . t) (vertical-scroll-bars . nil))
- "Parameters of the calendar frame, if the calendar is in a separate frame.
-Location and color should be set in .Xdefaults.")
-
-(defvar calendar-and-diary-frame-parameters
- '((name . "Calendar") (height . 28) (width . 80) (minibuffer . nil))
- "Parameters of the frame that displays both the calendar and the diary.
-Location and color should be set in .Xdefaults.")
-
-(defvar calendar-after-frame-setup-hooks nil
- "Hooks to be run just after setting up a calendar frame.
-Can be used to change frame parameters, such as font, color, location, etc.")
-
-(defun calendar-one-frame-setup (&optional arg)
- "Start calendar and display it in a dedicated frame together with the diary."
- (if (not window-system)
- (calendar-basic-setup arg)
- (if (frame-live-p calendar-frame) (delete-frame calendar-frame))
- (if (frame-live-p diary-frame) (delete-frame diary-frame))
- (let ((special-display-buffer-names nil)
- (view-diary-entries-initially t))
- (save-window-excursion
- (save-excursion
- (setq calendar-frame
- (make-frame calendar-and-diary-frame-parameters))
- (run-hooks 'calendar-after-frame-setup-hooks)
- (select-frame calendar-frame)
- (if (eq 'icon (cdr (assoc 'visibility
- (frame-parameters calendar-frame))))
- (iconify-or-deiconify-frame))
- (calendar-basic-setup arg)
- (set-window-dedicated-p (selected-window) 'calendar)
- (set-window-dedicated-p
- (display-buffer
- (if (not (memq 'fancy-diary-display diary-display-hook))
- (get-file-buffer diary-file)
- (if (not (bufferp (get-buffer fancy-diary-buffer)))
- (make-fancy-diary-buffer))
- fancy-diary-buffer))
- 'diary))))))
-
-(defun calendar-two-frame-setup (&optional arg)
- "Start calendar and diary in separate, dedicated frames."
- (if (not window-system)
- (calendar-basic-setup arg)
- (if (frame-live-p calendar-frame) (delete-frame calendar-frame))
- (if (frame-live-p diary-frame) (delete-frame diary-frame))
- (let ((pop-up-windows nil)
- (view-diary-entries-initially nil)
- (special-display-buffer-names nil))
- (save-window-excursion
- (save-excursion (calendar-basic-setup arg))
- (setq calendar-frame (make-frame calendar-frame-parameters))
- (run-hooks 'calendar-after-frame-setup-hooks)
- (select-frame calendar-frame)
- (if (eq 'icon (cdr (assoc 'visibility
- (frame-parameters calendar-frame))))
- (iconify-or-deiconify-frame))
- (display-buffer calendar-buffer)
- (set-window-dedicated-p (selected-window) 'calendar)
- (setq diary-frame (make-frame diary-frame-parameters))
- (run-hooks 'calendar-after-frame-setup-hooks)
- (select-frame diary-frame)
- (if (eq 'icon (cdr (assoc 'visibility
- (frame-parameters diary-frame))))
- (iconify-or-deiconify-frame))
- (save-excursion (diary))
- (set-window-dedicated-p
- (display-buffer
- (if (not (memq 'fancy-diary-display diary-display-hook))
- (get-file-buffer diary-file)
- (if (not (bufferp (get-buffer fancy-diary-buffer)))
- (make-fancy-diary-buffer))
- fancy-diary-buffer))
- 'diary)))))
-
-(setq special-display-buffer-names
- (append special-display-buffer-names
- (list "*Yahrzeits*" lunar-phases-buffer holiday-buffer
- fancy-diary-buffer (get-file-buffer diary-file)
- calendar-buffer)))
-
-(run-hooks 'cal-x-load-hook)
-
-(provide 'cal-x)
-
-;;; cal-x.el ends here
diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el
deleted file mode 100644
index bd3d58fe48f..00000000000
--- a/lisp/calendar/calendar.el
+++ /dev/null
@@ -1,2336 +0,0 @@
-;;; calendar.el --- Calendar functions.
-
-;; Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995 Free
-;; Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: calendar, Gregorian calendar, diary, holidays
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements a calendar window. It generates a
-;; calendar for the current month, together with the previous and coming
-;; months, or for any other three-month period. The calendar can be scrolled
-;; forward and backward in the window to show months in the past or future;
-;; the cursor can move forward and backward by days, weeks, or months, making
-;; it possible, for instance, to jump to the date a specified number of days,
-;; weeks, or months from the date under the cursor. The user can display a
-;; list of holidays and other notable days for the period shown; the notable
-;; days can be marked on the calendar, if desired. The user can also specify
-;; that dates having corresponding diary entries (in a file that the user
-;; specifies) be marked; the diary entries for any date can be viewed in a
-;; separate window. The diary and the notable days can be viewed
-;; independently of the calendar. Dates can be translated from the (usual)
-;; Gregorian calendar to the day of the year/days remaining in year, to the
-;; ISO commercial calendar, to the Julian (old style) calendar, to the Hebrew
-;; calendar, to the Islamic calendar, to the French Revolutionary calendar, to
-;; the Mayan calendar, to the Chinese calendar, to the Coptic calendar, to the
-;; Ethiopic calendar, and to the astronomical (Julian) day number. When
-;; floating point is available, times of sunrise/sunset can be displayed, as
-;; can the phases of the moon. Appointment notification for diary entries is
-;; available. Calendar printing via LaTeX is available.
-
-;; The following files are part of the calendar/diary code:
-
-;; appt.el Appointment notification
-;; cal-china.el Chinese calendar
-;; cal-coptic.el Coptic/Ethiopic calendars
-;; cal-dst.el Daylight savings time rules
-;; cal-hebrew.el Hebrew calendar
-;; cal-islam.el Islamic calendar
-;; cal-iso.el ISO calendar
-;; cal-julian.el Julian/astronomical calendars
-;; cal-mayan.el Mayan calendars
-;; cal-menu.el Menu support
-;; cal-move.el Movement in the calendar
-;; cal-persia.el Persian calendar
-;; cal-tex.el Calendars in LaTeX
-;; cal-x.el X-windows dedicated frame functions
-;; diary-lib.el Diary functions
-;; holidays.el Holiday functions
-;; lunar.el Phases of the moon
-;; solar.el Sunrise/sunset, equinoxes/solstices
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;; Technical details of all the calendrical calculations can be found in
-
-;; ``Calendrical Calculations'' by Nachum Dershowitz and Edward M. Reingold,
-;; Software--Practice and Experience, Volume 20, Number 9 (September, 1990),
-;; pages 899-928. ``Calendrical Calculations, Part II: Three Historical
-;; Calendars'' by E. M. Reingold, N. Dershowitz, and S. M. Clamen,
-;; Software--Practice and Experience, Volume 23, Number 4 (April, 1993),
-;; pages 383-404.
-
-;; Hard copies of these two papers can be obtained by sending email to
-;; reingold@cs.uiuc.edu with the SUBJECT "send-paper-cal" (no quotes) and
-;; the message BODY containing your mailing address (snail).
-
-;;; Code:
-
-(defun calendar-version ()
- (interactive)
- (message "Version 6, October 12, 1995"))
-
-;;;###autoload
-(defvar calendar-week-start-day 0
- "*The day of the week on which a week in the calendar begins.
-0 means Sunday (default), 1 means Monday, and so on.")
-
-;;;###autoload
-(defvar calendar-offset 0
- "*The offset of the principal month from the center of the calendar window.
-0 means the principal month is in the center (default), -1 means on the left,
-+1 means on the right. Larger (or smaller) values push the principal month off
-the screen.")
-
-;;;###autoload
-(defvar view-diary-entries-initially nil
- "*Non-nil means display current date's diary entries on entry.
-The diary is displayed in another window when the calendar is first displayed,
-if the current date is visible. The number of days of diary entries displayed
-is governed by the variable `number-of-diary-entries'.")
-
-;;;###autoload
-(defvar number-of-diary-entries 1
- "*Specifies how many days of diary entries are to be displayed initially.
-This variable affects the diary display when the command M-x diary is used,
-or if the value of the variable `view-diary-entries-initially' is t. For
-example, if the default value 1 is used, then only the current day's diary
-entries will be displayed. If the value 2 is used, then both the current
-day's and the next day's entries will be displayed.
-
-The value can also be a vector such as [0 2 2 2 2 4 1]; this value
-says to display no diary entries on Sunday, the display the entries
-for the current date and the day after on Monday through Thursday,
-display Friday through Monday's entries on Friday, and display only
-Saturday's entries on Saturday.
-
-This variable does not affect the diary display with the `d' command
-from the calendar; in that case, the prefix argument controls the
-number of days of diary entries displayed.")
-
-;;;###autoload
-(defvar mark-diary-entries-in-calendar nil
- "*Non-nil means mark dates with diary entries, in the calendar window.
-The marking symbol is specified by the variable `diary-entry-marker'.")
-
-(defvar diary-entry-marker
- (if (not window-system)
- "+"
- (require 'faces)
- (add-to-list 'facemenu-unlisted-faces 'diary-face)
- (make-face 'diary-face)
- (cond ((face-differs-from-default-p 'diary-face))
- ((x-display-color-p) (set-face-foreground 'diary-face "red"))
- (t (copy-face 'bold 'diary-face)))
- 'diary-face)
- "*Used to mark dates that have diary entries.
-Can be either a single-character string or a face.")
-
-(defvar calendar-today-marker
- (if (not window-system)
- "="
- (require 'faces)
- (add-to-list 'facemenu-unlisted-faces 'calendar-today-face)
- (make-face 'calendar-today-face)
- (if (not (face-differs-from-default-p 'calendar-today-face))
- (set-face-underline-p 'calendar-today-face t))
- 'calendar-today-face)
- "*Used to mark today's date.
-Can be either a single-character string or a face.")
-
-(defvar calendar-holiday-marker
- (if (not window-system)
- "*"
- (require 'faces)
- (add-to-list 'facemenu-unlisted-faces 'holiday-face)
- (make-face 'holiday-face)
- (cond ((face-differs-from-default-p 'holiday-face))
- ((x-display-color-p) (set-face-background 'holiday-face "pink"))
- (t (set-face-background 'holiday-face "black")
- (set-face-foreground 'holiday-face "white")))
- 'holiday-face)
- "*Used to mark notable dates in the calendar.
-Can be either a single-character string or a face.")
-
-;;;###autoload
-(defvar view-calendar-holidays-initially nil
- "*Non-nil means display holidays for current three month period on entry.
-The holidays are displayed in another window when the calendar is first
-displayed.")
-
-;;;###autoload
-(defvar mark-holidays-in-calendar nil
- "*Non-nil means mark dates of holidays in the calendar window.
-The marking symbol is specified by the variable `calendar-holiday-marker'.")
-
-;;;###autoload
-(defvar all-hebrew-calendar-holidays nil
- "*If nil, show only major holidays from the Hebrew calendar.
-This means only those Jewish holidays that appear on secular calendars.
-
-If t, show all the holidays that would appear in a complete Hebrew calendar.")
-
-;;;###autoload
-(defvar all-christian-calendar-holidays nil
- "*If nil, show only major holidays from the Christian calendar.
-This means only those Christian holidays that appear on secular calendars.
-
-If t, show all the holidays that would appear in a complete Christian
-calendar.")
-
-;;;###autoload
-(defvar all-islamic-calendar-holidays nil
- "*If nil, show only major holidays from the Islamic calendar.
-This means only those Islamic holidays that appear on secular calendars.
-
-If t, show all the holidays that would appear in a complete Islamic
-calendar.")
-
-;;;###autoload
-(defvar calendar-load-hook nil
- "*List of functions to be called after the calendar is first loaded.
-This is the place to add key bindings to `calendar-mode-map'.")
-
-;;;###autoload
-(defvar initial-calendar-window-hook nil
- "*List of functions to be called when the calendar window is first opened.
-The functions invoked are called after the calendar window is opened, but
-once opened is never called again. Leaving the calendar with the `q' command
-and reentering it will cause these functions to be called again.")
-
-;;;###autoload
-(defvar today-visible-calendar-hook nil
- "*List of functions called whenever the current date is visible.
-This can be used, for example, to replace today's date with asterisks; a
-function `calendar-star-date' is included for this purpose:
- (setq today-visible-calendar-hook 'calendar-star-date)
-It can also be used to mark the current date with `calendar-today-marker';
-a function is also provided for this:
- (setq today-visible-calendar-hook 'calendar-mark-today)
-
-The corresponding variable `today-invisible-calendar-hook' is the list of
-functions called when the calendar function was called when the current
-date is not visible in the window.
-
-Other than the use of the provided functions, the changing of any
-characters in the calendar buffer by the hooks may cause the failure of the
-functions that move by days and weeks.")
-
-;;;###autoload
-(defvar today-invisible-calendar-hook nil
- "*List of functions called whenever the current date is not visible.
-
-The corresponding variable `today-visible-calendar-hook' is the list of
-functions called when the calendar function was called when the current
-date is visible in the window.
-
-Other than the use of the provided functions, the changing of any
-characters in the calendar buffer by the hooks may cause the failure of the
-functions that move by days and weeks.")
-
-;;;###autoload
-(defvar diary-file "~/diary"
- "*Name of the file in which one's personal diary of dates is kept.
-
-The file's entries are lines in any of the forms
-
- MONTH/DAY
- MONTH/DAY/YEAR
- MONTHNAME DAY
- MONTHNAME DAY, YEAR
- DAYNAME
-
-at the beginning of the line; the remainder of the line is the diary entry
-string for that date. MONTH and DAY are one or two digit numbers, YEAR is
-a number and may be written in full or abbreviated to the final two digits.
-If the date does not contain a year, it is generic and applies to any year.
-DAYNAME entries apply to any date on which is on that day of the week.
-MONTHNAME and DAYNAME can be spelled in full, abbreviated to three
-characters (with or without a period), capitalized or not. Any of DAY,
-MONTH, or MONTHNAME, YEAR can be `*' which matches any day, month, or year,
-respectively.
-
-The European style (in which the day precedes the month) can be used
-instead, if you execute `european-calendar' when in the calendar, or set
-`european-calendar-style' to t in your .emacs file. The European forms are
-
- DAY/MONTH
- DAY/MONTH/YEAR
- DAY MONTHNAME
- DAY MONTHNAME YEAR
- DAYNAME
-
-To revert to the default American style from the European style, execute
-`american-calendar' in the calendar.
-
-A diary entry can be preceded by the character
-`diary-nonmarking-symbol' (ordinarily `&') to make that entry
-nonmarking--that is, it will not be marked on dates in the calendar
-window but will appear in a diary window.
-
-Multiline diary entries are made by indenting lines after the first with
-either a TAB or one or more spaces.
-
-Lines not in one the above formats are ignored. Here are some sample diary
-entries (in the default American style):
-
- 12/22/1988 Twentieth wedding anniversary!!
- &1/1. Happy New Year!
- 10/22 Ruth's birthday.
- 21: Payday
- Tuesday--weekly meeting with grad students at 10am
- Supowit, Shen, Bitner, and Kapoor to attend.
- 1/13/89 Friday the thirteenth!!
- &thu 4pm squash game with Lloyd.
- mar 16 Dad's birthday
- April 15, 1989 Income tax due.
- &* 15 time cards due.
-
-If the first line of a diary entry consists only of the date or day name with
-no trailing blanks or punctuation, then that line is not displayed in the
-diary window; only the continuation lines is shown. For example, the
-single diary entry
-
- 02/11/1989
- Bill Blattner visits Princeton today
- 2pm Cognitive Studies Committee meeting
- 2:30-5:30 Lizzie at Lawrenceville for `Group Initiative'
- 4:00pm Jamie Tappenden
- 7:30pm Dinner at George and Ed's for Alan Ryan
- 7:30-10:00pm dance at Stewart Country Day School
-
-will appear in the diary window without the date line at the beginning. This
-facility allows the diary window to look neater, but can cause confusion if
-used with more than one day's entries displayed.
-
-Diary entries can be based on Lisp sexps. For example, the diary entry
-
- %%(diary-block 11 1 1990 11 10 1990) Vacation
-
-causes the diary entry \"Vacation\" to appear from November 1 through November
-10, 1990. Other functions available are `diary-float', `diary-anniversary',
-`diary-cyclic', `diary-day-of-year', `diary-iso-date', `diary-french-date',
-`diary-hebrew-date', `diary-islamic-date', `diary-mayan-date',
-`diary-chinese-date', `diary-coptic-date', `diary-ethiopic-date',
-`diary-persian-date', `diary-yahrzeit', `diary-sunrise-sunset',
-`diary-phases-of-moon', `diary-parasha', `diary-omer', `diary-rosh-hodesh',
-and `diary-sabbath-candles'. See the documentation for the function
-`list-sexp-diary-entries' for more details.
-
-Diary entries based on the Hebrew and/or the Islamic calendar are also
-possible, but because these are somewhat slow, they are ignored
-unless you set the `nongregorian-diary-listing-hook' and the
-`nongregorian-diary-marking-hook' appropriately. See the documentation
-for these functions for details.
-
-Diary files can contain directives to include the contents of other files; for
-details, see the documentation for the variable `list-diary-entries-hook'.")
-
-;;;###autoload
-(defvar diary-nonmarking-symbol "&"
- "*Symbol indicating that a diary entry is not to be marked in the calendar.")
-
-;;;###autoload
-(defvar hebrew-diary-entry-symbol "H"
- "*Symbol indicating a diary entry according to the Hebrew calendar.")
-
-;;;###autoload
-(defvar islamic-diary-entry-symbol "I"
- "*Symbol indicating a diary entry according to the Islamic calendar.")
-
-;;;###autoload
-(defvar diary-include-string "#include"
- "*The string indicating inclusion of another file of diary entries.
-See the documentation for the function `include-other-diary-files'.")
-
-;;;###autoload
-(defvar sexp-diary-entry-symbol "%%"
- "*The string used to indicate a sexp diary entry in diary-file.
-See the documentation for the function `list-sexp-diary-entries'.")
-
-;;;###autoload
-(defvar abbreviated-calendar-year t
- "*Interpret a two-digit year DD in a diary entry as either 19DD or 20DD.
-For the Gregorian calendar; similarly for the Hebrew and Islamic calendars.
-If this variable is nil, years must be written in full.")
-
-;;;###autoload
-(defvar european-calendar-style nil
- "*Use the European style of dates in the diary and in any displays.
-If this variable is t, a date 1/2/1990 would be interpreted as February 1,
-1990. The accepted European date styles are
-
- DAY/MONTH
- DAY/MONTH/YEAR
- DAY MONTHNAME
- DAY MONTHNAME YEAR
- DAYNAME
-
-Names can be capitalized or not, written in full, or abbreviated to three
-characters with or without a period.")
-
-;;;###autoload
-(defvar american-date-diary-pattern
- '((month "/" day "[^/0-9]")
- (month "/" day "/" year "[^0-9]")
- (monthname " *" day "[^,0-9]")
- (monthname " *" day ", *" year "[^0-9]")
- (dayname "\\W"))
- "*List of pseudo-patterns describing the American patterns of date used.
-See the documentation of `diary-date-forms' for an explanation.")
-
-;;;###autoload
-(defvar european-date-diary-pattern
- '((day "/" month "[^/0-9]")
- (day "/" month "/" year "[^0-9]")
- (backup day " *" monthname "\\W+\\<[^*0-9]")
- (day " *" monthname " *" year "[^0-9]")
- (dayname "\\W"))
- "*List of pseudo-patterns describing the European patterns of date used.
-See the documentation of `diary-date-forms' for an explanation.")
-
-(defvar diary-date-forms
- (if european-calendar-style
- european-date-diary-pattern
- american-date-diary-pattern)
- "*List of pseudo-patterns describing the forms of date used in the diary.
-The patterns on the list must be MUTUALLY EXCLUSIVE and must should not match
-any portion of the diary entry itself, just the date component.
-
-A pseudo-pattern is a list of regular expressions and the keywords `month',
-`day', `year', `monthname', and `dayname'. The keyword `monthname' will
-match the name of the month, capitalized or not, or its three-letter
-abbreviation, followed by a period or not; it will also match `*'.
-Similarly, `dayname' will match the name of the day, capitalized or not, or
-its three-letter abbreviation, followed by a period or not. The keywords
-`month', `day', and `year' will match those numerical values, preceded by
-arbitrarily many zeros; they will also match `*'.
-
-The matching of the diary entries with the date forms is done with the
-standard syntax table from Fundamental mode, but with the `*' changed so
-that it is a word constituent.
-
-If, to be mutually exclusive, a pseudo-pattern must match a portion of the
-diary entry itself, the first element of the pattern MUST be `backup'. This
-directive causes the date recognizer to back up to the beginning of the
-current word of the diary entry, so in no case can the pattern match more than
-a portion of the first word of the diary entry.")
-
-;;;###autoload
-(defvar european-calendar-display-form
- '((if dayname (concat dayname ", ")) day " " monthname " " year)
- "*Pseudo-pattern governing the way a date appears in the European style.
-See the documentation of calendar-date-display-form for an explanation.")
-
-;;;###autoload
-(defvar american-calendar-display-form
- '((if dayname (concat dayname ", ")) monthname " " day ", " year)
- "*Pseudo-pattern governing the way a date appears in the American style.
-See the documentation of `calendar-date-display-form' for an explanation.")
-
-(defvar calendar-date-display-form
- (if european-calendar-style
- european-calendar-display-form
- american-calendar-display-form)
- "*Pseudo-pattern governing the way a date appears.
-
-Used by the function `calendar-date-string', a pseudo-pattern is a list of
-expressions that can involve the keywords `month', `day', and `year', all
-numbers in string form, and `monthname' and `dayname', both alphabetic
-strings. For example, the ISO standard would use the pseudo- pattern
-
- '(year \"-\" month \"-\" day)
-
-while a typical American form would be
-
- '(month \"/\" day \"/\" (substring year -2))
-
-and
-
- '((format \"%9s, %9s %2s, %4s\" dayname monthname day year))
-
-would give the usual American style in fixed-length fields.
-
-See the documentation of the function `calendar-date-string'.")
-
-(defun european-calendar ()
- "Set the interpretation and display of dates to the European style."
- (interactive)
- (setq european-calendar-style t)
- (setq calendar-date-display-form european-calendar-display-form)
- (setq diary-date-forms european-date-diary-pattern)
- (update-calendar-mode-line))
-
-(defun american-calendar ()
- "Set the interpretation and display of dates to the American style."
- (interactive)
- (setq european-calendar-style nil)
- (setq calendar-date-display-form american-calendar-display-form)
- (setq diary-date-forms american-date-diary-pattern)
- (update-calendar-mode-line))
-
-;;;###autoload
-(defvar print-diary-entries-hook 'lpr-buffer
- "*List of functions called after a temporary diary buffer is prepared.
-The buffer shows only the diary entries currently visible in the diary
-buffer. The default just does the printing. Other uses might include, for
-example, rearranging the lines into order by day and time, saving the buffer
-instead of deleting it, or changing the function used to do the printing.")
-
-;;;###autoload
-(defvar list-diary-entries-hook nil
- "*List of functions called after diary file is culled for relevant entries.
-It is to be used for diary entries that are not found in the diary file.
-
-A function `include-other-diary-files' is provided for use as the value of
-this hook. This function enables you to use shared diary files together
-with your own. The files included are specified in the diary file by lines
-of the form
-
- #include \"filename\"
-
-This is recursive; that is, #include directives in files thus included are
-obeyed. You can change the \"#include\" to some other string by changing
-the variable `diary-include-string'. When you use `include-other-diary-files'
-as part of the list-diary-entries-hook, you will probably also want to use the
-function `mark-included-diary-files' as part of `mark-diary-entries-hook'.
-
-For example, you could use
-
- (setq list-diary-entries-hook
- '(include-other-diary-files sort-diary-entries))
- (setq diary-display-hook 'fancy-diary-display)
-
-in your `.emacs' file to cause the fancy diary buffer to be displayed with
-diary entries from various included files, each day's entries sorted into
-lexicographic order.")
-
-;;;###autoload
-(defvar diary-hook nil
- "*List of functions called after the display of the diary.
-Can be used for appointment notification.")
-
-;;;###autoload
-(defvar diary-display-hook nil
- "*List of functions that handle the display of the diary.
-If nil (the default), `simple-diary-display' is used. Use `ignore' for no
-diary display.
-
-Ordinarily, this just displays the diary buffer (with holidays indicated in
-the mode line), if there are any relevant entries. At the time these
-functions are called, the variable `diary-entries-list' is a list, in order
-by date, of all relevant diary entries in the form of ((MONTH DAY YEAR)
-STRING), where string is the diary entry for the given date. This can be
-used, for example, a different buffer for display (perhaps combined with
-holidays), or produce hard copy output.
-
-A function `fancy-diary-display' is provided as an alternative
-choice for this hook; this function prepares a special noneditable diary
-buffer with the relevant diary entries that has neat day-by-day arrangement
-with headings. The fancy diary buffer will show the holidays unless the
-variable `holidays-in-diary-buffer' is set to nil. Ordinarily, the fancy
-diary buffer will not show days for which there are no diary entries, even
-if that day is a holiday; if you want such days to be shown in the fancy
-diary buffer, set the variable `diary-list-include-blanks' to t.")
-
-;;;###autoload
-(defvar nongregorian-diary-listing-hook nil
- "*List of functions called for listing diary file and included files.
-As the files are processed for diary entries, these functions are used to cull
-relevant entries. You can use either or both of `list-hebrew-diary-entries'
-and `list-islamic-diary-entries'. The documentation for these functions
-describes the style of such diary entries.")
-
-;;;###autoload
-(defvar mark-diary-entries-hook nil
- "*List of functions called after marking diary entries in the calendar.
-
-A function `mark-included-diary-files' is also provided for use as the
-mark-diary-entries-hook; it enables you to use shared diary files together
-with your own. The files included are specified in the diary file by lines
-of the form
- #include \"filename\"
-This is recursive; that is, #include directives in files thus included are
-obeyed. You can change the \"#include\" to some other string by changing the
-variable `diary-include-string'. When you use `mark-included-diary-files' as
-part of the mark-diary-entries-hook, you will probably also want to use the
-function `include-other-diary-files' as part of `list-diary-entries-hook'.")
-
-;;;###autoload
-(defvar nongregorian-diary-marking-hook nil
- "*List of functions called for marking diary file and included files.
-As the files are processed for diary entries, these functions are used to cull
-relevant entries. You can use either or both of `mark-hebrew-diary-entries'
-and `mark-islamic-diary-entries'. The documentation for these functions
-describes the style of such diary entries.")
-
-;;;###autoload
-(defvar diary-list-include-blanks nil
- "*If nil, do not include days with no diary entry in the list of diary entries.
-Such days will then not be shown in the the fancy diary buffer, even if they
-are holidays.")
-
-;;;###autoload
-(defvar holidays-in-diary-buffer t
- "*Non-nil means include holidays in the diary display.
-The holidays appear in the mode line of the diary buffer, or in the
-fancy diary buffer next to the date. This slows down the diary functions
-somewhat; setting it to nil makes the diary display faster.")
-
-(defvar calendar-mark-ring nil)
-
-;;;###autoload
-(put 'general-holidays 'risky-local-variable t)
-;;;###autoload
-(defvar general-holidays
- '((holiday-fixed 1 1 "New Year's Day")
- (holiday-float 1 1 3 "Martin Luther King Day")
- (holiday-fixed 2 2 "Ground Hog Day")
- (holiday-fixed 2 14 "Valentine's Day")
- (holiday-float 2 1 3 "President's Day")
- (holiday-fixed 3 17 "St. Patrick's Day")
- (holiday-fixed 4 1 "April Fools' Day")
- (holiday-float 5 0 2 "Mother's Day")
- (holiday-float 5 1 -1 "Memorial Day")
- (holiday-fixed 6 14 "Flag Day")
- (holiday-float 6 0 3 "Father's Day")
- (holiday-fixed 7 4 "Independence Day")
- (holiday-float 9 1 1 "Labor Day")
- (holiday-float 10 1 2 "Columbus Day")
- (holiday-fixed 10 31 "Halloween")
- (holiday-fixed 11 11 "Veteran's Day")
- (holiday-float 11 4 4 "Thanksgiving"))
- "*General holidays. Default value is for the United States.
-See the documentation for `calendar-holidays' for details.")
-
-;;;###autoload
-(put 'oriental-holidays 'risky-local-variable t)
-;;;###autoload
-(defvar oriental-holidays
- '((if (fboundp 'atan)
- (holiday-chinese-new-year)))
- "*Oriental holidays.
-See the documentation for `calendar-holidays' for details.")
-
-;;;###autoload
-(put 'local-holidays 'risky-local-variable t)
-;;;###autoload
-(defvar local-holidays nil
- "*Local holidays.
-See the documentation for `calendar-holidays' for details.")
-
-;;;###autoload
-(put 'other-holidays 'risky-local-variable t)
-;;;###autoload
-(defvar other-holidays nil
- "*User defined holidays.
-See the documentation for `calendar-holidays' for details.")
-
-;;;###autoload
-(put 'hebrew-holidays-1 'risky-local-variable t)
-;;;###autoload
-(defvar hebrew-holidays-1
- '((holiday-rosh-hashanah-etc)
- (if all-hebrew-calendar-holidays
- (holiday-julian
- 11
- (let* ((m displayed-month)
- (y displayed-year)
- (year))
- (increment-calendar-month m y -1)
- (let ((year (extract-calendar-year
- (calendar-julian-from-absolute
- (calendar-absolute-from-gregorian
- (list m 1 y))))))
- (if (zerop (% (1+ year) 4))
- 22
- 21))) "\"Tal Umatar\" (evening)"))))
-
-;;;###autoload
-(put 'hebrew-holidays-2 'risky-local-variable t)
-;;;###autoload
-(defvar hebrew-holidays-2
- '((if all-hebrew-calendar-holidays
- (holiday-hanukkah)
- (holiday-hebrew 9 25 "Hanukkah"))
- (if all-hebrew-calendar-holidays
- (holiday-hebrew
- 10
- (let ((h-year (extract-calendar-year
- (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (list displayed-month 28 displayed-year))))))
- (if (= (% (calendar-absolute-from-hebrew (list 10 10 h-year))
- 7)
- 6)
- 11 10))
- "Tzom Teveth"))
- (if all-hebrew-calendar-holidays
- (holiday-hebrew 11 15 "Tu B'Shevat"))))
-
-;;;###autoload
-(put 'hebrew-holidays-3 'risky-local-variable t)
-;;;###autoload
-(defvar hebrew-holidays-3
- '((if all-hebrew-calendar-holidays
- (holiday-hebrew
- 11
- (let ((m displayed-month)
- (y displayed-year))
- (increment-calendar-month m y 1)
- (let* ((h-year (extract-calendar-year
- (calendar-hebrew-from-absolute
- (calendar-absolute-from-gregorian
- (list m
- (calendar-last-day-of-month m y)
- y)))))
- (s-s
- (calendar-hebrew-from-absolute
- (if (=
- (% (calendar-absolute-from-hebrew
- (list 7 1 h-year))
- 7)
- 6)
- (calendar-dayname-on-or-before
- 6 (calendar-absolute-from-hebrew
- (list 11 17 h-year)))
- (calendar-dayname-on-or-before
- 6 (calendar-absolute-from-hebrew
- (list 11 16 h-year))))))
- (day (extract-calendar-day s-s)))
- day))
- "Shabbat Shirah"))))
-
-;;;###autoload
-(put 'hebrew-holidays-4 'risky-local-variable t)
-;;;###autoload
-(defvar hebrew-holidays-4
- '((holiday-passover-etc)
- (if (and all-hebrew-calendar-holidays
- (let* ((m displayed-month)
- (y displayed-year)
- (year))
- (increment-calendar-month m y -1)
- (let ((year (extract-calendar-year
- (calendar-julian-from-absolute
- (calendar-absolute-from-gregorian
- (list m 1 y))))))
- (= 21 (% year 28)))))
- (holiday-julian 3 26 "Kiddush HaHamah"))
- (if all-hebrew-calendar-holidays
- (holiday-tisha-b-av-etc))))
-
-;;;###autoload
-(put 'hebrew-holidays 'risky-local-variable t)
-;;;###autoload
-(defvar hebrew-holidays (append hebrew-holidays-1 hebrew-holidays-2
- hebrew-holidays-3 hebrew-holidays-4)
- "*Jewish holidays.
-See the documentation for `calendar-holidays' for details.")
-
-;;;###autoload
-(put 'christian-holidays 'risky-local-variable t)
-;;;###autoload
-(defvar christian-holidays
- '((if all-christian-calendar-holidays
- (holiday-fixed 1 6 "Epiphany"))
- (holiday-easter-etc)
- (if all-christian-calendar-holidays
- (holiday-greek-orthodox-easter))
- (if all-christian-calendar-holidays
- (holiday-fixed 8 15 "Assumption"))
- (if all-christian-calendar-holidays
- (holiday-advent))
- (holiday-fixed 12 25 "Christmas")
- (if all-christian-calendar-holidays
- (holiday-julian 12 25 "Eastern Orthodox Christmas")))
- "*Christian holidays.
-See the documentation for `calendar-holidays' for details.")
-
-;;;###autoload
-(put 'islamic-holidays 'risky-local-variable t)
-;;;###autoload
-(defvar islamic-holidays
- '((holiday-islamic
- 1 1
- (format "Islamic New Year %d"
- (let ((m displayed-month)
- (y displayed-year))
- (increment-calendar-month m y 1)
- (extract-calendar-year
- (calendar-islamic-from-absolute
- (calendar-absolute-from-gregorian
- (list
- m (calendar-last-day-of-month m y) y)))))))
- (if all-islamic-calendar-holidays
- (holiday-islamic 1 10 "Ashura"))
- (if all-islamic-calendar-holidays
- (holiday-islamic 3 12 "Mulad-al-Nabi"))
- (if all-islamic-calendar-holidays
- (holiday-islamic 7 26 "Shab-e-Mi'raj"))
- (if all-islamic-calendar-holidays
- (holiday-islamic 8 15 "Shab-e-Bara't"))
- (holiday-islamic 9 1 "Ramadan Begins")
- (if all-islamic-calendar-holidays
- (holiday-islamic 9 27 "Shab-e Qadr"))
- (if all-islamic-calendar-holidays
- (holiday-islamic 10 1 "Id-al-Fitr"))
- (if all-islamic-calendar-holidays
- (holiday-islamic 12 10 "Id-al-Adha")))
- "*Islamic holidays.
-See the documentation for `calendar-holidays' for details.")
-
-;;;###autoload
-(put 'solar-holidays 'risky-local-variable t)
-;;;###autoload
-(defvar solar-holidays
- '((if (fboundp 'atan)
- (solar-equinoxes-solstices))
- (if (progn
- (require 'cal-dst)
- t)
- (funcall
- 'holiday-sexp
- calendar-daylight-savings-starts
- '(format "Daylight Savings Time Begins %s"
- (if (fboundp 'atan)
- (solar-time-string
- (/ calendar-daylight-savings-starts-time (float 60))
- calendar-standard-time-zone-name)
- ""))))
- (funcall
- 'holiday-sexp
- calendar-daylight-savings-ends
- '(format "Daylight Savings Time Ends %s"
- (if (fboundp 'atan)
- (solar-time-string
- (/ calendar-daylight-savings-ends-time (float 60))
- calendar-daylight-time-zone-name)
- ""))))
- "*Sun-related holidays.
-See the documentation for `calendar-holidays' for details.")
-
-;;;###autoload
-(put 'calendar-holidays 'risky-local-variable t)
-(defvar calendar-holidays
- (append general-holidays local-holidays other-holidays
- christian-holidays hebrew-holidays islamic-holidays
- oriental-holidays solar-holidays)
- "*List of notable days for the command M-x holidays.
-
-Additional holidays are easy to add to the list, just put them in the list
-`other-holidays' in your .emacs file. Similarly, by setting any of
-`general-holidays', `local-holidays' `christian-holidays', `hebrew-holidays',
-`islamic-holidays', `oriental-holidays', or `solar-holidays' to nil in your
-.emacs file, you can eliminate unwanted categories of holidays. The intention
-is that (in the US) `local-holidays' be set in site-init.el and
-`other-holidays' be set by the user.
-
-Entries on the list are expressions that return (possibly empty) lists of
-items of the form ((month day year) string) of a holiday in the in the
-three-month period centered around `displayed-month' of `displayed-year'.
-Several basic functions are provided for this purpose:
-
- (holiday-fixed MONTH DAY STRING) is a fixed date on the Gregorian calendar
- (holiday-float MONTH DAYNAME K STRING &optional day) is the Kth DAYNAME in
- MONTH on the Gregorian calendar (0 for Sunday,
- etc.); K<0 means count back from the end of the
- month. An optional parameter DAY means the Kth
- DAYNAME after/before MONTH DAY.
- (holiday-hebrew MONTH DAY STRING) a fixed date on the Hebrew calendar
- (holiday-islamic MONTH DAY STRING) a fixed date on the Islamic calendar
- (holiday-julian MONTH DAY STRING) a fixed date on the Julian calendar
- (holiday-sexp SEXP STRING) SEXP is a Gregorian-date-valued expression
- in the variable `year'; if it evaluates to
- a visible date, that's the holiday; if it
- evaluates to nil, there's no holiday. STRING
- is an expression in the variable `date'.
-
-For example, to add Bastille Day, celebrated in France on July 14, add
-
- (holiday-fixed 7 14 \"Bastille Day\")
-
-to the list. To add Hurricane Supplication Day, celebrated in the Virgin
-Islands on the fourth Monday in August, add
-
- (holiday-float 8 1 4 \"Hurricane Supplication Day\")
-
-to the list (the last Monday would be specified with `-1' instead of `4').
-To add the last day of Hanukkah to the list, use
-
- (holiday-hebrew 10 2 \"Last day of Hanukkah\")
-
-since the Hebrew months are numbered with 1 starting from Nisan, while to
-add the Islamic feast celebrating Mohammed's birthday use
-
- (holiday-islamic 3 12 \"Mohammed's Birthday\")
-
-since the Islamic months are numbered from 1 starting with Muharram. To
-add Thomas Jefferson's birthday, April 2, 1743 (Julian), use
-
- (holiday-julian 4 2 \"Jefferson's Birthday\")
-
-To include a holiday conditionally, use the sexp form or a conditional. For
-example, to include American presidential elections, which occur on the first
-Tuesday after the first Monday in November of years divisible by 4, add
-
- (holiday-sexp
- (if (zerop (% year 4))
- (calendar-gregorian-from-absolute
- (1+ (calendar-dayname-on-or-before
- 1 (+ 6 (calendar-absolute-from-gregorian
- (list 11 1 year)))))))
- \"US Presidential Election\")
-
-or
-
- (if (zerop (% displayed-year 4))
- (holiday-fixed 11
- (extract-calendar-day
- (calendar-gregorian-from-absolute
- (1+ (calendar-dayname-on-or-before
- 1 (+ 6 (calendar-absolute-from-gregorian
- (list 11 1 displayed-year)))))))
- \"US Presidential Election\"))
-
-to the list. To include the phases of the moon, add
-
- (lunar-phases)
-
-to the holiday list, where `lunar-phases' is an Emacs-Lisp function that
-you've written to return a (possibly empty) list of the relevant VISIBLE dates
-with descriptive strings such as
-
- (((2 6 1989) \"New Moon\") ((2 12 1989) \"First Quarter Moon\") ... ).")
-
-(defconst calendar-buffer "*Calendar*"
- "Name of the buffer used for the calendar.")
-
-(defconst holiday-buffer "*Holidays*"
- "Name of the buffer used for the displaying the holidays.")
-
-(defconst fancy-diary-buffer "*Fancy Diary Entries*"
- "Name of the buffer used for the optional fancy display of the diary.")
-
-(defconst lunar-phases-buffer "*Phases of Moon*"
- "Name of the buffer used for the lunar phases.")
-
-(defmacro increment-calendar-month (mon yr n)
- "Move the variables MON and YR to the month and year by N months.
-Forward if N is positive or backward if N is negative."
- (` (let (( macro-y (+ (* (, yr) 12) (, mon) -1 (, n) )))
- (setq (, mon) (1+ (% macro-y 12) ))
- (setq (, yr) (/ macro-y 12)))))
-
-(defmacro calendar-for-loop (var from init to final do &rest body)
- "Execute a for loop."
- (` (let (( (, var) (1- (, init)) ))
- (while (>= (, final) (setq (, var) (1+ (, var))))
- (,@ body)))))
-
-(defmacro calendar-sum (index initial condition expression)
- "For INDEX = INITIAL et seq, as long as CONDITION holds, sum EXPRESSION."
- (` (let (( (, index) (, initial))
- (sum 0))
- (while (, condition)
- (setq sum (+ sum (, expression) ))
- (setq (, index) (1+ (, index))))
- sum)))
-
-;; The following are in-line for speed; they can be called thousands of times
-;; when looking up holidays or processing the diary. Here, for example, are
-;; the numbers of calls to calendar/diary/holiday functions in preparing the
-;; fancy diary display, for a moderately complex diary file, with functions
-;; used instead of macros. There were a total of 10000 such calls:
-;;
-;; 1934 extract-calendar-month
-;; 1852 extract-calendar-year
-;; 1819 extract-calendar-day
-;; 845 calendar-leap-year-p
-;; 837 calendar-day-number
-;; 775 calendar-absolute-from-gregorian
-;; 346 calendar-last-day-of-month
-;; 286 hebrew-calendar-last-day-of-month
-;; 188 hebrew-calendar-leap-year-p
-;; 180 hebrew-calendar-elapsed-days
-;; 163 hebrew-calendar-last-month-of-year
-;; 66 calendar-date-compare
-;; 65 hebrew-calendar-days-in-year
-;; 60 calendar-absolute-from-julian
-;; 50 calendar-absolute-from-hebrew
-;; 43 calendar-date-equal
-;; 38 calendar-gregorian-from-absolute
-;; .
-;; .
-;; .
-;;
-;; The use of these seven macros eliminates the overhead of 92% of the function
-;; calls; it's faster this way.
-
-(defsubst extract-calendar-month (date)
- "Extract the month part of DATE which has the form (month day year)."
- (car date))
-
-(defsubst extract-calendar-day (date)
- "Extract the day part of DATE which has the form (month day year)."
- (car (cdr date)))
-
-(defsubst extract-calendar-year (date)
- "Extract the year part of DATE which has the form (month day year)."
- (car (cdr (cdr date))))
-
-(defsubst calendar-leap-year-p (year)
- "Returns t if YEAR is a Gregorian leap year."
- (and (zerop (% year 4))
- (or (not (zerop (% year 100)))
- (zerop (% year 400)))))
-
-;; The foregoing is a bit faster, but not as clear as the following:
-;;
-;;(defsubst calendar-leap-year-p (year)
-;; "Returns t if YEAR is a Gregorian leap year."
-;; (or
-;; (and (= (% year 4) 0)
-;; (/= (% year 100) 0))
-;; (= (% year 400) 0)))
-
-(defsubst calendar-last-day-of-month (month year)
- "The last day in MONTH during YEAR."
- (if (and (= month 2) (calendar-leap-year-p year))
- 29
- (aref [31 28 31 30 31 30 31 31 30 31 30 31] (1- month))))
-
-;; An explanation of the calculation can be found in PascAlgorithms by
-;; Edward and Ruth Reingold, Scott-Foresman/Little, Brown, 1988.
-
-(defsubst calendar-day-number (date)
- "Return the day number within the year of the date DATE.
-For example, (calendar-day-number '(1 1 1987)) returns the value 1,
-while (calendar-day-number '(12 31 1980)) returns 366."
- (let* ((month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date))
- (day-of-year (+ day (* 31 (1- month)))))
- (if (> month 2)
- (progn
- (setq day-of-year (- day-of-year (/ (+ 23 (* 4 month)) 10)))
- (if (calendar-leap-year-p year)
- (setq day-of-year (1+ day-of-year)))))
- day-of-year))
-
-(defsubst calendar-absolute-from-gregorian (date)
- "The number of days elapsed between the Gregorian date 12/31/1 BC and DATE.
-The Gregorian date Sunday, December 31, 1 BC is imaginary."
- (let ((prior-years (1- (extract-calendar-year date))))
- (+ (calendar-day-number date);; Days this year
- (* 365 prior-years);; + Days in prior years
- (/ prior-years 4);; + Julian leap years
- (- (/ prior-years 100));; - century years
- (/ prior-years 400))));; + Gregorian leap years
-
-(autoload 'calendar-goto-today "cal-move"
- "Reposition the calendar window so the current date is visible."
- t)
-
-(autoload 'calendar-forward-month "cal-move"
- "Move the cursor forward ARG months."
- t)
-
-(autoload 'calendar-forward-year "cal-move"
- "Move the cursor forward by ARG years."
- t)
-
-(autoload 'calendar-backward-month "cal-move"
- "Move the cursor backward by ARG months."
- t)
-
-(autoload 'calendar-backward-year "cal-move"
- "Move the cursor backward ARG years."
- t)
-
-(autoload 'scroll-calendar-left "cal-move"
- "Scroll the displayed calendar left by ARG months."
- t)
-
-(autoload 'scroll-calendar-right "cal-move"
- "Scroll the displayed calendar window right by ARG months."
- t)
-
-(autoload 'scroll-calendar-left-three-months "cal-move"
- "Scroll the displayed calendar window left by 3*ARG months."
- t)
-
-(autoload 'scroll-calendar-right-three-months "cal-move"
- "Scroll the displayed calendar window right by 3*ARG months."
- t)
-
-(autoload 'calendar-cursor-to-nearest-date "cal-move"
- "Move the cursor to the closest date."
- t)
-
-(autoload 'calendar-forward-day "cal-move"
- "Move the cursor forward ARG days."
- t)
-
-(autoload 'calendar-backward-day "cal-move"
- "Move the cursor back ARG days."
- t)
-
-(autoload 'calendar-forward-week "cal-move"
- "Move the cursor forward ARG weeks."
- t)
-
-(autoload 'calendar-backward-week "cal-move"
- "Move the cursor back ARG weeks."
- t)
-
-(autoload 'calendar-beginning-of-week "cal-move"
- "Move the cursor back ARG calendar-week-start-day's."
- t)
-
-(autoload 'calendar-end-of-week "cal-move"
- "Move the cursor forward ARG calendar-week-start-day+6's."
- t)
-
-(autoload 'calendar-beginning-of-month "cal-move"
- "Move the cursor backward ARG month beginnings."
- t)
-
-(autoload 'calendar-end-of-month "cal-move"
- "Move the cursor forward ARG month ends."
- t)
-
-(autoload 'calendar-beginning-of-year "cal-move"
- "Move the cursor backward ARG year beginnings."
- t)
-
-(autoload 'calendar-end-of-year "cal-move"
- "Move the cursor forward ARG year beginnings."
- t)
-
-(autoload 'calendar-cursor-to-visible-date "cal-move"
- "Move the cursor to DATE that is on the screen."
- t)
-
-(autoload 'calendar-goto-date "cal-move"
- "Move cursor to DATE."
- t)
-
-(autoload 'calendar-one-frame-setup "cal-x"
- "Start calendar and display it in a dedicated frame together with the diary.")
-
-(autoload 'calendar-two-frame-setup "cal-x"
- "Start calendar and diary in separate, dedicated frames.")
-
-;;;###autoload
-(defvar calendar-setup nil
- "The frame set up of the calendar.
-The choices are `one-frame' (calendar and diary together in one separate,
-dedicated frame) or `two-frames' (calendar and diary in separate, dedicated
-frames); with any other value the current frame is used.")
-
-;;;###autoload
-(defun calendar (&optional arg)
- "Choose between the one frame, two frame, or basic calendar displays.
-The original function `calendar' has been renamed `calendar-basic-setup'."
- (interactive "P")
- (cond ((equal calendar-setup 'one-frame) (calendar-one-frame-setup arg))
- ((equal calendar-setup 'two-frames) (calendar-two-frame-setup arg))
- (t (calendar-basic-setup arg))))
-
-(defun calendar-basic-setup (&optional arg)
- "Display a 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.
-
-If called with an optional prefix argument, prompts for month and year.
-
-This function is suitable for execution in a .emacs file; appropriate setting
-of the variable `view-diary-entries-initially' will cause the diary entries for
-the current date to be displayed in another window. The value of the variable
-`number-of-diary-entries' controls the number of days of diary entries
-displayed upon initial display of the calendar.
-
-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.
-
-Once in the calendar window, future or past months can be moved into view.
-Arbitrary months can be displayed, or the calendar can be scrolled forward
-or backward.
-
-The cursor can be moved forward or backward by one day, one week, one month,
-or one year. All of these commands take prefix arguments which, when negative,
-cause movement in the opposite direction. For convenience, the digit keys
-and the minus sign are automatically prefixes. The window is replotted as
-necessary to display the desired date.
-
-Diary entries can be marked on the calendar or displayed in another window.
-
-Use M-x describe-mode for details of the key bindings in the calendar window.
-
-The Gregorian calendar is assumed.
-
-After loading the calendar, the hooks given by the variable
-`calendar-load-hook' are run. This is the place to add key bindings to the
-calendar-mode-map.
-
-After preparing the calendar window initially, the hooks given by the variable
-`initial-calendar-window-hook' are run.
-
-The hooks given by the variable `today-visible-calendar-hook' are run
-every time the calendar window gets scrolled, if the current date is visible
-in the window. If it is not visible, the hooks given by the variable
-`today-invisible-calendar-hook' are run. Thus, for example, setting
-`today-visible-calendar-hook' to 'calendar-star-date will cause today's date
-to be replaced by asterisks to highlight it whenever it is in the window."
- (interactive "P")
- (set-buffer (get-buffer-create calendar-buffer))
- (calendar-mode)
- (let* ((pop-up-windows t)
- (split-height-threshold 1000)
- (date (if arg
- (calendar-read-date t)
- (calendar-current-date)))
- (month (extract-calendar-month date))
- (year (extract-calendar-year date)))
- (pop-to-buffer calendar-buffer)
- (increment-calendar-month month year (- calendar-offset))
- (generate-calendar-window month year)
- (if (and view-diary-entries-initially (calendar-date-is-visible-p date))
- (view-diary-entries
- (if (vectorp number-of-diary-entries)
- (aref number-of-diary-entries (calendar-day-of-week date))
- number-of-diary-entries))))
- (let* ((diary-buffer (get-file-buffer diary-file))
- (diary-window (if diary-buffer (get-buffer-window diary-buffer)))
- (split-height-threshold (if diary-window 2 1000)))
- (if view-calendar-holidays-initially
- (list-calendar-holidays)))
- (run-hooks 'initial-calendar-window-hook))
-
-(autoload 'view-diary-entries "diary-lib"
- "Prepare and display a buffer with diary entries.
-Searches your diary file for entries that match ARG days starting with
-the date indicated by the cursor position in the displayed three-month
-calendar."
- t)
-
-(autoload 'calendar-sunrise-sunset "solar"
- "Local time of sunrise and sunset for date under cursor."
- t)
-
-(autoload 'calendar-phases-of-moon "lunar"
- "Create a buffer of the phases of the moon for the current calendar window."
- t)
-
-(autoload 'calendar-print-french-date "cal-french"
- "Show the French Revolutionary calendar equivalent of the date under the cursor."
- t)
-
-(autoload 'calendar-goto-french-date "cal-french"
- "Move cursor to French Revolutionary date."
- t)
-
-(autoload 'calendar-french-date-string "cal-french"
- "String of French Revolutionary date of Gregorian date."
- t)
-
-(autoload 'calendar-mayan-date-string "cal-mayan"
- "String of Mayan date of Gregorian date."
- t)
-
-(autoload 'calendar-print-mayan-date "cal-mayan"
- "Show the Mayan long count, Tzolkin, and Haab equivalents of the date under the cursor."
- t)
-
-(autoload 'calendar-goto-mayan-long-count-date "cal-mayan"
- "Move cursor to Mayan long count date."
- t)
-
-(autoload 'calendar-next-haab-date "cal-mayan"
- "Move cursor to next instance of Mayan Haab date."
- t)
-
-(autoload 'calendar-previous-haab-date "cal-mayan"
- "Move cursor to previous instance of Mayan Haab date."
- t)
-
-(autoload 'calendar-next-tzolkin-date "cal-mayan"
- "Move cursor to next instance of Mayan Tzolkin date."
- t)
-
-(autoload 'calendar-previous-tzolkin-date "cal-mayan"
- "Move cursor to previous instance of Mayan Tzolkin date."
- t)
-
-(autoload 'calendar-next-calendar-round-date "cal-mayan"
- "Move cursor to next instance of Mayan Haab/Tzolkin combination."
- t)
-
-(autoload 'calendar-previous-calendar-round-date "cal-mayan"
- "Move cursor to previous instance of Mayan Haab/Tzolkin combination."
- t)
-
-(autoload 'calendar-goto-chinese-date "cal-china"
- "Move cursor to Chinese date."
- t)
-
-(autoload 'calendar-print-chinese-date "cal-china"
- "Show the Chinese date equivalents of date."
- t)
-
-(autoload 'calendar-chinese-date-string "cal-china"
- "String of Chinese date of Gregorian date."
- t)
-
-(autoload 'calendar-absolute-from-astro
- "Absolute date of astronomical (Julian) day number D."
- "cal-julian")
-
-(autoload 'calendar-astro-from-absolute "cal-julian"
- "Astronomical (Julian) day number of absolute date D.")
-
-(autoload 'calendar-astro-date-string "cal-julian"
- "String of astronomical (Julian) day number of Gregorian date."
- t)
-
-(autoload 'calendar-goto-astro-date "cal-julian"
- "Move cursor to astronomical (Julian) day number."
- t)
-
-(autoload 'calendar-julian-from-absolute "cal-julian"
- "Compute the Julian (month day year) corresponding to the absolute DATE.
-The absolute date is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC.")
-
-(autoload 'calendar-goto-julian-date "cal-julian"
- "Move cursor to Julian DATE; echo Julian date unless NOECHO is t."
- t)
-
-(autoload 'calendar-julian-date-string "cal-julian"
- "String of Julian date of Gregorian DATE.
-Defaults to today's date if DATE is not given.
-Driven by the variable `calendar-date-display-form'."
- t)
-
-(autoload 'calendar-goto-iso-date "cal-iso"
- "Move cursor to ISO date."
- t)
-
-(autoload 'calendar-print-iso-date "cal-iso"
- "Show the ISO date equivalents of date."
- t)
-
-(autoload 'calendar-iso-date-string "cal-iso"
- "String of ISO date of Gregorian date."
- t)
-
-(autoload 'calendar-print-islamic-date "cal-islam"
- "Show the Islamic date equivalents of date."
- t)
-
-(autoload 'calendar-islamic-date-string "cal-islam"
- "String of Islamic date of Gregorian date."
- t)
-
-(autoload 'calendar-goto-hebrew-date "cal-hebrew"
- "Move cursor to Hebrew date date."
- t)
-
-(autoload 'calendar-print-hebrew-date "cal-hebrew"
- "Show the Hebrew date equivalents of date."
- t)
-
-(autoload 'calendar-hebrew-date-string "cal-hebrew"
- "String of Hebrew date of Gregorian date."
- t)
-
-(autoload 'calendar-goto-coptic-date "cal-coptic"
- "Move cursor to Coptic date date."
- t)
-
-(autoload 'calendar-print-coptic-date "cal-coptic"
- "Show the Coptic date equivalents of date."
- t)
-
-(autoload 'calendar-coptic-date-string "cal-coptic"
- "String of Coptic date of Gregorian date."
- t)
-
-(autoload 'calendar-goto-ethiopic-date "cal-coptic"
- "Move cursor to Ethiopic date date."
- t)
-
-(autoload 'calendar-print-ethiopic-date "cal-coptic"
- "Show the Ethiopic date equivalents of date."
- t)
-
-(autoload 'calendar-ethiopic-date-string "cal-coptic"
- "String of Ethiopic date of Gregorian date."
- t)
-
-(autoload 'calendar-goto-persian-date "cal-persia"
- "Move cursor to Persian date date."
- t)
-
-(autoload 'calendar-print-persian-date "cal-persia"
- "Show the Persian date equivalents of date."
- t)
-
-(autoload 'calendar-persian-date-string "cal-persia"
- "String of Persian date of Gregorian date."
- t)
-
-(autoload 'show-all-diary-entries "diary-lib"
- "Show all of the diary entries in the diary file.
-This function gets rid of the selective display of the diary file so that
-all entries, not just some, are visible. If there is no diary buffer, one
-is created."
- t)
-
-(autoload 'mark-diary-entries "diary-lib"
- "Mark days in the calendar window that have diary entries.
-Each entry in diary file visible in the calendar window is marked."
- t)
-
-(autoload 'make-diary-entry "diary-lib"
- "Insert a diary entry STRING which may be NONMARKING in FILE."
- t)
-
-(autoload 'insert-diary-entry "diary-lib"
- "Insert a diary entry for the date indicated by point."
- t)
-
-(autoload 'insert-weekly-diary-entry "diary-lib"
- "Insert a weekly diary entry for the day of the week indicated by point."
- t)
-
-
-(autoload 'insert-monthly-diary-entry "diary-lib"
- "Insert a monthly diary entry for the day of the month indicated by point."
- t)
-
-(autoload 'insert-yearly-diary-entry "diary-lib"
- "Insert an annual diary entry for the day of the year indicated by point."
- t)
-
-(autoload 'insert-anniversary-diary-entry "diary-lib"
- "Insert an anniversary diary entry for the date indicated by point."
- t)
-
-(autoload 'insert-block-diary-entry "diary-lib"
- "Insert a block diary entry for the dates indicated by point and mark."
- t)
-
-(autoload 'insert-cyclic-diary-entry "diary-lib"
- "Insert a cyclic diary entry starting at the date indicated by point."
- t)
-
-(autoload 'insert-hebrew-diary-entry "cal-hebrew"
- "Insert a diary entry for the Hebrew date corresponding to the date
-indicated by point."
- t)
-
-(autoload 'insert-monthly-hebrew-diary-entry "cal-hebrew"
- "Insert a monthly diary entry for the day of the Hebrew month corresponding
-to the date indicated by point."
- t)
-
-(autoload 'insert-yearly-hebrew-diary-entry "cal-hebrew"
- "Insert an annual diary entry for the day of the Hebrew year corresponding
-to the date indicated by point."
- t)
-
-(autoload 'insert-islamic-diary-entry "cal-islam"
- "Insert a diary entry for the Islamic date corresponding to the date
-indicated by point."
- t)
-
-(autoload 'insert-monthly-islamic-diary-entry "cal-islam"
- "Insert a monthly diary entry for the day of the Islamic month corresponding
-to the date indicated by point."
- t)
-
-(autoload 'insert-yearly-islamic-diary-entry "cal-islam"
- "Insert an annual diary entry for the day of the Islamic year corresponding
-to the date indicated by point."
- t)
-
-(autoload 'list-calendar-holidays "holidays"
- "Create a buffer containing the holidays for the current calendar window.
-The holidays are those in the list `calendar-notable-days'. Returns t if any
-holidays are found, nil if not."
- t)
-
-(autoload 'cal-tex-cursor-month "cal-tex"
- "Make a buffer with LaTeX commands for the month cursor is on.
-Optional prefix argument specifies number of months to be produced.
-Calendar is condensed onto one page.")
-
-(autoload 'cal-tex-cursor-month-landscape "cal-tex"
- "Make a buffer with LaTeX commands for the month cursor is on.
-Optional prefix argument specifies number of months to be produced.")
-
-(autoload 'cal-tex-cursor-day "cal-tex"
- "Make a buffer with LaTeX commands for the day cursor is on.")
-
-(autoload 'cal-tex-cursor-week "cal-tex"
- "Make a buffer with LaTeX commands for a two-page one-week calendar.
-It applies to the week that point is in.
-Optional prefix argument specifies number of weeks.
-Holidays are included if `cal-tex-holidays' is t.")
-
-(autoload 'cal-tex-cursor-week2 "cal-tex"
- "Make a buffer with LaTeX commands for a two-page one-week calendar.
-It applies to the week that point is in.
-Optional prefix argument specifies number of weeks.
-Holidays are included if `cal-tex-holidays' is t.")
-
-(autoload 'cal-tex-cursor-week-iso "cal-tex"
- "Make a buffer with LaTeX commands for a one page ISO-style weekly calendar.
-Optional prefix argument specifies number of weeks.
-Diary entries are included if `cal-tex-diary' is t.
-Holidays are included if `cal-tex-holidays' is t.")
-
-(autoload 'cal-tex-cursor-week-monday "cal-tex"
- "Make a buffer with LaTeX commands for a two-page one-week calendar.
-It applies to the week that point is in, and starts on Monday.
-Optional prefix argument specifies number of weeks.
-Holidays are included if `cal-tex-holidays' is t.")
-
-(autoload 'cal-tex-cursor-filofax-2week "cal-tex"
- "Two-weeks-at-a-glance Filofax style calendar for week indicated by cursor.
-Optional prefix argument specifies number of weeks.
-Diary entries are included if cal-tex-diary is t.
-Holidays are included if `cal-tex-holidays' is t.")
-
-(autoload 'cal-tex-cursor-filofax-week "cal-tex"
- "One-week-at-a-glance Filofax style calendar for week indicated by cursor.
-Optional prefix argument specifies number of weeks.
-Weeks start on Monday.
-Diary entries are included if cal-tex-diary is t.
-Holidays are included if `cal-tex-holidays' is t.")
-
-(autoload 'cal-tex-cursor-year "cal-tex"
- "Make a buffer with LaTeX commands for a year's calendar.
-Optional prefix argument specifies number of years.")
-
-(autoload 'cal-tex-cursor-year-landscape "cal-tex"
- "Make a buffer with LaTeX commands for a year's calendar (landscape).
-Optional prefix argument specifies number of years.")
-
-(autoload 'cal-tex-cursor-filofax-year "cal-tex"
- "Make a buffer with LaTeX commands for a year's calendar (Filofax).
-Optional prefix argument specifies number of years.")
-
-(autoload 'mark-calendar-holidays "holidays"
- "Mark notable days in the calendar window."
- t)
-
-(autoload 'calendar-cursor-holidays "holidays"
- "Find holidays for the date specified by the cursor in the calendar window."
- t)
-
-(defun generate-calendar-window (&optional mon yr)
- "Generate the calendar window for the current date.
-Or, for optional MON, YR."
- (let* ((buffer-read-only nil)
- (today (calendar-current-date))
- (month (extract-calendar-month today))
- (day (extract-calendar-day today))
- (year (extract-calendar-year today))
- (today-visible
- (or (not mon)
- (let ((offset (calendar-interval mon yr month year)))
- (and (<= offset 1) (>= offset -1)))))
- (day-in-week (calendar-day-of-week today)))
- (update-calendar-mode-line)
- (if mon
- (generate-calendar mon yr)
- (generate-calendar month year))
- (calendar-cursor-to-visible-date
- (if today-visible today (list displayed-month 1 displayed-year)))
- (set-buffer-modified-p nil)
- (or (one-window-p t)
- (/= (frame-width) (window-width))
- (shrink-window (- (window-height) 9)))
- (sit-for 0)
- (and mark-holidays-in-calendar
- (mark-calendar-holidays)
- (sit-for 0))
- (unwind-protect
- (if mark-diary-entries-in-calendar (mark-diary-entries))
- (if today-visible
- (run-hooks 'today-visible-calendar-hook)
- (run-hooks 'today-invisible-calendar-hook)))))
-
-(defun generate-calendar (month year)
- "Generate a three-month Gregorian calendar centered around MONTH, YEAR."
- (if (< (+ month (* 12 (1- year))) 2)
- (error "Months before February, 1 AD are not available."))
- (setq displayed-month month)
- (setq displayed-year year)
- (erase-buffer)
- (increment-calendar-month month year -1)
- (calendar-for-loop i from 0 to 2 do
- (generate-calendar-month month year (+ 5 (* 25 i)))
- (increment-calendar-month month year 1)))
-
-(defun generate-calendar-month (month year indent)
- "Produce a calendar for MONTH, YEAR on the Gregorian calendar.
-The calendar is inserted in the buffer starting at the line on which point
-is currently located, but indented INDENT spaces. The indentation is done
-from the first character on the line and does not disturb the first INDENT
-characters on the line."
- (let* ((blank-days;; at start of month
- (mod
- (- (calendar-day-of-week (list month 1 year))
- calendar-week-start-day)
- 7))
- (last (calendar-last-day-of-month month year)))
- (goto-char (point-min))
- (calendar-insert-indented
- (calendar-string-spread
- (list (format "%s %d" (calendar-month-name month) year)) ? 20)
- indent t)
- (calendar-insert-indented "" indent);; Go to proper spot
- (calendar-for-loop i from 0 to 6 do
- (insert (substring (aref calendar-day-name-array
- (mod (+ calendar-week-start-day i) 7))
- 0 2))
- (insert " "))
- (calendar-insert-indented "" 0 t);; Force onto following line
- (calendar-insert-indented "" indent);; Go to proper spot
- ;; Add blank days before the first of the month
- (calendar-for-loop i from 1 to blank-days do (insert " "))
- ;; Put in the days of the month
- (calendar-for-loop i from 1 to last do
- (insert (format "%2d " i))
- (put-text-property (- (point) 3) (1- (point))
- 'mouse-face 'highlight)
- (and (zerop (mod (+ i blank-days) 7))
- (/= i last)
- (calendar-insert-indented "" 0 t) ;; Force onto following line
- (calendar-insert-indented "" indent)))));; Go to proper spot
-
-(defun calendar-insert-indented (string indent &optional newline)
- "Insert STRING at column INDENT.
-If the optional parameter NEWLINE is t, 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 redraw-calendar ()
- "Redraw the calendar display."
- (interactive)
- (let ((cursor-date (calendar-cursor-to-date)))
- (generate-calendar-window displayed-month displayed-year)
- (calendar-cursor-to-visible-date cursor-date)))
-
-(defvar calendar-debug-sexp nil
- "*Turn debugging on when evaluating a sexp in the diary or holiday list.")
-
-(defvar calendar-mode-map nil)
-(if calendar-mode-map
- nil
- (setq calendar-mode-map (make-sparse-keymap))
- (if window-system (require 'cal-menu))
- (calendar-for-loop i from 0 to 9 do
- (define-key calendar-mode-map (int-to-string i) 'digit-argument))
- (let ((l (list 'narrow-to-region 'mark-word 'mark-sexp 'mark-paragraph
- 'mark-defun 'mark-whole-buffer 'mark-page
- 'downcase-region 'upcase-region 'kill-region
- 'copy-region-as-kill 'capitalize-region 'write-region)))
- (while l
- (substitute-key-definition (car l) 'calendar-not-implemented
- calendar-mode-map global-map)
- (setq l (cdr l))))
- (define-key calendar-mode-map "-" 'negative-argument)
- (define-key calendar-mode-map "\C-x>" 'scroll-calendar-right)
- (define-key calendar-mode-map [prior] 'scroll-calendar-right-three-months)
- (define-key calendar-mode-map "\ev" 'scroll-calendar-right-three-months)
- (define-key calendar-mode-map "\C-x<" 'scroll-calendar-left)
- (define-key calendar-mode-map [next] 'scroll-calendar-left-three-months)
- (define-key calendar-mode-map "\C-v" 'scroll-calendar-left-three-months)
- (define-key calendar-mode-map "\C-b" 'calendar-backward-day)
- (define-key calendar-mode-map "\C-p" 'calendar-backward-week)
- (define-key calendar-mode-map "\e{" 'calendar-backward-month)
- (define-key calendar-mode-map "\C-x[" 'calendar-backward-year)
- (define-key calendar-mode-map "\C-f" 'calendar-forward-day)
- (define-key calendar-mode-map "\C-n" 'calendar-forward-week)
- (define-key calendar-mode-map [left] 'calendar-backward-day)
- (define-key calendar-mode-map [up] 'calendar-backward-week)
- (define-key calendar-mode-map [right] 'calendar-forward-day)
- (define-key calendar-mode-map [down] 'calendar-forward-week)
- (define-key calendar-mode-map "\e}" 'calendar-forward-month)
- (define-key calendar-mode-map "\C-x]" 'calendar-forward-year)
- (define-key calendar-mode-map "\C-a" 'calendar-beginning-of-week)
- (define-key calendar-mode-map "\C-e" 'calendar-end-of-week)
- (define-key calendar-mode-map "\ea" 'calendar-beginning-of-month)
- (define-key calendar-mode-map "\ee" 'calendar-end-of-month)
- (define-key calendar-mode-map "\e<" 'calendar-beginning-of-year)
- (define-key calendar-mode-map "\e>" 'calendar-end-of-year)
- (define-key calendar-mode-map "\C-@" 'calendar-set-mark)
- ;; Many people are used to typing C-SPC and getting C-@.
- (define-key calendar-mode-map [?\C-\ ] 'calendar-set-mark)
- (define-key calendar-mode-map "\C-x\C-x" 'calendar-exchange-point-and-mark)
- (define-key calendar-mode-map "\e=" 'calendar-count-days-region)
- (define-key calendar-mode-map "gd" 'calendar-goto-date)
- (define-key calendar-mode-map "gj" 'calendar-goto-julian-date)
- (define-key calendar-mode-map "ga" 'calendar-goto-astro-day-number)
- (define-key calendar-mode-map "gh" 'calendar-goto-hebrew-date)
- (define-key calendar-mode-map "gi" 'calendar-goto-islamic-date)
- (define-key calendar-mode-map "gC" 'calendar-goto-chinese-date)
- (define-key calendar-mode-map "gk" 'calendar-goto-coptic-date)
- (define-key calendar-mode-map "ge" 'calendar-goto-ethiopic-date)
- (define-key calendar-mode-map "gp" 'calendar-goto-persian-date)
- (define-key calendar-mode-map "gc" 'calendar-goto-iso-date)
- (define-key calendar-mode-map "gf" 'calendar-goto-french-date)
- (define-key calendar-mode-map "gml" 'calendar-goto-mayan-long-count-date)
- (define-key calendar-mode-map "gmpc" 'calendar-previous-calendar-round-date)
- (define-key calendar-mode-map "gmnc" 'calendar-next-calendar-round-date)
- (define-key calendar-mode-map "gmph" 'calendar-previous-haab-date)
- (define-key calendar-mode-map "gmnh" 'calendar-next-haab-date)
- (define-key calendar-mode-map "gmpt" 'calendar-previous-tzolkin-date)
- (define-key calendar-mode-map "gmnt" 'calendar-next-tzolkin-date)
- (define-key calendar-mode-map "S" 'calendar-sunrise-sunset)
- (define-key calendar-mode-map "M" 'calendar-phases-of-moon)
- (define-key calendar-mode-map " " 'scroll-other-window)
- (define-key calendar-mode-map "\C-c\C-l" 'redraw-calendar)
- (define-key calendar-mode-map "." 'calendar-goto-today)
- (define-key calendar-mode-map "o" 'calendar-other-month)
- (define-key calendar-mode-map "q" 'exit-calendar)
- (define-key calendar-mode-map "a" 'list-calendar-holidays)
- (define-key calendar-mode-map "h" 'calendar-cursor-holidays)
- (define-key calendar-mode-map "x" 'mark-calendar-holidays)
- (define-key calendar-mode-map "u" 'calendar-unmark)
- (define-key calendar-mode-map "m" 'mark-diary-entries)
- (define-key calendar-mode-map "d" 'view-diary-entries)
- (define-key calendar-mode-map "D" 'view-other-diary-entries)
- (define-key calendar-mode-map "s" 'show-all-diary-entries)
- (define-key calendar-mode-map "pd" 'calendar-print-day-of-year)
- (define-key calendar-mode-map "pC" 'calendar-print-chinese-date)
- (define-key calendar-mode-map "pk" 'calendar-print-coptic-date)
- (define-key calendar-mode-map "pe" 'calendar-print-ethiopic-date)
- (define-key calendar-mode-map "pp" 'calendar-print-persian-date)
- (define-key calendar-mode-map "pc" 'calendar-print-iso-date)
- (define-key calendar-mode-map "pj" 'calendar-print-julian-date)
- (define-key calendar-mode-map "pa" 'calendar-print-astro-day-number)
- (define-key calendar-mode-map "ph" 'calendar-print-hebrew-date)
- (define-key calendar-mode-map "pi" 'calendar-print-islamic-date)
- (define-key calendar-mode-map "pf" 'calendar-print-french-date)
- (define-key calendar-mode-map "pm" 'calendar-print-mayan-date)
- (define-key calendar-mode-map "id" 'insert-diary-entry)
- (define-key calendar-mode-map "iw" 'insert-weekly-diary-entry)
- (define-key calendar-mode-map "im" 'insert-monthly-diary-entry)
- (define-key calendar-mode-map "iy" 'insert-yearly-diary-entry)
- (define-key calendar-mode-map "ia" 'insert-anniversary-diary-entry)
- (define-key calendar-mode-map "ib" 'insert-block-diary-entry)
- (define-key calendar-mode-map "ic" 'insert-cyclic-diary-entry)
- (define-key calendar-mode-map "ihd" 'insert-hebrew-diary-entry)
- (define-key calendar-mode-map "ihm" 'insert-monthly-hebrew-diary-entry)
- (define-key calendar-mode-map "ihy" 'insert-yearly-hebrew-diary-entry)
- (define-key calendar-mode-map "iid" 'insert-islamic-diary-entry)
- (define-key calendar-mode-map "iim" 'insert-monthly-islamic-diary-entry)
- (define-key calendar-mode-map "iiy" 'insert-yearly-islamic-diary-entry)
- (define-key calendar-mode-map "?" 'calendar-goto-info-node)
- (define-key calendar-mode-map "tm" 'cal-tex-cursor-month)
- (define-key calendar-mode-map "tM" 'cal-tex-cursor-month-landscape)
- (define-key calendar-mode-map "td" 'cal-tex-cursor-day)
- (define-key calendar-mode-map "tw1" 'cal-tex-cursor-week)
- (define-key calendar-mode-map "tw2" 'cal-tex-cursor-week2)
- (define-key calendar-mode-map "tw3" 'cal-tex-cursor-week-iso)
- (define-key calendar-mode-map "tw4" 'cal-tex-cursor-week-monday)
- (define-key calendar-mode-map "tfw" 'cal-tex-cursor-filofax-2week)
- (define-key calendar-mode-map "tfW" 'cal-tex-cursor-filofax-week)
- (define-key calendar-mode-map "tfy" 'cal-tex-cursor-filofax-year)
- (define-key calendar-mode-map "ty" 'cal-tex-cursor-year)
- (define-key calendar-mode-map "tY" 'cal-tex-cursor-year-landscape))
-
-(defun describe-calendar-mode ()
- "Create a help buffer with a brief description of the calendar-mode."
- (interactive)
- (with-output-to-temp-buffer "*Help*"
- (princ
- (format
- "Calendar Mode:\nFor a complete description, type %s\n%s\n"
- (substitute-command-keys
- "\\<calendar-mode-map>\\[describe-mode] from within the calendar")
- (substitute-command-keys "\\{calendar-mode-map}")))
- (save-excursion
- (set-buffer standard-output)
- (help-mode))
- (print-help-return-message)))
-
-;; Calendar mode is suitable only for specially formatted data.
-(put 'calendar-mode 'mode-class 'special)
-
-(defvar calendar-mode-line-format
- (list
- (substitute-command-keys "\\<calendar-mode-map>\\[scroll-calendar-left]")
- "Calendar"
- (substitute-command-keys "\\<calendar-mode-map>\\[calendar-goto-info-node] info/\\[calendar-other-month] other/\\[calendar-goto-today] today")
- '(calendar-date-string (calendar-current-date) t)
- (substitute-command-keys "\\<calendar-mode-map>\\[scroll-calendar-right]"))
- "The mode line of the calendar buffer.")
-
-(defun calendar-goto-info-node ()
- "Go to the info node for the calendar."
- (interactive)
- (require 'info)
- (let ((where (save-window-excursion
- (Info-find-emacs-command-nodes 'calendar))))
- (if (not where)
- (error "Couldn't find documentation for the calendar.")
- (let (same-window-buffer-names)
- (info))
- (Info-find-node (car (car where)) (car (cdr (car where)))))))
-
-(defun calendar-mode ()
- "A major mode for the calendar window.
-
-For a complete description, type \
-\\<calendar-mode-map>\\[calendar-goto-info-node] from within the calendar.
-
-\\<calendar-mode-map>\\{calendar-mode-map}"
-
- (kill-all-local-variables)
- (setq major-mode 'calendar-mode)
- (setq mode-name "Calendar")
- (use-local-map calendar-mode-map)
- (setq buffer-read-only t)
- (setq indent-tabs-mode nil)
- (update-calendar-mode-line)
- (make-local-variable 'calendar-mark-ring)
- (make-local-variable 'displayed-month);; Month in middle of window.
- (make-local-variable 'displayed-year));; Year in middle of window.
-
-(defun calendar-string-spread (strings char length)
- "Concatenate list of STRINGS separated with copies of CHAR to fill LENGTH.
-The effect is like mapconcat but the separating pieces are as balanced as
-possible. Each item of STRINGS is evaluated before concatenation so it can
-actually be an expression that evaluates to a string. If LENGTH is too short,
-the STRINGS are just concatenated and the result truncated."
-;; The algorithm is based on equation (3.25) on page 85 of Concrete
-;; Mathematics by Ronald L. Graham, Donald E. Knuth, and Oren Patashnik,
-;; Addison-Wesley, Reading, MA, 1989
- (let* ((strings (mapcar 'eval
- (if (< (length strings) 2)
- (append (list "") strings (list ""))
- strings)))
- (n (- length (length (apply 'concat strings))))
- (m (1- (length strings)))
- (s (car strings))
- (strings (cdr strings))
- (i 0))
- (while strings
- (setq s (concat s
- (make-string (max 0 (/ (+ n i) m)) char)
- (car strings)))
- (setq i (1+ i))
- (setq strings (cdr strings)))
- (substring s 0 length)))
-
-(defun update-calendar-mode-line ()
- "Update the calendar mode line with the current date and date style."
- (if (bufferp (get-buffer calendar-buffer))
- (save-excursion
- (set-buffer calendar-buffer)
- (setq mode-line-format
- (calendar-string-spread
- calendar-mode-line-format ? (frame-width))))))
-
-(defun calendar-window-list ()
- "List of all calendar-related windows."
- (let ((calendar-buffers (calendar-buffer-list))
- list)
- (walk-windows '(lambda (w)
- (if (memq (window-buffer w) calendar-buffers)
- (setq list (cons w list))))
- nil t)
- list))
-
-(defun calendar-buffer-list ()
- "List of all calendar-related buffers."
- (let* ((diary-buffer (get-file-buffer diary-file))
- (buffers (list "*Yahrzeits*" lunar-phases-buffer holiday-buffer
- fancy-diary-buffer diary-buffer calendar-buffer))
- (buffer-list nil)
- b)
- (while buffers
- (setq b (car buffers))
- (setq b (cond ((stringp b) (get-buffer b))
- ((bufferp b) b)
- (t nil)))
- (if b (setq buffer-list (cons b buffer-list)))
- (setq buffers (cdr buffers)))
- buffer-list))
-
-(defun exit-calendar ()
- "Get out of the calendar window and hide it and related buffers."
- (interactive)
- (let* ((diary-buffer (get-file-buffer diary-file)))
- (if (and diary-buffer (buffer-modified-p diary-buffer)
- (not
- (yes-or-no-p
- "Diary modified; do you really want to exit the calendar? ")))
- (error)
- ;; Need to do this multiple times because one time can replace some
- ;; calendar-related buffers with other calendar-related buffers
- (mapcar (lambda (x)
- (mapcar 'calendar-hide-window (calendar-window-list)))
- (calendar-window-list)))))
-
-(defun calendar-hide-window (window)
- "Hide WINDOW if it is calendar-related."
- (let ((buffer (if (window-live-p window) (window-buffer window))))
- (if (memq buffer (calendar-buffer-list))
- (cond
- ((and window-system
- (eq 'icon (cdr (assoc 'visibility
- (frame-parameters
- (window-frame window))))))
- nil)
- ((and window-system (window-dedicated-p window))
- (iconify-frame (window-frame window)))
- ((not (and (select-window window) (one-window-p window)))
- (delete-window window))
- (t (set-buffer buffer)
- (bury-buffer))))))
-
-(defun calendar-current-date ()
- "Returns the current date in a list (month day year)."
- (let ((now (decode-time)))
- (list (nth 4 now) (nth 3 now) (nth 5 now))))
-
-(defun calendar-cursor-to-date (&optional error)
- "Returns a list (month day year) of current cursor position.
-If cursor is not on a specific date, signals an error if optional parameter
-ERROR is t, otherwise just returns nil."
- (let* ((segment (/ (current-column) 25))
- (month (% (+ displayed-month segment -1) 12))
- (month (if (= 0 month) 12 month))
- (year
- (cond
- ((and (= 12 month) (= segment 0)) (1- displayed-year))
- ((and (= 1 month) (= segment 2)) (1+ displayed-year))
- (t displayed-year))))
- (if (and (looking-at "[ 0-9]?[0-9][^0-9]")
- (< 2 (count-lines (point-min) (point))))
- (save-excursion
- (if (not (looking-at " "))
- (re-search-backward "[^0-9]"))
- (list month
- (string-to-int (buffer-substring (1+ (point)) (+ 4 (point))))
- year))
- (if (looking-at "\\*")
- (save-excursion
- (re-search-backward "[^*]")
- (if (looking-at ".\\*\\*")
- (list month calendar-starred-day year)
- (if error (error "Not on a date!"))))
- (if error (error "Not on a date!"))))))
-
-;; The following version of calendar-gregorian-from-absolute is preferred for
-;; reasons of clarity, BUT it's much slower than the version that follows it.
-
-;;(defun calendar-gregorian-from-absolute (date)
-;; "Compute the list (month day year) corresponding to the absolute DATE.
-;;The absolute date is the number of days elapsed since the (imaginary)
-;;Gregorian date Sunday, December 31, 1 BC."
-;; (let* ((approx (/ date 366));; Approximation from below.
-;; (year ;; Search forward from the approximation.
-;; (+ approx
-;; (calendar-sum y approx
-;; (>= date (calendar-absolute-from-gregorian (list 1 1 (1+ y))))
-;; 1)))
-;; (month ;; Search forward from January.
-;; (1+ (calendar-sum m 1
-;; (> date
-;; (calendar-absolute-from-gregorian
-;; (list m (calendar-last-day-of-month m year) year)))
-;; 1)))
-;; (day ;; Calculate the day by subtraction.
-;; (- date
-;; (1- (calendar-absolute-from-gregorian (list month 1 year))))))
-;; (list month day year)))
-
-(defun calendar-gregorian-from-absolute (date)
- "Compute the list (month day year) corresponding to the absolute DATE.
-The absolute date is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
-;; See the footnote on page 384 of ``Calendrical Calculations, Part II:
-;; Three Historical Calendars'' by E. M. Reingold, N. Dershowitz, and S. M.
-;; Clamen, Software--Practice and Experience, Volume 23, Number 4
-;; (April, 1993), pages 383-404 for an explanation.
- (let* ((d0 (1- date))
- (n400 (/ d0 146097))
- (d1 (% d0 146097))
- (n100 (/ d1 36524))
- (d2 (% d1 36524))
- (n4 (/ d2 1461))
- (d3 (% d2 1461))
- (n1 (/ d3 365))
- (day (1+ (% d3 365)))
- (year (+ (* 400 n400) (* 100 n100) (* n4 4) n1)))
- (if (or (= n100 4) (= n1 4))
- (list 12 31 year)
- (let ((year (1+ year))
- (month 1))
- (while (let ((mdays (calendar-last-day-of-month month year)))
- (and (< mdays day)
- (setq day (- day mdays))))
- (setq month (1+ month)))
- (list month day year)))))
-
-(defun calendar-other-month (month year)
- "Display a three-month calendar centered around MONTH and YEAR."
- (interactive (calendar-read-date 'noday))
- (if (and (= month displayed-month)
- (= year displayed-year))
- nil
- (let ((old-date (calendar-cursor-to-date))
- (today (calendar-current-date)))
- (generate-calendar-window month year)
- (calendar-cursor-to-visible-date
- (cond
- ((calendar-date-is-visible-p old-date) old-date)
- ((calendar-date-is-visible-p today) today)
- (t (list month 1 year)))))))
-
-(defun calendar-set-mark (arg)
- "Mark the date under the cursor, or jump to marked date.
-With no prefix argument, push current date onto marked date ring.
-With argument, jump to mark, pop it, and put point at end of ring."
- (interactive "P")
- (let ((date (calendar-cursor-to-date t)))
- (if (null arg)
- (progn
- (setq calendar-mark-ring (cons date calendar-mark-ring))
- ;; Since the top of the mark ring is the marked date in the
- ;; calendar, the mark ring in the calendar is one longer than
- ;; in other buffers to get the same effect.
- (if (> (length calendar-mark-ring) (1+ mark-ring-max))
- (setcdr (nthcdr mark-ring-max calendar-mark-ring) nil))
- (message "Mark set"))
- (if (null calendar-mark-ring)
- (error "No mark set in this buffer")
- (calendar-goto-date (car calendar-mark-ring))
- (setq calendar-mark-ring
- (cdr (nconc calendar-mark-ring (list date))))))))
-
-(defun calendar-exchange-point-and-mark ()
- "Exchange the current cursor position with the marked date."
- (interactive)
- (let ((mark (car calendar-mark-ring))
- (date (calendar-cursor-to-date t)))
- (if (null mark)
- (error "No mark set in this buffer")
- (setq calendar-mark-ring (cons date (cdr calendar-mark-ring)))
- (calendar-goto-date mark))))
-
-(defun calendar-count-days-region ()
- "Count the number of days (inclusive) between point and the mark."
- (interactive)
- (let* ((days (- (calendar-absolute-from-gregorian
- (calendar-cursor-to-date t))
- (calendar-absolute-from-gregorian
- (or (car calendar-mark-ring)
- (error "No mark set in this buffer")))))
- (days (1+ (if (> days 0) days (- days)))))
- (message "Region has %d day%s (inclusive)"
- days (if (> days 1) "s" ""))))
-
-(defun calendar-not-implemented ()
- "Not implemented."
- (interactive)
- (error "%s not available in the calendar"
- (global-key-binding (this-command-keys))))
-
-(defun calendar-read (prompt acceptable &optional initial-contents)
- "Return an object read from the minibuffer.
-Prompt with the string PROMPT and use the function ACCEPTABLE to decide if
-entered item is acceptable. If non-nil, optional third arg INITIAL-CONTENTS
-is a string to insert in the minibuffer before reading."
- (let ((value (read-minibuffer prompt initial-contents)))
- (while (not (funcall acceptable value))
- (setq value (read-minibuffer prompt initial-contents)))
- value))
-
-(defun calendar-read-date (&optional noday)
- "Prompt for Gregorian date. Returns a list (month day year).
-If optional NODAY is t, does not ask for day, but just returns
-(month nil year); if NODAY is any other non-nil value the value returned is
-(month year) "
- (let* ((year (calendar-read
- "Year (>0): "
- '(lambda (x) (> x 0))
- (int-to-string (extract-calendar-year
- (calendar-current-date)))))
- (month-array calendar-month-name-array)
- (completion-ignore-case t)
- (month (cdr (assoc
- (capitalize
- (completing-read
- "Month name: "
- (mapcar 'list (append month-array nil))
- nil t))
- (calendar-make-alist month-array 1 'capitalize))))
- (last (calendar-last-day-of-month month year)))
- (if noday
- (if (eq noday t)
- (list month nil year)
- (list month year))
- (list month
- (calendar-read (format "Day (1-%d): " last)
- '(lambda (x) (and (< 0 x) (<= x last))))
- year))))
-
-(defun calendar-interval (mon1 yr1 mon2 yr2)
- "The number of months difference between MON1, YR1 and MON2, YR2."
- (+ (* 12 (- yr2 yr1))
- (- mon2 mon1)))
-
-(defun calendar-day-name (date)
- "Returns a string with the name of the day of the week of DATE."
- (aref calendar-day-name-array (calendar-day-of-week date)))
-
-(defvar calendar-day-name-array
- ["Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"])
-
-(defvar calendar-month-name-array
- ["January" "February" "March" "April" "May" "June"
- "July" "August" "September" "October" "November" "December"])
-
-(defun calendar-make-alist (sequence &optional start-index filter)
- "Make an assoc list corresponding to SEQUENCE.
-Start at index 1, unless optional START-INDEX is provided.
-If FILTER is provided, apply it to each item in the list."
- (let ((index (if start-index (1- start-index) 0)))
- (mapcar
- '(lambda (x)
- (setq index (1+ index))
- (cons (if filter (funcall filter x) x)
- index))
- (append sequence nil))))
-
-(defun calendar-month-name (month)
- "The name of MONTH."
- (aref calendar-month-name-array (1- month)))
-
-(defun calendar-day-of-week (date)
- "Returns the day-of-the-week index of DATE, 0 for Sunday, 1 for Monday, etc."
- (% (calendar-absolute-from-gregorian date) 7))
-
-(defun calendar-unmark ()
- "Delete all diary/holiday marks/highlighting from the calendar."
- (interactive)
- (setq mark-holidays-in-calendar nil)
- (setq mark-diary-entries-in-calendar nil)
- (redraw-calendar))
-
-(defun calendar-date-is-visible-p (date)
- "Returns t if DATE is legal and is visible in the calendar window."
- (let ((gap (calendar-interval
- displayed-month displayed-year
- (extract-calendar-month date) (extract-calendar-year date))))
- (and (calendar-date-is-legal-p date) (> 2 gap) (< -2 gap))))
-
-(defun calendar-date-is-legal-p (date)
- "Returns t if DATE is a legal date."
- (let ((month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date)))
- (and (<= 1 month) (<= month 12)
- (<= 1 day) (<= day (calendar-last-day-of-month month year))
- (<= 1 year))))
-
-(defun calendar-date-equal (date1 date2)
- "Returns t if the DATE1 and DATE2 are the same."
- (and
- (= (extract-calendar-month date1) (extract-calendar-month date2))
- (= (extract-calendar-day date1) (extract-calendar-day date2))
- (= (extract-calendar-year date1) (extract-calendar-year date2))))
-
-(defun mark-visible-calendar-date (date &optional mark)
- "Mark DATE in the calendar window with MARK.
-MARK is either a single-character string or a face.
-MARK defaults to diary-entry-marker."
- (if (calendar-date-is-legal-p date)
- (save-excursion
- (set-buffer calendar-buffer)
- (calendar-cursor-to-visible-date date)
- (let ((mark (or mark diary-entry-marker)))
- (if (stringp mark)
- (let ((buffer-read-only nil))
- (forward-char 1)
- (delete-char 1)
- (insert mark)
- (forward-char -2))
- (overlay-put
- (make-overlay (1- (point)) (1+ (point))) 'face mark))))))
-
-(defun calendar-star-date ()
- "Replace the date under the cursor in the calendar window with asterisks.
-This function can be used with the today-visible-calendar-hook run after the
-calendar window has been prepared."
- (let ((buffer-read-only nil))
- (make-variable-buffer-local 'calendar-starred-day)
- (forward-char 1)
- (setq calendar-starred-day
- (string-to-int
- (buffer-substring (point) (- (point) 2))))
- (delete-char -2)
- (insert "**")
- (backward-char 1)
- (set-buffer-modified-p nil)))
-
-(defun calendar-mark-today ()
- "Mark the date under the cursor in the calendar window.
-The date is marked with calendar-today-marker. This function can be used with
-the today-visible-calendar-hook run after the calendar window has been
-prepared."
- (mark-visible-calendar-date
- (calendar-cursor-to-date)
- calendar-today-marker))
-
-(defun calendar-date-compare (date1 date2)
- "Returns t if DATE1 is before DATE2, nil otherwise.
-The actual dates are in the car of DATE1 and DATE2."
- (< (calendar-absolute-from-gregorian (car date1))
- (calendar-absolute-from-gregorian (car date2))))
-
-(defun calendar-date-string (date &optional abbreviate nodayname)
- "A string form of DATE, driven by the variable `calendar-date-display-form'.
-An optional parameter ABBREVIATE, when t, causes the month and day names to be
-abbreviated to three characters. An optional parameter NODAYNAME, when t,
-omits the name of the day of the week."
- (let* ((dayname
- (if nodayname
- nil
- (if abbreviate
- (substring (calendar-day-name date) 0 3)
- (calendar-day-name date))))
- (month (extract-calendar-month date))
- (monthname
- (if abbreviate
- (substring
- (calendar-month-name month) 0 3)
- (calendar-month-name month)))
- (day (int-to-string (extract-calendar-day date)))
- (month (int-to-string month))
- (year (int-to-string (extract-calendar-year date))))
- (mapconcat 'eval calendar-date-display-form "")))
-
-(defun calendar-dayname-on-or-before (dayname date)
- "Returns the absolute date of the DAYNAME on or before absolute DATE.
-DAYNAME=0 means Sunday, DAYNAME=1 means Monday, and so on.
-
-Note: Applying this function to d+6 gives us the DAYNAME on or after an
-absolute day d. Similarly, applying it to d+3 gives the DAYNAME nearest to
-absolute date d, applying it to d-1 gives the DAYNAME previous to absolute
-date d, and applying it to d+7 gives the DAYNAME following absolute date d."
- (- date (% (- date dayname) 7)))
-
-(defun calendar-nth-named-absday (n dayname month year &optional day)
- "The absolute date of Nth DAYNAME in MONTH, YEAR before/after optional DAY.
-A DAYNAME of 0 means Sunday, 1 means Monday, and so on. If N<0,
-return the Nth DAYNAME before MONTH DAY, YEAR (inclusive).
-If N>0, return the Nth DAYNAME after MONTH DAY, YEAR (inclusive).
-
-If DAY is omitted, it defaults to 1 if N>0, and MONTH's last day otherwise."
- (if (> n 0)
- (+ (* 7 (1- n))
- (calendar-dayname-on-or-before
- dayname
- (+ 6 (calendar-absolute-from-gregorian
- (list month (or day 1) year)))))
- (+ (* 7 (1+ n))
- (calendar-dayname-on-or-before
- dayname
- (calendar-absolute-from-gregorian
- (list month
- (or day (calendar-last-day-of-month month year))
- year))))))
-
-(defun calendar-nth-named-day (n dayname month year &optional day)
- "The date of Nth DAYNAME in MONTH, YEAR before/after optional DAY.
-A DAYNAME of 0 means Sunday, 1 means Monday, and so on. If N<0,
-return the Nth DAYNAME before MONTH DAY, YEAR (inclusive).
-If N>0, return the Nth DAYNAME after MONTH DAY, YEAR (inclusive).
-
-If DAY is omitted, it defaults to 1 if N>0, and MONTH's last day otherwise."
- (calendar-gregorian-from-absolute
- (calendar-nth-named-absday n dayname month year day)))
-
-(defun calendar-day-of-year-string (&optional date)
- "String of day number of year of Gregorian DATE.
-Defaults to today's date if DATE is not given."
- (let* ((d (or date (calendar-current-date)))
- (year (extract-calendar-year d))
- (day (calendar-day-number d))
- (days-remaining (- (calendar-day-number (list 12 31 year)) day)))
- (format "Day %d of %d; %d day%s remaining in the year"
- day year days-remaining (if (= days-remaining 1) "" "s"))))
-
-(defun calendar-print-day-of-year ()
- "Show day number in year/days remaining in year for date under the cursor."
- (interactive)
- (message (calendar-day-of-year-string (calendar-cursor-to-date t))))
-
-(defun calendar-set-mode-line (str)
- "Set mode line to STR, centered, surrounded by dashes."
- (setq mode-line-format
- (calendar-string-spread (list str) ?- (frame-width))))
-
-(defun calendar-mod (m n)
- "Non-negative remainder of M/N with N instead of 0."
- (1+ (mod (1- m) n)))
-
-(run-hooks 'calendar-load-hook)
-
-(provide 'calendar)
-
-;;; Local variables:
-;;; byte-compile-dynamic: t
-;;; End:
-
-;;; calendar.el ends here
diff --git a/lisp/calendar/diary-lib.el b/lisp/calendar/diary-lib.el
deleted file mode 100644
index 875cc2ae840..00000000000
--- a/lisp/calendar/diary-lib.el
+++ /dev/null
@@ -1,1392 +0,0 @@
-;;; diary-lib.el --- diary functions.
-
-;; Copyright (C) 1989, 1990, 1992, 1993, 1994, 1995 Free Software
-;; Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the diary features as described
-;; in calendar.el.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(require 'calendar)
-
-;;;###autoload
-(defun diary (&optional arg)
- "Generate the diary window for ARG days starting with the current date.
-If no argument is provided, the number of days of diary entries is governed
-by the variable `number-of-diary-entries'. This function is suitable for
-execution in a `.emacs' file."
- (interactive "P")
- (let ((d-file (substitute-in-file-name diary-file))
- (date (calendar-current-date)))
- (if (and d-file (file-exists-p d-file))
- (if (file-readable-p d-file)
- (list-diary-entries
- date
- (cond
- (arg (prefix-numeric-value arg))
- ((vectorp number-of-diary-entries)
- (aref number-of-diary-entries (calendar-day-of-week date)))
- (t number-of-diary-entries)))
- (error "Your diary file is not readable!"))
- (error "You don't have a diary file!"))))
-
-(defun view-diary-entries (arg)
- "Prepare and display a buffer with diary entries.
-Searches the file named in `diary-file' for entries that
-match ARG days starting with the date indicated by the cursor position
-in the displayed three-month calendar."
- (interactive "p")
- (let ((d-file (substitute-in-file-name diary-file)))
- (if (and d-file (file-exists-p d-file))
- (if (file-readable-p d-file)
- (list-diary-entries (calendar-cursor-to-date t) arg)
- (error "Diary file is not readable!"))
- (error "You don't have a diary file!"))))
-
-(defun view-other-diary-entries (arg diary-file)
- "Prepare and display buffer of diary entries from an alternative diary file.
-Prompts for a file name and searches that file for entries that match ARG
-days starting with the date indicated by the cursor position in the displayed
-three-month calendar."
- (interactive
- (list (cond ((null current-prefix-arg) 1)
- ((listp current-prefix-arg) (car current-prefix-arg))
- (t current-prefix-arg))
- (setq diary-file (read-file-name "Enter diary file name: "
- default-directory nil t))))
- (view-diary-entries arg))
-
-(autoload 'check-calendar-holidays "holidays"
- "Check the list of holidays for any that occur on DATE.
-The value returned is a list of strings of relevant holiday descriptions.
-The holidays are those in the list `calendar-holidays'."
- t)
-
-(autoload 'calendar-holiday-list "holidays"
- "Form the list of holidays that occur on dates in the calendar window.
-The holidays are those in the list `calendar-holidays'."
- t)
-
-(autoload 'diary-french-date "cal-french"
- "French calendar equivalent of date diary entry."
- t)
-
-(autoload 'diary-mayan-date "cal-mayan"
- "Mayan calendar equivalent of date diary entry."
- t)
-
-(autoload 'diary-iso-date "cal-iso"
- "ISO calendar equivalent of date diary entry."
- t)
-
-(autoload 'diary-julian-date "cal-julian"
- "Julian calendar equivalent of date diary entry."
- t)
-
-(autoload 'diary-astro-day-number "cal-julian"
- "Astronomical (Julian) day number diary entry."
- t)
-
-(autoload 'diary-chinese-date "cal-china"
- "Chinese calendar equivalent of date diary entry."
- t)
-
-(autoload 'diary-islamic-date "cal-islam"
- "Islamic calendar equivalent of date diary entry."
- t)
-
-(autoload 'list-islamic-diary-entries "cal-islam"
- "Add any Islamic date entries from the diary file to `diary-entries-list'."
- t)
-
-(autoload 'mark-islamic-diary-entries "cal-islam"
- "Mark days in the calendar window that have Islamic date diary entries."
- t)
-
-(autoload 'mark-islamic-calendar-date-pattern "cal-islam"
- "Mark dates in calendar window that conform to Islamic date MONTH/DAY/YEAR."
- t)
-
-(autoload 'diary-hebrew-date "cal-hebrew"
- "Hebrew calendar equivalent of date diary entry."
- t)
-
-(autoload 'diary-omer "cal-hebrew"
- "Omer count diary entry."
- t)
-
-(autoload 'diary-yahrzeit "cal-hebrew"
- "Yahrzeit diary entry--entry applies if date is yahrzeit or the day before."
- t)
-
-(autoload 'diary-parasha "cal-hebrew"
- "Parasha diary entry--entry applies if date is a Saturday."
- t)
-
-(autoload 'diary-rosh-hodesh "cal-hebrew"
- "Rosh Hodesh diary entry."
- t)
-
-(autoload 'list-hebrew-diary-entries "cal-hebrew"
- "Add any Hebrew date entries from the diary file to `diary-entries-list'."
- t)
-
-(autoload 'mark-hebrew-diary-entries "cal-hebrew"
- "Mark days in the calendar window that have Hebrew date diary entries."
- t)
-
-(autoload 'mark-hebrew-calendar-date-pattern "cal-hebrew"
- "Mark dates in calendar window that conform to Hebrew date MONTH/DAY/YEAR."
- t)
-
-(autoload 'diary-coptic-date "cal-coptic"
- "Coptic calendar equivalent of date diary entry."
- t)
-
-(autoload 'diary-ethiopic-date "cal-coptic"
- "Ethiopic calendar equivalent of date diary entry."
- t)
-
-(autoload 'diary-persian-date "cal-persia"
- "Persian calendar equivalent of date diary entry."
- t)
-
-(autoload 'diary-phases-of-moon "lunar" "Moon phases diary entry." t)
-
-(autoload 'diary-sunrise-sunset "solar"
- "Local time of sunrise and sunset as a diary entry."
- t)
-
-(autoload 'diary-sabbath-candles "solar"
- "Local time of candle lighting diary entry--applies if date is a Friday.
-No diary entry if there is no sunset on that date."
- t)
-
-(defvar diary-syntax-table (copy-syntax-table (standard-syntax-table))
- "The syntax table used when parsing dates in the diary file.
-It is the standard syntax table used in Fundamental mode, but with the
-syntax of `*' changed to be a word constituent.")
-
-(modify-syntax-entry ?* "w" diary-syntax-table)
-
-(defun list-diary-entries (date number)
- "Create and display a buffer containing the relevant lines in diary-file.
-The arguments are DATE and NUMBER; the entries selected are those
-for NUMBER days starting with date DATE. The other entries are hidden
-using selective display.
-
-Returns a list of all relevant diary entries found, if any, in order by date.
-The list entries have the form ((month day year) string). If the variable
-`diary-list-include-blanks' is t, this list includes a dummy diary entry
-\(consisting of the empty string) for a date with no diary entries.
-
-After the list is prepared, the hooks `nongregorian-diary-listing-hook',
-`list-diary-entries-hook', `diary-display-hook', and `diary-hook' are run.
-These hooks have the following distinct roles:
-
- `nongregorian-diary-listing-hook' can cull dates from the diary
- and each included file. Usually used for Hebrew or Islamic
- diary entries in files. Applied to *each* file.
-
- `list-diary-entries-hook' adds or manipulates diary entries from
- external sources. Used, for example, to include diary entries
- from other files or to sort the diary entries. Invoked *once* only,
- before the display hook is run.
-
- `diary-display-hook' does the actual display of information. If this is
- nil, simple-diary-display will be used. Use add-hook to set this to
- fancy-diary-display, if desired. If you want no diary display, use
- add-hook to set this to ignore.
-
- `diary-hook' is run last. This can be used for an appointment
- notification function."
-
- (if (< 0 number)
- (let* ((original-date date);; save for possible use in the hooks
- (old-diary-syntax-table)
- (diary-entries-list)
- (date-string (calendar-date-string date))
- (d-file (substitute-in-file-name diary-file)))
- (message "Preparing diary...")
- (save-excursion
- (let ((diary-buffer (find-buffer-visiting d-file)))
- (if (not diary-buffer)
- (set-buffer (find-file-noselect d-file t))
- (set-buffer diary-buffer)
- (or (verify-visited-file-modtime diary-buffer)
- (revert-buffer t t))))
- (setq selective-display t)
- (setq selective-display-ellipses nil)
- (setq old-diary-syntax-table (syntax-table))
- (set-syntax-table diary-syntax-table)
- (unwind-protect
- (let ((buffer-read-only nil)
- (diary-modified (buffer-modified-p))
- (mark (regexp-quote diary-nonmarking-symbol)))
- (goto-char (1- (point-max)))
- (if (not (looking-at "\^M\\|\n"))
- (progn
- (forward-char 1)
- (insert-string "\^M")))
- (goto-char (point-min))
- (if (not (looking-at "\^M\\|\n"))
- (insert-string "\^M"))
- (subst-char-in-region (point-min) (point-max) ?\n ?\^M t)
- (calendar-for-loop i from 1 to number do
- (let ((d diary-date-forms)
- (month (extract-calendar-month date))
- (day (extract-calendar-day date))
- (year (extract-calendar-year date))
- (entry-found (list-sexp-diary-entries date)))
- (while d
- (let*
- ((date-form (if (equal (car (car d)) 'backup)
- (cdr (car d))
- (car d)))
- (backup (equal (car (car d)) 'backup))
- (dayname
- (concat
- (calendar-day-name date) "\\|"
- (substring (calendar-day-name date) 0 3) ".?"))
- (monthname
- (concat
- "\\*\\|"
- (calendar-month-name month) "\\|"
- (substring (calendar-month-name month) 0 3) ".?"))
- (month (concat "\\*\\|0*" (int-to-string month)))
- (day (concat "\\*\\|0*" (int-to-string day)))
- (year
- (concat
- "\\*\\|0*" (int-to-string year)
- (if abbreviated-calendar-year
- (concat "\\|" (int-to-string (% year 100)))
- "")))
- (regexp
- (concat
- "\\(\\`\\|\^M\\|\n\\)" mark "?\\("
- (mapconcat 'eval date-form "\\)\\(")
- "\\)"))
- (case-fold-search t))
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (if backup (re-search-backward "\\<" nil t))
- (if (and (or (char-equal (preceding-char) ?\^M)
- (char-equal (preceding-char) ?\n))
- (not (looking-at " \\|\^I")))
- ;; Diary entry that consists only of date.
- (backward-char 1)
- ;; Found a nonempty diary entry--make it visible and
- ;; add it to the list.
- (setq entry-found t)
- (let ((entry-start (point))
- (date-start))
- (re-search-backward "\^M\\|\n\\|\\`")
- (setq date-start (point))
- (re-search-forward "\^M\\|\n" nil t 2)
- (while (looking-at " \\|\^I")
- (re-search-forward "\^M\\|\n" nil t))
- (backward-char 1)
- (subst-char-in-region date-start
- (point) ?\^M ?\n t)
- (add-to-diary-list
- date
- (buffer-substring-no-properties
- entry-start (point)))))))
- (setq d (cdr d)))
- (or entry-found
- (not diary-list-include-blanks)
- (setq diary-entries-list
- (append diary-entries-list
- (list (list date "")))))
- (setq date
- (calendar-gregorian-from-absolute
- (1+ (calendar-absolute-from-gregorian date))))
- (setq entry-found nil)))
- (set-buffer-modified-p diary-modified))
- (set-syntax-table old-diary-syntax-table))
- (goto-char (point-min))
- (run-hooks 'nongregorian-diary-listing-hook
- 'list-diary-entries-hook)
- (if diary-display-hook
- (run-hooks 'diary-display-hook)
- (simple-diary-display))
- (run-hooks 'diary-hook)
- diary-entries-list))))
-
-(defun include-other-diary-files ()
- "Include the diary entries from other diary files with those of diary-file.
-This function is suitable for use in `list-diary-entries-hook';
-it enables you to use shared diary files together with your own.
-The files included are specified in the diaryfile by lines of this form:
- #include \"filename\"
-This is recursive; that is, #include directives in diary files thus included
-are obeyed. You can change the `#include' to some other string by
-changing the variable `diary-include-string'."
- (goto-char (point-min))
- (while (re-search-forward
- (concat
- "\\(\\`\\|\^M\\|\n\\)"
- (regexp-quote diary-include-string)
- " \"\\([^\"]*\\)\"")
- nil t)
- (let ((diary-file (substitute-in-file-name
- (buffer-substring-no-properties
- (match-beginning 2) (match-end 2))))
- (diary-list-include-blanks nil)
- (list-diary-entries-hook 'include-other-diary-files)
- (diary-display-hook 'ignore)
- (diary-hook nil))
- (if (file-exists-p diary-file)
- (if (file-readable-p diary-file)
- (unwind-protect
- (setq diary-entries-list
- (append diary-entries-list
- (list-diary-entries original-date number)))
- (kill-buffer (find-buffer-visiting diary-file)))
- (beep)
- (message "Can't read included diary file %s" diary-file)
- (sleep-for 2))
- (beep)
- (message "Can't find included diary file %s" diary-file)
- (sleep-for 2))))
- (goto-char (point-min)))
-
-(defun simple-diary-display ()
- "Display the diary buffer if there are any relevant entries or holidays."
- (let* ((holiday-list (if holidays-in-diary-buffer
- (check-calendar-holidays original-date)))
- (msg (format "No diary entries for %s %s"
- (concat date-string (if holiday-list ":" ""))
- (mapconcat 'identity holiday-list "; "))))
- (if (or (not diary-entries-list)
- (and (not (cdr diary-entries-list))
- (string-equal (car (cdr (car diary-entries-list))) "")))
- (if (<= (length msg) (frame-width))
- (message "%s" msg)
- (set-buffer (get-buffer-create holiday-buffer))
- (setq buffer-read-only nil)
- (calendar-set-mode-line date-string)
- (erase-buffer)
- (insert (mapconcat 'identity holiday-list "\n"))
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- (setq buffer-read-only t)
- (display-buffer holiday-buffer)
- (message "No diary entries for %s" date-string))
- (calendar-set-mode-line
- (concat "Diary for " date-string
- (if holiday-list ": " "")
- (mapconcat 'identity holiday-list "; ")))
- (display-buffer (find-buffer-visiting d-file))
- (message "Preparing diary...done"))))
-
-(defun fancy-diary-display ()
- "Prepare a diary buffer with relevant entries in a fancy, noneditable form.
-This function is provided for optional use as the `diary-display-hook'."
- (save-excursion;; Turn off selective-display in the diary file's buffer.
- (set-buffer (find-buffer-visiting (substitute-in-file-name diary-file)))
- (let ((diary-modified (buffer-modified-p)))
- (subst-char-in-region (point-min) (point-max) ?\^M ?\n t)
- (setq selective-display nil)
- (kill-local-variable 'mode-line-format)
- (set-buffer-modified-p diary-modified)))
- (if (or (not diary-entries-list)
- (and (not (cdr diary-entries-list))
- (string-equal (car (cdr (car diary-entries-list))) "")))
- (let* ((holiday-list (if holidays-in-diary-buffer
- (check-calendar-holidays original-date)))
- (msg (format "No diary entries for %s %s"
- (concat date-string (if holiday-list ":" ""))
- (mapconcat 'identity holiday-list "; "))))
- (if (<= (length msg) (frame-width))
- (message "%s" msg)
- (set-buffer (get-buffer-create holiday-buffer))
- (setq buffer-read-only nil)
- (calendar-set-mode-line date-string)
- (erase-buffer)
- (insert (mapconcat 'identity holiday-list "\n"))
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- (setq buffer-read-only t)
- (display-buffer holiday-buffer)
- (message "No diary entries for %s" date-string)))
- (save-excursion;; Prepare the fancy diary buffer.
- (set-buffer (make-fancy-diary-buffer))
- (setq buffer-read-only nil)
- (let ((entry-list diary-entries-list)
- (holiday-list)
- (holiday-list-last-month 1)
- (holiday-list-last-year 1)
- (date (list 0 0 0)))
- (while entry-list
- (if (not (calendar-date-equal date (car (car entry-list))))
- (progn
- (setq date (car (car entry-list)))
- (and holidays-in-diary-buffer
- (calendar-date-compare
- (list (list holiday-list-last-month
- (calendar-last-day-of-month
- holiday-list-last-month
- holiday-list-last-year)
- holiday-list-last-year))
- (list date))
- ;; We need to get the holidays for the next 3 months.
- (setq holiday-list-last-month
- (extract-calendar-month date))
- (setq holiday-list-last-year
- (extract-calendar-year date))
- (increment-calendar-month
- holiday-list-last-month holiday-list-last-year 1)
- (setq holiday-list
- (let ((displayed-month holiday-list-last-month)
- (displayed-year holiday-list-last-year))
- (calendar-holiday-list)))
- (increment-calendar-month
- holiday-list-last-month holiday-list-last-year 1))
- (let* ((date-string (calendar-date-string date))
- (date-holiday-list
- (let ((h holiday-list)
- (d))
- ;; Make a list of all holidays for date.
- (while h
- (if (calendar-date-equal date (car (car h)))
- (setq d (append d (cdr (car h)))))
- (setq h (cdr h)))
- d)))
- (insert (if (= (point) (point-min)) "" ?\n) date-string)
- (if date-holiday-list (insert ": "))
- (let* ((l (current-column))
- (longest 0))
- (insert (mapconcat '(lambda (x)
- (if (< longest (length x))
- (setq longest (length x)))
- x)
- date-holiday-list
- (concat "\n" (make-string l ? ))))
- (insert ?\n (make-string (+ l longest) ?=) ?\n)))))
- (if (< 0 (length (car (cdr (car entry-list)))))
- (insert (car (cdr (car entry-list))) ?\n))
- (setq entry-list (cdr entry-list))))
- (set-buffer-modified-p nil)
- (goto-char (point-min))
- (setq buffer-read-only t)
- (display-buffer fancy-diary-buffer)
- (message "Preparing diary...done"))))
-
-(defun make-fancy-diary-buffer ()
- "Create and return the initial fancy diary buffer."
- (save-excursion
- (set-buffer (get-buffer-create fancy-diary-buffer))
- (setq buffer-read-only nil)
- (make-local-variable 'mode-line-format)
- (calendar-set-mode-line "Diary Entries")
- (erase-buffer)
- (set-buffer-modified-p nil)
- (setq buffer-read-only t)
- (get-buffer fancy-diary-buffer)))
-
-(defun print-diary-entries ()
- "Print a hard copy of the diary display.
-
-If the simple diary display is being used, prepare a temp buffer with the
-visible lines of the diary buffer, add a heading line composed from the mode
-line, print the temp buffer, and destroy it.
-
-If the fancy diary display is being used, just print the buffer.
-
-The hooks given by the variable `print-diary-entries-hook' are called to do
-the actual printing."
- (interactive)
- (if (bufferp (get-buffer fancy-diary-buffer))
- (save-excursion
- (set-buffer (get-buffer fancy-diary-buffer))
- (run-hooks 'print-diary-entries-hook))
- (let ((diary-buffer
- (find-buffer-visiting (substitute-in-file-name diary-file))))
- (if diary-buffer
- (let ((temp-buffer (get-buffer-create "*Printable Diary Entries*"))
- (heading))
- (save-excursion
- (set-buffer diary-buffer)
- (setq heading
- (if (not (stringp mode-line-format))
- "All Diary Entries"
- (string-match "^-*\\([^-].*[^-]\\)-*$" mode-line-format)
- (substring mode-line-format
- (match-beginning 1) (match-end 1))))
- (copy-to-buffer temp-buffer (point-min) (point-max))
- (set-buffer temp-buffer)
- (while (re-search-forward "\^M.*$" nil t)
- (replace-match ""))
- (goto-char (point-min))
- (insert heading "\n"
- (make-string (length heading) ?=) "\n")
- (run-hooks 'print-diary-entries-hook)
- (kill-buffer temp-buffer)))
- (error "You don't have a diary buffer!")))))
-
-(defun show-all-diary-entries ()
- "Show all of the diary entries in the diary file.
-This function gets rid of the selective display of the diary file so that
-all entries, not just some, are visible. If there is no diary buffer, one
-is created."
- (interactive)
- (let ((d-file (substitute-in-file-name diary-file)))
- (if (and d-file (file-exists-p d-file))
- (if (file-readable-p d-file)
- (save-excursion
- (let ((diary-buffer (find-buffer-visiting d-file)))
- (set-buffer (if diary-buffer
- diary-buffer
- (find-file-noselect d-file t)))
- (let ((buffer-read-only nil)
- (diary-modified (buffer-modified-p)))
- (subst-char-in-region (point-min) (point-max) ?\^M ?\n t)
- (setq selective-display nil)
- (make-local-variable 'mode-line-format)
- (setq mode-line-format default-mode-line-format)
- (display-buffer (current-buffer))
- (set-buffer-modified-p diary-modified))))
- (error "Your diary file is not readable!"))
- (error "You don't have a diary file!"))))
-
-(defun diary-name-pattern (string-array &optional fullname)
- "Convert an STRING-ARRAY, an array of strings to a pattern.
-The pattern will match any of the strings, either entirely or abbreviated
-to three characters. An abbreviated form will match with or without a period;
-If the optional FULLNAME is t, abbreviations will not match, just the full
-name."
- (let ((pattern ""))
- (calendar-for-loop i from 0 to (1- (length string-array)) do
- (setq pattern
- (concat
- pattern
- (if (string-equal pattern "") "" "\\|")
- (aref string-array i)
- (if fullname
- ""
- (concat
- "\\|"
- (substring (aref string-array i) 0 3) ".?")))))
- pattern))
-
-(defvar marking-diary-entries nil
- "True during the marking of diary entries, nil otherwise.")
-
-(defvar marking-diary-entry nil
- "True during the marking of diary entries, if current entry is marking.")
-
-(defun mark-diary-entries ()
- "Mark days in the calendar window that have diary entries.
-Each entry in the diary file visible in the calendar window is marked.
-After the entries are marked, the hooks `nongregorian-diary-marking-hook' and
-`mark-diary-entries-hook' are run."
- (interactive)
- (setq mark-diary-entries-in-calendar t)
- (let ((d-file (substitute-in-file-name diary-file))
- (marking-diary-entries t))
- (if (and d-file (file-exists-p d-file))
- (if (file-readable-p d-file)
- (save-excursion
- (message "Marking diary entries...")
- (set-buffer (find-file-noselect d-file t))
- (let ((d diary-date-forms)
- (old-diary-syntax-table))
- (setq old-diary-syntax-table (syntax-table))
- (set-syntax-table diary-syntax-table)
- (while d
- (let*
- ((date-form (if (equal (car (car d)) 'backup)
- (cdr (car d))
- (car d)));; ignore 'backup directive
- (dayname (diary-name-pattern calendar-day-name-array))
- (monthname
- (concat
- (diary-name-pattern calendar-month-name-array)
- "\\|\\*"))
- (month "[0-9]+\\|\\*")
- (day "[0-9]+\\|\\*")
- (year "[0-9]+\\|\\*")
- (l (length date-form))
- (d-name-pos (- l (length (memq 'dayname date-form))))
- (d-name-pos (if (/= l d-name-pos) (+ 2 d-name-pos)))
- (m-name-pos (- l (length (memq 'monthname date-form))))
- (m-name-pos (if (/= l m-name-pos) (+ 2 m-name-pos)))
- (d-pos (- l (length (memq 'day date-form))))
- (d-pos (if (/= l d-pos) (+ 2 d-pos)))
- (m-pos (- l (length (memq 'month date-form))))
- (m-pos (if (/= l m-pos) (+ 2 m-pos)))
- (y-pos (- l (length (memq 'year date-form))))
- (y-pos (if (/= l y-pos) (+ 2 y-pos)))
- (regexp
- (concat
- "\\(\\`\\|\^M\\|\n\\)\\("
- (mapconcat 'eval date-form "\\)\\(")
- "\\)"))
- (case-fold-search t))
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (let* ((dd-name
- (if d-name-pos
- (buffer-substring-no-properties
- (match-beginning d-name-pos)
- (match-end d-name-pos))))
- (mm-name
- (if m-name-pos
- (buffer-substring-no-properties
- (match-beginning m-name-pos)
- (match-end m-name-pos))))
- (mm (string-to-int
- (if m-pos
- (buffer-substring-no-properties
- (match-beginning m-pos)
- (match-end m-pos))
- "")))
- (dd (string-to-int
- (if d-pos
- (buffer-substring-no-properties
- (match-beginning d-pos)
- (match-end d-pos))
- "")))
- (y-str (if y-pos
- (buffer-substring-no-properties
- (match-beginning y-pos)
- (match-end y-pos))))
- (yy (if (not y-str)
- 0
- (if (and (= (length y-str) 2)
- abbreviated-calendar-year)
- (let* ((current-y
- (extract-calendar-year
- (calendar-current-date)))
- (y (+ (string-to-int y-str)
- (* 100
- (/ current-y 100)))))
- (if (> (- y current-y) 50)
- (- y 100)
- (if (> (- current-y y) 50)
- (+ y 100)
- y)))
- (string-to-int y-str)))))
- (if dd-name
- (mark-calendar-days-named
- (cdr (assoc (capitalize (substring dd-name 0 3))
- (calendar-make-alist
- calendar-day-name-array
- 0
- '(lambda (x) (substring x 0 3))))))
- (if mm-name
- (if (string-equal mm-name "*")
- (setq mm 0)
- (setq mm
- (cdr (assoc
- (capitalize
- (substring mm-name 0 3))
- (calendar-make-alist
- calendar-month-name-array
- 1
- '(lambda (x) (substring x 0 3)))
- )))))
- (mark-calendar-date-pattern mm dd yy))))
- (setq d (cdr d))))
- (mark-sexp-diary-entries)
- (run-hooks 'nongregorian-diary-marking-hook
- 'mark-diary-entries-hook)
- (set-syntax-table old-diary-syntax-table)
- (message "Marking diary entries...done")))
- (error "Your diary file is not readable!"))
- (error "You don't have a diary file!"))))
-
-(defun mark-sexp-diary-entries ()
- "Mark days in the calendar window that have sexp diary entries.
-Each entry in the diary file (or included files) visible in the calendar window
-is marked. See the documentation for the function `list-sexp-diary-entries'."
- (let* ((sexp-mark (regexp-quote sexp-diary-entry-symbol))
- (s-entry (concat "\\(\\`\\|\^M\\|\n\\)\\("
- (regexp-quote sexp-mark) "(\\)\\|\\("
- (regexp-quote diary-nonmarking-symbol)
- (regexp-quote sexp-mark) "(diary-remind\\)"))
- (m)
- (y)
- (first-date)
- (last-date))
- (save-excursion
- (set-buffer calendar-buffer)
- (setq m displayed-month)
- (setq y displayed-year))
- (increment-calendar-month m y -1)
- (setq first-date
- (calendar-absolute-from-gregorian (list m 1 y)))
- (increment-calendar-month m y 2)
- (setq last-date
- (calendar-absolute-from-gregorian
- (list m (calendar-last-day-of-month m y) y)))
- (goto-char (point-min))
- (while (re-search-forward s-entry nil t)
- (if (char-equal (preceding-char) ?\()
- (setq marking-diary-entry t)
- (setq marking-diary-entry nil))
- (re-search-backward "(")
- (let ((sexp-start (point))
- (sexp)
- (entry)
- (entry-start)
- (line-start))
- (forward-sexp)
- (setq sexp (buffer-substring-no-properties sexp-start (point)))
- (save-excursion
- (re-search-backward "\^M\\|\n\\|\\`")
- (setq line-start (point)))
- (forward-char 1)
- (if (and (or (char-equal (preceding-char) ?\^M)
- (char-equal (preceding-char) ?\n))
- (not (looking-at " \\|\^I")))
- (progn;; Diary entry consists only of the sexp
- (backward-char 1)
- (setq entry ""))
- (setq entry-start (point))
- (re-search-forward "\^M\\|\n" nil t)
- (while (looking-at " \\|\^I")
- (re-search-forward "\^M\\|\n" nil t))
- (backward-char 1)
- (setq entry (buffer-substring-no-properties entry-start (point)))
- (while (string-match "[\^M]" entry)
- (aset entry (match-beginning 0) ?\n )))
- (calendar-for-loop date from first-date to last-date do
- (if (diary-sexp-entry sexp entry
- (calendar-gregorian-from-absolute date))
- (mark-visible-calendar-date
- (calendar-gregorian-from-absolute date))))))))
-
-(defun mark-included-diary-files ()
- "Mark the diary entries from other diary files with those of the diary file.
-This function is suitable for use as the `mark-diary-entries-hook'; it enables
-you to use shared diary files together with your own. The files included are
-specified in the diary-file by lines of this form:
- #include \"filename\"
-This is recursive; that is, #include directives in diary files thus included
-are obeyed. You can change the `#include' to some other string by
-changing the variable `diary-include-string'."
- (goto-char (point-min))
- (while (re-search-forward
- (concat
- "\\(\\`\\|\^M\\|\n\\)"
- (regexp-quote diary-include-string)
- " \"\\([^\"]*\\)\"")
- nil t)
- (let ((diary-file (substitute-in-file-name
- (buffer-substring-no-properties
- (match-beginning 2) (match-end 2))))
- (mark-diary-entries-hook 'mark-included-diary-files))
- (if (file-exists-p diary-file)
- (if (file-readable-p diary-file)
- (progn
- (mark-diary-entries)
- (kill-buffer (find-buffer-visiting diary-file)))
- (beep)
- (message "Can't read included diary file %s" diary-file)
- (sleep-for 2))
- (beep)
- (message "Can't find included diary file %s" diary-file)
- (sleep-for 2))))
- (goto-char (point-min)))
-
-(defun mark-calendar-days-named (dayname)
- "Mark all dates in the calendar window that are day DAYNAME of the week.
-0 means all Sundays, 1 means all Mondays, and so on."
- (save-excursion
- (set-buffer calendar-buffer)
- (let ((prev-month displayed-month)
- (prev-year displayed-year)
- (succ-month displayed-month)
- (succ-year displayed-year)
- (last-day)
- (day))
- (increment-calendar-month succ-month succ-year 1)
- (increment-calendar-month prev-month prev-year -1)
- (setq day (calendar-absolute-from-gregorian
- (calendar-nth-named-day 1 dayname prev-month prev-year)))
- (setq last-day (calendar-absolute-from-gregorian
- (calendar-nth-named-day -1 dayname succ-month succ-year)))
- (while (<= day last-day)
- (mark-visible-calendar-date (calendar-gregorian-from-absolute day))
- (setq day (+ day 7))))))
-
-(defun mark-calendar-date-pattern (month day year)
- "Mark all dates in the calendar window that conform to MONTH/DAY/YEAR.
-A value of 0 in any position is a wildcard."
- (save-excursion
- (set-buffer calendar-buffer)
- (let ((m displayed-month)
- (y displayed-year))
- (increment-calendar-month m y -1)
- (calendar-for-loop i from 0 to 2 do
- (mark-calendar-month m y month day year)
- (increment-calendar-month m y 1)))))
-
-(defun mark-calendar-month (month year p-month p-day p-year)
- "Mark dates in the MONTH/YEAR that conform to pattern P-MONTH/P_DAY/P-YEAR.
-A value of 0 in any position of the pattern is a wildcard."
- (if (or (and (= month p-month)
- (or (= p-year 0) (= year p-year)))
- (and (= p-month 0)
- (or (= p-year 0) (= year p-year))))
- (if (= p-day 0)
- (calendar-for-loop
- i from 1 to (calendar-last-day-of-month month year) do
- (mark-visible-calendar-date (list month i year)))
- (mark-visible-calendar-date (list month p-day year)))))
-
-(defun sort-diary-entries ()
- "Sort the list of diary entries by time of day."
- (setq diary-entries-list (sort diary-entries-list 'diary-entry-compare)))
-
-(defun diary-entry-compare (e1 e2)
- "Returns t if E1 is earlier than E2."
- (or (calendar-date-compare e1 e2)
- (and (calendar-date-equal (car e1) (car e2))
- (< (diary-entry-time (car (cdr e1)))
- (diary-entry-time (car (cdr e2)))))))
-
-(defun diary-entry-time (s)
- "Time at the beginning of the string S in a military-style integer.
-For example, returns 1325 for 1:25pm. Returns -9999 if no time is recognized.
-The recognized forms are XXXX or X:XX or XX:XX (military time), XXam or XXpm,
-and XX:XXam or XX:XXpm."
- (cond ((string-match;; Military time
- "^[ \t]*\\([0-9]?[0-9]\\):?\\([0-9][0-9]\\)\\(\\>\\|[^ap]\\)" s)
- (+ (* 100 (string-to-int
- (substring s (match-beginning 1) (match-end 1))))
- (string-to-int (substring s (match-beginning 2) (match-end 2)))))
- ((string-match;; Hour only XXam or XXpm
- "^[ \t]*\\([0-9]?[0-9]\\)\\([ap]\\)m\\>" s)
- (+ (* 100 (% (string-to-int
- (substring s (match-beginning 1) (match-end 1)))
- 12))
- (if (string-equal "a"
- (substring s (match-beginning 2) (match-end 2)))
- 0 1200)))
- ((string-match;; Hour and minute XX:XXam or XX:XXpm
- "^[ \t]*\\([0-9]?[0-9]\\):\\([0-9][0-9]\\)\\([ap]\\)m\\>" s)
- (+ (* 100 (% (string-to-int
- (substring s (match-beginning 1) (match-end 1)))
- 12))
- (string-to-int (substring s (match-beginning 2) (match-end 2)))
- (if (string-equal "a"
- (substring s (match-beginning 3) (match-end 3)))
- 0 1200)))
- (t -9999)));; Unrecognizable
-
-(defun list-sexp-diary-entries (date)
- "Add sexp entries for DATE from the diary file to `diary-entries-list'.
-Also, Make them visible in the diary file. Returns t if any entries were
-found.
-
-Sexp diary entries must be prefaced by a `sexp-diary-entry-symbol' (normally
-`%%'). The form of a sexp diary entry is
-
- %%(SEXP) ENTRY
-
-Both ENTRY and DATE are globally available when the SEXP is evaluated. If the
-SEXP yields the value nil, the diary entry does not apply. If it yields a
-non-nil value, ENTRY will be taken to apply to DATE; if the non-nil value is a
-string, that string will be the diary entry in the fancy diary display.
-
-For example, the following diary entry will apply to the 21st of the month
-if it is a weekday and the Friday before if the 21st is on a weekend:
-
- &%%(let ((dayname (calendar-day-of-week date))
- (day (extract-calendar-day date)))
- (or
- (and (= day 21) (memq dayname '(1 2 3 4 5)))
- (and (memq day '(19 20)) (= dayname 5)))
- ) UIUC pay checks deposited
-
-A number of built-in functions are available for this type of diary entry:
-
- %%(diary-date MONTH DAY YEAR) text
- Entry applies if date is MONTH, DAY, YEAR if
- `european-calendar-style' is nil, and DAY, MONTH, YEAR if
- `european-calendar-style' is t. DAY, MONTH, and YEAR
- can be lists of integers, the constant t, or an integer.
- The constant t means all values.
-
- %%(diary-float MONTH DAYNAME N) text
- Entry will appear on the Nth DAYNAME of MONTH.
- (DAYNAME=0 means Sunday, 1 means Monday, and so on;
- if N is negative it counts backward from the end of
- the month. MONTH can be a list of months, a single
- month, or t to specify all months.
-
- %%(diary-block M1 D1 Y1 M2 D2 Y2) text
- Entry will appear on dates between M1/D1/Y1 and M2/D2/Y2,
- inclusive. (If `european-calendar-style' is t, the
- order of the parameters should be changed to D1, M1, Y1,
- D2, M2, Y2.)
-
- %%(diary-anniversary MONTH DAY YEAR) text
- Entry will appear on anniversary dates of MONTH DAY, YEAR.
- (If `european-calendar-style' is t, the order of the
- parameters should be changed to DAY, MONTH, YEAR.) Text
- can contain %d or %d%s; %d will be replaced by the number
- of years since the MONTH DAY, YEAR and %s will be replaced
- by the ordinal ending of that number (that is, `st', `nd',
- `rd' or `th', as appropriate. The anniversary of February
- 29 is considered to be March 1 in a non-leap year.
-
- %%(diary-cyclic N MONTH DAY YEAR) text
- Entry will appear every N days, starting MONTH DAY, YEAR.
- (If `european-calendar-style' is t, the order of the
- parameters should be changed to N, DAY, MONTH, YEAR.) Text
- can contain %d or %d%s; %d will be replaced by the number
- of repetitions since the MONTH DAY, YEAR and %s will
- be replaced by the ordinal ending of that number (that is,
- `st', `nd', `rd' or `th', as appropriate.
-
- %%(diary-remind SEXP DAYS &optional MARKING) text
- Entry is a reminder for diary sexp SEXP. DAYS is either a
- single number or a list of numbers indicating the number(s)
- of days before the event that the warning(s) should occur.
- If the current date is (one of) DAYS before the event
- indicated by EXPR, then a suitable message (as specified
- by `diary-remind-message') appears. In addition to the
- reminders beforehand, the diary entry also appears on
- the date itself. If optional MARKING is non-nil then the
- *reminders* are marked on the calendar. Marking of
- reminders is independent of whether the entry *itself* is
- a marking or nonmarking one.
-
- %%(diary-day-of-year)
- Diary entries giving the day of the year and the number of
- days remaining in the year will be made every day. Note
- that since there is no text, it makes sense only if the
- fancy diary display is used.
-
- %%(diary-iso-date)
- Diary entries giving the corresponding ISO commercial date
- will be made every day. Note that since there is no text,
- it makes sense only if the fancy diary display is used.
-
- %%(diary-french-date)
- Diary entries giving the corresponding French Revolutionary
- date will be made every day. Note that since there is no
- text, it makes sense only if the fancy diary display is used.
-
- %%(diary-islamic-date)
- Diary entries giving the corresponding Islamic date will be
- made every day. Note that since there is no text, it
- makes sense only if the fancy diary display is used.
-
- %%(diary-hebrew-date)
- Diary entries giving the corresponding Hebrew date will be
- made every day. Note that since there is no text, it
- makes sense only if the fancy diary display is used.
-
- %%(diary-astro-day-number) Diary entries giving the corresponding
- astronomical (Julian) day number will be made every day.
- Note that since there is no text, it makes sense only if the
- fancy diary display is used.
-
- %%(diary-julian-date) Diary entries giving the corresponding
- Julian date will be made every day. Note that since
- there is no text, it makes sense only if the fancy diary
- display is used.
-
- %%(diary-sunrise-sunset)
- Diary entries giving the local times of sunrise and sunset
- will be made every day. Note that since there is no text,
- it makes sense only if the fancy diary display is used.
- Floating point required.
-
- %%(diary-phases-of-moon)
- Diary entries giving the times of the phases of the moon
- will be when appropriate. Note that since there is no text,
- it makes sense only if the fancy diary display is used.
- Floating point required.
-
- %%(diary-yahrzeit MONTH DAY YEAR) text
- Text is assumed to be the name of the person; the date is
- the date of death on the *civil* calendar. The diary entry
- will appear on the proper Hebrew-date anniversary and on the
- day before. (If `european-calendar-style' is t, the order
- of the parameters should be changed to DAY, MONTH, YEAR.)
-
- %%(diary-rosh-hodesh)
- Diary entries will be made on the dates of Rosh Hodesh on
- the Hebrew calendar. Note that since there is no text, it
- makes sense only if the fancy diary display is used.
-
- %%(diary-parasha)
- Diary entries giving the weekly parasha will be made on
- every Saturday. Note that since there is no text, it
- makes sense only if the fancy diary display is used.
-
- %%(diary-omer)
- Diary entries giving the omer count will be made every day
- from Passover to Shavuot. Note that since there is no text,
- it makes sense only if the fancy diary display is used.
-
-Marking these entries is *extremely* time consuming, so these entries are
-best if they are nonmarking."
- (let* ((mark (regexp-quote diary-nonmarking-symbol))
- (sexp-mark (regexp-quote sexp-diary-entry-symbol))
- (s-entry (concat "\\(\\`\\|\^M\\|\n\\)" mark "?" sexp-mark "("))
- (entry-found))
- (goto-char (point-min))
- (while (re-search-forward s-entry nil t)
- (backward-char 1)
- (let ((sexp-start (point))
- (sexp)
- (entry)
- (entry-start)
- (line-start))
- (forward-sexp)
- (setq sexp (buffer-substring-no-properties sexp-start (point)))
- (save-excursion
- (re-search-backward "\^M\\|\n\\|\\`")
- (setq line-start (point)))
- (forward-char 1)
- (if (and (or (char-equal (preceding-char) ?\^M)
- (char-equal (preceding-char) ?\n))
- (not (looking-at " \\|\^I")))
- (progn;; Diary entry consists only of the sexp
- (backward-char 1)
- (setq entry ""))
- (setq entry-start (point))
- (re-search-forward "\^M\\|\n" nil t)
- (while (looking-at " \\|\^I")
- (re-search-forward "\^M\\|\n" nil t))
- (backward-char 1)
- (setq entry (buffer-substring-no-properties entry-start (point)))
- (while (string-match "[\^M]" entry)
- (aset entry (match-beginning 0) ?\n )))
- (let ((diary-entry (diary-sexp-entry sexp entry date)))
- (if diary-entry
- (subst-char-in-region line-start (point) ?\^M ?\n t))
- (add-to-diary-list date diary-entry)
- (setq entry-found (or entry-found diary-entry)))))
- entry-found))
-
-(defun diary-sexp-entry (sexp entry date)
- "Process a SEXP diary ENTRY for DATE."
- (let ((result (if calendar-debug-sexp
- (let ((stack-trace-on-error t))
- (eval (car (read-from-string sexp))))
- (condition-case nil
- (eval (car (read-from-string sexp)))
- (error
- (beep)
- (message "Bad sexp at line %d in %s: %s"
- (save-excursion
- (save-restriction
- (narrow-to-region 1 (point))
- (goto-char (point-min))
- (let ((lines 1))
- (while (re-search-forward "\n\\|\^M" nil t)
- (setq lines (1+ lines)))
- lines)))
- diary-file sexp)
- (sleep-for 2))))))
- (if (stringp result)
- result
- (if result
- entry
- nil))))
-
-(defun diary-date (month day year)
- "Specific date(s) diary entry.
-Entry applies if date is MONTH, DAY, YEAR if `european-calendar-style' is nil,
-and DAY, MONTH, YEAR if `european-calendar-style' is t. DAY, MONTH, and YEAR
-can be lists of integers, the constant t, or an integer. The constant t means
-all values."
- (let* ((dd (if european-calendar-style
- month
- day))
- (mm (if european-calendar-style
- day
- month))
- (m (extract-calendar-month date))
- (y (extract-calendar-year date))
- (d (extract-calendar-day date)))
- (if (and
- (or (and (listp dd) (memq d dd))
- (equal d dd)
- (eq dd t))
- (or (and (listp mm) (memq m mm))
- (equal m mm)
- (eq mm t))
- (or (and (listp year) (memq y year))
- (equal y year)
- (eq year t)))
- entry)))
-
-(defun diary-block (m1 d1 y1 m2 d2 y2)
- "Block diary entry.
-Entry applies if date is between two dates. Order of the parameters is
-M1, D1, Y1, M2, D2, Y2 `european-calendar-style' is nil, and
-D1, M1, Y1, D2, M2, Y2 if `european-calendar-style' is t."
- (let ((date1 (calendar-absolute-from-gregorian
- (if european-calendar-style
- (list d1 m1 y1)
- (list m1 d1 y1))))
- (date2 (calendar-absolute-from-gregorian
- (if european-calendar-style
- (list d2 m2 y2)
- (list m2 d2 y2))))
- (d (calendar-absolute-from-gregorian date)))
- (if (and (<= date1 d) (<= d date2))
- entry)))
-
-(defun diary-float (month dayname n)
- "Floating diary entry--entry applies if date is the nth dayname of month.
-Parameters are MONTH, DAYNAME, N. MONTH can be a list of months, the constant
-t, or an integer. The constant t means all months. If N is negative, count
-backward from the end of the month."
- (let ((m (extract-calendar-month date))
- (y (extract-calendar-year date)))
- (if (and
- (or (and (listp month) (memq m month))
- (equal m month)
- (eq month t))
- (calendar-date-equal date (calendar-nth-named-day n dayname m y)))
- entry)))
-
-(defun diary-anniversary (month day year)
- "Anniversary diary entry.
-Entry applies if date is the anniversary of MONTH, DAY, YEAR if
-`european-calendar-style' is nil, and DAY, MONTH, YEAR if
-`european-calendar-style' is t. Diary entry can contain `%d' or `%d%s'; the
-%d will be replaced by the number of years since the MONTH DAY, YEAR and the
-%s will be replaced by the ordinal ending of that number (that is, `st', `nd',
-`rd' or `th', as appropriate. The anniversary of February 29 is considered
-to be March 1 in non-leap years."
- (let* ((d (if european-calendar-style
- month
- day))
- (m (if european-calendar-style
- day
- month))
- (y (extract-calendar-year date))
- (diff (- y year)))
- (if (and (= m 2) (= d 29) (not (calendar-leap-year-p y)))
- (setq m 3
- d 1))
- (if (and (> diff 0) (calendar-date-equal (list m d y) date))
- (format entry diff (diary-ordinal-suffix diff)))))
-
-(defun diary-cyclic (n month day year)
- "Cycle diary entry--entry applies every N days starting at MONTH, DAY, YEAR.
-If `european-calendar-style' is t, parameters are N, DAY, MONTH, YEAR.
-ENTRY can contain `%d' or `%d%s'; the %d will be replaced by the number of
-years since the MONTH DAY, YEAR and the %s will be replaced by the ordinal
-ending of that number (that is, `st', `nd', `rd' or `th', as appropriate."
- (let* ((d (if european-calendar-style
- month
- day))
- (m (if european-calendar-style
- day
- month))
- (diff (- (calendar-absolute-from-gregorian date)
- (calendar-absolute-from-gregorian
- (list m d year))))
- (cycle (/ diff n)))
- (if (and (>= diff 0) (zerop (% diff n)))
- (format entry cycle (diary-ordinal-suffix cycle)))))
-
-(defun diary-ordinal-suffix (n)
- "Ordinal suffix for N. (That is, `st', `nd', `rd', or `th', as appropriate.)"
- (if (or (memq (% n 100) '(11 12 13))
- (< 3 (% n 10)))
- "th"
- (aref ["th" "st" "nd" "rd"] (% n 10))))
-
-(defun diary-day-of-year ()
- "Day of year and number of days remaining in the year of date diary entry."
- (calendar-day-of-year-string date))
-
-(defvar diary-remind-message
- '("Reminder: Only "
- (if (= 0 (% days 7))
- (concat (int-to-string (/ days 7)) (if (= 7 days) " week" " weeks"))
- (concat (int-to-string days) (if (= 1 days) " day" " days")))
- " until "
- diary-entry)
- "*Pseudo-pattern giving form of reminder messages in the fancy diary
-display.
-
-Used by the function `diary-remind', a pseudo-pattern is a list of
-expressions that can involve the keywords `days' (a number), `date' (a list of
-month, day, year), and `diary-entry' (a string).")
-
-(defun diary-remind (sexp days &optional marking)
- "Provide a reminder of a diary entry.
-SEXP is a diary-sexp. DAYS is either a single number or a list of numbers
-indicating the number(s) of days before the event that the warning(s) should
-occur on. If the current date is (one of) DAYS before the event indicated by
-SEXP, then a suitable message (as specified by `diary-remind-message' is
-returned.
-
-In addition to the reminders beforehand, the diary entry also appears on
-the date itself.
-
-If optional parameter MARKING is non-nil then the reminders are marked on the
-calendar. Marking of reminders is independent of whether the entry itself is
-a marking or nonmarking one."
- (let ((diary-entry))
- (if (or (not marking-diary-entries) marking)
- (cond
- ((integerp days)
- (let ((date (calendar-gregorian-from-absolute
- (+ (calendar-absolute-from-gregorian date) days))))
- (if (setq diary-entry (eval sexp))
- (setq diary-entry (mapconcat 'eval diary-remind-message "")))))
- ((and (listp days) days)
- (setq diary-entry (diary-remind sexp (car days) marking))
- (if (not diary-entry)
- (setq diary-entry (diary-remind sexp (cdr days) marking))))))
- (or diary-entry
- (and (or (not marking-diary-entries) marking-diary-entry)
- (eval sexp)))))
-
-(defun add-to-diary-list (date string)
- "Add the entry (DATE STRING) to `diary-entries-list'.
-Do nothing if DATE or STRING is nil."
- (and date string
- (setq diary-entries-list
- (append diary-entries-list (list (list date string))))))
-
-(defun make-diary-entry (string &optional nonmarking file)
- "Insert a diary entry STRING which may be NONMARKING in FILE.
-If omitted, NONMARKING defaults to nil and FILE defaults to diary-file."
- (find-file-other-window
- (substitute-in-file-name (if file file diary-file)))
- (goto-char (point-max))
- (insert
- (if (bolp) "" "\n")
- (if nonmarking diary-nonmarking-symbol "")
- string " "))
-
-(defun insert-diary-entry (arg)
- "Insert a diary entry for the date indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (make-diary-entry (calendar-date-string (calendar-cursor-to-date t) t t)
- arg))
-
-(defun insert-weekly-diary-entry (arg)
- "Insert a weekly diary entry for the day of the week indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (make-diary-entry (calendar-day-name (calendar-cursor-to-date t))
- arg))
-
-(defun insert-monthly-diary-entry (arg)
- "Insert a monthly diary entry for the day of the month indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " * ")
- '("* " day))))
- (make-diary-entry (calendar-date-string (calendar-cursor-to-date t) t)
- arg)))
-
-(defun insert-yearly-diary-entry (arg)
- "Insert an annual diary entry for the day of the year indicated by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " " monthname)
- '(monthname " " day))))
- (make-diary-entry (calendar-date-string (calendar-cursor-to-date t) t)
- arg)))
-
-(defun insert-anniversary-diary-entry (arg)
- "Insert an anniversary diary entry for the date given by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " " month " " year)
- '(month " " day " " year))))
- (make-diary-entry
- (format "%s(diary-anniversary %s)"
- sexp-diary-entry-symbol
- (calendar-date-string (calendar-cursor-to-date t) nil t))
- arg)))
-
-(defun insert-block-diary-entry (arg)
- "Insert a block diary entry for the days between the point and marked date.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " " month " " year)
- '(month " " day " " year)))
- (cursor (calendar-cursor-to-date t))
- (mark (or (car calendar-mark-ring)
- (error "No mark set in this buffer")))
- (start)
- (end))
- (if (< (calendar-absolute-from-gregorian mark)
- (calendar-absolute-from-gregorian cursor))
- (setq start mark
- end cursor)
- (setq start cursor
- end mark))
- (make-diary-entry
- (format "%s(diary-block %s %s)"
- sexp-diary-entry-symbol
- (calendar-date-string start nil t)
- (calendar-date-string end nil t))
- arg)))
-
-(defun insert-cyclic-diary-entry (arg)
- "Insert a cyclic diary entry starting at the date given by point.
-Prefix arg will make the entry nonmarking."
- (interactive "P")
- (let* ((calendar-date-display-form
- (if european-calendar-style
- '(day " " month " " year)
- '(month " " day " " year))))
- (make-diary-entry
- (format "%s(diary-cyclic %d %s)"
- sexp-diary-entry-symbol
- (calendar-read "Repeat every how many days: "
- '(lambda (x) (> x 0)))
- (calendar-date-string (calendar-cursor-to-date t) nil t))
- arg)))
-
-(provide 'diary-lib)
-
-;;; diary-lib.el ends here
diff --git a/lisp/calendar/holidays.el b/lisp/calendar/holidays.el
deleted file mode 100644
index cb5b3a1d8cb..00000000000
--- a/lisp/calendar/holidays.el
+++ /dev/null
@@ -1,384 +0,0 @@
-;;; holidays.el --- holiday functions for the calendar package
-
-;; Copyright (C) 1989, 1990, 1992, 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: holidays, calendar
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the holiday features as described
-;; in calendar.el.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;; Technical details of all the calendrical calculations can be found in
-;; ``Calendrical Calculations'' by Nachum Dershowitz and Edward M. Reingold,
-;; Software--Practice and Experience, Volume 20, Number 9 (September, 1990),
-;; pages 899-928. ``Calendrical Calculations, Part II: Three Historical
-;; Calendars'' by E. M. Reingold, N. Dershowitz, and S. M. Clamen,
-;; Software--Practice and Experience, Volume 23, Number 4 (April, 1993),
-;; pages 383-404.
-
-;; Hard copies of these two papers can be obtained by sending email to
-;; reingold@cs.uiuc.edu with the SUBJECT "send-paper-cal" (no quotes) and
-;; the message BODY containing your mailing address (snail).
-
-;;; Code:
-
-(require 'calendar)
-
-(autoload 'holiday-julian "cal-julian"
- "Holiday on MONTH, DAY (Julian) called STRING."
- t)
-
-(autoload 'holiday-hebrew "cal-hebrew"
- "Holiday on MONTH, DAY (Hebrew) called STRING."
- t)
-
-(autoload 'holiday-rosh-hashanah-etc "cal-hebrew"
- "List of dates related to Rosh Hashanah, as visible in calendar window."
- t)
-
-(autoload 'holiday-hanukkah "cal-hebrew"
- "List of dates related to Hanukkah, as visible in calendar window."
- t)
-
-(autoload 'holiday-passover-etc "cal-hebrew"
- "List of dates related to Passover, as visible in calendar window."
- t)
-
-(autoload 'holiday-tisha-b-av-etc "cal-hebrew"
- "List of dates around Tisha B'Av, as visible in calendar window."
- t)
-
-(autoload 'holiday-islamic "cal-islam"
- "Holiday on MONTH, DAY (Islamic) called STRING."
- t)
-
-(autoload 'holiday-chinese-new-year "cal-china"
- "Date of Chinese New Year."
- t)
-
-(autoload 'solar-equinoxes-solstices "solar"
- "Date and time of equinoxes and solstices, if visible in the calendar window.
-Requires floating point."
- t)
-
-(defun holidays (&optional arg)
- "Display the holidays for last month, this month, and next month.
-If called with an optional prefix argument, prompts for month and year.
-
-This function is suitable for execution in a .emacs file."
- (interactive "P")
- (save-excursion
- (let* ((completion-ignore-case t)
- (date (if arg
- (calendar-read-date t)
- (calendar-current-date)))
- (displayed-month (extract-calendar-month date))
- (displayed-year (extract-calendar-year date)))
- (list-calendar-holidays))))
-
-(defun check-calendar-holidays (date)
- "Check the list of holidays for any that occur on DATE.
-The value returned is a list of strings of relevant holiday descriptions.
-The holidays are those in the list calendar-holidays."
- (let* ((displayed-month (extract-calendar-month date))
- (displayed-year (extract-calendar-year date))
- (h (calendar-holiday-list))
- (holiday-list))
- (while h
- (if (calendar-date-equal date (car (car h)))
- (setq holiday-list (append holiday-list (cdr (car h)))))
- (setq h (cdr h)))
- holiday-list))
-
-(defun calendar-cursor-holidays ()
- "Find holidays for the date specified by the cursor in the calendar window."
- (interactive)
- (message "Checking holidays...")
- (let* ((date (calendar-cursor-to-date t))
- (date-string (calendar-date-string date))
- (holiday-list (check-calendar-holidays date))
- (holiday-string (mapconcat 'identity holiday-list "; "))
- (msg (format "%s: %s" date-string holiday-string)))
- (if (not holiday-list)
- (message "No holidays known for %s" date-string)
- (if (<= (length msg) (frame-width))
- (message "%s" msg)
- (set-buffer (get-buffer-create holiday-buffer))
- (setq buffer-read-only nil)
- (calendar-set-mode-line date-string)
- (erase-buffer)
- (insert (mapconcat 'identity holiday-list "\n"))
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- (setq buffer-read-only t)
- (display-buffer holiday-buffer)
- (message "Checking holidays...done")))))
-
-(defun mark-calendar-holidays ()
- "Mark notable days in the calendar window."
- (interactive)
- (setq mark-holidays-in-calendar t)
- (message "Marking holidays...")
- (let ((holiday-list (calendar-holiday-list)))
- (while holiday-list
- (mark-visible-calendar-date
- (car (car holiday-list)) calendar-holiday-marker)
- (setq holiday-list (cdr holiday-list))))
- (message "Marking holidays...done"))
-
-(defun list-calendar-holidays ()
- "Create a buffer containing the holidays for the current calendar window.
-The holidays are those in the list calendar-notable-days. Returns t if any
-holidays are found, nil if not."
- (interactive)
- (message "Looking up holidays...")
- (let ((holiday-list (calendar-holiday-list))
- (m1 displayed-month)
- (y1 displayed-year)
- (m2 displayed-month)
- (y2 displayed-year))
- (if (not holiday-list)
- (progn
- (message "Looking up holidays...none found")
- nil)
- (set-buffer (get-buffer-create holiday-buffer))
- (setq buffer-read-only nil)
- (increment-calendar-month m1 y1 -1)
- (increment-calendar-month m2 y2 1)
- (calendar-set-mode-line
- (if (= y1 y2)
- (format "Notable Dates from %s to %s, %d%%-"
- (calendar-month-name m1) (calendar-month-name m2) y2)
- (format "Notable Dates from %s, %d to %s, %d%%-"
- (calendar-month-name m1) y1 (calendar-month-name m2) y2)))
- (erase-buffer)
- (insert
- (mapconcat
- '(lambda (x) (concat (calendar-date-string (car x))
- ": " (car (cdr x))))
- holiday-list "\n"))
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- (setq buffer-read-only t)
- (display-buffer holiday-buffer)
- (message "Looking up holidays...done")
- t)))
-
-(defun calendar-holiday-list ()
- "Form the list of holidays that occur on dates in the calendar window.
-The holidays are those in the list calendar-holidays."
- (let ((p calendar-holidays)
- (holiday-list))
- (while p
- (let* ((holidays
- (if calendar-debug-sexp
- (let ((stack-trace-on-error t))
- (eval (car p)))
- (condition-case nil
- (eval (car p))
- (error (beep)
- (message "Bad holiday list item: %s" (car p))
- (sleep-for 2))))))
- (if holidays
- (setq holiday-list (append holidays holiday-list))))
- (setq p (cdr p)))
- (setq holiday-list (sort holiday-list 'calendar-date-compare))))
-
-;; Below are the functions that calculate the dates of holidays; these
-;; are eval'ed in the function calendar-holiday-list. If you
-;; write other such functions, be sure to imitate the style used below.
-;; Remember that each function must return a list of items of the form
-;; ((month day year) string) of VISIBLE dates in the calendar window.
-
-(defun holiday-fixed (month day string)
- "Holiday on MONTH, DAY (Gregorian) called STRING.
-If MONTH, DAY is visible, the value returned is the list (((MONTH DAY year)
-STRING)). Returns nil if it is not visible in the current calendar window."
- (let ((m displayed-month)
- (y displayed-year))
- (increment-calendar-month m y (- 11 month))
- (if (> m 9)
- (list (list (list month day y) string)))))
-
-(defun holiday-float (month dayname n string &optional day)
- "Holiday on MONTH, DAYNAME (Nth occurrence, Gregorian) called STRING.
-If the Nth DAYNAME in MONTH is visible, the value returned is the list
-\(((MONTH DAY year) STRING)).
-
-If N<0, count backward from the end of MONTH.
-
-An optional parameter DAY means the Nth DAYNAME after/before MONTH DAY.
-
-Returns nil if it is not visible in the current calendar window."
- (let ((m displayed-month)
- (y displayed-year))
- (increment-calendar-month m y (- 11 month))
- (if (> m 9)
- (list (list (calendar-nth-named-day n dayname month y day) string)))))
-
-(defun holiday-sexp (sexp string)
- "Sexp holiday for dates in the calendar window.
-SEXP is an expression in variable `year' evaluates to `date'.
-
-STRING is an expression in `date' that evaluates to the holiday description
-of `date'.
-
-If `date' is visible in the calendar window, the holiday STRING is on that
-date. If date is nil, or if the date is not visible, there is no holiday."
- (let ((m displayed-month)
- (y displayed-year))
- (increment-calendar-month m y -1)
- (filter-visible-calendar-holidays
- (append
- (let* ((year y)
- (date (eval sexp))
- (string (if date (eval string))))
- (list (list date string)))
- (let* ((year (1+ y))
- (date (eval sexp))
- (string (if date (eval string))))
- (list (list date string)))))))
-
-(defun holiday-advent ()
- "Date of Advent, if visible in calendar window."
- (let ((year displayed-year)
- (month displayed-month))
- (increment-calendar-month month year -1)
- (let ((advent (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before 0
- (calendar-absolute-from-gregorian
- (list 12 3 year))))))
- (if (calendar-date-is-visible-p advent)
- (list (list advent "Advent"))))))
-
-(defun holiday-easter-etc ()
- "List of dates related to Easter, as visible in calendar window."
- (if (and (> displayed-month 5) (not all-christian-calendar-holidays))
- nil;; Ash Wednesday, Good Friday, and Easter are not visible.
- (let* ((century (1+ (/ displayed-year 100)))
- (shifted-epact ;; Age of moon for April 5...
- (% (+ 14 (* 11 (% displayed-year 19));; ...by Nicaean rule
- (- ;; ...corrected for the Gregorian century rule
- (/ (* 3 century) 4))
- (/ ;; ...corrected for Metonic cycle inaccuracy.
- (+ 5 (* 8 century)) 25)
- (* 30 century));; Keeps value positive.
- 30))
- (adjusted-epact ;; Adjust for 29.5 day month.
- (if (or (= shifted-epact 0)
- (and (= shifted-epact 1) (< 10 (% displayed-year 19))))
- (1+ shifted-epact)
- shifted-epact))
- (paschal-moon ;; Day after the full moon on or after March 21.
- (- (calendar-absolute-from-gregorian (list 4 19 displayed-year))
- adjusted-epact))
- (abs-easter (calendar-dayname-on-or-before 0 (+ paschal-moon 7)))
- (mandatory
- (list
- (list (calendar-gregorian-from-absolute abs-easter)
- "Easter Sunday")
- (list (calendar-gregorian-from-absolute (- abs-easter 2))
- "Good Friday")
- (list (calendar-gregorian-from-absolute (- abs-easter 46))
- "Ash Wednesday")))
- (optional
- (list
- (list (calendar-gregorian-from-absolute (- abs-easter 63))
- "Septuagesima Sunday")
- (list (calendar-gregorian-from-absolute (- abs-easter 56))
- "Sexagesima Sunday")
- (list (calendar-gregorian-from-absolute (- abs-easter 49))
- "Shrove Sunday")
- (list (calendar-gregorian-from-absolute (- abs-easter 48))
- "Shrove Monday")
- (list (calendar-gregorian-from-absolute (- abs-easter 47))
- "Shrove Tuesday")
- (list (calendar-gregorian-from-absolute (- abs-easter 14))
- "Passion Sunday")
- (list (calendar-gregorian-from-absolute (- abs-easter 7))
- "Palm Sunday")
- (list (calendar-gregorian-from-absolute (- abs-easter 3))
- "Maundy Thursday")
- (list (calendar-gregorian-from-absolute (+ abs-easter 35))
- "Rogation Sunday")
- (list (calendar-gregorian-from-absolute (+ abs-easter 39))
- "Ascension Day")
- (list (calendar-gregorian-from-absolute (+ abs-easter 49))
- "Pentecost (Whitsunday)")
- (list (calendar-gregorian-from-absolute (+ abs-easter 50))
- "Whitmonday")
- (list (calendar-gregorian-from-absolute (+ abs-easter 56))
- "Trinity Sunday")
- (list (calendar-gregorian-from-absolute (+ abs-easter 60))
- "Corpus Christi")))
- (output-list
- (filter-visible-calendar-holidays mandatory)))
- (if all-christian-calendar-holidays
- (setq output-list
- (append
- (filter-visible-calendar-holidays optional)
- output-list)))
- output-list)))
-
-(defun holiday-greek-orthodox-easter ()
- "Date of Easter according to the rule of the Council of Nicaea."
- (let ((m displayed-month)
- (y displayed-year))
- (increment-calendar-month m y 1)
- (let* ((julian-year
- (extract-calendar-year
- (calendar-julian-from-absolute
- (calendar-absolute-from-gregorian
- (list m (calendar-last-day-of-month m y) y)))))
- (shifted-epact ;; Age of moon for April 5.
- (% (+ 14
- (* 11 (% julian-year 19)))
- 30))
- (paschal-moon ;; Day after full moon on or after March 21.
- (- (calendar-absolute-from-julian (list 4 19 julian-year))
- shifted-epact))
- (nicaean-easter;; Sunday following the Paschal moon
- (calendar-gregorian-from-absolute
- (calendar-dayname-on-or-before 0 (+ paschal-moon 7)))))
- (if (calendar-date-is-visible-p nicaean-easter)
- (list (list nicaean-easter "Pascha (Greek Orthodox Easter)"))))))
-
-(defun filter-visible-calendar-holidays (l)
- "Return a list of all visible holidays of those on L."
- (let ((visible)
- (p l))
- (while p
- (and (car (car p))
- (calendar-date-is-visible-p (car (car p)))
- (setq visible (append (list (car p)) visible)))
- (setq p (cdr p)))
- visible))
-
-(provide 'holidays)
-
-;;; holidays.el ends here
diff --git a/lisp/calendar/lunar.el b/lisp/calendar/lunar.el
deleted file mode 100644
index 67a472ebaab..00000000000
--- a/lisp/calendar/lunar.el
+++ /dev/null
@@ -1,391 +0,0 @@
-;;; lunar.el --- calendar functions for phases of the moon.
-
-;; Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Keywords: calendar
-;; Human-Keywords: moon, lunar phases, calendar, diary
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements lunar phases for calendar.el and
-;; diary.el.
-
-;; Based on ``Astronomical Formulae for Calculators,'' 3rd ed., by Jean Meeus,
-;; Willmann-Bell, Inc., 1985 and ``Astronomical Algorithms'' by Jean Meeus,
-;; Willmann-Bell, Inc., 1991.
-;;
-;; WARNING: The calculations will be accurate only to within a few minutes.
-
-;; The author would be delighted to have an astronomically more sophisticated
-;; person rewrite the code for the lunar calculations in this file!
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(if (fboundp 'atan)
- (require 'lisp-float-type)
- (error "Lunar calculations impossible since floating point is unavailable."))
-
-(require 'solar)
-
-(defun lunar-phase-list (month year)
- "List of lunar phases for three months starting with Gregorian MONTH, YEAR."
- (let ((end-month month)
- (end-year year)
- (start-month month)
- (start-year year))
- (increment-calendar-month end-month end-year 3)
- (increment-calendar-month start-month start-year -1)
- (let* ((end-date (list (list end-month 1 end-year)))
- (start-date (list (list start-month
- (calendar-last-day-of-month
- start-month start-year)
- start-year)))
- (index (* 4
- (truncate
- (* 12.3685
- (+ year
- ( / (calendar-day-number (list month 1 year))
- 366.0)
- -1900)))))
- (new-moon (lunar-phase index))
- (list))
- (while (calendar-date-compare new-moon end-date)
- (if (calendar-date-compare start-date new-moon)
- (setq list (append list (list new-moon))))
- (setq index (1+ index))
- (setq new-moon (lunar-phase index)))
- list)))
-
-(defun lunar-phase (index)
- "Local date and time of lunar phase INDEX.
-Integer below INDEX/4 gives the lunation number, counting from Jan 1, 1900;
-remainder mod 4 gives the phase: 0 new moon, 1 first quarter, 2 full moon,
-3 last quarter."
- (let* ((phase (mod index 4))
- (index (/ index 4.0))
- (time (/ index 1236.85))
- (date (+ (calendar-absolute-from-gregorian '(1 0.5 1900))
- 0.75933
- (* 29.53058868 index)
- (* 0.0001178 time time)
- (* -0.000000155 time time time)
- (* 0.00033
- (solar-sin-degrees (+ 166.56
- (* 132.87 time)
- (* -0.009173 time time))))))
- (sun-anomaly (mod
- (+ 359.2242
- (* 29.105356 index)
- (* -0.0000333 time time)
- (* -0.00000347 time time time))
- 360.0))
- (moon-anomaly (mod
- (+ 306.0253
- (* 385.81691806 index)
- (* 0.0107306 time time)
- (* 0.00001236 time time time))
- 360.0))
- (moon-lat (mod
- (+ 21.2964
- (* 390.67050646 index)
- (* -0.0016528 time time)
- (* -0.00000239 time time time))
- 360.0))
- (adjustment
- (if (memq phase '(0 2))
- (+ (* (- 0.1734 (* 0.000393 time))
- (solar-sin-degrees sun-anomaly))
- (* 0.0021 (solar-sin-degrees (* 2 sun-anomaly)))
- (* -0.4068 (solar-sin-degrees moon-anomaly))
- (* 0.0161 (solar-sin-degrees (* 2 moon-anomaly)))
- (* -0.0004 (solar-sin-degrees (* 3 moon-anomaly)))
- (* 0.0104 (solar-sin-degrees (* 2 moon-lat)))
- (* -0.0051 (solar-sin-degrees (+ sun-anomaly moon-anomaly)))
- (* -0.0074 (solar-sin-degrees (- sun-anomaly moon-anomaly)))
- (* 0.0004 (solar-sin-degrees (+ (* 2 moon-lat) sun-anomaly)))
- (* -0.0004 (solar-sin-degrees (- (* 2 moon-lat) sun-anomaly)))
- (* -0.0006 (solar-sin-degrees
- (+ (* 2 moon-lat) moon-anomaly)))
- (* 0.0010 (solar-sin-degrees (- (* 2 moon-lat) moon-anomaly)))
- (* 0.0005 (solar-sin-degrees
- (+ (* 2 moon-anomaly) sun-anomaly))))
- (+ (* (- 0.1721 (* 0.0004 time))
- (solar-sin-degrees sun-anomaly))
- (* 0.0021 (solar-sin-degrees (* 2 sun-anomaly)))
- (* -0.6280 (solar-sin-degrees moon-anomaly))
- (* 0.0089 (solar-sin-degrees (* 2 moon-anomaly)))
- (* -0.0004 (solar-sin-degrees (* 3 moon-anomaly)))
- (* 0.0079 (solar-sin-degrees (* 2 moon-lat)))
- (* -0.0119 (solar-sin-degrees (+ sun-anomaly moon-anomaly)))
- (* -0.0047 (solar-sin-degrees (- sun-anomaly moon-anomaly)))
- (* 0.0003 (solar-sin-degrees (+ (* 2 moon-lat) sun-anomaly)))
- (* -0.0004 (solar-sin-degrees (- (* 2 moon-lat) sun-anomaly)))
- (* -0.0006 (solar-sin-degrees (+ (* 2 moon-lat) moon-anomaly)))
- (* 0.0021 (solar-sin-degrees (- (* 2 moon-lat) moon-anomaly)))
- (* 0.0003 (solar-sin-degrees
- (+ (* 2 moon-anomaly) sun-anomaly)))
- (* 0.0004 (solar-sin-degrees
- (- sun-anomaly (* 2 moon-anomaly))))
- (* -0.0003 (solar-sin-degrees
- (+ (* 2 sun-anomaly) moon-anomaly))))))
- (adj (+ 0.0028
- (* -0.0004 (solar-cosine-degrees
- sun-anomaly))
- (* 0.0003 (solar-cosine-degrees
- moon-anomaly))))
- (adjustment (cond ((= phase 1) (+ adjustment adj))
- ((= phase 2) (- adjustment adj))
- (t adjustment)))
- (date (+ date adjustment))
- (date (+ date (/ (- calendar-time-zone
- (solar-ephemeris-correction
- (extract-calendar-year
- (calendar-gregorian-from-absolute
- (truncate date)))))
- 60.0 24.0)))
- (time (* 24 (- date (truncate date))))
- (date (calendar-gregorian-from-absolute (truncate date)))
- (adj (dst-adjust-time date time)))
- (list (car adj) (apply 'solar-time-string (cdr adj)) phase)))
-
-(defun lunar-phase-name (phase)
- "Name of lunar PHASE.
-0 = new moon, 1 = first quarter, 2 = full moon, 3 = last quarter."
- (cond ((= 0 phase) "New Moon")
- ((= 1 phase) "First Quarter Moon")
- ((= 2 phase) "Full Moon")
- ((= 3 phase) "Last Quarter Moon")))
-
-(defun calendar-phases-of-moon ()
- "Create a buffer with the lunar phases for the current calendar window."
- (interactive)
- (message "Computing phases of the moon...")
- (let ((m1 displayed-month)
- (y1 displayed-year)
- (m2 displayed-month)
- (y2 displayed-year))
- (increment-calendar-month m1 y1 -1)
- (increment-calendar-month m2 y2 1)
- (set-buffer (get-buffer-create lunar-phases-buffer))
- (setq buffer-read-only nil)
- (calendar-set-mode-line
- (if (= y1 y2)
- (format "Phases of the Moon from %s to %s, %d%%-"
- (calendar-month-name m1) (calendar-month-name m2) y2)
- (format "Phases of the Moon from %s, %d to %s, %d%%-"
- (calendar-month-name m1) y1 (calendar-month-name m2) y2)))
- (erase-buffer)
- (insert
- (mapconcat
- '(lambda (x)
- (let ((date (car x))
- (time (car (cdr x)))
- (phase (car (cdr (cdr x)))))
- (concat (calendar-date-string date)
- ": "
- (lunar-phase-name phase)
- " "
- time)))
- (lunar-phase-list m1 y1) "\n"))
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- (setq buffer-read-only t)
- (display-buffer lunar-phases-buffer)
- (message "Computing phases of the moon...done")))
-
-;;;###autoload
-(defun phases-of-moon (&optional arg)
- "Display the quarters of the moon for last month, this month, and next month.
-If called with an optional prefix argument, prompts for month and year.
-
-This function is suitable for execution in a .emacs file."
- (interactive "P")
- (save-excursion
- (let* ((date (if arg
- (calendar-read-date t)
- (calendar-current-date)))
- (displayed-month (extract-calendar-month date))
- (displayed-year (extract-calendar-year date)))
- (calendar-phases-of-moon))))
-
-(defun diary-phases-of-moon ()
- "Moon phases diary entry."
- (let* ((index (* 4
- (truncate
- (* 12.3685
- (+ (extract-calendar-year date)
- ( / (calendar-day-number date)
- 366.0)
- -1900)))))
- (phase (lunar-phase index)))
- (while (calendar-date-compare phase (list date))
- (setq index (1+ index))
- (setq phase (lunar-phase index)))
- (if (calendar-date-equal (car phase) date)
- (concat (lunar-phase-name (car (cdr (cdr phase)))) " "
- (car (cdr phase))))))
-
-
-;; For the Chinese calendar the calculations for the new moon need to be more
-;; accurate than those above, so we use more terms in the approximation.
-
-(defun lunar-new-moon-time (k)
- "Astronomical (Julian) day number of K th new moon."
- (let* ((T (/ k 1236.85))
- (T2 (* T T))
- (T3 (* T T T))
- (T4 (* T2 T2))
- (JDE (+ 2451550.09765
- (* 29.530588853 k)
- (* 0.0001337 T2)
- (* -0.000000150 T3)
- (* 0.00000000073 T4)))
- (E (- 1 (* 0.002516 T) (* 0.0000074 T2)))
- (sun-anomaly (+ 2.5534
- (* 29.10535669 k)
- (* -0.0000218 T2)
- (* -0.00000011 T3)))
- (moon-anomaly (+ 201.5643
- (* 385.81693528 k)
- (* 0.0107438 T2)
- (* 0.00001239 T3)
- (* -0.000000058 T4)))
- (moon-argument (+ 160.7108
- (* 390.67050274 k)
- (* -0.0016341 T2)
- (* -0.00000227 T3)
- (* 0.000000011 T4)))
- (omega (+ 124.7746
- (* -1.56375580 k)
- (* 0.0020691 T2)
- (* 0.00000215 T3)))
- (A1 (+ 299.77 (* 0.107408 k) (* -0.009173 T2)))
- (A2 (+ 251.88 (* 0.016321 k)))
- (A3 (+ 251.83 (* 26.641886 k)))
- (A4 (+ 349.42 (* 36.412478 k)))
- (A5 (+ 84.66 (* 18.206239 k)))
- (A6 (+ 141.74 (* 53.303771 k)))
- (A7 (+ 207.14 (* 2.453732 k)))
- (A8 (+ 154.84 (* 7.306860 k)))
- (A9 (+ 34.52 (* 27.261239 k)))
- (A10 (+ 207.19 (* 0.121824 k)))
- (A11 (+ 291.34 (* 1.844379 k)))
- (A12 (+ 161.72 (* 24.198154 k)))
- (A13 (+ 239.56 (* 25.513099 k)))
- (A14 (+ 331.55 (* 3.592518 k)))
- (correction
- (+ (* -0.40720 (solar-sin-degrees moon-anomaly))
- (* 0.17241 E (solar-sin-degrees sun-anomaly))
- (* 0.01608 (solar-sin-degrees (* 2 moon-anomaly)))
- (* 0.01039 (solar-sin-degrees (* 2 moon-argument)))
- (* 0.00739 E (solar-sin-degrees (- moon-anomaly sun-anomaly)))
- (* -0.00514 E (solar-sin-degrees (+ moon-anomaly sun-anomaly)))
- (* 0.00208 E E (solar-sin-degrees (* 2 sun-anomaly)))
- (* -0.00111 (solar-sin-degrees
- (- moon-anomaly (* 2 moon-argument))))
- (* -0.00057 (solar-sin-degrees
- (+ moon-anomaly (* 2 moon-argument))))
- (* 0.00056 E (solar-sin-degrees
- (+ (* 2 moon-anomaly) sun-anomaly)))
- (* -0.00042 (solar-sin-degrees (* 3 moon-anomaly)))
- (* 0.00042 E (solar-sin-degrees
- (+ sun-anomaly (* 2 moon-argument))))
- (* 0.00038 E (solar-sin-degrees
- (- sun-anomaly (* 2 moon-argument))))
- (* -0.00024 E (solar-sin-degrees
- (- (* 2 moon-anomaly) sun-anomaly)))
- (* -0.00017 (solar-sin-degrees omega))
- (* -0.00007 (solar-sin-degrees
- (+ moon-anomaly (* 2 sun-anomaly))))
- (* 0.00004 (solar-sin-degrees
- (- (* 2 moon-anomaly) (* 2 moon-argument))))
- (* 0.00004 (solar-sin-degrees (* 3 sun-anomaly)))
- (* 0.00003 (solar-sin-degrees (+ moon-anomaly sun-anomaly
- (* -2 moon-argument))))
- (* 0.00003 (solar-sin-degrees
- (+ (* 2 moon-anomaly) (* 2 moon-argument))))
- (* -0.00003 (solar-sin-degrees (+ moon-anomaly sun-anomaly
- (* 2 moon-argument))))
- (* 0.00003 (solar-sin-degrees (- moon-anomaly sun-anomaly
- (* -2 moon-argument))))
- (* -0.00002 (solar-sin-degrees (- moon-anomaly sun-anomaly
- (* 2 moon-argument))))
- (* -0.00002 (solar-sin-degrees
- (+ (* 3 moon-anomaly) sun-anomaly)))
- (* 0.00002 (solar-sin-degrees (* 4 moon-anomaly)))))
- (additional
- (+ (* 0.000325 (solar-sin-degrees A1))
- (* 0.000165 (solar-sin-degrees A2))
- (* 0.000164 (solar-sin-degrees A3))
- (* 0.000126 (solar-sin-degrees A4))
- (* 0.000110 (solar-sin-degrees A5))
- (* 0.000062 (solar-sin-degrees A6))
- (* 0.000060 (solar-sin-degrees A7))
- (* 0.000056 (solar-sin-degrees A8))
- (* 0.000047 (solar-sin-degrees A9))
- (* 0.000042 (solar-sin-degrees A10))
- (* 0.000040 (solar-sin-degrees A11))
- (* 0.000037 (solar-sin-degrees A12))
- (* 0.000035 (solar-sin-degrees A13))
- (* 0.000023 (solar-sin-degrees A14))))
- (newJDE (+ JDE correction additional)))
- (+ newJDE
- (- (solar-ephemeris-correction
- (extract-calendar-year
- (calendar-gregorian-from-absolute
- (floor (calendar-absolute-from-astro newJDE))))))
- (/ calendar-time-zone 60.0 24.0))))
-
-(defun lunar-new-moon-on-or-after (d)
- "Astronomical (Julian) day number of first new moon on or after astronomical
-\(Julian) day number d. The fractional part is the time of day.
-
-The date and time are local time, including any daylight savings rules,
-as governed by the values of calendar-daylight-savings-starts,
-calendar-daylight-savings-starts-time, calendar-daylight-savings-ends,
-calendar-daylight-savings-ends-time, calendar-daylight-time-offset, and
-calendar-time-zone."
- (let* ((date (calendar-gregorian-from-absolute
- (floor (calendar-absolute-from-astro d))))
- (year (+ (extract-calendar-year date)
- (/ (calendar-day-number date) 365.25)))
- (k (floor (* (- year 2000.0) 12.3685)))
- (date (lunar-new-moon-time k)))
- (while (< date d)
- (setq k (1+ k))
- (setq date (lunar-new-moon-time k)))
- (let* ((a-date (calendar-absolute-from-astro date))
- (time (* 24 (- a-date (truncate a-date))))
- (date (calendar-gregorian-from-absolute (truncate a-date)))
- (adj (dst-adjust-time date time)))
- (calendar-astro-from-absolute
- (+ (calendar-absolute-from-gregorian (car adj))
- (/ (car (cdr adj)) 24.0))))))
-
-(provide 'lunar)
-
-;;; lunar.el ends here
diff --git a/lisp/calendar/solar.el b/lisp/calendar/solar.el
deleted file mode 100644
index 936f78501b1..00000000000
--- a/lisp/calendar/solar.el
+++ /dev/null
@@ -1,1045 +0,0 @@
-;;; solar.el --- calendar functions for solar events.
-
-;; Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc.
-
-;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
-;; Denis B. Roegel <Denis.Roegel@loria.fr>
-;; Keywords: calendar
-;; Human-Keywords: sunrise, sunset, equinox, solstice, calendar, diary,
-;; holidays
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This collection of functions implements the features of calendar.el,
-;; diary.el, and holiday.el that deal with times of day, sunrise/sunset, and
-;; equinoxes/solstices.
-
-;; Based on the ``Almanac for Computers 1984,'' prepared by the Nautical
-;; Almanac Office, United States Naval Observatory, Washington, 1984, on
-;; ``Astronomical Formulae for Calculators,'' 3rd ed., by Jean Meeus,
-;; Willmann-Bell, Inc., 1985, on ``Astronomical Algorithms'' by Jean Meeus,
-;; Willmann-Bell, Inc., 1991, and on ``Planetary Programs and Tables from
-;; -4000 to +2800'' by Pierre Bretagnon and Jean-Louis Simon, Willmann-Bell,
-;; Inc., 1986.
-
-;;
-;; Accuracy:
-;; 1. Sunrise/sunset times will be accurate to the minute for years
-;; 1951--2050. For other years the times will be within +/- 2 minutes.
-;;
-;; 2. Equinox/solstice times will be accurate to the minute for years
-;; 1951--2050. For other years the times will be within +/- 1 minute.
-
-;; 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@cs.uiuc.edu 1304 West Springfield Avenue
-;; Urbana, Illinois 61801
-
-;;; Code:
-
-(if (fboundp 'atan)
- (require 'lisp-float-type)
- (error "Solar/lunar calculations impossible since floating point is unavailable."))
-
-(require 'cal-dst)
-(require 'cal-julian)
-
-;;;###autoload
-(defvar calendar-time-display-form
- '(12-hours ":" minutes am-pm
- (if time-zone " (") time-zone (if time-zone ")"))
- "*The pseudo-pattern that governs the way a time of day is formatted.
-
-A pseudo-pattern is a list of expressions that can involve the keywords
-`12-hours', `24-hours', and `minutes', all numbers in string form,
-and `am-pm' and `time-zone', both alphabetic strings.
-
-For example, the form
-
- '(24-hours \":\" minutes
- (if time-zone \" (\") time-zone (if time-zone \")\"))
-
-would give military-style times like `21:07 (UTC)'.")
-
-;;;###autoload
-(defvar calendar-latitude nil
- "*Latitude of `calendar-location-name' in degrees.
-
-The value can be either a decimal fraction (one place of accuracy is
-sufficient), + north, - south, such as 40.7 for New York City, or the value
-can be a vector [degrees minutes north/south] such as [40 50 north] for New
-York City.
-
-This variable should be set in `site-start'.el.")
-
-;;;###autoload
-(defvar calendar-longitude nil
- "*Longitude of `calendar-location-name' in degrees.
-
-The value can be either a decimal fraction (one place of accuracy is
-sufficient), + east, - west, such as -73.9 for New York City, or the value
-can be a vector [degrees minutes east/west] such as [73 55 west] for New
-York City.
-
-This variable should be set in `site-start'.el.")
-
-(defsubst calendar-latitude ()
- "Convert calendar-latitude to a signed decimal fraction, if needed."
- (if (numberp calendar-latitude)
- calendar-latitude
- (let ((lat (+ (aref calendar-latitude 0)
- (/ (aref calendar-latitude 1) 60.0))))
- (if (equal (aref calendar-latitude 2) 'north)
- lat
- (- lat)))))
-
-(defsubst calendar-longitude ()
- "Convert calendar-longitude to a signed decimal fraction, if needed."
- (if (numberp calendar-longitude)
- calendar-longitude
- (let ((long (+ (aref calendar-longitude 0)
- (/ (aref calendar-longitude 1) 60.0))))
- (if (equal (aref calendar-longitude 2) 'east)
- long
- (- long)))))
-
-;;;###autoload
-(defvar calendar-location-name
- '(let ((float-output-format "%.1f"))
- (format "%s%s, %s%s"
- (if (numberp calendar-latitude)
- (abs calendar-latitude)
- (+ (aref calendar-latitude 0)
- (/ (aref calendar-latitude 1) 60.0)))
- (if (numberp calendar-latitude)
- (if (> calendar-latitude 0) "N" "S")
- (if (equal (aref calendar-latitude 2) 'north) "N" "S"))
- (if (numberp calendar-longitude)
- (abs calendar-longitude)
- (+ (aref calendar-longitude 0)
- (/ (aref calendar-longitude 1) 60.0)))
- (if (numberp calendar-longitude)
- (if (> calendar-longitude 0) "E" "W")
- (if (equal (aref calendar-longitude 2) 'east) "E" "W"))))
- "*Expression evaluating to name of `calendar-longitude', calendar-latitude'.
-For example, \"New York City\". Default value is just the latitude, longitude
-pair.
-
-This variable should be set in `site-start'.el.")
-
-(defvar solar-error 0.5
-"*Tolerance (in minutes) for sunrise/sunset calculations.
-
-A larger value makes the calculations for sunrise/sunset faster, but less
-accurate. The default is half a minute (30 seconds), so that sunrise/sunset
-times will be correct to the minute.
-
-It is useless to set the value smaller than 4*delta, where delta is the
-accuracy in the longitude of the sun (given by the function
-`solar-ecliptic-coordinates') in degrees since (delta/360) x (86400/60) = 4 x
-delta. At present, delta = 0.01 degrees, so the value of the variable
-`solar-error' should be at least 0.04 minutes (about 2.5 seconds).")
-
-(defvar solar-n-hemi-seasons
- '("Vernal Equinox" "Summer Solstice" "Autumnal Equinox" "Winter Solstice")
- "List of season changes for the northern hemisphere.")
-
-(defvar solar-s-hemi-seasons
- '("Autumnal Equinox" "Winter Solstice" "Vernal Equinox" "Summer Solstice")
- "List of season changes for the southern hemisphere.")
-
-(defvar solar-sidereal-time-greenwich-midnight
- nil
- "Sidereal time at Greenwich at midnight (universal time).")
-
-(defvar solar-spring-or-summer-season nil
- "T if spring or summer and nil otherwise.
-Needed for polar areas, in order to know whether the day lasts 0 or 24 hours.")
-
-(defun solar-setup ()
- "Prompt user for latitude, longitude, and time zone."
- (beep)
- (if (not calendar-longitude)
- (setq calendar-longitude
- (solar-get-number
- "Enter longitude (decimal fraction; + east, - west): ")))
- (if (not calendar-latitude)
- (setq calendar-latitude
- (solar-get-number
- "Enter latitude (decimal fraction; + north, - south): ")))
- (if (not calendar-time-zone)
- (setq calendar-time-zone
- (solar-get-number
- "Enter difference from Coordinated Universal Time (in minutes): "))))
-
-(defun solar-get-number (prompt)
- "Return a number from the minibuffer, prompting with PROMPT.
-Returns nil if nothing was entered."
- (let ((x (read-string prompt "")))
- (if (not (string-equal x ""))
- (string-to-int x))))
-
-;; The condition-case stuff is needed to catch bogus arithmetic
-;; exceptions that occur on some machines (like Sparcs)
-(defun solar-sin-degrees (x)
- (condition-case nil
- (sin (degrees-to-radians (mod x 360.0)))
- (solar-sin-degrees x)))
-(defun solar-cosine-degrees (x)
- (condition-case nil
- (cos (degrees-to-radians (mod x 360.0)))
- (solar-cosine-degrees x)))
-(defun solar-tangent-degrees (x)
- (condition-case nil
- (tan (degrees-to-radians (mod x 360.0)))
- (solar-tangent-degrees x)))
-
-(defun solar-xy-to-quadrant (x y)
- "Determines the quadrant of the point X, Y."
- (if (> x 0)
- (if (> y 0) 1 4)
- (if (> y 0) 2 3)))
-
-(defun solar-degrees-to-quadrant (angle)
- "Determines the quadrant of ANGLE."
- (1+ (floor (mod angle 360) 90)))
-
-(defun solar-arctan (x quad)
- "Arctangent of X in quadrant QUAD."
- (let ((deg (radians-to-degrees (atan x))))
- (cond ((equal quad 2) (+ deg 180))
- ((equal quad 3) (+ deg 180))
- ((equal quad 4) (+ deg 360))
- (t deg))))
-
-(defun solar-atn2 (x y)
- "Arctan of point X, Y."
- (if (= x 0)
- (if (> y 0) 90 270)
- (solar-arctan (/ y x) x)))
-
-(defun solar-arccos (x)
- "Arcos of X."
- (let ((y (sqrt (- 1 (* x x)))))
- (solar-atn2 x y)))
-
-(defun solar-arcsin (y)
- "Arcsin of Y."
- (let ((x (sqrt (- 1 (* y y)))))
- (solar-atn2 x y)
- ))
-
-(defsubst solar-degrees-to-hours (degrees)
- "Convert DEGREES to hours."
- (/ degrees 15.0))
-
-(defsubst solar-hours-to-days (hour)
- "Convert HOUR to decimal fraction of a day."
- (/ hour 24.0))
-
-(defun solar-right-ascension (longitude obliquity)
- "Right ascension of the sun, in hours, given LONGITUDE and OBLIQUITY.
-Both arguments are in degrees."
- (solar-degrees-to-hours
- (solar-arctan
- (* (solar-cosine-degrees obliquity) (solar-tangent-degrees longitude))
- (solar-degrees-to-quadrant longitude))))
-
-(defun solar-declination (longitude obliquity)
- "Declination of the sun, in degrees, given LONGITUDE and OBLIQUITY.
-Both arguments are in degrees."
- (solar-arcsin
- (* (solar-sin-degrees obliquity)
- (solar-sin-degrees longitude))))
-
-(defun solar-sunrise-and-sunset (time latitude longitude)
- "Sunrise, sunset and length of day.
-Parameters are the midday TIME and the LATITUDE, LONGITUDE of the location.
-
-TIME is a pair with the first component being the number of Julian centuries
-elapsed at 0 Universal Time, and the second component being the universal
-time. For instance, the pair corresponding to November 28, 1995 at 16 UT is
-\(-0.040945 16), -0.040945 being the number of julian centuries elapsed between
-Jan 1, 2000 at 12 UT and November 28, 1995 at 0 UT.
-
-Coordinates are included because this function is called with latitude=10
-degrees to find out if polar regions have 24 hours of sun or only night."
- (let* ((rise-time (solar-moment -1 latitude longitude time))
- (set-time (solar-moment 1 latitude longitude time))
- (day-length))
- (if (not (and rise-time set-time))
- (if (or (and (> latitude 0) solar-spring-or-summer-season)
- (and (< latitude 0) (not solar-spring-or-summer-season)))
- (setq day-length 24)
- (setq day-length 0))
- (setq day-length (- set-time rise-time)))
- (list (if rise-time (+ rise-time (/ calendar-time-zone 60.0)) nil)
- (if set-time (+ set-time (/ calendar-time-zone 60.0)) nil)
- day-length)))
-
-(defun solar-moment (direction latitude longitude time)
- "Sunrise/sunset at location.
-Sunrise if DIRECTION =-1 or sunset if =1 at LATITUDE, LONGITUDE, with midday
-being TIME.
-
-TIME is a pair with the first component being the number of Julian centuries
-elapsed at 0 Universal Time, and the second component being the universal
-time. For instance, the pair corresponding to November 28, 1995 at 16 UT is
-\(-0.040945 16), -0.040945 being the number of julian centuries elapsed between
-Jan 1, 2000 at 12 UT and November 28, 1995 at 0 UT.
-
-Uses binary search."
- (let* ((ut (car (cdr time)))
- (possible 1) ; we assume that rise or set are possible
- (utmin (+ ut (* direction 12.0)))
- (utmax ut) ; the time searched is between utmin and utmax
- ; utmin and utmax are in hours
- (utmoment-old 0.0) ; rise or set approximation
- (utmoment 1.0) ; rise or set approximation
- (hut 0) ; sun height at utmoment
- (t0 (car time))
- (hmin (car (cdr
- (solar-horizontal-coordinates (list t0 utmin)
- latitude longitude t))))
- (hmax (car (cdr
- (solar-horizontal-coordinates (list t0 utmax)
- latitude longitude t)))))
- ; -0.61 degrees is the height of the middle of the sun, when it rises
- ; or sets.
- (if (< hmin -0.61)
- (if (> hmax -0.61)
- (while ;(< i 20) ; we perform a simple dichotomy
- ; (> (abs (+ hut 0.61)) epsilon)
- (>= (abs (- utmoment utmoment-old))
- (/ solar-error 60))
- (setq utmoment-old utmoment)
- (setq utmoment (/ (+ utmin utmax) 2))
- (setq hut (car (cdr
- (solar-horizontal-coordinates
- (list t0 utmoment) latitude longitude t))))
- (if (< hut -0.61) (setq utmin utmoment))
- (if (> hut -0.61) (setq utmax utmoment))
- )
- (setq possible 0)) ; the sun never rises
- (setq possible 0)) ; the sun never sets
- (if (equal possible 0) nil utmoment)))
-
-(defun solar-time-string (time time-zone)
- "Printable form for decimal fraction TIME in TIME-ZONE.
-Format used is given by `calendar-time-display-form'."
- (let* ((time (round (* 60 time)))
- (24-hours (/ time 60))
- (minutes (format "%02d" (% time 60)))
- (12-hours (format "%d" (1+ (% (+ 24-hours 11) 12))))
- (am-pm (if (>= 24-hours 12) "pm" "am"))
- (24-hours (format "%02d" 24-hours)))
- (mapconcat 'eval calendar-time-display-form "")))
-
-
-(defun solar-daylight (time)
- "Printable form for time expressed in hours."
- (format "%d:%02d"
- (floor time)
- (floor (* 60 (- time (floor time))))))
-
-(defun solar-exact-local-noon (date)
- "Date and Universal Time of local noon at *local date* date.
-
-The date may be different from the one asked for, but it will be the right
-local date. The second component of date should be an integer."
- (let* ((nd date)
- (ut (- 12.0 (/ (calendar-longitude) 15)))
- (te (solar-time-equation date ut)))
- (setq ut (- ut te))
- (if (>= ut 24)
- (progn
- (setq nd (list (car date) (+ 1 (car (cdr date)))
- (car (cdr (cdr date)))))
- (setq ut (- ut 24))))
- (if (< ut 0)
- (progn
- (setq nd (list (car date) (- (car (cdr date)) 1)
- (car (cdr (cdr date)))))
- (setq ut (+ ut 24))))
- (setq nd (calendar-gregorian-from-absolute
- (calendar-absolute-from-gregorian nd)))
- ; date standardization
- (list nd ut)))
-
-(defun solar-sunrise-sunset (date)
- "List of *local* times of sunrise, sunset, and daylight on Gregorian DATE.
-
-Corresponding value is nil if there is no sunrise/sunset."
- (let* (; first, get the exact moment of local noon.
- (exact-local-noon (solar-exact-local-noon date))
- ; get the the time from the 2000 epoch.
- (t0 (solar-julian-ut-centuries (car exact-local-noon)))
- ; store the sidereal time at Greenwich at midnight of UT time.
- ; find if summer or winter slightly above the equator
- (equator-rise-set
- (progn (setq solar-sidereal-time-greenwich-midnight
- (solar-sidereal-time t0))
- (solar-sunrise-and-sunset
- (list t0 (car (cdr exact-local-noon)))
- 10.0
- (calendar-longitude))))
- ; store the spring/summer information,
- ; compute sunrise and sunset (two first components of rise-set).
- ; length of day is the third component (it is only the difference
- ; between sunset and sunrise when there is a sunset and a sunrise)
- (rise-set
- (progn
- (setq solar-spring-or-summer-season
- (if (> (car (cdr (cdr equator-rise-set))) 12) 1 0))
- (solar-sunrise-and-sunset
- (list t0 (car (cdr exact-local-noon)))
- (calendar-latitude)
- (calendar-longitude))))
- (rise (car rise-set))
- (adj-rise (if rise (dst-adjust-time date rise) nil))
- (set (car (cdr rise-set)))
- (adj-set (if set (dst-adjust-time date set) nil))
- (length (car (cdr (cdr rise-set)))) )
- (list
- (and rise (calendar-date-equal date (car adj-rise)) (cdr adj-rise))
- (and set (calendar-date-equal date (car adj-set)) (cdr adj-set))
- (solar-daylight length))))
-
-(defun solar-sunrise-sunset-string (date)
- "String of *local* times of sunrise, sunset, and daylight on Gregorian DATE."
- (let ((l (solar-sunrise-sunset date)))
- (format
- "%s, %s at %s (%s hours daylight)"
- (if (car l)
- (concat "Sunrise " (apply 'solar-time-string (car l)))
- "No sunrise")
- (if (car (cdr l))
- (concat "sunset " (apply 'solar-time-string (car (cdr l))))
- "no sunset")
- (eval calendar-location-name)
- (car (cdr (cdr l))))))
-
-(defun solar-julian-ut-centuries (date)
- "Number of Julian centuries elapsed since 1 Jan, 2000 at noon U.T. for Gregorian DATE."
- (/ (- (calendar-absolute-from-gregorian date)
- (calendar-absolute-from-gregorian '(1 1.5 2000)))
- 36525.0))
-
-(defun solar-ephemeris-time(time)
- "Ephemeris Time at moment TIME.
-
-TIME is a pair with the first component being the number of Julian centuries
-elapsed at 0 Universal Time, and the second component being the universal
-time. For instance, the pair corresponding to November 28, 1995 at 16 UT is
-\(-0.040945 16), -0.040945 being the number of julian centuries elapsed between
-Jan 1, 2000 at 12 UT and November 28, 1995 at 0 UT.
-
-Result is in julian centuries of ephemeris time."
- (let* ((t0 (car time))
- (ut (car (cdr time)))
- (t1 (+ t0 (/ (/ ut 24.0) 36525)))
- (y (+ 2000 (* 100 t1)))
- (dt (* 86400 (solar-ephemeris-correction (floor y)))))
- (+ t1 (/ (/ dt 86400) 36525))))
-
-(defun solar-date-next-longitude (d l)
- "First moment on or after Julian day number D when sun's longitude is a
-multiple of L degrees at calendar-location-name with that location's
-local time (including any daylight savings rules).
-
-L must be an integer divisor of 360.
-
-Result is in local time expressed astronomical (Julian) day numbers.
-
-The values of calendar-daylight-savings-starts,
-calendar-daylight-savings-starts-time, calendar-daylight-savings-ends,
-calendar-daylight-savings-ends-time, calendar-daylight-time-offset, and
-calendar-time-zone are used to interpret local time."
- (let* ((long)
- (start d)
- (start-long (solar-longitude d))
- (next (mod (* l (1+ (floor (/ start-long l)))) 360))
- (end (+ d (* (/ l 360.0) 400)))
- (end-long (solar-longitude end)))
- (while ;; bisection search for nearest minute
- (< 0.00001 (- end start))
- ;; start <= d < end
- ;; start-long <= next < end-long when next != 0
- ;; when next = 0, we look for the discontinuity (start-long is near 360
- ;; and end-long is small (less than l).
- (setq d (/ (+ start end) 2.0))
- (setq long (solar-longitude d))
- (if (or (and (/= next 0) (< long next))
- (and (= next 0) (< l long)))
- (progn
- (setq start d)
- (setq start-long long))
- (setq end d)
- (setq end-long long)))
- (/ (+ start end) 2.0)))
-
-(defun solar-horizontal-coordinates
- (time latitude longitude for-sunrise-sunset)
- "Azimuth and height of the sun at TIME, LATITUDE, and LONGITUDE.
-
-TIME is a pair with the first component being the number of Julian centuries
-elapsed at 0 Universal Time, and the second component being the universal
-time. For instance, the pair corresponding to November 28, 1995 at 16 UT is
-\(-0.040945 16), -0.040945 being the number of julian centuries elapsed between
-Jan 1, 2000 at 12 UT and November 28, 1995 at 0 UT.
-
-The azimuth is given in degrees as well as the height (between -180 and 180)."
- (let* ((ut (car (cdr time)))
- (ec (solar-equatorial-coordinates time for-sunrise-sunset))
- (st (+ solar-sidereal-time-greenwich-midnight
- (* ut 1.00273790935)))
- (ah (- (* st 15) (* 15 (car ec)) (* -1 (calendar-longitude))))
- ; hour angle (in degrees)
- (de (car (cdr ec)))
- (azimuth (solar-atn2 (- (* (solar-cosine-degrees ah)
- (solar-sin-degrees latitude))
- (* (solar-tangent-degrees de)
- (solar-cosine-degrees latitude)))
- (solar-sin-degrees ah)))
- (height (solar-arcsin
- (+ (* (solar-sin-degrees latitude) (solar-sin-degrees de))
- (* (solar-cosine-degrees latitude)
- (solar-cosine-degrees de)
- (solar-cosine-degrees ah))))))
- (if (> height 180) (setq height (- height 360)))
- (list azimuth height)))
-
-(defun solar-equatorial-coordinates (time for-sunrise-sunset)
- "Right ascension (in hours) and declination (in degrees) of the sun at TIME.
-
-TIME is a pair with the first component being the number of Julian centuries
-elapsed at 0 Universal Time, and the second component being the universal
-time. For instance, the pair corresponding to November 28, 1995 at 16 UT is
-\(-0.040945 16), -0.040945 being the number of julian centuries elapsed between
-Jan 1, 2000 at 12 UT and November 28, 1995 at 0 UT."
- (let* ((tm (solar-ephemeris-time time))
- (ec (solar-ecliptic-coordinates tm for-sunrise-sunset)))
- (list (solar-right-ascension (car ec) (car (cdr ec)))
- (solar-declination (car ec) (car (cdr ec))))))
-
-(defun solar-ecliptic-coordinates (time for-sunrise-sunset)
- "Apparent longitude of the sun, ecliptic inclination, (both in degrees)
-equation of time (in hours) and nutation in longitude (in seconds)
-at moment `time', expressed in julian centuries of Ephemeris Time
-since January 1st, 2000, at 12 ET."
- (let* ((l (+ 280.46645
- (* 36000.76983 time)
- (* 0.0003032 time time))) ; sun mean longitude
- (ml (+ 218.3165
- (* 481267.8813 time))) ; moon mean longitude
- (m (+ 357.52910
- (* 35999.05030 time)
- (* -0.0001559 time time)
- (* -0.00000048 time time time))) ; sun mean anomaly
- (i (+ 23.43929111 (* -0.013004167 time)
- (* -0.00000016389 time time)
- (* 0.0000005036 time time time))); mean inclination
- (c (+ (* (+ 1.914600
- (* -0.004817 time)
- (* -0.000014 time time))
- (solar-sin-degrees m))
- (* (+ 0.019993 (* -0.000101 time))
- (solar-sin-degrees (* 2 m)))
- (* 0.000290
- (solar-sin-degrees (* 3 m))))) ; center equation
- (L (+ l c)) ; total longitude
- (omega (+ 125.04
- (* -1934.136 time))) ; longitude of moon's ascending node
- ; on the ecliptic
- (nut (if (not for-sunrise-sunset)
- (+ (* -17.20 (solar-sin-degrees omega))
- (* -1.32 (solar-sin-degrees (* 2 l)))
- (* -0.23 (solar-sin-degrees (* 2 ml)))
- (* 0.21 (solar-sin-degrees (* 2 omega))))
- nil))
- ; nut = nutation in longitude, measured in seconds of angle.
- (ecc (if (not for-sunrise-sunset)
- (+ 0.016708617
- (* -0.000042037 time)
- (* -0.0000001236 time time)) ; eccentricity of earth's orbit
- nil))
- (app (+ L
- -0.00569
- (* -0.00478
- (solar-sin-degrees omega)))) ; apparent longitude of sun
- (y (if (not for-sunrise-sunset)
- (* (solar-tangent-degrees (/ i 2))
- (solar-tangent-degrees (/ i 2)))
- nil))
- (time-eq (if (not for-sunrise-sunset)
- (/ (* 12 (+ (* y (solar-sin-degrees (* 2 l)))
- (* -2 ecc (solar-sin-degrees m))
- (* 4 ecc y (solar-sin-degrees m)
- (solar-cosine-degrees (* 2 l)))
- (* -0.5 y y (solar-sin-degrees (* 4 l)))
- (* -1.25 ecc ecc (solar-sin-degrees (* 2 m)))))
- 3.1415926535)
- nil)))
- ; equation of time, in hours
- (list app i time-eq nut)))
-
-(defun solar-longitude (d)
- "Longitude of sun on astronomical (Julian) day number D.
-Accurary is about 0.0006 degree (about 365.25*24*60*0.0006/360 = 1 minutes).
-
-The values of calendar-daylight-savings-starts,
-calendar-daylight-savings-starts-time, calendar-daylight-savings-ends,
-calendar-daylight-savings-ends-time, calendar-daylight-time-offset, and
-calendar-time-zone are used to interpret local time."
- (let* ((a-d (calendar-absolute-from-astro d))
- ;; get Universal Time
- (date (calendar-astro-from-absolute
- (- a-d
- (if (dst-in-effect a-d)
- (/ calendar-daylight-time-offset 24.0 60.0) 0)
- (/ calendar-time-zone 60.0 24.0))))
- ;; get Ephemeris Time
- (date (+ date (solar-ephemeris-correction
- (extract-calendar-year
- (calendar-gregorian-from-absolute
- (floor
- (calendar-absolute-from-astro
- date)))))))
- (U (/ (- date 2451545) 3652500))
- (longitude
- (+ 4.9353929
- (* 62833.1961680 U)
- (* 0.0000001
- (apply '+
- (mapcar '(lambda (x)
- (* (car x)
- (sin (mod
- (+ (car (cdr x))
- (* (car (cdr (cdr x))) U))
- (* 2 pi)))))
- solar-data-list)))))
- (aberration
- (* 0.0000001 (- (* 17 (cos (+ 3.10 (* 62830.14 U)))) 973)))
- (A1 (mod (+ 2.18 (* U (+ -3375.70 (* 0.36 U)))) (* 2 pi)))
- (A2 (mod (+ 3.51 (* U (+ 125666.39 (* 0.10 U)))) (* 2 pi)))
- (nutation (* -0.0000001 (+ (* 834 (sin A1)) (* 64 (sin A2))))))
- (mod (radians-to-degrees (+ longitude aberration nutation)) 360.0)))
-
-(defconst solar-data-list
- '((403406 4.721964 1.621043)
- (195207 5.937458 62830.348067)
- (119433 1.115589 62830.821524)
- (112392 5.781616 62829.634302)
- (3891 5.5474 125660.5691)
- (2819 1.5120 125660.984)
- (1721 4.1897 62832.4766)
- (0 1.163 0.813)
- (660 5.415 125659.31)
- (350 4.315 57533.85)
- (334 4.553 -33.931)
- (314 5.198 777137.715)
- (268 5.989 78604.191)
- (242 2.911 5.412)
- (234 1.423 39302.098)
- (158 0.061 -34.861)
- (132 2.317 115067.698)
- (129 3.193 15774.337)
- (114 2.828 5296.670)
- (99 0.52 58849.27)
- (93 4.65 5296.11)
- (86 4.35 -3980.70)
- (78 2.75 52237.69)
- (72 4.50 55076.47)
- (68 3.23 261.08)
- (64 1.22 15773.85)
- (46 0.14 188491.03)
- (38 3.44 -7756.55)
- (37 4.37 264.89)
- (32 1.14 117906.27)
- (29 2.84 55075.75)
- (28 5.96 -7961.39)
- (27 5.09 188489.81)
- (27 1.72 2132.19)
- (25 2.56 109771.03)
- (24 1.92 54868.56)
- (21 0.09 25443.93)
- (21 5.98 -55731.43)
- (20 4.03 60697.74)
- (18 4.47 2132.79)
- (17 0.79 109771.63)
- (14 4.24 -7752.82)
- (13 2.01 188491.91)
- (13 2.65 207.81)
- (13 4.98 29424.63)
- (12 0.93 -7.99)
- (10 2.21 46941.14)
- (10 3.59 -68.29)
- (10 1.50 21463.25)
- (10 2.55 157208.40)))
-
-(defun solar-ephemeris-correction (year)
- "Ephemeris time minus Universal Time during Gregorian year.
-Result is in days.
-
-For the years 1800-1987, the maximum error is 1.9 seconds.
-For the other years, the maximum error is about 30 seconds."
- (cond ((and (<= 1988 year) (< year 2020))
- (/ (+ year -2000 67.0) 60.0 60.0 24.0))
- ((and (<= 1900 year) (< year 1988))
- (let* ((theta (/ (- (calendar-astro-from-absolute
- (calendar-absolute-from-gregorian
- (list 7 1 year)))
- (calendar-astro-from-absolute
- (calendar-absolute-from-gregorian
- '(1 1 1900))))
- 36525.0))
- (theta2 (* theta theta))
- (theta3 (* theta2 theta))
- (theta4 (* theta2 theta2))
- (theta5 (* theta3 theta2)))
- (+ -0.00002
- (* 0.000297 theta)
- (* 0.025184 theta2)
- (* -0.181133 theta3)
- (* 0.553040 theta4)
- (* -0.861938 theta5)
- (* 0.677066 theta3 theta3)
- (* -0.212591 theta4 theta3))))
- ((and (<= 1800 year) (< year 1900))
- (let* ((theta (/ (- (calendar-astro-from-absolute
- (calendar-absolute-from-gregorian
- (list 7 1 year)))
- (calendar-astro-from-absolute
- (calendar-absolute-from-gregorian
- '(1 1 1900))))
- 36525.0))
- (theta2 (* theta theta))
- (theta3 (* theta2 theta))
- (theta4 (* theta2 theta2))
- (theta5 (* theta3 theta2)))
- (+ -0.000009
- (* 0.003844 theta)
- (* 0.083563 theta2)
- (* 0.865736 theta3)
- (* 4.867575 theta4)
- (* 15.845535 theta5)
- (* 31.332267 theta3 theta3)
- (* 38.291999 theta4 theta3)
- (* 28.316289 theta4 theta4)
- (* 11.636204 theta4 theta5)
- (* 2.043794 theta5 theta5))))
- ((and (<= 1620 year) (< year 1800))
- (let ((x (/ (- year 1600) 10.0)))
- (/ (+ (* 2.19167 x x) (* -40.675 x) 196.58333) 60.0 60.0 24.0)))
- (t (let* ((tmp (- (calendar-astro-from-absolute
- (calendar-absolute-from-gregorian
- (list 1 1 year)))
- 2382148))
- (second (- (/ (* tmp tmp) 41048480.0) 15)))
- (/ second 60.0 60.0 24.0)))))
-
-(defun solar-sidereal-time (t0)
- "Sidereal time (in hours) in Greenwich.
-
-At T0=Julian centuries of universal time.
-T0 must correspond to 0 hours UT."
- (let* ((mean-sid-time (+ 6.6973746
- (* 2400.051337 t0)
- (* 0.0000258622 t0 t0)
- (* -0.0000000017222 t0 t0 t0)))
- (et (solar-ephemeris-time (list t0 0.0)))
- (nut-i (solar-ecliptic-coordinates et nil))
- (nut (car (cdr (cdr (cdr nut-i))))) ; nutation
- (i (car (cdr nut-i)))) ; inclination
- (mod (+ (mod (+ mean-sid-time
- (/ (/ (* nut (solar-cosine-degrees i)) 15) 3600)) 24.0)
- 24.0)
- 24.0)))
-
-(defun solar-time-equation (date ut)
- "Equation of time expressed in hours at Gregorian DATE at Universal time UT."
- (let* ((et (solar-date-to-et date ut))
- (ec (solar-ecliptic-coordinates et nil)))
- (car (cdr (cdr ec)))))
-
-(defun solar-date-to-et (date ut)
- "Ephemeris Time at Gregorian DATE at Universal Time UT (in hours).
-Expressed in julian centuries of Ephemeris Time."
- (let ((t0 (solar-julian-ut-centuries date)))
- (solar-ephemeris-time (list t0 ut))))
-
-;;;###autoload
-(defun sunrise-sunset (&optional arg)
- "Local time of sunrise and sunset for today. Accurate to a few seconds.
-If called with an optional prefix argument, prompt for date.
-
-If called with an optional double prefix argument, prompt for longitude,
-latitude, time zone, and date, and always use standard time.
-
-This function is suitable for execution in a .emacs file."
- (interactive "p")
- (or arg (setq arg 1))
- (if (and (< arg 16)
- (not (and calendar-latitude calendar-longitude calendar-time-zone)))
- (solar-setup))
- (let* ((calendar-longitude
- (if (< arg 16) calendar-longitude
- (solar-get-number
- "Enter longitude (decimal fraction; + east, - west): ")))
- (calendar-latitude
- (if (< arg 16) calendar-latitude
- (solar-get-number
- "Enter latitude (decimal fraction; + north, - south): ")))
- (calendar-time-zone
- (if (< arg 16) calendar-time-zone
- (solar-get-number
- "Enter difference from Coordinated Universal Time (in minutes): ")))
- (calendar-location-name
- (if (< arg 16) calendar-location-name
- (let ((float-output-format "%.1f"))
- (format "%s%s, %s%s"
- (if (numberp calendar-latitude)
- (abs calendar-latitude)
- (+ (aref calendar-latitude 0)
- (/ (aref calendar-latitude 1) 60.0)))
- (if (numberp calendar-latitude)
- (if (> calendar-latitude 0) "N" "S")
- (if (equal (aref calendar-latitude 2) 'north) "N" "S"))
- (if (numberp calendar-longitude)
- (abs calendar-longitude)
- (+ (aref calendar-longitude 0)
- (/ (aref calendar-longitude 1) 60.0)))
- (if (numberp calendar-longitude)
- (if (> calendar-longitude 0) "E" "W")
- (if (equal (aref calendar-longitude 2) 'east)
- "E" "W"))))))
- (calendar-standard-time-zone-name
- (if (< arg 16) calendar-standard-time-zone-name
- (cond ((= calendar-time-zone 0) "UTC")
- ((< calendar-time-zone 0)
- (format "UTC%dmin" calendar-time-zone))
- (t (format "UTC+%dmin" calendar-time-zone)))))
- (calendar-daylight-savings-starts
- (if (< arg 16) calendar-daylight-savings-starts))
- (calendar-daylight-savings-ends
- (if (< arg 16) calendar-daylight-savings-ends))
- (date (if (< arg 4) (calendar-current-date) (calendar-read-date)))
- (date-string (calendar-date-string date t))
- (time-string (solar-sunrise-sunset-string date))
- (msg (format "%s: %s" date-string time-string))
- (one-window (one-window-p t)))
- (if (<= (length msg) (frame-width))
- (message "%s" msg)
- (with-output-to-temp-buffer "*temp*"
- (princ (concat date-string "\n" time-string)))
- (message "%s"
- (substitute-command-keys
- (if one-window
- (if pop-up-windows
- "Type \\[delete-other-windows] to remove temp window."
- "Type \\[switch-to-buffer] RET to remove temp window.")
- "Type \\[switch-to-buffer-other-window] RET to restore old contents of temp window."))))))
-
-(defun calendar-sunrise-sunset ()
- "Local time of sunrise and sunset for date under cursor.
-Accurate to a few seconds."
- (interactive)
- (if (not (and calendar-latitude calendar-longitude calendar-time-zone))
- (solar-setup))
- (let ((date (calendar-cursor-to-date t)))
- (message "%s: %s"
- (calendar-date-string date t t)
- (solar-sunrise-sunset-string date))))
-
-(defun diary-sunrise-sunset ()
- "Local time of sunrise and sunset as a diary entry.
-Accurate to a few seconds."
- (if (not (and calendar-latitude calendar-longitude calendar-time-zone))
- (solar-setup))
- (solar-sunrise-sunset-string date))
-
-(defun diary-sabbath-candles ()
- "Local time of candle lighting diary entry--applies if date is a Friday.
-No diary entry if there is no sunset on that date."
- (if (not (and calendar-latitude calendar-longitude calendar-time-zone))
- (solar-setup))
- (if (= (% (calendar-absolute-from-gregorian date) 7) 5);; Friday
- (let* ((sunset (car (cdr (solar-sunrise-sunset date))))
- (light (if sunset
- (cons (- (car sunset) (/ 18.0 60.0)) (cdr sunset)))))
- (if sunset
- (format "%s Sabbath candle lighting"
- (apply 'solar-time-string light))))))
-
-(defun solar-equinoxes/solstices (k year)
- "Date of equinox/solstice K for YEAR.
-K=0, spring equinox; K=1, summer solstice; K=2, fall equinox;
-K=3, winter solstice.
-RESULT is a gregorian local date.
-
-Accurate to less than a minute between 1951 and 2050."
- (let* ((JDE0 (solar-mean-equinoxes/solstices k year))
- (T (/ (- JDE0 2451545.0) 36525))
- (W (- (* 35999.373 T) 2.47))
- (Delta-lambda (+ 1 (* 0.0334 (solar-cosine-degrees W))
- (* 0.0007 (solar-cosine-degrees (* 2 W)))))
- (S (apply '+ (mapcar '(lambda(x)
- (* (car x) (solar-cosine-degrees
- (+ (* (car (cdr (cdr x))) T)
- (car (cdr x))))))
- solar-seasons-data)))
- (JDE (+ JDE0 (/ (* 0.00001 S) Delta-lambda)))
- (correction (+ 102.3 (* 123.5 T) (* 32.5 T T)))
- ; ephemeris time correction
- (JD (- JDE (/ correction 86400)))
- (date (calendar-gregorian-from-absolute (floor (- JD 1721424.5))))
- (time (- (- JD 0.5) (floor (- JD 0.5))))
- )
- (list (car date) (+ (car (cdr date)) time
- (/ (/ calendar-time-zone 60.0) 24.0))
- (car (cdr (cdr date))))))
-
-; from Meeus, 1991, page 166
-(defun solar-mean-equinoxes/solstices (k year)
- "Julian day of mean equinox/solstice K for YEAR.
-K=0, spring equinox; K=1, summer solstice; K=2, fall equinox; K=3, winter
-solstice. These formulas are only to be used between 1000 BC and 3000 AD."
- (let ((y (/ year 1000.0))
- (z (/ (- year 2000) 1000.0)))
- (if (< year 1000) ; actually between -1000 and 1000
- (cond ((equal k 0) (+ 1721139.29189
- (* 365242.13740 y)
- (* 0.06134 y y)
- (* 0.00111 y y y)
- (* -0.00071 y y y y)))
- ((equal k 1) (+ 1721233.25401
- (* 365241.72562 y)
- (* -0.05323 y y)
- (* 0.00907 y y y)
- (* 0.00025 y y y y)))
- ((equal k 2) (+ 1721325.70455
- (* 365242.49558 y)
- (* -0.11677 y y)
- (* -0.00297 y y y)
- (* 0.00074 y y y y)))
- ((equal k 3) (+ 1721414.39987
- (* 365242.88257 y)
- (* -0.00769 y y)
- (* -0.00933 y y y)
- (* -0.00006 y y y y))))
- ; actually between 1000 and 3000
- (cond ((equal k 0) (+ 2451623.80984
- (* 365242.37404 z)
- (* 0.05169 z z)
- (* -0.00411 z z z)
- (* -0.00057 z z z z)))
- ((equal k 1) (+ 2451716.56767
- (* 365241.62603 z)
- (* 0.00325 z z)
- (* 0.00888 z z z)
- (* -0.00030 z z z z)))
- ((equal k 2) (+ 2451810.21715
- (* 365242.01767 z)
- (* -0.11575 z z)
- (* 0.00337 z z z)
- (* 0.00078 z z z z)))
- ((equal k 3) (+ 2451900.05952
- (* 365242.74049 z)
- (* -0.06223 z z)
- (* -0.00823 z z z)
- (* 0.00032 z z z z)))))))
-
-; from Meeus, 1991, page 167
-(defconst solar-seasons-data
- '((485 324.96 1934.136)
- (203 337.23 32964.467)
- (199 342.08 20.186)
- (182 27.85 445267.112)
- (156 73.14 45036.886)
- (136 171.52 22518.443)
- (77 222.54 65928.934)
- (74 296.72 3034.906)
- (70 243.58 9037.513)
- (58 119.81 33718.147)
- (52 297.17 150.678)
- (50 21.02 2281.226)
- (45 247.54 29929.562)
- (44 325.15 31555.956)
- (29 60.93 4443.417)
- (18 155.12 67555.328)
- (17 288.79 4562.452)
- (16 198.04 62894.029)
- (14 199.76 31436.921)
- (12 95.39 14577.848)
- (12 287.11 31931.756)
- (12 320.81 34777.259)
- (9 227.73 1222.114)
- (8 15.45 16859.074)))
-
-;;;###autoload
-(defun solar-equinoxes-solstices ()
- "*local* date and time of equinoxes and solstices, if visible in the calendar window.
-Requires floating point."
- (let ((m displayed-month)
- (y displayed-year))
- (increment-calendar-month m y (cond ((= 1 (% m 3)) -1)
- ((= 2 (% m 3)) 1)
- (t 0)))
- (let* ((calendar-standard-time-zone-name
- (if calendar-time-zone calendar-standard-time-zone-name "UTC"))
- (calendar-daylight-savings-starts
- (if calendar-time-zone calendar-daylight-savings-starts))
- (calendar-daylight-savings-ends
- (if calendar-time-zone calendar-daylight-savings-ends))
- (calendar-time-zone (if calendar-time-zone calendar-time-zone 0))
- (k (1- (/ m 3)))
- (d0 (solar-equinoxes/solstices k y))
- (d1 (list (car d0) (floor (car (cdr d0))) (car (cdr (cdr d0)))))
- (h0 (* 24 (- (car (cdr d0)) (floor (car (cdr d0))))))
- (adj (dst-adjust-time d1 h0))
- (d (list (car d1) (+ (car (cdr d1))
- (/ (car (cdr adj)) 24.0))
- (car (cdr (cdr d1)))))
- ; The following is nearly as accurate, but not quite:
- ;(d0 (solar-date-next-longitude
- ; (calendar-astro-from-absolute
- ; (calendar-absolute-from-gregorian
- ; (list (+ 3 (* k 3)) 15 y)))
- ; 90))
- ;(abs-day (calendar-absolute-from-astro d)))
- (abs-day (calendar-absolute-from-gregorian d)))
- (list
- (list (calendar-gregorian-from-absolute (floor abs-day))
- (format "%s %s"
- (nth k (if (and calendar-latitude
- (< (calendar-latitude) 0))
- solar-s-hemi-seasons
- solar-n-hemi-seasons))
- (solar-time-string
- (* 24 (- abs-day (floor abs-day)))
- (if (dst-in-effect abs-day)
- calendar-daylight-time-zone-name
- calendar-standard-time-zone-name))))))))
-
-
-(provide 'solar)
-
-;;; solar.el ends here
diff --git a/lisp/case-table.el b/lisp/case-table.el
deleted file mode 100644
index c47359b24bb..00000000000
--- a/lisp/case-table.el
+++ /dev/null
@@ -1,121 +0,0 @@
-;;; case-table.el --- code to extend the character set and support case tables.
-
-;; Copyright (C) 1988, 1994 Free Software Foundation, Inc.
-
-;; Author: Howard Gayle
-;; Maintainer: FSF
-;; Keywords: i18n
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; 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
-
-;;; Code:
-
-;;;###autoload
-(defun describe-buffer-case-table ()
- "Describe the case table of the current buffer."
- (interactive)
- (let ((description (make-char-table 'case-table)))
- (map-char-table
- (function (lambda (key value)
- (set-char-table-range
- description key
- (cond ((null key)
- "case-invariant")
- ((/= key (downcase key))
- (concat "uppercase, matches "
- (char-to-string (downcase key))))
- ((/= key (upcase key))
- (concat "lowercase, matches "
- (char-to-string (upcase key))))
- (t "case-invariant")))))
- (current-case-table))
- (save-excursion
- (with-output-to-temp-buffer "*Help*"
- (set-buffer standard-output)
- (describe-vector description)
- (help-mode)))))
-
-;;;###autoload
-(defun copy-case-table (case-table)
- (let ((copy (copy-sequence case-table)))
- ;; Clear out the extra slots so that they will be
- ;; recomputed from the main (downcase) table.
- (set-char-table-extra-slot copy 0 nil)
- (set-char-table-extra-slot copy 1 nil)
- (set-char-table-extra-slot copy 2 nil)
- copy))
-
-;;;###autoload
-(defun set-case-syntax-delims (l r table)
- "Make characters L and R a matching pair of non-case-converting delimiters.
-This sets the entries for L and R in TABLE, which is a string
-that will be used as the downcase part of a case table.
-It also modifies `standard-syntax-table' to
-indicate left and right delimiters."
- (aset table l l)
- (aset table r r)
- ;; Clear out the extra slots so that they will be
- ;; recomputed from the main (downcase) table.
- (set-char-table-extra-slot table 0 nil)
- (set-char-table-extra-slot table 1 nil)
- (set-char-table-extra-slot table 2 nil)
- (modify-syntax-entry l (concat "(" (char-to-string r) " ")
- (standard-syntax-table))
- (modify-syntax-entry r (concat ")" (char-to-string l) " ")
- (standard-syntax-table)))
-
-;;;###autoload
-(defun set-case-syntax-pair (uc lc table)
- "Make characters UC and LC a pair of inter-case-converting letters.
-This sets the entries for characters UC and LC in TABLE, which is a string
-that will be used as the downcase part of a case table.
-It also modifies `standard-syntax-table' to give them the syntax of
-word constituents."
- (aset table uc lc)
- (aset table lc lc)
- (set-char-table-extra-slot table 0 nil)
- (set-char-table-extra-slot table 1 nil)
- (set-char-table-extra-slot table 2 nil)
- (modify-syntax-entry lc "w " (standard-syntax-table))
- (modify-syntax-entry uc "w " (standard-syntax-table)))
-
-;;;###autoload
-(defun set-case-syntax (c syntax table)
- "Make characters C case-invariant with syntax SYNTAX.
-This sets the entries for character C in TABLE, which is a string
-that will be used as the downcase part of a case table.
-It also modifies `standard-syntax-table'.
-SYNTAX should be \" \", \"w\", \".\" or \"_\"."
- (aset table c c)
- (set-char-table-extra-slot table 0 nil)
- (set-char-table-extra-slot table 1 nil)
- (set-char-table-extra-slot table 2 nil)
- (modify-syntax-entry c syntax (standard-syntax-table)))
-
-(provide 'case-table)
-
-;;; case-table.el ends here
diff --git a/lisp/cdl.el b/lisp/cdl.el
deleted file mode 100644
index 2c88ec2d09e..00000000000
--- a/lisp/cdl.el
+++ /dev/null
@@ -1,44 +0,0 @@
-;;; cdl.el --- Common Data Language (CDL) utility functions for Gnu Emacs
-
-;; Copyright (C) 1993 Free Software Foundation, Inc.
-
-;; Author: ATAE@spva.physics.imperial.ac.uk (Ata Etemadi)
-;; Keywords: data
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(defun cdl-get-file (filename)
- "Run file through ncdump and insert result into buffer after point."
- (interactive "fCDF file: ")
- (message "ncdump in progress...")
- (let ((start (point)))
- (call-process "ncdump" nil t nil (expand-file-name filename))
- (goto-char start))
- (message "ncdump in progress...done"))
-
-(defun cdl-put-region (filename start end)
- "Run region through ncgen and write results into a file."
- (interactive "FNew CDF file: \nr")
- (message "ncgen in progress...")
- (call-process-region start end "ncgen"
- nil nil nil "-o" (expand-file-name filename))
- (message "ncgen in progress...done"))
-
-;;; cdl.el ends here.
diff --git a/lisp/chistory.el b/lisp/chistory.el
deleted file mode 100644
index 3685e01db5c..00000000000
--- a/lisp/chistory.el
+++ /dev/null
@@ -1,174 +0,0 @@
-;;; chistory.el --- list command history
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Author: K. Shane Hartman
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This really has nothing to do with list-command-history per se, but
-;; its a nice alternative to C-x ESC 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.
-
-;;; Code:
-
-;;;###autoload
-(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 (string-match "[^ \t]" pattern)
- (setq pattern (substring pattern (match-beginning 0)))
- (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? " temp)))
- (setq what (car history))
- (setq history (cdr history))))
- (if (not what)
- (error "Command history exhausted")
- ;; Try to remove any useless command history element for this command.
- (if (eq (car (car command-history)) 'repeat-matching-complex-command)
- (setq command-history (cdr command-history)))
- (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 to be ignored by `default-command-history-filter'.
-It that function 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
- "Predicate to test which commands should be excluded from the history listing.
-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, maximum length of the listing produced by `list-command-history'.")
-
-;;;###autoload
-(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
- (nconc (make-sparse-keymap) shared-lisp-mode-map))
- (suppress-keymap command-history-map)
- (define-key command-history-map "x" 'command-history-repeat)
- (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-repeat ()
- "Repeat the command shown on the current line.
-The buffer for that command is the previous current buffer."
- (interactive)
- (save-excursion
- (eval (prog1
- (save-excursion
- (beginning-of-line)
- (read (current-buffer)))
- (set-buffer
- (car (cdr (buffer-list))))))))
-
-;;;###autoload
-(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.
-Use \\<command-history-map>\\[command-history-repeat] to repeat the command on the current line.
-
-Otherwise much like Emacs-Lisp Mode except that there is no self-insertion
-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))
-
-(provide 'chistory)
-
-;;; chistory.el ends here
diff --git a/lisp/cmuscheme.el b/lisp/cmuscheme.el
deleted file mode 100644
index 0dbd7a2cb70..00000000000
--- a/lisp/cmuscheme.el
+++ /dev/null
@@ -1,413 +0,0 @@
-;;; cmuscheme.el --- Scheme process in a buffer. Adapted from tea.el.
-
-;; Copyright (C) 1988, 1994 Free Software Foundation, Inc.
-
-;; Author: Olin Shivers <olin.shivers@cs.cmu.edu>
-;; Maintainer: FSF
-;; Keywords: processes, lisp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This is a customisation of comint-mode (see comint.el)
-;;
-;; Written by Olin Shivers (olin.shivers@cs.cmu.edu). With bits and pieces
-;; lifted from scheme.el, shell.el, clisp.el, newclisp.el, cobol.el, et al..
-;; 8/88
-;;
-;; Please send me bug reports, bug fixes, and extensions, so that I can
-;; merge them into the master source.
-;;
-;; The changelog is at the end of this file.
-;;
-;; NOTE: MIT Cscheme, when invoked with the -emacs flag, has a special user
-;; interface that communicates process state back to the superior emacs by
-;; outputting special control sequences. The gnumacs package, xscheme.el, has
-;; lots and lots of special purpose code to read these control sequences, and
-;; so is very tightly integrated with the cscheme process. The cscheme
-;; interrupt handler and debugger read single character commands in cbreak
-;; mode; when this happens, xscheme.el switches to special keymaps that bind
-;; the single letter command keys to emacs functions that directly send the
-;; character to the scheme process. Cmuscheme mode does *not* provide this
-;; functionality. If you are a cscheme user, you may prefer to use the
-;; xscheme.el/cscheme -emacs interaction.
-;;
-;; Here's a summary of the pros and cons, as I see them.
-;; xscheme: Tightly integrated with inferior cscheme process! A few commands
-;; not in cmuscheme. But. Integration is a bit of a hack. Input
-;; history only keeps the immediately prior input. Bizarre
-;; keybindings.
-;;
-;; cmuscheme: Not tightly integrated with inferior cscheme process. But.
-;; Carefully integrated functionality with the entire suite of
-;; comint-derived CMU process modes. Keybindings reminiscent of
-;; Zwei and Hemlock. Good input history. A few commands not in
-;; xscheme.
-;;
-;; It's a tradeoff. Pay your money; take your choice. If you use a Scheme
-;; that isn't Cscheme, of course, there isn't a choice. Xscheme.el is *very*
-;; Cscheme-specific; you must use cmuscheme.el. Interested parties are
-;; invited to port xscheme functionality on top of comint mode...
-
-;;; Code:
-
-(require 'scheme)
-(require 'comint)
-
-;;; INFERIOR SCHEME MODE STUFF
-;;;============================================================================
-
-(defvar inferior-scheme-mode-hook nil
- "*Hook for customising inferior-scheme mode.")
-(defvar inferior-scheme-mode-map nil)
-
-(cond ((not inferior-scheme-mode-map)
- (setq inferior-scheme-mode-map
- (copy-keymap comint-mode-map))
- (define-key inferior-scheme-mode-map "\M-\C-x" ;gnu convention
- 'scheme-send-definition)
- (define-key inferior-scheme-mode-map "\C-x\C-e" 'scheme-send-last-sexp)
- (define-key inferior-scheme-mode-map "\C-c\C-l" 'scheme-load-file)
- (define-key inferior-scheme-mode-map "\C-c\C-k" 'scheme-compile-file)
- (scheme-mode-commands inferior-scheme-mode-map)))
-
-;; Install the process communication commands in the scheme-mode keymap.
-(define-key scheme-mode-map "\M-\C-x" 'scheme-send-definition);gnu convention
-(define-key scheme-mode-map "\C-x\C-e" 'scheme-send-last-sexp);gnu convention
-(define-key scheme-mode-map "\C-c\C-e" 'scheme-send-definition)
-(define-key scheme-mode-map "\C-c\M-e" 'scheme-send-definition-and-go)
-(define-key scheme-mode-map "\C-c\C-r" 'scheme-send-region)
-(define-key scheme-mode-map "\C-c\M-r" 'scheme-send-region-and-go)
-(define-key scheme-mode-map "\C-c\M-c" 'scheme-compile-definition)
-(define-key scheme-mode-map "\C-c\C-c" 'scheme-compile-definition-and-go)
-(define-key scheme-mode-map "\C-c\C-z" 'switch-to-scheme)
-(define-key scheme-mode-map "\C-c\C-l" 'scheme-load-file)
-(define-key scheme-mode-map "\C-c\C-k" 'scheme-compile-file) ;k for "kompile"
-
-(defvar scheme-buffer)
-
-(defun inferior-scheme-mode ()
- "Major mode for interacting with an inferior Scheme process.
-
-The following commands are available:
-\\{inferior-scheme-mode-map}
-
-A Scheme process can be fired up with M-x run-scheme.
-
-Customisation: Entry to this mode runs the hooks on comint-mode-hook and
-inferior-scheme-mode-hook (in that order).
-
-You can send text to the inferior Scheme process from other buffers containing
-Scheme source.
- switch-to-scheme switches the current buffer to the Scheme process buffer.
- scheme-send-definition sends the current definition to the Scheme process.
- scheme-compile-definition compiles the current definition.
- scheme-send-region sends the current region to the Scheme process.
- scheme-compile-region compiles the current region.
-
- scheme-send-definition-and-go, scheme-compile-definition-and-go,
- scheme-send-region-and-go, and scheme-compile-region-and-go
- switch to the Scheme process buffer after sending their text.
-For information on running multiple processes in multiple buffers, see
-documentation for variable scheme-buffer.
-
-Commands:
-Return after the end of the process' output sends the text from the
- end of process to point.
-Return before the end of the process' output copies the sexp ending at point
- to the end of the process' output, and sends it.
-Delete converts tabs to spaces as it moves back.
-Tab indents for Scheme; with argument, shifts rest
- of expression rigidly with the current line.
-C-M-q does Tab on each line starting within following expression.
-Paragraphs are separated only by blank lines. Semicolons start comments.
-If you accidentally suspend your process, use \\[comint-continue-subjob]
-to continue it."
- (interactive)
- (comint-mode)
- ;; Customise in inferior-scheme-mode-hook
- (setq comint-prompt-regexp "^[^>\n]*>+ *") ; OK for cscheme, oaklisp, T,...
- (scheme-mode-variables)
- (setq major-mode 'inferior-scheme-mode)
- (setq mode-name "Inferior Scheme")
- (setq mode-line-process '(":%s"))
- (use-local-map inferior-scheme-mode-map)
- (setq comint-input-filter (function scheme-input-filter))
- (setq comint-get-old-input (function scheme-get-old-input))
- (run-hooks 'inferior-scheme-mode-hook))
-
-(defvar inferior-scheme-filter-regexp "\\`\\s *\\S ?\\S ?\\s *\\'"
- "*Input matching this regexp are not saved on the history list.
-Defaults to a regexp ignoring all inputs of 0, 1, or 2 letters.")
-
-(defun scheme-input-filter (str)
- "Don't save anything matching inferior-scheme-filter-regexp"
- (not (string-match inferior-scheme-filter-regexp str)))
-
-(defun scheme-get-old-input ()
- "Snarf the sexp ending at point"
- (save-excursion
- (let ((end (point)))
- (backward-sexp)
- (buffer-substring (point) end))))
-
-(defun scheme-args-to-list (string)
- (let ((where (string-match "[ \t]" string)))
- (cond ((null where) (list string))
- ((not (= where 0))
- (cons (substring string 0 where)
- (scheme-args-to-list (substring string (+ 1 where)
- (length string)))))
- (t (let ((pos (string-match "[^ \t]" string)))
- (if (null pos)
- nil
- (scheme-args-to-list (substring string pos
- (length string)))))))))
-
-(defvar scheme-program-name "scheme"
- "*Program invoked by the run-scheme command")
-
-;;;###autoload
-(defun run-scheme (cmd)
- "Run an inferior Scheme process, input and output via buffer *scheme*.
-If there is a process already running in `*scheme*', switch to that buffer.
-With argument, allows you to edit the command line (default is value
-of `scheme-program-name'). Runs the hooks `inferior-scheme-mode-hook'
-\(after the `comint-mode-hook' is run).
-\(Type \\[describe-mode] in the process buffer for a list of commands.)"
-
- (interactive (list (if current-prefix-arg
- (read-string "Run Scheme: " scheme-program-name)
- scheme-program-name)))
- (if (not (comint-check-proc "*scheme*"))
- (let ((cmdlist (scheme-args-to-list cmd)))
- (set-buffer (apply 'make-comint "scheme" (car cmdlist)
- nil (cdr cmdlist)))
- (inferior-scheme-mode)))
- (setq scheme-program-name cmd)
- (setq scheme-buffer "*scheme*")
- (pop-to-buffer "*scheme*"))
-;;;###autoload (add-hook 'same-window-buffer-names "*scheme*")
-
-(defun scheme-send-region (start end)
- "Send the current region to the inferior Scheme process."
- (interactive "r")
- (comint-send-region (scheme-proc) start end)
- (comint-send-string (scheme-proc) "\n"))
-
-(defun scheme-send-definition ()
- "Send the current definition to the inferior Scheme process."
- (interactive)
- (save-excursion
- (end-of-defun)
- (let ((end (point)))
- (beginning-of-defun)
- (scheme-send-region (point) end))))
-
-(defun scheme-send-last-sexp ()
- "Send the previous sexp to the inferior Scheme process."
- (interactive)
- (scheme-send-region (save-excursion (backward-sexp) (point)) (point)))
-
-(defvar scheme-compile-exp-command "(compile '%s)"
- "*Template for issuing commands to compile arbitrary Scheme expressions.")
-
-(defun scheme-compile-region (start end)
- "Compile the current region in the inferior Scheme process.
-\(A BEGIN is wrapped around the region: (BEGIN <region>))"
- (interactive "r")
- (comint-send-string (scheme-proc) (format scheme-compile-exp-command
- (format "(begin %s)"
- (buffer-substring start end))))
- (comint-send-string (scheme-proc) "\n"))
-
-(defun scheme-compile-definition ()
- "Compile the current definition in the inferior Scheme process."
- (interactive)
- (save-excursion
- (end-of-defun)
- (let ((end (point)))
- (beginning-of-defun)
- (scheme-compile-region (point) end))))
-
-(defun switch-to-scheme (eob-p)
- "Switch to the scheme process buffer.
-With argument, positions cursor at end of buffer."
- (interactive "P")
- (if (get-buffer scheme-buffer)
- (pop-to-buffer scheme-buffer)
- (error "No current process buffer. See variable scheme-buffer."))
- (cond (eob-p
- (push-mark)
- (goto-char (point-max)))))
-
-(defun scheme-send-region-and-go (start end)
- "Send the current region to the inferior Scheme process.
-Then switch to the process buffer."
- (interactive "r")
- (scheme-send-region start end)
- (switch-to-scheme t))
-
-(defun scheme-send-definition-and-go ()
- "Send the current definition to the inferior Scheme.
-Then switch to the process buffer."
- (interactive)
- (scheme-send-definition)
- (switch-to-scheme t))
-
-(defun scheme-compile-definition-and-go ()
- "Compile the current definition in the inferior Scheme.
-Then switch to the process buffer."
- (interactive)
- (scheme-compile-definition)
- (switch-to-scheme t))
-
-(defun scheme-compile-region-and-go (start end)
- "Compile the current region in the inferior Scheme.
-Then switch to the process buffer."
- (interactive "r")
- (scheme-compile-region start end)
- (switch-to-scheme t))
-
-(defvar scheme-source-modes '(scheme-mode)
- "*Used to determine if a buffer contains Scheme source code.
-If it's loaded into a buffer that is in one of these major modes, it's
-considered a scheme source file by scheme-load-file and scheme-compile-file.
-Used by these commands to determine defaults.")
-
-(defvar scheme-prev-l/c-dir/file nil
- "Caches the last (directory . file) pair.
-Caches the last pair used in the last scheme-load-file or
-scheme-compile-file command. Used for determining the default in the
-next one.")
-
-(defun scheme-load-file (file-name)
- "Load a Scheme file into the inferior Scheme process."
- (interactive (comint-get-source "Load Scheme file: " scheme-prev-l/c-dir/file
- scheme-source-modes t)) ; T because LOAD
- ; needs an exact name
- (comint-check-source file-name) ; Check to see if buffer needs saved.
- (setq scheme-prev-l/c-dir/file (cons (file-name-directory file-name)
- (file-name-nondirectory file-name)))
- (comint-send-string (scheme-proc) (concat "(load \""
- file-name
- "\"\)\n")))
-
-(defun scheme-compile-file (file-name)
- "Compile a Scheme file in the inferior Scheme process."
- (interactive (comint-get-source "Compile Scheme file: "
- scheme-prev-l/c-dir/file
- scheme-source-modes
- nil)) ; NIL because COMPILE doesn't
- ; need an exact name.
- (comint-check-source file-name) ; Check to see if buffer needs saved.
- (setq scheme-prev-l/c-dir/file (cons (file-name-directory file-name)
- (file-name-nondirectory file-name)))
- (comint-send-string (scheme-proc) (concat "(compile-file \""
- file-name
- "\"\)\n")))
-
-
-(defvar scheme-buffer nil "*The current scheme process buffer.
-
-MULTIPLE PROCESS SUPPORT
-===========================================================================
-Cmuscheme.el supports, in a fairly simple fashion, running multiple Scheme
-processes. To run multiple Scheme processes, you start the first up with
-\\[run-scheme]. It will be in a buffer named *scheme*. Rename this buffer
-with \\[rename-buffer]. You may now start up a new process with another
-\\[run-scheme]. It will be in a new buffer, named *scheme*. You can
-switch between the different process buffers with \\[switch-to-buffer].
-
-Commands that send text from source buffers to Scheme processes --
-like scheme-send-definition or scheme-compile-region -- have to choose a
-process to send to, when you have more than one Scheme process around. This
-is determined by the global variable scheme-buffer. Suppose you
-have three inferior Schemes running:
- Buffer Process
- foo scheme
- bar scheme<2>
- *scheme* scheme<3>
-If you do a \\[scheme-send-definition-and-go] command on some Scheme source
-code, what process do you send it to?
-
-- If you're in a process buffer (foo, bar, or *scheme*),
- you send it to that process.
-- If you're in some other buffer (e.g., a source file), you
- send it to the process attached to buffer scheme-buffer.
-This process selection is performed by function scheme-proc.
-
-Whenever \\[run-scheme] fires up a new process, it resets scheme-buffer
-to be the new process's buffer. If you only run one process, this will
-do the right thing. If you run multiple processes, you can change
-scheme-buffer to another process buffer with \\[set-variable].
-
-More sophisticated approaches are, of course, possible. If you find yourself
-needing to switch back and forth between multiple processes frequently,
-you may wish to consider ilisp.el, a larger, more sophisticated package
-for running inferior Lisp and Scheme processes. The approach taken here is
-for a minimal, simple implementation. Feel free to extend it.")
-
-(defun scheme-proc ()
- "Returns the current scheme process. See variable scheme-buffer."
- (let ((proc (get-buffer-process (if (eq major-mode 'inferior-scheme-mode)
- (current-buffer)
- scheme-buffer))))
- (or proc
- (error "No current process. See variable scheme-buffer"))))
-
-
-;;; Do the user's customisation...
-
-(defvar cmuscheme-load-hook nil
- "This hook is run when cmuscheme is loaded in.
-This is a good place to put keybindings.")
-
-(run-hooks 'cmuscheme-load-hook)
-
-
-;;; CHANGE LOG
-;;; ===========================================================================
-;;; 8/88 Olin
-;;; Created.
-;;;
-;;; 2/15/89 Olin
-;;; Removed -emacs flag from process invocation. It's only useful for
-;;; cscheme, and makes cscheme assume it's running under xscheme.el,
-;;; which messes things up royally. A bug.
-;;;
-;;; 5/22/90 Olin
-;;; - Upgraded to use comint-send-string and comint-send-region.
-;;; - run-scheme now offers to let you edit the command line if
-;;; you invoke it with a prefix-arg. M-x scheme is redundant, and
-;;; has been removed.
-;;; - Explicit references to process "scheme" have been replaced with
-;;; (scheme-proc). This allows better handling of multiple process bufs.
-;;; - Added scheme-send-last-sexp, bound to C-x C-e. A gnu convention.
-;;; - Have not added process query facility a la cmulisp.el's lisp-show-arglist
-;;; and friends, but interested hackers might find a useful application
-;;; of this facility.
-;;;
-;;; 3/12/90 Olin
-;;; - scheme-load-file and scheme-compile-file no longer switch-to-scheme.
-;;; Tale suggested this.
-
-(provide 'cmuscheme)
-
-;;; cmuscheme.el ends here
diff --git a/lisp/comint.el b/lisp/comint.el
deleted file mode 100644
index 11f4afc705b..00000000000
--- a/lisp/comint.el
+++ /dev/null
@@ -1,2213 +0,0 @@
-;;; comint.el --- general command interpreter in a window stuff
-
-;; Copyright (C) 1988, 90, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
-
-;; Author: Olin Shivers <shivers@cs.cmu.edu>
-;; Adapted-by: Simon Marshall <simon@gnu.ai.mit.edu>
-;; Keywords: processes
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Please send me bug reports, bug fixes, and extensions, so that I can
-;; merge them into the master source.
-;; - Olin Shivers (shivers@cs.cmu.edu)
-;; - Simon Marshall (simon@gnu.ai.mit.edu)
-
-;; 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.).
-
-;; Several packages are already defined using comint mode:
-;; - shell.el defines a shell-in-a-buffer mode.
-;; - cmulisp.el defines a simple lisp-in-a-buffer mode.
-;;
-;; - The file cmuscheme.el defines a scheme-in-a-buffer mode.
-;; - The file tea.el tunes scheme and inferior-scheme modes for T.
-;; - The file soar.el tunes lisp and inferior-lisp modes for Soar.
-;; - cmutex.el defines tex and latex modes that invoke tex, latex, bibtex,
-;; previewers, and printers from within emacs.
-;; - background.el allows csh-like job control inside emacs.
-;; It is pretty easy to make new derived modes for other processes.
-
-;; 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 (e.g., tex-mode,
-;; background, dbx, gdb, kermit, prolog, telnet) to use comint-mode
-;; instead of shell-mode, see the notes at the end of this file.
-
-
-;; Brief Command Documentation:
-;;============================================================================
-;; Comint Mode Commands: (common to all derived modes, like shell & cmulisp
-;; mode)
-;;
-;; m-p comint-previous-input Cycle backwards in input history
-;; m-n comint-next-input Cycle forwards
-;; m-r comint-previous-matching-input Previous input matching a regexp
-;; m-s comint-next-matching-input Next input that matches
-;; m-c-l comint-show-output Show last batch of process output
-;; return comint-send-input
-;; c-d comint-delchar-or-maybe-eof Delete char unless at end of buff
-;; c-c c-a comint-bol Beginning of line; skip prompt
-;; c-c c-u comint-kill-input ^u
-;; c-c c-w backward-kill-word ^w
-;; c-c c-c comint-interrupt-subjob ^c
-;; c-c c-z comint-stop-subjob ^z
-;; c-c c-\ comint-quit-subjob ^\
-;; c-c c-o comint-kill-output Delete last batch of process output
-;; c-c c-r comint-show-output Show last batch of process output
-;; c-c c-l comint-dynamic-list-input-ring List input history
-;;
-;; Not bound by default in comint-mode (some are in shell mode)
-;; comint-run Run a program under comint-mode
-;; send-invisible Read a line w/o echo, and send to proc
-;; comint-dynamic-complete-filename Complete filename at point.
-;; comint-dynamic-complete-variable Complete variable name at point.
-;; comint-dynamic-list-filename-completions List completions in help buffer.
-;; comint-replace-by-expanded-filename Expand and complete filename at point;
-;; replace with expanded/completed name.
-;; comint-replace-by-expanded-history Expand history at point;
-;; replace with expanded name.
-;; comint-magic-space Expand history and add (a) space(s).
-;; comint-kill-subjob No mercy.
-;; comint-show-maximum-output Show as much output as possible.
-;; comint-continue-subjob Send CONT signal to buffer's process
-;; group. Useful if you accidentally
-;; suspend your process (with C-c C-z).
-
-;; comint-mode-hook is the comint mode hook. Basically for your keybindings.
-
-;;; Code:
-
-(require 'ring)
-
-;; Buffer Local Variables:
-;;============================================================================
-;; Comint mode buffer local variables:
-;; comint-prompt-regexp string comint-bol uses to match prompt
-;; comint-delimiter-argument-list list For delimiters and arguments
-;; comint-last-input-start marker Handy if inferior always echoes
-;; comint-last-input-end marker For comint-kill-output command
-;; comint-input-ring-size integer For the input history
-;; comint-input-ring ring mechanism
-;; comint-input-ring-index number ...
-;; comint-input-autoexpand symbol ...
-;; comint-input-ignoredups boolean ...
-;; comint-last-input-match string ...
-;; comint-dynamic-complete-functions hook For the completion mechanism
-;; comint-completion-fignore list ...
-;; comint-file-name-chars string ...
-;; comint-file-name-quote-list list ...
-;; comint-get-old-input function Hooks for specific
-;; comint-input-filter-functions hook process-in-a-buffer
-;; comint-output-filter-functions hook function modes.
-;; comint-input-filter function ...
-;; comint-input-sender function ...
-;; comint-eol-on-send boolean ...
-;; comint-process-echoes boolean ...
-;; comint-scroll-to-bottom-on-input symbol For scroll behavior
-;; comint-scroll-to-bottom-on-output symbol ...
-;; comint-scroll-show-maximum-output boolean ...
-;;
-;; Comint mode non-buffer local variables:
-;; comint-completion-addsuffix boolean/cons For file name
-;; comint-completion-autolist boolean completion behavior
-;; comint-completion-recexact boolean ...
-
-(defvar comint-prompt-regexp "^"
- "Regexp to recognise prompts in the inferior process.
-Defaults to \"^\", the null string at BOL.
-
-Good choices:
- Canonical Lisp: \"^[^> \\n]*>+:? *\" (Lucid, franz, kcl, T, cscheme, oaklisp)
- Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\"
- franz: \"^\\\\(->\\\\|<[0-9]*>:\\\\) *\"
- kcl: \"^>+ *\"
- shell: \"^[^#$%>\\n]*[#$%>] *\"
- T: \"^>+ *\"
-
-This is a good thing to set in mode hooks.")
-
-(defvar comint-delimiter-argument-list ()
- "List of characters to recognise as separate arguments in input.
-Strings comprising a character in this list will separate the arguments
-surrounding them, and also be regarded as arguments in their own right (unlike
-whitespace). See `comint-arguments'.
-Defaults to the empty list.
-
-For shells, a good value is (?\\| ?& ?< ?> ?\\( ?\\) ?;).
-
-This is a good thing to set in mode hooks.")
-
-(defvar comint-input-autoexpand nil
- "*If non-nil, expand input command history references on completion.
-This mirrors the optional behavior of tcsh (its autoexpand and histlit).
-
-If the value is `input', then the expansion is seen on input.
-If the value is `history', then the expansion is only when inserting
-into the buffer's input ring. See also `comint-magic-space' and
-`comint-dynamic-complete'.
-
-This variable is buffer-local.")
-
-(defvar comint-input-ignoredups nil
- "*If non-nil, don't add input matching the last on the input ring.
-This mirrors the optional behavior of bash.
-
-This variable is buffer-local.")
-
-(defvar comint-input-ring-file-name nil
- "*If non-nil, name of the file to read/write input history.
-See also `comint-read-input-ring' and `comint-write-input-ring'.
-
-This variable is buffer-local, and is a good thing to set in mode hooks.")
-
-(defvar comint-scroll-to-bottom-on-input nil
- "*Controls whether input to interpreter causes window to scroll.
-If nil, then do not scroll. If t or `all', scroll all windows showing buffer.
-If `this', scroll only the selected window.
-
-The default is nil.
-
-See `comint-preinput-scroll-to-bottom'. This variable is buffer-local.")
-
-(defvar comint-scroll-to-bottom-on-output nil
- "*Controls whether interpreter output causes window to scroll.
-If nil, then do not scroll. If t or `all', scroll all windows showing buffer.
-If `this', scroll only the selected window.
-If `others', scroll only those that are not the selected window.
-
-The default is nil.
-
-See variable `comint-scroll-show-maximum-output' and function
-`comint-postoutput-scroll-to-bottom'. This variable is buffer-local.")
-
-(defvar comint-scroll-show-maximum-output nil
- "*Controls how interpreter output causes window to scroll.
-If non-nil, then show the maximum output when the window is scrolled.
-
-See variable `comint-scroll-to-bottom-on-output' and function
-`comint-postoutput-scroll-to-bottom'. This variable is buffer-local.")
-
-(defvar comint-buffer-maximum-size 1024
- "*The maximum size in lines for comint buffers.
-Comint buffers are truncated from the top to be no greater than this number, if
-the function `comint-truncate-buffer' is on `comint-output-filter-functions'.")
-
-(defvar comint-input-ring-size 32
- "Size of input history ring.")
-
-(defvar comint-process-echoes nil
- "*If non-nil, assume that the subprocess echoes any input.
-If so, delete one copy of the input so that only one copy eventually
-appears in the buffer.
-
-This variable is buffer-local.")
-
-(defvar comint-password-prompt-regexp
- "\\(\\([Oo]ld \\|[Nn]ew \\|'s \\|^\\)[Pp]assword\\|pass phrase\\):\\s *\\'"
- "*Regexp matching prompts for passwords in the inferior process.
-This is used by `comint-watch-for-password-prompt'.")
-
-;; Here are the per-interpreter hooks.
-(defvar comint-get-old-input (function comint-get-old-input-default)
- "Function that returns 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'.")
-
-(defvar comint-dynamic-complete-functions
- '(comint-replace-by-expanded-history comint-dynamic-complete-filename)
- "List of functions called to perform completion.
-Functions should return non-nil if completion was performed.
-See also `comint-dynamic-complete'.
-
-This is a good thing to set in mode hooks.")
-
-(defvar comint-input-filter
- (function (lambda (str) (not (string-match "\\`\\s *\\'" str))))
- "Predicate for filtering additions to input history.
-Takes one argument, the input. If non-nil, the input may be saved on the input
-history list. Default is to save anything that isn't all whitespace.")
-
-(defvar comint-input-filter-functions '()
- "Functions to call before input is sent to the process.
-These functions get one argument, a string containing the text to send.
-
-This variable is buffer-local.")
-
-(defvar comint-output-filter-functions '(comint-postoutput-scroll-to-bottom)
- "Functions to call after output is inserted into the buffer.
-One possible function is `comint-postoutput-scroll-to-bottom'.
-These functions get one argument, a string containing the text as originally
-inserted. Note that this might not be the same as the buffer contents between
-`comint-last-output-start' and the buffer's `process-mark', if other filter
-functions have already modified the buffer.
-
-This variable is buffer-local.")
-
-(defvar comint-input-sender (function comint-simple-send)
- "Function to actually send to PROCESS the STRING submitted by user.
-Usually this is just `comint-simple-send', but if your mode needs to
-massage the input string, put a different function here.
-`comint-simple-send' just sends the string plus a newline.
-This is called from the user command `comint-send-input'.")
-
-(defvar comint-eol-on-send t
- "*Non-nil means go to the end of the line before sending input.
-See `comint-send-input'.")
-
-(defvar comint-mode-hook '()
- "Called upon entry into comint-mode
-This is run before the process is cranked up.")
-
-(defvar comint-exec-hook '()
- "Called each time a process is exec'd by `comint-exec'.
-This is called after the process is cranked up. It is useful for things that
-must be done each time a process is executed in a comint mode buffer (e.g.,
-`(process-kill-without-query)'). In contrast, the `comint-mode-hook' is only
-executed once when the buffer is created.")
-
-(defvar comint-mode-map nil)
-
-(defvar comint-ptyp t
- "Non-nil if communications via pty; false if by pipe. Buffer local.
-This is to work around a bug in Emacs process signaling.")
-
-(defvar comint-input-ring nil)
-(defvar comint-last-input-start)
-(defvar comint-last-input-end)
-(defvar comint-last-output-start)
-(defvar comint-input-ring-index nil
- "Index of last matched history element.")
-(defvar comint-matching-input-from-input-string ""
- "Input previously used to match input history.")
-
-(put 'comint-replace-by-expanded-history 'menu-enable 'comint-input-autoexpand)
-(put 'comint-input-ring 'permanent-local t)
-(put 'comint-input-ring-index 'permanent-local t)
-(put 'comint-input-autoexpand 'permanent-local t)
-(put 'comint-input-filter-functions 'permanent-local t)
-(put 'comint-output-filter-functions 'permanent-local t)
-(put 'comint-scroll-to-bottom-on-input 'permanent-local t)
-(put 'comint-scroll-to-bottom-on-output 'permanent-local t)
-(put 'comint-scroll-show-maximum-output 'permanent-local t)
-(put 'comint-ptyp 'permanent-local t)
-
-(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.
-Setting variable `comint-eol-on-send' means jump to the end of the line
-before submitting new input.
-
-This mode is customised to create major modes such as Inferior Lisp
-mode, Shell mode, etc. This can be done by setting the hooks
-`comint-input-filter-functions', `comint-input-filter', `comint-input-sender'
-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 `comint-input-ring-size', and
-can be accessed with the commands \\[comint-next-input], \\[comint-previous-input], and \\[comint-dynamic-list-input-ring].
-Input ring history expansion can be achieved with the commands
-\\[comint-replace-by-expanded-history] or \\[comint-magic-space].
-Input ring expansion is controlled by the variable `comint-input-autoexpand',
-and addition is controlled by the variable `comint-input-ignoredups'.
-
-Commands with no default key bindings include `send-invisible',
-`comint-dynamic-complete', `comint-dynamic-list-filename-completions', and
-`comint-magic-space'.
-
-Input to, and output from, the subprocess can cause the window to scroll to
-the end of the buffer. See variables `comint-output-filter-functions',
-`comint-scroll-to-bottom-on-input', and `comint-scroll-to-bottom-on-output'.
-
-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)
- ;; Do not remove this. All major modes must do this.
- (kill-all-local-variables)
- (setq major-mode 'comint-mode)
- (setq mode-name "Comint")
- (setq mode-line-process '(":%s"))
- (use-local-map comint-mode-map)
- (make-local-variable 'comint-last-input-start)
- (setq comint-last-input-start (make-marker))
- (set-marker comint-last-input-start (point-min))
- (make-local-variable 'comint-last-input-end)
- (setq comint-last-input-end (make-marker))
- (set-marker comint-last-input-end (point-min))
- (make-local-variable 'comint-last-output-start)
- (setq comint-last-output-start (make-marker))
- (make-local-variable 'comint-prompt-regexp) ; Don't set; default
- (make-local-variable 'comint-input-ring-size) ; ...to global val.
- (make-local-variable 'comint-input-ring)
- (make-local-variable 'comint-input-ring-file-name)
- (or (and (boundp 'comint-input-ring) comint-input-ring)
- (setq comint-input-ring (make-ring comint-input-ring-size)))
- (make-local-variable 'comint-input-ring-index)
- (or (and (boundp 'comint-input-ring-index) comint-input-ring-index)
- (setq comint-input-ring-index nil))
- (make-local-variable 'comint-matching-input-from-input-string)
- (make-local-variable 'comint-input-autoexpand)
- (make-local-variable 'comint-input-ignoredups)
- (make-local-variable 'comint-delimiter-argument-list)
- (make-local-hook 'comint-dynamic-complete-functions)
- (make-local-variable 'comint-completion-fignore)
- (make-local-variable 'comint-get-old-input)
- (make-local-hook 'comint-input-filter-functions)
- (make-local-variable 'comint-input-filter)
- (make-local-variable 'comint-input-sender)
- (make-local-variable 'comint-eol-on-send)
- (make-local-variable 'comint-scroll-to-bottom-on-input)
- (make-local-variable 'comint-scroll-to-bottom-on-output)
- (make-local-variable 'comint-scroll-show-maximum-output)
- (make-local-variable 'pre-command-hook)
- (add-hook 'pre-command-hook 'comint-preinput-scroll-to-bottom)
- (make-local-hook 'comint-output-filter-functions)
- (make-local-variable 'comint-ptyp)
- (make-local-variable 'comint-exec-hook)
- (make-local-variable 'comint-process-echoes)
- (make-local-variable 'comint-file-name-chars)
- (make-local-variable 'comint-file-name-quote-list)
- (run-hooks 'comint-mode-hook))
-
-(if comint-mode-map
- nil
- ;; Keys:
- (setq comint-mode-map (make-sparse-keymap))
- (define-key comint-mode-map "\ep" 'comint-previous-input)
- (define-key comint-mode-map "\en" 'comint-next-input)
- (define-key comint-mode-map [C-up] 'comint-previous-input)
- (define-key comint-mode-map [C-down] 'comint-next-input)
- (define-key comint-mode-map "\er" 'comint-previous-matching-input)
- (define-key comint-mode-map "\es" 'comint-next-matching-input)
- (define-key comint-mode-map [?\A-\M-r] 'comint-previous-matching-input-from-input)
- (define-key comint-mode-map [?\A-\M-s] 'comint-next-matching-input-from-input)
- (define-key comint-mode-map "\e\C-l" 'comint-show-output)
- (define-key comint-mode-map "\C-m" 'comint-send-input)
- (define-key comint-mode-map "\C-d" 'comint-delchar-or-maybe-eof)
- (define-key comint-mode-map "\C-c\C-a" 'comint-bol)
- (define-key comint-mode-map "\C-c\C-u" 'comint-kill-input)
- (define-key comint-mode-map "\C-c\C-w" 'backward-kill-word)
- (define-key comint-mode-map "\C-c\C-c" 'comint-interrupt-subjob)
- (define-key comint-mode-map "\C-c\C-z" 'comint-stop-subjob)
- (define-key comint-mode-map "\C-c\C-\\" 'comint-quit-subjob)
- (define-key comint-mode-map "\C-c\C-m" 'comint-copy-old-input)
- (define-key comint-mode-map "\C-c\C-o" 'comint-kill-output)
- (define-key comint-mode-map "\C-c\C-r" 'comint-show-output)
- (define-key comint-mode-map "\C-c\C-e" 'comint-show-maximum-output)
- (define-key comint-mode-map "\C-c\C-l" 'comint-dynamic-list-input-ring)
- (define-key comint-mode-map "\C-c\C-n" 'comint-next-prompt)
- (define-key comint-mode-map "\C-c\C-p" 'comint-previous-prompt)
- (define-key comint-mode-map "\C-c\C-d" 'comint-send-eof)
- ;; Menu bars:
- ;; completion:
- (define-key comint-mode-map [menu-bar completion]
- (cons "Complete" (make-sparse-keymap "Complete")))
- (define-key comint-mode-map [menu-bar completion complete-expand]
- '("Expand File Name" . comint-replace-by-expanded-filename))
- (define-key comint-mode-map [menu-bar completion complete-listing]
- '("File Completion Listing" . comint-dynamic-list-filename-completions))
- (define-key comint-mode-map [menu-bar completion complete-file]
- '("Complete File Name" . comint-dynamic-complete-filename))
- (define-key comint-mode-map [menu-bar completion complete]
- '("Complete Before Point" . comint-dynamic-complete))
- ;; Input history:
- (define-key comint-mode-map [menu-bar inout]
- (cons "In/Out" (make-sparse-keymap "In/Out")))
- (define-key comint-mode-map [menu-bar inout kill-output]
- '("Kill Current Output Group" . comint-kill-output))
- (define-key comint-mode-map [menu-bar inout next-prompt]
- '("Forward Output Group" . comint-next-prompt))
- (define-key comint-mode-map [menu-bar inout previous-prompt]
- '("Backward Output Group" . comint-previous-prompt))
- (define-key comint-mode-map [menu-bar inout show-maximum-output]
- '("Show Maximum Output" . comint-show-maximum-output))
- (define-key comint-mode-map [menu-bar inout show-output]
- '("Show Current Output Group" . comint-show-output))
- (define-key comint-mode-map [menu-bar inout kill-input]
- '("Kill Current Input" . comint-kill-input))
- (define-key comint-mode-map [menu-bar inout copy-input]
- '("Copy Old Input" . comint-copy-old-input))
- (define-key comint-mode-map [menu-bar inout forward-matching-history]
- '("Forward Matching Input..." . comint-forward-matching-input))
- (define-key comint-mode-map [menu-bar inout backward-matching-history]
- '("Backward Matching Input..." . comint-backward-matching-input))
- (define-key comint-mode-map [menu-bar inout next-matching-history]
- '("Next Matching Input..." . comint-next-matching-input))
- (define-key comint-mode-map [menu-bar inout previous-matching-history]
- '("Previous Matching Input..." . comint-previous-matching-input))
- (define-key comint-mode-map [menu-bar inout next-matching-history-from-input]
- '("Next Matching Current Input" . comint-next-matching-input-from-input))
- (define-key comint-mode-map [menu-bar inout previous-matching-history-from-input]
- '("Previous Matching Current Input" . comint-previous-matching-input-from-input))
- (define-key comint-mode-map [menu-bar inout next-history]
- '("Next Input" . comint-next-input))
- (define-key comint-mode-map [menu-bar inout previous-history]
- '("Previous Input" . comint-previous-input))
- (define-key comint-mode-map [menu-bar inout list-history]
- '("List Input History" . comint-dynamic-list-input-ring))
- (define-key comint-mode-map [menu-bar inout expand-history]
- '("Expand History Before Point" . comint-replace-by-expanded-history))
- ;; Signals
- (define-key comint-mode-map [menu-bar signals]
- (cons "Signals" (make-sparse-keymap "Signals")))
- (define-key comint-mode-map [menu-bar signals eof]
- '("EOF" . comint-send-eof))
- (define-key comint-mode-map [menu-bar signals kill]
- '("KILL" . comint-kill-subjob))
- (define-key comint-mode-map [menu-bar signals quit]
- '("QUIT" . comint-quit-subjob))
- (define-key comint-mode-map [menu-bar signals cont]
- '("CONT" . comint-continue-subjob))
- (define-key comint-mode-map [menu-bar signals stop]
- '("STOP" . comint-stop-subjob))
- (define-key comint-mode-map [menu-bar signals break]
- '("BREAK" . comint-interrupt-subjob))
- ;; Put them in the menu bar:
- (setq menu-bar-final-items (append '(completion inout signals)
- menu-bar-final-items))
- )
-
-(defun comint-check-proc (buffer)
- "Return t if there is a living process associated w/buffer BUFFER.
-Living means the status is `open', `run', or `stop'.
-BUFFER can be either a buffer or the name of one."
- (let ((proc (get-buffer-process buffer)))
- (and proc (memq (process-status proc) '(open run stop)))))
-
-;; Note that this guy, unlike shell.el's make-shell, barfs if you pass it ()
-;; for the second argument (program).
-;;;###autoload
-(defun make-comint (name program &optional startfile &rest switches)
- "Make a comint process NAME in a buffer, running PROGRAM.
-The name of the buffer is made by surrounding NAME with `*'s.
-PROGRAM should be either a string denoting an executable program to create
-via `start-process', or a cons pair of the form (HOST . SERVICE) denoting a TCP
-connection to be opened via `open-network-stream'. If there is already a
-running process in that buffer, it is not restarted. Optional third arg
-STARTFILE is the name of a file to send the contents of to the process.
-
-If PROGRAM is a string, any more args are arguments to PROGRAM."
- (or (fboundp 'start-process)
- (error "Multi-processing is not supported for this system"))
- (let ((buffer (get-buffer-create (concat "*" name "*"))))
- ;; 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))
-
-;;;###autoload
-(defun comint-run (program)
- "Run PROGRAM in a comint buffer and switch to it.
-The buffer name is made by surrounding the file name of PROGRAM with `*'s.
-The file name is used to make a symbol name, such as `comint-sh-hook', and any
-hooks on this symbol are run in the buffer.
-See `make-comint' and `comint-exec'."
- (interactive "sRun program: ")
- (let ((name (file-name-nondirectory program)))
- (switch-to-buffer (make-comint name program))
- (run-hooks (intern-soft (concat "comint-" name "-hook")))))
-
-(defun comint-exec (buffer name command startfile switches)
- "Start up a process in buffer 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 comint
-buffer. The hook `comint-exec-hook' is run after each exec."
- (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
- (if (consp command)
- (open-network-stream name buffer (car command) (cdr command))
- (comint-exec-1 name buffer command switches))))
- (set-process-filter proc 'comint-output-filter)
- (make-local-variable 'comint-ptyp)
- (setq comint-ptyp process-connection-type) ; T if pty, NIL if pipe.
- ;; Jump to the end, and set the process mark.
- (goto-char (point-max))
- (set-marker (process-mark proc) (point))
- ;; 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)))
- (run-hooks 'comint-exec-hook)
- buffer)))
-
-;; This auxiliary function cranks up the process for comint-exec in
-;; the appropriate environment.
-
-(defun comint-exec-1 (name buffer command switches)
- (let ((process-environment
- (nconc
- ;; If using termcap, we specify `emacs' as the terminal type
- ;; because that lets us specify a width.
- ;; If using terminfo, we specify `dumb' because that is
- ;; a defined terminal type. `emacs' is not a defined terminal type
- ;; and there is no way for us to define it here.
- ;; Some programs that use terminfo get very confused
- ;; if TERM is not a valid terminal type.
- (if (and (boundp 'system-uses-terminfo) system-uses-terminfo)
- (list "TERM=dumb"
- (format "COLUMNS=%d" (frame-width)))
- (list "TERM=emacs"
- (format "TERMCAP=emacs:co#%d:tc=unknown:" (frame-width))))
- (if (getenv "EMACS") nil (list "EMACS=t"))
- process-environment))
- (default-directory
- (if (file-directory-p default-directory)
- default-directory
- "/")))
- (apply 'start-process name buffer command switches)))
-
-;; Input history processing in a buffer
-;; ===========================================================================
-;; Useful input history functions, courtesy of the Ergo group.
-
-;; Eleven commands:
-;; comint-dynamic-list-input-ring List history in help buffer.
-;; comint-previous-input Previous input...
-;; comint-previous-matching-input ...matching a string.
-;; comint-previous-matching-input-from-input ... matching the current input.
-;; comint-next-input Next input...
-;; comint-next-matching-input ...matching a string.
-;; comint-next-matching-input-from-input ... matching the current input.
-;; comint-backward-matching-input Backwards input...
-;; comint-forward-matching-input ...matching a string.
-;; comint-replace-by-expanded-history Expand history at point;
-;; replace with expanded history.
-;; comint-magic-space Expand history and insert space.
-;;
-;; Three functions:
-;; comint-read-input-ring Read into comint-input-ring...
-;; comint-write-input-ring Write to comint-input-ring-file-name.
-;; comint-replace-by-expanded-history-before-point Workhorse function.
-
-(defun comint-read-input-ring (&optional silent)
- "Sets the buffer's `comint-input-ring' from a history file.
-The name of the file is given by the variable `comint-input-ring-file-name'.
-The history ring is of size `comint-input-ring-size', regardless of file size.
-If `comint-input-ring-file-name' is nil this function does nothing.
-
-If the optional argument SILENT is non-nil, we say nothing about a
-failure to read the history file.
-
-This function is useful for major mode commands and mode hooks.
-
-The structure of the history file should be one input command per line,
-with the most recent command last.
-See also `comint-input-ignoredups' and `comint-write-input-ring'."
- (cond ((or (null comint-input-ring-file-name)
- (equal comint-input-ring-file-name ""))
- nil)
- ((not (file-readable-p comint-input-ring-file-name))
- (or silent
- (message "Cannot read history file %s"
- comint-input-ring-file-name)))
- (t
- (let ((history-buf (get-buffer-create " *temp*"))
- (file comint-input-ring-file-name)
- (count 0)
- (ring (make-ring comint-input-ring-size)))
- (unwind-protect
- (save-excursion
- (set-buffer history-buf)
- (widen)
- (erase-buffer)
- (insert-file-contents file)
- ;; Save restriction in case file is already visited...
- ;; Watch for those date stamps in history files!
- (goto-char (point-max))
- (while (and (< count comint-input-ring-size)
- (re-search-backward "^[ \t]*\\([^#\n].*\\)[ \t]*$"
- nil t))
- (let ((history (buffer-substring (match-beginning 1)
- (match-end 1))))
- (if (or (null comint-input-ignoredups)
- (ring-empty-p ring)
- (not (string-equal (ring-ref ring 0) history)))
- (ring-insert-at-beginning ring history)))
- (setq count (1+ count))))
- (kill-buffer history-buf))
- (setq comint-input-ring ring
- comint-input-ring-index nil)))))
-
-(defun comint-write-input-ring ()
- "Writes the buffer's `comint-input-ring' to a history file.
-The name of the file is given by the variable `comint-input-ring-file-name'.
-The original contents of the file are lost if `comint-input-ring' is not empty.
-If `comint-input-ring-file-name' is nil this function does nothing.
-
-Useful within process sentinels.
-
-See also `comint-read-input-ring'."
- (cond ((or (null comint-input-ring-file-name)
- (equal comint-input-ring-file-name "")
- (null comint-input-ring) (ring-empty-p comint-input-ring))
- nil)
- ((not (file-writable-p comint-input-ring-file-name))
- (message "Cannot write history file %s" comint-input-ring-file-name))
- (t
- (let* ((history-buf (get-buffer-create " *Temp Input History*"))
- (ring comint-input-ring)
- (file comint-input-ring-file-name)
- (index (ring-length ring)))
- ;; Write it all out into a buffer first. Much faster, but messier,
- ;; than writing it one line at a time.
- (save-excursion
- (set-buffer history-buf)
- (erase-buffer)
- (while (> index 0)
- (setq index (1- index))
- (insert (ring-ref ring index) ?\n))
- (write-region (buffer-string) nil file nil 'no-message)
- (kill-buffer nil))))))
-
-
-(defun comint-dynamic-list-input-ring ()
- "List in help buffer the buffer's input history."
- (interactive)
- (if (or (not (ring-p comint-input-ring))
- (ring-empty-p comint-input-ring))
- (message "No history")
- (let ((history nil)
- (history-buffer " *Input History*")
- (index (1- (ring-length comint-input-ring)))
- (conf (current-window-configuration)))
- ;; We have to build up a list ourselves from the ring vector.
- (while (>= index 0)
- (setq history (cons (ring-ref comint-input-ring index) history)
- index (1- index)))
- ;; Change "completion" to "history reference"
- ;; to make the display accurate.
- (with-output-to-temp-buffer history-buffer
- (display-completion-list history)
- (set-buffer history-buffer)
- (forward-line 3)
- (while (search-backward "completion" nil 'move)
- (replace-match "history reference")))
- (sit-for 0)
- (message "Hit space to flush")
- (let ((ch (read-event)))
- (if (eq ch ?\ )
- (set-window-configuration conf)
- (setq unread-command-events (list ch)))))))
-
-
-(defun comint-regexp-arg (prompt)
- ;; Return list of regexp and prefix arg using PROMPT.
- (let* ((minibuffer-history-sexp-flag nil)
- ;; Don't clobber this.
- (last-command last-command)
- (regexp (read-from-minibuffer prompt nil nil nil
- 'minibuffer-history-search-history)))
- (list (if (string-equal regexp "")
- (setcar minibuffer-history-search-history
- (nth 1 minibuffer-history-search-history))
- regexp)
- (prefix-numeric-value current-prefix-arg))))
-
-(defun comint-search-arg (arg)
- ;; First make sure there is a ring and that we are after the process mark
- (cond ((not (comint-after-pmark-p))
- (error "Not at command line"))
- ((or (null comint-input-ring)
- (ring-empty-p comint-input-ring))
- (error "Empty input ring"))
- ((zerop arg)
- ;; arg of zero resets search from beginning, and uses arg of 1
- (setq comint-input-ring-index nil)
- 1)
- (t
- arg)))
-
-(defun comint-search-start (arg)
- ;; Index to start a directional search, starting at comint-input-ring-index
- (if comint-input-ring-index
- ;; If a search is running, offset by 1 in direction of arg
- (mod (+ comint-input-ring-index (if (> arg 0) 1 -1))
- (ring-length comint-input-ring))
- ;; For a new search, start from beginning or end, as appropriate
- (if (>= arg 0)
- 0 ; First elt for forward search
- (1- (ring-length comint-input-ring))))) ; Last elt for backward search
-
-(defun comint-previous-input-string (arg)
- "Return the string ARG places along the input ring.
-Moves relative to `comint-input-ring-index'."
- (ring-ref comint-input-ring (if comint-input-ring-index
- (mod (+ arg comint-input-ring-index)
- (ring-length comint-input-ring))
- arg)))
-
-(defun comint-previous-input (arg)
- "Cycle backwards through input history."
- (interactive "*p")
- (comint-previous-matching-input "." arg))
-
-(defun comint-next-input (arg)
- "Cycle forwards through input history."
- (interactive "*p")
- (comint-previous-input (- arg)))
-
-(defun comint-previous-matching-input-string (regexp arg)
- "Return the string matching REGEXP ARG places along the input ring.
-Moves relative to `comint-input-ring-index'."
- (let* ((pos (comint-previous-matching-input-string-position regexp arg)))
- (if pos (ring-ref comint-input-ring pos))))
-
-(defun comint-previous-matching-input-string-position (regexp arg &optional start)
- "Return the index matching REGEXP ARG places along the input ring.
-Moves relative to START, or `comint-input-ring-index'."
- (if (or (not (ring-p comint-input-ring))
- (ring-empty-p comint-input-ring))
- (error "No history"))
- (let* ((len (ring-length comint-input-ring))
- (motion (if (> arg 0) 1 -1))
- (n (mod (- (or start (comint-search-start arg)) motion) len))
- (tried-each-ring-item nil)
- (prev nil))
- ;; Do the whole search as many times as the argument says.
- (while (and (/= arg 0) (not tried-each-ring-item))
- ;; Step once.
- (setq prev n
- n (mod (+ n motion) len))
- ;; If we haven't reached a match, step some more.
- (while (and (< n len) (not tried-each-ring-item)
- (not (string-match regexp (ring-ref comint-input-ring n))))
- (setq n (mod (+ n motion) len)
- ;; If we have gone all the way around in this search.
- tried-each-ring-item (= n prev)))
- (setq arg (if (> arg 0) (1- arg) (1+ arg))))
- ;; Now that we know which ring element to use, if we found it, return that.
- (if (string-match regexp (ring-ref comint-input-ring n))
- n)))
-
-(defun comint-previous-matching-input (regexp arg)
- "Search backwards through input history for match for REGEXP.
-\(Previous history elements are earlier commands.)
-With prefix argument N, search for Nth previous match.
-If N is negative, find the next or Nth next match."
- (interactive (comint-regexp-arg "Previous input matching (regexp): "))
- (setq arg (comint-search-arg arg))
- (let ((pos (comint-previous-matching-input-string-position regexp arg)))
- ;; Has a match been found?
- (if (null pos)
- (error "Not found")
- (setq comint-input-ring-index pos)
- (message "History item: %d" (1+ pos))
- (delete-region
- ;; Can't use kill-region as it sets this-command
- (process-mark (get-buffer-process (current-buffer))) (point))
- (insert (ring-ref comint-input-ring pos)))))
-
-(defun comint-next-matching-input (regexp arg)
- "Search forwards through input history for match for REGEXP.
-\(Later history elements are more recent commands.)
-With prefix argument N, search for Nth following match.
-If N is negative, find the previous or Nth previous match."
- (interactive (comint-regexp-arg "Next input matching (regexp): "))
- (comint-previous-matching-input regexp (- arg)))
-
-(defun comint-previous-matching-input-from-input (arg)
- "Search backwards through input history for match for current input.
-\(Previous history elements are earlier commands.)
-With prefix argument N, search for Nth previous match.
-If N is negative, search forwards for the -Nth following match."
- (interactive "p")
- (if (not (memq last-command '(comint-previous-matching-input-from-input
- comint-next-matching-input-from-input)))
- ;; Starting a new search
- (setq comint-matching-input-from-input-string
- (buffer-substring
- (process-mark (get-buffer-process (current-buffer)))
- (point))
- comint-input-ring-index nil))
- (comint-previous-matching-input
- (concat "^" (regexp-quote comint-matching-input-from-input-string))
- arg))
-
-(defun comint-next-matching-input-from-input (arg)
- "Search forwards through input history for match for current input.
-\(Following history elements are more recent commands.)
-With prefix argument N, search for Nth following match.
-If N is negative, search backwards for the -Nth previous match."
- (interactive "p")
- (comint-previous-matching-input-from-input (- arg)))
-
-
-(defun comint-replace-by-expanded-history (&optional silent)
- "Expand input command history references before point.
-Expansion is dependent on the value of `comint-input-autoexpand'.
-
-This function depends on the buffer's idea of the input history, which may not
-match the command interpreter's idea, assuming it has one.
-
-Assumes history syntax is like typical Un*x shells'. However, since emacs
-cannot know the interpreter's idea of input line numbers, assuming it has one,
-it cannot expand absolute input line number references.
-
-If the optional argument SILENT is non-nil, never complain
-even if history reference seems erroneous.
-
-See `comint-magic-space' and `comint-replace-by-expanded-history-before-point'.
-
-Returns t if successful."
- (interactive)
- (if (and comint-input-autoexpand
- (string-match "!\\|^\\^" (funcall comint-get-old-input))
- (save-excursion (beginning-of-line)
- (looking-at comint-prompt-regexp)))
- ;; Looks like there might be history references in the command.
- (let ((previous-modified-tick (buffer-modified-tick)))
- (message "Expanding history references...")
- (comint-replace-by-expanded-history-before-point silent)
- (/= previous-modified-tick (buffer-modified-tick)))))
-
-
-(defun comint-replace-by-expanded-history-before-point (silent)
- "Expand directory stack reference before point.
-See `comint-replace-by-expanded-history'. Returns t if successful."
- (save-excursion
- (let ((toend (- (save-excursion (end-of-line nil) (point)) (point)))
- (start (progn (comint-bol nil) (point))))
- (while (progn
- (skip-chars-forward "^!^"
- (save-excursion
- (end-of-line nil) (- (point) toend)))
- (< (point)
- (save-excursion
- (end-of-line nil) (- (point) toend))))
- ;; This seems a bit complex. We look for references such as !!, !-num,
- ;; !foo, !?foo, !{bar}, !?{bar}, ^oh, ^my^, ^god^it, ^never^ends^.
- ;; If that wasn't enough, the plings can be suffixed with argument
- ;; range specifiers.
- ;; Argument ranges are complex too, so we hive off the input line,
- ;; referenced with plings, with the range string to `comint-args'.
- (setq comint-input-ring-index nil)
- (cond ((or (= (preceding-char) ?\\)
- (comint-within-quotes start (point)))
- ;; The history is quoted, or we're in quotes.
- (goto-char (1+ (point))))
- ((looking-at "![0-9]+\\($\\|[^-]\\)")
- ;; We cannot know the interpreter's idea of input line numbers.
- (goto-char (match-end 0))
- (message "Absolute reference cannot be expanded"))
- ((looking-at "!-\\([0-9]+\\)\\(:?[0-9^$*-]+\\)?")
- ;; Just a number of args from `number' lines backward.
- (let ((number (1- (string-to-number
- (buffer-substring (match-beginning 1)
- (match-end 1))))))
- (if (<= number (ring-length comint-input-ring))
- (progn
- (replace-match
- (comint-args (comint-previous-input-string number)
- (match-beginning 2) (match-end 2))
- t t)
- (setq comint-input-ring-index number)
- (message "History item: %d" (1+ number)))
- (goto-char (match-end 0))
- (message "Relative reference exceeds input history size"))))
- ((or (looking-at "!!?:?\\([0-9^$*-]+\\)") (looking-at "!!"))
- ;; Just a number of args from the previous input line.
- (replace-match
- (comint-args (comint-previous-input-string 0)
- (match-beginning 1) (match-end 1))
- t t)
- (message "History item: previous"))
- ((looking-at
- "!\\??\\({\\(.+\\)}\\|\\(\\sw+\\)\\)\\(:?[0-9^$*-]+\\)?")
- ;; Most recent input starting with or containing (possibly
- ;; protected) string, maybe just a number of args. Phew.
- (let* ((mb1 (match-beginning 1)) (me1 (match-end 1))
- (mb2 (match-beginning 2)) (me2 (match-end 2))
- (exp (buffer-substring (or mb2 mb1) (or me2 me1)))
- (pref (if (save-match-data (looking-at "!\\?")) "" "^"))
- (pos (save-match-data
- (comint-previous-matching-input-string-position
- (concat pref (regexp-quote exp)) 1))))
- (if (null pos)
- (progn
- (goto-char (match-end 0))
- (or silent
- (progn (message "Not found")
- (ding))))
- (setq comint-input-ring-index pos)
- (replace-match
- (comint-args (ring-ref comint-input-ring pos)
- (match-beginning 4) (match-end 4))
- t t)
- (message "History item: %d" (1+ pos)))))
- ((looking-at "\\^\\([^^]+\\)\\^?\\([^^]*\\)\\^?")
- ;; Quick substitution on the previous input line.
- (let ((old (buffer-substring (match-beginning 1) (match-end 1)))
- (new (buffer-substring (match-beginning 2) (match-end 2)))
- (pos nil))
- (replace-match (comint-previous-input-string 0) t t)
- (setq pos (point))
- (goto-char (match-beginning 0))
- (if (not (search-forward old pos t))
- (or silent
- (error "Not found"))
- (replace-match new t t)
- (message "History item: substituted"))))
- (t
- (goto-char (match-end 0))))))))
-
-
-(defun comint-magic-space (arg)
- "Expand input history references before point and insert ARG spaces.
-A useful command to bind to SPC. See `comint-replace-by-expanded-history'."
- (interactive "p")
- (comint-replace-by-expanded-history)
- (self-insert-command arg))
-
-(defun comint-within-quotes (beg end)
- "Return t if the number of quotes between BEG and END is odd.
-Quotes are single and double."
- (let ((countsq (comint-how-many-region "\\(^\\|[^\\\\]\\)\'" beg end))
- (countdq (comint-how-many-region "\\(^\\|[^\\\\]\\)\"" beg end)))
- (or (= (mod countsq 2) 1) (= (mod countdq 2) 1))))
-
-(defun comint-how-many-region (regexp beg end)
- "Return number of matches for REGEXP from BEG to END."
- (let ((count 0))
- (save-excursion
- (save-match-data
- (goto-char beg)
- (while (re-search-forward regexp end t)
- (setq count (1+ count)))))
- count))
-
-(defun comint-args (string begin end)
- ;; From STRING, return the args depending on the range specified in the text
- ;; from BEGIN to END. If BEGIN is nil, assume all args. Ignore leading `:'.
- ;; Range can be x-y, x-, -y, where x/y can be [0-9], *, ^, $.
- (save-match-data
- (if (null begin)
- (comint-arguments string 0 nil)
- (let* ((range (buffer-substring
- (if (eq (char-after begin) ?:) (1+ begin) begin) end))
- (nth (cond ((string-match "^[*^]" range) 1)
- ((string-match "^-" range) 0)
- ((string-equal range "$") nil)
- (t (string-to-number range))))
- (mth (cond ((string-match "[-*$]$" range) nil)
- ((string-match "-" range)
- (string-to-number (substring range (match-end 0))))
- (t nth))))
- (comint-arguments string nth mth)))))
-
-;; Return a list of arguments from ARG. Break it up at the
-;; delimiters in comint-delimiter-argument-list. Returned list is backwards.
-(defun comint-delim-arg (arg)
- (if (null comint-delimiter-argument-list)
- (list arg)
- (let ((args nil)
- (pos 0)
- (len (length arg)))
- (while (< pos len)
- (let ((char (aref arg pos))
- (start pos))
- (if (memq char comint-delimiter-argument-list)
- (while (and (< pos len) (eq (aref arg pos) char))
- (setq pos (1+ pos)))
- (while (and (< pos len)
- (not (memq (aref arg pos)
- comint-delimiter-argument-list)))
- (setq pos (1+ pos))))
- (setq args (cons (substring arg start pos) args))))
- args)))
-
-(defun comint-arguments (string nth mth)
- "Return from STRING the NTH to MTH arguments.
-NTH and/or MTH can be nil, which means the last argument.
-Returned arguments are separated by single spaces.
-We assume whitespace separates arguments, except within quotes.
-Also, a run of one or more of a single character
-in `comint-delimiter-argument-list' is a separate argument.
-Argument 0 is the command name."
- (let ((argpart "[^ \n\t\"'`]+\\|\\(\"[^\"]*\"\\|'[^']*'\\|`[^`]*`\\)")
- (args ()) (pos 0)
- (count 0)
- beg str value quotes)
- ;; Build a list of all the args until we have as many as we want.
- (while (and (or (null mth) (<= count mth))
- (string-match argpart string pos))
- (if (and beg (= pos (match-beginning 0)))
- ;; It's contiguous, part of the same arg.
- (setq pos (match-end 0)
- quotes (or quotes (match-beginning 1)))
- ;; It's a new separate arg.
- (if beg
- ;; Put the previous arg, if there was one, onto ARGS.
- (setq str (substring string beg pos)
- args (if quotes (cons str args)
- (nconc (comint-delim-arg str) args))
- count (1+ count)))
- (setq quotes (match-beginning 1))
- (setq beg (match-beginning 0))
- (setq pos (match-end 0))))
- (if beg
- (setq str (substring string beg pos)
- args (if quotes (cons str args)
- (nconc (comint-delim-arg str) args))
- count (1+ count)))
- (let ((n (or nth (1- count)))
- (m (if mth (1- (- count mth)) 0)))
- (mapconcat
- (function (lambda (a) a)) (nthcdr n (nreverse (nthcdr m args))) " "))))
-
-;;
-;; Input processing stuff
-;;
-
-(defun comint-send-input ()
- "Send input to process.
-After the process output mark, sends all text from the process mark to
-point as input to the process. Before the process output mark, calls value
-of variable `comint-get-old-input' to retrieve old input, copies it to the
-process mark, and sends it. If variable `comint-process-echoes' is nil,
-a terminal newline is also inserted into the buffer and sent to the process
-\(if it is non-nil, all text from the process mark to point is deleted,
-since it is assumed the remote process will re-echo it).
-
-Any history reference may be expanded depending on the value of the variable
-`comint-input-autoexpand'. The list of function names contained in the value
-of `comint-input-filter-functions' is called on the input before sending it.
-The input is entered into the input history ring, if the value of variable
-`comint-input-filter' returns non-nil when called on the input.
-
-If variable `comint-eol-on-send' is non-nil, then point is moved to the
-end of line before sending the input.
-
-The values of `comint-get-old-input', `comint-input-filter-functions', and
-`comint-input-filter' are chosen according to the command interpreter running
-in the buffer. E.g.,
-
-If the interpreter is the csh,
- comint-get-old-input is the default: take the current line, discard any
- initial string matching regexp comint-prompt-regexp.
- comint-input-filter-functions monitors input for \"cd\", \"pushd\", and
- \"popd\" commands. When it sees one, it cd's the buffer.
- comint-input-filter is the default: returns t if the input isn't all white
- space.
-
-If the comint is Lucid Common Lisp,
- comint-get-old-input snarfs the sexp ending at point.
- comint-input-filter-functions does nothing.
- comint-input-filter returns nil if the input matches input-filter-regexp,
- which matches (1) all whitespace (2) :a, :c, etc.
-
-Similarly for Soar, Scheme, etc."
- (interactive)
- ;; Note that the input string does not include its terminal newline.
- (let ((proc (get-buffer-process (current-buffer))))
- (if (not proc) (error "Current buffer has no process")
- (let* ((pmark (process-mark proc))
- (intxt (if (>= (point) (marker-position pmark))
- (progn (if comint-eol-on-send (end-of-line))
- (buffer-substring pmark (point)))
- (let ((copy (funcall comint-get-old-input)))
- (goto-char pmark)
- (insert copy)
- copy)))
- (input (if (not (eq comint-input-autoexpand 'input))
- ;; Just whatever's already there
- intxt
- ;; Expand and leave it visible in buffer
- (comint-replace-by-expanded-history t)
- (buffer-substring pmark (point))))
- (history (if (not (eq comint-input-autoexpand 'history))
- input
- ;; This is messy 'cos ultimately the original
- ;; functions used do insertion, rather than return
- ;; strings. We have to expand, then insert back.
- (comint-replace-by-expanded-history t)
- (let ((copy (buffer-substring pmark (point))))
- (delete-region pmark (point))
- (insert-before-markers input)
- copy))))
- (if comint-process-echoes
- (delete-region pmark (point))
- (insert-before-markers ?\n))
- (if (and (funcall comint-input-filter history)
- (or (null comint-input-ignoredups)
- (not (ring-p comint-input-ring))
- (ring-empty-p comint-input-ring)
- (not (string-equal (ring-ref comint-input-ring 0)
- history))))
- (ring-insert comint-input-ring history))
- (run-hook-with-args 'comint-input-filter-functions
- (concat input "\n"))
- (setq comint-input-ring-index nil)
- ;; Update the markers before we send the input
- ;; in case we get output amidst sending the input.
- (set-marker comint-last-input-start pmark)
- (set-marker comint-last-input-end (point))
- (set-marker (process-mark proc) (point))
- (funcall comint-input-sender proc input)
- ;; This used to call comint-output-filter-functions,
- ;; but that scrolled the buffer in undesirable ways.
- (run-hook-with-args 'comint-output-filter-functions "")))))
-
-;; The purpose of using this filter for comint processes
-;; is to keep comint-last-input-end from moving forward
-;; when output is inserted.
-(defun comint-output-filter (process string)
- ;; First check for killed buffer
- (let ((oprocbuf (process-buffer process)))
- (if (and oprocbuf (buffer-name oprocbuf))
- (let ((obuf (current-buffer))
- (opoint nil) (obeg nil) (oend nil))
- (set-buffer oprocbuf)
- (setq opoint (point))
- (setq obeg (point-min))
- (setq oend (point-max))
- (let ((buffer-read-only nil)
- (nchars (length string))
- (ostart nil))
- (widen)
- (goto-char (process-mark process))
- (setq ostart (point))
- (if (<= (point) opoint)
- (setq opoint (+ opoint nchars)))
- ;; Insert after old_begv, but before old_zv.
- (if (< (point) obeg)
- (setq obeg (+ obeg nchars)))
- (if (<= (point) oend)
- (setq oend (+ oend nchars)))
- (insert-before-markers string)
- ;; Don't insert initial prompt outside the top of the window.
- (if (= (window-start (selected-window)) (point))
- (set-window-start (selected-window) (- (point) (length string))))
- (if (and comint-last-input-end
- (marker-buffer comint-last-input-end)
- (= (point) comint-last-input-end))
- (set-marker comint-last-input-end (- comint-last-input-end nchars)))
- (set-marker comint-last-output-start ostart)
- (set-marker (process-mark process) (point))
- (force-mode-line-update))
-
- (narrow-to-region obeg oend)
- (goto-char opoint)
- (run-hook-with-args 'comint-output-filter-functions string)
- (set-buffer obuf)))))
-
-(defun comint-preinput-scroll-to-bottom ()
- "Go to the end of buffer in all windows showing it.
-Movement occurs if point in the selected window is not after the process mark,
-and `this-command' is an insertion command. Insertion commands recognised
-are `self-insert-command', `comint-magic-space', `yank', and `hilit-yank'.
-Depends on the value of `comint-scroll-to-bottom-on-input'.
-
-This function should be a pre-command hook."
- (if (and comint-scroll-to-bottom-on-input
- (memq this-command '(self-insert-command comint-magic-space yank
- hilit-yank)))
- (let* ((selected (selected-window))
- (current (current-buffer))
- (process (get-buffer-process current))
- (scroll comint-scroll-to-bottom-on-input))
- (if (and process (< (point) (process-mark process)))
- (if (eq scroll 'this)
- (goto-char (point-max))
- (walk-windows
- (function (lambda (window)
- (if (and (eq (window-buffer window) current)
- (or (eq scroll t) (eq scroll 'all)))
- (progn
- (select-window window)
- (goto-char (point-max))
- (select-window selected)))))
- nil t))))))
-
-(defun comint-postoutput-scroll-to-bottom (string)
- "Go to the end of buffer in all windows showing it.
-Does not scroll if the current line is the last line in the buffer.
-Depends on the value of `comint-scroll-to-bottom-on-output' and
-`comint-scroll-show-maximum-output'.
-
-This function should be in the list `comint-output-filter-functions'."
- (let* ((selected (selected-window))
- (current (current-buffer))
- (process (get-buffer-process current))
- (scroll comint-scroll-to-bottom-on-output))
- (unwind-protect
- (if process
- (walk-windows
- (function (lambda (window)
- (if (eq (window-buffer window) current)
- (progn
- (select-window window)
- (if (and (< (point) (process-mark process))
- (or (eq scroll t) (eq scroll 'all)
- ;; Maybe user wants point to jump to end.
- (and (eq scroll 'this) (eq selected window))
- (and (eq scroll 'others) (not (eq selected window)))
- ;; If point was at the end, keep it at end.
- (>= (point) comint-last-output-start)))
- (goto-char (process-mark process)))
- ;; Optionally scroll so that the text
- ;; ends at the bottom of the window.
- (if (and comint-scroll-show-maximum-output
- (>= (point) (process-mark process)))
- (save-excursion
- (goto-char (point-max))
- (recenter -1)))
- (select-window selected)))))
- nil t))
- (set-buffer current))))
-
-(defun comint-truncate-buffer (&optional string)
- "Truncate the buffer to `comint-buffer-maximum-size'.
-This function could be on `comint-output-filter-functions' or bound to a key."
- (interactive)
- (save-excursion
- (goto-char (process-mark (get-buffer-process (current-buffer))))
- (forward-line (- comint-buffer-maximum-size))
- (beginning-of-line)
- (delete-region (point-min) (point))))
-
-(defun comint-strip-ctrl-m (&optional string)
- "Strip trailing `^M' characters from the current output group.
-This function could be on `comint-output-filter-functions' or bound to a key."
- (interactive)
- (let ((pmark (process-mark (get-buffer-process (current-buffer)))))
- (save-excursion
- (goto-char
- (if (interactive-p) comint-last-input-end comint-last-output-start))
- (while (re-search-forward "\r+$" pmark t)
- (replace-match "" t t)))))
-(defalias 'shell-strip-ctrl-m 'comint-strip-ctrl-m)
-
-(defun comint-show-maximum-output ()
- "Put the end of the buffer at the bottom of the window."
- (interactive)
- (goto-char (point-max))
- (recenter -1))
-
-(defun comint-get-old-input-default ()
- "Default for `comint-get-old-input'.
-Take the current line, and discard any initial text matching
-`comint-prompt-regexp'."
- (save-excursion
- (beginning-of-line)
- (comint-skip-prompt)
- (let ((beg (point)))
- (end-of-line)
- (buffer-substring beg (point)))))
-
-(defun comint-copy-old-input ()
- "Insert after prompt old input at point as new input to be edited.
-Calls `comint-get-old-input' to get old input."
- (interactive)
- (let ((input (funcall comint-get-old-input))
- (process (get-buffer-process (current-buffer))))
- (if (not process)
- (error "Current buffer has no process")
- (goto-char (process-mark process))
- (insert input))))
-
-(defun comint-skip-prompt ()
- "Skip past the text matching regexp `comint-prompt-regexp'.
-If this takes us past the end of the current line, don't skip at all."
- (let ((eol (save-excursion (end-of-line) (point))))
- (if (and (looking-at comint-prompt-regexp)
- (<= (match-end 0) eol))
- (goto-char (match-end 0)))))
-
-(defun comint-after-pmark-p ()
- "Return t if point is after the process output marker."
- (let ((pmark (process-mark (get-buffer-process (current-buffer)))))
- (<= (marker-position pmark) (point))))
-
-(defun comint-simple-send (proc string)
- "Default function for sending to PROC input STRING.
-This just sends STRING plus a newline. To override this,
-set the hook `comint-input-sender'."
- (comint-send-string proc string)
- (comint-send-string proc "\n"))
-
-(defun comint-bol (arg)
- "Goes to the beginning of line, then skips past the prompt, if any.
-If prefix argument is given (\\[universal-argument]) the prompt is not skipped.
-
-The prompt skip is done by skipping text matching the regular expression
-`comint-prompt-regexp', a buffer local variable."
- (interactive "P")
- (beginning-of-line)
- (if (null arg) (comint-skip-prompt)))
-
-;; These three 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, or add
-;; `comint-watch-for-password-prompt' to `comint-output-filter-functions'.
-
-(defun comint-read-noecho (prompt &optional stars)
- "Read a single line of text from user without echoing, and return it.
-Prompt with argument PROMPT, a string. Optional argument STARS causes
-input to be echoed with '*' characters on the prompt line. Input ends with
-RET, LFD, or ESC. DEL or C-h rubs out. C-u kills line. C-g aborts (if
-`inhibit-quit' is set because e.g. this function was called from a process
-filter and C-g is pressed, this function returns nil rather than a string).
-
-Note that the keystrokes comprising the text can still be recovered
-\(temporarily) with \\[view-lossage]. Some people find this worrysome.
-Once the caller uses the password, it can erase the password
-by doing (fillarray STRING 0)."
- (let ((ans "")
- (newans nil)
- (c 0)
- (echo-keystrokes 0)
- (cursor-in-echo-area t)
- (message-log-max nil)
- (done nil))
- (while (not done)
- (if stars
- (message "%s%s" prompt (make-string (length ans) ?*))
- (message "%s" prompt))
- ;; Use this instead of `read-char' to avoid "Non-character input-event".
- (setq c (read-char-exclusive))
- (cond ((= c ?\C-g)
- ;; This function may get called from a process filter, where
- ;; inhibit-quit is set. In later versions of emacs read-char
- ;; may clear quit-flag itself and return C-g. That would make
- ;; it impossible to quit this loop in a simple way, so
- ;; re-enable it here (for backward-compatibility the check for
- ;; quit-flag below would still be necessary, so this seems
- ;; like the simplest way to do things).
- (setq quit-flag t
- done t))
- ((or (= c ?\r) (= c ?\n) (= c ?\e))
- (setq done t))
- ((= c ?\C-u)
- (fillarray ans 0)
- (setq ans ""))
- ((and (/= c ?\b) (/= c ?\177))
- (setq newans (concat ans (char-to-string c)))
- (fillarray ans 0)
- (setq ans newans))
- ((> (length ans) 0)
- (aset ans (1- (length ans)) 0)
- (setq ans (substring ans 0 -1)))))
- (if quit-flag
- ;; Emulate a true quit, except that we have to return a value.
- (prog1
- (setq quit-flag nil)
- (message "Quit")
- (beep t))
- (message "")
- ans)))
-
-(defun send-invisible (str)
- "Read a string without echoing.
-Then send it to the process running in the current buffer.
-The string is sent using `comint-input-sender'.
-Security bug: your string can still be temporarily recovered with
-\\[view-lossage]."
- (interactive "P") ; Defeat snooping via C-x ESC ESC
- (let ((proc (get-buffer-process (current-buffer))))
- (if (not proc)
- (error "Current buffer has no process")
- (funcall comint-input-sender proc
- (if (stringp str) str (comint-read-noecho "Non-echoed text: " t))))))
-
-(defun comint-watch-for-password-prompt (string)
- "Prompt in the minibuffer for password and send without echoing.
-This function uses `send-invisible' to read and send a password to the buffer's
-process if STRING contains a password prompt defined by
-`comint-password-prompt-regexp'.
-
-This function could be in the list `comint-output-filter-functions'."
- (if (string-match comint-password-prompt-regexp string)
- (send-invisible nil)))
-
-;; Low-level process communication
-
-(defalias 'comint-send-string 'process-send-string)
-(defalias 'comint-send-region 'process-send-region)
-
-;; Random input hackage
-
-(defun comint-kill-output ()
- "Kill all output from interpreter since last input.
-Does not delete the prompt."
- (interactive)
- (let ((proc (get-buffer-process (current-buffer)))
- (replacement nil))
- (save-excursion
- (let ((pmark (progn (goto-char (process-mark proc))
- (beginning-of-line nil)
- (point-marker))))
- (delete-region comint-last-input-end pmark)
- (goto-char (process-mark proc))
- (setq replacement (concat "*** output flushed ***\n"
- (buffer-substring pmark (point))))
- (delete-region pmark (point))))
- ;; Output message and put back prompt
- (comint-output-filter proc replacement)))
-
-(defun comint-show-output ()
- "Display start of this batch of interpreter output at top of window.
-Sets mark to the value of point when this command is run."
- (interactive)
- (push-mark)
- (let ((pos (point)))
- (goto-char (or (marker-position comint-last-input-end) (point-max)))
- (beginning-of-line 0)
- (set-window-start (selected-window) (point))
- (comint-skip-prompt)))
-
-(defun comint-interrupt-subjob ()
- "Interrupt the current subjob."
- (interactive)
- (interrupt-process nil comint-ptyp))
-
-(defun comint-kill-subjob ()
- "Send kill signal to the current subjob."
- (interactive)
- (kill-process nil comint-ptyp))
-
-(defun comint-quit-subjob ()
- "Send quit signal to the current subjob."
- (interactive)
- (quit-process nil comint-ptyp))
-
-(defun comint-stop-subjob ()
- "Stop the current subjob.
-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 comint-ptyp))
-
-(defun comint-continue-subjob ()
- "Send CONT signal to process buffer's process group.
-Useful if you accidentally suspend the top-level process."
- (interactive)
- (continue-process nil comint-ptyp))
-
-(defun comint-kill-input ()
- "Kill all text from last stuff output by interpreter to point."
- (interactive)
- (let ((pmark (process-mark (get-buffer-process (current-buffer)))))
- (if (> (point) (marker-position pmark))
- (kill-region pmark (point)))))
-
-(defun comint-delchar-or-maybe-eof (arg)
- "Delete ARG characters forward, or (if at eob) send an EOF to subprocess."
- (interactive "p")
- (if (eobp)
- (process-send-eof)
- (delete-char arg)))
-
-(defun comint-send-eof ()
- "Send an EOF to the current buffer's process."
- (interactive)
- (process-send-eof))
-
-
-(defun comint-backward-matching-input (regexp arg)
- "Search backward through buffer for match for REGEXP.
-Matches are searched for on lines that match `comint-prompt-regexp'.
-With prefix argument N, search for Nth previous match.
-If N is negative, find the next or Nth next match."
- (interactive (comint-regexp-arg "Backward input matching (regexp): "))
- (let* ((re (concat comint-prompt-regexp ".*" regexp))
- (pos (save-excursion (end-of-line (if (> arg 0) 0 1))
- (if (re-search-backward re nil t arg)
- (point)))))
- (if (null pos)
- (progn (message "Not found")
- (ding))
- (goto-char pos)
- (comint-bol nil))))
-
-(defun comint-forward-matching-input (regexp arg)
- "Search forward through buffer for match for REGEXP.
-Matches are searched for on lines that match `comint-prompt-regexp'.
-With prefix argument N, search for Nth following match.
-If N is negative, find the previous or Nth previous match."
- (interactive (comint-regexp-arg "Forward input matching (regexp): "))
- (comint-backward-matching-input regexp (- arg)))
-
-
-(defun comint-next-prompt (n)
- "Move to end of Nth next prompt in the buffer.
-See `comint-prompt-regexp'."
- (interactive "p")
- (let ((paragraph-start comint-prompt-regexp))
- (end-of-line (if (> n 0) 1 0))
- (forward-paragraph n)
- (comint-skip-prompt)))
-
-(defun comint-previous-prompt (n)
- "Move to end of Nth previous prompt in the buffer.
-See `comint-prompt-regexp'."
- (interactive "p")
- (comint-next-prompt (- n)))
-
-;; 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, cmulisp, and cmuscheme 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 CMU
-;; 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 ()
- "Return 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
- (condition-case ()
- (file-exists-p stringfile)
- (error nil))
- (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)))))
-
-;; I am somewhat divided on this string-default feature. It seems
-;; to violate the principle-of-least-astonishment, in that it makes
-;; the default harder to predict, so you actually have to look and see
-;; what the default really is before choosing it. This can trip you up.
-;; On the other hand, it can be useful, I guess. I would appreciate feedback
-;; on this.
-;; -Olin
-
-
-;; 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/command/history completion in a buffer
-;; ===========================================================================
-;; Useful completion functions, courtesy of the Ergo group.
-
-;; Six commands:
-;; comint-dynamic-complete Complete or expand command, filename,
-;; history at point.
-;; comint-dynamic-complete-filename Complete filename at point.
-;; comint-dynamic-list-filename-completions List completions in help buffer.
-;; comint-replace-by-expanded-filename Expand and complete filename at point;
-;; replace with expanded/completed name.
-;; comint-dynamic-simple-complete Complete stub given candidates.
-
-;; These are not installed in the comint-mode keymap. But they are
-;; available for people who want them. Shell-mode installs them:
-;; (define-key shell-mode-map "\t" 'comint-dynamic-complete)
-;; (define-key shell-mode-map "\M-?"
-;; 'comint-dynamic-list-filename-completions)))
-;;
-;; Commands like this are fine things to put in load hooks if you
-;; want them present in specific modes.
-
-(defvar comint-completion-autolist nil
- "*If non-nil, automatically list possibilities on partial completion.
-This mirrors the optional behavior of tcsh.")
-
-(defvar comint-completion-addsuffix t
- "*If non-nil, add a `/' to completed directories, ` ' to file names.
-If a cons pair, it should be of the form (DIRSUFFIX . FILESUFFIX) where
-DIRSUFFIX and FILESUFFIX are strings added on unambiguous or exact completion.
-This mirrors the optional behavior of tcsh.")
-
-(defvar comint-completion-recexact nil
- "*If non-nil, use shortest completion if characters cannot be added.
-This mirrors the optional behavior of tcsh.
-
-A non-nil value is useful if `comint-completion-autolist' is non-nil too.")
-
-(defvar comint-completion-fignore nil
- "*List of suffixes to be disregarded during file completion.
-This mirrors the optional behavior of bash and tcsh.
-
-Note that this applies to `comint-dynamic-complete-filename' only.")
-
-(defvar comint-file-name-prefix ""
- "Prefix prepended to absolute file names taken from process input.
-This is used by comint's and shell's completion functions, and by shell's
-directory tracking functions.")
-
-(defvar comint-file-name-chars
- (if (memq system-type '(ms-dos windows-nt))
- "~/A-Za-z0-9_^$!#%&{}@`'.()-"
- "~/A-Za-z0-9+@:_.$#%,={}-")
- "String of characters valid in a file name.
-
-This is a good thing to set in mode hooks.")
-
-(defvar comint-file-name-quote-list nil
- "List of characters to quote with `\\' when in a file name.
-
-This is a good thing to set in mode hooks.")
-
-
-(defun comint-directory (directory)
- ;; Return expanded DIRECTORY, with `comint-file-name-prefix' if absolute.
- (expand-file-name (if (file-name-absolute-p directory)
- (concat comint-file-name-prefix directory)
- directory)))
-
-
-(defun comint-word (word-chars)
- "Return the word of WORD-CHARS at point, or nil if non is found.
-Word constituents are considered to be those in WORD-CHARS, which is like the
-inside of a \"[...]\" (see `skip-chars-forward')."
- (save-excursion
- (let ((non-word-chars (concat "[^\\\\" word-chars "]")) (here (point)))
- (while (and (re-search-backward non-word-chars nil 'move)
- ;(memq (char-after (point)) shell-file-name-quote-list)
- (eq (preceding-char) ?\\))
- (backward-char 1))
- ;; Don't go forward over a word-char (this can happen if we're at bob).
- (if (or (not (bobp)) (looking-at non-word-chars))
- (forward-char 1))
- ;; Set match-data to match the entire string.
- (if (< (point) here)
- (progn (store-match-data (list (point) here))
- (match-string 0))))))
-
-(defun comint-substitute-in-file-name (filename)
- "Return FILENAME with environment variables substituted.
-Supports additional environment variable syntax of the command
-interpreter (e.g., the percent notation of cmd.exe on NT)."
- (let ((name (substitute-in-file-name filename)))
- (if (memq system-type '(ms-dos windows-nt))
- (let (env-var-name
- env-var-val)
- (save-match-data
- (while (string-match "%\\([^\\\\/]*\\)%" name)
- (setq env-var-name
- (substring name (match-beginning 1) (match-end 1)))
- (setq env-var-val (if (getenv env-var-name)
- (getenv env-var-name)
- ""))
- (setq name (replace-match env-var-val nil nil name))))))
- name))
-
-(defun comint-match-partial-filename ()
- "Return the filename at point, or nil if non is found.
-Environment variables are substituted. See `comint-word'."
- (let ((filename (comint-word comint-file-name-chars)))
- (and filename (comint-substitute-in-file-name
- (comint-unquote-filename filename)))))
-
-
-(defun comint-quote-filename (filename)
- "Return FILENAME with magic characters quoted.
-Magic characters are those in `comint-file-name-quote-list'."
- (if (null comint-file-name-quote-list)
- filename
- (let ((regexp
- (format "\\(^\\|[^\\]\\)\\([%s]\\)"
- (mapconcat 'char-to-string comint-file-name-quote-list ""))))
- (save-match-data
- (while (string-match regexp filename)
- (setq filename (replace-match "\\1\\\\\\2" nil nil filename)))
- filename))))
-
-(defun comint-unquote-filename (filename)
- "Return FILENAME with quoted characters unquoted."
- (if (null comint-file-name-quote-list)
- filename
- (save-match-data
- (let ((i 0))
- (while (string-match "\\\\\\(.\\)" filename i)
- (setq filename (replace-match "\\1" nil nil filename))
- (setq i (+ 1 (match-beginning 0)))))
- filename)))
-
-
-(defun comint-dynamic-complete ()
- "Dynamically perform completion at point.
-Calls the functions in `comint-dynamic-complete-functions' to perform
-completion until a function returns non-nil, at which point completion is
-assumed to have occurred."
- (interactive)
- (run-hook-with-args-until-success 'comint-dynamic-complete-functions))
-
-
-(defun comint-dynamic-complete-filename ()
- "Dynamically complete the filename at point.
-Completes if after a filename. See `comint-match-partial-filename' and
-`comint-dynamic-complete-as-filename'.
-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. A completions listing
-may be shown in a help buffer if completion is ambiguous.
-
-Completion is dependent on the value of `comint-completion-addsuffix',
-`comint-completion-recexact' and `comint-completion-fignore', and the timing of
-completions listing is dependent on the value of `comint-completion-autolist'.
-
-Returns t if successful."
- (interactive)
- (if (comint-match-partial-filename)
- (let ((directory-sep-char (if (memq system-type '(ms-dos windows-nt))
- ?\\
- ?/)))
- (prog2 (or (window-minibuffer-p (selected-window))
- (message "Completing file name..."))
- (comint-dynamic-complete-as-filename)))))
-
-(defun comint-dynamic-complete-as-filename ()
- "Dynamically complete at point as a filename.
-See `comint-dynamic-complete-filename'. Returns t if successful."
- (let* ((completion-ignore-case (memq system-type '(ms-dos windows-nt)))
- (completion-ignored-extensions comint-completion-fignore)
- ;; If we bind this, it breaks remote directory tracking in rlogin.el.
- ;; I think it was originally bound to solve file completion problems,
- ;; but subsequent changes may have made this unnecessary. sm.
- ;;(file-name-handler-alist nil)
- (minibuffer-p (window-minibuffer-p (selected-window)))
- (success t)
- (dirsuffix (cond ((not comint-completion-addsuffix) "")
- ((not (consp comint-completion-addsuffix)) "/")
- (t (car comint-completion-addsuffix))))
- (filesuffix (cond ((not comint-completion-addsuffix) "")
- ((not (consp comint-completion-addsuffix)) " ")
- (t (cdr comint-completion-addsuffix))))
- (filename (or (comint-match-partial-filename) ""))
- (pathdir (file-name-directory filename))
- (pathnondir (file-name-nondirectory filename))
- (directory (if pathdir (comint-directory pathdir) default-directory))
- (completion (file-name-completion pathnondir directory)))
- (cond ((null completion)
- (message "No completions of %s" filename)
- (setq success nil))
- ((eq completion t) ; Means already completed "file".
- (insert filesuffix)
- (or minibuffer-p (message "Sole completion")))
- ((string-equal completion "") ; Means completion on "directory/".
- (comint-dynamic-list-filename-completions))
- (t ; Completion string returned.
- (let ((file (concat (file-name-as-directory directory) completion)))
- (insert (comint-quote-filename
- (substring (directory-file-name completion)
- (length pathnondir))))
- (cond ((symbolp (file-name-completion completion directory))
- ;; We inserted a unique completion.
- (insert (if (file-directory-p file) dirsuffix filesuffix))
- (or minibuffer-p (message "Completed")))
- ((and comint-completion-recexact comint-completion-addsuffix
- (string-equal pathnondir completion)
- (file-exists-p file))
- ;; It's not unique, but user wants shortest match.
- (insert (if (file-directory-p file) dirsuffix filesuffix))
- (or minibuffer-p (message "Completed shortest")))
- ((or comint-completion-autolist
- (string-equal pathnondir completion))
- ;; It's not unique, list possible completions.
- (comint-dynamic-list-filename-completions))
- (t
- (or minibuffer-p (message "Partially completed")))))))
- success))
-
-
-(defun comint-replace-by-expanded-filename ()
- "Dynamically expand and complete the filename at point.
-Replace the filename with an expanded, canonicalised and completed replacement.
-\"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. For expansion
-see `expand-file-name' and `substitute-in-file-name'. For completion see
-`comint-dynamic-complete-filename'."
- (interactive)
- (replace-match (expand-file-name (comint-match-partial-filename)) t t)
- (comint-dynamic-complete-filename))
-
-
-(defun comint-dynamic-simple-complete (stub candidates)
- "Dynamically complete STUB from CANDIDATES list.
-This function inserts completion characters at point by completing STUB from
-the strings in CANDIDATES. A completions listing may be shown in a help buffer
-if completion is ambiguous.
-
-Returns nil if no completion was inserted.
-Returns `sole' if completed with the only completion match.
-Returns `shortest' if completed with the shortest of the completion matches.
-Returns `partial' if completed as far as possible with the completion matches.
-Returns `listed' if a completion listing was shown.
-
-See also `comint-dynamic-complete-filename'."
- (let* ((completion-ignore-case (memq system-type '(ms-dos windows-nt)))
- (suffix (cond ((not comint-completion-addsuffix) "")
- ((not (consp comint-completion-addsuffix)) " ")
- (t (cdr comint-completion-addsuffix))))
- (candidates (mapcar (function (lambda (x) (list x))) candidates))
- (completions (all-completions stub candidates)))
- (cond ((null completions)
- (message "No completions of %s" stub)
- nil)
- ((= 1 (length completions)) ; Gotcha!
- (let ((completion (car completions)))
- (if (string-equal completion stub)
- (message "Sole completion")
- (insert (substring completion (length stub)))
- (message "Completed"))
- (insert suffix)
- 'sole))
- (t ; There's no unique completion.
- (let ((completion (try-completion stub candidates)))
- ;; Insert the longest substring.
- (insert (substring completion (length stub)))
- (cond ((and comint-completion-recexact comint-completion-addsuffix
- (string-equal stub completion)
- (member completion completions))
- ;; It's not unique, but user wants shortest match.
- (insert suffix)
- (message "Completed shortest")
- 'shortest)
- ((or comint-completion-autolist
- (string-equal stub completion))
- ;; It's not unique, list possible completions.
- (comint-dynamic-list-completions completions)
- 'listed)
- (t
- (message "Partially completed")
- 'partial)))))))
-
-
-(defun comint-dynamic-list-filename-completions ()
- "List in help buffer possible completions of the filename at point."
- (interactive)
- (let* ((completion-ignore-case (memq system-type '(ms-dos windows-nt)))
- ;; If we bind this, it breaks remote directory tracking in rlogin.el.
- ;; I think it was originally bound to solve file completion problems,
- ;; but subsequent changes may have made this unnecessary. sm.
- ;;(file-name-handler-alist nil)
- (filename (or (comint-match-partial-filename) ""))
- (pathdir (file-name-directory filename))
- (pathnondir (file-name-nondirectory filename))
- (directory (if pathdir (comint-directory pathdir) default-directory))
- (completions (file-name-all-completions pathnondir directory)))
- (if (not completions)
- (message "No completions of %s" filename)
- (comint-dynamic-list-completions
- (mapcar 'comint-quote-filename completions)))))
-
-
-(defun comint-dynamic-list-completions (completions)
- "List in help buffer sorted COMPLETIONS.
-Typing SPC flushes the help buffer."
- (let ((conf (current-window-configuration)))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list (sort completions 'string-lessp)))
- (message "Hit space to flush")
- (let (key first)
- (if (save-excursion
- (set-buffer (get-buffer "*Completions*"))
- (setq key (read-key-sequence nil)
- first (aref key 0))
- (and (consp first) (consp (event-start first))
- (eq (window-buffer (posn-window (event-start first)))
- (get-buffer "*Completions*"))
- (eq (key-binding key) 'mouse-choose-completion)))
- ;; If the user does mouse-choose-completion with the mouse,
- ;; execute the command, then delete the completion window.
- (progn
- (mouse-choose-completion first)
- (set-window-configuration conf))
- (if (eq first ?\ )
- (set-window-configuration conf)
- (setq unread-command-events (listify-key-sequence key)))))))
-
-;; Converting process modes to use comint mode
-;; ===========================================================================
-;; The code in the Emacs 19 distribution has all been modified to use comint
-;; where needed. However, there are `third-party' packages out there that
-;; still use the old shell mode. Here's a guide to conversion.
-;;
-;; Renaming variables
-;; Most of the work is renaming variables and functions. These are the common
-;; ones:
-;; Local variables:
-;; last-input-start comint-last-input-start
-;; last-input-end comint-last-input-end
-;; 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
-;;
-;; SHELL-SET-DIRECTORY is gone, its functionality taken over by
-;; SHELL-DIRECTORY-TRACKER, the shell mode's comint-input-filter-functions.
-;; Comint mode does not provide functionality equivalent to
-;; shell-set-directory-error-hook; it is gone.
-;;
-;; comint-last-input-start is provided for modes which want to munge
-;; the buffer after input is sent, perhaps because the inferior
-;; insists on echoing the input. The LAST-INPUT-START variable in
-;; the old shell package was used to implement a history mechanism,
-;; but you should think twice before using comint-last-input-start
-;; for this; the input history ring often does the job better.
-;;
-;; 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, input-filter, input-filter-functions,
-;; 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. The following example, from shell.el,
-;; is typical:
-;;
-;; (defvar shell-mode-map '())
-;; (cond ((not shell-mode-map)
-;; (setq shell-mode-map (copy-keymap comint-mode-map))
-;; (define-key shell-mode-map "\C-c\C-f" 'shell-forward-command)
-;; (define-key shell-mode-map "\C-c\C-b" 'shell-backward-command)
-;; (define-key shell-mode-map "\t" 'comint-dynamic-complete)
-;; (define-key shell-mode-map "\M-?"
-;; 'comint-dynamic-list-filename-completions)))
-;;
-;; (defun shell-mode ()
-;; (interactive)
-;; (comint-mode)
-;; (setq comint-prompt-regexp shell-prompt-pattern)
-;; (setq major-mode 'shell-mode)
-;; (setq mode-name "Shell")
-;; (use-local-map shell-mode-map)
-;; (make-local-variable 'shell-directory-stack)
-;; (setq shell-directory-stack nil)
-;; (add-hook 'comint-input-filter-functions 'shell-directory-tracker)
-;; (run-hooks 'shell-mode-hook))
-;;
-;;
-;; 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...
-;;
-;; Completion for comint-mode users
-;;
-;; For modes that use comint-mode, comint-dynamic-complete-functions is the
-;; hook to add completion functions to. Functions on this list should return
-;; non-nil if completion occurs (i.e., further completion should not occur).
-;; You could use comint-dynamic-simple-complete to do the bulk of the
-;; completion job.
-
-(provide 'comint)
-
-;; comint.el ends here
diff --git a/lisp/compare-w.el b/lisp/compare-w.el
deleted file mode 100644
index ac569963268..00000000000
--- a/lisp/compare-w.el
+++ /dev/null
@@ -1,173 +0,0 @@
-;;; compare-w.el --- compare text between windows for Emacs.
-
-;; Copyright (C) 1986, 1989, 1993 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides one entry point, compare-windows. It compares
-;; text starting from point in two adjacent windows, advancing point
-;; until it finds a difference. Option variables permit you to ignore
-;; whitespace differences, or case differences, or both.
-
-;;; Code:
-
-(defvar compare-windows-whitespace "[ \t\n]+"
- "*Regexp that defines whitespace sequences for \\[compare-windows].
-Changes in whitespace are optionally ignored.
-
-The value of `compare-windows-whitespace' may instead be a function; this
-function is called in each buffer, with point at the current scanning point.
-The function's job is to categorize any whitespace around (including before)
-point; it should also advance past any whitespace.
-
-The function is passed one argument, the point where `compare-windows'
-was originally called; it should not consider any text before that point.
-If the function returns the same value for both buffers, then the
-whitespace is considered to match, and is skipped.")
-
-(defvar compare-ignore-case nil
- "*Non-nil means \\[compare-windows] ignores case differences.")
-
-;;;###autoload
-(defun compare-windows (ignore-whitespace)
- "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.
-
-This command pushes the mark in each window
-at the prior location of point in that window.
-If both windows display the same buffer,
-the mark is pushed twice in that buffer:
-first in the other window, then in the selected window.
-
-A prefix arg means ignore changes in whitespace.
-The variable `compare-windows-whitespace' controls how whitespace is skipped.
-If `compare-ignore-case' is non-nil, changes in case are also ignored."
- (interactive "P")
- (let* (p1 p2 maxp1 maxp2 b1 b2 w2
- success size
- (opoint1 (point))
- opoint2
- (skip-whitespace (if ignore-whitespace
- compare-windows-whitespace)))
- (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 opoint2 p2)
- (setq maxp1 (point-max))
- (save-excursion
- (set-buffer b2)
- (push-mark p2 t)
- (setq maxp2 (point-max)))
- (push-mark)
-
- (setq success t)
- (while success
- (setq success nil)
- ;; if interrupted, show how far we've gotten
- (goto-char p1)
- (set-window-point w2 p2)
-
- ;; If both buffers have whitespace next to point,
- ;; optionally skip over it.
-
- (and skip-whitespace
- (save-excursion
- (let (p1a p2a w1 w2 result1 result2)
- (setq result1
- (if (stringp skip-whitespace)
- (compare-windows-skip-whitespace opoint1)
- (funcall skip-whitespace opoint1)))
- (setq p1a (point))
- (set-buffer b2)
- (goto-char p2)
- (setq result2
- (if (stringp skip-whitespace)
- (compare-windows-skip-whitespace opoint2)
- (funcall skip-whitespace opoint2)))
- (setq p2a (point))
- (if (or (stringp skip-whitespace)
- (and result1 result2 (eq result1 result2)))
- (setq p1 p1a
- p2 p2a)))))
-
- ;; Try advancing comparing 1000 chars at a time.
- ;; When that fails, go 500 chars at a time, and so on.
- (let ((size 1000)
- success-1
- (case-fold-search compare-ignore-case))
- (while (> size 0)
- (setq success-1 t)
- ;; Try comparing SIZE chars at a time, repeatedly, till that fails.
- (while success-1
- (setq size (min size (- maxp1 p1) (- maxp2 p2)))
- (setq success-1
- (and (> size 0)
- (= 0 (compare-buffer-substrings b2 p2 (+ size p2)
- b1 p1 (+ size p1)))))
- (if success-1
- (setq p1 (+ p1 size) p2 (+ p2 size)
- success t)))
- ;; If SIZE chars don't match, try fewer.
- (setq size (/ size 2)))))
-
- (goto-char p1)
- (set-window-point w2 p2)
- (if (= (point) opoint1)
- (ding))))
-
-;; Move forward over whatever might be called whitespace.
-;; compare-windows-whitespace is a regexp that matches whitespace.
-;; Match it at various starting points before the original point
-;; and find the latest point at which a match ends.
-;; Don't try starting points before START, though.
-;; Value is non-nil if whitespace is found.
-
-;; If there is whitespace before point, but none after,
-;; then return t, but don't advance point.
-(defun compare-windows-skip-whitespace (start)
- (let ((end (point))
- (beg (point))
- (opoint (point)))
- (while (or (and (looking-at compare-windows-whitespace)
- (<= end (match-end 0))
- ;; This match goes past END, so advance END.
- (progn (setq end (match-end 0))
- (> (point) start)))
- (and (/= (point) start)
- ;; Consider at least the char before point,
- ;; unless it is also before START.
- (= (point) opoint)))
- ;; keep going back until whitespace
- ;; doesn't extend to or past end
- (forward-char -1))
- (setq beg (point))
- (goto-char end)
- (or (/= beg opoint)
- (/= end opoint))))
-
-(provide 'compare-w)
-
-;;; compare-w.el ends here
diff --git a/lisp/complete.el b/lisp/complete.el
deleted file mode 100644
index 50855ebd804..00000000000
--- a/lisp/complete.el
+++ /dev/null
@@ -1,898 +0,0 @@
-;;; complete.el --- partial completion mechanism plus other goodies
-
-;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
-
-;; Author: Dave Gillespie <daveg@synaptics.com>
-;; Keywords: abbrev
-;; Version: 2.02
-;; Special thanks to Hallvard Furuseth for his many ideas and contributions.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Extended completion for the Emacs minibuffer.
-;;
-;; The basic idea is that the command name or other completable text is
-;; divided into words and each word is completed separately, so that
-;; "M-x p-b" expands to "M-x print-buffer". If the entry is ambiguous
-;; each word is completed as much as possible and then the cursor is
-;; left at the first position where typing another letter will resolve
-;; the ambiguity.
-;;
-;; Word separators for this purpose are hyphen, space, and period.
-;; These would most likely occur in command names, Info menu items,
-;; and file names, respectively. But all word separators are treated
-;; alike at all times.
-;;
-;; This completion package replaces the old-style completer's key
-;; bindings for TAB, SPC, RET, and `?'. The old completer is still
-;; available on the Meta versions of those keys. If you set
-;; PC-meta-flag to nil, the old completion keys will be left alone
-;; and the partial completer will use the Meta versions of the keys.
-
-
-;; Usage: Load this file. Now, during completable minibuffer entry,
-;;
-;; TAB means to do a partial completion;
-;; SPC means to do a partial complete-word;
-;; RET means to do a partial complete-and-exit;
-;; ? means to do a partial completion-help.
-;;
-;; If you set PC-meta-flag to nil, then TAB, SPC, RET, and ? perform
-;; original Emacs completions, and M-TAB etc. do partial completion.
-;; To do this, put the command,
-;;
-;; (setq PC-meta-flag nil)
-;;
-;; in your .emacs file. To load partial completion automatically, put
-;;
-;; (load "complete")
-;;
-;; in your .emacs file, too. Things will be faster if you byte-compile
-;; this file when you install it.
-;;
-;; As an extra feature, in cases where RET would not normally
-;; complete (such as `C-x b'), the M-RET key will always do a partial
-;; complete-and-exit. Thus `C-x b f.c RET' will select or create a
-;; buffer called "f.c", but `C-x b f.c M-RET' will select the existing
-;; buffer whose name matches that pattern (perhaps "filing.c").
-;; (PC-meta-flag does not affect this behavior; M-RET used to be
-;; undefined in this situation.)
-;;
-;; The regular M-TAB (lisp-complete-symbol) command also supports
-;; partial completion in this package.
-
-;; This package also contains a wildcard feature for C-x C-f (find-file).
-;; For example, `C-x C-f *.c RET' loads all .c files at once, exactly
-;; as if you had typed C-x C-f separately for each file. Completion
-;; is supported in connection with wildcards. Currently only the `*'
-;; wildcard character works.
-
-;; File name completion does not do partial completion of directories
-;; on the path, e.g., "/u/b/f" will not complete to "/usr/bin/foo",
-;; but you can put *'s in the path to accomplish this: "/u*/b*/f".
-;; Stars are required for performance reasons.
-
-;; In addition, this package includes a feature for accessing include
-;; files. For example, `C-x C-f <sys/time.h> RET' reads the file
-;; /usr/include/sys/time.h. The variable PC-include-file-path is a
-;; list of directories in which to search for include files. Completion
-;; is supported in include file names.
-
-
-;;; Code:
-
-(defvar PC-meta-flag t
- "*If nil, TAB does normal Emacs completion and M-TAB does Partial Completion.
-If t, TAB does Partial Completion and M-TAB does normal completion.")
-
-
-(defvar PC-word-delimiters "-_. "
- "*A string of characters which are to be treated as word delimiters
-by the Partial Completion system.
-
-Some arcane rules: If `]' is in this string it must come first.
-If `^' is in this string it must NOT come first. If `-' is in this
-string, it must come first or right after `]'. In other words, if
-S is this string, then `[S]' must be a legal Emacs regular expression
-\(not containing character ranges like `a-z').")
-
-
-(defvar PC-first-char 'x
- "*If t, first character of a string to be completed is always taken literally.
-If nil, word delimiters are handled even if they appear as first character.
-This controls whether \".e\" matches \".e*\" (t) or \"*.e*\" (nil).
-If neither nil nor t, first char is literal only for filename completion.")
-
-
-(defvar PC-include-file-path '("/usr/include")
- "*List of directories in which to look for include files.
-If this is nil, uses the colon-separated path in $INCPATH instead.")
-
-
-(defvar PC-disable-wildcards nil
- "Set this to non-nil to disable wildcard support in \\[find-file].")
-
-(defvar PC-disable-includes nil
- "Set this to non-nil to disable include-file support in \\[find-file].")
-
-
-(defvar PC-default-bindings t
- "Set this to nil to suppress the default partial completion key bindings.")
-
-(if PC-default-bindings (progn
-(define-key minibuffer-local-completion-map "\t" 'PC-complete)
-(define-key minibuffer-local-completion-map " " 'PC-complete-word)
-(define-key minibuffer-local-completion-map "?" 'PC-completion-help)
-
-(define-key minibuffer-local-completion-map "\e\t" 'PC-complete)
-(define-key minibuffer-local-completion-map "\e " 'PC-complete-word)
-(define-key minibuffer-local-completion-map "\e\r" 'PC-force-complete-and-exit)
-(define-key minibuffer-local-completion-map "\e\n" 'PC-force-complete-and-exit)
-(define-key minibuffer-local-completion-map "\e?" 'PC-completion-help)
-
-(define-key minibuffer-local-must-match-map "\t" 'PC-complete)
-(define-key minibuffer-local-must-match-map " " 'PC-complete-word)
-(define-key minibuffer-local-must-match-map "\r" 'PC-complete-and-exit)
-(define-key minibuffer-local-must-match-map "\n" 'PC-complete-and-exit)
-(define-key minibuffer-local-must-match-map "?" 'PC-completion-help)
-
-(define-key minibuffer-local-must-match-map "\e\t" 'PC-complete)
-(define-key minibuffer-local-must-match-map "\e " 'PC-complete-word)
-(define-key minibuffer-local-must-match-map "\e\r" 'PC-complete-and-exit)
-(define-key minibuffer-local-must-match-map "\e\n" 'PC-complete-and-exit)
-(define-key minibuffer-local-must-match-map "\e?" 'PC-completion-help)
-
-(define-key global-map "\e\t" 'PC-lisp-complete-symbol)
-))
-
-
-(defun PC-complete ()
- "Like minibuffer-complete, but allows \"b--di\"-style abbreviations.
-For example, \"M-x b--di\" would match `byte-recompile-directory', or any
-name which consists of three or more words, the first beginning with \"b\"
-and the third beginning with \"di\".
-
-The pattern \"b--d\" is ambiguous for `byte-recompile-directory' and
-`beginning-of-defun', so this would produce a list of completions
-just like when normal Emacs completions are ambiguous.
-
-Word-delimiters for the purposes of Partial Completion are \"-\", \"_\",
-\".\", and SPC."
- (interactive)
- (if (PC-was-meta-key)
- (minibuffer-complete)
- ;; If the previous command was not this one,
- ;; never scroll, always retry completion.
- (or (eq last-command this-command)
- (setq minibuffer-scroll-window nil))
- (let ((window minibuffer-scroll-window))
- ;; If there's a fresh completion window with a live buffer,
- ;; and this command is repeated, scroll that window.
- (if (and window (window-buffer window)
- (buffer-name (window-buffer window)))
- (save-excursion
- (set-buffer (window-buffer window))
- (if (pos-visible-in-window-p (point-max) window)
- (set-window-start window (point-min) nil)
- (scroll-other-window)))
- (PC-do-completion nil)))))
-
-
-(defun PC-complete-word ()
- "Like `minibuffer-complete-word', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details.
-This can be bound to other keys, like `-' and `.', if you wish."
- (interactive)
- (if (eq (PC-was-meta-key) PC-meta-flag)
- (if (eq last-command-char ? )
- (minibuffer-complete-word)
- (self-insert-command 1))
- (self-insert-command 1)
- (if (eobp)
- (PC-do-completion 'word))))
-
-
-(defun PC-complete-space ()
- "Like `minibuffer-complete-word', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details.
-This is suitable for binding to other keys which should act just like SPC."
- (interactive)
- (if (eq (PC-was-meta-key) PC-meta-flag)
- (minibuffer-complete-word)
- (insert " ")
- (if (eobp)
- (PC-do-completion 'word))))
-
-
-(defun PC-complete-and-exit ()
- "Like `minibuffer-complete-and-exit', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details."
- (interactive)
- (if (eq (PC-was-meta-key) PC-meta-flag)
- (minibuffer-complete-and-exit)
- (PC-do-complete-and-exit)))
-
-(defun PC-force-complete-and-exit ()
- "Like `minibuffer-complete-and-exit', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details."
- (interactive)
- (let ((minibuffer-completion-confirm nil))
- (PC-do-complete-and-exit)))
-
-(defun PC-do-complete-and-exit ()
- (if (= (buffer-size) 0) ; Duplicate the "bug" that Info-menu relies on...
- (exit-minibuffer)
- (let ((flag (PC-do-completion 'exit)))
- (and flag
- (if (or (eq flag 'complete)
- (not minibuffer-completion-confirm))
- (exit-minibuffer)
- (PC-temp-minibuffer-message " [Confirm]"))))))
-
-
-(defun PC-completion-help ()
- "Like `minibuffer-completion-help', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details."
- (interactive)
- (if (eq (PC-was-meta-key) PC-meta-flag)
- (minibuffer-completion-help)
- (PC-do-completion 'help)))
-
-(defun PC-was-meta-key ()
- (or (/= (length (this-command-keys)) 1)
- (let ((key (aref (this-command-keys) 0)))
- (if (integerp key)
- (>= key 128)
- (not (null (memq 'meta (event-modifiers key))))))))
-
-
-(defvar PC-ignored-extensions 'empty-cache)
-(defvar PC-delims 'empty-cache)
-(defvar PC-ignored-regexp nil)
-(defvar PC-word-failed-flag nil)
-(defvar PC-delim-regex nil)
-(defvar PC-ndelims-regex nil)
-(defvar PC-delims-list nil)
-
-(defvar PC-completion-as-file-name-predicate
- (function
- (lambda ()
- (memq minibuffer-completion-table
- '(read-file-name-internal read-directory-name-internal))))
- "A function testing whether a minibuffer completion now will work filename-style.
-The function takes no arguments, and typically looks at the value
-of `minibuffer-completion-table' and the minibuffer contents.")
-
-(defun PC-do-completion (&optional mode beg end)
- (or beg (setq beg (point-min)))
- (or end (setq end (point-max)))
- (let* ((table minibuffer-completion-table)
- (pred minibuffer-completion-predicate)
- (filename (funcall PC-completion-as-file-name-predicate))
- (dirname nil)
- dirlength
- (str (buffer-substring beg end))
- (incname (and filename (string-match "<\\([^\"<>]*\\)>?$" str)))
- (ambig nil)
- basestr
- regex
- p offset
- (poss nil)
- helpposs
- (case-fold-search completion-ignore-case))
-
- ;; Check if buffer contents can already be considered complete
- (if (and (eq mode 'exit)
- (PC-is-complete-p str table pred))
- 'complete
-
- ;; Record how many characters at the beginning are not included
- ;; in completion.
- (setq dirlength
- (if filename
- (length (file-name-directory str))
- 0))
-
- ;; Do substitutions in directory names
- (and filename
- (not (equal str (setq p (substitute-in-file-name str))))
- (progn
- (delete-region beg end)
- (insert p)
- (setq str p end (+ beg (length str)))))
-
- ;; Prepare various delimiter strings
- (or (equal PC-word-delimiters PC-delims)
- (setq PC-delims PC-word-delimiters
- PC-delim-regex (concat "[" PC-delims "]")
- PC-ndelims-regex (concat "[^" PC-delims "]*")
- PC-delims-list (append PC-delims nil)))
-
- ;; Look for wildcard expansions in directory name
- (and filename
- (string-match "\\*.*/" str)
- (let ((pat str)
- files)
- (setq p (1+ (string-match "/[^/]*\\'" pat)))
- (while (setq p (string-match PC-delim-regex pat p))
- (setq pat (concat (substring pat 0 p)
- "*"
- (substring pat p))
- p (+ p 2)))
- (setq files (PC-expand-many-files (concat pat "*")))
- (if files
- (let ((dir (file-name-directory (car files)))
- (p files))
- (while (and (setq p (cdr p))
- (equal dir (file-name-directory (car p)))))
- (if p
- (setq filename nil table nil pred nil
- ambig t)
- (delete-region beg end)
- (setq str (concat dir (file-name-nondirectory str)))
- (insert str)
- (setq end (+ beg (length str)))))
- (setq filename nil table nil pred nil))))
-
- ;; Strip directory name if appropriate
- (if filename
- (if incname
- (setq basestr (substring str incname)
- dirname (substring str 0 incname))
- (setq basestr (file-name-nondirectory str)
- dirname (file-name-directory str)))
- (setq basestr str))
-
- ;; Convert search pattern to a standard regular expression
- (setq regex (regexp-quote basestr)
- offset (if (and (> (length regex) 0)
- (not (eq (aref basestr 0) ?\*))
- (or (eq PC-first-char t)
- (and PC-first-char filename))) 1 0)
- p offset)
- (while (setq p (string-match PC-delim-regex regex p))
- (if (eq (aref regex p) ? )
- (setq regex (concat (substring regex 0 p)
- PC-ndelims-regex
- PC-delim-regex
- (substring regex (1+ p)))
- p (+ p (length PC-ndelims-regex) (length PC-delim-regex)))
- (let ((bump (if (memq (aref regex p)
- '(?$ ?^ ?\. ?* ?+ ?? ?[ ?] ?\\))
- -1 0)))
- (setq regex (concat (substring regex 0 (+ p bump))
- PC-ndelims-regex
- (substring regex (+ p bump)))
- p (+ p (length PC-ndelims-regex) 1)))))
- (setq p 0)
- (if filename
- (while (setq p (string-match "\\\\\\*" regex p))
- (setq regex (concat (substring regex 0 p)
- "[^/]*"
- (substring regex (+ p 2))))))
- ;;(setq the-regex regex)
- (setq regex (concat "\\`" regex))
-
- ;; Find an initial list of possible completions
- (if (not (setq p (string-match (concat PC-delim-regex
- (if filename "\\|\\*" ""))
- str
- (+ (length dirname) offset))))
-
- ;; Minibuffer contains no hyphens -- simple case!
- (setq poss (all-completions str
- table
- pred))
-
- ;; Use all-completions to do an initial cull. This is a big win,
- ;; since all-completions is written in C!
- (let ((compl (all-completions (substring str 0 p)
- table
- pred)))
- (setq p compl)
- (while p
- (and (string-match regex (car p))
- (progn
- (set-text-properties 0 (length (car p)) '() (car p))
- (setq poss (cons (car p) poss))))
- (setq p (cdr p)))))
-
- ;; Now we have a list of possible completions
- (cond
-
- ;; No valid completions found
- ((null poss)
- (if (and (eq mode 'word)
- (not PC-word-failed-flag))
- (let ((PC-word-failed-flag t))
- (delete-backward-char 1)
- (PC-do-completion 'word))
- (beep)
- (PC-temp-minibuffer-message (if ambig
- " [Ambiguous dir name]"
- (if (eq mode 'help)
- " [No completions]"
- " [No match]")))
- nil))
-
- ;; More than one valid completion found
- ((or (cdr (setq helpposs poss))
- (memq mode '(help word)))
-
- ;; Handle completion-ignored-extensions
- (and filename
- (not (eq mode 'help))
- (let ((p2 poss))
-
- ;; Build a regular expression representing the extensions list
- (or (equal completion-ignored-extensions PC-ignored-extensions)
- (setq PC-ignored-regexp
- (concat "\\("
- (mapconcat
- 'regexp-quote
- (setq PC-ignored-extensions
- completion-ignored-extensions)
- "\\|")
- "\\)\\'")))
-
- ;; Check if there are any without an ignored extension
- (setq p nil)
- (while p2
- (or (string-match PC-ignored-regexp (car p2))
- (setq p (cons (car p2) p)))
- (setq p2 (cdr p2)))
-
- ;; If there are "good" names, use them
- (and p (setq poss p))))
-
- ;; Is the actual string one of the possible completions?
- (setq p (and (not (eq mode 'help)) poss))
- (while (and p
- (not (string-equal (car p) basestr)))
- (setq p (cdr p)))
- (and p (null mode)
- (PC-temp-minibuffer-message " [Complete, but not unique]"))
- (if (and p
- (not (and (null mode)
- (eq this-command last-command))))
- t
-
- ;; If ambiguous, try for a partial completion
- (let ((improved nil)
- prefix
- (pt nil)
- (skip "\\`"))
-
- ;; Check if next few letters are the same in all cases
- (if (and (not (eq mode 'help))
- (setq prefix (try-completion "" (mapcar 'list poss))))
- (let ((first t) i)
- (if (eq mode 'word)
- (setq prefix (PC-chop-word prefix basestr)))
- (goto-char (+ beg (length dirname)))
- (while (and (progn
- (setq i 0)
- (while (< i (length prefix))
- (if (and (< (point) end)
- (eq (aref prefix i)
- (following-char)))
- (forward-char 1)
- (if (and (< (point) end)
- (or (and (looking-at " ")
- (memq (aref prefix i)
- PC-delims-list))
- (eq (downcase (aref prefix i))
- (downcase
- (following-char)))))
- (progn
- (delete-char 1)
- (setq end (1- end)))
- (and filename (looking-at "\\*")
- (progn
- (delete-char 1)
- (setq end (1- end))))
- (setq improved t))
- (insert (substring prefix i (1+ i)))
- (setq end (1+ end)))
- (setq i (1+ i)))
- (or pt (equal (point) beg)
- (setq pt (point)))
- (looking-at PC-delim-regex))
- (setq skip (concat skip
- (regexp-quote prefix)
- PC-ndelims-regex)
- prefix (try-completion
- ""
- (mapcar
- (function
- (lambda (x)
- (list
- (and (string-match skip x)
- (substring
- x
- (match-end 0))))))
- poss)))
- (or (> i 0) (> (length prefix) 0))
- (or (not (eq mode 'word))
- (and first (> (length prefix) 0)
- (setq first nil
- prefix (substring prefix 0 1))))))
- (goto-char (if (eq mode 'word) end
- (or pt beg)))))
-
- (if (and (eq mode 'word)
- (not PC-word-failed-flag))
-
- (if improved
-
- ;; We changed it... would it be complete without the space?
- (if (PC-is-complete-p (buffer-substring 1 (1- end))
- table pred)
- (delete-region (1- end) end)))
-
- (if improved
-
- ;; We changed it... enough to be complete?
- (and (eq mode 'exit)
- (PC-is-complete-p (buffer-string) table pred))
-
- ;; If totally ambiguous, display a list of completions
- (if (or completion-auto-help
- (eq mode 'help))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list (sort helpposs 'string-lessp))
- (save-excursion
- (set-buffer standard-output)
- ;; Record which part of the buffer we are completing
- ;; so that choosing a completion from the list
- ;; knows how much old text to replace.
- (setq completion-base-size dirlength)))
- (PC-temp-minibuffer-message " [Next char not unique]"))
- nil)))))
-
- ;; Only one possible completion
- (t
- (if (equal basestr (car poss))
- (if (null mode)
- (PC-temp-minibuffer-message " [Sole completion]"))
- (delete-region beg end)
- (insert (format "%s"
- (if filename
- (substitute-in-file-name (concat dirname (car poss)))
- (car poss)))))
- t)))))
-
-
-(defun PC-is-complete-p (str table pred)
- (let ((res (if (listp table)
- (assoc str table)
- (if (vectorp table)
- (or (equal str "nil") ; heh, heh, heh
- (intern-soft str table))
- (funcall table str pred 'lambda)))))
- (and res
- (or (not pred)
- (and (not (listp table)) (not (vectorp table)))
- (funcall pred res))
- res)))
-
-(defun PC-chop-word (new old)
- (let ((i -1)
- (j -1))
- (while (and (setq i (string-match PC-delim-regex old (1+ i)))
- (setq j (string-match PC-delim-regex new (1+ j)))))
- (if (and j
- (or (not PC-word-failed-flag)
- (setq j (string-match PC-delim-regex new (1+ j)))))
- (substring new 0 (1+ j))
- new)))
-
-(defvar PC-not-minibuffer nil)
-
-(defun PC-temp-minibuffer-message (m)
- "A Lisp version of `temp_minibuffer_message' from minibuf.c."
- (if PC-not-minibuffer
- (progn
- (message m)
- (sit-for 2)
- (message ""))
- (if (fboundp 'temp-minibuffer-message)
- (temp-minibuffer-message m)
- (let ((savemax (point-max)))
- (save-excursion
- (goto-char (point-max))
- (insert m))
- (let ((inhibit-quit t))
- (sit-for 2)
- (delete-region savemax (point-max))
- (if quit-flag
- (setq quit-flag nil
- unread-command-char 7)))))))
-
-
-(defun PC-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."
- (interactive)
- (let* ((end (point))
- (buffer-syntax (syntax-table))
- (beg (unwind-protect
- (save-excursion
- (if lisp-mode-syntax-table
- (set-syntax-table lisp-mode-syntax-table))
- (backward-sexp 1)
- (while (= (char-syntax (following-char)) ?\')
- (forward-char 1))
- (point))
- (set-syntax-table buffer-syntax)))
- (minibuffer-completion-table obarray)
- (minibuffer-completion-predicate
- (if (eq (char-after (1- beg)) ?\()
- 'fboundp
- (function (lambda (sym)
- (or (boundp sym) (fboundp sym)
- (symbol-plist sym))))))
- (PC-not-minibuffer t))
- (PC-do-completion nil beg end)))
-
-
-;;; Wildcards in `C-x C-f' command. This is independent from the main
-;;; completion code, except for `PC-expand-many-files' which is called
-;;; when "*"'s are found in the path during filename completion. (The
-;;; above completion code always understands "*"'s, except in file paths,
-;;; without relying on the following code.)
-
-(defvar PC-many-files-list nil)
-
-(defun PC-try-load-many-files ()
- (if (string-match "\\*" buffer-file-name)
- (let* ((pat buffer-file-name)
- (files (PC-expand-many-files pat))
- (first (car files))
- (next files))
- (kill-buffer (current-buffer))
- (or files
- (error "No matching files"))
- (save-window-excursion
- (while (setq next (cdr next))
- (let ((buf (find-file-noselect (car next))))
- (switch-to-buffer buf))))
- ;; This modifies the "buf" variable inside find-file-noselect.
- (setq buf (get-file-buffer first))
- (if buf
- nil ; should do verify-visited-file-modtime stuff.
- (setq filename first)
- (setq buf (create-file-buffer filename))
- (set-buffer buf)
- (erase-buffer)
- (insert-file-contents filename t))
- (if (cdr files)
- (setq PC-many-files-list (mapconcat
- (if (string-match "\\*.*/" pat)
- 'identity
- 'file-name-nondirectory)
- (cdr files) ", ")
- find-file-hooks (cons 'PC-after-load-many-files
- find-file-hooks)))
- ;; This modifies the "error" variable inside find-file-noselect.
- (setq error nil)
- t)
- nil))
-
-(defun PC-after-load-many-files ()
- (setq find-file-hooks (delq 'PC-after-load-many-files find-file-hooks))
- (message "Also loaded %s." PC-many-files-list))
-
-(defun PC-expand-many-files (name)
- (save-excursion
- (set-buffer (generate-new-buffer " *Glob Output*"))
- (erase-buffer)
- (shell-command (concat "echo " name) t)
- (goto-char (point-min))
- (if (looking-at ".*No match")
- nil
- (insert "(\"")
- (while (search-forward " " nil t)
- (delete-backward-char 1)
- (insert "\" \""))
- (goto-char (point-max))
- (delete-backward-char 1)
- (insert "\")")
- (goto-char (point-min))
- (let ((files (read (current-buffer))))
- (kill-buffer (current-buffer))
- files))))
-
-(or PC-disable-wildcards
- (memq 'PC-try-load-many-files find-file-not-found-hooks)
- (setq find-file-not-found-hooks (cons 'PC-try-load-many-files
- find-file-not-found-hooks)))
-
-
-
-;;; Facilities for loading C header files. This is independent from the
-;;; main completion code. See also the variable `PC-include-file-path'
-;;; at top of this file.
-
-(defun PC-look-for-include-file ()
- (if (string-match "[\"<]\\([^\"<>]*\\)[\">]?$" (buffer-file-name))
- (let ((name (substring (buffer-file-name)
- (match-beginning 1) (match-end 1)))
- (punc (aref (buffer-file-name) (match-beginning 0)))
- (path nil)
- new-buf)
- (kill-buffer (current-buffer))
- (if (equal name "")
- (save-excursion
- (set-buffer (car (buffer-list)))
- (save-excursion
- (beginning-of-line)
- (if (looking-at
- "[ \t]*#[ \t]*include[ \t]+[<\"]\\(.+\\)[>\"][ \t]*[\n/]")
- (setq name (buffer-substring (match-beginning 1)
- (match-end 1))
- punc (char-after (1- (match-beginning 1))))
- ;; Suggested by Frank Siebenlist:
- (if (or (looking-at
- "[ \t]*([ \t]*load[ \t]+\"\\([^\"]+\\)\"")
- (looking-at
- "[ \t]*([ \t]*load-library[ \t]+\"\\([^\"]+\\)\"")
- (looking-at
- "[ \t]*([ \t]*require[ \t]+'\\([^\t )]+\\)[\t )]"))
- (progn
- (setq name (buffer-substring (match-beginning 1)
- (match-end 1))
- punc ?\<
- path load-path)
- (if (string-match "\\.elc$" name)
- (setq name (substring name 0 -1))
- (or (string-match "\\.el$" name)
- (setq name (concat name ".el")))))
- (error "Not on an #include line"))))))
- (or (string-match "\\.[a-zA-Z0-9]+$" name)
- (setq name (concat name ".h")))
- (if (eq punc ?\<)
- (let ((path (or path (PC-include-file-path))))
- (while (and path
- (not (file-exists-p
- (concat (file-name-as-directory (car path))
- name))))
- (setq path (cdr path)))
- (if path
- (setq name (concat (file-name-as-directory (car path)) name))
- (error "No such include file: <%s>" name)))
- (let ((dir (save-excursion
- (set-buffer (car (buffer-list)))
- default-directory)))
- (if (file-exists-p (concat dir name))
- (setq name (concat dir name))
- (error "No such include file: \"%s\"" name))))
- (setq new-buf (get-file-buffer name))
- (if new-buf
- ;; no need to verify last-modified time for this!
- (set-buffer new-buf)
- (setq new-buf (create-file-buffer name))
- (set-buffer new-buf)
- (erase-buffer)
- (insert-file-contents name t))
- (setq filename name
- error nil
- buf new-buf)
- t)
- nil))
-
-(defun PC-include-file-path ()
- (or PC-include-file-path
- (let ((env (getenv "INCPATH"))
- (path nil)
- pos)
- (or env (error "No include file path specified"))
- (while (setq pos (string-match ":[^:]+$" env))
- (setq path (cons (substring env (1+ pos)) path)
- env (substring env 0 pos)))
- path)))
-
-;;; This is adapted from lib-complete.el, by Mike Williams.
-(defun PC-include-file-all-completions (file search-path &optional full)
- "Return all completions for FILE in any directory on SEARCH-PATH.
-If optional third argument FULL is non-nil, returned pathnames should be
-absolute rather than relative to some directory on the SEARCH-PATH."
- (setq search-path
- (mapcar '(lambda (dir)
- (if dir (file-name-as-directory dir) default-directory))
- search-path))
- (if (file-name-absolute-p file)
- ;; It's an absolute file name, so don't need search-path
- (progn
- (setq file (expand-file-name file))
- (file-name-all-completions
- (file-name-nondirectory file) (file-name-directory file)))
- (let ((subdir (file-name-directory file))
- (ndfile (file-name-nondirectory file))
- file-lists)
- ;; Append subdirectory part to each element of search-path
- (if subdir
- (setq search-path
- (mapcar '(lambda (dir) (concat dir subdir))
- search-path)
- file ))
- ;; Make list of completions in each directory on search-path
- (while search-path
- (let* ((dir (car search-path))
- (subdir (if full dir subdir)))
- (if (file-directory-p dir)
- (progn
- (setq file-lists
- (cons
- (mapcar '(lambda (file) (concat subdir file))
- (file-name-all-completions ndfile
- (car search-path)))
- file-lists))))
- (setq search-path (cdr search-path))))
- ;; Compress out duplicates while building complete list (slloooow!)
- (let ((sorted (sort (apply 'nconc file-lists)
- '(lambda (x y) (not (string-lessp x y)))))
- compressed)
- (while sorted
- (if (equal (car sorted) (car compressed)) nil
- (setq compressed (cons (car sorted) compressed)))
- (setq sorted (cdr sorted)))
- compressed))))
-
-(defvar PC-old-read-file-name-internal nil)
-
-(defun PC-read-include-file-name-internal (string dir action)
- (if (string-match "<\\([^\"<>]*\\)>?$" string)
- (let* ((name (substring string (match-beginning 1) (match-end 1)))
- (str2 (substring string (match-beginning 0)))
- (completion-table
- (mapcar (function (lambda (x) (list (format "<%s>" x))))
- (PC-include-file-all-completions
- name (PC-include-file-path)))))
- (cond
- ((not completion-table) nil)
- ((eq action nil) (try-completion str2 completion-table nil))
- ((eq action t) (all-completions str2 completion-table nil))
- ((eq action 'lambda)
- (eq (try-completion str2 completion-table nil) t))))
- (funcall PC-old-read-file-name-internal string dir action)))
-
-(or PC-disable-includes
- (memq 'PC-look-for-include-file find-file-not-found-hooks)
- (setq find-file-not-found-hooks (cons 'PC-look-for-include-file
- find-file-not-found-hooks)))
-
-(or PC-disable-includes
- PC-old-read-file-name-internal
- (progn
- (setq PC-old-read-file-name-internal
- (symbol-function 'read-file-name-internal))
- (fset 'read-file-name-internal 'PC-read-include-file-name-internal)))
-
-
-(provide 'complete)
-
-;;; End.
diff --git a/lisp/completion.el b/lisp/completion.el
deleted file mode 100644
index 6ef505781e4..00000000000
--- a/lisp/completion.el
+++ /dev/null
@@ -1,2683 +0,0 @@
-;;; completion.el --- dynamic word-completion code
-
-;; Copyright (C) 1990, 1993, 1995 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: abbrev
-;; Author: Jim Salem <alem@bbnplanet.com> of Thinking Machines Inc.
-;; (ideas suggested by Brewster Kahle)
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; What to put in .emacs
-;;-----------------------
-;; (load "completion")
-;; (initialize-completions)
-
-;;---------------------------------------------------------------------------
-;; 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 hyphens, 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 noticeably faster).
-;;
-;; M-X completion-mode toggles whether or not new words are added to the
-;; database by changing the value of enable-completion.
-;;
-;; SAVING/LOADING COMPLETIONS
-;; Completions are automatically saved from one session to another
-;; (unless save-completions-flag or enable-completion 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 enable-completion is T. The number of old
-;; versions kept of the saved completions file is controlled by
-;; completions-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.
-;;
-;;---------------------------------------------------------------------------
-;;
-;;
-
-;;---------------------------------------------------------------------------
-;; 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
-;;
-;;
-;;-----------------------------------------------
-;;; Change Log:
-;;-----------------------------------------------
-;; 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 Brewster 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.
-;;
-;;-----------------------------------------------
-;; Acknowledgements
-;;-----------------------------------------------
-;; 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)
-
-;;; Code:
-
-;;---------------------------------------------------------------------------
-;; User changeable parameters
-;;---------------------------------------------------------------------------
-
-(defvar enable-completion t
- "*Non-nil means enable recording and saving of completions.
-If nil, no new words added to the database or saved to the init file.")
-
-(defvar save-completions-flag t
- "*Non-nil means save most-used completions when exiting Emacs.
-See also `saved-completions-retention-time'.")
-
-(defvar save-completions-file-name (convert-standard-filename "~/.completions")
- "*The filename to save completions to.")
-
-(defvar save-completions-retention-time 336
- "*Discard a completion if unused for this many 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 completion-on-separator-character nil
- "*Non-nil means separator characters mark previous word as used.
-This means the word will be saved as a completion.")
-
-(defvar completions-file-versions-kept kept-new-versions
- "*Number of versions to keep for the saved completions file.")
-
-(defvar completion-prompt-speed-threshold 4800
- "*Minimum output speed at which to display next potential completion.")
-
-(defvar completion-cdabbrev-prompt-flag nil
- "*If non-nil, the next completion prompt does a cdabbrev search.
-This can be time consuming.")
-
-(defvar completion-search-distance 15000
- "*How far to search in the buffer when looking for completions.
-In number of characters. If nil, search the whole buffer.")
-
-(defvar completions-merging-modes '(lisp c)
- "*List of modes {`c' or `lisp'} for automatic completions merging.
-Definitions from visited files which have these modes
-are automatically added to the completion database.")
-
-;;(defvar *record-cmpl-statistics-p* nil
-;; "*If non-nil, record completion statistics.")
-
-;;(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))
-
-(eval-when-compile
- (defvar completion-gensym-counter 0)
- (defun completion-gensym (&optional arg)
- "Generate a new uninterned symbol.
-The name is made by appending a number to PREFIX, default \"G\"."
- (let ((prefix (if (stringp arg) arg "G"))
- (num (if (integerp arg) arg
- (prog1 completion-gensym-counter
- (setq completion-gensym-counter (1+ completion-gensym-counter))))))
- (make-symbol (format "%s%d" prefix num)))))
-
-(defmacro completion-dolist (spec &rest body)
- "(completion-dolist (VAR LIST [RESULT]) BODY...): loop over a list.
-Evaluate BODY with VAR bound to each `car' from LIST, in turn.
-Then evaluate RESULT to get return value, default nil."
- (let ((temp (completion-gensym "--dolist-temp--")))
- (append (list 'let (list (list temp (nth 1 spec)) (car spec))
- (append (list 'while temp
- (list 'setq (car spec) (list 'car temp)))
- body (list (list 'setq temp
- (list 'cdr temp)))))
- (if (cdr (cdr spec))
- (cons (list 'setq (car spec) nil) (cdr (cdr spec)))
- '(nil)))))
-
-(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)))
-
-(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.")
-
-(defvar cmpl-preceding-syntax)
-
-(defvar completion-string)
-
-;;---------------------------------------------------------------------------
-;; Low level tools
-;;---------------------------------------------------------------------------
-
-;;-----------------------------------------------
-;; Misc.
-;;-----------------------------------------------
-
-(defun minibuffer-window-selected-p ()
- "True iff the current window is the minibuffer."
- (window-minibuffer-p (selected-window)))
-
-;; This used to be `(eval form)'. Eval FORM at run time now.
-(defmacro cmpl-read-time-eval (form)
- form)
-
-;;-----------------------------------------------
-;; 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
-
-
-(defun cmpl-hours-since-origin ()
- (let ((time (current-time)))
- (floor (+ (* 65536.0 (nth 0 time)) (nth 1 time)) 3600)))
-
-;;---------------------------------------------------------------------------
-;; "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 hyphen (`-'). Perhaps the hyphen 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 cmpl-make-standard-completion-syntax-table ()
- (let ((table (make-syntax-table))
- i)
- ;; Default syntax is whitespace.
- (setq i 0)
- (while (< i 256)
- (modify-syntax-entry i " " table)
- (setq i (1+ i)))
- ;; alpha chars
- (setq i 0)
- (while (< i 26)
- (modify-syntax-entry (+ ?a i) "_" table)
- (modify-syntax-entry (+ ?A i) "_" table)
- (setq i (1+ i)))
- ;; digit chars.
- (setq i 0)
- (while (< i 10)
- (modify-syntax-entry (+ ?0 i) "_" table)
- (setq i (1+ i)))
- ;; Other ones
- (let ((symbol-chars '(?@ ?/ ?\\ ?* ?+ ?~ ?$ ?< ?> ?%))
- (symbol-chars-ignore '(?_ ?- ?: ?.))
- )
- (completion-dolist (char symbol-chars)
- (modify-syntax-entry char "_" table))
- (completion-dolist (char symbol-chars-ignore)
- (modify-syntax-entry char "w" table)
- )
- )
- table))
-
-(defconst cmpl-standard-syntax-table (cmpl-make-standard-completion-syntax-table))
-
-(defun cmpl-make-lisp-completion-syntax-table ()
- (let ((table (copy-syntax-table cmpl-standard-syntax-table))
- (symbol-chars '(?! ?& ?? ?= ?^))
- )
- (completion-dolist (char symbol-chars)
- (modify-syntax-entry char "_" table))
- table))
-
-(defun cmpl-make-c-completion-syntax-table ()
- (let ((table (copy-syntax-table cmpl-standard-syntax-table))
- (separator-chars '(?+ ?* ?/ ?: ?%))
- )
- (completion-dolist (char separator-chars)
- (modify-syntax-entry char " " table))
- table))
-
-(defun cmpl-make-fortran-completion-syntax-table ()
- (let ((table (copy-syntax-table cmpl-standard-syntax-table))
- (separator-chars '(?+ ?- ?* ?/ ?:))
- )
- (completion-dolist (char separator-chars)
- (modify-syntax-entry char " " table))
- table))
-
-(defconst cmpl-lisp-syntax-table (cmpl-make-lisp-completion-syntax-table))
-(defconst cmpl-c-syntax-table (cmpl-make-c-completion-syntax-table))
-(defconst cmpl-fortran-syntax-table (cmpl-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
-;;-----------------------------------------------
-
-(add-hook 'lisp-mode-hook
- '(lambda ()
- (setq cmpl-syntax-table cmpl-lisp-syntax-table)))
-
-(add-hook 'c-mode-hook
- '(lambda ()
- (setq cmpl-syntax-table cmpl-c-syntax-table)))
-
-(add-hook 'fortran-mode-hook
- '(lambda ()
- (setq cmpl-syntax-table cmpl-fortran-syntax-table)
- (completion-setup-fortran-mode)))
-
-;;-----------------------------------------------
-;; Symbol functions
-;;-----------------------------------------------
-(defvar cmpl-symbol-start nil
- "Holds first character of symbol, after any completion symbol function.")
-(defvar cmpl-symbol-end nil
- "Holds last character of symbol, after any completion symbol function.")
-;; 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.
-But only if it is longer than `completion-min-length'."
- (setq cmpl-saved-syntax (syntax-table))
- (unwind-protect
- (progn
- (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)
- ))
- ;; Return completion if the length is reasonable.
- (if (and (<= (cmpl-read-time-eval completion-min-length)
- (- cmpl-symbol-end cmpl-symbol-start))
- (<= (- cmpl-symbol-end cmpl-symbol-start)
- (cmpl-read-time-eval completion-max-length)))
- (buffer-substring cmpl-symbol-start cmpl-symbol-end)))))
- (set-syntax-table cmpl-saved-syntax)))
-
-;; 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.
-Returns 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))
- (unwind-protect
- (progn
- (set-syntax-table cmpl-syntax-table)
- ;; Cursor is on following-char and after preceding-char
- (cond ((= (setq cmpl-preceding-syntax (char-syntax (preceding-char))) ?_)
- ;; Number of chars to ignore at end.
- (setq cmpl-symbol-end (point)
- cmpl-symbol-start (scan-sexps 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)
- ))
- ;; Return value if long enough.
- (if (>= cmpl-symbol-end
- (+ cmpl-symbol-start
- (cmpl-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 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)
- ;; Return completion if the length is reasonable
- (if (and (<= (cmpl-read-time-eval completion-min-length)
- (- cmpl-symbol-end cmpl-symbol-start))
- (<= (- cmpl-symbol-end cmpl-symbol-start)
- (cmpl-read-time-eval completion-max-length)))
- (buffer-substring cmpl-symbol-start cmpl-symbol-end)))))
- (set-syntax-table cmpl-saved-syntax)))
-
-;; 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.
- (cond ((memq (progn
- (setq cmpl-saved-syntax (syntax-table))
- (unwind-protect
- (progn
- (set-syntax-table cmpl-syntax-table)
- (char-syntax (following-char)))
- (set-syntax-table cmpl-saved-syntax)))
- '(?w ?_))
- (symbol-under-point))
- (t
- (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))
- (unwind-protect
- (progn
- (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 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)
- ))
- ;; Return completion if the length is reasonable.
- (if (and (<= (cmpl-read-time-eval
- completion-prefix-min-length)
- (- cmpl-symbol-end cmpl-symbol-start))
- (<= (- cmpl-symbol-end cmpl-symbol-start)
- (cmpl-read-time-eval completion-max-length)))
- (buffer-substring cmpl-symbol-start cmpl-symbol-end)))))
- ;; Restore syntax table.
- (set-syntax-table cmpl-saved-syntax)))
-
-;; 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)
-(defvar cdabbrev-stop-point)
-
-;; 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."
- ;; 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)))
- )
- (if cdabbrev-current-window
- (save-excursion
- (set-cdabbrev-buffer)
- (setq cdabbrev-current-point (point)
- cdabbrev-start-point cdabbrev-current-point
- cdabbrev-stop-point
- (if completion-search-distance
- (max (point-min)
- (- cdabbrev-start-point completion-search-distance))
- (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 already.
-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
- (if 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 completion-search-distance
- (min (point-max) (+ cdabbrev-start-point completion-search-distance))
- (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 prefixes.
-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 every time 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 origin. 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))
-
-;; Constructor
-
-(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))
- )
-
-(defvar completions-list-return-value)
-
-(defun list-all-completions ()
- "Returns a list of all the known completion entries."
- (let ((completions-list-return-value nil))
- (mapatoms 'list-all-completions-1 cmpl-prefix-obarray)
- completions-list-return-value))
-
-(defun list-all-completions-1 (prefix-symbol)
- (if (boundp prefix-symbol)
- (setq completions-list-return-value
- (append (cmpl-prefix-entry-head (symbol-value prefix-symbol))
- completions-list-return-value))))
-
-(defun list-all-completions-by-hash-bucket ()
- "Return list of lists of known completion entries, organized by hash bucket."
- (let ((completions-list-return-value nil))
- (mapatoms 'list-all-completions-by-hash-bucket-1 cmpl-prefix-obarray)
- completions-list-return-value))
-
-(defun list-all-completions-by-hash-bucket-1 (prefix-symbol)
- (if (boundp prefix-symbol)
- (setq completions-list-return-value
- (cons (cmpl-prefix-entry-head (symbol-value prefix-symbol))
- completions-list-return-value))))
-
-
-;;-----------------------------------------------
-;; 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"
- completion-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 STRING is not in the database add it to appropriate prefix list.
-STRING is added to the end of the appropriate 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
- (cmpl-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 (completion-string)
- "If COMPLETION-STRING is not in the database, add it to prefix list.
-We add COMPLETION-STRING to the head of the appropriate prefix list,
-or it to the head of the list.
-COMPLETION-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 completion-string))
- ;; found
- (let* ((prefix-entry (find-cmpl-prefix-entry
- (substring cmpl-db-downcase-string 0
- (cmpl-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 completion-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 completion-string))
- ;; setup the prefix
- (prefix-entry (find-cmpl-prefix-entry
- (substring cmpl-db-downcase-string 0
- (cmpl-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 (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 completion-string))
- ;; found
- (let* ((prefix-entry (find-cmpl-prefix-entry
- (substring cmpl-db-downcase-string 0
- (cmpl-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'" completion-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)
- "Add STRING to completion list, or move it to head of 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)
- "Add STRING if it isn't already listed, and mark it permanent."
- (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 ()
- "Add the completion symbol underneath the point into the completion buffer."
- (let ((string (and enable-completion (symbol-under-point)))
- (current-completion-source cmpl-source-cursor-moves))
- (if string (add-completion-to-head string))))
-
-(defun use-completion-before-point ()
- "Add the completion symbol before point into the completion buffer."
- (let ((string (and enable-completion (symbol-before-point)))
- (current-completion-source cmpl-source-cursor-moves))
- (if string (add-completion-to-head string))))
-
-(defun use-completion-under-or-before-point ()
- "Add the completion symbol before point into the completion buffer."
- (let ((string (and enable-completion (symbol-under-or-before-point)))
- (current-completion-source cmpl-source-cursor-moves))
- (if string (add-completion-to-head string))))
-
-(defun use-completion-before-separator ()
- "Add the completion symbol before point into the completion buffer.
-Completions added this way will automatically be saved if
-`completion-on-separator-character' is non-nil."
- (let ((string (and enable-completion (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))
- (if (and completion-on-separator-character
- (zerop (completion-num-uses entry)))
- (progn
- (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)
- "Set up the for completion searching for STRING.
-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 completion-prefix-min-length))))
- 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)
- "Return the next completion entry.
-If INDEX is out of sequence, reset and start from the top.
-If there are no more entries, try cdabbrev and returns only a string."
- (cond
- ((= index (setq cmpl-last-index (1+ cmpl-last-index)))
- (completion-search-peek t))
- ((< index 0)
- (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)
- (< (setq index (1+ index)) 0))
- (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 (< (setq index (1- index)) 0)))
- (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' results in the same
-string being returned. Depends on `case-fold-search'.
-If there are no more entries, try cdabbrev and then return 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 to add new words to the completion database."
- (interactive)
- (setq enable-completion (not enable-completion))
- (message "Completion mode is now %s." (if enable-completion "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)
- "Fill out a completion of the word before point.
-Point is left at end. Consecutive 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, 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 (>= baud-rate completion-prompt-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
- (sit-for 0)
- (setq entry
- (completion-search-peek
- completion-cdabbrev-prompt-flag)))
- (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
- ;; This used to call cmpl19-sit-for, an undefined function.
- ;; I hope that sit-for does the right thing; I don't know -- rms.
- (if (and print-status-p (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
-;;-----------------------------------------------
-
-(global-set-key "\M-\r" 'complete)
-(global-set-key [?\C-\r] 'complete)
-(define-key function-key-map [C-return] [?\C-\r])
-
-;; 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)
- "Parse possible completions from a file and add them to data base."
- (interactive "fFile: ")
- (setq file (expand-file-name file))
- (let* ((buffer (get-file-buffer file))
- (buffer-already-there-p buffer)
- )
- (if (not buffer-already-there-p)
- (let ((completions-merging-modes nil))
- (setq buffer (find-file-noselect file))))
- (unwind-protect
- (save-excursion
- (set-buffer buffer)
- (add-completions-from-buffer)
- )
- (if (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 "Cannot 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 (enable-completion
- (cond ((and (memq major-mode '(emacs-lisp-mode lisp-mode))
- (memq 'lisp completions-merging-modes)
- )
- (add-completions-from-buffer))
- ((and (memq major-mode '(c-mode))
- (memq 'c completions-merging-modes)
- )
- (add-completions-from-buffer)
- )))
- ))
-
-(add-hook 'find-file-hooks 'cmpl-find-file-hook)
-
-;;-----------------------------------------------
-;; Tags Table Completions
-;;-----------------------------------------------
-
-(defun add-completions-from-tags-table ()
- ;; Inspired by eero@media-lab.media.mit.edu
- "Add completions from the current tags table."
- (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
-
-;; Parses all the definition names from a Lisp mode buffer and adds them to
-;; the completion database.
-(defun add-completions-from-lisp-buffer ()
- ;;; 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 --> ] }
-;; opening and closing must be skipped over
-;; Whitespace chars (have symbol syntax)
-;; Everything else has word syntax
-
-(defun cmpl-make-c-def-completion-syntax-table ()
- (let ((table (make-syntax-table))
- (whitespace-chars '(? ?\n ?\t ?\f ?\v ?\r))
- ;; unfortunately the ?( causes the parens to appear unbalanced
- (separator-chars '(?, ?* ?= ?\( ?\;
- ))
- i)
- ;; default syntax is whitespace
- (setq i 0)
- (while (< i 256)
- (modify-syntax-entry i "w" table)
- (setq i (1+ i)))
- (completion-dolist (char whitespace-chars)
- (modify-syntax-entry char "_" table))
- (completion-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 (cmpl-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
-
-;; Parses all the definition names from a C mode buffer and adds them to the
-;; completion database.
-(defun add-completions-from-c-buffer ()
- ;; 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 (nth 1 e)
- "Containing expression ends prematurely")
- (string-equal (nth 1 e) "Unbalanced parentheses"))
- ;; unbalanced paren., keep going
- ;;(ding)
- (forward-line 1)
- (message "Error parsing C buffer for completions--please send bug report")
- (throw 'finish-add-completions t)
- ))
- ))
- (set-syntax-table saved-syntax)
- )))))
-
-
-;;---------------------------------------------------------------------------
-;; Init files
-;;---------------------------------------------------------------------------
-
-;; The version of save-completions-to-file called at kill-emacs time.
-(defun kill-emacs-save-completions ()
- (if (and save-completions-flag enable-completion cmpl-initialized-p)
- (cond
- ((not cmpl-completions-accepted-p)
- (message "Completions database has not changed - not writing."))
- (t
- (save-completions-to-file)))))
-
-;; There is no point bothering to change this again
-;; unless the package changes so much that it matters
-;; for people that have saved completions.
-(defconst completion-version "11")
-
-(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 origin.
-\n")
-
-(defun completion-backup-filename (filename)
- (concat filename ".BAK"))
-
-(defun save-completions-to-file (&optional filename)
- "Save completions in init file FILENAME.
-If file name is not specified, use `save-completions-file-name'."
- (interactive)
- (setq filename (expand-file-name (or filename save-completions-file-name)))
- (if (file-writable-p filename)
- (progn
- (if (not cmpl-initialized-p)
- (initialize-completions));; make sure everything's loaded
- (message "Saving completions to file %s" filename)
-
- (let* ((delete-old-versions t)
- (kept-old-versions 0)
- (kept-new-versions completions-file-versions-kept)
- last-use-time
- (current-time (cmpl-hours-since-origin))
- (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)
-
- (if (not (verify-visited-file-modtime (current-buffer)))
- (progn
- ;; 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))
- (completion-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 (> (completion-num-uses completion) 0)
- ;; it's been used
- (setq last-use-time current-time)
- ;; or it was saved before and
- (and last-use-time
- ;; save-completions-retention-time is nil
- (or (not save-completions-retention-time)
- ;; or time since last use is < ...retention-time*
- (< (- current-time last-use-time)
- save-completions-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)))
- (if file-exists-p
- (progn
- ;; 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}
- (or (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)
- (if 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 ()
-;; (if (and save-completions-flag enable-completion cmpl-initialized-p
-;; *completion-auto-save-period*
-;; (> cmpl-emacs-idle-time *completion-auto-save-period*)
-;; cmpl-completions-accepted-p)
-;; (save-completions-to-file)))
-
-;;(add-hook 'cmpl-emacs-idle-time-hooks 'autosave-completions)
-
-(defun load-completions-from-file (&optional filename no-message-p)
- "Loads a completion init file FILENAME.
-If file is not specified, then use `save-completions-file-name'."
- (interactive)
- (setq filename (expand-file-name (or filename save-completions-file-name)))
- (let* ((backup-filename (completion-backup-filename filename))
- (backup-readable-p (file-readable-p backup-filename))
- )
- (if backup-readable-p (setq filename backup-filename))
- (if (file-readable-p filename)
- (progn
- (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-origin))
- 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
- (if insert-okay-p
- (progn
- (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 ()
- "Load the default completions file.
-Also sets up so that exiting emacs will automatically save the file."
- (interactive)
- (cond ((not cmpl-initialized-p)
- (load-completions-from-file)
- ))
- (setq cmpl-initialized-p t)
- )
-
-
-;;-----------------------------------------------
-;; Kill EMACS patch
-;;-----------------------------------------------
-
-(add-hook 'kill-emacs-hook
- '(lambda ()
- (kill-emacs-save-completions)
- (cmpl-statistics-block
- (record-cmpl-kill-emacs))))
-
-;;-----------------------------------------------
-;; Kill region patch
-;;-----------------------------------------------
-
-(defun completion-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 "r")
- (cond ((eq last-command 'complete)
- (delete-region (point) cmpl-last-insert-location)
- (insert cmpl-original-string)
- (setq completion-to-accept nil)
- (cmpl-statistics-block
- (record-complete-failed)))
- (t
- (kill-region beg end))))
-
-(global-set-key "\C-w" 'completion-kill-region)
-
-;;-----------------------------------------------
-;; Patches to self-insert-command.
-;;-----------------------------------------------
-
-;; Need 2 versions: generic separator 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 before 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 auto-fill-function
- (funcall auto-fill-function))
- )
-
-;;-----------------------------------------------
-;; 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 function execution.
-TYPE is the type of the wrapper to be added. Can be :before or :under."
- (cond ((eq type ':separator)
- (list 'put (list 'quote function-name) ''completion-function
- ''use-completion-before-separator))
- ((eq type ':before)
- (list 'put (list 'quote function-name) ''completion-function
- ''use-completion-before-point))
- ((eq type ':backward-under)
- (list 'put (list 'quote function-name) ''completion-function
- ''use-completion-backward-under))
- ((eq type ':backward)
- (list 'put (list 'quote function-name) ''completion-function
- ''use-completion-backward))
- ((eq type ':under)
- (list 'put (list 'quote function-name) ''completion-function
- ''use-completion-under-point))
- ((eq type ':under-or-before)
- (list 'put (list 'quote function-name) ''completion-function
- ''use-completion-under-or-before-point))
- ((eq type ':minibuffer-separator)
- (list 'put (list 'quote function-name) ''completion-function
- ''use-completion-minibuffer-separator))))
-
-(defun use-completion-minibuffer-separator ()
- (let ((cmpl-syntax-table cmpl-standard-syntax-table))
- (use-completion-before-separator)))
-
-(defun use-completion-backward-under ()
- (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))))
-
-(defun use-completion-backward ()
- (if (eq last-command 'complete)
- ;; probably a failed completion if you have to back up
- (cmpl-statistics-block (record-complete-failed))))
-
-(defun completion-before-command ()
- (funcall (or (and (symbolp this-command)
- (get this-command 'completion-function))
- 'use-completion-under-or-before-point)))
-(add-hook 'pre-command-hook 'completion-before-command)
-
-
-;;---------------------------------------------------------------------------
-;; 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)
-
-;; Avoid warnings.
-(defvar c-mode-map)
-(defvar fortran-mode-map)
-
-;; C mode diffs.
-(defun completion-c-mode-hook ()
- (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))
-;; Do this either now or whenever C mode is loaded.
-(if (featurep 'cc-mode)
- (completion-c-mode-hook)
- (add-hook 'c-mode-hook 'completion-c-mode-hook))
-
-;; 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)
-(def-completion-wrapper comint-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)
-(def-completion-wrapper beginning-of-line :under-or-before)
-(def-completion-wrapper end-of-line :under-or-before)
-(def-completion-wrapper forward-char :under-or-before)
-(def-completion-wrapper forward-word :under-or-before)
-(def-completion-wrapper forward-sexp :under-or-before)
-(def-completion-wrapper backward-char :backward-under)
-(def-completion-wrapper backward-word :backward-under)
-(def-completion-wrapper backward-sexp :backward-under)
-
-(def-completion-wrapper delete-backward-char :backward)
-(def-completion-wrapper delete-backward-char-untabify :backward)
-
-;; Tests --
-;; foobarbiz
-;; foobar
-;; fooquux
-;; fooper
-
-(cmpl-statistics-block
- (record-completion-file-loaded))
-
-(provide 'completion)
-
-;;; completion.el ends here
diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el
deleted file mode 100644
index ed6ef3e92a4..00000000000
--- a/lisp/dabbrev.el
+++ /dev/null
@@ -1,867 +0,0 @@
-;;; dabbrev.el --- dynamic abbreviation package
-
-;; Copyright (C) 1985, 1986, 1992, 1994 Free Software Foundation, Inc.
-
-;; Author: Don Morrison
-;; Maintainer: Lars Lindberg <Lars.Lindberg@sypro.cap.se>
-;; Created: 16 Mars 1992
-;; Lindberg's last update version: 5.7
-;; Keywords: abbrev expand completion
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The purpose with this package is to let you write just a few
-;; characters of words you've written earlier to be able to expand
-;; them.
-;;
-;; To expand a word, just put the point right after the word and press
-;; M-/ (dabbrev-expand) or M-C-/ (dabbrev-completion).
-;;
-;; Check out the customizable variables below to learn about all the
-;; features of this package.
-
-;;; Hints and tips for major modes writers:
-
-;; Recommended values C/Lisp etc text
-;; dabbrev-case-fold-search nil t
-;; dabbrev-case-replace nil t
-;;
-;; Set the variables you want special for your mode like this:
-;; (set (make-local-variable 'dabbrev-case-replace) nil)
-;; Then you don't interfere with other modes.
-;;
-;; If your mode handles buffers that refers to other buffers
-;; (i.e. compilation-mode, gud-mode), then try to set
-;; `dabbrev-select-buffers-function' or `dabbrev-friend-buffer-function'
-;; to a function that point out those buffers.
-
-;; Same goes for major-modes that are connected to other modes. There
-;; are for instance a number of mail-modes. One for reading, one for
-;; creating a new mail etc. Maybe those should be connected.
-
-;; Example for GNUS (when we write a reply, we want dabbrev to look in
-;; the article for expansion):
-;; (set (make-local-variable 'dabbrev-friend-buffer-function)
-;; (lambda (buffer)
-;; (save-excursion
-;; (set-buffer buffer)
-;; (memq major-mode '(news-reply-mode gnus-article-mode)))))
-
-
-;; Known bugs and limitations.
-;; - Possible to do several levels of `dabbrev-completion' in the
-;; minibuffer.
-;; - dabbrev-completion doesn't handle resetting the globals variables
-;; right. It resets them after finding the abbrev.
-
-;; Future enhancements
-;; - Check the tags-files? Like tags-complete?
-;; - Add the possibility of searching both forward and backward to
-;; the nearest expansion.
-;; - Check the kill-ring when everything else fails. (Maybe something
-;; for hippie-expand?). [Bng] <boris@cs.rochester.edu>
-
-;;; These people gave suggestions:
-;; [hymie] Hyman Rosen <marks!hymie@jyacc.jyacc.com>
-;; [burgett] Steve Burgett <burgett@bizet.eecs.berkeley.edu>
-;; [jules] Julian Gosnell <jules@x.co.uk>
-;; [kifer] Michael Kifer <kifer@sbcs.sunysb.edu>
-;; [ake] Ake Stenhoff <extaksf@aom.ericsson.se>
-;; [alon] Alon Albert <al%imercury@uunet.uu.net>
-;; [tromey] Tom Tromey <tromey@busco.lanl.gov>
-;; [Rolf] Rolf Schreiber <rolf@mathematik.uni-stuttgart.de>
-;; [Petri] Petri Raitio <per@tekla.fi>
-;; [ejb] Jay Berkenbilt <ejb@ERA.COM>
-;; [hawley] Bob Hawley <rth1@quartet.mt.att.com>
-;; ... and to all the people who have participated in the beta tests.
-
-;;; Code:
-
-;;----------------------------------------------------------------
-;; Customization variables
-;;----------------------------------------------------------------
-(defvar dabbrev-backward-only nil
- "*If non-nil, `dabbrev-expand' only looks backwards.")
-
-(defvar dabbrev-limit nil
- "*Limits region searched by `dabbrev-expand' to this many chars away.")
-
-(defvar dabbrev-abbrev-skip-leading-regexp nil
- "*Regexp for skipping leading characters of an abbreviation.
-
-Example: Set this to \"\\\\$\" for programming languages
-in which variable names may appear with or without a leading `$'.
-\(For example, in Makefiles.)
-
-Set this to nil if no characters should be skipped.")
-
-;; I recommend that you set this to nil.
-(defvar dabbrev-case-fold-search 'case-fold-search
- "*Non-nil if dabbrev searches should ignore case.
-A value of nil means case is significant.
-
-The value of this variable is an expression; it is evaluated
-and the resulting value determines the decision.
-For example: setting this to `case-fold-search' means evaluate that
-variable to see whether its value is nil.")
-
-(defvar dabbrev-upcase-means-case-search nil
- "*The significance of an uppercase character in an abbreviation.
-nil means case fold search, non-nil means case sensitive search.
-
-This variable has an effect only when the value of
-`dabbrev-case-fold-search' evaluates to t.")
-
-;; I recommend that you set this to nil.
-(defvar dabbrev-case-replace 'case-replace
- "*Non-nil means dabbrev should preserve case when expanding the abbreviation.
-More precisely, it preserves the case pattern of the abbreviation as you
-typed it--as opposed to the case pattern of the expansion that is copied.
-The value of this variable is an expression; it is evaluated
-and the resulting value determines the decision.
-For example, setting this to `case-replace' means evaluate that
-variable to see if its value is t or nil.
-
-This variable has an effect only when the value of
-`dabbrev-case-fold-search' evaluates to t.")
-
-(defvar dabbrev-abbrev-char-regexp nil
- "*Regexp to recognize a character in an abbreviation or expansion.
-This regexp will be surrounded with \\\\( ... \\\\) when actually used.
-
-Set this variable to \"\\\\sw\" if you want ordinary words or
-\"\\\\sw\\\\|\\\\s_\" if you want symbols (including characters whose
-syntax is \"symbol\" as well as those whose syntax is \"word\".
-
-The value nil has a special meaning: the abbreviation is from point to
-previous word-start, but the search is for symbols.
-
-For instance, if you are programming in Lisp, `yes-or-no-p' is a symbol,
-while `yes', `or', `no' and `p' are considered words. If this
-variable is nil, then expanding `yes-or-no-' looks for a symbol
-starting with or containing `no-'. If you set this variable to
-\"\\\\sw\\\\|\\\\s_\", that expansion looks for a symbol starting with
-`yes-or-no-'. Finally, if you set this variable to \"\\\\sw\", then
-expanding `yes-or-no-' signals an error because `-' is not part of a word;
-but expanding `yes-or-no' looks for a word starting with `no'.
-
-The recommended value is \"\\\\sw\\\\|\\\\s_\".")
-
-(defvar dabbrev-check-all-buffers t
- "*Non-nil means dabbrev package should search *all* buffers.
-
-Dabbrev always searches the current buffer first. Then, if
-`dabbrev-check-other-buffers' says so, it searches the buffers
-designated by `dabbrev-select-buffers-function'.
-
-Then, if `dabbrev-check-all-buffers' is non-nil, dabbrev searches
-all the other buffers.")
-
-(defvar dabbrev-check-other-buffers t
- "*Should \\[dabbrev-expand] look in other buffers?\
-
-nil: Don't look in other buffers.
-t: Also look for expansions in the buffers pointed out by
- `dabbrev-select-buffers-function'.
-Anything else: When we can't find any more expansions in
-the current buffer, then ask the user whether to look in other
-buffers too.
-
-The default value is t.")
-
-;; I guess setting this to a function that selects all C- or C++-
-;; mode buffers would be a good choice for a debugging buffer,
-;; when debugging C- or C++-code.
-(defvar dabbrev-select-buffers-function 'dabbrev--select-buffers
- "A function that selects buffers that should be searched by dabbrev.
-The function should take no arguments and return a list of buffers to
-search for expansions. Have a look at `dabbrev--select-buffers' for
-an example.
-
-A mode setting this variable should make it buffer local.")
-
-(defvar dabbrev-friend-buffer-function 'dabbrev--same-major-mode-p
- "*A function to decide whether dabbrev should search OTHER-BUFFER.
-The function should take one argument, OTHER-BUFFER, and return
-non-nil if that buffer should be searched. Have a look at
-`dabbrev--same-major-mode-p' for an example.
-
-The value of `dabbrev-friend-buffer-function' has an effect only if
-the value of `dabbrev-select-buffers-function' uses it. The function
-`dabbrev--select-buffers' is one function you can use here.
-
-A mode setting this variable should make it buffer local.")
-
-(defvar dabbrev-search-these-buffers-only nil
- "If non-nil, a list of buffers which dabbrev should search.
-If this variable is non-nil, dabbrev will only look in these buffers.
-It will not even look in the current buffer if it is not a member of
-this list.")
-
-;;----------------------------------------------------------------
-;; Internal variables
-;;----------------------------------------------------------------
-
-;; Last obarray of completions in `dabbrev-completion'
-(defvar dabbrev--last-obarray nil)
-
-;; Table of expansions seen so far
-(defvar dabbrev--last-table nil)
-
-;; Last string we tried to expand.
-(defvar dabbrev--last-abbreviation nil)
-
-;; Location last abbreviation began
-(defvar dabbrev--last-abbrev-location nil)
-
-;; Direction of last dabbrevs search
-(defvar dabbrev--last-direction 0)
-
-;; Last expansion of an abbreviation.
-(defvar dabbrev--last-expansion nil)
-
-;; Location the last expansion was found.
-(defvar dabbrev--last-expansion-location nil)
-
-;; The list of remaining buffers with the same mode as current buffer.
-(defvar dabbrev--friend-buffer-list nil)
-
-;; The buffer we looked in last.
-(defvar dabbrev--last-buffer nil)
-
-;; The buffer we found the expansion last time.
-(defvar dabbrev--last-buffer-found nil)
-
-;; The buffer we last did a completion in.
-(defvar dabbrev--last-completion-buffer nil)
-
-;; Non-nil means we should upcase
-;; when copying successive words.
-(defvar dabbrev--last-case-pattern nil)
-
-;; Same as dabbrev-check-other-buffers, but is set for every expand.
-(defvar dabbrev--check-other-buffers dabbrev-check-other-buffers)
-
-;; The regexp for recognizing a character in an abbreviation.
-(defvar dabbrev--abbrev-char-regexp nil)
-
-;;----------------------------------------------------------------
-;; Macros
-;;----------------------------------------------------------------
-
-;;; Get the buffer that mini-buffer was activated from
-(defsubst dabbrev--minibuffer-origin ()
- (car (cdr (buffer-list))))
-
-;; Make a list of some of the elements of LIST.
-;; Check each element of LIST, storing it temporarily in the
-;; variable ELEMENT, and include it in the result
-;; if CONDITION evaluates non-nil.
-(defmacro dabbrev-filter-elements (element list condition)
- (` (let (dabbrev-result dabbrev-tail (, element))
- (setq dabbrev-tail (, list))
- (while dabbrev-tail
- (setq (, element) (car dabbrev-tail))
- (if (, condition)
- (setq dabbrev-result (cons (, element) dabbrev-result)))
- (setq dabbrev-tail (cdr dabbrev-tail)))
- (nreverse dabbrev-result))))
-
-;;----------------------------------------------------------------
-;; Exported functions
-;;----------------------------------------------------------------
-
-;;;###autoload
-(define-key esc-map "/" 'dabbrev-expand)
-;;;??? Do we want this?
-;;;###autoload
-(define-key esc-map [?\C-/] 'dabbrev-completion)
-
-;;;###autoload
-(defun dabbrev-completion (&optional arg)
- "Completion on current word.
-Like \\[dabbrev-expand] but finds all expansions in the current buffer
-and presents suggestions for completion.
-
-With a prefix argument, it searches all buffers accepted by the
-function pointed out by `dabbrev-friend-buffer-function' to find the
-completions.
-
-If the prefix argument is 16 (which comes from C-u C-u),
-then it searches *all* buffers.
-
-With no prefix argument, it reuses an old completion list
-if there is a suitable one already."
-
- (interactive "*P")
- (dabbrev--reset-global-variables)
- (let* ((dabbrev-check-other-buffers (and arg t))
- (dabbrev-check-all-buffers
- (and arg (= (prefix-numeric-value arg) 16)))
- (abbrev (dabbrev--abbrev-at-point))
- (ignore-case-p (and (eval dabbrev-case-fold-search)
- (or (not dabbrev-upcase-means-case-search)
- (string= abbrev (downcase abbrev)))))
- (my-obarray dabbrev--last-obarray)
- init)
- (save-excursion
- (if (and (null arg)
- my-obarray
- (or (eq dabbrev--last-completion-buffer (current-buffer))
- (and (window-minibuffer-p (selected-window))
- (eq dabbrev--last-completion-buffer
- (dabbrev--minibuffer-origin))))
- dabbrev--last-abbreviation
- (>= (length abbrev) (length dabbrev--last-abbreviation))
- (string= dabbrev--last-abbreviation
- (substring abbrev 0
- (length dabbrev--last-abbreviation)))
- (setq init (try-completion abbrev my-obarray)))
- ;; We can reuse the existing completion list.
- nil
- ;;--------------------------------
- ;; New abbreviation to expand.
- ;;--------------------------------
- (setq dabbrev--last-abbreviation abbrev)
- ;; Find all expansion
- (let ((completion-list
- (dabbrev--find-all-expansions abbrev ignore-case-p))
- (completion-ignore-case ignore-case-p))
- ;; Make an obarray with all expansions
- (setq my-obarray (make-vector (length completion-list) 0))
- (or (> (length my-obarray) 0)
- (error "No dynamic expansion for \"%s\" found%s"
- abbrev
- (if dabbrev--check-other-buffers "" " in this-buffer")))
- (cond
- ((or (not ignore-case-p)
- (not dabbrev-case-replace))
- (mapcar (function (lambda (string)
- (intern string my-obarray)))
- completion-list))
- ((string= abbrev (upcase abbrev))
- (mapcar (function (lambda (string)
- (intern (upcase string) my-obarray)))
- completion-list))
- ((string= (substring abbrev 0 1)
- (upcase (substring abbrev 0 1)))
- (mapcar (function (lambda (string)
- (intern (capitalize string) my-obarray)))
- completion-list))
- (t
- (mapcar (function (lambda (string)
- (intern (downcase string) my-obarray)))
- completion-list)))
- (setq dabbrev--last-obarray my-obarray)
- (setq dabbrev--last-completion-buffer (current-buffer))
- ;; Find the longest common string.
- (setq init (try-completion abbrev my-obarray)))))
- ;;--------------------------------
- ;; Let the user choose between the expansions
- ;;--------------------------------
- (or (stringp init)
- (setq init abbrev))
- (cond
- ;; * Replace string fragment with matched common substring completion.
- ((and (not (string-equal init ""))
- (not (string-equal (downcase init) (downcase abbrev))))
- (if (> (length (all-completions init my-obarray)) 1)
- (message "Repeat `%s' to see all completions"
- (key-description (this-command-keys)))
- (message "The only possible completion"))
- (dabbrev--substitute-expansion nil abbrev init))
- (t
- ;; * String is a common substring completion already. Make list.
- (message "Making completion list...")
- (with-output-to-temp-buffer " *Completions*"
- (display-completion-list (all-completions init my-obarray)))
- (message "Making completion list...done")))
- (and (window-minibuffer-p (selected-window))
- (message nil))))
-
-;;;###autoload
-(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. If still no suitable word is found, then look in the
-buffers accepted by the function pointed out by variable
-`dabbrev-friend-buffer-function'.
-
-A positive prefix argument, N, says to take the Nth backward *distinct*
-possibility. A negative argument says search forward.
-
-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.
-
-The variable `dabbrev-backward-only' may be used to limit the
-direction of search to backward if set non-nil.
-
-See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]."
- (interactive "*P")
- (let (abbrev record-case-pattern
- expansion old direction (orig-point (point)))
- ;; 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)
- (save-excursion
- (if (and (null arg)
- (markerp dabbrev--last-abbrev-location)
- (marker-position dabbrev--last-abbrev-location)
- (or (eq last-command this-command)
- (and (window-minibuffer-p (selected-window))
- (= dabbrev--last-abbrev-location
- (point)))))
- ;; Find a different expansion for the same abbrev as last time.
- (progn
- (setq abbrev dabbrev--last-abbreviation)
- (setq old dabbrev--last-expansion)
- (setq direction dabbrev--last-direction))
- ;; If the user inserts a space after expanding
- ;; and then asks to expand again, always fetch the next word.
- (if (and (eq (preceding-char) ?\ )
- (markerp dabbrev--last-abbrev-location)
- (marker-position dabbrev--last-abbrev-location)
- (= (point) (1+ dabbrev--last-abbrev-location)))
- (progn
- ;; The "abbrev" to expand is just the space.
- (setq abbrev " ")
- (save-excursion
- (if dabbrev--last-buffer
- (set-buffer dabbrev--last-buffer))
- ;; Find the end of the last "expansion" word.
- (if (or (eq dabbrev--last-direction 1)
- (and (eq dabbrev--last-direction 0)
- (< dabbrev--last-expansion-location (point))))
- (setq dabbrev--last-expansion-location
- (+ dabbrev--last-expansion-location
- (length dabbrev--last-expansion))))
- (goto-char dabbrev--last-expansion-location)
- ;; Take the following word, with intermediate separators,
- ;; as our expansion this time.
- (re-search-forward
- (concat "\\(\\(" dabbrev--abbrev-char-regexp "\\)+\\)"))
- (setq expansion
- (buffer-substring dabbrev--last-expansion-location
- (point)))
- (if dabbrev--last-case-pattern
- (setq expansion (upcase expansion)))
-
- ;; Record the end of this expansion, in case we repeat this.
- (setq dabbrev--last-expansion-location (point)))
- ;; Indicate that dabbrev--last-expansion-location is
- ;; at the end of the expansion.
- (setq dabbrev--last-direction -1))
-
- ;; We have a different abbrev to expand.
- (dabbrev--reset-global-variables)
- (setq direction (if (null arg)
- (if dabbrev-backward-only 1 0)
- (prefix-numeric-value arg)))
- (setq abbrev (dabbrev--abbrev-at-point))
- (setq record-case-pattern t)
- (setq old nil)))
-
- ;;--------------------------------
- ;; Find the expansion
- ;;--------------------------------
- (or expansion
- (setq expansion
- (dabbrev--find-expansion abbrev direction
- (and (eval dabbrev-case-fold-search)
- (or (not dabbrev-upcase-means-case-search)
- (string= abbrev (downcase abbrev))))))))
- (cond
- ((not expansion)
- (dabbrev--reset-global-variables)
- (if old
- (save-excursion
- (setq buffer-undo-list (cons orig-point buffer-undo-list))
- ;; Put back the original abbrev with its original case pattern.
- (search-backward old)
- (insert abbrev)
- (delete-region (point) (+ (point) (length old)))))
- (error "No%s dynamic expansion for `%s' found"
- (if old " further" "") abbrev))
- (t
- (if (not (eq dabbrev--last-buffer dabbrev--last-buffer-found))
- (progn
- (message "Expansion found in '%s'"
- (buffer-name dabbrev--last-buffer))
- (setq dabbrev--last-buffer-found dabbrev--last-buffer))
- (message nil))
- (if (and (or (eq (current-buffer) dabbrev--last-buffer)
- (null dabbrev--last-buffer))
- (numberp dabbrev--last-expansion-location)
- (and (> dabbrev--last-expansion-location (point))))
- (setq dabbrev--last-expansion-location
- (copy-marker dabbrev--last-expansion-location)))
- ;; Success: stick it in and return.
- (setq buffer-undo-list (cons orig-point buffer-undo-list))
- (dabbrev--substitute-expansion old abbrev expansion)
-
- ;; If we are not copying successive words now,
- ;; set dabbrev--last-case-pattern.
- (and record-case-pattern
- (setq dabbrev--last-case-pattern
- (and (eval dabbrev-case-fold-search)
- (not dabbrev-upcase-means-case-search)
- (equal abbrev (upcase abbrev)))))
-
- ;; Save state for re-expand.
- (setq dabbrev--last-expansion expansion)
- (setq dabbrev--last-abbreviation abbrev)
- (setq dabbrev--last-abbrev-location (point-marker))))))
-
-;;----------------------------------------------------------------
-;; Local functions
-;;----------------------------------------------------------------
-
-;;; Checks if OTHER-BUFFER has the same major mode as current buffer.
-(defun dabbrev--same-major-mode-p (other-buffer)
- (eq major-mode
- (save-excursion
- (set-buffer other-buffer)
- major-mode)))
-
-;;; Back over all abbrev type characters and then moves forward over
-;;; all skip characters.
-(defun dabbrev--goto-start-of-abbrev ()
- ;; Move backwards over abbrev chars
- (save-match-data
- (if (not (bobp))
- (progn
- (forward-char -1)
- (while (and (looking-at dabbrev--abbrev-char-regexp)
- (not (bobp)))
- (forward-char -1))
- (or (looking-at dabbrev--abbrev-char-regexp)
- (forward-char 1))))
- (and dabbrev-abbrev-skip-leading-regexp
- (while (looking-at dabbrev-abbrev-skip-leading-regexp)
- (forward-char 1)))))
-
-;;; Extract the symbol at point to serve as abbreviation.
-(defun dabbrev--abbrev-at-point ()
- ;; Check for error
- (if (bobp)
- (error "No possible abbreviation preceding point"))
- ;; Return abbrev at point
- (save-excursion
- ;; Record the end of the abbreviation.
- (setq dabbrev--last-abbrev-location (point))
- ;; If we aren't right after an abbreviation,
- ;; move point back to just after one.
- ;; This is so the user can get successive words
- ;; by typing the punctuation followed by M-/.
- (save-match-data
- (if (save-excursion
- (forward-char -1)
- (not (looking-at (concat "\\("
- (or dabbrev-abbrev-char-regexp
- "\\sw\\|\\s_")
- "\\)+"))))
- (if (re-search-backward (or dabbrev-abbrev-char-regexp
- "\\sw\\|\\s_")
- nil t)
- (forward-char 1)
- (error "No possible abbreviation preceding point"))))
- ;; Now find the beginning of that one.
- (dabbrev--goto-start-of-abbrev)
- (buffer-substring dabbrev--last-abbrev-location
- (point))))
-
-;;; Initializes all global variables
-(defun dabbrev--reset-global-variables ()
- ;; dabbrev--last-obarray and dabbrev--last-completion-buffer
- ;; must not be reset here.
- (setq dabbrev--last-table nil
- dabbrev--last-abbreviation nil
- dabbrev--last-abbrev-location nil
- dabbrev--last-direction nil
- dabbrev--last-expansion nil
- dabbrev--last-expansion-location nil
- dabbrev--friend-buffer-list nil
- dabbrev--last-buffer nil
- dabbrev--last-buffer-found nil
- dabbrev--abbrev-char-regexp (or dabbrev-abbrev-char-regexp
- "\\sw\\|\\s_")
- dabbrev--check-other-buffers dabbrev-check-other-buffers))
-
-;;; Find all buffers that are considered "friends" according to the
-;;; function pointed out by dabbrev-friend-buffer-function.
-(defun dabbrev--select-buffers ()
- (save-excursion
- (and (window-minibuffer-p (selected-window))
- (set-buffer (dabbrev--minibuffer-origin)))
- (let ((orig-buffer (current-buffer)))
- (dabbrev-filter-elements
- buffer (buffer-list)
- (and (not (eq orig-buffer buffer))
- (boundp 'dabbrev-friend-buffer-function)
- (funcall dabbrev-friend-buffer-function buffer))))))
-
-;;; Search for ABBREV, N times, normally looking forward,
-;;; but looking in reverse instead if REVERSE is non-nil.
-(defun dabbrev--try-find (abbrev reverse n ignore-case)
- (save-excursion
- (save-restriction
- (widen)
- (let ((expansion nil))
- (and dabbrev--last-expansion-location
- (goto-char dabbrev--last-expansion-location))
- (let ((case-fold-search ignore-case)
- (count n))
- (while (and (> count 0)
- (setq expansion (dabbrev--search abbrev
- reverse
- ignore-case)))
- (setq count (1- count))))
- (and expansion
- (setq dabbrev--last-expansion-location (point)))
- expansion))))
-
-;;; Find all expansions of ABBREV
-(defun dabbrev--find-all-expansions (abbrev ignore-case)
- (let ((all-expansions nil)
- expansion)
- (save-excursion
- (goto-char (point-min))
- (while (setq expansion (dabbrev--find-expansion abbrev -1 ignore-case))
- (setq all-expansions (cons expansion all-expansions))))
- all-expansions))
-
-(defun dabbrev--scanning-message ()
- (message "Scanning `%s'" (buffer-name (current-buffer))))
-
-;;; Find one occasion of ABBREV.
-;;; DIRECTION > 0 means look that many times backwards.
-;;; DIRECTION < 0 means look that many times forward.
-;;; DIRECTION = 0 means try both backward and forward.
-;;; IGNORE-CASE non-nil means ignore case when searching.
-(defun dabbrev--find-expansion (abbrev direction ignore-case)
- (let (expansion)
- (save-excursion
- (cond
- (dabbrev--last-buffer
- (set-buffer dabbrev--last-buffer)
- (dabbrev--scanning-message))
- ((and (not dabbrev-search-these-buffers-only)
- (window-minibuffer-p (selected-window)))
- (set-buffer (dabbrev--minibuffer-origin))
- ;; In the minibuffer-origin buffer we will only search from
- ;; the top and down.
- (goto-char (point-min))
- (setq direction -1)
- (dabbrev--scanning-message)))
- (cond
- ;; ------------------------------------------
- ;; Look backwards
- ;; ------------------------------------------
- ((and (not dabbrev-search-these-buffers-only)
- (>= direction 0)
- (setq dabbrev--last-direction (min 1 direction))
- (setq expansion (dabbrev--try-find abbrev t
- (max 1 direction)
- ignore-case)))
- expansion)
- ;; ------------------------------------------
- ;; Look forward
- ;; ------------------------------------------
- ((and (or (not dabbrev-search-these-buffers-only)
- dabbrev--last-buffer)
- (<= direction 0)
- (setq dabbrev--last-direction -1)
- (setq expansion (dabbrev--try-find abbrev nil
- (max 1 (- direction))
- ignore-case)))
- expansion)
- ;; ------------------------------------------
- ;; Look in other buffers.
- ;; Start at (point-min) and look forward.
- ;; ------------------------------------------
- (t
- (setq dabbrev--last-direction -1)
- ;; Make sure that we should check other buffers
- (or dabbrev--friend-buffer-list
- dabbrev--last-buffer
- (setq dabbrev--friend-buffer-list
- (mapcar (function get-buffer)
- dabbrev-search-these-buffers-only))
- (not dabbrev--check-other-buffers)
- (not (or (eq dabbrev--check-other-buffers t)
- (progn
- (setq dabbrev--check-other-buffers
- (y-or-n-p "Scan other buffers also? ")))))
- (let* (friend-buffer-list non-friend-buffer-list)
- (setq dabbrev--friend-buffer-list
- (funcall dabbrev-select-buffers-function))
- (if dabbrev-check-all-buffers
- (setq non-friend-buffer-list
- (nreverse
- (dabbrev-filter-elements
- buffer (buffer-list)
- (not (memq buffer dabbrev--friend-buffer-list))))
- dabbrev--friend-buffer-list
- (append dabbrev--friend-buffer-list
- non-friend-buffer-list)))))
- ;; Move buffers that are visible on the screen
- ;; to the front of the list.
- (if dabbrev--friend-buffer-list
- (let ((w (next-window (selected-window))))
- (while (not (eq w (selected-window)))
- (setq dabbrev--friend-buffer-list
- (cons (window-buffer w)
- (delq (window-buffer w) dabbrev--friend-buffer-list)))
- (setq w (next-window w)))))
- ;; Walk through the buffers
- (while (and (not expansion) dabbrev--friend-buffer-list)
- (setq dabbrev--last-buffer
- (car dabbrev--friend-buffer-list))
- (setq dabbrev--friend-buffer-list
- (cdr dabbrev--friend-buffer-list))
- (set-buffer dabbrev--last-buffer)
- (dabbrev--scanning-message)
- (setq dabbrev--last-expansion-location (point-min))
- (setq expansion (dabbrev--try-find abbrev nil 1 ignore-case)))
- expansion)))))
-
-(defun dabbrev--safe-replace-match (string &optional fixedcase literal)
- (if (eq major-mode 'picture-mode)
- (picture-replace-match string fixedcase literal)
- (replace-match string fixedcase literal)))
-
-;;;----------------------------------------------------------------
-;;; Substitute the current string in buffer with the expansion
-;;; OLD is nil or the last expansion substring.
-;;; ABBREV is the abbreviation we are working with.
-;;; EXPANSION is the expansion substring.
-(defun dabbrev--substitute-expansion (old abbrev expansion)
- ;;(undo-boundary)
- (let ((use-case-replace (and (eval dabbrev-case-fold-search)
- (or (not dabbrev-upcase-means-case-search)
- (string= abbrev (downcase abbrev)))
- (eval dabbrev-case-replace))))
- (and nil use-case-replace
- (setq old (concat abbrev (or old "")))
- (setq expansion (concat abbrev expansion)))
- ;; If the given abbrev is mixed case and its case pattern
- ;; matches the start of the expansion,
- ;; copy the expansion's case
- ;; instead of downcasing all the rest.
- (if (and (string= abbrev
- (substring expansion 0 (length abbrev)))
- (not (string= abbrev (downcase abbrev)))
- (not (string= abbrev (upcase abbrev))))
- (setq use-case-replace nil))
- (if (equal abbrev " ")
- (setq use-case-replace nil))
- (if use-case-replace
- (setq expansion (downcase expansion)))
- (if old
- (save-excursion
- (search-backward old))
- ;;(store-match-data (list (point-marker) (point-marker)))
- (search-backward abbrev))
- ;; 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.
- (dabbrev--safe-replace-match expansion
- (not use-case-replace)
- t)))
-
-
-;;;----------------------------------------------------------------
-;;; Search function used by dabbrevs library.
-
-;;; ABBREV is string to find as prefix of word. Second arg, REVERSE,
-;;; is t for reverse search, nil for forward. Variable dabbrev-limit
-;;; controls the maximum search region size. Third argument IGNORE-CASE
-;;; non-nil means treat case as insignificant while looking for a match
-;;; and when comparing with previous matches. Also if that's non-nil
-;;; and the match is found at the beginning of a sentence and is in
-;;; lower case except for the initial then it is converted to all lower
-;;; case for return.
-
-;;; Table of expansions already seen is examined in buffer
-;;; `dabbrev--last-table' so that only distinct possibilities are found
-;;; by dabbrev-re-expand.
-
-;;; Value is the expansion, or nil if not found.
-
-(defun dabbrev--search (abbrev reverse ignore-case)
- (save-match-data
- (let ((pattern1 (concat (regexp-quote abbrev)
- "\\(" dabbrev--abbrev-char-regexp "\\)"))
- (pattern2 (concat (regexp-quote abbrev)
- "\\(\\(" dabbrev--abbrev-char-regexp "\\)+\\)"))
- (found-string nil))
- ;; Limited search.
- (save-restriction
- (and dabbrev-limit
- (narrow-to-region dabbrev--last-expansion-location
- (+ (point)
- (if reverse (- dabbrev-limit) dabbrev-limit))))
- ;;--------------------------------
- ;; Look for a distinct expansion, using dabbrev--last-table.
- ;;--------------------------------
- (while (and (not found-string)
- (if reverse
- (re-search-backward pattern1 nil t)
- (re-search-forward pattern1 nil t)))
- (goto-char (match-beginning 0))
- ;; In case we matched in the middle of a word,
- ;; back up to start of word and verify we still match.
- (dabbrev--goto-start-of-abbrev)
-
- (if (not (looking-at pattern1))
- nil
- ;; We have a truly valid match. Find the end.
- (re-search-forward pattern2)
- (setq found-string
- (buffer-substring (match-beginning 1) (match-end 1)))
- (and ignore-case (setq found-string (downcase found-string)))
- ;; Ignore this match if it's already in the table.
- (if (dabbrev-filter-elements
- table-string dabbrev--last-table
- (string= found-string table-string))
- (setq found-string nil)))
- ;; Prepare to continue searching.
- (if reverse
- (goto-char (match-beginning 0))
- (goto-char (match-end 0))))
- ;; If we found something, use it.
- (if found-string
- ;; Put it into `dabbrev--last-table'
- ;; and return it (either downcased, or as is).
- (let ((result
- (buffer-substring (match-beginning 0) (match-end 0))))
- (setq dabbrev--last-table
- (cons found-string dabbrev--last-table))
- (if (and ignore-case (eval dabbrev-case-replace))
- result
- result)))))))
-
-(provide 'dabbrev)
-
-;;; dabbrev.el ends here
diff --git a/lisp/delsel.el b/lisp/delsel.el
deleted file mode 100644
index b402bf4f3c5..00000000000
--- a/lisp/delsel.el
+++ /dev/null
@@ -1,119 +0,0 @@
-;;; delsel.el --- delete selection if you insert
-
-;; Copyright (C) 1992 Free Software Foundation, Inc.
-
-;; Author: Matthieu Devin <devin@lucid.com>
-;; Created: 14 Jul 92
-;; Last change 18-Feb-93, devin.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This file makes the active region be pending delete, meaning that
-;; text inserted while the region is active will replace the region contents.
-;; This is a popular behavior of personal computers text editors.
-
-;;; Code:
-
-(defvar delete-selection-mode t
- "*Non-nil means Delete Selection mode is enabled.
-In Delete Selection mode, when a region is highlighted,
-insertion commands first delete the region and then insert.")
-
-(defun delete-active-region (&optional killp)
- (if killp
- (kill-region (point) (mark))
- (delete-region (point) (mark)))
- (setq mark-active nil)
- (run-hooks 'deactivate-mark-hook)
- t)
-
-(defun delete-selection-pre-hook ()
- (if (and delete-selection-mode
- (not buffer-read-only)
- transient-mark-mode mark-active)
- (let ((type (and (symbolp this-command)
- (get this-command 'delete-selection))))
- (cond ((eq type 'kill)
- (delete-active-region t))
- ((eq type 'yank)
- ;; Before a yank command,
- ;; make sure we don't yank the same region
- ;; that we are going to delete.
- ;; That would make yank a no-op.
- (if (string= (buffer-substring (point) (mark))
- (car kill-ring))
- (current-kill 1))
- (delete-active-region nil))
- ((eq type 'supersede)
- (if (delete-active-region nil)
- (setq this-command '(lambda () (interactive)))))
- (type
- (delete-active-region nil))))))
-
-(add-hook 'pre-command-hook 'delete-selection-pre-hook)
-
-(put 'self-insert-command 'delete-selection t)
-(put 'self-insert-iso 'delete-selection t)
-
-(put 'yank 'delete-selection 'yank)
-(put 'clipboard-yank 'delete-selection 'yank)
-(put 'insert-register 'delete-selection t)
-
-(put 'delete-backward-char 'delete-selection 'supersede)
-(put 'backward-delete-char-untabify 'delete-selection 'supersede)
-(put 'delete-char 'delete-selection 'supersede)
-
-(put 'newline-and-indent 'delete-selection 't)
-(put 'newline 'delete-selection t)
-(put 'open-line 'delete-selection t)
-
-;;;###autoload
-(defalias 'pending-delete-mode 'delete-selection-mode)
-;;;###autoload
-(defun delete-selection-mode (arg)
- "Toggle Delete Selection mode.
-When ON, typed text replaces the selection if the selection is active.
-When OFF, typed text is just inserted at point."
- (interactive "P")
- (setq delete-selection-mode
- (if (null arg) (not delete-selection-mode)
- (> (prefix-numeric-value arg) 0)))
- (force-mode-line-update))
-
-;; This is very useful for cancelling a selection in the minibuffer without
-;; aborting the minibuffer.
-(defun minibuffer-keyboard-quit ()
- "Abort recursive edit.
-In Delete Selection mode mode, if the mark is active, just deactivate it;
-then it takes a second C-g to abort the minibuffer."
- (interactive)
- (if (and delete-selection-mode transient-mark-mode mark-active)
- (setq deactivate-mark t)
- (abort-recursive-edit)))
-
-(define-key minibuffer-local-map "\C-g" 'minibuffer-keyboard-quit)
-(define-key minibuffer-local-ns-map "\C-g" 'minibuffer-keyboard-quit)
-(define-key minibuffer-local-completion-map "\C-g" 'minibuffer-keyboard-quit)
-(define-key minibuffer-local-must-match-map "\C-g" 'minibuffer-keyboard-quit)
-(define-key minibuffer-local-isearch-map "\C-g" 'minibuffer-keyboard-quit)
-
-(provide 'delsel)
-
-;;; delsel.el ends here
diff --git a/lisp/derived.el b/lisp/derived.el
deleted file mode 100644
index 48824a61ec2..00000000000
--- a/lisp/derived.el
+++ /dev/null
@@ -1,352 +0,0 @@
-;;; derived.el --- allow inheritance of major modes.
-;;; (formerly mode-clone.el)
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: David Megginson (dmeggins@aix1.uottawa.ca)
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; GNU Emacs is already, in a sense, object oriented -- each object
-;; (buffer) belongs to a class (major mode), and that class defines
-;; the relationship between messages (input events) and methods
-;; (commands) by means of a keymap.
-;;
-;; The only thing missing is a good scheme of inheritance. It is
-;; possible to simulate a single level of inheritance with generous
-;; use of hooks and a bit of work -- sgml-mode, for example, also runs
-;; the hooks for text-mode, and keymaps can inherit from other keymaps
-;; -- but generally, each major mode ends up reinventing the wheel.
-;; Ideally, someone should redesign all of Emacs's major modes to
-;; follow a more conventional object-oriented system: when defining a
-;; new major mode, the user should need only to name the existing mode
-;; it is most similar to, then list the (few) differences.
-;;
-;; In the mean time, this package offers most of the advantages of
-;; full inheritance with the existing major modes. The macro
-;; `define-derived-mode' allows the user to make a variant of an existing
-;; major mode, with its own keymap. The new mode will inherit the key
-;; bindings of its parent, and will, in fact, run its parent first
-;; every time it is called. For example, the commands
-;;
-;; (define-derived-mode hypertext-mode text-mode "Hypertext"
-;; "Major mode for hypertext.\n\n\\{hypertext-mode-map}"
-;; (setq case-fold-search nil))
-;;
-;; (define-key hypertext-mode-map [down-mouse-3] 'do-hyper-link)
-;;
-;; will create a function `hypertext-mode' with its own (sparse)
-;; keymap `hypertext-mode-map.' The command M-x hypertext-mode will
-;; perform the following actions:
-;;
-;; - run the command (text-mode) to get its default setup
-;; - replace the current keymap with 'hypertext-mode-map,' which will
-;; inherit from 'text-mode-map'.
-;; - replace the current syntax table with
-;; 'hypertext-mode-syntax-table', which will borrow its defaults
-;; from the current text-mode-syntax-table.
-;; - replace the current abbrev table with
-;; 'hypertext-mode-abbrev-table', which will borrow its defaults
-;; from the current text-mode-abbrev table
-;; - change the mode line to read "Hypertext"
-;; - assign the value 'hypertext-mode' to the 'major-mode' variable
-;; - run the body of commands provided in the macro -- in this case,
-;; set the local variable `case-fold-search' to nil.
-;; - **run the command (hypertext-mode-setup), which is empty by
-;; default, but may be redefined by the user to contain special
-;; commands (ie. setting local variables like 'outline-regexp')
-;; **NOTE: do not use this option -- it will soon be obsolete.
-;; - run anything assigned to 'hypertext-mode-hooks' (obsolete, but
-;; supported for the sake of compatibility).
-;;
-;; The advantages of this system are threefold. First, text mode is
-;; untouched -- if you had added the new keystroke to `text-mode-map,'
-;; possibly using hooks, you would have added it to all text buffers
-;; -- here, it appears only in hypertext buffers, where it makes
-;; sense. Second, it is possible to build even further, and make
-;; a derived mode from a derived mode. The commands
-;;
-;; (define-derived-mode html-mode hypertext-mode "HTML")
-;; [various key definitions]
-;;
-;; will add a new major mode for HTML with very little fuss.
-;;
-;; Note also the function `derived-mode-class,' which returns the non-derived
-;; major mode which a derived mode is based on (ie. NOT necessarily the
-;; immediate parent).
-;;
-;; (derived-mode-class 'text-mode) ==> text-mode
-;; (derived-mode-class 'hypertext-mode) ==> text-mode
-;; (derived-mode-class 'html-mode) ==> text-mode
-
-;;; Code:
-
-;; PUBLIC: define a new major mode which inherits from an existing one.
-
-;;;###autoload
-(defmacro define-derived-mode (child parent name &optional docstring &rest body)
- "Create a new mode as a variant of an existing mode.
-
-The arguments to this command are as follow:
-
-CHILD: the name of the command for the derived mode.
-PARENT: the name of the command for the parent mode (ie. text-mode).
-NAME: a string which will appear in the status line (ie. \"Hypertext\")
-DOCSTRING: an optional documentation string--if you do not supply one,
- the function will attempt to invent something useful.
-BODY: forms to execute just before running the
- hooks for the new mode.
-
-Here is how you could define LaTeX-Thesis mode as a variant of LaTeX mode:
-
- (define-derived-mode LaTeX-thesis-mode LaTeX-mode \"LaTeX-Thesis\")
-
-You could then make new key bindings for `LaTeX-thesis-mode-map'
-without changing regular LaTeX mode. In this example, BODY is empty,
-and DOCSTRING is generated by default.
-
-On a more complicated level, the following command uses sgml-mode as
-the parent, and then sets the variable `case-fold-search' to nil:
-
- (define-derived-mode article-mode sgml-mode \"Article\"
- \"Major mode for editing technical articles.\"
- (setq case-fold-search nil))
-
-Note that if the documentation string had been left out, it would have
-been generated automatically, with a reference to the keymap."
-
- ; Some trickiness, since what
- ; appears to be the docstring
- ; may really be the first
- ; element of the body.
- (if (and docstring (not (stringp docstring)))
- (progn (setq body (cons docstring body))
- (setq docstring nil)))
- (setq docstring (or docstring (derived-mode-make-docstring parent child)))
-
- (` (progn
- (derived-mode-init-mode-variables (quote (, child)))
- (defun (, child) ()
- (, docstring)
- (interactive)
- ; Run the parent.
- ((, parent))
- ; Identify special modes.
- (if (get (quote (, parent)) 'special)
- (put (quote (, child)) 'special t))
- ; Identify the child mode.
- (setq major-mode (quote (, child)))
- (setq mode-name (, name))
- ; Set up maps and tables.
- (derived-mode-set-keymap (quote (, child)))
- (derived-mode-set-syntax-table (quote (, child)))
- (derived-mode-set-abbrev-table (quote (, child)))
- ; Splice in the body (if any).
- (,@ body)
-;;; ; Run the setup function, if
-;;; ; any -- this will soon be
-;;; ; obsolete.
-;;; (derived-mode-run-setup-function (quote (, child)))
- ; Run the hooks, if any.
- (derived-mode-run-hooks (quote (, child)))))))
-
-
-;; PUBLIC: find the ultimate class of a derived mode.
-
-(defun derived-mode-class (mode)
- "Find the class of a major mode.
-A mode's class is the first ancestor which is NOT a derived mode.
-Use the `derived-mode-parent' property of the symbol to trace backwards."
- (while (get mode 'derived-mode-parent)
- (setq mode (get mode 'derived-mode-parent)))
- mode)
-
-
-;; Inline functions to construct various names from a mode name.
-
-(defsubst derived-mode-setup-function-name (mode)
- "Construct a setup-function name based on a mode name."
- (intern (concat (symbol-name mode) "-setup")))
-
-(defsubst derived-mode-hooks-name (mode)
- "Construct a hooks name based on a mode name."
- (intern (concat (symbol-name mode) "-hooks")))
-
-(defsubst derived-mode-map-name (mode)
- "Construct a map name based on a mode name."
- (intern (concat (symbol-name mode) "-map")))
-
-(defsubst derived-mode-syntax-table-name (mode)
- "Construct a syntax-table name based on a mode name."
- (intern (concat (symbol-name mode) "-syntax-table")))
-
-(defsubst derived-mode-abbrev-table-name (mode)
- "Construct an abbrev-table name based on a mode name."
- (intern (concat (symbol-name mode) "-abbrev-table")))
-
-
-;; Utility functions for defining a derived mode.
-
-;;;###autoload
-(defun derived-mode-init-mode-variables (mode)
- "Initialise variables for a new mode.
-Right now, if they don't already exist, set up a blank keymap, an
-empty syntax table, and an empty abbrev table -- these will be merged
-the first time the mode is used."
-
- (if (boundp (derived-mode-map-name mode))
- t
- (eval (` (defvar (, (derived-mode-map-name mode))
- (make-sparse-keymap)
- (, (format "Keymap for %s." mode)))))
- (put (derived-mode-map-name mode) 'derived-mode-unmerged t))
-
- (if (boundp (derived-mode-syntax-table-name mode))
- t
- (eval (` (defvar (, (derived-mode-syntax-table-name mode))
- ;; Make a syntax table which doesn't specify anything
- ;; for any char. Valid data will be merged in by
- ;; derived-mode-merge-syntax-tables.
- (make-char-table 'syntax-table nil)
- (, (format "Syntax table for %s." mode)))))
- (put (derived-mode-syntax-table-name mode) 'derived-mode-unmerged t))
-
- (if (boundp (derived-mode-abbrev-table-name mode))
- t
- (eval (` (defvar (, (derived-mode-abbrev-table-name mode))
- (progn (define-abbrev-table (derived-mode-abbrev-table-name mode) nil)
- (make-abbrev-table))
- (, (format "Abbrev table for %s." mode)))))))
-
-(defun derived-mode-make-docstring (parent child)
- "Construct a docstring for a new mode if none is provided."
-
- (format "This major mode is a variant of `%s', created by `define-derived-mode'.
-It inherits all of the parent's attributes, but has its own keymap,
-abbrev table and syntax table:
-
- `%s-map' and `%s-syntax-table'
-
-which more-or-less shadow
-
- `%s-map' and `%s-syntax-table'
-
-\\{%s-map}" parent child child parent parent child))
-
-
-;; Utility functions for running a derived mode.
-
-(defun derived-mode-set-keymap (mode)
- "Set the keymap of the new mode, maybe merging with the parent."
- (let* ((map-name (derived-mode-map-name mode))
- (new-map (eval map-name))
- (old-map (current-local-map)))
- (and old-map
- (get map-name 'derived-mode-unmerged)
- (derived-mode-merge-keymaps old-map new-map))
- (put map-name 'derived-mode-unmerged nil)
- (use-local-map new-map)))
-
-(defun derived-mode-set-syntax-table (mode)
- "Set the syntax table of the new mode, maybe merging with the parent."
- (let* ((table-name (derived-mode-syntax-table-name mode))
- (old-table (syntax-table))
- (new-table (eval table-name)))
- (if (get table-name 'derived-mode-unmerged)
- (derived-mode-merge-syntax-tables old-table new-table))
- (put table-name 'derived-mode-unmerged nil)
- (set-syntax-table new-table)))
-
-(defun derived-mode-set-abbrev-table (mode)
- "Set the abbrev table if it exists.
-Always merge its parent into it, since the merge is non-destructive."
- (let* ((table-name (derived-mode-abbrev-table-name mode))
- (old-table local-abbrev-table)
- (new-table (eval table-name)))
- (derived-mode-merge-abbrev-tables old-table new-table)
- (setq local-abbrev-table new-table)))
-
-;;;(defun derived-mode-run-setup-function (mode)
-;;; "Run the setup function if it exists."
-
-;;; (let ((fname (derived-mode-setup-function-name mode)))
-;;; (if (fboundp fname)
-;;; (funcall fname))))
-
-(defun derived-mode-run-hooks (mode)
- "Run the hooks if they exist."
-
- (let ((hooks-name (derived-mode-hooks-name mode)))
- (if (boundp hooks-name)
- (run-hooks hooks-name))))
-
-;; Functions to merge maps and tables.
-
-(defun derived-mode-merge-keymaps (old new)
- "Merge an old keymap into a new one.
-The old keymap is set to be the last cdr of the new one, so that there will
-be automatic inheritance."
- (let ((tail new))
- ;; Scan the NEW map for prefix keys.
- (while (consp tail)
- (and (consp (car tail))
- (let* ((key (vector (car (car tail))))
- (subnew (lookup-key new key))
- (subold (lookup-key old key)))
- ;; If KEY is a prefix key in both OLD and NEW, merge them.
- (and (keymapp subnew) (keymapp subold)
- (derived-mode-merge-keymaps subold subnew))))
- (and (vectorp (car tail))
- ;; Search a vector of ASCII char bindings for prefix keys.
- (let ((i (1- (length (car tail)))))
- (while (>= i 0)
- (let* ((key (vector i))
- (subnew (lookup-key new key))
- (subold (lookup-key old key)))
- ;; If KEY is a prefix key in both OLD and NEW, merge them.
- (and (keymapp subnew) (keymapp subold)
- (derived-mode-merge-keymaps subold subnew)))
- (setq i (1- i)))))
- (setq tail (cdr tail))))
- (setcdr (nthcdr (1- (length new)) new) old))
-
-(defun derived-mode-merge-syntax-tables (old new)
- "Merge an old syntax table into a new one.
-Where the new table already has an entry, nothing is copied from the old one."
- (set-char-table-parent new old))
-
-;; Merge an old abbrev table into a new one.
-;; This function requires internal knowledge of how abbrev tables work,
-;; presuming that they are obarrays with the abbrev as the symbol, the expansion
-;; as the value of the symbol, and the hook as the function definition.
-(defun derived-mode-merge-abbrev-tables (old new)
- (if old
- (mapatoms
- (function
- (lambda (symbol)
- (or (intern-soft (symbol-name symbol) new)
- (define-abbrev new (symbol-name symbol)
- (symbol-value symbol) (symbol-function symbol)))))
- old)))
-
-(provide 'derived)
-
-;;; derived.el ends here
diff --git a/lisp/desktop.el b/lisp/desktop.el
deleted file mode 100644
index 1eee466697a..00000000000
--- a/lisp/desktop.el
+++ /dev/null
@@ -1,587 +0,0 @@
-;;; desktop.el --- save partial status of Emacs when killed
-
-;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Morten Welinder <terra@diku.dk>
-;; Keywords: customization
-;; Favourite-brand-of-beer: None, I hate beer.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Save the Desktop, i.e.,
-;; - some global variables
-;; - the list of buffers with associated files. For each buffer also
-;; - the major mode
-;; - the default directory
-;; - the point
-;; - the mark & mark-active
-;; - buffer-read-only
-;; - some local variables
-
-;; To use this, first put these three lines in the bottom of your .emacs
-;; file (the later the better):
-;;
-;; (load "desktop")
-;; (desktop-load-default)
-;; (desktop-read)
-;;
-;; Between the second and the third line you may wish to add something that
-;; updates the variables `desktop-globals-to-save' and/or
-;; `desktop-locals-to-save'. If for instance you want to save the local
-;; variable `foobar' for every buffer in which it is local, you could add
-;; the line
-;;
-;; (setq desktop-locals-to-save (cons 'foobar desktop-locals-to-save))
-;;
-;; To avoid saving excessive amounts of data you may also wish to add
-;; something like the following
-;;
-;; (add-hook 'kill-emacs-hook
-;; '(lambda ()
-;; (desktop-truncate search-ring 3)
-;; (desktop-truncate regexp-search-ring 3)))
-;;
-;; which will make sure that no more than three search items are saved. You
-;; must place this line *after* the (load "desktop") line. See also the
-;; variable desktop-save-hook.
-
-;; Start Emacs in the root directory of your "project". The desktop saver
-;; is inactive by default. You activate it by M-x desktop-save RET. When
-;; you exit the next time the above data will be saved. This ensures that
-;; all the files you were editing will be reloaded the next time you start
-;; Emacs from the same directory and that points will be set where you
-;; left them. If you save a desktop file in your home directory it will
-;; act as a default desktop when you start Emacs from a directory that
-;; doesn't have its own. I never do this, but you may want to.
-
-;; By the way: don't use desktop.el to customize Emacs -- the file .emacs
-;; in your home directory is used for that. Saving global default values
-;; for buffers is an example of misuse.
-
-;; PLEASE NOTE: The kill ring can be saved as specified by the variable
-;; `desktop-globals-to-save' (by default it isn't). This may result in saving
-;; things you did not mean to keep. Use M-x desktop-clear RET.
-
-;; Thanks to hetrick@phys.uva.nl (Jim Hetrick) for useful ideas.
-;; avk@rtsg.mot.com (Andrew V. Klein) for a dired tip.
-;; chris@tecc.co.uk (Chris Boucher) for a mark tip.
-;; f89-kam@nada.kth.se (Klas Mellbourn) for a mh-e tip.
-;; kifer@sbkifer.cs.sunysb.edu (M. Kifer) for a bug hunt.
-;; treese@lcs.mit.edu (Win Treese) for ange-ftp tips.
-;; pot@cnuce.cnr.it (Francesco Potorti`) for misc. tips.
-;; ---------------------------------------------------------------------------
-;; TODO:
-;;
-;; Save window configuration.
-;; Recognize more minor modes.
-;; Save mark rings.
-;; Start-up with buffer-menu???
-
-;;; Code:
-
-;; Make the compilation more silent
-(eval-when-compile
- ;; We use functions from these modules
- ;; We can't (require 'mh-e) since that wants to load something.
- (mapcar 'require '(info dired reporter)))
-;; ----------------------------------------------------------------------------
-;; USER OPTIONS -- settings you might want to play with.
-;; ----------------------------------------------------------------------------
-(defconst desktop-basefilename
- (convert-standard-filename ".emacs.desktop")
- "File for Emacs desktop, not including the directory name.")
-
-(defvar desktop-missing-file-warning t
- "*If non-nil then desktop warns when a file no longer exists.
-Otherwise it simply ignores that file.")
-
-(defvar desktop-globals-to-save
- (list 'desktop-missing-file-warning
- ;; Feature: saving kill-ring implies saving kill-ring-yank-pointer
- ;; 'kill-ring
- 'tags-file-name
- 'tags-table-list
- 'search-ring
- 'regexp-search-ring
- 'register-alist
- ;; 'desktop-globals-to-save ; Itself!
- )
- "List of global variables to save when killing Emacs.
-An element may be variable name (a symbol)
-or a cons cell of the form (VAR . MAX-SIZE),
-which means to truncate VAR's value to at most MAX-SIZE elements
-\(if the value is a list) before saving the value.")
-
-(defvar desktop-locals-to-save
- (list 'desktop-locals-to-save ; Itself! Think it over.
- 'truncate-lines
- 'case-fold-search
- 'case-replace
- 'fill-column
- 'overwrite-mode
- 'change-log-default-name
- 'line-number-mode
- )
- "List of local variables to save for each buffer.
-The variables are saved only when they really are local.")
-(make-variable-buffer-local 'desktop-locals-to-save)
-
-;; We skip .log files because they are normally temporary.
-;; (ftp) files because they require passwords and whatnot.
-;; TAGS files to save time (tags-file-name is saved instead).
-(defvar desktop-buffers-not-to-save
- "\\(^nn\\.a[0-9]+\\|\\.log\\|(ftp)\\|^tags\\|^TAGS\\)$"
- "Regexp identifying buffers that are to be excluded from saving.")
-
-;; Skip ange-ftp files
-(defvar desktop-files-not-to-save
- "^/[^/:]*:"
- "Regexp identifying files whose buffers are to be excluded from saving.")
-
-(defvar desktop-buffer-major-mode nil
- "When desktop creates a buffer, this holds the desired Major mode.")
-
-(defvar desktop-buffer-file-name nil
- "When desktop creates a buffer, this holds the file name to visit.")
-
-(defvar desktop-buffer-name nil
- "When desktop creates a buffer, this holds the desired buffer name.")
-
-(defvar desktop-buffer-misc nil
- "When desktop creates a buffer, this holds a list of misc info.
-It is used by the `desktop-buffer-handlers' functions.")
-
-(defvar desktop-buffer-handlers
- '(desktop-buffer-dired
- desktop-buffer-rmail
- desktop-buffer-mh
- desktop-buffer-info
- desktop-buffer-file)
- "*List of functions to call in order to create a buffer.
-The functions are called without explicit parameters but can use the
-variables `desktop-buffer-major-mode', `desktop-buffer-file-name',
-`desktop-buffer-name'.
-If one function returns non-nil, no further functions are called.
-If the function returns t then the buffer is considered created.")
-
-(defvar desktop-create-buffer-form "(desktop-create-buffer 205"
- "Opening of form for creation of new buffers.")
-
-(defvar desktop-save-hook nil
- "Hook run before saving the desktop to allow you to cut history lists and
-the like shorter.")
-;; ----------------------------------------------------------------------------
-(defvar desktop-dirname nil
- "The directory in which the current desktop file resides.")
-
-(defconst desktop-header
-";; --------------------------------------------------------------------------
-;; Desktop File for Emacs
-;; --------------------------------------------------------------------------
-" "*Header to place in Desktop file.")
-
-(defvar desktop-delay-hook nil
- "Hooks run after all buffers are loaded; intended for internal use.")
-;; ----------------------------------------------------------------------------
-(defun desktop-truncate (l n)
- "Truncate LIST to at most N elements destructively."
- (let ((here (nthcdr (1- n) l)))
- (if (consp here)
- (setcdr here nil))))
-;; ----------------------------------------------------------------------------
-(defun desktop-clear () "Empty the Desktop."
- (interactive)
- (setq kill-ring nil
- kill-ring-yank-pointer nil
- search-ring nil
- search-ring-yank-pointer nil
- regexp-search-ring nil
- regexp-search-ring-yank-pointer nil)
- (mapcar (function kill-buffer) (buffer-list))
- (delete-other-windows))
-;; ----------------------------------------------------------------------------
-(add-hook 'kill-emacs-hook 'desktop-kill)
-
-(defun desktop-kill ()
- (if desktop-dirname
- (condition-case err
- (desktop-save desktop-dirname)
- (file-error
- (if (yes-or-no-p "Error while saving the desktop. Quit anyway? ")
- nil
- (signal (car err) (cdr err)))))))
-;; ----------------------------------------------------------------------------
-(defun desktop-list* (&rest args)
- (if (null (cdr args))
- (car args)
- (setq args (nreverse args))
- (let ((value (cons (nth 1 args) (car args))))
- (setq args (cdr (cdr args)))
- (while args
- (setq value (cons (car args) value))
- (setq args (cdr args)))
- value)))
-
-(defun desktop-internal-v2s (val)
- "Convert VALUE to a pair (QUOTE . TXT); (eval (read TXT)) gives VALUE.
-TXT is a string that when read and evaluated yields value.
-QUOTE may be `may' (value may be quoted),
-`must' (values must be quoted), or nil (value may not be quoted)."
- (cond
- ((or (numberp val) (null val) (eq t val))
- (cons 'may (prin1-to-string val)))
- ((stringp val)
- (let ((copy (copy-sequence val)))
- (set-text-properties 0 (length copy) nil copy)
- ;; Get rid of text properties because we cannot read them
- (cons 'may (prin1-to-string copy))))
- ((symbolp val)
- (cons 'must (prin1-to-string val)))
- ((vectorp val)
- (let* ((special nil)
- (pass1 (mapcar
- (lambda (el)
- (let ((res (desktop-internal-v2s el)))
- (if (null (car res))
- (setq special t))
- res))
- val)))
- (if special
- (cons nil (concat "(vector "
- (mapconcat (lambda (el)
- (if (eq (car el) 'must)
- (concat "'" (cdr el))
- (cdr el)))
- pass1
- " ")
- ")"))
- (cons 'may (concat "[" (mapconcat 'cdr pass1 " ") "]")))))
- ((consp val)
- (let ((p val)
- newlist
- use-list*
- anynil)
- (while (consp p)
- (let ((q.txt (desktop-internal-v2s (car p))))
- (or anynil (setq anynil (null (car q.txt))))
- (setq newlist (cons q.txt newlist)))
- (setq p (cdr p)))
- (if p
- (let ((last (desktop-internal-v2s p))
- (el (car newlist)))
- (or anynil (setq anynil (null (car last))))
- (or anynil
- (setq newlist (cons '(must . ".") newlist)))
- (setq use-list* t)
- (setq newlist (cons last newlist))))
- (setq newlist (nreverse newlist))
- (if anynil
- (cons nil
- (concat (if use-list* "(desktop-list* " "(list ")
- (mapconcat (lambda (el)
- (if (eq (car el) 'must)
- (concat "'" (cdr el))
- (cdr el)))
- newlist
- " ")
- ")"))
- (cons 'must
- (concat "(" (mapconcat 'cdr newlist " ") ")")))))
- ((subrp val)
- (cons nil (concat "(symbol-function '"
- (substring (prin1-to-string val) 7 -1)
- ")")))
- ((markerp val)
- (let ((pos (prin1-to-string (marker-position val)))
- (buf (prin1-to-string (buffer-name (marker-buffer val)))))
- (cons nil (concat "(let ((mk (make-marker)))"
- " (add-hook 'desktop-delay-hook"
- " (list 'lambda '() (list 'set-marker mk "
- pos " (get-buffer " buf ")))) mk)"))))
- (t ; save as text
- (cons 'may "\"Unprintable entity\""))))
-
-(defun desktop-value-to-string (val)
- "Convert VALUE to a string that when read evaluates to the same value.
-Not all types of values are supported."
- (let* ((print-escape-newlines t)
- (float-output-format nil)
- (quote.txt (desktop-internal-v2s val))
- (quote (car quote.txt))
- (txt (cdr quote.txt)))
- (if (eq quote 'must)
- (concat "'" txt)
- txt)))
-;; ----------------------------------------------------------------------------
-(defun desktop-outvar (varspec)
- "Output a setq statement for variable VAR to the desktop file.
-The argument VARSPEC may be the variable name VAR (a symbol),
-or a cons cell of the form (VAR . MAX-SIZE),
-which means to truncate VAR's value to at most MAX-SIZE elements
-\(if the value is a list) before saving the value."
- (let (var size)
- (if (consp varspec)
- (setq var (car varspec) size (cdr varspec))
- (setq var varspec))
- (if (boundp var)
- (progn
- (if (and (integerp size)
- (> size 0)
- (listp (eval var)))
- (desktop-truncate (eval var) size))
- (insert "(setq "
- (symbol-name var)
- " "
- (desktop-value-to-string (symbol-value var))
- ")\n")))))
-;; ----------------------------------------------------------------------------
-(defun desktop-save-buffer-p (filename bufname mode &rest dummy)
- "Return t if the desktop should record a particular buffer for next startup.
-FILENAME is the visited file name, BUFNAME is the buffer name, and
-MODE is the major mode."
- (let ((case-fold-search nil))
- (or (and filename
- (not (string-match desktop-buffers-not-to-save bufname))
- (not (string-match desktop-files-not-to-save filename)))
- (and (eq mode 'dired-mode)
- (save-excursion
- (set-buffer (get-buffer bufname))
- (not (string-match desktop-files-not-to-save
- default-directory))))
- (and (null filename)
- (memq mode '(Info-mode rmail-mode))))))
-;; ----------------------------------------------------------------------------
-(defun desktop-save (dirname)
- "Save the Desktop file. Parameter DIRNAME specifies where to save desktop."
- (interactive "DDirectory to save desktop file in: ")
- (run-hooks 'desktop-save-hook)
- (save-excursion
- (let ((filename (expand-file-name
- (concat dirname desktop-basefilename)))
- (info (nreverse
- (mapcar
- (function (lambda (b)
- (set-buffer b)
- (list
- (buffer-file-name)
- (buffer-name)
- major-mode
- (list ; list explaining minor modes
- (not (null auto-fill-function)))
- (point)
- (list (mark t) mark-active)
- buffer-read-only
- (cond ((eq major-mode 'Info-mode)
- (list Info-current-file
- Info-current-node))
- ((eq major-mode 'dired-mode)
- (cons
- (expand-file-name dired-directory)
- (cdr
- (nreverse
- (mapcar
- (function car)
- dired-subdir-alist))))))
- (let ((locals desktop-locals-to-save)
- (loclist (buffer-local-variables))
- (ll))
- (while locals
- (let ((here (assq (car locals) loclist)))
- (if here
- (setq ll (cons here ll))
- (if (member (car locals) loclist)
- (setq ll (cons (car locals) ll)))))
- (setq locals (cdr locals)))
- ll)
- )))
- (buffer-list))))
- (buf (get-buffer-create "*desktop*")))
- (set-buffer buf)
- (erase-buffer)
-
- (insert desktop-header
- ";; Created " (current-time-string) "\n"
- ";; Emacs version " emacs-version "\n\n"
- ";; Global section:\n")
- (mapcar (function desktop-outvar) desktop-globals-to-save)
- (if (memq 'kill-ring desktop-globals-to-save)
- (insert "(setq kill-ring-yank-pointer (nthcdr "
- (int-to-string
- (- (length kill-ring) (length kill-ring-yank-pointer)))
- " kill-ring))\n"))
-
- (insert "\n;; Buffer section:\n")
- (mapcar
- (function (lambda (l)
- (if (apply 'desktop-save-buffer-p l)
- (progn
- (insert desktop-create-buffer-form)
- (mapcar
- (function (lambda (e)
- (insert "\n "
- (desktop-value-to-string e))))
- l)
- (insert ")\n\n")))))
- info)
- (setq default-directory dirname)
- (if (file-exists-p filename) (delete-file filename))
- (write-region (point-min) (point-max) filename nil 'nomessage)))
- (setq desktop-dirname dirname))
-;; ----------------------------------------------------------------------------
-(defun desktop-remove ()
- "Delete the Desktop file and inactivate the desktop system."
- (interactive)
- (if desktop-dirname
- (let ((filename (concat desktop-dirname desktop-basefilename)))
- (setq desktop-dirname nil)
- (if (file-exists-p filename)
- (delete-file filename)))))
-;; ----------------------------------------------------------------------------
-(defun desktop-read ()
- "Read the Desktop file and the files it specifies.
-This is a no-op when Emacs is running in batch mode."
- (interactive)
- (if noninteractive
- nil
- (let ((dirs '("./" "~/")))
- (while (and dirs
- (not (file-exists-p (expand-file-name
- desktop-basefilename
- (car dirs)))))
- (setq dirs (cdr dirs)))
- (setq desktop-dirname (and dirs (expand-file-name (car dirs))))
- (if desktop-dirname
- (progn
- (load (expand-file-name desktop-basefilename desktop-dirname)
- t t t)
- (run-hooks 'desktop-delay-hook)
- (setq desktop-delay-hook nil)
- (message "Desktop loaded."))
- (desktop-clear)))))
-;; ----------------------------------------------------------------------------
-(defun desktop-load-default ()
- "Load the `default' start-up library manually.
-Also inhibit further loading of it. Call this from your `.emacs' file
-to provide correct modes for autoloaded files."
- (if (not inhibit-default-init) ; safety check
- (progn
- (load "default" t t)
- (setq inhibit-default-init t))))
-;; ----------------------------------------------------------------------------
-;; Note: the following functions use the dynamic variable binding in Lisp.
-;;
-(defun desktop-buffer-info () "Load an info file."
- (if (eq 'Info-mode desktop-buffer-major-mode)
- (progn
- (require 'info)
- (Info-find-node (nth 0 desktop-buffer-misc) (nth 1 desktop-buffer-misc))
- t)))
-;; ----------------------------------------------------------------------------
-(defun desktop-buffer-rmail () "Load an RMAIL file."
- (if (eq 'rmail-mode desktop-buffer-major-mode)
- (condition-case error
- (progn (rmail-input desktop-buffer-file-name) t)
- (file-locked
- (kill-buffer (current-buffer))
- 'ignored))))
-;; ----------------------------------------------------------------------------
-(defun desktop-buffer-mh () "Load a folder in the mh system."
- (if (eq 'mh-folder-mode desktop-buffer-major-mode)
- (progn
- (require 'mh-e)
- (mh-find-path)
- (mh-visit-folder desktop-buffer-name)
- t)))
-;; ----------------------------------------------------------------------------
-(defun desktop-buffer-dired () "Load a directory using dired."
- (if (eq 'dired-mode desktop-buffer-major-mode)
- (if (file-directory-p (file-name-directory (car desktop-buffer-misc)))
- (progn
- (dired (car desktop-buffer-misc))
- (mapcar 'dired-insert-subdir (cdr desktop-buffer-misc))
- t)
- (message "Directory %s no longer exists." (car desktop-buffer-misc))
- (sit-for 1)
- 'ignored)))
-;; ----------------------------------------------------------------------------
-(defun desktop-buffer-file () "Load a file."
- (if desktop-buffer-file-name
- (if (or (file-exists-p desktop-buffer-file-name)
- (and desktop-missing-file-warning
- (y-or-n-p (format
- "File \"%s\" no longer exists. Re-create? "
- desktop-buffer-file-name))))
- (progn (find-file desktop-buffer-file-name) t)
- 'ignored)))
-;; ----------------------------------------------------------------------------
-;; Create a buffer, load its file, set is mode, ...; called from Desktop file
-;; only.
-(defun desktop-create-buffer (ver desktop-buffer-file-name desktop-buffer-name
- desktop-buffer-major-mode
- mim pt mk ro desktop-buffer-misc &optional locals)
- (let ((hlist desktop-buffer-handlers)
- (result)
- (handler))
- (while (and (not result) hlist)
- (setq handler (car hlist))
- (setq result (funcall handler))
- (setq hlist (cdr hlist)))
- (if (eq result t)
- (progn
- (if (not (equal (buffer-name) desktop-buffer-name))
- (rename-buffer desktop-buffer-name))
- (auto-fill-mode (if (nth 0 mim) 1 0))
- (goto-char pt)
- (if (consp mk)
- (progn
- (set-mark (car mk))
- (setq mark-active (car (cdr mk))))
- (set-mark mk))
- ;; Never override file system if the file really is read-only marked.
- (if ro (setq buffer-read-only ro))
- (while locals
- (let ((this (car locals)))
- (if (consp this)
- ;; an entry of this form `(symbol . value)'
- (progn
- (make-local-variable (car this))
- (set (car this) (cdr this)))
- ;; an entry of the form `symbol'
- (make-local-variable this)
- (makunbound this)))
- (setq locals (cdr locals)))
- ))))
-
-;; Backward compatibility -- update parameters to 205 standards.
-(defun desktop-buffer (desktop-buffer-file-name desktop-buffer-name
- desktop-buffer-major-mode
- mim pt mk ro tl fc cfs cr desktop-buffer-misc)
- (desktop-create-buffer 205 desktop-buffer-file-name desktop-buffer-name
- desktop-buffer-major-mode (cdr mim) pt mk ro
- desktop-buffer-misc
- (list (cons 'truncate-lines tl)
- (cons 'fill-column fc)
- (cons 'case-fold-search cfs)
- (cons 'case-replace cr)
- (cons 'overwrite-mode (car mim)))))
-;; ----------------------------------------------------------------------------
-(provide 'desktop)
-
-;; desktop.el ends here.
diff --git a/lisp/diff.el b/lisp/diff.el
deleted file mode 100644
index 2ec0a8b14bd..00000000000
--- a/lisp/diff.el
+++ /dev/null
@@ -1,303 +0,0 @@
-;;; diff.el --- Run `diff' in compilation-mode.
-
-;; Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
-
-;; Keywords: unix, tools
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package helps you explore differences between files, using the
-;; UNIX command diff(1). The commands are `diff' and `diff-backup'.
-;; You can specify options with `diff-switches'.
-
-;;; Code:
-
-(require 'compile)
-
-;;; This is duplicated in vc.el.
-(defvar diff-switches "-c"
- "*A string or list of strings specifying switches to be be passed to diff.")
-
-(defvar diff-command "diff"
- "*The command to use to run diff.")
-
-(defvar diff-regexp-alist
- '(
- ;; -u format: @@ -OLDSTART,OLDEND +NEWSTART,NEWEND @@
- ("^@@ -\\([0-9]+\\),[0-9]+ \\+\\([0-9]+\\),[0-9]+ @@$" 1 2)
-
- ;; -c format: *** OLDSTART,OLDEND ****
- ("^\\*\\*\\* \\([0-9]+\\),[0-9]+ \\*\\*\\*\\*$" 1 nil)
- ;; --- NEWSTART,NEWEND ----
- ("^--- \\([0-9]+\\),[0-9]+ ----$" nil 1)
-
- ;; plain diff format: OLDSTART[,OLDEND]{a,d,c}NEWSTART[,NEWEND]
- ("^\\([0-9]+\\)\\(,[0-9]+\\)?[adc]\\([0-9]+\\)\\(,[0-9]+\\)?$" 1 3)
-
- ;; -e (ed) format: OLDSTART[,OLDEND]{a,d,c}
- ("^\\([0-9]+\\)\\(,[0-9]+\\)?[adc]$" 1)
-
- ;; -f format: {a,d,c}OLDSTART[ OLDEND]
- ;; -n format: {a,d,c}OLDSTART LINES-CHANGED
- ("^[adc]\\([0-9]+\\)\\( [0-9]+\\)?$" 1)
- )
- "Alist (REGEXP OLD-IDX NEW-IDX) of regular expressions to match difference
-sections in \\[diff] output. If REGEXP matches, the OLD-IDX'th
-subexpression gives the line number in the old file, and NEW-IDX'th
-subexpression gives the line number in the new file. If OLD-IDX or NEW-IDX
-is nil, REGEXP matches only half a section.")
-
-(defvar diff-old-file nil
- "This is the old file name in the comparison in this buffer.")
-(defvar diff-new-file nil
- "This is the new file name in the comparison in this buffer.")
-(defvar diff-old-temp-file nil
- "This is the name of a temp file to be deleted after diff finishes.")
-(defvar diff-new-temp-file nil
- "This is the name of a temp file to be deleted after diff finishes.")
-
-;; See compilation-parse-errors-function (compile.el).
-(defun diff-parse-differences (limit-search find-at-least)
- (setq compilation-error-list nil)
- (message "Parsing differences...")
-
- ;; Don't reparse diffs already seen at last parse.
- (if compilation-parsing-end (goto-char compilation-parsing-end))
-
- ;; Construct in REGEXP a regexp composed of all those in dired-regexp-alist.
- (let ((regexp (mapconcat (lambda (elt)
- (concat "\\(" (car elt) "\\)"))
- diff-regexp-alist
- "\\|"))
- ;; (GROUP-IDX OLD-IDX NEW-IDX)
- (groups (let ((subexpr 1))
- (mapcar (lambda (elt)
- (prog1
- (cons subexpr
- (mapcar (lambda (n)
- (and n
- (+ subexpr n)))
- (cdr elt)))
- (setq subexpr (+ subexpr 1
- (count-regexp-groupings
- (car elt))))))
- diff-regexp-alist)))
-
- (new-error
- (function (lambda (file subexpr)
- (setq compilation-error-list
- (cons
- (cons (save-excursion
- ;; Report location of message
- ;; at beginning of line.
- (goto-char
- (match-beginning subexpr))
- (beginning-of-line)
- (point-marker))
- ;; Report location of corresponding text.
- (let ((line (string-to-int
- (buffer-substring
- (match-beginning subexpr)
- (match-end subexpr)))))
- (save-excursion
- (save-match-data
- (set-buffer (find-file-noselect file)))
- (save-excursion
- (goto-line line)
- (point-marker)))))
- compilation-error-list)))))
-
- (found-desired nil)
- (num-loci-found 0)
- g)
-
- (while (and (not found-desired)
- ;; We don't just pass LIMIT-SEARCH to re-search-forward
- ;; because we want to find matches containing LIMIT-SEARCH
- ;; but which extend past it.
- (re-search-forward regexp nil t))
-
- ;; Find which individual regexp matched.
- (setq g groups)
- (while (and g (null (match-beginning (car (car g)))))
- (setq g (cdr g)))
- (setq g (car g))
-
- (if (nth 1 g) ;OLD-IDX
- (funcall new-error diff-old-file (nth 1 g)))
- (if (nth 2 g) ;NEW-IDX
- (funcall new-error diff-new-file (nth 2 g)))
-
- (setq num-loci-found (1+ num-loci-found))
- (if (or (and find-at-least
- (>= num-loci-found find-at-least))
- (and limit-search (>= (point) limit-search)))
- ;; We have found as many new loci as the user wants,
- ;; or the user wanted a specific diff, and we're past it.
- (setq found-desired t)))
- (if found-desired
- (setq compilation-parsing-end (point))
- ;; Set to point-max, not point, so we don't perpetually
- ;; parse the last bit of text when it isn't a diff header.
- (setq compilation-parsing-end (point-max)))
- (message "Parsing differences...done"))
- (setq compilation-error-list (nreverse compilation-error-list)))
-
-;;;###autoload
-(defun diff (old new &optional switches)
- "Find and display the differences between OLD and NEW files.
-Interactively the current buffer's file name is the default for NEW
-and a backup file for NEW is the default for OLD.
-With prefix arg, prompt for diff switches."
- (interactive
- (nconc
- (let (oldf newf)
- (nreverse
- (list
- (setq newf (buffer-file-name)
- newf (if (and newf (file-exists-p newf))
- (read-file-name
- (concat "Diff new file: ("
- (file-name-nondirectory newf) ") ")
- nil newf t)
- (read-file-name "Diff new file: " nil nil t)))
- (setq oldf (file-newest-backup newf)
- oldf (if (and oldf (file-exists-p oldf))
- (read-file-name
- (concat "Diff original file: ("
- (file-name-nondirectory oldf) ") ")
- (file-name-directory oldf) oldf t)
- (read-file-name "Diff original file: "
- (file-name-directory newf) nil t))))))
- (if current-prefix-arg
- (list (read-string "Diff switches: "
- (if (stringp diff-switches)
- diff-switches
- (mapconcat 'identity diff-switches " "))))
- nil)))
- (setq new (expand-file-name new)
- old (expand-file-name old))
- (let ((old-alt (file-local-copy old))
- (new-alt (file-local-copy new))
- buf)
- (save-excursion
- (let ((command
- (mapconcat 'identity
- (append (list diff-command)
- ;; Use explicitly specified switches
- (if switches
- (if (consp switches)
- switches (list switches))
- ;; If not specified, use default.
- (if (consp diff-switches)
- diff-switches
- (list diff-switches)))
- (if (or old-alt new-alt)
- (list "-L" old "-L" new))
- (list
- (shell-quote-argument (or old-alt old)))
- (list
- (shell-quote-argument (or new-alt new))))
- " ")))
- (setq buf
- (compile-internal command
- "No more differences" "Diff"
- 'diff-parse-differences))
- (set-buffer buf)
- ;; Avoid frightening people with "abnormally terminated"
- ;; if diff finds differences.
- (set (make-local-variable 'compilation-exit-message-function)
- (lambda (status code msg)
- (cond ((not (eq status 'exit))
- (cons msg code))
- ((zerop code)
- '("finished (no differences)\n" . "no differences"))
- ((= code 1)
- '("finished\n" . "differences found"))
- (t
- (cons msg code)))))
- (set (make-local-variable 'diff-old-file) old)
- (set (make-local-variable 'diff-new-file) new)
- (set (make-local-variable 'diff-old-temp-file) old-alt)
- (set (make-local-variable 'diff-new-temp-file) new-alt)
- (set (make-local-variable 'compilation-finish-function)
- (function (lambda (buff msg)
- (if diff-old-temp-file
- (delete-file diff-old-temp-file))
- (if diff-new-temp-file
- (delete-file diff-new-temp-file)))))
- buf))))
-
-;;;###autoload
-(defun diff-backup (file &optional switches)
- "Diff this file with its backup file or vice versa.
-Uses the latest backup, if there are several numerical backups.
-If this file is a backup, diff it with its original.
-The backup file is the first file given to `diff'."
- (interactive (list (read-file-name "Diff (file with backup): ")
- (if current-prefix-arg
- (read-string "Diff switches: "
- (if (stringp diff-switches)
- diff-switches
- (mapconcat 'identity
- diff-switches " ")))
- nil)))
- (let (bak ori)
- (if (backup-file-name-p file)
- (setq bak file
- ori (file-name-sans-versions file))
- (setq bak (or (diff-latest-backup-file file)
- (error "No backup found for %s" file))
- ori file))
- (diff bak ori switches)))
-
-(defun diff-latest-backup-file (fn) ; actually belongs into files.el
- "Return the latest existing backup of FILE, or nil."
- (let ((handler (find-file-name-handler fn 'diff-latest-backup-file)))
- (if handler
- (funcall handler 'diff-latest-backup-file fn)
- ;; First try simple backup, then the highest numbered of the
- ;; numbered backups.
- ;; Ignore the value of version-control because we look for existing
- ;; backups, which maybe were made earlier or by another user with
- ;; a different value of version-control.
- (setq fn (file-chase-links (expand-file-name fn)))
- (or
- (let ((bak (make-backup-file-name fn)))
- (if (file-exists-p bak) bak))
- ;; We use BACKUPNAME to cope with backups stored in a different dir.
- (let* ((backupname (car (find-backup-file-name fn)))
- (dir (file-name-directory backupname))
- (base-versions (concat (file-name-sans-versions
- (file-name-nondirectory backupname))
- ".~"))
- (bv-length (length base-versions)))
- (concat dir
- (car (sort
- (file-name-all-completions base-versions dir)
- ;; bv-length is a fluid var for backup-extract-version:
- (function
- (lambda (fn1 fn2)
- (> (backup-extract-version fn1)
- (backup-extract-version fn2))))))))))))
-
-(provide 'diff)
-
-;;; diff.el ends here
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
deleted file mode 100644
index 86b897d6616..00000000000
--- a/lisp/dired-aux.el
+++ /dev/null
@@ -1,1894 +0,0 @@
-;;; dired-aux.el --- less commonly used parts of dired -*-byte-compile-dynamic: t;-*-
-
-;; Copyright (C) 1985, 1986, 1992, 1994 Free Software Foundation, Inc.
-
-;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The parts of dired mode not normally used. This is a space-saving hack
-;; to avoid having to load a large mode when all that's wanted are a few
-;; functions.
-
-;; Rewritten in 1990/1991 to add tree features, file marking and
-;; sorting by Sebastian Kremer <sk@thp.uni-koeln.de>.
-;; Finished up by rms in 1992.
-
-;;; Code:
-
-;; We need macros in dired.el to compile properly.
-(eval-when-compile (require 'dired))
-
-;;; 15K
-;;;###begin dired-cmd.el
-;; Diffing and compressing
-
-;;;###autoload
-(defun dired-diff (file &optional switches)
- "Compare file at point with file FILE using `diff'.
-FILE defaults to the file at the mark.
-The prompted-for file is the first file given to `diff'.
-With prefix arg, prompt for second argument SWITCHES,
- which is options for `diff'."
- (interactive
- (let ((default (if (mark t)
- (save-excursion (goto-char (mark t))
- (dired-get-filename t t)))))
- (require 'diff)
- (list (read-file-name (format "Diff %s with: %s"
- (dired-get-filename t)
- (if default
- (concat "(default " default ") ")
- ""))
- (dired-current-directory) default t)
- (if current-prefix-arg
- (read-string "Options for diff: "
- (if (stringp diff-switches)
- diff-switches
- (mapconcat 'identity diff-switches " ")))))))
- (diff file (dired-get-filename t) switches))
-
-;;;###autoload
-(defun dired-backup-diff (&optional switches)
- "Diff this file with its backup file or vice versa.
-Uses the latest backup, if there are several numerical backups.
-If this file is a backup, diff it with its original.
-The backup file is the first file given to `diff'.
-With prefix arg, prompt for argument SWITCHES which is options for `diff'."
- (interactive
- (if current-prefix-arg
- (list (read-string "Options for diff: "
- (if (stringp diff-switches)
- diff-switches
- (mapconcat 'identity diff-switches " "))))
- nil))
- (diff-backup (dired-get-filename) switches))
-
-(defun dired-do-chxxx (attribute-name program op-symbol arg)
- ;; Change file attributes (mode, group, owner) of marked files and
- ;; refresh their file lines.
- ;; ATTRIBUTE-NAME is a string describing the attribute to the user.
- ;; PROGRAM is the program used to change the attribute.
- ;; OP-SYMBOL is the type of operation (for use in dired-mark-pop-up).
- ;; ARG describes which files to use, as in dired-get-marked-files.
- (let* ((files (dired-get-marked-files t arg))
- (new-attribute
- (dired-mark-read-string
- (concat "Change " attribute-name " of %s to: ")
- nil op-symbol arg files))
- (operation (concat program " " new-attribute))
- failures)
- (setq failures
- (dired-bunch-files 10000
- (function dired-check-process)
- (append
- (list operation program new-attribute)
- (if (string-match "gnu" system-configuration)
- '("--") nil))
- files))
- (dired-do-redisplay arg);; moves point if ARG is an integer
- (if failures
- (dired-log-summary
- (format "%s: error" operation)
- nil))))
-
-;;;###autoload
-(defun dired-do-chmod (&optional arg)
- "Change the mode of the marked (or next ARG) files.
-This calls chmod, thus symbolic modes like `g+w' are allowed."
- (interactive "P")
- (dired-do-chxxx "Mode" dired-chmod-program 'chmod arg))
-
-;;;###autoload
-(defun dired-do-chgrp (&optional arg)
- "Change the group of the marked (or next ARG) files."
- (interactive "P")
- (if (memq system-type '(ms-dos windows-nt))
- (error "chgrp not supported on this system."))
- (dired-do-chxxx "Group" "chgrp" 'chgrp arg))
-
-;;;###autoload
-(defun dired-do-chown (&optional arg)
- "Change the owner of the marked (or next ARG) files."
- (interactive "P")
- (if (memq system-type '(ms-dos windows-nt))
- (error "chown not supported on this system."))
- (dired-do-chxxx "Owner" dired-chown-program 'chown arg))
-
-;; Process all the files in FILES in batches of a convenient size,
-;; by means of (FUNCALL FUNCTION ARGS... SOME-FILES...).
-;; Batches are chosen to need less than MAX chars for the file names,
-;; allowing 3 extra characters of separator per file name.
-(defun dired-bunch-files (max function args files)
- (let (pending
- (pending-length 0)
- failures)
- ;; Accumulate files as long as they fit in MAX chars,
- ;; then process the ones accumulated so far.
- (while files
- (let* ((thisfile (car files))
- (thislength (+ (length thisfile) 3))
- (rest (cdr files)))
- ;; If we have at least 1 pending file
- ;; and this file won't fit in the length limit, process now.
- (if (and pending (> (+ thislength pending-length) max))
- (setq failures
- (nconc (apply function (append args pending))
- failures)
- pending nil
- pending-length 0))
- ;; Do (setq pending (cons thisfile pending))
- ;; but reuse the cons that was in `files'.
- (setcdr files pending)
- (setq pending files)
- (setq pending-length (+ thislength pending-length))
- (setq files rest)))
- (nconc (apply function (append args pending))
- failures)))
-
-;;;###autoload
-(defun dired-do-print (&optional arg)
- "Print the marked (or next ARG) files.
-Uses the shell command coming from variables `lpr-command' and
-`lpr-switches' as default."
- (interactive "P")
- (let* ((file-list (dired-get-marked-files t arg))
- (command (dired-mark-read-string
- "Print %s with: "
- (mapconcat 'identity
- (cons lpr-command
- (if (stringp lpr-switches)
- (list lpr-switches)
- lpr-switches))
- " ")
- 'print arg file-list)))
- (dired-run-shell-command (dired-shell-stuff-it command file-list nil))))
-
-;; Read arguments for a marked-files command that wants a string
-;; that is not a file name,
-;; perhaps popping up the list of marked files.
-;; ARG is the prefix arg and indicates whether the files came from
-;; marks (ARG=nil) or a repeat factor (integerp ARG).
-;; If the current file was used, the list has but one element and ARG
-;; does not matter. (It is non-nil, non-integer in that case, namely '(4)).
-
-(defun dired-mark-read-string (prompt initial op-symbol arg files)
- ;; PROMPT for a string, with INITIAL input.
- ;; Other args are used to give user feedback and pop-up:
- ;; OP-SYMBOL of command, prefix ARG, marked FILES.
- (dired-mark-pop-up
- nil op-symbol files
- (function read-string)
- (format prompt (dired-mark-prompt arg files)) initial))
-
-;;; Cleaning a directory: flagging some backups for deletion.
-
-(defvar dired-file-version-alist)
-
-(defun dired-clean-directory (keep)
- "Flag numerical backups for deletion.
-Spares `dired-kept-versions' latest versions, and `kept-old-versions' oldest.
-Positive prefix arg KEEP overrides `dired-kept-versions';
-Negative prefix arg KEEP overrides `kept-old-versions' with KEEP made positive.
-
-To clear the flags on these files, you can use \\[dired-flag-backup-files]
-with a prefix argument."
- (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))
- (dired-file-version-alist ()))
- (message "Cleaning numerical backups (keeping %d late, %d old)..."
- late-retention early-retention)
- ;; Look at each file.
- ;; If the file has numeric backup versions,
- ;; put on dired-file-version-alist an element of the form
- ;; (FILENAME . VERSION-NUMBER-LIST)
- (dired-map-dired-file-lines (function dired-collect-file-versions))
- ;; Sort each VERSION-NUMBER-LIST,
- ;; and remove the versions not to be deleted.
- (let ((fval dired-file-version-alist))
- (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 (function dired-trample-file-versions))
- (message "Cleaning numerical backups...done")))
-
-;;; Subroutines of dired-clean-directory.
-
-(defun dired-map-dired-file-lines (fun)
- ;; Perform FUN with point at the end of each non-directory line.
- ;; FUN takes one argument, the filename (complete pathname).
- (save-excursion
- (let (file buffer-read-only)
- (goto-char (point-min))
- (while (not (eobp))
- (save-excursion
- (and (not (looking-at dired-re-dir))
- (not (eolp))
- (setq file (dired-get-filename nil t)) ; nil on non-file
- (progn (end-of-line)
- (funcall fun file))))
- (forward-line 1)))))
-
-(defun dired-collect-file-versions (fn)
- (let ((fn (file-name-sans-versions fn)))
- ;; Only do work if this file is not already in the alist.
- (if (assoc fn dired-file-version-alist)
- nil
- ;; If it looks like file FN has versions, return a list of the versions.
- ;;That is a list of strings which are file names.
- ;;The caller may want to flag some of these files 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 dired-file-version-alist
- (cons (cons fn versions)
- dired-file-version-alist)))))))
-
-(defun dired-trample-file-versions (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
- dired-file-version-alist)) ; subversion
- (not (memq (string-to-int (substring fn (+ 2 start-vn)))
- base-version-list)) ; this one doesn't make the cut
- (progn (beginning-of-line)
- (delete-char 1)
- (insert dired-del-marker)))))
-
-;;; Shell commands
-;;>>> install (move this function into simple.el)
-(defun dired-shell-quote (filename)
- "Quote a file name for inferior shell (see variable `shell-file-name')."
- ;; Quote everything except POSIX filename characters.
- ;; This should be safe enough even for really weird shells.
- (let ((result "") (start 0) end)
- (while (string-match "[^-0-9a-zA-Z_./]" filename start)
- (setq end (match-beginning 0)
- result (concat result (substring filename start end)
- "\\" (substring filename end (1+ end)))
- start (1+ end)))
- (concat result (substring filename start))))
-
-(defun dired-read-shell-command (prompt arg files)
-;; "Read a dired shell command prompting with PROMPT (using read-string).
-;;ARG is the prefix arg and may be used to indicate in the prompt which
-;; files are affected.
-;;This is an extra function so that you can redefine it, e.g., to use gmhist."
- (dired-mark-pop-up
- nil 'shell files
- (function read-string)
- (format prompt (dired-mark-prompt arg files))
- nil 'shell-command-history))
-
-;; The in-background argument is only needed in Emacs 18 where
-;; shell-command doesn't understand an appended ampersand `&'.
-;;;###autoload
-(defun dired-do-shell-command (command &optional arg)
- "Run a shell command COMMAND on the marked files.
-If no files are marked or a specific numeric prefix arg is given,
-the next ARG files are used. Just \\[universal-argument] means the current file.
-The prompt mentions the file(s) or the marker, as appropriate.
-
-If there is output, it goes to a separate buffer.
-
-Normally the command is run on each file individually.
-However, if there is a `*' in the command then it is run
-just once with the entire file list substituted there.
-
-No automatic redisplay of dired buffers is attempted, as there's no
-telling what files the command may have changed. Type
-\\[dired-do-redisplay] to redisplay the marked files.
-
-The shell command has the top level directory as working directory, so
-output files usually are created there instead of in a subdir."
-;;Functions dired-run-shell-command and dired-shell-stuff-it do the
-;;actual work and can be redefined for customization.
- (interactive (list
- ;; Want to give feedback whether this file or marked files are used:
- (dired-read-shell-command (concat "! on "
- "%s: ")
- current-prefix-arg
- (dired-get-marked-files
- t current-prefix-arg))
- current-prefix-arg))
- (let* ((on-each (not (string-match "\\*" command)))
- (file-list (dired-get-marked-files t arg)))
- (if on-each
- (dired-bunch-files
- (- 10000 (length command))
- (function (lambda (&rest files)
- (dired-run-shell-command
- (dired-shell-stuff-it command files t arg))))
- nil
- file-list)
- ;; execute the shell command
- (dired-run-shell-command
- (dired-shell-stuff-it command file-list nil arg)))))
-
-;; Might use {,} for bash or csh:
-(defvar dired-mark-prefix ""
- "Prepended to marked files in dired shell commands.")
-(defvar dired-mark-postfix ""
- "Appended to marked files in dired shell commands.")
-(defvar dired-mark-separator " "
- "Separates marked files in dired shell commands.")
-
-(defun dired-shell-stuff-it (command file-list on-each &optional raw-arg)
-;; "Make up a shell command line from COMMAND and FILE-LIST.
-;; If ON-EACH is t, COMMAND should be applied to each file, else
-;; simply concat all files and apply COMMAND to this.
-;; FILE-LIST's elements will be quoted for the shell."
-;; Might be redefined for smarter things and could then use RAW-ARG
-;; (coming from interactive P and currently ignored) to decide what to do.
-;; Smart would be a way to access basename or extension of file names.
-;; See dired-trns.el for an approach to this.
- ;; Bug: There is no way to quote a *
- ;; On the other hand, you can never accidentally get a * into your cmd.
- (let ((stuff-it
- (if (string-match "\\*" command)
- (function (lambda (x)
- (dired-replace-in-string "\\*" x command)))
- (function (lambda (x) (concat command " " x))))))
- (if on-each
- (mapconcat stuff-it (mapcar 'dired-shell-quote file-list) ";")
- (let ((fns (mapconcat 'dired-shell-quote
- file-list dired-mark-separator)))
- (if (> (length file-list) 1)
- (setq fns (concat dired-mark-prefix fns dired-mark-postfix)))
- (funcall stuff-it fns)))))
-
-;; This is an extra function so that it can be redefined by ange-ftp.
-(defun dired-run-shell-command (command)
- (shell-command command)
- ;; Return nil for sake of nconc in dired-bunch-files.
- nil)
-
-;; In Emacs 19 this will return program's exit status.
-;; This is a separate function so that ange-ftp can redefine it.
-(defun dired-call-process (program discard &rest arguments)
-; "Run PROGRAM with output to current buffer unless DISCARD is t.
-;Remaining arguments are strings passed as command arguments to PROGRAM."
- ;; Look for a handler for default-directory in case it is a remote file name.
- (let ((handler
- (find-file-name-handler (directory-file-name default-directory)
- 'dired-call-process)))
- (if handler (apply handler 'dired-call-process
- program discard arguments)
- (apply 'call-process program nil (not discard) nil arguments))))
-
-(defun dired-check-process (msg program &rest arguments)
-; "Display MSG while running PROGRAM, and check for output.
-;Remaining arguments are strings passed as command arguments to PROGRAM.
-; On error, insert output
-; in a log buffer and return the offending ARGUMENTS or PROGRAM.
-; Caller can cons up a list of failed args.
-;Else returns nil for success."
- (let (err-buffer err (dir default-directory))
- (message "%s..." msg)
- (save-excursion
- ;; Get a clean buffer for error output:
- (setq err-buffer (get-buffer-create " *dired-check-process output*"))
- (set-buffer err-buffer)
- (erase-buffer)
- (setq default-directory dir ; caller's default-directory
- err (/= 0
- (apply (function dired-call-process) program nil arguments)))
- (if err
- (progn
- (dired-log (concat program " " (prin1-to-string arguments) "\n"))
- (dired-log err-buffer)
- (or arguments program t))
- (kill-buffer err-buffer)
- (message "%s...done" msg)
- nil))))
-
-;; Commands that delete or redisplay part of the dired buffer.
-
-(defun dired-kill-line (&optional arg)
- (interactive "P")
- (setq arg (prefix-numeric-value arg))
- (let (buffer-read-only file)
- (while (/= 0 arg)
- (setq file (dired-get-filename nil t))
- (if (not file)
- (error "Can only kill file lines.")
- (save-excursion (and file
- (dired-goto-subdir file)
- (dired-kill-subdir)))
- (delete-region (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point)))
- (if (> arg 0)
- (setq arg (1- arg))
- (setq arg (1+ arg))
- (forward-line -1))))
- (dired-move-to-filename)))
-
-;;;###autoload
-(defun dired-do-kill-lines (&optional arg fmt)
- "Kill all marked lines (not the files).
-With a prefix argument, kill that many lines starting with the current line.
-\(A negative argument kills lines before the current line.)
-To kill an entire subdirectory, go to its directory header line
-and use this command with a prefix argument (the value does not matter)."
- ;; Returns count of killed lines. FMT="" suppresses message.
- (interactive "P")
- (if arg
- (if (dired-get-subdir)
- (dired-kill-subdir)
- (dired-kill-line arg))
- (save-excursion
- (goto-char (point-min))
- (let (buffer-read-only (count 0))
- (if (not arg) ; kill marked lines
- (let ((regexp (dired-marker-regexp)))
- (while (and (not (eobp))
- (re-search-forward regexp nil t))
- (setq count (1+ count))
- (delete-region (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point)))))
- ;; else kill unmarked lines
- (while (not (eobp))
- (if (or (dired-between-files)
- (not (looking-at "^ ")))
- (forward-line 1)
- (setq count (1+ count))
- (delete-region (point) (save-excursion
- (forward-line 1)
- (point))))))
- (or (equal "" fmt)
- (message (or fmt "Killed %d line%s.") count (dired-plural-s count)))
- count))))
-
-;;;###end dired-cmd.el
-
-;;; 30K
-;;;###begin dired-cp.el
-
-(defun dired-compress ()
- ;; Compress or uncompress the current file.
- ;; Return nil for success, offending filename else.
- (let* (buffer-read-only
- (from-file (dired-get-filename))
- (new-file (dired-compress-file from-file)))
- (if new-file
- (let ((start (point)))
- ;; Remove any preexisting entry for the name NEW-FILE.
- (condition-case nil
- (dired-remove-entry new-file)
- (error nil))
- (goto-char start)
- ;; Now replace the current line with an entry for NEW-FILE.
- (dired-update-file-line new-file) nil)
- (dired-log (concat "Failed to compress" from-file))
- from-file)))
-
-(defvar dired-compress-file-suffixes
- '(("\\.gz\\'" "" "gunzip")
- ("\\.tgz\\'" ".tar" "gunzip")
- ("\\.Z\\'" "" "uncompress")
- ;; For .z, try gunzip. It might be an old gzip file,
- ;; or it might be from compact? pack? (which?) but gunzip handles both.
- ("\\.z\\'" "" "gunzip")
- ;; This item controls naming for compression.
- ("\\.tar\\'" ".tgz" nil))
- "Control changes in file name suffixes for compression and uncompression.
-Each element specifies one transformation rule, and has the form:
- (REGEXP NEW-SUFFIX PROGRAM)
-The rule applies when the old file name matches REGEXP.
-The new file name is computed by deleting the part that matches REGEXP
- (as well as anything after that), then adding NEW-SUFFIX in its place.
-If PROGRAM is non-nil, the rule is an uncompression rule,
-and uncompression is done by running PROGRAM.
-Otherwise, the rule is a compression rule, and compression is done with gzip.")
-
-;;;###autoload
-(defun dired-compress-file (file)
- ;; Compress or uncompress FILE.
- ;; Return the name of the compressed or uncompressed file.
- ;; Return nil if no change in files.
- (let ((handler (find-file-name-handler file 'dired-compress-file))
- suffix newname
- (suffixes dired-compress-file-suffixes))
- ;; See if any suffix rule matches this file name.
- (while suffixes
- (let (case-fold-search)
- (if (string-match (car (car suffixes)) file)
- (setq suffix (car suffixes) suffixes nil))
- (setq suffixes (cdr suffixes))))
- ;; If so, compute desired new name.
- (if suffix
- (setq newname (concat (substring file 0 (match-beginning 0))
- (nth 1 suffix))))
- (cond (handler
- (funcall handler 'dired-compress-file file))
- ((file-symlink-p file)
- nil)
- ((and suffix (nth 2 suffix))
- ;; We found an uncompression rule.
- (if (not (dired-check-process (concat "Uncompressing " file)
- (nth 2 suffix) file))
- newname))
- (t
- ;;; We don't recognize the file as compressed, so compress it.
- ;;; Try gzip; if we don't have that, use compress.
- (condition-case nil
- (if (not (dired-check-process (concat "Compressing " file)
- "gzip" "-f" file))
- (let ((out-name
- (if (file-exists-p (concat file ".gz"))
- (concat file ".gz")
- (concat file ".z"))))
- ;; Rename the compressed file to NEWNAME
- ;; if it hasn't got that name already.
- (if (and newname (not (equal newname out-name)))
- (progn
- (rename-file out-name newname t)
- newname)
- out-name)))
- (file-error
- (if (not (dired-check-process (concat "Compressing " file)
- "compress" "-f" file))
- ;; Don't use NEWNAME with `compress'.
- (concat file ".Z"))))))))
-
-(defun dired-mark-confirm (op-symbol arg)
- ;; Request confirmation from the user that the operation described
- ;; by OP-SYMBOL is to be performed on the marked files.
- ;; Confirmation consists in a y-or-n question with a file list
- ;; pop-up unless OP-SYMBOL is a member of `dired-no-confirm'.
- ;; The files used are determined by ARG (as in dired-get-marked-files).
- (or (memq op-symbol dired-no-confirm)
- (let ((files (dired-get-marked-files t arg))
- (string (if (eq op-symbol 'compress) "Compress or uncompress"
- (capitalize (symbol-name op-symbol)))))
- (dired-mark-pop-up nil op-symbol files (function y-or-n-p)
- (concat string " "
- (dired-mark-prompt arg files) "? ")))))
-
-(defun dired-map-over-marks-check (fun arg op-symbol &optional show-progress)
-; "Map FUN over marked files (with second ARG like in dired-map-over-marks)
-; and display failures.
-
-; FUN takes zero args. It returns non-nil (the offending object, e.g.
-; the short form of the filename) for a failure and probably logs a
-; detailed error explanation using function `dired-log'.
-
-; OP-SYMBOL is a symbol describing the operation performed (e.g.
-; `compress'). It is used with `dired-mark-pop-up' to prompt the user
-; (e.g. with `Compress * [2 files]? ') and to display errors (e.g.
-; `Failed to compress 1 of 2 files - type W to see why ("foo")')
-
-; SHOW-PROGRESS if non-nil means redisplay dired after each file."
- (if (dired-mark-confirm op-symbol arg)
- (let* ((total-list;; all of FUN's return values
- (dired-map-over-marks (funcall fun) arg show-progress))
- (total (length total-list))
- (failures (delq nil total-list))
- (count (length failures))
- (string (if (eq op-symbol 'compress) "Compress or uncompress"
- (capitalize (symbol-name op-symbol)))))
- (if (not failures)
- (message "%s: %d file%s."
- string total (dired-plural-s total))
- ;; end this bunch of errors:
- (dired-log-summary
- (format "Failed to %s %d of %d file%s"
- (downcase string) count total (dired-plural-s total))
- failures)))))
-
-(defvar dired-query-alist
- '((?\y . y) (?\040 . y) ; `y' or SPC means accept once
- (?n . n) (?\177 . n) ; `n' or DEL skips once
- (?! . yes) ; `!' accepts rest
- (?q. no) (?\e . no) ; `q' or ESC skips rest
- ;; None of these keys quit - use C-g for that.
- ))
-
-(defun dired-query (qs-var qs-prompt &rest qs-args)
- ;; Query user and return nil or t.
- ;; Store answer in symbol VAR (which must initially be bound to nil).
- ;; Format PROMPT with ARGS.
- ;; Binding variable help-form will help the user who types the help key.
- (let* ((char (symbol-value qs-var))
- (action (cdr (assoc char dired-query-alist))))
- (cond ((eq 'yes action)
- t) ; accept, and don't ask again
- ((eq 'no action)
- nil) ; skip, and don't ask again
- (t;; no lasting effects from last time we asked - ask now
- (let ((qprompt (concat qs-prompt
- (if help-form
- (format " [Type yn!q or %s] "
- (key-description
- (char-to-string help-char)))
- " [Type y, n, q or !] ")))
- result elt)
- ;; Actually it looks nicer without cursor-in-echo-area - you can
- ;; look at the dired buffer instead of at the prompt to decide.
- (apply 'message qprompt qs-args)
- (setq char (set qs-var (read-char)))
- (while (not (setq elt (assoc char dired-query-alist)))
- (message "Invalid char - type %c for help." help-char)
- (ding)
- (sit-for 1)
- (apply 'message qprompt qs-args)
- (setq char (set qs-var (read-char))))
- (memq (cdr elt) '(t y yes)))))))
-
-;;;###autoload
-(defun dired-do-compress (&optional arg)
- "Compress or uncompress marked (or next ARG) files."
- (interactive "P")
- (dired-map-over-marks-check (function dired-compress) arg 'compress t))
-
-;; Commands for Emacs Lisp files - load and byte compile
-
-(defun dired-byte-compile ()
- ;; Return nil for success, offending file name else.
- (let* ((filename (dired-get-filename))
- elc-file buffer-read-only failure)
- (condition-case err
- (save-excursion (byte-compile-file filename))
- (error
- (setq failure err)))
- (setq elc-file (byte-compile-dest-file filename))
- (or (file-exists-p elc-file)
- (setq failure t))
- (if failure
- (progn
- (dired-log "Byte compile error for %s:\n%s\n" filename failure)
- (dired-make-relative filename))
- (dired-remove-file elc-file)
- (forward-line) ; insert .elc after its .el file
- (dired-add-file elc-file)
- nil)))
-
-;;;###autoload
-(defun dired-do-byte-compile (&optional arg)
- "Byte compile marked (or next ARG) Emacs Lisp files."
- (interactive "P")
- (dired-map-over-marks-check (function dired-byte-compile) arg 'byte-compile t))
-
-(defun dired-load ()
- ;; Return nil for success, offending file name else.
- (let ((file (dired-get-filename)) failure)
- (condition-case err
- (load file nil nil t)
- (error (setq failure err)))
- (if (not failure)
- nil
- (dired-log "Load error for %s:\n%s\n" file failure)
- (dired-make-relative file))))
-
-;;;###autoload
-(defun dired-do-load (&optional arg)
- "Load the marked (or next ARG) Emacs Lisp files."
- (interactive "P")
- (dired-map-over-marks-check (function dired-load) arg 'load t))
-
-;;;###autoload
-(defun dired-do-redisplay (&optional arg test-for-subdir)
- "Redisplay all marked (or next ARG) files.
-If on a subdir line, redisplay that subdirectory. In that case,
-a prefix arg lets you edit the `ls' switches used for the new listing."
- ;; Moves point if the next ARG files are redisplayed.
- (interactive "P\np")
- (if (and test-for-subdir (dired-get-subdir))
- (dired-insert-subdir
- (dired-get-subdir)
- (if arg (read-string "Switches for listing: " dired-actual-switches)))
- (message "Redisplaying...")
- ;; message much faster than making dired-map-over-marks show progress
- (dired-uncache
- (if (consp dired-directory) (car dired-directory) dired-directory))
- (dired-map-over-marks (let ((fname (dired-get-filename)))
- (message "Redisplaying... %s" fname)
- (dired-update-file-line fname))
- arg)
- (dired-move-to-filename)
- (message "Redisplaying...done")))
-
-(defun dired-update-file-line (file)
- ;; Delete the current line, and insert an entry for FILE.
- ;; If FILE is nil, then just delete the current line.
- ;; Keeps any marks that may be present in column one (doing this
- ;; here is faster than with dired-add-entry's optional arg).
- ;; Does not update other dired buffers. Use dired-relist-entry for that.
- (beginning-of-line)
- (let ((char (following-char)) (opoint (point))
- (buffer-read-only))
- (delete-region (point) (progn (forward-line 1) (point)))
- (if file
- (progn
- (dired-add-entry file)
- ;; Replace space by old marker without moving point.
- ;; Faster than goto+insdel inside a save-excursion?
- (subst-char-in-region opoint (1+ opoint) ?\040 char))))
- (dired-move-to-filename))
-
-(defun dired-fun-in-all-buffers (directory fun &rest args)
- ;; In all buffers dired'ing DIRECTORY, run FUN with ARGS.
- ;; Return list of buffers where FUN succeeded (i.e., returned non-nil).
- (let ((buf-list (dired-buffers-for-dir (expand-file-name directory)))
- (obuf (current-buffer))
- buf success-list)
- (while buf-list
- (setq buf (car buf-list)
- buf-list (cdr buf-list))
- (unwind-protect
- (progn
- (set-buffer buf)
- (if (apply fun args)
- (setq success-list (cons (buffer-name buf) success-list))))
- (set-buffer obuf)))
- success-list))
-
-;;;###autoload
-(defun dired-add-file (filename &optional marker-char)
- (dired-fun-in-all-buffers
- (file-name-directory filename)
- (function dired-add-entry) filename marker-char))
-
-(defun dired-add-entry (filename &optional marker-char)
- ;; Add a new entry for FILENAME, optionally marking it
- ;; with MARKER-CHAR (a character, else dired-marker-char is used).
- ;; Note that this adds the entry `out of order' if files sorted by
- ;; time, etc.
- ;; At least this version inserts in the right subdirectory (if present).
- ;; And it skips "." or ".." (see `dired-trivial-filenames').
- ;; Hidden subdirs are exposed if a file is added there.
- (setq filename (directory-file-name filename))
- ;; Entry is always for files, even if they happen to also be directories
- (let ((opoint (point))
- (cur-dir (dired-current-directory))
- (orig-file-name filename)
- (directory (file-name-directory filename))
- reason)
- (setq filename (file-name-nondirectory filename)
- reason
- (catch 'not-found
- (if (string= directory cur-dir)
- (progn
- (skip-chars-forward "^\r\n")
- (if (eq (following-char) ?\r)
- (dired-unhide-subdir))
- ;; We are already where we should be, except when
- ;; point is before the subdir line or its total line.
- (let ((p (dired-after-subdir-garbage cur-dir)))
- (if (< (point) p)
- (goto-char p))))
- ;; else try to find correct place to insert
- (if (dired-goto-subdir directory)
- (progn;; unhide if necessary
- (if (looking-at "\r");; point is at end of subdir line
- (dired-unhide-subdir))
- ;; found - skip subdir and `total' line
- ;; and uninteresting files like . and ..
- ;; This better not moves into the next subdir!
- (dired-goto-next-nontrivial-file))
- ;; not found
- (throw 'not-found "Subdir not found")))
- (let (buffer-read-only opoint)
- (beginning-of-line)
- (setq opoint (point))
- (dired-add-entry-do-indentation marker-char)
- ;; don't expand `.'. Show just the file name within directory.
- (let ((default-directory directory))
- (insert-directory filename
- (concat dired-actual-switches "d")))
- ;; Compensate for a bug in ange-ftp.
- ;; It inserts the file's absolute name, rather than
- ;; the relative one. That may be hard to fix since it
- ;; is probably controlled by something in ftp.
- (goto-char opoint)
- (let ((inserted-name (dired-get-filename 'no-dir)))
- (if (file-name-directory inserted-name)
- (progn
- (end-of-line)
- (delete-char (- (length inserted-name)))
- (insert filename)
- (forward-char 1))
- (forward-line 1)))
- ;; Give each line a text property recording info about it.
- (dired-insert-set-properties opoint (point))
- (forward-line -1)
- (if dired-after-readin-hook;; the subdir-alist is not affected...
- (save-excursion;; ...so we can run it right now:
- (save-restriction
- (beginning-of-line)
- (narrow-to-region (point) (save-excursion
- (forward-line 1) (point)))
- (run-hooks 'dired-after-readin-hook))))
- (dired-move-to-filename))
- ;; return nil if all went well
- nil))
- (if reason ; don't move away on failure
- (goto-char opoint))
- (not reason))) ; return t on success, nil else
-
-;; This is a separate function for the sake of nested dired format.
-(defun dired-add-entry-do-indentation (marker-char)
- ;; two spaces or a marker plus a space:
- (insert (if marker-char
- (if (integerp marker-char) marker-char dired-marker-char)
- ?\040)
- ?\040))
-
-(defun dired-after-subdir-garbage (dir)
- ;; Return pos of first file line of DIR, skipping header and total
- ;; or wildcard lines.
- ;; Important: never moves into the next subdir.
- ;; DIR is assumed to be unhidden.
- ;; Will probably be redefined for VMS etc.
- (save-excursion
- (or (dired-goto-subdir dir) (error "This cannot happen"))
- (forward-line 1)
- (while (and (not (eolp)) ; don't cross subdir boundary
- (not (dired-move-to-filename)))
- (forward-line 1))
- (point)))
-
-;;;###autoload
-(defun dired-remove-file (file)
- (dired-fun-in-all-buffers
- (file-name-directory file) (function dired-remove-entry) file))
-
-(defun dired-remove-entry (file)
- (save-excursion
- (and (dired-goto-file file)
- (let (buffer-read-only)
- (delete-region (progn (beginning-of-line) (point))
- (save-excursion (forward-line 1) (point)))))))
-
-;;;###autoload
-(defun dired-relist-file (file)
- (dired-fun-in-all-buffers (file-name-directory file)
- (function dired-relist-entry) file))
-
-(defun dired-relist-entry (file)
- ;; Relist the line for FILE, or just add it if it did not exist.
- ;; FILE must be an absolute pathname.
- (let (buffer-read-only marker)
- ;; If cursor is already on FILE's line delete-region will cause
- ;; save-excursion to fail because of floating makers,
- ;; moving point to beginning of line. Sigh.
- (save-excursion
- (and (dired-goto-file file)
- (delete-region (progn (beginning-of-line)
- (setq marker (following-char))
- (point))
- (save-excursion (forward-line 1) (point))))
- (setq file (directory-file-name file))
- (dired-add-entry file (if (eq ?\040 marker) nil marker)))))
-
-;;; Copy, move/rename, making hard and symbolic links
-
-(defvar dired-backup-overwrite nil
- "*Non-nil if Dired should ask about making backups before overwriting files.
-Special value `always' suppresses confirmation.")
-
-(defvar dired-overwrite-confirmed)
-
-(defun dired-handle-overwrite (to)
- ;; Save old version of a to be overwritten file TO.
- ;; `dired-overwrite-confirmed' and `overwrite-backup-query' are fluid vars
- ;; from dired-create-files.
- (let (backup)
- (if (and dired-backup-overwrite
- dired-overwrite-confirmed
- (setq backup (car (find-backup-file-name to)))
- (or (eq 'always dired-backup-overwrite)
- (dired-query 'overwrite-backup-query
- (format "Make backup for existing file `%s'? " to))))
- (progn
- (rename-file to backup 0) ; confirm overwrite of old backup
- (dired-relist-entry backup)))))
-
-;;;###autoload
-(defun dired-copy-file (from to ok-flag)
- (dired-handle-overwrite to)
- (copy-file from to ok-flag dired-copy-preserve-time))
-
-;;;###autoload
-(defun dired-rename-file (from to ok-flag)
- (dired-handle-overwrite to)
- (rename-file from to ok-flag) ; error is caught in -create-files
- ;; Silently rename the visited file of any buffer visiting this file.
- (and (get-file-buffer from)
- (save-excursion
- (set-buffer (get-file-buffer from))
- (let ((modflag (buffer-modified-p)))
- (set-visited-file-name to)
- (set-buffer-modified-p modflag))))
- (dired-remove-file from)
- ;; See if it's an inserted subdir, and rename that, too.
- (dired-rename-subdir from to))
-
-(defun dired-rename-subdir (from-dir to-dir)
- (setq from-dir (file-name-as-directory from-dir)
- to-dir (file-name-as-directory to-dir))
- (dired-fun-in-all-buffers from-dir
- (function dired-rename-subdir-1) from-dir to-dir)
- ;; Update visited file name of all affected buffers
- (let ((expanded-from-dir (expand-file-name from-dir))
- (blist (buffer-list)))
- (while blist
- (save-excursion
- (set-buffer (car blist))
- (if (and buffer-file-name
- (dired-in-this-tree buffer-file-name expanded-from-dir))
- (let ((modflag (buffer-modified-p))
- (to-file (dired-replace-in-string
- (concat "^" (regexp-quote from-dir))
- to-dir
- buffer-file-name)))
- (set-visited-file-name to-file)
- (set-buffer-modified-p modflag))))
- (setq blist (cdr blist)))))
-
-(defun dired-rename-subdir-1 (dir to)
- ;; Rename DIR to TO in headerlines and dired-subdir-alist, if DIR or
- ;; one of its subdirectories is expanded in this buffer.
- (let ((expanded-dir (expand-file-name dir))
- (alist dired-subdir-alist)
- (elt nil))
- (while alist
- (setq elt (car alist)
- alist (cdr alist))
- (if (dired-in-this-tree (car elt) expanded-dir)
- ;; ELT's subdir is affected by the rename
- (dired-rename-subdir-2 elt dir to)))
- (if (equal dir default-directory)
- ;; if top level directory was renamed, lots of things have to be
- ;; updated:
- (progn
- (dired-unadvertise dir) ; we no longer dired DIR...
- (setq default-directory to
- dired-directory (expand-file-name;; this is correct
- ;; with and without wildcards
- (file-name-nondirectory dired-directory)
- to))
- (let ((new-name (file-name-nondirectory
- (directory-file-name dired-directory))))
- ;; try to rename buffer, but just leave old name if new
- ;; name would already exist (don't try appending "<%d>")
- (or (get-buffer new-name)
- (rename-buffer new-name)))
- ;; ... we dired TO now:
- (dired-advertise)))))
-
-(defun dired-rename-subdir-2 (elt dir to)
- ;; Update the headerline and dired-subdir-alist element of directory
- ;; described by alist-element ELT to reflect the moving of DIR to TO.
- ;; Thus, ELT describes either DIR itself or a subdir of DIR.
- (save-excursion
- (let ((regexp (regexp-quote (directory-file-name dir)))
- (newtext (directory-file-name to))
- buffer-read-only)
- (goto-char (dired-get-subdir-min elt))
- ;; Update subdir headerline in buffer
- (if (not (looking-at dired-subdir-regexp))
- (error "%s not found where expected - dired-subdir-alist broken?"
- dir)
- (goto-char (match-beginning 1))
- (if (re-search-forward regexp (match-end 1) t)
- (replace-match newtext t t)
- (error "Expected to find `%s' in headerline of %s" dir (car elt))))
- ;; Update buffer-local dired-subdir-alist
- (setcar elt
- (dired-normalize-subdir
- (dired-replace-in-string regexp newtext (car elt)))))))
-
-;; The basic function for half a dozen variations on cp/mv/ln/ln -s.
-(defun dired-create-files (file-creator operation fn-list name-constructor
- &optional marker-char)
-
-;; Create a new file for each from a list of existing files. The user
-;; is queried, dired buffers are updated, and at the end a success or
-;; failure message is displayed
-
-;; FILE-CREATOR must accept three args: oldfile newfile ok-if-already-exists
-
-;; It is called for each file and must create newfile, the entry of
-;; which will be added. The user will be queried if the file already
-;; exists. If oldfile is removed by FILE-CREATOR (i.e, it is a
-;; rename), it is FILE-CREATOR's responsibility to update dired
-;; buffers. FILE-CREATOR must abort by signaling a file-error if it
-;; could not create newfile. The error is caught and logged.
-
-;; OPERATION (a capitalized string, e.g. `Copy') describes the
-;; operation performed. It is used for error logging.
-
-;; FN-LIST is the list of files to copy (full absolute pathnames).
-
-;; NAME-CONSTRUCTOR returns a newfile for every oldfile, or nil to
-;; skip. If it skips files for other reasons than a direct user
-;; query, it is supposed to tell why (using dired-log).
-
-;; Optional MARKER-CHAR is a character with which to mark every
-;; newfile's entry, or t to use the current marker character if the
-;; oldfile was marked.
-
- (let (failures skipped (success-count 0) (total (length fn-list)))
- (let (to overwrite-query
- overwrite-backup-query) ; for dired-handle-overwrite
- (mapcar
- (function
- (lambda (from)
- (setq to (funcall name-constructor from))
- (if (equal to from)
- (progn
- (setq to nil)
- (dired-log "Cannot %s to same file: %s\n"
- (downcase operation) from)))
- (if (not to)
- (setq skipped (cons (dired-make-relative from) skipped))
- (let* ((overwrite (file-exists-p to))
- (dired-overwrite-confirmed ; for dired-handle-overwrite
- (and overwrite
- (let ((help-form '(format "\
-Type SPC or `y' to overwrite file `%s',
-DEL or `n' to skip to next,
-ESC or `q' to not overwrite any of the remaining files,
-`!' to overwrite all remaining files with no more questions." to)))
- (dired-query 'overwrite-query
- "Overwrite `%s'?" to))))
- ;; must determine if FROM is marked before file-creator
- ;; gets a chance to delete it (in case of a move).
- (actual-marker-char
- (cond ((integerp marker-char) marker-char)
- (marker-char (dired-file-marker from)) ; slow
- (t nil))))
- (condition-case err
- (progn
- (funcall file-creator from to dired-overwrite-confirmed)
- (if overwrite
- ;; If we get here, file-creator hasn't been aborted
- ;; and the old entry (if any) has to be deleted
- ;; before adding the new entry.
- (dired-remove-file to))
- (setq success-count (1+ success-count))
- (message "%s: %d of %d" operation success-count total)
- (dired-add-file to actual-marker-char))
- (file-error ; FILE-CREATOR aborted
- (progn
- (setq failures (cons (dired-make-relative from) failures))
- (dired-log "%s `%s' to `%s' failed:\n%s\n"
- operation from to err))))))))
- fn-list))
- (cond
- (failures
- (dired-log-summary
- (format "%s failed for %d of %d file%s"
- operation (length failures) total
- (dired-plural-s total))
- failures))
- (skipped
- (dired-log-summary
- (format "%s: %d of %d file%s skipped"
- operation (length skipped) total
- (dired-plural-s total))
- skipped))
- (t
- (message "%s: %s file%s"
- operation success-count (dired-plural-s success-count)))))
- (dired-move-to-filename))
-
-(defun dired-do-create-files (op-symbol file-creator operation arg
- &optional marker-char op1
- how-to)
- ;; Create a new file for each marked file.
- ;; Prompts user for target, which is a directory in which to create
- ;; the new files. Target may be a plain file if only one marked
- ;; file exists.
- ;; OP-SYMBOL is the symbol for the operation. Function `dired-mark-pop-up'
- ;; will determine whether pop-ups are appropriate for this OP-SYMBOL.
- ;; FILE-CREATOR and OPERATION as in dired-create-files.
- ;; ARG as in dired-get-marked-files.
- ;; Optional arg OP1 is an alternate form for OPERATION if there is
- ;; only one file.
- ;; Optional arg MARKER-CHAR as in dired-create-files.
- ;; Optional arg HOW-TO determines how to treat target:
- ;; If HOW-TO is not given (or nil), and target is a directory, the
- ;; file(s) are created inside the target directory. If target
- ;; is not a directory, there must be exactly one marked file,
- ;; else error.
- ;; If HOW-TO is t, then target is not modified. There must be
- ;; exactly one marked file, else error.
- ;; Else HOW-TO is assumed to be a function of one argument, target,
- ;; that looks at target and returns a value for the into-dir
- ;; variable. The function dired-into-dir-with-symlinks is provided
- ;; for the case (common when creating symlinks) that symbolic
- ;; links to directories are not to be considered as directories
- ;; (as file-directory-p would if HOW-TO had been nil).
- (or op1 (setq op1 operation))
- (let* ((fn-list (dired-get-marked-files nil arg))
- (fn-count (length fn-list))
- (target (expand-file-name
- (dired-mark-read-file-name
- (concat (if (= 1 fn-count) op1 operation) " %s to: ")
- (dired-dwim-target-directory)
- op-symbol arg (mapcar (function dired-make-relative) fn-list))))
- (into-dir (cond ((null how-to) (file-directory-p target))
- ((eq how-to t) nil)
- (t (funcall how-to target)))))
- (if (and (> fn-count 1)
- (not into-dir))
- (error "Marked %s: target must be a directory: %s" operation target))
- ;; rename-file bombs when moving directories unless we do this:
- (or into-dir (setq target (directory-file-name target)))
- (dired-create-files
- file-creator operation fn-list
- (if into-dir ; target is a directory
- ;; This function uses fluid vars into-dir and target when called
- ;; inside dired-create-files:
- (function (lambda (from)
- (expand-file-name (file-name-nondirectory from) target)))
- (function (lambda (from) target)))
- marker-char)))
-
-;; Read arguments for a marked-files command that wants a file name,
-;; perhaps popping up the list of marked files.
-;; ARG is the prefix arg and indicates whether the files came from
-;; marks (ARG=nil) or a repeat factor (integerp ARG).
-;; If the current file was used, the list has but one element and ARG
-;; does not matter. (It is non-nil, non-integer in that case, namely '(4)).
-
-(defun dired-mark-read-file-name (prompt dir op-symbol arg files)
- (dired-mark-pop-up
- nil op-symbol files
- (function read-file-name)
- (format prompt (dired-mark-prompt arg files)) dir))
-
-(defun dired-dwim-target-directory ()
- ;; Try to guess which target directory the user may want.
- ;; If there is a dired buffer displayed in the next window, use
- ;; its current subdir, else use current subdir of this dired buffer.
- (let ((this-dir (and (eq major-mode 'dired-mode)
- (dired-current-directory))))
- ;; non-dired buffer may want to profit from this function, e.g. vm-uudecode
- (if dired-dwim-target
- (let* ((other-buf (window-buffer (next-window)))
- (other-dir (save-excursion
- (set-buffer other-buf)
- (and (eq major-mode 'dired-mode)
- (dired-current-directory)))))
- (or other-dir this-dir))
- this-dir)))
-
-;;;###autoload
-(defun dired-create-directory (directory)
- "Create a directory called DIRECTORY."
- (interactive
- (list (read-file-name "Create directory: " (dired-current-directory))))
- (let ((expanded (directory-file-name (expand-file-name directory))))
- (make-directory expanded)
- (dired-add-file expanded)
- (dired-move-to-filename)))
-
-(defun dired-into-dir-with-symlinks (target)
- (and (file-directory-p target)
- (not (file-symlink-p target))))
-;; This may not always be what you want, especially if target is your
-;; home directory and it happens to be a symbolic link, as is often the
-;; case with NFS and automounters. Or if you want to make symlinks
-;; into directories that themselves are only symlinks, also quite
-;; common.
-
-;; So we don't use this function as value for HOW-TO in
-;; dired-do-symlink, which has the minor disadvantage of
-;; making links *into* a symlinked-dir, when you really wanted to
-;; *overwrite* that symlink. In that (rare, I guess) case, you'll
-;; just have to remove that symlink by hand before making your marked
-;; symlinks.
-
-;;;###autoload
-(defun dired-do-copy (&optional arg)
- "Copy all marked (or next ARG) files, or copy the current file.
-This normally preserves the last-modified date when copying.
-When operating on just the current file, you specify the new name.
-When operating on multiple or marked files, you specify a directory,
-and new copies of these files are made in that directory
-with the same names that the files currently have."
- (interactive "P")
- (dired-do-create-files 'copy (function dired-copy-file)
- (if dired-copy-preserve-time "Copy [-p]" "Copy")
- arg dired-keep-marker-copy))
-
-;;;###autoload
-(defun dired-do-symlink (&optional arg)
- "Make symbolic links to current file or all marked (or next ARG) files.
-When operating on just the current file, you specify the new name.
-When operating on multiple or marked files, you specify a directory
-and new symbolic links are made in that directory
-with the same names that the files currently have."
- (interactive "P")
- (dired-do-create-files 'symlink (function make-symbolic-link)
- "Symlink" arg dired-keep-marker-symlink))
-
-;;;###autoload
-(defun dired-do-hardlink (&optional arg)
- "Add names (hard links) current file or all marked (or next ARG) files.
-When operating on just the current file, you specify the new name.
-When operating on multiple or marked files, you specify a directory
-and new hard links are made in that directory
-with the same names that the files currently have."
- (interactive "P")
- (dired-do-create-files 'hardlink (function add-name-to-file)
- "Hardlink" arg dired-keep-marker-hardlink))
-
-;;;###autoload
-(defun dired-do-rename (&optional arg)
- "Rename current file or all marked (or next ARG) files.
-When renaming just the current file, you specify the new name.
-When renaming multiple or marked files, you specify a directory."
- (interactive "P")
- (dired-do-create-files 'move (function dired-rename-file)
- "Move" arg dired-keep-marker-rename "Rename"))
-;;;###end dired-cp.el
-
-;;; 5K
-;;;###begin dired-re.el
-(defun dired-do-create-files-regexp
- (file-creator operation arg regexp newname &optional whole-path marker-char)
- ;; Create a new file for each marked file using regexps.
- ;; FILE-CREATOR and OPERATION as in dired-create-files.
- ;; ARG as in dired-get-marked-files.
- ;; Matches each marked file against REGEXP and constructs the new
- ;; filename from NEWNAME (like in function replace-match).
- ;; Optional arg WHOLE-PATH means match/replace the whole pathname
- ;; instead of only the non-directory part of the file.
- ;; Optional arg MARKER-CHAR as in dired-create-files.
- (let* ((fn-list (dired-get-marked-files nil arg))
- (fn-count (length fn-list))
- (operation-prompt (concat operation " `%s' to `%s'?"))
- (rename-regexp-help-form (format "\
-Type SPC or `y' to %s one match, DEL or `n' to skip to next,
-`!' to %s all remaining matches with no more questions."
- (downcase operation)
- (downcase operation)))
- (regexp-name-constructor
- ;; Function to construct new filename using REGEXP and NEWNAME:
- (if whole-path ; easy (but rare) case
- (function
- (lambda (from)
- (let ((to (dired-string-replace-match regexp from newname))
- ;; must bind help-form directly around call to
- ;; dired-query
- (help-form rename-regexp-help-form))
- (if to
- (and (dired-query 'rename-regexp-query
- operation-prompt
- from
- to)
- to)
- (dired-log "%s: %s did not match regexp %s\n"
- operation from regexp)))))
- ;; not whole-path, replace non-directory part only
- (function
- (lambda (from)
- (let* ((new (dired-string-replace-match
- regexp (file-name-nondirectory from) newname))
- (to (and new ; nil means there was no match
- (expand-file-name new
- (file-name-directory from))))
- (help-form rename-regexp-help-form))
- (if to
- (and (dired-query 'rename-regexp-query
- operation-prompt
- (dired-make-relative from)
- (dired-make-relative to))
- to)
- (dired-log "%s: %s did not match regexp %s\n"
- operation (file-name-nondirectory from) regexp)))))))
- rename-regexp-query)
- (dired-create-files
- file-creator operation fn-list regexp-name-constructor marker-char)))
-
-(defun dired-mark-read-regexp (operation)
- ;; Prompt user about performing OPERATION.
- ;; Read and return list of: regexp newname arg whole-path.
- (let* ((whole-path
- (equal 0 (prefix-numeric-value current-prefix-arg)))
- (arg
- (if whole-path nil current-prefix-arg))
- (regexp
- (dired-read-regexp
- (concat (if whole-path "Path " "") operation " from (regexp): ")))
- (newname
- (read-string
- (concat (if whole-path "Path " "") operation " " regexp " to: "))))
- (list regexp newname arg whole-path)))
-
-;;;###autoload
-(defun dired-do-rename-regexp (regexp newname &optional arg whole-path)
- "Rename marked files containing REGEXP to NEWNAME.
-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.
-NEWNAME may contain \\=\\<n> or \\& as in `query-replace-regexp'.
-REGEXP defaults to the last regexp used.
-With a zero prefix arg, renaming by regexp affects the complete
- pathname - usually only the non-directory part of file names is used
- and changed."
- (interactive (dired-mark-read-regexp "Rename"))
- (dired-do-create-files-regexp
- (function dired-rename-file)
- "Rename" arg regexp newname whole-path dired-keep-marker-rename))
-
-;;;###autoload
-(defun dired-do-copy-regexp (regexp newname &optional arg whole-path)
- "Copy all marked files containing REGEXP to NEWNAME.
-See function `dired-rename-regexp' for more info."
- (interactive (dired-mark-read-regexp "Copy"))
- (dired-do-create-files-regexp
- (function dired-copy-file)
- (if dired-copy-preserve-time "Copy [-p]" "Copy")
- arg regexp newname whole-path dired-keep-marker-copy))
-
-;;;###autoload
-(defun dired-do-hardlink-regexp (regexp newname &optional arg whole-path)
- "Hardlink all marked files containing REGEXP to NEWNAME.
-See function `dired-rename-regexp' for more info."
- (interactive (dired-mark-read-regexp "HardLink"))
- (dired-do-create-files-regexp
- (function add-name-to-file)
- "HardLink" arg regexp newname whole-path dired-keep-marker-hardlink))
-
-;;;###autoload
-(defun dired-do-symlink-regexp (regexp newname &optional arg whole-path)
- "Symlink all marked files containing REGEXP to NEWNAME.
-See function `dired-rename-regexp' for more info."
- (interactive (dired-mark-read-regexp "SymLink"))
- (dired-do-create-files-regexp
- (function make-symbolic-link)
- "SymLink" arg regexp newname whole-path dired-keep-marker-symlink))
-
-(defun dired-create-files-non-directory
- (file-creator basename-constructor operation arg)
- ;; Perform FILE-CREATOR on the non-directory part of marked files
- ;; using function BASENAME-CONSTRUCTOR, with query for each file.
- ;; OPERATION like in dired-create-files, ARG as in dired-get-marked-files.
- (let (rename-non-directory-query)
- (dired-create-files
- file-creator
- operation
- (dired-get-marked-files nil arg)
- (function
- (lambda (from)
- (let ((to (concat (file-name-directory from)
- (funcall basename-constructor
- (file-name-nondirectory from)))))
- (and (let ((help-form (format "\
-Type SPC or `y' to %s one file, DEL or `n' to skip to next,
-`!' to %s all remaining matches with no more questions."
- (downcase operation)
- (downcase operation))))
- (dired-query 'rename-non-directory-query
- (concat operation " `%s' to `%s'")
- (dired-make-relative from)
- (dired-make-relative to)))
- to))))
- dired-keep-marker-rename)))
-
-(defun dired-rename-non-directory (basename-constructor operation arg)
- (dired-create-files-non-directory
- (function dired-rename-file)
- basename-constructor operation arg))
-
-;;;###autoload
-(defun dired-upcase (&optional arg)
- "Rename all marked (or next ARG) files to upper case."
- (interactive "P")
- (dired-rename-non-directory (function upcase) "Rename upcase" arg))
-
-;;;###autoload
-(defun dired-downcase (&optional arg)
- "Rename all marked (or next ARG) files to lower case."
- (interactive "P")
- (dired-rename-non-directory (function downcase) "Rename downcase" arg))
-
-;;;###end dired-re.el
-
-;;; 13K
-;;;###begin dired-ins.el
-
-;;;###autoload
-(defun dired-maybe-insert-subdir (dirname &optional
- switches no-error-if-not-dir-p)
- "Insert this subdirectory into the same dired buffer.
-If it is already present, just move to it (type \\[dired-do-redisplay] to refresh),
- else inserts it at its natural place (as `ls -lR' would have done).
-With a prefix arg, you may edit the ls switches used for this listing.
- You can add `R' to the switches to expand the whole tree starting at
- this subdirectory.
-This function takes some pains to conform to `ls -lR' output."
- (interactive
- (list (dired-get-filename)
- (if current-prefix-arg
- (read-string "Switches for listing: " dired-actual-switches))))
- (let ((opoint (point)))
- ;; We don't need a marker for opoint as the subdir is always
- ;; inserted *after* opoint.
- (setq dirname (file-name-as-directory dirname))
- (or (and (not switches)
- (dired-goto-subdir dirname))
- (dired-insert-subdir dirname switches no-error-if-not-dir-p))
- ;; Push mark so that it's easy to find back. Do this after the
- ;; insert message so that the user sees the `Mark set' message.
- (push-mark opoint)))
-
-(defun dired-insert-subdir (dirname &optional switches no-error-if-not-dir-p)
- "Insert this subdirectory into the same dired buffer.
-If it is already present, overwrites previous entry,
- else inserts it at its natural place (as `ls -lR' would have done).
-With a prefix arg, you may edit the `ls' switches used for this listing.
- You can add `R' to the switches to expand the whole tree starting at
- this subdirectory.
-This function takes some pains to conform to `ls -lR' output."
- ;; NO-ERROR-IF-NOT-DIR-P needed for special filesystems like
- ;; Prospero where dired-ls does the right thing, but
- ;; file-directory-p has not been redefined.
- (interactive
- (list (dired-get-filename)
- (if current-prefix-arg
- (read-string "Switches for listing: " dired-actual-switches))))
- (setq dirname (file-name-as-directory (expand-file-name dirname)))
- (dired-insert-subdir-validate dirname switches)
- (or no-error-if-not-dir-p
- (file-directory-p dirname)
- (error "Attempt to insert a non-directory: %s" dirname))
- (let ((elt (assoc dirname dired-subdir-alist))
- switches-have-R mark-alist case-fold-search buffer-read-only)
- ;; case-fold-search is nil now, so we can test for capital `R':
- (if (setq switches-have-R (and switches (string-match "R" switches)))
- ;; avoid duplicated subdirs
- (setq mark-alist (dired-kill-tree dirname t)))
- (if elt
- ;; If subdir is already present, remove it and remember its marks
- (setq mark-alist (nconc (dired-insert-subdir-del elt) mark-alist))
- (dired-insert-subdir-newpos dirname)) ; else compute new position
- (dired-insert-subdir-doupdate
- dirname elt (dired-insert-subdir-doinsert dirname switches))
- (if switches-have-R (dired-build-subdir-alist))
- (dired-initial-position dirname)
- (save-excursion (dired-mark-remembered mark-alist))))
-
-;; This is a separate function for dired-vms.
-(defun dired-insert-subdir-validate (dirname &optional switches)
- ;; Check that it is valid to insert DIRNAME with SWITCHES.
- ;; Signal an error if invalid (e.g. user typed `i' on `..').
- (or (dired-in-this-tree dirname (expand-file-name default-directory))
- (error "%s: not in this directory tree" dirname))
- (if switches
- (let (case-fold-search)
- (mapcar
- (function
- (lambda (x)
- (or (eq (null (string-match x switches))
- (null (string-match x dired-actual-switches)))
- (error "Can't have dirs with and without -%s switches together"
- x))))
- ;; all switches that make a difference to dired-get-filename:
- '("F" "b")))))
-
-(defun dired-alist-add (dir new-marker)
- ;; Add new DIR at NEW-MARKER. Sort alist.
- (dired-alist-add-1 dir new-marker)
- (dired-alist-sort))
-
-(defun dired-alist-sort ()
- ;; Keep the alist sorted on buffer position.
- (setq dired-subdir-alist
- (sort dired-subdir-alist
- (function (lambda (elt1 elt2)
- (> (dired-get-subdir-min elt1)
- (dired-get-subdir-min elt2)))))))
-
-(defun dired-kill-tree (dirname &optional remember-marks)
- ;;"Kill all proper subdirs of DIRNAME, excluding DIRNAME itself.
- ;; With optional arg REMEMBER-MARKS, return an alist of marked files."
- (interactive "DKill tree below directory: ")
- (setq dirname (expand-file-name dirname))
- (let ((s-alist dired-subdir-alist) dir m-alist)
- (while s-alist
- (setq dir (car (car s-alist))
- s-alist (cdr s-alist))
- (if (and (not (string-equal dir dirname))
- (dired-in-this-tree dir dirname)
- (dired-goto-subdir dir))
- (setq m-alist (nconc (dired-kill-subdir remember-marks) m-alist))))
- m-alist))
-
-(defun dired-insert-subdir-newpos (new-dir)
- ;; Find pos for new subdir, according to tree order.
- ;;(goto-char (point-max))
- (let ((alist dired-subdir-alist) elt dir pos new-pos)
- (while alist
- (setq elt (car alist)
- alist (cdr alist)
- dir (car elt)
- pos (dired-get-subdir-min elt))
- (if (dired-tree-lessp dir new-dir)
- ;; Insert NEW-DIR after DIR
- (setq new-pos (dired-get-subdir-max elt)
- alist nil)))
- (goto-char new-pos))
- ;; want a separating newline between subdirs
- (or (eobp)
- (forward-line -1))
- (insert "\n")
- (point))
-
-(defun dired-insert-subdir-del (element)
- ;; Erase an already present subdir (given by ELEMENT) from buffer.
- ;; Move to that buffer position. Return a mark-alist.
- (let ((begin-marker (dired-get-subdir-min element)))
- (goto-char begin-marker)
- ;; Are at beginning of subdir (and inside it!). Now determine its end:
- (goto-char (dired-subdir-max))
- (or (eobp);; want a separating newline _between_ subdirs:
- (forward-char -1))
- (prog1
- (dired-remember-marks begin-marker (point))
- (delete-region begin-marker (point)))))
-
-(defun dired-insert-subdir-doinsert (dirname switches)
- ;; Insert ls output after point and put point on the correct
- ;; position for the subdir alist.
- ;; Return the boundary of the inserted text (as list of BEG and END).
- (let ((begin (point)) end)
- (message "Reading directory %s..." dirname)
- (let ((dired-actual-switches
- (or switches
- (dired-replace-in-string "R" "" dired-actual-switches))))
- (if (equal dirname (car (car (reverse dired-subdir-alist))))
- ;; top level directory may contain wildcards:
- (dired-readin-insert dired-directory)
- (let ((opoint (point)))
- (insert-directory dirname dired-actual-switches nil t)
- (dired-insert-set-properties opoint (point)))))
- (message "Reading directory %s...done" dirname)
- (setq end (point-marker))
- (indent-rigidly begin end 2)
- ;; call dired-insert-headerline afterwards, as under VMS dired-ls
- ;; does insert the headerline itself and the insert function just
- ;; moves point.
- ;; Need a marker for END as this inserts text.
- (goto-char begin)
- (dired-insert-headerline dirname)
- ;; point is now like in dired-build-subdir-alist
- (prog1
- (list begin (marker-position end))
- (set-marker end nil))))
-
-(defun dired-insert-subdir-doupdate (dirname elt beg-end)
- ;; Point is at the correct subdir alist position for ELT,
- ;; BEG-END is the subdir-region (as list of begin and end).
- (if elt ; subdir was already present
- ;; update its position (should actually be unchanged)
- (set-marker (dired-get-subdir-min elt) (point-marker))
- (dired-alist-add dirname (point-marker)))
- ;; The hook may depend on the subdir-alist containing the just
- ;; inserted subdir, so run it after dired-alist-add:
- (if dired-after-readin-hook
- (save-excursion
- (let ((begin (nth 0 beg-end))
- (end (nth 1 beg-end)))
- (goto-char begin)
- (save-restriction
- (narrow-to-region begin end)
- ;; hook may add or delete lines, but the subdir boundary
- ;; marker floats
- (run-hooks 'dired-after-readin-hook))))))
-
-(defun dired-tree-lessp (dir1 dir2)
- ;; Lexicographic order on pathname components, like `ls -lR':
- ;; DIR1 < DIR2 iff DIR1 comes *before* DIR2 in an `ls -lR' listing,
- ;; i.e., iff DIR1 is a (grand)parent dir of DIR2,
- ;; or DIR1 and DIR2 are in the same parentdir and their last
- ;; components are string-lessp.
- ;; Thus ("/usr/" "/usr/bin") and ("/usr/a/" "/usr/b/") are tree-lessp.
- ;; string-lessp could arguably be replaced by file-newer-than-file-p
- ;; if dired-actual-switches contained `t'.
- (setq dir1 (file-name-as-directory dir1)
- dir2 (file-name-as-directory dir2))
- (let ((components-1 (dired-split "/" dir1))
- (components-2 (dired-split "/" dir2)))
- (while (and components-1
- components-2
- (equal (car components-1) (car components-2)))
- (setq components-1 (cdr components-1)
- components-2 (cdr components-2)))
- (let ((c1 (car components-1))
- (c2 (car components-2)))
-
- (cond ((and c1 c2)
- (string-lessp c1 c2))
- ((and (null c1) (null c2))
- nil) ; they are equal, not lessp
- ((null c1) ; c2 is a subdir of c1: c1<c2
- t)
- ((null c2) ; c1 is a subdir of c2: c1>c2
- nil)
- (t (error "This can't happen"))))))
-
-;; There should be a builtin split function - inverse to mapconcat.
-(defun dired-split (pat str &optional limit)
- "Splitting on regexp PAT, turn string STR into a list of substrings.
-Optional third arg LIMIT (>= 1) is a limit to the length of the
-resulting list.
-Thus, if SEP is a regexp that only matches itself,
-
- (mapconcat 'identity (dired-split SEP STRING) SEP)
-
-is always equal to STRING."
- (let* ((start (string-match pat str))
- (result (list (substring str 0 start)))
- (count 1)
- (end (if start (match-end 0))))
- (if end ; else nothing left
- (while (and (or (not (integerp limit))
- (< count limit))
- (string-match pat str end))
- (setq start (match-beginning 0)
- count (1+ count)
- result (cons (substring str end start) result)
- end (match-end 0)
- start end)
- ))
- (if (and (or (not (integerp limit))
- (< count limit))
- end) ; else nothing left
- (setq result
- (cons (substring str end) result)))
- (nreverse result)))
-
-;;; moving by subdirectories
-
-;;;###autoload
-(defun dired-prev-subdir (arg &optional no-error-if-not-found no-skip)
- "Go to previous subdirectory, regardless of level.
-When called interactively and not on a subdir line, go to this subdir's line."
- ;;(interactive "p")
- (interactive
- (list (if current-prefix-arg
- (prefix-numeric-value current-prefix-arg)
- ;; if on subdir start already, don't stay there!
- (if (dired-get-subdir) 1 0))))
- (dired-next-subdir (- arg) no-error-if-not-found no-skip))
-
-(defun dired-subdir-min ()
- (save-excursion
- (if (not (dired-prev-subdir 0 t t))
- (error "Not in a subdir!")
- (point))))
-
-;;;###autoload
-(defun dired-goto-subdir (dir)
- "Go to end of header line of DIR in this dired buffer.
-Return value of point on success, otherwise return nil.
-The next char is either \\n, or \\r if DIR is hidden."
- (interactive
- (prog1 ; let push-mark display its message
- (list (expand-file-name
- (completing-read "Goto in situ directory: " ; prompt
- dired-subdir-alist ; table
- nil ; predicate
- t ; require-match
- (dired-current-directory))))
- (push-mark)))
- (setq dir (file-name-as-directory dir))
- (let ((elt (assoc dir dired-subdir-alist)))
- (and elt
- (goto-char (dired-get-subdir-min elt))
- ;; dired-subdir-hidden-p and dired-add-entry depend on point being
- ;; at either \r or \n after this function succeeds.
- (progn (skip-chars-forward "^\r\n")
- (point)))))
-
-;;;###autoload
-(defun dired-mark-subdir-files ()
- "Mark all files except `.' and `..'."
- (interactive)
- (let ((p-min (dired-subdir-min)))
- (dired-mark-files-in-region p-min (dired-subdir-max))))
-
-;;;###autoload
-(defun dired-kill-subdir (&optional remember-marks)
- "Remove all lines of current subdirectory.
-Lower levels are unaffected."
- ;; With optional REMEMBER-MARKS, return a mark-alist.
- (interactive)
- (let ((beg (dired-subdir-min))
- (end (dired-subdir-max))
- buffer-read-only cur-dir)
- (setq cur-dir (dired-current-directory))
- (if (equal cur-dir default-directory)
- (error "Attempt to kill top level directory"))
- (prog1
- (if remember-marks (dired-remember-marks beg end))
- (delete-region beg end)
- (if (eobp) ; don't leave final blank line
- (delete-char -1))
- (dired-unsubdir cur-dir))))
-
-(defun dired-unsubdir (dir)
- ;; Remove DIR from the alist
- (setq dired-subdir-alist
- (delq (assoc dir dired-subdir-alist) dired-subdir-alist)))
-
-;;;###autoload
-(defun dired-tree-up (arg)
- "Go up ARG levels in the dired tree."
- (interactive "p")
- (let ((dir (dired-current-directory)))
- (while (>= arg 1)
- (setq arg (1- arg)
- dir (file-name-directory (directory-file-name dir))))
- ;;(setq dir (expand-file-name dir))
- (or (dired-goto-subdir dir)
- (error "Cannot go up to %s - not in this tree." dir))))
-
-;;;###autoload
-(defun dired-tree-down ()
- "Go down in the dired tree."
- (interactive)
- (let ((dir (dired-current-directory)) ; has slash
- pos case-fold-search) ; filenames are case sensitive
- (let ((rest (reverse dired-subdir-alist)) elt)
- (while rest
- (setq elt (car rest)
- rest (cdr rest))
- (if (dired-in-this-tree (directory-file-name (car elt)) dir)
- (setq rest nil
- pos (dired-goto-subdir (car elt))))))
- (if pos
- (goto-char pos)
- (error "At the bottom"))))
-
-;;; hiding
-
-(defun dired-unhide-subdir ()
- (let (buffer-read-only)
- (subst-char-in-region (dired-subdir-min) (dired-subdir-max) ?\r ?\n)))
-
-(defun dired-hide-check ()
- (or selective-display
- (error "selective-display must be t for subdir hiding to work!")))
-
-(defun dired-subdir-hidden-p (dir)
- (and selective-display
- (save-excursion
- (dired-goto-subdir dir)
- (looking-at "\r"))))
-
-;;;###autoload
-(defun dired-hide-subdir (arg)
- "Hide or unhide the current subdirectory and move to next directory.
-Optional prefix arg is a repeat factor.
-Use \\[dired-hide-all] to (un)hide all directories."
- (interactive "p")
- (dired-hide-check)
- (while (>= (setq arg (1- arg)) 0)
- (let* ((cur-dir (dired-current-directory))
- (hidden-p (dired-subdir-hidden-p cur-dir))
- (elt (assoc cur-dir dired-subdir-alist))
- (end-pos (1- (dired-get-subdir-max elt)))
- buffer-read-only)
- ;; keep header line visible, hide rest
- (goto-char (dired-get-subdir-min elt))
- (skip-chars-forward "^\n\r")
- (if hidden-p
- (subst-char-in-region (point) end-pos ?\r ?\n)
- (subst-char-in-region (point) end-pos ?\n ?\r)))
- (dired-next-subdir 1 t)))
-
-;;;###autoload
-(defun dired-hide-all (arg)
- "Hide all subdirectories, leaving only their header lines.
-If there is already something hidden, make everything visible again.
-Use \\[dired-hide-subdir] to (un)hide a particular subdirectory."
- (interactive "P")
- (dired-hide-check)
- (let (buffer-read-only)
- (if (save-excursion
- (goto-char (point-min))
- (search-forward "\r" nil t))
- ;; unhide - bombs on \r in filenames
- (subst-char-in-region (point-min) (point-max) ?\r ?\n)
- ;; hide
- (let ((pos (point-max)) ; pos of end of last directory
- (alist dired-subdir-alist))
- (while alist ; while there are dirs before pos
- (subst-char-in-region (dired-get-subdir-min (car alist)) ; pos of prev dir
- (save-excursion
- (goto-char pos) ; current dir
- ;; we're somewhere on current dir's line
- (forward-line -1)
- (point))
- ?\n ?\r)
- (setq pos (dired-get-subdir-min (car alist))) ; prev dir gets current dir
- (setq alist (cdr alist)))))))
-
-;;;###end dired-ins.el
-
-
-;; Functions for searching in tags style among marked files.
-
-;;;###autoload
-(defun dired-do-search (regexp)
- "Search through all marked files for a match for REGEXP.
-Stops when a match is found.
-To continue searching for next match, use command \\[tags-loop-continue]."
- (interactive "sSearch marked files (regexp): ")
- (tags-search regexp '(dired-get-marked-files)))
-
-;;;###autoload
-(defun dired-do-query-replace (from to &optional delimited)
- "Do `query-replace-regexp' of FROM with TO, on all marked files.
-Third arg DELIMITED (prefix arg) means replace only word-delimited matches.
-If you exit (\\[keyboard-quit] or ESC), you can resume the query replace
-with the command \\[tags-loop-continue]."
- (interactive
- "sQuery replace in marked files (regexp): \nsQuery replace %s by: \nP")
- (tags-query-replace from to delimited '(dired-get-marked-files)))
-
-
-(provide 'dired-aux)
-
-;;; dired-aux.el ends here
diff --git a/lisp/dired-x.el b/lisp/dired-x.el
deleted file mode 100644
index a45c9ad52df..00000000000
--- a/lisp/dired-x.el
+++ /dev/null
@@ -1,1698 +0,0 @@
-;;; dired-x.el --- Sebastian Kremer's Extra DIRED hacked up for GNU Emacs19
-
-;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
-;; Lawrence R. Dodd <dodd@roebling.poly.edu>
-;; Maintainer: Lawrence R. Dodd <dodd@roebling.poly.edu>
-;; Version: 2.37+
-;; Date: 1994/08/18 19:27:42
-;; Keywords: dired extensions
-
-;; Copyright (C) 1993, 1994 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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This is Sebastian Kremer's excellent dired-x.el (Dired Extra), version
-;; 1.191, hacked up for GNU Emacs 19. Redundant or conflicting material
-;; has been removed or renamed in order to work properly with dired of
-;; GNU Emacs 19. All suggestions or comments are most welcomed.
-
-;;
-;; Please, PLEASE, *PLEASE* see the info pages.
-;;
-
-;; BUGS: Type M-x dired-x-submit-report and a report will be generated.
-
-;; INSTALLATION: In your ~/.emacs,
-;;
-;; (add-hook 'dired-load-hook
-;; (function (lambda ()
-;; (load "dired-x")
-;; ;; Set global variables here. For example:
-;; ;; (setq dired-guess-shell-gnutar "gtar")
-;; )))
-;; (add-hook 'dired-mode-hook
-;; (function (lambda ()
-;; ;; Set buffer-local variables here. For example:
-;; ;; (setq dired-omit-files-p t)
-;; )))
-;;
-;; At load time dired-x.el will install itself, redefine some functions, and
-;; bind some dired keys. *Please* see the info pages for more details.
-
-;; CAUTION: If you are using a version of GNU Emacs earlier than 19.20 than
-;; you may have to edit dired.el. The copy of dired.el in GNU Emacs versions
-;; earlier than 19.20 incorrectly had the call to run-hooks *before* the call
-;; to provide. In such a case, it is possible that byte-compiling and/or
-;; loading dired can cause an infinite loop. To prevent this, make sure the
-;; line of code
-;;
-;; (run-hooks 'dired-load-hook)
-;;
-;; is the *last* executable line in the file dired.el. That is, make sure it
-;; comes *after* the line
-;;
-;; (provide 'dired)
-;;
-;; *Please* see the info pages for more details.
-
-;; User defined variables:
-;;
-;; dired-bind-vm
-;; dired-vm-read-only-folders
-;; dired-bind-jump
-;; dired-bind-info
-;; dired-bind-man
-;; dired-x-hands-off-my-keys
-;; dired-find-subdir
-;; dired-enable-local-variables
-;; dired-local-variables-file
-;; dired-guess-shell-gnutar
-;; dired-guess-shell-gzip-quiet
-;; dired-guess-shell-znew-switches
-;; dired-guess-shell-alist-user
-;; dired-clean-up-buffers-too
-;; dired-omit-files-p
-;; dired-omit-files
-;; dired-omit-extensions
-;; dired-omit-size-limit
-;;
-;; To find out more about these variables, load this file, put your cursor at
-;; the end of any of the variable names, and hit C-h v [RET]. *Please* see
-;; the info pages for more details.
-
-;; When loaded this code redefines the following functions of GNU Emacs
-;;
-;; Function Found in this file of GNU Emacs
-;; -------- -------------------------------
-;; dired-clean-up-after-deletion ../lisp/dired.el
-;; dired-find-buffer-nocreate ../lisp/dired.el
-;; dired-initial-position ../lisp/dired.el
-;;
-;; dired-add-entry ../lisp/dired-aux.el
-;; dired-read-shell-command ../lisp/dired-aux.el
-;;
-;; One drawback is that dired-x.el will load dired-aux.el as soon as dired is
-;; loaded. Thus, the advantage of separating out non-essential dired stuff
-;; into dired-aux.el and only loading when necessary will be lost. Please
-;; note also that some of the comments in dired.el and dired-aux.el are
-;; Kremer's that referred to the old dired-x.el. This now should be referring
-;; to this program. (This is also a good reason to call this dired-x.el
-;; instead of dired-x19.el.)
-
-
-;;; Code:
-
-;; LOAD.
-
-;; This is a no-op if dired-x is being loaded via `dired-load-hook'. It is
-;; here in case the user has autoloaded dired-x via the dired-jump key binding
-;; (instead of autoloading to dired as is suggested in the info-pages).
-
-(require 'dired)
-
-;; We will redefine some functions and also need some macros so we need to
-;; load dired stuff of GNU Emacs.
-
-(require 'dired-aux)
-
-;;; User-defined variables.
-
-(defvar dired-bind-vm nil
- "*t says \"V\" in dired-mode will `dired-vm', otherwise \"V\" is `dired-rmail'.
-Also, RMAIL files contain -*- rmail -*- at the top so \"f\",
-`dired-advertised-find-file', will run rmail.")
-
-(defvar dired-bind-jump t
- "*t says bind `dired-jump' to C-x C-j, otherwise do not.")
-
-(defvar dired-bind-man t
- "*t says bind `dired-man' to \"N\" in dired-mode, otherwise do not.")
-
-(defvar dired-bind-info t
- "*t says bind `dired-info' to \"I\" in dired-mode, otherwise do not.")
-
-(defvar dired-vm-read-only-folders nil
- "*If t, \\[dired-vm] will visit all folders read-only.
-If neither nil nor t, e.g. the symbol `if-file-read-only', only
-files not writable by you are visited read-only.
-
-Read-only folders only work in VM 5, not in VM 4.")
-
-(defvar dired-omit-files-p nil
- "*If non-nil, \"uninteresting\" files are not listed (buffer-local).
-Use \\[dired-omit-toggle] to toggle its value.
-Uninteresting files are those whose filenames match regexp `dired-omit-files',
-plus those ending with extensions in `dired-omit-extensions'.")
-(make-variable-buffer-local 'dired-omit-files-p)
-
-(defvar dired-omit-files "^#\\|^\\.$\\|^\\.\\.$"
- "*Filenames matching this regexp will not be displayed.
-This only has effect when `dired-omit-files-p' is t. See interactive function
-`dired-omit-toggle' \(\\[dired-omit-toggle]\) and variable
-`dired-omit-extensions'. The default is to omit `.', `..', and auto-save
-files.")
-
-(defvar dired-omit-size-limit 20000
- "*If a dired buffer listing contains more than this many characters,
-do not do omitting. If nil, always do omitting.")
-
-(defvar dired-find-subdir nil ; t is pretty near to DWIM...
- "*If non-nil, Dired always finds a directory in a buffer of its own.
-If nil, Dired finds the directory as a subdirectory in some other buffer
-if it is present as one.
-
-If there are several Dired buffers for a directory, the most recently
-used is chosen.
-
-Dired avoids switching to the current buffer, so that if you have
-a normal and a wildcard buffer for the same directory, C-x d RET will
-toggle between those two.")
-
-(defvar dired-enable-local-variables t
- "*Control use of local-variables lists in dired.
-The value can be t, nil or something else.
-A value of t means local-variables lists are obeyed;
-nil means they are ignored; anything else means query.
-
-This temporarily overrides the value of `enable-local-variables' when listing
-a directory. See also `dired-local-variables-file'.")
-
-(defvar dired-guess-shell-gnutar nil
- "*If non-nil, name of GNU tar executable (e.g., \"tar\" or \"gtar\") and `z'
-switch will be used for compressed or gzip'ed tar files. If no GNU tar, set
-to nil: a pipe using `zcat' or `gunzip -c' will be used.")
-
-(defvar dired-guess-shell-gzip-quiet t
- "*non-nil says pass -q to gzip overriding verbose GZIP environment.")
-
-(defvar dired-guess-shell-znew-switches nil
- "*If non-nil, then string of switches passed to `znew', example: \"-K\"")
-
-(defvar dired-clean-up-buffers-too t
- "*t says offer to kill buffers visiting files and dirs deleted in dired.")
-
-;;; KEY BINDINGS.
-
-(define-key dired-mode-map "\M-o" 'dired-omit-toggle)
-(define-key dired-mode-map "\M-(" 'dired-mark-sexp)
-(define-key dired-mode-map "*(" 'dired-mark-sexp)
-(define-key dired-mode-map "*." 'dired-mark-extension)
-(define-key dired-mode-map "\M-!" 'dired-smart-shell-command)
-(define-key dired-mode-map "T" 'dired-do-toggle)
-(define-key dired-mode-map "*t" 'dired-do-toggle)
-(define-key dired-mode-map "w" 'dired-copy-filename-as-kill)
-(define-key dired-mode-map "\M-g" 'dired-goto-file)
-(define-key dired-mode-map "\M-G" 'dired-goto-subdir)
-(define-key dired-mode-map "F" 'dired-do-find-marked-files)
-(define-key dired-mode-map "Y" 'dired-do-relsymlink)
-(define-key dired-mode-map "%Y" 'dired-do-relsymlink-regexp)
-(define-key dired-mode-map "V" 'dired-do-run-mail)
-
-(if dired-bind-man
- (define-key dired-mode-map "N" 'dired-man))
-
-(if dired-bind-info
- (define-key dired-mode-map "I" 'dired-info))
-
-;;; GLOBAL BINDING.
-(if dired-bind-jump
- (progn
- (define-key global-map "\C-x\C-j" 'dired-jump)
- (define-key global-map "\C-x4\C-j" 'dired-jump-other-window)))
-
-
-;;; Install into appropriate hooks.
-
-(add-hook 'dired-mode-hook 'dired-extra-startup)
-(add-hook 'dired-after-readin-hook 'dired-omit-expunge)
-
-(defun dired-extra-startup ()
- "Automatically put on dired-mode-hook to get extra dired features:
-\\<dired-mode-map>
-
- \\[dired-do-run-mail]\t-- run mail on folder (see `dired-bind-vm')
- \\[dired-info]\t-- run info on file
- \\[dired-man]\t-- run man on file
- \\[dired-do-find-marked-files]\t-- visit all marked files simultaneously
- \\[dired-omit-toggle]\t-- toggle omitting of files
- \\[dired-do-toggle]\t-- toggle marks
- \\[dired-mark-sexp]\t-- mark by lisp expression
- \\[dired-copy-filename-as-kill]\t-- copy the file or subdir names into the kill ring.
- \t You can feed it to other commands using \\[yank].
-
-For more features, see variables
-
- dired-bind-vm
- dired-bind-jump
- dired-bind-info
- dired-bind-man
- dired-vm-read-only-folders
- dired-omit-files-p
- dired-omit-files
- dired-omit-extensions
- dired-omit-size-limit
- dired-find-subdir
- dired-enable-local-variables
- dired-local-variables-file
- dired-guess-shell-gnutar
- dired-guess-shell-gzip-quiet
- dired-guess-shell-znew-switches
- dired-guess-shell-alist-user
- dired-clean-up-buffers-too
-
-See also functions
-
- dired-flag-extension
- dired-virtual
- dired-jump
- dired-man
- dired-vm
- dired-rmail
- dired-info
- dired-do-find-marked-files
-"
- (interactive)
-
- ;; These must be done in each new dired buffer.
- (dired-hack-local-variables)
- (dired-omit-startup))
-
-
-;;; BUFFER CLEANING.
-
-;; REDEFINE.
-(defun dired-clean-up-after-deletion (fn)
-
- ;; Clean up after a deleted file or directory FN.
- ;; Remove expanded subdir of deleted dir, if any.
- (save-excursion (and (cdr dired-subdir-alist)
- (dired-goto-subdir fn)
- (dired-kill-subdir)))
-
- ;; Offer to kill buffer of deleted file FN.
- (if dired-clean-up-buffers-too
- (progn
- (let ((buf (get-file-buffer fn)))
- (and buf
- (funcall (function y-or-n-p)
- (format "Kill buffer of %s, too? "
- (file-name-nondirectory fn)))
- (save-excursion ; you never know where kill-buffer leaves you
- (kill-buffer buf))))
- (let ((buf-list (dired-buffers-for-dir (expand-file-name fn)))
- (buf nil))
- (and buf-list
- (y-or-n-p (format "Kill dired buffer%s of %s, too? "
- (dired-plural-s (length buf-list))
- (file-name-nondirectory fn)))
- (while buf-list
- (save-excursion (kill-buffer (car buf-list)))
- (setq buf-list (cdr buf-list)))))))
- ;; Anything else?
- )
-
-
-;;; EXTENSION MARKING FUNCTIONS.
-
-;;; Mark files with some extension.
-(defun dired-mark-extension (extension &optional marker-char)
- "Mark all files with a certain extension for use in later commands.
-A `.' is not automatically prepended to the string entered."
- ;; EXTENSION may also be a list of extensions instead of a single one.
- ;; Optional MARKER-CHAR is marker to use.
- (interactive "sMarking extension: \nP")
- (or (listp extension)
- (setq extension (list extension)))
- (dired-mark-files-regexp
- (concat ".";; don't match names with nothing but an extension
- "\\("
- (mapconcat 'regexp-quote extension "\\|")
- "\\)$")
- marker-char))
-
-(defun dired-flag-extension (extension)
- "In dired, flag all files with a certain extension for deletion.
-A `.' is *not* automatically prepended to the string entered."
- (interactive "sFlagging extension: ")
- (dired-mark-extension extension dired-del-marker))
-
-;;; Define some unpopular file extensions. Used for cleaning and omitting.
-
-(defvar dired-patch-unclean-extensions
- '(".rej" ".orig")
- "List of extensions of dispensable files created by the `patch' program.")
-
-(defvar dired-tex-unclean-extensions
- '(".toc" ".log" ".aux");; these are already in completion-ignored-extensions
- "List of extensions of dispensable files created by TeX.")
-
-(defvar dired-latex-unclean-extensions
- '(".idx" ".lof" ".lot" ".glo")
- "List of extensions of dispensable files created by LaTeX.")
-
-(defvar dired-bibtex-unclean-extensions
- '(".blg" ".bbl")
- "List of extensions of dispensable files created by BibTeX.")
-
-(defvar dired-texinfo-unclean-extensions
- '(".cp" ".cps" ".fn" ".fns" ".ky" ".kys" ".pg" ".pgs"
- ".tp" ".tps" ".vr" ".vrs")
- "List of extensions of dispensable files created by texinfo.")
-
-(defun dired-clean-patch ()
- "Flag dispensable files created by patch for deletion.
-See variable `dired-patch-unclean-extensions'."
- (interactive)
- (dired-flag-extension dired-patch-unclean-extensions))
-
-(defun dired-clean-tex ()
- "Flag dispensable files created by [La]TeX etc. for deletion.
-See variables `dired-texinfo-unclean-extensions',
-`dired-latex-unclean-extensions', `dired-bibtex-unclean-extensions' and
-`dired-texinfo-unclean-extensions'."
- (interactive)
- (dired-flag-extension (append dired-texinfo-unclean-extensions
- dired-latex-unclean-extensions
- dired-bibtex-unclean-extensions
- dired-tex-unclean-extensions)))
-
-(defun dired-very-clean-tex ()
- "Flag dispensable files created by [La]TeX *and* \".dvi\" for deletion.
-See variables `dired-texinfo-unclean-extensions',
-`dired-latex-unclean-extensions', `dired-bibtex-unclean-extensions' and
-`dired-texinfo-unclean-extensions'."
- (interactive)
- (dired-flag-extension (append dired-texinfo-unclean-extensions
- dired-latex-unclean-extensions
- dired-bibtex-unclean-extensions
- dired-tex-unclean-extensions
- (list ".dvi"))))
-
-;;; JUMP.
-
-;;;###autoload
-(defun dired-jump (&optional other-window)
- "Jump to dired buffer corresponding to current buffer.
-If in a file, dired the current directory and move to file's line.
-If in dired already, pop up a level and goto old directory's line.
-In case the proper dired file line cannot be found, refresh the dired
-buffer and try again."
- (interactive "P")
- (let* ((file buffer-file-name)
- (dir (if file (file-name-directory file) default-directory)))
- (if (eq major-mode 'dired-mode)
- (progn
- (setq dir (dired-current-directory))
- (dired-up-directory other-window)
- (or (dired-goto-file dir)
- ;; refresh and try again
- (progn
- (dired-insert-subdir (file-name-directory dir))
- (dired-goto-file dir))))
- (if other-window
- (dired-other-window dir)
- (dired dir))
- (if file
- (or (dired-goto-file file)
- ;; refresh and try again
- (progn
- (dired-insert-subdir (file-name-directory file))
- (dired-goto-file file))
- ;; Toggle omitting, if it is on, and try again.
- (if dired-omit-files-p
- (progn
- (dired-omit-toggle)
- (dired-goto-file file))))))))
-
-(defun dired-jump-other-window ()
- "Like \\[dired-jump] (dired-jump) but in other window."
- (interactive)
- (dired-jump t))
-
-;;; TOGGLE.
-;;; Toggle marked files with unmarked files.
-
-(defun dired-do-toggle ()
- "Toggle marks.
-That is, currently marked files become unmarked and vice versa.
-Files marked with other flags (such as `D') are not affected.
-`.' and `..' are never toggled.
-As always, hidden subdirs are not affected."
- (interactive)
- (save-excursion
- (goto-char (point-min))
- (let (buffer-read-only)
- (while (not (eobp))
- (or (dired-between-files)
- (looking-at dired-re-dot)
- ;; use subst instead of insdel because it does not move
- ;; the gap and thus should be faster and because
- ;; other characters are left alone automatically
- (apply 'subst-char-in-region
- (point) (1+ (point))
- (if (eq ?\040 (following-char)) ; SPC
- (list ?\040 dired-marker-char)
- (list dired-marker-char ?\040))))
- (forward-line 1)))))
-
-
-;;; COPY NAMES OF MARKED FILES INTO KILL-RING.
-
-(defun dired-copy-filename-as-kill (&optional arg)
- "Copy names of marked (or next ARG) files into the kill ring.
-The names are separated by a space.
-With a zero prefix arg, use the complete pathname of each marked file.
-With \\[universal-argument], use the relative pathname of each marked file.
-
-If on a subdir headerline, use subdirname instead; prefix arg is ignored
-in this case.
-
-You can then feed the file name(s) to other commands with \\[yank]."
- (interactive "P")
- (let ((string
- (or (dired-get-subdir)
- (mapconcat (function identity)
- (if arg
- (cond ((zerop (prefix-numeric-value arg))
- (dired-get-marked-files))
- ((integerp arg)
- (dired-get-marked-files 'no-dir arg))
- (t ; else a raw arg
- (dired-get-marked-files t)))
- (dired-get-marked-files 'no-dir))
- " "))))
- (kill-new string)
- (message "%s" string)))
-
-
-;;; OMITTING.
-
-;;; Enhanced omitting of lines from directory listings.
-;;; Marked files are never omitted.
-
-;; should probably get rid of this and always use 'no-dir.
-;; sk 28-Aug-1991 09:37
-(defvar dired-omit-localp 'no-dir
- "The LOCALP argument dired-omit-expunge passes to dired-get-filename.
-If it is 'no-dir, omitting is much faster, but you can only match
-against the basename of the file. Set it to nil if you need to match the
-whole pathname.")
-
-;; \017=^O for Omit - other packages can chose other control characters.
-(defvar dired-omit-marker-char ?\017
- "Temporary marker used by by dired-omit.
-Should never be used as marker by the user or other packages.")
-
-(defun dired-omit-startup ()
- (or (assq 'dired-omit-files-p minor-mode-alist)
- (setq minor-mode-alist
- (append '((dired-omit-files-p " Omit")) minor-mode-alist))))
-
-(defun dired-omit-toggle (&optional flag)
- "Toggle omitting files matching `dired-omit-files' and `dired-omit-extensions'.
-With an arg, and if omitting was off, don't toggle and just mark the
- files but don't actually omit them.
-With an arg, and if omitting was on, turn it off but don't refresh the buffer."
- (interactive "P")
- (if flag
- (if dired-omit-files-p
- (setq dired-omit-files-p (not dired-omit-files-p))
- (dired-mark-unmarked-files (dired-omit-regexp) nil nil
- dired-omit-localp))
- ;; no FLAG
- (setq dired-omit-files-p (not dired-omit-files-p))
- (if (not dired-omit-files-p)
- (revert-buffer)
- ;; this will mention how many were omitted:
- (let ((dired-omit-size-limit nil))
- (dired-omit-expunge)))))
-
-(defvar dired-omit-extensions
- (append completion-ignored-extensions
- dired-latex-unclean-extensions
- dired-bibtex-unclean-extensions
- dired-texinfo-unclean-extensions)
- "If non-nil, a list of extensions \(strings\) to omit from Dired listings.
-Defaults to elements of `completion-ignored-extensions',
-`dired-latex-unclean-extensions', `dired-bibtex-unclean-extensions', and
-`dired-texinfo-unclean-extensions'.
-
-See interactive function `dired-omit-toggle' \(\\[dired-omit-toggle]\) and
-variables `dired-omit-files-p' and `dired-omit-files'.")
-
-(defun dired-omit-expunge (&optional regexp)
- "Erases all unmarked files matching REGEXP.
-Does nothing if global variable `dired-omit-files-p' is nil, or if called
- non-interactively and buffer is bigger than `dired-omit-size-limit'.
-If REGEXP is nil or not specified, uses `dired-omit-files', and also omits
- filenames ending in `dired-omit-extensions'.
-If REGEXP is the empty string, this function is a no-op.
-
-This functions works by temporarily binding `dired-marker-char' to
-`dired-omit-marker-char' and calling `dired-do-kill-lines'."
- (interactive "sOmit files (regexp): ")
- (if (and dired-omit-files-p
- (or (interactive-p)
- (not dired-omit-size-limit)
- (< (buffer-size) dired-omit-size-limit)))
- (let ((omit-re (or regexp (dired-omit-regexp)))
- (old-modified-p (buffer-modified-p))
- count)
- (or (string= omit-re "")
- (let ((dired-marker-char dired-omit-marker-char))
- (message "Omitting...")
- (if (dired-mark-unmarked-files omit-re nil nil dired-omit-localp)
- (progn
- (setq count (dired-do-kill-lines nil "Omitted %d line%s."))
- (force-mode-line-update))
- (message "(Nothing to omit)"))))
- ;; Try to preserve modified state of buffer. So `%*' doesn't appear
- ;; in mode-line of omitted buffers.
- (set-buffer-modified-p (and old-modified-p
- (save-excursion
- (goto-char (point-min))
- (re-search-forward dired-re-mark nil t))))
- count)))
-
-(defun dired-omit-regexp ()
- (concat (if dired-omit-files (concat "\\(" dired-omit-files "\\)") "")
- (if (and dired-omit-files dired-omit-extensions) "\\|" "")
- (if dired-omit-extensions
- (concat ".";; a non-extension part should exist
- "\\("
- (mapconcat 'regexp-quote dired-omit-extensions "\\|")
- "\\)$")
- "")))
-
-;; Returns t if any work was done, nil otherwise.
-(defun dired-mark-unmarked-files (regexp msg &optional unflag-p localp)
- "Marks unmarked files matching REGEXP, displaying MSG.
-REGEXP is matched against the complete pathname.
-Does not re-mark files which already have a mark.
-With prefix argument, unflag all those files.
-Second optional argument LOCALP is as in `dired-get-filename'."
- (interactive "P")
- (let ((dired-marker-char (if unflag-p ?\ dired-marker-char)))
- (dired-mark-if
- (and
- ;; not already marked
- (looking-at " ")
- ;; uninteresting
- (let ((fn (dired-get-filename localp t)))
- (and fn (string-match regexp fn))))
- msg)))
-
-;;; REDEFINE.
-(defun dired-omit-new-add-entry (filename &optional marker-char)
- ;; This redefines dired-aux.el's dired-add-entry to avoid calling ls for
- ;; files that are going to be omitted anyway.
- (if dired-omit-files-p
- ;; perhaps return t without calling ls
- (let ((omit-re (dired-omit-regexp)))
- (if (or (string= omit-re "")
- (not
- (string-match omit-re
- (cond
- ((eq 'no-dir dired-omit-localp)
- filename)
- ((eq t dired-omit-localp)
- (dired-make-relative filename))
- (t
- (dired-make-absolute
- filename
- (file-name-directory filename)))))))
- ;; if it didn't match, go ahead and add the entry
- (dired-omit-old-add-entry filename marker-char)
- ;; dired-add-entry returns t for success, perhaps we should
- ;; return file-exists-p
- t))
- ;; omitting is not turned on at all
- (dired-omit-old-add-entry filename marker-char)))
-
-;;; REDEFINE.
-;;; Redefine dired-aux.el's version of `dired-add-entry'
-;;; Save old defun if not already done:
-(or (fboundp 'dired-omit-old-add-entry)
- (fset 'dired-omit-old-add-entry (symbol-function 'dired-add-entry)))
-;; Redefine it.
-(fset 'dired-add-entry 'dired-omit-new-add-entry)
-
-
-;;; VIRTUAL DIRED MODE.
-
-;;; For browsing `ls -lR' listings in a dired-like fashion.
-
-(fset 'virtual-dired 'dired-virtual)
-(defun dired-virtual (dirname &optional switches)
- "Put this buffer into Virtual Dired mode.
-
-In Virtual Dired mode, all commands that do not actually consult the
-filesystem will work.
-
-This is useful if you want to peruse and move around in an ls -lR
-output file, for example one you got from an ftp server. With
-ange-ftp, you can even dired a directory containing an ls-lR file,
-visit that file and turn on virtual dired mode. But don't try to save
-this file, as dired-virtual indents the listing and thus changes the
-buffer.
-
-If you have save a Dired buffer in a file you can use \\[dired-virtual] to
-resume it in a later session.
-
-Type \\<dired-mode-map>\\[revert-buffer] in the
-Virtual Dired buffer and answer `y' to convert the virtual to a real
-dired buffer again. You don't have to do this, though: you can relist
-single subdirs using \\[dired-do-redisplay].
-"
-
- ;; DIRNAME is the top level directory of the buffer. It will become
- ;; its `default-directory'. If nil, the old value of
- ;; default-directory is used.
-
- ;; Optional SWITCHES are the ls switches to use.
-
- ;; Shell wildcards will be used if there already is a `wildcard'
- ;; line in the buffer (thus it is a saved Dired buffer), but there
- ;; is no other way to get wildcards. Insert a `wildcard' line by
- ;; hand if you want them.
-
- (interactive
- (list (read-string "Virtual Dired directory: " (dired-virtual-guess-dir))))
- (goto-char (point-min))
- (or (looking-at " ")
- ;; if not already indented, do it now:
- (indent-region (point-min) (point-max) 2))
- (or dirname (setq dirname default-directory))
- (setq dirname (expand-file-name (file-name-as-directory dirname)))
- (setq default-directory dirname) ; contains no wildcards
- (let ((wildcard (save-excursion
- (goto-char (point-min))
- (forward-line 1)
- (and (looking-at "^ wildcard ")
- (buffer-substring (match-end 0)
- (progn (end-of-line) (point)))))))
- (if wildcard
- (setq dirname (expand-file-name wildcard default-directory))))
- ;; If raw ls listing (not a saved old dired buffer), give it a
- ;; decent subdir headerline:
- (goto-char (point-min))
- (or (looking-at dired-subdir-regexp)
- (dired-insert-headerline default-directory))
- (dired-mode dirname (or switches dired-listing-switches))
- (setq mode-name "Virtual Dired"
- revert-buffer-function 'dired-virtual-revert)
- (set (make-local-variable 'dired-subdir-alist) nil)
- (dired-build-subdir-alist)
- (goto-char (point-min))
- (dired-initial-position dirname))
-
-(defun dired-virtual-guess-dir ()
-
- ;; Guess and return appropriate working directory of this buffer,
- ;; assumed to be in Dired or ls -lR format.
- ;; The guess is based upon buffer contents.
- ;; If nothing could be guessed, returns nil.
-
- (let ((regexp "^\\( \\)?\\([^ \n\r]*\\)\\(:\\)[\n\r]")
- (subexpr 2))
- (goto-char (point-min))
- (cond ((looking-at regexp)
- ;; If a saved dired buffer, look to which dir and
- ;; perhaps wildcard it belongs:
- (let ((dir (buffer-substring (match-beginning subexpr)
- (match-end subexpr))))
- (file-name-as-directory dir)))
- ;; Else no match for headerline found. It's a raw ls listing.
- ;; In raw ls listings the directory does not have a headerline
- ;; try parent of first subdir, if any
- ((re-search-forward regexp nil t)
- (file-name-directory
- (directory-file-name
- (file-name-as-directory
- (buffer-substring (match-beginning subexpr)
- (match-end subexpr))))))
- (t ; if all else fails
- nil))))
-
-
-(defun dired-virtual-revert (&optional arg noconfirm)
- (if (not
- (y-or-n-p "Cannot revert a Virtual Dired buffer - switch to Real Dired mode? "))
- (error "Cannot revert a Virtual Dired buffer.")
- (setq mode-name "Dired"
- revert-buffer-function 'dired-revert)
- (revert-buffer)))
-
-;; A zero-arg version of dired-virtual.
-;; You need my modified version of set-auto-mode for the
-;; `buffer-contents-mode-alist'.
-;; Or you use infer-mode.el and infer-mode-alist, same syntax.
-(defun dired-virtual-mode ()
- "Put current buffer into virtual dired mode (see `dired-virtual').
-Useful on `buffer-contents-mode-alist' (which see) with the regexp
-
- \"^ \\(/[^ /]+\\)/?+:$\"
-
-to put saved dired buffers automatically into virtual dired mode.
-
-Also useful for `auto-mode-alist' (which see) like this:
-
- \(setq auto-mode-alist (cons '(\"[^/]\\.dired\\'\" . dired-virtual-mode)
- auto-mode-alist)\)"
- (interactive)
- (dired-virtual (dired-virtual-guess-dir)))
-
-
-;;; SMART SHELL.
-
-;;; An Emacs buffer can have but one working directory, stored in the
-;;; buffer-local variable `default-directory'. A Dired buffer may have
-;;; several subdirectories inserted, but still has but one working directory:
-;;; that of the top level Dired directory in that buffer. For some commands
-;;; it is appropriate that they use the current Dired directory instead of
-;;; `default-directory', e.g., `find-file' and `compile'. This is a general
-;;; mechanism is provided for special handling of the working directory in
-;;; special major modes.
-
-;; It's easier to add to this alist than redefine function
-;; default-directory while keeping the old information.
-(defconst default-directory-alist
- '((dired-mode . (if (fboundp 'dired-current-directory)
- (dired-current-directory)
- default-directory)))
- "Alist of major modes and their opinion on default-directory, as a
-lisp expression to evaluate. A resulting value of nil is ignored in
-favor of default-directory.")
-
-(defun default-directory ()
- "Usage like variable `default-directory', but knows about the special
-cases in variable `default-directory-alist' (which see)."
- (or (eval (cdr (assq major-mode default-directory-alist)))
- default-directory))
-
-(defun dired-smart-shell-command (cmd &optional insert)
- "Like function `shell-command', but in the current Tree Dired directory."
- (interactive "sShell command: \nP")
- (let ((default-directory (default-directory)))
- (shell-command cmd insert)))
-
-
-;;; LOCAL VARIABLES FOR DIRED BUFFERS.
-
-;;; Brief Description:
-;;;
-;;; * `dired-extra-startup' is part of the `dired-mode-hook'.
-;;;
-;;; * `dired-extra-startup' calls `dired-hack-local-variables'
-;;;
-;;; * `dired-hack-local-variables' checks the value of
-;;; `dired-local-variables-file'
-;;;
-;;; * Check if `dired-local-variables-file' is a non-nil string and is a
-;;; filename found in the directory of the Dired Buffer being created.
-;;;
-;;; * If `dired-local-variables-file' satisfies the above, then temporarily
-;;; include it in the Dired Buffer at the bottom.
-;;;
-;;; * Set `enable-local-variables' temporarily to the user variable
-;;; `dired-enable-local-variables' and run `hack-local-variables' on the
-;;; Dired Buffer.
-
-(defvar dired-local-variables-file (convert-standard-filename ".dired")
- "Filename, as string, containing local dired buffer variables to be hacked.
-If this file found in current directory, then it will be inserted into dired
-buffer and `hack-local-variables' will be run. See Emacs Info pages for more
-information on local variables. See also `dired-enable-local-variables'.")
-
-(defun dired-hack-local-variables ()
- "Evaluate local variables in `dired-local-variables-file' for dired buffer."
- (if (and dired-local-variables-file
- (stringp dired-local-variables-file)
- (file-exists-p dired-local-variables-file))
- (let ((opoint (point-max))
- buffer-read-only
- ;; In case user has `enable-local-variables' set to nil we
- ;; override it locally with dired's variable.
- (enable-local-variables dired-enable-local-variables))
- ;; Insert 'em.
- (save-excursion
- (goto-char opoint)
- (insert "\^L\n")
- (insert-file-contents dired-local-variables-file))
- ;; Hack 'em.
- (let ((buffer-file-name dired-local-variables-file))
- (hack-local-variables))
- ;; Make sure that the modeline shows the proper information.
- (dired-sort-set-modeline)
- ;; Delete this stuff: `eobp' is used to find last subdir by dired.el.
- (delete-region opoint (point-max)))))
-
-(defun dired-omit-here-always ()
- "Creates `dired-local-variables-file' for omitting and reverts directory.
-Sets dired-omit-file-p to t in a local variables file that is readable by
-dired."
- (interactive)
- (if (file-exists-p dired-local-variables-file)
- (message "File `./%s' already exists." dired-local-variables-file)
-
- ;; Create `dired-local-variables-file'.
- (save-excursion
- (set-buffer (get-buffer-create " *dot-dired*"))
- (erase-buffer)
- (insert "Local Variables:\ndired-omit-files-p: t\nEnd:\n")
- (write-file dired-local-variables-file)
- (kill-buffer (current-buffer)))
-
- ;; Run extra-hooks and revert directory.
- (dired-extra-startup)
- (dired-revert)))
-
-
-;;; GUESS SHELL COMMAND.
-
-;;; Brief Description:
-;;;
-;;; `dired-do-shell-command' is bound to `!' by dired.el.
-;;;
-;;; * Redefine `dired-do-shell-command' so it calls
-;;; `dired-guess-shell-command'.
-;;;
-;;; * `dired-guess-shell-command' calls `dired-guess-default' with list of
-;;; marked files.
-;;;
-;;; * Parse `dired-guess-shell-alist-user' and
-;;; `dired-guess-shell-alist-default' (in that order) for the first REGEXP
-;;; that matches the first file in the file list.
-;;;
-;;; * If the REGEXP matches all the entries of the file list then evaluate
-;;; COMMAND, which is either a string or a Lisp expression returning a
-;;; string. COMMAND may be a list of commands.
-;;;
-;;; * Return this command to `dired-guess-shell-command' which prompts user
-;;; with it. The list of commands is temporarily put into the history list.
-;;; If a command is used successfully then it is stored permanently in
-;;; `dired-shell-command-history'.
-
-;;; Guess what shell command to apply to a file.
-(defvar dired-shell-command-history nil
- "History list for commands that read dired-shell commands.")
-
-;;; Default list of shell commands.
-
-;;; NOTE: Use `gunzip -c' instead of `zcat' on `.gz' files. Some do not
-;;; install GNU zip's version of zcat.
-
-(defvar dired-guess-shell-alist-default
- (list
- (list "\\.tar$" '(if dired-guess-shell-gnutar
- (concat dired-guess-shell-gnutar " xvf")
- "tar xvf"))
-
- ;; REGEXPS for compressed archives must come before the .Z rule to
- ;; be recognized:
- (list "\\.tar\\.Z$"
- ;; Untar it.
- '(if dired-guess-shell-gnutar
- (concat dired-guess-shell-gnutar " zxvf")
- (concat "zcat * | tar xvf -"))
- ;; Optional conversion to gzip format.
- '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
- " " dired-guess-shell-znew-switches))
-
- ;; gzip'ed archives
- (list "\\.tar\\.g?z$"
- '(if dired-guess-shell-gnutar
- (concat dired-guess-shell-gnutar " zxvf")
- (concat "gunzip -qc * | tar xvf -"))
- ;; Optional decompression.
- '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q" "")))
-
- '("\\.shar.Z$" "zcat * | unshar")
- '("\\.shar.g?z$" "gunzip -qc * | unshar")
-
- '("\\.ps$" "ghostview" "xv" "lpr")
- (list "\\.ps.g?z$" "gunzip -qc * | ghostview -"
- ;; Optional decompression.
- '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
- (list "\\.ps.Z$" "zcat * | ghostview -"
- ;; Optional conversion to gzip format.
- '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
- " " dired-guess-shell-znew-switches))
- '("\\.patch$" "cat * | patch")
- '("\\.patch.g?z$" "gunzip -qc * | patch")
- (list "\\.patch.Z$" "zcat * | patch"
- ;; Optional conversion to gzip format.
- '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
- " " dired-guess-shell-znew-switches))
-
- '("\\.dvi$" "xdvi" "dvips") ; preview and printing
- '("\\.au$" "play") ; play Sun audiofiles
- '("\\.mpg$" "mpeg_play")
- '("\\.uu$" "uudecode") ; for uudecoded files
- '("\\.hqx$" "mcvert")
- '("\\.sh$" "sh") ; execute shell scripts
- '("\\.xbm$" "bitmap") ; view X11 bitmaps
- '("\\.gp$" "gnuplot")
- '("\\.p[bgpn]m$" "xv")
- '("\\.gif$" "xv") ; view gif pictures
- '("\\.tif$" "xv")
- '("\\.jpg$" "xv")
- '("\\.fig$" "xfig") ; edit fig pictures
- '("\\.out$" "xgraph") ; for plotting purposes.
- '("\\.tex$" "latex" "tex")
- '("\\.texi\\(nfo\\)?$" "makeinfo" "texi2dvi")
-
- ;; Some other popular archivers.
- '("\\.zoo$" "zoo x//")
- '("\\.zip$" "unzip")
- '("\\.lzh$" "lharc x")
- '("\\.arc$" "arc x")
- '("\\.shar$" "unshar")
-
- ;; Compression.
- (list "\\.g?z$" '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
- (list "\\.Z$" "uncompress"
- ;; Optional conversion to gzip format.
- '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
- " " dired-guess-shell-znew-switches))
- )
-
- "Default alist used for shell command guessing.
-See `dired-guess-shell-alist-user'")
-
-(defvar dired-guess-shell-alist-user nil
- "User-defined alist of rules for suggested commands. These rules take
-precedence over the predefined rules in the variable
-`dired-guess-shell-alist-default' (to which they are prepended).
-
-Each element of this list looks like
-
- \(REGEXP COMMAND...\)
-
-where each COMMAND can either be a string or a lisp expression that evaluates
-to a string. If several COMMANDs are given, the first one will be the default
-and the rest will be added temporarily to the history and can be retrieved
-with \\[previous-history-element] (M-p) .
-
-You can set this variable in your ~/.emacs. For example, to add rules for
-`.foo' and `.bar' files, write
-
- \(setq dired-guess-shell-alist-user
- (list (list \"\\\\.foo$\" \"FOO-COMMAND\");; fixed rule
- ;; possibly more rules ...
- (list \"\\\\.bar$\";; rule with condition test
- '(if condition
- \"BAR-COMMAND-1\"
- \"BAR-COMMAND-2\")))\)
-")
-
-(defun dired-guess-default (files)
-
- ;; Guess a shell commands for FILES. Return command or list of commands.
- ;; See `dired-guess-shell-alist-user'.
-
- (let* ((case-fold-search nil) ; case-sensitive matching
- ;; Prepend the user's alist to the default alist.
- (alist (append dired-guess-shell-alist-user
- dired-guess-shell-alist-default))
- (file (car files))
- (flist (cdr files))
- elt regexp cmds)
-
- ;; Find the first match in the alist for first file in FILES.
- (while alist
- (setq elt (car alist)
- regexp (car elt)
- alist (cdr alist))
- (if (string-match regexp file)
- (setq cmds (cdr elt)
- alist nil)))
-
- ;; If more than one file, see if all of FILES match regular expression.
- (while (and flist
- (string-match regexp (car flist)))
- (setq flist (cdr flist)))
-
- ;; If flist is still non-nil, then do not guess since this means that not
- ;; all the files in FILES were matched by the regexp.
- (setq cmds (and (not flist) cmds))
-
- ;; Return commands or nil if flist is still non-nil.
- ;; Evaluate the commands in order that any logical testing will be done.
- (cond ((not (cdr cmds))
- (eval (car cmds))) ; single command
- (t
- (mapcar (function eval) cmds)))))
-
-(defun dired-guess-shell-command (prompt files)
-
- ;; Ask user with PROMPT for a shell command, guessing a default from FILES.
-
- (let ((default (dired-guess-default files))
- default-list old-history val (failed t))
-
- (if (null default)
- ;; Nothing to guess
- (read-from-minibuffer prompt nil nil nil 'dired-shell-command-history)
-
- ;; Save current history list
- (setq old-history dired-shell-command-history)
-
- (if (listp default)
-
- ;; More than one guess
- (setq default-list default
- default (car default)
- prompt (concat
- prompt
- (format "{%d guesses} " (length default-list))))
-
- ;; Just one guess
- (setq default-list (list default)))
-
- ;; Push all guesses onto history so that they can be retrieved with M-p
- ;; and put the first guess in the prompt but not in the initial value.
- (setq dired-shell-command-history
- (append default-list dired-shell-command-history)
- prompt (concat prompt (format "[%s] " default)))
-
- ;; The unwind-protect returns VAL, and we too.
- (unwind-protect
- ;; BODYFORM
- (progn
- (setq val (read-from-minibuffer prompt nil nil nil
- 'dired-shell-command-history)
- failed nil)
- ;; If we got a return, then use default.
- (if (equal val "")
- (setq val default))
- val)
-
- ;; UNWINDFORMS
- ;; Undo pushing onto the history list so that an aborted
- ;; command doesn't get the default in the next command.
- (setq dired-shell-command-history old-history)
- (if (not failed)
- (or (equal val (car-safe dired-shell-command-history))
- (setq dired-shell-command-history
- (cons val dired-shell-command-history))))))))
-
-
-;;; REDEFINE.
-;;; Redefine dired-aux.el's version:
-(defun dired-read-shell-command (prompt arg files)
-;; "Read a dired shell command prompting with PROMPT (using read-string).
-;;ARG is the prefix arg and may be used to indicate in the prompt which
-;; files are affected.
-;;This is an extra function so that you can redefine it, e.g., to use gmhist."
- (dired-mark-pop-up
- nil 'shell files
- 'dired-guess-shell-command
- (format prompt (dired-mark-prompt arg files)) ; PROMPT
- files)) ; FILES
-
-
-;;; RELATIVE SYMBOLIC LINKS.
-
-(defvar dired-keep-marker-relsymlink ?S
- "See variable `dired-keep-marker-move'.")
-
-(defun dired-make-relative-symlink (file1 file2 &optional ok-if-already-exists)
- "Three arguments: FILE1 FILE2 &optional OK-IF-ALREADY-EXISTS
-Make a symbolic link (pointing to FILE1) in FILE2.
-The link is relative (if possible), for example
-
- \"/vol/tex/bin/foo\" \"/vol/local/bin/foo\"
-
-results in
-
- \"../../tex/bin/foo\" \"/vol/local/bin/foo\"
-"
- (interactive "FRelSymLink: \nFRelSymLink %s: \np")
- (let (name1 name2 len1 len2 (index 0) sub)
- (setq file1 (expand-file-name file1)
- file2 (expand-file-name file2)
- len1 (length file1)
- len2 (length file2))
- ;; Find common initial pathname components:
- (let (next)
- (while (and (setq next (string-match "/" file1 index))
- (setq next (1+ next))
- (< next (min len1 len2))
- ;; For the comparison, both substrings must end in
- ;; `/', so NEXT is *one plus* the result of the
- ;; string-match.
- ;; E.g., consider the case of linking "/tmp/a/abc"
- ;; to "/tmp/abc" erroneously giving "/tmp/a" instead
- ;; of "/tmp/" as common initial component
- (string-equal (substring file1 0 next)
- (substring file2 0 next)))
- (setq index next))
- (setq name2 file2
- sub (substring file1 0 index)
- name1 (substring file1 index)))
- (if (string-equal sub "/")
- ;; No common initial pathname found
- (setq name1 file1)
- ;; Else they have a common parent directory
- (let ((tem (substring file2 index))
- (start 0)
- (count 0))
- ;; Count number of slashes we must compensate for ...
- (while (setq start (string-match "/" tem start))
- (setq count (1+ count)
- start (1+ start)))
- ;; ... and prepend a "../" for each slash found:
- (while (> count 0)
- (setq count (1- count)
- name1 (concat "../" name1)))))
- (make-symbolic-link
- (directory-file-name name1) ; must not link to foo/
- ; (trailing slash!)
- name2 ok-if-already-exists)))
-
-(defun dired-do-relsymlink (&optional arg)
- "Relative symlink all marked (or next ARG) files into a directory,
-or make a relative symbolic link to the current file.
-This creates relative symbolic links like
-
- foo -> ../bar/foo
-
-not absolute ones like
-
- foo -> /ugly/path/that/may/change/any/day/bar/foo"
- (interactive "P")
- (dired-do-create-files 'relsymlink (function dired-make-relative-symlink)
- "RelSymLink" arg dired-keep-marker-relsymlink))
-
-(defun dired-do-relsymlink-regexp (regexp newname &optional whole-path)
- "RelSymlink all marked files containing REGEXP to NEWNAME.
-See functions `dired-do-rename-regexp' and `dired-do-relsymlink'
-for more info."
- (interactive (dired-mark-read-regexp "RelSymLink"))
- (dired-do-create-files-regexp
- (function dired-make-relative-symlink)
- "RelSymLink" nil regexp newname whole-path dired-keep-marker-relsymlink))
-
-
-;;; VISIT ALL MARKED FILES SIMULTANEOUSLY.
-
-;;; Brief Description:
-;;;
-;;; `dired-do-find-marked-files' is bound to `F' by dired-x.el.
-;;;
-;;; * Use `dired-get-marked-files' to collect the marked files in the current
-;;; Dired Buffer into a list of filenames `FILE-LIST'.
-;;;
-;;; * Pass FILE-LIST to `dired-simultaneous-find-file' all with
-;;; `dired-do-find-marked-files''s prefix argument NOSELECT.
-;;;
-;;; * `dired-simultaneous-find-file' runs through FILE-LIST decrementing the
-;;; list each time.
-;;;
-;;; * If NOSELECT is non-nil then just run `find-file-noselect' on each
-;;; element of FILE-LIST.
-;;;
-;;; * If NOSELECT is nil then calculate the `size' of the window for each file
-;;; by dividing the `window-height' by length of FILE-LIST. Thus, `size' is
-;;; cognizant of the window-configuration.
-;;;
-;;; * If `size' is too small abort, otherwise run `find-file' on each element
-;;; of FILE-LIST giving each a window of height `size'.
-
-(defun dired-do-find-marked-files (&optional noselect)
- "Find all marked files displaying all of them simultaneously.
-With optional NOSELECT just find files but do not select them.
-
-The current window is split across all files marked, as evenly as possible.
-Remaining lines go to bottom-most window. The number of files that can be
-displayed this way is restricted by the height of the current window and
-`window-min-height'.
-
-To keep dired buffer displayed, type \\[split-window-vertically] first.
-To display just marked files, type \\[delete-other-windows] first."
-
- (interactive "P")
- (dired-simultaneous-find-file (dired-get-marked-files) noselect))
-
-(defun dired-simultaneous-find-file (file-list noselect)
-
- ;; Visit all files in FILE-LIST and display them simultaneously. The
- ;; current window is split across all files in FILE-LIST, as evenly as
- ;; possible. Remaining lines go to the bottom-most window. The number of
- ;; files that can be displayed this way is restricted by the height of the
- ;; current window and the variable `window-min-height'. With non-nil
- ;; NOSELECT the files are merely found but not selected.
-
- ;; We don't make this function interactive because it is usually too clumsy
- ;; to specify FILE-LIST interactively unless via dired.
-
- (let (size)
-
- (if noselect
- ;; Do not select the buffer.
- (find-file-noselect (car file-list))
-
- ;; We will have to select the buffer. Calculate and check window size.
- (setq size (/ (window-height) (length file-list)))
- (or (<= window-min-height size)
- (error "Too many files to visit simultaneously. Try C-u prefix."))
- (find-file (car file-list)))
-
- ;; Decrement.
- (setq file-list (cdr file-list))
-
- (while file-list
-
- (if noselect
- ;; Do not select the buffer.
- (find-file-noselect (car file-list))
-
- ;; Vertically split off a window of desired size. Upper window will
- ;; have SIZE lines. Select lower (larger) window. We split it again.
- (select-window (split-window nil size))
- (find-file (car file-list)))
-
- ;; Decrement.
- (setq file-list (cdr file-list)))))
-
-
-;;; MISCELLANEOUS COMMANDS.
-
-;;; Run man on files.
-
-(defun dired-man ()
- "Run man on this file. Display old buffer if buffer name matches filename.
-Uses ../lisp/man.el of \\[manual-entry] fame."
- (interactive)
- (require 'man)
- (let ((file (dired-get-filename))
- (manual-program "nroff -man -h"))
- (Man-getpage-in-background file)))
-
-;;; Run Info on files.
-
-(defun dired-info ()
- "Run info on this file."
- (interactive)
- (info (dired-get-filename)))
-
-;;; Run mail on mail folders.
-
-;;; (and (not (fboundp 'vm-visit-folder))
-;;; (defun vm-visit-folder (file &optional arg)
-;;; nil))
-
-(defun dired-vm (&optional read-only)
- "Run VM on this file.
-With prefix arg, visit folder read-only (this requires at least VM 5).
-See also variable `dired-vm-read-only-folders'."
- (interactive "P")
- (let ((dir (dired-current-directory))
- (fil (dired-get-filename)))
- ;; take care to supply 2nd arg only if requested - may still run VM 4!
- (cond (read-only (vm-visit-folder fil t))
- ((eq t dired-vm-read-only-folders) (vm-visit-folder fil t))
- ((null dired-vm-read-only-folders) (vm-visit-folder fil))
- (t (vm-visit-folder fil (not (file-writable-p fil)))))
- ;; so that pressing `v' inside VM does prompt within current directory:
- (set (make-local-variable 'vm-folder-directory) dir)))
-
-(defun dired-rmail ()
- "Run RMAIL on this file."
- (interactive)
- (rmail (dired-get-filename)))
-
-(defun dired-do-run-mail ()
- "If `dired-bind-vm' is t, then function `dired-vm', otherwise `dired-rmail'."
- (interactive)
- (if dired-bind-vm
- ;; Read mail folder using vm.
- (dired-vm)
- ;; Read mail folder using rmail.
- (dired-rmail)))
-
-
-;;; MISCELLANEOUS INTERNAL FUNCTIONS.
-
-(or (fboundp 'dired-old-find-buffer-nocreate)
- (fset 'dired-old-find-buffer-nocreate
- (symbol-function 'dired-find-buffer-nocreate)))
-
-;;; REDEFINE.
-;;; Redefines dired.el's version of `dired-find-buffer-nocreate'
-(defun dired-find-buffer-nocreate (dirname &optional mode)
- (if (and dired-find-subdir
- ;; don't try to find a wildcard as a subdirectory
- (string-equal dirname (file-name-directory dirname)))
- (let* ((cur-buf (current-buffer))
- (buffers (nreverse
- (dired-buffers-for-dir (expand-file-name dirname))))
- (cur-buf-matches (and (memq cur-buf buffers)
- ;; wildcards must match, too:
- (equal dired-directory dirname))))
- ;; We don't want to switch to the same buffer---
- (setq buffers (delq cur-buf buffers));;need setq with delq
- (or (car (sort buffers (function dired-buffer-more-recently-used-p)))
- ;; ---unless it's the only possibility:
- (and cur-buf-matches cur-buf)))
- (dired-old-find-buffer-nocreate dirname mode)))
-
-;; This should be a builtin
-(defun dired-buffer-more-recently-used-p (buffer1 buffer2)
- "Return t if BUFFER1 is more recently used than BUFFER2."
- (if (equal buffer1 buffer2)
- nil
- (let ((more-recent nil)
- (list (buffer-list)))
- (while (and list
- (not (setq more-recent (equal buffer1 (car list))))
- (not (equal buffer2 (car list))))
- (setq list (cdr list)))
- more-recent)))
-
-;;; Same thing as `dired-buffers-for-dir' of dired.el? - lrd 11/23/93
-;;; (defun dired-buffers-for-dir-exact (dir)
-;;; ;; Return a list of buffers that dired DIR (a directory or wildcard)
-;;; ;; at top level, or as subdirectory.
-;;; ;; Top level matches must match the wildcard part too, if any.
-;;; ;; The list is in reverse order of buffer creation, most recent last.
-;;; ;; As a side effect, killed dired buffers for DIR are removed from
-;;; ;; dired-buffers.
-;;; (let ((alist dired-buffers) result elt)
-;;; (while alist
-;;; (setq elt (car alist)
-;;; alist (cdr alist))
-;;; (let ((buf (cdr elt)))
-;;; (if (buffer-name buf)
-;;; ;; Top level must match exactly against dired-directory in
-;;; ;; case one of them is a wildcard.
-;;; (if (or (equal dir (save-excursion (set-buffer buf)
-;;; dired-directory))
-;;; (assoc dir (save-excursion (set-buffer buf)
-;;; dired-subdir-alist)))
-;;; (setq result (cons buf result)))
-;;; ;; else buffer is killed - clean up:
-;;; (setq dired-buffers (delq elt dired-buffers)))))
-;;; result))
-
-;;; REDEFINE.
-;;; Redefines dired.el's version of `dired-initial-position'
-(defun dired-initial-position (dirname)
- (end-of-line)
- (if dired-find-subdir (dired-goto-subdir dirname)) ; new
- (if dired-trivial-filenames (dired-goto-next-nontrivial-file)))
-
-
-;; Does anyone use this? - lrd 6/29/93.
-(defun dired-mark-sexp (predicate &optional unflag-p)
- "Mark files for which PREDICATE returns non-nil.
-With a prefix arg, unflag those files instead.
-
-PREDICATE is a lisp expression that can refer to the following symbols:
-
- inode [integer] the inode of the file (only for ls -i output)
- s [integer] the size of the file for ls -s output
- (usually in blocks or, with -k, in KByte)
- mode [string] file permission bits, e.g. \"-rw-r--r--\"
- nlink [integer] number of links to file
- uid [string] owner
- gid [string] group (If the gid is not displayed by ls,
- this will still be set (to the same as uid))
- size [integer] file size in bytes
- time [string] the time that ls displays, e.g. \"Feb 12 14:17\"
- name [string] the name of the file
- sym [string] if file is a symbolic link, the linked-to name, else \"\"
-
-For example, use
-
- (equal 0 size)
-
-to mark all zero length files."
- ;; Using sym="" instead of nil avoids the trap of
- ;; (string-match "foo" sym) into which a user would soon fall.
- ;; Give `equal' instead of `=' in the example, as this works on
- ;; integers and strings.
- (interactive "xMark if (lisp expr): \nP")
- (message "%s" predicate)
- (let ((dired-marker-char (if unflag-p ?\040 dired-marker-char))
- inode s mode nlink uid gid size time name sym)
- (dired-mark-if
- (save-excursion
- (and
- ;; Sets vars
- ;; inode s mode nlink uid gid size time name sym
-
- ;; according to current file line. Returns t for success, nil if
- ;; there is no file line. Upon success, all variables are set, either
- ;; to nil or the appropriate value, so they need not be initialized.
- ;; Moves point within the current line.
- (if (dired-move-to-filename)
- (let (pos
- (mode-len 10) ; length of mode string
- ;; like in dired.el, but with subexpressions \1=inode, \2=s:
- (dired-re-inode-size "\\s *\\([0-9]*\\)\\s *\\([0-9]*\\) ?"))
- (beginning-of-line)
- (forward-char 2)
- (if (looking-at dired-re-inode-size)
- (progn
- (goto-char (match-end 0))
- (setq inode (string-to-int (buffer-substring (match-beginning 1)
- (match-end 1)))
- s (string-to-int (buffer-substring (match-beginning 2)
- (match-end 2)))))
- (setq inode nil
- s nil))
- (setq mode (buffer-substring (point) (+ mode-len (point))))
- (forward-char mode-len)
- (setq nlink (read (current-buffer)))
- (setq uid (buffer-substring (point) (progn (forward-word 1) (point))))
- (re-search-forward "\\(Jan\\|Feb\\|Mar\\|Apr\\|May\\|Jun\\|Jul\\|Aug\\|Sep\\|Oct\\|Nov\\|Dec\\)")
- (goto-char (match-beginning 1))
- (forward-char -1)
- (setq size (string-to-int (buffer-substring (save-excursion
- (backward-word 1)
- (setq pos (point)))
- (point))))
- (goto-char pos)
- (backward-word 1)
- ;; if no gid is displayed, gid will be set to uid
- ;; but user will then not reference it anyway in PREDICATE.
- (setq gid (buffer-substring (save-excursion (forward-word 1) (point))
- (point))
- time (buffer-substring (match-beginning 1)
- (1- (dired-move-to-filename)))
- name (buffer-substring (point)
- (or (dired-move-to-end-of-filename t)
- (point)))
- sym (progn
- (if (looking-at " -> ")
- (buffer-substring (progn (forward-char 4) (point))
- (progn (end-of-line) (point)))
- "")))
- t)
- nil)
- (eval predicate)))
- (format "'%s file" predicate))))
-
-
-;;; FIND FILE AT POINT.
-
-(defvar dired-x-hands-off-my-keys t
- "*t means don't bind `dired-x-find-file' over `find-file' on keyboard.
-Similarly for `dired-x-find-file-other-window' over `find-file-other-window'.
-If you change this variable after dired-x.el is loaded then do
-\\[dired-x-bind-find-file].")
-
-;;; Bind `dired-x-find-file{-other-window}' over wherever
-;;; `find-file{-other-window}' is bound?
-(defun dired-x-bind-find-file ()
- "Bind `dired-x-find-file' in place of `find-file' \(or reverse\).
-Similarly for `dired-x-find-file-other-window' and `find-file-other-window'.
-Binding direction based on `dired-x-hands-off-my-keys'.
-This function part of `after-init-hook'."
- (interactive)
- (if (interactive-p)
- (setq dired-x-hands-off-my-keys
- (not (y-or-n-p "Bind dired-x-find-file over find-file? "))))
- (cond ((not dired-x-hands-off-my-keys)
- (substitute-key-definition 'find-file
- 'dired-x-find-file
- (current-global-map))
- (substitute-key-definition 'find-file-other-window
- 'dired-x-find-file-other-window
- (current-global-map)))
- (t
- (substitute-key-definition 'dired-x-find-file
- 'find-file
- (current-global-map))
- (substitute-key-definition 'dired-x-find-file-other-window
- 'find-file-other-window
- (current-global-map))))
- ;; Clear mini-buffer.
- (message nil))
-
-;;; Now call it so binding is correct and put on `after-init-hook' in case
-;;; user changes binding.
-(dired-x-bind-find-file)
-(add-hook 'after-init-hook 'dired-x-bind-find-file)
-
-(defun dired-x-find-file (filename)
- "Edit file FILENAME.
-May create a new window, or reuse an existing one.
-See the function `display-buffer'.
-
-Identical to `find-file' except when called interactively, with a prefix arg
-\(e.g., \\[universal-argument]\), in which case it guesses filename near
-point. Useful for editing file mentioned in buffer you are viewing, or to
-test if that file exists. Use minibuffer after snatching filename."
- (interactive (list (read-filename-at-point "Find file: ")))
- (find-file (expand-file-name filename)))
-
-(defun dired-x-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'.
-
-Identical to `find-file-other-window' except when called interactively, with a
-prefix arg \(e.g., \\[universal-argument]\), in which case it guesses filename
-near point. Useful for editing file mentioned in buffer you are viewing, or
-to test if that file exists. Use minibuffer after snatching filename."
- (interactive (list (read-filename-at-point "Find file: ")))
- (find-file-other-window (expand-file-name filename)))
-
-;;; Internal functions.
-(defun dired-filename-at-point ()
-
- ;; Get the filename closest to point, but do not change position. Has a
- ;; preference for looking backward when not directly on a symbol. Not
- ;; perfect - point must be in middle of or end of filename.
-
- (let ((filename-chars ".a-zA-Z0-9---_/:$+")
- (bol (save-excursion (beginning-of-line) (point)))
- (eol (save-excursion (end-of-line) (point)))
- start end filename)
-
- (save-excursion
- ;; First see if just past a filename.
- (if (not (eobp))
- (if (looking-at "[] \t\n[{}()]") ; whitespace or some parens
- (progn
- (skip-chars-backward " \n\t\r({[]})")
- (if (not (bobp))
- (backward-char 1)))))
-
- (if (string-match (concat "[" filename-chars "]")
- (char-to-string (following-char)))
- (progn
- (skip-chars-backward filename-chars)
- (setq start (point))
- (if (string-match "[/~]" (char-to-string (preceding-char)))
- (setq start (1- start)))
- (skip-chars-forward filename-chars))
-
- (error "No file found around point!"))
-
- ;; Return string.
- (expand-file-name (buffer-substring start (point))))))
-
-(defun read-filename-at-point (prompt)
- ;;; Returns filename prompting with PROMPT with completion. If
- ;;; `current-prefix-arg' is non-nil, uses name at point as guess.
- (if current-prefix-arg
- (let ((guess (dired-filename-at-point)))
- (read-file-name prompt
- (file-name-directory guess)
- guess
- nil (file-name-nondirectory guess)))
- (read-file-name prompt default-directory)))
-
-
-;;; BUG REPORTS
-
-;;; This section is provided for reports. It uses Barry A. Warsaw's
-;;; reporter.el which is bundled with GNU Emacs v19.
-
-(defconst dired-x-version "2.37"
- "Revision number of dired-x.el -- dired extra for GNU Emacs v19.
-Type \\[dired-x-submit-report] to send a bug report. Available via anonymous
-ftp in
-
- /roebling.poly.edu:/pub/packages/dired-x.tar.gz")
-
-(defconst dired-x-help-address "dodd@roebling.poly.edu"
- "Address(es) accepting submission of reports on dired-x.el.")
-
-(defconst dired-x-maintainer "Larry"
- "First name(s) of people accepting submission of reports on dired-x.el.")
-
-(defconst dired-x-file "dired-x.el"
- "Name of file containing emacs lisp code.")
-
-(defconst dired-x-variable-list
- (list
- 'dired-bind-vm
- 'dired-vm-read-only-folders
- 'dired-bind-jump
- 'dired-bind-info
- 'dired-bind-man
- 'dired-find-subdir
- 'dired-enable-local-variables
- 'dired-local-variables-file
- 'dired-guess-shell-gnutar
- 'dired-guess-shell-gzip-quiet
- 'dired-guess-shell-znew-switches
- 'dired-guess-shell-alist-user
- 'dired-clean-up-buffers-too
- 'dired-omit-files-p
- 'dired-omit-files
- 'dired-omit-extensions
- )
- "List of variables to be appended to reports sent by `dired-x-submit-report.'")
-
-(defun dired-x-submit-report ()
- "Submit via reporter.el a bug report on program. Send report on `dired-x-file'
-version `dired-x-version,' to `dired-x-maintainer' at address `dired-x-help-address'
-listing variables `dired-x-variable-list' in the message."
- (interactive)
-
- ;; In case we can't find reporter...
- (condition-case err
- (progn
- ;; Get it if we can.
- (require 'reporter)
-
- (reporter-submit-bug-report
- dired-x-help-address ; address
- (concat dired-x-file " (" dired-x-version ")") ; pkgname
- dired-x-variable-list ; varlist
- nil nil ; pre-/post-hooks
- (concat dired-x-maintainer ","))) ; salutation
-
- ;; ...fail gracefully.
- (error
- (beep)
- (message "Sorry, reporter.el not found."))))
-
-
-;; As Barry Warsaw would say: "This might be useful..."
-(provide 'dired-x)
-
-;;; dired-x.el ends here
diff --git a/lisp/dired.el b/lisp/dired.el
deleted file mode 100644
index ffb6bd22831..00000000000
--- a/lisp/dired.el
+++ /dev/null
@@ -1,2506 +0,0 @@
-;;; dired.el --- directory-browsing commands
-
-;; Copyright (C) 1985, 86, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
-
-;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This is a major mode for directory browsing and editing. It is
-;; documented in the Emacs manual.
-
-;; Rewritten in 1990/1991 to add tree features, file marking and
-;; sorting by Sebastian Kremer <sk@thp.uni-koeln.de>.
-;; Finished up by rms in 1992.
-
-;;; Code:
-
-;;; Customizable variables
-
-;;;###autoload
-(defvar dired-listing-switches "-al"
- "*Switches passed to `ls' for dired. MUST contain the `l' option.
-May contain all other options that don't contradict `-l';
-may contain even `F', `b', `i' and `s'. See also the variable
-`dired-ls-F-marks-symlinks' concerning the `F' switch.")
-
-; Don't use absolute paths as /bin should be in any PATH and people
-; may prefer /usr/local/gnu/bin or whatever. However, chown is
-; usually not in PATH.
-
-;;;###autoload
-(defvar dired-chown-program
- (if (memq system-type '(hpux dgux usg-unix-v irix linux gnu/linux))
- "chown"
- (if (file-exists-p "/usr/sbin/chown")
- "/usr/sbin/chown"
- "/etc/chown"))
- "Name of chown command (usually `chown' or `/etc/chown').")
-
-(defvar dired-chmod-program
- (if (eq system-type 'windows-nt)
- "chmode" "chmod")
- "Name of chmod command (usually `chmod' or `chmode').")
-
-;;;###autoload
-(defvar dired-ls-F-marks-symlinks nil
- "*Informs dired about how `ls -lF' marks symbolic links.
-Set this to t if `ls' (or whatever program is specified by
-`insert-directory-program') with `-lF' marks the symbolic link
-itself with a trailing @ (usually the case under Ultrix).
-
-Example: if `ln -s foo bar; ls -F bar' gives `bar -> foo', set it to
-nil (the default), if it gives `bar@ -> foo', set it to t.
-
-Dired checks if there is really a @ appended. Thus, if you have a
-marking `ls' program on one host and a non-marking on another host, and
-don't care about symbolic links which really end in a @, you can
-always set this variable to t.")
-
-;;;###autoload
-(defvar dired-trivial-filenames "^\\.\\.?$\\|^#"
- "*Regexp of files to skip when finding first file of a directory.
-A value of nil means move to the subdir line.
-A value of t means move to first file.")
-
-;;;###autoload
-(defvar dired-keep-marker-rename t
- ;; Use t as default so that moved files "take their markers with them".
- "*Controls marking of renamed files.
-If t, files keep their previous marks when they are renamed.
-If a character, renamed files (whether previously marked or not)
-are afterward marked with that character.")
-
-;;;###autoload
-(defvar dired-keep-marker-copy ?C
- "*Controls marking of copied files.
-If t, copied files are marked if and as the corresponding original files were.
-If a character, copied files are unconditionally marked with that character.")
-
-;;;###autoload
-(defvar dired-keep-marker-hardlink ?H
- "*Controls marking of newly made hard links.
-If t, they are marked if and as the files linked to were marked.
-If a character, new links are unconditionally marked with that character.")
-
-;;;###autoload
-(defvar dired-keep-marker-symlink ?Y
- "*Controls marking of newly made symbolic links.
-If t, they are marked if and as the files linked to were marked.
-If a character, new links are unconditionally marked with that character.")
-
-;;;###autoload
-(defvar dired-dwim-target nil
- "*If non-nil, dired tries to guess a default target directory.
-This means: if there is a dired buffer displayed in the next window,
-use its current subdir, instead of the current subdir of this dired buffer.
-
-The target is used in the prompt for file copy, rename etc.")
-
-;;;###autoload
-(defvar dired-copy-preserve-time t
- "*If non-nil, Dired preserves the last-modified time in a file copy.
-\(This works on only some systems.)")
-
-;;; Hook variables
-
-(defvar dired-load-hook nil
- "Run after loading dired.
-You can customize key bindings or load extensions with this.")
-
-(defvar dired-mode-hook nil
- "Run at the very end of dired-mode.")
-
-(defvar dired-before-readin-hook nil
- "This hook is run before a dired buffer is read in (created or reverted).")
-
-(defvar dired-after-readin-hook nil
- "Hook run after each time a file or directory is read by Dired.
-After each listing of a file or directory, this hook is run
-with the buffer narrowed to the listing.")
-;; Note this can't simply be run inside function `dired-ls' as the hook
-;; functions probably depend on the dired-subdir-alist to be OK.
-
-;;; Internal variables
-
-(defvar dired-marker-char ?* ; the answer is 42
- ;; so that you can write things like
- ;; (let ((dired-marker-char ?X))
- ;; ;; great code using X markers ...
- ;; )
- ;; For example, commands operating on two sets of files, A and B.
- ;; Or marking files with digits 0-9. This could implicate
- ;; concentric sets or an order for the marked files.
- ;; The code depends on dynamic scoping on the marker char.
- "In Dired, the current mark character.
-This is what the `do' commands look for and what the `mark' commands store.")
-
-(defvar dired-del-marker ?D
- "Character used to flag files for deletion.")
-
-(defvar dired-shrink-to-fit
- t
-;; I see no reason ever to make this nil -- rms.
-;; (> baud-rate search-slow-speed)
- "Non-nil means Dired shrinks the display buffer to fit the marked files.")
-
-(defvar dired-flagging-regexp nil);; Last regexp used to flag files.
-
-(defvar dired-file-version-alist)
-
-(defvar dired-directory nil
- "The directory name or shell wildcard that was used as argument to `ls'.
-Local to each dired buffer. May be a list, in which case the car is the
-directory name and the cdr is the actual files to list.")
-
-(defvar dired-actual-switches nil
- "The value of `dired-listing-switches' used to make this buffer's text.")
-
-(defvar dired-re-inode-size "[0-9 \t]*"
- "Regexp for optional initial inode and file size as made by `ls -i -s'.")
-
-;; These regexps must be tested at beginning-of-line, but are also
-;; used to search for next matches, so neither omitting "^" nor
-;; replacing "^" by "\n" (to make it slightly faster) will work.
-
-(defvar dired-re-mark "^[^ \n]")
-;; "Regexp matching a marked line.
-;; Important: the match ends just after the marker."
-(defvar dired-re-maybe-mark "^. ")
-(defvar dired-re-dir (concat dired-re-maybe-mark dired-re-inode-size "d"))
-(defvar dired-re-sym (concat dired-re-maybe-mark dired-re-inode-size "l"))
-(defvar dired-re-exe;; match ls permission string of an executable file
- (mapconcat (function
- (lambda (x)
- (concat dired-re-maybe-mark dired-re-inode-size x)))
- '("-[-r][-w][xs][-r][-w].[-r][-w]."
- "-[-r][-w].[-r][-w][xs][-r][-w]."
- "-[-r][-w].[-r][-w].[-r][-w][xst]")
- "\\|"))
-(defvar dired-re-perms "[-bcdlps][-r][-w].[-r][-w].[-r][-w].")
-(defvar dired-re-dot "^.* \\.\\.?$")
-
-;; The subdirectory names in this list are expanded.
-(defvar dired-subdir-alist nil
- "Association list of subdirectories and their buffer positions.
-Each subdirectory has an element: (DIRNAME . STARTMARKER).
-The order of elements is the reverse of the order in the buffer.
-In simple cases, this list contains one element.")
-
-(defvar dired-subdir-regexp "^. \\([^\n\r]+\\)\\(:\\)[\n\r]"
- "Regexp matching a maybe hidden subdirectory line in `ls -lR' output.
-Subexpression 1 is the subdirectory proper, no trailing colon.
-The match starts at the beginning of the line and ends after the end
-of the line (\\n or \\r).
-Subexpression 2 must end right before the \\n or \\r.")
-
-(defvar dired-font-lock-keywords
- (list
- ;;
- ;; Directory headers.
- (list dired-subdir-regexp '(1 font-lock-type-face))
- ;;
- ;; We make heavy use of MATCH-ANCHORED, since the regexps don't identify the
- ;; file name itself. We search for Dired defined regexps, and then use the
- ;; Dired defined function `dired-move-to-filename' before searching for the
- ;; simple regexp ".+". It is that regexp which matches the file name.
- ;;
- ;; Dired marks.
- (list dired-re-mark
- '(0 font-lock-reference-face)
- '(".+" (dired-move-to-filename) nil (0 font-lock-warning-face)))
- ;;
- ;; Files that are group or world writable.
- (list (concat dired-re-maybe-mark dired-re-inode-size
- "\\([-d]\\(....w....\\|.......w.\\)\\)")
- '(1 font-lock-comment-face)
- '(".+" (dired-move-to-filename) nil (0 font-lock-comment-face)))
- ;;
- ;; Subdirectories.
- (list dired-re-dir
- '(".+" (dired-move-to-filename) nil (0 font-lock-function-name-face)))
- ;;
- ;; Symbolic links.
- (list dired-re-sym
- '(".+" (dired-move-to-filename) nil (0 font-lock-keyword-face)))
- ;;
- ;; Files suffixed with `completion-ignored-extensions'.
- '(eval .
- (let ((extensions (mapcar 'regexp-quote completion-ignored-extensions)))
- ;; It is quicker to first find just an extension, then go back to the
- ;; start of that file name. So we do this complex MATCH-ANCHORED form.
- (list (concat "\\(" (mapconcat 'identity extensions "\\|") "\\|#\\)$")
- '(".+" (dired-move-to-filename) nil (0 font-lock-string-face))))))
- "Additional expressions to highlight in Dired mode.")
-
-;;; Macros must be defined before they are used, for the byte compiler.
-
-;; Mark all files for which CONDITION evals to non-nil.
-;; CONDITION is evaluated on each line, with point at beginning of line.
-;; MSG is a noun phrase for the type of files being marked.
-;; It should end with a noun that can be pluralized by adding `s'.
-;; Return value is the number of files marked, or nil if none were marked.
-(defmacro dired-mark-if (predicate msg)
- (` (let (buffer-read-only count)
- (save-excursion
- (setq count 0)
- (if (, msg) (message "Marking %ss..." (, msg)))
- (goto-char (point-min))
- (while (not (eobp))
- (if (, predicate)
- (progn
- (delete-char 1)
- (insert dired-marker-char)
- (setq count (1+ count))))
- (forward-line 1))
- (if (, msg) (message "%s %s%s %s%s."
- count
- (, msg)
- (dired-plural-s count)
- (if (eq dired-marker-char ?\040) "un" "")
- (if (eq dired-marker-char dired-del-marker)
- "flagged" "marked"))))
- (and (> count 0) count))))
-
-(defmacro dired-map-over-marks (body arg &optional show-progress)
-;; "Macro: Perform BODY with point somewhere on each marked line
-;;and return a list of BODY's results.
-;;If no marked file could be found, execute BODY on the current line.
-;; If ARG is an integer, use the next ARG (or previous -ARG, if ARG<0)
-;; files instead of the marked files.
-;; In that case point is dragged along. This is so that commands on
-;; the next ARG (instead of the marked) files can be chained easily.
-;; If ARG is otherwise non-nil, use current file instead.
-;;If optional third arg SHOW-PROGRESS evaluates to non-nil,
-;; redisplay the dired buffer after each file is processed.
-;;No guarantee is made about the position on the marked line.
-;; BODY must ensure this itself if it depends on this.
-;;Search starts at the beginning of the buffer, thus the car of the list
-;; corresponds to the line nearest to the buffer's bottom. This
-;; is also true for (positive and negative) integer values of ARG.
-;;BODY should not be too long as it is expanded four times."
-;;
-;;Warning: BODY must not add new lines before point - this may cause an
-;;endless loop.
-;;This warning should not apply any longer, sk 2-Sep-1991 14:10.
- (` (prog1
- (let (buffer-read-only case-fold-search found results)
- (if (, arg)
- (if (integerp (, arg))
- (progn;; no save-excursion, want to move point.
- (dired-repeat-over-lines
- (, arg)
- (function (lambda ()
- (if (, show-progress) (sit-for 0))
- (setq results (cons (, body) results)))))
- (if (< (, arg) 0)
- (nreverse results)
- results))
- ;; non-nil, non-integer ARG means use current file:
- (list (, body)))
- (let ((regexp (dired-marker-regexp)) next-position)
- (save-excursion
- (goto-char (point-min))
- ;; remember position of next marked file before BODY
- ;; can insert lines before the just found file,
- ;; confusing us by finding the same marked file again
- ;; and again and...
- (setq next-position (and (re-search-forward regexp nil t)
- (point-marker))
- found (not (null next-position)))
- (while next-position
- (goto-char next-position)
- (if (, show-progress) (sit-for 0))
- (setq results (cons (, body) results))
- ;; move after last match
- (goto-char next-position)
- (forward-line 1)
- (set-marker next-position nil)
- (setq next-position (and (re-search-forward regexp nil t)
- (point-marker)))))
- (if found
- results
- (list (, body))))))
- ;; save-excursion loses, again
- (dired-move-to-filename))))
-
-(defun dired-get-marked-files (&optional localp arg)
- "Return the marked files' names as list of strings.
-The list is in the same order as the buffer, that is, the car is the
- first marked file.
-Values returned are normally absolute pathnames.
-Optional arg LOCALP as in `dired-get-filename'.
-Optional second argument ARG forces to use other files. If ARG is an
- integer, use the next ARG files. If ARG is otherwise non-nil, use
- current file. Usually ARG comes from the current prefix arg."
- (save-excursion
- (nreverse (dired-map-over-marks (dired-get-filename localp) arg))))
-
-
-;; Function dired-ls is redefinable for VMS, ange-ftp, Prospero or
-;; other special applications.
-
-;; The dired command
-
-(defun dired-read-dir-and-switches (str)
- ;; For use in interactive.
- (reverse (list
- (if current-prefix-arg
- (read-string "Dired listing switches: "
- dired-listing-switches))
- (read-file-name (format "Dired %s(directory): " str)
- nil default-directory nil))))
-
-;;;###autoload (define-key ctl-x-map "d" 'dired)
-;;;###autoload
-(defun dired (dirname &optional switches)
- "\"Edit\" directory DIRNAME--delete, rename, print, etc. some files in it.
-Optional second argument SWITCHES specifies the `ls' options used.
-\(Interactively, use a prefix argument to be able to specify SWITCHES.)
-Dired displays a list of files in DIRNAME (which may also have
-shell wildcards appended to select certain files). If DIRNAME is a cons,
-its first element is taken as the directory name and the rest as an explicit
-list of files to make directory entries for.
-\\<dired-mode-map>\
-You can move around in it with the usual commands.
-You can flag files for deletion with \\[dired-flag-file-deletion] and then
-delete them by typing \\[dired-do-flagged-delete].
-Type \\[describe-mode] after entering dired for more info.
-
-If DIRNAME is already in a dired buffer, that buffer is used without refresh."
- ;; Cannot use (interactive "D") because of wildcards.
- (interactive (dired-read-dir-and-switches ""))
- (switch-to-buffer (dired-noselect dirname switches)))
-
-;;;###autoload (define-key ctl-x-4-map "d" 'dired-other-window)
-;;;###autoload
-(defun dired-other-window (dirname &optional switches)
- "\"Edit\" directory DIRNAME. Like `dired' but selects in another window."
- (interactive (dired-read-dir-and-switches "in other window "))
- (switch-to-buffer-other-window (dired-noselect dirname switches)))
-
-;;;###autoload (define-key ctl-x-5-map "d" 'dired-other-frame)
-;;;###autoload
-(defun dired-other-frame (dirname &optional switches)
- "\"Edit\" directory DIRNAME. Like `dired' but makes a new frame."
- (interactive (dired-read-dir-and-switches "in other frame "))
- (switch-to-buffer-other-frame (dired-noselect dirname switches)))
-
-;;;###autoload
-(defun dired-noselect (dir-or-list &optional switches)
- "Like `dired' but returns the dired buffer as value, does not select it."
- (or dir-or-list (setq dir-or-list default-directory))
- ;; This loses the distinction between "/foo/*/" and "/foo/*" that
- ;; some shells make:
- (let (dirname)
- (if (consp dir-or-list)
- (setq dirname (car dir-or-list))
- (setq dirname dir-or-list))
- (setq dirname (abbreviate-file-name
- (expand-file-name (directory-file-name dirname))))
- (if find-file-visit-truename
- (setq dirname (file-truename dirname)))
- (if (file-directory-p dirname)
- (setq dirname (file-name-as-directory dirname)))
- (if (consp dir-or-list)
- (setq dir-or-list (cons dirname (cdr dir-or-list)))
- (setq dir-or-list dirname))
- (dired-internal-noselect dir-or-list switches)))
-
-;; Separate function from dired-noselect for the sake of dired-vms.el.
-(defun dired-internal-noselect (dir-or-list &optional switches mode)
- ;; If there is an existing dired buffer for DIRNAME, just leave
- ;; buffer as it is (don't even call dired-revert).
- ;; This saves time especially for deep trees or with ange-ftp.
- ;; The user can type `g'easily, and it is more consistent with find-file.
- ;; But if SWITCHES are given they are probably different from the
- ;; buffer's old value, so call dired-sort-other, which does
- ;; revert the buffer.
- ;; A pity we can't possibly do "Directory has changed - refresh? "
- ;; like find-file does.
- ;; Optional argument MODE is passed to dired-find-buffer-nocreate,
- ;; see there.
- (let* ((dirname (if (consp dir-or-list) (car dir-or-list) dir-or-list))
- ;; The following line used to use dir-or-list.
- ;; That never found an existing buffer, in the case
- ;; where it is a list.
- (buffer (dired-find-buffer-nocreate dirname mode))
- ;; note that buffer already is in dired-mode, if found
- (new-buffer-p (not buffer))
- (old-buf (current-buffer)))
- (or buffer
- (let ((default-major-mode 'fundamental-mode))
- ;; We don't want default-major-mode to run hooks and set auto-fill
- ;; or whatever, now that dired-mode does not
- ;; kill-all-local-variables any longer.
- (setq buffer (create-file-buffer (directory-file-name dirname)))))
- (set-buffer buffer)
- (if (not new-buffer-p) ; existing buffer ...
- (cond (switches ; ... but new switches
- ;; file list may have changed
- (if (consp dir-or-list)
- (setq dired-directory dir-or-list))
- ;; this calls dired-revert
- (dired-sort-other switches))
- ;; If directory has changed on disk, offer to revert.
- ((if (let ((attributes (file-attributes dirname))
- (modtime (visited-file-modtime)))
- (or (eq modtime 0)
- (not (eq (car attributes) t))
- (and (= (car (nth 5 attributes)) (car modtime))
- (= (nth 1 (nth 5 attributes)) (cdr modtime)))))
- nil
- (message "%s"
- (substitute-command-keys
- "Directory has changed on disk; type \\[revert-buffer] to update Dired")))))
- ;; Else a new buffer
- (setq default-directory
- (if (file-directory-p dirname)
- dirname
- (file-name-directory dirname)))
- (or switches (setq switches dired-listing-switches))
- (dired-mode dirname switches)
- (if mode (funcall mode))
- ;; default-directory and dired-actual-switches are set now
- ;; (buffer-local), so we can call dired-readin:
- (let ((failed t))
- (unwind-protect
- (progn (dired-readin dir-or-list buffer)
- (setq failed nil))
- ;; dired-readin can fail if parent directories are inaccessible.
- ;; Don't leave an empty buffer around in that case.
- (if failed (kill-buffer buffer))))
- ;; No need to narrow since the whole buffer contains just
- ;; dired-readin's output, nothing else. The hook can
- ;; successfully use dired functions (e.g. dired-get-filename)
- ;; as the subdir-alist has been built in dired-readin.
- (run-hooks 'dired-after-readin-hook)
- (goto-char (point-min))
- (dired-initial-position dirname))
- (set-buffer old-buf)
- buffer))
-
-(defun dired-find-buffer-nocreate (dirname &optional mode)
- ;; This differs from dired-buffers-for-dir in that it does not consider
- ;; subdirs of default-directory and searches for the first match only.
- ;; Also, the major mode must be MODE.
- (let (found (blist dired-buffers)) ; was (buffer-list)
- (or mode (setq mode 'dired-mode))
- (while blist
- (if (null (buffer-name (cdr (car blist))))
- (setq blist (cdr blist))
- (save-excursion
- (set-buffer (cdr (car blist)))
- (if (and (eq major-mode mode)
- (if (consp dired-directory)
- (equal (car dired-directory) dirname)
- (equal dired-directory dirname)))
- (setq found (cdr (car blist))
- blist nil)
- (setq blist (cdr blist))))))
- found))
-
-
-;; Read in a new dired buffer
-
-;; dired-readin differs from dired-insert-subdir in that it accepts
-;; wildcards, erases the buffer, and builds the subdir-alist anew
-;; (including making it buffer-local and clearing it first).
-(defun dired-readin (dir-or-list buffer)
- ;; default-directory and dired-actual-switches must be buffer-local
- ;; and initialized by now.
- ;; Thus we can test (equal default-directory dirname) instead of
- ;; (file-directory-p dirname) and save a filesystem transaction.
- ;; Also, we can run this hook which may want to modify the switches
- ;; based on default-directory, e.g. with ange-ftp to a SysV host
- ;; where ls won't understand -Al switches.
- (let (dirname)
- (if (consp dir-or-list)
- (setq dirname (car dir-or-list))
- (setq dirname dir-or-list))
- (setq dirname (expand-file-name dirname))
- (if (consp dir-or-list)
- (setq dir-or-list (cons dirname (cdr dir-or-list))))
- (run-hooks 'dired-before-readin-hook)
- (save-excursion
- (message "Reading directory %s..." dirname)
- (set-buffer buffer)
- (let (buffer-read-only (failed t))
- (widen)
- (erase-buffer)
- (dired-readin-insert dir-or-list)
- (indent-rigidly (point-min) (point-max) 2)
- ;; We need this to make the root dir have a header line as all
- ;; other subdirs have:
- (goto-char (point-min))
- (dired-insert-headerline default-directory)
- ;; can't run dired-after-readin-hook here, it may depend on the subdir
- ;; alist to be OK.
- )
- (message "Reading directory %s...done" dirname)
- ;; Must first make alist buffer local and set it to nil because
- ;; dired-build-subdir-alist will call dired-clear-alist first
- (set (make-local-variable 'dired-subdir-alist) nil)
- (dired-build-subdir-alist)
- (let ((attributes (file-attributes dirname)))
- (if (eq (car attributes) t)
- (set-visited-file-modtime (nth 5 attributes))))
- (set-buffer-modified-p nil))))
-
-;; Subroutines of dired-readin
-
-(defun dired-readin-insert (dir-or-list)
- ;; Just insert listing for the passed-in directory or
- ;; directory-and-file list, assuming a clean buffer.
- (let (dirname)
- (if (consp dir-or-list)
- (setq dirname (car dir-or-list))
- (setq dirname dir-or-list))
- ;; Expand before comparing in case one or both have been abbreviated.
- (if (and (equal (expand-file-name default-directory)
- (expand-file-name dirname))
- (not (consp dir-or-list)))
- ;; If we are reading a whole single directory...
- (dired-insert-directory dir-or-list dired-actual-switches nil t)
- (if (not (file-readable-p
- (directory-file-name (file-name-directory dirname))))
- (error "Directory %s inaccessible or nonexistent" dirname)
- ;; Else assume it contains wildcards,
- ;; unless it is an explicit list of files.
- (dired-insert-directory dir-or-list dired-actual-switches
- (not (listp dir-or-list)))
- (save-excursion ;; insert wildcard instead of total line:
- (goto-char (point-min))
- (insert "wildcard " (file-name-nondirectory dirname) "\n"))))))
-
-(defun dired-insert-directory (dir-or-list switches &optional wildcard full-p)
- ;; Do the right thing whether dir-or-list is atomic or not. If it is,
- ;; inset all files listed in the cdr (the car is the passed-in directory
- ;; list).
- (let ((opoint (point))
- (process-environment (copy-sequence process-environment))
- end)
- ;; We used to specify the C locale here, to force English month names;
- ;; but this should not be necessary any more,
- ;; with the new value of dired-move-to-filename-regexp.
- (if (consp dir-or-list)
- ;; In this case, use the file names in the cdr
- ;; exactly as originally given to dired-noselect.
- (mapcar
- (function (lambda (x) (insert-directory x switches wildcard full-p)))
- (cdr dir-or-list))
- ;; Expand the file name here because it may have been abbreviated
- ;; in dired-noselect.
- (insert-directory (expand-file-name dir-or-list) switches wildcard full-p))
- ;; Quote certain characters, unless ls quoted them for us.
- (if (not (string-match "b" dired-actual-switches))
- (save-excursion
- (setq end (point-marker))
- (goto-char opoint)
- (while (search-forward "\\" end t)
- (replace-match "\\\\" nil t))
- (goto-char opoint)
- (while (search-forward "\^m" end t)
- (replace-match "\\015" nil t))
- (set-marker end nil)))
- (dired-insert-set-properties opoint (point)))
- (setq dired-directory dir-or-list))
-
-;; Make the file names highlight when the mouse is on them.
-(defun dired-insert-set-properties (beg end)
- (save-excursion
- (goto-char beg)
- (while (< (point) end)
- (condition-case nil
- (if (dired-move-to-filename)
- (put-text-property (point)
- (save-excursion
- (dired-move-to-end-of-filename)
- (point))
- 'mouse-face 'highlight))
- (error nil))
- (forward-line 1))))
-
-(defun dired-insert-headerline (dir);; also used by dired-insert-subdir
- ;; Insert DIR's headerline with no trailing slash, exactly like ls
- ;; would, and put cursor where dired-build-subdir-alist puts subdir
- ;; boundaries.
- (save-excursion (insert " " (directory-file-name dir) ":\n")))
-
-
-;; Reverting a dired buffer
-
-(defun dired-revert (&optional arg noconfirm)
- ;; Reread the dired buffer. Must also be called after
- ;; dired-actual-switches have changed.
- ;; Should not fail even on completely garbaged buffers.
- ;; Preserves old cursor, marks/flags, hidden-p.
- (widen) ; just in case user narrowed
- (let ((opoint (point))
- (ofile (dired-get-filename nil t))
- (mark-alist nil) ; save marked files
- (hidden-subdirs (dired-remember-hidden))
- (old-subdir-alist (cdr (reverse dired-subdir-alist))) ; except pwd
- (case-fold-search nil) ; we check for upper case ls flags
- buffer-read-only)
- (goto-char (point-min))
- (setq mark-alist;; only after dired-remember-hidden since this unhides:
- (dired-remember-marks (point-min) (point-max)))
- ;; treat top level dir extra (it may contain wildcards)
- (dired-uncache
- (if (consp dired-directory) (car dired-directory) dired-directory))
- (dired-readin dired-directory (current-buffer))
- (let ((dired-after-readin-hook nil))
- ;; don't run that hook for each subdir...
- (dired-insert-old-subdirs old-subdir-alist))
- (dired-mark-remembered mark-alist) ; mark files that were marked
- ;; ... run the hook for the whole buffer, and only after markers
- ;; have been reinserted (else omitting in dired-x would omit marked files)
- (run-hooks 'dired-after-readin-hook) ; no need to narrow
- (or (and ofile (dired-goto-file ofile)) ; move cursor to where it
- (goto-char opoint)) ; was before
- (dired-move-to-filename)
- (save-excursion ; hide subdirs that were hidden
- (mapcar (function (lambda (dir)
- (if (dired-goto-subdir dir)
- (dired-hide-subdir 1))))
- hidden-subdirs)))
- ;; outside of the let scope
-;;; Might as well not override the user if the user changed this.
-;;; (setq buffer-read-only t)
- )
-
-;; Subroutines of dired-revert
-;; Some of these are also used when inserting subdirs.
-
-(defun dired-remember-marks (beg end)
- ;; Return alist of files and their marks, from BEG to END.
- (if selective-display ; must unhide to make this work.
- (let (buffer-read-only)
- (subst-char-in-region beg end ?\r ?\n)))
- (let (fil chr alist)
- (save-excursion
- (goto-char beg)
- (while (re-search-forward dired-re-mark end t)
- (if (setq fil (dired-get-filename nil t))
- (setq chr (preceding-char)
- alist (cons (cons fil chr) alist)))))
- alist))
-
-;; Mark all files remembered in ALIST.
-;; Each element of ALIST looks like (FILE . MARKERCHAR).
-(defun dired-mark-remembered (alist)
- (let (elt fil chr)
- (while alist
- (setq elt (car alist)
- alist (cdr alist)
- fil (car elt)
- chr (cdr elt))
- (if (dired-goto-file fil)
- (save-excursion
- (beginning-of-line)
- (delete-char 1)
- (insert chr))))))
-
-;; Return a list of names of subdirs currently hidden.
-(defun dired-remember-hidden ()
- (let ((l dired-subdir-alist) dir pos result)
- (while l
- (setq dir (car (car l))
- pos (cdr (car l))
- l (cdr l))
- (goto-char pos)
- (skip-chars-forward "^\r\n")
- (if (eq (following-char) ?\r)
- (setq result (cons dir result))))
- result))
-
-;; Try to insert all subdirs that were displayed before,
-;; according to the former subdir alist OLD-SUBDIR-ALIST.
-(defun dired-insert-old-subdirs (old-subdir-alist)
- (or (string-match "R" dired-actual-switches)
- (let (elt dir)
- (while old-subdir-alist
- (setq elt (car old-subdir-alist)
- old-subdir-alist (cdr old-subdir-alist)
- dir (car elt))
- (condition-case ()
- (progn
- (dired-uncache dir)
- (dired-insert-subdir dir))
- (error nil))))))
-
-;; Remove directory DIR from any directory cache.
-(defun dired-uncache (dir)
- (let ((handler (find-file-name-handler dir 'dired-uncache)))
- (if handler
- (funcall handler 'dired-uncache dir))))
-
-;; dired mode key bindings and initialization
-
-(defvar dired-mode-map nil "Local keymap for dired-mode buffers.")
-(if dired-mode-map
- nil
- ;; This looks ugly when substitute-command-keys uses C-d instead d:
- ;; (define-key dired-mode-map "\C-d" 'dired-flag-file-deletion)
-
- (let ((map (make-keymap)))
- (suppress-keymap map)
- (define-key map [mouse-2] 'dired-mouse-find-file-other-window)
- ;; Commands to mark or flag certain categories of files
- (define-key map "#" 'dired-flag-auto-save-files)
- (define-key map "." 'dired-clean-directory)
- (define-key map "~" 'dired-flag-backup-files)
- (define-key map "&" 'dired-flag-garbage-files)
- ;; Upper case keys (except !) for operating on the marked files
- (define-key map "A" 'dired-do-search)
- (define-key map "C" 'dired-do-copy)
- (define-key map "B" 'dired-do-byte-compile)
- (define-key map "D" 'dired-do-delete)
- (define-key map "G" 'dired-do-chgrp)
- (define-key map "H" 'dired-do-hardlink)
- (define-key map "L" 'dired-do-load)
- (define-key map "M" 'dired-do-chmod)
- (define-key map "O" 'dired-do-chown)
- (define-key map "P" 'dired-do-print)
- (define-key map "Q" 'dired-do-query-replace)
- (define-key map "R" 'dired-do-rename)
- (define-key map "S" 'dired-do-symlink)
- (define-key map "X" 'dired-do-shell-command)
- (define-key map "Z" 'dired-do-compress)
- (define-key map "!" 'dired-do-shell-command)
- ;; Comparison commands
- (define-key map "=" 'dired-diff)
- (define-key map "\M-=" 'dired-backup-diff)
- ;; Tree Dired commands
- (define-key map "\M-\C-?" 'dired-unmark-all-files)
- (define-key map "\M-\C-d" 'dired-tree-down)
- (define-key map "\M-\C-u" 'dired-tree-up)
- (define-key map "\M-\C-n" 'dired-next-subdir)
- (define-key map "\M-\C-p" 'dired-prev-subdir)
- ;; move to marked files
- (define-key map "\M-{" 'dired-prev-marked-file)
- (define-key map "\M-}" 'dired-next-marked-file)
- ;; Make all regexp commands share a `%' prefix:
- ;; We used to get to the submap via a symbol dired-regexp-prefix,
- ;; but that seems to serve little purpose, and copy-keymap
- ;; does a better job without it.
- (define-key map "%" nil)
- (define-key map "%u" 'dired-upcase)
- (define-key map "%l" 'dired-downcase)
- (define-key map "%d" 'dired-flag-files-regexp)
- (define-key map "%m" 'dired-mark-files-regexp)
- (define-key map "%r" 'dired-do-rename-regexp)
- (define-key map "%C" 'dired-do-copy-regexp)
- (define-key map "%H" 'dired-do-hardlink-regexp)
- (define-key map "%R" 'dired-do-rename-regexp)
- (define-key map "%S" 'dired-do-symlink-regexp)
- ;; Commands for marking and unmarking.
- (define-key map "*" nil)
- (define-key map "**" 'dired-mark-executables)
- (define-key map "*/" 'dired-mark-directories)
- (define-key map "*@" 'dired-mark-symlinks)
- (define-key map "*%" 'dired-mark-files-regexp)
- (define-key map "*c" 'dired-change-marks)
- (define-key map "*s" 'dired-mark-subdir-files)
- (define-key map "*m" 'dired-mark)
- (define-key map "*u" 'dired-unmark)
- (define-key map "*?" 'dired-unmark-all-files)
- (define-key map "*!" 'dired-unmark-all-files-no-query)
- (define-key map "*\177" 'dired-unmark-backward)
- (define-key map "*\C-n" 'dired-next-marked-file)
- (define-key map "*\C-p" 'dired-prev-marked-file)
- ;; Lower keys for commands not operating on all the marked files
- (define-key map "d" 'dired-flag-file-deletion)
- (define-key map "e" 'dired-find-file)
- (define-key map "f" 'dired-find-file)
- (define-key map "\C-m" 'dired-advertised-find-file)
- (define-key map "g" 'revert-buffer)
- (define-key map "h" 'describe-mode)
- (define-key map "i" 'dired-maybe-insert-subdir)
- (define-key map "k" 'dired-do-kill-lines)
- (define-key map "l" 'dired-do-redisplay)
- (define-key map "m" 'dired-mark)
- (define-key map "n" 'dired-next-line)
- (define-key map "o" 'dired-find-file-other-window)
- (define-key map "\C-o" 'dired-display-file)
- (define-key map "p" 'dired-previous-line)
- (define-key map "q" 'dired-quit)
- (define-key map "s" 'dired-sort-toggle-or-edit)
- (define-key map "u" 'dired-unmark)
- (define-key map "v" 'dired-view-file)
- (define-key map "x" 'dired-do-flagged-delete)
- (define-key map "+" 'dired-create-directory)
- ;; moving
- (define-key map "<" 'dired-prev-dirline)
- (define-key map ">" 'dired-next-dirline)
- (define-key map "^" 'dired-up-directory)
- (define-key map " " 'dired-next-line)
- (define-key map "\C-n" 'dired-next-line)
- (define-key map "\C-p" 'dired-previous-line)
- (define-key map [down] 'dired-next-line)
- (define-key map [up] 'dired-previous-line)
- ;; hiding
- (define-key map "$" 'dired-hide-subdir)
- (define-key map "\M-$" 'dired-hide-all)
- ;; misc
- (define-key map "?" 'dired-summary)
- (define-key map "\177" 'dired-unmark-backward)
- (define-key map "\C-_" 'dired-undo)
- (define-key map "\C-xu" 'dired-undo)
-
- ;; Make menu bar items.
-
- ;; Get rid of the Edit menu bar item to save space.
- (define-key map [menu-bar edit] 'undefined)
-
- (define-key map [menu-bar subdir]
- (cons "Subdir" (make-sparse-keymap "Subdir")))
-
- (define-key map [menu-bar subdir hide-all]
- '("Hide All" . dired-hide-all))
- (define-key map [menu-bar subdir hide-subdir]
- '("Hide Subdir" . dired-hide-subdir))
- (define-key map [menu-bar subdir tree-down]
- '("Tree Down" . dired-tree-down))
- (define-key map [menu-bar subdir tree-up]
- '("Tree Up" . dired-tree-up))
- (define-key map [menu-bar subdir up]
- '("Up Directory" . dired-up-directory))
- (define-key map [menu-bar subdir prev-subdir]
- '("Prev Subdir" . dired-prev-subdir))
- (define-key map [menu-bar subdir next-subdir]
- '("Next Subdir" . dired-next-subdir))
- (define-key map [menu-bar subdir prev-dirline]
- '("Prev Dirline" . dired-prev-dirline))
- (define-key map [menu-bar subdir next-dirline]
- '("Next Dirline" . dired-next-dirline))
- (define-key map [menu-bar subdir insert]
- '("Insert This Subdir" . dired-maybe-insert-subdir))
-
- (define-key map [menu-bar immediate]
- (cons "Immediate" (make-sparse-keymap "Immediate")))
-
- (define-key map [menu-bar immediate revert-buffer]
- '("Update Buffer" . revert-buffer))
-
- (define-key map [menu-bar immediate dashes]
- '("--"))
-
- (define-key map [menu-bar immediate backup-diff]
- '("Compare with Backup" . dired-backup-diff))
- (define-key map [menu-bar immediate diff]
- '("Diff" . dired-diff))
- (define-key map [menu-bar immediate view]
- '("View This File" . dired-view-file))
- (define-key map [menu-bar immediate display]
- '("Display in Other Window" . dired-display-file))
- (define-key map [menu-bar immediate find-file-other-window]
- '("Find in Other Window" . dired-find-file-other-window))
- (define-key map [menu-bar immediate find-file]
- '("Find This File" . dired-find-file))
- (define-key map [menu-bar immediate create-directory]
- '("Create Directory..." . dired-create-directory))
-
- (define-key map [menu-bar regexp]
- (cons "Regexp" (make-sparse-keymap "Regexp")))
-
- (define-key map [menu-bar regexp downcase]
- '("Downcase" . dired-downcase))
- (define-key map [menu-bar regexp upcase]
- '("Upcase" . dired-upcase))
- (define-key map [menu-bar regexp hardlink]
- '("Hardlink..." . dired-do-hardlink-regexp))
- (define-key map [menu-bar regexp symlink]
- '("Symlink..." . dired-do-symlink-regexp))
- (define-key map [menu-bar regexp rename]
- '("Rename..." . dired-do-rename-regexp))
- (define-key map [menu-bar regexp copy]
- '("Copy..." . dired-do-copy-regexp))
- (define-key map [menu-bar regexp flag]
- '("Flag..." . dired-flag-files-regexp))
- (define-key map [menu-bar regexp mark]
- '("Mark..." . dired-mark-files-regexp))
-
- (define-key map [menu-bar mark]
- (cons "Mark" (make-sparse-keymap "Mark")))
-
- (define-key map [menu-bar mark prev]
- '("Previous Marked" . dired-prev-marked-file))
- (define-key map [menu-bar mark next]
- '("Next Marked" . dired-next-marked-file))
- (define-key map [menu-bar mark marks]
- '("Change Marks..." . dired-change-marks))
- (define-key map [menu-bar mark unmark-all]
- '("Unmark All" . dired-unmark-all-files-no-query))
- (define-key map [menu-bar mark symlinks]
- '("Mark Symlinks" . dired-mark-symlinks))
- (define-key map [menu-bar mark directories]
- '("Mark Directories" . dired-mark-directories))
- (define-key map [menu-bar mark directory]
- '("Mark Old Backups" . dired-clean-directory))
- (define-key map [menu-bar mark executables]
- '("Mark Executables" . dired-mark-executables))
- (define-key map [menu-bar mark garbage-files]
- '("Flag Garbage Files" . dired-flag-garbage-files))
- (define-key map [menu-bar mark backup-files]
- '("Flag Backup Files" . dired-flag-backup-files))
- (define-key map [menu-bar mark auto-save-files]
- '("Flag Auto-save Files" . dired-flag-auto-save-files))
- (define-key map [menu-bar mark deletion]
- '("Flag" . dired-flag-file-deletion))
- (define-key map [menu-bar mark unmark]
- '("Unmark" . dired-unmark))
- (define-key map [menu-bar mark mark]
- '("Mark" . dired-mark))
-
- (define-key map [menu-bar operate]
- (cons "Operate" (make-sparse-keymap "Operate")))
-
- (define-key map [menu-bar operate query-replace]
- '("Query Replace in Files..." . dired-do-query-replace))
- (define-key map [menu-bar operate search]
- '("Search Files..." . dired-do-search))
- (define-key map [menu-bar operate chown]
- '("Change Owner..." . dired-do-chown))
- (define-key map [menu-bar operate chgrp]
- '("Change Group..." . dired-do-chgrp))
- (define-key map [menu-bar operate chmod]
- '("Change Mode..." . dired-do-chmod))
- (define-key map [menu-bar operate load]
- '("Load" . dired-do-load))
- (define-key map [menu-bar operate compile]
- '("Byte-compile" . dired-do-byte-compile))
- (define-key map [menu-bar operate compress]
- '("Compress" . dired-do-compress))
- (define-key map [menu-bar operate print]
- '("Print" . dired-do-print))
- (define-key map [menu-bar operate hardlink]
- '("Hardlink to..." . dired-do-hardlink))
- (define-key map [menu-bar operate symlink]
- '("Symlink to..." . dired-do-symlink))
- (define-key map [menu-bar operate command]
- '("Shell Command..." . dired-do-shell-command))
- (define-key map [menu-bar operate delete]
- '("Delete" . dired-do-delete))
- (define-key map [menu-bar operate rename]
- '("Rename to..." . dired-do-rename))
- (define-key map [menu-bar operate copy]
- '("Copy to..." . dired-do-copy))
-
- (setq dired-mode-map map)))
-
-;; Dired mode is suitable only for specially formatted data.
-(put 'dired-mode 'mode-class 'special)
-
-(defun dired-mode (&optional dirname switches)
- "\
-Mode for \"editing\" directory listings.
-In dired, you are \"editing\" a list of the files in a directory and
- \(optionally) its subdirectories, in the format of `ls -lR'.
- Each directory is a page: use \\[backward-page] and \\[forward-page] to move pagewise.
-\"Editing\" means that you can run shell commands on files, visit,
- compress, load or byte-compile them, change their file attributes
- and insert subdirectories into the same buffer. You can \"mark\"
- files for later commands or \"flag\" them for deletion, either file
- by file or all files matching certain criteria.
-You can move using the usual cursor motion commands.\\<dired-mode-map>
-Letters no longer insert themselves. Digits are prefix arguments.
-Instead, type \\[dired-flag-file-deletion] to flag a file for Deletion.
-Type \\[dired-mark] to Mark a file or subdirectory for later commands.
- Most commands operate on the marked files and use the current file
- if no files are marked. Use a numeric prefix argument to operate on
- the next ARG (or previous -ARG if ARG<0) files, or just `1'
- to operate on the current file only. Prefix arguments override marks.
- Mark-using commands display a list of failures afterwards. Type \\[dired-summary]
- to see why something went wrong.
-Type \\[dired-unmark] to Unmark a file or all files of a subdirectory.
-Type \\[dired-unmark-backward] to back up one line and unflag.
-Type \\[dired-do-flagged-delete] to eXecute the deletions requested.
-Type \\[dired-advertised-find-file] to Find the current line's file
- (or dired it in another buffer, if it is a directory).
-Type \\[dired-find-file-other-window] to find file or dired directory in Other window.
-Type \\[dired-maybe-insert-subdir] to Insert a subdirectory in this buffer.
-Type \\[dired-do-rename] to Rename a file or move the marked files to another directory.
-Type \\[dired-do-copy] to Copy files.
-Type \\[dired-sort-toggle-or-edit] to toggle sorting by name/date or change the `ls' switches.
-Type \\[revert-buffer] to read all currently expanded directories again.
- This retains all marks and hides subdirs again that were hidden before.
-SPC and DEL can be used to move down and up by lines.
-
-If dired ever gets confused, you can either type \\[revert-buffer] \
-to read the
-directories again, type \\[dired-do-redisplay] \
-to relist a single or the marked files or a
-subdirectory, or type \\[dired-build-subdir-alist] to parse the buffer
-again for the directory tree.
-
-Customization variables (rename this buffer and type \\[describe-variable] on each line
-for more info):
-
- dired-listing-switches
- dired-trivial-filenames
- dired-shrink-to-fit
- dired-marker-char
- dired-del-marker
- dired-keep-marker-rename
- dired-keep-marker-copy
- dired-keep-marker-hardlink
- dired-keep-marker-symlink
-
-Hooks (use \\[describe-variable] to see their documentation):
-
- dired-before-readin-hook
- dired-after-readin-hook
- dired-mode-hook
- dired-load-hook
-
-Keybindings:
-\\{dired-mode-map}"
- ;; Not to be called interactively (e.g. dired-directory will be set
- ;; to default-directory, which is wrong with wildcards).
- (kill-all-local-variables)
- (use-local-map dired-mode-map)
- (dired-advertise) ; default-directory is already set
- (setq major-mode 'dired-mode
- mode-name "Dired"
-;; case-fold-search nil
- buffer-read-only t
- selective-display t ; for subdirectory hiding
- mode-line-buffer-identification '("Dired: %17b"))
- (set (make-local-variable 'revert-buffer-function)
- (function dired-revert))
- (set (make-local-variable 'page-delimiter)
- "\n\n")
- (set (make-local-variable 'dired-directory)
- (or dirname default-directory))
- ;; list-buffers uses this to display the dir being edited in this buffer.
- (set (make-local-variable 'list-buffers-directory)
- (expand-file-name dired-directory))
- (set (make-local-variable 'dired-actual-switches)
- (or switches dired-listing-switches))
- (set (make-local-variable 'font-lock-defaults) '(dired-font-lock-keywords t))
- (dired-sort-other dired-actual-switches t)
- (run-hooks 'dired-mode-hook))
-
-;; Idiosyncratic dired commands that don't deal with marks.
-
-(defun dired-quit ()
- "Bury the current dired buffer."
- (interactive)
- (bury-buffer))
-
-(defun dired-summary ()
- "Summarize basic Dired commands and show recent Dired errors."
- (interactive)
- (dired-why)
- ;>> this should check the key-bindings and use substitute-command-keys if non-standard
- (message
- "d-elete, u-ndelete, x-punge, f-ind, o-ther window, R-ename, C-opy, h-elp"))
-
-(defun dired-undo ()
- "Undo in a dired buffer.
-This doesn't recover lost files, it just undoes changes in the buffer itself.
-You can use it to recover marks, killed lines or subdirs.
-In the latter case, you have to do \\[dired-build-subdir-alist] to
-parse the buffer again."
- (interactive)
- (let (buffer-read-only)
- (undo)))
-
-(defun dired-next-line (arg)
- "Move down lines then position at filename.
-Optional prefix ARG says how many lines to move; default is one line."
- (interactive "p")
- (next-line arg)
- (dired-move-to-filename))
-
-(defun dired-previous-line (arg)
- "Move up lines then position at filename.
-Optional prefix ARG says how many lines to move; default is one line."
- (interactive "p")
- (previous-line arg)
- (dired-move-to-filename))
-
-(defun dired-next-dirline (arg &optional opoint)
- "Goto ARG'th next directory file line."
- (interactive "p")
- (or opoint (setq opoint (point)))
- (if (if (> arg 0)
- (re-search-forward dired-re-dir nil t arg)
- (beginning-of-line)
- (re-search-backward dired-re-dir nil t (- arg)))
- (dired-move-to-filename) ; user may type `i' or `f'
- (goto-char opoint)
- (error "No more subdirectories")))
-
-(defun dired-prev-dirline (arg)
- "Goto ARG'th previous directory file line."
- (interactive "p")
- (dired-next-dirline (- arg)))
-
-(defun dired-up-directory (&optional other-window)
- "Run dired on parent directory of current directory.
-Find the parent directory either in this buffer or another buffer.
-Creates a buffer if necessary."
- (interactive "P")
- (let* ((dir (dired-current-directory))
- (up (file-name-directory (directory-file-name dir))))
- (or (dired-goto-file (directory-file-name dir))
- ;; Only try dired-goto-subdir if buffer has more than one dir.
- (and (cdr dired-subdir-alist)
- (dired-goto-subdir up))
- (progn
- (if other-window
- (dired-other-window up)
- (dired up))
- (dired-goto-file dir)))))
-
-;; Force `f' rather than `e' in the mode doc:
-(defalias 'dired-advertised-find-file 'dired-find-file)
-(defun dired-find-file ()
- "In dired, visit the file or directory named on this line."
- (interactive)
- (let ((file-name (file-name-sans-versions (dired-get-filename) t)))
- (if (file-exists-p file-name)
- (find-file file-name)
- (error "File no longer exists; type `g' to update Dired buffer"))))
-
-(defun dired-mouse-find-file-other-window (event)
- "In dired, visit the file or directory name you click on."
- (interactive "e")
- (let (file)
- (save-excursion
- (set-buffer (window-buffer (posn-window (event-end event))))
- (save-excursion
- (goto-char (posn-point (event-end event)))
- (setq file (dired-get-filename))))
- (select-window (posn-window (event-end event)))
- (find-file-other-window (file-name-sans-versions file t))))
-
-(defun dired-view-file ()
- "In dired, examine a file in view mode, returning to dired when done.
-When file is a directory, show it in this buffer if it is inserted;
-otherwise, display it in another buffer."
- (interactive)
- (if (file-directory-p (dired-get-filename))
- (or (and (cdr dired-subdir-alist)
- (dired-goto-subdir (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 (file-name-sans-versions (dired-get-filename) t)))
-
-(defun dired-display-file ()
- "In dired, display this file or directory in another window."
- (interactive)
- (let ((file (file-name-sans-versions (dired-get-filename) t)))
- (display-buffer (find-file-noselect file))))
-
-;;; Functions for extracting and manipulating file names in dired buffers.
-
-(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.
-Optional arg LOCALP with value `no-dir' means don't include directory
- name in result. A value of t means construct name relative to
- `default-directory', which still may contain slashes if in a subdirectory.
-Optional arg NO-ERROR-IF-NOT-FILEP means return nil if no filename on
- this line, otherwise an error occurs."
- (let (case-fold-search file p1 p2)
- (save-excursion
- (if (setq p1 (dired-move-to-filename (not no-error-if-not-filep)))
- (setq p2 (dired-move-to-end-of-filename no-error-if-not-filep))))
- ;; nil if no file on this line, but no-error-if-not-filep is t:
- (if (setq file (and p1 p2 (buffer-substring p1 p2)))
- (progn
- ;; Get rid of the mouse-face property that file names have.
- (set-text-properties 0 (length file) nil file)
- ;; Unquote names quoted by ls or by dired-insert-directory.
- ;; Using read to unquote is much faster than substituting
- ;; \007 (4 chars) -> ^G (1 char) etc. in a lisp loop.
- (setq file
- (read
- (concat "\""
- ;; some ls -b don't escape quotes, argh!
- ;; This is not needed for GNU ls, though.
- (or (dired-string-replace-match
- "\\([^\\]\\|\\`\\)\"" file "\\1\\\\\"" nil t)
- file)
- "\"")))))
- (if (eq localp 'no-dir)
- file
- (and file (concat (dired-current-directory localp) file)))))
-
-(defun dired-string-replace-match (regexp string newtext
- &optional literal global)
- "Replace first match of REGEXP in STRING with NEWTEXT.
-If it does not match, nil is returned instead of the new string.
-Optional arg LITERAL means to take NEWTEXT literally.
-Optional arg GLOBAL means to replace all matches."
- (if global
- (let ((start 0))
- (while (string-match regexp string start)
- (let ((from-end (- (length string) (match-end 0))))
- (setq string (replace-match newtext t literal string))
- (setq start (- (length string) from-end))))
- string)
- (if (not (string-match regexp string 0))
- nil
- (replace-match newtext t literal string))))
-
-(defun dired-make-absolute (file &optional dir)
- ;;"Convert FILE (a pathname relative to DIR) to an absolute pathname."
- ;; We can't always use expand-file-name as this would get rid of `.'
- ;; or expand in / instead default-directory if DIR=="".
- ;; This should be good enough for ange-ftp, but might easily be
- ;; redefined (for VMS?).
- ;; It should be reasonably fast, though, as it is called in
- ;; dired-get-filename.
- (concat (or dir default-directory) file))
-
-(defun dired-make-relative (file &optional dir ignore)
- "Convert FILE (an absolute file name) to a name relative to DIR.
-If this is impossible, return FILE unchanged.
-DIR must be a directory name, not a file name."
- (or dir (setq dir default-directory))
- ;; This case comes into play if default-directory is set to
- ;; use ~.
- (if (and (> (length dir) 0) (= (aref dir 0) ?~))
- (setq dir (expand-file-name dir)))
- (if (string-match (concat "^" (regexp-quote dir)) file)
- (substring file (match-end 0))
-;;; (or no-error
-;;; (error "%s: not in directory tree growing at %s" file dir))
- file))
-
-;;; Functions for finding the file name in a dired buffer line.
-
-(defvar dired-move-to-filename-regexp
- " [A-Za-z\xa0-\xff][A-Za-z\xa0-\xff][A-Za-z\xa0-\xff] [0-3 ][0-9]\
- [ 0-9][0-9][:0-9][0-9][ 0-9] "
- "Regular expression to match a month abbreviation followed date/time.")
-
-(defvar dired-permission-flags-regexp
- "\\([^ ]\\)[-r][-w]\\([^ ]\\)[-r][-w]\\([^ ]\\)[-r][-w]\\([^ ]\\)"
- "Regular expression to match the permission flags in `ls -l'.")
-
-;; Move to first char of filename on this line.
-;; Returns position (point) or nil if no filename on this line."
-(defun dired-move-to-filename (&optional raise-error eol)
- ;; This is the UNIX version.
- (or eol (setq eol (progn (end-of-line) (point))))
- (beginning-of-line)
- (if (re-search-forward dired-move-to-filename-regexp eol t)
- (goto-char (match-end 0))
- (if raise-error
- (error "No file on this line"))))
-
-(defun dired-move-to-end-of-filename (&optional no-error)
- ;; Assumes point is at beginning of filename,
- ;; thus the rwx bit re-search-backward below will succeed in *this*
- ;; line if at all. So, it should be called only after
- ;; (dired-move-to-filename t).
- ;; On failure, signals an error (with non-nil NO-ERROR just returns nil).
- ;; This is the UNIX version.
- (let (opoint file-type executable symlink hidden case-fold-search used-F eol)
- ;; case-fold-search is nil now, so we can test for capital F:
- (setq used-F (string-match "F" dired-actual-switches)
- opoint (point)
- eol (save-excursion (end-of-line) (point))
- hidden (and selective-display
- (save-excursion (search-forward "\r" eol t))))
- (if hidden
- nil
- (save-excursion;; Find out what kind of file this is:
- ;; Restrict perm bits to be non-blank,
- ;; otherwise this matches one char to early (looking backward):
- ;; "l---------" (some systems make symlinks that way)
- ;; "----------" (plain file with zero perms)
- (if (re-search-backward
- dired-permission-flags-regexp nil t)
- (setq file-type (char-after (match-beginning 1))
- symlink (eq file-type ?l)
- ;; Only with -F we need to know whether it's an executable
- executable (and
- used-F
- (string-match
- "[xst]";; execute bit set anywhere?
- (concat
- (buffer-substring (match-beginning 2)
- (match-end 2))
- (buffer-substring (match-beginning 3)
- (match-end 3))
- (buffer-substring (match-beginning 4)
- (match-end 4))))))
- (or no-error (error "No file on this line"))))
- ;; Move point to end of name:
- (if symlink
- (if (search-forward " ->" eol t)
- (progn
- (forward-char -3)
- (and used-F
- dired-ls-F-marks-symlinks
- (eq (preceding-char) ?@);; did ls really mark the link?
- (forward-char -1))))
- (goto-char eol);; else not a symbolic link
- ;; ls -lF marks dirs, sockets and executables with exactly one
- ;; trailing character. (Executable bits on symlinks ain't mean
- ;; a thing, even to ls, but we know it's not a symlink.)
- (and used-F
- (or (memq file-type '(?d ?s))
- executable)
- (forward-char -1))))
- (or no-error
- (not (eq opoint (point)))
- (error (if hidden
- (substitute-command-keys
- "File line is hidden, type \\[dired-hide-subdir] to unhide")
- "No file on this line")))
- (if (eq opoint (point))
- nil
- (point))))
-
-
-;; Keeping Dired buffers in sync with the filesystem and with each other
-
-(defvar dired-buffers nil
- ;; Enlarged by dired-advertise
- ;; Queried by function dired-buffers-for-dir. When this detects a
- ;; killed buffer, it is removed from this list.
- "Alist of expanded directories and their associated dired buffers.")
-
-(defun dired-buffers-for-dir (dir)
-;; Return a list of buffers that dired DIR (top level or in-situ subdir).
-;; The list is in reverse order of buffer creation, most recent last.
-;; As a side effect, killed dired buffers for DIR are removed from
-;; dired-buffers.
- (setq dir (file-name-as-directory dir))
- (let ((alist dired-buffers) result elt buf)
- (while alist
- (setq elt (car alist)
- buf (cdr elt))
- (if (buffer-name buf)
- (if (dired-in-this-tree dir (car elt))
- (if (assoc dir (save-excursion
- (set-buffer buf)
- dired-subdir-alist))
- (setq result (cons buf result))))
- ;; else buffer is killed - clean up:
- (setq dired-buffers (delq elt dired-buffers)))
- (setq alist (cdr alist)))
- result))
-
-(defun dired-advertise ()
- ;;"Advertise in variable `dired-buffers' that we dired `default-directory'."
- ;; With wildcards we actually advertise too much.
- (let ((expanded-default (expand-file-name default-directory)))
- (if (memq (current-buffer) (dired-buffers-for-dir expanded-default))
- t ; we have already advertised ourselves
- (setq dired-buffers
- (cons (cons expanded-default (current-buffer))
- dired-buffers)))))
-
-(defun dired-unadvertise (dir)
- ;; Remove DIR from the buffer alist in variable dired-buffers.
- ;; This has the effect of removing any buffer whose main directory is DIR.
- ;; It does not affect buffers in which DIR is a subdir.
- ;; Removing is also done as a side-effect in dired-buffer-for-dir.
- (setq dired-buffers
- (delq (assoc (expand-file-name dir) dired-buffers) dired-buffers)))
-
-;; Tree Dired
-
-;;; utility functions
-
-(defun dired-in-this-tree (file dir)
- ;;"Is FILE part of the directory tree starting at DIR?"
- (let (case-fold-search)
- (string-match (concat "^" (regexp-quote dir)) file)))
-
-(defun dired-normalize-subdir (dir)
- ;; Prepend default-directory to DIR if relative path name.
- ;; dired-get-filename must be able to make a valid filename from a
- ;; file and its directory DIR.
- (file-name-as-directory
- (if (file-name-absolute-p dir)
- dir
- (expand-file-name dir default-directory))))
-
-(defun dired-get-subdir ()
- ;;"Return the subdir name on this line, or nil if not on a headerline."
- ;; Look up in the alist whether this is a headerline.
- (save-excursion
- (let ((cur-dir (dired-current-directory)))
- (beginning-of-line) ; alist stores b-o-l positions
- (and (zerop (- (point)
- (dired-get-subdir-min (assoc cur-dir
- dired-subdir-alist))))
- cur-dir))))
-
-;(defun dired-get-subdir-min (elt)
-; (cdr elt))
-;; can't use macro, must be redefinable for other alist format in dired-nstd.
-(defalias 'dired-get-subdir-min 'cdr)
-
-(defun dired-get-subdir-max (elt)
- (save-excursion
- (goto-char (dired-get-subdir-min elt))
- (dired-subdir-max)))
-
-(defun dired-clear-alist ()
- (while dired-subdir-alist
- (set-marker (dired-get-subdir-min (car dired-subdir-alist)) nil)
- (setq dired-subdir-alist (cdr dired-subdir-alist))))
-
-(defun dired-subdir-index (dir)
- ;; Return an index into alist for use with nth
- ;; for the sake of subdir moving commands.
- (let (found (index 0) (alist dired-subdir-alist))
- (while alist
- (if (string= dir (car (car alist)))
- (setq alist nil found t)
- (setq alist (cdr alist) index (1+ index))))
- (if found index nil)))
-
-(defun dired-next-subdir (arg &optional no-error-if-not-found no-skip)
- "Go to next subdirectory, regardless of level."
- ;; Use 0 arg to go to this directory's header line.
- ;; NO-SKIP prevents moving to end of header line, returning whatever
- ;; position was found in dired-subdir-alist.
- (interactive "p")
- (let ((this-dir (dired-current-directory))
- pos index)
- ;; nth with negative arg does not return nil but the first element
- (setq index (- (dired-subdir-index this-dir) arg))
- (setq pos (if (>= index 0)
- (dired-get-subdir-min (nth index dired-subdir-alist))))
- (if pos
- (progn
- (goto-char pos)
- (or no-skip (skip-chars-forward "^\n\r"))
- (point))
- (if no-error-if-not-found
- nil ; return nil if not found
- (error "%s directory" (if (> arg 0) "Last" "First"))))))
-
-(defun dired-build-subdir-alist ()
- "Build `dired-subdir-alist' by parsing the buffer.
-Returns the new value of the alist."
- (interactive)
- (dired-clear-alist)
- (save-excursion
- (let ((count 0)
- (buffer-read-only nil)
- new-dir-name)
- (goto-char (point-min))
- (setq dired-subdir-alist nil)
- (while (and (re-search-forward dired-subdir-regexp nil t)
- ;; Avoid taking a file name ending in a colon
- ;; as a subdir name.
- (not (save-excursion
- (goto-char (match-beginning 0))
- (beginning-of-line)
- (forward-char 2)
- (save-match-data (looking-at dired-re-perms)))))
- (save-excursion
- (goto-char (match-beginning 1))
- (setq new-dir-name
- (expand-file-name (buffer-substring (point) (match-end 1))))
- (delete-region (point) (match-end 1))
- (insert new-dir-name))
- (setq count (1+ count))
- (dired-alist-add-1 new-dir-name
- ;; Place a sub directory boundary between lines.
- (save-excursion
- (goto-char (match-beginning 0))
- (beginning-of-line)
- (point-marker))))
- (if (> count 1)
- (message "Buffer includes %d directories" count))
- ;; We don't need to sort it because it is in buffer order per
- ;; constructionem. Return new alist:
- dired-subdir-alist)))
-
-(defun dired-alist-add-1 (dir new-marker)
- ;; Add new DIR at NEW-MARKER. Don't sort.
- (setq dired-subdir-alist
- (cons (cons (dired-normalize-subdir dir) new-marker)
- dired-subdir-alist)))
-
-(defun dired-goto-next-nontrivial-file ()
- ;; Position point on first nontrivial file after point.
- (dired-goto-next-file);; so there is a file to compare with
- (if (stringp dired-trivial-filenames)
- (while (and (not (eobp))
- (string-match dired-trivial-filenames
- (file-name-nondirectory
- (or (dired-get-filename nil t) ""))))
- (forward-line 1)
- (dired-move-to-filename))))
-
-(defun dired-goto-next-file ()
- (let ((max (1- (dired-subdir-max))))
- (while (and (not (dired-move-to-filename)) (< (point) max))
- (forward-line 1))))
-
-(defun dired-goto-file (file)
- "Go to file line of FILE in this dired buffer."
- ;; Return value of point on success, else nil.
- ;; FILE must be an absolute pathname.
- ;; Loses if FILE contains control chars like "\007" for which ls
- ;; either inserts "?" or "\\007" into the buffer, so we won't find
- ;; it in the buffer.
- (interactive
- (prog1 ; let push-mark display its message
- (list (expand-file-name
- (read-file-name "Goto file: "
- (dired-current-directory))))
- (push-mark)))
- (setq file (directory-file-name file)) ; does no harm if no directory
- (let (found case-fold-search dir)
- (setq dir (or (file-name-directory file)
- (error "Need absolute pathname for %s" file)))
- (save-excursion
- ;; The hair here is to get the result of dired-goto-subdir
- ;; without really calling it if we don't have any subdirs.
- (if (if (string= dir (expand-file-name default-directory))
- (goto-char (point-min))
- (and (cdr dired-subdir-alist)
- (dired-goto-subdir dir)))
- (let ((base (file-name-nondirectory file))
- (boundary (dired-subdir-max)))
- (while (and (not found)
- ;; filenames are preceded by SPC, this makes
- ;; the search faster (e.g. for the filename "-"!).
- (search-forward (concat " " base) boundary 'move))
- ;; Match could have BASE just as initial substring or
- ;; or in permission bits or date or
- ;; not be a proper filename at all:
- (if (equal base (dired-get-filename 'no-dir t))
- ;; Must move to filename since an (actually
- ;; correct) match could have been elsewhere on the
- ;; ;; line (e.g. "-" would match somewhere in the
- ;; permission bits).
- (setq found (dired-move-to-filename))
- ;; If this isn't the right line, move forward to avoid
- ;; trying this line again.
- (forward-line 1))))))
- (and found
- ;; return value of point (i.e., FOUND):
- (goto-char found))))
-
-(defun dired-initial-position (dirname)
- ;; Where point should go in a new listing of DIRNAME.
- ;; Point assumed at beginning of new subdir line.
- ;; You may redefine this function as you wish, e.g. like in dired-x.el.
- (end-of-line)
- (if dired-trivial-filenames (dired-goto-next-nontrivial-file)))
-
-;; These are hooks which make tree dired work.
-;; They are in this file because other parts of dired need to call them.
-;; But they don't call the rest of tree dired unless there are subdirs loaded.
-
-;; This function is called for each retrieved filename.
-;; It could stand to be faster, though it's mostly function call
-;; overhead. Avoiding the function call seems to save about 10% in
-;; dired-get-filename. Make it a defsubst?
-(defun dired-current-directory (&optional localp)
- "Return the name of the subdirectory to which this line belongs.
-This returns a string with trailing slash, like `default-directory'.
-Optional argument means return a file name relative to `default-directory'."
- (let ((here (point))
- (alist (or dired-subdir-alist
- ;; probably because called in a non-dired buffer
- (error "No subdir-alist in %s" (current-buffer))))
- elt dir)
- (while alist
- (setq elt (car alist)
- dir (car elt)
- ;; use `<=' (not `<') as subdir line is part of subdir
- alist (if (<= (dired-get-subdir-min elt) here)
- nil ; found
- (cdr alist))))
- (if localp
- (dired-make-relative dir default-directory)
- dir)))
-
-;; Subdirs start at the beginning of their header lines and end just
-;; before the beginning of the next header line (or end of buffer).
-
-(defun dired-subdir-max ()
- (save-excursion
- (if (or (null (cdr dired-subdir-alist)) (not (dired-next-subdir 1 t t)))
- (point-max)
- (point))))
-
-;; Deleting files
-
-(defun dired-do-flagged-delete (&optional nomessage)
- "In dired, delete the files flagged for deletion.
-If NOMESSAGE is non-nil, we don't display any message
-if there are no flagged files."
- (interactive)
- (let* ((dired-marker-char dired-del-marker)
- (regexp (dired-marker-regexp))
- case-fold-search)
- (if (save-excursion (goto-char (point-min))
- (re-search-forward regexp nil t))
- (dired-internal-do-deletions
- ;; this can't move point since ARG is nil
- (dired-map-over-marks (cons (dired-get-filename) (point))
- nil)
- nil)
- (or nomessage
- (message "(No deletions requested)")))))
-
-(defun dired-do-delete (&optional arg)
- "Delete all marked (or next ARG) files."
- ;; This is more consistent with the file marking feature than
- ;; dired-do-flagged-delete.
- (interactive "P")
- (dired-internal-do-deletions
- ;; this may move point if ARG is an integer
- (dired-map-over-marks (cons (dired-get-filename) (point))
- arg)
- arg))
-
-(defvar dired-deletion-confirmer 'yes-or-no-p) ; or y-or-n-p?
-
-(defun dired-internal-do-deletions (l arg)
- ;; L is an alist of files to delete, with their buffer positions.
- ;; ARG is the prefix arg.
- ;; Filenames are absolute (VMS needs this for logical search paths).
- ;; (car L) *must* be the *last* (bottommost) file in the dired buffer.
- ;; That way as changes are made in the buffer they do not shift the
- ;; lines still to be changed, so the (point) values in L stay valid.
- ;; Also, for subdirs in natural order, a subdir's files are deleted
- ;; before the subdir itself - the other way around would not work.
- (let ((files (mapcar (function car) l))
- (count (length l))
- (succ 0))
- ;; canonicalize file list for pop up
- (setq files (nreverse (mapcar (function dired-make-relative) files)))
- (if (dired-mark-pop-up
- " *Deletions*" 'delete files dired-deletion-confirmer
- (format "Delete %s " (dired-mark-prompt arg files)))
- (save-excursion
- (let (failures);; files better be in reverse order for this loop!
- (while l
- (goto-char (cdr (car l)))
- (let (buffer-read-only)
- (condition-case err
- (let ((fn (car (car l))))
- ;; This test is equivalent to
- ;; (and (file-directory-p fn) (not (file-symlink-p fn)))
- ;; but more efficient
- (if (eq t (car (file-attributes fn)))
- (delete-directory fn)
- (delete-file fn))
- ;; if we get here, removing worked
- (setq succ (1+ succ))
- (message "%s of %s deletions" succ count)
- (delete-region (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point)))
- (dired-clean-up-after-deletion fn))
- (error;; catch errors from failed deletions
- (dired-log "%s\n" err)
- (setq failures (cons (car (car l)) failures)))))
- (setq l (cdr l)))
- (if (not failures)
- (message "%d deletion%s done" count (dired-plural-s count))
- (dired-log-summary
- (format "%d of %d deletion%s failed"
- (length failures) count
- (dired-plural-s count))
- failures))))
- (message "(No deletions performed)")))
- (dired-move-to-filename))
-
-;; This is a separate function for the sake of dired-x.el.
-(defun dired-clean-up-after-deletion (fn)
- ;; Clean up after a deleted file or directory FN.
- (save-excursion (and (cdr dired-subdir-alist)
- (dired-goto-subdir fn)
- (dired-kill-subdir))))
-
-;; Confirmation
-
-(defun dired-marker-regexp ()
- (concat "^" (regexp-quote (char-to-string dired-marker-char))))
-
-(defun dired-plural-s (count)
- (if (= 1 count) "" "s"))
-
-(defun dired-mark-prompt (arg files)
- ;; Return a string for use in a prompt, either the current file
- ;; name, or the marker and a count of marked files.
- (let ((count (length files)))
- (if (= count 1)
- (car files)
- ;; more than 1 file:
- (if (integerp arg)
- ;; abs(arg) = count
- ;; Perhaps this is nicer, but it also takes more screen space:
- ;;(format "[%s %d files]" (if (> arg 0) "next" "previous")
- ;; count)
- (format "[next %d files]" arg)
- (format "%c [%d files]" dired-marker-char count)))))
-
-(defun dired-pop-to-buffer (buf)
- ;; Pop up buffer BUF.
- ;; If dired-shrink-to-fit is t, make its window fit its contents.
- (if (not dired-shrink-to-fit)
- (pop-to-buffer (get-buffer-create buf))
- ;; let window shrink to fit:
- (let ((window (selected-window))
- target-lines w2)
- (cond ;; if split-window-threshold is enabled, use the largest window
- ((and (> (window-height (setq w2 (get-largest-window)))
- split-height-threshold)
- (= (frame-width) (window-width w2)))
- (setq window w2))
- ;; if the least-recently-used window is big enough, use it
- ((and (> (window-height (setq w2 (get-lru-window)))
- (* 2 window-min-height))
- (= (frame-width) (window-width w2)))
- (setq window w2)))
- (save-excursion
- (set-buffer buf)
- (goto-char (point-max))
- (skip-chars-backward "\n\r\t ")
- (setq target-lines (count-lines (point-min) (point)))
- ;; Don't forget to count the last line.
- (if (not (bolp))
- (setq target-lines (1+ target-lines))))
- (if (<= (window-height window) (* 2 window-min-height))
- ;; At this point, every window on the frame is too small to split.
- (setq w2 (display-buffer buf))
- (setq w2 (split-window window
- (max window-min-height
- (- (window-height window)
- (1+ (max window-min-height target-lines)))))))
- (set-window-buffer w2 buf)
- (if (< (1- (window-height w2)) target-lines)
- (progn
- (select-window w2)
- (enlarge-window (- target-lines (1- (window-height w2))))))
- (set-window-start w2 1)
- )))
-
-(defvar dired-no-confirm nil
-;; "If non-nil, list of symbols for commands dired should not confirm.
-;;It can be a sublist of
-;;
-;; '(byte-compile chgrp chmod chown compress copy delete hardlink load
-;; move print shell symlink uncompress)"
- )
-
-(defun dired-mark-pop-up (bufname op-symbol files function &rest args)
- ;;"Args BUFNAME OP-SYMBOL FILES FUNCTION &rest ARGS.
- ;;Return FUNCTION's result on ARGS after popping up a window (in a buffer
- ;;named BUFNAME, nil gives \" *Marked Files*\") showing the marked
- ;;files. Uses function `dired-pop-to-buffer' to do that.
- ;; FUNCTION should not manipulate files.
- ;; It should only read input (an argument or confirmation).
- ;;The window is not shown if there is just one file or
- ;; OP-SYMBOL is a member of the list in `dired-no-confirm'.
- ;;FILES is the list of marked files."
- (or bufname (setq bufname " *Marked Files*"))
- (if (or (memq op-symbol dired-no-confirm)
- (= (length files) 1))
- (apply function args)
- (save-excursion
- (set-buffer (get-buffer-create bufname))
- (erase-buffer)
- (dired-format-columns-of-files files)
- (remove-text-properties (point-min) (point-max) '(mouse-face)))
- (save-window-excursion
- (dired-pop-to-buffer bufname)
- (apply function args))))
-
-(defun dired-format-columns-of-files (files)
- ;; Files should be in forward order for this loop.
- ;; i.e., (car files) = first file in buffer.
- ;; Returns the number of lines used.
- (let* ((maxlen (+ 2 (apply 'max (mapcar 'length files))))
- (width (- (window-width (selected-window)) 2))
- (columns (max 1 (/ width maxlen)))
- (nfiles (length files))
- (rows (+ (/ nfiles columns)
- (if (zerop (% nfiles columns)) 0 1)))
- (i 0)
- (j 0))
- (setq files (nconc (copy-sequence files) ; fill up with empty fns
- (make-list (- (* columns rows) nfiles) "")))
- (setcdr (nthcdr (1- (length files)) files) files) ; make circular
- (while (< j rows)
- (while (< i columns)
- (indent-to (* i maxlen))
- (insert (car files))
- (setq files (nthcdr rows files)
- i (1+ i)))
- (insert "\n")
- (setq i 0
- j (1+ j)
- files (cdr files)))
- rows))
-
-;; Commands to mark or flag file(s) at or near current line.
-
-(defun dired-repeat-over-lines (arg function)
- ;; This version skips non-file lines.
- (let ((pos (make-marker)))
- (beginning-of-line)
- (while (and (> arg 0) (not (eobp)))
- (setq arg (1- arg))
- (beginning-of-line)
- (while (and (not (eobp)) (dired-between-files)) (forward-line 1))
- (save-excursion
- (forward-line 1)
- (move-marker pos (1+ (point))))
- (save-excursion (funcall function))
- ;; Advance to the next line--actually, to the line that *was* next.
- ;; (If FUNCTION inserted some new lines in between, skip them.)
- (goto-char pos))
- (while (and (< arg 0) (not (bobp)))
- (setq arg (1+ arg))
- (forward-line -1)
- (while (and (not (bobp)) (dired-between-files)) (forward-line -1))
- (beginning-of-line)
- (save-excursion (funcall function)))
- (move-marker pos nil)
- (dired-move-to-filename)))
-
-(defun dired-between-files ()
- ;; Point must be at beginning of line
- ;; Should be equivalent to (save-excursion (not (dired-move-to-filename)))
- ;; but is about 1.5..2.0 times as fast. (Actually that's not worth it)
- (or (looking-at "^$\\|^. *$\\|^. total\\|^. wildcard")
- (and (looking-at dired-subdir-regexp)
- (save-excursion (not (dired-move-to-filename))))))
-
-(defun dired-next-marked-file (arg &optional wrap opoint)
- "Move to the next marked file, wrapping around the end of the buffer."
- (interactive "p\np")
- (or opoint (setq opoint (point)));; return to where interactively started
- (if (if (> arg 0)
- (re-search-forward dired-re-mark nil t arg)
- (beginning-of-line)
- (re-search-backward dired-re-mark nil t (- arg)))
- (dired-move-to-filename)
- (if (null wrap)
- (progn
- (goto-char opoint)
- (error "No next marked file"))
- (message "(Wraparound for next marked file)")
- (goto-char (if (> arg 0) (point-min) (point-max)))
- (dired-next-marked-file arg nil opoint))))
-
-(defun dired-prev-marked-file (arg &optional wrap)
- "Move to the previous marked file, wrapping around the end of the buffer."
- (interactive "p\np")
- (dired-next-marked-file (- arg) wrap))
-
-(defun dired-file-marker (file)
- ;; Return FILE's marker, or nil if unmarked.
- (save-excursion
- (and (dired-goto-file file)
- (progn
- (beginning-of-line)
- (if (not (equal ?\040 (following-char)))
- (following-char))))))
-
-(defun dired-mark-files-in-region (start end)
- (let (buffer-read-only)
- (if (> start end)
- (error "start > end"))
- (goto-char start) ; assumed at beginning of line
- (while (< (point) end)
- ;; Skip subdir line and following garbage like the `total' line:
- (while (and (< (point) end) (dired-between-files))
- (forward-line 1))
- (if (and (not (looking-at dired-re-dot))
- (dired-get-filename nil t))
- (progn
- (delete-char 1)
- (insert dired-marker-char)))
- (forward-line 1))))
-
-(defun dired-mark (arg)
- "Mark the current (or next ARG) files.
-If on a subdir headerline, mark all its files except `.' and `..'.
-
-Use \\[dired-unmark-all-files] to remove all marks
-and \\[dired-unmark] on a subdir to remove the marks in
-this subdir."
- (interactive "P")
- (if (dired-get-subdir)
- (save-excursion (dired-mark-subdir-files))
- (let (buffer-read-only)
- (dired-repeat-over-lines
- (prefix-numeric-value arg)
- (function (lambda () (delete-char 1) (insert dired-marker-char)))))))
-
-(defun dired-unmark (arg)
- "Unmark the current (or next ARG) files.
-If looking at a subdir, unmark all its files except `.' and `..'."
- (interactive "P")
- (let ((dired-marker-char ?\040))
- (dired-mark arg)))
-
-(defun dired-flag-file-deletion (arg)
- "In dired, flag the current line's file for deletion.
-With prefix arg, repeat over several lines.
-
-If on a subdir headerline, mark all its files except `.' and `..'."
- (interactive "P")
- (let ((dired-marker-char dired-del-marker))
- (dired-mark arg)))
-
-(defun dired-unmark-backward (arg)
- "In dired, move up lines and remove deletion flag there.
-Optional prefix ARG says how many lines to unflag; default is one line."
- (interactive "p")
- (dired-unmark (- arg)))
-
-;;; Commands to mark or flag files based on their characteristics or names.
-
-(defvar dired-regexp-history nil
- "History list of regular expressions used in Dired commands.")
-
-(defun dired-read-regexp (prompt)
- (read-from-minibuffer prompt nil nil nil 'dired-regexp-history))
-
-(defun dired-mark-files-regexp (regexp &optional marker-char)
- "Mark all files matching REGEXP for use in later commands.
-A prefix argument means to unmark them instead.
-`.' and `..' are never marked.
-
-REGEXP is an Emacs regexp, not a shell wildcard. Thus, use `\\.o$' for
-object files--just `.o' will mark more than you might think."
- (interactive
- (list (dired-read-regexp (concat (if current-prefix-arg "Unmark" "Mark")
- " files (regexp): "))
- (if current-prefix-arg ?\040)))
- (let ((dired-marker-char (or marker-char dired-marker-char)))
- (dired-mark-if
- (and (not (looking-at dired-re-dot))
- (not (eolp)) ; empty line
- (let ((fn (dired-get-filename nil t)))
- (and fn (string-match regexp (file-name-nondirectory fn)))))
- "matching file")))
-
-(defun dired-flag-files-regexp (regexp)
- "In dired, flag all files containing the specified REGEXP for deletion.
-The match is against the non-directory part of the filename. Use `^'
- and `$' to anchor matches. Exclude subdirs by hiding them.
-`.' and `..' are never flagged."
- (interactive (list (dired-read-regexp "Flag for deletion (regexp): ")))
- (dired-mark-files-regexp regexp dired-del-marker))
-
-(defun dired-mark-symlinks (unflag-p)
- "Mark all symbolic links.
-With prefix argument, unflag all those files."
- (interactive "P")
- (let ((dired-marker-char (if unflag-p ?\040 dired-marker-char)))
- (dired-mark-if (looking-at dired-re-sym) "symbolic link")))
-
-(defun dired-mark-directories (unflag-p)
- "Mark all directory file lines except `.' and `..'.
-With prefix argument, unflag all those files."
- (interactive "P")
- (let ((dired-marker-char (if unflag-p ?\040 dired-marker-char)))
- (dired-mark-if (and (looking-at dired-re-dir)
- (not (looking-at dired-re-dot)))
- "directory file")))
-
-(defun dired-mark-executables (unflag-p)
- "Mark all executable files.
-With prefix argument, unflag all those files."
- (interactive "P")
- (let ((dired-marker-char (if unflag-p ?\040 dired-marker-char)))
- (dired-mark-if (looking-at dired-re-exe) "executable file")))
-
-;; dired-x.el has a dired-mark-sexp interactive command: mark
-;; files for which PREDICATE returns non-nil.
-
-(defun dired-flag-auto-save-files (&optional unflag-p)
- "Flag for deletion files whose names suggest they are auto save files.
-A prefix argument says to unflag those files instead."
- (interactive "P")
- (let ((dired-marker-char (if unflag-p ?\040 dired-del-marker)))
- (dired-mark-if
- ;; It is less than general to check for # here,
- ;; but it's the only way this runs fast enough.
- (and (save-excursion (end-of-line)
- (or
- (eq (preceding-char) ?#)
- ;; Handle executables in case of -F option.
- ;; We need not worry about the other kinds
- ;; of markings that -F makes, since they won't
- ;; appear on real auto-save files.
- (if (eq (preceding-char) ?*)
- (progn
- (forward-char -1)
- (eq (preceding-char) ?#)))))
- (not (looking-at dired-re-dir))
- (let ((fn (dired-get-filename t t)))
- (if fn (auto-save-file-name-p
- (file-name-nondirectory fn)))))
- "auto save file")))
-
-(defvar dired-garbage-files-regexp
- "\\.log$\\|\\.toc$\\|.dvi$|\\.bak$\\|\\.orig$\\|\\.rej$"
- "*Regular expression to match \"garbage\" files for `dired-flag-garbage-files'.")
-
-(defun dired-flag-garbage-files ()
- (interactive)
- "Flag for deletion all files that match `dired-garbage-files-regexp'."
- (dired-flag-files-regexp dired-garbage-files-regexp))
-
-(defun dired-flag-backup-files (&optional unflag-p)
- "Flag all backup files (names ending with `~') for deletion.
-With prefix argument, unflag these files."
- (interactive "P")
- (let ((dired-marker-char (if unflag-p ?\ dired-del-marker)))
- (dired-mark-if
- ;; Don't call backup-file-name-p unless the last character looks like
- ;; it might be the end of a backup file name. This isn't very general,
- ;; but it's the only way this runs fast enough.
- (and (save-excursion (end-of-line)
- ;; Handle executables in case of -F option.
- ;; We need not worry about the other kinds
- ;; of markings that -F makes, since they won't
- ;; appear on real backup files.
- (if (eq (preceding-char) ?*)
- (forward-char -1))
- (eq (preceding-char) ?~))
- (not (looking-at dired-re-dir))
- (let ((fn (dired-get-filename t t)))
- (if fn (backup-file-name-p fn))))
- "backup file")))
-
-(defun dired-change-marks (&optional old new)
- "Change all OLD marks to NEW marks.
-OLD and NEW are both characters used to mark files."
- (interactive
- (let* ((cursor-in-echo-area t)
- (old (progn (message "Change (old mark): ") (read-char)))
- (new (progn (message "Change %c marks to (new mark): " old)
- (read-char))))
- (list old new)))
- (if (or (eq old ?\r) (eq new ?\r))
- (ding)
- (let ((string (format "\n%c" old))
- (buffer-read-only))
- (save-excursion
- (goto-char (point-min))
- (while (search-forward string nil t)
- (if (if (= old ?\ )
- (save-match-data
- (dired-get-filename 'no-dir t))
- t)
- (subst-char-in-region (match-beginning 0)
- (match-end 0) old new)))))))
-
-(defun dired-unmark-all-files-no-query ()
- "Remove all marks from all files in the Dired buffer."
- (interactive)
- (dired-unmark-all-files ?\r))
-
-(defun dired-unmark-all-files (mark &optional arg)
- "Remove a specific mark (or any mark) from every file.
-After this command, type the mark character to remove,
-or type RET to remove all marks.
-With prefix arg, query for each marked file.
-Type \\[help-command] at that time for help."
- (interactive "cRemove marks (RET means all): \nP")
- (save-excursion
- (let* ((count 0)
- buffer-read-only case-fold-search query
- (string (format "\n%c" mark))
- (help-form "\
-Type SPC or `y' to unmark one file, DEL or `n' to skip to next,
-`!' to unmark all remaining files with no more questions."))
- (goto-char (point-min))
- (while (if (eq mark ?\r)
- (re-search-forward dired-re-mark nil t)
- (search-forward string nil t))
- (if (or (not arg)
- (dired-query 'query "Unmark file `%s'? "
- (dired-get-filename t)))
- (progn (subst-char-in-region (1- (point)) (point)
- (preceding-char) ?\ )
- (setq count (1+ count)))))
- (message (if (= count 1) "1 mark removed"
- "%d marks removed")
- count))))
-
-;; Logging failures operating on files, and showing the results.
-
-(defvar dired-log-buffer "*Dired log*")
-
-(defun dired-why ()
- "Pop up a buffer with error log output from Dired.
-A group of errors from a single command ends with a formfeed.
-Thus, use \\[backward-page] to find the beginning of a group of errors."
- (interactive)
- (if (get-buffer dired-log-buffer)
- (let ((owindow (selected-window))
- (window (display-buffer (get-buffer dired-log-buffer))))
- (unwind-protect
- (progn
- (select-window window)
- (goto-char (point-max))
- (recenter -1))
- (select-window owindow)))))
-
-(defun dired-log (log &rest args)
- ;; Log a message or the contents of a buffer.
- ;; If LOG is a string and there are more args, it is formatted with
- ;; those ARGS. Usually the LOG string ends with a \n.
- ;; End each bunch of errors with (dired-log t): this inserts
- ;; current time and buffer, and a \f (formfeed).
- (let ((obuf (current-buffer)))
- (unwind-protect ; want to move point
- (progn
- (set-buffer (get-buffer-create dired-log-buffer))
- (goto-char (point-max))
- (let (buffer-read-only)
- (cond ((stringp log)
- (insert (if args
- (apply (function format) log args)
- log)))
- ((bufferp log)
- (insert-buffer log))
- ((eq t log)
- (insert "\n\t" (current-time-string)
- "\tBuffer `" (buffer-name obuf) "'\n\f\n")))))
- (set-buffer obuf))))
-
-(defun dired-log-summary (string failures)
- (message (if failures "%s--type ? for details (%s)"
- "%s--type ? for details")
- string failures)
- ;; Log a summary describing a bunch of errors.
- (dired-log (concat "\n" string))
- (dired-log t))
-
-;;; Sorting
-
-;; Most ls can only sort by name or by date (with -t), nothing else.
-;; GNU ls sorts on size with -S, on extension with -X, and unsorted with -U.
-;; So anything that does not contain these is sort "by name".
-
-(defvar dired-ls-sorting-switches "SXU"
- "String of `ls' switches (single letters) except `t' that influence sorting.")
-
-(defvar dired-sort-by-date-regexp
- (concat "^-[^" dired-ls-sorting-switches
- "]*t[^" dired-ls-sorting-switches "]*$")
- "Regexp recognized by dired to set `by date' mode.")
-
-(defvar dired-sort-by-name-regexp
- (concat "^-[^t" dired-ls-sorting-switches "]+$")
- "Regexp recognized by dired to set `by name' mode.")
-
-(defun dired-sort-set-modeline ()
- ;; Set modeline display according to dired-actual-switches.
- ;; Modeline display of "by name" or "by date" guarantees the user a
- ;; match with the corresponding regexps. Non-matching switches are
- ;; shown literally.
- (setq mode-name
- (let (case-fold-search)
- (cond ((string-match dired-sort-by-name-regexp dired-actual-switches)
- "Dired by name")
- ((string-match dired-sort-by-date-regexp dired-actual-switches)
- "Dired by date")
- (t
- (concat "Dired " dired-actual-switches)))))
- (force-mode-line-update))
-
-(defun dired-sort-toggle-or-edit (&optional arg)
- "Toggle between sort by date/name and refresh the dired buffer.
-With a prefix argument you can edit the current listing switches instead."
- (interactive "P")
- (if arg
- (dired-sort-other
- (read-string "ls switches (must contain -l): " dired-actual-switches))
- (dired-sort-toggle)))
-
-(defun dired-sort-toggle ()
- ;; Toggle between sort by date/name. Reverts the buffer.
- (setq dired-actual-switches
- (let (case-fold-search)
- (concat
- "-l"
- (dired-replace-in-string (concat "[-lt"
- dired-ls-sorting-switches "]")
- ""
- dired-actual-switches)
- (if (string-match (concat "[t" dired-ls-sorting-switches "]")
- dired-actual-switches)
- ""
- "t"))))
- (dired-sort-set-modeline)
- (revert-buffer))
-
-(defun dired-replace-in-string (regexp newtext string)
- ;; Replace REGEXP with NEWTEXT everywhere in STRING and return result.
- ;; NEWTEXT is taken literally---no \\DIGIT escapes will be recognized.
- (let ((result "") (start 0) mb me)
- (while (string-match regexp string start)
- (setq mb (match-beginning 0)
- me (match-end 0)
- result (concat result (substring string start mb) newtext)
- start me))
- (concat result (substring string start))))
-
-(defun dired-sort-other (switches &optional no-revert)
- ;; Specify new ls SWITCHES for current dired buffer. Values matching
- ;; `dired-sort-by-date-regexp' or `dired-sort-by-name-regexp' set the
- ;; minor mode accordingly, others appear literally in the mode line.
- ;; With optional second arg NO-REVERT, don't refresh the listing afterwards.
- (setq dired-actual-switches switches)
- (if (eq major-mode 'dired-mode) (dired-sort-set-modeline))
- (or no-revert (revert-buffer)))
-
-;; To make this file smaller, the less common commands
-;; go in a separate file. But autoload them here
-;; to make the separation invisible.
-
-(autoload 'dired-diff "dired-aux"
- "Compare file at point with file FILE using `diff'.
-FILE defaults to the file at the mark.
-The prompted-for file is the first file given to `diff'."
- t)
-
-(autoload 'dired-backup-diff "dired-aux"
- "Diff this file with its backup file or vice versa.
-Uses the latest backup, if there are several numerical backups.
-If this file is a backup, diff it with its original.
-The backup file is the first file given to `diff'."
- t)
-
-(autoload 'dired-clean-directory "dired-aux"
- "Flag numerical backups for deletion.
-Spares `dired-kept-versions' latest versions, and `kept-old-versions' oldest.
-Positive prefix arg KEEP overrides `dired-kept-versions';
-Negative prefix arg KEEP overrides `kept-old-versions' with KEEP made positive.
-
-To clear the flags on these files, you can use \\[dired-flag-backup-files]
-with a prefix argument."
- t)
-
-(autoload 'dired-do-chmod "dired-aux"
- "Change the mode of the marked (or next ARG) files.
-This calls chmod, thus symbolic modes like `g+w' are allowed."
- t)
-
-(autoload 'dired-do-chgrp "dired-aux"
- "Change the group of the marked (or next ARG) files."
- t)
-
-(autoload 'dired-do-chown "dired-aux"
- "Change the owner of the marked (or next ARG) files."
- t)
-
-(autoload 'dired-do-print "dired-aux"
- "Print the marked (or next ARG) files.
-Uses the shell command coming from variables `lpr-command' and
-`lpr-switches' as default."
- t)
-
-(autoload 'dired-do-shell-command "dired-aux"
- "Run a shell command COMMAND on the marked files.
-If no files are marked or a specific numeric prefix arg is given,
-the next ARG files are used. Just \\[universal-argument] means the current file.
-The prompt mentions the file(s) or the marker, as appropriate.
-
-If there is output, it goes to a separate buffer.
-
-Normally the command is run on each file individually.
-However, if there is a `*' in the command then it is run
-just once with the entire file list substituted there.
-
-No automatic redisplay of dired buffers is attempted, as there's no
-telling what files the command may have changed. Type
-\\[dired-do-redisplay] to redisplay the marked files.
-
-The shell command has the top level directory as working directory, so
-output files usually are created there instead of in a subdir."
- t)
-
-(autoload 'dired-do-kill-lines "dired-aux"
- "Kill all marked lines (not the files).
-With a prefix arg, kill all lines not marked or flagged."
- t)
-
-(autoload 'dired-do-compress "dired-aux"
- "Compress or uncompress marked (or next ARG) files."
- t)
-
-(autoload 'dired-do-byte-compile "dired-aux"
- "Byte compile marked (or next ARG) Emacs Lisp files."
- t)
-
-(autoload 'dired-do-load "dired-aux"
- "Load the marked (or next ARG) Emacs Lisp files."
- t)
-
-(autoload 'dired-do-redisplay "dired-aux"
- "Redisplay all marked (or next ARG) files.
-If on a subdir line, redisplay that subdirectory. In that case,
-a prefix arg lets you edit the `ls' switches used for the new listing."
- t)
-
-(autoload 'dired-create-directory "dired-aux"
- "Create a directory called DIRECTORY."
- t)
-
-(autoload 'dired-do-copy "dired-aux"
- "Copy all marked (or next ARG) files, or copy the current file.
-Thus, a zero prefix argument copies nothing. But it toggles the
-variable `dired-copy-preserve-time' (which see)."
- t)
-
-(autoload 'dired-do-symlink "dired-aux"
- "Make symbolic links to current file or all marked (or next ARG) files.
-When operating on just the current file, you specify the new name.
-When operating on multiple or marked files, you specify a directory
-and new symbolic links are made in that directory
-with the same names that the files currently have."
- t)
-
-(autoload 'dired-do-hardlink "dired-aux"
- "Add names (hard links) current file or all marked (or next ARG) files.
-When operating on just the current file, you specify the new name.
-When operating on multiple or marked files, you specify a directory
-and new hard links are made in that directory
-with the same names that the files currently have."
- t)
-
-(autoload 'dired-do-rename "dired-aux"
- "Rename current file or all marked (or next ARG) files.
-When renaming just the current file, you specify the new name.
-When renaming multiple or marked files, you specify a directory."
- t)
-
-(autoload 'dired-do-rename-regexp "dired-aux"
- "Rename marked files containing REGEXP to NEWNAME.
-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.
-NEWNAME may contain \\=\\<n> or \\& as in `query-replace-regexp'.
-REGEXP defaults to the last regexp used.
-With a zero prefix arg, renaming by regexp affects the complete
- pathname - usually only the non-directory part of file names is used
- and changed."
- t)
-
-(autoload 'dired-do-copy-regexp "dired-aux"
- "Copy all marked files containing REGEXP to NEWNAME.
-See function `dired-rename-regexp' for more info."
- t)
-
-(autoload 'dired-do-hardlink-regexp "dired-aux"
- "Hardlink all marked files containing REGEXP to NEWNAME.
-See function `dired-rename-regexp' for more info."
- t)
-
-(autoload 'dired-do-symlink-regexp "dired-aux"
- "Symlink all marked files containing REGEXP to NEWNAME.
-See function `dired-rename-regexp' for more info."
- t)
-
-(autoload 'dired-upcase "dired-aux"
- "Rename all marked (or next ARG) files to upper case."
- t)
-
-(autoload 'dired-downcase "dired-aux"
- "Rename all marked (or next ARG) files to lower case."
- t)
-
-(autoload 'dired-maybe-insert-subdir "dired-aux"
- "Insert this subdirectory into the same dired buffer.
-If it is already present, just move to it (type \\[dired-do-redisplay] to refresh),
- else inserts it at its natural place (as `ls -lR' would have done).
-With a prefix arg, you may edit the ls switches used for this listing.
- You can add `R' to the switches to expand the whole tree starting at
- this subdirectory.
-This function takes some pains to conform to `ls -lR' output."
- t)
-
-(autoload 'dired-next-subdir "dired-aux"
- "Go to next subdirectory, regardless of level."
- t)
-
-(autoload 'dired-prev-subdir "dired-aux"
- "Go to previous subdirectory, regardless of level.
-When called interactively and not on a subdir line, go to this subdir's line."
- t)
-
-(autoload 'dired-goto-subdir "dired-aux"
- "Go to end of header line of DIR in this dired buffer.
-Return value of point on success, otherwise return nil.
-The next char is either \\n, or \\r if DIR is hidden."
- t)
-
-(autoload 'dired-mark-subdir-files "dired-aux"
- "Mark all files except `.' and `..'."
- t)
-
-(autoload 'dired-kill-subdir "dired-aux"
- "Remove all lines of current subdirectory.
-Lower levels are unaffected."
- t)
-
-(autoload 'dired-tree-up "dired-aux"
- "Go up ARG levels in the dired tree."
- t)
-
-(autoload 'dired-tree-down "dired-aux"
- "Go down in the dired tree."
- t)
-
-(autoload 'dired-hide-subdir "dired-aux"
- "Hide or unhide the current subdirectory and move to next directory.
-Optional prefix arg is a repeat factor.
-Use \\[dired-hide-all] to (un)hide all directories."
- t)
-
-(autoload 'dired-hide-all "dired-aux"
- "Hide all subdirectories, leaving only their header lines.
-If there is already something hidden, make everything visible again.
-Use \\[dired-hide-subdir] to (un)hide a particular subdirectory."
- t)
-
-(if (eq system-type 'vax-vms)
- (load "dired-vms"))
-
-(provide 'dired)
-
-(run-hooks 'dired-load-hook) ; for your customizations
-
-;;; dired.el ends here
diff --git a/lisp/dirtrack.el b/lisp/dirtrack.el
deleted file mode 100644
index 9f289f31fba..00000000000
--- a/lisp/dirtrack.el
+++ /dev/null
@@ -1,244 +0,0 @@
-;;; dirtrack.el --- Directory Tracking by watching the prompt
-
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Peter Breton
-;; Created: Sun Nov 17 1996
-;; Keywords: processes
-;; Time-stamp: <96/12/26 09:23:01 peter>
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Shell directory tracking by watching the prompt.
-;;
-;; This is yet another attempt at a directory-tracking package for
-;; Emacs shell-mode. However, this package makes one strong assumption:
-;; that you can customize your shell's prompt to contain the
-;; current working directory. Most shells do support this, including
-;; almost every type of Bourne and C shell on Unix, the native shells on
-;; Windows95 (COMMAND.COM) and Windows NT (CMD.EXE), and most 3rd party
-;; Windows shells. If you cannot do this, or do not wish to, this package
-;; will be useless to you.
-;;
-;; Installation:
-;;
-;; 1) Set your shell's prompt to contain the current working directory.
-;; You may need to consult your shell's documentation to find out how to
-;; do this.
-;;
-;; Note that directory tracking is done by matching regular expressions,
-;; therefore it is *VERY IMPORTANT* for your prompt to be easily
-;; distinguishable from other output. If your prompt regexp is too general,
-;; you will see error messages from the dirtrack filter as it attempts to cd
-;; to non-existent directories.
-;;
-;; 2) Set the variable 'dirtrack-list' to an appropriate value. This
-;; should be a list of two elements: the first is a regular expression
-;; which matches your prompt up to and including the pathname part.
-;; The second is a number which tells which regular expression group to
-;; match to extract only the pathname. If you use a multi-line prompt,
-;; add 't' as a third element. Note that some of the functions in
-;; 'comint.el' assume a single-line prompt (eg, comint-bol).
-;;
-;; Determining this information may take some experimentation. Setting
-;; the variable 'dirtrack-debug' may help; it causes the directory-tracking
-;; filter to log messages to the buffer 'dirtrack-debug-buffer'.
-;;
-;; 3) Autoload directory tracking by adding the following to your .emacs:
-;;
-;; (autoload 'dirtrack "dirtrack"
-;; "Directory tracking by watching the prompt")
-;;
-;; 4) Add a hook to shell-mode to enable the directory tracking:
-;;
-;; (add-hook 'shell-mode-hook
-;; (function (lambda ()
-;; (setq comint-output-filter-functions
-;; (append (list 'dirtrack)
-;; comint-output-filter-functions)))))
-;;
-;; You may wish to turn ordinary shell tracking off by calling
-;; 'shell-dirtrack-toggle' or setting 'shell-dirtrackp'.
-;;
-;; Examples:
-;;
-;; 1) On Windows NT, my prompt is set to emacs$S$P$G.
-;; 'dirtrack-list' is set to (list "^emacs \\([a-zA-Z]:.*\\)>" 1)
-;;
-;; 2) On Solaris running bash, my prompt is set like this:
-;; PS1="\w\012emacs@\h(\!) [\t]% "
-;; 'dirtrack-list' is set to (list "^\\([/~].*\\)\nemacs@[^%]+% *" 1 t)
-;;
-;; I'd appreciate other examples from people who use this package.
-
-;;; Code:
-
-(eval-when-compile
- (require 'comint)
- (require 'shell))
-
-(defvar dirtrack-list (list "^emacs \\([a-zA-Z]:.*\\)>" 1)
- "*List for directory tracking.
-First item is a regexp that describes where to find the path in a prompt.
-Second is a number, the regexp group to match. Optional third item is
-whether the prompt is multi-line. If nil or omitted, prompt is assumed to
-be on a single line.")
-
-(make-variable-buffer-local 'dirtrack-list)
-
-(defvar dirtrack-debug nil
- "*If non-nil, the function 'dirtrack' will report debugging info.")
-
-(defvar dirtrack-debug-buffer "*Directory Tracking Log*"
- "Buffer to write directory tracking debug information.")
-
-(defvar dirtrackp t
- "*If non-nil, directory tracking via 'dirtrack' is enabled.")
-
-(make-variable-buffer-local 'dirtrackp)
-
-(defvar dirtrack-directory-function
- (if (memq system-type (list 'ms-dos 'windows-nt))
- 'dirtrack-windows-directory-function
- 'dirtrack-default-directory-function)
- "*Function to apply to the prompt directory for comparison purposes.")
-
-(defvar dirtrack-canonicalize-function
- (if (memq system-type (list 'ms-dos 'windows-nt))
- 'downcase 'identity)
- "*Function to apply to the default directory for comparison purposes.")
-
-(defun dirtrack-default-directory-function (dir)
- "Return a canonical directory for comparison purposes.
-Such a directory ends with a forward slash."
- (let ((directory dir))
- (if (not (char-equal ?/ (string-to-char (substring directory -1))))
- (concat directory "/")
- directory)))
-
-(defun dirtrack-windows-directory-function (dir)
- "Return a canonical directory for comparison purposes.
-Such a directory is all lowercase, has forward-slashes as delimiters,
-and ends with a forward slash."
- (let ((directory dir))
- (setq directory (downcase (replace-slash directory t)))
- (if (not (char-equal ?/ (string-to-char (substring directory -1))))
- (concat directory "/")
- directory)))
-
-(defconst forward-slash (regexp-quote "/"))
-(defconst backward-slash (regexp-quote "\\"))
-
-(defun replace-slash (string &optional opposite)
- "Replace forward slashes with backwards ones.
-If additional argument is non-nil, replace backwards slashes with
-forward ones."
- (let ((orig (if opposite backward-slash forward-slash))
- (replace (if opposite forward-slash backward-slash))
- (newstring string)
- )
- (while (string-match orig newstring)
- (setq newstring (replace-match replace nil t newstring)))
- newstring))
-
-;; Copied from shell.el
-(defun dirtrack-toggle ()
- "Enable or disable Dirtrack directory tracking in a shell buffer."
- (interactive)
- (setq dirtrackp (not dirtrackp))
- (message "Directory tracking %s" (if dirtrackp "ON" "OFF")))
-
-(defun dirtrack-debug-message (string)
- (let ((buf (current-buffer))
- (debug-buf (get-buffer-create dirtrack-debug-buffer))
- )
- (set-buffer debug-buf)
- (insert (concat string "\n"))
- (set-buffer buf)
- ))
-
-;;;###autoload
-(defun dirtrack (input)
- (if (null dirtrackp)
- nil
- (let ((prompt-path)
- (current-dir default-directory)
- (matched)
- (dirtrack-regexp (nth 0 dirtrack-list))
- (match-num (nth 1 dirtrack-list))
- (multi-line (nth 2 dirtrack-list))
- )
- ;; No output?
- (if (eq (point) (point-min))
- nil
- (save-excursion
- (goto-char comint-last-output-start)
- ;; Look for the prompt
- (if multi-line
- (and
- (goto-char (point-max))
- (setq matched
- (re-search-backward
- dirtrack-regexp
- comint-last-output-start
- t)))
- (beginning-of-line)
- (setq matched (looking-at dirtrack-regexp)))
- ;; No match
- (if (null matched)
- (and dirtrack-debug
- (dirtrack-debug-message
- (format
- "Failed to match regexp: %s"
- dirtrack-regexp)))
- (setq prompt-path
- (buffer-substring-no-properties
- (match-beginning match-num) (match-end match-num)))
- ;; Empty string
- (if (not (> (length prompt-path) 0))
- (and dirtrack-debug
- (dirtrack-debug-message "Match is empty string"))
- ;; Transform prompts into canonical forms
- (setq prompt-path (funcall dirtrack-directory-function
- prompt-path))
- (setq current-dir (funcall dirtrack-canonicalize-function
- current-dir))
- (and dirtrack-debug
- (dirtrack-debug-message
- (format
- "Prompt is %s\nCurrent directory is %s"
- prompt-path current-dir)))
- ;; Compare them
- (if (or (string= current-dir prompt-path)
- (string= current-dir
- (abbreviate-file-name prompt-path)))
- (and dirtrack-debug
- (dirtrack-debug-message
- (format "Not changing directory")))
- ;; Change directory
- (shell-process-cd prompt-path)
- (and dirtrack-debug
- (dirtrack-debug-message
- (format "Changing directory to %s" prompt-path))))
- )))))))
-
-(provide 'dirtrack)
-
-;;; dirtrack.el ends here
diff --git a/lisp/disp-table.el b/lisp/disp-table.el
deleted file mode 100644
index 193bf5fbb7d..00000000000
--- a/lisp/disp-table.el
+++ /dev/null
@@ -1,198 +0,0 @@
-;;; disp-table.el --- functions for dealing with char tables.
-
-;; Copyright (C) 1987, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Erik Naggum <erik@naggum.no>
-;; Based on a previous version by Howard Gayle
-;; Maintainer: FSF
-;; Keywords: i18n
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(put 'display-table 'char-table-extra-slots 6)
-
-;;;###autoload
-(defun make-display-table ()
- "Return a new, empty display table."
- (make-char-table 'display-table nil))
-
-(or standard-display-table
- (setq standard-display-table (make-display-table)))
-
-;;; Display-table slot names. The property value says which slot.
-
-(put 'truncation 'display-table-slot 0)
-(put 'wrap 'display-table-slot 1)
-(put 'escape 'display-table-slot 2)
-(put 'control 'display-table-slot 3)
-(put 'selective-display 'display-table-slot 4)
-(put 'vertical-border 'display-table-slot 5)
-
-;;;###autoload
-(defun display-table-slot (display-table slot)
- "Return the value of the extra slot in DISPLAY-TABLE named SLOT.
-SLOT may be a number from 0 to 5 inclusive, or a slot name (symbol).
-Valid symbols are `truncation', `wrap', `escape', `control',
-`selective-display', and `vertical-border'."
- (let ((slot-number
- (if (numberp slot) slot
- (or (get slot 'display-table-slot)
- (error "Invalid display-table slot name: %s" slot)))))
- (char-table-extra-slot display-table slot-number)))
-
-;;;###autoload
-(defun set-display-table-slot (display-table slot value)
- "Set the value of the extra slot in DISPLAY-TABLE named SLOT to VALUE.
-SLOT may be a number from 0 to 5 inclusive, or a name (symbol).
-Valid symbols are `truncation', `wrap', `escape', `control',
-`selective-display', and `vertical-border'."
- (let ((slot-number
- (if (numberp slot) slot
- (or (get slot 'display-table-slot)
- (error "Invalid display-table slot name: %s" slot)))))
- (set-char-table-extra-slot display-table slot-number value)))
-
-;;;###autoload
-(defun describe-display-table (dt)
- "Describe the display table DT in a help buffer."
- (with-output-to-temp-buffer "*Help*"
- (princ "\nTruncation glyph: ")
- (prin1 (display-table-slot dt 'truncation))
- (princ "\nWrap glyph: ")
- (prin1 (display-table-slot dt 'wrap))
- (princ "\nEscape glyph: ")
- (prin1 (display-table-slot dt 'escape))
- (princ "\nCtrl glyph: ")
- (prin1 (display-table-slot dt 'control))
- (princ "\nSelective display glyph sequence: ")
- (prin1 (display-table-slot dt 'selective-display))
- (princ "\nVertical window border glyph: ")
- (prin1 (display-table-slot dt 'vertical-border))
- (princ "\nCharacter display glyph sequences:\n")
- (save-excursion
- (set-buffer standard-output)
- (let ((vector (make-vector 256 nil))
- (i 0))
- (while (< i 256)
- (aset vector i (aref dt i))
- (setq i (1+ i)))
- (describe-vector vector))
- (help-mode))
- (print-help-return-message)))
-
-;;;###autoload
-(defun describe-current-display-table ()
- "Describe the display table in use in the selected window and buffer."
- (interactive)
- (let ((disptab (or (window-display-table (selected-window))
- buffer-display-table
- standard-display-table)))
- (if disptab
- (describe-display-table disptab)
- (message "No display table"))))
-
-;;;###autoload
-(defun standard-display-8bit (l h)
- "Display characters in the range L to H literally."
- (while (<= l h)
- (if (and (>= l ?\ ) (< l 127))
- (aset standard-display-table l nil)
- (aset standard-display-table l (vector l)))
- (setq l (1+ l))))
-
-;;;###autoload
-(defun standard-display-default (l h)
- "Display characters in the range L to H using the default notation."
- (while (<= l h)
- (if (and (>= l ?\ ) (< l 127))
- (aset standard-display-table l nil)
- (aset standard-display-table l nil))
- (setq l (1+ l))))
-
-;; This function does NOT take terminal-dependent escape sequences.
-;; For that, you need to go through create-glyph. Use one of the
-;; other functions below, or roll your own.
-;;;###autoload
-(defun standard-display-ascii (c s)
- "Display character C using printable string S."
- (aset standard-display-table c (vconcat s)))
-
-;;;###autoload
-(defun standard-display-g1 (c sc)
- "Display character C as character SC in the g1 character set.
-This function assumes that your terminal uses the SO/SI characters;
-it is meaningless for an X frame."
- (if window-system
- (error "Cannot use string glyphs in a windowing system"))
- (aset standard-display-table c
- (vector (create-glyph (concat "\016" (char-to-string sc) "\017")))))
-
-;;;###autoload
-(defun standard-display-graphic (c gc)
- "Display character C as character GC in graphics character set.
-This function assumes VT100-compatible escapes; it is meaningless for an
-X frame."
- (if window-system
- (error "Cannot use string glyphs in a windowing system"))
- (aset standard-display-table c
- (vector (create-glyph (concat "\e(0" (char-to-string gc) "\e(B")))))
-
-;;;###autoload
-(defun standard-display-underline (c uc)
- "Display character C as character UC plus underlining."
- (if window-system (require 'faces))
- (aset standard-display-table c
- (vector
- (if window-system
- (logior uc (lsh (face-id (internal-find-face 'underline)) 8))
- (create-glyph (concat "\e[4m" (char-to-string uc) "\e[m"))))))
-
-;; Allocate a glyph code to display by sending STRING to the terminal.
-;;;###autoload
-(defun create-glyph (string)
- (if (= (length glyph-table) 65536)
- (error "No free glyph codes remain"))
- ;; Don't use slots that correspond to ASCII characters.
- (if (= (length glyph-table) 32)
- (setq glyph-table (vconcat glyph-table (make-vector 224 nil))))
- (setq glyph-table (vconcat glyph-table (list string)))
- (1- (length glyph-table)))
-
-;;;###autoload
-(defun standard-display-european (arg)
- "Toggle display of European characters encoded with ISO 8859.
-When enabled, characters in the range of 160 to 255 display not
-as octal escapes, but as accented characters.
-With prefix argument, enable European character display iff arg is positive."
- (interactive "P")
- (if (or (<= (prefix-numeric-value arg) 0)
- (and (null arg)
- (char-table-p standard-display-table)
- ;; Test 161, because 160 displays as a space.
- (equal (aref standard-display-table 161) [161])))
- (standard-display-default 160 255)
- (standard-display-8bit 160 255)
- ;; Make non-line-break space display as a plain space.
- ;; Most X fonts do the wrong thing for code 160.
- (aset standard-display-table 160 [32])))
-
-(provide 'disp-table)
-
-;;; disp-table.el ends here
diff --git a/lisp/docref.el b/lisp/docref.el
deleted file mode 100644
index 363ce6c33d5..00000000000
--- a/lisp/docref.el
+++ /dev/null
@@ -1,282 +0,0 @@
-;;; docref.el --- Simple cross references for Elisp documentation strings
-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-
-;; Author: Vadim Geshel <vadik@unas.cs.kiev.ua>
-;; Created: 12 Jul 1994
-;; Keywords: docs, help, lisp
-;; original name was cross-ref.el.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package allows you to use a simple form of cross references in
-;; your Emacs Lisp documentation strings. Cross-references look like
-;; \\(type@[label@]data), where type defines a method for retrieving
-;; reference information, data is used by a method routine as an argument,
-;; and label "represents" the reference in text. If label is absent, data
-;; is used instead.
-;;
-;; Special reference labeled `back', when present, can be used to return
-;; to the previous contents of help buffer.
-;;
-;; Cross-referencing currently is intended for use in doc strings only
-;; and works only in temporary buffers (created by `with-output-to-temp-buffer').
-;; List of temp buffers in which cross-referencing is to be active is specified
-;; by variable DOCREF-BUFFERS-LIST, which contains only "*Help*" by default.
-;;
-;; Documentation strings for this package's functions and variables can serve
-;; as examples of usage.
-;;
-;;; Customization:
-;;
-;; See source. The main customization variable is `docref-methods-alist'.
-;; It consists of (type . function) pairs, where type is a string which
-;; corresponds to type in cross-references and function is called with
-;; one argument - reference `data' - when a reference is activated.
-;;
-;;; Installation:
-;;
-;; Place this file somewhere in your load-path, byte-compiled it, and add
-;; (require 'cross-ref)
-;; to your .emacs.
-
-;;; Code:
-
-;; User customizable variables
-
-(defvar docref-highlight-p t
- "*If non-nil, \\(f@docref-subst) highlights cross-references.
-Under window system it highlights them with face defined by
-\\(v@docref-highlight-face), on character terminal highlighted references
-look like cross-references in info mode.")
-
-(defvar docref-highlight-face 'highlight
- "*Face used to highlight cross-references (used by \\(f@docref-subst))")
-
-(defvar docref-methods-alist
- '(("f" . docref-describe-function) ; reference to a function documentation
- ("v" . docref-describe-variable) ; reference to a variable documentation
- ("F" . docref-read-file) ; reference to a file contents
- ("s" . docref-use-string) ; reference to a string
- ("V" . docref-use-variable-value) ; reference to variable value
- ("0" . beep)) ; just highlighted text
- "Alist which maps cross-reference ``types'' to retrieval functions.
-
-The car of each element is a string that serves as `type' in cross-references.
-\(See \\(f@docref-subst)). The cdr is a function of one argument,
-to be called to find this reference.")
-
-(defvar docref-back-label "\nback"
- "Label to use by \\(f@docref-subst) for the go-back reference.")
-
-(defvar docref-back-reference nil
- "If non-nil, this is a go-back reference to add to the current buffer.
-The value specifies how to go back. It should be suitable for use
-as the second argument to \\(f@docref-insert-label).
-\\(f@docref-subst) uses this to set up the go-back reference.")
-
-(defvar docref-last-active-buffer)
-
-;;;###autoload
-(defun docref-setup ()
- "Process docref cross-references in the current buffer.
-See also \\(f@docref-subst)."
- (interactive)
- (docref-subst (current-buffer))
- (docref-mode))
-
-(defvar docref-mode-map nil)
-(or docref-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map [mouse-2] 'docref-follow-mouse)
- (define-key map "\C-c\C-b" 'docref-go-back)
- (define-key map "\C-c\C-c" 'docref-follow)
- (setq docref-mode-map map)))
-
-(defun docref-mode ()
- "Major mode for help buffers that contain cross references.
-To follow a reference, move to it and type \\[docref-follow], or use
-\\[docref-follow-mouse]. The command \\[docref-go-back] can used to go
-back to where you came from."
- (interactive)
- (kill-all-local-variables)
- (setq major-mode 'docref-mode)
- (setq mode-name "Docref")
- (use-local-map docref-mode-map)
- (run-hooks 'docref-mode))
-
-(defun docref-subst (buf)
- "Parse documentation cross-references in buffer BUF.
-
-Find cross-reference information in a buffer and
-highlight them with face defined by \\(v@docref-highlight-face).
-
-Cross-reference has the following format: \\ (TYPE[@LABEL]@DATA), where
-TYPE defines method used to retrieve xref data (like reading from file or
-calling \\(f@describe-function)), DATA is an argument to this method
-\(like file name or function name), and LABEL is displayed in text using
-\\(v@docref-highlight-face).
-
-The special reference `back' can be used to return back.
-The variable \\(v@docref-back-label) specifies the label to use for that.
-
-See \\(v@docref-methods-alist) for currently defined methods."
- (interactive "b")
- (save-excursion
- (set-buffer buf)
- (goto-char (point-min))
- ;; The docref-seen property indicates that we have processed this
- ;; buffer's contents already, so don't do it again.
- (if (not (get-text-property (point-min) 'docref-seen))
- (let ((old-modified (buffer-modified-p)))
- (while (re-search-forward "[\\](\\([^\)\@]+\\)\\(@[^\)\@]+\\)?@\\([^\)]*\\))"
- nil t)
- (let* ((start (match-beginning 0))
- (type (buffer-substring (match-beginning 1) (match-end 1)))
- (data (buffer-substring (match-beginning 3) (match-end 3)))
- (label
- (if (match-beginning 2)
- (buffer-substring (+ (match-beginning 2) 1) (match-end 2))
- data)))
- (replace-match "" t)
- (docref-insert-label label (cons type data))))
-
- ;; Make a back-reference in this buffer, if desired.
- ;; (This is true if called from docref-follow.)
- (if docref-back-reference
- (progn
- (goto-char (point-max))
- (put-text-property (point-min) (1+ (point-min))
- 'docref-back-position (point))
- (docref-insert-label docref-back-label docref-back-reference)))
- (put-text-property (point-min) (1+ (point-min)) 'docref-seen t)
- (set-buffer-modified-p old-modified)))))
-
-(defun docref-insert-label (string ref)
- (let ((label (concat string))
- (pos (point)))
- ;; decorate the label
- (let ((leading-space-end (save-match-data
- (if (string-match "^\\([ \t\n]+\\)" label)
- (match-end 1)
- 0)))
- (trailing-space-start (save-match-data
- (if (string-match "\\([ \t\n]+\\)$" label)
- (match-beginning 1)
- (length label)))))
- (if docref-highlight-p
- (if (not window-system)
- (setq label
- (concat (substring label 0 leading-space-end)
- "(*note "
- (substring label leading-space-end trailing-space-start)
- ")"
- (substring label trailing-space-start)))
- ;; window-system
- (put-text-property leading-space-end
- trailing-space-start
- 'face docref-highlight-face label)))
- (put-text-property 0 (length label) 'docref ref label)
- (insert label))))
-
-(defun docref-follow-mouse (click)
- "Follow the cross-reference that you click on."
- (interactive "e")
- (save-excursion
- (let* ((start (event-start click))
- (window (car start))
- (pos (car (cdr start)))
- (docref-last-active-buffer (current-buffer)))
- (set-buffer (window-buffer window))
- (docref-follow pos))))
-
-(defun docref-go-back ()
- "Go back to the previous contents of help buffer."
- (interactive)
- (let ((pos (get-text-property (point-min) 'docref-back-position)))
- (if pos
- (docref-follow pos)
- (error "No go-back reference"))))
-
-(defun docref-follow (&optional pos)
- "Follow cross-reference at point.
-For the cross-reference format, see \\(f@docref-subst).
-The special reference named `back' can be used to return back"
- (interactive)
- (or pos (setq pos (point)))
- (let ((docref-data (get-text-property pos 'docref)))
- (if docref-data
- ;; There is a reference at point. Follow it.
- (let* ((type (car docref-data))
- (name (cdr docref-data))
- (method (assoc type docref-methods-alist))
- (cur-contents (buffer-string))
- (opoint (point))
- (docref-back-reference (cons "s" cur-contents))
- success)
- (if (null method)
- (error "Unknown cross-reference type: %s" type))
- (unwind-protect
- (save-excursion
- (funcall (cdr method) name)
- (setq success t))
- (or success
- (progn
- ;; (cdr method) got an error.
- ;; Put back the text that we had.
- (erase-buffer)
- (insert cur-contents)
- (goto-char opoint)))
- (set-buffer-modified-p nil))))))
-
-;; Builtin methods for accessing a reference.
-
-(defun docref-describe-function (data)
- (save-excursion
- (if (boundp 'docref-last-active-buffer)
- (set-buffer docref-last-active-buffer))
- (describe-function (intern data))))
-
-(defun docref-describe-variable (data)
- (save-excursion
- (if (boundp 'docref-last-active-buffer)
- (set-buffer docref-last-active-buffer))
- (describe-variable (intern data))))
-
-(defun docref-read-file (data)
- (with-output-to-temp-buffer (buffer-name)
- (erase-buffer)
- (insert-file-contents (expand-file-name data))))
-
-(defun docref-use-string (data)
- (with-output-to-temp-buffer (buffer-name)
- (erase-buffer)
- (insert data)))
-
-(defun docref-use-variable-value (data)
- (let ((sym (intern data)))
- (with-output-to-temp-buffer (buffer-name)
- (erase-buffer)
- (princ (symbol-value sym)))))
-
-(provide 'docref)
-
-;;; docref.el ends here
-
diff --git a/lisp/dos-fns.el b/lisp/dos-fns.el
deleted file mode 100644
index 00d4a36d0e1..00000000000
--- a/lisp/dos-fns.el
+++ /dev/null
@@ -1,208 +0,0 @@
-;;; dos-fns.el --- MS-Dos specific functions.
-
-;; Copyright (C) 1991, 1993, 1995, 1996 Free Software Foundation, Inc.
-
-;; Maintainer: Morten Welinder (terra@diku.dk)
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Part of this code is taken from (or derived from) demacs.
-
-;;; Code:
-
-;; This overrides a trivial definition in files.el.
-(defun convert-standard-filename (filename)
- "Convert a standard file's name to something suitable for the current OS.
-This function's standard definition is trivial; it just returns the argument.
-However, on some systems, the function is redefined
-with a definition that really does change some file names."
- (if (or (msdos-long-file-names)
- (not (stringp filename))
- (member (file-name-nondirectory filename) '("" "." "..")))
- filename
- (let* ((dir (file-name-directory filename))
- (string (copy-sequence (file-name-nondirectory filename)))
- (lastchar (aref string (1- (length string))))
- i firstdot)
- ;; Change a leading period to a leading underscore.
- (if (= (aref string 0) ?.)
- (aset string 0 ?_))
- ;; Get rid of invalid characters.
- (while (setq i (string-match
- "[^-a-zA-Z0-9_.%~^$!#&{}@`'()\200-\376]"
- string))
- (aset string i ?_))
- ;; If we don't have a period,
- ;; and we have a dash or underscore that isn't the first char,
- ;; change that to a period.
- (if (and (not (string-match "\\." string))
- (setq i (string-match "[-_]" string 1)))
- (aset string i ?\.))
- ;; If we don't have a period in the first 8 chars, insert one.
- (if (> (or (string-match "\\." string)
- (length string))
- 8)
- (setq string
- (concat (substring string 0 8)
- "."
- (substring string 8))))
- (setq firstdot (or (string-match "\\." string) (1- (length string))))
- ;; Truncate to 3 chars after the first period.
- (if (> (length string) (+ firstdot 4))
- (setq string (substring string 0 (+ firstdot 4))))
- ;; Change all periods except the first one into underscores.
- (while (string-match "\\." string (1+ firstdot))
- (setq i (string-match "\\." string (1+ firstdot)))
- (aset string i ?_))
- ;; If the last character of the original filename was `~',
- ;; make sure the munged name ends with it also.
- (if (equal lastchar ?~)
- (aset string (1- (length string)) lastchar))
- (concat dir string))))
-
-(defvar msdos-shells '("command.com" "4dos.com" "ndos.com")
- "*List of shells that use `/c' instead of `-c' and a backslashed command.")
-
-(defvar register-name-alist
- '((ax . 0) (bx . 1) (cx . 2) (dx . 3) (si . 4) (di . 5)
- (cflag . 6) (flags . 7)
- (al . (0 . 0)) (bl . (1 . 0)) (cl . (2 . 0)) (dl . (3 . 0))
- (ah . (0 . 1)) (bh . (1 . 1)) (ch . (2 . 1)) (dh . (3 . 1))))
-
-(defun make-register ()
- (make-vector 8 0))
-
-(defun register-value (regs name)
- (let ((where (cdr (assoc name register-name-alist))))
- (cond ((consp where)
- (let ((tem (aref regs (car where))))
- (if (zerop (cdr where))
- (% tem 256)
- (/ tem 256))))
- ((numberp where)
- (aref regs where))
- (t nil))))
-
-(defun set-register-value (regs name value)
- (and (numberp value)
- (>= value 0)
- (let ((where (cdr (assoc name register-name-alist))))
- (cond ((consp where)
- (let ((tem (aref regs (car where)))
- (value (logand value 255)))
- (aset regs
- (car where)
- (if (zerop (cdr where))
- (logior (logand tem 65280) value)
- (logior (logand tem 255) (lsh value 8))))))
- ((numberp where)
- (aset regs where (logand value 65535))))))
- regs)
-
-(defsubst intdos (regs)
- (int86 33 regs))
-
-;; Support for printing under MS-DOS, see lpr.el and ps-print.el.
-(defvar dos-printer "PRN"
- "*The name of a local MS-DOS device to which data is sent for printing.
-\(Note that PostScript files are sent to `dos-ps-printer', which see.\)
-
-Typical non-default settings would be \"LPT1\" to \"LPT3\" for
-parallel printers, or \"COM1\" to \"COM4\" or \"AUX\" for serial
-printers. You can also set it to a name of a file, in which
-case the output gets appended to that file.
-If you want to discard the printed output, set this to \"NUL\".")
-
-(defun dos-print-region-function (start end
- &optional lpr-prog
- delete-text buf display rest)
- "MS-DOS-specific function to print the region on a printer.
-Writes the region to the device or file which is a value of
-`dos-printer' \(which see\). Ignores any arguments beyond
-START and END."
-
- (write-region start end dos-printer t 0)
- ;; Make each print-out start on a new page, but don't waste
- ;; paper if there was a form-feed at the end of this file.
- (if (not (char-equal (char-after (1- end)) ?\C-l))
- (write-region "\f" nil dos-printer t 0)))
-
-;; Set this to nil if you have a port of the `lpr' program and
-;; you want to use it for printing. If the default setting is
-;; in effect, `lpr-command' and its switches are ignored when
-;; printing with `lpr-xxx' and `print-xxx'.
-(setq print-region-function 'dos-print-region-function)
-
-;; Set this to nil if you have a port of the `pr' program
-;; (e.g., from GNU Textutils), or if you have an `lpr'
-;; program (see above) that can print page headers.
-;; If `lpr-headers-switches' is non-nil (the default) and
-;; `print-region-function' is set to `dos-print-region-function',
-;; then requests to print page headers will be silently
-;; ignored, and `print-buffer' and `print-region' produce
-;; the same output as `lpr-buffer' and `lpr-region', accordingly.
-(setq lpr-headers-switches "(page headers are not supported)")
-
-(defvar dos-ps-printer "PRN"
- "*Method for printing PostScript files under MS-DOS.
-
-If the value is a string, then it is taken as the name of the
-device to which PostScript files are written. By default it
-is the default printer device; typical non-default settings
-would be \"LPT1\" to \"LPT3\" for parallel printers, or \"COM1\"
-to \"COM4\" or \"AUX\" for serial printers. You can also set it
-to a name of a file, in which case the output gets appended
-to that file. \(Note that `ps-print' package already has
-facilities for printing to a file, so you might as well use
-them instead of changing the setting of this variable.\) If
-you want to silently discard the printed output, set this to \"NUL\".
-
-If the value is anything but a string, PostScript files will be
-piped to the program given by `ps-lpr-command', with switches
-given by `ps-lpr-switches', which see.")
-
-(setq ps-lpr-command "gs")
-
-(setq ps-lpr-switches '("-q" "-dNOPAUSE" "-sDEVICE=epson" "-r240x60"
- "-sOutputFile=LPT1" "-"))
-
-;; Backward compatibility for obsolescent functions which
-;; set screen size.
-
-(defun mode25 ()
- "Changes the number of screen rows to 25."
- (interactive)
- (set-frame-size (selected-frame) 80 25))
-
-(defun mode4350 ()
- "Changes the number of rows to 43 or 50.
-Emacs always tries to set the screen height to 50 rows first.
-If this fails, it will try to set it to 43 rows, on the assumption
-that your video hardware might not support 50-line mode."
- (interactive)
- (set-frame-size (selected-frame) 80 50)
- (if (eq (frame-height (selected-frame)) 50)
- nil ; the original built-in function returned nil
- (set-frame-size (selected-frame) 80 43)))
-
-(provide 'dos-fns)
-
-; dos-fns.el ends here
diff --git a/lisp/dos-w32.el b/lisp/dos-w32.el
deleted file mode 100644
index 83de34749af..00000000000
--- a/lisp/dos-w32.el
+++ /dev/null
@@ -1,169 +0,0 @@
-;;; dos-w32.el --- Functions shared among MS-DOS and W32 (NT/95) platforms
-
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Maintainer: Geoff Voelker (voelker@cs.washington.edu)
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Parts of this code are duplicated functions taken from dos-fns.el
-;; and winnt.el.
-
-;;; Code:
-
-;;; Add %t: into the mode line format just after the open-paren.
-(let ((tail (member " %[(" mode-line-format)))
- (setcdr tail (cons (purecopy "%t:")
- (cdr tail))))
-
-;; Use ";" instead of ":" as a path separator (from files.el).
-(setq path-separator ";")
-
-;; Set the null device (for compile.el).
-(setq grep-null-device "NUL")
-
-;; Set the grep regexp to match entries with drive letters.
-(setq grep-regexp-alist
- '(("^\\(\\([a-zA-Z]:\\)?[^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 3)))
-
-;; For distinguishing file types based upon suffixes.
-(defvar file-name-buffer-file-type-alist
- '(
- ("[:/].*config.sys$" . nil) ; config.sys text
- ("\\.elc$" . t) ; emacs stuff
- ("\\.\\(obj\\|exe\\|com\\|lib\\|sys\\|chk\\|out\\|bin\\|ico\\|pif\\)$" . t)
- ; MS-Dos stuff
- ("\\.\\(arc\\|zip\\|pak\\|lzh\\|zoo\\)$" . t)
- ; Packers
- ("\\.\\(a\\|o\\|tar\\|z\\|gz\\|taz\\)$" . t)
- ; Unix stuff
- ("\\.tp[ulpw]$" . t)
- ; Borland Pascal stuff
- ("[:/]tags$" . t)
- ; Emacs TAGS file
- )
- "*Alist for distinguishing text files from binary files.
-Each element has the form (REGEXP . TYPE), where REGEXP is matched
-against the file name, and TYPE is nil for text, t for binary.")
-
-(defun find-buffer-file-type (filename)
- ;; First check if file is on an untranslated filesystem, then on the alist.
- (if (untranslated-file-p filename)
- t ; for binary
- (let ((alist file-name-buffer-file-type-alist)
- (found nil)
- (code nil))
- (let ((case-fold-search t))
- (setq filename (file-name-sans-versions filename))
- (while (and (not found) alist)
- (if (string-match (car (car alist)) filename)
- (setq code (cdr (car alist))
- found t))
- (setq alist (cdr alist))))
- (if found
- (cond ((memq code '(nil t)) code)
- ((and (symbolp code) (fboundp code))
- (funcall code filename)))
- default-buffer-file-type))))
-
-(defun find-file-binary (filename)
- "Visit file FILENAME and treat it as binary."
- (interactive "FFind file binary: ")
- (let ((file-name-buffer-file-type-alist '(("" . t))))
- (find-file filename)))
-
-(defun find-file-text (filename)
- "Visit file FILENAME and treat it as a text file."
- (interactive "FFind file text: ")
- (let ((file-name-buffer-file-type-alist '(("" . nil))))
- (find-file filename)))
-
-(defun find-file-not-found-set-buffer-file-type ()
- (save-excursion
- (set-buffer (current-buffer))
- (setq buffer-file-type (find-buffer-file-type (buffer-file-name))))
- nil)
-
-;;; To set the default file type on new files.
-(add-hook 'find-file-not-found-hooks 'find-file-not-found-set-buffer-file-type)
-
-
-;;; To accomodate filesystems that do not require CR/LF translation.
-(defvar untranslated-filesystem-list nil
- "List of filesystems that require no CR/LF translation when reading
-and writing files. Each filesystem in the list is a string naming
-the directory prefix corresponding to the filesystem.")
-
-(defun untranslated-canonical-name (filename)
- "Return FILENAME in a canonicalized form for use with the functions
-dealing with untranslated filesystems."
- (if (memq system-type '(ms-dos windows-nt))
- ;; The canonical form for DOS/NT/Win95 is with A-Z downcased and all
- ;; directory separators changed to directory-sep-char.
- (let ((name nil))
- (setq name (mapconcat
- '(lambda (char)
- (if (and (<= ?A char) (<= char ?Z))
- (char-to-string (+ (- char ?A) ?a))
- (char-to-string char)))
- filename nil))
- ;; Use expand-file-name to canonicalize directory separators, except
- ;; with bare drive letters (which would have the cwd appended).
- (if (string-match "^.:$" name)
- name
- (expand-file-name name)))
- filename))
-
-(defun untranslated-file-p (filename)
- "Return t if FILENAME is on a filesystem that does not require
-CR/LF translation, and nil otherwise."
- (let ((fs (untranslated-canonical-name filename))
- (ufs-list untranslated-filesystem-list)
- (found nil))
- (while (and (not found) ufs-list)
- (if (string-match (concat "^" (car ufs-list)) fs)
- (setq found t)
- (setq ufs-list (cdr ufs-list))))
- found))
-
-(defun add-untranslated-filesystem (filesystem)
- "Add FILESYSTEM to the list of filesystems that do not require
-CR/LF translation. FILESYSTEM is a string containing the directory
-prefix corresponding to the filesystem. For example, for a Unix
-filesystem mounted on drive Z:, FILESYSTEM could be \"Z:\"."
- (let ((fs (untranslated-canonical-name filesystem)))
- (if (member fs untranslated-filesystem-list)
- untranslated-filesystem-list
- (setq untranslated-filesystem-list
- (cons fs untranslated-filesystem-list)))))
-
-(defun remove-untranslated-filesystem (filesystem)
- "Remove FILESYSTEM from the list of filesystems that do not require
-CR/LF translation. FILESYSTEM is a string containing the directory
-prefix corresponding to the filesystem. For example, for a Unix
-filesystem mounted on drive Z:, FILESYSTEM could be \"Z:\"."
- (setq untranslated-filesystem-list
- (delete (untranslated-canonical-name filesystem)
- untranslated-filesystem-list)))
-
-(provide 'dos-w32)
-
-;;; dos-w32.el ends here
diff --git a/lisp/dos-win32.el b/lisp/dos-win32.el
deleted file mode 100644
index 89704c029c5..00000000000
--- a/lisp/dos-win32.el
+++ /dev/null
@@ -1,170 +0,0 @@
-;;; dos-win32.el --- Functions shared among MS-DOS and Win32 (NT/95) platforms
-
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Maintainer: Geoff Voelker (voelker@cs.washington.edu)
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Parts of this code are duplicated functions taken from dos-fns.el
-;; and winnt.el.
-
-;;; Code:
-
-;;; Add %t: into the mode line format just after the open-paren.
-(let ((tail (member " %[(" mode-line-format)))
- (setcdr tail (cons (purecopy "%t:")
- (cdr tail))))
-
-;; Use ";" instead of ":" as a path separator (from files.el).
-(setq path-separator ";")
-
-;; Set the null device (for compile.el).
-(setq grep-null-device "NUL")
-
-;; Set the grep regexp to match entries with drive letters.
-(setq grep-regexp-alist
- '(("^\\(\\([a-zA-Z]:\\)?[^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 3)))
-
-;; For distinguishing file types based upon suffixes.
-(defvar file-name-buffer-file-type-alist
- '(
- ("[:/].*config.sys$" . nil) ; config.sys text
- ("\\.elc$" . t) ; emacs stuff
- ("\\.\\(obj\\|exe\\|com\\|lib\\|sys\\|chk\\|out\\|bin\\|ico\\|pif\\)$" . t)
- ; MS-Dos stuff
- ("\\.\\(arc\\|zip\\|pak\\|lzh\\|zoo\\)$" . t)
- ; Packers
- ("\\.\\(a\\|o\\|tar\\|z\\|gz\\|taz\\)$" . t)
- ; Unix stuff
- ("\\.tp[ulpw]$" . t)
- ; Borland Pascal stuff
- ("[:/]tags$" . t)
- ; Emacs TAGS file
- )
- "*Alist for distinguishing text files from binary files.
-Each element has the form (REGEXP . TYPE), where REGEXP is matched
-against the file name, and TYPE is nil for text, t for binary.")
-
-(defun find-buffer-file-type (filename)
- ;; First check if file is on an untranslated filesystem, then on the alist.
- (if (untranslated-file-p filename)
- t ; for binary
- (let ((alist file-name-buffer-file-type-alist)
- (found nil)
- (code nil))
- (let ((case-fold-search t))
- (setq filename (file-name-sans-versions filename))
- (while (and (not found) alist)
- (if (string-match (car (car alist)) filename)
- (setq code (cdr (car alist))
- found t))
- (setq alist (cdr alist))))
- (if found
- (cond ((memq code '(nil t)) code)
- ((and (symbolp code) (fboundp code))
- (funcall code filename)))
- default-buffer-file-type))))
-
-(defun find-file-binary (filename)
- "Visit file FILENAME and treat it as binary."
- (interactive "FFind file binary: ")
- (let ((file-name-buffer-file-type-alist '(("" . t))))
- (find-file filename)))
-
-(defun find-file-text (filename)
- "Visit file FILENAME and treat it as a text file."
- (interactive "FFind file text: ")
- (let ((file-name-buffer-file-type-alist '(("" . nil))))
- (find-file filename)))
-
-(defun find-file-not-found-set-buffer-file-type ()
- (save-excursion
- (set-buffer (current-buffer))
- (setq buffer-file-type (find-buffer-file-type (buffer-file-name))))
- nil)
-
-;;; To set the default file type on new files.
-(add-hook 'find-file-not-found-hooks 'find-file-not-found-set-buffer-file-type)
-
-
-;;; To accomodate filesystems that do not require CR/LF translation.
-(defvar untranslated-filesystem-list nil
- "List of filesystems that require no CR/LF translation during file I/O.
-Each element in the list is a string naming the directory prefix
-corresponding to the filesystem.")
-
-(defun untranslated-canonical-name (filename)
- "Return FILENAME in a canonicalized form.
-This is for use with the functions dealing with untranslated filesystems."
- (if (memq system-type '(ms-dos windows-nt))
- ;; The canonical form for DOS/NT/Win95 is with A-Z downcased and all
- ;; directory separators changed to directory-sep-char.
- (let ((name nil))
- (setq name (mapconcat
- '(lambda (char)
- (if (and (<= ?A char) (<= char ?Z))
- (char-to-string (+ (- char ?A) ?a))
- (char-to-string char)))
- filename nil))
- ;; Use expand-file-name to canonicalize directory separators, except
- ;; with bare drive letters (which would have the cwd appended).
- (if (string-match "^.:$" name)
- name
- (expand-file-name name)))
- filename))
-
-(defun untranslated-file-p (filename)
- "Test whether CR/LF translation should be disabled for FILENAME.
-Return t if FILENAME is on a filesystem that does not require
-CR/LF translation, and nil otherwise."
- (let ((fs (untranslated-canonical-name filename))
- (ufs-list untranslated-filesystem-list)
- (found nil))
- (while (and (not found) ufs-list)
- (if (string-match (concat "^" (regexp-quote (car ufs-list))) fs)
- (setq found t)
- (setq ufs-list (cdr ufs-list))))
- found))
-
-(defun add-untranslated-filesystem (filesystem)
- "Record that FILESYSTEM does not require CR/LF translation.
-FILESYSTEM is a string containing the directory prefix corresponding to
-the filesystem. For example, for a Unix filesystem mounted on drive Z:,
-FILESYSTEM could be \"Z:\"."
- (let ((fs (untranslated-canonical-name filesystem)))
- (if (member fs untranslated-filesystem-list)
- untranslated-filesystem-list
- (setq untranslated-filesystem-list
- (cons fs untranslated-filesystem-list)))))
-
-(defun remove-untranslated-filesystem (filesystem)
- "Record that FILESYSTEM requires CR/LF translation.
-FILESYSTEM is a string containing the directory prefix corresponding to
-the filesystem. For example, for a Unix filesystem mounted on drive Z:,
-FILESYSTEM could be \"Z:\"."
- (setq untranslated-filesystem-list
- (delete (untranslated-canonical-name filesystem)
- untranslated-filesystem-list)))
-
-(provide 'dos-win32)
-
-;;; dos-win32.el ends here
diff --git a/lisp/double.el b/lisp/double.el
deleted file mode 100644
index 0a422bedbf1..00000000000
--- a/lisp/double.el
+++ /dev/null
@@ -1,200 +0,0 @@
-;;; double.el --- Support for keyboard remapping with double clicking
-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-
-;; Author: Per Abrahamsen <abraham@iesd.auc.dk>
-;; Keywords: i18n
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This mode is intended for use with languages that adds a small
-;; number of extra letters not available on the keyboard.
-;;
-;; Examples includes Scandinavian and German with an US keyboard.
-;;
-;; The idea is that certain keys are overloaded. When you press it
-;; once it will insert one string, and when you press it twice the
-;; string will be replaced by another. This can be used for mapping
-;; keys on a US keyboard to generate characters according to the local
-;; keyboard convention when pressed once, and according to US keyboard
-;; convention when pressed twice.
-;;
-;; To use this mode, you must define the variable `double-map' and
-;; then enable double mode with `M-x double-mode'. Read the
-;; documentation for both of them.
-;;
-;; The default mapping is for getting Danish/Norwegian keyboard layout
-;; using ISO Latin 1 on a US keyboard.
-;;
-;; Important node: While I would like to hear comments, bug reports,
-;; suggestions, please do @strong{not} expect me to put other mappings
-;; than the default into this file. There are billions and billions
-;; of such mappings, and just supporting the most common would
-;; increase the size of this nice small file manyfold.
-
-;;; ChangeLog:
-
-;; * 1994-06-21 Per Abrahamsen
-;; Added `double-prefix-only'.
-;; * 1994-02-28 Per Abrahamsen
-;; Use 127 instead of 'delete to delete a character.
-;; * 1994-02-03 Per Abrahamsen
-;; Created.
-
-;;; Code:
-
-(defvar double-map
- '((?\; "\346" ";")
- (?\' "\370" "'")
- (?\[ "\345" "[")
- (?\: "\306" ":")
- (?\" "\330" "\"")
- (?\{ "\305" "{"))
- "Alist of key translations activated by double mode.
-
-Each entry is a list with three elements:
-1. The key activating the translation.
-2. The string to be inserted when the key is pressed once.
-3. The string to be inserted when the key is pressed twice.")
-
-(defvar double-prefix-only t
- "*Non-nil means that Double mode mapping only works for prefix keys.
-That is, for any key `X' in `double-map', `X' alone will be mapped
-but not `C-u X' or `ESC X' since the X is not the prefix key.")
-
-;;; Read Event
-
-(defvar double-last-event nil)
-;; The last key that generated a double key event.
-
-(defun double-read-event (prompt)
- ;; Read an event
- (if isearch-mode (isearch-update))
- (if prompt
- (prog2 (message "%s%c" prompt double-last-event)
- (read-event)
- (message ""))
- (read-event)))
-
-(global-set-key [ignore] '(lambda () (interactive)))
-
-(or (boundp 'isearch-mode-map)
- (load-library "isearch"))
-
-(define-key isearch-mode-map [ignore]
- (function (lambda () (interactive) (isearch-update))))
-
-(defun double-translate-key (prompt)
- ;; Translate input events using double map.
- (let ((key last-input-char))
- (cond (unread-command-events
- ;; Artificial event, ignore it.
- (vector key))
- ((and double-prefix-only
- (> (length (this-command-keys)) 1))
- ;; This is not a prefix key, ignore it.
- (vector key))
- ((eq key 'magic-start)
- ;; End of generated event. See if he will repeat it...
- (let ((new (double-read-event prompt))
- (entry (assoc double-last-event double-map)))
- (if (eq new double-last-event)
- (progn
- (setq unread-command-events
- (append (make-list (1- (length (nth 1 entry)))
- 127)
- (nth 2 entry)
- '(magic-end)))
- (vector 127))
- (setq unread-command-events (list new))
- [ignore])))
- ((eq key 'magic-end)
- ;; End of double event. Ignore.
- [ignore])
- (t
- ;; New key.
- (let ((exp (nth 1 (assoc key double-map))))
- (setq double-last-event key)
- (setq unread-command-events
- (append (substring exp 1) '(magic-start)))
- (vector (aref exp 0)))))))
-
-;;; Key Translation Map
-
-(defvar default-key-translation-map
- (or key-translation-map (make-sparse-keymap))
- "Key translation you want to have effect, regardless of Double mode.
-This defaults to the value of `key-translation-map' when double was
-first loaded.")
-
-(make-variable-buffer-local 'key-translation-map)
-
-(defun double-setup ()
- ;; Setup key-translation-map as indicated by `double-map'.
- (setq key-translation-map (copy-keymap default-key-translation-map))
- (mapcar (function (lambda (entry)
- (define-key key-translation-map (vector (nth 0 entry))
- 'double-translate-key)))
- (append double-map '((magic-start) (magic-end)))))
-
-;;; Mode
-
-(defvar double-mode nil)
-;; Indicator for the double mode.
- (make-variable-buffer-local 'double-mode)
-
-(or (assq 'double-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(double-mode " Double") minor-mode-alist)))
-
-;; This feature seemed useless and it confused describe-mode,
-;; so I deleted it.
-;;;(defvar double-mode-name "Double")
-;;;;; Name of current double mode.
-;;; (make-variable-buffer-local 'double-mode-name)
-
-;;;###autoload
-(defun double-mode (arg)
- "Toggle Double mode.
-With prefix arg, turn Double mode on iff arg is positive.
-
-When Double mode is on, some keys will insert different strings
-when pressed twice. See variable `double-map' for details."
- (interactive "P")
- (if (or (and (null arg) double-mode)
- (<= (prefix-numeric-value arg) 0))
- ;; Turn it off
- (if double-mode
- (progn
- (let ((double-map))
- (double-setup))
- (setq double-mode nil)
- (force-mode-line-update)))
- ;;Turn it on
- (if double-mode
- ()
- (double-setup)
- (setq double-mode t)
- (force-mode-line-update))))
-
-(provide 'double)
-
-;;; double.el ends here
-
diff --git a/lisp/ebuff-menu.el b/lisp/ebuff-menu.el
deleted file mode 100644
index 907cc2d92e0..00000000000
--- a/lisp/ebuff-menu.el
+++ /dev/null
@@ -1,265 +0,0 @@
-;;; ebuff-menu.el --- electric-buffer-list mode
-
-;; Copyright (C) 1985, 1986, 1994 Free Software Foundation, Inc.
-
-;; Author: Richard Mlynarik <mly@ai.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Who says one can't have typeout windows in GNU Emacs? The entry
-;; point, `electric-buffer-list' works like ^r select buffer from the
-;; ITS Emacs lunar or tmacs libraries.
-
-;;; Code:
-
-(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)
-
-;;;###autoload
-(defun electric-buffer-list (arg)
- "Pops up a buffer describing the set of Emacs buffers.
-Vaguely like ITS lunar select buffer; combining typeoutoid buffer
-listing with menuoid buffer selection.
-
-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 a 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 Return to bury the buffer list >>>")
- (if (eq (setq unread-command-events (list (read-event)))
- ?\ )
- (progn (setq unread-command-events nil)
- (throw 'electric-buffer-menu-select nil)))
- (let ((start-point (point))
- (first (progn (goto-char (point-min))
- (forward-line 2)
- (point)))
- (last (progn (goto-char (point-max))
- (forward-line -1)
- (point)))
- (goal-column 0))
- ;; Use start-point if it is meaningful.
- (goto-char (if (or (< start-point first)
- (> start-point last))
- first
- start-point))
- (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>
-\\[keyboard-quit] or \\[Electric-buffer-menu-quit] -- exit buffer menu, returning to previous window and buffer
- configuration. If the very first character typed is a space, it
- also has this effect.
-\\[Electric-buffer-menu-select] -- 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\".
-\\[Buffer-menu-mark] -- mark buffer to be displayed.
-\\[Buffer-menu-not-modified] -- clear modified-flag on that buffer.
-\\[Buffer-menu-save] -- mark that buffer to be saved.
-\\[Buffer-menu-delete] or \\[Buffer-menu-delete-backwards] -- mark that buffer to be deleted.
-\\[Buffer-menu-unmark] -- remove all kinds of marks from current line.
-\\[Electric-buffer-menu-mode-view-buffer] -- view buffer, returning when done.
-\\[Buffer-menu-backup-unmark] -- back up a line and remove marks.
-
-\\{electric-buffer-menu-mode-map}
-
-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")
- (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)) (submap (make-keymap)))
- (fillarray (car (cdr map)) 'Electric-buffer-menu-undefined)
- (define-key map "\e" submap)
- (fillarray (car (cdr submap)) 'Electric-buffer-menu-undefined)
- (define-key map "\C-z" 'suspend-emacs)
- (define-key map "v" 'Electric-buffer-menu-mode-view-buffer)
- (define-key map (char-to-string help-char) '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-m" '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 ">" 'scroll-right)
- (define-key map "<" 'scroll-left)
- (define-key map "\e\C-v" 'scroll-other-window)
- (define-key map "\e>" 'end-of-buffer)
- (define-key map "\e<" 'beginning-of-buffer)
- (define-key map "\e\e" nil)
- (define-key map "\e\e\e" 'Electric-buffer-menu-quit)
- (define-key map [escape escape escape] 'Electric-buffer-menu-quit)
- (define-key map [mouse-2] 'Electric-buffer-menu-mouse-select)
- (setq electric-buffer-menu-mode-map map)))
-
-(defun Electric-buffer-menu-exit ()
- (interactive)
- (setq unread-command-events (listify-key-sequence (this-command-keys)))
- ;; 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-mouse-select (event)
- (interactive "e")
- (select-window (posn-window (event-end event)))
- (set-buffer (window-buffer (selected-window)))
- (goto-char (posn-point (event-end event)))
- (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 "%s"
- (if (and (eq (key-binding "\C-c\C-c") 'Electric-buffer-menu-quit)
- (eq (key-binding " ") 'Electric-buffer-menu-select)
- (eq (key-binding (char-to-string help-char)) 'Helper-help)
- (eq (key-binding "?") 'Helper-describe-bindings))
- (substitute-command-keys "Type C-c C-c to exit, Space to select, \\[Helper-help] 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))))
-
-;;; ebuff-menu.el ends here
diff --git a/lisp/echistory.el b/lisp/echistory.el
deleted file mode 100644
index 66e0b08c52b..00000000000
--- a/lisp/echistory.el
+++ /dev/null
@@ -1,150 +0,0 @@
-;;; echistory.el --- Electric Command History Mode
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Author: K. Shane Hartman
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(require 'electric) ; command loop
-(require 'chistory) ; history lister
-
-;;;###autoload
-(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."
- (interactive "P")
- (let (todo)
- (save-excursion
- (set-buffer "*Command History*")
- (beginning-of-line)
- (setq todo (read (current-buffer)))
- (if (boundp 'electric-history-in-progress)
- (if todo (throw 'electric-history-quit (list noconfirm todo)))))))
-
-(defvar electric-history-map ())
-(if electric-history-map
- ()
- (setq electric-history-map (make-sparse-keymap))
- (define-key electric-history-map [t] 'Electric-history-undefined)
- (define-key electric-history-map "\e" (make-sparse-keymap))
- (define-key electric-history-map [?\e t] 'Electric-history-undefined)
- (define-key electric-history-map "\C-u" 'universal-argument)
- (define-key electric-history-map " " 'Electric-command-history-redo-expression)
- (define-key electric-history-map "!" 'Electric-command-history-redo-expression)
- (define-key electric-history-map "\e\C-x" 'eval-sexp)
- (define-key electric-history-map "\e\C-d" 'down-list)
- (define-key electric-history-map "\e\C-u" 'backward-up-list)
- (define-key electric-history-map "\e\C-b" 'backward-sexp)
- (define-key electric-history-map "\e\C-f" 'forward-sexp)
- (define-key electric-history-map "\e\C-a" 'beginning-of-defun)
- (define-key electric-history-map "\e\C-e" 'end-of-defun)
- (define-key electric-history-map "\e\C-n" 'forward-list)
- (define-key electric-history-map "\e\C-p" 'backward-list)
- (define-key electric-history-map "q" 'Electric-history-quit)
- (define-key electric-history-map "\C-c" nil)
- (define-key electric-history-map "\C-c\C-c" 'Electric-history-quit)
- (define-key electric-history-map "\C-]" 'Electric-history-quit)
- (define-key electric-history-map "\C-z" 'suspend-emacs)
- (define-key electric-history-map (char-to-string help-char) 'Helper-help)
- (define-key electric-history-map "?" 'Helper-describe-bindings)
- (define-key electric-history-map "\e>" 'end-of-buffer)
- (define-key electric-history-map "\e<" 'beginning-of-buffer)
- (define-key electric-history-map "\n" 'next-line)
- (define-key electric-history-map "\r" 'next-line)
- (define-key electric-history-map "\177" 'previous-line)
- (define-key electric-history-map "\C-n" 'next-line)
- (define-key electric-history-map "\C-p" 'previous-line)
- (define-key electric-history-map "\ev" 'scroll-down)
- (define-key electric-history-map "\C-v" 'scroll-up)
- (define-key electric-history-map [home] 'beginning-of-buffer)
- (define-key electric-history-map [down] 'next-line)
- (define-key electric-history-map [up] 'previous-line)
- (define-key electric-history-map [prior] 'scroll-down)
- (define-key electric-history-map [next] 'scroll-up)
- (define-key electric-history-map "\C-l" 'recenter)
- (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'.")
-
-(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.
-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.
-
-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}
-
-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)
- (old-buffer (current-buffer))
- (todo))
- (unwind-protect
- (setq todo
- (catch 'electric-history-quit
- (save-window-excursion
- (save-window-excursion
- (list-command-history)
- (set-buffer "*Command History*")
- (Command-history-setup 'electric-command-history
- "Electric History"
- electric-history-map))
- (Electric-pop-up-window "*Command History*")
- (run-hooks 'electric-command-history-hook)
- (if (eobp)
- (progn (ding)
- (message "No command history.")
- (throw 'electric-history-quit nil))
- (let ((Helper-return-blurb "return to History"))
- (Electric-command-loop 'electric-history-quit
- "->" t))))))
- (set-buffer "*Command History*")
- (Command-history-setup)
- (bury-buffer (current-buffer)))
- (if (consp todo)
- (progn (set-buffer old-buffer)
- (if (car todo)
- (apply (car (car (cdr todo))) (cdr (car (cdr todo))))
- (edit-and-eval-command "Redo: " (car (cdr todo))))))))
-
-(defun Electric-history-undefined ()
- (interactive)
- (ding)
- (message (substitute-command-keys "Type \\[Helper-help] for help, ? for commands, C-c C-c to quit, Space to execute"))
- (sit-for 4))
-
-(defun Electric-history-quit ()
- "Quit Electric Command History, restoring previous window configuration."
- (interactive)
- (if (boundp 'electric-history-in-progress)
- (progn (message "")
- (throw 'electric-history-quit nil))))
-
-;;; echistory.el ends here
diff --git a/lisp/ediff-diff.el b/lisp/ediff-diff.el
deleted file mode 100644
index 31e126c2292..00000000000
--- a/lisp/ediff-diff.el
+++ /dev/null
@@ -1,1210 +0,0 @@
-;;; ediff-diff.el --- diff-related utilities
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Michael Kifer <kifer@cs.sunysb.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(require 'ediff-init)
-
-
-(defvar ediff-shell
- (cond ((eq system-type 'emx) "cmd") ; OS/2
- ((memq system-type '(ms-dos windows-nt windows-95))
- shell-file-name) ; no standard name on MS-DOS
- ((memq system-type '(vax-vms axp-vms)) "*dcl*") ; VMS
- (t "sh")) ; UNIX
- "*The shell used to run diff and patch. If user's .profile or
-.cshrc files are set up correctly, any shell will do. However, some people
-set $prompt or other things incorrectly, which leads to undesirable output
-messages. These may cause Ediff to fail. In such a case, set ediff-shell
-to a shell that you are not using or, better, fix your shell's startup file.")
-
-
-(defvar ediff-diff-program "diff"
- "*Program to use for generating the differential of the two files.")
-(defvar ediff-diff-options ""
- "*Options to pass to `ediff-diff-program'.
-If diff\(1\) is used as `ediff-diff-program', then the most useful options are
-`-w', to ignore space, and `-i', to ignore case of letters.
-At present, the option `-c' is ignored, since Ediff doesn't understand this
-type of output.")
-
-(defvar ediff-custom-diff-program ediff-diff-program
- "*Program to use for generating custom diff output for saving it in a file.
-This output is not used by Ediff internally.")
-(defvar ediff-custom-diff-options "-c"
- "*Options to pass to `ediff-custom-diff-program'.")
-
-;;; Support for diff3
-
-(defvar ediff-match-diff3-line "^====\\(.?\\)$"
- "Pattern to match lines produced by diff3 that describe differences.")
-(defvar ediff-diff3-program "diff3"
- "*Program to be used for three-way comparison.
-Must produce output compatible with Unix's diff3 program.")
-(defvar ediff-diff3-options ""
- "*Options to pass to `ediff-diff3-program'.")
-(defvar ediff-diff3-ok-lines-regexp
- "^\\([1-3]:\\|====\\| \\|.*Warning *:\\|.*No newline\\|.*missing newline\\|^\C-m$\\)"
- "*Regexp that matches normal output lines from `ediff-diff3-program'.
-Lines that do not match are assumed to be error messages.")
-
-;; keeps the status of the current diff in 3-way jobs.
-;; the status can be =diff(A), =diff(B), or =diff(A+B)
-(ediff-defvar-local ediff-diff-status "" "")
-
-
-;;; Fine differences
-
-(ediff-defvar-local ediff-auto-refine (if (ediff-has-face-support-p) 'on 'nix)
- "If `on', Ediff auto-highlights fine diffs for the current diff region.
-If `off', auto-highlighting is not used. If `nix', no fine diffs are shown
-at all, unless the user force-refines the region by hitting `*'.
-
-This variable can be set either in .emacs or toggled interactively.
-Use `setq-default' if setting it in .emacs")
-
-(ediff-defvar-local ediff-ignore-similar-regions nil
- "*If t, skip over difference regions that differ only in the white space and line breaks.
-This variable can be set either in .emacs or toggled interactively.
-Use `setq-default' if setting it in .emacs")
-
-(ediff-defvar-local ediff-auto-refine-limit 1400
- "*Auto-refine only the regions of this size \(in bytes\) or less.")
-
-;;; General
-
-(defvar ediff-diff-ok-lines-regexp
- "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\|.*Warning *:\\|.*No +newline\\|.*missing +newline\\|^\C-m$\\)"
- "Regexp that matches normal output lines from `ediff-diff-program'.
-This is mostly lifted from Emerge, except that Ediff also considers
-warnings and `Missing newline'-type messages to be normal output.
-Lines that do not match are assumed to be error messages.")
-
-(defvar ediff-match-diff-line (let ((x "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)"))
- (concat "^" x "\\([acd]\\)" x "$"))
- "Pattern to match lines produced by diff that describe differences.")
-
-(ediff-defvar-local ediff-setup-diff-regions-function nil
- "value is a function symbol depending on the kind of job is to be done.
-For 2-way jobs and for ediff-merge, it should be `ediff-setup-diff-regions'.
-For jobs requiring diff3, it should be `ediff-setup-diff-regions3'.
-
-The function should take three mandatory arguments, file-A, file-B, and
-file-C. It may ignore file C for diff2 jobs. It should also take
-one optional arguments, diff-number to refine.")
-
-
-;;; Functions
-
-;; Generate the difference vector and overlays for the two files
-;; With optional arg REG-TO-REFINE, refine this region.
-;; File-C argument is not used here. It is there just because
-;; ediff-setup-diff-regions is called via a funcall to
-;; ediff-setup-diff-regions-function, which can also have the value
-;; ediff-setup-diff-regions3, which takes 4 arguments.
-(defun ediff-setup-diff-regions (file-A file-B file-C)
-;;; ;; Force all minibuffers to display ediff's messages.
-;;; ;; When xemacs implements minibufferless frames, this won't be necessary
-;;; (if ediff-xemacs-p (setq synchronize-minibuffers t))
-
- ;; create, if it doesn't exist
- (or (ediff-buffer-live-p ediff-diff-buffer)
- (setq ediff-diff-buffer
- (get-buffer-create (ediff-unique-buffer-name "*ediff-diff" "*"))))
- (ediff-make-diff2-buffer ediff-diff-buffer file-A file-B)
- (ediff-prepare-error-list ediff-diff-ok-lines-regexp ediff-diff-buffer)
- (ediff-convert-diffs-to-overlays
- (ediff-extract-diffs
- ediff-diff-buffer ediff-word-mode ediff-narrow-bounds)))
-
-;; Run the diff program on FILE1 and FILE2 and put the output in DIFF-BUFFER
-;; Return the size of DIFF-BUFFER
-(defun ediff-make-diff2-buffer (diff-buffer file1 file2)
- (let ((file1-size (ediff-file-size file1))
- (file2-size (ediff-file-size file2)))
- (cond ((not (numberp file1-size))
- (message "Can't find file: %s"
- (ediff-abbreviate-file-name file1))
- (sit-for 2)
- ;; 1 is an error exit code
- 1)
- ((not (numberp file2-size))
- (message "Can't find file: %s"
- (ediff-abbreviate-file-name file2))
- (sit-for 2)
- ;; 1 is an error exit code
- 1)
- ((< file1-size 0)
- (message "Can't diff remote files: %s"
- (ediff-abbreviate-file-name file1))
- (sit-for 2)
- ;; 1 is an error exit code
- 1)
- ((< file2-size 0)
- (message "Can't diff remote file: %s"
- (ediff-abbreviate-file-name file2))
- (sit-for 2)
- (message "")
- ;; 1 is an error exit code
- 1)
- (t (message "Computing differences between %s and %s ..."
- (file-name-nondirectory file1)
- (file-name-nondirectory file2))
- ;; this erases the diff buffer automatically
- (ediff-exec-process ediff-diff-program
- diff-buffer
- 'synchronize
- ediff-diff-options file1 file2)
- ;;(message "Computing differences ... done")
- (message "")
- (ediff-eval-in-buffer diff-buffer
- (buffer-size))))))
-
-
-
-;; If file-A/B/C is nil, do 2-way comparison with the non-nil buffers
-;; This function works for diff3 and diff2 jobs
-(defun ediff-setup-fine-diff-regions (file-A file-B file-C reg-num)
- (or (ediff-buffer-live-p ediff-fine-diff-buffer)
- (setq ediff-fine-diff-buffer
- (get-buffer-create
- (ediff-unique-buffer-name "*ediff-fine-diff" "*"))))
-
- (let (diff3-job diff-program diff-options ok-regexp diff-list)
- (setq diff3-job ediff-3way-job
- diff-program (if diff3-job ediff-diff3-program ediff-diff-program)
- diff-options (if diff3-job ediff-diff3-options ediff-diff-options)
- ok-regexp (if diff3-job
- ediff-diff3-ok-lines-regexp
- ediff-diff-ok-lines-regexp))
-
- (ediff-message-if-verbose "Refining difference region %d ..." (1+ reg-num))
- (ediff-exec-process diff-program ediff-fine-diff-buffer 'synchronize
- diff-options
- ;; The shuffle below is because we can compare 3-way
- ;; or in several 2-way fashions, like fA fC, fA fB,
- ;; or fB fC.
- (if file-A file-A file-B)
- (if file-B file-B file-A)
- (if diff3-job
- (if file-C file-C file-B))
- ) ; exec process
-
- (ediff-prepare-error-list ok-regexp ediff-fine-diff-buffer)
- (ediff-message-if-verbose
- "")
- ;; "Refining difference region %d ... done" (1+ reg-num))
-
- (setq diff-list
- (if diff3-job
- (ediff-extract-diffs3
- ediff-fine-diff-buffer '3way-comparison 'word-mode)
- (ediff-extract-diffs ediff-fine-diff-buffer 'word-mode)))
- ;; fixup diff-list
- (if diff3-job
- (cond ((not file-A)
- (mapcar (function (lambda (elt)
- (aset elt 0 nil)
- (aset elt 1 nil)))
- (cdr diff-list)))
- ((not file-B)
- (mapcar (function (lambda (elt)
- (aset elt 2 nil)
- (aset elt 3 nil)))
- (cdr diff-list)))
- ((not file-C)
- (mapcar (function (lambda (elt)
- (aset elt 4 nil)
- (aset elt 5 nil)))
- (cdr diff-list)))
- ))
-
- (ediff-convert-fine-diffs-to-overlays diff-list reg-num)
- ))
-
-
-(defun ediff-prepare-error-list (ok-regexp diff-buff)
- (or (ediff-buffer-live-p ediff-error-buffer)
- (setq ediff-error-buffer
- (get-buffer-create (ediff-unique-buffer-name
- "*ediff-errors" "*"))))
- (ediff-eval-in-buffer ediff-error-buffer
- (erase-buffer)
- (insert (ediff-eval-in-buffer diff-buff (buffer-string)))
- (goto-char (point-min))
- (delete-matching-lines ok-regexp)
- (if (memq system-type '(vax-vms axp-vms))
- (delete-matching-lines "^$")))
- ;; If diff reports errors, show them then quit.
- (if (/= 0 (ediff-eval-in-buffer ediff-error-buffer (buffer-size)))
- (let ((ctl-buf ediff-control-buffer)
- (error-buf ediff-error-buffer))
- (ediff-skip-unsuitable-frames)
- (switch-to-buffer error-buf)
- (ediff-kill-buffer-carefully ctl-buf)
- (error "Errors in diff output. Diff output is in %S" diff-buff))))
-
-;; BOUNDS specifies visibility bounds to use.
-;; WORD-MODE tells whether we are in the word-mode or not.
-;; If WORD-MODE, also construct vector of diffs using word numbers.
-;; Else, use point values.
-;; This function handles diff-2 jobs including the case of
-;; merging buffers and files without ancestor.
-(defun ediff-extract-diffs (diff-buffer word-mode &optional bounds)
- (let ((A-buffer ediff-buffer-A)
- (B-buffer ediff-buffer-B)
- (C-buffer ediff-buffer-C)
- (a-prev 1) ; this is needed to set the first diff line correctly
- (b-prev 1)
- (c-prev 1)
- diff-list shift-A shift-B
- )
-
- ;; diff list contains word numbers, unless changed later
- (setq diff-list (cons (if word-mode 'words 'points)
- diff-list))
- ;; we don't use visibility bounds for buffer C when merging
- (if bounds
- (setq shift-A
- (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type 'A bounds))
- shift-B
- (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type 'B bounds))))
-
- ;; reset point in buffers A/B/C
- (ediff-eval-in-buffer A-buffer
- (goto-char (if shift-A shift-A (point-min))))
- (ediff-eval-in-buffer B-buffer
- (goto-char (if shift-B shift-B (point-min))))
- (if (ediff-buffer-live-p C-buffer)
- (ediff-eval-in-buffer C-buffer
- (goto-char (point-min))))
-
- (ediff-eval-in-buffer diff-buffer
- (goto-char (point-min))
- (while (re-search-forward ediff-match-diff-line nil t)
- (let* ((a-begin (string-to-int (buffer-substring (match-beginning 1)
- (match-end 1))))
- (a-end (let ((b (match-beginning 3))
- (e (match-end 3)))
- (if b
- (string-to-int (buffer-substring b e))
- a-begin)))
- (diff-type (buffer-substring (match-beginning 4) (match-end 4)))
- (b-begin (string-to-int (buffer-substring (match-beginning 5)
- (match-end 5))))
- (b-end (let ((b (match-beginning 7))
- (e (match-end 7)))
- (if b
- (string-to-int (buffer-substring b e))
- b-begin)))
- a-begin-pt a-end-pt b-begin-pt b-end-pt
- c-begin c-end c-begin-pt c-end-pt)
- ;; fix the beginning and end numbers, because diff is somewhat
- ;; strange about how it numbers lines
- (if (string-equal diff-type "a")
- (setq b-end (1+ b-end)
- a-begin (1+ a-begin)
- a-end a-begin)
- (if (string-equal diff-type "d")
- (setq a-end (1+ a-end)
- b-begin (1+ b-begin)
- b-end b-begin)
- ;; (string-equal diff-type "c")
- (setq a-end (1+ a-end)
- b-end (1+ b-end))))
-
- (if (eq ediff-default-variant 'default-B)
- (setq c-begin b-begin
- c-end b-end)
- (setq c-begin a-begin
- c-end a-end))
-
- ;; compute main diff vector
- (if word-mode
- ;; make diff-list contain word numbers
- (setq diff-list
- (nconc diff-list
- (list
- (if (ediff-buffer-live-p C-buffer)
- (vector (- a-begin a-prev) (- a-end a-begin)
- (- b-begin b-prev) (- b-end b-begin)
- (- c-begin c-prev) (- c-end c-begin)
- nil nil ; dummy ancestor
- nil ; state of diff
- nil ; state of merge
- nil ; state of ancestor
- )
- (vector (- a-begin a-prev) (- a-end a-begin)
- (- b-begin b-prev) (- b-end b-begin)
- nil nil ; dummy buf C
- nil nil ; dummy ancestor
- nil ; state of diff
- nil ; state of merge
- nil ; state of ancestor
- ))
- ))
- a-prev a-end
- b-prev b-end
- c-prev c-end)
- ;; else convert lines to points
- (ediff-eval-in-buffer A-buffer
- (forward-line (- a-begin a-prev))
- (setq a-begin-pt (point))
- (forward-line (- a-end a-begin))
- (setq a-end-pt (point)
- a-prev a-end))
- (ediff-eval-in-buffer B-buffer
- (forward-line (- b-begin b-prev))
- (setq b-begin-pt (point))
- (forward-line (- b-end b-begin))
- (setq b-end-pt (point)
- b-prev b-end))
- (if (ediff-buffer-live-p C-buffer)
- (ediff-eval-in-buffer C-buffer
- (forward-line (- c-begin c-prev))
- (setq c-begin-pt (point))
- (forward-line (- c-end c-begin))
- (setq c-end-pt (point)
- c-prev c-end)))
- (setq diff-list
- (nconc
- diff-list
- (list
- (if (ediff-buffer-live-p C-buffer)
- (vector
- a-begin-pt a-end-pt b-begin-pt b-end-pt
- c-begin-pt c-end-pt
- nil nil ; dummy ancestor
- ;; state of diff
- ;; shows which buff is different from the other two
- (if (eq ediff-default-variant 'default-B) 'A 'B)
- ediff-default-variant ; state of merge
- nil ; state of ancestor
- )
- (vector a-begin-pt a-end-pt
- b-begin-pt b-end-pt
- nil nil ; dummy buf C
- nil nil ; dummy ancestor
- nil nil ; dummy state of diff & merge
- nil ; dummy state of ancestor
- )))
- )))
-
- ))) ; end ediff-eval-in-buffer
- diff-list
- ))
-
-
-(defun ediff-convert-diffs-to-overlays (diff-list)
- (ediff-set-diff-overlays-in-one-buffer 'A diff-list)
- (ediff-set-diff-overlays-in-one-buffer 'B diff-list)
- (if ediff-3way-job
- (ediff-set-diff-overlays-in-one-buffer 'C diff-list))
- (if ediff-merge-with-ancestor-job
- (ediff-set-diff-overlays-in-one-buffer 'Ancestor diff-list))
- ;; set up vector showing the status of merge regions
- (if ediff-merge-job
- (setq ediff-state-of-merge
- (vconcat
- (mapcar (function
- (lambda (elt)
- (let ((state-of-merge (aref elt 9))
- (state-of-ancestor (aref elt 10)))
- (vector
- (if state-of-merge (format "%S" state-of-merge))
- state-of-ancestor))))
- ;; the first elt designates type of list
- (cdr diff-list))
- )))
- (message "Processing difference regions ... done"))
-
-
-(defun ediff-set-diff-overlays-in-one-buffer (buf-type diff-list)
- (let* ((current-diff -1)
- (buff (ediff-get-buffer buf-type))
- ;; ediff-extract-diffs puts the type of diff-list as the first elt
- ;; of this list. The type is either 'points or 'words
- (diff-list-type (car diff-list))
- (shift (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type
- buf-type ediff-narrow-bounds)))
- (limit (ediff-overlay-end
- (ediff-get-value-according-to-buffer-type
- buf-type ediff-narrow-bounds)))
- diff-overlay-list list-element total-diffs
- begin end pt-saved overlay state-of-diff)
-
- (setq diff-list (cdr diff-list)) ; discard diff list type
- (setq total-diffs (length diff-list))
-
- ;; shift, if necessary
- (ediff-eval-in-buffer buff (setq pt-saved shift))
-
- (while diff-list
- (setq current-diff (1+ current-diff)
- list-element (car diff-list)
- begin (aref list-element (cond ((eq buf-type 'A) 0)
- ((eq buf-type 'B) 2)
- ((eq buf-type 'C) 4)
- (t 6))) ; Ancestor
- end (aref list-element (cond ((eq buf-type 'A) 1)
- ((eq buf-type 'B) 3)
- ((eq buf-type 'C) 5)
- (t 7))) ; Ancestor
- state-of-diff (aref list-element 8)
- )
-
- (cond ((and (not (eq buf-type state-of-diff))
- (not (eq buf-type 'Ancestor))
- (memq state-of-diff '(A B C)))
- (setq state-of-diff
- (car (delq buf-type (delq state-of-diff (list 'A 'B 'C)))))
- (setq state-of-diff (format "=diff(%S)" state-of-diff))
- )
- (t (setq state-of-diff nil)))
-
- ;; Put overlays at appropriate places in buffer
- ;; convert word numbers to points, if necessary
- (if (eq diff-list-type 'words)
- (progn
- (ediff-eval-in-buffer buff (goto-char pt-saved))
- (setq begin (ediff-goto-word (1+ begin) buff)
- end (ediff-goto-word end buff 'end))
- (if (> end limit) (setq end limit))
- (if (> begin end) (setq begin end))
- (setq pt-saved (ediff-eval-in-buffer buff (point)))))
- (setq overlay (ediff-make-bullet-proof-overlay begin end buff))
-
- (ediff-overlay-put overlay 'priority ediff-shadow-overlay-priority)
- (ediff-overlay-put overlay 'ediff-diff-num current-diff)
- (if (and (ediff-has-face-support-p)
- ediff-use-faces ediff-highlight-all-diffs)
- (ediff-set-overlay-face
- overlay (ediff-background-face buf-type current-diff)))
-
- (if (= 0 (mod current-diff 10))
- (message "Buffer %S: Processing difference region %d of %d"
- buf-type current-diff total-diffs))
- ;; record all overlays for this difference
- ;; the second elt, nil, is a place holder for the fine diff vector.
- ;; the third elt, nil, is a place holder for no-fine-diffs flag.
- (setq diff-overlay-list
- (nconc
- diff-overlay-list
- (list (vector overlay nil nil state-of-diff)))
- diff-list
- (cdr diff-list))
- ) ; while
-
- (set (intern (format "ediff-difference-vector-%S" buf-type))
- (vconcat diff-overlay-list))
- ))
-
-;; `n' is the diff region to work on. Default is ediff-current-difference.
-;; if `flag' is 'noforce then make fine-diffs only if this region's fine
-;; diffs have not been computed before.
-;; if `flag' is 'skip then don't compute fine diffs for this region.
-(defun ediff-make-fine-diffs (&optional n flag)
- (or n (setq n ediff-current-difference))
-
- (if (< ediff-number-of-differences 1)
- (error ediff-NO-DIFFERENCES))
-
- (if ediff-word-mode
- (setq flag 'skip
- ediff-auto-refine 'nix))
-
- (or (< n 0)
- (>= n ediff-number-of-differences)
- ;; n is within the range
- (let ((tmp-buffer (get-buffer-create ediff-tmp-buffer))
- (file-A ediff-temp-file-A)
- (file-B ediff-temp-file-B)
- (file-C ediff-temp-file-C)
- (empty-A (ediff-empty-diff-region-p n 'A))
- (empty-B (ediff-empty-diff-region-p n 'B))
- (empty-C (ediff-empty-diff-region-p n 'C))
- (whitespace-A (ediff-whitespace-diff-region-p n 'A))
- (whitespace-B (ediff-whitespace-diff-region-p n 'B))
- (whitespace-C (ediff-whitespace-diff-region-p n 'C))
- cumulative-fine-diff-length)
-
- (cond ((and (eq flag 'noforce) (ediff-get-fine-diff-vector n 'A))
- ;; don't compute fine diffs if diff vector exists
- (if (ediff-no-fine-diffs-p n)
- ;;(ediff-message-if-verbose
- (message
- "Only white-space differences in region %d" (1+ n))))
- ;; If one of the regions is empty (or 2 in 3way comparison)
- ;; then don't refine.
- ;; If the region happens to be entirely whitespace or empty then
- ;; mark as such.
- ((> (length (delq nil (list empty-A empty-B empty-C))) 1)
- (if (and (ediff-looks-like-combined-merge n)
- ediff-merge-job)
- (ediff-set-fine-overlays-in-one-buffer 'C nil n))
- (if ediff-3way-comparison-job
- (ediff-message-if-verbose
- "Region %d is empty in all buffers but %S"
- (1+ n)
- (cond ((not empty-A) 'A)
- ((not empty-B) 'B)
- ((not empty-C) 'C)))
- (ediff-message-if-verbose
- "Region %d in buffer %S is empty"
- (1+ n)
- (cond (empty-A 'A)
- (empty-B 'B)
- (empty-C 'C)))
- )
- ;; if all regions happen to be whitespace
- (if (and whitespace-A whitespace-B whitespace-C)
- ;; mark as space only
- (ediff-mark-diff-as-space-only n t)
- ;; if some regions are white and others don't, then mark as
- ;; non-white-space-only
- (ediff-mark-diff-as-space-only n nil)))
- ;; don't compute fine diffs for this region
- ((eq flag 'skip)
- (or (ediff-get-fine-diff-vector n 'A)
- (memq ediff-auto-refine '(off nix))
- (ediff-message-if-verbose
- "Region %d exceeds auto-refine limit. Type `%s' to refine"
- (1+ n)
- (substitute-command-keys
- "\\[ediff-make-or-kill-fine-diffs]")
- )))
- (t
- ;; recompute fine diffs
- (ediff-wordify
- (ediff-get-diff-posn 'A 'beg n)
- (ediff-get-diff-posn 'A 'end n)
- ediff-buffer-A
- tmp-buffer
- ediff-control-buffer)
- (setq file-A
- (ediff-make-temp-file tmp-buffer "fineDiffA" file-A))
-
- (ediff-wordify
- (ediff-get-diff-posn 'B 'beg n)
- (ediff-get-diff-posn 'B 'end n)
- ediff-buffer-B
- tmp-buffer
- ediff-control-buffer)
- (setq file-B
- (ediff-make-temp-file tmp-buffer "fineDiffB" file-B))
-
- (if ediff-3way-job
- (progn
- (ediff-wordify
- (ediff-get-diff-posn 'C 'beg n)
- (ediff-get-diff-posn 'C 'end n)
- ediff-buffer-C
- tmp-buffer
- ediff-control-buffer)
- (setq file-C
- (ediff-make-temp-file
- tmp-buffer "fineDiffC" file-C))))
-
- ;; save temp file names.
- (setq ediff-temp-file-A file-A
- ediff-temp-file-B file-B
- ediff-temp-file-C file-C)
-
- ;; set the new vector of fine diffs, if none exists
- (cond ((and ediff-3way-job whitespace-A)
- (ediff-setup-fine-diff-regions nil file-B file-C n))
- ((and ediff-3way-job whitespace-B)
- (ediff-setup-fine-diff-regions file-A nil file-C n))
- ((and ediff-3way-job
- ;; In merge-jobs, whitespace-C is t, since
- ;; ediff-empty-diff-region-p returns t in this case
- whitespace-C)
- (ediff-setup-fine-diff-regions file-A file-B nil n))
- (t
- (ediff-setup-fine-diff-regions file-A file-B file-C n)))
-
- (setq cumulative-fine-diff-length
- (+ (length (ediff-get-fine-diff-vector n 'A))
- (length (ediff-get-fine-diff-vector n 'B))
- ;; in merge jobs, the merge buffer is never refined
- (if (and file-C (not ediff-merge-job))
- (length (ediff-get-fine-diff-vector n 'C))
- 0)))
-
- (cond ((or
- ;; all regions are white space
- (and whitespace-A whitespace-B whitespace-C)
- ;; none is white space and no fine diffs detected
- (and (not whitespace-A)
- (not whitespace-B)
- (not (and ediff-3way-job whitespace-C))
- (eq cumulative-fine-diff-length 0)))
- (ediff-mark-diff-as-space-only n t)
- (ediff-message-if-verbose
- "Only white-space differences in region %d" (1+ n)))
- ((eq cumulative-fine-diff-length 0)
- (ediff-mark-diff-as-space-only n t)
- (ediff-message-if-verbose
- "Only white-space differences in region %d %s"
- (1+ n)
- (cond (whitespace-A "in buffers B & C")
- (whitespace-B "in buffers A & C")
- (whitespace-C "in buffers A & B"))))
- (t
- (ediff-mark-diff-as-space-only n nil)))
- )
- ) ; end cond
- (ediff-set-fine-diff-properties n)
- )))
-
-;; Interface to ediff-make-fine-diffs. Checks for auto-refine limit, etc.
-(defun ediff-install-fine-diff-if-necessary (n)
- (cond ((eq ediff-auto-refine 'on)
- (if (and
- (> ediff-auto-refine-limit
- (- (ediff-get-diff-posn 'A 'end n)
- (ediff-get-diff-posn 'A 'beg n)))
- (> ediff-auto-refine-limit
- (- (ediff-get-diff-posn 'B 'end n)
- (ediff-get-diff-posn 'B 'beg n))))
- (ediff-make-fine-diffs n 'noforce)
- (ediff-make-fine-diffs n 'skip)))
-
- ;; highlight iff fine diffs already exist
- ((eq ediff-auto-refine 'off)
- (ediff-make-fine-diffs n 'skip))))
-
-
-;; if fine diff vector is not set for diff N, then do nothing
-(defun ediff-set-fine-diff-properties (n &optional default)
- (or (not (ediff-has-face-support-p))
- (< n 0)
- (>= n ediff-number-of-differences)
- ;; when faces are supported, set faces and priorities of fine overlays
- (progn
- (ediff-set-fine-diff-properties-in-one-buffer 'A n default)
- (ediff-set-fine-diff-properties-in-one-buffer 'B n default)
- (if ediff-3way-job
- (ediff-set-fine-diff-properties-in-one-buffer 'C n default)))))
-
-(defun ediff-set-fine-diff-properties-in-one-buffer (buf-type
- n &optional default)
- (let ((fine-diff-vector (ediff-get-fine-diff-vector n buf-type))
- (face (if default
- 'default
- (face-name
- (intern (format "ediff-fine-diff-face-%S" buf-type)))))
- (priority (if default
- 0
- (1+ (or (ediff-overlay-get
- (symbol-value
- (intern
- (format
- "ediff-current-diff-overlay-%S" buf-type)))
- 'priority)
- 0)))))
- (mapcar
- (function (lambda (overl)
- (ediff-set-overlay-face overl face)
- (ediff-overlay-put overl 'priority priority)))
- fine-diff-vector)))
-
-;; This assumes buffer C and that the region looks like a combination of
-;; regions in buffer A and C.
-(defun ediff-set-fine-overlays-for-combined-merge (diff-list reg-num)
- (let (overlay1 overlay2 overlay3)
- (setq overlay1 (ediff-make-bullet-proof-overlay (nth 0 diff-list)
- (nth 1 diff-list)
- ediff-buffer-C)
- overlay2 (ediff-make-bullet-proof-overlay (nth 2 diff-list)
- (nth 3 diff-list)
- ediff-buffer-C)
- overlay3 (ediff-make-bullet-proof-overlay (nth 4 diff-list)
- (nth 5 diff-list)
- ediff-buffer-C))
- (ediff-set-fine-diff-vector reg-num 'C (vector overlay1 overlay2 overlay3))
- ))
-
-
-;; Convert diff list to overlays for a given DIFF-REGION
-;; in buffer of type BUF-TYPE
-(defun ediff-set-fine-overlays-in-one-buffer (buf-type diff-list region-num)
- (let* ((current-diff -1)
- (reg-start (ediff-get-diff-posn buf-type 'beg region-num))
- (buff (ediff-get-buffer buf-type))
- combined-merge-diff-list
- diff-overlay-list list-element
- begin end overlay)
-
- (ediff-clear-fine-differences-in-one-buffer region-num buf-type)
- (setq diff-list (cdr diff-list)) ; discard list type (words or points)
- (ediff-eval-in-buffer buff (goto-char reg-start))
-
- ;; if it is a combined merge then set overlays in buff C specially
- (if (and ediff-merge-job (eq buf-type 'C)
- (setq combined-merge-diff-list
- (ediff-looks-like-combined-merge region-num)))
- (ediff-set-fine-overlays-for-combined-merge
- combined-merge-diff-list region-num)
- ;; regular fine diff
- (while diff-list
- (setq current-diff (1+ current-diff)
- list-element (car diff-list)
- begin (aref list-element (cond ((eq buf-type 'A) 0)
- ((eq buf-type 'B) 2)
- (t 4))) ; buf C
- end (aref list-element (cond ((eq buf-type 'A) 1)
- ((eq buf-type 'B) 3)
- (t 5)))) ; buf C
- (if (not (or begin end))
- () ; skip this diff
- ;; Put overlays at appropriate places in buffers
- ;; convert lines to points, if necessary
- (setq begin (ediff-goto-word (1+ begin) buff)
- end (ediff-goto-word end buff 'end))
- (setq overlay (ediff-make-bullet-proof-overlay begin end buff))
- ;; record all overlays for this difference region
- (setq diff-overlay-list (nconc diff-overlay-list (list overlay))))
-
- (setq diff-list (cdr diff-list))
- ) ; while
- ;; convert the list of difference information into a vector
- ;; for fast access
- (ediff-set-fine-diff-vector
- region-num buf-type (vconcat diff-overlay-list))
- )))
-
-
-;; Stolen from emerge.el
-(defun ediff-get-diff3-group (file)
- ;; This save-excursion allows ediff-get-diff3-group to be called for the
- ;; various groups of lines (1, 2, 3) in any order, and for the lines to
- ;; appear in any order. The reason this is necessary is that Gnu diff3
- ;; can produce the groups in the order 1, 2, 3 or 1, 3, 2.
- (save-excursion
- (re-search-forward
- (concat "^" file ":\\([0-9]+\\)\\(,\\([0-9]+\\)\\)?\\([ac]\\)$"))
- (beginning-of-line 2)
- ;; treatment depends on whether it is an "a" group or a "c" group
- (if (string-equal (buffer-substring (match-beginning 4) (match-end 4)) "c")
- ;; it is a "c" group
- (if (match-beginning 2)
- ;; it has two numbers
- (list (string-to-int
- (buffer-substring (match-beginning 1) (match-end 1)))
- (1+ (string-to-int
- (buffer-substring (match-beginning 3) (match-end 3)))))
- ;; it has one number
- (let ((x (string-to-int
- (buffer-substring (match-beginning 1) (match-end 1)))))
- (list x (1+ x))))
- ;; it is an "a" group
- (let ((x (1+ (string-to-int
- (buffer-substring (match-beginning 1) (match-end 1))))))
- (list x x)))))
-
-
-;; If WORD-MODE, construct vector of diffs using word numbers.
-;; Else, use point values.
-;; WORD-MODE also tells if we are in the word-mode or not.
-;; If THREE-WAY-COMP, then it is a 3-way comparison. Else, it is merging
-;; with ancestor, in which case buffer-C contents is identical to buffer-A/B,
-;; contents (unless buffer-A is narrowed) depending on ediff-default-variant's
-;; value.
-;; BOUNDS specifies visibility bounds to use.
-(defun ediff-extract-diffs3 (diff-buffer word-mode three-way-comp
- &optional bounds)
- (let ((A-buffer ediff-buffer-A)
- (B-buffer ediff-buffer-B)
- (C-buffer ediff-buffer-C)
- (anc-buffer ediff-ancestor-buffer)
- (a-prev 1) ; needed to set the first diff line correctly
- (b-prev 1)
- (c-prev 1)
- (anc-prev 1)
- diff-list shift-A shift-B shift-C
- )
-
- ;; diff list contains word numbers or points, depending on word-mode
- (setq diff-list (cons (if word-mode 'words 'points)
- diff-list))
- (if bounds
- (setq shift-A
- (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type 'A bounds))
- shift-B
- (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type 'B bounds))
- shift-C
- (if three-way-comp
- (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type 'C bounds)))))
-
- ;; reset point in buffers A, B, C
- (ediff-eval-in-buffer A-buffer
- (goto-char (if shift-A shift-A (point-min))))
- (ediff-eval-in-buffer B-buffer
- (goto-char (if shift-B shift-B (point-min))))
- (if three-way-comp
- (ediff-eval-in-buffer C-buffer
- (goto-char (if shift-C shift-C (point-min)))))
- (if (ediff-buffer-live-p anc-buffer)
- (ediff-eval-in-buffer anc-buffer
- (goto-char (point-min))))
-
- (ediff-eval-in-buffer diff-buffer
- (goto-char (point-min))
- (while (re-search-forward ediff-match-diff3-line nil t)
- ;; leave point after matched line
- (beginning-of-line 2)
- (let ((agreement (buffer-substring (match-beginning 1) (match-end 1))))
- ;; if the files A and B are the same and not 3way-comparison,
- ;; ignore the difference
- (if (or three-way-comp (not (string-equal agreement "3")))
- (let* ((a-begin (car (ediff-get-diff3-group "1")))
- (a-end (nth 1 (ediff-get-diff3-group "1")))
- (b-begin (car (ediff-get-diff3-group "2")))
- (b-end (nth 1 (ediff-get-diff3-group "2")))
- (c-or-anc-begin (car (ediff-get-diff3-group "3")))
- (c-or-anc-end (nth 1 (ediff-get-diff3-group "3")))
- (state-of-merge
- (cond ((string-equal agreement "1") 'prefer-A)
- ((string-equal agreement "2") 'prefer-B)
- (t ediff-default-variant)))
- (state-of-diff-merge
- (if (memq state-of-merge '(default-A prefer-A)) 'B 'A))
- (state-of-diff-comparison
- (cond ((string-equal agreement "1") 'A)
- ((string-equal agreement "2") 'B)
- ((string-equal agreement "3") 'C)))
- state-of-ancestor
- c-begin c-end
- a-begin-pt a-end-pt
- b-begin-pt b-end-pt
- c-begin-pt c-end-pt
- anc-begin-pt anc-end-pt)
-
- (setq state-of-ancestor
- (= c-or-anc-begin c-or-anc-end))
-
- (cond (three-way-comp
- (setq c-begin c-or-anc-begin
- c-end c-or-anc-end))
- ((eq ediff-default-variant 'default-B)
- (setq c-begin b-begin
- c-end b-end))
- (t
- (setq c-begin a-begin
- c-end a-end)))
-
- ;; compute main diff vector
- (if word-mode
- ;; make diff-list contain word numbers
- (setq diff-list
- (nconc diff-list
- (list (vector
- (- a-begin a-prev) (- a-end a-begin)
- (- b-begin b-prev) (- b-end b-begin)
- (- c-begin c-prev) (- c-end c-begin)
- nil nil ; dummy ancestor
- nil ; state of diff
- nil ; state of merge
- nil ; state of ancestor
- )))
- a-prev a-end
- b-prev b-end
- c-prev c-end)
- ;; else convert lines to points
- (ediff-eval-in-buffer A-buffer
- (forward-line (- a-begin a-prev))
- (setq a-begin-pt (point))
- (forward-line (- a-end a-begin))
- (setq a-end-pt (point)
- a-prev a-end))
- (ediff-eval-in-buffer B-buffer
- (forward-line (- b-begin b-prev))
- (setq b-begin-pt (point))
- (forward-line (- b-end b-begin))
- (setq b-end-pt (point)
- b-prev b-end))
- (ediff-eval-in-buffer C-buffer
- (forward-line (- c-begin c-prev))
- (setq c-begin-pt (point))
- (forward-line (- c-end c-begin))
- (setq c-end-pt (point)
- c-prev c-end))
- (if (ediff-buffer-live-p anc-buffer)
- (ediff-eval-in-buffer anc-buffer
- (forward-line (- c-or-anc-begin anc-prev))
- (setq anc-begin-pt (point))
- (forward-line (- c-or-anc-end c-or-anc-begin))
- (setq anc-end-pt (point)
- anc-prev c-or-anc-end)))
- (setq diff-list
- (nconc
- diff-list
- ;; if comparing with ancestor, then there also is a
- ;; state-of-difference marker
- (if three-way-comp
- (list (vector
- a-begin-pt a-end-pt
- b-begin-pt b-end-pt
- c-begin-pt c-end-pt
- nil nil ; ancestor begin/end
- state-of-diff-comparison
- nil ; state of merge
- nil ; state of ancestor
- ))
- (list (vector a-begin-pt a-end-pt
- b-begin-pt b-end-pt
- c-begin-pt c-end-pt
- anc-begin-pt anc-end-pt
- state-of-diff-merge
- state-of-merge
- state-of-ancestor
- )))
- )))
- ))
-
- ))) ; end ediff-eval-in-buffer
- diff-list
- ))
-
-;; Generate the difference vector and overlays for three files
-;; File-C is either the third file to compare (in case of 3-way comparison)
-;; or it is the ancestor file.
-(defun ediff-setup-diff-regions3 (file-A file-B file-C)
-
-;;; ;; force all minibuffers to display ediff's messages.
-;;; ;; when xemacs implements minibufferless frames, this won't be necessary
-;;; (if ediff-xemacs-p (setq synchronize-minibuffers t))
-
- (or (ediff-buffer-live-p ediff-diff-buffer)
- (setq ediff-diff-buffer
- (get-buffer-create (ediff-unique-buffer-name "*ediff-diff" "*"))))
-
- (message "Computing differences ...")
- (ediff-exec-process ediff-diff3-program ediff-diff-buffer 'synchronize
- ediff-diff3-options file-A file-B file-C)
-
- (ediff-prepare-error-list ediff-diff3-ok-lines-regexp ediff-diff-buffer)
- ;;(message "Computing differences ... done")
- (ediff-convert-diffs-to-overlays
- (ediff-extract-diffs3
- ediff-diff-buffer
- ediff-word-mode ediff-3way-comparison-job ediff-narrow-bounds)
- ))
-
-
-;; Execute PROGRAM asynchronously, unless OS/2, Windows-*, or DOS, or unless
-;; SYNCH is non-nil. BUFFER must be a buffer object, and must be alive. All
-;; arguments in ARGS must be strings. The first arg may be a blank string, in
-;; which case we delete it from ARGS list. We also delete nil from args.
-(defun ediff-exec-process (program buffer synch &rest args)
- (let ((data (match-data)))
- (if (string-match "^[ \t]*$" (car args)) ; delete blank string
- (setq args (cdr args)))
- (setq args (delq nil args)) ; delete nil from arguments
- (setq args (ediff-split-string (mapconcat 'identity args " ")))
- (unwind-protect
- (let ((directory default-directory)
- proc)
- (save-excursion
- (set-buffer buffer)
- (erase-buffer)
- (setq default-directory directory)
- (if (or (memq system-type '(emx ms-dos windows-nt windows-95))
- synch)
- ;; In OS/2 (emx) do it synchronously, since OS/2 doesn't let us
- ;; delete files used by other processes. Thus, in ediff-buffers
- ;; and similar functions, we can't delete temp files because
- ;; they might be used by the asynch process that computes
- ;; custom diffs. So, we have to wait till custom diff
- ;; subprocess is done.
- ;; Similarly for Windows-*
- ;; In DOS, must synchronize because DOS doesn't have
- ;; asynchronous processes.
- (apply 'call-process program nil buffer nil args)
- ;; On other systems, do it asynchronously.
- (setq proc (get-buffer-process buffer))
- (if proc (kill-process proc))
- (setq proc
- (apply 'start-process "Custom Diff" buffer program args))
- (setq mode-line-process '(":%s"))
- (set-process-sentinel proc 'ediff-process-sentinel)
- (set-process-filter proc 'ediff-process-filter)
- )))
- (store-match-data data))))
-
-;; This is shell-command-filter from simple.el in FSF Emacs.
-;; Copied here because XEmacs doesn't have it.
-(defun ediff-process-filter (proc string)
- ;; Do save-excursion by hand so that we can leave point numerically unchanged
- ;; despite an insertion immediately after it.
- (let* ((obuf (current-buffer))
- (buffer (process-buffer proc))
- opoint
- (window (get-buffer-window buffer))
- (pos (window-start window)))
- (unwind-protect
- (progn
- (set-buffer buffer)
- (or (= (point) (point-max))
- (setq opoint (point)))
- (goto-char (point-max))
- (insert-before-markers string))
- ;; insert-before-markers moved this marker: set it back.
- (set-window-start window pos)
- ;; Finish our save-excursion.
- (if opoint
- (goto-char opoint))
- (set-buffer obuf))))
-
-;; like shell-command-sentinel but doesn't print an exit status message
-;; we do this because diff always exits with status 1, if diffs are found
-;; so shell-command-sentinel displays a confusing message to the user
-(defun ediff-process-sentinel (process signal)
- (if (and (memq (process-status process) '(exit signal))
- (buffer-name (process-buffer process)))
- (progn
- (save-excursion
- (set-buffer (process-buffer process))
- (setq mode-line-process nil))
- (delete-process process))))
-
-
-;;; Word functions used to refine the current diff
-
-(defvar ediff-forward-word-function 'ediff-forward-word
- "*Function to call to move to the next word.
-Used for splitting difference regions into individual words.")
-
-(defvar ediff-whitespace " \n\t\f"
- "*Characters constituting white space.
-These characters are ignored when differing regions are split into words.")
-
-;;(defvar ediff-word-1 "a-zA-Z---_`'.?!:"
-(defvar ediff-word-1 "a-zA-Z---_"
- "*Characters that constitute words of type 1.
-More precisely, [ediff-word-1] is a regexp that matches type 1 words.
-See `ediff-forward-word' for more details.")
-
-(defvar ediff-word-2 "0-9.,"
- "*Characters that constitute words of type 2.
-More precisely, [ediff-word-2] is a regexp that matches type 2 words.
-See `ediff-forward-word' for more details.")
-
-(defvar ediff-word-3 "`'?!:;\"{}[]()"
- "*Characters that constitute words of type 3.
-More precisely, [ediff-word-3] is a regexp that matches type 3 words.
-See `ediff-forward-word' for more details.")
-
-(defvar ediff-word-4
- (concat "^" ediff-word-1 ediff-word-2 ediff-word-3 ediff-whitespace)
- "*Characters that constitute words of type 4.
-More precisely, [ediff-word-4] is a regexp that matches type 4 words.
-See `ediff-forward-word' for more details.")
-
-;; Split region along word boundaries. Each word will be on its own line.
-;; Output to buffer out-buffer.
-(defun ediff-forward-word ()
- "Move point one word forward.
-There are four types of words, each of which consists entirely of
-characters in `ediff-word-1', `ediff-word-2', `ediff-word-3', or
-`ediff-word-4'. Words are recognized by passing these in turn as the
-argument to `skip-chars-forward'."
- (or (> (skip-chars-forward ediff-word-1) 0)
- (> (skip-chars-forward ediff-word-2) 0)
- (> (skip-chars-forward ediff-word-3) 0)
- (> (skip-chars-forward ediff-word-4) 0)
- ))
-
-(defun ediff-wordify (beg end in-buffer out-buffer &optional control-buf)
- (let (sv-point string)
- (save-excursion
- (set-buffer in-buffer)
- (setq string (buffer-substring beg end))
-
- (set-buffer out-buffer)
- (erase-buffer)
- (insert string)
- (goto-char (point-min))
- (skip-chars-forward ediff-whitespace)
- (delete-region (point-min) (point))
-
- (while (not (eobp))
- ;; eval incontrol buf to let user create local versions for
- ;; different invocations
- (if control-buf
- (funcall
- (ediff-eval-in-buffer control-buf ediff-forward-word-function))
- (funcall ediff-forward-word-function))
- (setq sv-point (point))
- (skip-chars-forward ediff-whitespace)
- (delete-region sv-point (point))
- (insert "\n")))))
-
-;; copy string from BEG END from IN-BUF to OUT-BUF
-(defun ediff-copy-to-buffer (beg end in-buffer out-buffer)
- (let (string)
- (save-excursion
- (set-buffer in-buffer)
- (setq string (buffer-substring beg end))
-
- (set-buffer out-buffer)
- (erase-buffer)
- (insert string)
- (goto-char (point-min)))))
-
-
-;; goto word #n starting at current position in buffer `buf'
-;; For ediff, a word is either a string of a-z,A-Z, incl `-' and `_';
-;; or a string of other non-blanks. A blank is a \n\t\f
-;; If `flag' is non-nil, goto the end of the n-th word.
-(defun ediff-goto-word (n buf &optional flag)
- ;; remember val ediff-forward-word-function has in ctl buf
- (let ((fwd-word-fun ediff-forward-word-function))
- (ediff-eval-in-buffer buf
- (skip-chars-forward ediff-whitespace)
- (while (> n 1)
- (funcall fwd-word-fun)
- (skip-chars-forward ediff-whitespace)
- (setq n (1- n)))
- (if (and flag (> n 0))
- (funcall fwd-word-fun))
- (point))))
-
-
-;;; Local Variables:
-;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
-;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
-;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
-;;; End:
-
-(provide 'ediff-diff)
-
-
-;; ediff-diff.el ends here
diff --git a/lisp/ediff-help.el b/lisp/ediff-help.el
deleted file mode 100644
index 6390b98e407..00000000000
--- a/lisp/ediff-help.el
+++ /dev/null
@@ -1,311 +0,0 @@
-;;; ediff-help.el --- Code related to the contents of Ediff help buffers
-
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Michael Kifer <kifer@cs.sunysb.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(require 'ediff-init)
-
-;; Compiler pacifier start
-(defvar ediff-multiframe)
-(and noninteractive
- (eval-when-compile
- (let ((load-path (cons (expand-file-name ".") load-path)))
- (load-file "ediff-init.el"))))
-;; end pacifier
-
-;; Help messages
-
-(defconst ediff-long-help-message-head
- " Move around | Toggle features | Manipulate
-=====================|===========================|============================="
- "The head of the full help message.")
-(defconst ediff-long-help-message-tail
- "=====================|===========================|=============================
- R -show registry | = -compare regions | M -show session group
- D -diff output | E -browse Ediff manual| G -send bug report
- i -status info | ? -help off | z/q -suspend/quit
--------------------------------------------------------------------------------
-For help on a specific command: Click Button 2 over it; or
- Put the cursor over it and type RET."
- "The tail of the full-help message.")
-
-(defconst ediff-long-help-message-compare3
- "
-p,DEL -previous diff | | -vert/horiz split | xy -copy buf X's region to Y
-n,SPC -next diff | h -hilighting | rx -restore buf X's old diff
- j -jump to diff | @ -auto-refinement | * -refine current region
- gx -goto X's point| | ! -update diff regions
- C-l -recenter | ## -ignore whitespace |
- v/V -scroll up/dn | #f/#h -focus/hide regions | wx -save buf X
- </> -scroll lt/rt | X -read-only in buf X | wd -save diff output
- ~ -rotate buffers| m -wide display |
-"
- "Help message usually used for 3-way comparison.
-Normally, not a user option. See `ediff-help-message' for details.")
-
-(defconst ediff-long-help-message-compare2
- "
-p,DEL -previous diff | | -vert/horiz split |a/b -copy A/B's region to B/A
-n,SPC -next diff | h -hilighting | rx -restore buf X's old diff
- j -jump to diff | @ -auto-refinement | * -refine current region
- gx -goto X's point| | ! -update diff regions
- C-l -recenter | ## -ignore whitespace |
- v/V -scroll up/dn | #f/#h -focus/hide regions | wx -save buf X
- </> -scroll lt/rt | X -read-only in buf X | wd -save diff output
- ~ -swap variants | m -wide display |
-"
- "Help message usually used for 2-way comparison.
-Normally, not a user option. See `ediff-help-message' for details.")
-
-(defconst ediff-long-help-message-narrow2
- "
-p,DEL -previous diff | | -vert/horiz split |a/b -copy A/B's region to B/A
-n,SPC -next diff | h -hilighting | rx -restore buf X's old diff
- j -jump to diff | @ -auto-refinement | * -refine current region
- gx -goto X's point| % -narrow/widen buffs | ! -update diff regions
- C-l -recenter | ## -ignore whitespace |
- v/V -scroll up/dn | #f/#h -focus/hide regions | wx -save buf X
- </> -scroll lt/rt | X -read-only in buf X | wd -save diff output
- ~ -swap variants | m -wide display |
-"
- "Help message when comparing windows or regions line-by-line.
-Normally, not a user option. See `ediff-help-message' for details.")
-
-(defconst ediff-long-help-message-word-mode
- "
-p,DEL -previous diff | | -vert/horiz split | xy -copy buf X's region to Y
-n,SPC -next diff | h -hilighting | rx -restore buf X's old diff
- j -jump to diff | |
- gx -goto X's point| % -narrow/widen buffs | ! -recompute diffs
- C-l -recenter | |
- v/V -scroll up/dn | #f/#h -focus/hide regions | wx -save buf X
- </> -scroll lt/rt | X -read-only in buf X | wd -save diff output
- ~ -swap variants | m -wide display |
-"
- "Help message when comparing windows or regions word-by-word.
-Normally, not a user option. See `ediff-help-message' for details.")
-
-(defconst ediff-long-help-message-merge
- "
-p,DEL -previous diff | | -vert/horiz split | x -copy buf X's region to C
-n,SPC -next diff | h -hilighting | r -restore buf C's old diff
- j -jump to diff | @ -auto-refinement | * -refine current region
- gx -goto X's point| ## -ignore whitespace | ! -update diff regions
- C-l -recenter | #f/#h -focus/hide regions | + -combine diff regions
- v/V -scroll up/dn | X -read-only in buf X | wx -save buf X
- </> -scroll lt/rt | m -wide display | wd -save diff output
- ~ -swap variants | s -shrink window C | / -show ancestor buff
- | $ -show clashes only | & -merge w/new default
-"
- "Help message during merging.
-Normally, not a user option. See `ediff-help-message' for details.")
-
-;; The actual long help message.
-(ediff-defvar-local ediff-long-help-message ""
- "Normally, not a user option. See `ediff-help-message' for details.")
-
-(defconst ediff-brief-message-string
- "? -quick help "
- "Contents of the brief help message.")
-;; The actual brief help message
-(ediff-defvar-local ediff-brief-help-message ""
- "Normally, not a user option. See `ediff-help-message' for details.")
-
-(ediff-defvar-local ediff-brief-help-message-function nil
- "The brief help message that the user can customize.
-If the user sets this to a parameter-less function, Ediff will use it to
-produce the brief help message. This function must return a string.")
-(ediff-defvar-local ediff-long-help-message-function nil
- "The long help message that the user can customize.
-See `ediff-brief-help-message-function' for more.")
-
-(defvar ediff-use-long-help-message nil
- "*If t, Ediff displays a long help message. Short help message otherwise.")
-
-;; The actual help message.
-(ediff-defvar-local ediff-help-message ""
- "The actual help message.
-Normally, the user shouldn't touch this. However, if you want Ediff to
-start up with different help messages for different jobs, you can change
-the value of this variable and the variables `ediff-help-message-*' in
-`ediff-startup-hook'.")
-
-
-;; the keymap that defines clicks over the quick help regions
-(defvar ediff-help-region-map (make-sparse-keymap))
-
-(define-key
- ediff-help-region-map
- (if ediff-emacs-p [mouse-2] [button2])
- 'ediff-help-for-quick-help)
-
-;; runs in the control buffer
-(defun ediff-set-help-overlays ()
- (goto-char (point-min))
- (let (overl beg end cmd)
- (while (re-search-forward " *\\([^ \t\n|]+\\||\\) +-[^|\n]+" nil 'noerror)
- (setq beg (match-beginning 0)
- end (match-end 0)
- cmd (buffer-substring (match-beginning 1) (match-end 1)))
- (setq overl (ediff-make-overlay beg end))
- (if ediff-emacs-p
- (ediff-overlay-put overl 'mouse-face 'highlight)
- (ediff-overlay-put overl 'highlight t))
- (ediff-overlay-put overl 'ediff-help-info cmd))))
-
-
-(defun ediff-help-for-quick-help ()
- "Explain Ediff commands in more detail."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (let ((ctl-buf (current-buffer))
- (pos (ediff-event-point last-command-event))
- overl cmd)
-
- (if ediff-xemacs-p
- (setq overl (extent-at pos (current-buffer) 'ediff-help-info)
- cmd (ediff-overlay-get overl 'ediff-help-info))
- (setq cmd (car (mapcar (function (lambda (elt)
- (overlay-get elt 'ediff-help-info)))
- (overlays-at pos)))))
-
- (if (not (stringp cmd))
- (error "Hmm... I don't see an Ediff command around here..."))
-
- (ediff-documentation "Quick Help Commands")
-
- (let (case-fold-search)
- (cond ((string= cmd "?") (re-search-forward "^`\\?'"))
- ((string= cmd "G") (re-search-forward "^`G'"))
- ((string= cmd "E") (re-search-forward "^`E'"))
- ((string= cmd "wd") (re-search-forward "^`wd'"))
- ((string= cmd "wx") (re-search-forward "^`wa'"))
- ((string= cmd "a/b") (re-search-forward "^`a'"))
- ((string= cmd "x") (re-search-forward "^`a'"))
- ((string= cmd "xy") (re-search-forward "^`ab'"))
- ((string= cmd "p,DEL") (re-search-forward "^`p'"))
- ((string= cmd "n,SPC") (re-search-forward "^`n'"))
- ((string= cmd "j") (re-search-forward "^`j'"))
- ((string= cmd "gx") (re-search-forward "^`ga'"))
- ((string= cmd "!") (re-search-forward "^`!'"))
- ((string= cmd "*") (re-search-forward "^`\\*'"))
- ((string= cmd "m") (re-search-forward "^`m'"))
- ((string= cmd "|") (re-search-forward "^`|'"))
- ((string= cmd "@") (re-search-forward "^`@'"))
- ((string= cmd "h") (re-search-forward "^`h'"))
- ((string= cmd "r") (re-search-forward "^`r'"))
- ((string= cmd "rx") (re-search-forward "^`ra'"))
- ((string= cmd "##") (re-search-forward "^`##'"))
- ((string= cmd "#f/#h") (re-search-forward "^`#f'"))
- ((string= cmd "X") (re-search-forward "^`A'"))
- ((string= cmd "v/V") (re-search-forward "^`v'"))
- ((string= cmd "</>") (re-search-forward "^`<'"))
- ((string= cmd "~") (re-search-forward "^`~'"))
- ((string= cmd "i") (re-search-forward "^`i'"))
- ((string= cmd "D") (re-search-forward "^`D'"))
- ((string= cmd "R") (re-search-forward "^`R'"))
- ((string= cmd "M") (re-search-forward "^`M'"))
- ((string= cmd "z/q") (re-search-forward "^`z'"))
- ((string= cmd "%") (re-search-forward "^`%'"))
- ((string= cmd "C-l") (re-search-forward "^`C-l'"))
- ((string= cmd "$") (re-search-forward "^`\\$'"))
- ((string= cmd "/") (re-search-forward "^`/'"))
- ((string= cmd "&") (re-search-forward "^`&'"))
- ((string= cmd "s") (re-search-forward "^`s'"))
- ((string= cmd "+") (re-search-forward "^`\\+'"))
- ((string= cmd "=") (re-search-forward "^`='"))
- (t (error "Undocumented command! Type `G' in Ediff Control Panel to drop a note to the Ediff maintainer")))
- ) ; let case-fold-search
- ))
-
-
-;; assuming we are in control window, calculate length of the first line in
-;; help message
-(defun ediff-help-message-line-length ()
- (save-excursion
- (goto-char (point-min))
- (if ediff-use-long-help-message
- (next-line 1))
- (end-of-line)
- (current-column)))
-
-
-(defun ediff-indent-help-message ()
- (let* ((shift (/ (max 0 (- (window-width (selected-window))
- (ediff-help-message-line-length)))
- 2))
- (str (make-string shift ?\ )))
- (save-excursion
- (goto-char (point-min))
- (while (< (point) (point-max))
- (insert str)
- (beginning-of-line)
- (forward-line 1)))))
-
-
-;; compose the help message as a string
-(defun ediff-set-help-message ()
- (setq ediff-long-help-message
- (cond ((and ediff-long-help-message-function
- (or (symbolp ediff-long-help-message-function)
- (consp ediff-long-help-message-function)))
- (funcall ediff-long-help-message-function))
- (ediff-word-mode
- (concat ediff-long-help-message-head
- ediff-long-help-message-word-mode
- ediff-long-help-message-tail))
- (ediff-narrow-job
- (concat ediff-long-help-message-head
- ediff-long-help-message-narrow2
- ediff-long-help-message-tail))
- (ediff-merge-job
- (concat ediff-long-help-message-head
- ediff-long-help-message-merge
- ediff-long-help-message-tail))
- (ediff-diff3-job
- (concat ediff-long-help-message-head
- ediff-long-help-message-compare3
- ediff-long-help-message-tail))
- (t
- (concat ediff-long-help-message-head
- ediff-long-help-message-compare2
- ediff-long-help-message-tail))))
- (setq ediff-brief-help-message
- (cond ((and ediff-brief-help-message-function
- (or (symbolp ediff-brief-help-message-function)
- (consp ediff-brief-help-message-function)))
- (funcall ediff-brief-help-message-function))
- ((stringp ediff-brief-help-message-function)
- ediff-brief-help-message-function)
- ((ediff-multiframe-setup-p) ediff-brief-message-string)
- (t ; long brief msg, not multiframe --- put in the middle
- ediff-brief-message-string)
- ))
- (setq ediff-help-message (if ediff-use-long-help-message
- ediff-long-help-message
- ediff-brief-help-message))
- (run-hooks 'ediff-display-help-hook))
-
-(provide 'ediff-help)
-
-;;; ediff-help.el ends here
diff --git a/lisp/ediff-hook.el b/lisp/ediff-hook.el
deleted file mode 100644
index 25c5afc1d8b..00000000000
--- a/lisp/ediff-hook.el
+++ /dev/null
@@ -1,352 +0,0 @@
-;;; ediff-hook.el --- setup for Ediff's menus and autoloads
-
-;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Michael Kifer <kifer@cs.sunysb.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;;; These must be placed in menu-bar.el in Emacs
-;;
-;; (define-key menu-bar-tools-menu [epatch]
-;; '("Apply Patch" . menu-bar-epatch-menu))
-;; (define-key menu-bar-tools-menu [ediff-merge]
-;; '("Merge" . menu-bar-ediff-merge-menu))
-;; (define-key menu-bar-tools-menu [ediff]
-;; '("Compare" . menu-bar-ediff-menu))
-
-;; Compiler pacifier
-(defvar ediff-menu)
-(defvar ediff-merge-menu)
-(defvar epatch-menu)
-;; end pacifier
-
-
-(defun ediff-xemacs-init-menus ()
- (if (featurep 'menubar)
- (progn
- (add-menu-button
- '("Tools")
- ["Use separate frame for Ediff control buffer"
- ediff-toggle-multiframe
- :style toggle
- :selected (eq ediff-window-setup-function 'ediff-setup-windows-multiframe)]
- "00-Browser...")
- (add-menu-button
- '("Tools")
- ["Use a toolbar with Ediff control buffer"
- ediff-menu-toggle-use-toolbar
- :style toggle
- :selected (ediff-use-toolbar-p)]
- "00-Browser...")
- (add-submenu
- '("Tools") ediff-menu "OO-Browser...")
- (add-submenu
- '("Tools") ediff-merge-menu "OO-Browser...")
- (add-submenu
- '("Tools") epatch-menu "OO-Browser...")
- (add-menu-button
- '("Tools")
- ["-------" nil nil] "OO-Browser...")
- )))
-
-
-;; explicit string-match is needed: ediff-xemacs-p is not defined at build time
-(cond ((string-match "XEmacs" emacs-version)
- (defvar ediff-menu
- '("Compare"
- ["Two Files..." ediff-files t]
- ["Two Buffers..." ediff-buffers t]
- ["Three Files..." ediff-files3 t]
- ["Three Buffers..." ediff-buffers3 t]
- "---"
- ["Two Directories..." ediff-directories t]
- ["Three Directories..." ediff-directories3 t]
- "---"
- ["File with Revision..." ediff-revision t]
- ["Directory Revisions..." ediff-directory-revisions t]
- "---"
- ["Windows Word-by-word..." ediff-windows-wordwise t]
- ["Windows Line-by-line..." ediff-windows-linewise t]
- "---"
- ["Regions Word-by-word..." ediff-regions-wordwise t]
- ["Regions Line-by-line..." ediff-regions-linewise t]
- "---"
- ["List Ediff Sessions..." ediff-show-registry t]
- ["Ediff Manual..." ediff-documentation t]
- ))
- (defvar ediff-merge-menu
- '("Merge"
- ["Files..." ediff-merge-files t]
- ["Files with Ancestor..." ediff-merge-files-with-ancestor t]
- ["Buffers..." ediff-merge-buffers t]
- ["Buffers with Ancestor..."
- ediff-merge-buffers-with-ancestor t]
- "---"
- ["Directories..." ediff-merge-directories t]
- ["Directories with Ancestor..."
- ediff-merge-directories-with-ancestor t]
- "---"
- ["Revisions..." ediff-merge-revisions t]
- ["Revisions with Ancestor..."
- ediff-merge-revisions-with-ancestor t]
- ["Directory Revisions..." ediff-merge-directory-revisions t]
- ["Directory Revisions with Ancestor..."
- ediff-merge-directory-revisions-with-ancestor t]
- "---"
- ["List Ediff Sessions..." ediff-show-registry t]
- ["Ediff Manual..." ediff-documentation t]
- ))
- (defvar epatch-menu
- '("Apply Patch"
- ["To a file..." ediff-patch-file t]
- ["To a buffer..." ediff-patch-buffer t]
- "---"
- ["List Ediff Sessions..." ediff-show-registry t]
- ["Ediff Manual..." ediff-documentation t]
- ))
-
- ;; put these menus before Object-Oriented-Browser in Tools menu
- (add-hook 'before-init-hook 'ediff-xemacs-init-menus)
- (if (not purify-flag)
- (ediff-xemacs-init-menus))
- )
-
- ;; Emacs--only if menu-bar is loaded
- ((featurep 'menu-bar)
- ;; initialize menu bar keymaps
- (defvar menu-bar-epatch-menu (make-sparse-keymap "Apply Patch"))
- (fset 'menu-bar-epatch-menu (symbol-value 'menu-bar-epatch-menu))
- (defvar menu-bar-ediff-merge-menu (make-sparse-keymap "Merge"))
- (fset 'menu-bar-ediff-merge-menu
- (symbol-value 'menu-bar-ediff-merge-menu))
- (defvar menu-bar-ediff-menu (make-sparse-keymap "Compare"))
- (fset 'menu-bar-ediff-menu (symbol-value 'menu-bar-ediff-menu))
-
- ;; define ediff-menu
- (define-key menu-bar-ediff-menu [ediff-doc]
- '("Ediff Manual..." . ediff-documentation))
- (define-key menu-bar-ediff-menu [emultiframe]
- '("Toggle separate control buffer frame..."
- . ediff-toggle-multiframe))
- (define-key menu-bar-ediff-menu [eregistry]
- '("List Ediff Sessions..." . ediff-show-registry))
- (define-key menu-bar-ediff-menu [separator-ediff-manual] '("--"))
- (define-key menu-bar-ediff-menu [window]
- '("This Window and Next Window" . compare-windows))
- (define-key menu-bar-ediff-menu [ediff-windows-linewise]
- '("Windows Line-by-line..." . ediff-windows-linewise))
- (define-key menu-bar-ediff-menu [ediff-windows-wordwise]
- '("Windows Word-by-word..." . ediff-windows-wordwise))
- (define-key menu-bar-ediff-menu [separator-ediff-windows] '("--"))
- (define-key menu-bar-ediff-menu [ediff-regions-linewise]
- '("Regions Line-by-line..." . ediff-regions-linewise))
- (define-key menu-bar-ediff-menu [ediff-regions-wordwise]
- '("Regions Word-by-word..." . ediff-regions-wordwise))
- (define-key menu-bar-ediff-menu [separator-ediff-regions] '("--"))
- (define-key menu-bar-ediff-menu [ediff-dir-revision]
- '("Directory Revisions..." . ediff-directory-revisions))
- (define-key menu-bar-ediff-menu [ediff-revision]
- '("File with Revision..." . ediff-revision))
- (define-key menu-bar-ediff-menu [separator-ediff-directories] '("--"))
- (define-key menu-bar-ediff-menu [ediff-directories3]
- '("Three Directories..." . ediff-directories3))
- (define-key menu-bar-ediff-menu [ediff-directories]
- '("Two Directories..." . ediff-directories))
- (define-key menu-bar-ediff-menu [separator-ediff-files] '("--"))
- (define-key menu-bar-ediff-menu [ediff-buffers3]
- '("Three Buffers..." . ediff-buffers3))
- (define-key menu-bar-ediff-menu [ediff-files3]
- '("Three Files..." . ediff-files3))
- (define-key menu-bar-ediff-menu [ediff-buffers]
- '("Two Buffers..." . ediff-buffers))
- (define-key menu-bar-ediff-menu [ediff-files]
- '("Two Files..." . ediff-files))
-
- ;; define merge menu
- (define-key menu-bar-ediff-merge-menu [ediff-doc2]
- '("Ediff Manual..." . ediff-documentation))
- (define-key menu-bar-ediff-merge-menu [emultiframe2]
- '("Toggle separate control buffer frame..."
- . ediff-toggle-multiframe))
- (define-key menu-bar-ediff-merge-menu [eregistry2]
- '("List Ediff Sessions..." . ediff-show-registry))
- (define-key
- menu-bar-ediff-merge-menu [separator-ediff-merge-manual] '("--"))
- (define-key
- menu-bar-ediff-merge-menu [ediff-merge-dir-revisions-with-ancestor]
- '("Directory Revisions with Ancestor..."
- . ediff-merge-directory-revisions-with-ancestor))
- (define-key
- menu-bar-ediff-merge-menu [ediff-merge-dir-revisions]
- '("Directory Revisions..." . ediff-merge-directory-revisions))
- (define-key
- menu-bar-ediff-merge-menu [ediff-merge-revisions-with-ancestor]
- '("Revisions with Ancestor..."
- . ediff-merge-revisions-with-ancestor))
- (define-key menu-bar-ediff-merge-menu [ediff-merge-revisions]
- '("Revisions..." . ediff-merge-revisions))
- (define-key menu-bar-ediff-merge-menu [separator-ediff-merge] '("--"))
- (define-key
- menu-bar-ediff-merge-menu [ediff-merge-directories-with-ancestor]
- '("Directories with Ancestor..."
- . ediff-merge-directories-with-ancestor))
- (define-key menu-bar-ediff-merge-menu [ediff-merge-directories]
- '("Directories..." . ediff-merge-directories))
- (define-key
- menu-bar-ediff-merge-menu [separator-ediff-merge-dirs] '("--"))
- (define-key
- menu-bar-ediff-merge-menu [ediff-merge-buffers-with-ancestor]
- '("Buffers with Ancestor..." . ediff-merge-buffers-with-ancestor))
- (define-key menu-bar-ediff-merge-menu [ediff-merge-buffers]
- '("Buffers..." . ediff-merge-buffers))
- (define-key menu-bar-ediff-merge-menu [ediff-merge-files-with-ancestor]
- '("Files with Ancestor..." . ediff-merge-files-with-ancestor))
- (define-key menu-bar-ediff-merge-menu [ediff-merge-files]
- '("Files..." . ediff-merge-files))
-
- ;; define epatch menu
- (define-key menu-bar-epatch-menu [ediff-doc3]
- '("Ediff Manual..." . ediff-documentation))
- (define-key menu-bar-epatch-menu [emultiframe3]
- '("Toggle separate control buffer frame..."
- . ediff-toggle-multiframe))
- (define-key menu-bar-epatch-menu [eregistry3]
- '("List Ediff Sessions..." . ediff-show-registry))
- (define-key menu-bar-epatch-menu [separator-epatch] '("--"))
- (define-key menu-bar-epatch-menu [ediff-patch-buffer]
- '("To a Buffer..." . ediff-patch-buffer))
- (define-key menu-bar-epatch-menu [ediff-patch-file]
- '("To a File..." . ediff-patch-file)))
-
- ) ; cond
-
-;; arrange for autoloads
-(if purify-flag
- () ; if dumping, autoloads are set up in loaddefs.el
- ;; if the user decides to load this file, set up autoloads
- ;; compare files and buffers
- (autoload 'ediff "ediff" "Compare two files" t)
- (autoload 'ediff-files "ediff" "Compare two files" t)
- (autoload 'ediff-buffers "ediff" "Compare two bufers" t)
- (autoload 'ebuffers "ediff" "Compare two bufers" t)
- (autoload 'ediff3 "ediff" "Compare three files" t)
- (autoload 'ediff-files3 "ediff" "Compare three files" t)
- (autoload 'ediff-buffers3 "ediff" "Compare three bufers" t)
- (autoload 'ebuffers3 "ediff" "Compare three bufers" t)
-
- (autoload 'ediff-revision "ediff" "Compare versions of a file" t)
-
- ;; compare regions and windows
- (autoload 'ediff-windows-wordwise
- "ediff" "Compare two windows word-by-word." t)
- (autoload 'ediff-regions-wordwise
- "ediff" "Compare two regions word-by-word." t)
- (autoload 'ediff-windows-linewise
- "ediff" "Compare two windows line-by-line." t)
- (autoload 'ediff-regions-linewise
- "ediff" "Compare two regions line-by-line." t)
-
- ;; patch
- (autoload 'ediff-patch-file "ediff" "Patch a file." t)
- (autoload 'epatch "ediff" "Patch a file." t)
- (autoload 'ediff-patch-buffer "ediff" "Patch a buffer.")
- (autoload 'epatch-buffer "ediff" "Patch a buffer." t)
-
- ;; merge
- (autoload 'ediff-merge "ediff" "Merge two files." t)
- (autoload 'ediff-merge-files "ediff" "Merge two files." t)
- (autoload 'ediff-merge-files-with-ancestor
- "ediff" "Merge two files using a third file as an ancestor." t)
- (autoload 'ediff-merge-buffers "ediff" "Merge two buffers." t)
- (autoload 'ediff-merge-buffers-with-ancestor
- "ediff" "Merge two buffers using a third buffer as an ancestor." t)
-
- (autoload 'ediff-merge-revisions "ediff" "Merge two versions of a file." t)
- (autoload 'ediff-merge-revisions-with-ancestor
- "ediff" "Merge two versions of a file." t)
-
- ;; compare directories
- (autoload 'edirs "ediff" "Compare files in two directories." t)
- (autoload 'ediff-directories "ediff" "Compare files in two directories." t)
- (autoload 'edirs3 "ediff" "Compare files in three directories." t)
- (autoload
- 'ediff-directories3 "ediff" "Compare files in three directories." t)
-
- (autoload 'edir-revisions
- "ediff" "Compare two versions of a file." t)
- (autoload 'ediff-directory-revisions
- "ediff" "Compare two versions of a file." t)
-
- ;; merge directories
- (autoload 'edirs-merge "ediff" "Merge files in two directories." t)
- (autoload 'ediff-merge-directories
- "ediff" "Merge files in two directories." t)
- (autoload 'edirs-merge-with-ancestor
- "ediff"
- "Merge files in two directories using files in a third dir as ancestors."
- t)
- (autoload 'ediff-merge-directories-with-ancestor
- "ediff"
- "Merge files in two directories using files in a third dir as ancestors."
- t)
-
- (autoload 'edir-merge-revisions
- "ediff" "Merge versions of files in a directory." t)
- (autoload 'ediff-merge-directory-revisions
- "ediff" "Merge versions of files in a directory." t)
- (autoload 'ediff-merge-directory-revisions-with-ancestor
- "ediff"
- "Merge versions of files in a directory using other versions as ancestors."
- t)
- (autoload 'edir-merge-revisions-with-ancestor
- "ediff"
- "Merge versions of files in a directory using other versions as ancestors."
- t)
-
- ;; misc
- (autoload 'ediff-show-registry
- "ediff-mult"
- "Display the registry of active Ediff sessions."
- t)
- (autoload 'ediff-documentation
- "ediff"
- "Display Ediff's manual."
- t)
- (autoload 'ediff-version
- "ediff"
- "Show Ediff's version and last modification date."
- t)
- (autoload 'ediff-toggle-multiframe
- "ediff-util"
- "Toggle the use of separate frame for Ediff control buffer."
- t)
- (if (string-match "XEmacs" emacs-version)
- (autoload 'ediff-toggle-use-toolbar
- "ediff-tbar"
- "Toggle the use of Ediff toolbar."
- t))
- ) ; if purify-flag
-
-
-(provide 'ediff-hook)
-
-
-;;; ediff-hook.el ends here
diff --git a/lisp/ediff-init.el b/lisp/ediff-init.el
deleted file mode 100644
index 3da02d7242a..00000000000
--- a/lisp/ediff-init.el
+++ /dev/null
@@ -1,1612 +0,0 @@
-;;; ediff-init.el --- Macros, variables, and defsubsts used by Ediff
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Michael Kifer <kifer@cs.sunysb.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;; Start compiler pacifier
-(defvar ediff-metajob-name)
-(defvar ediff-meta-buffer)
-(defvar pm-color-alist)
-(defvar ediff-grab-mouse)
-(defvar ediff-mouse-pixel-position)
-(defvar ediff-mouse-pixel-threshold)
-(defvar ediff-whitespace)
-(defvar ediff-multiframe)
-;; end pacifier
-
-;; Is it XEmacs?
-(defconst ediff-xemacs-p (string-match "XEmacs" emacs-version))
-;; Is it Emacs?
-(defconst ediff-emacs-p (not ediff-xemacs-p))
-
-(defvar ediff-force-faces nil
- "If t, Ediff will think that it is running on a display that supports faces.
-This is provided as a temporary relief for users of face-capable displays
-that Ediff doesn't know about.")
-
-;; Are we running as a window application or on a TTY?
-(defsubst ediff-device-type ()
- (if ediff-emacs-p
- window-system
- (device-type (selected-device))))
-
-;; in XEmacs: device-type is tty on tty and stream in batch.
-(defun ediff-window-display-p ()
- (and (ediff-device-type) (not (memq (ediff-device-type) '(tty pc stream)))))
-
-;; test if supports faces
-;; ediff-force-faces is for those devices that support faces, but we don't know
-;; this yet
-(defun ediff-has-face-support-p ()
- (cond ((ediff-window-display-p))
- (ediff-force-faces)
- (ediff-emacs-p (memq (ediff-device-type) '(pc)))
- (ediff-xemacs-p (memq (ediff-device-type) '(tty pc)))))
-
-
-;; Defines SYMBOL as an advertised local variable.
-;; Performs a defvar, then executes `make-variable-buffer-local' on
-;; the variable. Also sets the `permanent-local' property,
-;; so that `kill-all-local-variables' (called by major-mode setting
-;; commands) won't destroy Ediff control variables.
-;;
-;; Plagiarised from `emerge-defvar-local' for XEmacs.
-(defmacro ediff-defvar-local (var value doc)
- (` (progn
- (defvar (, var) (, value) (, doc))
- (make-variable-buffer-local '(, var))
- (put '(, var) 'permanent-local t))))
-
-
-
-;; Variables that control each Ediff session---local to the control buffer.
-
-;; Mode variables
-;; The buffer in which the A variant is stored.
-(ediff-defvar-local ediff-buffer-A nil "")
-;; The buffer in which the B variant is stored.
-(ediff-defvar-local ediff-buffer-B nil "")
-;; The buffer in which the C variant is stored.
-(ediff-defvar-local ediff-buffer-C nil "")
-;; Ancestor buffer
-(ediff-defvar-local ediff-ancestor-buffer nil "")
-;; The control buffer of ediff.
-(ediff-defvar-local ediff-control-buffer nil "")
-
-;;; Macros
-(defmacro ediff-odd-p (arg)
- (` (eq (logand (, arg) 1) 1)))
-
-(defmacro ediff-buffer-live-p (buf)
- (` (and (, buf) (get-buffer (, buf)) (buffer-name (get-buffer (, buf))))))
-
-(defmacro ediff-get-buffer (arg)
- (` (cond ((eq (, arg) 'A) ediff-buffer-A)
- ((eq (, arg) 'B) ediff-buffer-B)
- ((eq (, arg) 'C) ediff-buffer-C)
- ((eq (, arg) 'Ancestor) ediff-ancestor-buffer)
- )
- ))
-
-(defmacro ediff-get-value-according-to-buffer-type (buf-type list)
- (` (cond ((eq (, buf-type) 'A) (nth 0 (, list)))
- ((eq (, buf-type) 'B) (nth 1 (, list)))
- ((eq (, buf-type) 'C) (nth 2 (, list))))))
-
-(defmacro ediff-char-to-buftype (arg)
- (` (cond ((memq (, arg) '(?a ?A)) 'A)
- ((memq (, arg) '(?b ?B)) 'B)
- ((memq (, arg) '(?c ?C)) 'C)
- )
- ))
-
-(defmacro ediff-get-difference (n buf-type)
- (` (aref
- (symbol-value
- (intern (format "ediff-difference-vector-%S" (, buf-type)))) (, n))))
-
-;; tell if it has been previously determined that the region has
-;; no diffs other than the white space and newlines
-;; The argument, N, is the diff region number used by Ediff to index the
-;; diff vector. It is 1 less than the number seen by the user.
-;;
-;; A difference vector has the form:
-;; [diff diff diff ...]
-;; where each diff has the form:
-;; [overlay fine-diff-vector no-fine-diffs-flag]
-;; fine-diff-vector is a vector [fine-diff fine-diff fine-diff ...]
-(defmacro ediff-no-fine-diffs-p (n)
- (` (aref (ediff-get-difference (, n) 'A) 2)))
-
-(defmacro ediff-get-diff-overlay-from-diff-record (diff-rec)
- (` (aref (, diff-rec) 0)))
-
-(defmacro ediff-get-diff-overlay (n buf-type)
- (` (ediff-get-diff-overlay-from-diff-record
- (ediff-get-difference (, n) (, buf-type)))))
-
-(defmacro ediff-get-fine-diff-vector-from-diff-record (diff-rec)
- (` (aref (, diff-rec) 1)))
-
-(defmacro ediff-set-fine-diff-vector (n buf-type fine-vec)
- (` (aset (ediff-get-difference (, n) (, buf-type)) 1 (, fine-vec))))
-
-(defmacro ediff-get-state-of-diff (n buf-type)
- (` (if (ediff-buffer-live-p ediff-buffer-C)
- (aref (ediff-get-difference (, n) (, buf-type)) 3))))
-(defmacro ediff-set-state-of-diff (n buf-type val)
- (` (aset (ediff-get-difference (, n) (, buf-type)) 3 (, val))))
-(defmacro ediff-get-state-of-merge (n)
- (` (if ediff-state-of-merge
- (aref (aref ediff-state-of-merge (, n)) 0))))
-(defmacro ediff-get-state-of-ancestor (n)
- (` (if ediff-state-of-merge
- (aref (aref ediff-state-of-merge (, n)) 1))))
-(defmacro ediff-set-state-of-merge (n val)
- (` (if ediff-state-of-merge
- (aset (aref ediff-state-of-merge (, n)) 0 (, val)))))
-
-;; if flag is t, puts a mark on diff region saying that
-;; the differences are in white space only. If flag is nil,
-;; the region is marked as essential (i.e., differences are
-;; not just in the white space and newlines.)
-(defmacro ediff-mark-diff-as-space-only (n flag)
- (` (aset (ediff-get-difference (, n) 'A) 2 (, flag))))
-
-(defmacro ediff-get-fine-diff-vector (n buf-type)
- (` (ediff-get-fine-diff-vector-from-diff-record
- (ediff-get-difference (, n) (, buf-type)))))
-
-;; Macro to switch to BUFFER, evaluate FORMS, returns to original buffer.
-;; Differs from `save-excursion' in that it doesn't save the point and mark.
-;; This is essentially `emerge-eval-in-buffer' with the test for live buffers."
-(defmacro ediff-eval-in-buffer (buffer &rest forms)
- (` (let ((StartBuffer (current-buffer)))
- (if (ediff-buffer-live-p (, buffer))
- (unwind-protect
- (progn
- (set-buffer (, buffer))
- (,@ forms))
- (set-buffer StartBuffer))
- (or (eq this-command 'ediff-quit)
- (error ediff-KILLED-VITAL-BUFFER))
- ))))
-
-
-(defsubst ediff-multiframe-setup-p ()
- (and (ediff-window-display-p) ediff-multiframe))
-
-(defmacro ediff-narrow-control-frame-p ()
- (` (and (ediff-multiframe-setup-p)
- (equal ediff-help-message ediff-brief-message-string))))
-
-(defmacro ediff-3way-comparison-job ()
- (` (memq
- ediff-job-name
- '(ediff-files3 ediff-buffers3))))
-(ediff-defvar-local ediff-3way-comparison-job nil "")
-
-(defmacro ediff-merge-job ()
- (` (memq
- ediff-job-name
- '(ediff-merge-files
- ediff-merge-buffers
- ediff-merge-files-with-ancestor
- ediff-merge-buffers-with-ancestor
- ediff-merge-revisions
- ediff-merge-revisions-with-ancestor))))
-(ediff-defvar-local ediff-merge-job nil "")
-
-(defmacro ediff-merge-with-ancestor-job ()
- (` (memq
- ediff-job-name
- '(ediff-merge-files-with-ancestor
- ediff-merge-buffers-with-ancestor
- ediff-merge-revisions-with-ancestor))))
-(ediff-defvar-local ediff-merge-with-ancestor-job nil "")
-
-(defmacro ediff-3way-job ()
- (` (or ediff-3way-comparison-job ediff-merge-job)))
-(ediff-defvar-local ediff-3way-job nil "")
-
-;; A diff3 job is like a 3way job, but ediff-merge doesn't require the use
-;; of diff3.
-(defmacro ediff-diff3-job ()
- (` (or ediff-3way-comparison-job
- ediff-merge-with-ancestor-job)))
-(ediff-defvar-local ediff-diff3-job nil "")
-
-(defmacro ediff-windows-job ()
- (` (memq ediff-job-name '(ediff-windows-wordwise ediff-windows-linewise))))
-(ediff-defvar-local ediff-windows-job nil "")
-
-(defmacro ediff-word-mode-job ()
- (` (memq ediff-job-name '(ediff-windows-wordwise ediff-regions-wordwise))))
-(ediff-defvar-local ediff-word-mode-job nil "")
-
-(defmacro ediff-narrow-job ()
- (` (memq ediff-job-name '(ediff-windows-wordwise
- ediff-regions-wordwise
- ediff-windows-linewise
- ediff-regions-linewise))))
-(ediff-defvar-local ediff-narrow-job nil "")
-
-;; Note: ediff-merge-directory-revisions-with-ancestor is not treated as an
-;; ancestor metajob, since it behaves differently.
-(defsubst ediff-ancestor-metajob (&optional metajob)
- (memq (or metajob ediff-metajob-name)
- '(ediff-merge-directories-with-ancestor
- ediff-merge-filegroups-with-ancestor)))
-(defsubst ediff-revision-metajob (&optional metajob)
- (memq (or metajob ediff-metajob-name)
- '(ediff-directory-revisions
- ediff-merge-directory-revisions
- ediff-merge-directory-revisions-with-ancestor)))
-(defsubst ediff-patch-metajob (&optional metajob)
- (memq (or metajob ediff-metajob-name)
- '(ediff-multifile-patch)))
-;; metajob involving only one group of files, such as multipatch or directory
-;; revision
-(defsubst ediff-one-filegroup-metajob (&optional metajob)
- (or (ediff-revision-metajob metajob)
- (ediff-patch-metajob metajob)
- ;; add more here
- ))
-(defsubst ediff-collect-diffs-metajob (&optional metajob)
- (memq (or metajob ediff-metajob-name)
- '(ediff-directories
- ediff-directory-revisions
- ediff-merge-directories
- ediff-merge-directories-with-ancestor
- ediff-merge-directory-revisions
- ediff-merge-directory-revisions-with-ancestor
- ;; add more here
- )))
-(defsubst ediff-merge-metajob (&optional metajob)
- (memq (or metajob ediff-metajob-name)
- '(ediff-merge-directories
- ediff-merge-directories-with-ancestor
- ediff-merge-directory-revisions
- ediff-merge-directory-revisions-with-ancestor
- ediff-merge-filegroups-with-ancestor
- ;; add more here
- )))
-
-(defsubst ediff-metajob3 (&optional metajob)
- (memq (or metajob ediff-metajob-name)
- '(ediff-merge-directories-with-ancestor
- ediff-merge-filegroups-with-ancestor
- ediff-directories3
- ediff-filegroups3)))
-(defsubst ediff-comparison-metajob3 (&optional metajob)
- (memq (or metajob ediff-metajob-name)
- '(ediff-directories3 ediff-filegroups3)))
-
-;; with no argument, checks if we are in ediff-control-buffer
-;; with argument, checks if we are in ediff-meta-buffer
-(defun ediff-in-control-buffer-p (&optional meta-buf-p)
- (and (boundp 'ediff-control-buffer)
- (eq (if meta-buf-p ediff-meta-buffer ediff-control-buffer)
- (current-buffer))))
-
-(defsubst ediff-barf-if-not-control-buffer (&optional meta-buf-p)
- (or (ediff-in-control-buffer-p meta-buf-p)
- (error "%S: This command runs in Ediff Control Buffer only!"
- this-command)))
-
-;; Hook variables
-
-(defvar ediff-before-setup-windows-hook nil
- "*Hooks to run before Ediff sets its window configuration.
-This can be used to save the previous window config, which can be restored
-on ediff-quit or ediff-suspend.")
-(defvar ediff-after-setup-windows-hook nil
- "*Hooks to run after Ediff sets its window configuration.
-This can be used to set up control window or icon in a desired place.")
-(defvar ediff-before-setup-control-frame-hook nil
- "*Hooks run before setting up the frame to display Ediff Control Panel.
-Can be used to change control frame parameters to position it where it
-is desirable.")
-(defvar ediff-after-setup-control-frame-hook nil
- "*Hooks run after setting up the frame to display Ediff Control Panel.
-Can be used to move the frame where it is desired.")
-(defvar ediff-startup-hook nil
- "*Hooks to run in the control buffer after Ediff has been set up.")
-(defvar ediff-select-hook nil
- "*Hooks to run after a difference has been selected.")
-(defvar ediff-unselect-hook nil
- "*Hooks to run after a difference has been unselected.")
-(defvar ediff-prepare-buffer-hook nil
- "*Hooks called after buffers A, B, and C are set up.")
-(defvar ediff-load-hook nil
- "*Hook run after Ediff is loaded. Can be used to change defaults.")
-
-(defvar ediff-mode-hook nil
- "*Hook run just after ediff-mode is set up in the control buffer.
-This is done before any windows or frames are created. One can use it to
-set local variables that determine how the display looks like.")
-(defvar ediff-keymap-setup-hook nil
- "*Hook run just after the default bindings in Ediff keymap are set up.")
-
-(defvar ediff-display-help-hook nil
- "*Hooks run after preparing the help message.")
-
-(defvar ediff-suspend-hook (list 'ediff-default-suspend-function)
- "*Hooks to run in the Ediff control buffer when Ediff is suspended.")
-(defvar ediff-quit-hook (list 'ediff-cleanup-mess)
- "*Hooks to run in the Ediff control buffer after finishing Ediff.")
-(defvar ediff-cleanup-hook nil
- "*Hooks to run on exiting Ediff but before killing the control buffer.
-This is a place to do various cleanups, such as deleting the variant buffers.
-Ediff provides a function, `ediff-janitor', as one such possible hook.")
-(defvar ediff-quit-merge-hook 'ediff-maybe-save-and-delete-merge
- "*Hooks to run before quitting a merge job.
-The most common use is to save and delete the merge buffer.")
-
-
-;; Error messages
-(defconst ediff-KILLED-VITAL-BUFFER
- "You have killed a vital Ediff buffer---you must leave Ediff now!")
-(defconst ediff-NO-DIFFERENCES
- "Sorry, comparison of identical variants is not what I am made for...")
-(defconst ediff-BAD-DIFF-NUMBER
- ;; %S stands for this-command, %d - diff number, %d - max diff
- "%S: Bad diff region number, %d. Valid numbers are 1 to %d")
-(defconst ediff-BAD-INFO (format "
-*** The Info file for Ediff, a part of the standard distribution
-*** of %sEmacs, does not seem to be properly installed.
-***
-*** Please contact your system administrator. "
- (if ediff-xemacs-p "X" "")))
-
-;; Selective browsing
-
-(ediff-defvar-local ediff-skip-diff-region-function 'ediff-show-all-diffs
- "Function that determines the next/previous diff region to show.
-Should return t for regions to be ignored and nil otherwise.
-This function gets a region number as an argument. The region number
-is the one used internally by Ediff. It is 1 less than the number seen
-by the user.")
-
-(ediff-defvar-local ediff-hide-regexp-matches-function
- 'ediff-hide-regexp-matches
- "Function to use in determining which regions to hide.
-See the documentation string of `ediff-hide-regexp-matches' for details.")
-(ediff-defvar-local ediff-focus-on-regexp-matches-function
- 'ediff-focus-on-regexp-matches
- "Function to use in determining which regions to focus on.
-See the documentation string of `ediff-focus-on-regexp-matches' for details.")
-
-;; Regexp that determines buf A regions to focus on when skipping to diff
-(ediff-defvar-local ediff-regexp-focus-A "" "")
-;; Regexp that determines buf B regions to focus on when skipping to diff
-(ediff-defvar-local ediff-regexp-focus-B "" "")
-;; Regexp that determines buf C regions to focus on when skipping to diff
-(ediff-defvar-local ediff-regexp-focus-C "" "")
-;; connective that determines whether to focus regions that match both or
-;; one of the regexps
-(ediff-defvar-local ediff-focus-regexp-connective 'and "")
-
-;; Regexp that determines buf A regions to ignore when skipping to diff
-(ediff-defvar-local ediff-regexp-hide-A "" "")
-;; Regexp that determines buf B regions to ignore when skipping to diff
-(ediff-defvar-local ediff-regexp-hide-B "" "")
-;; Regexp that determines buf C regions to ignore when skipping to diff
-(ediff-defvar-local ediff-regexp-hide-C "" "")
-;; connective that determines whether to hide regions that match both or
-;; one of the regexps
-(ediff-defvar-local ediff-hide-regexp-connective 'and "")
-
-
-;; Copying difference regions between buffers.
-(ediff-defvar-local ediff-killed-diffs-alist nil
- "A list of killed diffs.
-A diff is saved here if it is replaced by a diff
-from another buffer. This alist has the form:
-\((num (buff-object . diff) (buff-object . diff) (buff-object . diff)) ...),
-where some buffer-objects may be missing.")
-
-
-;; Highlighting
-;;(defvar ediff-before-flag-bol (if ediff-emacs-p "->>\n" (make-glyph "->>\n"))
-(defvar ediff-before-flag-bol (if ediff-xemacs-p (make-glyph "->>") "->>")
- "*Flag placed above the highlighted block of differences.
-Must end with newline.")
-;;(defvar ediff-after-flag-eol (if ediff-emacs-p "<<-\n" (make-glyph "<<-"))
-(defvar ediff-after-flag-eol (if ediff-xemacs-p (make-glyph "<<-") "<<-")
- "*Flag placed below the highlighted block of differences.
-Must end with newline.")
-
-(defvar ediff-before-flag-mol (if ediff-xemacs-p (make-glyph "->>") "->>")
- "*Like ediff-before-flag, used when a difference starts in mid-line.")
-(defvar ediff-after-flag-mol (if ediff-xemacs-p (make-glyph "<<-") "<<-")
- "*Like ediff-after-flag, used when a difference starts in mid-line.")
-
-
-(ediff-defvar-local ediff-use-faces t
- "If t, differences are highlighted using faces, if device supports faces.
-If nil, differences are highlighted using ASCII flags, ediff-before-flag
-and ediff-after-flag. On a non-window system, differences are always
-highlighted using ASCII flags.
-This variable can be set either in .emacs or toggled interactively.
-Use `setq-default' if setting it in .emacs")
-
-;; this indicates that diff regions are word-size, so fine diffs are
-;; permanently nixed; used in ediff-windows-wordwise and ediff-regions-wordwise
-(ediff-defvar-local ediff-word-mode nil "")
-;; Name of the job (ediff-files, ediff-windows, etc.)
-(ediff-defvar-local ediff-job-name nil "")
-
-;; Narrowing and ediff-region/windows support
-;; This is a list (overlay-A overlay-B overlay-C)
-;; If set, Ediff compares only those parts of buffers A/B/C that lie within
-;; the bounds of these overlays.
-(ediff-defvar-local ediff-narrow-bounds nil "")
-
-;; List (overlay-A overlay-B overlay-C), where each overlay spans the
-;; entire corresponding buffer.
-(ediff-defvar-local ediff-wide-bounds nil "")
-
-;; Current visibility boundaries in buffers A, B, and C.
-;; This is also a list of overlays. When the user toggles narrow/widen,
-;; this list changes from ediff-wide-bounds to ediff-narrow-bounds.
-;; and back.
-(ediff-defvar-local ediff-visible-bounds nil "")
-
-(ediff-defvar-local ediff-start-narrowed t
- "Non-nil means start narrowed, if doing ediff-windows-* or ediff-regions-*")
-(ediff-defvar-local ediff-quit-widened t
- "*Non-nil means: when finished, Ediff widens buffers A/B.
-Actually, Ediff restores the scope of visibility that existed at startup.")
-(defvar ediff-keep-variants t
- "*Nil means that non-modified variant buffers should be removed after some
-interrogation.
-Supplying a prefix argument to the quit command `q' temporarily reverses the
-meaning of this variable.")
-
-(ediff-defvar-local ediff-highlight-all-diffs t
- "If nil, only the selected differences are highlighted.
-This variable can be set either in .emacs or toggled interactively, using
-ediff-toggle-hilit. Use `setq-default' to set it.")
-
-;; A var local to each control panel buffer. Indicates highlighting style
-;; in effect for this buffer: `face', `ascii', nil -- temporarily
-;; unhighlighted, `off' -- turned off \(on a dumb terminal only\).
-(ediff-defvar-local ediff-highlighting-style nil "")
-
-
-;; The suffix of the control buffer name.
-(ediff-defvar-local ediff-control-buffer-suffix nil "")
-;; Same as ediff-control-buffer-suffix, but without <,>.
-;; It's a number rather than string.
-(ediff-defvar-local ediff-control-buffer-number nil "")
-
-
-;; The original values of ediff-protected-variables for buffer A
-(ediff-defvar-local ediff-buffer-values-orig-A nil "")
-;; The original values of ediff-protected-variables for buffer B
-(ediff-defvar-local ediff-buffer-values-orig-B nil "")
-;; The original values of ediff-protected-variables for buffer C
-(ediff-defvar-local ediff-buffer-values-orig-C nil "")
-;; The original values of ediff-protected-variables for buffer Ancestor
-(ediff-defvar-local ediff-buffer-values-orig-Ancestor nil "")
-;; Buffer-local variables to be saved then restored during Ediff sessions
-;; Buffer-local variables to be saved then restored during Ediff sessions
-(defconst ediff-protected-variables '(
- ;;buffer-read-only
- mode-line-format))
-
-;; Vector of differences between the variants. Each difference is
-;; represented by a vector of two overlays plus a vector of fine diffs,
-;; plus a no-fine-diffs flag. The first overlay spans the
-;; difference region in the A buffer and the second overlays the diff in
-;; the B buffer. If a difference section is empty, the corresponding
-;; overlay's endpoints coincide.
-;;
-;; The precise form of a difference vector for one buffer is:
-;; [diff diff diff ...]
-;; where each diff has the form:
-;; [diff-overlay fine-diff-vector no-fine-diffs-flag state-of-difference]
-;; fine-diff-vector is a vector [fine-diff-overlay fine-diff-overlay ...]
-;; no-fine-diffs-flag says if there are fine differences.
-;; state-of-difference is A, B, C, or nil, indicating which buffer is
-;; different from the other two (used only in 3-way jobs.
-(ediff-defvar-local ediff-difference-vector-A nil "")
-(ediff-defvar-local ediff-difference-vector-B nil "")
-(ediff-defvar-local ediff-difference-vector-C nil "")
-(ediff-defvar-local ediff-difference-vector-Ancestor nil "")
-
-;; [ status status status ...]
-;; Each status: [state-of-merge state-of-ancestor]
-;; state-of-merge is default-A, default-B, prefer-A, or prefer-B. It
-;; indicates the way a diff region was created in buffer C.
-;; state-of-ancestor says if the corresponding region in ancestor buffer is
-;; empty.
-(ediff-defvar-local ediff-state-of-merge nil "")
-
-;; The difference that is currently selected.
-(ediff-defvar-local ediff-current-difference -1 "")
-;; Number of differences found.
-(ediff-defvar-local ediff-number-of-differences nil "")
-
-;; Buffer containing the output of diff, which is used by Ediff to step
-;; through files.
-(ediff-defvar-local ediff-diff-buffer nil "")
-;; Like ediff-diff-buffer, but contains context diff. It is not used by
-;; Ediff, but it is saved in a file, if user requests so.
-(ediff-defvar-local ediff-custom-diff-buffer nil "")
-;; Buffer used for diff-style fine differences between regions.
-(ediff-defvar-local ediff-fine-diff-buffer nil "")
-;; Temporary buffer used for computing fine differences.
-(defconst ediff-tmp-buffer " *ediff-tmp*" "")
-;; Buffer used for messages
-(defconst ediff-msg-buffer " *ediff-message*" "")
-;; Buffer containing the output of diff when diff returns errors.
-(ediff-defvar-local ediff-error-buffer nil "")
-;; Buffer to display debug info
-(ediff-defvar-local ediff-debug-buffer "*ediff-debug*" "")
-
-;; List of ediff control panels associated with each buffer A/B/C/Ancestor.
-;; Not used any more, but may be needed in the future.
-(ediff-defvar-local ediff-this-buffer-ediff-sessions nil "")
-
-;; to be deleted in due time
-;; List of difference overlays disturbed by working with the current diff.
-(defvar ediff-disturbed-overlays nil "")
-
-;; Priority of non-selected overlays.
-(defvar ediff-shadow-overlay-priority 100 "")
-
-(defvar ediff-version-control-package 'vc
- "Version control package used.
-Currently, Ediff supports vc.el, rcs.el, pcl-cvs.el, and generic-sc.el. The
-standard Emacs interface to RCS, CVS, SCCS, etc., is vc.el. However, some
-people find the other two packages more convenient. Set this variable to the
-appropriate symbol: `rcs', `pcl-cvs', or `generic-sc' if you so desire.")
-
-
-(if ediff-xemacs-p
- (progn
- (fset 'ediff-read-event (symbol-function 'next-command-event))
- (fset 'ediff-overlayp (symbol-function 'extentp))
- (fset 'ediff-make-overlay (symbol-function 'make-extent))
- (fset 'ediff-delete-overlay (symbol-function 'delete-extent)))
- (fset 'ediff-read-event (symbol-function 'read-event))
- (fset 'ediff-overlayp (symbol-function 'overlayp))
- (fset 'ediff-make-overlay (symbol-function 'make-overlay))
- (fset 'ediff-delete-overlay (symbol-function 'delete-overlay)))
-
-;; Check the current version against the major and minor version numbers
-;; using op: cur-vers op major.minor If emacs-major-version or
-;; emacs-minor-version are not defined, we assume that the current version
-;; is hopelessly outdated. We assume that emacs-major-version and
-;; emacs-minor-version are defined. Otherwise, for Emacs/XEmacs 19, if the
-;; current minor version is < 10 (xemacs) or < 23 (emacs) the return value
-;; will be nil (when op is =, >, or >=) and t (when op is <, <=), which may be
-;; incorrect. However, this gives correct result in our cases, since we are
-;; testing for sufficiently high Emacs versions.
-(defun ediff-check-version (op major minor &optional type-of-emacs)
- (if (and (boundp 'emacs-major-version) (boundp 'emacs-minor-version))
- (and (cond ((eq type-of-emacs 'xemacs) ediff-xemacs-p)
- ((eq type-of-emacs 'emacs) ediff-emacs-p)
- (t t))
- (cond ((eq op '=) (and (= emacs-minor-version minor)
- (= emacs-major-version major)))
- ((memq op '(> >= < <=))
- (and (or (funcall op emacs-major-version major)
- (= emacs-major-version major))
- (if (= emacs-major-version major)
- (funcall op emacs-minor-version minor)
- t)))
- (t
- (error "%S: Invalid op in ediff-check-version" op))))
- (cond ((memq op '(= > >=)) nil)
- ((memq op '(< <=)) t))))
-
-
-;;;; warn if it is a wrong version of emacs
-;;(if (or (ediff-check-version '< 19 29 'emacs)
-;; (ediff-check-version '< 19 12 'xemacs))
-;; (progn
-;; (with-output-to-temp-buffer ediff-msg-buffer
-;; (switch-to-buffer ediff-msg-buffer)
-;; (insert
-;; (format "
-;;
-;;This version of Ediff requires
-;;
-;;\t Emacs 19.29 and higher
-;;\t OR
-;;\t XEmacs 19.12 and higher
-;;
-;;It is unlikely to work under Emacs version %s
-;;that you are using... " emacs-version))
-;; (if noninteractive
-;; ()
-;; (beep 1)
-;; (beep 1)
-;; (insert "\n\nType any key to continue...")
-;; (ediff-read-event)))
-;; (kill-buffer ediff-msg-buffer)))
-
-;; A fix for NeXT Step
-;; Should probably be eliminated in later versions.
-(if (and (ediff-window-display-p) (eq (ediff-device-type) 'ns))
- (progn
- (fset 'x-display-color-p (symbol-function 'ns-display-color-p))
- (fset 'x-color-defined-p (symbol-function 'ns-color-defined-p))
- (fset 'x-display-pixel-height (symbol-function 'ns-display-pixel-height))
- (fset 'x-display-pixel-width (symbol-function 'ns-display-pixel-width))
- ))
-
-
-(defsubst ediff-color-display-p ()
- (if ediff-emacs-p
- (x-display-color-p)
- (eq (device-class (selected-device)) 'color)))
-
-
-(if (ediff-has-face-support-p)
- (if ediff-xemacs-p
- (progn
- (fset 'ediff-valid-color-p (symbol-function 'valid-color-name-p))
- (fset 'ediff-get-face (symbol-function 'get-face)))
- ;; Temporary fix for OS/2 port of Emacs
- ;; pm-win.el in PM-Emacs should be fixed.
- (if (eq (ediff-device-type) 'pm)
- (fset 'ediff-valid-color-p
- (function (lambda (color) (assoc color pm-color-alist))))
- (fset 'ediff-valid-color-p (symbol-function 'x-color-defined-p)))
- (fset 'ediff-get-face (symbol-function 'internal-get-face))))
-
-(if (ediff-window-display-p)
- (if ediff-xemacs-p
- (progn
- (fset 'ediff-display-pixel-width
- (symbol-function 'device-pixel-width))
- (fset 'ediff-display-pixel-height
- (symbol-function 'device-pixel-height)))
- (fset 'ediff-display-pixel-width
- (symbol-function 'x-display-pixel-width))
- (fset 'ediff-display-pixel-height
- (symbol-function 'x-display-pixel-height))))
-
-
-(defun ediff-make-current-diff-overlay (type)
- (if (ediff-has-face-support-p)
- (let ((overlay (intern (format "ediff-current-diff-overlay-%S" type)))
- (buffer (ediff-get-buffer type))
- (face (face-name
- (symbol-value
- (intern (format "ediff-current-diff-face-%S" type))))))
- (set overlay
- (ediff-make-bullet-proof-overlay (point-max) (point-max) buffer))
- (ediff-set-overlay-face (symbol-value overlay) face)
- (ediff-overlay-put (symbol-value overlay) 'ediff ediff-control-buffer))
- ))
-
-(defun ediff-set-overlay-face (extent face)
- (ediff-overlay-put extent 'face face)
- (ediff-overlay-put extent 'help-echo 'ediff-region-help-echo))
-
-;; This does nothing in Emacs, since overlays there have no help-echo property
-(defun ediff-region-help-echo (extent)
- (let ((is-current (ediff-overlay-get extent 'ediff))
- (face (ediff-overlay-get extent 'face))
- (diff-num (ediff-overlay-get extent 'ediff-diff-num))
- face-help)
-
- ;; This happens only for refinement overlays
- (setq face-help (and face (get face 'ediff-help-echo)))
-
- (cond ((and is-current diff-num) ; current diff region
- (format "Difference region %S -- current" (1+ diff-num)))
- (face-help) ; refinement of current diff region
- (diff-num ; non-current
- (format "Difference region %S -- non-current" (1+ diff-num)))
- (t "")) ; none
- ))
-
-(defun ediff-set-face (ground face color)
- "Set face foreground/background."
- (if (ediff-has-face-support-p)
- (if (ediff-valid-color-p color)
- (if (eq ground 'foreground)
- (set-face-foreground face color)
- (set-face-background face color))
- (cond ((memq face
- '(ediff-current-diff-face-A
- ediff-current-diff-face-B
- ediff-current-diff-face-C
- ediff-current-diff-face-Ancestor))
- (copy-face 'highlight face))
- ((memq face
- '(ediff-fine-diff-face-A
- ediff-fine-diff-face-B
- ediff-fine-diff-face-C
- ediff-fine-diff-face-Ancestor))
- (copy-face 'secondary-selection face)
- (set-face-underline-p face t))
- ((memq face
- '(ediff-even-diff-face-A
- ediff-odd-diff-face-A
- ediff-even-diff-face-B ediff-odd-diff-face-B
- ediff-even-diff-face-C ediff-odd-diff-face-C
- ediff-even-diff-face-Ancestor
- ediff-odd-diff-face-Ancestor))
- (copy-face 'secondary-selection face))))
- ))
-
-(defun ediff-set-face-pixmap (face pixmap)
- "Set face pixmap on a monochrome display."
- (if (and (ediff-window-display-p) (not (ediff-color-display-p)))
- (condition-case nil
- (set-face-background-pixmap face pixmap)
- (error
- (message "Pixmap not found for %S: %s" (face-name face) pixmap)
- (sit-for 1)))))
-
-(defun ediff-hide-face (face)
- (if (and (ediff-has-face-support-p) ediff-emacs-p)
- (add-to-list 'facemenu-unlisted-faces face)))
-
-(defvar ediff-current-diff-face-A
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-current-diff-face-A)
- (ediff-hide-face 'ediff-current-diff-face-A)
- (or (face-differs-from-default-p 'ediff-current-diff-face-A)
- (cond ((ediff-color-display-p)
- (ediff-set-face
- 'foreground 'ediff-current-diff-face-A "firebrick")
- (ediff-set-face
- 'background 'ediff-current-diff-face-A "pale green"))
- (t
- (if ediff-xemacs-p
- (copy-face 'modeline 'ediff-current-diff-face-A)
- (copy-face 'highlight 'ediff-current-diff-face-A))
- )))
- 'ediff-current-diff-face-A))
- "Face for highlighting the selected difference in buffer A.")
-
-(defvar ediff-current-diff-face-B
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-current-diff-face-B)
- (ediff-hide-face 'ediff-current-diff-face-B)
- (or (face-differs-from-default-p 'ediff-current-diff-face-B)
- (cond ((ediff-color-display-p)
- (ediff-set-face
- 'foreground 'ediff-current-diff-face-B "DarkOrchid")
- (ediff-set-face
- 'background 'ediff-current-diff-face-B "Yellow"))
- (t
- (if ediff-xemacs-p
- (copy-face 'modeline 'ediff-current-diff-face-B)
- (copy-face 'highlight 'ediff-current-diff-face-B))
- )))
- 'ediff-current-diff-face-B))
- "Face for highlighting the selected difference in buffer B.")
-
-
-(defvar ediff-current-diff-face-C
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-current-diff-face-C)
- (ediff-hide-face 'ediff-current-diff-face-C)
- (or (face-differs-from-default-p 'ediff-current-diff-face-C)
- (cond ((ediff-color-display-p)
- (ediff-set-face
- 'foreground 'ediff-current-diff-face-C "Navy")
- (ediff-set-face
- 'background 'ediff-current-diff-face-C "Pink"))
- (t
- (if ediff-xemacs-p
- (copy-face 'modeline 'ediff-current-diff-face-C)
- (copy-face 'highlight 'ediff-current-diff-face-C))
- )))
- 'ediff-current-diff-face-C))
- "Face for highlighting the selected difference in buffer C.")
-
-(defvar ediff-current-diff-face-Ancestor
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-current-diff-face-Ancestor)
- (ediff-hide-face 'ediff-current-diff-face-Ancestor)
- (or (face-differs-from-default-p 'ediff-current-diff-face-Ancestor)
- (copy-face
- 'ediff-current-diff-face-C 'ediff-current-diff-face-Ancestor))
- 'ediff-current-diff-face-Ancestor))
- "Face for highlighting the selected difference in the ancestor buffer.")
-
-(defvar ediff-fine-diff-pixmap "gray3"
- "Pixmap to use for highlighting fine differences.")
-(defvar ediff-odd-diff-pixmap "gray1"
- "Pixmap to use for highlighting odd differences.")
-(defvar ediff-even-diff-pixmap "Stipple"
- "Pixmap to use for highlighting even differences.")
-
-(defvar ediff-fine-diff-face-A
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-fine-diff-face-A)
- (ediff-hide-face 'ediff-fine-diff-face-A)
- (or (face-differs-from-default-p 'ediff-fine-diff-face-A)
- (cond ((ediff-color-display-p)
- (ediff-set-face 'foreground 'ediff-fine-diff-face-A
- "Navy")
- (ediff-set-face 'background 'ediff-fine-diff-face-A
- "sky blue"))
- (t
- (set-face-underline-p 'ediff-fine-diff-face-A t)
- (ediff-set-face-pixmap 'ediff-fine-diff-face-A
- ediff-fine-diff-pixmap)
- )))
- 'ediff-fine-diff-face-A))
- "Face for highlighting the refinement of the selected diff in buffer A.")
-
-(defvar ediff-fine-diff-face-B
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-fine-diff-face-B)
- (ediff-hide-face 'ediff-fine-diff-face-B)
- (or (face-differs-from-default-p 'ediff-fine-diff-face-B)
- (cond ((ediff-color-display-p)
- (ediff-set-face 'foreground 'ediff-fine-diff-face-B "Black")
- (ediff-set-face 'background 'ediff-fine-diff-face-B "cyan"))
- (t
- (set-face-underline-p 'ediff-fine-diff-face-B t)
- (ediff-set-face-pixmap 'ediff-fine-diff-face-B
- ediff-fine-diff-pixmap)
- )))
- 'ediff-fine-diff-face-B))
- "Face for highlighting the refinement of the selected diff in buffer B.")
-
-(defvar ediff-fine-diff-face-C
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-fine-diff-face-C)
- (ediff-hide-face 'ediff-fine-diff-face-C)
- (or (face-differs-from-default-p 'ediff-fine-diff-face-C)
- (cond ((ediff-color-display-p)
- (ediff-set-face 'foreground 'ediff-fine-diff-face-C "black")
- (ediff-set-face
- 'background 'ediff-fine-diff-face-C "Turquoise"))
- (t
- (set-face-underline-p 'ediff-fine-diff-face-C t)
- (ediff-set-face-pixmap 'ediff-fine-diff-face-C
- ediff-fine-diff-pixmap)
- )))
- 'ediff-fine-diff-face-C))
- "Face for highlighting the refinement of the selected diff in buffer C.")
-
-(defvar ediff-fine-diff-face-Ancestor
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-fine-diff-face-Ancestor)
- (ediff-hide-face 'ediff-fine-diff-face-Ancestor)
- (or (face-differs-from-default-p 'ediff-fine-diff-face-Ancestor)
- (progn
- (copy-face
- 'ediff-fine-diff-face-C 'ediff-fine-diff-face-Ancestor)
- (ediff-set-face-pixmap 'ediff-fine-diff-face-Ancestor
- ediff-fine-diff-pixmap))
- )))
- "Face highlighting refinements of the selected diff in ancestor buffer.
-Presently, this is not used, as difference regions are not refined in the
-ancestor buffer.")
-
-(defvar ediff-even-diff-face-A
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-even-diff-face-A)
- (ediff-hide-face 'ediff-even-diff-face-A)
- (or (face-differs-from-default-p 'ediff-even-diff-face-A)
- (cond ((ediff-color-display-p)
- (ediff-set-face
- 'foreground 'ediff-even-diff-face-A "black")
- (ediff-set-face
- 'background 'ediff-even-diff-face-A "light grey"))
- (t
- (copy-face 'italic 'ediff-even-diff-face-A)
- (ediff-set-face-pixmap 'ediff-even-diff-face-A
- ediff-even-diff-pixmap)
- )))
- 'ediff-even-diff-face-A))
- "Face used to highlight even-numbered differences in buffer A.")
-
-(defvar ediff-even-diff-face-B
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-even-diff-face-B)
- (ediff-hide-face 'ediff-even-diff-face-B)
- (or (face-differs-from-default-p 'ediff-even-diff-face-B)
- (cond ((ediff-color-display-p)
- (ediff-set-face
- 'foreground 'ediff-even-diff-face-B "White")
- (ediff-set-face
- 'background 'ediff-even-diff-face-B "Gray"))
- (t
- (copy-face 'italic 'ediff-even-diff-face-B)
- (ediff-set-face-pixmap 'ediff-even-diff-face-B
- ediff-even-diff-pixmap)
- )))
- 'ediff-even-diff-face-B))
- "Face used to highlight even-numbered differences in buffer B.")
-
-(defvar ediff-even-diff-face-C
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-even-diff-face-C)
- (ediff-hide-face 'ediff-even-diff-face-C)
- (or (face-differs-from-default-p 'ediff-even-diff-face-C)
- (progn
- (copy-face 'ediff-even-diff-face-A 'ediff-even-diff-face-C)
- (ediff-set-face-pixmap 'ediff-even-diff-face-C
- ediff-even-diff-pixmap)))
- 'ediff-even-diff-face-C))
- "Face used to highlight even-numbered differences in buffer C.")
-
-(defvar ediff-even-diff-face-Ancestor
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-even-diff-face-Ancestor)
- (ediff-hide-face 'ediff-even-diff-face-Ancestor)
- (or (face-differs-from-default-p 'ediff-even-diff-face-Ancestor)
- (progn
- (copy-face
- 'ediff-even-diff-face-C 'ediff-even-diff-face-Ancestor)
- (ediff-set-face-pixmap 'ediff-even-diff-face-Ancestor
- ediff-even-diff-pixmap)))
- 'ediff-even-diff-face-Ancestor))
- "Face highlighting even-numbered differences in the ancestor buffer.")
-
-(defvar ediff-odd-diff-face-A
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-odd-diff-face-A)
- (ediff-hide-face 'ediff-odd-diff-face-A)
- (or (face-differs-from-default-p 'ediff-odd-diff-face-A)
- (cond ((ediff-color-display-p)
- (ediff-set-face
- 'foreground 'ediff-odd-diff-face-A "White")
- (ediff-set-face
- 'background 'ediff-odd-diff-face-A "Gray"))
- (t
- (copy-face 'italic 'ediff-odd-diff-face-A)
- (ediff-set-face-pixmap 'ediff-odd-diff-face-A
- ediff-odd-diff-pixmap)
- )))
- 'ediff-odd-diff-face-A))
- "Face used to highlight odd-numbered differences in buffer A.")
-
-(defvar ediff-odd-diff-face-B
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-odd-diff-face-B)
- (ediff-hide-face 'ediff-odd-diff-face-B)
- (or (face-differs-from-default-p 'ediff-odd-diff-face-B)
- (cond ((ediff-color-display-p)
- (ediff-set-face
- 'foreground 'ediff-odd-diff-face-B "Black")
- (ediff-set-face
- 'background 'ediff-odd-diff-face-B "light grey"))
- (t
- (copy-face 'italic 'ediff-odd-diff-face-B)
- (ediff-set-face-pixmap 'ediff-odd-diff-face-B
- ediff-odd-diff-pixmap)
- )))
- 'ediff-odd-diff-face-B))
- "Face used to highlight odd-numbered differences in buffer B.")
-
-(defvar ediff-odd-diff-face-C
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-odd-diff-face-C)
- (ediff-hide-face 'ediff-odd-diff-face-C)
- (or (face-differs-from-default-p 'ediff-odd-diff-face-C)
- (progn
- (copy-face 'ediff-odd-diff-face-A 'ediff-odd-diff-face-C)
- (ediff-set-face-pixmap 'ediff-odd-diff-face-C
- ediff-odd-diff-pixmap)))
- 'ediff-odd-diff-face-C))
- "Face used to highlight odd-numbered differences in buffer C.")
-
-(defvar ediff-odd-diff-face-Ancestor
- (if (ediff-has-face-support-p)
- (progn
- (make-face 'ediff-odd-diff-face-Ancestor)
- (ediff-hide-face 'ediff-odd-diff-face-Ancestor)
- (or (face-differs-from-default-p 'ediff-odd-diff-face-Ancestor)
- (progn
- (copy-face 'ediff-odd-diff-face-C 'ediff-odd-diff-face-Ancestor)
- (ediff-set-face-pixmap 'ediff-odd-diff-face-Ancestor
- ediff-odd-diff-pixmap)))
- 'ediff-odd-diff-face-Ancestor))
- "Face used to highlight even-numbered differences in the ancestor buffer.")
-
-;; Help echo
-(put 'ediff-fine-diff-face-A 'ediff-help-echo
- "A `refinement' of the current difference region")
-(put 'ediff-fine-diff-face-B 'ediff-help-echo
- "A `refinement' of the current difference region")
-(put 'ediff-fine-diff-face-C 'ediff-help-echo
- "A `refinement' of the current difference region")
-(put 'ediff-fine-diff-face-Ancestor 'ediff-help-echo
- "A `refinement' of the current difference region")
-
-
-;;; Overlays
-
-(ediff-defvar-local ediff-current-diff-overlay-A nil
- "Overlay for the current difference region in buffer A.")
-(ediff-defvar-local ediff-current-diff-overlay-B nil
- "Overlay for the current difference region in buffer B.")
-(ediff-defvar-local ediff-current-diff-overlay-C nil
- "Overlay for the current difference region in buffer C.")
-(ediff-defvar-local ediff-current-diff-overlay-Ancestor nil
- "Overlay for the current difference region in the ancestor buffer.")
-
-;; Compute priority of ediff overlay.
-(defun ediff-highest-priority (start end buffer)
- (let ((pos (max 1 (1- start)))
- ovr-list)
- (if ediff-xemacs-p
- (1+ ediff-shadow-overlay-priority)
- (ediff-eval-in-buffer buffer
- (while (< pos (min (point-max) (1+ end)))
- (setq ovr-list (append (overlays-at pos) ovr-list))
- (setq pos (next-overlay-change pos)))
- (1+ (apply '+
- (mapcar (function
- (lambda (ovr)
- (if ovr
- (or (ediff-overlay-get ovr 'priority) 0)
- 0)))
- ovr-list)
- ))
- ))))
-
-
-(defvar ediff-toggle-read-only-function nil
- "*Specifies the function to be used to toggle read-only.
-If nil, Ediff tries to deduce the function from the binding of C-x C-q.
-Normally, this is the `toggle-read-only' function, but, if version
-control is used, it could be `vc-toggle-read-only' or `rcs-toggle-read-only'.")
-
-
-;;; Misc
-
-;; if nil, this silences some messages
-(defconst ediff-verbose-p t)
-
-(ediff-defvar-local ediff-autostore-merges 'group-jobs-only
- "*Save the results of merge jobs automatically.
-Nil means don't save automatically. t means always save. Anything but nil or t
-means save automatically only if the merge job is part of a group of jobs, such
-as `ediff-merge-directory' or `ediff-merge-directory-revisions'.")
-
-;; file where the result of the merge is to be saved. used internally
-(ediff-defvar-local ediff-merge-store-file nil "")
-
-(defvar ediff-no-emacs-help-in-control-buffer nil
- "*Non-nil means C-h should not invoke Emacs help in control buffer.
-Instead, C-h jumps to previous difference.")
-
-(defvar ediff-temp-file-prefix
- (let ((env (or (getenv "TMPDIR")
- (getenv "TMP")
- (getenv "TEMP")))
- d)
- (setq d (if (and env (> (length env) 0))
- env
- (cond ((memq system-type '(vax-vms axp-vms)) "SYS$SCRATCH:")
- ((eq system-type 'ms-dos) "c:/")
- (t "/tmp"))))
- ;; The following is to make sure we get something to which we can
- ;; add directory levels on VMS.
- (setq d (file-name-as-directory (directory-file-name d)))
- )
- "*Prefix to put on Ediff temporary file names.
-Do not start with `~/' or `~user-name/'.")
-
-(defvar ediff-temp-file-mode 384 ; u=rw only
- "*Mode for Ediff temporary files.")
-
-;; Metacharacters that have to be protected from the shell when executing
-;; a diff/diff3 command.
-(defvar ediff-metachars "[ \t\n!\"#$&'()*;<=>?[\\^`{|~]"
- "Characters that must be quoted with \\ when used in a shell command line.
-More precisely, a regexp to match any one such character.")
-
-;; needed to simulate frame-char-width in XEmacs.
-(defvar ediff-H-glyph (if ediff-xemacs-p (make-glyph "H")))
-
-
-(ediff-defvar-local ediff-temp-file-A nil
- "Temporary file used for refining difference regions in buffer A.")
-(ediff-defvar-local ediff-temp-file-B nil
- "Temporary file used for refining difference regions in buffer B.")
-(ediff-defvar-local ediff-temp-file-C nil
- "Temporary file used for refining difference regions in buffer C.")
-
-;;; In-line functions
-
-(defsubst ediff-file-remote-p (file-name)
- (require 'ange-ftp)
- (car (if ediff-xemacs-p
- (ange-ftp-ftp-path file-name)
- (ange-ftp-ftp-name file-name))))
-
-
-(defsubst ediff-frame-unsplittable-p (frame)
- (cdr (assq 'unsplittable (frame-parameters frame))))
-
-(defsubst ediff-get-next-window (wind prev-wind)
- (or (window-live-p wind)
- (setq wind (if prev-wind
- (next-window wind)
- (selected-window)))))
-
-
-(defsubst ediff-kill-buffer-carefully (buf)
- "Kill buffer BUF if it exists."
- (if (ediff-buffer-live-p buf)
- (kill-buffer (get-buffer buf))))
-
-
-;; activate faces on diff regions in buffer
-(defun ediff-paint-background-regions-in-one-buffer (buf-type unhighlight)
- (let ((diff-vector
- (eval (intern (format "ediff-difference-vector-%S" buf-type))))
- overl diff-num)
- (mapcar (function
- (lambda (rec)
- (setq overl (ediff-get-diff-overlay-from-diff-record rec)
- diff-num (ediff-overlay-get overl 'ediff-diff-num))
- (ediff-set-overlay-face
- overl
- (if (not unhighlight)
- (ediff-background-face buf-type diff-num))
- )))
- diff-vector)))
-
-
-;; activate faces on diff regions in all buffers
-(defun ediff-paint-background-regions (&optional unhighlight)
- (ediff-paint-background-regions-in-one-buffer
- 'A unhighlight)
- (ediff-paint-background-regions-in-one-buffer
- 'B unhighlight)
- (ediff-paint-background-regions-in-one-buffer
- 'C unhighlight)
- (ediff-paint-background-regions-in-one-buffer
- 'Ancestor unhighlight))
-
-(defun ediff-highlight-diff-in-one-buffer (n buf-type)
- (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
- (let* ((buff (ediff-get-buffer buf-type))
- (last (ediff-eval-in-buffer buff (point-max)))
- (begin (ediff-get-diff-posn buf-type 'beg n))
- (end (ediff-get-diff-posn buf-type 'end n))
- (xtra (if (equal begin end) 1 0))
- (end-hilit (min last (+ end xtra)))
- (current-diff-overlay
- (symbol-value
- (intern (format "ediff-current-diff-overlay-%S" buf-type)))))
-
- (if ediff-xemacs-p
- (ediff-move-overlay current-diff-overlay begin end-hilit)
- (ediff-move-overlay current-diff-overlay begin end-hilit buff))
- (ediff-overlay-put current-diff-overlay 'priority
- (ediff-highest-priority begin end-hilit buff))
- (ediff-overlay-put current-diff-overlay 'ediff-diff-num n)
-
- ;; unhighlight the background overlay for diff n so it won't
- ;; interfere with the current diff overlay
- (ediff-set-overlay-face (ediff-get-diff-overlay n buf-type) nil)
- )))
-
-
-(defun ediff-unhighlight-diff-in-one-buffer (buf-type)
- (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
- (let ((current-diff-overlay
- (symbol-value
- (intern (format "ediff-current-diff-overlay-%S" buf-type))))
- (overlay
- (ediff-get-diff-overlay ediff-current-difference buf-type))
- )
-
- (ediff-move-overlay current-diff-overlay 1 1)
-
- ;; rehighlight the overlay in the background of the
- ;; current difference region
- (ediff-set-overlay-face
- overlay
- (if (and (ediff-has-face-support-p)
- ediff-use-faces ediff-highlight-all-diffs)
- (ediff-background-face buf-type ediff-current-difference)))
- )))
-
-(defun ediff-unhighlight-diffs-totally-in-one-buffer (buf-type)
- (ediff-unselect-and-select-difference -1)
- (if (and (ediff-has-face-support-p) ediff-use-faces)
- (let* ((inhibit-quit t)
- (current-diff-overlay-var
- (intern (format "ediff-current-diff-overlay-%S" buf-type)))
- (current-diff-overlay (symbol-value current-diff-overlay-var)))
- (ediff-paint-background-regions 'unhighlight)
- (if (ediff-overlayp current-diff-overlay)
- (ediff-delete-overlay current-diff-overlay))
- (set current-diff-overlay-var nil)
- )))
-
-
-(defsubst ediff-highlight-diff (n)
- "Put face on diff N. Invoked for X displays only."
- (ediff-highlight-diff-in-one-buffer n 'A)
- (ediff-highlight-diff-in-one-buffer n 'B)
- (ediff-highlight-diff-in-one-buffer n 'C)
- (ediff-highlight-diff-in-one-buffer n 'Ancestor)
- )
-
-
-(defsubst ediff-unhighlight-diff ()
- "Remove overlays from buffers A, B, and C."
- (ediff-unhighlight-diff-in-one-buffer 'A)
- (ediff-unhighlight-diff-in-one-buffer 'B)
- (ediff-unhighlight-diff-in-one-buffer 'C)
- (ediff-unhighlight-diff-in-one-buffer 'Ancestor)
- )
-
-;; delete highlighting overlays, restore faces to their original form
-(defsubst ediff-unhighlight-diffs-totally ()
- (ediff-unhighlight-diffs-totally-in-one-buffer 'A)
- (ediff-unhighlight-diffs-totally-in-one-buffer 'B)
- (ediff-unhighlight-diffs-totally-in-one-buffer 'C)
- (ediff-unhighlight-diffs-totally-in-one-buffer 'Ancestor)
- )
-
-(defsubst ediff-background-face (buf-type dif-num)
- ;; The value of dif-num is always 1- the one that user sees.
- ;; This is why even face is used when dif-num is odd.
- (intern (format (if (ediff-odd-p dif-num)
- "ediff-even-diff-face-%S"
- "ediff-odd-diff-face-%S")
- buf-type)))
-
-
-;; arg is a record for a given diff in a difference vector
-;; this record is itself a vector
-(defsubst ediff-clear-fine-diff-vector (diff-record)
- (if diff-record
- (mapcar 'ediff-delete-overlay
- (ediff-get-fine-diff-vector-from-diff-record diff-record))))
-
-(defsubst ediff-clear-fine-differences-in-one-buffer (n buf-type)
- (ediff-clear-fine-diff-vector (ediff-get-difference n buf-type))
- (ediff-set-fine-diff-vector n buf-type nil))
-
-(defsubst ediff-clear-fine-differences (n)
- (ediff-clear-fine-differences-in-one-buffer n 'A)
- (ediff-clear-fine-differences-in-one-buffer n 'B)
- (if ediff-3way-job
- (ediff-clear-fine-differences-in-one-buffer n 'C)))
-
-
-(defsubst ediff-convert-fine-diffs-to-overlays (diff-list region-num)
- (ediff-set-fine-overlays-in-one-buffer 'A diff-list region-num)
- (ediff-set-fine-overlays-in-one-buffer 'B diff-list region-num)
- (if ediff-3way-job
- (ediff-set-fine-overlays-in-one-buffer 'C diff-list region-num)
- ))
-
-(defsubst ediff-mouse-event-p (event)
- (if ediff-xemacs-p
- (button-event-p event)
- (string-match "mouse" (format "%S" (event-basic-type event)))
- ))
-
-
-(defsubst ediff-key-press-event-p (event)
- (if ediff-xemacs-p
- (key-press-event-p event)
- (or (char-or-string-p event) (symbolp event))))
-
-(defun ediff-event-point (event)
- (cond ((ediff-mouse-event-p event)
- (if ediff-xemacs-p
- (event-point event)
- (posn-point (event-start event))))
- ((ediff-key-press-event-p event)
- (point))
- (t (error))))
-
-(defun ediff-event-buffer (event)
- (cond ((ediff-mouse-event-p event)
- (if ediff-xemacs-p
- (event-buffer event)
- (window-buffer (posn-window (event-start event)))))
- ((ediff-key-press-event-p event)
- (current-buffer))
- (t (error))))
-
-
-(defsubst ediff-frame-iconified-p (frame)
- (if (and (ediff-window-display-p) (frame-live-p frame))
- (if ediff-xemacs-p
- (frame-iconified-p frame)
- (eq (frame-visible-p frame) 'icon))))
-
-(defsubst ediff-window-visible-p (wind)
- ;; under TTY, window-live-p also means window is visible
- (and (window-live-p wind)
- (or (not (ediff-window-display-p))
- (frame-visible-p (window-frame wind)))))
-
-
-(defsubst ediff-frame-char-width (frame)
- (if ediff-xemacs-p
- (/ (frame-pixel-width frame) (frame-width frame))
- (frame-char-width frame)))
-
-(defun ediff-reset-mouse (&optional frame do-not-grab-mouse)
- (or frame (setq frame (selected-frame)))
- (if (ediff-window-display-p)
- (let ((frame-or-wind frame))
- (if ediff-xemacs-p
- (setq frame-or-wind (frame-selected-window frame)))
- (or do-not-grab-mouse
- ;; don't set mouse if the user said to never do this
- (not ediff-grab-mouse)
- ;; Don't grab on quit, if the user doesn't want to.
- ;; If ediff-grab-mouse = t, then mouse won't be grabbed for
- ;; sessions that are not part of a group (this is done in
- ;; ediff-recenter). The condition below affects only terminating
- ;; sessions in session groups (in which case mouse is warped into
- ;; a meta buffer).
- (and (eq ediff-grab-mouse 'maybe)
- (memq this-command '(ediff-quit ediff-update-diffs)))
- (set-mouse-position frame-or-wind 1 0))
- )))
-
-(defsubst ediff-spy-after-mouse ()
- (setq ediff-mouse-pixel-position (mouse-pixel-position)))
-
-;; It is not easy to find out when the user grabs the mouse, since emacs and
-;; xemacs behave differently when mouse is not in any frame. Also, this is
-;; sensitive to when the user grabbed mouse. Not used for now.
-(defun ediff-user-grabbed-mouse ()
- (if ediff-mouse-pixel-position
- (cond ((not (eq (car ediff-mouse-pixel-position)
- (car (mouse-pixel-position)))))
- ((and (car (cdr ediff-mouse-pixel-position))
- (car (cdr (mouse-pixel-position)))
- (cdr (cdr ediff-mouse-pixel-position))
- (cdr (cdr (mouse-pixel-position))))
- (not (and (< (abs (- (car (cdr ediff-mouse-pixel-position))
- (car (cdr (mouse-pixel-position)))))
- ediff-mouse-pixel-threshold)
- (< (abs (- (cdr (cdr ediff-mouse-pixel-position))
- (cdr (cdr (mouse-pixel-position)))))
- ediff-mouse-pixel-threshold))))
- (t nil))))
-
-(defsubst ediff-frame-char-height (frame)
- (if ediff-xemacs-p
- (glyph-height ediff-H-glyph (selected-window frame))
- (frame-char-height frame)))
-
-;; Some overlay functions
-
-(defsubst ediff-empty-overlay-p (overl)
- (= (ediff-overlay-start overl) (ediff-overlay-end overl)))
-
-;; like overlay-buffer in Emacs. In XEmacs, returns nil if the extent is
-;; dead. Otherwise, works like extent-buffer
-(defun ediff-overlay-buffer (overl)
- (if ediff-emacs-p
- (overlay-buffer overl)
- (and (extent-live-p overl) (extent-object overl))))
-
-;; like overlay-get in Emacs. In XEmacs, returns nil if the extent is
-;; dead. Otherwise, like extent-property
-(defun ediff-overlay-get (overl property)
- (if ediff-emacs-p
- (overlay-get overl property)
- (and (extent-live-p overl) (extent-property overl property))))
-
-
-;; These two functions are here because XEmacs refuses to
-;; handle overlays whose buffers were deleted.
-(defun ediff-move-overlay (overlay beg end &optional buffer)
- "Calls `move-overlay' in Emacs and `set-extent-endpoints' in Lemacs.
-Checks if overlay's buffer exists before actually doing the move."
- (let ((buf (and overlay (ediff-overlay-buffer overlay))))
- (if (ediff-buffer-live-p buf)
- (if ediff-xemacs-p
- (set-extent-endpoints overlay beg end)
- (move-overlay overlay beg end buffer))
- ;; buffer's dead
- (if overlay
- (ediff-delete-overlay overlay)))))
-
-(defun ediff-overlay-put (overlay prop value)
- "Calls `overlay-put' or `set-extent-property' depending on Emacs version.
-Checks if overlay's buffer exists."
- (if (ediff-buffer-live-p (ediff-overlay-buffer overlay))
- (if ediff-xemacs-p
- (set-extent-property overlay prop value)
- (overlay-put overlay prop value))
- (ediff-delete-overlay overlay)))
-
-;; Some diff region tests
-
-;; t if diff region is empty.
-;; In case of buffer C, t also if it is not a 3way
-;; comparison job (merging jobs return t as well).
-(defun ediff-empty-diff-region-p (n buf-type)
- (if (eq buf-type 'C)
- (or (not ediff-3way-comparison-job)
- (= (ediff-get-diff-posn 'C 'beg n)
- (ediff-get-diff-posn 'C 'end n)))
- (= (ediff-get-diff-posn buf-type 'beg n)
- (ediff-get-diff-posn buf-type 'end n))))
-
-;; Test if diff region is white space only.
-;; If 2-way job and buf-type = C, then returns t.
-(defun ediff-whitespace-diff-region-p (n buf-type)
- (or (and (eq buf-type 'C) (not ediff-3way-job))
- (ediff-empty-diff-region-p n buf-type)
- (let ((beg (ediff-get-diff-posn buf-type 'beg n))
- (end (ediff-get-diff-posn buf-type 'end n)))
- (ediff-eval-in-buffer (ediff-get-buffer buf-type)
- (save-excursion
- (goto-char beg)
- (skip-chars-forward ediff-whitespace)
- (>= (point) end))))))
-
-;; temporarily uses DIR to abbreviate file name
-;; if DIR is nil, use default-directory
-(defun ediff-abbreviate-file-name (file &optional dir)
- (cond ((stringp dir)
- (let ((directory-abbrev-alist (list (cons dir ""))))
- (abbreviate-file-name file)))
- (ediff-emacs-p (abbreviate-file-name file))
- (t ; XEmacs requires addl argument
- (abbreviate-file-name file t))))
-
-;; Takes a directory and returns the parent directory.
-;; does nothing to `/'. If the ARG is a regular file,
-;; strip the file AND the last dir.
-(defun ediff-strip-last-dir (dir)
- (if (not (stringp dir)) (setq dir default-directory))
- (setq dir (expand-file-name dir))
- (or (file-directory-p dir) (setq dir (file-name-directory dir)))
- (let* ((pos (1- (length dir)))
- (last-char (aref dir pos)))
- (if (and (> pos 0) (= last-char ?/))
- (setq dir (substring dir 0 pos)))
- (ediff-abbreviate-file-name (file-name-directory dir))))
-
-(defun ediff-truncate-string-left (str newlen)
- ;; leave space for ... on the left
- (let ((len (length str))
- substr)
- (if (<= len newlen)
- str
- (setq newlen (max 0 (- newlen 3)))
- (setq substr (substring str (max 0 (- len 1 newlen))))
- (concat "..." substr))))
-
-(defun ediff-abbrev-jobname (jobname)
- (cond ((eq jobname 'ediff-directories)
- "Compare two directories")
- ((eq jobname 'ediff-files)
- "Compare two files")
- ((eq jobname 'ediff-buffers)
- "Compare two buffers")
- ((eq jobname 'ediff-directories3)
- "Compare three directories")
- ((eq jobname 'ediff-files3)
- "Compare three files")
- ((eq jobname 'ediff-buffers3)
- "Compare three buffers")
- ((eq jobname 'ediff-revision)
- "Compare file with a version")
- ((eq jobname 'ediff-directory-revisions)
- "Compare dir files with versions")
- ((eq jobname 'ediff-merge-directory-revisions)
- "Merge dir files with versions")
- ((eq jobname 'ediff-merge-directory-revisions-with-ancestor)
- "Merge dir versions via ancestors")
- (t
- (let* ((str (substring (symbol-name jobname) 6))
- (len (length str))
- (pos 0))
- (while (< pos len)
- (if (= pos 0)
- (aset str pos (upcase (aref str pos))))
- (if (= (aref str pos) ?-)
- (aset str pos ?\ ))
- (setq pos (1+ pos)))
- str))))
-
-
-
-(defsubst ediff-get-region-contents (n buf-type ctrl-buf &optional start end)
- (ediff-eval-in-buffer
- (ediff-eval-in-buffer ctrl-buf (ediff-get-buffer buf-type))
- (buffer-substring
- (or start (ediff-get-diff-posn buf-type 'beg n ctrl-buf))
- (or end (ediff-get-diff-posn buf-type 'end n ctrl-buf)))))
-
-;; If ediff modified mode line, strip the modification
-(defsubst ediff-strip-mode-line-format ()
- (if (member (car mode-line-format) '(" A: " " B: " " C: " " Ancestor: "))
- (setq mode-line-format (nth 2 mode-line-format))))
-
-;; Verify that we have a difference selected.
-(defsubst ediff-valid-difference-p (&optional n)
- (or n (setq n ediff-current-difference))
- (and (>= n 0) (< n ediff-number-of-differences)))
-
-(defsubst ediff-show-all-diffs (n)
- "Don't skip difference regions."
- nil)
-
-(defsubst Xor (a b)
- (or (and a (not b)) (and (not a) b)))
-
-(defsubst ediff-message-if-verbose (string &rest args)
- (if ediff-verbose-p
- (apply 'message string args)))
-
-(defun ediff-file-attributes (filename attr-number)
- (let ((handler (find-file-name-handler filename 'find-file-noselect)))
- (if (and handler (string-match "ange-ftp" (format "%S" handler)))
- -1
- (nth attr-number (file-attributes filename)))))
-(defsubst ediff-file-size (filename)
- (ediff-file-attributes filename 7))
-(defsubst ediff-file-modtime (filename)
- (ediff-file-attributes filename 5))
-
-
-(defun ediff-convert-standard-filename (fname)
- (if ediff-emacs-p
- (convert-standard-filename fname)
- ;; hopefully, XEmacs adds this functionality
- fname))
-
-
-;;; Local Variables:
-;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
-;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
-;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
-;;; End:
-
-(provide 'ediff-init)
-
-
-;;; ediff-init.el ends here
diff --git a/lisp/ediff-merg.el b/lisp/ediff-merg.el
deleted file mode 100644
index a07dc8d8c16..00000000000
--- a/lisp/ediff-merg.el
+++ /dev/null
@@ -1,275 +0,0 @@
-;;; ediff-merg.el --- merging utilities
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Michael Kifer <kifer@cs.sunysb.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(require 'ediff-init)
-
-
-(defvar ediff-default-variant 'combined
- "*The variant to be used as a default for buffer C in merging.
-Valid values are the symbols `default-A', `default-B', and `combined'.")
-
-(defvar ediff-combination-pattern
- '("<<<<<<<<<<<<<< variant A" ">>>>>>>>>>>>>> variant B" "======= end of combination")
- "*Pattern to be used for combining difference regions in buffers A and B.
-The value is (STRING1 STRING2 STRING3). The combined text will look like this:
-
-STRING1
-diff region from variant A
-STRING2
-diff region from variant B
-STRING3
-")
-
-(ediff-defvar-local ediff-show-clashes-only nil
- "*If t, show only those diff regions where both buffers disagree with the ancestor.
-This means that regions that have status prefer-A or prefer-B will be
-skiped over. Nil means show all regions.")
-
-
-(defsubst ediff-get-combined-region (n)
- (concat (nth 0 ediff-combination-pattern) "\n"
- (ediff-get-region-contents n 'A ediff-control-buffer)
- (nth 1 ediff-combination-pattern) "\n"
- (ediff-get-region-contents n 'B ediff-control-buffer)
- (nth 2 ediff-combination-pattern) "\n"))
-
-(defsubst ediff-make-combined-diff (regA regB)
- (concat (nth 0 ediff-combination-pattern) "\n"
- regA
- (nth 1 ediff-combination-pattern) "\n"
- regB
- (nth 2 ediff-combination-pattern) "\n"))
-
-(defsubst ediff-set-state-of-all-diffs-in-all-buffers (ctl-buf)
- (let ((n 0))
- (while (< n ediff-number-of-differences)
- (ediff-set-state-of-diff-in-all-buffers n ctl-buf)
- (setq n (1+ n)))))
-
-(defun ediff-set-state-of-diff-in-all-buffers (n ctl-buf)
- (let ((regA (ediff-get-region-contents n 'A ctl-buf))
- (regB (ediff-get-region-contents n 'B ctl-buf))
- (regC (ediff-get-region-contents n 'C ctl-buf)))
- (cond ((and (string= regA regB) (string= regA regC))
- (ediff-set-state-of-diff n 'A "=diff(B)")
- (ediff-set-state-of-diff n 'B "=diff(C)")
- (ediff-set-state-of-diff n 'C "=diff(A)"))
- ((string= regA regB)
- (ediff-set-state-of-diff n 'A "=diff(B)")
- (ediff-set-state-of-diff n 'B "=diff(A)")
- (ediff-set-state-of-diff n 'C nil))
- ((string= regA regC)
- (ediff-set-state-of-diff n 'A "=diff(C)")
- (ediff-set-state-of-diff n 'C "=diff(A)")
- (ediff-set-state-of-diff n 'B nil))
- ((string= regB regC)
- (ediff-set-state-of-diff n 'C "=diff(B)")
- (ediff-set-state-of-diff n 'B "=diff(C)")
- (ediff-set-state-of-diff n 'A nil))
- ((string= regC (ediff-get-combined-region n))
- (ediff-set-state-of-diff n 'A nil)
- (ediff-set-state-of-diff n 'B nil)
- (ediff-set-state-of-diff n 'C "=diff(A+B)"))
- (t (ediff-set-state-of-diff n 'A nil)
- (ediff-set-state-of-diff n 'B nil)
- (ediff-set-state-of-diff n 'C nil)))
- ))
-
-(defun ediff-set-merge-mode ()
- ;; by Stig@hackvan.com
- (normal-mode t)
- (remove-hook 'local-write-file-hooks 'ediff-set-merge-mode))
-
-
-;; Go over all diffs starting with DIFF-NUM and copy regions into buffer C
-;; according to the state of the difference.
-;; Since ediff-copy-diff refuses to copy identical diff regions, there is
-;; no need to optimize ediff-do-merge any further.
-;;
-;; If re-merging, change state of merge in all diffs starting with
-;; DIFF-NUM, except those where the state is prefer-* or where it is
-;; `default-*' or `combined' but the buf C region appears to be modified
-;; since last set by default.
-(defun ediff-do-merge (diff-num &optional remerging)
- (if (< diff-num 0) (setq diff-num 0))
- (let ((n diff-num)
- ;;(default-state-of-merge (format "%S" ediff-default-variant))
- do-not-copy state-of-merge)
- (while (< n ediff-number-of-differences)
- (setq do-not-copy nil) ; reset after each cycle
- (if (= (mod n 10) 0)
- (message "%s buffers A & B into C ... region %d of %d"
- (if remerging "Re-merging" "Merging")
- n
- ediff-number-of-differences))
-
- (setq state-of-merge (ediff-get-state-of-merge n))
-
- (if remerging
- (let ((reg-A (ediff-get-region-contents n 'A ediff-control-buffer))
- (reg-B (ediff-get-region-contents n 'B ediff-control-buffer))
- (reg-C (ediff-get-region-contents n 'C ediff-control-buffer)))
-
- ;; if region was edited since it was first set by default
- (if (or (and (string= state-of-merge "default-A")
- (not (string= reg-A reg-C)))
- ;; was edited since first set by default
- (and (string= state-of-merge "default-B")
- (not (string= reg-B reg-C)))
- ;; was edited since first set by default
- (and (string= state-of-merge "combined")
- (not (string=
- (ediff-make-combined-diff reg-A reg-B) reg-C)))
- ;; was preferred--ignore
- (string-match "prefer" state-of-merge))
- (setq do-not-copy t))
-
- ;; change state of merge for this diff, if necessary
- (if (and (string-match "\\(default\\|combined\\)" state-of-merge)
- (not do-not-copy))
- (ediff-set-state-of-merge
- n (format "%S" ediff-default-variant)))
- ))
-
- ;; state-of-merge may have changed via ediff-set-state-of-merge, so
- ;; check it once again
- (setq state-of-merge (ediff-get-state-of-merge n))
-
- (or do-not-copy
- (if (string= state-of-merge "combined")
- ;; use n+1 because ediff-combine-diffs works via user numbering
- ;; of diffs, which is 1+ to what ediff uses internally
- (ediff-combine-diffs (1+ n) 'batch)
- (ediff-copy-diff
- n (if (string-match "-A" state-of-merge) 'A 'B) 'C 'batch)))
- (setq n (1+ n)))
- (message "Merging buffers A & B into C ... Done")
- ))
-
-
-(defun ediff-re-merge ()
- "Remerge unmodified diff regions using a new default. Start with the current region."
- (interactive)
- (let* ((default-variant-alist
- (list '("default-A") '("default-B") '("combined")))
- (actual-alist
- (delete (list (symbol-name ediff-default-variant))
- default-variant-alist)))
- (setq ediff-default-variant
- (intern
- (completing-read
- (format "Current merge default is `%S'. New default: "
- ediff-default-variant)
- actual-alist nil 'must-match)))
- (ediff-do-merge ediff-current-difference 'remerge)
- (ediff-recenter)
- ))
-
-(defun ediff-shrink-window-C (arg)
- "Shrink window C to just one line.
-With a prefix argument, returns window C to its normal size.
-Used only for merging jobs."
- (interactive "P")
- (if (not ediff-merge-job)
- (error "ediff-shrink-window-C can be used only for merging jobs"))
- (cond ((eq arg '-) (setq arg -1))
- ((not (numberp arg)) (setq arg nil)))
- (cond ((null arg)
- (let ((ediff-merge-window-share
- (if (< (window-height ediff-window-C) 3)
- ediff-merge-window-share 0)))
- (setq ediff-window-config-saved "") ; force redisplay
- (ediff-recenter 'no-rehighlight)))
- ((and (< arg 0) (> (window-height ediff-window-C) 2))
- (setq ediff-merge-window-share (* ediff-merge-window-share 0.9))
- (setq ediff-window-config-saved "") ; force redisplay
- (ediff-recenter 'no-rehighlight))
- ((and (> arg 0) (> (window-height ediff-window-A) 2))
- (setq ediff-merge-window-share (* ediff-merge-window-share 1.1))
- (setq ediff-window-config-saved "") ; force redisplay
- (ediff-recenter 'no-rehighlight))))
-
-
-;; N here is the user's region number. It is 1+ what Ediff uses internally.
-(defun ediff-combine-diffs (n &optional batch-invocation)
- "Combine Nth diff regions of buffers A and B and place the combination in C.
-N is a prefix argument. If nil, combine the current difference regions.
-Combining is done according to the specifications in variable
-`ediff-combination-pattern'."
- (interactive "P")
- (setq n (if (numberp n) (1- n) ediff-current-difference))
-
- (let (regA regB reg-combined)
- (setq regA (ediff-get-region-contents n 'A ediff-control-buffer)
- regB (ediff-get-region-contents n 'B ediff-control-buffer))
-
- (setq reg-combined (ediff-make-combined-diff regA regB))
-
- (ediff-copy-diff n nil 'C batch-invocation reg-combined))
- (or batch-invocation (ediff-jump-to-difference (1+ n))))
-
-
-;; Checks if the region in buff C looks like a combination of the regions
-;; in buffers A and B. Returns a list (reg-a-beg reg-a-end reg-b-beg reg-b-end)
-;; These refer to where the copies of region A and B start and end in buffer C
-(defun ediff-looks-like-combined-merge (region-num)
- (if ediff-merge-job
- (let ((combined (string-match (regexp-quote "(A+B)")
- (or (ediff-get-state-of-diff region-num 'C)
- "")))
- (reg-beg (ediff-get-diff-posn 'C 'beg region-num))
- (reg-end (ediff-get-diff-posn 'C 'end region-num))
- (pat1 (nth 0 ediff-combination-pattern))
- (pat2 (nth 1 ediff-combination-pattern))
- (pat3 (nth 2 ediff-combination-pattern))
- reg-a-beg reg-a-end reg-b-beg reg-b-end reg-c-beg reg-c-end)
-
- (if combined
- (ediff-eval-in-buffer ediff-buffer-C
- (goto-char reg-beg)
- (search-forward pat1 reg-end 'noerror)
- (setq reg-a-beg (match-beginning 0))
- (setq reg-a-end (match-end 0))
- (search-forward pat2 reg-end 'noerror)
- (setq reg-b-beg (match-beginning 0))
- (setq reg-b-end (match-end 0))
- (search-forward pat3 reg-end 'noerror)
- (setq reg-c-beg (match-beginning 0))
- (setq reg-c-end (match-end 0))))
-
- (if (and reg-a-beg reg-a-end reg-b-beg reg-b-end)
- (list reg-a-beg reg-a-end reg-b-beg reg-b-end reg-c-beg reg-c-end))
- )))
-
-
-;;; Local Variables:
-;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
-;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
-;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
-;;; End:
-
-(provide 'ediff-merg)
-
-;; ediff-merg.el ends here
diff --git a/lisp/ediff-mult.el b/lisp/ediff-mult.el
deleted file mode 100644
index 2920e250e86..00000000000
--- a/lisp/ediff-mult.el
+++ /dev/null
@@ -1,1724 +0,0 @@
-;;; ediff-mult.el --- support for multi-file/multi-buffer processing in Ediff
-
-;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Michael Kifer <kifer@cs.sunysb.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Users are encouraged to add functionality to this file.
-;; The present file contains all the infrastructure needed for that.
-;;
-;; Generally, to to implement a new multisession capability within Ediff,
-;; you need to tell it
-;;
-;; 1. How to display the session group buffer.
-;; This function must indicate which Ediff sessions are active (+) and
-;; which are finished (-).
-;; See ediff-redraw-directory-group-buffer for an example.
-;; In all likelihood, ediff-redraw-directory-group-buffer can be used
-;; directly or after a small modification.
-;; 2. What action to take when the user clicks button 2 or types v,e, or
-;; RET. See ediff-filegroup-action.
-;; 3. Provide a list of pairs or triples of file names (or buffers,
-;; depending on the particular Ediff operation you want to invoke)
-;; in the following format:
-;; (descriptor (obj1 obj2 obj3) (...) ...)
-;; Actually, the format of this list is pretty much up to the
-;; developer. The only thing is that it must be a list of lists,
-;; and the first list must describe the meta session, and subsequent
-;; elements must describe individual sessions.
-;; This descriptor must be a list of two, three, or four elements (nil
-;; or string). The function ediff-redraw-registry-buffer displays the
-;; second through last of these in the registry buffer.
-;; Also, keep in mind that the function ediff-prepare-meta-buffer
-;; (which see) prepends the session group buffer to the descriptor and
-;; nil in front of each subsequent list (i.e., the above list
-;; will become
-;; ((meta-buf descriptor) (nil obj1 obj2 obj3) (nil ...) ...)
-;; Ediff expects that your function (in 2 above) will arrange to
-;; replace this prepended nil (via setcar) with the actual ediff
-;; control buffer associated with an appropriate Ediff session.
-;; This is arranged through internal startup hooks that can be passed
-;; to any of Ediff major entries (such as ediff-files, epatch, etc.).
-;; See how this is done in ediff-filegroup-action.
-;;
-;; Session descriptions are of the form (obj1 obj2 obj3), which
-;; describe objects relevant to the session. Usually they are names of
-;; files, but sometimes they may be other things. For instance, obj3 is
-;; nil for jobs that involve only two files. For patch jobs, obj2 and
-;; obj3 are markers that specify the patch corresponding to the file
-;; (whose name is obj1).
-;; 4. Write a function that makes a call to ediff-prepare-meta-buffer
-;; passing all this info.
-;; You may be able to use ediff-directories-internal as a template.
-;; 5. If you intend to add several related pieces of functionality,
-;; you may want to keep the function in 4 as an internal version
-;; and then write several top-level interactive functions that call it
-;; with different parameters.
-;; See how ediff-directories, ediff-merge-directories, and
-;; ediff-merge-directories-with-ancestor all use
-;; ediff-directories-internal.
-;;
-;; A useful addition here could be session groups selected by patterns
-;; (which are different in each directory). For instance, one may want to
-;; compare files of the form abc{something}.c to files old{something}.d
-;; which may be in the same or different directories. Or, one may want to
-;; compare all files of the form {something} to files of the form {something}~.
-;;
-;; Implementing this requires writing an collating function, which should pair
-;; up appropriate files. It will also require a generalization of the functions
-;; that do the layout of the meta- and differences buffers and of
-;; ediff-filegroup-action.
-
-;;; Code:
-
-(require 'ediff-init)
-
-;; meta-buffer
-(ediff-defvar-local ediff-meta-buffer nil "")
-(ediff-defvar-local ediff-parent-meta-buffer nil "")
-;; the registry buffer
-(defvar ediff-registry-buffer nil)
-
-(defconst ediff-meta-buffer-message "This is an Ediff Session Group Panel: %s
-
-Useful commands:
- button2, `v', RET over a session line: start that Ediff session
- `M':\tin any session invoked from here, brings back this group panel
- `R':\tdisplay the registry of active Ediff sessions
- `h':\tmark session for hiding (toggle)
- `x':\thide marked sessions; with prefix arg--unhide hidden sessions
- `m':\tmark session for a non-hiding operation (toggle)
- SPC:\tnext session
- DEL:\tprevious session
- `E':\tbrowse Ediff on-line manual
- `q':\tquit this session group
-")
-
-(ediff-defvar-local ediff-meta-buffer-map nil
- "The keymap for the meta buffer.")
-(defvar ediff-dir-diffs-buffer-map (make-sparse-keymap)
- "The keymap to be installed in the buffer showing differences between
-directories.")
-
-;; Variable specifying the action to take when the use invokes ediff in the
-;; meta buffer. This is usually ediff-registry-action or ediff-filegroup-action
-(ediff-defvar-local ediff-meta-action-function nil "")
-;; Tells ediff-update-meta-buffer how to redraw it
-(ediff-defvar-local ediff-meta-redraw-function nil "")
-;; Tells ediff-filegroup-action and similar procedures how to invoke Ediff for
-;; the sessions in a given session group
-(ediff-defvar-local ediff-session-action-function nil "")
-
-(ediff-defvar-local ediff-metajob-name nil "")
-
-;; buffer used to collect custom diffs from individual sessions in the group
-(ediff-defvar-local ediff-meta-diff-buffer nil "")
-
-;; history var to use for filtering groups
-(defvar ediff-filtering-regexp-history nil "")
-
-;; This has the form ((ctl-buf file1 file2) (stl-buf file1 file2) ...)
-;; If ctl-buf is nil, the file-pair wasn't processed yet. If it is
-;; killed-buffer object, the file pair has been processed. If it is a live
-;; buffer, this means ediff is still working on the pair
-(ediff-defvar-local ediff-meta-list nil "")
-
-
-;; the difference list between directories in a directory session group
-(ediff-defvar-local ediff-dir-difference-list nil "")
-(ediff-defvar-local ediff-dir-diffs-buffer nil "")
-
-;; The registry of Ediff sessions. A list of control buffers.
-(defvar ediff-session-registry nil)
-
-(defvar ediff-registry-setup-hook nil
- "*Hooks run just after the registry control panel is set up.")
-(defvar ediff-session-group-setup-hook nil
- "*Hooks run just after a meta-buffer controlling a session group, such as
-ediff-directories, is run.")
-(defvar ediff-quit-session-group-hook nil
- "*Hooks run just before exiting a session group.")
-(defvar ediff-show-registry-hook nil
- "*Hooks run just after the registry buffer is shown.")
-(defvar ediff-show-session-group-hook nil
- "*Hooks run just after a session group buffer is shown.")
-(defvar ediff-meta-buffer-keymap-setup-hook nil
- "*Hooks run just after setting up the ediff-meta-buffer-map.
-This keymap controls key bindings in the meta buffer and is a local variable.
-This means that you can set different bindings for different kinds of meta
-buffers.")
-
-;; buffer holding the multi-file patch. local to the meta buffer
-(ediff-defvar-local ediff-meta-patchbufer nil "")
-
-;;; API for ediff-meta-list
-
-;; group buffer/regexp
-(defun ediff-get-group-buffer (meta-list)
- (nth 0 (car meta-list)))
-
-(defun ediff-get-group-regexp (meta-list)
- (nth 1 (car meta-list)))
-;; group objects
-(defun ediff-get-group-objA (meta-list)
- (nth 2 (car meta-list)))
-(defun ediff-get-group-objB (meta-list)
- (nth 3 (car meta-list)))
-(defun ediff-get-group-objC (meta-list)
- (nth 4 (car meta-list)))
-(defun ediff-get-group-merge-autostore-dir (meta-list)
- (nth 5 (car meta-list)))
-
-;; session buffer
-(defun ediff-get-session-buffer (elt)
- (nth 0 elt))
-(defun ediff-get-session-status (elt)
- (nth 1 elt))
-(defun ediff-set-session-status (session-info new-status)
- (setcar (cdr session-info) new-status))
-;; session objects
-(defun ediff-get-session-objA (elt)
- (nth 2 elt))
-(defun ediff-get-session-objB (elt)
- (nth 3 elt))
-(defun ediff-get-session-objC (elt)
- (nth 4 elt))
-(defun ediff-get-session-objA-name (elt)
- (car (nth 2 elt)))
-(defun ediff-get-session-objB-name (elt)
- (car (nth 3 elt)))
-(defun ediff-get-session-objC-name (elt)
- (car (nth 4 elt)))
-;; equality indicators
-(defsubst ediff-get-file-eqstatus (elt)
- (nth 1 elt))
-(defsubst ediff-set-file-eqstatus (elt value)
- (setcar (cdr elt) value))
-
-;; set up the keymap in the meta buffer
-(defun ediff-setup-meta-map()
- (setq ediff-meta-buffer-map (make-sparse-keymap))
- (suppress-keymap ediff-meta-buffer-map)
- (define-key ediff-meta-buffer-map "q" 'ediff-quit-meta-buffer)
- (define-key ediff-meta-buffer-map "R" 'ediff-show-registry)
- (define-key ediff-meta-buffer-map "E" 'ediff-documentation)
- (define-key ediff-meta-buffer-map "v" ediff-meta-action-function)
- (define-key ediff-meta-buffer-map "\C-m" ediff-meta-action-function)
- (define-key ediff-meta-buffer-map " " 'ediff-next-meta-item)
- (define-key ediff-meta-buffer-map "\C-?" 'ediff-previous-meta-item)
- (define-key ediff-meta-buffer-map [delete] 'ediff-previous-meta-item)
- (define-key ediff-meta-buffer-map [backspace] 'ediff-previous-meta-item)
- (or (ediff-one-filegroup-metajob)
- (define-key ediff-meta-buffer-map "=" 'ediff-meta-mark-equal-files))
- (if ediff-no-emacs-help-in-control-buffer
- (define-key ediff-meta-buffer-map "\C-h" 'ediff-previous-meta-item))
- (if ediff-emacs-p
- (define-key ediff-meta-buffer-map [mouse-2] ediff-meta-action-function)
- (define-key ediff-meta-buffer-map [button2] ediff-meta-action-function))
-
- (use-local-map ediff-meta-buffer-map)
- ;; modify ediff-meta-buffer-map here
- (run-hooks 'ediff-meta-buffer-keymap-setup-hook))
-
-(defun ediff-meta-mode ()
- "This mode controls all operations on Ediff session groups.
-It is entered through one of the following commands:
- `ediff-directories'
- `edirs'
- `ediff-directories3'
- `edirs3'
- `ediff-merge-directories'
- `edirs-merge'
- `ediff-merge-directories-with-ancestor'
- `edirs-merge-with-ancestor'
- `ediff-directory-revisions'
- `edir-revisions'
- `ediff-merge-directory-revisions'
- `edir-merge-revisions'
- `ediff-merge-directory-revisions-with-ancestor'
- `edir-merge-revisions-with-ancestor'
-
-Commands:
-\\{ediff-meta-buffer-map}"
- (kill-all-local-variables)
- (setq major-mode 'ediff-meta-mode)
- (setq mode-name "MetaEdiff"))
-
-
-;; the keymap for the buffer showing directory differences
-(suppress-keymap ediff-dir-diffs-buffer-map)
-(define-key ediff-dir-diffs-buffer-map "q" 'ediff-bury-dir-diffs-buffer)
-(define-key ediff-dir-diffs-buffer-map " " 'next-line)
-(define-key ediff-dir-diffs-buffer-map "\C-?" 'previous-line)
-(define-key ediff-dir-diffs-buffer-map [delete] 'previous-line)
-(define-key ediff-dir-diffs-buffer-map [backspace] 'previous-line)
-
-(defun ediff-next-meta-item (count)
- "Move to the next item in Ediff registry or session group buffer.
-Moves in circular fashion. With numeric prefix arg, skip this many items."
- (interactive "p")
- (or count (setq count 1))
- (while (< 0 count)
- (setq count (1- count))
- (ediff-next-meta-item1)))
-
-;; Move to the next meta item
-(defun ediff-next-meta-item1 ()
- (let (pos)
- (setq pos (ediff-next-meta-overlay-start (point)))
-;;; ;; skip deleted
-;;; (while (memq (ediff-get-session-status
-;;; (ediff-get-meta-info (current-buffer) pos 'noerror))
-;;; '(?H ?I))
-;;; (setq pos (ediff-next-meta-overlay-start pos)))
-
- (if pos (goto-char pos))
- (if (eq ediff-metajob-name 'ediff-registry)
- (if (and (ediff-get-meta-info (current-buffer) pos 'noerror)
- (search-forward "*Ediff" nil t))
- (skip-chars-backward "a-zA-Z*"))
- (if (> (skip-chars-forward "-+?H* \t0-9") 0)
- (backward-char 1)))))
-
-
-(defun ediff-previous-meta-item (count)
- "Move to the previous item in Ediff registry or session group buffer.
-Moves in circular fashion. With numeric prefix arg, skip this many items."
- (interactive "p")
- (or count (setq count 1))
- (while (< 0 count)
- (setq count (1- count))
- (ediff-previous-meta-item1)))
-
-(defun ediff-previous-meta-item1 ()
- (let (pos)
- (setq pos (ediff-previous-meta-overlay-start (point)))
-;;; ;; skip deleted
-;;; (while (ediff-get-session-status
-;;; (ediff-get-meta-info (current-buffer) pos 'noerror))
-;;; (setq pos (ediff-previous-meta-overlay-start pos)))
-
- (if pos (goto-char pos))
- (if (eq ediff-metajob-name 'ediff-registry)
- (if (and (ediff-get-meta-info (current-buffer) pos 'noerror)
- (search-forward "*Ediff" nil t))
- (skip-chars-backward "a-zA-Z*"))
- (if (> (skip-chars-forward "-+?H* \t0-9") 0)
- (backward-char 1)))
- ))
-
-(defsubst ediff-add-slash-if-directory (dir file)
- (if (file-directory-p (concat dir file))
- (file-name-as-directory file)
- file))
-
-
-;; DIR1, DIR2, DIR3 are directories. DIR3 can be nil.
-;; OUTPUT-DIR is a directory for auto-storing the results of merge jobs.
-;; Can be nil.
-;; REGEXP is a regexp used to filter out files in the directories.
-;; If a file is a directory in dir1 but not dir2 (or vice versa), it is not
-;; included in the intersection. However, a regular file that is a dir in dir3
-;; is included, since dir3 files are supposed to be ancestors for merging.
-;; Returns a list of the form:
-;; ((dir1 dir2 dir3) (f1 f2 f3) (f1 f2 f3) ...)
-;; dir3, f3 can be nil if intersecting only 2 directories.
-;; If COMPARISON-FUNC is given, use it. Otherwise, use string=
-;; DIFF-VAR contains the name of the variable in which to return the
-;; difference list (which represents the differences among the contents of
-;; directories). The diff list is of the form:
-;; ((dir1 dir2 dir3) (file . num) (file . num)...)
-;; where num encodes the set of dirs where the file is found:
-;; 2 - only dir1; 3 - only dir2; 5 - only dir3; 6 - dir1&2; 10 - dir1&3; etc.
-(defun ediff-intersect-directories (jobname
- diff-var regexp dir1 dir2
- &optional
- dir3 merge-autostore-dir comparison-func)
- (setq comparison-func (or comparison-func 'string=))
- (let (lis1 lis2 lis3 common auxdir1 auxdir2 auxdir3 difflist)
-
- (setq auxdir1 (file-name-as-directory dir1)
- lis1 (directory-files auxdir1 nil regexp)
- lis1 (delete "." lis1)
- lis1 (delete ".." lis1)
- lis1 (mapcar
- (function
- (lambda (elt)
- (ediff-add-slash-if-directory auxdir1 elt)))
- lis1)
- auxdir2 (file-name-as-directory dir2)
- lis2 (mapcar
- (function
- (lambda (elt)
- (ediff-add-slash-if-directory auxdir2 elt)))
- (directory-files auxdir2 nil regexp)))
-
- (if (stringp dir3)
- (setq auxdir3 (file-name-as-directory dir3)
- lis3 (mapcar
- (function
- (lambda (elt)
- (ediff-add-slash-if-directory auxdir3 elt)))
- (directory-files auxdir3 nil regexp))))
-
- (if (stringp merge-autostore-dir)
- (setq merge-autostore-dir
- (file-name-as-directory merge-autostore-dir)))
- (setq common (ediff-intersection lis1 lis2 comparison-func))
-
- ;; In merge with ancestor jobs, we don't intersect with lis3.
- ;; If there is no ancestor, we'll offer to merge without the ancestor.
- ;; So, we intersect with lis3 only when we are doing 3-way file comparison
- (if (and lis3 (ediff-comparison-metajob3 jobname))
- (setq common (ediff-intersection common lis3 comparison-func)))
-
- ;; copying is needed because sort sorts via side effects
- (setq common (sort (ediff-copy-list common) 'string-lessp))
-
- ;; compute difference list
- (setq difflist (ediff-set-difference
- (ediff-union (ediff-union lis1 lis2 comparison-func)
- lis3
- comparison-func)
- common
- comparison-func)
- difflist (delete "." difflist)
- ;; copying is needed because sort sorts via side effects
- difflist (sort (ediff-copy-list (delete ".." difflist))
- 'string-lessp))
-
- (setq difflist (mapcar (function (lambda (elt) (cons elt 1))) difflist))
-
- ;; check for files belonging to lis1/2/3
- (mapcar (function (lambda (elt)
- (if (member (car elt) lis1)
- (setcdr elt (* (cdr elt) 2)))
- (if (member (car elt) lis2)
- (setcdr elt (* (cdr elt) 3)))
- (if (member (car elt) lis3)
- (setcdr elt (* (cdr elt) 5)))
- ))
- difflist)
- (setq difflist (cons (list regexp auxdir1 auxdir2 auxdir3) difflist))
-
- ;; return the difference list back to the calling function
- (set diff-var difflist)
-
- ;; return result
- (cons (list regexp auxdir1 auxdir2 auxdir3 merge-autostore-dir)
- (mapcar
- (function
- (lambda (elt)
- (list (concat auxdir1 elt)
- (concat auxdir2 elt)
- (if lis3
- (progn
- ;; The following is done because:
- ;; In merging with ancestor, we don't intersect
- ;; with lis3. So, it is possible that elt is a
- ;; file in auxdir1/2 but a directory in auxdir3
- ;; Or elt may not exist in auxdir3 at all.
- ;; In the first case, we add a slash at the end.
- ;; In the second case, we insert nil.
- (setq elt (ediff-add-slash-if-directory auxdir3 elt))
- (if (file-exists-p (concat auxdir3 elt))
- (concat auxdir3 elt)))))))
- common))
- ))
-
-;; find directory files that are under revision.
-;; Include subdirectories, since we may visit them recursively.
-;; DIR1 is the directory to inspect.
-;; OUTPUT-DIR is the directory where to auto-store the results of merges. Can
-;; be nil.
-(defun ediff-get-directory-files-under-revision (jobname
- regexp dir1
- &optional merge-autostore-dir)
- (let (lis1 elt common auxdir1)
- (setq auxdir1 (file-name-as-directory dir1)
- lis1 (directory-files auxdir1 nil regexp))
-
- (if (stringp merge-autostore-dir)
- (setq merge-autostore-dir
- (file-name-as-directory merge-autostore-dir)))
-
- (while lis1
- (setq elt (car lis1)
- lis1 (cdr lis1))
- ;; take files under revision control
- (cond ((file-directory-p (concat auxdir1 elt))
- (setq common (cons elt common)))
- ((file-exists-p (concat auxdir1 elt ",v"))
- (setq common (cons elt common)))
- ((file-exists-p (concat auxdir1 "RCS/" elt ",v"))
- (setq common (cons elt common)))
- ) ; cond
- ) ; while
-
- (setq common (delete "." common)
- common (delete ".." common)
- common (delete "RCS" common))
-
- ;; copying is needed because sort sorts via side effects
- (setq common (sort (ediff-copy-list common) 'string-lessp))
-
- ;; return result
- (cons (list regexp auxdir1 nil nil merge-autostore-dir)
- (mapcar (function (lambda (elt)
- (list (concat auxdir1 elt)
- nil nil)))
- common))
- ))
-
-
-;; If file groups selected by patterns will ever be implemented, this
-;; comparison function might become useful.
-;;;; uses external variables PAT1 PAT2 to compare str1/2
-;;;; patterns must be of the form ???*???? where ??? are strings of chars
-;;;; containing no *.
-;;(defun ediff-pattern= (str1 str2)
-;; (let (pos11 pos12 pos21 pos22 len1 len2)
-;; (setq pos11 0
-;; len (length epat1)
-;; pos12 len)
-;; (while (and (< pos11 len) (not (= (aref epat1 pos11) ?*)))
-;; (setq pos11 (1+ pos11)))
-;; (while (and (> pos12 0) (not (= (aref epat1 (1- pos12)) ?*)))
-;; (setq pos12 (1- pos12)))
-;;
-;; (setq pos21 0
-;; len (length epat2)
-;; pos22 len)
-;; (while (and (< pos21 len) (not (= (aref epat2 pos21) ?*)))
-;; (setq pos21 (1+ pos21)))
-;; (while (and (> pos22 0) (not (= (aref epat2 (1- pos22)) ?*)))
-;; (setq pos22 (1- pos22)))
-;;
-;; (if (and (> (length str1) pos12) (>= pos12 pos11) (> pos11 -1)
-;; (> (length str2) pos22) (>= pos22 pos21) (> pos21 -1))
-;; (string= (substring str1 pos11 pos12)
-;; (substring str2 pos21 pos22)))
-;; ))
-
-
-;; Prepare meta-buffer in accordance with the argument-function and
-;; redraw-function. Must return the created meta-buffer.
-(defun ediff-prepare-meta-buffer (action-func meta-list
- meta-buffer-name redraw-function
- jobname &optional startup-hooks)
- (let* ((meta-buffer-name
- (ediff-unique-buffer-name meta-buffer-name "*"))
- (meta-buffer (get-buffer-create meta-buffer-name)))
- (ediff-eval-in-buffer meta-buffer
-
- ;; comes first
- (ediff-meta-mode)
-
- (setq ediff-meta-action-function action-func
- ediff-meta-redraw-function redraw-function
- ediff-metajob-name jobname
- ediff-meta-buffer meta-buffer)
-
- ;; comes after ediff-meta-action-function is set
- (ediff-setup-meta-map)
-
- (if (eq ediff-metajob-name 'ediff-registry)
- (progn
- (setq ediff-registry-buffer meta-buffer
- ediff-meta-list meta-list)
- ;; this func is used only from registry buffer, not from other
- ;; meta-buffs.
- (define-key
- ediff-meta-buffer-map "M" 'ediff-show-meta-buff-from-registry))
- ;; Initialize the meta list -- don't do this for registry.
- ;;
- ;; We prepend '(nil nil) to all elts of meta-list, except the first.
- ;; The first nil will later be replaced by the session buffer. The
- ;; second is reserved for session status.
- ;;
- ;; (car ediff-meta-list) gets cons'ed with the session group buffer.
- ;; Also, session objects A/B/C are turned into lists of the form
- ;; (obj eq-indicator). Eq-indicator is either nil or =. Initialized to
- ;; nil. If later it is discovered that this file is = to some other
- ;; file in the same session, eq-indicator is changed to `='.
- ;; For now, the eq-indicator is used only for 2 and 3-file jobs.
- (setq ediff-meta-list
- (cons (cons meta-buffer (car meta-list))
- (mapcar
- (function
- (lambda (elt)
- (cons nil
- (cons nil
- ;; convert each obj to (obj nil),
- ;; where nil is the initial value
- ;; for eq-indicator -- see above
- (mapcar
- (function (lambda (obj) (list obj nil)))
- elt)))))
- (cdr meta-list)))))
-
- (or (eq meta-buffer ediff-registry-buffer)
- (setq ediff-session-registry
- (cons meta-buffer ediff-session-registry)))
-
- ;; redraw-function uses ediff-meta-list
- (funcall redraw-function ediff-meta-list)
-
- ;; set read-only/non-modified
- (setq buffer-read-only t)
- (set-buffer-modified-p nil)
-
- (run-hooks 'startup-hooks)
-
- ;; Arrange to show directory contents differences
- ;; Must be after run startup-hooks, since ediff-dir-difference-list is
- ;; set inside these hooks
- (if (eq action-func 'ediff-filegroup-action)
- (progn
- ;; put meta buffer in (car ediff-dir-difference-list)
- (setq ediff-dir-difference-list
- (cons (cons meta-buffer (car ediff-dir-difference-list))
- (cdr ediff-dir-difference-list)))
-
- (or (ediff-one-filegroup-metajob jobname)
- (ediff-draw-dir-diffs ediff-dir-difference-list))
- (define-key ediff-meta-buffer-map "h" 'ediff-mark-for-hiding)
- (define-key
- ediff-meta-buffer-map "x" 'ediff-hide-marked-sessions)
- (define-key ediff-meta-buffer-map "m" 'ediff-mark-for-operation)
- (cond ((ediff-collect-diffs-metajob jobname)
- (define-key
- ediff-meta-buffer-map "P" 'ediff-collect-custom-diffs))
- ((ediff-patch-metajob jobname)
- (define-key
- ediff-meta-buffer-map "P" 'ediff-meta-show-patch)))
- (define-key ediff-meta-buffer-map "u" 'ediff-up-meta-hierarchy)
- (define-key ediff-meta-buffer-map "D" 'ediff-show-dir-diffs)))
-
- (if (eq ediff-metajob-name 'ediff-registry)
- (run-hooks 'ediff-registry-setup-hook)
- (run-hooks 'ediff-session-group-setup-hook))
- ) ; eval in meta-buffer
- meta-buffer))
-
-
-;; this is a setup function for ediff-directories
-;; must return meta-buffer
-(defun ediff-redraw-directory-group-buffer (meta-list)
- ;; extract directories
- (let ((meta-buf (ediff-get-group-buffer meta-list))
- (empty t)
- (sessionNum 0)
- regexp elt session-buf f1 f2 f3 pt
- merge-autostore-dir
- point tmp-list buffer-read-only)
- (ediff-eval-in-buffer meta-buf
- (setq point (point))
- (erase-buffer)
- (insert (format ediff-meta-buffer-message
- (ediff-abbrev-jobname ediff-metajob-name)))
-
- (setq regexp (ediff-get-group-regexp meta-list)
- merge-autostore-dir (ediff-get-group-merge-autostore-dir meta-list))
-
- (cond ((ediff-collect-diffs-metajob)
- (insert
- " `P':\tcollect custom diffs of all marked sessions\n"))
- ((ediff-patch-metajob)
- (insert
- " `P':\tshow patch appropriately for the context (session or group)\n")))
- (insert
- " `u':\tshow parent session group\n")
- (or (ediff-one-filegroup-metajob)
- (insert
- " `D':\tshow differences among directories\n"
- " `=':\tmark identical files in each session\n\n"))
-
- (if (and (stringp regexp) (> (length regexp) 0))
- (insert (format "Filter-through regular expression: %s\n" regexp)))
- (if (and ediff-autostore-merges (ediff-merge-metajob)
- (stringp merge-autostore-dir))
- (insert (format
- "\nMerges are automatically stored in directory: %s\n"
- merge-autostore-dir)))
- (insert "\n
- Size Last modified Name
- -----------------------------------------------------------------------
-
-")
-
- ;; discard info on directories and regexp
- (setq meta-list (cdr meta-list)
- tmp-list meta-list)
- (while (and tmp-list empty)
- (if (and (car tmp-list)
- (not (eq (ediff-get-session-status (car tmp-list)) ?I)))
- (setq empty nil))
- (setq tmp-list (cdr tmp-list)))
-
- (if empty
- (insert
- " ****** ****** This session group has no members\n"))
-
- ;; now organize file names like this:
- ;; use-mark sizeA dateA sizeB dateB filename
- ;; make sure directories are displayed with a trailing slash.
- (while meta-list
- (setq elt (car meta-list)
- meta-list (cdr meta-list)
- sessionNum (1+ sessionNum))
- (if (eq (ediff-get-session-status elt) ?I)
- ()
- (setq session-buf (ediff-get-session-buffer elt)
- f1 (ediff-get-session-objA elt)
- f2 (ediff-get-session-objB elt)
- f3 (ediff-get-session-objC elt))
- (setq pt (point))
- ;; insert markers
- (insert (cond ((null session-buf) " ") ; virgin session
- ((ediff-buffer-live-p session-buf) "+") ;active session
- (t "-"))) ; finished session
- (insert (cond ((ediff-get-session-status elt)) ; session has status,
- ;;; e.g., ?H, ?I
- (t " "))) ; normal session
- (insert " Session " (int-to-string sessionNum) ":\n")
- (ediff-meta-insert-file-info f1)
- (ediff-meta-insert-file-info f2)
- (ediff-meta-insert-file-info f3)
- (ediff-set-meta-overlay pt (point) elt)))
- (set-buffer-modified-p nil)
- (goto-char point)
- meta-buf)))
-
-;; Check if this is a problematic session.
-;; Return nil if not. Otherwise, return symbol representing the problem
-;; At present, problematic sessions occur only in -with-ancestor comparisons
-;; when the ancestor is a directory rather than a file, or when there is no
-;; suitable ancestor file in the ancestor directory
-(defun ediff-problematic-session-p (session)
- (let ((f1 (ediff-get-session-objA-name session))
- (f2 (ediff-get-session-objB-name session))
- (f3 (ediff-get-session-objC-name session)))
- (cond ((and (stringp f1) (not (file-directory-p f1))
- (stringp f2) (not (file-directory-p f2))
- ;; either invalid file name or a directory
- (or (not (stringp f3)) (file-directory-p f3))
- (ediff-ancestor-metajob))
- ;; more may be added later
- 'ancestor-is-dir)
- (t nil))))
-
-(defun ediff-meta-insert-file-info (fileinfo)
- (let ((fname (car fileinfo))
- (feq (ediff-get-file-eqstatus fileinfo))
- file-modtime file-size)
-
- (cond ((not (stringp fname)) (setq file-size -2)) ; file doesn't exits
- ((not (ediff-file-remote-p fname))
- (if (file-exists-p fname)
- ;; set real size and modtime
- (setq file-size (ediff-file-size fname)
- file-modtime (ediff-file-modtime fname))
- (setq file-size -2))) ; file doesn't exist
- ( t (setq file-size -1))) ; remote file
- (if (stringp fname)
- (insert
- (format
- "%s %s %-20s %s\n"
- (if feq "=" " ") ; equality indicator
- (format "%10s" (cond ((= file-size -1) "--")
- ((< file-size -1) "--")
- (t file-size)))
- (cond ((= file-size -1) "*remote file*")
- ((< file-size -1) "*file doesn't exist*")
- (t (ediff-format-date (decode-time file-modtime))))
-
- ;; dir names in meta lists have training slashes, so we just
- ;; abbreviate the file name, if file exists
- (if (and (not (stringp fname)) (< file-size -1))
- "-------" ; file doesn't exist
- (ediff-abbreviate-file-name fname)))))))
-
-(defconst ediff-months '((1 . "Jan") (2 . "Feb") (3 . "Mar") (4 . "Apr")
- (5 . "May") (6 . "Jun") (7 . "Jul") (8 . "Aug")
- (9 . "Sep") (10 . "Oct") (11 . "Nov") (12 . "Dec"))
- "Months' associative array.")
-
-;; returns 2char string
-(defsubst ediff-fill-leading-zero (num)
- (if (< num 10)
- (format "0%d" num)
- (number-to-string num)))
-
-;; TIME is like the output of decode-time
-(defun ediff-format-date (time)
- (format "%s %2d %4d %s:%s:%s"
- (cdr (assoc (nth 4 time) ediff-months)) ; month
- (nth 3 time) ; day
- (nth 5 time) ; year
- (ediff-fill-leading-zero (nth 2 time)) ; hour
- (ediff-fill-leading-zero (nth 1 time)) ; min
- (ediff-fill-leading-zero (nth 0 time)) ; sec
- ))
-
-(defun ediff-draw-dir-diffs (diff-list)
- (if (null diff-list) (error "Lost difference info on these directories"))
- (let* ((buf-name (ediff-unique-buffer-name
- "*Ediff File Group Differences" "*"))
- (regexp (ediff-get-group-regexp diff-list))
- (dir1 (ediff-abbreviate-file-name (ediff-get-group-objA diff-list)))
- (dir2 (ediff-abbreviate-file-name (ediff-get-group-objB diff-list)))
- (dir3 (ediff-get-group-objC diff-list))
- (dir3 (if (stringp dir3) (ediff-abbreviate-file-name dir3)))
- (meta-buf (ediff-get-group-buffer diff-list))
- (underline (make-string 26 ?-))
- file code
- buffer-read-only)
- ;; skip the directory part
- (setq diff-list (cdr diff-list))
- (setq ediff-dir-diffs-buffer (get-buffer-create buf-name))
- (ediff-eval-in-buffer ediff-dir-diffs-buffer
- (use-local-map ediff-dir-diffs-buffer-map)
- (erase-buffer)
- (setq ediff-meta-buffer meta-buf)
- (insert "\t\t*** Directory Differences ***\n")
- (insert "
-Useful commands:
- `q': hide this buffer
- SPC: next line
- DEL: previous line\n\n")
-
- (if (and (stringp regexp) (> (length regexp) 0))
- (insert (format "Filter-through regular expression: %s\n" regexp)))
- (insert "\n")
- (insert (format "\n%-27s%-26s"
- (ediff-truncate-string-left
- (ediff-abbreviate-file-name
- (file-name-as-directory dir1))
- 25)
- (ediff-truncate-string-left
- (ediff-abbreviate-file-name
- (file-name-as-directory dir2))
- 25)))
- (if dir3
- (insert (format " %-25s\n"
- (ediff-truncate-string-left
- (ediff-abbreviate-file-name
- (file-name-as-directory dir3))
- 25)))
- (insert "\n"))
- (insert (format "%s%s" underline underline))
- (if (stringp dir3)
- (insert (format "%s\n\n" underline))
- (insert "\n\n"))
-
- (if (null diff-list)
- (insert "\n\t*** No differences ***\n"))
-
- (while diff-list
- (setq file (car (car diff-list))
- code (cdr (car diff-list))
- diff-list (cdr diff-list))
- (if (= (mod code 2) 0) ; dir1
- (insert (format "%-27s"
- (ediff-truncate-string-left
- (ediff-abbreviate-file-name
- (if (file-directory-p (concat dir1 file))
- (file-name-as-directory file)
- file))
- 24)))
- (insert (format "%-27s" "---")))
- (if (= (mod code 3) 0) ; dir2
- (insert (format "%-26s"
- (ediff-truncate-string-left
- (ediff-abbreviate-file-name
- (if (file-directory-p (concat dir2 file))
- (file-name-as-directory file)
- file))
- 24)))
- (insert (format "%-26s" "---")))
- (if (stringp dir3)
- (if (= (mod code 5) 0) ; dir3
- (insert (format " %-25s"
- (ediff-truncate-string-left
- (ediff-abbreviate-file-name
- (if (file-directory-p (concat dir3 file))
- (file-name-as-directory file)
- file))
- 24)))
- (insert (format " %-25s" "---"))))
- (insert "\n"))
- (setq buffer-read-only t)
- (set-buffer-modified-p nil)) ; eval in diff buffer
- ))
-
-(defun ediff-bury-dir-diffs-buffer ()
- "Bury the directory difference buffer. Display the meta buffer instead."
- (interactive)
- (let ((buf ediff-meta-buffer)
- wind)
- (bury-buffer)
- (if (setq wind (ediff-get-visible-buffer-window buf))
- (select-window wind)
- (set-window-buffer (selected-window) buf))))
-
-;; executes in dir session group buffer
-;; show buffer differences
-(defun ediff-show-dir-diffs ()
- "Display differences among the directories involved in session group."
- (interactive)
- (if (ediff-one-filegroup-metajob)
- (error "This command is inapplicable in the present context"))
- (or (ediff-buffer-live-p ediff-dir-diffs-buffer)
- (ediff-draw-dir-diffs ediff-dir-difference-list))
- (let ((buf ediff-dir-diffs-buffer))
- (other-window 1)
- (set-window-buffer (selected-window) buf)
- (goto-char (point-min))))
-
-(defun ediff-up-meta-hierarchy ()
- "Go to the parent session group buffer."
- (interactive)
- (if (ediff-buffer-live-p ediff-parent-meta-buffer)
- (ediff-show-meta-buffer ediff-parent-meta-buffer)
- (error "This session group has no parent")))
-
-
-;; argument is ignored
-(defun ediff-redraw-registry-buffer (&optional ignore)
- (ediff-eval-in-buffer ediff-registry-buffer
- (let ((point (point))
- elt bufAname bufBname bufCname cur-diff total-diffs pt
- job-name meta-list registry-list buffer-read-only)
- (erase-buffer)
- (insert "This is a registry of all active Ediff sessions.
-
-Useful commands:
- button2, `v', RET over a session record: switch to that session
- `M' over a session record: display the associated session group
- `R' in any Ediff session: display session registry
- SPC:\tnext session
- DEL:\tprevious session
- `E':\tbrowse Ediff on-line manual
- `q':\tbury registry
-
-
-\t\tActive Ediff Sessions:
-\t\t----------------------
-
-")
- ;; purge registry list from dead buffers
- (mapcar (function (lambda (elt)
- (if (not (ediff-buffer-live-p elt))
- (setq ediff-session-registry
- (delq elt ediff-session-registry)))))
- ediff-session-registry)
-
- (if (null ediff-session-registry)
- (insert " ******* No active Ediff sessions *******\n"))
-
- (setq registry-list ediff-session-registry)
- (while registry-list
- (setq elt (car registry-list)
- registry-list (cdr registry-list))
-
- (if (ediff-buffer-live-p elt)
- (if (ediff-eval-in-buffer elt
- (setq job-name ediff-metajob-name
- meta-list ediff-meta-list)
- (and ediff-metajob-name
- (not (eq ediff-metajob-name 'ediff-registry))))
- (progn
- (setq pt (point))
- (insert (format " *group*\t%s: %s\n"
- (buffer-name elt)
- (ediff-abbrev-jobname job-name)))
- (insert (format "\t\t %s %s %s\n"
- (ediff-abbreviate-file-name
- (ediff-get-group-objA meta-list))
- (ediff-abbreviate-file-name
- (if (stringp
- (ediff-get-group-objB meta-list))
- (ediff-get-group-objB meta-list)
- ""))
- (ediff-abbreviate-file-name
- (if (stringp
- (ediff-get-group-objC meta-list))
- (ediff-get-group-objC meta-list)
- ""))))
- (ediff-set-meta-overlay pt (point) elt))
- (progn
- (ediff-eval-in-buffer elt
- (setq bufAname (if (ediff-buffer-live-p ediff-buffer-A)
- (buffer-name ediff-buffer-A)
- "!!!killed buffer!!!")
- bufBname (if (ediff-buffer-live-p ediff-buffer-B)
- (buffer-name ediff-buffer-B)
- "!!!killed buffer!!!")
- bufCname (cond ((not (ediff-3way-job))
- "")
- ((ediff-buffer-live-p ediff-buffer-C)
- (buffer-name ediff-buffer-C))
- (t "!!!killed buffer!!!")))
- (setq total-diffs (format "%-4d" ediff-number-of-differences)
- cur-diff
- (cond ((= ediff-current-difference -1) " _")
- ((= ediff-current-difference
- ediff-number-of-differences)
- " $")
- (t (format
- "%4d" (1+ ediff-current-difference))))
- job-name ediff-job-name))
- ;; back in the meta buf
- (setq pt (point))
- (insert cur-diff "/" total-diffs "\t"
- (buffer-name elt)
- (format ": %s" (ediff-abbrev-jobname job-name)))
- (insert
- "\n\t\t " bufAname " " bufBname " " bufCname "\n")
- (ediff-set-meta-overlay pt (point) elt))))
- ) ; while
- (set-buffer-modified-p nil)
- (goto-char point)
- )))
-
-;; sets overlay around a meta record with 'ediff-meta-info property PROP
-(defun ediff-set-meta-overlay (b e prop)
- (let (overl)
- (setq overl (ediff-make-overlay b e))
- (if ediff-emacs-p
- (ediff-overlay-put overl 'mouse-face 'highlight)
- (ediff-overlay-put overl 'highlight t))
- (ediff-overlay-put overl 'ediff-meta-info prop)))
-
-(defun ediff-mark-for-hiding (unmark)
- "Mark session for hiding. With prefix arg, unmark."
- (interactive "P")
- (let* ((pos (ediff-event-point last-command-event))
- (meta-buf (ediff-event-buffer last-command-event))
- ;; ediff-get-meta-info gives error if meta-buf or pos are invalid
- (info (ediff-get-meta-info meta-buf pos))
- (session-buf (ediff-get-session-buffer info)))
-
- (if (eq (ediff-get-session-status info) ?H)
- (setq unmark t))
- (if unmark
- (ediff-set-session-status info nil)
- (if (ediff-buffer-live-p session-buf)
- (error "Can't hide active session, %s" (buffer-name session-buf)))
- (ediff-set-session-status info ?H))
- (or unmark
- (ediff-next-meta-item 1))
- (ediff-update-meta-buffer meta-buf)
- ))
-
-(defun ediff-mark-for-operation (unmark)
- "Mark session for a group operation. With prefix arg, unmark."
- (interactive "P")
- (let* ((pos (ediff-event-point last-command-event))
- (meta-buf (ediff-event-buffer last-command-event))
- ;; ediff-get-meta-info gives error if meta-buf or pos are invalid
- (info (ediff-get-meta-info meta-buf pos)))
-
- (if (eq (ediff-get-session-status info) ?*)
- (setq unmark t))
- (if unmark
- (ediff-set-session-status info nil)
- (ediff-set-session-status info ?*))
- (or unmark
- (ediff-next-meta-item 1))
- (ediff-update-meta-buffer meta-buf)
- ))
-
-(defun ediff-hide-marked-sessions (unhide)
- "Hide marked sessions. With prefix arg, unhide."
- (interactive "P")
- (let ((grp-buf (ediff-get-group-buffer ediff-meta-list))
- (meta-list (cdr ediff-meta-list))
- (from (if unhide ?I ?H))
- (to (if unhide ?H ?I))
- (numMarked 0)
- active-sessions-exist session-buf elt)
- (while meta-list
- (setq elt (car meta-list)
- meta-list (cdr meta-list)
- session-buf (ediff-get-session-buffer elt))
-
- (if (eq (ediff-get-session-status elt) from)
- (progn
- (setq numMarked (1+ numMarked))
- (if (and (eq to ?I) (buffer-live-p session-buf))
- ;; shouldn't hide active sessions
- (setq active-sessions-exist t)
- (ediff-set-session-status elt to)))))
- (if (> numMarked 0)
- (ediff-update-meta-buffer grp-buf)
- (beep)
- (if unhide
- (message "Nothing to reveal...")
- (message "Nothing to hide...")))
- (if active-sessions-exist
- (message "Note: didn't hide active sessions!"))
- ))
-
-;; Apply OPERATION to marked sessions. Operation expects one argument of type
-;; meta-list member (not the first one), i.e., a regular session description.
-;; Returns number of marked sessions on which operation was performed
-(defun ediff-operate-on-marked-sessions (operation)
- (let ((grp-buf (ediff-get-group-buffer ediff-meta-list))
- (meta-list (cdr ediff-meta-list))
- (marksym ?*)
- (numMarked 0)
- (sessionNum 0)
- elt)
- (while meta-list
- (setq elt (car meta-list)
- meta-list (cdr meta-list)
- sessionNum (1+ sessionNum))
- (if (eq (ediff-get-session-status elt) marksym)
- (save-excursion
- (setq numMarked (1+ numMarked))
- (funcall operation elt sessionNum))))
- (ediff-update-meta-buffer grp-buf) ; just in case
- numMarked
- ))
-
-(defun ediff-append-custom-diff (session sessionNum)
- (or (ediff-collect-diffs-metajob)
- (error "Sorry, I don't do this for everyone..."))
- (let ((session-buf (ediff-get-session-buffer session))
- (meta-diff-buff ediff-meta-diff-buffer)
- (metajob ediff-metajob-name)
- tmp-buf custom-diff-buf)
- (if (ediff-buffer-live-p session-buf)
- (ediff-eval-in-buffer session-buf
- (if (eq ediff-control-buffer session-buf) ; individual session
- (progn
- (ediff-compute-custom-diffs-maybe)
- (setq custom-diff-buf ediff-custom-diff-buffer)))))
-
- (or (ediff-buffer-live-p meta-diff-buff)
- (error "Ediff: something wrong--no multiple diffs buffer"))
-
- (cond ((ediff-buffer-live-p custom-diff-buf)
- (save-excursion
- (set-buffer meta-diff-buff)
- (goto-char (point-max))
- (insert-buffer custom-diff-buf)
- (insert "\n")))
- ((memq metajob '(ediff-directories
- ediff-merge-directories
- ediff-merge-directories-with-ancestor))
- ;; get diffs by calling shell command on ediff-custom-diff-program
- (save-excursion
- (set-buffer (setq tmp-buf (get-buffer-create ediff-tmp-buffer)))
- (erase-buffer)
- (shell-command
- (format "%s %s %s %s"
- ediff-custom-diff-program ediff-custom-diff-options
- (ediff-get-session-objA-name session)
- (ediff-get-session-objB-name session))
- t))
- (save-excursion
- (set-buffer meta-diff-buff)
- (goto-char (point-max))
- (insert-buffer tmp-buf)
- (insert "\n")))
- (t
- (error "Can't make context diff for Session %d" sessionNum )))
- ))
-
-(defun ediff-collect-custom-diffs ()
- "Collect custom diffs of marked sessions in buffer `*Ediff Multifile Diffs*'.
-This operation is defined only for `ediff-directories' and
-`ediff-directory-revisions', since its intent is to produce
-multifile patches. For `ediff-directory-revisions', we insist that
-all marked sessions must be active."
- (interactive)
- (or (ediff-buffer-live-p ediff-meta-diff-buffer)
- (setq ediff-meta-diff-buffer
- (get-buffer-create
- (ediff-unique-buffer-name "*Ediff Multifile Diffs" "*"))))
- (ediff-eval-in-buffer ediff-meta-diff-buffer
- (erase-buffer))
- (if (> (ediff-operate-on-marked-sessions 'ediff-append-custom-diff) 0)
- ;; did something
- (display-buffer ediff-meta-diff-buffer 'not-this-window)
- (beep)
- (message "No marked sessions found")))
-
-(defun ediff-meta-show-patch ()
- "Show the multi-file patch associated with this group session."
- (interactive)
- (let* ((pos (ediff-event-point last-command-event))
- (meta-buf (ediff-event-buffer last-command-event))
- (info (ediff-get-meta-info meta-buf pos 'noerror))
- (patchbuffer ediff-meta-patchbufer))
- (if (ediff-buffer-live-p patchbuffer)
- (ediff-eval-in-buffer patchbuffer
- (save-restriction
- (if (not info)
- (widen)
- (narrow-to-region
- (ediff-get-session-objB-name info)
- (ediff-get-session-objC-name info)))
- (set-buffer (get-buffer-create ediff-tmp-buffer))
- (erase-buffer)
- (insert-buffer patchbuffer)
- (display-buffer ediff-tmp-buffer 'not-this-window)
- ))
- (error "The patch buffer wasn't found"))))
-
-
-;; This function executes in meta buffer. It knows where event happened.
-(defun ediff-filegroup-action ()
- "Execute appropriate action for the selected session."
- (interactive)
- (let* ((pos (ediff-event-point last-command-event))
- (meta-buf (ediff-event-buffer last-command-event))
- ;; ediff-get-meta-info gives error if meta-buf or pos are invalid
- (info (ediff-get-meta-info meta-buf pos))
- merge-autostore-dir
- session-buf file1 file2 file3 regexp)
-
- (setq session-buf (ediff-get-session-buffer info)
- file1 (ediff-get-session-objA-name info)
- file2 (ediff-get-session-objB-name info)
- file3 (ediff-get-session-objC-name info))
-
- ;; make sure we don't start on hidden sessions
- ;; ?H means marked for hiding. ?I means invalid (hidden).
- (if (memq (ediff-get-session-status info) '(?I))
- (progn
- (beep)
- (if (y-or-n-p "This session is marked as hidden, unmark? ")
- (progn
- (ediff-set-session-status info nil)
- (ediff-update-meta-buffer meta-buf))
- (error "Aborted"))))
-
- (ediff-eval-in-buffer meta-buf
- (setq merge-autostore-dir
- (ediff-get-group-merge-autostore-dir ediff-meta-list))
- (goto-char pos) ; if the user clicked on session--move point there
- ;; First handle sessions involving directories (which are themselves
- ;; session groups)
- ;; After that handle individual sessions
- (cond ((and (file-directory-p file1)
- (stringp file2) (file-directory-p file2)
- (if (stringp file3) (file-directory-p file1) t))
- ;; do ediff/ediff-merge on subdirectories
- (if (ediff-buffer-live-p session-buf)
- (ediff-show-meta-buffer session-buf)
- (setq regexp (read-string "Filter through regular expression: "
- nil 'ediff-filtering-regexp-history))
- (ediff-directories-internal
- file1 file2 file3 regexp
- ediff-session-action-function
- ediff-metajob-name
- ;; make it update car info after startup
- (` (list (lambda ()
- ;; child session group should know its parent
- (setq ediff-parent-meta-buffer
- (quote (, ediff-meta-buffer)))
- ;; and parent will know its child
- (setcar (quote (, info)) ediff-meta-buffer)))))))
-
- ;; Do ediff-revision on a subdirectory
- ((and (ediff-one-filegroup-metajob)
- (ediff-revision-metajob)
- (file-directory-p file1))
- (if (ediff-buffer-live-p session-buf)
- (ediff-show-meta-buffer session-buf)
- (setq regexp (read-string "Filter through regular expression: "
- nil 'ediff-filtering-regexp-history))
- (ediff-directory-revisions-internal
- file1 regexp
- ediff-session-action-function ediff-metajob-name
- ;; make it update car info after startup
- (` (list (lambda ()
- ;; child session group should know its parent
- (setq ediff-parent-meta-buffer
- (quote (, ediff-meta-buffer)))
- ;; and parent will know its child
- (setcar (quote (, info)) ediff-meta-buffer)))))))
-
- ;; From here on---only individual session handlers
-
- ;; handle an individual session with a live control buffer
- ((ediff-buffer-live-p session-buf)
- (ediff-eval-in-buffer session-buf
- (setq ediff-mouse-pixel-position (mouse-pixel-position))
- (ediff-recenter 'no-rehighlight)))
-
- ((ediff-problematic-session-p info)
- (beep)
- (if (y-or-n-p
- "This session has no ancestor. Merge without the ancestor? ")
- (ediff-merge-files
- file1 file2
- ;; provide startup hooks
- (` (list (lambda ()
- (setq ediff-meta-buffer (, (current-buffer)))
- (setq ediff-merge-store-file
- (, (concat
- merge-autostore-dir
- "mrg_"
- (file-name-nondirectory file1))))
- ;; make ediff-startup pass
- ;; ediff-control-buffer back to the meta
- ;; level; see below
- (setcar
- (quote (, info)) ediff-control-buffer)))))
- (error "Aborted")))
- ((ediff-one-filegroup-metajob) ; needs 1 file arg
- (funcall ediff-session-action-function
- file1
- ;; provide startup hooks
- (` (list (lambda ()
- (setq ediff-meta-buffer (, (current-buffer)))
- (setq ediff-merge-store-file
- (, (concat
- merge-autostore-dir
- "mrg_"
- (file-name-nondirectory file1))))
- ;; make ediff-startup pass
- ;; ediff-control-buffer back to the meta
- ;; level; see below
- (setcar
- (quote (, info)) ediff-control-buffer))))))
- ((not (ediff-metajob3)) ; need 2 file args
- (funcall ediff-session-action-function
- file1 file2
- ;; provide startup hooks
- (` (list (lambda ()
- (setq ediff-meta-buffer (, (current-buffer)))
- (setq ediff-merge-store-file
- (, (concat
- merge-autostore-dir
- "mrg_"
- (file-name-nondirectory file1))))
- ;; make ediff-startup pass
- ;; ediff-control-buffer back to the meta
- ;; level; see below
- (setcar
- (quote (, info)) ediff-control-buffer))))))
- ((ediff-metajob3) ; need 3 file args
- (funcall ediff-session-action-function
- file1 file2 file3
- ;; arrange startup hooks
- (` (list (lambda ()
- (setq ediff-merge-store-file
- (, (concat
- merge-autostore-dir
- "mrg_"
- (file-name-nondirectory file1))))
- (setq ediff-meta-buffer (, (current-buffer)))
- ;; this arranges that ediff-startup will pass
- ;; the value of ediff-control-buffer back to
- ;; the meta level, to the record in the meta
- ;; list containing the information about the
- ;; session associated with that
- ;; ediff-control-buffer
- (setcar
- (quote (, info)) ediff-control-buffer))))))
- ) ; cond
- ) ; eval in meta-buf
- ))
-
-(defun ediff-registry-action ()
- "Switch to a selected session."
- (interactive)
- (let* ((pos (ediff-event-point last-command-event))
- (buf (ediff-event-buffer last-command-event))
- (ctl-buf (ediff-get-meta-info buf pos)))
-
- (if (ediff-buffer-live-p ctl-buf)
- ;; check if this is ediff-control-buffer or ediff-meta-buffer
- (if (ediff-eval-in-buffer ctl-buf
- (eq (key-binding "q") 'ediff-quit-meta-buffer))
- ;; it's a meta-buffer -- last action should just display it
- (ediff-show-meta-buffer ctl-buf)
- ;; it's a session buffer -- invoke go back to session
- (ediff-eval-in-buffer ctl-buf
- (setq ediff-mouse-pixel-position (mouse-pixel-position))
- (ediff-recenter 'no-rehighlight)))
- (beep)
- (message "You've selected a stale session --- try again")
- (ediff-update-registry))
- (ediff-eval-in-buffer buf
- (goto-char pos))
- ))
-
-
-(defun ediff-show-meta-buffer (&optional meta-buf)
- "Show the session group buffer."
- (interactive)
- (let (wind frame silent)
- (if meta-buf (setq silent t))
-
- (setq meta-buf (or meta-buf ediff-meta-buffer))
- (cond ((not (bufferp meta-buf))
- (error "This Ediff session is not part of a session group"))
- ((not (ediff-buffer-live-p meta-buf))
- (error
- "Can't find this session's group panel -- session itself is ok")))
-
- (ediff-cleanup-meta-buffer meta-buf)
- (ediff-eval-in-buffer meta-buf
- (save-excursion
- (cond ((setq wind (ediff-get-visible-buffer-window meta-buf))
- (or silent
- (message
- "Already showing the group panel for this session"))
- (set-window-buffer wind meta-buf)
- (select-window wind))
- ((window-live-p (setq wind ediff-window-C)) ;in merge--merge buf
- (set-window-buffer ediff-window-C meta-buf)
- (select-window wind))
- ((window-live-p (setq wind ediff-window-A))
- (set-window-buffer ediff-window-A meta-buf)
- (select-window wind))
- ((window-live-p (setq wind ediff-window-B))
- (set-window-buffer ediff-window-B meta-buf)
- (select-window wind))
- ((and
- (setq wind
- (ediff-get-visible-buffer-window ediff-registry-buffer))
- (ediff-window-display-p))
- (select-window wind)
- (other-window 1)
- (set-window-buffer (selected-window) meta-buf))
- (t (ediff-skip-unsuitable-frames 'ok-unsplittable)
- (set-window-buffer (selected-window) meta-buf)))
- ))
- (if (and (ediff-window-display-p)
- (window-live-p
- (setq wind (ediff-get-visible-buffer-window meta-buf))))
- (progn
- (setq frame (window-frame wind))
- (raise-frame frame)
- (ediff-reset-mouse frame)))
- (run-hooks 'ediff-show-session-group-hook)
- ))
-
-(defun ediff-show-meta-buff-from-registry ()
- "Display the session group buffer for a selected session group."
- (interactive)
- (let* ((pos (ediff-event-point last-command-event))
- (meta-buf (ediff-event-buffer last-command-event))
- (info (ediff-get-meta-info meta-buf pos))
- (meta-or-session-buf info))
- (ediff-eval-in-buffer meta-or-session-buf
- (ediff-show-meta-buffer))))
-
-;;;###autoload
-(defun ediff-show-registry ()
- "Display Ediff's registry."
- (interactive)
- (ediff-update-registry)
- (if (not (ediff-buffer-live-p ediff-registry-buffer))
- (error "No active Ediff sessions or corrupted session registry"))
- (let (wind frame)
- ;; for some reason, point moves in ediff-registry-buffer, so we preserve it
- ;; explicitly
- (ediff-eval-in-buffer ediff-registry-buffer
- (save-excursion
- (cond ((setq wind
- (ediff-get-visible-buffer-window ediff-registry-buffer))
- (message "Already showing the registry")
- (set-window-buffer wind ediff-registry-buffer)
- (select-window wind))
- ((window-live-p ediff-window-C)
- (set-window-buffer ediff-window-C ediff-registry-buffer)
- (select-window ediff-window-C))
- ((window-live-p ediff-window-A)
- (set-window-buffer ediff-window-A ediff-registry-buffer)
- (select-window ediff-window-A))
- ((window-live-p ediff-window-B)
- (set-window-buffer ediff-window-B ediff-registry-buffer)
- (select-window ediff-window-B))
- ((and (setq wind
- (ediff-get-visible-buffer-window ediff-meta-buffer))
- (ediff-window-display-p))
- (select-window wind)
- (other-window 1)
- (set-window-buffer (selected-window) ediff-registry-buffer))
- (t (ediff-skip-unsuitable-frames 'ok-unsplittable)
- (set-window-buffer (selected-window) ediff-registry-buffer)))
- ))
- (if (ediff-window-display-p)
- (progn
- (setq frame
- (window-frame
- (ediff-get-visible-buffer-window ediff-registry-buffer)))
- (raise-frame frame)
- (ediff-reset-mouse frame)))
- (run-hooks 'ediff-show-registry-hook)
- ))
-
-;;;###autoload
-(defalias 'eregistry 'ediff-show-registry)
-
-;; If meta-buf doesn't exist, it is created. In that case, id doesn't have a
-;; parent meta-buf
-;; Check if META-BUF exists before calling this function
-(defun ediff-update-meta-buffer (meta-buf)
- (ediff-eval-in-buffer (current-buffer)
- (if (ediff-buffer-live-p meta-buf)
- (ediff-eval-in-buffer meta-buf
- (funcall ediff-meta-redraw-function ediff-meta-list))
- )))
-
-(defun ediff-update-registry ()
- (ediff-eval-in-buffer (current-buffer)
- (if (ediff-buffer-live-p ediff-registry-buffer)
- (ediff-redraw-registry-buffer)
- (ediff-prepare-meta-buffer
- 'ediff-registry-action
- ediff-session-registry
- "*Ediff Registry"
- 'ediff-redraw-registry-buffer
- 'ediff-registry))
- ))
-
-;; If meta-buf exists, it is redrawn along with parent.
-;; Otherwise, nothing happens.
-(defun ediff-cleanup-meta-buffer (meta-buffer)
- (if (ediff-buffer-live-p meta-buffer)
- (ediff-eval-in-buffer meta-buffer
- (ediff-update-meta-buffer meta-buffer)
- (if (ediff-buffer-live-p ediff-parent-meta-buffer)
- (ediff-update-meta-buffer ediff-parent-meta-buffer)))))
-
-;; t if no session in progress
-(defun ediff-safe-to-quit (meta-buffer)
- (if (ediff-buffer-live-p meta-buffer)
- (let ((lis ediff-meta-list)
- (cont t)
- buffer-read-only)
- (ediff-update-meta-buffer meta-buffer)
- (ediff-eval-in-buffer meta-buffer
- (setq lis (cdr lis)) ; discard the description part of meta-list
- (while (and cont lis)
- (if (ediff-buffer-live-p
- (ediff-get-group-buffer lis)) ; in progress
- (setq cont nil))
- (setq lis (cdr lis)))
- cont))))
-
-(defun ediff-quit-meta-buffer ()
- "If the group has no active session, delete the meta buffer.
-If no session is in progress, ask to confirm before deleting meta buffer.
-Otherwise, bury the meta buffer.
-If this is a session registry buffer then just bury it."
- (interactive)
- (let* ((buf (current-buffer))
- (dir-diffs-buffer ediff-dir-diffs-buffer)
- (meta-diff-buffer ediff-meta-diff-buffer)
- (parent-buf ediff-parent-meta-buffer)
- (dont-show-registry (eq buf ediff-registry-buffer)))
- (if dont-show-registry
- (bury-buffer)
- (ediff-cleanup-meta-buffer buf)
- (cond ((and (ediff-safe-to-quit buf)
- (y-or-n-p "Quit this session group? "))
- (run-hooks 'ediff-quit-session-group-hook)
- (message "")
- (ediff-dispose-of-meta-buffer buf))
- ((ediff-safe-to-quit buf)
- (bury-buffer))
- (t
- (error
- "This session group has active sessions---cannot exit")))
- (ediff-cleanup-meta-buffer parent-buf)
- (ediff-kill-buffer-carefully dir-diffs-buffer)
- (ediff-kill-buffer-carefully meta-diff-buffer)
- (if (ediff-buffer-live-p parent-buf)
- (progn
- (setq dont-show-registry t)
- (ediff-show-meta-buffer parent-buf)))
- )
- (or dont-show-registry
- (ediff-show-registry))))
-
-(defun ediff-dispose-of-meta-buffer (buf)
- (setq ediff-session-registry (delq buf ediff-session-registry))
- (ediff-eval-in-buffer buf
- (if (ediff-buffer-live-p ediff-dir-diffs-buffer)
- (kill-buffer ediff-dir-diffs-buffer)))
- (kill-buffer buf))
-
-
-;; Obtain information on a meta record where the user clicked or typed
-;; BUF is the buffer where this happened and POINT is the position
-;; If optional NOERROR arg is given, don't report error and return nil if no
-;; meta info is found on line.
-(defun ediff-get-meta-info (buf point &optional noerror)
- (let (result olist tmp)
- (if (and point (ediff-buffer-live-p buf))
- (ediff-eval-in-buffer buf
- (if ediff-xemacs-p
- (setq result
- (if (setq tmp (extent-at point buf 'ediff-meta-info))
- (ediff-overlay-get tmp 'ediff-meta-info)))
- (setq olist (overlays-at point))
- (setq olist
- (mapcar (function (lambda (elt)
- (overlay-get elt 'ediff-meta-info)))
- olist))
- (while (and olist (null (car olist))
- (overlay-get (car olist) 'invisible))
- (setq olist (cdr olist)))
- (setq result (car olist)))))
- (if result
- result
- (if noerror
- nil
- (ediff-update-registry)
- (error "No session info in this line")))))
-
-;; return location of the next meta overlay after point
-(defun ediff-next-meta-overlay-start (point)
- (if (eobp)
- (goto-char (point-min))
- (let (overl)
- (if ediff-xemacs-p
- (progn
- (setq overl (extent-at point (current-buffer) 'ediff-meta-info))
- (if overl
- (setq overl (next-extent overl))
- (setq overl (next-extent (current-buffer))))
- (if overl
- (extent-start-position overl)
- (point-max)))
- (setq overl (car (overlays-at point)))
- (if (and overl (overlay-get overl 'ediff-meta-info))
- ;; note: end of current overlay is the beginning of the next one
- (overlay-end overl)
- (next-overlay-change point))))
- ))
-
-(defun ediff-previous-meta-overlay-start (point)
- (if (bobp)
- (goto-char (point-max))
- (let (overl)
- (if ediff-xemacs-p
- (progn
- (setq overl (extent-at point (current-buffer) 'ediff-meta-info))
- (if overl
- (setq overl (previous-extent overl))
- (setq overl (previous-extent (current-buffer))))
- (if overl
- (extent-start-position overl)
- (point-min)))
- (setq overl (car (overlays-at point)))
- (if (and overl (overlay-get overl 'ediff-meta-info))
- (setq point (overlay-start overl)))
- ;; to get to the beginning of prev overlay
- (if (not (bobp))
- ;; trickery to overcome an emacs bug--doesn't always find previous
- ;; overlay change correctly
- (setq point (1- point)))
- (setq point (previous-overlay-change point))
- ;; If we are not over an overlay after subtracting 1, it means we are
- ;; in the description area preceding session records. In this case,
- ;; goto the top of the registry buffer.
- (or (car (overlays-at point))
- (setq point (point-min)))
- point
- ))))
-
-;; this is the action invoked when the user selects a patch from the meta
-;; buffer.
-(defun ediff-patch-file-form-meta (file &optional startup-hooks)
- (let* ((pos (ediff-event-point last-command-event))
- (meta-buf (ediff-event-buffer last-command-event))
- ;; ediff-get-meta-info gives error if meta-buf or pos are invalid
- (info (ediff-get-meta-info meta-buf pos))
- (meta-patchbuf ediff-meta-patchbufer)
- session-buf beg-marker end-marker)
-
- (if (or (file-directory-p file) (string-match "/dev/null" file))
- (error "`%s' is not an ordinary file" (file-name-as-directory file)))
- (setq session-buf (ediff-get-session-buffer info)
- beg-marker (ediff-get-session-objB-name info)
- end-marker (ediff-get-session-objC-name info))
-
- (or (ediff-buffer-live-p session-buf) ; either an active patch session
- (null session-buf) ; or it is a virgin session
- (error
- "Patch has been already applied to this file--cannot be repeated!"))
-
- (ediff-eval-in-buffer meta-patchbuf
- (save-restriction
- (widen)
- (narrow-to-region beg-marker end-marker)
- (ediff-patch-file-internal meta-patchbuf file startup-hooks)))))
-
-
-(defun ediff-meta-mark-equal-files ()
- "Run though the session list and mark identical files.
-This is used only for sessions that involve 2 or 3 files at the same time."
- (interactive)
- (let ((list (cdr ediff-meta-list))
- fileinfo1 fileinfo2 fileinfo3 elt)
- (while (setq elt (car list))
- (setq fileinfo1 (ediff-get-session-objA elt)
- fileinfo2 (ediff-get-session-objB elt)
- fileinfo3 (ediff-get-session-objC elt))
- (ediff-set-file-eqstatus fileinfo1 nil)
- (ediff-set-file-eqstatus fileinfo2 nil)
- (ediff-set-file-eqstatus fileinfo3 nil)
-
- (ediff-mark-if-equal fileinfo1 fileinfo2)
- (if (ediff-metajob3)
- (progn
- (ediff-mark-if-equal fileinfo1 fileinfo3)
- (ediff-mark-if-equal fileinfo2 fileinfo3)))
- (setq list (cdr list))))
- (ediff-update-meta-buffer (current-buffer)))
-
-;; mark files 1 and 2 as equal, if they are.
-(defun ediff-mark-if-equal (fileinfo1 fileinfo2)
- (get-buffer-create ediff-tmp-buffer)
- (or (file-directory-p (car fileinfo1))
- (file-directory-p (car fileinfo2))
- (if (= (ediff-make-diff2-buffer
- ediff-tmp-buffer (car fileinfo1) (car fileinfo2))
- 0)
- (progn
- (ediff-set-file-eqstatus fileinfo1 t)
- (ediff-set-file-eqstatus fileinfo2 t)))))
-
-
-
-;;; Local Variables:
-;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
-;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
-;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
-;;; End:
-
-(provide 'ediff-mult)
-(require 'ediff-util)
-
-;;; ediff-mult.el ends here
diff --git a/lisp/ediff-ptch.el b/lisp/ediff-ptch.el
deleted file mode 100644
index 309316d721e..00000000000
--- a/lisp/ediff-ptch.el
+++ /dev/null
@@ -1,630 +0,0 @@
-;;; ediff-ptch.el --- Ediff's patch support
-
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Michael Kifer <kifer@cs.sunysb.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-
-;;; Code:
-
-(require 'ediff-init)
-
-(defvar ediff-last-dir-patch nil
- "Last directory used by an Ediff command for file to patch.")
-
-(defvar ediff-backup-extension
- (if (memq system-type '(vax-vms axp-vms emx ms-dos windows-nt windows-95))
- "_orig" ".orig")
- "Backup extension used by the patch program.
-See also `ediff-backup-specs'.")
-
-(defvar ediff-backup-specs (format "-b %s" ediff-backup-extension)
- "*Backup directives to pass to the patch program.
-Ediff requires that the old version of the file \(before applying the patch\)
-is saved in a file named `the-patch-file.extension'. Usually `extension' is
-`.orig', but this can be changed by the user and may depend on the system.
-Therefore, Ediff needs to know the backup extension used by the patch program.
-
-Some versions of the patch program let you specify `-b backup-extension'.
-Other versions only permit `-b', which assumes some canned extension
- \(usually `.orig'\).
-
-Note that both `ediff-backup-extension' and `ediff-backup-specs'
-must be properly set. If your patch program takes the option `-b',
-but not `-b extension', the variable `ediff-backup-extension' must
-still be set so Ediff will know which extension to use.")
-
-
-(defvar ediff-patch-default-directory nil
- "*Default directory to look for patches.")
-
-(defvar ediff-context-diff-label-regexp
- (concat "\\(" ; context diff 2-liner
- "^\\*\\*\\* \\([^ \t]+\\)[^*]+[\t ]*\n--- \\([^ \t]+\\)"
- "\\|" ; GNU unified format diff 2-liner
- "^--- \\([^ \t]+\\)[\t ]+.*\n\\+\\+\\+ \\([^ \t]+\\)"
- "\\)")
- "*Regexp matching filename 2-liners at the start of each context diff.")
-
-(defvar ediff-patch-program "patch"
- "*Name of the program that applies patches.
-It is recommended to use GNU-compatible versions.")
-(defvar ediff-patch-options "-f"
- "*Options to pass to ediff-patch-program.
-
-Note: the `-b' option should be specified in `ediff-backup-specs'.
-
-It is recommended to pass the `-f' option to the patch program, so it won't ask
-questions. However, some implementations don't accept this option, in which
-case the default value for this variable should be changed.")
-
-;; The buffer of the patch file. Local to control buffer.
-(ediff-defvar-local ediff-patchbufer nil "")
-
-;; The buffer where patch displays its diagnostics.
-(ediff-defvar-local ediff-patch-diagnostics nil "")
-
-;; Map of patch buffer. Has the form:
-;; ((filename1 marker1 marker2) (filename2 marker1 marker2) ...)
-;; where filenames are files to which patch would have applied the patch;
-;; marker1 delimits the beginning of the corresponding patch and marker2 does
-;; it for the end.
-(ediff-defvar-local ediff-patch-map nil "")
-
-;; strip prefix from filename
-;; returns /dev/null, if can't strip prefix
-(defsubst ediff-file-name-sans-prefix (filename prefix)
- (save-match-data
- (if (string-match (concat "^" prefix) filename)
- (substring filename (match-end 0))
- (concat "/null/" filename))))
-
-
-
-;; no longer used
-;; return the number of matches of regexp in buf starting from the beginning
-(defun ediff-count-matches (regexp buf)
- (ediff-eval-in-buffer buf
- (let ((count 0) opoint)
- (save-excursion
- (goto-char (point-min))
- (while (and (not (eobp))
- (progn (setq opoint (point))
- (re-search-forward regexp nil t)))
- (if (= opoint (point))
- (forward-char 1)
- (setq count (1+ count)))))
- count)))
-
-;; Scan BUF (which is supposed to contain a patch) and make a list of the form
-;; ((filename1 marker1 marker2) (filename2 marker1 marker2) ...)
-;; where filenames are files to which patch would have applied the patch;
-;; marker1 delimits the beginning of the corresponding patch and marker2 does
-;; it for the end. This list is then assigned to ediff-patch-map.
-;; Returns the number of elements in the list ediff-patch-map
-(defun ediff-map-patch-buffer (buf)
- (ediff-eval-in-buffer buf
- (let ((count 0)
- (mark1 (move-marker (make-marker) (point-min)))
- (mark1-end (point-min))
- (possible-file-names '("/dev/null" . "/dev/null"))
- mark2-end mark2 filenames
- beg1 beg2 end1 end2
- patch-map opoint)
- (save-excursion
- (goto-char (point-min))
- (setq opoint (point))
- (while (and (not (eobp))
- (re-search-forward ediff-context-diff-label-regexp nil t))
- (if (= opoint (point))
- (forward-char 1) ; ensure progress towards the end
- (setq mark2 (move-marker (make-marker) (match-beginning 0))
- mark2-end (match-end 0)
- beg1 (or (match-beginning 2) (match-beginning 4))
- end1 (or (match-end 2) (match-end 4))
- beg2 (or (match-beginning 3) (match-beginning 5))
- end2 (or (match-end 3) (match-end 5)))
- ;; possible-file-names is holding the new file names until we
- ;; insert the old file name in the patch map
- ;; It is a pair (filename from 1st header line . fn from 2nd line)
- (setq possible-file-names
- (cons (if (and beg1 end1)
- (buffer-substring beg1 end1)
- "/dev/null")
- (if (and beg2 end2)
- (buffer-substring beg2 end2)
- "/dev/null")))
- ;; check for any `Index:' or `Prereq:' lines, but don't use them
- (if (re-search-backward "^Index:" mark1-end 'noerror)
- (move-marker mark2 (match-beginning 0)))
- (if (re-search-backward "^Prereq:" mark1-end 'noerror)
- (move-marker mark2 (match-beginning 0)))
-
- (goto-char mark2-end)
-
- (if filenames
- (setq patch-map (cons (list filenames mark1 mark2) patch-map)))
- (setq mark1 mark2
- mark1-end mark2-end
- filenames possible-file-names))
- (setq opoint (point)
- count (1+ count))))
- (setq mark2 (point-max-marker)
- patch-map (cons (list possible-file-names mark1 mark2) patch-map))
- (setq ediff-patch-map (nreverse patch-map))
- count)))
-
-;; Fix up the file names in the list using the argument FILENAME
-;; Algorithm: find the first file's directory and cut it out from each file
-;; name in the patch. Prepend the directory of FILENAME to each file in the
-;; patch. In addition, the first file in the patch is replaced by FILENAME.
-;; Each file is actually a file-pair of files found in the context diff header
-;; In the end, for each pair, we select the shortest existing file.
-;; Note: Ediff doesn't recognize multi-file patches that are separated
-;; with the `Index:' line. It treats them as a single-file patch.
-;;
-;; Executes inside the patch buffer
-(defun ediff-fixup-patch-map (filename)
- (setq filename (expand-file-name filename))
- (let ((actual-dir (if (file-directory-p filename)
- ;; directory part of filename
- (file-name-as-directory filename)
- (file-name-directory filename)))
- ;; directory part of the first file in the patch
- (base-dir1 (file-name-directory (car (car (car ediff-patch-map)))))
- (base-dir2 (file-name-directory (cdr (car (car ediff-patch-map)))))
- )
-
- ;; chop off base-dirs
- (mapcar (function (lambda (triple)
- (or (string= (car (car triple)) "/dev/null")
- (setcar (car triple)
- (ediff-file-name-sans-prefix
- (car (car triple)) base-dir1)))
- (or (string= (cdr (car triple)) "/dev/null")
- (setcdr (car triple)
- (ediff-file-name-sans-prefix
- (cdr (car triple)) base-dir2)))
- ))
- ediff-patch-map)
-
- ;; take the given file name into account
- (or (file-directory-p filename)
- (string= "/dev/null" filename)
- (progn
- (setcar (car ediff-patch-map)
- (cons (file-name-nondirectory filename)
- (file-name-nondirectory filename)))))
-
- ;; prepend actual-dir
- (mapcar (function (lambda (triple)
- (if (and (string-match "^/null/" (car (car triple)))
- (string-match "^/null/" (cdr (car triple))))
- ;; couldn't strip base-dir1 and base-dir2
- ;; hence, something wrong
- (progn
- (with-output-to-temp-buffer ediff-msg-buffer
- (princ
- (format "
-The patch file contains a context diff for
-
- %s
- %s
-
-However, Ediff cannot infer the name of the actual file
-to be patched on your system. If you know the correct file name,
-please enter it now.
-
-If you don't know and still would like to apply patches to
-other files, enter /dev/null
-"
- (substring (car (car triple)) 6)
- (substring (cdr (car triple)) 6))))
- (let ((directory t)
- user-file)
- (while directory
- (setq user-file
- (read-file-name
- "Please enter file name: "
- actual-dir actual-dir t))
- (if (not (file-directory-p user-file))
- (setq directory nil)
- (setq directory t)
- (beep)
- (message "%s is a directory" user-file)
- (sit-for 2)))
- (setcar triple (cons user-file user-file))))
- (setcar (car triple)
- (expand-file-name
- (concat actual-dir (car (car triple)))))
- (setcdr (car triple)
- (expand-file-name
- (concat actual-dir (cdr (car triple))))))
- ))
- ediff-patch-map)
- ;; check for the shorter existing file in each pair and discard the other
- ;; one
- (mapcar (function (lambda (triple)
- (let* ((file1 (car (car triple)))
- (file2 (cdr (car triple)))
- (f1-exists (file-exists-p file1))
- (f2-exists (file-exists-p file2)))
- (cond
- ((and (< (length file2) (length file1))
- f2-exists)
- (setcar triple file2))
- ((and (< (length file1) (length file2))
- f1-exists)
- (setcar triple file1))
- ((and f1-exists f2-exists
- (string= file1 file2))
- (setcar triple file1))
- ((and f1-exists f2-exists)
- (with-output-to-temp-buffer ediff-msg-buffer
- (princ (format "
-Ediff has inferred that
- %s
- %s
-are possible targets for applying the patch.
-Both files seem to be plausible alternatives.
-
-Please advice:
- Type `y' to use %s as the target;
- Type `n' to use %s as the target.
-"
- file1 file2 file2 file1)))
- (setcar triple
- (if (y-or-n-p (format "Use %s ? " file2))
- file2 file1)))
- (f2-exists (setcar triple file2))
- (f1-exists (setcar triple file1))
- (t
- (with-output-to-temp-buffer ediff-msg-buffer
- (princ (format "
-Ediff inferred that
- %s
- %s
-are possible alternative targets for this patch.
-
-However, these files do not exist.
-
-Please enter an alternative patch target ...
-"
- file1 file2)))
- (let ((directory t)
- target)
- (while directory
- (setq target (read-file-name
- "Please enter a patch target: "
- actual-dir actual-dir t))
- (if (not (file-directory-p target))
- (setq directory nil)
- (beep)
- (message "%s is a directory" target)
- (sit-for 2)))
- (setcar triple target)))))))
- ediff-patch-map)
- ))
-
-(defun ediff-show-patch-diagnostics ()
- (interactive)
- (cond ((window-live-p ediff-window-A)
- (set-window-buffer ediff-window-A ediff-patch-diagnostics))
- ((window-live-p ediff-window-B)
- (set-window-buffer ediff-window-B ediff-patch-diagnostics))
- (t (display-buffer ediff-patch-diagnostics 'not-this-window))))
-
-(defun ediff-get-patch-buffer ()
- "Obtain patch buffer. If patch is already in a buffer---use it.
-Else, read patch file into a new buffer."
- (let ((dir (cond (ediff-patch-default-directory) ; try patch default dir
- (ediff-use-last-dir ediff-last-dir-patch)
- (t default-directory)))
- patch-buf)
- (if (y-or-n-p "Is the patch already in a buffer? ")
- (setq patch-buf
- (get-buffer
- (read-buffer
- "Which buffer contains the patch? "
- (current-buffer) 'must-match)))
- (setq patch-buf
- (find-file-noselect
- (read-file-name "Which file contains the patch? "
- dir nil 'must-match))))
-
- (ediff-eval-in-buffer patch-buf
- (goto-char (point-min))
- (or (ediff-get-visible-buffer-window patch-buf)
- (progn
- (pop-to-buffer patch-buf 'other-window)
- (select-window (previous-window)))))
- (ediff-map-patch-buffer patch-buf)
- patch-buf))
-
-;; Dispatch the right patch file function: regular or meta-level,
-;; depending on how many patches are in the patch file.
-;; At present, there is no support for meta-level patches.
-;; Should return either the ctl buffer or the meta-buffer
-(defun ediff-dispatch-file-patching-job (patch-buf filename
- &optional startup-hooks)
- (ediff-eval-in-buffer patch-buf
- ;; relativize names in the patch with respect to source-file
- (ediff-fixup-patch-map filename)
- (if (< (length ediff-patch-map) 2)
- (ediff-patch-file-internal
- patch-buf
- (if (and (not (string-match "^/dev/null" (car (car ediff-patch-map))))
- (> (length (car (car ediff-patch-map))) 1))
- (car (car ediff-patch-map))
- filename)
- startup-hooks)
- (ediff-multi-patch-internal patch-buf startup-hooks))
- ))
-
-
-(defun ediff-patch-buffer-internal (patch-buf buf-to-patch-name
- &optional startup-hooks)
- (let* ((buf-to-patch (get-buffer buf-to-patch-name))
- (file-name-ok (if buf-to-patch (buffer-file-name buf-to-patch)))
- (buf-mod-status (buffer-modified-p buf-to-patch))
- (multifile-patch-p (> (length (ediff-eval-in-buffer patch-buf
- ediff-patch-map)) 1))
- default-dir file-name ctl-buf)
- (if file-name-ok
- (setq file-name file-name-ok)
- (if multifile-patch-p
- (error
- "Can't apply multi-file patches to buffers that visit no files"))
- (ediff-eval-in-buffer buf-to-patch
- (setq default-dir default-directory)
- (setq file-name (ediff-make-temp-file buf-to-patch))
- (set-visited-file-name file-name)
- (setq buffer-auto-save-file-name nil) ; don't create auto-save file
- ;;don't confuse the user with a new bufname
- (rename-buffer buf-to-patch-name)
- (set-buffer-modified-p nil)
- (set-visited-file-modtime) ; sync buffer and temp file
- (setq default-directory default-dir)
- ))
-
- ;; dispatch a patch function
- (setq ctl-buf (ediff-dispatch-file-patching-job
- patch-buf file-name startup-hooks))
-
- (if file-name-ok
- ()
- ;; buffer wasn't visiting any file,
- ;; so we will not run meta-level ediff here
- (ediff-eval-in-buffer ctl-buf
- (delete-file (buffer-file-name ediff-buffer-A))
- (delete-file (buffer-file-name ediff-buffer-B))
- (ediff-eval-in-buffer ediff-buffer-A
- (if default-dir (setq default-directory default-dir))
- (set-visited-file-name nil)
- (rename-buffer buf-to-patch-name)
- (set-buffer-modified-p buf-mod-status))
- (ediff-eval-in-buffer ediff-buffer-B
- (setq buffer-auto-save-file-name nil) ; don't create auto-save file
- (if default-dir (setq default-directory default-dir))
- (set-visited-file-name nil)
- (rename-buffer (ediff-unique-buffer-name
- (concat buf-to-patch-name "_patched") ""))
- (set-buffer-modified-p t))))
- ))
-
-(defun ediff-patch-file-internal (patch-buf source-filename
- &optional startup-hooks)
- (setq source-filename (expand-file-name source-filename))
-
- (let* ((shell-file-name ediff-shell)
- (patch-diagnostics (get-buffer-create "*ediff patch diagnostics*"))
- ;; ediff-find-file may use a temp file to do the patch
- ;; so, we save source-filename and true-source-filename as a var
- ;; that initially is source-filename but may be changed to a temp
- ;; file for the purpose of patching.
- (true-source-filename source-filename)
- (target-filename source-filename)
- target-buf buf-to-patch file-name-magic-p
- patch-return-code ctl-buf backup-style aux-wind)
-
- (if (string-match "-V" ediff-patch-options)
- (error
- "Ediff doesn't take the -V option in `ediff-patch-options'--sorry"))
-
- ;; Make a temp file, if source-filename has a magic file handler (or if
- ;; it is handled via auto-mode-alist and similar magic).
- ;; Check if there is a buffer visiting source-filename and if they are in
- ;; sync; arrange for the deletion of temp file.
- (ediff-find-file 'true-source-filename 'buf-to-patch
- 'ediff-last-dir-patch 'startup-hooks)
-
- ;; Check if source file name has triggered black magic, such as file name
- ;; handlers or auto mode alist, and make a note of it.
- ;; true-source-filename should be either the original name or a
- ;; temporary file where we put the after-product of the file handler.
- (setq file-name-magic-p (not (equal (file-truename true-source-filename)
- (file-truename source-filename))))
-
- ;; Checkout orig file, if necessary, so that the patched file
- ;; could be checked back in.
- (ediff-maybe-checkout buf-to-patch)
-
- (ediff-eval-in-buffer patch-diagnostics
- (insert-buffer patch-buf)
- (message "Applying patch ... ")
- ;; fix environment for gnu patch, so it won't make numbered extensions
- (setq backup-style (getenv "VERSION_CONTROL"))
- (setenv "VERSION_CONTROL" nil)
- (setq patch-return-code
- (call-process-region
- (point-min) (point-max)
- shell-file-name
- t ; delete region (which contains the patch
- t ; insert output (patch diagnostics) in current buffer
- nil ; don't redisplay
- shell-command-switch ; usually -c
- (format "%s %s %s %s"
- ediff-patch-program
- ediff-patch-options
- ediff-backup-specs
- (expand-file-name true-source-filename))
- ))
-
- ;; restore environment for gnu patch
- (setenv "VERSION_CONTROL" backup-style))
-
- (message "Applying patch ... done")
- (message "")
-
- (switch-to-buffer patch-diagnostics)
- (sit-for 0) ; synchronize - let the user see diagnostics
-
- (or (and (eq patch-return-code 0) ; patch reported success
- (file-exists-p
- (concat true-source-filename ediff-backup-extension)))
- (progn
- (with-output-to-temp-buffer ediff-msg-buffer
- (princ (format "
-Patch has failed OR the backup version of the patched file was not created by
-the patch program.
-
-One reason may be that the values of the variables
-
- ediff-patch-options = %S
- ediff-backup-extension = %S
- ediff-backup-specs = %S
-
-are not appropriate for the program specified in the variable
-
- ediff-patch-program = %S
-
-Another reason could be that the %S program doesn't understand
-the format of the patch file you used.
-
-See Ediff on-line manual for more details on these variables.
-\(Or use a GNU-compatible patch program and stay out of trouble.\)
-
-Type any key to continue...
-"
- ediff-patch-options
- ediff-backup-extension
- ediff-backup-specs
- ediff-patch-program
- ediff-patch-program)))
- (beep 1)
- (if (setq aux-wind (get-buffer-window ediff-msg-buffer))
- (progn
- (select-window aux-wind)
- (goto-char (point-max))))
- (read-char-exclusive)
- (if aux-wind (bury-buffer)) ; ediff-msg-buffer
- (if (setq aux-wind (get-buffer-window patch-diagnostics))
- (progn
- (select-window aux-wind)
- (bury-buffer)))
- (error "Patch appears to have failed")))
-
- ;; If black magic is involved, apply patch to a temp copy of the
- ;; file. Otherwise, apply patch to the orig copy. If patch is applied
- ;; to temp copy, we name the result old-name_patched for local files
- ;; and temp-copy_patched for remote files. The orig file name isn't
- ;; changed, and the temp copy of the original is later deleted.
- ;; Without magic, the original file is renamed (usually into
- ;; old-name_orig) and the result of patching will have the same name as
- ;; the original.
- (if (not file-name-magic-p)
- (ediff-eval-in-buffer buf-to-patch
- (set-visited-file-name
- (concat source-filename ediff-backup-extension))
- (set-buffer-modified-p nil))
-
- ;; Black magic in effect.
- ;; If orig file was remote, put the patched file in the temp directory.
- ;; If orig file is local, put the patched file in the directory of
- ;; the orig file.
- (setq target-filename
- (concat
- (if (ediff-file-remote-p (file-truename source-filename))
- true-source-filename
- source-filename)
- "_patched"))
-
- (rename-file true-source-filename target-filename t)
-
- ;; arrange that the temp copy of orig will be deleted
- (rename-file (concat true-source-filename ediff-backup-extension)
- true-source-filename t))
-
- ;; make orig buffer read-only
- (setq startup-hooks
- (cons 'ediff-set-read-only-in-buf-A startup-hooks))
-
- ;; set up a buf for the patched file
- (setq target-buf (find-file-noselect target-filename))
-
- (setq ctl-buf
- (ediff-buffers-internal
- buf-to-patch target-buf nil
- startup-hooks 'epatch))
- (ediff-eval-in-buffer ctl-buf
- (setq ediff-patchbufer patch-buf
- ediff-patch-diagnostics patch-diagnostics))
-
- (bury-buffer patch-diagnostics)
- (message "Type `P', if you need to see patch diagnostics")
- ctl-buf))
-
-(defun ediff-multi-patch-internal (patch-buf &optional startup-hooks)
- (let (meta-buf)
- (setq startup-hooks
- ;; this sets various vars in the meta buffer inside
- ;; ediff-prepare-meta-buffer
- (cons (` (lambda ()
- ;; tell what to do if the user clicks on a session record
- (setq ediff-session-action-function
- 'ediff-patch-file-form-meta
- ediff-meta-patchbufer patch-buf)
- ))
- startup-hooks))
- (setq meta-buf (ediff-prepare-meta-buffer
- 'ediff-filegroup-action
- (ediff-eval-in-buffer patch-buf
- ;; nil replaces a regular expression
- (cons (list nil (format "%S" patch-buf))
- ediff-patch-map))
- "*Ediff Session Group Panel"
- 'ediff-redraw-directory-group-buffer
- 'ediff-multifile-patch
- startup-hooks))
- (ediff-show-meta-buffer meta-buf)
- ))
-
-
-
-
-;;; Local Variables:
-;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
-;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
-;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
-;;; End:
-
-(provide 'ediff-ptch)
-
-;;; ediff-ptch.el ends here
diff --git a/lisp/ediff-util.el b/lisp/ediff-util.el
deleted file mode 100644
index 0a625aa14df..00000000000
--- a/lisp/ediff-util.el
+++ /dev/null
@@ -1,3599 +0,0 @@
-;;; ediff-util.el --- the core commands and utilities of ediff
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Michael Kifer <kifer@cs.sunysb.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;; Pacify compiler and avoid the need in checking for boundp
-(defvar ediff-patch-diagnostics nil)
-(defvar ediff-patchbufer nil)
-(and noninteractive
- (eval-when-compile
- (let ((load-path (cons (expand-file-name ".") load-path)))
- (load-file "ediff-init.el")
- (load-file "ediff-help.el"))))
-;; end pacifier
-
-(require 'ediff-init)
-(require 'ediff-help)
-(require 'ediff-mult)
-
-;;(if ediff-xemacs-p
-;; (require 'ediff-tbar)
-;; (defun ediff-use-toolbar-p () nil))
-;;
-;; for the time being
-(defun ediff-use-toolbar-p () nil)
-
-
-;;; Functions
-
-(defun ediff-mode ()
- "Ediff mode controls all operations in a single Ediff session.
-This mode is entered through one of the following commands:
- `ediff'
- `ediff-files'
- `ediff-buffers'
- `ebuffers'
- `ediff3'
- `ediff-files3'
- `ediff-buffers3'
- `ebuffers3'
- `ediff-merge'
- `ediff-merge-files'
- `ediff-merge-files-with-ancestor'
- `ediff-merge-buffers'
- `ediff-merge-buffers-with-ancestor'
- `ediff-merge-revisions'
- `ediff-merge-revisions-with-ancestor'
- `ediff-windows-wordwise'
- `ediff-windows-linewise'
- `ediff-regions-wordwise'
- `ediff-regions-linewise'
- `epatch'
- `ediff-patch-file'
- `ediff-patch-buffer'
- `epatch-buffer'
- `ediff-revision'
-
-Commands:
-\\{ediff-mode-map}"
- (kill-all-local-variables)
- (setq major-mode 'ediff-mode)
- (setq mode-name "Ediff")
- (run-hooks 'ediff-mode-hook))
-
-
-(require 'ediff-diff)
-(require 'ediff-merg)
-
-
-;;; Build keymaps
-
-(ediff-defvar-local ediff-mode-map nil
- "Local keymap used in Ediff mode.
-This is local to each Ediff Control Panel, so they may vary from invocation
-to invocation.")
-
-;; Set up the keymap in the control buffer
-(defun ediff-set-keys ()
- "Set up Ediff keymap, if necessary."
- (if (null ediff-mode-map)
- (ediff-setup-keymap))
- (use-local-map ediff-mode-map))
-
-;; Reload Ediff keymap. For debugging only.
-(defun ediff-reload-keymap ()
- (interactive)
- (setq ediff-mode-map nil)
- (ediff-set-keys))
-
-
-(defun ediff-setup-keymap ()
- "Set up the keymap used in the control buffer of Ediff."
- (setq ediff-mode-map (make-sparse-keymap))
- (suppress-keymap ediff-mode-map)
-
- (define-key ediff-mode-map
- (if ediff-emacs-p [mouse-2] [button2]) 'ediff-help-for-quick-help)
- (define-key ediff-mode-map "\C-m" 'ediff-help-for-quick-help)
-
- (define-key ediff-mode-map "p" 'ediff-previous-difference)
- (define-key ediff-mode-map "\C-?" 'ediff-previous-difference)
- (define-key ediff-mode-map [backspace] 'ediff-previous-difference)
- (define-key ediff-mode-map [delete] 'ediff-previous-difference)
- (define-key ediff-mode-map "\C-h" (if ediff-no-emacs-help-in-control-buffer
- 'ediff-previous-difference nil))
- (define-key ediff-mode-map "n" 'ediff-next-difference)
- (define-key ediff-mode-map " " 'ediff-next-difference)
- (define-key ediff-mode-map "j" 'ediff-jump-to-difference)
- (define-key ediff-mode-map "g" nil)
- (define-key ediff-mode-map "ga" 'ediff-jump-to-difference-at-point)
- (define-key ediff-mode-map "gb" 'ediff-jump-to-difference-at-point)
- (define-key ediff-mode-map "q" 'ediff-quit)
- (define-key ediff-mode-map "D" 'ediff-show-diff-output)
- (define-key ediff-mode-map "z" 'ediff-suspend)
- (define-key ediff-mode-map "\C-l" 'ediff-recenter)
- (define-key ediff-mode-map "|" 'ediff-toggle-split)
- (define-key ediff-mode-map "h" 'ediff-toggle-hilit)
- (or ediff-word-mode
- (define-key ediff-mode-map "@" 'ediff-toggle-autorefine))
- (if ediff-narrow-job
- (define-key ediff-mode-map "%" 'ediff-toggle-narrow-region))
- (define-key ediff-mode-map "~" 'ediff-swap-buffers)
- (define-key ediff-mode-map "v" 'ediff-scroll-vertically)
- (define-key ediff-mode-map "\C-v" 'ediff-scroll-vertically)
- (define-key ediff-mode-map "^" 'ediff-scroll-vertically)
- (define-key ediff-mode-map "\M-v" 'ediff-scroll-vertically)
- (define-key ediff-mode-map "V" 'ediff-scroll-vertically)
- (define-key ediff-mode-map "<" 'ediff-scroll-horizontally)
- (define-key ediff-mode-map ">" 'ediff-scroll-horizontally)
- (define-key ediff-mode-map "i" 'ediff-status-info)
- (define-key ediff-mode-map "E" 'ediff-documentation)
- (define-key ediff-mode-map "?" 'ediff-toggle-help)
- (define-key ediff-mode-map "!" 'ediff-update-diffs)
- (define-key ediff-mode-map "M" 'ediff-show-meta-buffer)
- (define-key ediff-mode-map "R" 'ediff-show-registry)
- (or ediff-word-mode
- (define-key ediff-mode-map "*" 'ediff-make-or-kill-fine-diffs))
- (define-key ediff-mode-map "a" nil)
- (define-key ediff-mode-map "b" nil)
- (define-key ediff-mode-map "r" nil)
- (cond (ediff-merge-job
- ;; Will barf if no ancestor
- (define-key ediff-mode-map "/" 'ediff-show-ancestor)
- ;; In merging, we allow only A->C and B->C copying.
- (define-key ediff-mode-map "a" 'ediff-copy-A-to-C)
- (define-key ediff-mode-map "b" 'ediff-copy-B-to-C)
- (define-key ediff-mode-map "r" 'ediff-restore-diff-in-merge-buffer)
- (define-key ediff-mode-map "s" 'ediff-shrink-window-C)
- (define-key ediff-mode-map "+" 'ediff-combine-diffs)
- (define-key ediff-mode-map "$" 'ediff-toggle-show-clashes-only)
- (define-key ediff-mode-map "&" 'ediff-re-merge))
- (ediff-3way-comparison-job
- (define-key ediff-mode-map "ab" 'ediff-copy-A-to-B)
- (define-key ediff-mode-map "ba" 'ediff-copy-B-to-A)
- (define-key ediff-mode-map "ac" 'ediff-copy-A-to-C)
- (define-key ediff-mode-map "bc" 'ediff-copy-B-to-C)
- (define-key ediff-mode-map "c" nil)
- (define-key ediff-mode-map "ca" 'ediff-copy-C-to-A)
- (define-key ediff-mode-map "cb" 'ediff-copy-C-to-B)
- (define-key ediff-mode-map "ra" 'ediff-restore-diff)
- (define-key ediff-mode-map "rb" 'ediff-restore-diff)
- (define-key ediff-mode-map "rc" 'ediff-restore-diff)
- (define-key ediff-mode-map "C" 'ediff-toggle-read-only))
- (t ; 2-way comparison
- (define-key ediff-mode-map "a" 'ediff-copy-A-to-B)
- (define-key ediff-mode-map "b" 'ediff-copy-B-to-A)
- (define-key ediff-mode-map "ra" 'ediff-restore-diff)
- (define-key ediff-mode-map "rb" 'ediff-restore-diff))
- ) ; cond
- (define-key ediff-mode-map "G" 'ediff-submit-report)
- (define-key ediff-mode-map "#" nil)
- (define-key ediff-mode-map "#h" 'ediff-toggle-regexp-match)
- (define-key ediff-mode-map "#f" 'ediff-toggle-regexp-match)
- (or ediff-word-mode
- (define-key ediff-mode-map "##" 'ediff-toggle-skip-similar))
- (define-key ediff-mode-map "o" nil)
- (define-key ediff-mode-map "A" 'ediff-toggle-read-only)
- (define-key ediff-mode-map "B" 'ediff-toggle-read-only)
- (define-key ediff-mode-map "w" nil)
- (define-key ediff-mode-map "wa" 'ediff-save-buffer)
- (define-key ediff-mode-map "wb" 'ediff-save-buffer)
- (define-key ediff-mode-map "wd" 'ediff-save-buffer)
- (define-key ediff-mode-map "=" 'ediff-inferior-compare-regions)
- (if (fboundp 'ediff-show-patch-diagnostics)
- (define-key ediff-mode-map "P" 'ediff-show-patch-diagnostics))
- (if ediff-3way-job
- (progn
- (define-key ediff-mode-map "wc" 'ediff-save-buffer)
- (define-key ediff-mode-map "gc" 'ediff-jump-to-difference-at-point)
- ))
-
- (define-key ediff-mode-map "m" 'ediff-toggle-wide-display)
-
- ;; Allow ediff-mode-map to be referenced indirectly
- (fset 'ediff-mode-map ediff-mode-map)
- (run-hooks 'ediff-keymap-setup-hook))
-
-
-;;; Setup functions
-
-(require 'ediff-wind)
-
-;; No longer needed: XEmacs has surrogate minibuffers now.
-;;(or (boundp 'synchronize-minibuffers)
-;; (defvar synchronize-minibuffers nil))
-
-;; Common startup entry for all Ediff functions
-;; It now returns control buffer so other functions can do post-processing
-(defun ediff-setup (buffer-A file-A buffer-B file-B buffer-C file-C
- startup-hooks setup-parameters)
- ;; ediff-convert-standard-filename puts file names in the form appropriate
- ;; for the OS at hand.
- (setq file-A (ediff-convert-standard-filename (expand-file-name file-A)))
- (setq file-B (ediff-convert-standard-filename (expand-file-name file-B)))
- (if (stringp file-C)
- (setq file-C
- (ediff-convert-standard-filename (expand-file-name file-C))))
- (let* ((control-buffer-name
- (ediff-unique-buffer-name "*Ediff Control Panel" "*"))
- (control-buffer (ediff-eval-in-buffer buffer-A
- (get-buffer-create control-buffer-name))))
- (ediff-eval-in-buffer control-buffer
- (ediff-mode)
-
- ;; unwrap set up parameters passed as argument
- (while setup-parameters
- (set (car (car setup-parameters)) (cdr (car setup-parameters)))
- (setq setup-parameters (cdr setup-parameters)))
-
- ;; set variables classifying the current ediff job
- (setq ediff-3way-comparison-job (ediff-3way-comparison-job)
- ediff-merge-job (ediff-merge-job)
- ediff-merge-with-ancestor-job (ediff-merge-with-ancestor-job)
- ediff-3way-job (ediff-3way-job)
- ediff-diff3-job (ediff-diff3-job)
- ediff-narrow-job (ediff-narrow-job)
- ediff-windows-job (ediff-windows-job)
- ediff-word-mode-job (ediff-word-mode-job))
-
- (make-local-variable 'ediff-use-long-help-message)
- (make-local-variable 'ediff-prefer-iconified-control-frame)
- (make-local-variable 'ediff-split-window-function)
- (make-local-variable 'ediff-default-variant)
- (make-local-variable 'ediff-merge-window-share)
- (make-local-variable 'ediff-window-setup-function)
- (make-local-variable 'ediff-keep-variants)
-
- ;; Don't delete variants in case of ediff-buffer-* jobs without asking.
- ;; This is because u may loose work---dangerous.
- (if (string-match "buffer" (symbol-name ediff-job-name))
- (setq ediff-keep-variants t))
-
- (make-local-hook 'pre-command-hook)
- (if (ediff-window-display-p)
- (add-hook 'pre-command-hook 'ediff-spy-after-mouse nil t))
- (setq ediff-mouse-pixel-position (mouse-pixel-position))
-
- ;; adjust for merge jobs
- (if ediff-merge-job
- (let ((buf
- ;; If default variant is `combined', the right stuff is
- ;; inserted by ediff-do-merge
- ;; Note: at some point, we tried to put ancestor buffer here
- ;; (which is currently buffer C. This didn't work right
- ;; because the merge buffer will contain lossage: diff regions
- ;; in the ancestor, which correspond to revisions that agree
- ;; in both buf A and B.
- (cond ((eq ediff-default-variant 'default-B)
- buffer-B)
- (t buffer-A))))
-
- (setq ediff-split-window-function
- ediff-merge-split-window-function)
-
- ;; remember the ancestor buffer, if any
- (setq ediff-ancestor-buffer buffer-C)
-
- (setq buffer-C
- (get-buffer-create
- (ediff-unique-buffer-name "*ediff-merge" "*")))
- (save-excursion
- (set-buffer buffer-C)
- (insert-buffer buf)
- (funcall (ediff-eval-in-buffer buf major-mode))
- ;; after Stig@hackvan.com
- (add-hook 'local-write-file-hooks 'ediff-set-merge-mode nil t)
- )))
- (setq buffer-read-only nil
- ediff-buffer-A buffer-A
- ediff-buffer-B buffer-B
- ediff-buffer-C buffer-C
- ediff-control-buffer control-buffer)
-
- (setq ediff-control-buffer-suffix
- (if (string-match "<[0-9]*>" control-buffer-name)
- (substring control-buffer-name
- (match-beginning 0) (match-end 0))
- "")
- ediff-control-buffer-number
- (max
- 0
- (1-
- (string-to-number
- (substring
- ediff-control-buffer-suffix
- (or
- (string-match "[0-9]+" ediff-control-buffer-suffix)
- 0))))))
-
- (setq ediff-error-buffer
- (get-buffer-create (ediff-unique-buffer-name "*ediff-errors" "*")))
-
- (ediff-eval-in-buffer buffer-A (ediff-strip-mode-line-format))
- (ediff-eval-in-buffer buffer-B (ediff-strip-mode-line-format))
- (if ediff-3way-job
- (ediff-eval-in-buffer buffer-C (ediff-strip-mode-line-format)))
- (if (ediff-buffer-live-p ediff-ancestor-buffer)
- (ediff-eval-in-buffer ediff-ancestor-buffer
- (ediff-strip-mode-line-format)))
-
- (ediff-save-protected-variables) ; save variables to be restored on exit
-
- ;; ediff-setup-diff-regions-function must be set after setup
- ;; parameters are processed.
- (setq ediff-setup-diff-regions-function
- (if ediff-diff3-job
- 'ediff-setup-diff-regions3
- 'ediff-setup-diff-regions))
-
- (setq ediff-wide-bounds
- (list (ediff-make-bullet-proof-overlay
- '(point-min) '(point-max) ediff-buffer-A)
- (ediff-make-bullet-proof-overlay
- '(point-min) '(point-max) ediff-buffer-B)
- (ediff-make-bullet-proof-overlay
- '(point-min) '(point-max) ediff-buffer-C)))
-
- ;; This has effect only on ediff-windows/regions
- ;; In all other cases, ediff-visible-region sets visibility bounds to
- ;; ediff-wide-bounds, and ediff-narrow-bounds are ignored.
- (if ediff-start-narrowed
- (setq ediff-visible-bounds ediff-narrow-bounds)
- (setq ediff-visible-bounds ediff-wide-bounds))
-
- (ediff-set-keys) ; comes after parameter setup
-
- ;; set up ediff-narrow-bounds, if not set
- (or ediff-narrow-bounds
- (setq ediff-narrow-bounds ediff-wide-bounds))
-
- ;; All these must be inside ediff-eval-in-buffer control-buffer,
- ;; since these vars are local to control-buffer
- ;; These won't run if there are errors in diff
- (ediff-eval-in-buffer ediff-buffer-A
- (ediff-nuke-selective-display)
- (run-hooks 'ediff-prepare-buffer-hook)
- (if (ediff-eval-in-buffer control-buffer ediff-merge-job)
- (setq buffer-read-only t))
- ;; add control-buffer to the list of sessions--no longer used, but may
- ;; be used again in the future
- (or (memq control-buffer ediff-this-buffer-ediff-sessions)
- (setq ediff-this-buffer-ediff-sessions
- (cons control-buffer ediff-this-buffer-ediff-sessions)))
- )
- (ediff-eval-in-buffer ediff-buffer-B
- (ediff-nuke-selective-display)
- (run-hooks 'ediff-prepare-buffer-hook)
- (if (ediff-eval-in-buffer control-buffer ediff-merge-job)
- (setq buffer-read-only t))
- ;; add control-buffer to the list of sessions
- (or (memq control-buffer ediff-this-buffer-ediff-sessions)
- (setq ediff-this-buffer-ediff-sessions
- (cons control-buffer ediff-this-buffer-ediff-sessions)))
- )
- (if ediff-3way-job
- (ediff-eval-in-buffer ediff-buffer-C
- (ediff-nuke-selective-display)
- (run-hooks 'ediff-prepare-buffer-hook)
- ;; add control-buffer to the list of sessions
- (or (memq control-buffer ediff-this-buffer-ediff-sessions)
- (setq ediff-this-buffer-ediff-sessions
- (cons control-buffer
- ediff-this-buffer-ediff-sessions)))
- ))
-
- (if (ediff-buffer-live-p ediff-ancestor-buffer)
- (ediff-eval-in-buffer ediff-ancestor-buffer
- (ediff-nuke-selective-display)
- (setq buffer-read-only t)
- (run-hooks 'ediff-prepare-buffer-hook)
- (or (memq control-buffer ediff-this-buffer-ediff-sessions)
- (setq ediff-this-buffer-ediff-sessions
- (cons control-buffer
- ediff-this-buffer-ediff-sessions)))
- ))
-
- ;; must come after setting up ediff-narrow-bounds AND after
- ;; nuking selective display
- (funcall ediff-setup-diff-regions-function file-A file-B file-C)
- (setq ediff-number-of-differences (length ediff-difference-vector-A))
- (setq ediff-current-difference -1)
-
- (ediff-make-current-diff-overlay 'A)
- (ediff-make-current-diff-overlay 'B)
- (if ediff-3way-job
- (ediff-make-current-diff-overlay 'C))
- (if ediff-merge-with-ancestor-job
- (ediff-make-current-diff-overlay 'Ancestor))
-
- (ediff-setup-windows buffer-A buffer-B buffer-C control-buffer)
-
- (let ((shift-A (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type
- 'A ediff-narrow-bounds)))
- (shift-B (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type
- 'B ediff-narrow-bounds)))
- (shift-C (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type
- 'C ediff-narrow-bounds))))
- ;; position point in buf A
- (save-excursion
- (select-window ediff-window-A)
- (goto-char shift-A))
- ;; position point in buf B
- (save-excursion
- (select-window ediff-window-B)
- (goto-char shift-B))
- (if ediff-3way-job
- (save-excursion
- (select-window ediff-window-C)
- (goto-char shift-C)))
- )
-
- (select-window ediff-control-window)
- (ediff-visible-region)
-
- (run-hooks 'startup-hooks)
- (ediff-refresh-mode-lines)
- (setq buffer-read-only t)
- (setq ediff-session-registry
- (cons control-buffer ediff-session-registry))
- (ediff-update-registry)
- (if (ediff-buffer-live-p ediff-meta-buffer)
- (ediff-update-meta-buffer ediff-meta-buffer))
- (run-hooks 'ediff-startup-hook)
- ) ; eval in control-buffer
- control-buffer))
-
-
-;; This function assumes that we are in the window where control buffer is
-;; to reside.
-(defun ediff-setup-control-buffer (ctl-buf)
- "Set up window for control buffer."
- (if (window-dedicated-p (selected-window))
- (set-buffer ctl-buf) ; we are in control frame but just in case
- (switch-to-buffer ctl-buf))
- (let ((window-min-height 2))
- (erase-buffer)
- (ediff-set-help-message)
- (insert ediff-help-message)
- (shrink-window-if-larger-than-buffer)
- (or (ediff-multiframe-setup-p)
- (ediff-indent-help-message))
- (ediff-set-help-overlays)
-
- (set-buffer-modified-p nil)
- (ediff-refresh-mode-lines)
- (setq ediff-control-window (selected-window))
- (setq ediff-window-config-saved
- (format "%S%S%S%S%S%S%S"
- ediff-control-window
- ediff-window-A
- ediff-window-B
- ediff-window-C
- ediff-split-window-function
- (ediff-multiframe-setup-p)
- ediff-wide-display-p))
- (if (not (ediff-multiframe-setup-p))
- (ediff-make-bottom-toolbar)) ; checks if toolbar is requested
- (goto-char (point-min))
- (skip-chars-forward ediff-whitespace)))
-
-
-
-
-;;; Commands for working with Ediff
-
-(defun ediff-update-diffs ()
- "Recompute difference regions in buffers A, B, and C.
-Buffers are not synchronized with their respective files, so changes done
-to these buffers are not saved at this point---the user can do this later,
-if necessary."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (if (and (ediff-buffer-live-p ediff-ancestor-buffer)
- (not (y-or-n-p "Recompute differences during merge, really? ")))
- (error "God forbid!"))
-
- (let ((point-A (ediff-eval-in-buffer ediff-buffer-A (point)))
- ;;(point-B (ediff-eval-in-buffer ediff-buffer-B (point)))
- (tmp-buffer (get-buffer-create ediff-tmp-buffer))
- (buf-A-file-name
- (file-name-nondirectory (or (buffer-file-name ediff-buffer-A)
- (buffer-name ediff-buffer-A)
- )))
- (buf-B-file-name
- (file-name-nondirectory (or (buffer-file-name ediff-buffer-B)
- (buffer-name ediff-buffer-B)
- )))
- (buf-C-file-name
- (file-name-nondirectory (or (buffer-file-name ediff-buffer-C)
- ;; if (null ediff-buffer-C), there is
- ;; no danger, since we later check if
- ;; ediff-buffer-C is alive
- (buffer-name ediff-buffer-C)
- )))
- (overl-A (ediff-get-value-according-to-buffer-type
- 'A ediff-narrow-bounds))
- (overl-B (ediff-get-value-according-to-buffer-type
- 'B ediff-narrow-bounds))
- (overl-C (ediff-get-value-according-to-buffer-type
- 'C ediff-narrow-bounds))
- beg-A end-A beg-B end-B beg-C end-C
- file-A file-B file-C)
- (ediff-unselect-and-select-difference -1)
-
- (setq beg-A (ediff-overlay-start overl-A)
- beg-B (ediff-overlay-start overl-B)
- beg-C (ediff-overlay-start overl-C)
- end-A (ediff-overlay-end overl-A)
- end-B (ediff-overlay-end overl-B)
- end-C (ediff-overlay-end overl-C))
-
- (if ediff-word-mode
- (progn
- (ediff-wordify beg-A end-A ediff-buffer-A tmp-buffer)
- (setq file-A (ediff-make-temp-file tmp-buffer "regA"))
- (ediff-wordify beg-B end-B ediff-buffer-B tmp-buffer)
- (setq file-B (ediff-make-temp-file tmp-buffer "regB"))
- (if ediff-3way-job
- (progn
- (ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer)
- (setq file-C (ediff-make-temp-file tmp-buffer "regC"))))
- )
- ;; not word-mode
- (setq file-A (ediff-make-temp-file ediff-buffer-A buf-A-file-name))
- (setq file-B (ediff-make-temp-file ediff-buffer-B buf-B-file-name))
- (if ediff-3way-job
- (setq file-C (ediff-make-temp-file ediff-buffer-C buf-C-file-name)))
- )
-
- (ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also)
- (ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also)
- (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
- (ediff-clear-diff-vector
- 'ediff-difference-vector-Ancestor 'fine-diffs-also)
- ;; let them garbage collect. we can't use the ancestor after recomputing
- ;; the diffs.
- (setq ediff-difference-vector-Ancestor nil
- ediff-ancestor-buffer nil
- ediff-state-of-merge nil)
-
- (setq ediff-killed-diffs-alist nil) ; invalidate saved killed diff regions
-
- ;; In case of merge job, fool it into thinking that it is just doing
- ;; comparison
- (let ((ediff-setup-diff-regions-function ediff-setup-diff-regions-function)
- (ediff-3way-comparison-job ediff-3way-comparison-job)
- (ediff-merge-job ediff-merge-job)
- (ediff-merge-with-ancestor-job ediff-merge-with-ancestor-job)
- (ediff-job-name ediff-job-name))
- (if ediff-merge-job
- (setq ediff-setup-diff-regions-function 'ediff-setup-diff-regions3
- ediff-3way-comparison-job t
- ediff-merge-job nil
- ediff-merge-with-ancestor-job nil
- ediff-job-name 'ediff-files3))
- (funcall ediff-setup-diff-regions-function file-A file-B file-C))
-
- (setq ediff-number-of-differences (length ediff-difference-vector-A))
- (delete-file file-A)
- (delete-file file-B)
- (if file-C
- (delete-file file-C))
-
- (if ediff-3way-job
- (ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
-
- (ediff-jump-to-difference (ediff-diff-at-point 'A point-A))
- (message "")
- ))
-
-;; Not bound to any key---to dangerous. A user can do it if necessary.
-(defun ediff-revert-buffers-then-recompute-diffs (noconfirm)
- "Revert buffers A, B and C. Then rerun Ediff on file A and file B."
- (interactive "P")
- (ediff-barf-if-not-control-buffer)
- (let ((bufA ediff-buffer-A)
- (bufB ediff-buffer-B)
- (bufC ediff-buffer-C)
- (ctl-buf ediff-control-buffer)
- (keep-variants ediff-keep-variants)
- (ancestor-buf ediff-ancestor-buffer)
- (ancestor-job ediff-merge-with-ancestor-job)
- (merge ediff-merge-job)
- (comparison ediff-3way-comparison-job))
- (ediff-eval-in-buffer bufA
- (revert-buffer t noconfirm))
- (ediff-eval-in-buffer bufB
- (revert-buffer t noconfirm))
- ;; this should only be executed in a 3way comparison, not in merge
- (if comparison
- (ediff-eval-in-buffer bufC
- (revert-buffer t noconfirm)))
- (if merge
- (progn
- (set-buffer ctl-buf)
- ;; the argument says whether to reverse the meaning of
- ;; ediff-keep-variants, i.e., ediff-really-quit runs here with
- ;; variants kept.
- (ediff-really-quit (not keep-variants))
- (kill-buffer bufC)
- (if ancestor-job
- (ediff-merge-buffers-with-ancestor bufA bufB ancestor-buf)
- (ediff-merge-buffers bufA bufB)))
- (ediff-update-diffs))))
-
-
-;; optional NO-REHIGHLIGHT says to not rehighlight buffers
-(defun ediff-recenter (&optional no-rehighlight)
- "Bring the highlighted region of all buffers being compared into view.
-Reestablish the default three-window display."
- (interactive)
- (ediff-barf-if-not-control-buffer)
-
-;; ;; No longer needed: XEmacs has surrogate minibuffers now.
-;; (if ediff-xemacs-p (setq synchronize-minibuffers t))
-
- (let (buffer-read-only)
- (if (and (ediff-buffer-live-p ediff-buffer-A)
- (ediff-buffer-live-p ediff-buffer-B)
- (or (not ediff-3way-job)
- (ediff-buffer-live-p ediff-buffer-C)))
- (ediff-setup-windows
- ediff-buffer-A ediff-buffer-B ediff-buffer-C ediff-control-buffer)
- (or (eq this-command 'ediff-quit)
- (message ediff-KILLED-VITAL-BUFFER
- (beep 1)))
- ))
-
- ;; set visibility range appropriate to this invocation of Ediff.
- (ediff-visible-region)
- ;; raise
- (if (and (ediff-window-display-p)
- (symbolp this-command)
- (symbolp last-command)
- ;; Either one of the display-changing commands
- (or (memq this-command
- '(ediff-recenter
- ediff-dir-action ediff-registry-action
- ediff-patch-action
- ediff-toggle-wide-display ediff-toggle-multiframe))
- ;; Or one of the movement cmds and prev cmd was an Ediff cmd
- ;; This avoids raising frames unnecessarily.
- (and (memq this-command
- '(ediff-next-difference
- ediff-previous-difference
- ediff-jump-to-difference
- ediff-jump-to-difference-at-point))
- (not (string-match "^ediff-" (symbol-name last-command)))
- )))
- (progn
- (if (window-live-p ediff-window-A)
- (raise-frame (window-frame ediff-window-A)))
- (if (window-live-p ediff-window-B)
- (raise-frame (window-frame ediff-window-B)))
- (if (window-live-p ediff-window-C)
- (raise-frame (window-frame ediff-window-C)))))
- (if (and (ediff-window-display-p)
- (frame-live-p ediff-control-frame)
- (not ediff-use-long-help-message)
- (not (ediff-frame-iconified-p ediff-control-frame)))
- (raise-frame ediff-control-frame))
-
- ;; Redisplay whatever buffers are showing, if there is a selected difference
- (let ((control-frame ediff-control-frame)
- (control-buf ediff-control-buffer))
- (if (and (ediff-buffer-live-p ediff-buffer-A)
- (ediff-buffer-live-p ediff-buffer-B)
- (or (not ediff-3way-job)
- (ediff-buffer-live-p ediff-buffer-C)))
- (progn
- (or no-rehighlight
- (ediff-select-difference ediff-current-difference))
-
- (ediff-recenter-one-window 'A)
- (ediff-recenter-one-window 'B)
- (if ediff-3way-job
- (ediff-recenter-one-window 'C))
-
- (ediff-eval-in-buffer control-buf
- (ediff-recenter-ancestor) ; check if ancestor is alive
-
- (if (and (ediff-multiframe-setup-p)
- (not ediff-use-long-help-message)
- (not (ediff-frame-iconified-p ediff-control-frame)))
- ;; never grab mouse on quit in this place
- (ediff-reset-mouse
- control-frame
- (eq this-command 'ediff-quit))))
- ))
-
- (ediff-restore-highlighting)
- (ediff-eval-in-buffer control-buf (ediff-refresh-mode-lines))
- ))
-
-;; this function returns to the window it was called from
-;; (which was the control window)
-(defun ediff-recenter-one-window (buf-type)
- (if (ediff-valid-difference-p)
- ;; context must be saved before switching to windows A/B/C
- (let* ((ctl-wind (selected-window))
- (shift (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type
- buf-type ediff-narrow-bounds)))
- (job-name ediff-job-name)
- (control-buf ediff-control-buffer)
- (window-name (intern (format "ediff-window-%S" buf-type)))
- (window (if (window-live-p (symbol-value window-name))
- (symbol-value window-name))))
-
- (if (and window ediff-windows-job)
- (set-window-start window shift))
- (if window
- (progn
- (select-window window)
- (ediff-deactivate-mark)
- (ediff-position-region
- (ediff-get-diff-posn buf-type 'beg nil control-buf)
- (ediff-get-diff-posn buf-type 'end nil control-buf)
- (ediff-get-diff-posn buf-type 'beg nil control-buf)
- job-name
- )))
- (select-window ctl-wind)
- )))
-
-(defun ediff-recenter-ancestor ()
- ;; do half-hearted job by recentering the ancestor buffer, if it is alive and
- ;; visible.
- (if (and (ediff-buffer-live-p ediff-ancestor-buffer)
- (ediff-valid-difference-p))
- (let ((window (ediff-get-visible-buffer-window ediff-ancestor-buffer))
- (ctl-wind (selected-window))
- (job-name ediff-job-name)
- (ctl-buf ediff-control-buffer))
- (ediff-eval-in-buffer ediff-ancestor-buffer
- (goto-char (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf))
- (if window
- (progn
- (select-window window)
- (ediff-position-region
- (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf)
- (ediff-get-diff-posn 'Ancestor 'end nil ctl-buf)
- (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf)
- job-name))))
- (select-window ctl-wind)
- )))
-
-
-;; This will have to be refined for 3way jobs
-(defun ediff-toggle-split ()
- "Toggle vertical/horizontal window split.
-Does nothing if file-A and file-B are in different frames."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (let* ((wind-A (if (window-live-p ediff-window-A) ediff-window-A))
- (wind-B (if (window-live-p ediff-window-B) ediff-window-B))
- (wind-C (if (window-live-p ediff-window-C) ediff-window-C))
- (frame-A (if wind-A (window-frame wind-A)))
- (frame-B (if wind-B (window-frame wind-B)))
- (frame-C (if wind-C (window-frame wind-C))))
- (if (or (eq frame-A frame-B)
- (not (frame-live-p frame-A))
- (not (frame-live-p frame-B))
- (if ediff-3way-comparison-job
- (or (not (frame-live-p frame-C))
- (eq frame-A frame-C) (eq frame-B frame-C))))
- (setq ediff-split-window-function
- (if (eq ediff-split-window-function 'split-window-vertically)
- 'split-window-horizontally
- 'split-window-vertically))
- (message "Buffers being compared are in different frames"))
- (ediff-recenter 'no-rehighlight)))
-
-(defun ediff-toggle-hilit ()
- "Switch between highlighting using ASCII flags and highlighting using faces.
-On a dumb terminal, switches between ASCII highlighting and no highlighting."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (if (not (ediff-has-face-support-p))
- (if (eq ediff-highlighting-style 'ascii)
- (progn
- (message "ASCII highlighting flags removed")
- (ediff-unselect-and-select-difference ediff-current-difference
- 'unselect-only)
- (setq ediff-highlighting-style 'off))
- (ediff-unselect-and-select-difference ediff-current-difference
- 'select-only))
- (ediff-unselect-and-select-difference ediff-current-difference
- 'unselect-only)
- ;; cycle through highlighting
- (cond ((and ediff-use-faces ediff-highlight-all-diffs)
- (message "Unhighlighting unselected difference regions")
- (setq ediff-highlight-all-diffs nil))
- (ediff-use-faces
- (message "Highlighting with ASCII flags")
- (setq ediff-use-faces nil))
- (t
- (message "Re-highlighting all difference regions")
- (setq ediff-use-faces t
- ediff-highlight-all-diffs t)))
-
- (if (and ediff-use-faces ediff-highlight-all-diffs)
- (ediff-paint-background-regions)
- (ediff-paint-background-regions 'unhighlight))
-
- (ediff-unselect-and-select-difference
- ediff-current-difference 'select-only))
- )
-
-
-(defun ediff-toggle-autorefine ()
- "Toggle auto-refine mode."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (if ediff-word-mode
- (error "No fine differences in this mode"))
- (cond ((eq ediff-auto-refine 'nix)
- (setq ediff-auto-refine 'on)
- (ediff-make-fine-diffs ediff-current-difference 'noforce)
- (message "Auto-refining is ON"))
- ((eq ediff-auto-refine 'on)
- (message "Auto-refining is OFF")
- (setq ediff-auto-refine 'off))
- (t ;; nix 'em
- (ediff-set-fine-diff-properties ediff-current-difference 'default)
- (message "Refinements are HIDDEN")
- (setq ediff-auto-refine 'nix))
- ))
-
-(defun ediff-show-ancestor ()
- "Show the ancestor buffer in a suitable window."
- (interactive)
- (ediff-recenter)
- (or (ediff-buffer-live-p ediff-ancestor-buffer)
- (if ediff-merge-with-ancestor-job
- (error "Lost connection to ancestor buffer...sorry")
- (error "Not merging with ancestor")))
- (let (wind)
- (cond ((setq wind (ediff-get-visible-buffer-window ediff-ancestor-buffer))
- (raise-frame (window-frame wind)))
- (t (set-window-buffer ediff-window-C ediff-ancestor-buffer)))))
-
-(defun ediff-make-or-kill-fine-diffs (arg)
- "Compute fine diffs. With negative prefix arg, kill fine diffs.
-In both cases, operates on the currrent difference region."
- (interactive "P")
- (ediff-barf-if-not-control-buffer)
- (cond ((eq arg '-)
- (ediff-clear-fine-differences ediff-current-difference))
- ((and (numberp arg) (< arg 0))
- (ediff-clear-fine-differences ediff-current-difference))
- (t (ediff-make-fine-diffs))))
-
-
-(defun ediff-toggle-help ()
- "Toggle short/long help message."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (let (buffer-read-only)
- (erase-buffer)
- (setq ediff-use-long-help-message (not ediff-use-long-help-message))
- (ediff-set-help-message))
- ;; remember the icon status of the control frame when the user requested
- ;; full control message
- (if (and ediff-use-long-help-message (ediff-multiframe-setup-p))
- (setq ediff-prefer-iconified-control-frame
- (ediff-frame-iconified-p ediff-control-frame)))
-
- (setq ediff-window-config-saved "") ; force redisplay
- (ediff-recenter 'no-rehighlight))
-
-
-;; If BUF, this is the buffer to toggle, not current buffer.
-(defun ediff-toggle-read-only (&optional buf)
- "Toggle read-only in current buffer.
-If buffer is under version control and locked, check it out first.
-If optional argument BUF is specified, toggle read-only in that buffer instead
-of the current buffer."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (let ((ctl-buf (if (null buf) (current-buffer)))
- (buf-type (ediff-char-to-buftype last-command-char)))
- (or buf (ediff-recenter))
- (or buf
- (setq buf (ediff-get-buffer buf-type)))
-
- (ediff-eval-in-buffer buf ; eval in buf A/B/C
- (let* ((file (buffer-file-name buf))
- (file-writable (and file
- (file-exists-p file)
- (file-writable-p file)))
- (toggle-ro-cmd (cond (ediff-toggle-read-only-function)
- ((ediff-file-checked-out-p file)
- 'toggle-read-only)
- (file-writable 'toggle-read-only)
- (t (key-binding "\C-x\C-q")))))
- ;; If the file is checked in, make sure we don't make buffer modifiable
- ;; without warning the user. The user can fool our checks by making the
- ;; buffer non-RO without checking the file out. We regard this as a
- ;; user problem.
- (if (and (ediff-file-checked-in-p file)
- ;; If ctl-buf is null, this means we called this
- ;; non-interactively, in which case don't ask questions
- ctl-buf)
- (cond ((not buffer-read-only)
- (setq toggle-ro-cmd 'toggle-read-only))
- ((and (or (beep 1) t) ; always beep
- (y-or-n-p
- (format
- "File %s is under version control. Check it out? "
- (ediff-abbreviate-file-name file))))
- ;; if we checked the file out, we should also change the
- ;; original state of buffer-read-only to nil. If we don't
- ;; do this, the mode line will show %%, since the file was
- ;; RO before ediff started, so the user will think the file
- ;; is checked in.
- (ediff-eval-in-buffer ctl-buf
- (ediff-change-saved-variable
- 'buffer-read-only nil buf-type)))
- (t
- (setq toggle-ro-cmd 'toggle-read-only)
- (beep 1) (beep 1)
- (message
- "Boy, this is risky! Don't modify this file...")
- (sit-for 3)))) ; let the user see the warning
- (if (and toggle-ro-cmd
- (string-match "toggle-read-only" (symbol-name toggle-ro-cmd)))
- (save-excursion
- (save-window-excursion
- (select-window (ediff-get-visible-buffer-window buf))
- (command-execute toggle-ro-cmd)))
- (error "Don't know how to toggle read-only in buffer %S" buf))
-
- ;; Check if we made the current buffer updatable, but its file is RO.
- ;; Signal a warning in this case.
- (if (and file (not buffer-read-only)
- (eq this-command 'ediff-toggle-read-only)
- (file-exists-p file)
- (not (file-writable-p file)))
- (message "Warning: file %s is read-only"
- (ediff-abbreviate-file-name file) (beep 1)))
- ))))
-
-;; checkout if visited file is checked in
-(defun ediff-maybe-checkout (buf)
- (let ((file (buffer-file-name buf))
- (checkout-function (key-binding "\C-x\C-q")))
- (if (and (ediff-file-checked-in-p file)
- (or (beep 1) t)
- (y-or-n-p
- (format
- "File %s is under version control. Check it out? "
- (ediff-abbreviate-file-name file))))
- (ediff-eval-in-buffer buf
- (command-execute checkout-function)))))
-
-
-;; This is a simple-minded check for whether a file is under version control.
-;; If file,v exists but file doesn't, this file is considered to be not checked
-;; in and not checked out for the purpose of patching (since patch won't be
-;; able to read such a file anyway).
-;; FILE is a string representing file name
-(defun ediff-file-under-version-control (file)
- (let* ((filedir (file-name-directory file))
- (file-nondir (file-name-nondirectory file))
- (trial (concat file-nondir ",v"))
- (full-trial (concat filedir trial))
- (full-rcs-trial (concat filedir "RCS/" trial)))
- (and (stringp file)
- (file-exists-p file)
- (or
- (and
- (file-exists-p full-trial)
- ;; in FAT FS, `file,v' and `file' may turn out to be the same!
- ;; don't be fooled by this!
- (not (equal (file-attributes file)
- (file-attributes full-trial))))
- ;; check if a version is in RCS/ directory
- (file-exists-p full-rcs-trial)))
- ))
-
-(defun ediff-file-checked-out-p (file)
- (and (ediff-file-under-version-control file)
- (file-writable-p file)))
-(defun ediff-file-checked-in-p (file)
- (and (ediff-file-under-version-control file)
- (not (file-writable-p file))))
-
-(defun ediff-swap-buffers ()
- "Rotate the display of buffers A, B, and C."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (if (and (window-live-p ediff-window-A) (window-live-p ediff-window-B))
- (let ((buf ediff-buffer-A)
- (values ediff-buffer-values-orig-A)
- (diff-vec ediff-difference-vector-A)
- (hide-regexp ediff-regexp-hide-A)
- (focus-regexp ediff-regexp-focus-A)
- (wide-visibility-p (eq ediff-visible-bounds ediff-wide-bounds))
- (overlay (if (ediff-has-face-support-p)
- ediff-current-diff-overlay-A)))
- (if ediff-3way-comparison-job
- (progn
- (set-window-buffer ediff-window-A ediff-buffer-C)
- (set-window-buffer ediff-window-B ediff-buffer-A)
- (set-window-buffer ediff-window-C ediff-buffer-B)
- )
- (set-window-buffer ediff-window-A ediff-buffer-B)
- (set-window-buffer ediff-window-B ediff-buffer-A))
- ;; swap diff buffers
- (if ediff-3way-comparison-job
- (setq ediff-buffer-A ediff-buffer-C
- ediff-buffer-C ediff-buffer-B
- ediff-buffer-B buf)
- (setq ediff-buffer-A ediff-buffer-B
- ediff-buffer-B buf))
-
- ;; swap saved buffer characteristics
- (if ediff-3way-comparison-job
- (setq ediff-buffer-values-orig-A ediff-buffer-values-orig-C
- ediff-buffer-values-orig-C ediff-buffer-values-orig-B
- ediff-buffer-values-orig-B values)
- (setq ediff-buffer-values-orig-A ediff-buffer-values-orig-B
- ediff-buffer-values-orig-B values))
-
- ;; swap diff vectors
- (if ediff-3way-comparison-job
- (setq ediff-difference-vector-A ediff-difference-vector-C
- ediff-difference-vector-C ediff-difference-vector-B
- ediff-difference-vector-B diff-vec)
- (setq ediff-difference-vector-A ediff-difference-vector-B
- ediff-difference-vector-B diff-vec))
-
- ;; swap hide/focus regexp
- (if ediff-3way-comparison-job
- (setq ediff-regexp-hide-A ediff-regexp-hide-C
- ediff-regexp-hide-C ediff-regexp-hide-B
- ediff-regexp-hide-B hide-regexp
- ediff-regexp-focus-A ediff-regexp-focus-C
- ediff-regexp-focus-C ediff-regexp-focus-B
- ediff-regexp-focus-B focus-regexp)
- (setq ediff-regexp-hide-A ediff-regexp-hide-B
- ediff-regexp-hide-B hide-regexp
- ediff-regexp-focus-A ediff-regexp-focus-B
- ediff-regexp-focus-B focus-regexp))
-
- ;; The following is needed for XEmacs, since there one can't move
- ;; overlay to another buffer. In Emacs, this swap is redundant.
- (if (ediff-has-face-support-p)
- (if ediff-3way-comparison-job
- (setq ediff-current-diff-overlay-A ediff-current-diff-overlay-C
- ediff-current-diff-overlay-C ediff-current-diff-overlay-B
- ediff-current-diff-overlay-B overlay)
- (setq ediff-current-diff-overlay-A ediff-current-diff-overlay-B
- ediff-current-diff-overlay-B overlay)))
-
- ;; swap wide bounds
- (setq ediff-wide-bounds
- (cond (ediff-3way-comparison-job
- (list (nth 2 ediff-wide-bounds)
- (nth 0 ediff-wide-bounds)
- (nth 1 ediff-wide-bounds)))
- (ediff-3way-job
- (list (nth 1 ediff-wide-bounds)
- (nth 0 ediff-wide-bounds)
- (nth 2 ediff-wide-bounds)))
- (t
- (list (nth 1 ediff-wide-bounds)
- (nth 0 ediff-wide-bounds)))))
- ;; swap narrow bounds
- (setq ediff-narrow-bounds
- (cond (ediff-3way-comparison-job
- (list (nth 2 ediff-narrow-bounds)
- (nth 0 ediff-narrow-bounds)
- (nth 1 ediff-narrow-bounds)))
- (ediff-3way-job
- (list (nth 1 ediff-narrow-bounds)
- (nth 0 ediff-narrow-bounds)
- (nth 2 ediff-narrow-bounds)))
- (t
- (list (nth 1 ediff-narrow-bounds)
- (nth 0 ediff-narrow-bounds)))))
- (if wide-visibility-p
- (setq ediff-visible-bounds ediff-wide-bounds)
- (setq ediff-visible-bounds ediff-narrow-bounds))
- ))
- (if ediff-3way-job
- (ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
- (ediff-recenter 'no-rehighlight)
- )
-
-
-(defun ediff-toggle-wide-display ()
- "Toggle wide/regular display.
-This is especially useful when comparing buffers side-by-side."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (or (ediff-window-display-p)
- (error "%sEmacs is not running as a window application"
- (if ediff-emacs-p "" "X")))
- (ediff-recenter 'no-rehighlight) ; make sure buffs are displayed in windows
- (let ((ctl-buf ediff-control-buffer))
- (setq ediff-wide-display-p (not ediff-wide-display-p))
- (if (not ediff-wide-display-p)
- (ediff-eval-in-buffer ctl-buf
- (modify-frame-parameters
- ediff-wide-display-frame ediff-wide-display-orig-parameters)
- ;;(sit-for (if ediff-xemacs-p 0.4 0))
- ;; restore control buf, since ctl window may have been deleted
- ;; during resizing
- (set-buffer ctl-buf)
- (setq ediff-wide-display-orig-parameters nil
- ediff-window-B nil) ; force update of window config
- (ediff-recenter 'no-rehighlight))
- (funcall ediff-make-wide-display-function)
- ;;(sit-for (if ediff-xemacs-p 0.4 0))
- (ediff-eval-in-buffer ctl-buf
- (setq ediff-window-B nil) ; force update of window config
- (ediff-recenter 'no-rehighlight)))))
-
-;;;###autoload
-(defun ediff-toggle-multiframe ()
- "Switch from the multiframe display to single-frame display and back.
-For a permanent change, set the variable `ediff-window-setup-function',
-which see."
- (interactive)
- (let (set-func)
- (or (ediff-window-display-p)
- (error "%sEmacs is not running as a window application"
- (if ediff-emacs-p "" "X")))
-
- (setq set-func (if (ediff-in-control-buffer-p) 'setq 'setq-default))
-
- (cond ((eq ediff-window-setup-function 'ediff-setup-windows-multiframe)
- (eval
- (list
- set-func
- 'ediff-window-setup-function ''ediff-setup-windows-plain)))
- ((eq ediff-window-setup-function 'ediff-setup-windows-plain)
- (if (ediff-in-control-buffer-p)
- (ediff-kill-bottom-toolbar))
- (eval
- (list
- set-func
- 'ediff-window-setup-function ''ediff-setup-windows-multiframe))))
- (if (ediff-in-control-buffer-p)
- (progn
- (setq ediff-window-B nil)
- (ediff-recenter 'no-rehighlight)))))
-
-;; if was using toolbar, kill it
-(defun ediff-kill-bottom-toolbar ()
- ;; Using ctl-buffer or ediff-control-window for LOCALE does not
- ;; work properly in XEmacs 19.14: we have to use
- ;;(selected-frame).
- ;; The problem with this is that any previous bottom-toolbar
- ;; will not re-appear after our cleanup here. Is there a way
- ;; to do "push" and "pop" toolbars ? --marcpa
- (if (ediff-use-toolbar-p)
- (progn
- (set-specifier bottom-toolbar (list (selected-frame) nil))
- (set-specifier bottom-toolbar-visible-p (list (selected-frame) nil)))))
-
-;; if wants to use toolbar, make it
-(defun ediff-make-bottom-toolbar ()
- (if (ediff-use-toolbar-p)
- (progn
- (set-specifier bottom-toolbar (list (selected-frame) ediff-toolbar))
- (set-specifier bottom-toolbar-visible-p (list (selected-frame) t))
- (set-specifier bottom-toolbar-height (list (selected-frame) 34)))))
-
-;; Merging
-
-(defun ediff-toggle-show-clashes-only ()
- "Toggle the mode where only the regions where both buffers differ with the ancestor are shown."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (if (not ediff-merge-with-ancestor-job)
- (error "This command makes sense only when merging with an ancestor"))
- (setq ediff-show-clashes-only (not ediff-show-clashes-only))
- (if ediff-show-clashes-only
- (message "Focus on regions where both buffers differ from the ancestor")
- (message "Canceling focus on regions where changes clash")))
-
-;; Widening/narrowing
-
-(defun ediff-toggle-narrow-region ()
- "Toggle narrowing in buffers A, B, and C.
-Used in ediff-windows/regions only."
- (interactive)
- (if (eq ediff-buffer-A ediff-buffer-B)
- (error ediff-NO-DIFFERENCES))
- (if (eq ediff-visible-bounds ediff-wide-bounds)
- (setq ediff-visible-bounds ediff-narrow-bounds)
- (setq ediff-visible-bounds ediff-wide-bounds))
- (ediff-recenter 'no-rehighlight))
-
-;; Narrow bufs A/B/C to ediff-visible-bounds. If this is currently set to
-;; ediff-wide-bounds, then this actually widens.
-;; This function does nothing if job-name is not
-;; ediff-regions-wordwise/linewise or ediff-windows-wordwise/linewise.
-;; Does nothing if buffer-A = buffer-B since we can't narrow
-;; to two different regions in one buffer.
-(defun ediff-visible-region ()
- (if (or (eq ediff-buffer-A ediff-buffer-B)
- (eq ediff-buffer-A ediff-buffer-C)
- (eq ediff-buffer-C ediff-buffer-B))
- ()
- ;; If ediff-*-regions/windows, ediff-visible-bounds is already set
- ;; Otherwise, always use full range.
- (if (not ediff-narrow-job)
- (setq ediff-visible-bounds ediff-wide-bounds))
- (let ((overl-A (ediff-get-value-according-to-buffer-type
- 'A ediff-visible-bounds))
- (overl-B (ediff-get-value-according-to-buffer-type
- 'B ediff-visible-bounds))
- (overl-C (ediff-get-value-according-to-buffer-type
- 'C ediff-visible-bounds))
- )
- (ediff-eval-in-buffer ediff-buffer-A
- (narrow-to-region
- (ediff-overlay-start overl-A) (ediff-overlay-end overl-A)))
- (ediff-eval-in-buffer ediff-buffer-B
- (narrow-to-region
- (ediff-overlay-start overl-B) (ediff-overlay-end overl-B)))
-
- (if ediff-3way-comparison-job
- (ediff-eval-in-buffer ediff-buffer-C
- (narrow-to-region
- (ediff-overlay-start overl-C) (ediff-overlay-end overl-C))))
- )))
-
-
-;; Window scrolling operations
-
-;; Performs some operation on the two file windows (if they are showing).
-;; Traps all errors on the operation in windows A/B/C.
-;; Usually, errors come from scrolling off the
-;; beginning or end of the buffer, and this gives error messages.
-(defun ediff-operate-on-windows (operation arg)
-
- ;; make sure windows aren't dead
- (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
- (ediff-recenter 'no-rehighlight))
- (if (not (and (ediff-buffer-live-p ediff-buffer-A)
- (ediff-buffer-live-p ediff-buffer-B)
- (or (not ediff-3way-job) ediff-buffer-C)
- ))
- (error ediff-KILLED-VITAL-BUFFER))
-
- (let* ((wind (selected-window))
- (wind-A ediff-window-A)
- (wind-B ediff-window-B)
- (wind-C ediff-window-C)
- (coefA (ediff-get-region-size-coefficient 'A operation))
- (coefB (ediff-get-region-size-coefficient 'B operation))
- (three-way ediff-3way-job)
- (coefC (if three-way
- (ediff-get-region-size-coefficient 'C operation))))
-
- (select-window wind-A)
- (condition-case nil
- (funcall operation (round (* coefA arg)))
- (error))
- (select-window wind-B)
- (condition-case nil
- (funcall operation (round (* coefB arg)))
- (error))
- (if three-way
- (progn
- (select-window wind-C)
- (condition-case nil
- (funcall operation (round (* coefC arg)))
- (error))))
- (select-window wind)))
-
-(defun ediff-scroll-vertically (&optional arg)
- "Vertically scroll buffers A, B \(and C if appropriate\).
-With optional argument ARG, scroll ARG lines; otherwise scroll by nearly
-the one half of the height of window-A."
- (interactive "P")
- (ediff-barf-if-not-control-buffer)
-
- ;; make sure windows aren't dead
- (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
- (ediff-recenter 'no-rehighlight))
- (if (not (and (ediff-buffer-live-p ediff-buffer-A)
- (ediff-buffer-live-p ediff-buffer-B)
- (or (not ediff-3way-job)
- (ediff-buffer-live-p ediff-buffer-C))
- ))
- (error ediff-KILLED-VITAL-BUFFER))
-
- (ediff-operate-on-windows
- (if (memq last-command-char '(?v ?\C-v))
- 'scroll-up
- 'scroll-down)
- ;; calculate argument to scroll-up/down
- ;; if there is an explicit argument
- (if (and arg (not (equal arg '-)))
- ;; use it
- (prefix-numeric-value arg)
- ;; if not, see if we can determine a default amount (the window height)
- (let (default-amount)
- (setq default-amount
- (- (/ (min (window-height ediff-window-A)
- (window-height ediff-window-B)
- (if ediff-3way-job
- (window-height ediff-window-C)
- 500)) ; some large number
- 2)
- 1 next-screen-context-lines))
- ;; window found
- (if arg
- ;; C-u as argument means half of default amount
- (/ default-amount 2)
- ;; no argument means default amount
- default-amount)))))
-
-
-(defun ediff-scroll-horizontally (&optional arg)
- "Horizontally scroll buffers A, B \(and C if appropriate\).
-If an argument is given, that is how many columns are scrolled, else nearly
-the width of the A/B/C windows."
- (interactive "P")
- (ediff-barf-if-not-control-buffer)
-
- ;; make sure windows aren't dead
- (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
- (ediff-recenter 'no-rehighlight))
- (if (not (and (ediff-buffer-live-p ediff-buffer-A)
- (ediff-buffer-live-p ediff-buffer-B)
- (or (not ediff-3way-job)
- (ediff-buffer-live-p ediff-buffer-C))
- ))
- (error ediff-KILLED-VITAL-BUFFER))
-
- (ediff-operate-on-windows
- (if (= last-command-char ?<)
- 'scroll-left
- 'scroll-right)
- ;; calculate argument to scroll-left/right
- ;; if there is an explicit argument
- (if (and arg (not (equal arg '-)))
- ;; use it
- (prefix-numeric-value arg)
- ;; if not, see if we can determine a default amount
- ;; (half the window width)
- (if (null ediff-control-window)
- ;; no control window, use nil
- nil
- (let ((default-amount
- (- (/ (min (window-width ediff-window-A)
- (window-width ediff-window-B)
- (if ediff-3way-comparison-job
- (window-width ediff-window-C)
- 500) ; some large number
- )
- 2)
- 3)))
- ;; window found
- (if arg
- ;; C-u as argument means half of default amount
- (/ default-amount 2)
- ;; no argument means default amount
- default-amount))))))
-
-
-;;BEG, END show the region to be positioned.
-;;JOB-NAME holds ediff-job-name. The ediff-windows job positions regions
-;;differently.
-(defun ediff-position-region (beg end pos job-name)
- (if (> end (point-max))
- (setq end (point-max)))
- (if ediff-windows-job
- (if (pos-visible-in-window-p end)
- () ; do nothing, wind is already positioned
- ;; at this point, windows are positioned at the beginning of the
- ;; file regions (not diff-regions) being compared.
- (save-excursion
- (move-to-window-line (- (window-height) 2))
- (let ((amount (+ 2 (count-lines (point) end))))
- (scroll-up amount))))
- (set-window-start (selected-window) beg)
- (if (pos-visible-in-window-p end)
- ;; Determine the number of lines that the region occupies
- (let ((lines 0)
- (prev-point 0))
- (while ( and (> end (progn
- (move-to-window-line lines)
- (point)))
- ;; `end' may be beyond the window bottom, so check
- ;; that we are making progress
- (< prev-point (point)))
- (setq prev-point (point))
- (setq lines (1+ lines)))
- ;; And position the beginning on the right line
- (goto-char beg)
- (recenter (/ (1+ (max (- (1- (window-height (selected-window)))
- lines)
- 1)
- )
- 2))))
- (goto-char pos)
- ))
-
-;; get number of lines from window start to region end
-(defun ediff-get-lines-to-region-end (buf-type &optional n ctl-buf)
- (or n (setq n ediff-current-difference))
- (or ctl-buf (setq ctl-buf ediff-control-buffer))
- (ediff-eval-in-buffer ctl-buf
- (let* ((buf (ediff-get-buffer buf-type))
- (wind (eval (intern (format "ediff-window-%S" buf-type))))
- (beg (window-start wind))
- (end (ediff-get-diff-posn buf-type 'end))
- lines)
- (ediff-eval-in-buffer buf
- (if (< beg end)
- (setq lines (count-lines beg end))
- (setq lines 0))
- lines
- ))))
-
-;; get number of lines from window end to region start
-(defun ediff-get-lines-to-region-start (buf-type &optional n ctl-buf)
- (or n (setq n ediff-current-difference))
- (or ctl-buf (setq ctl-buf ediff-control-buffer))
- (ediff-eval-in-buffer ctl-buf
- (let* ((buf (ediff-get-buffer buf-type))
- (wind (eval (intern (format "ediff-window-%S" buf-type))))
- (end (window-end wind))
- (beg (ediff-get-diff-posn buf-type 'beg)))
- (ediff-eval-in-buffer buf
- (if (< beg end) (count-lines beg end) 0))
- )))
-
-
-;; region size coefficient is a coefficient by which to adjust scrolling
-;; up/down of the window displaying buffer of type BUFTYPE.
-;; The purpose of this coefficient is to make the windows scroll in sync, so
-;; that it won't happen that one diff region is scrolled off while the other is
-;; still seen.
-;;
-;; If the difference region is invalid, the coefficient is 1
-(defun ediff-get-region-size-coefficient (buf-type op &optional n ctl-buf)
- (ediff-eval-in-buffer (or ctl-buf ediff-control-buffer)
- (if (ediff-valid-difference-p n)
- (let* ((func (cond ((eq op 'scroll-down)
- 'ediff-get-lines-to-region-start)
- ((eq op 'scroll-up)
- 'ediff-get-lines-to-region-end)
- (t '(lambda (a b c) 0))))
- (max-lines (max (funcall func 'A n ctl-buf)
- (funcall func 'B n ctl-buf)
- (if (ediff-buffer-live-p ediff-buffer-C)
- (funcall func 'C n ctl-buf)
- 0))))
- ;; this covers the horizontal coefficient as well:
- ;; if max-lines = 0 then coef = 1
- (if (> max-lines 0)
- (/ (+ (funcall func buf-type n ctl-buf) 0.0)
- (+ max-lines 0.0))
- 1))
- 1)))
-
-
-(defun ediff-next-difference (&optional arg)
- "Advance to the next difference.
-With a prefix argument, go forward that many differences."
- (interactive "p")
- (ediff-barf-if-not-control-buffer)
- (if (< ediff-current-difference ediff-number-of-differences)
- (let ((n (min ediff-number-of-differences
- (+ ediff-current-difference arg)))
- regexp-skip)
-
- (or (>= n ediff-number-of-differences)
- (setq regexp-skip (funcall ediff-skip-diff-region-function n))
- (ediff-install-fine-diff-if-necessary n))
- (while (and (< n ediff-number-of-differences)
- (or
- ;; regexp skip
- regexp-skip
- ;; skip clashes, if necessary
- (and ediff-show-clashes-only
- (string-match "prefer"
- (or (ediff-get-state-of-merge n) "")))
- ;; skip difference regions that differ in white space
- (and ediff-ignore-similar-regions
- (ediff-no-fine-diffs-p n))))
- (setq n (1+ n))
- (if (= 0 (mod n 20))
- (message "Skipped over region %d and counting ..." n))
- (or (>= n ediff-number-of-differences)
- (setq regexp-skip (funcall ediff-skip-diff-region-function n))
- (ediff-install-fine-diff-if-necessary n))
- )
- (message "")
- (ediff-unselect-and-select-difference n)
- ) ; let
- (ediff-visible-region)
- (error "At end of the difference list")))
-
-(defun ediff-previous-difference (&optional arg)
- "Go to the previous difference.
-With a prefix argument, go back that many differences."
- (interactive "p")
- (ediff-barf-if-not-control-buffer)
- (if (> ediff-current-difference -1)
- (let ((n (max -1 (- ediff-current-difference arg)))
- regexp-skip)
-
- (or (< n 0)
- (setq regexp-skip (funcall ediff-skip-diff-region-function n))
- (ediff-install-fine-diff-if-necessary n))
- (while (and (> n -1)
- (or
- ;; regexp skip
- regexp-skip
- ;; skip clashes, if necessary
- (and ediff-show-clashes-only
- (string-match "prefer"
- (or (ediff-get-state-of-merge n) "")))
- ;; skip difference regions that differ in white space
- (and ediff-ignore-similar-regions
- (ediff-no-fine-diffs-p n))))
- (if (= 0 (mod (1+ n) 20))
- (message "Skipped over region %d and counting ..." (1+ n)))
- (setq n (1- n))
- (or (< n 0)
- (setq regexp-skip (funcall ediff-skip-diff-region-function n))
- (ediff-install-fine-diff-if-necessary n))
- )
- (message "")
- (ediff-unselect-and-select-difference n)
- ) ; let
- (ediff-visible-region)
- (error "At beginning of the difference list")))
-
-;; The diff number is as perceived by the user (i.e., 1+ the internal
-;; representation)
-(defun ediff-jump-to-difference (difference-number)
- "Go to the difference specified as a prefix argument.
-If the prefix is negative, count differences from the end."
- (interactive "p")
- (ediff-barf-if-not-control-buffer)
- (setq difference-number
- (cond ((< difference-number 0)
- (+ ediff-number-of-differences difference-number))
- ((> difference-number 0) (1- difference-number))
- (t -1)))
- ;; -1 is allowed by ediff-unselect-and-select-difference --- it is the
- ;; position before the first one.
- (if (and (>= difference-number -1)
- (<= difference-number ediff-number-of-differences))
- (ediff-unselect-and-select-difference difference-number)
- (error ediff-BAD-DIFF-NUMBER
- this-command (1+ difference-number) ediff-number-of-differences)))
-
-(defun ediff-jump-to-difference-at-point (arg)
- "Go to difference closest to the point in buffer A, B, or C.
-The buffer depends on last command character \(a, b, or c\) that invoked this
-command. For instance, if the command was `ga' then the point value in buffer A
-is used.
-With a prefix argument, synchronize all files around the current point position
-in the specified buffer."
- (interactive "P")
- (ediff-barf-if-not-control-buffer)
- (let* ((buf-type (ediff-char-to-buftype last-command-char))
- (buffer (ediff-get-buffer buf-type))
- (pt (ediff-eval-in-buffer buffer (point)))
- (diff-no (ediff-diff-at-point buf-type nil (if arg 'after)))
- (past-last-diff (< ediff-number-of-differences diff-no))
- (beg (if past-last-diff
- (ediff-eval-in-buffer buffer (point-max))
- (ediff-get-diff-posn buf-type 'beg (1- diff-no))))
- ctl-wind wind-A wind-B wind-C
- shift)
- (if past-last-diff
- (ediff-jump-to-difference -1)
- (ediff-jump-to-difference diff-no))
- (setq ctl-wind (selected-window)
- wind-A ediff-window-A
- wind-B ediff-window-B
- wind-C ediff-window-C)
- (if arg
- (progn
- (ediff-eval-in-buffer buffer
- (setq shift (- beg pt)))
- (select-window wind-A)
- (if past-last-diff (goto-char (point-max)))
- (condition-case nil
- (backward-char shift) ; noerror, if beginning of buffer
- (error))
- (recenter)
- (select-window wind-B)
- (if past-last-diff (goto-char (point-max)))
- (condition-case nil
- (backward-char shift) ; noerror, if beginning of buffer
- (error))
- (recenter)
- (if (window-live-p wind-C)
- (progn
- (select-window wind-C)
- (if past-last-diff (goto-char (point-max)))
- (condition-case nil
- (backward-char shift) ; noerror, if beginning of buffer
- (error))
- (recenter)
- ))
- (select-window ctl-wind)
- ))
- ))
-
-
-;; find region most related to the current point position (or POS, if given)
-;; returns diff number as seen by the user (i.e., 1+ the internal
-;; representation)
-;; The optional argument WHICH-DIFF can be `after' or `before'. If `after',
-;; find the diff after the point. If `before', find the diff before the
-;; point. If the point is inside a diff, return that diff.
-(defun ediff-diff-at-point (buf-type &optional pos which-diff)
- (let ((buffer (ediff-get-buffer buf-type))
- (ctl-buffer ediff-control-buffer)
- (max-dif-num (1- ediff-number-of-differences))
- (diff-no -1)
- (prev-beg 0)
- (prev-end 0)
- (beg 0)
- (end 0))
-
- (ediff-eval-in-buffer buffer
- (setq pos (or pos (point)))
- (while (and (or (< pos prev-beg) (> pos beg))
- (< diff-no max-dif-num))
- (setq diff-no (1+ diff-no))
- (setq prev-beg beg
- prev-end end)
- (setq beg (ediff-get-diff-posn buf-type 'beg diff-no ctl-buffer)
- end (ediff-get-diff-posn buf-type 'end diff-no ctl-buffer))
- )
-
- ;; boost diff-no by 1, if past the last diff region
- (if (and (memq which-diff '(after before))
- (> pos beg) (= diff-no max-dif-num))
- (setq diff-no (1+ diff-no)))
-
- (cond ((eq which-diff 'after) (1+ diff-no))
- ((eq which-diff 'before) diff-no)
- ((< (abs (count-lines pos (max 1 prev-end)))
- (abs (count-lines pos (max 1 beg))))
- diff-no) ; choose prev difference
- (t
- (1+ diff-no))) ; choose next difference
- )))
-
-
-;;; Copying diffs.
-
-(defun ediff-diff-to-diff (arg &optional keys)
- "Copy buffer-X'th difference region to buffer Y \(X,Y are A, B, or C\).
-If numerical prefix argument, copy the difference specified in the arg.
-Otherwise, copy the difference given by `ediff-current-difference'.
-This command assumes it is bound to a 2-character key sequence, `ab', `ba',
-`ac', etc., which is used to determine the types of buffers to be used for
-copying difference regions. The first character in the sequence specifies
-the source buffer and the second specifies the target.
-
-If the second optional argument, a 2-character string, is given, use it to
-determine the source and the target buffers instead of the command keys."
- (interactive "P")
- (ediff-barf-if-not-control-buffer)
- (or keys (setq keys (this-command-keys)))
- (if (eq arg '-) (setq arg -1)) ; translate neg arg to -1
- (if (numberp arg) (ediff-jump-to-difference arg))
-
- (let* ((key1 (aref keys 0))
- (key2 (aref keys 1))
- (char1 (if (and ediff-xemacs-p (eventp key1)) (event-key key1) key1))
- (char2 (if (and ediff-xemacs-p (eventp key1)) (event-key key2) key2))
- ediff-verbose-p)
- (ediff-copy-diff ediff-current-difference
- (ediff-char-to-buftype char1)
- (ediff-char-to-buftype char2))
- ;; recenter with rehighlighting, but no messages
- (ediff-recenter)))
-
-(defun ediff-copy-A-to-B (arg)
- "Copy ARGth difference region from buffer A to B.
-ARG is a prefix argument. If nil, copy the current difference region."
- (interactive "P")
- (ediff-diff-to-diff arg "ab"))
-
-(defun ediff-copy-B-to-A (arg)
- "Copy ARGth difference region from buffer B to A.
-ARG is a prefix argument. If nil, copy the current difference region."
- (interactive "P")
- (ediff-diff-to-diff arg "ba"))
-
-(defun ediff-copy-A-to-C (arg)
- "Copy ARGth difference region from buffer A to buffer C.
-ARG is a prefix argument. If nil, copy the current difference region."
- (interactive "P")
- (ediff-diff-to-diff arg "ac"))
-
-(defun ediff-copy-B-to-C (arg)
- "Copy ARGth difference region from buffer B to buffer C.
-ARG is a prefix argument. If nil, copy the current difference region."
- (interactive "P")
- (ediff-diff-to-diff arg "bc"))
-
-(defun ediff-copy-C-to-B (arg)
- "Copy ARGth difference region from buffer C to B.
-ARG is a prefix argument. If nil, copy the current difference region."
- (interactive "P")
- (ediff-diff-to-diff arg "cb"))
-
-(defun ediff-copy-C-to-A (arg)
- "Copy ARGth difference region from buffer C to A.
-ARG is a prefix argument. If nil, copy the current difference region."
- (interactive "P")
- (ediff-diff-to-diff arg "ca"))
-
-
-
-;; Copy diff N from FROM-BUF-TYPE \(given as A, B or C\) to TO-BUF-TYPE.
-;; If optional DO-NOT-SAVE is non-nil, do not save the old value of the
-;; target diff. This is used in merging, when constructing the merged
-;; version.
-(defun ediff-copy-diff (n from-buf-type to-buf-type
- &optional batch-invocation reg-to-copy)
- (let* ((to-buf (ediff-get-buffer to-buf-type))
- ;;(from-buf (if (not reg-to-copy) (ediff-get-buffer from-buf-type)))
- (ctrl-buf ediff-control-buffer)
- (saved-p t)
- (three-way ediff-3way-job)
- messg
- ediff-verbose-p
- reg-to-delete reg-to-delete-beg reg-to-delete-end)
-
- (setq reg-to-delete-beg
- (ediff-get-diff-posn to-buf-type 'beg n ctrl-buf))
- (setq reg-to-delete-end
- (ediff-get-diff-posn to-buf-type 'end n ctrl-buf))
-
- (if reg-to-copy
- (setq from-buf-type nil)
- (setq reg-to-copy (ediff-get-region-contents n from-buf-type ctrl-buf)))
-
- (setq reg-to-delete (ediff-get-region-contents
- n to-buf-type ctrl-buf
- reg-to-delete-beg reg-to-delete-end))
-
- (if (string= reg-to-delete reg-to-copy)
- (setq saved-p nil) ; don't copy identical buffers
- ;; seems ok to copy
- (if (or batch-invocation (ediff-test-save-region n to-buf-type))
- (condition-case conds
- (progn
- (ediff-eval-in-buffer to-buf
- ;; to prevent flags from interfering if buffer is writable
- (let ((inhibit-read-only (null buffer-read-only)))
-
- (goto-char reg-to-delete-end)
- (insert reg-to-copy)
-
- (if (> reg-to-delete-end reg-to-delete-beg)
- (kill-region reg-to-delete-beg reg-to-delete-end))
- ))
- (or batch-invocation
- (setq
- messg
- (ediff-save-diff-region n to-buf-type reg-to-delete))))
- (error (message "ediff-copy-diff: %s %s"
- (car conds)
- (mapconcat 'prin1-to-string (cdr conds) " "))
- (beep 1)
- (sit-for 2) ; let the user see the error msg
- (setq saved-p nil)
- )))
- )
-
- ;; adjust state of difference in case 3-way and diff was copied ok
- (if (and saved-p three-way)
- (ediff-set-state-of-diff-in-all-buffers n ctrl-buf))
-
- (if batch-invocation
- (ediff-clear-fine-differences n)
- ;; If diff3 job, we should recompute fine diffs so we clear them
- ;; before reinserting flags (and thus before ediff-recenter).
- (if (and saved-p three-way)
- (ediff-clear-fine-differences n))
-
- (ediff-refresh-mode-lines)
-
- ;; For diff2 jobs, don't recompute fine diffs, since we know there
- ;; aren't any. So we clear diffs after ediff-recenter.
- (if (and saved-p (not three-way))
- (ediff-clear-fine-differences n))
- ;; Make sure that the message about saving and how to restore is seen
- ;; by the user
- (message messg))
- ))
-
-;; Save Nth diff of buffer BUF-TYPE \(A, B, or C\).
-;; That is to say, the Nth diff on the `ediff-killed-diffs-alist'. REG
-;; is the region to save. It is redundant here, but is passed anyway, for
-;; convenience.
-(defun ediff-save-diff-region (n buf-type reg)
- (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
- (buf (ediff-get-buffer buf-type))
- (this-buf-n-th-diff-saved (assoc buf (cdr n-th-diff-saved))))
-
- (if this-buf-n-th-diff-saved
- ;; either nothing saved for n-th diff and buffer or we OK'ed
- ;; overriding
- (setcdr this-buf-n-th-diff-saved reg)
- (if n-th-diff-saved ;; n-th diff saved, but for another buffer
- (nconc n-th-diff-saved (list (cons buf reg)))
- (setq ediff-killed-diffs-alist ;; create record for n-th diff
- (cons (list n (cons buf reg))
- ediff-killed-diffs-alist))))
- (message "Saving old diff region #%d of buffer %S. To recover, type `r%s'"
- (1+ n) buf-type
- (if ediff-merge-job
- "" (downcase (symbol-name buf-type))))
- ))
-
-;; Test if saving Nth difference region of buffer BUF-TYPE is possible.
-(defun ediff-test-save-region (n buf-type)
- (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
- (buf (ediff-get-buffer buf-type))
- (this-buf-n-th-diff-saved (assoc buf (cdr n-th-diff-saved))))
-
- (if this-buf-n-th-diff-saved
- (if (yes-or-no-p
- (format
- "You've previously copied diff region %d to buffer %S. Confirm "
- (1+ n) buf-type))
- t
- (error "Quit"))
- t)))
-
-(defun ediff-pop-diff (n buf-type)
- "Pop last killed Nth diff region from buffer BUF-TYPE."
- (let* ((n-th-record (assoc n ediff-killed-diffs-alist))
- (buf (ediff-get-buffer buf-type))
- (saved-rec (assoc buf (cdr n-th-record)))
- (three-way ediff-3way-job)
- (ctl-buf ediff-control-buffer)
- ediff-verbose-p
- saved-diff reg-beg reg-end recovered)
-
- (if (cdr saved-rec)
- (setq saved-diff (cdr saved-rec))
- (if (> ediff-number-of-differences 0)
- (error "Nothing saved for diff %d in buffer %S" (1+ n) buf-type)
- (error ediff-NO-DIFFERENCES)))
-
- (setq reg-beg (ediff-get-diff-posn buf-type 'beg n ediff-control-buffer))
- (setq reg-end (ediff-get-diff-posn buf-type 'end n ediff-control-buffer))
-
- (condition-case conds
- (ediff-eval-in-buffer buf
- (let ((inhibit-read-only (null buffer-read-only)))
-
- (goto-char reg-end)
- (insert saved-diff)
-
- (if (> reg-end reg-beg)
- (kill-region reg-beg reg-end))
-
- (setq recovered t)
- ))
- (error (message "ediff-pop-diff: %s %s"
- (car conds)
- (mapconcat 'prin1-to-string (cdr conds) " "))
- (beep 1)))
-
- ;; Clearing fine diffs is necessary for
- ;; ediff-unselect-and-select-difference to properly recompute them. We
- ;; can't rely on ediff-copy-diff to clear this vector, as the user might
- ;; have modified diff regions after copying and, thus, may have recomputed
- ;; fine diffs.
- (if recovered
- (ediff-clear-fine-differences n))
-
- ;; adjust state of difference
- (if (and three-way recovered)
- (ediff-set-state-of-diff-in-all-buffers n ctl-buf))
-
- (ediff-refresh-mode-lines)
-
- (if recovered
- (progn
- (setq n-th-record (delq saved-rec n-th-record))
- (message "Diff region %d in buffer %S restored" (1+ n) buf-type)
- ))
- ))
-
-(defun ediff-restore-diff (arg &optional key)
- "Restore ARGth diff from `ediff-killed-diffs-alist'.
-ARG is a prefix argument. If ARG is nil, restore the current-difference.
-If the second optional argument, a character, is given, use it to
-determine the target buffer instead of last-command-char"
- (interactive "P")
- (ediff-barf-if-not-control-buffer)
- (if (numberp arg)
- (ediff-jump-to-difference arg))
- (ediff-pop-diff ediff-current-difference
- (ediff-char-to-buftype (or key last-command-char)))
- ;; recenter with rehighlighting, but no messages
- (let (ediff-verbose-p)
- (ediff-recenter)))
-
-(defun ediff-restore-diff-in-merge-buffer (arg)
- "Restore ARGth diff in the merge buffer.
-ARG is a prefix argument. If nil, restore the current diff."
- (interactive "P")
- (ediff-restore-diff arg ?c))
-
-
-(defun ediff-toggle-regexp-match ()
- "Toggle between focusing and hiding of difference regions that match
-a regular expression typed in by the user."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (let ((regexp-A "")
- (regexp-B "")
- (regexp-C "")
- msg-connective alt-msg-connective alt-connective)
- (cond
- ((or (and (eq ediff-skip-diff-region-function
- ediff-focus-on-regexp-matches-function)
- (eq last-command-char ?f))
- (and (eq ediff-skip-diff-region-function
- ediff-hide-regexp-matches-function)
- (eq last-command-char ?h)))
- (message "Selective browsing by regexp turned off")
- (setq ediff-skip-diff-region-function 'ediff-show-all-diffs))
- ((eq last-command-char ?h)
- (setq ediff-skip-diff-region-function ediff-hide-regexp-matches-function
- regexp-A
- (read-string
- (format
- "Ignore A-regions matching this regexp (default \"%s\"): "
- ediff-regexp-hide-A))
- regexp-B
- (read-string
- (format
- "Ignore B-regions matching this regexp (default \"%s\"): "
- ediff-regexp-hide-B)))
- (if ediff-3way-comparison-job
- (setq regexp-C
- (read-string
- (format
- "Ignore C-regions matching this regexp (default \"%s\"): "
- ediff-regexp-hide-C))))
- (if (eq ediff-hide-regexp-connective 'and)
- (setq msg-connective "BOTH"
- alt-msg-connective "ONE OF"
- alt-connective 'or)
- (setq msg-connective "ONE OF"
- alt-msg-connective "BOTH"
- alt-connective 'and))
- (if (y-or-n-p
- (format
- "Ignore regions that match %s regexps, OK? "
- msg-connective alt-msg-connective))
- (message "Will ignore regions that match %s regexps" msg-connective)
- (setq ediff-hide-regexp-connective alt-connective)
- (message "Will ignore regions that match %s regexps"
- alt-msg-connective))
-
- (or (string= regexp-A "") (setq ediff-regexp-hide-A regexp-A))
- (or (string= regexp-B "") (setq ediff-regexp-hide-B regexp-B))
- (or (string= regexp-C "") (setq ediff-regexp-hide-C regexp-C)))
-
- ((eq last-command-char ?f)
- (setq ediff-skip-diff-region-function
- ediff-focus-on-regexp-matches-function
- regexp-A
- (read-string
- (format
- "Focus on A-regions matching this regexp (default \"%s\"): "
- ediff-regexp-focus-A))
- regexp-B
- (read-string
- (format
- "Focus on B-regions matching this regexp (default \"%s\"): "
- ediff-regexp-focus-B)))
- (if ediff-3way-comparison-job
- (setq regexp-C
- (read-string
- (format
- "Focus on C-regions matching this regexp (default \"%s\"): "
- ediff-regexp-focus-C))))
- (if (eq ediff-focus-regexp-connective 'and)
- (setq msg-connective "BOTH"
- alt-msg-connective "ONE OF"
- alt-connective 'or)
- (setq msg-connective "ONE OF"
- alt-msg-connective "BOTH"
- alt-connective 'and))
- (if (y-or-n-p
- (format
- "Focus on regions that match %s regexps, OK? "
- msg-connective alt-msg-connective))
- (message "Will focus on regions that match %s regexps"
- msg-connective)
- (setq ediff-focus-regexp-connective alt-connective)
- (message "Will focus on regions that match %s regexps"
- alt-msg-connective))
-
- (or (string= regexp-A "") (setq ediff-regexp-focus-A regexp-A))
- (or (string= regexp-B "") (setq ediff-regexp-focus-B regexp-B))
- (or (string= regexp-C "") (setq ediff-regexp-focus-C regexp-C))))))
-
-(defun ediff-toggle-skip-similar ()
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (if (not (eq ediff-auto-refine 'on))
- (error
- "Can't skip over whitespace regions: first turn auto-refining on"))
- (setq ediff-ignore-similar-regions (not ediff-ignore-similar-regions))
- (if ediff-ignore-similar-regions
- (message
- "Skipping regions that differ only in white space & line breaks")
- (message "Skipping over white-space differences turned off")))
-
-(defun ediff-focus-on-regexp-matches (n)
- "Focus on diffs that match regexp `ediff-regexp-focus-A/B'.
-Regions to be ignored according to this function are those where
-buf A region doesn't match `ediff-regexp-focus-A' and buf B region
-doesn't match `ediff-regexp-focus-B'.
-This function returns nil if the region number N (specified as
-an argument) is not to be ignored and t if region N is to be ignored.
-
-N is a region number used by Ediff internally. It is 1 less
-the number seen by the user."
- (if (ediff-valid-difference-p n)
- (let* ((ctl-buf ediff-control-buffer)
- (regex-A ediff-regexp-focus-A)
- (regex-B ediff-regexp-focus-B)
- (regex-C ediff-regexp-focus-C)
- (reg-A-match (ediff-eval-in-buffer ediff-buffer-A
- (save-restriction
- (narrow-to-region
- (ediff-get-diff-posn 'A 'beg n ctl-buf)
- (ediff-get-diff-posn 'A 'end n ctl-buf))
- (goto-char (point-min))
- (re-search-forward regex-A nil t))))
- (reg-B-match (ediff-eval-in-buffer ediff-buffer-B
- (save-restriction
- (narrow-to-region
- (ediff-get-diff-posn 'B 'beg n ctl-buf)
- (ediff-get-diff-posn 'B 'end n ctl-buf))
- (re-search-forward regex-B nil t))))
- (reg-C-match (if ediff-3way-comparison-job
- (ediff-eval-in-buffer ediff-buffer-C
- (save-restriction
- (narrow-to-region
- (ediff-get-diff-posn 'C 'beg n ctl-buf)
- (ediff-get-diff-posn 'C 'end n ctl-buf))
- (re-search-forward regex-C nil t))))))
- (not (eval (if ediff-3way-comparison-job
- (list ediff-focus-regexp-connective
- reg-A-match reg-B-match reg-C-match)
- (list ediff-focus-regexp-connective
- reg-A-match reg-B-match))))
- )))
-
-(defun ediff-hide-regexp-matches (n)
- "Hide diffs that match regexp `ediff-regexp-hide-A/B/C'.
-Regions to be ignored are those where buf A region matches
-`ediff-regexp-hide-A' and buf B region matches `ediff-regexp-hide-B'.
-This function returns nil if the region number N (specified as
-an argument) is not to be ignored and t if region N is to be ignored.
-
-N is a region number used by Ediff internally. It is 1 less
-the number seen by the user."
- (if (ediff-valid-difference-p n)
- (let* ((ctl-buf ediff-control-buffer)
- (regex-A ediff-regexp-hide-A)
- (regex-B ediff-regexp-hide-B)
- (regex-C ediff-regexp-hide-C)
- (reg-A-match (ediff-eval-in-buffer ediff-buffer-A
- (save-restriction
- (narrow-to-region
- (ediff-get-diff-posn 'A 'beg n ctl-buf)
- (ediff-get-diff-posn 'A 'end n ctl-buf))
- (goto-char (point-min))
- (re-search-forward regex-A nil t))))
- (reg-B-match (ediff-eval-in-buffer ediff-buffer-B
- (save-restriction
- (narrow-to-region
- (ediff-get-diff-posn 'B 'beg n ctl-buf)
- (ediff-get-diff-posn 'B 'end n ctl-buf))
- (goto-char (point-min))
- (re-search-forward regex-B nil t))))
- (reg-C-match (if ediff-3way-comparison-job
- (ediff-eval-in-buffer ediff-buffer-C
- (save-restriction
- (narrow-to-region
- (ediff-get-diff-posn 'C 'beg n ctl-buf)
- (ediff-get-diff-posn 'C 'end n ctl-buf))
- (goto-char (point-min))
- (re-search-forward regex-C nil t))))))
- (eval (if ediff-3way-comparison-job
- (list ediff-hide-regexp-connective
- reg-A-match reg-B-match reg-C-match)
- (list ediff-hide-regexp-connective reg-A-match reg-B-match)))
- )))
-
-
-
-;;; Quitting, suspending, etc.
-
-(defun ediff-quit (reverse-default-keep-variants)
- "Finish an Ediff session and exit Ediff.
-Unselects the selected difference, if any, restores the read-only and modified
-flags of the compared file buffers, kills Ediff buffers for this session
-\(but not buffers A, B, C\).
-
-If `ediff-keep-variants' is nil, the user will be asked whether the buffers
-containing the variants should be removed \(if they haven't been modified\).
-If it is t, they will be preserved unconditionally. A prefix argument,
-temporarily reverses the meaning of this variable."
- (interactive "P")
- (ediff-barf-if-not-control-buffer)
- (if (y-or-n-p (format "Quit this Ediff session%s? "
- (if (ediff-buffer-live-p ediff-meta-buffer)
- " & show containing session group" "")))
- (progn
- (message "")
- (ediff-really-quit reverse-default-keep-variants))
- (message "")))
-
-
-;; Perform the quit operations.
-(defun ediff-really-quit (reverse-default-keep-variants)
- (ediff-unhighlight-diffs-totally)
- (ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also)
- (ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also)
- (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
- (ediff-clear-diff-vector 'ediff-difference-vector-Ancestor 'fine-diffs-also)
-
- (ediff-delete-temp-files)
-
- ;; Restore visibility range. This affects only ediff-*-regions/windows.
- ;; Since for other job names ediff-visible-region sets
- ;; ediff-visible-bounds to ediff-wide-bounds, the settings below are
- ;; ignored for such jobs.
- (if ediff-quit-widened
- (setq ediff-visible-bounds ediff-wide-bounds)
- (setq ediff-visible-bounds ediff-narrow-bounds))
-
- ;; Apply selective display to narrow or widen
- (ediff-visible-region)
- (mapcar (function (lambda (overl)
- (if (ediff-overlayp overl)
- (ediff-delete-overlay overl))))
- ediff-wide-bounds)
- (mapcar (function (lambda (overl)
- (if (ediff-overlayp overl)
- (ediff-delete-overlay overl))))
- ediff-narrow-bounds)
-
- ;; restore buffer mode line id's in buffer-A/B/C
- (let ((control-buffer ediff-control-buffer)
- (meta-buffer ediff-meta-buffer)
- ;; suitable working frame
- (warp-frame (if (and (ediff-window-display-p) (eq ediff-grab-mouse t))
- (cond ((window-live-p ediff-window-A)
- (window-frame ediff-window-A))
- ((window-live-p ediff-window-B)
- (window-frame ediff-window-B))
- (t (next-frame))))))
- (condition-case nil
- (ediff-eval-in-buffer ediff-buffer-A
- (setq ediff-this-buffer-ediff-sessions
- (delq control-buffer ediff-this-buffer-ediff-sessions))
- (kill-local-variable 'mode-line-buffer-identification)
- (kill-local-variable 'mode-line-format)
- )
- (error))
-
- (condition-case nil
- (ediff-eval-in-buffer ediff-buffer-B
- (setq ediff-this-buffer-ediff-sessions
- (delq control-buffer ediff-this-buffer-ediff-sessions))
- (kill-local-variable 'mode-line-buffer-identification)
- (kill-local-variable 'mode-line-format)
- )
- (error))
-
- (condition-case nil
- (ediff-eval-in-buffer ediff-buffer-C
- (setq ediff-this-buffer-ediff-sessions
- (delq control-buffer ediff-this-buffer-ediff-sessions))
- (kill-local-variable 'mode-line-buffer-identification)
- (kill-local-variable 'mode-line-format)
- )
- (error))
-
- (condition-case nil
- (ediff-eval-in-buffer ediff-ancestor-buffer
- (setq ediff-this-buffer-ediff-sessions
- (delq control-buffer ediff-this-buffer-ediff-sessions))
- (kill-local-variable 'mode-line-buffer-identification)
- (kill-local-variable 'mode-line-format)
- )
- (error))
-
- (setq ediff-session-registry
- (delq ediff-control-buffer ediff-session-registry))
- (ediff-update-registry)
- ;; restore state of buffers to what it was before ediff
- (ediff-restore-protected-variables)
-
- ;; If the user interrupts (canceling saving the merge buffer), continue
- ;; normally.
- (condition-case nil
- (if (ediff-merge-job)
- (run-hooks 'ediff-quit-merge-hook))
- (quit))
-
- ;; good place to kill buffers A/B/C
- (run-hooks 'ediff-cleanup-hook)
- (let ((ediff-keep-variants ediff-keep-variants))
- (if reverse-default-keep-variants
- (setq ediff-keep-variants (not ediff-keep-variants)))
- (or ediff-keep-variants (ediff-janitor 'ask)))
-
- (run-hooks 'ediff-quit-hook)
- (ediff-cleanup-meta-buffer meta-buffer)
-
- ;; warp mouse into a working window
- (setq warp-frame ; if mouse is over a reasonable frame, use it
- (cond ((and ediff-xemacs-p (window-live-p (car (mouse-position))))
- (window-frame (car (mouse-position))))
- ((frame-live-p (car (mouse-position)))
- (car (mouse-position)))
- (t warp-frame)))
- (if (frame-live-p warp-frame)
- (set-mouse-position (if ediff-emacs-p
- warp-frame
- (frame-selected-window warp-frame))
- 2 1))
-
- (if (ediff-buffer-live-p meta-buffer)
- (ediff-show-meta-buffer meta-buffer))
- ))
-
-
-(defun ediff-delete-temp-files ()
- (if (stringp ediff-temp-file-A)
- (delete-file ediff-temp-file-A))
- (if (stringp ediff-temp-file-B)
- (delete-file ediff-temp-file-B))
- (if (stringp ediff-temp-file-C)
- (delete-file ediff-temp-file-C)))
-
-
-;; Kill control buffer, other auxiliary Ediff buffers.
-;; Leave one of the frames split between buffers A/B/C
-(defun ediff-cleanup-mess ()
- (let ((buff-A ediff-buffer-A)
- (buff-B ediff-buffer-B)
- (buff-C ediff-buffer-C)
- (ctl-buf ediff-control-buffer)
- (ctl-frame ediff-control-frame)
- (three-way-job ediff-3way-job))
-
- (ediff-kill-buffer-carefully ediff-diff-buffer)
- (ediff-kill-buffer-carefully ediff-custom-diff-buffer)
- (ediff-kill-buffer-carefully ediff-fine-diff-buffer)
- (ediff-kill-buffer-carefully ediff-tmp-buffer)
- (ediff-kill-buffer-carefully ediff-error-buffer)
- (ediff-kill-buffer-carefully ediff-patch-diagnostics)
- (ediff-kill-buffer-carefully ediff-msg-buffer)
- (ediff-kill-buffer-carefully ediff-debug-buffer)
-
- (if (and (ediff-window-display-p) (frame-live-p ctl-frame))
- (delete-frame ctl-frame))
- ;; Hide bottom toolbar. --marcpa
- (if (not (ediff-multiframe-setup-p))
- (ediff-kill-bottom-toolbar))
-
- (ediff-kill-buffer-carefully ctl-buf)
-
- (delete-other-windows)
-
- ;; display only if not visible
- (condition-case nil
- (or (ediff-get-visible-buffer-window buff-B)
- (switch-to-buffer buff-B))
- (error))
- (condition-case nil
- (or (ediff-get-visible-buffer-window buff-A)
- (progn
- (if (ediff-get-visible-buffer-window buff-B)
- (funcall ediff-split-window-function))
- (switch-to-buffer buff-A)))
- (error))
- (if three-way-job
- (condition-case nil
- (or (ediff-get-visible-buffer-window buff-C)
- (progn
- (if (or (ediff-get-visible-buffer-window buff-A)
- (ediff-get-visible-buffer-window buff-B))
- (funcall ediff-split-window-function))
- (switch-to-buffer buff-C)
- (balance-windows)))
- (error)))
- (message "")
- ))
-
-(defun ediff-janitor (&optional ask)
- "Kill buffers A, B, and, possibly, C, if these buffers aren't modified.
-In merge jobs, buffer C is never deleted.
-However, the side effect of cleaning up may be that you cannot compare the same
-buffer in two separate Ediff sessions: quitting one of them will delete this
-buffer in another session as well."
- (or (not (ediff-buffer-live-p ediff-buffer-A))
- (buffer-modified-p ediff-buffer-A)
- (and ask
- (not (y-or-n-p (format "Kill buffer A [%s]? "
- (buffer-name ediff-buffer-A)))))
- (ediff-kill-buffer-carefully ediff-buffer-A))
- (or (not (ediff-buffer-live-p ediff-buffer-B))
- (buffer-modified-p ediff-buffer-B)
- (and ask
- (not (y-or-n-p (format "Kill buffer B [%s]? "
- (buffer-name ediff-buffer-B)))))
- (ediff-kill-buffer-carefully ediff-buffer-B))
- (if ediff-merge-job ; don't del buf C if merging--del ancestor buf instead
- (or (not (ediff-buffer-live-p ediff-ancestor-buffer))
- (buffer-modified-p ediff-ancestor-buffer)
- (and ask
- (not (y-or-n-p (format "Kill the ancestor buffer [%s]? "
- (buffer-name ediff-ancestor-buffer)))))
- (ediff-kill-buffer-carefully ediff-ancestor-buffer))
- (or (not (ediff-buffer-live-p ediff-buffer-C))
- (buffer-modified-p ediff-buffer-C)
- (and ask (not (y-or-n-p (format "Kill buffer C [%s]? "
- (buffer-name ediff-buffer-C)))))
- (ediff-kill-buffer-carefully ediff-buffer-C))))
-
-(defun ediff-maybe-save-and-delete-merge ()
- "Default hook to run on quitting a merge job.
-If `ediff-autostore-merges' is nil, this does nothing.
-If it is t, it saves the merge buffer in the file `ediff-merge-store-file'
-or asks the user, if the latter is nil. It then then asks the user whether to
-delete the merge buffer.
-If `ediff-autostore-merges' is neither nil nor t, the merge buffer is saved
-only if this merge job is part of a group, i.e., was invoked from within
-`ediff-merge-directories', `ediff-merge-directory-revisions', and such."
- (let ((merge-store-file ediff-merge-store-file))
- (if ediff-autostore-merges
- (cond ((stringp ediff-merge-store-file)
- ;; store, ask to delete
- (ediff-write-merge-buffer-then-kill
- ediff-buffer-C merge-store-file 'show-file))
- ((eq ediff-autostore-merges t)
- ;; ask for file name
- (setq merge-store-file
- (read-file-name "Save the result of the merge in: "))
- (ediff-write-merge-buffer-then-kill
- ediff-buffer-C merge-store-file))
- ((and (ediff-buffer-live-p ediff-meta-buffer)
- (ediff-eval-in-buffer ediff-meta-buffer
- (ediff-merge-metajob)))
- ;; This case shouldn't occur, as the parent metajob must pass on
- ;; a file name, ediff-merge-store-file, where to save the result
- ;; of the merge.
- ;; Ask where to save anyway--will decide what to do here later.
- (setq merge-store-file
- (read-file-name "The result of the merge goes into: "))
- (ediff-write-merge-buffer-then-kill
- ediff-buffer-C merge-store-file))))
- ))
-
-(defun ediff-write-merge-buffer-then-kill (buf file &optional show-file)
- (ediff-eval-in-buffer buf
- (if (or (not (file-exists-p file))
- (y-or-n-p (format "File %s exists, overwrite? " file)))
- (progn
- (write-region (point-min) (point-max) file)
- (if show-file
- (progn
- (message "Merge buffer saved in: %s" file)
- (sit-for 2)))
- (if (y-or-n-p "Merge buffer saved in file. Now kill the buffer? ")
- (ediff-kill-buffer-carefully buf))))))
-
-;; The default way of suspending Ediff.
-;; Buries Ediff buffers, kills all windows.
-(defun ediff-default-suspend-function ()
- (let* ((buf-A ediff-buffer-A)
- (buf-B ediff-buffer-B)
- (buf-C ediff-buffer-C)
- (buf-A-wind (ediff-get-visible-buffer-window buf-A))
- (buf-B-wind (ediff-get-visible-buffer-window buf-B))
- (buf-C-wind (ediff-get-visible-buffer-window buf-C))
- (buf-patch ediff-patchbufer)
- (buf-patch-diag ediff-patch-diagnostics)
- (buf-err ediff-error-buffer)
- (buf-diff ediff-diff-buffer)
- (buf-custom-diff ediff-custom-diff-buffer)
- (buf-fine-diff ediff-fine-diff-buffer))
-
- ;; hide the control panel
- (if (and (ediff-window-display-p) (frame-live-p ediff-control-frame))
- (iconify-frame ediff-control-frame)
- (bury-buffer))
- (if buf-err (bury-buffer buf-err))
- (if buf-diff (bury-buffer buf-diff))
- (if buf-custom-diff (bury-buffer buf-custom-diff))
- (if buf-fine-diff (bury-buffer buf-fine-diff))
- (if buf-patch (bury-buffer buf-patch))
- (if buf-patch-diag (bury-buffer buf-patch-diag))
- (if (window-live-p buf-A-wind)
- (progn
- (select-window buf-A-wind)
- (delete-other-windows)
- (bury-buffer))
- (if (ediff-buffer-live-p buf-A) (bury-buffer buf-A)))
- (if (window-live-p buf-B-wind)
- (progn
- (select-window buf-B-wind)
- (delete-other-windows)
- (bury-buffer))
- (if (ediff-buffer-live-p buf-B) (bury-buffer buf-B)))
- (if (window-live-p buf-C-wind)
- (progn
- (select-window buf-C-wind)
- (delete-other-windows)
- (bury-buffer))
- (if (ediff-buffer-live-p buf-C) (bury-buffer buf-C)))
-
- ))
-
-
-(defun ediff-suspend ()
- "Suspend Ediff.
-To resume, switch to the appropriate `Ediff Control Panel'
-buffer and then type \\[ediff-recenter]. Ediff will automatically set
-up an appropriate window config."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (run-hooks 'ediff-suspend-hook)
- (message
- "To resume, type M-x eregistry and select the desired Ediff session"))
-
-
-(defun ediff-status-info ()
- "Show the names of the buffers or files being operated on by Ediff.
-Hit \\[ediff-recenter] to reset the windows afterward."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (save-excursion
- (ediff-skip-unsuitable-frames))
- (with-output-to-temp-buffer ediff-msg-buffer
- (raise-frame (selected-frame))
- (princ (ediff-version))
- (princ "\n\n")
- (ediff-eval-in-buffer ediff-buffer-A
- (if buffer-file-name
- (princ
- (format "File A = %S\n" buffer-file-name))
- (princ
- (format "Buffer A = %S\n" (buffer-name)))))
- (ediff-eval-in-buffer ediff-buffer-B
- (if buffer-file-name
- (princ
- (format "File B = %S\n" buffer-file-name))
- (princ
- (format "Buffer B = %S\n" (buffer-name)))))
- (if ediff-3way-job
- (ediff-eval-in-buffer ediff-buffer-C
- (if buffer-file-name
- (princ
- (format "File C = %S\n" buffer-file-name))
- (princ
- (format "Buffer C = %S\n" (buffer-name))))))
- (princ (format "Customized diff output %s\n"
- (if (ediff-buffer-live-p ediff-custom-diff-buffer)
- (concat "\tin buffer "
- (buffer-name ediff-custom-diff-buffer))
- "is not available")))
- (princ (format "Plain diff output %s\n"
- (if (ediff-buffer-live-p ediff-diff-buffer)
- (concat "\tin buffer "
- (buffer-name ediff-diff-buffer))
- "is not available")))
-
- (let* ((A-line (ediff-eval-in-buffer ediff-buffer-A
- (1+ (count-lines (point-min) (point)))))
- (B-line (ediff-eval-in-buffer ediff-buffer-B
- (1+ (count-lines (point-min) (point)))))
- C-line)
- (princ (format "\Buffer A's point is on line %d\n" A-line))
- (princ (format "Buffer B's point is on line %d\n" B-line))
- (if ediff-3way-job
- (progn
- (setq C-line (ediff-eval-in-buffer ediff-buffer-C
- (1+ (count-lines (point-min) (point)))))
- (princ (format "Buffer C's point is on line %d\n" C-line)))))
-
- (princ (format "\nCurrent difference number = %S\n"
- (cond ((< ediff-current-difference 0) 'start)
- ((>= ediff-current-difference
- ediff-number-of-differences) 'end)
- (t (1+ ediff-current-difference)))))
-
- (princ
- (format "\n%s regions that differ only in white space & line breaks"
- (if ediff-ignore-similar-regions
- "Skipping" "Not skipping")))
- (if (and ediff-merge-job ediff-show-clashes-only)
- (princ
- "\nFocusing on regions where both buffers differ from the ancestor"))
-
- (cond ((eq ediff-skip-diff-region-function 'ediff-show-all-diffs)
- (princ "\nSelective browsing by regexp is off\n"))
- ((eq ediff-skip-diff-region-function
- ediff-hide-regexp-matches-function)
- (princ
- "\nIgnoring regions that match")
- (princ
- (format
- "\n\t regexp `%s' in buffer A %S\n\t regexp `%s' in buffer B\n"
- ediff-regexp-hide-A ediff-hide-regexp-connective
- ediff-regexp-hide-B)))
- ((eq ediff-skip-diff-region-function
- ediff-focus-on-regexp-matches-function)
- (princ
- "\nFocusing on regions that match")
- (princ
- (format
- "\n\t regexp `%s' in buffer A %S\n\t regexp `%s' in buffer B\n"
- ediff-regexp-focus-A ediff-focus-regexp-connective
- ediff-regexp-focus-B)))
- (t (princ "\nSelective browsing via a user-defined method.\n")))
-
- (princ
- (format "\nBugs/suggestions: type `%s' while in Ediff Control Panel."
- (substitute-command-keys "\\[ediff-submit-report]")))
- ) ; with output
- (if (frame-live-p ediff-control-frame)
- (ediff-reset-mouse ediff-control-frame))
- (if (window-live-p ediff-control-window)
- (select-window ediff-control-window)))
-
-
-
-
-;;; Support routines
-
-;; Select a difference by placing the ASCII flags around the appropriate
-;; group of lines in the A, B buffers
-;; This may have to be modified for buffer C, when it will be supported.
-(defun ediff-select-difference (n)
- (if (and (ediff-buffer-live-p ediff-buffer-A)
- (ediff-buffer-live-p ediff-buffer-B)
- (ediff-valid-difference-p n))
- (progn
- (if (and (ediff-has-face-support-p) ediff-use-faces)
- (progn
- (ediff-highlight-diff n)
- (setq ediff-highlighting-style 'face))
- (setq ediff-highlighting-style 'ascii)
- (ediff-place-flags-in-buffer
- 'A ediff-buffer-A ediff-control-buffer n)
- (ediff-place-flags-in-buffer
- 'B ediff-buffer-B ediff-control-buffer n)
- (if ediff-3way-job
- (ediff-place-flags-in-buffer
- 'C ediff-buffer-C ediff-control-buffer n))
- (if (ediff-buffer-live-p ediff-ancestor-buffer)
- (ediff-place-flags-in-buffer
- 'Ancestor ediff-ancestor-buffer
- ediff-control-buffer n))
- )
-
- (ediff-install-fine-diff-if-necessary n)
- (run-hooks 'ediff-select-hook))))
-
-
-;; Unselect a difference by removing the ASCII flags in the buffers.
-;; This may have to be modified for buffer C, when it will be supported.
-(defun ediff-unselect-difference (n)
- (if (ediff-valid-difference-p n)
- (progn
- (cond ((and (ediff-has-face-support-p) ediff-use-faces)
- (ediff-unhighlight-diff))
- ((eq ediff-highlighting-style 'ascii)
- (ediff-remove-flags-from-buffer
- ediff-buffer-A
- (ediff-get-diff-overlay n 'A))
- (ediff-remove-flags-from-buffer
- ediff-buffer-B
- (ediff-get-diff-overlay n 'B))
- (if ediff-3way-job
- (ediff-remove-flags-from-buffer
- ediff-buffer-C
- (ediff-get-diff-overlay n 'C)))
- (if (ediff-buffer-live-p ediff-ancestor-buffer)
- (ediff-remove-flags-from-buffer
- ediff-ancestor-buffer
- (ediff-get-diff-overlay n 'Ancestor)))
- ))
- (setq ediff-highlighting-style nil)
-
- ;; unhighlight fine diffs
- (ediff-set-fine-diff-properties ediff-current-difference 'default)
- (run-hooks 'ediff-unselect-hook))))
-
-
-;; Unselects prev diff and selects a new one, if FLAG has value other than
-;; 'select-only or 'unselect-only. If FLAG is 'select-only, the
-;; next difference is selected, but the current selection is not
-;; unselected. If FLAG is 'unselect-only then the current selection is
-;; unselected, but the next one is not selected. If NO-RECENTER is non-nil,
-;; don't recenter buffers after selecting/unselecting.
-(defun ediff-unselect-and-select-difference (n &optional flag no-recenter)
- (let ((ediff-current-difference n))
- (or no-recenter
- (ediff-recenter 'no-rehighlight)))
-
- (let ((control-buf ediff-control-buffer))
- (unwind-protect
- (progn
- (or (eq flag 'select-only)
- (ediff-unselect-difference ediff-current-difference))
-
- (or (eq flag 'unselect-only)
- (ediff-select-difference n))
- (setq ediff-current-difference n)
- ) ; end protected section
-
- (ediff-eval-in-buffer control-buf (ediff-refresh-mode-lines))
- )))
-
-
-(defun ediff-read-file-name (prompt default-dir default-file)
-; This is a modified version of a similar function in `emerge.el'.
-; PROMPT should not have trailing ': ', so that it can be modified
-; according to context.
-; If default-file is set, it should be used as the default value.
-; If default-dir is non-nil, use it as the default directory.
-; Otherwise, use the value of Emacs' variable `default-directory.'
-
- ;; hack default-dir if it is not set
- (setq default-dir
- (file-name-as-directory
- (ediff-abbreviate-file-name
- (expand-file-name (or default-dir
- (and default-file
- (file-name-directory default-file))
- default-directory)))))
-
- ;; strip the directory from default-file
- (if default-file
- (setq default-file (file-name-nondirectory default-file)))
- (if (string= default-file "")
- (setq default-file nil))
-
- (let (f)
- (setq f (expand-file-name
- (read-file-name
- (format "%s%s "
- prompt
- (cond (default-file
- (concat " (default " default-file "):"))
- (t (concat " (default " default-dir "):"))))
- default-dir
- (or default-file default-dir)
- t ; must match, no-confirm
- (if default-file (file-name-directory default-file))
- )
- default-dir
- ))
- ;; If user enters a directory name, expand the default file in that
- ;; directory. This allows the user to enter a directory name for the
- ;; B-file and diff against the default-file in that directory instead
- ;; of a DIRED listing!
- (if (and (file-directory-p f) default-file)
- (setq f (expand-file-name
- (file-name-nondirectory default-file) f)))
- f))
-
-;; If PREFIX is given, then it is used as a prefix for the temp file
-;; name. Otherwise, `ediff_' is used. If FILE is given, use this
-;; file and don't create a new one.
-;; On MS-DOS, make sure the prefix isn't longer than 7 characters, or
-;; else `make-temp-name' isn't guaranteed to return a unique filename.
-;; Also, save buffer from START to END in the file.
-;; START defaults to (point-min), END to (point-max)
-(defun ediff-make-temp-file (buff &optional prefix given-file start end)
- (let ((p (or prefix "ediff"))
- f)
- (if (and (eq system-type 'ms-dos) (> (length p) 7))
- (setq p (substring p 0 7)))
-
- (setq f (concat ediff-temp-file-prefix p)
- f (cond (given-file)
- ((find-file-name-handler f 'find-file-noselect)
- ;; to thwart file handlers in write-region, e.g., if file
- ;; name ends with .Z or .gz
- ;; This is needed so that patches produced by ediff will
- ;; have more meaningful names
- (make-temp-name f))
- ;; Prefix is most often the same as the file name for the
- ;; variant. Here we are trying to use the original file name
- ;; but in the temp directory.
- ((and prefix (not (file-exists-p f))) f)
- ;; If a file with the orig name exists, add some random stuff
- ;; to it.
- (t (make-temp-name f))))
-
- ;; create the file
- (ediff-eval-in-buffer buff
- (write-region (if start start (point-min))
- (if end end (point-max))
- f
- nil ; don't append---erase
- 'no-message)
- (set-file-modes f ediff-temp-file-mode)
- (ediff-convert-standard-filename (expand-file-name f)))))
-
-;; Quote metacharacters (using \) when executing diff in Unix, but not in
-;; EMX OS/2
-;;(defun ediff-protect-metachars (str)
-;; (or (memq system-type '(emx vax-vms axp-vms))
-;; (let ((limit 0))
-;; (while (string-match ediff-metachars str limit)
-;; (setq str (concat (substring str 0 (match-beginning 0))
-;; "\\"
-;; (substring str (match-beginning 0))))
-;; (setq limit (1+ (match-end 0))))))
-;; str)
-
-;; Make sure the current buffer (for a file) has the same contents as the
-;; file on disk, and attempt to remedy the situation if not.
-;; Signal an error if we can't make them the same, or the user doesn't want
-;; to do what is necessary to make them the same.
-;; Also, Ediff always offers to revert obsolete buffers, whether they
-;; are modified or not.
-(defun ediff-verify-file-buffer (&optional file-magic)
- ;; First check if the file has been modified since the buffer visited it.
- (if (verify-visited-file-modtime (current-buffer))
- (if (buffer-modified-p)
- ;; If buffer is not obsolete and is modified, offer to save
- (if (yes-or-no-p
- (format "Buffer out of sync with visited file. Save file %s? "
- buffer-file-name))
- (condition-case nil
- (save-buffer)
- (error
- (beep)
- (message "Couldn't save %s" buffer-file-name)))
- (error "Buffer is out of sync for file %s" buffer-file-name))
- ;; If buffer is not obsolete and is not modified, do nothing
- nil)
- ;; If buffer is obsolete, offer to revert
- (if (yes-or-no-p
- (format "Buffer is out of sync with visited file. REVERT file %s? "
- buffer-file-name))
- (progn
- (if file-magic
- (erase-buffer))
- (revert-buffer t t))
- (error "Buffer out of sync for file %s" buffer-file-name))))
-
-
-(defun ediff-save-buffer (arg)
- "Safe way of saving buffers A, B, C, and the diff output.
-`wa' saves buffer A, `wb' saves buffer B, `wc' saves buffer C,
-and `wd' saves the diff output.
-
-With prefix argument, `wd' saves plain diff output.
-Without an argument, it saves customized diff argument, if available
-\(and plain output, if customized output was not generated\)."
- (interactive "P")
- (ediff-barf-if-not-control-buffer)
- (ediff-compute-custom-diffs-maybe)
- (ediff-eval-in-buffer
- (cond ((memq last-command-char '(?a ?b ?c))
- (ediff-get-buffer
- (ediff-char-to-buftype last-command-char)))
- ((eq last-command-char ?d)
- (message "Saving diff output ...")
- (sit-for 1) ; let the user see the message
- (cond ((and arg (ediff-buffer-live-p ediff-diff-buffer))
- ediff-diff-buffer)
- ((ediff-buffer-live-p ediff-custom-diff-buffer)
- ediff-custom-diff-buffer)
- ((ediff-buffer-live-p ediff-diff-buffer)
- ediff-diff-buffer)
- (t (error "Output from `diff' not found"))))
- )
- (save-buffer)))
-
-(defun ediff-compute-custom-diffs-maybe ()
- (let ((buf-A-file-name (buffer-file-name ediff-buffer-A))
- (buf-B-file-name (buffer-file-name ediff-buffer-B))
- file-A file-B)
- (if (stringp buf-A-file-name)
- (setq buf-A-file-name (file-name-nondirectory buf-A-file-name)))
- (if (stringp buf-B-file-name)
- (setq buf-B-file-name (file-name-nondirectory buf-B-file-name)))
- (setq file-A (ediff-make-temp-file ediff-buffer-A buf-A-file-name)
- file-B (ediff-make-temp-file ediff-buffer-B buf-B-file-name))
-
- (or (ediff-buffer-live-p ediff-custom-diff-buffer)
- (setq ediff-custom-diff-buffer
- (get-buffer-create
- (ediff-unique-buffer-name "*ediff-custom-diff" "*"))))
- (ediff-exec-process
- ediff-custom-diff-program ediff-custom-diff-buffer 'synchronize
- ediff-custom-diff-options file-A file-B)
- (delete-file file-A)
- (delete-file file-B)
- ))
-
-(defun ediff-show-diff-output (arg)
- (interactive "P")
- (ediff-barf-if-not-control-buffer)
- (ediff-compute-custom-diffs-maybe)
- (save-excursion
- (ediff-skip-unsuitable-frames ' ok-unsplittable))
- (let ((buf (cond ((and arg (ediff-buffer-live-p ediff-diff-buffer))
- ediff-diff-buffer)
- ((ediff-buffer-live-p ediff-custom-diff-buffer)
- ediff-custom-diff-buffer)
- ((ediff-buffer-live-p ediff-diff-buffer)
- ediff-diff-buffer)
- (t
- (beep)
- (message "Output from `diff' not found")
- nil))))
- (if buf
- (progn
- (ediff-eval-in-buffer buf
- (goto-char (point-min)))
- (switch-to-buffer buf)
- (raise-frame (selected-frame)))))
- (if (frame-live-p ediff-control-frame)
- (ediff-reset-mouse ediff-control-frame))
- (if (window-live-p ediff-control-window)
- (select-window ediff-control-window)))
-
-
-(defun ediff-inferior-compare-regions ()
- "Compare regions in an active Ediff session.
-Like ediff-regions-linewise but is called from under an active Ediff session on
-the files that belong to that session.
-
-After quitting the session invoked via this function, type C-l to the parent
-Ediff Control Panel to restore highlighting."
- (interactive)
- (let ((answer "")
- (possibilities (list ?A ?B ?C))
- (zmacs-regions t)
- quit-now
- begA begB endA endB bufA bufB)
-
- (cond ((ediff-merge-job)
- (setq bufB ediff-buffer-C)
- (while (cond ((memq answer '(?A ?a))
- (setq bufA ediff-buffer-A)
- nil)
- ((memq answer '(?B ?b))
- (setq bufA ediff-buffer-B)
- nil)
- ((equal answer ""))
- (t (beep 1)
- (message "Valid values are A or B")
- (sit-for 2)
- t))
- (let ((cursor-in-echo-area t))
- (message "Which buffer to compare to the merge buffer (A/B)? ")
- (setq answer (read-char-exclusive)))))
-
- ((ediff-3way-comparison-job)
- (while (cond ((memq answer possibilities)
- (setq possibilities (delq answer possibilities))
- (setq bufA
- (eval
- (intern (format "ediff-buffer-%c" answer))))
- nil)
- ((equal answer ""))
- (t (beep 1)
- (message
- "Valid values are %s"
- (mapconcat 'char-to-string possibilities " or "))
- (sit-for 2)
- t))
- (let ((cursor-in-echo-area t))
- (message "Enter the 1st buffer you want to compare (%s): "
- (mapconcat 'char-to-string possibilities "/"))
- (setq answer (capitalize (read-char-exclusive)))))
- (setq answer "") ; silence error msg
- (while (cond ((memq answer possibilities)
- (setq possibilities (delq answer possibilities))
- (setq bufB
- (eval
- (intern (format "ediff-buffer-%c" answer))))
- nil)
- ((equal answer ""))
- (t (beep 1)
- (message
- "Valid values are %s"
- (mapconcat 'char-to-string possibilities " or "))
- (sit-for 2)
- t))
- (let ((cursor-in-echo-area t))
- (message "Enter the 2nd buffer you want to compare (%s): "
- (mapconcat 'char-to-string possibilities "/"))
- (setq answer (capitalize (read-char-exclusive))))))
- (t ; 2way comparison
- (setq bufA ediff-buffer-A
- bufB ediff-buffer-B)))
-
- (ediff-eval-in-buffer bufA
- (or (mark t)
- (error "You forgot to specify a region in buffer %s" (buffer-name)))
- (setq begA (region-beginning)
- endA (region-end))
- (goto-char begA)
- (beginning-of-line)
- (setq begA (point))
- (goto-char endA)
- (end-of-line)
- (or (eobp) (forward-char)) ; include the newline char
- (setq endA (point)))
- (ediff-eval-in-buffer bufB
- (or (mark t)
- (error "You forgot to specify a region in buffer %s" (buffer-name)))
- (setq begB (region-beginning)
- endB (region-end))
- (goto-char begB)
- (beginning-of-line)
- (setq begB (point))
- (goto-char endB)
- (end-of-line)
- (or (eobp) (forward-char)) ; include the newline char
- (setq endB (point)))
-
- (ediff-unselect-and-select-difference
- ediff-current-difference 'unselect-only)
- (ediff-paint-background-regions 'unhighlight)
-
- (ediff-eval-in-buffer bufA
- (goto-char begA)
- (set-mark endA)
- (narrow-to-region begA endA)
- ;; (ediff-activate-mark)
- )
- ;; (sit-for 0)
- (ediff-eval-in-buffer bufB
- (goto-char begB)
- (set-mark endB)
- (narrow-to-region begB endB)
- ;; (ediff-activate-mark)
- )
- ;; (sit-for 0)
-
- (or (y-or-n-p
- "Please check the selected regions. Continue? ")
- (setq quit-now t))
-
- (ediff-eval-in-buffer bufA
- (widen))
- (ediff-eval-in-buffer bufB
- (widen))
- (if quit-now
- (error "Thank you. Come back another day..."))
-
- (ediff-regions-internal
- bufA begA endA bufB begB endB
- nil ; startup hook
- 'ediff-regions-linewise ; job name
- nil) ; no word mode
- ))
-
-
-
-(defun ediff-remove-flags-from-buffer (buffer overlay)
- (ediff-eval-in-buffer buffer
- (let ((inhibit-read-only t))
- (if ediff-xemacs-p
- (ediff-overlay-put overlay 'begin-glyph nil)
- (ediff-overlay-put overlay 'before-string nil))
-
- (if ediff-xemacs-p
- (ediff-overlay-put overlay 'end-glyph nil)
- (ediff-overlay-put overlay 'after-string nil))
- )))
-
-
-
-(defun ediff-place-flags-in-buffer (buf-type buffer ctl-buffer diff)
- (ediff-eval-in-buffer buffer
- (ediff-place-flags-in-buffer1 buf-type ctl-buffer diff)))
-
-
-(defun ediff-place-flags-in-buffer1 (buf-type ctl-buffer diff-no)
- (let* ((curr-overl (ediff-eval-in-buffer ctl-buffer
- (ediff-get-diff-overlay diff-no buf-type)))
- (before (ediff-get-diff-posn buf-type 'beg diff-no ctl-buffer))
- after beg-of-line flag)
-
- ;; insert flag before the difference
- (goto-char before)
- (setq beg-of-line (bolp))
-
- (setq flag (ediff-eval-in-buffer ctl-buffer
- (if (eq ediff-highlighting-style 'ascii)
- (if beg-of-line
- ediff-before-flag-bol ediff-before-flag-mol))))
-
- ;; insert the flag itself
- (if ediff-xemacs-p
- (ediff-overlay-put curr-overl 'begin-glyph flag)
- (ediff-overlay-put curr-overl 'before-string flag))
-
- ;; insert the flag after the difference
- ;; `after' must be set here, after the before-flag was inserted
- (setq after (ediff-get-diff-posn buf-type 'end diff-no ctl-buffer))
- (goto-char after)
- (setq beg-of-line (bolp))
-
- (setq flag (ediff-eval-in-buffer ctl-buffer
- (if (eq ediff-highlighting-style 'ascii)
- (if beg-of-line
- ediff-after-flag-eol ediff-after-flag-mol))))
-
- ;; insert the flag itself
- (if ediff-xemacs-p
- (ediff-overlay-put curr-overl 'end-glyph flag)
- (ediff-overlay-put curr-overl 'after-string flag))
- ))
-
-
-;; Returns positions of difference sectors in the BUF-TYPE buffer.
-;; BUF-TYPE should be a symbol -- `A', `B', or `C'.
-;; POS is either `beg' or `end'--it specifies whether you want the position at
-;; the beginning of a difference or at the end.
-;;
-;; The optional argument N says which difference (default:
-;; `ediff-current-difference'). N is the internal difference number (1- what
-;; the user sees). The optional argument CONTROL-BUF says
-;; which control buffer is in effect in case it is not the current
-;; buffer.
-(defun ediff-get-diff-posn (buf-type pos &optional n control-buf)
- (let (diff-overlay)
- (or control-buf
- (setq control-buf (current-buffer)))
-
- (ediff-eval-in-buffer control-buf
- (or n (setq n ediff-current-difference))
- (if (or (< n 0) (>= n ediff-number-of-differences))
- (if (> ediff-number-of-differences 0)
- (error ediff-BAD-DIFF-NUMBER
- this-command (1+ n) ediff-number-of-differences)
- (error ediff-NO-DIFFERENCES)))
- (setq diff-overlay (ediff-get-diff-overlay n buf-type)))
- (if (not (ediff-buffer-live-p (ediff-overlay-buffer diff-overlay)))
- (error ediff-KILLED-VITAL-BUFFER))
- (if (eq pos 'beg)
- (ediff-overlay-start diff-overlay)
- (ediff-overlay-end diff-overlay))
- ))
-
-
-;; Restore highlighting to what it should be according to ediff-use-faces,
-;; ediff-highlighting-style, and ediff-highlight-all-diffs variables.
-(defun ediff-restore-highlighting (&optional ctl-buf)
- (ediff-eval-in-buffer (or ctl-buf (current-buffer))
- (if (and (ediff-has-face-support-p)
- ediff-use-faces
- ediff-highlight-all-diffs)
- (ediff-paint-background-regions))
- (ediff-select-difference ediff-current-difference)))
-
-
-
-;; null out difference overlays so they won't slow down future
-;; editing operations
-;; VEC is either a difference vector or a fine-diff vector
-(defun ediff-clear-diff-vector (vec-var &optional fine-diffs-also)
- (if (vectorp (symbol-value vec-var))
- (mapcar (function
- (lambda (elt)
- (ediff-delete-overlay
- (ediff-get-diff-overlay-from-diff-record elt))
- (if fine-diffs-also
- (ediff-clear-fine-diff-vector elt))
- ))
- (symbol-value vec-var)))
- ;; allow them to be garbage collected
- (set vec-var nil))
-
-
-
-;;; Misc
-
-;; In Emacs, this just makes overlay. In the future, when Emacs will start
-;; supporting sticky overlays, this function will make a sticky overlay.
-;; BEG and END are expressions telling where overlay starts.
-;; If they are numbers or buffers, then all is well. Otherwise, they must
-;; be expressions to be evaluated in buffer BUF in order to get the overlay
-;; bounds.
-;; If BUFF is not a live buffer, then return nil; otherwise, return the
-;; newly created overlay.
-(defun ediff-make-bullet-proof-overlay (beg end buff)
- (if (ediff-buffer-live-p buff)
- (let (overl)
- (ediff-eval-in-buffer buff
- (or (number-or-marker-p beg)
- (setq beg (eval beg)))
- (or (number-or-marker-p end)
- (setq end (eval end)))
- (setq overl
- (if ediff-xemacs-p
- (make-extent beg end buff)
- ;; advance front and rear of the overlay
- (make-overlay beg end buff nil 'rear-advance)))
-
- ;; never detach
- (ediff-overlay-put
- overl (if ediff-emacs-p 'evaporate 'detachable) nil)
- ;; make vip-minibuffer-overlay open-ended
- ;; In emacs, it is made open ended at creation time
- (if ediff-xemacs-p
- (progn
- (ediff-overlay-put overl 'start-open nil)
- (ediff-overlay-put overl 'end-open nil)))
- (ediff-overlay-put overl 'ediff-diff-num 0)
- overl))))
-
-(defsubst ediff-overlay-start (overl)
- (if (ediff-overlayp overl)
- (if ediff-emacs-p
- (overlay-start overl)
- (extent-start-position overl))))
-
-(defsubst ediff-overlay-end (overl)
- (if (ediff-overlayp overl)
- (if ediff-emacs-p
- (overlay-end overl)
- (extent-end-position overl))))
-
-
-;; Like other-buffer, but prefers visible buffers and ignores temporary or
-;; other insignificant buffers (those beginning with "^[ *]").
-;; Gets one arg--buffer name or a list of buffer names (it won't return
-;; these buffers).
-(defun ediff-other-buffer (buff)
- (if (not (listp buff)) (setq buff (list buff)))
- (let* ((frame-buffers (buffer-list))
- (significant-buffers
- (mapcar
- (function (lambda (x)
- (cond ((member (buffer-name x) buff)
- nil)
- ((not (ediff-get-visible-buffer-window x))
- nil)
- ((string-match "^ " (buffer-name x))
- nil)
- (t x))))
- frame-buffers))
- (buffers (delq nil significant-buffers))
- less-significant-buffers)
-
- (cond (buffers (car buffers))
- ;; try also buffers that are not displayed in windows
- ((setq less-significant-buffers
- (delq nil
- (mapcar
- (function
- (lambda (x)
- (cond ((member (buffer-name x) buff) nil)
- ((string-match "^[ *]" (buffer-name x)) nil)
- (t x))))
- frame-buffers)))
- (car less-significant-buffers))
- (t (other-buffer (current-buffer))))
- ))
-
-
-;; Construct a unique buffer name.
-;; The first one tried is prefixsuffix, then prefix<2>suffix,
-;; prefix<3>suffix, etc.
-(defun ediff-unique-buffer-name (prefix suffix)
- (if (null (get-buffer (concat prefix suffix)))
- (concat prefix suffix)
- (let ((n 2))
- (while (get-buffer (format "%s<%d>%s" prefix n suffix))
- (setq n (1+ n)))
- (format "%s<%d>%s" prefix n suffix))))
-
-
-;; splits at a white space, returns a list
-(defun ediff-split-string (string)
- (let ((start 0)
- (result '())
- substr)
- (while (string-match "[ \t]+" string start)
- (let ((match (string-match "[ \t]+" string start)))
- (setq substr (substring string start match))
- (if (> (length substr) 0)
- (setq result (cons substr result)))
- (setq start (match-end 0))))
- (setq substr (substring string start nil))
- (if (> (length substr) 0)
- (setq result (cons substr result)))
- (nreverse result)))
-
-(defun ediff-submit-report ()
- "Submit bug report on Ediff."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (let ((reporter-prompt-for-summary-p t)
- (ctl-buf ediff-control-buffer)
- (ediff-device-type (ediff-device-type))
- varlist salutation buffer-name)
- (setq varlist '(ediff-diff-program ediff-diff-options
- ediff-patch-program ediff-patch-options
- ediff-shell
- ediff-use-faces
- ediff-auto-refine ediff-highlighting-style
- ediff-buffer-A ediff-buffer-B ediff-control-buffer
- ediff-forward-word-function
- ediff-control-frame
- ediff-control-frame-parameters
- ediff-control-frame-position-function
- ediff-prefer-iconified-control-frame
- ediff-window-setup-function
- ediff-split-window-function
- ediff-job-name
- ediff-word-mode
- buffer-name
- ediff-device-type
- ))
- (setq salutation "
-Congratulations! You may have unearthed a bug in Ediff!
-
-Please make a concise and accurate summary of what happened
-and mail it to the address above.
------------------------------------------------------------
-")
-
- (ediff-skip-unsuitable-frames)
- (ediff-reset-mouse)
-
- (switch-to-buffer ediff-msg-buffer)
- (erase-buffer)
- (delete-other-windows)
- (insert "
-Please read this first:
-----------------------
-
-Some ``bugs'' may actually be no bugs at all. For instance, if you are
-reporting that certain difference regions are not matched as you think they
-should, this is most likely due to the way Unix diff program decides what
-constitutes a difference region. Ediff is an Emacs interface to diff, and
-it has nothing to do with those decisions---it only takes the output from
-diff and presents it in a way that is better suited for human browsing and
-manipulation.
-
-If Emacs happens to dump core, this is NOT an Ediff problem---it is
-an Emacs bug. Report this to Emacs maintainers.
-
-Another popular topic for reports is compilation messages. Because Ediff
-interfaces to several other packages and runs under Emacs and XEmacs,
-byte-compilation may produce output like this:
-
- While compiling toplevel forms in file ediff.el:
- ** reference to free variable pm-color-alist
- ........................
- While compiling the end of the data:
- ** The following functions are not known to be defined:
- ediff-valid-color-p, ediff-set-face,
- ........................
-
-These are NOT errors, but inevitable warnings, which ought to be ignored.
-
-Please do not report those and similar things. However, comments and
-suggestions are always welcome.
-
-Mail anyway? (y or n) ")
-
- (if (y-or-n-p "Mail anyway? ")
- (progn
- (if (ediff-buffer-live-p ctl-buf)
- (set-buffer ctl-buf))
- (setq buffer-name (buffer-name))
- (require 'reporter)
- (reporter-submit-bug-report "kifer@cs.sunysb.edu"
- (ediff-version)
- varlist
- nil
- 'delete-other-windows
- salutation))
- (bury-buffer)
- (beep 1)(message "Bug report aborted")
- (if (ediff-buffer-live-p ctl-buf)
- (ediff-eval-in-buffer ctl-buf
- (ediff-recenter 'no-rehighlight))))
- ))
-
-
-(defun ediff-deactivate-mark ()
- (if ediff-xemacs-p
- (zmacs-deactivate-region)
- (deactivate-mark)))
-(defun ediff-activate-mark ()
- (if ediff-emacs-p
- (setq mark-active t)
- (zmacs-activate-region)))
-
-(cond ((fboundp 'nuke-selective-display)
- ;; XEmacs 19.12 has nuke-selective-display
- (fset 'ediff-nuke-selective-display 'nuke-selective-display))
- (t
- (defun ediff-nuke-selective-display ()
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (let ((mod-p (buffer-modified-p))
- buffer-read-only end)
- (and (eq t selective-display)
- (while (search-forward "\^M" nil t)
- (end-of-line)
- (setq end (point))
- (beginning-of-line)
- (while (search-forward "\^M" end t)
- (delete-char -1)
- (insert "\^J"))))
- (set-buffer-modified-p mod-p)
- (setq selective-display nil)))))
- ))
-
-
-;; The next two are modified versions from emerge.el.
-;; VARS must be a list of symbols
-;; ediff-save-variables returns an association list: ((var . val) ...)
-(defsubst ediff-save-variables (vars)
- (mapcar (function (lambda (v) (cons v (symbol-value v))))
- vars))
-;; VARS is a list of variable symbols.
-(defun ediff-restore-variables (vars assoc-list)
- (while vars
- (set (car vars) (cdr (assoc (car vars) assoc-list)))
- (setq vars (cdr vars))))
-
-(defun ediff-change-saved-variable (var value buf-type)
- (let* ((assoc-list
- (symbol-value (intern
- (concat "ediff-buffer-values-orig-"
- (symbol-name buf-type)))))
- (assoc-elt (assoc var assoc-list)))
- (if assoc-elt
- (setcdr assoc-elt value))))
-
-
-;; must execute in control buf
-(defun ediff-save-protected-variables ()
- (setq ediff-buffer-values-orig-A
- (ediff-eval-in-buffer ediff-buffer-A
- (ediff-save-variables ediff-protected-variables)))
- (setq ediff-buffer-values-orig-B
- (ediff-eval-in-buffer ediff-buffer-B
- (ediff-save-variables ediff-protected-variables)))
- (if ediff-3way-comparison-job
- (setq ediff-buffer-values-orig-C
- (ediff-eval-in-buffer ediff-buffer-C
- (ediff-save-variables ediff-protected-variables))))
- (if (ediff-buffer-live-p ediff-ancestor-buffer)
- (setq ediff-buffer-values-orig-Ancestor
- (ediff-eval-in-buffer ediff-ancestor-buffer
- (ediff-save-variables ediff-protected-variables)))))
-
-;; must execute in control buf
-(defun ediff-restore-protected-variables ()
- (let ((values-A ediff-buffer-values-orig-A)
- (values-B ediff-buffer-values-orig-B)
- (values-C ediff-buffer-values-orig-C)
- (values-Ancestor ediff-buffer-values-orig-Ancestor))
- (ediff-eval-in-buffer ediff-buffer-A
- (ediff-restore-variables ediff-protected-variables values-A))
- (ediff-eval-in-buffer ediff-buffer-B
- (ediff-restore-variables ediff-protected-variables values-B))
- (if ediff-3way-comparison-job
- (ediff-eval-in-buffer ediff-buffer-C
- (ediff-restore-variables ediff-protected-variables values-C)))
- (if (ediff-buffer-live-p ediff-ancestor-buffer)
- (ediff-eval-in-buffer ediff-ancestor-buffer
- (ediff-restore-variables ediff-protected-variables values-Ancestor)))
- ))
-
-;; save BUFFER in FILE. used in hooks.
-(defun ediff-save-buffer-in-file (buffer file)
- (ediff-eval-in-buffer buffer
- (write-file file)))
-
-
-;;; Debug
-
-(ediff-defvar-local ediff-command-begin-time '(0 0 0) "")
-
-;; calculate time used by command
-(defun ediff-calc-command-time ()
- (let ((end (current-time))
- micro sec)
- (setq micro
- (if (>= (nth 2 end) (nth 2 ediff-command-begin-time))
- (- (nth 2 end) (nth 2 ediff-command-begin-time))
- (+ (nth 2 end) (- 1000000 (nth 2 ediff-command-begin-time)))))
- (setq sec (- (nth 1 end) (nth 1 ediff-command-begin-time)))
- (or (equal ediff-command-begin-time '(0 0 0))
- (message "Elapsed time: %d second(s) + %d microsecond(s)" sec micro))))
-
-(defsubst ediff-save-time ()
- (setq ediff-command-begin-time (current-time)))
-
-(defun ediff-profile ()
- "Toggle profiling Ediff commands."
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (make-local-hook 'post-command-hook)
- (let ((pre-hook 'pre-command-hook)
- (post-hook 'post-command-hook))
- (if (not (equal ediff-command-begin-time '(0 0 0)))
- (progn (remove-hook pre-hook 'ediff-save-time)
- (remove-hook post-hook 'ediff-calc-command-time)
- (setq ediff-command-begin-time '(0 0 0))
- (message "Ediff profiling disabled"))
- (add-hook pre-hook 'ediff-save-time t t)
- (add-hook post-hook 'ediff-calc-command-time nil t)
- (message "Ediff profiling enabled"))))
-
-(defun ediff-print-diff-vector (diff-vector-var)
- (princ (format "\n*** %S ***\n" diff-vector-var))
- (mapcar (function
- (lambda (overl-vec)
- (princ
- (format
- "Diff %d: \tOverlay: %S
-\t\tFine diffs: %s
-\t\tNo-fine-diff-flag: %S
-\t\tState-of-diff:\t %S
-\t\tState-of-merge:\t %S
-"
- (1+ (ediff-overlay-get (aref overl-vec 0) 'ediff-diff-num))
- (aref overl-vec 0)
- ;; fine-diff-vector
- (if (= (length (aref overl-vec 1)) 0)
- "none\n"
- (mapconcat 'prin1-to-string
- (aref overl-vec 1) "\n\t\t\t "))
- (aref overl-vec 2) ; no fine diff flag
- (aref overl-vec 3) ; state-of-diff
- (aref overl-vec 4) ; state-of-merge
- ))))
- (eval diff-vector-var)))
-
-
-
-(defun ediff-debug-info ()
- (interactive)
- (ediff-barf-if-not-control-buffer)
- (with-output-to-temp-buffer ediff-debug-buffer
- (princ (format "\nCtl buffer: %S\n" ediff-control-buffer))
- (ediff-print-diff-vector (intern "ediff-difference-vector-A"))
- (ediff-print-diff-vector (intern "ediff-difference-vector-B"))
- (ediff-print-diff-vector (intern "ediff-difference-vector-C"))
- (ediff-print-diff-vector (intern "ediff-difference-vector-Ancestor"))
- ))
-
-
-;;; General utilities
-
-;; this uses comparison-func to decide who is a member
-(defun ediff-member (elt lis comparison-func)
- (while (and lis (not (funcall comparison-func (car lis) elt)))
- (setq lis (cdr lis)))
- lis)
-
-;; this uses comparison-func to decide who is a member, and this determines how
-;; intersection looks like
-(defun ediff-intersection (lis1 lis2 comparison-func)
- (let ((result (list 'a)))
- (while lis1
- (if (ediff-member (car lis1) lis2 comparison-func)
- (nconc result (list (car lis1))))
- (setq lis1 (cdr lis1)))
- (cdr result)))
-
-
-;; eliminates duplicates using comparison-func
-(defun ediff-union (lis1 lis2 comparison-func)
- (let ((result (list 'a)))
- (while lis1
- (or (ediff-member (car lis1) (cdr result) comparison-func)
- (nconc result (list (car lis1))))
- (setq lis1 (cdr lis1)))
- (while lis2
- (or (ediff-member (car lis2) (cdr result) comparison-func)
- (nconc result (list (car lis2))))
- (setq lis2 (cdr lis2)))
- (cdr result)))
-
-;; eliminates duplicates using comparison-func
-(defun ediff-set-difference (lis1 lis2 comparison-func)
- (let ((result (list 'a)))
- (while lis1
- (or (ediff-member (car lis1) (cdr result) comparison-func)
- (ediff-member (car lis1) lis2 comparison-func)
- (nconc result (list (car lis1))))
- (setq lis1 (cdr lis1)))
- (cdr result)))
-
-(defun ediff-copy-list (list)
- (if (consp list)
- ;;;(let ((res nil))
- ;;; (while (consp list) (push (pop list) res))
- ;;; (prog1 (nreverse res) (setcdr res list)))
- (let (res elt)
- (while (consp list)
- (setq elt (car list)
- res (cons elt res)
- list (cdr list)))
- (nreverse res))
- (car list)))
-
-
-;; don't report error if version control package wasn't found
-;;(ediff-load-version-control 'silent)
-
-(run-hooks 'ediff-load-hook)
-
-
-;;; Local Variables:
-;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
-;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
-;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
-;;; End:
-
-(provide 'ediff-util)
-
-;;; ediff-util.el ends here
diff --git a/lisp/ediff-vers.el b/lisp/ediff-vers.el
deleted file mode 100644
index cec2d6f2ccf..00000000000
--- a/lisp/ediff-vers.el
+++ /dev/null
@@ -1,367 +0,0 @@
-;;; ediff-vers.el --- version control interface to Ediff
-
-;;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Michael Kifer <kifer@cs.sunysb.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-
-;;; Code:
-
-;; Compiler pacifier
-(defvar rcs-default-co-switches)
-(defvar sc-mode)
-(defvar cvs-shell)
-(defvar cvs-program)
-(defvar cvs-cookie-handle)
-
-(and noninteractive
- (eval-when-compile
- (load "pcl-cvs" 'noerror)
- (load "rcs" 'noerror)
- (load "generic-sc" 'noerror)
- (load "vc" 'noerror)))
-;; end pacifier
-
-;; VC.el support
-(defun ediff-vc-internal (rev1 rev2 &optional startup-hooks)
-;; Run Ediff on versions of the current buffer.
-;; If REV2 is "" then compare current buffer with REV1.
-;; If the current buffer is named `F', the version is named `F.~REV~'.
-;; If `F.~REV~' already exists, it is used instead of being re-created.
- (let (file1 file2 rev1buf rev2buf)
- (save-excursion
- (vc-version-other-window rev1)
- (setq rev1buf (current-buffer)
- file1 (buffer-file-name)))
- (save-excursion
- (or (string= rev2 "") ; use current buffer
- (vc-version-other-window rev2))
- (setq rev2buf (current-buffer)
- file2 (buffer-file-name)))
- (setq startup-hooks
- (cons (` (lambda ()
- (delete-file (, file1))
- (or (, (string= rev2 "")) (delete-file (, file2)))
- ))
- startup-hooks))
- (ediff-buffers
- rev1buf rev2buf
- startup-hooks
- 'ediff-revision)))
-
-;; RCS.el support
-(defun rcs-ediff-view-revision (&optional rev)
-;; View previous RCS revision of current file.
-;; With prefix argument, prompts for a revision name.
- (interactive (list (if current-prefix-arg
- (read-string "Revision: "))))
- (let* ((filename (buffer-file-name (current-buffer)))
- (switches (append '("-p")
- (if rev (list (concat "-r" rev)) nil)))
- (buff (concat (file-name-nondirectory filename) ".~" rev "~")))
- (message "Working ...")
- (setq filename (expand-file-name filename))
- (with-output-to-temp-buffer buff
- (let ((output-buffer (ediff-rcs-get-output-buffer filename buff)))
- (delete-windows-on output-buffer)
- (save-excursion
- (set-buffer output-buffer)
- (apply 'call-process "co" nil t nil
- ;; -q: quiet (no diagnostics)
- (append switches rcs-default-co-switches
- (list "-q" filename)))))
- (message "")
- buff)))
-
-(defun ediff-rcs-get-output-buffer (file name)
- ;; Get a buffer for RCS output for FILE, make it writable and clean it up.
- ;; Optional NAME is name to use instead of `*RCS-output*'.
- ;; This is a modified version from rcs.el v1.1. I use it here to make
- ;; Ediff immune to changes in rcs.el
- (let* ((default-major-mode 'fundamental-mode) ; no frills!
- (buf (get-buffer-create name)))
- (save-excursion
- (set-buffer buf)
- (setq buffer-read-only nil
- default-directory (file-name-directory (expand-file-name file)))
- (erase-buffer))
- buf))
-
-(defun ediff-rcs-internal (rev1 rev2 &optional startup-hooks)
-;; Run Ediff on versions of the current buffer.
-;; If REV2 is "" then use current buffer.
- (let ((rev2buf (if (string= rev2 "")
- (current-buffer)
- (rcs-ediff-view-revision rev2)))
- (rev1buf (rcs-ediff-view-revision rev1)))
-
- ;; rcs.el doesn't create temp version files, so we don't have to delete
- ;; anything in startup hooks to ediff-buffers
- (ediff-buffers rev1buf rev2buf startup-hooks 'ediff-revision)
- ))
-
-
-;; GENERIC-SC.el support
-
-(defun generic-sc-get-latest-rev ()
- (cond ((eq sc-mode 'CCASE)
- (eval "main/LATEST"))
- (t (eval ""))))
-
-(defun ediff-generic-sc-internal (rev1 rev2 &optional startup-hooks)
-;; Run Ediff on versions of the current buffer.
-;; If REV2 is "" then compare current buffer with REV1.
-;; If the current buffer is named `F', the version is named `F.~REV~'.
-;; If `F.~REV~' already exists, it is used instead of being re-created.
- (let (rev1buf rev2buf)
- (save-excursion
- (if (or (not rev1) (string= rev1 ""))
- (setq rev1 (generic-sc-get-latest-rev)))
- (sc-visit-previous-revision rev1)
- (setq rev1buf (current-buffer)))
- (save-excursion
- (or (string= rev2 "") ; use current buffer
- (sc-visit-previous-revision rev2))
- (setq rev2buf (current-buffer)))
- (ediff-buffers rev1buf rev2buf startup-hooks 'ediff-revision)))
-
-
-;;; Merge with Version Control
-
-(defun ediff-vc-merge-internal (rev1 rev2 ancestor-rev &optional startup-hooks)
-;; If ANCESTOR-REV non-nil, merge with ancestor
- (let (buf1 buf2 ancestor-buf)
- (save-excursion
- (vc-version-other-window rev1)
- (setq buf1 (current-buffer)))
- (save-excursion
- (or (string= rev2 "")
- (vc-version-other-window rev2))
- (setq buf2 (current-buffer)))
- (if ancestor-rev
- (save-excursion
- (or (string= ancestor-rev "")
- (vc-version-other-window ancestor-rev))
- (setq ancestor-buf (current-buffer))))
- (setq startup-hooks
- (cons
- (` (lambda ()
- (delete-file (, (buffer-file-name buf1)))
- (or (, (string= rev2 ""))
- (delete-file (, (buffer-file-name buf2))))
- (or (, (string= ancestor-rev ""))
- (, (not ancestor-rev))
- (delete-file (, (buffer-file-name ancestor-buf))))
- ))
- startup-hooks))
- (if ancestor-rev
- (ediff-merge-buffers-with-ancestor
- buf1 buf2 ancestor-buf
- startup-hooks 'ediff-merge-revisions-with-ancestor)
- (ediff-merge-buffers buf1 buf2 startup-hooks 'ediff-merge-revisions))
- ))
-
-(defun ediff-rcs-merge-internal (rev1 rev2 ancestor-rev
- &optional startup-hooks)
- ;; If ANCESTOR-REV non-nil, merge with ancestor
- (let (buf1 buf2 ancestor-buf)
- (setq buf1 (rcs-ediff-view-revision rev1)
- buf2 (if (string= rev2 "")
- (current-buffer)
- (rcs-ediff-view-revision rev2))
- ancestor-buf (if ancestor-rev
- (if (string= ancestor-rev "")
- (current-buffer)
- (rcs-ediff-view-revision ancestor-rev))))
- ;; rcs.el doesn't create temp version files, so we don't have to delete
- ;; anything in startup hooks to ediff-buffers
- (if ancestor-rev
- (ediff-merge-buffers-with-ancestor
- buf1 buf2 ancestor-buf
- startup-hooks 'ediff-merge-revisions-with-ancestor)
- (ediff-merge-buffers buf1 buf2 startup-hooks 'ediff-merge-revisions))))
-
-(defun ediff-generic-sc-merge-internal (rev1 rev2 ancestor-rev
- &optional startup-hooks)
- ;; If ANCESTOR-REV non-nil, merge with ancestor
- (let (buf1 buf2 ancestor-buf)
- (save-excursion
- (if (string= rev1 "")
- (setq rev1 (generic-sc-get-latest-rev)))
- (sc-visit-previous-revision rev1)
- (setq buf1 (current-buffer)))
- (save-excursion
- (or (string= rev2 "")
- (sc-visit-previous-revision rev2))
- (setq buf2 (current-buffer)))
- (if ancestor-rev
- (save-excursion
- (or (string= ancestor-rev "")
- (sc-visit-previous-revision ancestor-rev))
- (setq ancestor-buf (current-buffer))))
- (if ancestor-rev
- (ediff-merge-buffers-with-ancestor
- buf1 buf2 ancestor-buf
- startup-hooks 'ediff-merge-revisions-with-ancestor)
- (ediff-merge-buffers buf1 buf2 startup-hooks 'ediff-merge-revisions))))
-
-
-;; PCL-CVS.el support
-
-(defun ediff-pcl-cvs-internal (rev1 rev2 &optional startup-hooks)
-;; Run Ediff on a pair of revisions of the current buffer.
-;; If REV1 is "", use the latest revision.
-;; If REV2 is "", use the current buffer as the second file to compare.
- (let ((orig-buf (current-buffer))
- orig-file-name buf1 buf2 file1 file2)
-
- (or (setq orig-file-name (buffer-file-name (current-buffer)))
- (error "Current buffer is not visiting any file"))
- (if (string= rev1 "") (setq rev1 nil)) ; latest revision
- (setq buf1 (ediff-pcl-cvs-view-revision orig-file-name rev1)
- buf2 (if (string= rev2 "")
- orig-buf
- (ediff-pcl-cvs-view-revision orig-file-name rev2))
- file1 (buffer-file-name buf1)
- file2 (buffer-file-name buf2))
- (setq startup-hooks
- (cons (` (lambda ()
- (delete-file (, file1))
- (or (, (string= rev2 "")) (delete-file (, file2)))
- ))
- startup-hooks))
- (ediff-buffers buf1 buf2 startup-hooks 'ediff-revision)))
-
-;; This function is the standard Ediff's interface to pcl-cvs.
-;; Works like with other interfaces: runs ediff on versions of the file in the
-;; current buffer.
-(defun ediff-pcl-cvs-merge-internal (rev1 rev2 ancestor-rev
- &optional startup-hooks)
-;; Ediff-merge appropriate revisions of the selected file.
-;; If REV1 is "" then use the latest revision.
-;; If REV2 is "" then merge current buffer's file with REV1.
-;; If ANCESTOR-REV is "" then use current buffer's file as ancestor.
-;; If ANCESTOR-REV is nil, then merge without the ancestor.
- (let ((orig-buf (current-buffer))
- orig-file-name buf1 buf2 ancestor-buf)
-
- (or (setq orig-file-name (buffer-file-name (current-buffer)))
- (error "Current buffer is not visiting any file"))
- (if (string= rev1 "") (setq rev1 nil)) ; latest revision
-
- (setq buf1 (ediff-pcl-cvs-view-revision orig-file-name rev1))
- (setq buf2 (if (string= rev2 "")
- orig-buf
- (ediff-pcl-cvs-view-revision orig-file-name rev2)))
- (if (stringp ancestor-rev)
- (setq ancestor-buf
- (if (string= ancestor-rev "")
- orig-buf
- (ediff-pcl-cvs-view-revision orig-file-name ancestor-rev))))
-
- (setq startup-hooks
- (cons
- (` (lambda ()
- (delete-file (, (buffer-file-name buf1)))
- (or (, (string= rev2 ""))
- (delete-file (, (buffer-file-name buf2))))
- (or (, (string= ancestor-rev ""))
- (, (not ancestor-rev))
- (delete-file (, (buffer-file-name ancestor-buf))))
- ))
- startup-hooks))
-
- (if ancestor-buf
- (ediff-merge-buffers-with-ancestor
- buf1 buf2 ancestor-buf startup-hooks
- 'ediff-merge-revisions-with-ancestor)
- (ediff-merge-buffers
- buf1 buf2 startup-hooks 'ediff-merge-revisions))
- ))
-
-(defun ediff-pcl-cvs-view-revision (file rev)
-;; if rev = "", get the latest revision
- (let ((temp-name (make-temp-name
- (concat ediff-temp-file-prefix
- "ediff_" rev))))
- (cvs-kill-buffer-visiting temp-name)
- (if rev
- (message "Retrieving revision %s..." rev)
- (message "Retrieving latest revision..."))
- (let ((res (call-process cvs-shell nil nil nil "-c"
- (concat cvs-program " update -p "
- (if rev
- (concat "-r " rev " ")
- "")
- file
- " > " temp-name))))
- (if (and res (not (and (integerp res) (zerop res))))
- (error "Failed to retrieve revision: %s" res))
-
- (if rev
- (message "Retrieving revision %s... Done." rev)
- (message "Retrieving latest revision... Done."))
- (find-file-noselect temp-name))))
-
-
-(defun cvs-run-ediff-on-file-descriptor (tin)
-;; This is a replacement for cvs-emerge-mode
-;; Run after cvs-update.
-;; Ediff-merge appropriate revisions of the selected file.
- (let* ((fileinfo (tin-cookie cvs-cookie-handle tin))
- (type (cvs-fileinfo->type fileinfo))
- (tmp-file
- (cvs-retrieve-revision-to-tmpfile fileinfo))
- ancestor-file)
-
- (or (memq type '(MERGED CONFLICT MODIFIED))
- (error
- "Can only merge `Modified', `Merged' or `Conflict' files"))
-
- (cond ((memq type '(MERGED CONFLICT))
- (setq ancestor-file
- (cvs-retrieve-revision-to-tmpfile
- fileinfo
- ;; revision
- (cvs-fileinfo->base-revision fileinfo)))
- (ediff-merge-buffers-with-ancestor
- (find-file-noselect tmp-file)
- (find-file-noselect (cvs-fileinfo->backup-file fileinfo))
- (find-file-noselect ancestor-file)
- nil ; startup-hooks
- 'ediff-merge-revisions-with-ancestor))
- ((eq type 'MODIFIED)
- (ediff-merge-buffers
- (find-file-noselect tmp-file)
- (find-file-noselect (cvs-fileinfo->full-path fileinfo))
- nil ; startup-hooks
- 'ediff-merge-revisions)))
- (if (stringp tmp-file) (delete-file tmp-file))
- (if (stringp ancestor-file) (delete-file ancestor-file))))
-
-;;; Local Variables:
-;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
-;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
-;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
-;;; End:
-
-(provide 'ediff-vers)
-
-;;; ediff-vers.el ends here
diff --git a/lisp/ediff-wind.el b/lisp/ediff-wind.el
deleted file mode 100644
index 8edde2995df..00000000000
--- a/lisp/ediff-wind.el
+++ /dev/null
@@ -1,1210 +0,0 @@
-;;; ediff-wind.el --- window manipulation utilities
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Michael Kifer <kifer@cs.sunysb.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(require 'ediff-init)
-(if ediff-xemacs-p
- (require 'ediff-tbar)
- (defun ediff-compute-toolbar-width () 0))
-
-;; Compiler pacifier
-(defvar icon-title-format)
-(defvar top-toolbar-height)
-(defvar bottom-toolbar-height)
-(defvar left-toolbar-height)
-(defvar right-toolbar-height)
-(defvar left-toolbar-width)
-(defvar right-toolbar-width)
-(defvar default-menubar)
-(defvar frame-icon-title-format)
-;; end pacifier
-
-
-(defvar ediff-window-setup-function (if (ediff-window-display-p)
- 'ediff-setup-windows-multiframe
- 'ediff-setup-windows-plain)
- "*Function called to set up windows.
-Ediff provides a choice of two functions: ediff-setup-windows-plain, for
-doing everything in one frame, and ediff-setup-windows-multiframe,
-which sets the control panel in a separate frame. Also, if the latter
-function detects that one of the buffers A/B is seen in some other frame,
-it will try to keep that buffer in that frame.
-
-If you don't like the two functions provided---write your own one.
-The basic guidelines:
- 1. It should leave the control buffer current and the control window
- selected.
- 2. It should set ediff-window-A, ediff-window-B, ediff-window-C,
- and ediff-control-window to contain window objects that display
- the corresponding buffers.
- 3. It should accept the following arguments:
- buffer-A, buffer-B, buffer-C, control-buffer
- Buffer C may not be used in jobs that compare only two buffers.
-If you plan to do something fancy, take a close look at how the two
-provided functions are written.")
-
-;; indicates if we are in a multiframe setup
-(ediff-defvar-local ediff-multiframe nil "")
-
-;; Share of the frame occupied by the merge window (buffer C)
-(ediff-defvar-local ediff-merge-window-share 0.45 "")
-
-;; The control window.
-(ediff-defvar-local ediff-control-window nil "")
-;; Official window for buffer A
-(ediff-defvar-local ediff-window-A nil "")
-;; Official window for buffer B
-(ediff-defvar-local ediff-window-B nil "")
-;; Official window for buffer C
-(ediff-defvar-local ediff-window-C nil "")
-;; Ediff's window configuration.
-;; Used to minimize the need to rearrange windows.
-(ediff-defvar-local ediff-window-config-saved "" "")
-
-
-(defvar ediff-split-window-function 'split-window-vertically
- "*The function used to split the main window between buffer-A and buffer-B.
-You can set it to a horizontal split instead of the default vertical split
-by setting this variable to `split-window-horizontally'.
-You can also have your own function to do fancy splits.
-This variable has no effect when buffer-A/B are shown in different frames.
-In this case, Ediff will use those frames to display these buffers.")
-
-(defvar ediff-merge-split-window-function 'split-window-horizontally
- "*The function used to split the main window between buffer-A and buffer-B.
-You can set it to a vertical split instead of the default horizontal split
-by setting this variable to `split-window-vertically'.
-You can also have your own function to do fancy splits.
-This variable has no effect when buffer-A/B/C are shown in different frames.
-In this case, Ediff will use those frames to display these buffers.")
-
-(defconst ediff-control-frame-parameters
- (list
- '(name . "Ediff")
- ;;'(unsplittable . t)
- '(minibuffer . nil)
- '(user-position . t) ; Emacs only
- '(vertical-scroll-bars . nil) ; Emacs only
- '(scrollbar-width . 0) ; XEmacs only
- '(menu-bar-lines . 0) ; Emacs only
- ;; don't lower and auto-raise
- '(auto-lower . nil)
- '(auto-raise . t)
- ;; this blocks queries from window manager as to where to put
- ;; ediff's control frame. we put the frame outside the display,
- ;; so the initial frame won't jump all over the screen
- (cons 'top (if (fboundp 'ediff-display-pixel-height)
- (1+ (ediff-display-pixel-height))
- 3000))
- (cons 'left (if (fboundp 'ediff-display-pixel-width)
- (1+ (ediff-display-pixel-width))
- 3000))
- )
- "Frame parameters for displaying Ediff Control Panel.
-Do not specify width and height here. These are computed automatically.")
-
-;; position of the mouse; used to decide whether to warp the mouse into ctl
-;; frame
-(ediff-defvar-local ediff-mouse-pixel-position nil "")
-
-;; not used for now
-(defvar ediff-mouse-pixel-threshold 30
- "If the user moves mouse more than this many pixels, Ediff won't warp mouse into control window.")
-
-(defvar ediff-grab-mouse t
- "*If t, Ediff will always grab the mouse and put it in the control frame.
-If 'maybe, Ediff will do it sometimes, but not after operations that require
-relatively long time. If nil, the mouse will be entirely user's
-responsibility.")
-
-(defvar ediff-control-frame-position-function 'ediff-make-frame-position
- "Function to call to determine the desired location for the control panel.
-Expects three parameters: the control buffer, the desired width and height
-of the control frame. It returns an association list
-of the form \(\(top . <position>\) \(left . <position>\)\)")
-
-(defvar ediff-control-frame-upward-shift (if ediff-xemacs-p 42 14)
- "*The upward shift of control frame from the top of buffer A's frame.
-Measured in pixels.
-This is used by the default control frame positioning function,
-`ediff-make-frame-position'. This variable is provided for easy
-customization of the default.")
-
-(defvar ediff-narrow-control-frame-leftward-shift (if ediff-xemacs-p 7 3)
- "*The leftward shift of control frame from the right edge of buf A's frame.
-Measured in characters.
-This is used by the default control frame positioning function,
-`ediff-make-frame-position' to adjust the position of the control frame
-when it shows the short menu. This variable is provided for easy
-customization of the default.")
-
-(defvar ediff-wide-control-frame-rightward-shift 7
- "*The rightward shift of control frame from the left edge of buf A's frame.
-Measured in characters.
-This is used by the default control frame positioning function,
-`ediff-make-frame-position' to adjust the position of the control frame
-when it shows the full menu. This variable is provided for easy
-customization of the default.")
-
-
-;; Wide frame display
-
-;; t means Ediff is using wide display
-(ediff-defvar-local ediff-wide-display-p nil "")
-;; keeps frame config for toggling wide display
-(ediff-defvar-local ediff-wide-display-orig-parameters nil
- "Frame parameters to be restored when the user wants to toggle the wide
-display off.")
-(ediff-defvar-local ediff-wide-display-frame nil
- "Frame to be used for wide display.")
-(ediff-defvar-local ediff-make-wide-display-function 'ediff-make-wide-display
- "The value is a function that is called to create a wide display.
-The function is called without arguments. It should resize the frame in
-which buffers A, B, and C are to be displayed, and it should save the old
-frame parameters in `ediff-wide-display-orig-parameters'.
-The variable `ediff-wide-display-frame' should be set to contain
-the frame used for the wide display.")
-
-;; Frame used for the control panel in a windowing system.
-(ediff-defvar-local ediff-control-frame nil "")
-
-(defvar ediff-prefer-iconified-control-frame nil
- "*If t, keep control panel iconified when help message is off.
-This has effect only on a windowing system.
-If t, hitting `?' to toggle control panel off iconifies it.
-
-This is only useful in Emacs and only for certain kinds of window managers,
-such as TWM and its derivatives, since the window manager must permit
-keyboard input to go into icons. XEmacs completely ignores keyboard input
-into icons, regardless of the window manager.")
-
-;;; Functions
-
-(defun ediff-get-window-by-clicking (wind prev-wind wind-number)
- (let (event)
- (message
- "Select windows by clicking. Please click on Window %d " wind-number)
- (while (not (ediff-mouse-event-p (setq event (ediff-read-event))))
- (if (sit-for 1) ; if sequence of events, wait till the final word
- (beep 1))
- (message "Please click on Window %d " wind-number))
- (ediff-read-event) ; discard event
- (setq wind (if ediff-xemacs-p
- (event-window event)
- (posn-window (event-start event))))
- ))
-
-
-;; Select the lowest window on the frame.
-(defun ediff-select-lowest-window ()
- (if ediff-xemacs-p
- (select-window (frame-lowest-window))
- (let* ((lowest-window (selected-window))
- (bottom-edge (car (cdr (cdr (cdr (window-edges))))))
- (last-window (save-excursion
- (other-window -1) (selected-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))))))))
-
-
-;;; Common window setup routines
-
-;; Set up the window configuration. If POS is given, set the points to
-;; the beginnings of the buffers.
-;; When 3way comparison is added, this will have to choose the appropriate
-;; setup function based on ediff-job-name
-(defun ediff-setup-windows (buffer-A buffer-B buffer-C control-buffer)
- ;; Make sure we are not in the minibuffer window when we try to delete
- ;; all other windows.
- (run-hooks 'ediff-before-setup-windows-hook)
- (if (eq (selected-window) (minibuffer-window))
- (other-window 1))
-
- ;; in case user did a no-no on a tty
- (or (ediff-window-display-p)
- (setq ediff-window-setup-function 'ediff-setup-windows-plain))
-
- (or (ediff-keep-window-config control-buffer)
- (funcall
- (ediff-eval-in-buffer control-buffer ediff-window-setup-function)
- buffer-A buffer-B buffer-C control-buffer))
- (run-hooks 'ediff-after-setup-windows-hook))
-
-;; Just set up 3 windows.
-;; Usually used without windowing systems
-;; With windowing, we want to use dedicated frames.
-(defun ediff-setup-windows-plain (buffer-A buffer-B buffer-C control-buffer)
- (ediff-eval-in-buffer control-buffer
- (setq ediff-multiframe nil))
- (if ediff-merge-job
- (ediff-setup-windows-plain-merge
- buffer-A buffer-B buffer-C control-buffer)
- (ediff-setup-windows-plain-compare
- buffer-A buffer-B buffer-C control-buffer)))
-
-(defun ediff-setup-windows-plain-merge (buf-A buf-B buf-C control-buffer)
- ;; skip dedicated and unsplittable frames
- (ediff-destroy-control-frame control-buffer)
- (let ((window-min-height 1)
- split-window-function
- merge-window-share merge-window-lines
- wind-A wind-B wind-C)
- (ediff-eval-in-buffer control-buffer
- (setq merge-window-share ediff-merge-window-share
- ;; this lets us have local versions of ediff-split-window-function
- split-window-function ediff-split-window-function))
- (delete-other-windows)
- (split-window-vertically)
- (ediff-select-lowest-window)
- (ediff-setup-control-buffer control-buffer)
-
- ;; go to the upper window and split it betw A, B, and possibly C
- (other-window 1)
- (setq merge-window-lines
- (max 2 (round (* (window-height) merge-window-share))))
- (switch-to-buffer buf-A)
- (setq wind-A (selected-window))
-
- ;; XEmacs used to have a lot of trouble with display
- ;; It did't set things right unless we tell it to sit still
- ;; 19.12 seems ok.
- ;;(if ediff-xemacs-p (sit-for 0))
-
- (split-window-vertically (max 2 (- (window-height) merge-window-lines)))
- (if (eq (selected-window) wind-A)
- (other-window 1))
- (setq wind-C (selected-window))
- (switch-to-buffer buf-C)
-
- (select-window wind-A)
- (funcall split-window-function)
-
- (if (eq (selected-window) wind-A)
- (other-window 1))
- (switch-to-buffer buf-B)
- (setq wind-B (selected-window))
-
- (ediff-eval-in-buffer control-buffer
- (setq ediff-window-A wind-A
- ediff-window-B wind-B
- ediff-window-C wind-C))
-
- (ediff-select-lowest-window)
- (ediff-setup-control-buffer control-buffer)
- ))
-
-
-;; This function handles all comparison jobs, including 3way jobs
-(defun ediff-setup-windows-plain-compare (buf-A buf-B buf-C control-buffer)
- ;; skip dedicated and unsplittable frames
- (ediff-destroy-control-frame control-buffer)
- (let ((window-min-height 1)
- split-window-function wind-width-or-height
- three-way-comparison
- wind-A-start wind-B-start wind-A wind-B wind-C)
- (ediff-eval-in-buffer control-buffer
- (setq wind-A-start (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type
- 'A ediff-narrow-bounds))
- wind-B-start (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type
- 'B ediff-narrow-bounds))
- ;; this lets us have local versions of ediff-split-window-function
- split-window-function ediff-split-window-function
- three-way-comparison ediff-3way-comparison-job))
- (delete-other-windows)
- (split-window-vertically)
- (ediff-select-lowest-window)
- (ediff-setup-control-buffer control-buffer)
-
- ;; go to the upper window and split it betw A, B, and possibly C
- (other-window 1)
- (switch-to-buffer buf-A)
- (setq wind-A (selected-window))
- (if three-way-comparison
- (setq wind-width-or-height
- (/ (if (eq split-window-function 'split-window-vertically)
- (window-height wind-A)
- (window-width wind-A))
- 3)))
-
- ;; XEmacs used to have a lot of trouble with display
- ;; It did't set things right unless we told it to sit still
- ;; 19.12 seems ok.
- ;;(if ediff-xemacs-p (sit-for 0))
-
- (funcall split-window-function wind-width-or-height)
-
- (if (eq (selected-window) wind-A)
- (other-window 1))
- (switch-to-buffer buf-B)
- (setq wind-B (selected-window))
-
- (if three-way-comparison
- (progn
- (funcall split-window-function) ; equally
- (if (eq (selected-window) wind-B)
- (other-window 1))
- (switch-to-buffer buf-C)
- (setq wind-C (selected-window))))
-
- (ediff-eval-in-buffer control-buffer
- (setq ediff-window-A wind-A
- ediff-window-B wind-B
- ediff-window-C wind-C))
-
- ;; It is unlikely that we will want to implement 3way window comparison.
- ;; So, only buffers A and B are used here.
- (if ediff-windows-job
- (progn
- (set-window-start wind-A wind-A-start)
- (set-window-start wind-B wind-B-start)))
-
- (ediff-select-lowest-window)
- (ediff-setup-control-buffer control-buffer)
- ))
-
-
-;; dispatch an appropriate window setup function
-(defun ediff-setup-windows-multiframe (buf-A buf-B buf-C control-buf)
- (ediff-eval-in-buffer control-buf
- (setq ediff-multiframe t))
- (if ediff-merge-job
- (ediff-setup-windows-multiframe-merge buf-A buf-B buf-C control-buf)
- (ediff-setup-windows-multiframe-compare buf-A buf-B buf-C control-buf)))
-
-(defun ediff-setup-windows-multiframe-merge (buf-A buf-B buf-C control-buf)
-;;; Algorithm:
-;;; 1. Never use frames that have dedicated windows in them---it is bad to
-;;; destroy dedicated windows.
-;;; 2. If A and B are in the same frame but C's frame is different--- use one
-;;; frame for A and B and use a separate frame for C.
-;;; 3. If C's frame is non-existent, then: if the first suitable
-;;; non-dedicated frame is different from A&B's, then use it for C.
-;;; Otherwise, put A,B, and C in one frame.
-;;; 4. If buffers A, B, C are is separate frames, use them to display these
-;;; buffers.
-
- ;; Skip dedicated or iconified frames.
- ;; Unsplittable frames are taken care of later.
- (ediff-skip-unsuitable-frames 'ok-unsplittable)
-
- (let* ((window-min-height 1)
- (wind-A (ediff-get-visible-buffer-window buf-A))
- (wind-B (ediff-get-visible-buffer-window buf-B))
- (wind-C (ediff-get-visible-buffer-window buf-C))
- (frame-A (if wind-A (window-frame wind-A)))
- (frame-B (if wind-B (window-frame wind-B)))
- (frame-C (if wind-C (window-frame wind-C)))
- ;; on wide display, do things in one frame
- (force-one-frame
- (ediff-eval-in-buffer control-buf ediff-wide-display-p))
- ;; this lets us have local versions of ediff-split-window-function
- (split-window-function
- (ediff-eval-in-buffer control-buf ediff-split-window-function))
- (orig-wind (selected-window))
- (orig-frame (selected-frame))
- (use-same-frame (or force-one-frame
- ;; A and C must be in one frame
- (eq frame-A (or frame-C orig-frame))
- ;; B and C must be in one frame
- (eq frame-B (or frame-C orig-frame))
- ;; A or B is not visible
- (not (frame-live-p frame-A))
- (not (frame-live-p frame-B))
- ;; A or B is not suitable for display
- (not (ediff-window-ok-for-display wind-A))
- (not (ediff-window-ok-for-display wind-B))
- ;; A and B in the same frame, and no good frame
- ;; for C
- (and (eq frame-A frame-B)
- (not (frame-live-p frame-C)))
- ))
- ;; use-same-frame-for-AB implies wind A and B are ok for display
- (use-same-frame-for-AB (and (not use-same-frame)
- (eq frame-A frame-B)))
- (merge-window-share (ediff-eval-in-buffer control-buf
- ediff-merge-window-share))
- merge-window-lines
- designated-minibuffer-frame
- done-A done-B done-C)
-
- ;; buf-A on its own
- (if (and (window-live-p wind-A)
- (null use-same-frame) ; implies wind-A is suitable
- (null use-same-frame-for-AB))
- (progn ; bug A on its own
- ;; buffer buf-A is seen in live wind-A
- (select-window wind-A)
- (delete-other-windows)
- (setq wind-A (selected-window))
- (setq done-A t)))
-
- ;; buf-B on its own
- (if (and (window-live-p wind-B)
- (null use-same-frame) ; implies wind-B is suitable
- (null use-same-frame-for-AB))
- (progn ; buf B on its own
- ;; buffer buf-B is seen in live wind-B
- (select-window wind-B)
- (delete-other-windows)
- (setq wind-B (selected-window))
- (setq done-B t)))
-
- ;; buf-C on its own
- (if (and (window-live-p wind-C)
- (ediff-window-ok-for-display wind-C)
- (null use-same-frame)) ; buf C on its own
- (progn
- ;; buffer buf-C is seen in live wind-C
- (select-window wind-C)
- (delete-other-windows)
- (setq wind-C (selected-window))
- (setq done-C t)))
-
- (if (and use-same-frame-for-AB ; implies wind A and B are suitable
- (window-live-p wind-A))
- (progn
- ;; wind-A must already be displaying buf-A
- (select-window wind-A)
- (delete-other-windows)
- (setq wind-A (selected-window))
-
- (funcall split-window-function)
- (if (eq (selected-window) wind-A)
- (other-window 1))
- (switch-to-buffer buf-B)
- (setq wind-B (selected-window))
-
- (setq done-A t
- done-B t)))
-
- (if use-same-frame
- (let ((window-min-height 1))
- ;; avoid dedicated and non-splittable windows
- (ediff-skip-unsuitable-frames)
- (delete-other-windows)
- (setq merge-window-lines
- (max 2 (round (* (window-height) merge-window-share))))
- (switch-to-buffer buf-A)
- (setq wind-A (selected-window))
-
- (split-window-vertically
- (max 2 (- (window-height) merge-window-lines)))
- (if (eq (selected-window) wind-A)
- (other-window 1))
- (setq wind-C (selected-window))
- (switch-to-buffer buf-C)
-
- (select-window wind-A)
-
- (funcall split-window-function)
- (if (eq (selected-window) wind-A)
- (other-window 1))
- (switch-to-buffer buf-B)
- (setq wind-B (selected-window))
-
- (setq done-A t
- done-B t
- done-C t)
- ))
-
- (or done-A ; Buf A to be set in its own frame,
- ;;; or it was set before because use-same-frame = 1
- (progn
- ;; Buf-A was not set up yet as it wasn't visible,
- ;; and use-same-frame = nil, use-same-frame-for-AB = nil
- (select-window orig-wind)
- (delete-other-windows)
- (switch-to-buffer buf-A)
- (setq wind-A (selected-window))
- ))
- (or done-B ; Buf B to be set in its own frame,
- ;;; or it was set before because use-same-frame = 1
- (progn
- ;; Buf-B was not set up yet as it wasn't visible
- ;; and use-same-frame = nil, use-same-frame-for-AB = nil
- (select-window orig-wind)
- (delete-other-windows)
- (switch-to-buffer buf-B)
- (setq wind-B (selected-window))
- ))
-
- (or done-C ; Buf C to be set in its own frame,
- ;;; or it was set before because use-same-frame = 1
- (progn
- ;; Buf-C was not set up yet as it wasn't visible
- ;; and use-same-frame = nil
- (select-window orig-wind)
- (delete-other-windows)
- (switch-to-buffer buf-C)
- (setq wind-C (selected-window))
- ))
-
- (ediff-eval-in-buffer control-buf
- (setq ediff-window-A wind-A
- ediff-window-B wind-B
- ediff-window-C wind-C)
- (setq frame-A (window-frame ediff-window-A)
- designated-minibuffer-frame
- (window-frame (minibuffer-window frame-A))))
-
- (ediff-setup-control-frame control-buf designated-minibuffer-frame)
- ))
-
-
-;; Window setup for all comparison jobs, including 3way comparisons
-(defun ediff-setup-windows-multiframe-compare (buf-A buf-B buf-C control-buf)
-;;; Algorithm:
-;;; If a buffer is seen in a frame, use that frame for that buffer.
-;;; If it is not seen, use the current frame.
-;;; If both buffers are not seen, they share the current frame. If one
-;;; of the buffers is not seen, it is placed in the current frame (where
-;;; ediff started). If that frame is displaying the other buffer, it is
-;;; shared between the two buffers.
-;;; However, if we decide to put both buffers in one frame
-;;; and the selected frame isn't splittable, we create a new frame and
-;;; put both buffers there, event if one of this buffers is visible in
-;;; another frame.
-
- ;; Skip dedicated or iconified frames.
- ;; Unsplittable frames are taken care of later.
- (ediff-skip-unsuitable-frames 'ok-unsplittable)
-
- (let* ((window-min-height 1)
- (wind-A (ediff-get-visible-buffer-window buf-A))
- (wind-B (ediff-get-visible-buffer-window buf-B))
- (wind-C (ediff-get-visible-buffer-window buf-C))
- (frame-A (if wind-A (window-frame wind-A)))
- (frame-B (if wind-B (window-frame wind-B)))
- (frame-C (if wind-C (window-frame wind-C)))
- (ctl-frame-exists-p (ediff-eval-in-buffer control-buf
- (frame-live-p ediff-control-frame)))
- ;; on wide display, do things in one frame
- (force-one-frame
- (ediff-eval-in-buffer control-buf ediff-wide-display-p))
- ;; this lets us have local versions of ediff-split-window-function
- (split-window-function
- (ediff-eval-in-buffer control-buf ediff-split-window-function))
- (three-way-comparison
- (ediff-eval-in-buffer control-buf ediff-3way-comparison-job))
- (orig-wind (selected-window))
- (use-same-frame (or force-one-frame
- (eq frame-A frame-B)
- (not (ediff-window-ok-for-display wind-A))
- (not (ediff-window-ok-for-display wind-B))
- (if three-way-comparison
- (or (eq frame-A frame-C)
- (eq frame-B frame-C)
- (not (ediff-window-ok-for-display wind-C))
- (not (frame-live-p frame-A))
- (not (frame-live-p frame-B))
- (not (frame-live-p frame-C))))
- (and (not (frame-live-p frame-B))
- (or ctl-frame-exists-p
- (eq frame-A (selected-frame))))
- (and (not (frame-live-p frame-A))
- (or ctl-frame-exists-p
- (eq frame-B (selected-frame))))))
- wind-A-start wind-B-start
- designated-minibuffer-frame
- done-A done-B done-C)
-
- (ediff-eval-in-buffer control-buf
- (setq wind-A-start (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type
- 'A ediff-narrow-bounds))
- wind-B-start (ediff-overlay-start
- (ediff-get-value-according-to-buffer-type
- 'B ediff-narrow-bounds))))
-
- (if (and (window-live-p wind-A) (null use-same-frame)) ; buf-A on its own
- (progn
- ;; buffer buf-A is seen in live wind-A
- (select-window wind-A) ; must be displaying buf-A
- (delete-other-windows)
- (setq wind-A (selected-window))
- (setq done-A t)))
-
- (if (and (window-live-p wind-B) (null use-same-frame)) ; buf B on its own
- (progn
- ;; buffer buf-B is seen in live wind-B
- (select-window wind-B) ; must be displaying buf-B
- (delete-other-windows)
- (setq wind-B (selected-window))
- (setq done-B t)))
-
- (if (and (window-live-p wind-C) (null use-same-frame)) ; buf C on its own
- (progn
- ;; buffer buf-C is seen in live wind-C
- (select-window wind-C) ; must be displaying buf-C
- (delete-other-windows)
- (setq wind-C (selected-window))
- (setq done-C t)))
-
- (if use-same-frame
- (let (wind-width-or-height) ; this affects 3way setups only
- ;; avoid dedicated and non-splittable windows
- (ediff-skip-unsuitable-frames)
- (delete-other-windows)
- (switch-to-buffer buf-A)
- (setq wind-A (selected-window))
-
- (if three-way-comparison
- (setq wind-width-or-height
- (/
- (if (eq split-window-function 'split-window-vertically)
- (window-height wind-A)
- (window-width wind-A))
- 3)))
-
- (funcall split-window-function wind-width-or-height)
- (if (eq (selected-window) wind-A)
- (other-window 1))
- (switch-to-buffer buf-B)
- (setq wind-B (selected-window))
-
- (if three-way-comparison
- (progn
- (funcall split-window-function) ; equally
- (if (memq (selected-window) (list wind-A wind-B))
- (other-window 1))
- (switch-to-buffer buf-C)
- (setq wind-C (selected-window))))
- (setq done-A t
- done-B t
- done-C t)
- ))
-
- (or done-A ; Buf A to be set in its own frame
- ;;; or it was set before because use-same-frame = 1
- (progn
- ;; Buf-A was not set up yet as it wasn't visible,
- ;; and use-same-frame = nil
- (select-window orig-wind)
- (delete-other-windows)
- (switch-to-buffer buf-A)
- (setq wind-A (selected-window))
- ))
- (or done-B ; Buf B to be set in its own frame
- ;;; or it was set before because use-same-frame = 1
- (progn
- ;; Buf-B was not set up yet as it wasn't visible,
- ;; and use-same-frame = nil
- (select-window orig-wind)
- (delete-other-windows)
- (switch-to-buffer buf-B)
- (setq wind-B (selected-window))
- ))
-
- (if three-way-comparison
- (or done-C ; Buf C to be set in its own frame
- ;;; or it was set before because use-same-frame = 1
- (progn
- ;; Buf-C was not set up yet as it wasn't visible,
- ;; and use-same-frame = nil
- (select-window orig-wind)
- (delete-other-windows)
- (switch-to-buffer buf-C)
- (setq wind-C (selected-window))
- )))
-
- (ediff-eval-in-buffer control-buf
- (setq ediff-window-A wind-A
- ediff-window-B wind-B
- ediff-window-C wind-C)
-
- (setq frame-A (window-frame ediff-window-A)
- designated-minibuffer-frame
- (window-frame (minibuffer-window frame-A))))
-
- ;; It is unlikely that we'll implement a version of ediff-windows that
- ;; would compare 3 windows at once. So, we don't use buffer C here.
- (if ediff-windows-job
- (progn
- (set-window-start wind-A wind-A-start)
- (set-window-start wind-B wind-B-start)))
-
- (ediff-setup-control-frame control-buf designated-minibuffer-frame)
- ))
-
-;; skip unsplittable frames and frames that have dedicated windows.
-;; create a new splittable frame if none is found
-(defun ediff-skip-unsuitable-frames (&optional ok-unsplittable)
- (if (ediff-window-display-p)
- (let (last-window)
- (while (and (not (eq (selected-window) last-window))
- (or
- (ediff-frame-has-dedicated-windows (selected-frame))
- (ediff-frame-iconified-p (selected-frame))
- (< (frame-height (selected-frame))
- (* 3 window-min-height))
- (if ok-unsplittable
- nil
- (ediff-frame-unsplittable-p (selected-frame)))))
- ;; remember where started
- (or last-window (setq last-window (selected-window)))
- ;; try new window
- (other-window 1 t))
- (if (eq (selected-window) last-window)
- ;; fed up, no appropriate frame
- (progn
- (select-frame (make-frame '((unsplittable)))))))))
-
-(defun ediff-frame-has-dedicated-windows (frame)
- (let ((cur-fr (selected-frame))
- ans)
- (select-frame frame)
- (walk-windows
- (function (lambda (wind)
- (if (window-dedicated-p wind)
- (setq ans t))))
- 'ignore-minibuffer
- frame)
- (select-frame cur-fr)
- ans))
-
-;; window is ok, if it is only one window on the frame, not counting the
-;; minibuffer, or none of the frame's windows is dedicated.
-;; The idea is that it is bad to destroy dedicated windows while creating an
-;; ediff window setup
-(defun ediff-window-ok-for-display (wind)
- (and
- (window-live-p wind)
- (or
- ;; only one window
- (eq wind (next-window wind 'ignore-minibuffer (window-frame wind)))
- ;; none is dedicated
- (not (ediff-frame-has-dedicated-windows (window-frame wind)))
- )))
-
-;; Prepare or refresh control frame
-(defun ediff-setup-control-frame (ctl-buffer designated-minibuffer-frame)
- (let ((window-min-height 1)
- ctl-frame-iconified-p dont-iconify-ctl-frame deiconify-ctl-frame
- ctl-frame old-ctl-frame lines
- ;; user-grabbed-mouse
- fheight fwidth adjusted-parameters)
-
- (ediff-eval-in-buffer ctl-buffer
- (if ediff-xemacs-p (set-buffer-menubar nil))
- ;;(setq user-grabbed-mouse (ediff-user-grabbed-mouse))
- (run-hooks 'ediff-before-setup-control-frame-hook))
-
- (setq old-ctl-frame (ediff-eval-in-buffer ctl-buffer ediff-control-frame))
- (ediff-eval-in-buffer ctl-buffer
- (setq ctl-frame (if (frame-live-p old-ctl-frame)
- old-ctl-frame
- (make-frame ediff-control-frame-parameters))
- ediff-control-frame ctl-frame))
-
- (setq ctl-frame-iconified-p (ediff-frame-iconified-p ctl-frame))
- (select-frame ctl-frame)
- (if (window-dedicated-p (selected-window))
- ()
- (delete-other-windows)
- (switch-to-buffer ctl-buffer))
-
- ;; must be before ediff-setup-control-buffer
- ;; just a precaution--we should be in ctl-buffer already
- (ediff-eval-in-buffer ctl-buffer
- (make-local-variable 'frame-title-format)
- (make-local-variable 'frame-icon-title-format) ; XEmacs
- (make-local-variable 'icon-title-format)) ; Emacs
-
- (ediff-setup-control-buffer ctl-buffer)
- (setq dont-iconify-ctl-frame
- (not (string= ediff-help-message ediff-brief-help-message)))
- (setq deiconify-ctl-frame
- (and (eq this-command 'ediff-toggle-help)
- dont-iconify-ctl-frame))
-
- ;; 1 more line for the modeline
- (setq lines (1+ (count-lines (point-min) (point-max)))
- fheight lines
- fwidth (max (+ (ediff-help-message-line-length) 2)
- (ediff-compute-toolbar-width))
- adjusted-parameters (append (list
- ;; possibly change surrogate minibuffer
- (cons 'minibuffer
- (minibuffer-window
- designated-minibuffer-frame))
- (cons 'width fwidth)
- (cons 'height fheight))
- (funcall
- ediff-control-frame-position-function
- ctl-buffer fwidth fheight)))
- (if ediff-use-long-help-message
- (setq adjusted-parameters
- (cons '(auto-raise . nil) adjusted-parameters)))
-
- ;; In XEmacs, buffer menubar needs to be killed before frame parameters
- ;; are changed.
- (if ediff-xemacs-p
- (progn
- (set-specifier top-toolbar-height (list ctl-frame 0))
- (set-specifier bottom-toolbar-height (list ctl-frame 0))
- (set-specifier left-toolbar-width (list ctl-frame 0))
- (set-specifier right-toolbar-width (list ctl-frame 0))
- ))
-
- ;; Under OS/2 (emx) we have to call modify frame parameters twice, in order
- ;; to make sure that at least once we do it for non-iconified frame. If
- ;; appears that in the OS/2 port of Emacs, one can't modify frame
- ;; parameters of iconified frames. As a precaution, we do likewise for
- ;; windows-nt.
- (if (memq system-type '(emx windows-nt windows-95))
- (modify-frame-parameters ctl-frame adjusted-parameters))
-
- (goto-char (point-min))
-
- (modify-frame-parameters ctl-frame adjusted-parameters)
- (make-frame-visible ctl-frame)
- (ediff-make-bottom-toolbar) ; no effect if the toolbar is not requested
-
- ;; This works around a bug in 19.25 and earlier. There, if frame gets
- ;; iconified, the current buffer changes to that of the frame that
- ;; becomes exposed as a result of this iconification.
- ;; So, we make sure the current buffer doesn't change.
- (select-frame ctl-frame)
- (ediff-refresh-control-frame)
-
- (cond ((and ediff-prefer-iconified-control-frame
- (not ctl-frame-iconified-p) (not dont-iconify-ctl-frame))
- (iconify-frame ctl-frame))
- ((or deiconify-ctl-frame (not ctl-frame-iconified-p))
- (raise-frame ctl-frame)))
-
- (set-window-dedicated-p (selected-window) t)
-
- ;; synchronize so the cursor will move to control frame
- ;; per RMS suggestion
- (if (ediff-window-display-p)
- (let ((count 7))
- (sit-for .1)
- (while (and (not (frame-visible-p ctl-frame)) (> count 0))
- (setq count (1- count))
- (sit-for .3))))
-
- (or (ediff-frame-iconified-p ctl-frame)
- ;; don't warp the mouse, unless ediff-grab-mouse = t
- (ediff-reset-mouse ctl-frame
- (or (eq this-command 'ediff-quit)
- (not (eq ediff-grab-mouse t)))))
-
- (if ediff-xemacs-p
- (ediff-eval-in-buffer ctl-buffer
- (make-local-hook 'select-frame-hook)
- (add-hook 'select-frame-hook 'ediff-xemacs-select-frame-hook nil t)
- ))
-
- (ediff-eval-in-buffer ctl-buffer
- (run-hooks 'ediff-after-setup-control-frame-hook))
- ))
-
-(defun ediff-destroy-control-frame (ctl-buffer)
- (ediff-eval-in-buffer ctl-buffer
- (if (and (ediff-window-display-p) (frame-live-p ediff-control-frame))
- (let ((ctl-frame ediff-control-frame))
- (if ediff-xemacs-p
- (set-buffer-menubar default-menubar))
- (setq ediff-control-frame nil)
- (delete-frame ctl-frame)
- )))
- (ediff-skip-unsuitable-frames)
- ;;(ediff-reset-mouse nil)
- )
-
-
-;; finds a good place to clip control frame
-(defun ediff-make-frame-position (ctl-buffer ctl-frame-width ctl-frame-height)
- (ediff-eval-in-buffer ctl-buffer
- (let* ((frame-A (window-frame ediff-window-A))
- (frame-A-parameters (frame-parameters frame-A))
- (frame-A-top (eval (cdr (assoc 'top frame-A-parameters))))
- (frame-A-left (eval (cdr (assoc 'left frame-A-parameters))))
- (frame-A-width (frame-width frame-A))
- (ctl-frame ediff-control-frame)
- horizontal-adjustment upward-adjustment
- ctl-frame-top ctl-frame-left)
-
- ;; Multiple control frames are clipped based on the value of
- ;; ediff-control-buffer-number. This is done in order not to obscure
- ;; other active control panels.
- (setq horizontal-adjustment (* 2 ediff-control-buffer-number)
- upward-adjustment (* -14 ediff-control-buffer-number))
-
- (setq ctl-frame-top
- (- frame-A-top upward-adjustment ediff-control-frame-upward-shift)
- ctl-frame-left
- (+ frame-A-left
- (if ediff-use-long-help-message
- (* (ediff-frame-char-width ctl-frame)
- (+ ediff-wide-control-frame-rightward-shift
- horizontal-adjustment))
- (- (* frame-A-width (ediff-frame-char-width frame-A))
- (* (ediff-frame-char-width ctl-frame)
- (+ ctl-frame-width
- ediff-narrow-control-frame-leftward-shift
- horizontal-adjustment))))))
- (setq ctl-frame-top
- (min ctl-frame-top
- (- (ediff-display-pixel-height)
- (* 2 ctl-frame-height
- (ediff-frame-char-height ctl-frame))))
- ctl-frame-left
- (min ctl-frame-left
- (- (ediff-display-pixel-width)
- (* ctl-frame-width (ediff-frame-char-width ctl-frame)))))
- ;; keep ctl frame within the visible bounds
- (setq ctl-frame-top (max ctl-frame-top 1)
- ctl-frame-left (max ctl-frame-left 1))
-
- (list (cons 'top ctl-frame-top)
- (cons 'left ctl-frame-left))
- )))
-
-(defun ediff-xemacs-select-frame-hook ()
- (if (and (equal (selected-frame) ediff-control-frame)
- (not ediff-use-long-help-message))
- (raise-frame ediff-control-frame)))
-
-(defun ediff-make-wide-display ()
- "Construct an alist of parameters for the wide display.
-Saves the old frame parameters in `ediff-wide-display-orig-parameters'.
-The frame to be resized is kept in `ediff-wide-display-frame'.
-This function modifies only the left margin and the width of the display.
-It assumes that it is called from within the control buffer."
- (if (not (fboundp 'ediff-display-pixel-width))
- (error "Can't determine display width."))
- (let* ((frame-A (window-frame ediff-window-A))
- (frame-A-params (frame-parameters frame-A))
- (cw (ediff-frame-char-width frame-A))
- (wd (- (/ (ediff-display-pixel-width) cw) 5)))
- (setq ediff-wide-display-orig-parameters
- (list (cons 'left (max 0 (eval (cdr (assoc 'left frame-A-params)))))
- (cons 'width (cdr (assoc 'width frame-A-params))))
- ediff-wide-display-frame frame-A)
- (modify-frame-parameters frame-A (list (cons 'left cw)
- (cons 'width wd)))))
-
-
-
-;; Revise the mode line to display which difference we have selected
-;; Also resets modelines of buffers A/B, since they may be clobbered by
-;; anothe invocations of Ediff.
-(defun ediff-refresh-mode-lines ()
- (let (buf-A-state-diff buf-B-state-diff buf-C-state-diff buf-C-state-merge)
-
- (if (ediff-valid-difference-p)
- (setq
- buf-C-state-diff (ediff-get-state-of-diff ediff-current-difference 'C)
- buf-C-state-merge (ediff-get-state-of-merge ediff-current-difference)
- buf-A-state-diff (ediff-get-state-of-diff ediff-current-difference 'A)
- buf-B-state-diff (ediff-get-state-of-diff ediff-current-difference 'B)
- buf-A-state-diff (if buf-A-state-diff
- (format "[%s] " buf-A-state-diff)
- "")
- buf-B-state-diff (if buf-B-state-diff
- (format "[%s] " buf-B-state-diff)
- "")
- buf-C-state-diff (if (and (ediff-buffer-live-p ediff-buffer-C)
- (or buf-C-state-diff buf-C-state-merge))
- (format "[%s%s%s] "
- (or buf-C-state-diff "")
- (if buf-C-state-merge
- (concat " " buf-C-state-merge)
- "")
- (if (ediff-get-state-of-ancestor
- ediff-current-difference)
- " AncestorEmpty"
- "")
- )
- ""))
- (setq buf-A-state-diff ""
- buf-B-state-diff ""
- buf-C-state-diff ""))
-
- ;; control buffer format
- (setq mode-line-format
- (list (if (ediff-narrow-control-frame-p) " " "-- ")
- mode-line-buffer-identification
- " Quick Help"))
- ;; control buffer id
- (setq mode-line-buffer-identification
- (if (ediff-narrow-control-frame-p)
- (ediff-make-narrow-control-buffer-id 'skip-name)
- (ediff-make-wide-control-buffer-id)))
- ;; Force mode-line redisplay
- (force-mode-line-update)
-
- (if (and (ediff-window-display-p) (frame-live-p ediff-control-frame))
- (ediff-refresh-control-frame))
-
- (ediff-eval-in-buffer ediff-buffer-A
- (setq ediff-diff-status buf-A-state-diff)
- (ediff-strip-mode-line-format)
- (setq mode-line-format
- (list " A: " 'ediff-diff-status mode-line-format))
- (force-mode-line-update))
- (ediff-eval-in-buffer ediff-buffer-B
- (setq ediff-diff-status buf-B-state-diff)
- (ediff-strip-mode-line-format)
- (setq mode-line-format
- (list " B: " 'ediff-diff-status mode-line-format))
- (force-mode-line-update))
- (if ediff-3way-job
- (ediff-eval-in-buffer ediff-buffer-C
- (setq ediff-diff-status buf-C-state-diff)
- (ediff-strip-mode-line-format)
- (setq mode-line-format
- (list " C: " 'ediff-diff-status mode-line-format))
- (force-mode-line-update)))
- (if (ediff-buffer-live-p ediff-ancestor-buffer)
- (ediff-eval-in-buffer ediff-ancestor-buffer
- (ediff-strip-mode-line-format)
- ;; we keep the second dummy string in the mode line format of the
- ;; ancestor, since for other buffers Ediff prepends 2 strings and
- ;; ediff-strip-mode-line-format expects that.
- (setq mode-line-format
- (list " Ancestor: "
- (cond ((not (stringp buf-C-state-merge))
- "")
- ((string-match "prefer-A" buf-C-state-merge)
- "[=diff(B)] ")
- ((string-match "prefer-B" buf-C-state-merge)
- "[=diff(A)] ")
- (t ""))
- mode-line-format))))
- ))
-
-
-(defun ediff-refresh-control-frame ()
- (if ediff-emacs-p
- ;; set frame/icon titles for Emacs
- (modify-frame-parameters
- ediff-control-frame
- (list (cons 'title (ediff-make-base-title))
- (cons 'icon-name (ediff-make-narrow-control-buffer-id))
- ))
- ;; set frame/icon titles for XEmacs
- (setq frame-title-format (ediff-make-base-title)
- frame-icon-title-format (ediff-make-narrow-control-buffer-id))
- ;; force an update of the frame title
- (modify-frame-parameters ediff-control-frame '(()))))
-
-
-(defun ediff-make-narrow-control-buffer-id (&optional skip-name)
- (concat
- (if skip-name
- " "
- (ediff-make-base-title))
- (cond ((< ediff-current-difference 0)
- (format " _/%d" ediff-number-of-differences))
- ((>= ediff-current-difference ediff-number-of-differences)
- (format " $/%d" ediff-number-of-differences))
- (t
- (format " %d/%d"
- (1+ ediff-current-difference)
- ediff-number-of-differences)))))
-
-(defun ediff-make-base-title ()
- (concat
- (cdr (assoc 'name ediff-control-frame-parameters))
- ediff-control-buffer-suffix))
-
-(defun ediff-make-wide-control-buffer-id ()
- (cond ((< ediff-current-difference 0)
- (list (format "%%b At start of %d diffs"
- ediff-number-of-differences)))
- ((>= ediff-current-difference ediff-number-of-differences)
- (list (format "%%b At end of %d diffs"
- ediff-number-of-differences)))
- (t
- (list (format "%%b diff %d of %d"
- (1+ ediff-current-difference)
- ediff-number-of-differences)))))
-
-
-
-;; If buff is not live, return nil
-(defun ediff-get-visible-buffer-window (buff)
- (if (ediff-buffer-live-p buff)
- (if ediff-xemacs-p
- (get-buffer-window buff t)
- (get-buffer-window buff 'visible))))
-
-
-;;; Functions to decide when to redraw windows
-
-(defun ediff-keep-window-config (control-buf)
- (and (eq control-buf (current-buffer))
- (/= (buffer-size) 0)
- (ediff-eval-in-buffer control-buf
- (let ((ctl-wind ediff-control-window)
- (A-wind ediff-window-A)
- (B-wind ediff-window-B)
- (C-wind ediff-window-C))
-
- (and
- (ediff-window-visible-p A-wind)
- (ediff-window-visible-p B-wind)
- ;; if buffer C is defined then take it into account
- (or (not ediff-3way-job)
- (ediff-window-visible-p C-wind))
- (eq (window-buffer A-wind) ediff-buffer-A)
- (eq (window-buffer B-wind) ediff-buffer-B)
- (or (not ediff-3way-job)
- (eq (window-buffer C-wind) ediff-buffer-C))
- (string= ediff-window-config-saved
- (format "%S%S%S%S%S%S%S"
- ctl-wind A-wind B-wind C-wind
- ediff-split-window-function
- (ediff-multiframe-setup-p)
- ediff-wide-display-p)))))))
-
-
-;;; Local Variables:
-;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
-;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
-;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
-;;; End:
-
-(provide 'ediff-wind)
-
-
-;;; ediff-wind.el ends here
diff --git a/lisp/ediff.el b/lisp/ediff.el
deleted file mode 100644
index 9c4c8cec3e5..00000000000
--- a/lisp/ediff.el
+++ /dev/null
@@ -1,1279 +0,0 @@
-;;; ediff.el --- a comprehensive visual interface to diff & patch
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Michael Kifer <kifer@cs.sunysb.edu>
-;; Created: February 2, 1994
-;; Keywords: comparing, merging, patching, version control.
-
-(defconst ediff-version "2.63" "The current version of Ediff")
-(defconst ediff-date "September 12, 1996" "Date of last update")
-
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Never read that diff output again!
-;; Apply patch interactively!
-;; Merge with ease!
-
-;; This package provides a convenient way of simultaneous browsing through
-;; the differences between a pair (or a triple) of files or buffers. The
-;; files being compared, file-A, file-B, and file-C (if applicable) are
-;; shown in separate windows (side by side, one above the another, or in
-;; separate frames), and the differences are highlighted as you step
-;; through them. You can also copy difference regions from one buffer to
-;; another (and recover old differences if you change your mind).
-
-;; Ediff also supports merging operations on files and buffers, including
-;; merging using ancestor versions. Both comparison and merging operations can
-;; be performed on directories, i.e., by pairwise comparison of files in those
-;; directories.
-
-;; In addition, Ediff can apply a patch to a file and then let you step
-;; though both files, the patched and the original one, simultaneously,
-;; difference-by-difference. You can even apply a patch right out of a
-;; mail buffer, i.e., patches received by mail don't even have to be saved.
-;; Since Ediff lets you copy differences between buffers, you can, in
-;; effect, apply patches selectively (i.e., you can copy a difference
-;; region from file_orig to file, thereby undoing any particular patch that
-;; you don't like).
-
-;; Ediff is aware of version control, which lets the user compare
-;; files with their older versions. Ediff can also work with remote and
-;; compressed files. Details are given below.
-
-;; Finally, Ediff supports directory-level comparison, merging and patching.
-;; See the on-line manual for details.
-
-;; This package builds upon the ideas borrowed from emerge.el and several
-;; Ediff's functions are adaptations from emerge.el. Much of the functionality
-;; Ediff provides is also influenced by emerge.el.
-
-;; The present version of Ediff supersedes Emerge. It provides a superior user
-;; interface and has numerous major features not found in Emerge. In
-;; particular, it can do patching, and 2-way and 3-way file comparison,
-;; merging, and directory operations.
-
-
-
-;;; Bugs:
-
-;; 1. The undo command doesn't restore deleted regions well. That is, if
-;; you delete all characters in a difference region and then invoke
-;; `undo', the reinstated text will most likely be inserted outside of
-;; what Ediff thinks is the current difference region. (This problem
-;; doesn't seem to exist with XEmacs.)
-;;
-;; If at any point you feel that difference regions are no longer correct,
-;; you can hit '!' to recompute the differences.
-
-;; 2. On a monochrome display, the repertoire of faces with which to
-;; highlight fine differences is limited. By default, Ediff is using
-;; underlining. However, if the region is already underlined by some other
-;; overlays, there is no simple way to temporarily remove that residual
-;; underlining. This problem occurs when a buffer is highlighted with
-;; hilit19.el or font-lock.el packages. If this residual highlighting gets
-;; in the way, you can do the following. Both font-lock.el and hilit19.el
-;; provide commands for unhighlighting buffers. You can either place these
-;; commands in `ediff-prepare-buffer-hook' (which will unhighlight every
-;; buffer used by Ediff) or you can execute them interactively, at any time
-;; and on any buffer.
-
-
-;;; Acknowledgements:
-
-;; Ediff was inspired by Dale R. Worley's <drw@math.mit.edu> emerge.el.
-;; Ediff would not have been possible without the help and encouragement of
-;; its many users. See Ediff on-line Info for the full list of those who
-;; helped. Improved defaults in Ediff file-name reading commands.
-
-;;; Code:
-
-(require 'ediff-init)
-;; ediff-mult is always required, because of the registry stuff
-(require 'ediff-mult)
-
-(and noninteractive
- (eval-when-compile
- (let ((load-path (cons (expand-file-name ".") load-path)))
- (load-library "dired")
- (load-file "ediff-ptch.el")
- (load-file "ediff-vers.el")
- (load "pcl-cvs" 'noerror))))
-
-(defvar ediff-use-last-dir nil
- "*If t, Ediff uses previous directory as default when reading file name.")
-
-(defvar ediff-last-dir-A nil
- "Last directory used by an Ediff command for file-A.")
-(defvar ediff-last-dir-B nil
- "Last directory used by an Ediff command for file-B.")
-(defvar ediff-last-dir-C nil
- "Last directory used by an Ediff command for file-C.")
-(defvar ediff-last-dir-ancestor nil
- "Last directory used by an Ediff command for the ancestor file.")
-(defvar ediff-last-merge-autostore-dir
- "Last directory used by an Ediff command as the output directory for merge.")
-
-;; Some defvars to reduce the number of compiler warnings
-(defvar cvs-cookie-handle)
-(defvar ediff-last-dir-patch)
-(defvar ediff-patch-default-directory)
-;; end of compiler pacifier
-
-
-;; Used as a startup hook to set `_orig' patch file read-only.
-(defun ediff-set-read-only-in-buf-A ()
- (ediff-eval-in-buffer ediff-buffer-A
- (toggle-read-only 1)))
-
-;; Return a plausible default for ediff's first file:
-;; In dired, return the file name under the point, unless it is a directory
-;; If the buffer has a file name, return that file name.
-(defun ediff-get-default-file-name ()
- (cond ((eq major-mode 'dired-mode)
- (let ((f (dired-get-filename nil 'no-error)))
- (if (and (stringp f) (not (file-directory-p f)))
- f)))
- ((buffer-file-name (current-buffer))
- (file-name-nondirectory (buffer-file-name (current-buffer))))
- ))
-
-;;; Compare files/buffers
-
-;;;###autoload
-(defun ediff-files (file-A file-B &optional startup-hooks)
- "Run Ediff on a pair of files, FILE-A and FILE-B."
- (interactive
- (let ((dir-A (if ediff-use-last-dir
- ediff-last-dir-A
- default-directory))
- dir-B f)
- (list (setq f (ediff-read-file-name
- "File A to compare" dir-A
- (ediff-get-default-file-name)))
- (ediff-read-file-name "File B to compare"
- (setq dir-B
- (if ediff-use-last-dir
- ediff-last-dir-B
- (file-name-directory f)))
- (progn
- (setq file-name-history
- (cons (ediff-abbreviate-file-name
- (expand-file-name
- (file-name-nondirectory f)
- dir-B))
- file-name-history))
- f))
- )))
- (ediff-files-internal file-A
- (if (file-directory-p file-B)
- (expand-file-name
- (file-name-nondirectory file-A) file-B)
- file-B)
- nil ; file-C
- startup-hooks
- 'ediff-files))
-
-;;;###autoload
-(defun ediff-files3 (file-A file-B file-C &optional startup-hooks)
- "Run Ediff on three files, FILE-A, FILE-B, and FILE-C."
- (interactive
- (let ((dir-A (if ediff-use-last-dir
- ediff-last-dir-A
- default-directory))
- dir-B dir-C f ff)
- (list (setq f (ediff-read-file-name
- "File A to compare" dir-A
- (ediff-get-default-file-name)))
- (setq ff (ediff-read-file-name "File B to compare"
- (setq dir-B
- (if ediff-use-last-dir
- ediff-last-dir-B
- (file-name-directory f)))
- (progn
- (setq file-name-history
- (cons
- (ediff-abbreviate-file-name
- (expand-file-name
- (file-name-nondirectory f)
- dir-B))
- file-name-history))
- f)))
- (ediff-read-file-name "File C to compare"
- (setq dir-C (if ediff-use-last-dir
- ediff-last-dir-C
- (file-name-directory ff)))
- (progn
- (setq file-name-history
- (cons (ediff-abbreviate-file-name
- (expand-file-name
- (file-name-nondirectory ff)
- dir-C))
- file-name-history))
- ff))
- )))
- (ediff-files-internal file-A
- (if (file-directory-p file-B)
- (expand-file-name
- (file-name-nondirectory file-A) file-B)
- file-B)
- (if (file-directory-p file-C)
- (expand-file-name
- (file-name-nondirectory file-A) file-C)
- file-C)
- startup-hooks
- 'ediff-files3))
-
-;;;###autoload
-(defalias 'ediff3 'ediff-files3)
-
-
-;; Visit FILE and arrange its buffer to Ediff's liking.
-;; FILE is actually a variable symbol that must contain a true file name.
-;; BUFFER-NAME is a variable symbol, which will get the buffer object into
-;; which FILE is read.
-;; LAST-DIR is the directory variable symbol where FILE's
-;; directory name should be returned. HOOKS-VAR is a variable symbol that will
-;; be assigned the hook to be executed after `ediff-startup' is finished.
-;; `ediff-find-file' arranges that the temp files it might create will be
-;; deleted.
-(defun ediff-find-file (file-var buffer-name &optional last-dir hooks-var)
- (let* ((file (symbol-value file-var))
- (file-magic (find-file-name-handler file 'find-file-noselect))
- (temp-file-name-prefix (file-name-nondirectory file)))
- (cond ((not (file-readable-p file))
- (error "File `%s' does not exist or is not readable" file))
- ((file-directory-p file)
- (error "File `%s' is a directory" file)))
-
- ;; some of the commands, below, require full file name
- (setq file (expand-file-name file))
-
- ;; Record the directory of the file
- (if last-dir
- (set last-dir (expand-file-name (file-name-directory file))))
-
- ;; Setup the buffer
- (set buffer-name (find-file-noselect file))
-
- (ediff-eval-in-buffer (symbol-value buffer-name)
- (widen) ; Make sure the entire file is seen
- (cond (file-magic ;; file has handler, such as jka-compr-handler or
- ;; ange-ftp-hook-function--arrange for temp file
- (ediff-verify-file-buffer 'magic)
- (setq file
- (ediff-make-temp-file
- (current-buffer) temp-file-name-prefix))
- (set hooks-var (cons (` (lambda () (delete-file (, file))))
- (symbol-value hooks-var))))
- ;; file processed via auto-mode-alist, a la uncompress.el
- ((not (equal (file-truename file)
- (file-truename (buffer-file-name))))
- (setq file
- (ediff-make-temp-file
- (current-buffer) temp-file-name-prefix))
- (set hooks-var (cons (` (lambda () (delete-file (, file))))
- (symbol-value hooks-var))))
- (t ;; plain file---just check that the file matches the buffer
- (ediff-verify-file-buffer))))
- (set file-var file)))
-
-(defun ediff-files-internal (file-A file-B file-C startup-hooks job-name)
- (let (buf-A buf-B buf-C)
- (message "Reading file %s ... " file-A)
- ;;(sit-for 0)
- (ediff-find-file 'file-A 'buf-A 'ediff-last-dir-A 'startup-hooks)
- (message "Reading file %s ... " file-B)
- ;;(sit-for 0)
- (ediff-find-file 'file-B 'buf-B 'ediff-last-dir-B 'startup-hooks)
- (if (stringp file-C)
- (progn
- (message "Reading file %s ... " file-C)
- ;;(sit-for 0)
- (ediff-find-file
- 'file-C 'buf-C
- (if (eq job-name 'ediff-merge-files-with-ancestor)
- 'ediff-last-dir-ancestor 'ediff-last-dir-C)
- 'startup-hooks)))
- (ediff-setup buf-A file-A
- buf-B file-B
- buf-C file-C
- startup-hooks
- (list (cons 'ediff-job-name job-name)))))
-
-
-;;;###autoload
-(defalias 'ediff 'ediff-files)
-
-
-;;;###autoload
-(defun ediff-buffers (buffer-A buffer-B &optional startup-hooks job-name)
- "Run Ediff on a pair of buffers, BUFFER-A and BUFFER-B."
- (interactive
- (let (bf)
- (list (setq bf (read-buffer "Buffer A to compare: "
- (ediff-other-buffer "") t))
- (read-buffer "Buffer B to compare: "
- (progn
- ;; realign buffers so that two visible bufs will be
- ;; at the top
- (save-window-excursion (other-window 1))
- (ediff-other-buffer bf))
- t))))
- (or job-name (setq job-name 'ediff-buffers))
- (ediff-buffers-internal buffer-A buffer-B nil startup-hooks job-name))
-
-;;;###autoload
-(defalias 'ebuffers 'ediff-buffers)
-
-
-;;;###autoload
-(defun ediff-buffers3 (buffer-A buffer-B buffer-C
- &optional startup-hooks job-name)
- "Run Ediff on three buffers, BUFFER-A, BUFFER-B, and BUFFER-C."
- (interactive
- (let (bf bff)
- (list (setq bf (read-buffer "Buffer A to compare: "
- (ediff-other-buffer "") t))
- (setq bff (read-buffer "Buffer B to compare: "
- (progn
- ;; realign buffers so that two visible
- ;; bufs will be at the top
- (save-window-excursion (other-window 1))
- (ediff-other-buffer bf))
- t))
- (read-buffer "Buffer C to compare: "
- (progn
- ;; realign buffers so that three visible
- ;; bufs will be at the top
- (save-window-excursion (other-window 1))
- (ediff-other-buffer (list bf bff)))
- t)
- )))
- (or job-name (setq job-name 'ediff-buffers3))
- (ediff-buffers-internal buffer-A buffer-B buffer-C startup-hooks job-name))
-
-;;;###autoload
-(defalias 'ebuffers3 'ediff-buffers3)
-
-
-
-(defun ediff-buffers-internal (buf-A buf-B buf-C startup-hooks job-name)
- (let* ((buf-A-file-name (buffer-file-name (get-buffer buf-A)))
- (buf-B-file-name (buffer-file-name (get-buffer buf-B)))
- (buf-C-is-alive (ediff-buffer-live-p buf-C))
- (buf-C-file-name (if buf-C-is-alive
- (buffer-file-name (get-buffer buf-B))))
- file-A file-B file-C)
- (if (not (ediff-buffer-live-p buf-A))
- (error "Buffer %S doesn't exist" buf-A))
- (if (not (ediff-buffer-live-p buf-B))
- (error "Buffer %S doesn't exist" buf-B))
- (let ((ediff-job-name job-name))
- (if (and ediff-3way-comparison-job
- (not buf-C-is-alive))
- (error "Buffer %S doesn't exist" buf-C)))
- (if (stringp buf-A-file-name)
- (setq buf-A-file-name (file-name-nondirectory buf-A-file-name)))
- (if (stringp buf-B-file-name)
- (setq buf-B-file-name (file-name-nondirectory buf-B-file-name)))
- (if (stringp buf-C-file-name)
- (setq buf-C-file-name (file-name-nondirectory buf-C-file-name)))
-
- (setq file-A (ediff-make-temp-file buf-A buf-A-file-name)
- file-B (ediff-make-temp-file buf-B buf-B-file-name))
- (if buf-C-is-alive
- (setq file-C (ediff-make-temp-file buf-C buf-C-file-name)))
-
- (ediff-setup (get-buffer buf-A) file-A
- (get-buffer buf-B) file-B
- (if buf-C-is-alive (get-buffer buf-C))
- file-C
- (cons (` (lambda ()
- (delete-file (, file-A))
- (delete-file (, file-B))
- (if (stringp (, file-C)) (delete-file (, file-C)))
- ))
- startup-hooks)
- (list (cons 'ediff-job-name job-name))
- )))
-
-
-;;; Directory and file group operations
-
-;; Get appropriate default name for directory:
-;; If ediff-use-last-dir, use ediff-last-dir-A.
-;; In dired mode, use the directory that is under the point (if any);
-;; otherwise, use default-directory
-(defun ediff-get-default-directory-name ()
- (cond (ediff-use-last-dir ediff-last-dir-A)
- ((eq major-mode 'dired-mode)
- (let ((f (dired-get-filename nil 'noerror)))
- (if (and (stringp f) (file-directory-p f))
- f
- default-directory)))
- (t default-directory)))
-
-
-;;;###autoload
-(defun ediff-directories (dir1 dir2 regexp)
- "Run Ediff on a pair of directories, DIR1 and DIR2, comparing files that have
-the same name in both. The third argument, REGEXP, is a regular expression that
-can be used to filter out certain file names."
- (interactive
- (let ((dir-A (ediff-get-default-directory-name))
- f)
- (list (setq f (ediff-read-file-name "Directory A to compare:" dir-A nil))
- (ediff-read-file-name "Directory B to compare:"
- (if ediff-use-last-dir
- ediff-last-dir-B
- (ediff-strip-last-dir f))
- nil)
- (read-string "Filter through regular expression: "
- nil 'ediff-filtering-regexp-history)
- )))
- (ediff-directories-internal
- dir1 dir2 nil regexp 'ediff-files 'ediff-directories
- ))
-
-;;;###autoload
-(defalias 'edirs 'ediff-directories)
-
-
-;;;###autoload
-(defun ediff-directory-revisions (dir1 regexp)
- "Run Ediff on a directory, DIR1, comparing its files with their revisions.
-The second argument, REGEXP, is a regular expression that filters the file
-names. Only the files that are under revision control are taken into account."
- (interactive
- (let ((dir-A (ediff-get-default-directory-name)))
- (list (ediff-read-file-name
- "Directory to compare with revision:" dir-A nil)
- (read-string "Filter through regular expression: "
- nil 'ediff-filtering-regexp-history)
- )))
- (ediff-directory-revisions-internal
- dir1 regexp 'ediff-revision 'ediff-directory-revisions
- ))
-
-;;;###autoload
-(defalias 'edir-revisions 'ediff-directory-revisions)
-
-
-;;;###autoload
-(defun ediff-directories3 (dir1 dir2 dir3 regexp)
- "Run Ediff on three directories, DIR1, DIR2, and DIR3, comparing files that
-have the same name in all three. The last argument, REGEXP, is a regular
-expression that can be used to filter out certain file names."
- (interactive
- (let ((dir-A (ediff-get-default-directory-name))
- f)
- (list (setq f (ediff-read-file-name "Directory A to compare:" dir-A nil))
- (setq f (ediff-read-file-name "Directory B to compare:"
- (if ediff-use-last-dir
- ediff-last-dir-B
- (ediff-strip-last-dir f))
- nil))
- (ediff-read-file-name "Directory C to compare:"
- (if ediff-use-last-dir
- ediff-last-dir-C
- (ediff-strip-last-dir f))
- nil)
- (read-string "Filter through regular expression: "
- nil 'ediff-filtering-regexp-history)
- )))
- (ediff-directories-internal
- dir1 dir2 dir3 regexp 'ediff-files3 'ediff-directories3
- ))
-
-;;;###autoload
-(defalias 'edirs3 'ediff-directories3)
-
-;;;###autoload
-(defun ediff-merge-directories (dir1 dir2 regexp)
- "Run Ediff on a pair of directories, DIR1 and DIR2, merging files that have
-the same name in both. The third argument, REGEXP, is a regular expression that
-can be used to filter out certain file names."
- (interactive
- (let ((dir-A (ediff-get-default-directory-name))
- f)
- (list (setq f (ediff-read-file-name "Directory A to merge:" dir-A nil))
- (ediff-read-file-name "Directory B to merge:"
- (if ediff-use-last-dir
- ediff-last-dir-B
- (ediff-strip-last-dir f))
- nil)
- (read-string "Filter through regular expression: "
- nil 'ediff-filtering-regexp-history)
- )))
- (ediff-directories-internal
- dir1 dir2 nil regexp 'ediff-merge-files 'ediff-merge-directories
- ))
-
-;;;###autoload
-(defalias 'edirs-merge 'ediff-merge-directories)
-
-;;;###autoload
-(defun ediff-merge-directories-with-ancestor (dir1 dir2 ancestor-dir regexp)
- "Merge files in directories DIR1 and DIR2 using files in ANCESTOR-DIR as ancestors.
-Ediff merges files that have identical names in DIR1, DIR2. If a pair of files
-in DIR1 and DIR2 doesn't have an ancestor in ANCESTOR-DIR, Ediff will merge
-without ancestor. The fourth argument, REGEXP, is a regular expression that
-can be used to filter out certain file names."
- (interactive
- (let ((dir-A (ediff-get-default-directory-name))
- f)
- (list (setq f (ediff-read-file-name "Directory A to merge:" dir-A nil))
- (setq f (ediff-read-file-name "Directory B to merge:"
- (if ediff-use-last-dir
- ediff-last-dir-B
- (ediff-strip-last-dir f))
- nil))
- (ediff-read-file-name "Ancestor directory:"
- (if ediff-use-last-dir
- ediff-last-dir-C
- (ediff-strip-last-dir f))
- nil)
- (read-string "Filter through regular expression: "
- nil 'ediff-filtering-regexp-history)
- )))
- (ediff-directories-internal
- dir1 dir2 ancestor-dir regexp
- 'ediff-merge-files-with-ancestor 'ediff-merge-directories-with-ancestor
- ))
-
-;;;###autoload
-(defun ediff-merge-directory-revisions (dir1 regexp)
- "Run Ediff on a directory, DIR1, merging its files with their revisions.
-The second argument, REGEXP, is a regular expression that filters the file
-names. Only the files that are under revision control are taken into account."
- (interactive
- (let ((dir-A (ediff-get-default-directory-name)))
- (list (ediff-read-file-name
- "Directory to merge with revisions:" dir-A nil)
- (read-string "Filter through regular expression: "
- nil 'ediff-filtering-regexp-history)
- )))
- (ediff-directory-revisions-internal
- dir1 regexp 'ediff-merge-revisions 'ediff-merge-directory-revisions
- ))
-
-;;;###autoload
-(defalias 'edir-merge-revisions 'ediff-merge-directory-revisions)
-
-;;;###autoload
-(defun ediff-merge-directory-revisions-with-ancestor (dir1 regexp)
- "Run Ediff on a directory, DIR1, merging its files with their revisions and ancestors.
-The second argument, REGEXP, is a regular expression that filters the file
-names. Only the files that are under revision control are taken into account."
- (interactive
- (let ((dir-A (ediff-get-default-directory-name)))
- (list (ediff-read-file-name
- "Directory to merge with revisions and ancestors:" dir-A nil)
- (read-string "Filter through regular expression: "
- nil 'ediff-filtering-regexp-history)
- )))
- (ediff-directory-revisions-internal
- dir1 regexp 'ediff-merge-revisions-with-ancestor
- 'ediff-merge-directory-revisions-with-ancestor
- ))
-
-;;;###autoload
-(defalias
- 'edir-merge-revisions-with-ancestor
- 'ediff-merge-directory-revisions-with-ancestor)
-
-;;;###autoload
-(defalias 'edirs-merge-with-ancestor 'ediff-merge-directories-with-ancestor)
-
-;; Run ediff-action (ediff-files, ediff-merge, ediff-merge-with-ancestors)
-;; on a pair of directories (three directories, in case of ancestor).
-;; The third argument, REGEXP, is a regular expression that can be used to
-;; filter out certain file names.
-;; JOBNAME is the symbol indicating the meta-job to be performed.
-;; MERGE-DIR is the directory in which to store merged files.
-(defun ediff-directories-internal (dir1 dir2 dir3 regexp action jobname
- &optional startup-hooks)
- ;; ediff-read-file-name is set to attach a previously entered file name if
- ;; the currently entered file is a directory. This code takes care of that.
- (setq dir1 (if (file-directory-p dir1) dir1 (file-name-directory dir1))
- dir2 (if (file-directory-p dir2) dir2 (file-name-directory dir2)))
-
- (if (stringp dir3)
- (setq dir3 (if (file-directory-p dir3) dir3 (file-name-directory dir3))))
-
- (cond ((string= dir1 dir2)
- (error "Directories A and B are the same: %s" dir1))
- ((and (eq jobname 'ediff-directories3)
- (string= dir1 dir3))
- (error "Directories A and C are the same: %s" dir1))
- ((and (eq jobname 'ediff-directories3)
- (string= dir2 dir3))
- (error "Directories B and C are the same: %s" dir1)))
-
- (let (diffs ; var where ediff-intersect-directories returns the diff list
- merge-autostore-dir
- file-list meta-buf)
- (if (and ediff-autostore-merges (ediff-merge-metajob jobname))
- (setq merge-autostore-dir
- (ediff-read-file-name "Directory to save merged files:"
- (if ediff-use-last-dir
- ediff-last-merge-autostore-dir
- (ediff-strip-last-dir dir1))
- nil)))
- ;; verify we are not merging into an orig directory
- (if (stringp merge-autostore-dir)
- (cond ((and (stringp dir1) (string= merge-autostore-dir dir1))
- (or (y-or-n-p "Merge directory same as directory A, sure? ")
- (error "Directory merge aborted")))
- ((and (stringp dir2) (string= merge-autostore-dir dir2))
- (or (y-or-n-p "Merge directory same as directory B, sure? ")
- (error "Directory merge aborted")))
- ((and (stringp dir3) (string= merge-autostore-dir dir3))
- (or (y-or-n-p
- "Merge directory same as ancestor directory, sure? ")
- (error "Directory merge aborted")))))
-
- (setq file-list (ediff-intersect-directories
- jobname 'diffs
- regexp dir1 dir2 dir3 merge-autostore-dir))
- (setq startup-hooks
- ;; this sets various vars in the meta buffer inside
- ;; ediff-prepare-meta-buffer
- (cons (` (lambda ()
- ;; tell what to do if the user clicks on a session record
- (setq ediff-session-action-function (quote (, action)))
- ;; set ediff-dir-difference-list
- (setq ediff-dir-difference-list (quote (, diffs)))))
- startup-hooks))
- (setq meta-buf (ediff-prepare-meta-buffer
- 'ediff-filegroup-action
- file-list
- "*Ediff Session Group Panel"
- 'ediff-redraw-directory-group-buffer
- jobname
- startup-hooks))
- (ediff-show-meta-buffer meta-buf)
- ))
-
-(defun ediff-directory-revisions-internal (dir1 regexp action jobname
- &optional startup-hooks)
- (setq dir1 (if (file-directory-p dir1) dir1 (file-name-directory dir1)))
-
- (let (file-list meta-buf merge-autostore-dir)
- (if (and ediff-autostore-merges (ediff-merge-metajob jobname))
- (setq merge-autostore-dir
- (ediff-read-file-name "Directory to save merged files:"
- (if ediff-use-last-dir
- ediff-last-merge-autostore-dir
- (ediff-strip-last-dir dir1))
- nil)))
- ;; verify merge-autostore-dir != dir1
- (if (and (stringp merge-autostore-dir)
- (stringp dir1)
- (string= merge-autostore-dir dir1))
- (or (y-or-n-p
- "Directory for saving merges is the same as directory A. Sure? ")
- (error "Merge of directory revisions aborted")))
-
- (setq file-list
- (ediff-get-directory-files-under-revision
- jobname regexp dir1 merge-autostore-dir))
- (setq startup-hooks
- ;; this sets various vars in the meta buffer inside
- ;; ediff-prepare-meta-buffer
- (cons (` (lambda ()
- ;; tell what to do if the user clicks on a session record
- (setq ediff-session-action-function (quote (, action)))
- ))
- startup-hooks))
- (setq meta-buf (ediff-prepare-meta-buffer
- 'ediff-filegroup-action
- file-list
- "*Ediff Session Group Panel"
- 'ediff-redraw-directory-group-buffer
- jobname
- startup-hooks))
- (ediff-show-meta-buffer meta-buf)
- ))
-
-
-;;; Compare regions and windows
-
-;;;###autoload
-(defun ediff-windows-wordwise (dumb-mode &optional wind-A wind-B startup-hooks)
- "Compare WIND-A and WIND-B, which are selected by clicking, wordwise.
-With prefix argument, DUMB-MODE, or on a non-windowing display, works as
-follows:
-If WIND-A is nil, use selected window.
-If WIND-B is nil, use window next to WIND-A."
- (interactive "P")
- (ediff-windows dumb-mode wind-A wind-B
- startup-hooks 'ediff-windows-wordwise 'word-mode))
-
-;;;###autoload
-(defun ediff-windows-linewise (dumb-mode &optional wind-A wind-B startup-hooks)
- "Compare WIND-A and WIND-B, which are selected by clicking, linewise.
-With prefix argument, DUMB-MODE, or on a non-windowing display, works as
-follows:
-If WIND-A is nil, use selected window.
-If WIND-B is nil, use window next to WIND-A."
- (interactive "P")
- (ediff-windows dumb-mode wind-A wind-B
- startup-hooks 'ediff-windows-linewise nil))
-
-;; Compare WIND-A and WIND-B, which are selected by clicking.
-;; With prefix argument, DUMB-MODE, or on a non-windowing display,
-;; works as follows:
-;; If WIND-A is nil, use selected window.
-;; If WIND-B is nil, use window next to WIND-A.
-(defun ediff-windows (dumb-mode wind-A wind-B startup-hooks job-name word-mode)
- (if (or dumb-mode (not (ediff-window-display-p)))
- (setq wind-A (ediff-get-next-window wind-A nil)
- wind-B (ediff-get-next-window wind-B wind-A))
- (setq wind-A (ediff-get-window-by-clicking wind-A nil 1)
- wind-B (ediff-get-window-by-clicking wind-B wind-A 2)))
-
- (let ((buffer-A (window-buffer wind-A))
- (buffer-B (window-buffer wind-B))
- beg-A end-A beg-B end-B)
-
- (save-excursion
- (save-window-excursion
- (sit-for 0) ; sync before using window-start/end -- a precaution
- (select-window wind-A)
- (setq beg-A (window-start)
- end-A (window-end))
- (select-window wind-B)
- (setq beg-B (window-start)
- end-B (window-end))))
- (ediff-regions-internal
- buffer-A beg-A end-A buffer-B beg-B end-B
- startup-hooks job-name word-mode)))
-
-;;;###autoload
-(defun ediff-regions-wordwise (buffer-A buffer-B &optional startup-hooks)
- "Run Ediff on a pair of regions in two different buffers.
-Regions \(i.e., point and mark\) are assumed to be set in advance.
-This function is effective only for relatively small regions, up to 200
-lines. For large regions, use `ediff-regions-linewise'."
- (interactive
- (let (bf)
- (list (setq bf (read-buffer "Region's A buffer: "
- (ediff-other-buffer "") t))
- (read-buffer "Region's B buffer: "
- (progn
- ;; realign buffers so that two visible bufs will be
- ;; at the top
- (save-window-excursion (other-window 1))
- (ediff-other-buffer bf))
- t))))
- (if (not (ediff-buffer-live-p buffer-A))
- (error "Buffer %S doesn't exist" buffer-A))
- (if (not (ediff-buffer-live-p buffer-B))
- (error "Buffer %S doesn't exist" buffer-B))
-
-
- (let (reg-A-beg reg-A-end reg-B-beg reg-B-end)
- (save-excursion
- (set-buffer buffer-A)
- (setq reg-A-beg (region-beginning)
- reg-A-end (region-end))
- (set-buffer buffer-B)
- (setq reg-B-beg (region-beginning)
- reg-B-end (region-end)))
-
- (ediff-regions-internal
- (get-buffer buffer-A) reg-A-beg reg-A-end
- (get-buffer buffer-B) reg-B-beg reg-B-end
- startup-hooks 'ediff-regions-wordwise 'word-mode)))
-
-;;;###autoload
-(defun ediff-regions-linewise (buffer-A buffer-B &optional startup-hooks)
- "Run Ediff on a pair of regions in two different buffers.
-Regions \(i.e., point and mark\) are assumed to be set in advance.
-Each region is enlarged to contain full lines.
-This function is effective for large regions, over 100-200
-lines. For small regions, use `ediff-regions-wordwise'."
- (interactive
- (let (bf)
- (list (setq bf (read-buffer "Region A's buffer: "
- (ediff-other-buffer "") t))
- (read-buffer "Region B's buffer: "
- (progn
- ;; realign buffers so that two visible bufs will be
- ;; at the top
- (save-window-excursion (other-window 1))
- (ediff-other-buffer bf))
- t))))
- (if (not (ediff-buffer-live-p buffer-A))
- (error "Buffer %S doesn't exist" buffer-A))
- (if (not (ediff-buffer-live-p buffer-B))
- (error "Buffer %S doesn't exist" buffer-B))
-
- (let (reg-A-beg reg-A-end reg-B-beg reg-B-end)
- (save-excursion
- (set-buffer buffer-A)
- (setq reg-A-beg (region-beginning)
- reg-A-end (region-end))
- ;; enlarge the region to hold full lines
- (goto-char reg-A-beg)
- (beginning-of-line)
- (setq reg-A-beg (point))
- (goto-char reg-A-end)
- (end-of-line)
- (or (eobp) (forward-char)) ; include the newline char
- (setq reg-A-end (point))
-
- (set-buffer buffer-B)
- (setq reg-B-beg (region-beginning)
- reg-B-end (region-end))
- ;; enlarge the region to hold full lines
- (goto-char reg-B-beg)
- (beginning-of-line)
- (setq reg-B-beg (point))
- (goto-char reg-B-end)
- (end-of-line)
- (or (eobp) (forward-char)) ; include the newline char
- (setq reg-B-end (point))
- ) ; save excursion
-
- (ediff-regions-internal
- (get-buffer buffer-A) reg-A-beg reg-A-end
- (get-buffer buffer-B) reg-B-beg reg-B-end
- startup-hooks 'ediff-regions-linewise nil))) ; no word mode
-
-;; compare region beg-A to end-A of buffer-A
-;; to regions beg-B -- end-B in buffer-B.
-(defun ediff-regions-internal (buffer-A beg-A end-A buffer-B beg-B end-B
- startup-hooks job-name word-mode)
- (let ((tmp-buffer (get-buffer-create ediff-tmp-buffer))
- overl-A overl-B
- file-A file-B)
-
- ;; in case beg/end-A/B aren't markers--make them into markers
- (ediff-eval-in-buffer buffer-A
- (setq beg-A (move-marker (make-marker) beg-A)
- end-A (move-marker (make-marker) end-A)))
- (ediff-eval-in-buffer buffer-B
- (setq beg-B (move-marker (make-marker) beg-B)
- end-B (move-marker (make-marker) end-B)))
-
- (if (and (eq buffer-A buffer-B)
- (or (and (< beg-A end-B) (<= beg-B beg-A)) ; b-B b-A e-B
- (and (< beg-B end-A) (<= end-A end-B)))) ; b-B e-A e-B
- (progn
- (with-output-to-temp-buffer ediff-msg-buffer
- (princ "
-You have requested to compare overlapping regions of the same buffer.
-
-In this case, Ediff's highlighting may be confusing---in the same window,
-you may see highlighted regions that belong to different regions.
-
-Continue anyway? (y/n) "))
-
- (if (y-or-n-p "Continue anyway? ")
- ()
- (error "%S aborted" job-name))))
-
- ;; make file-A
- (if word-mode
- (ediff-wordify beg-A end-A buffer-A tmp-buffer)
- (ediff-copy-to-buffer beg-A end-A buffer-A tmp-buffer))
- (setq file-A (ediff-make-temp-file tmp-buffer "regA"))
-
- ;; make file-B
- (if word-mode
- (ediff-wordify beg-B end-B buffer-B tmp-buffer)
- (ediff-copy-to-buffer beg-B end-B buffer-B tmp-buffer))
- (setq file-B (ediff-make-temp-file tmp-buffer "regB"))
-
- (setq overl-A (ediff-make-bullet-proof-overlay beg-A end-A buffer-A))
- (setq overl-B (ediff-make-bullet-proof-overlay beg-B end-B buffer-B))
- (ediff-setup buffer-A file-A
- buffer-B file-B
- nil nil ; buffer & file C
- (cons (` (lambda ()
- (delete-file (, file-A))
- (delete-file (, file-B))))
- startup-hooks)
- (list (cons 'ediff-word-mode word-mode)
- (cons 'ediff-narrow-bounds (list overl-A overl-B))
- (cons 'ediff-job-name job-name))
- )
- ))
-
-
-;;; Merge files and buffers
-
-;;;###autoload
-(defalias 'ediff-merge 'ediff-merge-files)
-
-(defsubst ediff-merge-on-startup ()
- (ediff-do-merge 0)
- (ediff-eval-in-buffer ediff-buffer-C
- (set-buffer-modified-p nil)))
-
-;;;###autoload
-(defun ediff-merge-files (file-A file-B &optional startup-hooks)
- "Merge two files without ancestor."
- (interactive
- (let ((dir-A (if ediff-use-last-dir
- ediff-last-dir-A
- default-directory))
- dir-B f)
- (list (setq f (ediff-read-file-name
- "File A to merge" dir-A
- (ediff-get-default-file-name)))
- (ediff-read-file-name "File B to merge"
- (setq dir-B
- (if ediff-use-last-dir
- ediff-last-dir-B
- (file-name-directory f)))
- (progn
- (setq file-name-history
- (cons (ediff-abbreviate-file-name
- (expand-file-name
- (file-name-nondirectory f)
- dir-B))
- file-name-history))
- f))
- )))
- (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
- (ediff-files-internal file-A
- (if (file-directory-p file-B)
- (expand-file-name
- (file-name-nondirectory file-A) file-B)
- file-B)
- nil ; file-C
- startup-hooks
- 'ediff-merge-files))
-
-;;;###autoload
-(defun ediff-merge-files-with-ancestor (file-A file-B file-ancestor
- &optional startup-hooks)
- "Merge two files with ancestor."
- (interactive
- (let ((dir-A (if ediff-use-last-dir
- ediff-last-dir-A
- default-directory))
- dir-B dir-ancestor f ff)
- (list (setq f (ediff-read-file-name
- "File A to merge" dir-A
- (ediff-get-default-file-name)))
- (setq ff (ediff-read-file-name "File B to merge"
- (setq dir-B
- (if ediff-use-last-dir
- ediff-last-dir-B
- (file-name-directory f)))
- (progn
- (setq file-name-history
- (cons
- (ediff-abbreviate-file-name
- (expand-file-name
- (file-name-nondirectory f)
- dir-B))
- file-name-history))
- f)))
- (ediff-read-file-name "Ancestor file"
- (setq dir-ancestor
- (if ediff-use-last-dir
- ediff-last-dir-ancestor
- (file-name-directory ff)))
- (progn
- (setq file-name-history
- (cons (ediff-abbreviate-file-name
- (expand-file-name
- (file-name-nondirectory ff)
- dir-ancestor))
- file-name-history))
- ff))
- )))
- (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
- (ediff-files-internal file-A
- (if (file-directory-p file-B)
- (expand-file-name
- (file-name-nondirectory file-A) file-B)
- file-B)
- file-ancestor
- startup-hooks
- 'ediff-merge-files-with-ancestor))
-
-;;;###autoload
-(defalias 'ediff-merge-with-ancestor 'ediff-merge-files-with-ancestor)
-
-;;;###autoload
-(defun ediff-merge-buffers (buffer-A buffer-B &optional startup-hooks job-name)
- "Merge buffers without ancestor."
- (interactive
- (let (bf)
- (list (setq bf (read-buffer "Buffer A to merge: "
- (ediff-other-buffer "") t))
- (read-buffer "Buffer B to merge: "
- (progn
- ;; realign buffers so that two visible bufs will be
- ;; at the top
- (save-window-excursion (other-window 1))
- (ediff-other-buffer bf))
- t))))
-
- (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
- (or job-name (setq job-name 'ediff-merge-buffers))
- (ediff-buffers-internal
- buffer-A buffer-B nil startup-hooks job-name))
-
-;;;###autoload
-(defun ediff-merge-buffers-with-ancestor (buffer-A
- buffer-B buffer-ancestor
- &optional startup-hooks job-name)
- "Merge buffers with ancestor."
- (interactive
- (let (bf bff)
- (list (setq bf (read-buffer "Buffer A to merge: "
- (ediff-other-buffer "") t))
- (setq bff (read-buffer "Buffer B to merge: "
- (progn
- ;; realign buffers so that two visible
- ;; bufs will be at the top
- (save-window-excursion (other-window 1))
- (ediff-other-buffer bf))
- t))
- (read-buffer "Ancestor buffer: "
- (progn
- ;; realign buffers so that three visible
- ;; bufs will be at the top
- (save-window-excursion (other-window 1))
- (ediff-other-buffer (list bf bff)))
- t)
- )))
-
- (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
- (or job-name (setq job-name 'ediff-merge-buffers-with-ancestor))
- (ediff-buffers-internal
- buffer-A buffer-B buffer-ancestor startup-hooks job-name))
-
-
-;;;###autoload
-(defun ediff-merge-revisions (&optional file startup-hooks)
- "Run Ediff by merging two revisions of a file.
-The file is the optional FILE argument or the file visited by the current
-buffer."
- (interactive)
- (if (stringp file) (find-file file))
- (let (rev1 rev2)
- (setq rev1
- (read-string
- (format
- "Version 1 to merge (default: %s's latest version): "
- (if (stringp file)
- (file-name-nondirectory file) "current buffer")))
- rev2
- (read-string
- (format
- "Version 2 to merge (default: %s): "
- (if (stringp file)
- (file-name-nondirectory file) "current buffer"))))
- (ediff-load-version-control)
- ;; ancestor-revision=nil
- (funcall
- (intern (format "ediff-%S-merge-internal" ediff-version-control-package))
- rev1 rev2 nil startup-hooks)))
-
-
-;;;###autoload
-(defun ediff-merge-revisions-with-ancestor (&optional file startup-hooks)
- "Run Ediff by merging two revisions of a file with a common ancestor.
-The file is the the optional FILE argument or the file visited by the current
-buffer."
- (interactive)
- (if (stringp file) (find-file file))
- (let (rev1 rev2 ancestor-rev)
- (setq rev1
- (read-string
- (format
- "Version 1 to merge (default: %s's latest version): "
- (if (stringp file)
- (file-name-nondirectory file) "current buffer")))
- rev2
- (read-string
- (format
- "Version 2 to merge (default: %s): "
- (if (stringp file)
- (file-name-nondirectory file) "current buffer")))
- ancestor-rev
- (read-string
- (format
- "Ancestor version (default: %s): "
- (if (stringp file)
- (file-name-nondirectory file) "current buffer"))))
- (ediff-load-version-control)
- (funcall
- (intern (format "ediff-%S-merge-internal" ediff-version-control-package))
- rev1 rev2 ancestor-rev startup-hooks)))
-
-;;;###autoload
-(defun run-ediff-from-cvs-buffer (pos)
- "Run Ediff-merge on appropriate revisions of the selected file.
-First run after `M-x cvs-update'. Then place the cursor on a lide describing a
-file and then run `run-ediff-from-cvs-buffer'."
- (interactive "d")
- (ediff-load-version-control)
- (let ((tin (tin-locate cvs-cookie-handle pos)))
- (if tin
- (cvs-run-ediff-on-file-descriptor tin)
- (error "There is no file to merge"))))
-
-
-;;; Apply patch
-
-;;;###autoload
-(defun ediff-patch-file ()
- "Run Ediff by patching SOURCE-FILENAME."
- ;; This now returns the control buffer
- (interactive)
- (let (source-dir source-file patch-buf)
- (require 'ediff-ptch)
- (setq patch-buf (ediff-get-patch-buffer))
- (setq source-dir (cond (ediff-use-last-dir ediff-last-dir-patch)
- ((and (not ediff-patch-default-directory)
- (buffer-file-name patch-buf))
- (file-name-directory
- (expand-file-name
- (buffer-file-name patch-buf))))
- (t default-directory)))
- (setq source-file
- ;; the default is the directory, not the visited file name
- (ediff-read-file-name "Which file to patch? " source-dir source-dir))
- (ediff-dispatch-file-patching-job patch-buf source-file)))
-
-;;;###autoload
-(defun ediff-patch-buffer ()
- "Run Ediff by patching BUFFER-NAME."
- (interactive)
- (let (patch-buf)
- (require 'ediff-ptch)
- (setq patch-buf (ediff-get-patch-buffer))
- (ediff-patch-buffer-internal
- patch-buf
- (read-buffer "Which buffer to patch? "
- (cond ((eq patch-buf (current-buffer))
- (window-buffer (other-window 1)))
- (t (current-buffer)))
- 'must-match))))
-
-;;;###autoload
-(defalias 'epatch 'ediff-patch-file)
-;;;###autoload
-(defalias 'epatch-buffer 'ediff-patch-buffer)
-
-
-
-
-;;; Versions Control functions
-
-;;;###autoload
-(defun ediff-revision (&optional file startup-hooks)
- "Run Ediff by comparing versions of a file.
-The file is an optional FILE argument or the file visited by the current
-buffer. Use `vc.el' or `rcs.el' depending on `ediff-version-control-package'."
- ;; if buffer is non-nil, use that buffer instead of the current buffer
- (interactive "P")
- (if (stringp file) (find-file file))
- (let (rev1 rev2)
- (setq rev1
- (read-string
- (format "Version 1 to compare (default: %s's latest version): "
- (if (stringp file)
- (file-name-nondirectory file) "current buffer")))
- rev2
- (read-string
- (format "Version 2 to compare (default: %s): "
- (if (stringp file)
- (file-name-nondirectory file) "current buffer"))))
- (ediff-load-version-control)
- (funcall
- (intern (format "ediff-%S-internal" ediff-version-control-package))
- rev1 rev2 startup-hooks)
- ))
-
-
-;; Test if version control package is loaded and load if not
-;; Is SILENT is non-nil, don't report error if package is not found.
-(defun ediff-load-version-control (&optional silent)
- (require 'ediff-vers)
- (or (featurep ediff-version-control-package)
- (if (locate-library (symbol-name ediff-version-control-package))
- (progn
- (message "") ; kill the message from `locate-library'
- (require ediff-version-control-package))
- (or silent
- (error "Version control package %S.el not found. Use vc.el instead"
- ediff-version-control-package)))))
-
-
-;;;###autoload
-(defun ediff-version ()
- "Return string describing the version of Ediff.
-When called interactively, displays the version."
- (interactive)
- (if (interactive-p)
- (message (ediff-version))
- (format "Ediff %s of %s" ediff-version ediff-date)))
-
-
-;;;###autoload
-(defun ediff-documentation (&optional node)
- "Display Ediff's manual.
-With optional NODE, goes to that node."
- (interactive)
- (let ((ctl-window ediff-control-window)
- (ctl-buf ediff-control-buffer))
-
- (ediff-skip-unsuitable-frames)
- (condition-case nil
- (progn
- (pop-to-buffer (get-buffer-create "*info*"))
- (info (if ediff-xemacs-p "ediff.info" "ediff"))
- (if node
- (Info-goto-node node)
- (message "Type `i' to search for a specific topic"))
- (raise-frame (selected-frame)))
- (error (beep 1)
- (with-output-to-temp-buffer ediff-msg-buffer
- (princ ediff-BAD-INFO))
- (if (window-live-p ctl-window)
- (progn
- (select-window ctl-window)
- (set-window-buffer ctl-window ctl-buf)))))))
-
-
-
-
-;;; Local Variables:
-;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
-;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
-;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
-;;; End:
-
-(provide 'ediff)
-(require 'ediff-util)
-
-;;; ediff.el ends here
diff --git a/lisp/edmacro.el b/lisp/edmacro.el
deleted file mode 100644
index 973ef680f80..00000000000
--- a/lisp/edmacro.el
+++ /dev/null
@@ -1,723 +0,0 @@
-;;; edmacro.el --- keyboard macro editor
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Dave Gillespie <daveg@synaptics.com>
-;; Maintainer: Dave Gillespie <daveg@synaptics.com>
-;; Version: 2.01
-;; Keywords: abbrev
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Usage:
-;;
-;; The `C-x C-k' (`edit-kbd-macro') command edits a keyboard macro
-;; in a special buffer. It prompts you to type a key sequence,
-;; which should be one of:
-;;
-;; * RET or `C-x e' (call-last-kbd-macro), to edit the most
-;; recently defined keyboard macro.
-;;
-;; * `M-x' followed by a command name, to edit a named command
-;; whose definition is a keyboard macro.
-;;
-;; * `C-h l' (view-lossage), to edit the 100 most recent keystrokes
-;; and install them as the "current" macro.
-;;
-;; * any key sequence whose definition is a keyboard macro.
-;;
-;; This file includes a version of `insert-kbd-macro' that uses the
-;; more readable format defined by these routines.
-;;
-;; Also, the `read-kbd-macro' command parses the region as
-;; a keyboard macro, and installs it as the "current" macro.
-;; This and `format-kbd-macro' can also be called directly as
-;; Lisp functions.
-
-;; Type `C-h m', or see the documentation for `edmacro-mode' below,
-;; for information about the format of written keyboard macros.
-
-;; `edit-kbd-macro' formats the macro with one command per line,
-;; including the command names as comments on the right. If the
-;; formatter gets confused about which keymap was used for the
-;; characters, the command-name comments will be wrong but that
-;; won't hurt anything.
-
-;; With a prefix argument, `edit-kbd-macro' will format the
-;; macro in a more concise way that omits the comments.
-
-;; This package requires GNU Emacs 19 or later, and daveg's CL
-;; package 2.02 or later. (CL 2.02 comes standard starting with
-;; Emacs 19.18.) This package does not work with Emacs 18 or
-;; Lucid Emacs.
-
-;;; Code:
-
-(eval-when-compile
- (require 'cl))
-
-;;; The user-level commands for editing macros.
-
-;;;###autoload (define-key ctl-x-map "\C-k" 'edit-kbd-macro)
-
-;;;###autoload
-(defvar edmacro-eight-bits nil
- "*Non-nil if edit-kbd-macro should leave 8-bit characters intact.
-Default nil means to write characters above \\177 in octal notation.")
-
-(defvar edmacro-mode-map nil)
-(unless edmacro-mode-map
- (setq edmacro-mode-map (make-sparse-keymap))
- (define-key edmacro-mode-map "\C-c\C-c" 'edmacro-finish-edit)
- (define-key edmacro-mode-map "\C-c\C-q" 'edmacro-insert-key))
-
-(defvar edmacro-store-hook)
-(defvar edmacro-finish-hook)
-(defvar edmacro-original-buffer)
-
-;;;###autoload
-(defun edit-kbd-macro (keys &optional prefix finish-hook store-hook)
- "Edit a keyboard macro.
-At the prompt, type any key sequence which is bound to a keyboard macro.
-Or, type `C-x e' or RET to edit the last keyboard macro, `C-h l' to edit
-the last 100 keystrokes as a keyboard macro, or `M-x' to edit a macro by
-its command name.
-With a prefix argument, format the macro in a more concise way."
- (interactive "kKeyboard macro to edit (C-x e, M-x, C-h l, or keys): \nP")
- (when keys
- (let ((cmd (if (arrayp keys) (key-binding keys) keys))
- (mac nil))
- (cond (store-hook
- (setq mac keys)
- (setq cmd nil))
- ((or (eq cmd 'call-last-kbd-macro)
- (member keys '("\r" [return])))
- (or last-kbd-macro
- (y-or-n-p "No keyboard macro defined. Create one? ")
- (keyboard-quit))
- (setq mac (or last-kbd-macro ""))
- (setq cmd 'last-kbd-macro))
- ((eq cmd 'execute-extended-command)
- (setq cmd (read-command "Name of keyboard macro to edit: "))
- (if (string-equal cmd "")
- (error "No command name given"))
- (setq mac (symbol-function cmd)))
- ((eq cmd 'view-lossage)
- (setq mac (recent-keys))
- (setq cmd 'last-kbd-macro))
- ((null cmd)
- (error "Key sequence %s is not defined" (key-description keys)))
- ((symbolp cmd)
- (setq mac (symbol-function cmd)))
- (t
- (setq mac cmd)
- (setq cmd nil)))
- (unless (arrayp mac)
- (error "Key sequence %s is not a keyboard macro"
- (key-description keys)))
- (message "Formatting keyboard macro...")
- (let* ((oldbuf (current-buffer))
- (mmac (edmacro-fix-menu-commands mac))
- (fmt (edmacro-format-keys mmac 1))
- (fmtv (edmacro-format-keys mmac (not prefix)))
- (buf (get-buffer-create "*Edit Macro*")))
- (message "Formatting keyboard macro...done")
- (switch-to-buffer buf)
- (kill-all-local-variables)
- (use-local-map edmacro-mode-map)
- (setq buffer-read-only nil)
- (setq major-mode 'edmacro-mode)
- (setq mode-name "Edit Macro")
- (set (make-local-variable 'edmacro-original-buffer) oldbuf)
- (set (make-local-variable 'edmacro-finish-hook) finish-hook)
- (set (make-local-variable 'edmacro-store-hook) store-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: " fmt "\n")
- (unless store-hook
- (insert "\nCommand: " (if cmd (symbol-name cmd) "none") "\n")
- (let ((keys (where-is-internal (or cmd mac) '(keymap))))
- (if keys
- (while keys
- (insert "Key: " (edmacro-format-keys (pop keys) 1) "\n"))
- (insert "Key: none\n"))))
- (insert "\nMacro:\n\n")
- (save-excursion
- (insert fmtv "\n"))
- (recenter '(4))
- (when (eq mac mmac)
- (set-buffer-modified-p nil))
- (run-hooks 'edmacro-format-hook)))))
-
-;;; The next two commands are provided for convenience and backward
-;;; compatibility.
-
-;;;###autoload
-(defun edit-last-kbd-macro (&optional prefix)
- "Edit the most recently defined keyboard macro."
- (interactive "P")
- (edit-kbd-macro 'call-last-kbd-macro prefix))
-
-;;;###autoload
-(defun edit-named-kbd-macro (&optional prefix)
- "Edit a keyboard macro which has been given a name by `name-last-kbd-macro'."
- (interactive "P")
- (edit-kbd-macro 'execute-extended-command prefix))
-
-;;;###autoload
-(defun read-kbd-macro (start &optional end)
- "Read the region as a keyboard macro definition.
-The region is interpreted as spelled-out keystrokes, e.g., \"M-x abc RET\".
-See documentation for `edmacro-mode' for details.
-Leading/trailing \"C-x (\" and \"C-x )\" in the text are allowed and ignored.
-The resulting macro is installed as the \"current\" keyboard macro.
-
-In Lisp, may also be called with a single STRING argument in which case
-the result is returned rather than being installed as the current macro.
-The result will be a string if possible, otherwise an event vector.
-Second argument NEED-VECTOR means to return an event vector always."
- (interactive "r")
- (if (stringp start)
- (edmacro-parse-keys start end)
- (setq last-kbd-macro (edmacro-parse-keys (buffer-substring start end)))))
-
-;;;###autoload
-(defun format-kbd-macro (&optional macro verbose)
- "Return the keyboard macro MACRO as a human-readable string.
-This string is suitable for passing to `read-kbd-macro'.
-Second argument VERBOSE means to put one command per line with comments.
-If VERBOSE is `1', put everything on one line. If VERBOSE is omitted
-or nil, use a compact 80-column format."
- (and macro (symbolp macro) (setq macro (symbol-function macro)))
- (edmacro-format-keys (or macro last-kbd-macro) verbose))
-
-;;; Commands for *Edit Macro* buffer.
-
-(defun edmacro-finish-edit ()
- (interactive)
- (unless (eq major-mode 'edmacro-mode)
- (error
- "This command is valid only in buffers created by `edit-kbd-macro'"))
- (run-hooks 'edmacro-finish-hook)
- (let ((cmd nil) (keys nil) (no-keys nil)
- (top (point-min)))
- (goto-char top)
- (let ((case-fold-search nil))
- (while (cond ((looking-at "[ \t]*\\($\\|;;\\|REM[ \t\n]\\)")
- t)
- ((looking-at "Command:[ \t]*\\([^ \t\n]*\\)[ \t]*$")
- (when edmacro-store-hook
- (error "\"Command\" line not allowed in this context"))
- (let ((str (buffer-substring (match-beginning 1)
- (match-end 1))))
- (unless (equal str "")
- (setq cmd (and (not (equal str "none"))
- (intern str)))
- (and (fboundp cmd) (not (arrayp (symbol-function cmd)))
- (not (y-or-n-p
- (format "Command %s is already defined; %s"
- cmd "proceed? ")))
- (keyboard-quit))))
- t)
- ((looking-at "Key:\\(.*\\)$")
- (when edmacro-store-hook
- (error "\"Key\" line not allowed in this context"))
- (let ((key (edmacro-parse-keys
- (buffer-substring (match-beginning 1)
- (match-end 1)))))
- (unless (equal key "")
- (if (equal key "none")
- (setq no-keys t)
- (push key keys)
- (let ((b (key-binding key)))
- (and b (commandp b) (not (arrayp b))
- (or (not (fboundp b))
- (not (arrayp (symbol-function b))))
- (not (y-or-n-p
- (format "Key %s is already defined; %s"
- (edmacro-format-keys key 1)
- "proceed? ")))
- (keyboard-quit))))))
- t)
- ((looking-at "Macro:[ \t\n]*")
- (goto-char (match-end 0))
- nil)
- ((eobp) nil)
- (t (error "Expected a `Macro:' line")))
- (forward-line 1))
- (setq top (point)))
- (let* ((buf (current-buffer))
- (str (buffer-substring top (point-max)))
- (modp (buffer-modified-p))
- (obuf edmacro-original-buffer)
- (store-hook edmacro-store-hook)
- (finish-hook edmacro-finish-hook))
- (unless (or cmd keys store-hook (equal str ""))
- (error "No command name or keys specified"))
- (when modp
- (when (buffer-name obuf)
- (set-buffer obuf))
- (message "Compiling keyboard macro...")
- (let ((mac (edmacro-parse-keys str)))
- (message "Compiling keyboard macro...done")
- (if store-hook
- (funcall store-hook mac)
- (when (eq cmd 'last-kbd-macro)
- (setq last-kbd-macro (and (> (length mac) 0) mac))
- (setq cmd nil))
- (when cmd
- (if (= (length mac) 0)
- (fmakunbound cmd)
- (fset cmd mac)))
- (if no-keys
- (when cmd
- (loop for key in (where-is-internal cmd '(keymap)) do
- (global-unset-key key)))
- (when keys
- (if (= (length mac) 0)
- (loop for key in keys do (global-unset-key key))
- (loop for key in keys do
- (global-set-key key (or cmd mac)))))))))
- (kill-buffer buf)
- (when (buffer-name obuf)
- (switch-to-buffer obuf))
- (when finish-hook
- (funcall finish-hook)))))
-
-(defun edmacro-insert-key (key)
- "Insert the written name of a key in the buffer."
- (interactive "kKey to insert: ")
- (if (bolp)
- (insert (edmacro-format-keys key t) "\n")
- (insert (edmacro-format-keys key) " ")))
-
-(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.
-
-Press \\[edmacro-insert-key] to insert the name of any key by typing the key.
-
-The editing buffer contains a \"Command:\" line and any number of
-\"Key:\" lines at the top. These are followed by a \"Macro:\" line
-and the macro itself as spelled-out keystrokes: `C-x C-f foo RET'.
-
-The \"Command:\" line specifies the command name to which the macro
-is bound, or \"none\" for no command name. Write \"last-kbd-macro\"
-to refer to the current keyboard macro (as used by \\[call-last-kbd-macro]).
-
-The \"Key:\" lines specify key sequences to which the macro is bound,
-or \"none\" for no key bindings.
-
-You can edit these lines to change the places where the new macro
-is stored.
-
-
-Format of keyboard macros during editing:
-
-Text is divided into \"words\" separated by whitespace. Except for
-the words described below, the characters of each word go directly
-as characters of the macro. The whitespace that separates words
-is ignored. Whitespace in the macro must be written explicitly,
-as in \"foo SPC bar RET\".
-
- * The special words RET, SPC, TAB, DEL, LFD, ESC, and NUL represent
- special control characters. The words must be written in uppercase.
-
- * A word in angle brackets, e.g., <return>, <down>, or <f1>, represents
- a function key. (Note that in the standard configuration, the
- function key <return> and the control key RET are synonymous.)
- You can use angle brackets on the words RET, SPC, etc., but they
- are not required there.
-
- * Keys can be written by their ASCII code, using a backslash followed
- by up to six octal digits. This is the only way to represent keys
- with codes above \\377.
-
- * One or more prefixes M- (meta), C- (control), S- (shift), A- (alt),
- H- (hyper), and s- (super) may precede a character or key notation.
- For function keys, the prefixes may go inside or outside of the
- brackets: C-<down> = <C-down>. The prefixes may be written in
- any order: M-C-x = C-M-x.
-
- Prefixes are not allowed on multi-key words, e.g., C-abc, except
- that the Meta prefix is allowed on a sequence of digits and optional
- minus sign: M--123 = M-- M-1 M-2 M-3.
-
- * The `^' notation for control characters also works: ^M = C-m.
-
- * Double angle brackets enclose command names: <<next-line>> is
- shorthand for M-x next-line RET.
-
- * Finally, REM or ;; causes the rest of the line to be ignored as a
- comment.
-
-Any word may be prefixed by a multiplier in the form of a decimal
-number and `*': 3*<right> = <right> <right> <right>, and
-10*foo = foofoofoofoofoofoofoofoofoofoo.
-
-Multiple text keys can normally be strung together to form a word,
-but you may need to add whitespace if the word would look like one
-of the above notations: `; ; ;' is a keyboard macro with three
-semicolons, but `;;;' is a comment. Likewise, `\\ 1 2 3' is four
-keys but `\\123' is a single key written in octal, and `< right >'
-is seven keys but `<right>' is a single function key. When in
-doubt, use whitespace."
- (interactive)
- (error "This mode can be enabled only by `edit-kbd-macro'"))
-(put 'edmacro-mode 'mode-class 'special)
-
-;;; Formatting a keyboard macro as human-readable text.
-
-(defun edmacro-format-keys (macro &optional verbose)
- (setq macro (edmacro-fix-menu-commands macro))
- (let* ((maps (append (current-minor-mode-maps)
- (if (current-local-map)
- (list (current-local-map)))
- (list (current-global-map))))
- (pkeys '(end-macro ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?- ?\C-u
- ?\M-- ?\M-0 ?\M-1 ?\M-2 ?\M-3 ?\M-4 ?\M-5 ?\M-6
- ?\M-7 ?\M-8 ?\M-9))
- (mdigs (nthcdr 13 pkeys))
- (maxkey (if edmacro-eight-bits 255 127))
- (case-fold-search nil)
- (res-words '("NUL" "TAB" "LFD" "RET" "ESC" "SPC" "DEL" "REM"))
- (rest-mac (vconcat macro [end-macro]))
- (res "")
- (len 0)
- (one-line (eq verbose 1)))
- (if one-line (setq verbose nil))
- (when (stringp macro)
- (loop for i below (length macro) do
- (when (>= (aref rest-mac i) 128)
- (incf (aref rest-mac i) (- ?\M-\^@ 128)))))
- (while (not (eq (aref rest-mac 0) 'end-macro))
- (let* ((prefix
- (or (and (integerp (aref rest-mac 0))
- (memq (aref rest-mac 0) mdigs)
- (memq (key-binding (edmacro-subseq rest-mac 0 1))
- '(digit-argument negative-argument))
- (let ((i 1))
- (while (memq (aref rest-mac i) (cdr mdigs))
- (incf i))
- (and (not (memq (aref rest-mac i) pkeys))
- (prog1 (concat "M-" (edmacro-subseq rest-mac 0 i) " ")
- (callf edmacro-subseq rest-mac i)))))
- (and (eq (aref rest-mac 0) ?\C-u)
- (eq (key-binding [?\C-u]) 'universal-argument)
- (let ((i 1))
- (while (eq (aref rest-mac i) ?\C-u)
- (incf i))
- (and (not (memq (aref rest-mac i) pkeys))
- (prog1 (loop repeat i concat "C-u ")
- (callf edmacro-subseq rest-mac i)))))
- (and (eq (aref rest-mac 0) ?\C-u)
- (eq (key-binding [?\C-u]) 'universal-argument)
- (let ((i 1))
- (when (eq (aref rest-mac i) ?-)
- (incf i))
- (while (memq (aref rest-mac i)
- '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9))
- (incf i))
- (and (not (memq (aref rest-mac i) pkeys))
- (prog1 (concat "C-u " (edmacro-subseq rest-mac 1 i) " ")
- (callf edmacro-subseq rest-mac i)))))))
- (bind-len (apply 'max 1
- (loop for map in maps
- for b = (lookup-key map rest-mac)
- when b collect b)))
- (key (edmacro-subseq rest-mac 0 bind-len))
- (fkey nil) tlen tkey
- (bind (or (loop for map in maps for b = (lookup-key map key)
- thereis (and (not (integerp b)) b))
- (and (setq fkey (lookup-key function-key-map rest-mac))
- (setq tlen fkey tkey (edmacro-subseq rest-mac 0 tlen)
- fkey (lookup-key function-key-map tkey))
- (loop for map in maps
- for b = (lookup-key map fkey)
- when (and (not (integerp b)) b)
- do (setq bind-len tlen key tkey)
- and return b
- finally do (setq fkey nil)))))
- (first (aref key 0))
- (text (loop for i from bind-len below (length rest-mac)
- for ch = (aref rest-mac i)
- while (and (integerp ch)
- (> ch 32) (< ch maxkey) (/= ch 92)
- (eq (key-binding (char-to-string ch))
- 'self-insert-command)
- (or (> i (- (length rest-mac) 2))
- (not (eq ch (aref rest-mac (+ i 1))))
- (not (eq ch (aref rest-mac (+ i 2))))))
- finally return i))
- desc)
- (if (stringp bind) (setq bind nil))
- (cond ((and (eq bind 'self-insert-command) (not prefix)
- (> text 1) (integerp first)
- (> first 32) (<= first maxkey) (/= first 92)
- (progn
- (if (> text 30) (setq text 30))
- (setq desc (concat (edmacro-subseq rest-mac 0 text)))
- (when (string-match "^[ACHMsS]-." desc)
- (setq text 2)
- (callf substring desc 0 2))
- (not (string-match
- "^;;\\|^<.*>$\\|^\\\\[0-9]+$\\|^[0-9]+\\*."
- desc))))
- (when (or (string-match "^\\^.$" desc)
- (member desc res-words))
- (setq desc (mapconcat 'char-to-string desc " ")))
- (when verbose
- (setq bind (format "%s * %d" bind text)))
- (setq bind-len text))
- ((and (eq bind 'execute-extended-command)
- (> text bind-len)
- (memq (aref rest-mac text) '(return 13))
- (progn
- (setq desc (concat (edmacro-subseq rest-mac bind-len text)))
- (commandp (intern-soft desc))))
- (if (commandp (intern-soft desc)) (setq bind desc))
- (setq desc (format "<<%s>>" desc))
- (setq bind-len (1+ text)))
- (t
- (setq desc (mapconcat
- (function
- (lambda (ch)
- (cond
- ((integerp ch)
- (concat
- (loop for pf across "ACHMsS"
- for bit in '(?\A-\^@ ?\C-\^@ ?\H-\^@
- ?\M-\^@ ?\s-\^@ ?\S-\^@)
- when (/= (logand ch bit) 0)
- concat (format "%c-" pf))
- (let ((ch2 (logand ch (1- (lsh 1 18)))))
- (cond ((<= ch2 32)
- (case ch2
- (0 "NUL") (9 "TAB") (10 "LFD")
- (13 "RET") (27 "ESC") (32 "SPC")
- (t
- (format "C-%c"
- (+ (if (<= ch2 26) 96 64)
- ch2)))))
- ((= ch2 127) "DEL")
- ((<= ch2 maxkey) (char-to-string ch2))
- (t (format "\\%o" ch2))))))
- ((symbolp ch)
- (format "<%s>" ch))
- (t
- (error "Unrecognized item in macro: %s" ch)))))
- (or fkey key) " "))))
- (if prefix (setq desc (concat prefix desc)))
- (unless (string-match " " desc)
- (let ((times 1) (pos bind-len))
- (while (not (edmacro-mismatch rest-mac rest-mac
- 0 bind-len pos (+ bind-len pos)))
- (incf times)
- (incf pos bind-len))
- (when (> times 1)
- (setq desc (format "%d*%s" times desc))
- (setq bind-len (* bind-len times)))))
- (setq rest-mac (edmacro-subseq rest-mac bind-len))
- (if verbose
- (progn
- (unless (equal res "") (callf concat res "\n"))
- (callf concat res desc)
- (when (and bind (or (stringp bind) (symbolp bind)))
- (callf concat res
- (make-string (max (- 3 (/ (length desc) 8)) 1) 9)
- ";; " (if (stringp bind) bind (symbol-name bind))))
- (setq len 0))
- (if (and (> (+ len (length desc) 2) 72) (not one-line))
- (progn
- (callf concat res "\n ")
- (setq len 1))
- (unless (equal res "")
- (callf concat res " ")
- (incf len)))
- (callf concat res desc)
- (incf len (length desc)))))
- res))
-
-(defun edmacro-mismatch (cl-seq1 cl-seq2 cl-start1 cl-end1 cl-start2 cl-end2)
- "Compare SEQ1 with SEQ2, return index of first mismatching element.
-Return nil if the sequences match. If one sequence is a prefix of the
-other, the return value indicates the end of the shorted sequence."
- (let (cl-test cl-test-not cl-key cl-from-end)
- (or cl-end1 (setq cl-end1 (length cl-seq1)))
- (or cl-end2 (setq cl-end2 (length cl-seq2)))
- (if cl-from-end
- (progn
- (while (and (< cl-start1 cl-end1) (< cl-start2 cl-end2)
- (cl-check-match (elt cl-seq1 (1- cl-end1))
- (elt cl-seq2 (1- cl-end2))))
- (setq cl-end1 (1- cl-end1) cl-end2 (1- cl-end2)))
- (and (or (< cl-start1 cl-end1) (< cl-start2 cl-end2))
- (1- cl-end1)))
- (let ((cl-p1 (and (listp cl-seq1) (nthcdr cl-start1 cl-seq1)))
- (cl-p2 (and (listp cl-seq2) (nthcdr cl-start2 cl-seq2))))
- (while (and (< cl-start1 cl-end1) (< cl-start2 cl-end2)
- (cl-check-match (if cl-p1 (car cl-p1)
- (aref cl-seq1 cl-start1))
- (if cl-p2 (car cl-p2)
- (aref cl-seq2 cl-start2))))
- (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2)
- cl-start1 (1+ cl-start1) cl-start2 (1+ cl-start2)))
- (and (or (< cl-start1 cl-end1) (< cl-start2 cl-end2))
- cl-start1)))))
-
-(defun edmacro-subseq (seq start &optional end)
- "Return the subsequence of SEQ from START to END.
-If END is omitted, it defaults to the length of the sequence.
-If START or END is negative, it counts from the end."
- (if (stringp seq) (substring seq start end)
- (let (len)
- (and end (< end 0) (setq end (+ end (setq len (length seq)))))
- (if (< start 0) (setq start (+ start (or len (setq len (length seq))))))
- (cond ((listp seq)
- (if (> start 0) (setq seq (nthcdr start seq)))
- (if end
- (let ((res nil))
- (while (>= (setq end (1- end)) start)
- (cl-push (cl-pop seq) res))
- (nreverse res))
- (copy-sequence seq)))
- (t
- (or end (setq end (or len (length seq))))
- (let ((res (make-vector (max (- end start) 0) nil))
- (i 0))
- (while (< start end)
- (aset res i (aref seq start))
- (setq i (1+ i) start (1+ start)))
- res))))))
-
-(defun edmacro-fix-menu-commands (macro)
- (when (vectorp macro)
- (let ((i 0) ev)
- (while (< i (length macro))
- (when (consp (setq ev (aref macro i)))
- (cond ((equal (cadadr ev) '(menu-bar))
- (setq macro (vconcat (edmacro-subseq macro 0 i)
- (vector 'menu-bar (car ev))
- (edmacro-subseq macro (1+ i))))
- (incf i))
- ;; It would be nice to do pop-up menus, too, but not enough
- ;; info is recorded in macros to make this possible.
- (t
- (error "Macros with mouse clicks are not %s"
- "supported by this command"))))
- (incf i))))
- macro)
-
-;;; Parsing a human-readable keyboard macro.
-
-(defun edmacro-parse-keys (string &optional need-vector)
- (let ((case-fold-search nil)
- (pos 0)
- (res []))
- (while (and (< pos (length string))
- (string-match "[^ \t\n\f]+" string pos))
- (let ((word (substring string (match-beginning 0) (match-end 0)))
- (key nil)
- (times 1))
- (setq pos (match-end 0))
- (when (string-match "\\([0-9]+\\)\\*." word)
- (setq times (string-to-int (substring word 0 (match-end 1))))
- (setq word (substring word (1+ (match-end 1)))))
- (cond ((string-match "^<<.+>>$" word)
- (setq key (vconcat (if (eq (key-binding [?\M-x])
- 'execute-extended-command)
- [?\M-x]
- (or (car (where-is-internal
- 'execute-extended-command))
- [?\M-x]))
- (substring word 2 -2) "\r")))
- ((and (string-match "^\\(\\([ACHMsS]-\\)*\\)<\\(.+\\)>$" word)
- (progn
- (setq word (concat (substring word (match-beginning 1)
- (match-end 1))
- (substring word (match-beginning 3)
- (match-end 3))))
- (not (string-match
- "\\<\\(NUL\\|RET\\|LFD\\|ESC\\|SPC\\|DEL\\)$"
- word))))
- (setq key (list (intern word))))
- ((or (equal word "REM") (string-match "^;;" word))
- (setq pos (string-match "$" string pos)))
- (t
- (let ((orig-word word) (prefix 0) (bits 0))
- (while (string-match "^[ACHMsS]-." word)
- (incf bits (cdr (assq (aref word 0)
- '((?A . ?\A-\^@) (?C . ?\C-\^@)
- (?H . ?\H-\^@) (?M . ?\M-\^@)
- (?s . ?\s-\^@) (?S . ?\S-\^@)))))
- (incf prefix 2)
- (callf substring word 2))
- (when (string-match "^\\^.$" word)
- (incf bits ?\C-\^@)
- (incf prefix)
- (callf substring word 1))
- (let ((found (assoc word '(("NUL" . "\0") ("RET" . "\r")
- ("LFD" . "\n") ("TAB" . "\t")
- ("ESC" . "\e") ("SPC" . " ")
- ("DEL" . "\177")))))
- (when found (setq word (cdr found))))
- (when (string-match "^\\\\[0-7]+$" word)
- (loop for ch across word
- for n = 0 then (+ (* n 8) ch -48)
- finally do (setq word (vector n))))
- (cond ((= bits 0)
- (setq key word))
- ((and (= bits ?\M-\^@) (stringp word)
- (string-match "^-?[0-9]+$" word))
- (setq key (loop for x across word collect (+ x bits))))
- ((/= (length word) 1)
- (error "%s must prefix a single character, not %s"
- (substring orig-word 0 prefix) word))
- ((and (/= (logand bits ?\C-\^@) 0) (stringp word)
- (string-match "[@-_.a-z?]" word))
- (setq key (list (+ bits (- ?\C-\^@)
- (if (equal word "?") 127
- (logand (aref word 0) 31))))))
- (t
- (setq key (list (+ bits (aref word 0)))))))))
- (when key
- (loop repeat times do (callf vconcat res key)))))
- (when (and (>= (length res) 4)
- (eq (aref res 0) ?\C-x)
- (eq (aref res 1) ?\()
- (eq (aref res (- (length res) 2)) ?\C-x)
- (eq (aref res (- (length res) 1)) ?\)))
- (setq res (edmacro-subseq res 2 -2)))
- (if (and (not need-vector)
- (loop for ch across res
- always (and (integerp ch)
- (let ((ch2 (logand ch (lognot ?\M-\^@))))
- (and (>= ch2 0) (<= ch2 127))))))
- (concat (loop for ch across res
- collect (if (= (logand ch ?\M-\^@) 0)
- ch (+ ch 128))))
- res)))
-
-(provide 'edmacro)
-
-;;; edmacro.el ends here
-
diff --git a/lisp/ehelp.el b/lisp/ehelp.el
deleted file mode 100644
index c469c3d10f9..00000000000
--- a/lisp/ehelp.el
+++ /dev/null
@@ -1,396 +0,0 @@
-;;; ehelp.el --- bindings for electric-help mode
-
-;; Copyright (C) 1986, 1995 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: help, extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides a pre-packaged `Electric Help Mode' for
-;; browsing on-line help screens. There is one entry point,
-;; `with-electric-help'; all you have to give it is a no-argument
-;; function that generates the actual text of the help into the current
-;; buffer.
-
-;; To make this the default, you must do
-;; (require 'ehelp)
-;; (define-key global-map "\C-h" 'ehelp-command)
-;; (define-key global-map [help] 'ehelp-command)
-;; (define-key global-map [f1] 'ehelp-command)
-
-;;; Code:
-
-(require 'electric)
-(defvar electric-help-map ()
- "Keymap defining commands available in `electric-help-mode'.")
-
-(defvar electric-help-form-to-execute nil)
-
-(put 'electric-help-undefined 'suppress-keymap t)
-(if electric-help-map
- ()
- (let ((map (make-keymap)))
- ;; allow all non-self-inserting keys - search, scroll, etc, but
- ;; let M-x and C-x exit ehelp mode and retain buffer:
- (suppress-keymap map)
- (define-key map "\C-u" 'electric-help-undefined)
- (define-key map [?\C-0] 'electric-help-undefined)
- (define-key map [?\C-1] 'electric-help-undefined)
- (define-key map [?\C-2] 'electric-help-undefined)
- (define-key map [?\C-3] 'electric-help-undefined)
- (define-key map [?\C-4] 'electric-help-undefined)
- (define-key map [?\C-5] 'electric-help-undefined)
- (define-key map [?\C-6] 'electric-help-undefined)
- (define-key map [?\C-7] 'electric-help-undefined)
- (define-key map [?\C-8] 'electric-help-undefined)
- (define-key map [?\C-9] 'electric-help-undefined)
- (define-key map (char-to-string help-char) 'electric-help-help)
- (define-key map "?" 'electric-help-help)
- (define-key map " " 'scroll-up)
- (define-key map "\^?" 'scroll-down)
- (define-key map "." 'beginning-of-buffer)
- (define-key map "<" 'beginning-of-buffer)
- (define-key map ">" 'end-of-buffer)
- ;(define-key map "\C-g" 'electric-help-exit)
- (define-key map "q" 'electric-help-exit)
- (define-key map "Q" 'electric-help-exit)
- ;;a better key than this?
- (define-key map "r" 'electric-help-retain)
- (define-key map "R" 'electric-help-retain)
- (define-key map "\ex" 'electric-help-execute-extended)
- (define-key map "\C-x" 'electric-help-ctrl-x-prefix)
-
- (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'.)"
- (setq buffer-read-only t)
- (setq mode-name "Help")
- (setq major-mode 'help)
- (setq mode-line-buffer-identification '(" Help: %b"))
- (use-local-map electric-help-map)
- (add-hook 'mouse-leave-buffer-hook 'electric-help-retain)
- (view-mode -1)
- ;; this is done below in with-electric-help
- ;(run-hooks 'electric-help-mode-hook)
- )
-
-;;;###autoload
-(defun with-electric-help (thunk &optional buffer noerase minheight)
- "Pop up an \"electric\" help buffer.
-The arguments are THUNK &optional BUFFER NOERASE MINHEIGHT.
-THUNK is a function of no arguments which is called to initialize the
-contents of BUFFER. BUFFER defaults to `*Help*'. BUFFER will be
-erased before THUNK is called unless NOERASE is non-nil. THUNK will
-be called while BUFFER is current and with `standard-output' bound to
-the buffer specified by BUFFER.
-
-If THUNK returns nil, we display BUFFER starting at the top, and
-shrink the window to fit. If THUNK returns non-nil, we don't do those things.
-
-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. The window's height will be at least MINHEIGHT if
-this value is non-nil.
-
-If THUNK returns nil, we display BUFFER starting at the top, and
-shrink the window to fit. If THUNK returns non-nil, we don't do those
-things.
-
-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."
- (setq buffer (get-buffer-create (or buffer "*Help*")))
- (let ((one (one-window-p t))
- (config (current-window-configuration))
- (bury nil)
- (electric-help-form-to-execute 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)
- (if (and minheight (< (window-height) minheight))
- (enlarge-window (- minheight (window-height))))
- (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)
- (setq buffer-read-only t)
- (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)))
- (eval electric-help-form-to-execute))))
-
-(defun electric-help-command-loop ()
- (catch 'exit
- (if (pos-visible-in-window-p (point-max))
- (progn (message "%s" (substitute-command-keys "<<< Press Space to bury the help buffer, Press \\[electric-help-retain] to retain it >>>"))
- (if (equal (setq unread-command-events (list (read-event)))
- '(?\ ))
- (progn (setq unread-command-events nil)
- (throw 'exit t)))))
- (let (up down both neither
- (standard (and (eq (key-binding " ")
- 'scroll-up)
- (eq (key-binding "\^?")
- 'scroll-down)
- (eq (key-binding "q")
- 'electric-help-exit)
- (eq (key-binding "r")
- 'electric-help-retain))))
- (Electric-command-loop
- 'exit
- (function (lambda ()
- (sit-for 0) ;necessary if last command was end-of-buffer or
- ;beginning-of-buffer - otherwise pos-visible-in-window-p
- ;will yield a wrong result.
- (let ((min (pos-visible-in-window-p (point-min)))
- (max (pos-visible-in-window-p (point-max))))
- (cond (isearch-mode 'noprompt)
- ((and min max)
- (cond (standard "Press q to exit, r to retain ")
- (neither)
- (t (setq neither (substitute-command-keys "Press \\[electric-help-exit] to exit, \\[electric-help-retain] to retain ")))))
- (min
- (cond (standard "Press SPC to scroll, q to exit, r to retain ")
- (up)
- (t (setq up (substitute-command-keys "Press \\[scroll-up] to scroll, \\[electric-help-exit] to exit, \\[electric-help-retain] to retain ")))))
- (max
- (cond (standard "Press DEL to scroll back, q to exit, r to retain ")
- (down)
- (t (setq down (substitute-command-keys "Press \\[scroll-down] to scroll back, \\[electric-help-exit] to exit, \\[electric-help-retain] to retain ")))))
- (t
- (cond (standard "Press SPC to scroll, DEL to scroll back, q to exit, r to retain ")
- (both)
- (t (setq both (substitute-command-keys "Press \\[scroll-up] to scroll, \\[scroll-down] to scroll back, \\[electric-help-exit] to exit, \\[electric-help-retain] to retain ")))))))))
- t))))
-
-
-
-;(defun electric-help-scroll-up (arg)
-; ">>>Doc"
-; (interactive "P")
-; (if (and (null arg) (pos-visible-in-window-p (point-max)))
-; (electric-help-exit)
-; (scroll-up arg)))
-
-(defun electric-help-exit ()
- ">>>Doc"
- (interactive)
- (throw 'exit t))
-
-(defun electric-help-retain ()
- "Exit `electric-help', retaining the current window/buffer configuration.
-\(The *Help* buffer will not be selected, but \\[switch-to-buffer-other-window] RET
-will select it.)"
- (interactive)
- ;; Make sure that we don't throw twice, even if two events cause
- ;; calling this function:
- (if (memq 'electric-help-retain mouse-leave-buffer-hook)
- (progn
- (remove-hook 'mouse-leave-buffer-hook 'electric-help-retain)
- (throw 'exit '(retain)))))
-
-
-(defun electric-help-undefined ()
- (interactive)
- (error "%s is undefined -- Press %s to exit"
- (mapconcat 'single-key-description (this-command-keys) " ")
- (if (eq (key-binding "q") 'electric-help-exit)
- "q"
- (substitute-command-keys "\\[electric-help-exit]"))))
-
-
-;>>> this needs to be hairified (recursive help, anybody?)
-(defun electric-help-help ()
- (interactive)
- (if (and (eq (key-binding "q") 'electric-help-exit)
- (eq (key-binding " ") 'scroll-up)
- (eq (key-binding "\^?") 'scroll-down)
- (eq (key-binding "r") 'electric-help-retain))
- (message "SPC scrolls up, DEL scrolls down, q exits burying help buffer, r exits")
- (message "%s" (substitute-command-keys "\\[scroll-up] scrolls up, \\[scroll-down] scrolls down, \\[electric-help-exit] exits burying help buffer, \\[electric-help-retain] exits")))
- (sit-for 2))
-
-
-;;;###autoload
-(defun electric-helpify (fun &optional name)
- (let ((name (or name "*Help*")))
- (if (save-window-excursion
- ;; kludge-o-rama
- (let* ((p (symbol-function 'print-help-return-message))
- (b (get-buffer name))
- (m (buffer-modified-p b)))
- (and b (not (get-buffer-window b))
- (setq b nil))
- (unwind-protect
- (progn
- (message "%s..." (capitalize (symbol-name fun)))
- ;; with-output-to-temp-buffer marks the buffer as unmodified.
- ;; kludging excessively and relying on that as some sort
- ;; of indication leads to the following abomination...
- ;;>> This would be doable without such icky kludges if either
- ;;>> (a) there were a function to read the interactive
- ;;>> args for a command and return a list of those args.
- ;;>> (To which one would then just apply the command)
- ;;>> (The only problem with this is that interactive-p
- ;;>> would break, but that is such a misfeature in
- ;;>> any case that I don't care)
- ;;>> It is easy to do this for emacs-lisp functions;
- ;;>> the only problem is getting the interactive spec
- ;;>> for subrs
- ;;>> (b) there were a function which returned a
- ;;>> modification-tick for a buffer. One could tell
- ;;>> whether a buffer had changed by whether the
- ;;>> modification-tick were different.
- ;;>> (Presumably there would have to be a way to either
- ;;>> restore the tick to some previous value, or to
- ;;>> suspend updating of the tick in order to allow
- ;;>> things like momentary-string-display)
- (and b
- (save-excursion
- (set-buffer b)
- (set-buffer-modified-p t)))
- (fset 'print-help-return-message 'ignore)
- (call-interactively fun)
- (and (get-buffer name)
- (get-buffer-window (get-buffer name))
- (or (not b)
- (not (eq b (get-buffer name)))
- (not (buffer-modified-p b)))))
- (fset 'print-help-return-message p)
- (and b (buffer-name b)
- (save-excursion
- (set-buffer b)
- (set-buffer-modified-p m))))))
- (with-electric-help 'ignore name t))))
-
-
-
-;; This is to be bound to M-x in ehelp mode. Retains ehelp buffer and then
-;; continues with execute-extended-command.
-(defun electric-help-execute-extended (prefixarg)
- (interactive "p")
- (setq electric-help-form-to-execute '(execute-extended-command nil))
- (electric-help-retain))
-
-;; This is to be buond to C-x in ehelp mode. Retains ehelp buffer and then
-;; continues with ctrl-x prefix.
-(defun electric-help-ctrl-x-prefix (prefixarg)
- (interactive "p")
- (setq electric-help-form-to-execute '(progn (message nil) (setq unread-command-char ?\C-x)))
- (electric-help-retain))
-
-
-(defun electric-describe-key ()
- (interactive)
- (electric-helpify 'describe-key))
-
-(defun electric-describe-mode ()
- (interactive)
- (electric-helpify 'describe-mode))
-
-(defun electric-view-lossage ()
- (interactive)
- (electric-helpify 'view-lossage))
-
-;(defun electric-help-for-help ()
-; "See help-for-help"
-; (interactive)
-; )
-
-(defun electric-describe-function ()
- (interactive)
- (electric-helpify 'describe-function))
-
-(defun electric-describe-variable ()
- (interactive)
- (electric-helpify 'describe-variable))
-
-(defun electric-describe-bindings ()
- (interactive)
- (electric-helpify 'describe-bindings))
-
-(defun electric-describe-syntax ()
- (interactive)
- (electric-helpify 'describe-syntax))
-
-(defun electric-command-apropos ()
- (interactive)
- (electric-helpify 'command-apropos "*Apropos*"))
-
-;(define-key help-map "a" 'electric-command-apropos)
-
-(defun electric-apropos ()
- (interactive)
- (electric-helpify 'apropos))
-
-
-;;;; ehelp-map
-
-(defvar ehelp-map ())
-(if ehelp-map
- nil
- (let ((map (copy-keymap help-map)))
- (substitute-key-definition 'apropos 'electric-apropos map)
- (substitute-key-definition 'command-apropos 'electric-command-apropos map)
- (substitute-key-definition 'describe-key 'electric-describe-key map)
- (substitute-key-definition 'describe-mode 'electric-describe-mode map)
- (substitute-key-definition 'view-lossage 'electric-view-lossage map)
- (substitute-key-definition 'describe-function 'electric-describe-function map)
- (substitute-key-definition 'describe-variable 'electric-describe-variable map)
- (substitute-key-definition 'describe-bindings 'electric-describe-bindings map)
- (substitute-key-definition 'describe-syntax 'electric-describe-syntax map)
-
- (setq ehelp-map map)
- (fset 'ehelp-command map)))
-
-(provide 'ehelp)
-
-;;; ehelp.el ends here
diff --git a/lisp/electric.el b/lisp/electric.el
deleted file mode 100644
index 8a155b324d5..00000000000
--- a/lisp/electric.el
+++ /dev/null
@@ -1,178 +0,0 @@
-;;; electric.el --- window maker and Command loop for `electric' modes.
-
-;; Copyright (C) 1985, 1986, 1995 Free Software Foundation, Inc.
-
-;; Author: K. Shane Hartman
-;; Maintainer: FSF
-;; Keywords: extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-; zaaaaaaap
-
-;;; Code:
-
-;; 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 throw. It assumes that you have set up the keymap, window, and
-;; everything else: all it does is read commands and execute them -
-;; providing error messages should one occur (if there is no loop
-;; function - which see). The required argument is a tag which should
-;; expect a value of nil if the user decides to punt. The second
-;; argument is the prompt to be used: if nil, use "->", if 'noprompt,
-;; don't use a prompt, if a string, use that string as prompt, and if
-;; a function of no variable, it will be evaluated in every iteration
-;; of the loop and its return value, which can be nil, 'noprompt or a
-;; string, will be used as prompt. Given third argument non-nil, it
-;; INHIBITS quitting unless the user types C-g at toplevel. This is
-;; so user can do things like C-u C-g and not get thrown out. Fourth
-;; argument, if non-nil, should be a function of two arguments which
-;; is called after every command is executed. The fifth argument, if
-;; provided, is the state variable for the function. If the
-;; loop-function gets an error, the loop will abort WITHOUT throwing
-;; (moral: use unwind-protect around call to this function for any
-;; critical stuff). The second argument for the loop function is the
-;; conditions for any error that occurred or nil if none.
-
-(defun Electric-command-loop (return-tag
- &optional prompt inhibit-quit
- loop-function loop-state)
-
- (let (cmd
- (err nil)
- (prompt-string prompt))
- (while t
- (if (not (or (stringp prompt) (eq prompt nil) (eq prompt 'noprompt)))
- (setq prompt-string (funcall prompt)))
- (if (not (stringp prompt-string))
- (if (eq prompt-string 'noprompt)
- (setq prompt-string nil)
- (setq prompt-string "->")))
- (setq cmd (read-key-sequence prompt-string))
- (setq last-command-char (aref cmd (1- (length cmd)))
- this-command (key-binding cmd t)
- cmd this-command)
- ;; This makes universal-argument-other-key work.
- (setq universal-argument-num-events 0)
- (if (or (prog1 quit-flag (setq quit-flag nil))
- (eq last-input-char ?\C-g))
- (progn (setq unread-command-events nil
- prefix-arg nil)
- ;; If it wasn't cancelling a prefix character, then quit.
- (if (or (= (length (this-command-keys)) 1)
- (not inhibit-quit)) ; safety
- (progn (ding)
- (message "Quit")
- (throw return-tag nil))
- (setq cmd nil))))
- (setq current-prefix-arg prefix-arg)
- (if cmd
- (condition-case conditions
- (progn (command-execute cmd)
- (setq last-command this-command)
- (if (or (prog1 quit-flag (setq quit-flag nil))
- (eq last-input-char ?\C-g))
- (progn (setq unread-command-events nil)
- (if (not inhibit-quit)
- (progn (ding)
- (message "Quit")
- (throw return-tag nil))
- (ding)))))
- (buffer-read-only (if loop-function
- (setq err conditions)
- (ding)
- (message "Buffer is read-only")
- (sit-for 2)))
- (beginning-of-buffer (if loop-function
- (setq err conditions)
- (ding)
- (message "Beginning of Buffer")
- (sit-for 2)))
- (end-of-buffer (if loop-function
- (setq err conditions)
- (ding)
- (message "End of Buffer")
- (sit-for 2)))
- (error (if loop-function
- (setq err conditions)
- (ding)
- (message "Error: %s"
- (if (eq (car conditions) 'error)
- (car (cdr conditions))
- (prin1-to-string conditions)))
- (sit-for 2))))
- (ding))
- (if loop-function (funcall loop-function loop-state err))))
- (ding)
- (throw return-tag nil))
-
-;; This function is like pop-to-buffer, sort of.
-;; The algorithm is
-;; If there is a window displaying buffer
-;; Select it
-;; Else if there is only one window
-;; Split it, selecting the window on the bottom with height being
-;; the lesser of max-height (if non-nil) and the number of lines in
-;; the buffer to be displayed subject to window-min-height constraint.
-;; Else
-;; Switch to buffer in the current window.
-;;
-;; Then if max-height is nil, and not all of the lines in the buffer
-;; are displayed, grab the whole frame.
-;;
-;; Returns selected window on buffer positioned at point-min.
-
-(defun Electric-pop-up-window (buffer &optional max-height)
- (let* ((win (or (get-buffer-window buffer) (selected-window)))
- (buf (get-buffer buffer))
- (one-window (one-window-p t))
- (pop-up-windows t)
- (target-height)
- (lines))
- (if (not buf)
- (error "Buffer %s does not exist" buffer)
- (save-excursion
- (set-buffer buf)
- (setq lines (count-lines (point-min) (point-max)))
- (setq target-height
- (min (max (if max-height (min max-height (1+ lines)) (1+ lines))
- window-min-height)
- (save-window-excursion
- (delete-other-windows)
- (1- (window-height (selected-window)))))))
- (cond ((and (eq (window-buffer win) buf))
- (select-window win))
- (one-window
- (goto-char (window-start win))
- (pop-to-buffer buffer)
- (setq win (selected-window))
- (enlarge-window (- target-height (window-height win))))
- (t
- (switch-to-buffer buf)))
- (if (and (not max-height)
- (> target-height (window-height (selected-window))))
- (progn (goto-char (window-start win))
- (enlarge-window (- target-height (window-height win)))))
- (goto-char (point-min))
- win)))
-
-(provide 'electric)
-
-;;; electric.el ends here
diff --git a/lisp/emacs-lisp/advice.el b/lisp/emacs-lisp/advice.el
deleted file mode 100644
index dabff28ae3a..00000000000
--- a/lisp/emacs-lisp/advice.el
+++ /dev/null
@@ -1,3960 +0,0 @@
-;;; advice.el --- an overloading mechanism for Emacs Lisp functions
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Hans Chalupsky <hans@cs.buffalo.edu>
-;; Created: 12 Dec 1992
-;; Version: advice.el,v 2.14 1994/08/05 03:42:04 hans Exp
-;; Keywords: extensions, lisp, tools
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; LCD Archive Entry:
-;; advice|Hans Chalupsky|hans@cs.buffalo.edu|
-;; Overloading mechanism for Emacs Lisp functions|
-;; 1994/08/05 03:42:04|2.14|~/packages/advice.el.Z|
-
-
-;;; Commentary:
-
-;; NOTE: This documentation is slightly out of date. In particular, all the
-;; references to Emacs-18 are obsolete now, because it is not any longer
-;; supported by this version of Advice. An up-to-date version will soon be
-;; available as an info file (thanks to the kind help of Jack Vinson and
-;; David M. Smith).
-
-;; @ Introduction:
-;; ===============
-;; This package implements a full-fledged Lisp-style advice mechanism
-;; for Emacs Lisp. Advice is a clean and efficient way to modify the
-;; behavior of Emacs Lisp functions without having to keep personal
-;; modified copies of such functions around. A great number of such
-;; modifications can be achieved by treating the original function as a
-;; black box and specifying a different execution environment for it
-;; with a piece of advice. Think of a piece of advice as a kind of fancy
-;; hook that you can attach to any function/macro/subr.
-
-;; @ Highlights:
-;; =============
-;; - Clean definition of multiple, named before/around/after advices
-;; for functions, macros, subrs and special forms
-;; - Full control over the arguments an advised function will receive,
-;; the binding environment in which it will be executed, as well as the
-;; value it will return.
-;; - Allows re/definition of interactive behavior for functions and subrs
-;; - Every piece of advice can have its documentation string which will be
-;; combined with the original documentation of the advised function at
-;; call-time of `documentation' for proper command-key substitution.
-;; - The execution of every piece of advice can be protected against error
-;; and non-local exits in preceding code or advices.
-;; - Simple argument access either by name, or, more portable but as
-;; efficient, via access macros
-;; - Allows the specification of a different argument list for the advised
-;; version of a function.
-;; - Advised functions can be byte-compiled either at file-compile time
-;; (see preactivation) or activation time.
-;; - Separation of advice definition and activation
-;; - Forward advice is possible, that is
-;; as yet undefined or autoload functions can be advised without having to
-;; preload the file in which they are defined.
-;; - Forward redefinition is possible because around advice can be used to
-;; completely redefine a function.
-;; - A caching mechanism for advised definition provides for cheap deactivation
-;; and reactivation of advised functions.
-;; - Preactivation allows efficient construction and compilation of advised
-;; definitions at file compile time without giving up the flexibility of
-;; the advice mechanism.
-;; - En/disablement mechanism allows the use of different "views" of advised
-;; functions depending on what pieces of advice are currently en/disabled
-;; - Provides manipulation mechanisms for sets of advised functions via
-;; regular expressions that match advice names
-
-;; @ How to get Advice for Emacs-18:
-;; =================================
-;; `advice18.el', a version of Advice that also works in Emacs-18 is available
-;; either via anonymous ftp from `ftp.cs.buffalo.edu (128.205.32.9)' with
-;; pathname `/pub/Emacs/advice18.el', or from one of the Emacs Lisp archive
-;; sites, or send email to <hans@cs.buffalo.edu> and I'll mail it to you.
-
-;; @ Overview, or how to read this file:
-;; =====================================
-;; NOTE: This documentation is slightly out of date. In particular, all the
-;; references to Emacs-18 are obsolete now, because it is not any longer
-;; supported by this version of Advice. An up-to-date version will soon be
-;; available as an info file (thanks to the kind help of Jack Vinson and
-;; David M. Smith). Until then you can use `outline-mode' to help you read
-;; this documentation (set `outline-regexp' to `";; @+"').
-;;
-;; The four major sections of this file are:
-;;
-;; @ This initial information ...installation, customization etc.
-;; @ Advice documentation: ...general documentation
-;; @ Foo games: An advice tutorial ...teaches about Advice by example
-;; @ Advice implementation: ...actual code, yeah!!
-;;
-;; The latter three are actual headings which you can search for
-;; directly in case `outline-mode' doesn't work for you.
-
-;; @ Restrictions:
-;; ===============
-;; - This version of Advice only works for Emacs 19.26 and later. It uses
-;; new versions of the built-in functions `fset/defalias' which are not
-;; yet available in Lucid Emacs, hence, it won't work there.
-;; - Advised functions/macros/subrs will only exhibit their advised behavior
-;; when they are invoked via their function cell. This means that advice will
-;; not work for the following:
-;; + advised subrs that are called directly from other subrs or C-code
-;; + advised subrs that got replaced with their byte-code during
-;; byte-compilation (e.g., car)
-;; + advised macros which were expanded during byte-compilation before
-;; their advice was activated.
-
-;; @ Credits:
-;; ==========
-;; This package is an extension and generalization of packages such as
-;; insert-hooks.el written by Noah S. Friedman, and advise.el written by
-;; Raul J. Acevedo. Some ideas used in here come from these packages,
-;; others come from the various Lisp advice mechanisms I've come across
-;; so far, and a few are simply mine.
-
-;; @ Comments, suggestions, bug reports:
-;; =====================================
-;; If you find any bugs, have suggestions for new advice features, find the
-;; documentation wrong, confusing, incomplete, or otherwise unsatisfactory,
-;; have any questions about Advice, or have otherwise enlightening
-;; comments feel free to send me email at <hans@cs.buffalo.edu>.
-
-;; @ Safety Rules and Emergency Exits:
-;; ===================================
-;; Before we begin: CAUTION!!
-;; Advice provides you with a lot of rope to hang yourself on very
-;; easily accessible trees, so, here are a few important things you
-;; should know: Once Advice has been started with `ad-start-advice'
-;; (which happens automatically when you load this file), it
-;; generates an advised definition of the `documentation' function, and
-;; it will enable automatic advice activation when functions get defined.
-;; All of this can be undone at any time with `M-x ad-stop-advice'.
-;;
-;; If you experience any strange behavior/errors etc. that you attribute to
-;; Advice or to some ill-advised function do one of the following:
-
-;; - M-x ad-deactivate FUNCTION (if you have a definite suspicion what
-;; function gives you problems)
-;; - M-x ad-deactivate-all (if you don't have a clue what's going wrong)
-;; - M-x ad-stop-advice (if you think the problem is related to the
-;; advised functions used by Advice itself)
-;; - M-x ad-recover-normality (for real emergencies)
-;; - If none of the above solves your Advice-related problem go to another
-;; terminal, kill your Emacs process and send me some hate mail.
-
-;; The first three measures have restarts, i.e., once you've figured out
-;; the problem you can reactivate advised functions with either `ad-activate',
-;; `ad-activate-all', or `ad-start-advice'. `ad-recover-normality' unadvises
-;; everything so you won't be able to reactivate any advised functions, you'll
-;; have to stick with their standard incarnations for the rest of the session.
-
-;; IMPORTANT: With Advice loaded always do `M-x ad-deactivate-all' before
-;; you byte-compile a file, because advised special forms and macros can lead
-;; to unwanted compilation results. When you are done compiling use
-;; `M-x ad-activate-all' to go back to the advised state of all your
-;; advised functions.
-
-;; RELAX: Advice is pretty safe even if you are oblivious to the above.
-;; I use it extensively and haven't run into any serious trouble in a long
-;; time. Just wanted you to be warned.
-
-;; @ Customization:
-;; ================
-
-;; Look at the documentation of `ad-redefinition-action' for possible values
-;; of this variable. Its default value is `warn' which will print a warning
-;; message when an already defined advised function gets redefined with a
-;; new original definition and de/activated.
-
-;; Look at the documentation of `ad-default-compilation-action' for possible
-;; values of this variable. Its default value is `maybe' which will compile
-;; advised definitions during activation in case the byte-compiler is already
-;; loaded. Otherwise, it will leave them uncompiled.
-
-;; @ Motivation:
-;; =============
-;; Before I go on explaining how advice works, here are four simple examples
-;; how this package can be used. The first three are very useful, the last one
-;; is just a joke:
-
-;;(defadvice switch-to-buffer (before existing-buffers-only activate)
-;; "When called interactively switch to existing buffers only, unless
-;;when called with a prefix argument."
-;; (interactive
-;; (list (read-buffer "Switch to buffer: " (other-buffer)
-;; (null current-prefix-arg)))))
-;;
-;;(defadvice switch-to-buffer (around confirm-non-existing-buffers activate)
-;; "Switch to non-existing buffers only upon confirmation."
-;; (interactive "BSwitch to buffer: ")
-;; (if (or (get-buffer (ad-get-arg 0))
-;; (y-or-n-p (format "`%s' does not exist, create? " (ad-get-arg 0))))
-;; ad-do-it))
-;;
-;;(defadvice find-file (before existing-files-only activate)
-;; "Find existing files only"
-;; (interactive "fFind file: "))
-;;
-;;(defadvice car (around interactive activate)
-;; "Make `car' an interactive function."
-;; (interactive "xCar of list: ")
-;; ad-do-it
-;; (if (interactive-p)
-;; (message "%s" ad-return-value)))
-
-
-;; @ Advice documentation:
-;; =======================
-;; Below is general documentation of the various features of advice. For more
-;; concrete examples check the corresponding sections in the tutorial part.
-
-;; @@ Terminology:
-;; ===============
-;; - Emacs, Emacs-19: FSF's version of Emacs with major version 19
-;; - Lemacs: Lucid's version of Emacs with major version 19
-;; - v18: Any Emacs with major version 18 or built as an extension to that
-;; (such as Epoch)
-;; - v19: Any Emacs with major version 19
-;; - jwz: Jamie Zawinski - keeper of Lemacs and creator of the optimizing
-;; byte-compiler used in v19s.
-;; - Advice: The name of this package.
-;; - advices: Short for "pieces of advice".
-
-;; @@ Defining a piece of advice with `defadvice':
-;; ===============================================
-;; The main means of defining a piece of advice is the macro `defadvice',
-;; there is no interactive way of specifying a piece of advice. A call to
-;; `defadvice' has the following syntax which is similar to the syntax of
-;; `defun/defmacro':
-;;
-;; (defadvice <function> (<class> <name> [<position>] [<arglist>] {<flags>}*)
-;; [ [<documentation-string>] [<interactive-form>] ]
-;; {<body-form>}* )
-
-;; <function> is the name of the function/macro/subr to be advised.
-
-;; <class> is the class of the advice which has to be one of `before',
-;; `around', `after', `activation' or `deactivation' (the last two allow
-;; definition of special act/deactivation hooks).
-
-;; <name> is the name of the advice which has to be a non-nil symbol.
-;; Names uniquely identify a piece of advice in a certain advice class,
-;; hence, advices can be redefined by defining an advice with the same class
-;; and name. Advice names are global symbols, hence, the same name space
-;; conventions used for function names should be applied.
-
-;; An optional <position> specifies where in the current list of advices of
-;; the specified <class> this new advice will be placed. <position> has to
-;; be either `first', `last' or a number that specifies a zero-based
-;; position (`first' is equivalent to 0). If no position is specified
-;; `first' will be used as a default. If this call to `defadvice' redefines
-;; an already existing advice (see above) then the position argument will
-;; be ignored and the position of the already existing advice will be used.
-
-;; An optional <arglist> which has to be a list can be used to define the
-;; argument list of the advised function. This argument list should of
-;; course be compatible with the argument list of the original function,
-;; otherwise functions that call the advised function with the original
-;; argument list in mind will break. If more than one advice specify an
-;; argument list then the first one (the one with the smallest position)
-;; found in the list of before/around/after advices will be used.
-
-;; <flags> is a list of symbols that specify further information about the
-;; advice. All flags can be specified with unambiguous initial substrings.
-;; `activate': Specifies that the advice information of the advised
-;; function should be activated right after this advice has been
-;; defined. In forward advices `activate' will be ignored.
-;; `protect': Specifies that this advice should be protected against
-;; non-local exits and errors in preceding code/advices.
-;; `compile': Specifies that the advised function should be byte-compiled.
-;; This flag will be ignored unless `activate' is also specified.
-;; `disable': Specifies that the defined advice should be disabled, hence,
-;; it will not be used in an activation until somebody enables it.
-;; `preactivate': Specifies that the advised function should get preactivated
-;; at macro-expansion/compile time of this `defadvice'. This
-;; generates a compiled advised definition according to the
-;; current advice state which will be used during activation
-;; if appropriate. Only use this if the `defadvice' gets
-;; actually compiled (with a v18 byte-compiler put the `defadvice'
-;; into the body of a `defun' to accomplish proper compilation).
-
-;; An optional <documentation-string> can be supplied to document the advice.
-;; On call of the `documentation' function it will be combined with the
-;; documentation strings of the original function and other advices.
-
-;; An optional <interactive-form> form can be supplied to change/add
-;; interactive behavior of the original function. If more than one advice
-;; has an `(interactive ...)' specification then the first one (the one
-;; with the smallest position) found in the list of before/around/after
-;; advices will be used.
-
-;; A possibly empty list of <body-forms> specifies the body of the advice in
-;; an implicit progn. The body of an advice can access/change arguments,
-;; the return value, the binding environment, and can have all sorts of
-;; other side effects.
-
-;; @@ Assembling advised definitions:
-;; ==================================
-;; Suppose a function/macro/subr/special-form has N pieces of before advice,
-;; M pieces of around advice and K pieces of after advice. Assuming none of
-;; the advices is protected, its advised definition will look like this
-;; (body-form indices correspond to the position of the respective advice in
-;; that advice class):
-
-;; ([macro] lambda <arglist>
-;; [ [<advised-docstring>] [(interactive ...)] ]
-;; (let (ad-return-value)
-;; {<before-0-body-form>}*
-;; ....
-;; {<before-N-1-body-form>}*
-;; {<around-0-body-form>}*
-;; {<around-1-body-form>}*
-;; ....
-;; {<around-M-1-body-form>}*
-;; (setq ad-return-value
-;; <apply original definition to <arglist>>)
-;; {<other-around-M-1-body-form>}*
-;; ....
-;; {<other-around-1-body-form>}*
-;; {<other-around-0-body-form>}*
-;; {<after-0-body-form>}*
-;; ....
-;; {<after-K-1-body-form>}*
-;; ad-return-value))
-
-;; Macros and special forms will be redefined as macros, hence the optional
-;; [macro] in the beginning of the definition.
-
-;; <arglist> is either the argument list of the original function or the
-;; first argument list defined in the list of before/around/after advices.
-;; The values of <arglist> variables can be accessed/changed in the body of
-;; an advice by simply referring to them by their original name, however,
-;; more portable argument access macros are also provided (see below). For
-;; subrs/special-forms for which neither explicit argument list definitions
-;; are available, nor their documentation strings contain such definitions
-;; (as they do v19s), `(&rest ad-subr-args)' will be used.
-
-;; <advised-docstring> is an optional, special documentation string which will
-;; be expanded into a proper documentation string upon call of `documentation'.
-
-;; (interactive ...) is an optional interactive form either taken from the
-;; original function or from a before/around/after advice. For advised
-;; interactive subrs that do not have an interactive form specified in any
-;; advice we have to use (interactive) and then call the subr interactively
-;; if the advised function was called interactively, because the
-;; interactive specification of subrs is not accessible. This is the only
-;; case where changing the values of arguments will not have an affect
-;; because they will be reset by the interactive specification of the subr.
-;; If this is a problem one can always specify an interactive form in a
-;; before/around/after advice to gain control over argument values that
-;; were supplied interactively.
-;;
-;; Then the body forms of the various advices in the various classes of advice
-;; are assembled in order. The forms of around advice L are normally part of
-;; one of the forms of around advice L-1. An around advice can specify where
-;; the forms of the wrapped or surrounded forms should go with the special
-;; keyword `ad-do-it', which will be substituted with a `progn' containing the
-;; forms of the surrounded code.
-
-;; The innermost part of the around advice onion is
-;; <apply original definition to <arglist>>
-;; whose form depends on the type of the original function. The variable
-;; `ad-return-value' will be set to its result. This variable is visible to
-;; all pieces of advice which can access and modify it before it gets returned.
-;;
-;; The semantic structure of advised functions that contain protected pieces
-;; of advice is the same. The only difference is that `unwind-protect' forms
-;; make sure that the protected advice gets executed even if some previous
-;; piece of advice had an error or a non-local exit. If any around advice is
-;; protected then the whole around advice onion will be protected.
-
-;; @@ Argument access in advised functions:
-;; ========================================
-;; As already mentioned, the simplest way to access the arguments of an
-;; advised function in the body of an advice is to refer to them by name. To
-;; do that, the advice programmer needs to know either the names of the
-;; argument variables of the original function, or the names used in the
-;; argument list redefinition given in a piece of advice. While this simple
-;; method might be sufficient in many cases, it has the disadvantage that it
-;; is not very portable because it hardcodes the argument names into the
-;; advice. If the definition of the original function changes the advice
-;; might break even though the code might still be correct. Situations like
-;; that arise, for example, if one advises a subr like `eval-region' which
-;; gets redefined in a non-advice style into a function by the edebug
-;; package. If the advice assumes `eval-region' to be a subr it might break
-;; once edebug is loaded. Similar situations arise when one wants to use the
-;; same piece of advice across different versions of Emacs. Some subrs in a
-;; v18 Emacs are functions in v19 and vice versa, but for the most part the
-;; semantics remain the same, hence, the same piece of advice might be usable
-;; in both Emacs versions.
-
-;; As a solution to that advice provides argument list access macros that get
-;; translated into the proper access forms at activation time, i.e., when the
-;; advised definition gets constructed. Access macros access actual arguments
-;; by position regardless of how these actual argument get distributed onto
-;; the argument variables of a function. The rational behind this is that in
-;; Emacs Lisp the semantics of an argument is strictly determined by its
-;; position (there are no keyword arguments).
-
-;; Suppose the function `foo' is defined as
-;;
-;; (defun foo (x y &optional z &rest r) ....)
-;;
-;; and is then called with
-;;
-;; (foo 0 1 2 3 4 5 6)
-
-;; which means that X=0, Y=1, Z=2 and R=(3 4 5 6). The assumption is that
-;; the semantics of an actual argument is determined by its position. It is
-;; this semantics that has to be known by the advice programmer. Then s/he
-;; can access these arguments in a piece of advice with some of the
-;; following macros (the arrows indicate what value they will return):
-
-;; (ad-get-arg 0) -> 0
-;; (ad-get-arg 1) -> 1
-;; (ad-get-arg 2) -> 2
-;; (ad-get-arg 3) -> 3
-;; (ad-get-args 2) -> (2 3 4 5 6)
-;; (ad-get-args 4) -> (4 5 6)
-
-;; `(ad-get-arg <position>)' will return the actual argument that was supplied
-;; at <position>, `(ad-get-args <position>)' will return the list of actual
-;; arguments supplied starting at <position>. Note that these macros can be
-;; used without any knowledge about the form of the actual argument list of
-;; the original function.
-
-;; Similarly, `(ad-set-arg <position> <value-form>)' can be used to set the
-;; value of the actual argument at <position> to <value-form>. For example,
-;;
-;; (ad-set-arg 5 "five")
-;;
-;; will have the effect that R=(3 4 "five" 6) once the original function is
-;; called. `(ad-set-args <position> <value-list-form>)' can be used to set
-;; the list of actual arguments starting at <position> to <value-list-form>.
-;; For example,
-;;
-;; (ad-set-args 0 '(5 4 3 2 1 0))
-;;
-;; will have the effect that X=5, Y=4, Z=3 and R=(2 1 0) once the original
-;; function is called.
-
-;; All these access macros are text macros rather than real Lisp macros. When
-;; the advised definition gets constructed they get replaced with actual access
-;; forms depending on the argument list of the advised function, i.e., after
-;; that argument access is in most cases as efficient as using the argument
-;; variable names directly.
-
-;; @@@ Accessing argument bindings of arbitrary functions:
-;; =======================================================
-;; Some functions (such as `trace-function' defined in trace.el) need a
-;; method of accessing the names and bindings of the arguments of an
-;; arbitrary advised function. To do that within an advice one can use the
-;; special keyword `ad-arg-bindings' which is a text macro that will be
-;; substituted with a form that will evaluate to a list of binding
-;; specifications, one for every argument variable. These binding
-;; specifications can then be examined in the body of the advice. For
-;; example, somewhere in an advice we could do this:
-;;
-;; (let* ((bindings ad-arg-bindings)
-;; (firstarg (car bindings))
-;; (secondarg (car (cdr bindings))))
-;; ;; Print info about first argument
-;; (print (format "%s=%s (%s)"
-;; (ad-arg-binding-field firstarg 'name)
-;; (ad-arg-binding-field firstarg 'value)
-;; (ad-arg-binding-field firstarg 'type)))
-;; ....)
-;;
-;; The `type' of an argument is either `required', `optional' or `rest'.
-;; Wherever `ad-arg-bindings' appears a form will be inserted that evaluates
-;; to the list of bindings, hence, in order to avoid multiple unnecessary
-;; evaluations one should always bind it to some variable.
-
-;; @@@ Argument list mapping:
-;; ==========================
-;; Because `defadvice' allows the specification of the argument list of the
-;; advised function we need a mapping mechanism that maps this argument list
-;; onto that of the original function. For example, somebody might specify
-;; `(sym newdef)' as the argument list of `fset', while advice might use
-;; `(&rest ad-subr-args)' as the argument list of the original function
-;; (depending on what Emacs version is used). Hence SYM and NEWDEF have to
-;; be properly mapped onto the &rest variable when the original definition is
-;; called. Advice automatically takes care of that mapping, hence, the advice
-;; programmer can specify an argument list without having to know about the
-;; exact structure of the original argument list as long as the new argument
-;; list takes a compatible number/magnitude of actual arguments.
-
-;; @@@ Definition of subr argument lists:
-;; ======================================
-;; When advice constructs the advised definition of a function it has to
-;; know the argument list of the original function. For functions and macros
-;; the argument list can be determined from the actual definition, however,
-;; for subrs there is no such direct access available. In Lemacs and for some
-;; subrs in Emacs-19 the argument list of a subr can be determined from
-;; its documentation string, in a v18 Emacs even that is not possible. If
-;; advice cannot at all determine the argument list of a subr it uses
-;; `(&rest ad-subr-args)' which will always work but is inefficient because
-;; it conses up arguments. The macro `ad-define-subr-args' can be used by
-;; the advice programmer to explicitly tell advice about the argument list
-;; of a certain subr, for example,
-;;
-;; (ad-define-subr-args 'fset '(sym newdef))
-;;
-;; is used by advice itself to tell a v18 Emacs about the arguments of `fset'.
-;; The following can be used to undo such a definition:
-;;
-;; (ad-undefine-subr-args 'fset)
-;;
-;; The argument list definition is stored on the property list of the subr
-;; name symbol. When an argument list could be determined from the
-;; documentation string it will be cached under that property. The general
-;; mechanism for looking up the argument list of a subr is the following:
-;; 1) look for a definition stored on the property list
-;; 2) if that failed try to infer it from the documentation string and
-;; if successful cache it on the property list
-;; 3) otherwise use `(&rest ad-subr-args)'
-
-;; @@ Activation and deactivation:
-;; ===============================
-;; The definition of an advised function does not change until all its advice
-;; gets actually activated. Activation can either happen with the `activate'
-;; flag specified in the `defadvice', with an explicit call or interactive
-;; invocation of `ad-activate', or if forward advice is enabled (i.e., the
-;; value of `ad-activate-on-definition' is t) at the time an already advised
-;; function gets defined.
-
-;; When a function gets first activated its original definition gets saved,
-;; all defined and enabled pieces of advice will get combined with the
-;; original definition, the resulting definition might get compiled depending
-;; on some conditions described below, and then the function will get
-;; redefined with the advised definition. This also means that undefined
-;; functions cannot get activated even though they might be already advised.
-
-;; The advised definition will get compiled either if `ad-activate' was called
-;; interactively with a prefix argument, or called explicitly with its second
-;; argument as t, or, if `ad-default-compilation-action' justifies it according
-;; to the current system state. If the advised definition was
-;; constructed during "preactivation" (see below) then that definition will
-;; be already compiled because it was constructed during byte-compilation of
-;; the file that contained the `defadvice' with the `preactivate' flag.
-
-;; `ad-deactivate' can be used to back-define an advised function to its
-;; original definition. It can be called interactively or directly. Because
-;; `ad-activate' caches the advised definition the function can be
-;; reactivated via `ad-activate' with only minor overhead (it is checked
-;; whether the current advice state is consistent with the cached
-;; definition, see the section on caching below).
-
-;; `ad-activate-regexp' and `ad-deactivate-regexp' can be used to de/activate
-;; all currently advised function that have a piece of advice with a name that
-;; contains a match for a regular expression. These functions can be used to
-;; de/activate sets of functions depending on certain advice naming
-;; conventions.
-
-;; Finally, `ad-activate-all' and `ad-deactivate-all' can be used to
-;; de/activate all currently advised functions. These are useful to
-;; (temporarily) return to an un/advised state.
-
-;; @@@ Reasons for the separation of advice definition and activation:
-;; ===================================================================
-;; As already mentioned, advising happens in two stages:
-
-;; 1) definition of various pieces of advice
-;; 2) activation of all advice currently defined and enabled
-
-;; The advantage of this is that various pieces of advice can be defined
-;; before they get combined into an advised definition which avoids
-;; unnecessary constructions of intermediate advised definitions. The more
-;; important advantage is that it allows the implementation of forward advice.
-;; Advice information for a certain function accumulates as the value of the
-;; `advice-info' property of the function symbol. This accumulation is
-;; completely independent of the fact that that function might not yet be
-;; defined. The special forms `defun' and `defmacro' have been advised to
-;; check whether the function/macro they defined had advice information
-;; associated with it. If so and forward advice is enabled, the original
-;; definition will be saved, and then the advice will be activated. When a
-;; file is loaded in a v18 Emacs the functions/macros it defines are also
-;; defined with calls to `defun/defmacro'. Hence, we can forward advise
-;; functions/macros which will be defined later during a load/autoload of some
-;; file (for compiled files generated by jwz's byte-compiler in a v19 Emacs
-;; this is slightly more complicated but the basic idea is the same).
-
-;; @@ Enabling/disabling pieces or sets of advice:
-;; ===============================================
-;; A major motivation for the development of this advice package was to bring
-;; a little bit more structure into the function overloading chaos in Emacs
-;; Lisp. Many packages achieve some of their functionality by adding a little
-;; bit (or a lot) to the standard functionality of some Emacs Lisp function.
-;; ange-ftp is a very popular package that achieves its magic by overloading
-;; most Emacs Lisp functions that deal with files. A popular function that's
-;; overloaded by many packages is `expand-file-name'. The situation that one
-;; function is multiply overloaded can arise easily.
-
-;; Once in a while it would be desirable to be able to disable some/all
-;; overloads of a particular package while keeping all the rest. Ideally -
-;; at least in my opinion - these overloads would all be done with advice,
-;; I know I am dreaming right now... In that ideal case the enable/disable
-;; mechanism of advice could be used to achieve just that.
-
-;; Every piece of advice is associated with an enablement flag. When the
-;; advised definition of a particular function gets constructed (e.g., during
-;; activation) only the currently enabled pieces of advice will be considered.
-;; This mechanism allows one to have different "views" of an advised function
-;; dependent on what pieces of advice are currently enabled.
-
-;; Another motivation for this mechanism is that it allows one to define a
-;; piece of advice for some function yet keep it dormant until a certain
-;; condition is met. Until then activation of the function will not make use
-;; of that piece of advice. Once the condition is met the advice can be
-;; enabled and a reactivation of the function will add its functionality as
-;; part of the new advised definition. For example, the advices of `defun'
-;; etc. used by advice itself will stay disabled until `ad-start-advice' is
-;; called and some variables have the proper values. Hence, if somebody
-;; else advised these functions too and activates them the advices defined
-;; by advice will get used only if they are intended to be used.
-
-;; The main interface to this mechanism are the interactive functions
-;; `ad-enable-advice' and `ad-disable-advice'. For example, the following
-;; would disable a particular advice of the function `foo':
-;;
-;; (ad-disable-advice 'foo 'before 'my-advice)
-;;
-;; This call by itself only changes the flag, to get the proper effect in
-;; the advised definition too one has to activate `foo' with
-;;
-;; (ad-activate 'foo)
-;;
-;; or interactively. To disable whole sets of advices one can use a regular
-;; expression mechanism. For example, let us assume that ange-ftp actually
-;; used advice to overload all its functions, and that it used the
-;; "ange-ftp-" prefix for all its advice names, then we could temporarily
-;; disable all its advices with
-;;
-;; (ad-disable-regexp "^ange-ftp-")
-;;
-;; and the following call would put that actually into effect:
-;;
-;; (ad-activate-regexp "^ange-ftp-")
-;;
-;; A saver way would have been to use
-;;
-;; (ad-update-regexp "^ange-ftp-")
-;;
-;; instead which would have only reactivated currently actively advised
-;; functions, but not functions that were currently deactivated. All these
-;; functions can also be called interactively.
-
-;; A certain piece of advice is considered a match if its name contains a
-;; match for the regular expression. To enable ange-ftp again we would use
-;; `ad-enable-regexp' and then activate or update again.
-
-;; @@ Forward advice, automatic advice activation:
-;; ===============================================
-;; Because most Emacs Lisp packages are loaded on demand via an autoload
-;; mechanism it is essential to be able to "forward advise" functions.
-;; Otherwise, proper advice definition and activation would make it necessary
-;; to preload every file that defines a certain function before it can be
-;; advised, which would partly defeat the purpose of the advice mechanism.
-
-;; In the following, "forward advice" always implies its automatic activation
-;; once a function gets defined, and not just the accumulation of advice
-;; information for a possibly undefined function.
-
-;; Advice implements forward advice mainly via the following: 1) Separation
-;; of advice definition and activation that makes it possible to accumulate
-;; advice information without having the original function already defined,
-;; 2) special versions of the built-in functions `fset/defalias' which check
-;; for advice information whenever they define a function. If advice
-;; information was found then the advice will immediately get activated when
-;; the function gets defined.
-
-;; Automatic advice activation means, that whenever a function gets defined
-;; with either `defun', `defmacro', `fset' or by loading a byte-compiled
-;; file, and the function has some advice-info stored with it then that
-;; advice will get activated right away.
-
-;; @@@ Enabling automatic advice activation:
-;; =========================================
-;; Automatic advice activation is enabled by default. It can be disabled by
-;; doint `M-x ad-stop-advice' and enabled again with `M-x ad-start-advice'.
-
-;; @@ Caching of advised definitions:
-;; ==================================
-;; After an advised definition got constructed it gets cached as part of the
-;; advised function's advice-info so it can be reused, for example, after an
-;; intermediate deactivation. Because the advice-info of a function might
-;; change between the time of caching and reuse a cached definition gets
-;; a cache-id associated with it so it can be verified whether the cached
-;; definition is still valid (the main application of this is preactivation
-;; - see below).
-
-;; When an advised function gets activated and a verifiable cached definition
-;; is available, then that definition will be used instead of creating a new
-;; advised definition from scratch. If you want to make sure that a new
-;; definition gets constructed then you should use `ad-clear-cache' before you
-;; activate the advised function.
-
-;; @@ Preactivation:
-;; =================
-;; Constructing an advised definition is moderately expensive. In a situation
-;; where one package defines a lot of advised functions it might be
-;; prohibitively expensive to do all the advised definition construction at
-;; runtime. Preactivation is a mechanism that allows compile-time construction
-;; of compiled advised definitions that can be activated cheaply during
-;; runtime. Preactivation uses the caching mechanism to do that. Here's how it
-;; works:
-
-;; When the byte-compiler compiles a `defadvice' that has the `preactivate'
-;; flag specified, it uses the current original definition of the advised
-;; function plus the advice specified in this `defadvice' (even if it is
-;; specified as disabled) and all other currently enabled pieces of advice to
-;; construct an advised definition and an identifying cache-id and makes them
-;; part of the `defadvice' expansion which will then be compiled by the
-;; byte-compiler (to ensure that in a v18 emacs you have to put the
-;; `defadvice' inside a `defun' to get it compiled and then you have to call
-;; that compiled `defun' in order to actually execute the `defadvice'). When
-;; the file with the compiled, preactivating `defadvice' gets loaded the
-;; precompiled advised definition will be cached on the advised function's
-;; advice-info. When it gets activated (can be immediately on execution of the
-;; `defadvice' or any time later) the cache-id gets checked against the
-;; current state of advice and if it is verified the precompiled definition
-;; will be used directly (the verification is pretty cheap). If it couldn't get
-;; verified a new advised definition for that function will be built from
-;; scratch, hence, the efficiency added by the preactivation mechanism does
-;; not at all impair the flexibility of the advice mechanism.
-
-;; MORAL: In order get all the efficiency out of preactivation the advice
-;; state of an advised function at the time the file with the
-;; preactivating `defadvice' gets byte-compiled should be exactly
-;; the same as it will be when the advice of that function gets
-;; actually activated. If it is not there is a high chance that the
-;; cache-id will not match and hence a new advised definition will
-;; have to be constructed at runtime.
-
-;; Preactivation and forward advice do not contradict each other. It is
-;; perfectly ok to load a file with a preactivating `defadvice' before the
-;; original definition of the advised function is available. The constructed
-;; advised definition will be used once the original function gets defined and
-;; its advice gets activated. The only constraint is that at the time the
-;; file with the preactivating `defadvice' got compiled the original function
-;; definition was available.
-
-;; TIPS: Here are some indications that a preactivation did not work the way
-;; you intended it to work:
-;; - Activation of the advised function takes longer than usual/expected
-;; - The byte-compiler gets loaded while an advised function gets
-;; activated
-;; - `byte-compile' is part of the `features' variable even though you
-;; did not use the byte-compiler
-;; Right now advice does not provide an elegant way to find out whether
-;; and why a preactivation failed. What you can do is to trace the
-;; function `ad-cache-id-verification-code' (with the function
-;; `trace-function-background' defined in my trace.el package) before
-;; any of your advised functions get activated. After they got
-;; activated check whether all calls to `ad-cache-id-verification-code'
-;; returned `verified' as a result. Other values indicate why the
-;; verification failed which should give you enough information to
-;; fix your preactivation/compile/load/activation sequence.
-
-;; IMPORTANT: There is one case (that I am aware of) that can make
-;; preactivation fail, i.e., a preconstructed advised definition that does
-;; NOT match the current state of advice gets used nevertheless. That case
-;; arises if one package defines a certain piece of advice which gets used
-;; during preactivation, and another package incompatibly redefines that
-;; very advice (i.e., same function/class/name), and it is the second advice
-;; that is available when the preconstructed definition gets activated, and
-;; that was the only definition of that advice so far (`ad-add-advice'
-;; catches advice redefinitions and clears the cache in such a case).
-;; Catching that would make the cache verification too expensive.
-
-;; MORAL-II: Redefining somebody else's advice is BAAAAD (to speak with
-;; George Walker Bush), and why would you redefine your own advice anyway?
-;; Advice is a mechanism to facilitate function redefinition, not advice
-;; redefinition (wait until I write Meta-Advice :-). If you really have
-;; to undo somebody else's advice try to write a "neutralizing" advice.
-
-;; @@ Advising macros and special forms and other dangerous things:
-;; ================================================================
-;; Look at the corresponding tutorial sections for more information on
-;; these topics. Here it suffices to point out that the special treatment
-;; of macros and special forms by the byte-compiler can lead to problems
-;; when they get advised. Macros can create problems because they get
-;; expanded at compile time, hence, they might not have all the necessary
-;; runtime support and such advice cannot be de/activated or changed as
-;; it is possible for functions. Special forms create problems because they
-;; have to be advised "into" macros, i.e., an advised special form is a
-;; implemented as a macro, hence, in most cases the byte-compiler will
-;; not recognize it as a special form anymore which can lead to very strange
-;; results.
-;;
-;; MORAL: - Only advise macros or special forms when you are absolutely sure
-;; what you are doing.
-;; - As a safety measure, always do `ad-deactivate-all' before you
-;; byte-compile a file to make sure that even if some inconsiderate
-;; person advised some special forms you'll get proper compilation
-;; results. After compilation do `ad-activate-all' to get back to
-;; the previous state.
-
-;; @@ Adding a piece of advice with `ad-add-advice':
-;; =================================================
-;; The non-interactive function `ad-add-advice' can be used to add a piece of
-;; advice to some function without using `defadvice'. This is useful if advice
-;; has to be added somewhere by a function (also look at `ad-make-advice').
-
-;; @@ Activation/deactivation advices, file load hooks:
-;; ====================================================
-;; There are two special classes of advice called `activation' and
-;; `deactivation'. The body forms of these advices are not included into the
-;; advised definition of a function, rather they are assembled into a hook
-;; form which will be evaluated whenever the advice-info of the advised
-;; function gets activated or deactivated. One application of this mechanism
-;; is to define file load hooks for files that do not provide such hooks
-;; (v19s already come with a general file-load-hook mechanism, v18s don't).
-;; For example, suppose you want to print a message whenever `file-x' gets
-;; loaded, and suppose the last function defined in `file-x' is
-;; `file-x-last-fn'. Then we can define the following advice:
-;;
-;; (defadvice file-x-last-fn (activation file-x-load-hook)
-;; "Executed whenever file-x is loaded"
-;; (if load-in-progress (message "Loaded file-x")))
-;;
-;; This will constitute a forward advice for function `file-x-last-fn' which
-;; will get activated when `file-x' is loaded (only if forward advice is
-;; enabled of course). Because there are no "real" pieces of advice
-;; available for it, its definition will not be changed, but the activation
-;; advice will be run during its activation which is equivalent to having a
-;; file load hook for `file-x'.
-
-;; @@ Summary of main advice concepts:
-;; ===================================
-;; - Definition:
-;; A piece of advice gets defined with `defadvice' and added to the
-;; `advice-info' property of a function.
-;; - Enablement:
-;; Every piece of advice has an enablement flag associated with it. Only
-;; enabled advices are considered during construction of an advised
-;; definition.
-;; - Activation:
-;; Redefine an advised function with its advised definition. Constructs
-;; an advised definition from scratch if no verifiable cached advised
-;; definition is available and caches it.
-;; - Deactivation:
-;; Back-define an advised function to its original definition.
-;; - Update:
-;; Reactivate an advised function but only if its advice is currently
-;; active. This can be used to bring all currently advised function up
-;; to date with the current state of advice without also activating
-;; currently deactivated functions.
-;; - Caching:
-;; Is the saving of an advised definition and an identifying cache-id so
-;; it can be reused, for example, for activation after deactivation.
-;; - Preactivation:
-;; Is the construction of an advised definition according to the current
-;; state of advice during byte-compilation of a file with a preactivating
-;; `defadvice'. That advised definition can then rather cheaply be used
-;; during activation without having to construct an advised definition
-;; from scratch at runtime.
-
-;; @@ Summary of interactive advice manipulation functions:
-;; ========================================================
-;; The following interactive functions can be used to manipulate the state
-;; of advised functions (all of them support completion on function names,
-;; advice classes and advice names):
-
-;; - ad-activate to activate the advice of a FUNCTION
-;; - ad-deactivate to deactivate the advice of a FUNCTION
-;; - ad-update to activate the advice of a FUNCTION unless it was not
-;; yet activated or is currently deactivated.
-;; - ad-unadvise deactivates a FUNCTION and removes all of its advice
-;; information, hence, it cannot be activated again
-;; - ad-recover tries to redefine a FUNCTION to its original definition and
-;; discards all advice information (a low-level `ad-unadvise').
-;; Use only in emergencies.
-
-;; - ad-remove-advice removes a particular piece of advice of a FUNCTION.
-;; You still have to do call `ad-activate' or `ad-update' to
-;; activate the new state of advice.
-;; - ad-enable-advice enables a particular piece of advice of a FUNCTION.
-;; - ad-disable-advice disables a particular piece of advice of a FUNCTION.
-;; - ad-enable-regexp maps over all currently advised functions and enables
-;; every advice whose name contains a match for a regular
-;; expression.
-;; - ad-disable-regexp disables matching advices.
-
-;; - ad-activate-regexp activates all advised function with a matching advice
-;; - ad-deactivate-regexp deactivates all advised function with matching advice
-;; - ad-update-regexp updates all advised function with a matching advice
-;; - ad-activate-all activates all advised functions
-;; - ad-deactivate-all deactivates all advised functions
-;; - ad-update-all updates all advised functions
-;; - ad-unadvise-all unadvises all advised functions
-;; - ad-recover-all recovers all advised functions
-
-;; - ad-compile byte-compiles a function/macro if it is compilable.
-
-;; @@ Summary of forms with special meanings when used within an advice:
-;; =====================================================================
-;; ad-return-value name of the return value variable (get/settable)
-;; ad-subr-args name of &rest argument variable used for advised
-;; subrs whose actual argument list cannot be
-;; determined (get/settable)
-;; (ad-get-arg <pos>), (ad-get-args <pos>),
-;; (ad-set-arg <pos> <value>), (ad-set-args <pos> <value-list>)
-;; argument access text macros to get/set the values of
-;; actual arguments at a certain position
-;; ad-arg-bindings text macro that returns the actual names, values
-;; and types of the arguments as a list of bindings. The
-;; order of the bindings corresponds to the order of the
-;; arguments. The individual fields of every binding (name,
-;; value and type) can be accessed with the function
-;; `ad-arg-binding-field' (see example above).
-;; ad-do-it text macro that identifies the place where the original
-;; or wrapped definition should go in an around advice
-
-
-;; @ Foo games: An advice tutorial
-;; ===============================
-;; The following tutorial was created in Emacs 18.59. Left-justified
-;; s-expressions are input forms followed by one or more result forms.
-;; First we have to start the advice magic:
-;;
-;; (ad-start-advice)
-;; nil
-;;
-;; We start by defining an innocent looking function `foo' that simply
-;; adds 1 to its argument X:
-;;
-;; (defun foo (x)
-;; "Add 1 to X."
-;; (1+ x))
-;; foo
-;;
-;; (foo 3)
-;; 4
-;;
-;; @@ Defining a simple piece of advice:
-;; =====================================
-;; Now let's define the first piece of advice for `foo'. To do that we
-;; use the macro `defadvice' which takes a function name, a list of advice
-;; specifiers and a list of body forms as arguments. The first element of
-;; the advice specifiers is the class of the advice, the second is its name,
-;; the third its position and the rest are some flags. The class of our
-;; first advice is `before', its name is `fg-add2', its position among the
-;; currently defined before advices (none so far) is `first', and the advice
-;; will be `activate'ed immediately. Advice names are global symbols, hence,
-;; the name space conventions used for function names should be applied. All
-;; advice names in this tutorial will be prefixed with `fg' for `Foo Games'
-;; (because everybody has the right to be inconsistent all the function names
-;; used in this tutorial do NOT follow this convention).
-;;
-;; In the body of an advice we can refer to the argument variables of the
-;; original function by name. Here we add 1 to X so the effect of calling
-;; `foo' will be to actually add 2. All of the advice definitions below only
-;; have one body form for simplicity, but there is no restriction to that
-;; extent. Every piece of advice can have a documentation string which will
-;; be combined with the documentation of the original function.
-;;
-;; (defadvice foo (before fg-add2 first activate)
-;; "Add 2 to X."
-;; (setq x (1+ x)))
-;; foo
-;;
-;; (foo 3)
-;; 5
-;;
-;; @@ Specifying the position of an advice:
-;; ========================================
-;; Now we define the second before advice which will cancel the effect of
-;; the previous advice. This time we specify the position as 0 which is
-;; equivalent to `first'. A number can be used to specify the zero-based
-;; position of an advice among the list of advices in the same class. This
-;; time we already have one before advice hence the position specification
-;; actually has an effect. So, after the following definition the position
-;; of the previous advice will be 1 even though we specified it with `first'
-;; above, the reason for this is that the position argument is relative to
-;; the currently defined pieces of advice which by now has changed.
-;;
-;; (defadvice foo (before fg-cancel-add2 0 activate)
-;; "Again only add 1 to X."
-;; (setq x (1- x)))
-;; foo
-;;
-;; (foo 3)
-;; 4
-;;
-;; @@ Redefining a piece of advice:
-;; ================================
-;; Now we define an advice with the same class and same name but with a
-;; different position. Defining an advice in a class in which an advice with
-;; that name already exists is interpreted as a redefinition of that
-;; particular advice, in which case the position argument will be ignored
-;; and the previous position of the redefined piece of advice is used.
-;; Advice flags can be specified with non-ambiguous initial substrings, hence,
-;; from now on we'll use `act' instead of the verbose `activate'.
-;;
-;; (defadvice foo (before fg-cancel-add2 last act)
-;; "Again only add 1 to X."
-;; (setq x (1- x)))
-;; foo
-;;
-;; @@ Assembly of advised documentation:
-;; =====================================
-;; The documentation strings of the various pieces of advice are assembled
-;; in order which shows that advice `fg-cancel-add2' is still the first
-;; `before' advice even though we specified position `last' above:
-;;
-;; (documentation 'foo)
-;; "Add 1 to X.
-;;
-;; This function is advised with the following advice(s):
-;;
-;; fg-cancel-add2 (before):
-;; Again only add 1 to X.
-;;
-;; fg-add2 (before):
-;; Add 2 to X."
-;;
-;; @@ Advising interactive behavior:
-;; =================================
-;; We can make a function interactive (or change its interactive behavior)
-;; by specifying an interactive form in one of the before or around
-;; advices (there could also be body forms in this advice). The particular
-;; definition always assigns 5 as an argument to X which gives us 6 as a
-;; result when we call foo interactively:
-;;
-;; (defadvice foo (before fg-inter last act)
-;; "Use 5 as argument when called interactively."
-;; (interactive (list 5)))
-;; foo
-;;
-;; (call-interactively 'foo)
-;; 6
-;;
-;; If more than one advice have an interactive declaration, then the one of
-;; the advice with the smallest position will be used (before advices go
-;; before around and after advices), hence, the declaration below does
-;; not have any effect:
-;;
-;; (defadvice foo (before fg-inter2 last act)
-;; (interactive (list 6)))
-;; foo
-;;
-;; (call-interactively 'foo)
-;; 6
-;;
-;; Let's have a look at what the definition of `foo' looks like now
-;; (indentation added by hand for legibility):
-;;
-;; (symbol-function 'foo)
-;; (lambda (x)
-;; "$ad-doc: foo$"
-;; (interactive (list 5))
-;; (let (ad-return-value)
-;; (setq x (1- x))
-;; (setq x (1+ x))
-;; (setq ad-return-value (ad-Orig-foo x))
-;; ad-return-value))
-;;
-;; @@ Around advices:
-;; ==================
-;; Now we'll try some `around' advices. An around advice is a wrapper around
-;; the original definition. It can shadow or establish bindings for the
-;; original definition, and it can look at and manipulate the value returned
-;; by the original function. The position of the special keyword `ad-do-it'
-;; specifies where the code of the original function will be executed. The
-;; keyword can appear multiple times which will result in multiple calls of
-;; the original function in the resulting advised code. Note, that if we don't
-;; specify a position argument (i.e., `first', `last' or a number), then
-;; `first' (or 0) is the default):
-;;
-;; (defadvice foo (around fg-times-2 act)
-;; "First double X."
-;; (let ((x (* x 2)))
-;; ad-do-it))
-;; foo
-;;
-;; (foo 3)
-;; 7
-;;
-;; Around advices are assembled like onion skins where the around advice
-;; with position 0 is the outermost skin and the advice at the last position
-;; is the innermost skin which is directly wrapped around the call of the
-;; original definition of the function. Hence, after the next `defadvice' we
-;; will first multiply X by 2 then add 1 and then call the original
-;; definition (i.e., add 1 again):
-;;
-;; (defadvice foo (around fg-add-1 last act)
-;; "Add 1 to X."
-;; (let ((x (1+ x)))
-;; ad-do-it))
-;; foo
-;;
-;; (foo 3)
-;; 8
-;;
-;; Again, let's see what the definition of `foo' looks like so far:
-;;
-;; (symbol-function 'foo)
-;; (lambda (x)
-;; "$ad-doc: foo$"
-;; (interactive (list 5))
-;; (let (ad-return-value)
-;; (setq x (1- x))
-;; (setq x (1+ x))
-;; (let ((x (* x 2)))
-;; (let ((x (1+ x)))
-;; (setq ad-return-value (ad-Orig-foo x))))
-;; ad-return-value))
-;;
-;; @@ Controlling advice activation:
-;; =================================
-;; In every `defadvice' so far we have used the flag `activate' to activate
-;; the advice immediately after its definition, and that's what we want in
-;; most cases. However, if we define multiple pieces of advice for a single
-;; function then activating every advice immediately is inefficient. A
-;; better way to do this is to only activate the last defined advice.
-;; For example:
-;;
-;; (defadvice foo (after fg-times-x)
-;; "Multiply the result with X."
-;; (setq ad-return-value (* ad-return-value x)))
-;; foo
-;;
-;; This still yields the same result as before:
-;; (foo 3)
-;; 8
-;;
-;; Now we define another advice and activate which will also activate the
-;; previous advice `fg-times-x'. Note the use of the special variable
-;; `ad-return-value' in the body of the advice which is set to the result of
-;; the original function. If we change its value then the value returned by
-;; the advised function will be changed accordingly:
-;;
-;; (defadvice foo (after fg-times-x-again act)
-;; "Again multiply the result with X."
-;; (setq ad-return-value (* ad-return-value x)))
-;; foo
-;;
-;; Now the advices have an effect:
-;;
-;; (foo 3)
-;; 72
-;;
-;; @@ Protecting advice execution:
-;; ===============================
-;; Once in a while we define an advice to perform some cleanup action,
-;; for example:
-;;
-;; (defadvice foo (after fg-cleanup last act)
-;; "Do some cleanup."
-;; (print "Let's clean up now!"))
-;; foo
-;;
-;; However, in case of an error the cleanup won't be performed:
-;;
-;; (condition-case error
-;; (foo t)
-;; (error 'error-in-foo))
-;; error-in-foo
-;;
-;; To make sure a certain piece of advice gets executed even if some error or
-;; non-local exit occurred in any preceding code, we can protect it by using
-;; the `protect' keyword. (if any of the around advices is protected then the
-;; whole around advice onion will be protected):
-;;
-;; (defadvice foo (after fg-cleanup prot act)
-;; "Do some protected cleanup."
-;; (print "Let's clean up now!"))
-;; foo
-;;
-;; Now the cleanup form will be executed even in case of an error:
-;;
-;; (condition-case error
-;; (foo t)
-;; (error 'error-in-foo))
-;; "Let's clean up now!"
-;; error-in-foo
-;;
-;; Again, let's see what `foo' looks like:
-;;
-;; (symbol-function 'foo)
-;; (lambda (x)
-;; "$ad-doc: foo$"
-;; (interactive (list 5))
-;; (let (ad-return-value)
-;; (unwind-protect
-;; (progn (setq x (1- x))
-;; (setq x (1+ x))
-;; (let ((x (* x 2)))
-;; (let ((x (1+ x)))
-;; (setq ad-return-value (ad-Orig-foo x))))
-;; (setq ad-return-value (* ad-return-value x))
-;; (setq ad-return-value (* ad-return-value x)))
-;; (print "Let's clean up now!"))
-;; ad-return-value))
-;;
-;; @@ Compilation of advised definitions:
-;; ======================================
-;; Finally, we can specify the `compile' keyword in a `defadvice' to say
-;; that we want the resulting advised function to be byte-compiled
-;; (`compile' will be ignored unless we also specified `activate'):
-;;
-;; (defadvice foo (after fg-cleanup prot act comp)
-;; "Do some protected cleanup."
-;; (print "Let's clean up now!"))
-;; foo
-;;
-;; Now `foo' is byte-compiled:
-;;
-;; (symbol-function 'foo)
-;; (lambda (x)
-;; "$ad-doc: foo$"
-;; (interactive (byte-code "....." [5] 1))
-;; (byte-code "....." [ad-return-value x nil ((byte-code "....." [print "Let's clean up now!"] 2)) * 2 ad-Orig-foo] 6))
-;;
-;; (foo 3)
-;; "Let's clean up now!"
-;; 72
-;;
-;; @@ Enabling and disabling pieces of advice:
-;; ===========================================
-;; Once in a while it is desirable to temporarily disable a piece of advice
-;; so that it won't be considered during activation, for example, if two
-;; different packages advise the same function and one wants to temporarily
-;; neutralize the effect of the advice of one of the packages.
-;;
-;; The following disables the after advice `fg-times-x' in the function `foo'.
-;; All that does is to change a flag for this particular advice. All the
-;; other information defining it will be left unchanged (e.g., its relative
-;; position in this advice class, etc.).
-;;
-;; (ad-disable-advice 'foo 'after 'fg-times-x)
-;; nil
-;;
-;; For this to have an effect we have to activate `foo':
-;;
-;; (ad-activate 'foo)
-;; foo
-;;
-;; (foo 3)
-;; "Let's clean up now!"
-;; 24
-;;
-;; If we want to disable all multiplication advices in `foo' we can use a
-;; regular expression that matches the names of such advices. Actually, any
-;; advice name that contains a match for the regular expression will be
-;; called a match. A special advice class `any' can be used to consider
-;; all advice classes:
-;;
-;; (ad-disable-advice 'foo 'any "^fg-.*times")
-;; nil
-;;
-;; (ad-activate 'foo)
-;; foo
-;;
-;; (foo 3)
-;; "Let's clean up now!"
-;; 5
-;;
-;; To enable the disabled advice we could use either `ad-enable-advice'
-;; similar to `ad-disable-advice', or as an alternative `ad-enable-regexp'
-;; which will enable matching advices in ALL currently advised functions.
-;; Hence, this can be used to dis/enable advices made by a particular
-;; package to a set of functions as long as that package obeys standard
-;; advice name conventions. We prefixed all advice names with `fg-', hence
-;; the following will do the trick (`ad-enable-regexp' returns the number
-;; of matched advices):
-;;
-;; (ad-enable-regexp "^fg-")
-;; 9
-;;
-;; The following will activate all currently active advised functions that
-;; contain some advice matched by the regular expression. This is a save
-;; way to update the activation of advised functions whose advice changed
-;; in some way or other without accidentally also activating currently
-;; deactivated functions:
-;;
-;; (ad-update-regexp "^fg-")
-;; nil
-;;
-;; (foo 3)
-;; "Let's clean up now!"
-;; 72
-;;
-;; Another use for the dis/enablement mechanism is to define a piece of advice
-;; and keep it "dormant" until a particular condition is satisfied, i.e., until
-;; then the advice will not be used during activation. The `disable' flag lets
-;; one do that with `defadvice':
-;;
-;; (defadvice foo (before fg-1-more dis)
-;; "Add yet 1 more."
-;; (setq x (1+ x)))
-;; foo
-;;
-;; (ad-activate 'foo)
-;; foo
-;;
-;; (foo 3)
-;; "Let's clean up now!"
-;; 72
-;;
-;; (ad-enable-advice 'foo 'before 'fg-1-more)
-;; nil
-;;
-;; (ad-activate 'foo)
-;; foo
-;;
-;; (foo 3)
-;; "Let's clean up now!"
-;; 160
-;;
-;; @@ Caching:
-;; ===========
-;; Advised definitions get cached to allow efficient activation/deactivation
-;; without having to reconstruct them if nothing in the advice-info of a
-;; function has changed. The following idiom can be used to temporarily
-;; deactivate functions that have a piece of advice defined by a certain
-;; package (we save the old definition to check out caching):
-;;
-;; (setq old-definition (symbol-function 'foo))
-;; (lambda (x) ....)
-;;
-;; (ad-deactivate-regexp "^fg-")
-;; nil
-;;
-;; (foo 3)
-;; 4
-;;
-;; (ad-activate-regexp "^fg-")
-;; nil
-;;
-;; (eq old-definition (symbol-function 'foo))
-;; t
-;;
-;; (foo 3)
-;; "Let's clean up now!"
-;; 160
-;;
-;; @@ Forward advice:
-;; ==================
-;; To enable automatic activation of forward advice we first have to set
-;; `ad-activate-on-definition' to t and restart advice:
-;;
-;; (setq ad-activate-on-definition t)
-;; t
-;;
-;; (ad-start-advice)
-;; (ad-activate-defined-function)
-;;
-;; Let's define a piece of advice for an undefined function:
-;;
-;; (defadvice bar (before fg-sub-1-more act)
-;; "Subtract one more from X."
-;; (setq x (1- x)))
-;; bar
-;;
-;; `bar' is not yet defined:
-;; (fboundp 'bar)
-;; nil
-;;
-;; Now we define it and the forward advice will get activated (only because
-;; `ad-activate-on-definition' was t when we started advice above with
-;; `ad-start-advice'):
-;;
-;; (defun bar (x)
-;; "Subtract 1 from X."
-;; (1- x))
-;; bar
-;;
-;; (bar 4)
-;; 2
-;;
-;; Redefinition will activate any available advice if the value of
-;; `ad-redefinition-action' is either `warn', `accept' or `discard':
-;;
-;; (defun bar (x)
-;; "Subtract 2 from X."
-;; (- x 2))
-;; bar
-;;
-;; (bar 4)
-;; 1
-;;
-;; @@ Preactivation:
-;; =================
-;; Constructing advised definitions is moderately expensive, hence, it is
-;; desirable to have a way to construct them at byte-compile time.
-;; Preactivation is a mechanism that allows one to do that.
-;;
-;; (defun fie (x)
-;; "Multiply X by 2."
-;; (* x 2))
-;; fie
-;;
-;; (defadvice fie (before fg-times-4 preact)
-;; "Multiply X by 4."
-;; (setq x (* x 2)))
-;; fie
-;;
-;; This advice did not affect `fie'...
-;;
-;; (fie 2)
-;; 4
-;;
-;; ...but it constructed a cached definition that will be used once `fie' gets
-;; activated as long as its current advice state is the same as it was during
-;; preactivation:
-;;
-;; (setq cached-definition (ad-get-cache-definition 'fie))
-;; (lambda (x) ....)
-;;
-;; (ad-activate 'fie)
-;; fie
-;;
-;; (eq cached-definition (symbol-function 'fie))
-;; t
-;;
-;; (fie 2)
-;; 8
-;;
-;; If you put a preactivating `defadvice' into a Lisp file that gets byte-
-;; compiled then the constructed advised definition will get compiled by
-;; the byte-compiler. For that to occur in a v18 emacs you have to put the
-;; `defadvice' inside a `defun' because the v18 compiler does not compile
-;; top-level forms other than `defun' or `defmacro', for example,
-;;
-;; (defun fg-defadvice-fum ()
-;; (defadvice fum (before fg-times-4 preact act)
-;; "Multiply X by 4."
-;; (setq x (* x 2))))
-;; fg-defadvice-fum
-;;
-;; So far, no `defadvice' for `fum' got executed, but when we compile
-;; `fg-defadvice-fum' the `defadvice' will be expanded by the byte compiler.
-;; In order for preactivation to be effective we have to have a proper
-;; definition of `fum' around at preactivation time, hence, we define it now:
-;;
-;; (defun fum (x)
-;; "Multiply X by 2."
-;; (* x 2))
-;; fum
-;;
-;; Now we compile the defining function which will construct an advised
-;; definition during expansion of the `defadvice', compile it and store it
-;; as part of the compiled `fg-defadvice-fum':
-;;
-;; (ad-compile-function 'fg-defadvice-fum)
-;; (lambda nil (byte-code ...))
-;;
-;; `fum' is still completely unaffected:
-;;
-;; (fum 2)
-;; 4
-;;
-;; (ad-get-advice-info 'fum)
-;; nil
-;;
-;; (fg-defadvice-fum)
-;; fum
-;;
-;; Now the advised version of `fum' is compiled because the compiled definition
-;; constructed during preactivation was used, even though we did not specify
-;; the `compile' flag:
-;;
-;; (symbol-function 'fum)
-;; (lambda (x)
-;; "$ad-doc: fum$"
-;; (byte-code "....." [ad-return-value x nil * 2 ad-Orig-fum] 4))
-;;
-;; (fum 2)
-;; 8
-;;
-;; A preactivated definition will only be used if it matches the current
-;; function definition and advice information. If it does not match it
-;; will simply be discarded and a new advised definition will be constructed
-;; from scratch. For example, let's first remove all advice-info for `fum':
-;;
-;; (ad-unadvise 'fum)
-;; (("fie") ("bar") ("foo") ...)
-;;
-;; And now define a new piece of advice:
-;;
-;; (defadvice fum (before fg-interactive act)
-;; "Make fum interactive."
-;; (interactive "nEnter x: "))
-;; fum
-;;
-;; When we now try to use a preactivation it will not be used because the
-;; current advice state is different from the one at preactivation time. This
-;; is no tragedy, everything will work as expected just not as efficient,
-;; because a new advised definition has to be constructed from scratch:
-;;
-;; (fg-defadvice-fum)
-;; fum
-;;
-;; A new uncompiled advised definition got constructed:
-;;
-;; (ad-compiled-p (symbol-function 'fum))
-;; nil
-;;
-;; (fum 2)
-;; 8
-;;
-;; MORAL: To get all the efficiency out of preactivation the function
-;; definition and advice state at preactivation time must be the same as the
-;; state at activation time. Preactivation does work with forward advice, all
-;; that's necessary is that the definition of the forward advised function is
-;; available when the `defadvice' with the preactivation gets compiled.
-;;
-;; @@ Portable argument access:
-;; ============================
-;; So far, we always used the actual argument variable names to access an
-;; argument in a piece of advice. For many advice applications this is
-;; perfectly ok and keeps advices simple. However, it decreases portability
-;; of advices because it assumes specific argument variable names. For example,
-;; if one advises a subr such as `eval-region' which then gets redefined by
-;; some package (e.g., edebug) into a function with different argument names,
-;; then a piece of advice written for `eval-region' that was written with
-;; the subr arguments in mind will break. Similar situations arise when one
-;; switches between major Emacs versions, e.g., certain subrs in v18 are
-;; functions in v19 and vice versa. Also, in v19s subr argument lists
-;; are available and will be used, while they are not available in v18.
-;;
-;; Argument access text macros allow one to access arguments of an advised
-;; function in a portable way without having to worry about all these
-;; possibilities. These macros will be translated into the proper access forms
-;; at activation time, hence, argument access will be as efficient as if
-;; the arguments had been used directly in the definition of the advice.
-;;
-;; (defun fuu (x y z)
-;; "Add 3 numbers."
-;; (+ x y z))
-;; fuu
-;;
-;; (fuu 1 1 1)
-;; 3
-;;
-;; Argument access macros specify actual arguments at a certain position.
-;; Position 0 access the first actual argument, position 1 the second etc.
-;; For example, the following advice adds 1 to each of the 3 arguments:
-;;
-;; (defadvice fuu (before fg-add-1-to-all act)
-;; "Adds 1 to all arguments."
-;; (ad-set-arg 0 (1+ (ad-get-arg 0)))
-;; (ad-set-arg 1 (1+ (ad-get-arg 1)))
-;; (ad-set-arg 2 (1+ (ad-get-arg 2))))
-;; fuu
-;;
-;; (fuu 1 1 1)
-;; 6
-;;
-;; Now suppose somebody redefines `fuu' with a rest argument. Our advice
-;; will still work because we used access macros (note, that automatic
-;; advice activation is still in effect, hence, the redefinition of `fuu'
-;; will automatically activate all its advice):
-;;
-;; (defun fuu (&rest numbers)
-;; "Add NUMBERS."
-;; (apply '+ numbers))
-;; fuu
-;;
-;; (fuu 1 1 1)
-;; 6
-;;
-;; (fuu 1 1 1 1 1 1)
-;; 9
-;;
-;; What's important to notice is that argument access macros access actual
-;; arguments regardless of how they got distributed onto argument variables.
-;; In Emacs Lisp the semantics of an actual argument is determined purely
-;; by position, hence, as long as nobody changes the semantics of what a
-;; certain actual argument at a certain position means the access macros
-;; will do the right thing.
-;;
-;; Because of &rest arguments we need a second kind of access macro that
-;; can access all actual arguments starting from a certain position:
-;;
-;; (defadvice fuu (before fg-print-args act)
-;; "Print all arguments."
-;; (print (ad-get-args 0)))
-;; fuu
-;;
-;; (fuu 1 2 3 4 5)
-;; (1 2 3 4 5)
-;; 18
-;;
-;; (defadvice fuu (before fg-set-args act)
-;; "Swaps 2nd and 3rd arg and discards all the rest."
-;; (ad-set-args 1 (list (ad-get-arg 2) (ad-get-arg 1))))
-;; fuu
-;;
-;; (fuu 1 2 3 4 4 4 4 4 4)
-;; (1 3 2)
-;; 9
-;;
-;; (defun fuu (x y z)
-;; "Add 3 numbers."
-;; (+ x y z))
-;;
-;; (fuu 1 2 3)
-;; (1 3 2)
-;; 9
-;;
-;; @@ Defining the argument list of an advised function:
-;; =====================================================
-;; Once in a while it might be desirable to advise a function and additionally
-;; give it an extra argument that controls the advised code, for example, one
-;; might want to make an interactive function sensitive to a prefix argument.
-;; For such cases `defadvice' allows the specification of an argument list
-;; for the advised function. Similar to the redefinition of interactive
-;; behavior, the first argument list specification found in the list of before/
-;; around/after advices will be used. Of course, the specified argument list
-;; should be downward compatible with the original argument list, otherwise
-;; functions that call the advised function with the original argument list
-;; in mind will break.
-;;
-;; (defun fii (x)
-;; "Add 1 to X."
-;; (1+ x))
-;; fii
-;;
-;; Now we advise `fii' to use an optional second argument that controls the
-;; amount of incrementation. A list following the (optional) position
-;; argument of the advice will be interpreted as an argument list
-;; specification. This means you cannot specify an empty argument list, and
-;; why would you want to anyway?
-;;
-;; (defadvice fii (before fg-inc-x (x &optional incr) act)
-;; "Increment X by INCR (default is 1)."
-;; (setq x (+ x (1- (or incr 1)))))
-;; fii
-;;
-;; (fii 3)
-;; 4
-;;
-;; (fii 3 2)
-;; 5
-;;
-;; @@ Specifying argument lists of subrs:
-;; ======================================
-;; The argument lists of subrs cannot be determined directly from Lisp.
-;; This means that Advice has to use `(&rest ad-subr-args)' as the
-;; argument list of the advised subr which is not very efficient. In Lemacs
-;; subr argument lists can be determined from their documentation string, in
-;; Emacs-19 this is the case for some but not all subrs. To accommodate
-;; for the cases where the argument lists cannot be determined (e.g., in a
-;; v18 Emacs) Advice comes with a specification mechanism that allows the
-;; advice programmer to tell advice what the argument list of a certain subr
-;; really is.
-;;
-;; In a v18 Emacs the following will return the &rest idiom:
-;;
-;; (ad-arglist (symbol-function 'car))
-;; (&rest ad-subr-args)
-;;
-;; To tell advice what the argument list of `car' really is we
-;; can do the following:
-;;
-;; (ad-define-subr-args 'car '(list))
-;; ((list))
-;;
-;; Now `ad-arglist' will return the proper argument list (this method is
-;; actually used by advice itself for the advised definition of `fset'):
-;;
-;; (ad-arglist (symbol-function 'car))
-;; (list)
-;;
-;; The defined argument list will be stored on the property list of the
-;; subr name symbol. When advice looks for a subr argument list it first
-;; checks for a definition on the property list, if that fails it tries
-;; to infer it from the documentation string and caches it on the property
-;; list if it was successful, otherwise `(&rest ad-subr-args)' will be used.
-;;
-;; @@ Advising interactive subrs:
-;; ==============================
-;; For the most part there is no difference between advising functions and
-;; advising subrs. There is one situation though where one might have to write
-;; slightly different advice code for subrs than for functions. This case
-;; arises when one wants to access subr arguments in a before/around advice
-;; when the arguments were determined by an interactive call to the subr.
-;; Advice cannot determine what `interactive' form determines the interactive
-;; behavior of the subr, hence, when it calls the original definition in an
-;; interactive subr invocation it has to use `call-interactively' to generate
-;; the proper interactive behavior. Thus up to that call the arguments of the
-;; interactive subr will be nil. For example, the following advice for
-;; `kill-buffer' will not work in an interactive invocation...
-;;
-;; (defadvice kill-buffer (before fg-kill-buffer-hook first act preact comp)
-;; (my-before-kill-buffer-hook (ad-get-arg 0)))
-;; kill-buffer
-;;
-;; ...because the buffer argument will be nil in that case. The way out of
-;; this dilemma is to provide an `interactive' specification that mirrors
-;; the interactive behavior of the unadvised subr, for example, the following
-;; will do the right thing even when `kill-buffer' is called interactively:
-;;
-;; (defadvice kill-buffer (before fg-kill-buffer-hook first act preact comp)
-;; (interactive "bKill buffer: ")
-;; (my-before-kill-buffer-hook (ad-get-arg 0)))
-;; kill-buffer
-;;
-;; @@ Advising macros:
-;; ===================
-;; Advising macros is slightly different because there are two significant
-;; time points in the invocation of a macro: Expansion and evaluation time.
-;; For an advised macro instead of evaluating the original definition we
-;; use `macroexpand', that is, changing argument values and binding
-;; environments by pieces of advice has an affect during macro expansion
-;; but not necessarily during evaluation. In particular, any side effects
-;; of pieces of advice will occur during macro expansion. To also affect
-;; the behavior during evaluation time one has to change the value of
-;; `ad-return-value' in a piece of after advice. For example:
-;;
-;; (defmacro foom (x)
-;; (` (list (, x))))
-;; foom
-;;
-;; (foom '(a))
-;; ((a))
-;;
-;; (defadvice foom (before fg-print-x act)
-;; "Print the value of X."
-;; (print x))
-;; foom
-;;
-;; The following works as expected because evaluation immediately follows
-;; macro expansion:
-;;
-;; (foom '(a))
-;; (quote (a))
-;; ((a))
-;;
-;; However, the printing happens during expansion (or byte-compile) time:
-;;
-;; (macroexpand '(foom '(a)))
-;; (quote (a))
-;; (list (quote (a)))
-;;
-;; If we want it to happen during evaluation time we have to do the
-;; following (first remove the old advice):
-;;
-;; (ad-remove-advice 'foom 'before 'fg-print-x)
-;; nil
-;;
-;; (defadvice foom (after fg-print-x act)
-;; "Print the value of X."
-;; (setq ad-return-value
-;; (` (progn (print (, x))
-;; (, ad-return-value)))))
-;; foom
-;;
-;; (macroexpand '(foom '(a)))
-;; (progn (print (quote (a))) (list (quote (a))))
-;;
-;; (foom '(a))
-;; (a)
-;; ((a))
-;;
-;; While this method might seem somewhat cumbersome, it is very general
-;; because it allows one to influence macro expansion as well as evaluation.
-;; In general, advising macros should be a rather rare activity anyway, in
-;; particular, because compile-time macro expansion takes away a lot of the
-;; flexibility and effectiveness of the advice mechanism. Macros that were
-;; compile-time expanded before the advice was activated will of course never
-;; exhibit the advised behavior.
-;;
-;; @@ Advising special forms:
-;; ==========================
-;; Now for something that should be even more rare than advising macros:
-;; Advising special forms. Because special forms are irregular in their
-;; argument evaluation behavior (e.g., `setq' evaluates the second but not
-;; the first argument) they have to be advised into macros. A dangerous
-;; consequence of this is that the byte-compiler will not recognize them
-;; as special forms anymore (well, in most cases) and use their expansion
-;; rather than the proper byte-code. Also, because the original definition
-;; of a special form cannot be `funcall'ed, `eval' has to be used instead
-;; which is less efficient.
-;;
-;; MORAL: Do not advise special forms unless you are completely sure about
-;; what you are doing (some of the forward advice behavior is
-;; implemented via advice of the special forms `defun' and `defmacro').
-;; As a safety measure one should always do `ad-deactivate-all' before
-;; one byte-compiles a file to avoid any interference of advised
-;; special forms.
-;;
-;; Apart from the safety concerns advising special forms is not any different
-;; from advising plain functions or subrs.
-
-
-;;; Code:
-
-;; @ Advice implementation:
-;; ========================
-
-;; @@ Compilation idiosyncrasies:
-;; ==============================
-
-;; `defadvice' expansion needs quite a few advice functions and variables,
-;; hence, I need to preload the file before it can be compiled. To avoid
-;; interference of bogus compiled files I always preload the source file:
-(provide 'advice-preload)
-;; During a normal load this is a noop:
-(require 'advice-preload "advice.el")
-
-
-(defmacro ad-lemacs-p ()
- ;;Expands into Non-nil constant if we run Lucid's version of Emacs-19.
- ;;Unselected conditional code will be optimized away during compilation.
- (string-match "Lucid" emacs-version))
-
-
-;; @@ Variable definitions:
-;; ========================
-
-(defconst ad-version "2.14")
-
-;;;###autoload
-(defvar ad-redefinition-action 'warn
- "*Defines what to do with redefinitions during Advice de/activation.
-Redefinition occurs if a previously activated function that already has an
-original definition associated with it gets redefined and then de/activated.
-In such a case we can either accept the current definition as the new
-original definition, discard the current definition and replace it with the
-old original, or keep it and raise an error. The values `accept', `discard',
-`error' or `warn' govern what will be done. `warn' is just like `accept' but
-it additionally prints a warning message. All other values will be
-interpreted as `error'.")
-
-;;;###autoload
-(defvar ad-default-compilation-action 'maybe
- "*Defines whether to compile advised definitions during activation.
-A value of `always' will result in unconditional compilation, `never' will
-always avoid compilation, `maybe' will compile if the byte-compiler is already
-loaded, and `like-original' will compile if the original definition of the
-advised function is compiled or a built-in function. Every other value will
-be interpreted as `maybe'. This variable will only be considered if the
-COMPILE argument of `ad-activate' was supplied as nil.")
-
-
-;; @@ Some utilities:
-;; ==================
-
-;; We don't want the local arguments to interfere with anything
-;; referenced in the supplied functions => the cryptic casing:
-(defun ad-substitute-tree (sUbTrEe-TeSt fUnCtIoN tReE)
- ;;"Substitutes qualifying subTREEs with result of FUNCTION(subTREE).
- ;;Only proper subtrees are considered, for example, if TREE is (1 (2 (3)) 4)
- ;;then the subtrees will be 1 (2 (3)) 2 (3) 3 4, dotted structures are
- ;;allowed too. Once a qualifying subtree has been found its subtrees will
- ;;not be considered anymore. (ad-substitute-tree 'atom 'identity tree)
- ;;generates a copy of TREE."
- (cond ((consp tReE)
- (cons (if (funcall sUbTrEe-TeSt (car tReE))
- (funcall fUnCtIoN (car tReE))
- (if (consp (car tReE))
- (ad-substitute-tree sUbTrEe-TeSt fUnCtIoN (car tReE))
- (car tReE)))
- (ad-substitute-tree sUbTrEe-TeSt fUnCtIoN (cdr tReE))))
- ((funcall sUbTrEe-TeSt tReE)
- (funcall fUnCtIoN tReE))
- (t tReE)))
-
-;; this is just faster than `ad-substitute-tree':
-(defun ad-copy-tree (tree)
- ;;"Returns a copy of the list structure of TREE."
- (cond ((consp tree)
- (cons (ad-copy-tree (car tree))
- (ad-copy-tree (cdr tree))))
- (t tree)))
-
-(defmacro ad-dolist (varform &rest body)
- "A Common-Lisp-style dolist iterator with the following syntax:
-
- (ad-dolist (VAR INIT-FORM [RESULT-FORM])
- BODY-FORM...)
-
-which will iterate over the list yielded by INIT-FORM binding VAR to the
-current head at every iteration. If RESULT-FORM is supplied its value will
-be returned at the end of the iteration, nil otherwise. The iteration can be
-exited prematurely with `(ad-do-return [VALUE])'."
- (let ((expansion
- (` (let ((ad-dO-vAr (, (car (cdr varform))))
- (, (car varform)))
- (while ad-dO-vAr
- (setq (, (car varform)) (car ad-dO-vAr))
- (,@ body)
- ;;work around a backquote bug:
- ;;(` ((,@ '(foo)) (bar))) => (append '(foo) '(((bar)))) wrong
- ;;(` ((,@ '(foo)) (, '(bar)))) => (append '(foo) (list '(bar)))
- (, '(setq ad-dO-vAr (cdr ad-dO-vAr))))
- (, (car (cdr (cdr varform))))))))
- ;;ok, this wastes some cons cells but only during compilation:
- (if (catch 'contains-return
- (ad-substitute-tree
- (function (lambda (subtree)
- (cond ((eq (car-safe subtree) 'ad-dolist))
- ((eq (car-safe subtree) 'ad-do-return)
- (throw 'contains-return t)))))
- 'identity body)
- nil)
- (` (catch 'ad-dO-eXiT (, expansion)))
- expansion)))
-
-(defmacro ad-do-return (value)
- (` (throw 'ad-dO-eXiT (, value))))
-
-(if (not (get 'ad-dolist 'lisp-indent-hook))
- (put 'ad-dolist 'lisp-indent-hook 1))
-
-
-;; @@ Save real definitions of subrs used by Advice:
-;; =================================================
-;; Advice depends on the real, unmodified functionality of various subrs,
-;; we save them here so advised versions will not interfere (eventually,
-;; we will save all subrs used in code generated by Advice):
-
-(defmacro ad-save-real-definition (function)
- (let ((saved-function (intern (format "ad-real-%s" function))))
- ;; Make sure the compiler is loaded during macro expansion:
- (require 'byte-compile "bytecomp")
- (` (if (not (fboundp '(, saved-function)))
- (progn (fset '(, saved-function) (symbol-function '(, function)))
- ;; Copy byte-compiler properties:
- (,@ (if (get function 'byte-compile)
- (` ((put '(, saved-function) 'byte-compile
- '(, (get function 'byte-compile)))))))
- (,@ (if (get function 'byte-opcode)
- (` ((put '(, saved-function) 'byte-opcode
- '(, (get function 'byte-opcode))))))))))))
-
-(defun ad-save-real-definitions ()
- ;; Macro expansion will hardcode the values of the various byte-compiler
- ;; properties into the compiled version of this function such that the
- ;; proper values will be available at runtime without loading the compiler:
- (ad-save-real-definition fset)
- (ad-save-real-definition documentation))
-
-(ad-save-real-definitions)
-
-
-;; @@ Advice info access fns:
-;; ==========================
-
-;; Advice information for a particular function is stored on the
-;; advice-info property of the function symbol. It is stored as an
-;; alist of the following format:
-;;
-;; ((active . t/nil)
-;; (before adv1 adv2 ...)
-;; (around adv1 adv2 ...)
-;; (after adv1 adv2 ...)
-;; (activation adv1 adv2 ...)
-;; (deactivation adv1 adv2 ...)
-;; (origname . <symbol fbound to origdef>)
-;; (cache . (<advised-definition> . <id>)))
-
-;; List of currently advised though not necessarily activated functions
-;; (this list is maintained as a completion table):
-(defvar ad-advised-functions nil)
-
-(defmacro ad-pushnew-advised-function (function)
- ;;"Add FUNCTION to `ad-advised-functions' unless its already there."
- (` (if (not (assoc (symbol-name (, function)) ad-advised-functions))
- (setq ad-advised-functions
- (cons (list (symbol-name (, function)))
- ad-advised-functions)))))
-
-(defmacro ad-pop-advised-function (function)
- ;;"Remove FUNCTION from `ad-advised-functions'."
- (` (setq ad-advised-functions
- (delq (assoc (symbol-name (, function)) ad-advised-functions)
- ad-advised-functions))))
-
-(defmacro ad-do-advised-functions (varform &rest body)
- ;;"`ad-dolist'-style iterator that maps over `ad-advised-functions'.
- ;; (ad-do-advised-functions (VAR [RESULT-FORM])
- ;; BODY-FORM...)
- ;;Also see `ad-dolist'. On each iteration VAR will be bound to the
- ;;name of an advised function (a symbol)."
- (` (ad-dolist ((, (car varform))
- ad-advised-functions
- (, (car (cdr varform))))
- (setq (, (car varform)) (intern (car (, (car varform)))))
- (,@ body))))
-
-(if (not (get 'ad-do-advised-functions 'lisp-indent-hook))
- (put 'ad-do-advised-functions 'lisp-indent-hook 1))
-
-(defmacro ad-get-advice-info (function)
- (` (get (, function) 'ad-advice-info)))
-
-(defmacro ad-set-advice-info (function advice-info)
- (` (put (, function) 'ad-advice-info (, advice-info))))
-
-(defmacro ad-copy-advice-info (function)
- (` (ad-copy-tree (get (, function) 'ad-advice-info))))
-
-(defmacro ad-is-advised (function)
- ;;"Returns non-nil if FUNCTION has any advice info associated with it.
- ;;This does not mean that the advice is also active."
- (list 'ad-get-advice-info function))
-
-(defun ad-initialize-advice-info (function)
- ;;"Initializes the advice info for FUNCTION.
- ;;Assumes that FUNCTION has not yet been advised."
- (ad-pushnew-advised-function function)
- (ad-set-advice-info function (list (cons 'active nil))))
-
-(defmacro ad-get-advice-info-field (function field)
- ;;"Retrieves the value of the advice info FIELD of FUNCTION."
- (` (cdr (assq (, field) (ad-get-advice-info (, function))))))
-
-(defun ad-set-advice-info-field (function field value)
- ;;"Destructively modifies VALUE of the advice info FIELD of FUNCTION."
- (and (ad-is-advised function)
- (cond ((assq field (ad-get-advice-info function))
- ;; A field with that name is already present:
- (rplacd (assq field (ad-get-advice-info function)) value))
- (t;; otherwise, create a new field with that name:
- (nconc (ad-get-advice-info function)
- (list (cons field value)))))))
-
-;; Don't make this a macro so we can use it as a predicate:
-(defun ad-is-active (function)
- ;;"non-nil if FUNCTION is advised and activated."
- (ad-get-advice-info-field function 'active))
-
-
-;; @@ Access fns for single pieces of advice and related predicates:
-;; =================================================================
-
-(defun ad-make-advice (name protect enable definition)
- "Constructs single piece of advice to be stored in some advice-info.
-NAME should be a non-nil symbol, PROTECT and ENABLE should each be
-either t or nil, and DEFINITION should be a list of the form
-`(advice lambda ARGLIST [DOCSTRING] [INTERACTIVE-FORM] BODY...)'."
- (list name protect enable definition))
-
-;; ad-find-advice uses the alist structure directly ->
-;; change if this data structure changes!!
-(defmacro ad-advice-name (advice)
- (list 'car advice))
-(defmacro ad-advice-protected (advice)
- (list 'nth 1 advice))
-(defmacro ad-advice-enabled (advice)
- (list 'nth 2 advice))
-(defmacro ad-advice-definition (advice)
- (list 'nth 3 advice))
-
-(defun ad-advice-set-enabled (advice flag)
- (rplaca (cdr (cdr advice)) flag))
-
-(defun ad-class-p (thing)
- (memq thing ad-advice-classes))
-(defun ad-name-p (thing)
- (and thing (symbolp thing)))
-(defun ad-position-p (thing)
- (or (natnump thing)
- (memq thing '(first last))))
-
-
-;; @@ Advice access functions:
-;; ===========================
-
-;; List of defined advice classes:
-(defvar ad-advice-classes '(before around after activation deactivation))
-
-(defun ad-has-enabled-advice (function class)
- ;;"True if at least one of FUNCTION's advices in CLASS is enabled."
- (ad-dolist (advice (ad-get-advice-info-field function class))
- (if (ad-advice-enabled advice) (ad-do-return t))))
-
-(defun ad-has-redefining-advice (function)
- ;;"True if FUNCTION's advice info defines at least 1 redefining advice.
- ;;Redefining advices affect the construction of an advised definition."
- (and (ad-is-advised function)
- (or (ad-has-enabled-advice function 'before)
- (ad-has-enabled-advice function 'around)
- (ad-has-enabled-advice function 'after))))
-
-(defun ad-has-any-advice (function)
- ;;"True if the advice info of FUNCTION defines at least one advice."
- (and (ad-is-advised function)
- (ad-dolist (class ad-advice-classes nil)
- (if (ad-get-advice-info-field function class)
- (ad-do-return t)))))
-
-(defun ad-get-enabled-advices (function class)
- ;;"Returns the list of enabled advices of FUNCTION in CLASS."
- (let (enabled-advices)
- (ad-dolist (advice (ad-get-advice-info-field function class))
- (if (ad-advice-enabled advice)
- (setq enabled-advices (cons advice enabled-advices))))
- (reverse enabled-advices)))
-
-
-;; @@ Dealing with automatic advice activation via `fset/defalias':
-;; ================================================================
-
-;; Since Emacs 19.26 the built-in versions of `fset' and `defalias'
-;; take care of automatic advice activation, hence, we don't have to
-;; hack it anymore by advising `fset/defun/defmacro/byte-code/etc'.
-
-;; The functionality of the new `fset' is as follows:
-;;
-;; fset(sym,newdef)
-;; assign NEWDEF to SYM
-;; if (get SYM 'ad-advice-info)
-;; ad-activate(SYM, nil)
-;; return (symbol-function SYM)
-;;
-;; Whether advised definitions created by automatic activations will be
-;; compiled depends on the value of `ad-default-compilation-action'.
-
-;; Since calling `ad-activate' in the built-in definition of `fset' can
-;; create major disasters we have to be a bit careful. One precaution is
-;; to provide a dummy definition for `ad-activate' which can be used to
-;; turn off automatic advice activation (e.g., when `ad-stop-advice' or
-;; `ad-recover-normality' are called). Another is to avoid recursive calls
-;; to `ad-activate-on' by using `ad-with-auto-activation-disabled' where
-;; appropriate, especially in a safe version of `fset'.
-
-;; For now define `ad-activate' to the dummy definition:
-(defun ad-activate (function &optional compile)
- "Automatic advice activation is disabled. `ad-start-advice' enables it."
- nil)
-
-;; This is just a copy of the above:
-(defun ad-activate-off (function &optional compile)
- "Automatic advice activation is disabled. `ad-start-advice' enables it."
- nil)
-
-;; This will be t for top-level calls to `ad-activate-on':
-(defvar ad-activate-on-top-level t)
-
-(defmacro ad-with-auto-activation-disabled (&rest body)
- (` (let ((ad-activate-on-top-level nil))
- (,@ body))))
-
-(defun ad-safe-fset (symbol definition)
- ;; A safe `fset' which will never call `ad-activate' recursively.
- (ad-with-auto-activation-disabled
- (ad-real-fset symbol definition)))
-
-
-;; @@ Access functions for original definitions:
-;; ============================================
-;; The advice-info of an advised function contains its `origname' which is
-;; a symbol that is fbound to the original definition available at the first
-;; proper activation of the function after a legal re/definition. If the
-;; original was defined via fcell indirection then `origname' will be defined
-;; just so. Hence, to get hold of the actual original definition of a function
-;; we need to use `ad-real-orig-definition'.
-
-(defun ad-make-origname (function)
- ;;"Makes name to be used to call the original FUNCTION."
- (intern (format "ad-Orig-%s" function)))
-
-(defmacro ad-get-orig-definition (function)
- (` (let ((origname (ad-get-advice-info-field (, function) 'origname)))
- (if (fboundp origname)
- (symbol-function origname)))))
-
-(defmacro ad-set-orig-definition (function definition)
- (` (ad-safe-fset
- (ad-get-advice-info-field function 'origname) (, definition))))
-
-(defmacro ad-clear-orig-definition (function)
- (` (fmakunbound (ad-get-advice-info-field (, function) 'origname))))
-
-
-;; @@ Interactive input functions:
-;; ===============================
-
-(defun ad-read-advised-function (&optional prompt predicate default)
- ;;"Reads name of advised function with completion from the minibuffer.
- ;;An optional PROMPT will be used to prompt for the function. PREDICATE
- ;;plays the same role as for `try-completion' (which see). DEFAULT will
- ;;be returned on empty input (defaults to the first advised function for
- ;;which PREDICATE returns non-nil)."
- (if (null ad-advised-functions)
- (error "ad-read-advised-function: There are no advised functions"))
- (setq default
- (or default
- (ad-do-advised-functions (function)
- (if (or (null predicate)
- (funcall predicate function))
- (ad-do-return function)))
- (error "ad-read-advised-function: %s"
- "There are no qualifying advised functions")))
- (let* ((ad-pReDiCaTe predicate)
- (function
- (completing-read
- (format "%s(default %s) " (or prompt "Function: ") default)
- ad-advised-functions
- (if predicate
- (function
- (lambda (function)
- ;; Oops, no closures - the joys of dynamic scoping:
- ;; `predicate' clashed with the `predicate' argument
- ;; of Lemacs' `completing-read'.....
- (funcall ad-pReDiCaTe (intern (car function))))))
- t)))
- (if (equal function "")
- (if (ad-is-advised default)
- default
- (error "ad-read-advised-function: `%s' is not advised" default))
- (intern function))))
-
-(defvar ad-advice-class-completion-table
- (mapcar '(lambda (class) (list (symbol-name class)))
- ad-advice-classes))
-
-(defun ad-read-advice-class (function &optional prompt default)
- ;;"Reads a legal advice class with completion from the minibuffer.
- ;;An optional PROMPT will be used to prompt for the class. DEFAULT will
- ;;be returned on empty input (defaults to the first non-empty advice
- ;;class of FUNCTION)."
- (setq default
- (or default
- (ad-dolist (class ad-advice-classes)
- (if (ad-get-advice-info-field function class)
- (ad-do-return class)))
- (error "ad-read-advice-class: `%s' has no advices" function)))
- (let ((class (completing-read
- (format "%s(default %s) " (or prompt "Class: ") default)
- ad-advice-class-completion-table nil t)))
- (if (equal class "")
- default
- (intern class))))
-
-(defun ad-read-advice-name (function class &optional prompt)
- ;;"Reads name of existing advice of CLASS for FUNCTION with completion.
- ;;An optional PROMPT is used to prompt for the name."
- (let* ((name-completion-table
- (mapcar (function (lambda (advice)
- (list (symbol-name (ad-advice-name advice)))))
- (ad-get-advice-info-field function class)))
- (default
- (if (null name-completion-table)
- (error "ad-read-advice-name: `%s' has no %s advice"
- function class)
- (car (car name-completion-table))))
- (prompt (format "%s(default %s) " (or prompt "Name: ") default))
- (name (completing-read prompt name-completion-table nil t)))
- (if (equal name "")
- (intern default)
- (intern name))))
-
-(defun ad-read-advice-specification (&optional prompt)
- ;;"Reads a complete function/class/name specification from minibuffer.
- ;;The list of read symbols will be returned. The optional PROMPT will
- ;;be used to prompt for the function."
- (let* ((function (ad-read-advised-function prompt))
- (class (ad-read-advice-class function))
- (name (ad-read-advice-name function class)))
- (list function class name)))
-
-;; Use previous regexp as a default:
-(defvar ad-last-regexp "")
-
-(defun ad-read-regexp (&optional prompt)
- ;;"Reads a regular expression from the minibuffer."
- (let ((regexp (read-from-minibuffer
- (concat (or prompt "Regular expression: ")
- (if (equal ad-last-regexp "") ""
- (format "(default \"%s\") " ad-last-regexp))))))
- (setq ad-last-regexp
- (if (equal regexp "") ad-last-regexp regexp))))
-
-
-;; @@ Finding, enabling, adding and removing pieces of advice:
-;; ===========================================================
-
-(defmacro ad-find-advice (function class name)
- ;;"Finds the first advice of FUNCTION in CLASS with NAME."
- (` (assq (, name) (ad-get-advice-info-field (, function) (, class)))))
-
-(defun ad-advice-position (function class name)
- ;;"Returns position of first advice of FUNCTION in CLASS with NAME."
- (let* ((found-advice (ad-find-advice function class name))
- (advices (ad-get-advice-info-field function class)))
- (if found-advice
- (- (length advices) (length (memq found-advice advices))))))
-
-(defun ad-find-some-advice (function class name)
- "Finds the first of FUNCTION's advices in CLASS matching NAME.
-NAME can be a symbol or a regular expression matching part of an advice name.
-If CLASS is `any' all legal advice classes will be checked."
- (if (ad-is-advised function)
- (let (found-advice)
- (ad-dolist (advice-class ad-advice-classes)
- (if (or (eq class 'any) (eq advice-class class))
- (setq found-advice
- (ad-dolist (advice (ad-get-advice-info-field
- function advice-class))
- (if (or (and (stringp name)
- (string-match
- name (symbol-name
- (ad-advice-name advice))))
- (eq name (ad-advice-name advice)))
- (ad-do-return advice)))))
- (if found-advice (ad-do-return found-advice))))))
-
-(defun ad-enable-advice-internal (function class name flag)
- ;;"Sets enable FLAG of FUNCTION's advices in CLASS matching NAME.
- ;;If NAME is a string rather than a symbol then it's interpreted as a regular
- ;;expression and all advices whose name contain a match for it will be
- ;;affected. If CLASS is `any' advices in all legal advice classes will be
- ;;considered. The number of changed advices will be returned (or nil if
- ;;FUNCTION was not advised)."
- (if (ad-is-advised function)
- (let ((matched-advices 0))
- (ad-dolist (advice-class ad-advice-classes)
- (if (or (eq class 'any) (eq advice-class class))
- (ad-dolist (advice (ad-get-advice-info-field
- function advice-class))
- (cond ((or (and (stringp name)
- (string-match
- name (symbol-name (ad-advice-name advice))))
- (eq name (ad-advice-name advice)))
- (setq matched-advices (1+ matched-advices))
- (ad-advice-set-enabled advice flag))))))
- matched-advices)))
-
-(defun ad-enable-advice (function class name)
- "Enables the advice of FUNCTION with CLASS and NAME."
- (interactive (ad-read-advice-specification "Enable advice of: "))
- (if (ad-is-advised function)
- (if (eq (ad-enable-advice-internal function class name t) 0)
- (error "ad-enable-advice: `%s' has no %s advice matching `%s'"
- function class name))
- (error "ad-enable-advice: `%s' is not advised" function)))
-
-(defun ad-disable-advice (function class name)
- "Disables the advice of FUNCTION with CLASS and NAME."
- (interactive (ad-read-advice-specification "Disable advice of: "))
- (if (ad-is-advised function)
- (if (eq (ad-enable-advice-internal function class name nil) 0)
- (error "ad-disable-advice: `%s' has no %s advice matching `%s'"
- function class name))
- (error "ad-disable-advice: `%s' is not advised" function)))
-
-(defun ad-enable-regexp-internal (regexp class flag)
- ;;"Sets enable FLAGs of all CLASS advices whose name contains a REGEXP match.
- ;;If CLASS is `any' all legal advice classes are considered. The number of
- ;;affected advices will be returned."
- (let ((matched-advices 0))
- (ad-do-advised-functions (advised-function)
- (setq matched-advices
- (+ matched-advices
- (or (ad-enable-advice-internal
- advised-function class regexp flag)
- 0))))
- matched-advices))
-
-(defun ad-enable-regexp (regexp)
- "Enables all advices with names that contain a match for REGEXP.
-All currently advised functions will be considered."
- (interactive
- (list (ad-read-regexp "Enable advices via regexp: ")))
- (let ((matched-advices (ad-enable-regexp-internal regexp 'any t)))
- (if (interactive-p)
- (message "%d matching advices enabled" matched-advices))
- matched-advices))
-
-(defun ad-disable-regexp (regexp)
- "Disables all advices with names that contain a match for REGEXP.
-All currently advised functions will be considered."
- (interactive
- (list (ad-read-regexp "Disable advices via regexp: ")))
- (let ((matched-advices (ad-enable-regexp-internal regexp 'any nil)))
- (if (interactive-p)
- (message "%d matching advices disabled" matched-advices))
- matched-advices))
-
-(defun ad-remove-advice (function class name)
- "Removes FUNCTION's advice with NAME from its advices in CLASS.
-If such an advice was found it will be removed from the list of advices
-in that CLASS."
- (interactive (ad-read-advice-specification "Remove advice of: "))
- (if (ad-is-advised function)
- (let* ((advice-to-remove (ad-find-advice function class name)))
- (if advice-to-remove
- (ad-set-advice-info-field
- function class
- (delq advice-to-remove (ad-get-advice-info-field function class)))
- (error "ad-remove-advice: `%s' has no %s advice `%s'"
- function class name)))
- (error "ad-remove-advice: `%s' is not advised" function)))
-
-;;;###autoload
-(defun ad-add-advice (function advice class position)
- "Adds a piece of ADVICE to FUNCTION's list of advices in CLASS.
-If FUNCTION already has one or more pieces of advice of the specified
-CLASS then POSITION determines where the new piece will go. The value
-of POSITION can either be `first', `last' or a number where 0 corresponds
-to `first'. Numbers outside the range will be mapped to the closest
-extreme position. If there was already a piece of ADVICE with the same
-name, then the position argument will be ignored and the old advice
-will be overwritten with the new one.
- If the FUNCTION was not advised already, then its advice info will be
-initialized. Redefining a piece of advice whose name is part of the cache-id
-will clear the cache."
- (cond ((not (ad-is-advised function))
- (ad-initialize-advice-info function)
- (ad-set-advice-info-field
- function 'origname (ad-make-origname function))))
- (let* ((previous-position
- (ad-advice-position function class (ad-advice-name advice)))
- (advices (ad-get-advice-info-field function class))
- ;; Determine a numerical position for the new advice:
- (position (cond (previous-position)
- ((eq position 'first) 0)
- ((eq position 'last) (length advices))
- ((numberp position)
- (max 0 (min position (length advices))))
- (t 0))))
- ;; Check whether we have to clear the cache:
- (if (memq (ad-advice-name advice) (ad-get-cache-class-id function class))
- (ad-clear-cache function))
- (if previous-position
- (setcar (nthcdr position advices) advice)
- (if (= position 0)
- (ad-set-advice-info-field function class (cons advice advices))
- (setcdr (nthcdr (1- position) advices)
- (cons advice (nthcdr position advices)))))))
-
-
-;; @@ Accessing and manipulating function definitions:
-;; ===================================================
-
-(defmacro ad-macrofy (definition)
- ;;"Takes a lambda function DEFINITION and makes a macro out of it."
- (` (cons 'macro (, definition))))
-
-(defmacro ad-lambdafy (definition)
- ;;"Takes a macro function DEFINITION and makes a lambda out of it."
- (` (cdr (, definition))))
-
-;; There is no way to determine whether some subr is a special form or not,
-;; hence we need this list (which is probably out of date):
-(defvar ad-special-forms
- (mapcar 'symbol-function
- '(and catch cond condition-case defconst defmacro
- defun defvar function if interactive let let*
- or prog1 prog2 progn quote save-excursion
- save-restriction save-window-excursion setq
- setq-default unwind-protect while
- with-output-to-temp-buffer)))
-
-(defmacro ad-special-form-p (definition)
- ;;"non-nil if DEFINITION is a special form."
- (list 'memq definition 'ad-special-forms))
-
-(defmacro ad-interactive-p (definition)
- ;;"non-nil if DEFINITION can be called interactively."
- (list 'commandp definition))
-
-(defmacro ad-subr-p (definition)
- ;;"non-nil if DEFINITION is a subr."
- (list 'subrp definition))
-
-(defmacro ad-macro-p (definition)
- ;;"non-nil if DEFINITION is a macro."
- (` (eq (car-safe (, definition)) 'macro)))
-
-(defmacro ad-lambda-p (definition)
- ;;"non-nil if DEFINITION is a lambda expression."
- (` (eq (car-safe (, definition)) 'lambda)))
-
-;; see ad-make-advice for the format of advice definitions:
-(defmacro ad-advice-p (definition)
- ;;"non-nil if DEFINITION is a piece of advice."
- (` (eq (car-safe (, definition)) 'advice)))
-
-;; Emacs/Lemacs cross-compatibility
-;; (compiled-function-p is an obsolete function in Emacs):
-(if (and (not (fboundp 'byte-code-function-p))
- (fboundp 'compiled-function-p))
- (ad-safe-fset 'byte-code-function-p 'compiled-function-p))
-
-(defmacro ad-compiled-p (definition)
- ;;"non-nil if DEFINITION is a compiled byte-code object."
- (` (or (byte-code-function-p (, definition))
- (and (ad-macro-p (, definition))
- (byte-code-function-p (ad-lambdafy (, definition)))))))
-
-(defmacro ad-compiled-code (compiled-definition)
- ;;"Returns the byte-code object of a COMPILED-DEFINITION."
- (` (if (ad-macro-p (, compiled-definition))
- (ad-lambdafy (, compiled-definition))
- (, compiled-definition))))
-
-(defun ad-lambda-expression (definition)
- ;;"Returns the lambda expression of a function/macro/advice DEFINITION."
- (cond ((ad-lambda-p definition)
- definition)
- ((ad-macro-p definition)
- (ad-lambdafy definition))
- ((ad-advice-p definition)
- (cdr definition))
- (t nil)))
-
-(defun ad-arglist (definition &optional name)
- ;;"Returns the argument list of DEFINITION.
- ;;If DEFINITION could be from a subr then its NAME should be
- ;;supplied to make subr arglist lookup more efficient."
- (cond ((ad-compiled-p definition)
- (aref (ad-compiled-code definition) 0))
- ((consp definition)
- (car (cdr (ad-lambda-expression definition))))
- ((ad-subr-p definition)
- (if name
- (ad-subr-arglist name)
- ;; otherwise get it from its printed representation:
- (setq name (format "%s" definition))
- (string-match "^#<subr \\([^>]+\\)>$" name)
- (ad-subr-arglist
- (intern (substring name (match-beginning 1) (match-end 1))))))))
-
-;; Store subr-args as `((arg1 arg2 ...))' so I can distinguish
-;; a defined empty arglist `(nil)' from an undefined arglist:
-(defmacro ad-define-subr-args (subr arglist)
- (` (put (, subr) 'ad-subr-arglist (list (, arglist)))))
-(defmacro ad-undefine-subr-args (subr)
- (` (put (, subr) 'ad-subr-arglist nil)))
-(defmacro ad-subr-args-defined-p (subr)
- (` (get (, subr) 'ad-subr-arglist)))
-(defmacro ad-get-subr-args (subr)
- (` (car (get (, subr) 'ad-subr-arglist))))
-
-(defun ad-subr-arglist (subr-name)
- ;;"Retrieve arglist of the subr with SUBR-NAME.
- ;;Either use the one stored under the `ad-subr-arglist' property,
- ;;or try to retrieve it from the docstring and cache it under
- ;;that property, or otherwise use `(&rest ad-subr-args)'."
- (cond ((ad-subr-args-defined-p subr-name)
- (ad-get-subr-args subr-name))
- ;; says jwz: Should use this for Lemacs 19.8 and above:
- ;;((fboundp 'subr-min-args)
- ;; ...)
- ;; says hans: I guess what Jamie means is that I should use the values
- ;; of `subr-min-args' and `subr-max-args' to construct the subr arglist
- ;; without having to look it up via parsing the docstring, e.g.,
- ;; values 1 and 2 would suggest `(arg1 &optional arg2)' as an
- ;; argument list. However, that won't work because there is no
- ;; way to distinguish a subr with args `(a &optional b &rest c)' from
- ;; one with args `(a &rest c)' using that mechanism. Also, the argument
- ;; names from the docstring are more meaningful. Hence, I'll stick with
- ;; the old way of doing things.
- (t (let ((doc (or (ad-real-documentation subr-name t) "")))
- (cond ((string-match "^\\(([^\)]+)\\)\n?\\'" doc)
- (ad-define-subr-args
- subr-name
- (cdr (car (read-from-string
- (downcase
- (substring doc
- (match-beginning 1)
- (match-end 1)))))))
- (ad-get-subr-args subr-name))
- ;; this is the old format used before Emacs 19.24:
- ((string-match
- "[\n\t ]*\narguments: ?\\((.*)\\)\n?\\'" doc)
- (ad-define-subr-args
- subr-name
- (car (read-from-string
- doc (match-beginning 1) (match-end 1))))
- (ad-get-subr-args subr-name))
- (t '(&rest ad-subr-args)))))))
-
-(defun ad-docstring (definition)
- ;;"Returns the unexpanded docstring of DEFINITION."
- (let ((docstring
- (if (ad-compiled-p definition)
- (ad-real-documentation definition t)
- (car (cdr (cdr (ad-lambda-expression definition)))))))
- (if (or (stringp docstring)
- (natnump docstring))
- docstring)))
-
-(defun ad-interactive-form (definition)
- ;;"Returns the interactive form of DEFINITION."
- (cond ((ad-compiled-p definition)
- (and (commandp definition)
- (list 'interactive (aref (ad-compiled-code definition) 5))))
- ((or (ad-advice-p definition)
- (ad-lambda-p definition))
- (commandp (ad-lambda-expression definition)))))
-
-(defun ad-body-forms (definition)
- ;;"Returns the list of body forms of DEFINITION."
- (cond ((ad-compiled-p definition)
- nil)
- ((consp definition)
- (nthcdr (+ (if (ad-docstring definition) 1 0)
- (if (ad-interactive-form definition) 1 0))
- (cdr (cdr (ad-lambda-expression definition)))))))
-
-;; Matches the docstring of an advised definition.
-;; The first group of the regexp matches the function name:
-(defvar ad-advised-definition-docstring-regexp "^\\$ad-doc: \\(.+\\)\\$$")
-
-(defun ad-make-advised-definition-docstring (function)
- ;; Makes an identifying docstring for the advised definition of FUNCTION.
- ;; Put function name into the documentation string so we can infer
- ;; the name of the advised function from the docstring. This is needed
- ;; to generate a proper advised docstring even if we are just given a
- ;; definition (also see the defadvice for `documentation'):
- (format "$ad-doc: %s$" (prin1-to-string function)))
-
-(defun ad-advised-definition-p (definition)
- ;;"non-nil if DEFINITION was generated from advice information."
- (if (or (ad-lambda-p definition)
- (ad-macro-p definition)
- (ad-compiled-p definition))
- (let ((docstring (ad-docstring definition)))
- (and (stringp docstring)
- (string-match
- ad-advised-definition-docstring-regexp docstring)))))
-
-(defun ad-definition-type (definition)
- ;;"Returns symbol that describes the type of DEFINITION."
- (if (ad-macro-p definition)
- 'macro
- (if (ad-subr-p definition)
- (if (ad-special-form-p definition)
- 'special-form
- 'subr)
- (if (or (ad-lambda-p definition)
- (ad-compiled-p definition))
- 'function
- (if (ad-advice-p definition)
- 'advice)))))
-
-(defun ad-has-proper-definition (function)
- ;;"True if FUNCTION is a symbol with a proper definition.
- ;;For that it has to be fbound with a non-autoload definition."
- (and (symbolp function)
- (fboundp function)
- (not (eq (car-safe (symbol-function function)) 'autoload))))
-
-;; The following two are necessary for the sake of packages such as
-;; ange-ftp which redefine functions via fcell indirection:
-(defun ad-real-definition (function)
- ;;"Finds FUNCTION's definition at the end of function cell indirection."
- (if (ad-has-proper-definition function)
- (let ((definition (symbol-function function)))
- (if (symbolp definition)
- (ad-real-definition definition)
- definition))))
-
-(defun ad-real-orig-definition (function)
- ;;"Finds FUNCTION's real original definition starting from its `origname'."
- (if (ad-is-advised function)
- (ad-real-definition (ad-get-advice-info-field function 'origname))))
-
-(defun ad-is-compilable (function)
- ;;"True if FUNCTION has an interpreted definition that can be compiled."
- (and (ad-has-proper-definition function)
- (or (ad-lambda-p (symbol-function function))
- (ad-macro-p (symbol-function function)))
- (not (ad-compiled-p (symbol-function function)))))
-
-(defun ad-compile-function (function)
- "Byte-compiles FUNCTION (or macro) if it is not yet compiled."
- (interactive "aByte-compile function: ")
- (if (ad-is-compilable function)
- ;; Need to turn off auto-activation
- ;; because `byte-compile' uses `fset':
- (ad-with-auto-activation-disabled
- (byte-compile function))))
-
-
-;; @@ Constructing advised definitions:
-;; ====================================
-;;
-;; Main design decisions about the form of advised definitions:
-;;
-;; A) How will original definitions be called?
-;; B) What will argument lists of advised functions look like?
-;;
-;; Ad A)
-;; I chose to use function indirection for all four types of original
-;; definitions (functions, macros, subrs and special forms), i.e., create
-;; a unique symbol `ad-Orig-<name>' which is fbound to the original
-;; definition and call it according to type and arguments. Functions and
-;; subrs that don't have any &rest arguments can be called directly in a
-;; `(ad-Orig-<name> ....)' form. If they have a &rest argument we have to
-;; use `apply'. Macros will be called with
-;; `(macroexpand '(ad-Orig-<name> ....))', and special forms also need a
-;; form like that with `eval' instead of `macroexpand'.
-;;
-;; Ad B)
-;; Use original arguments where possible and `(&rest ad-subr-args)'
-;; otherwise, even though this seems to be more complicated and less
-;; uniform than a general `(&rest args)' approach. My reason to still
-;; do it that way is that in most cases my approach leads to the more
-;; efficient form for the advised function, and portability (e.g., to
-;; make the same advice work regardless of whether something is a
-;; function or a subr) can still be achieved with argument access macros.
-
-
-(defun ad-prognify (forms)
- (cond ((<= (length forms) 1)
- (car forms))
- (t (cons 'progn forms))))
-
-;; @@@ Accessing argument lists:
-;; =============================
-
-(defun ad-parse-arglist (arglist)
- ;;"Parses ARGLIST into its required, optional and rest parameters.
- ;;A three-element list is returned, where the 1st element is the list of
- ;;required arguments, the 2nd is the list of optional arguments, and the 3rd
- ;;is the name of an optional rest parameter (or nil)."
- (let* (required optional rest)
- (setq rest (car (cdr (memq '&rest arglist))))
- (if rest (setq arglist (reverse (cdr (memq '&rest (reverse arglist))))))
- (setq optional (cdr (memq '&optional arglist)))
- (if optional
- (setq required (reverse (cdr (memq '&optional (reverse arglist)))))
- (setq required arglist))
- (list required optional rest)))
-
-(defun ad-retrieve-args-form (arglist)
- ;;"Generates a form which evaluates into names/values/types of ARGLIST.
- ;;When the form gets evaluated within a function with that argument list
- ;;it will result in a list with one entry for each argument, where the
- ;;first element of each entry is the name of the argument, the second
- ;;element is its actual current value, and the third element is either
- ;;`required', `optional' or `rest' depending on the type of the argument."
- (let* ((parsed-arglist (ad-parse-arglist arglist))
- (rest (nth 2 parsed-arglist)))
- (` (list
- (,@ (mapcar (function
- (lambda (req)
- (` (list '(, req) (, req) 'required))))
- (nth 0 parsed-arglist)))
- (,@ (mapcar (function
- (lambda (opt)
- (` (list '(, opt) (, opt) 'optional))))
- (nth 1 parsed-arglist)))
- (,@ (if rest (list (` (list '(, rest) (, rest) 'rest)))))
- ))))
-
-(defun ad-arg-binding-field (binding field)
- (cond ((eq field 'name) (car binding))
- ((eq field 'value) (car (cdr binding)))
- ((eq field 'type) (car (cdr (cdr binding))))))
-
-(defun ad-list-access (position list)
- (cond ((= position 0) list)
- ((= position 1) (list 'cdr list))
- (t (list 'nthcdr position list))))
-
-(defun ad-element-access (position list)
- (cond ((= position 0) (list 'car list))
- ((= position 1) (` (car (cdr (, list)))))
- (t (list 'nth position list))))
-
-(defun ad-access-argument (arglist index)
- ;;"Tells how to access ARGLIST's actual argument at position INDEX.
- ;;For a required/optional arg it simply returns it, if a rest argument has
- ;;to be accessed, it returns a list with the index and name."
- (let* ((parsed-arglist (ad-parse-arglist arglist))
- (reqopt-args (append (nth 0 parsed-arglist)
- (nth 1 parsed-arglist)))
- (rest-arg (nth 2 parsed-arglist)))
- (cond ((< index (length reqopt-args))
- (nth index reqopt-args))
- (rest-arg
- (list (- index (length reqopt-args)) rest-arg)))))
-
-(defun ad-get-argument (arglist index)
- ;;"Returns form to access ARGLIST's actual argument at position INDEX."
- (let ((argument-access (ad-access-argument arglist index)))
- (cond ((consp argument-access)
- (ad-element-access
- (car argument-access) (car (cdr argument-access))))
- (argument-access))))
-
-(defun ad-set-argument (arglist index value-form)
- ;;"Returns form to set ARGLIST's actual arg at INDEX to VALUE-FORM."
- (let ((argument-access (ad-access-argument arglist index)))
- (cond ((consp argument-access)
- ;; should this check whether there actually is something to set?
- (` (setcar (, (ad-list-access
- (car argument-access) (car (cdr argument-access))))
- (, value-form))))
- (argument-access
- (` (setq (, argument-access) (, value-form))))
- (t (error "ad-set-argument: No argument at position %d of `%s'"
- index arglist)))))
-
-(defun ad-get-arguments (arglist index)
- ;;"Returns form to access all actual arguments starting at position INDEX."
- (let* ((parsed-arglist (ad-parse-arglist arglist))
- (reqopt-args (append (nth 0 parsed-arglist)
- (nth 1 parsed-arglist)))
- (rest-arg (nth 2 parsed-arglist))
- args-form)
- (if (< index (length reqopt-args))
- (setq args-form (` (list (,@ (nthcdr index reqopt-args))))))
- (if rest-arg
- (if args-form
- (setq args-form (` (nconc (, args-form) (, rest-arg))))
- (setq args-form (ad-list-access (- index (length reqopt-args))
- rest-arg))))
- args-form))
-
-(defun ad-set-arguments (arglist index values-form)
- ;;"Makes form to assign elements of VALUES-FORM as actual ARGLIST args.
- ;;The assignment starts at position INDEX."
- (let ((values-index 0)
- argument-access set-forms)
- (while (setq argument-access (ad-access-argument arglist index))
- (if (symbolp argument-access)
- (setq set-forms
- (cons (ad-set-argument
- arglist index
- (ad-element-access values-index 'ad-vAlUeS))
- set-forms))
- (setq set-forms
- (cons (if (= (car argument-access) 0)
- (list 'setq
- (car (cdr argument-access))
- (ad-list-access values-index 'ad-vAlUeS))
- (list 'setcdr
- (ad-list-access (1- (car argument-access))
- (car (cdr argument-access)))
- (ad-list-access values-index 'ad-vAlUeS)))
- set-forms))
- ;; terminate loop
- (setq arglist nil))
- (setq index (1+ index))
- (setq values-index (1+ values-index)))
- (if (null set-forms)
- (error "ad-set-arguments: No argument at position %d of `%s'"
- index arglist)
- (if (= (length set-forms) 1)
- ;; For exactly one set-form we can use values-form directly,...
- (ad-substitute-tree
- (function (lambda (form) (eq form 'ad-vAlUeS)))
- (function (lambda (form) values-form))
- (car set-forms))
- ;; ...if we have more we have to bind it to a variable:
- (` (let ((ad-vAlUeS (, values-form)))
- (,@ (reverse set-forms))
- ;; work around the old backquote bug:
- (, 'ad-vAlUeS)))))))
-
-(defun ad-insert-argument-access-forms (definition arglist)
- ;;"Expands arg-access text macros in DEFINITION according to ARGLIST."
- (ad-substitute-tree
- (function
- (lambda (form)
- (or (eq form 'ad-arg-bindings)
- (and (memq (car-safe form)
- '(ad-get-arg ad-get-args ad-set-arg ad-set-args))
- (integerp (car-safe (cdr form)))))))
- (function
- (lambda (form)
- (if (eq form 'ad-arg-bindings)
- (ad-retrieve-args-form arglist)
- (let ((accessor (car form))
- (index (car (cdr form)))
- (val (car (cdr (ad-insert-argument-access-forms
- (cdr form) arglist)))))
- (cond ((eq accessor 'ad-get-arg)
- (ad-get-argument arglist index))
- ((eq accessor 'ad-set-arg)
- (ad-set-argument arglist index val))
- ((eq accessor 'ad-get-args)
- (ad-get-arguments arglist index))
- ((eq accessor 'ad-set-args)
- (ad-set-arguments arglist index val)))))))
- definition))
-
-;; @@@ Mapping argument lists:
-;; ===========================
-;; Here is the problem:
-;; Suppose function foo was called with (foo 1 2 3 4 5), and foo has the
-;; argument list (x y &rest z), and we want to call the function bar which
-;; has argument list (a &rest b) with a combination of x, y and z so that
-;; the effect is just as if we had called (bar 1 2 3 4 5) directly.
-;; The mapping should work for any two argument lists.
-
-(defun ad-map-arglists (source-arglist target-arglist)
- "Makes `funcall/apply' form to map SOURCE-ARGLIST to TARGET-ARGLIST.
-The arguments supplied to TARGET-ARGLIST will be taken from SOURCE-ARGLIST just
-as if they had been supplied to a function with TARGET-ARGLIST directly.
-Excess source arguments will be neglected, missing source arguments will be
-supplied as nil. Returns a `funcall' or `apply' form with the second element
-being `function' which has to be replaced by an actual function argument.
-Example: `(ad-map-arglists '(a &rest args) '(w x y z))' will return
- `(funcall function a (car args) (car (cdr args)) (nth 2 args))'."
- (let* ((parsed-source-arglist (ad-parse-arglist source-arglist))
- (source-reqopt-args (append (nth 0 parsed-source-arglist)
- (nth 1 parsed-source-arglist)))
- (source-rest-arg (nth 2 parsed-source-arglist))
- (parsed-target-arglist (ad-parse-arglist target-arglist))
- (target-reqopt-args (append (nth 0 parsed-target-arglist)
- (nth 1 parsed-target-arglist)))
- (target-rest-arg (nth 2 parsed-target-arglist))
- (need-apply (and source-rest-arg target-rest-arg))
- (target-arg-index -1))
- ;; This produces ``error-proof'' target function calls with the exception
- ;; of a case like (&rest a) mapped onto (x &rest y) where the actual args
- ;; supplied to A might not be enough to supply the required target arg X
- (append (list (if need-apply 'apply 'funcall) 'function)
- (cond (need-apply
- ;; `apply' can take care of that directly:
- (append source-reqopt-args (list source-rest-arg)))
- (t (mapcar (function
- (lambda (arg)
- (setq target-arg-index (1+ target-arg-index))
- (ad-get-argument
- source-arglist target-arg-index)))
- (append target-reqopt-args
- (and target-rest-arg
- ;; If we have a rest arg gobble up
- ;; remaining source args:
- (nthcdr (length target-reqopt-args)
- source-reqopt-args)))))))))
-
-(defun ad-make-mapped-call (source-arglist target-arglist target-function)
- ;;"Makes form to call TARGET-FUNCTION with args from SOURCE-ARGLIST."
- (let* ((mapped-form (ad-map-arglists source-arglist target-arglist)))
- (if (eq (car mapped-form) 'funcall)
- (cons target-function (cdr (cdr mapped-form)))
- (prog1 mapped-form
- (setcar (cdr mapped-form) (list 'quote target-function))))))
-
-;; @@@ Making an advised documentation string:
-;; ===========================================
-;; New policy: The documentation string for an advised function will be built
-;; at the time the advised `documentation' function is called. This has the
-;; following advantages:
-;; 1) command-key substitutions will automatically be correct
-;; 2) No wasted string space due to big advised docstrings in caches or
-;; compiled files that contain preactivations
-;; The overall overhead for this should be negligible because people normally
-;; don't lookup documentation for the same function over and over again.
-
-(defun ad-make-single-advice-docstring (advice class &optional style)
- (let ((advice-docstring (ad-docstring (ad-advice-definition advice))))
- (cond ((eq style 'plain)
- advice-docstring)
- ((eq style 'freeze)
- (format "Permanent %s-advice `%s':%s%s"
- class (ad-advice-name advice)
- (if advice-docstring "\n" "")
- (or advice-docstring "")))
- (t (format "%s-advice `%s':%s%s"
- (capitalize (symbol-name class)) (ad-advice-name advice)
- (if advice-docstring "\n" "")
- (or advice-docstring ""))))))
-
-(defun ad-make-advised-docstring (function &optional style)
- ;;"Constructs a documentation string for the advised FUNCTION.
- ;;It concatenates the original documentation with the documentation
- ;;strings of the individual pieces of advice which will be formatted
- ;;according to STYLE. STYLE can be `plain' or `freeze', everything else
- ;;will be interpreted as `default'. The order of the advice documentation
- ;;strings corresponds to before/around/after and the individual ordering
- ;;in any of these classes."
- (let* ((origdef (ad-real-orig-definition function))
- (origtype (symbol-name (ad-definition-type origdef)))
- (origdoc
- ;; Retrieve raw doc, key substitution will be taken care of later:
- (ad-real-documentation origdef t))
- paragraphs advice-docstring)
- (if origdoc (setq paragraphs (list origdoc)))
- (if (not (eq style 'plain))
- (setq paragraphs (cons (concat "This " origtype " is advised.")
- paragraphs)))
- (ad-dolist (class ad-advice-classes)
- (ad-dolist (advice (ad-get-enabled-advices function class))
- (setq advice-docstring
- (ad-make-single-advice-docstring advice class style))
- (if advice-docstring
- (setq paragraphs (cons advice-docstring paragraphs)))))
- (if paragraphs
- ;; separate paragraphs with blank lines:
- (mapconcat 'identity (nreverse paragraphs) "\n\n"))))
-
-(defun ad-make-plain-docstring (function)
- (ad-make-advised-docstring function 'plain))
-(defun ad-make-freeze-docstring (function)
- (ad-make-advised-docstring function 'freeze))
-
-;; @@@ Accessing overriding arglists and interactive forms:
-;; ========================================================
-
-(defun ad-advised-arglist (function)
- ;;"Finds first defined arglist in FUNCTION's redefining advices."
- (ad-dolist (advice (append (ad-get-enabled-advices function 'before)
- (ad-get-enabled-advices function 'around)
- (ad-get-enabled-advices function 'after)))
- (let ((arglist (ad-arglist (ad-advice-definition advice))))
- (if arglist
- ;; We found the first one, use it:
- (ad-do-return arglist)))))
-
-(defun ad-advised-interactive-form (function)
- ;;"Finds first interactive form in FUNCTION's redefining advices."
- (ad-dolist (advice (append (ad-get-enabled-advices function 'before)
- (ad-get-enabled-advices function 'around)
- (ad-get-enabled-advices function 'after)))
- (let ((interactive-form
- (ad-interactive-form (ad-advice-definition advice))))
- (if interactive-form
- ;; We found the first one, use it:
- (ad-do-return interactive-form)))))
-
-;; @@@ Putting it all together:
-;; ============================
-
-(defun ad-make-advised-definition (function)
- ;;"Generates an advised definition of FUNCTION from its advice info."
- (if (and (ad-is-advised function)
- (ad-has-redefining-advice function))
- (let* ((origdef (ad-real-orig-definition function))
- (origname (ad-get-advice-info-field function 'origname))
- (orig-interactive-p (ad-interactive-p origdef))
- (orig-subr-p (ad-subr-p origdef))
- (orig-special-form-p (ad-special-form-p origdef))
- (orig-macro-p (ad-macro-p origdef))
- ;; Construct the individual pieces that we need for assembly:
- (orig-arglist (ad-arglist origdef function))
- (advised-arglist (or (ad-advised-arglist function)
- orig-arglist))
- (advised-interactive-form (ad-advised-interactive-form function))
- (interactive-form
- (cond (orig-macro-p nil)
- (advised-interactive-form)
- ((ad-interactive-form origdef))
- ;; Otherwise we must have a subr: make it interactive if
- ;; we have to and initialize required arguments in case
- ;; it is called interactively:
- (orig-interactive-p
- (let ((reqargs (car (ad-parse-arglist advised-arglist))))
- (if reqargs
- (` (interactive
- '(, (make-list (length reqargs) nil))))
- '(interactive))))))
- (orig-form
- (cond ((or orig-special-form-p orig-macro-p)
- ;; Special forms and macros will be advised into macros.
- ;; The trick is to construct an expansion for the advised
- ;; macro that does the correct thing when it gets eval'ed.
- ;; For macros we'll just use the expansion of the original
- ;; macro and return that. This way compiled advised macros
- ;; will be expanded into something useful. Note that after
- ;; advices have full control over whether they want to
- ;; evaluate the expansion (the value of `ad-return-value')
- ;; at macro expansion time or not. For special forms there
- ;; is no solution that interacts reasonably with the
- ;; compiler, hence we just evaluate the original at macro
- ;; expansion time and return the result. The moral of that
- ;; is that one should always deactivate advised special
- ;; forms before one byte-compiles a file.
- (` ((, (if orig-macro-p
- 'macroexpand
- 'eval))
- (cons '(, origname)
- (, (ad-get-arguments advised-arglist 0))))))
- ((and orig-subr-p
- orig-interactive-p
- (not advised-interactive-form))
- ;; Check whether we were called interactively
- ;; in order to do proper prompting:
- (` (if (interactive-p)
- (call-interactively '(, origname))
- (, (ad-make-mapped-call
- orig-arglist advised-arglist origname)))))
- ;; And now for normal functions and non-interactive subrs
- ;; (or subrs whose interactive behavior was advised):
- (t (ad-make-mapped-call
- advised-arglist orig-arglist origname)))))
-
- ;; Finally, build the sucker:
- (ad-assemble-advised-definition
- (cond (orig-macro-p 'macro)
- (orig-special-form-p 'special-form)
- (t 'function))
- advised-arglist
- (ad-make-advised-definition-docstring function)
- interactive-form
- orig-form
- (ad-get-enabled-advices function 'before)
- (ad-get-enabled-advices function 'around)
- (ad-get-enabled-advices function 'after)))))
-
-(defun ad-assemble-advised-definition
- (type args docstring interactive orig &optional befores arounds afters)
-
- ;;"Assembles an original and its advices into an advised function.
- ;;It constructs a function or macro definition according to TYPE which has to
- ;;be either `macro', `function' or `special-form'. ARGS is the argument list
- ;;that has to be used, DOCSTRING if non-nil defines the documentation of the
- ;;definition, INTERACTIVE if non-nil is the interactive form to be used,
- ;;ORIG is a form that calls the body of the original unadvised function,
- ;;and BEFORES, AROUNDS and AFTERS are the lists of advices with which ORIG
- ;;should be modified. The assembled function will be returned."
-
- (let (before-forms around-form around-form-protected after-forms definition)
- (ad-dolist (advice befores)
- (cond ((and (ad-advice-protected advice)
- before-forms)
- (setq before-forms
- (` ((unwind-protect
- (, (ad-prognify before-forms))
- (,@ (ad-body-forms
- (ad-advice-definition advice))))))))
- (t (setq before-forms
- (append before-forms
- (ad-body-forms (ad-advice-definition advice)))))))
-
- (setq around-form (` (setq ad-return-value (, orig))))
- (ad-dolist (advice (reverse arounds))
- ;; If any of the around advices is protected then we
- ;; protect the complete around advice onion:
- (if (ad-advice-protected advice)
- (setq around-form-protected t))
- (setq around-form
- (ad-substitute-tree
- (function (lambda (form) (eq form 'ad-do-it)))
- (function (lambda (form) around-form))
- (ad-prognify (ad-body-forms (ad-advice-definition advice))))))
-
- (setq after-forms
- (if (and around-form-protected before-forms)
- (` ((unwind-protect
- (, (ad-prognify before-forms))
- (, around-form))))
- (append before-forms (list around-form))))
- (ad-dolist (advice afters)
- (cond ((and (ad-advice-protected advice)
- after-forms)
- (setq after-forms
- (` ((unwind-protect
- (, (ad-prognify after-forms))
- (,@ (ad-body-forms
- (ad-advice-definition advice))))))))
- (t (setq after-forms
- (append after-forms
- (ad-body-forms (ad-advice-definition advice)))))))
-
- (setq definition
- (` ((,@ (if (memq type '(macro special-form)) '(macro)))
- lambda
- (, args)
- (,@ (if docstring (list docstring)))
- (,@ (if interactive (list interactive)))
- (let (ad-return-value)
- (,@ after-forms)
- (, (if (eq type 'special-form)
- '(list 'quote ad-return-value)
- 'ad-return-value))))))
-
- (ad-insert-argument-access-forms definition args)))
-
-;; This is needed for activation/deactivation hooks:
-(defun ad-make-hook-form (function hook-name)
- ;;"Makes hook-form from FUNCTION's advice bodies in class HOOK-NAME."
- (let ((hook-forms
- (mapcar (function (lambda (advice)
- (ad-body-forms (ad-advice-definition advice))))
- (ad-get-enabled-advices function hook-name))))
- (if hook-forms
- (ad-prognify (apply 'append hook-forms)))))
-
-
-;; @@ Caching:
-;; ===========
-;; Generating an advised definition of a function is moderately expensive,
-;; hence, it makes sense to cache it so we can reuse it in appropriate
-;; circumstances. Of course, it only makes sense to reuse a cached
-;; definition if the current advice and function definition state is the
-;; same as it was at the time when the cached definition was generated.
-;; For that purpose we associate every cache with an id so we can verify
-;; if it is still valid at a certain point in time. This id mechanism
-;; makes it possible to preactivate advised functions, write the compiled
-;; advised definitions to a file and reuse them during the actual
-;; activation without having to risk that the resulting definition will be
-;; incorrect, well, almost.
-;;
-;; A cache id is a list with six elements:
-;; 1) the list of names of enabled before advices
-;; 2) the list of names of enabled around advices
-;; 3) the list of names of enabled after advices
-;; 4) the type of the original function (macro, subr, etc.)
-;; 5) the arglist of the original definition (or t if it was equal to the
-;; arglist of the cached definition)
-;; 6) t if the interactive form of the original definition was equal to the
-;; interactive form of the cached definition
-;;
-;; Here's how a cache can get invalidated or be incorrect:
-;; A) a piece of advice used in the cache gets redefined
-;; B) the current list of enabled advices is different from the ones used
-;; for the cache
-;; C) the type of the original function changed, e.g., a function became a
-;; macro, or a subr became a function
-;; D) the arglist of the original function changed
-;; E) the interactive form of the original function changed
-;; F) a piece of advice used in the cache got redefined before the
-;; defadvice with the cached definition got loaded: This is a PROBLEM!
-;;
-;; Cases A and B are the normal ones. A is taken care of by `ad-add-advice'
-;; which clears the cache in such a case, B is easily checked during
-;; verification at activation time.
-;;
-;; Cases C, D and E have to be considered if one is slightly paranoid, i.e.,
-;; if one considers the case that the original function could be different
-;; from the one available at caching time (e.g., for forward advice of
-;; functions that get redefined by some packages - such as `eval-region' gets
-;; redefined by edebug). All these cases can be easily checked during
-;; verification. Element 4 of the id lets one check case C, element 5 takes
-;; care of case D (using t in the equality case saves some space, because the
-;; arglist can be recovered at validation time from the cached definition),
-;; and element 6 takes care of case E which is only a problem if the original
-;; was actually a function whose interactive form was not overridden by a
-;; piece of advice.
-;;
-;; Case F is the only one which will lead to an incorrect advised function.
-;; There is no way to avoid this without storing the complete advice definition
-;; in the cache-id which is not feasible.
-;;
-;; The cache-id of a typical advised function with one piece of advice and
-;; no arglist redefinition takes 7 conses which is a small price to pay for
-;; the added efficiency. The validation itself is also pretty cheap, certainly
-;; a lot cheaper than reconstructing an advised definition.
-
-(defmacro ad-get-cache-definition (function)
- (` (car (ad-get-advice-info-field (, function) 'cache))))
-
-(defmacro ad-get-cache-id (function)
- (` (cdr (ad-get-advice-info-field (, function) 'cache))))
-
-(defmacro ad-set-cache (function definition id)
- (` (ad-set-advice-info-field
- (, function) 'cache (cons (, definition) (, id)))))
-
-(defun ad-clear-cache (function)
- "Clears a previously cached advised definition of FUNCTION.
-Clear the cache if you want to force `ad-activate' to construct a new
-advised definition from scratch."
- (interactive
- (list (ad-read-advised-function "Clear cached definition of: ")))
- (ad-set-advice-info-field function 'cache nil))
-
-(defun ad-make-cache-id (function)
- ;;"Generates an identifying image of the current advices of FUNCTION."
- (let ((original-definition (ad-real-orig-definition function))
- (cached-definition (ad-get-cache-definition function)))
- (list (mapcar (function (lambda (advice) (ad-advice-name advice)))
- (ad-get-enabled-advices function 'before))
- (mapcar (function (lambda (advice) (ad-advice-name advice)))
- (ad-get-enabled-advices function 'around))
- (mapcar (function (lambda (advice) (ad-advice-name advice)))
- (ad-get-enabled-advices function 'after))
- (ad-definition-type original-definition)
- (if (equal (ad-arglist original-definition function)
- (ad-arglist cached-definition))
- t
- (ad-arglist original-definition function))
- (if (eq (ad-definition-type original-definition) 'function)
- (equal (ad-interactive-form original-definition)
- (ad-interactive-form cached-definition))))))
-
-(defun ad-get-cache-class-id (function class)
- ;;"Returns the part of FUNCTION's cache id that identifies CLASS."
- (let ((cache-id (ad-get-cache-id function)))
- (if (eq class 'before)
- (car cache-id)
- (if (eq class 'around)
- (nth 1 cache-id)
- (nth 2 cache-id)))))
-
-(defun ad-verify-cache-class-id (cache-class-id advices)
- (ad-dolist (advice advices (null cache-class-id))
- (if (ad-advice-enabled advice)
- (if (eq (car cache-class-id) (ad-advice-name advice))
- (setq cache-class-id (cdr cache-class-id))
- (ad-do-return nil)))))
-
-;; There should be a way to monitor if and why a cache verification failed
-;; in order to determine whether a certain preactivation could be used or
-;; not. Right now the only way to find out is to trace
-;; `ad-cache-id-verification-code'. The code it returns indicates where the
-;; verification failed. Tracing `ad-verify-cache-class-id' might provide
-;; some additional useful information.
-
-(defun ad-cache-id-verification-code (function)
- (let ((cache-id (ad-get-cache-id function))
- (code 'before-advice-mismatch))
- (and (ad-verify-cache-class-id
- (car cache-id) (ad-get-advice-info-field function 'before))
- (setq code 'around-advice-mismatch)
- (ad-verify-cache-class-id
- (nth 1 cache-id) (ad-get-advice-info-field function 'around))
- (setq code 'after-advice-mismatch)
- (ad-verify-cache-class-id
- (nth 2 cache-id) (ad-get-advice-info-field function 'after))
- (setq code 'definition-type-mismatch)
- (let ((original-definition (ad-real-orig-definition function))
- (cached-definition (ad-get-cache-definition function)))
- (and (eq (nth 3 cache-id) (ad-definition-type original-definition))
- (setq code 'arglist-mismatch)
- (equal (if (eq (nth 4 cache-id) t)
- (ad-arglist original-definition function)
- (nth 4 cache-id) )
- (ad-arglist cached-definition))
- (setq code 'interactive-form-mismatch)
- (or (null (nth 5 cache-id))
- (equal (ad-interactive-form original-definition)
- (ad-interactive-form cached-definition)))
- (setq code 'verified))))
- code))
-
-(defun ad-verify-cache-id (function)
- ;;"True if FUNCTION's cache-id is compatible with its current advices."
- (eq (ad-cache-id-verification-code function) 'verified))
-
-
-;; @@ Preactivation:
-;; =================
-;; Preactivation can be used to generate compiled advised definitions
-;; at compile time without having to give up the dynamic runtime flexibility
-;; of the advice mechanism. Preactivation is a special feature of `defadvice',
-;; it involves the following steps:
-;; - remembering the function's current state (definition and advice-info)
-;; - advising it with the defined piece of advice
-;; - clearing its cache
-;; - generating an interpreted advised definition by activating it, this will
-;; make use of all its current active advice and its current definition
-;; - saving the so generated cached definition and id
-;; - resetting the function's advice and definition state to what it was
-;; before the preactivation
-;; - Returning the saved definition and its id to be used in the expansion of
-;; `defadvice' to assign it as an initial cache, hence it will be compiled
-;; at time the `defadvice' gets compiled.
-;; Naturally, for preactivation to be effective it has to be applied/compiled
-;; at the right time, i.e., when the current state of advices and function
-;; definition exactly reflects the state at activation time. Should that not
-;; be the case, the precompiled definition will just be discarded and a new
-;; advised definition will be generated.
-
-(defun ad-preactivate-advice (function advice class position)
- ;;"Preactivates FUNCTION and returns the constructed cache."
- (let* ((function-defined-p (fboundp function))
- (old-definition
- (if function-defined-p
- (symbol-function function)))
- (old-advice-info (ad-copy-advice-info function))
- (ad-advised-functions ad-advised-functions))
- (unwind-protect
- (progn
- (ad-add-advice function advice class position)
- (ad-enable-advice function class (ad-advice-name advice))
- (ad-clear-cache function)
- (ad-activate-on function -1)
- (if (and (ad-is-active function)
- (ad-get-cache-definition function))
- (list (ad-get-cache-definition function)
- (ad-get-cache-id function))))
- (ad-set-advice-info function old-advice-info)
- ;; Don't `fset' function to nil if it was previously unbound:
- (if function-defined-p
- (ad-safe-fset function old-definition)
- (fmakunbound function)))))
-
-
-;; @@ Freezing:
-;; ============
-;; Freezing transforms a `defadvice' into a redefining `defun/defmacro'
-;; for the advised function without keeping any advice information. This
-;; feature was jwz's idea: It generates a dumpable function definition
-;; whose documentation can be written to the DOC file, and the generated
-;; code does not need any Advice runtime support. Of course, frozen advices
-;; cannot be undone.
-
-;; Freezing only considers the advice of the particular `defadvice', other
-;; already existing advices for the same function will be ignored. To ensure
-;; proper interaction when an already advised function gets redefined with
-;; a frozen advice, frozen advices always use the actual original definition
-;; of the function, i.e., they are always at the core of the onion. E.g., if
-;; an already advised function gets redefined with a frozen advice and then
-;; unadvised, the frozen advice remains as the new definition of the function.
-
-;; While multiple freeze advices for a single function or freeze-advising
-;; of an already advised function are possible, they are better avoided,
-;; because definition/compile/load ordering is relevant, and it becomes
-;; incomprehensible pretty quickly.
-
-(defun ad-make-freeze-definition (function advice class position)
- (if (not (ad-has-proper-definition function))
- (error
- "ad-make-freeze-definition: `%s' is not yet defined"
- function))
- (let* ((name (ad-advice-name advice))
- ;; With a unique origname we can have multiple freeze advices
- ;; for the same function, each overloading the previous one:
- (unique-origname
- (intern (format "%s-%s-%s" (ad-make-origname function) class name)))
- (orig-definition
- ;; If FUNCTION is already advised, we'll use its current origdef
- ;; as the original definition of the frozen advice:
- (or (ad-get-orig-definition function)
- (symbol-function function)))
- (old-advice-info
- (if (ad-is-advised function)
- (ad-copy-advice-info function)))
- (real-docstring-fn
- (symbol-function 'ad-make-advised-definition-docstring))
- (real-origname-fn
- (symbol-function 'ad-make-origname))
- (frozen-definition
- (unwind-protect
- (progn
- ;; Make sure we construct a proper docstring:
- (ad-safe-fset 'ad-make-advised-definition-docstring
- 'ad-make-freeze-docstring)
- ;; Make sure `unique-origname' is used as the origname:
- (ad-safe-fset 'ad-make-origname '(lambda (x) unique-origname))
- ;; No we reset all current advice information to nil and
- ;; generate an advised definition that's solely determined
- ;; by ADVICE and the current origdef of FUNCTION:
- (ad-set-advice-info function nil)
- (ad-add-advice function advice class position)
- ;; The following will provide proper real docstrings as
- ;; well as a definition that will make the compiler happy:
- (ad-set-orig-definition function orig-definition)
- (ad-make-advised-definition function))
- ;; Restore the old advice state:
- (ad-set-advice-info function old-advice-info)
- ;; Restore functions:
- (ad-safe-fset
- 'ad-make-advised-definition-docstring real-docstring-fn)
- (ad-safe-fset 'ad-make-origname real-origname-fn))))
- (if frozen-definition
- (let* ((macro-p (ad-macro-p frozen-definition))
- (body (cdr (if macro-p
- (ad-lambdafy frozen-definition)
- frozen-definition))))
- (` (progn
- (if (not (fboundp '(, unique-origname)))
- (fset '(, unique-origname)
- ;; avoid infinite recursion in case the function
- ;; we want to freeze is already advised:
- (or (ad-get-orig-definition '(, function))
- (symbol-function '(, function)))))
- ((, (if macro-p 'defmacro 'defun))
- (, function)
- (,@ body))))))))
-
-
-;; @@ Activation and definition handling:
-;; ======================================
-
-(defun ad-should-compile (function compile)
- ;;"Returns non-nil if the advised FUNCTION should be compiled.
- ;;If COMPILE is non-nil and not a negative number then it returns t.
- ;;If COMPILE is a negative number then it returns nil.
- ;;If COMPILE is nil then the result depends on the value of
- ;;`ad-default-compilation-action' (which see)."
- (if (integerp compile)
- (>= compile 0)
- (if compile
- compile
- (cond ((eq ad-default-compilation-action 'never)
- nil)
- ((eq ad-default-compilation-action 'always)
- t)
- ((eq ad-default-compilation-action 'like-original)
- (or (ad-subr-p (ad-get-orig-definition function))
- (ad-compiled-p (ad-get-orig-definition function))))
- ;; everything else means `maybe':
- (t (featurep 'byte-compile))))))
-
-(defun ad-activate-advised-definition (function compile)
- ;;"Redefines FUNCTION with its advised definition from cache or scratch.
- ;;The resulting FUNCTION will be compiled if `ad-should-compile' returns t.
- ;;The current definition and its cache-id will be put into the cache."
- (let ((verified-cached-definition
- (if (ad-verify-cache-id function)
- (ad-get-cache-definition function))))
- (ad-safe-fset function
- (or verified-cached-definition
- (ad-make-advised-definition function)))
- (if (ad-should-compile function compile)
- (ad-compile-function function))
- (if verified-cached-definition
- (if (not (eq verified-cached-definition (symbol-function function)))
- ;; we must have compiled, cache the compiled definition:
- (ad-set-cache
- function (symbol-function function) (ad-get-cache-id function)))
- ;; We created a new advised definition, cache it with a proper id:
- (ad-clear-cache function)
- ;; ad-make-cache-id needs the new cached definition:
- (ad-set-cache function (symbol-function function) nil)
- (ad-set-cache
- function (symbol-function function) (ad-make-cache-id function)))))
-
-(defun ad-handle-definition (function)
- "Handles re/definition of an advised FUNCTION during de/activation.
-If FUNCTION does not have an original definition associated with it and
-the current definition is usable, then it will be stored as FUNCTION's
-original definition. If no current definition is available (even in the
-case of undefinition) nothing will be done. In the case of redefinition
-the action taken depends on the value of `ad-redefinition-action' (which
-see). Redefinition occurs when FUNCTION already has an original definition
-associated with it but got redefined with a new definition and then
-de/activated. If you do not like the current redefinition action change
-the value of `ad-redefinition-action' and de/activate again."
- (let ((original-definition (ad-get-orig-definition function))
- (current-definition (if (ad-real-definition function)
- (symbol-function function))))
- (if original-definition
- (if current-definition
- (if (and (not (eq current-definition original-definition))
- ;; Redefinition with an advised definition from a
- ;; different function won't count as such:
- (not (ad-advised-definition-p current-definition)))
- ;; we have a redefinition:
- (if (not (memq ad-redefinition-action '(accept discard warn)))
- (error "ad-handle-definition (see its doc): `%s' %s"
- function "illegally redefined")
- (if (eq ad-redefinition-action 'discard)
- (ad-safe-fset function original-definition)
- (ad-set-orig-definition function current-definition)
- (if (eq ad-redefinition-action 'warn)
- (message "ad-handle-definition: `%s' got redefined"
- function))))
- ;; either advised def or correct original is in place:
- nil)
- ;; we have an undefinition, ignore it:
- nil)
- (if current-definition
- ;; we have a first definition, save it as original:
- (ad-set-orig-definition function current-definition)
- ;; we don't have anything noteworthy:
- nil))))
-
-
-;; @@ The top-level advice interface:
-;; ==================================
-
-(defun ad-activate-on (function &optional compile)
- "Activates all the advice information of an advised FUNCTION.
-If FUNCTION has a proper original definition then an advised
-definition will be generated from FUNCTION's advice info and the
-definition of FUNCTION will be replaced with it. If a previously
-cached advised definition was available, it will be used.
-The optional COMPILE argument determines whether the resulting function
-or a compilable cached definition will be compiled. If it is negative
-no compilation will be performed, if it is positive or otherwise non-nil
-the resulting function will be compiled, if it is nil the behavior depends
-on the value of `ad-default-compilation-action' (which see).
-Activation of an advised function that has an advice info but no actual
-pieces of advice is equivalent to a call to `ad-unadvise'. Activation of
-an advised function that has actual pieces of advice but none of them are
-enabled is equivalent to a call to `ad-deactivate'. The current advised
-definition will always be cached for later usage."
- (interactive
- (list (ad-read-advised-function "Activate advice of: ")
- current-prefix-arg))
- (if ad-activate-on-top-level
- ;; avoid recursive calls to `ad-activate-on':
- (ad-with-auto-activation-disabled
- (if (not (ad-is-advised function))
- (error "ad-activate: `%s' is not advised" function)
- (ad-handle-definition function)
- ;; Just return for forward advised and not yet defined functions:
- (if (ad-get-orig-definition function)
- (if (not (ad-has-any-advice function))
- (ad-unadvise function)
- ;; Otherwise activate the advice:
- (cond ((ad-has-redefining-advice function)
- (ad-activate-advised-definition function compile)
- (ad-set-advice-info-field function 'active t)
- (eval (ad-make-hook-form function 'activation))
- function)
- ;; Here we are if we have all disabled advices:
- (t (ad-deactivate function)))))))))
-
-(defun ad-deactivate (function)
- "Deactivates the advice of an actively advised FUNCTION.
-If FUNCTION has a proper original definition, then the current
-definition of FUNCTION will be replaced with it. All the advice
-information will still be available so it can be activated again with
-a call to `ad-activate'."
- (interactive
- (list (ad-read-advised-function "Deactivate advice of: " 'ad-is-active)))
- (if (not (ad-is-advised function))
- (error "ad-deactivate: `%s' is not advised" function)
- (cond ((ad-is-active function)
- (ad-handle-definition function)
- (if (not (ad-get-orig-definition function))
- (error "ad-deactivate: `%s' has no original definition"
- function)
- (ad-safe-fset function (ad-get-orig-definition function))
- (ad-set-advice-info-field function 'active nil)
- (eval (ad-make-hook-form function 'deactivation))
- function)))))
-
-(defun ad-update (function &optional compile)
- "Update the advised definition of FUNCTION if its advice is active.
-See `ad-activate-on' for documentation on the optional COMPILE argument."
- (interactive
- (list (ad-read-advised-function
- "Update advised definition of: " 'ad-is-active)))
- (if (ad-is-active function)
- (ad-activate-on function compile)))
-
-(defun ad-unadvise (function)
- "Deactivates FUNCTION and then removes all its advice information.
-If FUNCTION was not advised this will be a noop."
- (interactive
- (list (ad-read-advised-function "Unadvise function: ")))
- (cond ((ad-is-advised function)
- (if (ad-is-active function)
- (ad-deactivate function))
- (ad-clear-orig-definition function)
- (ad-set-advice-info function nil)
- (ad-pop-advised-function function))))
-
-(defun ad-recover (function)
- "Tries to recover FUNCTION's original definition and unadvises it.
-This is more low-level than `ad-unadvise' because it does not do any
-deactivation which might run hooks and get into other trouble.
-Use in emergencies."
- ;; Use more primitive interactive behavior here: Accept any symbol that's
- ;; currently defined in obarray, not necessarily with a function definition:
- (interactive
- (list (intern
- (completing-read "Recover advised function: " obarray nil t))))
- (cond ((ad-is-advised function)
- (cond ((ad-get-orig-definition function)
- (ad-safe-fset function (ad-get-orig-definition function))
- (ad-clear-orig-definition function)))
- (ad-set-advice-info function nil)
- (ad-pop-advised-function function))))
-
-(defun ad-activate-regexp (regexp &optional compile)
- "Activates functions with an advice name containing a REGEXP match.
-See `ad-activate-on' for documentation on the optional COMPILE argument."
- (interactive
- (list (ad-read-regexp "Activate via advice regexp: ")
- current-prefix-arg))
- (ad-do-advised-functions (function)
- (if (ad-find-some-advice function 'any regexp)
- (ad-activate-on function compile))))
-
-(defun ad-deactivate-regexp (regexp)
- "Deactivates functions with an advice name containing REGEXP match."
- (interactive
- (list (ad-read-regexp "Deactivate via advice regexp: ")))
- (ad-do-advised-functions (function)
- (if (ad-find-some-advice function 'any regexp)
- (ad-deactivate function))))
-
-(defun ad-update-regexp (regexp &optional compile)
- "Updates functions with an advice name containing a REGEXP match.
-See `ad-activate-on' for documentation on the optional COMPILE argument."
- (interactive
- (list (ad-read-regexp "Update via advice regexp: ")
- current-prefix-arg))
- (ad-do-advised-functions (function)
- (if (ad-find-some-advice function 'any regexp)
- (ad-update function compile))))
-
-(defun ad-activate-all (&optional compile)
- "Activates all currently advised functions.
-See `ad-activate-on' for documentation on the optional COMPILE argument."
- (interactive "P")
- (ad-do-advised-functions (function)
- (ad-activate-on function compile)))
-
-(defun ad-deactivate-all ()
- "Deactivates all currently advised functions."
- (interactive)
- (ad-do-advised-functions (function)
- (ad-deactivate function)))
-
-(defun ad-update-all (&optional compile)
- "Updates all currently advised functions.
-With prefix argument compiles resulting advised definitions."
- (interactive "P")
- (ad-do-advised-functions (function)
- (ad-update function compile)))
-
-(defun ad-unadvise-all ()
- "Unadvises all currently advised functions."
- (interactive)
- (ad-do-advised-functions (function)
- (ad-unadvise function)))
-
-(defun ad-recover-all ()
- "Recovers all currently advised functions. Use in emergencies."
- (interactive)
- (ad-do-advised-functions (function)
- (condition-case nil
- (ad-recover function)
- (error nil))))
-
-
-;; Completion alist of legal `defadvice' flags
-(defvar ad-defadvice-flags
- '(("protect") ("disable") ("activate")
- ("compile") ("preactivate") ("freeze")))
-
-;;;###autoload
-(defmacro defadvice (function args &rest body)
- "Defines a piece of advice for FUNCTION (a symbol).
-The syntax of `defadvice' is as follows:
-
- (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...)
- [DOCSTRING] [INTERACTIVE-FORM]
- BODY... )
-
-FUNCTION ::= Name of the function to be advised.
-CLASS ::= `before' | `around' | `after' | `activation' | `deactivation'.
-NAME ::= Non-nil symbol that names this piece of advice.
-POSITION ::= `first' | `last' | NUMBER. Optional, defaults to `first',
- see also `ad-add-advice'.
-ARGLIST ::= An optional argument list to be used for the advised function
- instead of the argument list of the original. The first one found in
- before/around/after-advices will be used.
-FLAG ::= `protect'|`disable'|`activate'|`compile'|`preactivate'|`freeze'.
- All flags can be specified with unambiguous initial substrings.
-DOCSTRING ::= Optional documentation for this piece of advice.
-INTERACTIVE-FORM ::= Optional interactive form to be used for the advised
- function. The first one found in before/around/after-advices will be used.
-BODY ::= Any s-expression.
-
-Semantics of the various flags:
-`protect': The piece of advice will be protected against non-local exits in
-any code that precedes it. If any around-advice of a function is protected
-then automatically all around-advices will be protected (the complete onion).
-
-`activate': All advice of FUNCTION will be activated immediately if
-FUNCTION has been properly defined prior to this application of `defadvice'.
-
-`compile': In conjunction with `activate' specifies that the resulting
-advised function should be compiled.
-
-`disable': The defined advice will be disabled, hence, it will not be used
-during activation until somebody enables it.
-
-`preactivate': Preactivates the advised FUNCTION at macro-expansion/compile
-time. This generates a compiled advised definition according to the current
-advice state that will be used during activation if appropriate. Only use
-this if the `defadvice' gets actually compiled.
-
-`freeze': Expands the `defadvice' into a redefining `defun/defmacro' according
-to this particular single advice. No other advice information will be saved.
-Frozen advices cannot be undone, they behave like a hard redefinition of
-the advised function. `freeze' implies `activate' and `preactivate'. The
-documentation of the advised function can be dumped onto the `DOC' file
-during preloading.
-
-Look at the file `advice.el' for comprehensive documentation."
- (if (not (ad-name-p function))
- (error "defadvice: Illegal function name: %s" function))
- (let* ((class (car args))
- (name (if (not (ad-class-p class))
- (error "defadvice: Illegal advice class: %s" class)
- (nth 1 args)))
- (position (if (not (ad-name-p name))
- (error "defadvice: Illegal advice name: %s" name)
- (setq args (nthcdr 2 args))
- (if (ad-position-p (car args))
- (prog1 (car args)
- (setq args (cdr args))))))
- (arglist (if (listp (car args))
- (prog1 (car args)
- (setq args (cdr args)))))
- (flags
- (mapcar
- (function
- (lambda (flag)
- (let ((completion
- (try-completion (symbol-name flag) ad-defadvice-flags)))
- (cond ((eq completion t) flag)
- ((assoc completion ad-defadvice-flags)
- (intern completion))
- (t (error "defadvice: Illegal or ambiguous flag: %s"
- flag))))))
- args))
- (advice (ad-make-advice
- name (memq 'protect flags)
- (not (memq 'disable flags))
- (` (advice lambda (, arglist) (,@ body)))))
- (preactivation (if (memq 'preactivate flags)
- (ad-preactivate-advice
- function advice class position))))
- ;; Now for the things to be done at evaluation time:
- (if (memq 'freeze flags)
- ;; jwz's idea: Freeze the advised definition into a dumpable
- ;; defun/defmacro whose docs can be written to the DOC file:
- (ad-make-freeze-definition function advice class position)
- ;; the normal case:
- (` (progn
- (ad-add-advice '(, function) '(, advice) '(, class) '(, position))
- (,@ (if preactivation
- (` ((ad-set-cache
- '(, function)
- ;; the function will get compiled:
- (, (cond ((ad-macro-p (car preactivation))
- (` (ad-macrofy
- (function
- (, (ad-lambdafy
- (car preactivation)))))))
- (t (` (function
- (, (car preactivation)))))))
- '(, (car (cdr preactivation))))))))
- (,@ (if (memq 'activate flags)
- (` ((ad-activate-on '(, function)
- (, (if (memq 'compile flags) t)))))))
- '(, function))))))
-
-
-;; @@ Tools:
-;; =========
-
-(defmacro ad-with-originals (functions &rest body)
- "Binds FUNCTIONS to their original definitions and executes BODY.
-For any members of FUNCTIONS that are not currently advised the rebinding will
-be a noop. Any modifications done to the definitions of FUNCTIONS will be
-undone on exit of this macro."
- (let* ((index -1)
- ;; Make let-variables to store current definitions:
- (current-bindings
- (mapcar (function
- (lambda (function)
- (setq index (1+ index))
- (list (intern (format "ad-oRiGdEf-%d" index))
- (` (symbol-function '(, function))))))
- functions)))
- (` (let (, current-bindings)
- (unwind-protect
- (progn
- (,@ (progn
- ;; Make forms to redefine functions to their
- ;; original definitions if they are advised:
- (setq index -1)
- (mapcar
- (function
- (lambda (function)
- (setq index (1+ index))
- (` (ad-safe-fset
- '(, function)
- (or (ad-get-orig-definition '(, function))
- (, (car (nth index current-bindings))))))))
- functions)))
- (,@ body))
- (,@ (progn
- ;; Make forms to back-define functions to the definitions
- ;; they had outside this macro call:
- (setq index -1)
- (mapcar
- (function
- (lambda (function)
- (setq index (1+ index))
- (` (ad-safe-fset
- '(, function)
- (, (car (nth index current-bindings)))))))
- functions))))))))
-
-(if (not (get 'ad-with-originals 'lisp-indent-hook))
- (put 'ad-with-originals 'lisp-indent-hook 1))
-
-
-;; @@ Advising `documentation':
-;; ============================
-;; Use the advice mechanism to advise `documentation' to make it
-;; generate proper documentation strings for advised definitions:
-
-(defadvice documentation (after ad-advised-docstring first disable preact)
- "Builds an advised docstring if FUNCTION is advised."
- ;; Because we get the function name from the advised docstring
- ;; this will work for function names as well as for definitions:
- (if (and (stringp ad-return-value)
- (string-match
- ad-advised-definition-docstring-regexp ad-return-value))
- (let ((function
- (car (read-from-string
- ad-return-value (match-beginning 1) (match-end 1)))))
- (cond ((ad-is-advised function)
- (setq ad-return-value (ad-make-advised-docstring function))
- ;; Handle optional `raw' argument:
- (if (not (ad-get-arg 1))
- (setq ad-return-value
- (substitute-command-keys ad-return-value))))))))
-
-
-;; @@ Starting, stopping and recovering from the advice package magic:
-;; ===================================================================
-
-(defun ad-start-advice ()
- "Starts the automatic advice handling magic."
- (interactive)
- ;; Advising `ad-activate' means death!!
- (ad-set-advice-info 'ad-activate nil)
- (ad-safe-fset 'ad-activate 'ad-activate-on)
- (ad-enable-advice 'documentation 'after 'ad-advised-docstring)
- (ad-activate-on 'documentation 'compile))
-
-(defun ad-stop-advice ()
- "Stops the automatic advice handling magic.
-You should only need this in case of Advice-related emergencies."
- (interactive)
- ;; Advising `ad-activate' means death!!
- (ad-set-advice-info 'ad-activate nil)
- (ad-disable-advice 'documentation 'after 'ad-advised-docstring)
- (ad-update 'documentation)
- (ad-safe-fset 'ad-activate 'ad-activate-off))
-
-(defun ad-recover-normality ()
- "Undoes all advice related redefinitions and unadvises everything.
-Use only in REAL emergencies."
- (interactive)
- ;; Advising `ad-activate' means death!!
- (ad-set-advice-info 'ad-activate nil)
- (ad-safe-fset 'ad-activate 'ad-activate-off)
- (ad-recover-all)
- (setq ad-advised-functions nil))
-
-;; Until the Advice-related changes to `data.c' are part of Lemacs we
-;; have to load the old implementation of advice activation hooks:
-(if (ad-lemacs-p)
- (require 'ad-hooks))
-
-(ad-start-advice)
-
-(provide 'advice)
-
-;;; advice.el ends here
diff --git a/lisp/emacs-lisp/assoc.el b/lisp/emacs-lisp/assoc.el
deleted file mode 100644
index 997badc1732..00000000000
--- a/lisp/emacs-lisp/assoc.el
+++ /dev/null
@@ -1,140 +0,0 @@
-;;; assoc.el --- insert/delete/sort functions on association lists
-
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Barry A. Warsaw <bwarsaw@cen.com>
-;; Keywords: extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Association list utilities providing insertion, deletion, sorting
-;; fetching off key-value pairs in association lists.
-
-;;; Code:
-
-(defun asort (alist-symbol key)
- "Move a specified key-value pair to the head of an alist.
-The alist is referenced by ALIST-SYMBOL. Key-value pair to move to
-head is one matching KEY. Returns the sorted list and doesn't affect
-the order of any other key-value pair. Side effect sets alist to new
-sorted list."
- (set alist-symbol
- (sort (copy-alist (eval alist-symbol))
- (function (lambda (a b) (equal (car a) key))))))
-
-
-(defun aelement (key value)
- "Makes a list of a cons cell containing car of KEY and cdr of VALUE.
-The returned list is suitable as an element of an alist."
- (list (cons key value)))
-
-
-(defun aheadsym (alist)
- "Return the key symbol at the head of ALIST."
- (car (car alist)))
-
-
-(defun anot-head-p (alist key)
- "Find out if a specified key-value pair is not at the head of an alist.
-The alist to check is specified by ALIST and the key-value pair is the
-one matching the supplied KEY. Returns nil if ALIST is nil, or if
-key-value pair is at the head of the alist. Returns t if key-value
-pair is not at the head of alist. ALIST is not altered."
- (not (equal (aheadsym alist) key)))
-
-
-(defun aput (alist-symbol key &optional value)
- "Inserts a key-value pair into an alist.
-The alist is referenced by ALIST-SYMBOL. The key-value pair is made
-from KEY and optionally, VALUE. Returns the altered alist or nil if
-ALIST is nil.
-
-If the key-value pair referenced by KEY can be found in the alist, and
-VALUE is supplied non-nil, then the value of KEY will be set to VALUE.
-If VALUE is not supplied, or is nil, the key-value pair will not be
-modified, but will be moved to the head of the alist. If the key-value
-pair cannot be found in the alist, it will be inserted into the head
-of the alist (with value nil if VALUE is nil or not supplied)."
- (let ((elem (aelement key value))
- alist)
- (asort alist-symbol key)
- (setq alist (eval alist-symbol))
- (cond ((null alist) (set alist-symbol elem))
- ((anot-head-p alist key) (set alist-symbol (nconc elem alist)))
- (value (setcar alist (car elem)))
- (t alist))))
-
-
-(defun adelete (alist-symbol key)
- "Delete a key-value pair from the alist.
-Alist is referenced by ALIST-SYMBOL and the key-value pair to remove
-is pair matching KEY. Returns the altered alist."
- (asort alist-symbol key)
- (let ((alist (eval alist-symbol)))
- (cond ((null alist) nil)
- ((anot-head-p alist key) alist)
- (t (set alist-symbol (cdr alist))))))
-
-
-(defun aget (alist key &optional keynil-p)
- "Returns the value in ALIST that is associated with KEY.
-Optional KEYNIL-P describes what to do if the value associated with
-KEY is nil. If KEYNIL-P is not supplied or is nil, and the value is
-nil, then KEY is returned. If KEYNIL-P is non-nil, then nil would be
-returned.
-
-If no key-value pair matching KEY could be found in ALIST, or ALIST is
-nil then nil is returned. ALIST is not altered."
- (let ((copy (copy-alist alist)))
- (cond ((null alist) nil)
- ((progn (asort 'copy key)
- (anot-head-p copy key)) nil)
- ((cdr (car copy)))
- (keynil-p nil)
- ((car (car copy)))
- (t nil))))
-
-
-(defun amake (alist-symbol keylist &optional valuelist)
- "Make an association list.
-The association list is attached to the alist referenced by
-ALIST-SYMBOL. Each element in the KEYLIST becomes a key and is
-associated with the value in VALUELIST with the same index. If
-VALUELIST is not supplied or is nil, then each key in KEYLIST is
-associated with nil.
-
-KEYLIST and VALUELIST should have the same number of elements, but
-this isn't enforced. If VALUELIST is smaller than KEYLIST, remaining
-keys are associated with nil. If VALUELIST is larger than KEYLIST,
-extra values are ignored. Returns the created alist."
- (let ((keycar (car keylist))
- (keycdr (cdr keylist))
- (valcar (car valuelist))
- (valcdr (cdr valuelist)))
- (cond ((null keycdr)
- (aput alist-symbol keycar valcar))
- (t
- (amake alist-symbol keycdr valcdr)
- (aput alist-symbol keycar valcar))))
- (eval alist-symbol))
-
-(provide 'assoc)
-
-;;; assoc.el ends here
diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el
deleted file mode 100644
index 4614a5c42cb..00000000000
--- a/lisp/emacs-lisp/autoload.el
+++ /dev/null
@@ -1,416 +0,0 @@
-;;; autoload.el --- maintain autoloads in loaddefs.el.
-
-;; Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
-
-;; Author: Roland McGrath <roland@gnu.ai.mit.edu>
-;; Keywords: maint
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This code helps GNU Emacs maintainers keep the loaddefs.el file up to
-;; date. It interprets magic cookies of the form ";;;###autoload" in
-;; lisp source files in various useful ways. To learn more, read the
-;; source; if you're going to use this, you'd better be able to.
-
-;;; Code:
-
-(defun make-autoload (form file)
- "Turn FORM, a defun or defmacro, into an autoload for source file FILE.
-Returns nil if FORM is not a defun, define-skeleton or defmacro."
- (let ((car (car-safe form)))
- (if (memq car '(defun define-skeleton defmacro))
- (let ((macrop (eq car 'defmacro))
- name doc)
- (setq form (cdr form)
- name (car form)
- ;; Ignore the arguments.
- form (cdr (if (eq car 'define-skeleton)
- form
- (cdr form)))
- doc (car form))
- (if (stringp doc)
- (setq form (cdr form))
- (setq doc nil))
- (list 'autoload (list 'quote name) file doc
- (or (eq car 'define-skeleton)
- (eq (car-safe (car form)) 'interactive))
- (if macrop (list 'quote 'macro) nil)))
- nil)))
-
-(put 'define-skeleton 'doc-string-elt 3)
-
-(defconst generate-autoload-cookie ";;;###autoload"
- "Magic comment indicating the following form should be autoloaded.
-Used by \\[update-file-autoloads]. This string should be
-meaningless to Lisp (e.g., a comment).
-
-This string is used:
-
-;;;###autoload
-\(defun function-to-be-autoloaded () ...)
-
-If this string appears alone on a line, the following form will be
-read and an autoload made for it. If there is further text on the line,
-that text will be copied verbatim to `generated-autoload-file'.")
-
-(defconst generate-autoload-section-header "\f\n;;;### "
- "String inserted before the form identifying
-the section of autoloads for a file.")
-
-(defconst generate-autoload-section-trailer "\n;;;***\n"
- "String which indicates the end of the section of autoloads for a file.")
-
-;;; Forms which have doc-strings which should be printed specially.
-;;; A doc-string-elt property of ELT says that (nth ELT FORM) is
-;;; the doc-string in FORM.
-;;;
-;;; There used to be the following note here:
-;;; ;;; Note: defconst and defvar should NOT be marked in this way.
-;;; ;;; We don't want to produce defconsts and defvars that
-;;; ;;; make-docfile can grok, because then it would grok them twice,
-;;; ;;; once in foo.el (where they are given with ;;;###autoload) and
-;;; ;;; once in loaddefs.el.
-;;;
-;;; Counter-note: Yes, they should be marked in this way.
-;;; make-docfile only processes those files that are loaded into the
-;;; dumped Emacs, and those files should never have anything
-;;; autoloaded here. The above-feared problem only occurs with files
-;;; which have autoloaded entries *and* are processed by make-docfile;
-;;; there should be no such files.
-
-(put 'autoload 'doc-string-elt 3)
-(put 'defun 'doc-string-elt 3)
-(put 'defvar 'doc-string-elt 3)
-(put 'defconst 'doc-string-elt 3)
-(put 'defmacro 'doc-string-elt 3)
-
-(defun autoload-trim-file-name (file)
- ;; Returns a relative pathname of FILE
- ;; starting from the directory that loaddefs.el is in.
- ;; That is normally a directory in load-path,
- ;; which means Emacs will be able to find FILE when it looks.
- ;; Any extra directory names here would prevent finding the file.
- (setq file (expand-file-name file))
- (file-relative-name file
- (file-name-directory generated-autoload-file)))
-
-(defun generate-file-autoloads (file)
- "Insert at point a loaddefs autoload section for FILE.
-autoloads are generated for defuns and defmacros in FILE
-marked by `generate-autoload-cookie' (which see).
-If FILE is being visited in a buffer, the contents of the buffer
-are used."
- (interactive "fGenerate autoloads for file: ")
- (let ((outbuf (current-buffer))
- (autoloads-done '())
- (load-name (let ((name (file-name-nondirectory file)))
- (if (string-match "\\.elc?$" name)
- (substring name 0 (match-beginning 0))
- name)))
- (print-length nil)
- (print-readably t) ; This does something in Lucid Emacs.
- (float-output-format nil)
- (done-any nil)
- (visited (get-file-buffer file))
- output-end)
-
- ;; If the autoload section we create here uses an absolute
- ;; pathname for FILE in its header, and then Emacs is installed
- ;; under a different path on another system,
- ;; `update-autoloads-here' won't be able to find the files to be
- ;; autoloaded. So, if FILE is in the same directory or a
- ;; subdirectory of the current buffer's directory, we'll make it
- ;; relative to the current buffer's directory.
- (setq file (expand-file-name file))
- (let* ((source-truename (file-truename file))
- (dir-truename (file-name-as-directory
- (file-truename default-directory)))
- (len (length dir-truename)))
- (if (and (< len (length source-truename))
- (string= dir-truename (substring source-truename 0 len)))
- (setq file (substring source-truename len))))
-
- (message "Generating autoloads for %s..." file)
- (save-excursion
- (unwind-protect
- (progn
- (if visited
- (set-buffer visited)
- ;; It is faster to avoid visiting the file.
- (set-buffer (get-buffer-create " *generate-autoload-file*"))
- (kill-all-local-variables)
- (erase-buffer)
- (setq buffer-undo-list t
- buffer-read-only nil)
- (emacs-lisp-mode)
- (insert-file-contents file nil))
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (while (not (eobp))
- (skip-chars-forward " \t\n\f")
- (cond
- ((looking-at (regexp-quote generate-autoload-cookie))
- (search-forward generate-autoload-cookie)
- (skip-chars-forward " \t")
- (setq done-any t)
- (if (eolp)
- ;; Read the next form and make an autoload.
- (let* ((form (prog1 (read (current-buffer))
- (or (bolp) (forward-line 1))))
- (autoload (make-autoload form load-name))
- (doc-string-elt (get (car-safe form)
- 'doc-string-elt)))
- (if autoload
- (setq autoloads-done (cons (nth 1 form)
- autoloads-done))
- (setq autoload form))
- (if (and doc-string-elt
- (stringp (nth doc-string-elt autoload)))
- ;; We need to hack the printing because the
- ;; doc-string must be printed specially for
- ;; make-docfile (sigh).
- (let* ((p (nthcdr (1- doc-string-elt)
- autoload))
- (elt (cdr p)))
- (setcdr p nil)
- (princ "\n(" outbuf)
- (let ((print-escape-newlines t))
- (mapcar (function (lambda (elt)
- (prin1 elt outbuf)
- (princ " " outbuf)))
- autoload))
- (princ "\"\\\n" outbuf)
- (let ((begin (save-excursion
- (set-buffer outbuf)
- (point))))
- (princ (substring
- (prin1-to-string (car elt)) 1)
- outbuf)
- ;; Insert a backslash before each ( that
- ;; appears at the beginning of a line in
- ;; the doc string.
- (save-excursion
- (set-buffer outbuf)
- (save-excursion
- (while (search-backward "\n(" begin t)
- (forward-char 1)
- (insert "\\"))))
- (if (null (cdr elt))
- (princ ")" outbuf)
- (princ " " outbuf)
- (princ (substring
- (prin1-to-string (cdr elt))
- 1)
- outbuf))
- (terpri outbuf)))
- (let ((print-escape-newlines t))
- (print autoload outbuf))))
- ;; Copy the rest of the line to the output.
- (princ (buffer-substring
- (progn
- ;; Back up over whitespace, to preserve it.
- (skip-chars-backward " \f\t")
- (if (= (char-after (1+ (point))) ? )
- ;; Eat one space.
- (forward-char 1))
- (point))
- (progn (forward-line 1) (point)))
- outbuf)))
- ((looking-at ";")
- ;; Don't read the comment.
- (forward-line 1))
- (t
- (forward-sexp 1)
- (forward-line 1)))))))
- (or visited
- ;; We created this buffer, so we should kill it.
- (kill-buffer (current-buffer)))
- (set-buffer outbuf)
- (setq output-end (point-marker))))
- (if done-any
- (progn
- (insert generate-autoload-section-header)
- (prin1 (list 'autoloads autoloads-done load-name
- (autoload-trim-file-name file)
- (nth 5 (file-attributes file)))
- outbuf)
- (terpri outbuf)
- (insert ";;; Generated autoloads from "
- (autoload-trim-file-name file) "\n")
- ;; Warn if we put a line in loaddefs.el
- ;; that is long enough to cause trouble.
- (while (< (point) output-end)
- (let ((beg (point)))
- (end-of-line)
- (if (> (- (point) beg) 900)
- (progn
- (message "A line is too long--over 900 characters")
- (sleep-for 2)
- (goto-char output-end))))
- (forward-line 1))
- (goto-char output-end)
- (insert generate-autoload-section-trailer)))
- (message "Generating autoloads for %s...done" file)))
-
-(defconst generated-autoload-file "loaddefs.el"
- "*File \\[update-file-autoloads] puts autoloads into.
-A .el file can set this in its local variables section to make its
-autoloads go somewhere else.")
-
-;;;###autoload
-(defun update-file-autoloads (file)
- "Update the autoloads for FILE in `generated-autoload-file'
-\(which FILE might bind in its local variables)."
- (interactive "fUpdate autoloads for file: ")
- (let ((load-name (let ((name (file-name-nondirectory file)))
- (if (string-match "\\.elc?$" name)
- (substring name 0 (match-beginning 0))
- name)))
- (found nil)
- (existing-buffer (get-file-buffer file)))
- (save-excursion
- ;; We want to get a value for generated-autoload-file from
- ;; the local variables section if it's there.
- (if existing-buffer
- (set-buffer existing-buffer))
- (set-buffer (find-file-noselect generated-autoload-file))
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- ;; Look for the section for LOAD-NAME.
- (while (and (not found)
- (search-forward generate-autoload-section-header nil t))
- (let ((form (condition-case ()
- (read (current-buffer))
- (end-of-file nil))))
- (cond ((string= (nth 2 form) load-name)
- ;; We found the section for this file.
- ;; Check if it is up to date.
- (let ((begin (match-beginning 0))
- (last-time (nth 4 form))
- (file-time (nth 5 (file-attributes file))))
- (if (and (or (null existing-buffer)
- (not (buffer-modified-p existing-buffer)))
- (listp last-time) (= (length last-time) 2)
- (or (> (car last-time) (car file-time))
- (and (= (car last-time) (car file-time))
- (>= (nth 1 last-time)
- (nth 1 file-time)))))
- (progn
- (if (interactive-p)
- (message "\
-Autoload section for %s is up to date."
- file))
- (setq found 'up-to-date))
- (search-forward generate-autoload-section-trailer)
- (delete-region begin (point))
- (setq found t))))
- ((string< load-name (nth 2 form))
- ;; We've come to a section alphabetically later than
- ;; LOAD-NAME. We assume the file is in order and so
- ;; there must be no section for LOAD-NAME. We will
- ;; insert one before the section here.
- (goto-char (match-beginning 0))
- (setq found 'new)))))
- (or found
- (progn
- (setq found 'new)
- ;; No later sections in the file. Put before the last page.
- (goto-char (point-max))
- (search-backward "\f" nil t)))
- (or (eq found 'up-to-date)
- (and (eq found 'new)
- ;; Check that FILE has any cookies before generating a
- ;; new section for it.
- (save-excursion
- (if existing-buffer
- (set-buffer existing-buffer)
- ;; It is faster to avoid visiting the file.
- (set-buffer (get-buffer-create " *autoload-file*"))
- (kill-all-local-variables)
- (erase-buffer)
- (setq buffer-undo-list t
- buffer-read-only nil)
- (emacs-lisp-mode)
- (insert-file-contents file nil))
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (prog1
- (if (search-forward
- (concat "\n" generate-autoload-cookie)
- nil t)
- nil
- (if (interactive-p)
- (message "%s has no autoloads" file))
- t)
- (or existing-buffer
- (kill-buffer (current-buffer))))))))
- (generate-file-autoloads file))))
- (if (interactive-p) (save-buffer)))))
-
-;;;###autoload
-(defun update-autoloads-from-directory (dir)
- "\
-Update loaddefs.el with all the current autoloads from DIR, and no old ones.
-This uses `update-file-autoloads' (which see) do its work."
- (interactive "DUpdate autoloads from directory: ")
- (setq dir (expand-file-name dir))
- (let ((files (directory-files dir nil "^[^=].*\\.el$")))
- (save-excursion
- (set-buffer (find-file-noselect
- (if (file-exists-p generated-autoload-file)
- generated-autoload-file
- (expand-file-name generated-autoload-file
- dir))))
- (save-excursion
- (goto-char (point-min))
- (while (search-forward generate-autoload-section-header nil t)
- (let* ((form (condition-case ()
- (read (current-buffer))
- (end-of-file nil)))
- (file (nth 3 form)))
- (cond ((not (stringp file)))
- ((not (file-exists-p (expand-file-name file dir)))
- ;; Remove the obsolete section.
- (let ((begin (match-beginning 0)))
- (search-forward generate-autoload-section-trailer)
- (delete-region begin (point))))
- (t
- (update-file-autoloads file)))
- (setq files (delete file files)))))
- ;; Elements remaining in FILES have no existing autoload sections.
- (mapcar 'update-file-autoloads files)
- (save-buffer))))
-
-;;;###autoload
-(defun batch-update-autoloads ()
- "Update loaddefs.el autoloads in batch mode.
-Calls `update-autoloads-from-directory' on each command line argument."
- (mapcar 'update-autoloads-from-directory command-line-args-left)
- (setq command-line-args-left nil))
-
-(provide 'autoload)
-
-;;; autoload.el ends here
diff --git a/lisp/emacs-lisp/backquote.el b/lisp/emacs-lisp/backquote.el
deleted file mode 100644
index 807b4bd1c50..00000000000
--- a/lisp/emacs-lisp/backquote.el
+++ /dev/null
@@ -1,212 +0,0 @@
-;;; backquote.el --- implement the ` Lisp construct
-
-;;; Copyright (C) 1990, 1992, 1994 Free Software Foundation, Inc.
-
-;; Author: Rick Sladkey <jrs@world.std.com>
-;; Maintainer: FSF
-;; Keywords: extensions, internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This backquote will generate calls to the backquote-list* form.
-;; Both a function version and a macro version are included.
-;; The macro version is used by default because it is faster
-;; and needs no run-time support. It should really be a subr.
-
-;;; Code:
-
-(provide 'backquote)
-
-;; function and macro versions of backquote-list*
-
-(defun backquote-list*-function (first &rest list)
- "Like `list' but the last argument is the tail of the new list.
-
-For example (backquote-list* 'a 'b 'c) => (a b . c)"
- (if list
- (let* ((rest list) (newlist (cons first nil)) (last newlist))
- (while (cdr rest)
- (setcdr last (cons (car rest) nil))
- (setq last (cdr last)
- rest (cdr rest)))
- (setcdr last (car rest))
- newlist)
- first))
-
-(defmacro backquote-list*-macro (first &rest list)
- "Like `list' but the last argument is the tail of the new list.
-
-For example (backquote-list* 'a 'b 'c) => (a b . c)"
- (setq list (reverse (cons first list))
- first (car list)
- list (cdr list))
- (if list
- (let* ((second (car list))
- (rest (cdr list))
- (newlist (list 'cons second first)))
- (while rest
- (setq newlist (list 'cons (car rest) newlist)
- rest (cdr rest)))
- newlist)
- first))
-
-(defalias 'backquote-list* (symbol-function 'backquote-list*-macro))
-
-;; A few advertised variables that control which symbols are used
-;; to represent the backquote, unquote, and splice operations.
-
-(defvar backquote-backquote-symbol '\`
- "*Symbol used to represent a backquote or nested backquote (e.g. `).")
-
-(defvar backquote-unquote-symbol ',
- "*Symbol used to represent an unquote (e.g. `,') inside a backquote.")
-
-(defvar backquote-splice-symbol ',@
- "*Symbol used to represent a splice (e.g. `,@') inside a backquote.")
-
-;;;###autoload
-(defmacro backquote (arg)
- "Argument STRUCTURE describes a template to build.
-
-The whole structure acts as if it were quoted except for certain
-places where expressions are evaluated and inserted or spliced in.
-
-For example:
-
-b => (ba bb bc) ; assume b has this value
-`(a b c) => (a b c) ; backquote acts like quote
-`(a ,b c) => (a (ba bb bc) c) ; insert the value of b
-`(a ,@b c) => (a ba bb bc c) ; splice in the value of b
-
-Vectors work just like lists. Nested backquotes are permitted."
- (cdr (backquote-process arg)))
-
-;; GNU Emacs has no reader macros
-
-;;;###autoload
-(defalias '\` (symbol-function 'backquote))
-
-;; backquote-process returns a dotted-pair of a tag (0, 1, or 2) and
-;; the backquote-processed structure. 0 => the structure is
-;; constant, 1 => to be unquoted, 2 => to be spliced in.
-;; The top-level backquote macro just discards the tag.
-
-(defun backquote-process (s)
- (cond
- ((vectorp s)
- (let ((n (backquote-process (append s ()))))
- (if (= (car n) 0)
- (cons 0 s)
- (cons 1 (cond
- ((eq (nth 1 n) 'list)
- (cons 'vector (nthcdr 2 n)))
- ((eq (nth 1 n) 'append)
- (cons 'vconcat (nthcdr 2 n)))
- (t
- (list 'apply '(function vector) (cdr n))))))))
- ((atom s)
- (cons 0 (if (or (null s) (eq s t) (not (symbolp s)))
- s
- (list 'quote s))))
- ((eq (car s) backquote-unquote-symbol)
- (cons 1 (nth 1 s)))
- ((eq (car s) backquote-splice-symbol)
- (cons 2 (nth 1 s)))
- ((eq (car s) backquote-backquote-symbol)
- (backquote-process (cdr (backquote-process (nth 1 s)))))
- (t
- (let ((rest s)
- item firstlist list lists expression)
- ;; Scan this list-level, setting LISTS to a list of forms,
- ;; each of which produces a list of elements
- ;; that should go in this level.
- ;; The order of LISTS is backwards.
- ;; If there are non-splicing elements (constant or variable)
- ;; at the beginning, put them in FIRSTLIST,
- ;; as a list of tagged values (TAG . FORM).
- ;; If there are any at the end, they go in LIST, likewise.
- (while (consp rest)
- ;; Turn . (, foo) into (,@ foo).
- (if (eq (car rest) backquote-unquote-symbol)
- (setq rest (list (list backquote-splice-symbol (nth 1 rest)))))
- (setq item (backquote-process (car rest)))
- (cond
- ((= (car item) 2)
- ;; Put the nonspliced items before the first spliced item
- ;; into FIRSTLIST.
- (if (null lists)
- (setq firstlist list
- list nil))
- ;; Otherwise, put any preceding nonspliced items into LISTS.
- (if list
- (setq lists (cons (backquote-listify list '(0 . nil)) lists)))
- (setq lists (cons (cdr item) lists))
- (setq list nil))
- (t
- (setq list (cons item list))))
- (setq rest (cdr rest)))
- ;; Handle nonsplicing final elements, and the tail of the list
- ;; (which remains in REST).
- (if (or rest list)
- (setq lists (cons (backquote-listify list (backquote-process rest))
- lists)))
- ;; Turn LISTS into a form that produces the combined list.
- (setq expression
- (if (or (cdr lists)
- (eq (car-safe (car lists)) backquote-splice-symbol))
- (cons 'append (nreverse lists))
- (car lists)))
- ;; Tack on any initial elements.
- (if firstlist
- (setq expression (backquote-listify firstlist (cons 1 expression))))
- (if (eq (car-safe expression) 'quote)
- (cons 0 (list 'quote s))
- (cons 1 expression))))))
-
-;; backquote-listify takes (tag . structure) pairs from backquote-process
-;; and decides between append, list, backquote-list*, and cons depending
-;; on which tags are in the list.
-
-(defun backquote-listify (list old-tail)
- (let ((heads nil) (tail (cdr old-tail)) (list-tail list) (item nil))
- (if (= (car old-tail) 0)
- (setq tail (eval tail)
- old-tail nil))
- (while (consp list-tail)
- (setq item (car list-tail))
- (setq list-tail (cdr list-tail))
- (if (or heads old-tail (/= (car item) 0))
- (setq heads (cons (cdr item) heads))
- (setq tail (cons (eval (cdr item)) tail))))
- (cond
- (tail
- (if (null old-tail)
- (setq tail (list 'quote tail)))
- (if heads
- (let ((use-list* (or (cdr heads)
- (and (consp (car heads))
- (eq (car (car heads))
- backquote-splice-symbol)))))
- (cons (if use-list* 'backquote-list* 'cons)
- (append heads (list tail))))
- tail))
- (t (cons 'list heads)))))
-
-;; backquote.el ends here
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
deleted file mode 100644
index ef2880c7d9b..00000000000
--- a/lisp/emacs-lisp/byte-opt.el
+++ /dev/null
@@ -1,1872 +0,0 @@
-;;; byte-opt.el --- the optimization passes of the emacs-lisp byte compiler.
-
-;;; Copyright (c) 1991, 1994 Free Software Foundation, Inc.
-
-;; Author: Jamie Zawinski <jwz@lucid.com>
-;; Hallvard Furuseth <hbf@ulrik.uio.no>
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; This file has been censored by the Communications Decency Act.
-;;; That law was passed under the guise of a ban on pornography, but
-;;; it bans far more than that. This file did not contain pornography,
-;;; but it was censored nonetheless.
-
-;;; For information on US government censorship of the Internet, and
-;;; what you can do to bring back freedom of the press, see the web
-;;; site http://www.vtw.org/
-
-;; ========================================================================
-;; "No matter how hard you try, you can't make a racehorse out of a pig.
-;; You can, however, make a faster pig."
-;;
-;; Or, to put it another way, the emacs byte compiler is a VW Bug. This code
-;; makes it be a VW Bug with fuel injection and a turbocharger... You're
-;; still not going to make it go faster than 70 mph, but it might be easier
-;; to get it there.
-;;
-
-;; TO DO:
-;;
-;; (apply '(lambda (x &rest y) ...) 1 (foo))
-;;
-;; maintain a list of functions known not to access any global variables
-;; (actually, give them a 'dynamically-safe property) and then
-;; (let ( v1 v2 ... vM vN ) <...dynamically-safe...> ) ==>
-;; (let ( v1 v2 ... vM ) vN <...dynamically-safe...> )
-;; by recursing on this, we might be able to eliminate the entire let.
-;; However certain variables should never have their bindings optimized
-;; away, because they affect everything.
-;; (put 'debug-on-error 'binding-is-magic t)
-;; (put 'debug-on-abort 'binding-is-magic t)
-;; (put 'debug-on-next-call 'binding-is-magic t)
-;; (put 'mocklisp-arguments 'binding-is-magic t)
-;; (put 'inhibit-quit 'binding-is-magic t)
-;; (put 'quit-flag 'binding-is-magic t)
-;; (put 't 'binding-is-magic t)
-;; (put 'nil 'binding-is-magic t)
-;; possibly also
-;; (put 'gc-cons-threshold 'binding-is-magic t)
-;; (put 'track-mouse 'binding-is-magic t)
-;; others?
-;;
-;; Simple defsubsts often produce forms like
-;; (let ((v1 (f1)) (v2 (f2)) ...)
-;; (FN v1 v2 ...))
-;; It would be nice if we could optimize this to
-;; (FN (f1) (f2) ...)
-;; but we can't unless FN is dynamically-safe (it might be dynamically
-;; referring to the bindings that the lambda arglist established.)
-;; One of the uncountable lossages introduced by dynamic scope...
-;;
-;; Maybe there should be a control-structure that says "turn on
-;; fast-and-loose type-assumptive optimizations here." Then when
-;; we see a form like (car foo) we can from then on assume that
-;; the variable foo is of type cons, and optimize based on that.
-;; But, this won't win much because of (you guessed it) dynamic
-;; scope. Anything down the stack could change the value.
-;; (Another reason it doesn't work is that it is perfectly valid
-;; to call car with a null argument.) A better approach might
-;; be to allow type-specification of the form
-;; (put 'foo 'arg-types '(float (list integer) dynamic))
-;; (put 'foo 'result-type 'bool)
-;; It should be possible to have these types checked to a certain
-;; degree.
-;;
-;; collapse common subexpressions
-;;
-;; It would be nice if redundant sequences could be factored out as well,
-;; when they are known to have no side-effects:
-;; (list (+ a b c) (+ a b c)) --> a b add c add dup list-2
-;; but beware of traps like
-;; (cons (list x y) (list x y))
-;;
-;; Tail-recursion elimination is not really possible in Emacs Lisp.
-;; Tail-recursion elimination is almost always impossible when all variables
-;; have dynamic scope, but given that the "return" byteop requires the
-;; binding stack to be empty (rather than emptying it itself), there can be
-;; no truly tail-recursive Emacs Lisp functions that take any arguments or
-;; make any bindings.
-;;
-;; Here is an example of an Emacs Lisp function which could safely be
-;; byte-compiled tail-recursively:
-;;
-;; (defun tail-map (fn list)
-;; (cond (list
-;; (funcall fn (car list))
-;; (tail-map fn (cdr list)))))
-;;
-;; However, if there was even a single let-binding around the COND,
-;; it could not be byte-compiled, because there would be an "unbind"
-;; byte-op between the final "call" and "return." Adding a
-;; Bunbind_all byteop would fix this.
-;;
-;; (defun foo (x y z) ... (foo a b c))
-;; ... (const foo) (varref a) (varref b) (varref c) (call 3) END: (return)
-;; ... (varref a) (varbind x) (varref b) (varbind y) (varref c) (varbind z) (goto 0) END: (unbind-all) (return)
-;; ... (varref a) (varset x) (varref b) (varset y) (varref c) (varset z) (goto 0) END: (return)
-;;
-;; this also can be considered tail recursion:
-;;
-;; ... (const foo) (varref a) (call 1) (goto X) ... X: (return)
-;; could generalize this by doing the optimization
-;; (goto X) ... X: (return) --> (return)
-;;
-;; But this doesn't solve all of the problems: although by doing tail-
-;; recursion elimination in this way, the call-stack does not grow, the
-;; binding-stack would grow with each recursive step, and would eventually
-;; overflow. I don't believe there is any way around this without lexical
-;; scope.
-;;
-;; Wouldn't it be nice if Emacs Lisp had lexical scope.
-;;
-;; Idea: the form (lexical-scope) in a file means that the file may be
-;; compiled lexically. This proclamation is file-local. Then, within
-;; that file, "let" would establish lexical bindings, and "let-dynamic"
-;; would do things the old way. (Or we could use CL "declare" forms.)
-;; We'd have to notice defvars and defconsts, since those variables should
-;; always be dynamic, and attempting to do a lexical binding of them
-;; should simply do a dynamic binding instead.
-;; But! We need to know about variables that were not necessarily defvarred
-;; in the file being compiled (doing a boundp check isn't good enough.)
-;; Fdefvar() would have to be modified to add something to the plist.
-;;
-;; A major disadvantage of this scheme is that the interpreter and compiler
-;; would have different semantics for files compiled with (dynamic-scope).
-;; Since this would be a file-local optimization, there would be no way to
-;; modify the interpreter to obey this (unless the loader was hacked
-;; in some grody way, but that's a really bad idea.)
-
-;; Other things to consider:
-
-;;;;; Associative math should recognize subcalls to identical function:
-;;;(disassemble (lambda (x) (+ (+ (foo) 1) (+ (bar) 2))))
-;;;;; This should generate the same as (1+ x) and (1- x)
-
-;;;(disassemble (lambda (x) (cons (+ x 1) (- x 1))))
-;;;;; An awful lot of functions always return a non-nil value. If they're
-;;;;; error free also they may act as true-constants.
-
-;;;(disassemble (lambda (x) (and (point) (foo))))
-;;;;; When
-;;;;; - all but one arguments to a function are constant
-;;;;; - the non-constant argument is an if-expression (cond-expression?)
-;;;;; then the outer function can be distributed. If the guarding
-;;;;; condition is side-effect-free [assignment-free] then the other
-;;;;; arguments may be any expressions. Since, however, the code size
-;;;;; can increase this way they should be "simple". Compare:
-
-;;;(disassemble (lambda (x) (eq (if (point) 'a 'b) 'c)))
-;;;(disassemble (lambda (x) (if (point) (eq 'a 'c) (eq 'b 'c))))
-
-;;;;; (car (cons A B)) -> (progn B A)
-;;;(disassemble (lambda (x) (car (cons (foo) 42))))
-
-;;;;; (cdr (cons A B)) -> (progn A B)
-;;;(disassemble (lambda (x) (cdr (cons 42 (foo)))))
-
-;;;;; (car (list A B ...)) -> (progn B ... A)
-;;;(disassemble (lambda (x) (car (list (foo) 42 (bar)))))
-
-;;;;; (cdr (list A B ...)) -> (progn A (list B ...))
-;;;(disassemble (lambda (x) (cdr (list 42 (foo) (bar)))))
-
-
-;;; Code:
-
-(defun byte-compile-log-lap-1 (format &rest args)
- (if (aref byte-code-vector 0)
- (error "The old version of the disassembler is loaded. Reload new-bytecomp as well."))
- (byte-compile-log-1
- (apply 'format format
- (let (c a)
- (mapcar '(lambda (arg)
- (if (not (consp arg))
- (if (and (symbolp arg)
- (string-match "^byte-" (symbol-name arg)))
- (intern (substring (symbol-name arg) 5))
- arg)
- (if (integerp (setq c (car arg)))
- (error "non-symbolic byte-op %s" c))
- (if (eq c 'TAG)
- (setq c arg)
- (setq a (cond ((memq c byte-goto-ops)
- (car (cdr (cdr arg))))
- ((memq c byte-constref-ops)
- (car (cdr arg)))
- (t (cdr arg))))
- (setq c (symbol-name c))
- (if (string-match "^byte-." c)
- (setq c (intern (substring c 5)))))
- (if (eq c 'constant) (setq c 'const))
- (if (and (eq (cdr arg) 0)
- (not (memq c '(unbind call const))))
- c
- (format "(%s %s)" c a))))
- args)))))
-
-(defmacro byte-compile-log-lap (format-string &rest args)
- (list 'and
- '(memq byte-optimize-log '(t byte))
- (cons 'byte-compile-log-lap-1
- (cons format-string args))))
-
-
-;;; byte-compile optimizers to support inlining
-
-(put 'inline 'byte-optimizer 'byte-optimize-inline-handler)
-
-(defun byte-optimize-inline-handler (form)
- "byte-optimize-handler for the `inline' special-form."
- (cons 'progn
- (mapcar
- '(lambda (sexp)
- (let ((fn (car-safe sexp)))
- (if (and (symbolp fn)
- (or (cdr (assq fn byte-compile-function-environment))
- (and (fboundp fn)
- (not (or (cdr (assq fn byte-compile-macro-environment))
- (and (consp (setq fn (symbol-function fn)))
- (eq (car fn) 'macro))
- (subrp fn))))))
- (byte-compile-inline-expand sexp)
- sexp)))
- (cdr form))))
-
-
-;; Splice the given lap code into the current instruction stream.
-;; If it has any labels in it, you're responsible for making sure there
-;; are no collisions, and that byte-compile-tag-number is reasonable
-;; after this is spliced in. The provided list is destroyed.
-(defun byte-inline-lapcode (lap)
- (setq byte-compile-output (nconc (nreverse lap) byte-compile-output)))
-
-
-(defun byte-compile-inline-expand (form)
- (let* ((name (car form))
- (fn (or (cdr (assq name byte-compile-function-environment))
- (and (fboundp name) (symbol-function name)))))
- (if (null fn)
- (progn
- (byte-compile-warn "attempt to inline %s before it was defined" name)
- form)
- ;; else
- (if (and (consp fn) (eq (car fn) 'autoload))
- (load (nth 1 fn)))
- (if (and (consp fn) (eq (car fn) 'autoload))
- (error "file \"%s\" didn't define \"%s\"" (nth 1 fn) name))
- (if (symbolp fn)
- (byte-compile-inline-expand (cons fn (cdr form)))
- (if (byte-code-function-p fn)
- (progn
- (fetch-bytecode fn)
- (cons (list 'lambda (aref fn 0)
- (list 'byte-code (aref fn 1) (aref fn 2) (aref fn 3)))
- (cdr form)))
- (if (not (eq (car fn) 'lambda)) (error "%s is not a lambda" name))
- (cons fn (cdr form)))))))
-
-;;; ((lambda ...) ...)
-;;;
-(defun byte-compile-unfold-lambda (form &optional name)
- (or name (setq name "anonymous lambda"))
- (let ((lambda (car form))
- (values (cdr form)))
- (if (byte-code-function-p lambda)
- (setq lambda (list 'lambda (aref lambda 0)
- (list 'byte-code (aref lambda 1)
- (aref lambda 2) (aref lambda 3)))))
- (let ((arglist (nth 1 lambda))
- (body (cdr (cdr lambda)))
- optionalp restp
- bindings)
- (if (and (stringp (car body)) (cdr body))
- (setq body (cdr body)))
- (if (and (consp (car body)) (eq 'interactive (car (car body))))
- (setq body (cdr body)))
- (while arglist
- (cond ((eq (car arglist) '&optional)
- ;; ok, I'll let this slide because funcall_lambda() does...
- ;; (if optionalp (error "multiple &optional keywords in %s" name))
- (if restp (error "&optional found after &rest in %s" name))
- (if (null (cdr arglist))
- (error "nothing after &optional in %s" name))
- (setq optionalp t))
- ((eq (car arglist) '&rest)
- ;; ...but it is by no stretch of the imagination a reasonable
- ;; thing that funcall_lambda() allows (&rest x y) and
- ;; (&rest x &optional y) in arglists.
- (if (null (cdr arglist))
- (error "nothing after &rest in %s" name))
- (if (cdr (cdr arglist))
- (error "multiple vars after &rest in %s" name))
- (setq restp t))
- (restp
- (setq bindings (cons (list (car arglist)
- (and values (cons 'list values)))
- bindings)
- values nil))
- ((and (not optionalp) (null values))
- (byte-compile-warn "attempt to open-code %s with too few arguments" name)
- (setq arglist nil values 'too-few))
- (t
- (setq bindings (cons (list (car arglist) (car values))
- bindings)
- values (cdr values))))
- (setq arglist (cdr arglist)))
- (if values
- (progn
- (or (eq values 'too-few)
- (byte-compile-warn
- "attempt to open-code %s with too many arguments" name))
- form)
- (setq body (mapcar 'byte-optimize-form body))
- (let ((newform
- (if bindings
- (cons 'let (cons (nreverse bindings) body))
- (cons 'progn body))))
- (byte-compile-log " %s\t==>\t%s" form newform)
- newform)))))
-
-
-;;; implementing source-level optimizers
-
-(defun byte-optimize-form-code-walker (form for-effect)
- ;;
- ;; For normal function calls, We can just mapcar the optimizer the cdr. But
- ;; we need to have special knowledge of the syntax of the special forms
- ;; like let and defun (that's why they're special forms :-). (Actually,
- ;; the important aspect is that they are subrs that don't evaluate all of
- ;; their args.)
- ;;
- (let ((fn (car-safe form))
- tmp)
- (cond ((not (consp form))
- (if (not (and for-effect
- (or byte-compile-delete-errors
- (not (symbolp form))
- (eq form t))))
- form))
- ((eq fn 'quote)
- (if (cdr (cdr form))
- (byte-compile-warn "malformed quote form: %s"
- (prin1-to-string form)))
- ;; map (quote nil) to nil to simplify optimizer logic.
- ;; map quoted constants to nil if for-effect (just because).
- (and (nth 1 form)
- (not for-effect)
- form))
- ((or (byte-code-function-p fn)
- (eq 'lambda (car-safe fn)))
- (byte-compile-unfold-lambda form))
- ((memq fn '(let let*))
- ;; recursively enter the optimizer for the bindings and body
- ;; of a let or let*. This for depth-firstness: forms that
- ;; are more deeply nested are optimized first.
- (cons fn
- (cons
- (mapcar '(lambda (binding)
- (if (symbolp binding)
- binding
- (if (cdr (cdr binding))
- (byte-compile-warn "malformed let binding: %s"
- (prin1-to-string binding)))
- (list (car binding)
- (byte-optimize-form (nth 1 binding) nil))))
- (nth 1 form))
- (byte-optimize-body (cdr (cdr form)) for-effect))))
- ((eq fn 'cond)
- (cons fn
- (mapcar '(lambda (clause)
- (if (consp clause)
- (cons
- (byte-optimize-form (car clause) nil)
- (byte-optimize-body (cdr clause) for-effect))
- (byte-compile-warn "malformed cond form: %s"
- (prin1-to-string clause))
- clause))
- (cdr form))))
- ((eq fn 'progn)
- ;; as an extra added bonus, this simplifies (progn <x>) --> <x>
- (if (cdr (cdr form))
- (progn
- (setq tmp (byte-optimize-body (cdr form) for-effect))
- (if (cdr tmp) (cons 'progn tmp) (car tmp)))
- (byte-optimize-form (nth 1 form) for-effect)))
- ((eq fn 'prog1)
- (if (cdr (cdr form))
- (cons 'prog1
- (cons (byte-optimize-form (nth 1 form) for-effect)
- (byte-optimize-body (cdr (cdr form)) t)))
- (byte-optimize-form (nth 1 form) for-effect)))
- ((eq fn 'prog2)
- (cons 'prog2
- (cons (byte-optimize-form (nth 1 form) t)
- (cons (byte-optimize-form (nth 2 form) for-effect)
- (byte-optimize-body (cdr (cdr (cdr form))) t)))))
-
- ((memq fn '(save-excursion save-restriction save-current-buffer))
- ;; those subrs which have an implicit progn; it's not quite good
- ;; enough to treat these like normal function calls.
- ;; This can turn (save-excursion ...) into (save-excursion) which
- ;; will be optimized away in the lap-optimize pass.
- (cons fn (byte-optimize-body (cdr form) for-effect)))
-
- ((eq fn 'with-output-to-temp-buffer)
- ;; this is just like the above, except for the first argument.
- (cons fn
- (cons
- (byte-optimize-form (nth 1 form) nil)
- (byte-optimize-body (cdr (cdr form)) for-effect))))
-
- ((eq fn 'if)
- (cons fn
- (cons (byte-optimize-form (nth 1 form) nil)
- (cons
- (byte-optimize-form (nth 2 form) for-effect)
- (byte-optimize-body (nthcdr 3 form) for-effect)))))
-
- ((memq fn '(and or)) ; remember, and/or are control structures.
- ;; take forms off the back until we can't any more.
- ;; In the future it could conceivably be a problem that the
- ;; subexpressions of these forms are optimized in the reverse
- ;; order, but it's ok for now.
- (if for-effect
- (let ((backwards (reverse (cdr form))))
- (while (and backwards
- (null (setcar backwards
- (byte-optimize-form (car backwards)
- for-effect))))
- (setq backwards (cdr backwards)))
- (if (and (cdr form) (null backwards))
- (byte-compile-log
- " all subforms of %s called for effect; deleted" form))
- (and backwards
- (cons fn (nreverse backwards))))
- (cons fn (mapcar 'byte-optimize-form (cdr form)))))
-
- ((eq fn 'interactive)
- (byte-compile-warn "misplaced interactive spec: %s"
- (prin1-to-string form))
- nil)
-
- ((memq fn '(defun defmacro function
- condition-case save-window-excursion))
- ;; These forms are compiled as constants or by breaking out
- ;; all the subexpressions and compiling them separately.
- form)
-
- ((eq fn 'unwind-protect)
- ;; the "protected" part of an unwind-protect is compiled (and thus
- ;; optimized) as a top-level form, so don't do it here. But the
- ;; non-protected part has the same for-effect status as the
- ;; unwind-protect itself. (The protected part is always for effect,
- ;; but that isn't handled properly yet.)
- (cons fn
- (cons (byte-optimize-form (nth 1 form) for-effect)
- (cdr (cdr form)))))
-
- ((eq fn 'catch)
- ;; the body of a catch is compiled (and thus optimized) as a
- ;; top-level form, so don't do it here. The tag is never
- ;; for-effect. The body should have the same for-effect status
- ;; as the catch form itself, but that isn't handled properly yet.
- (cons fn
- (cons (byte-optimize-form (nth 1 form) nil)
- (cdr (cdr form)))))
-
- ;; If optimization is on, this is the only place that macros are
- ;; expanded. If optimization is off, then macroexpansion happens
- ;; in byte-compile-form. Otherwise, the macros are already expanded
- ;; by the time that is reached.
- ((not (eq form
- (setq form (macroexpand form
- byte-compile-macro-environment))))
- (byte-optimize-form form for-effect))
-
- ((not (symbolp fn))
- (or (eq 'mocklisp (car-safe fn)) ; ha!
- (byte-compile-warn "%s is a malformed function"
- (prin1-to-string fn)))
- form)
-
- ((and for-effect (setq tmp (get fn 'side-effect-free))
- (or byte-compile-delete-errors
- (eq tmp 'error-free)
- (progn
- (byte-compile-warn "%s called for effect"
- (prin1-to-string form))
- nil)))
- (byte-compile-log " %s called for effect; deleted" fn)
- ;; appending a nil here might not be necessary, but it can't hurt.
- (byte-optimize-form
- (cons 'progn (append (cdr form) '(nil))) t))
-
- (t
- ;; Otherwise, no args can be considered to be for-effect,
- ;; even if the called function is for-effect, because we
- ;; don't know anything about that function.
- (cons fn (mapcar 'byte-optimize-form (cdr form)))))))
-
-
-(defun byte-optimize-form (form &optional for-effect)
- "The source-level pass of the optimizer."
- ;;
- ;; First, optimize all sub-forms of this one.
- (setq form (byte-optimize-form-code-walker form for-effect))
- ;;
- ;; after optimizing all subforms, optimize this form until it doesn't
- ;; optimize any further. This means that some forms will be passed through
- ;; the optimizer many times, but that's necessary to make the for-effect
- ;; processing do as much as possible.
- ;;
- (let (opt new)
- (if (and (consp form)
- (symbolp (car form))
- (or (and for-effect
- ;; we don't have any of these yet, but we might.
- (setq opt (get (car form) 'byte-for-effect-optimizer)))
- (setq opt (get (car form) 'byte-optimizer)))
- (not (eq form (setq new (funcall opt form)))))
- (progn
-;; (if (equal form new) (error "bogus optimizer -- %s" opt))
- (byte-compile-log " %s\t==>\t%s" form new)
- (setq new (byte-optimize-form new for-effect))
- new)
- form)))
-
-
-(defun byte-optimize-body (forms all-for-effect)
- ;; optimize the cdr of a progn or implicit progn; all forms is a list of
- ;; forms, all but the last of which are optimized with the assumption that
- ;; they are being called for effect. the last is for-effect as well if
- ;; all-for-effect is true. returns a new list of forms.
- (let ((rest forms)
- (result nil)
- fe new)
- (while rest
- (setq fe (or all-for-effect (cdr rest)))
- (setq new (and (car rest) (byte-optimize-form (car rest) fe)))
- (if (or new (not fe))
- (setq result (cons new result)))
- (setq rest (cdr rest)))
- (nreverse result)))
-
-
-;;; some source-level optimizers
-;;;
-;;; when writing optimizers, be VERY careful that the optimizer returns
-;;; something not EQ to its argument if and ONLY if it has made a change.
-;;; This implies that you cannot simply destructively modify the list;
-;;; you must return something not EQ to it if you make an optimization.
-;;;
-;;; It is now safe to optimize code such that it introduces new bindings.
-
-;; I'd like this to be a defsubst, but let's not be self-referential...
-(defmacro byte-compile-trueconstp (form)
- ;; Returns non-nil if FORM is a non-nil constant.
- (` (cond ((consp (, form)) (eq (car (, form)) 'quote))
- ((not (symbolp (, form))))
- ((eq (, form) t)))))
-
-;; If the function is being called with constant numeric args,
-;; evaluate as much as possible at compile-time. This optimizer
-;; assumes that the function is associative, like + or *.
-(defun byte-optimize-associative-math (form)
- (let ((args nil)
- (constants nil)
- (rest (cdr form)))
- (while rest
- (if (numberp (car rest))
- (setq constants (cons (car rest) constants))
- (setq args (cons (car rest) args)))
- (setq rest (cdr rest)))
- (if (cdr constants)
- (if args
- (list (car form)
- (apply (car form) constants)
- (if (cdr args)
- (cons (car form) (nreverse args))
- (car args)))
- (apply (car form) constants))
- form)))
-
-;; If the function is being called with constant numeric args,
-;; evaluate as much as possible at compile-time. This optimizer
-;; assumes that the function satisfies
-;; (op x1 x2 ... xn) == (op ...(op (op x1 x2) x3) ...xn)
-;; like - and /.
-(defun byte-optimize-nonassociative-math (form)
- (if (or (not (numberp (car (cdr form))))
- (not (numberp (car (cdr (cdr form))))))
- form
- (let ((constant (car (cdr form)))
- (rest (cdr (cdr form))))
- (while (numberp (car rest))
- (setq constant (funcall (car form) constant (car rest))
- rest (cdr rest)))
- (if rest
- (cons (car form) (cons constant rest))
- constant))))
-
-;;(defun byte-optimize-associative-two-args-math (form)
-;; (setq form (byte-optimize-associative-math form))
-;; (if (consp form)
-;; (byte-optimize-two-args-left form)
-;; form))
-
-;;(defun byte-optimize-nonassociative-two-args-math (form)
-;; (setq form (byte-optimize-nonassociative-math form))
-;; (if (consp form)
-;; (byte-optimize-two-args-right form)
-;; form))
-
-(defun byte-optimize-approx-equal (x y)
- (< (* (abs (- x y)) 100) (abs (+ x y))))
-
-;; Collect all the constants from FORM, after the STARTth arg,
-;; and apply FUN to them to make one argument at the end.
-;; For functions that can handle floats, that optimization
-;; can be incorrect because reordering can cause an overflow
-;; that would otherwise be avoided by encountering an arg that is a float.
-;; We avoid this problem by (1) not moving float constants and
-;; (2) not moving anything if it would cause an overflow.
-(defun byte-optimize-delay-constants-math (form start fun)
- ;; Merge all FORM's constants from number START, call FUN on them
- ;; and put the result at the end.
- (let ((rest (nthcdr (1- start) form))
- (orig form)
- ;; t means we must check for overflow.
- (overflow (memq fun '(+ *))))
- (while (cdr (setq rest (cdr rest)))
- (if (integerp (car rest))
- (let (constants)
- (setq form (copy-sequence form)
- rest (nthcdr (1- start) form))
- (while (setq rest (cdr rest))
- (cond ((integerp (car rest))
- (setq constants (cons (car rest) constants))
- (setcar rest nil))))
- ;; If necessary, check now for overflow
- ;; that might be caused by reordering.
- (if (and overflow
- ;; We have overflow if the result of doing the arithmetic
- ;; on floats is not even close to the result
- ;; of doing it on integers.
- (not (byte-optimize-approx-equal
- (apply fun (mapcar 'float constants))
- (float (apply fun constants)))))
- (setq form orig)
- (setq form (nconc (delq nil form)
- (list (apply fun (nreverse constants)))))))))
- form))
-
-(defun byte-optimize-plus (form)
- (setq form (byte-optimize-delay-constants-math form 1 '+))
- (if (memq 0 form) (setq form (delq 0 (copy-sequence form))))
- ;;(setq form (byte-optimize-associative-two-args-math form))
- (cond ((null (cdr form))
- (condition-case ()
- (eval form)
- (error form)))
-;;; It is not safe to delete the function entirely
-;;; (actually, it would be safe if we know the sole arg
-;;; is not a marker).
-;; ((null (cdr (cdr form))) (nth 1 form))
- (t form)))
-
-(defun byte-optimize-minus (form)
- ;; Put constants at the end, except the last constant.
- (setq form (byte-optimize-delay-constants-math form 2 '+))
- ;; Now only first and last element can be a number.
- (let ((last (car (reverse (nthcdr 3 form)))))
- (cond ((eq 0 last)
- ;; (- x y ... 0) --> (- x y ...)
- (setq form (copy-sequence form))
- (setcdr (cdr (cdr form)) (delq 0 (nthcdr 3 form))))
- ;; If form is (- CONST foo... CONST), merge first and last.
- ((and (numberp (nth 1 form))
- (numberp last))
- (setq form (nconc (list '- (- (nth 1 form) last) (nth 2 form))
- (delq last (copy-sequence (nthcdr 3 form))))))))
-;;; It is not safe to delete the function entirely
-;;; (actually, it would be safe if we know the sole arg
-;;; is not a marker).
-;;; (if (eq (nth 2 form) 0)
-;;; (nth 1 form) ; (- x 0) --> x
- (byte-optimize-predicate
- (if (and (null (cdr (cdr (cdr form))))
- (eq (nth 1 form) 0)) ; (- 0 x) --> (- x)
- (cons (car form) (cdr (cdr form)))
- form))
-;;; )
- )
-
-(defun byte-optimize-multiply (form)
- (setq form (byte-optimize-delay-constants-math form 1 '*))
- ;; If there is a constant in FORM, it is now the last element.
- (cond ((null (cdr form)) 1)
-;;; It is not safe to delete the function entirely
-;;; (actually, it would be safe if we know the sole arg
-;;; is not a marker or if it appears in other arithmetic).
-;;; ((null (cdr (cdr form))) (nth 1 form))
- ((let ((last (car (reverse form))))
- (cond ((eq 0 last) (cons 'progn (cdr form)))
- ((eq 1 last) (delq 1 (copy-sequence form)))
- ((eq -1 last) (list '- (delq -1 (copy-sequence form))))
- ((and (eq 2 last)
- (memq t (mapcar 'symbolp (cdr form))))
- (prog1 (setq form (delq 2 (copy-sequence form)))
- (while (not (symbolp (car (setq form (cdr form))))))
- (setcar form (list '+ (car form) (car form)))))
- (form))))))
-
-(defsubst byte-compile-butlast (form)
- (nreverse (cdr (reverse form))))
-
-(defun byte-optimize-divide (form)
- (setq form (byte-optimize-delay-constants-math form 2 '*))
- (let ((last (car (reverse (cdr (cdr form))))))
- (if (numberp last)
- (cond ((= (length form) 3)
- (if (and (numberp (nth 1 form))
- (not (zerop last))
- (condition-case nil
- (/ (nth 1 form) last)
- (error nil)))
- (setq form (list 'progn (/ (nth 1 form) last)))))
- ((= last 1)
- (setq form (byte-compile-butlast form)))
- ((numberp (nth 1 form))
- (setq form (cons (car form)
- (cons (/ (nth 1 form) last)
- (byte-compile-butlast (cdr (cdr form)))))
- last nil))))
- (cond
-;;; ((null (cdr (cdr form)))
-;;; (nth 1 form))
- ((eq (nth 1 form) 0)
- (append '(progn) (cdr (cdr form)) '(0)))
- ((eq last -1)
- (list '- (if (nthcdr 3 form)
- (byte-compile-butlast form)
- (nth 1 form))))
- (form))))
-
-(defun byte-optimize-logmumble (form)
- (setq form (byte-optimize-delay-constants-math form 1 (car form)))
- (byte-optimize-predicate
- (cond ((memq 0 form)
- (setq form (if (eq (car form) 'logand)
- (cons 'progn (cdr form))
- (delq 0 (copy-sequence form)))))
- ((and (eq (car-safe form) 'logior)
- (memq -1 form))
- (cons 'progn (cdr form)))
- (form))))
-
-
-(defun byte-optimize-binary-predicate (form)
- (if (byte-compile-constp (nth 1 form))
- (if (byte-compile-constp (nth 2 form))
- (condition-case ()
- (list 'quote (eval form))
- (error form))
- ;; This can enable some lapcode optimizations.
- (list (car form) (nth 2 form) (nth 1 form)))
- form))
-
-(defun byte-optimize-predicate (form)
- (let ((ok t)
- (rest (cdr form)))
- (while (and rest ok)
- (setq ok (byte-compile-constp (car rest))
- rest (cdr rest)))
- (if ok
- (condition-case ()
- (list 'quote (eval form))
- (error form))
- form)))
-
-(defun byte-optimize-identity (form)
- (if (and (cdr form) (null (cdr (cdr form))))
- (nth 1 form)
- (byte-compile-warn "identity called with %d arg%s, but requires 1"
- (length (cdr form))
- (if (= 1 (length (cdr form))) "" "s"))
- form))
-
-(put 'identity 'byte-optimizer 'byte-optimize-identity)
-
-(put '+ 'byte-optimizer 'byte-optimize-plus)
-(put '* 'byte-optimizer 'byte-optimize-multiply)
-(put '- 'byte-optimizer 'byte-optimize-minus)
-(put '/ 'byte-optimizer 'byte-optimize-divide)
-(put 'max 'byte-optimizer 'byte-optimize-associative-math)
-(put 'min 'byte-optimizer 'byte-optimize-associative-math)
-
-(put '= 'byte-optimizer 'byte-optimize-binary-predicate)
-(put 'eq 'byte-optimizer 'byte-optimize-binary-predicate)
-(put 'eql 'byte-optimizer 'byte-optimize-binary-predicate)
-(put 'equal 'byte-optimizer 'byte-optimize-binary-predicate)
-(put 'string= 'byte-optimizer 'byte-optimize-binary-predicate)
-(put 'string-equal 'byte-optimizer 'byte-optimize-binary-predicate)
-
-(put '< 'byte-optimizer 'byte-optimize-predicate)
-(put '> 'byte-optimizer 'byte-optimize-predicate)
-(put '<= 'byte-optimizer 'byte-optimize-predicate)
-(put '>= 'byte-optimizer 'byte-optimize-predicate)
-(put '1+ 'byte-optimizer 'byte-optimize-predicate)
-(put '1- 'byte-optimizer 'byte-optimize-predicate)
-(put 'not 'byte-optimizer 'byte-optimize-predicate)
-(put 'null 'byte-optimizer 'byte-optimize-predicate)
-(put 'memq 'byte-optimizer 'byte-optimize-predicate)
-(put 'consp 'byte-optimizer 'byte-optimize-predicate)
-(put 'listp 'byte-optimizer 'byte-optimize-predicate)
-(put 'symbolp 'byte-optimizer 'byte-optimize-predicate)
-(put 'stringp 'byte-optimizer 'byte-optimize-predicate)
-(put 'string< 'byte-optimizer 'byte-optimize-predicate)
-(put 'string-lessp 'byte-optimizer 'byte-optimize-predicate)
-
-(put 'logand 'byte-optimizer 'byte-optimize-logmumble)
-(put 'logior 'byte-optimizer 'byte-optimize-logmumble)
-(put 'logxor 'byte-optimizer 'byte-optimize-logmumble)
-(put 'lognot 'byte-optimizer 'byte-optimize-predicate)
-
-(put 'car 'byte-optimizer 'byte-optimize-predicate)
-(put 'cdr 'byte-optimizer 'byte-optimize-predicate)
-(put 'car-safe 'byte-optimizer 'byte-optimize-predicate)
-(put 'cdr-safe 'byte-optimizer 'byte-optimize-predicate)
-
-
-;; I'm not convinced that this is necessary. Doesn't the optimizer loop
-;; take care of this? - Jamie
-;; I think this may some times be necessary to reduce ie (quote 5) to 5,
-;; so arithmetic optimizers recognize the numeric constant. - Hallvard
-(put 'quote 'byte-optimizer 'byte-optimize-quote)
-(defun byte-optimize-quote (form)
- (if (or (consp (nth 1 form))
- (and (symbolp (nth 1 form))
- (not (memq (nth 1 form) '(nil t)))))
- form
- (nth 1 form)))
-
-(defun byte-optimize-zerop (form)
- (cond ((numberp (nth 1 form))
- (eval form))
- (byte-compile-delete-errors
- (list '= (nth 1 form) 0))
- (form)))
-
-(put 'zerop 'byte-optimizer 'byte-optimize-zerop)
-
-(defun byte-optimize-and (form)
- ;; Simplify if less than 2 args.
- ;; if there is a literal nil in the args to `and', throw it and following
- ;; forms away, and surround the `and' with (progn ... nil).
- (cond ((null (cdr form)))
- ((memq nil form)
- (list 'progn
- (byte-optimize-and
- (prog1 (setq form (copy-sequence form))
- (while (nth 1 form)
- (setq form (cdr form)))
- (setcdr form nil)))
- nil))
- ((null (cdr (cdr form)))
- (nth 1 form))
- ((byte-optimize-predicate form))))
-
-(defun byte-optimize-or (form)
- ;; Throw away nil's, and simplify if less than 2 args.
- ;; If there is a literal non-nil constant in the args to `or', throw away all
- ;; following forms.
- (if (memq nil form)
- (setq form (delq nil (copy-sequence form))))
- (let ((rest form))
- (while (cdr (setq rest (cdr rest)))
- (if (byte-compile-trueconstp (car rest))
- (setq form (copy-sequence form)
- rest (setcdr (memq (car rest) form) nil))))
- (if (cdr (cdr form))
- (byte-optimize-predicate form)
- (nth 1 form))))
-
-(defun byte-optimize-cond (form)
- ;; if any clauses have a literal nil as their test, throw them away.
- ;; if any clause has a literal non-nil constant as its test, throw
- ;; away all following clauses.
- (let (rest)
- ;; This must be first, to reduce (cond (t ...) (nil)) to (progn t ...)
- (while (setq rest (assq nil (cdr form)))
- (setq form (delq rest (copy-sequence form))))
- (if (memq nil (cdr form))
- (setq form (delq nil (copy-sequence form))))
- (setq rest form)
- (while (setq rest (cdr rest))
- (cond ((byte-compile-trueconstp (car-safe (car rest)))
- (cond ((eq rest (cdr form))
- (setq form
- (if (cdr (car rest))
- (if (cdr (cdr (car rest)))
- (cons 'progn (cdr (car rest)))
- (nth 1 (car rest)))
- (car (car rest)))))
- ((cdr rest)
- (setq form (copy-sequence form))
- (setcdr (memq (car rest) form) nil)))
- (setq rest nil)))))
- ;;
- ;; Turn (cond (( <x> )) ... ) into (or <x> (cond ... ))
- (if (eq 'cond (car-safe form))
- (let ((clauses (cdr form)))
- (if (and (consp (car clauses))
- (null (cdr (car clauses))))
- (list 'or (car (car clauses))
- (byte-optimize-cond
- (cons (car form) (cdr (cdr form)))))
- form))
- form))
-
-(defun byte-optimize-if (form)
- ;; (if <true-constant> <then> <else...>) ==> <then>
- ;; (if <false-constant> <then> <else...>) ==> (progn <else...>)
- ;; (if <test> nil <else...>) ==> (if (not <test>) (progn <else...>))
- ;; (if <test> <then> nil) ==> (if <test> <then>)
- (let ((clause (nth 1 form)))
- (cond ((byte-compile-trueconstp clause)
- (nth 2 form))
- ((null clause)
- (if (nthcdr 4 form)
- (cons 'progn (nthcdr 3 form))
- (nth 3 form)))
- ((nth 2 form)
- (if (equal '(nil) (nthcdr 3 form))
- (list 'if clause (nth 2 form))
- form))
- ((or (nth 3 form) (nthcdr 4 form))
- (list 'if
- ;; Don't make a double negative;
- ;; instead, take away the one that is there.
- (if (and (consp clause) (memq (car clause) '(not null))
- (= (length clause) 2)) ; (not xxxx) or (not (xxxx))
- (nth 1 clause)
- (list 'not clause))
- (if (nthcdr 4 form)
- (cons 'progn (nthcdr 3 form))
- (nth 3 form))))
- (t
- (list 'progn clause nil)))))
-
-(defun byte-optimize-while (form)
- (if (nth 1 form)
- form))
-
-(put 'and 'byte-optimizer 'byte-optimize-and)
-(put 'or 'byte-optimizer 'byte-optimize-or)
-(put 'cond 'byte-optimizer 'byte-optimize-cond)
-(put 'if 'byte-optimizer 'byte-optimize-if)
-(put 'while 'byte-optimizer 'byte-optimize-while)
-
-;; byte-compile-negation-optimizer lives in bytecomp.el
-(put '/= 'byte-optimizer 'byte-compile-negation-optimizer)
-(put 'atom 'byte-optimizer 'byte-compile-negation-optimizer)
-(put 'nlistp 'byte-optimizer 'byte-compile-negation-optimizer)
-
-
-(defun byte-optimize-funcall (form)
- ;; (funcall '(lambda ...) ...) ==> ((lambda ...) ...)
- ;; (funcall 'foo ...) ==> (foo ...)
- (let ((fn (nth 1 form)))
- (if (memq (car-safe fn) '(quote function))
- (cons (nth 1 fn) (cdr (cdr form)))
- form)))
-
-(defun byte-optimize-apply (form)
- ;; If the last arg is a literal constant, turn this into a funcall.
- ;; The funcall optimizer can then transform (funcall 'foo ...) -> (foo ...).
- (let ((fn (nth 1 form))
- (last (nth (1- (length form)) form))) ; I think this really is fastest
- (or (if (or (null last)
- (eq (car-safe last) 'quote))
- (if (listp (nth 1 last))
- (let ((butlast (nreverse (cdr (reverse (cdr (cdr form)))))))
- (nconc (list 'funcall fn) butlast
- (mapcar '(lambda (x) (list 'quote x)) (nth 1 last))))
- (byte-compile-warn
- "last arg to apply can't be a literal atom: %s"
- (prin1-to-string last))
- nil))
- form)))
-
-(put 'funcall 'byte-optimizer 'byte-optimize-funcall)
-(put 'apply 'byte-optimizer 'byte-optimize-apply)
-
-
-(put 'let 'byte-optimizer 'byte-optimize-letX)
-(put 'let* 'byte-optimizer 'byte-optimize-letX)
-(defun byte-optimize-letX (form)
- (cond ((null (nth 1 form))
- ;; No bindings
- (cons 'progn (cdr (cdr form))))
- ((or (nth 2 form) (nthcdr 3 form))
- form)
- ;; The body is nil
- ((eq (car form) 'let)
- (append '(progn) (mapcar 'car-safe (mapcar 'cdr-safe (nth 1 form)))
- '(nil)))
- (t
- (let ((binds (reverse (nth 1 form))))
- (list 'let* (reverse (cdr binds)) (nth 1 (car binds)) nil)))))
-
-
-(put 'nth 'byte-optimizer 'byte-optimize-nth)
-(defun byte-optimize-nth (form)
- (if (and (= (safe-length form) 3) (memq (nth 1 form) '(0 1)))
- (list 'car (if (zerop (nth 1 form))
- (nth 2 form)
- (list 'cdr (nth 2 form))))
- (byte-optimize-predicate form)))
-
-(put 'nthcdr 'byte-optimizer 'byte-optimize-nthcdr)
-(defun byte-optimize-nthcdr (form)
- (if (and (= (safe-length form) 3) (not (memq (nth 1 form) '(0 1 2))))
- (byte-optimize-predicate form)
- (let ((count (nth 1 form)))
- (setq form (nth 2 form))
- (while (>= (setq count (1- count)) 0)
- (setq form (list 'cdr form)))
- form)))
-
-;;; enumerating those functions which need not be called if the returned
-;;; value is not used. That is, something like
-;;; (progn (list (something-with-side-effects) (yow))
-;;; (foo))
-;;; may safely be turned into
-;;; (progn (progn (something-with-side-effects) (yow))
-;;; (foo))
-;;; Further optimizations will turn (progn (list 1 2 3) 'foo) into 'foo.
-
-;;; I wonder if I missed any :-\)
-(let ((side-effect-free-fns
- '(% * + - / /= 1+ 1- < <= = > >= abs acos append aref ash asin atan
- assoc assq
- boundp buffer-file-name buffer-local-variables buffer-modified-p
- buffer-substring
- capitalize car-less-than-car car cdr ceiling concat coordinates-in-window-p
- copy-marker cos count-lines
- default-boundp default-value documentation downcase
- elt exp expt fboundp featurep
- file-directory-p file-exists-p file-locked-p file-name-absolute-p
- file-newer-than-file-p file-readable-p file-symlink-p file-writable-p
- float floor format
- get get-buffer get-buffer-window getenv get-file-buffer
- int-to-string
- length log log10 logand logb logior lognot logxor lsh
- marker-buffer max member memq min mod
- next-window nth nthcdr number-to-string
- parse-colon-path previous-window
- radians-to-degrees rassq regexp-quote reverse round
- sin sqrt string< string= string-equal string-lessp string-to-char
- string-to-int string-to-number substring symbol-plist
- tan upcase user-variable-p vconcat
- window-buffer window-dedicated-p window-edges window-height
- window-hscroll window-minibuffer-p window-width
- zerop))
- (side-effect-and-error-free-fns
- '(arrayp atom
- bobp bolp buffer-end buffer-list buffer-size buffer-string bufferp
- car-safe case-table-p cdr-safe char-or-string-p commandp cons consp
- current-buffer
- dot dot-marker eobp eolp eq eql equal eventp floatp framep
- get-largest-window get-lru-window
- identity ignore integerp integer-or-marker-p interactive-p
- invocation-directory invocation-name
- keymapp list listp
- make-marker mark mark-marker markerp memory-limit minibuffer-window
- mouse-movement-p
- natnump nlistp not null number-or-marker-p numberp
- one-window-p overlayp
- point point-marker point-min point-max processp
- selected-window sequencep stringp subrp symbolp syntax-table-p
- user-full-name user-login-name user-original-login-name
- user-real-login-name user-real-uid user-uid
- vector vectorp
- window-configuration-p window-live-p windowp)))
- (while side-effect-free-fns
- (put (car side-effect-free-fns) 'side-effect-free t)
- (setq side-effect-free-fns (cdr side-effect-free-fns)))
- (while side-effect-and-error-free-fns
- (put (car side-effect-and-error-free-fns) 'side-effect-free 'error-free)
- (setq side-effect-and-error-free-fns (cdr side-effect-and-error-free-fns)))
- nil)
-
-
-(defun byte-compile-splice-in-already-compiled-code (form)
- ;; form is (byte-code "..." [...] n)
- (if (not (memq byte-optimize '(t lap)))
- (byte-compile-normal-call form)
- (byte-inline-lapcode
- (byte-decompile-bytecode-1 (nth 1 form) (nth 2 form) t))
- (setq byte-compile-maxdepth (max (+ byte-compile-depth (nth 3 form))
- byte-compile-maxdepth))
- (setq byte-compile-depth (1+ byte-compile-depth))))
-
-(put 'byte-code 'byte-compile 'byte-compile-splice-in-already-compiled-code)
-
-
-(defconst byte-constref-ops
- '(byte-constant byte-constant2 byte-varref byte-varset byte-varbind))
-
-;;; This function extracts the bitfields from variable-length opcodes.
-;;; Originally defined in disass.el (which no longer uses it.)
-
-(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
- (defvar op)
- (defvar ptr)
- (defvar bytes)
- (cond ((< op byte-nth)
- (let ((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)
- (prog1 (- op byte-constant) ;offset in opcode
- (setq op byte-constant)))
- ((and (>= op byte-constant2)
- (<= 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))))
- ((and (>= op byte-listN)
- (<= op byte-insertN))
- (setq ptr (1+ ptr)) ;offset in next byte
- (aref bytes ptr))))
-
-
-;;; This de-compiler is used for inline expansion of compiled functions,
-;;; and by the disassembler.
-;;;
-;;; This list contains numbers, which are pc values,
-;;; before each instruction.
-(defun byte-decompile-bytecode (bytes constvec)
- "Turns BYTECODE into lapcode, referring to CONSTVEC."
- (let ((byte-compile-constants nil)
- (byte-compile-variables nil)
- (byte-compile-tag-number 0))
- (byte-decompile-bytecode-1 bytes constvec)))
-
-;; As byte-decompile-bytecode, but updates
-;; byte-compile-{constants, variables, tag-number}.
-;; If MAKE-SPLICEABLE is true, then `return' opcodes are replaced
-;; with `goto's destined for the end of the code.
-;; That is for use by the compiler.
-;; If MAKE-SPLICEABLE is nil, we are being called for the disassembler.
-;; In that case, we put a pc value into the list
-;; before each insn (or its label).
-(defun byte-decompile-bytecode-1 (bytes constvec &optional make-spliceable)
- (let ((length (length bytes))
- (ptr 0) optr tag tags op offset
- lap tmp
- endtag
- (retcount 0))
- (while (not (= ptr length))
- (or make-spliceable
- (setq lap (cons ptr lap)))
- (setq op (aref bytes ptr)
- optr ptr
- offset (disassemble-offset)) ; this does dynamic-scope magic
- (setq op (aref byte-code-vector op))
- (cond ((memq op byte-goto-ops)
- ;; it's a pc
- (setq offset
- (cdr (or (assq offset tags)
- (car (setq tags
- (cons (cons offset
- (byte-compile-make-tag))
- tags)))))))
- ((cond ((eq op 'byte-constant2) (setq op 'byte-constant) t)
- ((memq op byte-constref-ops)))
- (setq tmp (aref constvec offset)
- offset (if (eq op 'byte-constant)
- (byte-compile-get-constant tmp)
- (or (assq tmp byte-compile-variables)
- (car (setq byte-compile-variables
- (cons (list tmp)
- byte-compile-variables)))))))
- ((and make-spliceable
- (eq op 'byte-return))
- (if (= ptr (1- length))
- (setq op nil)
- (setq offset (or endtag (setq endtag (byte-compile-make-tag)))
- op 'byte-goto))))
- ;; lap = ( [ (pc . (op . arg)) ]* )
- (setq lap (cons (cons optr (cons op (or offset 0)))
- lap))
- (setq ptr (1+ ptr)))
- ;; take off the dummy nil op that we replaced a trailing "return" with.
- (let ((rest lap))
- (while rest
- (cond ((numberp (car rest)))
- ((setq tmp (assq (car (car rest)) tags))
- ;; this addr is jumped to
- (setcdr rest (cons (cons nil (cdr tmp))
- (cdr rest)))
- (setq tags (delq tmp tags))
- (setq rest (cdr rest))))
- (setq rest (cdr rest))))
- (if tags (error "optimizer error: missed tags %s" tags))
- (if (null (car (cdr (car lap))))
- (setq lap (cdr lap)))
- (if endtag
- (setq lap (cons (cons nil endtag) lap)))
- ;; remove addrs, lap = ( [ (op . arg) | (TAG tagno) ]* )
- (mapcar (function (lambda (elt)
- (if (numberp elt)
- elt
- (cdr elt))))
- (nreverse lap))))
-
-
-;;; peephole optimizer
-
-(defconst byte-tagref-ops (cons 'TAG byte-goto-ops))
-
-(defconst byte-conditional-ops
- '(byte-goto-if-nil byte-goto-if-not-nil byte-goto-if-nil-else-pop
- byte-goto-if-not-nil-else-pop))
-
-(defconst byte-after-unbind-ops
- '(byte-constant byte-dup
- byte-symbolp byte-consp byte-stringp byte-listp byte-numberp byte-integerp
- byte-eq byte-equal byte-not
- byte-cons byte-list1 byte-list2 ; byte-list3 byte-list4
- byte-interactive-p)
- ;; How about other side-effect-free-ops? Is it safe to move an
- ;; error invocation (such as from nth) out of an unwind-protect?
- "Byte-codes that can be moved past an unbind.")
-
-(defconst byte-compile-side-effect-and-error-free-ops
- '(byte-constant byte-dup byte-symbolp byte-consp byte-stringp byte-listp
- byte-integerp byte-numberp byte-eq byte-equal byte-not byte-car-safe
- byte-cdr-safe byte-cons byte-list1 byte-list2 byte-point byte-point-max
- byte-point-min byte-following-char byte-preceding-char
- byte-current-column byte-eolp byte-eobp byte-bolp byte-bobp
- byte-current-buffer byte-interactive-p))
-
-(defconst byte-compile-side-effect-free-ops
- (nconc
- '(byte-varref byte-nth byte-memq byte-car byte-cdr byte-length byte-aref
- byte-symbol-value byte-get byte-concat2 byte-concat3 byte-sub1 byte-add1
- byte-eqlsign byte-gtr byte-lss byte-leq byte-geq byte-diff byte-negate
- byte-plus byte-max byte-min byte-mult byte-char-after byte-char-syntax
- byte-buffer-substring byte-string= byte-string< byte-nthcdr byte-elt
- byte-member byte-assq byte-quo byte-rem)
- byte-compile-side-effect-and-error-free-ops))
-
-;;; This crock is because of the way DEFVAR_BOOL variables work.
-;;; Consider the code
-;;;
-;;; (defun foo (flag)
-;;; (let ((old-pop-ups pop-up-windows)
-;;; (pop-up-windows flag))
-;;; (cond ((not (eq pop-up-windows old-pop-ups))
-;;; (setq old-pop-ups pop-up-windows)
-;;; ...))))
-;;;
-;;; Uncompiled, old-pop-ups will always be set to nil or t, even if FLAG is
-;;; something else. But if we optimize
-;;;
-;;; varref flag
-;;; varbind pop-up-windows
-;;; varref pop-up-windows
-;;; not
-;;; to
-;;; varref flag
-;;; dup
-;;; varbind pop-up-windows
-;;; not
-;;;
-;;; we break the program, because it will appear that pop-up-windows and
-;;; old-pop-ups are not EQ when really they are. So we have to know what
-;;; the BOOL variables are, and not perform this optimization on them.
-;;;
-(defconst byte-boolean-vars
- '(abbrev-all-caps abbrevs-changed byte-metering-on
- cannot-suspend completion-auto-help completion-ignore-case
- cursor-in-echo-area debug-on-next-call debug-on-quit
- delete-exited-processes enable-recursive-minibuffers
- highlight-nonselected-windows indent-tabs-mode inhibit-local-menu-bar-menus
- insert-default-directory inverse-video load-force-doc-strings
- load-in-progress menu-prompting minibuffer-auto-raise
- mode-line-inverse-video multiple-frames no-redraw-on-reenter noninteractive
- parse-sexp-ignore-comments pop-up-frames pop-up-windows
- print-escape-newlines system-uses-terminfo truncate-partial-width-windows
- visible-bell vms-stmlf-recfm words-include-escapes)
- "DEFVAR_BOOL variables. Giving these any non-nil value sets them to t.
-If this does not enumerate all DEFVAR_BOOL variables, the byte-optimizer
-may generate incorrect code.")
-
-(defun byte-optimize-lapcode (lap &optional for-effect)
- "Simple peephole optimizer. LAP is both modified and returned."
- (let (lap0 off0
- lap1 off1
- lap2 off2
- (keep-going 'first-time)
- (add-depth 0)
- rest tmp tmp2 tmp3
- (side-effect-free (if byte-compile-delete-errors
- byte-compile-side-effect-free-ops
- byte-compile-side-effect-and-error-free-ops)))
- (while keep-going
- (or (eq keep-going 'first-time)
- (byte-compile-log-lap " ---- next pass"))
- (setq rest lap
- keep-going nil)
- (while rest
- (setq lap0 (car rest)
- lap1 (nth 1 rest)
- lap2 (nth 2 rest))
-
- ;; You may notice that sequences like "dup varset discard" are
- ;; optimized but sequences like "dup varset TAG1: discard" are not.
- ;; You may be tempted to change this; resist that temptation.
- (cond ;;
- ;; <side-effect-free> pop --> <deleted>
- ;; ...including:
- ;; const-X pop --> <deleted>
- ;; varref-X pop --> <deleted>
- ;; dup pop --> <deleted>
- ;;
- ((and (eq 'byte-discard (car lap1))
- (memq (car lap0) side-effect-free))
- (setq keep-going t)
- (setq tmp (aref byte-stack+-info (symbol-value (car lap0))))
- (setq rest (cdr rest))
- (cond ((= tmp 1)
- (byte-compile-log-lap
- " %s discard\t-->\t<deleted>" lap0)
- (setq lap (delq lap0 (delq lap1 lap))))
- ((= tmp 0)
- (byte-compile-log-lap
- " %s discard\t-->\t<deleted> discard" lap0)
- (setq lap (delq lap0 lap)))
- ((= tmp -1)
- (byte-compile-log-lap
- " %s discard\t-->\tdiscard discard" lap0)
- (setcar lap0 'byte-discard)
- (setcdr lap0 0))
- ((error "Optimizer error: too much on the stack"))))
- ;;
- ;; goto*-X X: --> X:
- ;;
- ((and (memq (car lap0) byte-goto-ops)
- (eq (cdr lap0) lap1))
- (cond ((eq (car lap0) 'byte-goto)
- (setq lap (delq lap0 lap))
- (setq tmp "<deleted>"))
- ((memq (car lap0) byte-goto-always-pop-ops)
- (setcar lap0 (setq tmp 'byte-discard))
- (setcdr lap0 0))
- ((error "Depth conflict at tag %d" (nth 2 lap0))))
- (and (memq byte-optimize-log '(t byte))
- (byte-compile-log " (goto %s) %s:\t-->\t%s %s:"
- (nth 1 lap1) (nth 1 lap1)
- tmp (nth 1 lap1)))
- (setq keep-going t))
- ;;
- ;; varset-X varref-X --> dup varset-X
- ;; varbind-X varref-X --> dup varbind-X
- ;; const/dup varset-X varref-X --> const/dup varset-X const/dup
- ;; const/dup varbind-X varref-X --> const/dup varbind-X const/dup
- ;; The latter two can enable other optimizations.
- ;;
- ((and (eq 'byte-varref (car lap2))
- (eq (cdr lap1) (cdr lap2))
- (memq (car lap1) '(byte-varset byte-varbind)))
- (if (and (setq tmp (memq (car (cdr lap2)) byte-boolean-vars))
- (not (eq (car lap0) 'byte-constant)))
- nil
- (setq keep-going t)
- (if (memq (car lap0) '(byte-constant byte-dup))
- (progn
- (setq tmp (if (or (not tmp)
- (memq (car (cdr lap0)) '(nil t)))
- (cdr lap0)
- (byte-compile-get-constant t)))
- (byte-compile-log-lap " %s %s %s\t-->\t%s %s %s"
- lap0 lap1 lap2 lap0 lap1
- (cons (car lap0) tmp))
- (setcar lap2 (car lap0))
- (setcdr lap2 tmp))
- (byte-compile-log-lap " %s %s\t-->\tdup %s" lap1 lap2 lap1)
- (setcar lap2 (car lap1))
- (setcar lap1 'byte-dup)
- (setcdr lap1 0)
- ;; The stack depth gets locally increased, so we will
- ;; increase maxdepth in case depth = maxdepth here.
- ;; This can cause the third argument to byte-code to
- ;; be larger than necessary.
- (setq add-depth 1))))
- ;;
- ;; dup varset-X discard --> varset-X
- ;; dup varbind-X discard --> varbind-X
- ;; (the varbind variant can emerge from other optimizations)
- ;;
- ((and (eq 'byte-dup (car lap0))
- (eq 'byte-discard (car lap2))
- (memq (car lap1) '(byte-varset byte-varbind)))
- (byte-compile-log-lap " dup %s discard\t-->\t%s" lap1 lap1)
- (setq keep-going t
- rest (cdr rest))
- (setq lap (delq lap0 (delq lap2 lap))))
- ;;
- ;; not goto-X-if-nil --> goto-X-if-non-nil
- ;; not goto-X-if-non-nil --> goto-X-if-nil
- ;;
- ;; it is wrong to do the same thing for the -else-pop variants.
- ;;
- ((and (eq 'byte-not (car lap0))
- (or (eq 'byte-goto-if-nil (car lap1))
- (eq 'byte-goto-if-not-nil (car lap1))))
- (byte-compile-log-lap " not %s\t-->\t%s"
- lap1
- (cons
- (if (eq (car lap1) 'byte-goto-if-nil)
- 'byte-goto-if-not-nil
- 'byte-goto-if-nil)
- (cdr lap1)))
- (setcar lap1 (if (eq (car lap1) 'byte-goto-if-nil)
- 'byte-goto-if-not-nil
- 'byte-goto-if-nil))
- (setq lap (delq lap0 lap))
- (setq keep-going t))
- ;;
- ;; goto-X-if-nil goto-Y X: --> goto-Y-if-non-nil X:
- ;; goto-X-if-non-nil goto-Y X: --> goto-Y-if-nil X:
- ;;
- ;; it is wrong to do the same thing for the -else-pop variants.
- ;;
- ((and (or (eq 'byte-goto-if-nil (car lap0))
- (eq 'byte-goto-if-not-nil (car lap0))) ; gotoX
- (eq 'byte-goto (car lap1)) ; gotoY
- (eq (cdr lap0) lap2)) ; TAG X
- (let ((inverse (if (eq 'byte-goto-if-nil (car lap0))
- 'byte-goto-if-not-nil 'byte-goto-if-nil)))
- (byte-compile-log-lap " %s %s %s:\t-->\t%s %s:"
- lap0 lap1 lap2
- (cons inverse (cdr lap1)) lap2)
- (setq lap (delq lap0 lap))
- (setcar lap1 inverse)
- (setq keep-going t)))
- ;;
- ;; const goto-if-* --> whatever
- ;;
- ((and (eq 'byte-constant (car lap0))
- (memq (car lap1) byte-conditional-ops))
- (cond ((if (or (eq (car lap1) 'byte-goto-if-nil)
- (eq (car lap1) 'byte-goto-if-nil-else-pop))
- (car (cdr lap0))
- (not (car (cdr lap0))))
- (byte-compile-log-lap " %s %s\t-->\t<deleted>"
- lap0 lap1)
- (setq rest (cdr rest)
- lap (delq lap0 (delq lap1 lap))))
- (t
- (if (memq (car lap1) byte-goto-always-pop-ops)
- (progn
- (byte-compile-log-lap " %s %s\t-->\t%s"
- lap0 lap1 (cons 'byte-goto (cdr lap1)))
- (setq lap (delq lap0 lap)))
- (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1
- (cons 'byte-goto (cdr lap1))))
- (setcar lap1 'byte-goto)))
- (setq keep-going t))
- ;;
- ;; varref-X varref-X --> varref-X dup
- ;; varref-X [dup ...] varref-X --> varref-X [dup ...] dup
- ;; We don't optimize the const-X variations on this here,
- ;; because that would inhibit some goto optimizations; we
- ;; optimize the const-X case after all other optimizations.
- ;;
- ((and (eq 'byte-varref (car lap0))
- (progn
- (setq tmp (cdr rest))
- (while (eq (car (car tmp)) 'byte-dup)
- (setq tmp (cdr tmp)))
- t)
- (eq (cdr lap0) (cdr (car tmp)))
- (eq 'byte-varref (car (car tmp))))
- (if (memq byte-optimize-log '(t byte))
- (let ((str ""))
- (setq tmp2 (cdr rest))
- (while (not (eq tmp tmp2))
- (setq tmp2 (cdr tmp2)
- str (concat str " dup")))
- (byte-compile-log-lap " %s%s %s\t-->\t%s%s dup"
- lap0 str lap0 lap0 str)))
- (setq keep-going t)
- (setcar (car tmp) 'byte-dup)
- (setcdr (car tmp) 0)
- (setq rest tmp))
- ;;
- ;; TAG1: TAG2: --> TAG1: <deleted>
- ;; (and other references to TAG2 are replaced with TAG1)
- ;;
- ((and (eq (car lap0) 'TAG)
- (eq (car lap1) 'TAG))
- (and (memq byte-optimize-log '(t byte))
- (byte-compile-log " adjacent tags %d and %d merged"
- (nth 1 lap1) (nth 1 lap0)))
- (setq tmp3 lap)
- (while (setq tmp2 (rassq lap0 tmp3))
- (setcdr tmp2 lap1)
- (setq tmp3 (cdr (memq tmp2 tmp3))))
- (setq lap (delq lap0 lap)
- keep-going t))
- ;;
- ;; unused-TAG: --> <deleted>
- ;;
- ((and (eq 'TAG (car lap0))
- (not (rassq lap0 lap)))
- (and (memq byte-optimize-log '(t byte))
- (byte-compile-log " unused tag %d removed" (nth 1 lap0)))
- (setq lap (delq lap0 lap)
- keep-going t))
- ;;
- ;; goto ... --> goto <delete until TAG or end>
- ;; return ... --> return <delete until TAG or end>
- ;;
- ((and (memq (car lap0) '(byte-goto byte-return))
- (not (memq (car lap1) '(TAG nil))))
- (setq tmp rest)
- (let ((i 0)
- (opt-p (memq byte-optimize-log '(t lap)))
- str deleted)
- (while (and (setq tmp (cdr tmp))
- (not (eq 'TAG (car (car tmp)))))
- (if opt-p (setq deleted (cons (car tmp) deleted)
- str (concat str " %s")
- i (1+ i))))
- (if opt-p
- (let ((tagstr
- (if (eq 'TAG (car (car tmp)))
- (format "%d:" (car (cdr (car tmp))))
- (or (car tmp) ""))))
- (if (< i 6)
- (apply 'byte-compile-log-lap-1
- (concat " %s" str
- " %s\t-->\t%s <deleted> %s")
- lap0
- (nconc (nreverse deleted)
- (list tagstr lap0 tagstr)))
- (byte-compile-log-lap
- " %s <%d unreachable op%s> %s\t-->\t%s <deleted> %s"
- lap0 i (if (= i 1) "" "s")
- tagstr lap0 tagstr))))
- (rplacd rest tmp))
- (setq keep-going t))
- ;;
- ;; <safe-op> unbind --> unbind <safe-op>
- ;; (this may enable other optimizations.)
- ;;
- ((and (eq 'byte-unbind (car lap1))
- (memq (car lap0) byte-after-unbind-ops))
- (byte-compile-log-lap " %s %s\t-->\t%s %s" lap0 lap1 lap1 lap0)
- (setcar rest lap1)
- (setcar (cdr rest) lap0)
- (setq keep-going t))
- ;;
- ;; varbind-X unbind-N --> discard unbind-(N-1)
- ;; save-excursion unbind-N --> unbind-(N-1)
- ;; save-restriction unbind-N --> unbind-(N-1)
- ;;
- ((and (eq 'byte-unbind (car lap1))
- (memq (car lap0) '(byte-varbind byte-save-excursion
- byte-save-restriction))
- (< 0 (cdr lap1)))
- (if (zerop (setcdr lap1 (1- (cdr lap1))))
- (delq lap1 rest))
- (if (eq (car lap0) 'byte-varbind)
- (setcar rest (cons 'byte-discard 0))
- (setq lap (delq lap0 lap)))
- (byte-compile-log-lap " %s %s\t-->\t%s %s"
- lap0 (cons (car lap1) (1+ (cdr lap1)))
- (if (eq (car lap0) 'byte-varbind)
- (car rest)
- (car (cdr rest)))
- (if (and (/= 0 (cdr lap1))
- (eq (car lap0) 'byte-varbind))
- (car (cdr rest))
- ""))
- (setq keep-going t))
- ;;
- ;; goto*-X ... X: goto-Y --> goto*-Y
- ;; goto-X ... X: return --> return
- ;;
- ((and (memq (car lap0) byte-goto-ops)
- (memq (car (setq tmp (nth 1 (memq (cdr lap0) lap))))
- '(byte-goto byte-return)))
- (cond ((and (not (eq tmp lap0))
- (or (eq (car lap0) 'byte-goto)
- (eq (car tmp) 'byte-goto)))
- (byte-compile-log-lap " %s [%s]\t-->\t%s"
- (car lap0) tmp tmp)
- (if (eq (car tmp) 'byte-return)
- (setcar lap0 'byte-return))
- (setcdr lap0 (cdr tmp))
- (setq keep-going t))))
- ;;
- ;; goto-*-else-pop X ... X: goto-if-* --> whatever
- ;; goto-*-else-pop X ... X: discard --> whatever
- ;;
- ((and (memq (car lap0) '(byte-goto-if-nil-else-pop
- byte-goto-if-not-nil-else-pop))
- (memq (car (car (setq tmp (cdr (memq (cdr lap0) lap)))))
- (eval-when-compile
- (cons 'byte-discard byte-conditional-ops)))
- (not (eq lap0 (car tmp))))
- (setq tmp2 (car tmp))
- (setq tmp3 (assq (car lap0) '((byte-goto-if-nil-else-pop
- byte-goto-if-nil)
- (byte-goto-if-not-nil-else-pop
- byte-goto-if-not-nil))))
- (if (memq (car tmp2) tmp3)
- (progn (setcar lap0 (car tmp2))
- (setcdr lap0 (cdr tmp2))
- (byte-compile-log-lap " %s-else-pop [%s]\t-->\t%s"
- (car lap0) tmp2 lap0))
- ;; Get rid of the -else-pop's and jump one step further.
- (or (eq 'TAG (car (nth 1 tmp)))
- (setcdr tmp (cons (byte-compile-make-tag)
- (cdr tmp))))
- (byte-compile-log-lap " %s [%s]\t-->\t%s <skip>"
- (car lap0) tmp2 (nth 1 tmp3))
- (setcar lap0 (nth 1 tmp3))
- (setcdr lap0 (nth 1 tmp)))
- (setq keep-going t))
- ;;
- ;; const goto-X ... X: goto-if-* --> whatever
- ;; const goto-X ... X: discard --> whatever
- ;;
- ((and (eq (car lap0) 'byte-constant)
- (eq (car lap1) 'byte-goto)
- (memq (car (car (setq tmp (cdr (memq (cdr lap1) lap)))))
- (eval-when-compile
- (cons 'byte-discard byte-conditional-ops)))
- (not (eq lap1 (car tmp))))
- (setq tmp2 (car tmp))
- (cond ((memq (car tmp2)
- (if (null (car (cdr lap0)))
- '(byte-goto-if-nil byte-goto-if-nil-else-pop)
- '(byte-goto-if-not-nil
- byte-goto-if-not-nil-else-pop)))
- (byte-compile-log-lap " %s goto [%s]\t-->\t%s %s"
- lap0 tmp2 lap0 tmp2)
- (setcar lap1 (car tmp2))
- (setcdr lap1 (cdr tmp2))
- ;; Let next step fix the (const,goto-if*) sequence.
- (setq rest (cons nil rest)))
- (t
- ;; Jump one step further
- (byte-compile-log-lap
- " %s goto [%s]\t-->\t<deleted> goto <skip>"
- lap0 tmp2)
- (or (eq 'TAG (car (nth 1 tmp)))
- (setcdr tmp (cons (byte-compile-make-tag)
- (cdr tmp))))
- (setcdr lap1 (car (cdr tmp)))
- (setq lap (delq lap0 lap))))
- (setq keep-going t))
- ;;
- ;; X: varref-Y ... varset-Y goto-X -->
- ;; X: varref-Y Z: ... dup varset-Y goto-Z
- ;; (varset-X goto-BACK, BACK: varref-X --> copy the varref down.)
- ;; (This is so usual for while loops that it is worth handling).
- ;;
- ((and (eq (car lap1) 'byte-varset)
- (eq (car lap2) 'byte-goto)
- (not (memq (cdr lap2) rest)) ;Backwards jump
- (eq (car (car (setq tmp (cdr (memq (cdr lap2) lap)))))
- 'byte-varref)
- (eq (cdr (car tmp)) (cdr lap1))
- (not (memq (car (cdr lap1)) byte-boolean-vars)))
- ;;(byte-compile-log-lap " Pulled %s to end of loop" (car tmp))
- (let ((newtag (byte-compile-make-tag)))
- (byte-compile-log-lap
- " %s: %s ... %s %s\t-->\t%s: %s %s: ... %s %s %s"
- (nth 1 (cdr lap2)) (car tmp)
- lap1 lap2
- (nth 1 (cdr lap2)) (car tmp)
- (nth 1 newtag) 'byte-dup lap1
- (cons 'byte-goto newtag)
- )
- (setcdr rest (cons (cons 'byte-dup 0) (cdr rest)))
- (setcdr tmp (cons (setcdr lap2 newtag) (cdr tmp))))
- (setq add-depth 1)
- (setq keep-going t))
- ;;
- ;; goto-X Y: ... X: goto-if*-Y --> goto-if-not-*-X+1 Y:
- ;; (This can pull the loop test to the end of the loop)
- ;;
- ((and (eq (car lap0) 'byte-goto)
- (eq (car lap1) 'TAG)
- (eq lap1
- (cdr (car (setq tmp (cdr (memq (cdr lap0) lap))))))
- (memq (car (car tmp))
- '(byte-goto byte-goto-if-nil byte-goto-if-not-nil
- byte-goto-if-nil-else-pop)))
-;; (byte-compile-log-lap " %s %s, %s %s --> moved conditional"
-;; lap0 lap1 (cdr lap0) (car tmp))
- (let ((newtag (byte-compile-make-tag)))
- (byte-compile-log-lap
- "%s %s: ... %s: %s\t-->\t%s ... %s:"
- lap0 (nth 1 lap1) (nth 1 (cdr lap0)) (car tmp)
- (cons (cdr (assq (car (car tmp))
- '((byte-goto-if-nil . byte-goto-if-not-nil)
- (byte-goto-if-not-nil . byte-goto-if-nil)
- (byte-goto-if-nil-else-pop .
- byte-goto-if-not-nil-else-pop)
- (byte-goto-if-not-nil-else-pop .
- byte-goto-if-nil-else-pop))))
- newtag)
-
- (nth 1 newtag)
- )
- (setcdr tmp (cons (setcdr lap0 newtag) (cdr tmp)))
- (if (eq (car (car tmp)) 'byte-goto-if-nil-else-pop)
- ;; We can handle this case but not the -if-not-nil case,
- ;; because we won't know which non-nil constant to push.
- (setcdr rest (cons (cons 'byte-constant
- (byte-compile-get-constant nil))
- (cdr rest))))
- (setcar lap0 (nth 1 (memq (car (car tmp))
- '(byte-goto-if-nil-else-pop
- byte-goto-if-not-nil
- byte-goto-if-nil
- byte-goto-if-not-nil
- byte-goto byte-goto))))
- )
- (setq keep-going t))
- )
- (setq rest (cdr rest)))
- )
- ;; Cleanup stage:
- ;; Rebuild byte-compile-constants / byte-compile-variables.
- ;; Simple optimizations that would inhibit other optimizations if they
- ;; were done in the optimizing loop, and optimizations which there is no
- ;; need to do more than once.
- (setq byte-compile-constants nil
- byte-compile-variables nil)
- (setq rest lap)
- (while rest
- (setq lap0 (car rest)
- lap1 (nth 1 rest))
- (if (memq (car lap0) byte-constref-ops)
- (if (eq (cdr lap0) 'byte-constant)
- (or (memq (cdr lap0) byte-compile-variables)
- (setq byte-compile-variables (cons (cdr lap0)
- byte-compile-variables)))
- (or (memq (cdr lap0) byte-compile-constants)
- (setq byte-compile-constants (cons (cdr lap0)
- byte-compile-constants)))))
- (cond (;;
- ;; const-C varset-X const-C --> const-C dup varset-X
- ;; const-C varbind-X const-C --> const-C dup varbind-X
- ;;
- (and (eq (car lap0) 'byte-constant)
- (eq (car (nth 2 rest)) 'byte-constant)
- (eq (cdr lap0) (car (nth 2 rest)))
- (memq (car lap1) '(byte-varbind byte-varset)))
- (byte-compile-log-lap " %s %s %s\t-->\t%s dup %s"
- lap0 lap1 lap0 lap0 lap1)
- (setcar (cdr (cdr rest)) (cons (car lap1) (cdr lap1)))
- (setcar (cdr rest) (cons 'byte-dup 0))
- (setq add-depth 1))
- ;;
- ;; const-X [dup/const-X ...] --> const-X [dup ...] dup
- ;; varref-X [dup/varref-X ...] --> varref-X [dup ...] dup
- ;;
- ((memq (car lap0) '(byte-constant byte-varref))
- (setq tmp rest
- tmp2 nil)
- (while (progn
- (while (eq 'byte-dup (car (car (setq tmp (cdr tmp))))))
- (and (eq (cdr lap0) (cdr (car tmp)))
- (eq (car lap0) (car (car tmp)))))
- (setcar tmp (cons 'byte-dup 0))
- (setq tmp2 t))
- (if tmp2
- (byte-compile-log-lap
- " %s [dup/%s]...\t-->\t%s dup..." lap0 lap0 lap0)))
- ;;
- ;; unbind-N unbind-M --> unbind-(N+M)
- ;;
- ((and (eq 'byte-unbind (car lap0))
- (eq 'byte-unbind (car lap1)))
- (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1
- (cons 'byte-unbind
- (+ (cdr lap0) (cdr lap1))))
- (setq keep-going t)
- (setq lap (delq lap0 lap))
- (setcdr lap1 (+ (cdr lap1) (cdr lap0))))
- )
- (setq rest (cdr rest)))
- (setq byte-compile-maxdepth (+ byte-compile-maxdepth add-depth)))
- lap)
-
-(provide 'byte-optimize)
-
-
-;; To avoid "lisp nesting exceeds max-lisp-eval-depth" when this file compiles
-;; itself, compile some of its most used recursive functions (at load time).
-;;
-(eval-when-compile
- (or (byte-code-function-p (symbol-function 'byte-optimize-form))
- (assq 'byte-code (symbol-function 'byte-optimize-form))
- (let ((byte-optimize nil)
- (byte-compile-warnings nil))
- (mapcar '(lambda (x)
- (or noninteractive (message "compiling %s..." x))
- (byte-compile x)
- (or noninteractive (message "compiling %s...done" x)))
- '(byte-optimize-form
- byte-optimize-body
- byte-optimize-predicate
- byte-optimize-binary-predicate
- ;; Inserted some more than necessary, to speed it up.
- byte-optimize-form-code-walker
- byte-optimize-lapcode))))
- nil)
-
-;;; byte-opt.el ends here
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
deleted file mode 100644
index 1ffd3cae2ca..00000000000
--- a/lisp/emacs-lisp/bytecomp.el
+++ /dev/null
@@ -1,3427 +0,0 @@
-;;; bytecomp.el --- compilation of Lisp code into byte code.
-
-;; Copyright (C) 1985, 1986, 1987, 1992, 1994 Free Software Foundation, Inc.
-
-;; Author: Jamie Zawinski <jwz@lucid.com>
-;; Hallvard Furuseth <hbf@ulrik.uio.no>
-;; Keywords: internal
-
-;; Subsequently modified by RMS.
-
-;;; This version incorporates changes up to version 2.10 of the
-;;; Zawinski-Furuseth compiler.
-(defconst byte-compile-version "$Revision: 2.24 $")
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The Emacs Lisp byte compiler. This crunches lisp source into a sort
-;; of p-code which takes up less space and can be interpreted faster.
-;; The user entry points are byte-compile-file and byte-recompile-directory.
-
-;;; Code:
-
-;; ========================================================================
-;; Entry points:
-;; byte-recompile-directory, byte-compile-file,
-;; batch-byte-compile, batch-byte-recompile-directory,
-;; byte-compile, compile-defun,
-;; display-call-tree
-;; (byte-compile-buffer and byte-compile-and-load-file were turned off
-;; because they are not terribly useful and get in the way of completion.)
-
-;; This version of the byte compiler has the following improvements:
-;; + optimization of compiled code:
-;; - removal of unreachable code;
-;; - removal of calls to side-effectless functions whose return-value
-;; is unused;
-;; - compile-time evaluation of safe constant forms, such as (consp nil)
-;; and (ash 1 6);
-;; - open-coding of literal lambdas;
-;; - peephole optimization of emitted code;
-;; - trivial functions are left uncompiled for speed.
-;; + support for inline functions;
-;; + compile-time evaluation of arbitrary expressions;
-;; + compile-time warning messages for:
-;; - functions being redefined with incompatible arglists;
-;; - functions being redefined as macros, or vice-versa;
-;; - functions or macros defined multiple times in the same file;
-;; - functions being called with the incorrect number of arguments;
-;; - functions being called which are not defined globally, in the
-;; file, or as autoloads;
-;; - assignment and reference of undeclared free variables;
-;; - various syntax errors;
-;; + correct compilation of nested defuns, defmacros, defvars and defsubsts;
-;; + correct compilation of top-level uses of macros;
-;; + the ability to generate a histogram of functions called.
-
-;; User customization variables:
-;;
-;; byte-compile-verbose Whether to report the function currently being
-;; compiled in the minibuffer;
-;; byte-optimize Whether to do optimizations; this may be
-;; t, nil, 'source, or 'byte;
-;; byte-optimize-log Whether to report (in excruciating detail)
-;; exactly which optimizations have been made.
-;; This may be t, nil, 'source, or 'byte;
-;; byte-compile-error-on-warn Whether to stop compilation when a warning is
-;; produced;
-;; byte-compile-delete-errors Whether the optimizer may delete calls or
-;; variable references that are side-effect-free
-;; except that they may return an error.
-;; byte-compile-generate-call-tree Whether to generate a histogram of
-;; function calls. This can be useful for
-;; finding unused functions, as well as simple
-;; performance metering.
-;; byte-compile-warnings List of warnings to issue, or t. May contain
-;; 'free-vars (references to variables not in the
-;; current lexical scope)
-;; 'unresolved (calls to unknown functions)
-;; 'callargs (lambda calls with args that don't
-;; match the lambda's definition)
-;; 'redefine (function cell redefined from
-;; a macro to a lambda or vice versa,
-;; or redefined to take other args)
-;; 'obsolete (obsolete variables and functions)
-;; byte-compile-compatibility Whether the compiler should
-;; generate .elc files which can be loaded into
-;; generic emacs 18.
-;; emacs-lisp-file-regexp Regexp for the extension of source-files;
-;; see also the function byte-compile-dest-file.
-
-;; New Features:
-;;
-;; o The form `defsubst' is just like `defun', except that the function
-;; generated will be open-coded in compiled code which uses it. This
-;; means that no function call will be generated, it will simply be
-;; spliced in. Lisp functions calls are very slow, so this can be a
-;; big win.
-;;
-;; You can generally accomplish the same thing with `defmacro', but in
-;; that case, the defined procedure can't be used as an argument to
-;; mapcar, etc.
-;;
-;; o You can also open-code one particular call to a function without
-;; open-coding all calls. Use the 'inline' form to do this, like so:
-;;
-;; (inline (foo 1 2 3)) ;; `foo' will be open-coded
-;; or...
-;; (inline ;; `foo' and `baz' will be
-;; (foo 1 2 3 (bar 5)) ;; open-coded, but `bar' will not.
-;; (baz 0))
-;;
-;; o It is possible to open-code a function in the same file it is defined
-;; in without having to load that file before compiling it. the
-;; byte-compiler has been modified to remember function definitions in
-;; the compilation environment in the same way that it remembers macro
-;; definitions.
-;;
-;; o Forms like ((lambda ...) ...) are open-coded.
-;;
-;; o The form `eval-when-compile' is like progn, except that the body
-;; is evaluated at compile-time. When it appears at top-level, this
-;; is analogous to the Common Lisp idiom (eval-when (compile) ...).
-;; When it does not appear at top-level, it is similar to the
-;; Common Lisp #. reader macro (but not in interpreted code).
-;;
-;; o The form `eval-and-compile' is similar to eval-when-compile, but
-;; the whole form is evalled both at compile-time and at run-time.
-;;
-;; o The command compile-defun is analogous to eval-defun.
-;;
-;; o If you run byte-compile-file on a filename which is visited in a
-;; buffer, and that buffer is modified, you are asked whether you want
-;; to save the buffer before compiling.
-;;
-;; o byte-compiled files now start with the string `;ELC'.
-;; Some versions of `file' can be customized to recognize that.
-
-(require 'backquote)
-
-(or (fboundp 'defsubst)
- ;; This really ought to be loaded already!
- (load-library "byte-run"))
-
-;;; The feature of compiling in a specific target Emacs version
-;;; has been turned off because compile time options are a bad idea.
-(defmacro byte-compile-single-version () nil)
-(defmacro byte-compile-version-cond (cond) cond)
-
-;;; The crud you see scattered through this file of the form
-;;; (or (and (boundp 'epoch::version) epoch::version)
-;;; (string-lessp emacs-version "19"))
-;;; is because the Epoch folks couldn't be bothered to follow the
-;;; normal emacs version numbering convention.
-
-;; (if (byte-compile-version-cond
-;; (or (and (boundp 'epoch::version) epoch::version)
-;; (string-lessp emacs-version "19")))
-;; (progn
-;; ;; emacs-18 compatibility.
-;; (defvar baud-rate (baud-rate)) ;Define baud-rate if it's undefined
-;;
-;; (if (byte-compile-single-version)
-;; (defmacro byte-code-function-p (x) "Emacs 18 doesn't have these." nil)
-;; (defun byte-code-function-p (x) "Emacs 18 doesn't have these." nil))
-;;
-;; (or (and (fboundp 'member)
-;; ;; avoid using someone else's possibly bogus definition of this.
-;; (subrp (symbol-function 'member)))
-;; (defun member (elt list)
-;; "like memq, but uses equal instead of eq. In v19, this is a subr."
-;; (while (and list (not (equal elt (car list))))
-;; (setq list (cdr list)))
-;; list))))
-
-
-(defvar emacs-lisp-file-regexp (if (eq system-type 'vax-vms)
- "\\.EL\\(;[0-9]+\\)?$"
- "\\.el$")
- "*Regexp which matches Emacs Lisp source files.
-You may want to redefine `byte-compile-dest-file' if you change this.")
-
-;; This enables file name handlers such as jka-compr
-;; to remove parts of the file name that should not be copied
-;; through to the output file name.
-(defun byte-compiler-base-file-name (filename)
- (let ((handler (find-file-name-handler filename
- 'byte-compiler-base-file-name)))
- (if handler
- (funcall handler 'byte-compiler-base-file-name filename)
- filename)))
-
-(or (fboundp 'byte-compile-dest-file)
- ;; The user may want to redefine this along with emacs-lisp-file-regexp,
- ;; so only define it if it is undefined.
- (defun byte-compile-dest-file (filename)
- "Convert an Emacs Lisp source file name to a compiled file name."
- (setq filename (byte-compiler-base-file-name filename))
- (setq filename (file-name-sans-versions filename))
- (cond ((eq system-type 'vax-vms)
- (concat (substring filename 0 (string-match ";" filename)) "c"))
- ((string-match emacs-lisp-file-regexp filename)
- (concat (substring filename 0 (match-beginning 0)) ".elc"))
- (t (concat filename ".elc")))))
-
-;; This can be the 'byte-compile property of any symbol.
-(autoload 'byte-compile-inline-expand "byte-opt")
-
-;; This is the entrypoint to the lapcode optimizer pass1.
-(autoload 'byte-optimize-form "byte-opt")
-;; This is the entrypoint to the lapcode optimizer pass2.
-(autoload 'byte-optimize-lapcode "byte-opt")
-(autoload 'byte-compile-unfold-lambda "byte-opt")
-
-;; This is the entry point to the decompiler, which is used by the
-;; disassembler. The disassembler just requires 'byte-compile, but
-;; that doesn't define this function, so this seems to be a reasonable
-;; thing to do.
-(autoload 'byte-decompile-bytecode "byte-opt")
-
-(defvar byte-compile-verbose
- (and (not noninteractive) (> baud-rate search-slow-speed))
- "*Non-nil means print messages describing progress of byte-compiler.")
-
-(defvar byte-compile-compatibility nil
- "*Non-nil means generate output that can run in Emacs 18.")
-
-;; (defvar byte-compile-generate-emacs19-bytecodes
-;; (not (or (and (boundp 'epoch::version) epoch::version)
-;; (string-lessp emacs-version "19")))
-;; "*If this is true, then the byte-compiler will generate bytecode which
-;; makes use of byte-ops which are present only in Emacs 19. Code generated
-;; this way can never be run in Emacs 18, and may even cause it to crash.")
-
-(defvar byte-optimize t
- "*Enables optimization in the byte compiler.
-nil means don't do any optimization.
-t means do all optimizations.
-`source' means do source-level optimizations only.
-`byte' means do code-level optimizations only.")
-
-(defvar byte-compile-delete-errors t
- "*If non-nil, the optimizer may delete forms that may signal an error.
-This includes variable references and calls to functions such as `car'.")
-
-(defvar byte-compile-dynamic nil
- "*If non-nil, compile function bodies so they load lazily.
-They are hidden comments in the compiled file, and brought into core when the
-function is called.
-
-To enable this option, make it a file-local variable
-in the source file you want it to apply to.
-For example, add -*-byte-compile-dynamic: t;-*- on the first line.
-
-When this option is true, if you load the compiled file and then move it,
-the functions you loaded will not be able to run.")
-
-(defvar byte-compile-dynamic-docstrings t
- "*If non-nil, compile doc strings for lazy access.
-We bury the doc strings of functions and variables
-inside comments in the file, and bring them into core only when they
-are actually needed.
-
-When this option is true, if you load the compiled file and then move it,
-you won't be able to find the documentation of anything in that file.
-
-To disable this option for a certain file, make it a file-local variable
-in the source file. For example, add this to the first line:
- -*-byte-compile-dynamic-docstrings:nil;-*-
-You can also set the variable globally.
-
-This option is enabled by default because it reduces Emacs memory usage.")
-
-(defvar byte-optimize-log nil
- "*If true, the byte-compiler will log its optimizations into *Compile-Log*.
-If this is 'source, then only source-level optimizations will be logged.
-If it is 'byte, then only byte-level optimizations will be logged.")
-
-(defvar byte-compile-error-on-warn nil
- "*If true, the byte-compiler reports warnings with `error'.")
-
-(defconst byte-compile-warning-types
- '(redefine callargs free-vars unresolved obsolete))
-(defvar byte-compile-warnings t
- "*List of warnings that the byte-compiler should issue (t for all).
-Elements of the list may be be:
-
- free-vars references to variables not in the current lexical scope.
- unresolved calls to unknown functions.
- callargs lambda calls with args that don't match the definition.
- redefine function cell redefined from a macro to a lambda or vice
- versa, or redefined to take a different number of arguments.
- obsolete obsolete variables and functions.
-
-See also the macro `byte-compiler-options'.")
-
-(defvar byte-compile-generate-call-tree nil
- "*Non-nil means collect call-graph information when compiling.
-This records functions were called and from where.
-If the value is t, compilation displays the call graph when it finishes.
-If the value is neither t nor nil, compilation asks you whether to display
-the graph.
-
-The call tree only lists functions called, not macros used. Those functions
-which the byte-code interpreter knows about directly (eq, cons, etc.) are
-not reported.
-
-The call tree also lists those functions which are not known to be called
-\(that is, to which no calls have been compiled). Functions which can be
-invoked interactively are excluded from this list.")
-
-(defconst byte-compile-call-tree nil "Alist of functions and their call tree.
-Each element looks like
-
- \(FUNCTION CALLERS CALLS\)
-
-where CALLERS is a list of functions that call FUNCTION, and CALLS
-is a list of functions for which calls were generated while compiling
-FUNCTION.")
-
-(defvar byte-compile-call-tree-sort 'name
- "*If non-nil, sort the call tree.
-The values `name', `callers', `calls', `calls+callers'
-specify different fields to sort on.")
-
-;; (defvar byte-compile-overwrite-file t
-;; "If nil, old .elc files are deleted before the new is saved, and .elc
-;; files will have the same modes as the corresponding .el file. Otherwise,
-;; existing .elc files will simply be overwritten, and the existing modes
-;; will not be changed. If this variable is nil, then an .elc file which
-;; is a symbolic link will be turned into a normal file, instead of the file
-;; which the link points to being overwritten.")
-
-(defvar byte-compile-constants nil
- "list of all constants encountered during compilation of this form")
-(defvar byte-compile-variables nil
- "list of all variables encountered during compilation of this form")
-(defvar byte-compile-bound-variables nil
- "list of variables bound in the context of the current form; this list
-lives partly on the stack.")
-(defvar byte-compile-free-references)
-(defvar byte-compile-free-assignments)
-
-(defvar byte-compiler-error-flag)
-
-(defconst byte-compile-initial-macro-environment
- '(
-;; (byte-compiler-options . (lambda (&rest forms)
-;; (apply 'byte-compiler-options-handler forms)))
- (eval-when-compile . (lambda (&rest body)
- (list 'quote (eval (byte-compile-top-level
- (cons 'progn body))))))
- (eval-and-compile . (lambda (&rest body)
- (eval (cons 'progn body))
- (cons 'progn body))))
- "The default macro-environment passed to macroexpand by the compiler.
-Placing a macro here will cause a macro to have different semantics when
-expanded by the compiler as when expanded by the interpreter.")
-
-(defvar byte-compile-macro-environment byte-compile-initial-macro-environment
- "Alist of macros defined in the file being compiled.
-Each element looks like (MACRONAME . DEFINITION). It is
-\(MACRONAME . nil) when a macro is redefined as a function.")
-
-(defvar byte-compile-function-environment nil
- "Alist of functions defined in the file being compiled.
-This is so we can inline them when necessary.
-Each element looks like (FUNCTIONNAME . DEFINITION). It is
-\(FUNCTIONNAME . nil) when a function is redefined as a macro.")
-
-(defvar byte-compile-unresolved-functions nil
- "Alist of undefined functions to which calls have been compiled (used for
-warnings when the function is later defined with incorrect args).")
-
-(defvar byte-compile-tag-number 0)
-(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.")
-
-
-;;; The byte codes; this information is duplicated in bytecomp.c
-
-(defconst byte-code-vector nil
- "An array containing byte-code names indexed by byte-code values.")
-
-(defconst byte-stack+-info nil
- "An array with the stack adjustment for each byte-code.")
-
-(defmacro byte-defop (opcode stack-adjust opname &optional docstring)
- ;; This is a speed-hack for building the byte-code-vector at compile-time.
- ;; We fill in the vector at macroexpand-time, and then after the last call
- ;; to byte-defop, we write the vector out as a constant instead of writing
- ;; out a bunch of calls to aset.
- ;; Actually, we don't fill in the vector itself, because that could make
- ;; it problematic to compile big changes to this compiler; we store the
- ;; values on its plist, and remove them later in -extrude.
- (let ((v1 (or (get 'byte-code-vector 'tmp-compile-time-value)
- (put 'byte-code-vector 'tmp-compile-time-value
- (make-vector 256 nil))))
- (v2 (or (get 'byte-stack+-info 'tmp-compile-time-value)
- (put 'byte-stack+-info 'tmp-compile-time-value
- (make-vector 256 nil)))))
- (aset v1 opcode opname)
- (aset v2 opcode stack-adjust))
- (if docstring
- (list 'defconst opname opcode (concat "Byte code opcode " docstring "."))
- (list 'defconst opname opcode)))
-
-(defmacro byte-extrude-byte-code-vectors ()
- (prog1 (list 'setq 'byte-code-vector
- (get 'byte-code-vector 'tmp-compile-time-value)
- 'byte-stack+-info
- (get 'byte-stack+-info 'tmp-compile-time-value))
- ;; emacs-18 has no REMPROP.
- (put 'byte-code-vector 'tmp-compile-time-value nil)
- (put 'byte-stack+-info 'tmp-compile-time-value nil)))
-
-
-;; unused: 0-7
-
-;; These opcodes are special in that they pack their argument into the
-;; opcode word.
-;;
-(byte-defop 8 1 byte-varref "for variable reference")
-(byte-defop 16 -1 byte-varset "for setting a variable")
-(byte-defop 24 -1 byte-varbind "for binding a variable")
-(byte-defop 32 0 byte-call "for calling a function")
-(byte-defop 40 0 byte-unbind "for unbinding special bindings")
-;; codes 8-47 are consumed by the preceding opcodes
-
-;; unused: 48-55
-
-(byte-defop 56 -1 byte-nth)
-(byte-defop 57 0 byte-symbolp)
-(byte-defop 58 0 byte-consp)
-(byte-defop 59 0 byte-stringp)
-(byte-defop 60 0 byte-listp)
-(byte-defop 61 -1 byte-eq)
-(byte-defop 62 -1 byte-memq)
-(byte-defop 63 0 byte-not)
-(byte-defop 64 0 byte-car)
-(byte-defop 65 0 byte-cdr)
-(byte-defop 66 -1 byte-cons)
-(byte-defop 67 0 byte-list1)
-(byte-defop 68 -1 byte-list2)
-(byte-defop 69 -2 byte-list3)
-(byte-defop 70 -3 byte-list4)
-(byte-defop 71 0 byte-length)
-(byte-defop 72 -1 byte-aref)
-(byte-defop 73 -2 byte-aset)
-(byte-defop 74 0 byte-symbol-value)
-(byte-defop 75 0 byte-symbol-function) ; this was commented out
-(byte-defop 76 -1 byte-set)
-(byte-defop 77 -1 byte-fset) ; this was commented out
-(byte-defop 78 -1 byte-get)
-(byte-defop 79 -2 byte-substring)
-(byte-defop 80 -1 byte-concat2)
-(byte-defop 81 -2 byte-concat3)
-(byte-defop 82 -3 byte-concat4)
-(byte-defop 83 0 byte-sub1)
-(byte-defop 84 0 byte-add1)
-(byte-defop 85 -1 byte-eqlsign)
-(byte-defop 86 -1 byte-gtr)
-(byte-defop 87 -1 byte-lss)
-(byte-defop 88 -1 byte-leq)
-(byte-defop 89 -1 byte-geq)
-(byte-defop 90 -1 byte-diff)
-(byte-defop 91 0 byte-negate)
-(byte-defop 92 -1 byte-plus)
-(byte-defop 93 -1 byte-max)
-(byte-defop 94 -1 byte-min)
-(byte-defop 95 -1 byte-mult) ; v19 only
-(byte-defop 96 1 byte-point)
-(byte-defop 97 0 byte-save-current-buffer
- "To make a binding to record the current buffer")
-(byte-defop 98 0 byte-goto-char)
-(byte-defop 99 0 byte-insert)
-(byte-defop 100 1 byte-point-max)
-(byte-defop 101 1 byte-point-min)
-(byte-defop 102 0 byte-char-after)
-(byte-defop 103 1 byte-following-char)
-(byte-defop 104 1 byte-preceding-char)
-(byte-defop 105 1 byte-current-column)
-(byte-defop 106 0 byte-indent-to)
-(byte-defop 107 0 byte-scan-buffer-OBSOLETE) ; no longer generated as of v18
-(byte-defop 108 1 byte-eolp)
-(byte-defop 109 1 byte-eobp)
-(byte-defop 110 1 byte-bolp)
-(byte-defop 111 1 byte-bobp)
-(byte-defop 112 1 byte-current-buffer)
-(byte-defop 113 0 byte-set-buffer)
-(byte-defop 114 1 byte-read-char-OBSOLETE)
-(byte-defop 115 0 byte-set-mark-OBSOLETE)
-(byte-defop 116 1 byte-interactive-p)
-
-;; These ops are new to v19
-(byte-defop 117 0 byte-forward-char)
-(byte-defop 118 0 byte-forward-word)
-(byte-defop 119 -1 byte-skip-chars-forward)
-(byte-defop 120 -1 byte-skip-chars-backward)
-(byte-defop 121 0 byte-forward-line)
-(byte-defop 122 0 byte-char-syntax)
-(byte-defop 123 -1 byte-buffer-substring)
-(byte-defop 124 -1 byte-delete-region)
-(byte-defop 125 -1 byte-narrow-to-region)
-(byte-defop 126 1 byte-widen)
-(byte-defop 127 0 byte-end-of-line)
-
-;; unused: 128
-
-;; These store their argument in the next two bytes
-(byte-defop 129 1 byte-constant2
- "for reference to a constant with vector index >= byte-constant-limit")
-(byte-defop 130 0 byte-goto "for unconditional jump")
-(byte-defop 131 -1 byte-goto-if-nil "to pop value and jump if it's nil")
-(byte-defop 132 -1 byte-goto-if-not-nil "to pop value and jump if it's not nil")
-(byte-defop 133 -1 byte-goto-if-nil-else-pop
- "to examine top-of-stack, jump and don't pop it if it's nil,
-otherwise pop it")
-(byte-defop 134 -1 byte-goto-if-not-nil-else-pop
- "to examine top-of-stack, jump and don't pop it if it's non nil,
-otherwise pop it")
-
-(byte-defop 135 -1 byte-return "to pop a value and return it from `byte-code'")
-(byte-defop 136 -1 byte-discard "to discard one value from stack")
-(byte-defop 137 1 byte-dup "to duplicate the top of the stack")
-
-(byte-defop 138 0 byte-save-excursion
- "to make a binding to record the buffer, point and mark")
-(byte-defop 139 0 byte-save-window-excursion
- "to make a binding to record entire window configuration")
-(byte-defop 140 0 byte-save-restriction
- "to make a binding to record the current buffer clipping restrictions")
-(byte-defop 141 -1 byte-catch
- "for catch. Takes, on stack, the tag and an expression for the body")
-(byte-defop 142 -1 byte-unwind-protect
- "for unwind-protect. Takes, on stack, an expression for the unwind-action")
-
-;; For condition-case. Takes, on stack, the variable to bind,
-;; an expression for the body, and a list of clauses.
-(byte-defop 143 -2 byte-condition-case)
-
-;; 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.
-(byte-defop 144 0 byte-temp-output-buffer-setup)
-
-;; 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.
-(byte-defop 145 -1 byte-temp-output-buffer-show)
-
-;; these ops are new to v19
-
-;; To unbind back to the beginning of this frame.
-;; Not used yet, but will be needed for tail-recursion elimination.
-(byte-defop 146 0 byte-unbind-all)
-
-;; these ops are new to v19
-(byte-defop 147 -2 byte-set-marker)
-(byte-defop 148 0 byte-match-beginning)
-(byte-defop 149 0 byte-match-end)
-(byte-defop 150 0 byte-upcase)
-(byte-defop 151 0 byte-downcase)
-(byte-defop 152 -1 byte-string=)
-(byte-defop 153 -1 byte-string<)
-(byte-defop 154 -1 byte-equal)
-(byte-defop 155 -1 byte-nthcdr)
-(byte-defop 156 -1 byte-elt)
-(byte-defop 157 -1 byte-member)
-(byte-defop 158 -1 byte-assq)
-(byte-defop 159 0 byte-nreverse)
-(byte-defop 160 -1 byte-setcar)
-(byte-defop 161 -1 byte-setcdr)
-(byte-defop 162 0 byte-car-safe)
-(byte-defop 163 0 byte-cdr-safe)
-(byte-defop 164 -1 byte-nconc)
-(byte-defop 165 -1 byte-quo)
-(byte-defop 166 -1 byte-rem)
-(byte-defop 167 0 byte-numberp)
-(byte-defop 168 0 byte-integerp)
-
-;; unused: 169-174
-(byte-defop 175 nil byte-listN)
-(byte-defop 176 nil byte-concatN)
-(byte-defop 177 nil byte-insertN)
-
-;; unused: 178-191
-
-(byte-defop 192 1 byte-constant "for reference to a constant")
-;; codes 193-255 are consumed by byte-constant.
-(defconst byte-constant-limit 64
- "Exclusive maximum index usable in the `byte-constant' opcode.")
-
-(defconst byte-goto-ops '(byte-goto byte-goto-if-nil byte-goto-if-not-nil
- byte-goto-if-nil-else-pop
- byte-goto-if-not-nil-else-pop)
- "List of byte-codes whose offset is a pc.")
-
-(defconst byte-goto-always-pop-ops '(byte-goto-if-nil byte-goto-if-not-nil))
-
-(byte-extrude-byte-code-vectors)
-
-;;; lapcode generator
-;;;
-;;; the byte-compiler now does source -> lapcode -> bytecode instead of
-;;; source -> bytecode, because it's a lot easier to make optimizations
-;;; on lapcode than on bytecode.
-;;;
-;;; Elements of the lapcode list are of the form (<instruction> . <parameter>)
-;;; where instruction is a symbol naming a byte-code instruction,
-;;; and parameter is an argument to that instruction, if any.
-;;;
-;;; The instruction can be the pseudo-op TAG, which means that this position
-;;; in the instruction stream is a target of a goto. (car PARAMETER) will be
-;;; the PC for this location, and the whole instruction "(TAG pc)" will be the
-;;; parameter for some goto op.
-;;;
-;;; If the operation is varbind, varref, varset or push-constant, then the
-;;; parameter is (variable/constant . index_in_constant_vector).
-;;;
-;;; First, the source code is macroexpanded and optimized in various ways.
-;;; Then the resultant code is compiled into lapcode. Another set of
-;;; optimizations are then run over the lapcode. Then the variables and
-;;; constants referenced by the lapcode are collected and placed in the
-;;; constants-vector. (This happens now so that variables referenced by dead
-;;; code don't consume space.) And finally, the lapcode is transformed into
-;;; compacted byte-code.
-;;;
-;;; A distinction is made between variables and constants because the variable-
-;;; referencing instructions are more sensitive to the variables being near the
-;;; front of the constants-vector than the constant-referencing instructions.
-;;; Also, this lets us notice references to free variables.
-
-(defun byte-compile-lapcode (lap)
- "Turns lapcode into bytecode. The lapcode is destroyed."
- ;; Lapcode modifications: changes the ID of a tag to be the tag's PC.
- (let ((pc 0) ; Program counter
- op off ; Operation & offset
- (bytes '()) ; Put the output bytes here
- (patchlist nil) ; List of tags and goto's to patch
- rest rel tmp)
- (while lap
- (setq op (car (car lap))
- off (cdr (car lap)))
- (cond ((not (symbolp op))
- (error "Non-symbolic opcode `%s'" op))
- ((eq op 'TAG)
- (setcar off pc)
- (setq patchlist (cons off patchlist)))
- ((memq op byte-goto-ops)
- (setq pc (+ pc 3))
- (setq bytes (cons (cons pc (cdr off))
- (cons nil
- (cons (symbol-value op) bytes))))
- (setq patchlist (cons bytes patchlist)))
- (t
- (setq bytes
- (cond ((cond ((consp off)
- ;; Variable or constant reference
- (setq off (cdr off))
- (eq op 'byte-constant)))
- (cond ((< off byte-constant-limit)
- (setq pc (1+ pc))
- (cons (+ byte-constant off) bytes))
- (t
- (setq pc (+ 3 pc))
- (cons (lsh off -8)
- (cons (logand off 255)
- (cons byte-constant2 bytes))))))
- ((<= byte-listN (symbol-value op))
- (setq pc (+ 2 pc))
- (cons off (cons (symbol-value op) bytes)))
- ((< off 6)
- (setq pc (1+ pc))
- (cons (+ (symbol-value op) off) bytes))
- ((< off 256)
- (setq pc (+ 2 pc))
- (cons off (cons (+ (symbol-value op) 6) bytes)))
- (t
- (setq pc (+ 3 pc))
- (cons (lsh off -8)
- (cons (logand off 255)
- (cons (+ (symbol-value op) 7)
- bytes))))))))
- (setq lap (cdr lap)))
- ;;(if (not (= pc (length bytes)))
- ;; (error "Compiler error: pc mismatch - %s %s" pc (length bytes)))
- ;; Patch PC into jumps
- (let (bytes)
- (while patchlist
- (setq bytes (car patchlist))
- (cond ((atom (car bytes))) ; Tag
- (t ; Absolute jump
- (setq pc (car (cdr (car bytes)))) ; Pick PC from tag
- (setcar (cdr bytes) (logand pc 255))
- (setcar bytes (lsh pc -8))))
- (setq patchlist (cdr patchlist))))
- (concat (nreverse bytes))))
-
-
-;;; byte compiler messages
-
-(defvar byte-compile-current-form nil)
-(defvar byte-compile-current-file nil)
-(defvar byte-compile-dest-file nil)
-
-(defmacro byte-compile-log (format-string &rest args)
- (list 'and
- 'byte-optimize
- '(memq byte-optimize-log '(t source))
- (list 'let '((print-escape-newlines t)
- (print-level 4)
- (print-length 4))
- (list 'byte-compile-log-1
- (cons 'format
- (cons format-string
- (mapcar
- '(lambda (x)
- (if (symbolp x) (list 'prin1-to-string x) x))
- args)))))))
-
-(defconst byte-compile-last-warned-form nil)
-
-;; Log a message STRING in *Compile-Log*.
-;; Also log the current function and file if not already done.
-(defun byte-compile-log-1 (string &optional fill)
- (cond (noninteractive
- (if (or byte-compile-current-file
- (and byte-compile-last-warned-form
- (not (eq byte-compile-current-form
- byte-compile-last-warned-form))))
- (message "While compiling %s%s:"
- (or byte-compile-current-form "toplevel forms")
- (if byte-compile-current-file
- (if (stringp byte-compile-current-file)
- (concat " in file " byte-compile-current-file)
- (concat " in buffer "
- (buffer-name byte-compile-current-file)))
- "")))
- (message " %s" string))
- (t
- (save-excursion
- (set-buffer (get-buffer-create "*Compile-Log*"))
- (goto-char (point-max))
- (cond ((or byte-compile-current-file
- (and byte-compile-last-warned-form
- (not (eq byte-compile-current-form
- byte-compile-last-warned-form))))
- (if byte-compile-current-file
- (insert "\n\^L\n" (current-time-string) "\n"))
- (insert "While compiling "
- (if byte-compile-current-form
- (format "%s" byte-compile-current-form)
- "toplevel forms"))
- (if byte-compile-current-file
- (if (stringp byte-compile-current-file)
- (insert " in file " byte-compile-current-file)
- (insert " in buffer "
- (buffer-name byte-compile-current-file))))
- (insert ":\n")))
- (insert " " string "\n")
- (if (and fill (not (string-match "\n" string)))
- (let ((fill-prefix " ")
- (fill-column 78))
- (fill-paragraph nil)))
- )))
- (setq byte-compile-current-file nil
- byte-compile-last-warned-form byte-compile-current-form))
-
-;; Log the start of a file in *Compile-Log*, and mark it as done.
-;; But do nothing in batch mode.
-(defun byte-compile-log-file ()
- (and byte-compile-current-file (not noninteractive)
- (save-excursion
- (set-buffer (get-buffer-create "*Compile-Log*"))
- (goto-char (point-max))
- (insert "\n\^L\nCompiling "
- (if (stringp byte-compile-current-file)
- (concat "file " byte-compile-current-file)
- (concat "buffer " (buffer-name byte-compile-current-file)))
- " at " (current-time-string) "\n")
- (setq byte-compile-current-file nil))))
-
-(defun byte-compile-warn (format &rest args)
- (setq format (apply 'format format args))
- (if byte-compile-error-on-warn
- (error "%s" format) ; byte-compile-file catches and logs it
- (byte-compile-log-1 (concat "** " format) t)
-;;; It is useless to flash warnings too fast to be read.
-;;; Besides, they will all be shown at the end.
-;;; (or noninteractive ; already written on stdout.
-;;; (message "Warning: %s" format))
- ))
-
-;;; This function should be used to report errors that have halted
-;;; compilation of the current file.
-(defun byte-compile-report-error (error-info)
- (setq byte-compiler-error-flag t)
- (byte-compile-log-1
- (concat "!! "
- (format (if (cdr error-info) "%s (%s)" "%s")
- (get (car error-info) 'error-message)
- (prin1-to-string (cdr error-info))))))
-
-;;; Used by make-obsolete.
-(defun byte-compile-obsolete (form)
- (let ((new (get (car form) 'byte-obsolete-info)))
- (if (memq 'obsolete byte-compile-warnings)
- (byte-compile-warn "%s is an obsolete function; %s" (car form)
- (if (stringp (car new))
- (car new)
- (format "use %s instead." (car new)))))
- (funcall (or (cdr new) 'byte-compile-normal-call) form)))
-
-;; Compiler options
-
-;; (defvar byte-compiler-valid-options
-;; '((optimize byte-optimize (t nil source byte) val)
-;; (file-format byte-compile-compatibility (emacs18 emacs19)
-;; (eq val 'emacs18))
-;; ;; (new-bytecodes byte-compile-generate-emacs19-bytecodes (t nil) val)
-;; (delete-errors byte-compile-delete-errors (t nil) val)
-;; (verbose byte-compile-verbose (t nil) val)
-;; (warnings byte-compile-warnings ((callargs redefine free-vars unresolved))
-;; val)))
-
-;; Inhibit v18/v19 selectors if the version is hardcoded.
-;; #### This should print a warning if the user tries to change something
-;; than can't be changed because the running compiler doesn't support it.
-;; (cond
-;; ((byte-compile-single-version)
-;; (setcar (cdr (cdr (assq 'new-bytecodes byte-compiler-valid-options)))
-;; (list (byte-compile-version-cond
-;; byte-compile-generate-emacs19-bytecodes)))
-;; (setcar (cdr (cdr (assq 'file-format byte-compiler-valid-options)))
-;; (if (byte-compile-version-cond byte-compile-compatibility)
-;; '(emacs18) '(emacs19)))))
-
-;; (defun byte-compiler-options-handler (&rest args)
-;; (let (key val desc choices)
-;; (while args
-;; (if (or (atom (car args)) (nthcdr 2 (car args)) (null (cdr (car args))))
-;; (error "Malformed byte-compiler option `%s'" (car args)))
-;; (setq key (car (car args))
-;; val (car (cdr (car args)))
-;; desc (assq key byte-compiler-valid-options))
-;; (or desc
-;; (error "Unknown byte-compiler option `%s'" key))
-;; (setq choices (nth 2 desc))
-;; (if (consp (car choices))
-;; (let (this
-;; (handler 'cons)
-;; (ret (and (memq (car val) '(+ -))
-;; (copy-sequence (if (eq t (symbol-value (nth 1 desc)))
-;; choices
-;; (symbol-value (nth 1 desc)))))))
-;; (setq choices (car choices))
-;; (while val
-;; (setq this (car val))
-;; (cond ((memq this choices)
-;; (setq ret (funcall handler this ret)))
-;; ((eq this '+) (setq handler 'cons))
-;; ((eq this '-) (setq handler 'delq))
-;; ((error "`%s' only accepts %s" key choices)))
-;; (setq val (cdr val)))
-;; (set (nth 1 desc) ret))
-;; (or (memq val choices)
-;; (error "`%s' must be one of `%s'" key choices))
-;; (set (nth 1 desc) (eval (nth 3 desc))))
-;; (setq args (cdr args)))
-;; nil))
-
-;;; sanity-checking arglists
-
-(defun byte-compile-fdefinition (name macro-p)
- (let* ((list (if macro-p
- byte-compile-macro-environment
- byte-compile-function-environment))
- (env (cdr (assq name list))))
- (or env
- (let ((fn name))
- (while (and (symbolp fn)
- (fboundp fn)
- (or (symbolp (symbol-function fn))
- (consp (symbol-function fn))
- (and (not macro-p)
- (byte-code-function-p (symbol-function fn)))))
- (setq fn (symbol-function fn)))
- (if (and (not macro-p) (byte-code-function-p fn))
- fn
- (and (consp fn)
- (if (eq 'macro (car fn))
- (cdr fn)
- (if macro-p
- nil
- (if (eq 'autoload (car fn))
- nil
- fn)))))))))
-
-(defun byte-compile-arglist-signature (arglist)
- (let ((args 0)
- opts
- restp)
- (while arglist
- (cond ((eq (car arglist) '&optional)
- (or opts (setq opts 0)))
- ((eq (car arglist) '&rest)
- (if (cdr arglist)
- (setq restp t
- arglist nil)))
- (t
- (if opts
- (setq opts (1+ opts))
- (setq args (1+ args)))))
- (setq arglist (cdr arglist)))
- (cons args (if restp nil (if opts (+ args opts) args)))))
-
-
-(defun byte-compile-arglist-signatures-congruent-p (old new)
- (not (or
- (> (car new) (car old)) ; requires more args now
- (and (null (cdr old)) ; took rest-args, doesn't any more
- (cdr new))
- (and (cdr new) (cdr old) ; can't take as many args now
- (< (cdr new) (cdr old)))
- )))
-
-(defun byte-compile-arglist-signature-string (signature)
- (cond ((null (cdr signature))
- (format "%d+" (car signature)))
- ((= (car signature) (cdr signature))
- (format "%d" (car signature)))
- (t (format "%d-%d" (car signature) (cdr signature)))))
-
-
-;; Warn if the form is calling a function with the wrong number of arguments.
-(defun byte-compile-callargs-warn (form)
- (let* ((def (or (byte-compile-fdefinition (car form) nil)
- (byte-compile-fdefinition (car form) t)))
- (sig (and def (byte-compile-arglist-signature
- (if (eq 'lambda (car-safe def))
- (nth 1 def)
- (if (byte-code-function-p def)
- (aref def 0)
- '(&rest def))))))
- (ncall (length (cdr form))))
- (if sig
- (if (or (< ncall (car sig))
- (and (cdr sig) (> ncall (cdr sig))))
- (byte-compile-warn
- "%s called with %d argument%s, but %s %s"
- (car form) ncall
- (if (= 1 ncall) "" "s")
- (if (< ncall (car sig))
- "requires"
- "accepts only")
- (byte-compile-arglist-signature-string sig)))
- (or (fboundp (car form)) ; might be a subr or autoload.
- (eq (car form) byte-compile-current-form) ; ## this doesn't work with recursion.
- ;; It's a currently-undefined function. Remember number of args in call.
- (let ((cons (assq (car form) byte-compile-unresolved-functions))
- (n (length (cdr form))))
- (if cons
- (or (memq n (cdr cons))
- (setcdr cons (cons n (cdr cons))))
- (setq byte-compile-unresolved-functions
- (cons (list (car form) n)
- byte-compile-unresolved-functions))))))))
-
-;; Warn if the function or macro is being redefined with a different
-;; number of arguments.
-(defun byte-compile-arglist-warn (form macrop)
- (let ((old (byte-compile-fdefinition (nth 1 form) macrop)))
- (if old
- (let ((sig1 (byte-compile-arglist-signature
- (if (eq 'lambda (car-safe old))
- (nth 1 old)
- (if (byte-code-function-p old)
- (aref old 0)
- '(&rest def)))))
- (sig2 (byte-compile-arglist-signature (nth 2 form))))
- (or (byte-compile-arglist-signatures-congruent-p sig1 sig2)
- (byte-compile-warn "%s %s used to take %s %s, now takes %s"
- (if (eq (car form) 'defun) "function" "macro")
- (nth 1 form)
- (byte-compile-arglist-signature-string sig1)
- (if (equal sig1 '(1 . 1)) "argument" "arguments")
- (byte-compile-arglist-signature-string sig2))))
- ;; This is the first definition. See if previous calls are compatible.
- (let ((calls (assq (nth 1 form) byte-compile-unresolved-functions))
- nums sig min max)
- (if calls
- (progn
- (setq sig (byte-compile-arglist-signature (nth 2 form))
- nums (sort (copy-sequence (cdr calls)) (function <))
- min (car nums)
- max (car (nreverse nums)))
- (if (or (< min (car sig))
- (and (cdr sig) (> max (cdr sig))))
- (byte-compile-warn
- "%s being defined to take %s%s, but was previously called with %s"
- (nth 1 form)
- (byte-compile-arglist-signature-string sig)
- (if (equal sig '(1 . 1)) " arg" " args")
- (byte-compile-arglist-signature-string (cons min max))))
-
- (setq byte-compile-unresolved-functions
- (delq calls byte-compile-unresolved-functions)))))
- )))
-
-;; If we have compiled any calls to functions which are not known to be
-;; defined, issue a warning enumerating them.
-;; `unresolved' in the list `byte-compile-warnings' disables this.
-(defun byte-compile-warn-about-unresolved-functions ()
- (if (memq 'unresolved byte-compile-warnings)
- (let ((byte-compile-current-form "the end of the data"))
- (if (cdr byte-compile-unresolved-functions)
- (let* ((str "The following functions are not known to be defined: ")
- (L (length str))
- (rest (reverse byte-compile-unresolved-functions))
- s)
- (while rest
- (setq s (symbol-name (car (car rest)))
- L (+ L (length s) 2)
- rest (cdr rest))
- (if (< L (1- fill-column))
- (setq str (concat str " " s (and rest ",")))
- (setq str (concat str "\n " s (and rest ","))
- L (+ (length s) 4))))
- (byte-compile-warn "%s" str))
- (if byte-compile-unresolved-functions
- (byte-compile-warn "the function %s is not known to be defined."
- (car (car byte-compile-unresolved-functions)))))))
- nil)
-
-
-(defmacro byte-compile-constp (form)
- ;; Returns non-nil if FORM is a constant.
- (` (cond ((consp (, form)) (eq (car (, form)) 'quote))
- ((not (symbolp (, form))))
- ((memq (, form) '(nil t))))))
-
-(defmacro byte-compile-close-variables (&rest body)
- (cons 'let
- (cons '(;;
- ;; Close over these variables to encapsulate the
- ;; compilation state
- ;;
- (byte-compile-macro-environment
- ;; Copy it because the compiler may patch into the
- ;; macroenvironment.
- (copy-alist byte-compile-initial-macro-environment))
- (byte-compile-function-environment nil)
- (byte-compile-bound-variables nil)
- (byte-compile-free-references nil)
- (byte-compile-free-assignments nil)
- ;;
- ;; Close over these variables so that `byte-compiler-options'
- ;; can change them on a per-file basis.
- ;;
- (byte-compile-verbose byte-compile-verbose)
- (byte-optimize byte-optimize)
- (byte-compile-compatibility byte-compile-compatibility)
- (byte-compile-dynamic byte-compile-dynamic)
- (byte-compile-dynamic-docstrings
- byte-compile-dynamic-docstrings)
-;; (byte-compile-generate-emacs19-bytecodes
-;; byte-compile-generate-emacs19-bytecodes)
- (byte-compile-warnings (if (eq byte-compile-warnings t)
- byte-compile-warning-types
- byte-compile-warnings))
- )
- body)))
-
-(defvar byte-compile-warnings-point-max nil)
-(defmacro displaying-byte-compile-warnings (&rest body)
- (list 'let
- '((byte-compile-warnings-point-max byte-compile-warnings-point-max))
- ;; Log the file name.
- '(byte-compile-log-file)
- ;; Record how much is logged now.
- ;; We will display the log buffer if anything more is logged
- ;; before the end of BODY.
- '(or byte-compile-warnings-point-max
- (save-excursion
- (set-buffer (get-buffer-create "*Compile-Log*"))
- (setq byte-compile-warnings-point-max (point-max))))
- (list 'unwind-protect
- (list 'condition-case 'error-info
- (cons 'progn body)
- '(error
- (byte-compile-report-error error-info)))
- '(save-excursion
- ;; If there were compilation warnings, display them.
- (set-buffer "*Compile-Log*")
- (if (= byte-compile-warnings-point-max (point-max))
- nil
- (select-window
- (prog1 (selected-window)
- (select-window (display-buffer (current-buffer)))
- (goto-char byte-compile-warnings-point-max)
- (recenter 1))))))))
-
-
-;;;###autoload
-(defun byte-force-recompile (directory)
- "Recompile every `.el' file in DIRECTORY that already has a `.elc' file.
-Files in subdirectories of DIRECTORY are processed also."
- (interactive "DByte force recompile (directory): ")
- (byte-recompile-directory directory nil t))
-
-;;;###autoload
-(defun byte-recompile-directory (directory &optional arg force)
- "Recompile every `.el' file in DIRECTORY that needs recompilation.
-This is if a `.elc' file exists but is older than the `.el' file.
-Files in subdirectories of DIRECTORY are processed also.
-
-If the `.elc' file does not exist, normally the `.el' file is *not* compiled.
-But a prefix argument (optional second arg) means ask user,
-for each such `.el' file, whether to compile it. Prefix argument 0 means
-don't ask and compile the file anyway.
-
-A nonzero prefix argument also means ask about each subdirectory.
-
-If the third argument FORCE is non-nil,
-recompile every `.el' file that already has a `.elc' file."
- (interactive "DByte recompile directory: \nP")
- (if arg
- (setq arg (prefix-numeric-value arg)))
- (if noninteractive
- nil
- (save-some-buffers)
- (force-mode-line-update))
- (let ((directories (list (expand-file-name directory)))
- (file-count 0)
- (dir-count 0)
- last-dir)
- (displaying-byte-compile-warnings
- (while directories
- (setq directory (car directories))
- (or noninteractive (message "Checking %s..." directory))
- (let ((files (directory-files directory))
- source dest)
- (while files
- (setq source (expand-file-name (car files) directory))
- (if (and (not (member (car files) '("." ".." "RCS" "CVS")))
- (file-directory-p source)
- (not (file-symlink-p source)))
- ;; This file is a subdirectory. Handle them differently.
- (if (or (null arg)
- (eq 0 arg)
- (y-or-n-p (concat "Check " source "? ")))
- (setq directories
- (nconc directories (list source))))
- ;; It is an ordinary file. Decide whether to compile it.
- (if (and (string-match emacs-lisp-file-regexp source)
- (not (auto-save-file-name-p source))
- (setq dest (byte-compile-dest-file source))
- (if (file-exists-p dest)
- ;; File was already compiled.
- (or force (file-newer-than-file-p source dest))
- ;; No compiled file exists yet.
- (and arg
- (or (eq 0 arg)
- (y-or-n-p (concat "Compile " source "? "))))))
- (progn (if (and noninteractive (not byte-compile-verbose))
- (message "Compiling %s..." source))
- (byte-compile-file source)
- (or noninteractive
- (message "Checking %s..." directory))
- (setq file-count (1+ file-count))
- (if (not (eq last-dir directory))
- (setq last-dir directory
- dir-count (1+ dir-count)))
- )))
- (setq files (cdr files))))
- (setq directories (cdr directories))))
- (message "Done (Total of %d file%s compiled%s)"
- file-count (if (= file-count 1) "" "s")
- (if (> dir-count 1) (format " in %d directories" dir-count) ""))))
-
-;;;###autoload
-(defun byte-compile-file (filename &optional load)
- "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.
-With prefix arg (noninteractively: 2nd arg), load the file after compiling."
-;; (interactive "fByte compile file: \nP")
- (interactive
- (let ((file buffer-file-name)
- (file-name nil)
- (file-dir nil))
- (and file
- (eq (cdr (assq 'major-mode (buffer-local-variables)))
- 'emacs-lisp-mode)
- (setq file-name (file-name-nondirectory file)
- file-dir (file-name-directory file)))
- (list (read-file-name (if current-prefix-arg
- "Byte compile and load file: "
- "Byte compile file: ")
- file-dir file-name nil)
- current-prefix-arg)))
- ;; Expand now so we get the current buffer's defaults
- (setq filename (expand-file-name filename))
-
- ;; If we're compiling a file that's in a buffer and is modified, offer
- ;; to save it first.
- (or noninteractive
- (let ((b (get-file-buffer (expand-file-name filename))))
- (if (and b (buffer-modified-p b)
- (y-or-n-p (format "save buffer %s first? " (buffer-name b))))
- (save-excursion (set-buffer b) (save-buffer)))))
-
- (if byte-compile-verbose
- (message "Compiling %s..." filename))
- (let ((byte-compile-current-file filename)
- target-file input-buffer output-buffer
- byte-compile-dest-file)
- (setq target-file (byte-compile-dest-file filename))
- (setq byte-compile-dest-file target-file)
- (save-excursion
- (setq input-buffer (get-buffer-create " *Compiler Input*"))
- (set-buffer input-buffer)
- (erase-buffer)
- (insert-file-contents filename)
- ;; Run hooks including the uncompression hook.
- ;; If they change the file name, then change it for the output also.
- (let ((buffer-file-name filename)
- (default-major-mode 'emacs-lisp-mode)
- (enable-local-eval nil))
- (normal-mode)
- (setq filename buffer-file-name))
- ;; Set the default directory, in case an eval-when-compile uses it.
- (setq default-directory (file-name-directory filename)))
- (setq byte-compiler-error-flag nil)
- ;; It is important that input-buffer not be current at this call,
- ;; so that the value of point set in input-buffer
- ;; within byte-compile-from-buffer lingers in that buffer.
- (setq output-buffer (byte-compile-from-buffer input-buffer filename))
- (if byte-compiler-error-flag
- nil
- (if byte-compile-verbose
- (message "Compiling %s...done" filename))
- (kill-buffer input-buffer)
- (save-excursion
- (set-buffer output-buffer)
- (goto-char (point-max))
- (insert "\n") ; aaah, unix.
- (let ((vms-stmlf-recfm t))
- (if (file-writable-p target-file)
- (let ((kanji-flag nil)) ; for nemacs, from Nakagawa Takayuki
- (if (or (eq system-type 'ms-dos) (eq system-type 'windows-nt))
- (setq buffer-file-type t))
- (write-region 1 (point-max) target-file))
- ;; This is just to give a better error message than
- ;; write-region
- (signal 'file-error
- (list "Opening output file"
- (if (file-exists-p target-file)
- "cannot overwrite file"
- "directory not writable or nonexistent")
- target-file))))
- (kill-buffer (current-buffer)))
- (if (and byte-compile-generate-call-tree
- (or (eq t byte-compile-generate-call-tree)
- (y-or-n-p (format "Report call tree for %s? " filename))))
- (save-excursion
- (display-call-tree filename)))
- (if load
- (load target-file))
- t)))
-
-;;(defun byte-compile-and-load-file (&optional filename)
-;; "Compile a file of Lisp code named FILENAME into a file of byte code,
-;;and then load it. The output file's name is made by appending \"c\" to
-;;the end of FILENAME."
-;; (interactive)
-;; (if filename ; I don't get it, (interactive-p) doesn't always work
-;; (byte-compile-file filename t)
-;; (let ((current-prefix-arg '(4)))
-;; (call-interactively 'byte-compile-file))))
-
-;;(defun byte-compile-buffer (&optional buffer)
-;; "Byte-compile and evaluate contents of BUFFER (default: the current buffer)."
-;; (interactive "bByte compile buffer: ")
-;; (setq buffer (if buffer (get-buffer buffer) (current-buffer)))
-;; (message "Compiling %s..." (buffer-name buffer))
-;; (let* ((filename (or (buffer-file-name buffer)
-;; (concat "#<buffer " (buffer-name buffer) ">")))
-;; (byte-compile-current-file buffer))
-;; (byte-compile-from-buffer buffer nil))
-;; (message "Compiling %s...done" (buffer-name buffer))
-;; t)
-
-;;; compiling a single function
-;;;###autoload
-(defun compile-defun (&optional arg)
- "Compile and evaluate the current top-level form.
-Print the result in the minibuffer.
-With argument, insert value in current buffer after the form."
- (interactive "P")
- (save-excursion
- (end-of-defun)
- (beginning-of-defun)
- (let* ((byte-compile-current-file nil)
- (byte-compile-last-warned-form 'nothing)
- (value (eval (displaying-byte-compile-warnings
- (byte-compile-sexp (read (current-buffer)))))))
- (cond (arg
- (message "Compiling from buffer... done.")
- (prin1 value (current-buffer))
- (insert "\n"))
- ((message "%s" (prin1-to-string value)))))))
-
-
-(defun byte-compile-from-buffer (inbuffer &optional filename)
- ;; Filename is used for the loading-into-Emacs-18 error message.
- (let (outbuffer
- ;; Prevent truncation of flonums and lists as we read and print them
- (float-output-format nil)
- (case-fold-search nil)
- (print-length nil)
- (print-level nil)
- ;; Simulate entry to byte-compile-top-level
- (byte-compile-constants nil)
- (byte-compile-variables nil)
- (byte-compile-tag-number 0)
- (byte-compile-depth 0)
- (byte-compile-maxdepth 0)
- (byte-compile-output nil)
- ;; #### This is bound in b-c-close-variables.
- ;; (byte-compile-warnings (if (eq byte-compile-warnings t)
- ;; byte-compile-warning-types
- ;; byte-compile-warnings))
- )
- (byte-compile-close-variables
- (save-excursion
- (setq outbuffer
- (set-buffer (get-buffer-create " *Compiler Output*")))
- (erase-buffer)
- ;; (emacs-lisp-mode)
- (setq case-fold-search nil)
- (and filename (byte-compile-insert-header filename inbuffer outbuffer))
-
- ;; This is a kludge. Some operating systems (OS/2, DOS) need to
- ;; write files containing binary information specially.
- ;; Under most circumstances, such files will be in binary
- ;; overwrite mode, so those OS's use that flag to guess how
- ;; they should write their data. Advise them that .elc files
- ;; need to be written carefully.
- (setq overwrite-mode 'overwrite-mode-binary))
- (displaying-byte-compile-warnings
- (save-excursion
- (set-buffer inbuffer)
- (goto-char 1)
-
- ;; Compile the forms from the input buffer.
- (while (progn
- (while (progn (skip-chars-forward " \t\n\^l")
- (looking-at ";"))
- (forward-line 1))
- (not (eobp)))
- (byte-compile-file-form (read inbuffer)))
-
- ;; Compile pending forms at end of file.
- (byte-compile-flush-pending)
- (byte-compile-warn-about-unresolved-functions)
- ;; Should we always do this? When calling multiple files, it
- ;; would be useful to delay this warning until all have
- ;; been compiled.
- (setq byte-compile-unresolved-functions nil))))
- outbuffer))
-
-(defun byte-compile-insert-header (filename inbuffer outbuffer)
- (set-buffer inbuffer)
- (let ((dynamic-docstrings byte-compile-dynamic-docstrings)
- (dynamic byte-compile-dynamic))
- (set-buffer outbuffer)
- (goto-char 1)
- ;;
- ;; The magic number of .elc files is ";ELC", or 0x3B454C43. After that is
- ;; the file-format version number (18 or 19) as a byte, followed by some
- ;; nulls. The primary motivation for doing this is to get some binary
- ;; characters up in the first line of the file so that `diff' will simply
- ;; say "Binary files differ" instead of actually doing a diff of two .elc
- ;; files. An extra benefit is that you can add this to /etc/magic:
- ;;
- ;; 0 string ;ELC GNU Emacs Lisp compiled file,
- ;; >4 byte x version %d
- ;;
- (insert
- ";ELC"
- (if (byte-compile-version-cond byte-compile-compatibility) 18 19)
- "\000\000\000\n"
- )
- (insert ";;; Compiled by "
- (or (and (boundp 'user-mail-address) user-mail-address)
- (concat (user-login-name) "@" (system-name)))
- " on "
- (current-time-string) "\n;;; from file " filename "\n")
- (insert ";;; in Emacs version " emacs-version "\n")
- (insert ";;; with bytecomp version "
- (progn (string-match "[0-9.]+" byte-compile-version)
- (match-string 0 byte-compile-version))
- "\n;;; "
- (cond
- ((eq byte-optimize 'source) "with source-level optimization only")
- ((eq byte-optimize 'byte) "with byte-level optimization only")
- (byte-optimize "with all optimizations")
- (t "without optimization"))
- (if (byte-compile-version-cond byte-compile-compatibility)
- "; compiled with Emacs 18 compatibility.\n"
- ".\n"))
- (if dynamic
- (insert ";;; Function definitions are lazy-loaded.\n"))
- (if (not (byte-compile-version-cond byte-compile-compatibility))
- (insert ";;; This file uses opcodes which do not exist in Emacs 18.\n"
- ;; Have to check if emacs-version is bound so that this works
- ;; in files loaded early in loadup.el.
- "\n(if (and (boundp 'emacs-version)\n"
- ;; If there is a name at the end of emacs-version,
- ;; don't try to check the version number.
- "\t (< (aref emacs-version (1- (length emacs-version))) ?A)\n"
- "\t (or (and (boundp 'epoch::version) epoch::version)\n"
- (if dynamic-docstrings
- "\t (string-lessp emacs-version \"19.29\")))\n"
- "\t (string-lessp emacs-version \"19\")))\n")
- " (error \"`"
- ;; prin1-to-string is used to quote backslashes.
- (substring (prin1-to-string (file-name-nondirectory filename))
- 1 -1)
- (if dynamic-docstrings
- "' was compiled for Emacs 19.29 or later\"))\n\n"
- "' was compiled for Emacs 19\"))\n\n"))
- (insert "(or (boundp 'current-load-list) (setq current-load-list nil))\n"
- "\n")
- )))
-
-
-(defun byte-compile-output-file-form (form)
- ;; writes the given form to the output buffer, being careful of docstrings
- ;; in defun, defmacro, defvar, defconst and autoload because make-docfile is
- ;; so amazingly stupid.
- ;; defalias calls are output directly by byte-compile-file-form-defmumble;
- ;; it does not pay to first build the defalias in defmumble and then parse
- ;; it here.
- (if (and (memq (car-safe form) '(defun defmacro defvar defconst autoload))
- (stringp (nth 3 form)))
- (byte-compile-output-docform nil nil '("\n(" 3 ")") form nil
- (eq (car form) 'autoload))
- (let ((print-escape-newlines t)
- (print-length nil)
- (print-level nil)
- (print-quoted t)
- (print-gensym t))
- (princ "\n" outbuffer)
- (prin1 form outbuffer)
- nil)))
-
-(defun byte-compile-output-docform (preface name info form specindex quoted)
- "Print a form with a doc string. INFO is (prefix doc-index postfix).
-If PREFACE and NAME are non-nil, print them too,
-before INFO and the FORM but after the doc string itself.
-If SPECINDEX is non-nil, it is the index in FORM
-of the function bytecode string. In that case,
-we output that argument and the following argument (the constants vector)
-together, for lazy loading.
-QUOTED says that we have to put a quote before the
-list that represents a doc string reference.
-`autoload' needs that."
- ;; We need to examine byte-compile-dynamic-docstrings
- ;; in the input buffer (now current), not in the output buffer.
- (let ((dynamic-docstrings byte-compile-dynamic-docstrings))
- (set-buffer
- (prog1 (current-buffer)
- (set-buffer outbuffer)
- (let (position)
-
- ;; Insert the doc string, and make it a comment with #@LENGTH.
- (and (>= (nth 1 info) 0)
- dynamic-docstrings
- (not byte-compile-compatibility)
- (progn
- ;; Make the doc string start at beginning of line
- ;; for make-docfile's sake.
- (insert "\n")
- (setq position
- (byte-compile-output-as-comment
- (nth (nth 1 info) form) nil))
- ;; If the doc string starts with * (a user variable),
- ;; negate POSITION.
- (if (and (stringp (nth (nth 1 info) form))
- (> (length (nth (nth 1 info) form)) 0)
- (eq (aref (nth (nth 1 info) form) 0) ?*))
- (setq position (- position)))))
-
- (if preface
- (progn
- (insert preface)
- (prin1 name outbuffer)))
- (insert (car info))
- (let ((print-escape-newlines t)
- (print-quoted t)
- (print-gensym t)
- (index 0))
- (prin1 (car form) outbuffer)
- (while (setq form (cdr form))
- (setq index (1+ index))
- (insert " ")
- (cond ((and (numberp specindex) (= index specindex))
- (let ((position
- (byte-compile-output-as-comment
- (cons (car form) (nth 1 form))
- t)))
- (princ (format "(#$ . %d) nil" position) outbuffer)
- (setq form (cdr form))
- (setq index (1+ index))))
- ((= index (nth 1 info))
- (if position
- (princ (format (if quoted "'(#$ . %d)" "(#$ . %d)")
- position)
- outbuffer)
- (let ((print-escape-newlines nil))
- (goto-char (prog1 (1+ (point))
- (prin1 (car form) outbuffer)))
- (insert "\\\n")
- (goto-char (point-max)))))
- (t
- (prin1 (car form) outbuffer)))))
- (insert (nth 2 info))))))
- nil)
-
-(defun byte-compile-keep-pending (form &optional handler)
- (if (memq byte-optimize '(t source))
- (setq form (byte-optimize-form form t)))
- (if handler
- (let ((for-effect t))
- ;; To avoid consing up monstrously large forms at load time, we split
- ;; the output regularly.
- (and (memq (car-safe form) '(fset defalias))
- (nthcdr 300 byte-compile-output)
- (byte-compile-flush-pending))
- (funcall handler form)
- (if for-effect
- (byte-compile-discard)))
- (byte-compile-form form t))
- nil)
-
-(defun byte-compile-flush-pending ()
- (if byte-compile-output
- (let ((form (byte-compile-out-toplevel t 'file)))
- (cond ((eq (car-safe form) 'progn)
- (mapcar 'byte-compile-output-file-form (cdr form)))
- (form
- (byte-compile-output-file-form form)))
- (setq byte-compile-constants nil
- byte-compile-variables nil
- byte-compile-depth 0
- byte-compile-maxdepth 0
- byte-compile-output nil))))
-
-(defun byte-compile-file-form (form)
- (let ((byte-compile-current-form nil) ; close over this for warnings.
- handler)
- (cond
- ((not (consp form))
- (byte-compile-keep-pending form))
- ((and (symbolp (car form))
- (setq handler (get (car form) 'byte-hunk-handler)))
- (cond ((setq form (funcall handler form))
- (byte-compile-flush-pending)
- (byte-compile-output-file-form form))))
- ((eq form (setq form (macroexpand form byte-compile-macro-environment)))
- (byte-compile-keep-pending form))
- (t
- (byte-compile-file-form form)))))
-
-;; Functions and variables with doc strings must be output separately,
-;; so make-docfile can recognise them. Most other things can be output
-;; as byte-code.
-
-(put 'defsubst 'byte-hunk-handler 'byte-compile-file-form-defsubst)
-(defun byte-compile-file-form-defsubst (form)
- (cond ((assq (nth 1 form) byte-compile-unresolved-functions)
- (setq byte-compile-current-form (nth 1 form))
- (byte-compile-warn "defsubst %s was used before it was defined"
- (nth 1 form))))
- (byte-compile-file-form
- (macroexpand form byte-compile-macro-environment))
- ;; Return nil so the form is not output twice.
- nil)
-
-(put 'autoload 'byte-hunk-handler 'byte-compile-file-form-autoload)
-(defun byte-compile-file-form-autoload (form)
- (and (let ((form form))
- (while (if (setq form (cdr form)) (byte-compile-constp (car form))))
- (null form)) ;Constants only
- (eval (nth 5 form)) ;Macro
- (eval form)) ;Define the autoload.
- (if (stringp (nth 3 form))
- form
- ;; No doc string, so we can compile this as a normal form.
- (byte-compile-keep-pending form 'byte-compile-normal-call)))
-
-(put 'defvar 'byte-hunk-handler 'byte-compile-file-form-defvar)
-(put 'defconst 'byte-hunk-handler 'byte-compile-file-form-defvar)
-(defun byte-compile-file-form-defvar (form)
- (if (null (nth 3 form))
- ;; Since there is no doc string, we can compile this as a normal form,
- ;; and not do a file-boundary.
- (byte-compile-keep-pending form)
- (if (memq 'free-vars byte-compile-warnings)
- (setq byte-compile-bound-variables
- (cons (nth 1 form) byte-compile-bound-variables)))
- (cond ((consp (nth 2 form))
- (setq form (copy-sequence form))
- (setcar (cdr (cdr form))
- (byte-compile-top-level (nth 2 form) nil 'file))))
- form))
-
-(put 'require 'byte-hunk-handler 'byte-compile-file-form-eval-boundary)
-(defun byte-compile-file-form-eval-boundary (form)
- (eval form)
- (byte-compile-keep-pending form 'byte-compile-normal-call))
-
-(put 'progn 'byte-hunk-handler 'byte-compile-file-form-progn)
-(put 'prog1 'byte-hunk-handler 'byte-compile-file-form-progn)
-(put 'prog2 'byte-hunk-handler 'byte-compile-file-form-progn)
-(defun byte-compile-file-form-progn (form)
- (mapcar 'byte-compile-file-form (cdr form))
- ;; Return nil so the forms are not output twice.
- nil)
-
-;; This handler is not necessary, but it makes the output from dont-compile
-;; and similar macros cleaner.
-(put 'eval 'byte-hunk-handler 'byte-compile-file-form-eval)
-(defun byte-compile-file-form-eval (form)
- (if (eq (car-safe (nth 1 form)) 'quote)
- (nth 1 (nth 1 form))
- (byte-compile-keep-pending form)))
-
-(put 'defun 'byte-hunk-handler 'byte-compile-file-form-defun)
-(defun byte-compile-file-form-defun (form)
- (byte-compile-file-form-defmumble form nil))
-
-(put 'defmacro 'byte-hunk-handler 'byte-compile-file-form-defmacro)
-(defun byte-compile-file-form-defmacro (form)
- (byte-compile-file-form-defmumble form t))
-
-(defun byte-compile-file-form-defmumble (form macrop)
- (let* ((name (car (cdr form)))
- (this-kind (if macrop 'byte-compile-macro-environment
- 'byte-compile-function-environment))
- (that-kind (if macrop 'byte-compile-function-environment
- 'byte-compile-macro-environment))
- (this-one (assq name (symbol-value this-kind)))
- (that-one (assq name (symbol-value that-kind)))
- (byte-compile-free-references nil)
- (byte-compile-free-assignments nil))
-
- ;; When a function or macro is defined, add it to the call tree so that
- ;; we can tell when functions are not used.
- (if byte-compile-generate-call-tree
- (or (assq name byte-compile-call-tree)
- (setq byte-compile-call-tree
- (cons (list name nil nil) byte-compile-call-tree))))
-
- (setq byte-compile-current-form name) ; for warnings
- (if (memq 'redefine byte-compile-warnings)
- (byte-compile-arglist-warn form macrop))
- (if byte-compile-verbose
- (message "Compiling %s... (%s)" (or filename "") (nth 1 form)))
- (cond (that-one
- (if (and (memq 'redefine byte-compile-warnings)
- ;; don't warn when compiling the stubs in byte-run...
- (not (assq (nth 1 form)
- byte-compile-initial-macro-environment)))
- (byte-compile-warn
- "%s defined multiple times, as both function and macro"
- (nth 1 form)))
- (setcdr that-one nil))
- (this-one
- (if (and (memq 'redefine byte-compile-warnings)
- ;; hack: don't warn when compiling the magic internal
- ;; byte-compiler macros in byte-run.el...
- (not (assq (nth 1 form)
- byte-compile-initial-macro-environment)))
- (byte-compile-warn "%s %s defined multiple times in this file"
- (if macrop "macro" "function")
- (nth 1 form))))
- ((and (fboundp name)
- (eq (car-safe (symbol-function name))
- (if macrop 'lambda 'macro)))
- (if (memq 'redefine byte-compile-warnings)
- (byte-compile-warn "%s %s being redefined as a %s"
- (if macrop "function" "macro")
- (nth 1 form)
- (if macrop "macro" "function")))
- ;; shadow existing definition
- (set this-kind
- (cons (cons name nil) (symbol-value this-kind))))
- )
- (let ((body (nthcdr 3 form)))
- (if (and (stringp (car body))
- (symbolp (car-safe (cdr-safe body)))
- (car-safe (cdr-safe body))
- (stringp (car-safe (cdr-safe (cdr-safe body)))))
- (byte-compile-warn "Probable `\"' without `\\' in doc string of %s"
- (nth 1 form))))
- (let* ((new-one (byte-compile-lambda (cons 'lambda (nthcdr 2 form))))
- (code (byte-compile-byte-code-maker new-one)))
- (if this-one
- (setcdr this-one new-one)
- (set this-kind
- (cons (cons name new-one) (symbol-value this-kind))))
- (if (and (stringp (nth 3 form))
- (eq 'quote (car-safe code))
- (eq 'lambda (car-safe (nth 1 code))))
- (cons (car form)
- (cons name (cdr (nth 1 code))))
- (byte-compile-flush-pending)
- (if (not (stringp (nth 3 form)))
- ;; No doc string. Provide -1 as the "doc string index"
- ;; so that no element will be treated as a doc string.
- (byte-compile-output-docform
- (if (byte-compile-version-cond byte-compile-compatibility)
- "\n(fset '" "\n(defalias '")
- name
- (cond ((atom code)
- (if macrop '(" '(macro . #[" -1 "])") '(" #[" -1 "]")))
- ((eq (car code) 'quote)
- (setq code new-one)
- (if macrop '(" '(macro " -1 ")") '(" '(" -1 ")")))
- ((if macrop '(" (cons 'macro (" -1 "))") '(" (" -1 ")"))))
- (append code nil)
- (and (atom code) byte-compile-dynamic
- 1)
- nil)
- ;; Output the form by hand, that's much simpler than having
- ;; b-c-output-file-form analyze the defalias.
- (byte-compile-output-docform
- (if (byte-compile-version-cond byte-compile-compatibility)
- "\n(fset '" "\n(defalias '")
- name
- (cond ((atom code)
- (if macrop '(" '(macro . #[" 4 "])") '(" #[" 4 "]")))
- ((eq (car code) 'quote)
- (setq code new-one)
- (if macrop '(" '(macro " 2 ")") '(" '(" 2 ")")))
- ((if macrop '(" (cons 'macro (" 5 "))") '(" (" 5 ")"))))
- (append code nil)
- (and (atom code) byte-compile-dynamic
- 1)
- nil))
- (princ ")" outbuffer)
- nil))))
-
-;; Print Lisp object EXP in the output file, inside a comment,
-;; and return the file position it will have.
-;; If QUOTED is non-nil, print with quoting; otherwise, print without quoting.
-(defun byte-compile-output-as-comment (exp quoted)
- (let ((position (point)))
- (set-buffer
- (prog1 (current-buffer)
- (set-buffer outbuffer)
-
- ;; Insert EXP, and make it a comment with #@LENGTH.
- (insert " ")
- (if quoted
- (prin1 exp outbuffer)
- (princ exp outbuffer))
- (goto-char position)
- ;; Quote certain special characters as needed.
- ;; get_doc_string in doc.c does the unquoting.
- (while (search-forward "\^A" nil t)
- (replace-match "\^A\^A" t t))
- (goto-char position)
- (while (search-forward "\000" nil t)
- (replace-match "\^A0" t t))
- (goto-char position)
- (while (search-forward "\037" nil t)
- (replace-match "\^A_" t t))
- (goto-char (point-max))
- (insert "\037")
- (goto-char position)
- (insert "#@" (format "%d" (- (point-max) position)))
-
- ;; Save the file position of the object.
- ;; Note we should add 1 to skip the space
- ;; that we inserted before the actual doc string,
- ;; and subtract 1 to convert from an 1-origin Emacs position
- ;; to a file position; they cancel.
- (setq position (point))
- (goto-char (point-max))))
- position))
-
-
-
-;;;###autoload
-(defun byte-compile (form)
- "If FORM is a symbol, byte-compile its function definition.
-If FORM is a lambda or a macro, byte-compile it as a function."
- (displaying-byte-compile-warnings
- (byte-compile-close-variables
- (let* ((fun (if (symbolp form)
- (and (fboundp form) (symbol-function form))
- form))
- (macro (eq (car-safe fun) 'macro)))
- (if macro
- (setq fun (cdr fun)))
- (cond ((eq (car-safe fun) 'lambda)
- (setq fun (if macro
- (cons 'macro (byte-compile-lambda fun))
- (byte-compile-lambda fun)))
- (if (symbolp form)
- (defalias form fun)
- fun)))))))
-
-(defun byte-compile-sexp (sexp)
- "Compile and return SEXP."
- (displaying-byte-compile-warnings
- (byte-compile-close-variables
- (byte-compile-top-level sexp))))
-
-;; Given a function made by byte-compile-lambda, make a form which produces it.
-(defun byte-compile-byte-code-maker (fun)
- (cond
- ((byte-compile-version-cond byte-compile-compatibility)
- ;; Return (quote (lambda ...)).
- (list 'quote (byte-compile-byte-code-unmake fun)))
- ;; ## atom is faster than compiled-func-p.
- ((atom fun) ; compiled function.
- ;; generate-emacs19-bytecodes must be on, otherwise byte-compile-lambda
- ;; would have produced a lambda.
- fun)
- ;; b-c-lambda didn't produce a compiled-function, so it's either a trivial
- ;; function, or this is Emacs 18, or generate-emacs19-bytecodes is off.
- ((let (tmp)
- (if (and (setq tmp (assq 'byte-code (cdr-safe (cdr fun))))
- (null (cdr (memq tmp fun))))
- ;; Generate a make-byte-code call.
- (let* ((interactive (assq 'interactive (cdr (cdr fun)))))
- (nconc (list 'make-byte-code
- (list 'quote (nth 1 fun)) ;arglist
- (nth 1 tmp) ;bytes
- (nth 2 tmp) ;consts
- (nth 3 tmp)) ;depth
- (cond ((stringp (nth 2 fun))
- (list (nth 2 fun))) ;doc
- (interactive
- (list nil)))
- (cond (interactive
- (list (if (or (null (nth 1 interactive))
- (stringp (nth 1 interactive)))
- (nth 1 interactive)
- ;; Interactive spec is a list or a variable
- ;; (if it is correct).
- (list 'quote (nth 1 interactive))))))))
- ;; a non-compiled function (probably trivial)
- (list 'quote fun))))))
-
-;; Turn a function into an ordinary lambda. Needed for v18 files.
-(defun byte-compile-byte-code-unmake (function)
- (if (consp function)
- function;;It already is a lambda.
- (setq function (append function nil)) ; turn it into a list
- (nconc (list 'lambda (nth 0 function))
- (and (nth 4 function) (list (nth 4 function)))
- (if (nthcdr 5 function)
- (list (cons 'interactive (if (nth 5 function)
- (nthcdr 5 function)))))
- (list (list 'byte-code
- (nth 1 function) (nth 2 function)
- (nth 3 function))))))
-
-
-;; Byte-compile a lambda-expression and return a valid function.
-;; The value is usually a compiled function but may be the original
-;; lambda-expression.
-(defun byte-compile-lambda (fun)
- (let* ((arglist (nth 1 fun))
- (byte-compile-bound-variables
- (nconc (and (memq 'free-vars byte-compile-warnings)
- (delq '&rest (delq '&optional (copy-sequence arglist))))
- byte-compile-bound-variables))
- (body (cdr (cdr fun)))
- (doc (if (stringp (car body))
- (prog1 (car body)
- ;; Discard the doc string
- ;; unless it is the last element of the body.
- (if (nthcdr 2 body)
- (setq body (cdr body))))))
- (int (assq 'interactive body)))
- (cond (int
- ;; Skip (interactive) if it is in front (the most usual location).
- (if (eq int (car body))
- (setq body (cdr body)))
- (cond ((consp (cdr int))
- (if (cdr (cdr int))
- (byte-compile-warn "malformed interactive spec: %s"
- (prin1-to-string int)))
- ;; If the interactive spec is a call to `list',
- ;; don't compile it, because `call-interactively'
- ;; looks at the args of `list'.
- (let ((form (nth 1 int)))
- (while (or (eq (car-safe form) 'let)
- (eq (car-safe form) 'let*)
- (eq (car-safe form) 'save-excursion))
- (while (consp (cdr form))
- (setq form (cdr form)))
- (setq form (car form)))
- (or (eq (car-safe form) 'list)
- (setq int (list 'interactive
- (byte-compile-top-level (nth 1 int)))))))
- ((cdr int)
- (byte-compile-warn "malformed interactive spec: %s"
- (prin1-to-string int))))))
- (let ((compiled (byte-compile-top-level (cons 'progn body) nil 'lambda)))
- (if (and (eq 'byte-code (car-safe compiled))
- (not (byte-compile-version-cond
- byte-compile-compatibility)))
- (apply 'make-byte-code
- (append (list arglist)
- ;; byte-string, constants-vector, stack depth
- (cdr compiled)
- ;; optionally, the doc string.
- (if (or doc int)
- (list doc))
- ;; optionally, the interactive spec.
- (if int
- (list (nth 1 int)))))
- (setq compiled
- (nconc (if int (list int))
- (cond ((eq (car-safe compiled) 'progn) (cdr compiled))
- (compiled (list compiled)))))
- (nconc (list 'lambda arglist)
- (if (or doc (stringp (car compiled)))
- (cons doc (cond (compiled)
- (body (list nil))))
- compiled))))))
-
-(defun byte-compile-constants-vector ()
- ;; Builds the constants-vector from the current variables and constants.
- ;; This modifies the constants from (const . nil) to (const . offset).
- ;; To keep the byte-codes to look up the vector as short as possible:
- ;; First 6 elements are vars, as there are one-byte varref codes for those.
- ;; Next up to byte-constant-limit are constants, still with one-byte codes.
- ;; Next variables again, to get 2-byte codes for variable lookup.
- ;; The rest of the constants and variables need 3-byte byte-codes.
- (let* ((i -1)
- (rest (nreverse byte-compile-variables)) ; nreverse because the first
- (other (nreverse byte-compile-constants)) ; vars often are used most.
- ret tmp
- (limits '(5 ; Use the 1-byte varref codes,
- 63 ; 1-constlim ; 1-byte byte-constant codes,
- 255 ; 2-byte varref codes,
- 65535)) ; 3-byte codes for the rest.
- limit)
- (while (or rest other)
- (setq limit (car limits))
- (while (and rest (not (eq i limit)))
- (if (setq tmp (assq (car (car rest)) ret))
- (setcdr (car rest) (cdr tmp))
- (setcdr (car rest) (setq i (1+ i)))
- (setq ret (cons (car rest) ret)))
- (setq rest (cdr rest)))
- (setq limits (cdr limits)
- rest (prog1 other
- (setq other rest))))
- (apply 'vector (nreverse (mapcar 'car ret)))))
-
-;; Given an expression FORM, compile it and return an equivalent byte-code
-;; expression (a call to the function byte-code).
-(defun byte-compile-top-level (form &optional for-effect output-type)
- ;; OUTPUT-TYPE advises about how form is expected to be used:
- ;; 'eval or nil -> a single form,
- ;; 'progn or t -> a list of forms,
- ;; 'lambda -> body of a lambda,
- ;; 'file -> used at file-level.
- (let ((byte-compile-constants nil)
- (byte-compile-variables nil)
- (byte-compile-tag-number 0)
- (byte-compile-depth 0)
- (byte-compile-maxdepth 0)
- (byte-compile-output nil))
- (if (memq byte-optimize '(t source))
- (setq form (byte-optimize-form form for-effect)))
- (while (and (eq (car-safe form) 'progn) (null (cdr (cdr form))))
- (setq form (nth 1 form)))
- (if (and (eq 'byte-code (car-safe form))
- (not (memq byte-optimize '(t byte)))
- (stringp (nth 1 form)) (vectorp (nth 2 form))
- (natnump (nth 3 form)))
- form
- (byte-compile-form form for-effect)
- (byte-compile-out-toplevel for-effect output-type))))
-
-(defun byte-compile-out-toplevel (&optional for-effect output-type)
- (if for-effect
- ;; The stack is empty. Push a value to be returned from (byte-code ..).
- (if (eq (car (car byte-compile-output)) 'byte-discard)
- (setq byte-compile-output (cdr byte-compile-output))
- (byte-compile-push-constant
- ;; Push any constant - preferably one which already is used, and
- ;; a number or symbol - ie not some big sequence. The return value
- ;; isn't returned, but it would be a shame if some textually large
- ;; constant was not optimized away because we chose to return it.
- (and (not (assq nil byte-compile-constants)) ; Nil is often there.
- (let ((tmp (reverse byte-compile-constants)))
- (while (and tmp (not (or (symbolp (car (car tmp)))
- (numberp (car (car tmp))))))
- (setq tmp (cdr tmp)))
- (car (car tmp)))))))
- (byte-compile-out 'byte-return 0)
- (setq byte-compile-output (nreverse byte-compile-output))
- (if (memq byte-optimize '(t byte))
- (setq byte-compile-output
- (byte-optimize-lapcode byte-compile-output for-effect)))
-
- ;; Decompile trivial functions:
- ;; only constants and variables, or a single funcall except in lambdas.
- ;; Except for Lisp_Compiled objects, forms like (foo "hi")
- ;; are still quicker than (byte-code "..." [foo "hi"] 2).
- ;; Note that even (quote foo) must be parsed just as any subr by the
- ;; interpreter, so quote should be compiled into byte-code in some contexts.
- ;; What to leave uncompiled:
- ;; lambda -> never. we used to leave it uncompiled if the body was
- ;; a single atom, but that causes confusion if the docstring
- ;; uses the (file . pos) syntax. Besides, now that we have
- ;; the Lisp_Compiled type, the compiled form is faster.
- ;; eval -> atom, quote or (function atom atom atom)
- ;; progn -> as <<same-as-eval>> or (progn <<same-as-eval>> atom)
- ;; file -> as progn, but takes both quotes and atoms, and longer forms.
- (let (rest
- (maycall (not (eq output-type 'lambda))) ; t if we may make a funcall.
- tmp body)
- (cond
- ;; #### This should be split out into byte-compile-nontrivial-function-p.
- ((or (eq output-type 'lambda)
- (nthcdr (if (eq output-type 'file) 50 8) byte-compile-output)
- (assq 'TAG byte-compile-output) ; Not necessary, but speeds up a bit.
- (not (setq tmp (assq 'byte-return byte-compile-output)))
- (progn
- (setq rest (nreverse
- (cdr (memq tmp (reverse byte-compile-output)))))
- (while (cond
- ((memq (car (car rest)) '(byte-varref byte-constant))
- (setq tmp (car (cdr (car rest))))
- (if (if (eq (car (car rest)) 'byte-constant)
- (or (consp tmp)
- (and (symbolp tmp)
- (not (memq tmp '(nil t))))))
- (if maycall
- (setq body (cons (list 'quote tmp) body)))
- (setq body (cons tmp body))))
- ((and maycall
- ;; Allow a funcall if at most one atom follows it.
- (null (nthcdr 3 rest))
- (setq tmp (get (car (car rest)) 'byte-opcode-invert))
- (or (null (cdr rest))
- (and (memq output-type '(file progn t))
- (cdr (cdr rest))
- (eq (car (nth 1 rest)) 'byte-discard)
- (progn (setq rest (cdr rest)) t))))
- (setq maycall nil) ; Only allow one real function call.
- (setq body (nreverse body))
- (setq body (list
- (if (and (eq tmp 'funcall)
- (eq (car-safe (car body)) 'quote))
- (cons (nth 1 (car body)) (cdr body))
- (cons tmp body))))
- (or (eq output-type 'file)
- (not (delq nil (mapcar 'consp (cdr (car body))))))))
- (setq rest (cdr rest)))
- rest))
- (let ((byte-compile-vector (byte-compile-constants-vector)))
- (list 'byte-code (byte-compile-lapcode byte-compile-output)
- byte-compile-vector byte-compile-maxdepth)))
- ;; it's a trivial function
- ((cdr body) (cons 'progn (nreverse body)))
- ((car body)))))
-
-;; Given BODY, compile it and return a new body.
-(defun byte-compile-top-level-body (body &optional for-effect)
- (setq body (byte-compile-top-level (cons 'progn body) for-effect t))
- (cond ((eq (car-safe body) 'progn)
- (cdr body))
- (body
- (list body))))
-
-;; This is the recursive entry point for compiling each subform of an
-;; expression.
-;; If for-effect is non-nil, byte-compile-form will output a byte-discard
-;; before terminating (ie no value will be left on the stack).
-;; A byte-compile handler may, when for-effect is non-nil, choose output code
-;; which does not leave a value on the stack, and then set for-effect to nil
-;; (to prevent byte-compile-form from outputting the byte-discard).
-;; If a handler wants to call another handler, it should do so via
-;; byte-compile-form, or take extreme care to handle for-effect correctly.
-;; (Use byte-compile-form-do-effect to reset the for-effect flag too.)
-;;
-(defun byte-compile-form (form &optional for-effect)
- (setq form (macroexpand form byte-compile-macro-environment))
- (cond ((not (consp form))
- (cond ((or (not (symbolp form)) (memq form '(nil t)))
- (byte-compile-constant form))
- ((and for-effect byte-compile-delete-errors)
- (setq for-effect nil))
- (t (byte-compile-variable-ref 'byte-varref form))))
- ((symbolp (car form))
- (let* ((fn (car form))
- (handler (get fn 'byte-compile)))
- (if (memq fn '(t nil))
- (byte-compile-warn "%s called as a function" fn))
- (if (and handler
- (or (not (byte-compile-version-cond
- byte-compile-compatibility))
- (not (get (get fn 'byte-opcode) 'emacs19-opcode))))
- (funcall handler form)
- (if (memq 'callargs byte-compile-warnings)
- (byte-compile-callargs-warn form))
- (byte-compile-normal-call form))))
- ((and (or (byte-code-function-p (car form))
- (eq (car-safe (car form)) 'lambda))
- ;; if the form comes out the same way it went in, that's
- ;; because it was malformed, and we couldn't unfold it.
- (not (eq form (setq form (byte-compile-unfold-lambda form)))))
- (byte-compile-form form for-effect)
- (setq for-effect nil))
- ((byte-compile-normal-call form)))
- (if for-effect
- (byte-compile-discard)))
-
-(defun byte-compile-normal-call (form)
- (if byte-compile-generate-call-tree
- (byte-compile-annotate-call-tree form))
- (byte-compile-push-constant (car form))
- (mapcar 'byte-compile-form (cdr form)) ; wasteful, but faster.
- (byte-compile-out 'byte-call (length (cdr form))))
-
-(defun byte-compile-variable-ref (base-op var)
- (if (or (not (symbolp var)) (memq var '(nil t)))
- (byte-compile-warn (if (eq base-op 'byte-varbind)
- "Attempt to let-bind %s %s"
- "Variable reference to %s %s")
- (if (symbolp var) "constant" "nonvariable")
- (prin1-to-string var))
- (if (and (get var 'byte-obsolete-variable)
- (memq 'obsolete byte-compile-warnings))
- (let ((ob (get var 'byte-obsolete-variable)))
- (byte-compile-warn "%s is an obsolete variable; %s" var
- (if (stringp ob)
- ob
- (format "use %s instead." ob)))))
- (if (memq 'free-vars byte-compile-warnings)
- (if (eq base-op 'byte-varbind)
- (setq byte-compile-bound-variables
- (cons var byte-compile-bound-variables))
- (or (boundp var)
- (memq var byte-compile-bound-variables)
- (if (eq base-op 'byte-varset)
- (or (memq var byte-compile-free-assignments)
- (progn
- (byte-compile-warn "assignment to free variable %s" var)
- (setq byte-compile-free-assignments
- (cons var byte-compile-free-assignments))))
- (or (memq var byte-compile-free-references)
- (progn
- (byte-compile-warn "reference to free variable %s" var)
- (setq byte-compile-free-references
- (cons var byte-compile-free-references)))))))))
- (let ((tmp (assq var byte-compile-variables)))
- (or tmp
- (setq tmp (list var)
- byte-compile-variables (cons tmp byte-compile-variables)))
- (byte-compile-out base-op tmp)))
-
-(defmacro byte-compile-get-constant (const)
- (` (or (if (stringp (, const))
- (assoc (, const) byte-compile-constants)
- (assq (, const) byte-compile-constants))
- (car (setq byte-compile-constants
- (cons (list (, const)) byte-compile-constants))))))
-
-;; Use this when the value of a form is a constant. This obeys for-effect.
-(defun byte-compile-constant (const)
- (if for-effect
- (setq for-effect nil)
- (byte-compile-out 'byte-constant (byte-compile-get-constant const))))
-
-;; Use this for a constant that is not the value of its containing form.
-;; This ignores for-effect.
-(defun byte-compile-push-constant (const)
- (let ((for-effect nil))
- (inline (byte-compile-constant const))))
-
-
-;; Compile those primitive ordinary functions
-;; which have special byte codes just for speed.
-
-(defmacro byte-defop-compiler (function &optional compile-handler)
- ;; add a compiler-form for FUNCTION.
- ;; If function is a symbol, then the variable "byte-SYMBOL" must name
- ;; the opcode to be used. If function is a list, the first element
- ;; is the function and the second element is the bytecode-symbol.
- ;; COMPILE-HANDLER is the function to use to compile this byte-op, or
- ;; may be the abbreviations 0, 1, 2, 3, 0-1, or 1-2.
- ;; If it is nil, then the handler is "byte-compile-SYMBOL."
- (let (opcode)
- (if (symbolp function)
- (setq opcode (intern (concat "byte-" (symbol-name function))))
- (setq opcode (car (cdr function))
- function (car function)))
- (let ((fnform
- (list 'put (list 'quote function) ''byte-compile
- (list 'quote
- (or (cdr (assq compile-handler
- '((0 . byte-compile-no-args)
- (1 . byte-compile-one-arg)
- (2 . byte-compile-two-args)
- (3 . byte-compile-three-args)
- (0-1 . byte-compile-zero-or-one-arg)
- (1-2 . byte-compile-one-or-two-args)
- (2-3 . byte-compile-two-or-three-args)
- )))
- compile-handler
- (intern (concat "byte-compile-"
- (symbol-name function))))))))
- (if opcode
- (list 'progn fnform
- (list 'put (list 'quote function)
- ''byte-opcode (list 'quote opcode))
- (list 'put (list 'quote opcode)
- ''byte-opcode-invert (list 'quote function)))
- fnform))))
-
-(defmacro byte-defop-compiler19 (function &optional compile-handler)
- ;; Just like byte-defop-compiler, but defines an opcode that will only
- ;; be used when byte-compile-compatibility is false.
- (if (and (byte-compile-single-version)
- byte-compile-compatibility)
- ;; #### instead of doing nothing, this should do some remprops,
- ;; #### to protect against the case where a single-version compiler
- ;; #### is loaded into a world that has contained a multi-version one.
- nil
- (list 'progn
- (list 'put
- (list 'quote
- (or (car (cdr-safe function))
- (intern (concat "byte-"
- (symbol-name (or (car-safe function) function))))))
- ''emacs19-opcode t)
- (list 'byte-defop-compiler function compile-handler))))
-
-(defmacro byte-defop-compiler-1 (function &optional compile-handler)
- (list 'byte-defop-compiler (list function nil) compile-handler))
-
-
-(put 'byte-call 'byte-opcode-invert 'funcall)
-(put 'byte-list1 'byte-opcode-invert 'list)
-(put 'byte-list2 'byte-opcode-invert 'list)
-(put 'byte-list3 'byte-opcode-invert 'list)
-(put 'byte-list4 'byte-opcode-invert 'list)
-(put 'byte-listN 'byte-opcode-invert 'list)
-(put 'byte-concat2 'byte-opcode-invert 'concat)
-(put 'byte-concat3 'byte-opcode-invert 'concat)
-(put 'byte-concat4 'byte-opcode-invert 'concat)
-(put 'byte-concatN 'byte-opcode-invert 'concat)
-(put 'byte-insertN 'byte-opcode-invert 'insert)
-
-(byte-defop-compiler (dot byte-point) 0)
-(byte-defop-compiler (dot-max byte-point-max) 0)
-(byte-defop-compiler (dot-min byte-point-min) 0)
-(byte-defop-compiler point 0)
-;;(byte-defop-compiler mark 0) ;; obsolete
-(byte-defop-compiler point-max 0)
-(byte-defop-compiler point-min 0)
-(byte-defop-compiler following-char 0)
-(byte-defop-compiler preceding-char 0)
-(byte-defop-compiler current-column 0)
-(byte-defop-compiler eolp 0)
-(byte-defop-compiler eobp 0)
-(byte-defop-compiler bolp 0)
-(byte-defop-compiler bobp 0)
-(byte-defop-compiler current-buffer 0)
-;;(byte-defop-compiler read-char 0) ;; obsolete
-(byte-defop-compiler interactive-p 0)
-(byte-defop-compiler19 widen 0)
-(byte-defop-compiler19 end-of-line 0-1)
-(byte-defop-compiler19 forward-char 0-1)
-(byte-defop-compiler19 forward-line 0-1)
-(byte-defop-compiler symbolp 1)
-(byte-defop-compiler consp 1)
-(byte-defop-compiler stringp 1)
-(byte-defop-compiler listp 1)
-(byte-defop-compiler not 1)
-(byte-defop-compiler (null byte-not) 1)
-(byte-defop-compiler car 1)
-(byte-defop-compiler cdr 1)
-(byte-defop-compiler length 1)
-(byte-defop-compiler symbol-value 1)
-(byte-defop-compiler symbol-function 1)
-(byte-defop-compiler (1+ byte-add1) 1)
-(byte-defop-compiler (1- byte-sub1) 1)
-(byte-defop-compiler goto-char 1)
-(byte-defop-compiler char-after 1)
-(byte-defop-compiler set-buffer 1)
-;;(byte-defop-compiler set-mark 1) ;; obsolete
-(byte-defop-compiler19 forward-word 1)
-(byte-defop-compiler19 char-syntax 1)
-(byte-defop-compiler19 nreverse 1)
-(byte-defop-compiler19 car-safe 1)
-(byte-defop-compiler19 cdr-safe 1)
-(byte-defop-compiler19 numberp 1)
-(byte-defop-compiler19 integerp 1)
-(byte-defop-compiler19 skip-chars-forward 1-2)
-(byte-defop-compiler19 skip-chars-backward 1-2)
-(byte-defop-compiler (eql byte-eq) 2)
-(byte-defop-compiler eq 2)
-(byte-defop-compiler memq 2)
-(byte-defop-compiler cons 2)
-(byte-defop-compiler aref 2)
-(byte-defop-compiler set 2)
-(byte-defop-compiler (= byte-eqlsign) 2)
-(byte-defop-compiler (< byte-lss) 2)
-(byte-defop-compiler (> byte-gtr) 2)
-(byte-defop-compiler (<= byte-leq) 2)
-(byte-defop-compiler (>= byte-geq) 2)
-(byte-defop-compiler get 2)
-(byte-defop-compiler nth 2)
-(byte-defop-compiler substring 2-3)
-(byte-defop-compiler19 (move-marker byte-set-marker) 2-3)
-(byte-defop-compiler19 set-marker 2-3)
-(byte-defop-compiler19 match-beginning 1)
-(byte-defop-compiler19 match-end 1)
-(byte-defop-compiler19 upcase 1)
-(byte-defop-compiler19 downcase 1)
-(byte-defop-compiler19 string= 2)
-(byte-defop-compiler19 string< 2)
-(byte-defop-compiler19 (string-equal byte-string=) 2)
-(byte-defop-compiler19 (string-lessp byte-string<) 2)
-(byte-defop-compiler19 equal 2)
-(byte-defop-compiler19 nthcdr 2)
-(byte-defop-compiler19 elt 2)
-(byte-defop-compiler19 member 2)
-(byte-defop-compiler19 assq 2)
-(byte-defop-compiler19 (rplaca byte-setcar) 2)
-(byte-defop-compiler19 (rplacd byte-setcdr) 2)
-(byte-defop-compiler19 setcar 2)
-(byte-defop-compiler19 setcdr 2)
-(byte-defop-compiler19 buffer-substring 2)
-(byte-defop-compiler19 delete-region 2)
-(byte-defop-compiler19 narrow-to-region 2)
-(byte-defop-compiler19 (% byte-rem) 2)
-(byte-defop-compiler aset 3)
-
-(byte-defop-compiler max byte-compile-associative)
-(byte-defop-compiler min byte-compile-associative)
-(byte-defop-compiler (+ byte-plus) byte-compile-associative)
-(byte-defop-compiler19 (* byte-mult) byte-compile-associative)
-
-;;####(byte-defop-compiler19 move-to-column 1)
-(byte-defop-compiler-1 interactive byte-compile-noop)
-
-
-(defun byte-compile-subr-wrong-args (form n)
- (byte-compile-warn "%s called with %d arg%s, but requires %s"
- (car form) (length (cdr form))
- (if (= 1 (length (cdr form))) "" "s") n)
- ;; get run-time wrong-number-of-args error.
- (byte-compile-normal-call form))
-
-(defun byte-compile-no-args (form)
- (if (not (= (length form) 1))
- (byte-compile-subr-wrong-args form "none")
- (byte-compile-out (get (car form) 'byte-opcode) 0)))
-
-(defun byte-compile-one-arg (form)
- (if (not (= (length form) 2))
- (byte-compile-subr-wrong-args form 1)
- (byte-compile-form (car (cdr form))) ;; Push the argument
- (byte-compile-out (get (car form) 'byte-opcode) 0)))
-
-(defun byte-compile-two-args (form)
- (if (not (= (length form) 3))
- (byte-compile-subr-wrong-args form 2)
- (byte-compile-form (car (cdr form))) ;; Push the arguments
- (byte-compile-form (nth 2 form))
- (byte-compile-out (get (car form) 'byte-opcode) 0)))
-
-(defun byte-compile-three-args (form)
- (if (not (= (length form) 4))
- (byte-compile-subr-wrong-args form 3)
- (byte-compile-form (car (cdr form))) ;; Push the arguments
- (byte-compile-form (nth 2 form))
- (byte-compile-form (nth 3 form))
- (byte-compile-out (get (car form) 'byte-opcode) 0)))
-
-(defun byte-compile-zero-or-one-arg (form)
- (let ((len (length form)))
- (cond ((= len 1) (byte-compile-one-arg (append form '(nil))))
- ((= len 2) (byte-compile-one-arg form))
- (t (byte-compile-subr-wrong-args form "0-1")))))
-
-(defun byte-compile-one-or-two-args (form)
- (let ((len (length form)))
- (cond ((= len 2) (byte-compile-two-args (append form '(nil))))
- ((= len 3) (byte-compile-two-args form))
- (t (byte-compile-subr-wrong-args form "1-2")))))
-
-(defun byte-compile-two-or-three-args (form)
- (let ((len (length form)))
- (cond ((= len 3) (byte-compile-three-args (append form '(nil))))
- ((= len 4) (byte-compile-three-args form))
- (t (byte-compile-subr-wrong-args form "2-3")))))
-
-(defun byte-compile-noop (form)
- (byte-compile-constant nil))
-
-(defun byte-compile-discard ()
- (byte-compile-out 'byte-discard 0))
-
-
-;; Compile a function that accepts one or more args and is right-associative.
-;; We do it by left-associativity so that the operations
-;; are done in the same order as in interpreted code.
-;; We treat the one-arg case, as in (+ x), like (+ x 0).
-;; in order to convert markers to numbers, and trigger expected errors.
-(defun byte-compile-associative (form)
- (if (cdr form)
- (let ((opcode (get (car form) 'byte-opcode))
- (args (copy-sequence (cdr form))))
- (byte-compile-form (car args))
- (setq args (cdr args))
- (or args (setq args '(0)
- opcode (get '+ 'byte-opcode)))
- (while args
- (byte-compile-form (car args))
- (byte-compile-out opcode 0)
- (setq args (cdr args))))
- (byte-compile-constant (eval form))))
-
-
-;; more complicated compiler macros
-
-(byte-defop-compiler list)
-(byte-defop-compiler concat)
-(byte-defop-compiler fset)
-(byte-defop-compiler (indent-to-column byte-indent-to) byte-compile-indent-to)
-(byte-defop-compiler indent-to)
-(byte-defop-compiler insert)
-(byte-defop-compiler-1 function byte-compile-function-form)
-(byte-defop-compiler-1 - byte-compile-minus)
-(byte-defop-compiler19 (/ byte-quo) byte-compile-quo)
-(byte-defop-compiler19 nconc)
-(byte-defop-compiler-1 beginning-of-line)
-
-(defun byte-compile-list (form)
- (let ((count (length (cdr form))))
- (cond ((= count 0)
- (byte-compile-constant nil))
- ((< count 5)
- (mapcar 'byte-compile-form (cdr form))
- (byte-compile-out
- (aref [byte-list1 byte-list2 byte-list3 byte-list4] (1- count)) 0))
- ((and (< count 256) (not (byte-compile-version-cond
- byte-compile-compatibility)))
- (mapcar 'byte-compile-form (cdr form))
- (byte-compile-out 'byte-listN count))
- (t (byte-compile-normal-call form)))))
-
-(defun byte-compile-concat (form)
- (let ((count (length (cdr form))))
- (cond ((and (< 1 count) (< count 5))
- (mapcar 'byte-compile-form (cdr form))
- (byte-compile-out
- (aref [byte-concat2 byte-concat3 byte-concat4] (- count 2))
- 0))
- ;; Concat of one arg is not a no-op if arg is not a string.
- ((= count 0)
- (byte-compile-form ""))
- ((and (< count 256) (not (byte-compile-version-cond
- byte-compile-compatibility)))
- (mapcar 'byte-compile-form (cdr form))
- (byte-compile-out 'byte-concatN count))
- ((byte-compile-normal-call form)))))
-
-(defun byte-compile-minus (form)
- (if (null (setq form (cdr form)))
- (byte-compile-constant 0)
- (byte-compile-form (car form))
- (if (cdr form)
- (while (setq form (cdr form))
- (byte-compile-form (car form))
- (byte-compile-out 'byte-diff 0))
- (byte-compile-out 'byte-negate 0))))
-
-(defun byte-compile-quo (form)
- (let ((len (length form)))
- (cond ((<= len 2)
- (byte-compile-subr-wrong-args form "2 or more"))
- (t
- (byte-compile-form (car (setq form (cdr form))))
- (while (setq form (cdr form))
- (byte-compile-form (car form))
- (byte-compile-out 'byte-quo 0))))))
-
-(defun byte-compile-nconc (form)
- (let ((len (length form)))
- (cond ((= len 1)
- (byte-compile-constant nil))
- ((= len 2)
- ;; nconc of one arg is a noop, even if that arg isn't a list.
- (byte-compile-form (nth 1 form)))
- (t
- (byte-compile-form (car (setq form (cdr form))))
- (while (setq form (cdr form))
- (byte-compile-form (car form))
- (byte-compile-out 'byte-nconc 0))))))
-
-(defun byte-compile-fset (form)
- ;; warn about forms like (fset 'foo '(lambda () ...))
- ;; (where the lambda expression is non-trivial...)
- (let ((fn (nth 2 form))
- body)
- (if (and (eq (car-safe fn) 'quote)
- (eq (car-safe (setq fn (nth 1 fn))) 'lambda))
- (progn
- (setq body (cdr (cdr fn)))
- (if (stringp (car body)) (setq body (cdr body)))
- (if (eq 'interactive (car-safe (car body))) (setq body (cdr body)))
- (if (and (consp (car body))
- (not (eq 'byte-code (car (car body)))))
- (byte-compile-warn
- "A quoted lambda form is the second argument of fset. This is probably
- not what you want, as that lambda cannot be compiled. Consider using
- the syntax (function (lambda (...) ...)) instead.")))))
- (byte-compile-two-args form))
-
-(defun byte-compile-funarg (form)
- ;; (mapcar '(lambda (x) ..) ..) ==> (mapcar (function (lambda (x) ..)) ..)
- ;; for cases where it's guaranteed that first arg will be used as a lambda.
- (byte-compile-normal-call
- (let ((fn (nth 1 form)))
- (if (and (eq (car-safe fn) 'quote)
- (eq (car-safe (nth 1 fn)) 'lambda))
- (cons (car form)
- (cons (cons 'function (cdr fn))
- (cdr (cdr form))))
- form))))
-
-(defun byte-compile-funarg-2 (form)
- ;; (sort ... '(lambda (x) ..)) ==> (sort ... (function (lambda (x) ..)))
- ;; for cases where it's guaranteed that second arg will be used as a lambda.
- (byte-compile-normal-call
- (let ((fn (nth 2 form)))
- (if (and (eq (car-safe fn) 'quote)
- (eq (car-safe (nth 1 fn)) 'lambda))
- (cons (car form)
- (cons (nth 1 form)
- (cons (cons 'function (cdr fn))
- (cdr (cdr (cdr form))))))
- form))))
-
-;; (function foo) must compile like 'foo, not like (symbol-function 'foo).
-;; Otherwise it will be incompatible with the interpreter,
-;; and (funcall (function foo)) will lose with autoloads.
-
-(defun byte-compile-function-form (form)
- (byte-compile-constant
- (cond ((symbolp (nth 1 form))
- (nth 1 form))
- ;; If we're not allowed to use #[] syntax, then output a form like
- ;; '(lambda (..) (byte-code ..)) instead of a call to make-byte-code.
- ;; In this situation, calling make-byte-code at run-time will usually
- ;; be less efficient than processing a call to byte-code.
- ((byte-compile-version-cond byte-compile-compatibility)
- (byte-compile-byte-code-unmake (byte-compile-lambda (nth 1 form))))
- ((byte-compile-lambda (nth 1 form))))))
-
-(defun byte-compile-indent-to (form)
- (let ((len (length form)))
- (cond ((= len 2)
- (byte-compile-form (car (cdr form)))
- (byte-compile-out 'byte-indent-to 0))
- ((= len 3)
- ;; no opcode for 2-arg case.
- (byte-compile-normal-call form))
- (t
- (byte-compile-subr-wrong-args form "1-2")))))
-
-(defun byte-compile-insert (form)
- (cond ((null (cdr form))
- (byte-compile-constant nil))
- ((and (not (byte-compile-version-cond
- byte-compile-compatibility))
- (<= (length form) 256))
- (mapcar 'byte-compile-form (cdr form))
- (if (cdr (cdr form))
- (byte-compile-out 'byte-insertN (length (cdr form)))
- (byte-compile-out 'byte-insert 0)))
- ((memq t (mapcar 'consp (cdr (cdr form))))
- (byte-compile-normal-call form))
- ;; We can split it; there is no function call after inserting 1st arg.
- (t
- (while (setq form (cdr form))
- (byte-compile-form (car form))
- (byte-compile-out 'byte-insert 0)
- (if (cdr form)
- (byte-compile-discard))))))
-
-(defun byte-compile-beginning-of-line (form)
- (if (not (byte-compile-constp (nth 1 form)))
- (byte-compile-normal-call form)
- (byte-compile-form
- (list 'forward-line
- (if (integerp (setq form (or (eval (nth 1 form)) 1)))
- (1- form)
- (byte-compile-warn "Non-numeric arg to beginning-of-line: %s"
- form)
- (list '1- (list 'quote form))))
- t)
- (byte-compile-constant nil)))
-
-
-(byte-defop-compiler-1 setq)
-(byte-defop-compiler-1 setq-default)
-(byte-defop-compiler-1 quote)
-(byte-defop-compiler-1 quote-form)
-
-(defun byte-compile-setq (form)
- (let ((args (cdr form)))
- (if args
- (while args
- (byte-compile-form (car (cdr args)))
- (or for-effect (cdr (cdr args))
- (byte-compile-out 'byte-dup 0))
- (byte-compile-variable-ref 'byte-varset (car args))
- (setq args (cdr (cdr args))))
- ;; (setq), with no arguments.
- (byte-compile-form nil for-effect))
- (setq for-effect nil)))
-
-(defun byte-compile-setq-default (form)
- (let ((args (cdr form))
- setters)
- (while args
- (setq setters
- (cons (list 'set-default (list 'quote (car args)) (car (cdr args)))
- setters))
- (setq args (cdr (cdr args))))
- (byte-compile-form (cons 'progn (nreverse setters)))))
-
-(defun byte-compile-quote (form)
- (byte-compile-constant (car (cdr form))))
-
-(defun byte-compile-quote-form (form)
- (byte-compile-constant (byte-compile-top-level (nth 1 form))))
-
-
-;;; control structures
-
-(defun byte-compile-body (body &optional for-effect)
- (while (cdr body)
- (byte-compile-form (car body) t)
- (setq body (cdr body)))
- (byte-compile-form (car body) for-effect))
-
-(defsubst byte-compile-body-do-effect (body)
- (byte-compile-body body for-effect)
- (setq for-effect nil))
-
-(defsubst byte-compile-form-do-effect (form)
- (byte-compile-form form for-effect)
- (setq for-effect nil))
-
-(byte-defop-compiler-1 inline byte-compile-progn)
-(byte-defop-compiler-1 progn)
-(byte-defop-compiler-1 prog1)
-(byte-defop-compiler-1 prog2)
-(byte-defop-compiler-1 if)
-(byte-defop-compiler-1 cond)
-(byte-defop-compiler-1 and)
-(byte-defop-compiler-1 or)
-(byte-defop-compiler-1 while)
-(byte-defop-compiler-1 funcall)
-(byte-defop-compiler-1 apply byte-compile-funarg)
-(byte-defop-compiler-1 mapcar byte-compile-funarg)
-(byte-defop-compiler-1 mapatoms byte-compile-funarg)
-(byte-defop-compiler-1 mapconcat byte-compile-funarg)
-(byte-defop-compiler-1 sort byte-compile-funarg-2)
-(byte-defop-compiler-1 let)
-(byte-defop-compiler-1 let*)
-
-(defun byte-compile-progn (form)
- (byte-compile-body-do-effect (cdr form)))
-
-(defun byte-compile-prog1 (form)
- (byte-compile-form-do-effect (car (cdr form)))
- (byte-compile-body (cdr (cdr form)) t))
-
-(defun byte-compile-prog2 (form)
- (byte-compile-form (nth 1 form) t)
- (byte-compile-form-do-effect (nth 2 form))
- (byte-compile-body (cdr (cdr (cdr form))) t))
-
-(defmacro byte-compile-goto-if (cond discard tag)
- (` (byte-compile-goto
- (if (, cond)
- (if (, discard) 'byte-goto-if-not-nil 'byte-goto-if-not-nil-else-pop)
- (if (, discard) 'byte-goto-if-nil 'byte-goto-if-nil-else-pop))
- (, tag))))
-
-(defun byte-compile-if (form)
- (byte-compile-form (car (cdr form)))
- (if (null (nthcdr 3 form))
- ;; No else-forms
- (let ((donetag (byte-compile-make-tag)))
- (byte-compile-goto-if nil for-effect donetag)
- (byte-compile-form (nth 2 form) for-effect)
- (byte-compile-out-tag donetag))
- (let ((donetag (byte-compile-make-tag)) (elsetag (byte-compile-make-tag)))
- (byte-compile-goto 'byte-goto-if-nil elsetag)
- (byte-compile-form (nth 2 form) for-effect)
- (byte-compile-goto 'byte-goto donetag)
- (byte-compile-out-tag elsetag)
- (byte-compile-body (cdr (cdr (cdr form))) for-effect)
- (byte-compile-out-tag donetag)))
- (setq for-effect nil))
-
-(defun byte-compile-cond (clauses)
- (let ((donetag (byte-compile-make-tag))
- nexttag clause)
- (while (setq clauses (cdr clauses))
- (setq clause (car clauses))
- (cond ((or (eq (car clause) t)
- (and (eq (car-safe (car clause)) 'quote)
- (car-safe (cdr-safe (car clause)))))
- ;; Unconditional clause
- (setq clause (cons t clause)
- clauses nil))
- ((cdr clauses)
- (byte-compile-form (car clause))
- (if (null (cdr clause))
- ;; First clause is a singleton.
- (byte-compile-goto-if t for-effect donetag)
- (setq nexttag (byte-compile-make-tag))
- (byte-compile-goto 'byte-goto-if-nil nexttag)
- (byte-compile-body (cdr clause) for-effect)
- (byte-compile-goto 'byte-goto donetag)
- (byte-compile-out-tag nexttag)))))
- ;; Last clause
- (and (cdr clause) (not (eq (car clause) t))
- (progn (byte-compile-form (car clause))
- (byte-compile-goto-if nil for-effect donetag)
- (setq clause (cdr clause))))
- (byte-compile-body-do-effect clause)
- (byte-compile-out-tag donetag)))
-
-(defun byte-compile-and (form)
- (let ((failtag (byte-compile-make-tag))
- (args (cdr form)))
- (if (null args)
- (byte-compile-form-do-effect t)
- (while (cdr args)
- (byte-compile-form (car args))
- (byte-compile-goto-if nil for-effect failtag)
- (setq args (cdr args)))
- (byte-compile-form-do-effect (car args))
- (byte-compile-out-tag failtag))))
-
-(defun byte-compile-or (form)
- (let ((wintag (byte-compile-make-tag))
- (args (cdr form)))
- (if (null args)
- (byte-compile-form-do-effect nil)
- (while (cdr args)
- (byte-compile-form (car args))
- (byte-compile-goto-if t for-effect wintag)
- (setq args (cdr args)))
- (byte-compile-form-do-effect (car args))
- (byte-compile-out-tag wintag))))
-
-(defun byte-compile-while (form)
- (let ((endtag (byte-compile-make-tag))
- (looptag (byte-compile-make-tag)))
- (byte-compile-out-tag looptag)
- (byte-compile-form (car (cdr form)))
- (byte-compile-goto-if nil for-effect endtag)
- (byte-compile-body (cdr (cdr form)) t)
- (byte-compile-goto 'byte-goto looptag)
- (byte-compile-out-tag endtag)
- (setq for-effect nil)))
-
-(defun byte-compile-funcall (form)
- (mapcar 'byte-compile-form (cdr form))
- (byte-compile-out 'byte-call (length (cdr (cdr form)))))
-
-
-(defun byte-compile-let (form)
- ;; First compute the binding values in the old scope.
- (let ((varlist (car (cdr form))))
- (while varlist
- (if (consp (car varlist))
- (byte-compile-form (car (cdr (car varlist))))
- (byte-compile-push-constant nil))
- (setq varlist (cdr varlist))))
- (let ((byte-compile-bound-variables byte-compile-bound-variables) ;new scope
- (varlist (reverse (car (cdr form)))))
- (while varlist
- (byte-compile-variable-ref 'byte-varbind (if (consp (car varlist))
- (car (car varlist))
- (car varlist)))
- (setq varlist (cdr varlist)))
- (byte-compile-body-do-effect (cdr (cdr form)))
- (byte-compile-out 'byte-unbind (length (car (cdr form))))))
-
-(defun byte-compile-let* (form)
- (let ((byte-compile-bound-variables byte-compile-bound-variables) ;new scope
- (varlist (copy-sequence (car (cdr form)))))
- (while varlist
- (if (atom (car varlist))
- (byte-compile-push-constant nil)
- (byte-compile-form (car (cdr (car varlist))))
- (setcar varlist (car (car varlist))))
- (byte-compile-variable-ref 'byte-varbind (car varlist))
- (setq varlist (cdr varlist)))
- (byte-compile-body-do-effect (cdr (cdr form)))
- (byte-compile-out 'byte-unbind (length (car (cdr form))))))
-
-
-(byte-defop-compiler-1 /= byte-compile-negated)
-(byte-defop-compiler-1 atom byte-compile-negated)
-(byte-defop-compiler-1 nlistp byte-compile-negated)
-
-(put '/= 'byte-compile-negated-op '=)
-(put 'atom 'byte-compile-negated-op 'consp)
-(put 'nlistp 'byte-compile-negated-op 'listp)
-
-(defun byte-compile-negated (form)
- (byte-compile-form-do-effect (byte-compile-negation-optimizer form)))
-
-;; Even when optimization is off, /= is optimized to (not (= ...)).
-(defun byte-compile-negation-optimizer (form)
- ;; an optimizer for forms where <form1> is less efficient than (not <form2>)
- (list 'not
- (cons (or (get (car form) 'byte-compile-negated-op)
- (error
- "Compiler error: `%s' has no `byte-compile-negated-op' property"
- (car form)))
- (cdr form))))
-
-;;; other tricky macro-like special-forms
-
-(byte-defop-compiler-1 catch)
-(byte-defop-compiler-1 unwind-protect)
-(byte-defop-compiler-1 condition-case)
-(byte-defop-compiler-1 save-excursion)
-(byte-defop-compiler-1 save-current-buffer)
-(byte-defop-compiler-1 save-restriction)
-(byte-defop-compiler-1 save-window-excursion)
-(byte-defop-compiler-1 with-output-to-temp-buffer)
-(byte-defop-compiler-1 track-mouse)
-
-(defun byte-compile-catch (form)
- (byte-compile-form (car (cdr form)))
- (byte-compile-push-constant
- (byte-compile-top-level (cons 'progn (cdr (cdr form))) for-effect))
- (byte-compile-out 'byte-catch 0))
-
-(defun byte-compile-unwind-protect (form)
- (byte-compile-push-constant
- (byte-compile-top-level-body (cdr (cdr form)) t))
- (byte-compile-out 'byte-unwind-protect 0)
- (byte-compile-form-do-effect (car (cdr form)))
- (byte-compile-out 'byte-unbind 1))
-
-(defun byte-compile-track-mouse (form)
- (byte-compile-form
- (list
- 'funcall
- (list 'quote
- (list 'lambda nil
- (cons 'track-mouse
- (byte-compile-top-level-body (cdr form))))))))
-
-(defun byte-compile-condition-case (form)
- (let* ((var (nth 1 form))
- (byte-compile-bound-variables
- (if var (cons var byte-compile-bound-variables)
- byte-compile-bound-variables)))
- (or (symbolp var)
- (byte-compile-warn
- "%s is not a variable-name or nil (in condition-case)" var))
- (byte-compile-push-constant var)
- (byte-compile-push-constant (byte-compile-top-level
- (nth 2 form) for-effect))
- (let ((clauses (cdr (cdr (cdr form))))
- compiled-clauses)
- (while clauses
- (let* ((clause (car clauses))
- (condition (car clause)))
- (cond ((not (or (symbolp condition)
- (and (listp condition)
- (let ((syms condition) (ok t))
- (while syms
- (if (not (symbolp (car syms)))
- (setq ok nil))
- (setq syms (cdr syms)))
- ok))))
- (byte-compile-warn
- "%s is not a condition name or list of such (in condition-case)"
- (prin1-to-string condition)))
-;; ((not (or (eq condition 't)
-;; (and (stringp (get condition 'error-message))
-;; (consp (get condition 'error-conditions)))))
-;; (byte-compile-warn
-;; "%s is not a known condition name (in condition-case)"
-;; condition))
- )
- (setq compiled-clauses
- (cons (cons condition
- (byte-compile-top-level-body
- (cdr clause) for-effect))
- compiled-clauses)))
- (setq clauses (cdr clauses)))
- (byte-compile-push-constant (nreverse compiled-clauses)))
- (byte-compile-out 'byte-condition-case 0)))
-
-
-(defun byte-compile-save-excursion (form)
- (byte-compile-out 'byte-save-excursion 0)
- (byte-compile-body-do-effect (cdr form))
- (byte-compile-out 'byte-unbind 1))
-
-(defun byte-compile-save-restriction (form)
- (byte-compile-out 'byte-save-restriction 0)
- (byte-compile-body-do-effect (cdr form))
- (byte-compile-out 'byte-unbind 1))
-
-(defun byte-compile-save-current-buffer (form)
- (byte-compile-out 'byte-save-current-buffer 0)
- (byte-compile-body-do-effect (cdr form))
- (byte-compile-out 'byte-unbind 1))
-
-(defun byte-compile-save-window-excursion (form)
- (byte-compile-push-constant
- (byte-compile-top-level-body (cdr form) for-effect))
- (byte-compile-out 'byte-save-window-excursion 0))
-
-(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))
-
-
-;;; top-level forms elsewhere
-
-(byte-defop-compiler-1 defun)
-(byte-defop-compiler-1 defmacro)
-(byte-defop-compiler-1 defvar)
-(byte-defop-compiler-1 defconst byte-compile-defvar)
-(byte-defop-compiler-1 autoload)
-(byte-defop-compiler-1 lambda byte-compile-lambda-form)
-(byte-defop-compiler-1 defalias)
-
-(defun byte-compile-defun (form)
- ;; This is not used for file-level defuns with doc strings.
- (byte-compile-two-args ; Use this to avoid byte-compile-fset's warning.
- (list 'fset (list 'quote (nth 1 form))
- (byte-compile-byte-code-maker
- (byte-compile-lambda (cons 'lambda (cdr (cdr form)))))))
- (byte-compile-discard)
- (byte-compile-constant (nth 1 form)))
-
-(defun byte-compile-defmacro (form)
- ;; This is not used for file-level defmacros with doc strings.
- (byte-compile-body-do-effect
- (list (list 'fset (list 'quote (nth 1 form))
- (let ((code (byte-compile-byte-code-maker
- (byte-compile-lambda
- (cons 'lambda (cdr (cdr form)))))))
- (if (eq (car-safe code) 'make-byte-code)
- (list 'cons ''macro code)
- (list 'quote (cons 'macro (eval code))))))
- (list 'quote (nth 1 form)))))
-
-(defun byte-compile-defvar (form)
- ;; This is not used for file-level defvar/consts with doc strings.
- (let ((var (nth 1 form))
- (value (nth 2 form))
- (string (nth 3 form)))
- (if (memq 'free-vars byte-compile-warnings)
- (setq byte-compile-bound-variables
- (cons var byte-compile-bound-variables)))
- (byte-compile-body-do-effect
- (list (if (cdr (cdr form))
- (if (eq (car form) 'defconst)
- (list 'setq var value)
- (list 'or (list 'boundp (list 'quote var))
- (list 'setq var value))))
- ;; Put the defined variable in this library's load-history entry
- ;; just as a real defvar would.
- (list 'setq 'current-load-list
- (list 'cons (list 'quote var)
- 'current-load-list))
- (if string
- (list 'put (list 'quote var) ''variable-documentation string))
- (list 'quote var)))))
-
-(defun byte-compile-autoload (form)
- (and (byte-compile-constp (nth 1 form))
- (byte-compile-constp (nth 5 form))
- (eval (nth 5 form)) ; macro-p
- (not (fboundp (eval (nth 1 form))))
- (byte-compile-warn
- "The compiler ignores `autoload' except at top level. You should
- probably put the autoload of the macro `%s' at top-level."
- (eval (nth 1 form))))
- (byte-compile-normal-call form))
-
-;; Lambda's in valid places are handled as special cases by various code.
-;; The ones that remain are errors.
-(defun byte-compile-lambda-form (form)
- (error "`lambda' used as function name is invalid"))
-
-;; Compile normally, but deal with warnings for the function being defined.
-(defun byte-compile-defalias (form)
- (if (and (consp (cdr form)) (consp (nth 1 form))
- (eq (car (nth 1 form)) 'quote)
- (consp (cdr (nth 1 form)))
- (symbolp (nth 1 (nth 1 form)))
- (consp (nthcdr 2 form))
- (consp (nth 2 form))
- (eq (car (nth 2 form)) 'quote)
- (consp (cdr (nth 2 form)))
- (symbolp (nth 1 (nth 2 form))))
- (progn
- (byte-compile-defalias-warn (nth 1 (nth 1 form))
- (nth 1 (nth 2 form)))
- (setq byte-compile-function-environment
- (cons (cons (nth 1 (nth 1 form))
- (nth 1 (nth 2 form)))
- byte-compile-function-environment))))
- (byte-compile-normal-call form))
-
-;; Turn off warnings about prior calls to the function being defalias'd.
-;; This could be smarter and compare those calls with
-;; the function it is being aliased to.
-(defun byte-compile-defalias-warn (new alias)
- (let ((calls (assq new byte-compile-unresolved-functions)))
- (if calls
- (setq byte-compile-unresolved-functions
- (delq calls byte-compile-unresolved-functions)))))
-
-;;; tags
-
-;; Note: Most operations will strip off the 'TAG, but it speeds up
-;; optimization to have the 'TAG as a part of the tag.
-;; Tags will be (TAG . (tag-number . stack-depth)).
-(defun byte-compile-make-tag ()
- (list 'TAG (setq byte-compile-tag-number (1+ byte-compile-tag-number))))
-
-
-(defun byte-compile-out-tag (tag)
- (setq byte-compile-output (cons tag byte-compile-output))
- (if (cdr (cdr tag))
- (progn
- ;; ## remove this someday
- (and byte-compile-depth
- (not (= (cdr (cdr tag)) byte-compile-depth))
- (error "Compiler bug: depth conflict at tag %d" (car (cdr tag))))
- (setq byte-compile-depth (cdr (cdr tag))))
- (setcdr (cdr tag) byte-compile-depth)))
-
-(defun byte-compile-goto (opcode tag)
- (setq byte-compile-output (cons (cons opcode tag) byte-compile-output))
- (setcdr (cdr tag) (if (memq opcode byte-goto-always-pop-ops)
- (1- byte-compile-depth)
- byte-compile-depth))
- (setq byte-compile-depth (and (not (eq opcode 'byte-goto))
- (1- byte-compile-depth))))
-
-(defun byte-compile-out (opcode offset)
- (setq byte-compile-output (cons (cons opcode offset) byte-compile-output))
- (cond ((eq opcode 'byte-call)
- (setq byte-compile-depth (- byte-compile-depth offset)))
- ((eq opcode 'byte-return)
- ;; This is actually an unnecessary case, because there should be
- ;; no more opcodes behind byte-return.
- (setq byte-compile-depth nil))
- (t
- (setq byte-compile-depth (+ byte-compile-depth
- (or (aref byte-stack+-info
- (symbol-value opcode))
- (- (1- offset))))
- byte-compile-maxdepth (max byte-compile-depth
- byte-compile-maxdepth))))
- ;;(if (< byte-compile-depth 0) (error "Compiler error: stack underflow"))
- )
-
-
-;;; call tree stuff
-
-(defun byte-compile-annotate-call-tree (form)
- (let (entry)
- ;; annotate the current call
- (if (setq entry (assq (car form) byte-compile-call-tree))
- (or (memq byte-compile-current-form (nth 1 entry)) ;callers
- (setcar (cdr entry)
- (cons byte-compile-current-form (nth 1 entry))))
- (setq byte-compile-call-tree
- (cons (list (car form) (list byte-compile-current-form) nil)
- byte-compile-call-tree)))
- ;; annotate the current function
- (if (setq entry (assq byte-compile-current-form byte-compile-call-tree))
- (or (memq (car form) (nth 2 entry)) ;called
- (setcar (cdr (cdr entry))
- (cons (car form) (nth 2 entry))))
- (setq byte-compile-call-tree
- (cons (list byte-compile-current-form nil (list (car form)))
- byte-compile-call-tree)))
- ))
-
-;; Renamed from byte-compile-report-call-tree
-;; to avoid interfering with completion of byte-compile-file.
-;;;###autoload
-(defun display-call-tree (&optional filename)
- "Display a call graph of a specified file.
-This lists which functions have been called, what functions called
-them, and what functions they call. The list includes all functions
-whose definitions have been compiled in this Emacs session, as well as
-all functions called by those functions.
-
-The call graph does not include macros, inline functions, or
-primitives that the byte-code interpreter knows about directly \(eq,
-cons, etc.\).
-
-The call tree also lists those functions which are not known to be called
-\(that is, to which no calls have been compiled\), and which cannot be
-invoked interactively."
- (interactive)
- (message "Generating call tree...")
- (with-output-to-temp-buffer "*Call-Tree*"
- (set-buffer "*Call-Tree*")
- (erase-buffer)
- (message "Generating call tree... (sorting on %s)"
- byte-compile-call-tree-sort)
- (insert "Call tree for "
- (cond ((null byte-compile-current-file) (or filename "???"))
- ((stringp byte-compile-current-file)
- byte-compile-current-file)
- (t (buffer-name byte-compile-current-file)))
- " sorted on "
- (prin1-to-string byte-compile-call-tree-sort)
- ":\n\n")
- (if byte-compile-call-tree-sort
- (setq byte-compile-call-tree
- (sort byte-compile-call-tree
- (cond ((eq byte-compile-call-tree-sort 'callers)
- (function (lambda (x y) (< (length (nth 1 x))
- (length (nth 1 y))))))
- ((eq byte-compile-call-tree-sort 'calls)
- (function (lambda (x y) (< (length (nth 2 x))
- (length (nth 2 y))))))
- ((eq byte-compile-call-tree-sort 'calls+callers)
- (function (lambda (x y) (< (+ (length (nth 1 x))
- (length (nth 2 x)))
- (+ (length (nth 1 y))
- (length (nth 2 y)))))))
- ((eq byte-compile-call-tree-sort 'name)
- (function (lambda (x y) (string< (car x)
- (car y)))))
- (t (error "`byte-compile-call-tree-sort': `%s' - unknown sort mode"
- byte-compile-call-tree-sort))))))
- (message "Generating call tree...")
- (let ((rest byte-compile-call-tree)
- (b (current-buffer))
- f p
- callers calls)
- (while rest
- (prin1 (car (car rest)) b)
- (setq callers (nth 1 (car rest))
- calls (nth 2 (car rest)))
- (insert "\t"
- (cond ((not (fboundp (setq f (car (car rest)))))
- (if (null f)
- " <top level>";; shouldn't insert nil then, actually -sk
- " <not defined>"))
- ((subrp (setq f (symbol-function f)))
- " <subr>")
- ((symbolp f)
- (format " ==> %s" f))
- ((byte-code-function-p f)
- "<compiled function>")
- ((not (consp f))
- "<malformed function>")
- ((eq 'macro (car f))
- (if (or (byte-code-function-p (cdr f))
- (assq 'byte-code (cdr (cdr (cdr f)))))
- " <compiled macro>"
- " <macro>"))
- ((assq 'byte-code (cdr (cdr f)))
- "<compiled lambda>")
- ((eq 'lambda (car f))
- "<function>")
- (t "???"))
- (format " (%d callers + %d calls = %d)"
- ;; Does the optimizer eliminate common subexpressions?-sk
- (length callers)
- (length calls)
- (+ (length callers) (length calls)))
- "\n")
- (if callers
- (progn
- (insert " called by:\n")
- (setq p (point))
- (insert " " (if (car callers)
- (mapconcat 'symbol-name callers ", ")
- "<top level>"))
- (let ((fill-prefix " "))
- (fill-region-as-paragraph p (point)))))
- (if calls
- (progn
- (insert " calls:\n")
- (setq p (point))
- (insert " " (mapconcat 'symbol-name calls ", "))
- (let ((fill-prefix " "))
- (fill-region-as-paragraph p (point)))))
- (insert "\n")
- (setq rest (cdr rest)))
-
- (message "Generating call tree...(finding uncalled functions...)")
- (setq rest byte-compile-call-tree)
- (let ((uncalled nil))
- (while rest
- (or (nth 1 (car rest))
- (null (setq f (car (car rest))))
- (byte-compile-fdefinition f t)
- (commandp (byte-compile-fdefinition f nil))
- (setq uncalled (cons f uncalled)))
- (setq rest (cdr rest)))
- (if uncalled
- (let ((fill-prefix " "))
- (insert "Noninteractive functions not known to be called:\n ")
- (setq p (point))
- (insert (mapconcat 'symbol-name (nreverse uncalled) ", "))
- (fill-region-as-paragraph p (point)))))
- )
- (message "Generating call tree...done.")
- ))
-
-
-;;; by crl@newton.purdue.edu
-;;; Only works noninteractively.
-;;;###autoload
-(defun batch-byte-compile ()
- "Run `byte-compile-file' on the files remaining on the command line.
-Use this from the command line, with `-batch';
-it won't work in an interactive Emacs.
-Each file is 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)
- (defvar command-line-args-left) ;Avoid 'free variable' warning
- (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 emacs-lisp-file-regexp (car files))
- (not (auto-save-file-name-p (car files)))
- (setq source (expand-file-name (car files)
- (car command-line-args-left)))
- (setq dest (byte-compile-dest-file source))
- (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)))
-
-;;;###autoload
-(defun batch-byte-recompile-directory ()
- "Runs `byte-recompile-directory' on the dirs remaining on the command line.
-Must be used only with `-batch', and kills Emacs on completion.
-For example, invoke `emacs -batch -f batch-byte-recompile-directory .'."
- ;; command-line-args-left is what is left of the command line (startup.el)
- (defvar command-line-args-left) ;Avoid 'free variable' warning
- (if (not noninteractive)
- (error "batch-byte-recompile-directory is to be used only with -batch"))
- (or command-line-args-left
- (setq command-line-args-left '(".")))
- (while command-line-args-left
- (byte-recompile-directory (car command-line-args-left))
- (setq command-line-args-left (cdr command-line-args-left)))
- (kill-emacs 0))
-
-
-(make-obsolete 'dot 'point)
-(make-obsolete 'dot-max 'point-max)
-(make-obsolete 'dot-min 'point-min)
-(make-obsolete 'dot-marker 'point-marker)
-
-(make-obsolete 'buffer-flush-undo 'buffer-disable-undo)
-(make-obsolete 'baud-rate "use the baud-rate variable instead")
-(make-obsolete 'compiled-function-p 'byte-code-function-p)
-(make-obsolete 'define-function 'defalias)
-(make-obsolete-variable 'auto-fill-hook 'auto-fill-function)
-(make-obsolete-variable 'blink-paren-hook 'blink-paren-function)
-(make-obsolete-variable 'lisp-indent-hook 'lisp-indent-function)
-(make-obsolete-variable 'temp-buffer-show-hook
- 'temp-buffer-show-function)
-(make-obsolete-variable 'inhibit-local-variables
- "use enable-local-variables (with the reversed sense).")
-(make-obsolete-variable 'unread-command-char
- "use unread-command-events instead. That variable is a list of events to reread, so it now uses nil to mean `no event', instead of -1.")
-(make-obsolete-variable 'unread-command-event
- "use unread-command-events; which is a list of events rather than a single event.")
-(make-obsolete-variable 'suspend-hooks 'suspend-hook)
-(make-obsolete-variable 'comment-indent-hook 'comment-indent-function)
-(make-obsolete-variable 'meta-flag "Use the set-input-mode function instead.")
-(make-obsolete-variable 'executing-macro 'executing-kbd-macro)
-(make-obsolete-variable 'before-change-function
- "use before-change-functions; which is a list of functions rather than a single function.")
-(make-obsolete-variable 'after-change-function
- "use after-change-functions; which is a list of functions rather than a single function.")
-(make-obsolete-variable 'font-lock-doc-string-face 'font-lock-string-face)
-(make-obsolete-variable 'post-command-idle-hook
- "use timers instead, with `run-with-idle-timer'.")
-(make-obsolete-variable 'post-command-idle-delay
- "use timers instead, with `run-with-idle-timer'.")
-
-(provide 'byte-compile)
-(provide 'bytecomp)
-
-
-;;; report metering (see the hacks in bytecode.c)
-
-(defun byte-compile-report-ops ()
- (defvar byte-code-meter)
- (with-output-to-temp-buffer "*Meter*"
- (set-buffer "*Meter*")
- (let ((i 0) n op off)
- (while (< i 256)
- (setq n (aref (aref byte-code-meter 0) i)
- off nil)
- (if t ;(not (zerop n))
- (progn
- (setq op i)
- (setq off nil)
- (cond ((< op byte-nth)
- (setq off (logand op 7))
- (setq op (logand op 248)))
- ((>= op byte-constant)
- (setq off (- op byte-constant)
- op byte-constant)))
- (setq op (aref byte-code-vector op))
- (insert (format "%-4d" i))
- (insert (symbol-name op))
- (if off (insert " [" (int-to-string off) "]"))
- (indent-to 40)
- (insert (int-to-string n) "\n")))
- (setq i (1+ i))))))
-
-;; To avoid "lisp nesting exceeds max-lisp-eval-depth" when bytecomp compiles
-;; itself, compile some of its most used recursive functions (at load time).
-;;
-(eval-when-compile
- (or (byte-code-function-p (symbol-function 'byte-compile-form))
- (assq 'byte-code (symbol-function 'byte-compile-form))
- (let ((byte-optimize nil) ; do it fast
- (byte-compile-warnings nil))
- (mapcar '(lambda (x)
- (or noninteractive (message "compiling %s..." x))
- (byte-compile x)
- (or noninteractive (message "compiling %s...done" x)))
- '(byte-compile-normal-call
- byte-compile-form
- byte-compile-body
- ;; Inserted some more than necessary, to speed it up.
- byte-compile-top-level
- byte-compile-out-toplevel
- byte-compile-constant
- byte-compile-variable-ref))))
- nil)
-
-;;; bytecomp.el ends here
diff --git a/lisp/emacs-lisp/cl-compat.el b/lisp/emacs-lisp/cl-compat.el
deleted file mode 100644
index 7d5b6492edf..00000000000
--- a/lisp/emacs-lisp/cl-compat.el
+++ /dev/null
@@ -1,192 +0,0 @@
-;;; cl-compat.el --- Common Lisp extensions for GNU Emacs Lisp (compatibility)
-
-;; Copyright (C) 1993 Free Software Foundation, Inc.
-
-;; Author: Dave Gillespie <daveg@synaptics.com>
-;; Version: 2.02
-;; Keywords: extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; These are extensions to Emacs Lisp that provide a degree of
-;; Common Lisp compatibility, beyond what is already built-in
-;; in Emacs Lisp.
-;;
-;; This package was written by Dave Gillespie; it is a complete
-;; rewrite of Cesar Quiroz's original cl.el package of December 1986.
-;;
-;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19.
-;;
-;; Bug reports, comments, and suggestions are welcome!
-
-;; This file contains emulations of internal routines of the older
-;; CL package which users may have called directly from their code.
-;; Use (require 'cl-compat) to get these routines.
-
-;; See cl.el for Change Log.
-
-
-;;; Code:
-
-;; Require at load-time, but not when compiling cl-compat.
-(or (featurep 'cl) (require 'cl))
-
-
-;;; Keyword routines not supported by new package.
-
-(defmacro defkeyword (x &optional doc)
- (list* 'defconst x (list 'quote x) (and doc (list doc))))
-
-(defun keywordp (sym)
- (and (symbolp sym) (eq (aref (symbol-name sym) 0) ?\:) (set sym sym)))
-
-(defun keyword-of (sym)
- (or (keywordp sym) (keywordp (intern (format ":%s" sym)))))
-
-
-;;; Multiple values. Note that the new package uses a different
-;;; convention for multiple values. The following definitions
-;;; emulate the old convention; all function names have been changed
-;;; by capitalizing the first letter: Values, Multiple-value-*,
-;;; to avoid conflict with the new-style definitions in cl-macs.
-
-(put 'Multiple-value-bind 'lisp-indent-function 2)
-(put 'Multiple-value-setq 'lisp-indent-function 2)
-(put 'Multiple-value-call 'lisp-indent-function 1)
-(put 'Multiple-value-prog1 'lisp-indent-function 1)
-
-(defvar *mvalues-values* nil)
-
-(defun Values (&rest val-forms)
- (setq *mvalues-values* val-forms)
- (car val-forms))
-
-(defun Values-list (val-forms)
- (apply 'values val-forms))
-
-(defmacro Multiple-value-list (form)
- (list 'let* (list '(*mvalues-values* nil) (list '*mvalues-temp* form))
- '(or (and (eq *mvalues-temp* (car *mvalues-values*)) *mvalues-values*)
- (list *mvalues-temp*))))
-
-(defmacro Multiple-value-call (function &rest args)
- (list 'apply function
- (cons 'append
- (mapcar (function (lambda (x) (list 'Multiple-value-list x)))
- args))))
-
-(defmacro Multiple-value-bind (vars form &rest body)
- (list* 'multiple-value-bind vars (list 'Multiple-value-list form) body))
-
-(defmacro Multiple-value-setq (vars form)
- (list 'multiple-value-setq vars (list 'Multiple-value-list form)))
-
-(defmacro Multiple-value-prog1 (form &rest body)
- (list 'prog1 form (list* 'let '((*mvalues-values* nil)) body)))
-
-
-;;; Routines for parsing keyword arguments.
-
-(defun build-klist (arglist keys &optional allow-others)
- (let ((res (Multiple-value-call 'mapcar* 'cons (unzip-lists arglist))))
- (or allow-others
- (let ((bad (set-difference (mapcar 'car res) keys)))
- (if bad (error "Bad keywords: %s not in %s" bad keys))))
- res))
-
-(defun extract-from-klist (klist key &optional def)
- (let ((res (assq key klist))) (if res (cdr res) def)))
-
-(defun keyword-argument-supplied-p (klist key)
- (assq key klist))
-
-(defun elt-satisfies-test-p (item elt klist)
- (let ((test-not (cdr (assq ':test-not klist)))
- (test (cdr (assq ':test klist)))
- (key (cdr (assq ':key klist))))
- (if key (setq elt (funcall key elt)))
- (if test-not (not (funcall test-not item elt))
- (funcall (or test 'eql) item elt))))
-
-
-;;; Rounding functions with old-style multiple value returns.
-
-(defun cl-floor (a &optional b) (Values-list (floor* a b)))
-(defun cl-ceiling (a &optional b) (Values-list (ceiling* a b)))
-(defun cl-round (a &optional b) (Values-list (round* a b)))
-(defun cl-truncate (a &optional b) (Values-list (truncate* a b)))
-
-(defun safe-idiv (a b)
- (let* ((q (/ (abs a) (abs b)))
- (s (* (signum a) (signum b))))
- (Values q (- a (* s q b)) s)))
-
-
-;; Internal routines.
-
-(defun pair-with-newsyms (oldforms)
- (let ((newsyms (mapcar (function (lambda (x) (gensym))) oldforms)))
- (Values (mapcar* 'list newsyms oldforms) newsyms)))
-
-(defun zip-lists (evens odds)
- (mapcan 'list evens odds))
-
-(defun unzip-lists (list)
- (let ((e nil) (o nil))
- (while list
- (setq e (cons (car list) e) o (cons (cadr list) o) list (cddr list)))
- (Values (nreverse e) (nreverse o))))
-
-(defun reassemble-argslists (list)
- (let ((n (apply 'min (mapcar 'length list))) (res nil))
- (while (>= (setq n (1- n)) 0)
- (setq res (cons (mapcar (function (lambda (x) (elt x n))) list) res)))
- res))
-
-(defun duplicate-symbols-p (list)
- (let ((res nil))
- (while list
- (if (memq (car list) (cdr list)) (setq res (cons (car list) res)))
- (setq list (cdr list)))
- res))
-
-
-;;; Setf internals.
-
-(defun setnth (n list x)
- (setcar (nthcdr n list) x))
-
-(defun setnthcdr (n list x)
- (setcdr (nthcdr (1- n) list) x))
-
-(defun setelt (seq n x)
- (if (consp seq) (setcar (nthcdr n seq) x) (aset seq n x)))
-
-
-;;; Functions omitted: case-clausify, check-do-stepforms, check-do-endforms,
-;;; extract-do-inits, extract-do[*]-steps, select-stepping-forms,
-;;; elt-satisfies-if[-not]-p, with-keyword-args, mv-bind-clausify,
-;;; all names with embedded `$'.
-
-
-(provide 'cl-compat)
-
-;;; cl-compat.el ends here
-
diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el
deleted file mode 100644
index 2402d799108..00000000000
--- a/lisp/emacs-lisp/cl-extra.el
+++ /dev/null
@@ -1,924 +0,0 @@
-;;; cl-extra.el --- Common Lisp features, part 2 -*-byte-compile-dynamic: t;-*-
-
-;; Copyright (C) 1993 Free Software Foundation, Inc.
-
-;; Author: Dave Gillespie <daveg@synaptics.com>
-;; Version: 2.02
-;; Keywords: extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; These are extensions to Emacs Lisp that provide a degree of
-;; Common Lisp compatibility, beyond what is already built-in
-;; in Emacs Lisp.
-;;
-;; This package was written by Dave Gillespie; it is a complete
-;; rewrite of Cesar Quiroz's original cl.el package of December 1986.
-;;
-;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19.
-;;
-;; Bug reports, comments, and suggestions are welcome!
-
-;; This file contains portions of the Common Lisp extensions
-;; package which are autoloaded since they are relatively obscure.
-
-;; See cl.el for Change Log.
-
-
-;;; Code:
-
-(or (memq 'cl-19 features)
- (error "Tried to load `cl-extra' before `cl'!"))
-
-
-;;; We define these here so that this file can compile without having
-;;; loaded the cl.el file already.
-
-(defmacro cl-push (x place) (list 'setq place (list 'cons x place)))
-(defmacro cl-pop (place)
- (list 'car (list 'prog1 place (list 'setq place (list 'cdr place)))))
-
-(defvar cl-emacs-type)
-
-
-;;; Type coercion.
-
-(defun coerce (x type)
- "Coerce OBJECT to type TYPE.
-TYPE is a Common Lisp type specifier."
- (cond ((eq type 'list) (if (listp x) x (append x nil)))
- ((eq type 'vector) (if (vectorp x) x (vconcat x)))
- ((eq type 'string) (if (stringp x) x (concat x)))
- ((eq type 'array) (if (arrayp x) x (vconcat x)))
- ((and (eq type 'character) (stringp x) (= (length x) 1)) (aref x 0))
- ((and (eq type 'character) (symbolp x)) (coerce (symbol-name x) type))
- ((eq type 'float) (float x))
- ((typep x type) x)
- (t (error "Can't coerce %s to type %s" x type))))
-
-
-;;; Predicates.
-
-(defun equalp (x y)
- "T if two Lisp objects have similar structures and contents.
-This is like `equal', except that it accepts numerically equal
-numbers of different types (float vs. integer), and also compares
-strings case-insensitively."
- (cond ((eq x y) t)
- ((stringp x)
- (and (stringp y) (= (length x) (length y))
- (or (string-equal x y)
- (string-equal (downcase x) (downcase y))))) ; lazy but simple!
- ((numberp x)
- (and (numberp y) (= x y)))
- ((consp x)
- (while (and (consp x) (consp y) (equalp (car x) (car y)))
- (setq x (cdr x) y (cdr y)))
- (and (not (consp x)) (equalp x y)))
- ((vectorp x)
- (and (vectorp y) (= (length x) (length y))
- (let ((i (length x)))
- (while (and (>= (setq i (1- i)) 0)
- (equalp (aref x i) (aref y i))))
- (< i 0))))
- (t (equal x y))))
-
-
-;;; Control structures.
-
-(defun cl-mapcar-many (cl-func cl-seqs)
- (if (cdr (cdr cl-seqs))
- (let* ((cl-res nil)
- (cl-n (apply 'min (mapcar 'length cl-seqs)))
- (cl-i 0)
- (cl-args (copy-sequence cl-seqs))
- cl-p1 cl-p2)
- (setq cl-seqs (copy-sequence cl-seqs))
- (while (< cl-i cl-n)
- (setq cl-p1 cl-seqs cl-p2 cl-args)
- (while cl-p1
- (setcar cl-p2
- (if (consp (car cl-p1))
- (prog1 (car (car cl-p1))
- (setcar cl-p1 (cdr (car cl-p1))))
- (aref (car cl-p1) cl-i)))
- (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2)))
- (cl-push (apply cl-func cl-args) cl-res)
- (setq cl-i (1+ cl-i)))
- (nreverse cl-res))
- (let ((cl-res nil)
- (cl-x (car cl-seqs))
- (cl-y (nth 1 cl-seqs)))
- (let ((cl-n (min (length cl-x) (length cl-y)))
- (cl-i -1))
- (while (< (setq cl-i (1+ cl-i)) cl-n)
- (cl-push (funcall cl-func
- (if (consp cl-x) (cl-pop cl-x) (aref cl-x cl-i))
- (if (consp cl-y) (cl-pop cl-y) (aref cl-y cl-i)))
- cl-res)))
- (nreverse cl-res))))
-
-(defun map (cl-type cl-func cl-seq &rest cl-rest)
- "Map a function across one or more sequences, returning a sequence.
-TYPE is the sequence type to return, FUNC is the function, and SEQS
-are the argument sequences."
- (let ((cl-res (apply 'mapcar* cl-func cl-seq cl-rest)))
- (and cl-type (coerce cl-res cl-type))))
-
-(defun maplist (cl-func cl-list &rest cl-rest)
- "Map FUNC to each sublist of LIST or LISTS.
-Like `mapcar', except applies to lists and their cdr's rather than to
-the elements themselves."
- (if cl-rest
- (let ((cl-res nil)
- (cl-args (cons cl-list (copy-sequence cl-rest)))
- cl-p)
- (while (not (memq nil cl-args))
- (cl-push (apply cl-func cl-args) cl-res)
- (setq cl-p cl-args)
- (while cl-p (setcar cl-p (cdr (cl-pop cl-p)) )))
- (nreverse cl-res))
- (let ((cl-res nil))
- (while cl-list
- (cl-push (funcall cl-func cl-list) cl-res)
- (setq cl-list (cdr cl-list)))
- (nreverse cl-res))))
-
-(defun mapc (cl-func cl-seq &rest cl-rest)
- "Like `mapcar', but does not accumulate values returned by the function."
- (if cl-rest
- (apply 'map nil cl-func cl-seq cl-rest)
- (mapcar cl-func cl-seq))
- cl-seq)
-
-(defun mapl (cl-func cl-list &rest cl-rest)
- "Like `maplist', but does not accumulate values returned by the function."
- (if cl-rest
- (apply 'maplist cl-func cl-list cl-rest)
- (let ((cl-p cl-list))
- (while cl-p (funcall cl-func cl-p) (setq cl-p (cdr cl-p)))))
- cl-list)
-
-(defun mapcan (cl-func cl-seq &rest cl-rest)
- "Like `mapcar', but nconc's together the values returned by the function."
- (apply 'nconc (apply 'mapcar* cl-func cl-seq cl-rest)))
-
-(defun mapcon (cl-func cl-list &rest cl-rest)
- "Like `maplist', but nconc's together the values returned by the function."
- (apply 'nconc (apply 'maplist cl-func cl-list cl-rest)))
-
-(defun some (cl-pred cl-seq &rest cl-rest)
- "Return true if PREDICATE is true of any element of SEQ or SEQs.
-If so, return the true (non-nil) value returned by PREDICATE."
- (if (or cl-rest (nlistp cl-seq))
- (catch 'cl-some
- (apply 'map nil
- (function (lambda (&rest cl-x)
- (let ((cl-res (apply cl-pred cl-x)))
- (if cl-res (throw 'cl-some cl-res)))))
- cl-seq cl-rest) nil)
- (let ((cl-x nil))
- (while (and cl-seq (not (setq cl-x (funcall cl-pred (cl-pop cl-seq))))))
- cl-x)))
-
-(defun every (cl-pred cl-seq &rest cl-rest)
- "Return true if PREDICATE is true of every element of SEQ or SEQs."
- (if (or cl-rest (nlistp cl-seq))
- (catch 'cl-every
- (apply 'map nil
- (function (lambda (&rest cl-x)
- (or (apply cl-pred cl-x) (throw 'cl-every nil))))
- cl-seq cl-rest) t)
- (while (and cl-seq (funcall cl-pred (car cl-seq)))
- (setq cl-seq (cdr cl-seq)))
- (null cl-seq)))
-
-(defun notany (cl-pred cl-seq &rest cl-rest)
- "Return true if PREDICATE is false of every element of SEQ or SEQs."
- (not (apply 'some cl-pred cl-seq cl-rest)))
-
-(defun notevery (cl-pred cl-seq &rest cl-rest)
- "Return true if PREDICATE is false of some element of SEQ or SEQs."
- (not (apply 'every cl-pred cl-seq cl-rest)))
-
-;;; Support for `loop'.
-(defun cl-map-keymap (cl-func cl-map)
- (while (symbolp cl-map) (setq cl-map (symbol-function cl-map)))
- (if (eq cl-emacs-type 'lucid) (funcall 'map-keymap cl-func cl-map)
- (if (listp cl-map)
- (let ((cl-p cl-map))
- (while (consp (setq cl-p (cdr cl-p)))
- (cond ((consp (car cl-p))
- (funcall cl-func (car (car cl-p)) (cdr (car cl-p))))
- ((vectorp (car cl-p))
- (cl-map-keymap cl-func (car cl-p)))
- ((eq (car cl-p) 'keymap)
- (setq cl-p nil)))))
- (let ((cl-i -1))
- (while (< (setq cl-i (1+ cl-i)) (length cl-map))
- (if (aref cl-map cl-i)
- (funcall cl-func cl-i (aref cl-map cl-i))))))))
-
-(defun cl-map-keymap-recursively (cl-func-rec cl-map &optional cl-base)
- (or cl-base
- (setq cl-base (copy-sequence (if (eq cl-emacs-type 18) "0" [0]))))
- (cl-map-keymap
- (function
- (lambda (cl-key cl-bind)
- (aset cl-base (1- (length cl-base)) cl-key)
- (if (keymapp cl-bind)
- (cl-map-keymap-recursively
- cl-func-rec cl-bind
- (funcall (if (eq cl-emacs-type 18) 'concat 'vconcat)
- cl-base (list 0)))
- (funcall cl-func-rec cl-base cl-bind))))
- cl-map))
-
-(defun cl-map-intervals (cl-func &optional cl-what cl-prop cl-start cl-end)
- (or cl-what (setq cl-what (current-buffer)))
- (if (bufferp cl-what)
- (let (cl-mark cl-mark2 (cl-next t) cl-next2)
- (save-excursion
- (set-buffer cl-what)
- (setq cl-mark (copy-marker (or cl-start (point-min))))
- (setq cl-mark2 (and cl-end (copy-marker cl-end))))
- (while (and cl-next (or (not cl-mark2) (< cl-mark cl-mark2)))
- (setq cl-next (and (fboundp 'next-property-change)
- (if cl-prop (next-single-property-change
- cl-mark cl-prop cl-what)
- (next-property-change cl-mark cl-what)))
- cl-next2 (or cl-next (save-excursion
- (set-buffer cl-what) (point-max))))
- (funcall cl-func (prog1 (marker-position cl-mark)
- (set-marker cl-mark cl-next2))
- (if cl-mark2 (min cl-next2 cl-mark2) cl-next2)))
- (set-marker cl-mark nil) (if cl-mark2 (set-marker cl-mark2 nil)))
- (or cl-start (setq cl-start 0))
- (or cl-end (setq cl-end (length cl-what)))
- (while (< cl-start cl-end)
- (let ((cl-next (or (and (fboundp 'next-property-change)
- (if cl-prop (next-single-property-change
- cl-start cl-prop cl-what)
- (next-property-change cl-start cl-what)))
- cl-end)))
- (funcall cl-func cl-start (min cl-next cl-end))
- (setq cl-start cl-next)))))
-
-(defun cl-map-overlays (cl-func &optional cl-buffer cl-start cl-end cl-arg)
- (or cl-buffer (setq cl-buffer (current-buffer)))
- (if (fboundp 'overlay-lists)
-
- ;; This is the preferred algorithm, though overlay-lists is undocumented.
- (let (cl-ovl)
- (save-excursion
- (set-buffer cl-buffer)
- (setq cl-ovl (overlay-lists))
- (if cl-start (setq cl-start (copy-marker cl-start)))
- (if cl-end (setq cl-end (copy-marker cl-end))))
- (setq cl-ovl (nconc (car cl-ovl) (cdr cl-ovl)))
- (while (and cl-ovl
- (or (not (overlay-start (car cl-ovl)))
- (and cl-end (>= (overlay-start (car cl-ovl)) cl-end))
- (and cl-start (<= (overlay-end (car cl-ovl)) cl-start))
- (not (funcall cl-func (car cl-ovl) cl-arg))))
- (setq cl-ovl (cdr cl-ovl)))
- (if cl-start (set-marker cl-start nil))
- (if cl-end (set-marker cl-end nil)))
-
- ;; This alternate algorithm fails to find zero-length overlays.
- (let ((cl-mark (save-excursion (set-buffer cl-buffer)
- (copy-marker (or cl-start (point-min)))))
- (cl-mark2 (and cl-end (save-excursion (set-buffer cl-buffer)
- (copy-marker cl-end))))
- cl-pos cl-ovl)
- (while (save-excursion
- (and (setq cl-pos (marker-position cl-mark))
- (< cl-pos (or cl-mark2 (point-max)))
- (progn
- (set-buffer cl-buffer)
- (setq cl-ovl (overlays-at cl-pos))
- (set-marker cl-mark (next-overlay-change cl-pos)))))
- (while (and cl-ovl
- (or (/= (overlay-start (car cl-ovl)) cl-pos)
- (not (and (funcall cl-func (car cl-ovl) cl-arg)
- (set-marker cl-mark nil)))))
- (setq cl-ovl (cdr cl-ovl))))
- (set-marker cl-mark nil) (if cl-mark2 (set-marker cl-mark2 nil)))))
-
-;;; Support for `setf'.
-(defun cl-set-frame-visible-p (frame val)
- (cond ((null val) (make-frame-invisible frame))
- ((eq val 'icon) (iconify-frame frame))
- (t (make-frame-visible frame)))
- val)
-
-;;; Support for `progv'.
-(defvar cl-progv-save)
-(defun cl-progv-before (syms values)
- (while syms
- (cl-push (if (boundp (car syms))
- (cons (car syms) (symbol-value (car syms)))
- (car syms)) cl-progv-save)
- (if values
- (set (cl-pop syms) (cl-pop values))
- (makunbound (cl-pop syms)))))
-
-(defun cl-progv-after ()
- (while cl-progv-save
- (if (consp (car cl-progv-save))
- (set (car (car cl-progv-save)) (cdr (car cl-progv-save)))
- (makunbound (car cl-progv-save)))
- (cl-pop cl-progv-save)))
-
-
-;;; Numbers.
-
-(defun gcd (&rest args)
- "Return the greatest common divisor of the arguments."
- (let ((a (abs (or (cl-pop args) 0))))
- (while args
- (let ((b (abs (cl-pop args))))
- (while (> b 0) (setq b (% a (setq a b))))))
- a))
-
-(defun lcm (&rest args)
- "Return the least common multiple of the arguments."
- (if (memq 0 args)
- 0
- (let ((a (abs (or (cl-pop args) 1))))
- (while args
- (let ((b (abs (cl-pop args))))
- (setq a (* (/ a (gcd a b)) b))))
- a)))
-
-(defun isqrt (a)
- "Return the integer square root of the argument."
- (if (and (integerp a) (> a 0))
- (let ((g (cond ((<= a 100) 10) ((<= a 10000) 100)
- ((<= a 1000000) 1000) (t a)))
- g2)
- (while (< (setq g2 (/ (+ g (/ a g)) 2)) g)
- (setq g g2))
- g)
- (if (eq a 0) 0 (signal 'arith-error nil))))
-
-(defun cl-expt (x y)
- "Return X raised to the power of Y. Works only for integer arguments."
- (if (<= y 0) (if (= y 0) 1 (if (memq x '(-1 1)) (cl-expt x (- y)) 0))
- (* (if (= (% y 2) 0) 1 x) (cl-expt (* x x) (/ y 2)))))
-(or (and (fboundp 'expt) (subrp (symbol-function 'expt)))
- (defalias 'expt 'cl-expt))
-
-(defun floor* (x &optional y)
- "Return a list of the floor of X and the fractional part of X.
-With two arguments, return floor and remainder of their quotient."
- (let ((q (floor x y)))
- (list q (- x (if y (* y q) q)))))
-
-(defun ceiling* (x &optional y)
- "Return a list of the ceiling of X and the fractional part of X.
-With two arguments, return ceiling and remainder of their quotient."
- (let ((res (floor* x y)))
- (if (= (car (cdr res)) 0) res
- (list (1+ (car res)) (- (car (cdr res)) (or y 1))))))
-
-(defun truncate* (x &optional y)
- "Return a list of the integer part of X and the fractional part of X.
-With two arguments, return truncation and remainder of their quotient."
- (if (eq (>= x 0) (or (null y) (>= y 0)))
- (floor* x y) (ceiling* x y)))
-
-(defun round* (x &optional y)
- "Return a list of X rounded to the nearest integer and the remainder.
-With two arguments, return rounding and remainder of their quotient."
- (if y
- (if (and (integerp x) (integerp y))
- (let* ((hy (/ y 2))
- (res (floor* (+ x hy) y)))
- (if (and (= (car (cdr res)) 0)
- (= (+ hy hy) y)
- (/= (% (car res) 2) 0))
- (list (1- (car res)) hy)
- (list (car res) (- (car (cdr res)) hy))))
- (let ((q (round (/ x y))))
- (list q (- x (* q y)))))
- (if (integerp x) (list x 0)
- (let ((q (round x)))
- (list q (- x q))))))
-
-(defun mod* (x y)
- "The remainder of X divided by Y, with the same sign as Y."
- (nth 1 (floor* x y)))
-
-(defun rem* (x y)
- "The remainder of X divided by Y, with the same sign as X."
- (nth 1 (truncate* x y)))
-
-(defun signum (a)
- "Return 1 if A is positive, -1 if negative, 0 if zero."
- (cond ((> a 0) 1) ((< a 0) -1) (t 0)))
-
-
-;; Random numbers.
-
-(defvar *random-state*)
-(defun random* (lim &optional state)
- "Return a random nonnegative number less than LIM, an integer or float.
-Optional second arg STATE is a random-state object."
- (or state (setq state *random-state*))
- ;; Inspired by "ran3" from Numerical Recipes. Additive congruential method.
- (let ((vec (aref state 3)))
- (if (integerp vec)
- (let ((i 0) (j (- 1357335 (% (abs vec) 1357333))) (k 1) ii)
- (aset state 3 (setq vec (make-vector 55 nil)))
- (aset vec 0 j)
- (while (> (setq i (% (+ i 21) 55)) 0)
- (aset vec i (setq j (prog1 k (setq k (- j k))))))
- (while (< (setq i (1+ i)) 200) (random* 2 state))))
- (let* ((i (aset state 1 (% (1+ (aref state 1)) 55)))
- (j (aset state 2 (% (1+ (aref state 2)) 55)))
- (n (logand 8388607 (aset vec i (- (aref vec i) (aref vec j))))))
- (if (integerp lim)
- (if (<= lim 512) (% n lim)
- (if (> lim 8388607) (setq n (+ (lsh n 9) (random* 512 state))))
- (let ((mask 1023))
- (while (< mask (1- lim)) (setq mask (1+ (+ mask mask))))
- (if (< (setq n (logand n mask)) lim) n (random* lim state))))
- (* (/ n '8388608e0) lim)))))
-
-(defun make-random-state (&optional state)
- "Return a copy of random-state STATE, or of `*random-state*' if omitted.
-If STATE is t, return a new state object seeded from the time of day."
- (cond ((null state) (make-random-state *random-state*))
- ((vectorp state) (cl-copy-tree state t))
- ((integerp state) (vector 'cl-random-state-tag -1 30 state))
- (t (make-random-state (cl-random-time)))))
-
-(defun random-state-p (object)
- "Return t if OBJECT is a random-state object."
- (and (vectorp object) (= (length object) 4)
- (eq (aref object 0) 'cl-random-state-tag)))
-
-
-;; Implementation limits.
-
-(defun cl-finite-do (func a b)
- (condition-case err
- (let ((res (funcall func a b))) ; check for IEEE infinity
- (and (numberp res) (/= res (/ res 2)) res))
- (arith-error nil)))
-
-(defvar most-positive-float)
-(defvar most-negative-float)
-(defvar least-positive-float)
-(defvar least-negative-float)
-(defvar least-positive-normalized-float)
-(defvar least-negative-normalized-float)
-(defvar float-epsilon)
-(defvar float-negative-epsilon)
-
-(defun cl-float-limits ()
- (or most-positive-float (not (numberp '2e1))
- (let ((x '2e0) y z)
- ;; Find maximum exponent (first two loops are optimizations)
- (while (cl-finite-do '* x x) (setq x (* x x)))
- (while (cl-finite-do '* x (/ x 2)) (setq x (* x (/ x 2))))
- (while (cl-finite-do '+ x x) (setq x (+ x x)))
- (setq z x y (/ x 2))
- ;; Now fill in 1's in the mantissa.
- (while (and (cl-finite-do '+ x y) (/= (+ x y) x))
- (setq x (+ x y) y (/ y 2)))
- (setq most-positive-float x
- most-negative-float (- x))
- ;; Divide down until mantissa starts rounding.
- (setq x (/ x z) y (/ 16 z) x (* x y))
- (while (condition-case err (and (= x (* (/ x 2) 2)) (> (/ y 2) 0))
- (arith-error nil))
- (setq x (/ x 2) y (/ y 2)))
- (setq least-positive-normalized-float y
- least-negative-normalized-float (- y))
- ;; Divide down until value underflows to zero.
- (setq x (/ 1 z) y x)
- (while (condition-case err (> (/ x 2) 0) (arith-error nil))
- (setq x (/ x 2)))
- (setq least-positive-float x
- least-negative-float (- x))
- (setq x '1e0)
- (while (/= (+ '1e0 x) '1e0) (setq x (/ x 2)))
- (setq float-epsilon (* x 2))
- (setq x '1e0)
- (while (/= (- '1e0 x) '1e0) (setq x (/ x 2)))
- (setq float-negative-epsilon (* x 2))))
- nil)
-
-
-;;; Sequence functions.
-
-(defun subseq (seq start &optional end)
- "Return the subsequence of SEQ from START to END.
-If END is omitted, it defaults to the length of the sequence.
-If START or END is negative, it counts from the end."
- (if (stringp seq) (substring seq start end)
- (let (len)
- (and end (< end 0) (setq end (+ end (setq len (length seq)))))
- (if (< start 0) (setq start (+ start (or len (setq len (length seq))))))
- (cond ((listp seq)
- (if (> start 0) (setq seq (nthcdr start seq)))
- (if end
- (let ((res nil))
- (while (>= (setq end (1- end)) start)
- (cl-push (cl-pop seq) res))
- (nreverse res))
- (copy-sequence seq)))
- (t
- (or end (setq end (or len (length seq))))
- (let ((res (make-vector (max (- end start) 0) nil))
- (i 0))
- (while (< start end)
- (aset res i (aref seq start))
- (setq i (1+ i) start (1+ start)))
- res))))))
-
-(defun concatenate (type &rest seqs)
- "Concatenate, into a sequence of type TYPE, the argument SEQUENCES."
- (cond ((eq type 'vector) (apply 'vconcat seqs))
- ((eq type 'string) (apply 'concat seqs))
- ((eq type 'list) (apply 'append (append seqs '(nil))))
- (t (error "Not a sequence type name: %s" type))))
-
-
-;;; List functions.
-
-(defun revappend (x y)
- "Equivalent to (append (reverse X) Y)."
- (nconc (reverse x) y))
-
-(defun nreconc (x y)
- "Equivalent to (nconc (nreverse X) Y)."
- (nconc (nreverse x) y))
-
-(defun list-length (x)
- "Return the length of a list. Return nil if list is circular."
- (let ((n 0) (fast x) (slow x))
- (while (and (cdr fast) (not (and (eq fast slow) (> n 0))))
- (setq n (+ n 2) fast (cdr (cdr fast)) slow (cdr slow)))
- (if fast (if (cdr fast) nil (1+ n)) n)))
-
-(defun tailp (sublist list)
- "Return true if SUBLIST is a tail of LIST."
- (while (and (consp list) (not (eq sublist list)))
- (setq list (cdr list)))
- (if (numberp sublist) (equal sublist list) (eq sublist list)))
-
-(defun cl-copy-tree (tree &optional vecp)
- "Make a copy of TREE.
-If TREE is a cons cell, this recursively copies both its car and its cdr.
-Contrast to copy-sequence, which copies only along the cdrs. With second
-argument VECP, this copies vectors as well as conses."
- (if (consp tree)
- (let ((p (setq tree (copy-list tree))))
- (while (consp p)
- (if (or (consp (car p)) (and vecp (vectorp (car p))))
- (setcar p (cl-copy-tree (car p) vecp)))
- (or (listp (cdr p)) (setcdr p (cl-copy-tree (cdr p) vecp)))
- (cl-pop p)))
- (if (and vecp (vectorp tree))
- (let ((i (length (setq tree (copy-sequence tree)))))
- (while (>= (setq i (1- i)) 0)
- (aset tree i (cl-copy-tree (aref tree i) vecp))))))
- tree)
-(or (and (fboundp 'copy-tree) (subrp (symbol-function 'copy-tree)))
- (defalias 'copy-tree 'cl-copy-tree))
-
-
-;;; Property lists.
-
-(defun get* (sym tag &optional def) ; See compiler macro in cl-macs.el
- "Return the value of SYMBOL's PROPNAME property, or DEFAULT if none."
- (or (get sym tag)
- (and def
- (let ((plist (symbol-plist sym)))
- (while (and plist (not (eq (car plist) tag)))
- (setq plist (cdr (cdr plist))))
- (if plist (car (cdr plist)) def)))))
-
-(defun getf (plist tag &optional def)
- "Search PROPLIST for property PROPNAME; return its value or DEFAULT.
-PROPLIST is a list of the sort returned by `symbol-plist'."
- (setplist '--cl-getf-symbol-- plist)
- (or (get '--cl-getf-symbol-- tag)
- (and def (get* '--cl-getf-symbol-- tag def))))
-
-(defun cl-set-getf (plist tag val)
- (let ((p plist))
- (while (and p (not (eq (car p) tag))) (setq p (cdr (cdr p))))
- (if p (progn (setcar (cdr p) val) plist) (list* tag val plist))))
-
-(defun cl-do-remf (plist tag)
- (let ((p (cdr plist)))
- (while (and (cdr p) (not (eq (car (cdr p)) tag))) (setq p (cdr (cdr p))))
- (and (cdr p) (progn (setcdr p (cdr (cdr (cdr p)))) t))))
-
-(defun cl-remprop (sym tag)
- "Remove from SYMBOL's plist the property PROP and its value."
- (let ((plist (symbol-plist sym)))
- (if (and plist (eq tag (car plist)))
- (progn (setplist sym (cdr (cdr plist))) t)
- (cl-do-remf plist tag))))
-(or (and (fboundp 'remprop) (subrp (symbol-function 'remprop)))
- (defalias 'remprop 'cl-remprop))
-
-
-
-;;; Hash tables.
-
-(defun make-hash-table (&rest cl-keys)
- "Make an empty Common Lisp-style hash-table.
-If :test is `eq', this can use Lucid Emacs built-in hash-tables.
-In non-Lucid Emacs, or with non-`eq' test, this internally uses a-lists.
-Keywords supported: :test :size
-The Common Lisp keywords :rehash-size and :rehash-threshold are ignored."
- (let ((cl-test (or (car (cdr (memq ':test cl-keys))) 'eql))
- (cl-size (or (car (cdr (memq ':size cl-keys))) 20)))
- (if (and (eq cl-test 'eq) (fboundp 'make-hashtable))
- (funcall 'make-hashtable cl-size)
- (list 'cl-hash-table-tag cl-test
- (if (> cl-size 1) (make-vector cl-size 0)
- (let ((sym (make-symbol "--hashsym--"))) (set sym nil) sym))
- 0))))
-
-(defvar cl-lucid-hash-tag
- (if (and (fboundp 'make-hashtable) (vectorp (make-hashtable 1)))
- (aref (make-hashtable 1) 0) (make-symbol "--cl-hash-tag--")))
-
-(defun hash-table-p (x)
- "Return t if OBJECT is a hash table."
- (or (eq (car-safe x) 'cl-hash-table-tag)
- (and (vectorp x) (= (length x) 4) (eq (aref x 0) cl-lucid-hash-tag))
- (and (fboundp 'hashtablep) (funcall 'hashtablep x))))
-
-(defun cl-not-hash-table (x &optional y &rest z)
- (signal 'wrong-type-argument (list 'hash-table-p (or y x))))
-
-(defun cl-hash-lookup (key table)
- (or (eq (car-safe table) 'cl-hash-table-tag) (cl-not-hash-table table))
- (let* ((array (nth 2 table)) (test (car (cdr table))) (str key) sym)
- (if (symbolp array) (setq str nil sym (symbol-value array))
- (while (or (consp str) (and (vectorp str) (> (length str) 0)))
- (setq str (elt str 0)))
- (cond ((stringp str) (if (eq test 'equalp) (setq str (downcase str))))
- ((symbolp str) (setq str (symbol-name str)))
- ((and (numberp str) (> str -8000000) (< str 8000000))
- (or (integerp str) (setq str (truncate str)))
- (setq str (aref ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
- "11" "12" "13" "14" "15"] (logand str 15))))
- (t (setq str "*")))
- (setq sym (symbol-value (intern-soft str array))))
- (list (and sym (cond ((or (eq test 'eq)
- (and (eq test 'eql) (not (numberp key))))
- (assq key sym))
- ((memq test '(eql equal)) (assoc key sym))
- (t (assoc* key sym ':test test))))
- sym str)))
-
-(defvar cl-builtin-gethash
- (if (and (fboundp 'gethash) (subrp (symbol-function 'gethash)))
- (symbol-function 'gethash) 'cl-not-hash-table))
-(defvar cl-builtin-remhash
- (if (and (fboundp 'remhash) (subrp (symbol-function 'remhash)))
- (symbol-function 'remhash) 'cl-not-hash-table))
-(defvar cl-builtin-clrhash
- (if (and (fboundp 'clrhash) (subrp (symbol-function 'clrhash)))
- (symbol-function 'clrhash) 'cl-not-hash-table))
-(defvar cl-builtin-maphash
- (if (and (fboundp 'maphash) (subrp (symbol-function 'maphash)))
- (symbol-function 'maphash) 'cl-not-hash-table))
-
-(defun cl-gethash (key table &optional def)
- "Look up KEY in HASH-TABLE; return corresponding value, or DEFAULT."
- (if (consp table)
- (let ((found (cl-hash-lookup key table)))
- (if (car found) (cdr (car found)) def))
- (funcall cl-builtin-gethash key table def)))
-(defalias 'gethash 'cl-gethash)
-
-(defun cl-puthash (key val table)
- (if (consp table)
- (let ((found (cl-hash-lookup key table)))
- (if (car found) (setcdr (car found) val)
- (if (nth 2 found)
- (progn
- (if (> (nth 3 table) (* (length (nth 2 table)) 3))
- (let ((new-table (make-vector (nth 3 table) 0)))
- (mapatoms (function
- (lambda (sym)
- (set (intern (symbol-name sym) new-table)
- (symbol-value sym))))
- (nth 2 table))
- (setcar (cdr (cdr table)) new-table)))
- (set (intern (nth 2 found) (nth 2 table))
- (cons (cons key val) (nth 1 found))))
- (set (nth 2 table) (cons (cons key val) (nth 1 found))))
- (setcar (cdr (cdr (cdr table))) (1+ (nth 3 table)))))
- (funcall 'puthash key val table)) val)
-
-(defun cl-remhash (key table)
- "Remove KEY from HASH-TABLE."
- (if (consp table)
- (let ((found (cl-hash-lookup key table)))
- (and (car found)
- (let ((del (delq (car found) (nth 1 found))))
- (setcar (cdr (cdr (cdr table))) (1- (nth 3 table)))
- (if (nth 2 found) (set (intern (nth 2 found) (nth 2 table)) del)
- (set (nth 2 table) del)) t)))
- (prog1 (not (eq (funcall cl-builtin-gethash key table '--cl--) '--cl--))
- (funcall cl-builtin-remhash key table))))
-(defalias 'remhash 'cl-remhash)
-
-(defun cl-clrhash (table)
- "Clear HASH-TABLE."
- (if (consp table)
- (progn
- (or (hash-table-p table) (cl-not-hash-table table))
- (if (symbolp (nth 2 table)) (set (nth 2 table) nil)
- (setcar (cdr (cdr table)) (make-vector (length (nth 2 table)) 0)))
- (setcar (cdr (cdr (cdr table))) 0))
- (funcall cl-builtin-clrhash table))
- nil)
-(defalias 'clrhash 'cl-clrhash)
-
-(defun cl-maphash (cl-func cl-table)
- "Call FUNCTION on keys and values from HASH-TABLE."
- (or (hash-table-p cl-table) (cl-not-hash-table cl-table))
- (if (consp cl-table)
- (mapatoms (function (lambda (cl-x)
- (setq cl-x (symbol-value cl-x))
- (while cl-x
- (funcall cl-func (car (car cl-x))
- (cdr (car cl-x)))
- (setq cl-x (cdr cl-x)))))
- (if (symbolp (nth 2 cl-table))
- (vector (nth 2 cl-table)) (nth 2 cl-table)))
- (funcall cl-builtin-maphash cl-func cl-table)))
-(defalias 'maphash 'cl-maphash)
-
-(defun hash-table-count (table)
- "Return the number of entries in HASH-TABLE."
- (or (hash-table-p table) (cl-not-hash-table table))
- (if (consp table) (nth 3 table) (funcall 'hashtable-fullness table)))
-
-
-;;; Some debugging aids.
-
-(defun cl-prettyprint (form)
- "Insert a pretty-printed rendition of a Lisp FORM in current buffer."
- (let ((pt (point)) last)
- (insert "\n" (prin1-to-string form) "\n")
- (setq last (point))
- (goto-char (1+ pt))
- (while (search-forward "(quote " last t)
- (delete-backward-char 7)
- (insert "'")
- (forward-sexp)
- (delete-char 1))
- (goto-char (1+ pt))
- (cl-do-prettyprint)))
-
-(defun cl-do-prettyprint ()
- (skip-chars-forward " ")
- (if (looking-at "(")
- (let ((skip (or (looking-at "((") (looking-at "(prog")
- (looking-at "(unwind-protect ")
- (looking-at "(function (")
- (looking-at "(cl-block-wrapper ")))
- (two (or (looking-at "(defun ") (looking-at "(defmacro ")))
- (let (or (looking-at "(let\\*? ") (looking-at "(while ")))
- (set (looking-at "(p?set[qf] ")))
- (if (or skip let
- (progn
- (forward-sexp)
- (and (>= (current-column) 78) (progn (backward-sexp) t))))
- (let ((nl t))
- (forward-char 1)
- (cl-do-prettyprint)
- (or skip (looking-at ")") (cl-do-prettyprint))
- (or (not two) (looking-at ")") (cl-do-prettyprint))
- (while (not (looking-at ")"))
- (if set (setq nl (not nl)))
- (if nl (insert "\n"))
- (lisp-indent-line)
- (cl-do-prettyprint))
- (forward-char 1))))
- (forward-sexp)))
-
-(defvar cl-macroexpand-cmacs nil)
-(defvar cl-closure-vars nil)
-
-(defun cl-macroexpand-all (form &optional env)
- "Expand all macro calls through a Lisp FORM.
-This also does some trivial optimizations to make the form prettier."
- (while (or (not (eq form (setq form (macroexpand form env))))
- (and cl-macroexpand-cmacs
- (not (eq form (setq form (compiler-macroexpand form)))))))
- (cond ((not (consp form)) form)
- ((memq (car form) '(let let*))
- (if (null (nth 1 form))
- (cl-macroexpand-all (cons 'progn (cddr form)) env)
- (let ((letf nil) (res nil) (lets (cadr form)))
- (while lets
- (cl-push (if (consp (car lets))
- (let ((exp (cl-macroexpand-all (caar lets) env)))
- (or (symbolp exp) (setq letf t))
- (cons exp (cl-macroexpand-body (cdar lets) env)))
- (let ((exp (cl-macroexpand-all (car lets) env)))
- (if (symbolp exp) exp
- (setq letf t) (list exp nil)))) res)
- (setq lets (cdr lets)))
- (list* (if letf (if (eq (car form) 'let) 'letf 'letf*) (car form))
- (nreverse res) (cl-macroexpand-body (cddr form) env)))))
- ((eq (car form) 'cond)
- (cons (car form)
- (mapcar (function (lambda (x) (cl-macroexpand-body x env)))
- (cdr form))))
- ((eq (car form) 'condition-case)
- (list* (car form) (nth 1 form) (cl-macroexpand-all (nth 2 form) env)
- (mapcar (function
- (lambda (x)
- (cons (car x) (cl-macroexpand-body (cdr x) env))))
- (cdddr form))))
- ((memq (car form) '(quote function))
- (if (eq (car-safe (nth 1 form)) 'lambda)
- (let ((body (cl-macroexpand-body (cddadr form) env)))
- (if (and cl-closure-vars (eq (car form) 'function)
- (cl-expr-contains-any body cl-closure-vars))
- (let* ((new (mapcar 'gensym cl-closure-vars))
- (sub (pairlis cl-closure-vars new)) (decls nil))
- (while (or (stringp (car body))
- (eq (car-safe (car body)) 'interactive))
- (cl-push (list 'quote (cl-pop body)) decls))
- (put (car (last cl-closure-vars)) 'used t)
- (append
- (list 'list '(quote lambda) '(quote (&rest --cl-rest--)))
- (sublis sub (nreverse decls))
- (list
- (list* 'list '(quote apply)
- (list 'list '(quote quote)
- (list 'function
- (list* 'lambda
- (append new (cadadr form))
- (sublis sub body))))
- (nconc (mapcar (function
- (lambda (x)
- (list 'list '(quote quote) x)))
- cl-closure-vars)
- '((quote --cl-rest--)))))))
- (list (car form) (list* 'lambda (cadadr form) body))))
- (let ((found (assq (cadr form) env)))
- (if (eq (cadr (caddr found)) 'cl-labels-args)
- (cl-macroexpand-all (cadr (caddr (cadddr found))) env)
- form))))
- ((memq (car form) '(defun defmacro))
- (list* (car form) (nth 1 form) (cl-macroexpand-body (cddr form) env)))
- ((and (eq (car form) 'progn) (not (cddr form)))
- (cl-macroexpand-all (nth 1 form) env))
- ((eq (car form) 'setq)
- (let* ((args (cl-macroexpand-body (cdr form) env)) (p args))
- (while (and p (symbolp (car p))) (setq p (cddr p)))
- (if p (cl-macroexpand-all (cons 'setf args)) (cons 'setq args))))
- (t (cons (car form) (cl-macroexpand-body (cdr form) env)))))
-
-(defun cl-macroexpand-body (body &optional env)
- (mapcar (function (lambda (x) (cl-macroexpand-all x env))) body))
-
-(defun cl-prettyexpand (form &optional full)
- (message "Expanding...")
- (let ((cl-macroexpand-cmacs full) (cl-compiling-file full)
- (byte-compile-macro-environment nil))
- (setq form (cl-macroexpand-all form
- (and (not full) '((block) (eval-when)))))
- (message "Formatting...")
- (prog1 (cl-prettyprint form)
- (message ""))))
-
-
-
-(run-hooks 'cl-extra-load-hook)
-
-;;; cl-extra.el ends here
diff --git a/lisp/emacs-lisp/cl-indent.el b/lisp/emacs-lisp/cl-indent.el
deleted file mode 100644
index 8d199c14452..00000000000
--- a/lisp/emacs-lisp/cl-indent.el
+++ /dev/null
@@ -1,474 +0,0 @@
-;;; cl-indent.el --- enhanced lisp-indent mode
-
-;; Copyright (C) 1987 Free Software Foundation, Inc.
-
-;; Author: Richard Mlynarik <mly@eddie.mit.edu>
-;; Created: July 1987
-;; Maintainer: FSF
-;; Keywords: lisp, tools
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package supplies a single entry point, common-lisp-indent-function,
-;; which performs indentation in the preferred style for Common Lisp code.
-;; To enable it:
-;;
-;; (setq lisp-indent-function 'common-lisp-indent-function)
-
-;;>> 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
-
-;;; Code:
-
-(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
-the 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'.")
-
-
-;;;###autoload
-(defun common-lisp-indent-function (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 containing 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-function))
- (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-function)))
- ((and (null method))
- ;; backwards compatibility
- (setq method (get tem 'lisp-indent-function)))))
- (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)))
- ((or (eql (char-after (1- containing-sexp)) ?\,)
- (and (eql (char-after (1- containing-sexp)) ?\@)
- (eql (char-after (- containing-sexp 2)) ?\,)))
- ;; ",(...)" or ",@(...)"
- (setq calculated normal-indent))
- ((eql (char-after (1- containing-sexp)) ?\#)
- ;; "#(...)"
- (setq calculated (1+ sexp-column)))
- ((null method))
- ((integerp method)
- ;; convenient top-level hack.
- ;; (also compatible with lisp-indent-function)
- ;; 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 those free variable references!!
- function 'common-lisp-indent-function 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.
- (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 weird 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)
- (compiler-let . let) ;barf
- (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-function
- (if (symbolp (cdr (car l)))
- (get (cdr (car l)) 'common-lisp-indent-function)
- (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-function 1)
-;(put 'defwrapper'common-lisp-indent-function ...)
-;(put 'def 'common-lisp-indent-function ...)
-;(put 'defflavor 'common-lisp-indent-function ...)
-;(put 'defsubst 'common-lisp-indent-function ...)
-
-;(put 'with-restart 'common-lisp-indent-function '((1 4 ((* 1))) (2 &body)))
-;(put 'restart-case 'common-lisp-indent-function '((1 4) (* 2 ((0 1) (* 1)))))
-;(put 'define-condition 'common-lisp-indent-function '((1 6) (2 6 ((* 1))) (3 4 ((* 1))) (4 &body)))
-;(put 'with-condition-handler 'common-lisp-indent-function '((1 4 ((* 1))) (2 &body)))
-;(put 'condition-case 'common-lisp-indent-function '((1 4) (* 2 ((0 1) (1 3) (2 &body)))))
-
-;;; cl-indent.el ends here
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
deleted file mode 100644
index 37d02b564cb..00000000000
--- a/lisp/emacs-lisp/cl-macs.el
+++ /dev/null
@@ -1,2635 +0,0 @@
-;;; cl-macs.el --- Common Lisp macros -*-byte-compile-dynamic: t;-*-
-
-;; Copyright (C) 1993 Free Software Foundation, Inc.
-
-;; Author: Dave Gillespie <daveg@synaptics.com>
-;; Version: 2.02
-;; Keywords: extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; These are extensions to Emacs Lisp that provide a degree of
-;; Common Lisp compatibility, beyond what is already built-in
-;; in Emacs Lisp.
-;;
-;; This package was written by Dave Gillespie; it is a complete
-;; rewrite of Cesar Quiroz's original cl.el package of December 1986.
-;;
-;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19.
-;;
-;; Bug reports, comments, and suggestions are welcome!
-
-;; This file contains the portions of the Common Lisp extensions
-;; package which should be autoloaded, but need only be present
-;; if the compiler or interpreter is used---this file is not
-;; necessary for executing compiled code.
-
-;; See cl.el for Change Log.
-
-
-;;; Code:
-
-(or (memq 'cl-19 features)
- (error "Tried to load `cl-macs' before `cl'!"))
-
-
-;;; We define these here so that this file can compile without having
-;;; loaded the cl.el file already.
-
-(defmacro cl-push (x place) (list 'setq place (list 'cons x place)))
-(defmacro cl-pop (place)
- (list 'car (list 'prog1 place (list 'setq place (list 'cdr place)))))
-(defmacro cl-pop2 (place)
- (list 'prog1 (list 'car (list 'cdr place))
- (list 'setq place (list 'cdr (list 'cdr place)))))
-(put 'cl-push 'edebug-form-spec 'edebug-sexps)
-(put 'cl-pop 'edebug-form-spec 'edebug-sexps)
-(put 'cl-pop2 'edebug-form-spec 'edebug-sexps)
-
-(defvar cl-emacs-type)
-(defvar cl-optimize-safety)
-(defvar cl-optimize-speed)
-
-
-;;; This kludge allows macros which use cl-transform-function-property
-;;; to be called at compile-time.
-
-(require
- (progn
- (or (fboundp 'defalias) (fset 'defalias 'fset))
- (or (fboundp 'cl-transform-function-property)
- (defalias 'cl-transform-function-property
- (function (lambda (n p f)
- (list 'put (list 'quote n) (list 'quote p)
- (list 'function (cons 'lambda f)))))))
- (car (or features (setq features (list 'cl-kludge))))))
-
-
-;;; Initialization.
-
-(defvar cl-old-bc-file-form nil)
-
-;; Patch broken Emacs 18 compiler (re top-level macros).
-;; Emacs 19 compiler doesn't need this patch.
-;; Also, undo broken definition of `eql' that uses same bytecode as `eq'.
-(defun cl-compile-time-init ()
- (setq cl-old-bc-file-form (symbol-function 'byte-compile-file-form))
- (or (fboundp 'byte-compile-flush-pending) ; Emacs 19 compiler?
- (defalias 'byte-compile-file-form
- (function
- (lambda (form)
- (setq form (macroexpand form byte-compile-macro-environment))
- (if (eq (car-safe form) 'progn)
- (cons 'progn (mapcar 'byte-compile-file-form (cdr form)))
- (funcall cl-old-bc-file-form form))))))
- (put 'eql 'byte-compile 'cl-byte-compile-compiler-macro)
- (run-hooks 'cl-hack-bytecomp-hook))
-
-
-;;; Symbols.
-
-(defvar *gensym-counter*)
-(defun gensym (&optional arg)
- "Generate a new uninterned symbol.
-The name is made by appending a number to PREFIX, default \"G\"."
- (let ((prefix (if (stringp arg) arg "G"))
- (num (if (integerp arg) arg
- (prog1 *gensym-counter*
- (setq *gensym-counter* (1+ *gensym-counter*))))))
- (make-symbol (format "%s%d" prefix num))))
-
-(defun gentemp (&optional arg)
- "Generate a new interned symbol with a unique name.
-The name is made by appending a number to PREFIX, default \"G\"."
- (let ((prefix (if (stringp arg) arg "G"))
- name)
- (while (intern-soft (setq name (format "%s%d" prefix *gensym-counter*)))
- (setq *gensym-counter* (1+ *gensym-counter*)))
- (intern name)))
-
-
-;;; Program structure.
-
-(defmacro defun* (name args &rest body)
- "(defun* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a function.
-Like normal `defun', except ARGLIST allows full Common Lisp conventions,
-and BODY is implicitly surrounded by (block NAME ...)."
- (let* ((res (cl-transform-lambda (cons args body) name))
- (form (list* 'defun name (cdr res))))
- (if (car res) (list 'progn (car res) form) form)))
-
-(defmacro defmacro* (name args &rest body)
- "(defmacro* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a macro.
-Like normal `defmacro', except ARGLIST allows full Common Lisp conventions,
-and BODY is implicitly surrounded by (block NAME ...)."
- (let* ((res (cl-transform-lambda (cons args body) name))
- (form (list* 'defmacro name (cdr res))))
- (if (car res) (list 'progn (car res) form) form)))
-
-(defmacro function* (func)
- "(function* SYMBOL-OR-LAMBDA): introduce a function.
-Like normal `function', except that if argument is a lambda form, its
-ARGLIST allows full Common Lisp conventions."
- (if (eq (car-safe func) 'lambda)
- (let* ((res (cl-transform-lambda (cdr func) 'cl-none))
- (form (list 'function (cons 'lambda (cdr res)))))
- (if (car res) (list 'progn (car res) form) form))
- (list 'function func)))
-
-(defun cl-transform-function-property (func prop form)
- (let ((res (cl-transform-lambda form func)))
- (append '(progn) (cdr (cdr (car res)))
- (list (list 'put (list 'quote func) (list 'quote prop)
- (list 'function (cons 'lambda (cdr res))))))))
-
-(defconst lambda-list-keywords
- '(&optional &rest &key &allow-other-keys &aux &whole &body &environment))
-
-(defvar cl-macro-environment nil)
-(defvar bind-block) (defvar bind-defs) (defvar bind-enquote)
-(defvar bind-inits) (defvar bind-lets) (defvar bind-forms)
-
-(defun cl-transform-lambda (form bind-block)
- (let* ((args (car form)) (body (cdr form))
- (bind-defs nil) (bind-enquote nil)
- (bind-inits nil) (bind-lets nil) (bind-forms nil)
- (header nil) (simple-args nil))
- (while (or (stringp (car body)) (eq (car-safe (car body)) 'interactive))
- (cl-push (cl-pop body) header))
- (setq args (if (listp args) (copy-list args) (list '&rest args)))
- (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p)))))
- (if (setq bind-defs (cadr (memq '&cl-defs args)))
- (setq args (delq '&cl-defs (delq bind-defs args))
- bind-defs (cadr bind-defs)))
- (if (setq bind-enquote (memq '&cl-quote args))
- (setq args (delq '&cl-quote args)))
- (if (memq '&whole args) (error "&whole not currently implemented"))
- (let* ((p (memq '&environment args)) (v (cadr p)))
- (if p (setq args (nconc (delq (car p) (delq v args))
- (list '&aux (list v 'cl-macro-environment))))))
- (while (and args (symbolp (car args))
- (not (memq (car args) '(nil &rest &body &key &aux)))
- (not (and (eq (car args) '&optional)
- (or bind-defs (consp (cadr args))))))
- (cl-push (cl-pop args) simple-args))
- (or (eq bind-block 'cl-none)
- (setq body (list (list* 'block bind-block body))))
- (if (null args)
- (list* nil (nreverse simple-args) (nconc (nreverse header) body))
- (if (memq '&optional simple-args) (cl-push '&optional args))
- (cl-do-arglist args nil (- (length simple-args)
- (if (memq '&optional simple-args) 1 0)))
- (setq bind-lets (nreverse bind-lets))
- (list* (and bind-inits (list* 'eval-when '(compile load eval)
- (nreverse bind-inits)))
- (nconc (nreverse simple-args)
- (list '&rest (car (cl-pop bind-lets))))
- (nconc (nreverse header)
- (list (nconc (list 'let* bind-lets)
- (nreverse bind-forms) body)))))))
-
-(defun cl-do-arglist (args expr &optional num) ; uses bind-*
- (if (nlistp args)
- (if (or (memq args lambda-list-keywords) (not (symbolp args)))
- (error "Invalid argument name: %s" args)
- (cl-push (list args expr) bind-lets))
- (setq args (copy-list args))
- (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p)))))
- (let ((p (memq '&body args))) (if p (setcar p '&rest)))
- (if (memq '&environment args) (error "&environment used incorrectly"))
- (let ((save-args args)
- (restarg (memq '&rest args))
- (safety (if (cl-compiling-file) cl-optimize-safety 3))
- (keys nil)
- (laterarg nil) (exactarg nil) minarg)
- (or num (setq num 0))
- (if (listp (cadr restarg))
- (setq restarg (gensym "--rest--"))
- (setq restarg (cadr restarg)))
- (cl-push (list restarg expr) bind-lets)
- (if (eq (car args) '&whole)
- (cl-push (list (cl-pop2 args) restarg) bind-lets))
- (let ((p args))
- (setq minarg restarg)
- (while (and p (not (memq (car p) lambda-list-keywords)))
- (or (eq p args) (setq minarg (list 'cdr minarg)))
- (setq p (cdr p)))
- (if (memq (car p) '(nil &aux))
- (setq minarg (list '= (list 'length restarg)
- (length (ldiff args p)))
- exactarg (not (eq args p)))))
- (while (and args (not (memq (car args) lambda-list-keywords)))
- (let ((poparg (list (if (or (cdr args) (not exactarg)) 'pop 'car)
- restarg)))
- (cl-do-arglist
- (cl-pop args)
- (if (or laterarg (= safety 0)) poparg
- (list 'if minarg poparg
- (list 'signal '(quote wrong-number-of-arguments)
- (list 'list (and (not (eq bind-block 'cl-none))
- (list 'quote bind-block))
- (list 'length restarg)))))))
- (setq num (1+ num) laterarg t))
- (while (and (eq (car args) '&optional) (cl-pop args))
- (while (and args (not (memq (car args) lambda-list-keywords)))
- (let ((arg (cl-pop args)))
- (or (consp arg) (setq arg (list arg)))
- (if (cddr arg) (cl-do-arglist (nth 2 arg) (list 'and restarg t)))
- (let ((def (if (cdr arg) (nth 1 arg)
- (or (car bind-defs)
- (nth 1 (assq (car arg) bind-defs)))))
- (poparg (list 'pop restarg)))
- (and def bind-enquote (setq def (list 'quote def)))
- (cl-do-arglist (car arg)
- (if def (list 'if restarg poparg def) poparg))
- (setq num (1+ num))))))
- (if (eq (car args) '&rest)
- (let ((arg (cl-pop2 args)))
- (if (consp arg) (cl-do-arglist arg restarg)))
- (or (eq (car args) '&key) (= safety 0) exactarg
- (cl-push (list 'if restarg
- (list 'signal '(quote wrong-number-of-arguments)
- (list 'list
- (and (not (eq bind-block 'cl-none))
- (list 'quote bind-block))
- (list '+ num (list 'length restarg)))))
- bind-forms)))
- (while (and (eq (car args) '&key) (cl-pop args))
- (while (and args (not (memq (car args) lambda-list-keywords)))
- (let ((arg (cl-pop args)))
- (or (consp arg) (setq arg (list arg)))
- (let* ((karg (if (consp (car arg)) (caar arg)
- (intern (format ":%s" (car arg)))))
- (varg (if (consp (car arg)) (cadar arg) (car arg)))
- (def (if (cdr arg) (cadr arg)
- (or (car bind-defs) (cadr (assq varg bind-defs)))))
- (look (list 'memq (list 'quote karg) restarg)))
- (and def bind-enquote (setq def (list 'quote def)))
- (if (cddr arg)
- (let* ((temp (or (nth 2 arg) (gensym)))
- (val (list 'car (list 'cdr temp))))
- (cl-do-arglist temp look)
- (cl-do-arglist varg
- (list 'if temp
- (list 'prog1 val (list 'setq temp t))
- def)))
- (cl-do-arglist
- varg
- (list 'car
- (list 'cdr
- (if (null def)
- look
- (list 'or look
- (if (eq (cl-const-expr-p def) t)
- (list
- 'quote
- (list nil (cl-const-expr-val def)))
- (list 'list nil def))))))))
- (cl-push karg keys)
- (if (= (aref (symbol-name karg) 0) ?:)
- (progn (set karg karg)
- (cl-push (list 'setq karg (list 'quote karg))
- bind-inits)))))))
- (setq keys (nreverse keys))
- (or (and (eq (car args) '&allow-other-keys) (cl-pop args))
- (null keys) (= safety 0)
- (let* ((var (gensym "--keys--"))
- (allow '(:allow-other-keys))
- (check (list
- 'while var
- (list
- 'cond
- (list (list 'memq (list 'car var)
- (list 'quote (append keys allow)))
- (list 'setq var (list 'cdr (list 'cdr var))))
- (list (list 'car
- (list 'cdr
- (list 'memq (cons 'quote allow)
- restarg)))
- (list 'setq var nil))
- (list t
- (list
- 'error
- (format "Keyword argument %%s not one of %s"
- keys)
- (list 'car var)))))))
- (cl-push (list 'let (list (list var restarg)) check) bind-forms)))
- (while (and (eq (car args) '&aux) (cl-pop args))
- (while (and args (not (memq (car args) lambda-list-keywords)))
- (if (consp (car args))
- (if (and bind-enquote (cadar args))
- (cl-do-arglist (caar args)
- (list 'quote (cadr (cl-pop args))))
- (cl-do-arglist (caar args) (cadr (cl-pop args))))
- (cl-do-arglist (cl-pop args) nil))))
- (if args (error "Malformed argument list %s" save-args)))))
-
-(defun cl-arglist-args (args)
- (if (nlistp args) (list args)
- (let ((res nil) (kind nil) arg)
- (while (consp args)
- (setq arg (cl-pop args))
- (if (memq arg lambda-list-keywords) (setq kind arg)
- (if (eq arg '&cl-defs) (cl-pop args)
- (and (consp arg) kind (setq arg (car arg)))
- (and (consp arg) (cdr arg) (eq kind '&key) (setq arg (cadr arg)))
- (setq res (nconc res (cl-arglist-args arg))))))
- (nconc res (and args (list args))))))
-
-(defmacro destructuring-bind (args expr &rest body)
- (let* ((bind-lets nil) (bind-forms nil) (bind-inits nil)
- (bind-defs nil) (bind-block 'cl-none))
- (cl-do-arglist (or args '(&aux)) expr)
- (append '(progn) bind-inits
- (list (nconc (list 'let* (nreverse bind-lets))
- (nreverse bind-forms) body)))))
-
-
-;;; The `eval-when' form.
-
-(defvar cl-not-toplevel nil)
-
-(defmacro eval-when (when &rest body)
- "(eval-when (WHEN...) BODY...): control when BODY is evaluated.
-If `compile' is in WHEN, BODY is evaluated when compiled at top-level.
-If `load' is in WHEN, BODY is evaluated when loaded after top-level compile.
-If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level."
- (if (and (fboundp 'cl-compiling-file) (cl-compiling-file)
- (not cl-not-toplevel) (not (boundp 'for-effect))) ; horrible kludge
- (let ((comp (or (memq 'compile when) (memq ':compile-toplevel when)))
- (cl-not-toplevel t))
- (if (or (memq 'load when) (memq ':load-toplevel when))
- (if comp (cons 'progn (mapcar 'cl-compile-time-too body))
- (list* 'if nil nil body))
- (progn (if comp (eval (cons 'progn body))) nil)))
- (and (or (memq 'eval when) (memq ':execute when))
- (cons 'progn body))))
-
-(defun cl-compile-time-too (form)
- (or (and (symbolp (car-safe form)) (get (car-safe form) 'byte-hunk-handler))
- (setq form (macroexpand
- form (cons '(eval-when) byte-compile-macro-environment))))
- (cond ((eq (car-safe form) 'progn)
- (cons 'progn (mapcar 'cl-compile-time-too (cdr form))))
- ((eq (car-safe form) 'eval-when)
- (let ((when (nth 1 form)))
- (if (or (memq 'eval when) (memq ':execute when))
- (list* 'eval-when (cons 'compile when) (cddr form))
- form)))
- (t (eval form) form)))
-
-(or (and (fboundp 'eval-when-compile)
- (not (eq (car-safe (symbol-function 'eval-when-compile)) 'autoload)))
- (eval '(defmacro eval-when-compile (&rest body)
- "Like `progn', but evaluates the body at compile time.
-The result of the body appears to the compiler as a quoted constant."
- (list 'quote (eval (cons 'progn body))))))
-
-(defmacro load-time-value (form &optional read-only)
- "Like `progn', but evaluates the body at load time.
-The result of the body appears to the compiler as a quoted constant."
- (if (cl-compiling-file)
- (let* ((temp (gentemp "--cl-load-time--"))
- (set (list 'set (list 'quote temp) form)))
- (if (and (fboundp 'byte-compile-file-form-defmumble)
- (boundp 'this-kind) (boundp 'that-one))
- (fset 'byte-compile-file-form
- (list 'lambda '(form)
- (list 'fset '(quote byte-compile-file-form)
- (list 'quote
- (symbol-function 'byte-compile-file-form)))
- (list 'byte-compile-file-form (list 'quote set))
- '(byte-compile-file-form form)))
- (print set (symbol-value 'outbuffer)))
- (list 'symbol-value (list 'quote temp)))
- (list 'quote (eval form))))
-
-
-;;; Conditional control structures.
-
-(defmacro case (expr &rest clauses)
- "(case EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value.
-Each clause looks like (KEYLIST BODY...). EXPR is evaluated and compared
-against each key in each KEYLIST; the corresponding BODY is evaluated.
-If no clause succeeds, case returns nil. A single atom may be used in
-place of a KEYLIST of one atom. A KEYLIST of `t' or `otherwise' is
-allowed only in the final clause, and matches if no other keys match.
-Key values are compared by `eql'."
- (let* ((temp (if (cl-simple-expr-p expr 3) expr (gensym)))
- (head-list nil)
- (body (cons
- 'cond
- (mapcar
- (function
- (lambda (c)
- (cons (cond ((memq (car c) '(t otherwise)) t)
- ((eq (car c) 'ecase-error-flag)
- (list 'error "ecase failed: %s, %s"
- temp (list 'quote (reverse head-list))))
- ((listp (car c))
- (setq head-list (append (car c) head-list))
- (list 'member* temp (list 'quote (car c))))
- (t
- (if (memq (car c) head-list)
- (error "Duplicate key in case: %s"
- (car c)))
- (cl-push (car c) head-list)
- (list 'eql temp (list 'quote (car c)))))
- (or (cdr c) '(nil)))))
- clauses))))
- (if (eq temp expr) body
- (list 'let (list (list temp expr)) body))))
-
-(defmacro ecase (expr &rest clauses)
- "(ecase EXPR CLAUSES...): like `case', but error if no case fits.
-`otherwise'-clauses are not allowed."
- (list* 'case expr (append clauses '((ecase-error-flag)))))
-
-(defmacro typecase (expr &rest clauses)
- "(typecase EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value.
-Each clause looks like (TYPE BODY...). EXPR is evaluated and, if it
-satisfies TYPE, the corresponding BODY is evaluated. If no clause succeeds,
-typecase returns nil. A TYPE of `t' or `otherwise' is allowed only in the
-final clause, and matches if no other keys match."
- (let* ((temp (if (cl-simple-expr-p expr 3) expr (gensym)))
- (type-list nil)
- (body (cons
- 'cond
- (mapcar
- (function
- (lambda (c)
- (cons (cond ((eq (car c) 'otherwise) t)
- ((eq (car c) 'ecase-error-flag)
- (list 'error "etypecase failed: %s, %s"
- temp (list 'quote (reverse type-list))))
- (t
- (cl-push (car c) type-list)
- (cl-make-type-test temp (car c))))
- (or (cdr c) '(nil)))))
- clauses))))
- (if (eq temp expr) body
- (list 'let (list (list temp expr)) body))))
-
-(defmacro etypecase (expr &rest clauses)
- "(etypecase EXPR CLAUSES...): like `typecase', but error if no case fits.
-`otherwise'-clauses are not allowed."
- (list* 'typecase expr (append clauses '((ecase-error-flag)))))
-
-
-;;; Blocks and exits.
-
-(defmacro block (name &rest body)
- "(block NAME BODY...): define a lexically-scoped block named NAME.
-NAME may be any symbol. Code inside the BODY forms can call `return-from'
-to jump prematurely out of the block. This differs from `catch' and `throw'
-in two respects: First, the NAME is an unevaluated symbol rather than a
-quoted symbol or other form; and second, NAME is lexically rather than
-dynamically scoped: Only references to it within BODY will work. These
-references may appear inside macro expansions, but not inside functions
-called from BODY."
- (if (cl-safe-expr-p (cons 'progn body)) (cons 'progn body)
- (list 'cl-block-wrapper
- (list* 'catch (list 'quote (intern (format "--cl-block-%s--" name)))
- body))))
-
-(defvar cl-active-block-names nil)
-
-(put 'cl-block-wrapper 'byte-compile 'cl-byte-compile-block)
-(defun cl-byte-compile-block (cl-form)
- (if (fboundp 'byte-compile-form-do-effect) ; Check for optimizing compiler
- (progn
- (let* ((cl-entry (cons (nth 1 (nth 1 (nth 1 cl-form))) nil))
- (cl-active-block-names (cons cl-entry cl-active-block-names))
- (cl-body (byte-compile-top-level
- (cons 'progn (cddr (nth 1 cl-form))))))
- (if (cdr cl-entry)
- (byte-compile-form (list 'catch (nth 1 (nth 1 cl-form)) cl-body))
- (byte-compile-form cl-body))))
- (byte-compile-form (nth 1 cl-form))))
-
-(put 'cl-block-throw 'byte-compile 'cl-byte-compile-throw)
-(defun cl-byte-compile-throw (cl-form)
- (let ((cl-found (assq (nth 1 (nth 1 cl-form)) cl-active-block-names)))
- (if cl-found (setcdr cl-found t)))
- (byte-compile-normal-call (cons 'throw (cdr cl-form))))
-
-(defmacro return (&optional res)
- "(return [RESULT]): return from the block named nil.
-This is equivalent to `(return-from nil RESULT)'."
- (list 'return-from nil res))
-
-(defmacro return-from (name &optional res)
- "(return-from NAME [RESULT]): return from the block named NAME.
-This jump out to the innermost enclosing `(block NAME ...)' form,
-returning RESULT from that form (or nil if RESULT is omitted).
-This is compatible with Common Lisp, but note that `defun' and
-`defmacro' do not create implicit blocks as they do in Common Lisp."
- (let ((name2 (intern (format "--cl-block-%s--" name))))
- (list 'cl-block-throw (list 'quote name2) res)))
-
-
-;;; The "loop" macro.
-
-(defvar args) (defvar loop-accum-var) (defvar loop-accum-vars)
-(defvar loop-bindings) (defvar loop-body) (defvar loop-destr-temps)
-(defvar loop-finally) (defvar loop-finish-flag) (defvar loop-first-flag)
-(defvar loop-initially) (defvar loop-map-form) (defvar loop-name)
-(defvar loop-result) (defvar loop-result-explicit)
-(defvar loop-result-var) (defvar loop-steps) (defvar loop-symbol-macs)
-
-(defmacro loop (&rest args)
- "(loop CLAUSE...): The Common Lisp `loop' macro.
-Valid clauses are:
- for VAR from/upfrom/downfrom NUM to/upto/downto/above/below NUM by NUM,
- for VAR in LIST by FUNC, for VAR on LIST by FUNC, for VAR = INIT then EXPR,
- for VAR across ARRAY, repeat NUM, with VAR = INIT, while COND, until COND,
- always COND, never COND, thereis COND, collect EXPR into VAR,
- append EXPR into VAR, nconc EXPR into VAR, sum EXPR into VAR,
- count EXPR into VAR, maximize EXPR into VAR, minimize EXPR into VAR,
- if COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...],
- unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...],
- do EXPRS..., initially EXPRS..., finally EXPRS..., return EXPR,
- finally return EXPR, named NAME."
- (if (not (memq t (mapcar 'symbolp (delq nil (delq t (copy-list args))))))
- (list 'block nil (list* 'while t args))
- (let ((loop-name nil) (loop-bindings nil)
- (loop-body nil) (loop-steps nil)
- (loop-result nil) (loop-result-explicit nil)
- (loop-result-var nil) (loop-finish-flag nil)
- (loop-accum-var nil) (loop-accum-vars nil)
- (loop-initially nil) (loop-finally nil)
- (loop-map-form nil) (loop-first-flag nil)
- (loop-destr-temps nil) (loop-symbol-macs nil))
- (setq args (append args '(cl-end-loop)))
- (while (not (eq (car args) 'cl-end-loop)) (cl-parse-loop-clause))
- (if loop-finish-flag
- (cl-push (list (list loop-finish-flag t)) loop-bindings))
- (if loop-first-flag
- (progn (cl-push (list (list loop-first-flag t)) loop-bindings)
- (cl-push (list 'setq loop-first-flag nil) loop-steps)))
- (let* ((epilogue (nconc (nreverse loop-finally)
- (list (or loop-result-explicit loop-result))))
- (ands (cl-loop-build-ands (nreverse loop-body)))
- (while-body (nconc (cadr ands) (nreverse loop-steps)))
- (body (append
- (nreverse loop-initially)
- (list (if loop-map-form
- (list 'block '--cl-finish--
- (subst
- (if (eq (car ands) t) while-body
- (cons (list 'or (car ands)
- '(return-from --cl-finish--
- nil))
- while-body))
- '--cl-map loop-map-form))
- (list* 'while (car ands) while-body)))
- (if loop-finish-flag
- (if (equal epilogue '(nil)) (list loop-result-var)
- (list (list 'if loop-finish-flag
- (cons 'progn epilogue) loop-result-var)))
- epilogue))))
- (if loop-result-var (cl-push (list loop-result-var) loop-bindings))
- (while loop-bindings
- (if (cdar loop-bindings)
- (setq body (list (cl-loop-let (cl-pop loop-bindings) body t)))
- (let ((lets nil))
- (while (and loop-bindings
- (not (cdar loop-bindings)))
- (cl-push (car (cl-pop loop-bindings)) lets))
- (setq body (list (cl-loop-let lets body nil))))))
- (if loop-symbol-macs
- (setq body (list (list* 'symbol-macrolet loop-symbol-macs body))))
- (list* 'block loop-name body)))))
-
-(defun cl-parse-loop-clause () ; uses args, loop-*
- (let ((word (cl-pop args))
- (hash-types '(hash-key hash-keys hash-value hash-values))
- (key-types '(key-code key-codes key-seq key-seqs
- key-binding key-bindings)))
- (cond
-
- ((null args)
- (error "Malformed `loop' macro"))
-
- ((eq word 'named)
- (setq loop-name (cl-pop args)))
-
- ((eq word 'initially)
- (if (memq (car args) '(do doing)) (cl-pop args))
- (or (consp (car args)) (error "Syntax error on `initially' clause"))
- (while (consp (car args))
- (cl-push (cl-pop args) loop-initially)))
-
- ((eq word 'finally)
- (if (eq (car args) 'return)
- (setq loop-result-explicit (or (cl-pop2 args) '(quote nil)))
- (if (memq (car args) '(do doing)) (cl-pop args))
- (or (consp (car args)) (error "Syntax error on `finally' clause"))
- (if (and (eq (caar args) 'return) (null loop-name))
- (setq loop-result-explicit (or (nth 1 (cl-pop args)) '(quote nil)))
- (while (consp (car args))
- (cl-push (cl-pop args) loop-finally)))))
-
- ((memq word '(for as))
- (let ((loop-for-bindings nil) (loop-for-sets nil) (loop-for-steps nil)
- (ands nil))
- (while
- (let ((var (or (cl-pop args) (gensym))))
- (setq word (cl-pop args))
- (if (eq word 'being) (setq word (cl-pop args)))
- (if (memq word '(the each)) (setq word (cl-pop args)))
- (if (memq word '(buffer buffers))
- (setq word 'in args (cons '(buffer-list) args)))
- (cond
-
- ((memq word '(from downfrom upfrom to downto upto
- above below by))
- (cl-push word args)
- (if (memq (car args) '(downto above))
- (error "Must specify `from' value for downward loop"))
- (let* ((down (or (eq (car args) 'downfrom)
- (memq (caddr args) '(downto above))))
- (excl (or (memq (car args) '(above below))
- (memq (caddr args) '(above below))))
- (start (and (memq (car args) '(from upfrom downfrom))
- (cl-pop2 args)))
- (end (and (memq (car args)
- '(to upto downto above below))
- (cl-pop2 args)))
- (step (and (eq (car args) 'by) (cl-pop2 args)))
- (end-var (and (not (cl-const-expr-p end)) (gensym)))
- (step-var (and (not (cl-const-expr-p step))
- (gensym))))
- (and step (numberp step) (<= step 0)
- (error "Loop `by' value is not positive: %s" step))
- (cl-push (list var (or start 0)) loop-for-bindings)
- (if end-var (cl-push (list end-var end) loop-for-bindings))
- (if step-var (cl-push (list step-var step)
- loop-for-bindings))
- (if end
- (cl-push (list
- (if down (if excl '> '>=) (if excl '< '<=))
- var (or end-var end)) loop-body))
- (cl-push (list var (list (if down '- '+) var
- (or step-var step 1)))
- loop-for-steps)))
-
- ((memq word '(in in-ref on))
- (let* ((on (eq word 'on))
- (temp (if (and on (symbolp var)) var (gensym))))
- (cl-push (list temp (cl-pop args)) loop-for-bindings)
- (cl-push (list 'consp temp) loop-body)
- (if (eq word 'in-ref)
- (cl-push (list var (list 'car temp)) loop-symbol-macs)
- (or (eq temp var)
- (progn
- (cl-push (list var nil) loop-for-bindings)
- (cl-push (list var (if on temp (list 'car temp)))
- loop-for-sets))))
- (cl-push (list temp
- (if (eq (car args) 'by)
- (let ((step (cl-pop2 args)))
- (if (and (memq (car-safe step)
- '(quote function
- function*))
- (symbolp (nth 1 step)))
- (list (nth 1 step) temp)
- (list 'funcall step temp)))
- (list 'cdr temp)))
- loop-for-steps)))
-
- ((eq word '=)
- (let* ((start (cl-pop args))
- (then (if (eq (car args) 'then) (cl-pop2 args) start)))
- (cl-push (list var nil) loop-for-bindings)
- (if (or ands (eq (car args) 'and))
- (progn
- (cl-push (list var
- (list 'if
- (or loop-first-flag
- (setq loop-first-flag
- (gensym)))
- start var))
- loop-for-sets)
- (cl-push (list var then) loop-for-steps))
- (cl-push (list var
- (if (eq start then) start
- (list 'if
- (or loop-first-flag
- (setq loop-first-flag (gensym)))
- start then)))
- loop-for-sets))))
-
- ((memq word '(across across-ref))
- (let ((temp-vec (gensym)) (temp-idx (gensym)))
- (cl-push (list temp-vec (cl-pop args)) loop-for-bindings)
- (cl-push (list temp-idx -1) loop-for-bindings)
- (cl-push (list '< (list 'setq temp-idx (list '1+ temp-idx))
- (list 'length temp-vec)) loop-body)
- (if (eq word 'across-ref)
- (cl-push (list var (list 'aref temp-vec temp-idx))
- loop-symbol-macs)
- (cl-push (list var nil) loop-for-bindings)
- (cl-push (list var (list 'aref temp-vec temp-idx))
- loop-for-sets))))
-
- ((memq word '(element elements))
- (let ((ref (or (memq (car args) '(in-ref of-ref))
- (and (not (memq (car args) '(in of)))
- (error "Expected `of'"))))
- (seq (cl-pop2 args))
- (temp-seq (gensym))
- (temp-idx (if (eq (car args) 'using)
- (if (and (= (length (cadr args)) 2)
- (eq (caadr args) 'index))
- (cadr (cl-pop2 args))
- (error "Bad `using' clause"))
- (gensym))))
- (cl-push (list temp-seq seq) loop-for-bindings)
- (cl-push (list temp-idx 0) loop-for-bindings)
- (if ref
- (let ((temp-len (gensym)))
- (cl-push (list temp-len (list 'length temp-seq))
- loop-for-bindings)
- (cl-push (list var (list 'elt temp-seq temp-idx))
- loop-symbol-macs)
- (cl-push (list '< temp-idx temp-len) loop-body))
- (cl-push (list var nil) loop-for-bindings)
- (cl-push (list 'and temp-seq
- (list 'or (list 'consp temp-seq)
- (list '< temp-idx
- (list 'length temp-seq))))
- loop-body)
- (cl-push (list var (list 'if (list 'consp temp-seq)
- (list 'pop temp-seq)
- (list 'aref temp-seq temp-idx)))
- loop-for-sets))
- (cl-push (list temp-idx (list '1+ temp-idx))
- loop-for-steps)))
-
- ((memq word hash-types)
- (or (memq (car args) '(in of)) (error "Expected `of'"))
- (let* ((table (cl-pop2 args))
- (other (if (eq (car args) 'using)
- (if (and (= (length (cadr args)) 2)
- (memq (caadr args) hash-types)
- (not (eq (caadr args) word)))
- (cadr (cl-pop2 args))
- (error "Bad `using' clause"))
- (gensym))))
- (if (memq word '(hash-value hash-values))
- (setq var (prog1 other (setq other var))))
- (setq loop-map-form
- (list 'maphash (list 'function
- (list* 'lambda (list var other)
- '--cl-map)) table))))
-
- ((memq word '(symbol present-symbol external-symbol
- symbols present-symbols external-symbols))
- (let ((ob (and (memq (car args) '(in of)) (cl-pop2 args))))
- (setq loop-map-form
- (list 'mapatoms (list 'function
- (list* 'lambda (list var)
- '--cl-map)) ob))))
-
- ((memq word '(overlay overlays extent extents))
- (let ((buf nil) (from nil) (to nil))
- (while (memq (car args) '(in of from to))
- (cond ((eq (car args) 'from) (setq from (cl-pop2 args)))
- ((eq (car args) 'to) (setq to (cl-pop2 args)))
- (t (setq buf (cl-pop2 args)))))
- (setq loop-map-form
- (list 'cl-map-extents
- (list 'function (list 'lambda (list var (gensym))
- '(progn . --cl-map) nil))
- buf from to))))
-
- ((memq word '(interval intervals))
- (let ((buf nil) (prop nil) (from nil) (to nil)
- (var1 (gensym)) (var2 (gensym)))
- (while (memq (car args) '(in of property from to))
- (cond ((eq (car args) 'from) (setq from (cl-pop2 args)))
- ((eq (car args) 'to) (setq to (cl-pop2 args)))
- ((eq (car args) 'property)
- (setq prop (cl-pop2 args)))
- (t (setq buf (cl-pop2 args)))))
- (if (and (consp var) (symbolp (car var)) (symbolp (cdr var)))
- (setq var1 (car var) var2 (cdr var))
- (cl-push (list var (list 'cons var1 var2)) loop-for-sets))
- (setq loop-map-form
- (list 'cl-map-intervals
- (list 'function (list 'lambda (list var1 var2)
- '(progn . --cl-map)))
- buf prop from to))))
-
- ((memq word key-types)
- (or (memq (car args) '(in of)) (error "Expected `of'"))
- (let ((map (cl-pop2 args))
- (other (if (eq (car args) 'using)
- (if (and (= (length (cadr args)) 2)
- (memq (caadr args) key-types)
- (not (eq (caadr args) word)))
- (cadr (cl-pop2 args))
- (error "Bad `using' clause"))
- (gensym))))
- (if (memq word '(key-binding key-bindings))
- (setq var (prog1 other (setq other var))))
- (setq loop-map-form
- (list (if (memq word '(key-seq key-seqs))
- 'cl-map-keymap-recursively 'cl-map-keymap)
- (list 'function (list* 'lambda (list var other)
- '--cl-map)) map))))
-
- ((memq word '(frame frames screen screens))
- (let ((temp (gensym)))
- (cl-push (list var (if (eq cl-emacs-type 'lucid)
- '(selected-screen) '(selected-frame)))
- loop-for-bindings)
- (cl-push (list temp nil) loop-for-bindings)
- (cl-push (list 'prog1 (list 'not (list 'eq var temp))
- (list 'or temp (list 'setq temp var)))
- loop-body)
- (cl-push (list var (list (if (eq cl-emacs-type 'lucid)
- 'next-screen 'next-frame) var))
- loop-for-steps)))
-
- ((memq word '(window windows))
- (let ((scr (and (memq (car args) '(in of)) (cl-pop2 args)))
- (temp (gensym)))
- (cl-push (list var (if scr
- (list (if (eq cl-emacs-type 'lucid)
- 'screen-selected-window
- 'frame-selected-window) scr)
- '(selected-window)))
- loop-for-bindings)
- (cl-push (list temp nil) loop-for-bindings)
- (cl-push (list 'prog1 (list 'not (list 'eq var temp))
- (list 'or temp (list 'setq temp var)))
- loop-body)
- (cl-push (list var (list 'next-window var)) loop-for-steps)))
-
- (t
- (let ((handler (and (symbolp word)
- (get word 'cl-loop-for-handler))))
- (if handler
- (funcall handler var)
- (error "Expected a `for' preposition, found %s" word)))))
- (eq (car args) 'and))
- (setq ands t)
- (cl-pop args))
- (if (and ands loop-for-bindings)
- (cl-push (nreverse loop-for-bindings) loop-bindings)
- (setq loop-bindings (nconc (mapcar 'list loop-for-bindings)
- loop-bindings)))
- (if loop-for-sets
- (cl-push (list 'progn
- (cl-loop-let (nreverse loop-for-sets) 'setq ands)
- t) loop-body))
- (if loop-for-steps
- (cl-push (cons (if ands 'psetq 'setq)
- (apply 'append (nreverse loop-for-steps)))
- loop-steps))))
-
- ((eq word 'repeat)
- (let ((temp (gensym)))
- (cl-push (list (list temp (cl-pop args))) loop-bindings)
- (cl-push (list '>= (list 'setq temp (list '1- temp)) 0) loop-body)))
-
- ((eq word 'collect)
- (let ((what (cl-pop args))
- (var (cl-loop-handle-accum nil 'nreverse)))
- (if (eq var loop-accum-var)
- (cl-push (list 'progn (list 'push what var) t) loop-body)
- (cl-push (list 'progn
- (list 'setq var (list 'nconc var (list 'list what)))
- t) loop-body))))
-
- ((memq word '(nconc nconcing append appending))
- (let ((what (cl-pop args))
- (var (cl-loop-handle-accum nil 'nreverse)))
- (cl-push (list 'progn
- (list 'setq var
- (if (eq var loop-accum-var)
- (list 'nconc
- (list (if (memq word '(nconc nconcing))
- 'nreverse 'reverse)
- what)
- var)
- (list (if (memq word '(nconc nconcing))
- 'nconc 'append)
- var what))) t) loop-body)))
-
- ((memq word '(concat concating))
- (let ((what (cl-pop args))
- (var (cl-loop-handle-accum "")))
- (cl-push (list 'progn (list 'callf 'concat var what) t) loop-body)))
-
- ((memq word '(vconcat vconcating))
- (let ((what (cl-pop args))
- (var (cl-loop-handle-accum [])))
- (cl-push (list 'progn (list 'callf 'vconcat var what) t) loop-body)))
-
- ((memq word '(sum summing))
- (let ((what (cl-pop args))
- (var (cl-loop-handle-accum 0)))
- (cl-push (list 'progn (list 'incf var what) t) loop-body)))
-
- ((memq word '(count counting))
- (let ((what (cl-pop args))
- (var (cl-loop-handle-accum 0)))
- (cl-push (list 'progn (list 'if what (list 'incf var)) t) loop-body)))
-
- ((memq word '(minimize minimizing maximize maximizing))
- (let* ((what (cl-pop args))
- (temp (if (cl-simple-expr-p what) what (gensym)))
- (var (cl-loop-handle-accum nil))
- (func (intern (substring (symbol-name word) 0 3)))
- (set (list 'setq var (list 'if var (list func var temp) temp))))
- (cl-push (list 'progn (if (eq temp what) set
- (list 'let (list (list temp what)) set))
- t) loop-body)))
-
- ((eq word 'with)
- (let ((bindings nil))
- (while (progn (cl-push (list (cl-pop args)
- (and (eq (car args) '=) (cl-pop2 args)))
- bindings)
- (eq (car args) 'and))
- (cl-pop args))
- (cl-push (nreverse bindings) loop-bindings)))
-
- ((eq word 'while)
- (cl-push (cl-pop args) loop-body))
-
- ((eq word 'until)
- (cl-push (list 'not (cl-pop args)) loop-body))
-
- ((eq word 'always)
- (or loop-finish-flag (setq loop-finish-flag (gensym)))
- (cl-push (list 'setq loop-finish-flag (cl-pop args)) loop-body)
- (setq loop-result t))
-
- ((eq word 'never)
- (or loop-finish-flag (setq loop-finish-flag (gensym)))
- (cl-push (list 'setq loop-finish-flag (list 'not (cl-pop args)))
- loop-body)
- (setq loop-result t))
-
- ((eq word 'thereis)
- (or loop-finish-flag (setq loop-finish-flag (gensym)))
- (or loop-result-var (setq loop-result-var (gensym)))
- (cl-push (list 'setq loop-finish-flag
- (list 'not (list 'setq loop-result-var (cl-pop args))))
- loop-body))
-
- ((memq word '(if when unless))
- (let* ((cond (cl-pop args))
- (then (let ((loop-body nil))
- (cl-parse-loop-clause)
- (cl-loop-build-ands (nreverse loop-body))))
- (else (let ((loop-body nil))
- (if (eq (car args) 'else)
- (progn (cl-pop args) (cl-parse-loop-clause)))
- (cl-loop-build-ands (nreverse loop-body))))
- (simple (and (eq (car then) t) (eq (car else) t))))
- (if (eq (car args) 'end) (cl-pop args))
- (if (eq word 'unless) (setq then (prog1 else (setq else then))))
- (let ((form (cons (if simple (cons 'progn (nth 1 then)) (nth 2 then))
- (if simple (nth 1 else) (list (nth 2 else))))))
- (if (cl-expr-contains form 'it)
- (let ((temp (gensym)))
- (cl-push (list temp) loop-bindings)
- (setq form (list* 'if (list 'setq temp cond)
- (subst temp 'it form))))
- (setq form (list* 'if cond form)))
- (cl-push (if simple (list 'progn form t) form) loop-body))))
-
- ((memq word '(do doing))
- (let ((body nil))
- (or (consp (car args)) (error "Syntax error on `do' clause"))
- (while (consp (car args)) (cl-push (cl-pop args) body))
- (cl-push (cons 'progn (nreverse (cons t body))) loop-body)))
-
- ((eq word 'return)
- (or loop-finish-flag (setq loop-finish-flag (gensym)))
- (or loop-result-var (setq loop-result-var (gensym)))
- (cl-push (list 'setq loop-result-var (cl-pop args)
- loop-finish-flag nil) loop-body))
-
- (t
- (let ((handler (and (symbolp word) (get word 'cl-loop-handler))))
- (or handler (error "Expected a loop keyword, found %s" word))
- (funcall handler))))
- (if (eq (car args) 'and)
- (progn (cl-pop args) (cl-parse-loop-clause)))))
-
-(defun cl-loop-let (specs body par) ; uses loop-*
- (let ((p specs) (temps nil) (new nil))
- (while (and p (or (symbolp (car-safe (car p))) (null (cadar p))))
- (setq p (cdr p)))
- (and par p
- (progn
- (setq par nil p specs)
- (while p
- (or (cl-const-expr-p (cadar p))
- (let ((temp (gensym)))
- (cl-push (list temp (cadar p)) temps)
- (setcar (cdar p) temp)))
- (setq p (cdr p)))))
- (while specs
- (if (and (consp (car specs)) (listp (caar specs)))
- (let* ((spec (caar specs)) (nspecs nil)
- (expr (cadr (cl-pop specs)))
- (temp (cdr (or (assq spec loop-destr-temps)
- (car (cl-push (cons spec (or (last spec 0)
- (gensym)))
- loop-destr-temps))))))
- (cl-push (list temp expr) new)
- (while (consp spec)
- (cl-push (list (cl-pop spec)
- (and expr (list (if spec 'pop 'car) temp)))
- nspecs))
- (setq specs (nconc (nreverse nspecs) specs)))
- (cl-push (cl-pop specs) new)))
- (if (eq body 'setq)
- (let ((set (cons (if par 'psetq 'setq) (apply 'nconc (nreverse new)))))
- (if temps (list 'let* (nreverse temps) set) set))
- (list* (if par 'let 'let*)
- (nconc (nreverse temps) (nreverse new)) body))))
-
-(defun cl-loop-handle-accum (def &optional func) ; uses args, loop-*
- (if (eq (car args) 'into)
- (let ((var (cl-pop2 args)))
- (or (memq var loop-accum-vars)
- (progn (cl-push (list (list var def)) loop-bindings)
- (cl-push var loop-accum-vars)))
- var)
- (or loop-accum-var
- (progn
- (cl-push (list (list (setq loop-accum-var (gensym)) def))
- loop-bindings)
- (setq loop-result (if func (list func loop-accum-var)
- loop-accum-var))
- loop-accum-var))))
-
-(defun cl-loop-build-ands (clauses)
- (let ((ands nil)
- (body nil))
- (while clauses
- (if (and (eq (car-safe (car clauses)) 'progn)
- (eq (car (last (car clauses))) t))
- (if (cdr clauses)
- (setq clauses (cons (nconc (butlast (car clauses))
- (if (eq (car-safe (cadr clauses))
- 'progn)
- (cdadr clauses)
- (list (cadr clauses))))
- (cddr clauses)))
- (setq body (cdr (butlast (cl-pop clauses)))))
- (cl-push (cl-pop clauses) ands)))
- (setq ands (or (nreverse ands) (list t)))
- (list (if (cdr ands) (cons 'and ands) (car ands))
- body
- (let ((full (if body
- (append ands (list (cons 'progn (append body '(t)))))
- ands)))
- (if (cdr full) (cons 'and full) (car full))))))
-
-
-;;; Other iteration control structures.
-
-(defmacro do (steps endtest &rest body)
- "The Common Lisp `do' loop.
-Format is: (do ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)"
- (cl-expand-do-loop steps endtest body nil))
-
-(defmacro do* (steps endtest &rest body)
- "The Common Lisp `do*' loop.
-Format is: (do* ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)"
- (cl-expand-do-loop steps endtest body t))
-
-(defun cl-expand-do-loop (steps endtest body star)
- (list 'block nil
- (list* (if star 'let* 'let)
- (mapcar (function (lambda (c)
- (if (consp c) (list (car c) (nth 1 c)) c)))
- steps)
- (list* 'while (list 'not (car endtest))
- (append body
- (let ((sets (mapcar
- (function
- (lambda (c)
- (and (consp c) (cdr (cdr c))
- (list (car c) (nth 2 c)))))
- steps)))
- (setq sets (delq nil sets))
- (and sets
- (list (cons (if (or star (not (cdr sets)))
- 'setq 'psetq)
- (apply 'append sets)))))))
- (or (cdr endtest) '(nil)))))
-
-(defmacro dolist (spec &rest body)
- "(dolist (VAR LIST [RESULT]) BODY...): loop over a list.
-Evaluate BODY with VAR bound to each `car' from LIST, in turn.
-Then evaluate RESULT to get return value, default nil."
- (let ((temp (gensym "--dolist-temp--")))
- (list 'block nil
- (list* 'let (list (list temp (nth 1 spec)) (car spec))
- (list* 'while temp (list 'setq (car spec) (list 'car temp))
- (append body (list (list 'setq temp
- (list 'cdr temp)))))
- (if (cdr (cdr spec))
- (cons (list 'setq (car spec) nil) (cdr (cdr spec)))
- '(nil))))))
-
-(defmacro dotimes (spec &rest body)
- "(dotimes (VAR COUNT [RESULT]) BODY...): loop a certain number of times.
-Evaluate BODY with VAR bound to successive integers from 0, inclusive,
-to COUNT, exclusive. Then evaluate RESULT to get return value, default
-nil."
- (let ((temp (gensym "--dotimes-temp--")))
- (list 'block nil
- (list* 'let (list (list temp (nth 1 spec)) (list (car spec) 0))
- (list* 'while (list '< (car spec) temp)
- (append body (list (list 'incf (car spec)))))
- (or (cdr (cdr spec)) '(nil))))))
-
-(defmacro do-symbols (spec &rest body)
- "(dosymbols (VAR [OBARRAY [RESULT]]) BODY...): loop over all symbols.
-Evaluate BODY with VAR bound to each interned symbol, or to each symbol
-from OBARRAY."
- ;; Apparently this doesn't have an implicit block.
- (list 'block nil
- (list 'let (list (car spec))
- (list* 'mapatoms
- (list 'function (list* 'lambda (list (car spec)) body))
- (and (cadr spec) (list (cadr spec))))
- (caddr spec))))
-
-(defmacro do-all-symbols (spec &rest body)
- (list* 'do-symbols (list (car spec) nil (cadr spec)) body))
-
-
-;;; Assignments.
-
-(defmacro psetq (&rest args)
- "(psetq SYM VAL SYM VAL ...): set SYMs to the values VALs in parallel.
-This is like `setq', except that all VAL forms are evaluated (in order)
-before assigning any symbols SYM to the corresponding values."
- (cons 'psetf args))
-
-
-;;; Binding control structures.
-
-(defmacro progv (symbols values &rest body)
- "(progv SYMBOLS VALUES BODY...): bind SYMBOLS to VALUES dynamically in BODY.
-The forms SYMBOLS and VALUES are evaluated, and must evaluate to lists.
-Each SYMBOL in the first list is bound to the corresponding VALUE in the
-second list (or made unbound if VALUES is shorter than SYMBOLS); then the
-BODY forms are executed and their result is returned. This is much like
-a `let' form, except that the list of symbols can be computed at run-time."
- (list 'let '((cl-progv-save nil))
- (list 'unwind-protect
- (list* 'progn (list 'cl-progv-before symbols values) body)
- '(cl-progv-after))))
-
-;;; This should really have some way to shadow 'byte-compile properties, etc.
-(defmacro flet (bindings &rest body)
- "(flet ((FUNC ARGLIST BODY...) ...) FORM...): make temporary function defns.
-This is an analogue of `let' that operates on the function cell of FUNC
-rather than its value cell. The FORMs are evaluated with the specified
-function definitions in place, then the definitions are undone (the FUNCs
-go back to their previous definitions, or lack thereof)."
- (list* 'letf*
- (mapcar
- (function
- (lambda (x)
- (if (or (and (fboundp (car x))
- (eq (car-safe (symbol-function (car x))) 'macro))
- (cdr (assq (car x) cl-macro-environment)))
- (error "Use `labels', not `flet', to rebind macro names"))
- (let ((func (list 'function*
- (list 'lambda (cadr x)
- (list* 'block (car x) (cddr x))))))
- (if (and (cl-compiling-file)
- (boundp 'byte-compile-function-environment))
- (cl-push (cons (car x) (eval func))
- byte-compile-function-environment))
- (list (list 'symbol-function (list 'quote (car x))) func))))
- bindings)
- body))
-
-(defmacro labels (bindings &rest body)
- "(labels ((FUNC ARGLIST BODY...) ...) FORM...): make temporary func bindings.
-This is like `flet', except the bindings are lexical instead of dynamic.
-Unlike `flet', this macro is fully complaint with the Common Lisp standard."
- (let ((vars nil) (sets nil) (cl-macro-environment cl-macro-environment))
- (while bindings
- (let ((var (gensym)))
- (cl-push var vars)
- (cl-push (list 'function* (cons 'lambda (cdar bindings))) sets)
- (cl-push var sets)
- (cl-push (list (car (cl-pop bindings)) 'lambda '(&rest cl-labels-args)
- (list 'list* '(quote funcall) (list 'quote var)
- 'cl-labels-args))
- cl-macro-environment)))
- (cl-macroexpand-all (list* 'lexical-let vars (cons (cons 'setq sets) body))
- cl-macro-environment)))
-
-;; The following ought to have a better definition for use with newer
-;; byte compilers.
-(defmacro macrolet (bindings &rest body)
- "(macrolet ((NAME ARGLIST BODY...) ...) FORM...): make temporary macro defns.
-This is like `flet', but for macros instead of functions."
- (if (cdr bindings)
- (list 'macrolet
- (list (car bindings)) (list* 'macrolet (cdr bindings) body))
- (if (null bindings) (cons 'progn body)
- (let* ((name (caar bindings))
- (res (cl-transform-lambda (cdar bindings) name)))
- (eval (car res))
- (cl-macroexpand-all (cons 'progn body)
- (cons (list* name 'lambda (cdr res))
- cl-macro-environment))))))
-
-(defmacro symbol-macrolet (bindings &rest body)
- "(symbol-macrolet ((NAME EXPANSION) ...) FORM...): make symbol macro defns.
-Within the body FORMs, references to the variable NAME will be replaced
-by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...)."
- (if (cdr bindings)
- (list 'symbol-macrolet
- (list (car bindings)) (list* 'symbol-macrolet (cdr bindings) body))
- (if (null bindings) (cons 'progn body)
- (cl-macroexpand-all (cons 'progn body)
- (cons (list (symbol-name (caar bindings))
- (cadar bindings))
- cl-macro-environment)))))
-
-(defvar cl-closure-vars nil)
-(defmacro lexical-let (bindings &rest body)
- "(lexical-let BINDINGS BODY...): like `let', but lexically scoped.
-The main visible difference is that lambdas inside BODY will create
-lexical closures as in Common Lisp."
- (let* ((cl-closure-vars cl-closure-vars)
- (vars (mapcar (function
- (lambda (x)
- (or (consp x) (setq x (list x)))
- (cl-push (gensym (format "--%s--" (car x)))
- cl-closure-vars)
- (set (car cl-closure-vars) [bad-lexical-ref])
- (list (car x) (cadr x) (car cl-closure-vars))))
- bindings))
- (ebody
- (cl-macroexpand-all
- (cons 'progn body)
- (nconc (mapcar (function (lambda (x)
- (list (symbol-name (car x))
- (list 'symbol-value (caddr x))
- t))) vars)
- (list '(defun . cl-defun-expander))
- cl-macro-environment))))
- (if (not (get (car (last cl-closure-vars)) 'used))
- (list 'let (mapcar (function (lambda (x)
- (list (caddr x) (cadr x)))) vars)
- (sublis (mapcar (function (lambda (x)
- (cons (caddr x)
- (list 'quote (caddr x)))))
- vars)
- ebody))
- (list 'let (mapcar (function (lambda (x)
- (list (caddr x)
- (list 'make-symbol
- (format "--%s--" (car x))))))
- vars)
- (apply 'append '(setf)
- (mapcar (function
- (lambda (x)
- (list (list 'symbol-value (caddr x)) (cadr x))))
- vars))
- ebody))))
-
-(defmacro lexical-let* (bindings &rest body)
- "(lexical-let* BINDINGS BODY...): like `let*', but lexically scoped.
-The main visible difference is that lambdas inside BODY will create
-lexical closures as in Common Lisp."
- (if (null bindings) (cons 'progn body)
- (setq bindings (reverse bindings))
- (while bindings
- (setq body (list (list* 'lexical-let (list (cl-pop bindings)) body))))
- (car body)))
-
-(defun cl-defun-expander (func &rest rest)
- (list 'progn
- (list 'defalias (list 'quote func)
- (list 'function (cons 'lambda rest)))
- (list 'quote func)))
-
-
-;;; Multiple values.
-
-(defmacro multiple-value-bind (vars form &rest body)
- "(multiple-value-bind (SYM SYM...) FORM BODY): collect multiple return values.
-FORM must return a list; the BODY is then executed with the first N elements
-of this list bound (`let'-style) to each of the symbols SYM in turn. This
-is analogous to the Common Lisp `multiple-value-bind' macro, using lists to
-simulate true multiple return values. For compatibility, (values A B C) is
-a synonym for (list A B C)."
- (let ((temp (gensym)) (n -1))
- (list* 'let* (cons (list temp form)
- (mapcar (function
- (lambda (v)
- (list v (list 'nth (setq n (1+ n)) temp))))
- vars))
- body)))
-
-(defmacro multiple-value-setq (vars form)
- "(multiple-value-setq (SYM SYM...) FORM): collect multiple return values.
-FORM must return a list; the first N elements of this list are stored in
-each of the symbols SYM in turn. This is analogous to the Common Lisp
-`multiple-value-setq' macro, using lists to simulate true multiple return
-values. For compatibility, (values A B C) is a synonym for (list A B C)."
- (cond ((null vars) (list 'progn form nil))
- ((null (cdr vars)) (list 'setq (car vars) (list 'car form)))
- (t
- (let* ((temp (gensym)) (n 0))
- (list 'let (list (list temp form))
- (list 'prog1 (list 'setq (cl-pop vars) (list 'car temp))
- (cons 'setq (apply 'nconc
- (mapcar (function
- (lambda (v)
- (list v (list
- 'nth
- (setq n (1+ n))
- temp))))
- vars)))))))))
-
-
-;;; Declarations.
-
-(defmacro locally (&rest body) (cons 'progn body))
-(defmacro the (type form) form)
-
-(defvar cl-proclaim-history t) ; for future compilers
-(defvar cl-declare-stack t) ; for future compilers
-
-(defun cl-do-proclaim (spec hist)
- (and hist (listp cl-proclaim-history) (cl-push spec cl-proclaim-history))
- (cond ((eq (car-safe spec) 'special)
- (if (boundp 'byte-compile-bound-variables)
- (setq byte-compile-bound-variables
- (append (cdr spec) byte-compile-bound-variables))))
-
- ((eq (car-safe spec) 'inline)
- (while (setq spec (cdr spec))
- (or (memq (get (car spec) 'byte-optimizer)
- '(nil byte-compile-inline-expand))
- (error "%s already has a byte-optimizer, can't make it inline"
- (car spec)))
- (put (car spec) 'byte-optimizer 'byte-compile-inline-expand)))
-
- ((eq (car-safe spec) 'notinline)
- (while (setq spec (cdr spec))
- (if (eq (get (car spec) 'byte-optimizer)
- 'byte-compile-inline-expand)
- (put (car spec) 'byte-optimizer nil))))
-
- ((eq (car-safe spec) 'optimize)
- (let ((speed (assq (nth 1 (assq 'speed (cdr spec)))
- '((0 nil) (1 t) (2 t) (3 t))))
- (safety (assq (nth 1 (assq 'safety (cdr spec)))
- '((0 t) (1 t) (2 t) (3 nil)))))
- (if speed (setq cl-optimize-speed (car speed)
- byte-optimize (nth 1 speed)))
- (if safety (setq cl-optimize-safety (car safety)
- byte-compile-delete-errors (nth 1 safety)))))
-
- ((and (eq (car-safe spec) 'warn) (boundp 'byte-compile-warnings))
- (if (eq byte-compile-warnings t)
- (setq byte-compile-warnings byte-compile-warning-types))
- (while (setq spec (cdr spec))
- (if (consp (car spec))
- (if (eq (cadar spec) 0)
- (setq byte-compile-warnings
- (delq (caar spec) byte-compile-warnings))
- (setq byte-compile-warnings
- (adjoin (caar spec) byte-compile-warnings)))))))
- nil)
-
-;;; Process any proclamations made before cl-macs was loaded.
-(defvar cl-proclaims-deferred)
-(let ((p (reverse cl-proclaims-deferred)))
- (while p (cl-do-proclaim (cl-pop p) t))
- (setq cl-proclaims-deferred nil))
-
-(defmacro declare (&rest specs)
- (if (cl-compiling-file)
- (while specs
- (if (listp cl-declare-stack) (cl-push (car specs) cl-declare-stack))
- (cl-do-proclaim (cl-pop specs) nil)))
- nil)
-
-
-
-;;; Generalized variables.
-
-(defmacro define-setf-method (func args &rest body)
- "(define-setf-method NAME ARGLIST BODY...): define a `setf' method.
-This method shows how to handle `setf's to places of the form (NAME ARGS...).
-The argument forms ARGS are bound according to ARGLIST, as if NAME were
-going to be expanded as a macro, then the BODY forms are executed and must
-return a list of five elements: a temporary-variables list, a value-forms
-list, a store-variables list (of length one), a store-form, and an access-
-form. See `defsetf' for a simpler way to define most setf-methods."
- (append '(eval-when (compile load eval))
- (if (stringp (car body))
- (list (list 'put (list 'quote func) '(quote setf-documentation)
- (cl-pop body))))
- (list (cl-transform-function-property
- func 'setf-method (cons args body)))))
-
-(defmacro defsetf (func arg1 &rest args)
- "(defsetf NAME FUNC): define a `setf' method.
-This macro is an easy-to-use substitute for `define-setf-method' that works
-well for simple place forms. In the simple `defsetf' form, `setf's of
-the form (setf (NAME ARGS...) VAL) are transformed to function or macro
-calls of the form (FUNC ARGS... VAL). Example: (defsetf aref aset).
-Alternate form: (defsetf NAME ARGLIST (STORE) BODY...).
-Here, the above `setf' call is expanded by binding the argument forms ARGS
-according to ARGLIST, binding the value form VAL to STORE, then executing
-BODY, which must return a Lisp form that does the necessary `setf' operation.
-Actually, ARGLIST and STORE may be bound to temporary variables which are
-introduced automatically to preserve proper execution order of the arguments.
-Example: (defsetf nth (n x) (v) (list 'setcar (list 'nthcdr n x) v))."
- (if (listp arg1)
- (let* ((largs nil) (largsr nil)
- (temps nil) (tempsr nil)
- (restarg nil) (rest-temps nil)
- (store-var (car (prog1 (car args) (setq args (cdr args)))))
- (store-temp (intern (format "--%s--temp--" store-var)))
- (lets1 nil) (lets2 nil)
- (docstr nil) (p arg1))
- (if (stringp (car args))
- (setq docstr (prog1 (car args) (setq args (cdr args)))))
- (while (and p (not (eq (car p) '&aux)))
- (if (eq (car p) '&rest)
- (setq p (cdr p) restarg (car p))
- (or (memq (car p) '(&optional &key &allow-other-keys))
- (setq largs (cons (if (consp (car p)) (car (car p)) (car p))
- largs)
- temps (cons (intern (format "--%s--temp--" (car largs)))
- temps))))
- (setq p (cdr p)))
- (setq largs (nreverse largs) temps (nreverse temps))
- (if restarg
- (setq largsr (append largs (list restarg))
- rest-temps (intern (format "--%s--temp--" restarg))
- tempsr (append temps (list rest-temps)))
- (setq largsr largs tempsr temps))
- (let ((p1 largs) (p2 temps))
- (while p1
- (setq lets1 (cons (list (car p2)
- (list 'gensym (format "--%s--" (car p1))))
- lets1)
- lets2 (cons (list (car p1) (car p2)) lets2)
- p1 (cdr p1) p2 (cdr p2))))
- (if restarg (setq lets2 (cons (list restarg rest-temps) lets2)))
- (append (list 'define-setf-method func arg1)
- (and docstr (list docstr))
- (list
- (list 'let*
- (nreverse
- (cons (list store-temp
- (list 'gensym (format "--%s--" store-var)))
- (if restarg
- (append
- (list
- (list rest-temps
- (list 'mapcar '(quote gensym)
- restarg)))
- lets1)
- lets1)))
- (list 'list ; 'values
- (cons (if restarg 'list* 'list) tempsr)
- (cons (if restarg 'list* 'list) largsr)
- (list 'list store-temp)
- (cons 'let*
- (cons (nreverse
- (cons (list store-var store-temp)
- lets2))
- args))
- (cons (if restarg 'list* 'list)
- (cons (list 'quote func) tempsr)))))))
- (list 'defsetf func '(&rest args) '(store)
- (let ((call (list 'cons (list 'quote arg1)
- '(append args (list store)))))
- (if (car args)
- (list 'list '(quote progn) call 'store)
- call)))))
-
-;;; Some standard place types from Common Lisp.
-(defsetf aref aset)
-(defsetf car setcar)
-(defsetf cdr setcdr)
-(defsetf elt (seq n) (store)
- (list 'if (list 'listp seq) (list 'setcar (list 'nthcdr n seq) store)
- (list 'aset seq n store)))
-(defsetf get put)
-(defsetf get* (x y &optional d) (store) (list 'put x y store))
-(defsetf gethash (x h &optional d) (store) (list 'cl-puthash x store h))
-(defsetf nth (n x) (store) (list 'setcar (list 'nthcdr n x) store))
-(defsetf subseq (seq start &optional end) (new)
- (list 'progn (list 'replace seq new ':start1 start ':end1 end) new))
-(defsetf symbol-function fset)
-(defsetf symbol-plist setplist)
-(defsetf symbol-value set)
-
-;;; Various car/cdr aliases. Note that `cadr' is handled specially.
-(defsetf first setcar)
-(defsetf second (x) (store) (list 'setcar (list 'cdr x) store))
-(defsetf third (x) (store) (list 'setcar (list 'cddr x) store))
-(defsetf fourth (x) (store) (list 'setcar (list 'cdddr x) store))
-(defsetf fifth (x) (store) (list 'setcar (list 'nthcdr 4 x) store))
-(defsetf sixth (x) (store) (list 'setcar (list 'nthcdr 5 x) store))
-(defsetf seventh (x) (store) (list 'setcar (list 'nthcdr 6 x) store))
-(defsetf eighth (x) (store) (list 'setcar (list 'nthcdr 7 x) store))
-(defsetf ninth (x) (store) (list 'setcar (list 'nthcdr 8 x) store))
-(defsetf tenth (x) (store) (list 'setcar (list 'nthcdr 9 x) store))
-(defsetf rest setcdr)
-
-;;; Some more Emacs-related place types.
-(defsetf buffer-file-name set-visited-file-name t)
-(defsetf buffer-modified-p set-buffer-modified-p t)
-(defsetf buffer-name rename-buffer t)
-(defsetf buffer-string () (store)
- (list 'progn '(erase-buffer) (list 'insert store)))
-(defsetf buffer-substring cl-set-buffer-substring)
-(defsetf current-buffer set-buffer)
-(defsetf current-case-table set-case-table)
-(defsetf current-column move-to-column t)
-(defsetf current-global-map use-global-map t)
-(defsetf current-input-mode () (store)
- (list 'progn (list 'apply 'set-input-mode store) store))
-(defsetf current-local-map use-local-map t)
-(defsetf current-window-configuration set-window-configuration t)
-(defsetf default-file-modes set-default-file-modes t)
-(defsetf default-value set-default)
-(defsetf documentation-property put)
-(defsetf extent-data set-extent-data)
-(defsetf extent-face set-extent-face)
-(defsetf extent-priority set-extent-priority)
-(defsetf extent-end-position (ext) (store)
- (list 'progn (list 'set-extent-endpoints (list 'extent-start-position ext)
- store) store))
-(defsetf extent-start-position (ext) (store)
- (list 'progn (list 'set-extent-endpoints store
- (list 'extent-end-position ext)) store))
-(defsetf face-background (f &optional s) (x) (list 'set-face-background f x s))
-(defsetf face-background-pixmap (f &optional s) (x)
- (list 'set-face-background-pixmap f x s))
-(defsetf face-font (f &optional s) (x) (list 'set-face-font f x s))
-(defsetf face-foreground (f &optional s) (x) (list 'set-face-foreground f x s))
-(defsetf face-underline-p (f &optional s) (x)
- (list 'set-face-underline-p f x s))
-(defsetf file-modes set-file-modes t)
-(defsetf frame-height set-screen-height t)
-(defsetf frame-parameters modify-frame-parameters t)
-(defsetf frame-visible-p cl-set-frame-visible-p)
-(defsetf frame-width set-screen-width t)
-(defsetf getenv setenv t)
-(defsetf get-register set-register)
-(defsetf global-key-binding global-set-key)
-(defsetf keymap-parent set-keymap-parent)
-(defsetf local-key-binding local-set-key)
-(defsetf mark set-mark t)
-(defsetf mark-marker set-mark t)
-(defsetf marker-position set-marker t)
-(defsetf match-data store-match-data t)
-(defsetf mouse-position (scr) (store)
- (list 'set-mouse-position scr (list 'car store) (list 'cadr store)
- (list 'cddr store)))
-(defsetf overlay-get overlay-put)
-(defsetf overlay-start (ov) (store)
- (list 'progn (list 'move-overlay ov store (list 'overlay-end ov)) store))
-(defsetf overlay-end (ov) (store)
- (list 'progn (list 'move-overlay ov (list 'overlay-start ov) store) store))
-(defsetf point goto-char)
-(defsetf point-marker goto-char t)
-(defsetf point-max () (store)
- (list 'progn (list 'narrow-to-region '(point-min) store) store))
-(defsetf point-min () (store)
- (list 'progn (list 'narrow-to-region store '(point-max)) store))
-(defsetf process-buffer set-process-buffer)
-(defsetf process-filter set-process-filter)
-(defsetf process-sentinel set-process-sentinel)
-(defsetf read-mouse-position (scr) (store)
- (list 'set-mouse-position scr (list 'car store) (list 'cdr store)))
-(defsetf screen-height set-screen-height t)
-(defsetf screen-width set-screen-width t)
-(defsetf selected-window select-window)
-(defsetf selected-screen select-screen)
-(defsetf selected-frame select-frame)
-(defsetf standard-case-table set-standard-case-table)
-(defsetf syntax-table set-syntax-table)
-(defsetf visited-file-modtime set-visited-file-modtime t)
-(defsetf window-buffer set-window-buffer t)
-(defsetf window-display-table set-window-display-table t)
-(defsetf window-dedicated-p set-window-dedicated-p t)
-(defsetf window-height () (store)
- (list 'progn (list 'enlarge-window (list '- store '(window-height))) store))
-(defsetf window-hscroll set-window-hscroll)
-(defsetf window-point set-window-point)
-(defsetf window-start set-window-start)
-(defsetf window-width () (store)
- (list 'progn (list 'enlarge-window (list '- store '(window-width)) t) store))
-(defsetf x-get-cutbuffer x-store-cutbuffer t)
-(defsetf x-get-cut-buffer x-store-cut-buffer t) ; groan.
-(defsetf x-get-secondary-selection x-own-secondary-selection t)
-(defsetf x-get-selection x-own-selection t)
-
-;;; More complex setf-methods.
-;;; These should take &environment arguments, but since full arglists aren't
-;;; available while compiling cl-macs, we fake it by referring to the global
-;;; variable cl-macro-environment directly.
-
-(define-setf-method apply (func arg1 &rest rest)
- (or (and (memq (car-safe func) '(quote function function*))
- (symbolp (car-safe (cdr-safe func))))
- (error "First arg to apply in setf is not (function SYM): %s" func))
- (let* ((form (cons (nth 1 func) (cons arg1 rest)))
- (method (get-setf-method form cl-macro-environment)))
- (list (car method) (nth 1 method) (nth 2 method)
- (cl-setf-make-apply (nth 3 method) (cadr func) (car method))
- (cl-setf-make-apply (nth 4 method) (cadr func) (car method)))))
-
-(defun cl-setf-make-apply (form func temps)
- (if (eq (car form) 'progn)
- (list* 'progn (cl-setf-make-apply (cadr form) func temps) (cddr form))
- (or (equal (last form) (last temps))
- (error "%s is not suitable for use with setf-of-apply" func))
- (list* 'apply (list 'quote (car form)) (cdr form))))
-
-(define-setf-method nthcdr (n place)
- (let ((method (get-setf-method place cl-macro-environment))
- (n-temp (gensym "--nthcdr-n--"))
- (store-temp (gensym "--nthcdr-store--")))
- (list (cons n-temp (car method))
- (cons n (nth 1 method))
- (list store-temp)
- (list 'let (list (list (car (nth 2 method))
- (list 'cl-set-nthcdr n-temp (nth 4 method)
- store-temp)))
- (nth 3 method) store-temp)
- (list 'nthcdr n-temp (nth 4 method)))))
-
-(define-setf-method getf (place tag &optional def)
- (let ((method (get-setf-method place cl-macro-environment))
- (tag-temp (gensym "--getf-tag--"))
- (def-temp (gensym "--getf-def--"))
- (store-temp (gensym "--getf-store--")))
- (list (append (car method) (list tag-temp def-temp))
- (append (nth 1 method) (list tag def))
- (list store-temp)
- (list 'let (list (list (car (nth 2 method))
- (list 'cl-set-getf (nth 4 method)
- tag-temp store-temp)))
- (nth 3 method) store-temp)
- (list 'getf (nth 4 method) tag-temp def-temp))))
-
-(define-setf-method substring (place from &optional to)
- (let ((method (get-setf-method place cl-macro-environment))
- (from-temp (gensym "--substring-from--"))
- (to-temp (gensym "--substring-to--"))
- (store-temp (gensym "--substring-store--")))
- (list (append (car method) (list from-temp to-temp))
- (append (nth 1 method) (list from to))
- (list store-temp)
- (list 'let (list (list (car (nth 2 method))
- (list 'cl-set-substring (nth 4 method)
- from-temp to-temp store-temp)))
- (nth 3 method) store-temp)
- (list 'substring (nth 4 method) from-temp to-temp))))
-
-;;; Getting and optimizing setf-methods.
-(defun get-setf-method (place &optional env)
- "Return a list of five values describing the setf-method for PLACE.
-PLACE may be any Lisp form which can appear as the PLACE argument to
-a macro like `setf' or `incf'."
- (if (symbolp place)
- (let ((temp (gensym "--setf--")))
- (list nil nil (list temp) (list 'setq place temp) place))
- (or (and (symbolp (car place))
- (let* ((func (car place))
- (name (symbol-name func))
- (method (get func 'setf-method))
- (case-fold-search nil))
- (or (and method
- (let ((cl-macro-environment env))
- (setq method (apply method (cdr place))))
- (if (and (consp method) (= (length method) 5))
- method
- (error "Setf-method for %s returns malformed method"
- func)))
- (and (save-match-data
- (string-match "\\`c[ad][ad][ad]?[ad]?r\\'" name))
- (get-setf-method (compiler-macroexpand place)))
- (and (eq func 'edebug-after)
- (get-setf-method (nth (1- (length place)) place)
- env)))))
- (if (eq place (setq place (macroexpand place env)))
- (if (and (symbolp (car place)) (fboundp (car place))
- (symbolp (symbol-function (car place))))
- (get-setf-method (cons (symbol-function (car place))
- (cdr place)) env)
- (error "No setf-method known for %s" (car place)))
- (get-setf-method place env)))))
-
-(defun cl-setf-do-modify (place opt-expr)
- (let* ((method (get-setf-method place cl-macro-environment))
- (temps (car method)) (values (nth 1 method))
- (lets nil) (subs nil)
- (optimize (and (not (eq opt-expr 'no-opt))
- (or (and (not (eq opt-expr 'unsafe))
- (cl-safe-expr-p opt-expr))
- (cl-setf-simple-store-p (car (nth 2 method))
- (nth 3 method)))))
- (simple (and optimize (consp place) (cl-simple-exprs-p (cdr place)))))
- (while values
- (if (or simple (cl-const-expr-p (car values)))
- (cl-push (cons (cl-pop temps) (cl-pop values)) subs)
- (cl-push (list (cl-pop temps) (cl-pop values)) lets)))
- (list (nreverse lets)
- (cons (car (nth 2 method)) (sublis subs (nth 3 method)))
- (sublis subs (nth 4 method)))))
-
-(defun cl-setf-do-store (spec val)
- (let ((sym (car spec))
- (form (cdr spec)))
- (if (or (cl-const-expr-p val)
- (and (cl-simple-expr-p val) (eq (cl-expr-contains form sym) 1))
- (cl-setf-simple-store-p sym form))
- (subst val sym form)
- (list 'let (list (list sym val)) form))))
-
-(defun cl-setf-simple-store-p (sym form)
- (and (consp form) (eq (cl-expr-contains form sym) 1)
- (eq (nth (1- (length form)) form) sym)
- (symbolp (car form)) (fboundp (car form))
- (not (eq (car-safe (symbol-function (car form))) 'macro))))
-
-;;; The standard modify macros.
-(defmacro setf (&rest args)
- "(setf PLACE VAL PLACE VAL ...): set each PLACE to the value of its VAL.
-This is a generalized version of `setq'; the PLACEs may be symbolic
-references such as (car x) or (aref x i), as well as plain symbols.
-For example, (setf (cadar x) y) is equivalent to (setcar (cdar x) y).
-The return value is the last VAL in the list."
- (if (cdr (cdr args))
- (let ((sets nil))
- (while args (cl-push (list 'setf (cl-pop args) (cl-pop args)) sets))
- (cons 'progn (nreverse sets)))
- (if (symbolp (car args))
- (and args (cons 'setq args))
- (let* ((method (cl-setf-do-modify (car args) (nth 1 args)))
- (store (cl-setf-do-store (nth 1 method) (nth 1 args))))
- (if (car method) (list 'let* (car method) store) store)))))
-
-(defmacro psetf (&rest args)
- "(psetf PLACE VAL PLACE VAL ...): set PLACEs to the values VALs in parallel.
-This is like `setf', except that all VAL forms are evaluated (in order)
-before assigning any PLACEs to the corresponding values."
- (let ((p args) (simple t) (vars nil))
- (while p
- (if (or (not (symbolp (car p))) (cl-expr-depends-p (nth 1 p) vars))
- (setq simple nil))
- (if (memq (car p) vars)
- (error "Destination duplicated in psetf: %s" (car p)))
- (cl-push (cl-pop p) vars)
- (or p (error "Odd number of arguments to psetf"))
- (cl-pop p))
- (if simple
- (list 'progn (cons 'setf args) nil)
- (setq args (reverse args))
- (let ((expr (list 'setf (cadr args) (car args))))
- (while (setq args (cddr args))
- (setq expr (list 'setf (cadr args) (list 'prog1 (car args) expr))))
- (list 'progn expr nil)))))
-
-(defun cl-do-pop (place)
- (if (cl-simple-expr-p place)
- (list 'prog1 (list 'car place) (list 'setf place (list 'cdr place)))
- (let* ((method (cl-setf-do-modify place t))
- (temp (gensym "--pop--")))
- (list 'let*
- (append (car method)
- (list (list temp (nth 2 method))))
- (list 'prog1
- (list 'car temp)
- (cl-setf-do-store (nth 1 method) (list 'cdr temp)))))))
-
-(defmacro remf (place tag)
- "(remf PLACE TAG): remove TAG from property list PLACE.
-PLACE may be a symbol, or any generalized variable allowed by `setf'.
-The form returns true if TAG was found and removed, nil otherwise."
- (let* ((method (cl-setf-do-modify place t))
- (tag-temp (and (not (cl-const-expr-p tag)) (gensym "--remf-tag--")))
- (val-temp (and (not (cl-simple-expr-p place))
- (gensym "--remf-place--")))
- (ttag (or tag-temp tag))
- (tval (or val-temp (nth 2 method))))
- (list 'let*
- (append (car method)
- (and val-temp (list (list val-temp (nth 2 method))))
- (and tag-temp (list (list tag-temp tag))))
- (list 'if (list 'eq ttag (list 'car tval))
- (list 'progn
- (cl-setf-do-store (nth 1 method) (list 'cddr tval))
- t)
- (list 'cl-do-remf tval ttag)))))
-
-(defmacro shiftf (place &rest args)
- "(shiftf PLACE PLACE... VAL): shift left among PLACEs.
-Example: (shiftf A B C) sets A to B, B to C, and returns the old A.
-Each PLACE may be a symbol, or any generalized variable allowed by `setf'."
- (if (not (memq nil (mapcar 'symbolp (butlast (cons place args)))))
- (list* 'prog1 place
- (let ((sets nil))
- (while args
- (cl-push (list 'setq place (car args)) sets)
- (setq place (cl-pop args)))
- (nreverse sets)))
- (let* ((places (reverse (cons place args)))
- (form (cl-pop places)))
- (while places
- (let ((method (cl-setf-do-modify (cl-pop places) 'unsafe)))
- (setq form (list 'let* (car method)
- (list 'prog1 (nth 2 method)
- (cl-setf-do-store (nth 1 method) form))))))
- form)))
-
-(defmacro rotatef (&rest args)
- "(rotatef PLACE...): rotate left among PLACEs.
-Example: (rotatef A B C) sets A to B, B to C, and C to A. It returns nil.
-Each PLACE may be a symbol, or any generalized variable allowed by `setf'."
- (if (not (memq nil (mapcar 'symbolp args)))
- (and (cdr args)
- (let ((sets nil)
- (first (car args)))
- (while (cdr args)
- (setq sets (nconc sets (list (cl-pop args) (car args)))))
- (nconc (list 'psetf) sets (list (car args) first))))
- (let* ((places (reverse args))
- (temp (gensym "--rotatef--"))
- (form temp))
- (while (cdr places)
- (let ((method (cl-setf-do-modify (cl-pop places) 'unsafe)))
- (setq form (list 'let* (car method)
- (list 'prog1 (nth 2 method)
- (cl-setf-do-store (nth 1 method) form))))))
- (let ((method (cl-setf-do-modify (car places) 'unsafe)))
- (list 'let* (append (car method) (list (list temp (nth 2 method))))
- (cl-setf-do-store (nth 1 method) form) nil)))))
-
-(defmacro letf (bindings &rest body)
- "(letf ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs.
-This is the analogue of `let', but with generalized variables (in the
-sense of `setf') for the PLACEs. Each PLACE is set to the corresponding
-VALUE, then the BODY forms are executed. On exit, either normally or
-because of a `throw' or error, the PLACEs are set back to their original
-values. Note that this macro is *not* available in Common Lisp.
-As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)',
-the PLACE is not modified before executing BODY."
- (if (and (not (cdr bindings)) (cdar bindings) (symbolp (caar bindings)))
- (list* 'let bindings body)
- (let ((lets nil) (sets nil)
- (unsets nil) (rev (reverse bindings)))
- (while rev
- (let* ((place (if (symbolp (caar rev))
- (list 'symbol-value (list 'quote (caar rev)))
- (caar rev)))
- (value (cadar rev))
- (method (cl-setf-do-modify place 'no-opt))
- (save (gensym "--letf-save--"))
- (bound (and (memq (car place) '(symbol-value symbol-function))
- (gensym "--letf-bound--")))
- (temp (and (not (cl-const-expr-p value)) (cdr bindings)
- (gensym "--letf-val--"))))
- (setq lets (nconc (car method)
- (if bound
- (list (list bound
- (list (if (eq (car place)
- 'symbol-value)
- 'boundp 'fboundp)
- (nth 1 (nth 2 method))))
- (list save (list 'and bound
- (nth 2 method))))
- (list (list save (nth 2 method))))
- (and temp (list (list temp value)))
- lets)
- body (list
- (list 'unwind-protect
- (cons 'progn
- (if (cdr (car rev))
- (cons (cl-setf-do-store (nth 1 method)
- (or temp value))
- body)
- body))
- (if bound
- (list 'if bound
- (cl-setf-do-store (nth 1 method) save)
- (list (if (eq (car place) 'symbol-value)
- 'makunbound 'fmakunbound)
- (nth 1 (nth 2 method))))
- (cl-setf-do-store (nth 1 method) save))))
- rev (cdr rev))))
- (list* 'let* lets body))))
-
-(defmacro letf* (bindings &rest body)
- "(letf* ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs.
-This is the analogue of `let*', but with generalized variables (in the
-sense of `setf') for the PLACEs. Each PLACE is set to the corresponding
-VALUE, then the BODY forms are executed. On exit, either normally or
-because of a `throw' or error, the PLACEs are set back to their original
-values. Note that this macro is *not* available in Common Lisp.
-As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)',
-the PLACE is not modified before executing BODY."
- (if (null bindings)
- (cons 'progn body)
- (setq bindings (reverse bindings))
- (while bindings
- (setq body (list (list* 'letf (list (cl-pop bindings)) body))))
- (car body)))
-
-(defmacro callf (func place &rest args)
- "(callf FUNC PLACE ARGS...): set PLACE to (FUNC PLACE ARGS...).
-FUNC should be an unquoted function name. PLACE may be a symbol,
-or any generalized variable allowed by `setf'."
- (let* ((method (cl-setf-do-modify place (cons 'list args)))
- (rargs (cons (nth 2 method) args)))
- (list 'let* (car method)
- (cl-setf-do-store (nth 1 method)
- (if (symbolp func) (cons func rargs)
- (list* 'funcall (list 'function func)
- rargs))))))
-
-(defmacro callf2 (func arg1 place &rest args)
- "(callf2 FUNC ARG1 PLACE ARGS...): set PLACE to (FUNC ARG1 PLACE ARGS...).
-Like `callf', but PLACE is the second argument of FUNC, not the first."
- (if (and (cl-safe-expr-p arg1) (cl-simple-expr-p place) (symbolp func))
- (list 'setf place (list* func arg1 place args))
- (let* ((method (cl-setf-do-modify place (cons 'list args)))
- (temp (and (not (cl-const-expr-p arg1)) (gensym "--arg1--")))
- (rargs (list* (or temp arg1) (nth 2 method) args)))
- (list 'let* (append (and temp (list (list temp arg1))) (car method))
- (cl-setf-do-store (nth 1 method)
- (if (symbolp func) (cons func rargs)
- (list* 'funcall (list 'function func)
- rargs)))))))
-
-(defmacro define-modify-macro (name arglist func &optional doc)
- "(define-modify-macro NAME ARGLIST FUNC): define a `setf'-like modify macro.
-If NAME is called, it combines its PLACE argument with the other arguments
-from ARGLIST using FUNC: (define-modify-macro incf (&optional (n 1)) +)"
- (if (memq '&key arglist) (error "&key not allowed in define-modify-macro"))
- (let ((place (gensym "--place--")))
- (list 'defmacro* name (cons place arglist) doc
- (list* (if (memq '&rest arglist) 'list* 'list)
- '(quote callf) (list 'quote func) place
- (cl-arglist-args arglist)))))
-
-
-;;; Structures.
-
-(defmacro defstruct (struct &rest descs)
- "(defstruct (NAME OPTIONS...) (SLOT SLOT-OPTS...)...): define a struct type.
-This macro defines a new Lisp data type called NAME, which contains data
-stored in SLOTs. This defines a `make-NAME' constructor, a `copy-NAME'
-copier, a `NAME-p' predicate, and setf-able `NAME-SLOT' accessors."
- (let* ((name (if (consp struct) (car struct) struct))
- (opts (cdr-safe struct))
- (slots nil)
- (defaults nil)
- (conc-name (concat (symbol-name name) "-"))
- (constructor (intern (format "make-%s" name)))
- (constrs nil)
- (copier (intern (format "copy-%s" name)))
- (predicate (intern (format "%s-p" name)))
- (print-func nil) (print-auto nil)
- (safety (if (cl-compiling-file) cl-optimize-safety 3))
- (include nil)
- (tag (intern (format "cl-struct-%s" name)))
- (tag-symbol (intern (format "cl-struct-%s-tags" name)))
- (include-descs nil)
- (side-eff nil)
- (type nil)
- (named nil)
- (forms nil)
- pred-form pred-check)
- (if (stringp (car descs))
- (cl-push (list 'put (list 'quote name) '(quote structure-documentation)
- (cl-pop descs)) forms))
- (setq descs (cons '(cl-tag-slot)
- (mapcar (function (lambda (x) (if (consp x) x (list x))))
- descs)))
- (while opts
- (let ((opt (if (consp (car opts)) (caar opts) (car opts)))
- (args (cdr-safe (cl-pop opts))))
- (cond ((eq opt ':conc-name)
- (if args
- (setq conc-name (if (car args)
- (symbol-name (car args)) ""))))
- ((eq opt ':constructor)
- (if (cdr args)
- (cl-push args constrs)
- (if args (setq constructor (car args)))))
- ((eq opt ':copier)
- (if args (setq copier (car args))))
- ((eq opt ':predicate)
- (if args (setq predicate (car args))))
- ((eq opt ':include)
- (setq include (car args)
- include-descs (mapcar (function
- (lambda (x)
- (if (consp x) x (list x))))
- (cdr args))))
- ((eq opt ':print-function)
- (setq print-func (car args)))
- ((eq opt ':type)
- (setq type (car args)))
- ((eq opt ':named)
- (setq named t))
- ((eq opt ':initial-offset)
- (setq descs (nconc (make-list (car args) '(cl-skip-slot))
- descs)))
- (t
- (error "Slot option %s unrecognized" opt)))))
- (if print-func
- (setq print-func (list 'progn
- (list 'funcall (list 'function print-func)
- 'cl-x 'cl-s 'cl-n) t))
- (or type (and include (not (get include 'cl-struct-print)))
- (setq print-auto t
- print-func (and (or (not (or include type)) (null print-func))
- (list 'progn
- (list 'princ (format "#S(%s" name)
- 'cl-s))))))
- (if include
- (let ((inc-type (get include 'cl-struct-type))
- (old-descs (get include 'cl-struct-slots)))
- (or inc-type (error "%s is not a struct name" include))
- (and type (not (eq (car inc-type) type))
- (error ":type disagrees with :include for %s" name))
- (while include-descs
- (setcar (memq (or (assq (caar include-descs) old-descs)
- (error "No slot %s in included struct %s"
- (caar include-descs) include))
- old-descs)
- (cl-pop include-descs)))
- (setq descs (append old-descs (delq (assq 'cl-tag-slot descs) descs))
- type (car inc-type)
- named (assq 'cl-tag-slot descs))
- (if (cadr inc-type) (setq tag name named t))
- (let ((incl include))
- (while incl
- (cl-push (list 'pushnew (list 'quote tag)
- (intern (format "cl-struct-%s-tags" incl)))
- forms)
- (setq incl (get incl 'cl-struct-include)))))
- (if type
- (progn
- (or (memq type '(vector list))
- (error "Illegal :type specifier: %s" type))
- (if named (setq tag name)))
- (setq type 'vector named 'true)))
- (or named (setq descs (delq (assq 'cl-tag-slot descs) descs)))
- (cl-push (list 'defvar tag-symbol) forms)
- (setq pred-form (and named
- (let ((pos (- (length descs)
- (length (memq (assq 'cl-tag-slot descs)
- descs)))))
- (if (eq type 'vector)
- (list 'and '(vectorp cl-x)
- (list '>= '(length cl-x) (length descs))
- (list 'memq (list 'aref 'cl-x pos)
- tag-symbol))
- (if (= pos 0)
- (list 'memq '(car-safe cl-x) tag-symbol)
- (list 'and '(consp cl-x)
- (list 'memq (list 'nth pos 'cl-x)
- tag-symbol))))))
- pred-check (and pred-form (> safety 0)
- (if (and (eq (caadr pred-form) 'vectorp)
- (= safety 1))
- (cons 'and (cdddr pred-form)) pred-form)))
- (let ((pos 0) (descp descs))
- (while descp
- (let* ((desc (cl-pop descp))
- (slot (car desc)))
- (if (memq slot '(cl-tag-slot cl-skip-slot))
- (progn
- (cl-push nil slots)
- (cl-push (and (eq slot 'cl-tag-slot) (list 'quote tag))
- defaults))
- (if (assq slot descp)
- (error "Duplicate slots named %s in %s" slot name))
- (let ((accessor (intern (format "%s%s" conc-name slot))))
- (cl-push slot slots)
- (cl-push (nth 1 desc) defaults)
- (cl-push (list*
- 'defsubst* accessor '(cl-x)
- (append
- (and pred-check
- (list (list 'or pred-check
- (list 'error
- (format "%s accessing a non-%s"
- accessor name)
- 'cl-x))))
- (list (if (eq type 'vector) (list 'aref 'cl-x pos)
- (if (= pos 0) '(car cl-x)
- (list 'nth pos 'cl-x)))))) forms)
- (cl-push (cons accessor t) side-eff)
- (cl-push (list 'define-setf-method accessor '(cl-x)
- (if (cadr (memq ':read-only (cddr desc)))
- (list 'error (format "%s is a read-only slot"
- accessor))
- (list 'cl-struct-setf-expander 'cl-x
- (list 'quote name) (list 'quote accessor)
- (and pred-check (list 'quote pred-check))
- pos)))
- forms)
- (if print-auto
- (nconc print-func
- (list (list 'princ (format " %s" slot) 'cl-s)
- (list 'prin1 (list accessor 'cl-x) 'cl-s)))))))
- (setq pos (1+ pos))))
- (setq slots (nreverse slots)
- defaults (nreverse defaults))
- (and predicate pred-form
- (progn (cl-push (list 'defsubst* predicate '(cl-x)
- (if (eq (car pred-form) 'and)
- (append pred-form '(t))
- (list 'and pred-form t))) forms)
- (cl-push (cons predicate 'error-free) side-eff)))
- (and copier
- (progn (cl-push (list 'defun copier '(x) '(copy-sequence x)) forms)
- (cl-push (cons copier t) side-eff)))
- (if constructor
- (cl-push (list constructor
- (cons '&key (delq nil (copy-sequence slots))))
- constrs))
- (while constrs
- (let* ((name (caar constrs))
- (args (cadr (cl-pop constrs)))
- (anames (cl-arglist-args args))
- (make (mapcar* (function (lambda (s d) (if (memq s anames) s d)))
- slots defaults)))
- (cl-push (list 'defsubst* name
- (list* '&cl-defs (list 'quote (cons nil descs)) args)
- (cons type make)) forms)
- (if (cl-safe-expr-p (cons 'progn (mapcar 'second descs)))
- (cl-push (cons name t) side-eff))))
- (if print-auto (nconc print-func (list '(princ ")" cl-s) t)))
- (if print-func
- (cl-push (list 'push
- (list 'function
- (list 'lambda '(cl-x cl-s cl-n)
- (list 'and pred-form print-func)))
- 'custom-print-functions) forms))
- (cl-push (list 'setq tag-symbol (list 'list (list 'quote tag))) forms)
- (cl-push (list* 'eval-when '(compile load eval)
- (list 'put (list 'quote name) '(quote cl-struct-slots)
- (list 'quote descs))
- (list 'put (list 'quote name) '(quote cl-struct-type)
- (list 'quote (list type (eq named t))))
- (list 'put (list 'quote name) '(quote cl-struct-include)
- (list 'quote include))
- (list 'put (list 'quote name) '(quote cl-struct-print)
- print-auto)
- (mapcar (function (lambda (x)
- (list 'put (list 'quote (car x))
- '(quote side-effect-free)
- (list 'quote (cdr x)))))
- side-eff))
- forms)
- (cons 'progn (nreverse (cons (list 'quote name) forms)))))
-
-(defun cl-struct-setf-expander (x name accessor pred-form pos)
- (let* ((temp (gensym "--x--")) (store (gensym "--store--")))
- (list (list temp) (list x) (list store)
- (append '(progn)
- (and pred-form
- (list (list 'or (subst temp 'cl-x pred-form)
- (list 'error
- (format
- "%s storing a non-%s" accessor name)
- temp))))
- (list (if (eq (car (get name 'cl-struct-type)) 'vector)
- (list 'aset temp pos store)
- (list 'setcar
- (if (<= pos 5)
- (let ((xx temp))
- (while (>= (setq pos (1- pos)) 0)
- (setq xx (list 'cdr xx)))
- xx)
- (list 'nthcdr pos temp))
- store))))
- (list accessor temp))))
-
-
-;;; Types and assertions.
-
-(defmacro deftype (name args &rest body)
- "(deftype NAME ARGLIST BODY...): define NAME as a new data type.
-The type name can then be used in `typecase', `check-type', etc."
- (list 'eval-when '(compile load eval)
- (cl-transform-function-property
- name 'cl-deftype-handler (cons (list* '&cl-defs ''('*) args) body))))
-
-(defun cl-make-type-test (val type)
- (if (memq type '(character string-char)) (setq type '(integer 0 255)))
- (if (symbolp type)
- (cond ((get type 'cl-deftype-handler)
- (cl-make-type-test val (funcall (get type 'cl-deftype-handler))))
- ((memq type '(nil t)) type)
- ((eq type 'null) (list 'null val))
- ((eq type 'float) (list 'floatp-safe val))
- ((eq type 'real) (list 'numberp val))
- ((eq type 'fixnum) (list 'integerp val))
- (t
- (let* ((name (symbol-name type))
- (namep (intern (concat name "p"))))
- (if (fboundp namep) (list namep val)
- (list (intern (concat name "-p")) val)))))
- (cond ((get (car type) 'cl-deftype-handler)
- (cl-make-type-test val (apply (get (car type) 'cl-deftype-handler)
- (cdr type))))
- ((memq (car-safe type) '(integer float real number))
- (delq t (list 'and (cl-make-type-test val (car type))
- (if (memq (cadr type) '(* nil)) t
- (if (consp (cadr type)) (list '> val (caadr type))
- (list '>= val (cadr type))))
- (if (memq (caddr type) '(* nil)) t
- (if (consp (caddr type)) (list '< val (caaddr type))
- (list '<= val (caddr type)))))))
- ((memq (car-safe type) '(and or not))
- (cons (car type)
- (mapcar (function (lambda (x) (cl-make-type-test val x)))
- (cdr type))))
- ((memq (car-safe type) '(member member*))
- (list 'and (list 'member* val (list 'quote (cdr type))) t))
- ((eq (car-safe type) 'satisfies) (list (cadr type) val))
- (t (error "Bad type spec: %s" type)))))
-
-(defun typep (val type) ; See compiler macro below.
- "Check that OBJECT is of type TYPE.
-TYPE is a Common Lisp-style type specifier."
- (eval (cl-make-type-test 'val type)))
-
-(defmacro check-type (form type &optional string)
- "Verify that FORM is of type TYPE; signal an error if not.
-STRING is an optional description of the desired type."
- (and (or (not (cl-compiling-file))
- (< cl-optimize-speed 3) (= cl-optimize-safety 3))
- (let* ((temp (if (cl-simple-expr-p form 3) form (gensym)))
- (body (list 'or (cl-make-type-test temp type)
- (list 'signal '(quote wrong-type-argument)
- (list 'list (or string (list 'quote type))
- temp (list 'quote form))))))
- (if (eq temp form) (list 'progn body nil)
- (list 'let (list (list temp form)) body nil)))))
-
-(defmacro assert (form &optional show-args string &rest args)
- "Verify that FORM returns non-nil; signal an error if not.
-Second arg SHOW-ARGS means to include arguments of FORM in message.
-Other args STRING and ARGS... are arguments to be passed to `error'.
-They are not evaluated unless the assertion fails. If STRING is
-omitted, a default message listing FORM itself is used."
- (and (or (not (cl-compiling-file))
- (< cl-optimize-speed 3) (= cl-optimize-safety 3))
- (let ((sargs (and show-args (delq nil (mapcar
- (function
- (lambda (x)
- (and (not (cl-const-expr-p x))
- x))) (cdr form))))))
- (list 'progn
- (list 'or form
- (if string
- (list* 'error string (append sargs args))
- (list 'signal '(quote cl-assertion-failed)
- (list* 'list (list 'quote form) sargs))))
- nil))))
-
-(defmacro ignore-errors (&rest body)
- "Execute FORMS; if an error occurs, return nil.
-Otherwise, return result of last FORM."
- (let ((err (gensym)))
- (list 'condition-case err (cons 'progn body) '(error nil))))
-
-
-;;; Some predicates for analyzing Lisp forms. These are used by various
-;;; macro expanders to optimize the results in certain common cases.
-
-(defconst cl-simple-funcs '(car cdr nth aref elt if and or + - 1+ 1- min max
- car-safe cdr-safe progn prog1 prog2))
-(defconst cl-safe-funcs '(* / % length memq list vector vectorp
- < > <= >= = error))
-
-;;; Check if no side effects, and executes quickly.
-(defun cl-simple-expr-p (x &optional size)
- (or size (setq size 10))
- (if (and (consp x) (not (memq (car x) '(quote function function*))))
- (and (symbolp (car x))
- (or (memq (car x) cl-simple-funcs)
- (get (car x) 'side-effect-free))
- (progn
- (setq size (1- size))
- (while (and (setq x (cdr x))
- (setq size (cl-simple-expr-p (car x) size))))
- (and (null x) (>= size 0) size)))
- (and (> size 0) (1- size))))
-
-(defun cl-simple-exprs-p (xs)
- (while (and xs (cl-simple-expr-p (car xs)))
- (setq xs (cdr xs)))
- (not xs))
-
-;;; Check if no side effects.
-(defun cl-safe-expr-p (x)
- (or (not (and (consp x) (not (memq (car x) '(quote function function*)))))
- (and (symbolp (car x))
- (or (memq (car x) cl-simple-funcs)
- (memq (car x) cl-safe-funcs)
- (get (car x) 'side-effect-free))
- (progn
- (while (and (setq x (cdr x)) (cl-safe-expr-p (car x))))
- (null x)))))
-
-;;; Check if constant (i.e., no side effects or dependencies).
-(defun cl-const-expr-p (x)
- (cond ((consp x)
- (or (eq (car x) 'quote)
- (and (memq (car x) '(function function*))
- (or (symbolp (nth 1 x))
- (and (eq (car-safe (nth 1 x)) 'lambda) 'func)))))
- ((symbolp x) (and (memq x '(nil t)) t))
- (t t)))
-
-(defun cl-const-exprs-p (xs)
- (while (and xs (cl-const-expr-p (car xs)))
- (setq xs (cdr xs)))
- (not xs))
-
-(defun cl-const-expr-val (x)
- (and (eq (cl-const-expr-p x) t) (if (consp x) (nth 1 x) x)))
-
-(defun cl-expr-access-order (x v)
- (if (cl-const-expr-p x) v
- (if (consp x)
- (progn
- (while (setq x (cdr x)) (setq v (cl-expr-access-order (car x) v)))
- v)
- (if (eq x (car v)) (cdr v) '(t)))))
-
-;;; Count number of times X refers to Y. Return NIL for 0 times.
-(defun cl-expr-contains (x y)
- (cond ((equal y x) 1)
- ((and (consp x) (not (memq (car-safe x) '(quote function function*))))
- (let ((sum 0))
- (while x
- (setq sum (+ sum (or (cl-expr-contains (cl-pop x) y) 0))))
- (and (> sum 0) sum)))
- (t nil)))
-
-(defun cl-expr-contains-any (x y)
- (while (and y (not (cl-expr-contains x (car y)))) (cl-pop y))
- y)
-
-;;; Check whether X may depend on any of the symbols in Y.
-(defun cl-expr-depends-p (x y)
- (and (not (cl-const-expr-p x))
- (or (not (cl-safe-expr-p x)) (cl-expr-contains-any x y))))
-
-
-;;; Compiler macros.
-
-(defmacro define-compiler-macro (func args &rest body)
- "(define-compiler-macro FUNC ARGLIST BODY...): Define a compiler-only macro.
-This is like `defmacro', but macro expansion occurs only if the call to
-FUNC is compiled (i.e., not interpreted). Compiler macros should be used
-for optimizing the way calls to FUNC are compiled; the form returned by
-BODY should do the same thing as a call to the normal function called
-FUNC, though possibly more efficiently. Note that, like regular macros,
-compiler macros are expanded repeatedly until no further expansions are
-possible. Unlike regular macros, BODY can decide to \"punt\" and leave the
-original function call alone by declaring an initial `&whole foo' parameter
-and then returning foo."
- (let ((p (if (listp args) args (list '&rest args))) (res nil))
- (while (consp p) (cl-push (cl-pop p) res))
- (setq args (nreverse res)) (setcdr res (and p (list '&rest p))))
- (list 'eval-when '(compile load eval)
- (cl-transform-function-property
- func 'cl-compiler-macro
- (cons (if (memq '&whole args) (delq '&whole args)
- (cons '--cl-whole-arg-- args)) body))
- (list 'or (list 'get (list 'quote func) '(quote byte-compile))
- (list 'put (list 'quote func) '(quote byte-compile)
- '(quote cl-byte-compile-compiler-macro)))))
-
-(defun compiler-macroexpand (form)
- (while
- (let ((func (car-safe form)) (handler nil))
- (while (and (symbolp func)
- (not (setq handler (get func 'cl-compiler-macro)))
- (fboundp func)
- (or (not (eq (car-safe (symbol-function func)) 'autoload))
- (load (nth 1 (symbol-function func)))))
- (setq func (symbol-function func)))
- (and handler
- (not (eq form (setq form (apply handler form (cdr form))))))))
- form)
-
-(defun cl-byte-compile-compiler-macro (form)
- (if (eq form (setq form (compiler-macroexpand form)))
- (byte-compile-normal-call form)
- (byte-compile-form form)))
-
-(defmacro defsubst* (name args &rest body)
- "(defsubst* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a function.
-Like `defun', except the function is automatically declared `inline',
-ARGLIST allows full Common Lisp conventions, and BODY is implicitly
-surrounded by (block NAME ...)."
- (let* ((argns (cl-arglist-args args)) (p argns)
- (pbody (cons 'progn body))
- (unsafe (not (cl-safe-expr-p pbody))))
- (while (and p (eq (cl-expr-contains args (car p)) 1)) (cl-pop p))
- (list 'progn
- (if p nil ; give up if defaults refer to earlier args
- (list 'define-compiler-macro name
- (list* '&whole 'cl-whole '&cl-quote args)
- (list* 'cl-defsubst-expand (list 'quote argns)
- (list 'quote (list* 'block name body))
- (not (or unsafe (cl-expr-access-order pbody argns)))
- (and (memq '&key args) 'cl-whole) unsafe argns)))
- (list* 'defun* name args body))))
-
-(defun cl-defsubst-expand (argns body simple whole unsafe &rest argvs)
- (if (and whole (not (cl-safe-expr-p (cons 'progn argvs)))) whole
- (if (cl-simple-exprs-p argvs) (setq simple t))
- (let ((lets (delq nil
- (mapcar* (function
- (lambda (argn argv)
- (if (or simple (cl-const-expr-p argv))
- (progn (setq body (subst argv argn body))
- (and unsafe (list argn argv)))
- (list argn argv))))
- argns argvs))))
- (if lets (list 'let lets body) body))))
-
-
-;;; Compile-time optimizations for some functions defined in this package.
-;;; Note that cl.el arranges to force cl-macs to be loaded at compile-time,
-;;; mainly to make sure these macros will be present.
-
-(put 'eql 'byte-compile nil)
-(define-compiler-macro eql (&whole form a b)
- (cond ((eq (cl-const-expr-p a) t)
- (let ((val (cl-const-expr-val a)))
- (if (and (numberp val) (not (integerp val)))
- (list 'equal a b)
- (list 'eq a b))))
- ((eq (cl-const-expr-p b) t)
- (let ((val (cl-const-expr-val b)))
- (if (and (numberp val) (not (integerp val)))
- (list 'equal a b)
- (list 'eq a b))))
- ((cl-simple-expr-p a 5)
- (list 'if (list 'numberp a)
- (list 'equal a b)
- (list 'eq a b)))
- ((and (cl-safe-expr-p a)
- (cl-simple-expr-p b 5))
- (list 'if (list 'numberp b)
- (list 'equal a b)
- (list 'eq a b)))
- (t form)))
-
-(define-compiler-macro member* (&whole form a list &rest keys)
- (let ((test (and (= (length keys) 2) (eq (car keys) ':test)
- (cl-const-expr-val (nth 1 keys)))))
- (cond ((eq test 'eq) (list 'memq a list))
- ((eq test 'equal) (list 'member a list))
- ((or (null keys) (eq test 'eql))
- (if (eq (cl-const-expr-p a) t)
- (list (if (floatp-safe (cl-const-expr-val a)) 'member 'memq)
- a list)
- (if (eq (cl-const-expr-p list) t)
- (let ((p (cl-const-expr-val list)) (mb nil) (mq nil))
- (if (not (cdr p))
- (and p (list 'eql a (list 'quote (car p))))
- (while p
- (if (floatp-safe (car p)) (setq mb t)
- (or (integerp (car p)) (symbolp (car p)) (setq mq t)))
- (setq p (cdr p)))
- (if (not mb) (list 'memq a list)
- (if (not mq) (list 'member a list) form))))
- form)))
- (t form))))
-
-(define-compiler-macro assoc* (&whole form a list &rest keys)
- (let ((test (and (= (length keys) 2) (eq (car keys) ':test)
- (cl-const-expr-val (nth 1 keys)))))
- (cond ((eq test 'eq) (list 'assq a list))
- ((eq test 'equal) (list 'assoc a list))
- ((and (eq (cl-const-expr-p a) t) (or (null keys) (eq test 'eql)))
- (if (floatp-safe (cl-const-expr-val a))
- (list 'assoc a list) (list 'assq a list)))
- (t form))))
-
-(define-compiler-macro adjoin (&whole form a list &rest keys)
- (if (and (cl-simple-expr-p a) (cl-simple-expr-p list)
- (not (memq ':key keys)))
- (list 'if (list* 'member* a list keys) list (list 'cons a list))
- form))
-
-(define-compiler-macro list* (arg &rest others)
- (let* ((args (reverse (cons arg others)))
- (form (car args)))
- (while (setq args (cdr args))
- (setq form (list 'cons (car args) form)))
- form))
-
-(define-compiler-macro get* (sym prop &optional def)
- (if def
- (list 'getf (list 'symbol-plist sym) prop def)
- (list 'get sym prop)))
-
-(define-compiler-macro typep (&whole form val type)
- (if (cl-const-expr-p type)
- (let ((res (cl-make-type-test val (cl-const-expr-val type))))
- (if (or (memq (cl-expr-contains res val) '(nil 1))
- (cl-simple-expr-p val)) res
- (let ((temp (gensym)))
- (list 'let (list (list temp val)) (subst temp val res)))))
- form))
-
-
-(mapcar (function
- (lambda (y)
- (put (car y) 'side-effect-free t)
- (put (car y) 'byte-compile 'cl-byte-compile-compiler-macro)
- (put (car y) 'cl-compiler-macro
- (list 'lambda '(w x)
- (if (symbolp (cadr y))
- (list 'list (list 'quote (cadr y))
- (list 'list (list 'quote (caddr y)) 'x))
- (cons 'list (cdr y)))))))
- '((first 'car x) (second 'cadr x) (third 'caddr x) (fourth 'cadddr x)
- (fifth 'nth 4 x) (sixth 'nth 5 x) (seventh 'nth 6 x)
- (eighth 'nth 7 x) (ninth 'nth 8 x) (tenth 'nth 9 x)
- (rest 'cdr x) (endp 'null x) (plusp '> x 0) (minusp '< x 0)
- (caar car car) (cadr car cdr) (cdar cdr car) (cddr cdr cdr)
- (caaar car caar) (caadr car cadr) (cadar car cdar)
- (caddr car cddr) (cdaar cdr caar) (cdadr cdr cadr)
- (cddar cdr cdar) (cdddr cdr cddr) (caaaar car caaar)
- (caaadr car caadr) (caadar car cadar) (caaddr car caddr)
- (cadaar car cdaar) (cadadr car cdadr) (caddar car cddar)
- (cadddr car cdddr) (cdaaar cdr caaar) (cdaadr cdr caadr)
- (cdadar cdr cadar) (cdaddr cdr caddr) (cddaar cdr cdaar)
- (cddadr cdr cdadr) (cdddar cdr cddar) (cddddr cdr cdddr) ))
-
-;;; Things that are inline.
-(proclaim '(inline floatp-safe acons map concatenate notany notevery
- cl-set-elt revappend nreconc gethash))
-
-;;; Things that are side-effect-free.
-(mapcar (function (lambda (x) (put x 'side-effect-free t)))
- '(oddp evenp abs expt signum last butlast ldiff pairlis gcd lcm
- isqrt floor* ceiling* truncate* round* mod* rem* subseq
- list-length get* getf gethash hash-table-count))
-
-;;; Things that are side-effect-and-error-free.
-(mapcar (function (lambda (x) (put x 'side-effect-free 'error-free)))
- '(eql floatp-safe list* subst acons equalp random-state-p
- copy-tree sublis hash-table-p))
-
-
-(run-hooks 'cl-macs-load-hook)
-
-;;; cl-macs.el ends here
diff --git a/lisp/emacs-lisp/cl-seq.el b/lisp/emacs-lisp/cl-seq.el
deleted file mode 100644
index eaac88a4e22..00000000000
--- a/lisp/emacs-lisp/cl-seq.el
+++ /dev/null
@@ -1,919 +0,0 @@
-;;; cl-seq.el --- Common Lisp features, part 3 -*-byte-compile-dynamic: t;-*-
-
-;; Copyright (C) 1993 Free Software Foundation, Inc.
-
-;; Author: Dave Gillespie <daveg@synaptics.com>
-;; Version: 2.02
-;; Keywords: extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; These are extensions to Emacs Lisp that provide a degree of
-;; Common Lisp compatibility, beyond what is already built-in
-;; in Emacs Lisp.
-;;
-;; This package was written by Dave Gillespie; it is a complete
-;; rewrite of Cesar Quiroz's original cl.el package of December 1986.
-;;
-;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19.
-;;
-;; Bug reports, comments, and suggestions are welcome!
-
-;; This file contains the Common Lisp sequence and list functions
-;; which take keyword arguments.
-
-;; See cl.el for Change Log.
-
-
-;;; Code:
-
-(or (memq 'cl-19 features)
- (error "Tried to load `cl-seq' before `cl'!"))
-
-
-;;; We define these here so that this file can compile without having
-;;; loaded the cl.el file already.
-
-(defmacro cl-push (x place) (list 'setq place (list 'cons x place)))
-(defmacro cl-pop (place)
- (list 'car (list 'prog1 place (list 'setq place (list 'cdr place)))))
-
-
-;;; Keyword parsing. This is special-cased here so that we can compile
-;;; this file independent from cl-macs.
-
-(defmacro cl-parsing-keywords (kwords other-keys &rest body)
- (cons
- 'let*
- (cons (mapcar
- (function
- (lambda (x)
- (let* ((var (if (consp x) (car x) x))
- (mem (list 'car (list 'cdr (list 'memq (list 'quote var)
- 'cl-keys)))))
- (if (eq var ':test-not)
- (setq mem (list 'and mem (list 'setq 'cl-test mem) t)))
- (if (eq var ':if-not)
- (setq mem (list 'and mem (list 'setq 'cl-if mem) t)))
- (list (intern
- (format "cl-%s" (substring (symbol-name var) 1)))
- (if (consp x) (list 'or mem (car (cdr x))) mem)))))
- kwords)
- (append
- (and (not (eq other-keys t))
- (list
- (list 'let '((cl-keys-temp cl-keys))
- (list 'while 'cl-keys-temp
- (list 'or (list 'memq '(car cl-keys-temp)
- (list 'quote
- (mapcar
- (function
- (lambda (x)
- (if (consp x)
- (car x) x)))
- (append kwords
- other-keys))))
- '(car (cdr (memq (quote :allow-other-keys)
- cl-keys)))
- '(error "Bad keyword argument %s"
- (car cl-keys-temp)))
- '(setq cl-keys-temp (cdr (cdr cl-keys-temp)))))))
- body))))
-(put 'cl-parsing-keywords 'lisp-indent-function 2)
-(put 'cl-parsing-keywords 'edebug-form-spec '(sexp sexp &rest form))
-
-(defmacro cl-check-key (x)
- (list 'if 'cl-key (list 'funcall 'cl-key x) x))
-
-(defmacro cl-check-test-nokey (item x)
- (list 'cond
- (list 'cl-test
- (list 'eq (list 'not (list 'funcall 'cl-test item x))
- 'cl-test-not))
- (list 'cl-if
- (list 'eq (list 'not (list 'funcall 'cl-if x)) 'cl-if-not))
- (list 't (list 'if (list 'numberp item)
- (list 'equal item x) (list 'eq item x)))))
-
-(defmacro cl-check-test (item x)
- (list 'cl-check-test-nokey item (list 'cl-check-key x)))
-
-(defmacro cl-check-match (x y)
- (setq x (list 'cl-check-key x) y (list 'cl-check-key y))
- (list 'if 'cl-test
- (list 'eq (list 'not (list 'funcall 'cl-test x y)) 'cl-test-not)
- (list 'if (list 'numberp x)
- (list 'equal x y) (list 'eq x y))))
-
-(put 'cl-check-key 'edebug-form-spec 'edebug-forms)
-(put 'cl-check-test 'edebug-form-spec 'edebug-forms)
-(put 'cl-check-test-nokey 'edebug-form-spec 'edebug-forms)
-(put 'cl-check-match 'edebug-form-spec 'edebug-forms)
-
-(defvar cl-test) (defvar cl-test-not)
-(defvar cl-if) (defvar cl-if-not)
-(defvar cl-key)
-
-
-(defun reduce (cl-func cl-seq &rest cl-keys)
- "Reduce two-argument FUNCTION across SEQUENCE.
-Keywords supported: :start :end :from-end :initial-value :key"
- (cl-parsing-keywords (:from-end (:start 0) :end :initial-value :key) ()
- (or (listp cl-seq) (setq cl-seq (append cl-seq nil)))
- (setq cl-seq (subseq cl-seq cl-start cl-end))
- (if cl-from-end (setq cl-seq (nreverse cl-seq)))
- (let ((cl-accum (cond ((memq ':initial-value cl-keys) cl-initial-value)
- (cl-seq (cl-check-key (cl-pop cl-seq)))
- (t (funcall cl-func)))))
- (if cl-from-end
- (while cl-seq
- (setq cl-accum (funcall cl-func (cl-check-key (cl-pop cl-seq))
- cl-accum)))
- (while cl-seq
- (setq cl-accum (funcall cl-func cl-accum
- (cl-check-key (cl-pop cl-seq))))))
- cl-accum)))
-
-(defun fill (seq item &rest cl-keys)
- "Fill the elements of SEQ with ITEM.
-Keywords supported: :start :end"
- (cl-parsing-keywords ((:start 0) :end) ()
- (if (listp seq)
- (let ((p (nthcdr cl-start seq))
- (n (if cl-end (- cl-end cl-start) 8000000)))
- (while (and p (>= (setq n (1- n)) 0))
- (setcar p item)
- (setq p (cdr p))))
- (or cl-end (setq cl-end (length seq)))
- (if (and (= cl-start 0) (= cl-end (length seq)))
- (fillarray seq item)
- (while (< cl-start cl-end)
- (aset seq cl-start item)
- (setq cl-start (1+ cl-start)))))
- seq))
-
-(defun replace (cl-seq1 cl-seq2 &rest cl-keys)
- "Replace the elements of SEQ1 with the elements of SEQ2.
-SEQ1 is destructively modified, then returned.
-Keywords supported: :start1 :end1 :start2 :end2"
- (cl-parsing-keywords ((:start1 0) :end1 (:start2 0) :end2) ()
- (if (and (eq cl-seq1 cl-seq2) (<= cl-start2 cl-start1))
- (or (= cl-start1 cl-start2)
- (let* ((cl-len (length cl-seq1))
- (cl-n (min (- (or cl-end1 cl-len) cl-start1)
- (- (or cl-end2 cl-len) cl-start2))))
- (while (>= (setq cl-n (1- cl-n)) 0)
- (cl-set-elt cl-seq1 (+ cl-start1 cl-n)
- (elt cl-seq2 (+ cl-start2 cl-n))))))
- (if (listp cl-seq1)
- (let ((cl-p1 (nthcdr cl-start1 cl-seq1))
- (cl-n1 (if cl-end1 (- cl-end1 cl-start1) 4000000)))
- (if (listp cl-seq2)
- (let ((cl-p2 (nthcdr cl-start2 cl-seq2))
- (cl-n (min cl-n1
- (if cl-end2 (- cl-end2 cl-start2) 4000000))))
- (while (and cl-p1 cl-p2 (>= (setq cl-n (1- cl-n)) 0))
- (setcar cl-p1 (car cl-p2))
- (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2))))
- (setq cl-end2 (min (or cl-end2 (length cl-seq2))
- (+ cl-start2 cl-n1)))
- (while (and cl-p1 (< cl-start2 cl-end2))
- (setcar cl-p1 (aref cl-seq2 cl-start2))
- (setq cl-p1 (cdr cl-p1) cl-start2 (1+ cl-start2)))))
- (setq cl-end1 (min (or cl-end1 (length cl-seq1))
- (+ cl-start1 (- (or cl-end2 (length cl-seq2))
- cl-start2))))
- (if (listp cl-seq2)
- (let ((cl-p2 (nthcdr cl-start2 cl-seq2)))
- (while (< cl-start1 cl-end1)
- (aset cl-seq1 cl-start1 (car cl-p2))
- (setq cl-p2 (cdr cl-p2) cl-start1 (1+ cl-start1))))
- (while (< cl-start1 cl-end1)
- (aset cl-seq1 cl-start1 (aref cl-seq2 cl-start2))
- (setq cl-start2 (1+ cl-start2) cl-start1 (1+ cl-start1))))))
- cl-seq1))
-
-(defun remove* (cl-item cl-seq &rest cl-keys)
- "Remove all occurrences of ITEM in SEQ.
-This is a non-destructive function; it makes a copy of SEQ if necessary
-to avoid corrupting the original SEQ.
-Keywords supported: :test :test-not :key :count :start :end :from-end"
- (cl-parsing-keywords (:test :test-not :key :if :if-not :count :from-end
- (:start 0) :end) ()
- (if (<= (or cl-count (setq cl-count 8000000)) 0)
- cl-seq
- (if (or (nlistp cl-seq) (and cl-from-end (< cl-count 4000000)))
- (let ((cl-i (cl-position cl-item cl-seq cl-start cl-end
- cl-from-end)))
- (if cl-i
- (let ((cl-res (apply 'delete* cl-item (append cl-seq nil)
- (append (if cl-from-end
- (list ':end (1+ cl-i))
- (list ':start cl-i))
- cl-keys))))
- (if (listp cl-seq) cl-res
- (if (stringp cl-seq) (concat cl-res) (vconcat cl-res))))
- cl-seq))
- (setq cl-end (- (or cl-end 8000000) cl-start))
- (if (= cl-start 0)
- (while (and cl-seq (> cl-end 0)
- (cl-check-test cl-item (car cl-seq))
- (setq cl-end (1- cl-end) cl-seq (cdr cl-seq))
- (> (setq cl-count (1- cl-count)) 0))))
- (if (and (> cl-count 0) (> cl-end 0))
- (let ((cl-p (if (> cl-start 0) (nthcdr cl-start cl-seq)
- (setq cl-end (1- cl-end)) (cdr cl-seq))))
- (while (and cl-p (> cl-end 0)
- (not (cl-check-test cl-item (car cl-p))))
- (setq cl-p (cdr cl-p) cl-end (1- cl-end)))
- (if (and cl-p (> cl-end 0))
- (nconc (ldiff cl-seq cl-p)
- (if (= cl-count 1) (cdr cl-p)
- (and (cdr cl-p)
- (apply 'delete* cl-item
- (copy-sequence (cdr cl-p))
- ':start 0 ':end (1- cl-end)
- ':count (1- cl-count) cl-keys))))
- cl-seq))
- cl-seq)))))
-
-(defun remove-if (cl-pred cl-list &rest cl-keys)
- "Remove all items satisfying PREDICATE in SEQ.
-This is a non-destructive function; it makes a copy of SEQ if necessary
-to avoid corrupting the original SEQ.
-Keywords supported: :key :count :start :end :from-end"
- (apply 'remove* nil cl-list ':if cl-pred cl-keys))
-
-(defun remove-if-not (cl-pred cl-list &rest cl-keys)
- "Remove all items not satisfying PREDICATE in SEQ.
-This is a non-destructive function; it makes a copy of SEQ if necessary
-to avoid corrupting the original SEQ.
-Keywords supported: :key :count :start :end :from-end"
- (apply 'remove* nil cl-list ':if-not cl-pred cl-keys))
-
-(defun delete* (cl-item cl-seq &rest cl-keys)
- "Remove all occurrences of ITEM in SEQ.
-This is a destructive function; it reuses the storage of SEQ whenever possible.
-Keywords supported: :test :test-not :key :count :start :end :from-end"
- (cl-parsing-keywords (:test :test-not :key :if :if-not :count :from-end
- (:start 0) :end) ()
- (if (<= (or cl-count (setq cl-count 8000000)) 0)
- cl-seq
- (if (listp cl-seq)
- (if (and cl-from-end (< cl-count 4000000))
- (let (cl-i)
- (while (and (>= (setq cl-count (1- cl-count)) 0)
- (setq cl-i (cl-position cl-item cl-seq cl-start
- cl-end cl-from-end)))
- (if (= cl-i 0) (setq cl-seq (cdr cl-seq))
- (let ((cl-tail (nthcdr (1- cl-i) cl-seq)))
- (setcdr cl-tail (cdr (cdr cl-tail)))))
- (setq cl-end cl-i))
- cl-seq)
- (setq cl-end (- (or cl-end 8000000) cl-start))
- (if (= cl-start 0)
- (progn
- (while (and cl-seq
- (> cl-end 0)
- (cl-check-test cl-item (car cl-seq))
- (setq cl-end (1- cl-end) cl-seq (cdr cl-seq))
- (> (setq cl-count (1- cl-count)) 0)))
- (setq cl-end (1- cl-end)))
- (setq cl-start (1- cl-start)))
- (if (and (> cl-count 0) (> cl-end 0))
- (let ((cl-p (nthcdr cl-start cl-seq)))
- (while (and (cdr cl-p) (> cl-end 0))
- (if (cl-check-test cl-item (car (cdr cl-p)))
- (progn
- (setcdr cl-p (cdr (cdr cl-p)))
- (if (= (setq cl-count (1- cl-count)) 0)
- (setq cl-end 1)))
- (setq cl-p (cdr cl-p)))
- (setq cl-end (1- cl-end)))))
- cl-seq)
- (apply 'remove* cl-item cl-seq cl-keys)))))
-
-(defun delete-if (cl-pred cl-list &rest cl-keys)
- "Remove all items satisfying PREDICATE in SEQ.
-This is a destructive function; it reuses the storage of SEQ whenever possible.
-Keywords supported: :key :count :start :end :from-end"
- (apply 'delete* nil cl-list ':if cl-pred cl-keys))
-
-(defun delete-if-not (cl-pred cl-list &rest cl-keys)
- "Remove all items not satisfying PREDICATE in SEQ.
-This is a destructive function; it reuses the storage of SEQ whenever possible.
-Keywords supported: :key :count :start :end :from-end"
- (apply 'delete* nil cl-list ':if-not cl-pred cl-keys))
-
-(or (and (fboundp 'delete) (subrp (symbol-function 'delete)))
- (defalias 'delete (function (lambda (x y) (delete* x y ':test 'equal)))))
-(defun remove (x y) (remove* x y ':test 'equal))
-(defun remq (x y) (if (memq x y) (delq x (copy-list y)) y))
-
-(defun remove-duplicates (cl-seq &rest cl-keys)
- "Return a copy of SEQ with all duplicate elements removed.
-Keywords supported: :test :test-not :key :start :end :from-end"
- (cl-delete-duplicates cl-seq cl-keys t))
-
-(defun delete-duplicates (cl-seq &rest cl-keys)
- "Remove all duplicate elements from SEQ (destructively).
-Keywords supported: :test :test-not :key :start :end :from-end"
- (cl-delete-duplicates cl-seq cl-keys nil))
-
-(defun cl-delete-duplicates (cl-seq cl-keys cl-copy)
- (if (listp cl-seq)
- (cl-parsing-keywords (:test :test-not :key (:start 0) :end :from-end :if)
- ()
- (if cl-from-end
- (let ((cl-p (nthcdr cl-start cl-seq)) cl-i)
- (setq cl-end (- (or cl-end (length cl-seq)) cl-start))
- (while (> cl-end 1)
- (setq cl-i 0)
- (while (setq cl-i (cl-position (cl-check-key (car cl-p))
- (cdr cl-p) cl-i (1- cl-end)))
- (if cl-copy (setq cl-seq (copy-sequence cl-seq)
- cl-p (nthcdr cl-start cl-seq) cl-copy nil))
- (let ((cl-tail (nthcdr cl-i cl-p)))
- (setcdr cl-tail (cdr (cdr cl-tail))))
- (setq cl-end (1- cl-end)))
- (setq cl-p (cdr cl-p) cl-end (1- cl-end)
- cl-start (1+ cl-start)))
- cl-seq)
- (setq cl-end (- (or cl-end (length cl-seq)) cl-start))
- (while (and (cdr cl-seq) (= cl-start 0) (> cl-end 1)
- (cl-position (cl-check-key (car cl-seq))
- (cdr cl-seq) 0 (1- cl-end)))
- (setq cl-seq (cdr cl-seq) cl-end (1- cl-end)))
- (let ((cl-p (if (> cl-start 0) (nthcdr (1- cl-start) cl-seq)
- (setq cl-end (1- cl-end) cl-start 1) cl-seq)))
- (while (and (cdr (cdr cl-p)) (> cl-end 1))
- (if (cl-position (cl-check-key (car (cdr cl-p)))
- (cdr (cdr cl-p)) 0 (1- cl-end))
- (progn
- (if cl-copy (setq cl-seq (copy-sequence cl-seq)
- cl-p (nthcdr (1- cl-start) cl-seq)
- cl-copy nil))
- (setcdr cl-p (cdr (cdr cl-p))))
- (setq cl-p (cdr cl-p)))
- (setq cl-end (1- cl-end) cl-start (1+ cl-start)))
- cl-seq)))
- (let ((cl-res (cl-delete-duplicates (append cl-seq nil) cl-keys nil)))
- (if (stringp cl-seq) (concat cl-res) (vconcat cl-res)))))
-
-(defun substitute (cl-new cl-old cl-seq &rest cl-keys)
- "Substitute NEW for OLD in SEQ.
-This is a non-destructive function; it makes a copy of SEQ if necessary
-to avoid corrupting the original SEQ.
-Keywords supported: :test :test-not :key :count :start :end :from-end"
- (cl-parsing-keywords (:test :test-not :key :if :if-not :count
- (:start 0) :end :from-end) ()
- (if (or (eq cl-old cl-new)
- (<= (or cl-count (setq cl-from-end nil cl-count 8000000)) 0))
- cl-seq
- (let ((cl-i (cl-position cl-old cl-seq cl-start cl-end)))
- (if (not cl-i)
- cl-seq
- (setq cl-seq (copy-sequence cl-seq))
- (or cl-from-end
- (progn (cl-set-elt cl-seq cl-i cl-new)
- (setq cl-i (1+ cl-i) cl-count (1- cl-count))))
- (apply 'nsubstitute cl-new cl-old cl-seq ':count cl-count
- ':start cl-i cl-keys))))))
-
-(defun substitute-if (cl-new cl-pred cl-list &rest cl-keys)
- "Substitute NEW for all items satisfying PREDICATE in SEQ.
-This is a non-destructive function; it makes a copy of SEQ if necessary
-to avoid corrupting the original SEQ.
-Keywords supported: :key :count :start :end :from-end"
- (apply 'substitute cl-new nil cl-list ':if cl-pred cl-keys))
-
-(defun substitute-if-not (cl-new cl-pred cl-list &rest cl-keys)
- "Substitute NEW for all items not satisfying PREDICATE in SEQ.
-This is a non-destructive function; it makes a copy of SEQ if necessary
-to avoid corrupting the original SEQ.
-Keywords supported: :key :count :start :end :from-end"
- (apply 'substitute cl-new nil cl-list ':if-not cl-pred cl-keys))
-
-(defun nsubstitute (cl-new cl-old cl-seq &rest cl-keys)
- "Substitute NEW for OLD in SEQ.
-This is a destructive function; it reuses the storage of SEQ whenever possible.
-Keywords supported: :test :test-not :key :count :start :end :from-end"
- (cl-parsing-keywords (:test :test-not :key :if :if-not :count
- (:start 0) :end :from-end) ()
- (or (eq cl-old cl-new) (<= (or cl-count (setq cl-count 8000000)) 0)
- (if (and (listp cl-seq) (or (not cl-from-end) (> cl-count 4000000)))
- (let ((cl-p (nthcdr cl-start cl-seq)))
- (setq cl-end (- (or cl-end 8000000) cl-start))
- (while (and cl-p (> cl-end 0) (> cl-count 0))
- (if (cl-check-test cl-old (car cl-p))
- (progn
- (setcar cl-p cl-new)
- (setq cl-count (1- cl-count))))
- (setq cl-p (cdr cl-p) cl-end (1- cl-end))))
- (or cl-end (setq cl-end (length cl-seq)))
- (if cl-from-end
- (while (and (< cl-start cl-end) (> cl-count 0))
- (setq cl-end (1- cl-end))
- (if (cl-check-test cl-old (elt cl-seq cl-end))
- (progn
- (cl-set-elt cl-seq cl-end cl-new)
- (setq cl-count (1- cl-count)))))
- (while (and (< cl-start cl-end) (> cl-count 0))
- (if (cl-check-test cl-old (aref cl-seq cl-start))
- (progn
- (aset cl-seq cl-start cl-new)
- (setq cl-count (1- cl-count))))
- (setq cl-start (1+ cl-start))))))
- cl-seq))
-
-(defun nsubstitute-if (cl-new cl-pred cl-list &rest cl-keys)
- "Substitute NEW for all items satisfying PREDICATE in SEQ.
-This is a destructive function; it reuses the storage of SEQ whenever possible.
-Keywords supported: :key :count :start :end :from-end"
- (apply 'nsubstitute cl-new nil cl-list ':if cl-pred cl-keys))
-
-(defun nsubstitute-if-not (cl-new cl-pred cl-list &rest cl-keys)
- "Substitute NEW for all items not satisfying PREDICATE in SEQ.
-This is a destructive function; it reuses the storage of SEQ whenever possible.
-Keywords supported: :key :count :start :end :from-end"
- (apply 'nsubstitute cl-new nil cl-list ':if-not cl-pred cl-keys))
-
-(defun find (cl-item cl-seq &rest cl-keys)
- "Find the first occurrence of ITEM in LIST.
-Return the matching ITEM, or nil if not found.
-Keywords supported: :test :test-not :key :start :end :from-end"
- (let ((cl-pos (apply 'position cl-item cl-seq cl-keys)))
- (and cl-pos (elt cl-seq cl-pos))))
-
-(defun find-if (cl-pred cl-list &rest cl-keys)
- "Find the first item satisfying PREDICATE in LIST.
-Return the matching ITEM, or nil if not found.
-Keywords supported: :key :start :end :from-end"
- (apply 'find nil cl-list ':if cl-pred cl-keys))
-
-(defun find-if-not (cl-pred cl-list &rest cl-keys)
- "Find the first item not satisfying PREDICATE in LIST.
-Return the matching ITEM, or nil if not found.
-Keywords supported: :key :start :end :from-end"
- (apply 'find nil cl-list ':if-not cl-pred cl-keys))
-
-(defun position (cl-item cl-seq &rest cl-keys)
- "Find the first occurrence of ITEM in LIST.
-Return the index of the matching item, or nil if not found.
-Keywords supported: :test :test-not :key :start :end :from-end"
- (cl-parsing-keywords (:test :test-not :key :if :if-not
- (:start 0) :end :from-end) ()
- (cl-position cl-item cl-seq cl-start cl-end cl-from-end)))
-
-(defun cl-position (cl-item cl-seq cl-start &optional cl-end cl-from-end)
- (if (listp cl-seq)
- (let ((cl-p (nthcdr cl-start cl-seq)))
- (or cl-end (setq cl-end 8000000))
- (let ((cl-res nil))
- (while (and cl-p (< cl-start cl-end) (or (not cl-res) cl-from-end))
- (if (cl-check-test cl-item (car cl-p))
- (setq cl-res cl-start))
- (setq cl-p (cdr cl-p) cl-start (1+ cl-start)))
- cl-res))
- (or cl-end (setq cl-end (length cl-seq)))
- (if cl-from-end
- (progn
- (while (and (>= (setq cl-end (1- cl-end)) cl-start)
- (not (cl-check-test cl-item (aref cl-seq cl-end)))))
- (and (>= cl-end cl-start) cl-end))
- (while (and (< cl-start cl-end)
- (not (cl-check-test cl-item (aref cl-seq cl-start))))
- (setq cl-start (1+ cl-start)))
- (and (< cl-start cl-end) cl-start))))
-
-(defun position-if (cl-pred cl-list &rest cl-keys)
- "Find the first item satisfying PREDICATE in LIST.
-Return the index of the matching item, or nil if not found.
-Keywords supported: :key :start :end :from-end"
- (apply 'position nil cl-list ':if cl-pred cl-keys))
-
-(defun position-if-not (cl-pred cl-list &rest cl-keys)
- "Find the first item not satisfying PREDICATE in LIST.
-Return the index of the matching item, or nil if not found.
-Keywords supported: :key :start :end :from-end"
- (apply 'position nil cl-list ':if-not cl-pred cl-keys))
-
-(defun count (cl-item cl-seq &rest cl-keys)
- "Count the number of occurrences of ITEM in LIST.
-Keywords supported: :test :test-not :key :start :end"
- (cl-parsing-keywords (:test :test-not :key :if :if-not (:start 0) :end) ()
- (let ((cl-count 0) cl-x)
- (or cl-end (setq cl-end (length cl-seq)))
- (if (consp cl-seq) (setq cl-seq (nthcdr cl-start cl-seq)))
- (while (< cl-start cl-end)
- (setq cl-x (if (consp cl-seq) (cl-pop cl-seq) (aref cl-seq cl-start)))
- (if (cl-check-test cl-item cl-x) (setq cl-count (1+ cl-count)))
- (setq cl-start (1+ cl-start)))
- cl-count)))
-
-(defun count-if (cl-pred cl-list &rest cl-keys)
- "Count the number of items satisfying PREDICATE in LIST.
-Keywords supported: :key :start :end"
- (apply 'count nil cl-list ':if cl-pred cl-keys))
-
-(defun count-if-not (cl-pred cl-list &rest cl-keys)
- "Count the number of items not satisfying PREDICATE in LIST.
-Keywords supported: :key :start :end"
- (apply 'count nil cl-list ':if-not cl-pred cl-keys))
-
-(defun mismatch (cl-seq1 cl-seq2 &rest cl-keys)
- "Compare SEQ1 with SEQ2, return index of first mismatching element.
-Return nil if the sequences match. If one sequence is a prefix of the
-other, the return value indicates the end of the shorted sequence.
-Keywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end"
- (cl-parsing-keywords (:test :test-not :key :from-end
- (:start1 0) :end1 (:start2 0) :end2) ()
- (or cl-end1 (setq cl-end1 (length cl-seq1)))
- (or cl-end2 (setq cl-end2 (length cl-seq2)))
- (if cl-from-end
- (progn
- (while (and (< cl-start1 cl-end1) (< cl-start2 cl-end2)
- (cl-check-match (elt cl-seq1 (1- cl-end1))
- (elt cl-seq2 (1- cl-end2))))
- (setq cl-end1 (1- cl-end1) cl-end2 (1- cl-end2)))
- (and (or (< cl-start1 cl-end1) (< cl-start2 cl-end2))
- (1- cl-end1)))
- (let ((cl-p1 (and (listp cl-seq1) (nthcdr cl-start1 cl-seq1)))
- (cl-p2 (and (listp cl-seq2) (nthcdr cl-start2 cl-seq2))))
- (while (and (< cl-start1 cl-end1) (< cl-start2 cl-end2)
- (cl-check-match (if cl-p1 (car cl-p1)
- (aref cl-seq1 cl-start1))
- (if cl-p2 (car cl-p2)
- (aref cl-seq2 cl-start2))))
- (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2)
- cl-start1 (1+ cl-start1) cl-start2 (1+ cl-start2)))
- (and (or (< cl-start1 cl-end1) (< cl-start2 cl-end2))
- cl-start1)))))
-
-(defun search (cl-seq1 cl-seq2 &rest cl-keys)
- "Search for SEQ1 as a subsequence of SEQ2.
-Return the index of the leftmost element of the first match found;
-return nil if there are no matches.
-Keywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end"
- (cl-parsing-keywords (:test :test-not :key :from-end
- (:start1 0) :end1 (:start2 0) :end2) ()
- (or cl-end1 (setq cl-end1 (length cl-seq1)))
- (or cl-end2 (setq cl-end2 (length cl-seq2)))
- (if (>= cl-start1 cl-end1)
- (if cl-from-end cl-end2 cl-start2)
- (let* ((cl-len (- cl-end1 cl-start1))
- (cl-first (cl-check-key (elt cl-seq1 cl-start1)))
- (cl-if nil) cl-pos)
- (setq cl-end2 (- cl-end2 (1- cl-len)))
- (while (and (< cl-start2 cl-end2)
- (setq cl-pos (cl-position cl-first cl-seq2
- cl-start2 cl-end2 cl-from-end))
- (apply 'mismatch cl-seq1 cl-seq2
- ':start1 (1+ cl-start1) ':end1 cl-end1
- ':start2 (1+ cl-pos) ':end2 (+ cl-pos cl-len)
- ':from-end nil cl-keys))
- (if cl-from-end (setq cl-end2 cl-pos) (setq cl-start2 (1+ cl-pos))))
- (and (< cl-start2 cl-end2) cl-pos)))))
-
-(defun sort* (cl-seq cl-pred &rest cl-keys)
- "Sort the argument SEQUENCE according to PREDICATE.
-This is a destructive function; it reuses the storage of SEQUENCE if possible.
-Keywords supported: :key"
- (if (nlistp cl-seq)
- (replace cl-seq (apply 'sort* (append cl-seq nil) cl-pred cl-keys))
- (cl-parsing-keywords (:key) ()
- (if (memq cl-key '(nil identity))
- (sort cl-seq cl-pred)
- (sort cl-seq (function (lambda (cl-x cl-y)
- (funcall cl-pred (funcall cl-key cl-x)
- (funcall cl-key cl-y)))))))))
-
-(defun stable-sort (cl-seq cl-pred &rest cl-keys)
- "Sort the argument SEQUENCE stably according to PREDICATE.
-This is a destructive function; it reuses the storage of SEQUENCE if possible.
-Keywords supported: :key"
- (apply 'sort* cl-seq cl-pred cl-keys))
-
-(defun merge (cl-type cl-seq1 cl-seq2 cl-pred &rest cl-keys)
- "Destructively merge the two sequences to produce a new sequence.
-TYPE is the sequence type to return, SEQ1 and SEQ2 are the two
-argument sequences, and PRED is a `less-than' predicate on the elements.
-Keywords supported: :key"
- (or (listp cl-seq1) (setq cl-seq1 (append cl-seq1 nil)))
- (or (listp cl-seq2) (setq cl-seq2 (append cl-seq2 nil)))
- (cl-parsing-keywords (:key) ()
- (let ((cl-res nil))
- (while (and cl-seq1 cl-seq2)
- (if (funcall cl-pred (cl-check-key (car cl-seq2))
- (cl-check-key (car cl-seq1)))
- (cl-push (cl-pop cl-seq2) cl-res)
- (cl-push (cl-pop cl-seq1) cl-res)))
- (coerce (nconc (nreverse cl-res) cl-seq1 cl-seq2) cl-type))))
-
-;;; See compiler macro in cl-macs.el
-(defun member* (cl-item cl-list &rest cl-keys)
- "Find the first occurrence of ITEM in LIST.
-Return the sublist of LIST whose car is ITEM.
-Keywords supported: :test :test-not :key"
- (if cl-keys
- (cl-parsing-keywords (:test :test-not :key :if :if-not) ()
- (while (and cl-list (not (cl-check-test cl-item (car cl-list))))
- (setq cl-list (cdr cl-list)))
- cl-list)
- (if (and (numberp cl-item) (not (integerp cl-item)))
- (member cl-item cl-list)
- (memq cl-item cl-list))))
-
-(defun member-if (cl-pred cl-list &rest cl-keys)
- "Find the first item satisfying PREDICATE in LIST.
-Return the sublist of LIST whose car matches.
-Keywords supported: :key"
- (apply 'member* nil cl-list ':if cl-pred cl-keys))
-
-(defun member-if-not (cl-pred cl-list &rest cl-keys)
- "Find the first item not satisfying PREDICATE in LIST.
-Return the sublist of LIST whose car matches.
-Keywords supported: :key"
- (apply 'member* nil cl-list ':if-not cl-pred cl-keys))
-
-(defun cl-adjoin (cl-item cl-list &rest cl-keys)
- (if (cl-parsing-keywords (:key) t
- (apply 'member* (cl-check-key cl-item) cl-list cl-keys))
- cl-list
- (cons cl-item cl-list)))
-
-;;; See compiler macro in cl-macs.el
-(defun assoc* (cl-item cl-alist &rest cl-keys)
- "Find the first item whose car matches ITEM in LIST.
-Keywords supported: :test :test-not :key"
- (if cl-keys
- (cl-parsing-keywords (:test :test-not :key :if :if-not) ()
- (while (and cl-alist
- (or (not (consp (car cl-alist)))
- (not (cl-check-test cl-item (car (car cl-alist))))))
- (setq cl-alist (cdr cl-alist)))
- (and cl-alist (car cl-alist)))
- (if (and (numberp cl-item) (not (integerp cl-item)))
- (assoc cl-item cl-alist)
- (assq cl-item cl-alist))))
-
-(defun assoc-if (cl-pred cl-list &rest cl-keys)
- "Find the first item whose car satisfies PREDICATE in LIST.
-Keywords supported: :key"
- (apply 'assoc* nil cl-list ':if cl-pred cl-keys))
-
-(defun assoc-if-not (cl-pred cl-list &rest cl-keys)
- "Find the first item whose car does not satisfy PREDICATE in LIST.
-Keywords supported: :key"
- (apply 'assoc* nil cl-list ':if-not cl-pred cl-keys))
-
-(defun rassoc* (cl-item cl-alist &rest cl-keys)
- "Find the first item whose cdr matches ITEM in LIST.
-Keywords supported: :test :test-not :key"
- (if (or cl-keys (numberp cl-item))
- (cl-parsing-keywords (:test :test-not :key :if :if-not) ()
- (while (and cl-alist
- (or (not (consp (car cl-alist)))
- (not (cl-check-test cl-item (cdr (car cl-alist))))))
- (setq cl-alist (cdr cl-alist)))
- (and cl-alist (car cl-alist)))
- (rassq cl-item cl-alist)))
-
-(defun rassoc-if (cl-pred cl-list &rest cl-keys)
- "Find the first item whose cdr satisfies PREDICATE in LIST.
-Keywords supported: :key"
- (apply 'rassoc* nil cl-list ':if cl-pred cl-keys))
-
-(defun rassoc-if-not (cl-pred cl-list &rest cl-keys)
- "Find the first item whose cdr does not satisfy PREDICATE in LIST.
-Keywords supported: :key"
- (apply 'rassoc* nil cl-list ':if-not cl-pred cl-keys))
-
-(defun union (cl-list1 cl-list2 &rest cl-keys)
- "Combine LIST1 and LIST2 using a set-union operation.
-The result list contains all items that appear in either LIST1 or LIST2.
-This is a non-destructive function; it makes a copy of the data if necessary
-to avoid corrupting the original LIST1 and LIST2.
-Keywords supported: :test :test-not :key"
- (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1)
- ((equal cl-list1 cl-list2) cl-list1)
- (t
- (or (>= (length cl-list1) (length cl-list2))
- (setq cl-list1 (prog1 cl-list2 (setq cl-list2 cl-list1))))
- (while cl-list2
- (if (or cl-keys (numberp (car cl-list2)))
- (setq cl-list1 (apply 'adjoin (car cl-list2) cl-list1 cl-keys))
- (or (memq (car cl-list2) cl-list1)
- (cl-push (car cl-list2) cl-list1)))
- (cl-pop cl-list2))
- cl-list1)))
-
-(defun nunion (cl-list1 cl-list2 &rest cl-keys)
- "Combine LIST1 and LIST2 using a set-union operation.
-The result list contains all items that appear in either LIST1 or LIST2.
-This is a destructive function; it reuses the storage of LIST1 and LIST2
-whenever possible.
-Keywords supported: :test :test-not :key"
- (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1)
- (t (apply 'union cl-list1 cl-list2 cl-keys))))
-
-(defun intersection (cl-list1 cl-list2 &rest cl-keys)
- "Combine LIST1 and LIST2 using a set-intersection operation.
-The result list contains all items that appear in both LIST1 and LIST2.
-This is a non-destructive function; it makes a copy of the data if necessary
-to avoid corrupting the original LIST1 and LIST2.
-Keywords supported: :test :test-not :key"
- (and cl-list1 cl-list2
- (if (equal cl-list1 cl-list2) cl-list1
- (cl-parsing-keywords (:key) (:test :test-not)
- (let ((cl-res nil))
- (or (>= (length cl-list1) (length cl-list2))
- (setq cl-list1 (prog1 cl-list2 (setq cl-list2 cl-list1))))
- (while cl-list2
- (if (if (or cl-keys (numberp (car cl-list2)))
- (apply 'member* (cl-check-key (car cl-list2))
- cl-list1 cl-keys)
- (memq (car cl-list2) cl-list1))
- (cl-push (car cl-list2) cl-res))
- (cl-pop cl-list2))
- cl-res)))))
-
-(defun nintersection (cl-list1 cl-list2 &rest cl-keys)
- "Combine LIST1 and LIST2 using a set-intersection operation.
-The result list contains all items that appear in both LIST1 and LIST2.
-This is a destructive function; it reuses the storage of LIST1 and LIST2
-whenever possible.
-Keywords supported: :test :test-not :key"
- (and cl-list1 cl-list2 (apply 'intersection cl-list1 cl-list2 cl-keys)))
-
-(defun set-difference (cl-list1 cl-list2 &rest cl-keys)
- "Combine LIST1 and LIST2 using a set-difference operation.
-The result list contains all items that appear in LIST1 but not LIST2.
-This is a non-destructive function; it makes a copy of the data if necessary
-to avoid corrupting the original LIST1 and LIST2.
-Keywords supported: :test :test-not :key"
- (if (or (null cl-list1) (null cl-list2)) cl-list1
- (cl-parsing-keywords (:key) (:test :test-not)
- (let ((cl-res nil))
- (while cl-list1
- (or (if (or cl-keys (numberp (car cl-list1)))
- (apply 'member* (cl-check-key (car cl-list1))
- cl-list2 cl-keys)
- (memq (car cl-list1) cl-list2))
- (cl-push (car cl-list1) cl-res))
- (cl-pop cl-list1))
- cl-res))))
-
-(defun nset-difference (cl-list1 cl-list2 &rest cl-keys)
- "Combine LIST1 and LIST2 using a set-difference operation.
-The result list contains all items that appear in LIST1 but not LIST2.
-This is a destructive function; it reuses the storage of LIST1 and LIST2
-whenever possible.
-Keywords supported: :test :test-not :key"
- (if (or (null cl-list1) (null cl-list2)) cl-list1
- (apply 'set-difference cl-list1 cl-list2 cl-keys)))
-
-(defun set-exclusive-or (cl-list1 cl-list2 &rest cl-keys)
- "Combine LIST1 and LIST2 using a set-exclusive-or operation.
-The result list contains all items that appear in exactly one of LIST1, LIST2.
-This is a non-destructive function; it makes a copy of the data if necessary
-to avoid corrupting the original LIST1 and LIST2.
-Keywords supported: :test :test-not :key"
- (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1)
- ((equal cl-list1 cl-list2) nil)
- (t (append (apply 'set-difference cl-list1 cl-list2 cl-keys)
- (apply 'set-difference cl-list2 cl-list1 cl-keys)))))
-
-(defun nset-exclusive-or (cl-list1 cl-list2 &rest cl-keys)
- "Combine LIST1 and LIST2 using a set-exclusive-or operation.
-The result list contains all items that appear in exactly one of LIST1, LIST2.
-This is a destructive function; it reuses the storage of LIST1 and LIST2
-whenever possible.
-Keywords supported: :test :test-not :key"
- (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1)
- ((equal cl-list1 cl-list2) nil)
- (t (nconc (apply 'nset-difference cl-list1 cl-list2 cl-keys)
- (apply 'nset-difference cl-list2 cl-list1 cl-keys)))))
-
-(defun subsetp (cl-list1 cl-list2 &rest cl-keys)
- "True if LIST1 is a subset of LIST2.
-I.e., if every element of LIST1 also appears in LIST2.
-Keywords supported: :test :test-not :key"
- (cond ((null cl-list1) t) ((null cl-list2) nil)
- ((equal cl-list1 cl-list2) t)
- (t (cl-parsing-keywords (:key) (:test :test-not)
- (while (and cl-list1
- (apply 'member* (cl-check-key (car cl-list1))
- cl-list2 cl-keys))
- (cl-pop cl-list1))
- (null cl-list1)))))
-
-(defun subst-if (cl-new cl-pred cl-tree &rest cl-keys)
- "Substitute NEW for elements matching PREDICATE in TREE (non-destructively).
-Return a copy of TREE with all matching elements replaced by NEW.
-Keywords supported: :key"
- (apply 'sublis (list (cons nil cl-new)) cl-tree ':if cl-pred cl-keys))
-
-(defun subst-if-not (cl-new cl-pred cl-tree &rest cl-keys)
- "Substitute NEW for elts not matching PREDICATE in TREE (non-destructively).
-Return a copy of TREE with all non-matching elements replaced by NEW.
-Keywords supported: :key"
- (apply 'sublis (list (cons nil cl-new)) cl-tree ':if-not cl-pred cl-keys))
-
-(defun nsubst (cl-new cl-old cl-tree &rest cl-keys)
- "Substitute NEW for OLD everywhere in TREE (destructively).
-Any element of TREE which is `eql' to OLD is changed to NEW (via a call
-to `setcar').
-Keywords supported: :test :test-not :key"
- (apply 'nsublis (list (cons cl-old cl-new)) cl-tree cl-keys))
-
-(defun nsubst-if (cl-new cl-pred cl-tree &rest cl-keys)
- "Substitute NEW for elements matching PREDICATE in TREE (destructively).
-Any element of TREE which matches is changed to NEW (via a call to `setcar').
-Keywords supported: :key"
- (apply 'nsublis (list (cons nil cl-new)) cl-tree ':if cl-pred cl-keys))
-
-(defun nsubst-if-not (cl-new cl-pred cl-tree &rest cl-keys)
- "Substitute NEW for elements not matching PREDICATE in TREE (destructively).
-Any element of TREE which matches is changed to NEW (via a call to `setcar').
-Keywords supported: :key"
- (apply 'nsublis (list (cons nil cl-new)) cl-tree ':if-not cl-pred cl-keys))
-
-(defun sublis (cl-alist cl-tree &rest cl-keys)
- "Perform substitutions indicated by ALIST in TREE (non-destructively).
-Return a copy of TREE with all matching elements replaced.
-Keywords supported: :test :test-not :key"
- (cl-parsing-keywords (:test :test-not :key :if :if-not) ()
- (cl-sublis-rec cl-tree)))
-
-(defvar cl-alist)
-(defun cl-sublis-rec (cl-tree) ; uses cl-alist/key/test*/if*
- (let ((cl-temp (cl-check-key cl-tree)) (cl-p cl-alist))
- (while (and cl-p (not (cl-check-test-nokey (car (car cl-p)) cl-temp)))
- (setq cl-p (cdr cl-p)))
- (if cl-p (cdr (car cl-p))
- (if (consp cl-tree)
- (let ((cl-a (cl-sublis-rec (car cl-tree)))
- (cl-d (cl-sublis-rec (cdr cl-tree))))
- (if (and (eq cl-a (car cl-tree)) (eq cl-d (cdr cl-tree)))
- cl-tree
- (cons cl-a cl-d)))
- cl-tree))))
-
-(defun nsublis (cl-alist cl-tree &rest cl-keys)
- "Perform substitutions indicated by ALIST in TREE (destructively).
-Any matching element of TREE is changed via a call to `setcar'.
-Keywords supported: :test :test-not :key"
- (cl-parsing-keywords (:test :test-not :key :if :if-not) ()
- (let ((cl-hold (list cl-tree)))
- (cl-nsublis-rec cl-hold)
- (car cl-hold))))
-
-(defun cl-nsublis-rec (cl-tree) ; uses cl-alist/temp/p/key/test*/if*
- (while (consp cl-tree)
- (let ((cl-temp (cl-check-key (car cl-tree))) (cl-p cl-alist))
- (while (and cl-p (not (cl-check-test-nokey (car (car cl-p)) cl-temp)))
- (setq cl-p (cdr cl-p)))
- (if cl-p (setcar cl-tree (cdr (car cl-p)))
- (if (consp (car cl-tree)) (cl-nsublis-rec (car cl-tree))))
- (setq cl-temp (cl-check-key (cdr cl-tree)) cl-p cl-alist)
- (while (and cl-p (not (cl-check-test-nokey (car (car cl-p)) cl-temp)))
- (setq cl-p (cdr cl-p)))
- (if cl-p
- (progn (setcdr cl-tree (cdr (car cl-p))) (setq cl-tree nil))
- (setq cl-tree (cdr cl-tree))))))
-
-(defun tree-equal (cl-x cl-y &rest cl-keys)
- "T if trees X and Y have `eql' leaves.
-Atoms are compared by `eql'; cons cells are compared recursively.
-Keywords supported: :test :test-not :key"
- (cl-parsing-keywords (:test :test-not :key) ()
- (cl-tree-equal-rec cl-x cl-y)))
-
-(defun cl-tree-equal-rec (cl-x cl-y)
- (while (and (consp cl-x) (consp cl-y)
- (cl-tree-equal-rec (car cl-x) (car cl-y)))
- (setq cl-x (cdr cl-x) cl-y (cdr cl-y)))
- (and (not (consp cl-x)) (not (consp cl-y)) (cl-check-match cl-x cl-y)))
-
-
-(run-hooks 'cl-seq-load-hook)
-
-;;; cl-seq.el ends here
diff --git a/lisp/emacs-lisp/cl-specs.el b/lisp/emacs-lisp/cl-specs.el
deleted file mode 100644
index 38497b26765..00000000000
--- a/lisp/emacs-lisp/cl-specs.el
+++ /dev/null
@@ -1,472 +0,0 @@
-;;; cl-specs.el --- Edebug specs for cl.el
-
-;; Copyright (C) 1993 Free Software Foundation, Inc.
-;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
-;; Keywords: lisp, tools, maint
-
-;; LCD Archive Entry:
-;; cl-specs.el|Daniel LaLiberte|liberte@cs.uiuc.edu
-;; |Edebug specs for cl.el
-;; |$Date: 1996/01/05 21:56:25 $|1.1|
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;;; Commentary:
-
-;; These specs are to be used with edebug.el version 3.3 or later and
-;; cl.el version 2.03 or later, by Dave Gillespie <daveg@synaptics.com>.
-
-;; This file need not be byte-compiled, but it shouldn't hurt.
-
-(provide 'cl-specs)
-;; Do the above provide before the following require.
-;; Otherwise if you load this before edebug if cl is already loaded
-;; an infinite loading loop would occur.
-(require 'edebug)
-
-;; Blocks
-
-(def-edebug-spec block (symbolp body))
-(def-edebug-spec return (&optional form))
-(def-edebug-spec return-from (symbolp &optional form))
-
-;; Loops
-
-(def-edebug-spec when t)
-(def-edebug-spec unless t)
-(def-edebug-spec case (form &rest (sexp body)))
-(def-edebug-spec ecase case)
-(def-edebug-spec do
- ((&rest &or symbolp (symbolp &optional form form))
- (form body)
- cl-declarations body))
-(def-edebug-spec do* do)
-(def-edebug-spec dolist
- ((symbolp form &optional form) cl-declarations body))
-(def-edebug-spec dotimes dolist)
-(def-edebug-spec do-symbols
- ((symbolp &optional form form) cl-declarations body))
-(def-edebug-spec do-all-symbols
- ((symbolp &optional form) cl-declarations body))
-
-;; Multiple values
-
-(def-edebug-spec multiple-value-list (form))
-(def-edebug-spec multiple-value-call (function-form body))
-(def-edebug-spec multiple-value-bind
- ((&rest symbolp) form cl-declarations body))
-(def-edebug-spec multiple-value-setq ((&rest symbolp) form))
-(def-edebug-spec multiple-value-prog1 (form body))
-
-;; Bindings
-
-(def-edebug-spec lexical-let let)
-(def-edebug-spec lexical-let* let)
-
-(def-edebug-spec psetq setq)
-(def-edebug-spec progv (form form body))
-
-(def-edebug-spec flet ((&rest (defun*)) cl-declarations body))
-(def-edebug-spec labels flet)
-
-(def-edebug-spec macrolet
- ((&rest (&define name (&rest arg) cl-declarations-or-string def-body))
- cl-declarations body))
-
-(def-edebug-spec symbol-macrolet
- ((&rest (symbol sexp)) cl-declarations body))
-
-(def-edebug-spec destructuring-bind
- (&define cl-macro-list form cl-declarations def-body))
-
-;; Setf
-
-(def-edebug-spec setf (&rest [place form])) ;; sexp is not specific enough
-(def-edebug-spec psetf setf)
-
-(def-edebug-spec letf ;; *not* available in Common Lisp
- ((&rest (gate place &optional form))
- body))
-(def-edebug-spec letf* letf)
-
-
-(def-edebug-spec defsetf
- (&define name
- [&or [symbolp &optional stringp]
- [cl-lambda-list (symbolp)]]
- cl-declarations-or-string def-body))
-
-(def-edebug-spec define-setf-method
- (&define name cl-lambda-list cl-declarations-or-string def-body))
-
-(def-edebug-spec define-modify-macro
- (&define name cl-lambda-list ;; should exclude &key
- symbolp &optional stringp))
-
-(def-edebug-spec callf (function* place &rest form))
-(def-edebug-spec callf2 (function* form place &rest form))
-
-;; Other operations on places
-
-(def-edebug-spec remf (place form))
-
-(def-edebug-spec incf (place &optional form))
-(def-edebug-spec decf incf)
-(def-edebug-spec push (form place))
-(def-edebug-spec pushnew
- (form place &rest
- &or [[&or ":test" ":test-not" ":key"] function-form]
- [edebug-keywordp form]))
-(def-edebug-spec pop (place))
-
-(def-edebug-spec shiftf (&rest place)) ;; really [&rest place] form
-(def-edebug-spec rotatef (&rest place))
-
-
-;; Functions with function args. These are only useful if the
-;; function arg is quoted with ' instead of function.
-
-(def-edebug-spec some (function-form form &rest form))
-(def-edebug-spec every some)
-(def-edebug-spec notany some)
-(def-edebug-spec notevery some)
-
-;; Mapping
-
-(def-edebug-spec map (form function-form form &rest form))
-(def-edebug-spec maplist (function-form form &rest form))
-(def-edebug-spec mapc maplist)
-(def-edebug-spec mapl maplist)
-(def-edebug-spec mapcan maplist)
-(def-edebug-spec mapcon maplist)
-
-;; Sequences
-
-(def-edebug-spec reduce (function-form form &rest form))
-
-;; Types and assertions
-
-(def-edebug-spec cl-type-spec (sexp)) ;; not worth the trouble to specify, yet.
-
-(def-edebug-spec deftype defmacro*)
-(def-edebug-spec check-type (place cl-type-spec &optional stringp))
-;; (def-edebug-spec assert (form &optional form stringp &rest form))
-(def-edebug-spec assert (form &rest form))
-(def-edebug-spec typecase (form &rest ([&or cl-type-spec "otherwise"] body)))
-(def-edebug-spec etypecase typecase)
-
-(def-edebug-spec ignore-errors t)
-
-;; Time of Evaluation
-
-(def-edebug-spec eval-when
- ((&rest &or "compile" "load" "eval") body))
-(def-edebug-spec load-time-value (form &optional &or "t" "nil"))
-
-;; Declarations
-
-(def-edebug-spec cl-decl-spec
- ((symbolp &rest sexp)))
-
-(def-edebug-spec cl-declarations
- (&rest ("declare" &rest cl-decl-spec)))
-
-(def-edebug-spec cl-declarations-or-string
- (&or stringp cl-declarations))
-
-(def-edebug-spec declaim (&rest cl-decl-spec))
-(def-edebug-spec declare (&rest cl-decl-spec)) ;; probably not needed.
-(def-edebug-spec locally (cl-declarations &rest form))
-(def-edebug-spec the (cl-type-spec form))
-
-;;======================================================
-;; Lambda things
-
-(def-edebug-spec cl-lambda-list
- (([&rest arg]
- [&optional ["&optional" cl-&optional-arg &rest cl-&optional-arg]]
- [&optional ["&rest" arg]]
- [&optional ["&key" [cl-&key-arg &rest cl-&key-arg]
- &optional "&allow-other-keywords"]]
- [&optional ["&aux" &rest
- &or (symbolp &optional def-form) symbolp]]
- )))
-
-(def-edebug-spec cl-&optional-arg
- (&or (arg &optional def-form arg) arg))
-
-(def-edebug-spec cl-&key-arg
- (&or ([&or (symbolp arg) arg] &optional def-form arg) arg))
-
-;; The lambda list for macros is different from that of normal lambdas.
-;; Note that &environment is only allowed as first or last items in the
-;; top level list.
-
-(def-edebug-spec cl-macro-list
- (([&optional "&environment" arg]
- [&rest cl-macro-arg]
- [&optional ["&optional" &rest
- &or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
- [&optional [[&or "&rest" "&body"] cl-macro-arg]]
- [&optional ["&key" [&rest
- [&or ([&or (symbolp cl-macro-arg) arg]
- &optional def-form cl-macro-arg)
- arg]]
- &optional "&allow-other-keywords"]]
- [&optional ["&aux" &rest
- &or (symbolp &optional def-form) symbolp]]
- [&optional "&environment" arg]
- )))
-
-(def-edebug-spec cl-macro-arg
- (&or arg cl-macro-list1))
-
-(def-edebug-spec cl-macro-list1
- (([&optional "&whole" arg] ;; only allowed at lower levels
- [&rest cl-macro-arg]
- [&optional ["&optional" &rest
- &or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
- [&optional [[&or "&rest" "&body"] cl-macro-arg]]
- [&optional ["&key" [&rest
- [&or ([&or (symbolp cl-macro-arg) arg]
- &optional def-form cl-macro-arg)
- arg]]
- &optional "&allow-other-keywords"]]
- [&optional ["&aux" &rest
- &or (symbolp &optional def-form) symbolp]]
- . [&or arg nil])))
-
-
-(def-edebug-spec defun*
- ;; Same as defun but use cl-lambda-list.
- (&define [&or name
- ("setf" :name setf name)]
- cl-lambda-list
- cl-declarations-or-string
- [&optional ("interactive" interactive)]
- def-body))
-(def-edebug-spec defsubst* defun*)
-
-(def-edebug-spec defmacro*
- (&define name cl-macro-list cl-declarations-or-string def-body))
-(def-edebug-spec define-compiler-macro defmacro*)
-
-
-(def-edebug-spec function*
- (&or symbolp cl-lambda-expr))
-
-(def-edebug-spec cl-lambda-expr
- (&define ("lambda" cl-lambda-list
- ;;cl-declarations-or-string
- ;;[&optional ("interactive" interactive)]
- def-body)))
-
-;; Redefine function-form to also match function*
-(def-edebug-spec function-form
- ;; form at the end could also handle "function",
- ;; but recognize it specially to avoid wrapping function forms.
- (&or ([&or "quote" "function"] &or symbolp lambda-expr)
- ("function*" cl-lambda-expr)
- form))
-
-;;======================================================
-;; Structures
-;; (def-edebug-spec defstruct (&rest sexp)) would be sufficient, but...
-
-;; defstruct may contain forms that are evaluated when a structure is created.
-(def-edebug-spec defstruct
- (&define ; makes top-level form not be wrapped
- [&or symbolp
- (gate
- symbolp &rest
- (&or [":conc-name" &or stringp "nil"]
- [":constructor" symbolp &optional cl-lambda-list]
- [":copier" symbolp]
- [":predicate" symbolp]
- [":include" symbolp &rest sexp];; not finished
- ;; The following are not supported.
- ;; [":print-function" ...]
- ;; [":type" ...]
- ;; [":initial-offset" ...]
- ))]
- [&optional stringp]
- ;; All the above is for the following def-form.
- &rest &or symbolp (symbolp def-form &optional ":read-only" sexp)))
-
-;;======================================================
-;; Loop
-
-;; The loop macro is very complex, and a full spec is found below.
-;; The following spec only minimally specifies that
-;; parenthesized forms are executable, but single variables used as
-;; expressions will be missed. You may want to use this if the full
-;; spec causes problems for you.
-
-(def-edebug-spec loop
- (&rest &or symbolp form))
-
-;; Below is a complete spec for loop, in several parts that correspond
-;; to the syntax given in CLtL2. The specs do more than specify where
-;; the forms are; it also specifies, as much as Edebug allows, all the
-;; syntactically legal loop clauses. The disadvantage of this
-;; completeness is rigidity, but the "for ... being" clause allows
-;; arbitrary extensions of the form: [symbolp &rest &or symbolp form].
-
-(def-edebug-spec loop
- ([&optional ["named" symbolp]]
- [&rest
- &or
- ["repeat" form]
- loop-for-as
- loop-with
- loop-initial-final]
- [&rest loop-clause]
- ))
-
-(def-edebug-spec loop-with
- ("with" loop-var
- loop-type-spec
- [&optional ["=" form]]
- &rest ["and" loop-var
- loop-type-spec
- [&optional ["=" form]]]))
-
-(def-edebug-spec loop-for-as
- ([&or "for" "as"] loop-for-as-subclause
- &rest ["and" loop-for-as-subclause]))
-
-(def-edebug-spec loop-for-as-subclause
- (loop-var
- loop-type-spec
- &or
- [[&or "in" "on" "in-ref" "across-ref"]
- form &optional ["by" function-form]]
-
- ["=" form &optional ["then" form]]
- ["across" form]
- ["being"
- [&or "the" "each"]
- &or
- [[&or "element" "elements"]
- [&or "of" "in" "of-ref"] form
- &optional "using" ["index" symbolp]];; is this right?
- [[&or "hash-key" "hash-keys"
- "hash-value" "hash-values"]
- [&or "of" "in"]
- hash-table-p &optional ["using" ([&or "hash-value" "hash-values"
- "hash-key" "hash-keys"] sexp)]]
-
- [[&or "symbol" "present-symbol" "external-symbol"
- "symbols" "present-symbols" "external-symbols"]
- [&or "in" "of"] package-p]
-
- ;; Extensions for Emacs Lisp, including Lucid Emacs.
- [[&or "frame" "frames"
- "screen" "screens"
- "buffer" "buffers"]]
-
- [[&or "window" "windows"]
- [&or "of" "in"] form]
-
- [[&or "overlay" "overlays"
- "extent" "extents"]
- [&or "of" "in"] form
- &optional [[&or "from" "to"] form]]
-
- [[&or "interval" "intervals"]
- [&or "in" "of"] form
- &optional [[&or "from" "to"] form]
- ["property" form]]
-
- [[&or "key-code" "key-codes"
- "key-seq" "key-seqs"
- "key-binding" "key-bindings"]
- [&or "in" "of"] form
- &optional ["using" ([&or "key-code" "key-codes"
- "key-seq" "key-seqs"
- "key-binding" "key-bindings"]
- sexp)]]
- ;; For arbitrary extensions, recognize anything else.
- [symbolp &rest &or symbolp form]
- ]
-
- ;; arithmetic - must be last since all parts are optional.
- [[&optional [[&or "from" "downfrom" "upfrom"] form]]
- [&optional [[&or "to" "downto" "upto" "below" "above"] form]]
- [&optional ["by" form]]
- ]))
-
-(def-edebug-spec loop-initial-final
- (&or ["initially"
- ;; [&optional &or "do" "doing"] ;; CLtL2 doesn't allow this.
- &rest loop-non-atomic-expr]
- ["finally" &or
- [[&optional &or "do" "doing"] &rest loop-non-atomic-expr]
- ["return" form]]))
-
-(def-edebug-spec loop-and-clause
- (loop-clause &rest ["and" loop-clause]))
-
-(def-edebug-spec loop-clause
- (&or
- [[&or "while" "until" "always" "never" "thereis"] form]
-
- [[&or "collect" "collecting"
- "append" "appending"
- "nconc" "nconcing"
- "concat" "vconcat"] form
- [&optional ["into" loop-var]]]
-
- [[&or "count" "counting"
- "sum" "summing"
- "maximize" "maximizing"
- "minimize" "minimizing"] form
- [&optional ["into" loop-var]]
- loop-type-spec]
-
- [[&or "if" "when" "unless"]
- form loop-and-clause
- [&optional ["else" loop-and-clause]]
- [&optional "end"]]
-
- [[&or "do" "doing"] &rest loop-non-atomic-expr]
-
- ["return" form]
- loop-initial-final
- ))
-
-(def-edebug-spec loop-non-atomic-expr
- ([&not atom] form))
-
-(def-edebug-spec loop-var
- ;; The symbolp must be last alternative to recognize e.g. (a b . c)
- ;; loop-var =>
- ;; (loop-var . [&or nil loop-var])
- ;; (symbolp . [&or nil loop-var])
- ;; (symbolp . loop-var)
- ;; (symbolp . (symbolp . [&or nil loop-var]))
- ;; (symbolp . (symbolp . loop-var))
- ;; (symbolp . (symbolp . symbolp)) == (symbolp symbolp . symbolp)
- (&or (loop-var . [&or nil loop-var]) [gate symbolp]))
-
-(def-edebug-spec loop-type-spec
- (&optional ["of-type" loop-d-type-spec]))
-
-(def-edebug-spec loop-d-type-spec
- (&or (loop-d-type-spec . [&or nil loop-d-type-spec]) cl-type-spec))
-
diff --git a/lisp/emacs-lisp/cl.el b/lisp/emacs-lisp/cl.el
deleted file mode 100644
index 29ec602f231..00000000000
--- a/lisp/emacs-lisp/cl.el
+++ /dev/null
@@ -1,765 +0,0 @@
-;;; cl.el --- Common Lisp extensions for Emacs -*-byte-compile-dynamic: t;-*-
-
-;; Copyright (C) 1993 Free Software Foundation, Inc.
-
-;; Author: Dave Gillespie <daveg@synaptics.com>
-;; Version: 2.02
-;; Keywords: extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; These are extensions to Emacs Lisp that provide a degree of
-;; Common Lisp compatibility, beyond what is already built-in
-;; in Emacs Lisp.
-;;
-;; This package was written by Dave Gillespie; it is a complete
-;; rewrite of Cesar Quiroz's original cl.el package of December 1986.
-;;
-;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19.
-;;
-;; Bug reports, comments, and suggestions are welcome!
-
-;; This file contains the portions of the Common Lisp extensions
-;; package which should always be present.
-
-
-;;; Future notes:
-
-;; Once Emacs 19 becomes standard, many things in this package which are
-;; messy for reasons of compatibility can be greatly simplified. For now,
-;; I prefer to maintain one unified version.
-
-
-;;; Change Log:
-
-;; Version 2.02 (30 Jul 93):
-;; * Added "cl-compat.el" file, extra compatibility with old package.
-;; * Added `lexical-let' and `lexical-let*'.
-;; * Added `define-modify-macro', `callf', and `callf2'.
-;; * Added `ignore-errors'.
-;; * Changed `(setf (nthcdr N PLACE) X)' to work when N is zero.
-;; * Merged `*gentemp-counter*' into `*gensym-counter*'.
-;; * Extended `subseq' to allow negative START and END like `substring'.
-;; * Added `in-ref', `across-ref', `elements of-ref' loop clauses.
-;; * Added `concat', `vconcat' loop clauses.
-;; * Cleaned up a number of compiler warnings.
-
-;; Version 2.01 (7 Jul 93):
-;; * Added support for FSF version of Emacs 19.
-;; * Added `add-hook' for Emacs 18 users.
-;; * Added `defsubst*' and `symbol-macrolet'.
-;; * Added `maplist', `mapc', `mapl', `mapcan', `mapcon'.
-;; * Added `map', `concatenate', `reduce', `merge'.
-;; * Added `revappend', `nreconc', `tailp', `tree-equal'.
-;; * Added `assert', `check-type', `typecase', `typep', and `deftype'.
-;; * Added destructuring and `&environment' support to `defmacro*'.
-;; * Added destructuring to `loop', and added the following clauses:
-;; `elements', `frames', `overlays', `intervals', `buffers', `key-seqs'.
-;; * Renamed `delete' to `delete*' and `remove' to `remove*'.
-;; * Completed support for all keywords in `remove*', `substitute', etc.
-;; * Added `most-positive-float' and company.
-;; * Fixed hash tables to work with latest Lucid Emacs.
-;; * `proclaim' forms are no longer compile-time-evaluating; use `declaim'.
-;; * Syntax for `warn' declarations has changed.
-;; * Improved implementation of `random*'.
-;; * Moved most sequence functions to a new file, cl-seq.el.
-;; * Moved `eval-when' into cl-macs.el.
-;; * Moved `pushnew' and `adjoin' to cl.el for most common cases.
-;; * Moved `provide' forms down to ends of files.
-;; * Changed expansion of `pop' to something that compiles to better code.
-;; * Changed so that no patch is required for Emacs 19 byte compiler.
-;; * Made more things dependent on `optimize' declarations.
-;; * Added a partial implementation of struct print functions.
-;; * Miscellaneous minor changes.
-
-;; Version 2.00:
-;; * First public release of this package.
-
-
-;;; Code:
-
-(defvar cl-emacs-type (cond ((or (and (fboundp 'epoch::version)
- (symbol-value 'epoch::version))
- (string-lessp emacs-version "19")) 18)
- ((string-match "Lucid" emacs-version) 'lucid)
- (t 19)))
-
-(or (fboundp 'defalias) (fset 'defalias 'fset))
-
-(defvar cl-optimize-speed 1)
-(defvar cl-optimize-safety 1)
-
-
-;;; Keywords used in this package.
-
-(defconst :test ':test)
-(defconst :test-not ':test-not)
-(defconst :key ':key)
-(defconst :start ':start)
-(defconst :start1 ':start1)
-(defconst :start2 ':start2)
-(defconst :end ':end)
-(defconst :end1 ':end1)
-(defconst :end2 ':end2)
-(defconst :count ':count)
-(defconst :initial-value ':initial-value)
-(defconst :size ':size)
-(defconst :from-end ':from-end)
-(defconst :rehash-size ':rehash-size)
-(defconst :rehash-threshold ':rehash-threshold)
-(defconst :allow-other-keys ':allow-other-keys)
-
-
-(defvar custom-print-functions nil
- "This is a list of functions that format user objects for printing.
-Each function is called in turn with three arguments: the object, the
-stream, and the print level (currently ignored). If it is able to
-print the object it returns true; otherwise it returns nil and the
-printer proceeds to the next function on the list.
-
-This variable is not used at present, but it is defined in hopes that
-a future Emacs interpreter will be able to use it.")
-
-
-;;; Predicates.
-
-(defun eql (a b) ; See compiler macro in cl-macs.el
- "T if the two args are the same Lisp object.
-Floating-point numbers of equal value are `eql', but they may not be `eq'."
- (if (numberp a)
- (equal a b)
- (eq a b)))
-
-
-;;; Generalized variables. These macros are defined here so that they
-;;; can safely be used in .emacs files.
-
-(defmacro incf (place &optional x)
- "(incf PLACE [X]): increment PLACE by X (1 by default).
-PLACE may be a symbol, or any generalized variable allowed by `setf'.
-The return value is the incremented value of PLACE."
- (if (symbolp place)
- (list 'setq place (if x (list '+ place x) (list '1+ place)))
- (list 'callf '+ place (or x 1))))
-
-(defmacro decf (place &optional x)
- "(decf PLACE [X]): decrement PLACE by X (1 by default).
-PLACE may be a symbol, or any generalized variable allowed by `setf'.
-The return value is the decremented value of PLACE."
- (if (symbolp place)
- (list 'setq place (if x (list '- place x) (list '1- place)))
- (list 'callf '- place (or x 1))))
-
-(defmacro pop (place)
- "(pop PLACE): remove and return the head of the list stored in PLACE.
-Analogous to (prog1 (car PLACE) (setf PLACE (cdr PLACE))), though more
-careful about evaluating each argument only once and in the right order.
-PLACE may be a symbol, or any generalized variable allowed by `setf'."
- (if (symbolp place)
- (list 'car (list 'prog1 place (list 'setq place (list 'cdr place))))
- (cl-do-pop place)))
-
-(defmacro push (x place)
- "(push X PLACE): insert X at the head of the list stored in PLACE.
-Analogous to (setf PLACE (cons X PLACE)), though more careful about
-evaluating each argument only once and in the right order. PLACE may
-be a symbol, or any generalized variable allowed by `setf'."
- (if (symbolp place) (list 'setq place (list 'cons x place))
- (list 'callf2 'cons x place)))
-
-(defmacro pushnew (x place &rest keys)
- "(pushnew X PLACE): insert X at the head of the list if not already there.
-Like (push X PLACE), except that the list is unmodified if X is `eql' to
-an element already on the list.
-Keywords supported: :test :test-not :key"
- (if (symbolp place) (list 'setq place (list* 'adjoin x place keys))
- (list* 'callf2 'adjoin x place keys)))
-
-(defun cl-set-elt (seq n val)
- (if (listp seq) (setcar (nthcdr n seq) val) (aset seq n val)))
-
-(defun cl-set-nthcdr (n list x)
- (if (<= n 0) x (setcdr (nthcdr (1- n) list) x) list))
-
-(defun cl-set-buffer-substring (start end val)
- (save-excursion (delete-region start end)
- (goto-char start)
- (insert val)
- val))
-
-(defun cl-set-substring (str start end val)
- (if end (if (< end 0) (incf end (length str)))
- (setq end (length str)))
- (if (< start 0) (incf start str))
- (concat (and (> start 0) (substring str 0 start))
- val
- (and (< end (length str)) (substring str end))))
-
-
-;;; Control structures.
-
-;;; These macros are so simple and so often-used that it's better to have
-;;; them all the time than to load them from cl-macs.el.
-
-(defmacro when (cond &rest body)
- "(when COND BODY...): if COND yields non-nil, do BODY, else return nil."
- (list 'if cond (cons 'progn body)))
-
-(defmacro unless (cond &rest body)
- "(unless COND BODY...): if COND yields nil, do BODY, else return nil."
- (cons 'if (cons cond (cons nil body))))
-
-(defun cl-map-extents (&rest cl-args)
- (if (fboundp 'next-overlay-at) (apply 'cl-map-overlays cl-args)
- (if (fboundp 'map-extents) (apply 'map-extents cl-args))))
-
-
-;;; Blocks and exits.
-
-(defalias 'cl-block-wrapper 'identity)
-(defalias 'cl-block-throw 'throw)
-
-
-;;; Multiple values. True multiple values are not supported, or even
-;;; simulated. Instead, multiple-value-bind and friends simply expect
-;;; the target form to return the values as a list.
-
-(defalias 'values 'list)
-(defalias 'values-list 'identity)
-(defalias 'multiple-value-list 'identity)
-(defalias 'multiple-value-call 'apply) ; only works for one arg
-(defalias 'nth-value 'nth)
-
-
-;;; Macros.
-
-(defvar cl-macro-environment nil)
-(defvar cl-old-macroexpand (prog1 (symbol-function 'macroexpand)
- (defalias 'macroexpand 'cl-macroexpand)))
-
-(defun cl-macroexpand (cl-macro &optional cl-env)
- "Return result of expanding macros at top level of FORM.
-If FORM is not a macro call, it is returned unchanged.
-Otherwise, the macro is expanded and the expansion is considered
-in place of FORM. When a non-macro-call results, it is returned.
-
-The second optional arg ENVIRONMENT species an environment of macro
-definitions to shadow the loaded ones for use in file byte-compilation."
- (let ((cl-macro-environment cl-env))
- (while (progn (setq cl-macro (funcall cl-old-macroexpand cl-macro cl-env))
- (and (symbolp cl-macro)
- (cdr (assq (symbol-name cl-macro) cl-env))))
- (setq cl-macro (cadr (assq (symbol-name cl-macro) cl-env))))
- cl-macro))
-
-
-;;; Declarations.
-
-(defvar cl-compiling-file nil)
-(defun cl-compiling-file ()
- (or cl-compiling-file
- (and (boundp 'outbuffer) (bufferp (symbol-value 'outbuffer))
- (equal (buffer-name (symbol-value 'outbuffer))
- " *Compiler Output*"))))
-
-(defvar cl-proclaims-deferred nil)
-
-(defun proclaim (spec)
- (if (fboundp 'cl-do-proclaim) (cl-do-proclaim spec t)
- (push spec cl-proclaims-deferred))
- nil)
-
-(defmacro declaim (&rest specs)
- (let ((body (mapcar (function (lambda (x) (list 'proclaim (list 'quote x))))
- specs)))
- (if (cl-compiling-file) (list* 'eval-when '(compile load eval) body)
- (cons 'progn body)))) ; avoid loading cl-macs.el for eval-when
-
-
-;;; Symbols.
-
-(defun cl-random-time ()
- (let* ((time (copy-sequence (current-time-string))) (i (length time)) (v 0))
- (while (>= (decf i) 0) (setq v (+ (* v 3) (aref time i))))
- v))
-
-(defvar *gensym-counter* (* (logand (cl-random-time) 1023) 100))
-
-
-;;; Numbers.
-
-(defun floatp-safe (x)
- "T if OBJECT is a floating point number.
-On Emacs versions that lack floating-point support, this function
-always returns nil."
- (and (numberp x) (not (integerp x))))
-
-(defun plusp (x)
- "T if NUMBER is positive."
- (> x 0))
-
-(defun minusp (x)
- "T if NUMBER is negative."
- (< x 0))
-
-(defun oddp (x)
- "T if INTEGER is odd."
- (eq (logand x 1) 1))
-
-(defun evenp (x)
- "T if INTEGER is even."
- (eq (logand x 1) 0))
-
-(defun cl-abs (x)
- "Return the absolute value of ARG."
- (if (>= x 0) x (- x)))
-(or (fboundp 'abs) (defalias 'abs 'cl-abs)) ; This is built-in to Emacs 19
-
-(defvar *random-state* (vector 'cl-random-state-tag -1 30 (cl-random-time)))
-
-;;; We use `eval' in case VALBITS differs from compile-time to load-time.
-(defconst most-positive-fixnum (eval '(lsh -1 -1)))
-(defconst most-negative-fixnum (eval '(- -1 (lsh -1 -1))))
-
-;;; The following are actually set by cl-float-limits.
-(defconst most-positive-float nil)
-(defconst most-negative-float nil)
-(defconst least-positive-float nil)
-(defconst least-negative-float nil)
-(defconst least-positive-normalized-float nil)
-(defconst least-negative-normalized-float nil)
-(defconst float-epsilon nil)
-(defconst float-negative-epsilon nil)
-
-
-;;; Sequence functions.
-
-(defalias 'copy-seq 'copy-sequence)
-
-(defun mapcar* (cl-func cl-x &rest cl-rest)
- "Apply FUNCTION to each element of SEQ, and make a list of the results.
-If there are several SEQs, FUNCTION is called with that many arguments,
-and mapping stops as soon as the shortest list runs out. With just one
-SEQ, this is like `mapcar'. With several, it is like the Common Lisp
-`mapcar' function extended to arbitrary sequence types."
- (if cl-rest
- (if (or (cdr cl-rest) (nlistp cl-x) (nlistp (car cl-rest)))
- (cl-mapcar-many cl-func (cons cl-x cl-rest))
- (let ((cl-res nil) (cl-y (car cl-rest)))
- (while (and cl-x cl-y)
- (push (funcall cl-func (pop cl-x) (pop cl-y)) cl-res))
- (nreverse cl-res)))
- (mapcar cl-func cl-x)))
-
-
-;;; List functions.
-
-(defalias 'first 'car)
-(defalias 'rest 'cdr)
-(defalias 'endp 'null)
-
-(defun second (x)
- "Return the second element of the list LIST."
- (car (cdr x)))
-
-(defun third (x)
- "Return the third element of the list LIST."
- (car (cdr (cdr x))))
-
-(defun fourth (x)
- "Return the fourth element of the list LIST."
- (nth 3 x))
-
-(defun fifth (x)
- "Return the fifth element of the list LIST."
- (nth 4 x))
-
-(defun sixth (x)
- "Return the sixth element of the list LIST."
- (nth 5 x))
-
-(defun seventh (x)
- "Return the seventh element of the list LIST."
- (nth 6 x))
-
-(defun eighth (x)
- "Return the eighth element of the list LIST."
- (nth 7 x))
-
-(defun ninth (x)
- "Return the ninth element of the list LIST."
- (nth 8 x))
-
-(defun tenth (x)
- "Return the tenth element of the list LIST."
- (nth 9 x))
-
-(defun caar (x)
- "Return the `car' of the `car' of X."
- (car (car x)))
-
-(defun cadr (x)
- "Return the `car' of the `cdr' of X."
- (car (cdr x)))
-
-(defun cdar (x)
- "Return the `cdr' of the `car' of X."
- (cdr (car x)))
-
-(defun cddr (x)
- "Return the `cdr' of the `cdr' of X."
- (cdr (cdr x)))
-
-(defun caaar (x)
- "Return the `car' of the `car' of the `car' of X."
- (car (car (car x))))
-
-(defun caadr (x)
- "Return the `car' of the `car' of the `cdr' of X."
- (car (car (cdr x))))
-
-(defun cadar (x)
- "Return the `car' of the `cdr' of the `car' of X."
- (car (cdr (car x))))
-
-(defun caddr (x)
- "Return the `car' of the `cdr' of the `cdr' of X."
- (car (cdr (cdr x))))
-
-(defun cdaar (x)
- "Return the `cdr' of the `car' of the `car' of X."
- (cdr (car (car x))))
-
-(defun cdadr (x)
- "Return the `cdr' of the `car' of the `cdr' of X."
- (cdr (car (cdr x))))
-
-(defun cddar (x)
- "Return the `cdr' of the `cdr' of the `car' of X."
- (cdr (cdr (car x))))
-
-(defun cdddr (x)
- "Return the `cdr' of the `cdr' of the `cdr' of X."
- (cdr (cdr (cdr x))))
-
-(defun caaaar (x)
- "Return the `car' of the `car' of the `car' of the `car' of X."
- (car (car (car (car x)))))
-
-(defun caaadr (x)
- "Return the `car' of the `car' of the `car' of the `cdr' of X."
- (car (car (car (cdr x)))))
-
-(defun caadar (x)
- "Return the `car' of the `car' of the `cdr' of the `car' of X."
- (car (car (cdr (car x)))))
-
-(defun caaddr (x)
- "Return the `car' of the `car' of the `cdr' of the `cdr' of X."
- (car (car (cdr (cdr x)))))
-
-(defun cadaar (x)
- "Return the `car' of the `cdr' of the `car' of the `car' of X."
- (car (cdr (car (car x)))))
-
-(defun cadadr (x)
- "Return the `car' of the `cdr' of the `car' of the `cdr' of X."
- (car (cdr (car (cdr x)))))
-
-(defun caddar (x)
- "Return the `car' of the `cdr' of the `cdr' of the `car' of X."
- (car (cdr (cdr (car x)))))
-
-(defun cadddr (x)
- "Return the `car' of the `cdr' of the `cdr' of the `cdr' of X."
- (car (cdr (cdr (cdr x)))))
-
-(defun cdaaar (x)
- "Return the `cdr' of the `car' of the `car' of the `car' of X."
- (cdr (car (car (car x)))))
-
-(defun cdaadr (x)
- "Return the `cdr' of the `car' of the `car' of the `cdr' of X."
- (cdr (car (car (cdr x)))))
-
-(defun cdadar (x)
- "Return the `cdr' of the `car' of the `cdr' of the `car' of X."
- (cdr (car (cdr (car x)))))
-
-(defun cdaddr (x)
- "Return the `cdr' of the `car' of the `cdr' of the `cdr' of X."
- (cdr (car (cdr (cdr x)))))
-
-(defun cddaar (x)
- "Return the `cdr' of the `cdr' of the `car' of the `car' of X."
- (cdr (cdr (car (car x)))))
-
-(defun cddadr (x)
- "Return the `cdr' of the `cdr' of the `car' of the `cdr' of X."
- (cdr (cdr (car (cdr x)))))
-
-(defun cdddar (x)
- "Return the `cdr' of the `cdr' of the `cdr' of the `car' of X."
- (cdr (cdr (cdr (car x)))))
-
-(defun cddddr (x)
- "Return the `cdr' of the `cdr' of the `cdr' of the `cdr' of X."
- (cdr (cdr (cdr (cdr x)))))
-
-(defun last (x &optional n)
- "Returns the last link in the list LIST.
-With optional argument N, returns Nth-to-last link (default 1)."
- (if n
- (let ((m 0) (p x))
- (while (consp p) (incf m) (pop p))
- (if (<= n 0) p
- (if (< n m) (nthcdr (- m n) x) x)))
- (while (consp (cdr x)) (pop x))
- x))
-
-(defun butlast (x &optional n)
- "Returns a copy of LIST with the last N elements removed."
- (if (and n (<= n 0)) x
- (nbutlast (copy-sequence x) n)))
-
-(defun nbutlast (x &optional n)
- "Modifies LIST to remove the last N elements."
- (let ((m (length x)))
- (or n (setq n 1))
- (and (< n m)
- (progn
- (if (> n 0) (setcdr (nthcdr (- (1- m) n) x) nil))
- x))))
-
-(defun list* (arg &rest rest) ; See compiler macro in cl-macs.el
- "Return a new list with specified args as elements, cons'd to last arg.
-Thus, `(list* A B C D)' is equivalent to `(nconc (list A B C) D)', or to
-`(cons A (cons B (cons C D)))'."
- (cond ((not rest) arg)
- ((not (cdr rest)) (cons arg (car rest)))
- (t (let* ((n (length rest))
- (copy (copy-sequence rest))
- (last (nthcdr (- n 2) copy)))
- (setcdr last (car (cdr last)))
- (cons arg copy)))))
-
-(defun ldiff (list sublist)
- "Return a copy of LIST with the tail SUBLIST removed."
- (let ((res nil))
- (while (and (consp list) (not (eq list sublist)))
- (push (pop list) res))
- (nreverse res)))
-
-(defun copy-list (list)
- "Return a copy of a list, which may be a dotted list.
-The elements of the list are not copied, just the list structure itself."
- (if (consp list)
- (let ((res nil))
- (while (consp list) (push (pop list) res))
- (prog1 (nreverse res) (setcdr res list)))
- (car list)))
-
-(defun cl-maclisp-member (item list)
- (while (and list (not (equal item (car list)))) (setq list (cdr list)))
- list)
-
-;;; Define an Emacs 19-compatible `member' for the benefit of Emacs 18 users.
-(or (and (fboundp 'member) (subrp (symbol-function 'member)))
- (defalias 'member 'cl-maclisp-member))
-
-(defalias 'cl-member 'memq) ; for compatibility with old CL package
-(defalias 'cl-floor 'floor*)
-(defalias 'cl-ceiling 'ceiling*)
-(defalias 'cl-truncate 'truncate*)
-(defalias 'cl-round 'round*)
-(defalias 'cl-mod 'mod*)
-
-(defun adjoin (cl-item cl-list &rest cl-keys) ; See compiler macro in cl-macs
- "Return ITEM consed onto the front of LIST only if it's not already there.
-Otherwise, return LIST unmodified.
-Keywords supported: :test :test-not :key"
- (cond ((or (equal cl-keys '(:test eq))
- (and (null cl-keys) (not (numberp cl-item))))
- (if (memq cl-item cl-list) cl-list (cons cl-item cl-list)))
- ((or (equal cl-keys '(:test equal)) (null cl-keys))
- (if (member cl-item cl-list) cl-list (cons cl-item cl-list)))
- (t (apply 'cl-adjoin cl-item cl-list cl-keys))))
-
-(defun subst (cl-new cl-old cl-tree &rest cl-keys)
- "Substitute NEW for OLD everywhere in TREE (non-destructively).
-Return a copy of TREE with all elements `eql' to OLD replaced by NEW.
-Keywords supported: :test :test-not :key"
- (if (or cl-keys (and (numberp cl-old) (not (integerp cl-old))))
- (apply 'sublis (list (cons cl-old cl-new)) cl-tree cl-keys)
- (cl-do-subst cl-new cl-old cl-tree)))
-
-(defun cl-do-subst (cl-new cl-old cl-tree)
- (cond ((eq cl-tree cl-old) cl-new)
- ((consp cl-tree)
- (let ((a (cl-do-subst cl-new cl-old (car cl-tree)))
- (d (cl-do-subst cl-new cl-old (cdr cl-tree))))
- (if (and (eq a (car cl-tree)) (eq d (cdr cl-tree)))
- cl-tree (cons a d))))
- (t cl-tree)))
-
-(defun acons (a b c) (cons (cons a b) c))
-(defun pairlis (a b &optional c) (nconc (mapcar* 'cons a b) c))
-
-
-;;; Miscellaneous.
-
-(put 'cl-assertion-failed 'error-conditions '(error))
-(put 'cl-assertion-failed 'error-message "Assertion failed")
-
-;;; This is defined in Emacs 19; define it here for Emacs 18 users.
-(defun cl-add-hook (hook func &optional append)
- "Add to hook variable HOOK the function FUNC.
-FUNC is not added if it already appears on the list stored in HOOK."
- (let ((old (and (boundp hook) (symbol-value hook))))
- (and (listp old) (not (eq (car old) 'lambda))
- (setq old (list old)))
- (and (not (member func old))
- (set hook (if append (nconc old (list func)) (cons func old))))))
-(or (fboundp 'add-hook) (defalias 'add-hook 'cl-add-hook))
-
-
-;;; Autoload the other portions of the package.
-(mapcar (function
- (lambda (set)
- (mapcar (function
- (lambda (func)
- (autoload func (car set) nil nil (nth 1 set))))
- (cddr set))))
- '(("cl-extra" nil
- coerce equalp cl-map-keymap maplist mapc mapl mapcan mapcon
- cl-map-keymap cl-map-keymap-recursively cl-map-intervals
- cl-map-overlays cl-set-frame-visible-p cl-float-limits
- gcd lcm isqrt expt floor* ceiling* truncate* round*
- mod* rem* signum random* make-random-state random-state-p
- subseq concatenate cl-mapcar-many map some every notany
- notevery revappend nreconc list-length tailp copy-tree get* getf
- cl-set-getf cl-do-remf remprop make-hash-table cl-hash-lookup
- gethash cl-puthash remhash clrhash maphash hash-table-p
- hash-table-count cl-progv-before cl-prettyexpand
- cl-macroexpand-all)
- ("cl-seq" nil
- reduce fill replace remq remove remove* remove-if remove-if-not
- delete delete* delete-if delete-if-not remove-duplicates
- delete-duplicates substitute substitute-if substitute-if-not
- nsubstitute nsubstitute-if nsubstitute-if-not find find-if
- find-if-not position position-if position-if-not count count-if
- count-if-not mismatch search sort* stable-sort merge member*
- member-if member-if-not cl-adjoin assoc* assoc-if assoc-if-not
- rassoc* rassoc rassoc-if rassoc-if-not union nunion intersection
- nintersection set-difference nset-difference set-exclusive-or
- nset-exclusive-or subsetp subst-if subst-if-not nsubst nsubst-if
- nsubst-if-not sublis nsublis tree-equal)
- ("cl-macs" nil
- gensym gentemp typep cl-do-pop get-setf-method
- cl-struct-setf-expander compiler-macroexpand cl-compile-time-init)
- ("cl-macs" t
- defun* defmacro* function* destructuring-bind eval-when
- eval-when-compile load-time-value case ecase typecase etypecase
- block return return-from loop do do* dolist dotimes do-symbols
- do-all-symbols psetq progv flet labels macrolet symbol-macrolet
- lexical-let lexical-let* multiple-value-bind multiple-value-setq
- locally the declare define-setf-method defsetf define-modify-macro
- setf psetf remf shiftf rotatef letf letf* callf callf2 defstruct
- check-type assert ignore-errors define-compiler-macro)))
-
-;;; Define data for indentation and edebug.
-(mapcar (function
- (lambda (entry)
- (mapcar (function
- (lambda (func)
- (put func 'lisp-indent-function (nth 1 entry))
- (put func 'lisp-indent-hook (nth 1 entry))
- (or (get func 'edebug-form-spec)
- (put func 'edebug-form-spec (nth 2 entry)))))
- (car entry))))
- '(((defun* defmacro*) 2)
- ((function*) nil
- (&or symbolp ([&optional 'macro] 'lambda (&rest sexp) &rest form)))
- ((eval-when) 1 (sexp &rest form))
- ((when unless) 1 (&rest form))
- ((declare) nil (&rest sexp))
- ((the) 1 (sexp &rest form))
- ((case ecase typecase etypecase) 1 (form &rest (sexp &rest form)))
- ((block return-from) 1 (sexp &rest form))
- ((return) nil (&optional form))
- ((do do*) 2 ((&rest &or symbolp (symbolp &optional form form))
- (form &rest form)
- &rest form))
- ((dolist dotimes) 1 ((symbolp form &rest form) &rest form))
- ((do-symbols) 1 ((symbolp form &optional form form) &rest form))
- ((do-all-symbols) 1 ((symbolp form &optional form) &rest form))
- ((psetq setf psetf) nil edebug-setq-form)
- ((progv) 2 (&rest form))
- ((flet labels macrolet) 1
- ((&rest (sexp sexp &rest form)) &rest form))
- ((symbol-macrolet lexical-let lexical-let*) 1
- ((&rest &or symbolp (symbolp form)) &rest form))
- ((multiple-value-bind) 2 ((&rest symbolp) &rest form))
- ((multiple-value-setq) 1 ((&rest symbolp) &rest form))
- ((incf decf remf pop push pushnew shiftf rotatef) nil (&rest form))
- ((letf letf*) 1 ((&rest (&rest form)) &rest form))
- ((callf destructuring-bind) 2 (sexp form &rest form))
- ((callf2) 3 (sexp form form &rest form))
- ((loop) nil (&rest &or symbolp form))
- ((ignore-errors) 0 (&rest form))))
-
-
-;;; This goes here so that cl-macs can find it if it loads right now.
-(provide 'cl-19) ; usage: (require 'cl-19 "cl")
-
-
-;;; Things to do after byte-compiler is loaded.
-;;; As a side effect, we cause cl-macs to be loaded when compiling, so
-;;; that the compiler-macros defined there will be present.
-
-(defvar cl-hacked-flag nil)
-(defun cl-hack-byte-compiler ()
- (if (and (not cl-hacked-flag) (fboundp 'byte-compile-file-form))
- (progn
- (cl-compile-time-init) ; in cl-macs.el
- (setq cl-hacked-flag t))))
-
-;;; Try it now in case the compiler has already been loaded.
-(cl-hack-byte-compiler)
-
-;;; Also make a hook in case compiler is loaded after this file.
-;;; The compiler doesn't call any hooks when it loads or runs, but
-;;; we can take advantage of the fact that emacs-lisp-mode will be
-;;; called when the compiler reads in the file to be compiled.
-;;; BUG: If the first compilation is `byte-compile' rather than
-;;; `byte-compile-file', we lose. Oh, well.
-(add-hook 'emacs-lisp-mode-hook 'cl-hack-byte-compiler)
-
-
-;;; The following ensures that packages which expect the old-style cl.el
-;;; will be happy with this one.
-
-(provide 'cl)
-
-(provide 'mini-cl) ; for Epoch
-
-(run-hooks 'cl-load-hook)
-
-;;; cl.el ends here
diff --git a/lisp/emacs-lisp/copyright.el b/lisp/emacs-lisp/copyright.el
deleted file mode 100644
index f8ba8c04404..00000000000
--- a/lisp/emacs-lisp/copyright.el
+++ /dev/null
@@ -1,143 +0,0 @@
-;;; copyright.el --- update the copyright notice in current buffer
-
-;; Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389
-;; Keywords: maint, tools
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Allows updating the copyright year and above mentioned GPL version manually
-;; or when saving a file. Do (add-hook 'write-file-hooks 'copyright-update).
-
-;;; Code:
-
-(defvar copyright-limit 2000
- "*Don't try to update copyright beyond this position unless interactive.
-`nil' means to search whole buffer.")
-
-
-(defvar copyright-regexp
- "\\(\251\\|[Cc]opyright\\s *:?\\s *(C)\\)\\s *\\([1-9][-0-9, ']*[0-9]+\\) "
- "*What your copyright notice looks like.
-The second \\( \\) construct must match the years.")
-
-
-(defvar copyright-query 'function
- "*If non-`nil', ask user before changing copyright.
-When this is `function', only ask when called non-interactively.")
-
-
-(defconst copyright-current-year (substring (current-time-string) -4)
- "String representing the current year.")
-
-
-;; when modifying this, also modify the comment generated by autoinsert.el
-(defconst copyright-current-gpl-version "2"
- "String representing the current version of the GPL or `nil'.")
-
-(defvar copyright-update t)
-
-;;;###autoload
-(defun copyright-update (&optional arg)
- "Update the copyright notice at the beginning of the buffer to indicate
-the current year. If optional prefix ARG is given replace the years in the
-notice rather than adding the current year after them. If necessary and
-`copyright-current-gpl-version' is set, the copying permissions following the
-copyright, if any, are updated as well."
- (interactive "*P")
- (if copyright-update
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (if (re-search-forward copyright-regexp copyright-limit t)
- (if (string= (buffer-substring (- (match-end 2) 2) (match-end 2))
- (substring copyright-current-year -2))
- ()
- (backward-char 1)
- (if (or (not copyright-query)
- (and (eq copyright-query 'function)
- (eq this-command 'copyright-update))
- (y-or-n-p (if arg
- (concat "Replace copyright year(s) by "
- copyright-current-year "? ")
- (concat "Add " copyright-current-year
- " to copyright? "))))
- (if arg
- (progn
- (delete-region (match-beginning 1) (match-end 1))
- (insert copyright-current-year))
- (setq arg (save-excursion (skip-chars-backward "0-9")))
- (if (and (eq (% (- (string-to-number
- copyright-current-year)
- (string-to-number (buffer-substring
- (+ (point) arg)
- (point))))
- 100)
- 1)
- (or (eq (char-after (+ (point) arg -1)) ?-)
- (eq (char-after (+ (point) arg -2)) ?-)))
- (delete-char arg)
- (insert ", ")
- (if (eq (char-after (+ (point) arg -3)) ?')
- (insert ?')))
- (insert (substring copyright-current-year arg))))))
- (goto-char (point-min))
- (and copyright-current-gpl-version
- ;; match the GPL version comment in .el files, including the
- ;; bilingual Esperanto one in two-column, and in texinfo.tex
- (re-search-forward "\\(the Free Software Foundation; either \\|; a\\^u eldono \\([0-9]+\\)a, ? a\\^u (la\\^u via \\)version \\([0-9]+\\), or (at"
- copyright-limit t)
- (not (string= (buffer-substring (match-beginning 3) (match-end 3))
- copyright-current-gpl-version))
- (or (not copyright-query)
- (and (eq copyright-query 'function)
- (eq this-command 'copyright-update))
- (y-or-n-p (concat "Replace GPL version by "
- copyright-current-gpl-version "? ")))
- (progn
- (if (match-end 2)
- ;; Esperanto bilingual comment in two-column.el
- (progn
- (delete-region (match-beginning 2) (match-end 2))
- (goto-char (match-beginning 2))
- (insert copyright-current-gpl-version)))
- (delete-region (match-beginning 3) (match-end 3))
- (goto-char (match-beginning 3))
- (insert copyright-current-gpl-version))))
- (set (make-local-variable 'copyright-update) nil)))
- ;; If a write-file-hook returns non-nil, the file is presumed to be written.
- nil)
-
-
-;;;###autoload
-(define-skeleton copyright
- "Insert a copyright by $ORGANIZATION notice at cursor."
- "Company: "
- comment-start
- "Copyright (C) " copyright-current-year " by "
- (or (getenv "ORGANIZATION")
- str)
- '(if (> (point) copyright-limit)
- (message "Copyright extends beyond `copyright-limit' and won't be updated automatically."))
- comment-end)
-
-;; copyright.el ends here
diff --git a/lisp/emacs-lisp/cust-print.el b/lisp/emacs-lisp/cust-print.el
deleted file mode 100644
index 0c80b6c8bdb..00000000000
--- a/lisp/emacs-lisp/cust-print.el
+++ /dev/null
@@ -1,725 +0,0 @@
-;;; cust-print.el --- handles print-level and print-circle.
-
-;; Copyright (C) 1992 Free Software Foundation, Inc.
-
-;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
-;; Adapted-By: ESR
-;; Keywords: extensions
-
-;; LCD Archive Entry:
-;; cust-print|Daniel LaLiberte|liberte@cs.uiuc.edu
-;; |Handle print-level, print-circle and more.
-;; |$Date: 1994/04/05 21:05:09 $|$Revision: 1.14 $|
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; ===============================
-;;; $Header: $
-;;; $Log: cust-print.el,v $
-;;; Revision 1.14 1994/04/05 21:05:09 liberte
-;;; Change install- and uninstall- to -install and -uninstall.
-;;;
-;;; Revision 1.13 1994/03/24 20:26:05 liberte
-;;; Change "internal" to "original" throughout.
-;;; (add-custom-printer, delete-custom-printer) replace customizers.
-;;; (with-custom-print) new
-;;; (custom-prin1-to-string) Made it more robust.
-;;;
-;;; Revision 1.4 1994/03/23 20:34:29 liberte
-;;; * Change "emacs" to "original" - I just can't decide.
-;;;
-;;; Revision 1.3 1994/02/21 21:25:36 liberte
-;;; * Make custom-prin1-to-string more robust when errors occur.
-;;; * Change "internal" to "emacs".
-;;;
-;;; Revision 1.2 1993/11/22 22:36:36 liberte
-;;; * Simplified and generalized printer customization.
-;;; custom-printers is an alist of (PREDICATE . PRINTER) pairs
-;;; for any data types. The PRINTER function should print to
-;;; `standard-output' add-custom-printer and delete-custom-printer
-;;; change custom-printers.
-;;;
-;;; * Installation function now called install-custom-print. The
-;;; old name is still around for now.
-;;;
-;;; * New macro with-custom-print (added earlier) - executes like
-;;; progn but with custom-print activated temporarily.
-;;;
-;;; * Cleaned up comments for replacements of standardard printers.
-;;;
-;;; * Changed custom-prin1-to-string to use a temporary buffer.
-;;;
-;;; * Option custom-print-vectors (added earlier) - controls whether
-;;; vectors should be printed according to print-length and
-;;; print-length. Emacs doesnt do this, but cust-print would
-;;; otherwise do it only if custom printing is required.
-;;;
-;;; * Uninterned symbols are treated as non-read-equivalent.
-;;;
-
-
-;;; Commentary:
-
-;; This package provides a general print handler for prin1 and princ
-;; that supports print-level and print-circle, and by the way,
-;; print-length since the standard routines are being replaced. Also,
-;; to print custom types constructed from lists and vectors, use
-;; custom-print-list and custom-print-vector. See the documentation
-;; strings of these variables for more details.
-
-;; If the results of your expressions contain circular references to
-;; other parts of the same structure, the standard Emacs print
-;; subroutines may fail to print with an untrappable error,
-;; "Apparently circular structure being printed". If you only use cdr
-;; circular lists (where cdrs of lists point back; what is the right
-;; term here?), you can limit the length of printing with
-;; print-length. But car circular lists and circular vectors generate
-;; the above mentioned error in Emacs version 18. Version
-;; 19 supports print-level, but it is often useful to get a better
-;; print representation of circular and shared structures; the print-circle
-;; option may be used to print more concise representations.
-
-;; There are three main ways to use this package. First, you may
-;; replace prin1, princ, and some subroutines that use them by calling
-;; install-custom-print so that any use of these functions in
-;; Lisp code will be affected; you can later reset with
-;; uninstall-custom-print. Second, you may temporarily install
-;; these functions with the macro with-custom-print. Third, you
-;; could call the custom routines directly, thus only affecting the
-;; printing that requires them.
-
-;; Note that subroutines which call print subroutines directly will
-;; not use the custom print functions. In particular, the evaluation
-;; functions like eval-region call the print subroutines directly.
-;; Therefore, if you evaluate (aref circ-list 0), where circ-list is a
-;; circular list rather than an array, aref calls error directly which
-;; will jump to the top level instead of printing the circular list.
-
-;; Uninterned symbols are recognized when print-circle is non-nil,
-;; but they are not printed specially here. Use the cl-packages package
-;; to print according to print-gensym.
-
-;; Obviously the right way to implement this custom-print facility is
-;; in C or with hooks into the standard printer. Please volunteer
-;; since I don't have the time or need. More CL-like printing
-;; capabilities could be added in the future.
-
-;; Implementation design: we want to use the same list and vector
-;; processing algorithm for all versions of prin1 and princ, since how
-;; the processing is done depends on print-length, print-level, and
-;; print-circle. For circle printing, a preprocessing step is
-;; required before the final printing. Thanks to Jamie Zawinski
-;; for motivation and algorithms.
-
-
-;;; Code:
-;;=========================================================
-
-;; If using cl-packages:
-
-'(defpackage "cust-print"
- (:nicknames "CP" "custom-print")
- (:use "el")
- (:export
- print-level
- print-circle
-
- custom-print-install
- custom-print-uninstall
- custom-print-installed-p
- with-custom-print
-
- custom-prin1
- custom-princ
- custom-prin1-to-string
- custom-print
- custom-format
- custom-message
- custom-error
-
- custom-printers
- add-custom-printer
- ))
-
-'(in-package cust-print)
-
-(require 'backquote)
-
-;; Emacs 18 doesnt have defalias.
-;; Provide def for byte compiler.
-(eval-and-compile
- (or (fboundp 'defalias) (fset 'defalias 'fset)))
-
-
-;; Variables:
-;;=========================================================
-
-;;(defvar print-length nil
-;; "*Controls how many elements of a list, at each level, are printed.
-;;This is defined by emacs.")
-
-(defvar print-level nil
- "*Controls how many levels deep a nested data object will print.
-
-If nil, printing proceeds recursively and may lead to
-max-lisp-eval-depth being exceeded or an error may occur:
-`Apparently circular structure being printed.'
-Also see `print-length' and `print-circle'.
-
-If non-nil, components at levels equal to or greater than `print-level'
-are printed simply as `#'. The object to be printed is at level 0,
-and if the object is a list or vector, its top-level components are at
-level 1.")
-
-
-(defvar print-circle nil
- "*Controls the printing of recursive structures.
-
-If nil, printing proceeds recursively and may lead to
-`max-lisp-eval-depth' being exceeded or an error may occur:
-\"Apparently circular structure being printed.\" Also see
-`print-length' and `print-level'.
-
-If non-nil, shared substructures anywhere in the structure are printed
-with `#N=' before the first occurrence (in the order of the print
-representation) and `#N#' in place of each subsequent occurrence,
-where N is a positive decimal integer.
-
-There is no way to read this representation in standard Emacs,
-but if you need to do so, try the cl-read.el package.")
-
-
-(defvar custom-print-vectors nil
- "*Non-nil if printing of vectors should obey print-level and print-length.
-
-For Emacs 18, setting print-level, or adding custom print list or
-vector handling will make this happen anyway. Emacs 19 obeys
-print-level, but not for vectors.")
-
-
-;; Custom printers
-;;==========================================================
-
-(defconst custom-printers nil
- ;; e.g. '((symbolp . pkg::print-symbol))
- "An alist for custom printing of any type.
-Pairs are of the form (PREDICATE . PRINTER). If PREDICATE is true
-for an object, then PRINTER is called with the object.
-PRINTER should print to `standard-output' using cust-print-original-princ
-if the standard printer is sufficient, or cust-print-prin for complex things.
-The PRINTER should return the object being printed.
-
-Don't modify this variable directly. Use `add-custom-printer' and
-`delete-custom-printer'")
-;; Should cust-print-original-princ and cust-print-prin be exported symbols?
-;; Or should the standard printers functions be replaced by
-;; CP ones in elisp so that CP internal functions need not be called?
-
-(defun add-custom-printer (pred printer)
- "Add a pair of PREDICATE and PRINTER to `custom-printers'.
-Any pair that has the same PREDICATE is first removed."
- (setq custom-printers (cons (cons pred printer)
- (delq (assq pred custom-printers)
- custom-printers)))
- ;; Rather than updating here, we could wait until cust-print-top-level is called.
- (cust-print-update-custom-printers))
-
-(defun delete-custom-printer (pred)
- "Delete the custom printer associated with PREDICATE."
- (setq custom-printers (delq (assq pred custom-printers)
- custom-printers))
- (cust-print-update-custom-printers))
-
-
-(defun cust-print-use-custom-printer (object)
- ;; Default function returns nil.
- nil)
-
-(defun cust-print-update-custom-printers ()
- ;; Modify the definition of cust-print-use-custom-printer
- (defalias 'cust-print-use-custom-printer
- ;; We dont really want to require the byte-compiler.
- ;; (byte-compile
- (` (lambda (object)
- (cond
- (,@ (mapcar (function
- (lambda (pair)
- (` (((, (car pair)) object)
- ((, (cdr pair)) object)))))
- custom-printers))
- ;; Otherwise return nil.
- (t nil)
- )))
- ;; )
- ))
-
-
-;; Saving and restoring emacs printing routines.
-;;====================================================
-
-(defun cust-print-set-function-cell (symbol-pair)
- (defalias (car symbol-pair)
- (symbol-function (car (cdr symbol-pair)))))
-
-(defun cust-print-original-princ (object &optional stream)) ; dummy def
-
-;; Save emacs routines.
-(if (not (fboundp 'cust-print-original-prin1))
- (mapcar 'cust-print-set-function-cell
- '((cust-print-original-prin1 prin1)
- (cust-print-original-princ princ)
- (cust-print-original-print print)
- (cust-print-original-prin1-to-string prin1-to-string)
- (cust-print-original-format format)
- (cust-print-original-message message)
- (cust-print-original-error error))))
-
-
-(defun custom-print-install ()
- "Replace print functions with general, customizable, Lisp versions.
-The emacs subroutines are saved away, and you can reinstall them
-by running `custom-print-uninstall'."
- (interactive)
- (mapcar 'cust-print-set-function-cell
- '((prin1 custom-prin1)
- (princ custom-princ)
- (print custom-print)
- (prin1-to-string custom-prin1-to-string)
- (format custom-format)
- (message custom-message)
- (error custom-error)
- ))
- t)
-
-(defun custom-print-uninstall ()
- "Reset print functions to their emacs subroutines."
- (interactive)
- (mapcar 'cust-print-set-function-cell
- '((prin1 cust-print-original-prin1)
- (princ cust-print-original-princ)
- (print cust-print-original-print)
- (prin1-to-string cust-print-original-prin1-to-string)
- (format cust-print-original-format)
- (message cust-print-original-message)
- (error cust-print-original-error)
- ))
- t)
-
-(defalias 'custom-print-funcs-installed-p 'custom-print-installed-p)
-(defun custom-print-installed-p ()
- "Return t if custom-print is currently installed, nil otherwise."
- (eq (symbol-function 'custom-prin1) (symbol-function 'prin1)))
-
-(put 'with-custom-print-funcs 'edebug-form-spec '(body))
-(put 'with-custom-print 'edebug-form-spec '(body))
-
-(defalias 'with-custom-print-funcs 'with-custom-print)
-(defmacro with-custom-print (&rest body)
- "Temporarily install the custom print package while executing BODY."
- (` (unwind-protect
- (progn
- (custom-print-install)
- (,@ body))
- (custom-print-uninstall))))
-
-
-;; Lisp replacements for prin1 and princ, and for some subrs that use them
-;;===============================================================
-;; - so far only the printing and formatting subrs.
-
-(defun custom-prin1 (object &optional stream)
- "Output the printed representation of OBJECT, any Lisp object.
-Quoting characters are printed when needed to make output that `read'
-can handle, whenever this is possible.
-Output stream is STREAM, or value of `standard-output' (which see).
-
-This is the custom-print replacement for the standard `prin1'. It
-uses the appropriate printer depending on the values of `print-level'
-and `print-circle' (which see)."
- (cust-print-top-level object stream 'cust-print-original-prin1))
-
-
-(defun custom-princ (object &optional stream)
- "Output the printed representation of OBJECT, any Lisp object.
-No quoting characters are used; no delimiters are printed around
-the contents of strings.
-Output stream is STREAM, or value of `standard-output' (which see).
-
-This is the custom-print replacement for the standard `princ'."
- (cust-print-top-level object stream 'cust-print-original-princ))
-
-
-(defun custom-prin1-to-string (object)
- "Return a string containing the printed representation of OBJECT,
-any Lisp object. Quoting characters are used when needed to make output
-that `read' can handle, whenever this is possible.
-
-This is the custom-print replacement for the standard `prin1-to-string'."
- (let ((buf (get-buffer-create " *custom-print-temp*")))
- ;; We must erase the buffer before printing in case an error
- ;; occured during the last prin1-to-string and we are in debugger.
- (save-excursion
- (set-buffer buf)
- (erase-buffer))
- ;; We must be in the current-buffer when the print occurs.
- (custom-prin1 object buf)
- (save-excursion
- (set-buffer buf)
- (buffer-string)
- ;; We could erase the buffer again, but why bother?
- )))
-
-
-(defun custom-print (object &optional stream)
- "Output the printed representation of OBJECT, with newlines around it.
-Quoting characters are printed when needed to make output that `read'
-can handle, whenever this is possible.
-Output stream is STREAM, or value of `standard-output' (which see).
-
-This is the custom-print replacement for the standard `print'."
- (cust-print-original-princ "\n" stream)
- (custom-prin1 object stream)
- (cust-print-original-princ "\n" stream))
-
-
-(defun custom-format (fmt &rest args)
- "Format a string out of a control-string and arguments.
-The first argument is a control string. It, and subsequent arguments
-substituted into it, become the value, which is a string.
-It may contain %s or %d or %c to substitute successive following arguments.
-%s means print an argument as a string, %d means print as number in decimal,
-%c means print a number as a single character.
-The argument used by %s must be a string or a symbol;
-the argument used by %d, %b, %o, %x or %c must be a number.
-
-This is the custom-print replacement for the standard `format'. It
-calls the emacs `format' after first making strings for list,
-vector, or symbol args. The format specification for such args should
-be `%s' in any case, so a string argument will also work. The string
-is generated with `custom-prin1-to-string', which quotes quotable
-characters."
- (apply 'cust-print-original-format fmt
- (mapcar (function (lambda (arg)
- (if (or (listp arg) (vectorp arg) (symbolp arg))
- (custom-prin1-to-string arg)
- arg)))
- args)))
-
-
-(defun custom-message (fmt &rest args)
- "Print a one-line message at the bottom of the screen.
-The first argument is a control string.
-It may contain %s or %d or %c to print successive following arguments.
-%s means print an argument as a string, %d means print as number in decimal,
-%c means print a number as a single character.
-The argument used by %s must be a string or a symbol;
-the argument used by %d or %c must be a number.
-
-This is the custom-print replacement for the standard `message'.
-See `custom-format' for the details."
- ;; It doesn't work to princ the result of custom-format as in:
- ;; (cust-print-original-princ (apply 'custom-format fmt args))
- ;; because the echo area requires special handling
- ;; to avoid duplicating the output.
- ;; cust-print-original-message does it right.
- (apply 'cust-print-original-message fmt
- (mapcar (function (lambda (arg)
- (if (or (listp arg) (vectorp arg) (symbolp arg))
- (custom-prin1-to-string arg)
- arg)))
- args)))
-
-
-(defun custom-error (fmt &rest args)
- "Signal an error, making error message by passing all args to `format'.
-
-This is the custom-print replacement for the standard `error'.
-See `custom-format' for the details."
- (signal 'error (list (apply 'custom-format fmt args))))
-
-
-
-;; Support for custom prin1 and princ
-;;=========================================
-
-;; Defs to quiet byte-compiler.
-(defvar circle-table)
-(defvar cust-print-current-level)
-
-(defun cust-print-original-printer (object)) ; One of the standard printers.
-(defun cust-print-low-level-prin (object)) ; Used internally.
-(defun cust-print-prin (object)) ; Call this to print recursively.
-
-(defun cust-print-top-level (object stream emacs-printer)
- ;; Set up for printing.
- (let ((standard-output (or stream standard-output))
- ;; circle-table will be non-nil if anything is circular.
- (circle-table (and print-circle
- (cust-print-preprocess-circle-tree object)))
- (cust-print-current-level (or print-level -1)))
-
- (defalias 'cust-print-original-printer emacs-printer)
- (defalias 'cust-print-low-level-prin
- (cond
- ((or custom-printers
- circle-table
- print-level ; comment out for version 19
- ;; Emacs doesn't use print-level or print-length
- ;; for vectors, but custom-print can.
- (if custom-print-vectors
- (or print-level print-length)))
- 'cust-print-print-object)
- (t 'cust-print-original-printer)))
- (defalias 'cust-print-prin
- (if circle-table 'cust-print-print-circular 'cust-print-low-level-prin))
-
- (cust-print-prin object)
- object))
-
-
-(defun cust-print-print-object (object)
- ;; Test object type and print accordingly.
- ;; Could be called as either cust-print-low-level-prin or cust-print-prin.
- (cond
- ((null object) (cust-print-original-printer object))
- ((cust-print-use-custom-printer object) object)
- ((consp object) (cust-print-list object))
- ((vectorp object) (cust-print-vector object))
- ;; All other types, just print.
- (t (cust-print-original-printer object))))
-
-
-(defun cust-print-print-circular (object)
- ;; Printer for `prin1' and `princ' that handles circular structures.
- ;; If OBJECT appears multiply, and has not yet been printed,
- ;; prefix with label; if it has been printed, use `#N#' instead.
- ;; Otherwise, print normally.
- (let ((tag (assq object circle-table)))
- (if tag
- (let ((id (cdr tag)))
- (if (> id 0)
- (progn
- ;; Already printed, so just print id.
- (cust-print-original-princ "#")
- (cust-print-original-princ id)
- (cust-print-original-princ "#"))
- ;; Not printed yet, so label with id and print object.
- (setcdr tag (- id)) ; mark it as printed
- (cust-print-original-princ "#")
- (cust-print-original-princ (- id))
- (cust-print-original-princ "=")
- (cust-print-low-level-prin object)
- ))
- ;; Not repeated in structure.
- (cust-print-low-level-prin object))))
-
-
-;;================================================
-;; List and vector processing for print functions.
-
-(defun cust-print-list (list)
- ;; Print a list using print-length, print-level, and print-circle.
- (if (= cust-print-current-level 0)
- (cust-print-original-princ "#")
- (let ((cust-print-current-level (1- cust-print-current-level)))
- (cust-print-original-princ "(")
- (let ((length (or print-length 0)))
-
- ;; Print the first element always (even if length = 0).
- (cust-print-prin (car list))
- (setq list (cdr list))
- (if list (cust-print-original-princ " "))
- (setq length (1- length))
-
- ;; Print the rest of the elements.
- (while (and list (/= 0 length))
- (if (and (listp list)
- (not (assq list circle-table)))
- (progn
- (cust-print-prin (car list))
- (setq list (cdr list)))
-
- ;; cdr is not a list, or it is in circle-table.
- (cust-print-original-princ ". ")
- (cust-print-prin list)
- (setq list nil))
-
- (setq length (1- length))
- (if list (cust-print-original-princ " ")))
-
- (if (and list (= length 0)) (cust-print-original-princ "..."))
- (cust-print-original-princ ")"))))
- list)
-
-
-(defun cust-print-vector (vector)
- ;; Print a vector according to print-length, print-level, and print-circle.
- (if (= cust-print-current-level 0)
- (cust-print-original-princ "#")
- (let ((cust-print-current-level (1- cust-print-current-level))
- (i 0)
- (len (length vector)))
- (cust-print-original-princ "[")
-
- (if print-length
- (setq len (min print-length len)))
- ;; Print the elements
- (while (< i len)
- (cust-print-prin (aref vector i))
- (setq i (1+ i))
- (if (< i (length vector)) (cust-print-original-princ " ")))
-
- (if (< i (length vector)) (cust-print-original-princ "..."))
- (cust-print-original-princ "]")
- ))
- vector)
-
-
-
-;; Circular structure preprocessing
-;;==================================
-
-(defun cust-print-preprocess-circle-tree (object)
- ;; Fill up the table.
- (let (;; Table of tags for each object in an object to be printed.
- ;; A tag is of the form:
- ;; ( <object> <nil-t-or-id-number> )
- ;; The id-number is generated after the entire table has been computed.
- ;; During walk through, the real circle-table lives in the cdr so we
- ;; can use setcdr to add new elements instead of having to setq the
- ;; variable sometimes (poor man's locf).
- (circle-table (list nil)))
- (cust-print-walk-circle-tree object)
-
- ;; Reverse table so it is in the order that the objects will be printed.
- ;; This pass could be avoided if we always added to the end of the
- ;; table with setcdr in walk-circle-tree.
- (setcdr circle-table (nreverse (cdr circle-table)))
-
- ;; Walk through the table, assigning id-numbers to those
- ;; objects which will be printed using #N= syntax. Delete those
- ;; objects which will be printed only once (to speed up assq later).
- (let ((rest circle-table)
- (id -1))
- (while (cdr rest)
- (let ((tag (car (cdr rest))))
- (cond ((cdr tag)
- (setcdr tag id)
- (setq id (1- id))
- (setq rest (cdr rest)))
- ;; Else delete this object.
- (t (setcdr rest (cdr (cdr rest))))))
- ))
- ;; Drop the car.
- (cdr circle-table)
- ))
-
-
-
-(defun cust-print-walk-circle-tree (object)
- (let (read-equivalent-p tag)
- (while object
- (setq read-equivalent-p
- (or (numberp object)
- (and (symbolp object)
- ;; Check if it is uninterned.
- (eq object (intern-soft (symbol-name object)))))
- tag (and (not read-equivalent-p)
- (assq object (cdr circle-table))))
- (cond (tag
- ;; Seen this object already, so note that.
- (setcdr tag t))
-
- ((not read-equivalent-p)
- ;; Add a tag for this object.
- (setcdr circle-table
- (cons (list object)
- (cdr circle-table)))))
- (setq object
- (cond
- (tag ;; No need to descend since we have already.
- nil)
-
- ((consp object)
- ;; Walk the car of the list recursively.
- (cust-print-walk-circle-tree (car object))
- ;; But walk the cdr with the above while loop
- ;; to avoid problems with max-lisp-eval-depth.
- ;; And it should be faster than recursion.
- (cdr object))
-
- ((vectorp object)
- ;; Walk the vector.
- (let ((i (length object))
- (j 0))
- (while (< j i)
- (cust-print-walk-circle-tree (aref object j))
- (setq j (1+ j))))))))))
-
-
-;; Example.
-;;=======================================
-
-'(progn
- (progn
- ;; Create some circular structures.
- (setq circ-sym (let ((x (make-symbol "FOO"))) (list x x)))
- (setq circ-list (list 'a 'b (vector 1 2 3 4) 'd 'e 'f))
- (setcar (nthcdr 3 circ-list) circ-list)
- (aset (nth 2 circ-list) 2 circ-list)
- (setq dotted-circ-list (list 'a 'b 'c))
- (setcdr (cdr (cdr dotted-circ-list)) dotted-circ-list)
- (setq circ-vector (vector 1 2 3 4 (list 'a 'b 'c 'd) 6 7))
- (aset circ-vector 5 (make-symbol "-gensym-"))
- (setcar (cdr (aref circ-vector 4)) (aref circ-vector 5))
- nil)
-
- (install-custom-print)
- ;; (setq print-circle t)
-
- (let ((print-circle t))
- (or (equal (prin1-to-string circ-list) "#1=(a b [1 2 #1# 4] #1# e f)")
- (error "circular object with array printing")))
-
- (let ((print-circle t))
- (or (equal (prin1-to-string dotted-circ-list) "#1=(a b c . #1#)")
- (error "circular object with array printing")))
-
- (let* ((print-circle t)
- (x (list 'p 'q))
- (y (list (list 'a 'b) x 'foo x)))
- (setcdr (cdr (cdr (cdr y))) (cdr y))
- (or (equal (prin1-to-string y) "((a b) . #1=(#2=(p q) foo #2# . #1#))"
- )
- (error "circular list example from CL manual")))
-
- (let ((print-circle nil))
- ;; cl-packages.el is required to print uninterned symbols like #:FOO.
- ;; (require 'cl-packages)
- (or (equal (prin1-to-string circ-sym) "(#:FOO #:FOO)")
- (error "uninterned symbols in list")))
- (let ((print-circle t))
- (or (equal (prin1-to-string circ-sym) "(#1=FOO #1#)")
- (error "circular uninterned symbols in list")))
-
- (uninstall-custom-print)
- )
-
-(provide 'cust-print)
-
-;;; cust-print.el ends here
-
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el
deleted file mode 100644
index fb2a1324331..00000000000
--- a/lisp/emacs-lisp/debug.el
+++ /dev/null
@@ -1,491 +0,0 @@
-;;; debug.el --- debuggers and related commands for Emacs
-
-;; Copyright (C) 1985, 1986, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: lisp, tools, maint
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This is a major mode documented in the Emacs manual.
-
-;;; Code:
-
-(defvar debug-function-list nil
- "List of functions currently set for debug on entry.")
-
-(defvar debugger-step-after-exit nil
- "Non-nil means \"single-step\" after the debugger exits.")
-
-(defvar debugger-value nil
- "This is the value for the debugger to return, when it returns.")
-
-(defvar debugger-old-buffer nil
- "This is the buffer that was current when the debugger was entered.")
-
-(defvar debugger-outer-match-data)
-(defvar debugger-outer-load-read-function)
-(defvar debugger-outer-overriding-local-map)
-(defvar debugger-outer-track-mouse)
-(defvar debugger-outer-last-command)
-(defvar debugger-outer-this-command)
-(defvar debugger-outer-unread-command-char)
-(defvar debugger-outer-unread-command-events)
-(defvar debugger-outer-last-input-event)
-(defvar debugger-outer-last-command-event)
-(defvar debugger-outer-last-nonmenu-event)
-(defvar debugger-outer-last-event-frame)
-(defvar debugger-outer-standard-input)
-(defvar debugger-outer-standard-output)
-(defvar debugger-outer-cursor-in-echo-area)
-
-;;;###autoload
-(setq debugger 'debug)
-;;;###autoload
-(defun debug (&rest debugger-args)
- "Enter debugger. To return, type \\<debugger-mode-map>`\\[debugger-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."
- (interactive)
- (message "Entering debugger...")
- (let (debugger-value
- (debug-on-error nil)
- (debug-on-quit nil)
- (debugger-buffer (let ((default-major-mode 'fundamental-mode))
- (get-buffer-create "*Backtrace*")))
- (debugger-old-buffer (current-buffer))
- (debugger-step-after-exit nil)
- ;; Don't keep reading from an executing kbd macro!
- (executing-kbd-macro nil)
- ;; Save the outer values of these vars for the `e' command
- ;; before we replace the values.
- (debugger-outer-match-data (match-data))
- (debugger-outer-load-read-function load-read-function)
- (debugger-outer-overriding-local-map overriding-local-map)
- (debugger-outer-track-mouse track-mouse)
- (debugger-outer-last-command last-command)
- (debugger-outer-this-command this-command)
- (debugger-outer-unread-command-char unread-command-char)
- (debugger-outer-unread-command-events unread-command-events)
- (debugger-outer-last-input-event last-input-event)
- (debugger-outer-last-command-event last-command-event)
- (debugger-outer-last-nonmenu-event last-nonmenu-event)
- (debugger-outer-last-event-frame last-event-frame)
- (debugger-outer-standard-input standard-input)
- (debugger-outer-standard-output standard-output)
- (debugger-outer-cursor-in-echo-area cursor-in-echo-area))
- ;; Don't let these magic variables affect the debugger itself.
- (let ((last-command nil) this-command track-mouse
- (unread-command-char -1) unread-command-events
- last-input-event last-command-event last-nonmenu-event
- last-event-frame
- overriding-local-map
- load-read-function
- (standard-input t) (standard-output t)
- (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
- (search-forward "\n debug(")
- (forward-line 1)
- (point)))
- (debugger-reenable)
- ;; lambda is for debug-on-call when a function call is next.
- ;; debug is for debug-on-entry function called.
- (cond ((memq (car debugger-args) '(lambda debug))
- (insert "Entering:\n")
- (if (eq (car debugger-args) 'debug)
- (progn
- ;; Skip the frames for backtrace-debug, byte-code,
- ;; and debug.
- (backtrace-debug 3 t)
- (delete-char 1)
- (insert ?*)
- (beginning-of-line))))
- ;; Exiting a function.
- ((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))
- ;; Debugger entered for an error.
- ((eq (car debugger-args) 'error)
- (insert "Signaling: ")
- (prin1 (nth 1 debugger-args) (current-buffer))
- (insert ?\n))
- ;; debug-on-call, when the next thing is an eval.
- ((eq (car debugger-args) t)
- (insert "Beginning evaluation of function call form:\n"))
- ;; User calls debug directly.
- (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))))
- ;; Kill or at least neuter the backtrace buffer, so that users
- ;; don't try to execute debugger commands in an invalid context.
- (if (get-buffer-window debugger-buffer 'visible)
- ;; Still visible despite the save-window-excursion? Maybe it
- ;; it's in a pop-up frame. It would be annoying to delete and
- ;; recreate it every time the debugger stops, so instead we'll
- ;; erase it but leave it visible.
- (save-excursion
- (set-buffer debugger-buffer)
- (erase-buffer)
- (fundamental-mode))
- (kill-buffer debugger-buffer))
- (store-match-data debugger-outer-match-data)))
- ;; Put into effect the modified values of these variables
- ;; in case the user set them with the `e' command.
- (setq load-read-function debugger-outer-load-read-function)
- (setq overriding-local-map debugger-outer-overriding-local-map)
- (setq track-mouse debugger-outer-track-mouse)
- (setq last-command debugger-outer-last-command)
- (setq this-command debugger-outer-this-command)
- (setq unread-command-char debugger-outer-unread-command-char)
- (setq unread-command-events debugger-outer-unread-command-events)
- (setq last-input-event debugger-outer-last-input-event)
- (setq last-command-event debugger-outer-last-command-event)
- (setq last-nonmenu-event debugger-outer-last-nonmenu-event)
- (setq last-event-frame debugger-outer-last-event-frame)
- (setq standard-input debugger-outer-standard-input)
- (setq standard-output debugger-outer-standard-output)
- (setq cursor-in-echo-area debugger-outer-cursor-in-echo-area)
- (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 "Proceeding, 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-jump ()
- "Continue to exit from this frame, with all debug-on-entry suspended."
- (interactive)
- ;; Compensate for the two extra stack frames for debugger-jump.
- (let ((debugger-frame-offset (+ debugger-frame-offset 2)))
- (debugger-frame))
- ;; Turn off all debug-on-entry functions
- ;; but leave them in the list.
- (let ((list debug-function-list))
- (while list
- (fset (car list)
- (debug-on-entry-1 (car list) (symbol-function (car list)) nil))
- (setq list (cdr list))))
- (message "Continuing through this frame")
- (exit-recursive-edit))
-
-(defun debugger-reenable ()
- "Turn all debug-on-entry functions back on."
- (let ((list debug-function-list))
- (while list
- (or (consp (symbol-function (car list)))
- (debug-convert-byte-code (car list)))
- (fset (car list)
- (debug-on-entry-1 (car list) (symbol-function (car list)) t))
- (setq list (cdr list)))))
-
-(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)
- "Eval an expression, in an environment like that outside the debugger."
- (interactive
- (list (read-from-minibuffer "Eval: "
- nil read-expression-map t
- 'read-expression-history)))
- (save-excursion
- (if (null (buffer-name debugger-old-buffer))
- ;; old buffer deleted
- (setq debugger-old-buffer (current-buffer)))
- (set-buffer debugger-old-buffer)
- (let ((track-mouse debugger-outer-track-mouse)
- (last-command debugger-outer-last-command)
- (this-command debugger-outer-this-command)
- (unread-command-char debugger-outer-unread-command-char)
- (unread-command-events debugger-outer-unread-command-events)
- (last-input-event debugger-outer-last-input-event)
- (last-command-event debugger-outer-last-command-event)
- (last-nonmenu-event debugger-outer-last-nonmenu-event)
- (last-event-frame debugger-outer-last-event-frame)
- (standard-input debugger-outer-standard-input)
- (standard-output debugger-outer-standard-output)
- (cursor-in-echo-area debugger-outer-cursor-in-echo-area)
- (overriding-local-map debugger-outer-overriding-local-map)
- (load-read-function debugger-outer-load-read-function))
- (store-match-data debugger-outer-match-data)
- (prog1 (eval-expression exp)
- (setq debugger-outer-match-data (match-data))
- (setq debugger-outer-load-read-function load-read-function)
- (setq debugger-outer-overriding-local-map overriding-local-map)
- (setq debugger-outer-track-mouse track-mouse)
- (setq debugger-outer-last-command last-command)
- (setq debugger-outer-this-command this-command)
- (setq debugger-outer-unread-command-char unread-command-char)
- (setq debugger-outer-unread-command-events unread-command-events)
- (setq debugger-outer-last-input-event last-input-event)
- (setq debugger-outer-last-command-event last-command-event)
- (setq debugger-outer-last-nonmenu-event last-nonmenu-event)
- (setq debugger-outer-last-event-frame last-event-frame)
- (setq debugger-outer-standard-input standard-input)
- (setq debugger-outer-standard-output standard-output)
- (setq debugger-outer-cursor-in-echo-area cursor-in-echo-area)))))
-
-(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 "j" 'debugger-jump)
- (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 "l" 'debugger-list-functions)
- (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>
-A line starts with `*' if exiting that frame will call the debugger.
-Type \\[debugger-frame] or \\[debugger-frame-clear] to set or remove the `*'.
-
-When in debugger due to frame being exited,
-use the \\[debugger-return-value] command to override the value
-being returned from that frame.
-
-Use \\[debug-on-entry] and \\[cancel-debug-on-entry] to control
-which functions will enter the debugger when called.
-
-Complete list of commands:
-\\{debugger-mode-map}"
- (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))
-
-;;;###autoload
-(defun debug-on-entry (function)
- "Request FUNCTION to invoke debugger each time it is called.
-If you tell the debugger to continue, FUNCTION's execution proceeds.
-This 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 cancels it."
- (interactive "aDebug on entry (to function): ")
- (debugger-reenable)
- (if (subrp (symbol-function function))
- (error "Function %s is a primitive" function))
- (or (consp (symbol-function function))
- (debug-convert-byte-code function))
- (or (consp (symbol-function function))
- (error "Definition of %s is not a list" function))
- (fset function (debug-on-entry-1 function (symbol-function function) t))
- (or (memq function debug-function-list)
- (setq debug-function-list (cons function debug-function-list)))
- function)
-
-;;;###autoload
-(defun cancel-debug-on-entry (&optional function)
- "Undo effect of \\[debug-on-entry] on FUNCTION.
-If argument is nil or an empty string, cancel for all functions."
- (interactive
- (list (let ((name
- (completing-read "Cancel debug on entry (to function): "
- ;; Make an "alist" of the functions
- ;; that now have debug on entry.
- (mapcar 'list
- (mapcar 'symbol-name
- debug-function-list))
- nil t nil)))
- (if name (intern name)))))
- (debugger-reenable)
- (if (and function (not (string= function "")))
- (progn
- (fset function
- (debug-on-entry-1 function (symbol-function function) nil))
- (setq debug-function-list (delq function debug-function-list))
- function)
- (message "Cancelling debug-on-entry for all functions")
- (mapcar 'cancel-debug-on-entry debug-function-list)))
-
-(defun debug-convert-byte-code (function)
- (let ((defn (symbol-function function)))
- (if (not (consp defn))
- ;; Assume a compiled code object.
- (let* ((contents (append defn nil))
- (body
- (list (list 'byte-code (nth 1 contents)
- (nth 2 contents) (nth 3 contents)))))
- (if (nthcdr 5 contents)
- (setq body (cons (list 'interactive (nth 5 contents)) body)))
- (if (nth 4 contents)
- ;; Use `documentation' here, to get the actual string,
- ;; in case the compiled function has a reference
- ;; to the .elc file.
- (setq body (cons (documentation function) body)))
- (fset function (cons 'lambda (cons (car contents) body)))))))
-
-(defun debug-on-entry-1 (function defn flag)
- (if (subrp defn)
- (error "%s is a built-in function" function)
- (if (eq (car defn) 'macro)
- (debug-on-entry-1 function (cdr 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)))
- defn
- (if flag
- (nconc prec (cons '(debug 'debug) tail))
- (nconc prec (cdr tail))))))))
-
-(defun debugger-list-functions ()
- "Display a list of all the functions now set to debug on entry."
- (interactive)
- (with-output-to-temp-buffer "*Help*"
- (if (null debug-function-list)
- (princ "No debug-on-entry functions now\n")
- (princ "Functions set to debug on entry:\n\n")
- (let ((list debug-function-list))
- (while list
- (prin1 (car list))
- (terpri)
- (setq list (cdr list))))
- (princ "Note: if you have redefined a function, then it may no longer\n")
- (princ "be set to debug on entry, even if it is in the list."))
- (save-excursion
- (set-buffer standard-output)
- (help-mode))))
-
-;;; debug.el ends here
diff --git a/lisp/emacs-lisp/disass.el b/lisp/emacs-lisp/disass.el
deleted file mode 100644
index 4199728888e..00000000000
--- a/lisp/emacs-lisp/disass.el
+++ /dev/null
@@ -1,266 +0,0 @@
-;;; disass.el --- disassembler for compiled Emacs Lisp code
-
-;; Copyright (C) 1986, 1991 Free Software Foundation, Inc.
-
-;; Author: Doug Cutting <doug@csli.stanford.edu>
-;; Jamie Zawinski <jwz@lucid.com>
-;; Maintainer: Jamie Zawinski <jwz@lucid.com>
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The single entry point, `disassemble', disassembles a code object generated
-;; by the Emacs Lisp byte-compiler. This doesn't invert the compilation
-;; operation, not by a long shot, but it's useful for debugging.
-
-;;
-;; Original version by Doug Cutting (doug@csli.stanford.edu)
-;; Substantially modified by Jamie Zawinski <jwz@lucid.com> for
-;; the new lapcode-based byte compiler.
-
-;;; Code:
-
-;;; The variable byte-code-vector is defined by the new bytecomp.el.
-;;; The function byte-decompile-lapcode is defined in byte-opt.el.
-;;; Since we don't use byte-decompile-lapcode, let's try not loading byte-opt.
-(require 'byte-compile "bytecomp")
-
-(defvar disassemble-column-1-indent 8 "*")
-(defvar disassemble-column-2-indent 10 "*")
-
-(defvar disassemble-recursive-indent 3 "*")
-
-;;;###autoload
-(defun disassemble (object &optional buffer indent interactive-p)
- "Print disassembled code for OBJECT in (optional) BUFFER.
-OBJECT can be a symbol defined as a function, or a function itself
-\(a lambda expression or a compiled-function object).
-If OBJECT is not already compiled, we compile it, but do not
-redefine OBJECT if it is a symbol."
- (interactive (list (intern (completing-read "Disassemble function: "
- obarray 'fboundp t))
- nil 0 t))
- (if (eq (car-safe object) 'byte-code)
- (setq object (list 'lambda () object)))
- (or indent (setq indent 0)) ;Default indent to zero
- (save-excursion
- (if (or interactive-p (null buffer))
- (with-output-to-temp-buffer "*Disassemble*"
- (set-buffer "*Disassemble*")
- (disassemble-internal object indent (not interactive-p)))
- (set-buffer buffer)
- (disassemble-internal object indent nil)))
- nil)
-
-
-(defun disassemble-internal (obj 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 (and (listp obj) (eq (car obj) 'autoload))
- (progn
- (load (nth 1 obj))
- (setq obj (symbol-function name))))
- (if (eq (car-safe obj) 'macro) ;handle macros
- (setq macro t
- obj (cdr obj)))
- (if (and (listp obj) (eq (car obj) 'byte-code))
- (setq obj (list 'lambda nil obj)))
- (if (and (listp obj) (not (eq (car obj) 'lambda)))
- (error "not a function"))
- (if (consp obj)
- (if (assq 'byte-code obj)
- nil
- (if interactive-p (message (if name
- "Compiling %s's definition..."
- "Compiling definition...")
- name))
- (setq obj (byte-compile obj))
- (if interactive-p (message "Done compiling. Disassembling..."))))
- (cond ((consp obj)
- (setq obj (cdr obj)) ;throw lambda away
- (setq args (car obj)) ;save arg list
- (setq obj (cdr obj)))
- ((byte-code-function-p obj)
- (setq args (aref obj 0)))
- (t (error "Compilation failed")))
- (if (zerop indent) ; not a nested function
- (progn
- (indent-to indent)
- (insert (format "byte code%s%s%s:\n"
- (if (or macro name) " for" "")
- (if macro " macro" "")
- (if name (format " %s" name) "")))))
- (let ((doc (if (consp obj)
- (and (stringp (car obj)) (car obj))
- ;; Use documentation to get lazy-loaded doc string
- (documentation obj t))))
- (if (and doc (stringp doc))
- (progn (and (consp obj) (setq obj (cdr obj)))
- (indent-to indent)
- (princ " doc: " (current-buffer))
- (if (string-match "\n" doc)
- (setq doc (concat (substring doc 0 (match-beginning 0))
- " ...")))
- (insert doc "\n"))))
- (indent-to indent)
- (insert " args: ")
- (prin1 args (current-buffer))
- (insert "\n")
- (let ((interactive (cond ((consp obj)
- (assq 'interactive obj))
- ((> (length obj) 5)
- (list 'interactive (aref obj 5))))))
- (if interactive
- (progn
- (setq interactive (nth 1 interactive))
- (if (eq (car-safe (car-safe obj)) 'interactive)
- (setq obj (cdr obj)))
- (indent-to indent)
- (insert " interactive: ")
- (if (eq (car-safe interactive) 'byte-code)
- (progn
- (insert "\n")
- (disassemble-1 interactive
- (+ indent disassemble-recursive-indent)))
- (let ((print-escape-newlines t))
- (prin1 interactive (current-buffer))))
- (insert "\n"))))
- (cond ((and (consp obj) (assq 'byte-code obj))
- (disassemble-1 (assq 'byte-code obj) indent))
- ((byte-code-function-p obj)
- (disassemble-1 obj indent))
- (t
- (insert "Uncompiled body: ")
- (let ((print-escape-newlines t))
- (prin1 (if (cdr obj) (cons 'progn obj) (car obj))
- (current-buffer))))))
- (if interactive-p
- (message "")))
-
-
-(defun disassemble-1 (obj indent)
- "Prints the byte-code call OBJ in the current buffer.
-OBJ should be a call to BYTE-CODE generated by the byte compiler."
- (let (bytes constvec)
- (if (consp obj)
- (setq bytes (car (cdr obj)) ;the byte code
- constvec (car (cdr (cdr obj)))) ;constant vector
- ;; If it is lazy-loaded, load it now
- (fetch-bytecode obj)
- (setq bytes (aref obj 1)
- constvec (aref obj 2)))
- (let ((lap (byte-decompile-bytecode bytes constvec))
- op arg opname pc-value)
- (let ((tagno 0)
- tmp
- (lap lap))
- (while (setq tmp (assq 'TAG lap))
- (setcar (cdr tmp) (setq tagno (1+ tagno)))
- (setq lap (cdr (memq tmp lap)))))
- (while lap
- ;; Take off the pc value of the next thing
- ;; and put it in pc-value.
- (setq pc-value nil)
- (if (numberp (car lap))
- (setq pc-value (car lap)
- lap (cdr lap)))
- ;; Fetch the next op and its arg.
- (setq op (car (car lap))
- arg (cdr (car lap)))
- (setq lap (cdr lap))
- (indent-to indent)
- (if (eq 'TAG op)
- (progn
- ;; We have a label. Display it, but first its pc value.
- (if pc-value
- (insert (format "%d:" pc-value)))
- (insert (int-to-string (car arg))))
- ;; We have an instruction. Display its pc value first.
- (if pc-value
- (insert (format "%d" pc-value)))
- (indent-to (+ indent disassemble-column-1-indent))
- (if (and op
- (string-match "^byte-" (setq opname (symbol-name op))))
- (setq opname (substring opname 5))
- (setq opname "<not-an-opcode>"))
- (if (eq op 'byte-constant2)
- (insert " #### shouldn't have seen constant2 here!\n "))
- (insert opname)
- (indent-to (+ indent disassemble-column-1-indent
- disassemble-column-2-indent
- -1))
- (insert " ")
- (cond ((memq op byte-goto-ops)
- (insert (int-to-string (nth 1 arg))))
- ((memq op '(byte-call byte-unbind
- byte-listN byte-concatN byte-insertN))
- (insert (int-to-string arg)))
- ((memq op '(byte-varref byte-varset byte-varbind))
- (prin1 (car arg) (current-buffer)))
- ((memq op '(byte-constant byte-constant2))
- ;; it's a constant
- (setq arg (car arg))
- ;; but if the value of the constant is compiled code, then
- ;; recursively disassemble it.
- (cond ((or (byte-code-function-p arg)
- (and (eq (car-safe arg) 'lambda)
- (assq 'byte-code arg))
- (and (eq (car-safe arg) 'macro)
- (or (byte-code-function-p (cdr arg))
- (and (eq (car-safe (cdr arg)) 'lambda)
- (assq 'byte-code (cdr arg))))))
- (cond ((byte-code-function-p arg)
- (insert "<compiled-function>\n"))
- ((eq (car-safe arg) 'lambda)
- (insert "<compiled lambda>"))
- (t (insert "<compiled macro>\n")))
- (disassemble-internal
- arg
- (+ indent disassemble-recursive-indent 1)
- nil))
- ((eq (car-safe arg) 'byte-code)
- (insert "<byte code>\n")
- (disassemble-1 ;recurse on byte-code object
- arg
- (+ indent disassemble-recursive-indent)))
- ((eq (car-safe (car-safe arg)) 'byte-code)
- (insert "(<byte code>...)\n")
- (mapcar ;recurse on list of byte-code objects
- '(lambda (obj)
- (disassemble-1
- obj
- (+ indent disassemble-recursive-indent)))
- arg))
- (t
- ;; really just a constant
- (let ((print-escape-newlines t))
- (prin1 arg (current-buffer))))))
- )
- (insert "\n")))))
- nil)
-
-;;; disass.el ends here
diff --git a/lisp/emacs-lisp/easymenu.el b/lisp/emacs-lisp/easymenu.el
deleted file mode 100644
index b172e131763..00000000000
--- a/lisp/emacs-lisp/easymenu.el
+++ /dev/null
@@ -1,244 +0,0 @@
-;;; easymenu.el --- support the easymenu interface for defining a menu.
-
-;; Copyright (C) 1994, 1996 Free Software Foundation, Inc.
-
-;; Keywords: emulations
-;; Author: rms
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This is compatible with easymenu.el by Per Abrahamsen
-;; but it is much simpler as it doesn't try to support other Emacs versions.
-;; The code was mostly derived from lmenu.el.
-
-;;; Code:
-
-;;;###autoload
-(defmacro easy-menu-define (symbol maps doc menu)
- "Define a menu bar submenu in maps MAPS, according to MENU.
-The menu keymap is stored in symbol SYMBOL, both as its value
-and as its function definition. DOC is used as the doc string for SYMBOL.
-
-The first element of MENU must be a string. It is the menu bar item name.
-The rest of the elements are menu items.
-
-A menu item is usually a vector of three elements: [NAME CALLBACK ENABLE]
-
-NAME is a string--the menu item name.
-
-CALLBACK is a command to run when the item is chosen,
-or a list to evaluate when the item is chosen.
-
-ENABLE is an expression; the item is enabled for selection
-whenever this expression's value is non-nil.
-
-Alternatively, a menu item may have the form:
-
- [ NAME CALLBACK [ KEYWORD ARG ] ... ]
-
-Where KEYWORD is one of the symbol defined below.
-
- :keys KEYS
-
-KEYS is a string; a complex keyboard equivalent to this menu item.
-This is normally not needed because keyboard equivalents are usually
-computed automatically.
-
- :active ENABLE
-
-ENABLE is an expression; the item is enabled for selection
-whenever this expression's value is non-nil.
-
- :suffix NAME
-
-NAME is a string; the name of an argument to CALLBACK.
-
- :style STYLE
-
-STYLE is a symbol describing the type of menu item. The following are
-defined:
-
-toggle: A checkbox.
- Prepend the name with '(*) ' or '( ) ' depending on if selected or not.
-radio: A radio button.
- Prepend the name with '[X] ' or '[ ] ' depending on if selected or not.
-nil: An ordinary menu item.
-
- :selected SELECTED
-
-SELECTED is an expression; the checkbox or radio button is selected
-whenever this expression's value is non-nil.
-
-A menu item can be a string. Then that string appears in the menu as
-unselectable text. A string consisting solely of hyphens is displayed
-as a solid horizontal line.
-
-A menu item can be a list. It is treated as a submenu.
-The first element should be the submenu name. That's used as the
-menu item in the top-level menu. The cdr of the submenu list
-is a list of menu items, as above."
- (` (progn
- (defvar (, symbol) nil (, doc))
- (easy-menu-do-define (quote (, symbol)) (, maps) (, doc) (, menu)))))
-
-;;;###autoload
-(defun easy-menu-do-define (symbol maps doc menu)
- ;; We can't do anything that might differ between Emacs dialects in
- ;; `easy-menu-define' in order to make byte compiled files
- ;; compatible. Therefore everything interesting is done in this
- ;; function.
- (set symbol (easy-menu-create-keymaps (car menu) (cdr menu)))
- (fset symbol (` (lambda (event) (, doc) (interactive "@e")
- (x-popup-menu event (, symbol)))))
- (mapcar (function (lambda (map)
- (define-key map (vector 'menu-bar (intern (car menu)))
- (cons (car menu) (symbol-value symbol)))))
- (if (keymapp maps) (list maps) maps)))
-
-(defvar easy-menu-item-count 0)
-
-;; Return a menu keymap corresponding to a Lucid-style menu list
-;; MENU-ITEMS, and with name MENU-NAME.
-;;;###autoload
-(defun easy-menu-create-keymaps (menu-name menu-items)
- (let ((menu (make-sparse-keymap menu-name)) old-items have-buttons)
- ;; Process items in reverse order,
- ;; since the define-key loop reverses them again.
- (setq menu-items (reverse menu-items))
- (while menu-items
- (let* ((item (car menu-items))
- (callback (if (vectorp item) (aref item 1)))
- (not-button t)
- command enabler item-string name)
- (cond ((stringp item)
- (setq command nil)
- (setq item-string (if (string-match "^-+$" item) "" item)))
- ((consp item)
- (setq command (easy-menu-create-keymaps (car item) (cdr item)))
- (setq name (setq item-string (car item))))
- ((vectorp item)
- (setq command (make-symbol (format "menu-function-%d"
- easy-menu-item-count)))
- (setq easy-menu-item-count (1+ easy-menu-item-count))
- (setq name (setq item-string (aref item 0)))
- (let ((keyword (aref item 2)))
- (if (and (symbolp keyword)
- (= ?: (aref (symbol-name keyword) 0)))
- (let ((count 2)
- style selected active keys
- arg)
- (while (> (length item) count)
- (setq keyword (aref item count))
- (setq arg (aref item (1+ count)))
- (setq count (+ 2 count))
- (cond ((eq keyword ':keys)
- (setq keys arg))
- ((eq keyword ':active)
- (setq active arg))
- ((eq keyword ':suffix)
- (setq item-string
- (concat item-string " " arg)))
- ((eq keyword ':style)
- (setq style arg))
- ((eq keyword ':selected)
- (setq selected arg))))
- (if keys
- (setq item-string
- (concat item-string " (" keys ")")))
- (if (and selected
- (or (eq style 'radio) (eq style 'toggle)))
- ;; Simulate checkboxes and radio buttons.
- (progn
- (setq item-string
- (concat
- (if (eval selected)
- (if (eq style 'radio) "(*) " "[X] ")
- (if (eq style 'radio) "( ) " "[ ] "))
- item-string))
- (put command 'menu-enable
- (list 'easy-menu-update-button
- item-string
- (if (eq style 'radio) ?* ?X)
- selected
- (or active t)))
- (setq not-button nil
- active nil
- have-buttons t)
- (while old-items ; Fix items aleady defined.
- (setcar (car old-items)
- (concat " " (car (car old-items))))
- (setq old-items (cdr old-items)))))
- (if active (put command 'menu-enable active)))
- (put command 'menu-enable keyword)))
- (if (symbolp callback)
- (fset command callback)
- (fset command (list 'lambda () '(interactive) callback)))
- (put command 'menu-alias t)))
- (if (null command)
- ;; Handle inactive strings specially--allow any number
- ;; of identical ones.
- (setcdr menu (cons (list nil item-string) (cdr menu)))
- (if (and not-button have-buttons)
- (setq item-string (concat " " item-string)))
- (setq command (cons item-string command))
- (if (not have-buttons) ; Save all items so that we can fix
- (setq old-items (cons command old-items))) ; if we have buttons.
- (if name (define-key menu (vector (intern name)) command))))
- (setq menu-items (cdr menu-items)))
- menu))
-
-(defun easy-menu-update-button (item ch selected active)
- "Used as menu-enable property to update buttons.
-A call to this function is used as the menu-enable property for buttons.
-ITEM is the item-string into wich CH or ` ' is inserted depending on if
-SELECTED is true or not. The menu entry in enabled iff ACTIVE is true."
- (let ((new (if selected ch ? ))
- (old (aref item 1)))
- (if (eq new old)
- ;; No change, just use the active value.
- active
- ;; It has changed. Update the entry.
- (aset item 1 new)
- ;; If the entry is active, make sure the menu gets updated by
- ;; returning a different value than last time to cheat the cache.
- (and active
- (random)))))
-
-(defun easy-menu-change (path name items)
- "Change menu found at PATH as item NAME to contain ITEMS.
-PATH is a list of strings for locating the menu containing NAME in the
-menu bar. ITEMS is a list of menu items, as in `easy-menu-define'.
-These items entirely replace the previous items in that map.
-
-Call this from `menu-bar-update-hook' to implement dynamic menus."
- (let ((map (key-binding (apply 'vector
- 'menu-bar
- (mapcar 'intern (append path (list name)))))))
- (if (keymapp map)
- (setcdr map (cdr (easy-menu-create-keymaps name items)))
- (error "Malformed menu in `easy-menu-change'"))))
-
-(defun easy-menu-remove (menu))
-
-(defun easy-menu-add (menu &optional map))
-
-(provide 'easymenu)
-
-;;; easymenu.el ends here
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
deleted file mode 100644
index f6831f6f29d..00000000000
--- a/lisp/emacs-lisp/edebug.el
+++ /dev/null
@@ -1,4515 +0,0 @@
-;;; edebug.el --- a source-level debugger for Emacs Lisp
-
-;; Copyright (C) 1988,'89,'90,'91,'92,'93,'94,'95 Free Software Foundation, Inc
-
-;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
-;; Keywords: lisp, tools, maint
-
-;; LCD Archive Entry:
-;; edebug|Daniel LaLiberte|liberte@cs.uiuc.edu
-;; |A source level debugger for Emacs Lisp.
-;; |$Date: 1996/11/09 21:48:07 $|$Revision: 3.12 $|~/modes/edebug.el|
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This minor mode allows programmers to step through Emacs Lisp
-;; source code while executing functions. You can also set
-;; breakpoints, trace (stopping at each expression), evaluate
-;; expressions as if outside Edebug, reevaluate and display a list of
-;; expressions, trap errors normally caught by debug, and display a
-;; debug style backtrace.
-
-;;; Installation
-;; =============
-
-;; Put edebug.el in some directory in your load-path and
-;; byte-compile it. Also read the beginning of edebug-epoch.el,
-;; cl-specs.el, and edebug-cl-read.el if they apply to you.
-
-;; Unless you are using Emacs 19 which is already set up to use Edebug,
-;; put the following forms in your .emacs file.
-;; (define-key emacs-lisp-mode-map "\C-xx" 'edebug-eval-top-level-form)
-;; (autoload 'edebug-eval-top-level-form "edebug")
-
-;; If you wish to change the default edebug global command prefix, change:
-;; (setq edebug-global-prefix "\C-xX")
-
-;; Other options, are described in the manual.
-
-;; In previous versions of Edebug, users were directed to set
-;; `debugger' to `edebug-debug'. This is no longer necessary
-;; since Edebug automatically sets it whenever Edebug is active.
-
-;;; Minimal Instructions
-;; =====================
-
-;; First evaluate a defun with C-xx, then run the function. Step
-;; through the code with SPC, mark breakpoints with b, go until a
-;; breakpoint is reached with g, and quit execution with q. Use the
-;; "?" command in edebug to describe other commands. See edebug.tex
-;; or the Emacs 19 Lisp Reference Manual for more instructions.
-
-;; Send me your enhancements, ideas, bugs, or fixes.
-;; For bugs, you can call edebug-submit-bug-report if you have reporter.el.
-;; There is an edebug mailing list if you want to keep up
-;; with the latest developments. Requests to: edebug-request@cs.uiuc.edu
-
-;; Daniel LaLiberte 217-398-4114
-;; University of Illinois, Urbana-Champaign
-;; Department of Computer Science
-;; 1304 W Springfield
-;; Urbana, IL 61801
-
-;; uiucdcs!liberte
-;; liberte@cs.uiuc.edu
-
-;; For the early revision history, see edebug-history.
-
-;;; Code:
-
-(defconst edebug-version
- (let ((raw-version "$Revision: 3.12 $"))
- (substring raw-version (string-match "[0-9.]*" raw-version)
- (match-end 0))))
-
-(require 'backquote)
-
-;; Emacs 18 doesn't have defalias.
-(eval-and-compile
- (or (fboundp 'defalias) (fset 'defalias 'fset)))
-
-
-;;; Bug reporting
-
-(defconst edebug-maintainer-address "liberte@cs.uiuc.edu")
-
-(defun edebug-submit-bug-report ()
- "Submit, via mail, a bug report on edebug."
- (interactive)
- (require 'reporter)
- (and (y-or-n-p "Do you really want to submit a report on edebug? ")
- (reporter-submit-bug-report
- edebug-maintainer-address
- (concat "edebug.el " edebug-version)
- (list 'edebug-setup-hook
- 'edebug-all-defs
- 'edebug-all-forms
- 'edebug-eval-macro-args
- 'edebug-stop-before-symbols
- 'edebug-save-windows
- 'edebug-save-displayed-buffer-points
- 'edebug-initial-mode
- 'edebug-trace
- 'edebug-test-coverage
- 'edebug-continue-kbd-macro
- 'edebug-print-length
- 'edebug-print-level
- 'edebug-print-circle
- ))))
-
-;;; Options
-
-(defvar edebug-setup-hook nil
- "*Functions to call before edebug is used.
-Each time it is set to a new value, Edebug will call those functions
-once and then `edebug-setup-hook' is reset to nil. You could use this
-to load up Edebug specifications associated with a package you are
-using but only when you also use Edebug.")
-
-(defvar edebug-all-defs nil
- "*If non-nil, evaluation of any defining forms will instrument for Edebug.
-This applies to `eval-defun', `eval-region', `eval-buffer', and
-`eval-current-buffer'. `eval-region' is also called by
-`eval-last-sexp', and `eval-print-last-sexp'.
-
-You can use the command `edebug-all-defs' to toggle the value of this
-variable. You may wish to make it local to each buffer with
-\(make-local-variable 'edebug-all-defs) in your
-`emacs-lisp-mode-hook'.")
-
-(defvar edebug-all-forms nil
- "*Non-nil evaluation of all forms will instrument for Edebug.
-This doesn't apply to loading or evaluations in the minibuffer.
-Use the command `edebug-all-forms' to toggle the value of this option.")
-
-(defvar edebug-eval-macro-args nil
- "*Non-nil means all macro call arguments may be evaluated.
-If this variable is nil, the default, Edebug will *not* wrap
-macro call arguments as if they will be evaluated.
-For each macro, a `edebug-form-spec' overrides this option.
-So to specify exceptions for macros that have some arguments evaluated
-and some not, you should specify an `edebug-form-spec'.
-
-This option is going away soon.")
-
-(defvar edebug-stop-before-symbols nil
- "*Non-nil causes Edebug to stop before symbols as well as after.
-In any case, a breakpoint or interrupt may stop before a symbol.
-
-This option is going away soon.")
-
-(defvar edebug-save-windows t
- "*If non-nil, Edebug saves and restores the window configuration.
-That takes some time, so if your program does not care what happens to
-the window configurations, it is better to set this variable to nil.
-
-If the value is a list, only the listed windows are saved and
-restored.
-
-`edebug-toggle-save-windows' may be used to change this variable.")
-
-(defvar edebug-save-displayed-buffer-points nil
- "*If non-nil, save and restore point in all displayed buffers.
-
-Saving and restoring point in other buffers is necessary if you are
-debugging code that changes the point of a buffer which is displayed
-in a non-selected window. If Edebug or the user then selects the
-window, the buffer's point will be changed to the window's point.
-
-Saving and restoring point in all buffers is expensive, since it
-requires selecting each window twice, so enable this only if you need
-it.")
-
-(defvar edebug-initial-mode 'step
- "*Initial execution mode for Edebug, if non-nil. If this variable
-is non-@code{nil}, it specifies the initial execution mode for Edebug
-when it is first activated. Possible values are step, next, go,
-Go-nonstop, trace, Trace-fast, continue, and Continue-fast.")
-
-(defvar edebug-trace nil
- "*Non-nil means display a trace of function entry and exit.
-Tracing output is displayed in a buffer named `*edebug-trace*', one
-function entry or exit per line, indented by the recursion level.
-
-You can customize by replacing functions `edebug-print-trace-before'
-and `edebug-print-trace-after'.")
-
-(defvar edebug-test-coverage nil
- "*If non-nil, Edebug tests coverage of all expressions debugged.
-This is done by comparing the result of each expression
-with the previous result. Coverage is considered OK if two different
-results are found.
-
-Use `edebug-display-freq-count' to display the frequency count and
-coverage information for a definition.")
-
-(defvar edebug-continue-kbd-macro nil
- "*If non-nil, continue defining or executing any keyboard macro.
-Use this with caution since it is not debugged.")
-
-
-(defvar edebug-print-length 50
- "*Default value of `print-length' to use while printing results in Edebug.")
-(defvar edebug-print-level 50
- "*Default value of `print-level' to use while printing results in Edebug.")
-(defvar edebug-print-circle t
- "*Default value of `print-circle' to use while printing results in Edebug.")
-
-(defvar edebug-unwrap-results nil
- "*Non-nil if Edebug should unwrap results of expressions.
-This is useful when debugging macros where the results of expressions
-are instrumented expressions. But don't do this when results might be
-circular or an infinite loop will result.")
-
-(defvar edebug-on-error t
- "*Value bound to `debug-on-error' while Edebug is active.
-
-If `debug-on-error' is non-nil, that value is still used.
-
-If the value is a list of signal names, Edebug will stop when any of
-these errors are signaled from Lisp code whether or not the signal is
-handled by a `condition-case'. This option is useful for debugging
-signals that *are* handled since they would otherwise be missed.
-After execution is resumed, the error is signaled again.")
-
-(defvar edebug-on-quit t
- "*Value bound to `debug-on-quit' while Edebug is active.")
-
-(defvar edebug-global-break-condition nil
- "*If non-nil, an expression to test for at every stop point.
-If the result is non-nil, then break. Errors are ignored.")
-
-;;; Form spec utilities.
-
-;;;###autoload
-(defmacro def-edebug-spec (symbol spec)
- "Set the edebug-form-spec property of SYMBOL according to SPEC.
-Both SYMBOL and SPEC are unevaluated. The SPEC can be 0, t, a symbol
-\(naming a function), or a list."
- (` (put (quote (, symbol)) 'edebug-form-spec (quote (, spec)))))
-
-(defmacro def-edebug-form-spec (symbol spec-form)
- "For compatibility with old version. Use `def-edebug-spec' instead."
- (message "Obsolete: use def-edebug-spec instead.")
- (def-edebug-spec symbol (eval spec-form)))
-
-(defun get-edebug-spec (symbol)
- ;; Get the spec of symbol resolving all indirection.
- (let ((edebug-form-spec (get symbol 'edebug-form-spec))
- indirect)
- (while (and (symbolp edebug-form-spec)
- (setq indirect (get edebug-form-spec 'edebug-form-spec)))
- ;; (edebug-trace "indirection: %s" edebug-form-spec)
- (setq edebug-form-spec indirect))
- edebug-form-spec
- ))
-
-;;; Utilities
-
-;; Define edebug-gensym - from old cl.el
-(defvar edebug-gensym-index 0
- "Integer used by `edebug-gensym' to produce new names.")
-
-(defun edebug-gensym (&optional prefix)
- "Generate a fresh uninterned symbol.
-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 "G"))
- (let ((newsymbol nil)
- (newname ""))
- (while (not newsymbol)
- (setq newname (concat prefix (int-to-string edebug-gensym-index)))
- (setq edebug-gensym-index (+ edebug-gensym-index 1))
- (if (not (intern-soft newname))
- (setq newsymbol (make-symbol newname))))
- newsymbol))
-
-;; Only used by CL-like code.
-(defun edebug-keywordp (object)
- "Return t if OBJECT is a keyword.
-A keyword is a symbol that starts with `:'."
- (and (symbolp object)
- (= ?: (aref (symbol-name object) 0))))
-
-(defun edebug-lambda-list-keywordp (object)
- "Return t if OBJECT is a lambda list keyword.
-A lambda list keyword is a symbol that starts with `&'."
- (and (symbolp object)
- (= ?& (aref (symbol-name object) 0))))
-
-
-(defun edebug-last-sexp ()
- ;; Return the last sexp before point in current buffer.
- ;; Assumes Emacs Lisp syntax is active.
- (car
- (read-from-string
- (buffer-substring
- (save-excursion
- (forward-sexp -1)
- (point))
- (point)))))
-
-(defun edebug-window-list ()
- "Return a list of windows, in order of `next-window'."
- ;; This doesn't work for epoch.
- (let* ((first-window (selected-window))
- (window-list (list first-window))
- (next (next-window first-window)))
- (while (not (eq next first-window))
- (setq window-list (cons next window-list))
- (setq next (next-window next)))
- (nreverse window-list)))
-
-(defun edebug-window-live-p (window)
- "Return non-nil if WINDOW is visible."
- (let* ((first-window (selected-window))
- (next (next-window first-window t)))
- (while (not (or (eq next window)
- (eq next first-window)))
- (setq next (next-window next t)))
- (eq next window)))
-
-;; Not used.
-'(defun edebug-two-window-p ()
- "Return t if there are two windows."
- (and (not (one-window-p))
- (eq (selected-window)
- (next-window (next-window (selected-window))))))
-
-(defsubst edebug-lookup-function (object)
- (while (and (symbolp object) (fboundp object))
- (setq object (symbol-function object)))
- object)
-
-(defun edebug-macrop (object)
- "Return the macro named by OBJECT, or nil if it is not a macro."
- (setq object (edebug-lookup-function object))
- (if (and (listp object)
- (eq 'macro (car object))
- (edebug-functionp (cdr object)))
- object))
-
-(defun edebug-functionp (object)
- "Returns the function named by OBJECT, or nil if it is not a function."
- (setq object (edebug-lookup-function object))
- (if (or (subrp object)
- (byte-code-function-p object)
- (and (listp object)
- (eq (car object) 'lambda)
- (listp (car (cdr object)))))
- object))
-
-(defun edebug-sort-alist (alist function)
- ;; Return the ALIST sorted with comparison function FUNCTION.
- ;; This uses 'sort so the sorting is destructive.
- (sort alist (function
- (lambda (e1 e2)
- (funcall function (car e1) (car e2))))))
-
-;;(def-edebug-spec edebug-save-restriction t)
-
-;; Not used. If it is used, def-edebug-spec must be defined before use.
-'(defmacro edebug-save-restriction (&rest body)
- "Evaluate BODY while saving the current buffers restriction.
-BODY may change buffer outside of current restriction, unlike
-save-restriction. BODY may change the current buffer,
-and the restriction will be restored to the original buffer,
-and the current buffer remains current.
-Return the result of the last expression in BODY."
- (` (let ((edebug:s-r-beg (point-min-marker))
- (edebug:s-r-end (point-max-marker)))
- (unwind-protect
- (progn (,@ body))
- (save-excursion
- (set-buffer (marker-buffer edebug:s-r-beg))
- (narrow-to-region edebug:s-r-beg edebug:s-r-end))))))
-
-;;; Display
-
-(defconst edebug-trace-buffer "*edebug-trace*"
- "Name of the buffer to put trace info in.")
-
-(defun edebug-pop-to-buffer (buffer &optional window)
- ;; Like pop-to-buffer, but select window where BUFFER was last shown.
- ;; Select WINDOW if it provided and it still exists. Otherwise,
- ;; if buffer is currently shown in several windows, choose one.
- ;; Otherwise, find a new window, possibly splitting one.
- (setq window (if (and (windowp window) (edebug-window-live-p window)
- (eq (window-buffer window) buffer))
- window
- (if (eq (window-buffer (selected-window)) buffer)
- (selected-window)
- (edebug-get-buffer-window buffer))))
- (if window
- (select-window window)
- (if (one-window-p)
- (split-window))
- ;; (message "next window: %s" (next-window)) (sit-for 1)
- (if (eq (get-buffer-window edebug-trace-buffer) (next-window))
- ;; Don't select trace window
- nil
- (select-window (next-window))))
- (set-window-buffer (selected-window) buffer)
- (set-window-hscroll (selected-window) 0);; should this be??
- ;; Selecting the window does not set the buffer until command loop.
- ;;(set-buffer buffer)
- )
-
-
-(defun edebug-get-displayed-buffer-points ()
- ;; Return a list of buffer point pairs, for all displayed buffers.
- (save-excursion
- (let* ((first-window (selected-window))
- (next (next-window first-window))
- (buffer-point-list nil)
- buffer)
- (while (not (eq next first-window))
- (set-buffer (setq buffer (window-buffer next)))
- (setq buffer-point-list
- (cons (cons buffer (point)) buffer-point-list))
- (setq next (next-window next)))
- buffer-point-list)))
-
-
-(defun edebug-set-buffer-points (buffer-points)
- ;; Restore the buffer-points created by edebug-get-displayed-buffer-points.
- (let ((current-buffer (current-buffer)))
- (mapcar (function (lambda (buf-point)
- (if (buffer-name (car buf-point)) ; still exists
- (progn
- (set-buffer (car buf-point))
- (goto-char (cdr buf-point))))))
- buffer-points)
- (set-buffer current-buffer)))
-
-(defun edebug-current-windows (which-windows)
- ;; Get either a full window configuration or some window information.
- (if (listp which-windows)
- (mapcar (function (lambda (window)
- (if (edebug-window-live-p window)
- (list window
- (window-buffer window)
- (window-point window)
- (window-start window)
- (window-hscroll window)))))
- which-windows)
- (current-window-configuration)))
-
-(defun edebug-set-windows (window-info)
- ;; Set either a full window configuration or some window information.
- (if (listp window-info)
- (mapcar (function
- (lambda (one-window-info)
- (if one-window-info
- (apply (function
- (lambda (window buffer point start hscroll)
- (if (edebug-window-live-p window)
- (progn
- (set-window-buffer window buffer)
- (set-window-point window point)
- (set-window-start window start)
- (set-window-hscroll window hscroll)))))
- one-window-info))))
- window-info)
- (set-window-configuration window-info)))
-
-(defalias 'edebug-get-buffer-window 'get-buffer-window)
-(defalias 'edebug-sit-for 'sit-for)
-(defalias 'edebug-input-pending-p 'input-pending-p)
-
-
-;;; Redefine read and eval functions
-;; read is redefined to maybe instrument forms.
-;; eval-defun is redefined to check edebug-all-forms and edebug-all-defs.
-
-;; Use the Lisp version of eval-region.
-(require 'eval-reg "eval-reg")
-
-;; Save the original read function
-(or (fboundp 'edebug-original-read)
- (defalias 'edebug-original-read (symbol-function 'read)))
-
-(defun edebug-read (&optional stream)
- "Read one Lisp expression as text from STREAM, return as Lisp object.
-If STREAM is nil, use the value of `standard-input' (which see).
-STREAM or the value of `standard-input' may be:
- a buffer (read from point and advance it)
- a marker (read from where it points and advance it)
- a function (call it with no arguments for each character,
- call it with a char as argument to push a char back)
- a string (takes text from string, starting at the beginning)
- t (read text line using minibuffer and use it).
-
-This version, from Edebug, maybe instruments the expression. But the
-STREAM must be the current buffer to do so. Whether it instruments is
-also dependent on the values of `edebug-all-defs' and
-`edebug-all-forms'."
- (or stream (setq stream standard-input))
- (if (eq stream (current-buffer))
- (edebug-read-and-maybe-wrap-form)
- (edebug-original-read stream)))
-
-(or (fboundp 'edebug-original-eval-defun)
- (defalias 'edebug-original-eval-defun (symbol-function 'eval-defun)))
-
-;; We should somehow arrange to be able to do this
-;; without actually replacing the eval-defun command.
-(defun edebug-eval-defun (edebug-it)
- "Evaluate the top-level form containing point, or after point.
-
-This version, from Edebug, has the following differences: With a
-prefix argument instrument the code for Edebug. If `edebug-all-defs' is
-non-nil, then the code is instrumented *unless* there is a prefix
-argument. If instrumenting, it prints: `Edebug: FUNCTIONNAME'.
-Otherwise, it prints in the minibuffer."
- (interactive "P")
- (let* ((edebugging (not (eq (not edebug-it) (not edebug-all-defs))))
- (edebug-result)
- (form
- (let ((edebug-all-forms edebugging)
- (edebug-all-defs (eq edebug-all-defs (not edebug-it))))
- (edebug-read-top-level-form))))
- (if (and (eq (car form) 'defvar)
- (cdr-safe (cdr-safe form)))
- (setq form (cons 'defconst (cdr form))))
- (setq edebug-result (eval form))
- (if (not edebugging)
- (princ edebug-result)
- edebug-result)))
-
-
-;;;###autoload
-(defalias 'edebug-defun 'edebug-eval-top-level-form)
-
-;;;###autoload
-(defun edebug-eval-top-level-form ()
- "Evaluate a top level form, such as a defun or defmacro.
-This is like `eval-defun', but the code is always instrumented for Edebug.
-Print its name in the minibuffer and leave point where it is,
-or if an error occurs, leave point after it with mark at the original point."
- (interactive)
- (eval
- ;; Bind edebug-all-forms only while reading, not while evalling
- ;; but this causes problems while edebugging edebug.
- (let ((edebug-all-forms t)
- (edebug-all-defs t))
- (edebug-read-top-level-form))))
-
-
-(defun edebug-read-top-level-form ()
- (let ((starting-point (point)))
- (end-of-defun)
- (beginning-of-defun)
- (prog1
- (edebug-read-and-maybe-wrap-form)
- ;; Recover point, but only if no error occurred.
- (goto-char starting-point))))
-
-
-;; Compatibility with old versions.
-(defalias 'edebug-all-defuns 'edebug-all-defs)
-
-(defun edebug-all-defs ()
- "Toggle edebugging of all definitions."
- (interactive)
- (setq edebug-all-defs (not edebug-all-defs))
- (message "Edebugging all definitions is %s."
- (if edebug-all-defs "on" "off")))
-
-
-(defun edebug-all-forms ()
- "Toggle edebugging of all forms."
- (interactive)
- (setq edebug-all-forms (not edebug-all-forms))
- (message "Edebugging all forms is %s."
- (if edebug-all-forms "on" "off")))
-
-
-(defun edebug-install-read-eval-functions ()
- (interactive)
- ;; Don't install if already installed.
- (if (eq (symbol-function 'read) 'edebug-read) nil
- (elisp-eval-region-install)
- (defalias 'read 'edebug-read)
- (defalias 'eval-defun 'edebug-eval-defun)))
-
-(defun edebug-uninstall-read-eval-functions ()
- (interactive)
- (elisp-eval-region-uninstall)
- (defalias 'read (symbol-function 'edebug-original-read))
- (defalias 'eval-defun (symbol-function 'edebug-original-eval-defun)))
-
-
-;;; Edebug internal data
-
-;; The internal data that is needed for edebugging is kept in the
-;; buffer-local variable `edebug-form-data'.
-
-(make-variable-buffer-local 'edebug-form-data)
-
-(defconst edebug-form-data nil)
-;; A list of entries associating symbols with buffer regions.
-;; This is an automatic buffer local variable. Each entry looks like:
-;; @code{(@var{symbol} @var{begin-marker} @var{end-marker}). The markers
-;; are at the beginning and end of an entry level form and @var{symbol} is
-;; a symbol that holds all edebug related information for the form on its
-;; property list.
-
-;; In the future, the symbol will be irrelevant and edebug data will
-;; be stored in the definitions themselves rather than in the property
-;; list of a symbol.
-
-(defun edebug-make-form-data-entry (symbol begin end)
- (list symbol begin end))
-
-(defsubst edebug-form-data-name (entry)
- (car entry))
-
-(defsubst edebug-form-data-begin (entry)
- (nth 1 entry))
-
-(defsubst edebug-form-data-end (entry)
- (nth 2 entry))
-
-(defsubst edebug-set-form-data-entry (entry name begin end)
- (setcar entry name);; in case name is changed
- (set-marker (nth 1 entry) begin)
- (set-marker (nth 2 entry) end))
-
-(defun edebug-get-form-data-entry (pnt &optional end-point)
- ;; Find the edebug form data entry which is closest to PNT.
- ;; If END-POINT is supplied, match must be exact.
- ;; Return `nil' if none found.
- (let ((rest edebug-form-data)
- closest-entry
- (closest-dist 999999)) ;; need maxint here
- (while (and rest (< 0 closest-dist))
- (let* ((entry (car rest))
- (begin (edebug-form-data-begin entry))
- (dist (- pnt begin)))
- (setq rest (cdr rest))
- (if (and (<= 0 dist)
- (< dist closest-dist)
- (or (not end-point)
- (= end-point (edebug-form-data-end entry)))
- (<= pnt (edebug-form-data-end entry)))
- (setq closest-dist dist
- closest-entry entry))))
- closest-entry))
-
-;; Also need to find all contained entries,
-;; and find an entry given a symbol, which should be just assq.
-
-(defun edebug-form-data-symbol ()
-;; Return the edebug data symbol of the form where point is in.
-;; If point is not inside a edebuggable form, cause error.
- (or (edebug-form-data-name (edebug-get-form-data-entry (point)))
- (error "Not inside instrumented form")))
-
-(defun edebug-make-top-form-data-entry (new-entry)
- ;; Make NEW-ENTRY the first element in the `edebug-form-data' list.
- (edebug-clear-form-data-entry new-entry)
- (setq edebug-form-data (cons new-entry edebug-form-data)))
-
-(defun edebug-clear-form-data-entry (entry)
-;; If non-nil, clear ENTRY out of the form data.
-;; Maybe clear the markers and delete the symbol's edebug property?
- (if entry
- (progn
- ;; Instead of this, we could just find all contained forms.
- ;; (put (car entry) 'edebug nil) ;
- ;; (mapcar 'edebug-clear-form-data-entry ; dangerous
- ;; (get (car entry) 'edebug-dependents))
- ;; (set-marker (nth 1 entry) nil)
- ;; (set-marker (nth 2 entry) nil)
- (setq edebug-form-data (delq entry edebug-form-data)))))
-
-;;; Parser utilities
-
-(defun edebug-syntax-error (&rest args)
- ;; Signal an invalid-read-syntax with ARGS.
- (signal 'invalid-read-syntax args))
-
-
-(defconst edebug-read-syntax-table
- ;; Lookup table for significant characters indicating the class of the
- ;; token that follows. This is not a \"real\" syntax table.
- (let ((table (make-vector 256 'symbol))
- (i 0))
- (while (< i ?!)
- (aset table i 'space)
- (setq i (1+ i)))
- (aset table ?\( 'lparen)
- (aset table ?\) 'rparen)
- (aset table ?\' 'quote)
- (aset table ?\` 'backquote)
- (aset table ?\, 'comma)
- (aset table ?\" 'string)
- (aset table ?\? 'char)
- (aset table ?\[ 'lbracket)
- (aset table ?\] 'rbracket)
- (aset table ?\. 'dot)
- (aset table ?\# 'hash)
- ;; We treat numbers as symbols, because of confusion with -, -1, and 1-.
- ;; We don't care about any other chars since they won't be seen.
- table))
-
-(defun edebug-next-token-class ()
- ;; Move to the next token and return its class. We only care about
- ;; lparen, rparen, dot, quote, backquote, comma, string, char, vector,
- ;; or symbol.
- (edebug-skip-whitespace)
- (aref edebug-read-syntax-table (following-char)))
-
-
-(defun edebug-skip-whitespace ()
- ;; Leave point before the next token, skipping white space and comments.
- (skip-chars-forward " \t\r\n\f")
- (while (= (following-char) ?\;)
- ;; \r is counted as a comment terminator to support selective display.
- (skip-chars-forward "^\n\r") ; skip the comment
- (skip-chars-forward " \t\r\n\f")))
-
-
-;; Mostly obsolete reader; still used in one case.
-
-(defun edebug-read-sexp ()
- ;; Read one sexp from the current buffer starting at point.
- ;; Leave point immediately after it. A sexp can be a list or atom.
- ;; An atom is a symbol (or number), character, string, or vector.
- ;; This works for reading anything legitimate, but it
- ;; is gummed up by parser inconsistencies (bugs?)
- (let ((class (edebug-next-token-class)))
- (cond
- ;; read goes one too far if a (possibly quoted) string or symbol
- ;; is immediately followed by non-whitespace.
- ((eq class 'symbol) (edebug-original-read (current-buffer)))
- ((eq class 'string) (edebug-original-read (current-buffer)))
- ((eq class 'quote) (forward-char 1)
- (list 'quote (edebug-read-sexp)))
- ((eq class 'backquote)
- (list '\` (edebug-read-sexp)))
- ((eq class 'comma)
- (list '\, (edebug-read-sexp)))
- (t ; anything else, just read it.
- (edebug-original-read (current-buffer))))))
-
-;;; Offsets for reader
-
-;; Define a structure to represent offset positions of expressions.
-;; Each offset structure looks like: (before . after) for constituents,
-;; or for structures that have elements: (before <subexpressions> . after)
-;; where the <subexpressions> are the offset structures for subexpressions
-;; including the head of a list.
-(defconst edebug-offsets nil)
-
-;; Stack of offset structures in reverse order of the nesting.
-;; This is used to get back to previous levels.
-(defconst edebug-offsets-stack nil)
-(defconst edebug-current-offset nil) ; Top of the stack, for convenience.
-
-;; We must store whether we just read a list with a dotted form that
-;; is itself a list. This structure will be condensed, so the offsets
-;; must also be condensed.
-(defconst edebug-read-dotted-list nil)
-
-(defsubst edebug-initialize-offsets ()
- ;; Reinitialize offset recording.
- (setq edebug-current-offset nil))
-
-(defun edebug-store-before-offset (point)
- ;; Add a new offset pair with POINT as the before offset.
- (let ((new-offset (list point)))
- (if edebug-current-offset
- (setcdr edebug-current-offset
- (cons new-offset (cdr edebug-current-offset)))
- ;; Otherwise, we are at the top level, so initialize.
- (setq edebug-offsets new-offset
- edebug-offsets-stack nil
- edebug-read-dotted-list nil))
- ;; Cons the new offset to the front of the stack.
- (setq edebug-offsets-stack (cons new-offset edebug-offsets-stack)
- edebug-current-offset new-offset)
- ))
-
-(defun edebug-store-after-offset (point)
- ;; Finalize the current offset struct by reversing it and
- ;; store POINT as the after offset.
- (if (not edebug-read-dotted-list)
- ;; Just reverse the offsets of all subexpressions.
- (setcdr edebug-current-offset (nreverse (cdr edebug-current-offset)))
-
- ;; We just read a list after a dot, which will be abbreviated out.
- (setq edebug-read-dotted-list nil)
- ;; Drop the corresponding offset pair.
- ;; That is, nconc the reverse of the rest of the offsets
- ;; with the cdr of last offset.
- (setcdr edebug-current-offset
- (nconc (nreverse (cdr (cdr edebug-current-offset)))
- (cdr (car (cdr edebug-current-offset))))))
-
- ;; Now append the point using nconc.
- (setq edebug-current-offset (nconc edebug-current-offset point))
- ;; Pop the stack.
- (setq edebug-offsets-stack (cdr edebug-offsets-stack)
- edebug-current-offset (car edebug-offsets-stack)))
-
-(defun edebug-ignore-offset ()
- ;; Ignore the last created offset pair.
- (setcdr edebug-current-offset (cdr (cdr edebug-current-offset))))
-
-(def-edebug-spec edebug-storing-offsets (form body))
-(put 'edebug-storing-offsets 'lisp-indent-hook 1)
-
-(defmacro edebug-storing-offsets (point &rest body)
- (` (unwind-protect
- (progn
- (edebug-store-before-offset (, point))
- (,@ body))
- (edebug-store-after-offset (point)))))
-
-
-;;; Reader for Emacs Lisp.
-
-;; Uses edebug-next-token-class (and edebug-skip-whitespace) above.
-
-(defconst edebug-read-alist
- '((symbol . edebug-read-symbol)
- (lparen . edebug-read-list)
- (string . edebug-read-string)
- (quote . edebug-read-quote)
- (backquote . edebug-read-backquote)
- (comma . edebug-read-comma)
- (lbracket . edebug-read-vector)
- (hash . edebug-read-function)
- ))
-
-(defun edebug-read-storing-offsets (stream)
- (let ((class (edebug-next-token-class))
- func
- edebug-read-dotted-list) ; see edebug-store-after-offset
- (edebug-storing-offsets (point)
- (if (setq func (assq class edebug-read-alist))
- (funcall (cdr func) stream)
- ;; anything else, just read it.
- (edebug-original-read stream))
- )))
-
-(defun edebug-read-symbol (stream)
- (edebug-original-read stream))
-
-(defun edebug-read-string (stream)
- (edebug-original-read stream))
-
-(defun edebug-read-quote (stream)
- ;; Turn 'thing into (quote thing)
- (forward-char 1)
- (list
- (edebug-storing-offsets (point) 'quote)
- (edebug-read-storing-offsets stream)))
-
-(defun edebug-read-backquote (stream)
- ;; Turn `thing into (\` thing)
- (let ((opoint (point)))
- (forward-char 1)
- ;; Generate the same structure of offsets we would have
- ;; if the resulting list appeared verbatim in the input text.
- (edebug-storing-offsets opoint
- (list
- (edebug-storing-offsets opoint '\`)
- (edebug-read-storing-offsets stream)))))
-
-(defvar edebug-read-backquote-new nil
- "Non-nil if reading the inside of a new-style backquote with no parens around it.
-Value of nil means reading the inside of an old-style backquote construct
-which is surrounded by an extra set of parentheses.
-This controls how we read comma constructs.")
-
-(defun edebug-read-comma (stream)
- ;; Turn ,thing into (\, thing). Handle ,@ and ,. also.
- (let ((opoint (point)))
- (forward-char 1)
- (let ((symbol '\,))
- (cond ((eq (following-char) ?\.)
- (setq symbol '\,\.)
- (forward-char 1))
- ((eq (following-char) ?\@)
- (setq symbol '\,@)
- (forward-char 1)))
- ;; Generate the same structure of offsets we would have
- ;; if the resulting list appeared verbatim in the input text.
- (if edebug-read-backquote-new
- (list
- (edebug-storing-offsets opoint symbol)
- (edebug-read-storing-offsets stream))
- (edebug-storing-offsets opoint symbol)))))
-
-(defun edebug-read-function (stream)
- ;; Turn #'thing into (function thing)
- (forward-char 1)
- (if (/= ?\' (following-char)) (edebug-syntax-error "Bad char"))
- (forward-char 1)
- (list
- (edebug-storing-offsets (point)
- (if (featurep 'cl) 'function* 'function))
- (edebug-read-storing-offsets stream)))
-
-(defun edebug-read-list (stream)
- (forward-char 1) ; skip \(
- (prog1
- (let ((elements))
- (while (not (memq (edebug-next-token-class) '(rparen dot)))
- (if (eq (edebug-next-token-class) 'backquote)
- (let ((edebug-read-backquote-new (not (null elements)))
- (opoint (point)))
- (if edebug-read-backquote-new
- (setq elements (cons (edebug-read-backquote stream) elements))
- (forward-char 1) ; Skip backquote.
- ;; Call edebug-storing-offsets here so that we
- ;; produce the same offsets we would have had
- ;; if the backquote were an ordinary symbol.
- (setq elements (cons (edebug-storing-offsets opoint '\`)
- elements))))
- (setq elements (cons (edebug-read-storing-offsets stream) elements))))
- (setq elements (nreverse elements))
- (if (eq 'dot (edebug-next-token-class))
- (let (dotted-form)
- (forward-char 1) ; skip \.
- (setq dotted-form (edebug-read-storing-offsets stream))
- elements (nconc elements dotted-form)
- (if (not (eq (edebug-next-token-class) 'rparen))
- (edebug-syntax-error "Expected `)'"))
- (setq edebug-read-dotted-list (listp dotted-form))
- ))
- elements)
- (forward-char 1) ; skip \)
- ))
-
-(defun edebug-read-vector (stream)
- (forward-char 1) ; skip \[
- (prog1
- (let ((elements))
- (while (not (eq 'rbracket (edebug-next-token-class)))
- (setq elements (cons (edebug-read-storing-offsets stream) elements)))
- (apply 'vector (nreverse elements)))
- (forward-char 1) ; skip \]
- ))
-
-;;; Cursors for traversal of list and vector elements with offsets.
-
-(defvar edebug-dotted-spec nil)
-
-(defun edebug-new-cursor (expressions offsets)
- ;; Return a new cursor for EXPRESSIONS with OFFSETS.
- (if (vectorp expressions)
- (setq expressions (append expressions nil)))
- (cons expressions offsets))
-
-(defsubst edebug-set-cursor (cursor expressions offsets)
- ;; Set the CURSOR's EXPRESSIONS and OFFSETS to the given.
- ;; Return the cursor.
- (setcar cursor expressions)
- (setcdr cursor offsets)
- cursor)
-
-'(defun edebug-copy-cursor (cursor)
- ;; Copy the cursor using the same object and offsets.
- (cons (car cursor) (cdr cursor)))
-
-(defsubst edebug-cursor-expressions (cursor)
- (car cursor))
-(defsubst edebug-cursor-offsets (cursor)
- (cdr cursor))
-
-(defsubst edebug-empty-cursor (cursor)
- ;; Return non-nil if CURSOR is empty - meaning no more elements.
- (null (car cursor)))
-
-(defsubst edebug-top-element (cursor)
- ;; Return the top element at the cursor.
- ;; Assumes not empty.
- (car (car cursor)))
-
-(defun edebug-top-element-required (cursor &rest error)
- ;; Check if a dotted form is required.
- (if edebug-dotted-spec (edebug-no-match cursor "Dot expected."))
- ;; Check if there is at least one more argument.
- (if (edebug-empty-cursor cursor) (apply 'edebug-no-match cursor error))
- ;; Return that top element.
- (edebug-top-element cursor))
-
-(defsubst edebug-top-offset (cursor)
- ;; Return the top offset pair corresponding to the top element.
- (car (cdr cursor)))
-
-(defun edebug-move-cursor (cursor)
- ;; Advance and return the cursor to the next element and offset.
- ;; throw no-match if empty before moving.
- ;; This is a violation of the cursor encapsulation, but
- ;; there is plenty of that going on while matching.
- ;; The following test should always fail.
- (if (edebug-empty-cursor cursor)
- (edebug-no-match cursor "Not enough arguments."))
- (setcar cursor (cdr (car cursor)))
- (setcdr cursor (cdr (cdr cursor)))
- cursor)
-
-
-(defun edebug-before-offset (cursor)
- ;; Return the before offset of the cursor.
- ;; If there is nothing left in the offsets,
- ;; return one less than the offset itself,
- ;; which is the after offset for a list.
- (let ((offset (edebug-cursor-offsets cursor)))
- (if (consp offset)
- (car (car offset))
- (1- offset))))
-
-(defun edebug-after-offset (cursor)
- ;; Return the after offset of the cursor object.
- (let ((offset (edebug-top-offset cursor)))
- (while (consp offset)
- (setq offset (cdr offset)))
- offset))
-
-;;; The Parser
-
-;; The top level function for parsing forms is
-;; edebug-read-and-maybe-wrap-form; it calls all the rest. It checks the
-;; syntax a bit and leaves point at any error it finds, but otherwise
-;; should appear to work like eval-defun.
-
-;; The basic plan is to surround each expression with a call to
-;; the edebug debugger together with indexes into a table of positions of
-;; all expressions. Thus an expression "exp" becomes:
-
-;; (edebug-after (edebug-before 1) 2 exp)
-
-;; When this is evaluated, first point is moved to the beginning of
-;; exp at offset 1 of the current function. The expression is
-;; evaluated, which may cause more edebug calls, and then point is
-;; moved to offset 2 after the end of exp.
-
-;; The highest level expressions of the function are wrapped in a call to
-;; edebug-enter, which supplies the function name and the actual
-;; arguments to the function. See functions edebug-enter, edebug-before,
-;; and edebug-after for more details.
-
-;; Dynamically bound vars, left unbound, but globally declared.
-;; This is to quiet the byte compiler.
-
-;; Window data of the highest definition being wrapped.
-;; This data is shared by all embedded definitions.
-(defvar edebug-top-window-data)
-
-(defvar edebug-&optional)
-(defvar edebug-&rest)
-(defvar edebug-gate nil) ;; whether no-match forces an error.
-
-(defconst edebug-def-name nil) ; name of definition, used by interactive-form
-(defconst edebug-old-def-name nil) ; previous name of containing definition.
-
-(defconst edebug-error-point nil)
-(defconst edebug-best-error nil)
-
-
-(defun edebug-read-and-maybe-wrap-form ()
- ;; Read a form and wrap it with edebug calls, if the conditions are right.
- ;; Here we just catch any no-match not caught below and signal an error.
-
- ;; Run the setup hook.
- (run-hooks 'edebug-setup-hook)
- (setq edebug-setup-hook nil)
-
- (let (result
- edebug-top-window-data
- edebug-def-name;; make sure it is locally nil
- ;; I don't like these here!!
- edebug-&optional
- edebug-&rest
- edebug-gate
- edebug-best-error
- edebug-error-point
- no-match
- ;; Do this once here instead of several times.
- (max-lisp-eval-depth (+ 800 max-lisp-eval-depth))
- (max-specpdl-size (+ 2000 max-specpdl-size)))
- (setq no-match
- (catch 'no-match
- (setq result (edebug-read-and-maybe-wrap-form1))
- nil))
- (if no-match
- (apply 'edebug-syntax-error no-match))
- result))
-
-
-(defun edebug-read-and-maybe-wrap-form1 ()
- (let (spec
- def-kind
- defining-form-p
- def-name
- ;; These offset things don't belong here, but to support recursive
- ;; calls to edebug-read, they need to be here.
- edebug-offsets
- edebug-offsets-stack
- edebug-current-offset ; reset to nil
- )
- (save-excursion
- (if (and (eq 'lparen (edebug-next-token-class))
- (eq 'symbol (progn (forward-char 1) (edebug-next-token-class))))
- ;; Find out if this is a defining form from first symbol
- (setq def-kind (edebug-original-read (current-buffer))
- spec (and (symbolp def-kind) (get-edebug-spec def-kind))
- defining-form-p (and (listp spec)
- (eq '&define (car spec)))
- ;; This is incorrect in general!! But OK most of the time.
- def-name (if (and defining-form-p
- (eq 'name (car (cdr spec)))
- (eq 'symbol (edebug-next-token-class)))
- (edebug-original-read (current-buffer))))))
-;;;(message "all defs: %s all forms: %s" edebug-all-defs edebug-all-forms)
- (cond
- (defining-form-p
- (if (or edebug-all-defs edebug-all-forms)
- ;; If it is a defining form and we are edebugging defs,
- ;; then let edebug-list-form start it.
- (let ((cursor (edebug-new-cursor
- (list (edebug-read-storing-offsets (current-buffer)))
- (list edebug-offsets))))
- (car
- (edebug-make-form-wrapper
- cursor
- (edebug-before-offset cursor)
- (1- (edebug-after-offset cursor))
- (list (cons (symbol-name def-kind) (cdr spec))))))
-
- ;; Not edebugging this form, so reset the symbol's edebug
- ;; property to be just a marker at the definition's source code.
- ;; This only works for defs with simple names.
- (put def-name 'edebug (point-marker))
- ;; Also nil out dependent defs.
- '(mapcar (function
- (lambda (def)
- (put def-name 'edebug nil)))
- (get def-name 'edebug-dependents))
- (edebug-read-sexp)))
-
- ;; If all forms are being edebugged, explicitly wrap it.
- (edebug-all-forms
- (let ((cursor (edebug-new-cursor
- (list (edebug-read-storing-offsets (current-buffer)))
- (list edebug-offsets))))
- (edebug-make-form-wrapper
- cursor
- (edebug-before-offset cursor)
- (edebug-after-offset cursor)
- nil)))
-
- ;; Not a defining form, and not edebugging.
- (t (edebug-read-sexp)))
- ))
-
-
-(defvar edebug-def-args) ; args of defining form.
-(defvar edebug-def-interactive) ; is it an emacs interactive function?
-(defvar edebug-inside-func) ;; whether code is inside function context.
-;; Currently def-form sets this to nil; def-body sets it to t.
-
-(defun edebug-interactive-p-name ()
- ;; Return a unique symbol for the variable used to store the
- ;; status of interactive-p for this function.
- (intern (format "edebug-%s-interactive-p" edebug-def-name)))
-
-
-(defun edebug-wrap-def-body (forms)
- "Wrap the FORMS of a definition body."
- (if edebug-def-interactive
- (` (let (((, (edebug-interactive-p-name))
- (interactive-p)))
- (, (edebug-make-enter-wrapper forms))))
- (edebug-make-enter-wrapper forms)))
-
-
-(defun edebug-make-enter-wrapper (forms)
- ;; Generate the enter wrapper for some forms of a definition.
- ;; This is not to be used for the body of other forms, e.g. `while',
- ;; since it wraps the list of forms with a call to `edebug-enter'.
- ;; Uses the dynamically bound vars edebug-def-name and edebug-def-args.
- ;; Do this after parsing since that may find a name.
- (setq edebug-def-name
- (or edebug-def-name edebug-old-def-name (edebug-gensym "edebug-anon")))
- (` (edebug-enter
- (quote (, edebug-def-name))
- (, (if edebug-inside-func
- (` (list (,@
- ;; Doesn't work with more than one def-body!!
- ;; But the list will just be reversed.
- (nreverse edebug-def-args))))
- 'nil))
- (function (lambda () (,@ forms)))
- )))
-
-
-(defvar edebug-form-begin-marker) ; the mark for def being instrumented
-
-(defvar edebug-offset-index) ; the next available offset index.
-(defvar edebug-offset-list) ; the list of offset positions.
-
-(defun edebug-inc-offset (offset)
- ;; modifies edebug-offset-index and edebug-offset-list
- ;; accesses edebug-func-marc and buffer point
- (prog1
- edebug-offset-index
- (setq edebug-offset-list (cons (- offset edebug-form-begin-marker)
- edebug-offset-list)
- edebug-offset-index (1+ edebug-offset-index))))
-
-
-(defun edebug-make-before-and-after-form (before-index form after-index)
- ;; Return the edebug form for the current function at offset BEFORE-INDEX
- ;; given FORM. Looks like:
- ;; (edebug-after (edebug-before BEFORE-INDEX) AFTER-INDEX FORM)
- ;; Also increment the offset index for subsequent use.
- ;; if (not edebug-stop-before-symbols) and form is a symbol,
- ;; then don't call edebug-before.
- (list 'edebug-after
- (list 'edebug-before before-index)
- after-index form))
-
-(defun edebug-make-after-form (form after-index)
- ;; Like edebug-make-before-and-after-form, but only after.
- (list 'edebug-after 0 after-index form))
-
-
-(defun edebug-unwrap (sexp)
- "Return the unwrapped SEXP or return it as is if it is not wrapped.
-The SEXP might be the result of wrapping a body, which is a list of
-expressions; a `progn' form will be returned enclosing these forms."
- (if (consp sexp)
- (cond
- ((eq 'edebug-after (car sexp))
- (nth 3 sexp))
- ((eq 'edebug-enter (car sexp))
- (let ((forms (nthcdr 2 (nth 1 (nth 3 sexp)))))
- (if (> (length forms) 1)
- (cons 'progn forms) ;; could return (values forms) instead.
- (car forms))))
- (t sexp);; otherwise it is not wrapped, so just return it.
- )
- sexp))
-
-(defun edebug-unwrap* (sexp)
- "Return the sexp recursively unwrapped."
- (let ((new-sexp (edebug-unwrap sexp)))
- (while (not (eq sexp new-sexp))
- (setq sexp new-sexp
- new-sexp (edebug-unwrap sexp)))
- (if (consp new-sexp)
- (mapcar 'edebug-unwrap* new-sexp)
- new-sexp)))
-
-
-(defun edebug-defining-form (cursor form-begin form-end speclist)
- ;; Process the defining form, starting outside the form.
- ;; The speclist is a generated list spec that looks like:
- ;; (("def-symbol" defining-form-spec-sans-&define))
- ;; Skip the first offset.
- (edebug-set-cursor cursor (edebug-cursor-expressions cursor)
- (cdr (edebug-cursor-offsets cursor)))
- (edebug-make-form-wrapper
- cursor
- form-begin (1- form-end)
- speclist))
-
-(defun edebug-make-form-wrapper (cursor form-begin form-end
- &optional speclist)
- ;; Wrap a form, usually a defining form, but any evaluated one.
- ;; If speclist is non-nil, this is being called by edebug-defining-form.
- ;; Otherwise it is being called from edebug-read-and-maybe-wrap-form1.
- ;; This is a hack, but I havent figured out a simpler way yet.
- (let* ((form-data-entry (edebug-get-form-data-entry form-begin form-end))
- ;; Set this marker before parsing.
- (edebug-form-begin-marker
- (if form-data-entry
- (edebug-form-data-begin form-data-entry)
- ;; Buffer must be current-buffer for this to work:
- (set-marker (make-marker) form-begin))))
-
- (let (edebug-offset-list
- (edebug-offset-index 0)
- result
- ;; For definitions.
- ;; (edebug-containing-def-name edebug-def-name)
- ;; Get name from form-data, if any.
- (edebug-old-def-name (edebug-form-data-name form-data-entry))
- edebug-def-name
- edebug-def-args
- edebug-def-interactive
- edebug-inside-func;; whether wrapped code executes inside a function.
- )
-
- (setq result
- (if speclist
- (edebug-match cursor speclist)
-
- ;; else wrap as an enter-form.
- (edebug-make-enter-wrapper (list (edebug-form cursor)))))
-
- ;; Set the name here if it was not set by edebug-make-enter-wrapper.
- (setq edebug-def-name
- (or edebug-def-name edebug-old-def-name (edebug-gensym "edebug-anon")))
-
- ;; Add this def as a dependent of containing def. Buggy.
- '(if (and edebug-containing-def-name
- (not (get edebug-containing-def-name 'edebug-dependents)))
- (put edebug-containing-def-name 'edebug-dependents
- (cons edebug-def-name
- (get edebug-containing-def-name
- 'edebug-dependents))))
-
- ;; Create a form-data-entry or modify existing entry's markers.
- ;; In the latter case, pointers to the entry remain eq.
- (if (not form-data-entry)
- (setq form-data-entry
- (edebug-make-form-data-entry
- edebug-def-name
- edebug-form-begin-marker
- ;; Buffer must be current-buffer.
- (set-marker (make-marker) form-end)
- ))
- (edebug-set-form-data-entry
- form-data-entry edebug-def-name ;; in case name is changed
- form-begin form-end))
-
- ;; (message "defining: %s" edebug-def-name) (sit-for 2)
- (edebug-make-top-form-data-entry form-data-entry)
- (message "Edebug: %s" edebug-def-name)
- ;;(debug edebug-def-name)
-
- ;; Destructively reverse edebug-offset-list and make vector from it.
- (setq edebug-offset-list (vconcat (nreverse edebug-offset-list)))
-
- ;; Side effects on the property list of edebug-def-name.
- (edebug-clear-frequency-count edebug-def-name)
- (edebug-clear-coverage edebug-def-name)
-
- ;; Set up the initial window data.
- (if (not edebug-top-window-data) ;; if not already set, do it now.
- (let ((window ;; Find the best window for this buffer.
- (or (get-buffer-window (current-buffer))
- (selected-window))))
- (setq edebug-top-window-data
- (cons window (window-start window)))))
-
- ;; Store the edebug data in symbol's property list.
- (put edebug-def-name 'edebug
- ;; A struct or vector would be better here!!
- (list edebug-form-begin-marker
- nil ; clear breakpoints
- edebug-offset-list
- edebug-top-window-data
- ))
- result
- )))
-
-
-(defun edebug-clear-frequency-count (name)
- ;; Create initial frequency count vector.
- ;; For each stop point, the counter is incremented each time it is visited.
- (put name 'edebug-freq-count
- (make-vector (length edebug-offset-list) 0)))
-
-
-(defun edebug-clear-coverage (name)
- ;; Create initial coverage vector.
- ;; Only need one per expression, but it is simpler to use stop points.
- (put name 'edebug-coverage
- (make-vector (length edebug-offset-list) 'unknown)))
-
-
-(defun edebug-form (cursor)
- ;; Return the instrumented form for the following form.
- ;; Add the point offsets to the edebug-offset-list for the form.
- (let* ((form (edebug-top-element-required cursor "Expected form"))
- (offset (edebug-top-offset cursor)))
- (prog1
- (cond
- ((consp form)
- ;; The first offset for a list form is for the list form itself.
- (if (eq 'quote (car form))
- form
- (let* ((head (car form))
- (spec (and (symbolp head) (get-edebug-spec head)))
- (new-cursor (edebug-new-cursor form offset)))
- ;; Find out if this is a defining form from first symbol.
- ;; An indirect spec would not work here, yet.
- (if (and (consp spec) (eq '&define (car spec)))
- (edebug-defining-form
- new-cursor
- (car offset);; before the form
- (edebug-after-offset cursor)
- (cons (symbol-name head) (cdr spec)))
- ;; Wrap a regular form.
- (edebug-make-before-and-after-form
- (edebug-inc-offset (car offset))
- (edebug-list-form new-cursor)
- ;; After processing the list form, the new-cursor is left
- ;; with the offset after the form.
- (edebug-inc-offset (edebug-cursor-offsets new-cursor))))
- )))
-
- ((symbolp form)
- (cond
- ;; Check for constant symbols that don't get wrapped.
- ((or (memq form '(t nil))
- (and (fboundp 'edebug-keywordp) (edebug-keywordp form)))
- form)
-
- ;; This option may go away.
- (edebug-stop-before-symbols
- (edebug-make-before-and-after-form
- (edebug-inc-offset (car offset))
- form
- (edebug-inc-offset (cdr offset))
- ))
-
- (t ;; just a variable
- (edebug-make-after-form form (edebug-inc-offset (cdr offset))))))
-
- ;; Anything else is self-evaluating.
- (t form))
- (edebug-move-cursor cursor))))
-
-
-(defsubst edebug-forms (cursor) (edebug-match cursor '(&rest form)))
-(defsubst edebug-sexps (cursor) (edebug-match cursor '(&rest sexp)))
-
-(defsubst edebug-list-form-args (head cursor)
- ;; Process the arguments of a list form given that head of form is a symbol.
- ;; Helper for edebug-list-form
- (let ((spec (get-edebug-spec head)))
- (cond
- (spec
- (cond
- ((consp spec)
- ;; It is a speclist.
- (let (edebug-best-error
- edebug-error-point);; This may not be needed.
- (edebug-match-sublist cursor spec)))
- ((eq t spec) (edebug-forms cursor))
- ((eq 0 spec) (edebug-sexps cursor))
- ((symbolp spec) (funcall spec cursor));; Not used by edebug,
- ; but leave it in for compatibility.
- ))
- ;; No edebug-form-spec provided.
- ((edebug-macrop head)
- (if edebug-eval-macro-args
- (edebug-forms cursor)
- (edebug-sexps cursor)))
- (t ;; Otherwise it is a function call.
- (edebug-forms cursor)))))
-
-
-(defun edebug-list-form (cursor)
- ;; Return an instrumented form built from the list form.
- ;; The after offset will be left in the cursor after processing the form.
- (let ((head (edebug-top-element-required cursor "Expected elements"))
- ;; Prevent backtracking whenever instrumenting.
- (edebug-gate t)
- ;; A list form is never optional because it matches anything.
- (edebug-&optional nil)
- (edebug-&rest nil))
- ;; Skip the first offset.
- (edebug-set-cursor cursor (edebug-cursor-expressions cursor)
- (cdr (edebug-cursor-offsets cursor)))
- (cond
- ((null head) nil) ; () is legal.
-
- ((symbolp head)
- (cond
- ((null head)
- (edebug-syntax-error "nil head"))
- ((eq head 'interactive-p)
- ;; Special case: replace (interactive-p) with variable
- (setq edebug-def-interactive 'check-it)
- (edebug-move-cursor cursor)
- (edebug-interactive-p-name))
- (t
- (cons head (edebug-list-form-args
- head (edebug-move-cursor cursor))))))
-
- ((consp head)
- (if (and (listp head) (eq (car head) ',))
- (edebug-match cursor '(("," def-form) body))
- ;; Process anonymous function and args.
- ;; This assumes no anonymous macros.
- (edebug-match-specs cursor '(lambda-expr body) 'edebug-match-specs)))
-
- (t (edebug-syntax-error
- "Head of list form must be a symbol or lambda expression.")))
- ))
-
-;;; Matching of specs.
-
-(defvar edebug-after-dotted-spec nil)
-
-(defvar edebug-matching-depth 0) ;; initial value
-(defconst edebug-max-depth 150) ;; maximum number of matching recursions.
-
-
-;;; Failure to match
-
-;; This throws to no-match, if there are higher alternatives.
-;; Otherwise it signals an error. The place of the error is found
-;; with the two before- and after-offset functions.
-
-(defun edebug-no-match (cursor &rest edebug-args)
- ;; Throw a no-match, or signal an error immediately if gate is active.
- ;; Remember this point in case we need to report this error.
- (setq edebug-error-point (or edebug-error-point
- (edebug-before-offset cursor))
- edebug-best-error (or edebug-best-error edebug-args))
- (if (and edebug-gate (not edebug-&optional))
- (progn
- (if edebug-error-point
- (goto-char edebug-error-point))
- (apply 'edebug-syntax-error edebug-args))
- (funcall 'throw 'no-match edebug-args)))
-
-
-(defun edebug-match (cursor specs)
- ;; Top level spec matching function.
- ;; Used also at each lower level of specs.
- (let (edebug-&optional
- edebug-&rest
- edebug-best-error
- edebug-error-point
- (edebug-gate edebug-gate) ;; locally bound to limit effect
- )
- (edebug-match-specs cursor specs 'edebug-match-specs)))
-
-
-(defun edebug-match-one-spec (cursor spec)
- ;; Match one spec, which is not a keyword &-spec.
- (cond
- ((symbolp spec) (edebug-match-symbol cursor spec))
- ((vectorp spec) (edebug-match cursor (append spec nil)))
- ((stringp spec) (edebug-match-string cursor spec))
- ((listp spec) (edebug-match-list cursor spec))
- ))
-
-
-(defun edebug-match-specs (cursor specs remainder-handler)
- ;; Append results of matching the list of specs.
- ;; The first spec is handled and the remainder-handler handles the rest.
- (let ((edebug-matching-depth
- (if (> edebug-matching-depth edebug-max-depth)
- (error "too deep - perhaps infinite loop in spec?")
- (1+ edebug-matching-depth))))
- (cond
- ((null specs) nil)
-
- ;; Is the spec dotted?
- ((atom specs)
- (let ((edebug-dotted-spec t));; Containing spec list was dotted.
- (edebug-match-specs cursor (list specs) remainder-handler)))
-
- ;; Is the form dotted?
- ((not (listp (edebug-cursor-expressions cursor)));; allow nil
- (if (not edebug-dotted-spec)
- (edebug-no-match cursor "Dotted spec required."))
- ;; Cancel dotted spec and dotted form.
- (let ((edebug-dotted-spec)
- (this-form (edebug-cursor-expressions cursor))
- (this-offset (edebug-cursor-offsets cursor)))
- ;; Wrap the form in a list, (by changing the cursor??)...
- (edebug-set-cursor cursor (list this-form) this-offset)
- ;; and process normally, then unwrap the result.
- (car (edebug-match-specs cursor specs remainder-handler))))
-
- (t;; Process normally.
- (let* ((spec (car specs))
- (rest)
- (first-char (and (symbolp spec) (aref (symbol-name spec) 0))))
- ;;(message "spec = %s first char = %s" spec first-char) (sit-for 1)
- (nconc
- (cond
- ((eq ?& first-char);; "&" symbols take all following specs.
- (funcall (get-edebug-spec spec) cursor (cdr specs)))
- ((eq ?: first-char);; ":" symbols take one following spec.
- (setq rest (cdr (cdr specs)))
- (funcall (get-edebug-spec spec) cursor (car (cdr specs))))
- (t;; Any other normal spec.
- (setq rest (cdr specs))
- (edebug-match-one-spec cursor spec)))
- (funcall remainder-handler cursor rest remainder-handler)))))))
-
-
-;; Define specs for all the symbol specs with functions used to process them.
-;; Perhaps we shouldn't be doing this with edebug-form-specs since the
-;; user may want to define macros or functions with the same names.
-;; We could use an internal obarray for these primitive specs.
-
-(mapcar
- (function (lambda (pair)
- (put (car pair) 'edebug-form-spec (cdr pair))))
- '((&optional . edebug-match-&optional)
- (&rest . edebug-match-&rest)
- (&or . edebug-match-&or)
- (form . edebug-match-form)
- (sexp . edebug-match-sexp)
- (body . edebug-match-body)
- (&define . edebug-match-&define)
- (name . edebug-match-name)
- (:name . edebug-match-colon-name)
- (arg . edebug-match-arg)
- (def-body . edebug-match-def-body)
- (def-form . edebug-match-def-form)
- ;; Less frequently used:
- ;; (function . edebug-match-function)
- (lambda-expr . edebug-match-lambda-expr)
- (&not . edebug-match-&not)
- (&key . edebug-match-&key)
- (place . edebug-match-place)
- (gate . edebug-match-gate)
- ;; (nil . edebug-match-nil) not this one - special case it.
- ))
-
-(defun edebug-match-symbol (cursor symbol)
- ;; Match a symbol spec.
- (let* ((spec (get-edebug-spec symbol)))
- (cond
- (spec
- (if (consp spec)
- ;; It is an indirect spec.
- (edebug-match cursor spec)
- ;; Otherwise it should be the symbol name of a function.
- ;; There could be a bug here - maybe need to do edebug-match bindings.
- (funcall spec cursor)))
-
- ((null symbol) ;; special case this.
- (edebug-match-nil cursor))
-
- ((fboundp symbol) ; is it a predicate?
- (let ((sexp (edebug-top-element-required cursor "Expected" symbol)))
- ;; Special case for edebug-`.
- (if (and (listp sexp) (eq (car sexp) ',))
- (edebug-match cursor '(("," def-form)))
- (if (not (funcall symbol sexp))
- (edebug-no-match cursor symbol "failed"))
- (edebug-move-cursor cursor)
- (list sexp))))
- (t (error "%s is not a form-spec or function" symbol))
- )))
-
-
-(defun edebug-match-sexp (cursor)
- (list (prog1 (edebug-top-element-required cursor "Expected sexp")
- (edebug-move-cursor cursor))))
-
-(defun edebug-match-form (cursor)
- (list (edebug-form cursor)))
-
-(defalias 'edebug-match-place 'edebug-match-form)
- ;; Currently identical to edebug-match-form.
- ;; This is for common lisp setf-style place arguments.
-
-(defsubst edebug-match-body (cursor) (edebug-forms cursor))
-
-(defun edebug-match-&optional (cursor specs)
- ;; Keep matching until one spec fails.
- (edebug-&optional-wrapper cursor specs 'edebug-&optional-wrapper))
-
-(defun edebug-&optional-wrapper (cursor specs remainder-handler)
- (let (result
- (edebug-&optional specs)
- (edebug-gate nil)
- (this-form (edebug-cursor-expressions cursor))
- (this-offset (edebug-cursor-offsets cursor)))
- (if (null (catch 'no-match
- (setq result
- (edebug-match-specs cursor specs remainder-handler))
- ;; Returning nil means no no-match was thrown.
- nil))
- result
- ;; no-match, but don't fail; just reset cursor and return nil.
- (edebug-set-cursor cursor this-form this-offset)
- nil)))
-
-
-(defun edebug-&rest-wrapper (cursor specs remainder-handler)
- (if (null specs) (setq specs edebug-&rest))
- ;; Reuse the &optional handler with this as the remainder handler.
- (edebug-&optional-wrapper cursor specs remainder-handler))
-
-(defun edebug-match-&rest (cursor specs)
- ;; Repeatedly use specs until failure.
- (let ((edebug-&rest specs) ;; remember these
- edebug-best-error
- edebug-error-point)
- (edebug-&rest-wrapper cursor specs 'edebug-&rest-wrapper)))
-
-
-(defun edebug-match-&or (cursor specs)
- ;; Keep matching until one spec succeeds, and return its results.
- ;; If none match, fail.
- ;; This needs to be optimized since most specs spend time here.
- (let ((original-specs specs)
- (this-form (edebug-cursor-expressions cursor))
- (this-offset (edebug-cursor-offsets cursor)))
- (catch 'matched
- (while specs
- (catch 'no-match
- (throw 'matched
- (let (edebug-gate ;; only while matching each spec
- edebug-best-error
- edebug-error-point)
- ;; Doesn't support e.g. &or symbolp &rest form
- (edebug-match-one-spec cursor (car specs)))))
- ;; Match failed, so reset and try again.
- (setq specs (cdr specs))
- ;; Reset the cursor for the next match.
- (edebug-set-cursor cursor this-form this-offset))
- ;; All failed.
- (apply 'edebug-no-match cursor "Expected one of" original-specs))
- ))
-
-
-(defun edebug-match-&not (cursor specs)
- ;; If any specs match, then fail
- (if (null (catch 'no-match
- (let ((edebug-gate nil))
- (save-excursion
- (edebug-match-&or cursor specs)))
- nil))
- ;; This means something matched, so it is a no match.
- (edebug-no-match cursor "Unexpected"))
- ;; This means nothing matched, so it is OK.
- nil) ;; So, return nothing
-
-
-(def-edebug-spec &key edebug-match-&key)
-
-(defun edebug-match-&key (cursor specs)
- ;; Following specs must look like (<name> <spec>) ...
- ;; where <name> is the name of a keyword, and spec is its spec.
- ;; This really doesn't save much over the expanded form and takes time.
- (edebug-match-&rest
- cursor
- (cons '&or
- (mapcar (function (lambda (pair)
- (vector (format ":%s" (car pair))
- (car (cdr pair)))))
- specs))))
-
-
-(defun edebug-match-gate (cursor)
- ;; Simply set the gate to prevent backtracking at this level.
- (setq edebug-gate t)
- nil)
-
-
-(defun edebug-match-list (cursor specs)
- ;; The spec is a list, but what kind of list, and what context?
- (if edebug-dotted-spec
- ;; After dotted spec but form did not contain dot,
- ;; so match list spec elements as if spliced in.
- (prog1
- (let ((edebug-dotted-spec))
- (edebug-match-specs cursor specs 'edebug-match-specs))
- ;; If it matched, really clear the dotted-spec flag.
- (setq edebug-dotted-spec nil))
- (let ((spec (car specs))
- (form (edebug-top-element-required cursor "Expected" specs)))
- (cond
- ((eq 'quote spec)
- (let ((spec (car (cdr specs))))
- (cond
- ((symbolp spec)
- ;; Special case: spec quotes a symbol to match.
- ;; Change in future. Use "..." instead.
- (if (not (eq spec form))
- (edebug-no-match cursor "Expected" spec))
- (edebug-move-cursor cursor)
- (setq edebug-gate t)
- form)
- (t
- (error "Bad spec: %s" specs)))))
-
- ((listp form)
- (prog1
- (list (edebug-match-sublist
- ;; First offset is for the list form itself.
- ;; Treat nil as empty list.
- (edebug-new-cursor form (cdr (edebug-top-offset cursor)))
- specs))
- (edebug-move-cursor cursor)))
-
- ((and (eq 'vector spec) (vectorp form))
- ;; Special case: match a vector with the specs.
- (let ((result (edebug-match-sublist
- (edebug-new-cursor
- form (cdr (edebug-top-offset cursor)))
- (cdr specs))))
- (edebug-move-cursor cursor)
- (list (apply 'vector result))))
-
- (t (edebug-no-match cursor "Expected" specs)))
- )))
-
-
-(defun edebug-match-sublist (cursor specs)
- ;; Match a sublist of specs.
- (let (edebug-&optional
- ;;edebug-best-error
- ;;edebug-error-point
- )
- (prog1
- ;; match with edebug-match-specs so edebug-best-error is not bound.
- (edebug-match-specs cursor specs 'edebug-match-specs)
- (if (not (edebug-empty-cursor cursor))
- (if edebug-best-error
- (apply 'edebug-no-match cursor edebug-best-error)
- ;; A failed &rest or &optional spec may leave some args.
- (edebug-no-match cursor "Failed matching" specs)
- )))))
-
-
-(defun edebug-match-string (cursor spec)
- (let ((sexp (edebug-top-element-required cursor "Expected" spec)))
- (if (not (eq (intern spec) sexp))
- (edebug-no-match cursor "Expected" spec)
- ;; Since it matched, failure means immediate error, unless &optional.
- (setq edebug-gate t)
- (edebug-move-cursor cursor)
- (list sexp)
- )))
-
-(defun edebug-match-nil (cursor)
- ;; There must be nothing left to match a nil.
- (if (not (edebug-empty-cursor cursor))
- (edebug-no-match cursor "Unmatched argument(s)")
- nil))
-
-
-(defun edebug-match-function (cursor)
- (error "Use function-form instead of function in edebug spec"))
-
-(defun edebug-match-&define (cursor specs)
- ;; Match a defining form.
- ;; Normally, &define is interpreted specially other places.
- ;; This should only be called inside of a spec list to match the remainder
- ;; of the current list. e.g. ("lambda" &define args def-body)
- (edebug-make-form-wrapper
- cursor
- (edebug-before-offset cursor)
- ;; Find the last offset in the list.
- (let ((offsets (edebug-cursor-offsets cursor)))
- (while (consp offsets) (setq offsets (cdr offsets)))
- offsets)
- specs))
-
-(defun edebug-match-lambda-expr (cursor)
- ;; The expression must be a function.
- ;; This will match any list form that begins with a symbol
- ;; that has an edebug-form-spec beginning with &define. In
- ;; practice, only lambda expressions should be used.
- ;; I could add a &lambda specification to avoid confusion.
- (let* ((sexp (edebug-top-element-required
- cursor "Expected lambda expression"))
- (offset (edebug-top-offset cursor))
- (head (and (consp sexp) (car sexp)))
- (spec (and (symbolp head) (get-edebug-spec head)))
- (edebug-inside-func nil))
- ;; Find out if this is a defining form from first symbol.
- (if (and (consp spec) (eq '&define (car spec)))
- (prog1
- (list
- (edebug-defining-form
- (edebug-new-cursor sexp offset)
- (car offset);; before the sexp
- (edebug-after-offset cursor)
- (cons (symbol-name head) (cdr spec))))
- (edebug-move-cursor cursor))
- (edebug-no-match cursor "Expected lambda expression")
- )))
-
-
-(defun edebug-match-name (cursor)
- ;; Set the edebug-def-name bound in edebug-defining-form.
- (let ((name (edebug-top-element-required cursor "Expected name")))
- ;; Maybe strings and numbers could be used.
- (if (not (symbolp name))
- (edebug-no-match cursor "Symbol expected for name of definition"))
- (setq edebug-def-name
- (if edebug-def-name
- ;; Construct a new name by appending to previous name.
- (intern (format "%s@%s" edebug-def-name name))
- name))
- (edebug-move-cursor cursor)
- (list name)))
-
-(defun edebug-match-colon-name (cursor spec)
- ;; Set the edebug-def-name to the spec.
- (setq edebug-def-name
- (if edebug-def-name
- ;; Construct a new name by appending to previous name.
- (intern (format "%s@%s" edebug-def-name spec))
- spec))
- nil)
-
-(defun edebug-match-arg (cursor)
- ;; set the def-args bound in edebug-defining-form
- (let ((edebug-arg (edebug-top-element-required cursor "Expected arg")))
- (if (or (not (symbolp edebug-arg))
- (edebug-lambda-list-keywordp edebug-arg))
- (edebug-no-match cursor "Bad argument:" edebug-arg))
- (edebug-move-cursor cursor)
- (setq edebug-def-args (cons edebug-arg edebug-def-args))
- (list edebug-arg)))
-
-(defun edebug-match-def-form (cursor)
- ;; Like form but the form is wrapped in edebug-enter form.
- ;; The form is assumed to be executing outside of the function context.
- ;; This is a hack for now, since a def-form might execute inside as well.
- ;; Not to be used otherwise.
- (let ((edebug-inside-func nil))
- (list (edebug-make-enter-wrapper (list (edebug-form cursor))))))
-
-(defun edebug-match-def-body (cursor)
- ;; Like body but body is wrapped in edebug-enter form.
- ;; The body is assumed to be executing inside of the function context.
- ;; Not to be used otherwise.
- (let ((edebug-inside-func t))
- (list (edebug-wrap-def-body (edebug-forms cursor)))))
-
-
-;;;; Edebug Form Specs
-;;; ==========================================================
-;;; See cl-specs.el for common lisp specs.
-
-;;;;* Spec for def-edebug-spec
-;;; Out of date.
-
-(defun edebug-spec-p (object)
- "Return non-nil if OBJECT is a symbol with an edebug-form-spec property."
- (and (symbolp object)
- (get object 'edebug-form-spec)))
-
-(def-edebug-spec def-edebug-spec
- ;; Top level is different from lower levels.
- (&define :name edebug-spec name
- &or "nil" edebug-spec-p "t" "0" (&rest edebug-spec)))
-
-(def-edebug-spec edebug-spec-list
- ;; A list must have something in it, or it is nil, a symbolp
- ((edebug-spec . [&or nil edebug-spec])))
-
-(def-edebug-spec edebug-spec
- (&or
- (vector &rest edebug-spec) ; matches a vector
- ("vector" &rest edebug-spec) ; matches a vector spec
- ("quote" symbolp)
- edebug-spec-list
- stringp
- [edebug-lambda-list-keywordp &rest edebug-spec]
- ;; [edebug-keywordp gate edebug-spec] ;; need edebug-keywordp for this.
- edebug-spec-p ;; Including all the special ones e.g. form.
- symbolp;; a predicate
- ))
-
-
-;;;* Emacs special forms and some functions.
-
-;; quote expects only one argument, although it allows any number.
-(def-edebug-spec quote sexp)
-
-;; The standard defining forms.
-(def-edebug-spec defconst defvar)
-(def-edebug-spec defvar (symbolp &optional form stringp))
-
-(def-edebug-spec defun
- (&define name lambda-list
- [&optional stringp]
- [&optional ("interactive" interactive)]
- def-body))
-(def-edebug-spec defmacro
- (&define name lambda-list def-body))
-
-(def-edebug-spec arglist lambda-list) ;; deprecated - use lambda-list.
-
-(def-edebug-spec lambda-list
- (([&rest arg]
- [&optional ["&optional" arg &rest arg]]
- &optional ["&rest" arg]
- )))
-
-(def-edebug-spec interactive
- (&optional &or stringp def-form))
-
-;; A function-form is for an argument that may be a function or a form.
-;; This specially recognizes anonymous functions quoted with quote.
-(def-edebug-spec function-form
- ;; form at the end could also handle "function",
- ;; but recognize it specially to avoid wrapping function forms.
- (&or ([&or "quote" "function"] &or symbolp lambda-expr) form))
-
-;; function expects a symbol or a lambda or macro expression
-;; A macro is allowed by Emacs.
-(def-edebug-spec function (&or symbolp lambda-expr))
-
-;; lambda is a macro in emacs 19.
-(def-edebug-spec lambda (&define lambda-list
- [&optional stringp]
- [&optional ("interactive" interactive)]
- def-body))
-
-;; A macro expression is a lambda expression with "macro" prepended.
-(def-edebug-spec macro (&define "lambda" lambda-list def-body))
-
-;; (def-edebug-spec anonymous-form ((&or ["lambda" lambda] ["macro" macro])))
-
-;; Standard functions that take function-forms arguments.
-(def-edebug-spec mapcar (function-form form))
-(def-edebug-spec mapconcat (function-form form form))
-(def-edebug-spec mapatoms (function-form &optional form))
-(def-edebug-spec apply (function-form &rest form))
-(def-edebug-spec funcall (function-form &rest form))
-
-(def-edebug-spec let
- ((&rest &or (symbolp &optional form) symbolp)
- body))
-
-(def-edebug-spec let* let)
-
-(def-edebug-spec setq (&rest symbolp form))
-(def-edebug-spec setq-default setq)
-
-(def-edebug-spec cond (&rest (&rest form)))
-
-(def-edebug-spec condition-case
- (symbolp
- form
- &rest (symbolp body)))
-
-
-(def-edebug-spec \` (backquote-form))
-
-;; Supports quotes inside backquotes,
-;; but only at the top level inside unquotes.
-(def-edebug-spec backquote-form
- (&or
- ([&or "," ",@"] &or ("quote" backquote-form) form)
- (backquote-form &rest backquote-form)
- ;; If you use dotted forms in backquotes, replace the previous line
- ;; with the following. This takes quite a bit more stack space, however.
- ;; (backquote-form . [&or nil backquote-form])
- (vector &rest backquote-form)
- sexp))
-
-;; Special version of backquote that instruments backquoted forms
-;; destined to be evaluated, usually as the result of a
-;; macroexpansion. Backquoted code can only have unquotes (, and ,@)
-;; in places where list forms are allowed, and predicates. If the
-;; backquote is used in a macro, unquoted code that come from
-;; arguments must be instrumented, if at all, with def-form not def-body.
-
-;; We could assume that all forms (not nested in other forms)
-;; in arguments of macros should be def-forms, whether or not the macros
-;; are defined with edebug-` but this would be expensive.
-
-;; ,@ might have some problems.
-
-(defalias 'edebug-\` '\`) ;; same macro as regular backquote.
-(def-edebug-spec edebug-\` (def-form))
-
-;; Assume immediate quote in unquotes mean backquote at next higher level.
-(def-edebug-spec , (&or ("quote" edebug-`) def-form))
-(def-edebug-spec ,@ (&define ;; so (,@ form) is never wrapped.
- &or ("quote" edebug-`) def-form))
-
-;; New byte compiler.
-(def-edebug-spec defsubst defun)
-(def-edebug-spec dont-compile t)
-(def-edebug-spec eval-when-compile t)
-(def-edebug-spec eval-and-compile t)
-
-(def-edebug-spec save-selected-window t)
-(def-edebug-spec save-current-buffer t)
-(def-edebug-spec save-match-data t)
-(def-edebug-spec with-output-to-string t)
-(def-edebug-spec with-current-buffer t)
-(def-edebug-spec combine-after-change-calls t)
-(def-edebug-spec with-temp-file t)
-(def-edebug-spec with-temp-buffer t)
-
-;; Anything else?
-
-
-;; Some miscellaneous specs for macros in public packages.
-;; Send me yours.
-
-;; advice.el by Hans Chalupsky (hans@cs.buffalo.edu)
-
-(def-edebug-spec ad-dolist ((symbolp form &optional form) body))
-(def-edebug-spec defadvice
- (&define name ;; thing being advised.
- (name ;; class is [&or "before" "around" "after"
- ;; "activation" "deactivation"]
- name ;; name of advice
- &rest sexp ;; optional position and flags
- )
- [&optional stringp]
- [&optional ("interactive" interactive)]
- def-body))
-
-;;; The debugger itself
-
-(defvar edebug-active nil) ;; Non-nil when edebug is active
-
-;;; add minor-mode-alist entry
-(or (assq 'edebug-active minor-mode-alist)
- (setq minor-mode-alist (cons (list 'edebug-active " *Debugging*")
- minor-mode-alist)))
-
-(defvar edebug-stack nil)
-;; Stack of active functions evaluated via edebug.
-;; Should be nil at the top level.
-
-(defvar edebug-stack-depth -1)
-;; Index of last edebug-stack item.
-
-(defvar edebug-offset-indices nil)
-;; Stack of offset indices of visited edebug sexps.
-;; Should be nil at the top level.
-;; Each function adds one cons. Top is modified with setcar.
-
-
-(defvar edebug-entered nil
- ;; Non-nil if edebug has already been entered at this recursive edit level.
- ;; This should stay nil at the top level.
- )
-
-;; Should these be options?
-(defconst edebug-debugger 'edebug
- ;; Name of function to use for debugging when error or quit occurs.
- ;; Set this to 'debug if you want to debug edebug.
- )
-
-
-;; Dynamically bound variables, declared globally but left unbound.
-(defvar edebug-function) ; the function being executed. change name!!
-(defvar edebug-args) ; the arguments of the function
-(defvar edebug-data) ; the edebug data for the function
-(defvar edebug-value) ; the result of the expression
-(defvar edebug-after-index)
-(defvar edebug-def-mark) ; the mark for the definition
-(defvar edebug-freq-count) ; the count of expression visits.
-(defvar edebug-coverage) ; the coverage results of each expression of function.
-
-(defvar edebug-buffer) ; which buffer the function is in.
-(defvar edebug-result) ; the result of the function call returned by body
-(defvar edebug-outside-executing-macro)
-(defvar edebug-outside-defining-kbd-macro)
-
-(defvar edebug-execution-mode 'step) ; Current edebug mode set by user.
-(defvar edebug-next-execution-mode nil) ; Use once instead of initial mode.
-
-(defvar edebug-outside-debug-on-error) ; the value of debug-on-error outside
-(defvar edebug-outside-debug-on-quit) ; the value of debug-on-quit outside
-
-(defvar edebug-outside-pre-command-hook)
-(defvar edebug-outside-post-command-hook)
-
-(defvar cl-lexical-debug) ;; Defined in cl.el
-
-;;; Handling signals
-
-(defun edebug-signal (edebug-signal-name edebug-signal-data)
- "Signal an error. Args are SIGNAL-NAME, and associated DATA.
-A signal name is a symbol with an `error-conditions' property
-that is a list of condition names.
-A handler for any of those names will get to handle this signal.
-The symbol `error' should always be one of them.
-
-DATA should be a list. Its elements are printed as part of the error message.
-If the signal is handled, DATA is made available to the handler.
-See `condition-case'.
-
-This is the Edebug replacement for the standard `signal'. It should
-only be active while Edebug is. It checks `debug-on-error' to see
-whether it should call the debugger. When execution is resumed, the
-error is signaled again."
- (if (and (listp debug-on-error) (memq edebug-signal-name debug-on-error))
- (edebug 'error (cons edebug-signal-name edebug-signal-data)))
- ;; If we reach here without another non-local exit, then send signal again.
- ;; i.e. the signal is not continuable, yet.
- (signal edebug-signal-name edebug-signal-data))
-
-;;; Entering Edebug
-
-(defun edebug-enter (edebug-function edebug-args edebug-body)
- ;; Entering FUNC. The arguments are ARGS, and the body is BODY.
- ;; Setup edebug variables and evaluate BODY. This function is called
- ;; when a function evaluated with edebug-eval-top-level-form is entered.
- ;; Return the result of BODY.
-
- ;; Is this the first time we are entering edebug since
- ;; lower-level recursive-edit command?
- ;; More precisely, this tests whether Edebug is currently active.
- (if (not edebug-entered)
- (let ((edebug-entered t)
- ;; Binding max-lisp-eval-depth here is OK,
- ;; but not inside an unwind-protect.
- ;; Doing it here also keeps it from growing too large.
- (max-lisp-eval-depth (+ 100 max-lisp-eval-depth)) ; too much??
- (max-specpdl-size (+ 200 max-specpdl-size))
-
- (debugger edebug-debugger) ; only while edebug is active.
- (edebug-outside-debug-on-error debug-on-error)
- (edebug-outside-debug-on-quit debug-on-quit)
- ;; Binding these may not be the right thing to do.
- ;; We want to allow the global values to be changed.
- (debug-on-error (or debug-on-error edebug-on-error))
- (debug-on-quit edebug-on-quit)
-
- ;; Lexical bindings must be uncompiled for this to work.
- (cl-lexical-debug t)
-
- ;; Save the outside value of executing macro. (here??)
- (edebug-outside-executing-macro executing-kbd-macro)
- (edebug-outside-pre-command-hook pre-command-hook)
- (edebug-outside-post-command-hook post-command-hook))
- (unwind-protect
- (let (;; Don't keep reading from an executing kbd macro
- ;; within edebug unless edebug-continue-kbd-macro is
- ;; non-nil. Again, local binding may not be best.
- (executing-kbd-macro
- (if edebug-continue-kbd-macro executing-kbd-macro))
-
- (signal-hook-function 'edebug-signal)
-
- ;; Disable command hooks. This is essential when
- ;; a hook function is instrumented - to avoid infinite loop.
- ;; This may be more than we need, however.
- (pre-command-hook nil)
- (post-command-hook nil))
- (setq edebug-execution-mode (or edebug-next-execution-mode
- edebug-initial-mode
- edebug-execution-mode)
- edebug-next-execution-mode nil)
- (edebug-enter edebug-function edebug-args edebug-body))
- ;; Reset global variables in case outside value was changed.
- (setq executing-kbd-macro edebug-outside-executing-macro
- pre-command-hook edebug-outside-pre-command-hook
- post-command-hook edebug-outside-post-command-hook
- )))
-
- (let* ((edebug-data (get edebug-function 'edebug))
- (edebug-def-mark (car edebug-data)) ; mark at def start
- (edebug-freq-count (get edebug-function 'edebug-freq-count))
- (edebug-coverage (get edebug-function 'edebug-coverage))
- (edebug-buffer (marker-buffer edebug-def-mark))
-
- (edebug-stack (cons edebug-function edebug-stack))
- (edebug-offset-indices (cons 0 edebug-offset-indices))
- )
- (if (get edebug-function 'edebug-on-entry)
- (progn
- (setq edebug-execution-mode 'step)
- (if (eq (get edebug-function 'edebug-on-entry) 'temp)
- (put edebug-function 'edebug-on-entry nil))))
- (if edebug-trace
- (edebug-enter-trace edebug-body)
- (funcall edebug-body))
- )))
-
-
-(defun edebug-enter-trace (edebug-body)
- (let ((edebug-stack-depth (1+ edebug-stack-depth))
- edebug-result)
- (edebug-print-trace-before
- (format "%s args: %s" edebug-function edebug-args))
- (prog1 (setq edebug-result (funcall edebug-body))
- (edebug-print-trace-after
- (format "%s result: %s" edebug-function edebug-result)))))
-
-(def-edebug-spec edebug-tracing (form body))
-
-(defmacro edebug-tracing (msg &rest body)
- "Print MSG in *edebug-trace* before and after evaluating BODY.
-The result of BODY is also printed."
- (` (let ((edebug-stack-depth (1+ edebug-stack-depth))
- edebug-result)
- (edebug-print-trace-before (, msg))
- (prog1 (setq edebug-result (progn (,@ body)))
- (edebug-print-trace-after
- (format "%s result: %s" (, msg) edebug-result))))))
-
-(defun edebug-print-trace-before (msg)
- "Function called to print trace info before expression evaluation.
-MSG is printed after `::::{ '."
- (edebug-trace-display
- edebug-trace-buffer "%s{ %s" (make-string edebug-stack-depth ?\:) msg))
-
-(defun edebug-print-trace-after (msg)
- "Function called to print trace info after expression evaluation.
-MSG is printed after `::::} '."
- (edebug-trace-display
- edebug-trace-buffer "%s} %s" (make-string edebug-stack-depth ?\:) msg))
-
-
-
-(defun edebug-slow-before (edebug-before-index)
- ;; Debug current function given BEFORE position.
- ;; Called from functions compiled with edebug-eval-top-level-form.
- ;; Return the before index.
- (setcar edebug-offset-indices edebug-before-index)
-
- ;; Increment frequency count
- (aset edebug-freq-count edebug-before-index
- (1+ (aref edebug-freq-count edebug-before-index)))
-
- (if (or (not (memq edebug-execution-mode '(Go-nonstop next)))
- (edebug-input-pending-p))
- (edebug-debugger edebug-before-index 'before nil))
- edebug-before-index)
-
-(defun edebug-fast-before (edebug-before-index)
- ;; Do nothing.
- )
-
-(defun edebug-slow-after (edebug-before-index edebug-after-index edebug-value)
- ;; Debug current function given AFTER position and VALUE.
- ;; Called from functions compiled with edebug-eval-top-level-form.
- ;; Return VALUE.
- (setcar edebug-offset-indices edebug-after-index)
-
- ;; Increment frequency count
- (aset edebug-freq-count edebug-after-index
- (1+ (aref edebug-freq-count edebug-after-index)))
- (if edebug-test-coverage (edebug-update-coverage))
-
- (if (and (eq edebug-execution-mode 'Go-nonstop)
- (not (edebug-input-pending-p)))
- ;; Just return result.
- edebug-value
- (edebug-debugger edebug-after-index 'after edebug-value)
- ))
-
-(defun edebug-fast-after (edebug-before-index edebug-after-index edebug-value)
- ;; Do nothing but return the value.
- edebug-value)
-
-(defun edebug-run-slow ()
- (defalias 'edebug-before 'edebug-slow-before)
- (defalias 'edebug-after 'edebug-slow-after))
-
-;; This is not used, yet.
-(defun edebug-run-fast ()
- (defalias 'edebug-before 'edebug-fast-before)
- (defalias 'edebug-after 'edebug-fast-after))
-
-(edebug-run-slow)
-
-
-(defun edebug-update-coverage ()
- (let ((old-result (aref edebug-coverage edebug-after-index)))
- (cond
- ((eq 'ok-coverage old-result))
- ((eq 'unknown old-result)
- (aset edebug-coverage edebug-after-index edebug-value))
- ;; Test if a different result.
- ((not (eq edebug-value old-result))
- (aset edebug-coverage edebug-after-index 'ok-coverage)))))
-
-
-;; Dynamically declared unbound variables.
-(defvar edebug-arg-mode) ; the mode, either before, after, or error
-(defvar edebug-breakpoints)
-(defvar edebug-break-data) ; break data for current function.
-(defvar edebug-break) ; whether a break occurred.
-(defvar edebug-global-break) ; whether a global break occurred.
-(defvar edebug-break-condition) ; whether the breakpoint is conditional.
-
-(defvar edebug-break-result nil)
-(defvar edebug-global-break-result nil)
-
-
-(defun edebug-debugger (edebug-offset-index edebug-arg-mode edebug-value)
- ;; Check breakpoints and pending input.
- ;; If edebug display should be updated, call edebug-display.
- ;; Return edebug-value.
- (let* (;; This needs to be here since breakpoints may be changed.
- (edebug-breakpoints (car (cdr edebug-data))) ; list of breakpoints
- (edebug-break-data (assq edebug-offset-index edebug-breakpoints))
- (edebug-break-condition (car (cdr edebug-break-data)))
- (edebug-global-break
- (if edebug-global-break-condition
- (condition-case nil
- (setq edebug-global-break-result
- (eval edebug-global-break-condition))
- (error nil))))
- (edebug-break))
-
-;;; (edebug-trace "exp: %s" edebug-value)
- ;; Test whether we should break.
- (setq edebug-break
- (or edebug-global-break
- (and edebug-break-data
- (or (not edebug-break-condition)
- (setq edebug-break-result
- (eval edebug-break-condition))))))
- (if (and edebug-break
- (nth 2 edebug-break-data)) ; is it temporary?
- ;; Delete the breakpoint.
- (setcdr edebug-data
- (cons (delq edebug-break-data edebug-breakpoints)
- (cdr (cdr edebug-data)))))
-
- ;; Display if mode is not go, continue, or Continue-fast
- ;; or break, or input is pending,
- (if (or (not (memq edebug-execution-mode '(go continue Continue-fast)))
- edebug-break
- (edebug-input-pending-p))
- (edebug-display)) ; <--------------- display
-
- edebug-value
- ))
-
-
-;; window-start now stored with each function.
-;;(defvar edebug-window-start nil)
-;; Remember where each buffers' window starts between edebug calls.
-;; This is to avoid spurious recentering.
-;; Does this still need to be buffer-local??
-;;(setq-default edebug-window-start nil)
-;;(make-variable-buffer-local 'edebug-window-start)
-
-
-;; Dynamically declared unbound vars
-(defvar edebug-point) ; the point in edebug buffer
-(defvar edebug-outside-buffer) ; the current-buffer outside of edebug
-(defvar edebug-outside-point) ; the point outside of edebug
-(defvar edebug-outside-mark) ; the mark outside of edebug
-(defvar edebug-window-data) ; window and window-start for current function
-(defvar edebug-outside-windows) ; outside window configuration
-(defvar edebug-eval-buffer) ; for the evaluation list.
-(defvar edebug-outside-o-a-p) ; outside overlay-arrow-position
-(defvar edebug-outside-o-a-s) ; outside overlay-arrow-string
-(defvar edebug-outside-c-i-e-a) ; outside cursor-in-echo-area
-
-(defvar edebug-eval-list nil) ;; List of expressions to evaluate.
-
-(defvar edebug-previous-result nil) ;; Last result returned.
-
-;; Emacs 19 adds an arg to mark and mark-marker.
-(defalias 'edebug-mark 'mark)
-(defalias 'edebug-mark-marker 'mark-marker)
-
-
-(defun edebug-display ()
- ;; Setup windows for edebug, determine mode, maybe enter recursive-edit.
- ;; Uses local variables of edebug-enter, edebug-before, edebug-after
- ;; and edebug-debugger.
- (let ((edebug-active t) ; for minor mode alist
- edebug-stop ; should we enter recursive-edit
- (edebug-point (+ edebug-def-mark
- (aref (nth 2 edebug-data) edebug-offset-index)))
- edebug-buffer-outside-point ; current point in edebug-buffer
- ;; window displaying edebug-buffer
- (edebug-window-data (nth 3 edebug-data))
- (edebug-outside-window (selected-window))
- (edebug-outside-buffer (current-buffer))
- (edebug-outside-point (point))
- (edebug-outside-mark (edebug-mark))
- edebug-outside-windows ; window or screen configuration
- edebug-buffer-points
-
- edebug-eval-buffer ; declared here so we can kill it below
- (edebug-eval-result-list (and edebug-eval-list
- (edebug-eval-result-list)))
- edebug-trace-window
- edebug-trace-window-start
-
- (edebug-outside-o-a-p overlay-arrow-position)
- (edebug-outside-o-a-s overlay-arrow-string)
- (edebug-outside-c-i-e-a cursor-in-echo-area))
- (unwind-protect
- (let ((overlay-arrow-position overlay-arrow-position)
- (overlay-arrow-string overlay-arrow-string)
- (cursor-in-echo-area nil)
- ;; any others??
- )
- (if (not (buffer-name edebug-buffer))
- (let ((debug-on-error nil))
- (error "Buffer defining %s not found" edebug-function)))
-
- (if (eq 'after edebug-arg-mode)
- ;; Compute result string now before windows are modified.
- (edebug-compute-previous-result edebug-value))
-
- (if edebug-save-windows
- ;; Save windows now before we modify them.
- (setq edebug-outside-windows
- (edebug-current-windows edebug-save-windows)))
-
- (if edebug-save-displayed-buffer-points
- (setq edebug-buffer-points (edebug-get-displayed-buffer-points)))
-
- ;; First move the edebug buffer point to edebug-point
- ;; so that window start doesn't get changed when we display it.
- ;; I don't know if this is going to help.
- ;;(set-buffer edebug-buffer)
- ;;(goto-char edebug-point)
-
- ;; If edebug-buffer is not currently displayed,
- ;; first find a window for it.
- (edebug-pop-to-buffer edebug-buffer (car edebug-window-data))
- (setcar edebug-window-data (selected-window))
-
- ;; Now display eval list, if any.
- ;; This is done after the pop to edebug-buffer
- ;; so that buffer-window correspondence is correct after quitting.
- (edebug-eval-display edebug-eval-result-list)
- ;; The evaluation list better not have deleted edebug-window-data.
- (select-window (car edebug-window-data))
- (set-buffer edebug-buffer)
-
- (setq edebug-buffer-outside-point (point))
- (goto-char edebug-point)
-
- (if (eq 'before edebug-arg-mode)
- ;; Check whether positions are up-to-date.
- ;; This assumes point is never before symbol.
- (if (not (memq (following-char) '(?\( ?\# ?\` )))
- (let ((debug-on-error nil))
- (error "Source has changed - reevaluate definition of %s"
- edebug-function)
- )))
-
- (setcdr edebug-window-data
- (edebug-adjust-window (cdr edebug-window-data)))
-
- ;; Test if there is input, not including keyboard macros.
- (if (edebug-input-pending-p)
- (progn
- (setq edebug-execution-mode 'step
- edebug-stop t)
- (edebug-stop)
- ;; (discard-input) ; is this unfriendly??
- ))
- ;; Now display arrow based on mode.
- (edebug-overlay-arrow)
-
- (cond
- ((eq 'error edebug-arg-mode)
- ;; Display error message
- (setq edebug-execution-mode 'step)
- (edebug-overlay-arrow)
- (beep)
- (if (eq 'quit (car edebug-value))
- (message "Quit")
- (edebug-report-error edebug-value)))
- (edebug-break
- (cond
- (edebug-global-break
- (message "Global Break: %s => %s"
- edebug-global-break-condition
- edebug-global-break-result))
- (edebug-break-condition
- (message "Break: %s => %s"
- edebug-break-condition
- edebug-break-result))
- ((not (eq edebug-execution-mode 'Continue-fast))
- (message "Break"))
- (t)))
-
- (t (message "")))
-
- (if (eq 'after edebug-arg-mode)
- (progn
- ;; Display result of previous evaluation.
- (if (and edebug-break
- (not (eq edebug-execution-mode 'Continue-fast)))
- (sit-for 1)) ; Show break message.
- (edebug-previous-result)))
-
- (cond
- (edebug-break
- (cond
- ((eq edebug-execution-mode 'continue) (edebug-sit-for 1))
- ((eq edebug-execution-mode 'Continue-fast) (edebug-sit-for 0))
- (t (setq edebug-stop t))))
- ;; not edebug-break
- ((eq edebug-execution-mode 'trace)
- (edebug-sit-for 1)) ; Force update and pause.
- ((eq edebug-execution-mode 'Trace-fast)
- (edebug-sit-for 0)) ; Force update and continue.
- )
-
- (unwind-protect
- (if (or edebug-stop
- (memq edebug-execution-mode '(step next))
- (eq edebug-arg-mode 'error))
- (progn
- ;; (setq edebug-execution-mode 'step)
- ;; (edebug-overlay-arrow) ; This doesn't always show up.
- (edebug-recursive-edit))) ; <---------- Recursive edit
-
- ;; Reset the edebug-window-data to whatever it is now.
- (let ((window (if (eq (window-buffer) edebug-buffer)
- (selected-window)
- (edebug-get-buffer-window edebug-buffer))))
- ;; Remember window-start for edebug-buffer, if still displayed.
- (if window
- (progn
- (setcar edebug-window-data window)
- (setcdr edebug-window-data (window-start window)))))
-
- ;; Save trace window point before restoring outside windows.
- ;; Could generalize this for other buffers.
- (setq edebug-trace-window (get-buffer-window edebug-trace-buffer))
- (if edebug-trace-window
- (setq edebug-trace-window-start
- (and edebug-trace-window
- (window-start edebug-trace-window))))
-
- ;; Restore windows before continuing.
- (if edebug-save-windows
- (progn
- (edebug-set-windows edebug-outside-windows)
-
- ;; Restore displayed buffer points.
- ;; Needed even if restoring windows because
- ;; window-points are not restored. (should they be??)
- (if edebug-save-displayed-buffer-points
- (edebug-set-buffer-points edebug-buffer-points))
-
- ;; Unrestore trace window's window-point.
- (if edebug-trace-window
- (set-window-start edebug-trace-window
- edebug-trace-window-start))
-
- ;; Unrestore edebug-buffer's window-start, if displayed.
- (let ((window (car edebug-window-data)))
- (if (and window (edebug-window-live-p window)
- (eq (window-buffer) edebug-buffer))
- (progn
- (set-window-start window (cdr edebug-window-data)
- 'no-force)
- ;; Unrestore edebug-buffer's window-point.
- ;; Needed in addition to setting the buffer point
- ;; - otherwise quitting doesn't leave point as is.
- ;; But this causes point to not be restored at times.
- ;; Also, it may not be a visible window.
- ;; (set-window-point window edebug-point)
- )))
-
- ;; Unrestore edebug-buffer's point. Rerestored below.
- ;; (goto-char edebug-point) ;; in edebug-buffer
- )
- ;; Since we may be in a save-excursion, in case of quit,
- ;; reselect the outside window only.
- ;; Only needed if we are not recovering windows??
- (if (edebug-window-live-p edebug-outside-window)
- (select-window edebug-outside-window))
- ) ; if edebug-save-windows
-
- ;; Restore current buffer always, in case application needs it.
- (set-buffer edebug-outside-buffer)
- ;; Restore point, and mark.
- ;; Needed even if restoring windows because
- ;; that doesn't restore point and mark in the current buffer.
- ;; But don't restore point if edebug-buffer is current buffer.
- (if (not (eq edebug-buffer edebug-outside-buffer))
- (goto-char edebug-outside-point))
- (if (marker-buffer (edebug-mark-marker))
- ;; Does zmacs-regions need to be nil while doing set-marker?
- (set-marker (edebug-mark-marker) edebug-outside-mark))
- ) ; unwind-protect
- ;; None of the following is done if quit or signal occurs.
-
- ;; Restore edebug-buffer's outside point.
- ;; (edebug-trace "restore edebug-buffer point: %s"
- ;; edebug-buffer-outside-point)
- (let ((current-buffer (current-buffer)))
- (set-buffer edebug-buffer)
- (goto-char edebug-buffer-outside-point)
- (set-buffer current-buffer))
- ;; ... nothing more.
- )
- ;; Reset global variables to outside values in case they were changed.
- (setq
- overlay-arrow-position edebug-outside-o-a-p
- overlay-arrow-string edebug-outside-o-a-s
- cursor-in-echo-area edebug-outside-c-i-e-a)
- )))
-
-
-(defvar edebug-number-of-recursions 0)
-;; Number of recursive edits started by edebug.
-;; Should be 0 at the top level.
-
-(defvar edebug-recursion-depth 0)
-;; Value of recursion-depth when edebug was called.
-
-;; Dynamically declared unbound vars
-(defvar edebug-outside-match-data) ; match data outside of edebug
-(defvar edebug-backtrace-buffer) ; each recursive edit gets its own
-(defvar edebug-inside-windows)
-(defvar edebug-interactive-p)
-
-(defvar edebug-outside-map)
-(defvar edebug-outside-standard-output)
-(defvar edebug-outside-standard-input)
-(defvar edebug-outside-last-command-char)
-(defvar edebug-outside-last-command)
-(defvar edebug-outside-this-command)
-(defvar edebug-outside-last-input-char)
-
-;; Note: here we have defvars for variables that are
-;; built-in in certain versions.
-;; Each defvar makes a difference
-;; in versions where the variable is *not* built-in.
-
-;; Emacs 18
-(defvar edebug-outside-unread-command-char)
-
-;; Lucid Emacs
-(defvar edebug-outside-unread-command-event) ;; like unread-command-events
-(defvar unread-command-event nil)
-
-;; Emacs 19.
-(defvar edebug-outside-last-command-event)
-(defvar edebug-outside-unread-command-events)
-(defvar edebug-outside-last-input-event)
-(defvar edebug-outside-last-event-frame)
-(defvar edebug-outside-last-nonmenu-event)
-(defvar edebug-outside-track-mouse)
-
-;; Disable byte compiler warnings about unread-command-char and -event
-;; (maybe works with byte-compile-version 2.22 at least)
-(defvar edebug-unread-command-char-warning)
-(defvar edebug-unread-command-event-warning)
-(eval-when-compile
- (setq edebug-unread-command-char-warning
- (get 'unread-command-char 'byte-obsolete-variable))
- (put 'unread-command-char 'byte-obsolete-variable nil)
- (setq edebug-unread-command-event-warning
- (get 'unread-command-event 'byte-obsolete-variable))
- (put 'unread-command-event 'byte-obsolete-variable nil))
-
-(defun edebug-recursive-edit ()
- ;; Start up a recursive edit inside of edebug.
- ;; The current buffer is the edebug-buffer, which is put into edebug-mode.
- ;; Assume that none of the variables below are buffer-local.
- (let ((edebug-buffer-read-only buffer-read-only)
- ;; match-data must be done in the outside buffer
- (edebug-outside-match-data
- (save-excursion ; might be unnecessary now??
- (set-buffer edebug-outside-buffer) ; in case match buffer different
- (match-data)))
-
- ;;(edebug-number-of-recursions (1+ edebug-number-of-recursions))
- (edebug-recursion-depth (recursion-depth))
- edebug-entered ; bind locally to nil
- (edebug-interactive-p nil) ; again non-interactive
- edebug-backtrace-buffer ; each recursive edit gets its own
- ;; The window configuration may be saved and restored
- ;; during a recursive-edit
- edebug-inside-windows
-
- (edebug-outside-map (current-local-map))
-
- (edebug-outside-standard-output standard-output)
- (edebug-outside-standard-input standard-input)
- (edebug-outside-defining-kbd-macro defining-kbd-macro)
-
- (edebug-outside-last-command-char last-command-char)
- (edebug-outside-last-command last-command)
- (edebug-outside-this-command this-command)
- (edebug-outside-last-input-char last-input-char)
-
- (edebug-outside-unread-command-char unread-command-char)
-
- (edebug-outside-last-input-event last-input-event)
- (edebug-outside-last-command-event last-command-event)
- (edebug-outside-unread-command-event unread-command-event)
- (edebug-outside-unread-command-events unread-command-events)
- (edebug-outside-last-event-frame last-event-frame)
- (edebug-outside-last-nonmenu-event last-nonmenu-event)
- (edebug-outside-track-mouse track-mouse)
- )
-
- (unwind-protect
- (let (
- ;; Declare global values local but using the same global value.
- ;; We could set these to the values for previous edebug call.
- (last-command-char last-command-char)
- (last-command last-command)
- (this-command this-command)
- (last-input-char last-input-char)
-
- ;; Assume no edebug command sets unread-command-char.
- (unread-command-char -1)
-
- ;; More for Emacs 19
- (last-input-event nil)
- (last-command-event nil)
- (unread-command-event nil);; lemacs
- (unread-command-events nil)
- (last-event-frame nil)
- (last-nonmenu-event nil)
- (track-mouse nil)
-
- ;; Bind again to outside values.
- (debug-on-error edebug-outside-debug-on-error)
- (debug-on-quit edebug-outside-debug-on-quit)
-
- ;; Don't keep defining a kbd macro.
- (defining-kbd-macro
- (if edebug-continue-kbd-macro defining-kbd-macro))
-
- ;; others??
- )
-
- (if (fboundp 'zmacs-deactivate-region);; for lemacs
- (zmacs-deactivate-region))
- (if (and (eq edebug-execution-mode 'go)
- (not (memq edebug-arg-mode '(after error))))
- (message "Break"))
-
- (setq buffer-read-only t)
- (setq signal-hook-function nil)
-
- (edebug-mode)
- (unwind-protect
- (recursive-edit) ; <<<<<<<<<< Recursive edit
-
- ;; Do the following, even if quit occurs.
- (setq signal-hook-function 'edebug-signal)
- (if edebug-backtrace-buffer
- (kill-buffer edebug-backtrace-buffer))
- ;; Could be an option to keep eval display up.
- (if edebug-eval-buffer (kill-buffer edebug-eval-buffer))
-
- ;; Remember selected-window after recursive-edit.
- ;; (setq edebug-inside-window (selected-window))
-
- (store-match-data edebug-outside-match-data)
-
- ;; Recursive edit may have changed buffers,
- ;; so set it back before exiting let.
- (if (buffer-name edebug-buffer) ; if it still exists
- (progn
- (set-buffer edebug-buffer)
- (if (memq edebug-execution-mode '(go Go-nonstop))
- (edebug-overlay-arrow))
- (setq buffer-read-only edebug-buffer-read-only)
- (use-local-map edebug-outside-map)
- )
- ;; gotta have a buffer to let its buffer local variables be set
- (get-buffer-create " bogus edebug buffer"))
- ));; inner let
-
- ;; Reset global vars to outside values, in case they have been changed.
- (setq
- last-command-char edebug-outside-last-command-char
- last-command-event edebug-outside-last-command-event
- last-command edebug-outside-last-command
- this-command edebug-outside-this-command
- unread-command-char edebug-outside-unread-command-char
- unread-command-event edebug-outside-unread-command-event
- unread-command-events edebug-outside-unread-command-events
- last-input-char edebug-outside-last-input-char
- last-input-event edebug-outside-last-input-event
- last-event-frame edebug-outside-last-event-frame
- last-nonmenu-event edebug-outside-last-nonmenu-event
- track-mouse edebug-outside-track-mouse
-
- standard-output edebug-outside-standard-output
- standard-input edebug-outside-standard-input
- defining-kbd-macro edebug-outside-defining-kbd-macro
- ))
- ))
-
-
-;;; Display related functions
-
-(defun edebug-adjust-window (old-start)
- ;; If pos is not visible, adjust current window to fit following context.
-;;; (message "window: %s old-start: %s window-start: %s pos: %s"
-;;; (selected-window) old-start (window-start) (point)) (sit-for 5)
- (if (not (pos-visible-in-window-p))
- (progn
- ;; First try old-start
- (if old-start
- (set-window-start (selected-window) old-start))
- (if (not (pos-visible-in-window-p))
- (progn
-;; (message "resetting window start") (sit-for 2)
- (set-window-start
- (selected-window)
- (save-excursion
- (forward-line
- (if (< (point) (window-start)) -1 ; one line before if in back
- (- (/ (window-height) 2)) ; center the line moving forward
- ))
- (beginning-of-line)
- (point)))))))
- (window-start))
-
-
-
-(defconst edebug-arrow-alist
- '((Continue-fast . "=")
- (Trace-fast . "-")
- (continue . ">")
- (trace . "->")
- (step . "=>")
- (next . "=>")
- (go . "<>")
- (Go-nonstop . "..") ; not used
- )
- "Association list of arrows for each edebug mode.")
-
-(defun edebug-overlay-arrow ()
- ;; Set up the overlay arrow at beginning-of-line in current buffer.
- ;; The arrow string is derived from edebug-arrow-alist and
- ;; edebug-execution-mode.
- (let ((pos (save-excursion (beginning-of-line) (point))))
- (setq overlay-arrow-string
- (cdr (assq edebug-execution-mode edebug-arrow-alist)))
- (setq overlay-arrow-position (make-marker))
- (set-marker overlay-arrow-position pos (current-buffer))))
-
-
-(defun edebug-toggle-save-all-windows ()
- "Toggle the saving and restoring of all windows.
-Also, each time you toggle it on, the inside and outside window
-configurations become the same as the current configuration."
- (interactive)
- (setq edebug-save-windows (not edebug-save-windows))
- (if edebug-save-windows
- (setq edebug-inside-windows
- (setq edebug-outside-windows
- (edebug-current-windows
- edebug-save-windows))))
- (message "Window saving is %s for all windows."
- (if edebug-save-windows "on" "off")))
-
-(defmacro edebug-changing-windows (&rest body)
- (` (let ((window (selected-window)))
- (setq edebug-inside-windows (edebug-current-windows t))
- (edebug-set-windows edebug-outside-windows)
- (,@ body) ;; Code to change edebug-save-windows
- (setq edebug-outside-windows (edebug-current-windows
- edebug-save-windows))
- ;; Problem: what about outside windows that are deleted inside?
- (edebug-set-windows edebug-inside-windows))))
-
-(defun edebug-toggle-save-selected-window ()
- "Toggle the saving and restoring of the selected window.
-Also, each time you toggle it on, the inside and outside window
-configurations become the same as the current configuration."
- (interactive)
- (cond
- ((eq t edebug-save-windows)
- ;; Save all outside windows except the selected one.
- ;; Remove (selected-window) from outside-windows.
- (edebug-changing-windows
- (setq edebug-save-windows (delq window (edebug-window-list)))))
-
- ((memq (selected-window) edebug-save-windows)
- (setq edebug-outside-windows
- (delq (assq (selected-window) edebug-outside-windows)
- edebug-outside-windows))
- (setq edebug-save-windows
- (delq (selected-window) edebug-save-windows)))
- (t ; Save a new window.
- (edebug-changing-windows
- (setq edebug-save-windows (cons window edebug-save-windows)))))
-
- (message "Window saving is %s for %s."
- (if (memq (selected-window) edebug-save-windows)
- "on" "off")
- (selected-window)))
-
-(defun edebug-toggle-save-windows (arg)
- "Toggle the saving and restoring of windows.
-With prefix, toggle for just the selected window.
-Otherwise, toggle for all windows."
- (interactive "P")
- (if arg
- (edebug-toggle-save-selected-window)
- (edebug-toggle-save-all-windows)))
-
-
-(defun edebug-where ()
- "Show the debug windows and where we stopped in the program."
- (interactive)
- (if (not edebug-active)
- (error "Edebug is not active"))
- ;; Restore the window configuration to what it last was inside.
- ;; But it is not always set. - experiment
- ;;(if edebug-inside-windows
- ;; (edebug-set-windows edebug-inside-windows))
- (edebug-pop-to-buffer edebug-buffer)
- (goto-char edebug-point))
-
-(defun edebug-view-outside ()
- "Change to the outside window configuration."
- (interactive)
- (if (not edebug-active)
- (error "Edebug is not active"))
- (setq edebug-inside-windows
- (edebug-current-windows edebug-save-windows))
- (edebug-set-windows edebug-outside-windows)
- (goto-char edebug-outside-point)
- (message "Window configuration outside of Edebug. Return with %s"
- (substitute-command-keys "\\<global-map>\\[edebug-where]")))
-
-
-(defun edebug-bounce-point (arg)
- "Bounce the point in the outside current buffer.
-If prefix arg is supplied, sit for that many seconds before returning.
-The default is one second."
- (interactive "p")
- (if (not edebug-active)
- (error "Edebug is not active"))
- (save-excursion
- ;; If the buffer's currently displayed, avoid set-window-configuration.
- (save-window-excursion
- (edebug-pop-to-buffer edebug-outside-buffer)
- (goto-char edebug-outside-point)
- (message "Current buffer: %s Point: %s Mark: %s"
- (current-buffer) (point)
- (if (marker-buffer (edebug-mark-marker))
- (marker-position (edebug-mark-marker)) "<not set>"))
- (edebug-sit-for arg)
- (edebug-pop-to-buffer edebug-buffer (car edebug-window-data)))))
-
-
-;; Joe Wells, here is a start at your idea of adding a buffer to the internal
-;; display list. Still need to use this list in edebug-display.
-
-'(defvar edebug-display-buffer-list nil
- "List of buffers that edebug will display when it is active.")
-
-'(defun edebug-display-buffer (buffer)
- "Toggle display of a buffer inside of edebug."
- (interactive "bBuffer: ")
- (let ((already-displaying (memq buffer edebug-display-buffer-list)))
- (setq edebug-display-buffer-list
- (if already-displaying
- (delq buffer edebug-display-buffer-list)
- (cons buffer edebug-display-buffer-list)))
- (message "Displaying %s %s" buffer
- (if already-displaying "off" "on"))))
-
-;;; Breakpoint related functions
-
-(defun edebug-find-stop-point ()
- ;; Return (function . index) of the nearest edebug stop point.
- (let* ((edebug-def-name (edebug-form-data-symbol))
- (edebug-data
- (let ((data (get edebug-def-name 'edebug)))
- (if (or (null data) (markerp data))
- (error "%s is not instrumented for Edebug" edebug-def-name))
- data)) ; we could do it automatically, if data is a marker.
- ;; pull out parts of edebug-data.
- (edebug-def-mark (car edebug-data))
- ;; (edebug-breakpoints (car (cdr edebug-data)))
-
- (offset-vector (nth 2 edebug-data))
- (offset (- (save-excursion
- (if (looking-at "[ \t]")
- ;; skip backwards until non-whitespace, or bol
- (skip-chars-backward " \t"))
- (point))
- edebug-def-mark))
- len i)
- ;; the offsets are in order so we can do a linear search
- (setq len (length offset-vector))
- (setq i 0)
- (while (and (< i len) (> offset (aref offset-vector i)))
- (setq i (1+ i)))
- (if (and (< i len)
- (<= offset (aref offset-vector i)))
- ;; return the relevant info
- (cons edebug-def-name i)
- (message "Point is not on an expression in %s."
- edebug-def-name)
- )))
-
-
-(defun edebug-next-breakpoint ()
- "Move point to the next breakpoint, or first if none past point."
- (interactive)
- (let ((edebug-stop-point (edebug-find-stop-point)))
- (if edebug-stop-point
- (let* ((edebug-def-name (car edebug-stop-point))
- (index (cdr edebug-stop-point))
- (edebug-data (get edebug-def-name 'edebug))
-
- ;; pull out parts of edebug-data
- (edebug-def-mark (car edebug-data))
- (edebug-breakpoints (car (cdr edebug-data)))
- (offset-vector (nth 2 edebug-data))
- breakpoint)
- (if (not edebug-breakpoints)
- (message "No breakpoints in this function.")
- (let ((breaks edebug-breakpoints))
- (while (and breaks
- (<= (car (car breaks)) index))
- (setq breaks (cdr breaks)))
- (setq breakpoint
- (if breaks
- (car breaks)
- ;; goto the first breakpoint
- (car edebug-breakpoints)))
- (goto-char (+ edebug-def-mark
- (aref offset-vector (car breakpoint))))
-
- (message "%s"
- (concat (if (nth 2 breakpoint)
- "Temporary " "")
- (if (car (cdr breakpoint))
- (format "Condition: %s"
- (edebug-safe-prin1-to-string
- (car (cdr breakpoint))))
- "")))
- ))))))
-
-
-(defun edebug-modify-breakpoint (flag &optional condition temporary)
- "Modify the breakpoint for the form at point or after it according
-to FLAG: set if t, clear if nil. Then move to that point.
-If CONDITION or TEMPORARY are non-nil, add those attributes to
-the breakpoint. "
- (let ((edebug-stop-point (edebug-find-stop-point)))
- (if edebug-stop-point
- (let* ((edebug-def-name (car edebug-stop-point))
- (index (cdr edebug-stop-point))
- (edebug-data (get edebug-def-name 'edebug))
-
- ;; pull out parts of edebug-data
- (edebug-def-mark (car edebug-data))
- (edebug-breakpoints (car (cdr edebug-data)))
- (offset-vector (nth 2 edebug-data))
- present)
- ;; delete it either way
- (setq present (assq index edebug-breakpoints))
- (setq edebug-breakpoints (delq present edebug-breakpoints))
- (if flag
- (progn
- ;; add it to the list and resort
- (setq edebug-breakpoints
- (edebug-sort-alist
- (cons
- (list index condition temporary)
- edebug-breakpoints) '<))
- (if condition
- (message "Breakpoint set in %s with condition: %s"
- edebug-def-name condition)
- (message "Breakpoint set in %s" edebug-def-name)))
- (if present
- (message "Breakpoint unset in %s" edebug-def-name)
- (message "No breakpoint here")))
-
- (setcar (cdr edebug-data) edebug-breakpoints)
- (goto-char (+ edebug-def-mark (aref offset-vector index)))
- ))))
-
-(defun edebug-set-breakpoint (arg)
- "Set the breakpoint of nearest sexp.
-With prefix argument, make it a temporary breakpoint."
- (interactive "P")
- (edebug-modify-breakpoint t nil arg))
-
-(defun edebug-unset-breakpoint ()
- "Clear the breakpoint of nearest sexp."
- (interactive)
- (edebug-modify-breakpoint nil))
-
-
-;; For emacs 18, no read-expression-history
-(defun edebug-set-conditional-breakpoint (arg condition)
- "Set a conditional breakpoint at nearest sexp.
-The condition is evaluated in the outside context.
-With prefix argument, make it a temporary breakpoint."
- ;; (interactive "P\nxCondition: ")
- (interactive
- (list
- current-prefix-arg
- ;; Edit previous condition as follows, but it is cumbersome:
- (let ((edebug-stop-point (edebug-find-stop-point)))
- (if edebug-stop-point
- (let* ((edebug-def-name (car edebug-stop-point))
- (index (cdr edebug-stop-point))
- (edebug-data (get edebug-def-name 'edebug))
- (edebug-breakpoints (car (cdr edebug-data)))
- (edebug-break-data (assq index edebug-breakpoints))
- (edebug-break-condition (car (cdr edebug-break-data))))
- (read-minibuffer
- (format "Condition in %s: " edebug-def-name)
- (if edebug-break-condition
- (format "%s" edebug-break-condition)
- (format ""))))))))
- (edebug-modify-breakpoint t condition arg))
-
-
-(defun edebug-set-global-break-condition (expression)
- (interactive (list (read-minibuffer
- "Global Condition: "
- (format "%s" edebug-global-break-condition))))
- (setq edebug-global-break-condition expression))
-
-
-;;; Mode switching functions
-
-(defun edebug-set-mode (mode shortmsg msg)
- ;; Set the edebug mode to MODE.
- ;; Display SHORTMSG, or MSG if not within edebug.
- (if (eq (1+ edebug-recursion-depth) (recursion-depth))
- (progn
- (setq edebug-execution-mode mode)
- (message shortmsg)
- ;; Continue execution
- (exit-recursive-edit))
- ;; This is not terribly useful!!
- (setq edebug-next-execution-mode mode)
- (message msg)))
-
-
-(defalias 'edebug-step-through-mode 'edebug-step-mode)
-
-(defun edebug-step-mode ()
- "Proceed to next stop point."
- (interactive)
- (edebug-set-mode 'step "" "Edebug will stop at next stop point."))
-
-(defun edebug-next-mode ()
- "Proceed to next `after' stop point."
- (interactive)
- (edebug-set-mode 'next "" "Edebug will stop after next eval."))
-
-(defun edebug-go-mode (arg)
- "Go, evaluating until break.
-With prefix ARG, set temporary break at current point and go."
- (interactive "P")
- (if arg
- (edebug-set-breakpoint t))
- (edebug-set-mode 'go "Go..." "Edebug will go until break."))
-
-(defun edebug-Go-nonstop-mode ()
- "Go, evaluating without debugging."
- (interactive)
- (edebug-set-mode 'Go-nonstop "Go-Nonstop..."
- "Edebug will not stop at breaks."))
-
-
-(defun edebug-trace-mode ()
- "Begin trace mode."
- (interactive)
- (edebug-set-mode 'trace "Tracing..." "Edebug will trace with pause."))
-
-(defun edebug-Trace-fast-mode ()
- "Trace with no wait at each step."
- (interactive)
- (edebug-set-mode 'Trace-fast
- "Trace fast..." "Edebug will trace without pause."))
-
-(defun edebug-continue-mode ()
- "Begin continue mode."
- (interactive)
- (edebug-set-mode 'continue "Continue..."
- "Edebug will pause at breakpoints."))
-
-(defun edebug-Continue-fast-mode ()
- "Trace with no wait at each step."
- (interactive)
- (edebug-set-mode 'Continue-fast "Continue fast..."
- "Edebug will stop and go at breakpoints."))
-
-;; ------------------------------------------------------------
-;; The following use the mode changing commands and breakpoints.
-
-
-(defun edebug-goto-here ()
- "Proceed to this stop point."
- (interactive)
- (edebug-go-mode t))
-
-
-(defun edebug-stop ()
- "Stop execution and do not continue.
-Useful for exiting from trace or continue loop."
- (interactive)
- (message "Stop"))
-
-
-'(defun edebug-forward ()
- "Proceed to the exit of the next expression to be evaluated."
- (interactive)
- (edebug-set-mode
- 'forward "Forward"
- "Edebug will stop after exiting the next expression."))
-
-
-(defun edebug-forward-sexp (arg)
- "Proceed from the current point to the end of the ARGth sexp ahead.
-If there are not ARG sexps ahead, then do edebug-step-out."
- (interactive "p")
- (condition-case nil
- (let ((parse-sexp-ignore-comments t))
- ;; Call forward-sexp repeatedly until done or failure.
- (forward-sexp arg)
- (edebug-go-mode t))
- (error
- (edebug-step-out)
- )))
-
-(defun edebug-step-out ()
- "Proceed from the current point to the end of the containing sexp.
-If there is no containing sexp that is not the top level defun,
-go to the end of the last sexp, or if that is the same point, then step."
- (interactive)
- (condition-case nil
- (let ((parse-sexp-ignore-comments t))
- (up-list 1)
- (save-excursion
- ;; Is there still a containing expression?
- (up-list 1))
- (edebug-go-mode t))
- (error
- ;; At top level - 1, so first check if there are more sexps at this level.
- (let ((start-point (point)))
-;; (up-list 1)
- (down-list -1)
- (if (= (point) start-point)
- (edebug-step-mode) ; No more at this level, so step.
- (edebug-go-mode t)
- )))))
-
-(defun edebug-instrument-function (func)
- ;; Func should be a function symbol.
- ;; Return the function symbol, or nil if not instrumented.
- (let ((func-marker))
- (setq func-marker (get func 'edebug))
- (cond
- ((markerp func-marker)
- ;; It is uninstrumented, so instrument it.
- (save-excursion
- (set-buffer (marker-buffer func-marker))
- (goto-char func-marker)
- (edebug-eval-top-level-form)
- func))
- ((consp func-marker)
- (message "%s is already instrumented." func)
- func)
- (t
- ;; We could try harder, e.g. do a tags search.
- (error "Don't know where %s is defined" func)
- nil))))
-
-(defun edebug-instrument-callee ()
- "Instrument the definition of the function or macro about to be called.
-Do this when stopped before the form or it will be too late.
-One side effect of using this command is that the next time the
-function or macro is called, Edebug will be called there as well."
- (interactive)
- (if (not (looking-at "\("))
- (error "You must be before a list form")
- (let ((func
- (save-excursion
- (down-list 1)
- (if (looking-at "\(")
- (edebug-form-data-name
- (edebug-get-form-data-entry (point)))
- (edebug-original-read (current-buffer))))))
- (edebug-instrument-function func))))
-
-
-(defun edebug-step-in ()
- "Step into the definition of the function or macro about to be called.
-This first does `edebug-instrument-callee' to ensure that it is
-instrumented. Then it does `edebug-on-entry' and switches to `go' mode."
- (interactive)
- (let ((func (edebug-instrument-callee)))
- (if func
- (progn
- (edebug-on-entry func 'temp)
- (edebug-go-mode nil)))))
-
-(defun edebug-on-entry (function &optional flag)
- "Cause Edebug to stop when FUNCTION is called.
-With prefix argument, make this temporary so it is automatically
-cancelled the first time the function is entered."
- (interactive "aEdebug on entry to: \nP")
- ;; Could store this in the edebug data instead.
- (put function 'edebug-on-entry (if flag 'temp t)))
-
-(defun cancel-edebug-on-entry (function)
- (interactive "aEdebug on entry to: ")
- (put function 'edebug-on-entry nil))
-
-
-(if (not (fboundp 'edebug-original-debug-on-entry))
- (fset 'edebug-original-debug-on-entry (symbol-function 'debug-on-entry)))
-'(fset 'debug-on-entry 'edebug-debug-on-entry) ;; Should we do this?
-;; Also need edebug-cancel-debug-on-entry
-
-'(defun edebug-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.
-
-This version is from Edebug. If the function is instrumented for
-Edebug, it calls `edebug-on-entry'"
- (interactive "aDebug on entry (to function): ")
- (let ((func-data (get function 'edebug)))
- (if (or (null func-data) (markerp func-data))
- (edebug-original-debug-on-entry function)
- (edebug-on-entry function))))
-
-
-(defun edebug-top-level-nonstop ()
- "Set mode to Go-nonstop, and exit to top-level.
-This is useful for exiting even if unwind-protect code may be executed."
- (interactive)
- (setq edebug-execution-mode 'Go-nonstop)
- (top-level))
-
-
-;;(defun edebug-exit-out ()
-;; "Go until the current function exits."
-;; (interactive)
-;; (edebug-set-mode 'exiting "Exit..."))
-
-
-;;; The following initial mode setting definitions are not used yet.
-
-'(defconst edebug-initial-mode-alist
- '((edebug-Continue-fast . Continue-fast)
- (edebug-Trace-fast . Trace-fast)
- (edebug-continue . continue)
- (edebug-trace . trace)
- (edebug-go . go)
- (edebug-step-through . step)
- (edebug-Go-nonstop . Go-nonstop)
- )
- "Association list between commands and the modes they set.")
-
-
-'(defun edebug-set-initial-mode ()
- "Ask for the initial mode of the enclosing function.
-The mode is requested via the key that would be used to set the mode in
-edebug-mode."
- (interactive)
- (let* ((this-function (edebug-which-function))
- (keymap (if (eq edebug-mode-map (current-local-map))
- edebug-mode-map))
- (old-mode (or (get this-function 'edebug-initial-mode)
- edebug-initial-mode))
- (key (read-key-sequence
- (format
- "Change initial edebug mode for %s from %s (%s) to (enter key): "
- this-function
- old-mode
- (where-is-internal
- (car (rassq old-mode edebug-initial-mode-alist))
- keymap 'firstonly
- ))))
- (mode (cdr (assq (key-binding key) edebug-initial-mode-alist)))
- )
- (if (and mode
- (or (get this-function 'edebug-initial-mode)
- (not (eq mode edebug-initial-mode))))
- (progn
- (put this-function 'edebug-initial-mode mode)
- (message "Initial mode for %s is now: %s"
- this-function mode))
- (error "Key must map to one of the mode changing commands")
- )))
-
-;;; Evaluation of expressions
-
-(def-edebug-spec edebug-outside-excursion t)
-
-(defmacro edebug-outside-excursion (&rest body)
- "Evaluate an expression list in the outside context.
-Return the result of the last expression."
- (` (save-excursion ; of current-buffer
- (if edebug-save-windows
- (progn
- ;; After excursion, we will
- ;; restore to current window configuration.
- (setq edebug-inside-windows
- (edebug-current-windows edebug-save-windows))
- ;; Restore outside windows.
- (edebug-set-windows edebug-outside-windows)))
-
- (set-buffer edebug-buffer) ; why?
- ;; (use-local-map edebug-outside-map)
- (store-match-data edebug-outside-match-data)
- ;; Restore outside context.
- (let (;; (edebug-inside-map (current-local-map)) ;; restore map??
- (last-command-char edebug-outside-last-command-char)
- (last-command-event edebug-outside-last-command-event)
- (last-command edebug-outside-last-command)
- (this-command edebug-outside-this-command)
- (unread-command-char edebug-outside-unread-command-char)
- (unread-command-event edebug-outside-unread-command-event)
- (unread-command-events edebug-outside-unread-command-events)
- (last-input-char edebug-outside-last-input-char)
- (last-input-event edebug-outside-last-input-event)
- (last-event-frame edebug-outside-last-event-frame)
- (last-nonmenu-event edebug-outside-last-nonmenu-event)
- (track-mouse edebug-outside-track-mouse)
- (standard-output edebug-outside-standard-output)
- (standard-input edebug-outside-standard-input)
-
- (executing-kbd-macro edebug-outside-executing-macro)
- (defining-kbd-macro edebug-outside-defining-kbd-macro)
- (pre-command-hook edebug-outside-pre-command-hook)
- (post-command-hook edebug-outside-post-command-hook)
-
- ;; See edebug-display
- (overlay-arrow-position edebug-outside-o-a-p)
- (overlay-arrow-string edebug-outside-o-a-s)
- (cursor-in-echo-area edebug-outside-c-i-e-a)
- )
- (unwind-protect
- (save-excursion ; of edebug-buffer
- (set-buffer edebug-outside-buffer)
- (goto-char edebug-outside-point)
- (if (marker-buffer (edebug-mark-marker))
- (set-marker (edebug-mark-marker) edebug-outside-mark))
- (,@ body))
-
- ;; Back to edebug-buffer. Restore rest of inside context.
- ;; (use-local-map edebug-inside-map)
- (if edebug-save-windows
- ;; Restore inside windows.
- (edebug-set-windows edebug-inside-windows))
-
- ;; Save values that may have been changed.
- (setq
- edebug-outside-last-command-char last-command-char
- edebug-outside-last-command-event last-command-event
- edebug-outside-last-command last-command
- edebug-outside-this-command this-command
- edebug-outside-unread-command-char unread-command-char
- edebug-outside-unread-command-event unread-command-event
- edebug-outside-unread-command-events unread-command-events
- edebug-outside-last-input-char last-input-char
- edebug-outside-last-input-event last-input-event
- edebug-outside-last-event-frame last-event-frame
- edebug-outside-last-nonmenu-event last-nonmenu-event
- edebug-outside-track-mouse track-mouse
- edebug-outside-standard-output standard-output
- edebug-outside-standard-input standard-input
-
- edebug-outside-executing-macro executing-kbd-macro
- edebug-outside-defining-kbd-macro defining-kbd-macro
- edebug-outside-pre-command-hook pre-command-hook
- edebug-outside-post-command-hook post-command-hook
-
- edebug-outside-o-a-p overlay-arrow-position
- edebug-outside-o-a-s overlay-arrow-string
- edebug-outside-c-i-e-a cursor-in-echo-area
- ))) ; let
- )))
-
-(defvar cl-debug-env nil) ;; defined in cl; non-nil when lexical env used.
-
-(defun edebug-eval (edebug-expr)
- ;; Are there cl lexical variables active?
- (if cl-debug-env
- (eval (cl-macroexpand-all edebug-expr cl-debug-env))
- (eval edebug-expr)))
-
-(defun edebug-safe-eval (edebug-expr)
- ;; Evaluate EXPR safely.
- ;; If there is an error, a string is returned describing the error.
- (condition-case edebug-err
- (edebug-eval edebug-expr)
- (error (edebug-format "%s: %s" ;; could
- (get (car edebug-err) 'error-message)
- (car (cdr edebug-err))))))
-
-;;; Printing
-
-;; Replace printing functions.
-
-;; obsolete names
-(defalias 'edebug-install-custom-print-funcs 'edebug-install-custom-print)
-(defalias 'edebug-reset-print-funcs 'edebug-uninstall-custom-print)
-(defalias 'edebug-uninstall-custom-print-funcs 'edebug-uninstall-custom-print)
-
-(defun edebug-install-custom-print ()
- "Replace print functions used by Edebug with custom versions."
- ;; Modifying the custom print functions, or changing print-length,
- ;; print-level, print-circle, custom-print-list or custom-print-vector
- ;; have immediate effect.
- (interactive)
- (require 'cust-print)
- (defalias 'edebug-prin1 'custom-prin1)
- (defalias 'edebug-print 'custom-print)
- (defalias 'edebug-prin1-to-string 'custom-prin1-to-string)
- (defalias 'edebug-format 'custom-format)
- (defalias 'edebug-message 'custom-message)
- "Installed")
-
-(eval-and-compile
- (defun edebug-uninstall-custom-print ()
- "Replace edebug custom print functions with internal versions."
- (interactive)
- (defalias 'edebug-prin1 'prin1)
- (defalias 'edebug-print 'print)
- (defalias 'edebug-prin1-to-string 'prin1-to-string)
- (defalias 'edebug-format 'format)
- (defalias 'edebug-message 'message)
- "Uninstalled")
-
- ;; Default print functions are the same as Emacs'.
- (edebug-uninstall-custom-print))
-
-
-(defun edebug-report-error (edebug-value)
- ;; Print an error message like command level does.
- ;; This also prints the error name if it has no error-message.
- (message "%s: %s"
- (or (get (car edebug-value) 'error-message)
- (format "peculiar error (%s)" (car edebug-value)))
- (mapconcat (function (lambda (edebug-arg)
- ;; continuing after an error may
- ;; complain about edebug-arg. why??
- (prin1-to-string edebug-arg)))
- (cdr edebug-value) ", ")))
-
-;; Define here in case they are not already defined.
-(defvar print-level nil)
-(defvar print-circle nil)
-(defvar print-readably) ;; defined by lemacs
-;; Alternatively, we could change the definition of
-;; edebug-safe-prin1-to-string to only use these if defined.
-
-(defun edebug-safe-prin1-to-string (value)
- (let ((print-escape-newlines t)
- (print-length (or edebug-print-length print-length))
- (print-level (or edebug-print-level print-level))
- (print-circle (or edebug-print-circle print-circle))
- (print-readably nil)) ;; lemacs uses this.
- (edebug-prin1-to-string value)))
-
-(defun edebug-compute-previous-result (edebug-previous-value)
- (setq edebug-previous-result
- (if (and (numberp edebug-previous-value)
- (< edebug-previous-value 256)
- (>= edebug-previous-value 0))
- (format "Result: %s = %s" edebug-previous-value
- (single-key-description edebug-previous-value))
- (if edebug-unwrap-results
- (setq edebug-previous-value
- (edebug-unwrap* edebug-previous-value)))
- (concat "Result: "
- (edebug-safe-prin1-to-string edebug-previous-value)))))
-
-(defun edebug-previous-result ()
- "Print the previous result."
- (interactive)
- (message "%s" edebug-previous-result))
-
-;;; Read, Eval and Print
-
-(defun edebug-eval-expression (edebug-expr)
- "Evaluate an expression in the outside environment.
-If interactive, prompt for the expression.
-Print result in minibuffer."
- (interactive "xEval: ")
- (princ
- (edebug-outside-excursion
- (setq values (cons (edebug-eval edebug-expr) values))
- (edebug-safe-prin1-to-string (car values)))))
-
-(defun edebug-eval-last-sexp ()
- "Evaluate sexp before point in the outside environment;
-print value in minibuffer."
- (interactive)
- (edebug-eval-expression (edebug-last-sexp)))
-
-(defun edebug-eval-print-last-sexp ()
- "Evaluate sexp before point in the outside environment;
-print value into current buffer."
- (interactive)
- (let* ((edebug-form (edebug-last-sexp))
- (edebug-result-string
- (edebug-outside-excursion
- (edebug-safe-prin1-to-string (edebug-safe-eval edebug-form))))
- (standard-output (current-buffer)))
- (princ "\n")
- ;; princ the string to get rid of quotes.
- (princ edebug-result-string)
- (princ "\n")
- ))
-
-;;; Edebug Minor Mode
-
-;; Global GUD bindings for all emacs-lisp-mode buffers.
-(define-key emacs-lisp-mode-map "\C-x\C-a\C-s" 'edebug-step-mode)
-(define-key emacs-lisp-mode-map "\C-x\C-a\C-n" 'edebug-next-mode)
-(define-key emacs-lisp-mode-map "\C-x\C-a\C-c" 'edebug-go-mode)
-(define-key emacs-lisp-mode-map "\C-x\C-a\C-l" 'edebug-where)
-
-
-(defvar edebug-mode-map nil)
-(if edebug-mode-map
- nil
- (progn
- (setq edebug-mode-map (copy-keymap emacs-lisp-mode-map))
- ;; control
- (define-key edebug-mode-map " " 'edebug-step-mode)
- (define-key edebug-mode-map "n" 'edebug-next-mode)
- (define-key edebug-mode-map "g" 'edebug-go-mode)
- (define-key edebug-mode-map "G" 'edebug-Go-nonstop-mode)
- (define-key edebug-mode-map "t" 'edebug-trace-mode)
- (define-key edebug-mode-map "T" 'edebug-Trace-fast-mode)
- (define-key edebug-mode-map "c" 'edebug-continue-mode)
- (define-key edebug-mode-map "C" 'edebug-Continue-fast-mode)
-
- ;;(define-key edebug-mode-map "f" 'edebug-forward) not implemented
- (define-key edebug-mode-map "f" 'edebug-forward-sexp)
- (define-key edebug-mode-map "h" 'edebug-goto-here)
-
- (define-key edebug-mode-map "I" 'edebug-instrument-callee)
- (define-key edebug-mode-map "i" 'edebug-step-in)
- (define-key edebug-mode-map "o" 'edebug-step-out)
-
- ;; quitting and stopping
- (define-key edebug-mode-map "q" 'top-level)
- (define-key edebug-mode-map "Q" 'edebug-top-level-nonstop)
- (define-key edebug-mode-map "a" 'abort-recursive-edit)
- (define-key edebug-mode-map "S" 'edebug-stop)
-
- ;; breakpoints
- (define-key edebug-mode-map "b" 'edebug-set-breakpoint)
- (define-key edebug-mode-map "u" 'edebug-unset-breakpoint)
- (define-key edebug-mode-map "B" 'edebug-next-breakpoint)
- (define-key edebug-mode-map "x" 'edebug-set-conditional-breakpoint)
- (define-key edebug-mode-map "X" 'edebug-set-global-break-condition)
-
- ;; evaluation
- (define-key edebug-mode-map "r" 'edebug-previous-result)
- (define-key edebug-mode-map "e" 'edebug-eval-expression)
- (define-key edebug-mode-map "\C-x\C-e" 'edebug-eval-last-sexp)
- (define-key edebug-mode-map "E" 'edebug-visit-eval-list)
-
- ;; views
- (define-key edebug-mode-map "w" 'edebug-where)
- (define-key edebug-mode-map "v" 'edebug-view-outside) ;; maybe obsolete??
- (define-key edebug-mode-map "p" 'edebug-bounce-point)
- (define-key edebug-mode-map "P" 'edebug-view-outside) ;; same as v
- (define-key edebug-mode-map "W" 'edebug-toggle-save-windows)
-
- ;; misc
- (define-key edebug-mode-map "?" 'edebug-help)
- (define-key edebug-mode-map "d" 'edebug-backtrace)
-
- (define-key edebug-mode-map "-" 'negative-argument)
-
- ;; statistics
- (define-key edebug-mode-map "=" 'edebug-temp-display-freq-count)
-
- ;; GUD bindings
- (define-key edebug-mode-map "\C-c\C-s" 'edebug-step-mode)
- (define-key edebug-mode-map "\C-c\C-n" 'edebug-next-mode)
- (define-key edebug-mode-map "\C-c\C-c" 'edebug-go-mode)
-
- (define-key edebug-mode-map "\C-x " 'edebug-set-breakpoint)
- (define-key edebug-mode-map "\C-c\C-d" 'edebug-unset-breakpoint)
- (define-key edebug-mode-map "\C-c\C-t"
- (function (lambda () (edebug-set-breakpoint t))))
- (define-key edebug-mode-map "\C-c\C-l" 'edebug-where)
- ))
-
-;; Autoloading these global bindings doesn't make sense because
-;; they cannot be used anyway unless Edebug is already loaded and active.
-
-(defvar global-edebug-prefix "\^XX"
- "Prefix key for global edebug commands, available from any buffer.")
-
-(defvar global-edebug-map nil
- "Global map of edebug commands, available from any buffer.")
-
-(if global-edebug-map
- nil
- (setq global-edebug-map (make-sparse-keymap))
-
- (global-unset-key global-edebug-prefix)
- (global-set-key global-edebug-prefix global-edebug-map)
-
- (define-key global-edebug-map " " 'edebug-step-mode)
- (define-key global-edebug-map "g" 'edebug-go-mode)
- (define-key global-edebug-map "G" 'edebug-Go-nonstop-mode)
- (define-key global-edebug-map "t" 'edebug-trace-mode)
- (define-key global-edebug-map "T" 'edebug-Trace-fast-mode)
- (define-key global-edebug-map "c" 'edebug-continue-mode)
- (define-key global-edebug-map "C" 'edebug-Continue-fast-mode)
-
- ;; breakpoints
- (define-key global-edebug-map "b" 'edebug-set-breakpoint)
- (define-key global-edebug-map "u" 'edebug-unset-breakpoint)
- (define-key global-edebug-map "x" 'edebug-set-conditional-breakpoint)
- (define-key global-edebug-map "X" 'edebug-set-global-break-condition)
-
- ;; views
- (define-key global-edebug-map "w" 'edebug-where)
- (define-key global-edebug-map "W" 'edebug-toggle-save-windows)
-
- ;; quitting
- (define-key global-edebug-map "q" 'top-level)
- (define-key global-edebug-map "Q" 'edebug-top-level-nonstop)
- (define-key global-edebug-map "a" 'abort-recursive-edit)
-
- ;; statistics
- (define-key global-edebug-map "=" 'edebug-display-freq-count)
- )
-
-(defun edebug-help ()
- (interactive)
- (describe-function 'edebug-mode))
-
-(defun edebug-mode ()
- "Mode for Emacs Lisp buffers while in Edebug.
-
-In addition to all Emacs Lisp commands (except those that modify the
-buffer) there are local and global key bindings to several Edebug
-specific commands. E.g. `edebug-step-mode' is bound to \\[edebug-step-mode]
-in the Edebug buffer and \\<global-map>\\[edebug-step-mode] in any buffer.
-
-Also see bindings for the eval list buffer, *edebug*.
-
-The edebug buffer commands:
-\\{edebug-mode-map}
-
-Global commands prefixed by `global-edebug-prefix':
-\\{global-edebug-map}
-
-Options:
-edebug-setup-hook
-edebug-all-defs
-edebug-all-forms
-edebug-save-windows
-edebug-save-displayed-buffer-points
-edebug-initial-mode
-edebug-trace
-edebug-test-coverage
-edebug-continue-kbd-macro
-edebug-print-length
-edebug-print-level
-edebug-print-circle
-edebug-on-error
-edebug-on-quit
-edebug-on-signal
-edebug-unwrap-results
-edebug-global-break-condition
-"
- (use-local-map edebug-mode-map))
-
-;;; edebug eval list mode
-
-;; A list of expressions and their evaluations is displayed in *edebug*.
-
-(defun edebug-eval-result-list ()
- "Return a list of evaluations of edebug-eval-list"
- ;; Assumes in outside environment.
- ;; Don't do any edebug things now.
- (let ((edebug-execution-mode 'Go-nonstop)
- (edebug-trace nil))
- (mapcar 'edebug-safe-eval edebug-eval-list)))
-
-(defun edebug-eval-display-list (edebug-eval-result-list)
- ;; Assumes edebug-eval-buffer exists.
- (let ((edebug-eval-list-temp edebug-eval-list)
- (standard-output edebug-eval-buffer)
- (edebug-comment-line
- (format ";%s\n" (make-string (- (window-width) 2) ?-))))
- (set-buffer edebug-eval-buffer)
- (erase-buffer)
- (while edebug-eval-list-temp
- (prin1 (car edebug-eval-list-temp)) (terpri)
- (prin1 (car edebug-eval-result-list)) (terpri)
- (princ edebug-comment-line)
- (setq edebug-eval-list-temp (cdr edebug-eval-list-temp))
- (setq edebug-eval-result-list (cdr edebug-eval-result-list)))
- (edebug-pop-to-buffer edebug-eval-buffer)
- ))
-
-(defun edebug-create-eval-buffer ()
- (if (not (and edebug-eval-buffer (buffer-name edebug-eval-buffer)))
- (progn
- (set-buffer (setq edebug-eval-buffer (get-buffer-create "*edebug*")))
- (edebug-eval-mode))))
-
-;; Should generalize this to be callable outside of edebug
-;; with calls in user functions, e.g. (edebug-eval-display)
-
-(defun edebug-eval-display (edebug-eval-result-list)
- "Display expressions and evaluations in EVAL-LIST.
-It modifies the context by popping up the eval display."
- (if edebug-eval-result-list
- (progn
- (edebug-create-eval-buffer)
- (edebug-eval-display-list edebug-eval-result-list)
- )))
-
-(defun edebug-eval-redisplay ()
- "Redisplay eval list in outside environment.
-May only be called from within edebug-recursive-edit."
- (edebug-create-eval-buffer)
- (edebug-outside-excursion
- (edebug-eval-display-list (edebug-eval-result-list))
- ))
-
-(defun edebug-visit-eval-list ()
- (interactive)
- (edebug-eval-redisplay)
- (edebug-pop-to-buffer edebug-eval-buffer))
-
-
-(defun edebug-update-eval-list ()
- "Replace the evaluation list with the sexps now in the eval buffer."
- (interactive)
- (let ((starting-point (point))
- new-list)
- (goto-char (point-min))
- ;; get the first expression
- (edebug-skip-whitespace)
- (if (not (eobp))
- (progn
- (forward-sexp 1)
- (setq new-list (cons (edebug-last-sexp) new-list))))
-
- (while (re-search-forward "^;" nil t)
- (forward-line 1)
- (skip-chars-forward " \t\n\r")
- (if (and (/= ?\; (following-char))
- (not (eobp)))
- (progn
- (forward-sexp 1)
- (setq new-list (cons (edebug-last-sexp) new-list)))))
-
- (setq edebug-eval-list (nreverse new-list))
- (edebug-eval-redisplay)
- (goto-char starting-point)))
-
-
-(defun edebug-delete-eval-item ()
- "Delete the item under point and redisplay."
- ;; could add arg to do repeatedly
- (interactive)
- (if (re-search-backward "^;" nil 'nofail)
- (forward-line 1))
- (delete-region
- (point) (progn (re-search-forward "^;" nil 'nofail)
- (beginning-of-line)
- (point)))
- (edebug-update-eval-list))
-
-
-
-(defvar edebug-eval-mode-map nil
- "Keymap for edebug-eval-mode. Superset of lisp-interaction-mode.")
-
-(if edebug-eval-mode-map
- nil
- (setq edebug-eval-mode-map (copy-keymap lisp-interaction-mode-map))
-
- (define-key edebug-eval-mode-map "\C-c\C-w" 'edebug-where)
- (define-key edebug-eval-mode-map "\C-c\C-d" 'edebug-delete-eval-item)
- (define-key edebug-eval-mode-map "\C-c\C-u" 'edebug-update-eval-list)
- (define-key edebug-eval-mode-map "\C-x\C-e" 'edebug-eval-last-sexp)
- (define-key edebug-eval-mode-map "\C-j" 'edebug-eval-print-last-sexp)
- )
-
-
-(defun edebug-eval-mode ()
- "Mode for evaluation list buffer while in Edebug.
-
-In addition to all Interactive Emacs Lisp commands there are local and
-global key bindings to several Edebug specific commands. E.g.
-`edebug-step-mode' is bound to \\[edebug-step-mode] in the Edebug
-buffer and \\<global-map>\\[edebug-step-mode] in any buffer.
-
-Eval list buffer commands:
-\\{edebug-eval-mode-map}
-
-Global commands prefixed by global-edebug-prefix:
-\\{global-edebug-map}
-"
- (lisp-interaction-mode)
- (setq major-mode 'edebug-eval-mode)
- (setq mode-name "Edebug-Eval")
- (use-local-map edebug-eval-mode-map))
-
-;;; Interface with standard debugger.
-
-;; (setq debugger 'edebug) ; to use the edebug debugger
-;; (setq debugger 'debug) ; use the standard debugger
-
-;; Note that debug and its utilities must be byte-compiled to work,
-;; since they depend on the backtrace looking a certain way. But
-;; edebug is not dependent on this, yet.
-
-(defun edebug (&optional edebug-arg-mode &rest debugger-args)
- "Replacement for debug.
-If we are running an edebugged function,
-show where we last were. Otherwise call debug normally."
-;; (message "entered: %s depth: %s edebug-recursion-depth: %s"
-;; edebug-entered (recursion-depth) edebug-recursion-depth) (sit-for 1)
- (if (and edebug-entered ; anything active?
- (eq (recursion-depth) edebug-recursion-depth))
- (let (;; Where were we before the error occurred?
- (edebug-offset-index (car edebug-offset-indices))
- ;; Bind variables required by edebug-display
- (edebug-value (car debugger-args))
- edebug-breakpoints
- edebug-break-data
- edebug-break-condition
- edebug-global-break
- (edebug-break (null edebug-arg-mode)) ;; if called explicitly
- )
- (edebug-display)
- (if (eq edebug-arg-mode 'error)
- nil
- edebug-value))
-
- ;; Otherwise call debug normally.
- ;; Still need to remove extraneous edebug calls from stack.
- (apply 'debug edebug-arg-mode debugger-args)
- ))
-
-
-(defun edebug-backtrace ()
- "Display a non-working backtrace. Better than nothing..."
- (interactive)
- (if (or (not edebug-backtrace-buffer)
- (null (buffer-name edebug-backtrace-buffer)))
- (setq edebug-backtrace-buffer
- (generate-new-buffer "*Backtrace*"))
- ;; else, could just display edebug-backtrace-buffer
- )
- (with-output-to-temp-buffer (buffer-name edebug-backtrace-buffer)
- (setq edebug-backtrace-buffer standard-output)
- (let ((print-escape-newlines t)
- (print-length 50)
- last-ok-point)
- (backtrace)
-
- ;; Clean up the backtrace.
- ;; Not quite right for current edebug scheme.
- (set-buffer edebug-backtrace-buffer)
- (setq truncate-lines t)
- (goto-char (point-min))
- (setq last-ok-point (point))
- (if t (progn
-
- ;; Delete interspersed edebug internals.
- (while (re-search-forward "^ \(?edebug" nil t)
- (beginning-of-line)
- (cond
- ((looking-at "^ \(edebug-after")
- ;; Previous lines may contain code, so just delete this line
- (setq last-ok-point (point))
- (forward-line 1)
- (delete-region last-ok-point (point)))
-
- ((looking-at "^ edebug")
- (forward-line 1)
- (delete-region last-ok-point (point))
- )))
- )))))
-
-
-;;; Trace display
-
-(defun edebug-trace-display (buf-name fmt &rest args)
- "In buffer BUF-NAME, display FMT and ARGS at the end and make it visible.
-The buffer is created if it does not exist.
-You must include newlines in FMT to break lines, but one newline is appended."
-;; e.g.
-;; (edebug-trace-display "*trace-point*"
-;; "saving: point = %s window-start = %s"
-;; (point) (window-start))
- (let* ((oldbuf (current-buffer))
- (selected-window (selected-window))
- (buffer (get-buffer-create buf-name))
- buf-window)
-;; (message "before pop-to-buffer") (sit-for 1)
- (edebug-pop-to-buffer buffer)
- (setq truncate-lines t)
- (setq buf-window (selected-window))
- (goto-char (point-max))
- (insert (apply 'edebug-format fmt args) "\n")
- ;; Make it visible.
- (vertical-motion (- 1 (window-height)))
- (set-window-start buf-window (point))
- (goto-char (point-max))
-;; (set-window-point buf-window (point))
-;; (edebug-sit-for 0)
- (bury-buffer buffer)
- (select-window selected-window)
- (set-buffer oldbuf))
- buf-name)
-
-
-(defun edebug-trace (fmt &rest args)
- "Convenience call to edebug-trace-display using edebug-trace-buffer"
- (apply 'edebug-trace-display edebug-trace-buffer fmt args))
-
-
-;;; Frequency count and coverage
-
-(defun edebug-display-freq-count ()
- "Display the frequency count data for each line of the current
-definition. The frequency counts are inserted as comment lines after
-each line, and you can undo all insertions with one `undo' command.
-
-The counts are inserted starting under the `(' before an expression
-or the `)' after an expression, or on the last char of a symbol.
-The counts are only displayed when they differ from previous counts on
-the same line.
-
-If coverage is being tested, whenever all known results of an expression
-are `eq', the char `=' will be appended after the count
-for that expression. Note that this is always the case for an
-expression only evaluated once.
-
-To clear the frequency count and coverage data for a definition,
-reinstrument it."
- (interactive)
- (let* ((function (edebug-form-data-symbol))
- (counts (get function 'edebug-freq-count))
- (coverages (get function 'edebug-coverage))
- (data (get function 'edebug))
- (def-mark (car data)) ; mark at def start
- (edebug-points (nth 2 data))
- (i (1- (length edebug-points)))
- (last-index)
- (first-index)
- (start-of-line)
- (start-of-count-line)
- (last-count)
- )
- (save-excursion
- ;; Traverse in reverse order so offsets are correct.
- (while (<= 0 i)
- ;; Start at last expression in line.
- (goto-char (+ def-mark (aref edebug-points i)))
- (beginning-of-line)
- (setq start-of-line (- (point) def-mark)
- last-index i)
-
- ;; Find all indexes on same line.
- (while (and (<= 0 (setq i (1- i)))
- (<= start-of-line (aref edebug-points i))))
- ;; Insert all the indices for this line.
- (forward-line 1)
- (setq start-of-count-line (point)
- first-index i ; really last index for line above this one.
- last-count -1) ; cause first count to always appear.
- (insert ";#")
- ;; i == first-index still
- (while (<= (setq i (1+ i)) last-index)
- (let ((count (aref counts i))
- (coverage (aref coverages i))
- (col (save-excursion
- (goto-char (+ (aref edebug-points i) def-mark))
- (- (current-column)
- (if (= ?\( (following-char)) 0 1)))))
- (insert (make-string
- (max 0 (- col (- (point) start-of-count-line))) ?\ )
- (if (and (< 0 count)
- (not (memq coverage
- '(unknown ok-coverage))))
- "=" "")
- (if (= count last-count) "" (int-to-string count))
- " ")
- (setq last-count count)))
- (insert "\n")
- (setq i first-index)))))
-
-(defun edebug-temp-display-freq-count ()
- "Temporarily display the frequency count data for the current definition.
-It is removed when you hit any char."
- ;; This seems not to work with Emacs 18.59. It undoes too far.
- (interactive)
- (let ((buffer-read-only nil))
- (undo-boundary)
- (edebug-display-freq-count)
- (setq unread-command-char (read-char))
- (undo)))
-
-
-;;; Menus
-
-(defun edebug-toggle (variable)
- (set variable (not (eval variable)))
- (message "%s: %s" variable (eval variable)))
-
-;; We have to require easymenu (even for Emacs 18) just so
-;; the easy-menu-define macro call is compiled correctly.
-(require 'easymenu)
-
-(defconst edebug-mode-menus
- '("Edebug"
- "----"
- ["Stop" edebug-stop t]
- ["Step" edebug-step-mode t]
- ["Next" edebug-next-mode t]
- ["Trace" edebug-trace-mode t]
- ["Trace Fast" edebug-Trace-fast-mode t]
- ["Continue" edebug-continue-mode t]
- ["Continue Fast" edebug-Continue-fast-mode t]
- ["Go" edebug-go-mode t]
- ["Go Nonstop" edebug-Go-nonstop-mode t]
- "----"
- ["Help" edebug-help t]
- ["Abort" abort-recursive-edit t]
- ["Quit to Top Level" top-level t]
- ["Quit Nonstop" edebug-top-level-nonstop t]
- "----"
- ("Jumps"
- ["Forward Sexp" edebug-forward-sexp t]
- ["Step In" edebug-step-in t]
- ["Step Out" edebug-step-out t]
- ["Goto Here" edebug-goto-here t])
-
- ("Breaks"
- ["Set Breakpoint" edebug-set-breakpoint t]
- ["Unset Breakpoint" edebug-unset-breakpoint t]
- ["Set Conditional Breakpoint" edebug-set-conditional-breakpoint t]
- ["Set Global Break Condition" edebug-set-global-break-condition t]
- ["Show Next Breakpoint" edebug-next-breakpoint t])
-
- ("Views"
- ["Where am I?" edebug-where t]
- ["Bounce to Current Point" edebug-bounce-point t]
- ["View Outside Windows" edebug-view-outside t]
- ["Previous Result" edebug-previous-result t]
- ["Show Backtrace" edebug-backtrace t]
- ["Display Freq Count" edebug-display-freq-count t])
-
- ("Eval"
- ["Expression" edebug-eval-expression t]
- ["Last Sexp" edebug-eval-last-sexp t]
- ["Visit Eval List" edebug-visit-eval-list t])
-
- ("Options"
- ["Edebug All Defs" edebug-all-defs t]
- ["Edebug All Forms" edebug-all-forms t]
- "----"
- ["Toggle Tracing" (edebug-toggle 'edebug-trace) t]
- ["Toggle Coverage Testing" (edebug-toggle 'edebug-test-coverage) t]
- ["Toggle Window Saving" edebug-toggle-save-windows t]
- ["Toggle Point Saving"
- (edebug-toggle 'edebug-save-displayed-buffer-points) t]
- ))
- "Lemacs style menus for Edebug.")
-
-
-;;; Emacs version specific code
-
-;;; The default for all above is Emacs 18, because it is easier to compile
-;;; Emacs 18 code in Emacs 19 than vice versa. This default will
-;;; change once most people are using Emacs 19 or derivatives.
-
-;; Epoch specific code is in a separate file: edebug-epoch.el.
-
-;; The byte-compiler will complain about changes in number of arguments
-;; to functions like mark and read-from-minibuffer. These warnings
-;; may be ignored because the right call should always be made.
-
-(defun edebug-emacs-19-specific ()
-
- (defalias 'edebug-window-live-p 'window-live-p)
-
- ;; Mark takes an argument in Emacs 19.
- (defun edebug-mark ()
- (mark t));; Does this work for lemacs too?
-
- (defun edebug-set-conditional-breakpoint (arg condition)
- "Set a conditional breakpoint at nearest sexp.
-The condition is evaluated in the outside context.
-With prefix argument, make it a temporary breakpoint."
- ;; (interactive "P\nxCondition: ")
- (interactive
- (list
- current-prefix-arg
- ;; Read condition as follows; getting previous condition is cumbersome:
- (let ((edebug-stop-point (edebug-find-stop-point)))
- (if edebug-stop-point
- (let* ((edebug-def-name (car edebug-stop-point))
- (index (cdr edebug-stop-point))
- (edebug-data (get edebug-def-name 'edebug))
- (edebug-breakpoints (car (cdr edebug-data)))
- (edebug-break-data (assq index edebug-breakpoints))
- (edebug-break-condition (car (cdr edebug-break-data)))
- (edebug-expression-history
- ;; Prepend the current condition, if any.
- (if edebug-break-condition
- (cons edebug-break-condition read-expression-history)
- read-expression-history)))
- (prog1
- (read-from-minibuffer
- "Condition: " nil read-expression-map t
- 'edebug-expression-history)
- (setq read-expression-history edebug-expression-history)
- ))))))
- (edebug-modify-breakpoint t condition arg))
-
- (defun edebug-eval-expression (edebug-expr)
- "Evaluate an expression in the outside environment.
-If interactive, prompt for the expression.
-Print result in minibuffer."
- (interactive (list (read-from-minibuffer
- "Eval: " nil read-expression-map t
- 'read-expression-history)))
- (princ
- (edebug-outside-excursion
- (setq values (cons (edebug-eval edebug-expr) values))
- (edebug-safe-prin1-to-string (car values)))))
-
- (easy-menu-define edebug-menu edebug-mode-map "Edebug menus" edebug-mode-menus)
- (if window-system
- (x-popup-menu nil (lookup-key edebug-mode-map [menu-bar Edebug])))
- )
-
-
-(defun edebug-lemacs-specific ()
-
- ;; We need to bind zmacs-regions to nil around all calls to `mark' and
- ;; `mark-marker' but don't bind it to nil before entering a recursive edit,
- ;; that is, don't interfere with the binding the user might see while
- ;; executing a command.
-
- (defvar zmacs-regions)
-
- (defun edebug-mark ()
- (let ((zmacs-regions nil))
- (mark)))
-
- (defun edebug-mark-marker ()
- (let ((zmacs-regions nil));; for lemacs
- (mark-marker)))
-
-
- (defun edebug-mode-menu (event)
- (interactive "@event")
- (popup-menu edebug-mode-menus))
-
- (define-key edebug-mode-map 'button3 'edebug-mode-menu)
- )
-
-(defun edebug-emacs-version-specific ()
- (cond
- ((string-match "Lucid" emacs-version);; Lucid Emacs
- (edebug-lemacs-specific))
-
- ((and (boundp 'epoch::version) epoch::version)
- (require 'edebug-epoch))
-
- ((not (string-match "^18" emacs-version))
- (edebug-emacs-19-specific))))
-
-(edebug-emacs-version-specific)
-
-
-;;; Byte-compiler
-
-;; Extension for bytecomp to resolve undefined function references.
-;; Requires new byte compiler.
-
-;; Reenable byte compiler warnings about unread-command-char and -event.
-;; Disabled before edebug-recursive-edit.
-(eval-when-compile
- (if edebug-unread-command-char-warning
- (put 'unread-command-char 'byte-obsolete-variable
- edebug-unread-command-char-warning))
- (if edebug-unread-command-event-warning
- (put 'unread-command-event 'byte-obsolete-variable
- edebug-unread-command-event-warning)))
-
-(eval-when-compile
- ;; The body of eval-when-compile seems to get evaluated with eval-defun.
- ;; We only want to evaluate when actually byte compiling.
- ;; But it is OK to evaluate as long as byte-compiler has been loaded.
- (if (featurep 'byte-compile) (progn
-
- (defun byte-compile-resolve-functions (funcs)
- "Say it is OK for the named functions to be unresolved."
- (mapcar
- (function
- (lambda (func)
- (setq byte-compile-unresolved-functions
- (delq (assq func byte-compile-unresolved-functions)
- byte-compile-unresolved-functions))))
- funcs)
- nil)
-
- '(defun byte-compile-resolve-free-references (vars)
- "Say it is OK for the named variables to be referenced."
- (mapcar
- (function
- (lambda (var)
- (setq byte-compile-free-references
- (delq var byte-compile-free-references))))
- vars)
- nil)
-
- '(defun byte-compile-resolve-free-assignments (vars)
- "Say it is OK for the named variables to be assigned."
- (mapcar
- (function
- (lambda (var)
- (setq byte-compile-free-assignments
- (delq var byte-compile-free-assignments))))
- vars)
- nil)
-
- (byte-compile-resolve-functions
- '(reporter-submit-bug-report
- edebug-gensym ;; also in cl.el
- ;; Interfaces to standard functions.
- edebug-original-eval-defun
- edebug-original-read
- edebug-get-buffer-window
- edebug-mark
- edebug-mark-marker
- edebug-input-pending-p
- edebug-sit-for
- edebug-prin1-to-string
- edebug-format
- ;; lemacs
- zmacs-deactivate-region
- popup-menu
- ;; CL
- cl-macroexpand-all
- ;; And believe it or not, the byte compiler doesn't know about:
- byte-compile-resolve-functions
- ))
-
- '(byte-compile-resolve-free-references
- '(read-expression-history
- read-expression-map))
-
- '(byte-compile-resolve-free-assignments
- '(read-expression-history))
-
- )))
-
-
-;;; Autoloading of Edebug accessories
-
-(if (featurep 'cl)
- (add-hook 'edebug-setup-hook
- (function (lambda () (require 'cl-specs))))
- ;; The following causes cl-specs to be loaded if you load cl.el.
- (add-hook 'cl-load-hook
- (function (lambda () (require 'cl-specs)))))
-
-;;; edebug-cl-read and cl-read are available from liberte@cs.uiuc.edu
-(if (featurep 'cl-read)
- (add-hook 'edebug-setup-hook
- (function (lambda () (require 'edebug-cl-read))))
- ;; The following causes edebug-cl-read to be loaded when you load cl-read.el.
- (add-hook 'cl-read-load-hooks
- (function (lambda () (require 'edebug-cl-read)))))
-
-
-;;; Finalize Loading
-
-;;; Finally, hook edebug into the rest of Emacs.
-;;; There are probably some other things that could go here.
-
-;; Install edebug read and eval functions.
-(edebug-install-read-eval-functions)
-
-(provide 'edebug)
-
-;;; edebug.el ends here
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
deleted file mode 100644
index ff84819c748..00000000000
--- a/lisp/emacs-lisp/eldoc.el
+++ /dev/null
@@ -1,458 +0,0 @@
-;;; eldoc.el --- show function arglist or variable docstring in echo area
-
-;; Copyright (C) 1995 Noah S. Friedman
-
-;; Author: Noah Friedman <friedman@prep.ai.mit.edu>
-;; Maintainer: friedman@prep.ai.mit.edu
-;; Keywords: extensions
-;; Status: Works in Emacs 19 and XEmacs.
-;; Created: 1995-10-06
-
-;; LCD Archive Entry:
-;; eldoc|Noah Friedman|friedman@prep.ai.mit.edu|
-;; show function arglist or variable docstring in echo area|
-;; $Date: 1996/07/14 16:46:25 $|$Revision: 1.6 $|~/misc/eldoc.el.gz|
-
-;; $Id: eldoc.el,v 1.6 1996/07/14 16:46:25 friedman Exp friedman $
-
-;; 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 2, 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, you can either send email to this
-;; program's maintainer or write to: The Free Software Foundation,
-;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This program was inspired by the behavior of the Lisp Machine "mouse
-;; documentation window"; as you type a function's symbol name as part of a
-;; sexp, it will print the argument list for that function. However, this
-;; program's behavior is different in a couple of significant ways. For
-;; one, you need not actually type the function name; you need only move
-;; point around in a sexp that calls it. However, if point is over a
-;; documented variable, it will print the one-line documentation for that
-;; variable instead, to remind you of that variable's purpose.
-
-;; One useful way to enable this minor mode is to put the following in your
-;; .emacs:
-;;
-;; (autoload 'turn-on-eldoc-mode "eldoc" nil t)
-;; (add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)
-;; (add-hook 'lisp-interaction-mode-hook 'turn-on-eldoc-mode)
-
-;;; Code:
-
-;;;###autoload
-(defvar eldoc-mode nil
- "*If non-nil, show the defined parameters for the elisp function near point.
-
-For the emacs lisp function at the beginning of the sexp which point is
-within, show the defined parameters for the function in the echo area.
-This information is extracted directly from the function or macro if it is
-in pure lisp.
-
-If the emacs function is a subr, the parameters are obtained from the
-documentation string if possible.
-
-If point is over a documented variable, print that variable's docstring
-instead; see function `eldoc-print-var-docstring'.
-
-This variable is buffer-local.")
-(make-variable-buffer-local 'eldoc-mode)
-
-(defvar eldoc-idle-delay 0.50
- "*Number of seconds of idle time to wait before printing.
-If user input arrives before this interval of time has elapsed after the
-last input, no documentation will be printed.
-
-If this variable is set to 0, no idle time is required.")
-
-(defvar eldoc-argument-case 'upcase
- "Case to display argument names of functions, as a symbol.
-This has two preferred values: `upcase' or `downcase'.
-Actually, any name of a function which takes a string as an argument and
-returns another string is acceptable.")
-
-(defvar eldoc-mode-message-commands nil
- "*Obarray of command names where it is appropriate to print in the echo area.
-
-This is not done for all commands since some print their own
-messages in the echo area, and these functions would instantly overwrite
-them. But self-insert-command as well as most motion commands are good
-candidates.
-
-It is probably best to manipulate this data structure with the commands
-`eldoc-add-command' and `eldoc-remove-command'.")
-
-(cond ((null eldoc-mode-message-commands)
- ;; If you increase the number of buckets, keep it a prime number.
- (setq eldoc-mode-message-commands (make-vector 31 0))
- (let ((list '("self-insert-command"
- "next-" "previous-"
- "forward-" "backward-"
- "beginning-of-" "end-of-"
- "goto-"
- "recenter"
- "scroll-"))
- (syms nil))
- (while list
- (setq syms (all-completions (car list) obarray 'fboundp))
- (setq list (cdr list))
- (while syms
- (set (intern (car syms) eldoc-mode-message-commands) t)
- (setq syms (cdr syms)))))))
-
-;; Bookkeeping; the car contains the last symbol read from the buffer.
-;; The cdr contains the string last displayed in the echo area, so it can
-;; be printed again if necessary without reconsing.
-(defvar eldoc-last-data '(nil . nil))
-
-(defvar eldoc-minor-mode-string " ElDoc"
- "*String to display in mode line when Eldoc Mode is enabled.")
-
-;; Put this minor mode on the global minor-mode-alist.
-(or (assq 'eldoc-mode (default-value 'minor-mode-alist))
- (setq-default minor-mode-alist
- (append (default-value 'minor-mode-alist)
- '((eldoc-mode eldoc-minor-mode-string)))))
-
-;; In emacs 19.29 and later, and XEmacs 19.13 and later, all messages are
-;; recorded in a log. Do not put eldoc messages in that log since
-;; they are Legion.
-(defmacro eldoc-message (&rest args)
- (if (fboundp 'display-message)
- ;; XEmacs 19.13 way of preventing log messages.
- (list 'display-message '(quote no-log) (apply 'list 'format args))
- (list 'let (list (list 'message-log-max 'nil))
- (apply 'list 'message args))))
-
-
-;;;###autoload
-(defun eldoc-mode (&optional prefix)
- "*If non-nil, then enable eldoc-mode (see variable docstring)."
- (interactive "P")
-
- ;; Make sure it's on the post-command-idle-hook if defined, otherwise put
- ;; it on post-command-hook. The former first appeared in Emacs 19.30.
- (add-hook (if (boundp 'post-command-idle-hook)
- 'post-command-idle-hook
- 'post-command-hook)
- 'eldoc-mode-print-current-symbol-info)
-
- (setq eldoc-mode (if prefix
- (>= (prefix-numeric-value prefix) 0)
- (not eldoc-mode)))
-
- (and (interactive-p)
- (if eldoc-mode
- (message "eldoc-mode is enabled")
- (message "eldoc-mode is disabled")))
- eldoc-mode)
-
-;;;###autoload
-(defun turn-on-eldoc-mode ()
- "Unequivocally turn on eldoc-mode (see variable documentation)."
- (interactive)
- (eldoc-mode 1))
-
-(defun eldoc-add-command (cmd)
- "Add COMMAND to the list of commands which causes function arg display.
-If called interactively, completion matches any bound function.
-
-When point is in a sexp, the function args are not reprinted in the echo
-area after every possible interactive command because some of them print
-their own messages in the echo area; the eldoc functions would instantly
-overwrite them unless it is more restrained."
- (interactive "aAdd function to eldoc message commands list: ")
- (and (fboundp cmd)
- (set (intern (symbol-name cmd) eldoc-mode-message-commands) t)))
-
-(defun eldoc-remove-command (cmd)
- "Remove COMMAND from the list of commands which causes function arg display.
-If called interactively, completion matches only those functions currently
-in the list.
-
-When point is in a sexp, the function args are not reprinted in the echo
-area after every possible interactive command because some of them print
-their own messages in the echo area; the eldoc functions would instantly
-overwrite them unless it is more restrained."
- (interactive (list (completing-read
- "Remove function from eldoc message commands list: "
- eldoc-mode-message-commands 'boundp t)))
- (and (symbolp cmd)
- (setq cmd (symbol-name cmd)))
- (if (fboundp 'unintern)
- (unintern cmd eldoc-mode-message-commands)
- (let ((s (intern-soft cmd eldoc-mode-message-commands)))
- (and s
- (makunbound s)))))
-
-(defun eldoc-mode-print-current-symbol-info ()
- (and eldoc-mode
- (not executing-macro)
- ;; Having this mode operate in the minibuffer makes it impossible to
- ;; see what you're doing.
- (not (eq (selected-window) (minibuffer-window)))
- (sit-for eldoc-idle-delay)
- (symbolp this-command)
- (intern-soft (symbol-name this-command) eldoc-mode-message-commands)
- (let ((current-symbol (eldoc-current-symbol))
- (current-fnsym (eldoc-fnsym-in-current-sexp)))
- (cond ((eq current-symbol current-fnsym)
- (eldoc-print-fnsym-args current-fnsym))
- (t
- (or (eldoc-print-var-docstring current-symbol)
- (eldoc-print-fnsym-args current-fnsym)))))))
-
-
-(defun eldoc-print-var-docstring (&optional sym)
- "Print the brief (one-line) documentation string for the variable at point.
-If called with no argument, print the first line of the variable
-documentation string for the symbol at point in the echo area.
-If called with a symbol, print the line for that symbol.
-
-If the entire line cannot fit in the echo area, the variable name may be
-truncated or eliminated entirely from the output to make room.
-Any leading `*' in the docstring (which indicates the variable is a user
-option) is not printed."
- (interactive)
- (let* ((s (or sym (eldoc-current-symbol)))
- (name (symbol-name s))
- (doc (and s (documentation-property s 'variable-documentation t))))
- (and doc
- (save-match-data
- (and (string-match "\n" doc)
- (setq doc (substring doc 0 (match-beginning 0))))
- (and (string-match "^\\*" doc)
- (setq doc (substring doc 1)))
- (let* ((doclen (+ (length name) (length ": ") (length doc)))
- ;; Subtract 1 from window width since emacs seems not to
- ;; write any chars to the last column, at least for some
- ;; terminal types.
- (strip (- doclen (1- (window-width (minibuffer-window))))))
- (cond ((> strip 0)
- (let* ((len (length name)))
- (cond ((>= strip len)
- (eldoc-message "%s" doc))
- (t
- (setq name (substring name 0 (- len strip)))
- (eldoc-message "%s: %s" name doc)))))
- (t
- (eldoc-message "%s: %s" s doc))))
- t))))
-
-
-;;;###autoload
-(defun eldoc-print-fnsym-args (&optional symbol)
- "*Show the defined parameters for the function near point.
-For the function at the beginning of the sexp which point is within, show
-the defined parameters for the function in the echo area.
-This information is extracted directly from the function or macro if it is
-in pure lisp.
-If the emacs function is a subr, the parameters are obtained from the
-documentation string if possible."
- (interactive)
- (let ((sym (or symbol (eldoc-fnsym-in-current-sexp)))
- (printit t)
- (args nil))
- (cond ((not (and (symbolp sym)
- (fboundp sym))))
- ((eq sym (car eldoc-last-data))
- (setq printit nil)
- (setq args (cdr eldoc-last-data)))
- ((subrp (eldoc-symbol-function sym))
- (setq args (eldoc-function-argstring-from-docstring sym))
- (setcdr eldoc-last-data args))
- (t
- (setq args (eldoc-function-argstring sym))
- (setcdr eldoc-last-data args)))
- (and args
- printit
- (eldoc-message "%s: %s" sym args))))
-
-(defun eldoc-fnsym-in-current-sexp ()
- (let* ((p (point))
- (sym (progn
- (while (and (eldoc-forward-sexp-safe -1)
- (> (point) (point-min))))
- (cond ((or (= (point) (point-min))
- (memq (or (char-after (point)) 0)
- '(?\( ?\"))
- ;; If we hit a quotation mark before a paren, we
- ;; are inside a specific string, not a list of
- ;; symbols.
- (eq (or (char-after (1- (point))) 0) ?\"))
- nil)
- (t (condition-case nil
- (read (current-buffer))
- (error nil)))))))
- (goto-char p)
- (and (symbolp sym)
- sym)))
-
-(defun eldoc-function-argstring (fn)
- (let* ((prelim-def (eldoc-symbol-function fn))
- (def (if (eq (car-safe prelim-def) 'macro)
- (cdr prelim-def)
- prelim-def))
- (arglist (cond ((null def) nil)
- ((byte-code-function-p def)
- (if (fboundp 'compiled-function-arglist)
- (funcall 'compiled-function-arglist def)
- (aref def 0)))
- ((eq (car-safe def) 'lambda)
- (nth 1 def))
- (t t))))
- (eldoc-function-argstring-format arglist)))
-
-(defun eldoc-function-argstring-from-docstring (fn)
- (let ((docstring (documentation fn 'raw))
- (doc nil)
- (doclist nil)
- (end nil))
- (save-match-data
- ;; TODO: Move these into a separate table that is iterated over until
- ;; a match is found.
- (cond
- ;; Try first searching for args starting with symbol name.
- ;; This is to avoid matching parenthetical remarks in e.g. sit-for.
- ((string-match (format "^(%s[^\n)]*)$" fn) docstring)
- ;; end does not include trailing ")" sequence.
- (setq end (- (match-end 0) 1))
- (if (string-match " +" docstring (match-beginning 0))
- (setq doc (substring docstring (match-end 0) end))
- (setq doc "")))
-
- ;; Try again not requiring this symbol name in the docstring.
- ;; This will be the case when looking up aliases.
- ((string-match (format "^([^\n)]+)$" fn) docstring)
- ;; end does not include trailing ")" sequence.
- (setq end (- (match-end 0) 1))
- (if (string-match " +" docstring (match-beginning 0))
- (setq doc (substring docstring (match-end 0) end))
- (setq doc "")))
-
- ;; Emacs subr docstring style:
- ;; (fn arg1 arg2 ...): description...
- ((string-match "^([^\n)]+):" docstring)
- ;; end does not include trailing "):" sequence.
- (setq end (- (match-end 0) 2))
- (if (string-match " +" docstring (match-beginning 0))
- (setq doc (substring docstring (match-end 0) end))
- (setq doc "")))
-
- ;; XEmacs subr docstring style:
- ;; "arguments: (arg1 arg2 ...)
- ((string-match "^arguments: (\\([^\n)]+\\))" docstring)
- ;; Also, skip leading paren, but the first word is actually an
- ;; argument, not the function name.
- (setq doc (substring docstring
- (match-beginning 1)
- (match-end 1))))
-
- ;; This finds the argstring for `condition-case'.
- ;; I don't know if there are any others with the same pattern.
- ((string-match (format "^Usage looks like \\((%s[^\n)]*)\\)\\.$" fn)
- docstring)
- ;; end does not include trailing ")" sequence.
- (setq end (- (match-end 1) 1))
- (if (string-match " +" docstring (match-beginning 1))
- (setq doc (substring docstring (match-end 0) end))
- (setq doc "")))
-
- ;; This finds the argstring for `setq-default'.
- ;; I don't know if there are any others with the same pattern.
- ((string-match (format "^[ \t]+\\((%s[^\n)]*)\\)$" fn) docstring)
- ;; end does not include trailing ")" sequence.
- (setq end (- (match-end 1) 1))
- (if (string-match " +" docstring (match-beginning 1))
- (setq doc (substring docstring (match-end 0) end))
- (setq doc "")))
-
- ;; This finds the argstring for `start-process'.
- ;; I don't know if there are any others with the same pattern.
- ((string-match "^Args are +\\([^\n]+\\)$" docstring)
- (setq doc (substring docstring (match-beginning 1) (match-end 1))))
- )
-
- (cond ((not (stringp doc))
- nil)
- ((string-match "&" doc)
- (let ((p 0)
- (l (length doc)))
- (while (< p l)
- (cond ((string-match "[ \t\n]+" doc p)
- (setq doclist
- (cons (substring doc p (match-beginning 0))
- doclist))
- (setq p (match-end 0)))
- (t
- (setq doclist (cons (substring doc p) doclist))
- (setq p l))))
- (eldoc-function-argstring-format (nreverse doclist))))
- (t
- (concat "(" (funcall eldoc-argument-case doc) ")"))))))
-
-(defun eldoc-function-argstring-format (arglist)
- (cond ((not (listp arglist))
- (setq arglist nil))
- ((symbolp (car arglist))
- (setq arglist
- (mapcar (function (lambda (s)
- (if (memq s '(&optional &rest))
- (symbol-name s)
- (funcall eldoc-argument-case
- (symbol-name s)))))
- arglist)))
- ((stringp (car arglist))
- (setq arglist
- (mapcar (function (lambda (s)
- (if (member s '("&optional" "&rest"))
- s
- (funcall eldoc-argument-case s))))
- arglist))))
- (concat "(" (mapconcat 'identity arglist " ") ")"))
-
-
-;; forward-sexp calls scan-sexps, which returns an error if it hits the
-;; beginning or end of the sexp. This returns nil instead.
-(defun eldoc-forward-sexp-safe (&optional count)
- "Move forward across one balanced expression (sexp).
-With argument, do it that many times. Negative arg -COUNT means
-move backward across COUNT balanced expressions.
-Return distance in buffer moved, or nil."
- (or count (setq count 1))
- (condition-case err
- (- (- (point) (progn
- (let ((parse-sexp-ignore-comments t))
- (forward-sexp count))
- (point))))
- (error nil)))
-
-;; Do indirect function resolution if possible.
-(defun eldoc-symbol-function (fsym)
- (let ((defn (and (fboundp fsym)
- (symbol-function fsym))))
- (and (symbolp defn)
- (condition-case err
- (setq defn (indirect-function fsym))
- (error (setq defn nil))))
- defn))
-
-(defun eldoc-current-symbol ()
- (let ((c (char-after (point))))
- (and c
- (memq (char-syntax c) '(?w ?_))
- (intern-soft (current-word)))))
-
-(provide 'eldoc)
-
-;;; eldoc.el ends here
diff --git a/lisp/emacs-lisp/elp.el b/lisp/emacs-lisp/elp.el
deleted file mode 100644
index 7c07e900b38..00000000000
--- a/lisp/emacs-lisp/elp.el
+++ /dev/null
@@ -1,563 +0,0 @@
-;;; elp.el --- Emacs Lisp Profiler
-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-
-;; Author: 1994 Barry A. Warsaw <bwarsaw@cnri.reston.va.us>
-;; Maintainer: tools-help@anthem.nlm.nih.gov
-;; Created: 26-Feb-1994
-;; Version: 2.23
-;; Last Modified: 1994/12/28 22:39:31
-;; Keywords: Emacs Lisp Profile Timing
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-;;
-;; If you want to profile a bunch of functions, set elp-function-list
-;; to the list of symbols, then do a M-x elp-instrument-list. This
-;; hacks those functions so that profiling information is recorded
-;; whenever they are called. To print out the current results, use
-;; M-x elp-results. With elp-reset-after-results set to non-nil,
-;; profiling information will be reset whenever the results are
-;; displayed. You can also reset all profiling info at any time with
-;; M-x elp-reset-all.
-;;
-;; You can also instrument all functions in a package, provided that
-;; the package follows the GNU coding standard of a common textural
-;; prefix. Use M-x elp-instrument-package for this.
-;;
-;; If you want to sort the results, set elp-sort-by-function to some
-;; predicate function. The three most obvious choices are predefined:
-;; elp-sort-by-call-count, elp-sort-by-average-time, and
-;; elp-sort-by-total-time. Also, you can prune from the output, all
-;; functions that have been called fewer than a given number of times
-;; by setting elp-report-limit.
-;;
-;; Elp can instrument byte-compiled functions just as easily as
-;; interpreted functions, but it cannot instrument macros. However,
-;; when you redefine a function (e.g. with eval-defun), you'll need to
-;; re-instrument it with M-x elp-instrument-function. This will also
-;; reset profiling information for that function. Elp can handle
-;; interactive functions (i.e. commands), but of course any time spent
-;; idling for user prompts will show up in the timing results.
-;;
-;; You can also designate a `master' function. Profiling times will
-;; be gathered for instrumented functions only during execution of
-;; this master function. Thus, if you have some defuns like:
-;;
-;; (defun foo () (do-something-time-intensive))
-;; (defun bar () (foo))
-;; (defun baz () (bar) (foo))
-;;
-;; and you want to find out the amount of time spent in bar and foo,
-;; but only during execution of bar, make bar the master. The call of
-;; foo from baz will not add to foo's total timing sums. Use M-x
-;; elp-set-master and M-x elp-unset-master to utilize this feature.
-;; Only one master function can be set at a time.
-
-;; You can restore any function's original function definition with
-;; elp-restore-function. The other instrument, restore, and reset
-;; functions are provided for symmetry.
-
-;; Note that there are plenty of factors that could make the times
-;; reported unreliable, including the accuracy and granularity of your
-;; system clock, and the overhead spent in lisp calculating and
-;; recording the intervals. The latter I figure is pretty constant
-;; so, while the times may not be entirely accurate, I think they'll
-;; give you a good feel for the relative amount of work spent in the
-;; various lisp routines you are profiling. Note further that times
-;; are calculated using wall-clock time, so other system load will
-;; affect accuracy too.
-
-;; Here is a list of variable you can use to customize elp:
-;; elp-function-list
-;; elp-reset-after-results
-;; elp-sort-by-function
-;; elp-report-limit
-;;
-;; Here is a list of the interactive commands you can use:
-;; elp-instrument-function
-;; elp-restore-function
-;; elp-instrument-list
-;; elp-restore-list
-;; elp-instrument-package
-;; elp-restore-all
-;; elp-reset-function
-;; elp-reset-list
-;; elp-reset-all
-;; elp-set-master
-;; elp-unset-master
-;; elp-results
-;; elp-submit-bug-report
-
-;; Note that there are plenty of factors that could make the times
-;; reported unreliable, including the accuracy and granularity of your
-;; system clock, and the overhead spent in lisp calculating and
-;; recording the intervals. I figure the latter is pretty constant,
-;; so while the times may not be entirely accurate, I think they'll
-;; give you a good feel for the relative amount of work spent in the
-;; various lisp routines you are profiling. Note further that times
-;; are calculated using wall-clock time, so other system load will
-;; affect accuracy too. You cannot profile anything longer than ~18
-;; hours since I throw away the most significant 16 bits of seconds
-;; returned by current-time: 2^16 == 65536 seconds == ~1092 minutes ==
-;; ~18 hours. I doubt you will ever want to profile stuff on the
-;; order of 18 hours anyway.
-
-;;; Background:
-
-;; This program is based on the only two existing Emacs Lisp profilers
-;; that I'm aware of, Boaz Ben-Zvi's profile.el, and Root Boy Jim's
-;; profiler.el. Both were written for Emacs 18 and both were pretty
-;; good first shots at profiling, but I found that they didn't provide
-;; the functionality or interface that I wanted. So I wrote this.
-;; I've tested elp in GNU Emacs 19 and in GNU XEmacs. There's no
-;; point in even trying to make this work with Emacs 18.
-
-;; Unlike previous profilers, elp uses Emacs 19's built-in function
-;; current-time to return interval times. This obviates the need for
-;; both an external C program and Emacs processes to communicate with
-;; such a program, and thus simplifies the package as a whole.
-
-;;; Code:
-
-
-;; start user configuration variables
-;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-
-(defvar elp-function-list nil
- "*List of function to profile.")
-
-(defvar elp-reset-after-results t
- "*Non-nil means reset all profiling info after results are displayed.
-Results are displayed with the `elp-results' command.")
-
-(defvar elp-sort-by-function nil
- "*Non-nil specifies elp results sorting function.
-These functions are currently available:
-
- elp-sort-by-call-count -- sort by the highest call count
- elp-sort-by-total-time -- sort by the highest total time
- elp-sort-by-average-time -- sort by the highest average times
-
-You can write you're own sort function. It should adhere to the
-interface specified by the PRED argument for the `sort' defun. Each
-\"element of LIST\" is really a 4 element vector where element 0 is
-the call count, element 1 is the total time spent in the function,
-element 2 is the average time spent in the function, and element 3 is
-the symbol's name string.")
-
-(defvar elp-report-limit nil
- "*Prevents some functions from being displayed in the results buffer.
-If a number, no function that has been called fewer than that number
-of times will be displayed in the output buffer. If nil, all
-functions will be displayed.")
-
-
-;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-;; end user configuration variables
-
-
-(defconst elp-version "2.23"
- "ELP version number.")
-
-(defconst elp-help-address "tools-help@anthem.nlm.nih.gov"
- "Address accepting submissions of bug reports and questions.")
-
-(defvar elp-results-buffer "*ELP Profiling Results*"
- "Buffer name for outputting profiling results.")
-
-(defconst elp-timer-info-property 'elp-info
- "ELP information property name.")
-
-(defvar elp-all-instrumented-list nil
- "List of all functions currently being instrumented.")
-
-(defvar elp-record-p t
- "Controls whether functions should record times or not.
-This variable is set by the master function.")
-
-(defvar elp-master nil
- "Master function symbol.")
-
-
-;;;###autoload
-(defun elp-instrument-function (funsym)
- "Instrument FUNSYM for profiling.
-FUNSYM must be a symbol of a defined function."
- (interactive "aFunction to instrument: ")
- ;; TBD what should we do if the function is already instrumented???
- (let* ((funguts (symbol-function funsym))
- (infovec (vector 0 0 funguts))
- (newguts '(lambda (&rest args))))
- ;; we cannot profile macros
- (and (eq (car-safe funguts) 'macro)
- (error "ELP cannot profile macro %s" funsym))
- ;; put rest of newguts together
- (if (commandp funsym)
- (setq newguts (append newguts '((interactive)))))
- (setq newguts (append newguts (list
- (list 'elp-wrapper
- (list 'quote funsym)
- (list 'and
- '(interactive-p)
- (not (not (commandp funsym))))
- 'args))))
- ;; to record profiling times, we set the symbol's function
- ;; definition so that it runs the elp-wrapper function with the
- ;; function symbol as an argument. We place the old function
- ;; definition on the info vector.
- ;;
- ;; The info vector data structure is a 3 element vector. The 0th
- ;; element is the call-count, i.e. the total number of times this
- ;; function has been entered. This value is bumped up on entry to
- ;; the function so that non-local exists are still recorded. TBD:
- ;; I haven't tested non-local exits at all, so no guarantees.
- ;;
- ;; The 1st element is the total amount of time in usecs that have
- ;; been spent inside this function. This number is added to on
- ;; function exit.
- ;;
- ;; The 2nd element is the old function definition list. This gets
- ;; funcall'd in between start/end time retrievals. I believe that
- ;; this lets us profile even byte-compiled functions.
-
- ;; put the info vector on the property list
- (put funsym elp-timer-info-property infovec)
-
- ;; set the symbol's new profiling function definition to run
- ;; elp-wrapper
- (fset funsym newguts)
-
- ;; add this function to the instrumentation list
- (or (memq funsym elp-all-instrumented-list)
- (setq elp-all-instrumented-list
- (cons funsym elp-all-instrumented-list)))
- ))
-
-;;;###autoload
-(defun elp-restore-function (funsym)
- "Restore an instrumented function to its original definition.
-Argument FUNSYM is the symbol of a defined function."
- (interactive "aFunction to restore: ")
- (let ((info (get funsym elp-timer-info-property)))
- ;; delete the function from the all instrumented list
- (setq elp-all-instrumented-list
- (delq funsym elp-all-instrumented-list))
-
- ;; if the function was the master, reset the master
- (if (eq funsym elp-master)
- (setq elp-master nil
- elp-record-p t))
-
- ;; zap the properties
- (put funsym elp-timer-info-property nil)
-
- ;; restore the original function definition, but if the function
- ;; wasn't instrumented do nothing. we do this after the above
- ;; because its possible the function got un-instrumented due to
- ;; circumstances beyond our control. Also, check to make sure
- ;; that the current function symbol points to elp-wrapper. If
- ;; not, then the user probably did an eval-defun while the
- ;; function was instrumented and we don't want to destroy the new
- ;; definition.
- (and info
- (assq 'elp-wrapper (symbol-function funsym))
- (fset funsym (aref info 2)))))
-
-;;;###autoload
-(defun elp-instrument-list (&optional list)
- "Instrument for profiling, all functions in `elp-function-list'.
-Use optional LIST if provided instead."
- (interactive "PList of functions to instrument: ")
- (let ((list (or list elp-function-list)))
- (mapcar 'elp-instrument-function list)))
-
-;;;###autoload
-(defun elp-instrument-package (prefix)
- "Instrument for profiling, all functions which start with PREFIX.
-For example, to instrument all ELP functions, do the following:
-
- \\[elp-instrument-package] RET elp- RET"
- (interactive "sPrefix of package to instrument: ")
- (elp-instrument-list
- (mapcar 'intern (all-completions prefix obarray
- (function
- (lambda (sym)
- (and (fboundp sym)
- (not (memq (car-safe
- (symbol-function sym))
- '(macro keymap autoload))))))))))
-
-(defun elp-restore-list (&optional list)
- "Restore the original definitions for all functions in `elp-function-list'.
-Use optional LIST if provided instead."
- (interactive "PList of functions to restore: ")
- (let ((list (or list elp-function-list)))
- (mapcar 'elp-restore-function list)))
-
-(defun elp-restore-all ()
- "Restores the original definitions of all functions being profiled."
- (interactive)
- (elp-restore-list elp-all-instrumented-list))
-
-
-(defun elp-reset-function (funsym)
- "Reset the profiling information for FUNSYM."
- (interactive "aFunction to reset: ")
- (let ((info (get funsym elp-timer-info-property)))
- (or info
- (error "%s is not instrumented for profiling." funsym))
- (aset info 0 0) ;reset call counter
- (aset info 1 0.0) ;reset total time
- ;; don't muck with aref 2 as that is the old symbol definition
- ))
-
-(defun elp-reset-list (&optional list)
- "Reset the profiling information for all functions in `elp-function-list'.
-Use optional LIST if provided instead."
- (interactive "PList of functions to reset: ")
- (let ((list (or list elp-function-list)))
- (mapcar 'elp-reset-function list)))
-
-(defun elp-reset-all ()
- "Reset the profiling information for all functions being profiled."
- (interactive)
- (elp-reset-list elp-all-instrumented-list))
-
-(defun elp-set-master (funsym)
- "Set the master function for profiling."
- (interactive "aMaster function: ")
- ;; when there's a master function, recording is turned off by
- ;; default
- (setq elp-master funsym
- elp-record-p nil)
- ;; make sure master function is instrumented
- (or (memq funsym elp-all-instrumented-list)
- (elp-instrument-function funsym)))
-
-(defun elp-unset-master ()
- "Unsets the master function."
- (interactive)
- ;; when there's no master function, recording is turned on by default.
- (setq elp-master nil
- elp-record-p t))
-
-
-(defsubst elp-get-time ()
- ;; get current time in seconds and microseconds. I throw away the
- ;; most significant 16 bits of seconds since I doubt we'll ever want
- ;; to profile lisp on the order of 18 hours. See notes at top of file.
- (let ((now (current-time)))
- (+ (float (nth 1 now)) (/ (float (nth 2 now)) 1000000.0))))
-
-(defun elp-wrapper (funsym interactive-p args)
- "This function has been instrumented for profiling by the ELP.
-ELP is the Emacs Lisp Profiler. To restore the function to its
-original definition, use \\[elp-restore-function] or \\[elp-restore-all]."
- ;; turn on recording if this is the master function
- (if (and elp-master
- (eq funsym elp-master))
- (setq elp-record-p t))
- ;; get info vector and original function symbol
- (let* ((info (get funsym elp-timer-info-property))
- (func (aref info 2))
- result)
- (or func
- (error "%s is not instrumented for profiling." funsym))
- (if (not elp-record-p)
- ;; when not recording, just call the original function symbol
- ;; and return the results.
- (setq result
- (if interactive-p
- (call-interactively func)
- (apply func args)))
- ;; we are recording times
- (let ((enter-time (elp-get-time)))
- ;; increment the call-counter
- (aset info 0 (1+ (aref info 0)))
- ;; now call the old symbol function, checking to see if it
- ;; should be called interactively. make sure we return the
- ;; correct value
- (setq result
- (if interactive-p
- (call-interactively func)
- (apply func args)))
- ;; calculate total time in function
- (aset info 1 (+ (aref info 1) (- (elp-get-time) enter-time)))
- ))
- ;; turn off recording if this is the master function
- (if (and elp-master
- (eq funsym elp-master))
- (setq elp-record-p nil))
- result))
-
-
-;; shut the byte-compiler up
-(defvar elp-field-len nil)
-(defvar elp-cc-len nil)
-(defvar elp-at-len nil)
-(defvar elp-et-len nil)
-
-(defun elp-sort-by-call-count (vec1 vec2)
- ;; sort by highest call count. See `sort'.
- (>= (aref vec1 0) (aref vec2 0)))
-
-(defun elp-sort-by-total-time (vec1 vec2)
- ;; sort by highest total time spent in function. See `sort'.
- (>= (aref vec1 1) (aref vec2 1)))
-
-(defun elp-sort-by-average-time (vec1 vec2)
- ;; sort by highest average time spent in function. See `sort'.
- (>= (aref vec1 2) (aref vec2 2)))
-
-(defsubst elp-pack-number (number width)
- ;; pack the NUMBER string into WIDTH characters, watching out for
- ;; very small or large numbers
- (if (<= (length number) width)
- number
- ;; check for very large or small numbers
- (if (string-match "^\\(.*\\)\\(e[+-].*\\)$" number)
- (concat (substring
- (substring number (match-beginning 1) (match-end 1))
- 0
- (- width (match-end 2) (- (match-beginning 2)) 3))
- "..."
- (substring number (match-beginning 2) (match-end 2)))
- (concat (substring number 0 width)))))
-
-(defun elp-output-result (resultvec)
- ;; output the RESULTVEC into the results buffer. RESULTVEC is a 4 or
- ;; more element vector where aref 0 is the call count, aref 1 is the
- ;; total time spent in the function, aref 2 is the average time
- ;; spent in the function, and aref 3 is the symbol's string
- ;; name. All other elements in the vector are ignored.
- (let* ((cc (aref resultvec 0))
- (tt (aref resultvec 1))
- (at (aref resultvec 2))
- (symname (aref resultvec 3))
- callcnt totaltime avetime)
- (setq callcnt (number-to-string cc)
- totaltime (number-to-string tt)
- avetime (number-to-string at))
- ;; possibly prune the results
- (if (and elp-report-limit
- (numberp elp-report-limit)
- (< cc elp-report-limit))
- nil
- (insert symname)
- (insert-char 32 (+ elp-field-len (- (length symname)) 2))
- ;; print stuff out, formatting it nicely
- (insert callcnt)
- (insert-char 32 (+ elp-cc-len (- (length callcnt)) 2))
- (let ((ttstr (elp-pack-number totaltime elp-et-len))
- (atstr (elp-pack-number avetime elp-at-len)))
- (insert ttstr)
- (insert-char 32 (+ elp-et-len (- (length ttstr)) 2))
- (insert atstr))
- (insert "\n"))))
-
-;;;###autoload
-(defun elp-results ()
- "Display current profiling results.
-If `elp-reset-after-results' is non-nil, then current profiling
-information for all instrumented functions are reset after results are
-displayed."
- (interactive)
- (let ((curbuf (current-buffer))
- (resultsbuf (get-buffer-create elp-results-buffer)))
- (set-buffer resultsbuf)
- (erase-buffer)
- (beginning-of-buffer)
- ;; get the length of the longest function name being profiled
- (let* ((longest 0)
- (title "Function Name")
- (titlelen (length title))
- (elp-field-len titlelen)
- (cc-header "Call Count")
- (elp-cc-len (length cc-header))
- (et-header "Elapsed Time")
- (elp-et-len (length et-header))
- (at-header "Average Time")
- (elp-at-len (length at-header))
- (resvec
- (mapcar
- (function
- (lambda (funsym)
- (let* ((info (get funsym elp-timer-info-property))
- (symname (format "%s" funsym))
- (cc (aref info 0))
- (tt (aref info 1)))
- (if (not info)
- (insert "No profiling information found for: "
- symname)
- (setq longest (max longest (length symname)))
- (vector cc tt (if (zerop cc)
- 0.0 ;avoid arithmetic div-by-zero errors
- (/ (float tt) (float cc)))
- symname)))))
- elp-all-instrumented-list))
- ) ; end let*
- (insert title)
- (if (> longest titlelen)
- (progn
- (insert-char 32 (- longest titlelen))
- (setq elp-field-len longest)))
- (insert " " cc-header " " et-header " " at-header "\n")
- (insert-char ?= elp-field-len)
- (insert " ")
- (insert-char ?= elp-cc-len)
- (insert " ")
- (insert-char ?= elp-et-len)
- (insert " ")
- (insert-char ?= elp-at-len)
- (insert "\n")
- ;; if sorting is enabled, then sort the results list. in either
- ;; case, call elp-output-result to output the result in the
- ;; buffer
- (if elp-sort-by-function
- (setq resvec (sort resvec elp-sort-by-function)))
- (mapcar 'elp-output-result resvec))
- ;; now pop up results buffer
- (set-buffer curbuf)
- (pop-to-buffer resultsbuf)
- ;; reset profiling info if desired
- (and elp-reset-after-results
- (elp-reset-all))))
-
-
-(eval-when-compile
- (require 'reporter))
-
-;;;###autoload
-(defun elp-submit-bug-report ()
- "Submit via mail, a bug report on elp."
- (interactive)
- (and
- (y-or-n-p "Do you want to submit a report on elp? ")
- (require 'reporter)
- (reporter-submit-bug-report
- elp-help-address (concat "elp " elp-version)
- '(elp-report-limit
- elp-reset-after-results
- elp-sort-by-function))))
-
-
-(provide 'elp)
-
-;; elp.el ends here
diff --git a/lisp/emacs-lisp/eval-reg.el b/lisp/emacs-lisp/eval-reg.el
deleted file mode 100644
index d97a4ea46de..00000000000
--- a/lisp/emacs-lisp/eval-reg.el
+++ /dev/null
@@ -1,219 +0,0 @@
-;;; eval-reg.el --- Redefine eval-region, and subrs that use it, in Lisp
-
-;; Copyright (C) 1994, 1996 Daniel LaLiberte
-
-;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
-;; Keywords: lisp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; eval-region, eval-buffer, and eval-current-buffer are redefined in
-;; Lisp to allow customizations by Lisp code. eval-region calls
-;; `read', `eval', and `prin1', so Lisp replacements of these
-;; functions will affect eval-region and anything else that calls it.
-;; eval-buffer and eval-current-buffer are redefined in Lisp to call
-;; eval-region on the buffer.
-
-;; Because of dynamic binding, all local variables are protected from
-;; being seen by eval by giving them funky names. But variables in
-;; routines that call eval-region are similarly exposed.
-
-;; Perhaps this should be one of several files in an `elisp' package
-;; that replaces Emacs Lisp subroutines with Lisp versions of the
-;; same.
-
-;; Eval-region may be installed, after loading, by calling:
-;; (elisp-eval-region-install). Installation can be undone with:
-;; (elisp-eval-region-uninstall).
-
-;;; Code:
-
-'(defpackage "elisp-eval-region"
- (:nicknames "elisp")
- (:use "elisp")
- (:export
- elisp-eval-region-install
- elisp-eval-region-uninstall
- elisp-eval-region-level
- with-elisp-eval-region
- eval-region
- eval-buffer
- eval-current-buffer
- ))
-'(in-package elisp-eval-region)
-
-;; Save standard versions.
-(if (not (fboundp 'original-eval-region))
- (defalias 'original-eval-region (symbol-function 'eval-region)))
-(if (not (fboundp 'original-eval-buffer))
- (defalias 'original-eval-buffer
- (if (fboundp 'eval-buffer) ;; only in Emacs 19
- (symbol-function 'eval-buffer)
- 'undefined)))
-(if (not (fboundp 'original-eval-current-buffer))
- (defalias 'original-eval-current-buffer
- (symbol-function 'eval-current-buffer)))
-
-(defvar elisp-eval-region-level 0
- "If the value is 0, use the original version of `elisp-eval-region'.
-Callers of `elisp-eval-region' should increment `elisp-eval-region-level'
-while the Lisp version should be used. Installing `elisp-eval-region'
-increments it once, and uninstalling decrements it.")
-
-;; Installing and uninstalling should always be used in pairs,
-;; or just install once and never uninstall.
-(defun elisp-eval-region-install ()
- (interactive)
- (defalias 'eval-region 'elisp-eval-region)
- (defalias 'eval-buffer 'elisp-eval-buffer)
- (defalias 'eval-current-buffer 'elisp-eval-current-buffer)
- (setq elisp-eval-region-level (1+ elisp-eval-region-level)))
-
-(defun elisp-eval-region-uninstall ()
- (interactive)
- (if (> 1 elisp-eval-region-level)
- (setq elisp-eval-region-level (1- elisp-eval-region-level))
- (setq elisp-eval-region-level 0)
- (defalias 'eval-region (symbol-function 'original-eval-region))
- (defalias 'eval-buffer (symbol-function 'original-eval-buffer))
- (defalias 'eval-current-buffer
- (symbol-function 'original-eval-current-buffer))
- ))
-
-(put 'with-elisp-eval-region 'lisp-indent-function 1)
-(put 'with-elisp-eval-region 'lisp-indent-hook 1)
-(put 'with-elisp-eval-region 'edebug-form-spec t)
-
-(defmacro with-elisp-eval-region (flag &rest body)
- "If FLAG is nil, decrement `eval-region-level' while executing BODY.
-The effect of decrementing all the way to zero is that `eval-region'
-will use the original `eval-region', which may be the Emacs subr or some
-previous redefinition. Before calling this macro, this package should
-already have been installed, using `elisp-eval-region-install', which
-increments the count once. So if another package still requires the
-Lisp version of the code, the count will still be non-zero.
-
-The count is not bound locally by this macro, so changes by BODY to
-its value will not be lost."
- (` (let ((elisp-code (function (lambda () (,@ body)))))
- (if (not (, flag))
- (unwind-protect
- (progn
- (setq elisp-eval-region-level (1- elisp-eval-region-level))
- (funcall elisp-code))
- (setq elisp-eval-region-level (1+ elisp-eval-region-level)))
- (funcall elisp-code)))))
-
-
-(defun elisp-eval-region (elisp-start elisp-end &optional elisp-output)
- "Execute the region as Lisp code.
-When called from programs, expects two arguments,
-giving starting and ending indices in the current buffer
-of the text to be executed.
-Programs can pass third argument PRINTFLAG which controls printing of output:
-nil means discard it; anything else is stream for print.
-
-This version, from `eval-reg.el', allows Lisp customization of read,
-eval, and the printer."
-
- ;; Because this doesn't narrow to the region, one other difference
- ;; concerns inserting whitespace after the expression being evaluated.
-
- (interactive "r")
- (if (= 0 elisp-eval-region-level)
- (original-eval-region elisp-start elisp-end elisp-output)
- (let ((elisp-pnt (point))
- (elisp-buf (current-buffer));; Outside buffer
- (elisp-inside-buf (current-buffer));; Buffer current while evalling
- ;; Mark the end because it may move.
- (elisp-end-marker (set-marker (make-marker) elisp-end))
- elisp-form
- elisp-val)
- (goto-char elisp-start)
- (elisp-skip-whitespace)
- (while (< (point) elisp-end-marker)
- (setq elisp-form (read elisp-buf))
-
- (let ((elisp-current-buffer (current-buffer)))
- ;; Restore the inside current-buffer.
- (set-buffer elisp-inside-buf)
- (setq elisp-val (eval elisp-form))
- ;; Remember current buffer for next time.
- (setq elisp-inside-buf (current-buffer))
- ;; Should this be protected?
- (set-buffer elisp-current-buffer))
-
- (if elisp-output
- (let ((standard-output (or elisp-output t)))
- (setq values (cons elisp-val values))
- (if (eq standard-output t)
- (prin1 elisp-val)
- (princ "\n")
- (prin1 elisp-val)
- (princ "\n")
- )))
- (goto-char (min (max elisp-end-marker (point))
- (progn (elisp-skip-whitespace) (point))))
- ) ; while
- (if elisp-output nil
- ;; like save-excursion recovery, but done only if no error occurs
- ;; but mark is not restored
- (set-buffer elisp-buf)
- (goto-char elisp-pnt))
- nil)))
-
-
-(defun elisp-skip-whitespace ()
- ;; Leave point before the next token, skipping white space and comments.
- (skip-chars-forward " \t\r\n\f")
- (while (= (following-char) ?\;)
- (skip-chars-forward "^\n\r") ; skip the comment
- (skip-chars-forward " \t\r\n\f")))
-
-
-(defun elisp-eval-current-buffer (&optional elisp-output)
- "Execute the current buffer as Lisp code.
-Programs can pass argument PRINTFLAG which controls printing of output:
-nil means discard it; anything else is stream for print.
-
-This version calls `eval-region' on the whole buffer."
- ;; The standard eval-current-buffer doesn't use eval-region.
- (interactive)
- (eval-region (point-min) (point-max) elisp-output))
-
-
-(defun elisp-eval-buffer (&optional elisp-bufname elisp-printflag)
- "Execute BUFFER as Lisp code. Use current buffer if BUFFER is nil.
-Programs can pass argument PRINTFLAG which controls printing of
-output: nil means discard it; anything else is stream for print.
-
-This version calls `eval-region' on the whole buffer."
- (interactive)
- (if (null elisp-bufname)
- (setq elisp-bufname (current-buffer)))
- (save-excursion
- (set-buffer (or (get-buffer elisp-bufname)
- (error "No such buffer: %s" elisp-bufname)))
- (eval-region (point-min) (point-max) elisp-printflag)))
-
-
-(provide 'eval-reg)
-
-;;; eval-reg.el ends here
diff --git a/lisp/emacs-lisp/float.el b/lisp/emacs-lisp/float.el
deleted file mode 100644
index f4fd9ae0ec9..00000000000
--- a/lisp/emacs-lisp/float.el
+++ /dev/null
@@ -1,458 +0,0 @@
-;;; float.el --- floating point arithmetic package.
-
-;; Copyright (C) 1986 Free Software Foundation, Inc.
-
-;; Author: Bill Rosenblatt
-;; Maintainer: FSF
-;; Keywords: extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Floating point numbers are represented by dot-pairs (mant . exp)
-;; where mant is the 24-bit signed integral mantissa and exp is the
-;; base 2 exponent.
-;;
-;; Emacs LISP supports a 24-bit signed integer data type, which has a
-;; range of -(2**23) to +(2**23)-1, or -8388608 to 8388607 decimal.
-;; This gives six significant decimal digit accuracy. Exponents can
-;; be anything in the range -(2**23) to +(2**23)-1.
-;;
-;; User interface:
-;; function f converts from integer to floating point
-;; function string-to-float converts from string to floating point
-;; function fint converts a floating point to integer (with truncation)
-;; function float-to-string converts from floating point to string
-;;
-;; Caveats:
-;; - Exponents outside of the range of +/-100 or so will cause certain
-;; functions (especially conversion routines) to take forever.
-;; - Very little checking is done for fixed point overflow/underflow.
-;; - No checking is done for over/underflow of the exponent
-;; (hardly necessary when exponent can be 2**23).
-;;
-;;
-;; Bill Rosenblatt
-;; June 20, 1986
-;;
-
-;;; Code:
-
-;; fundamental implementation constants
-(defconst exp-base 2
- "Base of exponent in this floating point representation.")
-
-(defconst mantissa-bits 24
- "Number of significant bits in this floating point representation.")
-
-(defconst decimal-digits 6
- "Number of decimal digits expected to be accurate.")
-
-(defconst expt-digits 2
- "Maximum permitted digits in a scientific notation exponent.")
-
-;; other constants
-(defconst maxbit (1- mantissa-bits)
- "Number of highest bit")
-
-(defconst mantissa-maxval (1- (ash 1 maxbit))
- "Maximum permissible value of mantissa")
-
-(defconst mantissa-minval (ash 1 maxbit)
- "Minimum permissible value of mantissa")
-
-(defconst floating-point-regexp
- "^[ \t]*\\(-?\\)\\([0-9]*\\)\
-\\(\\.\\([0-9]*\\)\\|\\)\
-\\(\\(\\([Ee]\\)\\(-?\\)\\([0-9][0-9]*\\)\\)\\|\\)[ \t]*$"
- "Regular expression to match floating point numbers. Extract matches:
-1 - minus sign
-2 - integer part
-4 - fractional part
-8 - minus sign for power of ten
-9 - power of ten
-")
-
-(defconst high-bit-mask (ash 1 maxbit)
- "Masks all bits except the high-order (sign) bit.")
-
-(defconst second-bit-mask (ash 1 (1- maxbit))
- "Masks all bits except the highest-order magnitude bit")
-
-;; various useful floating point constants
-(setq _f0 '(0 . 1))
-
-(setq _f1/2 '(4194304 . -23))
-
-(setq _f1 '(4194304 . -22))
-
-(setq _f10 '(5242880 . -19))
-
-;; support for decimal conversion routines
-(setq powers-of-10 (make-vector (1+ decimal-digits) _f1))
-(aset powers-of-10 1 _f10)
-(aset powers-of-10 2 '(6553600 . -16))
-(aset powers-of-10 3 '(8192000 . -13))
-(aset powers-of-10 4 '(5120000 . -9))
-(aset powers-of-10 5 '(6400000 . -6))
-(aset powers-of-10 6 '(8000000 . -3))
-
-(setq all-decimal-digs-minval (aref powers-of-10 (1- decimal-digits))
- highest-power-of-10 (aref powers-of-10 decimal-digits))
-
-(defun fashl (fnum) ; floating-point arithmetic shift left
- (cons (ash (car fnum) 1) (1- (cdr fnum))))
-
-(defun fashr (fnum) ; floating point arithmetic shift right
- (cons (ash (car fnum) -1) (1+ (cdr fnum))))
-
-(defun normalize (fnum)
- (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))
- (setq fnum (fashl fnum)))
- (setq fnum _f0))) ; "standard 0"
- fnum)
-
-(defun abs (n) ; integer absolute value
- (if (>= n 0) n (- n)))
-
-(defun fabs (fnum) ; re-normalize after taking abs value
- (normalize (cons (abs (car fnum)) (cdr fnum))))
-
-(defun xor (a b) ; logical exclusive or
- (and (or a b) (not (and a b))))
-
-(defun same-sign (a b) ; two f-p numbers have same sign?
- (not (xor (natnump (car a)) (natnump (car b)))))
-
-(defun extract-match (str i) ; used after string-match
- (condition-case ()
- (substring str (match-beginning i) (match-end i))
- (error "")))
-
-;; support for the multiplication function
-(setq halfword-bits (/ mantissa-bits 2) ; bits in a halfword
- masklo (1- (ash 1 halfword-bits)) ; isolate the lower halfword
- maskhi (lognot masklo) ; isolate the upper halfword
- round-limit (ash 1 (/ halfword-bits 2)))
-
-(defun hihalf (n) ; return high halfword, shifted down
- (ash (logand n maskhi) (- halfword-bits)))
-
-(defun lohalf (n) ; return low halfword
- (logand n masklo))
-
-;; Visible functions
-
-;; Arithmetic functions
-(defun f+ (a1 a2)
- "Returns the sum of two floating point numbers."
- (let ((f1 (fmax a1 a2))
- (f2 (fmin a1 a2)))
- (if (same-sign a1 a2)
- (setq f1 (fashr f1) ; shift right to avoid overflow
- f2 (fashr f2)))
- (normalize
- (cons (+ (car f1) (ash (car f2) (- (cdr f2) (cdr f1))))
- (cdr f1)))))
-
-(defun f- (a1 &optional a2) ; unary or binary minus
- "Returns the difference of two floating point numbers."
- (if a2
- (f+ a1 (f- a2))
- (normalize (cons (- (car a1)) (cdr a1)))))
-
-(defun f* (a1 a2) ; multiply in halfword chunks
- "Returns the product of two floating point numbers."
- (let* ((i1 (car (fabs a1)))
- (i2 (car (fabs a2)))
- (sign (not (same-sign a1 a2)))
- (prodlo (+ (hihalf (* (lohalf i1) (lohalf i2)))
- (lohalf (* (hihalf i1) (lohalf i2)))
- (lohalf (* (lohalf i1) (hihalf i2)))))
- (prodhi (+ (* (hihalf i1) (hihalf i2))
- (hihalf (* (hihalf i1) (lohalf i2)))
- (hihalf (* (lohalf i1) (hihalf i2)))
- (hihalf prodlo))))
- (if (> (lohalf prodlo) round-limit)
- (setq prodhi (1+ prodhi))) ; round off truncated bits
- (normalize
- (cons (if sign (- prodhi) prodhi)
- (+ (cdr (fabs a1)) (cdr (fabs a2)) mantissa-bits)))))
-
-(defun f/ (a1 a2) ; SLOW subtract-and-shift algorithm
- "Returns the quotient of two floating point numbers."
- (if (zerop (car a2)) ; if divide by 0
- (signal 'arith-error (list "attempt to divide by zero" a1 a2))
- (let ((bits (1- maxbit))
- (quotient 0)
- (dividend (car (fabs a1)))
- (divisor (car (fabs a2)))
- (sign (not (same-sign a1 a2))))
- (while (natnump bits)
- (if (< (- dividend divisor) 0)
- (setq quotient (ash quotient 1))
- (setq quotient (1+ (ash quotient 1))
- dividend (- dividend divisor)))
- (setq dividend (ash dividend 1)
- bits (1- bits)))
- (normalize
- (cons (if sign (- quotient) quotient)
- (- (cdr (fabs a1)) (cdr (fabs a2)) (1- maxbit)))))))
-
-(defun f% (a1 a2)
- "Returns the remainder of first floating point number divided by second."
- (f- a1 (f* (ftrunc (f/ a1 a2)) a2)))
-
-
-;; Comparison functions
-(defun f= (a1 a2)
- "Returns t if two floating point numbers are equal, nil otherwise."
- (equal a1 a2))
-
-(defun f> (a1 a2)
- "Returns t if first floating point number is greater than second,
-nil otherwise."
- (cond ((and (natnump (car a1)) (< (car a2) 0))
- t) ; a1 nonnegative, a2 negative
- ((and (> (car a1) 0) (<= (car a2) 0))
- t) ; a1 positive, a2 nonpositive
- ((and (<= (car a1) 0) (natnump (car a2)))
- nil) ; a1 nonpos, a2 nonneg
- ((/= (cdr a1) (cdr a2)) ; same signs. exponents differ
- (> (cdr a1) (cdr a2))) ; compare the mantissas.
- (t
- (> (car a1) (car a2))))) ; same exponents.
-
-(defun f>= (a1 a2)
- "Returns t if first floating point number is greater than or equal to
-second, nil otherwise."
- (or (f> a1 a2) (f= a1 a2)))
-
-(defun f< (a1 a2)
- "Returns t if first floating point number is less than second,
-nil otherwise."
- (not (f>= a1 a2)))
-
-(defun f<= (a1 a2)
- "Returns t if first floating point number is less than or equal to
-second, nil otherwise."
- (not (f> a1 a2)))
-
-(defun f/= (a1 a2)
- "Returns t if first floating point number is not equal to second,
-nil otherwise."
- (not (f= a1 a2)))
-
-(defun fmin (a1 a2)
- "Returns the minimum of two floating point numbers."
- (if (f< a1 a2) a1 a2))
-
-(defun fmax (a1 a2)
- "Returns the maximum of two floating point numbers."
- (if (f> a1 a2) a1 a2))
-
-(defun fzerop (fnum)
- "Returns t if the floating point number is zero, nil otherwise."
- (= (car fnum) 0))
-
-(defun floatp (fnum)
- "Returns t if the arg is a floating point number, nil otherwise."
- (and (consp fnum) (integerp (car fnum)) (integerp (cdr fnum))))
-
-;; Conversion routines
-(defun f (int)
- "Convert the integer argument to floating point, like a C cast operator."
- (normalize (cons int '0)))
-
-(defun int-to-hex-string (int)
- "Convert the integer argument to a C-style hexadecimal string."
- (let ((shiftval -20)
- (str "0x")
- (hex-chars "0123456789ABCDEF"))
- (while (<= shiftval 0)
- (setq str (concat str (char-to-string
- (aref hex-chars
- (logand (lsh int shiftval) 15))))
- shiftval (+ shiftval 4)))
- str))
-
-(defun ftrunc (fnum) ; truncate fractional part
- "Truncate the fractional part of a floating point number."
- (cond ((natnump (cdr fnum)) ; it's all integer, return number as is
- fnum)
- ((<= (cdr fnum) (- maxbit)) ; it's all fractional, return 0
- '(0 . 1))
- (t ; otherwise mask out fractional bits
- (let ((mant (car fnum)) (exp (cdr fnum)))
- (normalize
- (cons (if (natnump mant) ; if negative, use absolute value
- (ash (ash mant exp) (- exp))
- (- (ash (ash (- mant) exp) (- exp))))
- exp))))))
-
-(defun fint (fnum) ; truncate and convert to integer
- "Convert the floating point number to integer, with truncation,
-like a C cast operator."
- (let* ((tf (ftrunc fnum)) (tint (car tf)) (texp (cdr tf)))
- (cond ((>= texp mantissa-bits) ; too high, return "maxint"
- mantissa-maxval)
- ((<= texp (- mantissa-bits)) ; too low, return "minint"
- mantissa-minval)
- (t ; in range
- (ash tint texp))))) ; shift so that exponent is 0
-
-(defun float-to-string (fnum &optional sci)
- "Convert the floating point number to a decimal string.
-Optional second argument non-nil means use scientific notation."
- (let* ((value (fabs fnum)) (sign (< (car fnum) 0))
- (power 0) (result 0) (str "")
- (temp 0) (pow10 _f1))
-
- (if (f= fnum _f0)
- "0"
- (if (f>= value _f1) ; find largest power of 10 <= value
- (progn ; value >= 1, power is positive
- (while (f<= (setq temp (f* pow10 highest-power-of-10)) value)
- (setq pow10 temp
- power (+ power decimal-digits)))
- (while (f<= (setq temp (f* pow10 _f10)) value)
- (setq pow10 temp
- power (1+ power))))
- (progn ; value < 1, power is negative
- (while (f> (setq temp (f/ pow10 highest-power-of-10)) value)
- (setq pow10 temp
- power (- power decimal-digits)))
- (while (f> pow10 value)
- (setq pow10 (f/ pow10 _f10)
- power (1- power)))))
- ; get value in range 100000 to 999999
- (setq value (f* (f/ value pow10) all-decimal-digs-minval)
- result (ftrunc value))
- (let (int)
- (if (f> (f- value result) _f1/2) ; round up if remainder > 0.5
- (setq int (1+ (fint result)))
- (setq int (fint result)))
- (setq str (int-to-string int))
- (if (>= int 1000000)
- (setq power (1+ power))))
-
- (if sci ; scientific notation
- (setq str (concat (substring str 0 1) "." (substring str 1)
- "E" (int-to-string power)))
-
- ; regular decimal string
- (cond ((>= power (1- decimal-digits))
- ; large power, append zeroes
- (let ((zeroes (- power decimal-digits)))
- (while (natnump zeroes)
- (setq str (concat str "0")
- zeroes (1- zeroes)))))
-
- ; negative power, prepend decimal
- ((< power 0) ; point and zeroes
- (let ((zeroes (- (- power) 2)))
- (while (natnump zeroes)
- (setq str (concat "0" str)
- zeroes (1- zeroes)))
- (setq str (concat "0." str))))
-
- (t ; in range, insert decimal point
- (setq str (concat
- (substring str 0 (1+ power))
- "."
- (substring str (1+ power)))))))
-
- (if sign ; if negative, prepend minus sign
- (concat "-" str)
- str))))
-
-
-;; string to float conversion.
-;; accepts scientific notation, but ignores anything after the first two
-;; 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
-are recognized."
-
- (if (string-match floating-point-regexp str 0)
- (let (power)
- (f*
- ; calculate the mantissa
- (let* ((int-subst (extract-match str 2))
- (fract-subst (extract-match str 4))
- (digit-string (concat int-subst fract-subst))
- (mant-sign (equal (extract-match str 1) "-"))
- (leading-0s 0) (round-up nil))
-
- ; get rid of leading 0's
- (setq power (- (length int-subst) decimal-digits))
- (while (and (< leading-0s (length digit-string))
- (= (aref digit-string leading-0s) ?0))
- (setq leading-0s (1+ leading-0s)))
- (setq power (- power leading-0s)
- digit-string (substring digit-string leading-0s))
-
- ; if more than 6 digits, round off
- (if (> (length digit-string) decimal-digits)
- (setq round-up (>= (aref digit-string decimal-digits) ?5)
- digit-string (substring digit-string 0 decimal-digits))
- (setq power (+ power (- decimal-digits (length digit-string)))))
-
- ; round up and add minus sign, if necessary
- (f (* (+ (string-to-int digit-string)
- (if round-up 1 0))
- (if mant-sign -1 1))))
-
- ; calculate the exponent (power of ten)
- (let* ((expt-subst (extract-match str 9))
- (expt-sign (equal (extract-match str 8) "-"))
- (expt 0) (chunks 0) (tens 0) (exponent _f1)
- (func 'f*))
-
- (setq expt (+ (* (string-to-int
- (substring expt-subst 0
- (min expt-digits (length expt-subst))))
- (if expt-sign -1 1))
- power))
- (if (< expt 0) ; if power of 10 negative
- (setq expt (- expt) ; take abs val of exponent
- func 'f/)) ; and set up to divide, not multiply
-
- (setq chunks (/ expt decimal-digits)
- tens (% expt decimal-digits))
- ; divide or multiply by "chunks" of 10**6
- (while (> chunks 0)
- (setq exponent (funcall func exponent highest-power-of-10)
- chunks (1- chunks)))
- ; divide or multiply by remaining power of ten
- (funcall func exponent (aref powers-of-10 tens)))))
-
- _f0)) ; if invalid, return 0
-
-(provide 'float)
-
-;;; float.el ends here
diff --git a/lisp/emacs-lisp/gulp.el b/lisp/emacs-lisp/gulp.el
deleted file mode 100644
index 0020f720b60..00000000000
--- a/lisp/emacs-lisp/gulp.el
+++ /dev/null
@@ -1,152 +0,0 @@
-;;; gulp.el --- Ask for updates for Lisp packages
-
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Sam Shteingold <shteingd@math.ucla.edu>
-;; Maintainer: FSF
-;; Keywords: maintenance
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Search the emacs/{version}/lisp directory for *.el files, extract the
-;; name of the author or maintainer and send him e-mail requesting
-;; update.
-
-;;; Code:
-
-(defvar gulp-discard "^;+ *Maintainer: *FSF *$"
- "*The regexp matching the packages not requiring the request for updates.")
-
-(defvar gulp-tmp-buffer "*gulp*" "The name of the temporary buffer.")
-
-(defvar gulp-max-len 2000
- "*Distance into a Lisp source file to scan for keywords.")
-
-(defvar gulp-request-header
- (concat
- "This message was created automatically.
-A new version of GNU Emacs, "
- (format "%d.%d" emacs-major-version (+ emacs-minor-version 1))
- ", is entering the pretest state,
-and it is high time to submit the updates to the various emacs packages.
-You're listed as the maintainer of the following package(s):\n\n")
- "*The starting text of a gulp message.")
-
-(defvar gulp-request-end
- (concat
- "\nIf you have any changes since the version in the previous release ("
- (format "%d.%d" emacs-major-version emacs-minor-version)
- "),
-please send them to me ASAP.
-
-Thanks.")
- "*The closing text in a gulp message.")
-
-(defun gulp-send-requests (dir &optional time)
- "Send requests for updates to the authors of Lisp packages in directory DIR.
-For each maintainer, the message consists of `gulp-request-header',
-followed by the list of packages (with modification times if the optional
-prefix argument TIME is non-nil), concluded with `gulp-request-end'.
-
-You can't edit the messages, but you can confirm whether to send each one.
-
-The list of addresses for which you decided not to send mail
-is left in the `*gulp*' buffer at the end."
- (interactive "DRequest updates for Lisp directory: \nP")
- (save-excursion
- (set-buffer (get-buffer-create gulp-tmp-buffer))
- (let ((m-p-alist (gulp-create-m-p-alist
- (directory-files dir nil "^[^=].*\\.el$" t)
- dir))
- ;; Temporarily inhibit undo in the *gulp* buffer.
- (buffer-undo-list t)
- mail-setup-hook msg node)
- (while (setq node (car m-p-alist))
- (setq msg (gulp-create-message (cdr node) time))
- (setq mail-setup-hook
- '(lambda ()
- (mail-subject)
- (insert "It's time for Emacs updates again")
- (goto-char (point-max))
- (insert msg)))
- (mail nil (car node))
- (if (y-or-n-p "Send? ") (mail-send)
- (kill-this-buffer)
- (set-buffer gulp-tmp-buffer)
- (insert (format "%s\n\n" node)))
- (setq m-p-alist (cdr m-p-alist))))
- (set-buffer gulp-tmp-buffer)
- (setq buffer-undo-list nil)))
-
-
-(defun gulp-create-message (rec time)
- "Return the message string for REC, which is a list like (FILE TIME)."
- (let (node (str gulp-request-header))
- (while (setq node (car rec))
- (setq str (concat str "\t" (car node)
- (if time (concat "\tLast modified:\t" (cdr node)))
- "\n"))
- (setq rec (cdr rec)))
- (concat str gulp-request-end)))
-
-
-(defun gulp-create-m-p-alist (flist dir)
- "Create the maintainer/package alist for files in FLIST in DIR.
-That is a list of elements, each of the form (MAINTAINER PACKAGES...)."
- (save-excursion
- (let (mplist filen node mnt-tm mnt tm)
- (get-buffer-create gulp-tmp-buffer)
- (set-buffer gulp-tmp-buffer)
- (setq buffer-undo-list t)
- (while flist
- (setq fl-tm (gulp-maintainer (setq filen (car flist)) dir))
- (if (setq tm (cdr fl-tm) mnt (car fl-tm));; there is a definite maintainer
- (if (setq node (assoc mnt mplist));; this is not a new maintainer
- (setq mplist (cons (cons mnt (cons (cons filen tm) (cdr node)))
- (delete node mplist)))
- (setq mplist (cons (list mnt (cons filen (cdr fl-tm))) mplist))))
- (message "%s -- %s" filen fl-tm)
- (setq flist (cdr flist)))
- (erase-buffer)
- mplist)))
-
-(defun gulp-maintainer (filenm dir)
- "Return a list (MAINTAINER TIMESTAMP) for the package FILENM in directory DIR."
- (save-excursion
- (let* ((fl (concat dir filenm)) mnt
- (timest (format-time-string "%Y-%m-%d %a %T %Z"
- (elt (file-attributes fl) 5))))
- (set-buffer gulp-tmp-buffer)
- (erase-buffer)
- (insert-file-contents fl nil 0 gulp-max-len)
- (goto-char 1)
- (if (re-search-forward gulp-discard nil t)
- (setq mnt nil) ;; do nothing, return nil
- (goto-char 1)
- (if (and (re-search-forward "^;+ *Maintainer: \\(.*\\)$" nil t)
- (> (length (setq mnt (match-string 1))) 0))
- () ;; found!
- (goto-char 1)
- (if (re-search-forward "^;+ *Author: \\(.*\\)$" nil t)
- (setq mnt (match-string 1))))
- (if (= (length mnt) 0) (setq mnt nil))) ;; "^;; Author: $" --> nil
- (cons mnt timest))))
-
-;;; gulp.el ends here
diff --git a/lisp/emacs-lisp/helper.el b/lisp/emacs-lisp/helper.el
deleted file mode 100644
index b1f3cfdbd65..00000000000
--- a/lisp/emacs-lisp/helper.el
+++ /dev/null
@@ -1,157 +0,0 @@
-;;; helper.el --- utility help package supporting help in electric modes
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Author: K. Shane Hartman
-;; Maintainer: FSF
-;; Keywords: help
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;; hey, here's a helping hand.
-
-;; Bind this to a string for <blank> in "... Other keys <blank>".
-;; Helper-help uses this to construct help string when scrolling.
-;; Defaults to "return"
-(defvar Helper-return-blurb nil)
-
-;; Keymap implementation doesn't work too well for non-standard loops.
-;; But define it anyway for those who can use it. Non-standard loops
-;; will probably have to use Helper-help. You can't autoload the
-;; keymap either.
-
-
-(defvar Helper-help-map nil)
-(if Helper-help-map
- nil
- (setq Helper-help-map (make-keymap))
- ;(fillarray Helper-help-map 'undefined)
- (define-key Helper-help-map "m" 'Helper-describe-mode)
- (define-key Helper-help-map "b" 'Helper-describe-bindings)
- (define-key Helper-help-map "c" 'Helper-describe-key-briefly)
- (define-key Helper-help-map "k" 'Helper-describe-key)
- ;(define-key Helper-help-map "f" 'Helper-describe-function)
- ;(define-key Helper-help-map "v" 'Helper-describe-variable)
- (define-key Helper-help-map "?" 'Helper-help-options)
- (define-key Helper-help-map (char-to-string help-char) 'Helper-help-options)
- (fset 'Helper-help-map Helper-help-map))
-
-(defun Helper-help-scroller ()
- (let ((blurb (or (and (boundp 'Helper-return-blurb)
- Helper-return-blurb)
- "return")))
- (save-window-excursion
- (goto-char (window-start (selected-window)))
- (if (get-buffer-window "*Help*")
- (pop-to-buffer "*Help*")
- (switch-to-buffer "*Help*"))
- (goto-char (point-min))
- (let ((continue t) state)
- (while continue
- (setq state (+ (* 2 (if (pos-visible-in-window-p (point-max)) 1 0))
- (if (pos-visible-in-window-p (point-min)) 1 0)))
- (message
- (nth state
- '("Space forward, Delete back. Other keys %s"
- "Space scrolls forward. Other keys %s"
- "Delete scrolls back. Other keys %s"
- "Type anything to %s"))
- blurb)
- (setq continue (read-char))
- (cond ((and (memq continue '(?\ ?\C-v)) (< state 2))
- (scroll-up))
- ((= continue ?\C-l)
- (recenter))
- ((and (= continue ?\177) (zerop (% state 2)))
- (scroll-down))
- (t (setq continue nil))))))))
-
-(defun Helper-help-options ()
- "Describe help options."
- (interactive)
- (message "c (key briefly), m (mode), k (key), b (bindings)")
- ;(message "c (key briefly), m (mode), k (key), v (variable), f (function)")
- (sit-for 4))
-
-(defun Helper-describe-key-briefly (key)
- "Briefly describe binding of KEY."
- (interactive "kDescribe key briefly: ")
- (describe-key-briefly key)
- (sit-for 4))
-
-(defun Helper-describe-key (key)
- "Describe binding of KEY."
- (interactive "kDescribe key: ")
- (save-window-excursion (describe-key key))
- (Helper-help-scroller))
-
-(defun Helper-describe-function ()
- "Describe a function. Name read interactively."
- (interactive)
- (save-window-excursion (call-interactively 'describe-function))
- (Helper-help-scroller))
-
-(defun Helper-describe-variable ()
- "Describe a variable. Name read interactively."
- (interactive)
- (save-window-excursion (call-interactively 'describe-variable))
- (Helper-help-scroller))
-
-(defun Helper-describe-mode ()
- "Describe the current mode."
- (interactive)
- (let ((name mode-name)
- (documentation (documentation major-mode)))
- (save-excursion
- (set-buffer (get-buffer-create "*Help*"))
- (erase-buffer)
- (insert name " Mode\n" documentation)
- (help-mode)))
- (Helper-help-scroller))
-
-;;;###autoload
-(defun Helper-describe-bindings ()
- "Describe local key bindings of current mode."
- (interactive)
- (message "Making binding list...")
- (save-window-excursion (describe-bindings))
- (Helper-help-scroller))
-
-;;;###autoload
-(defun Helper-help ()
- "Provide help for current mode."
- (interactive)
- (let ((continue t) c)
- (while continue
- (message "Help (Type ? for further options)")
- (setq c (read-key-sequence nil))
- (setq c (lookup-key Helper-help-map c))
- (cond ((eq c 'Helper-help-options)
- (Helper-help-options))
- ((commandp c)
- (call-interactively c)
- (setq continue nil))
- (t
- (ding)
- (setq continue nil))))))
-
-(provide 'helper)
-
-;;; helper.el ends here
diff --git a/lisp/emacs-lisp/levents.el b/lisp/emacs-lisp/levents.el
deleted file mode 100644
index bc5c06c9cbc..00000000000
--- a/lisp/emacs-lisp/levents.el
+++ /dev/null
@@ -1,233 +0,0 @@
-;;; levents.el --- emulate the Lucid event data type and associated functions.
-
-;; Copyright (C) 1993 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Things we cannot emulate in Lisp:
-;; It is not possible to emulate current-mouse-event as a variable,
-;; though it is not hard to obtain the data from (this-command-keys).
-
-;; We do not have a variable unread-command-event;
-;; instead, we have the more general unread-command-events.
-
-;; Our read-key-sequence and read-char are not precisely
-;; compatible with those in Lucid Emacs, but they should work ok.
-
-;;; Code:
-
-(defun next-command-event (event)
- (error "You must rewrite to use `read-command-event' instead of `next-command-event'"))
-
-(defun next-event (event)
- (error "You must rewrite to use `read-event' instead of `next-event'"))
-
-(defun dispatch-event (event)
- (error "`dispatch-event' not supported"))
-
-;; Make events of type eval, menu and timeout
-;; execute properly.
-
-(define-key global-map [menu] 'execute-eval-event)
-(define-key global-map [timeout] 'execute-eval-event)
-(define-key global-map [eval] 'execute-eval-event)
-
-(defun execute-eval-event (event)
- (interactive "e")
- (funcall (nth 1 event) (nth 2 event)))
-
-(put 'eval 'event-symbol-elements '(eval))
-(put 'menu 'event-symbol-elements '(eval))
-(put 'timeout 'event-symbol-elements '(eval))
-
-(defun allocate-event ()
- "Returns an empty event structure.
-In this emulation, it returns nil."
- nil)
-
-(defun button-press-event-p (obj)
- "True if the argument is a mouse-button-press event object."
- (and (consp obj) (symbolp (car obj))
- (memq 'down (get (car obj) 'event-symbol-elements))))
-
-(defun button-release-event-p (obj)
- "True if the argument is a mouse-button-release event object."
- (and (consp obj) (symbolp (car obj))
- (or (memq 'click (get (car obj) 'event-symbol-elements))
- (memq 'drag (get (car obj) 'event-symbol-elements)))))
-
-(defun character-to-event (ch &optional event)
- "Converts a numeric ASCII value to an event structure, replete with
-bucky bits. The character is the first argument, and the event to fill
-in is the second. This function contains knowledge about what the codes
-mean -- for example, the number 9 is converted to the character Tab,
-not the distinct character Control-I.
-
-Beware that character-to-event and event-to-character are not strictly
-inverse functions, since events contain much more information than the
-ASCII character set can encode."
- ch)
-
-(defun copy-event (event1 &optional event2)
- "Make a copy of the given event object.
-In this emulation, `copy-event' just returns its argument."
- event1)
-
-(defun deallocate-event (event)
- "Allow the given event structure to be reused.
-In actual Lucid Emacs, you MUST NOT use this event object after
-calling this function with it. You will lose. It is not necessary to
-call this function, as event objects are garbage- collected like all
-other objects; however, it may be more efficient to explicitly
-deallocate events when you are sure that that is safe.
-
-This emulation does not actually deallocate or reuse events
-except via garbage collection and `cons'."
- nil)
-
-(defun enqueue-eval-event: (function object)
- "Add an eval event to the back of the queue.
-It will be the next event read after all pending events."
- (setq unread-command-events
- (nconc unread-command-events
- (list (list 'eval function object)))))
-
-(defun eval-event-p (obj)
- "True if the argument is an eval or menu event object."
- (eq (car-safe obj) 'eval))
-
-(defun event-button (event)
- "Return the button-number of the given mouse-button-press event."
- (let ((sym (car (get (car event) 'event-symbol-elements))))
- (cdr (assq sym '((mouse-1 . 1) (mouse-2 . 2) (mouse-3 . 3)
- (mouse-4 . 4) (mouse-5 . 5))))))
-
-(defun event-function (event)
- "Return the callback function of the given timeout, menu, or eval event."
- (nth 1 event))
-
-(defun event-key (event)
- "Returns the KeySym of the given key-press event.
-The value is an ASCII printing character (not upper case) or a symbol."
- (if (symbolp event)
- (car (get event 'event-symbol-elements))
- (let ((base (logand event (1- (lsh 1 18)))))
- (downcase (if (< base 32) (logior base 64) base)))))
-
-(defun event-object (event)
- "Returns the function argument of the given timeout, menu, or eval event."
- (nth 2 event))
-
-(defun event-point (event)
- "Returns the character position of the given mouse-related event.
-If the event did not occur over a window, or did
-not occur over text, then this returns nil. Otherwise, it returns an index
-into the buffer visible in the event's window."
- (posn-point (event-end event)))
-
-(defun event-process (event)
- "Returns the process of the given process-output event."
- (nth 1 event))
-
-(defun event-timestamp (event)
- "Returns the timestamp of the given event object.
-In Lucid Emacs, this works for any kind of event.
-In this emulation, it returns nil for non-mouse-related events."
- (and (listp event)
- (posn-timestamp (event-end event))))
-
-(defun event-to-character (event &optional lenient)
- "Returns the closest ASCII approximation to the given event object.
-If the event isn't a keypress, this returns nil.
-If the second argument is non-nil, then this is lenient in its
-translation; it will ignore modifier keys other than control and meta,
-and will ignore the shift modifier on those characters which have no
-shifted ASCII equivalent (Control-Shift-A for example, will be mapped to
-the same ASCII code as Control-A.) If the second arg is nil, then nil
-will be returned for events which have no direct ASCII equivalent."
- (if (symbolp event)
- (and lenient
- (cdr (assq event '((backspace . 8) (delete . 127) (tab . 9)
- (return . 10) (enter . 10)))))
- ;; Our interpretation is, ASCII means anything a number can represent.
- (if (integerp event)
- event nil)))
-
-(defun event-window (event)
- "Returns the window of the given mouse-related event object."
- (posn-window (event-end event)))
-
-(defun event-x (event)
- "Returns the X position in characters of the given mouse-related event."
- (/ (car (posn-col-row (event-end event)))
- (frame-char-width (window-frame (event-window event)))))
-
-(defun event-x-pixel (event)
- "Returns the X position in pixels of the given mouse-related event."
- (car (posn-col-row (event-end event))))
-
-(defun event-y (event)
- "Returns the Y position in characters of the given mouse-related event."
- (/ (cdr (posn-col-row (event-end event)))
- (frame-char-height (window-frame (event-window event)))))
-
-(defun event-y-pixel (event)
- "Returns the Y position in pixels of the given mouse-related event."
- (cdr (posn-col-row (event-end event))))
-
-(defun key-press-event-p (obj)
- "True if the argument is a keyboard event object."
- (or (integerp obj)
- (and (symbolp obj)
- (get obj 'event-symbol-elements))))
-
-(defun menu-event-p (obj)
- "True if the argument is a menu event object."
- (eq (car-safe obj) 'menu))
-
-(defun motion-event-p (obj)
- "True if the argument is a mouse-motion event object."
- (eq (car-safe obj) 'mouse-movement))
-
-(defun read-command-event ()
- "Return the next keyboard or mouse event; execute other events.
-This is similar to the function `next-command-event' of Lucid Emacs,
-but different in that it returns the event rather than filling in
-an existing event object."
- (let (event)
- (while (progn
- (setq event (read-event))
- (not (or (key-press-event-p event)
- (button-press-event-p event)
- (button-release-event-p event)
- (menu-event-p event))))
- (let ((type (car-safe event)))
- (cond ((eq type 'eval)
- (funcall (nth 1 event) (nth 2 event)))
- ((eq type 'switch-frame)
- (select-frame (nth 1 event))))))
- event))
-
-(defun process-event-p (obj)
- "True if the argument is a process-output event object.
-GNU Emacs 19 does not currently generate process-output events."
- (eq (car-safe obj) 'process))
-
-;;; levents.el ends here
diff --git a/lisp/emacs-lisp/lisp-mnt.el b/lisp/emacs-lisp/lisp-mnt.el
deleted file mode 100644
index 8a6af05993f..00000000000
--- a/lisp/emacs-lisp/lisp-mnt.el
+++ /dev/null
@@ -1,554 +0,0 @@
-;;; lisp-mnt.el --- minor mode for Emacs Lisp maintainers
-
-;; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
-
-;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
-;; Maintainer: Eric S. Raymond <esr@snark.thyrsus.com>
-;; Created: 14 Jul 1992
-;; Version: $Id: lisp-mnt.el,v 1.16 1996/02/06 21:35:20 erik Exp rms $
-;; Keywords: docs
-;; X-Bogus-Bureaucratic-Cruft: Gruad will get you if you don't watch out!
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This minor mode adds some services to Emacs-Lisp editing mode.
-;;
-;; First, it knows about the header conventions for library packages.
-;; One entry point supports generating synopses from a library directory.
-;; Another can be used to check for missing headers in library files.
-;;
-;; Another entry point automatically addresses bug mail to a package's
-;; maintainer or author.
-
-;; This file can be loaded by your lisp-mode-hook. Have it (require 'lisp-mnt)
-
-;; This file is an example of the header conventions. Note the following
-;; features:
-;;
-;; * Header line --- makes it possible to extract a one-line summary of
-;; the package's uses automatically for use in library synopses, KWIC
-;; indexes and the like.
-;;
-;; Format is three semicolons, followed by the filename, followed by
-;; three dashes, followed by the summary. All fields space-separated.
-;;
-;; * Author line --- contains the name and net address of at least
-;; the principal author.
-;;
-;; If there are multiple authors, they should be listed on continuation
-;; lines led by ;;<TAB>, like this:
-;;
-;; ;; Author: Ashwin Ram <Ram-Ashwin@cs.yale.edu>
-;; ;; Dave Sill <de5@ornl.gov>
-;; ;; David Lawrence <tale@pawl.rpi.edu>
-;; ;; Noah Friedman <friedman@ai.mit.edu>
-;; ;; Joe Wells <jbw@maverick.uswest.com>
-;; ;; Dave Brennan <brennan@hal.com>
-;; ;; Eric Raymond <esr@snark.thyrsus.com>
-;;
-;; This field may have some special values; notably "FSF", meaning
-;; "Free Software Foundation".
-;;
-;; * Maintainer line --- should be a single name/address as in the Author
-;; line, or an address only, or the string "FSF". If there is no maintainer
-;; line, the person(s) in the Author field are presumed to be it. The example
-;; in this file is mildly bogus because the maintainer line is redundant.
-;; The idea behind these two fields is to be able to write a Lisp function
-;; that does "send mail to the author" without having to mine the name out by
-;; hand. Please be careful about surrounding the network address with <> if
-;; there's also a name in the field.
-;;
-;; * Created line --- optional, gives the original creation date of the
-;; file. For historical interest, basically.
-;;
-;; * Version line --- intended to give the reader a clue if they're looking
-;; at a different version of the file than the one they're accustomed to. This
-;; may be an RCS or SCCS header.
-;;
-;; * Adapted-By line --- this is for FSF's internal use. The person named
-;; in this field was the one responsible for installing and adapting the
-;; package for the distribution. (This file doesn't have one because the
-;; author *is* one of the maintainers.)
-;;
-;; * Keywords line --- used by the finder code (now under construction)
-;; for finding Emacs Lisp code related to a topic.
-;;
-;; * X-Bogus-Bureaucratic-Cruft line --- this is a joke and an example
-;; of a comment header. Headers starting with `X-' should never be used
-;; for any real purpose; this is the way to safely add random headers
-;; without invoking the wrath of any program.
-;;
-;; * Commentary line --- enables Lisp code to find the developer's and
-;; maintainers' explanations of the package internals.
-;;
-;; * Change log line --- optional, exists to terminate the commentary
-;; section and start a change-log part, if one exists.
-;;
-;; * Code line --- exists so Lisp can know where commentary and/or
-;; change-log sections end.
-;;
-;; * Footer line --- marks end-of-file so it can be distinguished from
-;; an expanded formfeed or the results of truncation.
-
-;;; Change Log:
-
-;; Tue Jul 14 23:44:17 1992 ESR
-;; * Created.
-
-;;; Code:
-
-(require 'picture) ; provides move-to-column-force
-(require 'emacsbug)
-
-;;; Variables:
-
-(defvar lm-header-prefix "^;;*[ \t]+\\(@\(#\)\\)?[ \t]*\\([\$]\\)?"
- "Prefix that is ignored before the tag.
-For example, you can write the 1st line synopsis string and headers like this
-in your Lisp package:
-
- ;; @(#) package.el -- pacakge description
- ;;
- ;; @(#) $Maintainer: Person Foo Bar $
-
-The @(#) construct is used by unix what(1) and
-then $identifier: doc string $ is used by GNU ident(1)")
-
-(defvar lm-comment-column 16
- "Column used for placing formatted output.")
-
-(defvar lm-commentary-header "Commentary\\|Documentation"
- "Regexp which matches start of documentation section.")
-
-(defvar lm-history-header "Change Log\\|History"
- "Regexp which matches the start of code log section.")
-
-;;; Functions:
-
-;; These functions all parse the headers of the current buffer
-
-(defsubst lm-get-header-re (header &optional mode)
- "Returns regexp for matching HEADER.
-If called with optional MODE and with value `section',
-return section regexp instead."
- (cond ((eq mode 'section)
- (concat "^;;;;* " header ":[ \t]*$"))
- (t
- (concat lm-header-prefix header ":[ \t]*"))))
-
-(defsubst lm-get-package-name ()
- "Returns package name by looking at the first line."
- (save-excursion
- (goto-char (point-min))
- (if (and (looking-at (concat lm-header-prefix))
- (progn (goto-char (match-end 0))
- (looking-at "\\([^\t ]+\\)")
- (match-end 1)))
- (buffer-substring (match-beginning 1) (match-end 1))
- )))
-
-(defun lm-section-mark (header &optional after)
- "Return the buffer location of a given section start marker.
-The HEADER is the section mark string to search for.
-If AFTER is non-nil, return the location of the next line."
- (save-excursion
- (let ((case-fold-search t))
- (goto-char (point-min))
- (if (re-search-forward (lm-get-header-re header 'section) nil t)
- (progn
- (beginning-of-line)
- (if after (forward-line 1))
- (point))
- nil))))
-
-(defsubst lm-code-mark ()
- "Return the buffer location of the `Code' start marker."
- (lm-section-mark "Code"))
-
-(defsubst lm-commentary-mark ()
- "Return the buffer location of the `Commentary' start marker."
- (lm-section-mark lm-commentary-header))
-
-(defsubst lm-history-mark ()
- "Return the buffer location of the `History' start marker."
- (lm-section-mark lm-history-header))
-
-(defun lm-header (header)
- "Return the contents of the header named HEADER."
- (goto-char (point-min))
- (let ((case-fold-search t))
- (if (and (re-search-forward (lm-get-header-re header) (lm-code-mark) t)
- ;; RCS ident likes format "$identifier: data$"
- (looking-at "\\([^$\n]+\\)")
- (match-end 1))
- (buffer-substring (match-beginning 1) (match-end 1))
- nil)))
-
-(defun lm-header-multiline (header)
- "Return the contents of the header named HEADER, with continuation lines.
-The returned value is a list of strings, one per line."
- (save-excursion
- (goto-char (point-min))
- (let ((res (lm-header header)))
- (cond
- (res
- (setq res (list res))
- (forward-line 1)
-
- (while (and (looking-at (concat lm-header-prefix "[\t ]+"))
- (progn
- (goto-char (match-end 0))
- (looking-at "\\(.*\\)"))
- (match-end 1))
- (setq res (cons (buffer-substring
- (match-beginning 1)
- (match-end 1))
- res))
- (forward-line 1))
- ))
- res
- )))
-
-;; These give us smart access to the header fields and commentary
-
-(defun lm-summary (&optional file)
- "Return the one-line summary of file FILE, or current buffer if FILE is nil."
- (save-excursion
- (if file
- (find-file file))
- (goto-char (point-min))
- (prog1
- (if (and
- (looking-at lm-header-prefix)
- (progn (goto-char (match-end 0))
- (looking-at "[^ ]+[ \t]+--+[ \t]+\\(.*\\)")))
- (buffer-substring (match-beginning 1) (match-end 1)))
- (if file
- (kill-buffer (current-buffer)))
- )))
-
-(defun lm-crack-address (x)
- "Split up an email address into full name and real email address.
-The value is a cons of the form (FULLNAME . ADDRESS)."
- (cond ((string-match "\\(.+\\) [(<]\\(\\S-+@\\S-+\\)[>)]" x)
- (cons (substring x (match-beginning 1) (match-end 1))
- (substring x (match-beginning 2) (match-end 2))))
- ((string-match "\\(\\S-+@\\S-+\\) [(<]\\(.*\\)[>)]" x)
- (cons (substring x (match-beginning 2) (match-end 2))
- (substring x (match-beginning 1) (match-end 1))))
- ((string-match "\\S-+@\\S-+" x)
- (cons nil x))
- (t
- (cons x nil))))
-
-(defun lm-authors (&optional file)
- "Return the author list of file FILE, or current buffer if FILE is nil.
-Each element of the list is a cons; the car is the full name,
-the cdr is an email address."
- (save-excursion
- (if file
- (find-file file))
- (let ((authorlist (lm-header-multiline "author")))
- (prog1
- (mapcar 'lm-crack-address authorlist)
- (if file
- (kill-buffer (current-buffer)))
- ))))
-
-(defun lm-maintainer (&optional file)
- "Return the maintainer of file FILE, or current buffer if FILE is nil.
-The return value has the form (NAME . ADDRESS)."
- (save-excursion
- (if file
- (find-file file))
- (prog1
- (let ((maint (lm-header "maintainer")))
- (if maint
- (lm-crack-address maint)
- (car (lm-authors))))
- (if file
- (kill-buffer (current-buffer)))
- )))
-
-(defun lm-creation-date (&optional file)
- "Return the created date given in file FILE, or current buffer if FILE is nil."
- (save-excursion
- (if file
- (find-file file))
- (prog1
- (lm-header "created")
- (if file
- (kill-buffer (current-buffer)))
- )))
-
-
-(defun lm-last-modified-date (&optional file)
- "Return the modify-date given in file FILE, or current buffer if FILE is nil."
- (save-excursion
- (if file
- (find-file file))
- (prog1
- (if (progn
- (goto-char (point-min))
- (re-search-forward
- "\\$Id: [^ ]+ [^ ]+ \\([^/]+\\)/\\([^/]+\\)/\\([^ ]+\\) "
- (lm-code-mark) t))
- (format "%s %s %s"
- (buffer-substring (match-beginning 3) (match-end 3))
- (nth (string-to-int
- (buffer-substring (match-beginning 2) (match-end 2)))
- '("" "Jan" "Feb" "Mar" "Apr" "May" "Jun"
- "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"))
- (buffer-substring (match-beginning 1) (match-end 1))
- ))
- (if file
- (kill-buffer (current-buffer)))
- )))
-
-(defun lm-version (&optional file)
- "Return the version listed in file FILE, or current buffer if FILE is nil.
-This can befound in an RCS or SCCS header to crack it out of."
- (save-excursion
- (if file
- (find-file file))
- (prog1
- (or
- (lm-header "version")
- (let ((header-max (lm-code-mark)))
- (goto-char (point-min))
- (cond
- ;; Look for an RCS header
- ((re-search-forward "\\$Id: [^ ]+ \\([^ ]+\\) " header-max t)
- (buffer-substring (match-beginning 1) (match-end 1)))
-
- ;; Look for an SCCS header
- ((re-search-forward
- (concat
- (regexp-quote "@(#)")
- (regexp-quote (file-name-nondirectory (buffer-file-name)))
- "\t\\([012345679.]*\\)")
- header-max t)
- (buffer-substring (match-beginning 1) (match-end 1)))
-
- (t nil))))
- (if file
- (kill-buffer (current-buffer)))
- )))
-
-(defun lm-keywords (&optional file)
- "Return the keywords given in file FILE, or current buffer if FILE is nil."
- (save-excursion
- (if file
- (find-file file))
- (prog1
- (let ((keywords (lm-header "keywords")))
- (and keywords (downcase keywords)))
- (if file
- (kill-buffer (current-buffer)))
- )))
-
-(defun lm-adapted-by (&optional file)
- "Return the adapted-by names in file FILE, or current buffer if FILE is nil.
-This is the name of the person who cleaned up this package for
-distribution."
- (save-excursion
- (if file
- (find-file file))
- (prog1
- (lm-header "adapted-by")
- (if file
- (kill-buffer (current-buffer)))
- )))
-
-(defun lm-commentary (&optional file)
- "Return the commentary in file FILE, or current buffer if FILE is nil.
-The value is returned as a string. In the text, the commentary starts
-with tag `Commentary' and ends with tag `Change Log' or `History'."
- (save-excursion
- (if file
- (find-file file))
- (prog1
- (let ((commentary (lm-commentary-mark))
- (change-log (lm-history-mark))
- (code (lm-code-mark))
- )
- (cond
- ((and commentary change-log)
- (buffer-substring commentary change-log))
- ((and commentary code)
- (buffer-substring commentary code))
- (t
- nil)))
- (if file
- (kill-buffer (current-buffer)))
- )))
-
-;;; Verification and synopses
-
-(defun lm-insert-at-column (col &rest strings)
- "Insert list of STRINGS, at column COL."
- (if (> (current-column) col) (insert "\n"))
- (move-to-column-force col)
- (apply 'insert strings))
-
-(defun lm-verify (&optional file showok &optional verb)
- "Check that the current buffer (or FILE if given) is in proper format.
-If FILE is a directory, recurse on its files and generate a report in
-a temporary buffer."
- (interactive)
- (let* ((verb (or verb (interactive-p)))
- ret
- name
- )
- (if verb
- (setq ret "Ok.")) ;init value
-
- (if (and file (file-directory-p file))
- (setq
- ret
- (progn
- (switch-to-buffer (get-buffer-create "*lm-verify*"))
- (erase-buffer)
- (mapcar
- '(lambda (f)
- (if (string-match ".*\\.el$" f)
- (let ((status (lm-verify f)))
- (if status
- (progn
- (insert f ":")
- (lm-insert-at-column lm-comment-column status "\n"))
- (and showok
- (progn
- (insert f ":")
- (lm-insert-at-column lm-comment-column "OK\n")))))))
- (directory-files file))
- ))
- (save-excursion
- (if file
- (find-file file))
- (setq name (lm-get-package-name))
-
- (setq
- ret
- (prog1
- (cond
- ((null name)
- "Can't find a package NAME")
-
- ((not (lm-authors))
- "Author: tag missing.")
-
- ((not (lm-maintainer))
- "Maintainer: tag missing.")
-
- ((not (lm-summary))
- "Can't find a one-line 'Summary' description")
-
- ((not (lm-keywords))
- "Keywords: tag missing.")
-
- ((not (lm-commentary-mark))
- "Can't find a 'Commentary' section marker.")
-
- ((not (lm-history-mark))
- "Can't find a 'History' section marker.")
-
- ((not (lm-code-mark))
- "Can't find a 'Code' section marker")
-
- ((progn
- (goto-char (point-max))
- (not
- (re-search-backward
- (concat "^;;;[ \t]+" name "[ \t]+ends here[ \t]*$"
- "\\|^;;;[ \t]+ End of file[ \t]+" name)
- nil t
- )))
- (format "Can't find a footer line for [%s]" name))
- (t
- ret))
- (if file
- (kill-buffer (current-buffer)))
- ))))
- (if verb
- (message ret))
- ret
- ))
-
-(defun lm-synopsis (&optional file showall)
- "Generate a synopsis listing for the buffer or the given FILE if given.
-If FILE is a directory, recurse on its files and generate a report in
-a temporary buffer. If SHOWALL is non-nil, also generate a line for files
-which do not include a recognizable synopsis."
- (interactive
- (list
- (read-file-name "Synopsis for (file or dir): ")))
-
- (if (and file (file-directory-p file))
- (progn
- (switch-to-buffer (get-buffer-create "*lm-verify*"))
- (erase-buffer)
- (mapcar
- '(lambda (f)
- (if (string-match ".*\\.el$" f)
- (let ((syn (lm-synopsis f)))
- (if syn
- (progn
- (insert f ":")
- (lm-insert-at-column lm-comment-column syn "\n"))
- (and showall
- (progn
- (insert f ":")
- (lm-insert-at-column lm-comment-column "NA\n")))))))
- (directory-files file))
- )
- (save-excursion
- (if file
- (find-file file))
- (prog1
- (lm-summary)
- (if file
- (kill-buffer (current-buffer)))
- ))))
-
-(defun lm-report-bug (topic)
- "Report a bug in the package currently being visited to its maintainer.
-Prompts for bug subject. Leaves you in a mail buffer."
- (interactive "sBug Subject: ")
- (let ((package (lm-get-package-name))
- (addr (lm-maintainer))
- (version (lm-version)))
- (mail nil
- (if addr
- (concat (car addr) " <" (cdr addr) ">")
- bug-gnu-emacs)
- topic)
- (goto-char (point-max))
- (insert "\nIn "
- package
- (if version (concat " version " version) "")
- "\n\n")
- (message
- (substitute-command-keys "Type \\[mail-send] to send bug report."))))
-
-(provide 'lisp-mnt)
-
-;;; lisp-mnt.el ends here
-
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
deleted file mode 100644
index 26eab753c38..00000000000
--- a/lisp/emacs-lisp/lisp-mode.el
+++ /dev/null
@@ -1,838 +0,0 @@
-;;; lisp-mode.el --- Lisp mode, and its idiosyncratic commands.
-
-;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: lisp, languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The base major mode for editing Lisp code (used also for Emacs Lisp).
-;; This mode is documented in the Emacs manual
-
-;;; Code:
-
-(defvar lisp-mode-syntax-table nil "")
-(defvar emacs-lisp-mode-syntax-table nil "")
-(defvar lisp-mode-abbrev-table nil "")
-
-(if (not emacs-lisp-mode-syntax-table)
- (let ((i 0))
- (setq emacs-lisp-mode-syntax-table (make-syntax-table))
- (while (< i ?0)
- (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
- (setq i (1+ i)))
- (setq i (1+ ?9))
- (while (< i ?A)
- (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
- (setq i (1+ i)))
- (setq i (1+ ?Z))
- (while (< i ?a)
- (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
- (setq i (1+ i)))
- (setq i (1+ ?z))
- (while (< i 128)
- (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
- (setq i (1+ i)))
- (modify-syntax-entry ? " " emacs-lisp-mode-syntax-table)
- (modify-syntax-entry ?\t " " emacs-lisp-mode-syntax-table)
- (modify-syntax-entry ?\n "> " emacs-lisp-mode-syntax-table)
- ;; Give CR the same syntax as newline, for selective-display.
- (modify-syntax-entry ?\^m "> " 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)
- ;; 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)
- (modify-syntax-entry ?\) ")( " emacs-lisp-mode-syntax-table)
- (modify-syntax-entry ?\[ "(] " emacs-lisp-mode-syntax-table)
- (modify-syntax-entry ?\] ")[ " emacs-lisp-mode-syntax-table)))
-
-(if (not lisp-mode-syntax-table)
- (progn (setq lisp-mode-syntax-table
- (copy-syntax-table emacs-lisp-mode-syntax-table))
- (modify-syntax-entry ?\| "\" " lisp-mode-syntax-table)
- (modify-syntax-entry ?\[ "_ " lisp-mode-syntax-table)
- (modify-syntax-entry ?\] "_ " lisp-mode-syntax-table)))
-
-(define-abbrev-table 'lisp-mode-abbrev-table ())
-
-(defvar lisp-imenu-generic-expression
- '(
- (nil
- "^\\s-*(def\\(un\\|subst\\|macro\\|advice\\)\\s-+\\([-A-Za-z0-9+]+\\)" 2)
- ("Variables"
- "^\\s-*(def\\(var\\|const\\)\\s-+\\([-A-Za-z0-9+]+\\)" 2)
- ("Types"
- "^\\s-*(def\\(type\\|struct\\|class\\|ine-condition\\)\\s-+\\([-A-Za-z0-9+]+\\)"
- 2))
-
- "Imenu generic expression for Lisp mode. See `imenu-generic-expression'.")
-
-(defun lisp-mode-variables (lisp-syntax)
- (cond (lisp-syntax
- (set-syntax-table lisp-mode-syntax-table)))
- (setq local-abbrev-table lisp-mode-abbrev-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 'fill-paragraph-function)
- (setq fill-paragraph-function 'lisp-fill-paragraph)
- ;; Adaptive fill mode gets in the way of auto-fill,
- ;; and should make no difference for explicit fill
- ;; because lisp-fill-paragraph should do the job.
- (make-local-variable 'adaptive-fill-mode)
- (setq adaptive-fill-mode nil)
- (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 'outline-regexp)
- (setq outline-regexp ";;; \\|(....")
- (make-local-variable 'comment-start)
- (setq comment-start ";")
- (make-local-variable 'comment-start-skip)
- ;; Look within the line for a ; following an even number of backslashes
- ;; after either a non-backslash or the line beginning.
- (setq comment-start-skip "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\);+ *")
- (make-local-variable 'comment-column)
- (setq comment-column 40)
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'lisp-comment-indent)
- (make-local-variable 'imenu-generic-expression)
- (setq imenu-generic-expression lisp-imenu-generic-expression))
-
-(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))
-
-(defvar emacs-lisp-mode-map ()
- "Keymap for Emacs Lisp mode.
-All commands in `shared-lisp-mode-map' are inherited by this map.")
-
-(if emacs-lisp-mode-map
- ()
- (let ((map (make-sparse-keymap "Emacs-Lisp")))
- (setq emacs-lisp-mode-map
- (nconc (make-sparse-keymap) shared-lisp-mode-map))
- (define-key emacs-lisp-mode-map "\e\t" 'lisp-complete-symbol)
- (define-key emacs-lisp-mode-map "\e\C-x" 'eval-defun)
- (define-key emacs-lisp-mode-map [menu-bar] (make-sparse-keymap))
- (define-key emacs-lisp-mode-map [menu-bar emacs-lisp]
- (cons "Emacs-Lisp" map))
- (define-key map [edebug-defun]
- '("Instrument Function for Debugging" . edebug-defun))
- (define-key map [byte-recompile]
- '("Byte-recompile Directory..." . byte-recompile-directory))
- (define-key map [emacs-byte-compile-and-load]
- '("Byte-compile And Load" . emacs-lisp-byte-compile-and-load))
- (define-key map [byte-compile]
- '("Byte-compile This File" . emacs-lisp-byte-compile))
- (define-key map [separator-eval] '("--"))
- (define-key map [eval-buffer] '("Evaluate Buffer" . eval-current-buffer))
- (define-key map [eval-region] '("Evaluate Region" . eval-region))
- (define-key map [eval-sexp] '("Evaluate Last S-expression" . eval-last-sexp))
- (define-key map [separator-format] '("--"))
- (define-key map [comment-region] '("Comment Out Region" . comment-region))
- (define-key map [indent-region] '("Indent Region" . indent-region))
- (define-key map [indent-line] '("Indent Line" . lisp-indent-line))
- (put 'eval-region 'menu-enable 'mark-active)
- (put 'comment-region 'menu-enable 'mark-active)
- (put 'indent-region 'menu-enable 'mark-active)))
-
-(defun emacs-lisp-byte-compile ()
- "Byte compile the file containing the current buffer."
- (interactive)
- (if buffer-file-name
- (byte-compile-file buffer-file-name)
- (error "The buffer must be saved in a file first")))
-
-(defun emacs-lisp-byte-compile-and-load ()
- "Byte-compile the current file (if it has changed), then load compiled code."
- (interactive)
- (or buffer-file-name
- (error "The buffer must be saved in a file first"))
- (require 'bytecomp)
- ;; Recompile if file or buffer has changed since last compilation.
- (if (and (buffer-modified-p)
- (y-or-n-p (format "save buffer %s first? " (buffer-name))))
- (save-buffer))
- (let ((compiled-file-name (byte-compile-dest-file buffer-file-name)))
- (if (file-newer-than-file-p compiled-file-name buffer-file-name)
- (load-file compiled-file-name)
- (byte-compile-file buffer-file-name t))))
-
-(defun emacs-lisp-mode ()
- "Major mode for editing Lisp code to run in Emacs.
-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'
-if that value is non-nil."
- (interactive)
- (kill-all-local-variables)
- (use-local-map emacs-lisp-mode-map)
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (setq major-mode 'emacs-lisp-mode)
- (setq mode-name "Emacs-Lisp")
- (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.")
-
-(if lisp-mode-map
- ()
- (setq lisp-mode-map
- (nconc (make-sparse-keymap) shared-lisp-mode-map))
- (define-key lisp-mode-map "\e\C-x" 'lisp-eval-defun)
- (define-key lisp-mode-map "\C-c\C-z" 'run-lisp))
-
-(defun lisp-mode ()
- "Major mode for editing Lisp code for Lisps other than GNU Emacs Lisp.
-Commands:
-Delete converts tabs to spaces as it moves back.
-Blank lines separate paragraphs. Semicolons start comments.
-\\{lisp-mode-map}
-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'
-if that value is non-nil."
- (interactive)
- (kill-all-local-variables)
- (use-local-map lisp-mode-map)
- (setq major-mode 'lisp-mode)
- (setq mode-name "Lisp")
- (lisp-mode-variables t)
- (set-syntax-table lisp-mode-syntax-table)
- (run-hooks 'lisp-mode-hook))
-
-;; This will do unless shell.el is loaded.
-(defun lisp-eval-defun nil
- "Send the current defun to the Lisp process made by \\[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.")
-
-(if lisp-interaction-mode-map
- ()
- (setq lisp-interaction-mode-map
- (nconc (make-sparse-keymap) shared-lisp-mode-map))
- (define-key lisp-interaction-mode-map "\e\C-x" 'eval-defun)
- (define-key lisp-interaction-mode-map "\e\t" 'lisp-complete-symbol)
- (define-key lisp-interaction-mode-map "\n" 'eval-print-last-sexp))
-
-(defun lisp-interaction-mode ()
- "Major mode for typing and evaluating Lisp forms.
-Like Lisp mode except that \\[eval-print-last-sexp] evals the Lisp expression
-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.
-\\{lisp-interaction-mode-map}
-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)
- (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))
-
-(defun eval-print-last-sexp ()
- "Evaluate sexp before point; print value into current buffer."
- (interactive)
- (let ((standard-output (current-buffer)))
- (terpri)
- (eval-last-sexp t)
- (terpri)))
-
-(defun eval-last-sexp (eval-last-sexp-arg-internal)
- "Evaluate sexp before point; print value in minibuffer.
-With argument, print output into current buffer."
- (interactive "P")
- (let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t))
- (opoint (point)))
- (prin1 (let ((stab (syntax-table)))
- (eval (unwind-protect
- (save-excursion
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (forward-sexp -1)
- (save-restriction
- (narrow-to-region (point-min) opoint)
- (read (current-buffer))))
- (set-syntax-table stab)))))))
-
-(defun eval-defun (eval-defun-arg-internal)
- "Evaluate defun that point is in or before.
-Print value in minibuffer.
-With argument, insert value in current buffer after the defun."
- (interactive "P")
- (let ((standard-output (if eval-defun-arg-internal (current-buffer) t))
- (form (save-excursion
- (end-of-defun)
- (beginning-of-defun)
- (read (current-buffer)))))
- (if (and (eq (car form) 'defvar)
- (cdr-safe (cdr-safe form)))
- (setq form (cons 'defconst (cdr form))))
- (prin1 (eval form))))
-
-(defun lisp-comment-indent ()
- (if (looking-at "\\s<\\s<\\s<")
- (current-column)
- (if (looking-at "\\s<\\s<")
- (let ((tem (calculate-lisp-indent)))
- (if (listp tem) (car tem) tem))
- (skip-chars-backward " \t")
- (max (if (bolp) 0 (1+ (current-column)))
- comment-column))))
-
-(defvar lisp-indent-offset nil "")
-(defvar lisp-indent-function 'lisp-indent-function "")
-
-(defun lisp-indent-line (&optional whole-exp)
- "Indent current line as Lisp code.
-With argument, indent any additional lines of the same expression
-rigidly along with this one."
- (interactive "P")
- (let ((indent (calculate-lisp-indent)) shift-amt beg end
- (pos (- (point-max) (point))))
- (beginning-of-line)
- (setq beg (point))
- (skip-chars-forward " \t")
- (if (looking-at "\\s<\\s<\\s<")
- ;; Don't alter indentation of a ;;; comment line.
- (goto-char (- (point-max) pos))
- (if (and (looking-at "\\s<") (not (looking-at "\\s<\\s<")))
- ;; Single-semicolon comment lines should be indented
- ;; as comment lines, not as code.
- (progn (indent-for-comment) (forward-char -1))
- (if (listp indent) (setq indent (car indent)))
- (setq shift-amt (- indent (current-column)))
- (if (zerop shift-amt)
- nil
- (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)))
- ;; If desired, shift remaining lines of expression the same amount.
- (and whole-exp (not (zerop shift-amt))
- (save-excursion
- (goto-char beg)
- (forward-sexp 1)
- (setq end (point))
- (goto-char beg)
- (forward-line 1)
- (setq beg (point))
- (> end beg))
- (indent-code-rigidly beg end shift-amt)))))
-
-(defvar calculate-lisp-indent-last-sexp)
-
-(defun calculate-lisp-indent (&optional parse-start)
- "Return appropriate indentation for current line as Lisp code.
-In usual case returns an integer: the column to indent to.
-Can instead return a list, whose car is the column to indent to.
-This means that following lines at the same level of indentation
-should not necessarily be indented the same way.
-The second element of the list is the buffer position
-of the start of the containing expression."
- (save-excursion
- (beginning-of-line)
- (let ((indent-point (point))
- state paren-depth
- ;; setting this to a number inhibits calling hook
- (desired-indent nil)
- (retry t)
- calculate-lisp-indent-last-sexp containing-sexp)
- (if parse-start
- (goto-char parse-start)
- (beginning-of-defun))
- ;; Find outermost containing sexp
- (while (< (point) indent-point)
- (setq state (parse-partial-sexp (point) indent-point 0)))
- ;; Find innermost containing sexp
- (while (and retry
- state
- (> (setq paren-depth (elt state 0)) 0))
- (setq retry nil)
- (setq calculate-lisp-indent-last-sexp (elt state 2))
- (setq containing-sexp (elt state 1))
- ;; Position following last unclosed open.
- (goto-char (1+ containing-sexp))
- ;; Is there a complete sexp since then?
- (if (and calculate-lisp-indent-last-sexp
- (> calculate-lisp-indent-last-sexp (point)))
- ;; Yes, but is there a containing sexp after that?
- (let ((peek (parse-partial-sexp calculate-lisp-indent-last-sexp
- indent-point 0)))
- (if (setq retry (car (cdr peek))) (setq state peek)))))
- (if retry
- nil
- ;; Innermost containing sexp found
- (goto-char (1+ containing-sexp))
- (if (not calculate-lisp-indent-last-sexp)
- ;; indent-point immediately follows open paren.
- ;; Don't call hook.
- (setq desired-indent (current-column))
- ;; Find the start of first element of containing sexp.
- (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
- (cond ((looking-at "\\s(")
- ;; First element of containing sexp is a list.
- ;; Indent under that list.
- )
- ((> (save-excursion (forward-line 1) (point))
- calculate-lisp-indent-last-sexp)
- ;; This is the first line to start within the containing sexp.
- ;; It's almost certainly a function call.
- (if (= (point) calculate-lisp-indent-last-sexp)
- ;; Containing sexp has nothing before this line
- ;; except the first element. Indent under that element.
- nil
- ;; Skip the first element, find start of second (the first
- ;; argument of the function call) and indent under.
- (progn (forward-sexp 1)
- (parse-partial-sexp (point)
- calculate-lisp-indent-last-sexp
- 0 t)))
- (backward-prefix-chars))
- (t
- ;; Indent beneath first sexp on same line as
- ;; calculate-lisp-indent-last-sexp. Again, it's
- ;; almost certainly a function call.
- (goto-char calculate-lisp-indent-last-sexp)
- (beginning-of-line)
- (parse-partial-sexp (point) calculate-lisp-indent-last-sexp
- 0 t)
- (backward-prefix-chars)))))
- ;; Point is at the point to indent under unless we are inside a string.
- ;; Call indentation hook except when overridden by lisp-indent-offset
- ;; or if the desired indentation has already been computed.
- (let ((normal-indent (current-column)))
- (cond ((elt state 3)
- ;; Inside a string, don't change indentation.
- (goto-char indent-point)
- (skip-chars-forward " \t")
- (current-column))
- ((and (integerp lisp-indent-offset) containing-sexp)
- ;; Indent by constant offset
- (goto-char containing-sexp)
- (+ (current-column) lisp-indent-offset))
- (desired-indent)
- ((and (boundp 'lisp-indent-function)
- lisp-indent-function
- (not retry))
- (or (funcall lisp-indent-function indent-point state)
- normal-indent))
- (t
- normal-indent))))))
-
-(defun lisp-indent-function (indent-point state)
- (let ((normal-indent (current-column)))
- (goto-char (1+ (elt state 1)))
- (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
- (if (and (elt state 2)
- (not (looking-at "\\sw\\|\\s_")))
- ;; car of form doesn't seem to be a a symbol
- (progn
- (if (not (> (save-excursion (forward-line 1) (point))
- calculate-lisp-indent-last-sexp))
- (progn (goto-char calculate-lisp-indent-last-sexp)
- (beginning-of-line)
- (parse-partial-sexp (point)
- calculate-lisp-indent-last-sexp 0 t)))
- ;; Indent under the list or under the first sexp on the same
- ;; line as calculate-lisp-indent-last-sexp. Note that first
- ;; thing on that line has to be complete sexp since we are
- ;; inside the innermost containing sexp.
- (backward-prefix-chars)
- (current-column))
- (let ((function (buffer-substring (point)
- (progn (forward-sexp 1) (point))))
- method)
- (setq method (or (get (intern-soft function) 'lisp-indent-function)
- (get (intern-soft function) 'lisp-indent-hook)))
- (cond ((or (eq method 'defun)
- (and (null method)
- (> (length function) 3)
- (string-match "\\`def" function)))
- (lisp-indent-defform state indent-point))
- ((integerp method)
- (lisp-indent-specform method state
- indent-point normal-indent))
- (method
- (funcall method state indent-point)))))))
-
-(defvar lisp-body-indent 2
- "Number of columns to indent the second line of a `(def...)' form.")
-
-(defun lisp-indent-specform (count state indent-point normal-indent)
- (let ((containing-form-start (elt state 1))
- (i count)
- 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
- ;; least one word or symbol character following open paren of containing
- ;; form.
- (goto-char containing-form-start)
- (setq containing-form-column (current-column))
- (setq body-indent (+ lisp-body-indent containing-form-column))
- (forward-char 1)
- (forward-sexp 1)
- ;; Now find the start of the last form.
- (parse-partial-sexp (point) indent-point 1 t)
- (while (and (< (point) indent-point)
- (condition-case ()
- (progn
- (setq count (1- count))
- (forward-sexp 1)
- (parse-partial-sexp (point) indent-point 1 t))
- (error nil))))
- ;; Point is sitting on first character of last (or count) sexp.
- (if (> count 0)
- ;; A distinguished form. If it is the first or second form use double
- ;; lisp-body-indent, else normal indent. With lisp-body-indent bound
- ;; to 2 (the default), this just happens to work the same with if as
- ;; the older code, but it makes unwind-protect, condition-case,
- ;; with-output-to-temp-buffer, et. al. much more tasteful. The older,
- ;; less hacked, behavior can be obtained by replacing below with
- ;; (list normal-indent containing-form-start).
- (if (<= (- i count) 1)
- (list (+ containing-form-column (* 2 lisp-body-indent))
- containing-form-start)
- (list normal-indent containing-form-start))
- ;; A non-distinguished form. Use body-indent if there are no
- ;; distinguished forms and this is the first undistinguished form,
- ;; or if this is the first undistinguished form and the preceding
- ;; distinguished form has indentation at least as great as body-indent.
- (if (or (and (= i 0) (= count 0))
- (and (= count 0) (<= body-indent normal-indent)))
- body-indent
- normal-indent))))
-
-(defun lisp-indent-defform (state indent-point)
- (goto-char (car (cdr state)))
- (forward-line 1)
- (if (> (point) (car (cdr (cdr state))))
- (progn
- (goto-char (car (cdr state)))
- (+ lisp-body-indent (current-column)))))
-
-
-;; (put 'progn 'lisp-indent-function 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-selected-window 'lisp-indent-function 0)
-(put 'save-restriction 'lisp-indent-function 0)
-(put 'save-match-data 'lisp-indent-function 0)
-(put 'save-current-buffer 'lisp-indent-function 0)
-(put 'with-current-buffer 'lisp-indent-function 1)
-(put 'combine-after-change-calls 'lisp-indent-function 0)
-(put 'with-output-to-string 'lisp-indent-function 0)
-(put 'with-temp-file 'lisp-indent-function 1)
-(put 'with-temp-buffer '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)
-(put 'eval-after-load '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."
- (interactive)
- (let ((indent-stack (list nil))
- (next-depth 0)
- ;; If ENDPOS is non-nil, use nil as STARTING-POINT
- ;; so that calculate-lisp-indent will find the beginning of
- ;; the defun we are in.
- ;; If ENDPOS is nil, it is safe not to scan before point
- ;; since every line we indent is more deeply nested than point is.
- (starting-point (if endpos nil (point)))
- (last-point (point))
- last-depth bol outer-loop-done inner-loop-done state this-indent)
- (or endpos
- ;; 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))
- (setq last-depth next-depth
- inner-loop-done nil)
- ;; Parse this line so we can learn the state
- ;; to indent the next line.
- ;; This inner loop goes through only once
- ;; unless a line ends inside a string.
- (while (and (not inner-loop-done)
- (not (setq outer-loop-done (eobp))))
- (setq state (parse-partial-sexp (point) (progn (end-of-line) (point))
- nil nil state))
- (setq next-depth (car state))
- ;; If the line contains a comment other than the sort
- ;; that is indented like code,
- ;; indent it now with indent-for-comment.
- ;; Comments indented like code are right already.
- ;; In any case clear the in-comment flag in the state
- ;; because parse-partial-sexp never sees the newlines.
- (if (car (nthcdr 4 state))
- (progn (indent-for-comment)
- (end-of-line)
- (setcar (nthcdr 4 state) nil)))
- ;; If this line ends inside a string,
- ;; go straight to next line, remaining within the inner loop,
- ;; and turn off the \-flag.
- (if (car (nthcdr 3 state))
- (progn
- (forward-line 1)
- (setcar (nthcdr 5 state) nil))
- (setq inner-loop-done t)))
- (and endpos
- (<= next-depth 0)
- (progn
- (setq indent-stack (append indent-stack
- (make-list (- next-depth) nil))
- last-depth (- last-depth next-depth)
- next-depth 0)))
- (or outer-loop-done endpos
- (setq outer-loop-done (<= next-depth 0)))
- (if outer-loop-done
- (forward-line 1)
- (while (> last-depth next-depth)
- (setq indent-stack (cdr indent-stack)
- last-depth (1- last-depth)))
- (while (< last-depth next-depth)
- (setq indent-stack (cons nil indent-stack)
- last-depth (1+ last-depth)))
- ;; Now go to the next line and indent it according
- ;; to what we learned from parsing the previous one.
- (forward-line 1)
- (setq bol (point))
- (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"))
- 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))
- starting-point))))
- (if (integerp val)
- (setcar indent-stack
- (setq this-indent val))
- (setcar indent-stack (- (car (cdr val))))
- (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
- (let ((endmark (copy-marker end)))
- (goto-char start)
- (and (bolp) (not (eolp))
- (lisp-indent-line))
- (indent-sexp endmark)
- (set-marker endmark nil))))
-
-;;;; Lisp paragraph filling commands.
-
-(defun lisp-fill-paragraph (&optional justify)
- "Like \\[fill-paragraph], but handle Emacs Lisp comments.
-If any of the current line is a comment, fill the comment or the
-paragraph of it that point is in, preserving the comment's indentation
-and initial semicolons."
- (interactive "P")
- (let (
- ;; Non-nil if the current line contains a comment.
- has-comment
-
- ;; Non-nil if the current line contains code and a comment.
- has-code-and-comment
-
- ;; If has-comment, the appropriate fill-prefix for the comment.
- comment-fill-prefix
- )
-
- ;; Figure out what kind of comment we are looking at.
- (save-excursion
- (beginning-of-line)
- (cond
-
- ;; A line with nothing but a comment on it?
- ((looking-at "[ \t]*;[; \t]*")
- (setq has-comment t
- comment-fill-prefix (buffer-substring (match-beginning 0)
- (match-end 0))))
-
- ;; A line with some code, followed by a comment? Remember that the
- ;; semi which starts the comment shouldn't be part of a string or
- ;; character.
- ((condition-case nil
- (save-restriction
- (narrow-to-region (point-min)
- (save-excursion (end-of-line) (point)))
- (while (not (looking-at ";\\|$"))
- (skip-chars-forward "^;\n\"\\\\?")
- (cond
- ((eq (char-after (point)) ?\\) (forward-char 2))
- ((memq (char-after (point)) '(?\" ??)) (forward-sexp 1))))
- (looking-at ";+[\t ]*"))
- (error nil))
- (setq has-comment t has-code-and-comment t)
- (setq comment-fill-prefix
- (concat (make-string (/ (current-column) 8) ?\t)
- (make-string (% (current-column) 8) ?\ )
- (buffer-substring (match-beginning 0) (match-end 0)))))))
-
- (if (not has-comment)
- (fill-paragraph justify)
-
- ;; Narrow to include only the comment, and then fill the region.
- (save-excursion
- (save-restriction
- (beginning-of-line)
- (narrow-to-region
- ;; Find the first line we should include in the region to fill.
- (save-excursion
- (while (and (zerop (forward-line -1))
- (looking-at "^[ \t]*;")))
- ;; We may have gone too far. Go forward again.
- (or (looking-at ".*;")
- (forward-line 1))
- (point))
- ;; Find the beginning of the first line past the region to fill.
- (save-excursion
- (while (progn (forward-line 1)
- (looking-at "^[ \t]*;")))
- (point)))
-
- ;; Lines with only semicolons on them can be paragraph boundaries.
- (let* ((paragraph-start (concat paragraph-start "\\|[ \t;]*$"))
- (paragraph-separate (concat paragraph-start "\\|[ \t;]*$"))
- (paragraph-ignore-fill-prefix nil)
- (fill-prefix comment-fill-prefix)
- (after-line (if has-code-and-comment
- (save-excursion
- (forward-line 1) (point))))
- (end (progn
- (forward-paragraph)
- (or (bolp) (newline 1))
- (point)))
- ;; If this comment starts on a line with code,
- ;; include that like in the filling.
- (beg (progn (backward-paragraph)
- (if (eq (point) after-line)
- (forward-line -1))
- (point))))
- (fill-region-as-paragraph beg end
- justify nil
- (save-excursion
- (goto-char beg)
- (if (looking-at fill-prefix)
- nil
- (re-search-forward comment-start-skip)
- (point))))))))
- t))
-
-(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.
-
-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."
- (interactive "r\np")
- (let (state)
- (save-excursion
- (goto-char end)
- (setq end (point-marker))
- (goto-char start)
- (or (bolp)
- (setq state (parse-partial-sexp (point)
- (progn
- (forward-line 1) (point))
- nil nil state)))
- (while (< (point) end)
- (or (car (nthcdr 3 state))
- (and nochange-regexp
- (looking-at nochange-regexp))
- ;; If line does not start in string, indent it
- (let ((indent (current-indentation)))
- (delete-region (point) (progn (skip-chars-forward " \t") (point)))
- (or (eolp)
- (indent-to (max 0 (+ indent arg)) 0))))
- (setq state (parse-partial-sexp (point)
- (progn
- (forward-line 1) (point))
- nil nil state))))))
-
-(provide 'lisp-mode)
-
-;;; lisp-mode.el ends here
diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el
deleted file mode 100644
index 767c96e620b..00000000000
--- a/lisp/emacs-lisp/lisp.el
+++ /dev/null
@@ -1,316 +0,0 @@
-;;; lisp.el --- Lisp editing commands for Emacs
-
-;; Copyright (C) 1985, 1986, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: lisp, languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Lisp editing commands to go with Lisp major mode.
-
-;;; Code:
-
-;; Note that this variable is used by non-lisp modes too.
-(defvar defun-prompt-regexp nil
- "*Non-nil => regexp to ignore, before the character that starts a defun.
-This is only necessary if the opening paren or brace is not in column 0.
-See `beginning-of-defun'.")
-(make-variable-buffer-local 'defun-prompt-regexp)
-
-(defvar parens-require-spaces t
- "Non-nil => `insert-parentheses' should insert whitespace as needed.")
-
-(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."
- (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."
- (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."
- (interactive "p")
- (push-mark
- (save-excursion
- (forward-sexp arg)
- (point))
- nil t))
-
-(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."
- (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."
- (interactive "p")
- (or arg (setq arg 1))
- (forward-list (- arg)))
-
-(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."
- (interactive "p")
- (let ((inc (if (> arg 0) 1 -1)))
- (while (/= arg 0)
- (goto-char (or (scan-lists (point) inc -1) (buffer-end arg)))
- (setq arg (- arg inc)))))
-
-(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."
- (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."
- (interactive "p")
- (let ((inc (if (> arg 0) 1 -1)))
- (while (/= arg 0)
- (goto-char (or (scan-lists (point) inc 1) (buffer-end arg)))
- (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."
- (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."
- (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, and point ends up at the beginning of the line."
- (interactive "p")
- (and (beginning-of-defun-raw arg)
- (progn (beginning-of-line) t)))
-
-(defun beginning-of-defun-raw (&optional arg)
- "Move point to the character that starts a defun.
-This is identical to beginning-of-defun, except that point does not move
-to the beginning of the line when `defun-prompt-regexp' is non-nil."
- (interactive "p")
- (and arg (< arg 0) (not (eobp)) (forward-char 1))
- (and (re-search-backward (if defun-prompt-regexp
- (concat "^\\s(\\|"
- "\\(" defun-prompt-regexp "\\)\\s(")
- "^\\s(")
- nil 'move (or arg 1))
- (progn (goto-char (1- (match-end 0)))) 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'."
- (interactive "p")
- (if (or (null arg) (= arg 0)) (setq arg 1))
- (let ((first t))
- (while (and (> arg 0) (< (point) (point-max)))
- (let ((pos (point)) npos)
- (while (progn
- (if (and first
- (progn
- (end-of-line 1)
- (beginning-of-defun-raw 1)))
- nil
- (or (bobp) (forward-char -1))
- (beginning-of-defun-raw -1))
- (setq first nil)
- (forward-list 1)
- (skip-chars-forward " \t")
- (if (looking-at "\\s<\\|\n")
- (forward-line 1))
- (<= (point) pos))))
- (setq arg (1- arg)))
- (while (< arg 0)
- (let ((pos (point)))
- (beginning-of-defun-raw 1)
- (forward-sexp 1)
- (forward-line 1)
- (if (>= (point) pos)
- (if (beginning-of-defun-raw 2)
- (progn
- (forward-list 1)
- (skip-chars-forward " \t")
- (if (looking-at "\\s<\\|\n")
- (forward-line 1)))
- (goto-char (point-min)))))
- (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."
- (interactive)
- (push-mark (point))
- (end-of-defun)
- (push-mark (point) nil t)
- (beginning-of-defun)
- (re-search-backward "^\n" (- (point) 1) t))
-
-(defun narrow-to-defun (&optional arg)
- "Make text outside current defun invisible.
-The defun visible is the one that contains point or follows point."
- (interactive)
- (save-excursion
- (widen)
- (end-of-defun)
- (let ((end (point)))
- (beginning-of-defun)
- (narrow-to-region (point) end))))
-
-(defun insert-parentheses (arg)
- "Enclose following ARG sexps in parentheses. Leave point after open-paren.
-A negative ARG encloses the preceding ARG sexps instead.
-No argument is equivalent to zero: just insert `()' and leave point between.
-If `parens-require-spaces' is non-nil, this command also inserts a space
-before and after, depending on the surrounding characters."
- (interactive "P")
- (if arg (setq arg (prefix-numeric-value arg))
- (setq arg 0))
- (cond ((> arg 0) (skip-chars-forward " \t"))
- ((< arg 0) (forward-sexp arg) (setq arg (- arg))))
- (and parens-require-spaces
- (not (bobp))
- (memq (char-syntax (preceding-char)) '(?w ?_ ?\) ))
- (insert " "))
- (insert ?\()
- (save-excursion
- (or (eq arg 0) (forward-sexp arg))
- (insert ?\))
- (and parens-require-spaces
- (not (eobp))
- (memq (char-syntax (following-char)) '(?w ?_ ?\( ))
- (insert " "))))
-
-(defun move-past-close-and-reindent ()
- "Move past next `)', delete indentation before it, then indent after it."
- (interactive)
- (up-list 1)
- (forward-char -1)
- (while (save-excursion ; this is my contribution
- (let ((before-paren (point)))
- (back-to-indentation)
- (= (point) before-paren)))
- (delete-indentation))
- (forward-char 1)
- (newline-and-indent))
-
-(defun lisp-complete-symbol ()
- "Perform completion on Lisp symbol preceding point.
-Compare that symbol against the known Lisp symbols.
-
-The context determines which symbols are considered.
-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))
- (beg (unwind-protect
- (save-excursion
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (backward-sexp 1)
- (while (= (char-syntax (following-char)) ?\')
- (forward-char 1))
- (point))
- (set-syntax-table buffer-syntax)))
- (pattern (buffer-substring beg end))
- (predicate
- (if (eq (char-after (1- beg)) ?\()
- 'fboundp
- (function (lambda (sym)
- (or (boundp sym) (fboundp sym)
- (symbol-plist sym))))))
- (completion (try-completion pattern obarray predicate)))
- (cond ((eq completion t))
- ((null completion)
- (message "Can't find completion for \"%s\"" pattern)
- (ding))
- ((not (string= pattern completion))
- (delete-region beg end)
- (insert completion))
- (t
- (message "Making completion list...")
- (let ((list (all-completions pattern obarray predicate))
- (completion-fixup-function
- (function (lambda () (if (save-excursion
- (goto-char (max (point-min) (- (point) 4)))
- (looking-at " <f>"))
- (forward-char -4))))))
- (setq list (sort list 'string<))
- (or (eq predicate 'fboundp)
- (let (new)
- (while list
- (setq new (cons (if (fboundp (intern (car list)))
- (list (car list) " <f>")
- (car list))
- new))
- (setq list (cdr list)))
- (setq list (nreverse new))))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list list)))
- (message "Making completion list...%s" "done")))))
-
-;;; lisp.el ends here
diff --git a/lisp/emacs-lisp/lmenu.el b/lisp/emacs-lisp/lmenu.el
deleted file mode 100644
index a878f6ca206..00000000000
--- a/lisp/emacs-lisp/lmenu.el
+++ /dev/null
@@ -1,506 +0,0 @@
-;;; lmenu.el --- emulate Lucid's menubar support
-
-;; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
-
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-
-;; First, emulate the Lucid menubar support in GNU Emacs 19.
-
-;; Arrange to use current-menubar to set up part of the menu bar.
-
-(defvar current-menubar)
-
-(setq recompute-lucid-menubar 'recompute-lucid-menubar)
-(defun recompute-lucid-menubar ()
- (define-key lucid-menubar-map [menu-bar]
- (condition-case nil
- (make-lucid-menu-keymap "menu-bar" current-menubar)
- (error (message "Invalid data in current-menubar moved to lucid-failing-menubar")
- (sit-for 1)
- (setq lucid-failing-menubar current-menubar
- current-menubar nil))))
- (setq lucid-menu-bar-dirty-flag nil))
-
-(defvar lucid-menubar-map (make-sparse-keymap))
-(or (assq 'current-menubar minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons (cons 'current-menubar lucid-menubar-map)
- minor-mode-map-alist)))
-
-(defun set-menubar-dirty-flag ()
- (force-mode-line-update)
- (setq lucid-menu-bar-dirty-flag t))
-
-(defvar add-menu-item-count 0)
-
-;; This is a variable whose value is always nil.
-(defvar make-lucid-menu-keymap-disable nil)
-
-;; Return a menu keymap corresponding to a Lucid-style menu list
-;; MENU-ITEMS, and with name MENU-NAME.
-(defun make-lucid-menu-keymap (menu-name menu-items)
- (let ((menu (make-sparse-keymap menu-name)))
- ;; Process items in reverse order,
- ;; since the define-key loop reverses them again.
- (setq menu-items (reverse menu-items))
- (while menu-items
- (let ((item (car menu-items))
- command name callback)
- (cond ((stringp item)
- (setq command nil)
- (setq name (if (string-match "^-+$" item) "" item)))
- ((consp item)
- (setq command (make-lucid-menu-keymap (car item) (cdr item)))
- (setq name (car item)))
- ((vectorp item)
- (setq command (make-symbol (format "menu-function-%d"
- add-menu-item-count))
- add-menu-item-count (1+ add-menu-item-count)
- name (aref item 0)
- callback (aref item 1))
- (if (symbolp callback)
- (fset command callback)
- (fset command (list 'lambda () '(interactive) callback)))
- (put command 'menu-alias t)
- (let ((i 2))
- (while (< i (length item))
- (cond
- ((eq (aref item i) ':active)
- (put command 'menu-enable
- (or (aref item (1+ i))
- 'make-lucid-menu-keymap-disable))
- (setq i (+ 2 i)))
- ((eq (aref item i) ':suffix)
- ;; unimplemented
- (setq i (+ 2 i)))
- ((eq (aref item i) ':keys)
- ;; unimplemented
- (setq i (+ 2 i)))
- ((eq (aref item i) ':style)
- ;; unimplemented
- (setq i (+ 2 i)))
- ((eq (aref item i) ':selected)
- ;; unimplemented
- (setq i (+ 2 i)))
- ((and (symbolp (aref item i))
- (= ?: (string-to-char (symbol-name (aref item i)))))
- (error "Unrecognized menu item keyword: %S"
- (aref item i)))
- ((= i 2)
- ;; old-style format: active-p &optional suffix
- (put command 'menu-enable
- (or (aref item i) 'make-lucid-menu-keymap-disable))
- ;; suffix is unimplemented
- (setq i (length item)))
- (t
- (error "Unexpected menu item value: %S"
- (aref item i))))))))
- (if (null command)
- ;; Handle inactive strings specially--allow any number
- ;; of identical ones.
- (setcdr menu (cons (list nil name) (cdr menu)))
- (if name
- (define-key menu (vector (intern name)) (cons name command)))))
- (setq menu-items (cdr menu-items)))
- menu))
-
-(defun popup-menu (menu-desc)
- "Pop up the given menu.
-A menu is a list of menu items, strings, and submenus.
-
-The first element of a menu must be a string, which is the name of the
-menu. This is the string that will be displayed in the parent menu, if
-any. For toplevel menus, it is ignored. This string is not displayed
-in the menu itself.
-
-A menu item is a vector containing:
-
- - the name of the menu item (a string);
- - the `callback' of that item;
- - a list of keywords with associated values:
- - :active active-p a form specifying whether this item is selectable;
- - :suffix suffix a string to be appended to the name as an `argument'
- to the command, like `Kill Buffer NAME';
- - :keys command-keys a string, suitable for `substitute-command-keys',
- to specify the keyboard equivalent of a command
- when the callback is a form (this is not necessary
- when the callback is a symbol, as the keyboard
- equivalent is computed automatically in that case);
- - :style style a symbol: nil for a normal menu item, `toggle' for
- a toggle button (a single option that can be turned
- on or off), or `radio' for a radio button (one of a
- group of mutually exclusive options);
- - :selected form for `toggle' or `radio' style, a form that specifies
- whether the button will be in the selected state.
-
-Alternately, the vector may contain exactly 3 or 4 elements, with the third
-element specifying `active-p' and the fourth specifying `suffix'.
-
-If the `callback' of a menu item is a symbol, then it must name a command.
-It will be invoked with `call-interactively'. If it is a list, then it is
-evaluated with `eval'.
-
-If an element of a menu is a string, then that string will be presented in
-the menu as unselectable text.
-
-If an element of a menu is a string consisting solely of hyphens, then that
-item will be presented as a solid horizontal line.
-
-If an element of a menu is a list, it is treated as a submenu. The name of
-that submenu (the first element in the list) will be used as the name of the
-item representing this menu on the parent.
-
-The syntax, more precisely:
-
- form := <something to pass to `eval'>
- command := <a symbol or string, to pass to `call-interactively'>
- callback := command | form
- active-p := <t or nil, whether this thing is selectable>
- text := <string, non selectable>
- name := <string>
- suffix := <string>
- command-keys := <string>
- object-style := 'nil' | 'toggle' | 'radio'
- keyword := ':active' active-p
- | ':suffix' suffix
- | ':keys' command-keys
- | ':style' object-style
- | ':selected' form
- menu-item := '[' name callback active-p [ suffix ] ']'
- | '[' name callback [ keyword ]+ ']'
- menu := '(' name [ menu-item | menu | text ]+ ')'"
- (let ((menu (make-lucid-menu-keymap (car menu-desc) (cdr menu-desc)))
- (pos (mouse-pixel-position))
- answer cmd)
- (while (and menu
- (setq answer (x-popup-menu (list (list (nth 1 pos)
- (nthcdr 2 pos))
- (car pos))
- menu)))
- (setq cmd (lookup-key menu (apply 'vector answer)))
- (setq menu nil)
- (and cmd
- (if (keymapp cmd)
- (setq menu cmd)
- (call-interactively cmd))))))
-
-(defun popup-dialog-box (data)
- "Pop up a dialog box.
-A dialog box description is a list.
-
- - The first element of the list is a string to display in the dialog box.
- - The rest of the elements are descriptions of the dialog box's buttons.
- Each one is a vector of three elements:
- - The first element is the text of the button.
- - The second element is the `callback'.
- - The third element is t or nil, whether this button is selectable.
-
-If the `callback' of a button is a symbol, then it must name a command.
-It will be invoked with `call-interactively'. If it is a list, then it is
-evaluated with `eval'.
-
-One (and only one) of the buttons may be `nil'. This marker means that all
-following buttons should be flushright instead of flushleft.
-
-The syntax, more precisely:
-
- form := <something to pass to `eval'>
- command := <a symbol or string, to pass to `call-interactively'>
- callback := command | form
- active-p := <t, nil, or a form to evaluate to decide whether this
- button should be selectable>
- name := <string>
- partition := 'nil'
- button := '[' name callback active-p ']'
- dialog := '(' name [ button ]+ [ partition [ button ]+ ] ')'"
- (let ((name (car data))
- (tail (cdr data))
- converted
- choice meaning)
- (while tail
- (if (null (car tail))
- (setq converted (cons nil converted))
- (let ((item (aref (car tail) 0))
- (callback (aref (car tail) 1))
- (enable (aref (car tail) 2)))
- (setq converted
- (cons (if enable (cons item callback) item)
- converted))))
- (setq tail (cdr tail)))
- (setq choice (x-popup-dialog t (cons name (nreverse converted))))
- (if choice
- (if (symbolp choice)
- (call-interactively choice)
- (eval choice)))))
-
-;; This is empty because the usual elements of the menu bar
-;; are provided by menu-bar.el instead.
-;; It would not make sense to duplicate them here.
-(defconst default-menubar nil)
-
-(defun set-menubar (menubar)
- "Set the default menubar to be menubar."
- (setq-default current-menubar (copy-sequence menubar))
- (set-menubar-dirty-flag))
-
-(defun set-buffer-menubar (menubar)
- "Set the buffer-local menubar to be menubar."
- (make-local-variable 'current-menubar)
- (setq current-menubar (copy-sequence menubar))
- (set-menubar-dirty-flag))
-
-
-;;; menu manipulation functions
-
-(defun find-menu-item (menubar item-path-list &optional parent)
- "Searches MENUBAR for item given by ITEM-PATH-LIST.
-Returns (ITEM . PARENT), where PARENT is the immediate parent of
- the item found.
-Signals an error if the item is not found."
- (or parent (setq item-path-list (mapcar 'downcase item-path-list)))
- (if (not (consp menubar))
- nil
- (let ((rest menubar)
- result)
- (while rest
- (if (and (car rest)
- (equal (car item-path-list)
- (downcase (if (vectorp (car rest))
- (aref (car rest) 0)
- (if (stringp (car rest))
- (car rest)
- (car (car rest)))))))
- (setq result (car rest) rest nil)
- (setq rest (cdr rest))))
- (if (cdr item-path-list)
- (if (consp result)
- (find-menu-item (cdr result) (cdr item-path-list) result)
- (if result
- (signal 'error (list "not a submenu" result))
- (signal 'error (list "no such submenu" (car item-path-list)))))
- (cons result parent)))))
-
-
-(defun disable-menu-item (path)
- "Make the named menu item be unselectable.
-PATH is a list of strings which identify the position of the menu item in
-the menu hierarchy. (\"File\" \"Save\") means the menu item called \"Save\"
-under the toplevel \"File\" menu. (\"Menu\" \"Foo\" \"Item\") means the
-menu item called \"Item\" under the \"Foo\" submenu of \"Menu\"."
- (let* ((menubar current-menubar)
- (pair (find-menu-item menubar path))
- (item (car pair))
- (menu (cdr pair)))
- (or item
- (signal 'error (list (if menu "No such menu item" "No such menu")
- path)))
- (if (consp item) (error "can't disable menus, only menu items"))
- (aset item 2 nil)
- (set-menubar-dirty-flag)
- item))
-
-
-(defun enable-menu-item (path)
- "Make the named menu item be selectable.
-PATH is a list of strings which identify the position of the menu item in
-the menu hierarchy. (\"File\" \"Save\") means the menu item called \"Save\"
-under the toplevel \"File\" menu. (\"Menu\" \"Foo\" \"Item\") means the
-menu item called \"Item\" under the \"Foo\" submenu of \"Menu\"."
- (let* ((menubar current-menubar)
- (pair (find-menu-item menubar path))
- (item (car pair))
- (menu (cdr pair)))
- (or item
- (signal 'error (list (if menu "No such menu item" "No such menu")
- path)))
- (if (consp item) (error "%S is a menu, not a menu item" path))
- (aset item 2 t)
- (set-menubar-dirty-flag)
- item))
-
-
-(defun add-menu-item-1 (item-p menu-path item-name item-data enabled-p before)
- (if before (setq before (downcase before)))
- (let* ((menubar current-menubar)
- (menu (condition-case ()
- (car (find-menu-item menubar menu-path))
- (error nil)))
- (item (if (listp menu)
- (car (find-menu-item (cdr menu) (list item-name)))
- (signal 'error (list "not a submenu" menu-path)))))
- (or menu
- (let ((rest menu-path)
- (so-far menubar))
- (while rest
-;;; (setq menu (car (find-menu-item (cdr so-far) (list (car rest)))))
- (setq menu
- (if (eq so-far menubar)
- (car (find-menu-item so-far (list (car rest))))
- (car (find-menu-item (cdr so-far) (list (car rest))))))
- (or menu
- (let ((rest2 so-far))
- (or rest2
- (error "Trying to modify a menu that doesn't exist"))
- (while (and (cdr rest2) (car (cdr rest2)))
- (setq rest2 (cdr rest2)))
- (setcdr rest2
- (nconc (list (setq menu (list (car rest))))
- (cdr rest2)))))
- (setq so-far menu)
- (setq rest (cdr rest)))))
- (or menu (setq menu menubar))
- (if item
- nil ; it's already there
- (if item-p
- (setq item (vector item-name item-data enabled-p))
- (setq item (cons item-name item-data)))
- ;; if BEFORE is specified, try to add it there.
- (if before
- (setq before (car (find-menu-item menu (list before)))))
- (let ((rest menu)
- (added-before nil))
- (while rest
- (if (eq before (car (cdr rest)))
- (progn
- (setcdr rest (cons item (cdr rest)))
- (setq rest nil added-before t))
- (setq rest (cdr rest))))
- (if (not added-before)
- ;; adding before the first item on the menubar itself is harder
- (if (and (eq menu menubar) (eq before (car menu)))
- (setq menu (cons item menu)
- current-menubar menu)
- ;; otherwise, add the item to the end.
- (nconc menu (list item))))))
- (if item-p
- (progn
- (aset item 1 item-data)
- (aset item 2 (not (null enabled-p))))
- (setcar item item-name)
- (setcdr item item-data))
- (set-menubar-dirty-flag)
- item))
-
-(defun add-menu-item (menu-path item-name function enabled-p &optional before)
- "Add a menu item to some menu, creating the menu first if necessary.
-If the named item exists already, it is changed.
-MENU-PATH identifies the menu under which the new menu item should be inserted.
- It is a list of strings; for example, (\"File\") names the top-level \"File\"
- menu. (\"File\" \"Foo\") names a hypothetical submenu of \"File\".
-ITEM-NAME is the string naming the menu item to be added.
-FUNCTION is the command to invoke when this menu item is selected.
- If it is a symbol, then it is invoked with `call-interactively', in the same
- way that functions bound to keys are invoked. If it is a list, then the
- list is simply evaluated.
-ENABLED-P controls whether the item is selectable or not.
-BEFORE, if provided, is the name of a menu item before which this item should
- be added, if this item is not on the menu already. If the item is already
- present, it will not be moved."
- (or menu-path (error "must specify a menu path"))
- (or item-name (error "must specify an item name"))
- (add-menu-item-1 t menu-path item-name function enabled-p before))
-
-
-(defun delete-menu-item (path)
- "Remove the named menu item from the menu hierarchy.
-PATH is a list of strings which identify the position of the menu item in
-the menu hierarchy. (\"File\" \"Save\") means the menu item called \"Save\"
-under the toplevel \"File\" menu. (\"Menu\" \"Foo\" \"Item\") means the
-menu item called \"Item\" under the \"Foo\" submenu of \"Menu\"."
- (let* ((menubar current-menubar)
- (pair (find-menu-item menubar path))
- (item (car pair))
- (menu (or (cdr pair) menubar)))
- (if (not item)
- nil
- ;; the menubar is the only special case, because other menus begin
- ;; with their name.
- (if (eq menu current-menubar)
- (setq current-menubar (delq item menu))
- (delq item menu))
- (set-menubar-dirty-flag)
- item)))
-
-
-(defun relabel-menu-item (path new-name)
- "Change the string of the specified menu item.
-PATH is a list of strings which identify the position of the menu item in
-the menu hierarchy. (\"File\" \"Save\") means the menu item called \"Save\"
-under the toplevel \"File\" menu. (\"Menu\" \"Foo\" \"Item\") means the
-menu item called \"Item\" under the \"Foo\" submenu of \"Menu\".
-NEW-NAME is the string that the menu item will be printed as from now on."
- (or (stringp new-name)
- (setq new-name (signal 'wrong-type-argument (list 'stringp new-name))))
- (let* ((menubar current-menubar)
- (pair (find-menu-item menubar path))
- (item (car pair))
- (menu (cdr pair)))
- (or item
- (signal 'error (list (if menu "No such menu item" "No such menu")
- path)))
- (if (and (consp item)
- (stringp (car item)))
- (setcar item new-name)
- (aset item 0 new-name))
- (set-menubar-dirty-flag)
- item))
-
-(defun add-menu (menu-path menu-name menu-items &optional before)
- "Add a menu to the menubar or one of its submenus.
-If the named menu exists already, it is changed.
-MENU-PATH identifies the menu under which the new menu should be inserted.
- It is a list of strings; for example, (\"File\") names the top-level \"File\"
- menu. (\"File\" \"Foo\") names a hypothetical submenu of \"File\".
- If MENU-PATH is nil, then the menu will be added to the menubar itself.
-MENU-NAME is the string naming the menu to be added.
-MENU-ITEMS is a list of menu item descriptions.
- Each menu item should be a vector of three elements:
- - a string, the name of the menu item;
- - a symbol naming a command, or a form to evaluate;
- - and a form whose value determines whether this item is selectable.
-BEFORE, if provided, is the name of a menu before which this menu should
- be added, if this menu is not on its parent already. If the menu is already
- present, it will not be moved."
- (or menu-name (error "must specify a menu name"))
- (or menu-items (error "must specify some menu items"))
- (add-menu-item-1 nil menu-path menu-name menu-items t before))
-
-
-
-(defvar put-buffer-names-in-file-menu t)
-
-
-;; Don't unconditionally enable menu bars; leave that up to the user.
-;;(let ((frames (frame-list)))
-;; (while frames
-;; (modify-frame-parameters (car frames) '((menu-bar-lines . 1)))
-;; (setq frames (cdr frames))))
-;;(or (assq 'menu-bar-lines default-frame-alist)
-;; (setq default-frame-alist
-;; (cons '(menu-bar-lines . 1) default-frame-alist)))
-
-(set-menubar default-menubar)
-
-(provide 'lmenu)
-
-;;; lmenu.el ends here
diff --git a/lisp/emacs-lisp/lselect.el b/lisp/emacs-lisp/lselect.el
deleted file mode 100644
index c6c64a909f8..00000000000
--- a/lisp/emacs-lisp/lselect.el
+++ /dev/null
@@ -1,230 +0,0 @@
-;;; lselect.el --- Lucid interface to X Selections
-
-;; Copyright (C) 1990, 1993 Free Software Foundation, Inc.
-
-;; Keywords: emulations
-
-;; This won't completely work until we support or emulate Lucid-style extents.
-;; Based on Lucid's selection code.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;;; The selection code requires us to use certain symbols whose names are
-;;; all upper-case; this may seem tasteless, but it makes there be a 1:1
-;;; correspondence between these symbols and X Atoms (which are upcased.)
-
-(defalias 'x-get-cutbuffer 'x-get-cut-buffer)
-(defalias 'x-store-cutbuffer 'x-set-cut-buffer)
-
-(or (find-face 'primary-selection)
- (make-face 'primary-selection))
-
-(or (find-face 'secondary-selection)
- (make-face 'secondary-selection))
-
-(defun x-get-secondary-selection ()
- "Return text selected from some X window."
- (x-get-selection-internal 'SECONDARY 'STRING))
-
-(defvar primary-selection-extent nil
- "The extent of the primary selection; don't use this.")
-
-(defvar secondary-selection-extent nil
- "The extent of the secondary selection; don't use this.")
-
-
-(defun x-select-make-extent-for-selection (selection previous-extent face)
- ;; Given a selection, this makes an extent in the buffer which holds that
- ;; selection, for highlighting purposes. If the selection isn't associated
- ;; with a buffer, this does nothing.
- (let ((buffer nil)
- (valid (and (extentp previous-extent)
- (extent-buffer previous-extent)
- (buffer-name (extent-buffer previous-extent))))
- start end)
- (cond ((stringp selection)
- ;; if we're selecting a string, lose the previous extent used
- ;; to highlight the selection.
- (setq valid nil))
- ((consp selection)
- (setq start (min (car selection) (cdr selection))
- end (max (car selection) (cdr selection))
- valid (and valid
- (eq (marker-buffer (car selection))
- (extent-buffer previous-extent)))
- buffer (marker-buffer (car selection))))
- ((extentp selection)
- (setq start (extent-start-position selection)
- end (extent-end-position selection)
- valid (and valid
- (eq (extent-buffer selection)
- (extent-buffer previous-extent)))
- buffer (extent-buffer selection)))
- )
- (if (and (not valid)
- (extentp previous-extent)
- (extent-buffer previous-extent)
- (buffer-name (extent-buffer previous-extent)))
- (delete-extent previous-extent))
- (if (not buffer)
- ;; string case
- nil
- ;; normal case
- (if valid
- (set-extent-endpoints previous-extent start end)
- (setq previous-extent (make-extent start end buffer))
- ;; use same priority as mouse-highlighting so that conflicts between
- ;; the selection extent and a mouse-highlighted extent are resolved
- ;; by the usual size-and-endpoint-comparison method.
- (set-extent-priority previous-extent mouse-highlight-priority)
- (set-extent-face previous-extent face)))))
-
-
-(defun x-own-selection (selection &optional type)
- "Make a primary X Selection of the given argument.
-The argument may be a string, a cons of two markers, or an extent.
-In the latter cases the selection is considered to be the text
-between the markers, or the between extents endpoints."
- (interactive (if (not current-prefix-arg)
- (list (read-string "Store text for pasting: "))
- (list (cons ;; these need not be ordered.
- (copy-marker (point-marker))
- (copy-marker (mark-marker))))))
- (or type (setq type 'PRIMARY))
- (x-set-selection selection type)
- (cond ((eq type 'PRIMARY)
- (setq primary-selection-extent
- (x-select-make-extent-for-selection
- selection primary-selection-extent 'primary-selection)))
- ((eq type 'SECONDARY)
- (setq secondary-selection-extent
- (x-select-make-extent-for-selection
- selection secondary-selection-extent 'secondary-selection))))
- selection)
-
-
-(defun x-own-secondary-selection (selection &optional type)
- "Make a secondary X Selection of the given argument. The argument may be a
-string or a cons of two markers (in which case the selection is considered to
-be the text between those markers.)"
- (interactive (if (not current-prefix-arg)
- (list (read-string "Store text for pasting: "))
- (list (cons ;; these need not be ordered.
- (copy-marker (point-marker))
- (copy-marker (mark-marker))))))
- (x-own-selection selection 'SECONDARY))
-
-
-(defun x-own-clipboard (string)
- "Paste the given string to the X Clipboard."
- (x-own-selection string 'CLIPBOARD))
-
-
-(defun x-disown-selection (&optional secondary-p)
- "Assuming we own the selection, disown it. With an argument, discard the
-secondary selection instead of the primary selection."
- (x-disown-selection-internal (if secondary-p 'SECONDARY 'PRIMARY)))
-
-(defun x-dehilight-selection (selection)
- "for use as a value of x-lost-selection-hooks."
- (cond ((eq selection 'PRIMARY)
- (if primary-selection-extent
- (let ((inhibit-quit t))
- (delete-extent primary-selection-extent)
- (setq primary-selection-extent nil)))
- (if zmacs-regions (zmacs-deactivate-region)))
- ((eq selection 'SECONDARY)
- (if secondary-selection-extent
- (let ((inhibit-quit t))
- (delete-extent secondary-selection-extent)
- (setq secondary-selection-extent nil)))))
- nil)
-
-(setq x-lost-selection-hooks 'x-dehilight-selection)
-
-(defun x-notice-selection-requests (selection type successful)
- "for possible use as the value of x-sent-selection-hooks."
- (if (not successful)
- (message "Selection request failed to convert %s to %s"
- selection type)
- (message "Sent selection %s as %s" selection type)))
-
-(defun x-notice-selection-failures (selection type successful)
- "for possible use as the value of x-sent-selection-hooks."
- (or successful
- (message "Selection request failed to convert %s to %s"
- selection type)))
-
-;(setq x-sent-selection-hooks 'x-notice-selection-requests)
-;(setq x-sent-selection-hooks 'x-notice-selection-failures)
-
-
-;;; Random utility functions
-
-(defun x-kill-primary-selection ()
- "If there is a selection, delete the text it covers, and copy it to
-both the kill ring and the Clipboard."
- (interactive)
- (or (x-selection-owner-p) (error "emacs does not own the primary selection"))
- (setq last-command nil)
- (or primary-selection-extent
- (error "the primary selection is not an extent?"))
- (save-excursion
- (set-buffer (extent-buffer primary-selection-extent))
- (kill-region (extent-start-position primary-selection-extent)
- (extent-end-position primary-selection-extent)))
- (x-disown-selection nil))
-
-(defun x-delete-primary-selection ()
- "If there is a selection, delete the text it covers *without* copying it to
-the kill ring or the Clipboard."
- (interactive)
- (or (x-selection-owner-p) (error "emacs does not own the primary selection"))
- (setq last-command nil)
- (or primary-selection-extent
- (error "the primary selection is not an extent?"))
- (save-excursion
- (set-buffer (extent-buffer primary-selection-extent))
- (delete-region (extent-start-position primary-selection-extent)
- (extent-end-position primary-selection-extent)))
- (x-disown-selection nil))
-
-(defun x-copy-primary-selection ()
- "If there is a selection, copy it to both the kill ring and the Clipboard."
- (interactive)
- (setq last-command nil)
- (or (x-selection-owner-p) (error "emacs does not own the primary selection"))
- (or primary-selection-extent
- (error "the primary selection is not an extent?"))
- (save-excursion
- (set-buffer (extent-buffer primary-selection-extent))
- (copy-region-as-kill (extent-start-position primary-selection-extent)
- (extent-end-position primary-selection-extent))))
-
-(defun x-yank-clipboard-selection ()
- "If someone owns a Clipboard selection, insert it at point."
- (interactive)
- (setq last-command nil)
- (let ((clip (x-get-clipboard)))
- (or clip (error "there is no clipboard selection"))
- (push-mark)
- (insert clip)))
-
-;;; lselect.el ends here.
diff --git a/lisp/emacs-lisp/lucid.el b/lisp/emacs-lisp/lucid.el
deleted file mode 100644
index 5c609137ffe..00000000000
--- a/lisp/emacs-lisp/lucid.el
+++ /dev/null
@@ -1,223 +0,0 @@
-;;; lucid.el --- Emulate some Lucid Emacs functions.
-
-;; Copyright (C) 1993, 1995 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(defun copy-tree (tree)
- (if (consp tree)
- (cons (copy-tree (car tree))
- (copy-tree (cdr tree)))
- (if (vectorp tree)
- (let* ((new (copy-sequence tree))
- (i (1- (length new))))
- (while (>= i 0)
- (aset new i (copy-tree (aref new i)))
- (setq i (1- i)))
- new)
- tree)))
-
-(defalias 'current-time-seconds 'current-time)
-
-(defun remprop (symbol prop)
- (let ((plist (symbol-plist symbol)))
- (while (eq (car plist) prop)
- (setplist symbol (setq plist (cdr (cdr plist)))))
- (while plist
- (if (eq (nth 2 plist) prop)
- (setcdr (cdr plist) (nthcdr 4 plist)))
- (setq plist (cdr (cdr plist))))))
-
-(defun map-keymap (function keymap &optional sort-first)
- "Call FUNCTION for every binding in KEYMAP.
-This includes bindings inherited from a parent keymap.
-FUNCTION receives two arguments each time it is called:
-the character (more generally, the event type) that is bound,
-and the binding it has.
-
-Note that passing the event type directly to `define-key' does not work
-in Emacs 19. We do not emulate that particular feature of Lucid Emacs.
-If your code does that, modify it to make a vector containing the event
-type that you get. That will work in both versions of Emacs."
- (if sort-first
- (let (list)
- (map-keymap (function (lambda (a b)
- (setq list (cons (cons a b) list))))
- keymap)
- (setq list (sort list
- (function (lambda (a b)
- (setq a (car a) b (car b))
- (if (integerp a)
- (if (integerp b) (< a b)
- t)
- (if (integerp b) t
- (string< a b)))))))
- (while list
- (funcall function (car (car list)) (cdr (car list)))
- (setq list (cdr list))))
- (while (consp keymap)
- (if (consp (car keymap))
- (funcall function (car (car keymap)) (cdr (car keymap)))
- (if (vectorp (car keymap))
- (let ((i (1- (length (car keymap))))
- (vector (car keymap)))
- (while (>= i 0)
- (funcall function i (aref vector i))
- (setq i (1- i))))))
- (setq keymap (cdr keymap)))))
-
-(defun read-number (prompt &optional integers-only)
- "Read a number from the minibuffer.
-Keep reentering the minibuffer until we get suitable input.
-If optional argument INTEGERS-ONLY is non-nil, insist on an integer."
- (interactive)
- (let (success
- (number nil)
- (predicate (if integers-only 'integerp 'numberp)))
- (while (not success)
- (let ((input-string (read-string prompt)))
- (condition-case ()
- (setq number (read input-string))
- (error))
- (if (funcall predicate number)
- (setq success t)
- (let ((cursor-in-echo-area t))
- (message "Please type %s"
- (if integers-only "an integer" "a number"))
- (sit-for 1)))))
- number))
-
-(defun real-path-name (name &optional default)
- (file-truename (expand-file-name name default)))
-
-;; It's not clear what to return if the mouse is not in FRAME.
-(defun read-mouse-position (frame)
- (let ((pos (mouse-position)))
- (if (eq (car pos) frame)
- (cdr pos))))
-
-(defun switch-to-other-buffer (arg)
- "Switch to the previous buffer.
-With a numeric arg N, switch to the Nth most recent buffer.
-With an arg of 0, buries the current buffer at the
-bottom of the buffer stack."
- (interactive "p")
- (if (eq arg 0)
- (bury-buffer (current-buffer)))
- (switch-to-buffer
- (if (<= arg 1) (other-buffer (current-buffer))
- (nth arg
- (apply 'nconc
- (mapcar
- (lambda (buf)
- (if (= ?\ (string-to-char (buffer-name buf)))
- nil
- (list buf)))
- (buffer-list)))))))
-
-(defalias 'find-face 'internal-find-face)
-(defalias 'get-face 'internal-get-face)
-(defalias 'try-face-font 'internal-try-face-font)
-
-(defalias 'exec-to-string 'shell-command-to-string)
-
-(defun make-extent (beg end &optional buffer)
- (make-overlay beg end buffer))
-
-(defun set-extent-property (extent prop value)
- (if (eq prop 'duplicable)
- (cond ((and value (not (overlay-get extent prop)))
- ;; If becoming duplicable, copy all overlayprops to text props.
- (add-text-properties (overlay-start extent)
- (overlay-end extent)
- (overlay-properties extent)
- (overlay-buffer extent)))
- ;; If becoming no longer duplicable, remove these text props.
- ((and (not value) (overlay-get extent prop))
- (remove-text-properties (overlay-start extent)
- (overlay-end extent)
- (overlay-properties extent)
- (overlay-buffer extent))))
- ;; If extent is already duplicable, put this property
- ;; on the text as well as on the overlay.
- (if (overlay-get extent 'duplicable)
- (put-text-property (overlay-start extent)
- (overlay-end extent)
- prop value (overlay-buffer extent))))
- (overlay-put extent prop value))
-
-(defun set-extent-face (extent face)
- (set-extent-property extent 'face face))
-
-(defun delete-extent (extent)
- (set-extent-property extent 'duplicable nil)
- (delete-overlay extent))
-
-;; Support the Lucid names with `screen' instead of `frame'.
-
-(defalias 'current-screen-configuration 'current-frame-configuration)
-(defalias 'delete-screen 'delete-frame)
-(defalias 'find-file-new-screen 'find-file-other-frame)
-(defalias 'find-file-read-only-new-screen 'find-file-read-only-other-frame)
-(defalias 'find-tag-new-screen 'find-tag-other-frame)
-;;(defalias 'focus-screen 'focus-frame)
-(defalias 'iconify-screen 'iconify-frame)
-(defalias 'mail-new-screen 'mail-other-frame)
-(defalias 'make-screen-invisible 'make-frame-invisible)
-(defalias 'make-screen-visible 'make-frame-visible)
-;; (defalias 'minibuffer-screen-list 'minibuffer-frame-list)
-(defalias 'modify-screen-parameters 'modify-frame-parameters)
-(defalias 'next-screen 'next-frame)
-;; (defalias 'next-multiscreen-window 'next-multiframe-window)
-;; (defalias 'previous-multiscreen-window 'previous-multiframe-window)
-;; (defalias 'redirect-screen-focus 'redirect-frame-focus)
-(defalias 'redraw-screen 'redraw-frame)
-;; (defalias 'screen-char-height 'frame-char-height)
-;; (defalias 'screen-char-width 'frame-char-width)
-;; (defalias 'screen-configuration-to-register 'frame-configuration-to-register)
-;; (defalias 'screen-focus 'frame-focus)
-(defalias 'screen-list 'frame-list)
-;; (defalias 'screen-live-p 'frame-live-p)
-(defalias 'screen-parameters 'frame-parameters)
-(defalias 'screen-pixel-height 'frame-pixel-height)
-(defalias 'screen-pixel-width 'frame-pixel-width)
-(defalias 'screen-root-window 'frame-root-window)
-(defalias 'screen-selected-window 'frame-selected-window)
-(defalias 'lower-screen 'lower-frame)
-(defalias 'raise-screen 'raise-frame)
-(defalias 'screen-visible-p 'frame-visible-p)
-(defalias 'screenp 'framep)
-(defalias 'select-screen 'select-frame)
-(defalias 'selected-screen 'selected-frame)
-;; (defalias 'set-screen-configuration 'set-frame-configuration)
-;; (defalias 'set-screen-height 'set-frame-height)
-(defalias 'set-screen-position 'set-frame-position)
-(defalias 'set-screen-size 'set-frame-size)
-;; (defalias 'set-screen-width 'set-frame-width)
-(defalias 'switch-to-buffer-new-screen 'switch-to-buffer-other-frame)
-;; (defalias 'unfocus-screen 'unfocus-frame)
-(defalias 'visible-screen-list 'visible-frame-list)
-(defalias 'window-screen 'window-frame)
-(defalias 'x-create-screen 'x-create-frame)
-(defalias 'x-new-screen 'make-frame)
-
-(provide 'lucid)
-
-;;; end of lucid.el
diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el
deleted file mode 100644
index 013ce8402d3..00000000000
--- a/lisp/emacs-lisp/pp.el
+++ /dev/null
@@ -1,181 +0,0 @@
-;;; pp.el --- pretty printer for Emacs Lisp
-
-;; Copyright (C) 1989, 1993 Free Software Foundation, Inc.
-
-;; Author: Randal Schwartz <merlyn@stonehenge.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(defvar pp-escape-newlines t
- "*Value of print-escape-newlines used by pp-* functions.")
-
-(defun pp-to-string (object)
- "Return a string containing the pretty-printed representation of OBJECT,
-any Lisp object. Quoting characters are used when needed to make output
-that `read' can handle, whenever this is possible."
- (save-excursion
- (set-buffer (generate-new-buffer " pp-to-string"))
- (unwind-protect
- (progn
- (lisp-mode-variables t)
- (let ((print-escape-newlines pp-escape-newlines))
- (prin1 object (current-buffer)))
- (goto-char (point-min))
- (while (not (eobp))
- ;; (message "%06d" (- (point-max) (point)))
- (cond
- ((looking-at "\\s(\\|#\\s(")
- (while (looking-at "\\s(\\|#\\s(")
- (forward-char 1)))
- ((and (looking-at "\\(quote[ \t]+\\)\\([^.)]\\)")
- (> (match-beginning 1) 1)
- (= ?\( (char-after (1- (match-beginning 1))))
- ;; Make sure this is a two-element list.
- (save-excursion
- (goto-char (match-beginning 2))
- (forward-sexp)
- ;; (looking-at "[ \t]*\)")
- ;; Avoid mucking with match-data; does this test work?
- (char-equal ?\) (char-after (point)))))
- ;; -1 gets the paren preceding the quote as well.
- (delete-region (1- (match-beginning 1)) (match-end 1))
- (insert "'")
- (forward-sexp 1)
- (if (looking-at "[ \t]*\)")
- (delete-region (match-beginning 0) (match-end 0))
- (error "Malformed quote"))
- (backward-sexp 1))
- ((condition-case err-var
- (prog1 t (down-list 1))
- (error nil))
- (backward-char 1)
- (skip-chars-backward " \t")
- (delete-region
- (point)
- (progn (skip-chars-forward " \t") (point)))
- (if (not (char-equal ?' (char-after (1- (point)))))
- (insert ?\n)))
- ((condition-case err-var
- (prog1 t (up-list 1))
- (error nil))
- (while (looking-at "\\s)")
- (forward-char 1))
- (skip-chars-backward " \t")
- (delete-region
- (point)
- (progn (skip-chars-forward " \t") (point)))
- (if (not (char-equal ?' (char-after (1- (point)))))
- (insert ?\n)))
- (t (goto-char (point-max)))))
- (goto-char (point-min))
- (indent-sexp)
- (buffer-string))
- (kill-buffer (current-buffer)))))
-
-;;;###autoload
-(defun pp (object &optional stream)
- "Output the pretty-printed representation of OBJECT, any Lisp object.
-Quoting characters are printed when needed to make output that `read'
-can handle, whenever this is possible.
-Output stream is STREAM, or value of `standard-output' (which see)."
- (princ (pp-to-string object) (or stream standard-output)))
-
-;;;###autoload
-(defun pp-eval-expression (expression)
- "Evaluate EXPRESSION and pretty-print value into a new display buffer.
-If the pretty-printed value fits on one line, the message line is used
-instead. Value is also consed on to front of variable values 's
-value."
- (interactive "xPp-eval: ")
- (setq values (cons (eval expression) values))
- (let* ((old-show-function temp-buffer-show-function)
- ;; Use this function to display the buffer.
- ;; This function either decides not to display it at all
- ;; or displays it in the usual way.
- (temp-buffer-show-function
- (function
- (lambda (buf)
- (save-excursion
- (set-buffer buf)
- (goto-char (point-min))
- (end-of-line 1)
- (if (or (< (1+ (point)) (point-max))
- (>= (- (point) (point-min)) (frame-width)))
- (let ((temp-buffer-show-function old-show-function)
- (old-selected (selected-window))
- (window (display-buffer buf)))
- (goto-char (point-min)) ; expected by some hooks ...
- (make-frame-visible (window-frame window))
- (unwind-protect
- (progn
- (select-window window)
- (run-hooks 'temp-buffer-show-hook))
- (select-window old-selected)))
- (message "%s" (buffer-substring (point-min) (point)))
- ))))))
- (with-output-to-temp-buffer "*Pp Eval Output*"
- (pp (car values)))
- (save-excursion
- (set-buffer "*Pp Eval Output*")
- (emacs-lisp-mode)
- (make-local-variable 'font-lock-verbose)
- (setq font-lock-verbose nil))))
-
-;;;###autoload
-(defun pp-eval-last-sexp (arg)
- "Run `pp-eval-expression' on sexp before point (which see).
-With argument, pretty-print output into current buffer.
-Ignores leading comment characters."
- (interactive "P")
- (let ((stab (syntax-table)) (pt (point)) start exp)
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (save-excursion
- (forward-sexp -1)
- ;; If first line is commented, ignore all leading comments:
- (if (save-excursion (beginning-of-line) (looking-at "[ \t]*;"))
- (progn
- (setq exp (buffer-substring (point) pt))
- (while (string-match "\n[ \t]*;+" exp start)
- (setq start (1+ (match-beginning 0))
- exp (concat (substring exp 0 start)
- (substring exp (match-end 0)))))
- (setq exp (read exp)))
- (setq exp (read (current-buffer)))))
- (set-syntax-table stab)
- (if arg
- (insert (pp-to-string (eval exp)))
- (pp-eval-expression exp))))
-
-;;; Test cases for quote
-;; (pp-eval-expression ''(quote quote))
-;; (pp-eval-expression ''((quote a) (quote b)))
-;; (pp-eval-expression ''('a 'b)) ; same as above
-;; (pp-eval-expression ''((quote (quote quote)) (quote quote)))
-;; These do not satisfy the quote test.
-;; (pp-eval-expression ''quote)
-;; (pp-eval-expression ''(quote))
-;; (pp-eval-expression ''(quote . quote))
-;; (pp-eval-expression ''(quote a b))
-;; (pp-eval-expression ''(quotefoo))
-;; (pp-eval-expression ''(a b))
-
-(provide 'pp) ; so (require 'pp) works
-
-;;; pp.el ends here.
diff --git a/lisp/emacs-lisp/profile.el b/lisp/emacs-lisp/profile.el
deleted file mode 100644
index d8f8b5f86fa..00000000000
--- a/lisp/emacs-lisp/profile.el
+++ /dev/null
@@ -1,325 +0,0 @@
-;;; profile.el --- generate run time measurements of Emacs Lisp functions
-
-;; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
-
-;; Author: Boaz Ben-Zvi <boaz@lcs.mit.edu>
-;; Created: 07 Feb 1992
-;; Version: 1.0
-;; Adapted-By: ESR
-;; Keywords: lisp, tools
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; DESCRIPTION:
-;; ------------
-;; This program can be used to monitor running time performance of Emacs Lisp
-;; functions. It takes a list of functions and report the real time spent
-;; inside these functions. It runs a process with a separate timer program.
-;; Caveat: the C code in ../lib-src/profile.c requires BSD-compatible
-;; time-of-day functions. If you're running an AT&T version prior to SVr4,
-;; you may have difficulty getting it to work. Your X library may supply
-;; the required routines if the standard C library does not.
-
-;; HOW TO USE:
-;; -----------
-;; Set the variable profile-functions-list to the list of functions
-;; (as symbols) You want to profile. Call M-x profile-functions to set
-;; this list on and start using your program. Note that profile-functions
-;; MUST be called AFTER all the functions in profile-functions-list have
-;; been loaded !! (This call modifies the code of the profiled functions.
-;; Hence if you reload these functions, you need to call profile-functions
-;; again! ).
-;; To display the results do M-x profile-results . For example:
-;;-------------------------------------------------------------------
-;; (setq profile-functions-list '(sokoban-set-mode-line sokoban-load-game
-;; sokoban-move-vertical sokoban-move))
-;; (load "sokoban")
-;; M-x profile-functions
-;; ... I play the sokoban game ..........
-;; M-x profile-results
-;;
-;; Function Time (Seconds.Useconds)
-;; ======== =======================
-;; sokoban-move 0.539088
-;; sokoban-move-vertical 0.410130
-;; sokoban-load-game 0.453235
-;; sokoban-set-mode-line 1.949203
-;;-----------------------------------------------------
-;; To clear all the settings to profile use profile-finish.
-;; To set one function at a time (instead of or in addition to setting the
-;; above list and M-x profile-functions) use M-x profile-a-function.
-
-;;; Code:
-
-;;;
-;;; User modifiable VARIABLES
-;;;
-
-(defvar profile-functions-list nil "*List of functions to profile.")
-(defvar profile-timer-program
- (concat exec-directory "profile")
- "*Name of the profile timer program.")
-
-;;;
-;;; V A R I A B L E S
-;;;
-
-(defvar profile-timer-process nil "Process running the timer.")
-(defvar profile-time-list nil
- "List of cumulative calls and time for each profiled function.")
-(defvar profile-init-list nil
- "List of entry time for each function.
-Both how many times invoked and real time of start.")
-(defvar profile-max-fun-name 0 "Max length of name of any function profiled.")
-(defvar profile-temp-result- nil "Should NOT be used anywhere else.")
-(defvar profile-time (cons 0 0) "Used to return result from a filter.")
-(defvar profile-buffer "*profile*" "Name of profile buffer.")
-
-;;;
-;;; F U N C T I O N S
-;;;
-
-(defun profile-functions (&optional flist)
- "Profile all the functions listed in `profile-functions-list'.
-With argument FLIST, use the list FLIST instead."
- (interactive "P")
- (if (null flist) (setq flist profile-functions-list))
- (mapcar 'profile-a-function flist))
-
-(defun profile-filter (process input)
- "Filter for the timer process. Sets `profile-time' to the returned time."
- (if (zerop (string-match "\\." input))
- (error "Bad output from %s" profile-timer-program)
- (setcar profile-time
- (string-to-int (substring input 0 (match-beginning 0))))
- (setcdr profile-time
- (string-to-int (substring input (match-end 0))))))
-
-
-(defun profile-print (entry)
- "Print one ENTRY (from `profile-time-list')."
- (let* ((calls (car (cdr entry)))
- (timec (cdr (cdr entry)))
- (time (+ (car timec) (/ (cdr timec) (float profile-million))))
- (avgtime 0.0))
- (insert (format (concat "%-"
- (int-to-string profile-max-fun-name)
- "s%8d%11d.%06d")
- (car entry) calls (car timec) (cdr timec))
- (if (zerop calls)
- "\n"
- (format "%12d.%06d\n"
- (truncate (setq avgtime (/ time calls)))
- (truncate (* (- avgtime (ftruncate avgtime))
- profile-million))))
- )))
-
-(defun profile-results ()
- "Display profiling results in the buffer `*profile*'.
-\(The buffer name comes from `profile-buffer'.)"
- (interactive)
- (switch-to-buffer profile-buffer)
- (erase-buffer)
- (insert "Function" (make-string (- profile-max-fun-name 6) ? ))
- (insert " Calls Total time (sec) Avg time per call\n")
- (insert (make-string profile-max-fun-name ?=) " ")
- (insert "====== ================ =================\n")
- (mapcar 'profile-print profile-time-list))
-
-(defun profile-reset-timer ()
- (process-send-string profile-timer-process "z\n"))
-
-(defun profile-check-zero-init-times (entry)
- "If ENTRY has non zero time, give an error."
- (let ((time (cdr (cdr entry))))
- (if (and (zerop (car time)) (zerop (cdr time))) nil ; OK
- (error "Process timer died while making performance profile."))))
-
-(defun profile-get-time ()
- "Get time from timer process into `profile-time'."
- ;; first time or if process dies
- (if (and (processp profile-timer-process)
- (eq 'run (process-status profile-timer-process))) nil
- (setq profile-timer-process;; [re]start the timer process
- (start-process "timer"
- (get-buffer-create profile-buffer)
- profile-timer-program))
- (set-process-filter profile-timer-process 'profile-filter)
- (process-kill-without-query profile-timer-process)
- (profile-reset-timer)
- ;; check if timer died during time measurement
- (mapcar 'profile-check-zero-init-times profile-init-list))
- ;; make timer process return current time
- (process-send-string profile-timer-process "p\n")
- (accept-process-output))
-
-(defun profile-find-function (fun flist)
- "Linear search for FUN in FLIST."
- (if (null flist) nil
- (if (eq fun (car (car flist))) (cdr (car flist))
- (profile-find-function fun (cdr flist)))))
-
-(defun profile-start-function (fun)
- "On entry, keep current time for function FUN."
- ;; assumes that profile-time contains the current time
- (let ((init-time (profile-find-function fun profile-init-list)))
- (if (null init-time) (error "Function %s missing from list" fun))
- (if (not (zerop (car init-time)));; is it a recursive call ?
- (setcar init-time (1+ (car init-time)))
- (setcar init-time 1) ; mark first entry
- (setq init-time (cdr init-time))
- (setcar init-time (car profile-time))
- (setcdr init-time (cdr profile-time)))
- ))
-
-(defconst profile-million 1000000)
-
-(defun profile-update-function (fun)
- "When the call to the function FUN is finished, add its run time."
- ;; assumes that profile-time contains the current time
- (let ((init-time (profile-find-function fun profile-init-list))
- (accum (profile-find-function fun profile-time-list))
- calls time sec usec)
- (if (or (null init-time)
- (null accum)) (error "Function %s missing from list" fun))
- (setq calls (car accum))
- (setq time (cdr accum))
- (setcar init-time (1- (car init-time))) ; pop one level in recursion
- (if (not (zerop (car init-time)))
- nil ; in some recursion level,
- ; do not update cumulated time
- (setcar accum (1+ calls))
- (setq init-time (cdr init-time))
- (setq sec (- (car profile-time) (car init-time))
- usec (- (cdr profile-time) (cdr init-time)))
- (setcar init-time 0) ; reset time to check for error
- (setcdr init-time 0) ; in case timer process dies
- (if (>= usec 0) nil
- (setq usec (+ usec profile-million))
- (setq sec (1- sec)))
- (setcar time (+ sec (car time)))
- (setcdr time (+ usec (cdr time)))
- (if (< (cdr time) profile-million) nil
- (setcar time (1+ (car time)))
- (setcdr time (- (cdr time) profile-million)))
- )))
-
-(defun profile-convert-byte-code (function)
- (let ((defn (symbol-function function)))
- (if (byte-code-function-p defn)
- ;; It is a compiled code object.
- (let* ((contents (append defn nil))
- (body
- (list (list 'byte-code (nth 1 contents)
- (nth 2 contents) (nth 3 contents)))))
- (if (nthcdr 5 contents)
- (setq body (cons (list 'interactive (nth 5 contents)) body)))
- (if (nth 4 contents)
- ;; Use `documentation' here, to get the actual string,
- ;; in case the compiled function has a reference
- ;; to the .elc file.
- (setq body (cons (documentation function) body)))
- (fset function (cons 'lambda (cons (car contents) body)))))))
-
-(defun profile-a-function (fun)
- "Profile the function FUN."
- (interactive "aFunction to profile: ")
- (profile-convert-byte-code fun)
- (let ((def (symbol-function fun)) (funlen (length (symbol-name fun))))
- (if (eq (car def) 'lambda) nil
- (error "To profile: %s must be a user-defined function" fun))
- (setq profile-time-list ; add a new entry
- (cons (cons fun (cons 0 (cons 0 0))) profile-time-list))
- (setq profile-init-list ; add a new entry
- (cons (cons fun (cons 0 (cons 0 0))) profile-init-list))
- (if (< profile-max-fun-name funlen) (setq profile-max-fun-name funlen))
- (fset fun (profile-fix-fun fun def))))
-
-(defun profile-fix-fun (fun def)
- "Take function FUN and return it fixed for profiling.
-DEF is (symbol-function FUN)."
- (let (prefix first second third (count 2) inter suffix)
- (if (< (length def) 3)
- nil ; nothing to see
- (setq first (car def) second (car (cdr def))
- third (car (nthcdr 2 def)))
- (setq prefix (list first second))
- ;; Skip the doc string, if there is a string
- ;; which serves only as a doc string,
- ;; and put it in PREFIX.
- (if (or (not (stringp third)) (not (nthcdr 3 def)))
- ;; Either no doc string, or it is also the function value.
- (setq inter third)
- ;; Skip the doc string,
- (setq count 3
- prefix (nconc prefix (list third))
- inter (car (nthcdr 3 def))))
- ;; Check for an interactive spec.
- ;; If found, put it inu PREFIX and skip it.
- (if (not (and (listp inter)
- (eq (car inter) 'interactive)))
- nil
- (setq prefix (nconc prefix (list inter)))
- (setq count (1+ count))) ; skip this sexp for suffix
- ;; Set SUFFIX to the function body forms.
- (setq suffix (nthcdr count def))
- (if (equal (car suffix) '(profile-get-time))
- nil
- ;; Prepare new function definition.
- (nconc prefix
- (list '(profile-get-time)) ; read time
- (list (list 'profile-start-function
- (list 'quote fun)))
- (list (list 'setq 'profile-temp-result-
- (nconc (list 'progn) suffix)))
- (list '(profile-get-time)) ; read time
- (list (list 'profile-update-function
- (list 'quote fun)))
- (list 'profile-temp-result-)
- )))))
-
-(defun profile-restore-fun (fun)
- "Restore profiled function FUN to its original state."
- (let ((def (symbol-function (car fun))) body index)
- ;; move index beyond header
- (setq index (cdr def))
- (if (stringp (car (cdr index))) (setq index (cdr index)))
- (if (and (listp (car (cdr index)))
- (eq (car (car (cdr index))) 'interactive))
- (setq index (cdr index)))
- (setq body (car (nthcdr 3 index)))
- (if (and (listp body) ; the right element ?
- (eq (car (cdr body)) 'profile-temp-result-))
- (setcdr index (cdr (car (cdr (cdr body))))))))
-
-(defun profile-finish ()
- "Stop profiling functions. Clear all the settings."
- (interactive)
- (mapcar 'profile-restore-fun profile-time-list)
- (setq profile-max-fun-name 0)
- (setq profile-time-list nil)
- (setq profile-init-list nil))
-
-(defun profile-quit ()
- "Kill the timer process."
- (interactive)
- (process-send-string profile-timer-process "q\n"))
-
-;;; profile.el ends here
diff --git a/lisp/emacs-lisp/ring.el b/lisp/emacs-lisp/ring.el
deleted file mode 100644
index ac5a72a8e67..00000000000
--- a/lisp/emacs-lisp/ring.el
+++ /dev/null
@@ -1,135 +0,0 @@
-;;; ring.el --- handle rings of items
-
-;; Copyright (C) 1992 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This code defines a ring data structure. A ring is a
-;; (hd-index length . 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.
-;;
-;; In ring-ref, 0 is the index of the newest element. Higher indexes
-;; correspond to older elements until they wrap.
-;;
-;; hd-index = index of the newest item on the ring.
-;; length = number of ring items.
-;;
-;; These functions are used by the input history mechanism, but they can
-;; be used for other purposes as well.
-
-;;; Code:
-
-;;;###autoload
-(defun ring-p (x)
- "Returns 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)))))
-
-;;;###autoload
-(defun make-ring (size)
- "Make a ring that can contain SIZE elements."
- (cons 0 (cons 0 (make-vector size nil))))
-
-(defun ring-insert-at-beginning (ring item)
- "Add to RING the item ITEM. Add it at the front (the early end)."
- (let* ((vec (cdr (cdr ring)))
- (veclen (length vec))
- (hd (car ring))
- (ln (car (cdr ring))))
- (setq ln (min veclen (1+ ln))
- hd (ring-minus1 hd veclen))
- (aset vec hd item)
- (setcar ring hd)
- (setcar (cdr ring) ln)))
-
-(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 elements in the ring."
- (car (cdr ring)))
-
-(defun ring-empty-p (ring)
- (= 0 (car (cdr ring))))
-
-(defun ring-index (index head ringlen veclen)
- (setq index (mod index ringlen))
- (mod (1- (+ head (- ringlen index))) veclen))
-
-(defun ring-insert (ring item)
- "Insert onto ring RING the item ITEM, as the newest (last) item.
-If the ring is full, dump the oldest item to make room."
- (let* ((vec (cdr (cdr ring)))
- (veclen (length vec))
- (hd (car ring))
- (ln (car (cdr ring))))
- (prog1
- (aset vec (mod (+ hd ln) veclen) item)
- (if (= ln veclen)
- (setcar ring (ring-plus1 hd veclen))
- (setcar (cdr ring) (1+ ln))))))
-
-(defun ring-remove (ring &optional index)
- "Remove an item from the RING. Return the removed item.
-If optional INDEX is nil, remove the oldest item. If it's
-numeric, remove the element indexed."
- (if (ring-empty-p ring)
- (error "Ring empty")
- (let* ((hd (car ring))
- (ln (car (cdr ring)))
- (vec (cdr (cdr ring)))
- (veclen (length vec))
- (tl (mod (1- (+ hd ln)) veclen))
- oldelt)
- (if (null index)
- (setq index (1- ln)))
- (setq index (ring-index index hd ln veclen))
- (setq oldelt (aref vec index))
- (while (/= index tl)
- (aset vec index (aref vec (ring-plus1 index veclen)))
- (setq index (ring-plus1 index veclen)))
- (aset vec tl nil)
- (setcar (cdr ring) (1- ln))
- oldelt)))
-
-(defun ring-ref (ring index)
- "Returns RING's INDEX element.
-INDEX need not be <= the ring length, the appropriate modulo operation
-will be performed. Element 0 is the most recently inserted; higher indices
-correspond to older elements until they wrap."
- (if (ring-empty-p ring)
- (error "indexed empty ring")
- (let* ((hd (car ring)) (ln (car (cdr ring))) (vec (cdr (cdr ring))))
- (aref vec (ring-index index hd ln (length vec))))))
-
-(provide 'ring)
-
-;;; ring.el ends here
diff --git a/lisp/emacs-lisp/shadow.el b/lisp/emacs-lisp/shadow.el
deleted file mode 100644
index 73650de88c8..00000000000
--- a/lisp/emacs-lisp/shadow.el
+++ /dev/null
@@ -1,203 +0,0 @@
-;;; shadow.el --- Locate Emacs Lisp file shadowings.
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Terry Jones <terry@santafe.edu>
-;; Keywords: lisp
-;; Created: 15 December 1995
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The functions in this file detect (`find-emacs-lisp-shadows')
-;; and display (`list-load-path-shadows') potential load-path
-;; problems that arise when Emacs Lisp files "shadow" each other.
-;;
-;; For example, a file XXX.el early in one's load-path will shadow
-;; a file with the same name in a later load-path directory. When
-;; this is unintentional, it may result in problems that could have
-;; been easily avoided. This occurs often (to me) when installing a
-;; new version of emacs and something in the site-lisp directory
-;; has been updated and added to the emacs distribution. The old
-;; version, now outdated, shadows the new one. This is obviously
-;; undesirable.
-;;
-;; The `list-load-path-shadows' function was run when you installed
-;; this version of emacs. To run it by hand in emacs:
-;;
-;; M-x load-library RET shadow RET
-;; M-x list-load-path-shadows
-;;
-;; or run it non-interactively via:
-;;
-;; emacs -batch -l shadow.el -f list-load-path-shadows
-;;
-;; Thanks to Francesco Potorti` <pot@cnuce.cnr.it> for suggestions,
-;; rewritings & speedups.
-
-;;; Code:
-
-(defun find-emacs-lisp-shadows (&optional path)
- "Return a list of Emacs Lisp files that create shadows.
-This function does the work for `list-load-path-shadows'.
-
-We traverse PATH looking for shadows, and return a \(possibly empty\)
-even-length list of files. A file in this list at position 2i shadows
-the file in position 2i+1. Emacs Lisp file suffixes \(.el and .elc\)
-are stripped from the file names in the list.
-
-See the documentation for `list-load-path-shadows' for further information."
-
- (or path (setq path load-path))
-
- (let (true-names ; List of dirs considered.
- shadows ; List of shadowings, to be returned.
- files ; File names ever seen, with dirs.
- dir ; The dir being currently scanned.
- curr-files ; This dir's Emacs Lisp files.
- orig-dir ; Where the file was first seen.
- files-seen-this-dir ; Files seen so far in this dir.
- file) ; The current file.
-
-
- (while path
-
- (setq dir (file-truename (or (car path) ".")))
- (if (member dir true-names)
- ;; We have already considered this PATH redundant directory.
- ;; Show the redundancy if we are interactiver, unless the PATH
- ;; dir is nil or "." (these redundant directories are just a
- ;; result of the current working directory, and are therefore
- ;; not always redundant).
- (or noninteractive
- (and (car path)
- (not (string= (car path) "."))
- (message "Ignoring redundant directory %s" (car path))))
-
- (setq true-names (append true-names (list dir)))
- (setq dir (or (car path) "."))
- (setq curr-files (if (file-accessible-directory-p dir)
- (directory-files dir nil ".\\.elc?$" t)))
- (and curr-files
- (not noninteractive)
- (message "Checking %d files in %s..." (length curr-files) dir))
-
- (setq files-seen-this-dir nil)
-
- (while curr-files
-
- (setq file (car curr-files))
- (setq file (substring
- file 0 (if (string= (substring file -1) "c") -4 -3)))
-
- ;; 'file' now contains the current file name, with no suffix.
- (if (member file files-seen-this-dir)
- nil
-
- ;; File has not been seen yet in this directory.
- ;; This test prevents us declaring that XXX.el shadows
- ;; XXX.elc (or vice-versa) when they are in the same directory.
- (setq files-seen-this-dir (cons file files-seen-this-dir))
-
- (if (setq orig-dir (assoc file files))
- ;; This file was seen before, we have a shadowing.
- (setq shadows
- (append shadows
- (list (concat (cdr orig-dir) "/" file)
- (concat dir "/" file))))
-
- ;; Not seen before, add it to the list of seen files.
- (setq files (cons (cons file dir) files))))
-
- (setq curr-files (cdr curr-files))))
- (setq path (cdr path)))
-
- ;; Return the list of shadowings.
- shadows))
-
-
-;;;###autoload
-(defun list-load-path-shadows ()
-
- "Display a list of Emacs Lisp files that shadow other files.
-
-This function lists potential load-path problems. Directories in the
-`load-path' variable are searched, in order, for Emacs Lisp
-files. When a previously encountered file name is found again, a
-message is displayed indicating that the later file is \"hidden\" by
-the earlier.
-
-For example, suppose `load-path' is set to
-
-\(\"/usr/gnu/emacs/site-lisp\" \"/usr/gnu/emacs/share/emacs/19.30/lisp\"\)
-
-and that each of these directories contains a file called XXX.el. Then
-XXX.el in the site-lisp directory is referred to by all of:
-\(require 'XXX\), \(autoload .... \"XXX\"\), \(load-library \"XXX\"\) etc.
-
-The first XXX.el file prevents emacs from seeing the second \(unless
-the second is loaded explicitly via load-file\).
-
-When not intended, such shadowings can be the source of subtle
-problems. For example, the above situation may have arisen because the
-XXX package was not distributed with versions of emacs prior to
-19.30. An emacs maintainer downloaded XXX from elsewhere and installed
-it. Later, XXX was updated and included in the emacs distribution.
-Unless the emacs maintainer checks for this, the new version of XXX
-will be hidden behind the old \(which may no longer work with the new
-emacs version\).
-
-This function performs these checks and flags all possible
-shadowings. Because a .el file may exist without a corresponding .elc
-\(or vice-versa\), these suffixes are essentially ignored. A file
-XXX.elc in an early directory \(that does not contain XXX.el\) is
-considered to shadow a later file XXX.el, and vice-versa.
-
-When run interactively, the shadowings \(if any\) are displayed in a
-buffer called `*Shadows*'. Shadowings are located by calling the
-\(non-interactive\) companion function, `find-emacs-lisp-shadows'."
-
- (interactive)
- (let* ((shadows (find-emacs-lisp-shadows))
- (n (/ (length shadows) 2))
- (msg (format "%s Emacs Lisp load-path shadowing%s found"
- (if (zerop n) "No" (concat "\n" (number-to-string n)))
- (if (= n 1) " was" "s were"))))
- (if (interactive-p)
- (save-excursion
- ;; We are interactive.
- ;; Create the *Shadows* buffer and display shadowings there.
- (let ((output-buffer (get-buffer-create "*Shadows*")))
- (display-buffer output-buffer)
- (set-buffer output-buffer)
- (erase-buffer)
- (while shadows
- (insert (format "%s hides %s\n" (car shadows)
- (car (cdr shadows))))
- (setq shadows (cdr (cdr shadows))))
- (insert msg "\n")))
- ;; We are non-interactive, print shadows via message.
- (while shadows
- (message "%s hides %s" (car shadows) (car (cdr shadows)))
- (setq shadows (cdr (cdr shadows))))
- (message "%s" msg))))
-
-(provide 'shadow)
-
-;;; shadow.el ends here
diff --git a/lisp/emacs-lisp/tq.el b/lisp/emacs-lisp/tq.el
deleted file mode 100644
index 0de2c48e638..00000000000
--- a/lisp/emacs-lisp/tq.el
+++ /dev/null
@@ -1,123 +0,0 @@
-;;; tq.el --- utility to maintain a transaction queue
-
-;; Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
-
-;; Author: Scott Draves <spot@cs.cmu.edu>
-;; Adapted-By: ESR
-;; Keywords: extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; manages receiving a stream asynchronously,
-;;; parsing it into transactions, and then calling
-;;; handler functions
-
-;;; Our basic structure is the queue/process/buffer triple. Each entry
-;;; of the queue is a regexp/closure/function triple. We buffer
-;;; bytes from the process until we see the regexp at the head of the
-;;; queue. Then we call the function with the closure and the
-;;; collected bytes.
-
-;;; Code:
-
-;;;###autoload
-(defun tq-create (process)
- "Create and return a transaction queue communicating with PROCESS.
-PROCESS should be a subprocess capable of sending and receiving
-streams of bytes. It may be a local process, or it may be connected
-to a tcp server on another machine."
- (let ((tq (cons nil (cons process
- (generate-new-buffer
- (concat " tq-temp-"
- (process-name process)))))))
- (set-process-filter process
- (`(lambda (proc string)
- (tq-filter '(, tq) string))))
- tq))
-
-;;; accessors
-(defun tq-queue (tq) (car tq))
-(defun tq-process (tq) (car (cdr tq)))
-(defun tq-buffer (tq) (cdr (cdr tq)))
-
-(defun tq-queue-add (tq re closure fn)
- (setcar tq (nconc (tq-queue tq)
- (cons (cons re (cons closure fn)) nil)))
- 'ok)
-
-(defun tq-queue-head-regexp (tq) (car (car (tq-queue tq))))
-(defun tq-queue-head-fn (tq) (cdr (cdr (car (tq-queue tq)))))
-(defun tq-queue-head-closure (tq) (car (cdr (car (tq-queue tq)))))
-(defun tq-queue-empty (tq) (not (tq-queue tq)))
-(defun tq-queue-pop (tq) (setcar tq (cdr (car tq))) (null (car tq)))
-
-
-;;; must add to queue before sending!
-(defun tq-enqueue (tq question regexp closure fn)
- "Add a transaction to transaction queue TQ.
-This sends the string QUESTION to the process that TQ communicates with.
-When the corresponding answer comes back, we call FN
-with two arguments: CLOSURE, and the answer to the question.
-REGEXP is a regular expression to match the entire answer;
-that's how we tell where the answer ends."
- (tq-queue-add tq regexp closure fn)
- (process-send-string (tq-process tq) question))
-
-(defun tq-close (tq)
- "Shut down transaction queue TQ, terminating the process."
- (delete-process (tq-process tq))
- (kill-buffer (tq-buffer tq)))
-
-(defun tq-filter (tq string)
- "Append STRING to the TQ's buffer; then process the new data."
- (let ((old-buffer (current-buffer)))
- (unwind-protect
- (progn
- (set-buffer (tq-buffer tq))
- (goto-char (point-max))
- (insert string)
- (tq-process-buffer tq))
- (set-buffer old-buffer))))
-
-(defun tq-process-buffer (tq)
- "Check TQ's buffer for the regexp at the head of the queue."
- (set-buffer (tq-buffer tq))
- (if (= 0 (buffer-size)) ()
- (if (tq-queue-empty tq)
- (let ((buf (generate-new-buffer "*spurious*")))
- (copy-to-buffer buf (point-min) (point-max))
- (delete-region (point-min) (point))
- (pop-to-buffer buf nil)
- (error "Spurious communication from process %s, see buffer %s"
- (process-name (tq-process tq))
- (buffer-name buf)))
- (goto-char (point-min))
- (if (re-search-forward (tq-queue-head-regexp tq) nil t)
- (let ((answer (buffer-substring (point-min) (point))))
- (delete-region (point-min) (point))
- (funcall (tq-queue-head-fn tq)
- (tq-queue-head-closure tq)
- answer)
- (tq-queue-pop tq)
- (tq-process-buffer tq))))))
-
-(provide 'tq)
-
-;;; tq.el ends here
diff --git a/lisp/emacs-lisp/trace.el b/lisp/emacs-lisp/trace.el
deleted file mode 100644
index 40008e29a19..00000000000
--- a/lisp/emacs-lisp/trace.el
+++ /dev/null
@@ -1,314 +0,0 @@
-;;; trace.el --- tracing facility for Emacs Lisp functions
-
-;; Copyright (C) 1993 Free Software Foundation, Inc.
-
-;; Author: Hans Chalupsky <hans@cs.buffalo.edu>
-;; Created: 15 Dec 1992
-;; Keywords: tools, lisp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; LCD Archive Entry:
-;; trace|Hans Chalupsky|hans@cs.buffalo.edu|
-;; Tracing facility for Emacs Lisp functions|
-;; 1993/05/18 00:41:16|2.0|~/packages/trace.el.Z|
-
-
-;;; Commentary:
-
-;; Introduction:
-;; =============
-;; A simple trace package that utilizes advice.el. It generates trace
-;; information in a Lisp-style fashion and inserts it into a trace output
-;; buffer. Tracing can be done in the background (or silently) so that
-;; generation of trace output won't interfere with what you are currently
-;; doing.
-
-;; How to get the latest trace.el:
-;; ===============================
-;; You can get the latest version of this file either via anonymous ftp from
-;; ftp.cs.buffalo.edu (128.205.32.9) with pathname /pub/Emacs/trace.el,
-;; or send email to hans@cs.buffalo.edu and I'll mail it to you.
-
-;; Requirement:
-;; ============
-;; trace.el needs advice.el version 2.0 or later which you can get from the
-;; same place from where you got trace.el.
-
-;; Restrictions:
-;; =============
-;; - Traced subrs when called interactively will always show nil as the
-;; value of their arguments.
-;; - Only functions/macros/subrs that are called via their function cell will
-;; generate trace output, hence, you won't get trace output for:
-;; + Subrs called directly from other subrs/C-code
-;; + Compiled calls to subrs that have special byte-codes associated
-;; with them (e.g., car, cdr, ...)
-;; + Macros that were expanded during compilation
-;; - All the restrictions that apply to advice.el
-
-;; Installation:
-;; =============
-;; Put this file together with advice.el (version 2.0 or later) somewhere
-;; into your Emacs `load-path', byte-compile it/them for efficiency, and
-;; put the following autoload declarations into your .emacs
-;;
-;; (autoload 'trace-function "trace" "Trace a function" t)
-;; (autoload 'trace-function-background "trace" "Trace a function" t)
-;;
-;; or explicitly load it with (require 'trace) or (load "trace").
-
-;; Comments, suggestions, bug reports
-;; ==================================
-;; are strongly appreciated, please email them to hans@cs.buffalo.edu.
-
-;; Usage:
-;; ======
-;; - To trace a function say `M-x trace-function' which will ask you for the
-;; name of the function/subr/macro to trace, as well as for the buffer
-;; into which trace output should go.
-;; - If you want to trace a function that switches buffers or does other
-;; display oriented stuff use `M-x trace-function-background' which will
-;; generate the trace output silently in the background without popping
-;; up windows and doing other irritating stuff.
-;; - To untrace a function say `M-x untrace-function'.
-;; - To untrace all currently traced functions say `M-x untrace-all'.
-
-;; Examples:
-;; =========
-;;
-;; (defun fact (n)
-;; (if (= n 0) 1
-;; (* n (fact (1- n)))))
-;; fact
-;;
-;; (trace-function 'fact)
-;; fact
-;;
-;; Now, evaluating this...
-;;
-;; (fact 4)
-;; 24
-;;
-;; ...will generate the following in *trace-buffer*:
-;;
-;; 1 -> fact: n=4
-;; | 2 -> fact: n=3
-;; | | 3 -> fact: n=2
-;; | | | 4 -> fact: n=1
-;; | | | | 5 -> fact: n=0
-;; | | | | 5 <- fact: 1
-;; | | | 4 <- fact: 1
-;; | | 3 <- fact: 2
-;; | 2 <- fact: 6
-;; 1 <- fact: 24
-;;
-;;
-;; (defun ack (x y z)
-;; (if (= x 0)
-;; (+ y z)
-;; (if (and (<= x 2) (= z 0))
-;; (1- x)
-;; (if (and (> x 2) (= z 0))
-;; y
-;; (ack (1- x) y (ack x y (1- z)))))))
-;; ack
-;;
-;; (trace-function 'ack)
-;; ack
-;;
-;; Try this for some interesting trace output:
-;;
-;; (ack 3 3 1)
-;; 27
-;;
-;;
-;; The following does something similar to the functionality of the package
-;; log-message.el by Robert Potter, which is giving you a chance to look at
-;; messages that might have whizzed by too quickly (you won't see subr
-;; generated messages though):
-;;
-;; (trace-function-background 'message "*Message Log*")
-
-
-;;; Change Log:
-
-;; Revision 2.0 1993/05/18 00:41:16 hans
-;; * Adapted for advice.el 2.0; it now also works
-;; for GNU Emacs-19 and Lemacs
-;; * Separate function `trace-function-background'
-;; * Separate pieces of advice for foreground and background tracing
-;; * Less insane handling of interactive trace buffer specification
-;; * String arguments and values are now printed properly
-;;
-;; Revision 1.1 1992/12/15 22:45:15 hans
-;; * Created, first public release
-
-
-;;; Code:
-
-(require 'advice)
-
-;;;###autoload
-(defvar trace-buffer "*trace-output*"
- "*Trace output will by default go to that buffer.")
-
-;; Current level of traced function invocation:
-(defvar trace-level 0)
-
-;; Semi-cryptic name used for a piece of trace advice:
-(defvar trace-advice-name 'trace-function\ )
-
-;; Used to separate new trace output from previous traced runs:
-(defvar trace-separator (format "%s\n" (make-string 70 ?=)))
-
-(defun trace-entry-message (function level argument-bindings)
- ;; Generates a string that describes that FUNCTION has been entered at
- ;; trace LEVEL with ARGUMENT-BINDINGS.
- (format "%s%s%d -> %s: %s\n"
- (mapconcat 'char-to-string (make-string (1- level) ?|) " ")
- (if (> level 1) " " "")
- level
- function
- (mapconcat (function
- (lambda (binding)
- (concat
- (symbol-name (ad-arg-binding-field binding 'name))
- "="
- ;; do this so we'll see strings:
- (prin1-to-string
- (ad-arg-binding-field binding 'value)))))
- argument-bindings
- " ")))
-
-(defun trace-exit-message (function level value)
- ;; Generates a string that describes that FUNCTION has been exited at
- ;; trace LEVEL and that it returned VALUE.
- (format "%s%s%d <- %s: %s\n"
- (mapconcat 'char-to-string (make-string (1- level) ?|) " ")
- (if (> level 1) " " "")
- level
- function
- ;; do this so we'll see strings:
- (prin1-to-string value)))
-
-(defun trace-make-advice (function buffer background)
- ;; Builds the piece of advice to be added to FUNCTION's advice info
- ;; so that it will generate the proper trace output in BUFFER
- ;; (quietly if BACKGROUND is t).
- (ad-make-advice
- trace-advice-name nil t
- (cond (background
- (` (advice
- lambda ()
- (let ((trace-level (1+ trace-level))
- (trace-buffer (get-buffer-create (, buffer))))
- (save-excursion
- (set-buffer trace-buffer)
- (goto-char (point-max))
- ;; Insert a separator from previous trace output:
- (if (= trace-level 1) (insert trace-separator))
- (insert
- (trace-entry-message
- '(, function) trace-level ad-arg-bindings)))
- ad-do-it
- (save-excursion
- (set-buffer trace-buffer)
- (goto-char (point-max))
- (insert
- (trace-exit-message
- '(, function) trace-level ad-return-value)))))))
- (t (` (advice
- lambda ()
- (let ((trace-level (1+ trace-level))
- (trace-buffer (get-buffer-create (, buffer))))
- (pop-to-buffer trace-buffer)
- (goto-char (point-max))
- ;; Insert a separator from previous trace output:
- (if (= trace-level 1) (insert trace-separator))
- (insert
- (trace-entry-message
- '(, function) trace-level ad-arg-bindings))
- ad-do-it
- (pop-to-buffer trace-buffer)
- (goto-char (point-max))
- (insert
- (trace-exit-message
- '(, function) trace-level ad-return-value)))))))))
-
-(defun trace-function-internal (function buffer background)
- ;; Adds trace advice for FUNCTION and activates it.
- (ad-add-advice
- function
- (trace-make-advice function (or buffer trace-buffer) background)
- 'around 'last)
- (ad-activate function nil))
-
-(defun trace-is-traced (function)
- (ad-find-advice function 'around trace-advice-name))
-
-;;;###autoload
-(defun trace-function (function &optional buffer)
- "Traces FUNCTION with trace output going to BUFFER.
-For every call of FUNCTION Lisp-style trace messages that display argument
-and return values will be inserted into BUFFER. This function generates the
-trace advice for FUNCTION and activates it together with any other advice
-there might be!! The trace BUFFER will popup whenever FUNCTION is called.
-Do not use this to trace functions that switch buffers or do any other
-display oriented stuff, use `trace-function-background' instead."
- (interactive
- (list
- (intern (completing-read "Trace function: " obarray 'fboundp t))
- (read-buffer "Output to buffer: " trace-buffer)))
- (trace-function-internal function buffer nil))
-
-;;;###autoload
-(defun trace-function-background (function &optional buffer)
- "Traces FUNCTION with trace output going quietly to BUFFER.
-For every call of FUNCTION Lisp-style trace messages that display argument
-and return values will be inserted into BUFFER. This function generates the
-trace advice for FUNCTION and activates it together with any other advice
-there might be!! Trace output will quietly go to BUFFER without changing
-the window or buffer configuration at all."
- (interactive
- (list
- (intern
- (completing-read "Trace function in background: " obarray 'fboundp t))
- (read-buffer "Output to buffer: " trace-buffer)))
- (trace-function-internal function buffer t))
-
-(defun untrace-function (function)
- "Untraces FUNCTION and possibly activates all remaining advice.
-Activation is performed with `ad-update', hence remaining advice will get
-activated only if the advice of FUNCTION is currently active. If FUNCTION
-was not traced this is a noop."
- (interactive
- (list (ad-read-advised-function "Untrace function: " 'trace-is-traced)))
- (cond ((trace-is-traced function)
- (ad-remove-advice function 'around trace-advice-name)
- (ad-update function))))
-
-(defun untrace-all ()
- "Untraces all currently traced functions."
- (interactive)
- (ad-do-advised-functions (function)
- (untrace-function function)))
-
-(provide 'trace)
-
-;;; trace.el ends here
diff --git a/lisp/emacs-lock.el b/lisp/emacs-lock.el
deleted file mode 100644
index 724fa034429..00000000000
--- a/lisp/emacs-lock.el
+++ /dev/null
@@ -1,68 +0,0 @@
-;;; emacs-lock.el --- prevents you from exiting emacs if a buffer is locked
-
-;; Copyright (C) 1994 Free Software Foundation, Inc
-
-;; Author: Tom Wurgler <twurgler@goodyear.com>
-;; Created: 12/8/94
-;; Version: 1.3
-;; Keywords:
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This code sets a buffer-local variable to t if toggle-emacs-lock is run,
-;; then if the user attempts to exit emacs, the locked buffer name will be
-;; displayed and the exit aborted. This is just a way of protecting
-;; yourself from yourself. For example, if you have a shell running a big
-;; program and exiting emacs would abort that program, you may want to lock
-;; that buffer, then if you forget about it after a while, you won't
-;; accidentally exit emacs. To unlock the buffer, just goto the buffer and
-;; run toggle-emacs-lock again.
-
-;;; Code:
-
-(defvar lock-emacs-from-exiting nil
- "Whether emacs is locked to prevent exiting. See `check-emacs-lock'.")
-(make-variable-buffer-local 'lock-emacs-from-exiting)
-
-(defun check-emacs-lock ()
- "Check if variable `lock-emacs-from-exiting' is t for any buffer.
-If any t is found, signal error and display the locked buffer name."
- (let ((buffers (buffer-list)))
- (save-excursion
- (while buffers
- (set-buffer (car buffers))
- (if lock-emacs-from-exiting
- (error "Emacs is locked from exit due to buffer: %s" (buffer-name))
- (setq buffers (cdr buffers)))))))
-
-(defun toggle-emacs-lock ()
- "Toggle `lock-emacs-from-exiting' between t and nil for the current buffer.
-See `check-emacs-lock'."
- (interactive)
- (if lock-emacs-from-exiting
- (setq lock-emacs-from-exiting nil)
- (setq lock-emacs-from-exiting t))
- (if lock-emacs-from-exiting
- (message "Emacs is now locked from exiting.")
- (message "Emacs is now unlocked.")))
-
-(add-hook 'kill-emacs-hook 'check-emacs-lock)
-
-;; emacs-lock.el ends here
diff --git a/lisp/emerge.el b/lisp/emerge.el
deleted file mode 100644
index b8b085f64e5..00000000000
--- a/lisp/emerge.el
+++ /dev/null
@@ -1,3173 +0,0 @@
-;;; emerge.el --- merge diffs under Emacs control
-
-;;; The author has placed this file in the public domain.
-
-;; Author: Dale R. Worley <worley@world.std.com>
-;; Version: 5fsf
-;; Keywords: unix, tools
-
-;; This software was created by Dale R. Worley and is
-;; distributed free of charge. It is placed in the public domain and
-;; permission is granted to anyone to use, duplicate, modify and redistribute
-;; it provided that this notice is attached.
-
-;; Dale R. Worley provides absolutely NO WARRANTY OF ANY KIND
-;; with respect to this software. The entire risk as to the quality and
-;; performance of this software is with the user. IN NO EVENT WILL DALE
-;; R. WORLEY BE LIABLE TO ANYONE FOR ANY DAMAGES ARISING OUT THE
-;; USE OF THIS SOFTWARE, INCLUDING, WITHOUT LIMITATION, DAMAGES RESULTING FROM
-;; LOST DATA OR LOST PROFITS, OR FOR ANY SPECIAL, INCIDENTAL OR CONSEQUENTIAL
-;; DAMAGES.
-
-;;; Code:
-
-;;;###autoload
-(defvar menu-bar-emerge-menu (make-sparse-keymap "Emerge"))
-;;;###autoload
-(fset 'menu-bar-emerge-menu (symbol-value 'menu-bar-emerge-menu))
-
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-merge-directories]
- '("Merge Directories..." . emerge-merge-directories))
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-revisions-with-ancestor]
- '("Revisions with Ancestor..." . emerge-revisions-with-ancestor))
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-revisions]
- '("Revisions..." . emerge-revisions))
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-files-with-ancestor]
- '("Files with Ancestor..." . emerge-files-with-ancestor))
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-files]
- '("Files..." . emerge-files))
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-buffers-with-ancestor]
- '("Buffers with Ancestor..." . emerge-buffers-with-ancestor))
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-buffers]
- '("Buffers..." . emerge-buffers))
-
-;;; Macros
-
-(defmacro emerge-eval-in-buffer (buffer &rest forms)
- "Macro to switch to BUFFER, evaluate FORMS, returns to original buffer.
-Differs from `save-excursion' in that it doesn't save the point and mark."
- (` (let ((StartBuffer (current-buffer)))
- (unwind-protect
- (progn
- (set-buffer (, buffer))
- (,@ forms))
- (set-buffer StartBuffer)))))
-
-(defmacro emerge-defvar-local (var value doc)
- "Defines SYMBOL as an advertised variable.
-Performs a defvar, then executes `make-variable-buffer-local' on
-the variable. Also sets the `preserved' property, so that
-`kill-all-local-variables' (called by major-mode setting commands)
-won't destroy Emerge control variables."
- (` (progn
- (defvar (, var) (, value) (, doc))
- (make-variable-buffer-local '(, var))
- (put '(, var) 'preserved t))))
-
-;; Add entries to minor-mode-alist so that emerge modes show correctly
-(defvar emerge-minor-modes-list
- '((emerge-mode " Emerge")
- (emerge-fast-mode " F")
- (emerge-edit-mode " E")
- (emerge-auto-advance " A")
- (emerge-skip-prefers " S")))
-(if (not (assq 'emerge-mode minor-mode-alist))
- (setq minor-mode-alist (append emerge-minor-modes-list
- minor-mode-alist)))
-
-;; We need to define this function so describe-mode can describe Emerge mode.
-(defun emerge-mode ()
- "Emerge mode is used by the Emerge file-merging package.
-It is entered only through one of the functions:
- `emerge-files'
- `emerge-files-with-ancestor'
- `emerge-buffers'
- `emerge-buffers-with-ancestor'
- `emerge-files-command'
- `emerge-files-with-ancestor-command'
- `emerge-files-remote'
- `emerge-files-with-ancestor-remote'
-
-Commands:
-\\{emerge-basic-keymap}
-Commands must be prefixed by \\<emerge-fast-keymap>\\[emerge-basic-keymap] in `edit' mode,
-but can be invoked directly in `fast' mode.")
-
-(defvar emerge-version "5fsf"
- "The version of Emerge.")
-
-(defun emerge-version ()
- "Return string describing the version of Emerge.
-When called interactively, displays the version."
- (interactive)
- (if (interactive-p)
- (message "Emerge version %s" (emerge-version))
- emerge-version))
-
-;;; Emerge configuration variables
-
-;; Commands that produce difference files
-;; All that can be configured is the name of the programs to execute
-;; (emerge-diff-program and emerge-diff3-program) and the options
-;; to be provided (emerge-diff-options). The order in which the file names
-;; are given is fixed.
-;; The file names are always expanded (see expand-file-name) before being
-;; passed to diff, thus they need not be invoked under a shell that
-;; understands `~'.
-;; The code which processes the diff/diff3 output depends on all the
-;; finicky details of their output, including the somewhat strange
-;; way they number lines of a file.
-(defvar emerge-diff-program "diff"
- "*Name of the program which compares two files.")
-(defvar emerge-diff3-program "diff3"
- "*Name of the program which compares three files.
-Its arguments are the ancestor file and the two variant files.")
-(defvar emerge-diff-options ""
- "*Options to pass to `emerge-diff-program' and `emerge-diff3-program'.")
-(defvar emerge-match-diff-line (let ((x "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)"))
- (concat "^" x "\\([acd]\\)" x "$"))
- "*Pattern to match lines produced by diff that describe differences.
-This is as opposed to lines from the source files.")
-(defvar emerge-diff-ok-lines-regexp
- "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\)"
- "*Regexp that matches normal output lines from `emerge-diff-program'.
-Lines that do not match are assumed to be error messages.")
-(defvar emerge-diff3-ok-lines-regexp
- "^\\([1-3]:\\|====\\| \\)"
- "*Regexp that matches normal output lines from `emerge-diff3-program'.
-Lines that do not match are assumed to be error messages.")
-
-(defvar emerge-rcs-ci-program "ci"
- "*Name of the program that checks in RCS revisions.")
-(defvar emerge-rcs-co-program "co"
- "*Name of the program that checks out RCS revisions.")
-
-(defvar emerge-process-local-variables nil
- "*Non-nil if Emerge should process local-variables lists in merge buffers.
-\(You can explicitly request processing the local-variables
-by executing `(hack-local-variables)'.)")
-(defvar emerge-execute-line-deletions nil
- "*If non-nil: `emerge-execute-line' makes no output if an input was deleted.
-It concludes that an input version has been deleted when an ancestor entry
-is present, only one A or B entry is present, and an output entry is present.
-If nil: In such circumstances, the A or B file that is present will be
-copied to the designated output file.")
-
-(defvar emerge-before-flag "vvvvvvvvvvvvvvvvvvvv\n"
- "*Flag placed above the highlighted block of code. Must end with newline.
-Must be set before Emerge is loaded, or emerge-new-flags must be run
-after setting.")
-(defvar emerge-after-flag "^^^^^^^^^^^^^^^^^^^^\n"
- "*Flag placed below the highlighted block of code. Must end with newline.
-Must be set before Emerge is loaded, or emerge-new-flags must be run
-after setting.")
-
-;; Hook variables
-
-(defvar emerge-startup-hook nil
- "*Hook to run in the merge buffer after the merge has been set up.")
-(defvar emerge-select-hook nil
- "*Hook to run after a difference has been selected.
-The variable `n' holds the (internal) number of the difference.")
-(defvar emerge-unselect-hook nil
- "*Hook to run after a difference has been unselected.
-The variable `n' holds the (internal) number of the difference.")
-
-;; Variables to control the default directories of the arguments to
-;; Emerge commands.
-
-(defvar emerge-default-last-directories nil
- "*If nil, default dir for filenames in emerge is `default-directory'.
-If non-nil, filenames complete in the directory of the last argument of the
-same type to an `emerge-files...' command.")
-
-(defvar emerge-last-dir-A nil
- "Last directory for the first file of an `emerge-files...' command.")
-(defvar emerge-last-dir-B nil
- "Last directory for the second file of an `emerge-files...' command.")
-(defvar emerge-last-dir-ancestor nil
- "Last directory for the ancestor file of an `emerge-files...' command.")
-(defvar emerge-last-dir-output nil
- "Last directory for the output file of an `emerge-files...' command.")
-(defvar emerge-last-revision-A nil
- "Last RCS revision used for first file of an `emerge-revisions...' command.")
-(defvar emerge-last-revision-B nil
- "Last RCS revision used for second file of an `emerge-revisions...' command.")
-(defvar emerge-last-revision-ancestor nil
- "Last RCS revision used for ancestor file of an `emerge-revisions...' command.")
-
-(defvar emerge-before-flag-length)
-(defvar emerge-before-flag-lines)
-(defvar emerge-before-flag-match)
-(defvar emerge-after-flag-length)
-(defvar emerge-after-flag-lines)
-(defvar emerge-after-flag-match)
-(defvar emerge-diff-buffer)
-(defvar emerge-diff-error-buffer)
-(defvar emerge-prefix-argument)
-(defvar emerge-file-out)
-(defvar emerge-exit-func)
-(defvar emerge-globalized-difference-list)
-(defvar emerge-globalized-number-of-differences)
-
-;; The flags used to mark differences in the buffers.
-
-;; These function definitions need to be up here, because they are used
-;; during loading.
-(defun emerge-new-flags ()
- "Function to be called after `emerge-{before,after}-flag'.
-This is called after these functions are changed to compute values that
-depend on the flags."
- (setq emerge-before-flag-length (length emerge-before-flag))
- (setq emerge-before-flag-lines
- (emerge-count-matches-string emerge-before-flag "\n"))
- (setq emerge-before-flag-match (regexp-quote emerge-before-flag))
- (setq emerge-after-flag-length (length emerge-after-flag))
- (setq emerge-after-flag-lines
- (emerge-count-matches-string emerge-after-flag "\n"))
- (setq emerge-after-flag-match (regexp-quote emerge-after-flag)))
-
-(defun emerge-count-matches-string (string regexp)
- "Return the number of matches in STRING for REGEXP."
- (let ((i 0)
- (count 0))
- (while (string-match regexp string i)
- (setq count (1+ count))
- (setq i (match-end 0)))
- count))
-
-;; Calculate dependent variables
-(emerge-new-flags)
-
-(defvar emerge-min-visible-lines 3
- "*Number of lines that we want to show above and below the flags when we are
-displaying a difference.")
-
-(defvar emerge-temp-file-prefix
- (let ((env (or (getenv "TMPDIR")
- (getenv "TMP")
- (getenv "TEMP")))
- d)
- (setq d (if (and env (> (length env) 0))
- env
- "/tmp"))
- (if (= (aref d (1- (length d))) ?/)
- (setq d (substring d 0 -1)))
- (concat d "/emerge"))
- "*Prefix to put on Emerge temporary file names.
-Do not start with `~/' or `~user-name/'.")
-
-(defvar emerge-temp-file-mode 384 ; u=rw only
- "*Mode for Emerge temporary files.")
-
-(defvar emerge-combine-versions-template
- "#ifdef NEW\n%b#else /* not NEW */\n%a#endif /* not NEW */\n"
- "*Template for `emerge-combine-versions' to combine the two versions.
-The template is inserted as a string, with the following interpolations:
- %a the A version of the difference
- %b the B version of the difference
- %% the character `%'
-Don't forget to end the template with a newline.
-Note that this variable can be made local to a particular merge buffer by
-giving a prefix argument to `emerge-set-combine-versions-template'.")
-
-;; Build keymaps
-
-(defvar emerge-basic-keymap nil
- "Keymap of Emerge commands.
-Directly available in `fast' mode;
-must be prefixed by \\<emerge-fast-keymap>\\[emerge-basic-keymap] in `edit' mode.")
-
-(defvar emerge-fast-keymap nil
- "Local keymap used in Emerge `fast' mode.
-Makes Emerge commands directly available.")
-
-(defvar emerge-options-menu
- (make-sparse-keymap "Options"))
-
-(defvar emerge-merge-menu
- (make-sparse-keymap "Merge"))
-
-(defvar emerge-move-menu
- (make-sparse-keymap "Move"))
-
-(defvar emerge-command-prefix "\C-c\C-c"
- "*Command prefix for Emerge commands in `edit' mode.
-Must be set before Emerge is loaded.")
-
-;; This function sets up the fixed keymaps. It is executed when the first
-;; Emerge is done to allow the user maximum time to set up the global keymap.
-(defun emerge-setup-fixed-keymaps ()
- ;; Set up the basic keymap
- (setq emerge-basic-keymap (make-keymap))
- (suppress-keymap emerge-basic-keymap) ; this sets 0..9 to digit-argument and
- ; - to negative-argument
- (define-key emerge-basic-keymap "p" 'emerge-previous-difference)
- (define-key emerge-basic-keymap "n" 'emerge-next-difference)
- (define-key emerge-basic-keymap "a" 'emerge-select-A)
- (define-key emerge-basic-keymap "b" 'emerge-select-B)
- (define-key emerge-basic-keymap "j" 'emerge-jump-to-difference)
- (define-key emerge-basic-keymap "." 'emerge-find-difference)
- (define-key emerge-basic-keymap "q" 'emerge-quit)
- (define-key emerge-basic-keymap "\C-]" 'emerge-abort)
- (define-key emerge-basic-keymap "f" 'emerge-fast-mode)
- (define-key emerge-basic-keymap "e" 'emerge-edit-mode)
- (define-key emerge-basic-keymap "s" nil)
- (define-key emerge-basic-keymap "sa" 'emerge-auto-advance)
- (define-key emerge-basic-keymap "ss" 'emerge-skip-prefers)
- (define-key emerge-basic-keymap "l" 'emerge-recenter)
- (define-key emerge-basic-keymap "d" nil)
- (define-key emerge-basic-keymap "da" 'emerge-default-A)
- (define-key emerge-basic-keymap "db" 'emerge-default-B)
- (define-key emerge-basic-keymap "c" nil)
- (define-key emerge-basic-keymap "ca" 'emerge-copy-as-kill-A)
- (define-key emerge-basic-keymap "cb" 'emerge-copy-as-kill-B)
- (define-key emerge-basic-keymap "i" nil)
- (define-key emerge-basic-keymap "ia" 'emerge-insert-A)
- (define-key emerge-basic-keymap "ib" 'emerge-insert-B)
- (define-key emerge-basic-keymap "m" 'emerge-mark-difference)
- (define-key emerge-basic-keymap "v" 'emerge-scroll-up)
- (define-key emerge-basic-keymap "^" 'emerge-scroll-down)
- (define-key emerge-basic-keymap "<" 'emerge-scroll-left)
- (define-key emerge-basic-keymap ">" 'emerge-scroll-right)
- (define-key emerge-basic-keymap "|" 'emerge-scroll-reset)
- (define-key emerge-basic-keymap "x" nil)
- (define-key emerge-basic-keymap "x1" 'emerge-one-line-window)
- (define-key emerge-basic-keymap "xc" 'emerge-combine-versions)
- (define-key emerge-basic-keymap "xC" 'emerge-combine-versions-register)
- (define-key emerge-basic-keymap "xf" 'emerge-file-names)
- (define-key emerge-basic-keymap "xj" 'emerge-join-differences)
- (define-key emerge-basic-keymap "xl" 'emerge-line-numbers)
- (define-key emerge-basic-keymap "xm" 'emerge-set-merge-mode)
- (define-key emerge-basic-keymap "xs" 'emerge-split-difference)
- (define-key emerge-basic-keymap "xt" 'emerge-trim-difference)
- (define-key emerge-basic-keymap "xx" 'emerge-set-combine-versions-template)
- ;; Allow emerge-basic-keymap to be referenced indirectly
- (fset 'emerge-basic-keymap emerge-basic-keymap)
- ;; Set up the fast mode keymap
- (setq emerge-fast-keymap (copy-keymap emerge-basic-keymap))
- ;; Allow prefixed commands to work in fast mode
- (define-key emerge-fast-keymap emerge-command-prefix 'emerge-basic-keymap)
- ;; Allow emerge-fast-keymap to be referenced indirectly
- (fset 'emerge-fast-keymap emerge-fast-keymap)
- ;; Suppress write-file and save-buffer
- (substitute-key-definition 'write-file 'emerge-query-write-file
- emerge-fast-keymap (current-global-map))
- (substitute-key-definition 'save-buffer 'emerge-query-save-buffer
- emerge-fast-keymap (current-global-map))
-
- (define-key emerge-basic-keymap [menu-bar] (make-sparse-keymap))
-
- (define-key emerge-fast-keymap [menu-bar options]
- (cons "Options" emerge-options-menu))
- (define-key emerge-fast-keymap [menu-bar merge]
- (cons "Merge" emerge-merge-menu))
- (define-key emerge-fast-keymap [menu-bar move]
- (cons "Move" emerge-move-menu))
-
- (define-key emerge-move-menu [emerge-scroll-reset]
- '("Scroll Reset" . emerge-scroll-reset))
- (define-key emerge-move-menu [emerge-scroll-right]
- '("Scroll Right" . emerge-scroll-right))
- (define-key emerge-move-menu [emerge-scroll-left]
- '("Scroll Left" . emerge-scroll-left))
- (define-key emerge-move-menu [emerge-scroll-down]
- '("Scroll Down" . emerge-scroll-down))
- (define-key emerge-move-menu [emerge-scroll-up]
- '("Scroll Up" . emerge-scroll-up))
- (define-key emerge-move-menu [emerge-recenter]
- '("Recenter" . emerge-recenter))
- (define-key emerge-move-menu [emerge-mark-difference]
- '("Mark Difference" . emerge-mark-difference))
- (define-key emerge-move-menu [emerge-jump-to-difference]
- '("Jump To Difference" . emerge-jump-to-difference))
- (define-key emerge-move-menu [emerge-find-difference]
- '("Find Difference" . emerge-find-difference))
- (define-key emerge-move-menu [emerge-previous-difference]
- '("Previous Difference" . emerge-previous-difference))
- (define-key emerge-move-menu [emerge-next-difference]
- '("Next Difference" . emerge-next-difference))
-
-
- (define-key emerge-options-menu [emerge-one-line-window]
- '("One Line Window" . emerge-one-line-window))
- (define-key emerge-options-menu [emerge-set-merge-mode]
- '("Set Merge Mode" . emerge-set-merge-mode))
- (define-key emerge-options-menu [emerge-set-combine-template]
- '("Set Combine Template..." . emerge-set-combine-template))
- (define-key emerge-options-menu [emerge-default-B]
- '("Default B" . emerge-default-B))
- (define-key emerge-options-menu [emerge-default-A]
- '("Default A" . emerge-default-A))
- (define-key emerge-options-menu [emerge-skip-prefers]
- '("Skip Prefers" . emerge-skip-prefers))
- (define-key emerge-options-menu [emerge-auto-advance]
- '("Auto Advance" . emerge-auto-advance))
- (define-key emerge-options-menu [emerge-edit-mode]
- '("Edit Mode" . emerge-edit-mode))
- (define-key emerge-options-menu [emerge-fast-mode]
- '("Fast Mode" . emerge-fast-mode))
-
- (define-key emerge-merge-menu [emerge-abort] '("Abort" . emerge-abort))
- (define-key emerge-merge-menu [emerge-quit] '("Quit" . emerge-quit))
- (define-key emerge-merge-menu [emerge-split-difference]
- '("Split Difference" . emerge-split-difference))
- (define-key emerge-merge-menu [emerge-join-differences]
- '("Join Differences" . emerge-join-differences))
- (define-key emerge-merge-menu [emerge-trim-difference]
- '("Trim Difference" . emerge-trim-difference))
- (define-key emerge-merge-menu [emerge-combine-versions]
- '("Combine Versions" . emerge-combine-versions))
- (define-key emerge-merge-menu [emerge-copy-as-kill-B]
- '("Copy B as Kill" . emerge-copy-as-kill-B))
- (define-key emerge-merge-menu [emerge-copy-as-kill-A]
- '("Copy A as Kill" . emerge-copy-as-kill-A))
- (define-key emerge-merge-menu [emerge-insert-B]
- '("Insert B" . emerge-insert-B))
- (define-key emerge-merge-menu [emerge-insert-A]
- '("Insert A" . emerge-insert-A))
- (define-key emerge-merge-menu [emerge-select-B]
- '("Select B" . emerge-select-B))
- (define-key emerge-merge-menu [emerge-select-A]
- '("Select A" . emerge-select-A)))
-
-
-;; Variables which control each merge. They are local to the merge buffer.
-
-;; Mode variables
-(emerge-defvar-local emerge-mode nil
- "Indicator for emerge-mode.")
-(emerge-defvar-local emerge-fast-mode nil
- "Indicator for emerge-mode fast submode.")
-(emerge-defvar-local emerge-edit-mode nil
- "Indicator for emerge-mode edit submode.")
-(emerge-defvar-local emerge-A-buffer nil
- "The buffer in which the A variant is stored.")
-(emerge-defvar-local emerge-B-buffer nil
- "The buffer in which the B variant is stored.")
-(emerge-defvar-local emerge-merge-buffer nil
- "The buffer in which the merged file is manipulated.")
-(emerge-defvar-local emerge-ancestor-buffer nil
- "The buffer in which the ancestor variant is stored,
-or nil if there is none.")
-
-(defconst emerge-saved-variables
- '((buffer-modified-p set-buffer-modified-p)
- buffer-read-only
- buffer-auto-save-file-name)
- "Variables and properties of a buffer which are saved, modified and restored
-during a merge.")
-(defconst emerge-merging-values '(nil t nil)
- "Values to be assigned to emerge-saved-variables during a merge.")
-
-(emerge-defvar-local emerge-A-buffer-values nil
- "Remembers emerge-saved-variables for emerge-A-buffer.")
-(emerge-defvar-local emerge-B-buffer-values nil
- "Remembers emerge-saved-variables for emerge-B-buffer.")
-
-(emerge-defvar-local emerge-difference-list nil
- "Vector of differences between the variants, and markers in the buffers to
-show where they are. Each difference is represented by a vector of seven
-elements. The first two are markers to the beginning and end of the difference
-section in the A buffer, the second two are markers for the B buffer, the third
-two are markers for the merge buffer, and the last element is the \"state\" of
-that difference in the merge buffer.
- A section of a buffer is described by two markers, one to the beginning of
-the first line of the section, and one to the beginning of the first line
-after the section. (If the section is empty, both markers point to the same
-point.) If the section is part of the selected difference, then the markers
-are moved into the flags, so the user can edit the section without disturbing
-the markers.
- The \"states\" are:
- A the merge buffer currently contains the A variant
- B the merge buffer currently contains the B variant
- default-A the merge buffer contains the A variant by default,
- but this difference hasn't been selected yet, so
- change-default commands can alter it
- default-B the merge buffer contains the B variant by default,
- but this difference hasn't been selected yet, so
- change-default commands can alter it
- prefer-A in a three-file merge, the A variant is the preferred
- choice
- prefer-B in a three-file merge, the B variant is the preferred
- choice")
-(emerge-defvar-local emerge-current-difference -1
- "The difference that is currently selected.")
-(emerge-defvar-local emerge-number-of-differences nil
- "Number of differences found.")
-(emerge-defvar-local emerge-edit-keymap nil
- "The local keymap for the merge buffer, with the emerge commands defined in
-it. Used to save the local keymap during fast mode, when the local keymap is
-replaced by emerge-fast-keymap.")
-(emerge-defvar-local emerge-old-keymap nil
- "The original local keymap for the merge buffer.")
-(emerge-defvar-local emerge-auto-advance nil
- "*If non-nil, emerge-select-A and emerge-select-B automatically advance to
-the next difference.")
-(emerge-defvar-local emerge-skip-prefers nil
- "*If non-nil, differences for which there is a preference are automatically
-skipped.")
-(emerge-defvar-local emerge-quit-hook nil
- "Hooks to run in the merge buffer after the merge has been finished.
-`emerge-prefix-argument' will hold the prefix argument of the `emerge-quit'
-command.
-This is *not* a user option, since Emerge uses it for its own processing.")
-(emerge-defvar-local emerge-output-description nil
- "Describes output destination of emerge, for `emerge-file-names'.")
-
-;;; Setup functions for two-file mode.
-
-(defun emerge-files-internal (file-A file-B &optional startup-hooks quit-hooks
- output-file)
- (if (not (file-readable-p file-A))
- (error "File `%s' does not exist or is not readable" file-A))
- (if (not (file-readable-p file-B))
- (error "File `%s' does not exist or is not readable" file-B))
- (let ((buffer-A (find-file-noselect file-A))
- (buffer-B (find-file-noselect file-B)))
- ;; Record the directories of the files
- (setq emerge-last-dir-A (file-name-directory file-A))
- (setq emerge-last-dir-B (file-name-directory file-B))
- (if output-file
- (setq emerge-last-dir-output (file-name-directory output-file)))
- ;; Make sure the entire files are seen, and they reflect what is on disk
- (emerge-eval-in-buffer
- buffer-A
- (widen)
- (let ((temp (file-local-copy file-A)))
- (if temp
- (setq file-A temp
- startup-hooks
- (cons (` (lambda () (delete-file (, file-A))))
- startup-hooks))
- ;; Verify that the file matches the buffer
- (emerge-verify-file-buffer))))
- (emerge-eval-in-buffer
- buffer-B
- (widen)
- (let ((temp (file-local-copy file-B)))
- (if temp
- (setq file-B temp
- startup-hooks
- (cons (` (lambda () (delete-file (, file-B))))
- startup-hooks))
- ;; Verify that the file matches the buffer
- (emerge-verify-file-buffer))))
- (emerge-setup buffer-A file-A buffer-B file-B startup-hooks quit-hooks
- output-file)))
-
-;; Start up Emerge on two files
-(defun emerge-setup (buffer-A file-A buffer-B file-B startup-hooks quit-hooks
- output-file)
- (setq file-A (expand-file-name file-A))
- (setq file-B (expand-file-name file-B))
- (setq output-file (and output-file (expand-file-name output-file)))
- (let* ((merge-buffer-name (emerge-unique-buffer-name "*merge" "*"))
- ;; create the merge buffer from buffer A, so it inherits buffer A's
- ;; default directory, etc.
- (merge-buffer (emerge-eval-in-buffer
- buffer-A
- (get-buffer-create merge-buffer-name))))
- (emerge-eval-in-buffer
- merge-buffer
- (emerge-copy-modes buffer-A)
- (setq buffer-read-only nil)
- (auto-save-mode 1)
- (setq emerge-mode t)
- (setq emerge-A-buffer buffer-A)
- (setq emerge-B-buffer buffer-B)
- (setq emerge-ancestor-buffer nil)
- (setq emerge-merge-buffer merge-buffer)
- (setq emerge-output-description
- (if output-file
- (concat "Output to file: " output-file)
- (concat "Output to buffer: " (buffer-name merge-buffer))))
- (insert-buffer emerge-A-buffer)
- (emerge-set-keys)
- (setq emerge-difference-list (emerge-make-diff-list file-A file-B))
- (setq emerge-number-of-differences (length emerge-difference-list))
- (setq emerge-current-difference -1)
- (setq emerge-quit-hook quit-hooks)
- (emerge-remember-buffer-characteristics)
- (emerge-handle-local-variables))
- (emerge-setup-windows buffer-A buffer-B merge-buffer t)
- (emerge-eval-in-buffer merge-buffer
- (run-hooks 'startup-hooks 'emerge-startup-hook)
- (setq buffer-read-only t))))
-
-;; Generate the Emerge difference list between two files
-(defun emerge-make-diff-list (file-A file-B)
- (setq emerge-diff-buffer (get-buffer-create "*emerge-diff*"))
- (emerge-eval-in-buffer
- emerge-diff-buffer
- (erase-buffer)
- (shell-command
- (format "%s %s %s %s"
- emerge-diff-program emerge-diff-options
- (emerge-protect-metachars file-A)
- (emerge-protect-metachars file-B))
- t))
- (emerge-prepare-error-list emerge-diff-ok-lines-regexp)
- (emerge-convert-diffs-to-markers
- emerge-A-buffer emerge-B-buffer emerge-merge-buffer
- (emerge-extract-diffs emerge-diff-buffer)))
-
-(defun emerge-extract-diffs (diff-buffer)
- (let (list)
- (emerge-eval-in-buffer
- diff-buffer
- (goto-char (point-min))
- (while (re-search-forward emerge-match-diff-line nil t)
- (let* ((a-begin (string-to-int (buffer-substring (match-beginning 1)
- (match-end 1))))
- (a-end (let ((b (match-beginning 3))
- (e (match-end 3)))
- (if b
- (string-to-int (buffer-substring b e))
- a-begin)))
- (diff-type (buffer-substring (match-beginning 4) (match-end 4)))
- (b-begin (string-to-int (buffer-substring (match-beginning 5)
- (match-end 5))))
- (b-end (let ((b (match-beginning 7))
- (e (match-end 7)))
- (if b
- (string-to-int (buffer-substring b e))
- b-begin))))
- ;; fix the beginning and end numbers, because diff is somewhat
- ;; strange about how it numbers lines
- (if (string-equal diff-type "a")
- (progn
- (setq b-end (1+ b-end))
- (setq a-begin (1+ a-begin))
- (setq a-end a-begin))
- (if (string-equal diff-type "d")
- (progn
- (setq a-end (1+ a-end))
- (setq b-begin (1+ b-begin))
- (setq b-end b-begin))
- ;; (string-equal diff-type "c")
- (progn
- (setq a-end (1+ a-end))
- (setq b-end (1+ b-end)))))
- (setq list (cons (vector a-begin a-end
- b-begin b-end
- 'default-A)
- list)))))
- (nreverse list)))
-
-;; Set up buffer of diff/diff3 error messages.
-(defun emerge-prepare-error-list (ok-regexp)
- (setq emerge-diff-error-buffer (get-buffer-create "*emerge-diff-errors*"))
- (emerge-eval-in-buffer
- emerge-diff-error-buffer
- (erase-buffer)
- (insert-buffer emerge-diff-buffer)
- (delete-matching-lines ok-regexp)))
-
-;;; Top-level and setup functions for three-file mode.
-
-(defun emerge-files-with-ancestor-internal (file-A file-B file-ancestor
- &optional startup-hooks quit-hooks
- output-file)
- (if (not (file-readable-p file-A))
- (error "File `%s' does not exist or is not readable" file-A))
- (if (not (file-readable-p file-B))
- (error "File `%s' does not exist or is not readable" file-B))
- (if (not (file-readable-p file-ancestor))
- (error "File `%s' does not exist or is not readable" file-ancestor))
- (let ((buffer-A (find-file-noselect file-A))
- (buffer-B (find-file-noselect file-B))
- (buffer-ancestor (find-file-noselect file-ancestor)))
- ;; Record the directories of the files
- (setq emerge-last-dir-A (file-name-directory file-A))
- (setq emerge-last-dir-B (file-name-directory file-B))
- (setq emerge-last-dir-ancestor (file-name-directory file-ancestor))
- (if output-file
- (setq emerge-last-dir-output (file-name-directory output-file)))
- ;; Make sure the entire files are seen, and they reflect what is on disk
- (emerge-eval-in-buffer
- buffer-A
- (widen)
- (let ((temp (file-local-copy file-A)))
- (if temp
- (setq file-A temp
- startup-hooks
- (cons (` (lambda () (delete-file (, file-A))))
- startup-hooks))
- ;; Verify that the file matches the buffer
- (emerge-verify-file-buffer))))
- (emerge-eval-in-buffer
- buffer-B
- (widen)
- (let ((temp (file-local-copy file-B)))
- (if temp
- (setq file-B temp
- startup-hooks
- (cons (` (lambda () (delete-file (, file-B))))
- startup-hooks))
- ;; Verify that the file matches the buffer
- (emerge-verify-file-buffer))))
- (emerge-eval-in-buffer
- buffer-ancestor
- (widen)
- (let ((temp (file-local-copy file-ancestor)))
- (if temp
- (setq file-ancestor temp
- startup-hooks
- (cons (` (lambda () (delete-file (, file-ancestor))))
- startup-hooks))
- ;; Verify that the file matches the buffer
- (emerge-verify-file-buffer))))
- (emerge-setup-with-ancestor buffer-A file-A buffer-B file-B
- buffer-ancestor file-ancestor
- startup-hooks quit-hooks output-file)))
-
-;; Start up Emerge on two files with an ancestor
-(defun emerge-setup-with-ancestor (buffer-A file-A buffer-B file-B
- buffer-ancestor file-ancestor
- &optional startup-hooks quit-hooks
- output-file)
- (setq file-A (expand-file-name file-A))
- (setq file-B (expand-file-name file-B))
- (setq file-ancestor (expand-file-name file-ancestor))
- (setq output-file (and output-file (expand-file-name output-file)))
- (let* ((merge-buffer-name (emerge-unique-buffer-name "*merge" "*"))
- ;; create the merge buffer from buffer A, so it inherits buffer A's
- ;; default directory, etc.
- (merge-buffer (emerge-eval-in-buffer
- buffer-A
- (get-buffer-create merge-buffer-name))))
- (emerge-eval-in-buffer
- merge-buffer
- (emerge-copy-modes buffer-A)
- (setq buffer-read-only nil)
- (auto-save-mode 1)
- (setq emerge-mode t)
- (setq emerge-A-buffer buffer-A)
- (setq emerge-B-buffer buffer-B)
- (setq emerge-ancestor-buffer buffer-ancestor)
- (setq emerge-merge-buffer merge-buffer)
- (setq emerge-output-description
- (if output-file
- (concat "Output to file: " output-file)
- (concat "Output to buffer: " (buffer-name merge-buffer))))
- (insert-buffer emerge-A-buffer)
- (emerge-set-keys)
- (setq emerge-difference-list
- (emerge-make-diff3-list file-A file-B file-ancestor))
- (setq emerge-number-of-differences (length emerge-difference-list))
- (setq emerge-current-difference -1)
- (setq emerge-quit-hook quit-hooks)
- (emerge-remember-buffer-characteristics)
- (emerge-select-prefer-Bs)
- (emerge-handle-local-variables))
- (emerge-setup-windows buffer-A buffer-B merge-buffer t)
- (emerge-eval-in-buffer merge-buffer
- (run-hooks 'startup-hooks 'emerge-startup-hook)
- (setq buffer-read-only t))))
-
-;; Generate the Emerge difference list between two files with an ancestor
-(defun emerge-make-diff3-list (file-A file-B file-ancestor)
- (setq emerge-diff-buffer (get-buffer-create "*emerge-diff*"))
- (emerge-eval-in-buffer
- emerge-diff-buffer
- (erase-buffer)
- (shell-command
- (format "%s %s %s %s %s"
- emerge-diff3-program emerge-diff-options
- (emerge-protect-metachars file-A)
- (emerge-protect-metachars file-ancestor)
- (emerge-protect-metachars file-B))
- t))
- (emerge-prepare-error-list emerge-diff3-ok-lines-regexp)
- (emerge-convert-diffs-to-markers
- emerge-A-buffer emerge-B-buffer emerge-merge-buffer
- (emerge-extract-diffs3 emerge-diff-buffer)))
-
-(defun emerge-extract-diffs3 (diff-buffer)
- (let (list)
- (emerge-eval-in-buffer
- diff-buffer
- (while (re-search-forward "^====\\(.?\\)$" nil t)
- ;; leave point after matched line
- (beginning-of-line 2)
- (let ((agreement (buffer-substring (match-beginning 1) (match-end 1))))
- ;; if the A and B files are the same, ignore the difference
- (if (not (string-equal agreement "2"))
- (setq list
- (cons
- (let (group-1 group-3 pos)
- (setq pos (point))
- (setq group-1 (emerge-get-diff3-group "1"))
- (goto-char pos)
- (setq group-3 (emerge-get-diff3-group "3"))
- (vector (car group-1) (car (cdr group-1))
- (car group-3) (car (cdr group-3))
- (cond ((string-equal agreement "1") 'prefer-A)
- ((string-equal agreement "3") 'prefer-B)
- (t 'default-A))))
- list))))))
- (nreverse list)))
-
-(defun emerge-get-diff3-group (file)
- ;; This save-excursion allows emerge-get-diff3-group to be called for the
- ;; various groups of lines (1, 2, 3) in any order, and for the lines to
- ;; appear in any order. The reason this is necessary is that Gnu diff3
- ;; can produce the groups in the order 1, 2, 3 or 1, 3, 2.
- (save-excursion
- (re-search-forward
- (concat "^" file ":\\([0-9]+\\)\\(,\\([0-9]+\\)\\)?\\([ac]\\)$"))
- (beginning-of-line 2)
- ;; treatment depends on whether it is an "a" group or a "c" group
- (if (string-equal (buffer-substring (match-beginning 4) (match-end 4)) "c")
- ;; it is a "c" group
- (if (match-beginning 2)
- ;; it has two numbers
- (list (string-to-int
- (buffer-substring (match-beginning 1) (match-end 1)))
- (1+ (string-to-int
- (buffer-substring (match-beginning 3) (match-end 3)))))
- ;; it has one number
- (let ((x (string-to-int
- (buffer-substring (match-beginning 1) (match-end 1)))))
- (list x (1+ x))))
- ;; it is an "a" group
- (let ((x (1+ (string-to-int
- (buffer-substring (match-beginning 1) (match-end 1))))))
- (list x x)))))
-
-;;; Functions to start Emerge on files
-
-;;;###autoload
-(defun emerge-files (arg file-A file-B file-out &optional startup-hooks
- quit-hooks)
- "Run Emerge on two files."
- (interactive
- (let (f)
- (list current-prefix-arg
- (setq f (emerge-read-file-name "File A to merge" emerge-last-dir-A
- nil nil t))
- (emerge-read-file-name "File B to merge" emerge-last-dir-B nil f t)
- (and current-prefix-arg
- (emerge-read-file-name "Output file" emerge-last-dir-output
- f f nil)))))
- (if file-out
- (add-hook 'quit-hooks (` (lambda () (emerge-files-exit (, file-out))))))
- (emerge-files-internal
- file-A file-B startup-hooks
- quit-hooks
- file-out))
-
-;;;###autoload
-(defun emerge-files-with-ancestor (arg file-A file-B file-ancestor file-out
- &optional startup-hooks quit-hooks)
- "Run Emerge on two files, giving another file as the ancestor."
- (interactive
- (let (f)
- (list current-prefix-arg
- (setq f (emerge-read-file-name "File A to merge" emerge-last-dir-A
- nil nil t))
- (emerge-read-file-name "File B to merge" emerge-last-dir-B nil f t)
- (emerge-read-file-name "Ancestor file" emerge-last-dir-ancestor
- nil f t)
- (and current-prefix-arg
- (emerge-read-file-name "Output file" emerge-last-dir-output
- f f nil)))))
- (if file-out
- (add-hook 'quit-hooks (` (lambda () (emerge-files-exit (, file-out))))))
- (emerge-files-with-ancestor-internal
- file-A file-B file-ancestor startup-hooks
- quit-hooks
- file-out))
-
-;; Write the merge buffer out in place of the file the A buffer is visiting.
-(defun emerge-files-exit (file-out)
- ;; if merge was successful was given, save to disk
- (if (not emerge-prefix-argument)
- (emerge-write-and-delete file-out)))
-
-;;; Functions to start Emerge on buffers
-
-;;;###autoload
-(defun emerge-buffers (buffer-A buffer-B &optional startup-hooks quit-hooks)
- "Run Emerge on two buffers."
- (interactive "bBuffer A to merge: \nbBuffer B to merge: ")
- (let ((emerge-file-A (emerge-make-temp-file "A"))
- (emerge-file-B (emerge-make-temp-file "B")))
- (emerge-eval-in-buffer
- buffer-A
- (write-region (point-min) (point-max) emerge-file-A nil 'no-message))
- (emerge-eval-in-buffer
- buffer-B
- (write-region (point-min) (point-max) emerge-file-B nil 'no-message))
- (emerge-setup (get-buffer buffer-A) emerge-file-A
- (get-buffer buffer-B) emerge-file-B
- (cons (` (lambda ()
- (delete-file (, emerge-file-A))
- (delete-file (, emerge-file-B))))
- startup-hooks)
- quit-hooks
- nil)))
-
-;;;###autoload
-(defun emerge-buffers-with-ancestor (buffer-A buffer-B buffer-ancestor
- &optional startup-hooks
- quit-hooks)
- "Run Emerge on two buffers, giving another buffer as the ancestor."
- (interactive
- "bBuffer A to merge: \nbBuffer B to merge: \nbAncestor buffer: ")
- (let ((emerge-file-A (emerge-make-temp-file "A"))
- (emerge-file-B (emerge-make-temp-file "B"))
- (emerge-file-ancestor (emerge-make-temp-file "anc")))
- (emerge-eval-in-buffer
- buffer-A
- (write-region (point-min) (point-max) emerge-file-A nil 'no-message))
- (emerge-eval-in-buffer
- buffer-B
- (write-region (point-min) (point-max) emerge-file-B nil 'no-message))
- (emerge-eval-in-buffer
- buffer-ancestor
- (write-region (point-min) (point-max) emerge-file-ancestor nil
- 'no-message))
- (emerge-setup-with-ancestor (get-buffer buffer-A) emerge-file-A
- (get-buffer buffer-B) emerge-file-B
- (get-buffer buffer-ancestor)
- emerge-file-ancestor
- (cons (` (lambda ()
- (delete-file (, emerge-file-A))
- (delete-file (, emerge-file-B))
- (delete-file
- (, emerge-file-ancestor))))
- startup-hooks)
- quit-hooks
- nil)))
-
-;;; Functions to start Emerge from the command line
-
-;;;###autoload
-(defun emerge-files-command ()
- (let ((file-a (nth 0 command-line-args-left))
- (file-b (nth 1 command-line-args-left))
- (file-out (nth 2 command-line-args-left)))
- (setq command-line-args-left (nthcdr 3 command-line-args-left))
- (emerge-files-internal
- file-a file-b nil
- (list (` (lambda () (emerge-command-exit (, file-out))))))))
-
-;;;###autoload
-(defun emerge-files-with-ancestor-command ()
- (let (file-a file-b file-anc file-out)
- ;; check for a -a flag, for filemerge compatibility
- (if (string= (car command-line-args-left) "-a")
- ;; arguments are "-a ancestor file-a file-b file-out"
- (progn
- (setq file-a (nth 2 command-line-args-left))
- (setq file-b (nth 3 command-line-args-left))
- (setq file-anc (nth 1 command-line-args-left))
- (setq file-out (nth 4 command-line-args-left))
- (setq command-line-args-left (nthcdr 5 command-line-args-left)))
- ;; arguments are "file-a file-b ancestor file-out"
- (setq file-a (nth 0 command-line-args-left))
- (setq file-b (nth 1 command-line-args-left))
- (setq file-anc (nth 2 command-line-args-left))
- (setq file-out (nth 3 command-line-args-left))
- (setq command-line-args-left (nthcdr 4 command-line-args-left)))
- (emerge-files-with-ancestor-internal
- file-a file-b file-anc nil
- (list (` (lambda () (emerge-command-exit (, file-out))))))))
-
-(defun emerge-command-exit (file-out)
- (emerge-write-and-delete file-out)
- (kill-emacs (if emerge-prefix-argument 1 0)))
-
-;;; Functions to start Emerge via remote request
-
-;;;###autoload
-(defun emerge-files-remote (file-a file-b file-out)
- (setq emerge-file-out file-out)
- (emerge-files-internal
- file-a file-b nil
- (list (` (lambda () (emerge-remote-exit (, file-out) '(, emerge-exit-func)))))
- file-out)
- (throw 'client-wait nil))
-
-;;;###autoload
-(defun emerge-files-with-ancestor-remote (file-a file-b file-anc file-out)
- (setq emerge-file-out file-out)
- (emerge-files-with-ancestor-internal
- file-a file-b file-anc nil
- (list (` (lambda () (emerge-remote-exit (, file-out) '(, emerge-exit-func)))))
- file-out)
- (throw 'client-wait nil))
-
-(defun emerge-remote-exit (file-out emerge-exit-func)
- (emerge-write-and-delete file-out)
- (kill-buffer emerge-merge-buffer)
- (funcall emerge-exit-func (if emerge-prefix-argument 1 0)))
-
-;;; Functions to start Emerge on RCS versions
-
-;;;###autoload
-(defun emerge-revisions (arg file revision-A revision-B
- &optional startup-hooks quit-hooks)
- "Emerge two RCS revisions of a file."
- (interactive
- (list current-prefix-arg
- (read-file-name "File to merge: " nil nil 'confirm)
- (read-string "Revision A to merge: " emerge-last-revision-A)
- (read-string "Revision B to merge: " emerge-last-revision-B)))
- (setq emerge-last-revision-A revision-A
- emerge-last-revision-B revision-B)
- (emerge-revisions-internal
- file revision-A revision-B startup-hooks
- (if arg
- (cons (` (lambda ()
- (shell-command
- (, (format "%s %s" emerge-rcs-ci-program file)))))
- quit-hooks)
- quit-hooks)))
-
-;;;###autoload
-(defun emerge-revisions-with-ancestor (arg file revision-A
- revision-B ancestor
- &optional
- startup-hooks quit-hooks)
- "Emerge two RCS revisions of a file, with another revision as ancestor."
- (interactive
- (list current-prefix-arg
- (read-file-name "File to merge: " nil nil 'confirm)
- (read-string "Revision A to merge: " emerge-last-revision-A)
- (read-string "Revision B to merge: " emerge-last-revision-B)
- (read-string "Ancestor: " emerge-last-revision-ancestor)))
- (setq emerge-last-revision-A revision-A
- emerge-last-revision-B revision-B
- emerge-last-revision-ancestor ancestor)
- (emerge-revision-with-ancestor-internal
- file revision-A revision-B ancestor startup-hooks
- (if arg
- (let ((cmd ))
- (cons (` (lambda ()
- (shell-command
- (, (format "%s %s" emerge-rcs-ci-program file)))))
- quit-hooks))
- quit-hooks)))
-
-(defun emerge-revisions-internal (file revision-A revision-B &optional
- startup-hooks quit-hooks output-file)
- (let ((buffer-A (get-buffer-create (format "%s,%s" file revision-A)))
- (buffer-B (get-buffer-create (format "%s,%s" file revision-B)))
- (emerge-file-A (emerge-make-temp-file "A"))
- (emerge-file-B (emerge-make-temp-file "B")))
- ;; Get the revisions into buffers
- (emerge-eval-in-buffer
- buffer-A
- (erase-buffer)
- (shell-command
- (format "%s -q -p%s %s" emerge-rcs-co-program revision-A file)
- t)
- (write-region (point-min) (point-max) emerge-file-A nil 'no-message)
- (set-buffer-modified-p nil))
- (emerge-eval-in-buffer
- buffer-B
- (erase-buffer)
- (shell-command
- (format "%s -q -p%s %s" emerge-rcs-co-program revision-B file)
- t)
- (write-region (point-min) (point-max) emerge-file-B nil 'no-message)
- (set-buffer-modified-p nil))
- ;; Do the merge
- (emerge-setup buffer-A emerge-file-A
- buffer-B emerge-file-B
- (cons (` (lambda ()
- (delete-file (, emerge-file-A))
- (delete-file (, emerge-file-B))))
- startup-hooks)
- (cons (` (lambda () (emerge-files-exit (, file))))
- quit-hooks)
- nil)))
-
-(defun emerge-revision-with-ancestor-internal (file revision-A revision-B
- ancestor
- &optional startup-hooks
- quit-hooks output-file)
- (let ((buffer-A (get-buffer-create (format "%s,%s" file revision-A)))
- (buffer-B (get-buffer-create (format "%s,%s" file revision-B)))
- (buffer-ancestor (get-buffer-create (format "%s,%s" file ancestor)))
- (emerge-file-A (emerge-make-temp-file "A"))
- (emerge-file-B (emerge-make-temp-file "B"))
- (emerge-ancestor (emerge-make-temp-file "ancestor")))
- ;; Get the revisions into buffers
- (emerge-eval-in-buffer
- buffer-A
- (erase-buffer)
- (shell-command
- (format "%s -q -p%s %s" emerge-rcs-co-program
- revision-A file)
- t)
- (write-region (point-min) (point-max) emerge-file-A nil 'no-message)
- (set-buffer-modified-p nil))
- (emerge-eval-in-buffer
- buffer-B
- (erase-buffer)
- (shell-command
- (format "%s -q -p%s %s" emerge-rcs-co-program revision-B file)
- t)
- (write-region (point-min) (point-max) emerge-file-B nil 'no-message)
- (set-buffer-modified-p nil))
- (emerge-eval-in-buffer
- buffer-ancestor
- (erase-buffer)
- (shell-command
- (format "%s -q -p%s %s" emerge-rcs-co-program ancestor file)
- t)
- (write-region (point-min) (point-max) emerge-ancestor nil 'no-message)
- (set-buffer-modified-p nil))
- ;; Do the merge
- (emerge-setup-with-ancestor
- buffer-A emerge-file-A buffer-B emerge-file-B
- buffer-ancestor emerge-ancestor
- (cons (` (lambda ()
- (delete-file (, emerge-file-A))
- (delete-file (, emerge-file-B))
- (delete-file (, emerge-ancestor))))
- startup-hooks)
- (cons (` (lambda () (emerge-files-exit (, file))))
- quit-hooks)
- output-file)))
-
-;;; Function to start Emerge based on a line in a file
-
-(defun emerge-execute-line ()
- "Run Emerge using files named in current text line.
-Looks in that line for whitespace-separated entries of these forms:
- a=file1
- b=file2
- ancestor=file3
- output=file4
-to specify the files to use in Emerge.
-
-In addition, if only one of `a=file' or `b=file' is present, and `output=file'
-is present:
-If `emerge-execute-line-deletions' is non-nil and `ancestor=file' is present,
-it is assumed that the file in question has been deleted, and it is
-not copied to the output file.
-Otherwise, the A or B file present is copied to the output file."
- (interactive)
- (let (file-A file-B file-ancestor file-out
- (case-fold-search t))
- ;; Stop if at end of buffer (even though we might be in a line, if
- ;; the line does not end with newline)
- (if (eobp)
- (error "At end of buffer"))
- ;; Go to the beginning of the line
- (beginning-of-line)
- ;; Skip any initial whitespace
- (if (looking-at "[ \t]*")
- (goto-char (match-end 0)))
- ;; Process the entire line
- (while (not (eolp))
- ;; Get the next entry
- (if (looking-at "\\([a-z]+\\)=\\([^ \t\n]+\\)[ \t]*")
- ;; Break apart the tab (before =) and the filename (after =)
- (let ((tag (downcase
- (buffer-substring (match-beginning 1) (match-end 1))))
- (file (buffer-substring (match-beginning 2) (match-end 2))))
- ;; Move point after the entry
- (goto-char (match-end 0))
- ;; Store the filename in the right variable
- (cond
- ((string-equal tag "a")
- (if file-A
- (error "This line has two `A' entries"))
- (setq file-A file))
- ((string-equal tag "b")
- (if file-B
- (error "This line has two `B' entries"))
- (setq file-B file))
- ((or (string-equal tag "anc") (string-equal tag "ancestor"))
- (if file-ancestor
- (error "This line has two `ancestor' entries"))
- (setq file-ancestor file))
- ((or (string-equal tag "out") (string-equal tag "output"))
- (if file-out
- (error "This line has two `output' entries"))
- (setq file-out file))
- (t
- (error "Unrecognized entry"))))
- ;; If the match on the entry pattern failed
- (error "Unparsable entry")))
- ;; Make sure that file-A and file-B are present
- (if (not (or (and file-A file-B) file-out))
- (error "Must have both `A' and `B' entries"))
- (if (not (or file-A file-B))
- (error "Must have `A' or `B' entry"))
- ;; Go to the beginning of the next line, so next execution will use
- ;; next line in buffer.
- (beginning-of-line 2)
- ;; Execute the correct command
- (cond
- ;; Merge of two files with ancestor
- ((and file-A file-B file-ancestor)
- (message "Merging %s and %s..." file-A file-B)
- (emerge-files-with-ancestor (not (not file-out)) file-A file-B
- file-ancestor file-out
- nil
- ;; When done, return to this buffer.
- (list
- (` (lambda ()
- (switch-to-buffer (, (current-buffer)))
- (message "Merge done."))))))
- ;; Merge of two files without ancestor
- ((and file-A file-B)
- (message "Merging %s and %s..." file-A file-B)
- (emerge-files (not (not file-out)) file-A file-B file-out
- nil
- ;; When done, return to this buffer.
- (list
- (` (lambda ()
- (switch-to-buffer (, (current-buffer)))
- (message "Merge done."))))))
- ;; There is an output file (or there would have been an error above),
- ;; but only one input file.
- ;; The file appears to have been deleted in one version; do nothing.
- ((and file-ancestor emerge-execute-line-deletions)
- (message "No action."))
- ;; The file should be copied from the version that contains it
- (t (let ((input-file (or file-A file-B)))
- (message "Copying...")
- (copy-file input-file file-out)
- (message "%s copied to %s." input-file file-out))))))
-
-;;; Sample function for creating information for emerge-execute-line
-
-(defvar emerge-merge-directories-filename-regexp "[^.]"
- "Regexp describing files to be processed by `emerge-merge-directories'.")
-
-;;;###autoload
-(defun emerge-merge-directories (a-dir b-dir ancestor-dir output-dir)
- (interactive
- (list
- (read-file-name "A directory: " nil nil 'confirm)
- (read-file-name "B directory: " nil nil 'confirm)
- (read-file-name "Ancestor directory (null for none): " nil nil 'confirm)
- (read-file-name "Output directory (null for none): " nil nil 'confirm)))
- ;; Check that we're not on a line
- (if (not (and (bolp) (eolp)))
- (error "There is text on this line"))
- ;; Turn null strings into nil to indicate directories not used.
- (if (and ancestor-dir (string-equal ancestor-dir ""))
- (setq ancestor-dir nil))
- (if (and output-dir (string-equal output-dir ""))
- (setq output-dir nil))
- ;; Canonicalize the directory names
- (setq a-dir (expand-file-name a-dir))
- (if (not (string-equal (substring a-dir -1) "/"))
- (setq a-dir (concat a-dir "/")))
- (setq b-dir (expand-file-name b-dir))
- (if (not (string-equal (substring b-dir -1) "/"))
- (setq b-dir (concat b-dir "/")))
- (if ancestor-dir
- (progn
- (setq ancestor-dir (expand-file-name ancestor-dir))
- (if (not (string-equal (substring ancestor-dir -1) "/"))
- (setq ancestor-dir (concat ancestor-dir "/")))))
- (if output-dir
- (progn
- (setq output-dir (expand-file-name output-dir))
- (if (not (string-equal (substring output-dir -1) "/"))
- (setq output-dir (concat output-dir "/")))))
- ;; Set the mark to where we start
- (push-mark)
- ;; Find out what files are in the directories.
- (let* ((a-dir-files
- (directory-files a-dir nil emerge-merge-directories-filename-regexp))
- (b-dir-files
- (directory-files b-dir nil emerge-merge-directories-filename-regexp))
- (ancestor-dir-files
- (and ancestor-dir
- (directory-files ancestor-dir nil
- emerge-merge-directories-filename-regexp)))
- (all-files (sort (nconc (copy-sequence a-dir-files)
- (copy-sequence b-dir-files)
- (copy-sequence ancestor-dir-files))
- (function string-lessp))))
- ;; Remove duplicates from all-files.
- (let ((p all-files))
- (while p
- (if (and (cdr p) (string-equal (car p) (car (cdr p))))
- (setcdr p (cdr (cdr p)))
- (setq p (cdr p)))))
- ;; Generate the control lines for the various files.
- (while all-files
- (let ((f (car all-files)))
- (setq all-files (cdr all-files))
- (if (and a-dir-files (string-equal (car a-dir-files) f))
- (progn
- (insert "A=" a-dir f "\t")
- (setq a-dir-files (cdr a-dir-files))))
- (if (and b-dir-files (string-equal (car b-dir-files) f))
- (progn
- (insert "B=" b-dir f "\t")
- (setq b-dir-files (cdr b-dir-files))))
- (if (and ancestor-dir-files (string-equal (car ancestor-dir-files) f))
- (progn
- (insert "ancestor=" ancestor-dir f "\t")
- (setq ancestor-dir-files (cdr ancestor-dir-files))))
- (if output-dir
- (insert "output=" output-dir f "\t"))
- (backward-delete-char 1)
- (insert "\n")))))
-
-;;; Common setup routines
-
-;; Set up the window configuration. If POS is given, set the points to
-;; the beginnings of the buffers.
-(defun emerge-setup-windows (buffer-A buffer-B merge-buffer &optional pos)
- ;; Make sure we are not in the minibuffer window when we try to delete
- ;; all other windows.
- (if (eq (selected-window) (minibuffer-window))
- (other-window 1))
- (delete-other-windows)
- (switch-to-buffer merge-buffer)
- (emerge-refresh-mode-line)
- (split-window-vertically)
- (split-window-horizontally)
- (switch-to-buffer buffer-A)
- (if pos
- (goto-char (point-min)))
- (other-window 1)
- (switch-to-buffer buffer-B)
- (if pos
- (goto-char (point-min)))
- (other-window 1)
- (if pos
- (goto-char (point-min)))
- ;; If diff/diff3 reports errors, display them rather than the merge buffer.
- (if (/= 0 (emerge-eval-in-buffer emerge-diff-error-buffer (buffer-size)))
- (progn
- (ding)
- (message "Errors found in diff/diff3 output. Merge buffer is %s."
- (buffer-name emerge-merge-buffer))
- (switch-to-buffer emerge-diff-error-buffer))))
-
-;; Set up the keymap in the merge buffer
-(defun emerge-set-keys ()
- ;; Set up fixed keymaps if necessary
- (if (not emerge-basic-keymap)
- (emerge-setup-fixed-keymaps))
- ;; Save the old local map
- (setq emerge-old-keymap (current-local-map))
- ;; Construct the edit keymap
- (setq emerge-edit-keymap (if emerge-old-keymap
- (copy-keymap emerge-old-keymap)
- (make-sparse-keymap)))
- ;; Install the Emerge commands
- (emerge-force-define-key emerge-edit-keymap emerge-command-prefix
- 'emerge-basic-keymap)
- (define-key emerge-edit-keymap [menu-bar] (make-sparse-keymap))
-
- ;; Create the additional menu bar items.
- (define-key emerge-edit-keymap [menu-bar options]
- (cons "Options" emerge-options-menu))
- (define-key emerge-edit-keymap [menu-bar merge]
- (cons "Merge" emerge-merge-menu))
- (define-key emerge-edit-keymap [menu-bar move]
- (cons "Move" emerge-move-menu))
-
- ;; Suppress write-file and save-buffer
- (substitute-key-definition 'write-file
- 'emerge-query-write-file
- emerge-edit-keymap)
- (substitute-key-definition 'save-buffer
- 'emerge-query-save-buffer
- emerge-edit-keymap)
- (substitute-key-definition 'write-file 'emerge-query-write-file
- emerge-edit-keymap (current-global-map))
- (substitute-key-definition 'save-buffer 'emerge-query-save-buffer
- emerge-edit-keymap (current-global-map))
- (use-local-map emerge-fast-keymap)
- (setq emerge-edit-mode nil)
- (setq emerge-fast-mode t))
-
-(defun emerge-remember-buffer-characteristics ()
- "Record certain properties of the buffers being merged.
-Must be called in the merge buffer. Remembers read-only, modified,
-auto-save, and saves them in buffer local variables. Sets the buffers
-read-only and turns off `auto-save-mode'.
-These characteristics are restored by `emerge-restore-buffer-characteristics'."
- ;; force auto-save, because we will turn off auto-saving in buffers for the
- ;; duration
- (do-auto-save)
- ;; remember and alter buffer characteristics
- (setq emerge-A-buffer-values
- (emerge-eval-in-buffer
- emerge-A-buffer
- (prog1
- (emerge-save-variables emerge-saved-variables)
- (emerge-restore-variables emerge-saved-variables
- emerge-merging-values))))
- (setq emerge-B-buffer-values
- (emerge-eval-in-buffer
- emerge-B-buffer
- (prog1
- (emerge-save-variables emerge-saved-variables)
- (emerge-restore-variables emerge-saved-variables
- emerge-merging-values)))))
-
-(defun emerge-restore-buffer-characteristics ()
- "Restores characteristics saved by `emerge-remember-buffer-characteristics'."
- (let ((A-values emerge-A-buffer-values)
- (B-values emerge-B-buffer-values))
- (emerge-eval-in-buffer emerge-A-buffer
- (emerge-restore-variables emerge-saved-variables
- A-values))
- (emerge-eval-in-buffer emerge-B-buffer
- (emerge-restore-variables emerge-saved-variables
- B-values))))
-
-;; Move to line DESIRED-LINE assuming we are at line CURRENT-LINE.
-;; Return DESIRED-LINE.
-(defun emerge-goto-line (desired-line current-line)
- (forward-line (- desired-line current-line))
- desired-line)
-
-(defun emerge-convert-diffs-to-markers (A-buffer
- B-buffer
- merge-buffer
- lineno-list)
- (let* (marker-list
- (A-point-min (emerge-eval-in-buffer A-buffer (point-min)))
- (offset (1- A-point-min))
- (B-point-min (emerge-eval-in-buffer B-buffer (point-min)))
- ;; Record current line number in each buffer
- ;; so we don't have to count from the beginning.
- (a-line 1)
- (b-line 1))
- (emerge-eval-in-buffer A-buffer (goto-char (point-min)))
- (emerge-eval-in-buffer B-buffer (goto-char (point-min)))
- (while lineno-list
- (let* ((list-element (car lineno-list))
- a-begin-marker
- a-end-marker
- b-begin-marker
- b-end-marker
- merge-begin-marker
- merge-end-marker
- (a-begin (aref list-element 0))
- (a-end (aref list-element 1))
- (b-begin (aref list-element 2))
- (b-end (aref list-element 3))
- (state (aref list-element 4)))
- ;; place markers at the appropriate places in the buffers
- (emerge-eval-in-buffer
- A-buffer
- (setq a-line (emerge-goto-line a-begin a-line))
- (setq a-begin-marker (point-marker))
- (setq a-line (emerge-goto-line a-end a-line))
- (setq a-end-marker (point-marker)))
- (emerge-eval-in-buffer
- B-buffer
- (setq b-line (emerge-goto-line b-begin b-line))
- (setq b-begin-marker (point-marker))
- (setq b-line (emerge-goto-line b-end b-line))
- (setq b-end-marker (point-marker)))
- (setq merge-begin-marker (set-marker
- (make-marker)
- (- (marker-position a-begin-marker)
- offset)
- merge-buffer))
- (setq merge-end-marker (set-marker
- (make-marker)
- (- (marker-position a-end-marker)
- offset)
- merge-buffer))
- ;; record all the markers for this difference
- (setq marker-list (cons (vector a-begin-marker a-end-marker
- b-begin-marker b-end-marker
- merge-begin-marker merge-end-marker
- state)
- marker-list)))
- (setq lineno-list (cdr lineno-list)))
- ;; convert the list of difference information into a vector for
- ;; fast access
- (setq emerge-difference-list (apply 'vector (nreverse marker-list)))))
-
-;; If we have an ancestor, select all B variants that we prefer
-(defun emerge-select-prefer-Bs ()
- (let ((n 0))
- (while (< n emerge-number-of-differences)
- (if (eq (aref (aref emerge-difference-list n) 6) 'prefer-B)
- (progn
- (emerge-unselect-and-select-difference n t)
- (emerge-select-B)
- (aset (aref emerge-difference-list n) 6 'prefer-B)))
- (setq n (1+ n))))
- (emerge-unselect-and-select-difference -1))
-
-;; Process the local-variables list at the end of the merged file, if
-;; requested.
-(defun emerge-handle-local-variables ()
- (if emerge-process-local-variables
- (condition-case err
- (hack-local-variables)
- (error (message "Local-variables error in merge buffer: %s"
- (prin1-to-string err))))))
-
-;;; Common exit routines
-
-(defun emerge-write-and-delete (file-out)
- ;; clear screen format
- (delete-other-windows)
- ;; delete A, B, and ancestor buffers, if they haven't been changed
- (if (not (buffer-modified-p emerge-A-buffer))
- (kill-buffer emerge-A-buffer))
- (if (not (buffer-modified-p emerge-B-buffer))
- (kill-buffer emerge-B-buffer))
- (if (and emerge-ancestor-buffer
- (not (buffer-modified-p emerge-ancestor-buffer)))
- (kill-buffer emerge-ancestor-buffer))
- ;; Write merge buffer to file
- (and file-out
- (write-file file-out)))
-
-;;; Commands
-
-(defun emerge-recenter (&optional arg)
- "Bring the highlighted region of all three merge buffers into view.
-This brings the buffers into view if they are in windows.
-With an argument, reestablish the default three-window display."
- (interactive "P")
- ;; If there is an argument, rebuild the window structure
- (if arg
- (emerge-setup-windows emerge-A-buffer emerge-B-buffer
- emerge-merge-buffer))
- ;; Redisplay whatever buffers are showing, if there is a selected difference
- (if (and (>= emerge-current-difference 0)
- (< emerge-current-difference emerge-number-of-differences))
- (let* ((merge-buffer emerge-merge-buffer)
- (buffer-A emerge-A-buffer)
- (buffer-B emerge-B-buffer)
- (window-A (get-buffer-window buffer-A 'visible))
- (window-B (get-buffer-window buffer-B 'visible))
- (merge-window (get-buffer-window merge-buffer))
- (diff-vector
- (aref emerge-difference-list emerge-current-difference)))
- (if window-A (progn
- (select-window window-A)
- (emerge-position-region
- (- (aref diff-vector 0)
- (1- emerge-before-flag-length))
- (+ (aref diff-vector 1)
- (1- emerge-after-flag-length))
- (1+ (aref diff-vector 0)))))
- (if window-B (progn
- (select-window window-B)
- (emerge-position-region
- (- (aref diff-vector 2)
- (1- emerge-before-flag-length))
- (+ (aref diff-vector 3)
- (1- emerge-after-flag-length))
- (1+ (aref diff-vector 2)))))
- (if merge-window (progn
- (select-window merge-window)
- (emerge-position-region
- (- (aref diff-vector 4)
- (1- emerge-before-flag-length))
- (+ (aref diff-vector 5)
- (1- emerge-after-flag-length))
- (1+ (aref diff-vector 4))))))))
-
-;;; Window scrolling operations
-;; These operations are designed to scroll all three windows the same amount,
-;; so as to keep the text in them aligned.
-
-;; Perform some operation on all three windows (if they are showing).
-;; Catches all errors on the operation in the A and B windows, but not
-;; in the merge window. Usually, errors come from scrolling off the
-;; beginning or end of the buffer, and this gives a nice error message:
-;; End of buffer is reported in the merge buffer, but if the scroll was
-;; possible in the A or B windows, it is performed there before the error
-;; is reported.
-(defun emerge-operate-on-windows (operation arg)
- (let* ((merge-buffer emerge-merge-buffer)
- (buffer-A emerge-A-buffer)
- (buffer-B emerge-B-buffer)
- (window-A (get-buffer-window buffer-A 'visible))
- (window-B (get-buffer-window buffer-B 'visible))
- (merge-window (get-buffer-window merge-buffer)))
- (if window-A (progn
- (select-window window-A)
- (condition-case nil
- (funcall operation arg)
- (error))))
- (if window-B (progn
- (select-window window-B)
- (condition-case nil
- (funcall operation arg)
- (error))))
- (if merge-window (progn
- (select-window merge-window)
- (funcall operation arg)))))
-
-(defun emerge-scroll-up (&optional arg)
- "Scroll up all three merge buffers, if they are in windows.
-With argument N, scroll N lines; otherwise scroll by nearly
-the height of the merge window.
-`C-u -' alone as argument scrolls half the height of the merge window."
- (interactive "P")
- (emerge-operate-on-windows
- 'scroll-up
- ;; calculate argument to scroll-up
- ;; if there is an explicit argument
- (if (and arg (not (equal arg '-)))
- ;; use it
- (prefix-numeric-value arg)
- ;; if not, see if we can determine a default amount (the window height)
- (let ((merge-window (get-buffer-window emerge-merge-buffer)))
- (if (null merge-window)
- ;; no window, use nil
- nil
- (let ((default-amount
- (- (window-height merge-window) 1 next-screen-context-lines)))
- ;; the window was found
- (if arg
- ;; C-u as argument means half of default amount
- (/ default-amount 2)
- ;; no argument means default amount
- default-amount)))))))
-
-(defun emerge-scroll-down (&optional arg)
- "Scroll down all three merge buffers, if they are in windows.
-With argument N, scroll N lines; otherwise scroll by nearly
-the height of the merge window.
-`C-u -' alone as argument scrolls half the height of the merge window."
- (interactive "P")
- (emerge-operate-on-windows
- 'scroll-down
- ;; calculate argument to scroll-down
- ;; if there is an explicit argument
- (if (and arg (not (equal arg '-)))
- ;; use it
- (prefix-numeric-value arg)
- ;; if not, see if we can determine a default amount (the window height)
- (let ((merge-window (get-buffer-window emerge-merge-buffer)))
- (if (null merge-window)
- ;; no window, use nil
- nil
- (let ((default-amount
- (- (window-height merge-window) 1 next-screen-context-lines)))
- ;; the window was found
- (if arg
- ;; C-u as argument means half of default amount
- (/ default-amount 2)
- ;; no argument means default amount
- default-amount)))))))
-
-(defun emerge-scroll-left (&optional arg)
- "Scroll left all three merge buffers, if they are in windows.
-If an argument is given, that is how many columns are scrolled, else nearly
-the width of the A and B windows. `C-u -' alone as argument scrolls half the
-width of the A and B windows."
- (interactive "P")
- (emerge-operate-on-windows
- 'scroll-left
- ;; calculate argument to scroll-left
- ;; if there is an explicit argument
- (if (and arg (not (equal arg '-)))
- ;; use it
- (prefix-numeric-value arg)
- ;; if not, see if we can determine a default amount
- ;; (half the window width)
- (let ((merge-window (get-buffer-window emerge-merge-buffer)))
- (if (null merge-window)
- ;; no window, use nil
- nil
- (let ((default-amount
- (- (/ (window-width merge-window) 2) 3)))
- ;; the window was found
- (if arg
- ;; C-u as argument means half of default amount
- (/ default-amount 2)
- ;; no argument means default amount
- default-amount)))))))
-
-(defun emerge-scroll-right (&optional arg)
- "Scroll right all three merge buffers, if they are in windows.
-If an argument is given, that is how many columns are scrolled, else nearly
-the width of the A and B windows. `C-u -' alone as argument scrolls half the
-width of the A and B windows."
- (interactive "P")
- (emerge-operate-on-windows
- 'scroll-right
- ;; calculate argument to scroll-right
- ;; if there is an explicit argument
- (if (and arg (not (equal arg '-)))
- ;; use it
- (prefix-numeric-value arg)
- ;; if not, see if we can determine a default amount
- ;; (half the window width)
- (let ((merge-window (get-buffer-window emerge-merge-buffer)))
- (if (null merge-window)
- ;; no window, use nil
- nil
- (let ((default-amount
- (- (/ (window-width merge-window) 2) 3)))
- ;; the window was found
- (if arg
- ;; C-u as argument means half of default amount
- (/ default-amount 2)
- ;; no argument means default amount
- default-amount)))))))
-
-(defun emerge-scroll-reset ()
- "Reset horizontal scrolling in Emerge.
-This resets the horizontal scrolling of all three merge buffers
-to the left margin, if they are in windows."
- (interactive)
- (emerge-operate-on-windows
- (function (lambda (x) (set-window-hscroll (selected-window) 0)))
- nil))
-
-;; Attempt to show the region nicely.
-;; If there are min-lines lines above and below the region, then don't do
-;; anything.
-;; If not, recenter the region to make it so.
-;; If that isn't possible, remove context lines balancedly from top and bottom
-;; so the entire region shows.
-;; If that isn't possible, show the top of the region.
-;; BEG must be at the beginning of a line.
-(defun emerge-position-region (beg end pos)
- ;; First test whether the entire region is visible with
- ;; emerge-min-visible-lines above and below it
- (if (not (and (<= (progn
- (move-to-window-line emerge-min-visible-lines)
- (point))
- beg)
- (<= end (progn
- (move-to-window-line
- (- (1+ emerge-min-visible-lines)))
- (point)))))
- ;; We failed that test, see if it fits at all
- ;; Meanwhile positioning it correctly in case it doesn't fit
- (progn
- (set-window-start (selected-window) beg)
- (if (pos-visible-in-window-p end)
- ;; Determine the number of lines that the region occupies
- (let ((lines 0))
- (while (> end (progn
- (move-to-window-line lines)
- (point)))
- (setq lines (1+ lines)))
- ;; And position the beginning on the right line
- (goto-char beg)
- (recenter (/ (1+ (- (1- (window-height (selected-window)))
- lines))
- 2))))))
- (goto-char pos))
-
-(defun emerge-next-difference ()
- "Advance to the next difference."
- (interactive)
- (if (< emerge-current-difference emerge-number-of-differences)
- (let ((n (1+ emerge-current-difference)))
- (while (and emerge-skip-prefers
- (< n emerge-number-of-differences)
- (memq (aref (aref emerge-difference-list n) 6)
- '(prefer-A prefer-B)))
- (setq n (1+ n)))
- (let ((buffer-read-only nil))
- (emerge-unselect-and-select-difference n)))
- (error "At end")))
-
-(defun emerge-previous-difference ()
- "Go to the previous difference."
- (interactive)
- (if (> emerge-current-difference -1)
- (let ((n (1- emerge-current-difference)))
- (while (and emerge-skip-prefers
- (> n -1)
- (memq (aref (aref emerge-difference-list n) 6)
- '(prefer-A prefer-B)))
- (setq n (1- n)))
- (let ((buffer-read-only nil))
- (emerge-unselect-and-select-difference n)))
- (error "At beginning")))
-
-(defun emerge-jump-to-difference (difference-number)
- "Go to the N-th difference."
- (interactive "p")
- (let ((buffer-read-only nil))
- (setq difference-number (1- difference-number))
- (if (and (>= difference-number -1)
- (< difference-number (1+ emerge-number-of-differences)))
- (emerge-unselect-and-select-difference difference-number)
- (error "Bad difference number"))))
-
-(defun emerge-abort ()
- "Abort the Emerge session."
- (interactive)
- (emerge-quit t))
-
-(defun emerge-quit (arg)
- "Finish the Emerge session and exit Emerge.
-Prefix argument means to abort rather than successfully finish.
-The difference depends on how the merge was started,
-but usually means to not write over one of the original files, or to signal
-to some process which invoked Emerge a failure code.
-
-Unselects the selected difference, if any, restores the read-only and modified
-flags of the merged file buffers, restores the local keymap of the merge
-buffer, and sets off various emerge flags. Using Emerge commands in this
-buffer after this will cause serious problems."
- (interactive "P")
- (if (prog1
- (y-or-n-p
- (if (not arg)
- "Do you really want to successfully finish this merge? "
- "Do you really want to abort this merge? "))
- (message ""))
- (emerge-really-quit arg)))
-
-;; Perform the quit operations.
-(defun emerge-really-quit (arg)
- (setq buffer-read-only nil)
- (emerge-unselect-and-select-difference -1)
- (emerge-restore-buffer-characteristics)
- ;; null out the difference markers so they don't slow down future editing
- ;; operations
- (mapcar (function (lambda (d)
- (set-marker (aref d 0) nil)
- (set-marker (aref d 1) nil)
- (set-marker (aref d 2) nil)
- (set-marker (aref d 3) nil)
- (set-marker (aref d 4) nil)
- (set-marker (aref d 5) nil)))
- emerge-difference-list)
- ;; allow them to be garbage collected
- (setq emerge-difference-list nil)
- ;; restore the local map
- (use-local-map emerge-old-keymap)
- ;; turn off all the emerge modes
- (setq emerge-mode nil)
- (setq emerge-fast-mode nil)
- (setq emerge-edit-mode nil)
- (setq emerge-auto-advance nil)
- (setq emerge-skip-prefers nil)
- ;; restore mode line
- (kill-local-variable 'mode-line-buffer-identification)
- (let ((emerge-prefix-argument arg))
- (run-hooks 'emerge-quit-hook)))
-
-(defun emerge-select-A (&optional force)
- "Select the A variant of this difference.
-Refuses to function if this difference has been edited, i.e., if it
-is neither the A nor the B variant.
-A prefix argument forces the variant to be selected
-even if the difference has been edited."
- (interactive "P")
- (let ((operate
- (function (lambda ()
- (emerge-select-A-edit merge-begin merge-end A-begin A-end)
- (if emerge-auto-advance
- (emerge-next-difference)))))
- (operate-no-change
- (function (lambda ()
- (if emerge-auto-advance
- (emerge-next-difference))))))
- (emerge-select-version force operate-no-change operate operate)))
-
-;; Actually select the A variant
-(defun emerge-select-A-edit (merge-begin merge-end A-begin A-end)
- (emerge-eval-in-buffer
- emerge-merge-buffer
- (delete-region merge-begin merge-end)
- (goto-char merge-begin)
- (insert-buffer-substring emerge-A-buffer A-begin A-end)
- (goto-char merge-begin)
- (aset diff-vector 6 'A)
- (emerge-refresh-mode-line)))
-
-(defun emerge-select-B (&optional force)
- "Select the B variant of this difference.
-Refuses to function if this difference has been edited, i.e., if it
-is neither the A nor the B variant.
-A prefix argument forces the variant to be selected
-even if the difference has been edited."
- (interactive "P")
- (let ((operate
- (function (lambda ()
- (emerge-select-B-edit merge-begin merge-end B-begin B-end)
- (if emerge-auto-advance
- (emerge-next-difference)))))
- (operate-no-change
- (function (lambda ()
- (if emerge-auto-advance
- (emerge-next-difference))))))
- (emerge-select-version force operate operate-no-change operate)))
-
-;; Actually select the B variant
-(defun emerge-select-B-edit (merge-begin merge-end B-begin B-end)
- (emerge-eval-in-buffer
- emerge-merge-buffer
- (delete-region merge-begin merge-end)
- (goto-char merge-begin)
- (insert-buffer-substring emerge-B-buffer B-begin B-end)
- (goto-char merge-begin)
- (aset diff-vector 6 'B)
- (emerge-refresh-mode-line)))
-
-(defun emerge-default-A ()
- "Make the A variant the default from here down.
-This selects the A variant for all differences from here down in the buffer
-which are still defaulted, i.e., which the user has not selected and for
-which there is no preference."
- (interactive)
- (let ((buffer-read-only nil))
- (let ((selected-difference emerge-current-difference)
- (n (max emerge-current-difference 0)))
- (while (< n emerge-number-of-differences)
- (let ((diff-vector (aref emerge-difference-list n)))
- (if (eq (aref diff-vector 6) 'default-B)
- (progn
- (emerge-unselect-and-select-difference n t)
- (emerge-select-A)
- (aset diff-vector 6 'default-A))))
- (setq n (1+ n))
- (if (zerop (% n 10))
- (message "Setting default to A...%d" n)))
- (emerge-unselect-and-select-difference selected-difference)))
- (message "Default choice is now A"))
-
-(defun emerge-default-B ()
- "Make the B variant the default from here down.
-This selects the B variant for all differences from here down in the buffer
-which are still defaulted, i.e., which the user has not selected and for
-which there is no preference."
- (interactive)
- (let ((buffer-read-only nil))
- (let ((selected-difference emerge-current-difference)
- (n (max emerge-current-difference 0)))
- (while (< n emerge-number-of-differences)
- (let ((diff-vector (aref emerge-difference-list n)))
- (if (eq (aref diff-vector 6) 'default-A)
- (progn
- (emerge-unselect-and-select-difference n t)
- (emerge-select-B)
- (aset diff-vector 6 'default-B))))
- (setq n (1+ n))
- (if (zerop (% n 10))
- (message "Setting default to B...%d" n)))
- (emerge-unselect-and-select-difference selected-difference)))
- (message "Default choice is now B"))
-
-(defun emerge-fast-mode ()
- "Set fast mode, for Emerge.
-In this mode ordinary Emacs commands are disabled, and Emerge commands
-need not be prefixed with \\<emerge-fast-keymap>\\[emerge-basic-keymap]."
- (interactive)
- (setq buffer-read-only t)
- (use-local-map emerge-fast-keymap)
- (setq emerge-mode t)
- (setq emerge-fast-mode t)
- (setq emerge-edit-mode nil)
- (message "Fast mode set")
- (force-mode-line-update))
-
-(defun emerge-edit-mode ()
- "Set edit mode, for Emerge.
-In this mode ordinary Emacs commands are available, and Emerge commands
-must be prefixed with \\<emerge-fast-keymap>\\[emerge-basic-keymap]."
- (interactive)
- (setq buffer-read-only nil)
- (use-local-map emerge-edit-keymap)
- (setq emerge-mode t)
- (setq emerge-fast-mode nil)
- (setq emerge-edit-mode t)
- (message "Edit mode set")
- (force-mode-line-update))
-
-(defun emerge-auto-advance (arg)
- "Toggle Auto-Advance mode, for Emerge.
-This mode causes `emerge-select-A' and `emerge-select-B' to automatically
-advance to the next difference.
-With a positive argument, turn on Auto-Advance mode.
-With a negative argument, turn off Auto-Advance mode."
- (interactive "P")
- (setq emerge-auto-advance (if (null arg)
- (not emerge-auto-advance)
- (> (prefix-numeric-value arg) 0)))
- (message (if emerge-auto-advance
- "Auto-advance set"
- "Auto-advance cleared"))
- (force-mode-line-update))
-
-(defun emerge-skip-prefers (arg)
- "Toggle Skip-Prefers mode, for Emerge.
-This mode causes `emerge-next-difference' and `emerge-previous-difference'
-to automatically skip over differences for which there is a preference.
-With a positive argument, turn on Skip-Prefers mode.
-With a negative argument, turn off Skip-Prefers mode."
- (interactive "P")
- (setq emerge-skip-prefers (if (null arg)
- (not emerge-skip-prefers)
- (> (prefix-numeric-value arg) 0)))
- (message (if emerge-skip-prefers
- "Skip-prefers set"
- "Skip-prefers cleared"))
- (force-mode-line-update))
-
-(defun emerge-copy-as-kill-A ()
- "Put the A variant of this difference in the kill ring."
- (interactive)
- (emerge-validate-difference)
- (let* ((diff-vector
- (aref emerge-difference-list emerge-current-difference))
- (A-begin (1+ (aref diff-vector 0)))
- (A-end (1- (aref diff-vector 1)))
- ;; so further kills don't append
- this-command)
- (save-excursion
- (set-buffer emerge-A-buffer)
- (copy-region-as-kill A-begin A-end))))
-
-(defun emerge-copy-as-kill-B ()
- "Put the B variant of this difference in the kill ring."
- (interactive)
- (emerge-validate-difference)
- (let* ((diff-vector
- (aref emerge-difference-list emerge-current-difference))
- (B-begin (1+ (aref diff-vector 2)))
- (B-end (1- (aref diff-vector 3)))
- ;; so further kills don't append
- this-command)
- (save-excursion
- (set-buffer emerge-B-buffer)
- (copy-region-as-kill B-begin B-end))))
-
-(defun emerge-insert-A (arg)
- "Insert the A variant of this difference at the point.
-Leaves point after text, mark before.
-With prefix argument, puts point before, mark after."
- (interactive "P")
- (emerge-validate-difference)
- (let* ((diff-vector
- (aref emerge-difference-list emerge-current-difference))
- (A-begin (1+ (aref diff-vector 0)))
- (A-end (1- (aref diff-vector 1)))
- (opoint (point))
- (buffer-read-only nil))
- (insert-buffer-substring emerge-A-buffer A-begin A-end)
- (if (not arg)
- (set-mark opoint)
- (set-mark (point))
- (goto-char opoint))))
-
-(defun emerge-insert-B (arg)
- "Insert the B variant of this difference at the point.
-Leaves point after text, mark before.
-With prefix argument, puts point before, mark after."
- (interactive "P")
- (emerge-validate-difference)
- (let* ((diff-vector
- (aref emerge-difference-list emerge-current-difference))
- (B-begin (1+ (aref diff-vector 2)))
- (B-end (1- (aref diff-vector 3)))
- (opoint (point))
- (buffer-read-only nil))
- (insert-buffer-substring emerge-B-buffer B-begin B-end)
- (if (not arg)
- (set-mark opoint)
- (set-mark (point))
- (goto-char opoint))))
-
-(defun emerge-mark-difference (arg)
- "Leaves the point before this difference and the mark after it.
-With prefix argument, puts mark before, point after."
- (interactive "P")
- (emerge-validate-difference)
- (let* ((diff-vector
- (aref emerge-difference-list emerge-current-difference))
- (merge-begin (1+ (aref diff-vector 4)))
- (merge-end (1- (aref diff-vector 5))))
- (if (not arg)
- (progn
- (goto-char merge-begin)
- (set-mark merge-end))
- (goto-char merge-end)
- (set-mark merge-begin))))
-
-(defun emerge-file-names ()
- "Show the names of the buffers or files being operated on by Emerge.
-Use C-u l to reset the windows afterward."
- (interactive)
- (delete-other-windows)
- (let ((temp-buffer-show-function
- (function (lambda (buf)
- (split-window-vertically)
- (switch-to-buffer buf)
- (other-window 1)))))
- (with-output-to-temp-buffer "*Help*"
- (emerge-eval-in-buffer emerge-A-buffer
- (if buffer-file-name
- (progn
- (princ "File A is: ")
- (princ buffer-file-name))
- (progn
- (princ "Buffer A is: ")
- (princ (buffer-name))))
- (princ "\n"))
- (emerge-eval-in-buffer emerge-B-buffer
- (if buffer-file-name
- (progn
- (princ "File B is: ")
- (princ buffer-file-name))
- (progn
- (princ "Buffer B is: ")
- (princ (buffer-name))))
- (princ "\n"))
- (if emerge-ancestor-buffer
- (emerge-eval-in-buffer emerge-ancestor-buffer
- (if buffer-file-name
- (progn
- (princ "Ancestor file is: ")
- (princ buffer-file-name))
- (progn
- (princ "Ancestor buffer is: ")
- (princ (buffer-name))))
- (princ "\n")))
- (princ emerge-output-description)
- (save-excursion
- (set-buffer standard-output)
- (help-mode)))))
-
-(defun emerge-join-differences (arg)
- "Join the selected difference with the following one.
-With a prefix argument, join with the preceding one."
- (interactive "P")
- (let ((n emerge-current-difference))
- ;; adjust n to be first difference to join
- (if arg
- (setq n (1- n)))
- ;; n and n+1 are the differences to join
- ;; check that they are both differences
- (if (or (< n 0) (>= n (1- emerge-number-of-differences)))
- (error "Incorrect differences to join"))
- ;; remove the flags
- (emerge-unselect-difference emerge-current-difference)
- ;; decrement total number of differences
- (setq emerge-number-of-differences (1- emerge-number-of-differences))
- ;; build new differences vector
- (let ((i 0)
- (new-differences (make-vector emerge-number-of-differences nil)))
- (while (< i emerge-number-of-differences)
- (aset new-differences i
- (cond
- ((< i n) (aref emerge-difference-list i))
- ((> i n) (aref emerge-difference-list (1+ i)))
- (t (let ((prev (aref emerge-difference-list i))
- (next (aref emerge-difference-list (1+ i))))
- (vector (aref prev 0)
- (aref next 1)
- (aref prev 2)
- (aref next 3)
- (aref prev 4)
- (aref next 5)
- (let ((ps (aref prev 6))
- (ns (aref next 6)))
- (cond
- ((eq ps ns)
- ps)
- ((and (or (eq ps 'B) (eq ps 'prefer-B))
- (or (eq ns 'B) (eq ns 'prefer-B)))
- 'B)
- (t 'A))))))))
- (setq i (1+ i)))
- (setq emerge-difference-list new-differences))
- ;; set the current difference correctly
- (setq emerge-current-difference n)
- ;; fix the mode line
- (emerge-refresh-mode-line)
- ;; reinsert the flags
- (emerge-select-difference emerge-current-difference)
- (emerge-recenter)))
-
-(defun emerge-split-difference ()
- "Split the current difference where the points are in the three windows."
- (interactive)
- (let ((n emerge-current-difference))
- ;; check that this is a valid difference
- (emerge-validate-difference)
- ;; get the point values and old difference
- (let ((A-point (emerge-eval-in-buffer emerge-A-buffer
- (point-marker)))
- (B-point (emerge-eval-in-buffer emerge-B-buffer
- (point-marker)))
- (merge-point (point-marker))
- (old-diff (aref emerge-difference-list n)))
- ;; check location of the points, give error if they aren't in the
- ;; differences
- (if (or (< A-point (aref old-diff 0))
- (> A-point (aref old-diff 1)))
- (error "Point outside of difference in A buffer"))
- (if (or (< B-point (aref old-diff 2))
- (> B-point (aref old-diff 3)))
- (error "Point outside of difference in B buffer"))
- (if (or (< merge-point (aref old-diff 4))
- (> merge-point (aref old-diff 5)))
- (error "Point outside of difference in merge buffer"))
- ;; remove the flags
- (emerge-unselect-difference emerge-current-difference)
- ;; increment total number of differences
- (setq emerge-number-of-differences (1+ emerge-number-of-differences))
- ;; build new differences vector
- (let ((i 0)
- (new-differences (make-vector emerge-number-of-differences nil)))
- (while (< i emerge-number-of-differences)
- (aset new-differences i
- (cond
- ((< i n)
- (aref emerge-difference-list i))
- ((> i (1+ n))
- (aref emerge-difference-list (1- i)))
- ((= i n)
- (vector (aref old-diff 0)
- A-point
- (aref old-diff 2)
- B-point
- (aref old-diff 4)
- merge-point
- (aref old-diff 6)))
- (t
- (vector (copy-marker A-point)
- (aref old-diff 1)
- (copy-marker B-point)
- (aref old-diff 3)
- (copy-marker merge-point)
- (aref old-diff 5)
- (aref old-diff 6)))))
- (setq i (1+ i)))
- (setq emerge-difference-list new-differences))
- ;; set the current difference correctly
- (setq emerge-current-difference n)
- ;; fix the mode line
- (emerge-refresh-mode-line)
- ;; reinsert the flags
- (emerge-select-difference emerge-current-difference)
- (emerge-recenter))))
-
-(defun emerge-trim-difference ()
- "Trim lines off top and bottom of difference that are the same.
-If lines are the same in both the A and the B versions, strip them off.
-\(This can happen when the A and B versions have common lines that the
-ancestor version does not share.)"
- (interactive)
- ;; make sure we are in a real difference
- (emerge-validate-difference)
- ;; remove the flags
- (emerge-unselect-difference emerge-current-difference)
- (let* ((diff (aref emerge-difference-list emerge-current-difference))
- (top-a (marker-position (aref diff 0)))
- (bottom-a (marker-position (aref diff 1)))
- (top-b (marker-position (aref diff 2)))
- (bottom-b (marker-position (aref diff 3)))
- (top-m (marker-position (aref diff 4)))
- (bottom-m (marker-position (aref diff 5)))
- size success sa sb sm)
- ;; move down the tops of the difference regions as much as possible
- ;; 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 (- bottom-a top-a) (- bottom-b top-b)
- (- bottom-m top-m)))
- (setq sa (emerge-eval-in-buffer emerge-A-buffer
- (buffer-substring top-a
- (+ size top-a))))
- (setq sb (emerge-eval-in-buffer emerge-B-buffer
- (buffer-substring top-b
- (+ size top-b))))
- (setq sm (buffer-substring top-m (+ size top-m)))
- (setq success (and (> size 0) (equal sa sb) (equal sb sm)))
- (if success
- (setq top-a (+ top-a size)
- top-b (+ top-b size)
- top-m (+ top-m size))))
- (setq size (/ size 2)))
- ;; move up the bottoms of the difference regions as much as possible
- ;; 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 (- bottom-a top-a) (- bottom-b top-b)
- (- bottom-m top-m)))
- (setq sa (emerge-eval-in-buffer emerge-A-buffer
- (buffer-substring (- bottom-a size)
- bottom-a)))
- (setq sb (emerge-eval-in-buffer emerge-B-buffer
- (buffer-substring (- bottom-b size)
- bottom-b)))
- (setq sm (buffer-substring (- bottom-m size) bottom-m))
- (setq success (and (> size 0) (equal sa sb) (equal sb sm)))
- (if success
- (setq bottom-a (- bottom-a size)
- bottom-b (- bottom-b size)
- bottom-m (- bottom-m size))))
- (setq size (/ size 2)))
- ;; {top,bottom}-{a,b,m} are now set at the new beginnings and ends
- ;; of the difference regions. Move them to the beginning of lines, as
- ;; appropriate.
- (emerge-eval-in-buffer emerge-A-buffer
- (goto-char top-a)
- (beginning-of-line)
- (aset diff 0 (point-marker))
- (goto-char bottom-a)
- (beginning-of-line 2)
- (aset diff 1 (point-marker)))
- (emerge-eval-in-buffer emerge-B-buffer
- (goto-char top-b)
- (beginning-of-line)
- (aset diff 2 (point-marker))
- (goto-char bottom-b)
- (beginning-of-line 2)
- (aset diff 3 (point-marker)))
- (goto-char top-m)
- (beginning-of-line)
- (aset diff 4 (point-marker))
- (goto-char bottom-m)
- (beginning-of-line 2)
- (aset diff 5 (point-marker))
- ;; put the flags back in, recenter the display
- (emerge-select-difference emerge-current-difference)
- (emerge-recenter)))
-
-(defun emerge-find-difference (arg)
- "Find the difference containing the current position of the point.
-If there is no containing difference and the prefix argument is positive,
-it finds the nearest following difference. A negative prefix argument finds
-the nearest previous difference."
- (interactive "P")
- (cond ((eq (current-buffer) emerge-A-buffer)
- (emerge-find-difference-A arg))
- ((eq (current-buffer) emerge-B-buffer)
- (emerge-find-difference-B arg))
- (t (emerge-find-difference-merge arg))))
-
-(defun emerge-find-difference-merge (arg)
- "Find the difference containing point, in the merge buffer.
-If there is no containing difference and the prefix argument is positive,
-it finds the nearest following difference. A negative prefix argument finds
-the nearest previous difference."
- (interactive "P")
- ;; search for the point in the merge buffer, using the markers
- ;; for the beginning and end of the differences in the merge buffer
- (emerge-find-difference1 arg (point) 4 5))
-
-(defun emerge-find-difference-A (arg)
- "Find the difference containing point, in the A buffer.
-This command must be executed in the merge buffer.
-If there is no containing difference and the prefix argument is positive,
-it finds the nearest following difference. A negative prefix argument finds
-the nearest previous difference."
- (interactive "P")
- ;; search for the point in the A buffer, using the markers
- ;; for the beginning and end of the differences in the A buffer
- (emerge-find-difference1 arg
- (emerge-eval-in-buffer emerge-A-buffer (point))
- 0 1))
-
-(defun emerge-find-difference-B (arg)
- "Find the difference containing point, in the B buffer.
-This command must be executed in the merge buffer.
-If there is no containing difference and the prefix argument is positive,
-it finds the nearest following difference. A negative prefix argument finds
-the nearest previous difference."
- (interactive "P")
- ;; search for the point in the B buffer, using the markers
- ;; for the beginning and end of the differences in the B buffer
- (emerge-find-difference1 arg
- (emerge-eval-in-buffer emerge-B-buffer (point))
- 2 3))
-
-(defun emerge-find-difference1 (arg location begin end)
- (let* ((index
- ;; find first difference containing or after the current position
- (catch 'search
- (let ((n 0))
- (while (< n emerge-number-of-differences)
- (let ((diff-vector (aref emerge-difference-list n)))
- (if (<= location (marker-position (aref diff-vector end)))
- (throw 'search n)))
- (setq n (1+ n))))
- emerge-number-of-differences))
- (contains
- ;; whether the found difference contains the current position
- (and (< index emerge-number-of-differences)
- (<= (marker-position (aref (aref emerge-difference-list index)
- begin))
- location)))
- (arg-value
- ;; numeric value of prefix argument
- (prefix-numeric-value arg)))
- (emerge-unselect-and-select-difference
- (cond
- ;; if the point is in a difference, select it
- (contains index)
- ;; if the arg is nil and the point is not in a difference, error
- ((null arg) (error "No difference contains point"))
- ;; if the arg is positive, select the following difference
- ((> arg-value 0)
- (if (< index emerge-number-of-differences)
- index
- (error "No difference contains or follows point")))
- ;; if the arg is negative, select the preceding difference
- (t
- (if (> index 0)
- (1- index)
- (error "No difference contains or precedes point")))))))
-
-(defun emerge-line-numbers ()
- "Display the current line numbers.
-This function displays the line numbers of the points in the A, B, and
-merge buffers."
- (interactive)
- (let* ((valid-diff
- (and (>= emerge-current-difference 0)
- (< emerge-current-difference emerge-number-of-differences)))
- (diff (and valid-diff
- (aref emerge-difference-list emerge-current-difference)))
- (merge-line (emerge-line-number-in-buf 4 5))
- (A-line (emerge-eval-in-buffer emerge-A-buffer
- (emerge-line-number-in-buf 0 1)))
- (B-line (emerge-eval-in-buffer emerge-B-buffer
- (emerge-line-number-in-buf 2 3))))
- (message "At lines: merge = %d, A = %d, B = %d"
- merge-line A-line B-line)))
-
-(defun emerge-line-number-in-buf (begin-marker end-marker)
- (let (temp)
- (setq temp (save-excursion
- (beginning-of-line)
- (1+ (count-lines 1 (point)))))
- (if valid-diff
- (progn
- (if (> (point) (aref diff begin-marker))
- (setq temp (- temp emerge-before-flag-lines)))
- (if (> (point) (aref diff end-marker))
- (setq temp (- temp emerge-after-flag-lines)))))
- temp))
-
-(defun emerge-set-combine-template (string &optional localize)
- "Set `emerge-combine-versions-template' to STRING.
-This value controls how `emerge-combine-versions' combines the two versions.
-With prefix argument, `emerge-combine-versions-template' is made local to this
-merge buffer. Localization is permanent for any particular merge buffer."
- (interactive "s\nP")
- (if localize
- (make-local-variable 'emerge-combine-versions-template))
- (setq emerge-combine-versions-template string)
- (message
- (if (assq 'emerge-combine-versions-template (buffer-local-variables))
- "emerge-set-combine-versions-template set locally"
- "emerge-set-combine-versions-template set")))
-
-(defun emerge-set-combine-versions-template (start end &optional localize)
- "Copy region into `emerge-combine-versions-template'.
-This controls how `emerge-combine-versions' will combine the two versions.
-With prefix argument, `emerge-combine-versions-template' is made local to this
-merge buffer. Localization is permanent for any particular merge buffer."
- (interactive "r\nP")
- (if localize
- (make-local-variable 'emerge-combine-versions-template))
- (setq emerge-combine-versions-template (buffer-substring start end))
- (message
- (if (assq 'emerge-combine-versions-template (buffer-local-variables))
- "emerge-set-combine-versions-template set locally."
- "emerge-set-combine-versions-template set.")))
-
-(defun emerge-combine-versions (&optional force)
- "Combine versions using the template in `emerge-combine-versions-template'.
-Refuses to function if this difference has been edited, i.e., if it is
-neither the A nor the B variant.
-An argument forces the variant to be selected even if the difference has
-been edited."
- (interactive "P")
- (emerge-combine-versions-internal emerge-combine-versions-template force))
-
-(defun emerge-combine-versions-register (char &optional force)
- "Combine the two versions using the template in register REG.
-See documentation of the variable `emerge-combine-versions-template'
-for how the template is interpreted.
-Refuses to function if this difference has been edited, i.e., if it is
-neither the A nor the B variant.
-An argument forces the variant to be selected even if the difference has
-been edited."
- (interactive "cRegister containing template: \nP")
- (let ((template (get-register char)))
- (if (not (stringp template))
- (error "Register does not contain text"))
- (emerge-combine-versions-internal template force)))
-
-(defun emerge-combine-versions-internal (template force)
- (let ((operate
- (function (lambda ()
- (emerge-combine-versions-edit merge-begin merge-end
- A-begin A-end B-begin B-end)
- (if emerge-auto-advance
- (emerge-next-difference))))))
- (emerge-select-version force operate operate operate)))
-
-(defun emerge-combine-versions-edit (merge-begin merge-end
- A-begin A-end B-begin B-end)
- (emerge-eval-in-buffer
- emerge-merge-buffer
- (delete-region merge-begin merge-end)
- (goto-char merge-begin)
- (let ((i 0))
- (while (< i (length template))
- (let ((c (aref template i)))
- (if (= c ?%)
- (progn
- (setq i (1+ i))
- (setq c
- (condition-case nil
- (aref template i)
- (error ?%)))
- (cond ((= c ?a)
- (insert-buffer-substring emerge-A-buffer A-begin A-end))
- ((= c ?b)
- (insert-buffer-substring emerge-B-buffer B-begin B-end))
- ((= c ?%)
- (insert ?%))
- (t
- (insert c))))
- (insert c)))
- (setq i (1+ i))))
- (goto-char merge-begin)
- (aset diff-vector 6 'combined)
- (emerge-refresh-mode-line)))
-
-(defun emerge-set-merge-mode (mode)
- "Set the major mode in a merge buffer.
-Overrides any change that the mode might make to the mode line or local
-keymap. Leaves merge in fast mode."
- (interactive
- (list (intern (completing-read "New major mode for merge buffer: "
- obarray 'commandp t nil))))
- (funcall mode)
- (emerge-refresh-mode-line)
- (if emerge-fast-mode
- (emerge-fast-mode)
- (emerge-edit-mode)))
-
-(defun emerge-one-line-window ()
- (interactive)
- (let ((window-min-height 1))
- (shrink-window (- (window-height) 2))))
-
-;;; Support routines
-
-;; Select a difference by placing the visual flags around the appropriate
-;; group of lines in the A, B, and merge buffers
-(defun emerge-select-difference (n)
- (let ((emerge-globalized-difference-list emerge-difference-list)
- (emerge-globalized-number-of-differences emerge-number-of-differences))
- (emerge-place-flags-in-buffer emerge-A-buffer n 0 1)
- (emerge-place-flags-in-buffer emerge-B-buffer n 2 3)
- (emerge-place-flags-in-buffer nil n 4 5))
- (run-hooks 'emerge-select-hook))
-
-(defun emerge-place-flags-in-buffer (buffer difference before-index
- after-index)
- (if buffer
- (emerge-eval-in-buffer
- buffer
- (emerge-place-flags-in-buffer1 difference before-index after-index))
- (emerge-place-flags-in-buffer1 difference before-index after-index)))
-
-(defun emerge-place-flags-in-buffer1 (difference before-index after-index)
- (let ((buffer-read-only nil))
- ;; insert the flag before the difference
- (let ((before (aref (aref emerge-globalized-difference-list difference)
- before-index))
- here)
- (goto-char before)
- ;; insert the flag itself
- (insert-before-markers emerge-before-flag)
- (setq here (point))
- ;; Put the marker(s) referring to this position 1 character before the
- ;; end of the flag, so it won't be damaged by the user.
- ;; This gets a bit tricky, as there could be a number of markers
- ;; that have to be moved.
- (set-marker before (1- before))
- (let ((n (1- difference)) after-marker before-marker diff-list)
- (while (and
- (>= n 0)
- (progn
- (setq diff-list (aref emerge-globalized-difference-list n)
- after-marker (aref diff-list after-index))
- (= after-marker here)))
- (set-marker after-marker (1- after-marker))
- (setq before-marker (aref diff-list before-index))
- (if (= before-marker here)
- (setq before-marker (1- before-marker)))
- (setq n (1- n)))))
- ;; insert the flag after the difference
- (let* ((after (aref (aref emerge-globalized-difference-list difference)
- after-index))
- (here (marker-position after)))
- (goto-char here)
- ;; insert the flag itself
- (insert emerge-after-flag)
- ;; Put the marker(s) referring to this position 1 character after the
- ;; beginning of the flag, so it won't be damaged by the user.
- ;; This gets a bit tricky, as there could be a number of markers
- ;; that have to be moved.
- (set-marker after (1+ after))
- (let ((n (1+ difference)) before-marker after-marker diff-list)
- (while (and
- (< n emerge-globalized-number-of-differences)
- (progn
- (setq diff-list (aref emerge-globalized-difference-list n)
- before-marker (aref diff-list before-index))
- (= before-marker here)))
- (set-marker before-marker (1+ before-marker))
- (setq after-marker (aref diff-list after-index))
- (if (= after-marker here)
- (setq after-marker (1+ after-marker)))
- (setq n (1+ n)))))))
-
-;; Unselect a difference by removing the visual flags in the buffers.
-(defun emerge-unselect-difference (n)
- (let ((diff-vector (aref emerge-difference-list n)))
- (emerge-remove-flags-in-buffer emerge-A-buffer
- (aref diff-vector 0) (aref diff-vector 1))
- (emerge-remove-flags-in-buffer emerge-B-buffer
- (aref diff-vector 2) (aref diff-vector 3))
- (emerge-remove-flags-in-buffer emerge-merge-buffer
- (aref diff-vector 4) (aref diff-vector 5)))
- (run-hooks 'emerge-unselect-hook))
-
-(defun emerge-remove-flags-in-buffer (buffer before after)
- (emerge-eval-in-buffer
- buffer
- (let ((buffer-read-only nil))
- ;; remove the flags, if they're there
- (goto-char (- before (1- emerge-before-flag-length)))
- (if (looking-at emerge-before-flag-match)
- (delete-char emerge-before-flag-length)
- ;; the flag isn't there
- (ding)
- (message "Trouble removing flag"))
- (goto-char (1- after))
- (if (looking-at emerge-after-flag-match)
- (delete-char emerge-after-flag-length)
- ;; the flag isn't there
- (ding)
- (message "Trouble removing flag")))))
-
-;; Select a difference, removing any flags that exist now.
-(defun emerge-unselect-and-select-difference (n &optional suppress-display)
- (if (and (>= emerge-current-difference 0)
- (< emerge-current-difference emerge-number-of-differences))
- (emerge-unselect-difference emerge-current-difference))
- (if (and (>= n 0) (< n emerge-number-of-differences))
- (progn
- (emerge-select-difference n)
- (let* ((diff-vector (aref emerge-difference-list n))
- (selection-type (aref diff-vector 6)))
- (if (eq selection-type 'default-A)
- (aset diff-vector 6 'A)
- (if (eq selection-type 'default-B)
- (aset diff-vector 6 'B))))))
- (setq emerge-current-difference n)
- (if (not suppress-display)
- (progn
- (emerge-recenter)
- (emerge-refresh-mode-line))))
-
-;; Perform tests to see whether user should be allowed to select a version
-;; of this difference:
-;; a valid difference has been selected; and
-;; the difference text in the merge buffer is:
-;; the A version (execute a-version), or
-;; the B version (execute b-version), or
-;; empty (execute neither-version), or
-;; argument FORCE is true (execute neither-version)
-;; Otherwise, signal an error.
-(defun emerge-select-version (force a-version b-version neither-version)
- (emerge-validate-difference)
- (let ((buffer-read-only nil))
- (let* ((diff-vector
- (aref emerge-difference-list emerge-current-difference))
- (A-begin (1+ (aref diff-vector 0)))
- (A-end (1- (aref diff-vector 1)))
- (B-begin (1+ (aref diff-vector 2)))
- (B-end (1- (aref diff-vector 3)))
- (merge-begin (1+ (aref diff-vector 4)))
- (merge-end (1- (aref diff-vector 5))))
- (if (emerge-compare-buffers emerge-A-buffer A-begin A-end
- emerge-merge-buffer merge-begin
- merge-end)
- (funcall a-version)
- (if (emerge-compare-buffers emerge-B-buffer B-begin B-end
- emerge-merge-buffer merge-begin
- merge-end)
- (funcall b-version)
- (if (or force (= merge-begin merge-end))
- (funcall neither-version)
- (error "This difference region has been edited")))))))
-
-;; Read a file name, handling all of the various defaulting rules.
-
-(defun emerge-read-file-name (prompt alternative-default-dir default-file
- A-file must-match)
- ;; `prompt' should not have trailing ": ", so that it can be modified
- ;; according to context.
- ;; If alternative-default-dir is non-nil, it should be used as the default
- ;; directory instead if default-directory, if emerge-default-last-directories
- ;; is set.
- ;; If default-file is set, it should be used as the default value.
- ;; If A-file is set, and its directory is different from
- ;; alternative-default-dir, and if emerge-default-last-directories is set,
- ;; the default file should be the last part of A-file in the default
- ;; directory. (Overriding default-file.)
- (cond
- ;; If this is not the A-file argument (shown by non-nil A-file), and
- ;; if emerge-default-last-directories is set, and
- ;; the default directory exists but is not the same as the directory of the
- ;; A-file,
- ;; then make the default file have the same name as the A-file, but in
- ;; the default directory.
- ((and emerge-default-last-directories
- A-file
- alternative-default-dir
- (not (string-equal alternative-default-dir
- (file-name-directory A-file))))
- (read-file-name (format "%s (default %s): "
- prompt (file-name-nondirectory A-file))
- alternative-default-dir
- (concat alternative-default-dir
- (file-name-nondirectory A-file))
- (and must-match 'confirm)))
- ;; If there is a default file, use it.
- (default-file
- (read-file-name (format "%s (default %s): " prompt default-file)
- ;; If emerge-default-last-directories is set, use the
- ;; directory from the same argument of the last call of
- ;; Emerge as the default for this argument.
- (and emerge-default-last-directories
- alternative-default-dir)
- default-file (and must-match 'confirm)))
- (t
- (read-file-name (concat prompt ": ")
- ;; If emerge-default-last-directories is set, use the
- ;; directory from the same argument of the last call of
- ;; Emerge as the default for this argument.
- (and emerge-default-last-directories
- alternative-default-dir)
- nil (and must-match 'confirm)))))
-
-;; Revise the mode line to display which difference we have selected
-
-(defun emerge-refresh-mode-line ()
- (setq mode-line-buffer-identification
- (list (format "Emerge: %%b diff %d of %d%s"
- (1+ emerge-current-difference)
- emerge-number-of-differences
- (if (and (>= emerge-current-difference 0)
- (< emerge-current-difference
- emerge-number-of-differences))
- (cdr (assq (aref (aref emerge-difference-list
- emerge-current-difference)
- 6)
- '((A . " - A")
- (B . " - B")
- (prefer-A . " - A*")
- (prefer-B . " - B*")
- (combined . " - comb"))))
- ""))))
- (force-mode-line-update))
-
-;; compare two regions in two buffers for containing the same text
-(defun emerge-compare-buffers (buffer-x x-begin x-end buffer-y y-begin y-end)
- ;; first check that the two regions are the same length
- (if (not (and (= (- x-end x-begin) (- y-end y-begin))))
- nil
- (catch 'exit
- (while (< x-begin x-end)
- ;; bite off and compare no more than 1000 characters at a time
- (let* ((compare-length (min (- x-end x-begin) 1000))
- (x-string (emerge-eval-in-buffer
- buffer-x
- (buffer-substring x-begin
- (+ x-begin compare-length))))
- (y-string (emerge-eval-in-buffer
- buffer-y
- (buffer-substring y-begin
- (+ y-begin compare-length)))))
- (if (not (string-equal x-string y-string))
- (throw 'exit nil)
- (setq x-begin (+ x-begin compare-length))
- (setq y-begin (+ y-begin compare-length)))))
- t)))
-
-;; Construct a unique buffer name.
-;; The first one tried is prefixsuffix, then prefix<2>suffix,
-;; prefix<3>suffix, etc.
-(defun emerge-unique-buffer-name (prefix suffix)
- (if (null (get-buffer (concat prefix suffix)))
- (concat prefix suffix)
- (let ((n 2))
- (while (get-buffer (format "%s<%d>%s" prefix n suffix))
- (setq n (1+ n)))
- (format "%s<%d>%s" prefix n suffix))))
-
-;; Verify that we have a difference selected.
-(defun emerge-validate-difference ()
- (if (not (and (>= emerge-current-difference 0)
- (< emerge-current-difference emerge-number-of-differences)))
- (error "No difference selected")))
-
-;;; Functions for saving and restoring a batch of variables
-
-;; These functions save (get the values of) and restore (set the values of)
-;; a list of variables. The argument is a list of symbols (the names of
-;; the variables). A list element can also be a list of two functions,
-;; the first of which (when called with no arguments) gets the value, and
-;; the second (when called with a value as an argument) sets the value.
-;; A "function" is anything that funcall can handle as an argument.
-
-(defun emerge-save-variables (vars)
- (mapcar (function (lambda (v) (if (symbolp v)
- (symbol-value v)
- (funcall (car v)))))
- vars))
-
-(defun emerge-restore-variables (vars values)
- (while vars
- (let ((var (car vars))
- (value (car values)))
- (if (symbolp var)
- (set var value)
- (funcall (car (cdr var)) value)))
- (setq vars (cdr vars))
- (setq values (cdr values))))
-
-;; Make a temporary file that only we have access to.
-;; PREFIX is appended to emerge-temp-file-prefix to make the filename prefix.
-(defun emerge-make-temp-file (prefix)
- (let ((f (make-temp-name (concat emerge-temp-file-prefix prefix))))
- ;; create the file
- (write-region (point-min) (point-min) f nil 'no-message)
- (set-file-modes f emerge-temp-file-mode)
- f))
-
-;;; Functions that query the user before he can write out the current buffer.
-
-(defun emerge-query-write-file ()
- "Ask the user whether to write out an incomplete merge.
-If answer is yes, call `write-file' to do so. See `emerge-query-and-call'
-for details of the querying process."
- (interactive)
- (emerge-query-and-call 'write-file))
-
-(defun emerge-query-save-buffer ()
- "Ask the user whether to save an incomplete merge.
-If answer is yes, call `save-buffer' to do so. See `emerge-query-and-call'
-for details of the querying process."
- (interactive)
- (emerge-query-and-call 'save-buffer))
-
-(defun emerge-query-and-call (command)
- "Ask the user whether to save or write out the incomplete merge.
-If answer is yes, call COMMAND interactively. During the call, the flags
-around the current difference are removed."
- (if (yes-or-no-p "Do you really write to write out this unfinished merge? ")
- ;; He really wants to do it -- unselect the difference for the duration
- (progn
- (if (and (>= emerge-current-difference 0)
- (< emerge-current-difference emerge-number-of-differences))
- (emerge-unselect-difference emerge-current-difference))
- ;; call-interactively takes the value of current-prefix-arg as the
- ;; prefix argument value to be passed to the command. Thus, we have
- ;; to do nothing special to make sure the prefix argument is
- ;; transmitted to the command.
- (call-interactively command)
- (if (and (>= emerge-current-difference 0)
- (< emerge-current-difference emerge-number-of-differences))
- (progn
- (emerge-select-difference emerge-current-difference)
- (emerge-recenter))))
- ;; He's being smart and not doing it
- (message "Not written")))
-
-;; Make sure the current buffer (for a file) has the same contents as the
-;; file on disk, and attempt to remedy the situation if not.
-;; Signal an error if we can't make them the same, or the user doesn't want
-;; to do what is necessary to make them the same.
-(defun emerge-verify-file-buffer ()
- ;; First check if the file has been modified since the buffer visited it.
- (if (verify-visited-file-modtime (current-buffer))
- (if (buffer-modified-p)
- ;; If buffer is not obsolete and is modified, offer to save
- (if (yes-or-no-p (format "Save file %s? " buffer-file-name))
- (save-buffer)
- (error "Buffer out of sync for file %s" buffer-file-name))
- ;; If buffer is not obsolete and is not modified, do nothing
- nil)
- (if (buffer-modified-p)
- ;; If buffer is obsolete and is modified, give error
- (error "Buffer out of sync for file %s" buffer-file-name)
- ;; If buffer is obsolete and is not modified, offer to revert
- (if (yes-or-no-p (format "Revert file %s? " buffer-file-name))
- (revert-buffer t t)
- (error "Buffer out of sync for file %s" buffer-file-name)))))
-
-;; Utilities that might have value outside of Emerge.
-
-;; Set up the mode in the current buffer to duplicate the mode in another
-;; buffer.
-(defun emerge-copy-modes (buffer)
- ;; Set the major mode
- (funcall (emerge-eval-in-buffer buffer major-mode)))
-
-;; Define a key, even if a prefix of it is defined
-(defun emerge-force-define-key (keymap key definition)
- "Like `define-key', but forcibly creates prefix characters as needed.
-If some prefix of KEY has a non-prefix definition, it is redefined."
- ;; Find out if a prefix of key is defined
- (let ((v (lookup-key keymap key)))
- ;; If so, undefine it
- (if (integerp v)
- (define-key keymap (substring key 0 v) nil)))
- ;; Now define the key
- (define-key keymap key definition))
-
-;;;;; Improvements to describe-mode, so that it describes minor modes as well
-;;;;; as the major mode
-;;(defun describe-mode (&optional minor)
-;; "Display documentation of current major mode.
-;;If optional arg MINOR is non-nil (or prefix argument is given if interactive),
-;;display documentation of active minor modes as well.
-;;For this to work correctly for a minor mode, the mode's indicator variable
-;;\(listed in `minor-mode-alist') must also be a function whose documentation
-;;describes the minor mode."
-;; (interactive)
-;; (with-output-to-temp-buffer "*Help*"
-;; (princ mode-name)
-;; (princ " Mode:\n")
-;; (princ (documentation major-mode))
-;; (let ((minor-modes minor-mode-alist)
-;; (locals (buffer-local-variables)))
-;; (while minor-modes
-;; (let* ((minor-mode (car (car minor-modes)))
-;; (indicator (car (cdr (car minor-modes))))
-;; (local-binding (assq minor-mode locals)))
-;; ;; Document a minor mode if it is listed in minor-mode-alist,
-;; ;; bound locally in this buffer, non-nil, and has a function
-;; ;; definition.
-;; (if (and local-binding
-;; (cdr local-binding)
-;; (fboundp minor-mode))
-;; (progn
-;; (princ (format "\n\n\n%s minor mode (indicator%s):\n"
-;; minor-mode indicator))
-;; (princ (documentation minor-mode)))))
-;; (setq minor-modes (cdr minor-modes))))
-;; (save-excursion
-;; (set-buffer standard-output)
-;; (help-mode))
-;; (print-help-return-message)))
-
-;; This goes with the redefinition of describe-mode.
-;;;; Adjust things so that keyboard macro definitions are documented correctly.
-;;(fset 'defining-kbd-macro (symbol-function 'start-kbd-macro))
-
-;; substitute-key-definition should work now.
-;;;; Function to shadow a definition in a keymap with definitions in another.
-;;(defun emerge-shadow-key-definition (olddef newdef keymap shadowmap)
-;; "Shadow OLDDEF with NEWDEF for any keys in KEYMAP with entries in SHADOWMAP.
-;;In other words, SHADOWMAP will now shadow all definitions of OLDDEF in KEYMAP
-;;with NEWDEF. Does not affect keys that are already defined in SHADOWMAP,
-;;including those whose definition is OLDDEF."
-;; ;; loop through all keymaps accessible from keymap
-;; (let ((maps (accessible-keymaps keymap)))
-;; (while maps
-;; (let ((prefix (car (car maps)))
-;; (map (cdr (car maps))))
-;; ;; examine a keymap
-;; (if (arrayp map)
-;; ;; array keymap
-;; (let ((len (length map))
-;; (i 0))
-;; (while (< i len)
-;; (if (eq (aref map i) olddef)
-;; ;; set the shadowing definition
-;; (let ((key (concat prefix (char-to-string i))))
-;; (emerge-define-key-if-possible shadowmap key newdef)))
-;; (setq i (1+ i))))
-;; ;; sparse keymap
-;; (while map
-;; (if (eq (cdr-safe (car-safe map)) olddef)
-;; ;; set the shadowing definition
-;; (let ((key
-;; (concat prefix (char-to-string (car (car map))))))
-;; (emerge-define-key-if-possible shadowmap key newdef)))
-;; (setq map (cdr map)))))
-;; (setq maps (cdr maps)))))
-
-;; Define a key if it (or a prefix) is not already defined in the map.
-(defun emerge-define-key-if-possible (keymap key definition)
- ;; look up the present definition of the key
- (let ((present (lookup-key keymap key)))
- (if (integerp present)
- ;; if it is "too long", look up the valid prefix
- (if (not (lookup-key keymap (substring key 0 present)))
- ;; if the prefix isn't defined, define it
- (define-key keymap key definition))
- ;; if there is no present definition, define it
- (if (not present)
- (define-key keymap key definition)))))
-
-;; Ordinary substitute-key-definition should do this now.
-;;(defun emerge-recursively-substitute-key-definition (olddef newdef keymap)
-;; "Like `substitute-key-definition', but act recursively on subkeymaps.
-;;Make sure that subordinate keymaps aren't shared with other keymaps!
-;;\(`copy-keymap' will suffice.)"
-;; ;; Loop through all keymaps accessible from keymap
-;; (let ((maps (accessible-keymaps keymap)))
-;; (while maps
-;; ;; Substitute in this keymap
-;; (substitute-key-definition olddef newdef (cdr (car maps)))
-;; (setq maps (cdr maps)))))
-
-;; Show the name of the file in the buffer.
-(defun emerge-show-file-name ()
- "Displays the name of the file loaded into the current buffer.
-If the name won't fit on one line, the minibuffer is expanded to hold it,
-and the command waits for a keystroke from the user. If the keystroke is
-SPC, it is ignored; if it is anything else, it is processed as a command."
- (interactive)
- (let ((name (buffer-file-name)))
- (or name
- (setq name "Buffer has no file name."))
- (save-window-excursion
- (select-window (minibuffer-window))
- (erase-buffer)
- (insert name)
- (if (not (pos-visible-in-window-p))
- (let ((echo-keystrokes 0))
- (while (and (not (pos-visible-in-window-p))
- (> (1- (screen-height)) (window-height)))
- (enlarge-window 1))
- (let ((c (read-event)))
- (if (not (eq c 32))
- (setq unread-command-events (list c)))))))))
-
-;; Improved auto-save file names.
-;; This function fixes many problems with the standard auto-save file names:
-;; Auto-save files for non-file buffers get put in the default directory
-;; for the buffer, whether that makes sense or not.
-;; Auto-save files for file buffers get put in the directory of the file,
-;; regardless of whether we can write into it or not.
-;; Auto-save files for non-file buffers don't use the process id, so if a
-;; user runs more than on Emacs, they can make auto-save files that overwrite
-;; each other.
-;; To use this function, do:
-;; (fset 'make-auto-save-file-name
-;; (symbol-function 'emerge-make-auto-save-file-name))
-(defun emerge-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
- ;; if buffer has a file, try the format <file directory>/#<file name>#
- (let ((f (concat (file-name-directory buffer-file-name)
- "#"
- (file-name-nondirectory buffer-file-name)
- "#")))
- (if (file-writable-p f)
- ;; the file is writable, so use it
- f
- ;; the file isn't writable, so use the format
- ;; ~/#&<file name>&<hash of directory>#
- (concat (getenv "HOME")
- "/#&"
- (file-name-nondirectory buffer-file-name)
- "&"
- (emerge-hash-string-into-string
- (file-name-directory buffer-file-name))
- "#")))
- ;; if buffer has no file, use the format ~/#%<buffer name>%<process id>#
- (expand-file-name (concat (getenv "HOME")
- "/#%"
- ;; quote / into \! and \ into \\
- (emerge-unslashify-name (buffer-name))
- "%"
- (make-temp-name "")
- "#"))))
-
-;; Hash a string into five characters more-or-less suitable for use in a file
-;; name. (Allowed characters are ! through ~, except /.)
-(defun emerge-hash-string-into-string (s)
- (let ((bins (vector 0 0 0 0 0))
- (i 0))
- (while (< i (length s))
- (aset bins (% i 5) (% (+ (* (aref bins (% i 5)) 35)
- (aref s i))
- 65536))
- (setq i (1+ i)))
- (mapconcat (function (lambda (b)
- (setq b (+ (% b 93) ?!))
- (if (>= b ?/)
- (setq b (1+ b)))
- (char-to-string b)))
- bins "")))
-
-;; Quote any /s in a string by replacing them with \!.
-;; Also, replace any \s by \\, to make it one-to-one.
-(defun emerge-unslashify-name (s)
- (let ((limit 0))
- (while (string-match "[/\\]" s limit)
- (setq s (concat (substring s 0 (match-beginning 0))
- (if (string= (substring s (match-beginning 0)
- (match-end 0))
- "/")
- "\\!"
- "\\\\")
- (substring s (match-end 0))))
- (setq limit (1+ (match-end 0)))))
- s)
-
-;; Metacharacters that have to be protected from the shell when executing
-;; a diff/diff3 command.
-(defvar emerge-metachars "[ \t\n!\"#$&'()*;<=>?[\\^`{|~]"
- "Characters that must be quoted with \\ when used in a shell command line.
-More precisely, a [...] regexp to match any one such character.")
-
-;; Quote metacharacters (using \) when executing a diff/diff3 command.
-(defun emerge-protect-metachars (s)
- (let ((limit 0))
- (while (string-match emerge-metachars s limit)
- (setq s (concat (substring s 0 (match-beginning 0))
- "\\"
- (substring s (match-beginning 0))))
- (setq limit (1+ (match-end 0)))))
- s)
-
-(provide 'emerge)
-
-;;; emerge.el ends here
diff --git a/lisp/emulation/edt-lk201.el b/lisp/emulation/edt-lk201.el
deleted file mode 100644
index 8695914579a..00000000000
--- a/lisp/emulation/edt-lk201.el
+++ /dev/null
@@ -1,55 +0,0 @@
-;;; edt-lk201.el --- Enhanced EDT Keypad Mode Emulation for LK-201 Keyboards
-
-;; Copyright (C) 1986, 1992, 1993, 1995 Free Software Foundation, Inc.
-
-;; Author: Kevin Gallagher <kgallagh@spd.dsccc.com>
-;; Maintainer: Kevin Gallagher <kgallagh@spd.dsccc.com>
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Usage:
-
-;; See edt-user.doc in the Emacs etc directory.
-
-;; ====================================================================
-
-;;;;
-;;;; KEY TRANSLATIONS
-;;;;
-
-;; Associate EDT keynames with Emacs terminal function vector names.
-;; (Function key vector names for LK-201 are found in lisp/term/lk201.el.)
-;;
-;; F1 - F5 are not available on many DEC VT series terminals.
-;; However, this is not always the case. So support for F1 - F5 is
-;; provided here and in lisp/term/lk201.el.
-(defconst *EDT-keys*
- '(("KP0" . [kp-0]) ("KP1" . [kp-1]) ("KP2" . [kp-2]) ("KP3" . [kp-3])
- ("KP4" . [kp-4]) ("KP5" . [kp-5]) ("KP6" . [kp-6]) ("KP7" . [kp-7])
- ("KP8" . [kp-8]) ("KP9" . [kp-9]) ("KP," . [kp-separator])
- ("KP-" . [kp-subtract]) ("KPP" . [kp-decimal]) ("KPE" . [kp-enter])
- ("PF1" . [kp-f1]) ("PF2" . [kp-f2]) ("PF3" . [kp-f3]) ("PF4" . [kp-f4])
- ("UP" . [up]) ("DOWN" . [down]) ("RIGHT" . [right]) ("LEFT" . [left])
- ("FIND" . [find]) ("INSERT" . [insert]) ("REMOVE" . [delete])
- ("SELECT" . [select]) ("PREVIOUS" . [prior]) ("NEXT" . [next])
- ("F1" . [f1]) ("F2" . [f2]) ("F3" . [f3]) ("F4" . [f4]) ("F5" . [f5])
- ("F6" . [f6]) ("F7" . [f7]) ("F8" . [f8]) ("F9" . [f9]) ("F10" . [f10])
- ("F11" . [f11]) ("F12" . [f12]) ("F13" . [f13]) ("F14" . [f14])
- ("HELP" . [help]) ("DO" . [menu]) ("F17" . [f17]) ("F18" . [f18])
- ("F19" . [f19]) ("F20" . [f20])))
diff --git a/lisp/emulation/edt-mapper.el b/lisp/emulation/edt-mapper.el
deleted file mode 100644
index ebebb92ad25..00000000000
--- a/lisp/emulation/edt-mapper.el
+++ /dev/null
@@ -1,405 +0,0 @@
-;;; edt-mapper.el --- Create an EDT LK-201 Map File for X-Windows Emacs
-
-;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Kevin Gallagher <kgallagh@spd.dsccc.com>
-;; Maintainer: Kevin Gallagher <kgallagh@spd.dsccc.com>
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This emacs lisp program can be used to create an emacs lisp file
-;; that defines the mapping of the user's keyboard under X-Windows to
-;; the LK-201 keyboard function keys and keypad keys (around which
-;; EDT has been designed). Please read the "Usage" AND "Known
-;; Problems" sections before attempting to run this program. (The
-;; design of this file, edt-mapper.el, was heavily influenced by
-;; tpu-mapper.el.)
-
-;;; Usage:
-
-;; Simply load this file into the X-Windows version of emacs (version 19)
-;; using the following command.
-
-;; emacs -q -l edt-mapper.el
-
-;; The "-q" option prevents loading of your .emacs file (commands therein
-;; might confuse this program).
-
-;; An instruction screen showing the typical LK-201 terminal functions keys
-;; will be displayed, and you will be prompted to press the keys on your
-;; keyboard which you want to emulate the corresponding LK-201 keys.
-
-;; Finally, you will be prompted for the name of the file to store
-;; the key definitions. If you chose the default, it will be found
-;; and loaded automatically when the EDT emulation is started. If
-;; you specify a different file name, you will need to set the
-;; variable "edt-xkeys-file" before starting the EDT emulation.
-;; Here's how you might go about doing that in your .emacs file.
-
-;; (setq edt-xkeys-file (expand-file-name "~/.my-emacs-x-keys"))
-
-;;; Known Problems:
-
-;; Sometimes, edt-mapper will ignore a key you press, and just continue to
-;; prompt for the same key. This can happen when your window manager sucks
-;; up the key and doesn't pass it on to emacs, or it could be an emacs bug.
-;; Either way, there's nothing that edt-mapper can do about it. You must
-;; press RETURN, to skip the current key and continue. Later, you and/or
-;; your local X guru can try to figure out why the key is being ignored.
-
-;; ====================================================================
-
-;;;
-;;; Make sure we're running X-windows and Emacs version 19
-;;;
-(cond
- ((not (and window-system (not (string-lessp emacs-version "19"))))
- (insert "
-
- Whoa! This isn't going to work...
-
- You must run edt-mapper.el under X-windows and Emacs version 19.
-
- Press any key to exit. ")
- (sit-for 600)
- (kill-emacs t)))
-
-
-;;;
-;;; Decide whether we're running GNU or Lucid emacs.
-;;;
-(defconst edt-lucid-emacs19-p (string-match "Lucid" emacs-version)
- "Non-NIL if we are running Lucid Emacs version 19.")
-
-
-;;;
-;;; Key variables
-;;;
-(defvar edt-key nil)
-(defvar edt-enter nil)
-(defvar edt-return nil)
-(defvar edt-key-seq nil)
-(defvar edt-enter-seq nil)
-(defvar edt-return-seq nil)
-
-
-;;;
-;;; Make sure the window is big enough to display the instructions
-;;;
-(if edt-lucid-emacs19-p (set-screen-size nil 80 36)
- (set-frame-size (selected-frame) 80 36))
-
-
-;;;
-;;; Create buffers - Directions and Keys
-;;;
-(if (not (get-buffer "Directions")) (generate-new-buffer "Directions"))
-(if (not (get-buffer "Keys")) (generate-new-buffer "Keys"))
-
-;;;
-;;; Put header in the Keys buffer
-;;;
-(set-buffer "Keys")
-(insert "\
-;;
-;; Key definitions for the EDT emulation within GNU Emacs
-;;
-
-(defconst *EDT-keys*
- '(
-")
-
-;;;
-;;; Display directions
-;;;
-(switch-to-buffer "Directions")
-(insert "
- EDT MAPPER
-
- You will be asked to press keys to create a custom mapping (under
- X-Windows) of your keypad keys and function keys so that they can emulate
- the LK-201 keypad and function keys or the subset of keys found on a
- VT-100 series terminal keyboard. (The LK-201 keyboard is the standard
- keyboard attached to VT-200 series terminals, and above.)
-
- Sometimes, edt-mapper will ignore a key you press, and just continue to
- prompt for the same key. This can happen when your window manager sucks
- up the key and doesn't pass it on to emacs, or it could be an emacs bug.
- Either way, there's nothing that edt-mapper can do about it. You must
- press RETURN, to skip the current key and continue. Later, you and/or
- your local X guru can try to figure out why the key is being ignored.
-
- Start by pressing the RETURN key, and continue by pressing the keys
- specified in the mini-buffer. If you want to entirely omit a key,
- because your keyboard does not have a corresponding key, for example,
- just press RETURN at the prompt.
-
-")
-(delete-other-windows)
-
-;;;
-;;; Save <CR> for future reference
-;;;
-(cond
- (edt-lucid-emacs19-p
- (setq edt-return-seq (read-key-sequence "Hit carriage-return <CR> to continue "))
- (setq edt-return (concat "[" (format "%s" (event-key (aref edt-return-seq 0))) "]")))
- (t
- (message "Hit carriage-return <CR> to continue ")
- (setq edt-return-seq (read-event))
- (setq edt-return (concat "[" (format "%s" edt-return-seq) "]"))))
-
-;;;
-;;; Display Keypad Diagram and Begin Prompting for Keys
-;;;
-(set-buffer "Directions")
-(delete-region (point-min) (point-max))
-(insert "
-
-
-
- PRESS THE KEY SPECIFIED IN THE MINIBUFFER BELOW.
-
-
-
-
- Here's a picture of the standard LK-201 keypad for reference:
-
- _______________________ _______________________________
- | HELP | DO | | F17 | F18 | F19 | F20 |
- | | | | | | | |
- |_______|_______________| |_______|_______|_______|_______|
- _______________________ _______________________________
- | FIND |INSERT |REMOVE | | PF1 | PF2 | PF3 | PF4 |
- | | | | | | | | |
- |_______|_______|_______| |_______|_______|_______|_______|
- |SELECT |PREVIOU| NEXT | | KP7 | KP8 | KP9 | KP- |
- | | | | | | | | |
- |_______|_______|_______| |_______|_______|_______|_______|
- | UP | | KP4 | KP5 | KP6 | KP, |
- | | | | | | |
- _______|_______|_______ |_______|_______|_______|_______|
- | LEFT | DOWN | RIGHT | | KP1 | KP2 | KP3 | |
- | | | | | | | | |
- |_______|_______|_______| |_______|_______|_______| KPE |
- | KP0 | KPP | |
- | | | |
- |_______________|_______|_______|
-
-")
-
-;;;
-;;; Key mapping functions
-;;;
-(defun edt-lucid-map-key (ident descrip func gold-func)
- (interactive)
- (setq edt-key-seq (read-key-sequence (format "Press %s%s: " ident descrip)))
- (setq edt-key (concat "[" (format "%s" (event-key (aref edt-key-seq 0))) "]"))
- (cond ((not (equal edt-key edt-return))
- (set-buffer "Keys")
- (insert (format " (\"%s\" . %s)\n" ident edt-key))
- (set-buffer "Directions"))
- ;; bogosity to get next prompt to come up, if the user hits <CR>!
- ;; check periodically to see if this is still needed...
- (t
- (format "%s" edt-key)))
- edt-key)
-
-(defun edt-gnu-map-key (ident descrip)
- (interactive)
- (message "Press %s%s: " ident descrip)
- (setq edt-key-seq (read-event))
- (setq edt-key (concat "[" (format "%s" edt-key-seq) "]"))
- (cond ((not (equal edt-key edt-return))
- (set-buffer "Keys")
- (insert (format " (\"%s\" . %s)\n" ident edt-key))
- (set-buffer "Directions"))
- ;; bogosity to get next prompt to come up, if the user hits <CR>!
- ;; check periodically to see if this is still needed...
- (t
- (set-buffer "Keys")
- (insert (format " (\"%s\" . \"\" )\n" ident))
- (set-buffer "Directions")))
- edt-key)
-
-(fset 'edt-map-key (if edt-lucid-emacs19-p 'edt-lucid-map-key 'edt-gnu-map-key))
-(set-buffer "Keys")
-(insert "
-;;
-;; Arrows
-;;
-")
-(set-buffer "Directions")
-
-(edt-map-key "UP" " - The Up Arrow Key")
-(edt-map-key "DOWN" " - The Down Arrow Key")
-(edt-map-key "LEFT" " - The Left Arrow Key")
-(edt-map-key "RIGHT" " - The Right Arrow Key")
-
-
-(set-buffer "Keys")
-(insert "
-;;
-;; PF keys
-;;
-")
-(set-buffer "Directions")
-
-(edt-map-key "PF1" " - The PF1 (GOLD) Key")
-(edt-map-key "PF2" " - The Keypad PF2 Key")
-(edt-map-key "PF3" " - The Keypad PF3 Key")
-(edt-map-key "PF4" " - The Keypad PF4 Key")
-
-(set-buffer "Keys")
-(insert "
-;;
-;; KP0-9 KP- KP, KPP and KPE
-;;
-")
-(set-buffer "Directions")
-
-(edt-map-key "KP0" " - The Keypad 0 Key")
-(edt-map-key "KP1" " - The Keypad 1 Key")
-(edt-map-key "KP2" " - The Keypad 2 Key")
-(edt-map-key "KP3" " - The Keypad 3 Key")
-(edt-map-key "KP4" " - The Keypad 4 Key")
-(edt-map-key "KP5" " - The Keypad 5 Key")
-(edt-map-key "KP6" " - The Keypad 6 Key")
-(edt-map-key "KP7" " - The Keypad 7 Key")
-(edt-map-key "KP8" " - The Keypad 8 Key")
-(edt-map-key "KP9" " - The Keypad 9 Key")
-(edt-map-key "KP-" " - The Keypad - Key")
-(edt-map-key "KP," " - The Keypad , Key")
-(edt-map-key "KPP" " - The Keypad . Key")
-(edt-map-key "KPE" " - The Keypad Enter Key")
-;; Save the enter key
-(setq edt-enter edt-key)
-(setq edt-enter-seq edt-key-seq)
-
-
-(set-buffer "Keys")
-(insert "
-;;
-;; Editing keypad (FIND, INSERT, REMOVE)
-;; (SELECT, PREVIOUS, NEXT)
-;;
-")
-(set-buffer "Directions")
-
-(edt-map-key "FIND" " - The Find key on the editing keypad")
-(edt-map-key "INSERT" " - The Insert key on the editing keypad")
-(edt-map-key "REMOVE" " - The Remove key on the editing keypad")
-(edt-map-key "SELECT" " - The Select key on the editing keypad")
-(edt-map-key "PREVIOUS" " - The Prev Scr key on the editing keypad")
-(edt-map-key "NEXT" " - The Next Scr key on the editing keypad")
-
-(set-buffer "Keys")
-(insert "
-;;
-;; F1-14 Help Do F17-F20
-;;
-")
-(set-buffer "Directions")
-
-(edt-map-key "F1" " - F1 Function Key")
-(edt-map-key "F2" " - F2 Function Key")
-(edt-map-key "F3" " - F3 Function Key")
-(edt-map-key "F4" " - F4 Function Key")
-(edt-map-key "F5" " - F5 Function Key")
-(edt-map-key "F6" " - F6 Function Key")
-(edt-map-key "F7" " - F7 Function Key")
-(edt-map-key "F8" " - F8 Function Key")
-(edt-map-key "F9" " - F9 Function Key")
-(edt-map-key "F10" " - F10 Function Key")
-(edt-map-key "F11" " - F11 Function Key")
-(edt-map-key "F12" " - F12 Function Key")
-(edt-map-key "F13" " - F13 Function Key")
-(edt-map-key "F14" " - F14 Function Key")
-(edt-map-key "HELP" " - HELP Function Key")
-(edt-map-key "DO" " - DO Function Key")
-(edt-map-key "F17" " - F17 Function Key")
-(edt-map-key "F18" " - F18 Function Key")
-(edt-map-key "F19" " - F19 Function Key")
-(edt-map-key "F20" " - F20 Function Key")
-
-(set-buffer "Directions")
-(delete-region (point-min) (point-max))
-(insert "
- ADDITIONAL FUNCTION KEYS
-
- Your keyboard may have additional function keys which do not
- correspond to any LK-201 keys. The EDT Emulation can be
- configured to recognize those keys, since you may wish to add your
- own key bindings to those keys.
-
- For example, suppose your keyboard has a keycap marked \"Line Del\"
- and you wish to add it to the list of keys which can be customized
- by the EDT Emulation. First, assign a unique single-word name to
- the key for use by the EDT Emulation, let's say \"linedel\", in this
- example. Then, at the \"EDT Key Name:\" prompt, enter \"linedel\",
- followed by a press of the RETURN key. Finally, when prompted,
- press the \"Line Del\" key. You now will be able to bind functions
- to \"linedel\" and \"Gold-linedel\" in edt-user.el in just the same way
- you can customize bindings of the standard LK-201 keys.
-
- When you have no additional function keys to specify, just press
- RETURN at the \"EDT Key Name:\" prompt. (If you change your mind
- AFTER you enter an EDT Key Name and before you press a key at the
- \"Press\" prompt, you may omit the key by simply pressing RETURN at
- the prompt.)
-")
-(switch-to-buffer "Directions")
-;;;
-;;; Add support for extras keys
-;;;
-(set-buffer "Keys")
-(insert "\
-;;
-;; Extra Keys
-;;
-")
-(setq EDT-key-name "")
-(while (not
- (string-equal (setq EDT-key-name (read-string "EDT Key Name: ")) ""))
- (edt-map-key EDT-key-name ""))
-
-;
-; No more keys to add, so wrap up.
-;
-(set-buffer "Keys")
-(insert "\
- )
- )
-")
-
-;;;
-;;; Save the key mapping program and blow this pop stand
-;;;
-(let ((file (if edt-lucid-emacs19-p "~/.edt-lucid-keys" "~/.edt-gnu-keys")))
- (set-visited-file-name
- (read-file-name (format "Save key mapping to file (default %s): " file) nil file)))
-(save-buffer)
-
-(message "That's it! Press any key to exit")
-(sit-for 600)
-(kill-emacs t)
-
-;;; edt-mapper.el ends here
diff --git a/lisp/emulation/edt-pc.el b/lisp/emulation/edt-pc.el
deleted file mode 100644
index 0130c98919c..00000000000
--- a/lisp/emulation/edt-pc.el
+++ /dev/null
@@ -1,85 +0,0 @@
-;;; edt-pc.el --- Enhanced EDT Keypad Mode Emulation for PC 101 Keyboards
-
-;; Copyright (C) 1986, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Kevin Gallagher <kgallagh@spd.dsccc.com>
-;; Maintainer: Kevin Gallagher <kgallagh@spd.dsccc.com>
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Usage:
-
-;; See edt-user.doc in the Emacs etc directory.
-
-;; ====================================================================
-
-;;;;
-;;;; KEY TRANSLATIONS
-;;;;
-
-;; Associate EDT keynames with Emacs terminal function vector names.
-;;
-;; To emulate the DEC LK-201 keypad keys on the PC 101 keyboard,
-;; NumLock must be ON.
-;;
-;; The PC keypad keys are mapped to the corresponding DEC LK-201
-;; keypad keys according to the corresponding physical position on
-;; the keyboard. Thus, the physical position of the PC keypad key
-;; determines its function, not the PC keycap name.
-;;
-;; There are two LK-201 keypad keys needing special handling: PF1 and
-;; the keypad comma key.
-;;
-;; PF1:
-;; Most PC software does not see a press of the NumLock key. A TSR
-;; program distributed with MS-Kermit to support its VT-100 emulation
-;; solves this problem. The TSR, called GOLD, causes a press of the
-;; keypad NumLock key to look as if the PC F1 key were pressed. So
-;; the PC F1 key is mapped here to behave as the PF1 (GOLD) key.
-;; Then with GOLD loaded, the NumLock key will behave as the GOLD key.
-;;
-;; By the way, with GOLD loaded, you can still toggle numlock on/off.
-;; GOLD binds this to Shift-NumLock.
-;;
-;; Keypad Comma:
-;; There is no physical PC keypad key to correspond to the LK-201
-;; keypad comma key. So, the EDT Emulation is configured below to
-;; ignore attempts to bind functions to the keypad comma key.
-;;
-;; Finally, F2 through F12 are also available for making key bindings
-;; in the EDT Emulation on the PC. F1 is reserved for the GOLD key,
-;; so don't attempt to bind anything to it. Also, F13, F14, HELP, DO,
-;; and F17 through F20 do not exist on the PC, so the EDT emulation is
-;; configured below to ignore attempts to bind functions to those keys.
-;;
-(defconst *EDT-keys*
- '(("KP0" . [kp-0]) ("KP1" . [kp-1]) ("KP2" . [kp-2]) ("KP3" . [kp-3])
- ("KP4" . [kp-4]) ("KP5" . [kp-5]) ("KP6" . [kp-6]) ("KP7" . [kp-7])
- ("KP8" . [kp-8]) ("KP9" . [kp-9]) ("KP," . "" )
- ("KP-" . [kp-add]) ("KPP" . [kp-decimal]) ("KPE" . [kp-enter])
- ("PF1" . [f1]) ("PF2" . [kp-divide]) ("PF3" . [kp-multiply])
- ("PF4" . [kp-subtract])
- ("UP" . [up]) ("DOWN" . [down]) ("RIGHT" . [right]) ("LEFT" . [left])
- ("FIND" . [insert]) ("INSERT" . [home]) ("REMOVE" . [prior])
- ("SELECT" . [delete]) ("PREVIOUS" . [end]) ("NEXT" . [next])
- ("F1" . "" ) ("F2" . [f2]) ("F3" . [f3]) ("F4" . [f4]) ("F5" . [f5])
- ("F6" . [f6]) ("F7" . [f7]) ("F8" . [f8]) ("F9" . [f9]) ("F10" . [f10])
- ("F11" . [f11]) ("F12" . [f12]) ("F13" . "" ) ("F14" . "" )
- ("HELP" . "" ) ("DO" . "" ) ("F17" . "" ) ("F18" . "" )
- ("F19" . "" ) ("F20" . "" )))
diff --git a/lisp/emulation/edt-vt100.el b/lisp/emulation/edt-vt100.el
deleted file mode 100644
index 4c2d225127b..00000000000
--- a/lisp/emulation/edt-vt100.el
+++ /dev/null
@@ -1,44 +0,0 @@
-;;; edt-vt100.el --- Enhanced EDT Keypad Mode Emulation for VT Series Terminals
-
-;; Copyright (C) 1986, 1992, 1993, 1995 Free Software Foundation, Inc.
-
-;; Author: Kevin Gallagher <kgallagh@spd.dsccc.com>
-;; Maintainer: Kevin Gallagher <kgallagh@spd.dsccc.com>
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Usage:
-
-;; See edt-user.doc in the Emacs etc directory.
-
-;; ====================================================================
-
-;; Get keyboard function key mapping to EDT keys.
-(load "edt-lk201" nil t)
-
-;; The following functions are called by the EDT screen width commands defined
-;; in edt.el.
-
-(defun edt-set-term-width-80 ()
- "Set terminal width to 80 columns."
- (vt100-wide-mode -1))
-
-(defun edt-set-term-width-132 ()
- "Set terminal width to 132 columns."
- (vt100-wide-mode 1))
diff --git a/lisp/emulation/edt.el b/lisp/emulation/edt.el
deleted file mode 100644
index 6ec3dbc3f1e..00000000000
--- a/lisp/emulation/edt.el
+++ /dev/null
@@ -1,2018 +0,0 @@
-;;; edt.el --- Enhanced EDT Keypad Mode Emulation for GNU Emacs 19
-
-;; Copyright (C) 1986, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Kevin Gallagher <kgallagh@spd.dsccc.com>
-;; Maintainer: Kevin Gallagher <kgallagh@spd.dsccc.com>
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Usage:
-
-;; See edt-user.doc in the Emacs etc directory.
-
-;; ====================================================================
-
-;;; Electric Help functions are used for keypad help displays. A few
-;;; picture functions are used in rectangular cut and paste commands.
-(require 'ehelp)
-(require 'picture)
-
-;;;;
-;;;; VARIABLES and CONSTANTS
-;;;;
-
-(defvar edt-last-deleted-lines ""
- "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.")
-
-(defvar edt-last-deleted-chars ""
- "Last text deleted by an EDT emulation character delete command.")
-
-(defvar edt-last-replaced-key-definition ""
- "Key definition replaced with edt-define-key or edt-learn command.")
-
-(defvar edt-direction-string ""
- "String indicating current direction of movement.")
-
-(defvar edt-select-mode nil
- "Non-nil means select mode is active.")
-
-(defvar edt-select-mode-text ""
- "Text displayed in mode line when select mode is active.")
-
-(defconst edt-select-mode-string " Select"
- "String to indicate select mode is active.")
-
-(defconst edt-forward-string " ADVANCE"
- "Direction string in mode line to indicate forward movement.")
-
-(defconst edt-backward-string " BACKUP"
- "Direction string in mode line to indicate backward movement.")
-
-(defvar edt-default-map-active nil
- "Non-nil indicates that default EDT emulation key bindings are active.
-Nil means user-defined custom bindings are active.")
-
-(defvar edt-user-map-configured nil
- "Non-nil indicates that user custom EDT key bindings are configured.
-This means that an edt-user.el file was found in the user's load-path.")
-
-(defvar edt-keep-current-page-delimiter nil
- "Non-nil leaves current value of page-delimiter unchanged.
-Nil causes the page-delimiter variable to be set to to \"\\f\"
-when edt-emulation-on is first invoked. Original value is restored
-when edt-emulation-off is called.")
-
-(defvar edt-use-EDT-control-key-bindings nil
- "Non-nil causes the control key bindings to be replaced with EDT bindings.
-Nil (the default) means EDT control key bindings are not used and the current
-control key bindings are retained for use in the EDT emulation.")
-
-(defvar edt-word-entities '(?\t)
- "*Specifies the list of EDT word entity characters.")
-
-;;;
-;;; Emacs version identifiers - currently referenced by
-;;;
-;;; o edt-emulation-on o edt-load-xkeys
-;;;
-(defconst edt-emacs19-p (not (string-lessp emacs-version "19"))
- "Non-nil if we are running Lucid or GNU Emacs version 19.")
-
-(defconst edt-lucid-emacs19-p
- (and edt-emacs19-p (string-match "Lucid" emacs-version))
- "Non-nil if we are running Lucid Emacs version 19.")
-
-(defconst edt-gnu-emacs19-p (and edt-emacs19-p (not edt-lucid-emacs19-p))
- "Non-nil if we are running GNU Emacs version 19.")
-
-(defvar edt-xkeys-file nil
- "File mapping X function keys to LK-201 keyboard function and keypad keys.")
-
-;;;;
-;;;; EDT Emulation Commands
-;;;;
-
-;;; Almost all of EDT's keypad mode commands have equivalent
-;;; counterparts in Emacs. Some behave the same way in Emacs as they
-;;; do in EDT, but most do not.
-;;;
-;;; The following Emacs functions emulate, where practical, the exact
-;;; behavior of the corresponding EDT keypad mode commands. In a few
-;;; cases, the emulation is not exact, but it is close enough for most
-;;; EDT die-hards.
-;;;
-;;; In a very few cases, we chose to use the superior Emacs way of
-;;; handling things. For example, we do not emulate the EDT SUBS
-;;; command. Instead, we chose to use the superior Emacs
-;;; query-replace function.
-;;;
-
-;;;
-;;; PAGE
-;;;
-;;; Emacs uses the regexp assigned to page-delimiter to determine what
-;;; marks a page break. This is normally "^\f", which causes the
-;;; edt-page command to ignore form feeds not located at the beginning
-;;; of a line. To emulate the EDT PAGE command exactly,
-;;; page-delimiter is set to "\f" when EDT emulation is turned on, and
-;;; restored to its original value when EDT emulation is turned off.
-;;; But this can be overridden if the EDT definition is not desired by
-;;; placing
-;;;
-;;; (setq edt-keep-current-page-delimiter t)
-;;;
-;;; in your .emacs file.
-
-(defun edt-page-forward (num)
- "Move forward to just after next page delimiter.
-Accepts a positive prefix argument for the number of page delimiters to move."
- (interactive "p")
- (edt-check-prefix num)
- (if (eobp)
- (error "End of buffer")
- (progn
- (forward-page num)
- (if (eobp)
- (edt-line-to-bottom-of-window)
- (edt-line-to-top-of-window)))))
-
-(defun edt-page-backward (num)
- "Move backward to just after previous page delimiter.
-Accepts a positive prefix argument for the number of page delimiters to move."
- (interactive "p")
- (edt-check-prefix num)
- (if (bobp)
- (error "Beginning of buffer")
- (progn
- (backward-page num)
- (edt-line-to-top-of-window))))
-
-(defun edt-page (num)
- "Move in current direction to next page delimiter.
-Accepts a positive prefix argument for the number of page delimiters to move."
- (interactive "p")
- (if (equal edt-direction-string edt-forward-string)
- (edt-page-forward num)
- (edt-page-backward num)))
-
-;;;
-;;; SECT
-;;;
-;;; EDT defaults a section size to be 16 lines of its one and only
-;;; 24-line window. That's two-thirds of the window at a time. The
-;;; EDT SECT commands moves the cursor, not the window.
-;;;
-;;; This emulation of EDT's SECT moves the cursor approximately two-thirds
-;;; of the current window at a time.
-
-(defun edt-sect-forward (num)
- "Move cursor forward two-thirds of a window.
-Accepts a positive prefix argument for the number of sections to move."
- (interactive "p")
- (edt-check-prefix num)
- (edt-line-forward (* (* (/ (- (window-height) 1) 3) 2) num)))
-
-(defun edt-sect-backward (num)
- "Move cursor backward two-thirds of a window.
-Accepts a positive prefix argument for the number of sections to move."
- (interactive "p")
- (edt-check-prefix num)
- (edt-line-backward (* (* (/ (- (window-height) 1) 3) 2) num)))
-
-(defun edt-sect (num)
- "Move in current direction a full window.
-Accepts a positive prefix argument for the number windows to move."
- (interactive "p")
- (if (equal edt-direction-string edt-forward-string)
- (edt-sect-forward num)
- (edt-sect-backward num)))
-
-;;;
-;;; BEGINNING OF LINE
-;;;
-;;; EDT's beginning-of-line command is not affected by current
-;;; direction, for some unknown reason.
-
-(defun edt-beginning-of-line (num)
- "Move backward to next beginning of line mark.
-Accepts a positive prefix argument for the number of BOL marks to move."
- (interactive "p")
- (edt-check-prefix num)
- (if (bolp)
- (forward-line (* -1 num))
- (progn
- (setq num (1- num))
- (forward-line (* -1 num)))))
-
-;;;
-;;; EOL (End of Line)
-;;;
-
-(defun edt-end-of-line-forward (num)
- "Move forward to next end of line mark.
-Accepts a positive prefix argument for the number of EOL marks to move."
- (interactive "p")
- (edt-check-prefix num)
- (forward-char)
- (end-of-line num))
-
-(defun edt-end-of-line-backward (num)
- "Move backward to next end of line mark.
-Accepts a positive prefix argument for the number of EOL marks to move."
- (interactive "p")
- (edt-check-prefix num)
- (end-of-line (1- num)))
-
-(defun edt-end-of-line (num)
- "Move in current direction to next end of line mark.
-Accepts a positive prefix argument for the number of EOL marks to move."
- (interactive "p")
- (if (equal edt-direction-string edt-forward-string)
- (edt-end-of-line-forward num)
- (edt-end-of-line-backward num)))
-
-;;;
-;;; WORD
-;;;
-;;; This one is a tad messy. To emulate EDT's behavior everywhere in
-;;; the file (beginning of file, end of file, beginning of line, end
-;;; of line, etc.) it takes a bit of special handling.
-;;;
-;;; The variable edt-word-entities contains a list of characters which
-;;; are to be viewed as distinct words where ever they appear in the
-;;; buffer. This emulates the EDT line mode command SET ENTITY WORD.
-
-
-(defun edt-one-word-forward ()
- "Move forward to first character of next word."
- (interactive)
- (if (eobp)
- (error "End of buffer"))
- (if (eolp)
- (forward-char)
- (progn
- (if (memq (following-char) edt-word-entities)
- (forward-char)
- (while (and
- (not (eolp))
- (not (eobp))
- (not (eq ?\ (char-syntax (following-char))))
- (not (memq (following-char) edt-word-entities)))
- (forward-char)))
- (while (and
- (not (eolp))
- (not (eobp))
- (eq ?\ (char-syntax (following-char)))
- (not (memq (following-char) edt-word-entities)))
- (forward-char)))))
-
-(defun edt-one-word-backward ()
- "Move backward to first character of previous word."
- (interactive)
- (if (bobp)
- (error "Beginning of buffer"))
- (if (bolp)
- (backward-char)
- (progn
- (backward-char)
- (while (and
- (not (bolp))
- (not (bobp))
- (eq ?\ (char-syntax (following-char)))
- (not (memq (following-char) edt-word-entities)))
- (backward-char))
- (if (not (memq (following-char) edt-word-entities))
- (while (and
- (not (bolp))
- (not (bobp))
- (not (eq ?\ (char-syntax (preceding-char))))
- (not (memq (preceding-char) edt-word-entities)))
- (backward-char))))))
-
-(defun edt-word-forward (num)
- "Move forward to first character of next word.
-Accepts a positive prefix argument for the number of words to move."
- (interactive "p")
- (edt-check-prefix num)
- (while (> num 0)
- (edt-one-word-forward)
- (setq num (1- num))))
-
-(defun edt-word-backward (num)
- "Move backward to first character of previous word.
-Accepts a positive prefix argument for the number of words to move."
- (interactive "p")
- (edt-check-prefix num)
- (while (> num 0)
- (edt-one-word-backward)
- (setq num (1- num))))
-
-(defun edt-word (num)
- "Move in current direction to first character of next word.
-Accepts a positive prefix argument for the number of words to move."
- (interactive "p")
- (if (equal edt-direction-string edt-forward-string)
- (edt-word-forward num)
- (edt-word-backward num)))
-
-;;;
-;;; CHAR
-;;;
-
-(defun edt-character (num)
- "Move in current direction to next character.
-Accepts a positive prefix argument for the number of characters to move."
- (interactive "p")
- (edt-check-prefix num)
- (if (equal edt-direction-string edt-forward-string)
- (forward-char num)
- (backward-char num)))
-
-;;;
-;;; LINE
-;;;
-;;; When direction is set to BACKUP, LINE behaves just like BEGINNING
-;;; OF LINE in EDT. So edt-line-backward is not really needed as a
-;;; separate function.
-
-(defun edt-line-backward (num)
- "Move backward to next beginning of line mark.
-Accepts a positive prefix argument for the number of BOL marks to move."
- (interactive "p")
- (edt-beginning-of-line num))
-
-(defun edt-line-forward (num)
- "Move forward to next beginning of line mark.
-Accepts a positive prefix argument for the number of BOL marks to move."
- (interactive "p")
- (edt-check-prefix num)
- (forward-line num))
-
-(defun edt-line (num)
- "Move in current direction to next beginning of line mark.
-Accepts a positive prefix argument for the number of BOL marks to move."
- (interactive "p")
- (if (equal edt-direction-string edt-forward-string)
- (edt-line-forward num)
- (edt-line-backward num)))
-
-;;;
-;;; TOP
-;;;
-
-(defun edt-top ()
- "Move cursor to the beginning of buffer."
- (interactive)
- (goto-char (point-min)))
-
-;;;
-;;; BOTTOM
-;;;
-
-(defun edt-bottom ()
- "Move cursor to the end of buffer."
- (interactive)
- (goto-char (point-max))
- (edt-line-to-bottom-of-window))
-
-;;;
-;;; FIND
-;;;
-
-(defun edt-find-forward (&optional find)
- "Find first occurrence of a string in forward direction and save it."
- (interactive)
- (if (not find)
- (set 'search-last-string (read-string "Search forward: ")))
- (if (search-forward search-last-string)
- (search-backward search-last-string)))
-
-(defun edt-find-backward (&optional find)
- "Find first occurrence of a string in the backward direction and save it."
- (interactive)
- (if (not find)
- (set 'search-last-string (read-string "Search backward: ")))
- (search-backward search-last-string))
-
-(defun edt-find ()
- "Find first occurrence of string in current direction and save it."
- (interactive)
- (set 'search-last-string (read-string "Search: "))
- (if (equal edt-direction-string edt-forward-string)
- (edt-find-forward t)
- (edt-find-backward t)))
-
-
-;;;
-;;; FNDNXT
-;;;
-
-(defun edt-find-next-forward ()
- "Find next occurrence of a string in forward direction."
- (interactive)
- (forward-char 1)
- (if (search-forward search-last-string nil t)
- (search-backward search-last-string)
- (progn
- (backward-char 1)
- (error "Search failed: \"%s\"." search-last-string))))
-
-(defun edt-find-next-backward ()
- "Find next occurrence of a string in backward direction."
- (interactive)
- (if (eq (search-backward search-last-string nil t) nil)
- (progn
- (error "Search failed: \"%s\"." search-last-string))))
-
-(defun edt-find-next ()
- "Find next occurrence of a string in current direction."
- (interactive)
- (if (equal edt-direction-string edt-forward-string)
- (edt-find-next-forward)
- (edt-find-next-backward)))
-
-;;;
-;;; APPEND
-;;;
-
-(defun edt-append ()
- "Append this kill region to last killed region."
- (interactive "*")
- (edt-check-selection)
- (append-next-kill)
- (kill-region (mark) (point))
- (message "Selected text APPENDED to kill ring"))
-
-;;;
-;;; DEL L
-;;;
-
-(defun edt-delete-line (num)
- "Delete from cursor up to and including the end of line mark.
-Accepts a positive prefix argument for the number of lines to delete."
- (interactive "*p")
- (edt-check-prefix num)
- (let ((beg (point)))
- (forward-line num)
- (if (not (eq (preceding-char) ?\n))
- (insert "\n"))
- (setq edt-last-deleted-lines
- (buffer-substring beg (point)))
- (delete-region beg (point))))
-
-;;;
-;;; DEL EOL
-;;;
-
-(defun edt-delete-to-end-of-line (num)
- "Delete from cursor up to but excluding the end of line mark.
-Accepts a positive prefix argument for the number of lines to delete."
- (interactive "*p")
- (edt-check-prefix num)
- (let ((beg (point)))
- (forward-char 1)
- (end-of-line num)
- (setq edt-last-deleted-lines
- (buffer-substring beg (point)))
- (delete-region beg (point))))
-
-;;;
-;;; SELECT
-;;;
-
-(defun edt-select-mode (arg)
- "Turn EDT select mode off if ARG is nil; otherwise, turn EDT select mode on.
-In select mode, selected text is highlighted."
- (if arg
- (progn
- (make-local-variable 'edt-select-mode)
- (setq edt-select-mode 'edt-select-mode-text)
- (setq rect-start-point (window-point)))
- (progn
- (kill-local-variable 'edt-select-mode)))
- (force-mode-line-update))
-
-(defun edt-select ()
- "Set mark at cursor and start text selection."
- (interactive)
- (set-mark-command nil))
-
-(defun edt-reset ()
- "Cancel text selection."
- (interactive)
- (deactivate-mark))
-
-;;;
-;;; CUT
-;;;
-
-(defun edt-cut ()
- "Deletes selected text but copies to kill ring."
- (interactive "*")
- (edt-check-selection)
- (kill-region (mark) (point))
- (message "Selected text CUT to kill ring"))
-
-;;;
-;;; DELETE TO BEGINNING OF LINE
-;;;
-
-(defun edt-delete-to-beginning-of-line (num)
- "Delete from cursor to beginning of line.
-Accepts a positive prefix argument for the number of lines to delete."
- (interactive "*p")
- (edt-check-prefix num)
- (let ((beg (point)))
- (edt-beginning-of-line num)
- (setq edt-last-deleted-lines
- (buffer-substring (point) beg))
- (delete-region beg (point))))
-
-;;;
-;;; DEL W
-;;;
-
-(defun edt-delete-word (num)
- "Delete from cursor up to but excluding first character of next word.
-Accepts a positive prefix argument for the number of words to delete."
- (interactive "*p")
- (edt-check-prefix num)
- (let ((beg (point)))
- (edt-word-forward num)
- (setq edt-last-deleted-words (buffer-substring beg (point)))
- (delete-region beg (point))))
-
-;;;
-;;; DELETE TO BEGINNING OF WORD
-;;;
-
-(defun edt-delete-to-beginning-of-word (num)
- "Delete from cursor to beginning of word.
-Accepts a positive prefix argument for the number of words to delete."
- (interactive "*p")
- (edt-check-prefix num)
- (let ((beg (point)))
- (edt-word-backward num)
- (setq edt-last-deleted-words (buffer-substring (point) beg))
- (delete-region beg (point))))
-
-;;;
-;;; DEL C
-;;;
-
-(defun edt-delete-character (num)
- "Delete character under cursor.
-Accepts a positive prefix argument for the number of characters to delete."
- (interactive "*p")
- (edt-check-prefix num)
- (setq edt-last-deleted-chars
- (buffer-substring (point) (min (point-max) (+ (point) num))))
- (delete-region (point) (min (point-max) (+ (point) num))))
-
-;;;
-;;; DELETE CHAR
-;;;
-
-(defun edt-delete-previous-character (num)
- "Delete character in front of cursor.
-Accepts a positive prefix argument for the number of characters to delete."
- (interactive "*p")
- (edt-check-prefix num)
- (setq edt-last-deleted-chars
- (buffer-substring (max (point-min) (- (point) num)) (point)))
- (delete-region (max (point-min) (- (point) num)) (point)))
-
-;;;
-;;; UND L
-;;;
-
-(defun edt-undelete-line ()
- "Undelete previous deleted line(s)."
- (interactive "*")
- (point-to-register 1)
- (insert edt-last-deleted-lines)
- (register-to-point 1))
-
-;;;
-;;; UND W
-;;;
-
-(defun edt-undelete-word ()
- "Undelete previous deleted word(s)."
- (interactive "*")
- (point-to-register 1)
- (insert edt-last-deleted-words)
- (register-to-point 1))
-
-;;;
-;;; UND C
-;;;
-
-(defun edt-undelete-character ()
- "Undelete previous deleted character(s)."
- (interactive "*")
- (point-to-register 1)
- (insert edt-last-deleted-chars)
- (register-to-point 1))
-
-;;;
-;;; REPLACE
-;;;
-
-(defun edt-replace ()
- "Replace marked section with last CUT (killed) text."
- (interactive "*")
- (exchange-point-and-mark)
- (let ((beg (point)))
- (exchange-point-and-mark)
- (delete-region beg (point)))
- (yank))
-
-;;;
-;;; ADVANCE
-;;;
-
-(defun edt-advance ()
- "Set movement direction forward.
-Also, execute command specified if in Minibuffer."
- (interactive)
- (setq edt-direction-string edt-forward-string)
- (force-mode-line-update)
- (if (string-equal " *Minibuf"
- (substring (buffer-name) 0 (min (length (buffer-name)) 9)))
- (exit-minibuffer)))
-
-;;;
-;;; BACKUP
-;;;
-
-(defun edt-backup ()
- "Set movement direction backward.
-Also, execute command specified if in Minibuffer."
- (interactive)
- (setq edt-direction-string edt-backward-string)
- (force-mode-line-update)
- (if (string-equal " *Minibuf"
- (substring (buffer-name) 0 (min (length (buffer-name)) 9)))
- (exit-minibuffer)))
-
-;;;
-;;; CHNGCASE
-;;;
-;; This function is based upon Jeff Kowalski's case-flip function in his
-;; tpu.el.
-
-(defun edt-change-case (num)
- "Change the case of specified characters.
-If text selection IS active, then characters between the cursor and mark are
-changed. If text selection is NOT active, there are two cases. First, if the
-current direction is ADVANCE, then the prefix number of character(s) under and
-following cursor are changed. Second, if the current direction is BACKUP, then
-the prefix number of character(s) before the cursor are changed. Accepts a
-positive prefix for the number of characters to change, but the prefix is
-ignored if text selection is active."
- (interactive "*p")
- (edt-check-prefix num)
- (if edt-select-mode
- (let ((end (max (mark) (point)))
- (point-save (point)))
- (goto-char (min (point) (mark)))
- (while (not (eq (point) end))
- (funcall (if (<= ?a (following-char))
- 'upcase-region 'downcase-region)
- (point) (1+ (point)))
- (forward-char 1))
- (goto-char point-save))
- (progn
- (if (string= edt-direction-string edt-backward-string)
- (backward-char num))
- (while (> num 0)
- (funcall (if (<= ?a (following-char))
- 'upcase-region 'downcase-region)
- (point) (1+ (point)))
- (forward-char 1)
- (setq num (1- num))))))
-
-;;;
-;;; DEFINE KEY
-;;;
-
-(defun edt-define-key ()
- "Assign an interactively-callable function to a specified key sequence.
-The current key definition is saved in edt-last-replaced-key-definition.
-Use edt-restore-key to restore last replaced key definition."
- (interactive)
- (let (edt-function
- edt-key-definition-string)
- (setq edt-key-definition-string
- (read-key-sequence "Press the key to be defined: "))
- (if (string-equal "\C-m" edt-key-definition-string)
- (message "Key not defined")
- (progn
- (setq edt-function (read-command "Enter command name: "))
- (if (string-equal "" edt-function)
- (message "Key not defined")
- (progn
- (setq edt-last-replaced-key-definition
- (lookup-key (current-global-map) edt-key-definition-string))
- (define-key (current-global-map)
- edt-key-definition-string edt-function)))))))
-
-;;;
-;;; FORM FEED INSERT
-;;;
-
-(defun edt-form-feed-insert (num)
- "Insert form feed character at cursor position.
-Accepts a positive prefix argument for the number of form feeds to insert."
- (interactive "*p")
- (edt-check-prefix num)
- (while (> num 0)
- (insert ?\f)
- (setq num (1- num))))
-
-;;;
-;;; TAB INSERT
-;;;
-
-(defun edt-tab-insert (num)
- "Insert tab character at cursor position.
-Accepts a positive prefix argument for the number of tabs to insert."
- (interactive "*p")
- (edt-check-prefix num)
- (while (> num 0)
- (insert ?\t)
- (setq num (1- num))))
-
-;;;
-;;; Check Prefix
-;;;
-
-(defun edt-check-prefix (num)
- "Indicate error if prefix is not positive."
- (if (<= num 0)
- (error "Prefix must be positive")))
-
-;;;
-;;; Check Selection
-;;;
-
-(defun edt-check-selection ()
- "Indicate error if EDT selection is not active."
- (if (not edt-select-mode)
- (error "Selection NOT active")))
-
-;;;;
-;;;; ENHANCEMENTS AND ADDITIONS FOR EDT KEYPAD MODE
-;;;;
-
-;;;
-;;; Several enhancements and additions to EDT keypad mode commands are
-;;; provided here. Some of these have been motivated by similar
-;;; TPU/EVE and EVE-Plus commands. Others are new.
-
-;;;
-;;; CHANGE DIRECTION
-;;;
-
-(defun edt-change-direction ()
- "Toggle movement direction."
- (interactive)
- (if (equal edt-direction-string edt-forward-string)
- (edt-backup)
- (edt-advance)))
-
-;;;
-;;; TOGGLE SELECT
-;;;
-
-(defun edt-toggle-select ()
- "Toggle to start (or cancel) text selection."
- (interactive)
- (if edt-select-mode
- (edt-reset)
- (edt-select)))
-
-;;;
-;;; SENTENCE
-;;;
-
-(defun edt-sentence-forward (num)
- "Move forward to start of next sentence.
-Accepts a positive prefix argument for the number of sentences to move."
- (interactive "p")
- (edt-check-prefix num)
- (if (eobp)
- (progn
- (error "End of buffer"))
- (progn
- (forward-sentence num)
- (edt-one-word-forward))))
-
-(defun edt-sentence-backward (num)
- "Move backward to next sentence beginning.
-Accepts a positive prefix argument for the number of sentences to move."
- (interactive "p")
- (edt-check-prefix num)
- (if (eobp)
- (progn
- (error "End of buffer"))
- (backward-sentence num)))
-
-(defun edt-sentence (num)
- "Move in current direction to next sentence.
-Accepts a positive prefix argument for the number of sentences to move."
- (interactive "p")
- (if (equal edt-direction-string edt-forward-string)
- (edt-sentence-forward num)
- (edt-sentence-backward num)))
-
-;;;
-;;; PARAGRAPH
-;;;
-
-(defun edt-paragraph-forward (num)
- "Move forward to beginning of paragraph.
-Accepts a positive prefix argument for the number of paragraphs to move."
- (interactive "p")
- (edt-check-prefix num)
- (while (> num 0)
- (next-line 1)
- (forward-paragraph)
- (previous-line 1)
- (if (eolp)
- (next-line 1))
- (setq num (1- num))))
-
-(defun edt-paragraph-backward (num)
- "Move backward to beginning of paragraph.
-Accepts a positive prefix argument for the number of paragraphs to move."
- (interactive "p")
- (edt-check-prefix num)
- (while (> num 0)
- (backward-paragraph)
- (previous-line 1)
- (if (eolp) (next-line 1))
- (setq num (1- num))))
-
-(defun edt-paragraph (num)
- "Move in current direction to next paragraph.
-Accepts a positive prefix argument for the number of paragraph to move."
- (interactive "p")
- (if (equal edt-direction-string edt-forward-string)
- (edt-paragraph-forward num)
- (edt-paragraph-backward num)))
-
-;;;
-;;; RESTORE KEY
-;;;
-
-(defun edt-restore-key ()
- "Restore last replaced key definition.
-Definition is stored in edt-last-replaced-key-definition."
- (interactive)
- (if edt-last-replaced-key-definition
- (progn
- (let (edt-key-definition-string)
- (set 'edt-key-definition-string
- (read-key-sequence "Press the key to be restored: "))
- (if (string-equal "\C-m" edt-key-definition-string)
- (message "Key not restored")
- (define-key (current-global-map)
- edt-key-definition-string edt-last-replaced-key-definition))))
- (error "No replaced key definition to restore!")))
-
-;;;
-;;; WINDOW TOP
-;;;
-
-(defun edt-window-top ()
- "Move the cursor to the top of the window."
- (interactive)
- (let ((start-column (current-column)))
- (move-to-window-line 0)
- (move-to-column start-column)))
-
-;;;
-;;; WINDOW BOTTOM
-;;;
-
-(defun edt-window-bottom ()
- "Move the cursor to the bottom of the window."
- (interactive)
- (let ((start-column (current-column)))
- (move-to-window-line (- (window-height) 2))
- (move-to-column start-column)))
-
-;;;
-;;; SCROLL WINDOW LINE
-;;;
-
-(defun edt-scroll-window-forward-line ()
- "Move window forward one line leaving cursor at position in window."
- (interactive)
- (scroll-up 1))
-
-(defun edt-scroll-window-backward-line ()
- "Move window backward one line leaving cursor at position in window."
- (interactive)
- (scroll-down 1))
-
-(defun edt-scroll-line ()
- "Move window one line in current direction."
- (interactive)
- (if (equal edt-direction-string edt-forward-string)
- (edt-scroll-window-forward-line)
- (edt-scroll-window-backward-line)))
-
-;;;
-;;; SCROLL WINDOW
-;;;
-;;; Scroll a window (less one line) at a time. Leave cursor in center of
-;;; window.
-
-(defun edt-scroll-window-forward (num)
- "Scroll forward one window in buffer, less one line.
-Accepts a positive prefix argument for the number of windows to move."
- (interactive "p")
- (edt-check-prefix num)
- (scroll-up (- (* (window-height) num) 2))
- (edt-line-forward (/ (- (window-height) 1) 2)))
-
-(defun edt-scroll-window-backward (num)
- "Scroll backward one window in buffer, less one line.
-Accepts a positive prefix argument for the number of windows to move."
- (interactive "p")
- (edt-check-prefix num)
- (scroll-down (- (* (window-height) num) 2))
- (edt-line-backward (/ (- (window-height) 1) 2)))
-
-(defun edt-scroll-window (num)
- "Scroll one window in buffer, less one line, in current direction.
-Accepts a positive prefix argument for the number windows to move."
- (interactive "p")
- (if (equal edt-direction-string edt-forward-string)
- (edt-scroll-window-forward num)
- (edt-scroll-window-backward num)))
-
-;;;
-;;; LINE TO BOTTOM OF WINDOW
-;;;
-
-(defun edt-line-to-bottom-of-window ()
- "Move the current line to the bottom of the window."
- (interactive)
- (recenter -1))
-
-;;;
-;;; LINE TO TOP OF WINDOW
-;;;
-
-(defun edt-line-to-top-of-window ()
- "Move the current line to the top of the window."
- (interactive)
- (recenter 0))
-
-;;;
-;;; LINE TO MIDDLE OF WINDOW
-;;;
-
-(defun edt-line-to-middle-of-window ()
- "Move window so line with cursor is in the middle of the window."
- (interactive)
- (recenter '(4)))
-
-;;;
-;;; GOTO PERCENTAGE
-;;;
-
-(defun edt-goto-percentage (num)
- "Move to specified percentage in buffer from top of buffer."
- (interactive "NGoto-percentage: ")
- (if (or (> num 100) (< num 0))
- (error "Percentage %d out of range 0 < percent < 100" num)
- (goto-char (/ (* (point-max) num) 100))))
-
-;;;
-;;; FILL REGION
-;;;
-
-(defun edt-fill-region ()
- "Fill selected text."
- (interactive "*")
- (edt-check-selection)
- (fill-region (point) (mark)))
-
-;;;
-;;; INDENT OR FILL REGION
-;;;
-
-(defun edt-indent-or-fill-region ()
- "Fill region in text modes, indent region in programming language modes."
- (interactive "*")
- (if (string= paragraph-start "$\\|\f")
- (indent-region (point) (mark) nil)
- (fill-region (point) (mark))))
-
-;;;
-;;; MARK SECTION WISELY
-;;;
-
-(defun edt-mark-section-wisely ()
- "Mark the section in a manner consistent with the major-mode.
-Uses mark-defun for emacs-lisp and lisp,
-mark-c-function for C,
-mark-fortran-subsystem for fortran,
-and mark-paragraph for other modes."
- (interactive)
- (if edt-select-mode
- (progn
- (edt-reset))
- (progn
- (cond ((or (eq major-mode 'emacs-lisp-mode)
- (eq major-mode 'lisp-mode))
- (mark-defun)
- (message "Lisp defun selected"))
- ((eq major-mode 'c-mode)
- (mark-c-function)
- (message "C function selected"))
- ((eq major-mode 'fortran-mode)
- (mark-fortran-subprogram)
- (message "Fortran subprogram selected"))
- (t (mark-paragraph)
- (message "Paragraph selected"))))))
-
-;;;
-;;; COPY
-;;;
-
-(defun edt-copy ()
- "Copy selected region to kill ring, but don't delete it!"
- (interactive)
- (edt-check-selection)
- (copy-region-as-kill (mark) (point))
- (edt-reset)
- (message "Selected text COPIED to kill ring"))
-
-;;;
-;;; CUT or COPY
-;;;
-
-(defun edt-cut-or-copy ()
- "Cuts (or copies) selected text to kill ring.
-Cuts selected text if buffer-read-only is nil.
-Copies selected text if buffer-read-only is t."
- (interactive)
- (if buffer-read-only
- (edt-copy)
- (edt-cut)))
-
-;;;
-;;; DELETE ENTIRE LINE
-;;;
-
-(defun edt-delete-entire-line ()
- "Delete entire line regardless of cursor position in the line."
- (interactive "*")
- (beginning-of-line)
- (edt-delete-line 1))
-
-;;;
-;;; DUPLICATE LINE
-;;;
-
-(defun edt-duplicate-line (num)
- "Duplicate a line of text.
-Accepts a positive prefix argument for the number times to duplicate the line."
- (interactive "*p")
- (edt-check-prefix num)
- (let ((old-column (current-column))
- (count num))
- (edt-delete-entire-line)
- (edt-undelete-line)
- (while (> count 0)
- (edt-undelete-line)
- (setq count (1- count)))
- (edt-line-forward num)
- (move-to-column old-column)))
-
-;;;
-;;; DUPLICATE WORD
-;;;
-
-(defun edt-duplicate-word()
- "Duplicate word (or rest of word) found directly above cursor, if any."
- (interactive "*")
- (let ((start (point))
- (start-column (current-column)))
- (forward-line -1)
- (move-to-column start-column)
- (if (and (not (equal start (point)))
- (not (eolp)))
- (progn
- (if (and (equal ?\t (preceding-char))
- (< start-column (current-column)))
- (backward-char))
- (let ((beg (point)))
- (edt-one-word-forward)
- (setq edt-last-copied-word (buffer-substring beg (point))))
- (forward-line)
- (move-to-column start-column)
- (insert edt-last-copied-word))
- (progn
- (if (not (equal start (point)))
- (forward-line))
- (move-to-column start-column)
- (error "Nothing to duplicate!")))))
-
-;;;
-;;; KEY NOT ASSIGNED
-;;;
-
-(defun edt-key-not-assigned ()
- "Displays message that key has not been assigned to a function."
- (interactive)
- (error "Key not assigned"))
-
-;;;
-;;; TOGGLE CAPITALIZATION OF WORD
-;;;
-
-(defun edt-toggle-capitalization-of-word ()
- "Toggle the capitalization of the current word and move forward to next."
- (interactive "*")
- (edt-one-word-forward)
- (edt-one-word-backward)
- (edt-change-case 1)
- (edt-one-word-backward)
- (edt-one-word-forward))
-
-;;;
-;;; ELIMINATE ALL TABS
-;;;
-
-(defun edt-eliminate-all-tabs ()
- "Convert all tabs to spaces in the entire buffer."
- (interactive "*")
- (untabify (point-min) (point-max))
- (message "TABS converted to SPACES"))
-
-;;;
-;;; DISPLAY THE TIME
-;;;
-
-(defun edt-display-the-time ()
- "Display the current time."
- (interactive)
- (set 'time-string (current-time-string))
- (message "%s" time-string))
-
-;;;
-;;; LEARN
-;;;
-
-(defun edt-learn ()
- "Learn a sequence of key strokes to bind to a key."
- (interactive)
- (if (eq defining-kbd-macro t)
- (edt-remember)
- (start-kbd-macro nil)))
-
-;;;
-;;; REMEMBER
-;;;
-
-(defun edt-remember ()
- "Store the sequence of key strokes started by edt-learn to a key."
- (interactive)
- (if (eq defining-kbd-macro nil)
- (error "Nothing to remember!")
- (progn
- (end-kbd-macro nil)
- (let (edt-key-definition-string)
- (set 'edt-key-definition-string
- (read-key-sequence "Enter key for binding: "))
- (if (string-equal "\C-m" edt-key-definition-string)
- (message "Key sequence not remembered")
- (progn
- (set 'edt-learn-macro-count (+ edt-learn-macro-count 1))
- (setq edt-last-replaced-key-definition
- (lookup-key (current-global-map)
- edt-key-definition-string))
- (define-key (current-global-map) edt-key-definition-string
- (name-last-kbd-macro
- (intern (concat "last-learned-sequence-"
- (int-to-string edt-learn-macro-count)))))))))))
-
-;;;
-;;; EXIT
-;;;
-
-(defun edt-exit ()
- "Save current buffer, ask to save other buffers, and then exit Emacs."
- (interactive)
- (save-buffer)
- (save-buffers-kill-emacs))
-
-;;;
-;;; QUIT
-;;;
-
-(defun edt-quit ()
- "Quit Emacs without saving changes."
- (interactive)
- (kill-emacs))
-
-;;;
-;;; SPLIT WINDOW
-;;;
-
-(defun edt-split-window ()
- "Split current window and place cursor in the new window."
- (interactive)
- (split-window)
- (other-window 1))
-
-;;;
-;;; COPY RECTANGLE
-;;;
-
-(defun edt-copy-rectangle ()
- "Copy a rectangle of text between mark and cursor to register."
- (interactive)
- (edt-check-selection)
- (copy-rectangle-to-register 3 (region-beginning) (region-end) nil)
- (edt-reset)
- (message "Selected rectangle COPIED to register"))
-
-;;;
-;;; CUT RECTANGLE
-;;;
-
-(defun edt-cut-rectangle-overstrike-mode ()
- "Cut a rectangle of text between mark and cursor to register.
-Replace cut characters with spaces and moving cursor back to
-upper left corner."
- (interactive "*")
- (edt-check-selection)
- (setq edt-rect-start-point (region-beginning))
- (picture-clear-rectangle-to-register (region-beginning) (region-end) 3)
- (set-window-point (get-buffer-window (window-buffer)) edt-rect-start-point)
- (message "Selected rectangle CUT to register"))
-
-(defun edt-cut-rectangle-insert-mode ()
- "Cut a rectangle of text between mark and cursor to register.
-Move cursor back to upper left corner."
- (interactive "*")
- (edt-check-selection)
- (setq edt-rect-start-point (region-beginning))
- (picture-clear-rectangle-to-register (region-beginning) (region-end) 3 t)
- (fixup-whitespace)
- (set-window-point (get-buffer-window (window-buffer)) edt-rect-start-point)
- (message "Selected rectangle CUT to register"))
-
-(defun edt-cut-rectangle ()
- "Cut a rectangular region of text to register.
-If overwrite mode is active, cut text is replaced with whitespace."
- (interactive "*")
- (if overwrite-mode
- (edt-cut-rectangle-overstrike-mode)
- (edt-cut-rectangle-insert-mode)))
-
-;;;
-;;; PASTE RECTANGLE
-;;;
-
-(defun edt-paste-rectangle-overstrike-mode ()
- "Paste a rectangular region of text from register, replacing text at cursor."
- (interactive "*")
- (picture-yank-rectangle-from-register 3))
-
-(defun edt-paste-rectangle-insert-mode ()
- "Paste previously deleted rectangular region, inserting text at cursor."
- (interactive "*")
- (picture-yank-rectangle-from-register 3 t))
-
-(defun edt-paste-rectangle ()
- "Paste a rectangular region of text.
-If overwrite mode is active, existing text is replace with text from register."
- (interactive)
- (if overwrite-mode
- (edt-paste-rectangle-overstrike-mode)
- (edt-paste-rectangle-insert-mode)))
-
-;;;
-;;; DOWNCASE REGION
-;;;
-
-(defun edt-lowercase ()
- "Change specified characters to lower case.
-If text selection IS active, then characters between the cursor and
-mark are changed. If text selection is NOT active, there are two
-situations. If the current direction is ADVANCE, then the word under
-the cursor is changed to lower case and the cursor is moved to rest at
-the beginning of the next word. If the current direction is BACKUP,
-the word prior to the word under the cursor is changed to lower case
-and the cursor is left to rest at the beginning of that word."
- (interactive "*")
- (if edt-select-mode
- (progn
- (downcase-region (mark) (point)))
- (progn
- ;; Move to beginning of current word.
- (if (and
- (not (bobp))
- (not (eobp))
- (not (bolp))
- (not (eolp))
- (not (eq ?\ (char-syntax (preceding-char))))
- (not (memq (preceding-char) edt-word-entities))
- (not (memq (following-char) edt-word-entities)))
- (edt-one-word-backward))
- (if (equal edt-direction-string edt-backward-string)
- (edt-one-word-backward))
- (let ((beg (point)))
- (edt-one-word-forward)
- (downcase-region beg (point)))
- (if (equal edt-direction-string edt-backward-string)
- (edt-one-word-backward)))))
-
-;;;
-;;; UPCASE REGION
-;;;
-
-(defun edt-uppercase ()
- "Change specified characters to upper case.
-If text selection IS active, then characters between the cursor and
-mark are changed. If text selection is NOT active, there are two
-situations. If the current direction is ADVANCE, then the word under
-the cursor is changed to upper case and the cursor is moved to rest at
-the beginning of the next word. If the current direction is BACKUP,
-the word prior to the word under the cursor is changed to upper case
-and the cursor is left to rest at the beginning of that word."
- (interactive "*")
- (if edt-select-mode
- (progn
- (upcase-region (mark) (point)))
- (progn
- ;; Move to beginning of current word.
- (if (and
- (not (bobp))
- (not (eobp))
- (not (bolp))
- (not (eolp))
- (not (eq ?\ (char-syntax (preceding-char))))
- (not (memq (preceding-char) edt-word-entities))
- (not (memq (following-char) edt-word-entities)))
- (edt-one-word-backward))
- (if (equal edt-direction-string edt-backward-string)
- (edt-one-word-backward))
- (let ((beg (point)))
- (edt-one-word-forward)
- (upcase-region beg (point)))
- (if (equal edt-direction-string edt-backward-string)
- (edt-one-word-backward)))))
-
-
-;;;
-;;; INITIALIZATION COMMANDS.
-;;;
-
-;;;
-;;; Emacs version 19 X-windows key definition support
-;;;
-(defvar edt-last-answer nil
- "Most recent response to edt-y-or-n-p.")
-
-(defun edt-y-or-n-p (prompt &optional not-yes)
- "Prompt for a y or n answer with positive default.
-Optional second argument NOT-YES changes default to negative.
-Like emacs y-or-n-p, also accepts space as y and DEL as n."
- (message "%s[%s]" prompt (if not-yes "n" "y"))
- (let ((doit t))
- (while doit
- (setq doit nil)
- (let ((ans (read-char)))
- (cond ((or (= ans ?y) (= ans ?Y) (= ans ?\ ))
- (setq edt-last-answer t))
- ((or (= ans ?n) (= ans ?N) (= ans ?\C-?))
- (setq edt-last-answer nil))
- ((= ans ?\r) (setq edt-last-answer (not not-yes)))
- (t
- (setq doit t) (beep)
- (message "Please answer y or n. %s[%s]"
- prompt (if not-yes "n" "y")))))))
- edt-last-answer)
-
-(defun edt-load-xkeys (file)
- "Load the EDT X-windows key definitions FILE.
-If FILE is nil, try to load a default file. The default file names are
-~/.edt-lucid-keys for Lucid emacs, and ~/.edt-gnu-keys for GNU emacs."
- (interactive "fX key definition file: ")
- (cond (file
- (setq file (expand-file-name file)))
- (edt-xkeys-file
- (setq file (expand-file-name edt-xkeys-file)))
- (edt-gnu-emacs19-p
- (setq file (expand-file-name "~/.edt-gnu-keys")))
- (edt-lucid-emacs19-p
- (setq file (expand-file-name "~/.edt-lucid-keys"))))
- (cond ((file-readable-p file)
- (load-file file))
- (t
- (switch-to-buffer "*scratch*")
- (erase-buffer)
- (insert "
-
- Ack!! You're running the Enhanced EDT Emulation under X-windows
- without loading an EDT X key definition file. To create an EDT X
- key definition file, run the edt-mapper.el program. But ONLY run
- it from an Emacs loaded without any of your own customizations
- found in your .emacs file, etc. Some user customization confuse
- the edt-mapper function. To do this, you need to invoke Emacs
- as follows:
-
- emacs -q -l edt-mapper.el
-
- The file edt-mapper.el includes these same directions on how to
- use it! Perhaps it's lying around here someplace. \n ")
- (let ((file "edt-mapper.el")
- (found nil)
- (path nil)
- (search-list (append (list (expand-file-name ".")) load-path)))
- (while (and (not found) search-list)
- (setq path (concat (car search-list)
- (if (string-match "/$" (car search-list)) "" "/")
- file))
- (if (and (file-exists-p path) (not (file-directory-p path)))
- (setq found t))
- (setq search-list (cdr search-list)))
- (cond (found
- (insert (format
- "Ah yes, there it is, in \n\n %s \n\n" path))
- (if (edt-y-or-n-p "Do you want to run it now? ")
- (load-file path)
- (error "EDT Emulation not configured.")))
- (t
- (insert "Nope, I can't seem to find it. :-(\n\n")
- (sit-for 20)
- (error "EDT Emulation not configured.")))))))
-
-;;;###autoload
-(defun edt-emulation-on ()
- "Turn on EDT Emulation."
- (interactive)
- ;; If using MS-DOS, need to load edt-pc.el
- (if (eq system-type 'ms-dos)
- (setq edt-term "pc")
- (setq edt-term (getenv "TERM")))
- ;; All DEC VT series terminals are supported by loading edt-vt100.el
- (if (string-equal "vt" (substring edt-term 0 (min (length edt-term) 2)))
- (setq edt-term "vt100"))
- ;; Load EDT terminal specific configuration file.
- (let ((term edt-term)
- hyphend)
- (while (and term
- (not (load (concat "edt-" 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)))
- ;; Override terminal-specific file if running X Windows. X Windows support
- ;; is handled differently in edt-load-xkeys
- (if (eq window-system 'x)
- (edt-load-xkeys nil)
- (if (null term)
- (error "Unable to load EDT terminal specific file for %s" edt-term)))
- (setq edt-term term))
- (setq edt-orig-transient-mark-mode transient-mark-mode)
- (add-hook 'activate-mark-hook
- (function
- (lambda ()
- (edt-select-mode t))))
- (add-hook 'deactivate-mark-hook
- (function
- (lambda ()
- (edt-select-mode nil))))
- (if (load "edt-user" t t)
- (edt-user-emulation-setup)
- (edt-default-emulation-setup)))
-
-(defun edt-emulation-off()
- "Select original global key bindings, disabling EDT Emulation."
- (interactive)
- (use-global-map global-map)
- (if (not edt-keep-current-page-delimiter)
- (setq page-delimiter edt-orig-page-delimiter))
- (setq edt-direction-string "")
- (setq edt-select-mode-text nil)
- (edt-reset)
- (force-mode-line-update t)
- (setq transient-mark-mode edt-orig-transient-mark-mode)
- (message "Original key bindings restored; EDT Emulation disabled"))
-
-(defun edt-default-emulation-setup (&optional user-setup)
- "Setup emulation of DEC's EDT editor."
- ;; Setup default EDT global map by copying global map bindings.
- ;; This preserves ESC and C-x prefix bindings and other bindings we
- ;; wish to retain in EDT emulation mode keymaps. It also permits
- ;; customization of these bindings in the EDT global maps without
- ;; disturbing the original bindings in global-map.
- (fset 'edt-default-ESC-prefix (copy-keymap 'ESC-prefix))
- (setq edt-default-global-map (copy-keymap (current-global-map)))
- (define-key edt-default-global-map "\e" 'edt-default-ESC-prefix)
- (define-prefix-command 'edt-default-gold-map)
- (edt-setup-default-bindings)
- ;; If terminal has additional function keys, the terminal-specific
- ;; initialization file can assign bindings to them via the optional
- ;; function edt-setup-extra-default-bindings.
- (if (fboundp 'edt-setup-extra-default-bindings)
- (edt-setup-extra-default-bindings))
- ;; Variable needed by edt-learn.
- (setq edt-learn-macro-count 0)
- ;; Display EDT text selection active within the mode line
- (or (assq 'edt-select-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(edt-select-mode edt-select-mode) minor-mode-alist)))
- ;; Display EDT direction of motion within the mode line
- (or (assq 'edt-direction-string minor-mode-alist)
- (setq minor-mode-alist
- (cons
- '(edt-direction-string edt-direction-string) minor-mode-alist)))
- (if user-setup
- (progn
- (setq edt-user-map-configured t)
- (fset 'edt-emulation-on (symbol-function 'edt-select-user-global-map)))
- (progn
- (fset 'edt-emulation-on (symbol-function 'edt-select-default-global-map))
- (edt-select-default-global-map))))
-
-(defun edt-user-emulation-setup ()
- "Setup user custom emulation of DEC's EDT editor."
- ;; Initialize EDT default bindings.
- (edt-default-emulation-setup t)
- ;; Setup user EDT global map by copying default EDT global map bindings.
- (fset 'edt-user-ESC-prefix (copy-keymap 'edt-default-ESC-prefix))
- (setq edt-user-global-map (copy-keymap edt-default-global-map))
- (define-key edt-user-global-map "\e" 'edt-user-ESC-prefix)
- ;; If terminal has additional function keys, the user's initialization
- ;; file can assign bindings to them via the optional
- ;; function edt-setup-extra-default-bindings.
- (define-prefix-command 'edt-user-gold-map)
- (fset 'edt-user-gold-map (copy-keymap 'edt-default-gold-map))
- (edt-setup-user-bindings)
- (edt-select-user-global-map))
-
-(defun edt-select-default-global-map()
- "Select default EDT emulation key bindings."
- (interactive)
- (transient-mark-mode 1)
- (use-global-map edt-default-global-map)
- (if (not edt-keep-current-page-delimiter)
- (progn
- (setq edt-orig-page-delimiter page-delimiter)
- (setq page-delimiter "\f")))
- (setq edt-default-map-active t)
- (edt-advance)
- (setq edt-select-mode-text 'edt-select-mode-string)
- (edt-reset)
- (message "Default EDT keymap active"))
-
-(defun edt-select-user-global-map()
- "Select user EDT emulation custom key bindings."
- (interactive)
- (if edt-user-map-configured
- (progn
- (transient-mark-mode 1)
- (use-global-map edt-user-global-map)
- (if (not edt-keep-current-page-delimiter)
- (progn
- (setq edt-orig-page-delimiter page-delimiter)
- (setq page-delimiter "\f")))
- (setq edt-default-map-active nil)
- (edt-advance)
- (setq edt-select-mode-text 'edt-select-mode-string)
- (edt-reset)
- (message "User EDT custom keymap active"))
- (error "User EDT custom keymap NOT configured!")))
-
-(defun edt-switch-global-maps ()
- "Toggle between default EDT keymap and user EDT keymap."
- (interactive)
- (if edt-default-map-active
- (edt-select-user-global-map)
- (edt-select-default-global-map)))
-
-;; There are three key binding functions needed: one for standard keys
-;; (used to bind control keys, primarily), one for Gold sequences of
-;; standard keys, and one for function keys.
-
-(defun edt-bind-gold-key (key gold-binding &optional default)
- "Binds commands to a gold key sequence in the EDT Emulator."
- (if default
- (define-key 'edt-default-gold-map key gold-binding)
- (define-key 'edt-user-gold-map key gold-binding)))
-
-(defun edt-bind-standard-key (key gold-binding &optional default)
- "Bind commands to a gold key sequence in the default EDT keymap."
- (if default
- (define-key edt-default-global-map key gold-binding)
- (define-key edt-user-global-map key gold-binding)))
-
-(defun edt-bind-function-key
- (function-key binding gold-binding &optional default)
- "Binds function keys in the EDT Emulator."
- (catch 'edt-key-not-supported
- (let ((key-vector (cdr (assoc function-key *EDT-keys*))))
- (if (stringp key-vector)
- (throw 'edt-key-not-supported t))
- (if (not (null key-vector))
- (progn
- (if default
- (progn
- (define-key edt-default-global-map key-vector binding)
- (define-key 'edt-default-gold-map key-vector gold-binding))
- (progn
- (define-key edt-user-global-map key-vector binding)
- (define-key 'edt-user-gold-map key-vector gold-binding))))
- (error "%s is not a legal function key name" function-key)))))
-
-(defun edt-setup-default-bindings ()
- "Assigns default EDT Emulation keyboard bindings."
-
- ;; Function Key Bindings: Regular and GOLD.
-
- ;; VT100/VT200/VT300 PF1 (GOLD), PF2, PF3, PF4 Keys
- (edt-bind-function-key "PF1" 'edt-default-gold-map 'edt-mark-section-wisely t)
- (edt-bind-function-key "PF2" 'edt-electric-keypad-help 'describe-function t)
- (edt-bind-function-key "PF3" 'edt-find-next 'edt-find t)
- (edt-bind-function-key "PF4" 'edt-delete-line 'edt-undelete-line t)
-
- ;; VT100/VT200/VT300 Arrow Keys
- (edt-bind-function-key "UP" 'previous-line 'edt-window-top t)
- (edt-bind-function-key "DOWN" 'next-line 'edt-window-bottom t)
- (edt-bind-function-key "LEFT" 'backward-char 'edt-sentence-backward t)
- (edt-bind-function-key "RIGHT" 'forward-char 'edt-sentence-forward t)
-
- ;; VT100/VT200/VT300 Keypad Keys
- (edt-bind-function-key "KP0" 'edt-line 'open-line t)
- (edt-bind-function-key "KP1" 'edt-word 'edt-change-case t)
- (edt-bind-function-key "KP2" 'edt-end-of-line 'edt-delete-to-end-of-line t)
- (edt-bind-function-key "KP3" 'edt-character 'quoted-insert t)
- (edt-bind-function-key "KP4" 'edt-advance 'edt-bottom t)
- (edt-bind-function-key "KP5" 'edt-backup 'edt-top t)
- (edt-bind-function-key "KP6" 'edt-cut 'yank t)
- (edt-bind-function-key "KP7" 'edt-page 'execute-extended-command t)
- (edt-bind-function-key "KP8" 'edt-sect 'edt-fill-region t)
- (edt-bind-function-key "KP9" 'edt-append 'edt-replace t)
- (edt-bind-function-key "KP-" 'edt-delete-word 'edt-undelete-word t)
- (edt-bind-function-key "KP," 'edt-delete-character 'edt-undelete-character t)
- (edt-bind-function-key "KPP" 'edt-select 'edt-reset t)
- (edt-bind-function-key "KPE" 'other-window 'query-replace t)
-
- ;; VT200/VT300 Function Keys
- ;; (F1 through F5, on the VT220, are not programmable, so we skip
- ;; making default bindings to those keys.
- (edt-bind-function-key "FIND" 'edt-find-next 'edt-find t)
- (edt-bind-function-key "INSERT" 'yank 'edt-key-not-assigned t)
- (edt-bind-function-key "REMOVE" 'edt-cut 'edt-copy t)
- (edt-bind-function-key "SELECT" 'edt-toggle-select 'edt-key-not-assigned t)
- (edt-bind-function-key "NEXT" 'edt-sect-forward 'edt-key-not-assigned t)
- (edt-bind-function-key "PREVIOUS" 'edt-sect-backward 'edt-key-not-assigned t)
- (edt-bind-function-key "F6" 'edt-key-not-assigned 'edt-key-not-assigned t)
- (edt-bind-function-key "F7" 'edt-copy-rectangle 'edt-key-not-assigned t)
- (edt-bind-function-key "F8"
- 'edt-cut-rectangle-overstrike-mode 'edt-paste-rectangle-overstrike-mode t)
- (edt-bind-function-key "F9"
- 'edt-cut-rectangle-insert-mode 'edt-paste-rectangle-insert-mode t)
- (edt-bind-function-key "F10" 'edt-cut-rectangle 'edt-paste-rectangle t)
- ;; Under X, the F11 key can be bound. If using a VT-200 or higher terminal,
- ;; the default emacs terminal support causes the VT F11 key to seem as if it
- ;; is an ESC key when in emacs.
- (edt-bind-function-key "F11"
- 'edt-key-not-assigned 'edt-key-not-assigned t)
- (edt-bind-function-key "F12"
- 'edt-beginning-of-line 'delete-other-windows t) ;BS
- (edt-bind-function-key "F13"
- 'edt-delete-to-beginning-of-word 'edt-key-not-assigned t) ;LF
- (edt-bind-function-key "F14" 'edt-key-not-assigned 'edt-key-not-assigned t)
- (edt-bind-function-key "HELP" 'edt-electric-keypad-help 'edt-key-not-assigned t)
- (edt-bind-function-key "DO" 'execute-extended-command 'edt-key-not-assigned t)
- (edt-bind-function-key "F17" 'edt-key-not-assigned 'edt-key-not-assigned t)
- (edt-bind-function-key "F18" 'edt-key-not-assigned 'edt-key-not-assigned t)
- (edt-bind-function-key "F19" 'edt-key-not-assigned 'edt-key-not-assigned t)
- (edt-bind-function-key "F20" 'edt-key-not-assigned 'edt-key-not-assigned t)
-
- ;; Control key bindings: Regular and GOLD
- ;;
- ;; Standard EDT control key bindings conflict with standard Emacs
- ;; control key bindings. Normally, the standard Emacs control key
- ;; bindings are left unchanged in the default EDT mode. However, if
- ;; the variable edt-use-EDT-control-key-bindings is set to true
- ;; before invoking edt-emulation-on for the first time, then the
- ;; standard EDT bindings (with some enhancements) as defined here are
- ;; used, instead.
- (if edt-use-EDT-control-key-bindings
- (progn
- (edt-bind-standard-key "\C-a" 'edt-key-not-assigned t)
- (edt-bind-standard-key "\C-b" 'edt-key-not-assigned t)
- ;; Leave binding of C-c as original prefix key.
- (edt-bind-standard-key "\C-d" 'edt-key-not-assigned t)
- (edt-bind-standard-key "\C-e" 'edt-key-not-assigned t)
- (edt-bind-standard-key "\C-f" 'edt-key-not-assigned t)
- ;; Leave binding of C-g to keyboard-quit
-; (edt-bind-standard-key "\C-g" 'keyboard-quit t)
- ;; Standard EDT binding of C-h. To invoke Emacs help, use
- ;; GOLD-C-h instead.
- (edt-bind-standard-key "\C-h" 'edt-beginning-of-line t)
- (edt-bind-standard-key "\C-i" 'edt-tab-insert t)
- (edt-bind-standard-key "\C-j" 'edt-delete-to-beginning-of-word t)
- (edt-bind-standard-key "\C-k" 'edt-define-key t)
- (edt-bind-gold-key "\C-k" 'edt-restore-key t)
- (edt-bind-standard-key "\C-l" 'edt-form-feed-insert t)
- ;; Leave binding of C-m to newline.
- (edt-bind-standard-key "\C-n" 'edt-set-screen-width-80 t)
- (edt-bind-standard-key "\C-o" 'edt-key-not-assigned t)
- (edt-bind-standard-key "\C-p" 'edt-key-not-assigned t)
- (edt-bind-standard-key "\C-q" 'edt-key-not-assigned t)
- ;; Leave binding of C-r to isearch-backward.
- ;; Leave binding of C-s to isearch-forward.
- (edt-bind-standard-key "\C-t" 'edt-display-the-time t)
- (edt-bind-standard-key "\C-u" 'edt-delete-to-beginning-of-line t)
- (edt-bind-standard-key "\C-v" 'redraw-display t)
- (edt-bind-standard-key "\C-w" 'edt-set-screen-width-132 t)
- ;; Leave binding of C-x as original prefix key.
- (edt-bind-standard-key "\C-y" 'edt-key-not-assigned t)
-; (edt-bind-standard-key "\C-z" 'suspend-emacs t)
- )
- )
-
- ;; GOLD bindings for a few Control keys.
- (edt-bind-gold-key "\C-g" 'keyboard-quit t); Just in case.
- (edt-bind-gold-key "\C-h" 'help-for-help t)
- (edt-bind-gold-key [f1] 'help-for-help t)
- (edt-bind-gold-key [help] 'help-for-help t)
- (edt-bind-gold-key "\C-\\" 'split-window-vertically t)
-
- ;; GOLD bindings for regular keys.
- (edt-bind-gold-key "a" 'edt-key-not-assigned t)
- (edt-bind-gold-key "A" 'edt-key-not-assigned t)
- (edt-bind-gold-key "b" 'buffer-menu t)
- (edt-bind-gold-key "B" 'buffer-menu t)
- (edt-bind-gold-key "c" 'compile t)
- (edt-bind-gold-key "C" 'compile t)
- (edt-bind-gold-key "d" 'delete-window t)
- (edt-bind-gold-key "D" 'delete-window t)
- (edt-bind-gold-key "e" 'edt-exit t)
- (edt-bind-gold-key "E" 'edt-exit t)
- (edt-bind-gold-key "f" 'find-file t)
- (edt-bind-gold-key "F" 'find-file t)
- (edt-bind-gold-key "g" 'find-file-other-window t)
- (edt-bind-gold-key "G" 'find-file-other-window t)
- (edt-bind-gold-key "h" 'edt-electric-keypad-help t)
- (edt-bind-gold-key "H" 'edt-electric-keypad-help t)
- (edt-bind-gold-key "i" 'insert-file t)
- (edt-bind-gold-key "I" 'insert-file t)
- (edt-bind-gold-key "j" 'edt-key-not-assigned t)
- (edt-bind-gold-key "J" 'edt-key-not-assigned t)
- (edt-bind-gold-key "k" 'edt-toggle-capitalization-of-word t)
- (edt-bind-gold-key "K" 'edt-toggle-capitalization-of-word t)
- (edt-bind-gold-key "l" 'edt-lowercase t)
- (edt-bind-gold-key "L" 'edt-lowercase t)
- (edt-bind-gold-key "m" 'save-some-buffers t)
- (edt-bind-gold-key "M" 'save-some-buffers t)
- (edt-bind-gold-key "n" 'next-error t)
- (edt-bind-gold-key "N" 'next-error t)
- (edt-bind-gold-key "o" 'switch-to-buffer-other-window t)
- (edt-bind-gold-key "O" 'switch-to-buffer-other-window t)
- (edt-bind-gold-key "p" 'edt-key-not-assigned t)
- (edt-bind-gold-key "P" 'edt-key-not-assigned t)
- (edt-bind-gold-key "q" 'edt-quit t)
- (edt-bind-gold-key "Q" 'edt-quit t)
- (edt-bind-gold-key "r" 'revert-buffer t)
- (edt-bind-gold-key "R" 'revert-buffer t)
- (edt-bind-gold-key "s" 'save-buffer t)
- (edt-bind-gold-key "S" 'save-buffer t)
- (edt-bind-gold-key "t" 'edt-key-not-assigned t)
- (edt-bind-gold-key "T" 'edt-key-not-assigned t)
- (edt-bind-gold-key "u" 'edt-uppercase t)
- (edt-bind-gold-key "U" 'edt-uppercase t)
- (edt-bind-gold-key "v" 'find-file-other-window t)
- (edt-bind-gold-key "V" 'find-file-other-window t)
- (edt-bind-gold-key "w" 'write-file t)
- (edt-bind-gold-key "W" 'write-file t)
- (edt-bind-gold-key "x" 'edt-key-not-assigned t)
- (edt-bind-gold-key "X" 'edt-key-not-assigned t)
- (edt-bind-gold-key "y" 'edt-emulation-off t)
- (edt-bind-gold-key "Y" 'edt-emulation-off t)
- (edt-bind-gold-key "z" 'edt-switch-global-maps t)
- (edt-bind-gold-key "Z" 'edt-switch-global-maps t)
- (edt-bind-gold-key "1" 'delete-other-windows t)
- (edt-bind-gold-key "!" 'edt-key-not-assigned t)
- (edt-bind-gold-key "2" 'edt-split-window t)
- (edt-bind-gold-key "@" 'edt-key-not-assigned t)
- (edt-bind-gold-key "3" 'edt-key-not-assigned t)
- (edt-bind-gold-key "#" 'edt-key-not-assigned t)
- (edt-bind-gold-key "4" 'edt-key-not-assigned t)
- (edt-bind-gold-key "$" 'edt-key-not-assigned t)
- (edt-bind-gold-key "5" 'edt-key-not-assigned t)
- (edt-bind-gold-key "%" 'edt-goto-percentage t)
- (edt-bind-gold-key "6" 'edt-key-not-assigned t)
- (edt-bind-gold-key "^" 'edt-key-not-assigned t)
- (edt-bind-gold-key "7" 'edt-key-not-assigned t)
- (edt-bind-gold-key "&" 'edt-key-not-assigned t)
- (edt-bind-gold-key "8" 'edt-key-not-assigned t)
- (edt-bind-gold-key "*" 'edt-key-not-assigned t)
- (edt-bind-gold-key "9" 'edt-key-not-assigned t)
- (edt-bind-gold-key "(" 'edt-key-not-assigned t)
- (edt-bind-gold-key "0" 'edt-key-not-assigned t)
- (edt-bind-gold-key ")" 'edt-key-not-assigned t)
- (edt-bind-gold-key " " 'undo t)
- (edt-bind-gold-key "," 'edt-key-not-assigned t)
- (edt-bind-gold-key "<" 'edt-key-not-assigned t)
- (edt-bind-gold-key "." 'edt-key-not-assigned t)
- (edt-bind-gold-key ">" 'edt-key-not-assigned t)
- (edt-bind-gold-key "/" 'edt-key-not-assigned t)
- (edt-bind-gold-key "?" 'edt-key-not-assigned t)
- (edt-bind-gold-key "\\" 'edt-key-not-assigned t)
- (edt-bind-gold-key "|" 'edt-key-not-assigned t)
- (edt-bind-gold-key ";" 'edt-key-not-assigned t)
- (edt-bind-gold-key ":" 'edt-key-not-assigned t)
- (edt-bind-gold-key "'" 'edt-key-not-assigned t)
- (edt-bind-gold-key "\"" 'edt-key-not-assigned t)
- (edt-bind-gold-key "-" 'edt-key-not-assigned t)
- (edt-bind-gold-key "_" 'edt-key-not-assigned t)
- (edt-bind-gold-key "=" 'goto-line t)
- (edt-bind-gold-key "+" 'edt-key-not-assigned t)
- (edt-bind-gold-key "[" 'edt-key-not-assigned t)
- (edt-bind-gold-key "{" 'edt-key-not-assigned t)
- (edt-bind-gold-key "]" 'edt-key-not-assigned t)
- (edt-bind-gold-key "}" 'edt-key-not-assigned t)
- (edt-bind-gold-key "`" 'what-line t)
- (edt-bind-gold-key "~" 'edt-key-not-assigned t)
-)
-
-;;;
-;;; DEFAULT EDT KEYPAD HELP
-;;;
-
-;;;
-;;; Upper case commands in the keypad diagram below indicate that the
-;;; emulation should look and feel very much like EDT. Lower case
-;;; commands are enhancements and/or additions to the EDT keypad
-;;; commands or are native Emacs commands.
-;;;
-
-(defun edt-keypad-help ()
- "
- DEFAULT EDT Keypad Active
-
- F7: Copy Rectangle +----------+----------+----------+----------+
- F8: Cut Rect Overstrike |Prev Line |Next Line |Bkwd Char |Frwd Char |
- G-F8: Paste Rect Overstrike | (UP) | (DOWN) | (LEFT) | (RIGHT) |
- F9: Cut Rect Insert |Window Top|Window Bot|Bkwd Sent |Frwd Sent |
- G-F9: Paste Rect Insert +----------+----------+----------+----------+
- F10: Cut Rectangle
-G-F10: Paste Rectangle
- F11: ESC
- F12: Begining of Line +----------+----------+----------+----------+
-G-F12: Delete Other Windows | GOLD | HELP | FNDNXT | DEL L |
- F13: Delete to Begin of Word | (PF1) | (PF2) | (PF3) | (PF4) |
- HELP: Keypad Help |Mark Wisel|Desc Funct| FIND | UND L |
- DO: Execute extended command +----------+----------+----------+----------+
- | PAGE | SECT | APPEND | DEL W |
- C-g: Keyboard Quit | (7) | (8) | (9) | (-) |
-G-C-g: Keyboard Quit |Ex Ext Cmd|Fill Regio| REPLACE | UND W |
- C-h: Beginning of Line +----------+----------+----------+----------+
-G-C-h: Emacs Help | ADVANCE | BACKUP | CUT | DEL C |
- C-i: Tab Insert | (4) | (5) | (6) | (,) |
- C-j: Delete to Begin of Word | BOTTOM | TOP | Yank | UND C |
- C-k: Define Key +----------+----------+----------+----------+
-G-C-k: Restore Key | WORD | EOL | CHAR | Next |
- C-l: Form Feed Insert | (1) | (2) | (3) | Window |
- C-n: Set Screen Width 80 | CHNGCASE | DEL EOL |Quoted Ins| !
- C-r: Isearch Backward +---------------------+----------+ (ENTER) |
- C-s: Isearch Forward | LINE | SELECT | !
- C-t: Display the Time | (0) | (.) | Query |
- C-u: Delete to Begin of Line | Open Line | RESET | Replace |
- C-v: Redraw Display +---------------------+----------+----------+
- C-w: Set Screen Width 132
- C-z: Suspend Emacs +----------+----------+----------+
-G-C-\\: Split Window | FNDNXT | Yank | CUT |
- | (FIND) | (INSERT) | (REMOVE) |
- G-b: Buffer Menu | FIND | | COPY |
- G-c: Compile +----------+----------+----------+
- G-d: Delete Window |SELECT/RES|SECT BACKW|SECT FORWA|
- G-e: Exit | (SELECT) |(PREVIOUS)| (NEXT) |
- G-f: Find File | | | |
- G-g: Find File Other Window +----------+----------+----------+
- G-h: Keypad Help
- G-i: Insert File
- G-k: Toggle Capitalization Word
- G-l: Downcase Region
- G-m: Save Some Buffers
- G-n: Next Error
- G-o: Switch to Next Window
- G-q: Quit
- G-r: Revert File
- G-s: Save Buffer
- G-u: Upcase Region
- G-v: Find File Other Window
- G-w: Write file
- G-y: EDT Emulation OFF
- G-z: Switch to User EDT Key Bindings
- G-1: Delete Other Windows
- G-2: Split Window
- G-%: Go to Percentage
- G- : Undo (GOLD Spacebar)
- G-=: Go to Line
- G-`: What line"
-
- (interactive)
- (describe-function 'edt-keypad-help))
-
-(defun edt-electric-helpify (fun)
- (let ((name "*Help*"))
- (if (save-window-excursion
- (let* ((p (symbol-function 'print-help-return-message))
- (b (get-buffer name))
- (m (buffer-modified-p b)))
- (and b (not (get-buffer-window b))
- (setq b nil))
- (unwind-protect
- (progn
- (message "%s..." (capitalize (symbol-name fun)))
- (and b
- (save-excursion
- (set-buffer b)
- (set-buffer-modified-p t)))
- (fset 'print-help-return-message 'ignore)
- (call-interactively fun)
- (and (get-buffer name)
- (get-buffer-window (get-buffer name))
- (or (not b)
- (not (eq b (get-buffer name)))
- (not (buffer-modified-p b)))))
- (fset 'print-help-return-message p)
- (and b (buffer-name b)
- (save-excursion
- (set-buffer b)
- (set-buffer-modified-p m))))))
- (with-electric-help 'delete-other-windows name t))))
-
-(defun edt-electric-keypad-help ()
- "Display default EDT bindings."
- (interactive)
- (edt-electric-helpify 'edt-keypad-help))
-
-(defun edt-electric-user-keypad-help ()
- "Display user custom EDT bindings."
- (interactive)
- (edt-electric-helpify 'edt-user-keypad-help))
-
-;;;
-;;; EDT emulation screen width commands.
-;;;
-;; Some terminals require modification of terminal attributes when changing the
-;; number of columns displayed, hence the fboundp tests below. These functions
-;; are defined in the corresponding terminal specific file, if needed.
-
-(defun edt-set-screen-width-80 ()
- "Set screen width to 80 columns."
- (interactive)
- (if (fboundp 'edt-set-term-width-80)
- (edt-set-term-width-80))
- (set-screen-width 80)
- (message "Screen width 80"))
-
-(defun edt-set-screen-width-132 ()
- "Set screen width to 132 columns."
- (interactive)
- (if (fboundp 'edt-set-term-width-132)
- (edt-set-term-width-132))
- (set-screen-width 132)
- (message "Screen width 132"))
-
-(provide 'edt)
-
-;;; edt.el ends here
diff --git a/lisp/emulation/mlconvert.el b/lisp/emulation/mlconvert.el
deleted file mode 100644
index 3ded26469ff..00000000000
--- a/lisp/emulation/mlconvert.el
+++ /dev/null
@@ -1,288 +0,0 @@
-;;; mlconvert.el --- convert buffer of Mocklisp code to real lisp.
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package converts Mocklisp code written under a Gosling or UniPress
-;; Emacs for use with GNU Emacs. The translated code will require runtime
-;; support from the mlsupport.el equivalent.
-
-;;; Code:
-
-;;;###autoload
-(defun convert-mocklisp-buffer ()
- "Convert buffer of Mocklisp code to real Lisp that GNU Emacs can run."
- (interactive)
- (emacs-lisp-mode)
- (set-syntax-table (copy-sequence (syntax-table)))
- (modify-syntax-entry ?\| "w")
- (message "Converting mocklisp (ugh!)...")
- (goto-char (point-min))
- (fix-mlisp-syntax)
-
- ;; Emulation of mocklisp is accurate only within a mocklisp-function
- ;; so turn any non-function into a defun and then call it.
- (goto-char (point-min))
- (condition-case ignore
- (while t
- (let ((opt (point))
- (form (read (current-buffer))))
- (and (listp form)
- (not (eq (car form) 'defun))
- (progn (insert "))\n\n(ml-foo)\n\n")
- (save-excursion
- (goto-char opt)
- (skip-chars-forward "\n")
- (insert "(defun (ml-foo \n "))))))
- (end-of-file nil))
-
- (goto-char (point-min))
- (insert ";;; GNU Emacs code converted from Mocklisp\n")
- (insert "(require 'mlsupport)\n\n")
- (fix-mlisp-symbols)
-
- (goto-char (point-min))
- (message "Converting mocklisp...done"))
-
-(defun fix-mlisp-syntax ()
- (while (re-search-forward "['\"]" nil t)
- (if (= (preceding-char) ?\")
- (progn (forward-char -1)
- (forward-sexp 1))
- (delete-char -1)
- (insert "?")
- (if (or (= (following-char) ?\\) (= (following-char) ?^))
- (forward-char 1)
- (if (looking-at "[^a-zA-Z]")
- (insert ?\\)))
- (forward-char 1)
- (delete-char 1))))
-
-(defun fix-mlisp-symbols ()
- (while (progn
- (skip-chars-forward " \t\n()")
- (not (eobp)))
- (cond ((or (= (following-char) ?\?)
- (= (following-char) ?\"))
- (forward-sexp 1))
- ((= (following-char) ?\;)
- (forward-line 1))
- (t
- (let ((start (point)) prop)
- (forward-sexp 1)
- (setq prop (get (intern-soft (buffer-substring start (point)))
- 'mocklisp))
- (cond ((null prop))
- ((stringp prop)
- (delete-region start (point))
- (insert prop))
- (t
- (save-excursion
- (goto-char start)
- (funcall prop)))))))))
-
-(defun ml-expansion (ml-name lisp-string)
- (put ml-name 'mocklisp lisp-string))
-
-(ml-expansion 'defun "ml-defun")
-(ml-expansion 'if "ml-if")
-(ml-expansion 'setq '(lambda ()
- (if (looking-at "setq[ \t\n]+buffer-modified-p")
- (replace-match "set-buffer-modified-p"))))
-
-;;(ml-expansion 'while '(lambda ()
-;; (let ((end (progn (forward-sexp 2) (point-marker)))
-;; (start (progn (forward-sexp -1) (point))))
-;; (let ((cond (buffer-substring start end)))
-;; (cond ((equal cond "1")
-;; (delete-region (point) end)
-;; (insert "t"))
-;; (t
-;; (insert "(not (zerop ")
-;; (goto-char end)
-;; (insert "))")))
-;; (set-marker end nil)
-;; (goto-char start)))))
-
-(ml-expansion 'arg "ml-arg")
-(ml-expansion 'nargs "ml-nargs")
-(ml-expansion 'interactive "ml-interactive")
-(ml-expansion 'message "ml-message")
-(ml-expansion 'print "ml-print")
-(ml-expansion 'set "ml-set")
-(ml-expansion 'set-default "ml-set-default")
-(ml-expansion 'provide-prefix-argument "ml-provide-prefix-argument")
-(ml-expansion 'prefix-argument-loop "ml-prefix-argument-loop")
-(ml-expansion 'prefix-argument "ml-prefix-arg")
-(ml-expansion 'use-local-map "ml-use-local-map")
-(ml-expansion 'use-global-map "ml-use-global-map")
-(ml-expansion 'modify-syntax-entry "ml-modify-syntax-entry")
-(ml-expansion 'error-message "error")
-
-(ml-expansion 'dot "point-marker")
-(ml-expansion 'mark "mark-marker")
-(ml-expansion 'beginning-of-file "beginning-of-buffer")
-(ml-expansion 'end-of-file "end-of-buffer")
-(ml-expansion 'exchange-dot-and-mark "exchange-point-and-mark")
-(ml-expansion 'set-mark "set-mark-command")
-(ml-expansion 'argument-prefix "universal-arg")
-
-(ml-expansion 'previous-page "ml-previous-page")
-(ml-expansion 'next-page "ml-next-page")
-(ml-expansion 'next-window "ml-next-window")
-(ml-expansion 'previous-window "ml-previous-window")
-
-(ml-expansion 'newline "ml-newline")
-(ml-expansion 'next-line "ml-next-line")
-(ml-expansion 'previous-line "ml-previous-line")
-(ml-expansion 'self-insert "self-insert-command")
-(ml-expansion 'meta-digit "digit-argument")
-(ml-expansion 'meta-minus "negative-argument")
-
-(ml-expansion 'newline-and-indent "ml-newline-and-indent")
-(ml-expansion 'yank-from-killbuffer "yank")
-(ml-expansion 'yank-buffer "insert-buffer")
-(ml-expansion 'copy-region "copy-region-as-kill")
-(ml-expansion 'delete-white-space "delete-horizontal-space")
-(ml-expansion 'widen-region "widen")
-
-(ml-expansion 'forward-word '(lambda ()
- (if (looking-at "forward-word[ \t\n]*)")
- (replace-match "forward-word 1)"))))
-(ml-expansion 'backward-word '(lambda ()
- (if (looking-at "backward-word[ \t\n]*)")
- (replace-match "backward-word 1)"))))
-
-(ml-expansion 'forward-paren "forward-list")
-(ml-expansion 'backward-paren "backward-list")
-(ml-expansion 'search-reverse "ml-search-backward")
-(ml-expansion 're-search-reverse "ml-re-search-backward")
-(ml-expansion 'search-forward "ml-search-forward")
-(ml-expansion 're-search-forward "ml-re-search-forward")
-(ml-expansion 'quote "regexp-quote")
-(ml-expansion 're-query-replace "query-replace-regexp")
-(ml-expansion 're-replace-string "replace-regexp")
-
-; forward-paren-bl, backward-paren-bl
-
-(ml-expansion 'get-tty-character "read-char")
-(ml-expansion 'get-tty-input "read-input")
-(ml-expansion 'get-tty-string "read-string")
-(ml-expansion 'get-tty-buffer "read-buffer")
-(ml-expansion 'get-tty-command "read-command")
-(ml-expansion 'get-tty-variable "read-variable")
-(ml-expansion 'get-tty-no-blanks-input "read-no-blanks-input")
-(ml-expansion 'get-tty-key "read-key")
-
-(ml-expansion 'concat "ml-concat")
-(ml-expansion 'c= "char-equal")
-(ml-expansion 'goto-character "goto-char")
-(ml-expansion 'substr "ml-substr")
-(ml-expansion 'variable-apropos "apropos")
-(ml-expansion 'execute-mlisp-buffer "eval-current-buffer")
-(ml-expansion 'execute-mlisp-file "load")
-(ml-expansion 'visit-file "find-file")
-(ml-expansion 'read-file "find-file")
-(ml-expansion 'write-modified-files "save-some-buffers")
-(ml-expansion 'backup-before-writing "make-backup-files")
-(ml-expansion 'write-file-exit "save-buffers-kill-emacs")
-(ml-expansion 'write-named-file "write-file")
-(ml-expansion 'change-file-name "set-visited-file-name")
-(ml-expansion 'change-buffer-name "rename-buffer")
-(ml-expansion 'buffer-exists "get-buffer")
-(ml-expansion 'delete-buffer "kill-buffer")
-(ml-expansion 'unlink-file "delete-file")
-(ml-expansion 'unlink-checkpoint-files "delete-auto-save-files")
-(ml-expansion 'file-exists "file-exists-p")
-(ml-expansion 'write-current-file "save-buffer")
-(ml-expansion 'change-directory "cd")
-(ml-expansion 'temp-use-buffer "set-buffer")
-(ml-expansion 'fast-filter-region "filter-region")
-
-(ml-expansion 'pending-input "input-pending-p")
-(ml-expansion 'execute-keyboard-macro "call-last-kbd-macro")
-(ml-expansion 'start-remembering "start-kbd-macro")
-(ml-expansion 'end-remembering "end-kbd-macro")
-(ml-expansion 'define-keyboard-macro "name-last-kbd-macro")
-(ml-expansion 'define-string-macro "ml-define-string-macro")
-
-(ml-expansion 'current-column "ml-current-column")
-(ml-expansion 'current-indent "ml-current-indent")
-(ml-expansion 'insert-character "insert")
-
-(ml-expansion 'users-login-name "user-login-name")
-(ml-expansion 'users-full-name "user-full-name")
-(ml-expansion 'current-time "current-time-string")
-(ml-expansion 'current-numeric-time "current-numeric-time-you-lose")
-(ml-expansion 'current-buffer-name "buffer-name")
-(ml-expansion 'current-file-name "buffer-file-name")
-
-(ml-expansion 'local-binding-of "local-key-binding")
-(ml-expansion 'global-binding-of "global-key-binding")
-
-;defproc (ProcedureType, "procedure-type");
-
-(ml-expansion 'remove-key-binding "global-unset-key")
-(ml-expansion 'remove-binding "global-unset-key")
-(ml-expansion 'remove-local-binding "local-unset-key")
-(ml-expansion 'remove-all-local-bindings "use-local-map nil")
-(ml-expansion 'autoload "ml-autoload")
-
-(ml-expansion 'checkpoint-frequency "auto-save-interval")
-
-(ml-expansion 'mode-string "mode-name")
-(ml-expansion 'right-margin "fill-column")
-(ml-expansion 'tab-size "tab-width")
-(ml-expansion 'default-right-margin "default-fill-column")
-(ml-expansion 'default-tab-size "default-tab-width")
-(ml-expansion 'buffer-is-modified "(buffer-modified-p)")
-
-(ml-expansion 'file-modified-time "you-lose-on-file-modified-time")
-(ml-expansion 'needs-checkpointing "you-lose-on-needs-checkpointing")
-
-(ml-expansion 'lines-on-screen "set-frame-height")
-(ml-expansion 'columns-on-screen "set-frame-width")
-
-(ml-expansion 'dumped-emacs "t")
-
-(ml-expansion 'buffer-size "ml-buffer-size")
-(ml-expansion 'dot-is-visible "pos-visible-in-window-p")
-
-(ml-expansion 'track-eol-on-^N-^P "track-eol")
-(ml-expansion 'ctlchar-with-^ "ctl-arrow")
-(ml-expansion 'help-on-command-completion-error "completion-auto-help")
-(ml-expansion 'dump-stack-trace "backtrace")
-(ml-expansion 'pause-emacs "suspend-emacs")
-(ml-expansion 'compile-it "compile")
-
-(ml-expansion '!= "/=")
-(ml-expansion '& "logand")
-(ml-expansion '| "logior")
-(ml-expansion '^ "logxor")
-(ml-expansion '! "ml-not")
-(ml-expansion '<< "lsh")
-
-;Variable pause-writes-files
-
-;;; mlconvert.el ends here
diff --git a/lisp/emulation/mlsupport.el b/lisp/emulation/mlsupport.el
deleted file mode 100644
index 7f7a357cc3c..00000000000
--- a/lisp/emulation/mlsupport.el
+++ /dev/null
@@ -1,435 +0,0 @@
-;;; mlsupport.el --- run-time support for mocklisp code.
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides equivalents of certain primitives from Gosling
-;; Emacs (including the commercial UniPress versions). These have an
-;; ml- prefix to distinguish them from native GNU Emacs functions with
-;; similar names. The package mlconvert.el translates Mocklisp code
-;; to use these names.
-
-;;; Code:
-
-(defmacro ml-defun (&rest defs)
- (list 'ml-defun-1 (list 'quote defs)))
-
-(defun ml-defun-1 (args)
- (while args
- (fset (car (car args)) (cons 'mocklisp (cdr (car args))))
- (setq args (cdr args))))
-
-(defmacro declare-buffer-specific (&rest vars)
- (cons 'progn (mapcar (function (lambda (var) (list 'make-variable-buffer-local (list 'quote var)))) vars)))
-
-(defun ml-set-default (varname value)
- (set-default (intern varname) value))
-
-; Lossage: must make various things default missing args to the prefix arg
-; Alternatively, must make provide-prefix-argument do something hairy.
-
-(defun >> (val count) (lsh val (- count)))
-(defun novalue () nil)
-
-(defun ml-not (arg) (if (zerop arg) 1 0))
-
-(defun provide-prefix-arg (arg form)
- (funcall (car form) arg))
-
-(defun define-keymap (name)
- (fset (intern name) (make-keymap)))
-
-;; Make it work to use ml-use-...-map on "esc" and such.
-(fset 'esc-map esc-map)
-(fset 'ctl-x-map ctl-x-map)
-
-(defun ml-use-local-map (name)
- (use-local-map (intern (concat name "-map"))))
-
-(defun ml-use-global-map (name)
- (use-global-map (intern (concat name "-map"))))
-
-(defun local-bind-to-key (name key)
- (or (current-local-map)
- (use-local-map (make-keymap)))
- (define-key (current-local-map)
- (if (integerp key)
- (if (>= key 128)
- (concat (char-to-string meta-prefix-char)
- (char-to-string (- key 128)))
- (char-to-string key))
- key)
- (intern name)))
-
-(defun bind-to-key (name key)
- (define-key global-map (if (integerp key) (char-to-string key) key)
- (intern name)))
-
-(defun ml-autoload (name file)
- (autoload (intern name) file))
-
-(defun ml-define-string-macro (name defn)
- (fset (intern name) defn))
-
-(defun push-back-character (char)
- (setq unread-command-events (list char)))
-
-(defun to-col (column)
- (indent-to column 0))
-
-(defmacro is-bound (&rest syms)
- (cons 'and (mapcar (function (lambda (sym) (list 'boundp (list 'quote sym)))) syms)))
-
-(defmacro declare-global (&rest syms)
- (cons 'progn (mapcar (function (lambda (sym) (list 'defvar sym nil))) syms)))
-
-(defmacro error-occurred (&rest body)
- (list 'condition-case nil (cons 'progn (append body '(nil))) '(error t)))
-
-(defun return-prefix-argument (value)
- (setq prefix-arg value))
-
-(defun ml-prefix-argument ()
- (if (null current-prefix-arg) 1
- (if (listp current-prefix-arg) (car current-prefix-arg)
- (if (eq current-prefix-arg '-) -1
- current-prefix-arg))))
-
-(defun ml-print (varname)
- (interactive "vPrint variable: ")
- (if (boundp varname)
- (message "%s => %s" (symbol-name varname) (symbol-value varname))
- (message "%s has no value" (symbol-name varname))))
-
-(defun ml-set (str val) (set (intern str) val))
-
-(defun ml-message (&rest args) (message "%s" (apply 'concat args)))
-
-(defun kill-to-end-of-line ()
- (ml-prefix-argument-loop
- (if (eolp)
- (kill-region (point) (1+ (point)))
- (kill-region (point) (if (search-forward ?\n nil t)
- (1- (point)) (point-max))))))
-
-(defun set-auto-fill-hook (arg)
- (setq auto-fill-function (intern arg)))
-
-(defun auto-execute (function pattern)
- (if (/= (aref pattern 0) ?*)
- (error "Only patterns starting with * supported in auto-execute"))
- (setq auto-mode-alist (cons (cons (concat "\\." (substring pattern 1)
- "\\'")
- function)
- auto-mode-alist)))
-
-(defun move-to-comment-column ()
- (indent-to comment-column))
-
-(defun erase-region ()
- (delete-region (point) (mark)))
-
-(defun delete-region-to-buffer (bufname)
- (copy-to-buffer bufname (point) (mark))
- (delete-region (point) (mark)))
-
-(defun copy-region-to-buffer (bufname)
- (copy-to-buffer bufname (point) (mark)))
-
-(defun append-region-to-buffer (bufname)
- (append-to-buffer bufname (point) (mark)))
-
-(defun prepend-region-to-buffer (bufname)
- (prepend-to-buffer bufname (point) (mark)))
-
-(defun delete-next-character ()
- (delete-char (ml-prefix-argument)))
-
-(defun delete-next-word ()
- (delete-region (point) (progn (forward-word (ml-prefix-argument)) (point))))
-
-(defun delete-previous-word ()
- (delete-region (point) (progn (backward-word (ml-prefix-argument)) (point))))
-
-(defun delete-previous-character ()
- (delete-backward-char (ml-prefix-argument)))
-
-(defun forward-character ()
- (forward-char (ml-prefix-argument)))
-
-(defun backward-character ()
- (backward-char (ml-prefix-argument)))
-
-(defun ml-newline ()
- (newline (ml-prefix-argument)))
-
-(defun ml-next-line ()
- (next-line (ml-prefix-argument)))
-
-(defun ml-previous-line ()
- (previous-line (ml-prefix-argument)))
-
-(defun delete-to-kill-buffer ()
- (kill-region (point) (mark)))
-
-(defun narrow-region ()
- (narrow-to-region (point) (mark)))
-
-(defun ml-newline-and-indent ()
- (let ((column (current-indentation)))
- (newline (ml-prefix-argument))
- (indent-to column)))
-
-(defun newline-and-backup ()
- (open-line (ml-prefix-argument)))
-
-(defun quote-char ()
- (quoted-insert (ml-prefix-argument)))
-
-(defun ml-current-column ()
- (1+ (current-column)))
-
-(defun ml-current-indent ()
- (1+ (current-indentation)))
-
-(defun region-around-match (&optional n)
- (set-mark (match-beginning n))
- (goto-char (match-end n)))
-
-(defun region-to-string ()
- (buffer-substring (min (point) (mark)) (max (point) (mark))))
-
-(defun use-abbrev-table (name)
- (let ((symbol (intern (concat name "-abbrev-table"))))
- (or (boundp symbol)
- (define-abbrev-table symbol nil))
- (symbol-value symbol)))
-
-(defun define-hooked-local-abbrev (name exp hook)
- (define-local-abbrev name exp (intern hook)))
-
-(defun define-hooked-global-abbrev (name exp hook)
- (define-global-abbrev name exp (intern hook)))
-
-(defun case-word-lower ()
- (ml-casify-word 'downcase-region))
-
-(defun case-word-upper ()
- (ml-casify-word 'upcase-region))
-
-(defun case-word-capitalize ()
- (ml-casify-word 'capitalize-region))
-
-(defun ml-casify-word (fun)
- (save-excursion
- (forward-char 1)
- (forward-word -1)
- (funcall fun (point)
- (progn (forward-word (ml-prefix-argument))
- (point)))))
-
-(defun case-region-lower ()
- (downcase-region (point) (mark)))
-
-(defun case-region-upper ()
- (upcase-region (point) (mark)))
-
-(defun case-region-capitalize ()
- (capitalize-region (point) (mark)))
-
-(defvar saved-command-line-args nil)
-
-(defun argc ()
- (or saved-command-line-args
- (setq saved-command-line-args command-line-args
- command-line-args ()))
- (length command-line-args))
-
-(defun argv (i)
- (or saved-command-line-args
- (setq saved-command-line-args command-line-args
- command-line-args ()))
- (nth i saved-command-line-args))
-
-(defun invisible-argc ()
- (length (or saved-command-line-args
- command-line-args)))
-
-(defun invisible-argv (i)
- (nth i (or saved-command-line-args
- command-line-args)))
-
-(defun exit-emacs ()
- (interactive)
- (condition-case ()
- (exit-recursive-edit)
- (error (kill-emacs))))
-
-;; Lisp function buffer-size returns total including invisible;
-;; mocklisp wants just visible.
-(defun ml-buffer-size ()
- (- (point-max) (point-min)))
-
-(defun previous-command ()
- last-command)
-
-(defun beginning-of-window ()
- (goto-char (window-start)))
-
-(defun end-of-window ()
- (goto-char (window-start))
- (vertical-motion (- (window-height) 2)))
-
-(defun ml-search-forward (string)
- (search-forward string nil nil (ml-prefix-argument)))
-
-(defun ml-re-search-forward (string)
- (re-search-forward string nil nil (ml-prefix-argument)))
-
-(defun ml-search-backward (string)
- (search-backward string nil nil (ml-prefix-argument)))
-
-(defun ml-re-search-backward (string)
- (re-search-backward string nil nil (ml-prefix-argument)))
-
-(defvar use-users-shell 1
- "Mocklisp compatibility variable; 1 means use shell from SHELL env var.
-0 means use /bin/sh.")
-
-(defvar use-csh-option-f 1
- "Mocklisp compatibility variable; 1 means pass -f when calling csh.")
-
-(defun filter-region (command)
- (let ((shell (if (/= use-users-shell 0) shell-file-name "/bin/sh"))
- (csh (equal (file-name-nondirectory shell) "csh")))
- (call-process-region (point) (mark) shell t t nil
- (if (and csh use-csh-option-f) "-cf" "-c")
- (concat "exec " command))))
-
-(defun execute-monitor-command (command)
- (let ((shell (if (/= use-users-shell 0) shell-file-name "/bin/sh"))
- (csh (equal (file-name-nondirectory shell) "csh")))
- (call-process shell nil t t
- (if (and csh use-csh-option-f) "-cf" "-c")
- (concat "exec " command))))
-
-(defun use-syntax-table (name)
- (set-syntax-table (symbol-value (intern (concat name "-syntax-table")))))
-
-(defun line-to-top-of-window ()
- (recenter (1- (ml-prefix-argument))))
-
-(defun ml-previous-page (&optional arg)
- (let ((count (or arg (ml-prefix-argument))))
- (while (> count 0)
- (scroll-down nil)
- (setq count (1- count)))
- (while (< count 0)
- (scroll-up nil)
- (setq count (1+ count)))))
-
-(defun ml-next-page ()
- (previous-page (- (ml-prefix-argument))))
-
-(defun page-next-window (&optional arg)
- (let ((count (or arg (ml-prefix-argument))))
- (while (> count 0)
- (scroll-other-window nil)
- (setq count (1- count)))
- (while (< count 0)
- (scroll-other-window '-)
- (setq count (1+ count)))))
-
-(defun ml-next-window ()
- (select-window (next-window)))
-
-(defun ml-previous-window ()
- (select-window (previous-window)))
-
-(defun scroll-one-line-up ()
- (scroll-up (ml-prefix-argument)))
-
-(defun scroll-one-line-down ()
- (scroll-down (ml-prefix-argument)))
-
-(defun split-current-window ()
- (split-window (selected-window)))
-
-(defun last-key-struck () last-command-char)
-
-(defun execute-mlisp-line (string)
- (eval (read string)))
-
-(defun move-dot-to-x-y (x y)
- (goto-char (window-start (selected-window)))
- (vertical-motion (1- y))
- (move-to-column (1- x)))
-
-(defun ml-modify-syntax-entry (string)
- (let ((i 5)
- (len (length string))
- (datastring (substring string 0 2)))
- (if (= (aref string 0) ?\-)
- (aset datastring 0 ?\ ))
- (if (= (aref string 2) ?\{)
- (if (= (aref string 4) ?\ )
- (aset datastring 0 ?\<)
- (error "Two-char comment delimiter: use modify-syntax-entry directly")))
- (if (= (aref string 3) ?\})
- (if (= (aref string 4) ?\ )
- (aset datastring 0 ?\>)
- (error "Two-char comment delimiter: use modify-syntax-entry directly")))
- (while (< i len)
- (modify-syntax-entry (aref string i) datastring)
- (setq i (1+ i))
- (if (and (< i len)
- (= (aref string i) ?\-))
- (let ((c (aref string (1- i)))
- (lim (aref string (1+ i))))
- (while (<= c lim)
- (modify-syntax-entry c datastring)
- (setq c (1+ c)))
- (setq i (+ 2 i)))))))
-
-
-
-(defun ml-substr (string from to)
- (let ((length (length string)))
- (if (< from 0) (setq from (+ from length)))
- (if (< to 0) (setq to (+ to length)))
- (substring string from (+ from to))))
-
-(defun ml-concat (&rest args)
- (let ((newargs nil) this)
- (while args
- (setq this (car args))
- (if (numberp this)
- (setq this (number-to-string this)))
- (setq newargs (cons this newargs)
- args (cdr args)))
- (apply 'concat (nreverse newargs))))
-
-(provide 'mlsupport)
-
-;;; mlsupport.el ends here
diff --git a/lisp/emulation/pc-mode.el b/lisp/emulation/pc-mode.el
deleted file mode 100644
index c7db52ba567..00000000000
--- a/lisp/emulation/pc-mode.el
+++ /dev/null
@@ -1,52 +0,0 @@
-;;; pc-mode.el --- emulate certain key bindings used on PCs.
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;;;###autoload
-(defun pc-bindings-mode ()
- "Set up certain key bindings for PC compatibility.
-The keys affected are:
-Delete (and its variants) delete forward instead of backward.
-C-Backspace kills backward a word (as C-Delete normally would).
-M-Backspace does undo.
-Home and End move to beginning and end of line
-C-Home and C-End move to beginning and end of buffer.
-C-Escape does list-buffers."
-
- (interactive)
- (define-key function-key-map [delete] "\C-d")
- (define-key function-key-map [M-delete] [?\M-d])
- (define-key function-key-map [C-delete] [?\M-d])
- (global-set-key [C-M-delete] 'kill-sexp)
- (global-set-key [C-backspace] 'backward-kill-word)
- (global-set-key [M-backspace] 'undo)
-
- (global-set-key [C-escape] 'list-buffers)
-
- (global-set-key [home] 'beginning-of-line)
- (global-set-key [end] 'end-of-line)
- (global-set-key [C-home] 'beginning-of-buffer)
- (global-set-key [C-end] 'end-of-buffer))
-
-;; pc-mode.el ends here
diff --git a/lisp/emulation/pc-select.el b/lisp/emulation/pc-select.el
deleted file mode 100644
index a9ca7048243..00000000000
--- a/lisp/emulation/pc-select.el
+++ /dev/null
@@ -1,689 +0,0 @@
-;;; pc-select.el --- emulate mark, cut, copy and paste from motif
-;;; (or MAC GUI) or MS-windoze (bah)) look-and-feel
-;;; including key bindings
-
-;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Michael Staats <michael@thp.Uni-Duisburg.DE>
-;; Created: 26 Sep 1995
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package emulates the mark, copy, cut and paste look-and-feel of motif
-;; programs (which is the same as the MAC gui and (sorry for that) MS-Windows).
-;; It modifies the keybindings of the cursor keys and the next, prior,
-;; home and end keys. They will modify mark-active.
-;; You can still get the old behaviour of cursor moving with the
-;; control sequences C-f, C-b, etc.
-;; This package uses transient-mark-mode and
-;; delete-selection-mode.
-;;
-;; In addition to that all key-bindings from the pc-mode are
-;; done here too (as suggested by RMS).
-;;
-;; As I found out after I finished the first version, s-region.el tries
-;; to do the same.... But my code is a little more complete and using
-;; delete-selection-mode is very important for the look-and-feel.
-;; Pete Forman <pete.forman@airgun.wg.waii.com> provided some motif
-;; compliant keybindings which I added. I had to modify them a little
-;; to add the -mark and -nomark functionality of cursor moving.
-;;
-;; Credits:
-;; Many thanks to all who made comments.
-;; Thanks to RMS and Ralf Muschall <prm@rz.uni-jena.de> for criticism.
-;; Kevin Cutts <cutts@ukraine.corp.mot.com> added the beginning-of-buffer
-;; and end-of-buffer functions which I modified a little.
-;; David Biesack <sasdjb@unx.sas.com> suggested some more cleanup.
-;; Thanks to Pete Forman <pete.forman@airgun.wg.waii.com>
-;; for additional motif keybindings.
-;; Thanks to jvromans@squirrel.nl (Johan Vromans) for a bug report
-;; concerning setting of this-command.
-;; Dan Nicolaescu <done@nexus.sorostm.ro> suggested suppressing the
-;; scroll-up/scroll-down error.
-;;
-;; Ok, some details about the idea of pc-selection-mode:
-;;
-;; o The standard keys for moving around (right, left, up, down, home, end,
-;; prior, next, called "move-keys" from now on) will always de-activate
-;; the mark.
-;; o If you press "Shift" together with the "move-keys", the region
-;; you pass along is activated
-;; o You have the copy, cut and paste functions (as in many other programs)
-;; which will operate on the active region
-;; It was not possible to bind them to C-v, C-x and C-c for obvious
-;; emacs reasons.
-;; They will be bound according to the "old" behaviour to S-delete (cut),
-;; S-insert (paste) and C-insert (copy). These keys do the same in many
-;; other programs.
-;;
-
-;;;; Customization:
-
-(defvar pc-select-override-scroll-error t
- "*Non-nil means don't generate error on scrolling past edge of buffer.
-This variable applies in PC Selection mode only.
-The scroll commands normally generate an error if you try to scroll
-past the top or bottom of the buffer. This is annoying when selecting
-text with these commands. If you set this variable to non-nil, these
-errors are suppressed.")
-
-;;;;
-;; misc
-;;;;
-
-(provide 'pc-select)
-
-(defun copy-region-as-kill-nomark (beg end)
- "Save the region as if killed; but don't kill it; deactivate mark.
-If `interprogram-cut-function' is non-nil, also save the text for a window
-system cut and paste.
-
-Deactivating mark is to avoid confusion with delete-selection-mode
-and transient-mark-mode."
- (interactive "r")
- (copy-region-as-kill beg end)
- (setq mark-active nil)
- (message "Region saved"))
-
-;;;;
-;; non-interactive
-;;;;
-(defun ensure-mark()
- ;; make sure mark is active
- ;; test if it is active, if it isn't, set it and activate it
- (or mark-active (set-mark-command nil)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;; forward and mark
-;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun forward-char-mark (&optional arg)
- "Ensure mark is active; move point right ARG characters (left if ARG negative).
-On reaching end of buffer, stop and signal error."
- (interactive "p")
- (ensure-mark)
- (forward-char arg))
-
-(defun forward-word-mark (&optional arg)
- "Ensure mark is active; move point right ARG words (backward if ARG is negative).
-Normally returns t.
-If an edge of the buffer is reached, point is left there
-and nil is returned."
- (interactive "p")
- (ensure-mark)
- (forward-word arg))
-
-(defun forward-line-mark (&optional arg)
- "Ensure mark is active; move cursor vertically down ARG lines."
- (interactive "p")
- (ensure-mark)
- (forward-line arg)
- (setq this-command 'forward-line)
-)
-
-(defun forward-paragraph-mark (&optional arg)
- "Ensure mark is active; move forward to end of paragraph.
-With arg N, do it N times; negative arg -N means move backward N paragraphs.
-
-A line which `paragraph-start' matches either separates paragraphs
-\(if `paragraph-separate' matches it also) or is the first line of a paragraph.
-A paragraph end is the beginning of a line which is not part of the paragraph
-to which the end of the previous line belongs, or the end of the buffer."
- (interactive "p")
- (ensure-mark)
- (forward-paragraph arg))
-
-(defun next-line-mark (&optional arg)
- "Ensure mark is active; 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, behavior depends on the
-value of `next-line-add-newlines'. If non-nil, it inserts a newline character
-to create a line, and moves the cursor to that line. Otherwise it moves the
-cursor to the end of the buffer \(if already at the end of the buffer, an error
-is signaled).
-
-The command C-x C-n can be used to create
-a semipermanent goal column to which this command always moves.
-Then it does not try to move vertically. This goal column is stored
-in `goal-column', which is nil when there is none."
- (interactive "p")
- (ensure-mark)
- (next-line arg)
- (setq this-command 'next-line))
-
-(defun end-of-line-mark (&optional arg)
- "Ensure mark is active; move point to end of current line.
-With argument ARG not nil or 1, move forward ARG - 1 lines first.
-If scan reaches end of buffer, stop there without error."
- (interactive "p")
- (ensure-mark)
- (end-of-line arg)
- (setq this-command 'end-of-line))
-
-(defun backward-line-mark (&optional arg)
- "Ensure mark is active; move cursor vertically up ARG lines."
- (interactive "p")
- (ensure-mark)
- (if (null arg)
- (setq arg 1))
- (forward-line (- arg))
- (setq this-command 'forward-line)
-)
-
-(defun scroll-down-mark (&optional arg)
- "Ensure mark is active; scroll down ARG lines; or near full screen if no ARG.
-A near full screen is `next-screen-context-lines' less than a full screen.
-Negative ARG means scroll upward.
-When calling from a program, supply a number as argument or nil."
- (interactive "P")
- (ensure-mark)
- (cond (pc-select-override-scroll-error
- (condition-case nil (scroll-down arg)
- (beginning-of-buffer (goto-char (point-min)))))
- (t (scroll-down arg))))
-
-(defun end-of-buffer-mark (&optional arg)
- "Ensure mark is active; move point to the end of the buffer.
-With arg N, put point N/10 of the way from the end.
-
-If the buffer is narrowed, this command uses the beginning and size
-of the accessible part of the buffer.
-
-Don't use this command in Lisp programs!
-\(goto-char \(point-max)) is faster and avoids clobbering the mark."
- (interactive "P")
- (ensure-mark)
- (let ((size (- (point-max) (point-min))))
- (goto-char (if arg
- (- (point-max)
- (if (> size 10000)
- ;; Avoid overflow for large buffer sizes!
- (* (prefix-numeric-value arg)
- (/ size 10))
- (/ (* size (prefix-numeric-value arg)) 10)))
- (point-max))))
- ;; If we went to a place in the middle of the buffer,
- ;; adjust it to the beginning of a line.
- (if arg (forward-line 1)
- ;; If the end of the buffer is not already on the screen,
- ;; then scroll specially to put it near, but not at, the bottom.
- (if (let ((old-point (point)))
- (save-excursion
- (goto-char (window-start))
- (vertical-motion (window-height))
- (< (point) old-point)))
- (progn
- (overlay-recenter (point))
- (recenter -3)))))
-
-;;;;;;;;;
-;;;;; no mark
-;;;;;;;;;
-
-(defun forward-char-nomark (&optional arg)
- "Deactivate mark; move point right ARG characters \(left if ARG negative).
-On reaching end of buffer, stop and signal error."
- (interactive "p")
- (setq mark-active nil)
- (forward-char arg))
-
-(defun forward-word-nomark (&optional arg)
- "Deactivate mark; move point right ARG words \(backward if ARG is negative).
-Normally returns t.
-If an edge of the buffer is reached, point is left there
-and nil is returned."
- (interactive "p")
- (setq mark-active nil)
- (forward-word arg))
-
-(defun forward-line-nomark (&optional arg)
- "Deactivate mark; move cursor vertically down ARG lines."
- (interactive "p")
- (setq mark-active nil)
- (forward-line arg)
- (setq this-command 'forward-line)
-)
-
-(defun forward-paragraph-nomark (&optional arg)
- "Deactivate mark; move forward to end of paragraph.
-With arg N, do it N times; negative arg -N means move backward N paragraphs.
-
-A line which `paragraph-start' matches either separates paragraphs
-\(if `paragraph-separate' matches it also) or is the first line of a paragraph.
-A paragraph end is the beginning of a line which is not part of the paragraph
-to which the end of the previous line belongs, or the end of the buffer."
- (interactive "p")
- (setq mark-active nil)
- (forward-paragraph arg))
-
-(defun next-line-nomark (&optional arg)
- "Deactivate mark; 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, behavior depends on the
-value of `next-line-add-newlines'. If non-nil, it inserts a newline character
-to create a line, and moves the cursor to that line. Otherwise it moves the
-cursor to the end of the buffer (if already at the end of the buffer, an error
-is signaled).
-
-The command C-x C-n can be used to create
-a semipermanent goal column to which this command always moves.
-Then it does not try to move vertically. This goal column is stored
-in `goal-column', which is nil when there is none."
- (interactive "p")
- (setq mark-active nil)
- (next-line arg)
- (setq this-command 'next-line))
-
-(defun end-of-line-nomark (&optional arg)
- "Deactivate mark; move point to end of current line.
-With argument ARG not nil or 1, move forward ARG - 1 lines first.
-If scan reaches end of buffer, stop there without error."
- (interactive "p")
- (setq mark-active nil)
- (end-of-line arg)
- (setq this-command 'end-of-line))
-
-(defun backward-line-nomark (&optional arg)
- "Deactivate mark; move cursor vertically up ARG lines."
- (interactive "p")
- (setq mark-active nil)
- (if (null arg)
- (setq arg 1))
- (forward-line (- arg))
- (setq this-command 'forward-line)
-)
-
-(defun scroll-down-nomark (&optional arg)
- "Deactivate mark; scroll down ARG lines; or near full screen if no ARG.
-A near full screen is `next-screen-context-lines' less than a full screen.
-Negative ARG means scroll upward.
-When calling from a program, supply a number as argument or nil."
- (interactive "P")
- (setq mark-active nil)
- (cond (pc-select-override-scroll-error
- (condition-case nil (scroll-down arg)
- (beginning-of-buffer (goto-char (point-min)))))
- (t (scroll-down arg))))
-
-(defun end-of-buffer-nomark (&optional arg)
- "Deactivate mark; move point to the end of the buffer.
-With arg N, put point N/10 of the way from the end.
-
-If the buffer is narrowed, this command uses the beginning and size
-of the accessible part of the buffer.
-
-Don't use this command in Lisp programs!
-\(goto-char (point-max)) is faster and avoids clobbering the mark."
- (interactive "P")
- (setq mark-active nil)
- (let ((size (- (point-max) (point-min))))
- (goto-char (if arg
- (- (point-max)
- (if (> size 10000)
- ;; Avoid overflow for large buffer sizes!
- (* (prefix-numeric-value arg)
- (/ size 10))
- (/ (* size (prefix-numeric-value arg)) 10)))
- (point-max))))
- ;; If we went to a place in the middle of the buffer,
- ;; adjust it to the beginning of a line.
- (if arg (forward-line 1)
- ;; If the end of the buffer is not already on the screen,
- ;; then scroll specially to put it near, but not at, the bottom.
- (if (let ((old-point (point)))
- (save-excursion
- (goto-char (window-start))
- (vertical-motion (window-height))
- (< (point) old-point)))
- (progn
- (overlay-recenter (point))
- (recenter -3)))))
-
-
-;;;;;;;;;;;;;;;;;;;;
-;;;;;; backwards and mark
-;;;;;;;;;;;;;;;;;;;;
-
-(defun backward-char-mark (&optional arg)
-"Ensure mark is active; move point left ARG characters (right if ARG negative).
-On attempt to pass beginning or end of buffer, stop and signal error."
- (interactive "p")
- (ensure-mark)
- (backward-char arg))
-
-(defun backward-word-mark (&optional arg)
- "Ensure mark is active; move backward until encountering the end of a word.
-With argument, do this that many times."
- (interactive "p")
- (ensure-mark)
- (backward-word arg))
-
-(defun backward-paragraph-mark (&optional arg)
- "Ensure mark is active; 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."
- (interactive "p")
- (ensure-mark)
- (backward-paragraph arg))
-
-(defun previous-line-mark (&optional arg)
- "Ensure mark is active; 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 C-x C-n 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 a negative argument instead. It is usually easier
-to use and more reliable (no dependence on goal column, etc.)."
- (interactive "p")
- (ensure-mark)
- (previous-line arg)
- (setq this-command 'previous-line))
-
-(defun beginning-of-line-mark (&optional arg)
- "Ensure mark is active; move point to beginning of current line.
-With argument ARG not nil or 1, move forward ARG - 1 lines first.
-If scan reaches end of buffer, stop there without error."
- (interactive "p")
- (ensure-mark)
- (beginning-of-line arg))
-
-
-(defun scroll-up-mark (&optional arg)
-"Ensure mark is active; scroll upward ARG lines; or near full screen if no ARG.
-A near full screen is `next-screen-context-lines' less than a full screen.
-Negative ARG means scroll downward.
-When calling from a program, supply a number as argument or nil."
- (interactive "P")
- (ensure-mark)
- (cond (pc-select-override-scroll-error
- (condition-case nil (scroll-up arg)
- (end-of-buffer (goto-char (point-max)))))
- (t (scroll-up arg))))
-
-(defun beginning-of-buffer-mark (&optional arg)
- "Ensure mark is active; move point to the beginning of the buffer.
-With arg N, put point N/10 of the way from the beginning.
-
-If the buffer is narrowed, this command uses the beginning and size
-of the accessible part of the buffer.
-
-Don't use this command in Lisp programs!
-\(goto-char (p\oint-min)) is faster and avoids clobbering the mark."
- (interactive "P")
- (ensure-mark)
- (let ((size (- (point-max) (point-min))))
- (goto-char (if arg
- (+ (point-min)
- (if (> size 10000)
- ;; Avoid overflow for large buffer sizes!
- (* (prefix-numeric-value arg)
- (/ size 10))
- (/ (+ 10 (* size (prefix-numeric-value arg))) 10)))
- (point-min))))
- (if arg (forward-line 1)))
-
-;;;;;;;;
-;;; no mark
-;;;;;;;;
-
-(defun backward-char-nomark (&optional arg)
- "Deactivate mark; move point left ARG characters (right if ARG negative).
-On attempt to pass beginning or end of buffer, stop and signal error."
- (interactive "p")
- (setq mark-active nil)
- (backward-char arg))
-
-(defun backward-word-nomark (&optional arg)
- "Deactivate mark; move backward until encountering the end of a word.
-With argument, do this that many times."
- (interactive "p")
- (setq mark-active nil)
- (backward-word arg))
-
-(defun backward-paragraph-nomark (&optional arg)
- "Deactivate mark; 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."
- (interactive "p")
- (setq mark-active nil)
- (backward-paragraph arg))
-
-(defun previous-line-nomark (&optional arg)
- "Deactivate mark; 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 C-x C-n can be used to create
-a semipermanent goal column to which this command always moves.
-Then it does not try to move vertically."
- (interactive "p")
- (setq mark-active nil)
- (previous-line arg)
- (setq this-command 'previous-line))
-
-(defun beginning-of-line-nomark (&optional arg)
- "Deactivate mark; move point to beginning of current line.
-With argument ARG not nil or 1, move forward ARG - 1 lines first.
-If scan reaches end of buffer, stop there without error."
- (interactive "p")
- (setq mark-active nil)
- (beginning-of-line arg))
-
-(defun scroll-up-nomark (&optional arg)
- "Deactivate mark; scroll upward ARG lines; or near full screen if no ARG.
-A near full screen is `next-screen-context-lines' less than a full screen.
-Negative ARG means scroll downward.
-When calling from a program, supply a number as argument or nil."
- (interactive "P")
- (setq mark-active nil)
- (cond (pc-select-override-scroll-error
- (condition-case nil (scroll-up arg)
- (end-of-buffer (goto-char (point-max)))))
- (t (scroll-up arg))))
-
-(defun beginning-of-buffer-nomark (&optional arg)
- "Deactivate mark; move point to the beginning of the buffer.
-With arg N, put point N/10 of the way from the beginning.
-
-If the buffer is narrowed, this command uses the beginning and size
-of the accessible part of the buffer.
-
-Don't use this command in Lisp programs!
-\(goto-char (point-min)) is faster and avoids clobbering the mark."
- (interactive "P")
- (setq mark-active nil)
- (let ((size (- (point-max) (point-min))))
- (goto-char (if arg
- (+ (point-min)
- (if (> size 10000)
- ;; Avoid overflow for large buffer sizes!
- (* (prefix-numeric-value arg)
- (/ size 10))
- (/ (+ 10 (* size (prefix-numeric-value arg))) 10)))
- (point-min))))
- (if arg (forward-line 1)))
-
-;;;###autoload
-(defun pc-selection-mode ()
- "Change mark behaviour to emulate Motif, MAC or MS-Windows cut and paste style.
-
-This mode enables Delete Selection mode and Transient Mark mode.
-
-The arrow keys (and others) are bound to new functions
-which modify the status of the mark.
-
-The ordinary arrow keys disable the mark.
-The shift-arrow keys move, leaving the mark behind.
-
-C-LEFT and C-RIGHT move back or forward one word, disabling the mark.
-S-C-LEFT and S-C-RIGHT move back or forward one word, leaving the mark behind.
-
-C-DOWN and C-UP move back or forward a paragraph, disabling the mark.
-S-C-DOWN and S-C-UP move back or forward a paragraph, leaving the mark behind.
-
-HOME moves to beginning of line, disabling the mark.
-S-HOME moves to beginning of line, leaving the mark behind.
-With Ctrl or Meta, these keys move to beginning of buffer instead.
-
-END moves to end of line, disabling the mark.
-S-END moves to end of line, leaving the mark behind.
-With Ctrl or Meta, these keys move to end of buffer instead.
-
-PRIOR or PAGE-UP scrolls and disables the mark.
-S-PRIOR or S-PAGE-UP scrolls and leaves the mark behind.
-
-S-DELETE kills the region (`kill-region').
-S-INSERT yanks text from the kill ring (`yank').
-C-INSERT copies the region into the kill ring (`copy-region-as-kill').
-
-In addition, certain other PC bindings are imitated:
-
- F6 other-window
- DELETE delete-char
- C-DELETE kill-line
- M-DELETE kill-word
- C-M-DELETE kill-sexp
- C-BACKSPACE backward-kill-word
- M-BACKSPACE undo"
-
- (interactive)
- ;;
- ;; keybindings
- ;;
-
- ;; This is to avoid confusion with the delete-selection-mode
- ;; On simple displays you can't see that a region is active and
- ;; will be deleted on the next keypress. IMHO especially for
- ;; copy-region-as-kill this is confusing
- (define-key global-map "\M-w" 'copy-region-as-kill-nomark)
-
-
- ;; The following keybindings are for standard ISO keyboards
- ;; as they are used with IBM compatible PCs, IBM RS/6000,
- ;; MACs, many X-Stations and probably more
- (define-key global-map [S-right] 'forward-char-mark)
- (define-key global-map [right] 'forward-char-nomark)
- (define-key global-map [C-S-right] 'forward-word-mark)
- (define-key global-map [C-right] 'forward-word-nomark)
- (define-key global-map [M-S-right] 'forward-word-mark)
- (define-key global-map [M-right] 'forward-word-nomark)
-
- (define-key global-map [S-down] 'next-line-mark)
- (define-key global-map [down] 'next-line-nomark)
-
- (define-key global-map [S-end] 'end-of-line-mark)
- (define-key global-map [end] 'end-of-line-nomark)
- (global-set-key [S-C-end] 'end-of-buffer-mark)
- (global-set-key [C-end] 'end-of-buffer-nomark)
- (global-set-key [S-M-end] 'end-of-buffer-mark)
- (global-set-key [M-end] 'end-of-buffer-nomark)
-
- (define-key global-map [S-next] 'scroll-up-mark)
- (define-key global-map [next] 'scroll-up-nomark)
-
- (define-key global-map [S-left] 'backward-char-mark)
- (define-key global-map [left] 'backward-char-nomark)
- (define-key global-map [C-S-left] 'backward-word-mark)
- (define-key global-map [C-left] 'backward-word-nomark)
- (define-key global-map [M-S-left] 'backward-word-mark)
- (define-key global-map [M-left] 'backward-word-nomark)
-
- (define-key global-map [S-up] 'previous-line-mark)
- (define-key global-map [up] 'previous-line-nomark)
-
- (define-key global-map [S-home] 'beginning-of-line-mark)
- (define-key global-map [home] 'beginning-of-line-nomark)
- (global-set-key [S-C-home] 'beginning-of-buffer-mark)
- (global-set-key [C-home] 'beginning-of-buffer-nomark)
- (global-set-key [S-M-home] 'beginning-of-buffer-mark)
- (global-set-key [M-home] 'beginning-of-buffer-nomark)
-
- (define-key global-map [S-prior] 'scroll-down-mark)
- (define-key global-map [prior] 'scroll-down-nomark)
-
- (define-key global-map [S-insert] 'yank)
- (define-key global-map [C-insert] 'copy-region-as-kill)
- (define-key global-map [S-delete] 'kill-region)
-
- (define-key global-map [M-S-down] 'forward-line-mark)
- (define-key global-map [M-down] 'forward-line-nomark)
- (define-key global-map [M-S-up] 'backward-line-mark)
- (define-key global-map [M-up] 'backward-line-nomark)
-
- ;; The following bindings are useful on Sun Type 3 keyboards
- ;; They implement the Get-Delete-Put (copy-cut-paste)
- ;; functions from sunview on the L6, L8 and L10 keys
- (define-key global-map [f16] 'yank)
- (define-key global-map [f18] 'copy-region-as-kill)
- (define-key global-map [f20] 'kill-region)
-
- ;; The following bindings are from Pete Forman.
- ;; I modified them a little to work together with the
- ;; mark functionality I added.
-
- (global-set-key [f6] 'other-window) ; KNextPane F6
- (global-set-key [delete] 'delete-char) ; KDelete Del
- (global-set-key [C-delete] 'kill-line) ; KEraseEndLine cDel
- (global-set-key [M-backspace] 'undo) ; KUndo aBS
- (global-set-key [C-down] 'forward-paragraph-nomark) ; KNextPara cDn
- (global-set-key [C-up] 'backward-paragraph-nomark) ; KPrevPara cUp
- (global-set-key [S-C-down] 'forward-paragraph-mark)
- (global-set-key [S-C-up] 'backward-paragraph-mark)
-
- ;; The following bindings are taken from pc-mode.el
- ;; as suggested by RMS.
- ;; I only used the ones that are not covered above.
- (define-key function-key-map [M-delete] [?\M-d])
- (global-set-key [C-M-delete] 'kill-sexp)
- (global-set-key [C-backspace] 'backward-kill-word)
- (global-set-key [C-escape] 'list-buffers)
-
- ;;
- ;; setup
- ;;
- (setq transient-mark-mode t)
- (setq mark-even-if-inactive t)
- (delete-selection-mode 1)
-)
-;;; pc-select.el ends here
diff --git a/lisp/emulation/tpu-edt.el b/lisp/emulation/tpu-edt.el
deleted file mode 100644
index 7388e5144c0..00000000000
--- a/lisp/emulation/tpu-edt.el
+++ /dev/null
@@ -1,2490 +0,0 @@
-;;; tpu-edt.el --- Emacs emulating TPU emulating EDT
-
-;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Rob Riepel <riepel@networking.stanford.edu>
-;; Maintainer: Rob Riepel <riepel@networking.stanford.edu>
-;; Version: 4.2
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; TPU-edt is based on tpu.el by Jeff Kowalski and Bob Covey.
-
-;;; Commentary:
-
-;; %% TPU-edt -- Emacs emulating TPU emulating EDT
-
-;; %% Contents
-
-;; % Introduction
-;; % Differences Between TPU-edt and DEC TPU/edt
-;; % Starting TPU-edt
-;; % Customizing TPU-edt using the Emacs Initialization File
-;; % Regular Expressions in TPU-edt
-
-
-;; %% Introduction
-
-;; TPU-edt emulates the popular DEC VMS editor EDT (actually, it emulates
-;; DEC TPU's EDT emulation, hence the name TPU-edt). TPU-edt features the
-;; following TPU/edt functionality:
-
-;; . EDT keypad
-;; . On-line help
-;; . Repeat counts
-;; . Scroll margins
-;; . Learn sequences
-;; . Free cursor mode
-;; . Rectangular cut and paste
-;; . Multiple windows and buffers
-;; . TPU line-mode REPLACE command
-;; . Wild card search and substitution
-;; . Configurable through an initialization file
-;; . History recall of search strings, file names, and commands
-
-;; Please note that TPU-edt does NOT emulate TPU. It emulates TPU's EDT
-;; emulation. Very few TPU line-mode commands are supported.
-
-;; TPU-edt, like its VMS cousin, works on VT-series terminals with DEC
-;; style keyboards. VT terminal emulators, including xterm with the
-;; appropriate key translations, work just fine too.
-
-;; TPU-edt works with X-windows. This is accomplished through a TPU-edt X
-;; key map. The TPU-edt module tpu-mapper creates this map and stores it
-;; in a file. Tpu-mapper will be run automatically the first time you
-;; invoke the X-windows version of emacs, or you can run it by hand. See
-;; the commentary in tpu-mapper.el for details.
-
-
-;; %% Differences Between TPU-edt and DEC TPU/edt
-
-;; In some cases, Emacs doesn't support text highlighting, so selected
-;; regions are not shown in inverse video. Emacs uses the concept of "the
-;; mark". The mark is set at one end of a selected region; the cursor is
-;; at the other. The letter "M" appears in the mode line when the mark is
-;; set. The native emacs command ^X^X (Control-X twice) exchanges the
-;; cursor with the mark; this provides a handy way to find the location of
-;; the mark.
-
-;; In TPU the cursor can be either bound or free. Bound means the cursor
-;; cannot wander outside the text of the file being edited. Free means
-;; the arrow keys can move the cursor past the ends of lines. Free is the
-;; default mode in TPU; bound is the only mode in EDT. Bound is the only
-;; mode in the base version of TPU-edt; optional extensions add an
-;; approximation of free mode, see the commentary in tpu-extras.el for
-;; details.
-
-;; Like TPU, emacs uses multiple buffers. Some buffers are used to hold
-;; files you are editing; other "internal" buffers are used for emacs' own
-;; purposes (like showing you help). Here are some commands for dealing
-;; with buffers.
-
-;; Gold-B moves to next buffer, including internal buffers
-;; Gold-N moves to next buffer containing a file
-;; Gold-M brings up a buffer menu (like TPU "show buffers")
-
-;; Emacs is very fond of throwing up new windows. Dealing with all these
-;; windows can be a little confusing at first, so here are a few commands
-;; to that may help:
-
-;; Gold-Next_Scr moves to the next window on the screen
-;; Gold-Prev_Scr moves to the previous window on the screen
-;; Gold-TAB also moves to the next window on the screen
-
-;; Control-x 1 deletes all but the current window
-;; Control-x 0 deletes the current window
-
-;; Note that the buffers associated with deleted windows still exist!
-
-;; Like TPU, TPU-edt has a "command" function, invoked with Gold-KP7 or
-;; Do. Most of the commands available are emacs commands. Some TPU
-;; commands are available, they are: replace, exit, quit, include, and
-;; Get (unfortunately, "get" is an internal emacs function, so we are
-;; stuck with "Get" - to make life easier, Get is available as Gold-g).
-
-;; TPU-edt supports the recall of commands, file names, and search
-;; strings. The history of strings recalled differs slightly from
-;; TPU/edt, but it is still very convenient.
-
-;; Help is available! The traditional help keys (Help and PF2) display
-;; a small help file showing the default keypad layout, control key
-;; functions, and Gold key functions. Pressing any key inside of help
-;; splits the screen and prints a description of the function of the
-;; pressed key. Gold-PF2 invokes the native emacs help, with its
-;; zillions of options.
-
-;; Thanks to emacs, TPU-edt has some extensions that may make your life
-;; easier, or at least more interesting. For example, Gold-r toggles
-;; TPU-edt rectangular mode. In rectangular mode, Remove and Insert work
-;; on rectangles. Likewise, Gold-* toggles TPU-edt regular expression
-;; mode. In regular expression mode Find, Find Next, and the line-mode
-;; replace command work with regular expressions. [A regular expression
-;; is a pattern that denotes a set of strings; like VMS wildcards.]
-
-;; Emacs also gives TPU-edt the undo and occur functions. Undo does
-;; what it says; it undoes the last change. Multiple undos in a row
-;; undo multiple changes. For your convenience, undo is available on
-;; Gold-u. Occur shows all the lines containing a specific string in
-;; another window. Moving to that window, and typing ^C^C (Control-C
-;; twice) on a particular line moves you back to the original window
-;; at that line. Occur is on Gold-o.
-
-;; Finally, as you edit, remember that all the power of emacs is at
-;; your disposal. It really is a fantastic tool. You may even want to
-;; take some time and read the emacs tutorial; perhaps not to learn the
-;; native emacs key bindings, but to get a feel for all the things
-;; emacs can do for you. The emacs tutorial is available from the
-;; emacs help function: "Gold-PF2 t"
-
-
-;; %% Starting TPU-edt
-
-;; All you have to do to start TPU-edt, is turn it on. This can be
-;; done from the command line when running emacs.
-
-;; prompt> emacs -f tpu-edt
-
-;; If you've already started emacs, turn on TPU-edt using the tpu-edt
-;; command. First press `M-x' (that's usually `ESC' followed by `x')
-;; and type `tpu-edt' followed by a carriage return.
-
-;; If you like TPU-edt and want to use it all the time, you can start
-;; TPU-edt using the emacs initialization file, .emacs. Simply create
-;; a .emacs file in your home directory containing the line:
-
-;; (tpu-edt)
-
-;; That's all you need to do to start TPU-edt.
-
-
-;; %% Customizing TPU-edt using the Emacs Initialization File
-
-;; The following is a sample emacs initialization file. It shows how to
-;; invoke TPU-edt, and how to customize it.
-
-;; ; .emacs - a sample emacs initialization file
-
-;; ; Turn on TPU-edt
-;; (tpu-edt)
-
-;; ; Set scroll margins 10% (top) and 15% (bottom).
-;; (tpu-set-scroll-margins "10%" "15%")
-
-;; ; Load the vtxxx terminal control functions.
-;; (load "vt-control" t)
-
-;; ; TPU-edt treats words like EDT; here's how to add word separators.
-;; ; Note that backslash (\) and double quote (") are quoted with '\'.
-;; (tpu-add-word-separators "]\\[-_,.\"=+()'/*#:!&;$")
-
-;; ; Emacs is happy to save files without a final newline; other Unix
-;; ; programs hate that! Here we make sure that files end with newlines.
-;; (setq require-final-newline t)
-
-;; ; Emacs uses Control-s and Control-q. Problems can occur when using
-;; ; emacs on terminals that use these codes for flow control (Xon/Xoff
-;; ; flow control). These lines disable emacs' use of these characters.
-;; (global-unset-key "\C-s")
-;; (global-unset-key "\C-q")
-
-;; ; The emacs universal-argument function is very useful.
-;; ; This line maps universal-argument to Gold-PF1.
-;; (define-key GOLD-SS3-map "P" 'universal-argument) ; Gold-PF1
-
-;; ; Make KP7 move by paragraphs, instead of pages.
-;; (define-key SS3-map "w" 'tpu-paragraph) ; KP7
-
-;; ; Repeat the preceding mappings for X-windows.
-;; (cond
-;; (window-system
-;; (global-set-key [kp_7] 'tpu-paragraph) ; KP7
-;; (define-key GOLD-map [kp_f1] 'universal-argument))) ; GOLD-PF1
-
-;; ; Display the TPU-edt version.
-;; (tpu-version)
-
-
-;; %% Regular Expressions in TPU-edt
-
-;; Gold-* toggles TPU-edt regular expression mode. In regular expression
-;; mode, find, find next, replace, and substitute accept emacs regular
-;; expressions. A complete list of emacs regular expressions can be found
-;; using the emacs "info" command (it's somewhat like the VMS help
-;; command). Try the following sequence of commands:
-
-;; DO info <enter info mode>
-;; m emacs <select the "emacs" topic>
-;; m regexs <select the "regular expression" topic>
-
-;; Type "q" to quit out of info mode.
-
-;; There is a problem in regular expression mode when searching for empty
-;; strings, like beginning-of-line (^) and end-of-line ($). When searching
-;; for these strings, find-next may find the current string, instead of the
-;; next one. This can cause global replace and substitute commands to loop
-;; forever in the same location. For this reason, commands like
-
-;; replace "^" "> " <add "> " to beginning of line>
-;; replace "$" "00711" <add "00711" to end of line>
-
-;; may not work properly.
-
-;; Commands like those above are very useful for adding text to the
-;; beginning or end of lines. They might work on a line-by-line basis, but
-;; go into an infinite loop if the "all" response is specified. If the
-;; goal is to add a string to the beginning or end of a particular set of
-;; lines TPU-edt provides functions to do this.
-
-;; Gold-^ Add a string at BOL in region or buffer
-;; Gold-$ Add a string at EOL in region or buffer
-
-;; There is also a TPU-edt interface to the native emacs string replacement
-;; commands. Gold-/ invokes this command. It accepts regular expressions
-;; if TPU-edt is in regular expression mode. Given a repeat count, it will
-;; perform the replacement without prompting for confirmation.
-
-;; This command replaces empty strings correctly, however, it has its
-;; drawbacks. As a native emacs command, it has a different interface
-;; than the emulated TPU commands. Also, it works only in the forward
-;; direction, regardless of the current TPU-edt direction.
-
-;;; Code:
-
-
-;;;
-;;; Version Information
-;;;
-(defconst tpu-version "4.2" "TPU-edt version number.")
-
-
-;;;
-;;; User Configurable Variables
-;;;
-(defconst tpu-have-ispell t
- "*If non-nil (default), TPU-edt uses ispell for spell checking.")
-
-(defconst tpu-kill-buffers-silently nil
- "*If non-nil, TPU-edt kills modified buffers without asking.")
-
-(defvar tpu-percent-scroll 75
- "*Percentage of the screen to scroll for next/previous screen commands.")
-
-(defvar tpu-pan-columns 16
- "*Number of columns the tpu-pan functions scroll left or right.")
-
-
-;;;
-;;; Emacs version identifiers - currently referenced by
-;;;
-;;; o tpu-mark o tpu-set-mark
-;;; o tpu-string-prompt o tpu-regexp-prompt
-;;; o tpu-edt-on o tpu-load-xkeys
-;;; o tpu-update-mode-line o mode line section
-;;;
-(defconst tpu-emacs19-p (not (string-lessp emacs-version "19"))
- "Non-nil if we are running Lucid Emacs or version 19.")
-
-(defconst tpu-lucid-emacs19-p
- (and tpu-emacs19-p (string-match "Lucid" emacs-version))
- "Non-nil if we are running Lucid Emacs version 19.")
-
-
-;;;
-;;; Global Keymaps
-;;;
-(defvar CSI-map (make-sparse-keymap)
- "Maps the CSI function keys on the VT100 keyboard.
-CSI is DEC's name for the sequence <ESC>[.")
-
-(defvar SS3-map (make-sparse-keymap)
- "Maps the SS3 function keys on the VT100 keyboard.
-SS3 is DEC's name for the sequence <ESC>O.")
-
-(defvar GOLD-map (make-keymap)
- "Maps the function keys on the VT100 keyboard preceded by PF1.
-GOLD is the ASCII 7-bit escape sequence <ESC>OP.")
-
-(defvar GOLD-CSI-map (make-sparse-keymap)
- "Maps the function keys on the VT100 keyboard preceded by GOLD-CSI.")
-
-(defvar GOLD-SS3-map (make-sparse-keymap)
- "Maps the function keys on the VT100 keyboard preceded by GOLD-SS3.")
-
-(defvar tpu-global-map nil "TPU-edt global keymap.")
-(defvar tpu-original-global-map (copy-keymap global-map)
- "Original global keymap.")
-
-(and tpu-lucid-emacs19-p
- (defvar minibuffer-local-ns-map (make-sparse-keymap)
- "Hack to give Lucid Emacs the same maps as ordinary Emacs."))
-
-
-;;;
-;;; Global Variables
-;;;
-(defvar tpu-edt-mode nil
- "If non-nil, TPU-edt mode is active.")
-
-(defvar tpu-last-replaced-text ""
- "Last text deleted by a TPU-edt replace command.")
-(defvar tpu-last-deleted-region ""
- "Last text deleted by a TPU-edt remove command.")
-(defvar tpu-last-deleted-lines ""
- "Last text deleted by a TPU-edt line-delete command.")
-(defvar tpu-last-deleted-words ""
- "Last text deleted by a TPU-edt word-delete command.")
-(defvar tpu-last-deleted-char ""
- "Last character deleted by a TPU-edt character-delete command.")
-
-(defvar tpu-searching-forward t
- "If non-nil, TPU-edt is searching in the forward direction.")
-(defvar tpu-search-last-string ""
- "Last text searched for by the TPU-edt search commands.")
-
-(defvar tpu-regexp-p nil
- "If non-nil, TPU-edt uses regexp search and replace routines.")
-(defvar tpu-rectangular-p nil
- "If non-nil, TPU-edt removes and inserts rectangles.")
-(defvar tpu-advance t
- "True when TPU-edt is operating in the forward direction.")
-(defvar tpu-reverse nil
- "True when TPU-edt is operating in the backward direction.")
-(defvar tpu-control-keys nil
- "If non-nil, control keys are set to perform TPU functions.")
-(defvar tpu-xkeys-file nil
- "File containing TPU-edt X key map.")
-
-(defvar tpu-rectangle-string nil
- "Mode line string to identify rectangular mode.")
-(defvar tpu-direction-string nil
- "Mode line string to identify current direction.")
-
-(defvar tpu-add-at-bol-hist nil
- "History variable for tpu-edt-add-at-bol function.")
-(defvar tpu-add-at-eol-hist nil
- "History variable for tpu-edt-add-at-eol function.")
-(defvar tpu-regexp-prompt-hist nil
- "History variable for search and replace functions.")
-
-
-;;;
-;;; Buffer Local Variables
-;;;
-(defvar tpu-newline-and-indent-p nil
- "If non-nil, Return produces a newline and indents.")
-(make-variable-buffer-local 'tpu-newline-and-indent-p)
-
-(defvar tpu-newline-and-indent-string nil
- "Mode line string to identify AutoIndent mode.")
-(make-variable-buffer-local 'tpu-newline-and-indent-string)
-
-(defvar tpu-saved-delete-func nil
- "Saved value of the delete key.")
-(make-variable-buffer-local 'tpu-saved-delete-func)
-
-(defvar tpu-buffer-local-map nil
- "TPU-edt buffer local key map.")
-(make-variable-buffer-local 'tpu-buffer-local-map)
-
-
-;;;
-;;; Mode Line - Modify the mode line to show the following
-;;;
-;;; o If the mark is set.
-;;; o Direction of motion.
-;;; o Active rectangle mode.
-;;;
-(defvar tpu-original-mode-line mode-line-format)
-(defvar tpu-original-mm-alist minor-mode-alist)
-
-(defvar tpu-mark-flag " ")
-(make-variable-buffer-local 'tpu-mark-flag)
-
-(defun tpu-set-mode-line (for-tpu)
- "Set the mode for TPU-edt, or reset it to default Emacs."
- (cond ((not for-tpu)
- (setq mode-line-format tpu-original-mode-line)
- (setq minor-mode-alist tpu-original-mm-alist))
- (t
- (setq-default mode-line-format
- (list (purecopy "")
- 'mode-line-modified
- 'mode-line-buffer-identification
- (purecopy " ")
- 'global-mode-string
- (purecopy " ")
- 'tpu-mark-flag
- (purecopy " %[(")
- 'mode-name 'mode-line-process 'minor-mode-alist
- (purecopy "%n")
- (purecopy ")%]--")
- (purecopy '(line-number-mode "L%l--"))
- (purecopy '(column-number-mode "C%c--"))
- (purecopy '(-3 . "%p"))
- (purecopy "-%-")))
- (or (assq 'tpu-newline-and-indent-p minor-mode-alist)
- (setq minor-mode-alist
- (cons '(tpu-newline-and-indent-p
- tpu-newline-and-indent-string)
- minor-mode-alist)))
- (or (assq 'tpu-rectangular-p minor-mode-alist)
- (setq minor-mode-alist
- (cons '(tpu-rectangular-p tpu-rectangle-string)
- minor-mode-alist)))
- (or (assq 'tpu-direction-string minor-mode-alist)
- (setq minor-mode-alist
- (cons '(tpu-direction-string tpu-direction-string)
- minor-mode-alist))))))
-
-(defun tpu-update-mode-line nil
- "Make sure mode-line in the current buffer reflects all changes."
- (setq tpu-mark-flag (if (tpu-mark) "M" " "))
- (cond (tpu-emacs19-p (force-mode-line-update))
- (t (set-buffer-modified-p (buffer-modified-p)) (sit-for 0))))
-
-(cond (tpu-lucid-emacs19-p
- (add-hook 'zmacs-deactivate-region-hook 'tpu-update-mode-line)
- (add-hook 'zmacs-activate-region-hook 'tpu-update-mode-line))
- (tpu-emacs19-p
- (add-hook 'activate-mark-hook 'tpu-update-mode-line)
- (add-hook 'deactivate-mark-hook 'tpu-update-mode-line)))
-
-
-;;;
-;;; Match Markers -
-;;;
-;;; Set in: Search
-;;;
-;;; Used in: Replace, Substitute, Store-Text, Cut/Remove,
-;;; Append, and Change-Case
-;;;
-(defvar tpu-match-beginning-mark (make-marker))
-(defvar tpu-match-end-mark (make-marker))
-
-(defun tpu-set-match nil
- "Set markers at match beginning and end."
- ;; Add one to beginning mark so it stays with the first character of
- ;; the string even if characters are added just before the string.
- (setq tpu-match-beginning-mark (copy-marker (1+ (match-beginning 0))))
- (setq tpu-match-end-mark (copy-marker (match-end 0))))
-
-(defun tpu-unset-match nil
- "Unset match beginning and end markers."
- (set-marker tpu-match-beginning-mark nil)
- (set-marker tpu-match-end-mark nil))
-
-(defun tpu-match-beginning nil
- "Returns the location of the last match beginning."
- (1- (marker-position tpu-match-beginning-mark)))
-
-(defun tpu-match-end nil
- "Returns the location of the last match end."
- (marker-position tpu-match-end-mark))
-
-(defun tpu-check-match nil
- "Returns t if point is between tpu-match markers.
-Otherwise sets the tpu-match markers to nil and returns nil."
- ;; make sure 1- marker is in this buffer
- ;; 2- point is at or after beginning marker
- ;; 3- point is before ending marker, or in the case of
- ;; zero length regions (like bol, or eol) that the
- ;; beginning, end, and point are equal.
- (cond ((and
- (equal (marker-buffer tpu-match-beginning-mark) (current-buffer))
- (>= (point) (1- (marker-position tpu-match-beginning-mark)))
- (or
- (< (point) (marker-position tpu-match-end-mark))
- (and (= (1- (marker-position tpu-match-beginning-mark))
- (marker-position tpu-match-end-mark))
- (= (marker-position tpu-match-end-mark) (point))))) t)
- (t
- (tpu-unset-match) nil)))
-
-(defun tpu-show-match-markers nil
- "Show the values of the match markers."
- (interactive)
- (if (markerp tpu-match-beginning-mark)
- (let ((beg (marker-position tpu-match-beginning-mark)))
- (message "(%s, %s) in %s -- current %s in %s"
- (if beg (1- beg) nil)
- (marker-position tpu-match-end-mark)
- (marker-buffer tpu-match-end-mark)
- (point) (current-buffer)))))
-
-
-;;;
-;;; Utilities
-;;;
-(defun tpu-caar (thingy) (car (car thingy)))
-(defun tpu-cadr (thingy) (car (cdr thingy)))
-
-(defun tpu-mark nil
- "TPU-edt version of the mark function.
-Return the appropriate value of the mark for the current
-version of Emacs."
- (cond (tpu-lucid-emacs19-p (mark (not zmacs-regions)))
- (tpu-emacs19-p (and mark-active (mark (not transient-mark-mode))))
- (t (mark))))
-
-(defun tpu-set-mark (pos)
- "TPU-edt verion of the `set-mark' function.
-Sets the mark at POS and activates the region according to the
-current version of Emacs."
- (set-mark pos)
- (and tpu-lucid-emacs19-p pos (zmacs-activate-region)))
-
-(defun tpu-string-prompt (prompt history-symbol)
- "Read a string with PROMPT."
- (if tpu-emacs19-p
- (read-from-minibuffer prompt nil nil nil history-symbol)
- (read-string prompt)))
-
-(defvar tpu-last-answer nil "Most recent response to tpu-y-or-n-p.")
-
-(defun tpu-y-or-n-p (prompt &optional not-yes)
- "Prompt for a y or n answer with positive default.
-Optional second argument NOT-YES changes default to negative.
-Like Emacs `y-or-n-p', but also accepts space as y and DEL as n."
- (message "%s[%s]" prompt (if not-yes "n" "y"))
- (let ((doit t))
- (while doit
- (setq doit nil)
- (let ((ans (read-char)))
- (cond ((or (= ans ?y) (= ans ?Y) (= ans ?\ ))
- (setq tpu-last-answer t))
- ((or (= ans ?n) (= ans ?N) (= ans ?\C-?))
- (setq tpu-last-answer nil))
- ((= ans ?\r) (setq tpu-last-answer (not not-yes)))
- (t
- (setq doit t) (beep)
- (message "Please answer y or n. %s[%s]"
- prompt (if not-yes "n" "y")))))))
- tpu-last-answer)
-
-(defun tpu-local-set-key (key func)
- "Replace a key in the TPU-edt local key map.
-Create the key map if necessary."
- (cond ((not (keymapp tpu-buffer-local-map))
- (setq tpu-buffer-local-map (if (current-local-map)
- (copy-keymap (current-local-map))
- (make-sparse-keymap)))
- (use-local-map tpu-buffer-local-map)))
- (local-set-key key func))
-
-(defun tpu-current-line nil
- "Return the vertical position of point in the selected window.
-Top line is 0. Counts each text line only once, even if it wraps."
- (+ (count-lines (window-start) (point)) (if (= (current-column) 0) 1 0) -1))
-
-
-;;;
-;;; Breadcrumbs
-;;;
-(defvar tpu-breadcrumb-plist nil
- "The set of user-defined markers (breadcrumbs), as a plist.")
-
-(defun tpu-drop-breadcrumb (num)
- "Drops a breadcrumb that can be returned to later with goto-breadcrumb."
- (interactive "p")
- (put tpu-breadcrumb-plist num (list (current-buffer) (point)))
- (message "Mark %d set." num))
-
-(defun tpu-goto-breadcrumb (num)
- "Returns to a breadcrumb set with drop-breadcrumb."
- (interactive "p")
- (cond ((get tpu-breadcrumb-plist num)
- (switch-to-buffer (car (get tpu-breadcrumb-plist num)))
- (goto-char (tpu-cadr (get tpu-breadcrumb-plist num)))
- (message "mark %d found." num))
- (t
- (message "mark %d not found." num))))
-
-
-;;;
-;;; Miscellaneous
-;;;
-(defun tpu-change-case (num)
- "Change the case of the character under the cursor or region.
-Accepts a prefix argument of the number of characters to invert."
- (interactive "p")
- (cond ((tpu-mark)
- (let ((beg (region-beginning)) (end (region-end)))
- (while (> end beg)
- (funcall (if (= (downcase (char-after beg)) (char-after beg))
- 'upcase-region 'downcase-region)
- beg (1+ beg))
- (setq beg (1+ beg)))
- (tpu-unselect t)))
- ((tpu-check-match)
- (let ((beg (tpu-match-beginning)) (end (tpu-match-end)))
- (while (> end beg)
- (funcall (if (= (downcase (char-after beg)) (char-after beg))
- 'upcase-region 'downcase-region)
- beg (1+ beg))
- (setq beg (1+ beg)))
- (tpu-unset-match)))
- (t
- (while (> num 0)
- (funcall (if (= (downcase (following-char)) (following-char))
- 'upcase-region 'downcase-region)
- (point) (1+ (point)))
- (forward-char (if tpu-reverse -1 1))
- (setq num (1- num))))))
-
-(defun tpu-fill (num)
- "Fill paragraph or marked region.
-With argument, fill and justify."
- (interactive "P")
- (cond ((tpu-mark)
- (fill-region (point) (tpu-mark) num)
- (tpu-unselect t))
- (t
- (fill-paragraph num))))
-
-(defun tpu-version nil
- "Print the TPU-edt version number."
- (interactive)
- (message
- "TPU-edt version %s by Rob Riepel (riepel@networking.stanford.edu)"
- tpu-version))
-
-(defun tpu-reset-screen-size (height width)
- "Sets the screen size."
- (interactive "nnew screen height: \nnnew screen width: ")
- (set-screen-height height)
- (set-screen-width width))
-
-(defun tpu-toggle-newline-and-indent nil
- "Toggle between 'newline and indent' and 'simple newline'."
- (interactive)
- (cond (tpu-newline-and-indent-p
- (setq tpu-newline-and-indent-string "")
- (setq tpu-newline-and-indent-p nil)
- (tpu-local-set-key "\C-m" 'newline))
- (t
- (setq tpu-newline-and-indent-string " AutoIndent")
- (setq tpu-newline-and-indent-p t)
- (tpu-local-set-key "\C-m" 'newline-and-indent)))
- (tpu-update-mode-line)
- (and (interactive-p)
- (message "Carriage return inserts a newline%s"
- (if tpu-newline-and-indent-p " and indents." "."))))
-
-(defun tpu-spell-check nil
- "Checks the spelling of the region, or of the entire buffer if no
- region is selected."
- (interactive)
- (cond (tpu-have-ispell
- (if (tpu-mark) (ispell-region (tpu-mark) (point)) (ispell-buffer)))
- (t
- (if (tpu-mark) (spell-region (tpu-mark) (point)) (spell-buffer))))
- (if (tpu-mark) (tpu-unselect t)))
-
-(defun tpu-toggle-overwrite-mode nil
- "Switches in and out of overwrite mode"
- (interactive)
- (cond (overwrite-mode
- (tpu-local-set-key "\177" tpu-saved-delete-func)
- (overwrite-mode 0))
- (t
- (setq tpu-saved-delete-func (local-key-binding "\177"))
- (tpu-local-set-key "\177" 'picture-backward-clear-column)
- (overwrite-mode 1))))
-
-(defun tpu-special-insert (num)
- "Insert a character or control code according to
-its ASCII decimal value."
- (interactive "P")
- (if overwrite-mode (delete-char 1))
- (insert (if num num 0)))
-
-(defun tpu-quoted-insert (num)
- "Read next input character and insert it.
-This is useful for inserting control characters."
- (interactive "*p")
- (let ((char (read-char)) )
- (if overwrite-mode (delete-char num))
- (insert-char char num)))
-
-
-;;;
-;;; TPU line-mode commands
-;;;
-(defun tpu-include (file)
- "TPU-like include file"
- (interactive "fInclude file: ")
- (save-excursion
- (insert-file file)
- (message "")))
-
-(defun tpu-get (file)
- "TPU-like get file"
- (interactive "FFile to get: ")
- (find-file file))
-
-(defun tpu-what-line nil
- "Tells what line the point is on,
- and the total number of lines in the buffer."
- (interactive)
- (if (eobp)
- (message "You are at the End of Buffer. The last line is %d."
- (count-lines 1 (point-max)))
- (message "Line %d of %d"
- (count-lines 1 (1+ (point)))
- (count-lines 1 (point-max)))))
-
-(defun tpu-exit nil
- "Exit the way TPU does, save current buffer and ask about others."
- (interactive)
- (if (not (eq (recursion-depth) 0))
- (exit-recursive-edit)
- (progn (save-buffer) (save-buffers-kill-emacs))))
-
-(defun tpu-quit nil
- "Quit the way TPU does, ask to make sure changes should be abandoned."
- (interactive)
- (let ((list (buffer-list))
- (working t))
- (while (and list working)
- (let ((buffer (car list)))
- (if (and (buffer-file-name buffer) (buffer-modified-p buffer))
- (if (tpu-y-or-n-p
- "Modifications will not be saved, continue quitting? ")
- (kill-emacs t) (setq working nil)))
- (setq list (cdr list))))
- (if working (kill-emacs t))))
-
-
-;;;
-;;; Command and Function Aliases
-;;;
-;;;###autoload
-(fset 'tpu-edt-mode 'tpu-edt-on)
-(fset 'TPU-EDT-MODE 'tpu-edt-on)
-
-;;;###autoload
-(fset 'tpu-edt 'tpu-edt-on)
-(fset 'TPU-EDT 'tpu-edt-on)
-
-(fset 'exit 'tpu-exit)
-(fset 'EXIT 'tpu-exit)
-
-(fset 'Get 'tpu-get)
-(fset 'GET 'tpu-get)
-
-(fset 'include 'tpu-include)
-(fset 'INCLUDE 'tpu-include)
-
-(fset 'quit 'tpu-quit)
-(fset 'QUIT 'tpu-quit)
-
-(fset 'spell 'tpu-spell-check)
-(fset 'SPELL 'tpu-spell-check)
-
-(fset 'what\ line 'tpu-what-line)
-(fset 'WHAT\ LINE 'tpu-what-line)
-
-(fset 'replace 'tpu-lm-replace)
-(fset 'REPLACE 'tpu-lm-replace)
-
-;; Apparently TPU users really expect to do M-x help RET to get help.
-;; So it is really necessary to redefine this.
-(fset 'help 'tpu-help)
-(fset 'HELP 'tpu-help)
-
-(fset 'set\ cursor\ free 'tpu-set-cursor-free)
-(fset 'SET\ CURSOR\ FREE 'tpu-set-cursor-free)
-
-(fset 'set\ cursor\ bound 'tpu-set-cursor-bound)
-(fset 'SET\ CURSOR\ BOUND 'tpu-set-cursor-bound)
-
-(fset 'set\ scroll\ margins 'tpu-set-scroll-margins)
-(fset 'SET\ SCROLL\ MARGINS 'tpu-set-scroll-margins)
-
-
-;; Around emacs version 18.57, function line-move was renamed to
-;; next-line-internal. If we're running under an older emacs,
-;; make next-line-internal equivalent to line-move.
-
-(if (not (fboundp 'next-line-internal)) (fset 'next-line-internal 'line-move))
-
-
-;;;
-;;; Help
-;;;
-(defconst tpu-help-keypad-map "\f
- _______________________ _______________________________
- | HELP | Do | | | | | |
- |KeyDefs| | | | | | |
- |_______|_______________| |_______|_______|_______|_______|
- _______________________ _______________________________
- | Find |Insert |Remove | | Gold | HELP |FndNxt | Del L |
- | | |Sto Tex| | key |E-Help | Find |Undel L|
- |_______|_______|_______| |_______|_______|_______|_______|
- |Select |Pre Scr|Nex Scr| | Page | Sect |Append | Del W |
- | Reset |Pre Win|Nex Win| | Do | Fill |Replace|Undel W|
- |_______|_______|_______| |_______|_______|_______|_______|
- |Move up| |Forward|Reverse|Remove | Del C |
- | Top | |Bottom | Top |Insert |Undel C|
- _______|_______|_______ |_______|_______|_______|_______|
- |Mov Lef|Mov Dow|Mov Rig| | Word | EOL | Char | |
- |StaOfLi|Bottom |EndOfLi| |ChngCas|Del EOL|SpecIns| Enter |
- |_______|_______|_______| |_______|_______|_______| |
- | Line |Select | Subs |
- | Open Line | Reset | |
- |_______________|_______|_______|
-")
-
-(defconst tpu-help-text "
-\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\f
-
- Control Characters
-
- ^A toggle insert and overwrite
- ^B recall
- ^E end of line
-
- ^G Cancel current operation
- ^H beginning of line
- ^J delete previous word
-
- ^K learn
- ^L insert page break
- ^R remember (during learn), re-center
-
- ^U delete to beginning of line
- ^V quote
- ^W refresh
-
- ^Z exit
- ^X^X exchange point and mark - useful for checking region boundaries
-
-\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\f
- Gold-<key> Functions
-
- B Next Buffer - display the next buffer (all buffers)
- C Recall - edit and possibly repeat previous commands
- E Exit - save current buffer and ask about others
- G Get - load a file into a new edit buffer
-
- I Include - include a file in this buffer
- K Kill Buffer - abandon edits and delete buffer
- M Buffer Menu - display a list of all buffers
- N Next File Buffer - display next buffer containing a file
-
- O Occur - show following lines containing REGEXP
- Q Quit - exit without saving anything
- R Toggle rectangular mode for remove and insert
- S Search and substitute - line mode REPLACE command
-
- ^T Toggle control key bindings between TPU and emacs
- U Undo - undo the last edit
- W Write - save current buffer
- X Exit - save all modified buffers and exit
-
-\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\f
-
- More extensive documentation on TPU-edt can be found in the `Commentary'
- section of tpu-edt.el. This section can be accessed through the standard
- Emacs help facility using the `p' option. Once you exit TPU-edt Help, one
- of the following key sequences is sure to get you there.
-
- ^h p if you're not yet using TPU-edt
- Gold-PF2 p if you're using TPU-edt
-
- Alternatively, fire up Emacs help from the command prompt, with
-
- M-x help-for-help <CR> p <CR>
-
- Where `M-x' might be any of `Gold-KP7', 'Do', or 'ESC-x'.
-
- When you successfully invoke this part of the Emacs help facility, you
- will see a buffer named `*Finder*' listing a number of topics. Look for
- tpu-edt under `emulations'.
-
-\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\f
-
- *** No more help, use P to view previous screen")
-
-(defvar tpu-help-enter (format "%s" "\eOM")) ; tpu-help enter key symbol
-(defvar tpu-help-return (format "%s" "\r")) ; tpu-help enter key symbol
-(defvar tpu-help-N "N") ; tpu-help "N" symbol
-(defvar tpu-help-n "n") ; tpu-help "n" symbol
-(defvar tpu-help-P "P") ; tpu-help "P" symbol
-(defvar tpu-help-p "p") ; tpu-help "p" symbol
-
-(defun tpu-help nil
- "Display TPU-edt help."
- (interactive)
- ;; Save current window configuration
- (save-window-excursion
- ;; Create and fill help buffer if necessary
- (if (not (get-buffer "*TPU-edt Help*"))
- (progn (generate-new-buffer "*TPU-edt Help*")
- (switch-to-buffer "*TPU-edt Help*")
- (insert tpu-help-keypad-map)
- (insert tpu-help-text)
- (setq buffer-read-only t)))
-
- ;; Display the help buffer
- (switch-to-buffer "*TPU-edt Help*")
- (delete-other-windows)
- (tpu-move-to-beginning)
- (forward-line 1)
- (tpu-line-to-top-of-window)
-
- ;; Prompt for keys to describe, based on screen state (split/not split)
- (let ((key nil) (fkey nil) (split nil))
- (while (not (equal tpu-help-return fkey))
- (if split
- (setq key
- (read-key-sequence
- "Press the key you want help on (RET=exit, ENTER=redisplay, N=next, P=prev): "))
- (setq key
- (read-key-sequence
- "Press the key you want help on (RET to exit, N next screen, P prev screen): ")))
-
- ;; Process the read key
- ;;
- ;; ENTER - Display just the help window
- ;; N or n - Next help or describe-key screen
- ;; P or p - Previous help or describe-key screen
- ;; RETURN - Exit from TPU-help
- ;; default - describe the key
- ;;
- (setq fkey (format "%s" key))
- (cond ((equal tpu-help-enter fkey)
- (setq split nil)
- (delete-other-windows))
- ((or (equal tpu-help-N fkey) (equal tpu-help-n fkey))
- (cond (split
- (condition-case nil
- (scroll-other-window 8)
- (error nil)))
- (t
- (forward-page)
- (forward-line 1)
- (tpu-line-to-top-of-window))))
- ((or (equal tpu-help-P fkey) (equal tpu-help-p fkey))
- (cond (split
- (condition-case nil
- (scroll-other-window -8)
- (error nil)))
- (t
- (backward-page)
- (forward-line 1)
- (tpu-line-to-top-of-window))))
- ((not (equal tpu-help-return fkey))
- (setq split t)
- (describe-key key)
- ;; If the key is undefined, leave the
- ;; message in the mini-buffer for 3 seconds
- (if (not (key-binding key)) (sit-for 3))))))))
-
-
-;;;
-;;; Auto-insert
-;;;
-(defun tpu-insert-escape nil
- "Inserts an escape character, and so becomes the escape-key alias."
- (interactive)
- (insert "\e"))
-
-(defun tpu-insert-formfeed nil
- "Inserts a formfeed character."
- (interactive)
- (insert "\C-L"))
-
-
-;;;
-;;; Define key
-;;;
-(defvar tpu-saved-control-r nil "Saved value of Control-r.")
-
-(defun tpu-end-define-macro-key (key)
- "Ends the current macro definition"
- (interactive "kPress the key you want to use to do what was just learned: ")
- (end-kbd-macro nil)
- (global-set-key key last-kbd-macro)
- (global-set-key "\C-r" tpu-saved-control-r))
-
-(defun tpu-define-macro-key nil
- "Bind a set of keystrokes to a single key, or key combination."
- (interactive)
- (setq tpu-saved-control-r (global-key-binding "\C-r"))
- (global-set-key "\C-r" 'tpu-end-define-macro-key)
- (start-kbd-macro nil))
-
-
-;;;
-;;; Buffers and Windows
-;;;
-(defun tpu-kill-buffer nil
- "Kills the current buffer. If tpu-kill-buffers-silently is non-nil,
-kills modified buffers without asking."
- (interactive)
- (if tpu-kill-buffers-silently (set-buffer-modified-p nil))
- (kill-buffer (current-buffer)))
-
-(defun tpu-save-all-buffers-kill-emacs nil
- "Save all buffers and exit emacs."
- (interactive)
- (let ((delete-old-versions t))
- (save-buffers-kill-emacs t)))
-
-(defun tpu-write-current-buffers nil
- "Save all modified buffers without exiting."
- (interactive)
- (save-some-buffers t))
-
-(defun tpu-next-buffer nil
- "Go to next buffer in ring."
- (interactive)
- (switch-to-buffer (car (reverse (buffer-list)))))
-
-(defun tpu-next-file-buffer nil
- "Go to next buffer in ring that is visiting a file or directory."
- (interactive)
- (let ((list (tpu-make-file-buffer-list (buffer-list))))
- (setq list (delq (current-buffer) list))
- (if (not list) (error "No other buffers."))
- (switch-to-buffer (car (reverse list)))))
-
-(defun tpu-make-file-buffer-list (buffer-list)
- "Returns names from BUFFER-LIST excluding those beginning with a space or star."
- (delq nil (mapcar '(lambda (b)
- (if (or (= (aref (buffer-name b) 0) ? )
- (= (aref (buffer-name b) 0) ?*)) nil b))
- buffer-list)))
-
-(defun tpu-next-window nil
- "Move to the next window."
- (interactive)
- (if (one-window-p) (message "There is only one window on screen.")
- (other-window 1)))
-
-(defun tpu-previous-window nil
- "Move to the previous window."
- (interactive)
- (if (one-window-p) (message "There is only one window on screen.")
- (select-window (previous-window))))
-
-
-;;;
-;;; Search
-;;;
-(defun tpu-toggle-regexp nil
- "Switches in and out of regular expression search and replace mode."
- (interactive)
- (setq tpu-regexp-p (not tpu-regexp-p))
- (tpu-set-search)
- (and (interactive-p)
- (message "Regular expression search and substitute %sabled."
- (if tpu-regexp-p "en" "dis"))))
-
-(defun tpu-regexp-prompt (prompt)
- "Read a string, adding 'RE' to the prompt if tpu-regexp-p is set."
- (let ((re-prompt (concat (if tpu-regexp-p "RE ") prompt)))
- (if tpu-emacs19-p
- (read-from-minibuffer re-prompt nil nil nil 'tpu-regexp-prompt-hist)
- (read-string re-prompt))))
-
-(defun tpu-search nil
- "Search for a string or regular expression.
-The search is performed in the current direction."
- (interactive)
- (tpu-set-search)
- (tpu-search-internal ""))
-
-(defun tpu-search-forward nil
- "Search for a string or regular expression.
-The search is begins in the forward direction."
- (interactive)
- (setq tpu-searching-forward t)
- (tpu-set-search t)
- (tpu-search-internal ""))
-
-(defun tpu-search-reverse nil
- "Search for a string or regular expression.
-The search is begins in the reverse direction."
- (interactive)
- (setq tpu-searching-forward nil)
- (tpu-set-search t)
- (tpu-search-internal ""))
-
-(defun tpu-search-again nil
- "Search for the same string or regular expression as last time.
-The search is performed in the current direction."
- (interactive)
- (tpu-search-internal tpu-search-last-string))
-
-;; tpu-set-search defines the search functions used by the TPU-edt internal
-;; search function. It should be called whenever the direction changes, or
-;; the regular expression mode is turned on or off. It can also be called
-;; to ensure that the next search will be in the current direction. It is
-;; called from:
-
-;; tpu-advance tpu-backup
-;; tpu-toggle-regexp tpu-toggle-search-direction (t)
-;; tpu-search tpu-lm-replace
-;; tpu-search-forward (t) tpu-search-reverse (t)
-;; tpu-search-forward-exit (t) tpu-search-backward-exit (t)
-
-(defun tpu-set-search (&optional arg)
- "Set the search functions and set the search direction to the current
-direction. If an argument is specified, don't set the search direction."
- (if (not arg) (setq tpu-searching-forward (if tpu-advance t nil)))
- (cond (tpu-searching-forward
- (cond (tpu-regexp-p
- (fset 'tpu-emacs-search 're-search-forward)
- (fset 'tpu-emacs-rev-search 're-search-backward))
- (t
- (fset 'tpu-emacs-search 'search-forward)
- (fset 'tpu-emacs-rev-search 'search-backward))))
- (t
- (cond (tpu-regexp-p
- (fset 'tpu-emacs-search 're-search-backward)
- (fset 'tpu-emacs-rev-search 're-search-forward))
- (t
- (fset 'tpu-emacs-search 'search-backward)
- (fset 'tpu-emacs-rev-search 'search-forward))))))
-
-(defun tpu-search-internal (pat &optional quiet)
- "Search for a string or regular expression."
- (setq tpu-search-last-string
- (if (not (string= "" pat)) pat (tpu-regexp-prompt "Search: ")))
-
- (tpu-unset-match)
- (tpu-adjust-search)
-
- (let ((case-fold-search
- (and case-fold-search (tpu-check-search-case tpu-search-last-string))))
-
- (cond ((tpu-emacs-search tpu-search-last-string nil t)
- (tpu-set-match) (goto-char (tpu-match-beginning)))
-
- (t
- (tpu-adjust-search t)
- (let ((found nil) (pos nil))
- (save-excursion
- (let ((tpu-searching-forward (not tpu-searching-forward)))
- (tpu-adjust-search)
- (setq found (tpu-emacs-rev-search tpu-search-last-string nil t))
- (setq pos (match-beginning 0))))
-
- (cond
- (found
- (cond ((tpu-y-or-n-p
- (format "Found in %s direction. Go there? "
- (if tpu-searching-forward "reverse" "forward")))
- (goto-char pos) (tpu-set-match)
- (tpu-toggle-search-direction))))
-
- (t
- (if (not quiet)
- (message
- "%sSearch failed: \"%s\""
- (if tpu-regexp-p "RE " "") tpu-search-last-string)))))))))
-
-(fset 'tpu-search-internal-core (symbol-function 'tpu-search-internal))
-
-(defun tpu-check-search-case (string)
- "Returns t if string contains upper case."
- ;; if using regexp, eliminate upper case forms (\B \W \S.)
- (if tpu-regexp-p
- (let ((pat (copy-sequence string)) (case-fold-search nil) (pos 0))
- (while (setq pos (string-match "\\\\\\\\" pat)) (aset pat (+ 1 pos) ?.))
- (while (setq pos (string-match "\\\\B" pat)) (aset pat (+ 1 pos) ?.))
- (while (setq pos (string-match "\\\\W" pat)) (aset pat (+ 1 pos) ?.))
- (while (setq pos (string-match "\\\\S." pat))
- (aset pat (+ 1 pos) ?.) (aset pat (+ 2 pos) ?.))
- (string-equal pat (downcase pat)))
- (string-equal string (downcase string))))
-
-(defun tpu-adjust-search (&optional arg)
- "For forward searches, move forward a character before searching,
-and backward a character after a failed search. Arg means end of search."
- (if tpu-searching-forward
- (cond (arg (if (not (bobp)) (forward-char -1)))
- (t (if (not (eobp)) (forward-char 1))))))
-
-(defun tpu-toggle-search-direction nil
- "Toggle the TPU-edt search direction.
-Used for reversing a search in progress."
- (interactive)
- (setq tpu-searching-forward (not tpu-searching-forward))
- (tpu-set-search t)
- (and (interactive-p)
- (message "Searching %sward."
- (if tpu-searching-forward "for" "back"))))
-
-(defun tpu-search-forward-exit nil
- "Set search direction forward and exit minibuffer."
- (interactive)
- (setq tpu-searching-forward t)
- (tpu-set-search t)
- (exit-minibuffer))
-
-(defun tpu-search-backward-exit nil
- "Set search direction backward and exit minibuffer."
- (interactive)
- (setq tpu-searching-forward nil)
- (tpu-set-search t)
- (exit-minibuffer))
-
-
-;;;
-;;; Select / Unselect
-;;;
-(defun tpu-select (&optional quiet)
- "Sets the mark to define one end of a region."
- (interactive "P")
- (cond ((tpu-mark)
- (tpu-unselect quiet))
- (t
- (tpu-set-mark (point))
- (tpu-update-mode-line)
- (if (not quiet) (message "Move the text cursor to select text.")))))
-
-(defun tpu-unselect (&optional quiet)
- "Removes the mark to unselect the current region."
- (interactive "P")
- (setq mark-ring nil)
- (tpu-set-mark nil)
- (tpu-update-mode-line)
- (if (not quiet) (message "Selection canceled.")))
-
-
-;;;
-;;; Delete / Cut
-;;;
-(defun tpu-toggle-rectangle nil
- "Toggle rectangular mode for remove and insert."
- (interactive)
- (setq tpu-rectangular-p (not tpu-rectangular-p))
- (setq tpu-rectangle-string (if tpu-rectangular-p " Rect" ""))
- (tpu-update-mode-line)
- (and (interactive-p)
- (message "Rectangular cut and paste %sabled."
- (if tpu-rectangular-p "en" "dis"))))
-
-(defun tpu-arrange-rectangle nil
- "Adjust point and mark to mark upper left and lower right
-corners of a rectangle."
- (let ((mc (current-column))
- (pc (progn (exchange-point-and-mark) (current-column))))
-
- (cond ((> (point) (tpu-mark)) ; point on lower line
- (cond ((> pc mc) ; point @ lower-right
- (exchange-point-and-mark)) ; point -> upper-left
-
- (t ; point @ lower-left
- (move-to-column-force mc) ; point -> lower-right
- (exchange-point-and-mark) ; point -> upper-right
- (move-to-column-force pc)))) ; point -> upper-left
-
- (t ; point on upper line
- (cond ((> pc mc) ; point @ upper-right
- (move-to-column-force mc) ; point -> upper-left
- (exchange-point-and-mark) ; point -> lower-left
- (move-to-column-force pc) ; point -> lower-right
- (exchange-point-and-mark))))))) ; point -> upper-left
-
-(defun tpu-cut-text nil
- "Delete the selected region.
-The text is saved for the tpu-paste command."
- (interactive)
- (cond ((tpu-mark)
- (cond (tpu-rectangular-p
- (tpu-arrange-rectangle)
- (picture-clear-rectangle (point) (tpu-mark) (not overwrite-mode))
- (tpu-unselect t))
- (t
- (setq tpu-last-deleted-region
- (buffer-substring (tpu-mark) (point)))
- (delete-region (tpu-mark) (point))
- (tpu-unselect t))))
- ((tpu-check-match)
- (let ((beg (tpu-match-beginning)) (end (tpu-match-end)))
- (setq tpu-last-deleted-region (buffer-substring beg end))
- (delete-region beg end)
- (tpu-unset-match)))
- (t
- (error "No selection active."))))
-
-(defun tpu-store-text nil
- "Copy the selected region to the cut buffer without deleting it.
-The text is saved for the tpu-paste command."
- (interactive)
- (cond ((tpu-mark)
- (cond (tpu-rectangular-p
- (save-excursion
- (tpu-arrange-rectangle)
- (setq picture-killed-rectangle
- (extract-rectangle (point) (tpu-mark))))
- (tpu-unselect t))
- (t
- (setq tpu-last-deleted-region
- (buffer-substring (tpu-mark) (point)))
- (tpu-unselect t))))
- ((tpu-check-match)
- (setq tpu-last-deleted-region
- (buffer-substring (tpu-match-beginning) (tpu-match-end)))
- (tpu-unset-match))
- (t
- (error "No selection active."))))
-
-(defun tpu-cut (arg)
- "Copy selected region to the cut buffer. In the absence of an
-argument, delete the selected region too."
- (interactive "P")
- (if arg (tpu-store-text) (tpu-cut-text)))
-
-(defun tpu-append-region (arg)
- "Append selected region to the tpu-cut buffer. In the absence of an
-argument, delete the selected region too."
- (interactive "P")
- (cond ((tpu-mark)
- (let ((beg (region-beginning)) (end (region-end)))
- (setq tpu-last-deleted-region
- (concat tpu-last-deleted-region
- (buffer-substring beg end)))
- (if (not arg) (delete-region beg end))
- (tpu-unselect t)))
- ((tpu-check-match)
- (let ((beg (tpu-match-beginning)) (end (tpu-match-end)))
- (setq tpu-last-deleted-region
- (concat tpu-last-deleted-region
- (buffer-substring beg end)))
- (if (not arg) (delete-region beg end))
- (tpu-unset-match)))
- (t
- (error "No selection active."))))
-
-(defun tpu-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 TPU-edt undelete-lines command."
- (interactive "p")
- (let ((beg (point)))
- (forward-line num)
- (if (not (eq (preceding-char) ?\n))
- (insert "\n"))
- (setq tpu-last-deleted-lines
- (buffer-substring beg (point)))
- (delete-region beg (point))))
-
-(defun tpu-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 TPU-edt undelete-lines command."
- (interactive "p")
- (let ((beg (point)))
- (forward-char 1)
- (end-of-line num)
- (setq tpu-last-deleted-lines
- (buffer-substring beg (point)))
- (delete-region beg (point))))
-
-(defun tpu-delete-to-bol (num)
- "Delete text back to beginning of line.
-With argument, delete up to to Nth line-end past point.
-They are saved for the TPU-edt undelete-lines command."
- (interactive "p")
- (let ((beg (point)))
- (tpu-next-beginning-of-line num)
- (setq tpu-last-deleted-lines
- (buffer-substring (point) beg))
- (delete-region (point) beg)))
-
-(defun tpu-delete-current-word (num)
- "Delete one or specified number of words after point.
-They are saved for the TPU-edt undelete-words command."
- (interactive "p")
- (let ((beg (point)))
- (tpu-forward-to-word num)
- (setq tpu-last-deleted-words
- (buffer-substring beg (point)))
- (delete-region beg (point))))
-
-(defun tpu-delete-previous-word (num)
- "Delete one or specified number of words before point.
-They are saved for the TPU-edt undelete-words command."
- (interactive "p")
- (let ((beg (point)))
- (tpu-backward-to-word num)
- (setq tpu-last-deleted-words
- (buffer-substring (point) beg))
- (delete-region beg (point))))
-
-(defun tpu-delete-current-char (num)
- "Delete one or specified number of characters after point. The last
-character deleted is saved for the TPU-edt undelete-char command."
- (interactive "p")
- (while (and (> num 0) (not (eobp)))
- (setq tpu-last-deleted-char (char-after (point)))
- (cond (overwrite-mode
- (picture-clear-column 1)
- (forward-char 1))
- (t
- (delete-char 1)))
- (setq num (1- num))))
-
-
-;;;
-;;; Undelete / Paste
-;;;
-(defun tpu-paste (num)
- "Insert the last region or rectangle of killed text.
-With argument reinserts the text that many times."
- (interactive "p")
- (while (> num 0)
- (cond (tpu-rectangular-p
- (let ((beg (point)))
- (save-excursion
- (picture-yank-rectangle (not overwrite-mode))
- (message ""))
- (goto-char beg)))
- (t
- (insert tpu-last-deleted-region)))
- (setq num (1- num))))
-
-(defun tpu-undelete-lines (num)
- "Insert lines deleted by last TPU-edt line-deletion command.
-With argument reinserts lines that many times."
- (interactive "p")
- (let ((beg (point)))
- (while (> num 0)
- (insert tpu-last-deleted-lines)
- (setq num (1- num)))
- (goto-char beg)))
-
-(defun tpu-undelete-words (num)
- "Insert words deleted by last TPU-edt word-deletion command.
-With argument reinserts words that many times."
- (interactive "p")
- (let ((beg (point)))
- (while (> num 0)
- (insert tpu-last-deleted-words)
- (setq num (1- num)))
- (goto-char beg)))
-
-(defun tpu-undelete-char (num)
- "Insert character deleted by last TPU-edt character-deletion command.
-With argument reinserts the character that many times."
- (interactive "p")
- (while (> num 0)
- (if overwrite-mode (prog1 (forward-char -1) (delete-char 1)))
- (insert tpu-last-deleted-char)
- (forward-char -1)
- (setq num (1- num))))
-
-
-;;;
-;;; Replace and Substitute
-;;;
-(defun tpu-replace nil
- "Replace the selected region with the contents of the cut buffer."
- (interactive)
- (cond ((tpu-mark)
- (let ((beg (region-beginning)) (end (region-end)))
- (setq tpu-last-replaced-text (buffer-substring beg end))
- (delete-region beg end)
- (insert tpu-last-deleted-region)
- (tpu-unselect t)))
- ((tpu-check-match)
- (let ((beg (tpu-match-beginning)) (end (tpu-match-end)))
- (setq tpu-last-replaced-text (buffer-substring beg end))
- (replace-match tpu-last-deleted-region
- (not case-replace) (not tpu-regexp-p))
- (tpu-unset-match)))
- (t
- (error "No selection active."))))
-
-(defun tpu-substitute (num)
- "Replace the selected region with the contents of the cut buffer, and
-repeat most recent search. A numeric argument serves as a repeat count.
-A negative argument means replace all occurrences of the search string."
- (interactive "p")
- (cond ((or (tpu-mark) (tpu-check-match))
- (while (and (not (= num 0)) (or (tpu-mark) (tpu-check-match)))
- (let ((beg (point)))
- (tpu-replace)
- (if tpu-searching-forward (forward-char -1) (goto-char beg))
- (if (= num 1) (tpu-search-internal tpu-search-last-string)
- (tpu-search-internal-core tpu-search-last-string)))
- (setq num (1- num))))
- (t
- (error "No selection active."))))
-
-(defun tpu-lm-replace (from to)
- "Interactively search for OLD-string and substitute NEW-string."
- (interactive (list (tpu-regexp-prompt "Old String: ")
- (tpu-regexp-prompt "New String: ")))
-
- (let ((doit t) (strings 0))
-
- ;; Can't replace null strings
- (if (string= "" from) (error "No string to replace."))
-
- ;; Find the first occurrence
- (tpu-set-search)
- (tpu-search-internal from t)
-
- ;; Loop on replace question - yes, no, all, last, or quit.
- (while doit
- (if (not (tpu-check-match)) (setq doit nil)
- (progn (message "Replace? Type Yes, No, All, Last, or Quit: ")
- (let ((ans (read-char)))
-
- (cond ((or (= ans ?y) (= ans ?Y) (= ans ?\r) (= ans ?\ ))
- (let ((beg (point)))
- (replace-match to (not case-replace) (not tpu-regexp-p))
- (setq strings (1+ strings))
- (if tpu-searching-forward (forward-char -1) (goto-char beg)))
- (tpu-search-internal from t))
-
- ((or (= ans ?n) (= ans ?N) (= ans ?\C-?))
- (tpu-search-internal from t))
-
- ((or (= ans ?a) (= ans ?A))
- (save-excursion
- (let ((beg (point)))
- (replace-match to (not case-replace) (not tpu-regexp-p))
- (setq strings (1+ strings))
- (if tpu-searching-forward (forward-char -1) (goto-char beg)))
- (tpu-search-internal-core from t)
- (while (tpu-check-match)
- (let ((beg (point)))
- (replace-match to (not case-replace) (not tpu-regexp-p))
- (setq strings (1+ strings))
- (if tpu-searching-forward (forward-char -1) (goto-char beg)))
- (tpu-search-internal-core from t)))
- (setq doit nil))
-
- ((or (= ans ?l) (= ans ?L))
- (let ((beg (point)))
- (replace-match to (not case-replace) (not tpu-regexp-p))
- (setq strings (1+ strings))
- (if tpu-searching-forward (forward-char -1) (goto-char beg)))
- (setq doit nil))
-
- ((or (= ans ?q) (= ans ?Q))
- (setq doit nil)))))))
-
- (message "Replaced %s occurrence%s." strings
- (if (not (= 1 strings)) "s" ""))))
-
-(defun tpu-emacs-replace (&optional dont-ask)
- "A TPU-edt interface to the emacs replace functions. If TPU-edt is
-currently in regular expression mode, the emacs regular expression
-replace functions are used. If an argument is supplied, replacements
-are performed without asking. Only works in forward direction."
- (interactive "P")
- (cond (dont-ask
- (setq current-prefix-arg nil)
- (call-interactively
- (if tpu-regexp-p 'replace-regexp 'replace-string)))
- (t
- (call-interactively
- (if tpu-regexp-p 'query-replace-regexp 'query-replace)))))
-
-(defun tpu-add-at-bol (text)
- "Add text to the beginning of each line in a region,
-or each line in the entire buffer if no region is selected."
- (interactive
- (list (tpu-string-prompt "String to add: " 'tpu-add-at-bol-hist)))
- (if (string= "" text) (error "No string specified."))
- (cond ((tpu-mark)
- (save-excursion
- (if (> (point) (tpu-mark)) (exchange-point-and-mark))
- (while (and (< (point) (tpu-mark)) (re-search-forward "^" (tpu-mark) t))
- (if (< (point) (tpu-mark)) (replace-match text))))
- (tpu-unselect t))
- (t
- (save-excursion
- (goto-char (point-min))
- (while (and (re-search-forward "^" nil t) (not (eobp)))
- (replace-match text))))))
-
-(defun tpu-add-at-eol (text)
- "Add text to the end of each line in a region,
-or each line of the entire buffer if no region is selected."
- (interactive
- (list (tpu-string-prompt "String to add: " 'tpu-add-at-eol-hist)))
- (if (string= "" text) (error "No string specified."))
- (cond ((tpu-mark)
- (save-excursion
- (if (> (point) (tpu-mark)) (exchange-point-and-mark))
- (while (< (point) (tpu-mark))
- (end-of-line)
- (if (<= (point) (tpu-mark)) (insert text))
- (forward-line)))
- (tpu-unselect t))
- (t
- (save-excursion
- (goto-char (point-min))
- (while (not (eobp))
- (end-of-line) (insert text) (forward-line))))))
-
-(defun tpu-trim-line-ends nil
- "Removes trailing whitespace from every line in the buffer."
- (interactive)
- (picture-clean))
-
-
-;;;
-;;; Movement by character
-;;;
-(defun tpu-char (num)
- "Move to the next character in the current direction.
-A repeat count means move that many characters."
- (interactive "p")
- (if tpu-advance (tpu-forward-char num) (tpu-backward-char num)))
-
-(defun tpu-forward-char (num)
- "Move right ARG characters (left if ARG is negative)."
- (interactive "p")
- (forward-char num))
-
-(defun tpu-backward-char (num)
- "Move left ARG characters (right if ARG is negative)."
- (interactive "p")
- (backward-char num))
-
-
-;;;
-;;; Movement by word
-;;;
-(defconst tpu-word-separator-list '()
- "List of additional word separators.")
-(defconst tpu-skip-chars "^ \t"
- "Characters to skip when moving by word.
-Additional word separators are added to this string.")
-
-(defun tpu-word (num)
- "Move to the beginning of the next word in the current direction.
-A repeat count means move that many words."
- (interactive "p")
- (if tpu-advance (tpu-forward-to-word num) (tpu-backward-to-word num)))
-
-(defun tpu-forward-to-word (num)
- "Move forward until encountering the beginning of a word.
-With argument, do this that many times."
- (interactive "p")
- (while (and (> num 0) (not (eobp)))
- (let* ((beg (point))
- (end (prog2 (end-of-line) (point) (goto-char beg))))
- (cond ((eolp)
- (forward-char 1))
- ((memq (char-after (point)) tpu-word-separator-list)
- (forward-char 1)
- (skip-chars-forward " \t" end))
- (t
- (skip-chars-forward tpu-skip-chars end)
- (skip-chars-forward " \t" end))))
- (setq num (1- num))))
-
-(defun tpu-backward-to-word (num)
- "Move backward until encountering the beginning of a word.
-With argument, do this that many times."
- (interactive "p")
- (while (and (> num 0) (not (bobp)))
- (let* ((beg (point))
- (end (prog2 (beginning-of-line) (point) (goto-char beg))))
- (cond ((bolp)
- ( forward-char -1))
- ((memq (char-after (1- (point))) tpu-word-separator-list)
- (forward-char -1))
- (t
- (skip-chars-backward " \t" end)
- (skip-chars-backward tpu-skip-chars end)
- (if (and (not (bolp)) (= ? (char-syntax (char-after (point)))))
- (forward-char -1)))))
- (setq num (1- num))))
-
-(defun tpu-add-word-separators (separators)
- "Add new word separators for TPU-edt word commands."
- (interactive "sSeparators: ")
- (let* ((n 0) (length (length separators)))
- (while (< n length)
- (let ((char (aref separators n))
- (ss (substring separators n (1+ n))))
- (cond ((not (memq char tpu-word-separator-list))
- (setq tpu-word-separator-list
- (append ss tpu-word-separator-list))
- (cond ((= char ?-)
- (setq tpu-skip-chars (concat tpu-skip-chars "\\-")))
- ((= char ?\\)
- (setq tpu-skip-chars (concat tpu-skip-chars "\\\\")))
- ((= char ?^)
- (setq tpu-skip-chars (concat tpu-skip-chars "\\^")))
- (t
- (setq tpu-skip-chars (concat tpu-skip-chars ss))))))
- (setq n (1+ n))))))
-
-(defun tpu-reset-word-separators nil
- "Reset word separators to default value."
- (interactive)
- (setq tpu-word-separator-list nil)
- (setq tpu-skip-chars "^ \t"))
-
-(defun tpu-set-word-separators (separators)
- "Set new word separators for TPU-edt word commands."
- (interactive "sSeparators: ")
- (tpu-reset-word-separators)
- (tpu-add-word-separators separators))
-
-
-;;;
-;;; Movement by line
-;;;
-(defun tpu-next-line (num)
- "Move to next line.
-Prefix argument serves as a repeat count."
- (interactive "p")
- (next-line-internal num)
- (setq this-command 'next-line))
-
-(defun tpu-previous-line (num)
- "Move to previous line.
-Prefix argument serves as a repeat count."
- (interactive "p")
- (next-line-internal (- num))
- (setq this-command 'previous-line))
-
-(defun tpu-next-beginning-of-line (num)
- "Move to beginning of line; if at beginning, move to beginning of next line.
-Accepts a prefix argument for the number of lines to move."
- (interactive "p")
- (backward-char 1)
- (forward-line (- 1 num)))
-
-(defun tpu-end-of-line (num)
- "Move to the next end of line in the current direction.
-A repeat count means move that many lines."
- (interactive "p")
- (if tpu-advance (tpu-next-end-of-line num) (tpu-previous-end-of-line num)))
-
-(defun tpu-next-end-of-line (num)
- "Move to end of line; if at end, move to end of next line.
-Accepts a prefix argument for the number of lines to move."
- (interactive "p")
- (forward-char 1)
- (end-of-line num))
-
-(defun tpu-previous-end-of-line (num)
- "Move EOL upward.
-Accepts a prefix argument for the number of lines to move."
- (interactive "p")
- (end-of-line (- 1 num)))
-
-(defun tpu-current-end-of-line nil
- "Move point to end of current line."
- (interactive)
- (let ((beg (point)))
- (end-of-line)
- (if (= beg (point)) (message "You are already at the end of a line."))))
-
-(defun tpu-line (num)
- "Move to the beginning of the next line in the current direction.
-A repeat count means move that many lines."
- (interactive "p")
- (if tpu-advance (tpu-forward-line num) (tpu-backward-line num)))
-
-(defun tpu-forward-line (num)
- "Move to beginning of next line.
-Prefix argument serves as a repeat count."
- (interactive "p")
- (forward-line num))
-
-(defun tpu-backward-line (num)
- "Move to beginning of previous line.
-Prefix argument serves as repeat count."
- (interactive "p")
- (or (bolp) (>= 0 num) (setq num (- num 1)))
- (forward-line (- num)))
-
-
-;;;
-;;; Movement by paragraph
-;;;
-(defun tpu-paragraph (num)
- "Move to the next paragraph in the current direction.
-A repeat count means move that many paragraphs."
- (interactive "p")
- (if tpu-advance
- (tpu-next-paragraph num) (tpu-previous-paragraph num)))
-
-(defun tpu-next-paragraph (num)
- "Move to beginning of the next paragraph.
-Accepts a prefix argument for the number of paragraphs."
- (interactive "p")
- (beginning-of-line)
- (while (and (not (eobp)) (> num 0))
- (if (re-search-forward "^[ \t]*$" nil t)
- (if (re-search-forward "[^ \t\n]" nil t)
- (goto-char (match-beginning 0))
- (goto-char (point-max))))
- (setq num (1- num)))
- (beginning-of-line))
-
-
-(defun tpu-previous-paragraph (num)
- "Move to beginning of previous paragraph.
-Accepts a prefix argument for the number of paragraphs."
- (interactive "p")
- (end-of-line)
- (while (and (not (bobp)) (> num 0))
- (if (not (and (re-search-backward "^[ \t]*$" nil t)
- (re-search-backward "[^ \t\n]" nil t)
- (re-search-backward "^[ \t]*$" nil t)
- (progn (re-search-forward "[^ \t\n]" nil t)
- (goto-char (match-beginning 0)))))
- (goto-char (point-min)))
- (setq num (1- num)))
- (beginning-of-line))
-
-
-;;;
-;;; Movement by page
-;;;
-(defun tpu-page (num)
- "Move to the next page in the current direction.
-A repeat count means move that many pages."
- (interactive "p")
- (if tpu-advance (forward-page num) (backward-page num))
- (if (eobp) (recenter -1)))
-
-
-;;;
-;;; Scrolling and movement within the buffer
-;;;
-(defun tpu-scroll-window (num)
- "Scroll the display to the next section in the current direction.
-A repeat count means scroll that many sections."
- (interactive "p")
- (if tpu-advance (tpu-scroll-window-up num) (tpu-scroll-window-down num)))
-
-(defun tpu-scroll-window-down (num)
- "Scroll the display down to the next section.
-A repeat count means scroll that many sections."
- (interactive "p")
- (let* ((beg (tpu-current-line))
- (height (1- (window-height)))
- (lines (* num (/ (* height tpu-percent-scroll) 100))))
- (next-line-internal (- lines))
- (if (> lines beg) (recenter 0))))
-
-(defun tpu-scroll-window-up (num)
- "Scroll the display up to the next section.
-A repeat count means scroll that many sections."
- (interactive "p")
- (let* ((beg (tpu-current-line))
- (height (1- (window-height)))
- (lines (* num (/ (* height tpu-percent-scroll) 100))))
- (next-line-internal lines)
- (if (>= (+ lines beg) height) (recenter -1))))
-
-(defun tpu-pan-right (num)
- "Pan right tpu-pan-columns (16 by default).
-Accepts a prefix argument for the number of tpu-pan-columns to scroll."
- (interactive "p")
- (scroll-left (* tpu-pan-columns num)))
-
-(defun tpu-pan-left (num)
- "Pan left tpu-pan-columns (16 by default).
-Accepts a prefix argument for the number of tpu-pan-columns to scroll."
- (interactive "p")
- (scroll-right (* tpu-pan-columns num)))
-
-(defun tpu-move-to-beginning nil
- "Move cursor to the beginning of buffer, but don't set the mark."
- (interactive)
- (goto-char (point-min)))
-
-(defun tpu-move-to-end nil
- "Move cursor to the end of buffer, but don't set the mark."
- (interactive)
- (goto-char (point-max))
- (recenter -1))
-
-(defun tpu-goto-percent (perc)
- "Move point to ARG percentage of the buffer."
- (interactive "NGoto-percentage: ")
- (if (or (> perc 100) (< perc 0))
- (error "Percentage %d out of range 0 < percent < 100" perc)
- (goto-char (/ (* (point-max) perc) 100))))
-
-(defun tpu-beginning-of-window nil
- "Move cursor to top of window."
- (interactive)
- (move-to-window-line 0))
-
-(defun tpu-end-of-window nil
- "Move cursor to bottom of window."
- (interactive)
- (move-to-window-line -1))
-
-(defun tpu-line-to-bottom-of-window nil
- "Move the current line to the bottom of the window."
- (interactive)
- (recenter -1))
-
-(defun tpu-line-to-top-of-window nil
- "Move the current line to the top of the window."
- (interactive)
- (recenter 0))
-
-
-;;;
-;;; Direction
-;;;
-(defun tpu-advance-direction nil
- "Set TPU Advance mode so keypad commands move forward."
- (interactive)
- (setq tpu-direction-string " Advance")
- (setq tpu-advance t)
- (setq tpu-reverse nil)
- (tpu-set-search)
- (tpu-update-mode-line))
-
-(defun tpu-backup-direction nil
- "Set TPU Backup mode so keypad commands move backward."
- (interactive)
- (setq tpu-direction-string " Reverse")
- (setq tpu-advance nil)
- (setq tpu-reverse t)
- (tpu-set-search)
- (tpu-update-mode-line))
-
-
-;;;
-;;; Define keymaps
-;;;
-(define-key global-map "\e[" CSI-map) ; CSI map
-(define-key global-map "\eO" SS3-map) ; SS3 map
-(define-key SS3-map "P" GOLD-map) ; GOLD map
-(define-key GOLD-map "\e[" GOLD-CSI-map) ; GOLD-CSI map
-(define-key GOLD-map "\eO" GOLD-SS3-map) ; GOLD-SS3 map
-
-
-;;;
-;;; CSI-map key definitions
-;;;
-(define-key CSI-map "A" 'tpu-previous-line) ; up
-(define-key CSI-map "B" 'tpu-next-line) ; down
-(define-key CSI-map "D" 'tpu-backward-char) ; left
-(define-key CSI-map "C" 'tpu-forward-char) ; right
-
-(define-key CSI-map "1~" 'tpu-search) ; Find
-(define-key CSI-map "2~" 'tpu-paste) ; Insert Here
-(define-key CSI-map "3~" 'tpu-cut) ; Remove
-(define-key CSI-map "4~" 'tpu-select) ; Select
-(define-key CSI-map "5~" 'tpu-scroll-window-down) ; Prev Screen
-(define-key CSI-map "6~" 'tpu-scroll-window-up) ; Next Screen
-
-(define-key CSI-map "11~" 'nil) ; F1
-(define-key CSI-map "12~" 'nil) ; F2
-(define-key CSI-map "13~" 'nil) ; F3
-(define-key CSI-map "14~" 'nil) ; F4
-(define-key CSI-map "15~" 'nil) ; F5
-(define-key CSI-map "17~" 'nil) ; F6
-(define-key CSI-map "18~" 'nil) ; F7
-(define-key CSI-map "19~" 'nil) ; F8
-(define-key CSI-map "20~" 'nil) ; F9
-(define-key CSI-map "21~" 'tpu-exit) ; F10
-(define-key CSI-map "23~" 'tpu-insert-escape) ; F11 (ESC)
-(define-key CSI-map "24~" 'tpu-next-beginning-of-line) ; F12 (BS)
-(define-key CSI-map "25~" 'tpu-delete-previous-word) ; F13 (LF)
-(define-key CSI-map "26~" 'tpu-toggle-overwrite-mode) ; F14
-(define-key CSI-map "28~" 'tpu-help) ; HELP
-(define-key CSI-map "29~" 'execute-extended-command) ; DO
-(define-key CSI-map "31~" 'tpu-goto-breadcrumb) ; F17
-(define-key CSI-map "32~" 'nil) ; F18
-(define-key CSI-map "33~" 'nil) ; F19
-(define-key CSI-map "34~" 'nil) ; F20
-
-
-;;;
-;;; SS3-map key definitions
-;;;
-(define-key SS3-map "A" 'tpu-previous-line) ; up
-(define-key SS3-map "B" 'tpu-next-line) ; down
-(define-key SS3-map "C" 'tpu-forward-char) ; right
-(define-key SS3-map "D" 'tpu-backward-char) ; left
-
-(define-key SS3-map "Q" 'tpu-help) ; PF2
-(define-key SS3-map "R" 'tpu-search-again) ; PF3
-(define-key SS3-map "S" 'tpu-delete-current-line) ; PF4
-(define-key SS3-map "p" 'tpu-line) ; KP0
-(define-key SS3-map "q" 'tpu-word) ; KP1
-(define-key SS3-map "r" 'tpu-end-of-line) ; KP2
-(define-key SS3-map "s" 'tpu-char) ; KP3
-(define-key SS3-map "t" 'tpu-advance-direction) ; KP4
-(define-key SS3-map "u" 'tpu-backup-direction) ; KP5
-(define-key SS3-map "v" 'tpu-cut) ; KP6
-(define-key SS3-map "w" 'tpu-page) ; KP7
-(define-key SS3-map "x" 'tpu-scroll-window) ; KP8
-(define-key SS3-map "y" 'tpu-append-region) ; KP9
-(define-key SS3-map "m" 'tpu-delete-current-word) ; KP-
-(define-key SS3-map "l" 'tpu-delete-current-char) ; KP,
-(define-key SS3-map "n" 'tpu-select) ; KP.
-(define-key SS3-map "M" 'newline) ; KPenter
-
-
-;;;
-;;; GOLD-map key definitions
-;;;
-(define-key GOLD-map "\C-A" 'tpu-toggle-overwrite-mode) ; ^A
-(define-key GOLD-map "\C-B" 'nil) ; ^B
-(define-key GOLD-map "\C-C" 'nil) ; ^C
-(define-key GOLD-map "\C-D" 'nil) ; ^D
-(define-key GOLD-map "\C-E" 'nil) ; ^E
-(define-key GOLD-map "\C-F" 'set-visited-file-name) ; ^F
-(define-key GOLD-map "\C-g" 'keyboard-quit) ; safety first
-(define-key GOLD-map "\C-h" 'delete-other-windows) ; BS
-(define-key GOLD-map "\C-i" 'other-window) ; TAB
-(define-key GOLD-map "\C-J" 'nil) ; ^J
-(define-key GOLD-map "\C-K" 'tpu-define-macro-key) ; ^K
-(define-key GOLD-map "\C-l" 'downcase-region) ; ^L
-(define-key GOLD-map "\C-M" 'nil) ; ^M
-(define-key GOLD-map "\C-N" 'nil) ; ^N
-(define-key GOLD-map "\C-O" 'nil) ; ^O
-(define-key GOLD-map "\C-P" 'nil) ; ^P
-(define-key GOLD-map "\C-Q" 'nil) ; ^Q
-(define-key GOLD-map "\C-R" 'nil) ; ^R
-(define-key GOLD-map "\C-S" 'nil) ; ^S
-(define-key GOLD-map "\C-T" 'tpu-toggle-control-keys) ; ^T
-(define-key GOLD-map "\C-u" 'upcase-region) ; ^U
-(define-key GOLD-map "\C-V" 'nil) ; ^V
-(define-key GOLD-map "\C-w" 'tpu-write-current-buffers) ; ^W
-(define-key GOLD-map "\C-X" 'nil) ; ^X
-(define-key GOLD-map "\C-Y" 'nil) ; ^Y
-(define-key GOLD-map "\C-Z" 'nil) ; ^Z
-(define-key GOLD-map " " 'undo) ; SPC
-(define-key GOLD-map "!" 'nil) ; !
-(define-key GOLD-map "#" 'nil) ; #
-(define-key GOLD-map "$" 'tpu-add-at-eol) ; $
-(define-key GOLD-map "%" 'tpu-goto-percent) ; %
-(define-key GOLD-map "&" 'nil) ; &
-(define-key GOLD-map "(" 'nil) ; (
-(define-key GOLD-map ")" 'nil) ; )
-(define-key GOLD-map "*" 'tpu-toggle-regexp) ; *
-(define-key GOLD-map "+" 'nil) ; +
-(define-key GOLD-map "," 'tpu-goto-breadcrumb) ; ,
-(define-key GOLD-map "-" 'negative-argument) ; -
-(define-key GOLD-map "." 'tpu-drop-breadcrumb) ; .
-(define-key GOLD-map "/" 'tpu-emacs-replace) ; /
-(define-key GOLD-map "0" 'digit-argument) ; 0
-(define-key GOLD-map "1" 'digit-argument) ; 1
-(define-key GOLD-map "2" 'digit-argument) ; 2
-(define-key GOLD-map "3" 'digit-argument) ; 3
-(define-key GOLD-map "4" 'digit-argument) ; 4
-(define-key GOLD-map "5" 'digit-argument) ; 5
-(define-key GOLD-map "6" 'digit-argument) ; 6
-(define-key GOLD-map "7" 'digit-argument) ; 7
-(define-key GOLD-map "8" 'digit-argument) ; 8
-(define-key GOLD-map "9" 'digit-argument) ; 9
-(define-key GOLD-map ":" 'nil) ; :
-(define-key GOLD-map ";" 'tpu-trim-line-ends) ; ;
-(define-key GOLD-map "<" 'nil) ; <
-(define-key GOLD-map "=" 'nil) ; =
-(define-key GOLD-map ">" 'nil) ; >
-(define-key GOLD-map "?" 'tpu-spell-check) ; ?
-(define-key GOLD-map "A" 'tpu-toggle-newline-and-indent) ; A
-(define-key GOLD-map "B" 'tpu-next-buffer) ; B
-(define-key GOLD-map "C" 'repeat-complex-command) ; C
-(define-key GOLD-map "D" 'shell-command) ; D
-(define-key GOLD-map "E" 'tpu-exit) ; E
-(define-key GOLD-map "F" 'tpu-set-cursor-free) ; F
-(define-key GOLD-map "G" 'tpu-get) ; G
-(define-key GOLD-map "H" 'nil) ; H
-(define-key GOLD-map "I" 'tpu-include) ; I
-(define-key GOLD-map "K" 'tpu-kill-buffer) ; K
-(define-key GOLD-map "L" 'tpu-what-line) ; L
-(define-key GOLD-map "M" 'buffer-menu) ; M
-(define-key GOLD-map "N" 'tpu-next-file-buffer) ; N
-(define-key GOLD-map "O" 'occur) ; O
-(define-key GOLD-map "P" 'lpr-buffer) ; P
-(define-key GOLD-map "Q" 'tpu-quit) ; Q
-(define-key GOLD-map "R" 'tpu-toggle-rectangle) ; R
-(define-key GOLD-map "S" 'replace) ; S
-(define-key GOLD-map "T" 'tpu-line-to-top-of-window) ; T
-(define-key GOLD-map "U" 'undo) ; U
-(define-key GOLD-map "V" 'tpu-version) ; V
-(define-key GOLD-map "W" 'save-buffer) ; W
-(define-key GOLD-map "X" 'tpu-save-all-buffers-kill-emacs) ; X
-(define-key GOLD-map "Y" 'copy-region-as-kill) ; Y
-(define-key GOLD-map "Z" 'suspend-emacs) ; Z
-(define-key GOLD-map "[" 'blink-matching-open) ; [
-(define-key GOLD-map "\\" 'nil) ; \
-(define-key GOLD-map "]" 'blink-matching-open) ; ]
-(define-key GOLD-map "^" 'tpu-add-at-bol) ; ^
-(define-key GOLD-map "_" 'split-window-vertically) ; -
-(define-key GOLD-map "`" 'what-line) ; `
-(define-key GOLD-map "a" 'tpu-toggle-newline-and-indent) ; a
-(define-key GOLD-map "b" 'tpu-next-buffer) ; b
-(define-key GOLD-map "c" 'repeat-complex-command) ; c
-(define-key GOLD-map "d" 'shell-command) ; d
-(define-key GOLD-map "e" 'tpu-exit) ; e
-(define-key GOLD-map "f" 'tpu-set-cursor-free) ; f
-(define-key GOLD-map "g" 'tpu-get) ; g
-(define-key GOLD-map "h" 'nil) ; h
-(define-key GOLD-map "i" 'tpu-include) ; i
-(define-key GOLD-map "k" 'tpu-kill-buffer) ; k
-(define-key GOLD-map "l" 'goto-line) ; l
-(define-key GOLD-map "m" 'buffer-menu) ; m
-(define-key GOLD-map "n" 'tpu-next-file-buffer) ; n
-(define-key GOLD-map "o" 'occur) ; o
-(define-key GOLD-map "p" 'lpr-region) ; p
-(define-key GOLD-map "q" 'tpu-quit) ; q
-(define-key GOLD-map "r" 'tpu-toggle-rectangle) ; r
-(define-key GOLD-map "s" 'replace) ; s
-(define-key GOLD-map "t" 'tpu-line-to-top-of-window) ; t
-(define-key GOLD-map "u" 'undo) ; u
-(define-key GOLD-map "v" 'tpu-version) ; v
-(define-key GOLD-map "w" 'save-buffer) ; w
-(define-key GOLD-map "x" 'tpu-save-all-buffers-kill-emacs) ; x
-(define-key GOLD-map "y" 'copy-region-as-kill) ; y
-(define-key GOLD-map "z" 'suspend-emacs) ; z
-(define-key GOLD-map "{" 'nil) ; {
-(define-key GOLD-map "|" 'split-window-horizontally) ; |
-(define-key GOLD-map "}" 'nil) ; }
-(define-key GOLD-map "~" 'exchange-point-and-mark) ; ~
-(define-key GOLD-map "\177" 'delete-window) ; <X]
-
-
-;;;
-;;; GOLD-CSI-map key definitions
-;;;
-(define-key GOLD-CSI-map "A" 'tpu-move-to-beginning) ; up-arrow
-(define-key GOLD-CSI-map "B" 'tpu-move-to-end) ; down-arrow
-(define-key GOLD-CSI-map "C" 'end-of-line) ; right-arrow
-(define-key GOLD-CSI-map "D" 'beginning-of-line) ; left-arrow
-
-(define-key GOLD-CSI-map "1~" 'nil) ; Find
-(define-key GOLD-CSI-map "2~" 'nil) ; Insert Here
-(define-key GOLD-CSI-map "3~" 'tpu-store-text) ; Remove
-(define-key GOLD-CSI-map "4~" 'tpu-unselect) ; Select
-(define-key GOLD-CSI-map "5~" 'tpu-previous-window) ; Prev Screen
-(define-key GOLD-CSI-map "6~" 'tpu-next-window) ; Next Screen
-
-(define-key GOLD-CSI-map "11~" 'nil) ; F1
-(define-key GOLD-CSI-map "12~" 'nil) ; F2
-(define-key GOLD-CSI-map "13~" 'nil) ; F3
-(define-key GOLD-CSI-map "14~" 'nil) ; F4
-(define-key GOLD-CSI-map "16~" 'nil) ; F5
-(define-key GOLD-CSI-map "17~" 'nil) ; F6
-(define-key GOLD-CSI-map "18~" 'nil) ; F7
-(define-key GOLD-CSI-map "19~" 'nil) ; F8
-(define-key GOLD-CSI-map "20~" 'nil) ; F9
-(define-key GOLD-CSI-map "21~" 'nil) ; F10
-(define-key GOLD-CSI-map "23~" 'nil) ; F11
-(define-key GOLD-CSI-map "24~" 'nil) ; F12
-(define-key GOLD-CSI-map "25~" 'nil) ; F13
-(define-key GOLD-CSI-map "26~" 'nil) ; F14
-(define-key GOLD-CSI-map "28~" 'describe-bindings) ; HELP
-(define-key GOLD-CSI-map "29~" 'nil) ; DO
-(define-key GOLD-CSI-map "31~" 'tpu-drop-breadcrumb) ; F17
-(define-key GOLD-CSI-map "32~" 'nil) ; F18
-(define-key GOLD-CSI-map "33~" 'nil) ; F19
-(define-key GOLD-CSI-map "34~" 'nil) ; F20
-
-
-;;;
-;;; GOLD-SS3-map key definitions
-;;;
-(define-key GOLD-SS3-map "A" 'tpu-move-to-beginning) ; up-arrow
-(define-key GOLD-SS3-map "B" 'tpu-move-to-end) ; down-arrow
-(define-key GOLD-SS3-map "C" 'end-of-line) ; right-arrow
-(define-key GOLD-SS3-map "D" 'beginning-of-line) ; left-arrow
-
-(define-key GOLD-SS3-map "P" 'keyboard-quit) ; PF1
-(define-key GOLD-SS3-map "Q" 'help-for-help) ; PF2
-(define-key GOLD-SS3-map "R" 'tpu-search) ; PF3
-(define-key GOLD-SS3-map "S" 'tpu-undelete-lines) ; PF4
-(define-key GOLD-SS3-map "p" 'open-line) ; KP0
-(define-key GOLD-SS3-map "q" 'tpu-change-case) ; KP1
-(define-key GOLD-SS3-map "r" 'tpu-delete-to-eol) ; KP2
-(define-key GOLD-SS3-map "s" 'tpu-special-insert) ; KP3
-(define-key GOLD-SS3-map "t" 'tpu-move-to-end) ; KP4
-(define-key GOLD-SS3-map "u" 'tpu-move-to-beginning) ; KP5
-(define-key GOLD-SS3-map "v" 'tpu-paste) ; KP6
-(define-key GOLD-SS3-map "w" 'execute-extended-command) ; KP7
-(define-key GOLD-SS3-map "x" 'tpu-fill) ; KP8
-(define-key GOLD-SS3-map "y" 'tpu-replace) ; KP9
-(define-key GOLD-SS3-map "m" 'tpu-undelete-words) ; KP-
-(define-key GOLD-SS3-map "l" 'tpu-undelete-char) ; KP,
-(define-key GOLD-SS3-map "n" 'tpu-unselect) ; KP.
-(define-key GOLD-SS3-map "M" 'tpu-substitute) ; KPenter
-
-
-;;;
-;;; Repeat complex command map additions to make arrows work
-;;;
-(cond ((boundp 'repeat-complex-command-map)
- (define-key repeat-complex-command-map "\e[A" 'previous-complex-command)
- (define-key repeat-complex-command-map "\e[B" 'next-complex-command)
- (define-key repeat-complex-command-map "\eOA" 'previous-complex-command)
- (define-key repeat-complex-command-map "\eOB" 'next-complex-command)))
-
-
-;;;
-;;; Minibuffer map additions to make KP_enter = RET
-;;;
-(define-key minibuffer-local-map "\eOM" 'exit-minibuffer)
-(define-key minibuffer-local-ns-map "\eOM" 'exit-minibuffer)
-(define-key minibuffer-local-completion-map "\eOM" 'exit-minibuffer)
-(define-key minibuffer-local-must-match-map "\eOM" 'minibuffer-complete-and-exit)
-(and (boundp 'repeat-complex-command-map)
- (define-key repeat-complex-command-map "\eOM" 'exit-minibuffer))
-
-
-;;;
-;;; Minibuffer map additions to set search direction
-;;;
-(define-key minibuffer-local-map "\eOt" 'tpu-search-forward-exit)
-(define-key minibuffer-local-map "\eOu" 'tpu-search-backward-exit)
-
-
-;;;
-;;; Functions to set, reset, and toggle the control key bindings
-;;;
-(defun tpu-set-control-keys nil
- "Set control keys to TPU style functions."
- (define-key global-map "\C-\\" 'quoted-insert) ; ^\
- (define-key global-map "\C-a" 'tpu-toggle-overwrite-mode) ; ^A
- (define-key global-map "\C-b" 'repeat-complex-command) ; ^B
- (define-key global-map "\C-e" 'tpu-current-end-of-line) ; ^E
- (define-key global-map "\C-h" 'tpu-next-beginning-of-line) ; ^H (BS)
- (define-key global-map "\C-j" 'tpu-delete-previous-word) ; ^J (LF)
- (define-key global-map "\C-k" 'tpu-define-macro-key) ; ^K
- (define-key global-map "\C-l" 'tpu-insert-formfeed) ; ^L (FF)
- (define-key global-map "\C-r" 'recenter) ; ^R
- (define-key global-map "\C-u" 'tpu-delete-to-bol) ; ^U
- (define-key global-map "\C-v" 'tpu-quoted-insert) ; ^V
- (define-key global-map "\C-w" 'redraw-display) ; ^W
- (define-key global-map "\C-z" 'tpu-exit) ; ^Z
- (setq tpu-control-keys t))
-
-(defun tpu-reset-control-keys (tpu-style)
- "Set control keys to TPU or emacs style functions."
- (let* ((tpu (and tpu-style (not tpu-control-keys)))
- (emacs (and (not tpu-style) tpu-control-keys))
- (doit (or tpu emacs)))
- (cond (doit
- (if emacs (setq tpu-global-map (copy-keymap global-map)))
- (let ((map (if tpu
- (copy-keymap tpu-global-map)
- (copy-keymap tpu-original-global-map))))
-
- (define-key global-map "\C-\\" (lookup-key map "\C-\\")) ; ^\
- (define-key global-map "\C-a" (lookup-key map "\C-a")) ; ^A
- (define-key global-map "\C-b" (lookup-key map "\C-b")) ; ^B
- (define-key global-map "\C-e" (lookup-key map "\C-e")) ; ^E
- (define-key global-map "\C-h" (lookup-key map "\C-h")) ; ^H (BS)
- (define-key global-map "\C-j" (lookup-key map "\C-j")) ; ^J (LF)
- (define-key global-map "\C-k" (lookup-key map "\C-k")) ; ^K
- (define-key global-map "\C-l" (lookup-key map "\C-l")) ; ^L (FF)
- (define-key global-map "\C-r" (lookup-key map "\C-r")) ; ^R
- (define-key global-map "\C-u" (lookup-key map "\C-u")) ; ^U
- (define-key global-map "\C-v" (lookup-key map "\C-v")) ; ^V
- (define-key global-map "\C-w" (lookup-key map "\C-w")) ; ^W
- (define-key global-map "\C-z" (lookup-key map "\C-z")) ; ^Z
- (setq tpu-control-keys tpu-style))))))
-
-(defun tpu-toggle-control-keys nil
- "Toggles control key bindings between TPU-edt and Emacs."
- (interactive)
- (tpu-reset-control-keys (not tpu-control-keys))
- (and (interactive-p)
- (message "Control keys function with %s bindings."
- (if tpu-control-keys "TPU-edt" "Emacs"))))
-
-
-;;;
-;;; Emacs version 19 minibuffer history support
-;;;
-(defun tpu-next-history-element (n)
- "Insert the next element of the minibuffer history into the minibuffer."
- (interactive "p")
- (next-history-element n)
- (goto-char (point-max)))
-
-(defun tpu-previous-history-element (n)
- "Insert the previous element of the minibuffer history into the minibuffer."
- (interactive "p")
- (previous-history-element n)
- (goto-char (point-max)))
-
-(defun tpu-arrow-history nil
- "Modify minibuffer maps to use arrows for history recall."
- (interactive)
- (let ((loc (where-is-internal 'tpu-previous-line)) (cur nil))
- (while (setq cur (car loc))
- (define-key read-expression-map cur 'tpu-previous-history-element)
- (define-key minibuffer-local-map cur 'tpu-previous-history-element)
- (define-key minibuffer-local-ns-map cur 'tpu-previous-history-element)
- (define-key minibuffer-local-completion-map cur 'tpu-previous-history-element)
- (define-key minibuffer-local-must-match-map cur 'tpu-previous-history-element)
- (setq loc (cdr loc)))
-
- (setq loc (where-is-internal 'tpu-next-line))
- (while (setq cur (car loc))
- (define-key read-expression-map cur 'tpu-next-history-element)
- (define-key minibuffer-local-map cur 'tpu-next-history-element)
- (define-key minibuffer-local-ns-map cur 'tpu-next-history-element)
- (define-key minibuffer-local-completion-map cur 'tpu-next-history-element)
- (define-key minibuffer-local-must-match-map cur 'tpu-next-history-element)
- (setq loc (cdr loc)))))
-
-
-;;;
-;;; Emacs version 19 X-windows key definition support
-;;;
-(defun tpu-load-xkeys (file)
- "Load the TPU-edt X-windows key definitions FILE.
-If FILE is nil, try to load a default file. The default file names are
-`~/.tpu-lucid-keys' for Lucid emacs, and `~/.tpu-keys' for Emacs."
- (interactive "fX key definition file: ")
- (cond (file
- (setq file (expand-file-name file)))
- (tpu-xkeys-file
- (setq file (expand-file-name tpu-xkeys-file)))
- (tpu-lucid-emacs19-p
- (setq file (convert-standard-filename
- (expand-file-name "~/.tpu-lucid-keys"))))
- (tpu-emacs19-p
- (setq file (convert-standard-filename
- (expand-file-name "~/.tpu-keys")))
- (and (not (file-exists-p file))
- (file-exists-p
- (convert-standard-filename
- (expand-file-name "~/.tpu-gnu-keys")))
- (tpu-copy-keyfile
- (convert-standard-filename
- (expand-file-name "~/.tpu-gnu-keys")) file))))
- (cond ((file-readable-p file)
- (load-file file))
- (t
- (switch-to-buffer "*scratch*")
- (erase-buffer)
- (insert "
-
- Ack!! You're running TPU-edt under X-windows without loading an
- X key definition file. To create a TPU-edt X key definition
- file, run the tpu-mapper.el program. It came with TPU-edt. It
- even includes directions on how to use it! Perhaps it's lying
- around here someplace. ")
- (let ((file "tpu-mapper.el")
- (found nil)
- (path nil)
- (search-list (append (list (expand-file-name ".")) load-path)))
- (while (and (not found) search-list)
- (setq path (concat (car search-list)
- (if (string-match "/$" (car search-list)) "" "/")
- file))
- (if (and (file-exists-p path) (not (file-directory-p path)))
- (setq found t))
- (setq search-list (cdr search-list)))
- (cond (found
- (insert (format
- "Ah yes, there it is, in \n\n %s \n\n" path))
- (if (tpu-y-or-n-p "Do you want to run it now? ")
- (load-file path)))
- (t
- (insert "Nope, I can't seem to find it. :-(\n\n")
- (sit-for 120)))))))
-
-(defun tpu-copy-keyfile (oldname newname)
- "Copy the TPU-edt X key definitions file to the new default name."
- (interactive "fOld name: \nFNew name: ")
- (if (not (get-buffer "*TPU-Notice*")) (generate-new-buffer "*TPU-Notice*"))
- (set-buffer "*TPU-Notice*")
- (erase-buffer)
- (insert "
- NOTICE --
-
- The default name of the TPU-edt key definition file has changed
- from `~/.tpu-gnu-keys' to `~/.tpu-keys'. With your permission,
- your key definitions will be copied to the new file. If you'll
- never use older versions of Emacs, you can remove the old file.
- If the copy fails, you'll be asked if you want to create a new
- key definitions file. Do you want to copy your key definition
- file now?
- ")
- (save-window-excursion
- (switch-to-buffer-other-window "*TPU-Notice*")
- (shrink-window-if-larger-than-buffer)
- (goto-char (point-min))
- (beep)
- (and (tpu-y-or-n-p "Copy key definitions to the new file now? ")
- (condition-case conditions
- (copy-file oldname newname)
- (error (message "Sorry, couldn't copy - %s" (cdr conditions)))))
- (kill-buffer "*TPU-Notice*")))
-
-
-;;;
-;;; Start and Stop TPU-edt
-;;;
-;;;###autoload
-(defun tpu-edt-on nil
- "Turn on TPU/edt emulation."
- (interactive)
- (cond
- ((not tpu-edt-mode)
- ;; we use picture-mode functions
- (require 'picture)
- (tpu-set-control-keys)
- (cond (tpu-emacs19-p
- (and window-system (tpu-load-xkeys nil))
- (tpu-arrow-history))
- (t
- ;; define ispell functions
- (autoload 'ispell-word "ispell" "Check spelling of word at or before point" t)
- (autoload 'ispell-complete-word "ispell" "Complete word at or before point" t)
- (autoload 'ispell-buffer "ispell" "Check spelling of entire buffer" t)
- (autoload 'ispell-region "ispell" "Check spelling of region" t)))
- (tpu-set-mode-line t)
- (tpu-advance-direction)
- ;; set page delimiter, display line truncation, and scrolling like TPU
- (setq-default page-delimiter "\f")
- (setq-default truncate-lines t)
- (setq scroll-step 1)
- (setq tpu-edt-mode t))))
-
-(defun tpu-edt-off nil
- "Turn off TPU/edt emulation. Note that the keypad is left on."
- (interactive)
- (cond
- (tpu-edt-mode
- (tpu-reset-control-keys nil)
- (tpu-set-mode-line nil)
- (setq-default page-delimiter "^\f")
- (setq-default truncate-lines nil)
- (setq scroll-step 0)
- (setq global-map (copy-keymap tpu-original-global-map))
- (use-global-map global-map)
- (setq tpu-edt-mode nil))))
-
-(provide 'tpu-edt)
-
-;;; tpu-edt.el ends here
diff --git a/lisp/emulation/tpu-extras.el b/lisp/emulation/tpu-extras.el
deleted file mode 100644
index dbaf20ce3aa..00000000000
--- a/lisp/emulation/tpu-extras.el
+++ /dev/null
@@ -1,477 +0,0 @@
-;;; tpu-extras.el --- Scroll margins and free cursor mode for TPU-edt
-
-;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Rob Riepel <riepel@networking.stanford.edu>
-;; Maintainer: Rob Riepel <riepel@networking.stanford.edu>
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Use the functions defined here to customize TPU-edt to your tastes by
-;; setting scroll margins and/or turning on free cursor mode. Here's an
-;; example for your .emacs file.
-
-;; (tpu-set-cursor-free) ; Set cursor free.
-;; (tpu-set-scroll-margins "10%" "15%") ; Set scroll margins.
-
-;; Scroll margins and cursor binding can be changed from within emacs using
-;; the following commands:
-
-;; tpu-set-scroll-margins or set scroll margins
-;; tpu-set-cursor-bound or set cursor bound
-;; tpu-set-cursor-free or set cursor free
-
-;; Additionally, Gold-F toggles between bound and free cursor modes.
-
-;; Note that switching out of free cursor mode or exiting TPU-edt while in
-;; free cursor mode strips trailing whitespace from every line in the file.
-
-
-;;; Details:
-
-;; The functions contained in this file implement scroll margins and free
-;; cursor mode. The following keys and commands are affected.
-
-;; key/command function scroll cursor
-
-;; Up-Arrow previous line x x
-;; Down-Arrow next line x x
-;; Right-Arrow next character x
-;; Left-Arrow previous character x
-;; KP0 next or previous line x
-;; KP7 next or previous page x
-;; KP8 next or previous screen x
-;; KP2 next or previous end-of-line x x
-;; Control-e current end-of-line x
-;; Control-h previous beginning-of-line x
-;; Next Scr next screen x
-;; Prev Scr previous screen x
-;; Search find a string x
-;; Replace find and replace a string x
-;; Newline insert a newline x
-;; Paragraph next or previous paragraph x
-;; Auto-Fill break lines on spaces x
-
-;; These functions are not part of the base TPU-edt for the following
-;; reasons:
-
-;; Free cursor mode is implemented with the emacs picture-mode functions.
-;; These functions support moving the cursor all over the screen, however,
-;; when the cursor is moved past the end of a line, spaces or tabs are
-;; appended to the line - even if no text is entered in that area. In
-;; order for a free cursor mode to work exactly like TPU/edt, this trailing
-;; whitespace needs to be dealt with in every function that might encounter
-;; it. Such global changes are impractical, however, free cursor mode is
-;; too valuable to abandon completely, so it has been implemented in those
-;; functions where it serves best.
-
-;; The implementation of scroll margins adds overhead to previously
-;; simple and often used commands. These commands are now responsible
-;; for their normal operation and part of the display function. There
-;; is a possibility that this display overhead could adversely affect the
-;; performance of TPU-edt on slower computers. In order to support the
-;; widest range of computers, scroll margin support is optional.
-
-;; It's actually not known whether the overhead associated with scroll
-;; margin support is significant. If you find that it is, please send
-;; a note describing the extent of the performance degradation. Be sure
-;; to include a description of the platform where you're running TPU-edt.
-;; Send your note to the address provided by Gold-V.
-
-;; Even with these differences and limitations, these functions implement
-;; important aspects of the real TPU/edt. Those who miss free cursor mode
-;; and/or scroll margins will appreciate these implementations.
-
-;;; Code:
-
-
-;;; Gotta have tpu-edt
-
-(require 'tpu-edt)
-
-
-;;; Customization variables
-
-(defconst tpu-top-scroll-margin 0
- "*Scroll margin at the top of the screen.
-Interpreted as a percent of the current window size.")
-(defconst tpu-bottom-scroll-margin 0
- "*Scroll margin at the bottom of the screen.
-Interpreted as a percent of the current window size.")
-
-(defvar tpu-backward-char-like-tpu t
- "*If non-nil, in free cursor mode backward-char (left-arrow) works
-just like TPU/edt. Otherwise, backward-char will move to the end of
-the previous line when starting from a line beginning.")
-
-
-;;; Global variables
-
-(defvar tpu-cursor-free nil
- "If non-nil, let the cursor roam free.")
-
-
-;;; Hooks -- Set cursor free in picture mode.
-;;; Clean up when writing a file from cursor free mode.
-
-(add-hook 'picture-mode-hook 'tpu-set-cursor-free)
-
-(defun tpu-write-file-hook nil
- "Eliminate whitespace at ends of lines, if the cursor is free."
- (if (and (buffer-modified-p) tpu-cursor-free) (picture-clean)))
-
-(or (memq 'tpu-write-file-hook write-file-hooks)
- (setq write-file-hooks
- (cons 'tpu-write-file-hook write-file-hooks)))
-
-
-;;; Utility routines for implementing scroll margins
-
-(defun tpu-top-check (beg lines)
- "Enforce scroll margin at the top of screen."
- (let ((margin (/ (* (window-height) tpu-top-scroll-margin) 100)))
- (cond ((< beg margin) (recenter beg))
- ((< (- beg lines) margin) (recenter margin)))))
-
-(defun tpu-bottom-check (beg lines)
- "Enforce scroll margin at the bottom of screen."
- (let* ((height (window-height))
- (margin (+ 1 (/ (* height tpu-bottom-scroll-margin) 100)))
- ;; subtract 1 from height because it includes mode line
- (difference (- height margin 1)))
- (cond ((> beg difference) (recenter beg))
- ((> (+ beg lines) difference) (recenter (- margin))))))
-
-
-;;; Movement by character
-
-(defun tpu-forward-char (num)
- "Move right ARG characters (left if ARG is negative)."
- (interactive "p")
- (if tpu-cursor-free (picture-forward-column num) (forward-char num)))
-
-(defun tpu-backward-char (num)
- "Move left ARG characters (right if ARG is negative)."
- (interactive "p")
- (cond ((not tpu-cursor-free)
- (backward-char num))
- (tpu-backward-char-like-tpu
- (picture-backward-column num))
- ((bolp)
- (backward-char 1)
- (picture-end-of-line)
- (picture-backward-column (1- num)))
- (t
- (picture-backward-column num))))
-
-
-;;; Movement by line
-
-(defun tpu-next-line (num)
- "Move to next line.
-Prefix argument serves as a repeat count."
- (interactive "p")
- (let ((beg (tpu-current-line)))
- (if tpu-cursor-free (or (eobp) (picture-move-down num))
- (next-line-internal num))
- (tpu-bottom-check beg num)
- (setq this-command 'next-line)))
-
-(defun tpu-previous-line (num)
- "Move to previous line.
-Prefix argument serves as a repeat count."
- (interactive "p")
- (let ((beg (tpu-current-line)))
- (if tpu-cursor-free (picture-move-up num) (next-line-internal (- num)))
- (tpu-top-check beg num)
- (setq this-command 'previous-line)))
-
-(defun tpu-next-beginning-of-line (num)
- "Move to beginning of line; if at beginning, move to beginning of next line.
-Accepts a prefix argument for the number of lines to move."
- (interactive "p")
- (let ((beg (tpu-current-line)))
- (backward-char 1)
- (forward-line (- 1 num))
- (tpu-top-check beg num)))
-
-(defun tpu-next-end-of-line (num)
- "Move to end of line; if at end, move to end of next line.
-Accepts a prefix argument for the number of lines to move."
- (interactive "p")
- (let ((beg (tpu-current-line)))
- (cond (tpu-cursor-free
- (let ((beg (point)))
- (if (< 1 num) (forward-line num))
- (picture-end-of-line)
- (if (<= (point) beg) (progn (forward-line) (picture-end-of-line)))))
- (t
- (forward-char)
- (end-of-line num)))
- (tpu-bottom-check beg num)))
-
-(defun tpu-previous-end-of-line (num)
- "Move EOL upward.
-Accepts a prefix argument for the number of lines to move."
- (interactive "p")
- (let ((beg (tpu-current-line)))
- (cond (tpu-cursor-free
- (picture-end-of-line (- 1 num)))
- (t
- (end-of-line (- 1 num))))
- (tpu-top-check beg num)))
-
-(defun tpu-current-end-of-line nil
- "Move point to end of current line."
- (interactive)
- (let ((beg (point)))
- (if tpu-cursor-free (picture-end-of-line) (end-of-line))
- (if (= beg (point)) (message "You are already at the end of a line."))))
-
-(defun tpu-forward-line (num)
- "Move to beginning of next line.
-Prefix argument serves as a repeat count."
- (interactive "p")
- (let ((beg (tpu-current-line)))
- (next-line-internal num)
- (tpu-bottom-check beg num)
- (beginning-of-line)))
-
-(defun tpu-backward-line (num)
- "Move to beginning of previous line.
-Prefix argument serves as repeat count."
- (interactive "p")
- (let ((beg (tpu-current-line)))
- (or (bolp) (>= 0 num) (setq num (- num 1)))
- (next-line-internal (- num))
- (tpu-top-check beg num)
- (beginning-of-line)))
-
-
-;;; Movement by paragraph
-
-(defun tpu-paragraph (num)
- "Move to the next paragraph in the current direction.
-A repeat count means move that many paragraphs."
- (interactive "p")
- (let* ((left nil)
- (beg (tpu-current-line))
- (height (window-height))
- (top-percent
- (if (= 0 tpu-top-scroll-margin) 10 tpu-top-scroll-margin))
- (bottom-percent
- (if (= 0 tpu-bottom-scroll-margin) 15 tpu-bottom-scroll-margin))
- (top-margin (/ (* height top-percent) 100))
- (bottom-up-margin (+ 1 (/ (* height bottom-percent) 100)))
- (bottom-margin (max beg (- height bottom-up-margin 1)))
- (top (save-excursion (move-to-window-line top-margin) (point)))
- (bottom (save-excursion (move-to-window-line bottom-margin) (point)))
- (far (save-excursion
- (goto-char bottom) (forward-line (- height 2)) (point))))
- (cond (tpu-advance
- (tpu-next-paragraph num)
- (cond((> (point) far)
- (setq left (save-excursion (forward-line height)))
- (if (= 0 left) (recenter top-margin)
- (recenter (- left bottom-up-margin))))
- (t
- (and (> (point) bottom) (recenter bottom-margin)))))
- (t
- (tpu-previous-paragraph num)
- (and (< (point) top) (recenter (min beg top-margin)))))))
-
-
-;;; Movement by page
-
-(defun tpu-page (num)
- "Move to the next page in the current direction.
-A repeat count means move that many pages."
- (interactive "p")
- (let* ((left nil)
- (beg (tpu-current-line))
- (height (window-height))
- (top-percent
- (if (= 0 tpu-top-scroll-margin) 10 tpu-top-scroll-margin))
- (bottom-percent
- (if (= 0 tpu-bottom-scroll-margin) 15 tpu-bottom-scroll-margin))
- (top-margin (/ (* height top-percent) 100))
- (bottom-up-margin (+ 1 (/ (* height bottom-percent) 100)))
- (bottom-margin (max beg (- height bottom-up-margin 1)))
- (top (save-excursion (move-to-window-line top-margin) (point)))
- (bottom (save-excursion (move-to-window-line bottom-margin) (point)))
- (far (save-excursion
- (goto-char bottom) (forward-line (- height 2)) (point))))
- (cond (tpu-advance
- (forward-page num)
- (cond((> (point) far)
- (setq left (save-excursion (forward-line height)))
- (if (= 0 left) (recenter top-margin)
- (recenter (- left bottom-up-margin))))
- (t
- (and (> (point) bottom) (recenter bottom-margin)))))
- (t
- (backward-page num)
- (and (< (point) top) (recenter (min beg top-margin)))))))
-
-
-;;; Scrolling
-
-(defun tpu-scroll-window-down (num)
- "Scroll the display down to the next section.
-A repeat count means scroll that many sections."
- (interactive "p")
- (let* ((beg (tpu-current-line))
- (height (1- (window-height)))
- (lines (* num (/ (* height tpu-percent-scroll) 100))))
- (next-line-internal (- lines))
- (tpu-top-check beg lines)))
-
-(defun tpu-scroll-window-up (num)
- "Scroll the display up to the next section.
-A repeat count means scroll that many sections."
- (interactive "p")
- (let* ((beg (tpu-current-line))
- (height (1- (window-height)))
- (lines (* num (/ (* height tpu-percent-scroll) 100))))
- (next-line-internal lines)
- (tpu-bottom-check beg lines)))
-
-
-;;; Replace the TPU-edt internal search function
-
-(defun tpu-search-internal (pat &optional quiet)
- "Search for a string or regular expression."
- (let* ((left nil)
- (beg (tpu-current-line))
- (height (window-height))
- (top-percent
- (if (= 0 tpu-top-scroll-margin) 10 tpu-top-scroll-margin))
- (bottom-percent
- (if (= 0 tpu-bottom-scroll-margin) 15 tpu-bottom-scroll-margin))
- (top-margin (/ (* height top-percent) 100))
- (bottom-up-margin (+ 1 (/ (* height bottom-percent) 100)))
- (bottom-margin (max beg (- height bottom-up-margin 1)))
- (top (save-excursion (move-to-window-line top-margin) (point)))
- (bottom (save-excursion (move-to-window-line bottom-margin) (point)))
- (far (save-excursion
- (goto-char bottom) (forward-line (- height 2)) (point))))
- (tpu-search-internal-core pat quiet)
- (if tpu-searching-forward
- (cond((> (point) far)
- (setq left (save-excursion (forward-line height)))
- (if (= 0 left) (recenter top-margin)
- (recenter (- left bottom-up-margin))))
- (t
- (and (> (point) bottom) (recenter bottom-margin))))
- (and (< (point) top) (recenter (min beg top-margin))))))
-
-
-
-;;; Replace the newline, newline-and-indent, and do-auto-fill functions
-
-(or (fboundp 'tpu-old-newline)
- (fset 'tpu-old-newline (symbol-function 'newline)))
-(or (fboundp 'tpu-old-do-auto-fill)
- (fset 'tpu-old-do-auto-fill (symbol-function 'do-auto-fill)))
-(or (fboundp 'tpu-old-newline-and-indent)
- (fset 'tpu-old-newline-and-indent (symbol-function 'newline-and-indent)))
-
-(defun newline (&optional num)
- "Insert a newline. With arg, insert that many newlines.
-In Auto Fill mode, can break the preceding line if no numeric arg.
-This is the TPU-edt version that respects the bottom scroll margin."
- (interactive "p")
- (let ((beg (tpu-current-line)))
- (or num (setq num 1))
- (tpu-old-newline num)
- (tpu-bottom-check beg num)))
-
-(defun newline-and-indent nil
- "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. This is the TPU-edt
-version that respects the bottom scroll margin."
- (interactive)
- (let ((beg (tpu-current-line)))
- (tpu-old-newline-and-indent)
- (tpu-bottom-check beg 1)))
-
-(defun do-auto-fill nil
- "TPU-edt version that respects the bottom scroll margin."
- (let ((beg (tpu-current-line)))
- (tpu-old-do-auto-fill)
- (tpu-bottom-check beg 1)))
-
-
-;;; Function to set scroll margins
-
-;;;###autoload
-(defun tpu-set-scroll-margins (top bottom)
- "Set scroll margins."
- (interactive
- "sEnter top scroll margin (N lines or N%% or RETURN for current value): \
-\nsEnter bottom scroll margin (N lines or N%% or RETURN for current value): ")
- ;; set top scroll margin
- (or (string= top "")
- (if (string= "%" (substring top -1))
- (setq tpu-top-scroll-margin (string-to-int top))
- (setq tpu-top-scroll-margin
- (/ (1- (+ (* (string-to-int top) 100) (window-height)))
- (window-height)))))
- ;; set bottom scroll margin
- (or (string= bottom "")
- (if (string= "%" (substring bottom -1))
- (setq tpu-bottom-scroll-margin (string-to-int bottom))
- (setq tpu-bottom-scroll-margin
- (/ (1- (+ (* (string-to-int bottom) 100) (window-height)))
- (window-height)))))
- ;; report scroll margin settings if running interactively
- (and (interactive-p)
- (message "Scroll margins set. Top = %s%%, Bottom = %s%%"
- tpu-top-scroll-margin tpu-bottom-scroll-margin)))
-
-
-;;; Functions to set cursor bound or free
-
-;;;###autoload
-(defun tpu-set-cursor-free nil
- "Allow the cursor to move freely about the screen."
- (interactive)
- (setq tpu-cursor-free t)
- (substitute-key-definition 'tpu-set-cursor-free
- 'tpu-set-cursor-bound
- GOLD-map)
- (message "The cursor will now move freely about the screen."))
-
-;;;###autoload
-(defun tpu-set-cursor-bound nil
- "Constrain the cursor to the flow of the text."
- (interactive)
- (picture-clean)
- (setq tpu-cursor-free nil)
- (substitute-key-definition 'tpu-set-cursor-bound
- 'tpu-set-cursor-free
- GOLD-map)
- (message "The cursor is now bound to the flow of your text."))
-
-;;; tpu-extras.el ends here
diff --git a/lisp/emulation/tpu-mapper.el b/lisp/emulation/tpu-mapper.el
deleted file mode 100644
index ba6d032fd6a..00000000000
--- a/lisp/emulation/tpu-mapper.el
+++ /dev/null
@@ -1,395 +0,0 @@
-;;; tpu-mapper.el --- Create a TPU-edt X-windows keymap file
-
-;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Rob Riepel <riepel@networking.stanford.edu>
-;; Maintainer: Rob Riepel <riepel@networking.stanford.edu>
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This emacs lisp program can be used to create an emacs lisp file that
-;; defines the TPU-edt keypad for emacs running on x-windows. Please read
-;; the "Usage" AND "Known Problems" sections before attempting to run this
-;; program.
-
-;;; Usage:
-
-;; Simply load this file into the X-windows version of emacs using the
-;; following command.
-
-;; emacs -q -l tpu-mapper
-
-;; The "-q" option prevents loading of your .emacs file (commands therein
-;; might confuse this program).
-
-;; An instruction screen showing the TPU-edt keypad will be displayed, and
-;; you will be prompted to press the TPU-edt editing keys. Tpu-mapper uses
-;; the keys you press to create an Emacs Lisp file that will define a
-;; TPU-edt keypad for your X server. You can even re-arrange the standard
-;; EDT keypad to suit your tastes (or to cope with those silly Sun and PC
-;; keypads).
-
-;; Finally, you will be prompted for the name of the file to store the key
-;; definitions. If you chose the default, TPU-edt will find it and load it
-;; automatically. If you specify a different file name, you will need to
-;; set the variable "tpu-xkeys-file" before starting TPU-edt. Here's how
-;; you might go about doing that in your .emacs file.
-
-;; (setq tpu-xkeys-file (expand-file-name "~/.my-emacs-x-keys"))
-;; (tpu-edt)
-
-;;; Known Problems:
-
-;; Sometimes, tpu-mapper will ignore a key you press, and just continue to
-;; prompt for the same key. This can happen when your window manager sucks
-;; up the key and doesn't pass it on to Emacs, or it could be an Emacs bug.
-;; Either way, there's nothing that tpu-mapper can do about it. You must
-;; press RETURN, to skip the current key and continue. Later, you and/or
-;; your local X guru can try to figure out why the key is being ignored.
-
-;;; Code:
-
-
-;;;
-;;; Make sure we're running X-windows and Emacs version 19
-;;;
-(cond
- ((not (and window-system (not (string-lessp emacs-version "19"))))
- (error "tpu-mapper requires running in Emacs 19, with an X display")))
-
-
-;;;
-;;; Decide whether we're running Lucid Emacs or Emacs itself.
-;;;
-(defconst tpu-lucid-emacs19-p (string-match "Lucid" emacs-version)
- "Non-NIL if we are running Lucid Emacs version 19.")
-
-
-;;;
-;;; Key variables
-;;;
-(defvar tpu-kp4 nil)
-(defvar tpu-kp5 nil)
-(defvar tpu-key nil)
-(defvar tpu-enter nil)
-(defvar tpu-return nil)
-(defvar tpu-key-seq nil)
-(defvar tpu-enter-seq nil)
-(defvar tpu-return-seq nil)
-
-
-;;;
-;;; Make sure the window is big enough to display the instructions
-;;;
-(if tpu-lucid-emacs19-p (set-screen-size (selected-screen) 80 36)
- (set-frame-size (selected-frame) 80 36))
-
-
-;;;
-;;; Create buffers - Directions, Keys, Gold-Keys
-;;;
-(if (not (get-buffer "Directions")) (generate-new-buffer "Directions"))
-(if (not (get-buffer "Keys")) (generate-new-buffer "Keys"))
-(if (not (get-buffer "Gold-Keys")) (generate-new-buffer "Gold-Keys"))
-
-
-;;;
-;;; Put headers in the Keys buffer
-;;;
-(set-buffer "Keys")
-(insert "\
-;; Key definitions for TPU-edt
-;;
-")
-
-
-;;;
-;;; Display directions
-;;;
-(switch-to-buffer "Directions")
-(insert "
- This program prompts you to press keys to create a custom keymap file
- for use with the x-windows version of Emacs and TPU-edt.
-
- Start by pressing the RETURN key, and continue by pressing the keys
- specified in the mini-buffer. You can re-arrange the TPU-edt keypad
- by pressing any key you want at any prompt. If you want to entirely
- omit a key, just press RETURN at the prompt.
-
- Here's a picture of the standard TPU/edt keypad for reference:
-
- _______________________ _______________________________
- | HELP | Do | | | | | |
- |KeyDefs| | | | | | |
- |_______|_______________| |_______|_______|_______|_______|
- _______________________ _______________________________
- | Find |Insert |Remove | | Gold | HELP |FndNxt | Del L |
- | | |Sto Tex| | key |E-Help | Find |Undel L|
- |_______|_______|_______| |_______|_______|_______|_______|
- |Select |Pre Scr|Nex Scr| | Page | Sect |Append | Del W |
- | Reset |Pre Win|Nex Win| | Do | Fill |Replace|Undel W|
- |_______|_______|_______| |_______|_______|_______|_______|
- |Move up| |Forward|Reverse|Remove | Del C |
- | Top | |Bottom | Top |Insert |Undel C|
- _______|_______|_______ |_______|_______|_______|_______|
- |Mov Lef|Mov Dow|Mov Rig| | Word | EOL | Char | |
- |StaOfLi|Bottom |EndOfLi| |ChngCas|Del EOL|SpecIns| Enter |
- |_______|_______|_______| |_______|_______|_______| |
- | Line |Select | Subs |
- | Open Line | Reset | |
- |_______________|_______|_______|
-
-
-")
-(delete-other-windows)
-(goto-char (point-min))
-
-;;;
-;;; Save <CR> for future reference
-;;;
-(cond
- (tpu-lucid-emacs19-p
- (setq tpu-return-seq (read-key-sequence "Hit carriage-return <CR> to continue "))
- (setq tpu-return (concat "[" (format "%s" (event-key (aref tpu-return-seq 0))) "]")))
- (t
- (message "Hit carriage-return <CR> to continue ")
- (setq tpu-return-seq (read-event))
- (setq tpu-return (concat "[" (format "%s" tpu-return-seq) "]"))))
-
-
-;;;
-;;; Key mapping functions
-;;;
-(defun tpu-lucid-map-key (ident descrip func gold-func)
- (interactive)
- (setq tpu-key-seq (read-key-sequence (format "Press %s%s: " ident descrip)))
- (setq tpu-key (concat "[" (format "%s" (event-key (aref tpu-key-seq 0))) "]"))
- (cond ((not (equal tpu-key tpu-return))
- (set-buffer "Keys")
- (insert (format"(global-set-key %s %s)\n" tpu-key func))
- (set-buffer "Gold-Keys")
- (insert (format "(define-key GOLD-map %s %s)\n" tpu-key gold-func))
- (set-buffer "Directions"))
- ;; bogosity to get next prompt to come up, if the user hits <CR>!
- ;; check periodically to see if this is still needed...
- (t
- (format "%s" tpu-key)))
- tpu-key)
-
-(defun tpu-emacs-map-key (ident descrip func gold-func)
- (interactive)
- (message "Press %s%s: " ident descrip)
- (setq tpu-key-seq (read-event))
- (setq tpu-key (concat "[" (format "%s" tpu-key-seq) "]"))
- (cond ((not (equal tpu-key tpu-return))
- (set-buffer "Keys")
- (insert (format"(global-set-key %s %s)\n" tpu-key func))
- (set-buffer "Gold-Keys")
- (insert (format "(define-key GOLD-map %s %s)\n" tpu-key gold-func))
- (set-buffer "Directions"))
- ;; bogosity to get next prompt to come up, if the user hits <CR>!
- ;; check periodically to see if this is still needed...
- (t
- (format "%s" tpu-key)))
- tpu-key)
-
-(fset 'tpu-map-key (if tpu-lucid-emacs19-p 'tpu-lucid-map-key 'tpu-emacs-map-key))
-
-
-(set-buffer "Keys")
-(insert "
-;; Arrows
-;;
-")
-(set-buffer "Gold-Keys")
-(insert "
-;; GOLD Arrows
-;;
-")
-(set-buffer "Directions")
-
-(tpu-map-key "Up-Arrow" "" "'tpu-previous-line" "'tpu-move-to-beginning")
-(tpu-map-key "Down-arrow" "" "'tpu-next-line" "'tpu-move-to-end")
-(tpu-map-key "Right-arrow" "" "'tpu-forward-char" "'end-of-line")
-(tpu-map-key "Left-arrow" "" "'tpu-backward-char" "'beginning-of-line")
-
-
-(set-buffer "Keys")
-(insert "
-;; PF keys
-;;
-")
-(set-buffer "Gold-Keys")
-(insert "
-;; GOLD PF keys
-;;
-")
-(set-buffer "Directions")
-
-(tpu-map-key "PF1" " - The GOLD key" "GOLD-map" "'keyboard-quit")
-(tpu-map-key "PF2" " - The Keypad Help key" "'tpu-help" "'help-for-help")
-(tpu-map-key "PF3" " - The Find/Find-Next key" "'tpu-search-again" "'tpu-search")
-(tpu-map-key "PF4" " - The Del/Undelete Line key" "'tpu-delete-current-line" "'tpu-undelete-lines")
-
-(set-buffer "Keys")
-(insert "
-;; KP0-9 KP- KP, KP. and KPenter
-;;
-")
-(set-buffer "Gold-Keys")
-(insert "
-;; GOLD KP0-9 KP- KP, and KPenter
-;;
-")
-(set-buffer "Directions")
-
-(tpu-map-key "KP-0" " - The Line/Open-Line key" "'tpu-line" "'open-line")
-(tpu-map-key "KP-1" " - The Word/Change-Case key" "'tpu-word" "'tpu-change-case")
-(tpu-map-key "KP-2" " - The EOL/Delete-EOL key" "'tpu-end-of-line" "'tpu-delete-to-eol")
-(tpu-map-key "KP-3" " - The Character/Special-Insert key" "'tpu-char" "'tpu-special-insert")
-(setq tpu-kp4 (tpu-map-key "KP-4" " - The Forward/Bottom key" "'tpu-advance-direction" "'tpu-move-to-end"))
-(setq tpu-kp5 (tpu-map-key "KP-5" " - The Reverse/Top key" "'tpu-backup-direction" "'tpu-move-to-beginning"))
-(tpu-map-key "KP-6" " - The Remove/Insert key" "'tpu-cut" "'tpu-paste")
-(tpu-map-key "KP-7" " - The Page/Do key" "'tpu-page" "'execute-extended-command")
-(tpu-map-key "KP-8" " - The Section/Fill key" "'tpu-scroll-window" "'tpu-fill")
-(tpu-map-key "KP-9" " - The Append/Replace key" "'tpu-append-region" "'tpu-replace")
-(tpu-map-key "KP--" " - The Delete/Undelete Word key" "'tpu-delete-current-word" "'tpu-undelete-words")
-(tpu-map-key "KP-," " - The Delete/Undelete Character key" "'tpu-delete-current-char" "'tpu-undelete-char")
-(tpu-map-key "KP-." " - The Select/Reset key" "'tpu-select" "'tpu-unselect")
-(tpu-map-key "KP-Enter" " - The Enter key on the numeric keypad" "'newline" "'tpu-substitute")
-;; Save the enter key
-(setq tpu-enter tpu-key)
-(setq tpu-enter-seq tpu-key-seq)
-
-(set-buffer "Keys")
-(insert "
-;; Editing keypad (find, insert, remove)
-;; (select, prev, next)
-;;
-")
-(set-buffer "Gold-Keys")
-(insert "
-;; GOLD Editing keypad (find, insert, remove)
-;; (select, prev, next)
-;;
-")
-(set-buffer "Directions")
-
-(tpu-map-key "Find" " - The Find key on the editing keypad" "'tpu-search" "'nil")
-(tpu-map-key "Insert" " - The Insert key on the editing keypad" "'tpu-paste" "'nil")
-(tpu-map-key "Remove" " - The Remove key on the editing keypad" "'tpu-cut" "'tpu-store-text")
-(tpu-map-key "Select" " - The Select key on the editing keypad" "'tpu-select" "'tpu-unselect")
-(tpu-map-key "Prev Scr" " - The Prev Scr key on the editing keypad" "'tpu-scroll-window-down" "'tpu-previous-window")
-(tpu-map-key "Next Scr" " - The Next Scr key on the editing keypad" "'tpu-scroll-window-up" "'tpu-next-window")
-
-(set-buffer "Keys")
-(insert "
-;; F10-14 Help Do F17
-;;
-")
-(set-buffer "Gold-Keys")
-(insert "
-;; GOLD F10-14 Help Do F17
-;;
-")
-(set-buffer "Directions")
-
-(tpu-map-key "F10" " - Invokes the Exit function on VT200+ terminals" "'tpu-exit" "'nil")
-(tpu-map-key "F11" " - Inserts an Escape character into the text" "'tpu-insert-escape" "'nil")
-(tpu-map-key "Backspace" " - Not Delete nor ^H! Sometimes on the F12 key" "'tpu-next-beginning-of-line" "'nil")
-(tpu-map-key "F13" " - Invokes the delete previous word function" "'tpu-delete-previous-word" "'nil")
-(tpu-map-key "F14" " - Toggles insert/overstrike modes" "'tpu-toggle-overwrite-mode" "'nil")
-(tpu-map-key "Help" " - Brings up the help screen, same as PF2" "'tpu-help" "'describe-bindings")
-(tpu-map-key "Do" " - Invokes the COMMAND function" "'execute-extended-command" "'nil")
-(tpu-map-key "F17" "" "'tpu-goto-breadcrumb" "'tpu-drop-breadcrumb")
-
-(set-buffer "Gold-Keys")
-(cond
- ((not (equal tpu-enter tpu-return))
- (insert "
-;; Minibuffer map additions to make KP_enter = RET
-;;
-")
-
- (insert (format "(define-key minibuffer-local-map %s 'exit-minibuffer)\n" tpu-enter))
- (insert (format "(define-key minibuffer-local-ns-map %s 'exit-minibuffer)\n" tpu-enter))
- (insert (format "(define-key minibuffer-local-completion-map %s 'exit-minibuffer)\n" tpu-enter))
- (insert (format "(define-key minibuffer-local-must-match-map %s 'minibuffer-complete-and-exit)\n" tpu-enter))))
-
-(cond
- ((not (or (equal tpu-kp4 tpu-return) (equal tpu-kp5 tpu-return)))
- (insert "
-;; Minibuffer map additions to allow KP-4/5 termination of search strings.
-;;
-")
-
- (insert (format "(define-key minibuffer-local-map %s 'tpu-search-forward-exit)\n" tpu-kp4))
- (insert (format "(define-key minibuffer-local-map %s 'tpu-search-backward-exit)\n" tpu-kp5))))
-
-(insert "
-;; Define the tpu-help-enter/return symbols
-;;
-")
-
-(cond (tpu-lucid-emacs19-p
- (insert (format "(setq tpu-help-enter \"%s\")\n" tpu-enter-seq))
- (insert (format "(setq tpu-help-return \"%s\")\n" tpu-return-seq))
- (insert "(setq tpu-help-N \"[#<keypress-event N>]\")\n")
- (insert "(setq tpu-help-n \"[#<keypress-event n>]\")\n")
- (insert "(setq tpu-help-P \"[#<keypress-event P>]\")\n")
- (insert "(setq tpu-help-p \"[#<keypress-event p>]\")\n"))
- (t
- (insert (format "(setq tpu-help-enter \"%s\")\n" tpu-enter))))
-
-(append-to-buffer "Keys" 1 (point))
-(set-buffer "Keys")
-
-;;;
-;;; Save the key mapping program
-;;;
-(let ((file
- (convert-standard-filename
- (if tpu-lucid-emacs19-p "~/.tpu-lucid-keys" "~/.tpu-keys"))))
- (set-visited-file-name
- (read-file-name (format "Save key mapping to file (default %s): " file) "" file)))
-(save-buffer)
-
-;;;
-;;; Load the newly defined keys and clean up
-;;;
-(eval-current-buffer)
-(kill-buffer (current-buffer))
-(kill-buffer "*scratch*")
-(kill-buffer "Gold-Keys")
-
-;;;
-;;; Let them know it worked.
-;;;
-(switch-to-buffer "Directions")
-(erase-buffer)
-(insert "
- A custom TPU-edt keymap file has been created.
-
- Press GOLD-k to remove this buffer and continue editing.
-")
-(goto-char (point-min))
-
-;;; tpu-mapper.el ends here
diff --git a/lisp/emulation/vi.el b/lisp/emulation/vi.el
deleted file mode 100644
index 265ab94f43f..00000000000
--- a/lisp/emulation/vi.el
+++ /dev/null
@@ -1,1467 +0,0 @@
-;;; vi.el --- major mode for emulating "vi" editor under GNU Emacs.
-
-; This file is in the public domain because the authors distributed it
-; without a copyright notice before the US signed the Bern Convention.
-
-;; Author: Neal Ziring <nz@rsch.wisc.edu>
-;; Felix S. T. Wu <wu@crys.wisc.edu>
-;; Keywords: emulations
-
-;;; Commentary:
-
-; Originally written by : seismo!wucs!nz@rsch.wisc.edu (Neal Ziring)
-; Extensively redesigned and rewritten by wu@crys.wisc.edu (Felix S.T. Wu)
-; Last revision: 01/07/87 Wed (for GNU Emacs 18.33)
-
-; INSTALLATION PROCEDURE:
-; 1) Add a global key binding for command "vi-mode" (I use ESC ESC instead of
-; the single ESC used in real "vi", so I can access other ESC prefixed emacs
-; commands while I'm in "vi"), say, by putting the following line in your
-; ".emacs" file:
-; (define-key global-map "\e\e" 'vi-mode) ;quick switch into vi-mode
-; 2) If you wish you can define "find-file-hooks" to enter "vi" automatically
-; after a file is loaded into the buffer. For example, I defined it as:
-; (setq find-file-hooks (list
-; (function (lambda ()
-; (if (not (or (eq major-mode 'Info-mode)
-; (eq major-mode 'vi-mode)))
-; (vi-mode))))))
-; 3) In your .emacs file you can define the command "vi-mode" to be "autoload"
-; or you can execute the "load" command to load "vi" directly.
-; 4) Read the comments for command "vi-mode" before you start using it.
-;
-; COULD DO
-; 1). A general 'define-operator' function to replace current hack
-; 2). In operator handling, should allow other point moving Emacs commands
-; (such as ESC <, ESC >) to be used as arguments.
-;
-;;; Code:
-
-(defun vi-switch-mode (arg mode-char)
- "Switch the major mode of current buffer as specified by the following char \\{vi-tilde-map}"
- (interactive "P\nc")
- (let ((mode-cmd (lookup-key vi-tilde-map (char-to-string mode-char))))
- (if (null mode-cmd)
- (with-output-to-temp-buffer "*Help*"
- (princ (substitute-command-keys "Possible major modes to switch to: \\{vi-tilde-map}"))
- (save-excursion
- (set-buffer standard-output)
- (help-mode)))
- (setq prefix-arg arg) ; prefix arg will be passed down
- (command-execute mode-cmd nil) ; may need to save mode-line-format etc
- (force-mode-line-update)))) ; just in case
-
-
-(if (null (where-is-internal 'vi-switch-mode (current-local-map)))
- (define-key ctl-x-map "~" 'vi-switch-mode))
-
-(defvar vi-tilde-map nil
- "Keymap used for \\[vi-switch-mode] prefix key. Link to various major modes.")
-
-(if vi-tilde-map
- nil
- (setq vi-tilde-map (make-keymap))
- (define-key vi-tilde-map "a" 'abbrev-mode)
- (define-key vi-tilde-map "c" 'c-mode)
- (define-key vi-tilde-map "d" 'vi-debugging)
- (define-key vi-tilde-map "e" 'emacs-lisp-mode)
- (define-key vi-tilde-map "f" 'auto-fill-mode)
- (define-key vi-tilde-map "g" 'prolog-mode)
- (define-key vi-tilde-map "h" 'hanoi)
- (define-key vi-tilde-map "i" 'info-mode)
- (define-key vi-tilde-map "l" 'lisp-mode)
- (define-key vi-tilde-map "n" 'nroff-mode)
- (define-key vi-tilde-map "o" 'overwrite-mode)
- (define-key vi-tilde-map "O" 'outline-mode)
- (define-key vi-tilde-map "P" 'picture-mode)
- (define-key vi-tilde-map "r" 'vi-readonly-mode)
- (define-key vi-tilde-map "t" 'text-mode)
- (define-key vi-tilde-map "v" 'vi-mode)
- (define-key vi-tilde-map "x" 'tex-mode)
- (define-key vi-tilde-map "~" 'vi-back-to-old-mode))
-
-(defun vi-debugging (arg)
- "Toggle debug-on-error flag. If prefix arg is given, set t."
- (interactive "P")
- (if arg
- (setq debug-on-error t)
- (setq debug-on-error (not debug-on-error)))
- (if debug-on-error
- (message "Debug-on-error ...")
- (message "NO more debug-on-error")))
-
-(defun vi-back-to-old-mode ()
- "Go back to the previous mode without setting up for insertion."
- (interactive)
- (if vi-mode-old-major-mode
- (progn
- (setq mode-name vi-mode-old-mode-name)
- (use-local-map vi-mode-old-local-map)
- (setq major-mode vi-mode-old-major-mode)
- (setq case-fold-search vi-mode-old-case-fold)
- (force-mode-line-update))))
-
-(defun vi-readonly-mode ()
- "Toggle current buffer's readonly flag."
- (interactive)
- (setq buffer-read-only (not buffer-read-only)))
-
-(defvar vi-com-map nil
- "Keymap used in Evi's command state
-Command state includes most of the vi editing commands, with some Emacs
-command extensions.")
-
-(put 'vi-undefined 'suppress-keymap t)
-(if vi-com-map nil
- (setq vi-com-map (make-keymap))
-;;(fillarray vi-com-map 'vi-undefined)
- (define-key vi-com-map "\C-@" 'vi-mark-region) ; extension
- (define-key vi-com-map "\C-a" 'vi-ask-for-info) ; extension
- (define-key vi-com-map "\C-b" 'vi-backward-windowful)
- (define-key vi-com-map "\C-c" 'vi-do-old-mode-C-c-command) ; extension
- (define-key vi-com-map "\C-d" 'vi-scroll-down-window)
- (define-key vi-com-map "\C-e" 'vi-expose-line-below)
- (define-key vi-com-map "\C-f" 'vi-forward-windowful)
- (define-key vi-com-map "\C-g" 'keyboard-quit)
- (define-key vi-com-map "\C-i" 'indent-relative-maybe) ; TAB
- (define-key vi-com-map "\C-j" 'vi-next-line) ; LFD
- (define-key vi-com-map "\C-k" 'vi-kill-line) ; extension
- (define-key vi-com-map "\C-l" 'recenter)
- (define-key vi-com-map "\C-m" 'vi-next-line-first-nonwhite) ; RET
- (define-key vi-com-map "\C-n" 'vi-next-line)
- (define-key vi-com-map "\C-o" 'vi-split-open-line)
- (define-key vi-com-map "\C-p" 'previous-line)
- (define-key vi-com-map "\C-q" 'vi-query-replace) ; extension
- (define-key vi-com-map "\C-r" 'vi-isearch-backward) ; modification
- (define-key vi-com-map "\C-s" 'vi-isearch-forward) ; extension
- (define-key vi-com-map "\C-t" 'vi-transpose-objects) ; extension
- (define-key vi-com-map "\C-u" 'vi-scroll-up-window)
- (define-key vi-com-map "\C-v" 'scroll-up) ; extension
- (define-key vi-com-map "\C-w" 'vi-kill-region) ; extension
- (define-key vi-com-map "\C-x" 'Control-X-prefix) ; extension
- (define-key vi-com-map "\C-y" 'vi-expose-line-above)
- (define-key vi-com-map "\C-z" 'suspend-emacs)
-
- (define-key vi-com-map "\e" 'ESC-prefix); C-[ (ESC)
- (define-key vi-com-map "\C-\\" 'vi-unimplemented)
- (define-key vi-com-map "\C-]" 'find-tag)
- (define-key vi-com-map "\C-^" 'vi-locate-def) ; extension
- (define-key vi-com-map "\C-_" 'vi-undefined)
-
- (define-key vi-com-map " " 'forward-char)
- (define-key vi-com-map "!" 'vi-operator)
- (define-key vi-com-map "\"" 'vi-char-argument)
- (define-key vi-com-map "#" 'universal-argument) ; extension
- (define-key vi-com-map "$" 'end-of-line)
- (define-key vi-com-map "%" 'vi-find-matching-paren)
- (define-key vi-com-map "&" 'vi-unimplemented)
- (define-key vi-com-map "'" 'vi-goto-line-mark)
- (define-key vi-com-map "(" 'backward-sexp)
- (define-key vi-com-map ")" 'forward-sexp)
- (define-key vi-com-map "*" 'vi-name-last-change-or-macro) ; extension
- (define-key vi-com-map "+" 'vi-next-line-first-nonwhite)
- (define-key vi-com-map "," 'vi-reverse-last-find-char)
- (define-key vi-com-map "-" 'vi-previous-line-first-nonwhite)
- (define-key vi-com-map "." 'vi-redo-last-change-command)
- (define-key vi-com-map "/" 'vi-search-forward)
- (define-key vi-com-map "0" 'beginning-of-line)
-
- (define-key vi-com-map "1" 'vi-digit-argument)
- (define-key vi-com-map "2" 'vi-digit-argument)
- (define-key vi-com-map "3" 'vi-digit-argument)
- (define-key vi-com-map "4" 'vi-digit-argument)
- (define-key vi-com-map "5" 'vi-digit-argument)
- (define-key vi-com-map "6" 'vi-digit-argument)
- (define-key vi-com-map "7" 'vi-digit-argument)
- (define-key vi-com-map "8" 'vi-digit-argument)
- (define-key vi-com-map "9" 'vi-digit-argument)
-
- (define-key vi-com-map ":" 'vi-ex-cmd)
- (define-key vi-com-map ";" 'vi-repeat-last-find-char)
- (define-key vi-com-map "<" 'vi-operator)
- (define-key vi-com-map "=" 'vi-operator)
- (define-key vi-com-map ">" 'vi-operator)
- (define-key vi-com-map "?" 'vi-search-backward)
- (define-key vi-com-map "@" 'vi-call-named-change-or-macro) ; extension
-
- (define-key vi-com-map "A" 'vi-append-at-end-of-line)
- (define-key vi-com-map "B" 'vi-backward-blank-delimited-word)
- (define-key vi-com-map "C" 'vi-change-rest-of-line)
- (define-key vi-com-map "D" 'vi-kill-line)
- (define-key vi-com-map "E" 'vi-end-of-blank-delimited-word)
- (define-key vi-com-map "F" 'vi-backward-find-char)
- (define-key vi-com-map "G" 'vi-goto-line)
- (define-key vi-com-map "H" 'vi-home-window-line)
- (define-key vi-com-map "I" 'vi-insert-before-first-nonwhite)
- (define-key vi-com-map "J" 'vi-join-lines)
- (define-key vi-com-map "K" 'vi-undefined)
- (define-key vi-com-map "L" 'vi-last-window-line)
- (define-key vi-com-map "M" 'vi-middle-window-line)
- (define-key vi-com-map "N" 'vi-reverse-last-search)
- (define-key vi-com-map "O" 'vi-open-above)
- (define-key vi-com-map "P" 'vi-put-before)
- (define-key vi-com-map "Q" 'vi-quote-words) ; extension
- (define-key vi-com-map "R" 'vi-replace-chars)
- (define-key vi-com-map "S" 'vi-substitute-lines)
- (define-key vi-com-map "T" 'vi-backward-upto-char)
- (define-key vi-com-map "U" 'vi-unimplemented)
- (define-key vi-com-map "V" 'vi-undefined)
- (define-key vi-com-map "W" 'vi-forward-blank-delimited-word)
- (define-key vi-com-map "X" 'call-last-kbd-macro) ; modification/extension
- (define-key vi-com-map "Y" 'vi-yank-line)
- (define-key vi-com-map "Z" (make-sparse-keymap)) ;allow below prefix command
- (define-key vi-com-map "ZZ" 'vi-save-all-and-exit)
-
- (define-key vi-com-map "[" 'vi-unimplemented)
- (define-key vi-com-map "\\" 'vi-operator) ; extension for vi-narrow-op
- (define-key vi-com-map "]" 'vi-unimplemented)
- (define-key vi-com-map "^" 'back-to-indentation)
- (define-key vi-com-map "_" 'vi-undefined)
- (define-key vi-com-map "`" 'vi-goto-char-mark)
-
- (define-key vi-com-map "a" 'vi-insert-after)
- (define-key vi-com-map "b" 'backward-word)
- (define-key vi-com-map "c" 'vi-operator)
- (define-key vi-com-map "d" 'vi-operator)
- (define-key vi-com-map "e" 'vi-end-of-word)
- (define-key vi-com-map "f" 'vi-forward-find-char)
- (define-key vi-com-map "g" 'vi-beginning-of-buffer) ; extension
- (define-key vi-com-map "h" 'backward-char)
- (define-key vi-com-map "i" 'vi-insert-before)
- (define-key vi-com-map "j" 'vi-next-line)
- (define-key vi-com-map "k" 'previous-line)
- (define-key vi-com-map "l" 'forward-char)
- (define-key vi-com-map "m" 'vi-set-mark)
- (define-key vi-com-map "n" 'vi-repeat-last-search)
- (define-key vi-com-map "o" 'vi-open-below)
- (define-key vi-com-map "p" 'vi-put-after)
- (define-key vi-com-map "q" 'vi-replace)
- (define-key vi-com-map "r" 'vi-replace-1-char)
- (define-key vi-com-map "s" 'vi-substitute-chars)
- (define-key vi-com-map "t" 'vi-forward-upto-char)
- (define-key vi-com-map "u" 'undo)
- (define-key vi-com-map "v" 'vi-verify-spelling)
- (define-key vi-com-map "w" 'vi-forward-word)
- (define-key vi-com-map "x" 'vi-kill-char)
- (define-key vi-com-map "y" 'vi-operator)
- (define-key vi-com-map "z" 'vi-adjust-window)
-
- (define-key vi-com-map "{" 'backward-paragraph)
- (define-key vi-com-map "|" 'vi-goto-column)
- (define-key vi-com-map "}" 'forward-paragraph)
- (define-key vi-com-map "~" 'vi-change-case)
- (define-key vi-com-map "\177" 'delete-backward-char))
-
-(put 'backward-char 'point-moving-unit 'char)
-(put 'vi-next-line 'point-moving-unit 'line)
-(put 'next-line 'point-moving-unit 'line)
-(put 'forward-line 'point-moving-unit 'line)
-(put 'previous-line 'point-moving-unit 'line)
-(put 'vi-isearch-backward 'point-moving-unit 'search)
-(put 'vi-search-backward 'point-moving-unit 'search)
-(put 'vi-isearch-forward 'point-moving-unit 'search)
-(put 'vi-search-forward 'point-moving-unit 'search)
-(put 'forward-char 'point-moving-unit 'char)
-(put 'end-of-line 'point-moving-unit 'char)
-(put 'vi-find-matching-paren 'point-moving-unit 'match)
-(put 'vi-goto-line-mark 'point-moving-unit 'line)
-(put 'backward-sexp 'point-moving-unit 'sexp)
-(put 'forward-sexp 'point-moving-unit 'sexp)
-(put 'vi-next-line-first-nonwhite 'point-moving-unit 'line)
-(put 'vi-previous-line-first-nonwhite 'point-moving-unit 'line)
-(put 'vi-reverse-last-find-char 'point-moving-unit 'rev-find)
-(put 'vi-re-search-forward 'point-moving-unit 'search)
-(put 'beginning-of-line 'point-moving-unit 'char)
-(put 'vi-beginning-of-buffer 'point-moving-unit 'char)
-(put 'vi-repeat-last-find-char 'point-moving-unit 'find)
-(put 'vi-re-search-backward 'point-moving-unit 'search)
-(put 'vi-backward-blank-delimited-word 'point-moving-unit 'WORD)
-(put 'vi-end-of-blank-delimited-word 'point-moving-unit 'match)
-(put 'vi-backward-find-char 'point-moving-unit 'find)
-(put 'vi-goto-line 'point-moving-unit 'line)
-(put 'vi-home-window-line 'point-moving-unit 'line)
-(put 'vi-last-window-line 'point-moving-unit 'line)
-(put 'vi-middle-window-line 'point-moving-unit 'line)
-(put 'vi-reverse-last-search 'point-moving-unit 'rev-search)
-(put 'vi-backward-upto-char 'point-moving-unit 'find)
-(put 'vi-forward-blank-delimited-word 'point-moving-unit 'WORD)
-(put 'back-to-indentation 'point-moving-unit 'char)
-(put 'vi-goto-char-mark 'point-moving-unit 'char)
-(put 'backward-word 'point-moving-unit 'word)
-(put 'vi-end-of-word 'point-moving-unit 'match)
-(put 'vi-forward-find-char 'point-moving-unit 'find)
-(put 'backward-char 'point-moving-unit 'char)
-(put 'vi-forward-char 'point-moving-unit 'char)
-(put 'vi-repeat-last-search 'point-moving-unit 'search)
-(put 'vi-forward-upto-char 'point-moving-unit 'find)
-(put 'vi-forward-word 'point-moving-unit 'word)
-(put 'vi-goto-column 'point-moving-unit 'match)
-(put 'forward-paragraph 'point-moving-unit 'paragraph)
-(put 'backward-paragraph 'point-moving-unit 'paragraph)
-
-;;; region mark commands
-(put 'mark-page 'point-moving-unit 'region)
-(put 'mark-paragraph 'point-moving-unit 'region)
-(put 'mark-word 'point-moving-unit 'region)
-(put 'mark-sexp 'point-moving-unit 'region)
-(put 'mark-defun 'point-moving-unit 'region)
-(put 'mark-whole-buffer 'point-moving-unit 'region)
-(put 'mark-end-of-sentence 'point-moving-unit 'region)
-(put 'mark-c-function 'point-moving-unit 'region)
-;;;
-
-(defvar vi-mark-alist nil
- "Alist of (NAME . MARK), marks are local to each buffer.")
-
-(defvar vi-scroll-amount (/ (window-height) 2)
- "Default amount of lines for scrolling (used by \"^D\"/\"^U\").")
-
-(defvar vi-shift-width 4
- "Shift amount for \"<\"/\">\" operators.")
-
-(defvar vi-ins-point nil ; integer
- "Last insertion point. Should use `mark' instead.")
-
-(defvar vi-ins-length nil ; integer
- "Length of last insertion.")
-
-(defvar vi-ins-repetition nil ; integer
- "The repetition required for last insertion.")
-
-(defvar vi-ins-overwrt-p nil ; boolean
- "T if last insertion was a replace actually.")
-
-(defvar vi-ins-prefix-code nil ; ready-to-eval sexp
- "Code to be eval'ed before (redo-)insertion begins.")
-
-(defvar vi-last-find-char nil ; cons cell
- "Save last direction, char and upto-flag used for char finding.")
-
-(defvar vi-last-change-command nil ; cons cell
- "Save commands for redoing last changes. Each command is in (FUNC . ARGS)
-form that is ready to be `apply'ed.")
-
-(defvar vi-last-shell-command nil ; last shell op command line
- "Save last shell command given for \"!\" operator.")
-
-(defvar vi-insert-state nil ; boolean
- "Non-nil if it is in insert state.")
-
-; in "loaddefs.el"
-;(defvar search-last-string ""
-; "Last string search for by a search command.")
-
-(defvar vi-search-last-command nil ; (re-)search-forward(backward)
- "Save last search command for possible redo.")
-
-(defvar vi-mode-old-local-map nil
- "Save the local-map used before entering vi-mode.")
-
-(defvar vi-mode-old-mode-name nil
- "Save the mode-name before entering vi-mode.")
-
-(defvar vi-mode-old-major-mode nil
- "Save the major-mode before entering vi-mode.")
-
-(defvar vi-mode-old-case-fold nil)
-
-;(defconst vi-add-to-mode-line-1
-; '(overwrite-mode nil " Insert"))
-
-;; Value is same as vi-add-to-mode-line-1 when in vi mode,
-;; but nil in other buffers.
-;(defvar vi-add-to-mode-line nil)
-
-(defun vi-mode-setup ()
- "Setup a buffer for vi-mode by creating necessary buffer-local variables."
-; (make-local-variable 'vi-add-to-mode-line)
-; (setq vi-add-to-mode-line vi-add-to-mode-line-1)
-; (or (memq vi-add-to-mode-line minor-mode-alist)
-; (setq minor-mode-alist (cons vi-add-to-mode-line minor-mode-alist)))
- (make-local-variable 'vi-scroll-amount)
- (setq vi-scroll-amount (/ (window-height) 2))
- (make-local-variable 'vi-shift-width)
- (setq vi-shift-width 4)
- (make-local-variable 'vi-ins-point)
- (make-local-variable 'vi-ins-length)
- (make-local-variable 'vi-ins-repetition)
- (make-local-variable 'vi-ins-overwrt-p)
- (make-local-variable 'vi-ins-prefix-code)
- (make-local-variable 'vi-last-change-command)
- (make-local-variable 'vi-last-shell-command)
- (make-local-variable 'vi-last-find-char)
- (make-local-variable 'vi-mark-alist)
- (make-local-variable 'vi-insert-state)
- (make-local-variable 'vi-mode-old-local-map)
- (make-local-variable 'vi-mode-old-mode-name)
- (make-local-variable 'vi-mode-old-major-mode)
- (make-local-variable 'vi-mode-old-case-fold)
- (run-hooks 'vi-mode-hook))
-
-;;;###autoload
-(defun vi-mode ()
- "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."
- (interactive)
- (if (null vi-mode-old-major-mode) ; very first call for current buffer
- (vi-mode-setup))
-
- (if (eq major-mode 'vi-mode)
- (message "Already in vi-mode." (ding))
- (setq vi-mode-old-local-map (current-local-map))
- (setq vi-mode-old-mode-name mode-name)
- (setq vi-mode-old-major-mode major-mode)
- (setq vi-mode-old-case-fold case-fold-search) ; this is needed !!
- (setq case-fold-search nil) ; exact case match in searching
- (use-local-map vi-com-map)
- (setq major-mode 'vi-mode)
- (setq mode-name "VI")
- (force-mode-line-update) ; force mode line update
- (if vi-insert-state ; this is a return from insertion
- (vi-end-of-insert-state))))
-
-(defun vi-ding()
- "Ding !"
- (interactive)
- (ding))
-
-(defun vi-save-all-and-exit ()
- "Save all modified buffers without asking, then exits emacs."
- (interactive)
- (save-some-buffers t)
- (kill-emacs))
-
-;; to be used by "ex" commands
-(defvar vi-replaced-string nil)
-(defvar vi-replacing-string nil)
-
-(defun vi-ex-cmd ()
- "Ex commands are not implemented in Evi mode. For some commonly used ex
-commands, you can use the following alternatives for similar effect :
-w C-x C-s (save-buffer)
-wq C-x C-c (save-buffers-kill-emacs)
-w fname C-x C-w (write-file)
-e fname C-x C-f (find-file)
-r fname C-x i (insert-file)
-s/old/new use q (vi-replace) to do unconditional replace
- use C-q (vi-query-replace) to do query replace
-set sw=n M-x set-variable vi-shift-width n "
- (interactive)
-;; (let ((cmd (read-string ":")) (lines 1))
-;; (cond ((string-match "s"))))
- (with-output-to-temp-buffer "*Help*"
- (princ (documentation 'vi-ex-cmd))
- (save-excursion
- (set-buffer standard-output)
- (help-mode))))
-
-(defun vi-undefined ()
- (interactive)
- (message "Command key \"%s\" is undefined in Evi."
- (single-key-description last-command-char))
- (ding))
-
-(defun vi-unimplemented ()
- (interactive)
- (message "Command key \"%s\" is not implemented in Evi."
- (single-key-description last-command-char))
- (ding))
-
-;;;;;
-(defun vi-goto-insert-state (repetition &optional prefix-code do-it-now-p)
- "Go into insert state, the text entered will be repeated if REPETITION > 1.
-If PREFIX-CODE is given, do it before insertion begins if DO-IT-NOW-P is T.
-In any case, the prefix-code will be done before each 'redo-insert'.
-This function expects 'overwrite-mode' being set properly beforehand."
- (if do-it-now-p (apply (car prefix-code) (cdr prefix-code)))
- (setq vi-ins-point (point))
- (setq vi-ins-repetition repetition)
- (setq vi-ins-prefix-code prefix-code)
- (setq mode-name vi-mode-old-mode-name)
- (setq case-fold-search vi-mode-old-case-fold)
- (use-local-map vi-mode-old-local-map)
- (setq major-mode vi-mode-old-major-mode)
- (force-mode-line-update)
- (setq vi-insert-state t))
-
-(defun vi-end-of-insert-state ()
- "Terminate insertion and set up last change command."
- (if (or (< (point) vi-ins-point) ;Check if there is any effective change
- (and (= (point) vi-ins-point) (null vi-ins-prefix-code))
- (<= vi-ins-repetition 0))
- (vi-goto-command-state t)
- (if (> vi-ins-repetition 1)
- (progn
- (let ((str (buffer-substring vi-ins-point (point))))
- (while (> vi-ins-repetition 1)
- (insert str)
- (setq vi-ins-repetition (1- vi-ins-repetition))))))
- (vi-set-last-change-command 'vi-first-redo-insertion vi-ins-point (point)
- overwrite-mode vi-ins-prefix-code)
- (vi-goto-command-state t)))
-
-(defun vi-first-redo-insertion (begin end &optional overwrite-p prefix-code)
- "Redo last insertion the first time. Extract the string and save it for
-future redoes. Do prefix-code if it's given, use overwrite mode if asked."
- (let ((str (buffer-substring begin end)))
- (if prefix-code (apply (car prefix-code) (cdr prefix-code)))
- (if overwrite-p (delete-region (point) (+ (point) (length str))))
- (insert str)
- (vi-set-last-change-command 'vi-more-redo-insertion str overwrite-p prefix-code)))
-
-(defun vi-more-redo-insertion (str &optional overwrite-p prefix-code)
- "Redo more insertion : copy string from STR to point, use overwrite mode
-if overwrite-p is T; apply prefix-code first if it's non-nil."
- (if prefix-code (apply (car prefix-code) (cdr prefix-code)))
- (if overwrite-p (delete-region (point) (+ (point) (length str))))
- (insert str))
-
-(defun vi-goto-command-state (&optional from-insert-state-p)
- "Go to vi-mode command state. If optional arg exists, means return from
-insert state."
- (use-local-map vi-com-map)
- (setq vi-insert-state nil)
- (if from-insert-state-p
- (if overwrite-mode
- (overwrite-mode 0)
-; (set-minor-mode 'ins "Insert" nil)
- )))
-
-(defun vi-kill-line (arg)
- "kill specified number of lines (=d$), text saved in the kill ring."
- (interactive "*P")
- (kill-line arg)
- (vi-set-last-change-command 'kill-line arg))
-
-(defun vi-kill-region (start end)
- (interactive "*r")
- (kill-region start end)
- (vi-set-last-change-command 'kill-region))
-
-(defun vi-append-at-end-of-line (arg)
- "go to end of line and then go into vi insert state."
- (interactive "*p")
- (vi-goto-insert-state arg '(end-of-line) t))
-
-(defun vi-change-rest-of-line (arg)
- "Change the rest of (ARG) lines (= c$ in vi)."
- (interactive "*P")
- (vi-goto-insert-state 1 (list 'kill-line arg) t))
-
-(defun vi-insert-before-first-nonwhite (arg)
- "(= ^i in vi)"
- (interactive "*p")
- (vi-goto-insert-state arg '(back-to-indentation) t))
-
-(defun vi-open-above (arg)
- "open new line(s) above current line and enter insert state."
- (interactive "*p")
- (vi-goto-insert-state 1
- (list (function (lambda (x)
- (or (beginning-of-line)
- (open-line x)))) arg)
- t))
-
-(defun vi-open-below (arg)
- "open new line(s) and go into insert mode on the last line."
- (interactive "*p")
- (vi-goto-insert-state 1
- (list (function (lambda (x)
- (or (end-of-line)
- (open-line x)
- (forward-line x)))) arg)
- t))
-
-(defun vi-insert-after (arg)
- "start vi insert state after cursor."
- (interactive "*p")
- (vi-goto-insert-state arg
- (list (function (lambda ()
- (if (not (eolp)) (forward-char)))))
- t))
-
-(defun vi-insert-before (arg)
- "enter insert state before the cursor."
- (interactive "*p")
- (vi-goto-insert-state arg))
-
-(defun vi-goto-line (arg)
- "Go to ARGth line."
- (interactive "P")
- (if (null (vi-raw-numeric-prefix arg))
- (end-of-buffer)
- (goto-line (vi-prefix-numeric-value arg))))
-
-(defun vi-beginning-of-buffer ()
- "Move point to the beginning of current buffer."
- (interactive)
- (goto-char (point-min)))
-
-;;;;; not used now
-;;(defvar regexp-search t ; string
-;; "*T if search string can contain regular expressions. (= set magic in vi)")
-;;;;;
-
-(defun vi-isearch-forward (arg)
- "Incremental search forward. Use regexp version if ARG is non-nil."
- (interactive "P")
- (let ((scmd (if arg 'isearch-forward-regexp 'isearch-forward))
- (opoint (point)))
- (call-interactively scmd)
- (if (= opoint (point))
- nil
- (setq vi-search-last-command (if arg 're-search-forward 'search-forward)))))
-
-(defun vi-isearch-backward (arg)
- "Incremental search backward. Use regexp version if ARG is non-nil."
- (interactive "P")
- (let ((scmd (if arg 'isearch-backward-regexp 'isearch-backward))
- (opoint (point)))
- (call-interactively scmd)
- (if (= opoint (point))
- nil
- (setq vi-search-last-command (if arg 're-search-backward 'search-backward)))))
-
-(defun vi-search-forward (arg string)
- "Nonincremental search forward. Use regexp version if ARG is non-nil."
- (interactive (if current-prefix-arg
- (list t (read-string "regexp/" nil))
- (list nil (read-string "/" nil))))
- (setq vi-search-last-command (if arg 're-search-forward 'search-forward))
- (if (> (length string) 0) (setq search-last-string string))
- (funcall vi-search-last-command search-last-string nil nil 1))
-
-(defun vi-search-backward (arg string)
- "Nonincremental search backward. Use regexp version if ARG is non-nil."
- (interactive (if current-prefix-arg
- (list t (read-string "regexp?" nil))
- (list nil (read-string "?" nil))))
- (setq vi-search-last-command (if arg 're-search-backward 'search-backward))
- (if (> (length string) 0) (setq search-last-string string))
- (funcall vi-search-last-command search-last-string nil nil 1))
-
-(defun vi-repeat-last-search (arg &optional search-command search-string)
- "Repeat last search command. If optional search-command/string are given,
-use those instead of the ones saved."
- (interactive "p")
- (if (null search-command) (setq search-command vi-search-last-command))
- (if (null search-string) (setq search-string search-last-string))
- (if (null search-command)
- (message "No last search command to repeat." (ding))
- (funcall search-command search-string nil nil arg)))
-
-(defun vi-reverse-last-search (arg &optional search-command search-string)
- "Redo last search command in reverse direction. If the optional search args
-are given, use those instead of the ones saved."
- (interactive "p")
- (if (null search-command) (setq search-command vi-search-last-command))
- (if (null search-string) (setq search-string search-last-string))
- (if (null search-command)
- (message "No last search command to repeat." (ding))
- (funcall (cond ((eq search-command 're-search-forward) 're-search-backward)
- ((eq search-command 're-search-backward) 're-search-forward)
- ((eq search-command 'search-forward) 'search-backward)
- ((eq search-command 'search-backward) 'search-forward))
- search-string nil nil arg)))
-
-(defun vi-join-lines (arg)
- "join ARG lines from current line (default 2), cleaning up white space."
- (interactive "P")
- (if (null (vi-raw-numeric-prefix arg))
- (delete-indentation t)
- (setq count (vi-prefix-numeric-value arg))
- (while (>= count 2)
- (delete-indentation t)
- (setq count (1- count))))
- (vi-set-last-change-command 'vi-join-lines arg))
-
-(defun vi-backward-kill-line ()
- "kill the current line. Only works in insert state."
- (interactive)
- (if (not vi-insert-state)
- nil
- (beginning-of-line 1)
- (kill-line nil)))
-
-(defun vi-abort-ins ()
- "abort insert state, kill inserted text and go back to command state."
- (interactive)
- (if (not vi-insert-state)
- nil
- (if (> (point) vi-ins-point)
- (kill-region vi-ins-point (point)))
- (vi-goto-command-state t)))
-
-(defun vi-backward-windowful (count)
- "Backward COUNT windowfuls. Default is one."
- (interactive "p")
-; (set-mark-command nil)
- (while (> count 0)
- (scroll-down nil)
- (setq count (1- count))))
-
-(defun vi-scroll-down-window (count)
- "Scrolls down window COUNT lines.
-If COUNT is nil (actually, non-integer), scrolls default amount.
-The given COUNT is remembered for future scrollings."
- (interactive "P")
- (if (integerp count)
- (setq vi-scroll-amount count))
- (scroll-up vi-scroll-amount))
-
-(defun vi-expose-line-below (count)
- "Expose COUNT more lines below the current window. Default COUNT is 1."
- (interactive "p")
- (scroll-up count))
-
-(defun vi-forward-windowful (count)
- "Forward COUNT windowfuls. Default is one."
- (interactive "p")
-; (set-mark-command nil)
- (while (> count 0)
- (scroll-up nil)
- (setq count (1- count))))
-
-(defun vi-next-line (count)
- "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)))
- (ding) ; no moving, already at end of buffer
- (setq last-command 'next-line)))
-
-(defun vi-next-line-first-nonwhite (count)
- "Go down COUNT lines. Stop at first non-white."
- (interactive "p")
- (if (= (point) (progn (forward-line count) (back-to-indentation) (point)))
- (ding))) ; no moving, already at end of buffer
-
-(defun vi-previous-line-first-nonwhite (count)
- "Go up COUNT lines. Stop at first non-white."
- (interactive "p")
- (previous-line count)
- (back-to-indentation))
-
-(defun vi-scroll-up-window (count)
- "Scrolls up window COUNT lines.
-If COUNT is nil (actually, non-integer), scrolls default amount.
-The given COUNT is remembered for future scrollings."
- (interactive "P")
- (if (integerp count)
- (setq vi-scroll-amount count))
- (scroll-down vi-scroll-amount))
-
-(defun vi-expose-line-above (count)
- "Expose COUNT more lines above the current window. Default COUNT is 1."
- (interactive "p")
- (scroll-down count))
-
-(defun vi-char-argument (arg)
- "Get following character (could be any CHAR) as part of the prefix argument.
-Possible prefix-arg cases are NIL, INTEGER, (NIL . CHAR) or (INTEGER . CHAR)."
- (interactive "P")
- (let ((char (read-char)))
- (cond ((null arg) (setq prefix-arg (cons nil char)))
- ((integerp arg) (setq prefix-arg (cons arg char)))
- ; This can happen only if the user changed his/her mind for CHAR,
- ; Or there are some leading "universal-argument"s
- (t (setq prefix-arg (cons (car arg) char))))))
-
-(defun vi-goto-mark (mark-char &optional line-flag)
- "Go to marked position or line (if line-flag is given).
-Goto mark '@' means jump into and pop the top mark on the mark ring."
- (cond ((char-equal mark-char last-command-char) ; `` or ''
- (exchange-point-and-mark) (if line-flag (back-to-indentation)))
- ((char-equal mark-char ?@) ; jump and pop mark
- (set-mark-command t) (if line-flag (back-to-indentation)))
- (t
- (let ((mark (vi-get-mark mark-char)))
- (if (null mark)
- (message "Mark register undefined." (vi-ding))
- (set-mark-command nil)
- (goto-char mark)
- (if line-flag (back-to-indentation)))))))
-
-(defun vi-goto-line-mark (char)
- "Go to the line (at first non-white) marked by next char."
- (interactive "c")
- (vi-goto-mark char t))
-
-(defun vi-goto-char-mark (char)
- "Go to the char position marked by next mark-char."
- (interactive "c")
- (vi-goto-mark char))
-
-(defun vi-digit-argument (arg)
- "Set numeric prefix argument."
- (interactive "P")
- (cond ((null arg) (digit-argument arg))
- ((integerp arg) (digit-argument nil)
- (setq prefix-arg (* prefix-arg arg)))
- (t (digit-argument nil) ; in (NIL . CHAR) or (NUM . CHAR) form
- (setq prefix-arg (cons (* prefix-arg
- (if (null (car arg)) 1 (car arg)))
- (cdr arg))))))
-
-(defun vi-raw-numeric-prefix (arg)
- "Return the raw value of numeric part prefix argument."
- (if (consp arg) (car arg) arg))
-
-(defun vi-prefix-numeric-value (arg)
- "Return numeric meaning of the raw prefix argument. This is a modification
-to the standard one provided in `callint.c' to handle (_ . CHAR) cases."
- (cond ((null arg) 1)
- ((integerp arg) arg)
- ((consp arg) (if (car arg) (car arg) 1))))
-
-(defun vi-reverse-last-find-char (count &optional find-arg)
- "Reverse last f F t T operation COUNT times. If the optional FIND-ARG
-is given, it is used instead of the saved one."
- (interactive "p")
- (if (null find-arg) (setq find-arg vi-last-find-char))
- (if (null find-arg)
- (message "No last find char to repeat." (ding))
- (vi-find-char (cons (* (car find-arg) -1) (cdr find-arg)) count))) ;6/13/86
-
-(defun vi-find-char (arg count)
- "Find in DIRECTION (1/-1) for CHAR of COUNT'th times on current line.
-If UPTO-FLAG is T, stop before the char. ARG = (DIRECTION.CHAR.UPTO-FLAG."
- (let* ((direction (car arg)) (char (car (cdr arg)))
- (upto-flag (cdr (cdr arg))) (pos (+ (point) direction)))
- (if (catch 'exit-find-char
- (while t
- (cond ((null (char-after pos)) (throw 'exit-find-char nil))
- ((char-equal (char-after pos) ?\n) (throw 'exit-find-char nil))
- ((char-equal char (char-after pos)) (setq count (1- count))
- (if (= count 0)
- (throw 'exit-find-char
- (if upto-flag
- (setq pos (- pos direction))
- pos)))))
- (setq pos (+ pos direction))))
- (goto-char pos)
- (ding))))
-
-(defun vi-repeat-last-find-char (count &optional find-arg)
- "Repeat last f F t T operation COUNT times. If optional FIND-ARG is given,
-it is used instead of the saved one."
- (interactive "p")
- (if (null find-arg) (setq find-arg vi-last-find-char))
- (if (null find-arg)
- (message "No last find char to repeat." (ding))
- (vi-find-char find-arg count)))
-
-(defun vi-backward-find-char (count char)
- "Find the COUNT'th CHAR backward on current line."
- (interactive "p\nc")
- (setq vi-last-find-char (cons -1 (cons char nil)))
- (vi-repeat-last-find-char count))
-
-(defun vi-forward-find-char (count char)
- "Find the COUNT'th CHAR forward on current line."
- (interactive "p\nc")
- (setq vi-last-find-char (cons 1 (cons char nil)))
- (vi-repeat-last-find-char count))
-
-(defun vi-backward-upto-char (count char)
- "Find upto the COUNT'th CHAR backward on current line."
- (interactive "p\nc")
- (setq vi-last-find-char (cons -1 (cons char t)))
- (vi-repeat-last-find-char count))
-
-(defun vi-forward-upto-char (count char)
- "Find upto the COUNT'th CHAR forward on current line."
- (interactive "p\nc")
- (setq vi-last-find-char (cons 1 (cons char t)))
- (vi-repeat-last-find-char count))
-
-(defun vi-end-of-word (count)
- "Move forward until encountering the end of a word.
-With argument, do this that many times."
- (interactive "p")
- (if (not (eobp)) (forward-char))
- (if (re-search-forward "\\W*\\w+\\>" nil t count)
- (backward-char)))
-
-(defun vi-replace-1-char (count char)
- "Replace char after point by CHAR. Repeat COUNT times."
- (interactive "p\nc")
- (delete-char count nil) ; don't save in kill ring
- (setq last-command-char char)
- (self-insert-command count)
- (vi-set-last-change-command 'vi-replace-1-char count char))
-
-(defun vi-replace-chars (arg)
- "Replace chars over old ones."
- (interactive "*p")
- (overwrite-mode 1)
- (vi-goto-insert-state arg))
-
-(defun vi-substitute-chars (count)
- "Substitute COUNT chars by the input chars, enter insert state."
- (interactive "*p")
- (vi-goto-insert-state 1 (list (function (lambda (c) ; this is a bit tricky
- (delete-region (point)
- (+ (point) c))))
- count) t))
-
-(defun vi-substitute-lines (count)
- "Substitute COUNT lines by the input chars. (=cc in vi)"
- (interactive "*p")
- (vi-goto-insert-state 1 (list 'vi-delete-op 'next-line (1- count)) t))
-
-(defun vi-prefix-char-value (arg)
- "Get the char part of the current prefix argument."
- (cond ((null arg) nil)
- ((integerp arg) nil)
- ((consp arg) (cdr arg))
- (t nil)))
-
-(defun vi-operator (arg)
- "Handling vi operators (d/c/</>/!/=/y). Current implementation requires
-the key bindings of the operators being fixed."
- (interactive "P")
- (catch 'vi-exit-op
- (let ((this-op-char last-command-char))
- (setq last-command-char (read-char))
- (setq this-command (lookup-key vi-com-map (char-to-string last-command-char)))
- (if (not (eq this-command 'vi-digit-argument))
- (setq prefix-arg arg)
- (vi-digit-argument arg)
- (setq last-command-char (read-char))
- (setq this-command (lookup-key vi-com-map (char-to-string last-command-char))))
- (cond ((char-equal this-op-char last-command-char) ; line op
- (vi-execute-op this-op-char 'next-line
- (cons (1- (vi-prefix-numeric-value prefix-arg))
- (vi-prefix-char-value prefix-arg))))
- ;; We assume any command that has no property 'point-moving-unit'
- ;; as having that property with the value 'CHAR'. 3/12/86
- (t ;; (get this-command 'point-moving-unit)
- (vi-execute-op this-op-char this-command prefix-arg))))))
- ;; (t (throw 'vi-exit-op (ding)))))))
-
-(defun vi-execute-op (op-char motion-command arg)
- "Execute vi edit operator as specified by OP-CHAR, the operand is the region
-determined by the MOTION-COMMAND with ARG."
- (cond ((= op-char ?d)
- (if (vi-delete-op motion-command arg)
- (vi-set-last-change-command 'vi-delete-op (vi-repeat-command-of motion-command) arg)))
- ((= op-char ?c)
- (if (vi-delete-op motion-command arg)
- (vi-goto-insert-state 1 (list 'vi-delete-op
- (vi-repeat-command-of motion-command) arg) nil)))
- ((= op-char ?y)
- (if (vi-yank-op motion-command arg)
- (vi-set-last-change-command 'vi-yank-op (vi-repeat-command-of motion-command) arg)))
- ((= op-char ?!)
- (if (vi-shell-op motion-command arg)
- (vi-set-last-change-command 'vi-shell-op (vi-repeat-command-of motion-command) arg vi-last-shell-command)))
- ((= op-char ?<)
- (if (vi-shift-op motion-command arg (- vi-shift-width))
- (vi-set-last-change-command 'vi-shift-op (vi-repeat-command-of motion-command) arg (- vi-shift-width))))
- ((= op-char ?>)
- (if (vi-shift-op motion-command arg vi-shift-width)
- (vi-set-last-change-command 'vi-shift-op (vi-repeat-command-of motion-command) arg vi-shift-width)))
- ((= op-char ?=)
- (if (vi-indent-op motion-command arg)
- (vi-set-last-change-command 'vi-indent-op (vi-repeat-command-of motion-command) arg)))
- ((= op-char ?\\)
- (vi-narrow-op motion-command arg))))
-
-(defun vi-repeat-command-of (command)
- "Return the command for redo the given command."
- (let ((cmd-type (get command 'point-moving-unit)))
- (cond ((eq cmd-type 'search) 'vi-repeat-last-search)
- ((eq cmd-type 'find) 'vi-repeat-last-find-char)
- (t command))))
-
-(defun vi-effective-range (motion-command arg)
- "Return (begin . end) of the range spanned by executing the given
-MOTION-COMMAND with ARG.
- MOTION-COMMAND in ready-to-eval list form is not yet supported."
- (save-excursion
- (let ((begin (point)) end opoint
- (moving-unit (get motion-command 'point-moving-unit)))
- (setq prefix-arg arg)
- (setq opoint (point))
- (command-execute motion-command nil)
-;; Check if there is any effective motion. Note that for single line operation
-;; the motion-command causes no effective point movement (since it moves up or
-;; down zero lines), but it should be counted as effectively moved.
- (if (and (= (point) opoint) (not (eq moving-unit 'line)))
- (cons opoint opoint) ; no effective motion
- (if (eq moving-unit 'region)
- (setq begin (or (mark) (point))))
- (if (<= begin (point))
- (setq end (point))
- (setq end begin)
- (setq begin (point)))
- (cond ((or (eq moving-unit 'match) (eq moving-unit 'find))
- (setq end (1+ end)))
- ((eq moving-unit 'line)
- (goto-char begin) (beginning-of-line) (setq begin (point))
- (goto-char end) (next-line 1) (beginning-of-line) (setq end (point))))
- (if (> end (point-max)) (setq end (point-max))) ; force in buffer region
- (cons begin end)))))
-
-(defun vi-delete-op (motion-command arg)
- "Delete range specified by MOTION-COMMAND with ARG."
- (let* ((range (vi-effective-range motion-command arg))
- (begin (car range)) (end (cdr range)) reg)
- (if (= begin end)
- nil ; point not moved, abort op
- (setq reg (vi-prefix-char-value arg))
- (if (null reg)
- (kill-region begin end) ; kill ring as unnamed registers
- (if (and (>= reg ?A) (<= reg ?Z))
- (append-to-register (downcase reg) begin end t)
- (copy-to-register reg begin end t)))
- t)))
-
-(defun vi-yank-op (motion-command arg)
- "Yank (in vi sense) range specified by MOTION-COMMAND with ARG."
- (let* ((range (vi-effective-range motion-command arg))
- (begin (car range)) (end (cdr range)) reg)
- (if (= begin end)
- nil ; point not moved, abort op
- (setq reg (vi-prefix-char-value arg))
- (if (null reg)
- (copy-region-as-kill begin end); kill ring as unnamed registers
- (if (and (>= reg ?A) (<= reg ?Z))
- (append-to-register (downcase reg) begin end nil)
- (copy-to-register reg begin end nil)))
- t)))
-
-(defun vi-yank-line (arg)
- "Yank (in vi sense) lines (= `yy' command)."
- (interactive "*P")
- (setq arg (cons (1- (vi-prefix-numeric-value arg)) (vi-prefix-char-value arg)))
- (if (vi-yank-op 'next-line arg)
- (vi-set-last-change-command 'vi-yank-op 'next-line arg)))
-
-(defun vi-string-end-with-nl-p (string)
- "See if STRING ends with a newline char.
-Used in checking whether the yanked text should be put back as lines or not."
- (= (aref string (1- (length string))) ?\n))
-
-(defun vi-put-before (arg &optional after-p)
- "Put yanked (in vi sense) text back before/above cursor.
-If a numeric prefix value (currently it should be >1) is given, put back
-text as lines. If the optional after-p is given, put after/below the cursor."
- (interactive "P")
- (let ((reg (vi-prefix-char-value arg)) put-text)
- (if (and reg (or (< reg ?1) (> reg ?9)) (null (get-register reg)))
- (error "Nothing in register %c" reg)
- (if (null reg) (setq reg ?1)) ; the default is the last text killed
- (setq put-text
- (cond
- ((and (>= reg ?1) (<= reg ?9))
- (setq this-command 'yank) ; So we may yank-pop !!
- (current-kill (- reg ?0 1) 'do-not-rotate))
- ((stringp (get-register reg)) (get-register reg))
- (t (error "Register %c is not containing text string" reg))))
- (if (vi-string-end-with-nl-p put-text) ; put back text as lines
- (if after-p
- (progn (next-line 1) (beginning-of-line))
- (beginning-of-line))
- (if after-p (forward-char 1)))
- (push-mark (point))
- (insert put-text)
- (exchange-point-and-mark)
-;; (back-to-indentation) ; this is not allowed if we allow yank-pop
- (vi-set-last-change-command 'vi-put-before arg after-p))))
-
-(defun vi-put-after (arg)
- "Put yanked (in vi sense) text back after/below cursor."
- (interactive "P")
- (vi-put-before arg t))
-
-(defun vi-shell-op (motion-command arg &optional shell-command)
- "Perform shell command (as filter).
-Performs command on range specified by MOTION-COMMAND
-with ARG. If SHELL-COMMAND is not given, ask for one from minibuffer.
-If char argument is given, it directs the output to a *temp* buffer."
- (let* ((range (vi-effective-range motion-command arg))
- (begin (car range)) (end (cdr range)))
- (if (= begin end)
- nil ; point not moved, abort op
- (cond ((null shell-command)
- (setq shell-command (read-string "!" nil))
- (setq vi-last-shell-command shell-command)))
- (shell-command-on-region begin end shell-command (not (vi-prefix-char-value arg)))
- t)))
-
-(defun vi-shift-op (motion-command arg amount)
- "Perform shift command on range specified by MOTION-COMMAND with ARG for
-AMOUNT on each line. Negative amount means shift left.
-SPECIAL FEATURE: char argument can be used to specify shift amount(1-9)."
- (let* ((range (vi-effective-range motion-command arg))
- (begin (car range)) (end (cdr range)))
- (if (= begin end)
- nil ; point not moved, abort op
- (if (vi-prefix-char-value arg)
- (setq amount (if (> amount 0)
- (- (vi-prefix-char-value arg) ?0)
- (- ?0 (vi-prefix-char-value arg)))))
- (indent-rigidly begin end amount)
- t)))
-
-(defun vi-indent-op (motion-command arg)
- "Perform indent command on range specified by MOTION-COMMAND with ARG."
- (let* ((range (vi-effective-range motion-command arg))
- (begin (car range)) (end (cdr range)))
- (if (= begin end)
- nil ; point not moved, abort op
- (indent-region begin end nil) ; insert TAB as indent command
- t)))
-
-(defun vi-narrow-op (motion-command arg)
- "Narrow to region specified by MOTION-COMMAND with ARG."
- (let* ((range (vi-effective-range motion-command arg))
- (begin (car range)) (end (cdr range)) reg)
- (if (= begin end)
- nil ; point not moved, abort op
- (narrow-to-region begin end))))
-
-(defun vi-get-mark (char)
- "Return contents of vi mark register named CHAR, or nil if undefined."
- (cdr (assq char vi-mark-alist)))
-
-(defun vi-set-mark (char)
- "Set contents of vi mark register named CHAR to current point.
-'@' is the special anonymous mark register."
- (interactive "c")
- (if (char-equal char ?@)
- (set-mark-command nil)
- (let ((aelt (assq char vi-mark-alist)))
- (if aelt
- (move-marker (cdr aelt) (point)) ; fixed 6/12/86
- (setq aelt (cons char (copy-marker (point))))
- (setq vi-mark-alist (cons aelt vi-mark-alist))))))
-
-(defun vi-find-matching-paren ()
- "Locate the matching paren. It's a hack right now."
- (interactive)
- (cond ((looking-at "[[({]") (forward-sexp 1) (backward-char 1))
- ((looking-at "[])}]") (forward-char 1) (backward-sexp 1))
- (t (ding))))
-
-(defun vi-backward-blank-delimited-word (count)
- "Backward COUNT blank-delimited words."
- (interactive "p")
- (if (re-search-backward "[ \t\n\`][^ \t\n\`]+" nil t count)
- (if (not (bobp)) (forward-char 1))))
-
-(defun vi-forward-blank-delimited-word (count)
- "Forward COUNT blank-delimited words."
- (interactive "p")
- (if (re-search-forward "[^ \t\n]*[ \t\n]+[^ \t\n]" nil t count)
- (if (not (eobp)) (backward-char 1))))
-
-(defun vi-end-of-blank-delimited-word (count)
- "Forward to the end of the COUNT'th blank-delimited word."
- (interactive "p")
- (if (re-search-forward "[^ \t\n\']+[ \t\n\']" nil t count)
- (if (not (eobp)) (backward-char 2))))
-
-(defun vi-home-window-line (arg)
- "To window home or arg'th line from the top of the window."
- (interactive "p")
- (move-to-window-line (1- arg))
- (back-to-indentation))
-
-(defun vi-last-window-line (arg)
- "To window last line or arg'th line from the bottom of the window."
- (interactive "p")
- (move-to-window-line (- arg))
- (back-to-indentation))
-
-(defun vi-middle-window-line ()
- "To the middle line of the window."
- (interactive)
- (move-to-window-line nil)
- (back-to-indentation))
-
-(defun vi-forward-word (count)
- "Stop at the beginning of the COUNT'th words from point."
- (interactive "p")
- (if (re-search-forward "\\w*\\W+\\<" nil t count)
- t
- (vi-ding)))
-
-(defun vi-set-last-change-command (fun &rest args)
- "Set (FUN . ARGS) as the `last-change-command'."
- (setq vi-last-change-command (cons fun args)))
-
-(defun vi-redo-last-change-command (count &optional command)
- "Redo last change command COUNT times. If the optional COMMAND is given,
-it is used instead of the current `last-change-command'."
- (interactive "p")
- (if (null command)
- (setq command vi-last-change-command))
- (if (null command)
- (message "No last change command available.")
- (while (> count 0)
- (apply (car command) (cdr command))
- (setq count (1- count)))))
-
-(defun vi-kill-char (count)
- "Kill COUNT chars from current point."
- (interactive "*p")
- (delete-char count t) ; save in kill ring
- (vi-set-last-change-command 'delete-char count t))
-
-(defun vi-transpose-objects (arg unit)
- "Transpose objects.
-The following char specifies unit of objects to be
-transposed -- \"c\" for chars, \"l\" for lines, \"w\" for words, \"s\" for
- sexp, \"p\" for paragraph.
-For the use of the prefix-arg, refer to individual functions called."
- (interactive "*P\nc")
- (if (char-equal unit ??)
- (progn
- (message "Transpose: c(har), l(ine), p(aragraph), s(-exp), w(ord),")
- (setq unit (read-char))))
- (vi-set-last-change-command 'vi-transpose-objects arg unit)
- (cond ((char-equal unit ?c) (transpose-chars arg))
- ((char-equal unit ?l) (transpose-lines (vi-prefix-numeric-value arg)))
- ((char-equal unit ?p) (transpose-paragraphs (vi-prefix-numeric-value arg)))
- ((char-equal unit ?s) (transpose-sexps (vi-prefix-numeric-value arg)))
- ((char-equal unit ?w) (transpose-words (vi-prefix-numeric-value arg)))
- (t (vi-transpose-objects arg ??))))
-
-(defun vi-query-replace (arg)
- "Query replace, use regexp version if ARG is non-nil."
- (interactive "*P")
- (let ((rcmd (if arg 'query-replace-regexp 'query-replace)))
- (call-interactively rcmd nil)))
-
-(defun vi-replace (arg)
- "Replace strings, use regexp version if ARG is non-nil."
- (interactive "*P")
- (let ((rcmd (if arg 'replace-regexp 'replace-string)))
- (call-interactively rcmd nil)))
-
-(defun vi-adjust-window (arg position)
- "Move current line to the top/center/bottom of the window."
- (interactive "p\nc")
- (cond ((char-equal position ?\r) (recenter 0))
- ((char-equal position ?-) (recenter -1))
- ((char-equal position ?.) (recenter (/ (window-height) 2)))
- (t (message "Move current line to: \\r(top) -(bottom) .(middle)")
- (setq position (read-char))
- (vi-adjust-window arg position))))
-
-(defun vi-goto-column (col)
- "Go to given column of the current line."
- (interactive "p")
- (let ((opoint (point)))
- (beginning-of-line)
- (while (> col 1)
- (if (eolp)
- (setq col 0)
- (forward-char 1)
- (setq col (1- col))))
- (if (= col 1)
- t
- (goto-char opoint)
- (ding))))
-
-(defun vi-name-last-change-or-macro (arg char)
- "Give name to the last change command or just defined kbd macro.
-If prefix ARG is given, name last macro, otherwise name last change command.
-The following CHAR will be the name for the command or macro."
- (interactive "P\nc")
- (if arg
- (name-last-kbd-macro (intern (char-to-string char)))
- (if (eq (car vi-last-change-command) 'vi-first-redo-insertion)
- (let* ((args (cdr vi-last-change-command)) ; save the insertion text
- (str (buffer-substring (nth 0 args) (nth 1 args)))
- (overwrite-p (nth 2 args))
- (prefix-code (nth 3 args)))
- (vi-set-last-change-command 'vi-more-redo-insertion str
- overwrite-p prefix-code)))
- (fset (intern (char-to-string char)) vi-last-change-command)))
-
-(defun vi-call-named-change-or-macro (count char)
- "Execute COUNT times the keyboard macro definition named by the following CHAR."
- (interactive "p\nc")
- (if (stringp (symbol-function (intern (char-to-string char))))
- (execute-kbd-macro (intern (char-to-string char)) count)
- (vi-redo-last-change-command count (symbol-function (intern (char-to-string char))))))
-
-(defun vi-change-case (arg) ; could be made as an operator ?
- "Change the case of the char after point."
- (interactive "*p")
- (catch 'exit
- (if (looking-at "[a-z]")
- (upcase-region (point) (+ (point) arg))
- (if (looking-at "[A-Z]")
- (downcase-region (point) (+ (point) arg))
- (ding)
- (throw 'exit nil)))
- (vi-set-last-change-command 'vi-change-case arg) ;should avoid redundant save
- (forward-char arg)))
-
-(defun vi-ask-for-info (char)
- "Inquire status info. The next CHAR will specify the particular info requested."
- (interactive "c")
- (cond ((char-equal char ?l) (what-line))
- ((char-equal char ?c) (what-cursor-position))
- ((char-equal char ?p) (what-page))
- (t (message "Ask for: l(ine number), c(ursor position), p(age number)")
- (setq char (read-char))
- (vi-ask-for-info char))))
-
-(defun vi-mark-region (arg region)
- "Mark region appropriately. The next char REGION is d(efun),s(-exp),b(uffer),
-p(aragraph), P(age), f(unction in C/Pascal etc.), w(ord), e(nd of sentence),
-l(ines)."
- (interactive "p\nc")
- (cond ((char-equal region ?d) (mark-defun))
- ((char-equal region ?s) (mark-sexp arg))
- ((char-equal region ?b) (mark-whole-buffer))
- ((char-equal region ?p) (mark-paragraph))
- ((char-equal region ?P) (mark-page arg))
- ((char-equal region ?f) (mark-c-function))
- ((char-equal region ?w) (mark-word arg))
- ((char-equal region ?e) (mark-end-of-sentence arg))
- ((char-equal region ?l) (vi-mark-lines arg))
- (t (message "Mark: d(efun),s(-exp),b(uf),p(arag),P(age),f(unct),w(ord),e(os),l(ines)")
- (setq region (read-char))
- (vi-mark-region arg region))))
-
-(defun vi-mark-lines (num)
- "Mark NUM of lines from current line as current region."
- (beginning-of-line 1)
- (push-mark)
- (end-of-line num))
-
-(defun vi-verify-spelling (arg unit)
- "Verify spelling for the objects specified by char UNIT : [b(uffer),
-r(egion), s(tring), w(ord) ]."
- (interactive "P\nc")
- (setq prefix-arg arg) ; seems not needed
- (cond ((char-equal unit ?b) (call-interactively 'spell-buffer))
- ((char-equal unit ?r) (call-interactively 'spell-region))
- ((char-equal unit ?s) (call-interactively 'spell-string))
- ((char-equal unit ?w) (call-interactively 'spell-word))
- (t (message "Spell check: b(uffer), r(egion), s(tring), w(ord)")
- (setq unit (read-char))
- (vi-verify-spelling arg unit))))
-
-(defun vi-do-old-mode-C-c-command (arg)
- "This is a hack for accessing mode specific C-c commands in vi-mode."
- (interactive "P")
- (let ((cmd (lookup-key vi-mode-old-local-map
- (concat "\C-c" (char-to-string (read-char))))))
- (if (catch 'exit-vi-mode ; kludge hack due to dynamic binding
- ; of case-fold-search
- (if (null cmd)
- (progn (ding) nil)
- (let ((case-fold-search vi-mode-old-case-fold)) ; a hack
- (setq prefix-arg arg)
- (command-execute cmd nil)
- nil)))
- (progn
- (vi-back-to-old-mode)
- (setq prefix-arg arg)
- (command-execute cmd nil)))))
-
-(defun vi-quote-words (arg char)
- "Quote ARG words from the word point is on with pattern specified by CHAR.
-Currently, CHAR could be [,{,(,\",',`,<,*, etc."
- (interactive "*p\nc")
- (while (not (string-match "[[({<\"'`*]" (char-to-string char)))
- (message "Enter any of [,{,(,<,\",',`,* as quoting character.")
- (setq char (read-char)))
- (vi-set-last-change-command 'vi-quote-words arg char)
- (if (not (looking-at "\\<")) (forward-word -1))
- (insert char)
- (cond ((char-equal char ?[) (setq char ?]))
- ((char-equal char ?{) (setq char ?}))
- ((char-equal char ?<) (setq char ?>))
- ((char-equal char ?() (setq char ?)))
- ((char-equal char ?`) (setq char ?')))
- (vi-end-of-word arg)
- (forward-char 1)
- (insert char))
-
-(defun vi-locate-def ()
- "Locate definition in current file for the name before the point.
-It assumes a `(def..' always starts at the beginning of a line."
- (interactive)
- (let (name)
- (save-excursion
- (setq name (buffer-substring (progn (vi-backward-blank-delimited-word 1)
- (skip-chars-forward "^a-zA-Z")
- (point))
- (progn (vi-end-of-blank-delimited-word 1)
- (forward-char)
- (skip-chars-backward "^a-zA-Z")
- (point)))))
- (set-mark-command nil)
- (goto-char (point-min))
- (if (re-search-forward (concat "^(def[unvarconst ]*" name) nil t)
- nil
- (message "No definition for \"%s\" in current file." name (ding))
- (set-mark-command t))))
-
-(defun vi-split-open-line (arg)
- "Insert a newline and leave point before it.
-With ARG, inserts that many newlines."
- (interactive "*p")
- (vi-goto-insert-state 1
- (list (function (lambda (arg)
- (let ((flag (and (bolp) (not (bobp)))))
- (if flag (forward-char -1))
- (while (> arg 0)
- (save-excursion
- (insert ?\n)
- (if fill-prefix (insert fill-prefix)))
- (setq arg (1- arg)))
- (if flag (forward-char 1))))) arg)
- t))
-
-;;; vi.el ends here
diff --git a/lisp/emulation/vip.el b/lisp/emulation/vip.el
deleted file mode 100644
index a8739f2350b..00000000000
--- a/lisp/emulation/vip.el
+++ /dev/null
@@ -1,3045 +0,0 @@
-;;; vip.el --- a VI Package for GNU Emacs
-
-;; Author: Masahiko Sato <ms@sail.stanford.edu>
-;; Version: 3.5
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; A full-featured vi(1) emulator.
-;;
-;; In Japan, the author's address is: masahiko@sato.riec.tohoku.junet
-;;
-;; Send suggestions and bug reports to one of the above addresses.
-;; When you report a bug, be sure to include the version number of VIP and
-;; Emacs you are using.
-
-;; Execute info command by typing "M-x info" to get information on VIP.
-
-;;; Code:
-
-;; external variables
-
-(defvar vip-emacs-local-map nil
- "Local map used in emacs mode. (Buffer-specific.)")
-
-(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-insert-local-map)
-
-(defvar vip-insert-point nil
- "Remember insert point as a marker. (Buffer-specific.)")
-
-(set-default 'vip-insert-point (make-marker))
-(make-variable-buffer-local 'vip-insert-point)
-
-(defvar vip-com-point nil
- "Remember com point as a marker. (Buffer-specific.)")
-
-(set-default 'vip-com-point (make-marker))
-(make-variable-buffer-local 'vip-com-point)
-
-(defvar vip-current-mode nil
- "Current mode. One of `emacs-mode', `vi-mode', `insert-mode'.")
-
-(make-variable-buffer-local 'vip-current-mode)
-(setq-default vip-current-mode 'emacs-mode)
-
-(defvar vip-emacs-mode-line-buffer-identification nil
- "Value of mode-line-buffer-identification in Emacs mode within vip.")
-(make-variable-buffer-local 'vip-emacs-mode-line-buffer-identification)
-(setq-default vip-emacs-mode-line-buffer-identification
- '("Emacs: %17b"))
-
-(defvar vip-current-major-mode nil
- "vip-current-major-mode is the major-mode vi considers it is now.
-\(buffer specific\)")
-
-(make-variable-buffer-local 'vip-current-major-mode)
-
-(defvar vip-last-shell-com nil
- "Last shell command executed by ! command.")
-
-(defvar vip-use-register nil
- "Name of register to store deleted or yanked strings.")
-
-(defvar vip-d-com nil
- "How to reexecute last destructive command. Value is list (M-COM VAL COM).")
-
-(defconst vip-shift-width 8
- "*The number of columns shifted by > and < command.")
-
-(defconst vip-re-replace nil
- "*If t then do regexp replace, if nil then do string replace.")
-
-(defvar vip-d-char nil
- "The character remembered by the vi \"r\" command.")
-
-(defvar vip-f-char nil
- "For use by \";\" command.")
-
-(defvar vip-F-char nil
- "For use by \".\" command.")
-
-(defvar vip-f-forward nil
- "For use by \";\" command.")
-
-(defvar vip-f-offset nil
- "For use by \";\" command.")
-
-(defconst vip-search-wrap-around t
- "*if t, search wraps around.")
-
-(defconst vip-re-search nil
- "*if t, search is reg-exp search, otherwise vanilla search.")
-
-(defvar vip-s-string nil
- "Last vip search string.")
-
-(defvar vip-s-forward nil
- "If t, search is forward.")
-
-(defconst vip-case-fold-search nil
- "*If t, search ignores cases.")
-
-(defconst vip-re-query-replace nil
- "*If t then do regexp replace, if nil then do string replace.")
-
-(defconst vip-open-with-indent nil
- "*If t, indent when open a new line.")
-
-(defconst vip-help-in-insert-mode nil
- "*If t then C-h is bound to help-command in insert mode.
-If nil then it is bound to `delete-backward-char'.")
-
-(defvar vip-quote-string "> "
- "String inserted at the beginning of region.")
-
-(defvar vip-tags-file-name "TAGS")
-
-(defvar vip-inhibit-startup-message nil)
-
-(defvar vip-startup-file (convert-standard-filename "~/.vip")
- "Filename used as startup file for vip.")
-
-;; basic set up
-
-(global-set-key "\C-z" 'vip-change-mode-to-vi)
-
-(defmacro vip-loop (count body)
- "(COUNT BODY) Execute BODY COUNT times."
- (list 'let (list (list 'count count))
- (list 'while (list '> 'count 0)
- body
- (list 'setq 'count (list '1- 'count)))))
-
-(defun vip-push-mark-silent (&optional location)
- "Set mark at LOCATION (point, by default) and push old mark on mark ring.
-No message."
- (if (null (mark t))
- 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))))
-
-(defun vip-goto-col (arg)
- "Go to ARG's column."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (save-excursion
- (end-of-line)
- (if (> val (1+ (current-column))) (error "")))
- (if com (move-marker vip-com-point (point)))
- (beginning-of-line)
- (forward-char (1- val))
- (if com (vip-execute-com 'vip-goto-col val com))))
-
-(defun vip-copy-keymap (map)
- (if (null map) (make-sparse-keymap) (copy-keymap map)))
-
-
-;; changing mode
-
-(defun vip-change-mode (new-mode)
- "Change mode to NEW-MODE---either emacs-mode, vi-mode, or insert-mode."
- (or (eq new-mode vip-current-mode)
- (progn
- (cond ((eq new-mode 'vi-mode)
- (if (eq vip-current-mode 'insert-mode)
- (progn
- (vip-copy-region-as-kill (point) vip-insert-point)
- (vip-repeat-insert-command))
- (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))))
- (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)))
- (setq vip-insert-local-map (vip-copy-keymap
- vip-emacs-local-map)))
- (vip-change-mode-line "Insert")
- (use-local-map vip-insert-local-map)
- (define-key vip-insert-local-map "\e" 'vip-change-mode-to-vi)
- (define-key vip-insert-local-map "\C-z" 'vip-ESC)
- (define-key vip-insert-local-map "\C-h"
- (if vip-help-in-insert-mode 'help-command
- 'delete-backward-char))
- (define-key vip-insert-local-map "\C-w"
- 'vip-delete-backward-word))
- ((eq new-mode 'emacs-mode)
- (vip-change-mode-line "Emacs:")
- (use-local-map vip-emacs-local-map)))
- (setq vip-current-mode new-mode)
- (force-mode-line-update))))
-
-(defun vip-copy-region-as-kill (beg end)
- "If BEG and END do not belong to the same buffer, it copies empty region."
- (condition-case nil
- (copy-region-as-kill beg end)
- (error (copy-region-as-kill beg beg))))
-
-(defun vip-change-mode-line (string)
- "Assuming that the mode line format contains the string \"Emacs:\", this
-function replaces the string by \"Vi: \" etc."
- (setq mode-line-buffer-identification
- (if (string= string "Emacs:")
- vip-emacs-mode-line-buffer-identification
- (list (concat string " %17b")))))
-
-;;;###autoload
-(defun vip-mode ()
- "Turn on VIP emulation of VI."
- (interactive)
- (if (not vip-inhibit-startup-message)
- (progn
- (switch-to-buffer "VIP Startup Message")
- (erase-buffer)
- (insert
- "VIP is a Vi emulation package for GNU Emacs. VIP provides most Vi commands
-including Ex commands. VIP is however different from Vi in several points.
-You can get more information on VIP by:
- 1. Typing `M-x info' and selecting menu item \"vip\".
- 2. Typing `C-h k' followed by a key whose description you want.
- 3. Printing VIP manual which can be found as GNU/man/vip.texinfo
- 4. Printing VIP Reference Card which can be found as GNU/etc/vipcard.tex
-
-This startup message appears whenever you load VIP unless you type `y' now.
-Type `n' to quit this window for now.\n")
- (goto-char (point-min))
- (if (y-or-n-p "Inhibit VIP startup message? ")
- (progn
- (save-excursion
- (set-buffer
- (find-file-noselect
- (substitute-in-file-name vip-startup-file)))
- (goto-char (point-max))
- (insert "\n(setq vip-inhibit-startup-message t)\n")
- (save-buffer)
- (kill-buffer (current-buffer)))
- (message "VIP startup message inhibited.")
- (sit-for 2)))
- (kill-buffer (current-buffer))
- (message "")
- (setq vip-inhibit-startup-message t)))
- (vip-change-mode-to-vi))
-
-(defun vip-change-mode-to-vi ()
- "Change mode to vi mode."
- (interactive)
- (vip-change-mode 'vi-mode))
-
-(defun vip-change-mode-to-insert ()
- "Change mode to insert mode."
- (interactive)
- (vip-change-mode 'insert-mode))
-
-(defun vip-change-mode-to-emacs ()
- "Change mode to emacs mode."
- (interactive)
- (vip-change-mode 'emacs-mode))
-
-
-;; escape to emacs mode temporarily
-
-(defun vip-escape-to-emacs (arg &optional events)
- "Escape to Emacs mode for one Emacs command.
-ARG is used as the prefix value for the executed command. If
-EVENTS is a list of events, which become the beginning of the command."
- (interactive "P")
- (let (com key (old-map (current-local-map)))
- (if events (setq unread-command-events events))
- (setq prefix-arg arg)
- (use-local-map vip-emacs-local-map)
- (unwind-protect
- (setq com (key-binding (setq key (read-key-sequence nil))))
- (use-local-map old-map))
- (command-execute com prefix-arg)
- (setq prefix-arg nil) ;; reset prefix arg
- ))
-
-(defun vip-message-conditions (conditions)
- "Print CONDITIONS as a message."
- (let ((case (car conditions)) (msg (cdr conditions)))
- (if (null msg)
- (message "%s" case)
- (message "%s %s" case (prin1-to-string msg)))
- (ding)))
-
-(defun vip-ESC (arg)
- "Emulate ESC key in Emacs mode."
- (interactive "P")
- (vip-escape-to-emacs arg '(?\e)))
-
-(defun vip-ctl-c (arg)
- "Emulate C-c key in Emacs mode."
- (interactive "P")
- (vip-escape-to-emacs arg '(?\C-c)))
-
-(defun vip-ctl-x (arg)
- "Emulate C-x key in Emacs mode."
- (interactive "P")
- (vip-escape-to-emacs arg '(?\C-x)))
-
-(defun vip-ctl-h (arg)
- "Emulate C-h key in Emacs mode."
- (interactive "P")
- (vip-escape-to-emacs arg '(?\C-h)))
-
-
-;; prefix argument for vi mode
-
-;; In vi mode, prefix argument is a dotted pair (NUM . COM) where NUM
-;; represents the numeric value of the prefix argument and COM represents
-;; command prefix such as "c", "d", "m" and "y".
-
-(defun vip-prefix-arg-value (char value com)
- "Compute numeric prefix arg value. Invoked by CHAR. VALUE is the value
-obtained so far, and COM is the command part obtained so far."
- (while (and (>= char ?0) (<= char ?9))
- (setq value (+ (* (if (numberp value) value 0) 10) (- char ?0)))
- (setq char (read-char)))
- (setq prefix-arg value)
- (if com (setq prefix-arg (cons prefix-arg com)))
- (while (= char ?U)
- (vip-describe-arg prefix-arg)
- (setq char (read-char)))
- (setq unread-command-events (list char)))
-
-(defun vip-prefix-arg-com (char value com)
- "Vi operator as prefix argument."
- (let ((cont t))
- (while (and cont
- (or (= char ?c) (= char ?d) (= char ?y)
- (= char ?!) (= char ?<) (= char ?>) (= char ?=)
- (= char ?#) (= char ?r) (= char ?R) (= char ?\")))
- (if com
- ;; this means that we already have a command character, so we
- ;; construct a com list and exit while. however, if char is "
- ;; it is an error.
- (progn
- ;; new com is (CHAR . OLDCOM)
- (if (or (= char ?#) (= char ?\")) (error ""))
- (setq com (cons char com))
- (setq cont nil))
- ;; if com is nil we set com as char, and read more. again, if char
- ;; is ", we read the name of register and store it in vip-use-register.
- ;; if char is !, =, or #, a complete com is formed so we exit while.
- (cond ((or (= char ?!) (= char ?=))
- (setq com char)
- (setq char (read-char))
- (setq cont nil))
- ((= char ?#)
- ;; read a char and encode it as com
- (setq com (+ 128 (read-char)))
- (setq char (read-char))
- (setq cont nil))
- ((or (= char ?<) (= char ?>))
- (setq com char)
- (setq char (read-char))
- (if (= com char) (setq com (cons char com)))
- (setq cont nil))
- ((= char ?\")
- (let ((reg (read-char)))
- (if (or (and (<= ?A reg) (<= reg ?z))
- (and (<= ?1 reg) (<= reg ?9)))
- (setq vip-use-register reg)
- (error ""))
- (setq char (read-char))))
- (t
- (setq com char)
- (setq char (read-char)))))))
- (if (atom com)
- ;; com is a single char, so we construct prefix-arg
- ;; and if char is ?, describe prefix arg, otherwise exit by
- ;; pushing the char back
- (progn
- (setq prefix-arg (cons value com))
- (while (= char ?U)
- (vip-describe-arg prefix-arg)
- (setq char (read-char)))
- (setq unread-command-events (list char)))
- ;; as com is non-nil, this means that we have a command to execute
- (if (or (= (car com) ?r) (= (car com) ?R))
- ;; execute appropriate region command.
- (let ((char (car com)) (com (cdr com)))
- (setq prefix-arg (cons value com))
- (if (= char ?r) (vip-region prefix-arg)
- (vip-Region prefix-arg))
- ;; reset prefix-arg
- (setq prefix-arg nil))
- ;; otherwise, reset prefix arg and call appropriate command
- (setq value (if (null value) 1 value))
- (setq prefix-arg nil)
- (cond ((equal com '(?c . ?c)) (vip-line (cons value ?C)))
- ((equal com '(?d . ?d)) (vip-line (cons value ?D)))
- ((equal com '(?d . ?y)) (vip-yank-defun))
- ((equal com '(?y . ?y)) (vip-line (cons value ?Y)))
- ((equal com '(?< . ?<)) (vip-line (cons value ?<)))
- ((equal com '(?> . ?>)) (vip-line (cons value ?>)))
- ((equal com '(?! . ?!)) (vip-line (cons value ?!)))
- ((equal com '(?= . ?=)) (vip-line (cons value ?=)))
- (t (error ""))))))
-
-(defun vip-describe-arg (arg)
- (let (val com)
- (setq val (vip-P-val arg)
- com (vip-getcom arg))
- (if (null val)
- (if (null com)
- (message "Value is nil, and command is nil.")
- (message "Value is nil, and command is %c." com))
- (if (null com)
- (message "Value is %d, and command is nil." val)
- (message "Value is %d, and command is %c." val com)))))
-
-(defun vip-digit-argument (arg)
- "Begin numeric argument for the next command."
- (interactive "P")
- (vip-prefix-arg-value last-command-char nil
- (if (consp arg) (cdr arg) nil)))
-
-(defun vip-command-argument (arg)
- "Accept a motion command as an argument."
- (interactive "P")
- (condition-case conditions
- (vip-prefix-arg-com
- last-command-char
- (cond ((null arg) nil)
- ((consp arg) (car arg))
- ((numberp arg) arg)
- (t (error "strange arg")))
- (cond ((null arg) nil)
- ((consp arg) (cdr arg))
- ((numberp arg) nil)
- (t (error "strange arg"))))
- (quit
- (setq vip-use-register nil)
- (signal 'quit nil))))
-
-(defun vip-p-val (arg)
- "Get value part of prefix-argument ARG."
- (cond ((null arg) 1)
- ((consp arg) (if (null (car arg)) 1 (car arg)))
- (t arg)))
-
-(defun vip-P-val (arg)
- "Get value part of prefix-argument ARG."
- (cond ((consp arg) (car arg))
- (t arg)))
-
-(defun vip-getcom (arg)
- "Get com part of prefix-argument ARG."
- (cond ((null arg) nil)
- ((consp arg) (cdr arg))
- (t nil)))
-
-(defun vip-getCom (arg)
- "Get com part of prefix-argument ARG and modify it."
- (let ((com (vip-getcom arg)))
- (cond ((equal com ?c) ?C)
- ((equal com ?d) ?D)
- ((equal com ?y) ?Y)
- (t com))))
-
-
-;; repeat last destructive command
-
-(defun vip-append-to-register (reg start end)
- "Append region to text in register REG.
-START and END are buffer positions indicating what to append."
- (set-register reg (concat (or (get-register reg) "")
- (buffer-substring start end))))
-
-(defun vip-execute-com (m-com val com)
- "(M-COM VAL COM) Execute command COM. The list (M-COM VAL COM) is set
-to vip-d-com for later use by vip-repeat"
- (let ((reg vip-use-register))
- (if com
- (cond ((= com ?c) (vip-change vip-com-point (point)))
- ((= com (- ?c)) (vip-change-subr vip-com-point (point)))
- ((or (= com ?C) (= com (- ?C)))
- (save-excursion
- (set-mark vip-com-point)
- (vip-enlarge-region (mark) (point))
- (if vip-use-register
- (progn
- (cond ((and (<= ?a vip-use-register)
- (<= vip-use-register ?z))
- (copy-to-register
- vip-use-register (mark) (point) nil))
- ((and (<= ?A vip-use-register)
- (<= vip-use-register ?Z))
- (vip-append-to-register
- (+ vip-use-register 32) (mark) (point)))
- (t (setq vip-use-register nil)
- (error "")))
- (setq vip-use-register nil)))
- (delete-region (mark) (point)))
- (open-line 1)
- (if (= com ?C) (vip-change-mode-to-insert) (yank)))
- ((= com ?d)
- (if vip-use-register
- (progn
- (cond ((and (<= ?a vip-use-register)
- (<= vip-use-register ?z))
- (copy-to-register
- vip-use-register vip-com-point (point) nil))
- ((and (<= ?A vip-use-register)
- (<= vip-use-register ?Z))
- (vip-append-to-register
- (+ vip-use-register 32) vip-com-point (point)))
- (t (setq vip-use-register nil)
- (error "")))
- (setq vip-use-register nil)))
- (setq last-command
- (if (eq last-command 'd-command) 'kill-region nil))
- (kill-region vip-com-point (point))
- (setq this-command 'd-command))
- ((= com ?D)
- (save-excursion
- (set-mark vip-com-point)
- (vip-enlarge-region (mark) (point))
- (if vip-use-register
- (progn
- (cond ((and (<= ?a vip-use-register)
- (<= vip-use-register ?z))
- (copy-to-register
- vip-use-register (mark) (point) nil))
- ((and (<= ?A vip-use-register)
- (<= vip-use-register ?Z))
- (vip-append-to-register
- (+ vip-use-register 32) (mark) (point)))
- (t (setq vip-use-register nil)
- (error "")))
- (setq vip-use-register nil)))
- (setq last-command
- (if (eq last-command 'D-command) 'kill-region nil))
- (kill-region (mark) (point))
- (if (eq m-com 'vip-line) (setq this-command 'D-command)))
- (back-to-indentation))
- ((= com ?y)
- (if vip-use-register
- (progn
- (cond ((and (<= ?a vip-use-register)
- (<= vip-use-register ?z))
- (copy-to-register
- vip-use-register vip-com-point (point) nil))
- ((and (<= ?A vip-use-register)
- (<= vip-use-register ?Z))
- (vip-append-to-register
- (+ vip-use-register 32) vip-com-point (point)))
- (t (setq vip-use-register nil)
- (error "")))
- (setq vip-use-register nil)))
- (setq last-command nil)
- (copy-region-as-kill vip-com-point (point))
- (goto-char vip-com-point))
- ((= com ?Y)
- (save-excursion
- (set-mark vip-com-point)
- (vip-enlarge-region (mark) (point))
- (if vip-use-register
- (progn
- (cond ((and (<= ?a vip-use-register)
- (<= vip-use-register ?z))
- (copy-to-register
- vip-use-register (mark) (point) nil))
- ((and (<= ?A vip-use-register)
- (<= vip-use-register ?Z))
- (vip-append-to-register
- (+ vip-use-register 32) (mark) (point)))
- (t (setq vip-use-register nil)
- (error "")))
- (setq vip-use-register nil)))
- (setq last-command nil)
- (copy-region-as-kill (mark) (point)))
- (goto-char vip-com-point))
- ((or (= com ?!) (= com (- ?!)))
- (save-excursion
- (set-mark vip-com-point)
- (vip-enlarge-region (mark) (point))
- (shell-command-on-region
- (mark) (point)
- (if (= com ?!)
- (setq vip-last-shell-com (vip-read-string "!"))
- vip-last-shell-com)
- t)))
- ((= com ?=)
- (save-excursion
- (set-mark vip-com-point)
- (vip-enlarge-region (mark) (point))
- (if (> (mark) (point)) (exchange-point-and-mark))
- (indent-region (mark) (point) nil)))
- ((= com ?<)
- (save-excursion
- (set-mark vip-com-point)
- (vip-enlarge-region (mark) (point))
- (indent-rigidly (mark) (point) (- vip-shift-width)))
- (goto-char vip-com-point))
- ((= com ?>)
- (save-excursion
- (set-mark vip-com-point)
- (vip-enlarge-region (mark) (point))
- (indent-rigidly (mark) (point) vip-shift-width))
- (goto-char vip-com-point))
- ((>= com 128)
- ;; this is special command #
- (vip-special-prefix-com (- com 128)))))
- (setq vip-d-com (list m-com val (if (or (= com ?c) (= com ?C) (= com ?!))
- (- com) com)
- reg))))
-
-(defun vip-repeat (arg)
- "(ARG) Re-execute last destructive command. vip-d-com has the form
-\(COM ARG CH REG), where COM is the command to be re-executed, ARG is the
-argument for COM, CH is a flag for repeat, and REG is optional and if exists
-is the name of the register for COM."
- (interactive "P")
- (if (eq last-command 'vip-undo)
- ;; if the last command was vip-undo, then undo-more
- (vip-undo-more)
- ;; otherwise execute the command stored in vip-d-com. if arg is non-nil
- ;; its prefix value is used as new prefix value for the command.
- (let ((m-com (car vip-d-com))
- (val (vip-P-val arg))
- (com (car (cdr (cdr vip-d-com))))
- (reg (nth 3 vip-d-com)))
- (if (null val) (setq val (car (cdr vip-d-com))))
- (if (null m-com) (error "No previous command to repeat."))
- (setq vip-use-register reg)
- (funcall m-com (cons val com)))))
-
-(defun vip-special-prefix-com (char)
- "This command is invoked interactively by the key sequence #<char>"
- (cond ((= char ?c)
- (downcase-region (min vip-com-point (point))
- (max vip-com-point (point))))
- ((= char ?C)
- (upcase-region (min vip-com-point (point))
- (max vip-com-point (point))))
- ((= char ?g)
- (set-mark vip-com-point)
- (vip-global-execute))
- ((= char ?q)
- (set-mark vip-com-point)
- (vip-quote-region))
- ((= char ?s) (spell-region vip-com-point (point)))))
-
-
-;; undoing
-
-(defun vip-undo ()
- "Undo previous change."
- (interactive)
- (message "undo!")
- (undo-start)
- (undo-more 2)
- (setq this-command 'vip-undo))
-
-(defun vip-undo-more ()
- "Continue undoing previous changes."
- (message "undo more!")
- (undo-more 1)
- (setq this-command 'vip-undo))
-
-
-;; utilities
-
-(defun vip-string-tail (str)
- (if (or (null str) (string= str "")) nil
- (substring str 1)))
-
-(defun vip-yank-defun ()
- (mark-defun)
- (copy-region-as-kill (point) (mark)))
-
-(defun vip-enlarge-region (beg end)
- "Enlarge region between BEG and END."
- (if (< beg end)
- (progn (goto-char beg) (set-mark end))
- (goto-char end)
- (set-mark beg))
- (beginning-of-line)
- (exchange-point-and-mark)
- (if (or (not (eobp)) (not (bolp))) (next-line 1))
- (beginning-of-line)
- (if (> beg end) (exchange-point-and-mark)))
-
-(defun vip-global-execute ()
- "Call last keyboad macro for each line in the region."
- (if (> (point) (mark)) (exchange-point-and-mark))
- (beginning-of-line)
- (call-last-kbd-macro)
- (while (< (point) (mark))
- (forward-line 1)
- (beginning-of-line)
- (call-last-kbd-macro)))
-
-(defun vip-quote-region ()
- "Quote region by inserting the user supplied string at the beginning of
-each line in the region."
- (setq vip-quote-string
- (let ((str
- (vip-read-string (format "quote string \(default \"%s\"\): "
- vip-quote-string))))
- (if (string= str "") vip-quote-string str)))
- (vip-enlarge-region (point) (mark))
- (if (> (point) (mark)) (exchange-point-and-mark))
- (insert vip-quote-string)
- (beginning-of-line)
- (forward-line 1)
- (while (and (< (point) (mark)) (bolp))
- (insert vip-quote-string)
- (beginning-of-line)
- (forward-line 1)))
-
-(defun vip-end-with-a-newline-p (string)
- "Check if the string ends with a newline."
- (or (string= text "")
- (= (aref string (1- (length string))) ?\n)))
-
-(defun vip-read-string (prompt &optional init)
- (setq save-minibuffer-local-map (copy-keymap minibuffer-local-map))
- (define-key minibuffer-local-map "\C-h" 'backward-char)
- (define-key minibuffer-local-map "\C-w" 'backward-word)
- (define-key minibuffer-local-map "\e" 'exit-minibuffer)
- (let (str)
- (condition-case conditions
- (setq str (read-string prompt init))
- (quit
- (setq minibuffer-local-map save-minibuffer-local-map)
- (signal 'quit nil)))
- (setq minibuffer-local-map save-minibuffer-local-map)
- str))
-
-
-;; insertion commands
-
-(defun vip-repeat-insert-command ()
- "This function is called when mode changes from insertion mode to
-vi command mode. It will repeat the insertion command if original insertion
-command was invoked with argument > 1."
- (let ((i-com (car vip-d-com)) (val (car (cdr vip-d-com))))
- (if (and val (> val 1)) ;; first check that val is non-nil
- (progn
- (setq vip-d-com (list i-com (1- val) ?r))
- (vip-repeat nil)
- (setq vip-d-com (list i-com val ?r))))))
-
-(defun vip-insert (arg) ""
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (setq vip-d-com (list 'vip-insert val ?r))
- (if com (vip-loop val (yank))
- (vip-change-mode-to-insert))))
-
-(defun vip-append (arg)
- "Append after point."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (setq vip-d-com (list 'vip-append val ?r))
- (if (not (eolp)) (forward-char))
- (if (equal com ?r)
- (vip-loop val (yank))
- (vip-change-mode-to-insert))))
-
-(defun vip-Append (arg)
- "Append at end of line."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (setq vip-d-com (list 'vip-Append val ?r))
- (end-of-line)
- (if (equal com ?r)
- (vip-loop val (yank))
- (vip-change-mode-to-insert))))
-
-(defun vip-Insert (arg)
- "Insert before first non-white."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (setq vip-d-com (list 'vip-Insert val ?r))
- (back-to-indentation)
- (if (equal com ?r)
- (vip-loop val (yank))
- (vip-change-mode-to-insert))))
-
-(defun vip-open-line (arg)
- "Open line below."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (setq vip-d-com (list 'vip-open-line val ?r))
- (let ((col (current-indentation)))
- (if (equal com ?r)
- (vip-loop val
- (progn
- (end-of-line)
- (newline 1)
- (if vip-open-with-indent (indent-to col))
- (yank)))
- (end-of-line)
- (newline 1)
- (if vip-open-with-indent (indent-to col))
- (vip-change-mode-to-insert)))))
-
-(defun vip-Open-line (arg)
- "Open line above."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (setq vip-d-com (list 'vip-Open-line val ?r))
- (let ((col (current-indentation)))
- (if (equal com ?r)
- (vip-loop val
- (progn
- (beginning-of-line)
- (open-line 1)
- (if vip-open-with-indent (indent-to col))
- (yank)))
- (beginning-of-line)
- (open-line 1)
- (if vip-open-with-indent (indent-to col))
- (vip-change-mode-to-insert)))))
-
-(defun vip-open-line-at-point (arg)
- "Open line at point."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (setq vip-d-com (list 'vip-open-line-at-point val ?r))
- (if (equal com ?r)
- (vip-loop val
- (progn
- (open-line 1)
- (yank)))
- (open-line 1)
- (vip-change-mode-to-insert))))
-
-(defun vip-substitute (arg)
- "Substitute characters."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (save-excursion
- (set-mark (point))
- (forward-char val)
- (if (equal com ?r)
- (vip-change-subr (mark) (point))
- (vip-change (mark) (point))))
- (setq vip-d-com (list 'vip-substitute val ?r))))
-
-(defun vip-substitute-line (arg)
- "Substitute lines."
- (interactive "p")
- (vip-line (cons arg ?C)))
-
-
-;; line command
-
-(defun vip-line (arg)
- (let ((val (car arg)) (com (cdr arg)))
- (move-marker vip-com-point (point))
- (next-line (1- val))
- (vip-execute-com 'vip-line val com)))
-
-(defun vip-yank-line (arg)
- "Yank ARG lines (in vi's sense)"
- (interactive "P")
- (let ((val (vip-p-val arg)))
- (vip-line (cons val ?Y))))
-
-
-;; region command
-
-(defun vip-region (arg)
- (interactive "P")
- (let ((val (vip-P-val arg))
- (com (vip-getcom arg)))
- (move-marker vip-com-point (point))
- (exchange-point-and-mark)
- (vip-execute-com 'vip-region val com)))
-
-(defun vip-Region (arg)
- (interactive "P")
- (let ((val (vip-P-val arg))
- (com (vip-getCom arg)))
- (move-marker vip-com-point (point))
- (exchange-point-and-mark)
- (vip-execute-com 'vip-Region val com)))
-
-(defun vip-replace-char (arg)
- "Replace the following ARG chars by the character read."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (setq vip-d-com (list 'vip-replace-char val ?r))
- (vip-replace-char-subr (if (equal com ?r) vip-d-char (read-char)) val)))
-
-(defun vip-replace-char-subr (char arg)
- (delete-char arg t)
- (setq vip-d-char char)
- (vip-loop (if (> arg 0) arg (- arg)) (insert char))
- (backward-char arg))
-
-(defun vip-replace-string ()
- "Replace string. If you supply null string as the string to be replaced,
-the query replace mode will toggle between string replace and regexp replace."
- (interactive)
- (let (str)
- (setq str (vip-read-string
- (if vip-re-replace "Replace regexp: " "Replace string: ")))
- (if (string= str "")
- (progn
- (setq vip-re-replace (not vip-re-replace))
- (message "Replace mode changed to %s."
- (if vip-re-replace "regexp replace"
- "string replace")))
- (if vip-re-replace
- ;; (replace-regexp
- ;; str
- ;; (vip-read-string (format "Replace regexp \"%s\" with: " str)))
- (while (re-search-forward str nil t)
- (replace-match (vip-read-string
- (format "Replace regexp \"%s\" with: " str))
- nil nil))
- (replace-string
- str
- (vip-read-string (format "Replace \"%s\" with: " str)))))))
-
-
-;; basic cursor movement. j, k, l, m commands.
-
-(defun vip-forward-char (arg)
- "Move point right ARG characters (left if ARG negative).On reaching end
-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)))
- (forward-char val)
- (if com (vip-execute-com 'vip-forward-char val com))))
-
-(defun vip-backward-char (arg)
- "Move point left ARG characters (right if ARG negative). On reaching
-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)))
- (backward-char val)
- (if com (vip-execute-com 'vip-backward-char val com))))
-
-
-;; word command
-
-(defun vip-forward-word (arg)
- "Forward word."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (move-marker vip-com-point (point)))
- (forward-word val)
- (skip-chars-forward " \t\n")
- (if com
- (progn
- (if (or (= com ?c) (= com (- ?c)))
- (progn (backward-word 1) (forward-word 1)))
- (if (or (= com ?d) (= com ?y))
- (progn
- (backward-word 1)
- (forward-word 1)
- (skip-chars-forward " \t")))
- (vip-execute-com 'vip-forward-word val com)))))
-
-(defun vip-end-of-word (arg)
- "Move point to end of current word."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (move-marker vip-com-point (point)))
- (forward-char)
- (forward-word val)
- (backward-char)
- (if com
- (progn
- (forward-char)
- (vip-execute-com 'vip-end-of-word val com)))))
-
-(defun vip-backward-word (arg)
- "Backward word."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (move-marker vip-com-point (point)))
- (backward-word val)
- (if com (vip-execute-com 'vip-backward-word val com))))
-
-(defun vip-forward-Word (arg)
- "Forward word delimited by white character."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (move-marker vip-com-point (point)))
- (re-search-forward "[^ \t\n]*[ \t\n]+" nil t val)
- (if com
- (progn
- (if (or (= com ?c) (= com (- ?c)))
- (progn (backward-word 1) (forward-word 1)))
- (if (or (= com ?d) (= com ?y))
- (progn
- (backward-word 1)
- (forward-word 1)
- (skip-chars-forward " \t")))
- (vip-execute-com 'vip-forward-Word val com)))))
-
-(defun vip-end-of-Word (arg)
- "Move forward to end of word delimited by white character."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (move-marker vip-com-point (point)))
- (forward-char)
- (if (re-search-forward "[^ \t\n]+" nil t val) (backward-char))
- (if com
- (progn
- (forward-char)
- (vip-execute-com 'vip-end-of-Word val com)))))
-
-(defun vip-backward-Word (arg)
- "Backward word delimited by white character."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (move-marker vip-com-point (point)))
- (if (re-search-backward "[ \t\n]+[^ \t\n]+" nil t val)
- (forward-char)
- (goto-char (point-min)))
- (if com (vip-execute-com 'vip-backward-Word val com))))
-
-(defun vip-beginning-of-line (arg)
- "Go to beginning of line."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (if com (move-marker vip-com-point (point)))
- (beginning-of-line val)
- (if com (vip-execute-com 'vip-beginning-of-line val com))))
-
-(defun vip-bol-and-skip-white (arg)
- "Beginning of line at first non-white character."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (if com (move-marker vip-com-point (point)))
- (back-to-indentation)
- (if com (vip-execute-com 'vip-bol-and-skip-white val com))))
-
-(defun vip-goto-eol (arg)
- "Go to end of line."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (if com (move-marker vip-com-point (point)))
- (end-of-line val)
- (if com (vip-execute-com 'vip-goto-eol val com))))
-
-(defun vip-next-line (arg)
- "Go to next line."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getCom arg)))
- (if com (move-marker vip-com-point (point)))
- (line-move val)
- (setq this-command 'next-line)
- (if com (vip-execute-com 'vip-next-line val com))))
-
-(defun vip-next-line-at-bol (arg)
- "Next line at beginning of line."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getCom arg)))
- (if com (move-marker vip-com-point (point)))
- (next-line val)
- (back-to-indentation)
- (if com (vip-execute-com 'vip-next-line-at-bol val com))))
-
-(defun vip-previous-line (arg)
- "Go to previous line."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getCom arg)))
- (if com (move-marker vip-com-point (point)))
- (next-line (- val))
- (setq this-command 'previous-line)
- (if com (vip-execute-com 'vip-previous-line val com))))
-
-(defun vip-previous-line-at-bol (arg)
- "Previous line at beginning of line."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getCom arg)))
- (if com (move-marker vip-com-point (point)))
- (next-line (- val))
- (back-to-indentation)
- (if com (vip-execute-com 'vip-previous-line val com))))
-
-(defun vip-change-to-eol (arg)
- "Change to end of line."
- (interactive "P")
- (vip-goto-eol (cons arg ?c)))
-
-(defun vip-kill-line (arg)
- "Delete line."
- (interactive "P")
- (vip-goto-eol (cons arg ?d)))
-
-
-;; moving around
-
-(defun vip-goto-line (arg)
- "Go to ARG's line. Without ARG go to end of buffer."
- (interactive "P")
- (let ((val (vip-P-val arg)) (com (vip-getCom arg)))
- (move-marker vip-com-point (point))
- (set-mark (point))
- (if (null val)
- (goto-char (point-max))
- (goto-char (point-min))
- (forward-line (1- val)))
- (back-to-indentation)
- (if com (vip-execute-com 'vip-goto-line val com))))
-
-(defun vip-find-char (arg char forward offset)
- "Find ARG's occurrence of CHAR on the current line. If FORWARD then
-search is forward, otherwise backward. OFFSET is used to adjust point
-after search."
- (let ((arg (if forward arg (- arg))) point)
- (save-excursion
- (save-restriction
- (if (> arg 0)
- (narrow-to-region
- ;; forward search begins here
- (if (eolp) (error "") (point))
- ;; forward search ends here
- (progn (next-line 1) (beginning-of-line) (point)))
- (narrow-to-region
- ;; backward search begins from here
- (if (bolp) (error "") (point))
- ;; backward search ends here
- (progn (beginning-of-line) (point))))
- ;; if arg > 0, point is forwarded before search.
- (if (> arg 0) (goto-char (1+ (point-min)))
- (goto-char (point-max)))
- (let ((case-fold-search nil))
- (search-forward (char-to-string char) nil 0 arg))
- (setq point (point))
- (if (or (and (> arg 0) (= point (point-max)))
- (and (< arg 0) (= point (point-min))))
- (error ""))))
- (goto-char (+ point (if (> arg 0) (if offset -2 -1) (if offset 1 0))))))
-
-(defun vip-find-char-forward (arg)
- "Find char on the line. If called interactively read the char to find
-from the terminal, and if called from vip-repeat, the char last used is
-used. This behaviour is controlled by the sign of prefix numeric value."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (if (> val 0)
- ;; this means that the function was called interactively
- (setq vip-f-char (read-char)
- vip-f-forward t
- vip-f-offset nil)
- (setq val (- val)))
- (if com (move-marker vip-com-point (point)))
- (vip-find-char val (if (> (vip-p-val arg) 0) vip-f-char vip-F-char) t nil)
- (setq val (- val))
- (if com
- (progn
- (setq vip-F-char vip-f-char);; set new vip-F-char
- (forward-char)
- (vip-execute-com 'vip-find-char-forward val com)))))
-
-(defun vip-goto-char-forward (arg)
- "Go up to char ARG forward on line."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (if (> val 0)
- ;; this means that the function was called interactively
- (setq vip-f-char (read-char)
- vip-f-forward t
- vip-f-offset t)
- (setq val (- val)))
- (if com (move-marker vip-com-point (point)))
- (vip-find-char val (if (> (vip-p-val arg) 0) vip-f-char vip-F-char) t t)
- (setq val (- val))
- (if com
- (progn
- (setq vip-F-char vip-f-char);; set new vip-F-char
- (forward-char)
- (vip-execute-com 'vip-goto-char-forward val com)))))
-
-(defun vip-find-char-backward (arg)
- "Find char ARG on line backward."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (if (> val 0)
- ;; this means that the function was called interactively
- (setq vip-f-char (read-char)
- vip-f-forward nil
- vip-f-offset nil)
- (setq val (- val)))
- (if com (move-marker vip-com-point (point)))
- (vip-find-char
- val (if (> (vip-p-val arg) 0) vip-f-char vip-F-char) nil nil)
- (setq val (- val))
- (if com
- (progn
- (setq vip-F-char vip-f-char);; set new vip-F-char
- (vip-execute-com 'vip-find-char-backward val com)))))
-
-(defun vip-goto-char-backward (arg)
- "Go up to char ARG backward on line."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (if (> val 0)
- ;; this means that the function was called interactively
- (setq vip-f-char (read-char)
- vip-f-forward nil
- vip-f-offset t)
- (setq val (- val)))
- (if com (move-marker vip-com-point (point)))
- (vip-find-char val (if (> (vip-p-val arg) 0) vip-f-char vip-F-char) nil t)
- (setq val (- val))
- (if com
- (progn
- (setq vip-F-char vip-f-char);; set new vip-F-char
- (vip-execute-com 'vip-goto-char-backward val com)))))
-
-(defun vip-repeat-find (arg)
- "Repeat previous find command."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (if com (move-marker vip-com-point (point)))
- (vip-find-char val vip-f-char vip-f-forward vip-f-offset)
- (if com
- (progn
- (if vip-f-forward (forward-char))
- (vip-execute-com 'vip-repeat-find val com)))))
-
-(defun vip-repeat-find-opposite (arg)
- "Repeat previous find command in the opposite direction."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (if com (move-marker vip-com-point (point)))
- (vip-find-char val vip-f-char (not vip-f-forward) vip-f-offset)
- (if com
- (progn
- (if vip-f-forward (forward-char))
- (vip-execute-com 'vip-repeat-find-opposite val com)))))
-
-
-;; window scrolling etc.
-
-(defun vip-other-window (arg)
- "Switch to other window."
- (interactive "p")
- (other-window arg)
- (or (not (eq vip-current-mode 'emacs-mode))
- (string= (buffer-name (current-buffer)) " *Minibuf-1*")
- (vip-change-mode-to-vi)))
-
-(defun vip-window-top (arg)
- "Go to home window line."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (move-marker vip-com-point (point)))
- (move-to-window-line (1- val))
- (if com (vip-execute-com 'vip-window-top val com))))
-
-(defun vip-window-middle (arg)
- "Go to middle window line."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (move-marker vip-com-point (point)))
- (move-to-window-line (+ (/ (1- (window-height)) 2) (1- val)))
- (if com (vip-execute-com 'vip-window-middle val com))))
-
-(defun vip-window-bottom (arg)
- "Go to last window line."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (move-marker vip-com-point (point)))
- (move-to-window-line (- val))
- (if com (vip-execute-com 'vip-window-bottom val com))))
-
-(defun vip-line-to-top (arg)
- "Put current line on the home line."
- (interactive "p")
- (recenter (1- arg)))
-
-(defun vip-line-to-middle (arg)
- "Put current line on the middle line."
- (interactive "p")
- (recenter (+ (1- arg) (/ (1- (window-height)) 2))))
-
-(defun vip-line-to-bottom (arg)
- "Put current line on the last line."
- (interactive "p")
- (recenter (- (window-height) (1+ arg))))
-
-
-;; paren match
-
-(defun vip-paren-match (arg)
- "Go to the matching parenthesis."
- (interactive "P")
- (let ((com (vip-getcom arg)))
- (if (numberp arg)
- (if (or (> arg 99) (< arg 1))
- (error "Prefix must be between 1 and 99.")
- (goto-char
- (if (> (point-max) 80000)
- (* (/ (point-max) 100) arg)
- (/ (* (point-max) arg) 100)))
- (back-to-indentation))
- (cond ((looking-at "[\(\[{]")
- (if com (move-marker vip-com-point (point)))
- (forward-sexp 1)
- (if com
- (vip-execute-com 'vip-paren-match nil com)
- (backward-char)))
- ((looking-at "[])}]")
- (forward-char)
- (if com (move-marker vip-com-point (point)))
- (backward-sexp 1)
- (if com (vip-execute-com 'vip-paren-match nil com)))
- (t (error ""))))))
-
-
-;; sentence and paragraph
-
-(defun vip-forward-sentence (arg)
- "Forward sentence."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (move-marker vip-com-point (point)))
- (forward-sentence val)
- (if com (vip-execute-com 'vip-forward-sentence nil com))))
-
-(defun vip-backward-sentence (arg)
- "Backward sentence."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (move-marker vip-com-point (point)))
- (backward-sentence val)
- (if com (vip-execute-com 'vip-backward-sentence nil com))))
-
-(defun vip-forward-paragraph (arg)
- "Forward paragraph."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (move-marker vip-com-point (point)))
- (forward-paragraph val)
- (if com (vip-execute-com 'vip-forward-paragraph nil com))))
-
-(defun vip-backward-paragraph (arg)
- "Backward paragraph."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (move-marker vip-com-point (point)))
- (backward-paragraph val)
- (if com (vip-execute-com 'vip-backward-paragraph nil com))))
-
-
-;; scrolling
-
-(defun vip-scroll (arg)
- "Scroll to next screen."
- (interactive "p")
- (if (> arg 0)
- (while (> arg 0)
- (scroll-up)
- (setq arg (1- arg)))
- (while (> 0 arg)
- (scroll-down)
- (setq arg (1+ arg)))))
-
-(defun vip-scroll-back (arg)
- "Scroll to previous screen."
- (interactive "p")
- (vip-scroll (- arg)))
-
-(defun vip-scroll-down (arg)
- "Scroll up half screen."
- (interactive "P")
- (if (null arg) (scroll-down (/ (window-height) 2))
- (scroll-down arg)))
-
-(defun vip-scroll-down-one (arg)
- "Scroll up one line."
- (interactive "p")
- (scroll-down arg))
-
-(defun vip-scroll-up (arg)
- "Scroll down half screen."
- (interactive "P")
- (if (null arg) (scroll-up (/ (window-height) 2))
- (scroll-up arg)))
-
-(defun vip-scroll-up-one (arg)
- "Scroll down one line."
- (interactive "p")
- (scroll-up arg))
-
-
-;; splitting window
-
-(defun vip-buffer-in-two-windows ()
- "Show current buffer in two windows."
- (interactive)
- (delete-other-windows)
- (split-window-vertically nil))
-
-
-;; searching
-
-(defun vip-search-forward (arg)
- "Search a string forward. ARG is used to find the ARG's occurrence
-of the string. Default is vanilla search. Search mode can be toggled by
-giving null search string."
- (interactive "P")
- (let ((val (vip-P-val arg)) (com (vip-getcom arg)))
- (setq vip-s-forward t
- vip-s-string (vip-read-string (if vip-re-search "RE-/" "/")))
- (if (string= vip-s-string "")
- (progn
- (setq vip-re-search (not vip-re-search))
- (message "Search mode changed to %s search."
- (if vip-re-search "regular expression"
- "vanilla")))
- (vip-search vip-s-string t val)
- (if com
- (progn
- (move-marker vip-com-point (mark))
- (vip-execute-com 'vip-search-next val com))))))
-
-(defun vip-search-backward (arg)
- "Search a string backward. ARG is used to find the ARG's occurrence
-of the string. Default is vanilla search. Search mode can be toggled by
-giving null search string."
- (interactive "P")
- (let ((val (vip-P-val arg)) (com (vip-getcom arg)))
- (setq vip-s-forward nil
- vip-s-string (vip-read-string (if vip-re-search "RE-?" "?")))
- (if (string= vip-s-string "")
- (progn
- (setq vip-re-search (not vip-re-search))
- (message "Search mode changed to %s search."
- (if vip-re-search "regular expression"
- "vanilla")))
- (vip-search vip-s-string nil val)
- (if com
- (progn
- (move-marker vip-com-point (mark))
- (vip-execute-com 'vip-search-next val com))))))
-
-(defun vip-search (string forward arg &optional no-offset init-point)
- "(STRING FORWARD COUNT &optional NO-OFFSET) Search COUNT's occurrence of
-STRING. Search will be forward if FORWARD, otherwise backward."
- (let ((val (vip-p-val arg)) (com (vip-getcom arg))
- (null-arg (null (vip-P-val arg))) (offset (not no-offset))
- (case-fold-search vip-case-fold-search)
- (start-point (or init-point (point))))
- (if forward
- (condition-case conditions
- (progn
- (if (and offset (not (eobp))) (forward-char))
- (if vip-re-search
- (progn
- (re-search-forward string nil nil val)
- (re-search-backward string))
- (search-forward string nil nil val)
- (search-backward string))
- (push-mark start-point))
- (search-failed
- (if (and null-arg vip-search-wrap-around)
- (progn
- (goto-char (point-min))
- (vip-search string forward (cons 1 com) t start-point))
- (goto-char start-point)
- (signal 'search-failed (cdr conditions)))))
- (condition-case conditions
- (progn
- (if vip-re-search
- (re-search-backward string nil nil val)
- (search-backward string nil nil val))
- (push-mark start-point))
- (search-failed
- (if (and null-arg vip-search-wrap-around)
- (progn
- (goto-char (point-max))
- (vip-search string forward (cons 1 com) t start-point))
- (goto-char start-point)
- (signal 'search-failed (cdr conditions))))))))
-
-(defun vip-search-next (arg)
- "Repeat previous search."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (if (null vip-s-string) (error "No previous search string."))
- (vip-search vip-s-string vip-s-forward arg)
- (if com (vip-execute-com 'vip-search-next val com))))
-
-(defun vip-search-Next (arg)
- "Repeat previous search in the reverse direction."
- (interactive "P")
- (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
- (if (null vip-s-string) (error "No previous search string."))
- (vip-search vip-s-string (not vip-s-forward) arg)
- (if com (vip-execute-com 'vip-search-Next val com))))
-
-
-;; visiting and killing files, buffers
-
-(defun vip-switch-to-buffer ()
- "Switch to buffer in the current window."
- (interactive)
- (let (buffer)
- (setq buffer
- (read-buffer
- (format "switch to buffer \(%s\): "
- (buffer-name (other-buffer (current-buffer))))))
- (switch-to-buffer buffer)
- (vip-change-mode-to-vi)))
-
-(defun vip-switch-to-buffer-other-window ()
- "Switch to buffer in another window."
- (interactive)
- (let (buffer)
- (setq buffer
- (read-buffer
- (format "Switch to buffer \(%s\): "
- (buffer-name (other-buffer (current-buffer))))))
- (switch-to-buffer-other-window buffer)
- (vip-change-mode-to-vi)))
-
-(defun vip-kill-buffer ()
- "Kill a buffer."
- (interactive)
- (let (buffer buffer-name)
- (setq buffer-name
- (read-buffer
- (format "Kill buffer \(%s\): "
- (buffer-name (current-buffer)))))
- (setq buffer
- (if (null buffer-name)
- (current-buffer)
- (get-buffer buffer-name)))
- (if (null buffer) (error "Buffer %s nonexistent." buffer-name))
- (if (or (not (buffer-modified-p buffer))
- (y-or-n-p "Buffer is modified, are you sure? "))
- (kill-buffer buffer)
- (error "Buffer not killed."))))
-
-(defun vip-find-file ()
- "Visit file in the current window."
- (interactive)
- (let (file)
- (setq file (read-file-name "visit file: "))
- (switch-to-buffer (find-file-noselect file))
- (vip-change-mode-to-vi)))
-
-(defun vip-find-file-other-window ()
- "Visit file in another window."
- (interactive)
- (let (file)
- (setq file (read-file-name "Visit file: "))
- (switch-to-buffer-other-window (find-file-noselect file))
- (vip-change-mode-to-vi)))
-
-(defun vip-info-on-file ()
- "Give information of the file associated to the current buffer."
- (interactive)
- (message "\"%s\" line %d of %d"
- (if (buffer-file-name) (buffer-file-name) "")
- (1+ (count-lines (point-min) (point)))
- (1+ (count-lines (point-min) (point-max)))))
-
-
-;; yank and pop
-
-(defun vip-yank (text)
- "yank TEXT silently."
- (save-excursion
- (vip-push-mark-silent (point))
- (insert text)
- (exchange-point-and-mark))
- (skip-chars-forward " \t"))
-
-(defun vip-put-back (arg)
- "Put back after point/below line."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (text (if vip-use-register
- (if (and (<= ?1 vip-use-register) (<= vip-use-register ?9))
- (current-kill (- vip-use-register ?1) 'do-not-rotate)
- (get-register vip-use-register))
- (current-kill 0))))
- (if (null text)
- (if vip-use-register
- (let ((reg vip-use-register))
- (setq vip-use-register nil)
- (error "Nothing in register %c" reg))
- (error "")))
- (setq vip-use-register nil)
- (if (vip-end-with-a-newline-p text)
- (progn
- (next-line 1)
- (beginning-of-line))
- (if (and (not (eolp)) (not (eobp))) (forward-char)))
- (setq vip-d-com (list 'vip-put-back val nil vip-use-register))
- (vip-loop val (vip-yank text))))
-
-(defun vip-Put-back (arg)
- "Put back at point/above line."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (text (if vip-use-register
- (if (and (<= ?1 vip-use-register) (<= vip-use-register ?9))
- (current-kill (- vip-use-register ?1) 'do-not-rotate)
- (get-register vip-use-register))
- (current-kill 0))))
- (if (null text)
- (if vip-use-register
- (let ((reg vip-use-register))
- (setq vip-use-register nil)
- (error "Nothing in register %c" reg))
- (error "")))
- (setq vip-use-register nil)
- (if (vip-end-with-a-newline-p text) (beginning-of-line))
- (setq vip-d-com (list 'vip-Put-back val nil vip-use-register))
- (vip-loop val (vip-yank text))))
-
-(defun vip-delete-char (arg)
- "Delete character."
- (interactive "P")
- (let ((val (vip-p-val arg)))
- (setq vip-d-com (list 'vip-delete-char val nil))
- (if vip-use-register
- (progn
- (if (and (<= ?A vip-use-register) (<= vip-use-register ?Z))
- (vip-append-to-register
- (+ vip-use-register 32) (point) (- (point) val))
- (copy-to-register vip-use-register (point) (- (point) val) nil))
- (setq vip-use-register nil)))
- (delete-char val t)))
-
-(defun vip-delete-backward-char (arg)
- "Delete previous character."
- (interactive "P")
- (let ((val (vip-p-val arg)))
- (setq vip-d-com (list 'vip-delete-backward-char val nil))
- (if vip-use-register
- (progn
- (if (and (<= ?A vip-use-register) (<= vip-use-register ?Z))
- (vip-append-to-register
- (+ vip-use-register 32) (point) (+ (point) val))
- (copy-to-register vip-use-register (point) (+ (point) val) nil))
- (setq vip-use-register nil)))
- (delete-backward-char val t)))
-
-
-;; join lines.
-
-(defun vip-join-lines (arg)
- "Join this line to next, if ARG is nil. Otherwise, join ARG lines"
- (interactive "*P")
- (let ((val (vip-P-val arg)))
- (setq vip-d-com (list 'vip-join-lines val nil))
- (vip-loop (if (null val) 1 (1- val))
- (progn
- (end-of-line)
- (if (not (eobp))
- (progn
- (forward-line 1)
- (delete-region (point) (1- (point)))
- (fixup-whitespace)))))))
-
-
-;; making small changes
-
-(defun vip-change (beg end)
- (setq c-string
- (vip-read-string (format "%s => " (buffer-substring beg end))))
- (vip-change-subr beg end))
-
-(defun vip-change-subr (beg end)
- (if vip-use-register
- (progn
- (copy-to-register vip-use-register beg end nil)
- (setq vip-use-register nil)))
- (kill-region beg end)
- (setq this-command 'vip-change)
- (insert c-string))
-
-
-;; query replace
-
-(defun vip-query-replace ()
- "Query replace. If you supply null string as the string to be replaced,
-the query replace mode will toggle between string replace and regexp replace."
- (interactive)
- (let (str)
- (setq str (vip-read-string
- (if vip-re-query-replace "Query replace regexp: "
- "Query replace: ")))
- (if (string= str "")
- (progn
- (setq vip-re-query-replace (not vip-re-query-replace))
- (message "Query replace mode changed to %s."
- (if vip-re-query-replace "regexp replace"
- "string replace")))
- (if vip-re-query-replace
- (query-replace-regexp
- str
- (vip-read-string (format "Query replace regexp \"%s\" with: " str)))
- (query-replace
- str
- (vip-read-string (format "Query replace \"%s\" with: " str)))))))
-
-
-;; marking
-
-(defun vip-mark-beginning-of-buffer ()
- (interactive)
- (set-mark (point))
- (goto-char (point-min))
- (exchange-point-and-mark)
- (message "mark set at the beginning of buffer"))
-
-(defun vip-mark-end-of-buffer ()
- (interactive)
- (set-mark (point))
- (goto-char (point-max))
- (exchange-point-and-mark)
- (message "mark set at the end of buffer"))
-
-(defun vip-mark-point (char)
- (interactive "c")
- (cond ((and (<= ?a char) (<= char ?z))
- (point-to-register (- char (- ?a ?\C-a)) nil))
- ((= char ?<) (vip-mark-beginning-of-buffer))
- ((= char ?>) (vip-mark-end-of-buffer))
- ((= char ?.) (push-mark))
- ((= char ?,) (set-mark-command 1))
- ((= char ?D) (mark-defun))
- (t (error ""))))
-
-(defun vip-goto-mark (arg)
- "Go to mark."
- (interactive "P")
- (let ((char (read-char)) (com (vip-getcom arg)))
- (vip-goto-mark-subr char com nil)))
-
-(defun vip-goto-mark-and-skip-white (arg)
- "Go to mark and skip to first non-white on line."
- (interactive "P")
- (let ((char (read-char)) (com (vip-getCom arg)))
- (vip-goto-mark-subr char com t)))
-
-(defun vip-goto-mark-subr (char com skip-white)
- (cond ((and (<= ?a char) (<= char ?z))
- (let ((buff (current-buffer)))
- (if com (move-marker vip-com-point (point)))
- (goto-char (register-to-point (- char (- ?a ?\C-a))))
- (if skip-white (back-to-indentation))
- (vip-change-mode-to-vi)
- (if com
- (if (equal buff (current-buffer))
- (vip-execute-com (if skip-white
- 'vip-goto-mark-and-skip-white
- 'vip-goto-mark)
- nil com)
- (switch-to-buffer buff)
- (goto-char vip-com-point)
- (vip-change-mode-to-vi)
- (error "")))))
- ((and (not skip-white) (= char ?`))
- (if com (move-marker vip-com-point (point)))
- (exchange-point-and-mark)
- (if com (vip-execute-com 'vip-goto-mark nil com)))
- ((and skip-white (= char ?'))
- (if com (move-marker vip-com-point (point)))
- (exchange-point-and-mark)
- (back-to-indentation)
- (if com (vip-execute-com 'vip-goto-mark-and-skip-white nil com)))
- (t (error ""))))
-
-(defun vip-exchange-point-and-mark ()
- (interactive)
- (exchange-point-and-mark)
- (back-to-indentation))
-
-(defun vip-keyboard-quit ()
- "Abort partially formed or running command."
- (interactive)
- (setq vip-use-register nil)
- (keyboard-quit))
-
-(defun vip-ctl-c-equivalent (arg)
- "Emulate C-c in Emacs mode."
- (interactive "P")
- (vip-ctl-key-equivalent "\C-c" arg))
-
-(defun vip-ctl-x-equivalent (arg)
- "Emulate C-x in Emacs mode."
- (interactive "P")
- (vip-ctl-key-equivalent "\C-x" arg))
-
-(defun vip-ctl-key-equivalent (key arg)
- (let ((char (read-char)))
- (if (and (<= ?A char) (<= char ?Z))
- (setq char (- char (- ?A ?\C-a))))
- (vip-escape-to-emacs arg (list (aref key 0) char))))
-
-;; commands in insertion mode
-
-(defun vip-delete-backward-word (arg)
- "Delete previous word."
- (interactive "p")
- (save-excursion
- (set-mark (point))
- (backward-word arg)
- (delete-region (point) (mark))))
-
-
-;; key bindings
-
-(set 'vip-mode-map (make-keymap))
-
-(define-key vip-mode-map "\C-a" 'beginning-of-line)
-(define-key vip-mode-map "\C-b" 'vip-scroll-back)
-(define-key vip-mode-map "\C-c" 'vip-ctl-c)
-(define-key vip-mode-map "\C-d" 'vip-scroll-up)
-(define-key vip-mode-map "\C-e" 'vip-scroll-up-one)
-(define-key vip-mode-map "\C-f" 'vip-scroll)
-(define-key vip-mode-map "\C-g" 'vip-keyboard-quit)
-(define-key vip-mode-map "\C-h" 'help-command)
-(define-key vip-mode-map "\C-m" 'vip-scroll-back)
-(define-key vip-mode-map "\C-n" 'vip-other-window)
-(define-key vip-mode-map "\C-o" 'vip-open-line-at-point)
-(define-key vip-mode-map "\C-u" 'vip-scroll-down)
-(define-key vip-mode-map "\C-x" 'vip-ctl-x)
-(define-key vip-mode-map "\C-y" 'vip-scroll-down-one)
-(define-key vip-mode-map "\C-z" 'vip-change-mode-to-emacs)
-(define-key vip-mode-map "\e" 'vip-ESC)
-
-(define-key vip-mode-map " " 'vip-scroll)
-(define-key vip-mode-map "!" 'vip-command-argument)
-(define-key vip-mode-map "\"" 'vip-command-argument)
-(define-key vip-mode-map "#" 'vip-command-argument)
-(define-key vip-mode-map "$" 'vip-goto-eol)
-(define-key vip-mode-map "%" 'vip-paren-match)
-(define-key vip-mode-map "&" 'vip-nil)
-(define-key vip-mode-map "'" 'vip-goto-mark-and-skip-white)
-(define-key vip-mode-map "(" 'vip-backward-sentence)
-(define-key vip-mode-map ")" 'vip-forward-sentence)
-(define-key vip-mode-map "*" 'call-last-kbd-macro)
-(define-key vip-mode-map "+" 'vip-next-line-at-bol)
-(define-key vip-mode-map "," 'vip-repeat-find-opposite)
-(define-key vip-mode-map "-" 'vip-previous-line-at-bol)
-(define-key vip-mode-map "." 'vip-repeat)
-(define-key vip-mode-map "/" 'vip-search-forward)
-
-(define-key vip-mode-map "0" 'vip-beginning-of-line)
-(define-key vip-mode-map "1" 'vip-digit-argument)
-(define-key vip-mode-map "2" 'vip-digit-argument)
-(define-key vip-mode-map "3" 'vip-digit-argument)
-(define-key vip-mode-map "4" 'vip-digit-argument)
-(define-key vip-mode-map "5" 'vip-digit-argument)
-(define-key vip-mode-map "6" 'vip-digit-argument)
-(define-key vip-mode-map "7" 'vip-digit-argument)
-(define-key vip-mode-map "8" 'vip-digit-argument)
-(define-key vip-mode-map "9" 'vip-digit-argument)
-
-(define-key vip-mode-map ":" 'vip-ex)
-(define-key vip-mode-map ";" 'vip-repeat-find)
-(define-key vip-mode-map "<" 'vip-command-argument)
-(define-key vip-mode-map "=" 'vip-command-argument)
-(define-key vip-mode-map ">" 'vip-command-argument)
-(define-key vip-mode-map "?" 'vip-search-backward)
-(define-key vip-mode-map "@" 'vip-nil)
-
-(define-key vip-mode-map "A" 'vip-Append)
-(define-key vip-mode-map "B" 'vip-backward-Word)
-(define-key vip-mode-map "C" 'vip-ctl-c-equivalent)
-(define-key vip-mode-map "D" 'vip-kill-line)
-(define-key vip-mode-map "E" 'vip-end-of-Word)
-(define-key vip-mode-map "F" 'vip-find-char-backward)
-(define-key vip-mode-map "G" 'vip-goto-line)
-(define-key vip-mode-map "H" 'vip-window-top)
-(define-key vip-mode-map "I" 'vip-Insert)
-(define-key vip-mode-map "J" 'vip-join-lines)
-(define-key vip-mode-map "K" 'vip-kill-buffer)
-(define-key vip-mode-map "L" 'vip-window-bottom)
-(define-key vip-mode-map "M" 'vip-window-middle)
-(define-key vip-mode-map "N" 'vip-search-Next)
-(define-key vip-mode-map "O" 'vip-Open-line)
-(define-key vip-mode-map "P" 'vip-Put-back)
-(define-key vip-mode-map "Q" 'vip-query-replace)
-(define-key vip-mode-map "R" 'vip-replace-string)
-(define-key vip-mode-map "S" 'vip-switch-to-buffer-other-window)
-(define-key vip-mode-map "T" 'vip-goto-char-backward)
-(define-key vip-mode-map "U" 'vip-nil)
-(define-key vip-mode-map "V" 'vip-find-file-other-window)
-(define-key vip-mode-map "W" 'vip-forward-Word)
-(define-key vip-mode-map "X" 'vip-ctl-x-equivalent)
-(define-key vip-mode-map "Y" 'vip-yank-line)
-(define-key vip-mode-map "ZZ" 'save-buffers-kill-emacs)
-
-(define-key vip-mode-map "[" 'vip-nil)
-(define-key vip-mode-map "\\" 'vip-escape-to-emacs)
-(define-key vip-mode-map "]" 'vip-nil)
-(define-key vip-mode-map "^" 'vip-bol-and-skip-white)
-(define-key vip-mode-map "_" 'vip-nil)
-(define-key vip-mode-map "`" 'vip-goto-mark)
-
-(define-key vip-mode-map "a" 'vip-append)
-(define-key vip-mode-map "b" 'vip-backward-word)
-(define-key vip-mode-map "c" 'vip-command-argument)
-(define-key vip-mode-map "d" 'vip-command-argument)
-(define-key vip-mode-map "e" 'vip-end-of-word)
-(define-key vip-mode-map "f" 'vip-find-char-forward)
-(define-key vip-mode-map "g" 'vip-info-on-file)
-(define-key vip-mode-map "h" 'vip-backward-char)
-(define-key vip-mode-map "i" 'vip-insert)
-(define-key vip-mode-map "j" 'vip-next-line)
-(define-key vip-mode-map "k" 'vip-previous-line)
-(define-key vip-mode-map "l" 'vip-forward-char)
-(define-key vip-mode-map "m" 'vip-mark-point)
-(define-key vip-mode-map "n" 'vip-search-next)
-(define-key vip-mode-map "o" 'vip-open-line)
-(define-key vip-mode-map "p" 'vip-put-back)
-(define-key vip-mode-map "q" 'vip-nil)
-(define-key vip-mode-map "r" 'vip-replace-char)
-(define-key vip-mode-map "s" 'vip-switch-to-buffer)
-(define-key vip-mode-map "t" 'vip-goto-char-forward)
-(define-key vip-mode-map "u" 'vip-undo)
-(define-key vip-mode-map "v" 'vip-find-file)
-(define-key vip-mode-map "w" 'vip-forward-word)
-(define-key vip-mode-map "x" 'vip-delete-char)
-(define-key vip-mode-map "y" 'vip-command-argument)
-(define-key vip-mode-map "zH" 'vip-line-to-top)
-(define-key vip-mode-map "zM" 'vip-line-to-middle)
-(define-key vip-mode-map "zL" 'vip-line-to-bottom)
-(define-key vip-mode-map "z\C-m" 'vip-line-to-top)
-(define-key vip-mode-map "z." 'vip-line-to-middle)
-(define-key vip-mode-map "z-" 'vip-line-to-bottom)
-
-(define-key vip-mode-map "{" 'vip-backward-paragraph)
-(define-key vip-mode-map "|" 'vip-goto-col)
-(define-key vip-mode-map "}" 'vip-forward-paragraph)
-(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"))
-
-
-;; implement ex commands
-
-(defvar ex-token-type nil
- "type of token. if non-nil, gives type of address. if nil, it
-is a command.")
-
-(defvar ex-token nil
- "value of token.")
-
-(defvar ex-addresses nil
- "list of ex addresses")
-
-(defvar ex-flag nil
- "flag for ex flag")
-
-(defvar ex-buffer nil
- "name of ex buffer")
-
-(defvar ex-count nil
- "value of ex count")
-
-(defvar ex-g-flag nil
- "flag for global command")
-
-(defvar ex-g-variant nil
- "if t global command is executed on lines not matching ex-g-pat")
-
-(defvar ex-reg-exp nil
- "save reg-exp used in substitute")
-
-(defvar ex-repl nil
- "replace pattern for substitute")
-
-(defvar ex-g-pat nil
- "pattern for global command")
-
-(defvar ex-map (make-sparse-keymap)
- "save commands for mapped keys")
-
-(defvar ex-tag nil
- "save ex tag")
-
-(defvar ex-file nil)
-
-(defvar ex-variant nil)
-
-(defvar ex-offset nil)
-
-(defvar ex-append nil)
-
-(defun vip-nil ()
- (interactive)
- (error ""))
-
-(defun vip-looking-back (str)
- "returns t if looking back reg-exp STR before point."
- (and (save-excursion (re-search-backward str nil t))
- (= (point) (match-end 0))))
-
-(defun vip-check-sub (str)
- "check if ex-token is an initial segment of STR"
- (let ((length (length ex-token)))
- (if (and (<= length (length str))
- (string= ex-token (substring str 0 length)))
- (setq ex-token str)
- (setq ex-token-type "non-command"))))
-
-(defun vip-get-ex-com-subr ()
- "get a complete ex command"
- (set-mark (point))
- (re-search-forward "[a-z][a-z]*")
- (setq ex-token-type "command")
- (setq ex-token (buffer-substring (point) (mark)))
- (exchange-point-and-mark)
- (cond ((looking-at "a")
- (cond ((looking-at "ab") (vip-check-sub "abbreviate"))
- ((looking-at "ar") (vip-check-sub "args"))
- (t (vip-check-sub "append"))))
- ((looking-at "[bh]") (setq ex-token-type "non-command"))
- ((looking-at "c")
- (if (looking-at "co") (vip-check-sub "copy")
- (vip-check-sub "change")))
- ((looking-at "d") (vip-check-sub "delete"))
- ((looking-at "e")
- (if (looking-at "ex") (vip-check-sub "ex")
- (vip-check-sub "edit")))
- ((looking-at "f") (vip-check-sub "file"))
- ((looking-at "g") (vip-check-sub "global"))
- ((looking-at "i") (vip-check-sub "insert"))
- ((looking-at "j") (vip-check-sub "join"))
- ((looking-at "l") (vip-check-sub "list"))
- ((looking-at "m")
- (cond ((looking-at "map") (vip-check-sub "map"))
- ((looking-at "mar") (vip-check-sub "mark"))
- (t (vip-check-sub "move"))))
- ((looking-at "n")
- (if (looking-at "nu") (vip-check-sub "number")
- (vip-check-sub "next")))
- ((looking-at "o") (vip-check-sub "open"))
- ((looking-at "p")
- (cond ((looking-at "pre") (vip-check-sub "preserve"))
- ((looking-at "pu") (vip-check-sub "put"))
- (t (vip-check-sub "print"))))
- ((looking-at "q") (vip-check-sub "quit"))
- ((looking-at "r")
- (cond ((looking-at "rec") (vip-check-sub "recover"))
- ((looking-at "rew") (vip-check-sub "rewind"))
- (t (vip-check-sub "read"))))
- ((looking-at "s")
- (cond ((looking-at "se") (vip-check-sub "set"))
- ((looking-at "sh") (vip-check-sub "shell"))
- ((looking-at "so") (vip-check-sub "source"))
- ((looking-at "st") (vip-check-sub "stop"))
- (t (vip-check-sub "substitute"))))
- ((looking-at "t")
- (if (looking-at "ta") (vip-check-sub "tag")
- (vip-check-sub "t")))
- ((looking-at "u")
- (cond ((looking-at "una") (vip-check-sub "unabbreviate"))
- ((looking-at "unm") (vip-check-sub "unmap"))
- (t (vip-check-sub "undo"))))
- ((looking-at "v")
- (cond ((looking-at "ve") (vip-check-sub "version"))
- ((looking-at "vi") (vip-check-sub "visual"))
- (t (vip-check-sub "v"))))
- ((looking-at "w")
- (if (looking-at "wq") (vip-check-sub "wq")
- (vip-check-sub "write")))
- ((looking-at "x") (vip-check-sub "xit"))
- ((looking-at "y") (vip-check-sub "yank"))
- ((looking-at "z") (vip-check-sub "z")))
- (exchange-point-and-mark))
-
-(defun vip-get-ex-token ()
- "get an ex-token which is either an address or a command.
-a token has type \(command, address, end-mark\) and value."
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (skip-chars-forward " \t")
- (cond ((looking-at "[k#]")
- (setq ex-token-type "command")
- (setq ex-token (char-to-string (following-char)))
- (forward-char 1))
- ((looking-at "[a-z]") (vip-get-ex-com-subr))
- ((looking-at "\\.")
- (forward-char 1)
- (setq ex-token-type "dot"))
- ((looking-at "[0-9]")
- (set-mark (point))
- (re-search-forward "[0-9]*")
- (setq ex-token-type
- (cond ((string= ex-token-type "plus") "add-number")
- ((string= ex-token-type "minus") "sub-number")
- (t "abs-number")))
- (setq ex-token (string-to-int (buffer-substring (point) (mark)))))
- ((looking-at "\\$")
- (forward-char 1)
- (setq ex-token-type "end"))
- ((looking-at "%")
- (forward-char 1)
- (setq ex-token-type "whole"))
- ((looking-at "+")
- (cond ((or (looking-at "+[-+]") (looking-at "+[\n|]"))
- (forward-char 1)
- (insert "1")
- (backward-char 1)
- (setq ex-token-type "plus"))
- ((looking-at "+[0-9]")
- (forward-char 1)
- (setq ex-token-type "plus"))
- (t
- (error "Badly formed address"))))
- ((looking-at "-")
- (cond ((or (looking-at "-[-+]") (looking-at "-[\n|]"))
- (forward-char 1)
- (insert "1")
- (backward-char 1)
- (setq ex-token-type "minus"))
- ((looking-at "-[0-9]")
- (forward-char 1)
- (setq ex-token-type "minus"))
- (t
- (error "Badly formed address"))))
- ((looking-at "/")
- (forward-char 1)
- (set-mark (point))
- (let ((cont t))
- (while (and (not (eolp)) cont)
- ;;(re-search-forward "[^/]*/")
- (re-search-forward "[^/]*\\(/\\|\n\\)")
- (if (not (vip-looking-back "[^\\\\]\\(\\\\\\\\\\)*\\\\/"))
- (setq cont nil))))
- (backward-char 1)
- (setq ex-token (buffer-substring (point) (mark)))
- (if (looking-at "/") (forward-char 1))
- (setq ex-token-type "search-forward"))
- ((looking-at "\\?")
- (forward-char 1)
- (set-mark (point))
- (let ((cont t))
- (while (and (not (eolp)) cont)
- ;;(re-search-forward "[^\\?]*\\?")
- (re-search-forward "[^\\?]*\\(\\?\\|\n\\)")
- (if (not (vip-looking-back "[^\\\\]\\(\\\\\\\\\\)*\\\\\\?"))
- (setq cont nil))
- (backward-char 1)
- (if (not (looking-at "\n")) (forward-char 1))))
- (setq ex-token-type "search-backward")
- (setq ex-token (buffer-substring (1- (point)) (mark))))
- ((looking-at ",")
- (forward-char 1)
- (setq ex-token-type "comma"))
- ((looking-at ";")
- (forward-char 1)
- (setq ex-token-type "semi-colon"))
- ((looking-at "[!=><&~]")
- (setq ex-token-type "command")
- (setq ex-token (char-to-string (following-char)))
- (forward-char 1))
- ((looking-at "'")
- (setq ex-token-type "goto-mark")
- (forward-char 1)
- (cond ((looking-at "'") (setq ex-token nil))
- ((looking-at "[a-z]") (setq ex-token (following-char)))
- (t (error "Marks are ' and a-z")))
- (forward-char 1))
- ((looking-at "\n")
- (setq ex-token-type "end-mark")
- (setq ex-token "goto"))
- (t
- (error "illegal token")))))
-
-(defun vip-ex (&optional string)
- "ex commands within VIP."
- (interactive)
- (or string
- (setq ex-g-flag nil
- ex-g-variant nil))
- (let ((com-str (or string (vip-read-string ":")))
- (address nil) (cont t) (dot (point)))
- (save-window-excursion
- (set-buffer (get-buffer-create " *ex-working-space*"))
- (delete-region (point-min) (point-max))
- (insert com-str "\n")
- (goto-char (point-min)))
- (setq ex-token-type "")
- (setq ex-addresses nil)
- (while cont
- (vip-get-ex-token)
- (cond ((or (string= ex-token-type "command")
- (string= ex-token-type "end-mark"))
- (if address (setq ex-addresses (cons address ex-addresses)))
- (cond ((string= ex-token "global")
- (ex-global nil)
- (setq cont nil))
- ((string= ex-token "v")
- (ex-global t)
- (setq cont nil))
- (t
- (vip-execute-ex-command)
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (skip-chars-forward " \t")
- (cond ((looking-at "|")
- (forward-char 1))
- ((looking-at "\n")
- (setq cont nil))
- (t (error "Extra character at end of a command")))))))
- ((string= ex-token-type "non-command")
- (error (format "%s: Not an editor command" ex-token)))
- ((string= ex-token-type "whole")
- (setq ex-addresses
- (cons (point-max) (cons (point-min) ex-addresses))))
- ((string= ex-token-type "comma")
- (setq ex-addresses
- (cons (if (null address) (point) address) ex-addresses)))
- ((string= ex-token-type "semi-colon")
- (if address (setq dot address))
- (setq ex-addresses
- (cons (if (null address) (point) address) ex-addresses)))
- (t (let ((ans (vip-get-ex-address-subr address dot)))
- (if ans (setq address ans))))))))
-
-(defun vip-get-ex-pat ()
- "get a regular expression and set ex-variant if found"
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (skip-chars-forward " \t")
- (if (looking-at "!")
- (progn
- (setq ex-g-variant (not ex-g-variant)
- ex-g-flag (not ex-g-flag))
- (forward-char 1)
- (skip-chars-forward " \t")))
- (if (looking-at "/")
- (progn
- (forward-char 1)
- (set-mark (point))
- (let ((cont t))
- (while (and (not (eolp)) cont)
- (re-search-forward "[^/]*\\(/\\|\n\\)")
- ;;(re-search-forward "[^/]*/")
- (if (not (vip-looking-back "[^\\\\]\\(\\\\\\\\\\)*\\\\/"))
- (setq cont nil))))
- (setq ex-token
- (if (= (mark) (point)) ""
- (buffer-substring (1- (point)) (mark))))
- (backward-char 1))
- (setq ex-token nil))))
-
-(defun vip-get-ex-command ()
- "get an ex command"
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (if (looking-at "/") (forward-char 1))
- (skip-chars-forward " \t")
- (cond ((looking-at "[a-z]")
- (vip-get-ex-com-subr)
- (if (string= ex-token-type "non-command")
- (error "%s: not an editor command" ex-token)))
- ((looking-at "[!=><&~]")
- (setq ex-token (char-to-string (following-char)))
- (forward-char 1))
- (t (error "Could not find an ex command")))))
-
-(defun vip-get-ex-opt-gc ()
- "get an ex option g or c"
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (if (looking-at "/") (forward-char 1))
- (skip-chars-forward " \t")
- (cond ((looking-at "g")
- (setq ex-token "g")
- (forward-char 1)
- t)
- ((looking-at "c")
- (setq ex-token "c")
- (forward-char 1)
- t)
- (t nil))))
-
-(defun vip-default-ex-addresses (&optional whole-flag)
- "compute default addresses. whole-flag means whole buffer."
- (cond ((null ex-addresses)
- (setq ex-addresses
- (if whole-flag
- (cons (point-max) (cons (point-min) nil))
- (cons (point) (cons (point) nil)))))
- ((null (cdr ex-addresses))
- (setq ex-addresses
- (cons (car ex-addresses) ex-addresses)))))
-
-(defun vip-get-ex-address ()
- "get an ex-address as a marker and set ex-flag if a flag is found"
- (let ((address (point-marker)) (cont t))
- (setq ex-token "")
- (setq ex-flag nil)
- (while cont
- (vip-get-ex-token)
- (cond ((string= ex-token-type "command")
- (if (or (string= ex-token "print") (string= ex-token "list")
- (string= ex-token "#"))
- (progn
- (setq ex-flag t)
- (setq cont nil))
- (error "address expected")))
- ((string= ex-token-type "end-mark")
- (setq cont nil))
- ((string= ex-token-type "whole")
- (error "a trailing address is expected"))
- ((string= ex-token-type "comma")
- (error "Extra characters after an address"))
- (t (let ((ans (vip-get-ex-address-subr address (point-marker))))
- (if ans (setq address ans))))))
- address))
-
-(defun vip-get-ex-address-subr (old-address dot)
- "returns an address as a point"
- (let ((address nil))
- (if (null old-address) (setq old-address dot))
- (cond ((string= ex-token-type "dot")
- (setq address dot))
- ((string= ex-token-type "add-number")
- (save-excursion
- (goto-char old-address)
- (forward-line (if (= old-address 0) (1- ex-token) ex-token))
- (setq address (point-marker))))
- ((string= ex-token-type "sub-number")
- (save-excursion
- (goto-char old-address)
- (forward-line (- ex-token))
- (setq address (point-marker))))
- ((string= ex-token-type "abs-number")
- (save-excursion
- (goto-char (point-min))
- (if (= ex-token 0) (setq address 0)
- (forward-line (1- ex-token))
- (setq address (point-marker)))))
- ((string= ex-token-type "end")
- (setq address (point-max-marker)))
- ((string= ex-token-type "plus") t);; do nothing
- ((string= ex-token-type "minus") t);; do nothing
- ((string= ex-token-type "search-forward")
- (save-excursion
- (ex-search-address t)
- (setq address (point-marker))))
- ((string= ex-token-type "search-backward")
- (save-excursion
- (ex-search-address nil)
- (setq address (point-marker))))
- ((string= ex-token-type "goto-mark")
- (save-excursion
- (if (null ex-token)
- (exchange-point-and-mark)
- (goto-char (register-to-point (- ex-token (- ?a ?\C-a)))))
- (setq address (point-marker)))))
- address))
-
-(defun ex-search-address (forward)
- "search pattern and set address"
- (if (string= ex-token "")
- (if (null vip-s-string) (error "No previous search string")
- (setq ex-token vip-s-string))
- (setq vip-s-string ex-token))
- (if forward
- (progn
- (forward-line 1)
- (re-search-forward ex-token))
- (forward-line -1)
- (re-search-backward ex-token)))
-
-(defun vip-get-ex-buffer ()
- "get a buffer name and set ex-count and ex-flag if found"
- (setq ex-buffer nil)
- (setq ex-count nil)
- (setq ex-flag nil)
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (skip-chars-forward " \t")
- (if (looking-at "[a-zA-Z]")
- (progn
- (setq ex-buffer (following-char))
- (forward-char 1)
- (skip-chars-forward " \t")))
- (if (looking-at "[0-9]")
- (progn
- (set-mark (point))
- (re-search-forward "[0-9][0-9]*")
- (setq ex-count (string-to-int (buffer-substring (point) (mark))))
- (skip-chars-forward " \t")))
- (if (looking-at "[pl#]")
- (progn
- (setq ex-flag t)
- (forward-char 1)))
- (if (not (looking-at "[\n|]"))
- (error "Illegal extra characters"))))
-
-(defun vip-get-ex-count ()
- (setq ex-variant nil
- ex-count nil
- ex-flag nil)
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (skip-chars-forward " \t")
- (if (looking-at "!")
- (progn
- (setq ex-variant t)
- (forward-char 1)))
- (skip-chars-forward " \t")
- (if (looking-at "[0-9]")
- (progn
- (set-mark (point))
- (re-search-forward "[0-9][0-9]*")
- (setq ex-count (string-to-int (buffer-substring (point) (mark))))
- (skip-chars-forward " \t")))
- (if (looking-at "[pl#]")
- (progn
- (setq ex-flag t)
- (forward-char 1)))
- (if (not (looking-at "[\n|]"))
- (error "Illegal extra characters"))))
-
-(defun vip-get-ex-file ()
- "get a file name and set ex-variant, ex-append and ex-offset if found"
- (setq ex-file nil
- ex-variant nil
- ex-append nil
- ex-offset nil)
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (skip-chars-forward " \t")
- (if (looking-at "!")
- (progn
- (setq ex-variant t)
- (forward-char 1)
- (skip-chars-forward " \t")))
- (if (looking-at ">>")
- (progn
- (setq ex-append t
- ex-variant t)
- (forward-char 2)
- (skip-chars-forward " \t")))
- (if (looking-at "+")
- (progn
- (forward-char 1)
- (set-mark (point))
- (re-search-forward "[ \t\n]")
- (backward-char 1)
- (setq ex-offset (buffer-substring (point) (mark)))
- (forward-char 1)
- (skip-chars-forward " \t")))
- (set-mark (point))
- (re-search-forward "[ \t\n]")
- (backward-char 1)
- (setq ex-file (buffer-substring (point) (mark)))))
-
-(defun vip-execute-ex-command ()
- "execute ex command using the value of addresses."
- (cond ((string= ex-token "goto") (ex-goto))
- ((string= ex-token "copy") (ex-copy nil))
- ((string= ex-token "delete") (ex-delete))
- ((string= ex-token "edit") (ex-edit))
- ((string= ex-token "file") (vip-info-on-file))
- ;((string= ex-token "global") (ex-global nil))
- ((string= ex-token "join") (ex-line "join"))
- ((string= ex-token "k") (ex-mark))
- ((string= ex-token "mark") (ex-mark))
- ((string= ex-token "map") (ex-map))
- ((string= ex-token "move") (ex-copy t))
- ((string= ex-token "put") (ex-put))
- ((string= ex-token "quit") (ex-quit))
- ((string= ex-token "read") (ex-read))
- ((string= ex-token "set") (ex-set))
- ((string= ex-token "shell") (ex-shell))
- ((string= ex-token "substitute") (ex-substitute))
- ((string= ex-token "stop") (suspend-emacs))
- ((string= ex-token "t") (ex-copy nil))
- ((string= ex-token "tag") (ex-tag))
- ((string= ex-token "undo") (vip-undo))
- ((string= ex-token "unmap") (ex-unmap))
- ;((string= ex-token "v") (ex-global t))
- ((string= ex-token "version") (vip-version))
- ((string= ex-token "visual") (ex-edit))
- ((string= ex-token "write") (ex-write nil))
- ((string= ex-token "wq") (ex-write t))
- ((string= ex-token "yank") (ex-yank))
- ((string= ex-token "!") (ex-command))
- ((string= ex-token "=") (ex-line-no))
- ((string= ex-token ">") (ex-line "right"))
- ((string= ex-token "<") (ex-line "left"))
- ((string= ex-token "&") (ex-substitute t))
- ((string= ex-token "~") (ex-substitute t t))
- ((or (string= ex-token "append")
- (string= ex-token "args")
- (string= ex-token "change")
- (string= ex-token "insert")
- (string= ex-token "open")
- )
- (error "%s: no such command from VIP" ex-token))
- ((or (string= ex-token "abbreviate")
- (string= ex-token "list")
- (string= ex-token "next")
- (string= ex-token "print")
- (string= ex-token "preserve")
- (string= ex-token "recover")
- (string= ex-token "rewind")
- (string= ex-token "source")
- (string= ex-token "unabbreviate")
- (string= ex-token "xit")
- (string= ex-token "z")
- )
- (error "%s: not implemented in VIP" ex-token))
- (t (error "%s: Not an editor command" ex-token))))
-
-(defun ex-goto ()
- "ex goto command"
- (if (null ex-addresses)
- (setq ex-addresses (cons (point) nil)))
- (push-mark (point))
- (goto-char (car ex-addresses))
- (beginning-of-line))
-
-(defun ex-copy (del-flag)
- "ex copy and move command. DEL-FLAG means delete."
- (vip-default-ex-addresses)
- (let ((address (vip-get-ex-address))
- (end (car ex-addresses)) (beg (car (cdr ex-addresses))))
- (goto-char end)
- (save-excursion
- (set-mark beg)
- (vip-enlarge-region (mark) (point))
- (if del-flag (kill-region (point) (mark))
- (copy-region-as-kill (point) (mark)))
- (if ex-flag
- (progn
- (with-output-to-temp-buffer "*copy text*"
- (princ
- (if (or del-flag ex-g-flag ex-g-variant)
- (current-kill 0)
- (buffer-substring (point) (mark)))))
- (condition-case nil
- (progn
- (vip-read-string "[Hit return to continue] ")
- (save-excursion (kill-buffer "*copy text*")))
- (quit
- (save-excursion (kill-buffer "*copy text*"))
- (signal 'quit nil))))))
- (if (= address 0)
- (goto-char (point-min))
- (goto-char address)
- (forward-line 1))
- (insert (current-kill 0))))
-
-(defun ex-delete ()
- "ex delete"
- (vip-default-ex-addresses)
- (vip-get-ex-buffer)
- (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
- (if (> beg end) (error "First address exceeds second"))
- (save-excursion
- (vip-enlarge-region beg end)
- (exchange-point-and-mark)
- (if ex-count
- (progn
- (set-mark (point))
- (forward-line (1- ex-count)))
- (set-mark end))
- (vip-enlarge-region (point) (mark))
- (if ex-flag
- ;; show text to be deleted and ask for confirmation
- (progn
- (with-output-to-temp-buffer " *delete text*"
- (princ (buffer-substring (point) (mark))))
- (condition-case conditions
- (vip-read-string "[Hit return to continue] ")
- (quit
- (save-excursion (kill-buffer " *delete text*"))
- (error "")))
- (save-excursion (kill-buffer " *delete text*")))
- (if ex-buffer
- (if (and (<= ?A ex-buffer) (<= ex-buffer ?Z))
- (vip-append-to-register
- (+ ex-buffer 32) (point) (mark))
- (copy-to-register ex-buffer (point) (mark) nil)))
- (delete-region (point) (mark))))))
-
-(defun ex-edit ()
- "ex-edit"
- (vip-get-ex-file)
- (if (and (not ex-variant) (buffer-modified-p) buffer-file-name)
- (error "No write since last change \(:e! overrides\)"))
- (vip-change-mode-to-emacs)
- (set-buffer
- (find-file-noselect (concat default-directory ex-file)))
- (vip-change-mode-to-vi)
- (goto-char (point-min))
- (if ex-offset
- (progn
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (delete-region (point-min) (point-max))
- (insert ex-offset "\n")
- (goto-char (point-min)))
- (goto-char (vip-get-ex-address))
- (beginning-of-line))))
-
-(defun ex-global (variant)
- "ex global command"
- (if (or ex-g-flag ex-g-variant)
- (error "Global within global not allowed")
- (if variant
- (setq ex-g-flag nil
- ex-g-variant t)
- (setq ex-g-flag t
- ex-g-variant nil)))
- (vip-get-ex-pat)
- (if (null ex-token)
- (error "Missing regular expression for global command"))
- (if (string= ex-token "")
- (if (null vip-s-string) (error "No previous search string")
- (setq ex-g-pat vip-s-string))
- (setq ex-g-pat ex-token
- vip-s-string ex-token))
- (if (null ex-addresses)
- (setq ex-addresses (list (point-max) (point-min))))
- (let ((marks nil) (mark-count 0)
- com-str (end (car ex-addresses)) (beg (car (cdr ex-addresses))))
- (if (> beg end) (error "First address exceeds second"))
- (save-excursion
- (vip-enlarge-region beg end)
- (exchange-point-and-mark)
- (let ((cont t) (limit (point-marker)))
- (exchange-point-and-mark)
- ;; skip the last line if empty
- (beginning-of-line)
- (if (and (eobp) (not (bobp))) (backward-char 1))
- (while (and cont (not (bobp)) (>= (point) limit))
- (beginning-of-line)
- (set-mark (point))
- (end-of-line)
- (let ((found (re-search-backward ex-g-pat (mark) t)))
- (if (or (and ex-g-flag found)
- (and ex-g-variant (not found)))
- (progn
- (end-of-line)
- (setq mark-count (1+ mark-count))
- (setq marks (cons (point-marker) marks)))))
- (beginning-of-line)
- (if (bobp) (setq cont nil)
- (forward-line -1)
- (end-of-line)))))
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (setq com-str (buffer-substring (1+ (point)) (1- (point-max)))))
- (while marks
- (goto-char (car marks))
- ; report progress of execution on a slow machine.
- ;(message "Executing global command...")
- ;(if (zerop (% mark-count 10))
- ;(message "Executing global command...%d" mark-count))
- (vip-ex com-str)
- (setq mark-count (1- mark-count))
- (setq marks (cdr marks)))))
- ;(message "Executing global command...done")))
-
-(defun ex-line (com)
- "ex line commands. COM is join, shift-right or shift-left."
- (vip-default-ex-addresses)
- (vip-get-ex-count)
- (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))) point)
- (if (> beg end) (error "First address exceeds second"))
- (save-excursion
- (vip-enlarge-region beg end)
- (exchange-point-and-mark)
- (if ex-count
- (progn
- (set-mark (point))
- (forward-line ex-count)))
- (if ex-flag
- ;; show text to be joined and ask for confirmation
- (progn
- (with-output-to-temp-buffer " *text*"
- (princ (buffer-substring (point) (mark))))
- (condition-case conditions
- (progn
- (vip-read-string "[Hit return to continue] ")
- (ex-line-subr com (point) (mark)))
- (quit
- (ding)))
- (save-excursion (kill-buffer " *text*")))
- (ex-line-subr com (point) (mark)))
- (setq point (point)))
- (goto-char (1- point))
- (beginning-of-line)))
-
-(defun ex-line-subr (com beg end)
- (cond ((string= com "join")
- (goto-char (min beg end))
- (while (and (not (eobp)) (< (point) (max beg end)))
- (end-of-line)
- (if (and (<= (point) (max beg end)) (not (eobp)))
- (progn
- (forward-line 1)
- (delete-region (point) (1- (point)))
- (if (not ex-variant) (fixup-whitespace))))))
- ((or (string= com "right") (string= com "left"))
- (indent-rigidly
- (min beg end) (max beg end)
- (if (string= com "right") vip-shift-width (- vip-shift-width)))
- (goto-char (max beg end))
- (end-of-line)
- (forward-char 1))))
-
-(defun ex-mark ()
- "ex mark"
- (let (char)
- (if (null ex-addresses)
- (setq ex-addresses
- (cons (point) nil)))
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (skip-chars-forward " \t")
- (if (looking-at "[a-z]")
- (progn
- (setq char (following-char))
- (forward-char 1)
- (skip-chars-forward " \t")
- (if (not (looking-at "[\n|]"))
- (error "Extra characters at end of \"k\" command")))
- (if (looking-at "[\n|]")
- (error "\"k\" requires a following letter")
- (error "Mark must specify a letter"))))
- (save-excursion
- (goto-char (car ex-addresses))
- (point-to-register (- char (- ?a ?\C-a)) nil))))
-
-(defun ex-map ()
- "ex map"
- (let (char string)
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (skip-chars-forward " \t")
- (setq char (char-to-string (following-char)))
- (forward-char 1)
- (skip-chars-forward " \t")
- (if (looking-at "[\n|]") (error "Missing rhs"))
- (set-mark (point))
- (end-of-buffer)
- (backward-char 1)
- (setq string (buffer-substring (mark) (point))))
- (if (not (lookup-key ex-map char))
- (define-key ex-map char
- (or (lookup-key vip-mode-map char) 'vip-nil)))
- (define-key vip-mode-map char
- (eval
- (list 'quote
- (cons 'lambda
- (list '(count)
- '(interactive "p")
- (list 'execute-kbd-macro string 'count))))))))
-
-(defun ex-unmap ()
- "ex unmap"
- (let (char)
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (skip-chars-forward " \t")
- (setq char (char-to-string (following-char)))
- (forward-char 1)
- (skip-chars-forward " \t")
- (if (not (looking-at "[\n|]")) (error "Macro must be a character")))
- (if (not (lookup-key ex-map char))
- (error "That macro wasn't mapped"))
- (define-key vip-mode-map char (lookup-key ex-map char))
- (define-key ex-map char nil)))
-
-(defun ex-put ()
- "ex put"
- (let ((point (if (null ex-addresses) (point) (car ex-addresses))))
- (vip-get-ex-buffer)
- (setq vip-use-register ex-buffer)
- (goto-char point)
- (if (= point 0) (vip-Put-back 1) (vip-put-back 1))))
-
-(defun ex-quit ()
- "ex quit"
- (let (char)
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (skip-chars-forward " \t")
- (setq char (following-char)))
- (if (= char ?!) (kill-emacs t) (save-buffers-kill-emacs))))
-
-(defun ex-read ()
- "ex read"
- (let ((point (if (null ex-addresses) (point) (car ex-addresses)))
- (variant nil) command file)
- (goto-char point)
- (if (not (= point 0)) (next-line 1))
- (beginning-of-line)
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (skip-chars-forward " \t")
- (if (looking-at "!")
- (progn
- (setq variant t)
- (forward-char 1)
- (skip-chars-forward " \t")
- (set-mark (point))
- (end-of-line)
- (setq command (buffer-substring (mark) (point))))
- (set-mark (point))
- (re-search-forward "[ \t\n]")
- (backward-char 1)
- (setq file (buffer-substring (point) (mark)))))
- (if variant
- (shell-command command t)
- (insert-file file))))
-
-(defun ex-set ()
- (eval (list 'setq
- (read-variable "Variable: ")
- (eval (read-minibuffer "Value: ")))))
-
-(defun ex-shell ()
- "ex shell"
- (vip-change-mode-to-emacs)
- (shell))
-
-(defun ex-substitute (&optional repeat r-flag)
- "ex substitute.
-If REPEAT use previous reg-exp which is ex-reg-exp or
-vip-s-string"
- (let (pat repl (opt-g nil) (opt-c nil) (matched-pos nil))
- (if repeat (setq ex-token nil) (vip-get-ex-pat))
- (if (null ex-token)
- (setq pat (if r-flag vip-s-string ex-reg-exp)
- repl ex-repl)
- (setq pat (if (string= ex-token "") vip-s-string ex-token))
- (setq vip-s-string pat
- ex-reg-exp pat)
- (vip-get-ex-pat)
- (if (null ex-token)
- (setq ex-token ""
- ex-repl "")
- (setq repl ex-token
- ex-repl ex-token)))
- (while (vip-get-ex-opt-gc)
- (if (string= ex-token "g") (setq opt-g t) (setq opt-c t)))
- (vip-get-ex-count)
- (if ex-count
- (save-excursion
- (if ex-addresses (goto-char (car ex-addresses)))
- (set-mark (point))
- (forward-line (1- ex-count))
- (setq ex-addresses (cons (point) (cons (mark) nil))))
- (if (null ex-addresses)
- (setq ex-addresses (cons (point) (cons (point) nil)))
- (if (null (cdr ex-addresses))
- (setq ex-addresses (cons (car ex-addresses) ex-addresses)))))
- ;(setq G opt-g)
- (let ((beg (car ex-addresses)) (end (car (cdr ex-addresses)))
- (cont t) eol-mark)
- (save-excursion
- (vip-enlarge-region beg end)
- (let ((limit (save-excursion
- (goto-char (max (point) (mark)))
- (point-marker))))
- (goto-char (min (point) (mark)))
- (while (< (point) limit)
- (end-of-line)
- (setq eol-mark (point-marker))
- (beginning-of-line)
- (if opt-g
- (progn
- (while (and (not (eolp))
- (re-search-forward pat eol-mark t))
- (if (or (not opt-c) (y-or-n-p "Replace? "))
- (progn
- (setq matched-pos (point))
- (replace-match repl))))
- (end-of-line)
- (forward-char))
- (if (and (re-search-forward pat eol-mark t)
- (or (not opt-c) (y-or-n-p "Replace? ")))
- (progn
- (setq matched-pos (point))
- (replace-match repl)))
- (end-of-line)
- (forward-char))))))
- (if matched-pos (goto-char matched-pos))
- (beginning-of-line)
- (if opt-c (message "done"))))
-
-(defun ex-tag ()
- "ex tag"
- (let (tag)
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (skip-chars-forward " \t")
- (set-mark (point))
- (skip-chars-forward "^ |\t\n")
- (setq tag (buffer-substring (mark) (point))))
- (if (not (string= tag "")) (setq ex-tag tag))
- (vip-change-mode-to-emacs)
- (condition-case conditions
- (progn
- (if (string= tag "")
- (find-tag ex-tag t)
- (find-tag-other-window ex-tag))
- (vip-change-mode-to-vi))
- (error
- (vip-change-mode-to-vi)
- (vip-message-conditions conditions)))))
-
-(defun ex-write (q-flag)
- "ex write"
- (vip-default-ex-addresses t)
- (vip-get-ex-file)
- (if (string= ex-file "")
- (progn
- (if (null buffer-file-name)
- (error "No file associated with this buffer"))
- (setq ex-file buffer-file-name))
- (setq ex-file (expand-file-name ex-file)))
- (if (and (not (string= ex-file (buffer-file-name)))
- (file-exists-p ex-file)
- (not ex-variant))
- (error "\"%s\" File exists - use w! to override" ex-file))
- (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
- (if (> beg end) (error "First address exceeds second"))
- (save-excursion
- (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)))
-
-(defun ex-yank ()
- "ex yank"
- (vip-default-ex-addresses)
- (vip-get-ex-buffer)
- (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
- (if (> beg end) (error "First address exceeds second"))
- (save-excursion
- (vip-enlarge-region beg end)
- (exchange-point-and-mark)
- (if (or ex-g-flag ex-g-variant) (error "Can't yank within global"))
- (if ex-count
- (progn
- (set-mark (point))
- (forward-line (1- ex-count)))
- (set-mark end))
- (vip-enlarge-region (point) (mark))
- (if ex-flag (error "Extra characters at end of command"))
- (if ex-buffer
- (copy-to-register ex-buffer (point) (mark) nil))
- (copy-region-as-kill (point) (mark)))))
-
-(defun ex-command ()
- "execute shell command"
- (let (command)
- (save-window-excursion
- (set-buffer " *ex-working-space*")
- (skip-chars-forward " \t")
- (set-mark (point))
- (end-of-line)
- (setq command (buffer-substring (mark) (point))))
- (if (null ex-addresses)
- (shell-command command)
- (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
- (if (null beg) (setq beg end))
- (save-excursion
- (goto-char beg)
- (set-mark end)
- (vip-enlarge-region (point) (mark))
- (shell-command-on-region (point) (mark) command t))
- (goto-char beg)))))
-
-(defun ex-line-no ()
- "print line number"
- (message "%d"
- (1+ (count-lines
- (point-min)
- (if (null ex-addresses) (point-max) (car ex-addresses))))))
-
-(if (file-exists-p vip-startup-file) (load vip-startup-file))
-
-;;; vip.el ends here
diff --git a/lisp/emulation/viper-ex.el b/lisp/emulation/viper-ex.el
deleted file mode 100644
index 93846321476..00000000000
--- a/lisp/emulation/viper-ex.el
+++ /dev/null
@@ -1,2029 +0,0 @@
-;;; viper-ex.el --- functions implementing the Ex commands for Viper
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-
-;; Code
-
-(require 'viper-util)
-
-;; Compiler pacifier
-(defvar read-file-name-map)
-;; end compiler pacifier
-
-;;; Variables
-
-(defconst vip-ex-work-buf-name " *ex-working-space*")
-(defconst vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
-(defconst vip-ex-tmp-buf-name " *ex-tmp*")
-
-
-;;; Variable completion in :set command
-
-;; The list of Ex commands. Used for completing command names.
-(defconst ex-token-alist
- '(("!") ("=") (">") ("&") ("~")
- ("yank") ("xit") ("WWrite") ("Write") ("write") ("wq") ("visual")
- ("version") ("vglobal") ("unmap") ("undo") ("tag") ("transfer") ("suspend")
- ("substitute") ("submitReport") ("stop") ("sr") ("source") ("shell")
- ("set") ("rewind") ("recover") ("read") ("quit") ("pwd")
- ("put") ("preserve") ("PreviousRelatedFile") ("RelatedFile")
- ("next") ("Next") ("move") ("mark") ("map") ("kmark") ("join")
- ("help") ("goto") ("global") ("file") ("edit") ("delete") ("copy")
- ("chdir") ("cd") ("Buffer") ("buffer") ("args")) )
-
-;; A-list of Ex variables that can be set using the :set command.
-(defconst ex-variable-alist
- '(("wrapscan") ("ws") ("wrapmargin") ("wm")
- ("global-tabstop") ("gts") ("tabstop") ("ts")
- ("showmatch") ("sm") ("shiftwidth") ("sw") ("shell") ("sh")
- ("readonly") ("ro")
- ("nowrapscan") ("nows") ("noshowmatch") ("nosm")
- ("noreadonly") ("noro") ("nomagic") ("noma")
- ("noignorecase") ("noic")
- ("global-noautoindent") ("gnoai") ("noautoindent") ("noai")
- ("magic") ("ma") ("ignorecase") ("ic")
- ("global-autoindent") ("gai") ("autoindent") ("ai")
- ))
-
-
-
-;; Token recognized during parsing of Ex commands (e.g., "read", "comma")
-(defvar ex-token nil)
-
-;; Type of token.
-;; If non-nil, gives type of address; if nil, it is a command.
-(defvar ex-token-type nil)
-
-;; List of addresses passed to Ex command
-(defvar ex-addresses nil)
-
-;; It seems that this flag is used only for `#', `print', and `list', which
-;; aren't implemented. Check later.
-(defvar ex-flag nil)
-
-;; "buffer" where Ex commands keep deleted data.
-;; In Emacs terms, this is a register.
-(defvar ex-buffer nil)
-
-;; Value of ex count.
-(defvar ex-count nil)
-
-;; Flag for global command.
-(defvar ex-g-flag nil)
-
-;; If t, global command is executed on lines not matching ex-g-pat.
-(defvar ex-g-variant nil)
-
-;; Save reg-exp used in substitute.
-(defvar ex-reg-exp nil)
-
-
-;; Replace pattern for substitute.
-(defvar ex-repl nil)
-
-;; Pattern for global command.
-(defvar ex-g-pat nil)
-
-
-(defvar ex-unix-type-shell
- (let ((case-fold-search t))
- (and (stringp shell-file-name)
- (string-match
- (concat
- "\\("
- "csh$\\|csh.exe$"
- "\\|"
- "ksh$\\|ksh.exe$"
- "\\|"
- "^sh$\\|sh.exe$"
- "\\|"
- "[^a-z]sh$\\|[^a-z]sh.exe$"
- "\\|"
- "bash$\\|bash.exe$"
- "\\)")
- shell-file-name)))
- "Is the user using a unix-type shell?")
-
-(defvar ex-unix-type-shell-options
- (let ((case-fold-search t))
- (if ex-unix-type-shell
- (cond ((string-match "\\(csh$\\|csh.exe$\\)" shell-file-name)
- "-f") ; csh: do it fast
- ((string-match "\\(bash$\\|bash.exe$\\)" shell-file-name)
- "-noprofile") ; bash: ignore .profile
- )))
- "Options to pass to the Unix-style shell.
-Don't put `-c' here, as it is added automatically.")
-
-(defvar ex-nontrivial-find-file-function
- (cond (ex-unix-type-shell 'vip-ex-nontrivial-find-file-unix)
- ((eq system-type 'emx) 'vip-ex-nontrivial-find-file-ms) ; OS/2
- (vip-ms-style-os-p 'vip-ex-nontrivial-find-file-ms) ; a Microsoft OS
- (vip-vms-os-p 'vip-ex-nontrivial-find-file-unix) ; VMS
- (t 'vip-ex-nontrivial-find-file-unix) ; presumably UNIX
- ))
-
-;; Remembers the previous Ex tag.
-(defvar ex-tag nil)
-
-;; file used by Ex commands like :r, :w, :n
-(defvar ex-file nil)
-
-;; If t, tells Ex that this is a variant-command, i.e., w>>, r!, etc.
-(defvar ex-variant nil)
-
-;; Specified the offset of an Ex command, such as :read.
-(defvar ex-offset nil)
-
-;; Tells Ex that this is a w>> command.
-(defvar ex-append nil)
-
-;; File containing the shell command to be executed at Ex prompt,
-;; e.g., :r !date
-(defvar ex-cmdfile nil)
-
-;; flag used in vip-ex-read-file-name to indicate that we may be reading
-;; multiple file names. Used for :edit and :next
-(defvar vip-keep-reading-filename nil)
-
-(defconst ex-cycle-other-window t
- "*If t, :n and :b cycles through files and buffers in other window.
-Then :N and :B cycles in the current window. If nil, this behavior is
-reversed.")
-
-(defconst ex-cycle-through-non-files nil
- "*Cycle through *scratch* and other buffers that don't visit any file.")
-
-;; Last shell command executed with :! command.
-(defvar vip-ex-last-shell-com nil)
-
-;; Indicates if Minibuffer was exited temporarily in Ex-command.
-(defvar vip-incomplete-ex-cmd nil)
-
-;; Remembers the last ex-command prompt.
-(defvar vip-last-ex-prompt "")
-
-
-;;; Code
-
-;; Check if ex-token is an initial segment of STR
-(defun vip-check-sub (str)
- (let ((length (length ex-token)))
- (if (and (<= length (length str))
- (string= ex-token (substring str 0 length)))
- (setq ex-token str)
- (setq ex-token-type 'non-command))))
-
-;; Get a complete ex command
-(defun vip-get-ex-com-subr ()
- (let (case-fold-search)
- (set-mark (point))
- (re-search-forward "[a-zA-Z][a-zA-Z]*")
- (setq ex-token-type 'command)
- (setq ex-token (buffer-substring (point) (mark t)))
- (exchange-point-and-mark)
- (cond ((looking-at "a")
- (cond ((looking-at "ab") (vip-check-sub "abbreviate"))
- ((looking-at "ar") (vip-check-sub "args"))
- (t (vip-check-sub "append"))))
- ((looking-at "h") (vip-check-sub "help"))
- ((looking-at "c")
- (cond ((looking-at "cd") (vip-check-sub "cd"))
- ((looking-at "ch") (vip-check-sub "chdir"))
- ((looking-at "co") (vip-check-sub "copy"))
- (t (vip-check-sub "change"))))
- ((looking-at "d") (vip-check-sub "delete"))
- ((looking-at "b") (vip-check-sub "buffer"))
- ((looking-at "B") (vip-check-sub "Buffer"))
- ((looking-at "e")
- (if (looking-at "ex") (vip-check-sub "ex")
- (vip-check-sub "edit")))
- ((looking-at "f") (vip-check-sub "file"))
- ((looking-at "g") (vip-check-sub "global"))
- ((looking-at "i") (vip-check-sub "insert"))
- ((looking-at "j") (vip-check-sub "join"))
- ((looking-at "l") (vip-check-sub "list"))
- ((looking-at "m")
- (cond ((looking-at "map") (vip-check-sub "map"))
- ((looking-at "mar") (vip-check-sub "mark"))
- (t (vip-check-sub "move"))))
- ((looking-at "k[a-z][^a-z]")
- (setq ex-token "kmark")
- (forward-char 1)
- (exchange-point-and-mark)) ; this is canceled out by another
- ; exchange-point-and-mark at the end
- ((looking-at "k") (vip-check-sub "kmark"))
- ((looking-at "n") (if (looking-at "nu")
- (vip-check-sub "number")
- (vip-check-sub "next")))
- ((looking-at "N") (vip-check-sub "Next"))
- ((looking-at "o") (vip-check-sub "open"))
- ((looking-at "p")
- (cond ((looking-at "pre") (vip-check-sub "preserve"))
- ((looking-at "pu") (vip-check-sub "put"))
- ((looking-at "pw") (vip-check-sub "pwd"))
- (t (vip-check-sub "print"))))
- ((looking-at "P") (vip-check-sub "PreviousRelatedFile"))
- ((looking-at "R") (vip-check-sub "RelatedFile"))
- ((looking-at "q") (vip-check-sub "quit"))
- ((looking-at "r")
- (cond ((looking-at "rec") (vip-check-sub "recover"))
- ((looking-at "rew") (vip-check-sub "rewind"))
- (t (vip-check-sub "read"))))
- ((looking-at "s")
- (cond ((looking-at "se") (vip-check-sub "set"))
- ((looking-at "sh") (vip-check-sub "shell"))
- ((looking-at "so") (vip-check-sub "source"))
- ((looking-at "sr") (vip-check-sub "sr"))
- ((looking-at "st") (vip-check-sub "stop"))
- ((looking-at "sus") (vip-check-sub "suspend"))
- ((looking-at "subm") (vip-check-sub "submitReport"))
- (t (vip-check-sub "substitute"))))
- ((looking-at "t")
- (if (looking-at "ta") (vip-check-sub "tag")
- (vip-check-sub "transfer")))
- ((looking-at "u")
- (cond ((looking-at "una") (vip-check-sub "unabbreviate"))
- ((looking-at "unm") (vip-check-sub "unmap"))
- (t (vip-check-sub "undo"))))
- ((looking-at "v")
- (cond ((looking-at "ve") (vip-check-sub "version"))
- ((looking-at "vi") (vip-check-sub "visual"))
- (t (vip-check-sub "vglobal"))))
- ((looking-at "w")
- (if (looking-at "wq") (vip-check-sub "wq")
- (vip-check-sub "write")))
- ((looking-at "W")
- (if (looking-at "WW")
- (vip-check-sub "WWrite")
- (vip-check-sub "Write")))
- ((looking-at "x") (vip-check-sub "xit"))
- ((looking-at "y") (vip-check-sub "yank"))
- ((looking-at "z") (vip-check-sub "z")))
- (exchange-point-and-mark)
- ))
-
-;; Get an ex-token which is either an address or a command.
-;; A token has a type, \(command, address, end-mark\), and a value
-(defun vip-get-ex-token ()
- (save-window-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (skip-chars-forward " \t|")
- (cond ((looking-at "#")
- (setq ex-token-type 'command)
- (setq ex-token (char-to-string (following-char)))
- (forward-char 1))
- ((looking-at "[a-z]") (vip-get-ex-com-subr))
- ((looking-at "\\.")
- (forward-char 1)
- (setq ex-token-type 'dot))
- ((looking-at "[0-9]")
- (set-mark (point))
- (re-search-forward "[0-9]*")
- (setq ex-token-type
- (cond ((eq ex-token-type 'plus) 'add-number)
- ((eq ex-token-type 'minus) 'sub-number)
- (t 'abs-number)))
- (setq ex-token (string-to-int (buffer-substring (point) (mark t)))))
- ((looking-at "\\$")
- (forward-char 1)
- (setq ex-token-type 'end))
- ((looking-at "%")
- (forward-char 1)
- (setq ex-token-type 'whole))
- ((looking-at "+")
- (cond ((or (looking-at "+[-+]") (looking-at "+[\n|]"))
- (forward-char 1)
- (insert "1")
- (backward-char 1)
- (setq ex-token-type 'plus))
- ((looking-at "+[0-9]")
- (forward-char 1)
- (setq ex-token-type 'plus))
- (t
- (error vip-BadAddress))))
- ((looking-at "-")
- (cond ((or (looking-at "-[-+]") (looking-at "-[\n|]"))
- (forward-char 1)
- (insert "1")
- (backward-char 1)
- (setq ex-token-type 'minus))
- ((looking-at "-[0-9]")
- (forward-char 1)
- (setq ex-token-type 'minus))
- (t
- (error vip-BadAddress))))
- ((looking-at "/")
- (forward-char 1)
- (set-mark (point))
- (let ((cont t))
- (while (and (not (eolp)) cont)
- ;;(re-search-forward "[^/]*/")
- (re-search-forward "[^/]*\\(/\\|\n\\)")
- (if (not (vip-looking-back "[^\\\\]\\(\\\\\\\\\\)*\\\\/"))
- (setq cont nil))))
- (backward-char 1)
- (setq ex-token (buffer-substring (point) (mark t)))
- (if (looking-at "/") (forward-char 1))
- (setq ex-token-type 'search-forward))
- ((looking-at "\\?")
- (forward-char 1)
- (set-mark (point))
- (let ((cont t))
- (while (and (not (eolp)) cont)
- ;;(re-search-forward "[^\\?]*\\?")
- (re-search-forward "[^\\?]*\\(\\?\\|\n\\)")
- (if (not (vip-looking-back "[^\\\\]\\(\\\\\\\\\\)*\\\\\\?"))
- (setq cont nil))
- (backward-char 1)
- (if (not (looking-at "\n")) (forward-char 1))))
- (setq ex-token-type 'search-backward)
- (setq ex-token (buffer-substring (1- (point)) (mark t))))
- ((looking-at ",")
- (forward-char 1)
- (setq ex-token-type 'comma))
- ((looking-at ";")
- (forward-char 1)
- (setq ex-token-type 'semi-colon))
- ((looking-at "[!=><&~]")
- (setq ex-token-type 'command)
- (setq ex-token (char-to-string (following-char)))
- (forward-char 1))
- ((looking-at "'")
- (setq ex-token-type 'goto-mark)
- (forward-char 1)
- (cond ((looking-at "'") (setq ex-token nil))
- ((looking-at "[a-z]") (setq ex-token (following-char)))
- (t (error "Marks are ' and a-z")))
- (forward-char 1))
- ((looking-at "\n")
- (setq ex-token-type 'end-mark)
- (setq ex-token "goto"))
- (t
- (error vip-BadExCommand)))))
-
-;; Reads Ex command. Tries to determine if it has to exit because command
-;; is complete or invalid. If not, keeps reading command.
-(defun ex-cmd-read-exit ()
- (interactive)
- (setq vip-incomplete-ex-cmd t)
- (let ((quit-regex1 (concat
- "\\(" "set[ \t]*"
- "\\|" "edit[ \t]*"
- "\\|" "[nN]ext[ \t]*"
- "\\|" "unm[ \t]*"
- "\\|" "^[ \t]*rep"
- "\\)"))
- (quit-regex2 (concat
- "[a-zA-Z][ \t]*"
- "\\(" "!" "\\|" ">>"
- "\\|" "\\+[0-9]+"
- "\\)"
- "*[ \t]*$"))
- (stay-regex (concat
- "\\(" "^[ \t]*$"
- "\\|" "[?/].*[?/].*"
- "\\|" "[ktgjmsz][ \t]*$"
- "\\|" "^[ \t]*ab.*"
- "\\|" "tr[ansfer \t]*"
- "\\|" "sr[ \t]*"
- "\\|" "mo.*"
- "\\|" "^[ \t]*k?ma[^p]*"
- "\\|" "^[ \t]*fi.*"
- "\\|" "v?gl.*"
- "\\|" "[vg][ \t]*$"
- "\\|" "jo.*"
- "\\|" "^[ \t]*ta.*"
- "\\|" "^[ \t]*una.*"
- "\\|" "^[ \t]*su.*"
- "\\|['`][a-z][ \t]*"
- "\\|" "![ \t]*[a-zA-Z].*"
- "\\)"
- "!*")))
-
- (save-window-excursion ;; put cursor at the end of the Ex working buffer
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (goto-char (point-max)))
- (cond ((vip-looking-back quit-regex1) (exit-minibuffer))
- ((vip-looking-back stay-regex) (insert " "))
- ((vip-looking-back quit-regex2) (exit-minibuffer))
- (t (insert " ")))))
-
-;; complete Ex command
-(defun ex-cmd-complete ()
- (interactive)
- (let (save-pos dist compl-list string-to-complete completion-result)
-
- (save-excursion
- (setq dist (skip-chars-backward "[a-zA-Z!=>&~]")
- save-pos (point)))
-
- (if (or (= dist 0)
- (vip-looking-back "\\([ \t]*['`][ \t]*[a-z]*\\)")
- (vip-looking-back
- "^[ \t]*[a-zA-Z!=>&~][ \t]*[/?]*+[ \t]+[a-zA-Z!=>&~]+"))
- ;; Preceding characters are not the ones allowed in an Ex command
- ;; or we have typed past command name.
- ;; Note: we didn't do parsing, so there may be surprises.
- (if (or (vip-looking-back "[a-zA-Z!=>&~][ \t]*[/?]*[ \t]*")
- (vip-looking-back "\\([ \t]*['`][ \t]*[a-z]*\\)")
- (looking-at "[^ \t\n\C-m]"))
- nil
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list
- (vip-alist-to-list ex-token-alist))))
- ;; Preceding chars may be part of a command name
- (setq string-to-complete (buffer-substring save-pos (point)))
- (setq completion-result
- (try-completion string-to-complete ex-token-alist))
-
- (cond ((eq completion-result t) ; exact match--do nothing
- (vip-tmp-insert-at-eob " (Sole completion)"))
- ((eq completion-result nil)
- (vip-tmp-insert-at-eob " (No match)"))
- (t ;; partial completion
- (goto-char save-pos)
- (delete-region (point) (point-max))
- (insert completion-result)
- (let (case-fold-search)
- (setq compl-list
- (vip-filter-alist (concat "^" completion-result)
- ex-token-alist)))
- (if (> (length compl-list) 1)
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list
- (vip-alist-to-list (reverse compl-list)))))))
- )))
-
-
-;; Read Ex commands
-;; Ex commands themselves are implemented in viper-ex.el
-(defun vip-ex (&optional string)
- (interactive)
- (or string
- (setq ex-g-flag nil
- ex-g-variant nil))
- (let* ((map (copy-keymap minibuffer-local-map))
- (address nil)
- (cont t)
- (dot (point))
- prev-token-type com-str)
-
- (vip-add-keymap vip-ex-cmd-map map)
-
- (setq com-str (or string (vip-read-string-with-history
- ":"
- nil
- 'vip-ex-history
- (car vip-ex-history)
- map)))
- (save-window-excursion
- ;; just a precaution
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (delete-region (point-min) (point-max))
- (insert com-str "\n")
- (goto-char (point-min)))
- (setq ex-token-type nil
- ex-addresses nil)
- (while cont
- (vip-get-ex-token)
- (cond ((memq ex-token-type '(command end-mark))
- (if address (setq ex-addresses (cons address ex-addresses)))
- (cond ((string= ex-token "global")
- (ex-global nil)
- (setq cont nil))
- ((string= ex-token "vglobal")
- (ex-global t)
- (setq cont nil))
- (t
- (vip-execute-ex-command)
- (save-window-excursion
- (setq vip-ex-work-buf
- (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (skip-chars-forward " \t")
- (cond ((looking-at "|")
- (forward-char 1))
- ((looking-at "\n")
- (setq cont nil))
- (t (error "`%s': %s" ex-token vip-SpuriousText)))
- ))
- ))
- ((eq ex-token-type 'non-command)
- (error "`%s': %s" ex-token vip-BadExCommand))
- ((eq ex-token-type 'whole)
- (setq address nil)
- (setq ex-addresses
- (if ex-addresses
- (cons (point-max) ex-addresses)
- (cons (point-max) (cons (point-min) ex-addresses)))))
- ((eq ex-token-type 'comma)
- (if (eq prev-token-type 'whole)
- (setq address (point-min)))
- (setq ex-addresses
- (cons (if (null address) (point) address) ex-addresses)))
- ((eq ex-token-type 'semi-colon)
- (if (eq prev-token-type 'whole)
- (setq address (point-min)))
- (if address (setq dot address))
- (setq ex-addresses
- (cons (if (null address) (point) address) ex-addresses)))
- (t (let ((ans (vip-get-ex-address-subr address dot)))
- (if ans (setq address ans)))))
- (setq prev-token-type ex-token-type))))
-
-
-;; Get a regular expression and set `ex-variant', if found
-(defun vip-get-ex-pat ()
- (save-window-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (skip-chars-forward " \t")
- (if (looking-at "!")
- (progn
- (setq ex-g-variant (not ex-g-variant)
- ex-g-flag (not ex-g-flag))
- (forward-char 1)
- (skip-chars-forward " \t")))
- (let ((c (following-char)))
- (if (string-match "[0-9A-Za-z]" (format "%c" c))
- (error
- "Global regexp must be inside matching non-alphanumeric chars"))
- (if (looking-at "[^\\\\\n]")
- (progn
- (forward-char 1)
- (set-mark (point))
- (let ((cont t))
- (while (and (not (eolp)) cont)
- (if (not (re-search-forward (format "[^%c]*%c" c c) nil t))
- (if (member ex-token '("global" "vglobal"))
- (error
- "Missing closing delimiter for global regexp")
- (goto-char (point-max))))
- (if (not (vip-looking-back
- (format "[^\\\\]\\(\\\\\\\\\\)*\\\\%c" c)))
- (setq cont nil))))
- (setq ex-token
- (if (= (mark t) (point)) ""
- (buffer-substring (1- (point)) (mark t))))
- (backward-char 1))
- (setq ex-token nil))
- c)))
-
-;; get an ex command
-(defun vip-get-ex-command ()
- (save-window-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (if (looking-at "/") (forward-char 1))
- (skip-chars-forward " \t")
- (cond ((looking-at "[a-z]")
- (vip-get-ex-com-subr)
- (if (eq ex-token-type 'non-command)
- (error "`%s': %s" ex-token vip-BadExCommand)))
- ((looking-at "[!=><&~]")
- (setq ex-token (char-to-string (following-char)))
- (forward-char 1))
- (t (error vip-BadExCommand)))))
-
-;; Get an Ex option g or c
-(defun vip-get-ex-opt-gc (c)
- (save-window-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (if (looking-at (format "%c" c)) (forward-char 1))
- (skip-chars-forward " \t")
- (cond ((looking-at "g")
- (setq ex-token "g")
- (forward-char 1)
- t)
- ((looking-at "c")
- (setq ex-token "c")
- (forward-char 1)
- t)
- (t nil))))
-
-;; Compute default addresses. WHOLE-FLAG means use the whole buffer
-(defun vip-default-ex-addresses (&optional whole-flag)
- (cond ((null ex-addresses)
- (setq ex-addresses
- (if whole-flag
- (cons (point-max) (cons (point-min) nil))
- (cons (point) (cons (point) nil)))))
- ((null (cdr ex-addresses))
- (setq ex-addresses
- (cons (car ex-addresses) ex-addresses)))))
-
-;; Get an ex-address as a marker and set ex-flag if a flag is found
-(defun vip-get-ex-address ()
- (let ((address (point-marker)) (cont t))
- (setq ex-token "")
- (setq ex-flag nil)
- (while cont
- (vip-get-ex-token)
- (cond ((eq ex-token-type 'command)
- (if (member ex-token '("print" "list" "#"))
- (progn
- (setq ex-flag t
- cont nil))
- (error "Address expected in this Ex command")))
- ((eq ex-token-type 'end-mark)
- (setq cont nil))
- ((eq ex-token-type 'whole)
- (error "Trailing address expected"))
- ((eq ex-token-type 'comma)
- (error "`%s': %s" ex-token vip-SpuriousText))
- (t (let ((ans (vip-get-ex-address-subr address (point-marker))))
- (if ans (setq address ans))))))
- address))
-
-;; Returns an address as a point
-(defun vip-get-ex-address-subr (old-address dot)
- (let ((address nil))
- (if (null old-address) (setq old-address dot))
- (cond ((eq ex-token-type 'dot)
- (setq address dot))
- ((eq ex-token-type 'add-number)
- (save-excursion
- (goto-char old-address)
- (forward-line (if (= old-address 0) (1- ex-token) ex-token))
- (setq address (point-marker))))
- ((eq ex-token-type 'sub-number)
- (save-excursion
- (goto-char old-address)
- (forward-line (- ex-token))
- (setq address (point-marker))))
- ((eq ex-token-type 'abs-number)
- (save-excursion
- (goto-char (point-min))
- (if (= ex-token 0) (setq address 0)
- (forward-line (1- ex-token))
- (setq address (point-marker)))))
- ((eq ex-token-type 'end)
- (setq address (point-max-marker)))
- ((eq ex-token-type 'plus) t) ; do nothing
- ((eq ex-token-type 'minus) t) ; do nothing
- ((eq ex-token-type 'search-forward)
- (save-excursion
- (ex-search-address t)
- (setq address (point-marker))))
- ((eq ex-token-type 'search-backward)
- (save-excursion
- (ex-search-address nil)
- (setq address (point-marker))))
- ((eq ex-token-type 'goto-mark)
- (save-excursion
- (if (null ex-token)
- (exchange-point-and-mark)
- (goto-char (vip-register-to-point
- (1+ (- ex-token ?a)) 'enforce-buffer)))
- (setq address (point-marker)))))
- address))
-
-
-;; Search pattern and set address
-(defun ex-search-address (forward)
- (if (string= ex-token "")
- (if (null vip-s-string)
- (error vip-NoPrevSearch)
- (setq ex-token vip-s-string))
- (setq vip-s-string ex-token))
- (if forward
- (progn
- (forward-line 1)
- (re-search-forward ex-token))
- (forward-line -1)
- (re-search-backward ex-token)))
-
-;; Get a buffer name and set `ex-count' and `ex-flag' if found
-(defun vip-get-ex-buffer ()
- (setq ex-buffer nil)
- (setq ex-count nil)
- (setq ex-flag nil)
- (save-window-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (skip-chars-forward " \t")
- (if (looking-at "[a-zA-Z]")
- (progn
- (setq ex-buffer (following-char))
- (forward-char 1)
- (skip-chars-forward " \t")))
- (if (looking-at "[0-9]")
- (progn
- (set-mark (point))
- (re-search-forward "[0-9][0-9]*")
- (setq ex-count (string-to-int (buffer-substring (point) (mark t))))
- (skip-chars-forward " \t")))
- (if (looking-at "[pl#]")
- (progn
- (setq ex-flag t)
- (forward-char 1)))
- (if (not (looking-at "[\n|]"))
- (error "`%s': %s" ex-token vip-SpuriousText))))
-
-(defun vip-get-ex-count ()
- (setq ex-variant nil
- ex-count nil
- ex-flag nil)
- (save-window-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (skip-chars-forward " \t")
- (if (looking-at "!")
- (progn
- (setq ex-variant t)
- (forward-char 1)))
- (skip-chars-forward " \t")
- (if (looking-at "[0-9]")
- (progn
- (set-mark (point))
- (re-search-forward "[0-9][0-9]*")
- (setq ex-count (string-to-int (buffer-substring (point) (mark t))))
- (skip-chars-forward " \t")))
- (if (looking-at "[pl#]")
- (progn
- (setq ex-flag t)
- (forward-char 1)))
- (if (not (looking-at "[\n|]"))
- (error "`%s': %s"
- (buffer-substring (point-min) (1- (point-max))) vip-BadExCommand))))
-
-;; Expand \% and \# in ex command
-(defun ex-expand-filsyms (cmd buf)
- (let (cf pf ret)
- (save-excursion
- (set-buffer buf)
- (setq cf buffer-file-name)
- (setq pf (ex-next nil t))) ; this finds alternative file name
- (if (and (null cf) (string-match "[^\\]%\\|\\`%" cmd))
- (error "No current file to substitute for `%%'"))
- (if (and (null pf) (string-match "[^\\]#\\|\\`#" cmd))
- (error "No alternate file to substitute for `#'"))
- (save-excursion
- (set-buffer (get-buffer-create vip-ex-tmp-buf-name))
- (erase-buffer)
- (insert cmd)
- (goto-char (point-min))
- (while (re-search-forward "%\\|#" nil t)
- (let ((data (match-data))
- (char (buffer-substring (match-beginning 0) (match-end 0))))
- (if (vip-looking-back (concat "\\\\" char))
- (replace-match char)
- (store-match-data data)
- (if (string= char "%")
- (replace-match cf)
- (replace-match pf)))))
- (end-of-line)
- (setq ret (buffer-substring (point-min) (point)))
- (message "%s" ret))
- ret))
-
-;; Get a file name and set ex-variant, `ex-append' and `ex-offset' if found
-(defun vip-get-ex-file ()
- (let (prompt)
- (setq ex-file nil
- ex-variant nil
- ex-append nil
- ex-offset nil
- ex-cmdfile nil)
- (save-excursion
- (save-window-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (skip-chars-forward " \t")
- (if (looking-at "!")
- (if (and (not (vip-looking-back "[ \t]"))
- ;; read doesn't have a corresponding :r! form, so ! is
- ;; immediately interpreted as a shell command.
- (not (string= ex-token "read")))
- (progn
- (setq ex-variant t)
- (forward-char 1)
- (skip-chars-forward " \t"))
- (setq ex-cmdfile t)
- (forward-char 1)
- (skip-chars-forward " \t")))
- (if (looking-at ">>")
- (progn
- (setq ex-append t
- ex-variant t)
- (forward-char 2)
- (skip-chars-forward " \t")))
- (if (looking-at "+")
- (progn
- (forward-char 1)
- (set-mark (point))
- (re-search-forward "[ \t\n]")
- (backward-char 1)
- (setq ex-offset (buffer-substring (point) (mark t)))
- (forward-char 1)
- (skip-chars-forward " \t")))
- ;; this takes care of :r, :w, etc., when they get file names
- ;; from the history list
- (if (member ex-token '("read" "write" "edit" "visual" "next"))
- (progn
- (setq ex-file (buffer-substring (point) (1- (point-max))))
- (setq ex-file
- ;; For :e, match multiple non-white strings separated
- ;; by white. For others, find the first non-white string
- (if (string-match
- (if (string= ex-token "edit")
- "[^ \t\n]+\\([ \t]+[^ \t\n]+\\)*"
- "[^ \t\n]+")
- ex-file)
- (progn
- ;; if file name comes from history, don't leave
- ;; minibuffer when the user types space
- (setq vip-incomplete-ex-cmd nil)
- ;; this must be the last clause in this progn
- (substring ex-file (match-beginning 0) (match-end 0))
- )
- ""))
- ;; this leaves only the command name in the work area
- ;; file names are gone
- (delete-region (point) (1- (point-max)))
- ))
- (goto-char (point-max))
- (skip-chars-backward " \t\n")
- (setq prompt (buffer-substring (point-min) (point)))
- ))
-
- (setq vip-last-ex-prompt prompt)
-
- ;; If we just finished reading command, redisplay prompt
- (if vip-incomplete-ex-cmd
- (setq ex-file (vip-ex-read-file-name (format ":%s " prompt)))
- ;; file was typed in-line
- (setq ex-file (or ex-file "")))
- ))
-
-
-;; Completes file name or exits minibuffer. If Ex command accepts multiple
-;; file names, arranges to re-enter the minibuffer.
-(defun vip-complete-filename-or-exit ()
- (interactive)
- (setq vip-keep-reading-filename t)
- ;; don't exit if directory---ex-commands don't
- (cond ((ex-cmd-accepts-multiple-files-p ex-token) (exit-minibuffer))
- ;; apparently the argument to an Ex command is
- ;; supposed to be a shell command
- ((vip-looking-back "^[ \t]*!.*")
- (setq ex-cmdfile t)
- (insert " "))
- (t
- (setq ex-cmdfile nil)
- (minibuffer-complete-word))))
-
-(defun vip-handle-! ()
- (interactive)
- (if (and (string=
- (buffer-string) (vip-abbreviate-file-name default-directory))
- (member ex-token '("read" "write")))
- (erase-buffer))
- (insert "!"))
-
-(defun ex-cmd-accepts-multiple-files-p (token)
- (member token '("edit" "next" "Next")))
-
-;; If user doesn't enter anything, then "" is returned, i.e., the
-;; prompt-directory is not returned.
-(defun vip-ex-read-file-name (prompt)
- (let* ((str "")
- (minibuffer-local-completion-map
- (copy-keymap minibuffer-local-completion-map))
- beg end cont val)
-
- (vip-add-keymap ex-read-filename-map
- (if vip-emacs-p
- minibuffer-local-completion-map
- read-file-name-map))
-
- (setq cont (setq vip-keep-reading-filename t))
- (while cont
- (setq vip-keep-reading-filename nil
- val (read-file-name (concat prompt str) nil default-directory))
- (if (string-match " " val)
- (setq val (concat "\\\"" val "\\\"")))
- (setq str (concat str (if (equal val "") "" " ")
- val (if (equal val "") "" " ")))
-
- ;; Only edit, next, and Next commands accept multiple files.
- ;; vip-keep-reading-filename is set in the anonymous function that is
- ;; bound to " " in ex-read-filename-map.
- (setq cont (and vip-keep-reading-filename
- (ex-cmd-accepts-multiple-files-p ex-token)))
- )
-
- (setq beg (string-match "[^ \t]" str) ; delete leading blanks
- end (string-match "[ \t]*$" str)) ; delete trailing blanks
- (if (member ex-token '("read" "write"))
- (if (string-match "[\t ]*!" str)
- ;; this is actually a shell command
- (progn
- (setq ex-cmdfile t)
- (setq beg (1+ beg))
- (setq vip-last-ex-prompt (concat vip-last-ex-prompt " !")))))
- (substring str (or beg 0) end)))
-
-;; Execute ex command using the value of addresses
-(defun vip-execute-ex-command ()
- (vip-deactivate-mark)
- (cond ((string= ex-token "args") (ex-args))
- ((string= ex-token "copy") (ex-copy nil))
- ((string= ex-token "cd") (ex-cd))
- ((string= ex-token "chdir") (ex-cd))
- ((string= ex-token "delete") (ex-delete))
- ((string= ex-token "edit") (ex-edit))
- ((string= ex-token "file") (vip-info-on-file))
- ((string= ex-token "goto") (ex-goto))
- ((string= ex-token "help") (ex-help))
- ((string= ex-token "join") (ex-line "join"))
- ((string= ex-token "kmark") (ex-mark))
- ((string= ex-token "mark") (ex-mark))
- ((string= ex-token "map") (ex-map))
- ((string= ex-token "move") (ex-copy t))
- ((string= ex-token "next") (ex-next ex-cycle-other-window))
- ((string= ex-token "Next") (ex-next (not ex-cycle-other-window)))
- ((string= ex-token "RelatedFile") (ex-next-related-buffer 1))
- ((string= ex-token "put") (ex-put))
- ((string= ex-token "pwd") (ex-pwd))
- ((string= ex-token "preserve") (ex-preserve))
- ((string= ex-token "PreviousRelatedFile") (ex-next-related-buffer -1))
- ((string= ex-token "quit") (ex-quit))
- ((string= ex-token "read") (ex-read))
- ((string= ex-token "recover") (ex-recover))
- ((string= ex-token "rewind") (ex-rewind))
- ((string= ex-token "submitReport") (vip-submit-report))
- ((string= ex-token "set") (ex-set))
- ((string= ex-token "shell") (ex-shell))
- ((string= ex-token "source") (ex-source))
- ((string= ex-token "sr") (ex-substitute t t))
- ((string= ex-token "substitute") (ex-substitute))
- ((string= ex-token "suspend") (suspend-emacs))
- ((string= ex-token "stop") (suspend-emacs))
- ((string= ex-token "transfer") (ex-copy nil))
- ((string= ex-token "buffer") (if ex-cycle-other-window
- (vip-switch-to-buffer-other-window)
- (vip-switch-to-buffer)))
- ((string= ex-token "Buffer") (if ex-cycle-other-window
- (vip-switch-to-buffer)
- (vip-switch-to-buffer-other-window)))
- ((string= ex-token "tag") (ex-tag))
- ((string= ex-token "undo") (vip-undo))
- ((string= ex-token "unmap") (ex-unmap))
- ((string= ex-token "version") (vip-version))
- ((string= ex-token "visual") (ex-edit))
- ((string= ex-token "write") (ex-write nil))
- ((string= ex-token "Write") (save-some-buffers))
- ((string= ex-token "wq") (ex-write t))
- ((string= ex-token "WWrite") (save-some-buffers t)) ; don't ask
- ((string= ex-token "xit") (ex-write t))
- ((string= ex-token "yank") (ex-yank))
- ((string= ex-token "!") (ex-command))
- ((string= ex-token "=") (ex-line-no))
- ((string= ex-token ">") (ex-line "right"))
- ((string= ex-token "<") (ex-line "left"))
- ((string= ex-token "&") (ex-substitute t))
- ((string= ex-token "~") (ex-substitute t t))
- ((or (string= ex-token "append")
- (string= ex-token "change")
- (string= ex-token "insert")
- (string= ex-token "open"))
- (error "`%s': Obsolete command, not supported by Viper" ex-token))
- ((or (string= ex-token "abbreviate")
- (string= ex-token "unabbreviate"))
- (error
- "`%s': Vi abbrevs are obsolete. Use the more powerful Emacs abbrevs"
- ex-token))
- ((or (string= ex-token "list")
- (string= ex-token "print")
- (string= ex-token "z")
- (string= ex-token "#"))
- (error "`%s': Command not implemented in Viper" ex-token))
- (t (error "`%s': %s" ex-token vip-BadExCommand))))
-
-(defun vip-undisplayed-files ()
- (mapcar
- (function
- (lambda (b)
- (if (null (get-buffer-window b))
- (let ((f (buffer-file-name b)))
- (if f f
- (if ex-cycle-through-non-files
- (let ((s (buffer-name b)))
- (if (string= " " (substring s 0 1))
- nil
- s))
- nil)))
- nil)))
- (buffer-list)))
-
-
-(defun ex-args ()
- (let ((l (vip-undisplayed-files))
- (args "")
- (file-count 1))
- (while (not (null l))
- (if (car l)
- (setq args (format "%s %d) %s\n" args file-count (car l))
- file-count (1+ file-count)))
- (setq l (cdr l)))
- (if (string= args "")
- (message "All files are already displayed")
- (save-excursion
- (save-window-excursion
- (with-output-to-temp-buffer " *vip-info*"
- (princ "\n\nThese files are not displayed in any window.\n")
- (princ "\n=============\n")
- (princ args)
- (princ "\n=============\n")
- (princ "\nThe numbers can be given as counts to :next. ")
- (princ "\n\nPress any key to continue...\n\n"))
- (vip-read-event))))))
-
-;; Ex cd command. Default directory of this buffer changes
-(defun ex-cd ()
- (vip-get-ex-file)
- (if (string= ex-file "")
- (setq ex-file "~"))
- (setq default-directory (file-name-as-directory (expand-file-name ex-file))))
-
-;; Ex copy and move command. DEL-FLAG means delete
-(defun ex-copy (del-flag)
- (vip-default-ex-addresses)
- (let ((address (vip-get-ex-address))
- (end (car ex-addresses)) (beg (car (cdr ex-addresses))))
- (goto-char end)
- (save-excursion
- (push-mark beg t)
- (vip-enlarge-region (mark t) (point))
- (if del-flag
- (kill-region (point) (mark t))
- (copy-region-as-kill (point) (mark t)))
- (if ex-flag
- (progn
- (with-output-to-temp-buffer "*copy text*"
- (princ
- (if (or del-flag ex-g-flag ex-g-variant)
- (current-kill 0)
- (buffer-substring (point) (mark t)))))
- (condition-case nil
- (progn
- (read-string "[Hit return to continue] ")
- (save-excursion (kill-buffer "*copy text*")))
- (quit (save-excursion (kill-buffer "*copy text*"))
- (signal 'quit nil))))))
- (if (= address 0)
- (goto-char (point-min))
- (goto-char address)
- (forward-line 1))
- (insert (current-kill 0))))
-
-;; Ex delete command
-(defun ex-delete ()
- (vip-default-ex-addresses)
- (vip-get-ex-buffer)
- (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
- (if (> beg end) (error vip-FirstAddrExceedsSecond))
- (save-excursion
- (vip-enlarge-region beg end)
- (exchange-point-and-mark)
- (if ex-count
- (progn
- (set-mark (point))
- (forward-line (1- ex-count)))
- (set-mark end))
- (vip-enlarge-region (point) (mark t))
- (if ex-flag
- ;; show text to be deleted and ask for confirmation
- (progn
- (with-output-to-temp-buffer " *delete text*"
- (princ (buffer-substring (point) (mark t))))
- (condition-case nil
- (read-string "[Hit return to continue] ")
- (quit
- (save-excursion (kill-buffer " *delete text*"))
- (error "")))
- (save-excursion (kill-buffer " *delete text*")))
- (if ex-buffer
- (cond ((vip-valid-register ex-buffer '(Letter))
- (vip-append-to-register
- (downcase ex-buffer) (point) (mark t)))
- ((vip-valid-register ex-buffer)
- (copy-to-register ex-buffer (point) (mark t) nil))
- (t (error vip-InvalidRegister ex-buffer))))
- (kill-region (point) (mark t))))))
-
-
-
-;; Ex edit command
-;; In Viper, `e' and `e!' behave identically. In both cases, the user is
-;; asked if current buffer should really be discarded.
-;; This command can take multiple file names. It replaces the current buffer
-;; with the first file in its argument list
-(defun ex-edit (&optional file)
- (if (not file)
- (vip-get-ex-file))
- (cond ((and (string= ex-file "") buffer-file-name)
- (setq ex-file (vip-abbreviate-file-name (buffer-file-name))))
- ((string= ex-file "")
- (error vip-NoFileSpecified)))
-
- (let (msg do-edit)
- (if buffer-file-name
- (cond ((buffer-modified-p)
- (setq msg
- (format "Buffer %s is modified. Discard changes? "
- (buffer-name))
- do-edit t))
- ((not (verify-visited-file-modtime (current-buffer)))
- (setq msg
- (format "File %s changed on disk. Reread from disk? "
- buffer-file-name)
- do-edit t))
- (t (setq do-edit nil))))
-
- (if do-edit
- (if (yes-or-no-p msg)
- (progn
- (set-buffer-modified-p nil)
- (kill-buffer (current-buffer)))
- (message "Buffer %s was left intact" (buffer-name))))
- ) ; let
-
- (if (null (setq file (get-file-buffer ex-file)))
- (progn
- (ex-find-file ex-file)
- (or (eq major-mode 'dired-mode)
- (vip-change-state-to-vi))
- (goto-char (point-min)))
- (switch-to-buffer file))
- (if ex-offset
- (progn
- (save-window-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (delete-region (point-min) (point-max))
- (insert ex-offset "\n")
- (goto-char (point-min)))
- (goto-char (vip-get-ex-address))
- (beginning-of-line)))
- (ex-fixup-history vip-last-ex-prompt ex-file))
-
-;; Find-file FILESPEC if it appears to specify a single file.
-;; Otherwise, assume that FILES{EC is a wildcard.
-;; In this case, split it into substrings separated by newlines.
-;; Each line is assumed to be a file name. find-file's each file thus obtained.
-(defun ex-find-file (filespec)
- (let ((nonstandard-filename-chars "[^-a-zA-Z0-9_./,~$\\]"))
- (cond ((file-exists-p filespec) (find-file filespec))
- ((string-match nonstandard-filename-chars filespec)
- (funcall ex-nontrivial-find-file-function filespec))
- (t (find-file filespec)))
- ))
-
-
-;; Ex global command
-(defun ex-global (variant)
- (let ((gcommand ex-token))
- (if (or ex-g-flag ex-g-variant)
- (error "`%s' within `global' is not allowed" gcommand)
- (if variant
- (setq ex-g-flag nil
- ex-g-variant t)
- (setq ex-g-flag t
- ex-g-variant nil)))
- (vip-get-ex-pat)
- (if (null ex-token)
- (error "`%s': Missing regular expression" gcommand)))
-
- (if (string= ex-token "")
- (if (null vip-s-string)
- (error vip-NoPrevSearch)
- (setq ex-g-pat vip-s-string))
- (setq ex-g-pat ex-token
- vip-s-string ex-token))
- (if (null ex-addresses)
- (setq ex-addresses (list (point-max) (point-min)))
- (vip-default-ex-addresses))
- (let ((marks nil) (mark-count 0)
- com-str (end (car ex-addresses)) (beg (car (cdr ex-addresses))))
- (if (> beg end) (error vip-FirstAddrExceedsSecond))
- (save-excursion
- (vip-enlarge-region beg end)
- (exchange-point-and-mark)
- (let ((cont t) (limit (point-marker)))
- (exchange-point-and-mark)
- ;; skip the last line if empty
- (beginning-of-line)
- (if (eobp) (vip-backward-char-carefully))
- (while (and cont (not (bobp)) (>= (point) limit))
- (beginning-of-line)
- (set-mark (point))
- (end-of-line)
- (let ((found (re-search-backward ex-g-pat (mark t) t)))
- (if (or (and ex-g-flag found)
- (and ex-g-variant (not found)))
- (progn
- (end-of-line)
- (setq mark-count (1+ mark-count))
- (setq marks (cons (point-marker) marks)))))
- (beginning-of-line)
- (if (bobp) (setq cont nil)
- (forward-line -1)
- (end-of-line)))))
- (save-window-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (setq com-str (buffer-substring (1+ (point)) (1- (point-max)))))
- (while marks
- (goto-char (car marks))
- (vip-ex com-str)
- (setq mark-count (1- mark-count))
- (setq marks (cdr marks)))))
-
-;; Ex goto command
-(defun ex-goto ()
- (if (null ex-addresses)
- (setq ex-addresses (cons (point) nil)))
- (push-mark (point) t)
- (goto-char (car ex-addresses))
- (beginning-of-line))
-
-;; Ex line commands. COM is join, shift-right or shift-left
-(defun ex-line (com)
- (vip-default-ex-addresses)
- (vip-get-ex-count)
- (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))) point)
- (if (> beg end) (error vip-FirstAddrExceedsSecond))
- (save-excursion
- (vip-enlarge-region beg end)
- (exchange-point-and-mark)
- (if ex-count
- (progn
- (set-mark (point))
- (forward-line ex-count)))
- (if ex-flag
- ;; show text to be joined and ask for confirmation
- (progn
- (with-output-to-temp-buffer " *text*"
- (princ (buffer-substring (point) (mark t))))
- (condition-case nil
- (progn
- (read-string "[Hit return to continue] ")
- (ex-line-subr com (point) (mark t)))
- (quit (ding)))
- (save-excursion (kill-buffer " *text*")))
- (ex-line-subr com (point) (mark t)))
- (setq point (point)))
- (goto-char (1- point))
- (beginning-of-line)))
-
-(defun ex-line-subr (com beg end)
- (cond ((string= com "join")
- (goto-char (min beg end))
- (while (and (not (eobp)) (< (point) (max beg end)))
- (end-of-line)
- (if (and (<= (point) (max beg end)) (not (eobp)))
- (progn
- (forward-line 1)
- (delete-region (point) (1- (point)))
- (if (not ex-variant) (fixup-whitespace))))))
- ((or (string= com "right") (string= com "left"))
- (indent-rigidly
- (min beg end) (max beg end)
- (if (string= com "right") vip-shift-width (- vip-shift-width)))
- (goto-char (max beg end))
- (end-of-line)
- (vip-forward-char-carefully))))
-
-
-;; Ex mark command
-(defun ex-mark ()
- (let (char)
- (if (null ex-addresses)
- (setq ex-addresses
- (cons (point) nil)))
- (save-window-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (skip-chars-forward " \t")
- (if (looking-at "[a-z]")
- (progn
- (setq char (following-char))
- (forward-char 1)
- (skip-chars-forward " \t")
- (if (not (looking-at "[\n|]"))
- (error "`%s': %s" ex-token vip-SpuriousText)))
- (error "`%s' requires a following letter" ex-token)))
- (save-excursion
- (goto-char (car ex-addresses))
- (point-to-register (1+ (- char ?a))))))
-
-
-
-;; Alternate file is the file next to the first one in the buffer ring
-(defun ex-next (cycle-other-window &optional find-alt-file)
- (catch 'ex-edit
- (let (count l)
- (if (not find-alt-file)
- (progn
- (vip-get-ex-file)
- (if (or (char-or-string-p ex-offset)
- (and (not (string= "" ex-file))
- (not (string-match "^[0-9]+$" ex-file))))
- (progn
- (ex-edit t)
- (throw 'ex-edit nil))
- (setq count (string-to-int ex-file))
- (if (= count 0) (setq count 1))
- (if (< count 0) (error "Usage: `next <count>' (count >= 0)"))))
- (setq count 1))
- (setq l (vip-undisplayed-files))
- (while (> count 0)
- (while (and (not (null l)) (null (car l)))
- (setq l (cdr l)))
- (setq count (1- count))
- (if (> count 0)
- (setq l (cdr l))))
- (if find-alt-file (car l)
- (progn
- (if (and (car l) (get-file-buffer (car l)))
- (let* ((w (if cycle-other-window
- (get-lru-window) (selected-window)))
- (b (window-buffer w)))
- (set-window-buffer w (get-file-buffer (car l)))
- (bury-buffer b)
- ;; this puts "next <count>" in the ex-command history
- (ex-fixup-history vip-last-ex-prompt ex-file))
- (error "Not that many undisplayed files")))))))
-
-
-(defun ex-next-related-buffer (direction &optional no-recursion)
-
- (vip-ring-rotate1 vip-related-files-and-buffers-ring direction)
-
- (let ((file-or-buffer-name
- (vip-current-ring-item vip-related-files-and-buffers-ring))
- (old-ring vip-related-files-and-buffers-ring)
- (old-win (selected-window))
- skip-rest buf wind)
-
- (or (and (ring-p vip-related-files-and-buffers-ring)
- (> (ring-length vip-related-files-and-buffers-ring) 0))
- (error "This buffer has no related files or buffers"))
-
- (or (stringp file-or-buffer-name)
- (error
- "File and buffer names must be strings, %S" file-or-buffer-name))
-
- (setq buf (cond ((get-buffer file-or-buffer-name))
- ((file-exists-p file-or-buffer-name)
- (find-file-noselect file-or-buffer-name))
- ))
-
- (if (not (vip-buffer-live-p buf))
- (error "Didn't find buffer %S or file %S"
- file-or-buffer-name
- (vip-abbreviate-file-name
- (expand-file-name file-or-buffer-name))))
-
- (if (equal buf (current-buffer))
- (or no-recursion
- ;; try again
- (progn
- (setq skip-rest t)
- (ex-next-related-buffer direction 'norecursion))))
-
- (if skip-rest
- ()
- ;; setup buffer
- (if (setq wind (vip-get-visible-buffer-window buf))
- ()
- (setq wind (get-lru-window (if vip-xemacs-p nil 'visible)))
- (set-window-buffer wind buf))
-
- (if (vip-window-display-p)
- (progn
- (raise-frame (window-frame wind))
- (if (equal (window-frame wind) (window-frame old-win))
- (save-window-excursion (select-window wind) (sit-for 1))
- (select-window wind)))
- (save-window-excursion (select-window wind) (sit-for 1)))
-
- (save-excursion
- (set-buffer buf)
- (setq vip-related-files-and-buffers-ring old-ring))
-
- (setq vip-local-search-start-marker (point-marker))
- )))
-
-
-;; Force auto save
-(defun ex-preserve ()
- (message "Autosaving all buffers that need to be saved...")
- (do-auto-save t))
-
-;; Ex put
-(defun ex-put ()
- (let ((point (if (null ex-addresses) (point) (car ex-addresses))))
- (vip-get-ex-buffer)
- (setq vip-use-register ex-buffer)
- (goto-char point)
- (if (bobp) (vip-Put-back 1) (vip-put-back 1))))
-
-;; Ex print working directory
-(defun ex-pwd ()
- (message default-directory))
-
-;; Ex quit command
-(defun ex-quit ()
- ;; skip "!", if it is q!. In Viper q!, w!, etc., behave as q, w, etc.
- (save-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (if (looking-at "!") (forward-char 1)))
- (if (< vip-expert-level 3)
- (save-buffers-kill-emacs)
- (kill-buffer (current-buffer))))
-
-
-;; Ex read command
-(defun ex-read ()
- (vip-get-ex-file)
- (let ((point (if (null ex-addresses) (point) (car ex-addresses)))
- command)
- (goto-char point)
- (vip-add-newline-at-eob-if-necessary)
- (if (not (or (bobp) (eobp))) (forward-line 1))
- (if (and (not ex-variant) (string= ex-file ""))
- (progn
- (if (null buffer-file-name)
- (error vip-NoFileSpecified))
- (setq ex-file buffer-file-name)))
- (if ex-cmdfile
- (progn
- (setq command (ex-expand-filsyms ex-file (current-buffer)))
- (shell-command command t))
- (insert-file-contents ex-file)))
- (ex-fixup-history vip-last-ex-prompt ex-file))
-
-;; this function fixes ex-history for some commands like ex-read, ex-edit
-(defun ex-fixup-history (&rest args)
- (setq vip-ex-history
- (cons (mapconcat 'identity args " ") (cdr vip-ex-history))))
-
-
-;; Ex recover from emacs \#file\#
-(defun ex-recover ()
- (vip-get-ex-file)
- (if (or ex-append ex-offset)
- (error "`recover': %s" vip-SpuriousText))
- (if (string= ex-file "")
- (progn
- (if (null buffer-file-name)
- (error "This buffer isn't visiting any file"))
- (setq ex-file buffer-file-name))
- (setq ex-file (expand-file-name ex-file)))
- (if (and (not (string= ex-file (buffer-file-name)))
- (buffer-modified-p)
- (not ex-variant))
- (error "No write since last change \(:rec! overrides\)"))
- (recover-file ex-file))
-
-;; Tell that `rewind' is obsolete and to use `:next count' instead
-(defun ex-rewind ()
- (message
- "Use `:n <count>' instead. Counts are obtained from the `:args' command"))
-
-
-;; read variable name for ex-set
-(defun ex-set-read-variable ()
- (let ((minibuffer-local-completion-map
- (copy-keymap minibuffer-local-completion-map))
- (cursor-in-echo-area t)
- str batch)
- (define-key
- minibuffer-local-completion-map " " 'minibuffer-complete-and-exit)
- (define-key minibuffer-local-completion-map "=" 'exit-minibuffer)
- (if (vip-set-unread-command-events
- (ex-get-inline-cmd-args "[ \t]*[a-zA-Z]*[ \t]*" nil "\C-m"))
- (progn
- (setq batch t)
- (vip-set-unread-command-events ?\C-m)))
- (message ":set <Variable> [= <Value>]")
- (or batch (sit-for 2))
-
- (while (string-match "^[ \\t\\n]*$"
- (setq str
- (completing-read ":set " ex-variable-alist)))
- (message ":set <Variable> ")
- ;; if there are unread events, don't wait
- (or (vip-set-unread-command-events "") (sit-for 2))
- ) ; while
- str))
-
-
-(defun ex-set ()
- (let ((var (ex-set-read-variable))
- (val 0)
- (set-cmd "setq")
- (ask-if-save t)
- (auto-cmd-label "; don't touch or else...")
- (delete-turn-on-auto-fill-pattern
- "([ \t]*add-hook[ \t]+'vip-insert-state-hooks[ \t]+'turn-on-auto-fill.*)")
- actual-lisp-cmd lisp-cmd-del-pattern
- val2 orig-var)
- (setq orig-var var)
- (cond ((member var '("ai" "autoindent"))
- (setq var "vip-auto-indent"
- set-cmd "setq"
- ask-if-save nil
- val "t"))
- ((member var '("gai" "global-autoindent"))
- (kill-local-variable 'vip-auto-indent)
- (setq var "vip-auto-indent"
- set-cmd "setq-default"
- val "t"))
- ((member var '("noai" "noautoindent"))
- (setq var "vip-auto-indent"
- ask-if-save nil
- val "nil"))
- ((member var '("gnoai" "global-noautoindent"))
- (kill-local-variable 'vip-auto-indent)
- (setq var "vip-auto-indent"
- set-cmd "setq-default"
- val "nil"))
- ((member var '("ic" "ignorecase"))
- (setq var "vip-case-fold-search"
- val "t"))
- ((member var '("noic" "noignorecase"))
- (setq var "vip-case-fold-search"
- val "nil"))
- ((member var '("ma" "magic"))
- (setq var "vip-re-search"
- val "t"))
- ((member var '("noma" "nomagic"))
- (setq var "vip-re-search"
- val "nil"))
- ((member var '("ro" "readonly"))
- (setq var "buffer-read-only"
- val "t"))
- ((member var '("noro" "noreadonly"))
- (setq var "buffer-read-only"
- val "nil"))
- ((member var '("sm" "showmatch"))
- (setq var "blink-matching-paren"
- val "t"))
- ((member var '("nosm" "noshowmatch"))
- (setq var "blink-matching-paren"
- val "nil"))
- ((member var '("ws" "wrapscan"))
- (setq var "vip-search-wrap-around-t"
- val "t"))
- ((member var '("nows" "nowrapscan"))
- (setq var "vip-search-wrap-around-t"
- val "nil")))
- (if (eq val 0) ; value must be set by the user
- (let ((cursor-in-echo-area t))
- (message ":set %s = <Value>" var)
- ;; if there are unread events, don't wait
- (or (vip-set-unread-command-events "") (sit-for 2))
- (setq val (read-string (format ":set %s = " var)))
- (ex-fixup-history "set" orig-var val)
-
- ;; check numerical values
- (if (member var
- '("sw" "shiftwidth"
- "ts" "tabstop"
- "gts" "global-tabstop"
- "wm" "wrapmargin"))
- (condition-case nil
- (or (numberp (setq val2 (car (read-from-string val))))
- (error "%s: Invalid value, numberp, %S" var val))
- (error
- (error "%s: Invalid value, numberp, %S" var val))))
-
- (cond
- ((member var '("sw" "shiftwidth"))
- (setq var "vip-shift-width"))
- ((member var '("ts" "tabstop"))
- ;; make it take effect in curr buff and new bufs
- (setq var "tab-width"
- set-cmd "setq"
- ask-if-save nil))
- ((member var '("gts" "global-tabstop"))
- (kill-local-variable 'tab-width)
- (setq var "tab-width"
- set-cmd "setq-default"))
- ((member var '("wm" "wrapmargin"))
- ;; make it take effect in curr buff and new bufs
- (kill-local-variable 'fill-column)
- (setq var "fill-column"
- val (format "(- (window-width) %s)" val)
- set-cmd "setq-default"))
- ((member var '("sh" "shell"))
- (setq var "explicit-shell-file-name"
- val (format "\"%s\"" val)))))
- (ex-fixup-history "set" orig-var))
-
- (setq actual-lisp-cmd (format "\n(%s %s %s) %s"
- set-cmd var val auto-cmd-label))
- (setq lisp-cmd-del-pattern
- (format "^\n?[ \t]*([ \t]*%s[ \t]+%s[ \t].*)[ \t]*%s"
- set-cmd var auto-cmd-label))
-
- (if (and ask-if-save
- (y-or-n-p (format "Do you want to save this setting in %s "
- vip-custom-file-name)))
- (progn
- (vip-save-string-in-file
- actual-lisp-cmd vip-custom-file-name
- ;; del pattern
- lisp-cmd-del-pattern)
- (if (string= var "fill-column")
- (if (> val2 0)
- (vip-save-string-in-file
- (concat
- "(add-hook 'vip-insert-state-hooks 'turn-on-auto-fill) "
- auto-cmd-label)
- vip-custom-file-name
- delete-turn-on-auto-fill-pattern)
- (vip-save-string-in-file
- nil vip-custom-file-name delete-turn-on-auto-fill-pattern)
- (vip-save-string-in-file
- nil vip-custom-file-name
- ;; del pattern
- lisp-cmd-del-pattern)
- ))
- ))
-
- (message "%s %s %s" set-cmd var (if (string-match "^[ \t]*$" val)
- (format "%S" val)
- val))
- (eval (car (read-from-string actual-lisp-cmd)))
- (if (string= var "fill-column")
- (if (> val2 0)
- (auto-fill-mode 1)
- (auto-fill-mode -1)))
-
- ))
-
-;; In inline args, skip regex-forw and (optionally) chars-back.
-;; Optional 3d arg is a string that should replace ' ' to prevent its
-;; special meaning
-(defun ex-get-inline-cmd-args (regex-forw &optional chars-back replace-str)
- (save-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (goto-char (point-min))
- (re-search-forward regex-forw nil t)
- (let ((beg (point))
- end)
- (goto-char (point-max))
- (if chars-back
- (skip-chars-backward chars-back)
- (skip-chars-backward " \t\n\C-m"))
- (setq end (point))
- ;; replace SPC with `=' to suppress the special meaning SPC has
- ;; in Ex commands
- (goto-char beg)
- (if replace-str
- (while (re-search-forward " +" nil t)
- (replace-match replace-str nil t)
- (vip-forward-char-carefully)))
- (goto-char end)
- (buffer-substring beg end))))
-
-
-;; Ex shell command
-(defun ex-shell ()
- (shell))
-
-;; Viper help. Invokes Info
-(defun ex-help ()
- (condition-case nil
- (progn
- (pop-to-buffer (get-buffer-create "*info*"))
- (info (if vip-xemacs-p "viper.info" "viper"))
- (message "Type `i' to search for a specific topic"))
- (error (beep 1)
- (with-output-to-temp-buffer " *vip-info*"
- (princ (format "
-The Info file for Viper does not seem to be installed.
-
-This file is part of the standard distribution of %sEmacs.
-Please contact your system administrator. "
- (if vip-xemacs-p "X" "")
- ))))))
-
-;; Ex source command. Loads the file specified as argument or `~/.vip'
-(defun ex-source ()
- (vip-get-ex-file)
- (if (string= ex-file "")
- (load vip-custom-file-name)
- (load ex-file)))
-
-;; Ex substitute command
-;; If REPEAT use previous regexp which is ex-reg-exp or vip-s-string
-(defun ex-substitute (&optional repeat r-flag)
- (let ((opt-g nil)
- (opt-c nil)
- (matched-pos nil)
- (case-fold-search vip-case-fold-search)
- delim pat repl)
- (if repeat (setq ex-token nil) (setq delim (vip-get-ex-pat)))
- (if (null ex-token)
- (progn
- (setq pat (if r-flag vip-s-string ex-reg-exp))
- (or (stringp pat)
- (error "No previous pattern to use in substitution"))
- (setq repl ex-repl
- delim (string-to-char pat)))
- (setq pat (if (string= ex-token "") vip-s-string ex-token))
- (setq vip-s-string pat
- ex-reg-exp pat)
- (setq delim (vip-get-ex-pat))
- (if (null ex-token)
- (setq ex-token ""
- ex-repl "")
- (setq repl ex-token
- ex-repl ex-token)))
- (while (vip-get-ex-opt-gc delim)
- (if (string= ex-token "g") (setq opt-g t) (setq opt-c t)))
- (vip-get-ex-count)
- (if ex-count
- (save-excursion
- (if ex-addresses (goto-char (car ex-addresses)))
- (set-mark (point))
- (forward-line (1- ex-count))
- (setq ex-addresses (cons (point) (cons (mark t) nil))))
- (if (null ex-addresses)
- (setq ex-addresses (cons (point) (cons (point) nil)))
- (if (null (cdr ex-addresses))
- (setq ex-addresses (cons (car ex-addresses) ex-addresses)))))
- ;(setq G opt-g)
- (let ((beg (car ex-addresses))
- (end (car (cdr ex-addresses)))
- eol-mark)
- (save-excursion
- (vip-enlarge-region beg end)
- (let ((limit (save-excursion
- (goto-char (max (point) (mark t)))
- (point-marker))))
- (goto-char (min (point) (mark t)))
- (while (< (point) limit)
- (end-of-line)
- (setq eol-mark (point-marker))
- (beginning-of-line)
- (if opt-g
- (progn
- (while (and (not (eolp))
- (re-search-forward pat eol-mark t))
- (if (or (not opt-c) (y-or-n-p "Replace? "))
- (progn
- (setq matched-pos (point))
- (if (not (stringp repl))
- (error "Can't perform Ex substitution: No previous replacement pattern"))
- (replace-match repl t))))
- (end-of-line)
- (vip-forward-char-carefully))
- (if (null pat)
- (error
- "Can't repeat Ex substitution: No previous regular expression"))
- (if (and (re-search-forward pat eol-mark t)
- (or (not opt-c) (y-or-n-p "Replace? ")))
- (progn
- (setq matched-pos (point))
- (if (not (stringp repl))
- (error "Can't perform Ex substitution: No previous replacement pattern"))
- (replace-match repl t)))
- (end-of-line)
- (vip-forward-char-carefully))))))
- (if matched-pos (goto-char matched-pos))
- (beginning-of-line)
- (if opt-c (message "done"))))
-
-;; Ex tag command
-(defun ex-tag ()
- (let (tag)
- (save-window-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (skip-chars-forward " \t")
- (set-mark (point))
- (skip-chars-forward "^ |\t\n")
- (setq tag (buffer-substring (mark t) (point))))
- (if (not (string= tag "")) (setq ex-tag tag))
- (vip-change-state-to-emacs)
- (condition-case conds
- (progn
- (if (string= tag "")
- (find-tag ex-tag t)
- (find-tag-other-window ex-tag))
- (vip-change-state-to-vi))
- (error
- (vip-change-state-to-vi)
- (vip-message-conditions conds)))))
-
-;; Ex write command
-(defun ex-write (q-flag)
- (vip-default-ex-addresses t)
- (vip-get-ex-file)
- (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses)))
- temp-buf writing-same-file region
- file-exists writing-whole-file)
- (if (> beg end) (error vip-FirstAddrExceedsSecond))
- (if ex-cmdfile
- (progn
- (vip-enlarge-region beg end)
- (shell-command-on-region (point) (mark t) ex-file))
- (if (and (string= ex-file "") (not (buffer-file-name)))
- (setq ex-file
- (read-file-name
- (format "Buffer %s isn't visiting any file. File to save in: "
- (buffer-name)))))
-
- (setq writing-whole-file (and (= (point-min) beg) (= (point-max) end))
- ex-file (if (string= ex-file "")
- (buffer-file-name)
- (expand-file-name ex-file)))
- ;; if ex-file is a directory use the file portion of the buffer file name
- (if (and (file-directory-p ex-file)
- buffer-file-name
- (not (file-directory-p buffer-file-name)))
- (setq ex-file
- (concat ex-file (file-name-nondirectory buffer-file-name))))
-
- (setq file-exists (file-exists-p ex-file)
- writing-same-file (string= ex-file (buffer-file-name)))
-
- (if (and writing-whole-file writing-same-file)
- (if (not (buffer-modified-p))
- (message "(No changes need to be saved)")
- (save-buffer)
- (ex-write-info file-exists ex-file beg end))
- ;; writing some other file or portion of the currents
- ;; file---create temp buffer for it
- ;; disable undo in that buffer, for efficiency
- (buffer-disable-undo (setq temp-buf (create-file-buffer ex-file)))
- (unwind-protect
- (save-excursion
- (if (and file-exists
- (not writing-same-file)
- (not (yes-or-no-p
- (format "File %s exists. Overwrite? " ex-file))))
- (error "Quit")
- (vip-enlarge-region beg end)
- (setq region (buffer-substring (point) (mark t)))
- (set-buffer temp-buf)
- (set-visited-file-name ex-file)
- (erase-buffer)
- (if (and file-exists ex-append)
- (insert-file-contents ex-file))
- (goto-char (point-max))
- (insert region)
- (save-buffer)
- (ex-write-info file-exists ex-file (point-min) (point-max))
- )
- (set-buffer temp-buf)
- (set-buffer-modified-p nil)
- (kill-buffer temp-buf)
- ))
- )
- ;; this prevents the loss of data if writing part of the buffer
- (if (and (buffer-file-name) writing-same-file)
- (set-visited-file-modtime))
- (or writing-whole-file
- (not writing-same-file)
- (set-buffer-modified-p t))
- (if q-flag
- (if (< vip-expert-level 2)
- (save-buffers-kill-emacs)
- (kill-buffer (current-buffer))))
- )))
-
-
-(defun ex-write-info (exists file-name beg end)
- (message "`%s'%s %d lines, %d characters"
- (vip-abbreviate-file-name file-name)
- (if exists "" " [New file]")
- (count-lines beg (min (1+ end) (point-max)))
- (- end beg)))
-
-;; Ex yank command
-(defun ex-yank ()
- (vip-default-ex-addresses)
- (vip-get-ex-buffer)
- (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
- (if (> beg end) (error vip-FirstAddrExceedsSecond))
- (save-excursion
- (vip-enlarge-region beg end)
- (exchange-point-and-mark)
- (if (or ex-g-flag ex-g-variant)
- (error "Can't execute `yank' within `global'"))
- (if ex-count
- (progn
- (set-mark (point))
- (forward-line (1- ex-count)))
- (set-mark end))
- (vip-enlarge-region (point) (mark t))
- (if ex-flag (error "`yank': %s" vip-SpuriousText))
- (if ex-buffer
- (cond ((vip-valid-register ex-buffer '(Letter))
- (vip-append-to-register
- (downcase ex-buffer) (point) (mark t)))
- ((vip-valid-register ex-buffer)
- (copy-to-register ex-buffer (point) (mark t) nil))
- (t (error vip-InvalidRegister ex-buffer))))
- (copy-region-as-kill (point) (mark t)))))
-
-;; Execute shell command
-(defun ex-command ()
- (let (command)
- (save-window-excursion
- (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name))
- (set-buffer vip-ex-work-buf)
- (skip-chars-forward " \t")
- (setq command (buffer-substring (point) (point-max)))
- (end-of-line))
- (setq command (ex-expand-filsyms command (current-buffer)))
- (if (and (> (length command) 0) (string= "!" (substring command 0 1)))
- (if vip-ex-last-shell-com
- (setq command (concat vip-ex-last-shell-com (substring command 1)))
- (error "No previous shell command")))
- (setq vip-ex-last-shell-com command)
- (if (null ex-addresses)
- (shell-command command)
- (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
- (if (null beg) (setq beg end))
- (save-excursion
- (goto-char beg)
- (set-mark end)
- (vip-enlarge-region (point) (mark t))
- (shell-command-on-region (point) (mark t) command t))
- (goto-char beg)))))
-
-;; Print line number
-(defun ex-line-no ()
- (message "%d"
- (1+ (count-lines
- (point-min)
- (if (null ex-addresses) (point-max) (car ex-addresses))))))
-
-;; Give information on the file visited by the current buffer
-(defun vip-info-on-file ()
- (interactive)
- (let ((pos1 (vip-line-pos 'start))
- (pos2 (vip-line-pos 'end))
- lines file info)
- (setq lines (count-lines (point-min) (vip-line-pos 'end))
- file (if (buffer-file-name)
- (concat (vip-abbreviate-file-name (buffer-file-name)) ":")
- (concat (buffer-name) " [Not visiting any file]:"))
- info (format "line=%d/%d pos=%d/%d col=%d %s"
- (if (= pos1 pos2)
- (1+ lines)
- lines)
- (count-lines (point-min) (point-max))
- (point) (1- (point-max))
- (1+ (current-column))
- (if (buffer-modified-p) "[Modified]" "[Unchanged]")))
- (if (< (+ 1 (length info) (length file))
- (window-width (minibuffer-window)))
- (message (concat file " " info))
- (save-window-excursion
- (with-output-to-temp-buffer " *vip-info*"
- (princ (concat "\n"
- file "\n\n\t" info
- "\n\n\nPress any key to continue...\n\n")))
- (vip-read-event)
- (kill-buffer " *vip-info*")))
- ))
-
-
-(provide 'viper-ex)
-
-;;; viper-ex.el ends here
diff --git a/lisp/emulation/viper-keym.el b/lisp/emulation/viper-keym.el
deleted file mode 100644
index f9c09514d79..00000000000
--- a/lisp/emulation/viper-keym.el
+++ /dev/null
@@ -1,584 +0,0 @@
-;;; viper-keym.el --- Viper keymaps
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; Code
-
-(require 'viper-util)
-
-;;; Variables
-
-(defvar vip-toggle-key "\C-z"
- "The key used to change states from emacs to Vi and back.
-In insert mode, this key also functions as Meta.
-Must be set in .vip file or prior to loading Viper.
-This setting cannot be changed interactively.")
-
-(defvar vip-ESC-key "\e"
- "Key used to ESC.
-Must be set in .vip file or prior to loading Viper.
-This setting cannot be changed interactively.")
-
-
-;;; Keymaps
-
-;; Keymaps for vital things like \e and C-z.
-;; Not for users
-(defvar vip-vi-intercept-map (make-sparse-keymap))
-(defvar vip-insert-intercept-map (make-sparse-keymap))
-(defvar vip-emacs-intercept-map (make-sparse-keymap))
-
-;; keymap used to zap all keymaps other than function-key-map,
-;; device-function-key-map, etc.
-(defvar vip-overriding-map (make-sparse-keymap))
-
-(vip-deflocalvar vip-vi-local-user-map (make-sparse-keymap)
- "Keymap for user-defined local bindings.
-Useful for changing bindings such as ZZ in certain major modes.
-For instance, in letter-mode, one may want to bind ZZ to
-mh-send-letter. In a newsreader such as gnus, tin, or rn, ZZ could be bound
-to save-buffers-kill-emacs then post article, etc.")
-(put 'vip-vi-local-user-map 'permanent-local t)
-
-(defvar vip-vi-global-user-map (make-sparse-keymap)
- "Keymap for user-defined global bindings.
-These bindings are seen in all Viper buffers.")
-
-(defvar vip-vi-basic-map (make-keymap)
- "This is the main keymap in effect in Viper's Vi state.
-This map is global, shared by all buffers.")
-
-(defvar vip-vi-kbd-map (make-sparse-keymap)
- "This keymap keeps keyboard macros defined via the :map command.")
-
-(defvar vip-vi-diehard-map (make-sparse-keymap)
- "This keymap is in use when the user asks Viper to simulate Vi very closely.
-This happens when vip-expert-level is 1 or 2. See vip-set-expert-level.")
-
-
-(vip-deflocalvar vip-insert-local-user-map (make-sparse-keymap)
- "Auxiliary map for per-buffer user-defined keybindings in Insert state.")
-(put 'vip-insert-local-user-map 'permanent-local t)
-
-(defvar vip-insert-global-user-map (make-sparse-keymap)
- "Auxiliary map for global user-defined bindings in Insert state.")
-
-(defvar vip-insert-basic-map (make-sparse-keymap)
- "The basic insert-mode keymap.")
-
-(defvar vip-insert-diehard-map (make-keymap)
- "Map used when user wants vi-style keys in insert mode.
-Most of the Emacs keys are suppressed. This map overshadows
-vip-insert-basic-map. Not recommended, except for novice users.")
-
-(defvar vip-insert-kbd-map (make-sparse-keymap)
- "This keymap keeps VI-style kbd macros for insert mode.")
-
-(defvar vip-replace-map (make-sparse-keymap)
- "Map used in Viper's replace state.")
-
-(defvar vip-emacs-global-user-map (make-sparse-keymap)
- "Auxiliary map for global user-defined bindings in Emacs state.")
-
-(defvar vip-emacs-kbd-map (make-sparse-keymap)
- "This keymap keeps Vi-style kbd macros for emacs mode.")
-
-(vip-deflocalvar vip-emacs-local-user-map (make-sparse-keymap)
- "Auxiliary map for local user-defined bindings in Emacs state.")
-(put 'vip-emacs-local-user-map 'permanent-local t)
-
-;; This keymap should stay empty
-(defvar vip-empty-keymap (make-sparse-keymap))
-
-;; This was the main Vi mode in old versions of VIP which may have been
-;; extensively used by VIP users. We declare it as a global var
-;; and, after .vip is loaded, we add this keymap to vip-vi-basic-map.
-(defvar vip-mode-map (make-sparse-keymap))
-
-
-;;; Variables used by minor modes
-
-;; Association list of the form
-;; ((major-mode . keymap) (major-mode . keymap) ...)
-;; Viper uses these keymaps to make user-requested adjustments
-;; to its Vi state in various major modes.")
-(defvar vip-vi-state-modifier-alist nil)
-
-;; Association list of the form
-;; ((major-mode . keymap) (major-mode . keymap) ...)
-;; Viper uses these keymaps to make user-requested adjustments
-;; to its Insert state in various major modes.")
-(defvar vip-insert-state-modifier-alist nil)
-
-;; Association list of the form
-;; ((major-mode . keymap) (major-mode . keymap) ...)
-;; Viper uses these keymaps to make user-requested adjustments
-;; to its Emacs state in various major modes.
-(defvar vip-emacs-state-modifier-alist nil)
-
-;; Tells vip-add-local-keys to create a new vip-vi-local-user-map for new
-;; buffers. Not a user option.
-(vip-deflocalvar vip-need-new-vi-local-map t "")
-(put 'vip-need-new-vi-local-map 'permanent-local t)
-
-;; Tells vip-add-local-keys to create a new vip-insert-local-user-map for new
-;; buffers. Not a user option.
-(vip-deflocalvar vip-need-new-insert-local-map t "")
-(put 'vip-need-new-insert-local-map 'permanent-local t)
-
-;; Tells vip-add-local-keys to create a new vip-emacs-local-user-map for new
-;; buffers. Not a user option.
-(vip-deflocalvar vip-need-new-emacs-local-map t "")
-(put 'vip-need-new-emacs-local-map 'permanent-local t)
-
-
-
-;; Insert mode keymap
-
-;; for novice users, pretend you are the real vi.
-(define-key vip-insert-diehard-map "\t" 'vip-insert-tab)
-(define-key vip-insert-diehard-map "\C-a" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-b" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-c" 'vip-change-state-to-vi)
-(define-key vip-insert-diehard-map "\C-e" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-f" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-g" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-i" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-k" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-l" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-n" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-o" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-p" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-q" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-r" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-s" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-u" 'vip-erase-line)
-(define-key vip-insert-diehard-map "\C-x" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-y" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-z" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-]" 'self-insert-command)
-(define-key vip-insert-diehard-map "\C-_" 'self-insert-command)
-
-(let ((i ?\ ))
- (while (<= i ?~)
- (define-key vip-insert-diehard-map (make-string 1 i) 'self-insert-command)
- (setq i (1+ i))))
-
-;; Insert mode map when user wants emacs style
-(define-key vip-insert-basic-map "\C-d" 'vip-backward-indent)
-(define-key vip-insert-basic-map "\C-w" 'vip-delete-backward-word)
-(define-key vip-insert-basic-map "\C-t" 'vip-forward-indent)
-(define-key vip-insert-basic-map
- (if vip-xemacs-p [(shift tab)] [S-tab]) 'vip-insert-tab)
-(define-key vip-insert-basic-map "\C-v" 'quoted-insert)
-(define-key vip-insert-basic-map "\C-?" 'vip-del-backward-char-in-insert)
-(define-key vip-insert-basic-map "\C-\\" 'vip-alternate-Meta-key)
-(define-key vip-insert-basic-map vip-toggle-key 'vip-escape-to-vi)
-(define-key vip-insert-basic-map "\C-c\M-p"
- 'vip-insert-prev-from-insertion-ring)
-(define-key vip-insert-basic-map "\C-c\M-n"
- 'vip-insert-next-from-insertion-ring)
-
-
-;; Replace keymap
-(define-key vip-replace-map "\C-t" 'vip-forward-indent)
-(define-key vip-replace-map "\C-j" 'vip-replace-state-exit-cmd)
-(define-key vip-replace-map "\C-m" 'vip-replace-state-exit-cmd)
-(define-key vip-replace-map "\C-?" 'vip-del-backward-char-in-replace)
-
-
-
-;; Vi keymaps
-
-(define-key vip-vi-basic-map "\C-^"
- (function (lambda () (interactive) (vip-ex "e#"))))
-(define-key vip-vi-basic-map "\C-b" 'vip-scroll-screen-back)
-(define-key vip-vi-basic-map "\C-d" 'vip-scroll-up)
-(define-key vip-vi-basic-map "\C-e" 'vip-scroll-up-one)
-(define-key vip-vi-basic-map "\C-f" 'vip-scroll-screen)
-(define-key vip-vi-basic-map "\C-m" 'vip-next-line-at-bol)
-(define-key vip-vi-basic-map "\C-u" 'vip-scroll-down)
-(define-key vip-vi-basic-map "\C-y" 'vip-scroll-down-one)
-(define-key vip-vi-basic-map "\C-s" 'vip-isearch-forward)
-(define-key vip-vi-basic-map "\C-r" 'vip-isearch-backward)
-(define-key vip-vi-basic-map "\C-c/" 'vip-toggle-search-style)
-(define-key vip-vi-basic-map "\C-cg" 'vip-info-on-file)
-
-(define-key vip-vi-basic-map "\C-c\M-p" 'vip-prev-destructive-command)
-(define-key vip-vi-basic-map "\C-c\M-n" 'vip-next-destructive-command)
-
-
-(define-key vip-vi-basic-map " " 'vip-forward-char)
-(define-key vip-vi-basic-map "!" 'vip-command-argument)
-(define-key vip-vi-basic-map "\"" 'vip-command-argument)
-(define-key vip-vi-basic-map "#" 'vip-command-argument)
-(define-key vip-vi-basic-map "$" 'vip-goto-eol)
-(define-key vip-vi-basic-map "%" 'vip-paren-match)
-(define-key vip-vi-basic-map "&"
- (function (lambda () (interactive) (vip-ex "&"))))
-(define-key vip-vi-basic-map "'" 'vip-goto-mark-and-skip-white)
-(define-key vip-vi-basic-map "(" 'vip-backward-sentence)
-(define-key vip-vi-basic-map ")" 'vip-forward-sentence)
-(define-key vip-vi-basic-map "*" 'call-last-kbd-macro)
-(define-key vip-vi-basic-map "+" 'vip-next-line-at-bol)
-(define-key vip-vi-basic-map "," 'vip-repeat-find-opposite)
-(define-key vip-vi-basic-map "-" 'vip-previous-line-at-bol)
-(define-key vip-vi-basic-map "." 'vip-repeat)
-(define-key vip-vi-basic-map "/" 'vip-search-forward)
-
-(define-key vip-vi-basic-map "0" 'vip-beginning-of-line)
-(define-key vip-vi-basic-map "1" 'vip-digit-argument)
-(define-key vip-vi-basic-map "2" 'vip-digit-argument)
-(define-key vip-vi-basic-map "3" 'vip-digit-argument)
-(define-key vip-vi-basic-map "4" 'vip-digit-argument)
-(define-key vip-vi-basic-map "5" 'vip-digit-argument)
-(define-key vip-vi-basic-map "6" 'vip-digit-argument)
-(define-key vip-vi-basic-map "7" 'vip-digit-argument)
-(define-key vip-vi-basic-map "8" 'vip-digit-argument)
-(define-key vip-vi-basic-map "9" 'vip-digit-argument)
-
-(define-key vip-vi-basic-map ":" 'vip-ex)
-(define-key vip-vi-basic-map ";" 'vip-repeat-find)
-(define-key vip-vi-basic-map "<" 'vip-command-argument)
-(define-key vip-vi-basic-map "=" 'vip-command-argument)
-(define-key vip-vi-basic-map ">" 'vip-command-argument)
-(define-key vip-vi-basic-map "?" 'vip-search-backward)
-(define-key vip-vi-basic-map "@" 'vip-register-macro)
-
-(define-key vip-vi-basic-map "A" 'vip-Append)
-(define-key vip-vi-basic-map "B" 'vip-backward-Word)
-(define-key vip-vi-basic-map "C" 'vip-change-to-eol)
-(define-key vip-vi-basic-map "D" 'vip-kill-line)
-(define-key vip-vi-basic-map "E" 'vip-end-of-Word)
-(define-key vip-vi-basic-map "F" 'vip-find-char-backward)
-(define-key vip-vi-basic-map "G" 'vip-goto-line)
-(define-key vip-vi-basic-map "H" 'vip-window-top)
-(define-key vip-vi-basic-map "I" 'vip-Insert)
-(define-key vip-vi-basic-map "J" 'vip-join-lines)
-(define-key vip-vi-basic-map "K" 'vip-nil)
-(define-key vip-vi-basic-map "L" 'vip-window-bottom)
-(define-key vip-vi-basic-map "M" 'vip-window-middle)
-(define-key vip-vi-basic-map "N" 'vip-search-Next)
-(define-key vip-vi-basic-map "O" 'vip-Open-line)
-(define-key vip-vi-basic-map "P" 'vip-Put-back)
-(define-key vip-vi-basic-map "Q" 'vip-query-replace)
-(define-key vip-vi-basic-map "R" 'vip-overwrite)
-(define-key vip-vi-basic-map "S" 'vip-substitute-line)
-(define-key vip-vi-basic-map "T" 'vip-goto-char-backward)
-(define-key vip-vi-basic-map "U" 'vip-undo)
-(define-key vip-vi-basic-map "V" 'find-file-other-window)
-(define-key vip-vi-basic-map "W" 'vip-forward-Word)
-(define-key vip-vi-basic-map "X" 'vip-delete-backward-char)
-(define-key vip-vi-basic-map "Y" 'vip-yank-line)
-(define-key vip-vi-basic-map "ZZ" 'vip-save-kill-buffer)
-
-(define-key vip-vi-basic-map "\\" 'vip-escape-to-emacs)
-(define-key vip-vi-basic-map "[" 'vip-brac-function)
-(define-key vip-vi-basic-map "]" 'vip-ket-function)
-(define-key vip-vi-basic-map "\C-\\" 'vip-alternate-Meta-key)
-(define-key vip-vi-basic-map "^" 'vip-bol-and-skip-white)
-(define-key vip-vi-basic-map "`" 'vip-goto-mark)
-
-(define-key vip-vi-basic-map "a" 'vip-append)
-(define-key vip-vi-basic-map "b" 'vip-backward-word)
-(define-key vip-vi-basic-map "c" 'vip-command-argument)
-(define-key vip-vi-basic-map "d" 'vip-command-argument)
-(define-key vip-vi-basic-map "e" 'vip-end-of-word)
-(define-key vip-vi-basic-map "f" 'vip-find-char-forward)
-(define-key vip-vi-basic-map "g" 'vip-nil)
-(define-key vip-vi-basic-map "h" 'vip-backward-char)
-(define-key vip-vi-basic-map "i" 'vip-insert)
-(define-key vip-vi-basic-map "j" 'vip-next-line)
-(define-key vip-vi-basic-map "k" 'vip-previous-line)
-(define-key vip-vi-basic-map "l" 'vip-forward-char)
-(define-key vip-vi-basic-map "m" 'vip-mark-point)
-(define-key vip-vi-basic-map "n" 'vip-search-next)
-(define-key vip-vi-basic-map "o" 'vip-open-line)
-(define-key vip-vi-basic-map "p" 'vip-put-back)
-(define-key vip-vi-basic-map "q" 'vip-nil)
-(define-key vip-vi-basic-map "r" 'vip-replace-char)
-(define-key vip-vi-basic-map "s" 'vip-substitute)
-(define-key vip-vi-basic-map "t" 'vip-goto-char-forward)
-(define-key vip-vi-basic-map "u" 'vip-undo)
-(define-key vip-vi-basic-map "v" 'find-file)
-(define-key vip-vi-basic-map "\C-v" 'find-file-other-frame)
-(define-key vip-vi-basic-map "w" 'vip-forward-word)
-(define-key vip-vi-basic-map "x" 'vip-delete-char)
-(define-key vip-vi-basic-map "y" 'vip-command-argument)
-(define-key vip-vi-basic-map "zH" 'vip-line-to-top)
-(define-key vip-vi-basic-map "zM" 'vip-line-to-middle)
-(define-key vip-vi-basic-map "zL" 'vip-line-to-bottom)
-(define-key vip-vi-basic-map "z\C-m" 'vip-line-to-top)
-(define-key vip-vi-basic-map "z." 'vip-line-to-middle)
-(define-key vip-vi-basic-map "z-" 'vip-line-to-bottom)
-
-(define-key vip-vi-basic-map "{" 'vip-backward-paragraph)
-(define-key vip-vi-basic-map "|" 'vip-goto-col)
-(define-key vip-vi-basic-map "}" 'vip-forward-paragraph)
-(define-key vip-vi-basic-map "~" 'vip-toggle-case)
-(define-key vip-vi-basic-map "\C-?" 'vip-backward-char)
-(define-key vip-vi-basic-map "_" 'vip-nil)
-
-;;; Escape from Emacs to Vi for one command
-(global-set-key "\C-c\\" 'vip-escape-to-vi) ; everywhere
-
-;;; This is vip-vi-diehard-map. Used when vip-vi-diehard-minor-mode is on.
-
-(define-key vip-vi-diehard-map "\C-a" 'vip-nil)
-(define-key vip-vi-diehard-map "\C-c" 'vip-nil)
-(define-key vip-vi-diehard-map "\C-g" 'vip-info-on-file)
-(define-key vip-vi-diehard-map "\C-i" 'vip-nil)
-(define-key vip-vi-diehard-map "\C-k" 'vip-nil)
-(define-key vip-vi-diehard-map "\C-l" 'redraw-display)
-(define-key vip-vi-diehard-map "\C-n" 'vip-next-line)
-(define-key vip-vi-diehard-map "\C-o" 'vip-nil)
-(define-key vip-vi-diehard-map "\C-p" 'vip-previous-line)
-(define-key vip-vi-diehard-map "\C-q" 'vip-nil)
-(define-key vip-vi-diehard-map "\C-r" 'redraw-display)
-(define-key vip-vi-diehard-map "\C-s" 'vip-nil)
-(define-key vip-vi-diehard-map "\C-t" 'vip-nil)
-(define-key vip-vi-diehard-map "\C-v" 'vip-nil)
-(define-key vip-vi-diehard-map "\C-w" 'vip-nil)
-(define-key vip-vi-diehard-map "@" 'vip-nil)
-(define-key vip-vi-diehard-map "_" 'vip-nil)
-(define-key vip-vi-diehard-map "*" 'vip-nil)
-(define-key vip-vi-diehard-map "#" 'vip-nil)
-(define-key vip-vi-diehard-map "\C-_" 'vip-nil)
-(define-key vip-vi-diehard-map "\C-]" 'vip-nil) ; This is actually tags.
-
-
-;;; Minibuffer keymap
-
-
-(defvar vip-minibuffer-map (make-sparse-keymap)
- "Keymap used to modify keys when Minibuffer is in Insert state.")
-
-(define-key vip-minibuffer-map "\C-m" 'vip-exit-minibuffer)
-(define-key vip-minibuffer-map "\C-j" 'vip-exit-minibuffer)
-
-;; Map used to read Ex-style commands.
-(defvar vip-ex-cmd-map (make-sparse-keymap))
-(define-key vip-ex-cmd-map " " 'ex-cmd-read-exit)
-(define-key vip-ex-cmd-map "\t" 'ex-cmd-complete)
-
-;; Keymap for reading file names in Ex-style commands.
-(defvar ex-read-filename-map (make-sparse-keymap))
-(define-key ex-read-filename-map " " 'vip-complete-filename-or-exit)
-(define-key ex-read-filename-map "!" 'vip-handle-!)
-
-;; Some other maps
-(defvar vip-slash-and-colon-map (make-sparse-keymap)
- "This map redefines `/' and `:' to behave as in Vi.
-Useful in some modes, such as Gnus, MH, etc.")
-(define-key vip-slash-and-colon-map ":" 'vip-ex)
-(define-key vip-slash-and-colon-map "/" 'vip-search-forward)
-
-(defvar vip-comint-mode-modifier-map (make-sparse-keymap)
- "This map modifies comint mode.")
-(define-key vip-comint-mode-modifier-map "\C-m" 'comint-send-input)
-(define-key vip-comint-mode-modifier-map "\C-d" 'comint-delchar-or-maybe-eof)
-
-(defvar vip-dired-modifier-map (make-sparse-keymap)
- "This map modifies Dired behavior.")
-(define-key vip-dired-modifier-map ":" 'vip-ex)
-(define-key vip-dired-modifier-map "/" 'vip-search-forward)
-
-
-
-;;; Code
-
-(defun vip-add-local-keys (state alist)
- "Override some vi-state or insert-state bindings in the current buffer.
-The effect is seen in the current buffer only.
-Useful for customizing mailer buffers, gnus, etc.
-STATE is 'vi-state, 'insert-state, or 'emacs-state
-ALIST is of the form ((key . func) (key . func) ...)
-Normally, this would be called from a hook to a major mode or
-on a per buffer basis.
-Usage:
- (vip-add-local-keys state '((key-str . func) (key-str . func)...)) "
-
- (let (map)
- (cond ((eq state 'vi-state)
- (if vip-need-new-vi-local-map
- (setq vip-vi-local-user-map (make-sparse-keymap)))
- (setq vip-need-new-vi-local-map nil
- map vip-vi-local-user-map))
- ((eq state 'insert-state)
- (if vip-need-new-insert-local-map
- (setq vip-insert-local-user-map (make-sparse-keymap)))
- (setq vip-need-new-insert-local-map nil
- map vip-insert-local-user-map))
- ((eq state 'emacs-state)
- (if vip-need-new-emacs-local-map
- (setq vip-emacs-local-user-map (make-sparse-keymap)))
- (setq vip-need-new-emacs-local-map nil
- map vip-emacs-local-user-map))
- (t
- (error
- "Invalid state in vip-add-local-keys: %S. Valid states: vi-state, insert-state or emacs-state" state)))
-
- (vip-modify-keymap map alist)
- (vip-normalize-minor-mode-map-alist)
- (vip-set-mode-vars-for vip-current-state)))
-
-(defun vip-zap-local-keys ()
- "Unconditionally reset Viper vip-*-local-user-map's.
-Rarely useful, but if u made a mistake by switching to a mode that adds
-undesirable local keys, e.g., comint-mode, then this function can restore
-sanity."
- (interactive)
- (setq vip-vi-local-user-map (make-sparse-keymap)
- vip-need-new-vi-local-map nil
- vip-insert-local-user-map (make-sparse-keymap)
- vip-need-new-insert-local-map nil
- vip-emacs-local-user-map (make-sparse-keymap)
- vip-need-new-emacs-local-map nil)
- (vip-normalize-minor-mode-map-alist))
-
-
-(defun vip-modify-major-mode (mode state keymap)
- "Modify key bindings in a major-mode in a Viper state using a keymap.
-
-If the default for a major mode is emacs-state, then modifications to this
-major mode may not take effect until the buffer switches state to Vi,
-Insert or Emacs. If this happens, add vip-change-state-to-emacs to this
-major mode's hook. If no such hook exists, you may have to put an advice on
-the function that invokes the major mode. See vip-set-hooks for hints.
-
-The above needs not to be done for major modes that come up in Vi or Insert
-state by default.
-
-Arguments: (major-mode vip-state keymap)"
- (let ((alist
- (cond ((eq state 'vi-state) 'vip-vi-state-modifier-alist)
- ((eq state 'insert-state) 'vip-insert-state-modifier-alist)
- ((eq state 'emacs-state) 'vip-emacs-state-modifier-alist)))
- elt)
- (if (setq elt (assoc mode (eval alist)))
- (set alist (delq elt (eval alist))))
- (set alist (cons (cons mode keymap) (eval alist)))
-
- ;; Normalization usually doesn't help here, since one needs to
- ;; normalize in the actual buffer where changes to the keymap are
- ;; to take place. However, it doesn't hurt, and it helps whenever this
- ;; function is actually called from within the right buffer.
- (vip-normalize-minor-mode-map-alist)
-
- (vip-set-mode-vars-for vip-current-state)))
-
-
-;; Displays variables that control Viper's keymaps
-(defun vip-debug-keymaps ()
- (interactive)
- (with-output-to-temp-buffer " *vip-debug*"
- (princ (format "Buffer name: %s\n\n" (buffer-name)))
- (princ "Variables: \n")
- (princ (format "major-mode: %S\n" major-mode))
- (princ (format "vip-current-state: %S\n" vip-current-state))
- (princ (format "vip-mode-string: %S\n\n" vip-mode-string))
- (princ (format "vip-vi-intercept-minor-mode: %S\n"
- vip-vi-intercept-minor-mode))
- (princ (format "vip-insert-intercept-minor-mode: %S\n"
- vip-insert-intercept-minor-mode))
- (princ (format "vip-emacs-intercept-minor-mode: %S\n"
- vip-emacs-intercept-minor-mode))
- (princ (format "vip-vi-minibuffer-minor-mode: %S\n"
- vip-vi-minibuffer-minor-mode))
- (princ (format "vip-insert-minibuffer-minor-mode: %S\n\n"
- vip-insert-minibuffer-minor-mode))
- (princ (format "vip-vi-local-user-minor-mode: %S\n"
- vip-vi-local-user-minor-mode))
- (princ (format "vip-vi-global-user-minor-mode: %S\n"
- vip-vi-global-user-minor-mode))
- (princ (format "vip-vi-kbd-minor-mode: %S\n" vip-vi-kbd-minor-mode))
- (princ (format "vip-vi-state-modifier-minor-mode: %S\n"
- vip-vi-state-modifier-minor-mode))
- (princ (format "vip-vi-diehard-minor-mode: %S\n"
- vip-vi-diehard-minor-mode))
- (princ (format "vip-vi-basic-minor-mode: %S\n" vip-vi-basic-minor-mode))
- (princ (format "vip-replace-minor-mode: %S\n" vip-replace-minor-mode))
- (princ (format "vip-insert-local-user-minor-mode: %S\n"
- vip-insert-local-user-minor-mode))
- (princ (format "vip-insert-global-user-minor-mode: %S\n"
- vip-insert-global-user-minor-mode))
- (princ (format "vip-insert-kbd-minor-mode: %S\n"
- vip-insert-kbd-minor-mode))
- (princ (format "vip-insert-state-modifier-minor-mode: %S\n"
- vip-insert-state-modifier-minor-mode))
- (princ (format "vip-insert-diehard-minor-mode: %S\n"
- vip-insert-diehard-minor-mode))
- (princ (format "vip-insert-basic-minor-mode: %S\n"
- vip-insert-basic-minor-mode))
- (princ (format "vip-emacs-local-user-minor-mode: %S\n"
- vip-emacs-local-user-minor-mode))
- (princ (format "vip-emacs-kbd-minor-mode: %S\n"
- vip-emacs-kbd-minor-mode))
- (princ (format "vip-emacs-global-user-minor-mode: %S\n"
- vip-emacs-global-user-minor-mode))
- (princ (format "vip-emacs-state-modifier-minor-mode: %S\n"
- vip-emacs-state-modifier-minor-mode))
-
- (princ (format "\nvip-expert-level %S\n" vip-expert-level))
- (princ (format "vip-no-multiple-ESC %S\n" vip-no-multiple-ESC))
- (princ (format "vip-always %S\n" vip-always))
- (princ (format "vip-ex-style-motion %S\n"
- vip-ex-style-motion))
- (princ (format "vip-ex-style-editing-in-insert %S\n"
- vip-ex-style-editing-in-insert))
- (princ (format "vip-want-emacs-keys-in-vi %S\n"
- vip-want-emacs-keys-in-vi))
- (princ (format "vip-want-emacs-keys-in-insert %S\n"
- vip-want-emacs-keys-in-insert))
- (princ (format "vip-want-ctl-h-help %S\n" vip-want-ctl-h-help))
-
- (princ "\n\n\n")
- (princ (format "Default value for minor-mode-map-alist: \n%S\n\n"
- (default-value 'minor-mode-map-alist)))
- (princ (format "Actual value for minor-mode-map-alist: \n%S\n"
- minor-mode-map-alist))
- ))
-
-
-;;; Keymap utils
-
-(defun vip-add-keymap (mapsrc mapdst)
- "Add contents of mapsrc to mapdst. It is assumed that mapsrc is sparse."
- (if vip-xemacs-p
- (map-keymap (function (lambda (key binding)
- (define-key mapdst key binding)))
- mapsrc)
- (mapcar
- (function (lambda (p)
- (define-key mapdst (vector (car p)) (cdr p))
- ))
- (cdr mapsrc))))
-
-(defun vip-modify-keymap (map alist)
- "Modifies MAP with bindings specified in the ALIST. The alist has the
-form ((key . function) (key . function) ... )."
- (mapcar (function (lambda (p)
- (define-key map (eval (car p)) (cdr p))))
- alist))
-
-
-(provide 'viper-keym)
-
-;;; viper-keym.el ends here
diff --git a/lisp/emulation/viper-macs.el b/lisp/emulation/viper-macs.el
deleted file mode 100644
index 6b0b2fb99ea..00000000000
--- a/lisp/emulation/viper-macs.el
+++ /dev/null
@@ -1,943 +0,0 @@
-;;; viper-macs.el --- functions implementing keyboard macros for Viper
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; Code
-
-(require 'viper-util)
-(require 'viper-keym)
-
-
-;;; Variables
-
-;; Register holding last macro.
-(defvar vip-last-macro-reg nil)
-
-;; format of the elements of kbd alists:
-;; (name ((buf . macr)...(buf . macr)) ((maj-mode . macr)...) (t . macr))
-;; kbd macro alist for Vi state
-(defvar vip-vi-kbd-macro-alist nil)
-;; same for insert/replace state
-(defvar vip-insert-kbd-macro-alist nil)
-;; same for emacs state
-(defvar vip-emacs-kbd-macro-alist nil)
-
-;; Internal var that passes info between start-kbd-macro and end-kbd-macro
-;; in :map and :map!
-(defvar vip-kbd-macro-parameters nil)
-
-(defvar vip-this-kbd-macro nil
- "Vector of keys representing the name of currently running Viper kbd macro.")
-(defvar vip-last-kbd-macro nil
- "Vector of keys representing the name of last Viper keyboard macro.")
-
-(defconst vip-fast-keyseq-timeout 200
- "*Key sequence separated by no more than this many milliseconds is viewed as a macro, if such a macro is defined.
-This also controls ESC-keysequences generated by keyboard function keys.")
-
-
-(defvar vip-repeat-from-history-key 'f12
- "Prefix key for invocation of vip-repeat-from-history function,
-which repeats previous destructive commands from the history of such
-commands.
-This function can then be invoked as <this-key> 1 or <this-key> 2.
-The notation for these keys is borrowed from XEmacs. Basically,
-a key is a symbol, e.g., `a', `\\1', `f2', etc., or a list, e.g.,
-`(meta control f1)'.")
-
-
-
-;;; Code
-
-;; Ex map command
-(defun ex-map ()
- (let ((mod-char "")
- macro-name macro-body map-args ins)
- (save-window-excursion
- (set-buffer vip-ex-work-buf)
- (if (looking-at "!")
- (progn
- (setq ins t
- mod-char "!")
- (forward-char 1))))
- (setq map-args (ex-map-read-args mod-char)
- macro-name (car map-args)
- macro-body (cdr map-args))
- (setq vip-kbd-macro-parameters (list ins mod-char macro-name macro-body))
- (if macro-body
- (vip-end-mapping-kbd-macro 'ignore)
- (ex-fixup-history (format "map%s %S" mod-char
- (vip-display-macro macro-name)))
- ;; if defining macro for insert, switch there for authentic WYSIWYG
- (if ins (vip-change-state-to-insert))
- (start-kbd-macro nil)
- (define-key vip-vi-intercept-map "\C-x)" 'vip-end-mapping-kbd-macro)
- (define-key vip-insert-intercept-map "\C-x)" 'vip-end-mapping-kbd-macro)
- (define-key vip-emacs-intercept-map "\C-x)" 'vip-end-mapping-kbd-macro)
- (message "Mapping %S in %s state. Hit `C-x )' to complete the mapping"
- (vip-display-macro macro-name)
- (if ins "Insert" "Vi")))
- ))
-
-
-;; Ex unmap
-(defun ex-unmap ()
- (let ((mod-char "")
- temp macro-name ins)
- (save-window-excursion
- (set-buffer vip-ex-work-buf)
- (if (looking-at "!")
- (progn
- (setq ins t
- mod-char "!")
- (forward-char 1))))
-
- (setq macro-name (ex-unmap-read-args mod-char))
- (setq temp (vip-fixup-macro (vconcat macro-name))) ;; copy and fixup
- (ex-fixup-history (format "unmap%s %S" mod-char
- (vip-display-macro temp)))
- (vip-unrecord-kbd-macro macro-name (if ins 'insert-state 'vi-state))
- ))
-
-
-;; read arguments for ex-map
-(defun ex-map-read-args (variant)
- (let ((cursor-in-echo-area t)
- (key-seq [])
- temp key event message
- macro-name macro-body args)
-
- (condition-case nil
- (setq args (concat (ex-get-inline-cmd-args ".*map[!]*[ \t]?" "\n\C-m")
- " nil nil ")
- temp (read-from-string args)
- macro-name (car temp)
- macro-body (car (read-from-string args (cdr temp))))
- (error
- (signal
- 'error
- '("map: Macro name and body must be a quoted string or a vector"))))
-
- ;; We expect macro-name to be a vector, a string, or a quoted string.
- ;; In the second case, it will emerge as a symbol when read from
- ;; the above read-from-string. So we need to convert it into a string
- (if macro-name
- (cond ((vectorp macro-name) nil)
- ((stringp macro-name)
- (setq macro-name (vconcat macro-name)))
- (t (setq macro-name (vconcat (prin1-to-string macro-name)))))
- (message ":map%s <Name>" variant)(sit-for 2)
- (while
- (not (member key
- '(?\C-m ?\n (control m) (control j) return linefeed)))
- (setq key-seq (vconcat key-seq (if key (vector key) [])))
- ;; the only keys available for editing are these-- no help while there
- (if (member
- key
- '(?\b ?\d '^? '^H (control h) (control \?) backspace delete))
- (setq key-seq (subseq key-seq 0 (- (length key-seq) 2))))
- (setq message
- (format
- ":map%s %s"
- variant (if (> (length key-seq) 0)
- (prin1-to-string (vip-display-macro key-seq))
- "")))
- (message message)
- (setq event (vip-read-key))
- ;;(setq event (vip-read-event))
- (setq key
- (if (vip-mouse-event-p event)
- (progn
- (message "%s (No mouse---only keyboard keys, please)"
- message)
- (sit-for 2)
- nil)
- (vip-event-key event)))
- )
- (setq macro-name key-seq))
-
- (if (= (length macro-name) 0)
- (error "Can't map an empty macro name"))
- (setq macro-name (vip-fixup-macro macro-name))
- (if (vip-char-array-p macro-name)
- (setq macro-name (vip-char-array-to-macro macro-name)))
-
- (if macro-body
- (cond ((vip-char-array-p macro-body)
- (setq macro-body (vip-char-array-to-macro macro-body)))
- ((vectorp macro-body) nil)
- (t (error "map: Invalid syntax in macro definition"))))
- (setq cursor-in-echo-area nil)(sit-for 0) ; this overcomes xemacs tty bug
- (cons macro-name macro-body)))
-
-
-
-;; read arguments for ex-unmap
-(defun ex-unmap-read-args (variant)
- (let ((cursor-in-echo-area t)
- (macro-alist (if (string= variant "!")
- vip-insert-kbd-macro-alist
- vip-vi-kbd-macro-alist))
- ;; these are disabled just in case, to avoid surprises when doing
- ;; completing-read
- vip-vi-kbd-minor-mode vip-insert-kbd-minor-mode
- vip-emacs-kbd-minor-mode
- vip-vi-intercept-minor-mode vip-insert-intercept-minor-mode
- vip-emacs-intercept-minor-mode
- event message
- key key-seq macro-name)
- (setq macro-name (ex-get-inline-cmd-args ".*unma?p?[!]*[ \t]*"))
-
- (if (> (length macro-name) 0)
- ()
- (message ":unmap%s <Name>" variant) (sit-for 2)
- (while
- (not
- (member key '(?\C-m ?\n (control m) (control j) return linefeed)))
- (setq key-seq (vconcat key-seq (if key (vector key) [])))
- ;; the only keys available for editing are these-- no help while there
- (cond ((member
- key
- '(?\b ?\d '^? '^H (control h) (control \?) backspace delete))
- (setq key-seq (subseq key-seq 0 (- (length key-seq) 2))))
- ((member key '(tab (control i) ?\t))
- (setq key-seq (subseq key-seq 0 (1- (length key-seq))))
- (setq message
- (format
- ":unmap%s %s"
- variant (if (> (length key-seq) 0)
- (prin1-to-string
- (vip-display-macro key-seq))
- "")))
- (setq key-seq
- (vip-do-sequence-completion key-seq macro-alist message))
- ))
- (setq message
- (format
- ":unmap%s %s"
- variant (if (> (length key-seq) 0)
- (prin1-to-string
- (vip-display-macro key-seq))
- "")))
- (message message)
- (setq event (vip-read-key))
- ;;(setq event (vip-read-event))
- (setq key
- (if (vip-mouse-event-p event)
- (progn
- (message "%s (No mouse---only keyboard keys, please)"
- message)
- (sit-for 2)
- nil)
- (vip-event-key event)))
- )
- (setq macro-name key-seq))
-
- (if (= (length macro-name) 0)
- (error "Can't unmap an empty macro name"))
-
- ;; convert macro names into vector, if starts with a `['
- (if (memq (elt macro-name 0) '(?\[ ?\"))
- (car (read-from-string macro-name))
- (vconcat macro-name))
- ))
-
-
-;; Terminate a Vi kbd macro.
-;; optional argument IGNORE, if t, indicates that we are dealing with an
-;; existing macro that needs to be registered, but there is no need to
-;; terminate a kbd macro.
-(defun vip-end-mapping-kbd-macro (&optional ignore)
- (interactive)
- (define-key vip-vi-intercept-map "\C-x)" nil)
- (define-key vip-insert-intercept-map "\C-x)" nil)
- (define-key vip-emacs-intercept-map "\C-x)" nil)
- (if (and (not ignore)
- (or (not vip-kbd-macro-parameters)
- (not defining-kbd-macro)))
- (error "Not mapping a kbd-macro"))
- (let ((mod-char (nth 1 vip-kbd-macro-parameters))
- (ins (nth 0 vip-kbd-macro-parameters))
- (macro-name (nth 2 vip-kbd-macro-parameters))
- (macro-body (nth 3 vip-kbd-macro-parameters)))
- (setq vip-kbd-macro-parameters nil)
- (or ignore
- (progn
- (end-kbd-macro nil)
- (setq macro-body (vip-events-to-macro last-kbd-macro))
- ;; always go back to Vi, since this is where we started
- ;; defining macro
- (vip-change-state-to-vi)))
-
- (vip-record-kbd-macro macro-name
- (if ins 'insert-state 'vi-state)
- (vip-display-macro macro-body))
-
- (ex-fixup-history (format "map%s %S %S" mod-char
- (vip-display-macro macro-name)
- (vip-display-macro macro-body)))
- ))
-
-
-
-(defadvice start-kbd-macro (after vip-kbd-advice activate)
- "Remove Viper's intercepting bindings for C-x ).
-This may be needed if the previous `:map' command terminated abnormally."
- (define-key vip-vi-intercept-map "\C-x)" nil)
- (define-key vip-insert-intercept-map "\C-x)" nil)
- (define-key vip-emacs-intercept-map "\C-x)" nil))
-
-
-
-;;; Recording, unrecording, executing
-
-;; accepts as macro names: strings and vectors.
-;; strings must be strings of characters; vectors must be vectors of keys
-;; in canonic form. the canonic form is essentially the form used in XEmacs
-(defun vip-record-kbd-macro (macro-name state macro-body &optional scope)
- "Record a Vi macro. Can be used in `.vip' file to define permanent macros.
-MACRO-NAME is a string of characters or a vector of keys. STATE is
-either `vi-state' or `insert-state'. It specifies the Viper state in which to
-define the macro. MACRO-BODY is a string that represents the keyboard macro.
-Optional SCOPE says whether the macro should be global \(t\), mode-specific
-\(a major-mode symbol\), or buffer-specific \(buffer name, a string\).
-If SCOPE is nil, the user is asked to specify the scope."
- (let* (state-name keymap
- (macro-alist-var
- (cond ((eq state 'vi-state)
- (setq state-name "Vi state"
- keymap vip-vi-kbd-map)
- 'vip-vi-kbd-macro-alist)
- ((memq state '(insert-state replace-state))
- (setq state-name "Insert state"
- keymap vip-insert-kbd-map)
- 'vip-insert-kbd-macro-alist)
- (t
- (setq state-name "Emacs state"
- keymap vip-emacs-kbd-map)
- 'vip-emacs-kbd-macro-alist)
- ))
- new-elt old-elt old-sub-elt msg
- temp lis lis2)
-
- (if (= (length macro-name) 0)
- (error "Can't map an empty macro name"))
-
- ;; Macro-name is usually a vector. However, command history or macros
- ;; recorded in ~/.vip may be recorded as strings. So, convert to vectors.
- (setq macro-name (vip-fixup-macro macro-name))
- (if (vip-char-array-p macro-name)
- (setq macro-name (vip-char-array-to-macro macro-name)))
- (setq macro-body (vip-fixup-macro macro-body))
- (if (vip-char-array-p macro-body)
- (setq macro-body (vip-char-array-to-macro macro-body)))
-
- ;; don't ask if scope is given and is of the right type
- (or (eq scope t)
- (stringp scope)
- (and scope (symbolp scope))
- (progn
- (setq scope
- (cond
- ((y-or-n-p
- (format
- "Map this macro for buffer `%s' only? "
- (buffer-name)))
- (setq msg
- (format
- "%S is mapped to %s for %s in `%s'"
- (vip-display-macro macro-name)
- (vip-abbreviate-string
- (format
- "%S"
- (setq temp (vip-display-macro macro-body)))
- 14 "" ""
- (if (stringp temp) " ....\"" " ....]"))
- state-name (buffer-name)))
- (buffer-name))
- ((y-or-n-p
- (format
- "Map this macro for the major mode `%S' only? "
- major-mode))
- (setq msg
- (format
- "%S is mapped to %s for %s in `%S'"
- (vip-display-macro macro-name)
- (vip-abbreviate-string
- (format
- "%S"
- (setq temp (vip-display-macro macro-body)))
- 14 "" ""
- (if (stringp macro-body) " ....\"" " ....]"))
- state-name major-mode))
- major-mode)
- (t
- (setq msg
- (format
- "%S is globally mapped to %s in %s"
- (vip-display-macro macro-name)
- (vip-abbreviate-string
- (format
- "%S"
- (setq temp (vip-display-macro macro-body)))
- 14 "" ""
- (if (stringp macro-body) " ....\"" " ....]"))
- state-name))
- t)))
- (if (y-or-n-p
- (format "Save this macro in %s? "
- (vip-abbreviate-file-name vip-custom-file-name)))
- (vip-save-string-in-file
- (format "\n(vip-record-kbd-macro %S '%S %s '%S)"
- (vip-display-macro macro-name)
- state
- ;; if we don't let vector macro-body through %S,
- ;; the symbols `\.' `\[' etc will be converted into
- ;; characters, causing invalid read error on recorded
- ;; macros in .vip.
- ;; I am not sure is macro-body can still be a string at
- ;; this point, but I am preserving this option anyway.
- (if (vectorp macro-body)
- (format "%S" macro-body)
- macro-body)
- scope)
- vip-custom-file-name))
-
- (message msg)
- ))
-
- (setq new-elt
- (cons macro-name
- (cond ((eq scope t) (list nil nil (cons t nil)))
- ((symbolp scope)
- (list nil (list (cons scope nil)) (cons t nil)))
- ((stringp scope)
- (list (list (cons scope nil)) nil (cons t nil))))))
- (setq old-elt (assoc macro-name (eval macro-alist-var)))
-
- (if (null old-elt)
- (progn
- ;; insert new-elt in macro-alist-var and keep the list sorted
- (define-key
- keymap
- (vector (vip-key-to-emacs-key (aref macro-name 0)))
- 'vip-exec-mapped-kbd-macro)
- (setq lis (eval macro-alist-var))
- (while (and lis (string< (vip-array-to-string (car (car lis)))
- (vip-array-to-string macro-name)))
- (setq lis2 (cons (car lis) lis2))
- (setq lis (cdr lis)))
-
- (setq lis2 (reverse lis2))
- (set macro-alist-var (append lis2 (cons new-elt lis)))
- (setq old-elt new-elt)))
- (setq old-sub-elt
- (cond ((eq scope t) (vip-kbd-global-pair old-elt))
- ((symbolp scope) (assoc scope (vip-kbd-mode-alist old-elt)))
- ((stringp scope) (assoc scope (vip-kbd-buf-alist old-elt)))))
- (if old-sub-elt
- (setcdr old-sub-elt macro-body)
- (cond ((symbolp scope) (setcar (cdr (cdr old-elt))
- (cons (cons scope macro-body)
- (vip-kbd-mode-alist old-elt))))
- ((stringp scope) (setcar (cdr old-elt)
- (cons (cons scope macro-body)
- (vip-kbd-buf-alist old-elt))))))
- ))
-
-
-
-;; macro name must be a vector of vip-style keys
-(defun vip-unrecord-kbd-macro (macro-name state)
- "Delete macro MACRO-NAME from Viper STATE.
-MACRO-NAME must be a vector of vip-style keys. This command is used by Viper
-internally, but the user can also use it in ~/.vip to delete pre-defined macros
-supplied with Viper. The best way to avoid mistakes in macro names to be passed
-to this function is to use vip-describe-kbd-macros and copy the name from
-there."
- (let* (state-name keymap
- (macro-alist-var
- (cond ((eq state 'vi-state)
- (setq state-name "Vi state"
- keymap vip-vi-kbd-map)
- 'vip-vi-kbd-macro-alist)
- ((memq state '(insert-state replace-state))
- (setq state-name "Insert state"
- keymap vip-insert-kbd-map)
- 'vip-insert-kbd-macro-alist)
- (t
- (setq state-name "Emacs state"
- keymap vip-emacs-kbd-map)
- 'vip-emacs-kbd-macro-alist)
- ))
- buf-mapping mode-mapping global-mapping
- macro-pair macro-entry)
-
- ;; Macro-name is usually a vector. However, command history or macros
- ;; recorded in ~/.vip may appear as strings. So, convert to vectors.
- (setq macro-name (vip-fixup-macro macro-name))
- (if (vip-char-array-p macro-name)
- (setq macro-name (vip-char-array-to-macro macro-name)))
-
- (setq macro-entry (assoc macro-name (eval macro-alist-var)))
- (if (= (length macro-name) 0)
- (error "Can't unmap an empty macro name"))
- (if (null macro-entry)
- (error "%S is not mapped to a macro for %s in `%s'"
- (vip-display-macro macro-name)
- state-name (buffer-name)))
-
- (setq buf-mapping (vip-kbd-buf-pair macro-entry)
- mode-mapping (vip-kbd-mode-pair macro-entry)
- global-mapping (vip-kbd-global-pair macro-entry))
-
- (cond ((and (cdr buf-mapping)
- (or (and (not (cdr mode-mapping)) (not (cdr global-mapping)))
- (y-or-n-p
- (format "Unmap %S for `%s' only? "
- (vip-display-macro macro-name)
- (buffer-name)))))
- (setq macro-pair buf-mapping)
- (message "%S is unmapped for %s in `%s'"
- (vip-display-macro macro-name)
- state-name (buffer-name)))
- ((and (cdr mode-mapping)
- (or (not (cdr global-mapping))
- (y-or-n-p
- (format "Unmap %S for the major mode `%S' only? "
- (vip-display-macro macro-name)
- major-mode))))
- (setq macro-pair mode-mapping)
- (message "%S is unmapped for %s in %S"
- (vip-display-macro macro-name) state-name major-mode))
- ((cdr (setq macro-pair (vip-kbd-global-pair macro-entry)))
- (message
- "Global mapping of %S for %s is removed"
- (vip-display-macro macro-name) state-name))
- (t (error "%S is not mapped to a macro for %s in `%s'"
- (vip-display-macro macro-name)
- state-name (buffer-name))))
- (setcdr macro-pair nil)
- (or (cdr buf-mapping)
- (cdr mode-mapping)
- (cdr global-mapping)
- (progn
- (set macro-alist-var (delq macro-entry (eval macro-alist-var)))
- (if (vip-can-release-key (aref macro-name 0)
- (eval macro-alist-var))
- (define-key
- keymap
- (vector (vip-key-to-emacs-key (aref macro-name 0)))
- nil))
- ))
- ))
-
-;; Check if MACRO-ALIST has an entry for a macro name starting with
-;; CHAR. If not, this indicates that the binding for this char
-;; in vip-vi/insert-kbd-map can be released.
-(defun vip-can-release-key (char macro-alist)
- (let ((lis macro-alist)
- (can-release t)
- macro-name)
-
- (while (and lis can-release)
- (setq macro-name (car (car lis)))
- (if (eq char (aref macro-name 0))
- (setq can-release nil))
- (setq lis (cdr lis)))
- can-release))
-
-
-(defun vip-exec-mapped-kbd-macro (count)
- "Dispatch kbd macro."
- (interactive "P")
- (let* ((macro-alist (cond ((eq vip-current-state 'vi-state)
- vip-vi-kbd-macro-alist)
- ((memq vip-current-state
- '(insert-state replace-state))
- vip-insert-kbd-macro-alist)
- (t
- vip-emacs-kbd-macro-alist)))
- (unmatched-suffix "")
- ;; Macros and keys are executed with other macros turned off
- ;; For macros, this is done to avoid macro recursion
- vip-vi-kbd-minor-mode vip-insert-kbd-minor-mode
- vip-emacs-kbd-minor-mode
- next-best-match keyseq event-seq
- macro-first-char macro-alist-elt macro-body
- command)
-
- (setq macro-first-char last-command-event
- event-seq (vip-read-fast-keysequence macro-first-char macro-alist)
- keyseq (vip-events-to-macro event-seq)
- macro-alist-elt (assoc keyseq macro-alist)
- next-best-match (vip-find-best-matching-macro macro-alist keyseq))
-
- (if (null macro-alist-elt)
- (setq macro-alist-elt (car next-best-match)
- unmatched-suffix (subseq event-seq (cdr next-best-match))))
-
- (cond ((null macro-alist-elt))
- ((setq macro-body (vip-kbd-buf-definition macro-alist-elt)))
- ((setq macro-body (vip-kbd-mode-definition macro-alist-elt)))
- ((setq macro-body (vip-kbd-global-definition macro-alist-elt))))
-
- ;; when defining keyboard macro, don't use the macro mappings
- (if (and macro-body (not defining-kbd-macro))
- ;; block cmd executed as part of a macro from entering command history
- (let ((command-history command-history))
- (setq vip-this-kbd-macro (car macro-alist-elt))
- (execute-kbd-macro (vip-macro-to-events macro-body) count)
- (setq vip-this-kbd-macro nil
- vip-last-kbd-macro (car macro-alist-elt))
- (vip-set-unread-command-events unmatched-suffix))
- ;; If not a macro, or the macro is suppressed while defining another
- ;; macro, put keyseq back on the event queue
- (vip-set-unread-command-events event-seq)
- ;; if the user typed arg, then use it if prefix arg is not set by
- ;; some other command (setting prefix arg can happen if we do, say,
- ;; 2dw and there is a macro starting with 2. Then control will go to
- ;; this routine
- (or prefix-arg (setq prefix-arg count))
- (setq command (key-binding (read-key-sequence nil)))
- (if (commandp command)
- (command-execute command)
- (beep 1)))
- ))
-
-
-
-;;; Displaying and completing macros
-
-(defun vip-describe-kbd-macros ()
- "Show currently defined keyboard macros."
- (interactive)
- (with-output-to-temp-buffer " *vip-info*"
- (princ "Macros in Vi state:\n===================\n")
- (mapcar 'vip-describe-one-macro vip-vi-kbd-macro-alist)
- (princ "\n\nMacros in Insert and Replace states:\n====================================\n")
- (mapcar 'vip-describe-one-macro vip-insert-kbd-macro-alist)
- (princ "\n\nMacros in Emacs state:\n======================\n")
- (mapcar 'vip-describe-one-macro vip-emacs-kbd-macro-alist)
- ))
-
-(defun vip-describe-one-macro (macro)
- (princ (format "\n *** Mappings for %S:\n ------------\n"
- (vip-display-macro (car macro))))
- (princ " ** Buffer-specific:")
- (if (vip-kbd-buf-alist macro)
- (mapcar 'vip-describe-one-macro-elt (vip-kbd-buf-alist macro))
- (princ " none\n"))
- (princ "\n ** Mode-specific:")
- (if (vip-kbd-mode-alist macro)
- (mapcar 'vip-describe-one-macro-elt (vip-kbd-mode-alist macro))
- (princ " none\n"))
- (princ "\n ** Global:")
- (if (vip-kbd-global-definition macro)
- (princ (format "\n %S" (cdr (vip-kbd-global-pair macro))))
- (princ " none"))
- (princ "\n"))
-
-(defun vip-describe-one-macro-elt (elt)
- (let ((name (car elt))
- (defn (cdr elt)))
- (princ (format "\n * %S:\n %S\n" name defn))))
-
-
-
-;; check if SEQ is a prefix of some car of an element in ALIST
-(defun vip-keyseq-is-a-possible-macro (seq alist)
- (let ((converted-seq (vip-events-to-macro seq)))
- (eval (cons 'or
- (mapcar
- (function (lambda (elt)
- (vip-prefix-subseq-p converted-seq elt)))
- (vip-this-buffer-macros alist))))))
-
-;; whether SEQ1 is a prefix of SEQ2
-(defun vip-prefix-subseq-p (seq1 seq2)
- (let ((len1 (length seq1))
- (len2 (length seq2)))
- (if (<= len1 len2)
- (equal seq1 (subseq seq2 0 len1)))))
-
-;; find the longest common prefix
-(defun vip-common-seq-prefix (&rest seqs)
- (let* ((first (car seqs))
- (rest (cdr seqs))
- (pref [])
- (idx 0)
- len)
- (if (= (length seqs) 0)
- (setq len 0)
- (setq len (apply 'min (mapcar 'length seqs))))
- (while (< idx len)
- (if (eval (cons 'and
- (mapcar (function (lambda (s)
- (equal (elt first idx)
- (elt s idx))))
- rest)))
- (setq pref (vconcat pref (vector (elt first idx)))))
- (setq idx (1+ idx)))
- pref))
-
-;; get all sequences that match PREFIX from a given A-LIST
-(defun vip-extract-matching-alist-members (pref alist)
- (delq nil (mapcar (function (lambda (elt)
- (if (vip-prefix-subseq-p pref elt)
- elt)))
- (vip-this-buffer-macros alist))))
-
-(defun vip-do-sequence-completion (seq alist compl-message)
- (let* ((matches (vip-extract-matching-alist-members seq alist))
- (new-seq (apply 'vip-common-seq-prefix matches))
- )
- (cond ((and (equal seq new-seq) (= (length matches) 1))
- (message "%s (Sole completion)" compl-message)
- (sit-for 2))
- ((null matches)
- (message "%s (No match)" compl-message)
- (sit-for 2)
- (setq new-seq seq))
- ((member seq matches)
- (message "%s (Complete, but not unique)" compl-message)
- (sit-for 2)
- (vip-display-vector-completions matches))
- ((equal seq new-seq)
- (vip-display-vector-completions matches)))
- new-seq))
-
-
-(defun vip-display-vector-completions (list)
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list
- (mapcar 'prin1-to-string
- (mapcar 'vip-display-macro list)))))
-
-
-
-;; alist is the alist of macros
-;; str is the fast key sequence entered
-;; returns: (matching-macro-def . unmatched-suffix-start-index)
-(defun vip-find-best-matching-macro (alist str)
- (let ((lis alist)
- (def-len 0)
- (str-len (length str))
- match unmatched-start-idx found macro-def)
- (while (and (not found) lis)
- (setq macro-def (car lis)
- def-len (length (car macro-def)))
- (if (and (>= str-len def-len)
- (equal (car macro-def) (subseq str 0 def-len)))
- (if (or (vip-kbd-buf-definition macro-def)
- (vip-kbd-mode-definition macro-def)
- (vip-kbd-global-definition macro-def))
- (setq found t))
- )
- (setq lis (cdr lis)))
-
- (if found
- (setq match macro-def
- unmatched-start-idx def-len)
- (setq match nil
- unmatched-start-idx 0))
-
- (cons match unmatched-start-idx)))
-
-
-
-;; returns a list of names of macros defined for the current buffer
-(defun vip-this-buffer-macros (macro-alist)
- (let (candidates)
- (setq candidates
- (mapcar (function
- (lambda (elt)
- (if (or (vip-kbd-buf-definition elt)
- (vip-kbd-mode-definition elt)
- (vip-kbd-global-definition elt))
- (car elt))))
- macro-alist))
- (setq candidates (delq nil candidates))))
-
-
-;; if seq of Viper key symbols (representing a macro) can be converted to a
-;; string--do so. Otherwise, do nothing.
-(defun vip-display-macro (macro-name-or-body)
- (cond ((vip-char-symbol-sequence-p macro-name-or-body)
- (mapconcat 'symbol-name macro-name-or-body ""))
- ((vip-char-array-p macro-name-or-body)
- (mapconcat 'char-to-string macro-name-or-body ""))
- (t macro-name-or-body)))
-
-;; convert sequence of events (that came presumably from emacs kbd macro) into
-;; Viper's macro, which is a vector of the form
-;; [ desc desc ... ]
-;; Each desc is either a symbol of (meta symb), (shift symb), etc.
-;; Here we purge events that happen to be lists. In most cases, these events
-;; got into a macro definition unintentionally; say, when the user moves mouse
-;; during a macro definition, then something like (switch-frame ...) might get
-;; in. Another reason for purging lists-events is that we can't store them in
-;; textual form (say, in .emacs) and then read them back.
-(defun vip-events-to-macro (event-seq)
- (vconcat (delq nil (mapcar (function (lambda (elt)
- (if (consp elt)
- nil
- (vip-event-key elt))))
- event-seq))))
-
-;; convert strings or arrays of characters to Viper macro form
-(defun vip-char-array-to-macro (array)
- (let ((vec (vconcat array))
- macro)
- (if vip-xemacs-p
- (setq macro (mapcar 'character-to-event vec))
- (setq macro vec))
- (vconcat (mapcar 'vip-event-key macro))))
-
-;; For macros bodies and names, goes over MACRO and checks if all members are
-;; names of keys (actually, it only checks if they are symbols or lists
-;; if a digit is found, it is converted into a symbol (e.g., 0 -> \0, etc).
-;; If MACRO is not a list or vector -- doesn't change MACRO.
-(defun vip-fixup-macro (macro)
- (let ((len (length macro))
- (idx 0)
- elt break)
- (if (or (vectorp macro) (listp macro))
- (while (and (< idx len) (not break))
- (setq elt (elt macro idx))
- (cond ((numberp elt)
- ;; fix number
- (if (and (<= 0 elt) (<= elt 9))
- (cond ((arrayp macro)
- (aset macro
- idx
- (intern (char-to-string (+ ?0 elt)))))
- ((listp macro)
- (setcar (nthcdr idx macro)
- (intern (char-to-string (+ ?0 elt)))))
- )))
- ((listp elt)
- (vip-fixup-macro elt))
- ((symbolp elt) nil)
- (t (setq break t)))
- (setq idx (1+ idx))))
-
- (if break
- (error "Wrong type macro component, symbol-or-listp, %S" elt)
- macro)))
-
-(defun vip-char-array-p (array)
- (eval (cons 'and (mapcar 'vip-characterp array))))
-
-(defun vip-macro-to-events (macro-body)
- (vconcat (mapcar 'vip-key-to-emacs-key macro-body)))
-
-
-;; check if vec is a vector of character symbols
-(defun vip-char-symbol-sequence-p (vec)
- (and
- (sequencep vec)
- (eval
- (cons 'and
- (mapcar
- (function (lambda (elt)
- (and (symbolp elt) (= (length (symbol-name elt)) 1))))
- vec)))))
-
-
-;; Check if vec is a vector of key-press events representing characters
-;; XEmacs only
-(defun vip-event-vector-p (vec)
- (and (vectorp vec)
- (eval (cons 'and (mapcar '(lambda (elt) (if (eventp elt) t)) vec)))))
-
-
-;;; Reading fast key sequences
-
-;; Assuming that CHAR was the first character in a fast succession of key
-;; strokes, read the rest. Return the vector of keys that was entered in
-;; this fast succession of key strokes.
-;; A fast keysequence is one that is terminated by a pause longer than
-;; vip-fast-keyseq-timeout.
-(defun vip-read-fast-keysequence (event macro-alist)
- (let ((lis (vector event))
- next-event)
- (while (and (vip-fast-keysequence-p)
- (vip-keyseq-is-a-possible-macro lis macro-alist))
- (setq next-event (vip-read-key))
- ;;(setq next-event (vip-read-event))
- (or (vip-mouse-event-p next-event)
- (setq lis (vconcat lis (vector next-event)))))
- lis))
-
-
-;;; Keyboard macros in registers
-
-;; sets register to last-kbd-macro carefully.
-(defun vip-set-register-macro (reg)
- (if (get-register reg)
- (if (y-or-n-p "Register contains data. Overwrite? ")
- ()
- (error
- "Macro not saved in register. Can still be invoked via `C-x e'")))
- (set-register reg last-kbd-macro))
-
-(defun vip-register-macro (count)
- "Keyboard macros in registers - a modified \@ command."
- (interactive "P")
- (let ((reg (downcase (read-char))))
- (cond ((or (and (<= ?a reg) (<= reg ?z)))
- (setq vip-last-macro-reg reg)
- (if defining-kbd-macro
- (progn
- (end-kbd-macro)
- (vip-set-register-macro reg))
- (execute-kbd-macro (get-register reg) count)))
- ((or (= ?@ reg) (= ?\^j reg) (= ?\^m reg))
- (if vip-last-macro-reg
- nil
- (error "No previous kbd macro"))
- (execute-kbd-macro (get-register vip-last-macro-reg) count))
- ((= ?\# reg)
- (start-kbd-macro count))
- ((= ?! reg)
- (setq reg (downcase (read-char)))
- (if (or (and (<= ?a reg) (<= reg ?z)))
- (progn
- (setq vip-last-macro-reg reg)
- (vip-set-register-macro reg))))
- (t
- (error "`%c': Unknown register" reg)))))
-
-
-(defun vip-global-execute ()
- "Call last keyboad macro for each line in the region."
- (if (> (point) (mark t)) (exchange-point-and-mark))
- (beginning-of-line)
- (call-last-kbd-macro)
- (while (< (point) (mark t))
- (forward-line 1)
- (beginning-of-line)
- (call-last-kbd-macro)))
-
-
-(provide 'viper-macs)
-
-;;; viper-macs.el ends here
diff --git a/lisp/emulation/viper-mous.el b/lisp/emulation/viper-mous.el
deleted file mode 100644
index 73cef2eef85..00000000000
--- a/lisp/emulation/viper-mous.el
+++ /dev/null
@@ -1,459 +0,0 @@
-;;; viper-mous.el --- mouse support for Viper
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; Code
-
-(require 'viper-util)
-
-;; compiler pacifier
-(defvar double-click-time)
-(defvar mouse-track-multi-click-time)
-;; end compiler pacifier
-
-
-;;; Variables
-
-;; Variable used for catching the switch-frame event.
-;; If non-nil, indicates that previous-frame should be the selected
-;; one. Used by vip-mouse-click-get-word. Not a user option.
-(defvar vip-frame-of-focus nil)
-
-;; Frame that was selected before the switch-frame event.
-(defconst vip-current-frame-saved (selected-frame))
-
-(defvar vip-surrounding-word-function 'vip-surrounding-word
- "*Function that determines what constitutes a word for clicking events.
-Takes two parameters: a COUNT, indicating how many words to return,
-and CLICK-COUNT, telling whether this is the first click, a double-click,
-or a tripple-click.")
-
-;; time interval in millisecond within which successive clicks are
-;; considered related
-(defconst vip-multiclick-timeout (if vip-xemacs-p
- mouse-track-multi-click-time
- double-click-time)
- "*Time interval in millisecond within which successive clicks are
-considered related.")
-
-;; current event click count; XEmacs only
-(defvar vip-current-click-count 0)
-;; time stamp of the last click event; XEmacs only
-(defvar vip-last-click-event-timestamp 0)
-
-;; Local variable used to toggle wraparound search on click.
-(vip-deflocalvar vip-mouse-click-search-noerror t)
-
-;; Local variable used to delimit search after wraparound.
-(vip-deflocalvar vip-mouse-click-search-limit nil)
-
-;; remembers prefix argument to pass along to commands invoked by second
-;; click.
-;; This is needed because in Emacs (not XEmacs), assigning to preix-arg
-;; causes Emacs to count the second click as if it was a single click
-(defvar vip-global-prefix-argument nil)
-
-
-
-;;; Code
-
-(defsubst vip-multiclick-p ()
- (not (vip-sit-for-short vip-multiclick-timeout t)))
-
-;; Returns window where click occurs
-(defsubst vip-mouse-click-window (click)
- (if vip-xemacs-p
- (event-window click)
- (posn-window (event-start click))))
-
-;; Returns window where click occurs
-(defsubst vip-mouse-click-frame (click)
- (window-frame (vip-mouse-click-window click)))
-
-;; Returns the buffer of the window where click occurs
-(defsubst vip-mouse-click-window-buffer (click)
- (window-buffer (vip-mouse-click-window click)))
-
-;; Returns the name of the buffer in the window where click occurs
-(defsubst vip-mouse-click-window-buffer-name (click)
- (buffer-name (vip-mouse-click-window-buffer click)))
-
-;; Returns position of a click
-(defsubst vip-mouse-click-posn (click)
- (if vip-xemacs-p
- (event-point click)
- (posn-point (event-start click))))
-
-
-(defun vip-surrounding-word (count click-count)
- "Returns word surrounding point according to a heuristic.
-COUNT indicates how many regions to return.
-If CLICK-COUNT is 1, `word' is a word in Vi sense.
-If CLICK-COUNT is 2,then `word' is a Word in Vi sense.
-If the character clicked on is a non-separator and is non-alphanumeric but
-is adjacent to an alphanumeric symbol, then it is considered alphanumeric
-for the purpose of this command. If this character has a matching
-character, such as `\(' is a match for `\)', then the matching character is
-also considered alphanumeric.
-For convenience, in Lisp modes, `-' is considered alphanumeric.
-
-If CLICK-COUNT is 3 or more, returns the line clicked on with leading and
-trailing space and tabs removed. In that case, the first argument, COUNT,
-is ignored."
- (let ((modifiers "")
- beg skip-flag result
- word-beg)
- (if (> click-count 2)
- (save-excursion
- (beginning-of-line)
- (vip-skip-all-separators-forward 'within-line)
- (setq beg (point))
- (end-of-line)
- (setq result (buffer-substring beg (point))))
-
- (if (and (not (vip-looking-at-alphasep))
- (or (save-excursion (vip-backward-char-carefully)
- (vip-looking-at-alpha))
- (save-excursion (vip-forward-char-carefully)
- (vip-looking-at-alpha))))
- (setq modifiers
- (cond ((looking-at "\\\\") "\\\\")
- ((looking-at "-") "C-C-")
- ((looking-at "[][]") "][")
- ((looking-at "[()]") ")(")
- ((looking-at "[{}]") "{}")
- ((looking-at "[<>]") "<>")
- ((looking-at "[`']") "`'")
- ((looking-at "\\^") "\\^")
- ((vip-looking-at-separator) "")
- (t (char-to-string (following-char))))
- ))
-
- ;; Add `-' to alphanum, if it wasn't added and if we are in Lisp
- (or (looking-at "-")
- (not (string-match "lisp" (symbol-name major-mode)))
- (setq modifiers (concat modifiers "C-C-")))
-
-
- (save-excursion
- (cond ((> click-count 1) (vip-skip-nonseparators 'backward))
- ((vip-looking-at-alpha modifiers)
- (vip-skip-alpha-backward modifiers))
- ((not (vip-looking-at-alphasep modifiers))
- (vip-skip-nonalphasep-backward))
- (t (if (> click-count 1)
- (vip-skip-nonseparators 'backward)
- (vip-skip-alpha-backward modifiers))))
-
- (setq word-beg (point))
-
- (setq skip-flag nil) ; don't move 1 char forw the first time
- (while (> count 0)
- (if skip-flag (vip-forward-char-carefully 1))
- (setq skip-flag t) ; now always move 1 char forward
- (if (> click-count 1)
- (vip-skip-nonseparators 'forward)
- (vip-skip-alpha-forward modifiers))
- (setq count (1- count)))
-
- (setq result (buffer-substring word-beg (point))))
- ) ; if
- ;; XEmacs doesn't have set-text-properties, but there buffer-substring
- ;; doesn't return properties together with the string, so it's not needed.
- (if vip-emacs-p
- (set-text-properties 0 (length result) nil result))
- result
- ))
-
-
-(defun vip-mouse-click-get-word (click count click-count)
- "Returns word surrounding the position of a mouse click.
-Click may be in another window. Current window and buffer isn't changed.
-On single or double click, returns the word as determined by
-`vip-surrounding-word-function'."
-
- (let ((click-word "")
- (click-pos (vip-mouse-click-posn click))
- (click-buf (vip-mouse-click-window-buffer click)))
- (or (natnump count) (setq count 1))
- (or (natnump click-count) (setq click-count 1))
-
- (save-excursion
- (save-window-excursion
- (if click-pos
- (progn
- (set-buffer click-buf)
-
- (goto-char click-pos)
- (setq click-word
- (funcall vip-surrounding-word-function count click-count)))
- (error "Click must be over a window."))
- click-word))))
-
-
-(defun vip-mouse-click-insert-word (click arg)
- "Insert word clicked or double-clicked on.
-With prefix argument, N, insert that many words.
-This command must be bound to a mouse click.
-The double-click action of the same mouse button must not be bound
-\(or it must be bound to the same function\).
-See `vip-surrounding-word' for the definition of a word in this case."
- (interactive "e\nP")
- (if vip-frame-of-focus ;; to handle clicks in another frame
- (select-frame vip-frame-of-focus))
-
- ;; turn arg into a number
- (cond ((integerp arg) nil)
- ;; prefix arg is a list when one hits C-u then command
- ((and (listp arg) (integerp (car arg)))
- (setq arg (car arg)))
- (t (setq arg 1)))
-
- (let (click-count interrupting-event)
- (if (and
- (vip-multiclick-p)
- ;; This trick checks if there is a pending mouse event
- ;; if so, we use this latter event and discard the current mouse click
- ;; If the next pending event is not a mouse event, we execute
- ;; the current mouse event
- (progn
- (setq interrupting-event (vip-read-event))
- (vip-mouse-event-p last-input-event)))
- (progn ;; interrupted wait
- (setq vip-global-prefix-argument arg)
- ;; count this click for XEmacs
- (vip-event-click-count click))
- ;; uninterrupted wait or the interrupting event wasn't a mouse event
- (setq click-count (vip-event-click-count click))
- (if (> click-count 1)
- (setq arg vip-global-prefix-argument
- vip-global-prefix-argument nil))
- (insert (vip-mouse-click-get-word click arg click-count))
- (if (and interrupting-event
- (eventp interrupting-event)
- (not (vip-mouse-event-p interrupting-event)))
- (vip-set-unread-command-events interrupting-event))
- )))
-
-;; arg is an event. accepts symbols and numbers, too
-(defun vip-mouse-event-p (event)
- (if (eventp event)
- (string-match "\\(mouse-\\|frame\\|screen\\|track\\)"
- (prin1-to-string (vip-event-key event)))))
-
-;; XEmacs has no double-click events. So, we must simulate.
-;; So, we have to simulate event-click-count.
-(defun vip-event-click-count (click)
- (if vip-xemacs-p
- (progn
- ;; if more than 1 second
- (if (> (- (event-timestamp click) vip-last-click-event-timestamp)
- vip-multiclick-timeout)
- (setq vip-current-click-count 0))
- (setq vip-last-click-event-timestamp (event-timestamp click)
- vip-current-click-count (1+ vip-current-click-count)))
- (event-click-count click)))
-
-
-
-(defun vip-mouse-click-search-word (click arg)
- "Find the word clicked or double-clicked on. Word may be in another window.
-With prefix argument, N, search for N-th occurrence.
-This command must be bound to a mouse click. The double-click action of the
-same button must not be bound \(or it must be bound to the same function\).
-See `vip-surrounding-word' for the details on what constitutes a word for
-this command."
- (interactive "e\nP")
- (if vip-frame-of-focus ;; to handle clicks in another frame
- (select-frame vip-frame-of-focus))
- (let (click-word click-count
- (previous-search-string vip-s-string))
-
- (if (and
- (vip-multiclick-p)
- ;; This trick checks if there is a pending mouse event
- ;; if so, we use this latter event and discard the current mouse click
- ;; If the next pending event is not a mouse event, we execute
- ;; the current mouse event
- (progn
- (vip-read-event)
- (vip-mouse-event-p last-input-event)))
- (progn ;; interrupted wait
- (setq vip-global-prefix-argument
- (or vip-global-prefix-argument arg))
- ;; remember command that was before the multiclick
- (setq this-command last-command)
- ;; make sure we counted this event---needed for XEmacs only
- (vip-event-click-count click))
- ;; uninterrupted wait
- (setq click-count (vip-event-click-count click))
- (setq click-word (vip-mouse-click-get-word click nil click-count))
-
- (if (> click-count 1)
- (setq arg vip-global-prefix-argument
- vip-global-prefix-argument nil))
- (setq arg (or arg 1))
-
- (vip-deactivate-mark)
- (if (or (not (string= click-word vip-s-string))
- (not (markerp vip-search-start-marker))
- (not (equal (marker-buffer vip-search-start-marker)
- (current-buffer)))
- (not (eq last-command 'vip-mouse-click-search-word)))
- (progn
- (setq vip-search-start-marker (point-marker)
- vip-local-search-start-marker vip-search-start-marker
- vip-mouse-click-search-noerror t
- vip-mouse-click-search-limit nil)
-
- ;; make search string known to Viper
- (setq vip-s-string (if vip-re-search
- (regexp-quote click-word)
- click-word))
- (if (not (string= vip-s-string (car vip-search-history)))
- (setq vip-search-history
- (cons vip-s-string vip-search-history)))
- ))
-
- (push-mark nil t)
- (while (> arg 0)
- (vip-forward-word 1)
- (condition-case nil
- (progn
- (if (not (search-forward click-word vip-mouse-click-search-limit
- vip-mouse-click-search-noerror))
- (progn
- (setq vip-mouse-click-search-noerror nil)
- (setq vip-mouse-click-search-limit
- (save-excursion
- (if (and
- (markerp vip-local-search-start-marker)
- (marker-buffer vip-local-search-start-marker))
- (goto-char vip-local-search-start-marker))
- (vip-line-pos 'end)))
-
- (goto-char (point-min))
- (search-forward click-word
- vip-mouse-click-search-limit nil)))
- (goto-char (match-beginning 0))
- (message "Searching for: %s" vip-s-string)
- (if (<= arg 1) ; found the right occurrence of the pattern
- (progn
- (vip-adjust-window)
- (vip-flash-search-pattern)))
- )
- (error (beep 1)
- (if (or (not (string= click-word previous-search-string))
- (not (eq last-command 'vip-mouse-click-search-word)))
- (message "`%s': String not found in %s"
- vip-s-string (buffer-name (current-buffer)))
- (message
- "`%s': Last occurrence in %s. Back to beginning of search"
- click-word (buffer-name (current-buffer)))
- (setq arg 1) ;; to terminate the loop
- (sit-for 2))
- (setq vip-mouse-click-search-noerror t)
- (setq vip-mouse-click-search-limit nil)
- (if (and (markerp vip-local-search-start-marker)
- (marker-buffer vip-local-search-start-marker))
- (goto-char vip-local-search-start-marker))))
- (setq arg (1- arg)))
- )))
-
-(defun vip-mouse-catch-frame-switch (event arg)
- "Catch the event of switching frame.
-Usually is bound to a 'down-mouse' event to work properly. See sample
-bindings in viper.el and in the Viper manual."
- (interactive "e\nP")
- (setq vip-frame-of-focus nil)
- ;; pass prefix arg along to vip-mouse-click-search/insert-word
- (setq prefix-arg arg)
- (if (eq last-command 'handle-switch-frame)
- (setq vip-frame-of-focus vip-current-frame-saved))
- ;; make Emacs forget that it executed vip-mouse-catch-frame-switch
- (setq this-command last-command))
-
-;; Called just before switching frames. Saves the old selected frame.
-;; Sets last-command to handle-switch-frame (this is done automatically in
-;; Emacs.
-;; The semantics of switching frames is different in Emacs and XEmacs.
-;; In Emacs, if you select-frame A while mouse is over frame B and then
-;; start typing, input goes to frame B, which becomes selected.
-;; In XEmacs, input will go to frame A. This may be a bug in one of the
-;; Emacsen, but also may be a design decision.
-;; Also, in Emacs sending input to frame B generates handle-switch-frame
-;; event, while in XEmacs it doesn't.
-;; All this accounts for the difference in the behavior of
-;; vip-mouse-click-* commands when you click in a frame other than the one
-;; that was the last to receive input. In Emacs, focus will be in frame A
-;; until you do something other than vip-mouse-click-* command.
-;; In XEmacs, you have to manually select frame B (with the mouse click) in
-;; order to shift focus to frame B.
-(defsubst vip-remember-current-frame (frame)
- (setq last-command 'handle-switch-frame
- vip-current-frame-saved (selected-frame)))
-
-
-(cond ((vip-window-display-p)
- (let* ((search-key (if vip-xemacs-p
- [(meta shift button1up)] [M-S-mouse-1]))
- (search-key-catch (if vip-xemacs-p
- [(meta shift button1)] [M-S-down-mouse-1]))
- (insert-key (if vip-xemacs-p
- [(meta shift button2up)] [M-S-mouse-2]))
- (insert-key-catch (if vip-xemacs-p
- [(meta shift button2)] [M-S-down-mouse-2]))
- (search-key-unbound (and (not (key-binding search-key))
- (not (key-binding search-key-catch))))
- (insert-key-unbound (and (not (key-binding insert-key))
- (not (key-binding insert-key-catch))))
- )
-
- (if search-key-unbound
- (global-set-key search-key 'vip-mouse-click-search-word))
- (if insert-key-unbound
- (global-set-key insert-key 'vip-mouse-click-insert-word))
-
- ;; The following would be needed if you want to use the above two
- ;; while clicking in another frame. If you only want to use them
- ;; by clicking in another window, not frame, the bindings below
- ;; aren't necessary.
-
- ;; These must be bound to mouse-down event for the same mouse
- ;; buttons as 'vip-mouse-click-search-word and
- ;; 'vip-mouse-click-insert-word
- (if search-key-unbound
- (global-set-key search-key-catch 'vip-mouse-catch-frame-switch))
- (if insert-key-unbound
- (global-set-key insert-key-catch 'vip-mouse-catch-frame-switch))
-
- (if vip-xemacs-p
- (add-hook 'mouse-leave-frame-hook
- 'vip-remember-current-frame)
- (defadvice handle-switch-frame (before vip-frame-advice activate)
- "Remember the selected frame before the switch-frame event."
- (vip-remember-current-frame (selected-frame))))
- )))
-
-
-
-(provide 'viper-mous)
-
-;;; viper-mous.el ends here
diff --git a/lisp/emulation/viper-util.el b/lisp/emulation/viper-util.el
deleted file mode 100644
index 059e840d3a4..00000000000
--- a/lisp/emulation/viper-util.el
+++ /dev/null
@@ -1,1269 +0,0 @@
-;;; viper-util.el --- Utilities used by viper.el
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-
-;; Code
-
-(require 'ring)
-
-;; Compiler pacifier
-(defvar vip-overriding-map)
-(defvar pm-color-alist)
-(defvar zmacs-region-stays)
-(defvar vip-search-face)
-(defvar vip-minibuffer-current-face)
-(defvar vip-minibuffer-insert-face)
-(defvar vip-minibuffer-vi-face)
-(defvar vip-minibuffer-emacs-face)
-(defvar vip-replace-overlay-face)
-(defvar vip-minibuffer-overlay)
-(defvar vip-replace-overlay)
-(defvar vip-search-overlay)
-(defvar vip-replace-overlay-cursor-color)
-(defvar vip-intermediate-command)
-(defvar vip-use-replace-region-delimiters)
-(defvar vip-fast-keyseq-timeout)
-(defvar vip-related-files-and-buffers-ring)
-;; end compiler pacifier
-
-;; Is it XEmacs?
-(defconst vip-xemacs-p (string-match "\\(Lucid\\|XEmacs\\)" emacs-version))
-;; Is it Emacs?
-(defconst vip-emacs-p (not vip-xemacs-p))
-;; Tell whether we are running as a window application or on a TTY
-(defsubst vip-device-type ()
- (if vip-emacs-p
- window-system
- (device-type (selected-device))))
-;; in XEmacs: device-type is tty on tty and stream in batch.
-(defun vip-window-display-p ()
- (and (vip-device-type) (not (memq (vip-device-type) '(tty stream pc)))))
-
-(defvar vip-ms-style-os-p (memq system-type '(ms-dos windows-nt windows-95))
- "Tells if Emacs is running under an MS-style OS: ms-dos, windows-nt, W95.")
-(defvar vip-vms-os-p (memq system-type '(vax-vms axp-vms))
- "Tells if Emacs is running under VMS.")
-
-(defvar vip-force-faces nil
- "If t, Viper will think that it is running on a display that supports faces.
-This is provided as a temporary relief for users of face-capable displays
-that Viper doesn't know about.")
-
-(defun vip-has-face-support-p ()
- (cond ((vip-window-display-p))
- (vip-force-faces)
- (vip-emacs-p (memq (vip-device-type) '(pc)))
- (vip-xemacs-p (memq (vip-device-type) '(tty pc)))))
-
-
-;;; Macros
-
-(defmacro vip-deflocalvar (var default-value &optional documentation)
- (` (progn
- (defvar (, var) (, default-value)
- (, (format "%s\n\(buffer local\)" documentation)))
- (make-variable-buffer-local '(, var))
- )))
-
-(defmacro vip-loop (count body)
- "(vip-loop COUNT BODY) Execute BODY COUNT times."
- (list 'let (list (list 'count count))
- (list 'while '(> count 0)
- body
- '(setq count (1- count))
- )))
-
-(defmacro vip-buffer-live-p (buf)
- (` (and (, buf) (get-buffer (, buf)) (buffer-name (get-buffer (, buf))))))
-
-;; return buffer-specific macro definition, given a full macro definition
-(defmacro vip-kbd-buf-alist (macro-elt)
- (` (nth 1 (, macro-elt))))
-;; get a pair: (curr-buffer . macro-definition)
-(defmacro vip-kbd-buf-pair (macro-elt)
- (` (assoc (buffer-name) (vip-kbd-buf-alist (, macro-elt)))))
-;; get macro definition for current buffer
-(defmacro vip-kbd-buf-definition (macro-elt)
- (` (cdr (vip-kbd-buf-pair (, macro-elt)))))
-
-;; return mode-specific macro definitions, given a full macro definition
-(defmacro vip-kbd-mode-alist (macro-elt)
- (` (nth 2 (, macro-elt))))
-;; get a pair: (major-mode . macro-definition)
-(defmacro vip-kbd-mode-pair (macro-elt)
- (` (assoc major-mode (vip-kbd-mode-alist (, macro-elt)))))
-;; get macro definition for the current major mode
-(defmacro vip-kbd-mode-definition (macro-elt)
- (` (cdr (vip-kbd-mode-pair (, macro-elt)))))
-
-;; return global macro definition, given a full macro definition
-(defmacro vip-kbd-global-pair (macro-elt)
- (` (nth 3 (, macro-elt))))
-;; get global macro definition from an elt of macro-alist
-(defmacro vip-kbd-global-definition (macro-elt)
- (` (cdr (vip-kbd-global-pair (, macro-elt)))))
-
-;; last elt of a sequence
-(defsubst vip-seq-last-elt (seq)
- (elt seq (1- (length seq))))
-
-;; Check if arg is a valid character for register
-;; TYPE is a list that can contain `letter', `Letter', and `digit'.
-;; Letter means lowercase letters, Letter means uppercase letters, and
-;; digit means digits from 1 to 9.
-;; If TYPE is nil, then down/uppercase letters and digits are allowed.
-(defun vip-valid-register (reg &optional type)
- (or type (setq type '(letter Letter digit)))
- (or (if (memq 'letter type)
- (and (<= ?a reg) (<= reg ?z)))
- (if (memq 'digit type)
- (and (<= ?1 reg) (<= reg ?9)))
- (if (memq 'Letter type)
- (and (<= ?A reg) (<= reg ?Z)))
- ))
-
-;; checks if object is a marker, has a buffer, and points to within that buffer
-(defun vip-valid-marker (marker)
- (if (and (markerp marker) (marker-buffer marker))
- (let ((buf (marker-buffer marker))
- (pos (marker-position marker)))
- (save-excursion
- (set-buffer buf)
- (and (<= pos (point-max)) (<= (point-min) pos))))))
-
-
-(defvar vip-minibuffer-overlay-priority 300)
-(defvar vip-replace-overlay-priority 400)
-(defvar vip-search-overlay-priority 500)
-
-
-;;; XEmacs support
-
-(if vip-xemacs-p
- (progn
- (fset 'vip-read-event (symbol-function 'next-command-event))
- (fset 'vip-make-overlay (symbol-function 'make-extent))
- (fset 'vip-overlay-start (symbol-function 'extent-start-position))
- (fset 'vip-overlay-end (symbol-function 'extent-end-position))
- (fset 'vip-overlay-put (symbol-function 'set-extent-property))
- (fset 'vip-overlay-p (symbol-function 'extentp))
- (fset 'vip-overlay-get (symbol-function 'extent-property))
- (fset 'vip-move-overlay (symbol-function 'set-extent-endpoints))
- (if (vip-window-display-p)
- (fset 'vip-iconify (symbol-function 'iconify-frame)))
- (cond ((vip-has-face-support-p)
- (fset 'vip-get-face (symbol-function 'get-face))
- (fset 'vip-color-defined-p
- (symbol-function 'valid-color-name-p))
- )))
- (fset 'vip-read-event (symbol-function 'read-event))
- (fset 'vip-make-overlay (symbol-function 'make-overlay))
- (fset 'vip-overlay-start (symbol-function 'overlay-start))
- (fset 'vip-overlay-end (symbol-function 'overlay-end))
- (fset 'vip-overlay-put (symbol-function 'overlay-put))
- (fset 'vip-overlay-p (symbol-function 'overlayp))
- (fset 'vip-overlay-get (symbol-function 'overlay-get))
- (fset 'vip-move-overlay (symbol-function 'move-overlay))
- (if (vip-window-display-p)
- (fset 'vip-iconify (symbol-function 'iconify-or-deiconify-frame)))
- (cond ((vip-has-face-support-p)
- (fset 'vip-get-face (symbol-function 'internal-get-face))
- (fset 'vip-color-defined-p (symbol-function 'x-color-defined-p))
- )))
-
-(fset 'vip-characterp
- (symbol-function
- (if vip-xemacs-p 'characterp 'integerp)))
-
-(defsubst vip-color-display-p ()
- (if vip-emacs-p
- (x-display-color-p)
- (eq (device-class (selected-device)) 'color)))
-
-(defsubst vip-get-cursor-color ()
- (if vip-emacs-p
- (cdr (assoc 'cursor-color (frame-parameters)))
- (color-instance-name (frame-property (selected-frame) 'cursor-color))))
-
-(defun vip-set-face-pixmap (face pixmap)
- "Set face pixmap on a monochrome display."
- (if (and (vip-window-display-p) (not (vip-color-display-p)))
- (condition-case nil
- (set-face-background-pixmap face pixmap)
- (error
- (message "Pixmap not found for %S: %s" (face-name face) pixmap)
- (sit-for 1)))))
-
-
-;; OS/2
-(cond ((eq (vip-device-type) 'pm)
- (fset 'vip-color-defined-p
- (function (lambda (color) (assoc color pm-color-alist))))))
-
-;; needed to smooth out the difference between Emacs and XEmacs
-(defsubst vip-italicize-face (face)
- (if vip-xemacs-p
- (make-face-italic face)
- (make-face-italic face nil 'noerror)))
-
-;; test if display is color and the colors are defined
-(defsubst vip-can-use-colors (&rest colors)
- (if (vip-color-display-p)
- (not (memq nil (mapcar 'vip-color-defined-p colors)))
- ))
-
-(defun vip-hide-face (face)
- (if (and (vip-has-face-support-p) vip-emacs-p)
- (add-to-list 'facemenu-unlisted-faces face)))
-
-;; cursor colors
-(defun vip-change-cursor-color (new-color)
- (if (and (vip-window-display-p) (vip-color-display-p)
- (stringp new-color) (vip-color-defined-p new-color)
- (not (string= new-color (vip-get-cursor-color))))
- (modify-frame-parameters
- (selected-frame) (list (cons 'cursor-color new-color)))))
-
-(defsubst vip-save-cursor-color ()
- (if (and (vip-window-display-p) (vip-color-display-p))
- (let ((color (vip-get-cursor-color)))
- (if (and (stringp color) (vip-color-defined-p color)
- (not (string= color vip-replace-overlay-cursor-color)))
- (vip-overlay-put vip-replace-overlay 'vip-cursor-color color)))))
-
-;; restore cursor color from replace overlay
-(defsubst vip-restore-cursor-color-after-replace ()
- (vip-change-cursor-color
- (vip-overlay-get vip-replace-overlay 'vip-cursor-color)))
-(defsubst vip-restore-cursor-color-after-insert ()
- (vip-change-cursor-color vip-saved-cursor-color))
-
-
-;; Check the current version against the major and minor version numbers
-;; using op: cur-vers op major.minor If emacs-major-version or
-;; emacs-minor-version are not defined, we assume that the current version
-;; is hopelessly outdated. We assume that emacs-major-version and
-;; emacs-minor-version are defined. Otherwise, for Emacs/XEmacs 19, if the
-;; current minor version is < 10 (xemacs) or < 23 (emacs) the return value
-;; will be nil (when op is =, >, or >=) and t (when op is <, <=), which may be
-;; incorrect. However, this gives correct result in our cases, since we are
-;; testing for sufficiently high Emacs versions.
-(defun vip-check-version (op major minor &optional type-of-emacs)
- (if (and (boundp 'emacs-major-version) (boundp 'emacs-minor-version))
- (and (cond ((eq type-of-emacs 'xemacs) vip-xemacs-p)
- ((eq type-of-emacs 'emacs) vip-emacs-p)
- (t t))
- (cond ((eq op '=) (and (= emacs-minor-version minor)
- (= emacs-major-version major)))
- ((memq op '(> >= < <=))
- (and (or (funcall op emacs-major-version major)
- (= emacs-major-version major))
- (if (= emacs-major-version major)
- (funcall op emacs-minor-version minor)
- t)))
- (t
- (error "%S: Invalid op in vip-check-version" op))))
- (cond ((memq op '(= > >=)) nil)
- ((memq op '(< <=)) t))))
-
-;;;; warn if it is a wrong version of emacs
-;;(if (or (vip-check-version '< 19 29 'emacs)
-;; (vip-check-version '< 19 12 'xemacs))
-;; (progn
-;; (with-output-to-temp-buffer " *vip-info*"
-;; (switch-to-buffer " *vip-info*")
-;; (insert
-;; (format "
-;;
-;;This version of Viper requires
-;;
-;;\t Emacs 19.29 and higher
-;;\t OR
-;;\t XEmacs 19.12 and higher
-;;
-;;It is unlikely to work under Emacs version %s
-;;that you are using... " emacs-version))
-;;
-;; (if noninteractive
-;; ()
-;; (beep 1)
-;; (beep 1)
-;; (insert "\n\nType any key to continue... ")
-;; (vip-read-event)))
-;; (kill-buffer " *vip-info*")))
-
-
-(defun vip-get-visible-buffer-window (wind)
- (if vip-xemacs-p
- (get-buffer-window wind t)
- (get-buffer-window wind 'visible)))
-
-
-;; Return line position.
-;; If pos is 'start then returns position of line start.
-;; If pos is 'end, returns line end. If pos is 'mid, returns line center.
-;; Pos = 'indent returns beginning of indentation.
-;; Otherwise, returns point. Current point is not moved in any case."
-(defun vip-line-pos (pos)
- (let ((cur-pos (point))
- (result))
- (cond
- ((equal pos 'start)
- (beginning-of-line))
- ((equal pos 'end)
- (end-of-line))
- ((equal pos 'mid)
- (goto-char (+ (vip-line-pos 'start) (vip-line-pos 'end) 2)))
- ((equal pos 'indent)
- (back-to-indentation))
- (t nil))
- (setq result (point))
- (goto-char cur-pos)
- result))
-
-
-;; Like move-marker but creates a virgin marker if arg isn't already a marker.
-;; The first argument must eval to a variable name.
-;; Arguments: (var-name position &optional buffer).
-;;
-;; This is useful for moving markers that are supposed to be local.
-;; For this, VAR-NAME should be made buffer-local with nil as a default.
-;; Then, each time this var is used in `vip-move-marker-locally' in a new
-;; buffer, a new marker will be created.
-(defun vip-move-marker-locally (var pos &optional buffer)
- (if (markerp (eval var))
- ()
- (set var (make-marker)))
- (move-marker (eval var) pos buffer))
-
-
-;; Print CONDITIONS as a message.
-(defun vip-message-conditions (conditions)
- (let ((case (car conditions)) (msg (cdr conditions)))
- (if (null msg)
- (message "%s" case)
- (message "%s: %s" case (mapconcat 'prin1-to-string msg " ")))
- (beep 1)))
-
-
-
-;;; List/alist utilities
-
-;; Convert LIST to an alist
-(defun vip-list-to-alist (lst)
- (let ((alist))
- (while lst
- (setq alist (cons (list (car lst)) alist))
- (setq lst (cdr lst)))
- alist))
-
-;; Convert ALIST to a list.
-(defun vip-alist-to-list (alst)
- (let ((lst))
- (while alst
- (setq lst (cons (car (car alst)) lst))
- (setq alst (cdr alst)))
- lst))
-
-;; Filter ALIST using REGEXP. Return alist whose elements match the regexp.
-(defun vip-filter-alist (regexp alst)
- (interactive "s x")
- (let ((outalst) (inalst alst))
- (while (car inalst)
- (if (string-match regexp (car (car inalst)))
- (setq outalst (cons (car inalst) outalst)))
- (setq inalst (cdr inalst)))
- outalst))
-
-;; Filter LIST using REGEXP. Return list whose elements match the regexp.
-(defun vip-filter-list (regexp lst)
- (interactive "s x")
- (let ((outlst) (inlst lst))
- (while (car inlst)
- (if (string-match regexp (car inlst))
- (setq outlst (cons (car inlst) outlst)))
- (setq inlst (cdr inlst)))
- outlst))
-
-
-;; Append LIS2 to LIS1, both alists, by side-effect and returns LIS1
-;; LIS2 is modified by filtering it: deleting its members of the form
-;; \(car elt\) such that (car elt') is in LIS1.
-(defun vip-append-filter-alist (lis1 lis2)
- (let ((temp lis1)
- elt)
-
- ;;filter-append the second list
- (while temp
- ;; delete all occurrences
- (while (setq elt (assoc (car (car temp)) lis2))
- (setq lis2 (delq elt lis2)))
- (setq temp (cdr temp)))
-
- (nconc lis1 lis2)))
-
-
-;;; Support for :e and file globbing
-
-(defun vip-ex-nontrivial-find-file-unix (filespec)
- "Glob the file spec and visit all files matching the spec.
-This function is designed to work under Unix. It may also work under VMS.
-
-Users who prefer other types of shells should write their own version of this
-function and set the variable `ex-nontrivial-find-file-function'
-appropriately."
- (let ((gshell
- (cond (ex-unix-type-shell shell-file-name)
- ((memq system-type '(vax-vms axp-vms)) "*dcl*") ; VAX VMS
- (t "sh"))) ; probably Unix anyway
- (gshell-options
- ;; using cond in anticipation of further additions
- (cond (ex-unix-type-shell-options)
- ))
- (command (cond (vip-ms-style-os-p (format "\"ls -1 -d %s\"" filespec))
- (t (format "ls -1 -d %s" filespec))))
- file-list status)
- (save-excursion
- (set-buffer (get-buffer-create vip-ex-tmp-buf-name))
- (erase-buffer)
- (setq status
- (if gshell-options
- (call-process gshell nil t nil
- gshell-options
- "-c"
- command)
- (call-process gshell nil t nil
- "-c"
- command)))
- (goto-char (point-min))
- ;; Issue an error, if no match.
- (if (> status 0)
- (save-excursion
- (skip-chars-forward " \t\n\j")
- (if (looking-at "ls:")
- (vip-forward-Word 1))
- (error "%s: %s"
- (if (stringp gshell)
- gshell
- "shell")
- (buffer-substring (point) (vip-line-pos 'end)))
- ))
- (goto-char (point-min))
- (setq file-list (vip-get-filenames-from-buffer 'one-per-line)))
-
- (mapcar 'find-file file-list)
- ))
-
-(defun vip-ex-nontrivial-find-file-ms (filespec)
- "Glob the file spec and visit all files matching the spec.
-This function is designed to work under MS type systems, such as NT, W95, and
-DOS. It may also work under OS/2.
-
-The users of Unix-type shells should be able to use
-`vip-ex-nontrivial-find-file-unix', making it into the value of the variable
-`ex-nontrivial-find-file-function'. If this doesn't work, the user may have
-to write a custom function, similar to `vip-ex-nontrivial-find-file-unix'."
- (save-excursion
- (set-buffer (get-buffer-create vip-ex-tmp-buf-name))
- (erase-buffer)
- (insert filespec)
- (goto-char (point-min))
- (mapcar 'find-file
- (vip-glob-ms-windows-files (vip-get-filenames-from-buffer)))
- ))
-
-
-;; Interpret the stuff in the buffer as a list of file names
-;; return a list of file names listed in the buffer beginning at point
-;; If optional arg is supplied, assume each filename is listed on a separate
-;; line
-(defun vip-get-filenames-from-buffer (&optional one-per-line)
- (let ((skip-chars (if one-per-line "\t\n" " \t\n"))
- result fname delim)
- (skip-chars-forward skip-chars)
- (while (not (eobp))
- (if (cond ((looking-at "\"")
- (setq delim ?\")
- (re-search-forward "[^\"]+" nil t)) ; noerror
- ((looking-at "'")
- (setq delim ?')
- (re-search-forward "[^']+" nil t)) ; noerror
- (t
- (re-search-forward
- (concat "[^" skip-chars "]+") nil t))) ;noerror
- (setq fname
- (buffer-substring (match-beginning 0) (match-end 0))))
- (if delim
- (forward-char 1))
- (skip-chars-forward " \t\n")
- (setq result (cons fname result)))
- result))
-
-;; convert MS-DOS wildcards to regexp
-(defun vip-wildcard-to-regexp (wcard)
- (save-excursion
- (set-buffer (get-buffer-create vip-ex-tmp-buf-name))
- (erase-buffer)
- (insert wcard)
- (goto-char (point-min))
- (while (not (eobp))
- (skip-chars-forward "^*?.\\\\")
- (cond ((eq (char-after (point)) ?*) (insert ".")(forward-char 1))
- ((eq (char-after (point)) ?.) (insert "\\")(forward-char 1))
- ((eq (char-after (point)) ?\\) (insert "\\")(forward-char 1))
- ((eq (char-after (point)) ??) (delete-char 1)(insert ".")))
- )
- (buffer-string)
- ))
-
-
-;; glob windows files
-;; LIST is expected to be in reverse order
-(defun vip-glob-ms-windows-files (list)
- (let ((tmp list)
- (case-fold-search t)
- tmp2)
- (while tmp
- (setq tmp2 (cons (directory-files
- ;; the directory part
- (or (file-name-directory (car tmp))
- "")
- t ; return full names
- ;; the regexp part: globs the file names
- (concat "^"
- (vip-wildcard-to-regexp
- (file-name-nondirectory (car tmp)))
- "$"))
- tmp2))
- (setq tmp (cdr tmp)))
- (reverse (apply 'append tmp2))))
-
-(defun vip-convert-standard-file-name (fname)
- (if vip-emacs-p
- (convert-standard-filename fname)
- ;; hopefully, XEmacs adds this functionality
- fname))
-
-
-
-;;; Insertion ring
-
-;; Rotate RING's index. DIRection can be positive or negative.
-(defun vip-ring-rotate1 (ring dir)
- (if (and (ring-p ring) (> (ring-length ring) 0))
- (progn
- (setcar ring (cond ((> dir 0)
- (ring-plus1 (car ring) (ring-length ring)))
- ((< dir 0)
- (ring-minus1 (car ring) (ring-length ring)))
- ;; don't rotate if dir = 0
- (t (car ring))))
- (vip-current-ring-item ring)
- )))
-
-(defun vip-special-ring-rotate1 (ring dir)
- (if (memq vip-intermediate-command
- '(repeating-display-destructive-command
- repeating-insertion-from-ring))
- (vip-ring-rotate1 ring dir)
- ;; don't rotate otherwise
- (vip-ring-rotate1 ring 0)))
-
-;; current ring item; if N is given, then so many items back from the
-;; current
-(defun vip-current-ring-item (ring &optional n)
- (setq n (or n 0))
- (if (and (ring-p ring) (> (ring-length ring) 0))
- (aref (cdr (cdr ring)) (mod (- (car ring) 1 n) (ring-length ring)))))
-
-;; push item onto ring. the second argument is a ring-variable, not value.
-(defun vip-push-onto-ring (item ring-var)
- (or (ring-p (eval ring-var))
- (set ring-var (make-ring (eval (intern (format "%S-size" ring-var))))))
- (or (null item) ; don't push nil
- (and (stringp item) (string= item "")) ; or empty strings
- (equal item (vip-current-ring-item (eval ring-var))) ; or old stuff
- ;; Since vip-set-destructive-command checks if we are inside vip-repeat,
- ;; we don't check whether this-command-keys is a `.'.
- ;; The cmd vip-repeat makes a call to the current function only if
- ;; `.' is executing a command from the command history. It doesn't
- ;; call the push-onto-ring function if `.' is simply repeating the
- ;; last destructive command.
- ;; We only check for ESC (which happens when we do insert with a
- ;; prefix argument, or if this-command-keys doesn't give anything
- ;; meaningful (in that case we don't know what to show to the user).
- (and (eq ring-var 'vip-command-ring)
- (string-match "\\([0-9]*\e\\|^[ \t]*$\\|escape\\)"
- (vip-array-to-string (this-command-keys))))
- (vip-ring-insert (eval ring-var) item))
- )
-
-
-;; removing elts from ring seems to break it
-(defun vip-cleanup-ring (ring)
- (or (< (ring-length ring) 2)
- (null (vip-current-ring-item ring))
- ;; last and previous equal
- (if (equal (vip-current-ring-item ring) (vip-current-ring-item ring 1))
- (vip-ring-pop ring))))
-
-;; ring-remove seems to be buggy, so we concocted this for our purposes.
-(defun vip-ring-pop (ring)
- (let* ((ln (ring-length ring))
- (vec (cdr (cdr ring)))
- (veclen (length vec))
- (hd (car ring))
- (idx (max 0 (ring-minus1 hd ln)))
- (top-elt (aref vec idx)))
-
- ;; shift elements
- (while (< (1+ idx) veclen)
- (aset vec idx (aref vec (1+ idx)))
- (setq idx (1+ idx)))
- (aset vec idx nil)
-
- (setq hd (max 0 (ring-minus1 hd ln)))
- (if (= hd (1- ln)) (setq hd 0))
- (setcar ring hd) ; move head
- (setcar (cdr ring) (max 0 (1- ln))) ; adjust length
- top-elt
- ))
-
-(defun vip-ring-insert (ring item)
- (let* ((ln (ring-length ring))
- (vec (cdr (cdr ring)))
- (veclen (length vec))
- (hd (car ring))
- (vecpos-after-hd (if (= hd 0) ln hd))
- (idx ln))
-
- (if (= ln veclen)
- (progn
- (aset vec hd item) ; hd is always 1+ the actual head index in vec
- (setcar ring (ring-plus1 hd ln)))
- (setcar (cdr ring) (1+ ln))
- (setcar ring (ring-plus1 vecpos-after-hd (1+ ln)))
- (while (and (>= idx vecpos-after-hd) (> ln 0))
- (aset vec idx (aref vec (1- idx)))
- (setq idx (1- idx)))
- (aset vec vecpos-after-hd item))
- item))
-
-
-;;; String utilities
-
-;; If STRING is longer than MAX-LEN, truncate it and print ...... instead
-;; PRE-STRING is a string to prepend to the abbrev string.
-;; POST-STRING is a string to append to the abbrev string.
-;; ABBREV_SIGN is a string to be inserted before POST-STRING
-;; if the orig string was truncated.
-(defun vip-abbreviate-string (string max-len
- pre-string post-string abbrev-sign)
- (let (truncated-str)
- (setq truncated-str
- (if (stringp string)
- (substring string 0 (min max-len (length string)))))
- (cond ((null truncated-str) "")
- ((> (length string) max-len)
- (format "%s%s%s%s"
- pre-string truncated-str abbrev-sign post-string))
- (t (format "%s%s%s" pre-string truncated-str post-string)))))
-
-;; tells if we are over a whitespace-only line
-(defsubst vip-over-whitespace-line ()
- (save-excursion
- (beginning-of-line)
- (looking-at "^[ \t]*$")))
-
-
-;;; Saving settings in custom file
-
-;; Save the current setting of VAR in CUSTOM-FILE.
-;; If given, MESSAGE is a message to be displayed after that.
-;; This message is erased after 2 secs, if erase-msg is non-nil.
-;; Arguments: var message custom-file &optional erase-message
-(defun vip-save-setting (var message custom-file &optional erase-msg)
- (let* ((var-name (symbol-name var))
- (var-val (if (boundp var) (eval var)))
- (regexp (format "^[^;]*%s[ \t\n]*[a-zA-Z---_']*[ \t\n)]" var-name))
- (buf (find-file-noselect (substitute-in-file-name custom-file)))
- )
- (message message)
- (save-excursion
- (set-buffer buf)
- (goto-char (point-min))
- (if (re-search-forward regexp nil t)
- (let ((reg-end (1- (match-end 0))))
- (search-backward var-name)
- (delete-region (match-beginning 0) reg-end)
- (goto-char (match-beginning 0))
- (insert (format "%s '%S" var-name var-val)))
- (goto-char (point-max))
- (if (not (bolp)) (insert "\n"))
- (insert (format "(setq %s '%S)\n" var-name var-val)))
- (save-buffer))
- (kill-buffer buf)
- (if erase-msg
- (progn
- (sit-for 2)
- (message "")))
- ))
-
-;; Save STRING in CUSTOM-FILE. If PATTERN is non-nil, remove strings that
-;; match this pattern.
-(defun vip-save-string-in-file (string custom-file &optional pattern)
- (let ((buf (find-file-noselect (substitute-in-file-name custom-file))))
- (save-excursion
- (set-buffer buf)
- (goto-char (point-min))
- (if pattern (delete-matching-lines pattern))
- (goto-char (point-max))
- (if string (insert string))
- (save-buffer))
- (kill-buffer buf)
- ))
-
-
-;;; Overlays
-
-;; Search
-
-(defun vip-flash-search-pattern ()
- (if (vip-overlay-p vip-search-overlay)
- (vip-move-overlay vip-search-overlay (match-beginning 0) (match-end 0))
- (setq vip-search-overlay
- (vip-make-overlay
- (match-beginning 0) (match-end 0) (current-buffer))))
-
- (vip-overlay-put vip-search-overlay 'priority vip-search-overlay-priority)
- (if (vip-has-face-support-p)
- (progn
- (vip-overlay-put vip-search-overlay 'face vip-search-face)
- (sit-for 2)
- (vip-overlay-put vip-search-overlay 'face nil))))
-
-
-;; Replace state
-
-(defsubst vip-move-replace-overlay (beg end)
- (vip-move-overlay vip-replace-overlay beg end))
-
-(defun vip-set-replace-overlay (beg end)
- (if (vip-overlay-p vip-replace-overlay)
- (vip-move-replace-overlay beg end)
- (setq vip-replace-overlay (vip-make-overlay beg end (current-buffer)))
- ;; never detach
- (vip-overlay-put
- vip-replace-overlay (if vip-emacs-p 'evaporate 'detachable) nil)
- (vip-overlay-put
- vip-replace-overlay 'priority vip-replace-overlay-priority))
- (if (vip-has-face-support-p)
- (vip-overlay-put vip-replace-overlay 'face vip-replace-overlay-face))
- (vip-save-cursor-color)
- (vip-change-cursor-color vip-replace-overlay-cursor-color)
- )
-
-
-(defsubst vip-set-replace-overlay-glyphs (before-glyph after-glyph)
- (if (or (not (vip-has-face-support-p))
- vip-use-replace-region-delimiters)
- (let ((before-name (if vip-xemacs-p 'begin-glyph 'before-string))
- (after-name (if vip-xemacs-p 'end-glyph 'after-string)))
- (vip-overlay-put vip-replace-overlay before-name before-glyph)
- (vip-overlay-put vip-replace-overlay after-name after-glyph))))
-
-(defsubst vip-hide-replace-overlay ()
- (vip-set-replace-overlay-glyphs nil nil)
- (vip-restore-cursor-color-after-replace)
- (vip-restore-cursor-color-after-insert)
- (if (vip-has-face-support-p)
- (vip-overlay-put vip-replace-overlay 'face nil)))
-
-
-(defsubst vip-replace-start ()
- (vip-overlay-start vip-replace-overlay))
-(defsubst vip-replace-end ()
- (vip-overlay-end vip-replace-overlay))
-
-
-;; Minibuffer
-
-(defun vip-set-minibuffer-overlay ()
- (vip-check-minibuffer-overlay)
- (if (vip-has-face-support-p)
- (progn
- (vip-overlay-put
- vip-minibuffer-overlay 'face vip-minibuffer-current-face)
- (vip-overlay-put
- vip-minibuffer-overlay 'priority vip-minibuffer-overlay-priority)
- ;; never detach
- (vip-overlay-put
- vip-minibuffer-overlay (if vip-emacs-p 'evaporate 'detachable) nil)
- ;; make vip-minibuffer-overlay open-ended
- ;; In emacs, it is made open ended at creation time
- (if vip-xemacs-p
- (progn
- (vip-overlay-put vip-minibuffer-overlay 'start-open nil)
- (vip-overlay-put vip-minibuffer-overlay 'end-open nil)))
- )))
-
-(defun vip-check-minibuffer-overlay ()
- (or (vip-overlay-p vip-minibuffer-overlay)
- (setq vip-minibuffer-overlay
- (if vip-xemacs-p
- (vip-make-overlay 1 (1+ (buffer-size)) (current-buffer))
- ;; make overlay open-ended
- (vip-make-overlay
- 1 (1+ (buffer-size)) (current-buffer) nil 'rear-advance)))
- ))
-
-
-(defsubst vip-is-in-minibuffer ()
- (string-match "\*Minibuf-" (buffer-name)))
-
-
-
-;;; XEmacs compatibility
-
-(defun vip-abbreviate-file-name (file)
- (if vip-emacs-p
- (abbreviate-file-name file)
- ;; XEmacs requires addl argument
- (abbreviate-file-name file t)))
-
-;; Sit for VAL milliseconds. XEmacs doesn't support the millisecond arg
-;; in sit-for, so this function smoothes out the differences.
-(defsubst vip-sit-for-short (val &optional nodisp)
- (if vip-xemacs-p
- (sit-for (/ val 1000.0) nodisp)
- (sit-for 0 val nodisp)))
-
-;; EVENT may be a single event of a sequence of events
-(defsubst vip-ESC-event-p (event)
- (let ((ESC-keys '(?\e (control \[) escape))
- (key (vip-event-key event)))
- (member key ESC-keys)))
-
-
-(defsubst vip-mark-marker ()
- (if vip-xemacs-p
- (mark-marker t)
- (mark-marker)))
-
-;; like (set-mark-command nil) but doesn't push twice, if (car mark-ring)
-;; is the same as (mark t).
-(defsubst vip-set-mark-if-necessary ()
- (setq mark-ring (delete (vip-mark-marker) mark-ring))
- (set-mark-command nil))
-
-;; In transient mark mode (zmacs mode), it is annoying when regions become
-;; highlighted due to Viper's pushing marks. So, we deactivate marks, unless
-;; the user explicitly wants highlighting, e.g., by hitting '' or ``
-(defun vip-deactivate-mark ()
- (if vip-xemacs-p
- (zmacs-deactivate-region)
- (deactivate-mark)))
-
-(defsubst vip-leave-region-active ()
- (if vip-xemacs-p
- (setq zmacs-region-stays t)))
-
-
-(defsubst vip-events-to-keys (events)
- (cond (vip-xemacs-p (events-to-keys events))
- (t events)))
-
-
-(defun vip-eval-after-load (file form)
- (if vip-emacs-p
- (eval-after-load file form)
- (or (assoc file after-load-alist)
- (setq after-load-alist (cons (list file) after-load-alist)))
- (let ((elt (assoc file after-load-alist)))
- (or (member form (cdr elt))
- (setq elt (nconc elt (list form)))))
- form
- ))
-
-;; This is here because Emacs changed the way local hooks work.
-;;
-;;Add to the value of HOOK the function FUNCTION.
-;;FUNCTION is not added if already present.
-;;FUNCTION is added (if necessary) at the beginning of the hook list
-;;unless the optional argument APPEND is non-nil, in which case
-;;FUNCTION is added at the end.
-;;
-;;HOOK should be a symbol, and FUNCTION may be any valid function. If
-;;HOOK is void, it is first set to nil. If HOOK's value is a single
-;;function, it is changed to a list of functions."
-(defun vip-add-hook (hook function &optional append)
- (if (not (boundp hook)) (set hook nil))
- ;; If the hook value is a single function, turn it into a list.
- (let ((old (symbol-value hook)))
- (if (or (not (listp old)) (eq (car old) 'lambda))
- (setq old (list old)))
- (if (member function old)
- nil
- (set hook (if append
- (append old (list function)) ; don't nconc
- (cons function old))))))
-
-;; This is here because of Emacs's changes in the semantics of add/remove-hooks
-;; and due to the bugs they introduced.
-;;
-;; Remove from the value of HOOK the function FUNCTION.
-;; HOOK should be a symbol, and FUNCTION may be any valid function. If
-;; FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the
-;; list of hooks to run in HOOK, then nothing is done. See `vip-add-hook'."
-(defun vip-remove-hook (hook function)
- (if (or (not (boundp hook)) ;unbound symbol, or
- (null (symbol-value hook)) ;value is nil, or
- (null function)) ;function is nil, then
- nil ;Do nothing.
- (let ((hook-value (symbol-value hook)))
- (if (consp hook-value)
- ;; don't side-effect the list
- (setq hook-value (delete function (copy-sequence hook-value)))
- (if (equal hook-value function)
- (setq hook-value nil)))
- (set hook hook-value))))
-
-
-
-;; like read-event, but in XEmacs also try to convert to char, if possible
-(defun vip-read-event-convert-to-char ()
- (let (event)
- (if vip-emacs-p
- (read-event)
- (setq event (next-command-event))
- (or (event-to-character event)
- event))
- ))
-
-;; This function lets function-key-map convert key sequences into logical
-;; keys. This does a better job than vip-read-event when it comes to kbd
-;; macros, since it enables certain macros to be shared between X and TTY modes
-;; by correctly mapping key sequences for Left/Right/... (one an ascii
-;; terminal) into logical keys left, right, etc.
-(defun vip-read-key ()
- (let ((overriding-local-map vip-overriding-map)
- (inhibit-quit t)
- key)
- (use-global-map vip-overriding-map)
- (setq key (elt (read-key-sequence nil) 0))
- (use-global-map global-map)
- key))
-
-
-;; Emacs has a bug in eventp, which causes (eventp nil) to return (nil)
-;; instead of nil, if '(nil) was previously inadvertently assigned to
-;; unread-command-events
-(defun vip-event-key (event)
- (or (and event (eventp event))
- (error "vip-event-key: Wrong type argument, eventp, %S" event))
- (let ((mod (event-modifiers event))
- basis)
- (setq basis
- (cond
- (vip-xemacs-p
- (cond ((key-press-event-p event)
- (event-key event))
- ((button-event-p event)
- (concat "mouse-" (prin1-to-string (event-button event))))
- (t
- (error "vip-event-key: Unknown event, %S" event))))
- (t
- ;; Emacs doesn't handle capital letters correctly, since
- ;; \S-a isn't considered the same as A (it behaves as
- ;; plain `a' instead). So we take care of this here
- (cond ((and (vip-characterp event) (<= ?A event) (<= event ?Z))
- (setq mod nil
- event event))
- ;; Emacs has the oddity whereby characters 128+char
- ;; represent M-char *if* this appears inside a string.
- ;; So, we convert them manually to (meta char).
- ((and (vip-characterp event) (< ?\C-? event) (<= event 255))
- (setq mod '(meta)
- event (- event ?\C-? 1)))
- (t (event-basic-type event)))
- )))
- (if (vip-characterp basis)
- (setq basis
- (if (= basis ?\C-?)
- (list 'control '\?) ; taking care of an emacs bug
- (intern (char-to-string basis)))))
- (if mod
- (append mod (list basis))
- basis)))
-
-(defun vip-key-to-emacs-key (key)
- (let (key-name char-p modifiers mod-char-list base-key base-key-name)
- (cond (vip-xemacs-p key)
- ((symbolp key)
- (setq key-name (symbol-name key))
- (if (= (length key-name) 1) ; character event
- (string-to-char key-name)
- key))
- ((listp key)
- (setq modifiers (subseq key 0 (1- (length key)))
- base-key (vip-seq-last-elt key)
- base-key-name (symbol-name base-key)
- char-p (= (length base-key-name) 1))
- (setq mod-char-list
- (mapcar
- '(lambda (elt) (upcase (substring (symbol-name elt) 0 1)))
- modifiers))
- (if char-p
- (setq key-name
- (car (read-from-string
- (concat
- "?\\"
- (mapconcat 'identity mod-char-list "-\\")
- "-"
- base-key-name))))
- (setq key-name
- (intern
- (concat
- (mapconcat 'identity mod-char-list "-")
- "-"
- base-key-name))))))
- ))
-
-
-;; Args can be a sequence of events, a string, or a Viper macro. Will try to
-;; convert events to keys and, if all keys are regular printable
-;; characters, will return a string. Otherwise, will return a string
-;; representing a vector of converted events. If the input was a Viper macro,
-;; will return a string that represents this macro as a vector.
-(defun vip-array-to-string (event-seq)
- (let (temp temp2)
- (cond ((stringp event-seq) event-seq)
- ((vip-event-vector-p event-seq)
- (setq temp (mapcar 'vip-event-key event-seq))
- (cond ((vip-char-symbol-sequence-p temp)
- (mapconcat 'symbol-name temp ""))
- ((and (vip-char-array-p
- (setq temp2 (mapcar 'vip-key-to-character temp))))
- (mapconcat 'char-to-string temp2 ""))
- (t (prin1-to-string (vconcat temp)))))
- ((vip-char-symbol-sequence-p event-seq)
- (mapconcat 'symbol-name event-seq ""))
- ((and (vectorp event-seq)
- (vip-char-array-p
- (setq temp (mapcar 'vip-key-to-character event-seq))))
- (mapconcat 'char-to-string temp ""))
- (t (prin1-to-string event-seq)))))
-
-(defun vip-key-press-events-to-chars (events)
- (mapconcat (if vip-emacs-p
- 'char-to-string
- (function
- (lambda (elt) (char-to-string (event-to-character elt)))))
- events
- ""))
-
-
-(defsubst vip-fast-keysequence-p ()
- (not (vip-sit-for-short vip-fast-keyseq-timeout t)))
-
-(defun vip-read-char-exclusive ()
- (let (char
- (echo-keystrokes 1))
- (while (null char)
- (condition-case nil
- (setq char (read-char))
- (error
- ;; skip event if not char
- (vip-read-event))))
- char))
-
-;; key is supposed to be in viper's representation, e.g., (control l), a
-;; character, etc.
-(defun vip-key-to-character (key)
- (cond ((eq key 'space) ?\ )
- ((eq key 'delete) ?\C-?)
- ((eq key 'backspace) ?\C-h)
- ((and (symbolp key)
- (= 1 (length (symbol-name key))))
- (string-to-char (symbol-name key)))
- ((and (listp key)
- (eq (car key) 'control)
- (symbol-name (nth 1 key))
- (= 1 (length (symbol-name (nth 1 key)))))
- (read (format "?\\C-%s" (symbol-name (nth 1 key)))))
- (t key)))
-
-
-(defun vip-setup-master-buffer (&rest other-files-or-buffers)
- "Set up the current buffer as a master buffer.
-Arguments become related buffers. This function should normally be used in
-the `Local variables' section of a file."
- (setq vip-related-files-and-buffers-ring
- (make-ring (1+ (length other-files-or-buffers))))
- (mapcar '(lambda (elt)
- (vip-ring-insert vip-related-files-and-buffers-ring elt))
- other-files-or-buffers)
- (vip-ring-insert vip-related-files-and-buffers-ring (buffer-name))
- )
-
-;;; Movement utilities
-
-(defvar vip-syntax-preference 'strict-vi
- "*Syntax type characterizing Viper's alphanumeric symbols.
-`emacs' means only word constituents are considered to be alphanumeric.
-Word constituents are symbols specified as word constituents by the current
-syntax table.
-`extended' means word and symbol constituents.
-`reformed-vi' means Vi-ish behavior: word constituents and the symbol `_'.
-However, word constituents are determined according to Emacs syntax tables,
-which may be different from Vi in some major modes.
-`strict-vi' means Viper words are exactly as in Vi.")
-
-(vip-deflocalvar vip-ALPHA-char-class "w"
- "String of syntax classes characterizing Viper's alphanumeric symbols.
-In addition, the symbol `_' may be considered alphanumeric if
-`vip-syntax-preference'is `reformed-vi'.")
-
-(vip-deflocalvar vip-strict-ALPHA-chars "a-zA-Z0-9_"
- "Regexp matching the set of alphanumeric characters acceptable to strict
-Vi.")
-(vip-deflocalvar vip-strict-SEP-chars " \t\n"
- "Regexp matching the set of alphanumeric characters acceptable to strict
-Vi.")
-
-(vip-deflocalvar vip-SEP-char-class " -"
- "String of syntax classes for Vi separators.
-Usually contains ` ', linefeed, TAB or formfeed.")
-
-(defun vip-update-alphanumeric-class ()
- "Set the syntax class of Viper alphanumerals according to `vip-syntax-preference'.
-Must be called in order for changes to `vip-syntax-preference' to take effect."
- (interactive)
- (setq-default
- vip-ALPHA-char-class
- (cond ((eq vip-syntax-preference 'emacs) "w") ; only word constituents
- ((eq vip-syntax-preference 'extended) "w_") ; word & symbol chars
- (t "w")))) ; vi syntax: word constituents and the symbol `_'
-
-;; addl-chars are characters to be temporarily considered as alphanumerical
-(defun vip-looking-at-alpha (&optional addl-chars)
- (or (stringp addl-chars) (setq addl-chars ""))
- (if (eq vip-syntax-preference 'reformed-vi)
- (setq addl-chars (concat addl-chars "_")))
- (let ((char (char-after (point))))
- (if char
- (if (eq vip-syntax-preference 'strict-vi)
- (looking-at (concat "[" vip-strict-ALPHA-chars addl-chars "]"))
- (or (memq char
- ;; convert string to list
- (append (vconcat addl-chars) nil))
- (memq (char-syntax char)
- (append (vconcat vip-ALPHA-char-class) nil)))))
- ))
-
-(defsubst vip-looking-at-separator ()
- (let ((char (char-after (point))))
- (if char
- (or (eq char ?\n) ; RET is always a separator in Vi
- (memq (char-syntax char)
- (append (vconcat vip-SEP-char-class) nil))))))
-
-(defsubst vip-looking-at-alphasep (&optional addl-chars)
- (or (vip-looking-at-separator) (vip-looking-at-alpha addl-chars)))
-
-(defsubst vip-skip-alpha-forward (&optional addl-chars)
- (or (stringp addl-chars) (setq addl-chars ""))
- (vip-skip-syntax
- 'forward
- (cond ((eq vip-syntax-preference 'strict-vi)
- "")
- (t vip-ALPHA-char-class ))
- (cond ((eq vip-syntax-preference 'strict-vi)
- (concat vip-strict-ALPHA-chars addl-chars))
- (t addl-chars))))
-
-(defsubst vip-skip-alpha-backward (&optional addl-chars)
- (or (stringp addl-chars) (setq addl-chars ""))
- (vip-skip-syntax
- 'backward
- (cond ((eq vip-syntax-preference 'strict-vi)
- "")
- (t vip-ALPHA-char-class ))
- (cond ((eq vip-syntax-preference 'strict-vi)
- (concat vip-strict-ALPHA-chars addl-chars))
- (t addl-chars))))
-
-;; weird syntax tables may confuse strict-vi style
-(defsubst vip-skip-all-separators-forward (&optional within-line)
- (vip-skip-syntax 'forward
- vip-SEP-char-class
- (or within-line "\n")
- (if within-line (vip-line-pos 'end))))
-(defsubst vip-skip-all-separators-backward (&optional within-line)
- (vip-skip-syntax 'backward
- vip-SEP-char-class
- (or within-line "\n")
- (if within-line (vip-line-pos 'start))))
-(defun vip-skip-nonseparators (direction)
- (let ((func (intern (format "skip-syntax-%S" direction))))
- (funcall func (concat "^" vip-SEP-char-class)
- (vip-line-pos (if (eq direction 'forward) 'end 'start)))))
-
-(defsubst vip-skip-nonalphasep-forward ()
- (if (eq vip-syntax-preference 'strict-vi)
- (skip-chars-forward
- (concat "^" vip-strict-SEP-chars vip-strict-ALPHA-chars))
- (skip-syntax-forward
- (concat
- "^" vip-ALPHA-char-class vip-SEP-char-class) (vip-line-pos 'end))))
-(defsubst vip-skip-nonalphasep-backward ()
- (if (eq vip-syntax-preference 'strict-vi)
- (skip-chars-backward
- (concat "^" vip-strict-SEP-chars vip-strict-ALPHA-chars))
- (skip-syntax-backward
- (concat
- "^" vip-ALPHA-char-class vip-SEP-char-class) (vip-line-pos 'start))))
-
-;; Skip SYNTAX like skip-syntax-* and ADDL-CHARS like skip-chars-*
-;; Return the number of chars traveled.
-;; Either SYNTAX or ADDL-CHARS can be nil, in which case they are interpreted
-;; as an empty string.
-(defun vip-skip-syntax (direction syntax addl-chars &optional limit)
- (let ((total 0)
- (local 1)
- (skip-chars-func (intern (format "skip-chars-%S" direction)))
- (skip-syntax-func (intern (format "skip-syntax-%S" direction))))
- (or (stringp addl-chars) (setq addl-chars ""))
- (or (stringp syntax) (setq syntax ""))
- (while (and (not (= local 0)) (not (eobp)))
- (setq local
- (+ (funcall skip-syntax-func syntax limit)
- (funcall skip-chars-func addl-chars limit)))
- (setq total (+ total local)))
- total
- ))
-
-
-
-
-(provide 'viper-util)
-
-;;; viper-util.el ends here
diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el
deleted file mode 100644
index 592f15021ac..00000000000
--- a/lisp/emulation/viper.el
+++ /dev/null
@@ -1,5892 +0,0 @@
-;;; viper.el --- A full-featured Vi emulator for GNU Emacs 19 and XEmacs 19,
-;; a VI Plan for Emacs Rescue,
-;; and a venomous VI PERil.
-;; Viper Is also a Package for Emacs Rebels.
-;;
-;; Keywords: emulations
-;; Author: Michael Kifer <kifer@cs.sunysb.edu>
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-(defconst viper-version "2.91 of August 5, 1996"
- "The current version of Viper")
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Viper is a full-featured Vi emulator for Emacs 19. It emulates and
-;; improves upon the standard features of Vi and, at the same time, allows
-;; full access to all Emacs facilities. Viper supports multiple undo,
-;; file name completion, command, file, and search history and it extends
-;; Vi in many other ways. Viper is highly customizable through the various
-;; hooks, user variables, and keymaps. It is implemented as a collection
-;; of minor modes and it is designed to provide full access to all Emacs
-;; major and minor modes.
-;;
-;;; History
-;;
-;; Viper is a new name for a package formerly known as VIP-19,
-;; which was a successor of VIP version 3.5 by Masahiko Sato
-;; <ms@sail.stanford.edu> and VIP version 4.2 by Aamod Sane
-;; <sane@cs.uiuc.edu>. Some ideas from vip 4.4.2 by Aamod Sane
-;; were also shamelessly plagiarized.
-;;
-;; Viper maintains some degree of compatibility with these older
-;; packages. See the documentation for customization.
-;;
-;; The main difference between Viper and these older packages are:
-;;
-;; 1. Viper emulates Vi at several levels, from almost complete conformity
-;; to a rather loose Vi-compliance.
-;;
-;; 2. Viper provides full access to all major and minor modes of Emacs
-;; without the need to type extra keys.
-;; The older versions of VIP (and other Vi emulators) do not work with
-;; some major and minor modes.
-;;
-;; 3. Viper supports vi-style undo.
-;;
-;; 4. Viper fully emulates (and improves upon) vi's replacement mode.
-;;
-;; 5. Viper has a better interface to ex, including command, variable, and
-;; file name completion.
-;;
-;; 6. Viper uses native Emacs history and completion features; it doesn't
-;; rely on other packages (such as gmhist.el and completer.el) to provide
-;; these features.
-;;
-;; 7. Viper supports Vi-style editing in the minibuffer, by allowing the
-;; user to switch from Insert state to Vi state to Replace state, etc.
-;;
-;; 8. Viper keeps history of recently inserted pieces of text and recently
-;; executed Vi-style destructive commands, such as `i', `d', etc.
-;; These pieces of text can be inserted in later insertion commands;
-;; the previous destructive commands can be re-executed.
-;;
-;; 9. Viper has Vi-style keyboard macros, which enhances the similar
-;; facility in the original Vi.
-;; First, one can execute any Emacs command while defining a
-;; macro, not just the Vi commands. Second, macros are defined in a
-;; WYSYWYG mode, using an interface to Emacs' WYSIWYG style of defining
-;; macros. Third, in Viper, one can define macros that are specific to
-;; a given buffer, a given major mode, or macros defined for all buffers.
-;; The same macro name can have several different definitions:
-;; one global, several definitions for various major modes, and
-;; definitions for specific buffers.
-;; Buffer-specific definitions override mode-specific
-;; definitions, which, in turn, override global definitions.
-;;
-;;
-;;; Installation:
-;; -------------
-;;
-;; (require 'viper)
-;;
-
-;;; Acknowledgements:
-;; -----------------
-;; Bug reports and ideas contributed by many users have helped
-;; improve Viper and the various versions of VIP.
-;; See the on-line manual for a complete list of contributors.
-;;
-;;
-;;; Notes:
-;;
-;; 1. Major modes.
-;; In most cases, Viper handles major modes correctly, i.e., they come up
-;; in the right state (either vi-state or emacs-state). For instance, text
-;; files come up in vi-state, while, say, Dired appears in emacs-state by
-;; default.
-;; However, some modes do not appear in the right mode in the beginning,
-;; usually because they neglect to follow Emacs conventions (e.g., they don't
-;; use kill-all-local-variables when they start). Some major modes
-;; may fail to come up in emacs-state if they call hooks, such as
-;; text-hook, for no good reason.
-;;
-;; As an immediate solution, you can hit C-z to bring about the right mode.
-;; An interim solution is to add an appropriate hook to the mode like this:
-;;
-;; (add-hook 'your-favorite-mode 'viper-mode)
-;; or
-;; (add-hook 'your-favorite-mode 'vip-change-state-to-emacs)
-;;
-;; whichever applies. The right thing to do, however, is to complain to the
-;; author of the respective package. (Sometimes they also neglect to equip
-;; their modes with hooks, which is one more reason for complaining.)
-;;
-;; 2. Keymap handling
-;; Because Emacs 19 has an elegant mechanism for turning minor mode keymaps
-;; on and off, implementation of Viper has been greatly simplified. Viper
-;; has several minor modes.
-;;
-;; Viper's Vi state consists of seven minor modes:
-;;
-;; vip-vi-intercept-minor-mode
-;; vip-vi-local-user-minor-mode
-;; vip-vi-global-user-minor-mode
-;; vip-vi-kbd-minor-mode
-;; vip-vi-state-modifier-minor-mode
-;; vip-vi-diehard-minor-mode
-;; vip-vi-basic-minor-mode
-;;
-;; Bindings done to the keymap of the first mode overshadow those done to
-;; the second, which, in turn, overshadows those done to the third, etc.
-;;
-;; The last vip-vi-basic-minor-mode contains most of the usual Vi bindings
-;; in its edit mode. This mode provides access to all Emacs facilities.
-;; Novice users, however, may want to set their vip-expert-level to 1
-;; in their .vip file. This will enable vip-vi-diehard-minor-mode. This
-;; minor mode's bindings make Viper simulate the usual Vi very closely.
-;; For instance, C-c will not have its standard Emacs binding
-;; and so many of the goodies of Emacs are not available.
-;;
-;; A skilled user should set vip-expert-level to at least 3. This will
-;; enable `C-c' and many Emacs facilities will become available.
-;; In this case, vip-vi-diehard-minor-mode is inactive.
-;;
-;; Viper gurus should have at least
-;; (setq vip-expert-level 4)
-;; in their ~/.vip files. This will unsuppress all Emacs keys that are not
-;; essential for VI-style editing.
-;; Pick-and-choose users may want to put
-;; (setq vip-expert-level 5)
-;; in ~/.vip. Viper will then leave it up to the user to set the variables
-;; vip-want-* See vip-set-expert-level for details.
-;;
-;; The very first minor mode, vip-vi-intercept-minor-mode, is of no
-;; concern for the user. It is needed to bind Viper's vital keys, such as
-;; ESC and C-z.
-;;
-;; The second mode, vip-vi-local-user-minor-mode, usually has an
-;; empty keymap. However, the user can set bindings in this keymap, which
-;; will overshadow the corresponding bindings in the other two minor
-;; modes. This is useful, for example, for setting up ZZ in gnus,
-;; rmail, mh-e, etc., to send message instead of saving it in a file.
-;; Likewise, in Dired mode, you may want to bind ZN and ZP to commands
-;; that would visit the next or the previous file in the Dired buffer.
-;; Setting local keys is tricky, so don't do it directly. Instead, use
-;; vip-add-local-keys function (see its doc).
-;;
-;; The third minor mode, vip-vi-global-user-minor-mode, is also intended
-;; for the users but, unlike vip-vi-local-user-minor-mode, its key
-;; bindings are seen in all Viper buffers. This mode keys can be done
-;; with define-key command.
-;;
-;; The fourth minor mode, vip-vi-kbd-minor-mode, is used by keyboard
-;; macros. Users are NOT supposed to modify this keymap directly.
-;;
-;; The fifth mode, vip-vi-state-modifier-minor-mode, can be used to set
-;; key bindings that are visible in some major modes but not in others.
-;;
-;; Users are allowed to modify keymaps that belong to
-;; vip-vi-local-user-minor-mode, vip-vi-global-user-minor-mode,
-;; and vip-vi-state-modifier-minor-mode only.
-;;
-;; Viper's Insert state also has seven minor modes:
-;;
-;; vip-insert-intercept-minor-mode
-;; vip-insert-local-user-minor-mode
-;; vip-insert-global-user-minor-mode
-;; vip-insert-kbd-minor-mode
-;; vip-insert-state-modifier-minor-mode
-;; vip-insert-diehard-minor-mode
-;; vip-insert-basic-minor-mode
-;;
-;; As with VI's editing modes, the first mode, vip-insert-intercept-minor-mode
-;; is used to bind vital keys that are not to be changed by the user.
-;;
-;; The next mode, vip-insert-local-user-minor-mode, is used to customize
-;; bindings in the insert state of Viper. The third mode,
-;; vip-insert-global-user-minor-mode is like
-;; vip-insert-local-user-minor-mode, except that its bindings are seen in
-;; all Viper buffers. As with vip-vi-local-user-minor-mode, its bindings
-;; should be done via the function vip-add-local-keys. Bindings for
-;; vip-insert-global-user-minor-mode can be set with the define-key command.
-;;
-;; The next minor mode, vip-insert-kbd-minor-mode,
-;; is used for keyboard VI-style macros defined with :map!.
-;;
-;; The fifth minor mode, vip-insert-state-modifier-minor-mode, is like
-;; vip-vi-state-modifier-minor-mode, except that it is used in the Insert
-;; state; it can be used to modify keys in a mode-specific fashion.
-;;
-;; The minor mode vip-insert-diehard-minor-mode is in effect when
-;; the user wants a high degree of Vi compatibility (a bad idea, really!).
-;; The last minor mode, vip-insert-basic-minor-mode, is always in effect
-;; when Viper is in insert state. It binds a small number of keys needed for
-;; Viper's operation.
-;;
-;; Finally, Viper provides minor modes for overriding bindings set by Emacs
-;; modes when Viper is in Emacs state:
-;;
-;; vip-emacs-local-user-minor-mode
-;; vip-emacs-global-user-minor-mode
-;; vip-emacs-kbd-minor-mode
-;; vip-emacs-state-modifier-minor-mode
-;;
-;; These minor modes are in effect when Viper is in Emacs state. The keymap
-;; associated with vip-emacs-global-user-minor-mode,
-;; vip-emacs-global-user-map, overrides the global and local keymaps as
-;; well as the minor mode keymaps set by other modes. The keymap of
-;; vip-emacs-local-user-minor-mode, vip-emacs-local-user-map, overrides
-;; everything, but it is used on a per buffer basis.
-;; The keymap associated with vip-emacs-state-modifier-minor-mode
-;; overrides keys on a per-major-mode basis. The mode
-;; vip-emacs-kbd-minor-mode is used to define Vi-style macros in Emacs
-;; state.
-;;
-;; 3. There is also one minor mode that is used when Viper is in its
-;; replace-state (used for commands like cw, C, etc.). This mode is
-;; called
-;;
-;; vip-replace-minor-mode
-;;
-;; and its keymap is vip-replace-map. Replace minor mode is always
-;; used in conjunction with the minor modes for insert-state, and its
-;; keymap overshadows the keymaps for insert minor modes.
-;;
-;; 4. Defining buffer-local bindings in Vi and Insert modes.
-;; As mentioned before, sometimes, it is convenient to have
-;; buffer-specific of mode-specific key bindings in Vi and insert modes.
-;; Viper provides a special function, vip-add-local-keys, to do precisely
-;; this. For instance, is you need to add couple of mode-specific bindings
-;; to Insert mode, you can put
-;;
-;; (vip-add-local-keys 'insert-state '((key1 . func1) (key2 .func2)))
-;;
-;; somewhere in a hook of this major mode. If you put something like this
-;; in your own elisp function, this will define bindings specific to the
-;; buffer that was current at the time of the call to vip-add-local-keys.
-;; The only thing to make sure here is that the major mode of this buffer
-;; is written according to Emacs conventions, which includes a call to
-;; (kill-all-local-variables). See vip-add-local-keys for more details.
-;;
-;;
-;; TO DO (volunteers?):
-;;
-;; 1. Some of the code that is inherited from VIP-3.5 is rather
-;; convoluted. Instead of vip-command-argument, keymaps should bind the
-;; actual commands. E.g., "dw" should be bound to a generic command
-;; vip-delete that will delete things based on the value of
-;; last-command-char. This would greatly simplify the logic and the code.
-;;
-;; 2. Somebody should venture to write a customization package a la
-;; options.el that would allow the user to change values of variables
-;; that meet certain specs (e.g., match a regexp) and whose doc string
-;; starts with a '*'. Then, the user should be offered to save
-;; variables that were changed. This will make user's customization job
-;; much easier.
-;;
-
-;; Code
-
-(require 'advice)
-(require 'cl)
-(require 'ring)
-
-(require 'viper-util)
-
-;; Compiler pacifier
-(defvar vip-minibuffer-current-face)
-(defvar vip-minibuffer-insert-face)
-(defvar vip-minibuffer-vi-face)
-(defvar vip-minibuffer-emacs-face)
-(defvar iso-accents-mode)
-(defvar zmacs-region-stays)
-;; end pacifier
-
-
-;;; Variables
-
-;; Is t until viper-mode executes for the very first time.
-;; Prevents recursive descend into startup messages.
-(defvar vip-first-time t)
-
-(defvar vip-expert-level 0
- "User's expert level.
-The minor mode vip-vi-diehard-minor-mode is in effect when
-vip-expert-level is 1 or 2 or when vip-want-emacs-keys-in-vi is t.
-The minor mode vip-insert-diehard-minor-mode is in effect when
-vip-expert-level is 1 or 2 or if vip-want-emacs-keys-in-insert is t.
-Use `M-x vip-set-expert-level' to change this.")
-
-;; Max expert level supported by Viper. This is NOT a user option.
-;; It is here to make it hard for the user from resetting it.
-(defconst vip-max-expert-level 5)
-
-;; Contains user settings for vars affected by vip-set-expert-level function.
-;; Not a user option.
-(defvar vip-saved-user-settings nil)
-
-
-;;; Viper minor modes
-
-;; This is not local in Emacs, so we make it local.
-;; This must be local because although the stack of minor modes can be the same
-;; for all buffers, the associated *keymaps* can be different. In Viper,
-;; vip-vi-local-user-map, vip-insert-local-user-map, and others can have
-;; different keymaps for different buffers.
-;; Also, the keymaps associated with vip-vi/insert-state-modifier-minor-mode
-;; can be different.
-(make-variable-buffer-local 'minor-mode-map-alist)
-
-;; Mode for vital things like \e, C-z.
-(vip-deflocalvar vip-vi-intercept-minor-mode nil)
-
-(vip-deflocalvar vip-vi-basic-minor-mode nil
- "Viper's minor mode for Vi bindings.")
-
-(vip-deflocalvar vip-vi-local-user-minor-mode nil
- "Auxiliary minor mode for user-defined local bindings in Vi state.")
-
-(vip-deflocalvar vip-vi-global-user-minor-mode nil
- "Auxiliary minor mode for user-defined global bindings in Vi state.")
-
-(vip-deflocalvar vip-vi-state-modifier-minor-mode nil
- "Minor mode used to make major-mode-specific modification to Vi state.")
-
-(vip-deflocalvar vip-vi-diehard-minor-mode nil
- "This minor mode is in effect when the user wants Viper to be Vi.")
-
-(vip-deflocalvar vip-vi-kbd-minor-mode nil
- "Minor mode for Ex command macros in Vi state.
-The corresponding keymap stores key bindings of Vi macros defined with
-the Ex command :map.")
-
-;; Mode for vital things like \e, C-z.
-(vip-deflocalvar vip-insert-intercept-minor-mode nil)
-
-(vip-deflocalvar vip-insert-basic-minor-mode nil
- "Viper's minor mode for bindings in Insert mode.")
-
-(vip-deflocalvar vip-insert-local-user-minor-mode nil
- "Auxiliary minor mode for buffer-local user-defined bindings in Insert state.
-This is a way to overshadow normal Insert mode bindings locally to certain
-designated buffers.")
-
-(vip-deflocalvar vip-insert-global-user-minor-mode nil
- "Auxiliary minor mode for global user-defined bindings in Insert state.")
-
-(vip-deflocalvar vip-insert-state-modifier-minor-mode nil
- "Minor mode used to make major-mode-specific modification to Insert state.")
-
-(vip-deflocalvar vip-insert-diehard-minor-mode nil
- "Minor mode that simulates Vi very closely.
-Not recommened, except for the novice user.")
-
-(vip-deflocalvar vip-insert-kbd-minor-mode nil
-"Minor mode for Ex command macros Insert state.
-The corresponding keymap stores key bindings of Vi macros defined with
-the Ex command :map!.")
-
-(vip-deflocalvar vip-replace-minor-mode nil
- "Minor mode in effect in replace state (cw, C, and the like commands).")
-
-;; Mode for vital things like \C-z and \C-x)
-;; This is t, by default. So, any new buffer will have C-z defined as
-;; switch to Vi, unless we switched states in this buffer
-(vip-deflocalvar vip-emacs-intercept-minor-mode t)
-
-(vip-deflocalvar vip-emacs-local-user-minor-mode t
- "Minor mode for local user bindings effective in Emacs state.
-Users can use it to override Emacs bindings when Viper is in its Emacs
-state.")
-
-(vip-deflocalvar vip-emacs-global-user-minor-mode t
- "Minor mode for global user bindings in effect in Emacs state.
-Users can use it to override Emacs bindings when Viper is in its Emacs
-state.")
-
-(vip-deflocalvar vip-emacs-kbd-minor-mode t
- "Minor mode for Vi style macros in Emacs state.
-The corresponding keymap stores key bindings of Vi macros defined with
-`vip-record-kbd-macro' command. There is no Ex-level command to do this
-interactively.")
-
-(vip-deflocalvar vip-emacs-state-modifier-minor-mode t
- "Minor mode used to make major-mode-specific modification to Emacs state.
-For instance, a Vi purist may want to bind `dd' in Dired mode to a function
-that deletes a file.")
-
-
-
-;;; ISO characters
-
-(vip-deflocalvar vip-automatic-iso-accents nil
- "*If non-nil, ISO accents will be turned on in insert/replace emacs states and turned off in vi-state.
-For some users, this behavior may be too primitive. In this case, use
-insert/emacs/vi state hooks.")
-
-
-;;; Emacs keys in other states.
-
-(defvar vip-want-emacs-keys-in-insert t
- "*Set to nil if you want complete Vi compatibility in insert mode.
-Complete compatibility with Vi is not recommended for power use of Viper.")
-
-(defvar vip-want-emacs-keys-in-vi t
- "*Set to nil if you want complete Vi compatibility in Vi mode.
-Full Vi compatibility is not recommended for power use of Viper.")
-
-
-
-;; VI-style Undo
-
-;; Used to 'undo' complex commands, such as replace and insert commands.
-(vip-deflocalvar vip-undo-needs-adjustment nil)
-(put 'vip-undo-needs-adjustment 'permanent-local t)
-
-;; A mark that Viper puts on buffer-undo-list. Marks the beginning of a
-;; complex command that must be undone atomically. If inserted, it is
-;; erased by vip-change-state-to-vi and vip-repeat.
-(defconst vip-buffer-undo-list-mark 'viper)
-
-(defvar vip-keep-point-on-undo nil
- "*Non-nil means not to move point while undoing commands.
-This style is different from Emacs and Vi. Try it to see if
-it better fits your working style.")
-
-;; Replace mode and changing text
-
-;; Viper's own after/before change functions, which get vip-add-hook'ed to
-;; Emacs's
-(vip-deflocalvar vip-after-change-functions nil "")
-(vip-deflocalvar vip-before-change-functions nil "")
-(vip-deflocalvar vip-post-command-hooks nil "")
-(vip-deflocalvar vip-pre-command-hooks nil "")
-
-;; Can be used to pass global states around for short period of time
-(vip-deflocalvar vip-intermediate-command nil "")
-
-;; Indicates that the current destructive command has started in replace mode.
-(vip-deflocalvar vip-began-as-replace nil "")
-
-(defvar vip-replace-overlay-cursor-color "Red"
- "*Cursor color to use in Replace state")
-(defvar vip-insert-state-cursor-color nil
- "Cursor color for Viper insert state.")
-(put 'vip-insert-state-cursor-color 'permanent-local t)
-;; place to save cursor colow when switching to insert mode
-(vip-deflocalvar vip-saved-cursor-color nil "")
-
-(vip-deflocalvar vip-replace-overlay nil "")
-(put 'vip-replace-overlay 'permanent-local t)
-
-(defvar vip-replace-overlay-pixmap "gray3"
- "Pixmap to use for search face on non-color displays.")
-(defvar vip-search-face-pixmap "gray3"
- "Pixmap to use for search face on non-color displays.")
-
-
-(defun vip-set-replace-overlay-face ()
- (if (vip-has-face-support-p)
- (defvar vip-replace-overlay-face
- (progn
- (make-face 'vip-replace-overlay-face)
- (vip-hide-face 'vip-replace-overlay-face)
- (or (face-differs-from-default-p 'vip-replace-overlay-face)
- (progn
- (if (vip-can-use-colors "darkseagreen2" "Black")
- (progn
- (set-face-background
- 'vip-replace-overlay-face "darkseagreen2")
- (set-face-foreground 'vip-replace-overlay-face "Black")))
- (set-face-underline-p 'vip-replace-overlay-face t)
- (vip-set-face-pixmap
- 'vip-replace-overlay-face vip-replace-overlay-pixmap)))
- 'vip-replace-overlay-face)
- "*Face for highlighting replace regions on a window display.")
- ))
-
-(defvar vip-replace-region-end-delimiter "$"
- "A string marking the end of replacement regions.
-It is used only with TTYs or if `vip-use-replace-region-delimiters'
-is non-nil.")
-(defvar vip-replace-region-start-delimiter ""
- "A string marking the beginning of replacement regions.
-It is used only with TTYs or if `vip-use-replace-region-delimiters'
-is non-nil.")
-(defvar vip-use-replace-region-delimiters (not (vip-has-face-support-p))
- "*If non-nil, Viper will always use `vip-replace-region-end-delimiter' and
-`vip-replace-region-start-delimiter' to delimit replacement regions, even on
-color displays. By default, the delimiters are used only on TTYs.")
-
-;; XEmacs requires glyphs
-(if vip-xemacs-p
- (progn
- (or (glyphp vip-replace-region-end-delimiter)
- (setq vip-replace-region-end-delimiter
- (make-glyph vip-replace-region-end-delimiter)))
- (or (glyphp vip-replace-region-start-delimiter)
- (setq vip-replace-region-start-delimiter
- (make-glyph vip-replace-region-start-delimiter)))
- ))
-
-
-;; These are local marker that must be initialized to nil and moved with
-;; `vip-move-marker-locally'
-;;
-;; Remember the last position inside the replace region.
-(vip-deflocalvar vip-last-posn-in-replace-region nil)
-;; Remember the last position while inserting
-(vip-deflocalvar vip-last-posn-while-in-insert-state nil)
-(put 'vip-last-posn-in-replace-region 'permanent-local t)
-(put 'vip-last-posn-while-in-insert-state 'permanent-local t)
-
-(vip-deflocalvar vip-sitting-in-replace nil "")
-(put 'vip-sitting-in-replace 'permanent-local t)
-
-;; Remember the number of characters that have to be deleted in replace
-;; mode to compensate for the inserted characters.
-(vip-deflocalvar vip-replace-chars-to-delete 0 "")
-(vip-deflocalvar vip-replace-chars-deleted 0 "")
-
-;; Insertion ring and command ring
-(defvar vip-insertion-ring-size 14
- "The size of the insertion ring.")
-;; The insertion ring.
-(defvar vip-insertion-ring nil)
-;; This is temp insertion ring. Used to do rotation for display purposes.
-;; When rotation just started, it is initialized to vip-insertion-ring.
-(defvar vip-temp-insertion-ring nil)
-(defvar vip-last-inserted-string-from-insertion-ring "")
-
-(defvar vip-command-ring-size 14
- "The size of the command ring.")
-;; The command ring.
-(defvar vip-command-ring nil)
-;; This is temp command ring. Used to do rotation for display purposes.
-;; When rotation just started, it is initialized to vip-command-ring.
-(defvar vip-temp-command-ring nil)
-
-;; Modes and related variables
-
-;; Current mode. One of: `emacs-state', `vi-state', `insert-state'
-(vip-deflocalvar vip-current-state 'emacs-state)
-
-(defvar vip-no-multiple-ESC t
- "*If true, multiple ESC in Vi mode will cause bell to ring.
-This is set to t on a windowing terminal and to 'twice on a dumb
-terminal (unless the user level is 1, 2, or 5). On a dumb terminal, this
-enables cursor keys and is generally more convenient, as terminals usually
-don't have a convenient Meta key.
-Setting vip-no-multiple-ESC to nil will allow as many multiple ESC,
-as is allowed by the major mode in effect.")
-
-
-(defvar vip-want-ctl-h-help nil
- "*If t then C-h is bound to help-command in insert mode, if nil then it is
-bound to delete-backward-char.")
-
-;; Autoindent in insert
-
-;; Variable that keeps track of whether C-t has been pressed.
-(vip-deflocalvar vip-cted nil "")
-
-;; Preserve the indent value, used by C-d in insert mode.
-(vip-deflocalvar vip-current-indent 0)
-
-;; Whether to preserve the indent, used by C-d in insert mode.
-(vip-deflocalvar vip-preserve-indent nil)
-
-(vip-deflocalvar vip-auto-indent nil
- "*Autoindent if t.")
-(vip-deflocalvar vip-electric-mode t
- "*If t, enable electric behavior.
-Currently only enables auto-indentation `according to mode'.")
-
-(defconst vip-shift-width 8
- "*The shiftwidth variable.")
-
-;; Variables for repeating destructive commands
-
-(defconst vip-keep-point-on-repeat t
- "*If t, don't move point when repeating previous command.
-This is useful for doing repeated changes with the '.' key.
-The user can change this to nil, if she likes when the cursor moves
-to a new place after repeating previous Vi command.")
-
-;; Remember insert point as a marker. This is a local marker that must be
-;; initialized to nil and moved with `vip-move-marker-locally'.
-(vip-deflocalvar vip-insert-point nil)
-(put 'vip-insert-point 'permanent-local t)
-
-;; This remembers the point before dabbrev-expand was called.
-;; If vip-insert-point turns out to be bigger than that, it is reset
-;; back to vip-pre-command-point.
-;; The reason this is needed is because dabbrev-expand (and possibly
-;; others) may jump to before the insertion point, delete something and
-;; then reinsert a bigger piece. For instance: bla^blo
-;; If dabbrev-expand is called after `blo' and ^ undicates vip-insert-point,
-;; then point jumps to the beginning of `blo'. If expansion is found, `blablo'
-;; is deleted, and we have |^, where | denotes point. Next, dabbrev-expand
-;; will insert the expansion, and we get: blablo^
-;; Whatever we insert next goes before the ^, i.e., before the
-;; vip-insert-point marker. So, Viper will think that nothing was
-;; inserted. Remembering the orig position of the marker circumvents the
-;; problem.
-;; We don't know of any command, except dabbrev-expand, that has the same
-;; problem. However, the same trick can be used if such a command is
-;; discovered later.
-;;
-(vip-deflocalvar vip-pre-command-point nil)
-(put 'vip-pre-command-point 'permanent-local t) ; this is probably an overkill
-
-;; This is used for saving inserted text.
-(defvar vip-last-insertion nil)
-
-;; Remembers the last replaced region.
-(defvar vip-last-replace-region "")
-
-;; Remember com point as a marker.
-;; This is a local marker. Should be moved with `vip-move-marker-locally'
-(vip-deflocalvar vip-com-point nil)
-
-;; If non-nil, the value is a list (M-COM VAL COM REG inserted-text cmd-keys)
-;; It is used to re-execute last destructive command.
-;; M-COM is a Lisp symbol representing the function to be executed.
-;; VAL is the prefix argument that was used with that command.
-;; COM is an internal descriptor, such as ?r, ?c, ?C, which contains
-;; additional information on how the function in M-COM is to be handled.
-;; REG is the register used by command
-;; INSERTED-TEXT is text inserted by that command (in case of o, c, C, i, r
-;; commands).
-;; COMMAND-KEYS are the keys that were typed to invoke the command.
-(defvar vip-d-com nil)
-
-;; The character remembered by the Vi `r' command.
-(defvar vip-d-char nil)
-
-;; Name of register to store deleted or yanked strings
-(defvar vip-use-register nil)
-
-
-
-;; Variables for Moves and Searches
-
-;; For use by `;' command.
-(defvar vip-f-char nil)
-
-;; For use by `.' command.
-(defvar vip-F-char nil)
-
-;; For use by `;' command.
-(defvar vip-f-forward nil)
-
-;; For use by `;' command.
-(defvar vip-f-offset nil)
-
-;; Last search string
-(defvar vip-s-string "")
-
-(defvar vip-quote-string "> "
- "String inserted at the beginning of quoted region.")
-
-;; If t, search is forward.
-(defvar vip-s-forward nil)
-
-(defconst vip-case-fold-search nil
- "*If not nil, search ignores cases.")
-
-(defconst vip-re-search t
- "*If not nil, search is reg-exp search, otherwise vanilla search.")
-
-(defvar vip-adjust-window-after-search t
- "*If not nil, pull the window up or down, depending on the direction of the
-search, if search ends up near the bottom or near the top of the window.")
-
-(defconst vip-re-query-replace t
- "*If t then do regexp replace, if nil then do string replace.")
-
-(defconst vip-re-replace t
- "*If t, do regexp replace. nil means do string replace.")
-
-(vip-deflocalvar vip-ex-style-motion t
- "*Ex-style: the commands l,h do not cross lines, etc.")
-
-(vip-deflocalvar vip-ex-style-editing-in-insert t
- "*The keys ^H, ^? don't jump lines in insert, ESC moves cursor back, etc.
-Note: this doesn't preclude ^H and ^? from deleting characters by moving
-past the insertion point. This is a feature, not a bug. ")
-
-(vip-deflocalvar vip-delete-backwards-in-replace nil
- "*If t, DEL key will delete characters while moving the cursor backwards.
-If nil, the cursor will move backwards without deleting anything.")
-
-(defconst vip-buffer-search-char nil
- "*Key bound for buffer-searching.")
-
-(defconst vip-search-wrap-around-t t
- "*If t, search wraps around.")
-
-(vip-deflocalvar vip-related-files-and-buffers-ring nil
- "*Ring of file and buffer names that are considered to be related to the
-current buffer.
-These buffers can be cycled through via :R and :P commands.")
-(put 'vip-related-files-and-buffers-ring 'permanent-local t)
-
-;; Used to find out if we are done with searching the current buffer.
-(vip-deflocalvar vip-local-search-start-marker nil)
-;; As above, but global
-(defvar vip-search-start-marker (make-marker))
-
-;; the search overlay
-(vip-deflocalvar vip-search-overlay nil)
-
-
-(defvar vip-heading-start
- (concat "^\\s-*(\\s-*defun\\s-\\|" ; lisp
- "^{\\s-*$\\|^[_a-zA-Z][^()]*[()].*{\\s-*$\\|" ; C/C++
- "^\\s-*class.*{\\|^\\s-*struct.*{\\|^\\s-*enum.*{\\|"
- "^\\\\[sb][a-z]*{.*}\\s-*$\\|" ; latex
- "^@node\\|@table\\|^@m?enu\\|^@itemize\\|^@if\\|" ; texinfo
- "^.+:-") ; prolog
- "*Regexps for Headings. Used by \[\[ and \]\].")
-
-(defvar vip-heading-end
- (concat "^}\\|" ; C/C++
- "^\\\\end{\\|" ; latex
- "^@end \\|" ; texinfo
- ")\n\n[ \t\n]*\\|" ; lisp
- "\\.\\s-*$") ; prolog
- "*Regexps to end Headings/Sections. Used by \[\].")
-
-
-;; These two vars control the interaction of jumps performed by ' and `.
-;; In this new version, '' doesn't erase the marks set by ``, so one can
-;; use both kinds of jumps interchangeably and without loosing positions
-;; inside the lines.
-
-;; Remembers position of the last jump done using ``'.
-(vip-deflocalvar vip-last-jump nil)
-;; Remembers position of the last jump done using `''.
-(vip-deflocalvar vip-last-jump-ignore 0)
-
-;; Some common error messages
-
-(defconst vip-SpuriousText "Spurious text after command" "")
-(defconst vip-BadExCommand "Not an editor command" "")
-(defconst vip-InvalidCommandArgument "Invalid command argument" "")
-(defconst vip-NoPrevSearch "No previous search string" "")
-(defconst vip-EmptyRegister "`%c': Nothing in this register" "")
-(defconst vip-InvalidRegister "`%c': Invalid register" "")
-(defconst vip-EmptyTextmarker "`%c': Text marker doesn't point anywhere" "")
-(defconst vip-InvalidTextmarker "`%c': Invalid text marker" "")
-(defconst vip-InvalidViCommand "Invalid command" "")
-(defconst vip-BadAddress "Ill-formed address" "")
-(defconst vip-FirstAddrExceedsSecond "First address exceeds second" "")
-(defconst vip-NoFileSpecified "No file specified" "")
-
-
-;; History variables
-
-;; History of search strings.
-(defvar vip-search-history (list ""))
-;; History of query-replace strings used as a source.
-(defvar vip-replace1-history nil)
-;; History of query-replace strings used as replacement.
-(defvar vip-replace2-history nil)
-;; History of region quoting strings.
-(defvar vip-quote-region-history (list vip-quote-string))
-;; History of Ex-style commands.
-(defvar vip-ex-history nil)
-;; History of shell commands.
-(defvar vip-shell-history nil)
-
-
-;; Last shell command. There are two of these, one for Ex (in viper-ex)
-;; and one for Vi.
-
-;; Last shell command executed with ! command.
-(defvar vip-last-shell-com nil)
-
-
-
-;;; Miscellaneous
-
-;; don't bark when mark is inactive
-(setq mark-even-if-inactive t)
-
-(defvar vip-inhibit-startup-message nil
- "Whether Viper startup message should be inhibited.")
-
-(defvar vip-always t
- "t means, arrange that vi-state will be a default.")
-
-(defvar vip-custom-file-name (vip-convert-standard-file-name "~/.vip")
- "Viper customisation file.
-This variable must be set _before_ loading Viper.")
-
-
-(defvar vip-spell-function 'ispell-region
- "Spell function used by #s<move> command to spell.")
-
-(defvar vip-tags-file-name "TAGS"
- "The tags file used by Viper.")
-
-;; Minibuffer
-
-(defvar vip-vi-style-in-minibuffer t
- "If t, use vi-style editing in minibuffer.
-Should be set in `~/.vip' file.")
-
-;; overlay used in the minibuffer to indicate which state it is in
-(vip-deflocalvar vip-minibuffer-overlay nil)
-
-;; Hook, specific to Viper, which is run just *before* exiting the minibuffer.
-;; Beginning with Emacs 19.26, the standard `minibuffer-exit-hook' is run
-;; *after* exiting the minibuffer
-(defvar vip-minibuffer-exit-hook nil)
-
-(vip-deflocalvar vip-vi-minibuffer-minor-mode nil
- "Minor mode that forces Vi-style when the Minibuffer is in Vi state.")
-(vip-deflocalvar vip-insert-minibuffer-minor-mode nil
- "Minor mode that forces Vi-style when the Minibuffer is in Insert state.")
-
-;; setup emacs-supported vi-style feel
-(setq next-line-add-newlines nil
- require-final-newline t)
-
-(make-variable-buffer-local 'require-final-newline)
-
-
-;; Mode line
-(defconst vip-vi-state-id "<V> "
- "Mode line tag identifying the Vi mode of Viper.")
-(defconst vip-emacs-state-id "<E> "
- "Mode line tag identifying the Emacs mode of Viper.")
-(defconst vip-insert-state-id "<I> "
- "Mode line tag identifying the Insert mode of Viper.")
-(defconst vip-replace-state-id "<R> "
- "Mode line tag identifying the Replace mode of Viper.")
-
-;; Viper changes the default mode-line-buffer-identification
-(setq-default mode-line-buffer-identification '(" %b"))
-
-;; Variable displaying the current Viper state in the mode line.
-(vip-deflocalvar vip-mode-string vip-emacs-state-id)
-(or (memq 'vip-mode-string global-mode-string)
- (setq global-mode-string
- (append '("" vip-mode-string) (cdr global-mode-string))))
-
-
-(defvar vip-vi-state-hook nil
- "*Hooks run just before the switch to Vi mode is completed.")
-(defvar vip-insert-state-hook nil
- "*Hooks run just before the switch to Insert mode is completed.")
-(defvar vip-replace-state-hook nil
- "*Hooks run just before the switch to Replace mode is completed.")
-(defvar vip-emacs-state-hook nil
- "*Hooks run just before the switch to Emacs mode is completed.")
-
-(defvar vip-load-hook nil
- "Hooks run just after loading Viper.")
-
-
-;; Generic predicates
-
-;; These test functions are shamelessly lifted from vip 4.4.2 by Aamod Sane
-
-;; generate test functions
-;; given symbol foo, foo-p is the test function, foos is the set of
-;; Viper command keys
-;; (macroexpand '(vip-test-com-defun foo))
-;; (defun foo-p (com) (consp (memq (if (< com 0) (- com) com) foos)))
-
-(defmacro vip-test-com-defun (name)
- (let* ((snm (symbol-name name))
- (nm-p (intern (concat snm "-p")))
- (nms (intern (concat snm "s"))))
- (` (defun (, nm-p) (com)
- (consp (memq (if (< com 0) (- com) com) (, nms)))))))
-
-;; Variables for defining VI commands
-
-;; Modifying commands that can be prefixes to movement commands
-(defconst vip-prefix-commands '(?c ?d ?y ?! ?= ?# ?< ?> ?\"))
-(vip-test-com-defun vip-prefix-command)
-
-;; Commands that are pairs eg. dd. r and R here are a hack
-(defconst vip-charpair-commands '(?c ?d ?y ?! ?= ?< ?> ?r ?R))
-(vip-test-com-defun vip-charpair-command)
-
-(defconst vip-movement-commands '(?b ?B ?e ?E ?f ?F ?G ?h ?H ?j ?k ?l
- ?H ?M ?n ?t ?T ?w ?W ?$ ?%
- ?^ ?( ?) ?- ?+ ?| ?{ ?} ?[ ?] ?' ?`
- ?; ?, ?0 ?? ?/
- )
- "Movement commands")
-(vip-test-com-defun vip-movement-command)
-
-;; Commands that can be repeated by . (dotted)
-(defconst vip-dotable-commands '(?c ?d ?C ?D ?> ?<))
-(vip-test-com-defun vip-dotable-command)
-
-;; Commands that can follow a #
-(defconst vip-hash-cmds '(?c ?C ?g ?q ?S))
-(vip-test-com-defun vip-hash-cmd)
-
-;; Commands that may have registers as prefix
-(defconst vip-regsuffix-commands '(?d ?y ?Y ?D ?p ?P ?x ?X))
-(vip-test-com-defun vip-regsuffix-command)
-
-(defconst vip-vi-commands (append vip-movement-commands
- vip-dotable-commands
- vip-charpair-commands
- vip-hash-cmds
- vip-prefix-commands
- vip-regsuffix-commands)
- "The list of all commands in Vi-state.")
-(vip-test-com-defun vip-vi-command)
-
-
-;;; Arrange the keymaps
-(require 'viper-keym)
-
-
-;;; CODE
-
-;; sentinels
-
-;; Runs vip-after-change-functions inside after-change-functions
-(defun vip-after-change-sentinel (beg end len)
- (let ((list vip-after-change-functions))
- (while list
- (funcall (car list) beg end len)
- (setq list (cdr list)))))
-
-;; Runs vip-before-change-functions inside before-change-functions
-(defun vip-before-change-sentinel (beg end)
- (let ((list vip-before-change-functions))
- (while list
- (funcall (car list) beg end)
- (setq list (cdr list)))))
-
-(defsubst vip-post-command-sentinel ()
- (run-hooks 'vip-post-command-hooks))
-
-(defsubst vip-pre-command-sentinel ()
- (run-hooks 'vip-pre-command-hooks))
-
-;; Needed so that Viper will be able to figure the last inserted
-;; chunk of text with reasonable accuracy.
-(defsubst vip-insert-state-post-command-sentinel ()
- (if (and (memq vip-current-state '(insert-state replace-state))
- vip-insert-point
- (>= (point) vip-insert-point))
- (setq vip-last-posn-while-in-insert-state (point-marker)))
- (if (eq vip-current-state 'insert-state)
- (progn
- (or (stringp vip-saved-cursor-color)
- (string= (vip-get-cursor-color) vip-insert-state-cursor-color)
- (setq vip-saved-cursor-color (vip-get-cursor-color)))
- (if (stringp vip-saved-cursor-color)
- (vip-change-cursor-color vip-insert-state-cursor-color))
- ))
- (if (and (eq this-command 'dabbrev-expand)
- (integerp vip-pre-command-point)
- (> vip-insert-point vip-pre-command-point))
- (move-marker vip-insert-point vip-pre-command-point))
- )
-
-(defsubst vip-insert-state-pre-command-sentinel ()
- (or (memq this-command '(self-insert-command))
- (memq (vip-event-key last-command-event)
- '(up down left right (meta f) (meta b)
- (control n) (control p) (control f) (control b)))
- (vip-restore-cursor-color-after-insert))
- (if (and (eq this-command 'dabbrev-expand)
- (markerp vip-insert-point)
- (marker-position vip-insert-point))
- (setq vip-pre-command-point (marker-position vip-insert-point))))
-
-(defsubst vip-R-state-post-command-sentinel ()
- ;; Restoring cursor color is needed despite
- ;; vip-replace-state-pre-command-sentinel: When you jump to another buffer in
- ;; another frame, the pre-command hook won't change cursor color to default
- ;; in that other frame. So, if the second frame cursor was red and we set
- ;; the point outside the replacement region, then the cursor color will
- ;; remain red. Restoring the default, below, prevents this.
- (if (and (<= (vip-replace-start) (point))
- (<= (point) (vip-replace-end)))
- (vip-change-cursor-color vip-replace-overlay-cursor-color)
- (vip-restore-cursor-color-after-replace)
- ))
-
-;; to speed up, don't change cursor color before self-insert
-;; and common move commands
-(defsubst vip-replace-state-pre-command-sentinel ()
- (or (memq this-command '(self-insert-command))
- (memq (vip-event-key last-command-event)
- '(up down left right (meta f) (meta b)
- (control n) (control p) (control f) (control b)))
- (vip-restore-cursor-color-after-replace)))
-
-(defun vip-replace-state-post-command-sentinel ()
- ;; Restoring cursor color is needed despite
- ;; vip-replace-state-pre-command-sentinel: When one jumps to another buffer
- ;; in another frame, the pre-command hook won't change cursor color to
- ;; default in that other frame. So, if the second frame cursor was red and
- ;; we set the point outside the replacement region, then the cursor color
- ;; will remain red. Restoring the default, below, fixes this problem.
- ;;
- ;; We optimize for self-insert-command's here, since they either don't change
- ;; cursor color or, if they terminate replace mode, the color will be changed
- ;; in vip-finish-change
- (or (memq this-command '(self-insert-command))
- (vip-restore-cursor-color-after-replace))
- (cond
- ((eq vip-current-state 'replace-state)
- ;; delete characters to compensate for inserted chars.
- (let ((replace-boundary (vip-replace-end)))
- (save-excursion
- (goto-char vip-last-posn-in-replace-region)
- (delete-char vip-replace-chars-to-delete)
- (setq vip-replace-chars-to-delete 0
- vip-replace-chars-deleted 0)
- ;; terminate replace mode if reached replace limit
- (if (= vip-last-posn-in-replace-region
- (vip-replace-end))
- (vip-finish-change vip-last-posn-in-replace-region)))
-
- (if (and (<= (vip-replace-start) (point))
- (<= (point) replace-boundary))
- (progn
- ;; the state may have changed in vip-finish-change above
- (if (eq vip-current-state 'replace-state)
- (vip-change-cursor-color vip-replace-overlay-cursor-color))
- (setq vip-last-posn-in-replace-region (point-marker))))
- ))
-
- (t ;; terminate replace mode if changed Viper states.
- (vip-finish-change vip-last-posn-in-replace-region))))
-
-
-;; changing mode
-
-;; Change state to NEW-STATE---either emacs-state, vi-state, or insert-state.
-(defun vip-change-state (new-state)
- ;; Keep vip-post/pre-command-hooks fresh.
- ;; We remove then add vip-post/pre-command-sentinel since it is very
- ;; desirable that vip-pre-command-sentinel is the last hook and
- ;; vip-post-command-sentinel is the first hook.
- (remove-hook 'post-command-hook 'vip-post-command-sentinel)
- (add-hook 'post-command-hook 'vip-post-command-sentinel)
- (remove-hook 'pre-command-hook 'vip-pre-command-sentinel)
- (add-hook 'pre-command-hook 'vip-pre-command-sentinel t)
- ;; These hooks will be added back if switching to insert/replace mode
- (vip-remove-hook 'vip-post-command-hooks
- 'vip-insert-state-post-command-sentinel)
- (vip-remove-hook 'vip-pre-command-hooks
- 'vip-insert-state-pre-command-sentinel)
- (cond ((eq new-state 'vi-state)
- (cond ((member vip-current-state '(insert-state replace-state))
-
- ;; move vip-last-posn-while-in-insert-state
- ;; This is a normal hook that is executed in insert/replace
- ;; states after each command. In Vi/Emacs state, it does
- ;; nothing. We need to execute it here to make sure that
- ;; the last posn was recorded when we hit ESC.
- ;; It may be left unrecorded if the last thing done in
- ;; insert/repl state was dabbrev-expansion or abbrev
- ;; expansion caused by hitting ESC
- (vip-insert-state-post-command-sentinel)
-
- (condition-case conds
- (progn
- (vip-save-last-insertion
- vip-insert-point
- vip-last-posn-while-in-insert-state)
- (if vip-began-as-replace
- (setq vip-began-as-replace nil)
- ;; repeat insert commands if numerical arg > 1
- (save-excursion
- (vip-repeat-insert-command))))
- (error
- (vip-message-conditions conds)))
-
- (if (> (length vip-last-insertion) 0)
- (vip-push-onto-ring vip-last-insertion
- 'vip-insertion-ring))
-
- (if vip-ex-style-editing-in-insert
- (or (bolp) (backward-char 1))))
- ))
-
- ;; insert or replace
- ((memq new-state '(insert-state replace-state))
- (if (memq vip-current-state '(emacs-state vi-state))
- (vip-move-marker-locally 'vip-insert-point (point)))
- (vip-move-marker-locally 'vip-last-posn-while-in-insert-state (point))
- (vip-add-hook 'vip-post-command-hooks
- 'vip-insert-state-post-command-sentinel t)
- (vip-add-hook 'vip-pre-command-hooks
- 'vip-insert-state-pre-command-sentinel t))
- ) ; outermost cond
-
- ;; Nothing needs to be done to switch to emacs mode! Just set some
- ;; variables, which is already done in vip-change-state-to-emacs!
-
- (setq vip-current-state new-state)
- (vip-normalize-minor-mode-map-alist)
- (vip-adjust-keys-for new-state)
- (vip-set-mode-vars-for new-state)
- (vip-refresh-mode-line)
- )
-
-
-
-(defun vip-adjust-keys-for (state)
- "Make necessary adjustments to keymaps before entering STATE."
- (cond ((memq state '(insert-state replace-state))
- (if vip-auto-indent
- (progn
- (define-key vip-insert-basic-map "\C-m" 'vip-autoindent)
- (if vip-want-emacs-keys-in-insert
- ;; expert
- (define-key vip-insert-basic-map "\C-j" nil)
- ;; novice
- (define-key vip-insert-basic-map "\C-j" 'vip-autoindent))))
-
- (setq vip-insert-diehard-minor-mode
- (not vip-want-emacs-keys-in-insert))
-
- (if vip-want-ctl-h-help
- (progn
- (define-key vip-insert-basic-map [(control h)] 'help-command)
- (define-key vip-replace-map [(control h)] 'help-command))
- (define-key vip-insert-basic-map
- [(control h)] 'vip-del-backward-char-in-insert)
- (define-key vip-replace-map
- [(control h)] 'vip-del-backward-char-in-replace)))
-
- (t ; Vi state
- (setq vip-vi-diehard-minor-mode (not vip-want-emacs-keys-in-vi))
- (if vip-want-ctl-h-help
- (define-key vip-vi-basic-map [(control h)] 'help-command)
- (define-key vip-vi-basic-map [(control h)] 'vip-backward-char)))
- ))
-
-
-;; Normalizes minor-mode-map-alist by putting Viper keymaps first.
-;; This ensures that Viper bindings are in effect, regardless of which minor
-;; modes were turned on by the user or by other packages.
-(defun vip-normalize-minor-mode-map-alist ()
- (setq minor-mode-map-alist
- (vip-append-filter-alist
- (list
- (cons 'vip-vi-intercept-minor-mode vip-vi-intercept-map)
- (cons 'vip-vi-minibuffer-minor-mode vip-minibuffer-map)
- (cons 'vip-vi-local-user-minor-mode vip-vi-local-user-map)
- (cons 'vip-vi-kbd-minor-mode vip-vi-kbd-map)
- (cons 'vip-vi-global-user-minor-mode vip-vi-global-user-map)
- (cons 'vip-vi-state-modifier-minor-mode
- (if (keymapp
- (cdr (assoc major-mode vip-vi-state-modifier-alist)))
- (cdr (assoc major-mode vip-vi-state-modifier-alist))
- vip-empty-keymap))
- (cons 'vip-vi-diehard-minor-mode vip-vi-diehard-map)
- (cons 'vip-vi-basic-minor-mode vip-vi-basic-map)
- (cons 'vip-insert-intercept-minor-mode vip-insert-intercept-map)
- (cons 'vip-replace-minor-mode vip-replace-map)
- ;; vip-insert-minibuffer-minor-mode must come after
- ;; vip-replace-minor-mode
- (cons 'vip-insert-minibuffer-minor-mode
- vip-minibuffer-map)
- (cons 'vip-insert-local-user-minor-mode
- vip-insert-local-user-map)
- (cons 'vip-insert-kbd-minor-mode vip-insert-kbd-map)
- (cons 'vip-insert-global-user-minor-mode
- vip-insert-global-user-map)
- (cons 'vip-insert-state-modifier-minor-mode
- (if (keymapp
- (cdr
- (assoc major-mode vip-insert-state-modifier-alist)))
- (cdr
- (assoc major-mode vip-insert-state-modifier-alist))
- vip-empty-keymap))
- (cons 'vip-insert-diehard-minor-mode vip-insert-diehard-map)
- (cons 'vip-insert-basic-minor-mode vip-insert-basic-map)
- (cons 'vip-emacs-intercept-minor-mode
- vip-emacs-intercept-map)
- (cons 'vip-emacs-local-user-minor-mode
- vip-emacs-local-user-map)
- (cons 'vip-emacs-kbd-minor-mode vip-emacs-kbd-map)
- (cons 'vip-emacs-global-user-minor-mode
- vip-emacs-global-user-map)
- (cons 'vip-emacs-state-modifier-minor-mode
- (if (keymapp
- (cdr
- (assoc major-mode vip-emacs-state-modifier-alist)))
- (cdr
- (assoc major-mode vip-emacs-state-modifier-alist))
- vip-empty-keymap))
- )
- minor-mode-map-alist)))
-
-
-
-
-
-;; Viper mode-changing commands and utilities
-
-;; Modifies mode-line-buffer-identification.
-(defun vip-refresh-mode-line ()
- (setq vip-mode-string
- (cond ((eq vip-current-state 'emacs-state) vip-emacs-state-id)
- ((eq vip-current-state 'vi-state) vip-vi-state-id)
- ((eq vip-current-state 'replace-state) vip-replace-state-id)
- ((eq vip-current-state 'insert-state) vip-insert-state-id)))
-
- ;; Sets Viper mode string in global-mode-string
- (force-mode-line-update))
-
-;;;###autoload
-(defun viper-mode ()
- "Turn on Viper emulation of Vi."
- (interactive)
- (if (not noninteractive)
- (progn
- (if vip-first-time ; This check is important. Without it, startup and
- (progn ; expert-level msgs mix up when viper-mode recurses
- (setq vip-first-time nil)
- (if (not vip-inhibit-startup-message)
- (save-window-excursion
- (setq vip-inhibit-startup-message t)
- (delete-other-windows)
- (switch-to-buffer "Viper Startup Message")
- (erase-buffer)
- (insert
- (substitute-command-keys
- "Viper Is a Package for Emacs Rebels.
-It is also a VI Plan for Emacs Rescue and a venomous VI PERil.
-
-Technically speaking, Viper is a Vi emulation package for GNU Emacs 19 and
-XEmacs 19. It supports virtually all of Vi and Ex functionality, extending
-and improving upon much of it.
-
- 1. Viper supports Vi at several levels. Level 1 is the closest to Vi,
- level 5 provides the most flexibility to depart from many Vi conventions.
-
- You will be asked to specify your user level in a following screen.
-
- If you select user level 1 then the keys ^X, ^C, ^Z, and ^G will behave
- as in VI, to smooth transition to Viper for the beginners. However, to
- use Emacs productively, you are advised to reach user level 3 or higher.
-
- If your user level is 2 or higher, ^X and ^C will invoke Emacs
- functions,as usual in Emacs; ^Z will toggle vi/emacs modes, and
- ^G will be the usual Emacs's keyboard-quit (something like ^C in VI).
-
- 2. Vi exit functions (e.g., :wq, ZZ) work on INDIVIDUAL files -- they
- do not cause Emacs to quit, except at user level 1 (a novice).
- 3. ^X^C EXITS EMACS.
- 4. Viper supports multiple undo: `u' will undo. Typing `.' will repeat
- undo. Another `u' changes direction.
-
- 6. Emacs Meta functions are invoked by typing `C-\\' or `\\ ESC'.
- On a window system, the best way is to use the Meta-key.
- 7. Try \\[keyboard-quit] and \\[abort-recursive-edit] repeatedly,if
- something funny happens. This would abort the current editing command.
-
-You can get more information on Viper by:
-
- a. Typing `:help' in Vi state
- b. Printing Viper manual, found in ./etc/viper.dvi
- c. Printing ViperCard, the Quick Reference, found in ./etc/viperCard.dvi
-
-This startup message appears whenever you load Viper, unless you type `y' now."
- ))
- (goto-char (point-min))
- (if (y-or-n-p "Inhibit Viper startup message? ")
- (vip-save-setting
- 'vip-inhibit-startup-message
- "Viper startup message inhibited"
- vip-custom-file-name t))
- ;;(kill-buffer (current-buffer))
- (message
- "The last message is in buffer `Viper Startup Message'")
- (sit-for 4)
- ))
- (vip-set-expert-level 'dont-change-unless)))
- (vip-change-state-to-vi))))
-
-;;;###autoload
-(defalias 'vip-mode 'viper-mode)
-
-
-;; Switch from Insert state to Vi state.
-(defun vip-exit-insert-state ()
- (interactive)
- (vip-change-state-to-vi))
-
-(defun vip-set-mode-vars-for (state)
- "Sets Viper minor mode variables to put Viper's state STATE in effect."
-
- ;; Emacs state
- (setq vip-vi-minibuffer-minor-mode nil
- vip-insert-minibuffer-minor-mode nil
- vip-vi-intercept-minor-mode nil
- vip-insert-intercept-minor-mode nil
-
- vip-vi-local-user-minor-mode nil
- vip-vi-kbd-minor-mode nil
- vip-vi-global-user-minor-mode nil
- vip-vi-state-modifier-minor-mode nil
- vip-vi-diehard-minor-mode nil
- vip-vi-basic-minor-mode nil
-
- vip-replace-minor-mode nil
-
- vip-insert-local-user-minor-mode nil
- vip-insert-kbd-minor-mode nil
- vip-insert-global-user-minor-mode nil
- vip-insert-state-modifier-minor-mode nil
- vip-insert-diehard-minor-mode nil
- vip-insert-basic-minor-mode nil
- vip-emacs-intercept-minor-mode t
- vip-emacs-local-user-minor-mode t
- vip-emacs-kbd-minor-mode (not (vip-is-in-minibuffer))
- vip-emacs-global-user-minor-mode t
- vip-emacs-state-modifier-minor-mode t
- )
-
- ;; Vi state
- (if (eq state 'vi-state) ; adjust for vi-state
- (setq
- vip-vi-intercept-minor-mode t
- vip-vi-minibuffer-minor-mode (vip-is-in-minibuffer)
- vip-vi-local-user-minor-mode t
- vip-vi-kbd-minor-mode (not (vip-is-in-minibuffer))
- vip-vi-global-user-minor-mode t
- vip-vi-state-modifier-minor-mode t
- ;; don't let the diehard keymap block command completion
- ;; and other things in the minibuffer
- vip-vi-diehard-minor-mode (not
- (or vip-want-emacs-keys-in-vi
- (vip-is-in-minibuffer)))
- vip-vi-basic-minor-mode t
- vip-emacs-intercept-minor-mode nil
- vip-emacs-local-user-minor-mode nil
- vip-emacs-kbd-minor-mode nil
- vip-emacs-global-user-minor-mode nil
- vip-emacs-state-modifier-minor-mode nil
- ))
-
- ;; Insert and Replace states
- (if (member state '(insert-state replace-state))
- (setq
- vip-insert-intercept-minor-mode t
- vip-replace-minor-mode (eq state 'replace-state)
- vip-insert-minibuffer-minor-mode (vip-is-in-minibuffer)
- vip-insert-local-user-minor-mode t
- vip-insert-kbd-minor-mode (not (vip-is-in-minibuffer))
- vip-insert-global-user-minor-mode t
- vip-insert-state-modifier-minor-mode t
- ;; don't let the diehard keymap block command completion
- ;; and other things in the minibuffer
- vip-insert-diehard-minor-mode (not
- (or vip-want-emacs-keys-in-insert
- (vip-is-in-minibuffer)))
- vip-insert-basic-minor-mode t
- vip-emacs-intercept-minor-mode nil
- vip-emacs-local-user-minor-mode nil
- vip-emacs-kbd-minor-mode nil
- vip-emacs-global-user-minor-mode nil
- vip-emacs-state-modifier-minor-mode nil
- ))
-
- ;; minibuffer faces
- (if (vip-has-face-support-p)
- (setq vip-minibuffer-current-face
- (cond ((eq state 'emacs-state) vip-minibuffer-emacs-face)
- ((eq state 'vi-state) vip-minibuffer-vi-face)
- ((memq state '(insert-state replace-state))
- vip-minibuffer-insert-face))))
-
- (if (vip-is-in-minibuffer)
- (vip-set-minibuffer-overlay))
- )
-
-;; This also takes care of the annoying incomplete lines in files.
-;; Also, this fixes `undo' to work vi-style for complex commands.
-(defun vip-change-state-to-vi ()
- "Change Viper state to Vi."
- (interactive)
- (if (and vip-first-time (not (vip-is-in-minibuffer)))
- (viper-mode)
- (if overwrite-mode (overwrite-mode nil))
- (if abbrev-mode (expand-abbrev))
- (if (and auto-fill-function (> (current-column) fill-column))
- (funcall auto-fill-function))
- ;; don't leave whitespace lines around
- (if (and (memq last-command
- '(vip-autoindent
- vip-open-line vip-Open-line
- vip-replace-state-exit-cmd))
- (vip-over-whitespace-line))
- (indent-to-left-margin))
- (vip-add-newline-at-eob-if-necessary)
- (if vip-undo-needs-adjustment (vip-adjust-undo))
- (vip-change-state 'vi-state)
-
- ;; always turn off iso-accents-mode, or else we won't be able to use the
- ;; keys `,',^ in Vi state, as they will do accents instead of Vi actions.
- (if (and (boundp 'iso-accents-mode) iso-accents-mode)
- (iso-accents-mode -1))
-
- (vip-restore-cursor-color-after-insert)
-
- ;; Protection against user errors in hooks
- (condition-case conds
- (run-hooks 'vip-vi-state-hook)
- (error
- (vip-message-conditions conds)))))
-
-(defun vip-change-state-to-insert ()
- "Change Viper state to Insert."
- (interactive)
- (vip-change-state 'insert-state)
- (if (and vip-automatic-iso-accents (fboundp 'iso-accents-mode))
- (iso-accents-mode 1)) ; turn iso accents on
-
- (or (stringp vip-saved-cursor-color)
- (string= (vip-get-cursor-color) vip-insert-state-cursor-color)
- (setq vip-saved-cursor-color (vip-get-cursor-color)))
- ;; Commented out, because if vip-change-state-to-insert is executed
- ;; non-interactively then the old cursor color may get lost. Same old Emacs
- ;; bug related to local variables?
-;;;(if (stringp vip-saved-cursor-color)
-;;; (vip-change-cursor-color vip-insert-state-cursor-color))
- ;; Protection against user errors in hooks
- (condition-case conds
- (run-hooks 'vip-insert-state-hook)
- (error
- (vip-message-conditions conds))))
-
-(defsubst vip-downgrade-to-insert ()
- (setq vip-current-state 'insert-state
- vip-replace-minor-mode nil)
- )
-
-
-
-;; Change to replace state. When the end of replacement region is reached,
-;; replace state changes to insert state.
-(defun vip-change-state-to-replace (&optional non-R-cmd)
- (vip-change-state 'replace-state)
- (if (and vip-automatic-iso-accents (fboundp 'iso-accents-mode))
- (iso-accents-mode 1)) ; turn iso accents on
- ;; Run insert-state-hook
- (condition-case conds
- (run-hooks 'vip-insert-state-hook 'vip-replace-state-hook)
- (error
- (vip-message-conditions conds)))
-
- (if non-R-cmd
- (vip-start-replace)
- ;; 'R' is implemented using Emacs's overwrite-mode
- (vip-start-R-mode))
- )
-
-
-(defun vip-change-state-to-emacs ()
- "Change Viper state to Emacs."
- (interactive)
- (vip-change-state 'emacs-state)
- (if (and vip-automatic-iso-accents (fboundp 'iso-accents-mode))
- (iso-accents-mode 1)) ; turn iso accents on
-
- ;; Protection agains user errors in hooks
- (condition-case conds
- (run-hooks 'vip-emacs-state-hook)
- (error
- (vip-message-conditions conds))))
-
-;; escape to emacs mode termporarily
-(defun vip-escape-to-emacs (arg &optional events)
- "Escape to Emacs state from Vi state for one Emacs command.
-ARG is used as the prefix value for the executed command. If
-EVENTS is a list of events, which become the beginning of the command."
- (interactive "P")
- (if (= last-command-char ?\\)
- (message "Switched to EMACS state for the next command..."))
- (vip-escape-to-state arg events 'emacs-state))
-
-;; escape to Vi mode termporarily
-(defun vip-escape-to-vi (arg)
- "Escape from Emacs state to Vi state for one Vi 1-character command.
-If the Vi command that the user types has a prefix argument, e.g., `d2w', then
-Vi's prefix argument will be used. Otherwise, the prefix argument passed to
-`vip-escape-to-vi' is used."
- (interactive "P")
- (message "Switched to VI state for the next command...")
- (vip-escape-to-state arg nil 'vi-state))
-
-;; Escape to STATE mode for one Emacs command.
-(defun vip-escape-to-state (arg events state)
- ;;(let (com key prefix-arg)
- (let (com key)
- ;; this temporarily turns off Viper's minor mode keymaps
- (vip-set-mode-vars-for state)
- (vip-normalize-minor-mode-map-alist)
- (if events (vip-set-unread-command-events events))
-
- ;; protect against keyboard quit and other errors
- (condition-case nil
- (let (vip-vi-kbd-minor-mode
- vip-insert-kbd-minor-mode
- vip-emacs-kbd-minor-mode)
- (unwind-protect
- (progn
- (setq com (key-binding (setq key
- (if vip-xemacs-p
- (read-key-sequence nil)
- (read-key-sequence nil t)))))
- ;; In case of binding indirection--chase definitions.
- ;; Have to do it here because we execute this command under
- ;; different keymaps, so command-execute may not do the
- ;; right thing there
- (while (vectorp com) (setq com (key-binding com))))
- nil)
- ;; Execute command com in the original Viper state, not in state
- ;; `state'. Otherwise, if we switch buffers while executing the
- ;; escaped to command, Viper's mode vars will remain those of
- ;; `state'. When we return to the orig buffer, the bindings will be
- ;; screwed up.
- (vip-set-mode-vars-for vip-current-state)
-
- ;; this-command, last-command-char, last-command-event
- (setq this-command com)
- (if vip-xemacs-p ; XEmacs represents key sequences as vectors
- (setq last-command-event (vip-seq-last-elt key)
- last-command-char (event-to-character last-command-event))
- ;; Emacs represents them as sequences (str or vec)
- (setq last-command-event (vip-seq-last-elt key)
- last-command-char last-command-event))
-
- (if (commandp com)
- (progn
- (setq prefix-arg (or prefix-arg arg))
- (command-execute com)))
- )
- (quit (ding))
- (error (beep 1))))
- ;; set state in the new buffer
- (vip-set-mode-vars-for vip-current-state))
-
-(defun vip-exec-form-in-vi (form)
- "Execute FORM in Vi state, regardless of the Ccurrent Vi state."
- (let ((buff (current-buffer))
- result)
- (vip-set-mode-vars-for 'vi-state)
- (setq result (eval form))
- (if (not (equal buff (current-buffer))) ; cmd switched buffer
- (save-excursion
- (set-buffer buff)
- (vip-set-mode-vars-for vip-current-state)))
- (vip-set-mode-vars-for vip-current-state)
- result))
-
-(defun vip-exec-form-in-emacs (form)
- "Execute FORM in Emacs, temporarily disabling Viper's minor modes.
-Similar to vip-escape-to-emacs, but accepts forms rather than keystrokes."
- (let ((buff (current-buffer))
- result)
- (vip-set-mode-vars-for 'emacs-state)
- (setq result (eval form))
- (if (not (equal buff (current-buffer))) ; cmd switched buffer
- (save-excursion
- (set-buffer buff)
- (vip-set-mode-vars-for vip-current-state)))
- (vip-set-mode-vars-for vip-current-state)
- result))
-
-
-;; This is needed because minor modes sometimes override essential Viper
-;; bindings. By letting Viper know which files these modes are in, it will
-;; arrange to reorganize minor-mode-map-alist so that things will work right.
-(defun vip-harness-minor-mode (load-file)
- "Familiarize Viper with a minor mode defined in LOAD_FILE.
-Minor modes that have their own keymaps may overshadow Viper keymaps.
-This function is designed to make Viper aware of the packages that define
-such minor modes.
-Usage:
- (vip-harness-minor-mode load-file)
-
-LOAD-FILE is a name of the file where the specific minor mode is defined.
-Suffixes such as .el or .elc should be stripped."
-
- (interactive "sEnter name of the load file: ")
-
- (vip-eval-after-load load-file '(vip-normalize-minor-mode-map-alist))
-
- ;; Change the default for minor-mode-map-alist each time a harnessed minor
- ;; mode adds its own keymap to the a-list.
- (vip-eval-after-load
- load-file '(setq-default minor-mode-map-alist minor-mode-map-alist))
- )
-
-
-(defun vip-ESC (arg)
- "Emulate ESC key in Emacs.
-Prevents multiple escape keystrokes if vip-no-multiple-ESC is true.
-If vip-no-multiple-ESC is 'twice double ESC would ding in vi-state.
-Other ESC sequences are emulated via the current Emacs's major mode
-keymap. This is more convenient on TTYs, since this won't block
-function keys such as up,down, etc. ESC will also will also work as
-a Meta key in this case. When vip-no-multiple-ESC is nil, ESC functions
-as a Meta key and any number of multiple escapes is allowed."
- (interactive "P")
- (let (char)
- (cond ((and (not vip-no-multiple-ESC) (eq vip-current-state 'vi-state))
- (setq char (vip-read-char-exclusive))
- (vip-escape-to-emacs arg (list ?\e char) ))
- ((and (eq vip-no-multiple-ESC 'twice)
- (eq vip-current-state 'vi-state))
- (setq char (vip-read-char-exclusive))
- (if (= char (string-to-char vip-ESC-key))
- (ding)
- (vip-escape-to-emacs arg (list ?\e char) )))
- (t (ding)))
- ))
-
-(defun vip-alternate-Meta-key (arg)
- "Simulate Emacs Meta key."
- (interactive "P")
- (sit-for 1) (message "ESC-")
- (vip-escape-to-emacs arg '(?\e)))
-
-(defun vip-toggle-key-action ()
- "Action bound to `vip-toggle-key'."
- (interactive)
- (if (and (< vip-expert-level 2) (equal vip-toggle-key "\C-z"))
- (if (vip-window-display-p)
- (vip-iconify)
- (suspend-emacs))
- (vip-change-state-to-emacs)))
-
-
-;; Intercept ESC sequences on dumb terminals.
-;; Based on the idea contributed by Marcelino Veiga Tuimil <mveiga@dit.upm.es>
-
-;; Check if last key was ESC and if so try to reread it as a function key.
-;; But only if there are characters to read during a very short time.
-;; Returns the last event, if any.
-(defun vip-envelop-ESC-key ()
- (let ((event last-input-event)
- (keyseq [nil])
- inhibit-quit)
- (if (vip-ESC-event-p event)
- (progn
- (if (vip-fast-keysequence-p)
- (progn
- (let (minor-mode-map-alist)
- (vip-set-unread-command-events event)
- (setq keyseq
- (funcall
- (ad-get-orig-definition 'read-key-sequence) nil))
- ) ; let
- ;; If keyseq translates into something that still has ESC
- ;; at the beginning, separate ESC from the rest of the seq.
- ;; In XEmacs we check for events that are keypress meta-key
- ;; and convert them into [escape key]
- ;;
- ;; This is needed for the following reason:
- ;; If ESC is the first symbol, we interpret it as if the
- ;; user typed ESC and then quickly some other symbols.
- ;; If ESC is not the first one, then the key sequence
- ;; entered was apparently translated into a function key or
- ;; something (e.g., one may have
- ;; (define-key function-key-map "\e[192z" [f11])
- ;; which would translate the escape-sequence generated by
- ;; f11 in an xterm window into the symbolic key f11.
- ;;
- ;; If `first-key' is not an ESC event, we make it into the
- ;; last-command-event in order to pretend that this key was
- ;; pressed. This is needed to allow arrow keys to be bound to
- ;; macros. Otherwise, vip-exec-mapped-kbd-macro will think that
- ;; the last event was ESC and so it'll execute whatever is
- ;; bound to ESC. (Viper macros can't be bound to
- ;; ESC-sequences).
- (let* ((first-key (elt keyseq 0))
- (key-mod (event-modifiers first-key)))
- (cond ((vip-ESC-event-p first-key)
- ;; put keys following ESC on the unread list
- ;; and return ESC as the key-sequence
- (vip-set-unread-command-events (subseq keyseq 1))
- (setq last-input-event event
- keyseq (if vip-emacs-p
- "\e"
- (vector (character-to-event ?\e)))))
- ((and vip-xemacs-p
- (key-press-event-p first-key)
- (equal '(meta) key-mod))
- (vip-set-unread-command-events
- (vconcat (vector
- (character-to-event (event-key first-key)))
- (subseq keyseq 1)))
- (setq last-input-event event
- keyseq (vector (character-to-event ?\e))))
- ((eventp first-key)
- (setq last-command-event first-key))
- ))
- ) ; end progn
-
- ;; this is escape event with nothing after it
- ;; put in unread-command-event and then re-read
- (vip-set-unread-command-events event)
- (setq keyseq
- (funcall (ad-get-orig-definition 'read-key-sequence) nil))
- ))
- ;; not an escape event
- (setq keyseq (vector event)))
- keyseq))
-
-
-
-(defadvice read-key-sequence (around vip-read-keyseq-ad activate)
- "Harness to work for Viper. This advice is harmless---don't worry!"
- (let (inhibit-quit event keyseq)
- (setq keyseq ad-do-it)
- (setq event (if vip-xemacs-p
- (elt keyseq 0) ; XEmacs returns vector of events
- (elt (listify-key-sequence keyseq) 0)))
- (if (vip-ESC-event-p event)
- (let (unread-command-events)
- (vip-set-unread-command-events keyseq)
- (if (vip-fast-keysequence-p)
- (let ((vip-vi-global-user-minor-mode nil)
- (vip-vi-local-user-minor-mode nil)
- (vip-replace-minor-mode nil) ; actually unnecessary
- (vip-insert-global-user-minor-mode nil)
- (vip-insert-local-user-minor-mode nil))
- (setq keyseq ad-do-it))
- (setq keyseq ad-do-it))))
- keyseq))
-
-(defadvice describe-key (before vip-read-keyseq-ad protect activate)
- "Force to read key via `read-key-sequence'."
- (interactive (list (vip-events-to-keys
- (read-key-sequence "Describe key: ")))))
-
-(defadvice describe-key-briefly (before vip-read-keyseq-ad protect activate)
- "Force to read key via `read-key-sequence'."
- (interactive (list (vip-events-to-keys
- (read-key-sequence "Describe key briefly: ")))))
-
-;; Listen to ESC key.
-;; If a sequence of keys starting with ESC is issued with very short delays,
-;; interpret these keys in Emacs mode, so ESC won't be interpreted as a Vi key.
-(defun vip-intercept-ESC-key ()
- "Function that implements ESC key in Viper emulation of Vi."
- (interactive)
- (let ((cmd (or (key-binding (vip-envelop-ESC-key))
- '(lambda () (interactive) (error "")))))
-
- ;; call the actual function to execute ESC (if no other symbols followed)
- ;; or the key bound to the ESC sequence (if the sequence was issued
- ;; with very short delay between characters.
- (if (eq cmd 'vip-intercept-ESC-key)
- (setq cmd
- (cond ((eq vip-current-state 'vi-state)
- 'vip-ESC)
- ((eq vip-current-state 'insert-state)
- 'vip-exit-insert-state)
- ((eq vip-current-state 'replace-state)
- 'vip-replace-state-exit-cmd)
- (t 'vip-change-state-to-vi)
- )))
- (call-interactively cmd)))
-
-
-
-;; prefix argument for Vi mode
-
-;; In Vi mode, prefix argument is a dotted pair (NUM . COM) where NUM
-;; represents the numeric value of the prefix argument and COM represents
-;; command prefix such as "c", "d", "m" and "y".
-
-;; Get value part of prefix-argument ARG.
-(defsubst vip-p-val (arg)
- (cond ((null arg) 1)
- ((consp arg)
- (if (or (null (car arg)) (equal (car arg) '(nil)))
- 1 (car arg)))
- (t arg)))
-
-;; Get raw value part of prefix-argument ARG.
-(defsubst vip-P-val (arg)
- (cond ((consp arg) (car arg))
- (t arg)))
-
-;; Get com part of prefix-argument ARG.
-(defsubst vip-getcom (arg)
- (cond ((null arg) nil)
- ((consp arg) (cdr arg))
- (t nil)))
-
-;; Get com part of prefix-argument ARG and modify it.
-(defun vip-getCom (arg)
- (let ((com (vip-getcom arg)))
- (cond ((equal com ?c) ?C)
- ((equal com ?d) ?D)
- ((equal com ?y) ?Y)
- (t com))))
-
-
-;; Compute numeric prefix arg value.
-;; Invoked by EVENT. COM is the command part obtained so far.
-(defun vip-prefix-arg-value (event com)
- (let (value func)
- ;; read while number
- (while (and (vip-characterp event) (>= event ?0) (<= event ?9))
- (setq value (+ (* (if (vip-characterp value) value 0) 10) (- event ?0)))
- (setq event (vip-read-event-convert-to-char)))
-
- (setq prefix-arg value)
- (if com (setq prefix-arg (cons prefix-arg com)))
- (while (eq event ?U)
- (vip-describe-arg prefix-arg)
- (setq event (vip-read-event-convert-to-char)))
-
- (if (or com (and (not (eq vip-current-state 'vi-state))
- ;; make sure it is a Vi command
- (vip-characterp event) (vip-vi-command-p event)
- ))
- ;; If appears to be one of the vi commands,
- ;; then execute it with funcall and clear prefix-arg in order to not
- ;; confuse subsequent commands
- (progn
- ;; last-command-char is the char we want emacs to think was typed
- ;; last. If com is not nil, the vip-digit-argument command was called
- ;; from within vip-prefix-arg command, such as `d', `w', etc., i.e.,
- ;; the user typed, say, d2. In this case, `com' would be `d', `w',
- ;; etc.
- ;; If vip-digit-argument was invoked by vip-escape-to-vi (which is
- ;; indicated by the fact that the current state is not vi-state,
- ;; then `event' represents the vi command to be executed (e.g., `d',
- ;; `w', etc. Again, last-command-char must make emacs believe that
- ;; this is the command we typed.
- (setq last-command-char (or com event))
- (setq func (vip-exec-form-in-vi
- (` (key-binding (char-to-string (, event))))))
- (funcall func prefix-arg)
- (setq prefix-arg nil))
- ;; some other command -- let emacs do it in its own way
- (vip-set-unread-command-events event))
- ))
-
-
-;; Vi operator as prefix argument."
-(defun vip-prefix-arg-com (char value com)
- (let ((cont t)
- cmd-info mv-or-digit-cmd)
- (while (and cont
- (memq char
- (list ?c ?d ?y ?! ?< ?> ?= ?# ?r ?R ?\"
- vip-buffer-search-char)))
- (if com
- ;; this means that we already have a command character, so we
- ;; construct a com list and exit while. however, if char is "
- ;; it is an error.
- (progn
- ;; new com is (CHAR . OLDCOM)
- (if (memq char '(?# ?\")) (error ""))
- (setq com (cons char com))
- (setq cont nil))
- ;; If com is nil we set com as char, and read more. Again, if char
- ;; is ", we read the name of register and store it in vip-use-register.
- ;; if char is !, =, or #, a complete com is formed so we exit the
- ;; while loop.
- (cond ((memq char '(?! ?=))
- (setq com char)
- (setq char (read-char))
- (setq cont nil))
- ((= char ?#)
- ;; read a char and encode it as com
- (setq com (+ 128 (read-char)))
- (setq char (read-char)))
- ((= char ?\")
- (let ((reg (read-char)))
- (if (vip-valid-register reg)
- (setq vip-use-register reg)
- (error ""))
- (setq char (read-char))))
- (t
- (setq com char)
- (setq char (vip-read-char-exclusive))))))
-
- (if (atom com)
- ;; `com' is a single char, so we construct the command argument
- ;; and if `char' is `?', we describe the arg; otherwise
- ;; we prepare the command that will be executed at the end.
- (progn
- (setq cmd-info (cons value com))
- (while (= char ?U)
- (vip-describe-arg cmd-info)
- (setq char (read-char)))
- ;; `char' is a movement command or a digit arg command---so we execute
- ;; it at the very end
- (setq mv-or-digit-cmd
- (vip-exec-form-in-vi
- (` (key-binding (char-to-string (, char)))))))
-
- ;; as com is non-nil, this means that we have a command to execute
- (if (memq (car com) '(?r ?R))
- ;; execute apropriate region command.
- (let ((char (car com)) (com (cdr com)))
- (setq prefix-arg (cons value com))
- (if (= char ?r) (vip-region prefix-arg)
- (vip-Region prefix-arg))
- ;; reset prefix-arg
- (setq prefix-arg nil))
- ;; otherwise, reset prefix arg and call appropriate command
- (setq value (if (null value) 1 value))
- (setq prefix-arg nil)
- (cond ((equal com '(?c . ?c)) (vip-line (cons value ?C)))
- ((equal com '(?d . ?d)) (vip-line (cons value ?D)))
- ((equal com '(?d . ?y)) (vip-yank-defun))
- ((equal com '(?y . ?y)) (vip-line (cons value ?Y)))
- ((equal com '(?< . ?<)) (vip-line (cons value ?<)))
- ((equal com '(?> . ?>)) (vip-line (cons value ?>)))
- ((equal com '(?! . ?!)) (vip-line (cons value ?!)))
- ((equal com '(?= . ?=)) (vip-line (cons value ?=)))
- (t (error "")))))
-
- (if mv-or-digit-cmd
- (progn
- (setq last-command-char char)
- (funcall mv-or-digit-cmd cmd-info)))
- ))
-
-(defun vip-describe-arg (arg)
- (let (val com)
- (setq val (vip-P-val arg)
- com (vip-getcom arg))
- (if (null val)
- (if (null com)
- (message "Value is nil, and command is nil")
- (message "Value is nil, and command is `%c'" com))
- (if (null com)
- (message "Value is `%d', and command is nil" val)
- (message "Value is `%d', and command is `%c'" val com)))))
-
-(defun vip-digit-argument (arg)
- "Begin numeric argument for the next command."
- (interactive "P")
- (vip-leave-region-active)
- (vip-prefix-arg-value
- last-command-char (if (consp arg) (cdr arg) nil)))
-
-(defun vip-command-argument (arg)
- "Accept a motion command as an argument."
- (interactive "P")
- (condition-case nil
- (vip-prefix-arg-com
- last-command-char
- (cond ((null arg) nil)
- ((consp arg) (car arg))
- ((integerp arg) arg)
- (t (error vip-InvalidCommandArgument)))
- (cond ((null arg) nil)
- ((consp arg) (cdr arg))
- ((integerp arg) nil)
- (t (error vip-InvalidCommandArgument))))
- (quit (setq vip-use-register nil)
- (signal 'quit nil)))
- (vip-deactivate-mark))
-
-
-;; repeat last destructive command
-
-;; Append region to text in register REG.
-;; START and END are buffer positions indicating what to append.
-(defsubst vip-append-to-register (reg start end)
- (set-register reg (concat (if (stringp (get-register reg))
- (get-register reg) "")
- (buffer-substring start end))))
-
-;; Saves last inserted text for possible use by vip-repeat command.
-(defun vip-save-last-insertion (beg end)
- (setq vip-last-insertion (buffer-substring beg end))
- (or (< (length vip-d-com) 5)
- (setcar (nthcdr 4 vip-d-com) vip-last-insertion))
- (or (null vip-command-ring)
- (ring-empty-p vip-command-ring)
- (progn
- (setcar (nthcdr 4 (vip-current-ring-item vip-command-ring))
- vip-last-insertion)
- ;; del most recent elt, if identical to the second most-recent
- (vip-cleanup-ring vip-command-ring)))
- )
-
-(defsubst vip-yank-last-insertion ()
- "Inserts the text saved by the previous vip-save-last-insertion command."
- (condition-case nil
- (insert vip-last-insertion)
- (error nil)))
-
-
-;; define functions to be executed
-
-;; invoked by the `C' command
-(defun vip-exec-change (m-com com)
- ;; handle C cmd at the eol and at eob.
- (if (or (and (eolp) (= vip-com-point (point)))
- (= vip-com-point (point-max)))
- (progn
- (insert " ")(backward-char 1)))
- (if (= vip-com-point (point))
- (vip-forward-char-carefully))
- (if (= com ?c)
- (vip-change vip-com-point (point))
- (vip-change-subr vip-com-point (point))))
-
-;; this is invoked by vip-substitute-line
-(defun vip-exec-Change (m-com com)
- (save-excursion
- (set-mark vip-com-point)
- (vip-enlarge-region (mark t) (point))
- (if vip-use-register
- (progn
- (cond ((vip-valid-register vip-use-register '(letter digit))
- ;;(vip-valid-register vip-use-register '(letter)
- (copy-to-register
- vip-use-register (mark t) (point) nil))
- ((vip-valid-register vip-use-register '(Letter))
- (vip-append-to-register
- (downcase vip-use-register) (mark t) (point)))
- (t (setq vip-use-register nil)
- (error vip-InvalidRegister vip-use-register)))
- (setq vip-use-register nil)))
- (delete-region (mark t) (point)))
- (open-line 1)
- (if (= com ?C) (vip-change-mode-to-insert) (vip-yank-last-insertion)))
-
-(defun vip-exec-delete (m-com com)
- (if vip-use-register
- (progn
- (cond ((vip-valid-register vip-use-register '(letter digit))
- ;;(vip-valid-register vip-use-register '(letter))
- (copy-to-register
- vip-use-register vip-com-point (point) nil))
- ((vip-valid-register vip-use-register '(Letter))
- (vip-append-to-register
- (downcase vip-use-register) vip-com-point (point)))
- (t (setq vip-use-register nil)
- (error vip-InvalidRegister vip-use-register)))
- (setq vip-use-register nil)))
- (setq last-command
- (if (eq last-command 'd-command) 'kill-region nil))
- (kill-region vip-com-point (point))
- (setq this-command 'd-command)
- (if vip-ex-style-motion
- (if (and (eolp) (not (bolp))) (backward-char 1))))
-
-(defun vip-exec-Delete (m-com com)
- (save-excursion
- (set-mark vip-com-point)
- (vip-enlarge-region (mark t) (point))
- (if vip-use-register
- (progn
- (cond ((vip-valid-register vip-use-register '(letter digit))
- ;;(vip-valid-register vip-use-register '(letter))
- (copy-to-register
- vip-use-register (mark t) (point) nil))
- ((vip-valid-register vip-use-register '(Letter))
- (vip-append-to-register
- (downcase vip-use-register) (mark t) (point)))
- (t (setq vip-use-register nil)
- (error vip-InvalidRegister vip-use-register)))
- (setq vip-use-register nil)))
- (setq last-command
- (if (eq last-command 'D-command) 'kill-region nil))
- (kill-region (mark t) (point))
- (if (eq m-com 'vip-line) (setq this-command 'D-command)))
- (back-to-indentation))
-
-(defun vip-exec-yank (m-com com)
- (if vip-use-register
- (progn
- (cond ((vip-valid-register vip-use-register '(letter digit))
- ;; (vip-valid-register vip-use-register '(letter))
- (copy-to-register
- vip-use-register vip-com-point (point) nil))
- ((vip-valid-register vip-use-register '(Letter))
- (vip-append-to-register
- (downcase vip-use-register) vip-com-point (point)))
- (t (setq vip-use-register nil)
- (error vip-InvalidRegister vip-use-register)))
- (setq vip-use-register nil)))
- (setq last-command nil)
- (copy-region-as-kill vip-com-point (point))
- (goto-char vip-com-point))
-
-(defun vip-exec-Yank (m-com com)
- (save-excursion
- (set-mark vip-com-point)
- (vip-enlarge-region (mark t) (point))
- (if vip-use-register
- (progn
- (cond ((vip-valid-register vip-use-register '(letter digit))
- (copy-to-register
- vip-use-register (mark t) (point) nil))
- ((vip-valid-register vip-use-register '(Letter))
- (vip-append-to-register
- (downcase vip-use-register) (mark t) (point)))
- (t (setq vip-use-register nil)
- (error vip-InvalidRegister vip-use-register)))
- (setq vip-use-register nil)))
- (setq last-command nil)
- (copy-region-as-kill (mark t) (point)))
- (vip-deactivate-mark)
- (goto-char vip-com-point))
-
-(defun vip-exec-bang (m-com com)
- (save-excursion
- (set-mark vip-com-point)
- (vip-enlarge-region (mark t) (point))
- (shell-command-on-region
- (mark t) (point)
- (if (= com ?!)
- (setq vip-last-shell-com
- (vip-read-string-with-history
- "!"
- nil
- 'vip-shell-history
- (car vip-shell-history)
- ))
- vip-last-shell-com)
- t)))
-
-(defun vip-exec-equals (m-com com)
- (save-excursion
- (set-mark vip-com-point)
- (vip-enlarge-region (mark t) (point))
- (if (> (mark t) (point)) (exchange-point-and-mark))
- (indent-region (mark t) (point) nil)))
-
-(defun vip-exec-shift (m-com com)
- (save-excursion
- (set-mark vip-com-point)
- (vip-enlarge-region (mark t) (point))
- (if (> (mark t) (point)) (exchange-point-and-mark))
- (indent-rigidly (mark t) (point)
- (if (= com ?>)
- vip-shift-width
- (- vip-shift-width))))
- ;; return point to where it was before shift
- (goto-char vip-com-point))
-
-;; this is needed because some commands fake com by setting it to ?r, which
-;; denotes repeated insert command.
-(defsubst vip-exec-dummy (m-com com)
- nil)
-
-(defun vip-exec-buffer-search (m-com com)
- (setq vip-s-string (buffer-substring (point) vip-com-point))
- (setq vip-s-forward t)
- (setq vip-search-history (cons vip-s-string vip-search-history))
- (vip-search vip-s-string vip-s-forward 1))
-
-(defvar vip-exec-array (make-vector 128 nil))
-
-;; Using a dispatch array allows adding functions like buffer search
-;; without affecting other functions. Buffer search can now be bound
-;; to any character.
-
-(aset vip-exec-array ?c 'vip-exec-change)
-(aset vip-exec-array ?C 'vip-exec-Change)
-(aset vip-exec-array ?d 'vip-exec-delete)
-(aset vip-exec-array ?D 'vip-exec-Delete)
-(aset vip-exec-array ?y 'vip-exec-yank)
-(aset vip-exec-array ?Y 'vip-exec-Yank)
-(aset vip-exec-array ?r 'vip-exec-dummy)
-(aset vip-exec-array ?! 'vip-exec-bang)
-(aset vip-exec-array ?< 'vip-exec-shift)
-(aset vip-exec-array ?> 'vip-exec-shift)
-(aset vip-exec-array ?= 'vip-exec-equals)
-
-
-
-;; This function is called by various movement commands to execute a
-;; destructive command on the region specified by the movement command. For
-;; instance, if the user types cw, then the command vip-forward-word will
-;; call vip-execute-com to execute vip-exec-change, which eventually will
-;; call vip-change to invoke the replace mode on the region.
-;;
-;; The list (M-COM VAL COM REG INSETED-TEXT COMMAND-KEYS) is set to
-;; vip-d-com for later use by vip-repeat.
-(defun vip-execute-com (m-com val com)
- (let ((reg vip-use-register))
- ;; this is the special command `#'
- (if (> com 128)
- (vip-special-prefix-com (- com 128))
- (let ((fn (aref vip-exec-array (if (< com 0) (- com) com))))
- (if (null fn)
- (error "%c: %s" com vip-InvalidViCommand)
- (funcall fn m-com com))))
- (if (vip-dotable-command-p com)
- (vip-set-destructive-command
- (list m-com val
- (if (memq com (list ?c ?C ?!)) (- com) com)
- reg nil nil)))
- ))
-
-
-(defun vip-repeat (arg)
- "Re-execute last destructive command.
-Use the info in vip-d-com, which has the form
-\(com val ch reg inserted-text command-keys\),
-where `com' is the command to be re-executed, `val' is the
-argument to `com', `ch' is a flag for repeat, and `reg' is optional;
-if it exists, it is the name of the register for `com'.
-If the prefix argument, ARG, is non-nil, it is used instead of `val'."
- (interactive "P")
- (let ((save-point (point)) ; save point before repeating prev cmd
- ;; Pass along that we are repeating a destructive command
- ;; This tells vip-set-destructive-command not to update
- ;; vip-command-ring
- (vip-intermediate-command 'vip-repeat))
- (if (eq last-command 'vip-undo)
- ;; if the last command was vip-undo, then undo-more
- (vip-undo-more)
- ;; otherwise execute the command stored in vip-d-com. if arg is non-nil
- ;; its prefix value is used as new prefix value for the command.
- (let ((m-com (car vip-d-com))
- (val (vip-P-val arg))
- (com (nth 2 vip-d-com))
- (reg (nth 3 vip-d-com)))
- (if (null val) (setq val (nth 1 vip-d-com)))
- (if (null m-com) (error "No previous command to repeat."))
- (setq vip-use-register reg)
- (if (nth 4 vip-d-com) ; text inserted by command
- (setq vip-last-insertion (nth 4 vip-d-com)
- vip-d-char (nth 4 vip-d-com)))
- (funcall m-com (cons val com))
- (if (and vip-keep-point-on-repeat (< save-point (point)))
- (goto-char save-point)) ; go back to before repeat.
- (if (and (eolp) (not (bolp)))
- (backward-char 1))
- ))
- (if vip-undo-needs-adjustment (vip-adjust-undo)) ; take care of undo
- ;; If the prev cmd was rotating the command ring, this means that `.' has
- ;; just executed a command from that ring. So, push it on the ring again.
- ;; If we are just executing previous command , then don't push vip-d-com
- ;; because vip-d-com is not fully constructed in this case (its keys and
- ;; the inserted text may be nil). Besides, in this case, the command
- ;; executed by `.' is already on the ring.
- (if (eq last-command 'vip-display-current-destructive-command)
- (vip-push-onto-ring vip-d-com 'vip-command-ring))
- (vip-deactivate-mark)
- ))
-
-(defun vip-repeat-from-history ()
- "Repeat a destructive command from history.
-Doesn't change vip-command-ring in any way, so `.' will work as before
-executing this command.
-This command is supposed to be bound to a two-character Vi macro where
-the second character is a digit 0 to 9. The digit indicates which
-history command to execute. `<char>0' is equivalent to `.', `<char>1'
-invokes the command before that, etc."
- (interactive)
- (let* ((vip-intermediate-command 'repeating-display-destructive-command)
- (idx (cond (vip-this-kbd-macro
- (string-to-number
- (symbol-name (elt vip-this-kbd-macro 1))))
- (t 0)))
- (num idx)
- (vip-d-com vip-d-com))
-
- (or (and (numberp num) (<= 0 num) (<= num 9))
- (progn
- (setq idx 0
- num 0)
- (message
- "`vip-repeat-from-history' must be invoked as a Vi macro bound to `<key><digit>'")))
- (while (< 0 num)
- (setq vip-d-com (vip-special-ring-rotate1 vip-command-ring -1))
- (setq num (1- num)))
- (vip-repeat nil)
- (while (> idx num)
- (vip-special-ring-rotate1 vip-command-ring 1)
- (setq num (1+ num)))
- ))
-
-
-;; This command is invoked interactively by the key sequence #<char>
-(defun vip-special-prefix-com (char)
- (cond ((= char ?c)
- (downcase-region (min vip-com-point (point))
- (max vip-com-point (point))))
- ((= char ?C)
- (upcase-region (min vip-com-point (point))
- (max vip-com-point (point))))
- ((= char ?g)
- (push-mark vip-com-point t)
- (vip-global-execute))
- ((= char ?q)
- (push-mark vip-com-point t)
- (vip-quote-region))
- ((= char ?s) (funcall vip-spell-function vip-com-point (point)))
- (t (error "#%c: %s" char vip-InvalidViCommand))))
-
-
-;; undoing
-
-(defun vip-undo ()
- "Undo previous change."
- (interactive)
- (message "undo!")
- (let ((modified (buffer-modified-p))
- (before-undo-pt (point-marker))
- (after-change-functions after-change-functions)
- undo-beg-posn undo-end-posn)
-
- ;; no need to remove this hook, since this var has scope inside a let.
- (add-hook 'after-change-functions
- '(lambda (beg end len)
- (setq undo-beg-posn beg
- undo-end-posn (or end beg))))
-
- (undo-start)
- (undo-more 2)
- (setq undo-beg-posn (or undo-beg-posn before-undo-pt)
- undo-end-posn (or undo-end-posn undo-beg-posn))
-
- (goto-char undo-beg-posn)
- (sit-for 0)
- (if (and vip-keep-point-on-undo
- (pos-visible-in-window-p before-undo-pt))
- (progn
- (push-mark (point-marker) t)
- (vip-sit-for-short 300)
- (goto-char undo-end-posn)
- (vip-sit-for-short 300)
- (if (and (> (abs (- undo-beg-posn before-undo-pt)) 1)
- (> (abs (- undo-end-posn before-undo-pt)) 1))
- (goto-char before-undo-pt)
- (goto-char undo-beg-posn)))
- (push-mark before-undo-pt t))
- (if (and (eolp) (not (bolp))) (backward-char 1))
- (if (not modified) (set-buffer-modified-p t)))
- (setq this-command 'vip-undo))
-
-;; Continue undoing previous changes.
-(defun vip-undo-more ()
- (message "undo more!")
- (condition-case nil
- (undo-more 1)
- (error (beep)
- (message "No further undo information in this buffer")))
- (if (and (eolp) (not (bolp))) (backward-char 1))
- (setq this-command 'vip-undo))
-
-;; The following two functions are used to set up undo properly.
-;; In VI, unlike Emacs, if you open a line, say, and add a bunch of lines,
-;; they are undone all at once.
-(defun vip-adjust-undo ()
- (let ((inhibit-quit t)
- tmp tmp2)
- (setq vip-undo-needs-adjustment nil)
- (if (listp buffer-undo-list)
- (if (setq tmp (memq vip-buffer-undo-list-mark buffer-undo-list))
- (progn
- (setq tmp2 (cdr tmp)) ; the part after mark
-
- ;; cut tail from buffer-undo-list temporarily by direct
- ;; manipulation with pointers in buffer-undo-list
- (setcdr tmp nil)
-
- (setq buffer-undo-list (delq nil buffer-undo-list))
- (setq buffer-undo-list
- (delq vip-buffer-undo-list-mark buffer-undo-list))
- ;; restore tail of buffer-undo-list
- (setq buffer-undo-list (nconc buffer-undo-list tmp2)))
- (setq buffer-undo-list (delq nil buffer-undo-list))))))
-
-
-(defun vip-set-complex-command-for-undo ()
- (if (listp buffer-undo-list)
- (if (not vip-undo-needs-adjustment)
- (let ((inhibit-quit t))
- (setq buffer-undo-list
- (cons vip-buffer-undo-list-mark buffer-undo-list))
- (setq vip-undo-needs-adjustment t)))))
-
-
-
-
-(defun vip-display-current-destructive-command ()
- (let ((text (nth 4 vip-d-com))
- (keys (nth 5 vip-d-com))
- (max-text-len 30))
-
- (setq this-command 'vip-display-current-destructive-command)
-
- (message " `.' runs %s%s"
- (concat "`" (vip-array-to-string keys) "'")
- (vip-abbreviate-string text max-text-len
- " inserting `" "'" " ......."))
- ))
-
-
-;; don't change vip-d-com if it was vip-repeat command invoked with `.'
-;; or in some other way (non-interactively).
-(defun vip-set-destructive-command (list)
- (or (eq vip-intermediate-command 'vip-repeat)
- (progn
- (setq vip-d-com list)
- (setcar (nthcdr 5 vip-d-com)
- (vip-array-to-string (this-command-keys)))
- (vip-push-onto-ring vip-d-com 'vip-command-ring))))
-
-(defun vip-prev-destructive-command (next)
- "Find previous destructive command in the history of destructive commands.
-With prefix argument, find next destructive command."
- (interactive "P")
- (let (cmd vip-intermediate-command)
- (if (eq last-command 'vip-display-current-destructive-command)
- ;; repeated search through command history
- (setq vip-intermediate-command 'repeating-display-destructive-command)
- ;; first search through command history--set temp ring
- (setq vip-temp-command-ring (copy-list vip-command-ring)))
- (setq cmd (if next
- (vip-special-ring-rotate1 vip-temp-command-ring 1)
- (vip-special-ring-rotate1 vip-temp-command-ring -1)))
- (if (null cmd)
- ()
- (setq vip-d-com cmd))
- (vip-display-current-destructive-command)))
-
-(defun vip-next-destructive-command ()
- "Find next destructive command in the history of destructive commands."
- (interactive)
- (vip-prev-destructive-command 'next))
-
-(defun vip-insert-prev-from-insertion-ring (arg)
- "Cycle through insertion ring in the direction of older insertions.
-Undoes previous insertion and inserts new.
-With prefix argument, cycles in the direction of newer elements.
-In minibuffer, this command executes whatever the invocation key is bound
-to in the global map, instead of cycling through the insertion ring."
- (interactive "P")
- (let (vip-intermediate-command)
- (if (eq last-command 'vip-insert-from-insertion-ring)
- (progn ; repeated search through insertion history
- (setq vip-intermediate-command 'repeating-insertion-from-ring)
- (if (eq vip-current-state 'replace-state)
- (undo 1)
- (if vip-last-inserted-string-from-insertion-ring
- (backward-delete-char
- (length vip-last-inserted-string-from-insertion-ring))))
- )
- ;;first search through insertion history
- (setq vip-temp-insertion-ring (copy-list vip-insertion-ring)))
- (setq this-command 'vip-insert-from-insertion-ring)
- ;; so that things will be undone properly
- (setq buffer-undo-list (cons nil buffer-undo-list))
- (setq vip-last-inserted-string-from-insertion-ring
- (vip-special-ring-rotate1 vip-temp-insertion-ring (if arg 1 -1)))
-
- ;; this change of vip-intermediate-command must come after
- ;; vip-special-ring-rotate1, so that the ring will rotate, but before the
- ;; insertion.
- (setq vip-intermediate-command nil)
- (if vip-last-inserted-string-from-insertion-ring
- (insert vip-last-inserted-string-from-insertion-ring))
- ))
-
-(defun vip-insert-next-from-insertion-ring ()
- "Cycle through insertion ring in the direction of older insertions.
-Undo previous insertion and inserts new."
- (interactive)
- (vip-insert-prev-from-insertion-ring 'next))
-
-
-;; some region utilities
-
-;; If at the last line of buffer, add \\n before eob, if newline is missing.
-(defun vip-add-newline-at-eob-if-necessary ()
- (save-excursion
- (end-of-line)
- ;; make sure all lines end with newline, unless in the minibuffer or
- ;; when requested otherwise (require-final-newline is nil)
- (if (and (eobp)
- (not (bolp))
- require-final-newline
- (not (vip-is-in-minibuffer))
- (not buffer-read-only))
- (insert "\n"))))
-
-(defun vip-yank-defun ()
- (mark-defun)
- (copy-region-as-kill (point) (mark t)))
-
-;; Enlarge region between BEG and END.
-(defun vip-enlarge-region (beg end)
- (or beg (setq beg end)) ; if beg is nil, set to end
- (or end (setq end beg)) ; if end is nil, set to beg
-
- (if (< beg end)
- (progn (goto-char beg) (set-mark end))
- (goto-char end)
- (set-mark beg))
- (beginning-of-line)
- (exchange-point-and-mark)
- (if (or (not (eobp)) (not (bolp))) (forward-line 1))
- (if (not (eobp)) (beginning-of-line))
- (if (> beg end) (exchange-point-and-mark)))
-
-
-;; Quote region by each line with a user supplied string.
-(defun vip-quote-region ()
- (setq vip-quote-string
- (vip-read-string-with-history
- "Quote string: "
- nil
- 'vip-quote-region-history
- vip-quote-string))
- (vip-enlarge-region (point) (mark t))
- (if (> (point) (mark t)) (exchange-point-and-mark))
- (insert vip-quote-string)
- (beginning-of-line)
- (forward-line 1)
- (while (and (< (point) (mark t)) (bolp))
- (insert vip-quote-string)
- (beginning-of-line)
- (forward-line 1)))
-
-;; Tells whether BEG is on the same line as END.
-;; If one of the args is nil, it'll return nil.
-(defun vip-same-line (beg end)
- (let ((selective-display nil)
- (incr 0)
- temp)
- (if (and beg end (> beg end))
- (setq temp beg
- beg end
- end temp))
- (if (and beg end)
- (cond ((or (> beg (point-max)) (> end (point-max))) ; out of range
- nil)
- (t
- ;; This 'if' is needed because Emacs treats the next empty line
- ;; as part of the previous line.
- (if (= (vip-line-pos 'start) end)
- (setq incr 1))
- (<= (+ incr (count-lines beg end)) 1))))
- ))
-
-
-;; Check if the string ends with a newline.
-(defun vip-end-with-a-newline-p (string)
- (or (string= string "")
- (= (vip-seq-last-elt string) ?\n)))
-
-(defun vip-tmp-insert-at-eob (msg)
- (let ((savemax (point-max)))
- (goto-char savemax)
- (insert msg)
- (sit-for 2)
- (goto-char savemax) (delete-region (point) (point-max))
- ))
-
-
-
-;;; Minibuffer business
-
-(defsubst vip-set-minibuffer-style ()
- (add-hook 'minibuffer-setup-hook 'vip-minibuffer-setup-sentinel))
-
-
-(defun vip-minibuffer-setup-sentinel ()
- (let ((hook (if vip-vi-style-in-minibuffer
- 'vip-change-state-to-insert
- 'vip-change-state-to-emacs)))
- (funcall hook)
- ))
-
-;; Interpret last event in the local map
-(defun vip-exit-minibuffer ()
- (interactive)
- (let (command)
- (setq command (local-key-binding (char-to-string last-command-char)))
- (if command
- (command-execute command)
- (exit-minibuffer))))
-
-
-(defun vip-set-search-face ()
- (if (vip-has-face-support-p)
- (defvar vip-search-face
- (progn
- (make-face 'vip-search-face)
- (vip-hide-face 'vip-search-face)
- (or (face-differs-from-default-p 'vip-search-face)
- ;; face wasn't set in .vip or .Xdefaults
- (if (vip-can-use-colors "Black" "khaki")
- (progn
- (set-face-background 'vip-search-face "khaki")
- (set-face-foreground 'vip-search-face "Black"))
- (set-face-underline-p 'vip-search-face t)
- (vip-set-face-pixmap 'vip-search-face vip-search-face-pixmap)))
- 'vip-search-face)
- "*Face used to flash out the search pattern.")
- ))
-
-
-(defun vip-set-minibuffer-faces ()
- (if (not (vip-has-face-support-p))
- ()
- (defvar vip-minibuffer-emacs-face
- (progn
- (make-face 'vip-minibuffer-emacs-face)
- (vip-hide-face 'vip-minibuffer-emacs-face)
- (or (face-differs-from-default-p 'vip-minibuffer-emacs-face)
- ;; face wasn't set in .vip or .Xdefaults
- (if vip-vi-style-in-minibuffer
- ;; emacs state is an exception in the minibuffer
- (if (vip-can-use-colors "darkseagreen2" "Black")
- (progn
- (set-face-background
- 'vip-minibuffer-emacs-face "darkseagreen2")
- (set-face-foreground
- 'vip-minibuffer-emacs-face "Black"))
- (copy-face 'modeline 'vip-minibuffer-emacs-face))
- ;; emacs state is the main state in the minibuffer
- (if (vip-can-use-colors "Black" "pink")
- (progn
- (set-face-background 'vip-minibuffer-emacs-face "pink")
- (set-face-foreground
- 'vip-minibuffer-emacs-face "Black"))
- (copy-face 'italic 'vip-minibuffer-emacs-face))
- ))
- 'vip-minibuffer-emacs-face)
- "Face used in the Minibuffer when it is in Emacs state.")
-
- (defvar vip-minibuffer-insert-face
- (progn
- (make-face 'vip-minibuffer-insert-face)
- (vip-hide-face 'vip-minibuffer-insert-face)
- (or (face-differs-from-default-p 'vip-minibuffer-insert-face)
- (if vip-vi-style-in-minibuffer
- (if (vip-can-use-colors "Black" "pink")
- (progn
- (set-face-background 'vip-minibuffer-insert-face "pink")
- (set-face-foreground
- 'vip-minibuffer-insert-face "Black"))
- (copy-face 'italic 'vip-minibuffer-insert-face))
- ;; If Insert state is an exception
- (if (vip-can-use-colors "darkseagreen2" "Black")
- (progn
- (set-face-background
- 'vip-minibuffer-insert-face "darkseagreen2")
- (set-face-foreground
- 'vip-minibuffer-insert-face "Black"))
- (copy-face 'modeline 'vip-minibuffer-insert-face))
- (vip-italicize-face 'vip-minibuffer-insert-face)))
- 'vip-minibuffer-insert-face)
- "Face used in the Minibuffer when it is in Insert state.")
-
- (defvar vip-minibuffer-vi-face
- (progn
- (make-face 'vip-minibuffer-vi-face)
- (vip-hide-face 'vip-minibuffer-vi-face)
- (or (face-differs-from-default-p 'vip-minibuffer-vi-face)
- (if vip-vi-style-in-minibuffer
- (if (vip-can-use-colors "Black" "grey")
- (progn
- (set-face-background 'vip-minibuffer-vi-face "grey")
- (set-face-foreground 'vip-minibuffer-vi-face "Black"))
- (copy-face 'bold 'vip-minibuffer-vi-face))
- (copy-face 'bold 'vip-minibuffer-vi-face)
- (invert-face 'vip-minibuffer-vi-face)))
- 'vip-minibuffer-vi-face)
- "Face used in the Minibuffer when it is in Vi state.")
-
- ;; the current face used in the minibuffer
- (vip-deflocalvar vip-minibuffer-current-face vip-minibuffer-emacs-face "")
- ))
-
-
-
-;;; Reading string with history
-
-(defun vip-read-string-with-history (prompt &optional initial
- history-var default keymap)
- ;; Read string, prompting with PROMPT and inserting the INITIAL
- ;; value. Uses HISTORY-VAR. DEFAULT is the default value to accept if the
- ;; input is an empty string. Use KEYMAP, if given, or the
- ;; minibuffer-local-map.
- ;; Default value is displayed until the user types something in the
- ;; minibuffer.
- (let ((minibuffer-setup-hook
- '(lambda ()
- (if (stringp initial)
- (progn
- ;; don't wait if we have unread events or in kbd macro
- (or unread-command-events
- executing-kbd-macro
- (sit-for 840))
- (erase-buffer)
- (insert initial)))
- (vip-minibuffer-setup-sentinel)))
- (val "")
- (padding "")
- temp-msg)
-
- (setq keymap (or keymap minibuffer-local-map)
- initial (or initial "")
- temp-msg (if default
- (format "(default: %s) " default)
- ""))
-
- (setq vip-incomplete-ex-cmd nil)
- (setq val (read-from-minibuffer prompt
- (concat temp-msg initial val padding)
- keymap nil history-var))
- (setq minibuffer-setup-hook nil
- padding (vip-array-to-string (this-command-keys))
- temp-msg "")
- ;; the following tries to be smart about what to put in history
- (if (not (string= val (car (eval history-var))))
- (set history-var (cons val (eval history-var))))
- (if (or (string= (nth 0 (eval history-var)) (nth 1 (eval history-var)))
- (string= (nth 0 (eval history-var)) ""))
- (set history-var (cdr (eval history-var))))
- ;; If the user enters nothing but the prev cmd wasn't vip-ex,
- ;; vip-command-argument, or `! shell-command', this probably means
- ;; that the user typed something then erased. Return "" in this case, not
- ;; the default---the default is too confusing in this case.
- (cond ((and (string= val "")
- (not (string= prompt "!")) ; was a `! shell-command'
- (not (memq last-command
- '(vip-ex
- vip-command-argument
- t)
- )))
- "")
- ((string= val "") (or default ""))
- (t val))
- ))
-
-
-
-;; insertion commands
-
-;; Called when state changes from Insert Vi command mode.
-;; Repeats the insertion command if Insert state was entered with prefix
-;; argument > 1.
-(defun vip-repeat-insert-command ()
- (let ((i-com (car vip-d-com))
- (val (nth 1 vip-d-com))
- (char (nth 2 vip-d-com)))
- (if (and val (> val 1)) ; first check that val is non-nil
- (progn
- (setq vip-d-com (list i-com (1- val) ?r nil nil nil))
- (vip-repeat nil)
- (setq vip-d-com (list i-com val char nil nil nil))
- ))))
-
-(defun vip-insert (arg)
- "Insert before point."
- (interactive "P")
- (vip-set-complex-command-for-undo)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (vip-set-destructive-command (list 'vip-insert val ?r nil nil nil))
- (if com
- (vip-loop val (vip-yank-last-insertion))
- (vip-change-state-to-insert))))
-
-(defun vip-append (arg)
- "Append after point."
- (interactive "P")
- (vip-set-complex-command-for-undo)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (vip-set-destructive-command (list 'vip-append val ?r nil nil nil))
- (if (not (eolp)) (forward-char))
- (if (equal com ?r)
- (vip-loop val (vip-yank-last-insertion))
- (vip-change-state-to-insert))))
-
-(defun vip-Append (arg)
- "Append at end of line."
- (interactive "P")
- (vip-set-complex-command-for-undo)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (vip-set-destructive-command (list 'vip-Append val ?r nil nil nil))
- (end-of-line)
- (if (equal com ?r)
- (vip-loop val (vip-yank-last-insertion))
- (vip-change-state-to-insert))))
-
-(defun vip-Insert (arg)
- "Insert before first non-white."
- (interactive "P")
- (vip-set-complex-command-for-undo)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (vip-set-destructive-command (list 'vip-Insert val ?r nil nil nil))
- (back-to-indentation)
- (if (equal com ?r)
- (vip-loop val (vip-yank-last-insertion))
- (vip-change-state-to-insert))))
-
-(defun vip-open-line (arg)
- "Open line below."
- (interactive "P")
- (vip-set-complex-command-for-undo)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (vip-set-destructive-command (list 'vip-open-line val ?r nil nil nil))
- (let ((col (current-indentation)))
- (if (equal com ?r)
- (vip-loop val
- (progn
- (end-of-line)
- (newline 1)
- (if vip-auto-indent
- (progn
- (setq vip-cted t)
- (if vip-electric-mode
- (indent-according-to-mode)
- (indent-to col))
- ))
- (vip-yank-last-insertion)))
- (end-of-line)
- (newline 1)
- (if vip-auto-indent
- (progn
- (setq vip-cted t)
- (if vip-electric-mode
- (indent-according-to-mode)
- (indent-to col))))
- (vip-change-state-to-insert)))))
-
-(defun vip-Open-line (arg)
- "Open line above."
- (interactive "P")
- (vip-set-complex-command-for-undo)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (vip-set-destructive-command (list 'vip-Open-line val ?r nil nil nil))
- (let ((col (current-indentation)))
- (if (equal com ?r)
- (vip-loop val
- (progn
- (beginning-of-line)
- (open-line 1)
- (if vip-auto-indent
- (progn
- (setq vip-cted t)
- (if vip-electric-mode
- (indent-according-to-mode)
- (indent-to col))
- ))
- (vip-yank-last-insertion)))
- (beginning-of-line)
- (open-line 1)
- (if vip-auto-indent
- (progn
- (setq vip-cted t)
- (if vip-electric-mode
- (indent-according-to-mode)
- (indent-to col))
- ))
- (vip-change-state-to-insert)))))
-
-(defun vip-open-line-at-point (arg)
- "Open line at point."
- (interactive "P")
- (vip-set-complex-command-for-undo)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (vip-set-destructive-command
- (list 'vip-open-line-at-point val ?r nil nil nil))
- (if (equal com ?r)
- (vip-loop val
- (progn
- (open-line 1)
- (vip-yank-last-insertion)))
- (open-line 1)
- (vip-change-state-to-insert))))
-
-(defun vip-substitute (arg)
- "Substitute characters."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (push-mark nil t)
- (forward-char val)
- (if (equal com ?r)
- (vip-change-subr (mark t) (point))
- (vip-change (mark t) (point)))
- (vip-set-destructive-command (list 'vip-substitute val ?r nil nil nil))
- ))
-
-(defun vip-substitute-line (arg)
- "Substitute lines."
- (interactive "p")
- (vip-set-complex-command-for-undo)
- (vip-line (cons arg ?C)))
-
-;; Prepare for replace
-(defun vip-start-replace ()
- (setq vip-began-as-replace t
- vip-sitting-in-replace t
- vip-replace-chars-to-delete 0
- vip-replace-chars-deleted 0)
- (vip-add-hook 'vip-after-change-functions 'vip-replace-mode-spy-after t)
- (vip-add-hook 'vip-before-change-functions 'vip-replace-mode-spy-before t)
- ;; this will get added repeatedly, but no harm
- (add-hook 'after-change-functions 'vip-after-change-sentinel t)
- (add-hook 'before-change-functions 'vip-before-change-sentinel t)
- (vip-move-marker-locally 'vip-last-posn-in-replace-region
- (vip-replace-start))
- (vip-add-hook
- 'vip-post-command-hooks 'vip-replace-state-post-command-sentinel t)
- (vip-add-hook
- 'vip-pre-command-hooks 'vip-replace-state-pre-command-sentinel t)
- )
-
-
-;; checks how many chars were deleted by the last change
-(defun vip-replace-mode-spy-before (beg end)
- (setq vip-replace-chars-deleted
- (- end beg
- (max 0 (- end (vip-replace-end)))
- (max 0 (- (vip-replace-start) beg))
- )))
-
-;; Invoked as an after-change-function to set up parameters of the last change
-(defun vip-replace-mode-spy-after (beg end length)
- (if (memq vip-intermediate-command '(repeating-insertion-from-ring))
- (progn
- (setq vip-replace-chars-to-delete 0)
- (vip-move-marker-locally
- 'vip-last-posn-in-replace-region (point)))
-
- (let (beg-col end-col real-end chars-to-delete)
- (setq real-end (min end (vip-replace-end)))
- (save-excursion
- (goto-char beg)
- (setq beg-col (current-column))
- (goto-char real-end)
- (setq end-col (current-column)))
-
- ;; If beg of change is outside the replacement region, then don't
- ;; delete anything in the repl region (set chars-to-delete to 0).
- ;;
- ;; This works fine except that we have to take special care of
- ;; dabbrev-expand. The problem stems from new-dabbrev.el, which
- ;; sometimes simply shifts the repl region rightwards, without
- ;; deleting an equal amount of characters.
- ;;
- ;; The reason why new-dabbrev.el causes this are this:
- ;; if one dinamically completes a partial word that starts before the
- ;; replacement region (but ends inside) then new-dabbrev.el first
- ;; moves cursor backwards, to the beginning of the word to be
- ;; completed (say, pt A). Then it inserts the
- ;; completed word and then deletes the old, incomplete part.
- ;; Since the complete word is inserted at position before the repl
- ;; region, the next If-statement would have set chars-to-delete to 0
- ;; unless we check for the current command, which must be
- ;; dabbrev-expand.
- ;;
- ;; In fact, it might be also useful to have overlays for insert
- ;; regions as well, since this will let us capture the situation when
- ;; dabbrev-expand goes back past the insertion point to find the
- ;; beginning of the word to be expanded.
- (if (or (and (<= (vip-replace-start) beg)
- (<= beg (vip-replace-end)))
- (and (= length 0) (eq this-command 'dabbrev-expand)))
- (setq chars-to-delete
- (max (- end-col beg-col) (- real-end beg) 0))
- (setq chars-to-delete 0))
-
- ;; if beg = last change position, it means that we are within the
- ;; same command that does multiple changes. Moreover, it means
- ;; that we have two subsequent changes (insert/delete) that
- ;; complement each other.
- (if (= beg (marker-position vip-last-posn-in-replace-region))
- (setq vip-replace-chars-to-delete
- (- (+ chars-to-delete vip-replace-chars-to-delete)
- vip-replace-chars-deleted))
- (setq vip-replace-chars-to-delete chars-to-delete))
-
- (vip-move-marker-locally
- 'vip-last-posn-in-replace-region
- (max (if (> end (vip-replace-end)) (vip-replace-start) end)
- (or (marker-position vip-last-posn-in-replace-region)
- (vip-replace-start))
- ))
-
- (setq vip-replace-chars-to-delete
- (max 0 (min vip-replace-chars-to-delete
- (- (vip-replace-end)
- vip-last-posn-in-replace-region))))
- )))
-
-
-;; Delete stuff between posn and the end of vip-replace-overlay-marker, if
-;; posn is within the overlay.
-(defun vip-finish-change (posn)
- (vip-remove-hook 'vip-after-change-functions 'vip-replace-mode-spy-after)
- (vip-remove-hook 'vip-before-change-functions 'vip-replace-mode-spy-before)
- (vip-remove-hook 'vip-post-command-hooks
- 'vip-replace-state-post-command-sentinel)
- (vip-remove-hook
- 'vip-pre-command-hooks 'vip-replace-state-pre-command-sentinel)
- (vip-restore-cursor-color-after-replace)
- (setq vip-sitting-in-replace nil) ; just in case we'll need to know it
- (save-excursion
- (if (and
- vip-replace-overlay
- (>= posn (vip-replace-start))
- (< posn (vip-replace-end)))
- (delete-region posn (vip-replace-end)))
- )
-
- (if (eq vip-current-state 'replace-state)
- (vip-downgrade-to-insert))
- ;; replace mode ended => nullify vip-last-posn-in-replace-region
- (vip-move-marker-locally 'vip-last-posn-in-replace-region nil)
- (vip-hide-replace-overlay)
- (vip-refresh-mode-line)
- (vip-put-string-on-kill-ring vip-last-replace-region)
- )
-
-;; Make STRING be the first element of the kill ring.
-(defun vip-put-string-on-kill-ring (string)
- (setq kill-ring (cons string kill-ring))
- (if (> (length kill-ring) kill-ring-max)
- (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))
- (setq kill-ring-yank-pointer kill-ring))
-
-(defun vip-finish-R-mode ()
- (vip-remove-hook 'vip-post-command-hooks 'vip-R-state-post-command-sentinel)
- (vip-remove-hook
- 'vip-pre-command-hooks 'vip-replace-state-pre-command-sentinel)
- (vip-downgrade-to-insert))
-
-(defun vip-start-R-mode ()
- ;; Leave arg as 1, not t: XEmacs insists that it must be a pos number
- (overwrite-mode 1)
- (vip-add-hook
- 'vip-post-command-hooks 'vip-R-state-post-command-sentinel t)
- (vip-add-hook
- 'vip-pre-command-hooks 'vip-replace-state-pre-command-sentinel t)
- )
-
-
-
-(defun vip-replace-state-exit-cmd ()
- "Binding for keys that cause Replace state to switch to Vi or to Insert.
-These keys are ESC, RET, and LineFeed"
- (interactive)
- (if overwrite-mode ;; If you are in replace mode invoked via 'R'
- (vip-finish-R-mode)
- (vip-finish-change vip-last-posn-in-replace-region))
- (let (com)
- (if (eq this-command 'vip-intercept-ESC-key)
- (setq com 'vip-exit-insert-state)
- (vip-set-unread-command-events last-input-char)
- (setq com (key-binding (read-key-sequence nil))))
-
- (condition-case conds
- (command-execute com)
- (error
- (vip-message-conditions conds)))
- )
- (vip-hide-replace-overlay))
-
-
-;; This is the function bound to 'R'---unlimited replace.
-;; Similar to Emacs's own overwrite-mode.
-(defun vip-overwrite (arg)
- "Begin overwrite mode."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)) (len))
- (vip-set-destructive-command (list 'vip-overwrite val ?r nil nil nil))
- (if com
- (progn
- ;; Viper saves inserted text in vip-last-insertion
- (setq len (length vip-last-insertion))
- (delete-char len)
- (vip-loop val (vip-yank-last-insertion)))
- (setq last-command 'vip-overwrite)
- (vip-set-complex-command-for-undo)
- (vip-set-replace-overlay (point) (vip-line-pos 'end))
- (vip-change-state-to-replace)
- )))
-
-
-;; line commands
-
-(defun vip-line (arg)
- (let ((val (car arg))
- (com (cdr arg)))
- (vip-move-marker-locally 'vip-com-point (point))
- (if (not (eobp))
- (vip-next-line-carefully (1- val)))
- ;; this ensures that dd, cc, D, yy will do the right thing on the last
- ;; line of buffer when this line has no \n.
- (vip-add-newline-at-eob-if-necessary)
- (vip-execute-com 'vip-line val com))
- (if (and (eobp) (not (bobp))) (forward-line -1))
- )
-
-(defun vip-yank-line (arg)
- "Yank ARG lines (in Vi's sense)."
- (interactive "P")
- (let ((val (vip-p-val arg)))
- (vip-line (cons val ?Y))))
-
-
-;; region commands
-
-(defun vip-region (arg)
- "Execute command on a region."
- (interactive "P")
- (let ((val (vip-P-val arg))
- (com (vip-getcom arg)))
- (vip-move-marker-locally 'vip-com-point (point))
- (exchange-point-and-mark)
- (vip-execute-com 'vip-region val com)))
-
-(defun vip-Region (arg)
- "Execute command on a Region."
- (interactive "P")
- (let ((val (vip-P-val arg))
- (com (vip-getCom arg)))
- (vip-move-marker-locally 'vip-com-point (point))
- (exchange-point-and-mark)
- (vip-execute-com 'vip-Region val com)))
-
-(defun vip-replace-char (arg)
- "Replace the following ARG chars by the character read."
- (interactive "P")
- (if (and (eolp) (bolp)) (error "No character to replace here"))
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (vip-replace-char-subr com val)
- (if (and (eolp) (not (bolp))) (forward-char 1))
- (vip-set-destructive-command
- (list 'vip-replace-char val ?r nil vip-d-char nil))
- ))
-
-(defun vip-replace-char-subr (com arg)
- (let ((take-care-of-iso-accents
- (and (boundp 'iso-accents-mode) vip-automatic-iso-accents))
- char)
- (setq char (if (equal com ?r)
- vip-d-char
- (read-char)))
- (if (and take-care-of-iso-accents (memq char '(?' ?\" ?^ ?~)))
- ;; get European characters
- (progn
- (iso-accents-mode 1)
- (vip-set-unread-command-events char)
- (setq char (aref (read-key-sequence nil) 0))
- (iso-accents-mode -1)))
- (delete-char arg t)
- (setq vip-d-char char)
- (vip-loop (if (> arg 0) arg (- arg))
- (if (eq char ?\C-m) (insert "\n") (insert char)))
- (backward-char arg)))
-
-
-;; basic cursor movement. j, k, l, h commands.
-
-(defun vip-forward-char (arg)
- "Move point right ARG characters (left if ARG negative).
-On reaching end of line, stop and signal error."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (if vip-ex-style-motion
- (progn
- ;; the boundary condition check gets weird here because
- ;; forward-char may be the parameter of a delete, and 'dl' works
- ;; just like 'x' for the last char on a line, so we have to allow
- ;; the forward motion before the 'vip-execute-com', but, of
- ;; course, 'dl' doesn't work on an empty line, so we have to
- ;; catch that condition before 'vip-execute-com'
- (if (and (eolp) (bolp)) (error "") (forward-char val))
- (if com (vip-execute-com 'vip-forward-char val com))
- (if (eolp) (progn (backward-char 1) (error ""))))
- (forward-char val)
- (if com (vip-execute-com 'vip-forward-char val com)))))
-
-(defun vip-backward-char (arg)
- "Move point left ARG characters (right if ARG negative).
-On reaching beginning of line, stop and signal error."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (if vip-ex-style-motion
- (progn
- (if (bolp) (error "") (backward-char val))
- (if com (vip-execute-com 'vip-backward-char val com)))
- (backward-char val)
- (if com (vip-execute-com 'vip-backward-char val com)))))
-
-;; Like forward-char, but doesn't move at end of buffer.
-(defun vip-forward-char-carefully (&optional arg)
- (setq arg (or arg 1))
- (if (>= (point-max) (+ (point) arg))
- (forward-char arg)
- (goto-char (point-max))))
-
-;; Like backward-char, but doesn't move at end of buffer.
-(defun vip-backward-char-carefully (&optional arg)
- (setq arg (or arg 1))
- (if (<= (point-min) (- (point) arg))
- (backward-char arg)
- (goto-char (point-min))))
-
-(defun vip-next-line-carefully (arg)
- (condition-case nil
- (next-line arg)
- (error nil)))
-
-
-
-;;; Word command
-
-;; Words are formed from alpha's and nonalphas - <sp>,\t\n are separators
-;; for word movement. When executed with a destructive command, \n is
-;; usually left untouched for the last word.
-;; Viper uses syntax table to determine what is a word and what is a
-;; separator. However, \n is always a separator. Also, if vip-syntax-preference
-;; is 'vi, then `_' is part of the word.
-
-;; skip only one \n
-(defun vip-skip-separators (forward)
- (if forward
- (progn
- (vip-skip-all-separators-forward 'within-line)
- (if (looking-at "\n")
- (progn
- (forward-char)
- (vip-skip-all-separators-forward 'within-line))))
- (vip-skip-all-separators-backward 'within-line)
- (backward-char)
- (if (looking-at "\n")
- (vip-skip-all-separators-backward 'within-line)
- (forward-char))))
-
-(defun vip-forward-word-kernel (val)
- (while (> val 0)
- (cond ((vip-looking-at-alpha)
- (vip-skip-alpha-forward "_")
- (vip-skip-separators t))
- ((vip-looking-at-separator)
- (vip-skip-separators t))
- ((not (vip-looking-at-alphasep))
- (vip-skip-nonalphasep-forward)
- (vip-skip-separators t)))
- (setq val (1- val))))
-
-;; first search backward for pat. Then skip chars backwards using aux-pat
-(defun vip-fwd-skip (pat aux-pat lim)
- (if (and (save-excursion
- (re-search-backward pat lim t))
- (= (point) (match-end 0)))
- (goto-char (match-beginning 0)))
- (skip-chars-backward aux-pat lim)
- (if (= (point) lim)
- (vip-forward-char-carefully))
- )
-
-
-(defun vip-forward-word (arg)
- "Forward word."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (vip-forward-word-kernel val)
- (if com (progn
- (cond ((memq com (list ?c (- ?c)))
- (vip-fwd-skip "\n[ \t]*" " \t" vip-com-point))
- ;; Yank words including the whitespace, but not newline
- ((memq com (list ?y (- ?y)))
- (vip-fwd-skip "\n[ \t]*" "" vip-com-point))
- ((vip-dotable-command-p com)
- (vip-fwd-skip "\n[ \t]*" "" vip-com-point)))
- (vip-execute-com 'vip-forward-word val com)))))
-
-
-(defun vip-forward-Word (arg)
- "Forward word delimited by white characters."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (vip-loop val
- (progn
- (vip-skip-nonseparators 'forward)
- (vip-skip-separators t)))
- (if com (progn
- (cond ((memq com (list ?c (- ?c)))
- (vip-fwd-skip "\n[ \t]*" " \t" vip-com-point))
- ;; Yank words including the whitespace, but not newline
- ((memq com (list ?y (- ?y)))
- (vip-fwd-skip "\n[ \t]*" "" vip-com-point))
- ((vip-dotable-command-p com)
- (vip-fwd-skip "\n[ \t]*" "" vip-com-point)))
- (vip-execute-com 'vip-forward-Word val com)))))
-
-
-;; this is a bit different from Vi, but Vi's end of word
-;; makes no sense whatsoever
-(defun vip-end-of-word-kernel ()
- (if (vip-end-of-word-p) (forward-char))
- (if (vip-looking-at-separator)
- (vip-skip-all-separators-forward))
-
- (cond ((vip-looking-at-alpha) (vip-skip-alpha-forward "_"))
- ((not (vip-looking-at-alphasep)) (vip-skip-nonalphasep-forward)))
- (vip-backward-char-carefully))
-
-(defun vip-end-of-word-p ()
- (or (eobp)
- (save-excursion
- (cond ((vip-looking-at-alpha)
- (forward-char)
- (not (vip-looking-at-alpha)))
- ((not (vip-looking-at-alphasep))
- (forward-char)
- (vip-looking-at-alphasep))))))
-
-
-(defun vip-end-of-word (arg &optional careful)
- "Move point to end of current word."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (vip-loop val (vip-end-of-word-kernel))
- (if com
- (progn
- (forward-char)
- (vip-execute-com 'vip-end-of-word val com)))))
-
-(defun vip-end-of-Word (arg)
- "Forward to end of word delimited by white character."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (vip-loop val
- (progn
- (vip-end-of-word-kernel)
- (vip-skip-nonseparators 'forward)
- (backward-char)))
- (if com
- (progn
- (forward-char)
- (vip-execute-com 'vip-end-of-Word val com)))))
-
-(defun vip-backward-word-kernel (val)
- (while (> val 0)
- (backward-char)
- (cond ((vip-looking-at-alpha)
- (vip-skip-alpha-backward "_"))
- ((vip-looking-at-separator)
- (forward-char)
- (vip-skip-separators nil)
- (backward-char)
- (cond ((vip-looking-at-alpha)
- (vip-skip-alpha-backward "_"))
- ((not (vip-looking-at-alphasep))
- (vip-skip-nonalphasep-backward))
- (t (forward-char))))
- ((not (vip-looking-at-alphasep))
- (vip-skip-nonalphasep-backward)))
- (setq val (1- val))))
-
-(defun vip-backward-word (arg)
- "Backward word."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com
- (let (i)
- (if (setq i (save-excursion (backward-char) (looking-at "\n")))
- (backward-char))
- (vip-move-marker-locally 'vip-com-point (point))
- (if i (forward-char))))
- (vip-backward-word-kernel val)
- (if com (vip-execute-com 'vip-backward-word val com))))
-
-(defun vip-backward-Word (arg)
- "Backward word delimited by white character."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com
- (let (i)
- (if (setq i (save-excursion (backward-char) (looking-at "\n")))
- (backward-char))
- (vip-move-marker-locally 'vip-com-point (point))
- (if i (forward-char))))
- (vip-loop val
- (progn
- (vip-skip-separators nil)
- (vip-skip-nonseparators 'backward)))
- (if com (vip-execute-com 'vip-backward-Word val com))))
-
-
-
-;; line commands
-
-(defun vip-beginning-of-line (arg)
- "Go to beginning of line."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (beginning-of-line val)
- (if com (vip-execute-com 'vip-beginning-of-line val com))))
-
-(defun vip-bol-and-skip-white (arg)
- "Beginning of line at first non-white character."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (forward-to-indentation (1- val))
- (if com (vip-execute-com 'vip-bol-and-skip-white val com))))
-
-(defun vip-goto-eol (arg)
- "Go to end of line."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (end-of-line val)
- (if com (vip-execute-com 'vip-goto-eol val com))
- (if vip-ex-style-motion
- (if (and (eolp) (not (bolp))
- ;; a fix for vip-change-to-eol
- (not (equal vip-current-state 'insert-state)))
- (backward-char 1)
- ))))
-
-
-(defun vip-goto-col (arg)
- "Go to ARG's column."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (save-excursion
- (end-of-line)
- (if (> val (1+ (current-column))) (error "")))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (beginning-of-line)
- (forward-char (1- val))
- (if com (vip-execute-com 'vip-goto-col val com))))
-
-
-(defun vip-next-line (arg)
- "Go to next line."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (next-line val)
- (if vip-ex-style-motion
- (if (and (eolp) (not (bolp))) (backward-char 1)))
- (setq this-command 'next-line)
- (if com (vip-execute-com 'vip-next-line val com))))
-
-(defun vip-next-line-at-bol (arg)
- "Next line at beginning of line."
- (interactive "P")
- (vip-leave-region-active)
- (save-excursion
- (end-of-line)
- (if (eobp) (error "Last line in buffer")))
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (forward-line val)
- (back-to-indentation)
- (if com (vip-execute-com 'vip-next-line-at-bol val com))))
-
-(defun vip-previous-line (arg)
- "Go to previous line."
- (interactive "P")
- (vip-leave-region-active)
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (previous-line val)
- (if vip-ex-style-motion
- (if (and (eolp) (not (bolp))) (backward-char 1)))
- (setq this-command 'previous-line)
- (if com (vip-execute-com 'vip-previous-line val com))))
-
-
-(defun vip-previous-line-at-bol (arg)
- "Previous line at beginning of line."
- (interactive "P")
- (vip-leave-region-active)
- (save-excursion
- (beginning-of-line)
- (if (bobp) (error "First line in buffer")))
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (forward-line (- val))
- (back-to-indentation)
- (if com (vip-execute-com 'vip-previous-line val com))))
-
-(defun vip-change-to-eol (arg)
- "Change to end of line."
- (interactive "P")
- (vip-goto-eol (cons arg ?c)))
-
-(defun vip-kill-line (arg)
- "Delete line."
- (interactive "P")
- (vip-goto-eol (cons arg ?d)))
-
-(defun vip-erase-line (arg)
- "Erase line."
- (interactive "P")
- (vip-beginning-of-line (cons arg ?d)))
-
-
-;;; Moving around
-
-(defun vip-goto-line (arg)
- "Go to ARG's line. Without ARG go to end of buffer."
- (interactive "P")
- (let ((val (vip-P-val arg))
- (com (vip-getCom arg)))
- (vip-move-marker-locally 'vip-com-point (point))
- (vip-deactivate-mark)
- (push-mark nil t)
- (if (null val)
- (goto-char (point-max))
- (goto-char (point-min))
- (forward-line (1- val)))
-
- ;; positioning is done twice: before and after command execution
- (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
- (back-to-indentation)
-
- (if com (vip-execute-com 'vip-goto-line val com))
-
- (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
- (back-to-indentation)
- ))
-
-;; Find ARG's occurrence of CHAR on the current line.
-;; If FORWARD then search is forward, otherwise backward. OFFSET is used to
-;; adjust point after search.
-(defun vip-find-char (arg char forward offset)
- (or (char-or-string-p char) (error ""))
- (let ((arg (if forward arg (- arg)))
- (cmd (if (eq vip-intermediate-command 'vip-repeat)
- (nth 5 vip-d-com)
- (vip-array-to-string (this-command-keys))))
- point)
- (save-excursion
- (save-restriction
- (if (> arg 0)
- (narrow-to-region
- ;; forward search begins here
- (if (eolp) (error "Command `%s': At end of line" cmd) (point))
- ;; forward search ends here
- (progn (end-of-line) (point)))
- (narrow-to-region
- ;; backward search begins from here
- (if (bolp)
- (error "Command `%s': At beginning of line" cmd) (point))
- ;; backward search ends here
- (progn (beginning-of-line) (point))))
- ;; if arg > 0, point is forwarded before search.
- (if (> arg 0) (goto-char (1+ (point-min)))
- (goto-char (point-max)))
- (if (let ((case-fold-search nil))
- (search-forward (char-to-string char) nil 0 arg))
- (setq point (point))
- (error "Command `%s': `%c' not found" cmd char))))
- (goto-char (+ point (if (> arg 0) (if offset -2 -1) (if offset 1 0))))))
-
-(defun vip-find-char-forward (arg)
- "Find char on the line.
-If called interactively read the char to find from the terminal, and if
-called from vip-repeat, the char last used is used. This behaviour is
-controlled by the sign of prefix numeric value."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg))
- (cmd-representation (nth 5 vip-d-com)))
- (if (> val 0)
- ;; this means that the function was called interactively
- (setq vip-f-char (read-char)
- vip-f-forward t
- vip-f-offset nil)
- ;; vip-repeat --- set vip-F-char from command-keys
- (setq vip-F-char (if (stringp cmd-representation)
- (vip-seq-last-elt cmd-representation)
- vip-F-char)
- vip-f-char vip-F-char)
- (setq val (- val)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (vip-find-char val (if (> (vip-p-val arg) 0) vip-f-char vip-F-char) t nil)
- (setq val (- val))
- (if com
- (progn
- (setq vip-F-char vip-f-char) ; set new vip-F-char
- (forward-char)
- (vip-execute-com 'vip-find-char-forward val com)))))
-
-(defun vip-goto-char-forward (arg)
- "Go up to char ARG forward on line."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg))
- (cmd-representation (nth 5 vip-d-com)))
- (if (> val 0)
- ;; this means that the function was called interactively
- (setq vip-f-char (read-char)
- vip-f-forward t
- vip-f-offset t)
- ;; vip-repeat --- set vip-F-char from command-keys
- (setq vip-F-char (if (stringp cmd-representation)
- (vip-seq-last-elt cmd-representation)
- vip-F-char)
- vip-f-char vip-F-char)
- (setq val (- val)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (vip-find-char val (if (> (vip-p-val arg) 0) vip-f-char vip-F-char) t t)
- (setq val (- val))
- (if com
- (progn
- (setq vip-F-char vip-f-char) ; set new vip-F-char
- (forward-char)
- (vip-execute-com 'vip-goto-char-forward val com)))))
-
-(defun vip-find-char-backward (arg)
- "Find char ARG on line backward."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg))
- (cmd-representation (nth 5 vip-d-com)))
- (if (> val 0)
- ;; this means that the function was called interactively
- (setq vip-f-char (read-char)
- vip-f-forward nil
- vip-f-offset nil)
- ;; vip-repeat --- set vip-F-char from command-keys
- (setq vip-F-char (if (stringp cmd-representation)
- (vip-seq-last-elt cmd-representation)
- vip-F-char)
- vip-f-char vip-F-char)
- (setq val (- val)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (vip-find-char
- val (if (> (vip-p-val arg) 0) vip-f-char vip-F-char) nil nil)
- (setq val (- val))
- (if com
- (progn
- (setq vip-F-char vip-f-char) ; set new vip-F-char
- (vip-execute-com 'vip-find-char-backward val com)))))
-
-(defun vip-goto-char-backward (arg)
- "Go up to char ARG backward on line."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg))
- (cmd-representation (nth 5 vip-d-com)))
- (if (> val 0)
- ;; this means that the function was called interactively
- (setq vip-f-char (read-char)
- vip-f-forward nil
- vip-f-offset t)
- ;; vip-repeat --- set vip-F-char from command-keys
- (setq vip-F-char (if (stringp cmd-representation)
- (vip-seq-last-elt cmd-representation)
- vip-F-char)
- vip-f-char vip-F-char)
- (setq val (- val)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (vip-find-char val (if (> (vip-p-val arg) 0) vip-f-char vip-F-char) nil t)
- (setq val (- val))
- (if com
- (progn
- (setq vip-F-char vip-f-char) ; set new vip-F-char
- (vip-execute-com 'vip-goto-char-backward val com)))))
-
-(defun vip-repeat-find (arg)
- "Repeat previous find command."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (vip-deactivate-mark)
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (vip-find-char val vip-f-char vip-f-forward vip-f-offset)
- (if com
- (progn
- (if vip-f-forward (forward-char))
- (vip-execute-com 'vip-repeat-find val com)))))
-
-(defun vip-repeat-find-opposite (arg)
- "Repeat previous find command in the opposite direction."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (vip-deactivate-mark)
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (vip-find-char val vip-f-char (not vip-f-forward) vip-f-offset)
- (if com
- (progn
- (if vip-f-forward (forward-char))
- (vip-execute-com 'vip-repeat-find-opposite val com)))))
-
-
-;; window scrolling etc.
-
-(defun vip-other-window (arg)
- "Switch to other window."
- (interactive "p")
- (other-window arg)
- (or (not (eq vip-current-state 'emacs-state))
- (string= (buffer-name (current-buffer)) " *Minibuf-1*")
- (vip-change-state-to-vi)))
-
-(defun vip-window-top (arg)
- "Go to home window line."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (push-mark nil t)
- (move-to-window-line (1- val))
-
- ;; positioning is done twice: before and after command execution
- (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
- (back-to-indentation)
-
- (if com (vip-execute-com 'vip-window-top val com))
-
- (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
- (back-to-indentation)
- ))
-
-(defun vip-window-middle (arg)
- "Go to middle window line."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg))
- lines)
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (push-mark nil t)
- (if (not (pos-visible-in-window-p (point-max)))
- (move-to-window-line (+ (/ (1- (window-height)) 2) (1- val)))
- (setq lines (count-lines (window-start) (point-max)))
- (move-to-window-line (+ (/ lines 2) (1- val))))
-
- ;; positioning is done twice: before and after command execution
- (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
- (back-to-indentation)
-
- (if com (vip-execute-com 'vip-window-middle val com))
-
- (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
- (back-to-indentation)
- ))
-
-(defun vip-window-bottom (arg)
- "Go to last window line."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (push-mark nil t)
- (move-to-window-line (- val))
-
- ;; positioning is done twice: before and after command execution
- (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
- (back-to-indentation)
-
- (if com (vip-execute-com 'vip-window-bottom val com))
-
- (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
- (back-to-indentation)
- ))
-
-(defun vip-line-to-top (arg)
- "Put current line on the home line."
- (interactive "p")
- (recenter (1- arg)))
-
-(defun vip-line-to-middle (arg)
- "Put current line on the middle line."
- (interactive "p")
- (recenter (+ (1- arg) (/ (1- (window-height)) 2))))
-
-(defun vip-line-to-bottom (arg)
- "Put current line on the last line."
- (interactive "p")
- (recenter (- (window-height) (1+ arg))))
-
-;; If vip-adjust-window-after-search is t, scroll up or down 1/4 of window
-;; height, depending on whether we are at the bottom or at the top of the
-;; window. This function is called by vip-search (which is called from
-;; vip-search-forward/backward/next)
-(defun vip-adjust-window ()
- (let ((win-height (if vip-emacs-p
- (1- (window-height)) ; adjust for modeline
- (window-displayed-height)))
- (pt (point))
- at-top-p at-bottom-p
- min-scroll direction)
- (save-excursion
- (move-to-window-line 0) ; top
- (setq at-top-p (<= (count-lines pt (point)) 2))
- (move-to-window-line -1) ; bottom
- (setq at-bottom-p (<= (count-lines pt (point)) 2))
- )
- (cond (at-top-p (setq min-scroll 1
- direction 1))
- (at-bottom-p (setq min-scroll 2
- direction -1)))
- (if (and vip-adjust-window-after-search min-scroll)
- (recenter
- (* (max min-scroll (/ win-height 7)) direction)))
- ))
-
-
-;; paren match
-;; must correct this to only match ( to ) etc. On the other hand
-;; it is good that paren match gets confused, because that way you
-;; catch _all_ imbalances.
-
-(defun vip-paren-match (arg)
- "Go to the matching parenthesis."
- (interactive "P")
- (vip-leave-region-active)
- (let ((com (vip-getcom arg))
- parse-sexp-ignore-comments anchor-point)
- (if (integerp arg)
- (if (or (> arg 99) (< arg 1))
- (error "Prefix must be between 1 and 99")
- (goto-char
- (if (> (point-max) 80000)
- (* (/ (point-max) 100) arg)
- (/ (* (point-max) arg) 100)))
- (back-to-indentation))
- (let (beg-lim end-lim)
- (if (and (eolp) (not (bolp))) (forward-char -1))
- (if (not (looking-at "[][(){}]"))
- (setq anchor-point (point)))
- (save-excursion
- (beginning-of-line)
- (setq beg-lim (point))
- (end-of-line)
- (setq end-lim (point)))
- (cond ((re-search-forward "[][(){}]" end-lim t)
- (backward-char) )
- ((re-search-backward "[][(){}]" beg-lim t))
- (t
- (error "No matching character on line"))))
- (cond ((looking-at "[\(\[{]")
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (forward-sexp 1)
- (if com
- (vip-execute-com 'vip-paren-match nil com)
- (backward-char)))
- (anchor-point
- (if com
- (progn
- (vip-move-marker-locally 'vip-com-point anchor-point)
- (forward-char 1)
- (vip-execute-com 'vip-paren-match nil com)
- )))
- ((looking-at "[])}]")
- (forward-char)
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (backward-sexp 1)
- (if com (vip-execute-com 'vip-paren-match nil com)))
- (t (error ""))))))
-
-
-;; sentence ,paragraph and heading
-
-(defun vip-forward-sentence (arg)
- "Forward sentence."
- (interactive "P")
- (push-mark nil t)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (forward-sentence val)
- (if com (vip-execute-com 'vip-forward-sentence nil com))))
-
-(defun vip-backward-sentence (arg)
- "Backward sentence."
- (interactive "P")
- (push-mark nil t)
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (backward-sentence val)
- (if com (vip-execute-com 'vip-backward-sentence nil com))))
-
-(defun vip-forward-paragraph (arg)
- "Forward paragraph."
- (interactive "P")
- (push-mark nil t)
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (forward-paragraph val)
- (if com
- (progn
- (backward-char 1)
- (vip-execute-com 'vip-forward-paragraph nil com)))))
-
-(defun vip-backward-paragraph (arg)
- "Backward paragraph."
- (interactive "P")
- (push-mark nil t)
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (backward-paragraph val)
- (if com
- (progn
- (forward-char 1)
- (vip-execute-com 'vip-backward-paragraph nil com)
- (backward-char 1)))))
-
-;; should be mode-specific etc.
-
-(defun vip-prev-heading (arg)
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (re-search-backward vip-heading-start nil t val)
- (goto-char (match-beginning 0))
- (if com (vip-execute-com 'vip-prev-heading nil com))))
-
-(defun vip-heading-end (arg)
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (re-search-forward vip-heading-end nil t val)
- (goto-char (match-beginning 0))
- (if com (vip-execute-com 'vip-heading-end nil com))))
-
-(defun vip-next-heading (arg)
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getCom arg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (end-of-line)
- (re-search-forward vip-heading-start nil t val)
- (goto-char (match-beginning 0))
- (if com (vip-execute-com 'vip-next-heading nil com))))
-
-
-;; scrolling
-
-(setq scroll-step 1)
-
-(defun vip-scroll-screen (arg)
- "Scroll to next screen."
- (interactive "p")
- (condition-case nil
- (if (> arg 0)
- (while (> arg 0)
- (scroll-up)
- (setq arg (1- arg)))
- (while (> 0 arg)
- (scroll-down)
- (setq arg (1+ arg))))
- (error (beep 1)
- (if (> arg 0)
- (progn
- (message "End of buffer")
- (goto-char (point-max)))
- (message "Beginning of buffer")
- (goto-char (point-min))))
- ))
-
-(defun vip-scroll-screen-back (arg)
- "Scroll to previous screen."
- (interactive "p")
- (vip-scroll-screen (- arg)))
-
-(defun vip-scroll-down (arg)
- "Pull down half screen."
- (interactive "P")
- (condition-case nil
- (if (null arg)
- (scroll-down (/ (window-height) 2))
- (scroll-down arg))
- (error (beep 1)
- (message "Beginning of buffer")
- (goto-char (point-min)))))
-
-(defun vip-scroll-down-one (arg)
- "Scroll up one line."
- (interactive "p")
- (scroll-down arg))
-
-(defun vip-scroll-up (arg)
- "Pull up half screen."
- (interactive "P")
- (condition-case nil
- (if (null arg)
- (scroll-up (/ (window-height) 2))
- (scroll-up arg))
- (error (beep 1)
- (message "End of buffer")
- (goto-char (point-max)))))
-
-(defun vip-scroll-up-one (arg)
- "Scroll down one line."
- (interactive "p")
- (scroll-up arg))
-
-
-;; searching
-
-(defun vip-if-string (prompt)
- (let ((s (vip-read-string-with-history
- prompt
- nil ; no initial
- 'vip-search-history
- (car vip-search-history))))
- (if (not (string= s ""))
- (setq vip-s-string s))))
-
-
-(defun vip-toggle-search-style (arg)
- "Toggle the value of vip-case-fold-search/vip-re-search.
-Without prefix argument, will ask which search style to toggle. With prefix
-arg 1,toggles vip-case-fold-search; with arg 2 toggles vip-re-search.
-
-Although this function is bound to \\[vip-toggle-search-style], the most
-convenient way to use it is to bind `//' to the macro
-`1 M-x vip-toggle-search-style' and `///' to
-`2 M-x vip-toggle-search-style'. In this way, hitting `//' quickly will
-toggle case-fold-search and hitting `/' three times witth toggle regexp
-search. Macros are more convenient in this case because they don't affect
-the Emacs binding of `/'."
- (interactive "P")
- (let (msg)
- (cond ((or (eq arg 1)
- (and (null arg)
- (y-or-n-p (format "Search style: '%s'. Want '%s'? "
- (if vip-case-fold-search
- "case-insensitive" "case-sensitive")
- (if vip-case-fold-search
- "case-sensitive"
- "case-insensitive")))))
- (setq vip-case-fold-search (null vip-case-fold-search))
- (if vip-case-fold-search
- (setq msg "Search becomes case-insensitive")
- (setq msg "Search becomes case-sensitive")))
- ((or (eq arg 2)
- (and (null arg)
- (y-or-n-p (format "Search style: '%s'. Want '%s'? "
- (if vip-re-search
- "regexp-search" "vanilla-search")
- (if vip-re-search
- "vanilla-search"
- "regexp-search")))))
- (setq vip-re-search (null vip-re-search))
- (if vip-re-search
- (setq msg "Search becomes regexp-style")
- (setq msg "Search becomes vanilla-style")))
- (t
- (setq msg "Search style remains unchanged")))
- (prin1 msg t)))
-
-(defun vip-set-vi-search-style-macros (unset)
- "Set the macros for toggling the search style in Viper's vi-state.
-The macro that toggles case sensitivity is bound to `//', and the one that
-toggles regexp search is bound to `///'.
-With a prefix argument, this function unsets the macros. "
- (interactive "P")
- (or noninteractive
- (if (not unset)
- (progn
- ;; toggle case sensitivity in search
- (vip-record-kbd-macro
- "//" 'vi-state
- [1 (meta x) v i p - t o g g l e - s e a r c h - s t y l e return]
- 't)
- ;; toggle regexp/vanila search
- (vip-record-kbd-macro
- "///" 'vi-state
- [2 (meta x) v i p - t o g g l e - s e a r c h - s t y l e return]
- 't)
- (if (interactive-p)
- (message
- "// and /// now toggle case-sensitivity and regexp search.")))
- (vip-unrecord-kbd-macro "//" 'vi-state)
- (sit-for 2)
- (vip-unrecord-kbd-macro "///" 'vi-state))))
-
-(defun vip-set-emacs-search-style-macros (unset &optional arg-majormode)
- "Set the macros for toggling the search style in Viper's emacs-state.
-The macro that toggles case sensitivity is bound to `//', and the one that
-toggles regexp search is bound to `///'.
-With a prefix argument, this function unsets the macros.
-If the optional prefix argument is non-nil and specifies a valid major mode,
-this sets the macros only in the macros in that major mode. Otherwise,
-the macros are set in the current major mode.
-\(When unsetting the macros, the second argument has no effect.\)"
- (interactive "P")
- (or noninteractive
- (if (not unset)
- (progn
- ;; toggle case sensitivity in search
- (vip-record-kbd-macro
- "//" 'emacs-state
- [1 (meta x) v i p - t o g g l e - s e a r c h - s t y l e return]
- (or arg-majormode major-mode))
- ;; toggle regexp/vanila search
- (vip-record-kbd-macro
- "///" 'emacs-state
- [2 (meta x) v i p - t o g g l e - s e a r c h - s t y l e return]
- (or arg-majormode major-mode))
- (if (interactive-p)
- (message
- "// and /// now toggle case-sensitivity and regexp search.")))
- (vip-unrecord-kbd-macro "//" 'emacs-state)
- (sit-for 2)
- (vip-unrecord-kbd-macro "///" 'emacs-state))))
-
-
-(defun vip-search-forward (arg)
- "Search a string forward.
-ARG is used to find the ARG's occurrence of the string.
-Null string will repeat previous search."
- (interactive "P")
- (let ((val (vip-P-val arg))
- (com (vip-getcom arg))
- (old-str vip-s-string))
- (setq vip-s-forward t)
- (vip-if-string "/")
- ;; this is not used at present, but may be used later
- (if (or (not (equal old-str vip-s-string))
- (not (markerp vip-local-search-start-marker))
- (not (marker-buffer vip-local-search-start-marker)))
- (setq vip-local-search-start-marker (point-marker)))
- (vip-search vip-s-string t val)
- (if com
- (progn
- (vip-move-marker-locally 'vip-com-point (mark t))
- (vip-execute-com 'vip-search-next val com)))))
-
-(defun vip-search-backward (arg)
- "Search a string backward.
-ARG is used to find the ARG's occurrence of the string.
-Null string will repeat previous search."
- (interactive "P")
- (let ((val (vip-P-val arg))
- (com (vip-getcom arg))
- (old-str vip-s-string))
- (setq vip-s-forward nil)
- (vip-if-string "?")
- ;; this is not used at present, but may be used later
- (if (or (not (equal old-str vip-s-string))
- (not (markerp vip-local-search-start-marker))
- (not (marker-buffer vip-local-search-start-marker)))
- (setq vip-local-search-start-marker (point-marker)))
- (vip-search vip-s-string nil val)
- (if com
- (progn
- (vip-move-marker-locally 'vip-com-point (mark t))
- (vip-execute-com 'vip-search-next val com)))))
-
-
-;; Search for COUNT's occurrence of STRING.
-;; Search is forward if FORWARD is non-nil, otherwise backward.
-;; INIT-POINT is the position where search is to start.
-;; Arguments:
-;; (STRING FORW COUNT &optional NO-OFFSET INIT-POINT LIMIT FAIL-IF-NOT-FOUND)
-(defun vip-search (string forward arg
- &optional no-offset init-point fail-if-not-found)
- (if (not (equal string ""))
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg))
- (offset (not no-offset))
- (case-fold-search vip-case-fold-search)
- (start-point (or init-point (point))))
- (vip-deactivate-mark)
- (if forward
- (condition-case nil
- (progn
- (if offset (vip-forward-char-carefully))
- (if vip-re-search
- (progn
- (re-search-forward string nil nil val)
- (re-search-backward string))
- (search-forward string nil nil val)
- (search-backward string))
- (if (not (equal start-point (point)))
- (push-mark start-point t)))
- (search-failed
- (if (and (not fail-if-not-found) vip-search-wrap-around-t)
- (progn
- (message "Search wrapped around BOTTOM of buffer")
- (goto-char (point-min))
- (vip-search string forward (cons 1 com) t start-point 'fail)
- ;; don't wait in macros
- (or executing-kbd-macro (sit-for 2))
- ;; delete the wrap-around message
- (message "")
- )
- (goto-char start-point)
- (error "`%s': %s not found"
- string
- (if vip-re-search "Pattern" "String"))
- )))
- ;; backward
- (condition-case nil
- (progn
- (if vip-re-search
- (re-search-backward string nil nil val)
- (search-backward string nil nil val))
- (if (not (equal start-point (point)))
- (push-mark start-point t)))
- (search-failed
- (if (and (not fail-if-not-found) vip-search-wrap-around-t)
- (progn
- (message "Search wrapped around TOP of buffer")
- (goto-char (point-max))
- (vip-search string forward (cons 1 com) t start-point 'fail)
- ;; don't wait in macros
- (or executing-kbd-macro (sit-for 2))
- ;; delete the wrap-around message
- (message "")
- )
- (goto-char start-point)
- (error "`%s': %s not found"
- string
- (if vip-re-search "Pattern" "String"))
- ))))
- ;; pull up or down if at top/bottom of window
- (vip-adjust-window)
- ;; highlight the result of search
- ;; don't wait and don't highlight in macros
- (or executing-kbd-macro
- (vip-flash-search-pattern))
- )))
-
-(defun vip-search-next (arg)
- "Repeat previous search."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if (null vip-s-string) (error vip-NoPrevSearch))
- (vip-search vip-s-string vip-s-forward arg)
- (if com
- (progn
- (vip-move-marker-locally 'vip-com-point (mark t))
- (vip-execute-com 'vip-search-next val com)))))
-
-(defun vip-search-Next (arg)
- "Repeat previous search in the reverse direction."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (com (vip-getcom arg)))
- (if (null vip-s-string) (error vip-NoPrevSearch))
- (vip-search vip-s-string (not vip-s-forward) arg)
- (if com
- (progn
- (vip-move-marker-locally 'vip-com-point (mark t))
- (vip-execute-com 'vip-search-Next val com)))))
-
-
-;; Search contents of buffer defined by one of Viper's motion commands.
-;; Repeatable via `n' and `N'.
-(defun vip-buffer-search-enable (&optional c)
- (cond (c (setq vip-buffer-search-char c))
- ((null vip-buffer-search-char)
- (setq vip-buffer-search-char ?g)))
- (define-key vip-vi-basic-map
- (char-to-string vip-buffer-search-char) 'vip-command-argument)
- (aset vip-exec-array vip-buffer-search-char 'vip-exec-buffer-search)
- (setq vip-prefix-commands (cons vip-buffer-search-char vip-prefix-commands)))
-
-;; This is a Viper wraper for isearch-forward.
-(defun vip-isearch-forward (arg)
- "Do incremental search forward."
- (interactive "P")
- ;; emacs bug workaround
- (if (listp arg) (setq arg (car arg)))
- (vip-exec-form-in-emacs (list 'isearch-forward arg)))
-
-;; This is a Viper wraper for isearch-backward."
-(defun vip-isearch-backward (arg)
- "Do incremental search backward."
- (interactive "P")
- ;; emacs bug workaround
- (if (listp arg) (setq arg (car arg)))
- (vip-exec-form-in-emacs (list 'isearch-backward arg)))
-
-
-;; visiting and killing files, buffers
-
-(defun vip-switch-to-buffer ()
- "Switch to buffer in the current window."
- (interactive)
- (let (buffer)
- (setq buffer
- (read-buffer
- (format "Switch to buffer in this window \(%s\): "
- (buffer-name (other-buffer (current-buffer))))))
- (switch-to-buffer buffer)
- ))
-
-(defun vip-switch-to-buffer-other-window ()
- "Switch to buffer in another window."
- (interactive)
- (let (buffer)
- (setq buffer
- (read-buffer
- (format "Switch to buffer in another window \(%s\): "
- (buffer-name (other-buffer (current-buffer))))))
- (switch-to-buffer-other-window buffer)
- ))
-
-(defun vip-kill-buffer ()
- "Kill a buffer."
- (interactive)
- (let (buffer buffer-name)
- (setq buffer-name
- (read-buffer
- (format "Kill buffer \(%s\): "
- (buffer-name (current-buffer)))))
- (setq buffer
- (if (null buffer-name)
- (current-buffer)
- (get-buffer buffer-name)))
- (if (null buffer) (error "`%s': No such buffer" buffer-name))
- (if (or (not (buffer-modified-p buffer))
- (y-or-n-p
- (format
- "Buffer `%s' is modified, are you sure you want to kill it? "
- buffer-name)))
- (kill-buffer buffer)
- (error "Buffer not killed"))))
-
-
-(defvar vip-smart-suffix-list '("" "tex" "c" "cc" "el" "p")
- "*List of suffixes that Viper automatically tries to append to filenames ending with a `.'.
-This is useful when you the current directory contains files with the same
-prefix and many different suffixes. Usually, only one of the suffixes
-represents an editable file. However, file completion will stop at the `.'
-The smart suffix feature lets you hit RET in such a case, and Viper will
-select the appropriate suffix.
-
-Suffixes are tried in the order given and the first suffix for which a
-corresponding file exists is selected. If no file exists for any of the
-suffixes, the user is asked to confirm.
-
-To turn this feature off, set this variable to nil.")
-
-;; Try to add suffix to files ending with a `.'
-;; Useful when the user hits RET on a non-completed file name.
-(defun vip-file-add-suffix ()
- (let ((count 0)
- (len (length vip-smart-suffix-list))
- (file (buffer-string))
- found key cmd suff)
- (goto-char (point-max))
- (if (and vip-smart-suffix-list (string-match "\\.$" file))
- (progn
- (while (and (not found) (< count len))
- (setq suff (nth count vip-smart-suffix-list)
- count (1+ count))
- (if (file-exists-p (format "%s%s" file suff))
- (progn
- (setq found t)
- (insert suff))))
-
- (if found
- ()
- (vip-tmp-insert-at-eob " [Please complete file name]")
- (unwind-protect
- (while (not (memq cmd '(exit-minibuffer vip-exit-minibuffer)))
- (setq cmd
- (key-binding (setq key (read-key-sequence nil))))
- (cond ((eq cmd 'self-insert-command)
- (if vip-xemacs-p
- (insert (events-to-keys key))
- (insert key)))
- ((memq cmd '(exit-minibuffer vip-exit-minibuffer))
- nil)
- (t (command-execute cmd)))
- )))
- ))
- ))
-
-
-;; Advice for use in find-file and read-file-name commands.
-(defadvice exit-minibuffer (before vip-exit-minibuffer-advice activate)
- "Run `vip-minibuffer-exit-hook' just before exiting the minibuffer."
- (run-hooks 'vip-minibuffer-exit-hook))
-
-(defadvice find-file (before vip-add-suffix-advice activate)
- "Use `read-file-name' for reading arguments."
- (interactive (list (read-file-name "Find file: "
- nil default-directory))))
-
-(defadvice find-file-other-window (before vip-add-suffix-advice activate)
- "Use `read-file-name' for reading arguments."
- (interactive (list (read-file-name "Find file in other window: "
- nil default-directory))))
-
-(defadvice find-file-other-frame (before vip-add-suffix-advice activate)
- "Use `read-file-name' for reading arguments."
- (interactive (list (read-file-name "Find file in other frame: "
- nil default-directory))))
-
-(defadvice read-file-name (around vip-suffix-advice activate)
- "Tell `exit-minibuffer' to run `vip-file-add-suffix' as a hook."
- (let ((vip-minibuffer-exit-hook 'vip-file-add-suffix))
- ad-do-it))
-
-
-
-;; yank and pop
-
-(defsubst vip-yank (text)
- "Yank TEXT silently. This works correctly with Emacs's yank-pop command."
- (insert text)
- (setq this-command 'yank))
-
-(defun vip-put-back (arg)
- "Put back after point/below line."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (text (if vip-use-register
- (cond ((vip-valid-register vip-use-register '(digit))
- (current-kill (- vip-use-register ?1) 'do-not-rotate))
- ((vip-valid-register vip-use-register)
- (get-register (downcase vip-use-register)))
- (t (error vip-InvalidRegister vip-use-register)))
- (current-kill 0))))
- (if (null text)
- (if vip-use-register
- (let ((reg vip-use-register))
- (setq vip-use-register nil)
- (error vip-EmptyRegister reg))
- (error "")))
- (setq vip-use-register nil)
- (if (vip-end-with-a-newline-p text)
- (progn
- (end-of-line)
- (if (eobp)
- (insert "\n")
- (forward-line 1))
- (beginning-of-line))
- (if (not (eolp)) (vip-forward-char-carefully)))
- (set-marker (vip-mark-marker) (point) (current-buffer))
- (vip-set-destructive-command
- (list 'vip-put-back val nil vip-use-register nil nil))
- (vip-loop val (vip-yank text)))
- ;; Vi puts cursor on the last char when the yanked text doesn't contain a
- ;; newline; it leaves the cursor at the beginning when the text contains
- ;; a newline
- (if (vip-same-line (point) (mark))
- (or (= (point) (mark)) (vip-backward-char-carefully))
- (exchange-point-and-mark)
- (if (bolp)
- (back-to-indentation)))
- (vip-deactivate-mark))
-
-(defun vip-Put-back (arg)
- "Put back at point/above line."
- (interactive "P")
- (let ((val (vip-p-val arg))
- (text (if vip-use-register
- (cond ((vip-valid-register vip-use-register '(digit))
- (current-kill (- vip-use-register ?1) 'do-not-rotate))
- ((vip-valid-register vip-use-register)
- (get-register (downcase vip-use-register)))
- (t (error vip-InvalidRegister vip-use-register)))
- (current-kill 0))))
- (if (null text)
- (if vip-use-register
- (let ((reg vip-use-register))
- (setq vip-use-register nil)
- (error vip-EmptyRegister reg))
- (error "")))
- (setq vip-use-register nil)
- (if (vip-end-with-a-newline-p text) (beginning-of-line))
- (vip-set-destructive-command
- (list 'vip-Put-back val nil vip-use-register nil nil))
- (set-marker (vip-mark-marker) (point) (current-buffer))
- (vip-loop val (vip-yank text)))
- ;; Vi puts cursor on the last char when the yanked text doesn't contain a
- ;; newline; it leaves the cursor at the beginning when the text contains
- ;; a newline
- (if (vip-same-line (point) (mark))
- (or (= (point) (mark)) (vip-backward-char-carefully))
- (exchange-point-and-mark)
- (if (bolp)
- (back-to-indentation)))
- (vip-deactivate-mark))
-
-
-;; Copy region to kill-ring.
-;; If BEG and END do not belong to the same buffer, copy empty region.
-(defun vip-copy-region-as-kill (beg end)
- (condition-case nil
- (copy-region-as-kill beg end)
- (error (copy-region-as-kill beg beg))))
-
-
-(defun vip-delete-char (arg)
- "Delete character."
- (interactive "P")
- (let ((val (vip-p-val arg)))
- (vip-set-destructive-command (list 'vip-delete-char val nil nil nil nil))
- (if (> val 1)
- (save-excursion
- (let ((here (point)))
- (end-of-line)
- (if (> val (- (point) here))
- (setq val (- (point) here))))))
- (if (and (eq val 0) (not vip-ex-style-motion)) (setq val 1))
- (if (and vip-ex-style-motion (eolp))
- (if (bolp) (error "") (setq val 0))) ; not bol---simply back 1 ch
- (if vip-use-register
- (progn
- (cond ((vip-valid-register vip-use-register '((Letter)))
- (vip-append-to-register
- (downcase vip-use-register) (point) (- (point) val)))
- ((vip-valid-register vip-use-register)
- (copy-to-register
- vip-use-register (point) (- (point) val) nil))
- (t (error vip-InvalidRegister vip-use-register)))
- (setq vip-use-register nil)))
- (if vip-ex-style-motion
- (progn
- (delete-char val t)
- (if (and (eolp) (not (bolp))) (backward-char 1)))
- (if (eolp)
- (delete-backward-char val t)
- (delete-char val t)))))
-
-(defun vip-delete-backward-char (arg)
- "Delete previous character. On reaching beginning of line, stop and beep."
- (interactive "P")
- (let ((val (vip-p-val arg)))
- (vip-set-destructive-command
- (list 'vip-delete-backward-char val nil nil nil nil))
- (if (> val 1)
- (save-excursion
- (let ((here (point)))
- (beginning-of-line)
- (if (> val (- here (point)))
- (setq val (- here (point)))))))
- (if vip-use-register
- (progn
- (cond ((vip-valid-register vip-use-register '(Letter))
- (vip-append-to-register
- (downcase vip-use-register) (point) (+ (point) val)))
- ((vip-valid-register vip-use-register)
- (copy-to-register
- vip-use-register (point) (+ (point) val) nil))
- (t (error vip-InvalidRegister vip-use-register)))
- (setq vip-use-register nil)))
- (if (bolp) (ding)
- (delete-backward-char val t))))
-
-(defun vip-del-backward-char-in-insert ()
- "Delete 1 char backwards while in insert mode."
- (interactive)
- (if (and vip-ex-style-editing-in-insert (bolp))
- (beep 1)
- (delete-backward-char 1 t)))
-
-(defun vip-del-backward-char-in-replace ()
- "Delete one character in replace mode.
-If `vip-delete-backwards-in-replace' is t, then DEL key actually deletes
-charecters. If it is nil, then the cursor just moves backwards, similarly
-to Vi. The variable `vip-ex-style-editing-in-insert', if t, doesn't let the
-cursor move past the beginning of line."
- (interactive)
- (cond (vip-delete-backwards-in-replace
- (cond ((not (bolp))
- (delete-backward-char 1 t))
- (vip-ex-style-editing-in-insert
- (beep 1))
- ((bobp)
- (beep 1))
- (t
- (delete-backward-char 1 t))))
- (vip-ex-style-editing-in-insert
- (if (bolp)
- (beep 1)
- (backward-char 1)))
- (t
- (backward-char 1))))
-
-
-
-;; join lines.
-
-(defun vip-join-lines (arg)
- "Join this line to next, if ARG is nil. Otherwise, join ARG lines."
- (interactive "*P")
- (let ((val (vip-P-val arg)))
- (vip-set-destructive-command (list 'vip-join-lines val nil nil nil nil))
- (vip-loop (if (null val) 1 (1- val))
- (progn
- (end-of-line)
- (if (not (eobp))
- (progn
- (forward-line 1)
- (delete-region (point) (1- (point)))
- (fixup-whitespace)))))))
-
-
-;; Replace state
-
-(defun vip-change (beg end)
- (if (markerp beg) (setq beg (marker-position beg)))
- (if (markerp end) (setq end (marker-position end)))
- ;; beg is sometimes (mark t), which may be nil
- (or beg (setq beg end))
-
- (vip-set-complex-command-for-undo)
- (if vip-use-register
- (progn
- (copy-to-register vip-use-register beg end nil)
- (setq vip-use-register nil)))
- (vip-set-replace-overlay beg end)
- (setq last-command nil) ; separate repl text from prev kills
-
- (if (= (vip-replace-start) (point-max))
- (error "End of buffer"))
-
- (setq vip-last-replace-region
- (buffer-substring (vip-replace-start)
- (vip-replace-end)))
-
- ;; protect against error while inserting "@" and other disasters
- ;; (e.g., read-only buff)
- (condition-case conds
- (if (vip-same-line (vip-replace-start)
- (vip-replace-end))
- (progn
- ;; tabs cause problems in replace, so untabify
- (goto-char (vip-replace-end))
- (insert-before-markers "@") ; put placeholder after the TAB
- (untabify (vip-replace-start) (point))
- ;; del @, don't put on kill ring
- (delete-backward-char 1)
-
- (vip-set-replace-overlay-glyphs
- vip-replace-region-start-delimiter
- vip-replace-region-end-delimiter)
- ;; this move takes care of the last posn in the overlay, which
- ;; has to be shifted because of insert. We can't simply insert
- ;; "$" before-markers because then overlay-start will shift the
- ;; beginning of the overlay in case we are replacing a single
- ;; character. This fixes the bug with `s' and `cl' commands.
- (vip-move-replace-overlay (vip-replace-start) (point))
- (goto-char (vip-replace-start))
- (vip-change-state-to-replace t))
- (kill-region (vip-replace-start)
- (vip-replace-end))
- (vip-hide-replace-overlay)
- (vip-change-state-to-insert))
- (error ;; make sure that the overlay doesn't stay.
- ;; go back to the original point
- (goto-char (vip-replace-start))
- (vip-hide-replace-overlay)
- (vip-message-conditions conds))))
-
-
-(defun vip-change-subr (beg end)
- ;; beg is sometimes (mark t), which may be nil
- (or beg (setq beg end))
-
- (if vip-use-register
- (progn
- (copy-to-register vip-use-register beg end nil)
- (setq vip-use-register nil)))
- (kill-region beg end)
- (setq this-command 'vip-change)
- (vip-yank-last-insertion))
-
-(defun vip-toggle-case (arg)
- "Toggle character case."
- (interactive "P")
- (let ((val (vip-p-val arg)) (c))
- (vip-set-destructive-command (list 'vip-toggle-case val nil nil nil nil))
- (while (> val 0)
- (setq c (following-char))
- (delete-char 1 nil)
- (if (eq c (upcase c))
- (insert-char (downcase c) 1)
- (insert-char (upcase c) 1))
- (if (eolp) (backward-char 1))
- (setq val (1- val)))))
-
-
-;; query replace
-
-(defun vip-query-replace ()
- "Query replace.
-If a null string is suplied as the string to be replaced,
-the query replace mode will toggle between string replace
-and regexp replace."
- (interactive)
- (let (str)
- (setq str (vip-read-string-with-history
- (if vip-re-query-replace "Query replace regexp: "
- "Query replace: ")
- nil ; no initial
- 'vip-replace1-history
- (car vip-replace1-history) ; default
- ))
- (if (string= str "")
- (progn
- (setq vip-re-query-replace (not vip-re-query-replace))
- (message "Query replace mode changed to %s"
- (if vip-re-query-replace "regexp replace"
- "string replace")))
- (if vip-re-query-replace
- (query-replace-regexp
- str
- (vip-read-string-with-history
- (format "Query replace regexp `%s' with: " str)
- nil ; no initial
- 'vip-replace1-history
- (car vip-replace1-history) ; default
- ))
- (query-replace
- str
- (vip-read-string-with-history
- (format "Query replace `%s' with: " str)
- nil ; no initial
- 'vip-replace1-history
- (car vip-replace1-history) ; default
- ))))))
-
-
-;; marking
-
-(defun vip-mark-beginning-of-buffer ()
- "Mark beginning of buffer."
- (interactive)
- (push-mark (point))
- (goto-char (point-min))
- (exchange-point-and-mark)
- (message "Mark set at the beginning of buffer"))
-
-(defun vip-mark-end-of-buffer ()
- "Mark end of buffer."
- (interactive)
- (push-mark (point))
- (goto-char (point-max))
- (exchange-point-and-mark)
- (message "Mark set at the end of buffer"))
-
-(defun vip-mark-point ()
- "Set mark at point of buffer."
- (interactive)
- (let ((char (vip-read-char-exclusive)))
- (cond ((and (<= ?a char) (<= char ?z))
- (point-to-register (1+ (- char ?a))))
- ((= char ?<) (vip-mark-beginning-of-buffer))
- ((= char ?>) (vip-mark-end-of-buffer))
- ((= char ?.) (vip-set-mark-if-necessary))
- ((= char ?,) (vip-cycle-through-mark-ring))
- ((= char ?D) (mark-defun))
- (t (error ""))
- )))
-
-;; Algorithm: If first invocation of this command save mark on ring, goto
-;; mark, M0, and pop the most recent elt from the mark ring into mark,
-;; making it into the new mark, M1.
-;; Push this mark back and set mark to the original point position, p1.
-;; So, if you hit '' or `` then you can return to p1.
-;;
-;; If repeated command, pop top elt from the ring into mark and
-;; jump there. This forgets the position, p1, and puts M1 back into mark.
-;; Then we save the current pos, which is M0, jump to M1 and pop M2 from
-;; the ring into mark. Push M2 back on the ring and set mark to M0.
-;; etc.
-(defun vip-cycle-through-mark-ring ()
- "Visit previous locations on the mark ring.
-One can use `` and '' to temporarily jump 1 step back."
- (let* ((sv-pt (point)))
- ;; if repeated `m,' command, pop the previously saved mark.
- ;; Prev saved mark is actually prev saved point. It is used if the
- ;; user types `` or '' and is discarded
- ;; from the mark ring by the next `m,' command.
- ;; In any case, go to the previous or previously saved mark.
- ;; Then push the current mark (popped off the ring) and set current
- ;; point to be the mark. Current pt as mark is discarded by the next
- ;; m, command.
- (if (eq last-command 'vip-cycle-through-mark-ring)
- ()
- ;; save current mark if the first iteration
- (setq mark-ring (delete (vip-mark-marker) mark-ring))
- (if (mark t)
- (push-mark (mark t) t)) )
- (pop-mark)
- (set-mark-command 1)
- ;; don't duplicate mark on the ring
- (setq mark-ring (delete (vip-mark-marker) mark-ring))
- (push-mark sv-pt t)
- (vip-deactivate-mark)
- (setq this-command 'vip-cycle-through-mark-ring)
- ))
-
-
-(defun vip-goto-mark (arg)
- "Go to mark."
- (interactive "P")
- (let ((char (read-char))
- (com (vip-getcom arg)))
- (vip-goto-mark-subr char com nil)))
-
-(defun vip-goto-mark-and-skip-white (arg)
- "Go to mark and skip to first non-white character on line."
- (interactive "P")
- (let ((char (read-char))
- (com (vip-getCom arg)))
- (vip-goto-mark-subr char com t)))
-
-(defun vip-goto-mark-subr (char com skip-white)
- (if (eobp)
- (if (bobp)
- (error "Empty buffer")
- (backward-char 1)))
- (cond ((vip-valid-register char '(letter))
- (let* ((buff (current-buffer))
- (reg (1+ (- char ?a)))
- (text-marker (get-register reg)))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (if (not (vip-valid-marker text-marker))
- (error vip-EmptyTextmarker char))
- (if (and (vip-same-line (point) vip-last-jump)
- (= (point) vip-last-jump-ignore))
- (push-mark vip-last-jump t)
- (push-mark nil t)) ; no msg
- (vip-register-to-point reg)
- (setq vip-last-jump (point-marker))
- (cond (skip-white
- (back-to-indentation)
- (setq vip-last-jump-ignore (point))))
- (if com
- (if (equal buff (current-buffer))
- (vip-execute-com (if skip-white
- 'vip-goto-mark-and-skip-white
- 'vip-goto-mark)
- nil com)
- (switch-to-buffer buff)
- (goto-char vip-com-point)
- (vip-change-state-to-vi)
- (error "")))))
- ((and (not skip-white) (= char ?`))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (if (and (vip-same-line (point) vip-last-jump)
- (= (point) vip-last-jump-ignore))
- (goto-char vip-last-jump))
- (if (null (mark t)) (error "Mark is not set in this buffer"))
- (if (= (point) (mark t)) (pop-mark))
- (exchange-point-and-mark)
- (setq vip-last-jump (point-marker)
- vip-last-jump-ignore 0)
- (if com (vip-execute-com 'vip-goto-mark nil com)))
- ((and skip-white (= char ?'))
- (if com (vip-move-marker-locally 'vip-com-point (point)))
- (if (and (vip-same-line (point) vip-last-jump)
- (= (point) vip-last-jump-ignore))
- (goto-char vip-last-jump))
- (if (= (point) (mark t)) (pop-mark))
- (exchange-point-and-mark)
- (setq vip-last-jump (point))
- (back-to-indentation)
- (setq vip-last-jump-ignore (point))
- (if com (vip-execute-com 'vip-goto-mark-and-skip-white nil com)))
- (t (error vip-InvalidTextmarker char))))
-
-(defun vip-insert-tab ()
- (interactive)
- (insert-tab))
-
-(defun vip-exchange-point-and-mark ()
- (interactive)
- (exchange-point-and-mark)
- (back-to-indentation))
-
-;; Input Mode Indentation
-
-;; Returns t, if the string before point matches the regexp STR.
-(defsubst vip-looking-back (str)
- (and (save-excursion (re-search-backward str nil t))
- (= (point) (match-end 0))))
-
-
-(defun vip-forward-indent ()
- "Indent forward -- `C-t' in Vi."
- (interactive)
- (setq vip-cted t)
- (indent-to (+ (current-column) vip-shift-width)))
-
-(defun vip-backward-indent ()
- "Backtab, C-d in VI"
- (interactive)
- (if vip-cted
- (let ((p (point)) (c (current-column)) bol (indent t))
- (if (vip-looking-back "[0^]")
- (progn
- (if (eq ?^ (preceding-char))
- (setq vip-preserve-indent t))
- (delete-backward-char 1)
- (setq p (point))
- (setq indent nil)))
- (save-excursion
- (beginning-of-line)
- (setq bol (point)))
- (if (re-search-backward "[^ \t]" bol 1) (forward-char))
- (delete-region (point) p)
- (if indent
- (indent-to (- c vip-shift-width)))
- (if (or (bolp) (vip-looking-back "[^ \t]"))
- (setq vip-cted nil)))))
-
-(defun vip-autoindent ()
- "Auto Indentation, Vi-style."
- (interactive)
- (let ((col (current-indentation)))
- (if vip-preserve-indent
- (setq vip-preserve-indent nil)
- (setq vip-current-indent col))
- ;; don't leave whitespace lines around
- (if (memq last-command
- '(vip-autoindent
- vip-open-line vip-Open-line
- vip-replace-state-exit-cmd))
- (indent-to-left-margin))
- ;; use \n instead of newline, or else <Return> will move the insert point
- ;;(newline 1)
- (insert "\n")
- (if vip-auto-indent
- (progn
- (setq vip-cted t)
- (if vip-electric-mode
- (indent-according-to-mode)
- (indent-to vip-current-indent))
- ))
- ))
-
-
-;; Viewing registers
-
-(defun vip-ket-function (arg)
- "Function called by \], the ket. View registers and call \]\]."
- (interactive "P")
- (let ((reg (read-char)))
- (cond ((vip-valid-register reg '(letter Letter))
- (view-register (downcase reg)))
- ((vip-valid-register reg '(digit))
- (let ((text (current-kill (- reg ?1) 'do-not-rotate)))
- (save-excursion
- (set-buffer (get-buffer-create "*Output*"))
- (delete-region (point-min) (point-max))
- (insert (format "Register %c contains the string:\n" reg))
- (insert text)
- (goto-char (point-min)))
- (display-buffer "*Output*")))
- ((= ?\] reg)
- (vip-next-heading arg))
- (t (error
- vip-InvalidRegister reg)))))
-
-(defun vip-brac-function (arg)
- "Function called by \[, the brac. View textmarkers and call \[\["
- (interactive "P")
- (let ((reg (read-char)))
- (cond ((= ?\[ reg)
- (vip-prev-heading arg))
- ((= ?\] reg)
- (vip-heading-end arg))
- ((vip-valid-register reg '(letter))
- (let* ((val (get-register (1+ (- reg ?a))))
- (buf (if (not val)
- (error vip-EmptyTextmarker reg)
- (marker-buffer val)))
- (pos (marker-position val))
- line-no text (s pos) (e pos))
- (save-excursion
- (set-buffer (get-buffer-create "*Output*"))
- (delete-region (point-min) (point-max))
- (if (and buf pos)
- (progn
- (save-excursion
- (set-buffer buf)
- (setq line-no (1+ (count-lines (point-min) val)))
- (goto-char pos)
- (beginning-of-line)
- (if (re-search-backward "[^ \t]" nil t)
- (progn
- (beginning-of-line)
- (setq s (point))))
- (goto-char pos)
- (forward-line 1)
- (if (re-search-forward "[^ \t]" nil t)
- (progn
- (end-of-line)
- (setq e (point))))
- (setq text (buffer-substring s e))
- (setq text (format "%s<%c>%s"
- (substring text 0 (- pos s))
- reg (substring text (- pos s)))))
- (insert
- (format
- "Textmarker `%c' is in buffer `%s' at line %d.\n"
- reg (buffer-name buf) line-no))
- (insert (format "Here is some text around %c:\n\n %s"
- reg text)))
- (insert (format vip-EmptyTextmarker reg)))
- (goto-char (point-min)))
- (display-buffer "*Output*")))
- (t (error vip-InvalidTextmarker reg)))))
-
-
-
-;; commands in insertion mode
-
-(defun vip-delete-backward-word (arg)
- "Delete previous word."
- (interactive "p")
- (save-excursion
- (push-mark nil t)
- (backward-word arg)
- (delete-region (point) (mark t))
- (pop-mark)))
-
-
-(defun vip-set-expert-level (&optional dont-change-unless)
- "Sets the expert level for a Viper user.
-Can be called interactively to change (temporarily or permanently) the
-current expert level.
-
-The optional argument DONT-CHANGE-UNLESS if not nil, says that
-the level should not be changed, unless its current value is
-meaningless (i.e., not one of 1,2,3,4,5).
-
-User level determines the setting of Viper variables that are most
-sensitive for VI-style look-and-feel."
-
- (interactive)
-
- (if (not (natnump vip-expert-level)) (setq vip-expert-level 0))
-
- (save-window-excursion
- (delete-other-windows)
- ;; if 0 < vip-expert-level < vip-max-expert-level
- ;; & dont-change-unless = t -- use it; else ask
- (vip-ask-level dont-change-unless))
-
- (setq vip-always t
- vip-ex-style-motion t
- vip-ex-style-editing-in-insert t
- vip-want-ctl-h-help nil)
-
- (cond ((eq vip-expert-level 1) ; novice or beginner
- (global-set-key ; in emacs-state
- vip-toggle-key
- (if (vip-window-display-p) 'vip-iconify 'suspend-emacs))
- (setq vip-no-multiple-ESC t
- vip-re-search t
- vip-vi-style-in-minibuffer t
- vip-search-wrap-around-t t
- vip-want-emacs-keys-in-vi nil
- vip-want-emacs-keys-in-insert nil))
-
- ((and (> vip-expert-level 1) (< vip-expert-level 5))
- ;; intermediate to guru
- (setq vip-no-multiple-ESC (if (vip-window-display-p) t 'twice)
- vip-want-emacs-keys-in-vi t
- vip-want-emacs-keys-in-insert (> vip-expert-level 2))
-
- (if (eq vip-expert-level 4) ; respect user's ex-style motions
- ; and vip-no-multiple-ESC
- (progn
- (setq-default vip-ex-style-editing-in-insert
- (cdr (assoc 'vip-ex-style-editing-in-insert
- vip-saved-user-settings))
- vip-ex-style-motion
- (cdr (assoc 'vip-ex-style-motion
- vip-saved-user-settings)))
- (setq vip-ex-style-motion
- (cdr (assoc 'vip-ex-style-motion vip-saved-user-settings))
- vip-ex-style-editing-in-insert
- (cdr (assoc 'vip-ex-style-editing-in-insert
- vip-saved-user-settings))
- vip-re-search
- (cdr (assoc 'vip-re-search vip-saved-user-settings))
- vip-no-multiple-ESC
- (cdr (assoc 'vip-no-multiple-ESC
- vip-saved-user-settings))))))
-
- ;; A wizard!!
- ;; Ideally, if 5 is selected, a buffer should pop up to let the
- ;; user toggle the values of variables.
- (t (setq-default vip-ex-style-editing-in-insert
- (cdr (assoc 'vip-ex-style-editing-in-insert
- vip-saved-user-settings))
- vip-ex-style-motion
- (cdr (assoc 'vip-ex-style-motion
- vip-saved-user-settings)))
- (setq vip-want-ctl-h-help
- (cdr (assoc 'vip-want-ctl-h-help vip-saved-user-settings))
- vip-always
- (cdr (assoc 'vip-always vip-saved-user-settings))
- vip-no-multiple-ESC
- (cdr (assoc 'vip-no-multiple-ESC vip-saved-user-settings))
- vip-ex-style-motion
- (cdr (assoc 'vip-ex-style-motion vip-saved-user-settings))
- vip-ex-style-editing-in-insert
- (cdr (assoc 'vip-ex-style-editing-in-insert
- vip-saved-user-settings))
- vip-re-search
- (cdr (assoc 'vip-re-search vip-saved-user-settings))
- vip-want-emacs-keys-in-vi
- (cdr (assoc 'vip-want-emacs-keys-in-vi
- vip-saved-user-settings))
- vip-want-emacs-keys-in-insert
- (cdr (assoc 'vip-want-emacs-keys-in-insert
- vip-saved-user-settings)))))
- (vip-set-mode-vars-for vip-current-state)
- (if (or vip-always
- (and (> vip-expert-level 0) (> 5 vip-expert-level)))
- (vip-set-hooks)))
-
-;; Ask user expert level.
-(defun vip-ask-level (dont-change-unless)
- (let ((ask-buffer " *vip-ask-level*")
- level-changed repeated)
- (save-window-excursion
- (switch-to-buffer ask-buffer)
-
- (or (eq this-command 'vip-set-expert-level)
- (and
- (<= vip-expert-level vip-max-expert-level)
- (>= vip-expert-level 1))
- (progn
- (insert "
-
- *** Important Notice for VIP users***
-
- This is VIPER
-
-@joke
-Viper Is a Package for Emacs Rebels,
-a VI Plan for Emacs Rescue,
-and a venomous VI PERil.
-@end joke
-
-Technically speaking, Viper is a new Vi emulator that replaces
-the old VIP package.
-
-Viper emulates Vi much better than VIP. It also significantly
-extends and improves upon Vi in many useful ways.
-
-Although many VIP settings in your ~/.vip are compatible with Viper,
-you may have to change some of them. Please refer to the documentation,
-which can be obtained by executing
-
-:help
-
-when Viper is in Vi state.
-
-If you will be so lucky as to find a bug, report it via the command
-
-:submitReport
-
-Type any key to continue... ")
-
- (read-char)
- (erase-buffer)))
-
- (while (or (> vip-expert-level vip-max-expert-level)
- (< vip-expert-level 1)
- (null dont-change-unless))
- (erase-buffer)
- (if repeated
- (progn
- (message "Invalid user level")
- (beep 1))
- (setq repeated t))
- (setq dont-change-unless t
- level-changed t)
- (insert "
-Please specify your level of familiarity with the venomous VI PERil
-(and the VI Plan for Emacs Rescue).
-You can change it at any time by typing `M-x vip-set-expert-level RET'
-
- 1 -- BEGINNER: Almost all Emacs features are suppressed.
- Feels almost like straight Vi. File name completion and
- command history in the minibuffer are thrown in as a bonus.
- To use Emacs productively, you must reach level 3 or higher.
- 2 -- MASTER: C-c now has its standard Emacs meaning in Vi command state,
- so most Emacs commands can be used when Viper is in Vi state.
- Good progress---you are well on the way to level 3!
- 3 -- GRAND MASTER: Like 3, but most Emacs commands are available also
- in Viper's insert state.
- 4 -- GURU: Like 3, but user settings are respected for vip-no-multiple-ESC,
- vip-re-search, vip-ex-style-motion, & vip-ex-style-editing-in-insert
- variables. Adjust these settings to your taste.
- 5 -- WIZARD: Like 4, but user settings are also respected for vip-always,
- vip-want-ctl-h-help, vip-want-emacs-keys-in-vi, and
- vip-want-emacs-keys-in-insert. Adjust these to your taste.
-
-Please, specify your level now: ")
-
- (setq vip-expert-level (- (vip-read-char-exclusive) ?0))
- ) ; end while
-
- ;; tell the user if level was changed
- (and level-changed
- (progn
- (insert
- (format "\n\n\n\n\n\t\tYou have selected user level %d"
- vip-expert-level))
- (if (y-or-n-p "Do you wish to make this change permanent? ")
- ;; save the setting for vip-expert-level
- (vip-save-setting
- 'vip-expert-level
- (format "Saving user level %d ..." vip-expert-level)
- vip-custom-file-name))
- ))
- (bury-buffer) ; remove ask-buffer from screen
- (message "")
- )))
-
-
-(defun viper-version ()
- (interactive)
- (message "Viper version is %s" viper-version))
-
-(defalias 'vip-version 'viper-version)
-
-(defun vip-nil ()
- (interactive)
- (beep 1))
-
-
-;; if ENFORCE-BUFFER is not nil, error if CHAR is a marker in another buffer
-(defun vip-register-to-point (char &optional enforce-buffer)
- "Like jump-to-register, but switches to another buffer in another window."
- (interactive "cViper register to point: ")
- (let ((val (get-register char)))
- (cond
- ((and (fboundp 'frame-configuration-p)
- (frame-configuration-p val))
- (set-frame-configuration val))
- ((window-configuration-p val)
- (set-window-configuration val))
- ((vip-valid-marker val)
- (if (and enforce-buffer
- (not (equal (current-buffer) (marker-buffer val))))
- (error (concat vip-EmptyTextmarker " in this buffer")
- (1- (+ char ?a))))
- (pop-to-buffer (marker-buffer val))
- (goto-char val))
- ((and (consp val) (eq (car val) 'file))
- (find-file (cdr val)))
- (t
- (error vip-EmptyTextmarker (1- (+ char ?a)))))))
-
-
-(defun vip-save-kill-buffer ()
- "Save then kill current buffer. "
- (interactive)
- (if (< vip-expert-level 2)
- (save-buffers-kill-emacs)
- (save-buffer)
- (kill-buffer (current-buffer))))
-
-
-
-;;; Bug Report
-
-(defun vip-submit-report ()
- "Submit bug report on Viper."
- (interactive)
- (let ((reporter-prompt-for-summary-p t)
- (vip-device-type (vip-device-type))
- color-display-p frame-parameters
- minibuffer-emacs-face minibuffer-vi-face minibuffer-insert-face
- varlist salutation window-config)
-
- ;; If mode info is needed, add variable to `let' and then set it below,
- ;; like we did with color-display-p.
- (setq color-display-p (if (vip-window-display-p)
- (vip-color-display-p)
- 'non-x)
- minibuffer-vi-face (if (vip-has-face-support-p)
- (vip-get-face vip-minibuffer-vi-face)
- 'non-x)
- minibuffer-insert-face (if (vip-has-face-support-p)
- (vip-get-face vip-minibuffer-insert-face)
- 'non-x)
- minibuffer-emacs-face (if (vip-has-face-support-p)
- (vip-get-face vip-minibuffer-emacs-face)
- 'non-x)
- frame-parameters (if (fboundp 'frame-parameters)
- (frame-parameters (selected-frame))))
-
- (setq varlist (list 'vip-vi-minibuffer-minor-mode
- 'vip-insert-minibuffer-minor-mode
- 'vip-vi-intercept-minor-mode
- 'vip-vi-local-user-minor-mode
- 'vip-vi-kbd-minor-mode
- 'vip-vi-global-user-minor-mode
- 'vip-vi-state-modifier-minor-mode
- 'vip-vi-diehard-minor-mode
- 'vip-vi-basic-minor-mode
- 'vip-replace-minor-mode
- 'vip-insert-intercept-minor-mode
- 'vip-insert-local-user-minor-mode
- 'vip-insert-kbd-minor-mode
- 'vip-insert-global-user-minor-mode
- 'vip-insert-state-modifier-minor-mode
- 'vip-insert-diehard-minor-mode
- 'vip-insert-basic-minor-mode
- 'vip-emacs-intercept-minor-mode
- 'vip-emacs-local-user-minor-mode
- 'vip-emacs-kbd-minor-mode
- 'vip-emacs-global-user-minor-mode
- 'vip-emacs-state-modifier-minor-mode
- 'vip-automatic-iso-accents
- 'vip-want-emacs-keys-in-insert
- 'vip-want-emacs-keys-in-vi
- 'vip-keep-point-on-undo
- 'vip-no-multiple-ESC
- 'vip-ESC-key
- 'vip-want-ctl-h-help
- 'vip-ex-style-editing-in-insert
- 'vip-delete-backwards-in-replace
- 'vip-vi-style-in-minibuffer
- 'vip-vi-state-hook
- 'vip-insert-state-hook
- 'vip-replace-state-hook
- 'vip-emacs-state-hook
- 'ex-cycle-other-window
- 'ex-cycle-through-non-files
- 'vip-expert-level
- 'major-mode
- 'vip-device-type
- 'color-display-p
- 'frame-parameters
- 'minibuffer-vi-face
- 'minibuffer-insert-face
- 'minibuffer-emacs-face
- ))
- (setq salutation "
-Congratulations! You may have unearthed a bug in Viper!
-Please mail a concise, accurate summary of the problem to the address above.
-
--------------------------------------------------------------------")
- (setq window-config (current-window-configuration))
- (with-output-to-temp-buffer " *vip-info*"
- (switch-to-buffer " *vip-info*")
- (delete-other-windows)
- (princ "
-PLEASE FOLLOW THESE PROCEDURES
-------------------------------
-
-Before reporting a bug, please verify that it is related to Viper, and is
-not cause by other packages you are using.
-
-Don't report compilation warnings, unless you are certain that there is a
-problem. These warnings are normal and unavoidable.
-
-Please note that users should not modify variables and keymaps other than
-those advertised in the manual. Such `customization' is likely to crash
-Viper, as it would any other improperly customized Emacs package.
-
-If you are reporting an error message received while executing one of the
-Viper commands, type:
-
- M-x set-variable <Return> debug-on-error <Return> t <Return>
-
-Then reproduce the error. The above command will cause Emacs to produce a
-back trace of the execution that leads to the error. Please include this
-trace in your bug report.
-
-If you believe that one of Viper's commands goes into an infinite loop
-\(e.g., Emacs freezes\), type:
-
- M-x set-variable <Return> debug-on-quit <Return> t <Return>
-
-Then reproduce the problem. Wait for a few seconds, then type C-g to abort
-the current command. Include the resulting back trace in the bug report.
-
-Mail anyway (y or n)? ")
- (if (y-or-n-p "Mail anyway? ")
- ()
- (set-window-configuration window-config)
- (error "Bug report aborted")))
-
- (require 'reporter)
- (set-window-configuration window-config)
-
- (reporter-submit-bug-report "kifer@cs.sunysb.edu"
- (vip-version)
- varlist
- nil 'delete-other-windows
- salutation)
- ))
-
-
-
-
-;; Smoothes out the difference between Emacs' unread-command-events
-;; and XEmacs unread-command-event. Arg is a character, an event, a list of
-;; events or a sequence of keys.
-;;
-;; Due to the way unread-command-events in Emacs (not XEmacs), a non-event
-;; symbol in unread-command-events list may cause Emacs to turn this symbol
-;; into an event. Below, we delete nil from event lists, since nil is the most
-;; common symbol that might appear in this wrong context.
-(defun vip-set-unread-command-events (arg)
- (if vip-emacs-p
- (setq
- unread-command-events
- (let ((new-events
- (cond ((eventp arg) (list arg))
- ((listp arg) arg)
- ((sequencep arg)
- (listify-key-sequence arg))
- (t (error
- "vip-set-unread-command-events: Invalid argument, %S"
- arg)))))
- (if (not (eventp nil))
- (setq new-events (delq nil new-events)))
- (append new-events unread-command-events)))
- ;; XEmacs
- (setq
- unread-command-events
- (append
- (cond ((vip-characterp arg) (list (character-to-event arg)))
- ((eventp arg) (list arg))
- ((stringp arg) (mapcar 'character-to-event arg))
- ((vectorp arg) (append arg nil)) ; turn into list
- ((listp arg) (vip-eventify-list-xemacs arg))
- (t (error
- "vip-set-unread-command-events: Invalid argument, %S" arg)))
- unread-command-events))))
-
-;; list is assumed to be a list of events of characters
-(defun vip-eventify-list-xemacs (lis)
- (mapcar
- (function (lambda (elt)
- (cond ((vip-characterp elt) (character-to-event elt))
- ((eventp elt) elt)
- (t (error
- "vip-eventify-list-xemacs: can't convert to event, %S"
- elt)))))
- lis))
-
-
-
-;;; Bring in the rest of the files
-(require 'viper-mous)
-(require 'viper-macs)
-(require 'viper-ex)
-
-
-
-;; The following is provided for compatibility with older VIP's
-
-(defalias 'vip-change-mode-to-vi 'vip-change-state-to-vi)
-(defalias 'vip-change-mode-to-insert 'vip-change-state-to-insert)
-(defalias 'vip-change-mode-to-emacs 'vip-change-state-to-emacs)
-
-
-
-;;; Load .vip and set up hooks
-
-;; This hook designed to enable Vi-style editing in comint-based modes."
-(defun vip-comint-mode-hook ()
- (setq require-final-newline nil
- vip-ex-style-editing-in-insert nil
- vip-ex-style-motion nil)
- (vip-change-state-to-insert))
-
-
-;; This sets major mode hooks to make them come up in vi-state.
-(defun vip-set-hooks ()
-
- ;; It is of course a misnomer to call viper-mode a `major mode'.
- ;; However, this has the effect that if the user didn't specify the
- ;; default mode, new buffers that fall back on the default will come up
- ;; in Fundamental Mode and Vi state.
- (setq default-major-mode 'viper-mode)
-
- ;; The following major modes should come up in vi-state
- (defadvice fundamental-mode (after vip-fundamental-mode-ad activate)
- "Run `vip-change-state-to-vi' on entry."
- (vip-change-state-to-vi))
-
- (defvar makefile-mode-hook)
- (add-hook 'makefile-mode-hook 'viper-mode)
-
- (defvar help-mode-hook)
- (add-hook 'help-mode-hook 'viper-mode)
-
- (defvar awk-mode-hook)
- (add-hook 'awk-mode-hook 'viper-mode)
-
- (defvar html-mode-hook)
- (add-hook 'html-mode-hook 'viper-mode)
- (defvar html-helper-mode-hook)
- (add-hook 'html-helper-mode-hook 'viper-mode)
- (defvar java-mode-hook)
- (add-hook 'java-mode-hook 'viper-mode)
-
- (defvar emacs-lisp-mode-hook)
- (add-hook 'emacs-lisp-mode-hook 'viper-mode)
-
- (defvar lisp-mode-hook)
- (add-hook 'lisp-mode-hook 'viper-mode)
-
- (defvar bibtex-mode-hook)
- (add-hook 'bibtex-mode-hook 'viper-mode)
-
- (defvar cc-mode-hook)
- (add-hook 'cc-mode-hook 'viper-mode)
-
- (defvar c-mode-hook)
- (add-hook 'c-mode-hook 'viper-mode)
-
- (defvar c++-mode-hook)
- (add-hook 'c++-mode-hook 'viper-mode)
-
- (defvar lisp-interaction-mode-hook)
- (add-hook 'lisp-interaction-mode-hook 'viper-mode)
-
- (defvar fortran-mode-hook)
- (add-hook 'fortran-mode-hook 'vip-mode)
-
- (defvar basic-mode-hook)
- (add-hook 'basic-mode-hook 'vip-mode)
- (defvar bat-mode-hook)
- (add-hook 'bat-mode-hook 'vip-mode)
-
- (defvar text-mode-hook)
- (add-hook 'text-mode-hook 'viper-mode)
-
- (add-hook 'completion-list-mode-hook 'viper-mode)
- (add-hook 'compilation-mode-hook 'viper-mode)
-
- (add-hook 'perl-mode-hook 'viper-mode)
- (add-hook 'tcl-mode-hook 'viper-mode)
-
- (defvar emerge-startup-hook)
- (add-hook 'emerge-startup-hook 'vip-change-state-to-emacs)
-
- ;; Tell vc-diff to put *vc* in Vi mode
- (if (featurep 'vc)
- (defadvice vc-diff (after vip-vc-ad activate)
- "Force Vi state in VC diff buffer."
- (vip-change-state-to-vi))
- (vip-eval-after-load
- "vc"
- '(defadvice vc-diff (after vip-vc-ad activate)
- "Force Vi state in VC diff buffer."
- (vip-change-state-to-vi))))
-
- (vip-eval-after-load
- "emerge"
- '(defadvice emerge-quit (after vip-emerge-advice activate)
- "Run `vip-change-state-to-vi' after quitting emerge."
- (vip-change-state-to-vi)))
- ;; In case Emerge was loaded before Viper.
- (defadvice emerge-quit (after vip-emerge-advice activate)
- "Run `vip-change-state-to-vi' after quitting emerge."
- (vip-change-state-to-vi))
-
- (vip-eval-after-load
- "asm-mode"
- '(defadvice asm-mode (after vip-asm-mode-ad activate)
- "Run `vip-change-state-to-vi' on entry."
- (vip-change-state-to-vi)))
-
- ;; passwd.el sets up its own buffer, which turns up in Vi mode,
- ;; thus overriding the local map. We don't need Vi mode here.
- (vip-eval-after-load
- "passwd"
- '(defadvice read-passwd-1 (before vip-passwd-ad activate)
- "Switch to emacs state while reading password."
- (vip-change-state-to-emacs)))
-
- (vip-eval-after-load
- "prolog"
- '(defadvice prolog-mode (after vip-prolog-ad activate)
- "Switch to Vi state in Prolog mode."
- (vip-change-state-to-vi)))
-
- ;; Emacs shell, ange-ftp, and comint-based modes
- (defvar comint-mode-hook)
- (vip-modify-major-mode
- 'comint-mode 'insert-state vip-comint-mode-modifier-map)
- (vip-modify-major-mode
- 'comint-mode 'vi-state vip-comint-mode-modifier-map)
- (vip-modify-major-mode
- 'shell-mode 'insert-state vip-comint-mode-modifier-map)
- (vip-modify-major-mode
- 'shell-mode 'vi-state vip-comint-mode-modifier-map)
- ;; ange-ftp in XEmacs
- (vip-modify-major-mode
- 'ange-ftp-shell-mode 'insert-state vip-comint-mode-modifier-map)
- (vip-modify-major-mode
- 'ange-ftp-shell-mode 'vi-state vip-comint-mode-modifier-map)
- ;; ange-ftp in Emacs
- (vip-modify-major-mode
- 'internal-ange-ftp-mode 'insert-state vip-comint-mode-modifier-map)
- (vip-modify-major-mode
- 'internal-ange-ftp-mode 'vi-state vip-comint-mode-modifier-map)
- ;; set hook
- (add-hook 'comint-mode-hook 'vip-comint-mode-hook)
-
- ;; Shell scripts
- (defvar sh-mode-hook)
- (add-hook 'sh-mode-hook 'viper-mode)
- (defvar ksh-mode-hook)
- (add-hook 'ksh-mode-hook 'viper-mode)
-
- ;; Dired
- (vip-modify-major-mode 'dired-mode 'emacs-state vip-dired-modifier-map)
- (vip-set-emacs-search-style-macros nil 'dired-mode)
- (add-hook 'dired-mode-hook 'vip-change-state-to-emacs)
-
- ;; Tar
- (vip-modify-major-mode 'tar-mode 'emacs-state vip-slash-and-colon-map)
- (vip-set-emacs-search-style-macros nil 'tar-mode)
-
- ;; MH-E
- (vip-modify-major-mode 'mh-folder-mode 'emacs-state vip-slash-and-colon-map)
- (vip-set-emacs-search-style-macros nil 'mh-folder-mode)
- ;; changing state to emacs is needed so the preceding will take hold
- (add-hook 'mh-folder-mode-hook 'vip-change-state-to-emacs)
- (add-hook 'mh-show-mode-hook 'viper-mode)
-
- ;; Gnus
- (vip-modify-major-mode 'gnus-group-mode 'emacs-state vip-slash-and-colon-map)
- (vip-set-emacs-search-style-macros nil 'gnus-group-mode)
- (vip-modify-major-mode
- 'gnus-summary-mode 'emacs-state vip-slash-and-colon-map)
- (vip-set-emacs-search-style-macros nil 'gnus-summary-mode)
- ;; changing state to emacs is needed so the preceding will take hold
- (add-hook 'gnus-group-mode-hook 'vip-change-state-to-emacs)
- (add-hook 'gnus-summary-mode-hook 'vip-change-state-to-emacs)
- (add-hook 'gnus-article-mode-hook 'viper-mode)
-
- ;; Info
- (vip-modify-major-mode 'Info-mode 'emacs-state vip-slash-and-colon-map)
- (vip-set-emacs-search-style-macros nil 'Info-mode)
- ;; Switching to emacs is needed so the above will take hold
- (defadvice Info-mode (after vip-Info-ad activate)
- "Switch to emacs mode."
- (vip-change-state-to-emacs))
-
- ;; Buffer menu
- (vip-modify-major-mode
- 'Buffer-menu-mode 'emacs-state vip-slash-and-colon-map)
- (vip-set-emacs-search-style-macros nil 'Buffer-menu-mode)
- ;; Switching to emacs is needed so the above will take hold
- (defadvice Buffer-menu-mode (after vip-Buffer-menu-ad activate)
- "Switch to emacs mode."
- (vip-change-state-to-emacs))
-
- ;; View mode
- (if vip-emacs-p
- (progn
- (defvar view-mode-hook)
- (add-hook 'view-mode-hook 'vip-change-state-to-emacs))
- (defadvice view-minor-mode (after vip-view-ad activate)
- "Switch to Emacs state in View mode."
- (vip-change-state-to-emacs))
- (defvar view-hook)
- (add-hook 'view-hook 'vip-change-state-to-emacs))
-
- ;; For VM users.
- ;; Put summary and other VM buffers in Emacs state.
- (defvar vm-mode-hooks)
- (defvar vm-summary-mode-hooks)
- (add-hook 'vm-mode-hooks 'vip-change-state-to-emacs)
- (add-hook 'vm-summary-mode-hooks 'vip-change-state-to-emacs)
-
- ;; For RMAIL users.
- ;; Put buf in Emacs state after edit.
- (vip-eval-after-load
- "rmailedit"
- '(defadvice rmail-cease-edit (after vip-rmail-advice activate)
- "Switch to emacs state when done editing message."
- (vip-change-state-to-emacs)))
- ;; In case RMAIL was loaded before Viper.
- (defadvice rmail-cease-edit (after vip-rmail-advice activate)
- "Switch to emacs state when done editing message."
- (vip-change-state-to-emacs))
- ) ; vip-set-hooks
-
-;; Set some useful macros
-;; These must be before we load .vip, so the user can unrecord them.
-
-;; repeat the 2nd previous command without rotating the command history
-(vip-record-kbd-macro
- (vector vip-repeat-from-history-key '\1) 'vi-state
- [(meta x) v i p - r e p e a t - f r o m - h i s t o r y return] 't)
-;; repeat the 3d previous command without rotating the command history
-(vip-record-kbd-macro
- (vector vip-repeat-from-history-key '\2) 'vi-state
- [(meta x) v i p - r e p e a t - f r o m - h i s t o r y return] 't)
-
-;; set the toggle case sensitivity and regexp search macros
-(vip-set-vi-search-style-macros nil)
-
-
-;; ~/.vip is loaded if it exists
-(if (and (file-exists-p vip-custom-file-name)
- (not noninteractive))
- (load vip-custom-file-name))
-
-;; VIP compatibility: merge whatever the user has in vip-mode-map into
-;; Viper's basic map.
-(vip-add-keymap vip-mode-map vip-vi-global-user-map)
-
-
-;; Applying Viper customization -- runs after (load .vip)
-
-;; Save user settings or Viper defaults for vars controled by vip-expert-level
-(setq vip-saved-user-settings
- (list (cons 'vip-want-ctl-h-help vip-want-ctl-h-help)
- (cons 'vip-always vip-always)
- (cons 'vip-no-multiple-ESC vip-no-multiple-ESC)
- (cons 'vip-ex-style-motion vip-ex-style-motion)
- (cons 'vip-ex-style-editing-in-insert
- vip-ex-style-editing-in-insert)
- (cons 'vip-want-emacs-keys-in-vi vip-want-emacs-keys-in-vi)
- (cons 'vip-want-emacs-keys-in-insert vip-want-emacs-keys-in-insert)
- (cons 'vip-re-search vip-re-search)))
-
-
-(vip-set-minibuffer-style)
-(vip-set-minibuffer-faces)
-(vip-set-search-face)
-(vip-set-replace-overlay-face)
-(if vip-buffer-search-char
- (vip-buffer-search-enable))
-(vip-update-alphanumeric-class)
-
-;;; Familiarize Viper with some minor modes that have their own keymaps
-(vip-harness-minor-mode "compile")
-(vip-harness-minor-mode "outline")
-(vip-harness-minor-mode "allout")
-(vip-harness-minor-mode "xref")
-(vip-harness-minor-mode "lmenu")
-(vip-harness-minor-mode "vc")
-(vip-harness-minor-mode "ltx-math") ; LaTeX-math-mode in AUC-TeX
-(vip-harness-minor-mode "latex") ; which is in one of these two files
-(vip-harness-minor-mode "cyrillic")
-(vip-harness-minor-mode "russian")
-(vip-harness-minor-mode "view-less")
-(vip-harness-minor-mode "view")
-
-
-;; Intercept maps could go in viper-keym.el
-;; We keep them here in case someone redefines them in ~/.vip
-
-(define-key vip-vi-intercept-map vip-ESC-key 'vip-intercept-ESC-key)
-(define-key vip-insert-intercept-map vip-ESC-key 'vip-intercept-ESC-key)
-
-;; This is taken care of by vip-insert-global-user-map.
-;;(define-key vip-replace-map vip-ESC-key 'vip-intercept-ESC-key)
-
-
-;; The default vip-toggle-key is \C-z; for the novice, it suspends or
-;; iconifies Emacs
-(define-key vip-vi-intercept-map vip-toggle-key 'vip-toggle-key-action)
-(define-key vip-emacs-intercept-map vip-toggle-key 'vip-change-state-to-vi)
-
-
-(if (or vip-always
- (and (< vip-expert-level 5) (> vip-expert-level 0)))
- (vip-set-hooks))
-
-;; Let all minor modes take effect after loading
-;; this may not be enough, so we also set default minor-mode-alist.
-;; Without setting the default, new buffers that come up in emacs mode have
-;; minor-mode-map-alist = nil, unless we call vip-change-state-*
-(if (eq vip-current-state 'emacs-state)
- (progn
- (vip-change-state-to-emacs)
- (setq-default minor-mode-map-alist minor-mode-map-alist)
- ))
-
-
-(run-hooks 'vip-load-hook) ; the last chance to change something
-
-(provide 'viper)
-(provide 'vip19)
-(provide 'vip)
-
-;;; viper.el ends here
diff --git a/lisp/emulation/ws-mode.el b/lisp/emulation/ws-mode.el
deleted file mode 100644
index 91f8b0170fc..00000000000
--- a/lisp/emulation/ws-mode.el
+++ /dev/null
@@ -1,753 +0,0 @@
-;;; ws-mode.el --- WordStar emulation mode for GNU Emacs
-
-;; Copyright (C) 1991 Free Software Foundation, Inc.
-
-;; Author: Juergen Nickelsen <nickel@cs.tu-berlin.de>
-;; Version: 0.7
-;; Keywords: emulations
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This emulates WordStar, with a major mode.
-
-;;; Code:
-
-(defvar wordstar-mode-map nil "")
-(defvar wordstar-C-j-map nil "")
-(defvar wordstar-C-k-map nil "")
-(defvar wordstar-C-o-map nil "")
-(defvar wordstar-C-q-map nil "")
-
-(if wordstar-mode-map
- ()
- (setq wordstar-mode-map (make-keymap))
- ;; (setq wordstar-C-j-map (make-keymap)) ; later, perhaps
- (setq wordstar-C-k-map (make-keymap))
- (setq wordstar-C-o-map (make-keymap))
- (setq wordstar-C-q-map (make-keymap))
-
- (define-key wordstar-mode-map "\C-a" 'backward-word)
- (define-key wordstar-mode-map "\C-b" 'fill-paragraph)
- (define-key wordstar-mode-map "\C-c" 'scroll-up)
- (define-key wordstar-mode-map "\C-d" 'forward-char)
- (define-key wordstar-mode-map "\C-e" 'previous-line)
- (define-key wordstar-mode-map "\C-f" 'forward-word)
- (define-key wordstar-mode-map "\C-g" 'delete-char)
- (define-key wordstar-mode-map "\C-h" 'backward-char)
- (define-key wordstar-mode-map "\C-i" 'indent-for-tab-command)
- (define-key wordstar-mode-map "\C-j" 'help-for-help)
- (define-key wordstar-mode-map "\C-k" wordstar-C-k-map)
- (define-key wordstar-mode-map "\C-l" 'ws-repeat-search)
- (define-key wordstar-mode-map "\C-n" 'open-line)
- (define-key wordstar-mode-map "\C-o" wordstar-C-o-map)
- (define-key wordstar-mode-map "\C-p" 'quoted-insert)
- (define-key wordstar-mode-map "\C-q" wordstar-C-q-map)
- (define-key wordstar-mode-map "\C-r" 'scroll-down)
- (define-key wordstar-mode-map "\C-s" 'backward-char)
- (define-key wordstar-mode-map "\C-t" 'kill-word)
- (define-key wordstar-mode-map "\C-u" 'keyboard-quit)
- (define-key wordstar-mode-map "\C-v" 'overwrite-mode)
- (define-key wordstar-mode-map "\C-w" 'scroll-down-line)
- (define-key wordstar-mode-map "\C-x" 'next-line)
- (define-key wordstar-mode-map "\C-y" 'kill-complete-line)
- (define-key wordstar-mode-map "\C-z" 'scroll-up-line)
-
- ;; wordstar-C-k-map
-
- (define-key wordstar-C-k-map " " ())
- (define-key wordstar-C-k-map "0" 'ws-set-marker-0)
- (define-key wordstar-C-k-map "1" 'ws-set-marker-1)
- (define-key wordstar-C-k-map "2" 'ws-set-marker-2)
- (define-key wordstar-C-k-map "3" 'ws-set-marker-3)
- (define-key wordstar-C-k-map "4" 'ws-set-marker-4)
- (define-key wordstar-C-k-map "5" 'ws-set-marker-5)
- (define-key wordstar-C-k-map "6" 'ws-set-marker-6)
- (define-key wordstar-C-k-map "7" 'ws-set-marker-7)
- (define-key wordstar-C-k-map "8" 'ws-set-marker-8)
- (define-key wordstar-C-k-map "9" 'ws-set-marker-9)
- (define-key wordstar-C-k-map "b" 'ws-begin-block)
- (define-key wordstar-C-k-map "\C-b" 'ws-begin-block)
- (define-key wordstar-C-k-map "c" 'ws-copy-block)
- (define-key wordstar-C-k-map "\C-c" 'ws-copy-block)
- (define-key wordstar-C-k-map "d" 'save-buffers-kill-emacs)
- (define-key wordstar-C-k-map "\C-d" 'save-buffers-kill-emacs)
- (define-key wordstar-C-k-map "f" 'find-file)
- (define-key wordstar-C-k-map "\C-f" 'find-file)
- (define-key wordstar-C-k-map "h" 'ws-show-markers)
- (define-key wordstar-C-k-map "\C-h" 'ws-show-markers)
- (define-key wordstar-C-k-map "i" 'ws-indent-block)
- (define-key wordstar-C-k-map "\C-i" 'ws-indent-block)
- (define-key wordstar-C-k-map "k" 'ws-end-block)
- (define-key wordstar-C-k-map "\C-k" 'ws-end-block)
- (define-key wordstar-C-k-map "p" 'ws-print-block)
- (define-key wordstar-C-k-map "\C-p" 'ws-print-block)
- (define-key wordstar-C-k-map "q" 'kill-emacs)
- (define-key wordstar-C-k-map "\C-q" 'kill-emacs)
- (define-key wordstar-C-k-map "r" 'insert-file)
- (define-key wordstar-C-k-map "\C-r" 'insert-file)
- (define-key wordstar-C-k-map "s" 'save-some-buffers)
- (define-key wordstar-C-k-map "\C-s" 'save-some-buffers)
- (define-key wordstar-C-k-map "t" 'ws-mark-word)
- (define-key wordstar-C-k-map "\C-t" 'ws-mark-word)
- (define-key wordstar-C-k-map "u" 'ws-exdent-block)
- (define-key wordstar-C-k-map "\C-u" 'keyboard-quit)
- (define-key wordstar-C-k-map "v" 'ws-move-block)
- (define-key wordstar-C-k-map "\C-v" 'ws-move-block)
- (define-key wordstar-C-k-map "w" 'ws-write-block)
- (define-key wordstar-C-k-map "\C-w" 'ws-write-block)
- (define-key wordstar-C-k-map "x" 'save-buffers-kill-emacs)
- (define-key wordstar-C-k-map "\C-x" 'save-buffers-kill-emacs)
- (define-key wordstar-C-k-map "y" 'ws-delete-block)
- (define-key wordstar-C-k-map "\C-y" 'ws-delete-block)
-
- ;; wordstar-C-j-map not yet implemented
-
- ;; wordstar-C-o-map
-
- (define-key wordstar-C-o-map " " ())
- (define-key wordstar-C-o-map "c" 'wordstar-center-line)
- (define-key wordstar-C-o-map "\C-c" 'wordstar-center-line)
- (define-key wordstar-C-o-map "b" 'switch-to-buffer)
- (define-key wordstar-C-o-map "\C-b" 'switch-to-buffer)
- (define-key wordstar-C-o-map "j" 'justify-current-line)
- (define-key wordstar-C-o-map "\C-j" 'justify-current-line)
- (define-key wordstar-C-o-map "k" 'kill-buffer)
- (define-key wordstar-C-o-map "\C-k" 'kill-buffer)
- (define-key wordstar-C-o-map "l" 'list-buffers)
- (define-key wordstar-C-o-map "\C-l" 'list-buffers)
- (define-key wordstar-C-o-map "m" 'auto-fill-mode)
- (define-key wordstar-C-o-map "\C-m" 'auto-fill-mode)
- (define-key wordstar-C-o-map "r" 'set-fill-column)
- (define-key wordstar-C-o-map "\C-r" 'set-fill-column)
- (define-key wordstar-C-o-map "\C-u" 'keyboard-quit)
- (define-key wordstar-C-o-map "wd" 'delete-other-windows)
- (define-key wordstar-C-o-map "wh" 'split-window-horizontally)
- (define-key wordstar-C-o-map "wo" 'other-window)
- (define-key wordstar-C-o-map "wv" 'split-window-vertically)
-
- ;; wordstar-C-q-map
- (define-key wordstar-C-q-map " " ())
- (define-key wordstar-C-q-map "0" 'ws-find-marker-0)
- (define-key wordstar-C-q-map "1" 'ws-find-marker-1)
- (define-key wordstar-C-q-map "2" 'ws-find-marker-2)
- (define-key wordstar-C-q-map "3" 'ws-find-marker-3)
- (define-key wordstar-C-q-map "4" 'ws-find-marker-4)
- (define-key wordstar-C-q-map "5" 'ws-find-marker-5)
- (define-key wordstar-C-q-map "6" 'ws-find-marker-6)
- (define-key wordstar-C-q-map "7" 'ws-find-marker-7)
- (define-key wordstar-C-q-map "8" 'ws-find-marker-8)
- (define-key wordstar-C-q-map "9" 'ws-find-marker-9)
- (define-key wordstar-C-q-map "a" 'ws-query-replace)
- (define-key wordstar-C-q-map "\C-a" 'ws-query-replace)
- (define-key wordstar-C-q-map "b" 'ws-goto-block-begin)
- (define-key wordstar-C-q-map "\C-b" 'ws-goto-block-begin)
- (define-key wordstar-C-q-map "c" 'end-of-buffer)
- (define-key wordstar-C-q-map "\C-c" 'end-of-buffer)
- (define-key wordstar-C-q-map "d" 'end-of-line)
- (define-key wordstar-C-q-map "\C-d" 'end-of-line)
- (define-key wordstar-C-q-map "f" 'ws-search)
- (define-key wordstar-C-q-map "\C-f" 'ws-search)
- (define-key wordstar-C-q-map "k" 'ws-goto-block-end)
- (define-key wordstar-C-q-map "\C-k" 'ws-goto-block-end)
- (define-key wordstar-C-q-map "l" 'ws-undo)
- (define-key wordstar-C-q-map "\C-l" 'ws-undo)
- (define-key wordstar-C-q-map "p" 'ws-last-cursorp)
- (define-key wordstar-C-q-map "\C-p" 'ws-last-cursorp)
- (define-key wordstar-C-q-map "r" 'beginning-of-buffer)
- (define-key wordstar-C-q-map "\C-r" 'beginning-of-buffer)
- (define-key wordstar-C-q-map "s" 'beginning-of-line)
- (define-key wordstar-C-q-map "\C-s" 'beginning-of-line)
- (define-key wordstar-C-q-map "\C-u" 'keyboard-quit)
- (define-key wordstar-C-q-map "w" 'ws-last-error)
- (define-key wordstar-C-q-map "\C-w" 'ws-last-error)
- (define-key wordstar-C-q-map "y" 'ws-kill-eol)
- (define-key wordstar-C-q-map "\C-y" 'ws-kill-eol)
- (define-key wordstar-C-q-map "\177" 'ws-kill-bol))
-
-;;;###autoload
-(defun wordstar-mode ()
- "Major mode with WordStar-like key bindings.
-
-BUGS:
- - Help menus with WordStar commands (C-j just calls help-for-help)
- are not implemented
- - Options for search and replace
- - Show markers (C-k h) is somewhat strange
- - Search and replace (C-q a) is only available in forward direction
-
-No key bindings beginning with ESC are installed, they will work
-Emacs-like.
-
-The key bindings are:
-
- C-a backward-word
- C-b fill-paragraph
- C-c scroll-up-line
- C-d forward-char
- C-e previous-line
- C-f forward-word
- C-g delete-char
- C-h backward-char
- C-i indent-for-tab-command
- C-j help-for-help
- C-k ordstar-C-k-map
- C-l ws-repeat-search
- C-n open-line
- C-p quoted-insert
- C-r scroll-down-line
- C-s backward-char
- C-t kill-word
- C-u keyboard-quit
- C-v overwrite-mode
- C-w scroll-down
- C-x next-line
- C-y kill-complete-line
- C-z scroll-up
-
- C-k 0 ws-set-marker-0
- C-k 1 ws-set-marker-1
- C-k 2 ws-set-marker-2
- C-k 3 ws-set-marker-3
- C-k 4 ws-set-marker-4
- C-k 5 ws-set-marker-5
- C-k 6 ws-set-marker-6
- C-k 7 ws-set-marker-7
- C-k 8 ws-set-marker-8
- C-k 9 ws-set-marker-9
- C-k b ws-begin-block
- C-k c ws-copy-block
- C-k d save-buffers-kill-emacs
- C-k f find-file
- C-k h ws-show-markers
- C-k i ws-indent-block
- C-k k ws-end-block
- C-k p ws-print-block
- C-k q kill-emacs
- C-k r insert-file
- C-k s save-some-buffers
- C-k t ws-mark-word
- C-k u ws-exdent-block
- C-k C-u keyboard-quit
- C-k v ws-move-block
- C-k w ws-write-block
- C-k x kill-emacs
- C-k y ws-delete-block
-
- C-o c wordstar-center-line
- C-o b switch-to-buffer
- C-o j justify-current-line
- C-o k kill-buffer
- C-o l list-buffers
- C-o m auto-fill-mode
- C-o r set-fill-column
- C-o C-u keyboard-quit
- C-o wd delete-other-windows
- C-o wh split-window-horizontally
- C-o wo other-window
- C-o wv split-window-vertically
-
- C-q 0 ws-find-marker-0
- C-q 1 ws-find-marker-1
- C-q 2 ws-find-marker-2
- C-q 3 ws-find-marker-3
- C-q 4 ws-find-marker-4
- C-q 5 ws-find-marker-5
- C-q 6 ws-find-marker-6
- C-q 7 ws-find-marker-7
- C-q 8 ws-find-marker-8
- C-q 9 ws-find-marker-9
- C-q a ws-query-replace
- C-q b ws-to-block-begin
- C-q c end-of-buffer
- C-q d end-of-line
- C-q f ws-search
- C-q k ws-to-block-end
- C-q l ws-undo
- C-q p ws-last-cursorp
- C-q r beginning-of-buffer
- C-q C-u keyboard-quit
- C-q w ws-last-error
- C-q y ws-kill-eol
- C-q DEL ws-kill-bol
-"
- (interactive)
- (kill-all-local-variables)
- (use-local-map wordstar-mode-map)
- (setq mode-name "WordStar")
- (setq major-mode 'wordstar-mode))
-
-
-(defun wordstar-center-paragraph ()
- "Center each line in the paragraph at or after point.
-See `wordstar-center-line' for more info."
- (interactive)
- (save-excursion
- (forward-paragraph)
- (or (bolp) (newline 1))
- (let ((end (point)))
- (backward-paragraph)
- (wordstar-center-region (point) end))))
-
-(defun wordstar-center-region (from to)
- "Center each line starting in the region.
-See `wordstar-center-line' for more info."
- (interactive "r")
- (if (> from to)
- (let ((tem to))
- (setq to from from tem)))
- (save-excursion
- (save-restriction
- (narrow-to-region from to)
- (goto-char from)
- (while (not (eobp))
- (wordstar-center-line)
- (forward-line 1)))))
-
-(defun wordstar-center-line ()
- "Center the line point is on, within the width specified by `fill-column'.
-This means adjusting the indentation to match
-the distance between the end of the text and `fill-column'."
- (interactive)
- (save-excursion
- (let (line-length)
- (beginning-of-line)
- (delete-horizontal-space)
- (end-of-line)
- (delete-horizontal-space)
- (setq line-length (current-column))
- (beginning-of-line)
- (indent-to
- (+ left-margin
- (/ (- fill-column left-margin line-length) 2))))))
-
-(defun scroll-down-line ()
- "Scroll one line down."
- (interactive)
- (scroll-down 1))
-
-(defun scroll-up-line ()
- "Scroll one line up."
- (interactive)
- (scroll-up 1))
-
-;;;;;;;;;;;
-;; wordstar special variables:
-
-(defvar ws-marker-0 nil "Position marker 0 in WordStar mode.")
-(defvar ws-marker-1 nil "Position marker 1 in WordStar mode.")
-(defvar ws-marker-2 nil "Position marker 2 in WordStar mode.")
-(defvar ws-marker-3 nil "Position marker 3 in WordStar mode.")
-(defvar ws-marker-4 nil "Position marker 4 in WordStar mode.")
-(defvar ws-marker-5 nil "Position marker 5 in WordStar mode.")
-(defvar ws-marker-6 nil "Position marker 6 in WordStar mode.")
-(defvar ws-marker-7 nil "Position marker 7 in WordStar mode.")
-(defvar ws-marker-8 nil "Position marker 8 in WordStar mode.")
-(defvar ws-marker-9 nil "Position marker 9 in WordStar mode.")
-
-(defvar ws-block-begin-marker nil "Beginning of \"Block\" in WordStar mode.")
-(defvar ws-block-end-marker nil "End of \"Block\" in WordStar mode.")
-
-(defvar ws-search-string nil "String of last search in WordStar mode.")
-(defvar ws-search-direction t
- "Direction of last search in WordStar mode. T if forward, NIL if backward.")
-
-(defvar ws-last-cursorposition nil
- "Position before last search etc. in WordStar mode.")
-
-(defvar ws-last-errormessage nil
- "Last error message issued by a WordStar mode function.")
-
-;;;;;;;;;;;
-;; wordstar special functions:
-
-(defun ws-error (string)
- "Report error of a WordStar special function. Error message is saved
-in ws-last-errormessage for recovery with C-q w."
- (setq ws-last-errormessage string)
- (error string))
-
-(defun ws-set-marker-0 ()
- "In WordStar mode: Set marker 0 to current cursor position."
- (interactive)
- (setq ws-marker-0 (point-marker))
- (message "Marker 0 set"))
-
-(defun ws-set-marker-1 ()
- "In WordStar mode: Set marker 1 to current cursor position."
- (interactive)
- (setq ws-marker-1 (point-marker))
- (message "Marker 1 set"))
-
-(defun ws-set-marker-2 ()
- "In WordStar mode: Set marker 2 to current cursor position."
- (interactive)
- (setq ws-marker-2 (point-marker))
- (message "Marker 2 set"))
-
-(defun ws-set-marker-3 ()
- "In WordStar mode: Set marker 3 to current cursor position."
- (interactive)
- (setq ws-marker-3 (point-marker))
- (message "Marker 3 set"))
-
-(defun ws-set-marker-4 ()
- "In WordStar mode: Set marker 4 to current cursor position."
- (interactive)
- (setq ws-marker-4 (point-marker))
- (message "Marker 4 set"))
-
-(defun ws-set-marker-5 ()
- "In WordStar mode: Set marker 5 to current cursor position."
- (interactive)
- (setq ws-marker-5 (point-marker))
- (message "Marker 5 set"))
-
-(defun ws-set-marker-6 ()
- "In WordStar mode: Set marker 6 to current cursor position."
- (interactive)
- (setq ws-marker-6 (point-marker))
- (message "Marker 6 set"))
-
-(defun ws-set-marker-7 ()
- "In WordStar mode: Set marker 7 to current cursor position."
- (interactive)
- (setq ws-marker-7 (point-marker))
- (message "Marker 7 set"))
-
-(defun ws-set-marker-8 ()
- "In WordStar mode: Set marker 8 to current cursor position."
- (interactive)
- (setq ws-marker-8 (point-marker))
- (message "Marker 8 set"))
-
-(defun ws-set-marker-9 ()
- "In WordStar mode: Set marker 9 to current cursor position."
- (interactive)
- (setq ws-marker-9 (point-marker))
- (message "Marker 9 set"))
-
-(defun ws-begin-block ()
- "In WordStar mode: Set block begin marker to current cursor position."
- (interactive)
- (setq ws-block-begin-marker (point-marker))
- (message "Block begin marker set"))
-
-(defun ws-show-markers ()
- "In WordStar mode: Show block markers."
- (interactive)
- (if (or ws-block-begin-marker ws-block-end-marker)
- (save-excursion
- (if ws-block-begin-marker
- (let ()
- (goto-char ws-block-begin-marker)
- (message "Block begin marker")
- (sit-for 2))
- (message "Block begin marker not set")
- (sit-for 2))
- (if ws-block-end-marker
- (let ()
- (goto-char ws-block-end-marker)
- (message "Block end marker")
- (sit-for 2))
- (message "Block end marker not set"))
- (message ""))
- (message "Block markers not set")))
-
-
-(defun ws-indent-block ()
- "In WordStar mode: Indent block (not yet implemented)."
- (interactive)
- (ws-error "Indent block not yet implemented"))
-
-(defun ws-end-block ()
- "In WordStar mode: Set block end marker to current cursor position."
- (interactive)
- (setq ws-block-end-marker (point-marker))
- (message "Block end marker set"))
-
-(defun ws-print-block ()
- "In WordStar mode: Print block."
- (interactive)
- (message "Don't do this. Write block to a file (C-k w) and print this file."))
-
-(defun ws-mark-word ()
- "In WordStar mode: Mark current word as block."
- (interactive)
- (save-excursion
- (forward-word 1)
- (sit-for 1)
- (ws-end-block)
- (forward-word -1)
- (sit-for 1)
- (ws-begin-block)))
-
-(defun ws-exdent-block ()
- "I don't know what this (C-k u) should do."
- (interactive)
- (ws-error "This won't be done -- not yet implemented."))
-
-(defun ws-move-block ()
- "In WordStar mode: Move block to current cursor position."
- (interactive)
- (if (and ws-block-begin-marker ws-block-end-marker)
- (let ()
- (kill-region ws-block-begin-marker ws-block-end-marker)
- (yank)
- (save-excursion
- (goto-char (region-beginning))
- (setq ws-block-begin-marker (point-marker))
- (goto-char (region-end))
- (setq ws-block-end-marker (point-marker))))
- (ws-error (cond (ws-block-begin-marker "Block end marker not set")
- (ws-block-end-marker "Block begin marker not set")
- (t "Block markers not set")))))
-
-(defun ws-write-block ()
- "In WordStar mode: Write block to file."
- (interactive)
- (if (and ws-block-begin-marker ws-block-end-marker)
- (let ((filename (read-file-name "Write block to file: ")))
- (write-region ws-block-begin-marker ws-block-end-marker filename))
- (ws-error (cond (ws-block-begin-marker "Block end marker not set")
- (ws-block-end-marker "Block begin marker not set")
- (t "Block markers not set")))))
-
-
-(defun ws-delete-block ()
- "In WordStar mode: Delete block."
- (interactive)
- (if (and ws-block-begin-marker ws-block-end-marker)
- (let ()
- (kill-region ws-block-begin-marker ws-block-end-marker)
- (setq ws-block-end-marker nil)
- (setq ws-block-begin-marker nil))
- (ws-error (cond (ws-block-begin-marker "Block end marker not set")
- (ws-block-end-marker "Block begin marker not set")
- (t "Block markers not set")))))
-
-(defun ws-find-marker-0 ()
- "In WordStar mode: Go to marker 0."
- (interactive)
- (if ws-marker-0
- (let ()
- (setq ws-last-cursorposition (point-marker))
- (goto-char ws-marker-0))
- (ws-error "Marker 0 not set")))
-
-(defun ws-find-marker-1 ()
- "In WordStar mode: Go to marker 1."
- (interactive)
- (if ws-marker-1
- (let ()
- (setq ws-last-cursorposition (point-marker))
- (goto-char ws-marker-1))
- (ws-error "Marker 1 not set")))
-
-(defun ws-find-marker-2 ()
- "In WordStar mode: Go to marker 2."
- (interactive)
- (if ws-marker-2
- (let ()
- (setq ws-last-cursorposition (point-marker))
- (goto-char ws-marker-2))
- (ws-error "Marker 2 not set")))
-
-(defun ws-find-marker-3 ()
- "In WordStar mode: Go to marker 3."
- (interactive)
- (if ws-marker-3
- (let ()
- (setq ws-last-cursorposition (point-marker))
- (goto-char ws-marker-3))
- (ws-error "Marker 3 not set")))
-
-(defun ws-find-marker-4 ()
- "In WordStar mode: Go to marker 4."
- (interactive)
- (if ws-marker-4
- (let ()
- (setq ws-last-cursorposition (point-marker))
- (goto-char ws-marker-4))
- (ws-error "Marker 4 not set")))
-
-(defun ws-find-marker-5 ()
- "In WordStar mode: Go to marker 5."
- (interactive)
- (if ws-marker-5
- (let ()
- (setq ws-last-cursorposition (point-marker))
- (goto-char ws-marker-5))
- (ws-error "Marker 5 not set")))
-
-(defun ws-find-marker-6 ()
- "In WordStar mode: Go to marker 6."
- (interactive)
- (if ws-marker-6
- (let ()
- (setq ws-last-cursorposition (point-marker))
- (goto-char ws-marker-6))
- (ws-error "Marker 6 not set")))
-
-(defun ws-find-marker-7 ()
- "In WordStar mode: Go to marker 7."
- (interactive)
- (if ws-marker-7
- (let ()
- (setq ws-last-cursorposition (point-marker))
- (goto-char ws-marker-7))
- (ws-error "Marker 7 not set")))
-
-(defun ws-find-marker-8 ()
- "In WordStar mode: Go to marker 8."
- (interactive)
- (if ws-marker-8
- (let ()
- (setq ws-last-cursorposition (point-marker))
- (goto-char ws-marker-8))
- (ws-error "Marker 8 not set")))
-
-(defun ws-find-marker-9 ()
- "In WordStar mode: Go to marker 9."
- (interactive)
- (if ws-marker-9
- (let ()
- (setq ws-last-cursorposition (point-marker))
- (goto-char ws-marker-9))
- (ws-error "Marker 9 not set")))
-
-(defun ws-goto-block-begin ()
- "In WordStar mode: Go to block begin marker."
- (interactive)
- (if ws-block-begin-marker
- (let ()
- (setq ws-last-cursorposition (point-marker))
- (goto-char ws-block-begin-marker))
- (ws-error "Block begin marker not set")))
-
-(defun ws-search (string)
- "In WordStar mode: Search string, remember string for repetition."
- (interactive "sSearch for: ")
- (message "Forward (f) or backward (b)")
- (let ((direction
- (read-char)))
- (cond ((equal (upcase direction) ?F)
- (setq ws-search-string string)
- (setq ws-search-direction t)
- (setq ws-last-cursorposition (point-marker))
- (search-forward string))
- ((equal (upcase direction) ?B)
- (setq ws-search-string string)
- (setq ws-search-direction nil)
- (setq ws-last-cursorposition (point-marker))
- (search-backward string))
- (t (keyboard-quit)))))
-
-(defun ws-goto-block-end ()
- "In WordStar mode: Go to block end marker."
- (interactive)
- (if ws-block-end-marker
- (let ()
- (setq ws-last-cursorposition (point-marker))
- (goto-char ws-block-end-marker))
- (ws-error "Block end marker not set")))
-
-(defun ws-undo ()
- "In WordStar mode: Undo and give message about undoing more changes."
- (interactive)
- (undo)
- (message "Repeat C-q l to undo more changes."))
-
-(defun ws-goto-last-cursorposition ()
- "In WordStar mode: "
- (interactive)
- (if ws-last-cursorposition
- (let ()
- (setq ws-last-cursorposition (point-marker))
- (goto-char ws-last-cursorposition))
- (ws-error "No last cursor position available.")))
-
-(defun ws-last-error ()
- "In WordStar mode: repeat last error message.
-This will only work for errors raised by WordStar mode functions."
- (interactive)
- (if ws-last-errormessage
- (message ws-last-errormessage)
- (message "No WordStar error yet.")))
-
-(defun ws-kill-eol ()
- "In WordStar mode: Kill to end of line (like WordStar, not like Emacs)."
- (interactive)
- (let ((p (point)))
- (end-of-line)
- (kill-region p (point))))
-
-(defun ws-kill-bol ()
- "In WordStar mode: Kill to beginning of line
-\(like WordStar, not like Emacs)."
- (interactive)
- (let ((p (point)))
- (beginning-of-line)
- (kill-region (point) p)))
-
-(defun kill-complete-line ()
- "Kill the complete line."
- (interactive)
- (beginning-of-line)
- (if (eobp) (error "End of buffer"))
- (let ((beg (point)))
- (forward-line 1)
- (kill-region beg (point))))
-
-(defun ws-repeat-search ()
- "In WordStar mode: Repeat last search."
- (interactive)
- (setq ws-last-cursorposition (point-marker))
- (if ws-search-string
- (if ws-search-direction
- (search-forward ws-search-string)
- (search-backward ws-search-string))
- (ws-error "No search to repeat")))
-
-(defun ws-query-replace (from to)
- "In WordStar mode: Search string, remember string for repetition."
- (interactive "sReplace:
-sWith: " )
- (setq ws-search-string from)
- (setq ws-search-direction t)
- (setq ws-last-cursorposition (point-marker))
- (query-replace from to))
-
-(defun ws-copy-block ()
- "In WordStar mode: Copy block to current cursor position."
- (interactive)
- (if (and ws-block-begin-marker ws-block-end-marker)
- (let ()
- (copy-region-as-kill ws-block-begin-marker ws-block-end-marker)
- (yank)
- (save-excursion
- (goto-char (region-beginning))
- (setq ws-block-begin-marker (point-marker))
- (goto-char (region-end))
- (setq ws-block-end-marker (point-marker))))
- (ws-error (cond (ws-block-begin-marker "Block end marker not set")
- (ws-block-end-marker "Block begin marker not set")
- (t "Block markers not set")))))
-
-;;; ws-mode.el ends here
diff --git a/lisp/enriched.el b/lisp/enriched.el
deleted file mode 100644
index 362a537d846..00000000000
--- a/lisp/enriched.el
+++ /dev/null
@@ -1,447 +0,0 @@
-;;; enriched.el --- read and save files in text/enriched format
-
-;; Copyright (c) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Boris Goldowsky <boris@gnu.ai.mit.edu>
-;; Keywords: wp, faces
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This file implements reading, editing, and saving files with
-;; text-properties such as faces, levels of indentation, and true line
-;; breaks distinguished from newlines just used to fit text into the window.
-
-;; The file format used is the MIME text/enriched format, which is a
-;; standard format defined in internet RFC 1563. All standard annotations
-;; are supported except for <smaller> and <bigger>, which are currently not
-;; possible to display.
-
-;; A separate file, enriched.doc, contains further documentation and other
-;; important information about this code. It also serves as an example
-;; file in text/enriched format. It should be in the etc directory of your
-;; emacs distribution.
-
-;;; Code:
-
-(provide 'enriched)
-
-;;;
-;;; Variables controlling the display
-;;;
-
-(defvar enriched-verbose t
- "*If non-nil, give status messages when reading and writing files.")
-
-;;;
-;;; Set up faces & display table
-;;;
-
-;; A slight cheat - all emacs's faces are fixed-width.
-;; The idea is just to pick one that looks different from the default.
-(if (internal-find-face 'fixed)
- nil
- (make-face 'fixed)
- (if window-system
- (set-face-font 'fixed
- (car (or (x-list-fonts "*fixed-medium*"
- 'default (selected-frame))
- (x-list-fonts "*fixed*"
- 'default (selected-frame)))))))
-
-(if (internal-find-face 'excerpt)
- nil
- (make-face 'excerpt)
- (if window-system
- (make-face-italic 'excerpt nil t)))
-
-(defconst enriched-display-table (or (copy-sequence standard-display-table)
- (make-display-table)))
-(aset enriched-display-table ?\f (make-vector (1- (frame-width)) ?-))
-
-(defconst enriched-par-props '(left-margin right-margin justification)
- "Text-properties that usually apply to whole paragraphs.
-These are set front-sticky everywhere except at hard newlines.")
-
-;;;
-;;; Variables controlling the file format
-;;; (bidirectional)
-
-(defconst enriched-initial-annotation
- (lambda ()
- (format "Content-Type: text/enriched\nText-Width: %d\n\n"
- fill-column))
- "What to insert at the start of a text/enriched file.
-If this is a string, it is inserted. If it is a list, it should be a lambda
-expression, which is evaluated to get the string to insert.")
-
-(defconst enriched-annotation-format "<%s%s>"
- "General format of enriched-text annotations.")
-
-(defconst enriched-annotation-regexp "<\\(/\\)?\\([-A-za-z0-9]+\\)>"
- "Regular expression matching enriched-text annotations.")
-
-(defconst enriched-translations
- '((face (bold-italic "bold" "italic")
- (bold "bold")
- (italic "italic")
- (underline "underline")
- (fixed "fixed")
- (excerpt "excerpt")
- (default )
- (nil enriched-encode-other-face))
- (left-margin (4 "indent"))
- (right-margin (4 "indentright"))
- (justification (none "nofill")
- (right "flushright")
- (left "flushleft")
- (full "flushboth")
- (center "center"))
- (PARAMETER (t "param")) ; Argument of preceding annotation
- ;; The following are not part of the standard:
- (FUNCTION (enriched-decode-foreground "x-color")
- (enriched-decode-background "x-bg-color"))
- (read-only (t "x-read-only"))
- (unknown (nil format-annotate-value))
-; (font-size (2 "bigger") ; unimplemented
-; (-2 "smaller"))
-)
- "List of definitions of text/enriched annotations.
-See `format-annotate-region' and `format-deannotate-region' for the definition
-of this structure.")
-
-(defconst enriched-ignore
- '(front-sticky rear-nonsticky hard)
- "Properties that are OK to ignore when saving text/enriched files.
-Any property that is neither on this list nor dealt with by
-`enriched-translations' will generate a warning.")
-
-;;; Internal variables
-
-(defvar enriched-mode nil
- "True if Enriched mode is in use.")
-(make-variable-buffer-local 'enriched-mode)
-
-(if (not (assq 'enriched-mode minor-mode-alist))
- (setq minor-mode-alist
- (cons '(enriched-mode " Enriched")
- minor-mode-alist)))
-
-(defvar enriched-mode-hook nil
- "Functions to run when entering Enriched mode.
-If you set variables in this hook, you should arrange for them to be restored
-to their old values if you leave Enriched mode. One way to do this is to add
-them and their old values to `enriched-old-bindings'.")
-
-(defvar enriched-old-bindings nil
- "Store old variable values that we change when entering mode.
-The value is a list of \(VAR VALUE VAR VALUE...).")
-(make-variable-buffer-local 'enriched-old-bindings)
-
-;;;
-;;; Define the mode
-;;;
-
-;;;###autoload
-(defun enriched-mode (&optional arg)
- "Minor mode for editing text/enriched files.
-These are files with embedded formatting information in the MIME standard
-text/enriched format.
-Turning the mode on runs `enriched-mode-hook'.
-
-More information about Enriched mode is available in the file
-etc/enriched.doc in the Emacs distribution directory.
-
-Commands:
-
-\\<enriched-mode-map>\\{enriched-mode-map}"
- (interactive "P")
- (let ((mod (buffer-modified-p)))
- (cond ((or (<= (prefix-numeric-value arg) 0)
- (and enriched-mode (null arg)))
- ;; Turn mode off
- (setq enriched-mode nil)
- (setq buffer-file-format (delq 'text/enriched buffer-file-format))
- ;; restore old variable values
- (while enriched-old-bindings
- (funcall 'set (car enriched-old-bindings)
- (car (cdr enriched-old-bindings)))
- (setq enriched-old-bindings (cdr (cdr enriched-old-bindings)))))
-
- (enriched-mode nil) ; Mode already on; do nothing.
-
- (t (setq enriched-mode t) ; Turn mode on
- (add-to-list 'buffer-file-format 'text/enriched)
- ;; Save old variable values before we change them.
- ;; These will be restored if we exit Enriched mode.
- (setq enriched-old-bindings
- (list 'buffer-display-table buffer-display-table
- 'indent-line-function indent-line-function
- 'default-text-properties default-text-properties))
- (make-local-variable 'indent-line-function)
- (make-local-variable 'default-text-properties)
- (setq indent-line-function 'indent-to-left-margin
- buffer-display-table enriched-display-table)
- (use-hard-newlines 1 nil)
- (let ((sticky (plist-get default-text-properties 'front-sticky))
- (p enriched-par-props))
- (while p
- (add-to-list 'sticky (car p))
- (setq p (cdr p)))
- (if sticky
- (setq default-text-properties
- (plist-put default-text-properties
- 'front-sticky sticky))))
- (run-hooks 'enriched-mode-hook)))
- (set-buffer-modified-p mod)
- (force-mode-line-update)))
-
-;;;
-;;; Keybindings
-;;;
-
-(defvar enriched-mode-map nil
- "Keymap for Enriched mode.")
-
-(if (null enriched-mode-map)
- (fset 'enriched-mode-map (setq enriched-mode-map (make-sparse-keymap))))
-
-(if (not (assq 'enriched-mode minor-mode-map-alist))
- (setq minor-mode-map-alist
- (cons (cons 'enriched-mode enriched-mode-map)
- minor-mode-map-alist)))
-
-(define-key enriched-mode-map "\C-a" 'beginning-of-line-text)
-(define-key enriched-mode-map "\C-m" 'reindent-then-newline-and-indent)
-(define-key enriched-mode-map "\C-j" 'reindent-then-newline-and-indent)
-(define-key enriched-mode-map "\M-j" 'facemenu-justification-menu)
-(define-key enriched-mode-map "\M-S" 'set-justification-center)
-(define-key enriched-mode-map "\C-x\t" 'increase-left-margin)
-(define-key enriched-mode-map "\C-c\C-l" 'set-left-margin)
-(define-key enriched-mode-map "\C-c\C-r" 'set-right-margin)
-
-;;;
-;;; Some functions dealing with text-properties, especially indentation
-;;;
-
-(defun enriched-map-property-regions (prop func &optional from to)
- "Apply a function to regions of the buffer based on a text property.
-For each contiguous region of the buffer for which the value of PROPERTY is
-eq, the FUNCTION will be called. Optional arguments FROM and TO specify the
-region over which to scan.
-
-The specified function receives three arguments: the VALUE of the property in
-the region, and the START and END of each region."
- (save-excursion
- (save-restriction
- (if to (narrow-to-region (point-min) to))
- (goto-char (or from (point-min)))
- (let ((begin (point))
- end
- (marker (make-marker))
- (val (get-text-property (point) prop)))
- (while (setq end (text-property-not-all begin (point-max) prop val))
- (move-marker marker end)
- (funcall func val begin (marker-position marker))
- (setq begin (marker-position marker)
- val (get-text-property marker prop)))
- (if (< begin (point-max))
- (funcall func val begin (point-max)))))))
-
-(put 'enriched-map-property-regions 'lisp-indent-hook 1)
-
-(defun enriched-insert-indentation (&optional from to)
- "Indent and justify each line in the region."
- (save-excursion
- (save-restriction
- (if to (narrow-to-region (point-min) to))
- (goto-char (or from (point-min)))
- (if (not (bolp)) (forward-line 1))
- (while (not (eobp))
- (if (eolp)
- nil ; skip blank lines
- (indent-to (current-left-margin))
- (justify-current-line t nil t))
- (forward-line 1)))))
-
-;;;
-;;; Encoding Files
-;;;
-
-;;;###autoload
-(defun enriched-encode (from to orig-buf)
- (if enriched-verbose (message "Enriched: encoding document..."))
- (save-restriction
- (narrow-to-region from to)
- (delete-to-left-margin)
- (unjustify-region)
- (goto-char from)
- (format-replace-strings '(("<" . "<<")))
- (format-insert-annotations
- (format-annotate-region from (point-max) enriched-translations
- 'enriched-make-annotation enriched-ignore))
- (goto-char from)
- (insert (if (stringp enriched-initial-annotation)
- enriched-initial-annotation
- (save-excursion
- ;; Eval this in the buffer we are annotating. This
- ;; fixes a bug which was saving incorrect File-Width
- ;; information, since we were looking at local
- ;; variables in the wrong buffer.
- (if orig-buf (set-buffer orig-buf))
- (funcall enriched-initial-annotation))))
- (enriched-map-property-regions 'hard
- (lambda (v b e)
- (if (and v (= ?\n (char-after b)))
- (progn (goto-char b) (insert "\n"))))
- (point) nil)
- (if enriched-verbose (message nil))
- ;; Return new end.
- (point-max)))
-
-(defun enriched-make-annotation (name positive)
- "Format an annotation called NAME.
-If POSITIVE is non-nil, this is the opening annotation, if nil, this is the
-matching close."
- (cond ((stringp name)
- (format enriched-annotation-format (if positive "" "/") name))
- ;; Otherwise it is an annotation with parameters, represented as a list
- (positive
- (let ((item (car name))
- (params (cdr name)))
- (concat (format enriched-annotation-format "" item)
- (mapconcat (lambda (i) (concat "<param>" i "</param>"))
- params ""))))
- (t (format enriched-annotation-format "/" (car name)))))
-
-(defun enriched-encode-other-face (old new)
- "Generate annotations for random face change.
-One annotation each for foreground color, background color, italic, etc."
- (cons (and old (enriched-face-ans old))
- (and new (enriched-face-ans new))))
-
-(defun enriched-face-ans (face)
- "Return annotations specifying FACE."
- (cond ((string-match "^fg:" (symbol-name face))
- (list (list "x-color" (substring (symbol-name face) 3))))
- ((string-match "^bg:" (symbol-name face))
- (list (list "x-bg-color" (substring (symbol-name face) 3))))
- ((let* ((fg (face-foreground face))
- (bg (face-background face))
- (props (face-font face t))
- (ans (cdr (format-annotate-single-property-change
- 'face nil props enriched-translations))))
- (if fg (setq ans (cons (list "x-color" fg) ans)))
- (if bg (setq ans (cons (list "x-bg-color" bg) ans)))
- ans))))
-
-;;;
-;;; Decoding files
-;;;
-
-;;;###autoload
-(defun enriched-decode (from to)
- (if enriched-verbose (message "Enriched: decoding document..."))
- (use-hard-newlines 1 'never)
- (save-excursion
- (save-restriction
- (narrow-to-region from to)
- (goto-char from)
-
- ;; Deal with header
- (let ((file-width (enriched-get-file-width)))
- (enriched-remove-header)
-
- ;; Deal with newlines
- (while (search-forward-regexp "\n\n+" nil t)
- (if (current-justification)
- (delete-char -1))
- (set-hard-newline-properties (match-beginning 0) (point)))
-
- ;; Translate annotations
- (format-deannotate-region from (point-max) enriched-translations
- 'enriched-next-annotation)
-
- ;; Indent or fill the buffer
- (cond (file-width ; File was filled to this width
- (setq fill-column file-width)
- (if enriched-verbose (message "Indenting..."))
- (enriched-insert-indentation))
- (t ; File was not filled.
- (if enriched-verbose (message "Filling paragraphs..."))
- (fill-region (point-min) (point-max))))
- (if enriched-verbose (message nil)))
- (point-max))))
-
-(defun enriched-next-annotation ()
- "Find and return next text/enriched annotation.
-Any \"<<\" strings encountered are converted to \"<\".
-Return value is \(begin end name positive-p), or nil if none was found."
- (while (and (search-forward "<" nil 1)
- (progn (goto-char (match-beginning 0))
- (not (looking-at enriched-annotation-regexp))))
- (forward-char 1)
- (if (= ?< (char-after (point)))
- (delete-char 1)
- ;; A single < that does not start an annotation is an error,
- ;; which we note and then ignore.
- (message "Warning: malformed annotation in file at %s"
- (1- (point)))))
- (if (not (eobp))
- (let* ((beg (match-beginning 0))
- (end (match-end 0))
- (name (downcase (buffer-substring
- (match-beginning 2) (match-end 2))))
- (pos (not (match-beginning 1))))
- (list beg end name pos))))
-
-(defun enriched-get-file-width ()
- "Look for file width information on this line."
- (save-excursion
- (if (search-forward "Text-Width: " (+ (point) 1000) t)
- (read (current-buffer)))))
-
-(defun enriched-remove-header ()
- "Remove file-format header at point."
- (while (looking-at "^[-A-Za-z]+: .*\n")
- (delete-region (point) (match-end 0)))
- (if (looking-at "^\n")
- (delete-char 1)))
-
-(defun enriched-decode-foreground (from to color)
- (let ((face (intern (concat "fg:" color))))
- (cond ((internal-find-face face))
- ((and window-system (facemenu-get-face face)))
- (window-system
- (message "Warning: color \"%s\" is not defined." color))
- ((make-face face)
- (message "Warning: Color \"%s\" can't be displayed." color)))
- (list from to 'face face)))
-
-(defun enriched-decode-background (from to color)
- (let ((face (intern (concat "bg:" color))))
- (cond ((internal-find-face face))
- ((and window-system (facemenu-get-face face)))
- (window-system
- (message "Warning: color \"%s\" is not defined." color))
- ((make-face face)
- (message "Warning: Color \"%s\" can't be displayed." color)))
- (list from to 'face face)))
-
-;;; enriched.el ends here
diff --git a/lisp/env.el b/lisp/env.el
deleted file mode 100644
index c0e68f63412..00000000000
--- a/lisp/env.el
+++ /dev/null
@@ -1,114 +0,0 @@
-;;; env.el --- functions to manipulate environment variables.
-
-;; Copyright (C) 1991, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: processes, unix
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; UNIX processes inherit a list of name-to-string associations from their
-;; parents called their `environment'; these are commonly used to control
-;; program options. This package permits you to set environment variables
-;; to be passed to any sub-process run under Emacs.
-
-;;; Code:
-
-;; History list for environment variable names.
-(defvar read-envvar-name-history nil)
-
-(defun read-envvar-name (prompt &optional mustmatch)
- "Read environment variable name, prompting with PROMPT.
-Optional second arg MUSTMATCH, if non-nil, means require existing envvar name.
-If it is also not t, RET does not exit if it does non-null completion."
- (completing-read prompt
- (mapcar (function
- (lambda (enventry)
- (list (substring enventry 0
- (string-match "=" enventry)))))
- process-environment)
- nil mustmatch nil 'read-envvar-name-history))
-
-;; History list for VALUE argument to setenv.
-(defvar setenv-history nil)
-
-;;;###autoload
-(defun setenv (variable &optional value unset)
- "Set the value of the environment variable named VARIABLE to VALUE.
-VARIABLE should be a string. VALUE is optional; if not provided or is
-`nil', the environment variable VARIABLE will be removed.
-
-Interactively, a prefix argument means to unset the variable.
-Interactively, the current value (if any) of the variable
-appears at the front of the history list when you type in the new value.
-
-This function works by modifying `process-environment'."
- (interactive
- (if current-prefix-arg
- (list (read-envvar-name "Clear environment variable: " 'exact) nil t)
- (let* ((var (read-envvar-name "Set environment variable: " nil))
- (oldval (getenv var))
- newval
- oldhist)
- ;; Don't put the current value on the history
- ;; if it is already there.
- (if (equal oldval (car setenv-history))
- (setq oldval nil))
- ;; Now if OLDVAL is non-nil, we should add it to the history.
- (if oldval
- (setq setenv-history (cons oldval setenv-history)))
- (setq oldhist setenv-history)
- (setq newval (read-from-minibuffer (format "Set %s to value: " var)
- nil nil nil 'setenv-history))
- ;; If we added the current value to the history, remove it.
- ;; Note that read-from-minibuffer may have added the new value.
- ;; Don't remove that!
- (if oldval
- (if (eq oldhist setenv-history)
- (setq setenv-history (cdr setenv-history))
- (setcdr setenv-history (cdr (cdr setenv-history)))))
- ;; Here finally we specify the args to give call setenv with.
- (list var newval))))
- (if unset (setq value nil))
- (if (string-match "=" variable)
- (error "Environment variable name `%s' contains `='" variable)
- (let ((pattern (concat "\\`" (regexp-quote (concat variable "="))))
- (case-fold-search nil)
- (scan process-environment)
- found)
- (if (string-equal "TZ" variable)
- (set-time-zone-rule value))
- (while scan
- (cond ((string-match pattern (car scan))
- (setq found t)
- (if (eq nil value)
- (setq process-environment (delq (car scan) process-environment))
- (setcar scan (concat variable "=" value)))
- (setq scan nil)))
- (setq scan (cdr scan)))
- (or found
- (if value
- (setq process-environment
- (cons (concat variable "=" value)
- process-environment)))))))
-
-(provide 'env)
-
-;;; env.el ends here
diff --git a/lisp/expand.el b/lisp/expand.el
deleted file mode 100644
index 1b46d4b3f68..00000000000
--- a/lisp/expand.el
+++ /dev/null
@@ -1,496 +0,0 @@
-;; expand.el --- make abbreviations more usable.
-
-;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Frederic Lepied <Frederic.Lepied@sugix.frmug.org>
-;; Maintainer: Frederic Lepied <Frederic.Lepied@sugix.frmug.org>
-;; Keywords: abbrev
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-;;
-;; This package defines abbrevs which expand into structured constructs
-;; for certain languages. The construct is indented for you,
-;; and contains slots for you to fill in other text.
-
-;; These abbrevs expand only at the end of a line and when not in a comment
-;; or a string.
-;;
-;; Look at the Sample: section for emacs-lisp, perl and c expand lists.
-;; For example for c-mode, you could declare your abbrev table with :
-;;
-;; (defconst c-expand-list
-;; '(("if" "if () {\n \n} else {\n \n}" (5 10 21))
-;; ("ifn" "if () {}" (5 8))
-;; ("uns" "unsigned ")
-;; ("for" "for(; ; ) {\n\n}" (5 7 9 13))
-;; ("switch" "switch () {\n\n}" (9 13))
-;; ("case" "case :\n\nbreak;\n" (6 8 16))
-;; ("do" "do {\n\n} while ();" (6 16))
-;; ("while" "while () {\n\n}" (8 12))
-;; ("default" "default:\n\nbreak;" 10)
-;; ("main" "int\nmain(int argc, char * argv[])\n{\n\n}\n" 37))
-;; "Expansions for C mode")
-;;
-;; and enter Abbrev mode with the following hook :
-;;
-;; (add-hook 'c-mode-hook (function (lambda ()
-;; (expand-add-abbrevs c-mode-abbrev-table c-expand-list)
-;; (abbrev-mode))))
-;;
-;; you can also init some post-process hooks :
-;;
-;; (add-hook 'expand-load-hook
-;; (function
-;; (lambda ()
-;; (add-hook 'expand-expand-hook 'indent-according-to-mode)
-;; (add-hook 'expand-jump-hook 'indent-according-to-mode))))
-;;
-;; Remarks:
-;;
-;; Many thanks to Heddy Boubaker <boubaker@cenatls.cena.dgac.fr>,
-;; Jerome Santini <santini@chambord.univ-orleans.fr>,
-;; Jari Aalto <jaalto@tre.tele.nokia.fi>.
-;;
-;; Please send me a word to give me your feeling about this feature or
-;; to explain me how you use it (your expansions table for example) using
-;; the function expand-submit-report.
-
-;;; Constants:
-
-(defvar expand-load-hook nil
- "Hooks run when `expand.el' is loaded.")
-
-(defvar expand-expand-hook nil
- "Hooks run when an abbrev made by `expand-add-abbrevs' is expanded.")
-
-(defvar expand-jump-hook nil
- "Hooks run by `expand-jump-to-previous-slot' and `expand-jump-to-next-slot'.")
-
-;;; Samples:
-
-(define-skeleton expand-c-for-skeleton "For loop skeleton"
- "Loop var: "
- "for(" str _ @ "=0; " str @ "; " str @ ") {" \n
- @ _ \n
- "}" >
- )
-
-(defconst expand-c-sample-expand-list
- '(("if" "if () {\n \n} else {\n \n}" (5 10 21))
- ("ifn" "if () {}" (5 8))
- ("uns" "unsigned ")
- ("for" expand-c-for-skeleton)
- ("switch" "switch () {\n\n}" (9 13))
- ("case" "case :\n\nbreak;\n" (6 8 16))
- ("do" "do {\n\n} while ();" (6 16))
- ("while" "while () {\n\n}" (8 12))
- ("default" "default:\n\nbreak;" 10)
- ("main" "int\nmain(int argc, char * argv[])\n{\n\n}\n" 37))
- "Expansions for C mode. See `expand-add-abbrevs'.")
-
-;; lisp example from Jari Aalto <jaalto@tre.tele.nokia.fi>
-(defconst expand-sample-lisp-mode-expand-list
- (list
- (list
- "defu"
- (concat
- "(defun ()\n"
- " \"\"\n"
- " (interactive)\n"
- " (let* (\n"
- " )\n"
- " \n"
- " ))")
- (list 8 11 16 32 43 59))
-
- (list
- "defs"
- (concat
- "(defsubst ()\n"
- " \"\"\n"
- " (interactive)\n"
- " )")
- (list 11 14 19 23 39))
-
- (list
- "defm"
- (concat
- "(defmacro ()\n"
- " \"\"\n"
- " (` \n"
- " ))")
- (list 11 13 18 25))
-
- (list
- "defa"
- (concat
- "(defadvice (around act)\n"
- " \"\"\n"
- " \n"
- " )")
- (list 12 22 32 36))
-
- (list
- "defc"
- "(defconst nil\n \"\")\n"
- (list 11 13 20))
-
- (list
- "defv"
- "(defvar nil\n \"\")\n"
- (list 9 11 18))
-
- (list
- "let"
- "(let* (\n)\n "
- (list 8 13))
-
- (list
- "sav"
- "(save-excursion\n \n)"
- (list 18))
-
- (list
- "aut"
- "(autoload ' \"\" t t)\n"
- (list 12 14))
-
- )
- "Expansions for Lisp mode. See `expand-add-abbrevs'.")
-
-;; perl example from Jari Aalto <jaalto@tre.tele.nokia.fi>
-(defconst expand-sample-perl-mode-expand-list
- (list
- (list
- ;; This is default perl4 subroutine template
- ;;
- "sub"
- (concat
- "#" (make-string 70 ?-) "\n"
- "sub {\n"
- " # DESCRIPTION\n"
- " # \n"
- " # \n"
- " # INPUT\n"
- " # \n"
- " # \n"
- " # RETURN\n"
- " # \n"
- "\n"
- " local( $f ) = \"$lib.\";\n" ;; Function name AFTER period
- " local() = @_;\n" ;; func arguments here
- " \n"
- " \n}\n"
- )
- (list 77 88 120 146 159 176))
-
- (list
- "for" ; foreach
- (concat
- "for ( )\n"
- "{\n\n\}"
- )
- (list 7 12))
-
- (list
- "whi" ; foreach
- (concat
- "while ( )\n"
- "{\n\n\}"
- )
- (list 9 15))
-
-
- ;; The normal "if" can be used like
- ;; print $F "xxxxxx" if defined @arr;
- ;;
- (list
- "iff"
- (concat
- "if ( )\n"
- "{\n\n\}"
- )
- (list 6 12))
-
- (list "loc" "local( $ );" (list 9))
- (list "my" "my( $ );" (list 6))
- (list "ope" "open(,\"\")\t|| die \"$f: Can't open [$]\";" (list 6 8 36))
- (list "clo" "close ;" 7)
- (list "def" "defined " (list 9))
- (list "und" "undef ;" (list 7))
-
- ;; There is no ending colon, because they can be in statement
- ;; defined $REXP_NOT_NEW && (print "xxxxx" );
- ;;
- (list "pr" "print " 7)
- (list "pf" "printf " 8)
-
-
- (list "gre" "grep( //, );" (list 8 11))
- (list "pus" "push( , );" (list 7 9))
- (list "joi" "join( '', );" (list 7 11))
- (list "rtu" "return ;" (list 8))
-
- )
- "Expansions for Perl mode. See `expand-add-abbrevs'.")
-
-;;; Code:
-
-;;;###autoload
-(defun expand-add-abbrevs (table abbrevs)
- "Add a list of abbrev to abbrev table TABLE.
-ABBREVS is a list of abbrev definitions; each abbrev description entry
-has the form (ABBREV EXPANSION ARG).
-
-ABBREV is the abbreviation to replace.
-
-EXPANSION is the replacement string or a function which will make the
-expansion. For example you, could use the DMacros or skeleton packages
-to generate such functions.
-
-ARG is an optional argument which can be a number or a list of
-numbers. If ARG is a number, point is placed ARG chars from the
-beginning of the expanded text.
-
-If ARG is a list of numbers, point is placed according to the first
-member of the list, but you can visit the other specified positions
-cyclicaly with the functions `expand-jump-to-previous-slot' and
-`expand-jump-to-next-slot'.
-
-If ARG is omitted, point is placed at the end of the expanded text."
-
- (if (null abbrevs)
- table
- (expand-add-abbrev table (nth 0 (car abbrevs)) (nth 1 (car abbrevs))
- (nth 2 (car abbrevs)))
- (expand-add-abbrevs table (cdr abbrevs))))
-
-(defvar expand-list nil "Temporary variable used by the Expand package.")
-
-(defvar expand-pos nil
- "If non nil, stores a vector containing markers to positions defined by the last expansion.
-This variable is local to a buffer.")
-(make-variable-buffer-local 'expand-pos)
-
-(defvar expand-index 0
- "Index of the last marker used in `expand-pos'.
-This variable is local to a buffer.")
-(make-variable-buffer-local 'expand-index)
-
-(defvar expand-point nil
- "End of the expanded region.
-This variable is local to a buffer.")
-(make-variable-buffer-local 'expand-point)
-
-(defun expand-add-abbrev (table abbrev expansion arg)
- "Add one abbreviation and provide the hook to move to the specified positions."
- (let* ((string-exp (if (and (symbolp expansion) (fboundp expansion))
- nil
- expansion))
- (position (if (and arg string-exp)
- (if (listp arg)
- (- (length expansion) (1- (car arg)))
- (- (length expansion) (1- arg)))
- 0)))
- (define-abbrev
- table
- abbrev
- (vector string-exp
- position
- (if (and (listp arg)
- (not (null arg)))
- (cons (length string-exp) arg)
- nil)
- (if (and (symbolp expansion) (fboundp expansion))
- expansion
- nil)
- )
- 'expand-abbrev-hook)))
-
-(put 'expand-abbrev-hook 'no-self-insert t)
-(defun expand-abbrev-hook ()
- "Abbrev hook used to do the expansion job of expand abbrevs.
-See `expand-add-abbrevs'."
- ;; Expand only at the end of a line if we are near a word that has
- ;; an abbrev built from expand-add-abbrev.
- (if (and (eolp)
- (not (expand-in-literal)))
- (let ((p (point)))
- (setq expand-point nil)
- ;; don't expand if the preceding char isn't a word constituent
- (if (and (eq (char-syntax (preceding-char))
- ?w)
- (expand-do-expansion))
- (progn
- ;; expand-point tells us if we have inserted the text
- ;; ourself or if it is the hook which has done the job.
- (if expand-point
- (progn
- (if (vectorp expand-list)
- (expand-build-marks expand-point))
- (indent-region p expand-point nil))
- ;; an outside function can set expand-list to a list of
- ;; markers in reverse order.
- (if (listp expand-list)
- (setq expand-index 0
- expand-pos (expand-list-to-markers expand-list)
- expand-list nil)))
- (run-hooks 'expand-expand-hook)
- t))))
- )
-
-(defun expand-do-expansion ()
- (delete-backward-char (length last-abbrev-text))
- (let* ((vect (symbol-value last-abbrev))
- (text (aref vect 0))
- (position (aref vect 1))
- (jump-args (aref vect 2))
- (hook (aref vect 3)))
- (cond (text
- (insert text)
- (setq expand-point (point))))
- (if jump-args
- (funcall 'expand-build-list (car jump-args) (cdr jump-args)))
- (if position
- (backward-char position))
- (if hook
- (funcall hook))
- t)
- )
-
-(defun expand-abbrev-from-expand (word)
- "Test if an abbrev has a hook."
- (or
- (and (intern-soft word local-abbrev-table)
- (symbol-function (intern-soft word local-abbrev-table)))
- (and (intern-soft word global-abbrev-table)
- (symbol-function (intern-soft word global-abbrev-table)))))
-
-(defun expand-previous-word ()
- "Return the previous word."
- (save-excursion
- (let ((p (point)))
- (backward-word 1)
- (buffer-substring p (point)))))
-
-;;;###autoload
-(defun expand-jump-to-previous-slot ()
- "Move the cursor to the previous slot in the last abbrev expansion.
-This is used only in conjunction with `expand-add-abbrevs'."
- (interactive)
- (if expand-pos
- (progn
- (setq expand-index (1- expand-index))
- (if (< expand-index 0)
- (setq expand-index (1- (length expand-pos))))
- (goto-char (aref expand-pos expand-index))
- (run-hooks 'expand-jump-hook))))
-
-;;;###autoload
-(defun expand-jump-to-next-slot ()
- "Move the cursor to the next slot in the last abbrev expansion.
-This is used only in conjunction with `expand-add-abbrevs'."
- (interactive)
- (if expand-pos
- (progn
- (setq expand-index (1+ expand-index))
- (if (>= expand-index (length expand-pos))
- (setq expand-index 0))
- (goto-char (aref expand-pos expand-index))
- (run-hooks 'expand-jump-hook))))
-
-;;;###autoload (define-key ctl-x-map "ap" 'expand-jump-to-previous-slot)
-;;;###autoload (define-key ctl-x-map "an" 'expand-jump-to-next-slot)
-
-(defun expand-build-list (len l)
- "Build a vector of offset positions from the list of positions."
- (expand-clear-markers)
- (setq expand-list (vconcat l))
- (let ((i 0)
- (lenlist (length expand-list)))
- (while (< i lenlist)
- (aset expand-list i (- len (1- (aref expand-list i))))
- (setq i (1+ i))))
- )
-
-(defun expand-build-marks (p)
- "Transform the offsets vector into a marker vector."
- (if expand-list
- (progn
- (setq expand-index 0)
- (setq expand-pos (make-vector (length expand-list) nil))
- (let ((i (1- (length expand-list))))
- (while (>= i 0)
- (aset expand-pos i (copy-marker (- p (aref expand-list i))))
- (setq i (1- i))))
- (setq expand-list nil))))
-
-(defun expand-clear-markers ()
- "Make the markers point nowhere."
- (if expand-pos
- (progn
- (let ((i (1- (length expand-pos))))
- (while (>= i 0)
- (set-marker (aref expand-pos i) nil)
- (setq i (1- i))))
- (setq expand-pos nil))))
-
-(defun expand-in-literal ()
- "Test if we are in a comment or in a string."
- (save-excursion
- (let* ((lim (or (save-excursion
- (beginning-of-defun)
- (point))
- (point-min)))
- (here (point))
- (state (parse-partial-sexp lim (point))))
- (cond
- ((nth 3 state) 'string)
- ((nth 4 state) 'comment)
- (t nil)))))
-
-;; support functions to add marks to jump from outside function
-
-(defun expand-list-to-markers (l)
- "Transform a list of markers in reverse order into a vector in the correct order."
- (let* ((len (1- (length l)))
- (loop len)
- (v (make-vector (+ len 1) nil)))
- (while (>= loop 0)
- (aset v loop (if (markerp (car l)) (car l) (copy-marker (car l))))
- (setq l (cdr l)
- loop (1- loop)))
- v))
-
-;; integration with skeleton.el
-;; Used in `skeleton-end-hook' to fetch the positions for @ skeleton tags.
-;; See `skeleton-insert'.
-(defun expand-skeleton-end-hook ()
- (if skeleton-positions
- (setq expand-list skeleton-positions)))
-
-(add-hook 'skeleton-end-hook (function expand-skeleton-end-hook))
-
-(provide 'expand)
-
-;; run load hooks
-(run-hooks 'expand-load-hook)
-
-;;; expand.el ends here
diff --git a/lisp/facemenu.el b/lisp/facemenu.el
deleted file mode 100644
index 07d5f52c628..00000000000
--- a/lisp/facemenu.el
+++ /dev/null
@@ -1,658 +0,0 @@
-;;; facemenu.el --- create a face menu for interactively adding fonts to text
-
-;; Copyright (c) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Boris Goldowsky <boris@gnu.ai.mit.edu>
-;; Keywords: faces
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This file defines a menu of faces (bold, italic, etc) which allows you to
-;; set the face used for a region of the buffer. Some faces also have
-;; keybindings, which are shown in the menu. Faces with names beginning with
-;; "fg:" or "bg:", as in "fg:red", are treated specially.
-;; Such faces are assumed to consist only of a foreground (if "fg:") or
-;; background (if "bg:") color. They are thus put into the color submenus
-;; rather than the general Face submenu. These faces can also be
-;; automatically created by selecting the "Other..." menu items in the
-;; "Foreground" and "Background" submenus.
-;;
-;; The menu also contains submenus for indentation and justification-changing
-;; commands.
-
-;;; Usage:
-;; Selecting a face from the menu or typing the keyboard equivalent will
-;; change the region to use that face. If you use transient-mark-mode and the
-;; region is not active, the face will be remembered and used for the next
-;; insertion. It will be forgotten if you move point or make other
-;; modifications before inserting or typing anything.
-;;
-;; Faces can be selected from the keyboard as well.
-;; The standard keybindings are M-g (or ESC g) + letter:
-;; M-g i = "set italic", M-g b = "set bold", etc.
-
-;;; Customization:
-;; An alternative set of keybindings that may be easier to type can be set up
-;; using "Alt" or "Hyper" keys. This requires that you either have or create
-;; an Alt or Hyper key on your keyboard. On my keyboard, there is a key
-;; labeled "Alt", but to make it act as an Alt key I have to put this command
-;; into my .xinitrc:
-;; xmodmap -e "add Mod3 = Alt_L"
-;; Or, I can make it into a Hyper key with this:
-;; xmodmap -e "keysym Alt_L = Hyper_L" -e "add Mod2 = Hyper_L"
-;; Check with local X-perts for how to do it on your system.
-;; Then you can define your keybindings with code like this in your .emacs:
-;; (setq facemenu-keybindings
-;; '((default . [?\H-d])
-;; (bold . [?\H-b])
-;; (italic . [?\H-i])
-;; (bold-italic . [?\H-l])
-;; (underline . [?\H-u])))
-;; (setq facemenu-keymap global-map)
-;; (setq facemenu-key nil)
-;; (define-key global-map [?\H-c] 'facemenu-set-foreground) ; set fg color
-;; (define-key global-map [?\H-C] 'facemenu-set-background) ; set bg color
-;; (require 'facemenu)
-;;
-;; The order of the faces that appear in the menu and their keybindings can be
-;; controlled by setting the variables `facemenu-keybindings' and
-;; `facemenu-new-faces-at-end'. List faces that you don't use in documents
-;; (eg, `region') in `facemenu-unlisted-faces'.
-
-;;; Known Problems:
-;; Bold and Italic do not combine to create bold-italic if you select them
-;; both, although most other combinations (eg bold + underline + some color)
-;; do the intuitive thing.
-;;
-;; There is at present no way to display what the faces look like in
-;; the menu itself.
-;;
-;; `list-faces-display' shows the faces in a different order than
-;; this menu, which could be confusing. I do /not/ sort the list
-;; alphabetically, because I like the default order: it puts the most
-;; basic, common fonts first.
-;;
-;; Please send me any other problems, comments or ideas.
-
-;;; Code:
-
-(provide 'facemenu)
-
-;;; Provide some binding for startup:
-;;;###autoload (define-key global-map "\M-g" 'facemenu-keymap)
-;;;###autoload (autoload 'facemenu-keymap "facemenu" "Keymap for face-changing commands." t 'keymap)
-
-(defvar facemenu-key "\M-g"
- "Prefix key to use for facemenu commands.")
-
-(defvar facemenu-keybindings
- '((default . "d")
- (bold . "b")
- (italic . "i")
- (bold-italic . "l") ; {bold} intersect {italic} = {l}
- (underline . "u"))
- "Alist of interesting faces and keybindings.
-Each element is itself a list: the car is the name of the face,
-the next element is the key to use as a keyboard equivalent of the menu item;
-the binding is made in facemenu-keymap.
-
-The faces specifically mentioned in this list are put at the top of
-the menu, in the order specified. All other faces which are defined,
-except for those in `facemenu-unlisted-faces', are listed after them,
-but get no keyboard equivalents.
-
-If you change this variable after loading facemenu.el, you will need to call
-`facemenu-update' to make it take effect.")
-
-(defvar facemenu-new-faces-at-end t
- "Where in the menu to insert newly-created faces.
-This should be nil to put them at the top of the menu, or t to put them
-just before \"Other\" at the end.")
-
-(defvar facemenu-unlisted-faces
- '(modeline region secondary-selection highlight scratch-face)
- "List of faces not to include in the Face menu.
-You can set this list before loading facemenu.el, or add a face to it before
-creating that face if you do not want it to be listed. If you change the
-variable so as to eliminate faces that have already been added to the menu,
-call `facemenu-update' to recalculate the menu contents.
-
-If this variable is t, no faces will be added to the menu. This is useful for
-temporarily turning off the feature that automatically adds faces to the menu
-when they are created.")
-
-;;;###autoload
-(defvar facemenu-face-menu
- (let ((map (make-sparse-keymap "Face")))
- (define-key map "o" (cons "Other..." 'facemenu-set-face))
- map)
- "Menu keymap for faces.")
-;;;###autoload
-(defalias 'facemenu-face-menu facemenu-face-menu)
-
-;;;###autoload
-(defvar facemenu-foreground-menu
- (let ((map (make-sparse-keymap "Foreground Color")))
- (define-key map "o" (cons "Other..." 'facemenu-set-foreground))
- map)
- "Menu keymap for foreground colors.")
-;;;###autoload
-(defalias 'facemenu-foreground-menu facemenu-foreground-menu)
-
-;;;###autoload
-(defvar facemenu-background-menu
- (let ((map (make-sparse-keymap "Background Color")))
- (define-key map "o" (cons "Other..." 'facemenu-set-background))
- map)
- "Menu keymap for background colors")
-;;;###autoload
-(defalias 'facemenu-background-menu facemenu-background-menu)
-
-;;;###autoload
-(defvar facemenu-special-menu
- (let ((map (make-sparse-keymap "Special")))
- (define-key map [?s] (cons "Remove Special" 'facemenu-remove-special))
- (define-key map [?t] (cons "Intangible" 'facemenu-set-intangible))
- (define-key map [?v] (cons "Invisible" 'facemenu-set-invisible))
- (define-key map [?r] (cons "Read-Only" 'facemenu-set-read-only))
- map)
- "Menu keymap for non-face text-properties.")
-;;;###autoload
-(defalias 'facemenu-special-menu facemenu-special-menu)
-
-;;;###autoload
-(defvar facemenu-justification-menu
- (let ((map (make-sparse-keymap "Justification")))
- (define-key map [?c] (cons "Center" 'set-justification-center))
- (define-key map [?b] (cons "Full" 'set-justification-full))
- (define-key map [?r] (cons "Right" 'set-justification-right))
- (define-key map [?l] (cons "Left" 'set-justification-left))
- (define-key map [?u] (cons "Unfilled" 'set-justification-none))
- map)
- "Submenu for text justification commands.")
-;;;###autoload
-(defalias 'facemenu-justification-menu facemenu-justification-menu)
-
-;;;###autoload
-(defvar facemenu-indentation-menu
- (let ((map (make-sparse-keymap "Indentation")))
- (define-key map [decrease-right-margin]
- (cons "Indent Right Less" 'decrease-right-margin))
- (define-key map [increase-right-margin]
- (cons "Indent Right More" 'increase-right-margin))
- (define-key map [decrease-left-margin]
- (cons "Indent Less" 'decrease-left-margin))
- (define-key map [increase-left-margin]
- (cons "Indent More" 'increase-left-margin))
- map)
- "Submenu for indentation commands.")
-;;;###autoload
-(defalias 'facemenu-indentation-menu facemenu-indentation-menu)
-
-;; This is split up to avoid an overlong line in loaddefs.el.
-;;;###autoload
-(defvar facemenu-menu nil
- "Facemenu top-level menu keymap.")
-;;;###autoload
-(setq facemenu-menu (make-sparse-keymap "Text Properties"))
-;;;###autoload
-(let ((map facemenu-menu))
- (define-key map [dc] (cons "Display Colors" 'list-colors-display))
- (define-key map [df] (cons "Display Faces" 'list-faces-display))
- (define-key map [dp] (cons "List Properties" 'list-text-properties-at))
- (define-key map [ra] (cons "Remove All" 'facemenu-remove-all))
- (define-key map [rm] (cons "Remove Properties" 'facemenu-remove-props))
- (define-key map [s1] (list "-----------------")))
-;;;###autoload
-(let ((map facemenu-menu))
- (define-key map [in] (cons "Indentation" 'facemenu-indentation-menu))
- (define-key map [ju] (cons "Justification" 'facemenu-justification-menu))
- (define-key map [s2] (list "-----------------"))
- (define-key map [sp] (cons "Special Properties" 'facemenu-special-menu))
- (define-key map [bg] (cons "Background Color" 'facemenu-background-menu))
- (define-key map [fg] (cons "Foreground Color" 'facemenu-foreground-menu))
- (define-key map [fc] (cons "Face" 'facemenu-face-menu)))
-;;;###autoload
-(defalias 'facemenu-menu facemenu-menu)
-
-(defvar facemenu-keymap
- (let ((map (make-sparse-keymap "Set face")))
- (define-key map "o" (cons "Other..." 'facemenu-set-face))
- map)
- "Keymap for face-changing commands.
-`Facemenu-update' fills in the keymap according to the bindings
-requested in `facemenu-keybindings'.")
-(defalias 'facemenu-keymap facemenu-keymap)
-
-
-(defvar facemenu-add-face-function nil
- "Function called at beginning of text to change or `nil'.
-This function is passed the FACE to set and END of text to change, and must
-return a string which is inserted. It may set `facemenu-end-add-face'.")
-
-(defvar facemenu-end-add-face nil
- "String to insert or function called at end of text to change or `nil'.
-This function is passed the FACE to set, and must return a string which is
-inserted.")
-
-(defvar facemenu-remove-face-function nil
- "When non-`nil' function called to remove faces.
-This function is passed the START and END of text to change.
-May also be `t' meaning to use `facemenu-add-face-function'.")
-
-;;; Internal Variables
-
-(defvar facemenu-color-alist nil
- ;; Don't initialize here; that doesn't work if preloaded.
- "Alist of colors, used for completion.
-If null, `facemenu-read-color' will set it.")
-
-(defun facemenu-update ()
- "Add or update the \"Face\" menu in the menu bar.
-You can call this to update things if you change any of the menu configuration
-variables."
- (interactive)
-
- ;; Global bindings:
- (define-key global-map [C-down-mouse-2] 'facemenu-menu)
- (if facemenu-key (define-key global-map facemenu-key 'facemenu-keymap))
-
- ;; Add each defined face to the menu.
- (facemenu-iterate 'facemenu-add-new-face
- (facemenu-complete-face-list facemenu-keybindings)))
-
-;;;###autoload
-(defun facemenu-set-face (face &optional start end)
- "Add FACE to the region or next character typed.
-It will be added to the top of the face list; any faces lower on the list that
-will not show through at all will be removed.
-
-Interactively, the face to be used is read with the minibuffer.
-
-If the region is active and there is no prefix argument,
-this command sets the region to the requested face.
-
-Otherwise, this command specifies the face for the next character
-inserted. Moving point or switching buffers before
-typing a character to insert cancels the specification."
- (interactive (list (read-face-name "Use face: ")))
- (barf-if-buffer-read-only)
- (facemenu-add-new-face face)
- (if (and mark-active (not current-prefix-arg))
- (let ((start (or start (region-beginning)))
- (end (or end (region-end))))
- (facemenu-add-face face start end))
- (facemenu-add-face face)))
-
-;;;###autoload
-(defun facemenu-set-foreground (color &optional start end)
- "Set the foreground color of the region or next character typed.
-The color is prompted for. A face named `fg:color' is used \(or created).
-If the region is active, it will be set to the requested face. If
-it is inactive \(even if mark-even-if-inactive is set) the next
-character that is typed \(via `self-insert-command') will be set to
-the selected face. Moving point or switching buffers before
-typing a character cancels the request."
- (interactive (list (facemenu-read-color "Foreground color: ")))
- (let ((face (intern (concat "fg:" color))))
- (or (facemenu-get-face face)
- (error "Unknown color: %s" color))
- (facemenu-set-face face start end)))
-
-;;;###autoload
-(defun facemenu-set-background (color &optional start end)
- "Set the background color of the region or next character typed.
-The color is prompted for. A face named `bg:color' is used \(or created).
-If the region is active, it will be set to the requested face. If
-it is inactive \(even if mark-even-if-inactive is set) the next
-character that is typed \(via `self-insert-command') will be set to
-the selected face. Moving point or switching buffers before
-typing a character cancels the request."
- (interactive (list (facemenu-read-color "Background color: ")))
- (let ((face (intern (concat "bg:" color))))
- (or (facemenu-get-face face)
- (error "Unknown color: %s" color))
- (facemenu-set-face face start end)))
-
-;;;###autoload
-(defun facemenu-set-face-from-menu (face start end)
- "Set the face of the region or next character typed.
-This function is designed to be called from a menu; the face to use
-is the menu item's name.
-
-If the region is active and there is no prefix argument,
-this command sets the region to the requested face.
-
-Otherwise, this command specifies the face for the next character
-inserted. Moving point or switching buffers before
-typing a character to insert cancels the specification."
- (interactive (list last-command-event
- (if (and mark-active (not current-prefix-arg))
- (region-beginning))
- (if (and mark-active (not current-prefix-arg))
- (region-end))))
- (barf-if-buffer-read-only)
- (facemenu-get-face face)
- (if start
- (facemenu-add-face face start end)
- (facemenu-add-face face)))
-
-;;;###autoload
-(defun facemenu-set-invisible (start end)
- "Make the region invisible.
-This sets the `invisible' text property; it can be undone with
-`facemenu-remove-special'."
- (interactive "r")
- (put-text-property start end 'invisible t))
-
-;;;###autoload
-(defun facemenu-set-intangible (start end)
- "Make the region intangible: disallow moving into it.
-This sets the `intangible' text property; it can be undone with
-`facemenu-remove-special'."
- (interactive "r")
- (put-text-property start end 'intangible t))
-
-;;;###autoload
-(defun facemenu-set-read-only (start end)
- "Make the region unmodifiable.
-This sets the `read-only' text property; it can be undone with
-`facemenu-remove-special'."
- (interactive "r")
- (put-text-property start end 'read-only t))
-
-;;;###autoload
-(defun facemenu-remove-props (start end)
- "Remove all text properties that facemenu added to region."
- (interactive "*r") ; error if buffer is read-only despite the next line.
- (let ((inhibit-read-only t))
- (remove-text-properties
- start end '(face nil invisible nil intangible nil
- read-only nil category nil))))
-
-;;;###autoload
-(defun facemenu-remove-all (start end)
- "Remove all text properties from the region."
- (interactive "*r") ; error if buffer is read-only despite the next line.
- (let ((inhibit-read-only t))
- (set-text-properties start end nil)))
-
-;;;###autoload
-(defun facemenu-remove-special (start end)
- "Remove all the \"special\" text properties from the region.
-These special properties include `invisible', `intangible' and `read-only'."
- (interactive "*r") ; error if buffer is read-only despite the next line.
- (let ((inhibit-read-only t))
- (remove-text-properties
- start end '(invisible nil intangible nil read-only nil))))
-
-;;;###autoload
-(defun list-text-properties-at (p)
- "Pop up a buffer listing text-properties at LOCATION."
- (interactive "d")
- (let ((props (text-properties-at p))
- category
- str)
- (if (null props)
- (message "None")
- (if (and (not (cdr (cdr props)))
- (not (eq (car props) 'category))
- (< (length (setq str (format "Text property at %d: %s %S"
- p (car props) (car (cdr props)))))
- (frame-width)))
- (message "%s" str)
- (with-output-to-temp-buffer "*Text Properties*"
- (princ (format "Text properties at %d:\n\n" p))
- (while props
- (if (eq (car props) 'category)
- (setq category (car (cdr props))))
- (princ (format "%-20s %S\n"
- (car props) (car (cdr props))))
- (setq props (cdr (cdr props))))
- (if category
- (progn
- (setq props (symbol-plist category))
- (princ (format "\nCategory %s:\n\n" category))
- (while props
- (princ (format "%-20s %S\n"
- (car props) (car (cdr props))))
- (if (eq (car props) 'category)
- (setq category (car (cdr props))))
- (setq props (cdr (cdr props)))))))))))
-
-;;;###autoload
-(defun facemenu-read-color (&optional prompt)
- "Read a color using the minibuffer."
- (let ((col (completing-read (or prompt "Color: ")
- (or facemenu-color-alist
- (if window-system
- (mapcar 'list (x-defined-colors))))
- nil t)))
- (if (equal "" col)
- nil
- col)))
-
-;;;###autoload
-(defun list-colors-display (&optional list)
- "Display names of defined colors, and show what they look like.
-If the optional argument LIST is non-nil, it should be a list of
-colors to display. Otherwise, this command computes a list
-of colors that the current display can handle."
- (interactive)
- (if (and (null list) window-system)
- (progn
- (setq list (x-defined-colors))
- ;; Delete duplicate colors.
- (let ((l list))
- (while (cdr l)
- (if (facemenu-color-equal (car l) (car (cdr l)))
- (setcdr l (cdr (cdr l)))
- (setq l (cdr l)))))))
- (with-output-to-temp-buffer "*Colors*"
- (save-excursion
- (set-buffer standard-output)
- (let ((facemenu-unlisted-faces t)
- s)
- (while list
- (setq s (point))
- (insert (car list))
- (indent-to 20)
- (put-text-property s (point) 'face
- (facemenu-get-face
- (intern (concat "bg:" (car list)))))
- (setq s (point))
- (insert " " (car list) "\n")
- (put-text-property s (point) 'face
- (facemenu-get-face
- (intern (concat "fg:" (car list)))))
- (setq list (cdr list)))))))
-
-(defun facemenu-color-equal (a b)
- "Return t if colors A and B are the same color.
-A and B should be strings naming colors.
-This function queries the window-system server to find out what the
-color names mean. It returns nil if the colors differ or if it can't
-determine the correct answer."
- (cond ((equal a b) t)
- ((and (memq window-system '(x w32))
- (equal (x-color-values a) (x-color-values b))))
- ((eq window-system 'pc)
- (and (x-color-defined-p a) (x-color-defined-p b)
- (eq (msdos-color-translate a) (msdos-color-translate b))))))
-
-(defun facemenu-add-face (face &optional start end)
- "Add FACE to text between START and END.
-If START is `nil' or START to END is empty, add FACE to next typed character
-instead. For each section of that region that has a different face property,
-FACE will be consed onto it, and other faces that are completely hidden by
-that will be removed from the list.
-If `facemenu-add-face-function' and maybe `facemenu-end-add-face' are non-`nil'
-they are used to set the face information.
-
-As a special case, if FACE is `default', then the region is left with NO face
-text property. Otherwise, selecting the default face would not have any
-effect. See `facemenu-remove-face-function'."
- (interactive "*xFace: \nr")
- (if (and (eq face 'default)
- (not (eq facemenu-remove-face-function t)))
- (if facemenu-remove-face-function
- (funcall facemenu-remove-face-function start end)
- (if (and start (< start end))
- (remove-text-properties start end '(face default))
- (setq self-insert-face 'default
- self-insert-face-command this-command)))
- (if facemenu-add-face-function
- (save-excursion
- (if end (goto-char end))
- (save-excursion
- (if start (goto-char start))
- (insert-before-markers
- (funcall facemenu-add-face-function face end)))
- (if facemenu-end-add-face
- (insert (if (stringp facemenu-end-add-face)
- facemenu-end-add-face
- (funcall facemenu-end-add-face face)))))
- (if (and start (< start end))
- (let ((part-start start) part-end)
- (while (not (= part-start end))
- (setq part-end (next-single-property-change part-start 'face
- nil end))
- (let ((prev (get-text-property part-start 'face)))
- (put-text-property part-start part-end 'face
- (if (null prev)
- face
- (facemenu-active-faces
- (cons face
- (if (listp prev)
- prev
- (list prev)))))))
- (setq part-start part-end)))
- (setq self-insert-face (if (eq last-command self-insert-face-command)
- (cons face (if (listp self-insert-face)
- self-insert-face
- (list self-insert-face)))
- face)
- self-insert-face-command this-command)))))
-
-(defun facemenu-active-faces (face-list &optional frame)
- "Return from FACE-LIST those faces that would be used for display.
-This means each face attribute is not specified in a face earlier in FACE-LIST
-and such a face is therefore active when used to display text.
-If the optional argument FRAME is given, use the faces in that frame; otherwise
-use the selected frame. If t, then the global, non-frame faces are used."
- (let* ((mask-atts (copy-sequence (internal-get-face (car face-list) frame)))
- (active-list (list (car face-list)))
- (face-list (cdr face-list))
- (mask-len (length mask-atts)))
- (while face-list
- (if (let ((face-atts (internal-get-face (car face-list) frame))
- (i mask-len) (useful nil))
- (while (> (setq i (1- i)) 1)
- (and (aref face-atts i) (not (aref mask-atts i))
- (aset mask-atts i (setq useful t))))
- useful)
- (setq active-list (cons (car face-list) active-list)))
- (setq face-list (cdr face-list)))
- (nreverse active-list)))
-
-(defun facemenu-get-face (symbol)
- "Make sure FACE exists.
-If not, it is created. If it is created and is of the form `fg:color', then
-set the foreground to that color. If of the form `bg:color', set the
-background. In any case, add it to the appropriate menu. Returns the face,
-or nil if given a bad color."
- (if (or (internal-find-face symbol)
- (let* ((face (make-face symbol))
- (name (symbol-name symbol))
- (color (substring name 3)))
- (cond ((string-match "^fg:" name)
- (set-face-foreground face color)
- (and window-system
- (x-color-defined-p color)))
- ((string-match "^bg:" name)
- (set-face-background face color)
- (and window-system
- (x-color-defined-p color)))
- (t))))
- symbol))
-
-(defun facemenu-add-new-face (face)
- "Add a FACE to the appropriate Face menu.
-Automatically called when a new face is created."
- (let* ((name (symbol-name face))
- (menu (cond ((string-match "^fg:" name)
- (setq name (substring name 3))
- 'facemenu-foreground-menu)
- ((string-match "^bg:" name)
- (setq name (substring name 3))
- 'facemenu-background-menu)
- (t 'facemenu-face-menu)))
- (key (cdr (assoc face facemenu-keybindings)))
- function menu-val)
- (cond ((eq t facemenu-unlisted-faces))
- ((memq face facemenu-unlisted-faces))
- (key ; has a keyboard equivalent. These go at the front.
- (setq function (intern (concat "facemenu-set-" name)))
- (fset function
- (` (lambda () (interactive)
- (facemenu-set-face (quote (, face))))))
- (define-key 'facemenu-keymap key (cons name function))
- (define-key menu key (cons name function)))
- ((facemenu-iterate ; check if equivalent face is already in the menu
- (lambda (m) (and (listp m)
- (symbolp (car m))
- (face-equal (car m) face)))
- (cdr (symbol-function menu))))
- (t ; No keyboard equivalent. Figure out where to put it:
- (setq key (vector face)
- function 'facemenu-set-face-from-menu
- menu-val (symbol-function menu))
- (if (and facemenu-new-faces-at-end
- (> (length menu-val) 3))
- (define-key-after menu-val key (cons name function)
- (car (nth (- (length menu-val) 3) menu-val)))
- (define-key menu key (cons name function))))))
- nil) ; Return nil for facemenu-iterate
-
-(defun facemenu-complete-face-list (&optional oldlist)
- "Return list of all faces that look different.
-Starts with given ALIST of faces, and adds elements only if they display
-differently from any face already on the list.
-The faces on ALIST will end up at the end of the returned list, in reverse
-order."
- (let ((list (nreverse (mapcar 'car oldlist))))
- (facemenu-iterate
- (lambda (new-face)
- (if (not (memq new-face list))
- (setq list (cons new-face list)))
- nil)
- (nreverse (face-list)))
- list))
-
-(defun facemenu-iterate (func iterate-list)
- "Apply FUNC to each element of LIST until one returns non-nil.
-Returns the non-nil value it found, or nil if all were nil."
- (while (and iterate-list (not (funcall func (car iterate-list))))
- (setq iterate-list (cdr iterate-list)))
- (car iterate-list))
-
-(facemenu-update)
-
-;;; facemenu.el ends here
diff --git a/lisp/faces.el b/lisp/faces.el
deleted file mode 100644
index 6d1e195b140..00000000000
--- a/lisp/faces.el
+++ /dev/null
@@ -1,1313 +0,0 @@
-;;; faces.el --- Lisp interface to the c "face" structure
-
-;; Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Mostly derived from Lucid.
-
-;;; Code:
-
-(eval-when-compile
- ;; These used to be defsubsts, now they're subrs. Avoid losing if we're
- ;; being compiled with an old Emacs that still has defsubrs in it.
- (put 'face-name 'byte-optimizer nil)
- (put 'face-id 'byte-optimizer nil)
- (put 'face-font 'byte-optimizer nil)
- (put 'face-foreground 'byte-optimizer nil)
- (put 'face-background 'byte-optimizer nil)
- (put 'face-stipple 'byte-optimizer nil)
- (put 'face-underline-p 'byte-optimizer nil)
- (put 'set-face-font 'byte-optimizer nil)
- (put 'set-face-foreground 'byte-optimizer nil)
- (put 'set-face-background 'byte-optimizer nil)
- (put 'set-face-stipple 'byte-optimizer nil)
- (put 'set-face-underline-p 'byte-optimizer nil))
-
-;;;; Functions for manipulating face vectors.
-
-;;; A face vector is a vector of the form:
-;;; [face NAME ID FONT FOREGROUND BACKGROUND STIPPLE UNDERLINE]
-
-;;; Type checkers.
-(defsubst internal-facep (x)
- (and (vectorp x) (= (length x) 8) (eq (aref x 0) 'face)))
-
-(defun facep (x)
- "Return t if X is a face name or an internal face vector."
- (and (or (internal-facep x)
- (and (symbolp x) (assq x global-face-data)))
- t))
-
-(defmacro internal-check-face (face)
- (` (or (internal-facep (, face))
- (signal 'wrong-type-argument (list 'internal-facep (, face))))))
-
-;;; Accessors.
-(defun face-name (face)
- "Return the name of face FACE."
- (aref (internal-get-face face) 1))
-
-(defun face-id (face)
- "Return the internal ID number of face FACE."
- (aref (internal-get-face face) 2))
-
-(defun face-font (face &optional frame)
- "Return the font name of face FACE, or nil if it is unspecified.
-If the optional argument FRAME is given, report on face FACE in that frame.
-If FRAME is t, report on the defaults for face FACE (for new frames).
- The font default for a face is either nil, or a list
- of the form (bold), (italic) or (bold italic).
-If FRAME is omitted or nil, use the selected frame."
- (aref (internal-get-face face frame) 3))
-
-(defun face-foreground (face &optional frame)
- "Return the foreground color name of face FACE, or nil if unspecified.
-If the optional argument FRAME is given, report on face FACE in that frame.
-If FRAME is t, report on the defaults for face FACE (for new frames).
-If FRAME is omitted or nil, use the selected frame."
- (aref (internal-get-face face frame) 4))
-
-(defun face-background (face &optional frame)
- "Return the background color name of face FACE, or nil if unspecified.
-If the optional argument FRAME is given, report on face FACE in that frame.
-If FRAME is t, report on the defaults for face FACE (for new frames).
-If FRAME is omitted or nil, use the selected frame."
- (aref (internal-get-face face frame) 5))
-
-(defun face-stipple (face &optional frame)
- "Return the stipple pixmap name of face FACE, or nil if unspecified.
-If the optional argument FRAME is given, report on face FACE in that frame.
-If FRAME is t, report on the defaults for face FACE (for new frames).
-If FRAME is omitted or nil, use the selected frame."
- (aref (internal-get-face face frame) 6))
-
-(defalias 'face-background-pixmap 'face-stipple)
-
-(defun face-underline-p (face &optional frame)
- "Return t if face FACE is underlined.
-If the optional argument FRAME is given, report on face FACE in that frame.
-If FRAME is t, report on the defaults for face FACE (for new frames).
-If FRAME is omitted or nil, use the selected frame."
- (aref (internal-get-face face frame) 7))
-
-
-;;; Mutators.
-
-(defun set-face-font (face font &optional frame)
- "Change the font of face FACE to FONT (a string).
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
- (interactive (internal-face-interactive "font"))
- (if (stringp font) (setq font (x-resolve-font-name font 'default frame)))
- (internal-set-face-1 face 'font font 3 frame))
-
-(defun set-face-foreground (face color &optional frame)
- "Change the foreground color of face FACE to COLOR (a string).
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
- (interactive (internal-face-interactive "foreground"))
- (internal-set-face-1 face 'foreground color 4 frame))
-
-(defvar face-default-stipple "gray3"
- "Default stipple pattern used on monochrome displays.
-This stipple pattern is used on monochrome displays
-instead of shades of gray for a face background color.
-See `set-face-stipple' for possible values for this variable.")
-
-(defun face-color-gray-p (color &optional frame)
- "Return t if COLOR is a shade of gray (or white or black).
-FRAME specifies the frame and thus the display for interpreting COLOR."
- (let* ((values (x-color-values color frame))
- (r (nth 0 values))
- (g (nth 1 values))
- (b (nth 2 values)))
- (and values
- (< (abs (- r g)) (/ (max 1 (abs r) (abs g)) 20))
- (< (abs (- g b)) (/ (max 1 (abs g) (abs b)) 20))
- (< (abs (- b r)) (/ (max 1 (abs b) (abs r)) 20)))))
-
-(defun set-face-background (face color &optional frame)
- "Change the background color of face FACE to COLOR (a string).
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
- (interactive (internal-face-interactive "background"))
- ;; For a specific frame, use gray stipple instead of gray color
- ;; if the display does not support a gray color.
- (if (and frame (not (eq frame t)) color
- ;; Check for support for foreground, not for background!
- ;; face-color-supported-p is smart enough to know
- ;; that grays are "supported" as background
- ;; because we are supposed to use stipple for them!
- (not (face-color-supported-p frame color nil)))
- (set-face-stipple face face-default-stipple frame)
- (if (null frame)
- (let ((frames (frame-list)))
- (while frames
- (set-face-background (face-name face) color (car frames))
- (setq frames (cdr frames)))
- (set-face-background face color t)
- color)
- (internal-set-face-1 face 'background color 5 frame))))
-
-(defun set-face-stipple (face pixmap &optional frame)
- "Change the stipple pixmap of face FACE to PIXMAP.
-PIXMAP should be a string, the name of a file of pixmap data.
-The directories listed in the `x-bitmap-file-path' variable are searched.
-
-Alternatively, PIXMAP may be a list of the form (WIDTH HEIGHT DATA)
-where WIDTH and HEIGHT are the size in pixels,
-and DATA is a string, containing the raw bits of the bitmap.
-
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
- (interactive (internal-face-interactive-stipple "stipple"))
- (internal-set-face-1 face 'background-pixmap pixmap 6 frame))
-
-(defalias 'set-face-background-pixmap 'set-face-stipple)
-
-(defun set-face-underline-p (face underline-p &optional frame)
- "Specify whether face FACE is underlined. (Yes if UNDERLINE-P is non-nil.)
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame."
- (interactive (internal-face-interactive "underline-p" "underlined"))
- (internal-set-face-1 face 'underline underline-p 7 frame))
-
-(defun modify-face-read-string (face default name alist)
- (let ((value
- (completing-read
- (if default
- (format "Set face %s %s (default %s): "
- face name (downcase default))
- (format "Set face %s %s: " face name))
- alist)))
- (cond ((equal value "none")
- nil)
- ((equal value "")
- default)
- (t value))))
-
-(defun modify-face (face foreground background stipple
- bold-p italic-p underline-p &optional frame)
- "Change the display attributes for face FACE.
-If the optional FRAME argument is provided, change only
-in that frame; otherwise change each frame.
-
-FOREGROUND and BACKGROUND should be a colour name string (or list of strings to
-try) or nil. STIPPLE should be a stipple pattern name string or nil.
-If nil, means do not change the display attribute corresponding to that arg.
-
-BOLD-P, ITALIC-P, and UNDERLINE-P specify whether the face should be set bold,
-in italic, and underlined, respectively. If neither nil or t, means do not
-change the display attribute corresponding to that arg.
-
-If called interactively, prompts for a face name and face attributes."
- (interactive
- (let* ((completion-ignore-case t)
- (face (symbol-name (read-face-name "Modify face: ")))
- (colors (mapcar 'list x-colors))
- (stipples (mapcar 'list (apply 'nconc
- (mapcar 'directory-files
- x-bitmap-file-path))))
- (foreground (modify-face-read-string
- face (face-foreground (intern face))
- "foreground" colors))
- (background (modify-face-read-string
- face (face-background (intern face))
- "background" colors))
- ;; If the stipple value is a list (WIDTH HEIGHT DATA),
- ;; represent that as a string by printing it out.
- (old-stipple-string
- (if (stringp (face-stipple (intern face)))
- (face-stipple (intern face))
- (if (face-stipple (intern face))
- (prin1-to-string (face-stipple (intern face))))))
- (new-stipple-string
- (modify-face-read-string
- face old-stipple-string
- "stipple" stipples))
- ;; Convert the stipple value text we read
- ;; back to a list if it looks like one.
- ;; This makes the assumption that a pixmap file name
- ;; won't start with an open-paren.
- (stipple
- (and new-stipple-string
- (if (string-match "^(" new-stipple-string)
- (read new-stipple-string)
- new-stipple-string)))
- (bold-p (y-or-n-p (concat "Should face " face " be bold ")))
- (italic-p (y-or-n-p (concat "Should face " face " be italic ")))
- (underline-p (y-or-n-p (concat "Should face " face " be underlined ")))
- (all-frames-p (y-or-n-p (concat "Modify face " face " in all frames "))))
- (message "Face %s: %s" face
- (mapconcat 'identity
- (delq nil
- (list (and foreground (concat (downcase foreground) " foreground"))
- (and background (concat (downcase background) " background"))
- (and stipple (concat (downcase new-stipple-string) " stipple"))
- (and bold-p "bold") (and italic-p "italic")
- (and underline-p "underline"))) ", "))
- (list (intern face) foreground background stipple
- bold-p italic-p underline-p
- (if all-frames-p nil (selected-frame)))))
- (condition-case nil
- (face-try-color-list 'set-face-foreground face foreground frame)
- (error nil))
- (condition-case nil
- (face-try-color-list 'set-face-background face background frame)
- (error nil))
- (condition-case nil
- (set-face-stipple face stipple frame)
- (error nil))
- (cond ((eq bold-p nil) (make-face-unbold face frame t))
- ((eq bold-p t) (make-face-bold face frame t)))
- (cond ((eq italic-p nil) (make-face-unitalic face frame t))
- ((eq italic-p t) (make-face-italic face frame t)))
- (if (memq underline-p '(nil t))
- (set-face-underline-p face underline-p frame))
- (and (interactive-p) (redraw-display)))
-
-;;;; Associating face names (symbols) with their face vectors.
-
-(defvar global-face-data nil
- "Internal data for face support functions. Not for external use.
-This is an alist associating face names with the default values for
-their parameters. Newly created frames get their data from here.")
-
-(defun face-list ()
- "Returns a list of all defined face names."
- (mapcar 'car global-face-data))
-
-(defun internal-find-face (name &optional frame)
- "Retrieve the face named NAME. Return nil if there is no such face.
-If the optional argument FRAME is given, this gets the face NAME for
-that frame; otherwise, it uses the selected frame.
-If FRAME is the symbol t, then the global, non-frame face is returned.
-If NAME is already a face, it is simply returned."
- (if (and (eq frame t) (not (symbolp name)))
- (setq name (face-name name)))
- (if (symbolp name)
- (cdr (assq name
- (if (eq frame t)
- global-face-data
- (frame-face-alist (or frame (selected-frame))))))
- (internal-check-face name)
- name))
-
-(defun internal-get-face (name &optional frame)
- "Retrieve the face named NAME; error if there is none.
-If the optional argument FRAME is given, this gets the face NAME for
-that frame; otherwise, it uses the selected frame.
-If FRAME is the symbol t, then the global, non-frame face is returned.
-If NAME is already a face, it is simply returned."
- (or (internal-find-face name frame)
- (internal-check-face name)))
-
-
-(defun internal-set-face-1 (face name value index frame)
- (let ((inhibit-quit t))
- (if (null frame)
- (let ((frames (frame-list)))
- (while frames
- (internal-set-face-1 (face-name face) name value index (car frames))
- (setq frames (cdr frames)))
- (aset (internal-get-face (if (symbolp face) face (face-name face)) t)
- index value)
- value)
- (or (eq frame t)
- (set-face-attribute-internal (face-id face) name value frame))
- (aset (internal-get-face face frame) index value))))
-
-
-(defun read-face-name (prompt)
- (let (face)
- (while (= (length face) 0)
- (setq face (completing-read prompt
- (mapcar '(lambda (x) (list (symbol-name x)))
- (face-list))
- nil t)))
- (intern face)))
-
-(defun internal-face-interactive (what &optional bool)
- (let* ((fn (intern (concat "face-" what)))
- (prompt (concat "Set " what " of face"))
- (face (read-face-name (concat prompt ": ")))
- (default (if (fboundp fn)
- (or (funcall fn face (selected-frame))
- (funcall fn 'default (selected-frame)))))
- (value (if bool
- (y-or-n-p (concat "Should face " (symbol-name face)
- " be " bool "? "))
- (read-string (concat prompt " " (symbol-name face) " to: ")
- default))))
- (list face (if (equal value "") nil value))))
-
-(defun internal-face-interactive-stipple (what)
- (let* ((fn (intern (concat "face-" what)))
- (prompt (concat "Set " what " of face"))
- (face (read-face-name (concat prompt ": ")))
- (default (if (fboundp fn)
- (or (funcall fn face (selected-frame))
- (funcall fn 'default (selected-frame)))))
- ;; If the stipple value is a list (WIDTH HEIGHT DATA),
- ;; represent that as a string by printing it out.
- (old-stipple-string
- (if (stringp (face-stipple face))
- (face-stipple face)
- (if (null (face-stipple face))
- nil
- (prin1-to-string (face-stipple face)))))
- (new-stipple-string
- (read-string
- (concat prompt " " (symbol-name face) " to: ")
- old-stipple-string))
- ;; Convert the stipple value text we read
- ;; back to a list if it looks like one.
- ;; This makes the assumption that a pixmap file name
- ;; won't start with an open-paren.
- (stipple
- (if (string-match "^(" new-stipple-string)
- (read new-stipple-string)
- new-stipple-string)))
- (list face (if (equal stipple "") nil stipple))))
-
-(defun make-face (name)
- "Define a new FACE on all frames.
-You can modify the font, color, etc of this face with the set-face- functions.
-If the face already exists, it is unmodified."
- (interactive "SMake face: ")
- (or (internal-find-face name)
- (let ((face (make-vector 8 nil)))
- (aset face 0 'face)
- (aset face 1 name)
- (let* ((frames (frame-list))
- (inhibit-quit t)
- (id (internal-next-face-id)))
- (make-face-internal id)
- (aset face 2 id)
- (while frames
- (set-frame-face-alist (car frames)
- (cons (cons name (copy-sequence face))
- (frame-face-alist (car frames))))
- (setq frames (cdr frames)))
- (setq global-face-data (cons (cons name face) global-face-data)))
- ;; when making a face after frames already exist
- (if (memq window-system '(x w32))
- (make-face-x-resource-internal face))
- ;; add to menu
- (if (fboundp 'facemenu-add-new-face)
- (facemenu-add-new-face name))
- face))
- name)
-
-;; Fill in a face by default based on X resources, for all existing frames.
-;; This has to be done when a new face is made.
-(defun make-face-x-resource-internal (face &optional frame set-anyway)
- (cond ((null frame)
- (let ((frames (frame-list)))
- (while frames
- (if (memq (framep (car frames)) '(x w32))
- (make-face-x-resource-internal (face-name face)
- (car frames) set-anyway))
- (setq frames (cdr frames)))))
- (t
- (setq face (internal-get-face (face-name face) frame))
- ;;
- ;; These are things like "attributeForeground" instead of simply
- ;; "foreground" because people tend to do things like "*foreground",
- ;; which would cause all faces to be fully qualified, making faces
- ;; inherit attributes in a non-useful way. So we've made them slightly
- ;; less obvious to specify in order to make them work correctly in
- ;; more random environments.
- ;;
- ;; I think these should be called "face.faceForeground" instead of
- ;; "face.attributeForeground", but they're the way they are for
- ;; hysterical reasons.
- ;;
- (let* ((name (symbol-name (face-name face)))
- (fn (or (x-get-resource (concat name ".attributeFont")
- "Face.AttributeFont")
- (and set-anyway (face-font face))))
- (fg (or (x-get-resource (concat name ".attributeForeground")
- "Face.AttributeForeground")
- (and set-anyway (face-foreground face))))
- (bg (or (x-get-resource (concat name ".attributeBackground")
- "Face.AttributeBackground")
- (and set-anyway (face-background face))))
- (bgp (or (x-get-resource (concat name ".attributeStipple")
- "Face.AttributeStipple")
- (x-get-resource (concat name ".attributeBackgroundPixmap")
- "Face.AttributeBackgroundPixmap")
- (and set-anyway (face-stipple face))))
- (ulp (let ((resource (x-get-resource
- (concat name ".attributeUnderline")
- "Face.AttributeUnderline")))
- (if resource
- (member (downcase resource) '("on" "true"))
- (and set-anyway (face-underline-p face)))))
- )
- (if fn
- (condition-case ()
- (cond ((string= fn "italic")
- (make-face-italic face))
- ((string= fn "bold")
- (make-face-bold face))
- ((string= fn "bold-italic")
- (make-face-bold-italic face))
- (t
- (set-face-font face fn frame)))
- (error
- (if (member fn '("italic" "bold" "bold-italic"))
- (message "no %s version found for face `%s'" fn name)
- (message "font `%s' not found for face `%s'" fn name)))))
- (if fg
- (condition-case ()
- (set-face-foreground face fg frame)
- (error (message "color `%s' not allocated for face `%s'" fg name))))
- (if bg
- (condition-case ()
- (set-face-background face bg frame)
- (error (message "color `%s' not allocated for face `%s'" bg name))))
- (if bgp
- (condition-case ()
- (set-face-stipple face bgp frame)
- (error (message "pixmap `%s' not found for face `%s'" bgp name))))
- (if (or ulp set-anyway)
- (set-face-underline-p face ulp frame))
- )))
- face)
-
-(defun copy-face (old-face new-face &optional frame new-frame)
- "Define a face just like OLD-FACE, with name NEW-FACE.
-If NEW-FACE already exists as a face, it is modified to be like OLD-FACE.
-If it doesn't already exist, it is created.
-
-If the optional argument FRAME is given as a frame,
-NEW-FACE is changed on FRAME only.
-If FRAME is t, the frame-independent default specification for OLD-FACE
-is copied to NEW-FACE.
-If FRAME is nil, copying is done for the frame-independent defaults
-and for each existing frame.
-If the optional fourth argument NEW-FRAME is given,
-copy the information from face OLD-FACE on frame FRAME
-to NEW-FACE on frame NEW-FRAME."
- (or new-frame (setq new-frame frame))
- (let ((inhibit-quit t))
- (if (null frame)
- (let ((frames (frame-list)))
- (while frames
- (copy-face old-face new-face (car frames))
- (setq frames (cdr frames)))
- (copy-face old-face new-face t))
- (setq old-face (internal-get-face old-face frame))
- (setq new-face (or (internal-find-face new-face new-frame)
- (make-face new-face)))
- (condition-case nil
- ;; A face that has a global symbolic font modifier such as `bold'
- ;; might legitimately get an error here.
- ;; Use the frame's default font in that case.
- (set-face-font new-face (face-font old-face frame) new-frame)
- (error
- (set-face-font new-face nil new-frame)))
- (set-face-foreground new-face (face-foreground old-face frame) new-frame)
- (set-face-background new-face (face-background old-face frame) new-frame)
- (set-face-stipple new-face
- (face-stipple old-face frame)
- new-frame)
- (set-face-underline-p new-face (face-underline-p old-face frame)
- new-frame))
- new-face))
-
-(defun face-equal (face1 face2 &optional frame)
- "True if the faces FACE1 and FACE2 display in the same way."
- (setq face1 (internal-get-face face1 frame)
- face2 (internal-get-face face2 frame))
- (and (equal (face-foreground face1 frame) (face-foreground face2 frame))
- (equal (face-background face1 frame) (face-background face2 frame))
- (equal (face-font face1 frame) (face-font face2 frame))
- (eq (face-underline-p face1 frame) (face-underline-p face2 frame))
- (equal (face-stipple face1 frame)
- (face-stipple face2 frame))))
-
-(defun face-differs-from-default-p (face &optional frame)
- "True if face FACE displays differently from the default face, on FRAME.
-A face is considered to be ``the same'' as the default face if it is
-actually specified in the same way (equivalent fonts, etc) or if it is
-fully unspecified, and thus inherits the attributes of any face it
-is displayed on top of.
-
-The optional argument FRAME specifies which frame to test;
-if FRAME is t, test the default for new frames.
-If FRAME is nil or omitted, test the selected frame."
- (let ((default (internal-get-face 'default frame)))
- (setq face (internal-get-face face frame))
- (not (and (or (equal (face-foreground default frame)
- (face-foreground face frame))
- (null (face-foreground face frame)))
- (or (equal (face-background default frame)
- (face-background face frame))
- (null (face-background face frame)))
- (or (equal (face-font default frame) (face-font face frame))
- (null (face-font face frame)))
- (or (equal (face-stipple default frame)
- (face-stipple face frame))
- (null (face-stipple face frame)))
- (equal (face-underline-p default frame)
- (face-underline-p face frame))
- ))))
-
-(defun face-nontrivial-p (face &optional frame)
- "True if face FACE has some non-nil attribute.
-The optional argument FRAME specifies which frame to test;
-if FRAME is t, test the default for new frames.
-If FRAME is nil or omitted, test the selected frame."
- (setq face (internal-get-face face frame))
- (or (face-foreground face frame)
- (face-background face frame)
- (face-font face frame)
- (face-stipple face frame)
- (face-underline-p face frame)))
-
-
-(defun invert-face (face &optional frame)
- "Swap the foreground and background colors of face FACE.
-If the face doesn't specify both foreground and background, then
-set its foreground and background to the default background and foreground."
- (interactive (list (read-face-name "Invert face: ")))
- (setq face (internal-get-face face frame))
- (let ((fg (face-foreground face frame))
- (bg (face-background face frame)))
- (if (or fg bg)
- (progn
- (set-face-foreground face bg frame)
- (set-face-background face fg frame))
- (let* ((frame-bg (cdr (assq 'background-color (frame-parameters frame))))
- (default-bg (or (face-background 'default frame)
- frame-bg))
- (frame-fg (cdr (assq 'foreground-color (frame-parameters frame))))
- (default-fg (or (face-foreground 'default frame)
- frame-fg)))
- (set-face-foreground face default-bg frame)
- (set-face-background face default-fg frame))))
- face)
-
-
-(defun internal-try-face-font (face font &optional frame)
- "Like set-face-font, but returns nil on failure instead of an error."
- (condition-case ()
- (set-face-font face font frame)
- (error nil)))
-
-;; Manipulating font names.
-
-(defvar x-font-regexp nil)
-(defvar x-font-regexp-head nil)
-(defvar x-font-regexp-weight nil)
-(defvar x-font-regexp-slant nil)
-
-(defconst x-font-regexp-weight-subnum 1)
-(defconst x-font-regexp-slant-subnum 2)
-(defconst x-font-regexp-swidth-subnum 3)
-(defconst x-font-regexp-adstyle-subnum 4)
-
-;;; Regexps matching font names in "Host Portable Character Representation."
-;;;
-(let ((- "[-?]")
- (foundry "[^-]+")
- (family "[^-]+")
- (weight "\\(bold\\|demibold\\|medium\\)") ; 1
-; (weight\? "\\(\\*\\|bold\\|demibold\\|medium\\|\\)") ; 1
- (weight\? "\\([^-]*\\)") ; 1
- (slant "\\([ior]\\)") ; 2
-; (slant\? "\\([ior?*]?\\)") ; 2
- (slant\? "\\([^-]?\\)") ; 2
-; (swidth "\\(\\*\\|normal\\|semicondensed\\|\\)") ; 3
- (swidth "\\([^-]*\\)") ; 3
-; (adstyle "\\(\\*\\|sans\\|\\)") ; 4
- (adstyle "\\([^-]*\\)") ; 4
- (pixelsize "[0-9]+")
- (pointsize "[0-9][0-9]+")
- (resx "[0-9][0-9]+")
- (resy "[0-9][0-9]+")
- (spacing "[cmp?*]")
- (avgwidth "[0-9]+")
- (registry "[^-]+")
- (encoding "[^-]+")
- )
- (setq x-font-regexp
- (concat "\\`\\*?[-?*]"
- foundry - family - weight\? - slant\? - swidth - adstyle -
- pixelsize - pointsize - resx - resy - spacing - avgwidth -
- registry - encoding "\\*?\\'"
- ))
- (setq x-font-regexp-head
- (concat "\\`[-?*]" foundry - family - weight\? - slant\?
- "\\([-*?]\\|\\'\\)"))
- (setq x-font-regexp-slant (concat - slant -))
- (setq x-font-regexp-weight (concat - weight -))
- nil)
-
-(defun x-resolve-font-name (pattern &optional face frame)
- "Return a font name matching PATTERN.
-All wildcards in PATTERN become substantiated.
-If PATTERN is nil, return the name of the frame's base font, which never
-contains wildcards.
-Given optional arguments FACE and FRAME, return a font which is
-also the same size as FACE on FRAME, or fail."
- (or (symbolp face)
- (setq face (face-name face)))
- (and (eq frame t)
- (setq frame nil))
- (if pattern
- ;; Note that x-list-fonts has code to handle a face with nil as its font.
- (let ((fonts (x-list-fonts pattern face frame 1)))
- (or fonts
- (if face
- (if (string-match "\\*" pattern)
- (if (null (face-font face))
- (error "No matching fonts are the same height as the frame default font")
- (error "No matching fonts are the same height as face `%s'" face))
- (if (null (face-font face))
- (error "Height of font `%s' doesn't match the frame default font"
- pattern)
- (error "Height of font `%s' doesn't match face `%s'"
- pattern face)))
- (error "No fonts match `%s'" pattern)))
- (car fonts))
- (cdr (assq 'font (frame-parameters (selected-frame))))))
-
-(defun x-frob-font-weight (font which)
- (let ((case-fold-search t))
- (cond ((string-match x-font-regexp font)
- (concat (substring font 0
- (match-beginning x-font-regexp-weight-subnum))
- which
- (substring font (match-end x-font-regexp-weight-subnum)
- (match-beginning x-font-regexp-adstyle-subnum))
- ;; Replace the ADD_STYLE_NAME field with *
- ;; because the info in it may not be the same
- ;; for related fonts.
- "*"
- (substring font (match-end x-font-regexp-adstyle-subnum))))
- ((string-match x-font-regexp-head font)
- (concat (substring font 0 (match-beginning 1)) which
- (substring font (match-end 1))))
- ((string-match x-font-regexp-weight font)
- (concat (substring font 0 (match-beginning 1)) which
- (substring font (match-end 1)))))))
-
-(defun x-frob-font-slant (font which)
- (let ((case-fold-search t))
- (cond ((string-match x-font-regexp font)
- (concat (substring font 0
- (match-beginning x-font-regexp-slant-subnum))
- which
- (substring font (match-end x-font-regexp-slant-subnum)
- (match-beginning x-font-regexp-adstyle-subnum))
- ;; Replace the ADD_STYLE_NAME field with *
- ;; because the info in it may not be the same
- ;; for related fonts.
- "*"
- (substring font (match-end x-font-regexp-adstyle-subnum))))
- ((string-match x-font-regexp-head font)
- (concat (substring font 0 (match-beginning 2)) which
- (substring font (match-end 2))))
- ((string-match x-font-regexp-slant font)
- (concat (substring font 0 (match-beginning 1)) which
- (substring font (match-end 1)))))))
-
-(defun x-make-font-bold (font)
- "Given an X font specification, make a bold version of it.
-If that can't be done, return nil."
- (x-frob-font-weight font "bold"))
-
-(defun x-make-font-demibold (font)
- "Given an X font specification, make a demibold version of it.
-If that can't be done, return nil."
- (x-frob-font-weight font "demibold"))
-
-(defun x-make-font-unbold (font)
- "Given an X font specification, make a non-bold version of it.
-If that can't be done, return nil."
- (x-frob-font-weight font "medium"))
-
-(defun x-make-font-italic (font)
- "Given an X font specification, make an italic version of it.
-If that can't be done, return nil."
- (x-frob-font-slant font "i"))
-
-(defun x-make-font-oblique (font) ; you say tomayto...
- "Given an X font specification, make an oblique version of it.
-If that can't be done, return nil."
- (x-frob-font-slant font "o"))
-
-(defun x-make-font-unitalic (font)
- "Given an X font specification, make a non-italic version of it.
-If that can't be done, return nil."
- (x-frob-font-slant font "r"))
-
-;;; non-X-specific interface
-
-(defun make-face-bold (face &optional frame noerror)
- "Make the font of the given face be bold, if possible.
-If NOERROR is non-nil, return nil on failure."
- (interactive (list (read-face-name "Make which face bold: ")))
- (if (and (eq frame t) (listp (face-font face t)))
- (set-face-font face (if (memq 'italic (face-font face t))
- '(bold italic) '(bold))
- t)
- (let (font)
- (if (null frame)
- (let ((frames (frame-list)))
- ;; Make this face bold in global-face-data.
- (make-face-bold face t noerror)
- ;; Make this face bold in each frame.
- (while frames
- (make-face-bold face (car frames) noerror)
- (setq frames (cdr frames))))
- (setq face (internal-get-face face frame))
- (setq font (or (face-font face frame)
- (face-font face t)))
- (if (listp font)
- (setq font nil))
- (setq font (or font
- (face-font 'default frame)
- (cdr (assq 'font (frame-parameters frame)))))
- (or (and font (make-face-bold-internal face frame font))
- ;; We failed to find a bold version of the font.
- noerror
- (error "No bold version of %S" font))))))
-
-(defun make-face-bold-internal (face frame font)
- (let (f2)
- (or (and (setq f2 (x-make-font-bold font))
- (internal-try-face-font face f2 frame))
- (and (setq f2 (x-make-font-demibold font))
- (internal-try-face-font face f2 frame)))))
-
-(defun make-face-italic (face &optional frame noerror)
- "Make the font of the given face be italic, if possible.
-If NOERROR is non-nil, return nil on failure."
- (interactive (list (read-face-name "Make which face italic: ")))
- (if (and (eq frame t) (listp (face-font face t)))
- (set-face-font face (if (memq 'bold (face-font face t))
- '(bold italic) '(italic))
- t)
- (let (font)
- (if (null frame)
- (let ((frames (frame-list)))
- ;; Make this face italic in global-face-data.
- (make-face-italic face t noerror)
- ;; Make this face italic in each frame.
- (while frames
- (make-face-italic face (car frames) noerror)
- (setq frames (cdr frames))))
- (setq face (internal-get-face face frame))
- (setq font (or (face-font face frame)
- (face-font face t)))
- (if (listp font)
- (setq font nil))
- (setq font (or font
- (face-font 'default frame)
- (cdr (assq 'font (frame-parameters frame)))))
- (or (and font (make-face-italic-internal face frame font))
- ;; We failed to find an italic version of the font.
- noerror
- (error "No italic version of %S" font))))))
-
-(defun make-face-italic-internal (face frame font)
- (let (f2)
- (or (and (setq f2 (x-make-font-italic font))
- (internal-try-face-font face f2 frame))
- (and (setq f2 (x-make-font-oblique font))
- (internal-try-face-font face f2 frame)))))
-
-(defun make-face-bold-italic (face &optional frame noerror)
- "Make the font of the given face be bold and italic, if possible.
-If NOERROR is non-nil, return nil on failure."
- (interactive (list (read-face-name "Make which face bold-italic: ")))
- (if (and (eq frame t) (listp (face-font face t)))
- (set-face-font face '(bold italic) t)
- (let (font)
- (if (null frame)
- (let ((frames (frame-list)))
- ;; Make this face bold-italic in global-face-data.
- (make-face-bold-italic face t noerror)
- ;; Make this face bold in each frame.
- (while frames
- (make-face-bold-italic face (car frames) noerror)
- (setq frames (cdr frames))))
- (setq face (internal-get-face face frame))
- (setq font (or (face-font face frame)
- (face-font face t)))
- (if (listp font)
- (setq font nil))
- (setq font (or font
- (face-font 'default frame)
- (cdr (assq 'font (frame-parameters frame)))))
- (or (and font (make-face-bold-italic-internal face frame font))
- ;; We failed to find a bold italic version.
- noerror
- (error "No bold italic version of %S" font))))))
-
-(defun make-face-bold-italic-internal (face frame font)
- (let (f2 f3)
- (or (and (setq f2 (x-make-font-italic font))
- (not (equal font f2))
- (setq f3 (x-make-font-bold f2))
- (not (equal f2 f3))
- (internal-try-face-font face f3 frame))
- (and (setq f2 (x-make-font-oblique font))
- (not (equal font f2))
- (setq f3 (x-make-font-bold f2))
- (not (equal f2 f3))
- (internal-try-face-font face f3 frame))
- (and (setq f2 (x-make-font-italic font))
- (not (equal font f2))
- (setq f3 (x-make-font-demibold f2))
- (not (equal f2 f3))
- (internal-try-face-font face f3 frame))
- (and (setq f2 (x-make-font-oblique font))
- (not (equal font f2))
- (setq f3 (x-make-font-demibold f2))
- (not (equal f2 f3))
- (internal-try-face-font face f3 frame)))))
-
-(defun make-face-unbold (face &optional frame noerror)
- "Make the font of the given face be non-bold, if possible.
-If NOERROR is non-nil, return nil on failure."
- (interactive (list (read-face-name "Make which face non-bold: ")))
- (if (and (eq frame t) (listp (face-font face t)))
- (set-face-font face (if (memq 'italic (face-font face t))
- '(italic) nil)
- t)
- (let (font font1)
- (if (null frame)
- (let ((frames (frame-list)))
- ;; Make this face unbold in global-face-data.
- (make-face-unbold face t noerror)
- ;; Make this face unbold in each frame.
- (while frames
- (make-face-unbold face (car frames) noerror)
- (setq frames (cdr frames))))
- (setq face (internal-get-face face frame))
- (setq font1 (or (face-font face frame)
- (face-font face t)))
- (if (listp font1)
- (setq font1 nil))
- (setq font1 (or font1
- (face-font 'default frame)
- (cdr (assq 'font (frame-parameters frame)))))
- (setq font (and font1 (x-make-font-unbold font1)))
- (or (if font (internal-try-face-font face font frame))
- noerror
- (error "No unbold version of %S" font1))))))
-
-(defun make-face-unitalic (face &optional frame noerror)
- "Make the font of the given face be non-italic, if possible.
-If NOERROR is non-nil, return nil on failure."
- (interactive (list (read-face-name "Make which face non-italic: ")))
- (if (and (eq frame t) (listp (face-font face t)))
- (set-face-font face (if (memq 'bold (face-font face t))
- '(bold) nil)
- t)
- (let (font font1)
- (if (null frame)
- (let ((frames (frame-list)))
- ;; Make this face unitalic in global-face-data.
- (make-face-unitalic face t noerror)
- ;; Make this face unitalic in each frame.
- (while frames
- (make-face-unitalic face (car frames) noerror)
- (setq frames (cdr frames))))
- (setq face (internal-get-face face frame))
- (setq font1 (or (face-font face frame)
- (face-font face t)))
- (if (listp font1)
- (setq font1 nil))
- (setq font1 (or font1
- (face-font 'default frame)
- (cdr (assq 'font (frame-parameters frame)))))
- (setq font (and font1 (x-make-font-unitalic font1)))
- (or (if font (internal-try-face-font face font frame))
- noerror
- (error "No unitalic version of %S" font1))))))
-
-(defvar list-faces-sample-text
- "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "*Text string to display as the sample text for `list-faces-display'.")
-
-;; The name list-faces would be more consistent, but let's avoid a conflict
-;; with Lucid, which uses that name differently.
-(defun list-faces-display ()
- "List all faces, using the same sample text in each.
-The sample text is a string that comes from the variable
-`list-faces-sample-text'.
-
-It is possible to give a particular face name different appearances in
-different frames. This command shows the appearance in the
-selected frame."
- (interactive)
- (let ((faces (sort (face-list) (function string-lessp)))
- (face nil)
- (frame (selected-frame))
- disp-frame window)
- (with-output-to-temp-buffer "*Faces*"
- (save-excursion
- (set-buffer standard-output)
- (setq truncate-lines t)
- (while faces
- (setq face (car faces))
- (setq faces (cdr faces))
- (insert (format "%25s " (symbol-name face)))
- (let ((beg (point)))
- (insert list-faces-sample-text)
- (insert "\n")
- (put-text-property beg (1- (point)) 'face face)
- ;; If the sample text has multiple lines, line up all of them.
- (goto-char beg)
- (forward-line 1)
- (while (not (eobp))
- (insert " ")
- (forward-line 1))))
- (goto-char (point-min))))
- ;; If the *Faces* buffer appears in a different frame,
- ;; copy all the face definitions from FRAME,
- ;; so that the display will reflect the frame that was selected.
- (setq window (get-buffer-window (get-buffer "*Faces*") t))
- (setq disp-frame (if window (window-frame window)
- (car (frame-list))))
- (or (eq frame disp-frame)
- (let ((faces (face-list)))
- (while faces
- (copy-face (car faces) (car faces) frame disp-frame)
- (setq faces (cdr faces)))))))
-
-(defun describe-face (face)
- "Display the properties of face FACE."
- (interactive (list (read-face-name "Describe face: ")))
- (with-output-to-temp-buffer "*Help*"
- (princ "Properties of face `")
- (princ (face-name face))
- (princ "':") (terpri)
- (princ "Foreground: ") (princ (face-foreground face)) (terpri)
- (princ "Background: ") (princ (face-background face)) (terpri)
- (princ " Font: ") (princ (face-font face)) (terpri)
- (princ "Underlined: ") (princ (if (face-underline-p face) "yes" "no")) (terpri)
- (princ " Stipple: ") (princ (or (face-stipple face) "none"))))
-
-;;; Make the standard faces.
-;;; The C code knows the default and modeline faces as faces 0 and 1,
-;;; so they must be the first two faces made.
-(defun face-initialize ()
- (make-face 'default)
- (make-face 'modeline)
- (make-face 'highlight)
-
- ;; These aren't really special in any way, but they're nice to have around.
-
- (make-face 'bold)
- (make-face 'italic)
- (make-face 'bold-italic)
- (make-face 'region)
- (make-face 'secondary-selection)
- (make-face 'underline)
-
- (setq region-face (face-id 'region))
-
- ;; Specify the global properties of these faces
- ;; so they will come out right on new frames.
-
- (make-face-bold 'bold t)
- (make-face-italic 'italic t)
- (make-face-bold-italic 'bold-italic t)
-
- (set-face-background 'highlight '("darkseagreen2" "green" t) t)
- (set-face-background 'region '("gray" underline) t)
- (set-face-background 'secondary-selection '("paleturquoise" "green" t) t)
- (set-face-background 'modeline '(t) t)
- (set-face-underline-p 'underline t t)
-
- ;; Set up the faces of all existing X Window frames
- ;; from those global properties, unless already set in a given frame.
-
- (let ((frames (frame-list)))
- (while frames
- (if (not (memq (framep (car frames)) '(t nil)))
- (let ((frame (car frames))
- (rest global-face-data))
- (while rest
- (let ((face (car (car rest))))
- (or (face-differs-from-default-p face)
- (face-fill-in face (cdr (car rest)) frame)))
- (setq rest (cdr rest)))))
- (setq frames (cdr frames)))))
-
-
-;; Like x-create-frame but also set up the faces.
-
-(defun x-create-frame-with-faces (&optional parameters)
- ;; Read this frame's geometry resource, if it has an explicit name,
- ;; and put the specs into PARAMETERS.
- (let* ((name (or (cdr (assq 'name parameters))
- (cdr (assq 'name default-frame-alist))))
- (x-resource-name name)
- (res-geometry (if name (x-get-resource "geometry" "Geometry")))
- parsed)
- (if res-geometry
- (progn
- (setq parsed (x-parse-geometry res-geometry))
- ;; If the resource specifies a position,
- ;; call the position and size "user-specified".
- (if (or (assq 'top parsed) (assq 'left parsed))
- (setq parsed (cons '(user-position . t)
- (cons '(user-size . t) parsed))))
- ;; Put the geometry parameters at the end.
- ;; Copy default-frame-alist so that they go after it.
- (setq parameters (append parameters
- default-frame-alist
- parsed)))))
- (let (frame)
- (if (null global-face-data)
- (setq frame (x-create-frame parameters))
- (let* ((visibility-spec (assq 'visibility parameters))
- (faces (copy-alist global-face-data))
- success
- (rest faces))
- (setq frame (x-create-frame (cons '(visibility . nil) parameters)))
- (unwind-protect
- (progn
- (set-frame-face-alist frame faces)
-
- (if (cdr (or (assq 'reverse parameters)
- (assq 'reverse default-frame-alist)
- (let ((resource (x-get-resource "reverseVideo"
- "ReverseVideo")))
- (if resource
- (cons nil (member (downcase resource)
- '("on" "true")))))))
- (let* ((params (frame-parameters frame))
- (bg (cdr (assq 'foreground-color params)))
- (fg (cdr (assq 'background-color params))))
- (modify-frame-parameters frame
- (list (cons 'foreground-color fg)
- (cons 'background-color bg)))
- (if (equal bg (cdr (assq 'border-color params)))
- (modify-frame-parameters frame
- (list (cons 'border-color fg))))
- (if (equal bg (cdr (assq 'mouse-color params)))
- (modify-frame-parameters frame
- (list (cons 'mouse-color fg))))
- (if (equal bg (cdr (assq 'cursor-color params)))
- (modify-frame-parameters frame
- (list (cons 'cursor-color fg))))))
- ;; Copy the vectors that represent the faces.
- ;; Also fill them in from X resources.
- (while rest
- (let ((global (cdr (car rest))))
- (setcdr (car rest) (vector 'face
- (face-name (cdr (car rest)))
- (face-id (cdr (car rest)))
- nil nil nil nil nil))
- (face-fill-in (car (car rest)) global frame))
- (make-face-x-resource-internal (cdr (car rest)) frame t)
- (setq rest (cdr rest)))
- (if (null visibility-spec)
- (make-frame-visible frame)
- (modify-frame-parameters frame (list visibility-spec)))
- (setq success t))
- (or success
- (delete-frame frame)))))
- ;; Set up the background-mode frame parameter
- ;; so that programs can decide good ways of highlighting
- ;; on this frame.
- (let ((bg-resource (x-get-resource ".backgroundMode"
- "BackgroundMode"))
- (params (frame-parameters frame))
- (bg-mode))
- (setq bg-mode
- (cond (bg-resource (intern (downcase bg-resource)))
- ((< (apply '+ (x-color-values
- (cdr (assq 'background-color params))
- frame))
- ;; Just looking at the screen,
- ;; colors whose values add up to .6 of the white total
- ;; still look dark to me.
- (* (apply '+ (x-color-values "white" frame)) .6))
- 'dark)
- (t 'light)))
- (modify-frame-parameters frame
- (list (cons 'background-mode bg-mode)
- (cons 'display-type
- (cond ((x-display-color-p frame)
- 'color)
- ((x-display-grayscale-p frame)
- 'grayscale)
- (t 'mono))))))
- frame))
-
-;; Update a frame's faces when we change its default font.
-(defun frame-update-faces (frame)
- (let* ((faces global-face-data)
- (rest faces))
- (while rest
- (let* ((face (car (car rest)))
- (font (face-font face t)))
- (if (listp font)
- (let ((bold (memq 'bold font))
- (italic (memq 'italic font)))
- ;; Ignore any previous (string-valued) font, it might not even
- ;; be the right size anymore.
- (set-face-font face nil frame)
- (cond ((and bold italic)
- (make-face-bold-italic face frame t))
- (bold
- (make-face-bold face frame t))
- (italic
- (make-face-italic face frame t)))))
- (setq rest (cdr rest)))
- frame)))
-
-;; Update the colors of FACE, after FRAME's own colors have been changed.
-;; This applies only to faces with global color specifications
-;; that are not simple constants.
-(defun frame-update-face-colors (frame)
- (let ((faces global-face-data))
- (while faces
- (condition-case nil
- (let* ((data (cdr (car faces)))
- (face (car (car faces)))
- (foreground (face-foreground data))
- (background (face-background data)))
- ;; If the global spec is a specific color,
- ;; which doesn't depend on the frame's attributes,
- ;; we don't need to recalculate it now.
- (or (listp foreground)
- (setq foreground nil))
- (or (listp background)
- (setq background nil))
- ;; If we are going to frob this face at all,
- ;; reinitialize it first.
- (if (or foreground background)
- (progn (set-face-foreground face nil frame)
- (set-face-background face nil frame)))
- (if foreground
- (face-try-color-list 'set-face-foreground
- face foreground frame))
- (if background
- (face-try-color-list 'set-face-background
- face background frame)))
- (error nil))
- (setq faces (cdr faces)))))
-
-;; Fill in the face FACE from frame-independent face data DATA.
-;; DATA should be the non-frame-specific ("global") face vector
-;; for the face. FACE should be a face name or face object.
-;; FRAME is the frame to act on; it must be an actual frame, not nil or t.
-(defun face-fill-in (face data frame)
- (condition-case nil
- (let ((foreground (face-foreground data))
- (background (face-background data))
- (font (face-font data))
- (stipple (face-stipple data)))
- (set-face-underline-p face (face-underline-p data) frame)
- (if foreground
- (face-try-color-list 'set-face-foreground
- face foreground frame))
- (if background
- (face-try-color-list 'set-face-background
- face background frame))
- (if (listp font)
- (let ((bold (memq 'bold font))
- (italic (memq 'italic font)))
- (cond ((and bold italic)
- (make-face-bold-italic face frame))
- (bold
- (make-face-bold face frame))
- (italic
- (make-face-italic face frame))))
- (if font
- (set-face-font face font frame)))
- (if stipple
- (set-face-stipple face stipple frame)))
- (error nil)))
-
-;; Assuming COLOR is a valid color name,
-;; return t if it can be displayed on FRAME.
-(defun face-color-supported-p (frame color background-p)
- (and window-system
- (or (x-display-color-p frame)
- ;; A black-and-white display can implement these.
- (member color '("black" "white"))
- ;; A black-and-white display can fake gray for background.
- (and background-p
- (face-color-gray-p color frame))
- ;; A grayscale display can implement colors that are gray (more or less).
- (and (x-display-grayscale-p frame)
- (face-color-gray-p color frame)))))
-
-;; Use FUNCTION to store a color in FACE on FRAME.
-;; COLORS is either a single color or a list of colors.
-;; If it is a list, try the colors one by one until one of them
-;; succeeds. We signal an error only if all the colors failed.
-;; t as COLORS or as an element of COLORS means to invert the face.
-;; That can't fail, so any subsequent elements after the t are ignored.
-(defun face-try-color-list (function face colors frame)
- (if (stringp colors)
- (if (face-color-supported-p frame colors
- (eq function 'set-face-background))
- (funcall function face colors frame))
- (if (eq colors t)
- (invert-face face frame)
- (let (done)
- (while (and colors (not done))
- (if (or (memq (car colors) '(t underline))
- (face-color-supported-p frame (car colors)
- (eq function 'set-face-background)))
- (if (cdr colors)
- ;; If there are more colors to try, catch errors
- ;; and set `done' if we succeed.
- (condition-case nil
- (progn
- (cond ((eq (car colors) t)
- (invert-face face frame))
- ((eq (car colors) 'underline)
- (set-face-underline-p face t frame))
- (t
- (funcall function face (car colors) frame)))
- (setq done t))
- (error nil))
- ;; If this is the last color, let the error get out if it fails.
- ;; If it succeeds, we will exit anyway after this iteration.
- (cond ((eq (car colors) t)
- (invert-face face frame))
- ((eq (car colors) 'underline)
- (set-face-underline-p face t frame))
- (t
- (funcall function face (car colors) frame)))))
- (setq colors (cdr colors)))))))
-
-;; If we are already using x-window frames, initialize faces for them.
-(if (memq (framep (selected-frame)) '(x w32))
- (face-initialize))
-
-(provide 'faces)
-
-;;; faces.el ends here
diff --git a/lisp/fast-lock.el b/lisp/fast-lock.el
deleted file mode 100644
index aa3a57b9e41..00000000000
--- a/lisp/fast-lock.el
+++ /dev/null
@@ -1,735 +0,0 @@
-;;; fast-lock.el --- Automagic text properties caching for fast Font Lock mode.
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Simon Marshall <simon@gnu.ai.mit.edu>
-;; Keywords: faces files
-;; Version: 3.11
-
-;;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Lazy Lock mode is a Font Lock support mode.
-;; It makes visiting a file in Font Lock mode faster by restoring its face text
-;; properties from automatically saved associated Font Lock cache files.
-;;
-;; See caveats and feedback below.
-;; See also the lazy-lock package. (But don't use the two at the same time!)
-
-;; Installation:
-;;
-;; Put in your ~/.emacs:
-;;
-;; (setq font-lock-support-mode 'fast-lock-mode)
-;;
-;; Start up a new Emacs and use font-lock as usual (except that you can use the
-;; so-called "gaudier" fontification regexps on big files without frustration).
-;;
-;; When you visit a file (which has `font-lock-mode' enabled) that has a
-;; corresponding Font Lock cache file associated with it, the Font Lock cache
-;; will be loaded from that file instead of being generated by Font Lock code.
-
-;; Caveats:
-;;
-;; A cache will be saved when visiting a compressed file using crypt++, but not
-;; be read. This is a "feature"/"consequence"/"bug" of crypt++.
-;;
-;; Version control packages are likely to stamp all over file modification
-;; times. Therefore the act of checking out may invalidate a cache.
-
-;; History:
-;;
-;; 0.02--1.00:
-;; - Changed name from turbo-prop to fast-lock. Automagic for font-lock only
-;; - Made `fast-lock-mode' a minor mode, like G. Dinesh Dutt's fss-mode
-;; 1.00--1.01:
-;; - Turn on `fast-lock-mode' only if `buffer-file-name' or `interactive-p'
-;; - Made `fast-lock-file-name' use `buffer-name' if `buffer-file-name' is nil
-;; - Moved save-all conditions to `fast-lock-save-cache'
-;; - Added `fast-lock-save-text-properties' to `kill-buffer-hook'
-;; 1.01--2.00: complete rewrite---not worth the space to document
-;; - Changed structure of text properties cache and threw out file mod checks
-;; 2.00--2.01:
-;; - Made `condition-case' forms understand `quit'.
-;; - Made `fast-lock' require `font-lock'
-;; - Made `fast-lock-cache-name' chase links (from Ben Liblit)
-;; 2.01--3.00:
-;; - Changed structure of cache to include `font-lock-keywords' (from rms)
-;; - Changed `fast-lock-cache-mechanisms' to `fast-lock-cache-directories'
-;; - Removed `fast-lock-read-others'
-;; - Made `fast-lock-read-cache' ignore cache owner
-;; - Made `fast-lock-save-cache-external' create cache directory
-;; - Made `fast-lock-save-cache-external' save `font-lock-keywords'
-;; - Made `fast-lock-cache-data' check `font-lock-keywords'
-;; 3.00--3.01: incorporated port of 2.00 to Lucid, made by Barry Warsaw
-;; - Package now provides itself
-;; - Lucid: Use `font-lock-any-extents-p' for `font-lock-any-properties-p'
-;; - Lucid: Use `list-faces' for `face-list'
-;; - Lucid: Added `set-text-properties'
-;; - Lucid: Made `turn-on-fast-lock' pass 1 not t to `fast-lock-mode'
-;; - Removed test for `fast-lock-mode' from `fast-lock-read-cache'
-;; - Lucid: Added Lucid-specific `fast-lock-get-face-properties'
-;; 3.01--3.02: now works with Lucid Emacs, thanks to Barry Warsaw
-;; - Made `fast-lock-cache-name' map ":" to ";" for OS/2 (from Serganova Vera)
-;; - Made `fast-lock-cache-name' use abbreviated file name (from Barry Warsaw)
-;; - Lucid: Separated handlers for `error' and `quit' for `condition-case'
-;; 3.02--3.03:
-;; - Changed `fast-lock-save-cache-external' to `fast-lock-save-cache-data'
-;; - Lucid: Added Lucid-specific `fast-lock-set-face-properties'
-;; 3.03--3.04:
-;; - Corrected `subrp' test of Lucid code
-;; - Replaced `font-lock-any-properties-p' with `text-property-not-all'
-;; - Lucid: Made `fast-lock-set-face-properties' put `text-prop' on extents
-;; - Made `fast-lock-cache-directories' a regexp alist (from Colin Rafferty)
-;; - Made `fast-lock-cache-directory' to return a usable cache file directory
-;; 3.04--3.05:
-;; - Lucid: Fix for XEmacs 19.11 `text-property-not-all'
-;; - Replaced `subrp' test of Lucid code with `emacs-version' `string-match'
-;; - Made `byte-compile-warnings' omit `unresolved' on compilation
-;; - Made `fast-lock-save-cache-data' use a buffer (from Rick Sladkey)
-;; - Reverted to old `fast-lock-get-face-properties' (from Rick Sladkey)
-;; 3.05--3.06: incorporated hack of 3.03, made by Jonathan Stigelman (Stig)
-;; - Reverted to 3.04 version of `fast-lock-get-face-properties'
-;; - XEmacs: Removed `list-faces' `defalias'
-;; - Made `fast-lock-mode' and `turn-on-fast-lock' succeed `autoload' cookies
-;; - Added `fast-lock-submit-bug-report'
-;; - Renamed `fast-lock-save-size' to `fast-lock-minimum-size'
-;; - Made `fast-lock-save-cache' output a message if no save ever attempted
-;; - Made `fast-lock-save-cache-data' output a message if save attempted
-;; - Made `fast-lock-cache-data' output a message if load attempted
-;; - Made `fast-lock-save-cache-data' do `condition-case' not `unwind-protect'
-;; - Made `fast-lock-save-cache' and `fast-lock-read-cache' return nothing
-;; - Made `fast-lock-save-cache' check `buffer-modified-p' (Stig)
-;; - Added `fast-lock-save-events'
-;; - Added `fast-lock-after-save-hook' to `after-save-hook' (Stig)
-;; - Added `fast-lock-kill-buffer-hook' to `kill-buffer-hook'
-;; - Changed `fast-lock-save-caches' to `fast-lock-kill-emacs-hook'
-;; - Added `fast-lock-kill-emacs-hook' to `kill-emacs-hook'
-;; - Made `fast-lock-save-cache' check `verify-visited-file-modtime' (Stig)
-;; - Made `visited-file-modtime' be the basis of the timestamp (Stig)
-;; - Made `fast-lock-save-cache-1' and `fast-lock-cache-data' use/reformat it
-;; - Added `fast-lock-cache-filename' to keep track of the cache file name
-;; - Added `fast-lock-after-fontify-buffer'
-;; - Added `fast-lock-save-faces' list of faces to save (idea from Stig/Tibor)
-;; - Made `fast-lock-get-face-properties' functions use it
-;; - XEmacs: Made `fast-lock-set-face-properties' do extents the Font Lock way
-;; - XEmacs: Removed fix for `text-property-not-all' (19.11 support dropped)
-;; - Made `fast-lock-mode' ensure `font-lock-mode' is on
-;; - Made `fast-lock-save-cache' do `cdr-safe' not `cdr' (from Dave Foster)
-;; - Made `fast-lock-save-cache' do `set-buffer' first (from Dave Foster)
-;; - Made `fast-lock-save-cache' loop until saved or quit (from Georg Nikodym)
-;; - Made `fast-lock-cache-data' check `buffer-modified-p'
-;; - Made `fast-lock-cache-data' do `font-lock-compile-keywords' if necessary
-;; - XEmacs: Made `font-lock-compile-keywords' `defalias'
-;; 3.06--3.07:
-;; - XEmacs: Add `fast-lock-after-fontify-buffer' to the Font Lock hook
-;; - Made `fast-lock-cache-name' explain the use of `directory-abbrev-alist'
-;; - Made `fast-lock-mode' use `buffer-file-truename' not `buffer-file-name'
-;; 3.07--3.08:
-;; - Made `fast-lock-read-cache' set `fast-lock-cache-filename'
-;; 3.08--3.09:
-;; - Made `fast-lock-save-cache' cope if `fast-lock-minimum-size' is an a list
-;; - Made `fast-lock-mode' respect the value of `font-lock-inhibit-thing-lock'
-;; - Added `fast-lock-after-unfontify-buffer'
-;; 3.09--3.10:
-;; - Rewrite for Common Lisp macros
-;; - Made fast-lock.el barf on a crap 8+3 pseudo-OS (Eli Zaretskii help)
-;; - XEmacs: Made `add-minor-mode' succeed `autoload' cookie
-;; - XEmacs: Made `fast-lock-save-faces' default to `font-lock-face-list'
-;; - Made `fast-lock-save-cache' use `font-lock-value-in-major-mode'
-;; - Wrap with `save-buffer-state' (Ray Van Tassle report)
-;; - Made `fast-lock-mode' wrap `font-lock-support-mode'
-;; 3.10--3.11:
-;; - Made `fast-lock-get-face-properties' cope with face lists
-;; - Added `fast-lock-verbose'
-;; - XEmacs: Add `font-lock-value-in-major-mode' if necessary
-;; - Removed `fast-lock-submit-bug-report' and bade farewell
-
-;;; Code:
-
-(require 'font-lock)
-
-;; Make sure fast-lock.el is supported.
-(if (and (eq system-type 'ms-dos) (not (msdos-long-file-names)))
- (error "`fast-lock' was written for long file name systems"))
-
-(eval-when-compile
- ;;
- ;; We don't do this at the top-level as we only use non-autoloaded macros.
- (require 'cl)
- ;;
- ;; I prefer lazy code---and lazy mode.
- (setq byte-compile-dynamic t byte-compile-dynamic-docstrings t)
- ;; But, we make sure that the code is as zippy as can be.
- (setq byte-optimize t)
- ;;
- ;; We use this to preserve or protect things when modifying text properties.
- (defmacro save-buffer-state (varlist &rest body)
- "Bind variables according to VARLIST and eval BODY restoring buffer state."
- (` (let* ((,@ (append varlist
- '((modified (buffer-modified-p))
- (inhibit-read-only t) (buffer-undo-list t)
- before-change-functions after-change-functions
- deactivate-mark buffer-file-name buffer-file-truename))))
- (,@ body)
- (when (and (not modified) (buffer-modified-p))
- (set-buffer-modified-p nil)))))
- (put 'save-buffer-state 'lisp-indent-function 1)
- ;;
- ;; We use this to verify that a face should be saved.
- (defmacro fast-lock-save-facep (face)
- "Return non-nil if FACE is one of `fast-lock-save-faces'."
- (` (or (null fast-lock-save-faces)
- (if (symbolp (, face))
- (memq (, face) fast-lock-save-faces)
- (let ((faces (, face)))
- (while (unless (memq (car faces) fast-lock-save-faces)
- (setq faces (cdr faces))))
- faces))))))
-
-;(defun fast-lock-submit-bug-report ()
-; "Submit via mail a bug report on fast-lock.el."
-; (interactive)
-; (let ((reporter-prompt-for-summary-p t))
-; (reporter-submit-bug-report "simon@gnu.ai.mit.edu" "fast-lock 3.11"
-; '(fast-lock-cache-directories fast-lock-minimum-size
-; fast-lock-save-others fast-lock-save-events fast-lock-save-faces
-; fast-lock-verbose)
-; nil nil
-; (concat "Hi Si.,
-;
-;I want to report a bug. I've read the `Bugs' section of `Info' on Emacs, so I
-;know how to make a clear and unambiguous report. To reproduce the bug:
-;
-;Start a fresh editor via `" invocation-name " -no-init-file -no-site-file'.
-;In the `*scratch*' buffer, evaluate:"))))
-
-(defvar fast-lock-mode nil)
-(defvar fast-lock-cache-timestamp nil) ; for saving/reading
-(defvar fast-lock-cache-filename nil) ; for deleting
-
-;; User Variables:
-
-(defvar fast-lock-cache-directories '("." "~/.emacs-flc")
-; - `internal', keep each file's Font Lock cache file in the same file.
-; - `external', keep each file's Font Lock cache file in the same directory.
- "*Directories in which Font Lock cache files are saved and read.
-Each item should be either DIR or a cons pair of the form (REGEXP . DIR) where
-DIR is a directory name (relative or absolute) and REGEXP is a regexp.
-
-An attempt will be made to save or read Font Lock cache files using these items
-until one succeeds (i.e., until a readable or writable one is found). If an
-item contains REGEXP, DIR is used only if the buffer file name matches REGEXP.
-For example:
-
- (let ((home (expand-file-name (abbreviate-file-name (file-truename \"~/\")))))
- (list (cons (concat \"^\" (regexp-quote home)) \".\") \"~/.emacs-flc\"))
- =>
- ((\"^/your/true/home/directory/\" . \".\") \"~/.emacs-flc\")
-
-would cause a file's current directory to be used if the file is under your
-home directory hierarchy, or otherwise the absolute directory `~/.emacs-flc'.")
-
-(defvar fast-lock-minimum-size (* 25 1024)
- "*Minimum size of a buffer for cached fontification.
-Only buffers more than this can have associated Font Lock cache files saved.
-If nil, means cache files are never created.
-If a list, each element should be a cons pair of the form (MAJOR-MODE . SIZE),
-where MAJOR-MODE is a symbol or t (meaning the default). For example:
- ((c-mode . 25600) (c++-mode . 25600) (rmail-mode . 1048576))
-means that the minimum size is 25K for buffers in C or C++ modes, one megabyte
-for buffers in Rmail mode, and size is irrelevant otherwise.")
-
-(defvar fast-lock-save-events '(kill-buffer kill-emacs)
- "*Events under which caches will be saved.
-Valid events are `save-buffer', `kill-buffer' and `kill-emacs'.
-If concurrent editing sessions use the same associated cache file for a file's
-buffer, then you should add `save-buffer' to this list.")
-
-(defvar fast-lock-save-others t
- "*If non-nil, save Font Lock cache files irrespective of file owner.
-If nil, means only buffer files known to be owned by you can have associated
-Font Lock cache files saved. Ownership may be unknown for networked files.")
-
-(defvar fast-lock-save-faces
- (when (save-match-data (string-match "XEmacs" (emacs-version)))
- ;; XEmacs uses extents for everything, so we have to pick the right ones.
- font-lock-face-list)
- "Faces that will be saved in a Font Lock cache file.
-If nil, means information for all faces will be saved.")
-
-(defvar fast-lock-verbose font-lock-verbose
- "*If non-nil, means show status messages for cache processing.
-If a number, only buffers greater than this size have processing messages.")
-
-;; User Functions:
-
-;;;###autoload
-(defun fast-lock-mode (&optional arg)
- "Toggle Fast Lock mode.
-With arg, turn Fast Lock mode on if and only if arg is positive and the buffer
-is associated with a file. Enable it automatically in your `~/.emacs' by:
-
- (setq font-lock-support-mode 'fast-lock-mode)
-
-If Fast Lock mode is enabled, and the current buffer does not contain any text
-properties, any associated Font Lock cache is used if its timestamp matches the
-buffer's file, and its `font-lock-keywords' match those that you are using.
-
-Font Lock caches may be saved:
-- When you save the file's buffer.
-- When you kill an unmodified file's buffer.
-- When you exit Emacs, for all unmodified or saved buffers.
-Depending on the value of `fast-lock-save-events'.
-See also the commands `fast-lock-read-cache' and `fast-lock-save-cache'.
-
-Use \\[font-lock-fontify-buffer] to fontify the buffer if the cache is bad.
-
-Various methods of control are provided for the Font Lock cache. In general,
-see variable `fast-lock-cache-directories' and function `fast-lock-cache-name'.
-For saving, see variables `fast-lock-minimum-size', `fast-lock-save-events',
-`fast-lock-save-others' and `fast-lock-save-faces'."
- (interactive "P")
- ;; Only turn on if we are visiting a file. We could use `buffer-file-name',
- ;; but many packages temporarily wrap that to nil when doing their own thing.
- (set (make-local-variable 'fast-lock-mode)
- (and buffer-file-truename
- (not (memq 'fast-lock-mode font-lock-inhibit-thing-lock))
- (if arg (> (prefix-numeric-value arg) 0) (not fast-lock-mode))))
- (if (and fast-lock-mode (not font-lock-mode))
- ;; Turned on `fast-lock-mode' rather than `font-lock-mode'.
- (let ((font-lock-support-mode 'fast-lock-mode))
- (font-lock-mode t))
- ;; Let's get down to business.
- (set (make-local-variable 'fast-lock-cache-timestamp) nil)
- (set (make-local-variable 'fast-lock-cache-filename) nil)
- (when (and fast-lock-mode (not font-lock-fontified))
- (fast-lock-read-cache))))
-
-(defun fast-lock-read-cache ()
- "Read the Font Lock cache for the current buffer.
-
-The following criteria must be met for a Font Lock cache file to be read:
-- Fast Lock mode must be turned on in the buffer.
-- The buffer must not be modified.
-- The buffer's `font-lock-keywords' must match the cache's.
-- The buffer file's timestamp must match the cache's.
-- Criteria imposed by `fast-lock-cache-directories'.
-
-See `fast-lock-mode'."
- (interactive)
- (let ((directories fast-lock-cache-directories)
- (modified (buffer-modified-p)) (inhibit-read-only t)
- (fontified font-lock-fontified))
- (set (make-local-variable 'font-lock-fontified) nil)
- ;; Keep trying directories until fontification is turned off.
- (while (and directories (not font-lock-fontified))
- (let ((directory (fast-lock-cache-directory (car directories) nil)))
- (condition-case nil
- (when directory
- (setq fast-lock-cache-filename (fast-lock-cache-name directory))
- (when (file-readable-p fast-lock-cache-filename)
- (load fast-lock-cache-filename t t t)))
- (error nil) (quit nil))
- (setq directories (cdr directories))))
- ;; Unset `fast-lock-cache-filename', and restore `font-lock-fontified', if
- ;; we don't use a cache. (Note that `fast-lock-cache-data' sets the value
- ;; of `fast-lock-cache-timestamp'.)
- (set-buffer-modified-p modified)
- (unless font-lock-fontified
- (setq fast-lock-cache-filename nil font-lock-fontified fontified))))
-
-(defun fast-lock-save-cache (&optional buffer)
- "Save the Font Lock cache of BUFFER or the current buffer.
-
-The following criteria must be met for a Font Lock cache file to be saved:
-- Fast Lock mode must be turned on in the buffer.
-- The event must be one of `fast-lock-save-events'.
-- The buffer must be at least `fast-lock-minimum-size' bytes long.
-- The buffer file must be owned by you, or `fast-lock-save-others' must be t.
-- The buffer must contain at least one `face' text property.
-- The buffer must not be modified.
-- The buffer file's timestamp must be the same as the file's on disk.
-- The on disk file's timestamp must be different than the buffer's cache.
-- Criteria imposed by `fast-lock-cache-directories'.
-
-See `fast-lock-mode'."
- (interactive)
- (save-excursion
- (when buffer
- (set-buffer buffer))
- (let ((min-size (font-lock-value-in-major-mode fast-lock-minimum-size))
- (file-timestamp (visited-file-modtime)) (saved nil))
- (when (and fast-lock-mode
- ;;
- ;; "Only save if the buffer matches the file, the file has
- ;; changed, and it was changed by the current emacs session."
- ;;
- ;; Only save if the buffer is not modified,
- ;; (i.e., so we don't save for something not on disk)
- (not (buffer-modified-p))
- ;; and the file's timestamp is the same as the buffer's,
- ;; (i.e., someone else hasn't written the file in the meantime)
- (verify-visited-file-modtime (current-buffer))
- ;; and the file's timestamp is different from the cache's.
- ;; (i.e., a save has occurred since the cache was read)
- (not (equal fast-lock-cache-timestamp file-timestamp))
- ;;
- ;; Only save if user's restrictions are satisfied.
- (and min-size (>= (buffer-size) min-size))
- (or fast-lock-save-others
- (eq (user-uid) (nth 2 (file-attributes buffer-file-name))))
- ;;
- ;; Only save if there are `face' properties to save.
- (text-property-not-all (point-min) (point-max) 'face nil))
- ;;
- ;; Try each directory until we manage to save or the user quits.
- (let ((directories fast-lock-cache-directories))
- (while (and directories (memq saved '(nil error)))
- (let* ((dir (fast-lock-cache-directory (car directories) t))
- (file (and dir (fast-lock-cache-name dir))))
- (when (and file (file-writable-p file))
- (setq saved (fast-lock-save-cache-1 file file-timestamp)))
- (setq directories (cdr directories)))))))))
-
-;;;###autoload
-(defun turn-on-fast-lock ()
- "Unconditionally turn on Fast Lock mode."
- (fast-lock-mode t))
-
-;;; API Functions:
-
-(defun fast-lock-after-fontify-buffer ()
- ;; Delete the Font Lock cache file used to restore fontification, if any.
- (when fast-lock-cache-filename
- (if (file-writable-p fast-lock-cache-filename)
- (delete-file fast-lock-cache-filename)
- (message "File %s font lock cache cannot be deleted" (buffer-name))))
- ;; Flag so that a cache will be saved later even if the file is never saved.
- (setq fast-lock-cache-timestamp nil))
-
-(defalias 'fast-lock-after-unfontify-buffer
- 'ignore)
-
-;; Miscellaneous Functions:
-
-(defun fast-lock-save-cache-after-save-file ()
- ;; Do `fast-lock-save-cache' if `save-buffer' is on `fast-lock-save-events'.
- (when (memq 'save-buffer fast-lock-save-events)
- (fast-lock-save-cache)))
-
-(defun fast-lock-save-cache-before-kill-buffer ()
- ;; Do `fast-lock-save-cache' if `kill-buffer' is on `fast-lock-save-events'.
- (when (memq 'kill-buffer fast-lock-save-events)
- (fast-lock-save-cache)))
-
-(defun fast-lock-save-caches-before-kill-emacs ()
- ;; Do `fast-lock-save-cache's if `kill-emacs' is on `fast-lock-save-events'.
- (when (memq 'kill-emacs fast-lock-save-events)
- (mapcar 'fast-lock-save-cache (buffer-list))))
-
-(defun fast-lock-cache-directory (directory create)
- "Return usable directory based on DIRECTORY.
-Returns nil if the directory does not exist, or, if CREATE non-nil, cannot be
-created. DIRECTORY may be a string or a cons pair of the form (REGEXP . DIR).
-See `fast-lock-cache-directories'."
- (let ((dir
- (cond ((not buffer-file-name)
- ;; Should never be nil, but `crypt++' screws it up.
- nil)
- ((stringp directory)
- ;; Just a directory.
- directory)
- (t
- ;; A directory iff the file name matches the regexp.
- (let ((bufile (expand-file-name buffer-file-truename))
- (case-fold-search nil))
- (when (save-match-data (string-match (car directory) bufile))
- (cdr directory)))))))
- (cond ((not dir)
- nil)
- ((file-accessible-directory-p dir)
- dir)
- (create
- (condition-case nil
- (progn (make-directory dir t) dir)
- (error nil))))))
-
-;; If you are wondering why we only hash if the directory is not ".", rather
-;; than if `file-name-absolute-p', it is because if we just appended ".flc" for
-;; relative cache directories (that are not ".") then it is possible that more
-;; than one file would have the same cache name in that directory, if the luser
-;; made a link from one relative cache directory to another. (Phew!)
-(defun fast-lock-cache-name (directory)
- "Return full cache path name using caching DIRECTORY.
-If DIRECTORY is `.', the path is the buffer file name appended with `.flc'.
-Otherwise, the path name is constructed from DIRECTORY and the buffer's true
-abbreviated file name, with all `/' characters in the name replaced with `#'
-characters, and appended with `.flc'.
-
-If the same file has different cache path names when edited on different
-machines, e.g., on one machine the cache file name has the prefix `#home',
-perhaps due to automount, try putting in your `~/.emacs' something like:
-
- (setq directory-abbrev-alist (cons '(\"^/home/\" . \"/\") directory-abbrev-alist))
-
-Emacs automagically removes the common `/tmp_mnt' automount prefix by default.
-
-See `fast-lock-cache-directory'."
- (if (string-equal directory ".")
- (concat buffer-file-name ".flc")
- (let* ((bufile (expand-file-name buffer-file-truename))
- (chars-alist
- (if (eq system-type 'emx)
- '((?/ . (?#)) (?# . (?# ?#)) (?: . (?\;)) (?\; . (?\; ?\;)))
- '((?/ . (?#)) (?# . (?# ?#)))))
- (mapchars
- (function (lambda (c) (or (cdr (assq c chars-alist)) (list c))))))
- (concat
- (file-name-as-directory (expand-file-name directory))
- (mapconcat 'char-to-string (apply 'append (mapcar mapchars bufile)) "")
- ".flc"))))
-
-;; Font Lock Cache Processing Functions:
-
-(defun fast-lock-save-cache-1 (file timestamp)
- ;; Save the FILE with the TIMESTAMP as:
- ;; (fast-lock-cache-data Version=2 TIMESTAMP font-lock-keywords PROPERTIES).
- ;; Returns non-nil if a save was attempted to a writable cache file.
- (let ((tpbuf (generate-new-buffer " *fast-lock*"))
- (verbose (if (numberp fast-lock-verbose)
- (> (buffer-size) fast-lock-verbose)
- fast-lock-verbose))
- (saved t))
- (if verbose (message "Saving %s font lock cache..." (buffer-name)))
- (condition-case nil
- (save-excursion
- (print (list 'fast-lock-cache-data 2
- (list 'quote timestamp)
- (list 'quote font-lock-keywords)
- (list 'quote (fast-lock-get-face-properties)))
- tpbuf)
- (set-buffer tpbuf)
- (write-region (point-min) (point-max) file nil 'quietly)
- (setq fast-lock-cache-timestamp timestamp
- fast-lock-cache-filename file))
- (error (setq saved 'error)) (quit (setq saved 'quit)))
- (kill-buffer tpbuf)
- (if verbose (message "Saving %s font lock cache...%s" (buffer-name)
- (cond ((eq saved 'error) "failed")
- ((eq saved 'quit) "aborted")
- (t "done"))))
- ;; We return non-nil regardless of whether a failure occurred.
- saved))
-
-(defun fast-lock-cache-data (version timestamp keywords properties
- &rest ignored)
- ;; Change from (HIGH LOW) for back compatibility. Remove for version 3!
- (when (consp (cdr-safe timestamp))
- (setcdr timestamp (nth 1 timestamp)))
- ;; Compile KEYWORDS and `font-lock-keywords' in case one is and one isn't.
- (let ((current font-lock-keywords))
- (setq keywords (font-lock-compile-keywords keywords)
- font-lock-keywords (font-lock-compile-keywords current)))
- ;; Use the Font Lock cache PROPERTIES if we're using cache VERSION format 2,
- ;; the current buffer's file timestamp matches the TIMESTAMP, and the current
- ;; buffer's font-lock-keywords are the same as KEYWORDS.
- (let ((buf-timestamp (visited-file-modtime))
- (verbose (if (numberp fast-lock-verbose)
- (> (buffer-size) fast-lock-verbose)
- fast-lock-verbose))
- (loaded t))
- (if (or (/= version 2)
- (buffer-modified-p)
- (not (equal timestamp buf-timestamp))
- (not (equal keywords font-lock-keywords)))
- (setq loaded nil)
- (if verbose (message "Loading %s font lock cache..." (buffer-name)))
- (condition-case nil
- (fast-lock-set-face-properties properties)
- (error (setq loaded 'error)) (quit (setq loaded 'quit)))
- (if verbose (message "Loading %s font lock cache...%s" (buffer-name)
- (cond ((eq loaded 'error) "failed")
- ((eq loaded 'quit) "aborted")
- (t "done")))))
- (setq font-lock-fontified (eq loaded t)
- fast-lock-cache-timestamp (and (eq loaded t) timestamp))))
-
-;; Text Properties Processing Functions:
-
-;; This is fast, but fails if adjacent characters have different `face' text
-;; properties. Maybe that's why I dropped it in the first place?
-;(defun fast-lock-get-face-properties ()
-; "Return a list of all `face' text properties in the current buffer.
-;Each element of the list is of the form (VALUE START1 END1 START2 END2 ...)
-;where VALUE is a `face' property value and STARTx and ENDx are positions."
-; (save-restriction
-; (widen)
-; (let ((start (text-property-not-all (point-min) (point-max) 'face nil))
-; (limit (point-max)) end properties value cell)
-; (while start
-; (setq end (next-single-property-change start 'face nil limit)
-; value (get-text-property start 'face))
-; ;; Make, or add to existing, list of regions with same `face'.
-; (if (setq cell (assq value properties))
-; (setcdr cell (cons start (cons end (cdr cell))))
-; (setq properties (cons (list value start end) properties)))
-; (setq start (next-single-property-change end 'face)))
-; properties)))
-
-;; This is slow, but copes if adjacent characters have different `face' text
-;; properties, but fails if they are lists.
-;(defun fast-lock-get-face-properties ()
-; "Return a list of all `face' text properties in the current buffer.
-;Each element of the list is of the form (VALUE START1 END1 START2 END2 ...)
-;where VALUE is a `face' property value and STARTx and ENDx are positions.
-;Only those `face' VALUEs in `fast-lock-save-faces' are returned."
-; (save-restriction
-; (widen)
-; (let ((faces (or fast-lock-save-faces (face-list))) (limit (point-max))
-; properties regions face start end)
-; (while faces
-; (setq face (car faces) faces (cdr faces) regions () end (point-min))
-; ;; Make a list of start/end regions with `face' property face.
-; (while (setq start (text-property-any end limit 'face face))
-; (setq end (or (text-property-not-all start limit 'face face) limit)
-; regions (cons start (cons end regions))))
-; ;; Add `face' face's regions, if any, to properties.
-; (when regions
-; (push (cons face regions) properties)))
-; properties)))
-
-(defun fast-lock-get-face-properties ()
- "Return a list of all `face' text properties in the current buffer.
-Each element of the list is of the form (VALUE START1 END1 START2 END2 ...)
-where VALUE is a `face' property value and STARTx and ENDx are positions."
- (save-restriction
- (widen)
- (let ((start (text-property-not-all (point-min) (point-max) 'face nil))
- end properties value cell)
- (while start
- (setq end (next-single-property-change start 'face nil (point-max))
- value (get-text-property start 'face))
- ;; Make, or add to existing, list of regions with same `face'.
- (cond ((setq cell (assoc value properties))
- (setcdr cell (cons start (cons end (cdr cell)))))
- ((fast-lock-save-facep value)
- (push (list value start end) properties)))
- (setq start (text-property-not-all end (point-max) 'face nil)))
- properties)))
-
-(defun fast-lock-set-face-properties (properties)
- "Set all `face' text properties to PROPERTIES in the current buffer.
-Any existing `face' text properties are removed first.
-See `fast-lock-get-face-properties' for the format of PROPERTIES."
- (save-buffer-state (plist regions)
- (save-restriction
- (widen)
- (font-lock-unfontify-region (point-min) (point-max))
- (while properties
- (setq plist (list 'face (car (car properties)))
- regions (cdr (car properties))
- properties (cdr properties))
- ;; Set the `face' property for each start/end region.
- (while regions
- (set-text-properties (nth 0 regions) (nth 1 regions) plist)
- (setq regions (nthcdr 2 regions)))))))
-
-;; Functions for XEmacs:
-
-(when (save-match-data (string-match "XEmacs" (emacs-version)))
- ;;
- ;; It would be better to use XEmacs' `map-extents' over extents with a
- ;; `font-lock' property, but `face' properties are on different extents.
- (defun fast-lock-get-face-properties ()
- "Return a list of all `face' text properties in the current buffer.
-Each element of the list is of the form (VALUE START1 END1 START2 END2 ...)
-where VALUE is a `face' property value and STARTx and ENDx are positions.
-Only those `face' VALUEs in `fast-lock-save-faces' are returned."
- (save-restriction
- (widen)
- (let ((properties ()) cell)
- (map-extents
- (function (lambda (extent ignore)
- (let ((value (extent-face extent)))
- ;; We're only interested if it's one of `fast-lock-save-faces'.
- (when (and value (fast-lock-save-facep value))
- (let ((start (extent-start-position extent))
- (end (extent-end-position extent)))
- ;; Make or add to existing list of regions with the same
- ;; `face' property value.
- (if (setq cell (assoc value properties))
- (setcdr cell (cons start (cons end (cdr cell))))
- (push (list value start end) properties))))
- ;; Return nil to keep `map-extents' going.
- nil))))
- properties)))
- ;;
- ;; Make extents just like XEmacs' font-lock.el does.
- (defun fast-lock-set-face-properties (properties)
- "Set all `face' text properties to PROPERTIES in the current buffer.
-Any existing `face' text properties are removed first.
-See `fast-lock-get-face-properties' for the format of PROPERTIES."
- (save-restriction
- (widen)
- (font-lock-unfontify-region (point-min) (point-max))
- (while properties
- (let ((face (car (car properties)))
- (regions (cdr (car properties))))
- ;; Set the `face' property, etc., for each start/end region.
- (while regions
- (font-lock-set-face (nth 0 regions) (nth 1 regions) face)
- (setq regions (nthcdr 2 regions)))
- (setq properties (cdr properties))))))
- ;;
- ;; XEmacs 19.12 font-lock.el's `font-lock-fontify-buffer' runs a hook.
- (add-hook 'font-lock-after-fontify-buffer-hook
- 'fast-lock-after-fontify-buffer))
-
-(unless (boundp 'font-lock-inhibit-thing-lock)
- (defvar font-lock-inhibit-thing-lock nil
- "List of Font Lock mode related modes that should not be turned on."))
-
-(unless (fboundp 'font-lock-value-in-major-mode)
- (defun font-lock-value-in-major-mode (alist)
- ;; Return value in ALIST for `major-mode'.
- (if (consp alist)
- (cdr (or (assq major-mode alist) (assq t alist)))
- alist)))
-
-(unless (fboundp 'font-lock-compile-keywords)
- (defalias 'font-lock-compile-keywords 'identity))
-
-;; Install ourselves:
-
-(add-hook 'after-save-hook 'fast-lock-save-cache-after-save-file)
-(add-hook 'kill-buffer-hook 'fast-lock-save-cache-before-kill-buffer)
-(add-hook 'kill-emacs-hook 'fast-lock-save-caches-before-kill-emacs)
-
-;;;###autoload
-(if (fboundp 'add-minor-mode) (add-minor-mode 'fast-lock-mode nil))
-;;;###dont-autoload
-(unless (assq 'fast-lock-mode minor-mode-alist)
- (setq minor-mode-alist (append minor-mode-alist '((fast-lock-mode nil)))))
-
-;; Provide ourselves:
-
-(provide 'fast-lock)
-
-;;; fast-lock.el ends here
diff --git a/lisp/ffap.el b/lisp/ffap.el
deleted file mode 100644
index a4d69ec0eb6..00000000000
--- a/lisp/ffap.el
+++ /dev/null
@@ -1,1433 +0,0 @@
-;;; ffap.el --- find file or url at point
-
-;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Michelangelo Grigni <mic@mathcs.emory.edu>
-;; Created: 29 Mar 1993
-;; Keywords: files, hypermedia, matching, mouse
-;; X-Latest: ftp://ftp.mathcs.emory.edu:/pub/mic/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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-
-;;; Commentary:
-;;
-;; Command find-file-at-point replaces find-file. With a prefix, it
-;; behaves exactly like find-file. Without a prefix, it first tries
-;; to guess a default file or url from the text around the point
-;; (`ffap-require-prefix' swaps these behaviors). This is useful for
-;; following references in situations such as mail or news buffers,
-;; README's, MANIFEST's, and so on. Submit bugs or suggestions with
-;; M-x ffap-bug.
-;;
-;; For the default installation, byte-compile ffap.el somewhere in
-;; your `load-path' and add these two lines to your .emacs file:
-;;
-;; (require 'ffap) ; load the package
-;; (ffap-bindings) ; do default key bindings
-;;
-;; ffap-bindings makes the following global key bindings:
-;;
-;; C-x C-f find-file-at-point (abbreviated as ffap)
-;; C-x 4 f ffap-other-window
-;; C-x 5 f ffap-other-frame
-;; S-mouse-3 ffap-at-mouse
-;;
-;; ffap-bindings also adds hooks to make the following local bindings
-;; in vm, gnus, and rmail:
-;;
-;; M-l ffap-next, or ffap-gnus-next in gnus
-;; M-m ffap-menu, or ffap-gnus-menu in gnus
-;;
-;; If you do not like these bindings, modify the variable
-;; `ffap-bindings', or write your own.
-;;
-;; If you use ange-ftp, browse-url, complete, efs, or w3, it is best
-;; to load or autoload them before ffap. If you use ff-paths, load it
-;; afterwards. Try apropos {C-h a ffap RET} to get a list of the many
-;; option variables. In particular, if ffap is slow, try these:
-;;
-;; (setq ffap-alist nil) ; faster, dumber prompting
-;; (setq ffap-machine-p-known 'accept) ; no pinging
-;; (setq ffap-url-regexp nil) ; disable url features in ffap
-;;
-;; ffap uses w3 (if found) or else browse-url to fetch url's. For
-;; a hairier `ffap-url-fetcher', try ffap-url.el (same ftp site).
-;; Also, you can add `ffap-menu-rescan' to various hooks to fontify
-;; the file and url references within a buffer.
-
-;;; Todo list:
-;; * recognize paths inside /usr/bin:/bin:/etc, ./ffap.el:80:
-;; * let "/path/file#key" jump to key (offset or regexp) in /path/file
-;; * find file of symbol if TAGS is loaded (like above)
-;; * break up long menus into multiple panes (like imenu?)
-;; * notice node in "(dired)Virtual Dired" (handle the space?)
-;; * notice "machine.dom blah blah blah path/file" (how?)
-;; * if w3 becomes standard, could rewrite to use its functions
-;; * regexp options for ffap-string-at-point, like font-lock (MCOOK)
-;; * v19: could replace `ffap-locate-file' with a quieter `locate-library'
-;; * support for custom.el
-;; + handle "$(HOME)" in Makefiles?
-;; + modify `font-lock-keywords' to do fontification
-
-
-;;; Code:
-
-(provide 'ffap)
-
-;; Versions: This file is tested with Emacs 19.30. It mostly works
-;; with XEmacs, but get ffap-xe.el for the popup menu. Emacs 18 is
-;; now abandoned (get ffap-15.el instead).
-
-(defvar ffap-xemacs (and (string-match "X[Ee]macs" emacs-version) t)
- "Whether ffap thinks it is running under XEmacs.")
-
-
-
-;;; User Variables:
-
-;; This function is used inside defvars:
-(defun ffap-soft-value (name &optional default)
- "Return value of symbol with NAME, if it is interned.
-Otherwise return nil (or the optional DEFAULT value)."
- ;; Bug: (ffap-soft-value "nil" 5) --> 5
- (let ((sym (intern-soft name)))
- (if (and sym (boundp sym)) (symbol-value sym) default)))
-
-
-(defvar ffap-ftp-regexp
- (and
- (or (featurep 'ange-ftp)
- (featurep 'efs)
- (and (boundp 'file-name-handler-alist) ; v19
- (or (rassq 'ange-ftp-hook-function file-name-handler-alist)
- (rassq 'efs-file-handler-function file-name-handler-alist))))
- ;; Apparently this is good enough for both ange-ftp and efs:
- "\\`/[^/:]+:")
- "*Treat paths matching this as remote ftp paths. Nil to disable.
-Nil also disables the generation of such paths by ffap.")
-
-(defvar ffap-url-unwrap-local t
- "*If non-nil, convert \"file:\" url to local path before prompting.")
-
-(defvar ffap-url-unwrap-remote t
- "*If non-nil, convert \"ftp:\" url to remote path before prompting.
-This is ignored if `ffap-ftp-regexp' is nil.")
-
-(defvar ffap-ftp-default-user
- (if (or (equal (ffap-soft-value "ange-ftp-default-user") "anonymous")
- (equal (ffap-soft-value "efs-default-user") "anonymous"))
- nil
- "anonymous")
- "*User name in ftp paths generated by `ffap-host-to-path'.
-Nil to rely on `efs-default-user' or `ange-ftp-default-user'.")
-
-(defvar ffap-rfs-regexp
- ;; Remote file access built into file system? HP rfa or Andrew afs:
- "\\`/\\(afs\\|net\\)/."
- ;; afs only: (and (file-exists-p "/afs") "\\`/afs/.")
- "*Matching paths are treated as remote. Nil to disable.")
-
-(defvar ffap-url-regexp
- ;; Could just use `url-nonrelative-link' of w3, if loaded.
- ;; This regexp is not exhaustive, it just matches common cases.
- (concat
- "\\`\\("
- "news\\(post\\)?:\\|mailto:\\|file:" ; no host ok
- "\\|"
- "\\(ftp\\|http\\|telnet\\|gopher\\|www\\|wais\\)://" ; needs host
- "\\)." ; require one more character
- )
- "Regexp matching url's. Nil to disable url features in ffap.")
-
-(defvar ffap-foo-at-bar-prefix "mailto"
- "*Presumed url prefix type of strings like \"<foo.9z@bar>\".
-Sensible values are nil, \"news\", or \"mailto\".")
-
-
-;;; Peanut Gallery:
-;;
-;; Users of ffap occasionally suggest new features. If I consider
-;; those features interesting but not clear winners (a matter of
-;; personal taste) I try to leave options to enable them. Read
-;; through this section for features that you like, put an appropriate
-;; enabler in your .emacs file.
-
-(defvar ffap-dired-wildcards nil ; "[*?][^/]*$"
- ;; Suggestion from RHOGEE, 07 Jul 1994. Disabled, dired is still
- ;; available by "C-x C-d <pattern>", and valid filenames may
- ;; sometimes contain wildcard characters.
- "*A regexp matching filename wildcard characters, or nil.
-If `find-file-at-point' gets a filename matching this pattern,
-it passes it on to `dired' instead of `find-file'.")
-
-(defvar ffap-newfile-prompt nil ; t
- ;; Suggestion from RHOGEE, 11 Jul 1994. Disabled, I think this is
- ;; better handled by `find-file-not-found-hooks'.
- "*Whether `find-file-at-point' prompts about a nonexistent file.")
-
-(defvar ffap-require-prefix nil
- ;; Suggestion from RHOGEE, 20 Oct 1994.
- "*If set, reverses the prefix argument to `find-file-at-point'.
-This is nil so neophytes notice ffap. Experts may prefer to disable
-ffap most of the time.")
-
-(defvar ffap-file-finder 'find-file
- "*The command called by `find-file-at-point' to find a file.")
-(put 'ffap-file-finder 'risky-local-variable t)
-
-(defvar ffap-url-fetcher
- (cond ((fboundp 'w3-fetch) 'w3-fetch)
- ((fboundp 'browse-url-netscape) 'browse-url-netscape)
- (t 'w3-fetch))
- ;; Remote control references:
- ;; http://www.ncsa.uiuc.edu/SDG/Software/XMosaic/remote-control.html
- ;; http://home.netscape.com/newsref/std/x-remote.html
- "*A function of one argument, called by ffap to fetch an URL.
-Reasonable choices are `w3-fetch' or `browse-url-netscape'.
-For a fancier alternative, get ffap-url.el.")
-(put 'ffap-url-fetcher 'risky-local-variable t)
-
-
-;;; Command ffap-next:
-;;
-;; Original ffap-next-url (URL's only) from RPECK 30 Mar 1995. Since
-;; then, broke it up into ffap-next-guess (noninteractive) and
-;; ffap-next (a command). It now work on files as well as url's.
-
-(defvar ffap-next-regexp
- ;; If you want ffap-next to find URL's only, try this:
- ;; (and ffap-url-regexp (string-match "\\\\`" ffap-url-regexp)
- ;; (concat "\\<" (substring ffap-url-regexp 2))))
- ;;
- ;; It pays to put a big fancy regexp here, since ffap-guesser is
- ;; much more time-consuming than regexp searching:
- "[/:.~a-zA-Z]/\\|@[a-zA-Z][-a-zA-Z0-9]*\\."
- "*Regular expression governing movements of `ffap-next'.")
-
-(defvar ffap-next-guess nil "Last value returned by `ffap-next-guess'.")
-(defun ffap-next-guess (&optional back lim)
- "Move point to next file or url, and return it as a string.
-If nothing is found, leave point at limit and return nil.
-Optional BACK argument makes search backwards.
-Optional LIM argument limits the search.
-Only considers strings that match `ffap-next-regexp'."
- (or lim (setq lim (if back (point-min) (point-max))))
- (let (guess)
- (while (not (or guess (eq (point) lim)))
- (funcall (if back 're-search-backward 're-search-forward)
- ffap-next-regexp lim 'move)
- (setq guess (ffap-guesser)))
- ;; Go to end, so we do not get same guess twice:
- (goto-char (nth (if back 0 1) ffap-string-at-point-region))
- (setq ffap-next-guess guess)))
-
-;;;###autoload
-(defun ffap-next (&optional back wrap)
- "Search buffer for next file or url, and run ffap.
-Optional argument BACK says to search backwards.
-Optional argument WRAP says to try wrapping around if necessary.
-Interactively: use a single prefix to search backwards,
-double prefix to wrap forward, triple to wrap backwards.
-Actual search is done by `ffap-next-guess'."
- (interactive
- (cdr (assq (prefix-numeric-value current-prefix-arg)
- '((1) (4 t) (16 nil t) (64 t t)))))
- (let ((pt (point))
- (guess (ffap-next-guess back)))
- ;; Try wraparound if necessary:
- (and (not guess) wrap
- (goto-char (if back (point-max) (point-min)))
- (setq guess (ffap-next-guess back pt)))
- (if guess
- (progn
- (sit-for 0) ; display point movement
- (find-file-at-point (ffap-prompter guess)))
- (goto-char pt) ; restore point
- (message "No %sfiles or URL's found."
- (if wrap "" "more ")))))
-
-(defun ffap-next-url (&optional back wrap)
- "Like `ffap-next', but search with `ffap-url-regexp'."
- (interactive)
- (let ((ffap-next-regexp ffap-url-regexp))
- (if (interactive-p)
- (call-interactively 'ffap-next)
- (ffap-next back wrap))))
-
-
-;;; Remote machines and paths:
-
-(defun ffap-replace-path-component (fullname name)
- "In remote FULLNAME, replace path with NAME. May return nil."
- ;; Use ange-ftp or efs if loaded, but do not load them otherwise.
- (let (found)
- (mapcar
- (function (lambda (sym) (and (fboundp sym) (setq found sym))))
- '(
- efs-replace-path-component
- ange-ftp-replace-path-component
- ange-ftp-replace-name-component
- ))
- (and found
- (fset 'ffap-replace-path-component found)
- (funcall found fullname name))))
-;; (ffap-replace-path-component "/who@foo.com:/whatever" "/new")
-
-(defun ffap-file-exists-string (file)
- ;; With certain packages (ange-ftp, jka-compr?) file-exists-p
- ;; sometimes returns a nicer string than it is given. Otherwise, it
- ;; just returns nil or t.
- "Return FILE \(maybe modified\) if it exists, else nil."
- (and file ; quietly reject nil
- (let ((exists (file-exists-p file)))
- (and exists (if (stringp exists) exists file)))))
-
-;; I cannot decide a "best" strategy here, so these are variables. In
-;; particular, if `Pinging...' is broken or takes too long on your
-;; machine, try setting these all to accept or reject.
-(defvar ffap-machine-p-local 'reject ; this happens often
- "*A symbol, one of: ping, accept, reject.
-What `ffap-machine-p' does with hostnames that have no domain.")
-(defvar ffap-machine-p-known 'ping ; 'accept for speed
- "*A symbol, one of: ping, accept, reject.
-What `ffap-machine-p' does with hostnames that have a known domain
-\(see mail-extr.el for the known domains\).")
-(defvar ffap-machine-p-unknown 'reject
- "*A symbol, one of: ping, accept, reject.
-What `ffap-machine-p' does with hostnames that have an unknown domain
-\(see mail-extr.el for the known domains\).")
-
-(defun ffap-what-domain (domain)
- ;; Like what-domain in mail-extr.el, returns string or nil.
- (require 'mail-extr)
- (defvar mail-extr-all-top-level-domains
- (ffap-soft-value "all-top-level-domains" obarray)) ; XEmacs, old Emacs
- (get (intern-soft (downcase domain) mail-extr-all-top-level-domains)
- 'domain-name))
-
-(defun ffap-machine-p (host &optional service quiet strategy)
- "Decide whether HOST is the name of a real, reachable machine.
-Depending on the domain (none, known, or unknown), follow the strategy
-named by the variable `ffap-machine-p-local', `ffap-machine-p-known',
-or `ffap-machine-p-unknown'. Pinging uses `open-network-stream'.
-Optional SERVICE specifies the port used \(default \"discard\"\).
-Optional QUIET flag suppresses the \"Pinging...\" message.
-Optional STRATEGY overrides the three variables above.
-Returned values:
- t means that HOST answered.
-'accept means the relevant variable told us to accept.
-\"mesg\" means HOST exists, but does not respond for some reason."
- ;; Try some (Emory local):
- ;; (ffap-machine-p "ftp" nil nil 'ping)
- ;; (ffap-machine-p "nonesuch" nil nil 'ping)
- ;; (ffap-machine-p "ftp.mathcs.emory.edu" nil nil 'ping)
- ;; (ffap-machine-p "mathcs" 5678 nil 'ping)
- ;; (ffap-machine-p "foo.bonk" nil nil 'ping)
- ;; (ffap-machine-p "foo.bonk.com" nil nil 'ping)
- (if (or (string-match "[^-a-zA-Z0-9.]" host) ; Illegal chars (?)
- (not (string-match "[^0-9]" host))) ; 1: a number? 2: quick reject
- nil
- (let* ((domain
- (and (string-match "\\.[^.]*$" host)
- (downcase (substring host (1+ (match-beginning 0))))))
- (what-domain (if domain (ffap-what-domain domain) "Local")))
- (or strategy
- (setq strategy
- (cond ((not domain) ffap-machine-p-local)
- ((not what-domain) ffap-machine-p-unknown)
- (t ffap-machine-p-known))))
- (cond
- ((eq strategy 'accept) 'accept)
- ((eq strategy 'reject) nil)
- ;; assume (eq strategy 'ping)
- (t
- (or quiet
- (if (stringp what-domain)
- (message "Pinging %s (%s)..." host what-domain)
- (message "Pinging %s ..." host)))
- (condition-case error
- (progn
- (delete-process
- (open-network-stream
- "ffap-machine-p" nil host (or service "discard")))
- t)
- (error
- (let ((mesg (car (cdr error))))
- (cond
- ;; v18:
- ((string-match "^Unknown host" mesg) nil)
- ((string-match "not responding$" mesg) mesg)
- ;; v19:
- ;; (file-error "connection failed" "permission denied"
- ;; "nonesuch" "ffap-machine-p")
- ;; (file-error "connection failed" "host is unreachable"
- ;; "gopher.house.gov" "ffap-machine-p")
- ;; (file-error "connection failed" "address already in use"
- ;; "ftp.uu.net" "ffap-machine-p")
- ((equal mesg "connection failed")
- (if (equal (nth 2 error) "permission denied")
- nil ; host does not exist
- ;; Other errors mean the host exists:
- (nth 2 error)))
- ;; Could be "Unknown service":
- (t (signal (car error) (cdr error))))))))))))
-
-(defun ffap-file-remote-p (filename)
- "If FILENAME looks remote, return it \(maybe slightly improved\)."
- ;; (ffap-file-remote-p "/user@foo.bar.com:/pub")
- ;; (ffap-file-remote-p "/cssun.mathcs.emory.edu://path")
- ;; (ffap-file-remote-p "/ffap.el:80")
- (or (and ffap-ftp-regexp
- (string-match ffap-ftp-regexp filename)
- ;; Convert "/host.com://path" to "/host:/path", to handle a dieing
- ;; practice of advertising ftp paths as "host.dom://path".
- (if (string-match "//" filename)
- ;; (replace-match "/" nil nil filename)
- (concat (substring filename 0 (1+ (match-beginning 0)))
- (substring filename (match-end 0)))
- filename))
- (and ffap-rfs-regexp
- (string-match ffap-rfs-regexp filename)
- filename)))
-
-(defun ffap-machine-at-point nil
- "Return machine name at point if it exists, or nil."
- (let ((mach (ffap-string-at-point 'machine)))
- (and (ffap-machine-p mach) mach)))
-
-(defsubst ffap-host-to-path (host)
- "Convert HOST to something like \"/anonymous@HOST:\".
-Looks at `ffap-ftp-default-user', returns \"\" for \"localhost\"."
- (if (equal host "localhost") ""
- (concat "/"
- ffap-ftp-default-user (and ffap-ftp-default-user "@")
- host ":")))
-
-(defun ffap-fixup-machine (mach)
- ;; Convert a hostname into an url, an ftp path, or nil.
- (cond
- ((not (and ffap-url-regexp (stringp mach))) nil)
- ;; gopher.well.com
- ((string-match "\\`gopher[-.]" mach) ; or "info"?
- (concat "gopher://" mach "/"))
- ;; www.ncsa.uiuc.edu
- ((and (string-match "\\`w\\(ww\\|eb\\)[-.]" mach))
- (concat "http://" mach "/"))
- ;; More cases? Maybe "telnet:" for archie?
- (ffap-ftp-regexp (ffap-host-to-path mach))
- ))
-
-(defun ffap-newsgroup-p (string)
- "Return STRING if it looks like a newsgroup name, else nil."
- (and
- (string-match ffap-newsgroup-regexp string)
- (let ((htbs '(gnus-active-hashtb gnus-newsrc-hashtb gnus-killed-hashtb))
- (heads ffap-newsgroup-heads)
- htb ret)
- (while htbs
- (setq htb (car htbs) htbs (cdr htbs))
- (condition-case nil
- (progn
- ;; errs: htb symbol may be unbound, or not a hash-table.
- ;; gnus-gethash is just a macro for intern-soft.
- (and (intern-soft string (symbol-value htb))
- (setq ret string htbs nil))
- ;; If we made it this far, gnus is running, so ignore "heads":
- (setq heads nil))
- (error nil)))
- (or ret (not heads)
- (let ((head (string-match "\\`\\([a-z]+\\)\\." string)))
- (and head (setq head (substring string 0 (match-end 1)))
- (member head heads)
- (setq ret string))))
- ;; Is there ever a need to modify string as a newsgroup name?
- ret)))
-(defvar ffap-newsgroup-regexp "^[a-z]+\\.[-+a-z_0-9.]+$"
- "Strings not matching this fail `ffap-newsgroup-p'.")
-(defvar ffap-newsgroup-heads ; entirely inadequate
- '("alt" "comp" "gnu" "misc" "news" "sci" "soc" "talk")
- "Used by `ffap-newsgroup-p' if gnus is not running.")
-
-(defsubst ffap-url-p (string)
- "If STRING looks like an url, return it (maybe improved), else nil."
- (let ((case-fold-search t))
- (and ffap-url-regexp (string-match ffap-url-regexp string)
- ;; I lied, no improvement:
- string)))
-
-;; Broke these out of ffap-fixup-url, for use of ffap-url package.
-(defsubst ffap-url-unwrap-local (url)
- "Return URL as a local file, or nil. Ignores `ffap-url-regexp'."
- (and (string-match "\\`\\(file\\|ftp\\):/?\\([^/]\\|\\'\\)" url)
- (substring url (1+ (match-end 1)))))
-(defsubst ffap-url-unwrap-remote (url)
- "Return URL as a remote file, or nil. Ignores `ffap-url-regexp'."
- (and (string-match "\\`\\(ftp\\|file\\)://\\([^:/]+\\):?\\(/.*\\)" url)
- (concat
- (ffap-host-to-path (substring url (match-beginning 2) (match-end 2)))
- (substring url (match-beginning 3) (match-end 3)))))
-;; Test: (ffap-url-unwrap-remote "ftp://foo.com/bar.boz")
-
-(defun ffap-fixup-url (url)
- "Clean up URL and return it, maybe as a file name."
- (cond
- ((not (stringp url)) nil)
- ((and ffap-url-unwrap-local (ffap-url-unwrap-local url)))
- ((and ffap-url-unwrap-remote ffap-ftp-regexp
- (ffap-url-unwrap-remote url)))
- ;; Do not load w3 just for this:
- (t (let ((normal (and (fboundp 'url-normalize-url)
- (url-normalize-url url))))
- ;; In case url-normalize-url is confused:
- (or (and normal (not (zerop (length normal))) normal)
- url)))))
-
-
-;;; `ffap-alist':
-;;
-;; Search actions depending on the major-mode or extensions of the
-;; current name. Note all the little defun's could be broken out, at
-;; some loss of locality. A good example of featuritis.
-
-;; First, some helpers for functions in `ffap-alist':
-
-(defun ffap-list-env (env &optional empty)
- ;; Replace this with parse-colon-path (lisp/files.el)?
- "Directory list parsed from path envinronment variable ENV.
-Optional EMPTY is default if (getenv ENV) is undefined, and is also
-substituted for the first empty-string component, if there is one.
-Uses `path-separator' to separate the path into directories."
- ;; Derived from psg-list-env in RHOGEE's ff-paths and
- ;; bib-cite packages. The `empty' argument is intended to mimic
- ;; the semantics of TeX/BibTeX variables, it is substituted for
- ;; any empty string entry.
- (if (or empty (getenv env)) ; should return something
- (let ((start 0) match dir ret)
- (setq env (concat (getenv env) path-separator))
- (while (setq match (string-match path-separator env start))
- (setq dir (substring env start match) start (1+ match))
- ;;(and (file-directory-p dir) (not (member dir ret)) ...)
- (setq ret (cons dir ret)))
- (setq ret (nreverse ret))
- (and empty (setq match (member "" ret))
- (progn
- (setcdr match (append (cdr-safe empty) (cdr match)))
- (setcar match (or (car-safe empty) empty))))
- ret)))
-
-(defun ffap-reduce-path (path)
- "Remove duplicates and non-directories from PATH list."
- (let (ret tem)
- (while path
- (setq tem path path (cdr path))
- (if (equal (car tem) ".") (setcar tem ""))
- (or (member (car tem) ret)
- (not (file-directory-p (car tem)))
- (progn (setcdr tem ret) (setq ret tem))))
- (nreverse ret)))
-
-(defun ffap-add-subdirs (path)
- "Return PATH augmented with its immediate subdirectories."
- ;; (ffap-add-subdirs '("/notexist" "~"))
- (let (ret subs)
- (while path
- (mapcar
- (function
- (lambda (f) (and (file-directory-p f) (setq ret (cons f ret)))))
- (condition-case nil
- (directory-files (car path) t "[^.]")
- (error nil)))
- (setq ret (cons (car path) ret)
- path (cdr path)))
- (nreverse ret)))
-
-(defvar ffap-alist
- ;; A big mess! Parts are probably useless.
- (list
- (cons "\\.info\\'"
- (defun ffap-info (name)
- (locate-library
- name '("" ".info")
- (or (ffap-soft-value "Info-directory-list")
- (ffap-soft-value "Info-default-directory-list")
- ;; v18:
- (list (ffap-soft-value "Info-directory" "~/info/"))))))
- ;; Since so many info files do not have .info extension, also do this:
- (cons "\\`info/"
- (defun ffap-info-2 (name) (ffap-info (substring name 5))))
- (cons "\\`[-a-z]+\\'"
- ;; This ignores the node! "(emacs)Top" same as "(emacs)Intro"
- (defun ffap-info-3 (name)
- (and (equal (ffap-string-around) "()") (ffap-info name))))
- (cons "\\.elc?\\'"
- (defun ffap-el (name) (locate-library name t)))
- (cons 'emacs-lisp-mode
- (defun ffap-el-mode (name)
- ;; We do not bother with "" here, since it was considered above.
- ;; Also ignore "elc", for speed (who else reads elc files?)
- (and (not (string-match "\\.el\\'" name))
- (locate-library name '(".el")))))
- '(finder-mode . ffap-el-mode) ; v19: {C-h p}
- '(help-mode . ffap-el-mode) ; v19.29
- (cons 'c-mode
- (progn
- ;; Need better defaults here!
- (defvar ffap-c-path '("/usr/include" "/usr/local/include"))
- (defun ffap-c-mode (name)
- (locate-library name t ffap-c-path))))
- '(c++-mode . ffap-c-mode)
- '(cc-mode . ffap-c-mode)
- '("\\.\\([chCH]\\|cc\\|hh\\)\\'" . ffap-c-mode)
- (cons 'tex-mode
- ;; Complicated because auctex may not be loaded yet.
- (progn
- (defvar ffap-tex-path
- t ; delayed initialization
- "Path where `ffap-tex-mode' looks for tex files.
-If t, `ffap-tex-init' will initialize this when needed.")
- (defun ffap-tex-init nil
- ;; Compute ffap-tex-path if it is now t.
- (and (eq t ffap-tex-path)
- (message "Initializing ffap-tex-path ...")
- (setq ffap-tex-path
- (ffap-reduce-path
- (append
- (list ".")
- (ffap-list-env "TEXINPUTS")
- ;; (ffap-list-env "BIBINPUTS")
- (ffap-add-subdirs
- (ffap-list-env "TEXINPUTS_SUBDIR"
- (ffap-soft-value
- "TeX-macro-global"
- '("/usr/local/lib/tex/macros"
- "/usr/local/lib/tex/inputs")
- ))))))))
- (defun ffap-tex-mode (name)
- (ffap-tex-init)
- (locate-library name '(".tex" "") ffap-tex-path))))
- (cons 'latex-mode
- (defun ffap-latex-mode (name)
- (ffap-tex-init)
- ;; Any real need for "" here?
- (locate-library name '(".cls" ".sty" ".tex" "")
- ffap-tex-path)))
- (cons "\\.\\(tex\\|sty\\|doc\\|cls\\)\\'"
- (defun ffap-tex (name)
- (ffap-tex-init)
- (locate-library name t ffap-tex-path)))
- (cons "\\.bib\\'"
- (defun ffap-bib (name)
- (locate-library
- name t
- (ffap-list-env "BIBINPUTS" '("/usr/local/lib/tex/macros/bib")))))
- (cons 'math-mode
- (defun ffap-math-mode (name)
- (while (string-match "`" name)
- (setq name (concat (substring name 0 (match-beginning 0))
- "/"
- (substring name (match-end 0)))))
- (locate-library
- name '(".m" "") (ffap-soft-value "Mathematica-search-path"))))
- (cons "\\`\\." (defun ffap-home (name) (locate-library name t '("~"))))
- (cons "\\`~/"
- ;; Maybe a "Lisp Code Directory" reference:
- (defun ffap-lcd (name)
- (and
- (or
- ;; lisp-dir-apropos output buffer:
- (string-match "Lisp Code Dir" (buffer-name))
- ;; Inside an LCD entry like |~/misc/ffap.el.Z|,
- ;; or maybe the holy LCD-Datafile itself:
- (member (ffap-string-around) '("||" "|\n")))
- (concat
- ;; lispdir.el may not be loaded yet:
- (ffap-host-to-path
- (ffap-soft-value "elisp-archive-host"
- "archive.cis.ohio-state.edu"))
- (file-name-as-directory
- (ffap-soft-value "elisp-archive-directory"
- "/pub/gnu/emacs/elisp-archive/"))
- (substring name 2)))))
- (cons "^[Rr][Ff][Cc][- #]?\\([0-9]+\\)" ; no $
- (progn
- (defvar ffap-rfc-path
- (concat (ffap-host-to-path "ds.internic.net") "/rfc/rfc%s.txt"))
- (defun ffap-rfc (name)
- (format ffap-rfc-path
- (substring name (match-beginning 1) (match-end 1))))))
- (cons "\\`[^/]*\\'"
- (defun ffap-dired (name)
- (let ((pt (point)) dir try)
- (save-excursion
- (and (progn
- (beginning-of-line)
- (looking-at " *[-d]r[-w][-x][-r][-w][-x][-r][-w][-x] "))
- (re-search-backward "^ *$" nil t)
- (re-search-forward "^ *\\([^ \t\n:]*\\):\n *total " pt t)
- (file-exists-p
- (setq try
- (expand-file-name
- name
- (buffer-substring
- (match-beginning 1) (match-end 1)))))
- try)))))
- )
- "Alist of \(KEY . FUNCTION\) pairs parsed by `ffap-file-at-point'.
-If string NAME at point (maybe \"\") is not a file or url, these pairs
-specify actions to try creating such a string. A pair matches if either
- KEY is a symbol, and it equals `major-mode', or
- KEY is a string, it should matches NAME as a regexp.
-On a match, \(FUNCTION NAME\) is called and should return a file, an
-url, or nil. If nil, search the alist for further matches.")
-
-(put 'ffap-alist 'risky-local-variable t)
-
-
-;;; At-Point Functions:
-
-(defvar ffap-string-at-point-mode-alist
- '(
- ;; The default, used when the `major-mode' is not found.
- ;; Slightly controversial decisions:
- ;; * strip trailing "@" and ":"
- ;; * no commas (good for latex)
- (file "--:$+<>@-Z_a-z~" "<@" "@>;.,!?:")
- ;; An url, or maybe a email/news message-id:
- (url "--:?$+@-Z_a-z~#,%" "^A-Za-z0-9" ":;.,!?")
- ;; Find a string that does *not* contain a colon:
- (nocolon "--9$+<>@-Z_a-z~" "<@" "@>;.,!?")
- ;; A machine:
- (machine "-a-zA-Z0-9." "" ".")
- ;; Mathematica paths: allow backquotes
- (math-mode ",-:$+<>@-Z_a-z~`" "<" "@>;.,!?`:")
- )
- "Alist of \(MODE CHARS BEG END\), where MODE is a symbol,
-possibly a `major-mode' or some symbol internal to ffap
-\(such as 'file, 'url, 'machine, and 'nocolon\).
-`ffap-string-at-point' uses the data fields as follows:
-1. find a maximal string of CHARS around point,
-2. strip BEG chars before point from the beginning,
-3. Strip END chars after point from the end.")
-
-(defvar ffap-string-at-point-region '(1 1)
- "List (BEG END), last region returned by `ffap-string-at-point'.")
-
-(defvar ffap-string-at-point nil
- ;; Added at suggestion of RHOGEE (for ff-paths), 7/24/95.
- "Last string returned by `ffap-string-at-point'.")
-
-(defun ffap-string-at-point (&optional mode)
- "Return a string of characters from around point.
-MODE (defaults to `major-mode') is a symbol used to lookup string
-syntax parameters in `ffap-string-at-point-mode-alist'.
-If MODE is not found, we fall back on the symbol 'file.
-Sets `ffap-string-at-point' and `ffap-string-at-point-region'."
- (let* ((args
- (cdr
- (or (assq (or mode major-mode) ffap-string-at-point-mode-alist)
- (assq 'file ffap-string-at-point-mode-alist))))
- (pt (point))
- (str
- (buffer-substring
- (save-excursion
- (skip-chars-backward (car args))
- (skip-chars-forward (nth 1 args) pt)
- (setcar ffap-string-at-point-region (point)))
- (save-excursion
- (skip-chars-forward (car args))
- (skip-chars-backward (nth 2 args) pt)
- (setcar (cdr ffap-string-at-point-region) (point))))))
- (or ffap-xemacs (set-text-properties 0 (length str) nil str))
- (setq ffap-string-at-point str)))
-
-(defun ffap-string-around nil
- ;; Sometimes useful to decide how to treat a string.
- "Return string of two chars around last `ffap-string-at-point'.
-Assumes the buffer has not changed."
- (save-excursion
- (format "%c%c"
- (progn
- (goto-char (car ffap-string-at-point-region))
- (preceding-char)) ; maybe 0
- (progn
- (goto-char (nth 1 ffap-string-at-point-region))
- (following-char)) ; maybe 0
- )))
-
-(defun ffap-copy-string-as-kill (&optional mode)
- ;; Requested by MCOOK. Useful?
- "Call `ffap-string-at-point', and copy result to `kill-ring'."
- (interactive)
- (let ((str (ffap-string-at-point mode)))
- (if (equal "" str)
- (message "No string found around point.")
- (kill-new str)
- ;; Older: (apply 'copy-region-as-kill ffap-string-at-point-region)
- (message "Copied to kill ring: %s" str))))
-
-(defun ffap-url-at-point nil
- "Return url from around point if it exists, or nil."
- ;; Could use w3's url-get-url-at-point instead. Both handle "URL:",
- ;; ignore non-relative links, trim punctuation. The other will
- ;; actually look back if point is in whitespace, but I would rather
- ;; ffap be non-rabid in such situations.
- (and
- ffap-url-regexp
- (or
- ;; In a w3 buffer button zone?
- (let (tem)
- (and (eq major-mode 'w3-mode)
- ;; assume: (boundp 'w3-zone-at) (boundp 'w3-zone-data)
- (setq tem (w3-zone-at (point)))
- (consp (setq tem (w3-zone-data tem)))
- (nth 2 tem)))
- ;; Is there a reason not to strip trailing colon?
- (let ((name (ffap-string-at-point 'url)))
- ;; (case-fold-search t), why?
- (cond
- ((string-match "^url:" name) (setq name (substring name 4)))
- ((and (string-match "\\`[^:</>@]+@[^:</>@]+[a-zA-Z]\\'" name)
- ;; "foo@bar": could be "mailto" or "news" (a Message-ID).
- ;; If not adorned with "<>", it must be "mailto".
- ;; Otherwise could be either, so consult `ffap-foo-at-bar-prefix'.
- (let ((prefix (if (and (equal (ffap-string-around) "<>")
- ;; At least a couple of odd characters:
- (string-match "[$.0-9].*[$.0-9].*@" name))
- ;; Could be news:
- ffap-foo-at-bar-prefix
- "mailto")))
- (and prefix (setq name (concat prefix ":" name))))))
- ((ffap-newsgroup-p name) (setq name (concat "news:" name)))
- ((and (string-match "\\`[a-z0-9]+\\'" name) ; <mic> <root> <nobody>
- (equal (ffap-string-around) "<>")
- ;; (ffap-user-p name):
- (not (string-match "~" (expand-file-name (concat "~" name))))
- )
- (setq name (concat "mailto:" name)))
- )
- (and (ffap-url-p name) name)
- ))))
-
-(defvar ffap-gopher-regexp
- "^.*\\<\\(Type\\|Name\\|Path\\|Host\\|Port\\) *= *\\(.*\\) *$"
- "Regexp Matching a line in a gopher bookmark (maybe indented).
-The two subexpressions are the KEY and VALUE.")
-
-(defun ffap-gopher-at-point nil
- "If point is inside a gopher bookmark block, return its url."
- ;; `gopher-parse-bookmark' from gopher.el is not so robust
- (save-excursion
- (beginning-of-line)
- (if (looking-at ffap-gopher-regexp)
- (progn
- (while (and (looking-at ffap-gopher-regexp) (not (bobp)))
- (forward-line -1))
- (or (looking-at ffap-gopher-regexp) (forward-line 1))
- (let ((type "1") name path host (port "70"))
- (while (looking-at ffap-gopher-regexp)
- (let ((var (intern
- (downcase
- (buffer-substring (match-beginning 1)
- (match-end 1)))))
- (val (buffer-substring (match-beginning 2)
- (match-end 2))))
- (set var val)
- (forward-line 1)))
- (if (and path (string-match "^ftp:.*@" path))
- (concat "ftp://"
- (substring path 4 (1- (match-end 0)))
- (substring path (match-end 0)))
- (and (= (length type) 1)
- host;; (ffap-machine-p host)
- (concat "gopher://" host
- (if (equal port "70") "" (concat ":" port))
- "/" type path))))))))
-
-(defvar ffap-ftp-sans-slash-regexp
- (and
- ffap-ftp-regexp
- ;; Note: by now, we know it is not an url.
- ;; Icky regexp avoids: default: 123: foo::bar cs:pub
- ;; It does match on: mic@cs: cs:/pub mathcs.emory.edu: (point at end)
- "\\`\\([^:@]+@[^:@]+:\\|[^@.:]+\\.[^@:]+:\\|[^:]+:[~/]\\)\\([^:]\\|\\'\\)")
- "Strings matching this are coerced to ftp paths by ffap.
-That is, ffap just prepends \"/\". Set to nil to disable.")
-
-(defun ffap-file-at-point nil
- "Return filename from around point if it exists, or nil.
-Existence test is skipped for names that look remote.
-If the filename is not obvious, it also tries `ffap-alist',
-which may actually result in an url rather than a filename."
- ;; Note: this function does not need to look for url's, just
- ;; filenames. On the other hand, it is responsible for converting
- ;; a pseudo-url "site.com://path" to an ftp path
- (let* ((case-fold-search t) ; url prefixes are case-insensitive
- (data (match-data))
- (string (ffap-string-at-point)) ; uses mode alist
- (name
- (or (condition-case nil
- (and (not (string-match "//" string)) ; foo.com://bar
- (substitute-in-file-name string))
- (error nil))
- string))
- (abs (file-name-absolute-p name))
- (default-directory default-directory))
- (unwind-protect
- (cond
- ;; Immediate rejects (/ and // are too common in C++):
- ((member name '("" "/" "//")) nil)
- ;; Immediately test local filenames. If default-directory is
- ;; remote, you probably already have a connection.
- ((and (not abs) (ffap-file-exists-string name)))
- ;; Accept remote names without actual checking (too slow):
- ((if abs
- (ffap-file-remote-p name)
- ;; Try adding a leading "/" (common omission in ftp paths):
- (and
- ffap-ftp-sans-slash-regexp
- (string-match ffap-ftp-sans-slash-regexp name)
- (ffap-file-remote-p (concat "/" name)))))
- ;; Ok, not remote, try the existence test even if it is absolute:
- ((and abs (ffap-file-exists-string name)))
- ;; If it contains a colon, get rid of it (and return if exists)
- ((and (string-match path-separator name)
- (setq name (ffap-string-at-point 'nocolon))
- (ffap-file-exists-string name)))
- ;; File does not exist, try the alist:
- ((let ((alist ffap-alist) tem try case-fold-search)
- (while (and alist (not try))
- (setq tem (car alist) alist (cdr alist))
- (if (or (eq major-mode (car tem))
- (and (stringp (car tem))
- (string-match (car tem) name)))
- (and (setq try (funcall (cdr tem) name))
- (setq try (or
- (ffap-url-p try) ; not a file!
- (ffap-file-remote-p try)
- (ffap-file-exists-string try))))))
- try))
- ;; Alist failed? Try to guess an active remote connection
- ;; from buffer variables, and try once more, both as an
- ;; absolute and relative path on that remote host.
- ((let* (ffap-rfs-regexp ; suppress
- (remote-dir
- (cond
- ((ffap-file-remote-p default-directory))
- ((and (eq major-mode 'internal-ange-ftp-mode)
- (string-match "^\\*ftp \\(.*\\)@\\(.*\\)\\*$"
- (buffer-name)))
- (concat "/" (substring (buffer-name) 5 -1) ":"))
- ;; This is too often a bad idea:
- ;;((and (eq major-mode 'w3-mode)
- ;; (stringp url-current-server))
- ;; (host-to-ange-path url-current-server))
- )))
- (and remote-dir
- (or
- (and (string-match "\\`\\(/?~?ftp\\)/" name)
- (ffap-file-exists-string
- (ffap-replace-path-component
- remote-dir (substring name (match-end 1)))))
- (ffap-file-exists-string
- (ffap-replace-path-component remote-dir name))))))
- )
- (store-match-data data))))
-
-
-;;; ffap-read-file-or-url:
-;;
-;; We want to complete filenames as in read-file-name, but also url's
-;; which read-file-name-internal would truncate at the "//" string.
-;; The solution here is to replace read-file-name-internal with
-;; `ffap-read-file-or-url-internal', which checks the minibuffer
-;; contents before attempting to complete filenames.
-
-(defun ffap-read-file-or-url (prompt guess)
- "Read file or url from minibuffer, with PROMPT and initial GUESS."
- (or guess (setq guess default-directory))
- (let (dir)
- ;; Tricky: guess may have or be a local directory, like "w3/w3.elc"
- ;; or "w3/" or "../el/ffap.el" or "../../../"
- (or (ffap-url-p guess)
- (progn
- (or (ffap-file-remote-p guess)
- (setq guess (abbreviate-file-name (expand-file-name guess))))
- (setq dir (file-name-directory guess))))
- (setq guess
- (completing-read
- prompt
- 'ffap-read-file-or-url-internal
- dir
- nil
- (if dir (cons guess (length dir)) guess)
- (list 'file-name-history)
- ))
- ;; Do file substitution like (interactive "F"), suggested by MCOOK.
- (or (ffap-url-p guess) (setq guess (substitute-in-file-name guess)))
- ;; Should not do it on url's, where $ is a common (VMS?) character.
- ;; Note: upcoming url.el package ought to handle this automatically.
- guess))
-
-(defun ffap-read-url-internal (string dir action)
- "Complete url's from history, treating given string as valid."
- (let ((hist (ffap-soft-value "url-global-history-hash-table")))
- (cond
- ((not action)
- (or (try-completion string hist) string))
- ((eq action t)
- (or (all-completions string hist) (list string)))
- ;; action == lambda, documented where? Tests whether string is a
- ;; valid "match". Let us always say yes.
- (t t))))
-
-(defun ffap-read-file-or-url-internal (string dir action)
- (if (ffap-url-p string)
- (ffap-read-url-internal string dir action)
- (read-file-name-internal string dir action)))
-
-;; The rest of this page is just to work with package complete.el.
-;; This code assumes that you load ffap.el after complete.el.
-;;
-;; We must inform complete about whether our completion function
-;; will do filename style completion. For earlier versions of
-;; complete.el, this requires a defadvice. For recent versions
-;; there may be a special variable for this purpose.
-
-(defun ffap-complete-as-file-p nil
- ;; Will `minibuffer-completion-table' complete the minibuffer
- ;; contents as a filename? Assumes the minibuffer is current.
- ;; Note: t and non-nil mean somewhat different reasons.
- (if (eq minibuffer-completion-table 'ffap-read-file-or-url-internal)
- (not (ffap-url-p (buffer-string))) ; t
- (memq minibuffer-completion-table
- '(read-file-name-internal read-directory-name-internal)) ; list
- ))
-
-(and
- (featurep 'complete)
- (if (boundp 'PC-completion-as-file-name-predicate)
- ;; modern version of complete.el, just set the variable:
- (setq PC-completion-as-file-name-predicate 'ffap-complete-as-file-p)
- (require 'advice)
- (defadvice PC-do-completion (around ffap-fix act)
- "Work with ffap."
- (let ((minibuffer-completion-table
- (if (eq t (ffap-complete-as-file-p))
- 'read-file-name-internal
- minibuffer-completion-table)))
- ad-do-it))))
-
-
-;;; Highlighting:
-;;
-;; Based on overlay highlighting in Emacs 19.28 isearch.el.
-
-(defvar ffap-highlight (and window-system t)
- "If non-nil, ffap highlights the current buffer substring.")
-
-(defvar ffap-highlight-overlay nil "Overlay used by `ffap-highlight'.")
-
-(defun ffap-highlight (&optional remove)
- "If `ffap-highlight' is set, highlight the guess in this buffer.
-That is, the last buffer substring found by `ffap-string-at-point'.
-Optional argument REMOVE means to remove any such highlighting.
-Uses the face `ffap' if it is defined, or else `highlight'."
- (cond
- (remove (and ffap-highlight-overlay (delete-overlay ffap-highlight-overlay)))
- ((not ffap-highlight) nil)
- (ffap-highlight-overlay
- (move-overlay ffap-highlight-overlay
- (car ffap-string-at-point-region)
- (nth 1 ffap-string-at-point-region)
- (current-buffer)))
- (t
- (setq ffap-highlight-overlay (apply 'make-overlay ffap-string-at-point-region))
- (overlay-put ffap-highlight-overlay 'face
- (if (internal-find-face 'ffap nil)
- 'ffap 'highlight)))))
-
-
-;;; The big enchilada:
-
-(defun ffap-guesser nil
- "Return file or url or nil, guessed from text around point."
- (or (and ffap-url-regexp
- (ffap-fixup-url (or (ffap-url-at-point)
- (ffap-gopher-at-point))))
- (ffap-file-at-point) ; may yield url!
- (ffap-fixup-machine (ffap-machine-at-point))))
-
-(defun ffap-prompter (&optional guess)
- ;; Does guess and prompt step for find-file-at-point.
- ;; Extra complication for the temporary highlighting.
- (unwind-protect
- (ffap-read-file-or-url
- (if ffap-url-regexp "Find file or URL: " "Find file: ")
- (prog1
- (setq guess (or guess (ffap-guesser)))
- (and guess (ffap-highlight))
- ))
- (ffap-highlight t)))
-
-;;;###autoload
-(defun find-file-at-point (&optional filename)
- "Find FILENAME (or url), guessing default from text around point.
-If `ffap-dired-wildcards' is set, wildcard patterns are passed to dired.
-See also the functions `ffap-file-at-point', `ffap-url-at-point'.
-With a prefix, this command behaves *exactly* like `ffap-file-finder'.
-If `ffap-require-prefix' is set, the prefix meaning is reversed.
-
-See <ftp://ftp.mathcs.emory.edu/pub/mic/emacs/> for latest version."
- (interactive)
- (if (and (interactive-p)
- (if ffap-require-prefix (not current-prefix-arg)
- current-prefix-arg))
- ;; Do exactly the ffap-file-finder command, even the prompting:
- (let (current-prefix-arg) ; we already interpreted it
- (call-interactively ffap-file-finder))
- (or filename (setq filename (ffap-prompter)))
- (cond
- ((ffap-url-p filename)
- (let (current-prefix-arg) ; w3 2.3.25 bug, reported by KPC
- (funcall ffap-url-fetcher filename)))
- ;; This junk more properly belongs in a modified ffap-file-finder:
- ((and ffap-dired-wildcards
- (string-match ffap-dired-wildcards filename))
- (dired filename))
- ((or (not ffap-newfile-prompt)
- (file-exists-p filename)
- (y-or-n-p "File does not exist, create buffer? "))
- (funcall ffap-file-finder
- ;; expand-file-name fixes "~/~/.emacs" bug sent by CHUCKR.
- (expand-file-name filename)))
- ;; User does not want to find a non-existent file:
- ((signal 'file-error (list "Opening file buffer"
- "no such file or directory"
- filename))))))
-
-;; M-x shortcut:
-;;###autoload
-(defalias 'ffap 'find-file-at-point)
-
-
-;;; Menu support:
-;;
-;; Bind ffap-menu to a key if you want, since it also works in tty mode.
-;; Or just use it through the ffap-at-mouse binding (next section).
-
-(defvar ffap-menu-regexp nil
- "*If non-nil, overrides `ffap-next-regexp' during `ffap-menu'.
-Make this more restrictive for faster menu building.
-For example, try \":/\" for url (and some ftp) references.")
-
-(defvar ffap-menu-alist nil
- "Buffer local cache of menu presented by `ffap-menu'.")
-(make-variable-buffer-local 'ffap-menu-alist)
-
-(defvar ffap-menu-text-plist
- (and window-system
- ;; These choices emulate goto-addr:
- (if ffap-xemacs
- '(face bold highlight t) ; keymap <map>
- '(face bold mouse-face highlight) ; keymap <mousy-map>
- ))
- "Text properties applied to strings found by `ffap-menu-rescan'.
-These properties may be used to fontify the menu references.")
-
-;;;###autoload
-(defun ffap-menu (&optional rescan)
- "Put up a menu of files and urls mentioned in this buffer.
-Then set mark, jump to choice, and try to fetch it. The menu is
-cached in `ffap-menu-alist', and rebuilt by `ffap-menu-rescan'.
-The optional RESCAN argument \(a prefix, interactively\) forces
-a rebuild. Searches with `ffap-menu-regexp'."
- (interactive "P")
- ;; (require 'imenu) -- no longer used, but roughly emulated
- (if (or (not ffap-menu-alist) rescan
- ;; or if the first entry is wrong:
- (and ffap-menu-alist
- (let ((first (car ffap-menu-alist)))
- (save-excursion
- (goto-char (cdr first))
- (not (equal (car first) (ffap-guesser)))))))
- (ffap-menu-rescan))
- ;; Tail recursive:
- (ffap-menu-ask
- (if ffap-url-regexp "Find file or URL" "Find file")
- (cons (cons "*Rescan Buffer*" -1) ffap-menu-alist)
- 'ffap-menu-cont))
-
-(defun ffap-menu-cont (choice) ; continuation of ffap-menu
- (if (< (cdr choice) 0)
- (ffap-menu t) ; *Rescan*
- (push-mark)
- (goto-char (cdr choice))
- ;; Momentary highlight:
- (unwind-protect
- (progn
- (and ffap-highlight (ffap-guesser) (ffap-highlight))
- (sit-for 0) ; display
- (find-file-at-point (car choice)))
- (ffap-highlight t))))
-
-(defun ffap-menu-ask (title alist cont)
- "Prompt from a menu of choices, and then apply some action.
-Arguments are TITLE, ALIST, and CONT (a continuation).
-This uses either a menu or the minibuffer depending on invocation.
-The TITLE string is used as either the prompt or menu title.
-Each \(string . data\) ALIST entry defines a choice \(data is ignored\).
-Once the user makes a choice, function CONT is applied to the entry.
-Always returns nil."
- ;; Bug: minibuffer prompting assumes the strings are unique.
- (let ((choice
- (if (and (fboundp 'x-popup-menu) ; Emacs 19 or XEmacs 19.13
- (boundp 'last-nonmenu-event) ; not in XEmacs 19.13
- (listp last-nonmenu-event))
- (x-popup-menu
- t
- (list ""
- (cons title
- (mapcar
- (function (lambda (i) (cons (car i) i)))
- alist))))
- ;; Immediately popup completion buffer:
- (prog1
- (let ((minibuffer-setup-hook 'minibuffer-completion-help))
- ;; BUG: this code assumes that "" is not a valid choice
- (completing-read
- (format "%s (default %s): " title (car (car alist)))
- alist nil t
- ;; (cons (car (car alist)) 0)
- nil
- ))
- ;; Redraw original screen:
- (sit-for 0)))))
- ;; Defaulting: convert "" to (car (car alist))
- (and (equal choice "") (setq choice (car (car alist))))
- (and (stringp choice) (setq choice (assoc choice alist)))
- (if choice (funcall cont choice) (message "No choice made!")))
- nil) ; return nothing
-
-(defun ffap-menu-rescan nil
- "Search buffer for `ffap-menu-regexp' to build `ffap-menu-alist'.
-Applies `ffap-menu-text-plist' text properties at all matches."
- (interactive)
- (let ((ffap-next-regexp (or ffap-menu-regexp ffap-next-regexp))
- (range (- (point-max) (point-min))) item
- buffer-read-only ; to set text-properties
- ;; Avoid repeated searches of the *mode-alist:
- (major-mode (if (assq major-mode ffap-string-at-point-mode-alist)
- major-mode
- 'file))
- )
- (setq ffap-menu-alist nil)
- (save-excursion
- (goto-char (point-min))
- (while (setq item (ffap-next-guess))
- (setq ffap-menu-alist (cons (cons item (point)) ffap-menu-alist))
- (add-text-properties (car ffap-string-at-point-region) (point)
- ffap-menu-text-plist)
- (message "Scanning...%2d%% <%s>"
- (/ (* 100 (- (point) (point-min))) range) item))))
- (message "Scanning...done")
- ;; Remove duplicates.
- (setq ffap-menu-alist ; sort by item
- (sort ffap-menu-alist
- (function
- (lambda (a b) (string-lessp (car a) (car b))))))
- (let ((ptr ffap-menu-alist))
- (while (cdr ptr)
- (if (equal (car (car ptr)) (car (car (cdr ptr))))
- (setcdr ptr (cdr (cdr ptr)))
- (setq ptr (cdr ptr)))))
- (setq ffap-menu-alist ; sort by position
- (sort ffap-menu-alist
- (function
- (lambda (a b) (< (cdr a) (cdr b)))))))
-
-
-;;; Mouse Support:
-;;
-;; See the suggested binding in ffap-bindings (near eof).
-
-(defvar ffap-at-mouse-fallback 'ffap-menu
- "Invoked by `ffap-at-mouse' if no file or url at click.
-A command symbol, or nil for nothing.")
-(put 'ffap-at-mouse-fallback 'risky-local-variable t)
-
-(defun ffap-at-mouse (e)
- "Find file or url guessed from text around mouse point.
-If none is found, call `ffap-at-mouse-fallback'."
- (interactive "e")
- (let ((guess
- ;; Maybe less surprising without the save-excursion?
- (save-excursion
- (mouse-set-point e)
- ;; Would like to do nothing unless click was *on* text. How?
- ;; (cdr (posn-col-row (event-start e))) is always same as
- ;; current column. For posn-x-y, need pixel-width!
- (ffap-guesser))))
- (cond
- (guess
- (ffap-highlight)
- (unwind-protect
- (progn
- (sit-for 0) ; display
- (message "Guessing `%s'" guess)
- (find-file-at-point guess))
- (ffap-highlight t)))
- ((and (interactive-p)
- ffap-at-mouse-fallback)
- (call-interactively ffap-at-mouse-fallback))
- ((message "No file or URL found at mouse click.")))))
-
-
-;;; ffap-other-* commands
-;; Suggested by KPC.
-
-(defun ffap-other-window nil
- "Like `ffap', but put buffer in another window."
- (interactive)
- (switch-to-buffer-other-window
- (save-window-excursion (call-interactively 'ffap) (current-buffer))))
-
-(defun ffap-other-frame nil
- "Like `ffap', but put buffer in another frame."
- (interactive)
- (switch-to-buffer-other-frame
- (save-window-excursion (call-interactively 'ffap) (current-buffer))))
-
-
-;;; Bug Reporter:
-
-(defun ffap-bug nil
- "Submit a bug report for the ffap package."
- ;; Important: keep the version string here in synch with that at top
- ;; of file! Could use lisp-mnt from Emacs 19, but that would depend
- ;; on being able to find the ffap.el source file.
- (interactive)
- (require 'reporter)
- (let ((reporter-prompt-for-summary-p t))
- (reporter-submit-bug-report
- "Michelangelo Grigni <mic@mathcs.emory.edu>"
- "ffap 1.6"
- (mapcar 'intern (all-completions "ffap-" obarray 'boundp)))))
-
-(fset 'ffap-submit-bug 'ffap-bug) ; another likely name
-
-
-;;; Hooks for Gnus, VM, Rmail:
-;;
-;; If you do not like these bindings, write versions with whatever
-;; bindings you would prefer.
-
-(defun ffap-ro-mode-hook nil
- "Bind `ffap-next' and `ffap-menu' to M-l and M-m, resp."
- (local-set-key "\M-l" 'ffap-next)
- (local-set-key "\M-m" 'ffap-menu)
- )
-
-(defun ffap-gnus-hook nil
- "Bind `ffap-gnus-next' and `ffap-gnus-menu' to M-l and M-m, resp."
- (set (make-local-variable 'ffap-foo-at-bar-prefix) "news") ; message-id's
- ;; Note "l", "L", "m", "M" are taken:
- (local-set-key "\M-l" 'ffap-gnus-next)
- (local-set-key "\M-m" 'ffap-gnus-menu))
-
-(defun ffap-gnus-wrapper (form) ; used by both commands below
- (and (eq (current-buffer) (get-buffer gnus-summary-buffer))
- (gnus-summary-select-article)) ; get article of current line
- ;; Preserve selected buffer, but do not do save-window-excursion,
- ;; since we want to see any window created by the form. Temporarily
- ;; select the article buffer, so we can see any point movement.
- (let ((sb (window-buffer (selected-window))))
- (gnus-configure-windows 'article)
- (pop-to-buffer gnus-article-buffer)
- (widen)
- ;; Skip headers for ffap-gnus-next (which will wrap around)
- (if (eq (point) (point-min)) (search-forward "\n\n" nil t))
- (unwind-protect
- (eval form)
- (pop-to-buffer sb))))
-
-(defun ffap-gnus-next nil
- "Run `ffap-next' in the gnus article buffer."
- (interactive) (ffap-gnus-wrapper '(ffap-next nil t)))
-
-(defun ffap-gnus-menu nil
- "Run `ffap-menu' in the gnus article buffer."
- (interactive) (ffap-gnus-wrapper '(ffap-menu)))
-
-
-;;; ffap-bindings: offer default global bindings
-
-(defvar ffap-bindings
- (nconc
- (cond
- ((not (eq window-system 'x))
- nil)
- ;; GNU coding standards say packages should not bind S-mouse-*.
- ;; Is it ok to simply suggest such a binding to the user?
- (ffap-xemacs
- '((global-set-key '(shift button3) 'ffap-at-mouse)))
- (t
- '((global-set-key [S-down-mouse-3] 'ffap-at-mouse))))
- '(
- (global-set-key "\C-x\C-f" 'find-file-at-point)
- (global-set-key "\C-x4f" 'ffap-other-window)
- (global-set-key "\C-x5f" 'ffap-other-frame)
- (add-hook 'gnus-summary-mode-hook 'ffap-gnus-hook)
- (add-hook 'gnus-article-mode-hook 'ffap-gnus-hook)
- (add-hook 'vm-mode-hook 'ffap-ro-mode-hook)
- (add-hook 'rmail-mode-hook 'ffap-ro-mode-hook)
- ;; (setq dired-x-hands-off-my-keys t) ; the default
- ))
- "List of forms evaluated by function `ffap-bindings'.
-A reasonable ffap installation needs just these two lines:
- (require 'ffap)
- (ffap-bindings)
-These are only suggestions, they may be modified or ignored.")
-
-(defun ffap-bindings nil
- "Evaluate the forms in variable `ffap-bindings'."
- (eval (cons 'progn ffap-bindings)))
-
-;; Example modifications:
-;;
-;; (setq ffap-alist ; remove a feature in `ffap-alist'
-;; (delete (assoc 'c-mode ffap-alist) ffap-alist))
-;;
-;; (setq ffap-alist ; add something to `ffap-alist'
-;; (cons
-;; (cons "^[Yy][Ss][Nn][0-9]+$"
-;; (defun ffap-ysn (name)
-;; (concat
-;; "http://snorri.chem.washington.edu/ysnarchive/issuefiles/"
-;; (substring name 3) ".html")))
-;; ffap-alist))
-
-
-;;; XEmacs:
-;; Extended suppport in another file, for copyright reasons.
-(or (not ffap-xemacs)
- (load "ffap-xe" t t)
- (message "ffap warning: ffap-xe.el not found"))
-
-
-;;; ffap.el ends here
diff --git a/lisp/files.el b/lisp/files.el
deleted file mode 100644
index 3d605384344..00000000000
--- a/lisp/files.el
+++ /dev/null
@@ -1,2863 +0,0 @@
-;;; files.el --- file input and output commands for Emacs
-
-;; Copyright (C) 1985, 86, 87, 92, 93,
-;; 94, 95, 1996 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Defines most of Emacs's file- and directory-handling functions,
-;; including basic file visiting, backup generation, link handling,
-;; ITS-id version control, load- and write-hook handling, and the like.
-
-;;; Code:
-
-(defvar delete-auto-save-files t
- "*Non-nil means delete auto-save file when a buffer is saved or killed.")
-
-(defvar directory-abbrev-alist
- nil
- "*Alist of abbreviations for file directories.
-A list of elements of the form (FROM . TO), each meaning to replace
-FROM with TO when it appears in a directory name. This replacement is
-done when setting up the default directory of a newly visited file.
-*Every* FROM string should start with `^'.
-
-Do not use `~' in the TO strings.
-They should be ordinary absolute directory names.
-
-Use this feature when you have directories which you normally refer to
-via absolute symbolic links. Make TO the name of the link, and FROM
-the name it is linked to.")
-
-;;; Turn off backup files on VMS since it has version numbers.
-(defvar make-backup-files (not (eq system-type 'vax-vms))
- "*Non-nil means make a backup of a file the first time it is saved.
-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'. See also `backup-inhibited'.")
-
-;; Do this so that local variables based on the file name
-;; are not overridden by the major mode.
-(defvar backup-inhibited nil
- "Non-nil means don't make a backup, regardless of the other parameters.
-This variable is intended for use by making it local to a buffer.
-But it is local only if you make it local.")
-(put 'backup-inhibited 'permanent-local t)
-
-(defvar backup-by-copying nil
- "*Non-nil means always use copying to create backup files.
-See documentation of variable `make-backup-files'.")
-
-(defvar 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.")
-
-(defvar 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.")
-
-(defvar backup-enable-predicate
- '(lambda (name)
- (or (< (length name) 5)
- (not (string-equal "/tmp/" (substring name 0 5)))))
- "Predicate that looks at a file name and decides whether to make backups.
-Called with an absolute file name as argument, it returns t to enable backup.")
-
-(defvar 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)
-
-(defvar find-file-existing-other-name t
- "*Non-nil means find a file under alternative names, in existing buffers.
-This means if any existing buffer is visiting the file you want
-under another name, you get the existing buffer instead of a new buffer.")
-
-(defvar find-file-visit-truename nil
- "*Non-nil means visit a file under its truename.
-The truename of a file is found by chasing all links
-both at the file level and at the levels of the containing directories.")
-
-(defvar find-file-revert-without-query
- nil
- "*Specify which files should be reverted without query.
-The value is a list of regular expressions.
-If the file name matches one of these regular expressions,
-then `find-file' reverts the file without querying
-if the file has changed on disk and you have not edited the buffer.")
-
-(defvar buffer-file-number nil
- "The device number and file number of the file visited in the current buffer.
-The value is a list of the form (FILENUM DEVNUM).
-This pair of numbers uniquely identifies the file.
-If the buffer is visiting a new file, the value is nil.")
-(make-variable-buffer-local 'buffer-file-number)
-(put 'buffer-file-number 'permanent-local t)
-
-(defvar buffer-file-numbers-unique (not (memq system-type '(windows-nt)))
- "Non-nil means that buffer-file-number uniquely identifies files.")
-
-(defvar file-precious-flag nil
- "*Non-nil means protect against I/O errors while saving files.
-Some modes set this non-nil in particular buffers.
-
-This feature works by writing the new contents into a temporary file
-and then renaming the temporary file to replace the original.
-In this way, any I/O error in writing leaves the original untouched,
-and there is never any instant where the file is nonexistent.
-
-Note that this feature forces backups to be made by copying.
-Yet, at the same time, saving a precious file
-breaks any hard links between it and other files.")
-
-(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 delete-old-versions nil
- "*If t, delete excess backup versions silently.
-If nil, ask confirmation. Any other value prevents any trimming.")
-
-(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")
-
-(defvar require-final-newline nil
- "*Value of t says silently ensure a file ends in a newline when it is saved.
-Non-nil but not t says ask user whether to add a newline when there isn't one.
-nil means don't add newlines.")
-
-(defvar auto-save-default t
- "*Non-nil says by default do auto-saving of every file-visiting buffer.")
-
-(defvar auto-save-visited-file-name nil
- "*Non-nil says auto-save a buffer in the file it is visiting, when practical.
-Normally auto-save files are written under other names.")
-
-(defvar save-abbrevs nil
- "*Non-nil means save word abbrevs too when files are saved.
-Loading an abbrev file sets this to t.")
-
-(defvar find-file-run-dired t
- "*Non-nil says run dired if `find-file' is given the name of a directory.")
-
-;;;It is not useful to make this a local variable.
-;;;(put 'find-file-not-found-hooks 'permanent-local t)
-(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.")
-
-;;;It is not useful to make this a local variable.
-;;;(put 'find-file-hooks 'permanent-local t)
-(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.
-These hooks are considered to pertain to the visited file.
-So this list is cleared if you change the visited file name.
-
-Don't make this variable buffer-local; instead, use `local-write-file-hooks'.
-See also `write-contents-hooks'.")
-;;; However, in case someone does make it local...
-(put 'write-file-hooks 'permanent-local t)
-
-(defvar local-write-file-hooks nil
- "Just like `write-file-hooks', except intended for per-buffer use.
-The functions in this list are called before the ones in
-`write-file-hooks'.
-
-This variable is meant to be used for hooks that have to do with a
-particular visited file. Therefore, it is a permanent local, so that
-changing the major mode does not clear it. However, calling
-`set-visited-file-name' does clear it.")
-(make-variable-buffer-local 'local-write-file-hooks)
-(put 'local-write-file-hooks 'permanent-local t)
-
-(defvar write-contents-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.
-
-This variable is meant to be used for hooks that pertain to the
-buffer's contents, not to the particular visited file; thus,
-`set-visited-file-name' does not clear this variable; but changing the
-major mode does clear it.
-
-This variable automatically becomes buffer-local whenever it is set.
-If you use `add-hook' to add elements to the list, use nil for the
-LOCAL argument.
-
-See also `write-file-hooks'.")
-(make-variable-buffer-local 'write-contents-hooks)
-
-(defvar enable-local-variables t
- "*Control use of local variables in files you visit.
-The value can be t, nil or something else.
-A value of t means file local variables specifications are obeyed;
-nil means they are ignored; anything else means query.
-
-The command \\[normal-mode] always obeys file local variable
-specifications and ignores this variable.")
-
-(defvar enable-local-eval 'maybe
- "*Control processing of the \"variable\" `eval' in a file's local variables.
-The value can be t, nil or something else.
-A value of t means obey `eval' variables;
-nil means ignore them; anything else means query.
-
-The command \\[normal-mode] always obeys local-variables lists
-and ignores this variable.")
-
-;; Avoid losing in versions where CLASH_DETECTION is disabled.
-(or (fboundp 'lock-buffer)
- (defalias 'lock-buffer 'ignore))
-(or (fboundp 'unlock-buffer)
- (defalias 'unlock-buffer 'ignore))
-(or (fboundp 'file-locked-p)
- (defalias 'file-locked-p 'ignore))
-
-;; This hook function provides support for ange-ftp host name
-;; completion. It runs the usual ange-ftp hook, but only for
-;; completion operations. Having this here avoids the need
-;; to load ange-ftp when it's not really in use.
-(defun ange-ftp-completion-hook-function (op &rest args)
- (if (memq op '(file-name-completion file-name-all-completions))
- (apply 'ange-ftp-hook-function op args)
- (let ((inhibit-file-name-handlers
- (cons 'ange-ftp-completion-hook-function
- (and (eq inhibit-file-name-operation op)
- inhibit-file-name-handlers)))
- (inhibit-file-name-operation op))
- (apply op args))))
-
-(defun convert-standard-filename (filename)
- "Convert a standard file's name to something suitable for the current OS.
-This function's standard definition is trivial; it just returns the argument.
-However, on some systems, the function is redefined
-with a definition that really does change some file names."
- filename)
-
-(defun pwd ()
- "Show the current default directory."
- (interactive nil)
- (message "Directory %s" default-directory))
-
-(defvar cd-path nil
- "Value of the CDPATH environment variable, as a list.
-Not actually set up until the first time you you use it.")
-
-(defvar path-separator ":"
- "Character used to separate concatenated paths.")
-
-(defun parse-colon-path (cd-path)
- "Explode a colon-separated list of paths into a string list."
- (and cd-path
- (let (cd-prefix cd-list (cd-start 0) cd-colon)
- (setq cd-path (concat cd-path path-separator))
- (while (setq cd-colon (string-match path-separator cd-path cd-start))
- (setq cd-list
- (nconc cd-list
- (list (if (= cd-start cd-colon)
- nil
- (substitute-in-file-name
- (file-name-as-directory
- (substring cd-path cd-start cd-colon)))))))
- (setq cd-start (+ cd-colon 1)))
- cd-list)))
-
-(defun cd-absolute (dir)
- "Change current directory to given absolute file name DIR."
- ;; Put the name into directory syntax now,
- ;; because otherwise expand-file-name may give some bad results.
- (if (not (eq system-type 'vax-vms))
- (setq dir (file-name-as-directory dir)))
- (setq dir (abbreviate-file-name (expand-file-name dir)))
- (if (not (file-directory-p dir))
- (error "%s is not a directory" dir)
- (if (file-executable-p dir)
- (setq default-directory dir)
- (error "Cannot cd to %s: Permission denied" dir))))
-
-(defun cd (dir)
- "Make DIR become the current buffer's default directory.
-If your environment includes a `CDPATH' variable, try each one of that
-colon-separated list of directories when resolving a relative directory name."
- (interactive
- (list (read-file-name "Change default directory: "
- default-directory default-directory
- (and (member cd-path '(nil ("./")))
- (null (getenv "CDPATH"))))))
- (if (file-name-absolute-p dir)
- (cd-absolute (expand-file-name dir))
- (if (null cd-path)
- (let ((trypath (parse-colon-path (getenv "CDPATH"))))
- (setq cd-path (or trypath (list "./")))))
- (if (not (catch 'found
- (mapcar
- (function (lambda (x)
- (let ((f (expand-file-name (concat x dir))))
- (if (file-directory-p f)
- (progn
- (cd-absolute f)
- (throw 'found t))))))
- cd-path)
- nil))
- (error "No such directory found via CDPATH environment variable"))))
-
-(defun load-file (file)
- "Load the Lisp file named FILE."
- (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 file-local-copy (file &optional buffer)
- "Copy the file FILE into a temporary file on this machine.
-Returns the name of the local copy, or nil, if FILE is directly
-accessible."
- (let ((handler (find-file-name-handler file 'file-local-copy)))
- (if handler
- (funcall handler 'file-local-copy file)
- nil)))
-
-(defun file-truename (filename &optional counter prev-dirs)
- "Return the truename of FILENAME, which should be absolute.
-The truename of a file name is found by chasing symbolic links
-both at the level of the file and at the level of the directories
-containing it, until no links are left at any level.
-
-The arguments COUNTER and PREV-DIRS are used only in recursive calls.
-Do not specify them in other calls."
- ;; COUNTER can be a cons cell whose car is the count of how many more links
- ;; to chase before getting an error.
- ;; PREV-DIRS can be a cons cell whose car is an alist
- ;; of truenames we've just recently computed.
-
- ;; The last test looks dubious, maybe `+' is meant here? --simon.
- (if (or (string= filename "") (string= filename "~")
- (and (string= (substring filename 0 1) "~")
- (string-match "~[^/]*" filename)))
- (progn
- (setq filename (expand-file-name filename))
- (if (string= filename "")
- (setq filename "/"))))
- (or counter (setq counter (list 100)))
- (let (done
- ;; For speed, remove the ange-ftp completion handler from the list.
- ;; We know it's not needed here.
- ;; For even more speed, do this only on the outermost call.
- (file-name-handler-alist
- (if prev-dirs file-name-handler-alist
- (let ((tem (copy-sequence file-name-handler-alist)))
- (delq (rassq 'ange-ftp-completion-hook-function tem) tem)))))
- (or prev-dirs (setq prev-dirs (list nil)))
- ;; If this file directly leads to a link, process that iteratively
- ;; so that we don't use lots of stack.
- (while (not done)
- (setcar counter (1- (car counter)))
- (if (< (car counter) 0)
- (error "Apparent cycle of symbolic links for %s" filename))
- (let ((handler (find-file-name-handler filename 'file-truename)))
- ;; For file name that has a special handler, call handler.
- ;; This is so that ange-ftp can save time by doing a no-op.
- (if handler
- (setq filename (funcall handler 'file-truename filename)
- done t)
- (let ((dir (or (file-name-directory filename) default-directory))
- target dirfile)
- ;; Get the truename of the directory.
- (setq dirfile (directory-file-name dir))
- ;; If these are equal, we have the (or a) root directory.
- (or (string= dir dirfile)
- ;; If this is the same dir we last got the truename for,
- ;; save time--don't recalculate.
- (if (assoc dir (car prev-dirs))
- (setq dir (cdr (assoc dir (car prev-dirs))))
- (let ((old dir)
- (new (file-name-as-directory (file-truename dirfile counter prev-dirs))))
- (setcar prev-dirs (cons (cons old new) (car prev-dirs)))
- (setq dir new))))
- (if (equal ".." (file-name-nondirectory filename))
- (setq filename
- (directory-file-name (file-name-directory (directory-file-name dir)))
- done t)
- (if (equal "." (file-name-nondirectory filename))
- (setq filename (directory-file-name dir)
- done t)
- ;; Put it back on the file name.
- (setq filename (concat dir (file-name-nondirectory filename)))
- ;; Is the file name the name of a link?
- (setq target (file-symlink-p filename))
- (if target
- ;; Yes => chase that link, then start all over
- ;; since the link may point to a directory name that uses links.
- ;; We can't safely use expand-file-name here
- ;; since target might look like foo/../bar where foo
- ;; is itself a link. Instead, we handle . and .. above.
- (setq filename
- (if (file-name-absolute-p target)
- target
- (concat dir target))
- done nil)
- ;; No, we are done!
- (setq done t))))))))
- filename))
-
-(defun file-chase-links (filename)
- "Chase links in FILENAME until a name that is not a link.
-Does not examine containing directories for links,
-unlike `file-truename'."
- (let (tem (count 100) (newname filename))
- (while (setq tem (file-symlink-p newname))
- (if (= count 0)
- (error "Apparent cycle of symbolic links for %s" filename))
- ;; In the context of a link, `//' doesn't mean what Emacs thinks.
- (while (string-match "//+" tem)
- (setq tem (concat (substring tem 0 (1+ (match-beginning 0)))
- (substring tem (match-end 0)))))
- ;; Handle `..' by hand, since it needs to work in the
- ;; target of any directory symlink.
- ;; This code is not quite complete; it does not handle
- ;; embedded .. in some cases such as ./../foo and foo/bar/../../../lose.
- (while (string-match "\\`\\.\\./" tem)
- (setq tem (substring tem 3))
- (setq newname (file-name-as-directory
- ;; Do the .. by hand.
- (directory-file-name
- (file-name-directory
- ;; Chase links in the default dir of the symlink.
- (file-chase-links
- (directory-file-name
- (file-name-directory newname))))))))
- (setq newname (expand-file-name tem (file-name-directory newname)))
- (setq count (1- count)))
- newname))
-
-(defun switch-to-buffer-other-window (buffer &optional norecord)
- "Select buffer BUFFER in another window.
-Optional second arg NORECORD non-nil means
-do not put this buffer at the front of the list of recently selected ones."
- (interactive "BSwitch to buffer in other window: ")
- (let ((pop-up-windows t))
- (pop-to-buffer buffer t norecord)))
-
-(defun switch-to-buffer-other-frame (buffer &optional norecord)
- "Switch to buffer BUFFER in another frame.
-Optional second arg NORECORD non-nil means
-do not put this buffer at the front of the list of recently selected ones."
- (interactive "BSwitch to buffer in other frame: ")
- (let ((pop-up-frames t))
- (pop-to-buffer buffer t norecord)
- (raise-frame (window-frame (selected-window)))))
-
-(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-other-frame (filename)
- "Edit file FILENAME, in another frame.
-May create a new frame, or reuse an existing one.
-See the function `display-buffer'."
- (interactive "FFind file in other frame: ")
- (switch-to-buffer-other-frame (find-file-noselect filename)))
-
-(defun find-file-read-only (filename)
- "Edit file FILENAME but don't allow changes.
-Like \\[find-file] but marks buffer as read-only.
-Use \\[toggle-read-only] to permit editing."
- (interactive "fFind file read-only: ")
- (find-file filename)
- (setq buffer-read-only t)
- (current-buffer))
-
-(defun find-file-read-only-other-window (filename)
- "Edit file FILENAME in another window but don't allow changes.
-Like \\[find-file-other-window] but marks buffer as read-only.
-Use \\[toggle-read-only] to permit editing."
- (interactive "fFind file read-only other window: ")
- (find-file-other-window filename)
- (setq buffer-read-only t)
- (current-buffer))
-
-(defun find-file-read-only-other-frame (filename)
- "Edit file FILENAME in another frame but don't allow changes.
-Like \\[find-file-other-frame] but marks buffer as read-only.
-Use \\[toggle-read-only] to permit editing."
- (interactive "fFind file read-only other frame: ")
- (find-file-other-frame filename)
- (setq buffer-read-only t)
- (current-buffer))
-
-(defun find-alternate-file-other-window (filename)
- "Find file FILENAME as a replacement for the file in the next window.
-This command does not select that window."
- (interactive
- (save-selected-window
- (other-window 1)
- (let ((file buffer-file-name)
- (file-name nil)
- (file-dir nil))
- (and file
- (setq file-name (file-name-nondirectory file)
- file-dir (file-name-directory file)))
- (list (read-file-name
- "Find alternate file: " file-dir nil nil file-name)))))
- (if (one-window-p)
- (find-file-other-window filename)
- (save-selected-window
- (other-window 1)
- (find-alternate-file filename))))
-
-(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
- (let ((file buffer-file-name)
- (file-name nil)
- (file-dir nil))
- (and file
- (setq file-name (file-name-nondirectory file)
- file-dir (file-name-directory file)))
- (list (read-file-name
- "Find alternate file: " file-dir nil nil file-name))))
- (and (buffer-modified-p) (buffer-file-name)
- ;; (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)
- (onum buffer-file-number)
- (otrue buffer-file-truename)
- (oname (buffer-name)))
- (if (get-buffer " **lose**")
- (kill-buffer " **lose**"))
- (rename-buffer " **lose**")
- (unwind-protect
- (progn
- (unlock-buffer)
- (setq buffer-file-name nil)
- (setq buffer-file-number nil)
- (setq buffer-file-truename nil)
- (find-file filename))
- (cond ((eq obuf (current-buffer))
- (setq buffer-file-name ofile)
- (setq buffer-file-number onum)
- (setq buffer-file-truename otrue)
- (lock-buffer)
- (rename-buffer oname))))
- (or (eq (current-buffer) obuf)
- (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)))
-
-(defun generate-new-buffer (name)
- "Create and return a buffer with a name based on NAME.
-Choose the buffer's name using `generate-new-buffer-name'."
- (get-buffer-create (generate-new-buffer-name name)))
-
-(defvar automount-dir-prefix "^/tmp_mnt/"
- "Regexp to match the automounter prefix in a directory name.")
-
-(defvar abbreviated-home-dir nil
- "The user's homedir abbreviated according to `directory-abbrev-list'.")
-
-(defun abbreviate-file-name (filename)
- "Return a version of FILENAME shortened using `directory-abbrev-alist'.
-This also substitutes \"~\" for the user's home directory.
-Type \\[describe-variable] directory-abbrev-alist RET for more information."
- ;; Get rid of the prefixes added by the automounter.
- (if (and automount-dir-prefix
- (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)))))
- (let ((tail directory-abbrev-alist))
- ;; If any elt of directory-abbrev-alist matches this name,
- ;; abbreviate accordingly.
- (while tail
- (if (string-match (car (car tail)) filename)
- (setq filename
- (concat (cdr (car tail)) (substring filename (match-end 0)))))
- (setq tail (cdr tail)))
- ;; Compute and save the abbreviated homedir name.
- ;; We defer computing this until the first time it's needed, to
- ;; give time for directory-abbrev-alist to be set properly.
- ;; We include a slash at the end, to avoid spurious matches
- ;; such as `/usr/foobar' when the home dir is `/usr/foo'.
- (or abbreviated-home-dir
- (setq abbreviated-home-dir
- (let ((abbreviated-home-dir "$foo"))
- (concat "^" (abbreviate-file-name (expand-file-name "~"))
- "\\(/\\|$\\)"))))
-
- ;; If FILENAME starts with the abbreviated homedir,
- ;; make it start with `~' instead.
- (if (and (string-match abbreviated-home-dir filename)
- ;; If the home dir is just /, don't change it.
- (not (and (= (match-end 0) 1)
- (= (aref filename 0) ?/)))
- ;; MS-DOS root directories can come with a drive letter;
- ;; Novell Netware allows drive letters beyond `Z:'.
- (not (and (or (eq system-type 'ms-dos)
- (eq system-type 'windows-nt))
- (save-match-data
- (string-match "^[a-zA-`]:/$" filename)))))
- (setq filename
- (concat "~"
- (substring filename (match-beginning 1) (match-end 1))
- (substring filename (match-end 0)))))
- filename))
-
-(defvar find-file-not-true-dirname-list nil
- "*List of logical names for which visiting shouldn't save the true dirname.
-On VMS, when you visit a file using a logical name that searches a path,
-you may or may not want the visited file name to record the specific
-directory where the file was found. If you *do not* want that, add the logical
-name to this list as a string.")
-
-(defun find-buffer-visiting (filename)
- "Return the buffer visiting file FILENAME (a string).
-This is like `get-file-buffer', except that it checks for any buffer
-visiting the same file, possibly under a different name.
-If there is no such live buffer, return nil."
- (let ((buf (get-file-buffer filename))
- (truename (abbreviate-file-name (file-truename filename))))
- (or buf
- (let ((list (buffer-list)) found)
- (while (and (not found) list)
- (save-excursion
- (set-buffer (car list))
- (if (and buffer-file-name
- (string= buffer-file-truename truename))
- (setq found (car list))))
- (setq list (cdr list)))
- found)
- (let ((number (nthcdr 10 (file-attributes truename)))
- (list (buffer-list)) found)
- (and buffer-file-numbers-unique
- number
- (while (and (not found) list)
- (save-excursion
- (set-buffer (car list))
- (if (and buffer-file-name
- (equal buffer-file-number number)
- ;; Verify this buffer's file number
- ;; still belongs to its file.
- (file-exists-p buffer-file-name)
- (equal (nthcdr 10 (file-attributes buffer-file-name))
- number))
- (setq found (car list))))
- (setq list (cdr list))))
- found))))
-
-(defun insert-file-contents-literally (filename &optional visit beg end replace)
- "Like `insert-file-contents', q.v., but only reads in the file.
-A buffer may be modified in several ways after reading into the buffer due
-to advanced Emacs features, such as file-name-handlers, format decoding,
-find-file-hooks, etc.
- This function ensures that none of these modifications will take place.
-
-This function does not work for remote files, because it turns off
-file name handlers and remote file access uses a file name handler."
- (let ((file-name-handler-alist nil)
- (format-alist nil)
- (after-insert-file-functions nil)
- (find-buffer-file-type-function
- (if (fboundp 'find-buffer-file-type)
- (symbol-function 'find-buffer-file-type)
- nil)))
- (unwind-protect
- (progn
- (fset 'find-buffer-file-type (lambda (filename) t))
- (insert-file-contents filename visit beg end replace))
- (if find-buffer-file-type-function
- (fset 'find-buffer-file-type find-buffer-file-type-function)
- (fmakunbound 'find-buffer-file-type)))))
-
-(defun find-file-noselect (filename &optional nowarn rawfile)
- "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
- (abbreviate-file-name
- (expand-file-name filename)))
- (if (file-directory-p filename)
- (if find-file-run-dired
- (dired-noselect (if find-file-visit-truename
- (abbreviate-file-name (file-truename filename))
- filename))
- (error "%s is a directory" filename))
- (let* ((buf (get-file-buffer filename))
- (truename (abbreviate-file-name (file-truename filename)))
- (number (nthcdr 10 (file-attributes truename)))
- ;; Find any buffer for a file which has same truename.
- (other (and (not buf) (find-buffer-visiting filename)))
- error)
- ;; Let user know if there is a buffer with the same truename.
- (if other
- (progn
- (or nowarn
- (string-equal filename (buffer-file-name other))
- (message "%s and %s are the same file"
- filename (buffer-file-name other)))
- ;; Optionally also find that buffer.
- (if (or find-file-existing-other-name find-file-visit-truename)
- (setq buf other))))
- (if buf
- (or nowarn
- (verify-visited-file-modtime buf)
- (cond ((not (file-exists-p filename))
- (error "File %s no longer exists!" filename))
- ;; Certain files should be reverted automatically
- ;; if they have changed on disk and not in the buffer.
- ((and (not (buffer-modified-p buf))
- (let ((tail find-file-revert-without-query)
- (found nil))
- (while tail
- (if (string-match (car tail) filename)
- (setq found t))
- (setq tail (cdr tail)))
- found))
- (with-current-buffer buf
- (message "Reverting file %s..." filename)
- (revert-buffer t t)
- (message "Reverting file %s...done" filename)))
- ((yes-or-no-p
- (if (string= (file-name-nondirectory filename)
- (buffer-name buf))
- (format
- (if (buffer-modified-p buf)
- "File %s changed on disk. Discard your edits? "
- "File %s changed on disk. Reread from disk? ")
- (file-name-nondirectory filename))
- (format
- (if (buffer-modified-p buf)
- "File %s changed on disk. Discard your edits in %s? "
- "File %s changed on disk. Reread from disk into %s? ")
- (file-name-nondirectory filename)
- (buffer-name buf))))
- (with-current-buffer buf
- (revert-buffer t t)))))
- (save-excursion
-;;; The truename stuff makes this obsolete.
-;;; (let* ((link-name (car (file-attributes filename)))
-;;; (linked-buf (and (stringp link-name)
-;;; (get-file-buffer link-name))))
-;;; (if (bufferp linked-buf)
-;;; (message "Symbolic link to file in buffer %s"
-;;; (buffer-name linked-buf))))
- (setq buf (create-file-buffer filename))
- (set-buffer-major-mode buf)
- (set-buffer buf)
- (erase-buffer)
- (if rawfile
- (condition-case ()
- (insert-file-contents-literally filename t)
- (file-error
- ;; Unconditionally set error
- (setq error t)))
- (condition-case ()
- (insert-file-contents filename t)
- (file-error
- ;; Run find-file-not-found-hooks until one returns non-nil.
- (or (run-hook-with-args-until-success 'find-file-not-found-hooks)
- ;; If they fail too, set error.
- (setq error t)))))
- ;; Find the file's truename, and maybe use that as visited name.
- (setq buffer-file-truename truename)
- (setq buffer-file-number number)
- ;; On VMS, we may want to remember which directory in a search list
- ;; the file was found in.
- (and (eq system-type 'vax-vms)
- (let (logical)
- (if (string-match ":" (file-name-directory filename))
- (setq logical (substring (file-name-directory filename)
- 0 (match-beginning 0))))
- (not (member logical find-file-not-true-dirname-list)))
- (setq buffer-file-name buffer-file-truename))
- (if find-file-visit-truename
- (setq buffer-file-name
- (setq filename
- (expand-file-name buffer-file-truename))))
- ;; Set buffer's default directory to that of the file.
- (setq default-directory (file-name-directory filename))
- ;; Turn off backup files for certain file names. Since
- ;; this is a permanent local, the major mode won't eliminate it.
- (and (not (funcall backup-enable-predicate buffer-file-name))
- (progn
- (make-local-variable 'backup-inhibited)
- (setq backup-inhibited t)))
- (if rawfile
- nil
- (after-find-file error (not nowarn))
- (setq buf (current-buffer)))))
- buf)))
-
-(defvar after-find-file-from-revert-buffer nil)
-
-(defun after-find-file (&optional error warn noauto
- after-find-file-from-revert-buffer
- nomodes)
- "Called after finding a file and by the default revert function.
-Sets buffer mode, parses local variables.
-Optional args ERROR, WARN, and NOAUTO: 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.
-NOAUTO means don't mess with auto-save mode.
-Fourth arg AFTER-FIND-FILE-FROM-REVERT-BUFFER non-nil
- means this call was from `revert-buffer'.
-Fifth arg NOMODES non-nil means don't alter the file's modes.
-Finishes by calling the functions in `find-file-hooks'
-unless NOMODES is non-nil."
- (setq buffer-read-only (not (file-writable-p buffer-file-name)))
- (if noninteractive
- nil
- (let* (not-serious
- (msg
- (cond ((and error (file-attributes buffer-file-name))
- (setq buffer-read-only t)
- "File exists, but cannot be read.")
- ((not buffer-read-only)
- (if (and warn
- (file-newer-than-file-p (make-auto-save-file-name)
- buffer-file-name))
- (format "%s has auto save data; consider M-x recover-file"
- (file-name-nondirectory buffer-file-name))
- (setq not-serious t)
- (if error "(New file)" nil)))
- ((not error)
- (setq not-serious t)
- "Note: file is write protected")
- ((file-attributes (directory-file-name default-directory))
- "File not found and directory write-protected")
- ((file-exists-p (file-name-directory buffer-file-name))
- (setq buffer-read-only nil))
- (t
- (setq buffer-read-only nil)
- (if (file-exists-p (file-name-directory (directory-file-name (file-name-directory buffer-file-name))))
- "Use M-x make-dir RET RET to create the directory"
- "Use C-u M-x make-dir RET RET to create directory and its parents")))))
- (if msg
- (progn
- (message msg)
- (or not-serious (sit-for 1 nil t)))))
- (if (and auto-save-default (not noauto))
- (auto-save-mode t)))
- (if nomodes
- nil
- (normal-mode t)
- (run-hooks '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,
-we may set up specified local variables depending on the value of
-`enable-local-variables': if it is t, we do; if it is nil, we don't;
-otherwise, we query. `enable-local-variables' is ignored if you
-run `normal-mode' explicitly."
- (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
- (let ((enable-local-variables (or (not find-file)
- enable-local-variables)))
- (hack-local-variables))
- (error (message "File local-variables error: %s"
- (prin1-to-string err)))))
-
-(defvar auto-mode-alist
- '(("\\.te?xt\\'" . text-mode)
- ("\\.c\\'" . c-mode)
- ("\\.h\\'" . c-mode)
- ("\\.tex\\'" . tex-mode)
- ("\\.ltx\\'" . latex-mode)
- ("\\.el\\'" . emacs-lisp-mode)
- ("\\.mm\\'" . nroff-mode)
- ("\\.me\\'" . nroff-mode)
- ("\\.ms\\'" . nroff-mode)
- ("\\.man\\'" . nroff-mode)
- ("\\.scm\\'" . scheme-mode)
- ("\\.l\\'" . lisp-mode)
- ("\\.lisp\\'" . lisp-mode)
- ("\\.f\\'" . fortran-mode)
- ("\\.F\\'" . fortran-mode)
- ("\\.for\\'" . fortran-mode)
- ("\\.p\\'" . pascal-mode)
- ("\\.pas\\'" . pascal-mode)
- ("\\.mss\\'" . scribe-mode)
- ("\\.ad[abs]\\'" . ada-mode)
- ("\\.icn\\'" . icon-mode)
- ("\\.pl\\'" . perl-mode)
- ("\\.pm\\'" . perl-mode)
- ("\\.cc\\'" . c++-mode)
- ("\\.hh\\'" . c++-mode)
- ("\\.hpp\\'" . c++-mode)
- ("\\.C\\'" . c++-mode)
- ("\\.H\\'" . c++-mode)
- ("\\.cpp\\'" . c++-mode)
- ("\\.cxx\\'" . c++-mode)
- ("\\.hxx\\'" . c++-mode)
- ("\\.c\\+\\+\\'" . c++-mode)
- ("\\.h\\+\\+\\'" . c++-mode)
- ("\\.m\\'" . objc-mode)
- ("\\.java\\'" . java-mode)
- ("\\.sim\\'" . simula-mode)
- ("\\.mk\\'" . makefile-mode)
- ("\\(M\\|m\\|GNUm\\)akefile\\(.in\\)?\\'" . makefile-mode)
-;;; Less common extensions come here
-;;; so more common ones above are found faster.
- ("\\.texinfo\\'" . texinfo-mode)
- ("\\.te?xi\\'" . texinfo-mode)
- ("\\.s\\'" . asm-mode)
- ("\\.S\\'" . asm-mode)
- ("\\.asm\\'" . asm-mode)
- ("ChangeLog\\'" . change-log-mode)
- ("change.log\\'" . change-log-mode)
- ("changelo\\'" . change-log-mode)
- ("ChangeLog.[0-9]+\\'" . change-log-mode)
- ;; for MSDOS and MS-Windows (which are case-insensitive)
- ("changelog\\'" . change-log-mode)
- ("changelog.[0-9]+\\'" . change-log-mode)
- ("\\$CHANGE_LOG\\$\\.TXT" . change-log-mode)
- ("\\.scm\\.[0-9]*\\'" . scheme-mode)
- ("\\.[ck]?sh\\'\\|\\.shar\\'\\|/\\.z?profile\\'" . sh-mode)
- ("/\\.\\(bash_profile\\|z?login\\|bash_login\\|z?logout\\)\\'" . sh-mode)
- ("/\\.\\(bash_logout\\|[kz]shrc\\|bashrc\\|t?cshrc\\|esrc\\)\\'" . sh-mode)
- ("/\\.\\([kz]shenv\\|xinitrc\\|startxrc\\|xsession\\)\\'" . sh-mode)
-;;; The following should come after the ChangeLog pattern
-;;; for the sake of ChangeLog.1, etc.
-;;; and after the .scm.[0-9] pattern too.
- ("\\.[12345678]\\'" . nroff-mode)
- ("\\.TeX\\'" . tex-mode)
- ("\\.sty\\'" . latex-mode)
- ("\\.cls\\'" . latex-mode) ;LaTeX 2e class
- ("\\.bbl\\'" . latex-mode)
- ("\\.bib\\'" . bibtex-mode)
- ("\\.article\\'" . text-mode)
- ("\\.letter\\'" . text-mode)
- ("\\.tcl\\'" . tcl-mode)
- ("\\.exp\\'" . tcl-mode)
- ("\\.itcl\\'" . tcl-mode)
- ("\\.itk\\'" . tcl-mode)
- ("\\.f90\\'" . f90-mode)
- ("\\.lsp\\'" . lisp-mode)
- ("\\.awk\\'" . awk-mode)
- ("\\.prolog\\'" . prolog-mode)
- ("\\.tar\\'" . tar-mode)
- ("\\.\\(arc\\|zip\\|lzh\\|zoo\\)\\'" . archive-mode)
- ("\\.\\(ARC\\|ZIP\\|LZH\\|ZOO\\)\\'" . archive-mode)
- ;; Mailer puts message to be edited in
- ;; /tmp/Re.... or Message
- ("\\`/tmp/Re" . text-mode)
- ("/Message[0-9]*\\'" . text-mode)
- ("/drafts/[0-9]+\\'" . mh-letter-mode)
- ;; some news reader is reported to use this
- ("\\`/tmp/fol/" . text-mode)
- ("\\.y\\'" . c-mode)
- ("\\.lex\\'" . c-mode)
- ("\\.oak\\'" . scheme-mode)
- ("\\.sgml?\\'" . sgml-mode)
- ("\\.dtd\\'" . sgml-mode)
- ("\\.s?html?\\'" . html-mode)
- ;; .emacs following a directory delimiter
- ;; in either Unix or VMS syntax.
- ("[]>:/]\\..*emacs\\'" . emacs-lisp-mode)
- ;; _emacs following a directory delimiter
- ;; in MsDos syntax
- ("[:/]_emacs\\'" . emacs-lisp-mode)
- ("\\.ml\\'" . lisp-mode))
- "\
-Alist of filename patterns vs corresponding major mode functions.
-Each element looks like (REGEXP . FUNCTION) or (REGEXP FUNCTION NON-NIL).
-\(NON-NIL stands for anything that is not nil; the value does not matter.)
-Visiting a file whose name matches REGEXP specifies FUNCTION as the
-mode function to use. FUNCTION will be called, unless it is nil.
-
-If the element has the form (REGEXP FUNCTION NON-NIL), then after
-calling FUNCTION (if it's not nil), we delete the suffix that matched
-REGEXP and search the list again for another match.")
-
-(defvar interpreter-mode-alist
- '(("perl" . perl-mode)
- ("perl5" . perl-mode)
- ("wish" . tcl-mode)
- ("wishx" . tcl-mode)
- ("tcl" . tcl-mode)
- ("tclsh" . tcl-mode)
- ("awk" . awk-mode)
- ("mawk" . awk-mode)
- ("nawk" . awk-mode)
- ("gawk" . awk-mode)
- ("scm" . scheme-mode)
- ("ash" . sh-mode)
- ("bash" . sh-mode)
- ("csh" . sh-mode)
- ("dtksh" . sh-mode)
- ("es" . sh-mode)
- ("itcsh" . sh-mode)
- ("jsh" . sh-mode)
- ("ksh" . sh-mode)
- ("oash" . sh-mode)
- ("pdksh" . sh-mode)
- ("rc" . sh-mode)
- ("sh" . sh-mode)
- ("sh5" . sh-mode)
- ("tcsh" . sh-mode)
- ("wksh" . sh-mode)
- ("wsh" . sh-mode)
- ("zsh" . sh-mode)
- ("tail" . text-mode)
- ("more" . text-mode)
- ("less" . text-mode)
- ("pg" . text-mode))
- "Alist mapping interpreter names to major modes.
-This alist applies to files whose first line starts with `#!'.
-Each element looks like (INTERPRETER . MODE).
-The car of each element is compared with
-the name of the interpreter specified in the first line.
-If it matches, mode MODE is selected.")
-
-(defvar inhibit-first-line-modes-regexps '("\\.tar\\'" "\\.tgz\\'")
- "List of regexps; if one matches a file name, don't look for `-*-'.")
-
-(defvar inhibit-first-line-modes-suffixes nil
- "List of regexps for what to ignore, for `inhibit-first-line-modes-regexps'.
-When checking `inhibit-first-line-modes-regexps', we first discard
-from the end of the file name anything that matches one of these regexps.")
-
-(defvar user-init-file
- "" ; set by command-line
- "File name including directory of user's initialization file.")
-
-(defun set-auto-mode ()
- "Select major mode appropriate for current buffer.
-This checks for a -*- mode tag in the buffer's text,
-compares the filename against the entries in `auto-mode-alist',
-or checks the interpreter that runs this file against
-`interpreter-mode-alist'.
-
-It does not check for the `mode:' local variable in the
-Local Variables section of the file; for that, use `hack-local-variables'.
-
-If `enable-local-variables' is nil, this function does not check for a
--*- mode tag."
- ;; Look for -*-MODENAME-*- or -*- ... mode: MODENAME; ... -*-
- (let (beg end done modes)
- (save-excursion
- (goto-char (point-min))
- (skip-chars-forward " \t\n")
- (and enable-local-variables
- ;; Don't look for -*- if this file name matches any
- ;; of the regexps in inhibit-first-line-modes-regexps.
- (let ((temp inhibit-first-line-modes-regexps)
- (name (if buffer-file-name
- (file-name-sans-versions buffer-file-name)
- (buffer-name))))
- (while (let ((sufs inhibit-first-line-modes-suffixes))
- (while (and sufs (not (string-match (car sufs) name)))
- (setq sufs (cdr sufs)))
- sufs)
- (setq name (substring name 0 (match-beginning 0))))
- (while (and temp
- (not (string-match (car temp) name)))
- (setq temp (cdr temp)))
- (not temp))
- (search-forward "-*-" (save-excursion
- ;; If the file begins with "#!"
- ;; (exec interpreter magic), look
- ;; for mode frobs in the first two
- ;; lines. You cannot necessarily
- ;; put them in the first line of
- ;; such a file without screwing up
- ;; the interpreter invocation.
- (end-of-line (and (looking-at "^#!") 2))
- (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 (save-excursion (search-forward ":" end t))
- ;; Find all specifications for the `mode:' variable
- ;; and execute them left to right.
- (while (let ((case-fold-search t))
- (or (and (looking-at "mode:")
- (goto-char (match-end 0)))
- (re-search-forward "[ \t;]mode:" end t)))
- (skip-chars-forward " \t")
- (setq beg (point))
- (if (search-forward ";" end t)
- (forward-char -1)
- (goto-char end))
- (skip-chars-backward " \t")
- (setq modes (cons (intern (concat (downcase (buffer-substring beg (point))) "-mode"))
- modes)))
- ;; Simple -*-MODE-*- case.
- (setq modes (cons (intern (concat (downcase (buffer-substring beg end))
- "-mode"))
- modes))))))
- ;; If we found modes to use, invoke them now,
- ;; outside the save-excursion.
- (if modes
- (progn (mapcar 'funcall (nreverse modes))
- (setq done t)))
- ;; If we didn't find a mode from a -*- line, try using the file name.
- (if (and (not done) buffer-file-name)
- (let ((name buffer-file-name)
- (keep-going t))
- ;; Remove backup-suffixes from file name.
- (setq name (file-name-sans-versions name))
- (while keep-going
- (setq keep-going nil)
- (let ((alist auto-mode-alist)
- (mode nil))
- ;; Find first matching alist entry.
- (let ((case-fold-search
- (memq system-type '(vax-vms windows-nt))))
- (while (and (not mode) alist)
- (if (string-match (car (car alist)) name)
- (if (and (consp (cdr (car alist)))
- (nth 2 (car alist)))
- (progn
- (setq mode (car (cdr (car alist)))
- name (substring name 0 (match-beginning 0))
- keep-going t))
- (setq mode (cdr (car alist))
- keep-going nil)))
- (setq alist (cdr alist))))
- (if mode
- (funcall mode)
- ;; If we can't deduce a mode from the file name,
- ;; look for an interpreter specified in the first line.
- ;; As a special case, allow for things like "#!/bin/env perl",
- ;; which finds the interpreter anywhere in $PATH.
- (let ((interpreter
- (save-excursion
- (goto-char (point-min))
- (if (looking-at "#![ \t]?\\([^ \t\n]*/bin/env[ \t]\\)?\\([^ \t\n]+\\)")
- (buffer-substring (match-beginning 2)
- (match-end 2))
- "")))
- elt)
- ;; Map interpreter name to a mode.
- (setq elt (assoc (file-name-nondirectory interpreter)
- interpreter-mode-alist))
- (if elt
- (funcall (cdr elt)))))))))))
-
-(defun hack-local-variables-prop-line ()
- ;; Set local variables specified in the -*- line.
- ;; Ignore any specification for `mode:';
- ;; set-auto-mode should already have handled that.
- (save-excursion
- (goto-char (point-min))
- (let ((result nil)
- (end (save-excursion (end-of-line (and (looking-at "^#!") 2)) (point))))
- ;; Parse the -*- line into the `result' alist.
- (cond ((not (search-forward "-*-" end t))
- ;; doesn't have one.
- nil)
- ((looking-at "[ \t]*\\([^ \t\n\r:;]+\\)\\([ \t]*-\\*-\\)")
- ;; Simple form: "-*- MODENAME -*-". Already handled.
- nil)
- (t
- ;; Hairy form: '-*-' [ <variable> ':' <value> ';' ]* '-*-'
- ;; (last ";" is optional).
- (save-excursion
- (if (search-forward "-*-" end t)
- (setq end (- (point) 3))
- (error "-*- not terminated before end of line")))
- (while (< (point) end)
- (or (looking-at "[ \t]*\\([^ \t\n:]+\\)[ \t]*:[ \t]*")
- (error "malformed -*- line"))
- (goto-char (match-end 0))
- ;; There used to be a downcase here,
- ;; but the manual didn't say so,
- ;; and people want to set var names that aren't all lc.
- (let ((key (intern (buffer-substring
- (match-beginning 1)
- (match-end 1))))
- (val (save-restriction
- (narrow-to-region (point) end)
- (read (current-buffer)))))
- ;; It is traditional to ignore
- ;; case when checking for `mode' in set-auto-mode,
- ;; so we must do that here as well.
- ;; That is inconsistent, but we're stuck with it.
- (or (equal (downcase (symbol-name key)) "mode")
- (setq result (cons (cons key val) result)))
- (skip-chars-forward " \t;")))
- (setq result (nreverse result))))
-
- (if (and result
- (or (eq enable-local-variables t)
- (and enable-local-variables
- (save-window-excursion
- (condition-case nil
- (switch-to-buffer (current-buffer))
- (error
- ;; If we fail to switch in the selected window,
- ;; it is probably a minibuffer.
- ;; So try another window.
- (condition-case nil
- (switch-to-buffer-other-window (current-buffer))
- (error
- (switch-to-buffer-other-frame (current-buffer))))))
- (y-or-n-p (format "Set local variables as specified in -*- line of %s? "
- (file-name-nondirectory buffer-file-name)))))))
- (let ((enable-local-eval enable-local-eval))
- (while result
- (hack-one-local-variable (car (car result)) (cdr (car result)))
- (setq result (cdr result))))))))
-
-(defvar hack-local-variables-hook nil
- "Normal hook run after processing a file's local variables specs.
-Major modes can use this to examine user-specified local variables
-in order to initialize other data structure based on them.")
-
-(defun hack-local-variables ()
- "Parse and put into effect this buffer's local variables spec."
- (hack-local-variables-prop-line)
- ;; 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 (eq enable-local-variables t)
- (and enable-local-variables
- (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? "
- (if buffer-file-name
- (file-name-nondirectory
- buffer-file-name)
- (concat "buffer "
- (buffer-name))))))))))
- (let ((continue t)
- prefix prefixlen suffix beg
- (enable-local-eval enable-local-eval))
- ;; 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.
- (hack-one-local-variable var val)))))))
- (run-hooks 'hack-local-variables-hook))
-
-(defvar ignored-local-variables
- '(enable-local-eval)
- "Variables to be ignored in a file's local variable spec.")
-
-;; Get confirmation before setting these variables as locals in a file.
-(put 'debugger 'risky-local-variable t)
-(put 'enable-local-eval 'risky-local-variable t)
-(put 'ignored-local-variables 'risky-local-variable t)
-(put 'eval 'risky-local-variable t)
-(put 'file-name-handler-alist 'risky-local-variable t)
-(put 'minor-mode-map-alist 'risky-local-variable t)
-(put 'after-load-alist 'risky-local-variable t)
-(put 'buffer-file-name 'risky-local-variable t)
-(put 'buffer-auto-save-file-name 'risky-local-variable t)
-(put 'buffer-file-truename 'risky-local-variable t)
-(put 'exec-path 'risky-local-variable t)
-(put 'load-path 'risky-local-variable t)
-(put 'exec-directory 'risky-local-variable t)
-(put 'process-environment 'risky-local-variable t)
-(put 'dabbrev-case-fold-search 'risky-local-variable t)
-(put 'dabbrev-case-replace 'risky-local-variable t)
-;; Don't wait for outline.el to be loaded, for the sake of outline-minor-mode.
-(put 'outline-level 'risky-local-variable t)
-(put 'rmail-output-file-alist 'risky-local-variable t)
-
-;; This one is safe because the user gets to check it before it is used.
-(put 'compile-command 'safe-local-variable t)
-
-(defun hack-one-local-variable-quotep (exp)
- (and (consp exp) (eq (car exp) 'quote) (consp (cdr exp))))
-
-;; "Set" one variable in a local variables spec.
-;; A few variable names are treated specially.
-(defun hack-one-local-variable (var val)
- (cond ((eq var 'mode)
- (funcall (intern (concat (downcase (symbol-name val))
- "-mode"))))
- ((memq var ignored-local-variables)
- nil)
- ;; "Setting" eval means either eval it or do nothing.
- ;; Likewise for setting hook variables.
- ((or (get var 'risky-local-variable)
- (and
- (string-match "-hooks?$\\|-functions?$\\|-forms?$\\|-program$\\|-command$"
- (symbol-name var))
- (not (get var 'safe-local-variable))))
- ;; Permit evalling a put of a harmless property.
- ;; if the args do nothing tricky.
- (if (or (and (eq var 'eval)
- (consp val)
- (eq (car val) 'put)
- (hack-one-local-variable-quotep (nth 1 val))
- (hack-one-local-variable-quotep (nth 2 val))
- ;; Only allow safe values of lisp-indent-hook;
- ;; not functions.
- (or (numberp (nth 3 val))
- (equal (nth 3 val) ''defun))
- (memq (nth 1 (nth 2 val))
- '(lisp-indent-hook)))
- ;; Permit eval if not root and user says ok.
- (and (not (zerop (user-uid)))
- (or (eq enable-local-eval t)
- (and enable-local-eval
- (save-window-excursion
- (switch-to-buffer (current-buffer))
- (save-excursion
- (beginning-of-line)
- (set-window-start (selected-window) (point)))
- (setq enable-local-eval
- (y-or-n-p (format "Process `eval' or hook local variables in file %s? "
- (file-name-nondirectory buffer-file-name)))))))))
- (if (eq var 'eval)
- (save-excursion (eval val))
- (make-local-variable var)
- (set var val))
- (message "Ignoring `eval:' in file's local variables")))
- ;; Ordinary variable, really set it.
- (t (make-local-variable var)
- (set var val))))
-
-
-(defun set-visited-file-name (filename &optional no-query)
- "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.
-
-The optional second argument NO-QUERY, if non-nil, inhibits asking for
-confirmation in the case where another buffer is already visiting FILENAME."
- (interactive "FSet visited file name: ")
- (if (buffer-base-buffer)
- (error "An indirect buffer cannot visit a file"))
- (let (truename)
- (if filename
- (setq filename
- (if (string-equal filename "")
- nil
- (expand-file-name filename))))
- (if filename
- (progn
- (setq truename (file-truename filename))
- (if find-file-visit-truename
- (setq filename truename))))
- (let ((buffer (and filename (find-buffer-visiting filename))))
- (and buffer (not (eq buffer (current-buffer)))
- (not no-query)
- (not (y-or-n-p (message "A buffer is visiting %s; proceed? "
- filename)))
- (error "Aborted")))
- (or (equal filename buffer-file-name)
- (progn
- (and filename (lock-buffer filename))
- (unlock-buffer)))
- (setq buffer-file-name filename)
- (if filename ; make buffer name reflect filename.
- (let ((new-name (file-name-nondirectory buffer-file-name)))
- (if (string= new-name "")
- (error "Empty file name"))
- (if (eq system-type 'vax-vms)
- (setq new-name (downcase new-name)))
- (setq default-directory (file-name-directory buffer-file-name))
- (or (string= new-name (buffer-name))
- (rename-buffer new-name t))))
- (setq buffer-backed-up nil)
- (clear-visited-file-modtime)
- ;; Abbreviate the file names of the buffer.
- (if truename
- (progn
- (setq buffer-file-truename (abbreviate-file-name truename))
- (if find-file-visit-truename
- (setq buffer-file-name buffer-file-truename))))
- (setq buffer-file-number
- (if filename
- (nthcdr 10 (file-attributes buffer-file-name))
- nil)))
- ;; write-file-hooks is normally used for things like ftp-find-file
- ;; that visit things that are not local files as if they were files.
- ;; Changing to visit an ordinary local file instead should flush the hook.
- (kill-local-variable 'write-file-hooks)
- (kill-local-variable 'local-write-file-hooks)
- (kill-local-variable 'revert-buffer-function)
- (kill-local-variable 'backup-inhibited)
- ;; If buffer was read-only because of version control,
- ;; that reason is gone now, so make it writable.
- (if vc-mode
- (setq buffer-read-only nil))
- (kill-local-variable 'vc-mode)
- ;; Turn off backup files for certain file names.
- ;; Since this is a permanent local, the major mode won't eliminate it.
- (and (not (funcall backup-enable-predicate buffer-file-name))
- (progn
- (make-local-variable 'backup-inhibited)
- (setq backup-inhibited t)))
- (let ((oauto buffer-auto-save-file-name))
- ;; If auto-save was not already on, turn it on if appropriate.
- (if (not buffer-auto-save-file-name)
- (and buffer-file-name auto-save-default
- (auto-save-mode t))
- ;; If auto save is on, start using a new name.
- ;; We deliberately don't rename or delete the old auto save
- ;; for the old visited file name. This is because perhaps
- ;; the user wants to save the new state and then compare with the
- ;; previous state from the auto save file.
- (setq buffer-auto-save-file-name
- (make-auto-save-file-name)))
- ;; Rename the old auto save file if any.
- (and oauto buffer-auto-save-file-name
- (file-exists-p oauto)
- (rename-file oauto buffer-auto-save-file-name t)))
- (if buffer-file-name
- (set-buffer-modified-p t)))
-
-(defun write-file (filename &optional confirm)
- "Write current buffer into file FILENAME.
-Makes buffer visit that file, and marks it not modified.
-If the buffer is already visiting a file, you can specify
-a directory name as FILENAME, to write a file of the same
-old name in that directory.
-
-If optional second arg CONFIRM is non-nil,
-ask for confirmation for overwriting an existing file.
-Interactively, confirmation is required unless you supply a prefix argument."
-;; (interactive "FWrite file: ")
- (interactive
- (list (if buffer-file-name
- (read-file-name "Write file: "
- nil nil nil nil)
- (read-file-name "Write file: "
- (cdr (assq 'default-directory
- (buffer-local-variables)))
- nil nil (buffer-name)))
- (not current-prefix-arg)))
- (or (null filename) (string-equal filename "")
- (progn
- ;; If arg is just a directory,
- ;; use same file name, but in that directory.
- (if (and (file-directory-p filename) buffer-file-name)
- (setq filename (concat (file-name-as-directory filename)
- (file-name-nondirectory buffer-file-name))))
- (and confirm
- (file-exists-p filename)
- (or (y-or-n-p (format "File `%s' exists; overwrite? " filename))
- (error "Canceled")))
- (set-visited-file-name filename (not confirm))))
- (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.
-
-A backup may be done by renaming or by copying; see documentation of
-variable `make-backup-files'. If it's done by renaming, then the file is
-no longer accessible under its old name."
- (if (and make-backup-files (not backup-inhibited)
- (not buffer-backed-up)
- (file-exists-p buffer-file-name)
- (memq (aref (elt (file-attributes buffer-file-name) 8) 0)
- '(?- ?l)))
- (let ((real-file-name buffer-file-name)
- backup-info backupname targets setmodes)
- ;; If specified name is a symbolic link, chase it to the target.
- ;; Thus we make the backups in the directory where the real file is.
- (setq real-file-name (file-chase-links real-file-name))
- (setq backup-info (find-backup-file-name real-file-name)
- backupname (car backup-info)
- targets (cdr backup-info))
-;;; (if (file-directory-p buffer-file-name)
-;;; (error "Cannot save buffer in directory %s" buffer-file-name))
- (if backup-info
- (condition-case ()
- (let ((delete-old-versions
- ;; If have old versions to maybe delete,
- ;; ask the user to confirm now, before doing anything.
- ;; But don't actually delete til later.
- (and targets
- (or (eq delete-old-versions t) (eq delete-old-versions nil))
- (or delete-old-versions
- (y-or-n-p (format "Delete excess backup versions of %s? "
- real-file-name))))))
- ;; Actually write the back up file.
- (condition-case ()
- (if (or file-precious-flag
- ; (file-symlink-p buffer-file-name)
- backup-by-copying
- (and backup-by-copying-when-linked
- (> (file-nlinks real-file-name) 1))
- (and backup-by-copying-when-mismatch
- (let ((attr (file-attributes real-file-name)))
- (or (nth 9 attr)
- (not (file-ownership-preserved-p real-file-name))))))
- (condition-case ()
- (copy-file real-file-name backupname t t)
- (file-error
- ;; If copying fails because file BACKUPNAME
- ;; is not writable, delete that file and try again.
- (if (and (file-exists-p backupname)
- (not (file-writable-p backupname)))
- (delete-file backupname))
- (copy-file real-file-name backupname t t)))
- ;; rename-file should delete old backup.
- (rename-file real-file-name backupname t)
- (setq setmodes (file-modes backupname)))
- (file-error
- ;; If trouble writing the backup, write it in ~.
- (setq backupname (expand-file-name
- (convert-standard-filename
- "~/%backup%~")))
- (message "Cannot write backup file; backing up in %s"
- (file-name-nondirectory backupname))
- (sleep-for 1)
- (condition-case ()
- (copy-file real-file-name backupname t t)
- (file-error
- ;; If copying fails because file BACKUPNAME
- ;; is not writable, delete that file and try again.
- (if (and (file-exists-p backupname)
- (not (file-writable-p backupname)))
- (delete-file backupname))
- (copy-file real-file-name backupname t t)))))
- (setq buffer-backed-up t)
- ;; Now delete the old versions, if desired.
- (if delete-old-versions
- (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 &optional keep-backup-version)
- "Return FILENAME sans backup versions or strings.
-This is a separate procedure so your site-init or startup file can
-redefine it.
-If the optional argument KEEP-BACKUP-VERSION is non-nil,
-we do not remove backup version numbers, only true file version numbers."
- (let ((handler (find-file-name-handler name 'file-name-sans-versions)))
- (if handler
- (funcall handler 'file-name-sans-versions name keep-backup-version)
- (substring name 0
- (if (eq system-type 'vax-vms)
- ;; VMS version number is (a) semicolon, optional
- ;; sign, zero or more digits or (b) period, option
- ;; sign, zero or more digits, provided this is the
- ;; second period encountered outside of the
- ;; device/directory part of the file name.
- (or (string-match ";[-+]?[0-9]*\\'" name)
- (if (string-match "\\.[^]>:]*\\(\\.[-+]?[0-9]*\\)\\'"
- name)
- (match-beginning 1))
- (length name))
- (if keep-backup-version
- (length name)
- (or (string-match "\\.~[0-9.]+~\\'" name)
- (string-match "~\\'" name)
- (length name))))))))
-
-(defun file-ownership-preserved-p (file)
- "Returns t if deleting FILE and rewriting it would preserve the owner."
- (let ((handler (find-file-name-handler file 'file-ownership-preserved-p)))
- (if handler
- (funcall handler 'file-ownership-preserved-p file)
- (let ((attributes (file-attributes file)))
- ;; Return t if the file doesn't exist, since it's true that no
- ;; information would be lost by an (attempted) delete and create.
- (or (null attributes)
- (= (nth 2 attributes) (user-uid)))))))
-
-(defun file-name-sans-extension (filename)
- "Return FILENAME sans final \"extension\".
-The extension, in a file name, is the part that follows the last `.'."
- (save-match-data
- (let ((file (file-name-sans-versions (file-name-nondirectory filename)))
- directory)
- (if (string-match "\\.[^.]*\\'" file)
- (if (setq directory (file-name-directory filename))
- (expand-file-name (substring file 0 (match-beginning 0))
- directory)
- (substring file 0 (match-beginning 0)))
- filename))))
-
-(defun file-name-extension (filename &optional period)
- "Return FILENAME's final \"extension\".
-The extension, in a file name, is the part that follows the last `.'.
-Return nil for extensionless file names such as `foo'.
-Return the empty string for file names such as `foo.'.
-
-If PERIOD is non-nil, then the returned value includes the period
-that delimits the extension, and if FILENAME has no extension,
-the value is \"\"."
- (save-match-data
- (let ((file (file-name-sans-versions (file-name-nondirectory filename))))
- (if (string-match "\\.[^.]*\\'" file)
- (substring file (+ (match-beginning 0) (if period 0 1)))
- (if period
- "")))))
-
-(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."
- (if (and (eq system-type 'ms-dos)
- (not (msdos-long-file-names)))
- (let ((fn (file-name-nondirectory file)))
- (concat (file-name-directory file)
- (or
- (and (string-match "\\`[^.]+\\'" fn)
- (concat (match-string 0 fn) ".~"))
- (and (string-match "\\`[^.]+\\.\\(..?\\)?" fn)
- (concat (match-string 0 fn) "~")))))
- (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))
-
-;; This is used in various files.
-;; The usage of bv-length is not very clean,
-;; but I can't see a good alternative,
-;; so as of now I am leaving it alone.
-(defun backup-extract-version (fn)
- "Given the name of a numeric backup file, return the backup number.
-Uses the free variable `bv-length', whose value should be
-the index in the name where the version number begins."
- (if (and (string-match "[0-9]+~$" fn bv-length)
- (= (match-beginning 0) bv-length))
- (string-to-int (substring fn bv-length -1))
- 0))
-
-;; 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 the value is nil, don't make a backup."
- (let ((handler (find-file-name-handler fn 'find-backup-file-name)))
- ;; Run a handler for this function so that ange-ftp can refuse to do it.
- (if handler
- (funcall handler 'find-backup-file-name fn)
- (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
- (versions nil)
- (high-water-mark 0)
- (deserve-versions-p nil)
- (number-to-delete 0))
- (condition-case ()
- (setq possibilities (file-name-all-completions
- base-versions
- (file-name-directory fn))
- versions (sort (mapcar
- (function backup-extract-version)
- possibilities)
- '<)
- high-water-mark (apply 'max 0 versions)
- deserve-versions-p (or version-control
- (> high-water-mark 0))
- number-to-delete (- (length versions)
- kept-old-versions kept-new-versions -1))
- (file-error
- (setq possibilities nil)))
- (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 file-nlinks (filename)
- "Return number of names file FILENAME has."
- (car (cdr (file-attributes filename))))
-
-(defun file-relative-name (filename &optional directory)
- "Convert FILENAME to be relative to DIRECTORY (default: default-directory)."
- (setq filename (expand-file-name filename)
- directory (file-name-as-directory (expand-file-name
- (or directory default-directory))))
- (let ((ancestor ""))
- (while (not (string-match (concat "^" (regexp-quote directory)) filename))
- (setq directory (file-name-directory (substring directory 0 -1))
- ancestor (concat "../" ancestor)))
- (concat ancestor (substring filename (match-end 0)))))
-
-(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 \\[universal-argument], marks this version
- to become a backup when the next save is done.
-With 2 \\[universal-argument]'s,
- unconditionally makes the previous version into a backup file.
-With 3 \\[universal-argument]'s, marks this version
- to become a backup when the next save is done,
- and 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 `delete-old-versions' 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 (or (and make-backup-files (not (eq args 0)))
- (memq args '(16 64)))))
- (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 (&optional force)
- "Delete auto-save file for current buffer if `delete-auto-save-files' is t.
-Normally delete only if the file was written by this Emacs since
-the last real save, but optional arg FORCE non-nil means delete anyway."
- (and buffer-auto-save-file-name delete-auto-save-files
- (not (string= buffer-file-name buffer-auto-save-file-name))
- (or force (recent-auto-save-p))
- (progn
- (condition-case ()
- (delete-file buffer-auto-save-file-name)
- (file-error nil))
- (set-buffer-auto-saved))))
-
-(defvar after-save-hook nil
- "Normal hook that is run after a buffer is saved to its file.")
-
-(defun basic-save-buffer ()
- "Save the current buffer in its visited file, if it has been modified.
-After saving the buffer, run `after-save-hook'."
- (interactive)
- (save-excursion
- ;; In an indirect buffer, save its base buffer instead.
- (if (buffer-base-buffer)
- (set-buffer (buffer-base-buffer)))
- (if (buffer-modified-p)
- (let ((recent-save (recent-auto-save-p))
- setmodes tempsetmodes)
- ;; On VMS, rename file and buffer to get rid of version number.
- (if (and (eq system-type 'vax-vms)
- (not (string= buffer-file-name
- (file-name-sans-versions buffer-file-name))))
- (let (buffer-new-name)
- ;; Strip VMS version number before save.
- (setq buffer-file-name
- (file-name-sans-versions buffer-file-name))
- ;; Construct a (unique) buffer name to correspond.
- (let ((buf (create-file-buffer (downcase buffer-file-name))))
- (setq buffer-new-name (buffer-name buf))
- (kill-buffer buf))
- (rename-buffer buffer-new-name)))
- ;; If buffer has no file name, ask user for one.
- (or buffer-file-name
- (let ((filename
- (expand-file-name
- (read-file-name "File to save in: ") nil)))
- (and (file-exists-p filename)
- (or (y-or-n-p (format "File `%s' exists; overwrite? "
- filename))
- (error "Canceled")))
- (set-visited-file-name filename)))
- (or (verify-visited-file-modtime (current-buffer))
- (not (file-exists-p buffer-file-name))
- (yes-or-no-p
- (format "%s has changed since visited or saved. Save anyway? "
- (file-name-nondirectory buffer-file-name)))
- (error "Save not confirmed"))
- (save-restriction
- (widen)
- (and (> (point-max) 1)
- (/= (char-after (1- (point-max))) ?\n)
- (not (and (eq selective-display t)
- (= (char-after (1- (point-max))) ?\r)))
- (or (eq require-final-newline t)
- (and require-final-newline
- (y-or-n-p
- (format "Buffer %s does not end in newline. Add one? "
- (buffer-name)))))
- (save-excursion
- (goto-char (point-max))
- (insert ?\n)))
- (or (run-hook-with-args-until-success 'write-contents-hooks)
- (run-hook-with-args-until-success 'local-write-file-hooks)
- (run-hook-with-args-until-success 'write-file-hooks)
- ;; If a hook returned t, file is already "written".
- ;; Otherwise, write it the usual way now.
- (setq setmodes (basic-save-buffer-1)))
- (setq buffer-file-number
- (nthcdr 10 (file-attributes buffer-file-name)))
- (if setmodes
- (condition-case ()
- (set-file-modes buffer-file-name setmodes)
- (error nil))))
- ;; If the auto-save file was recent before this command,
- ;; delete it now.
- (delete-auto-save-file-if-necessary recent-save)
- ;; Support VC `implicit' locking.
- (vc-after-save)
- (run-hooks 'after-save-hook))
- (message "(No changes need to be saved)"))))
-
-;; This does the "real job" of writing a buffer into its visited file
-;; and making a backup file. This is what is normally done
-;; but inhibited if one of write-file-hooks returns non-nil.
-;; It returns a value to store in setmodes.
-(defun basic-save-buffer-1 ()
- (let (tempsetmodes setmodes)
- (if (not (file-writable-p buffer-file-name))
- (let ((dir (file-name-directory buffer-file-name)))
- (if (not (file-directory-p dir))
- (error "%s is not a directory" dir)
- (if (not (file-exists-p buffer-file-name))
- (error "Directory %s write-protected" dir)
- (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 buffer-backed-up
- (setq setmodes (backup-buffer)))
- (let ((dir (file-name-directory buffer-file-name)))
- (if (and file-precious-flag
- (file-writable-p dir))
- ;; If file is precious, write temp name, then rename it.
- ;; This requires write access to the containing dir,
- ;; which is why we don't try it if we don't have that access.
- (let ((realname buffer-file-name)
- tempname temp nogood i succeed
- (old-modtime (visited-file-modtime)))
- (setq i 0)
- (setq nogood t)
- ;; Find the temporary name to write under.
- (while nogood
- (setq tempname (format
- (if (and (eq system-type 'ms-dos)
- (not (msdos-long-file-names)))
- "%s#%d.tm#" ; MSDOS limits files to 8+3
- "%s#tmp#%d")
- dir i))
- (setq nogood (file-exists-p tempname))
- (setq i (1+ i)))
- (unwind-protect
- (progn (clear-visited-file-modtime)
- (write-region (point-min) (point-max)
- tempname nil realname
- buffer-file-truename)
- (setq succeed t))
- ;; If writing the temp file fails,
- ;; delete the temp file.
- (or succeed
- (progn
- (delete-file tempname)
- (set-visited-file-modtime old-modtime))))
- ;; Since we have created an entirely new file
- ;; and renamed it, make sure it gets the
- ;; right permission bits set.
- (setq setmodes (file-modes buffer-file-name))
- ;; We succeeded in writing the temp file,
- ;; so rename it.
- (rename-file tempname buffer-file-name t))
- ;; 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.
- (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 buffer-file-truename)))
- setmodes))
-
-(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")
- (save-window-excursion
- (let* ((queried nil)
- (files-done
- (map-y-or-n-p
- (function
- (lambda (buffer)
- (and (buffer-modified-p buffer)
- (not (buffer-base-buffer buffer))
- (or
- (buffer-file-name buffer)
- (and exiting
- (progn
- (set-buffer buffer)
- (and buffer-offer-save (> (buffer-size) 0)))))
- (if arg
- t
- (setq queried t)
- (if (buffer-file-name buffer)
- (format "Save file %s? "
- (buffer-file-name buffer))
- (format "Save buffer %s? "
- (buffer-name buffer)))))))
- (function
- (lambda (buffer)
- (set-buffer buffer)
- (save-buffer)))
- (buffer-list)
- '("buffer" "buffers" "save")
- (list (list ?\C-r (lambda (buf)
- (view-buffer buf)
- (setq view-exit-action
- '(lambda (ignore)
- (exit-recursive-edit)))
- (recursive-edit)
- ;; Return nil to ask about BUF again.
- nil)
- "display the current buffer"))))
- (abbrevs-done
- (and save-abbrevs abbrevs-changed
- (progn
- (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)
- t))))
- (or queried (> files-done 0) abbrevs-done
- (message "(No files need saving)")))))
-
-(defun not-modified (&optional arg)
- "Mark current buffer as unmodified, not needing to be saved.
-With prefix arg, mark buffer as modified, so \\[save-buffer] will save.
-
-It is not a good idea to use this function in Lisp programs, because it
-prints a message in the minibuffer. Instead, use `set-buffer-modified-p'."
- (interactive "P")
- (message (if arg "Modification-flag set"
- "Modification-flag cleared"))
- (set-buffer-modified-p arg))
-
-(defun toggle-read-only (&optional arg)
- "Change whether this buffer is visiting its file read-only.
-With arg, set read-only iff arg is positive."
- (interactive "P")
- (setq buffer-read-only
- (if (null arg)
- (not buffer-read-only)
- (> (prefix-numeric-value arg) 0)))
- (force-mode-line-update))
-
-(defun insert-file (filename)
- "Insert contents of file FILENAME into buffer after point.
-Set mark after the inserted text.
-
-This function is meant for the user to run interactively.
-Don't call it from programs! Use `insert-file-contents' instead.
-\(Its calling sequence is different; see its documentation)."
- (interactive "*fInsert file: ")
- (if (file-directory-p filename)
- (signal 'file-error (list "Opening input file" "file is a directory"
- filename)))
- (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))
-
-(defun file-newest-backup (filename)
- "Return most recent backup file for FILENAME or nil if no backups exist."
- (let* ((filename (expand-file-name filename))
- (file (file-name-nondirectory filename))
- (dir (file-name-directory filename))
- (comp (file-name-all-completions file dir))
- (newest nil)
- tem)
- (while comp
- (setq tem (car comp)
- comp (cdr comp))
- (cond ((and (backup-file-name-p tem)
- (string= (file-name-sans-versions tem) file))
- (setq tem (concat dir tem))
- (if (or (null newest)
- (file-newer-than-file-p tem newest))
- (setq newest tem)))))
- newest))
-
-(defun rename-uniquely ()
- "Rename current buffer to a similar name not already taken.
-This function is useful for creating multiple shell process buffers
-or multiple mail buffers, etc."
- (interactive)
- (save-match-data
- (let* ((base-name (if (and (string-match "<[0-9]+>\\'" (buffer-name))
- (not (and buffer-file-name
- (string= (buffer-name)
- (file-name-nondirectory
- buffer-file-name)))))
- ;; If the existing buffer name has a <NNN>,
- ;; which isn't part of the file name (if any),
- ;; then get rid of that.
- (substring (buffer-name) 0 (match-beginning 0))
- (buffer-name)))
- (new-buf (generate-new-buffer base-name))
- (name (buffer-name new-buf)))
- (kill-buffer new-buf)
- (rename-buffer name)
- (force-mode-line-update))))
-
-(defun make-directory (dir &optional parents)
- "Create the directory DIR and any nonexistent parent dirs.
-Interactively, the default choice of directory to create
-is the current default directory for file names.
-That is useful when you have visited a file in a nonexistent directory.
-
-Noninteractively, the second (optional) argument PARENTS says whether
-to create parent directories if they don't exist."
- (interactive
- (list (read-file-name "Make directory: " default-directory default-directory
- nil nil)
- t))
- (let ((handler (find-file-name-handler dir 'make-directory)))
- (if handler
- (funcall handler 'make-directory dir parents)
- (if (not parents)
- (make-directory-internal dir)
- (let ((dir (directory-file-name (expand-file-name dir)))
- create-list)
- (while (not (file-exists-p dir))
- (setq create-list (cons dir create-list)
- dir (directory-file-name (file-name-directory dir))))
- (while create-list
- (make-directory-internal (car create-list))
- (setq create-list (cdr create-list))))))))
-
-(put 'revert-buffer-function 'permanent-local t)
-(defvar revert-buffer-function nil
- "Function to use to revert this buffer, or nil to do the default.
-The function receives two arguments IGNORE-AUTO and NOCONFIRM,
-which are the arguments that `revert-buffer' received.")
-
-(put 'revert-buffer-insert-file-contents-function 'permanent-local t)
-(defvar revert-buffer-insert-file-contents-function nil
- "Function to use to insert contents when reverting this buffer.
-Gets two args, first the nominal file name to use,
-and second, t if reading the auto-save file.")
-
-(defvar before-revert-hook nil
- "Normal hook for `revert-buffer' to run before reverting.
-If `revert-buffer-function' is used to override the normal revert
-mechanism, this hook is not used.")
-
-(defvar after-revert-hook nil
- "Normal hook for `revert-buffer' to run after reverting.
-Note that the hook value that it runs is the value that was in effect
-before reverting; that makes a difference if you have buffer-local
-hook functions.
-
-If `revert-buffer-function' is used to override the normal revert
-mechanism, this hook is not used.")
-
-(defun revert-buffer (&optional ignore-auto noconfirm preserve-modes)
- "Replace current buffer text with the text of the visited file on disk.
-This undoes all changes since the file was visited or saved.
-With a prefix argument, offer to revert from latest auto-save file, if
-that is more recent than the visited file.
-
-This command also works for special buffers that contain text which
-doesn't come from a file, but reflects some other data base instead:
-for example, Dired buffers and buffer-list buffers. In these cases,
-it reconstructs the buffer contents from the appropriate data base.
-
-When called from Lisp, the first argument is IGNORE-AUTO; only offer
-to revert from the auto-save file when this is nil. Note that the
-sense of this argument is the reverse of the prefix argument, for the
-sake of backward compatibility. IGNORE-AUTO is optional, defaulting
-to nil.
-
-Optional second argument NOCONFIRM means don't ask for confirmation at
-all.
-
-Optional third argument PRESERVE-MODES non-nil means don't alter
-the files modes. Normally we reinitialize them using `normal-mode'.
-
-If the value of `revert-buffer-function' is non-nil, it is called to
-do all the work for this command. Otherwise, the hooks
-`before-revert-hook' and `after-revert-hook' are run at the beginning
-and the end, and if `revert-buffer-insert-file-contents-function' is
-non-nil, it is called instead of rereading visited file contents."
-
- ;; I admit it's odd to reverse the sense of the prefix argument, but
- ;; there is a lot of code out there which assumes that the first
- ;; argument should be t to avoid consulting the auto-save file, and
- ;; there's no straightforward way to encourage authors to notice a
- ;; reversal of the argument sense. So I'm just changing the user
- ;; interface, but leaving the programmatic interface the same.
- (interactive (list (not current-prefix-arg)))
- (if revert-buffer-function
- (funcall revert-buffer-function ignore-auto noconfirm)
- (let* ((opoint (point))
- (auto-save-p (and (not ignore-auto)
- (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"))
- ((or noconfirm
- (yes-or-no-p (format "Revert buffer from file %s? "
- file-name)))
- (run-hooks 'before-revert-hook)
- ;; 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))
- ;; Get rid of all undo records for this buffer.
- (or (eq buffer-undo-list t)
- (setq buffer-undo-list nil))
- ;; Effectively copy the after-revert-hook status,
- ;; since after-find-file will clobber it.
- (let ((global-hook (default-value 'after-revert-hook))
- (local-hook-p (local-variable-p 'after-revert-hook))
- (local-hook (and (local-variable-p 'after-revert-hook)
- after-revert-hook)))
- (let (buffer-read-only
- ;; Don't make undo records for the reversion.
- (buffer-undo-list t))
- (if revert-buffer-insert-file-contents-function
- (funcall revert-buffer-insert-file-contents-function
- file-name auto-save-p)
- (if (not (file-exists-p file-name))
- (error "File %s no longer exists!" file-name))
- ;; 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)))
- (widen)
- (insert-file-contents file-name (not auto-save-p)
- nil nil t)))
- (goto-char (min opoint (point-max)))
- ;; Recompute the truename in case changes in symlinks
- ;; have changed the truename.
- (setq buffer-file-truename
- (abbreviate-file-name (file-truename buffer-file-name)))
- (after-find-file nil nil t t preserve-modes)
- ;; Run after-revert-hook as it was before we reverted.
- (setq-default revert-buffer-internal-hook global-hook)
- (if local-hook-p
- (progn
- (make-local-variable 'revert-buffer-internal-hook)
- (setq revert-buffer-internal-hook local-hook))
- (kill-local-variable 'revert-buffer-internal-hook))
- (run-hooks 'revert-buffer-internal-hook))
- t)))))
-
-(defun recover-file (file)
- "Visit file FILE, but get contents from its last auto-save file."
- ;; Actually putting the file name in the minibuffer should be used
- ;; only rarely.
- ;; Not just because users often use the default.
- (interactive "FRecover file: ")
- (setq file (expand-file-name file))
- (if (auto-save-file-name-p (file-name-nondirectory file))
- (error "%s is an auto-save file" file))
- (let ((file-name (let ((buffer-file-name file))
- (make-auto-save-file-name))))
- (cond ((if (file-exists-p file)
- (not (file-newer-than-file-p file-name file))
- (not (file-exists-p file-name)))
- (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-disable-undo standard-output)
- (call-process "ls" nil standard-output nil
- (if (file-symlink-p file) "-lL" "-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 nil t))
- (t (error "Recover-file cancelled.")))))
-
-(defun recover-session ()
- "Recover auto save files from a previous Emacs session.
-This command first displays a Dired buffer showing you the
-previous sessions that you could recover from.
-To choose one, move point to the proper line and then type C-c C-c.
-Then you'll be asked about a number of files to recover."
- (interactive)
- (if (null auto-save-list-file-prefix)
- (error "You set `auto-save-list-file-prefix' to disable making session files"))
- (let ((ls-lisp-support-shell-wildcards t))
- (dired (concat auto-save-list-file-prefix "*")))
- (goto-char (point-min))
- (or (looking-at "Move to the session you want to recover,")
- (let ((inhibit-read-only t))
- (insert "Move to the session you want to recover,\n"
- "then type C-c C-c to select it.\n\n"
- "You can also delete some of these files;\n"
- "type d on a line to mark that file for deletion.\n\n")))
- (use-local-map (nconc (make-sparse-keymap) (current-local-map)))
- (define-key (current-local-map) "\C-c\C-c" 'recover-session-finish))
-
-(defun recover-session-finish ()
- "Choose one saved session to recover auto-save files from.
-This command is used in the special Dired buffer created by
-\\[recover-session]."
- (interactive)
- ;; Get the name of the session file to recover from.
- (let ((file (dired-get-filename))
- files
- (buffer (get-buffer-create " *recover*")))
- (dired-do-flagged-delete t)
- (unwind-protect
- (save-excursion
- ;; Read in the auto-save-list file.
- (set-buffer buffer)
- (erase-buffer)
- (insert-file-contents file)
- ;; Loop thru the text of that file
- ;; and get out the names of the files to recover.
- (while (not (eobp))
- (let (thisfile autofile)
- (if (eolp)
- ;; This is a pair of lines for a non-file-visiting buffer.
- ;; Get the auto-save file name and manufacture
- ;; a "visited file name" from that.
- (progn
- (forward-line 1)
- (setq autofile
- (buffer-substring-no-properties
- (point)
- (save-excursion
- (end-of-line)
- (point))))
- (setq thisfile
- (expand-file-name
- (substring
- (file-name-nondirectory autofile)
- 1 -1)
- (file-name-directory autofile)))
- (forward-line 1))
- ;; This pair of lines is a file-visiting
- ;; buffer. Use the visited file name.
- (progn
- (setq thisfile
- (buffer-substring-no-properties
- (point) (progn (end-of-line) (point))))
- (forward-line 1)
- (setq autofile
- (buffer-substring-no-properties
- (point) (progn (end-of-line) (point))))
- (forward-line 1)))
- ;; Ignore a file if its auto-save file does not exist now.
- (if (file-exists-p autofile)
- (setq files (cons thisfile files)))))
- (setq files (nreverse files))
- ;; The file contains a pair of line for each auto-saved buffer.
- ;; The first line of the pair contains the visited file name
- ;; or is empty if the buffer was not visiting a file.
- ;; The second line is the auto-save file name.
- (if files
- (map-y-or-n-p "Recover %s? "
- (lambda (file)
- (condition-case nil
- (save-excursion (recover-file file))
- (error
- "Failed to recover `%s'" file)))
- files
- '("file" "files" "recover"))
- (message "No files can be recovered from this session now")))
- (kill-buffer buffer))))
-
-(defun kill-some-buffers (&optional list)
- "For each buffer in LIST, ask whether to kill it.
-LIST defaults to all existing live buffers."
- (interactive)
- (if (null list)
- (setq 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 prefix argument ARG, turn auto-saving on if positive, else off."
- (interactive "P")
- (setq buffer-auto-save-file-name
- (and (if (null arg)
- (or (not buffer-auto-save-file-name)
- ;; If autosave is off because buffer has shrunk,
- ;; then toggling should turn it on.
- (< buffer-saved-size 0))
- (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 -1 was stored here, to temporarily turn off saving,
- ;; turn it back on.
- (and (< buffer-saved-size 0)
- (setq buffer-saved-size 0))
- (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, if it was made in this session."
- (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)
- (recent-auto-save-p))
- (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' as that variable is checked
-before calling this function. You can redefine this for customization.
-See also `auto-save-file-name-p'."
- (if buffer-file-name
- (if (and (eq system-type 'ms-dos)
- (not (msdos-long-file-names)))
- (let ((fn (file-name-nondirectory buffer-file-name)))
- (string-match "\\`\\([^.]+\\)\\(\\.\\(..?\\)?.?\\|\\)\\'" fn)
- (concat (file-name-directory buffer-file-name)
- "#" (match-string 1 fn)
- "." (match-string 3 fn) "#"))
- (concat (file-name-directory buffer-file-name)
- "#"
- (file-name-nondirectory buffer-file-name)
- "#"))
-
- ;; Deal with buffers that don't have any associated files. (Mail
- ;; mode tends to create a good number of these.)
-
- (let ((buffer-name (buffer-name))
- (limit 0))
- ;; Use technique from Sebastian Kremer's auto-save
- ;; package to turn slashes into \\!. This ensures that
- ;; the auto-save buffer name is unique.
-
- (while (string-match "[/\\]" buffer-name limit)
- (setq buffer-name (concat (substring buffer-name 0 (match-beginning 0))
- (if (string= (substring buffer-name
- (match-beginning 0)
- (match-end 0))
- "/")
- "\\!"
- "\\\\")
- (substring buffer-name (match-end 0))))
- (setq limit (1+ (match-end 0))))
- ;; Generate the file name.
- (expand-file-name
- (format "#%s#%s#" buffer-name (make-temp-name ""))
- ;; Try a few alternative directories, to get one we can write it.
- (cond
- ((file-writable-p default-directory) default-directory)
- ((file-writable-p "/var/tmp/") "/var/tmp/")
- ("~/"))))))
-
-(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))
-
-(defun wildcard-to-regexp (wildcard)
- "Given a shell file name pattern WILDCARD, return an equivalent regexp.
-The generated regexp will match a filename iff the filename
-matches that wildcard according to shell rules. Only wildcards known
-by `sh' are supported."
- (let* ((i (string-match "[[.*+\\^$?]" wildcard))
- ;; Copy the initial run of non-special characters.
- (result (substring wildcard 0 i))
- (len (length wildcard)))
- ;; If no special characters, we're almost done.
- (if i
- (while (< i len)
- (let ((ch (aref wildcard i))
- j)
- (setq
- result
- (concat result
- (cond
- ((and (eq ch ?\[)
- (< (1+ i) len)
- (eq (aref wildcard (1+ i)) ?\]))
- "\\[")
- ((eq ch ?\[) ; [...] maps to regexp char class
- (progn
- (setq i (1+ i))
- (concat
- (cond
- ((eq (aref wildcard i) ?!) ; [!...] -> [^...]
- (progn
- (setq i (1+ i))
- (if (eq (aref wildcard i) ?\])
- (progn
- (setq i (1+ i))
- "[^]")
- "[^")))
- ((eq (aref wildcard i) ?^)
- ;; Found "[^". Insert a `\0' character
- ;; (which cannot happen in a filename)
- ;; into the character class, so that `^'
- ;; is not the first character after `[',
- ;; and thus non-special in a regexp.
- (progn
- (setq i (1+ i))
- "[\000^"))
- ((eq (aref wildcard i) ?\])
- ;; I don't think `]' can appear in a
- ;; character class in a wildcard, but
- ;; let's be general here.
- (progn
- (setq i (1+ i))
- "[]"))
- (t "["))
- (prog1 ; copy everything upto next `]'.
- (substring wildcard
- i
- (setq j (string-match
- "]" wildcard i)))
- (setq i (if j (1- j) (1- len)))))))
- ((eq ch ?.) "\\.")
- ((eq ch ?*) "[^\000]*")
- ((eq ch ?+) "\\+")
- ((eq ch ?^) "\\^")
- ((eq ch ?$) "\\$")
- ((eq ch ?\\) "\\\\") ; probably cannot happen...
- ((eq ch ??) "[^\000]")
- (t (char-to-string ch)))))
- (setq i (1+ i)))))
- ;; Shell wildcards should match the entire filename,
- ;; not its part. Make the regexp say so.
- (concat "\\`" result "\\'")))
-
-(defvar list-directory-brief-switches
- (if (eq system-type 'vax-vms) "" "-CF")
- "*Switches for list-directory to pass to `ls' for brief listing,")
-
-(defvar list-directory-verbose-switches
- (if (eq system-type 'vax-vms)
- "/PROTECTION/SIZE/DATE/OWNER/WIDTH=(OWNER:10)"
- "-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)))
- (or dirname (setq dirname default-directory))
- (setq dirname (expand-file-name dirname))
- (with-output-to-temp-buffer "*Directory*"
- (buffer-disable-undo standard-output)
- (princ "Directory ")
- (princ dirname)
- (terpri)
- (save-excursion
- (set-buffer "*Directory*")
- (setq default-directory
- (if (file-directory-p dirname)
- (file-name-as-directory dirname)
- (file-name-directory dirname)))
- (let ((wildcard (not (file-directory-p dirname))))
- (insert-directory dirname switches wildcard (not wildcard)))))))
-
-(defvar insert-directory-program "ls"
- "Absolute or relative name of the `ls' program used by `insert-directory'.")
-
-;; insert-directory
-;; - must insert _exactly_one_line_ describing FILE if WILDCARD and
-;; FULL-DIRECTORY-P is nil.
-;; The single line of output must display FILE's name as it was
-;; given, namely, an absolute path name.
-;; - must insert exactly one line for each file if WILDCARD or
-;; FULL-DIRECTORY-P is t, plus one optional "total" line
-;; before the file lines, plus optional text after the file lines.
-;; Lines are delimited by "\n", so filenames containing "\n" are not
-;; allowed.
-;; File lines should display the basename.
-;; - must be consistent with
-;; - functions dired-move-to-filename, (these two define what a file line is)
-;; dired-move-to-end-of-filename,
-;; dired-between-files, (shortcut for (not (dired-move-to-filename)))
-;; dired-insert-headerline
-;; dired-after-subdir-garbage (defines what a "total" line is)
-;; - variable dired-subdir-regexp
-(defun insert-directory (file switches &optional wildcard full-directory-p)
- "Insert directory listing for FILE, formatted according to SWITCHES.
-Leaves point after the inserted text.
-SWITCHES may be a string of options, or a list of strings.
-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', so that a full listing is expected.
-
-This works by running a directory listing program
-whose name is in the variable `insert-directory-program'.
-If WILDCARD, it also runs the shell specified by `shell-file-name'."
- ;; We need the directory in order to find the right handler.
- (let ((handler (find-file-name-handler (expand-file-name file)
- 'insert-directory)))
- (if handler
- (funcall handler 'insert-directory file switches
- wildcard full-directory-p)
- (if (eq system-type 'vax-vms)
- (vms-read-directory file switches (current-buffer))
- (or (= 0
- (if wildcard
- ;; Run ls in the directory of the file pattern we asked for.
- (let ((default-directory
- (if (file-name-absolute-p file)
- (file-name-directory file)
- (file-name-directory (expand-file-name file))))
- (pattern (file-name-nondirectory file))
- (beg 0))
- ;; Quote some characters that have special meanings in shells;
- ;; but don't quote the wildcards--we want them to be special.
- ;; We also currently don't quote the quoting characters
- ;; in case people want to use them explicitly to quote
- ;; wildcard characters.
- (while (string-match "[ \t\n;<>&|()#$]" pattern beg)
- (setq pattern
- (concat (substring pattern 0 (match-beginning 0))
- "\\"
- (substring pattern (match-beginning 0)))
- beg (1+ (match-end 0))))
- (call-process shell-file-name nil t nil
- "-c" (concat "\\" ;; Disregard shell aliases!
- insert-directory-program
- " -d "
- (if (stringp switches)
- switches
- (mapconcat 'identity switches " "))
- " -- "
- pattern)))
- ;; SunOS 4.1.3, SVr4 and others need the "." to list the
- ;; directory if FILE is a symbolic link.
- (apply 'call-process
- insert-directory-program nil t nil
- (let (list)
- (if (listp switches)
- (setq list switches)
- (if (not (equal switches ""))
- (progn
- ;; Split the switches at any spaces
- ;; so we can pass separate options as separate args.
- (while (string-match " " switches)
- (setq list (cons (substring switches 0 (match-beginning 0))
- list)
- switches (substring switches (match-end 0))))
- (setq list (nreverse (cons switches list))))))
- (append list
- ;; Avoid lossage if FILE starts with `-'.
- '("--")
- (list
- (if full-directory-p
- (concat (file-name-as-directory file) ".")
- file)))))))
- ;; We get here if ls failed.
- ;; Access the file to get a suitable error.
- (access-file file "Reading directory"))))))
-
-(defvar kill-emacs-query-functions nil
- "Functions to call with no arguments to query about killing Emacs.
-If any of these functions returns nil, killing Emacs is cancelled.
-`save-buffers-kill-emacs' (\\[save-buffers-kill-emacs]) calls these functions,
-but `kill-emacs', the low level primitive, does not.
-See also `kill-emacs-hook'.")
-
-(defun save-buffers-kill-emacs (&optional arg)
- "Offer to save each buffer, then kill this Emacs process.
-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? "))))
- ;; Query the user for other things, perhaps.
- (run-hook-with-args-until-failure 'kill-emacs-query-functions)
- (kill-emacs)))
-
-;; We use /: as a prefix to "quote" a file name
-;; so that magic file name handlers will not apply to it.
-
-(setq file-name-handler-alist
- (cons '("\\`/:" . file-name-non-special)
- file-name-handler-alist))
-
-;; We depend on being the last handler on the list,
-;; so that anything else which does need handling
-;; has been handled already.
-;; So it is safe for us to inhibit *all* magic file name handlers.
-
-(defun file-name-non-special (operation &rest arguments)
- (let ((file-name-handler-alist nil)
- ;; Get a list of the indices of the args which are file names.
- (file-arg-indices
- (cdr (or (assq operation
- ;; The first four are special because they
- ;; return a file name. We want to include the /:
- ;; in the return value.
- ;; So just avoid stripping it in the first place.
- '((expand-file-name . nil)
- (file-name-directory . nil)
- (file-name-as-directory . nil)
- (directory-file-name . nil)
- (rename-file 0 1)
- (copy-file 0 1)
- (make-symbolic-link 0 1)
- (add-name-to-file 0 1)))
- ;; For all other operations, treat the first argument only
- ;; as the file name.
- '(nil 0))))
- ;; Copy ARGUMENTS so we can replace elements in it.
- (arguments (copy-sequence arguments)))
- ;; Strip off the /: from the file names that have this handler.
- (save-match-data
- (while file-arg-indices
- (and (nth (car file-arg-indices) arguments)
- (string-match "\\`/:" (nth (car file-arg-indices) arguments))
- (setcar (nthcdr (car file-arg-indices) arguments)
- (substring (nth (car file-arg-indices) arguments) 2)))
- (setq file-arg-indices (cdr file-arg-indices))))
- (apply operation arguments)))
-
-(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)
-
-(define-key ctl-x-4-map "f" 'find-file-other-window)
-(define-key ctl-x-4-map "r" 'find-file-read-only-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)
-(define-key ctl-x-4-map "\C-o" 'display-buffer)
-
-(define-key ctl-x-5-map "b" 'switch-to-buffer-other-frame)
-(define-key ctl-x-5-map "f" 'find-file-other-frame)
-(define-key ctl-x-5-map "\C-f" 'find-file-other-frame)
-(define-key ctl-x-5-map "r" 'find-file-read-only-other-frame)
-
-;;; files.el ends here
diff --git a/lisp/find-dired.el b/lisp/find-dired.el
deleted file mode 100644
index a46c6c65150..00000000000
--- a/lisp/find-dired.el
+++ /dev/null
@@ -1,212 +0,0 @@
-;;; find-dired.el --- run a `find' command and dired the output
-
-;; Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Roland McGrath <roland@gnu.ai.mit.edu>,
-;; Sebastian Kremer <sk@thp.uni-koeln.de>
-;; Keywords: unix
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(require 'dired)
-
-;; find's -ls corresponds to these switches.
-;; Note -b, at least GNU find quotes spaces etc. in filenames
-;;;###autoload
-(defvar find-ls-option (if (eq system-type 'berkeley-unix) '("-ls" . "-gilsb")
- '("-exec ls -ld {} \\;" . "-ld"))
- "*Description of the option to `find' to produce an `ls -l'-type listing.
-This is a cons of two strings (FIND-OPTION . LS-SWITCHES). FIND-OPTION
-gives the option (or options) to `find' that produce the desired output.
-LS-SWITCHES is a list of `ls' switches to tell dired how to parse the output.")
-
-;;;###autoload
-(defvar find-grep-options
- (if (or (eq system-type 'berkeley-unix)
- (string-match "solaris2" system-configuration)
- (string-match "irix" system-configuration))
- "-s" "-q")
- "*Option to grep to be as silent as possible.
-On Berkeley systems, this is `-s'; on Posix, and with GNU grep, `-q' does it.
-On other systems, the closest you can come is to use `-l'.")
-
-(defvar find-args nil
- "Last arguments given to `find' by \\[find-dired].")
-
-;; History of find-args values entered in the minibuffer.
-(defvar find-args-history nil)
-
-;;;###autoload
-(defun find-dired (dir args)
- "Run `find' and go into dired-mode on a buffer of the output.
-The command run (after changing into DIR) is
-
- find . \\( ARGS \\) -ls
-
-except that the variable `find-ls-option' specifies what to use
-as the final argument."
- (interactive (list (read-file-name "Run find in directory: " nil "" t)
- (read-string "Run find (with args): " find-args
- '(find-args-history . 1))))
- ;; Expand DIR ("" means default-directory), and make sure it has a
- ;; trailing slash.
- (setq dir (file-name-as-directory (expand-file-name dir)))
- ;; Check that it's really a directory.
- (or (file-directory-p dir)
- (error "find-dired needs a directory: %s" dir))
- (switch-to-buffer (get-buffer-create "*Find*"))
- (widen)
- (kill-all-local-variables)
- (setq buffer-read-only nil)
- (erase-buffer)
- (setq default-directory dir
- find-args args ; save for next interactive call
- args (concat "find . "
- (if (string= args "")
- ""
- (concat "\\( " args " \\) "))
- (car find-ls-option)))
- ;; The next statement will bomb in classic dired (no optional arg allowed)
- (dired-mode dir (cdr find-ls-option))
- ;; This really should rerun the find command, but I don't
- ;; have time for that.
- (use-local-map (append (make-sparse-keymap) (current-local-map)))
- (define-key (current-local-map) "g" 'undefined)
- ;; Set subdir-alist so that Tree Dired will work:
- (if (fboundp 'dired-simple-subdir-alist)
- ;; will work even with nested dired format (dired-nstd.el,v 1.15
- ;; and later)
- (dired-simple-subdir-alist)
- ;; else we have an ancient tree dired (or classic dired, where
- ;; this does no harm)
- (set (make-local-variable 'dired-subdir-alist)
- (list (cons default-directory (point-min-marker)))))
- (setq buffer-read-only nil)
- ;; Subdir headlerline must come first because the first marker in
- ;; subdir-alist points there.
- (insert " " dir ":\n")
- ;; Make second line a ``find'' line in analogy to the ``total'' or
- ;; ``wildcard'' line.
- (insert " " args "\n")
- ;; Start the find process.
- (let ((proc (start-process-shell-command "find" (current-buffer) args)))
- (set-process-filter proc (function find-dired-filter))
- (set-process-sentinel proc (function find-dired-sentinel))
- ;; Initialize the process marker; it is used by the filter.
- (move-marker (process-mark proc) 1 (current-buffer)))
- (setq mode-line-process '(":%s")))
-
-;;;###autoload
-(defun find-name-dired (dir pattern)
- "Search DIR recursively for files matching the globbing pattern PATTERN,
-and run dired on those files.
-PATTERN is a shell wildcard (not an Emacs regexp) and need not be quoted.
-The command run (after changing into DIR) is
-
- find . -name 'PATTERN' -ls"
- (interactive
- "DFind-name (directory): \nsFind-name (filename wildcard): ")
- (find-dired dir (concat "-name '" pattern "'")))
-
-;; This functionality suggested by
-;; From: oblanc@watcgl.waterloo.edu (Olivier Blanc)
-;; Subject: find-dired, lookfor-dired
-;; Date: 10 May 91 17:50:00 GMT
-;; Organization: University of Waterloo
-
-(defalias 'lookfor-dired 'find-grep-dired)
-;;;###autoload
-(defun find-grep-dired (dir args)
- "Find files in DIR containing a regexp ARG and start Dired on output.
-The command run (after changing into DIR) is
-
- find . -exec grep -s ARG {} \\\; -ls
-
-Thus ARG can also contain additional grep options."
- (interactive "DFind-grep (directory): \nsFind-grep (grep regexp): ")
- ;; find -exec doesn't allow shell i/o redirections in the command,
- ;; or we could use `grep -l >/dev/null'
- (find-dired dir
- (concat "! -type d -exec grep " find-grep-options " "
- args " {} \\\; ")))
-
-(defun find-dired-filter (proc string)
- ;; Filter for \\[find-dired] processes.
- (let ((buf (process-buffer proc)))
- (if (buffer-name buf) ; not killed?
- (save-excursion
- (set-buffer buf)
- (save-restriction
- (widen)
- (save-excursion
- (let ((buffer-read-only nil)
- (end (point-max)))
- (goto-char end)
- (insert string)
- (goto-char end)
- (or (looking-at "^")
- (forward-line 1))
- (while (looking-at "^")
- (insert " ")
- (forward-line 1))
- ;; Convert ` ./FILE' to ` FILE'
- ;; This would lose if the current chunk of output
- ;; starts or ends within the ` ./', so back up a bit:
- (goto-char (- end 3)) ; no error if < 0
- (while (search-forward " ./" nil t)
- (delete-region (point) (- (point) 2)))
- ;; Find all the complete lines in the unprocessed
- ;; output and process it to add text properties.
- (goto-char end)
- (if (search-backward "\n" (process-mark proc) t)
- (progn
- (dired-insert-set-properties (process-mark proc)
- (1+ (point)))
- (move-marker (process-mark proc) (1+ (point)))))
- ))))
- ;; The buffer has been killed.
- (delete-process proc))))
-
-(defun find-dired-sentinel (proc state)
- ;; Sentinel for \\[find-dired] processes.
- (let ((buf (process-buffer proc)))
- (if (buffer-name buf)
- (save-excursion
- (set-buffer buf)
- (let ((buffer-read-only nil))
- (save-excursion
- (goto-char (point-max))
- (insert "\nfind " state)
- (forward-char -1) ;Back up before \n at end of STATE.
- (insert " at " (substring (current-time-string) 0 19))
- (forward-char 1)
- (setq mode-line-process
- (concat ":"
- (symbol-name (process-status proc))))
- ;; Since the 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-update)))
- (message "find-dired %s finished." (current-buffer))))))
-
-(provide 'find-dired)
-
-;;; find-dired.el ends here
diff --git a/lisp/find-file.el b/lisp/find-file.el
deleted file mode 100644
index b8aee680516..00000000000
--- a/lisp/find-file.el
+++ /dev/null
@@ -1,913 +0,0 @@
-;;; find-file.el --- find a file corresponding to this one given a pattern
-
-;; Author: Henry Guillaume <henry@qbd.com.au>
-;; Keywords: c, matching, tools
-
-;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; PURPOSE:
-;; This package features a function called ff-find-other-file, which performs
-;; the following function:
-;;
-;; When in a .c file, find the first corresponding .h file in a set
-;; of directories and display it, and vice-versa from the .h file.
-;;
-;; Many people maintain their include file in a directory separate to their
-;; src directory, and very often you may be editing a file and have a need to
-;; visit the "other file". This package searches through a set of directories
-;; to find that file.
-;;
-;; THE "OTHER FILE", or "corresponding file", generally has the same basename,
-;; and just has a different extension as described by the ff-other-file-alist
-;; variable:
-;;
-;; '(("\\.cc$" (".hh" ".h"))
-;; ("\\.hh$" (".cc" ".C" ".CC" ".cxx" ".cpp")))
-;;
-;; If the current file has a .cc extension, ff-find-other-file will attempt
-;; to look for a .hh file, and then a .h file in some directory as described
-;; below. The mechanism here is to replace the matched part of the original
-;; filename with each of the corresponding extensions in turn.
-;;
-;; Alternatively, there are situations where the filename of the other file
-;; cannot be determined easily with regexps. For example, a .c file may
-;; have two corresponding .h files, for its public and private parts, or
-;; the filename for the .c file contains part of the pathname of the .h
-;; file, as between src/fooZap.cc and include/FOO/zap.hh. In that case, the
-;; format above can be changed to include a function to be called when the
-;; current file matches the regexp:
-;;
-;; '(("\\.cc$" cc-function)
-;; ("\\.hh$" hh-function))
-;;
-;; These functions must return a list consisting of the possible names of the
-;; corresponding file, with or without path. There is no real need for more
-;; than one function, and one could imagine the following value for cc-other-
-;; file-alist:
-;;
-;; (setq cc-other-file-alist
-;; '(("\\.cc$" ff-cc-hh-converter)
-;; ("\\.hh$" ff-cc-hh-converter)
-;; ("\\.c$" (".h"))
-;; ("\\.h$" (".c" ".cc" ".C" ".CC" ".cxx" ".cpp"))))
-;;
-;; ff-cc-hh-converter is included at the end of this file as a reference.
-;;
-;; SEARCHING is carried out in a set of directories specified by the
-;; ff-search-directories variable:
-;;
-;; ("." "../../src" "../include/*" "/usr/local/*/src/*" "$PROJECT/src")
-;;
-;; This means that the corresponding file will be searched for first in
-;; the current directory, then in ../../src, then in one of the directories
-;; under ../include, and so on. The star is _not_ a general wildcard
-;; character: it just indicates that the subdirectories of this directory
-;; must each be searched in turn. Environment variables will be expanded in
-;; the ff-search-directories variable.
-;;
-;; If the point is on a #include line, the file to be #included is searched
-;; for in the same manner. This can be disabled with the ff-ignore-include
-;; variable, or by calling ff-get-other-file instead of ff-find-other-file.
-;;
-;; If the file was not found, ff-find-other-file will prompt you for where
-;; to create the new "corresponding file" (defaults to the current directory),
-;; unless the variable ff-always-try-to-create is set to nil.
-;;
-;; GIVEN AN ARGUMENT (with the ^U prefix), ff-find-other-file will get the
-;; other file in another (the other?) window (see find-file-other-window and
-;; switch-to-buffer-other-window). This can be set on a more permanent basis
-;; by setting ff-always-in-other-window to t in which case the ^U prefix will
-;; do the opposite of what was described above.
-;;
-;; THERE ARE FIVE AVAILABLE HOOKS, called in this order if non-nil:
-;;
-;; - ff-pre-find-hooks - called before the search for the other file starts
-;; - ff-not-found-hooks - called when the other file could not be found
-;; - ff-pre-load-hooks - called just before the other file is 'loaded'
-;; - ff-file-created-hooks - called when the other file is created
-;; - ff-post-load-hooks - called just after the other file is 'loaded'
-;;
-;; The *load-hooks allow you to place point where you want it in the other
-;; file.
-
-;;; Change Log:
-;;
-;; FEEDBACK:
-;; Please send me bug reports, bug fixes, and extensions, so that I can
-;; merge them into the master source.
-
-;; CREDITS:
-;; Many thanks go to TUSC Computer Systems Pty Ltd for providing an environ-
-;; ment that made the development of this package possible.
-;;
-;; Many thanks also go to all those who provided valuable feedback throughout
-;; the development of this package:
-;; Rolf Ebert in particular, Fritz Knabe, Heddy Boubaker, Sebastian Kremer,
-;; Vasco Lopes Paulo, Mark A. Plaksin, Robert Lang, Trevor West, Kevin
-;; Pereira, Benedict Lofstedt & Justin Vallon.
-
-;;; Code:
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; User definable variables:
-
-(defvar ff-pre-find-hooks nil
- "*List of functions to be called before the search for the file starts.")
-
-(defvar ff-pre-load-hooks nil
- "*List of functions to be called before the other file is loaded.")
-
-(defvar ff-post-load-hooks nil
- "*List of functions to be called after the other file is loaded.")
-
-(defvar ff-not-found-hooks nil
- "*List of functions to be called if the other file could not be found.")
-
-(defvar ff-file-created-hooks nil
- "*List of functions to be called if the other file needs to be created.")
-
-(defvar ff-case-fold-search nil
- "*Non-nil means ignore cases in matches (see `case-fold-search').
-If you have extensions in different cases, you will want this to be nil.")
-
-(defvar ff-always-in-other-window nil
- "*If non-nil, find the corresponding file in another window by default.
-To override this, give an argument to `ff-find-other-file'.")
-
-(defvar ff-ignore-include nil
- "*If non-nil, ignore `#include' lines.")
-
-(defvar ff-always-try-to-create t
- "*If non-nil, always attempt to create the other file if it was not found.")
-
-(defvar ff-quiet-mode nil
- "*If non-nil, trace which directories are being searched.")
-
-(defvar ff-special-constructs
- '(
- ;; C/C++ include, for NeXTSTEP too
- ("^\#\\s *\\(include\\|import\\)\\s +[<\"]\\(.*\\)[>\"]" .
- (lambda ()
- (setq fname (buffer-substring (match-beginning 2) (match-end 2)))))
-
- ;; Ada import
- ("^with[ \t]+\\([a-zA-Z0-9_\\.]+\\)" .
- (lambda ()
- (setq fname (buffer-substring (match-beginning 1) (match-end 1)))
- (require 'ada-mode)
- (setq fname (concat (ada-make-filename-from-adaname fname)
- ada-spec-suffix))))
- )
- "*A list of regular expressions specifying how to recognise special
-constructs such as include files etc, and an associated method for
-extracting the filename from that construct.")
-
-(defvar ff-other-file-alist 'cc-other-file-alist
- "*Alist of extensions to find given the current file's extension.
-
-This list should contain the most used extensions before the others,
-since the search algorithm searches sequentially through each
-directory specified in `ff-search-directories'. If a file is not found,
-a new one is created with the first matching extension (`.cc' yields `.hh').
-This alist should be set by the major mode.")
-
-(defvar ff-search-directories 'cc-search-directories
- "*List of directories to search for a specific file.
-
-Set by default to `cc-search-directories', expanded at run-time.
-
-This list is searched through with each extension specified in
-`ff-other-file-alist' that matches this file's extension. So the
-longer the list, the longer it'll take to realise that a file
-may not exist.
-
-A typical format is
-
- '(\".\" \"/usr/include\" \"$PROJECT/*/include\")
-
-Environment variables can be inserted between slashes (`/').
-They will be replaced by their definition. If a variable does
-not exist, it is replaced (silently) with an empty string.
-
-The stars are *not* wildcards: they are searched for together with
-the preceding slash. The star represents all the subdirectories except
-`..', and each of these subdirectories will be searched in turn.")
-
-(defvar cc-search-directories
- '("." "/usr/include" "/usr/local/include/*")
- "*See the description of the `ff-search-directories' variable.")
-
-(defvar cc-other-file-alist
- '(
- ("\\.cc$" (".hh" ".h"))
- ("\\.hh$" (".cc" ".C"))
-
- ("\\.c$" (".h"))
- ("\\.h$" (".c" ".cc" ".C" ".CC" ".cxx" ".cpp"))
-
- ("\\.C$" (".H" ".hh" ".h"))
- ("\\.H$" (".C" ".CC"))
-
- ("\\.CC$" (".HH" ".H" ".hh" ".h"))
- ("\\.HH$" (".CC"))
-
- ("\\.cxx$" (".hh" ".h"))
- ("\\.cpp$" (".hh" ".h"))
- )
- "*Alist of extensions to find given the current file's extension.
-
-This list should contain the most used extensions before the others,
-since the search algorithm searches sequentially through each directory
-specified in `ff-search-directories'. If a file is not found, a new one
-is created with the first matching extension (`.cc' yields `.hh').")
-
-(defvar ada-search-directories
- '("." "/usr/adainclude" "/usr/local/adainclude")
- "*See the description for the `ff-search-directories' variable.")
-
-(defvar ada-other-file-alist
- '(
- ("\\.ads$" (".adb")) ;; Ada specs and bodies
- ("\\.adb$" (".ads")) ;; GNAT filename conventions
- )
- "*Alist of extensions to find given the current file's extension.
-
-This list should contain the most used extensions before the others,
-since the search algorithm searches sequentially through each directory
-specified in `ada-search-directories'. If a file is not found, a new one
-is created with the first matching extension (`.adb' yields `.ads').
-")
-
-(defvar modula2-other-file-alist
- '(
- ("\\.mi$" (".md")) ;; Modula-2 module definition
- ("\\.md$" (".mi")) ;; and implementation.
- )
- "*See the description for the `ff-search-directories' variable.")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; No user definable variables beyond this point!
-;; ==============================================
-
-(make-variable-buffer-local 'ff-pre-find-hooks)
-(make-variable-buffer-local 'ff-pre-load-hooks)
-(make-variable-buffer-local 'ff-post-load-hooks)
-(make-variable-buffer-local 'ff-not-found-hooks)
-(make-variable-buffer-local 'ff-file-created-hooks)
-(make-variable-buffer-local 'ff-case-fold-search)
-(make-variable-buffer-local 'ff-always-in-other-window)
-(make-variable-buffer-local 'ff-ignore-include)
-(make-variable-buffer-local 'ff-quiet-mode)
-(make-variable-buffer-local 'ff-other-file-alist)
-(make-variable-buffer-local 'ff-search-directories)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; User entry points
-
-;;;###autoload
-(defun ff-get-other-file (&optional in-other-window)
- "Find the header or source file corresponding to this file.
-See also the documentation for `ff-find-other-file;.
-
-If optional IN-OTHER-WINDOW is non-nil, find the file in another window."
- (interactive "P")
- (let ((ignore ff-ignore-include))
- (setq ff-ignore-include t)
- (ff-find-the-other-file in-other-window)
- (setq ff-ignore-include ignore)))
-
-;;;###autoload
-(defun ff-find-other-file (&optional in-other-window ignore-include)
- "Find the header or source file corresponding to this file.
-Being on a `#include' line pulls in that file.
-
-If optional IN-OTHER-WINDOW is non-nil, find the file in the other window.
-If optional IGNORE-INCLUDE is non-nil, ignore being on `#include' lines.
-
-Variables of interest include:
-
- - ff-case-fold-search
- Non-nil means ignore cases in matches (see case-fold-search).
- If you have extensions in different cases, you will want this to be nil.
-
- - ff-always-in-other-window
- If non-nil, always open the other file in another window, unless an
- argument is given to ff-find-other-file.
-
- - ff-ignore-include
- If non-nil, ignores #include lines.
-
- - ff-always-try-to-create
- If non-nil, always attempt to create the other file if it was not found.
-
- - ff-quiet-mode
- If non-nil, traces which directories are being searched.
-
- - ff-special-constructs
- A list of regular expressions specifying how to recognise special
- constructs such as include files etc, and an associated method for
- extracting the filename from that construct.
-
- - ff-other-file-alist
- Alist of extensions to find given the current file's extension.
-
- - ff-search-directories
- List of directories searched through with each extension specified in
- ff-other-file-alist that matches this file's extension.
-
- - ff-pre-find-hooks
- List of functions to be called before the search for the file starts.
-
- - ff-pre-load-hooks
- List of functions to be called before the other file is loaded.
-
- - ff-post-load-hooks
- List of functions to be called after the other file is loaded.
-
- - ff-not-found-hooks
- List of functions to be called if the other file could not be found.
-
- - ff-file-created-hooks
- List of functions to be called if the other file has been created."
- (interactive "P")
- (let ((ignore ff-ignore-include))
- (setq ff-ignore-include ignore-include)
- (ff-find-the-other-file in-other-window)
- (setq ff-ignore-include ignore)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Support functions
-
-(defun ff-emacs-19 ()
- (string-match "^19\\.[0-9]+\\.[0-9]+$" emacs-version))
-
-(defun ff-xemacs ()
- (or (string-match "Lucid" emacs-version)
- (string-match "XEmacs" emacs-version)))
-
-(defun ff-find-the-other-file (&optional in-other-window)
- "Find the header or source file corresponding to the current file.
-Being on a `#include' line pulls in that file, but see the help on
-the `ff-ignore-include' variable.
-
-If optional IN-OTHER-WINDOW is non-nil, find the file in another window."
-
- (let (match ;; matching regexp for this file
- suffixes ;; set of replacing regexps for the matching regexp
- action ;; function to generate the names of the other files
- fname ;; basename of this file
- pos ;; where we start matching filenames
- stub ;; name of the file without extension
- alist ;; working copy of the list of file extensions
- pathname ;; the pathname of the file or the #include line
- default-name ;; file we should create if none found
- format ;; what we have to match
- found ;; name of the file or buffer found - nil if none
- dirs ;; local value of ff-search-directories
- no-match) ;; whether we know about this kind of file
-
- (if ff-pre-find-hooks
- (run-hooks 'ff-pre-find-hooks))
-
- (message "Working...")
-
- (setq dirs
- (if (symbolp ff-search-directories)
- (ff-list-replace-env-vars (symbol-value ff-search-directories))
- (ff-list-replace-env-vars ff-search-directories)))
-
- (save-excursion
- (beginning-of-line 1)
- (setq fname (ff-treat-as-special)))
-
- (cond
- ((and (not ff-ignore-include) fname)
- (setq default-name fname)
- (setq found (ff-get-file dirs fname nil in-other-window)))
-
- ;; let's just get the corresponding file
- (t
- (setq alist (if (symbolp ff-other-file-alist)
- (symbol-value ff-other-file-alist)
- ff-other-file-alist)
- pathname (if (buffer-file-name)
- (buffer-file-name)
- "/none.none"))
-
- (string-match ".*/\\(.+\\)$" pathname)
- (setq fname (substring pathname (match-beginning 1) (match-end 1))
- no-match nil
- match (car alist))
-
- ;; find the table entry corresponding to this file
- (setq pos (ff-string-match (car match) fname))
- (while (and match (if (and pos (>= pos 0)) nil (not pos)))
- (setq alist (cdr alist))
- (setq match (car alist))
- (setq pos (ff-string-match (car match) fname)))
-
- ;; no point going on if we haven't found anything
- (if (not match)
- (setq no-match t)
-
- ;; otherwise, suffixes contains what we need
- (setq suffixes (car (cdr match))
- action (car (cdr match))
- found nil)
-
- ;; if we have a function to generate new names,
- ;; invoke it with the name of the current file
- (if (and (atom action) (fboundp action))
- (progn
- (setq suffixes (funcall action (buffer-file-name))
- match (cons (car match) (list suffixes))
- stub nil
- default-name (car suffixes)))
-
- ;; otherwise build our filename stub
- (cond
-
- ;; get around the problem that 0 and nil both mean false!
- ((= pos 0)
- (setq format "")
- (setq stub "")
- )
-
- (t
- (setq format (concat "\\(.+\\)" (car match)))
- (string-match format fname)
- (setq stub (substring fname (match-beginning 1) (match-end 1)))
- ))
-
- ;; if we find nothing, we should try to get a file like this one
- (setq default-name
- (concat stub (car (car (cdr match))))))
-
- ;; do the real work - find the file
- (setq found
- (ff-get-file dirs
- stub
- suffixes
- in-other-window)))))
-
- (cond
- (no-match ;; could not even determine the other file
- (message ""))
-
- (t
- (cond
-
- ((not found) ;; could not find the other file
-
- (if ff-not-found-hooks ;; run the hooks
- (run-hooks 'ff-not-found-hooks))
-
- (cond
- (ff-always-try-to-create ;; try to create the file
- (let (name pathname)
-
- (setq name
- (expand-file-name
- (read-file-name
- (format "Find or create %s in: " default-name)
- default-directory default-name nil)))
-
- (setq pathname
- (if (file-directory-p name)
- (concat (file-name-as-directory name) default-name)
- (setq found name)))
-
- (ff-find-file pathname in-other-window t)))
-
- (t ;; don't create the file, just whinge
- (message "no file found for %s" fname))))
-
- (t ;; matching file found
- nil))))
-
- found)) ;; return buffer-name or filename
-
-(defun ff-get-file (search-dirs fname-stub &optional suffix-list other-window)
- "Find a file in the SEARCH-DIRS with the given FILENAME (or filename stub).
-If (optional) SUFFIXES is nil, search for fname, otherwise search for fname
-with each of the given suffixes. Gets the file or the buffer corresponding
-to the name of the first file found, or nil.
-
-Arguments: (search-dirs fname-stub &optional suffix-list in-other-window)
-"
- (let ((filename (ff-get-file-name search-dirs fname-stub suffix-list)))
-
- (cond
- ((not filename)
- nil)
-
- ((bufferp (get-file-buffer filename))
- (ff-switch-to-buffer (get-file-buffer filename) other-window)
- filename)
-
- ((file-exists-p filename)
- (ff-find-file filename other-window nil)
- filename)
-
- (t
- nil))))
-
-(defun ff-get-file-name (search-dirs fname-stub &optional suffix-list)
- "Find a file in the SEARCH-DIRS with the given FILENAME (or filename stub).
-If (optional) SUFFIXES is nil, search for fname, otherwise search for fname
-with each of the given suffixes. Returns the name of the first file found.
-
-Arguments: (search-dirs fname-stub &optional suffix-list)
-"
- (let* (dirs ;; working copy of dirs to search
- dir ;; the current dir considered
- file ;; filename being looked for
- rest ;; pathname after first /*
- this-suffix ;; the suffix we are currently considering
- suffixes ;; working copy of suffix-list
- filename ;; built filename
- blist ;; list of live buffers
- buf ;; current buffer in blist
- found) ;; whether we have found anything
-
- (setq suffixes suffix-list)
-
- ;; suffixes is nil => fname-stub is the file we are looking for
- ;; otherwise fname-stub is a stub, and we append a suffix
- (if suffixes
- (setq this-suffix (car suffixes))
- (setq this-suffix "")
- (setq suffixes (list "")))
-
- ;; find whether the file is in a buffer first
- (while (and suffixes (not found))
- (setq filename (concat fname-stub this-suffix))
-
- (if (not ff-quiet-mode)
- (message "finding buffer %s..." filename))
-
- (if (bufferp (get-buffer filename))
- (setq found (buffer-file-name (get-buffer filename))))
-
- (setq blist (buffer-list))
- (setq buf (buffer-name (car blist)))
- (while (and blist (not found))
-
- (if (string-match (concat filename "<[0-9]+>") buf)
- (setq found (buffer-file-name (car blist))))
-
- (setq blist (cdr blist))
- (setq buf (buffer-name (car blist))))
-
- (setq suffixes (cdr suffixes))
- (setq this-suffix (car suffixes)))
-
- ;; now look for the real file
- (setq dirs search-dirs)
- (setq dir (car dirs))
- (while (and (not found) dirs)
-
- (setq suffixes suffix-list)
-
- ;; if dir does not contain '/*', look for the file
- (if (and dir (not (string-match "\\([^*]*\\)/\\\*\\(/.*\\)*" dir)))
- (progn
-
- ;; suffixes is nil => fname-stub is the file we are looking for
- ;; otherwise fname-stub is a stub, and we append a suffix
- (if suffixes
- (setq this-suffix (car suffixes))
- (setq this-suffix "")
- (setq suffixes (list "")))
-
- (while (and suffixes (not found))
-
- (setq filename (concat fname-stub this-suffix))
- (setq file (concat dir "/" filename))
-
- (if (not ff-quiet-mode)
- (message "finding %s..." file))
-
- (if (file-exists-p file)
- (setq found file))
-
- (setq suffixes (cdr suffixes))
- (setq this-suffix (car suffixes))))
-
- ;; otherwise dir matches the '/*', so search each dir separately
- (progn
- (if (match-beginning 2)
- (setq rest (substring dir (match-beginning 2) (match-end 2)))
- (setq rest "")
- )
- (setq dir (substring dir (match-beginning 1) (match-end 1)))
-
- (let ((dirlist (ff-all-dirs-under dir '("..")))
- this-dir compl-dirs)
-
- (setq this-dir (car dirlist))
- (while dirlist
- (setq compl-dirs
- (append
- compl-dirs
- (list (concat this-dir rest))
- ))
- (setq dirlist (cdr dirlist))
- (setq this-dir (car dirlist)))
-
- (if compl-dirs
- (setq found (ff-get-file-name compl-dirs
- fname-stub
- suffix-list))))))
- (setq dirs (cdr dirs))
- (setq dir (car dirs)))
-
- (if found
- (message "%s found" found))
-
- found))
-
-(defun ff-string-match (regexp string &optional start)
- "Like `string-match', but set `case-fold-search' temporarily.
-The value used comes from `ff-case-fold-search'."
- (let ((case-fold-search ff-case-fold-search))
- (if regexp
- (string-match regexp string start))))
-
-(defun ff-list-replace-env-vars (search-list)
- "Replace environment variables (of the form $VARIABLE) in SEARCH-LIST."
- (let (list
- (var (car search-list)))
- (while search-list
- (if (string-match "\\(.*\\)\\$[({]*\\([a-zA-Z0-9_]+\\)[)}]*\\(.*\\)" var)
- (setq var
- (concat
- (substring var (match-beginning 1) (match-end 1))
- (getenv (substring var (match-beginning 2) (match-end 2)))
- (substring var (match-beginning 3) (match-end 3)))))
- (setq search-list (cdr search-list))
- (setq list (cons var list))
- (setq var (car search-list)))
- (setq search-list (reverse list))))
-
-(defun ff-treat-as-special ()
- "Returns the file to look for if the construct was special, else nil.
-The construct is defined in the variable `ff-special-constructs'."
- (let* (fname
- (list ff-special-constructs)
- (elem (car list))
- (regexp (car elem))
- (match (cdr elem)))
- (while (and list (not fname))
- (if (and (looking-at regexp) match)
- (setq fname (funcall match)))
- (setq list (cdr list))
- (setq elem (car list))
- (setq regexp (car elem))
- (setq match (cdr elem)))
- fname))
-
-(defun ff-basename (string)
- "Return the basename of PATHNAME."
- (setq string (concat "/" string))
- (string-match ".*/\\([^/]+\\)$" string)
- (setq string (substring string (match-beginning 1) (match-end 1))))
-
-(defun ff-all-dirs-under (here &optional exclude)
- "Get all the directory files under directory HERE.
-Exclude all files in the optional EXCLUDE list."
- (if (file-directory-p here)
- (condition-case nil
- (progn
- (let ((files (directory-files here t))
- (dirlist (list))
- file)
- (while files
- (setq file (car files))
- (if (and
- (file-directory-p file)
- (not (member (ff-basename file) exclude)))
- (setq dirlist (cons file dirlist)))
- (setq files (cdr files)))
- (setq dirlist (reverse dirlist))))
- (error nil))
- nil))
-
-(defun ff-switch-file (f1 f2 file &optional in-other-window new-file)
- "Call F1 or F2 on FILE, according to IN-OTHER-WINDOW.
-In addition, this runs various hooks.
-
-Either F1 or F2 receives FILE as the sole argument.
-The decision of which one to call is based on IN-OTHER-WINDOW
-and on the global variable `ff-always-in-other-window'.
-
-F1 and F2 are typically `find-file' / `find-file-other-window'
-or `switch-to-buffer' / `switch-to-buffer-other-window' function pairs.
-
-If optional NEW-FILE is t, then a special hook (`ff-file-created-hooks') is
-called before `ff-post-load-hooks'."
- (if ff-pre-load-hooks
- (run-hooks 'ff-pre-load-hooks))
- (if (or
- (and in-other-window (not ff-always-in-other-window))
- (and (not in-other-window) ff-always-in-other-window))
- (funcall f2 file)
- (funcall f1 file))
- (if new-file
- (if ff-file-created-hooks
- (run-hooks 'ff-file-created-hooks)))
- (if ff-post-load-hooks
- (run-hooks 'ff-post-load-hooks)))
-
-(defun ff-find-file (file &optional in-other-window new-file)
- "Like `find-file', but may show the file in another window."
- (ff-switch-file 'find-file
- 'find-file-other-window
- file in-other-window new-file))
-
-(defun ff-switch-to-buffer (buffer-or-name &optional in-other-window)
- "Like `switch-to-buffer', but may show the buffer in another window."
-
- (ff-switch-file 'switch-to-buffer
- 'switch-to-buffer-other-window
- buffer-or-name in-other-window nil))
-
-(cond
- ((ff-emacs-19)
- (defun ff-goto-click (event)
- (set-buffer (window-buffer (posn-window (event-end event))))
- (goto-char (posn-point (event-end event))))
-
- ;;;###autoload
- (defun ff-mouse-find-other-file (event)
- "Visit the file you click on."
- (interactive "e")
- (save-excursion
- (ff-goto-click event)
- (ff-find-other-file nil)))
-
- ;;;###autoload
- (defun ff-mouse-find-other-file-other-window (event)
- "Visit the file you click on."
- (interactive "e")
- (save-excursion
- (ff-goto-click event)
- (ff-find-other-file t)))
-
- ;;;###autoload
- (defun locate-file (fname dirs &optional suffix-list ignore-perms)
- "Defines XEmacs look-alike locate-file for GNU Emacs-19."
- (interactive)
- (ff-get-file dirs fname suffix-list))
- )
-
- ((ff-xemacs)
-
- ;;;###autoload
- (defun ff-mouse-find-other-file (event)
- "Visit the file you click on."
- (interactive "@e")
- (save-excursion
- (mouse-set-point event)
- (ff-find-other-file nil)))
-
- ;;;###autoload
- (defun ff-mouse-find-other-file-other-window (event)
- "Visit the file you click on."
- (interactive "@e")
- (save-excursion
- (mouse-set-point event)
- (ff-find-other-file t)))
- ))
-
-(provide 'find-file)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; This section offers an example of user defined function to select files
-
-(defun ff-upcase-p (string &optional start end)
- "Return t if this string is all uppercase.
-Given START and/or END, checks between these characters."
- (let (match str)
- (if (not start)
- (setq start 0))
- (if (not end)
- (setq end (length string)))
- (if (= start end)
- (setq end (1+ end)))
- (setq str (substring string start end))
- (if (and
- (ff-string-match "[A-Z]+" str)
- (setq match (match-data))
- (= (car match) 0)
- (= (car (cdr match)) (length str)))
- t
- nil)))
-
-(defun ff-cc-hh-converter (arg)
- "Discriminate file extensions.
-Build up a new file list based possibly on part of the directory name
-and the name of the file passed in."
- (ff-string-match "\\(.*\\)/\\([^/]+\\)/\\([^.]+\\).\\([^/]+\\)$" arg)
- (let ((path (if (match-beginning 1)
- (substring arg (match-beginning 1) (match-end 1)) nil))
- (dire (if (match-beginning 2)
- (substring arg (match-beginning 2) (match-end 2)) nil))
- (file (if (match-beginning 3)
- (substring arg (match-beginning 3) (match-end 3)) nil))
- (extn (if (match-beginning 4)
- (substring arg (match-beginning 4) (match-end 4)) nil))
- return-list)
- (cond
- ;; fooZapJunk.cc => ZapJunk.{hh,h} or fooZapJunk.{hh,h}
- ((and (string= extn "cc")
- (ff-string-match "^\\([a-z]+\\)\\([A-Z].+\\)$" file))
- (let ((stub (substring file (match-beginning 2) (match-end 2))))
- (setq dire (upcase (substring file (match-beginning 1) (match-end 1))))
- (setq return-list (list (concat stub ".hh")
- (concat stub ".h")
- (concat file ".hh")
- (concat file ".h")))
- ))
- ;; FOO/ZapJunk.hh => fooZapJunk.{cc,C} or ZapJunk.{cc,C}
- ((and (string= extn "hh") (ff-upcase-p dire) file)
- (let ((stub (concat (downcase dire) file)))
- (setq return-list (list (concat stub ".cc")
- (concat stub ".C")
- (concat file ".cc")
- (concat file ".C")))
- ))
- ;; zap.cc => zap.hh or zap.h
- ((string= extn "cc")
- (let ((stub file))
- (setq return-list (list (concat stub ".hh")
- (concat stub ".h")))
- ))
- ;; zap.hh => zap.cc or zap.C
- ((string= extn "hh")
- (let ((stub file))
- (setq return-list (list (concat stub ".cc")
- (concat stub ".C")))
- ))
- (t
- nil))
-
- return-list))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; This section offers an example of user defined function to place point.
-;; The regexps are Ada specific.
-
-(defvar ff-function-name nil "Name of the function we are in.")
-
-(defvar ada-procedure-start-regexp)
-(defvar ada-package-start-regexp)
-
-;; bind with (setq ff-pre-load-hooks 'ff-which-function-are-we-in)
-;;
-(defun ff-which-function-are-we-in ()
- "Return the name of the function whose definition/declaration point is in.
-Also remember that name in `ff-function-name'."
-
- (setq ff-function-name nil)
-
- (save-excursion
- (if (re-search-backward ada-procedure-start-regexp nil t)
- (setq ff-function-name (buffer-substring (match-beginning 0)
- (match-end 0)))
- ; we didn't find a procedure start, perhaps there is a package
- (if (re-search-backward ada-package-start-regexp nil t)
- (setq ff-function-name (buffer-substring (match-beginning 0)
- (match-end 0)))
- ))))
-
-;; bind with (setq ff-post-load-hooks 'ff-set-point-accordingly)
-;;
-(defun ff-set-point-accordingly ()
- "Find the function specified in `ff-function-name'.
-That name was previously determined by `ff-which-function-are-we-in'."
- (if ff-function-name
- (progn
- (goto-char (point-min))
- (search-forward ff-function-name nil t))))
-
-;; find-file.el ends here
-
diff --git a/lisp/find-gc.el b/lisp/find-gc.el
deleted file mode 100644
index 4bce53c9184..00000000000
--- a/lisp/find-gc.el
+++ /dev/null
@@ -1,152 +0,0 @@
-;;; find-gc.el --- detect functions that call the garbage collector
-
-;; Copyright (C) 1992 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; 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.
-
-;;; Code:
-
-(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))))
-)
-
-;;; find-gc.el ends here
diff --git a/lisp/finder.el b/lisp/finder.el
deleted file mode 100644
index 3d93cba79d5..00000000000
--- a/lisp/finder.el
+++ /dev/null
@@ -1,299 +0,0 @@
-;;; finder.el --- topic & keyword-based code finder
-
-;; Copyright (C) 1992 Free Software Foundation, Inc.
-
-;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
-;; Created: 16 Jun 1992
-;; Version: 1.0
-;; Keywords: help
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This mode uses the Keywords library header to provide code-finding
-;; services by keyword.
-;;
-;; Things to do:
-;; 1. Support multiple keywords per search. This could be extremely hairy;
-;; there doesn't seem to be any way to get completing-read to exit on
-;; an EOL with no substring pending, which is what we'd want to end the loop.
-;; 2. Search by string in synopsis line?
-;; 3. Function to check finder-package-info for unknown keywords.
-
-;;; Code:
-
-(require 'lisp-mnt)
-(require 'finder-inf)
-
-;; Local variable in finder buffer.
-(defvar finder-headmark)
-
-(defvar finder-known-keywords
- '(
- (abbrev . "abbreviation handling, typing shortcuts, macros")
- (bib . "code related to the `bib' bibliography processor")
- (c . "support for the C language and related languages")
- (calendar . "calendar and time management support")
- (comm . "communications, networking, remote access to files")
- (data . "support editing files of data")
- (docs . "support for Emacs documentation")
- (emulations . "emulations of other editors")
- (extensions . "Emacs Lisp language extensions")
- (faces . "support for multiple fonts")
- (frames . "support for Emacs frames and window systems")
- (games . "games, jokes and amusements")
- (hardware . "support for interfacing with exotic hardware")
- (help . "support for on-line help systems")
- (hypermedia . "support for links between text or other media types")
- (i18n . "internationalization and alternate character-set support")
- (internal . "code for Emacs internals, build process, defaults")
- (languages . "specialized modes for editing programming languages")
- (lisp . "Lisp support, including Emacs Lisp")
- (local . "code local to your site")
- (maint . "maintenance aids for the Emacs development group")
- (mail . "modes for electronic-mail handling")
- (matching . "various sorts of searching and matching")
- (mouse . "mouse support")
- (news . "support for netnews reading and posting")
- (oop . "support for object-oriented programming")
- (outlines . "support for hierarchical outlining")
- (processes . "process, subshell, compilation, and job control support")
- (terminals . "support for terminal types")
- (tex . "code related to the TeX formatter")
- (tools . "programming tools")
- (unix . "front-ends/assistants for, or emulators of, UNIX features")
- (vms . "support code for vms")
- (wp . "word processing")
- ))
-
-(defvar finder-mode-map nil)
-(or finder-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map " " 'finder-select)
- (define-key map "f" 'finder-select)
- (define-key map "\C-m" 'finder-select)
- (define-key map "?" 'finder-summary)
- (define-key map "q" 'finder-exit)
- (define-key map "d" 'finder-list-keywords)
- (setq finder-mode-map map)))
-
-
-;;; Code for regenerating the keyword list.
-
-(defvar finder-package-info nil
- "Assoc list mapping file names to description & keyword lists.")
-
-(defun finder-compile-keywords (&rest dirs)
- "Regenerate the keywords association list into the file `finder-inf.el'.
-Optional arguments are a list of Emacs Lisp directories to compile from; no
-arguments compiles from `load-path'."
- (save-excursion
- (let ((processed nil))
- (find-file "finder-inf.el")
- (erase-buffer)
- (insert ";;; finder-inf.el --- keyword-to-package mapping\n")
- (insert ";; Keywords: help\n")
- (insert ";;; Commentary:\n")
- (insert ";; Don't edit this file. It's generated by finder.el\n\n")
- (insert ";;; Code:\n")
- (insert "\n(setq finder-package-info '(\n")
- (mapcar
- (lambda (d)
- (mapcar
- (lambda (f)
- (if (and (string-match "^[^=].*\\.el$" f)
- (not (member f processed)))
- (let (summary keystart keywords)
- (setq processed (cons f processed))
- (save-excursion
- (set-buffer (get-buffer-create "*finder-scratch*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert-file-contents
- (concat (file-name-as-directory (or d ".")) f))
- (setq summary (lm-synopsis))
- (setq keywords (lm-keywords)))
- (insert
- (format " (\"%s\"\n " f))
- (prin1 summary (current-buffer))
- (insert
- "\n ")
- (setq keystart (point))
- (insert
- (if keywords (format "(%s)" keywords) "nil")
- ")\n")
- (subst-char-in-region keystart (point) ?, ? )
- )))
- (directory-files (or d "."))))
- (or dirs load-path))
- (insert "))\n\n(provide 'finder-inf)\n\n;;; finder-inf.el ends here\n")
- (kill-buffer "*finder-scratch*")
- (eval-current-buffer) ;; So we get the new keyword list immediately
- (basic-save-buffer))))
-
-(defun finder-compile-keywords-make-dist ()
- "Regenerate `finder-inf.el' for the Emacs distribution."
- (finder-compile-keywords default-directory))
-
-;;; Now the retrieval code
-
-(defun finder-insert-at-column (column &rest strings)
- "Insert list of STRINGS, at column COLUMN."
- (if (> (current-column) column) (insert "\n"))
- (move-to-column column)
- (let ((col (current-column)))
- (if (< col column)
- (indent-to column)
- (if (and (/= col column)
- (= (preceding-char) ?\t))
- (let (indent-tabs-mode)
- (delete-char -1)
- (indent-to col)
- (move-to-column column)))))
- (apply 'insert strings))
-
-(defun finder-list-keywords ()
- "Display descriptions of the keywords in the Finder buffer."
- (interactive)
- (setq buffer-read-only nil)
- (erase-buffer)
- (mapcar
- (lambda (assoc)
- (let ((keyword (car assoc)))
- (insert (symbol-name keyword))
- (finder-insert-at-column 14 (concat (cdr assoc) "\n"))
- (cons (symbol-name keyword) keyword)))
- finder-known-keywords)
- (goto-char (point-min))
- (setq finder-headmark (point))
- (setq buffer-read-only t)
- (set-buffer-modified-p nil)
- (balance-windows)
- (finder-summary))
-
-(defun finder-list-matches (key)
- (setq buffer-read-only nil)
- (erase-buffer)
- (let ((id (intern key)))
- (insert
- "The following packages match the keyword `" key "':\n\n")
- (setq finder-headmark (point))
- (mapcar
- (lambda (x)
- (if (memq id (car (cdr (cdr x))))
- (progn
- (insert (car x))
- (finder-insert-at-column 16 (concat (car (cdr x)) "\n")))))
- finder-package-info)
- (goto-char (point-min))
- (forward-line)
- (setq buffer-read-only t)
- (set-buffer-modified-p nil)
- (shrink-window-if-larger-than-buffer)
- (finder-summary)))
-
-;; Search for a file named FILE the same way `load' would search.
-(defun finder-find-library (file)
- (if (file-name-absolute-p file)
- file
- (let ((dirs load-path)
- found)
- (while (and dirs (not found))
- (if (file-exists-p (expand-file-name (concat file ".el") (car dirs)))
- (setq found (expand-file-name file (car dirs)))
- (if (file-exists-p (expand-file-name file (car dirs)))
- (setq found (expand-file-name file (car dirs)))))
- (setq dirs (cdr dirs)))
- found)))
-
-(defun finder-commentary (file)
- (interactive)
- (let* ((str (lm-commentary (finder-find-library file))))
- (if (null str)
- (error "Can't find any Commentary section"))
- (pop-to-buffer "*Finder*")
- (setq buffer-read-only nil)
- (erase-buffer)
- (insert str)
- (goto-char (point-min))
- (delete-blank-lines)
- (goto-char (point-max))
- (delete-blank-lines)
- (goto-char (point-min))
- (while (re-search-forward "^;+ ?" nil t)
- (replace-match "" nil nil))
- (goto-char (point-min))
- (setq buffer-read-only t)
- (set-buffer-modified-p nil)
- (shrink-window-if-larger-than-buffer)
- (finder-summary)))
-
-(defun finder-current-item ()
- (if (and finder-headmark (< (point) finder-headmark))
- (error "No keyword or filename on this line")
- (save-excursion
- (beginning-of-line)
- (current-word))))
-
-(defun finder-select ()
- (interactive)
- (let ((key (finder-current-item)))
- (if (string-match "\\.el$" key)
- (finder-commentary key)
- (finder-list-matches key))))
-
-(defun finder-by-keyword ()
- "Find packages matching a given keyword."
- (interactive)
- (finder-mode)
- (finder-list-keywords))
-
-(defun finder-mode ()
- "Major mode for browsing package documentation.
-\\<finder-mode-map>
-\\[finder-select] more help for the item on the current line
-\\[finder-exit] exit Finder mode and kill the Finder buffer.
-"
- (interactive)
- (pop-to-buffer "*Finder*")
- (setq buffer-read-only nil)
- (erase-buffer)
- (use-local-map finder-mode-map)
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (setq mode-name "Finder")
- (setq major-mode 'finder-mode)
- (make-local-variable 'finder-headmark)
- (setq finder-headmark nil))
-
-(defun finder-summary ()
- "Summarize basic Finder commands."
- (interactive)
- (message "%s"
- (substitute-command-keys
- "\\<finder-mode-map>\\[finder-select] = select, \\[finder-list-keywords] = to finder directory, \\[finder-exit] = quit, \\[finder-summary] = help")))
-
-(defun finder-exit ()
- "Exit Finder mode and kill the buffer"
- (interactive)
- (delete-window)
- (kill-buffer "*Finder*"))
-
-(provide 'finder)
-
-;;; finder.el ends here
diff --git a/lisp/float-sup.el b/lisp/float-sup.el
deleted file mode 100644
index 5a93f5fec05..00000000000
--- a/lisp/float-sup.el
+++ /dev/null
@@ -1,60 +0,0 @@
-;;; float-sup.el --- detect absence of floating-point support in Emacs runtime
-
-;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;; 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.
-;; 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))
-
-(provide 'lisp-float-type)
-
-;;; float-sup.el ends here
diff --git a/lisp/flow-ctrl.el b/lisp/flow-ctrl.el
deleted file mode 100644
index f98ecaa0fb9..00000000000
--- a/lisp/flow-ctrl.el
+++ /dev/null
@@ -1,126 +0,0 @@
-;;; flow-ctrl.el --- help for lusers on cu(1) or ttys with wired-in ^S/^Q flow control
-
-;; Copyright (C) 1990, 1991, 1994 Free Software Foundation, Inc.
-
-;; Author Kevin Gallagher
-;; Maintainer: FSF
-;; Adapted-By: ESR
-;; Keywords: hardware
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Terminals that use XON/XOFF flow control can cause problems with
-;; GNU Emacs users. This file contains Emacs Lisp code that makes it
-;; easy for a user to deal with this problem, when using such a
-;; terminal.
-;;
-;; To invoke these adjustments, a user need only invoke the function
-;; enable-flow-control-on with a list of terminal types in his/her own
-;; .emacs file. As arguments, give it the names of one or more terminal
-;; types in use by that user which require flow control adjustments.
-;; Here's an example:
-;;
-;; (enable-flow-control-on "vt200" "vt300" "vt101" "vt131")
-
-;; Portability note: This uses (getenv "TERM"), and therefore probably
-;; won't work outside of UNIX-like environments.
-
-;;; Code:
-
-(defvar flow-control-c-s-replacement ?\034
- "Character that replaces C-s, when flow control handling is enabled.")
-(defvar flow-control-c-q-replacement ?\036
- "Character that replaces C-q, when flow control handling is enabled.")
-
-(put 'keyboard-translate-table 'char-table-extra-slots 0)
-
-;;;###autoload
-(defun enable-flow-control (&optional argument)
- "Toggle flow control handling.
-When handling is enabled, user can type C-s as C-\\, and C-q as C-^.
-With arg, enable flow control mode if arg is positive, otherwise disable."
- (interactive "P")
- (if (if argument
- ;; Argument means enable if arg is positive.
- (<= (prefix-numeric-value argument) 0)
- ;; No arg means toggle.
- (nth 1 (current-input-mode)))
- (progn
- ;; Turn flow control off, and stop exchanging chars.
- (set-input-mode t nil (nth 2 (current-input-mode)))
- (if keyboard-translate-table
- (progn
- (aset keyboard-translate-table flow-control-c-s-replacement nil)
- (aset keyboard-translate-table ?\^s nil)
- (aset keyboard-translate-table flow-control-c-q-replacement nil)
- (aset keyboard-translate-table ?\^q nil))))
- ;; Turn flow control on.
- ;; Tell emacs to pass C-s and C-q to OS.
- (set-input-mode nil t (nth 2 (current-input-mode)))
- ;; Initialize translate table, saving previous mappings, if any.
- (cond ((null keyboard-translate-table)
- (setq keyboard-translate-table
- (make-char-table 'keyboard-translate-table nil)))
- ((char-table-p keyboard-translate-table)
- (setq keyboard-translate-table
- (copy-sequence keyboard-translate-table)))
- (t
- (let ((the-table (make-char-table 'keyboard-translate-table nil)))
- (let ((i 0)
- (j (length keyboard-translate-table)))
- (while (< i j)
- (aset the-table i (elt keyboard-translate-table i))
- (setq i (1+ i))))
- (setq keyboard-translate-table the-table))))
- ;; Swap C-s and C-\
- (aset keyboard-translate-table flow-control-c-s-replacement ?\^s)
- (aset keyboard-translate-table ?\^s flow-control-c-s-replacement)
- ;; Swap C-q and C-^
- (aset keyboard-translate-table flow-control-c-q-replacement ?\^q)
- (aset keyboard-translate-table ?\^q flow-control-c-q-replacement)
- (message "XON/XOFF adjustment for %s: use %s for C-s, and use %s for C-q"
- (getenv "TERM")
- (single-key-description flow-control-c-s-replacement)
- (single-key-description flow-control-c-q-replacement))
- (sleep-for 2))) ; Give user a chance to see message.
-
-;;;###autoload
-(defun enable-flow-control-on (&rest losing-terminal-types)
- "Enable flow control if using one of a specified set of terminal types.
-Use `(enable-flow-control-on \"vt100\" \"h19\")' to enable flow control
-on VT-100 and H19 terminals. 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."
- (let ((term (getenv "TERM"))
- hyphend)
- ;; Look for TERM in LOSING-TERMINAL-TYPES.
- ;; If we don't find it literally, try stripping off words
- ;; from the end, one by one.
- (while (and term (not (member term losing-terminal-types)))
- ;; 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)))
- (if term
- (enable-flow-control))))
-
-(provide 'flow-ctrl)
-
-;;; flow-ctrl.el ends here
diff --git a/lisp/foldout.el b/lisp/foldout.el
deleted file mode 100644
index ad9bfe2c2ec..00000000000
--- a/lisp/foldout.el
+++ /dev/null
@@ -1,570 +0,0 @@
-;;; foldout.el --- Folding extensions for outline-mode and outline-minor-mode.
-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-
-;; Author: Kevin Broadey <KevinB@bartley.demon.co.uk>
-;; Created: 27 Jan 1994
-;; Version: foldout.el 1.10 dated 94/05/19 at 17:09:12
-;; Keywords: folding, outline
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This file provides folding editor extensions for outline-mode and
-;; outline-minor-mode buffers. What's a "folding editor"? Read on...
-;;
-;; Imagine you're in an outline-mode buffer and you've hidden all the text and
-;; subheadings under your level-1 headings. You now want to look at the stuff
-;; hidden under one of these headings. Normally you'd do C-c C-e (show-entry)
-;; to expose the body or C-c C-i to expose the child (level-2) headings.
-;;
-;; With foldout, you do C-c C-z (foldout-zoom-subtree). This exposes the body
-;; and child subheadings and narrows the buffer so that only the level-1
-;; heading, the body and the level-2 headings are visible. If you now want to
-;; look under one of the level-2 headings, position the cursor on it and do C-c
-;; C-z again. This exposes the level-2 body and its level-3 child subheadings
-;; and narrows the buffer again. You can keep on zooming in on successive
-;; subheadings as much as you like. A string in the modeline tells you how
-;; deep you've gone.
-;;
-;; When zooming in on a heading you might only want to see the child
-;; subheadings. You do this by specifying a numeric argument: C-u C-c C-z.
-;; You can specify the number of levels of children too (c.f. show-children):
-;; e.g. M-2 C-c C-z exposes two levels of child subheadings. Alternatively,
-;; you might only be interested in the body. You do this by specifying a
-;; negative argument: M-- C-c C-z. You can also cause the whole subtree to be
-;; expanded, similar to C-c C-s (show-subtree), by specifying a zero argument:
-;; M-0 C-c C-z.
-;;
-;; While you're zoomed in you can still use outline-mode's exposure and hiding
-;; functions. It won't upset foldout at all. Also, since the buffer is
-;; narrowed, "global" editing actions will only affect the stuff under the
-;; zoomed-in heading. This is useful for restricting changes to a particular
-;; chapter or section of your document.
-;;
-;; You unzoom (exit) a fold by doing C-c C-x (foldout-exit-fold). This hides
-;; all the text and subheadings under the top-level heading and returns you to
-;; the previous view of the buffer. Specifying a numeric argument exits that
-;; many folds. Specifying a zero argument exits *all* folds.
-;;
-;; You might want to exit a fold *without* hiding the text and subheadings.
-;; You do this by specifying a negative argument. For example, M--2 C-c C-x
-;; exits two folds and leaves the text and subheadings exposed.
-;;
-;; Foldout also provides mouse bindings for entering and exiting folds and for
-;; showing and hiding text. Hold down Meta and Control, then click a mouse
-;; button as follows:-
-;;
-;; mouse-1 (foldout-mouse-zoom) zooms in on the heading clicked on:-
-;;
-;; single click expose body
-;; double click expose subheadings
-;; triple click expose body and subheadings
-;; quad click expose entire subtree
-;;
-;; mouse-2 (foldout-mouse-show) exposes text under the heading clicked on:-
-;;
-;; single click expose body
-;; double click expose subheadings
-;; triple click expose body and subheadings
-;; quad click expose entire subtree
-;;
-;; mouse-3 (foldout-mouse-hide-or-exit) hides text under the heading clicked
-;; on or exits the fold:-
-;;
-;; single click hide subtree
-;; double click exit fold and hide text
-;; triple click exit fold without hiding text
-;; quad click exit all folds and hide text
-;;
-;; You can change the modifier keys used by setting `foldout-mouse-modifiers'.
-
-;;; Installation:
-
-;; To use foldout, put this in your .emacs:-
-;;
-;; (require 'foldout)
-;;
-;; If you don't want it loaded until you need it, try this instead:-
-;;
-;; (eval-after-load "outline" '(require 'foldout))
-
-;;; Advertisements:
-
-;; Get out-xtra.el by Per Abrahamsen <abraham@iesd.auc.dk> for more
-;; outline-mode goodies. In particular, `outline-hide-sublevels' makes
-;; setup a lot easier.
-;;
-;; folding.el by Jamie Lokier <u90jl@ecs.ox.ac.uk> supports folding by
-;; recognising special marker text in you file.
-;;
-;; c-outline.el (by me) provides outline-mode support to recognise `C'
-;; statements as outline headings, so with foldout you can have a folding `C'
-;; code editor without having to put in start- and end-of-fold markers. This
-;; is a real winner!
-
-;;; ChangeLog:
-
-;; 1.10 21-Mar-94
-;; foldout.el is now part of the GNU Emacs distribution!!
-;; Put in changes made by RMS to version 1.8 to keep the diffs to a minimum.
-;; bugfix: numeric arg to foldout-exit-fold wasn't working - looks like I don't
-;; know how to use the Common LISP `loop' macro after all, so use `while'
-;; instead.
-
-;; 1.9 15-Mar-94
-;; Didn't test that very well, did I? The change to foldout-zoom-subtree
-;; affected foldout-mouse-zoom: if the heading under the `level n' one clicked
-;; on was at `level n+2' then it didn't get exposed. Sorry about that!
-
-;; 1.8 15-Mar-94
-;; Changed meaning of prefix arg to foldout-zoom-subtree. arg > 0 now means
-;; "expose that many children" instead of just "expose children" so it is more
-;; like `show-children' (C-c C-i). Arg of C-u on its own only shows one level
-;; of children, though, so you can still zoom by doing C-u C-c C-z.
-;;
-;; I can't think of a good meaning for the value of a negative prefix. Any
-;; suggestions?
-;;
-;; Added advertisement for my c-outline.el package. Now you can have a folding
-;; editor for c-mode without any effort!
-
-;; 1.7 7-Mar-94
-;; I got fed up trying to work out how many blank lines there were outside the
-;; narrowed region when inside a fold. Now *all* newlines before the following
-;; heading are *in* the narrowed region. Thus, if the cursor is at point-max,
-;; the number of blank lines above it is the number you'll get above the next
-;; heading.
-;;
-;; Since all newlines are now inside the narrowed region, when exiting a fold
-;; add a newline at the end of the region if there isn't one so that the
-;; following heading doesn't accidentally get joined to the body text.
-;;
-;; Bugfix: `foldout-mouse-modifiers' should be `defvar', not `defconst'.
-;;
-;; Use "cond" instead of "case" so that lemacs-19.9 users can use the mouse.
-;;
-;; Improve "Commentary" entry on using the mouse.
-;;
-;; Add "Installation" keyword.
-
-;; 1.6 3-Mar-94
-;; Add mouse support functions foldout-mouse-zoom, foldout-mouse-show,
-;; foldout-mouse-hide-or-exit.
-
-;; 1.5 11-Feb-94
-;; Rename `foldout-enter-subtree' to `foldout-zoom-subtree' and change
-;; keystroke from C-g to C-z. This is more mnemonic and leaves C-g alone, as
-;; users expect this to cancel the current key sequence.
-;;
-;; Added better commentary at the request of RMS. Added stuff to comply with
-;; the lisp-mnt.el conventions. Added instructions on how best to load the
-;; package.
-
-;; 1.4 2-Feb-94
-;; Bugfix: end-of-fold marking was wrong:-
-;;
-;; End of narrowed region should be one character on from
-;; (outline-end-of-subtree) so it includes the end-of-line at the end of the
-;; last line of the subtree.
-;;
-;; End-of-fold marker should be outside the narrowed region so text inserted
-;; at the end of the region goes before the marker. Need to make a special
-;; case for end-of-buffer because it is impossible to set a marker that will
-;; follow eob. Bummer.
-
-;; 1.3 28-Jan-94
-;; Changed `foldout-zoom-subtree'. A zero arg now makes it expose the entire
-;; subtree on entering the fold. As before, < 0 shows only the body and > 0
-;; shows only the subheadings.
-
-;; 1.2 28-Jan-94
-;; Fixed a dumb bug - didn't make `foldout-modeline-string' buffer-local :-(
-;;
-;; Changed `foldout-exit-fold' to use prefix arg to say how many folds to exit.
-;; Negative arg means exit but don't hide text. Zero arg means exit all folds.
-;;
-;; Added `foldout-inhibit-key-bindings' to inhibit key bindings.
-
-;; 1.1 27-Jan-94
-;; Released to the net. Inspired by a question in gnu.emacs.help from
-;; Jason D Lohn <jlohn@eng.umd.edu>.
-
-;;; Code:
-
-(require 'outline)
-
-;; something has gone very wrong if outline-minor-mode isn't bound now.
-(if (not (boundp 'outline-minor-mode))
- (error "Can't find outline-minor-mode"))
-
-(defconst foldout-fold-list nil
- "List of start and end markers for the folds currently entered.
-An end marker of NIL means the fold ends after (point-max).")
-(make-variable-buffer-local 'foldout-fold-list)
-
-(defconst foldout-modeline-string nil
- "Modeline string announcing that we are in an outline fold.")
-(make-variable-buffer-local 'foldout-modeline-string)
-
-;; put our minor mode string immediately following outline-minor-mode's
-(or (assq 'foldout-modeline-string minor-mode-alist)
- (let ((outl-entry (memq (assq 'outline-minor-mode minor-mode-alist)
- minor-mode-alist))
- (foldout-entry '((foldout-modeline-string foldout-modeline-string))))
-
- ;; something's wrong with outline if we can't find it
- (if (null outl-entry)
- (error "Can't find outline-minor-mode in minor-mode-alist"))
-
- ;; slip our fold announcement into the list
- (setcdr outl-entry (nconc foldout-entry (cdr outl-entry)))
- ))
-
-;; outline-flag-region has different `flag' values in outline.el and
-;; noutline.el for hiding and showing text.
-
-(defconst foldout-hide-flag
- (if (featurep 'noutline) t ?\^M))
-
-(defconst foldout-show-flag
- (if (featurep 'noutline) nil ?\n))
-
-
-(defun foldout-zoom-subtree (&optional exposure)
- "Open the subtree under the current heading and narrow to it.
-
-Normally the body and the immediate subheadings are exposed, but
-optional arg EXPOSURE \(interactively with prefix arg\) changes this:-
-
- EXPOSURE > 0 exposes n levels of subheadings (c.f. show-children)
- EXPOSURE < 0 exposes only the body
- EXPOSURE = 0 exposes the entire subtree"
- (interactive "P")
- (save-excursion
- (widen)
- (outline-back-to-heading)
- (let* ((exposure-value (prefix-numeric-value exposure))
- (start (point))
- (start-marker (point-marker))
- (end (progn (outline-end-of-subtree)
- (skip-chars-forward "\n\^M")
- (point)))
- ;; I need a marker that will follow the end of the region even when
- ;; text is inserted right at the end. Text gets inserted *after*
- ;; markers, so I need it at end+1. Unfortunately I can't set a
- ;; marker at (point-max)+1, so I use NIL to mean the region ends at
- ;; (point-max).
- (end-marker (if (eobp) nil (set-marker (make-marker) (1+ end))))
- )
-
- ;; narrow to this subtree
- (narrow-to-region start end)
-
- ;; show the body and/or subheadings for this heading
- (goto-char start)
- (cond
- ((null exposure)
- (show-entry)
- (show-children))
- ((< exposure-value 0)
- (show-entry))
- ((consp exposure)
- (show-children))
- ((> exposure-value 0)
- (show-children exposure-value))
- (t
- (show-subtree))
- )
-
- ;; save the location of the fold we are entering
- (setq foldout-fold-list (cons (cons start-marker end-marker)
- foldout-fold-list))
-
- ;; update the modeline
- (foldout-update-modeline)
- )))
-
-
-(defun foldout-exit-fold (&optional num-folds)
- "Return to the ARG'th enclosing fold view. With ARG = 0 exit all folds.
-
-Normally causes exited folds to be hidden, but with ARG < 0, -ARG folds are
-exited and text is left visible."
- (interactive "p")
- (let (start-marker end-marker (hide-fold t))
-
- ;; check there are some folds to leave
- (if (null foldout-fold-list)
- (error "Not in a fold!"))
-
- (cond
- ;; catch a request to leave all folds
- ((zerop num-folds)
- (setq num-folds (length foldout-fold-list)))
-
- ;; have we been told not to hide the fold?
- ((< num-folds 0)
- (setq hide-fold nil
- num-folds (- num-folds)))
- )
-
- ;; limit the number of folds if we've been told to exit too many
- (setq num-folds (min num-folds (length foldout-fold-list)))
-
- ;; exit the folds
- (widen)
- (while (not (zerop num-folds))
- ;; get the fold at the top of the stack
- (setq start-marker (car (car foldout-fold-list))
- end-marker (cdr (car foldout-fold-list))
- foldout-fold-list (cdr foldout-fold-list)
- num-folds (1- num-folds))
-
- ;; Make sure there is a newline at the end of this fold,
- ;; otherwise the following heading will get joined to the body
- ;; text.
- (if end-marker
- (progn
- (goto-char end-marker)
- (forward-char -1)
- (or (memq (preceding-char) '(?\n ?\^M))
- (insert ?\n))))
-
- ;; If this is the last fold to exit, hide the text unless we've
- ;; been told not to. Note that at the moment point is at the
- ;; beginning of the following heading if there is one.
-
- ;; Also, make sure that the newline before the following heading
- ;; is \n otherwise it will be hidden. If there is a newline
- ;; before this one, make it visible too so we do the same as
- ;; outline.el and leave a blank line before the heading.
- (if (zerop num-folds)
- (let ((beginning-of-heading (point))
- (end-of-subtree (if end-marker
- (progn
- (forward-char -1)
- (if (memq (preceding-char)
- '(?\n ?\^M))
- (forward-char -1))
- (point))
- (point-max))))
- ;; hide the subtree
- (if hide-fold
- (outline-flag-region start-marker end-of-subtree
- foldout-hide-flag))
-
- ;; make sure the next heading is exposed
- (if end-marker
- (outline-flag-region end-of-subtree beginning-of-heading
- foldout-show-flag))
- ))
-
- ;; zap the markers so they don't slow down editing
- (set-marker start-marker nil)
- (if end-marker (set-marker end-marker nil))
- )
-
- ;; narrow to the enclosing fold if there is one
- (if foldout-fold-list
- (progn
- (setq start-marker (car (car foldout-fold-list))
- end-marker (cdr (car foldout-fold-list)))
- (narrow-to-region start-marker
- (if end-marker
- (1- (marker-position end-marker))
- (point-max)))
- ))
- (recenter)
-
- ;; update the modeline
- (foldout-update-modeline)
- ))
-
-
-(defun foldout-update-modeline ()
- "Set the modeline string to indicate our fold depth."
- (let ((depth (length foldout-fold-list)))
- (setq foldout-modeline-string
- (cond
- ;; if we're not in a fold, keep quiet
- ((zerop depth)
- nil)
- ;; in outline-minor-mode we're after "Outl:xx" in the modeline
- (outline-minor-mode
- (format ":%d" depth))
- ;; otherwise just announce the depth (I guess we're in outline-mode)
- ((= depth 1)
- " Inside 1 fold")
- (t
- (format " Inside %d folds" depth))
- ))))
-
-
-(defun foldout-mouse-zoom (event)
- "Zoom in on the heading clicked on.
-
-How much is exposed by the zoom depends on the number of mouse clicks:-
-
- 1 expose body
- 2 expose subheadings
- 3 expose body and subheadings
- 4 expose entire subtree"
- (interactive "@e")
-
- ;; swallow intervening mouse events so we only get the final click-count.
- (setq event (foldout-mouse-swallow-events event))
-
- ;; go to the heading clicked on
- (foldout-mouse-goto-heading event)
-
- ;; zoom away
- (foldout-zoom-subtree
- (let ((nclicks (event-click-count event)))
- (cond
- ((= nclicks 1) -1) ; body only
- ((= nclicks 2) '(1)) ; subheadings only
- ((= nclicks 3) nil) ; body and subheadings
- (t 0))))) ; entire subtree
-
-(defun foldout-mouse-show (event)
- "Show what is hidden under the heading clicked on.
-
-What gets exposed depends on the number of mouse clicks:-
-
- 1 expose body
- 2 expose subheadings
- 3 expose body and subheadings
- 4 expose entire subtree"
- (interactive "@e")
-
- ;; swallow intervening mouse events so we only get the final click-count.
- (setq event (foldout-mouse-swallow-events event))
-
- ;; expose the text
- (foldout-mouse-goto-heading event)
- (let ((nclicks (event-click-count event)))
- (cond
- ((= nclicks 1) (show-entry))
- ((= nclicks 2) (show-children))
- ((= nclicks 3) (show-entry) (show-children))
- (t (show-subtree)))))
-
-(defun foldout-mouse-hide-or-exit (event)
- "Hide the subtree under the heading clicked on, or exit a fold.
-
-What happens depends on the number of mouse clicks:-
-
- 1 hide subtree
- 2 exit fold and hide text
- 3 exit fold without hiding text
- 4 exit all folds and hide text"
- (interactive "@e")
-
- ;; swallow intervening mouse events so we only get the final click-count.
- (setq event (foldout-mouse-swallow-events event))
-
- ;; hide or exit
- (let ((nclicks (event-click-count event)))
- (if (= nclicks 1)
- (progn
- (foldout-mouse-goto-heading event)
- (hide-subtree))
- (foldout-exit-fold
- (cond
- ((= nclicks 2) 1) ; exit and hide
- ((= nclicks 3) -1) ; exit don't hide
- (t 0)))))) ; exit all
-
-
-(defun foldout-mouse-swallow-events (event)
- "Swallow intervening mouse events so we only get the final click-count.
-Signal an error if the final event isn't the same type as the first one."
- (let ((initial-event-type (event-basic-type event)))
- (while (null (sit-for 0 double-click-time 'nodisplay))
- (setq event (read-event)))
- (or (eq initial-event-type (event-basic-type event))
- (error "")))
- event)
-
-(defun foldout-mouse-goto-heading (event)
- "Go to the heading where the mouse event started. Signal an error
-if the event didn't occur on a heading."
- (goto-char (posn-point (event-start event)))
- (or (outline-on-heading-p)
- ;; outline.el sometimes treats beginning-of-buffer as a heading
- ;; even though outline-on-heading returns nil.
- (save-excursion (beginning-of-line) (bobp))
- (error "Not a heading line")))
-
-
-;;; Keymaps:
-
-(defvar foldout-inhibit-key-bindings nil
- "Set non-NIL before loading foldout to inhibit key bindings.")
-
-(defvar foldout-mouse-modifiers '(meta control)
- "List of modifier keys to apply to foldout's mouse events.
-
-The default (meta control) makes foldout bind its functions to
-M-C-down-mouse-{1,2,3}.
-
-Valid modifiers are shift, control, meta, alt, hyper and super.")
-
-(if foldout-inhibit-key-bindings
- ()
- (define-key outline-mode-map "\C-c\C-z" 'foldout-zoom-subtree)
- (define-key outline-mode-map "\C-c\C-x" 'foldout-exit-fold)
- (define-key outline-minor-mode-map
- (concat outline-minor-mode-prefix "\C-z") 'foldout-zoom-subtree)
- (define-key outline-minor-mode-map
- (concat outline-minor-mode-prefix "\C-x") 'foldout-exit-fold)
-
- (let* ((modifiers (apply 'concat
- (mapcar (function
- (lambda (modifier)
- (vector
- (cond
- ((eq modifier 'shift) ?S)
- ((eq modifier 'control) ?C)
- ((eq modifier 'meta) ?M)
- ((eq modifier 'alt) ?A)
- ((eq modifier 'hyper) ?H)
- ((eq modifier 'super) ?s)
- (t (error "invalid mouse modifier %s"
- modifier)))
- ?-)))
- foldout-mouse-modifiers)))
- (mouse-1 (vector (intern (concat modifiers "down-mouse-1"))))
- (mouse-2 (vector (intern (concat modifiers "down-mouse-2"))))
- (mouse-3 (vector (intern (concat modifiers "down-mouse-3")))))
-
- (define-key outline-mode-map mouse-1 'foldout-mouse-zoom)
- (define-key outline-mode-map mouse-2 'foldout-mouse-show)
- (define-key outline-mode-map mouse-3 'foldout-mouse-hide-or-exit)
-
- (define-key outline-minor-mode-map mouse-1 'foldout-mouse-zoom)
- (define-key outline-minor-mode-map mouse-2 'foldout-mouse-show)
- (define-key outline-minor-mode-map mouse-3 'foldout-mouse-hide-or-exit)
- ))
-
-(provide 'foldout)
-
-;;; foldout.el ends here
-
diff --git a/lisp/follow.el b/lisp/follow.el
deleted file mode 100644
index 80f143fba72..00000000000
--- a/lisp/follow.el
+++ /dev/null
@@ -1,2430 +0,0 @@
-;;; follow.el --- Minor mode, Synchronize windows showing the same buffer.
-
-;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Anders Lindgren <andersl@csd.uu.se>
-;; Maintainer: Anders Lindgren <andersl@csd.uu.se>
-;; Created: 25 May 1995
-;; Version: 1.6
-;; Keywords: display, window, minor-mode
-;; Date: 20 Feb 1996
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;{{{ Documentation
-
-;; `Follow mode' is a minor mode for Emacs 19 and XEmacs which
-;; combines windows into one tall virtual window.
-;;
-;; The feeling of a "virtual window" has been accomplished by the use
-;; of two major techniques:
-;;
-;; * The windows always displays adjacent sections of the buffer.
-;; This means that whenever one window is moved, all the
-;; others will follow. (Hence the name Follow Mode.)
-;;
-;; * Should the point (cursor) end up outside a window, another
-;; window displaying that point is selected, if possible. This
-;; makes it possible to walk between windows using normal cursor
-;; movement commands.
-;;
-;; Follow mode comes to its prime when used on a large screen and two
-;; side-by-side window are used. The user can, with the help of Follow
-;; mode, use two full-height windows as though they would have been
-;; one. Imagine yourself editing a large function, or section of text,
-;; and beeing able to use 144 lines instead of the normal 72... (your
-;; mileage may vary).
-
-;; The latest version, and a demonstration, are avaiable at:
-;;
-;; ftp://ftp.csd.uu.se/pub/users/andersl/emacs/follow.el
-;; http://www.csd.uu.se/~andersl/follow.shtml
-
-;; `Follow mode' can be used together with Emacs 19 and XEmacs.
-;; It has been tested together with Emacs 19.27, 19.28, 19.29,
-;; 19.30, XEmacs 19.12, and 19.13.
-
-
-;; To test this package, make sure `follow' is loaded, or will be
-;; autoloaded when activated (see below). Then do the following:
-;;
-;; * Find your favorite file (preferably a long one.)
-;;
-;; * Resize Emacs so that it will be wide enough for two full sized
-;; columns. Delete the other windows and split with the commands
-;; `C-x 1 C-x 3'.
-;;
-;; * Give the command:
-;; M-x follow-mode <RETURN>
-;;
-;; * Now the display should look something like (assuming the text "71"
-;; is on line 71):
-;;
-;; +----------+----------+
-;; |1 |73 |
-;; |2 |74 |
-;; |3 |75 |
-;; ... ...
-;; |71 |143 |
-;; |72 |144 |
-;; +----------+----------+
-;;
-;; As you can see, the right-hand window starts at line 73, the line
-;; immediately below the end of the left-hand window. As long as
-;; `follow-mode' is active, the two windows will follow eachother!
-;;
-;; * Play around and enjoy! Scroll one window and watch the other.
-;; Jump to the beginning or end. Press `Cursor down' at the last
-;; line of the left-hand window. Enter new lines into the
-;; text. Enter long lines spanning several lines, or several
-;; windows.
-;;
-;; * Should you find `Follow' mode annoying, just type
-;; M-x follow-mode <RETURN>
-;; to turn it off.
-
-
-;; Installation:
-;;
-;; To fully install this, add this file to your Emacs Lisp directory and
-;; compile it with M-x byte-compile-file. Then add the following to the
-;; appropriate init file (normally your `~/.emacs' file):
-;;
-;; (autoload 'follow-mode "follow"
-;; "Synchronize windows showing the same buffer, minor mode." t)
-
-
-;; The command `follow-delete-other-windows-and-split' maximises the
-;; visible area of the current buffer.
-;;
-;; I recommend adding it, and `follow-mode', to hotkeys in the global
-;; key map. To do so, add the following lines (replacing `[f7]' and
-;; `[f8]' with your favorite keys) to the init file:
-;;
-;; (autoload 'follow-mode "follow"
-;; "Synchronize windows showing the same buffer, minor mode." t)
-;; (global-set-key [f8] 'follow-mode)
-;;
-;; (autoload 'follow-delete-other-windows-and-split "follow"
-;; "Delete other windows, split the frame in two, and enter Follow Mode." t)
-;; (global-set-key [f7] 'follow-delete-other-windows-and-split)
-
-
-;; There exists two system variables which controls the appearence of
-;; lines which are wider than the window containing them. The default
-;; is to truncate long lines whenever a window isn't as wide as the
-;; frame.
-;;
-;; To make sure lines are never truncated, please place the following
-;; lines in your init file:
-;;
-;; (setq truncate-lines nil)
-;; (setq truncate-partial-width-windows nil)
-
-
-;; Since the display of XEmacs is pixel-oriented, a line could be
-;; clipped in half at the bottom of the window.
-;;
-;; To make XEmacs avoid clipping (normal) lines, please place the
-;; following line in your init-file:
-;;
-;; (setq pixel-vertical-clip-threshold 30)
-
-
-;; The correct way to cofigurate Follow mode, or any other mode for
-;; that matter, is to create one (or more) function which does
-;; whatever you would like to do. The function is then added to
-;; a hook.
-;;
-;; When `Follow' mode is activated, functions stored in the hook
-;; `follow-mode-hook' are called. When it is deactivated
-;; `follow-mode-off-hook' is runed.
-;;
-;; The keymap `follow-key-map' contains key bindings activated by
-;; `follow-mode'.
-;;
-;; Example:
-;; (add-hook 'follow-mode-hook 'my-follow-mode-hook)
-;;
-;; (defun my-follow-mode-hook ()
-;; (define-key follow-mode-map "\C-ca" 'your-favorite-function)
-;; (define-key follow-mode-map "\C-cb" 'another-function))
-
-
-;; Usage:
-;;
-;; To activate give the command: M-x follow-mode
-;; and press return. To deactivate, do it again.
-;;
-;; Some special commands have been developed to make life even easier:
-;; follow-scroll-up C-c . C-v
-;; Scroll text in a Follow Mode window chain up.
-;;
-;; follow-scroll-down C-c . v
-;; Like `follow-scroll-up', but in the other direction.
-;;
-;; follow-delete-other-windows-and-split C-c . 1
-;; Maximise the visible area of the current buffer,
-;; and enter Follow Mode. This is a very convenient
-;; way to start Follow Mode, hence it is recomended
-;; that this command is added to the global keymap.
-;;
-;; follow-recenter C-c . C-l
-;; Place the point in the center of the middle window,
-;; or a specified number of lines from either top or bottom.
-;;
-;; follow-switch-to-buffer C-c . b
-;; Switch buffer in all windows displaying the current buffer
-;; in this frame.
-;;
-;; follow-switch-to-buffer-all C-c . C-b
-;; Switch buffer in all windows in the active frame.
-;;
-;; follow-switch-to-current-buffer-all
-;; Show the current buffer in all windows on the current
-;; frame and turn on `follow-mode'.
-;;
-;; follow-first-window C-c . <
-;; Select the first window in the frame showing the same buffer.
-;;
-;; follow-last-window C-c . >
-;; Select the last window in the frame showing the same buffer.
-;;
-;; follow-next-window C-c . n
-;; Select the next window in the frame showing the same buffer.
-;;
-;; follow-previous-window C-c . p
-;; Select the previous window showing the same buffer.
-
-
-;; Well, it seems ok, but what if I really want to look at two different
-;; positions in the text? Here are two simple methods to use:
-;;
-;; 1) Use multiple frames; `follow' mode only affects windows displayed
-;; in the same frame. (My apoligies to you who can't use frames.)
-;;
-;; 2) Bind `follow-mode' to key so you can turn it off whenever
-;; you want to view two locations. Of course, `follow' mode can
-;; be reactivated by hitting the same key again.
-;;
-;; Example from my ~/.emacs:
-;; (global-set-key [f8] 'follow-mode)
-
-
-;; Implementation:
-;;
-;; In an ideal world, follow mode would have been implemented in the
-;; kernal of the display routines, making sure that the windows (in
-;; follow mode) ALWAYS are aligned. On planet earth, however, we must
-;; accept a solution where we ALMOST ALWAYS can make sure that the
-;; windows are aligned.
-;;
-;; Follow mode does this in three places:
-;; 1) After each user command.
-;; 2) After a process output has been perfomed.
-;; 3) When a scrollbar has been moved.
-;;
-;; This will cover most situations. (Let me know if there are other
-;; situations which should be covered.)
-;;
-;; However, only the selected window is checked, for the reason of
-;; efficiency and code complexity. (i.e. it is possible to make a
-;; non-selected windows unaligned. It will, however, pop right back
-;; when it is selected.)
-
-;;}}}
-;;{{{ Change Log
-
-;;; Change log:
-;; 25-May-95 andersl * File created.
-;; 26-May-95 andersl * It works!
-;; 27-May-95 andersl * Avoids hitting the head in the roof.
-;; * follow-scroll-up, -scroll-down, and -recenter.
-;; * V0.1 Sent to Ohio.
-;; 28-May-95 andersl * Scroll-bar support added.
-;; 30-May-95 andersl * Code adopted to standard style.
-;; * Minor mode keymap.
-;; 2-Jun-95 andersl * Processor output.
-;; 3-Jun-95 andersl * V0.4
-;; 5-Jun-95 andersl * V0.5. Copyright notice corrected.
-;; (The old one stated that I had copyright, but
-;; that Emacs could be freely distributed ;-) )
-;; 6-Jun-95 andersl * Lucid support added. (no longer valid.)
-;; 7-Jun-95 andersl * Menu bar added.
-;; * Bug fix, (at-window 0 0) => (frame-first-window)
-;; 15-Jun-95 andersl * 0.8 Major rework. looong lines and outline mode.
-;; 18-Jun-95 andersl * 0.9 Allow a tail window to be selected, but pick
-;; a better one when edited.
-;; 26-Jun-95 andersl * Inlineing.
-;; 02-Jul-95 andersl * compute-motion imitated with a ugly workaround,
-;; Works with XEmacs again!
-;; 15-Jul-95 andersl * find-file hook.
-;; * submit-feedback.
-;; * Survives major mode changes.
-;; * Region spanning multiple windows looks
-;; resonabely good.
-;; 19-Jul-95 andersl * New process-filter handling.
-;; 1-Aug-95 andersl * XEmacs scrollbar support.
-;; * Emacs 19 `window-size-change' support.
-;; * `save-window-excursion' removed, it triggered
-;; a redraw!
-;; 5-Aug-95 andersl * `follow-switch-to-current-buffer-all' added.
-;; 16-Nov-95 andersl * V1.0 released!
-;; 17-Nov-95 andersl * Byte compiler silencer for XEmacs broken.
-;; * fkey-end-of-buffer treated the same way
-;; end-of-buffer is.
-;; * follow-mode-off-hook added.
-;; (Suggested by David Hughes, thanks!)
-;; 20-Nov-95 andersl * Bug in menu code corrected.
-;; (Reported by Robert E. Brown, thanks!)
-;; 5-Dec-95 andersl * `follow-avoid-tail-recenter' added to the
-;; post-command-idle-hook to avoid recentering
-;; caused by `paren' et. al.
-;; 7-Dec-95 andersl * `follow-avoid-tail-recenter' called by
-;; `window-scroll-functions'.
-;; 18-Dec-95 andersl * All processes intercepted.
-;; 20-Dec-95 andersl * `follow-recenter' accepts arguments.
-;; * `move-overlay' advices, drag-region works.
-;; 2-Jan-96 andersl * XEmacs: isearch fixed.
-;; * `follow-calc-win-end' created.
-;; 8-Jan-96 andersl * XEmacs: `window-end' with `guarantee'
-;; argument used in `follow-calc-win-end'.
-;; 9-Jan-96 andersl * `follow-end-of-buffer' added.
-;; Code in post hook removed.
-;; * XEmacs: Post hook is always executed
-;; after a mouse button event.
-;; 22-Jan-96 andersl * 1.5 released.
-;;
-
-;;}}}
-;;{{{ LCD Entry
-
-;;; LCD Archive Entry:
-;; follow|Anders Lindgren|andersl@csd.uu.se|
-;; Combines windows into tall virtual window, minor mode.
-;; 20-Feb-1996|1.6|~/modes/follow.el.Z|
-
-;;}}}
-
-;;; Code:
-
-;;{{{ Preliminaries
-
-;; Make the compiler shut up!
-;; There are two strategies:
-;; 1) Shut warnings off completely.
-;; 2) Handle each warning separately.
-;;
-;; Since I would like to see real errors, I've selected the latter
-;; method.
-;;
-;; The problem with undefined variables and functions has been solved
-;; by using `set', `symbol-value' and `symbol-function' rather than
-;; `setq' and direct references to variables and functions.
-;;
-;; For example:
-;; (if (boundp 'foo) ... (symbol-value 'foo) )
-;; (set 'foo ...) <-- XEmacs doesn't fall for this one.
-;; (funcall (symbol-function 'set) 'bar ...)
-;;
-;; Note: When this file is interpreted, `eval-when-compile' is
-;; evaluted (really smart...) Since it doesn't hurt to evaluate it,
-;; but it is a bit annoying, we test if the byte-compiler has been
-;; loaded. This can, of course, lead to some occasional unintended
-;; evaluation...
-;;
-;; Should someone come up with a better solution, please let me
-;; know.
-
-(eval-when-compile
- (if (or (featurep 'bytecomp)
- (featurep 'byte-compile))
- (cond ((string-match "XEmacs" emacs-version)
- ;; Make XEmacs shut up! I'm using standard Emacs
- ;; functions, they are NOT obsolete!
- (if (eq (get 'force-mode-line-update 'byte-compile)
- 'byte-compile-obsolete)
- (put 'force-mode-line-update 'byte-compile 'nil))
- (if (eq (get 'frame-first-window 'byte-compile)
- 'byte-compile-obsolete)
- (put 'frame-first-window 'byte-compile 'nil))))))
-
-;;}}}
-;;{{{ Variables
-
-(defvar follow-mode nil
- "Variable indicating if Follow mode is active.")
-
-(defvar follow-mode-hook nil
- "*Hooks to run when follow-mode is turned on.")
-
-(defvar follow-mode-off-hook nil
- "*Hooks to run when follow-mode is turned off.")
-
-(defvar follow-mode-version "follow.el (Release 1.6)"
- "The current version of Follow mode.")
-
-(defvar follow-mode-map nil
- "*Minor mode keymap for Follow mode.")
-
-(defvar follow-mode-line-text " Follow"
- "*Text shown in the mode line when Follow mode is active.
-Defaults to \" Follow\". Examples of other values
-are \" Fw\", or simply \"\".")
-
-(defvar follow-auto nil
- "*Non-nil activates Follow mode whenever a file is loaded.")
-
-(defvar follow-mode-prefix "\C-c."
- "*Prefix key to use for follow commands in Follow mode.
-The value of this variable is checked as part of loading Follow mode.
-After that, changing the prefix key requires manipulating keymaps.")
-
-(defvar follow-intercept-processes t
- "*When non-nil, Follow Mode will monitor process output.")
-
-(defvar follow-emacs-version-xemacs-p
- (string-match "XEmacs" emacs-version)
- "Non-nil when running under XEmacs.")
-
-(defvar follow-avoid-tail-recenter-p
- (not follow-emacs-version-xemacs-p)
- "*When non-nil, patch emacs so that tail windows won't be recentered.
-
-A \"tail window\" is a window which displays only the end of
-the buffer. Normally it is practical for the user that empty
-windows are recentered automatically. However, when using
-Follow Mode it breaks the display when the end is displayed
-in a window \"above\" the last window. This is for
-example the case when displaying a short page in info.
-
-Must be set before Follow Mode is loaded.
-
-Please note that it is not possible to fully prevent Emacs from
-recentering empty windows. Please report if you find a repeatable
-situation in which Emacs recenters empty windows.
-
-XEmacs, as of 19.12, does not recenter windows, good!")
-
-(defvar follow-cache-command-list
- '(next-line previous-line forward-char backward-char)
- "List of commands which don't require recalculation.
-
-In order to be able to use the cache, a command should not change the
-contents of the buffer, nor should it change selected window or current
-buffer.
-
-The commands in this list are checked at load time.
-
-To mark other commands as suitable for caching, set the symbol
-property `follow-mode-use-cache' to non-nil.")
-
-(defvar follow-debug nil
- "*Non-nil when debugging Follow mode.")
-
-
-;; Internal variables:
-
-(defvar follow-internal-force-redisplay nil
- "True when Follow mode should redisplay the windows.")
-
-(defvar follow-process-filter-alist '()
- "The original filters for processes intercepted by Follow mode.")
-
-(defvar follow-active-menu nil
- "The menu visible when Follow mode is active.")
-
-(defvar follow-deactive-menu nil
- "The menu visible when Follow mode is deactivated.")
-
-(defvar follow-inside-post-command-hook nil
- "Non-nil when inside Follow modes `post-command-hook'.
-Used by `follow-window-size-change'.")
-
-(defvar follow-windows-start-end-cache nil
- "Cache used by `follow-window-start-end'.")
-
-;;}}}
-;;{{{ Bug report
-
-(eval-when-compile (require 'reporter))
-
-(defun follow-submit-feedback ()
- "Sumbit feedback on Follow mode to the author: andersl@csd.uu.se"
- (interactive)
- (require 'reporter)
- (and (y-or-n-p "Do you really want to submit a report on Follow mode? ")
- (reporter-submit-bug-report
- "Anders Lindgren <andersl@csd.uu.se>"
- follow-mode-version
- '(post-command-hook
- post-command-idle-hook
- pre-command-hook
- window-size-change-functions
- window-scroll-functions
- follow-mode-hook
- follow-mode-off-hook
- follow-auto
- follow-intercept-processes
- follow-avoid-tail-recenter-p
- follow-process-filter-alist)
- nil
- nil
- (concat
- "Hi Anders!\n\n"
- "(I have read the section on how to report bugs in the "
- "Emacs manual.)\n\n"
- "Even though I know you are busy, I thought you might "
- "want to know...\n\n"))))
-
-;;}}}
-;;{{{ Debug messages
-
-;; This inline function must be as small as possible!
-;; Maybe we should define a macro which expands to nil if
-;; the varible is not set.
-
-(defsubst follow-debug-message (&rest args)
- "Like message, but only active when `follow-debug' is non-nil."
- (if (and (boundp 'follow-debug) follow-debug)
- (apply 'message args)))
-
-;;}}}
-
-;;{{{ Keymap/Menu
-
-;;; Define keys for the follow-mode minor mode map and replace some
-;;; functions in the global map. All `follow' mode special functions
-;;; can be found on (the somewhat cumbersome) "C-c . <key>"
-;;; (Control-C dot <key>). (As of Emacs 19.29 the keys
-;;; C-c <punctuation character> are reserved for minor modes.)
-;;;
-;;; To change the prefix, redefine `follow-mode-prefix' before
-;;; `follow' is loaded, or see the section on `follow-mode-hook'
-;;; above for an example of how to bind the keys the way you like.
-;;;
-;;; Please note that the keymap is defined the first time this file is
-;;; loaded. Also note that the only legal way to manipulate the
-;;; keymap is to use `define-key'. Don't change it using `setq' or
-;;; similar!
-
-
-(if follow-mode-map
- nil
- (setq follow-mode-map (make-sparse-keymap))
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-v" 'follow-scroll-up)
- (define-key map "\M-v" 'follow-scroll-down)
- (define-key map "v" 'follow-scroll-down)
- (define-key map "1" 'follow-delete-other-windows-and-split)
- (define-key map "b" 'follow-switch-to-buffer)
- (define-key map "\C-b" 'follow-switch-to-buffer-all)
- (define-key map "\C-l" 'follow-recenter)
- (define-key map "<" 'follow-first-window)
- (define-key map ">" 'follow-last-window)
- (define-key map "n" 'follow-next-window)
- (define-key map "p" 'follow-previous-window)
-
- (define-key follow-mode-map follow-mode-prefix map)
-
- ;; Replace the standard `end-of-buffer', when in Follow Mode. (I
- ;; don't see the point in trying to replace every function which
- ;; could be enhanced in Follow mode. End-of-buffer is a special
- ;; case since it is very simple to define and it greatly enhances
- ;; the look and feel of Follow mode.)
- ;;
- ;; (The function `substitute-key-definition' does not work
- ;; in all versions of Emacs.)
- (mapcar
- (function
- (lambda (pair)
- (let ((old (car pair))
- (new (cdr pair)))
- (mapcar (function (lambda (key)
- (define-key follow-mode-map key new)))
- (where-is-internal old global-map)))))
- '((end-of-buffer . follow-end-of-buffer)
- (fkey-end-of-buffer . follow-end-of-buffer)))
-
- ;;;
- ;;; The menu.
- ;;;
-
- (if (not follow-emacs-version-xemacs-p)
-
- ;;
- ;; Emacs 19
- ;;
- (let ((menumap (funcall (symbol-function 'make-sparse-keymap)
- "Follow"))
- (count 0)
- id)
- (mapcar
- (function
- (lambda (item)
- (setq id
- (or (cdr item)
- (progn
- (setq count (+ count 1))
- (intern (format "separator-%d" count)))))
- (define-key menumap (vector id) item)
- (or (eq id 'follow-mode)
- (put id 'menu-enable 'follow-mode))))
- ;; In reverse order:
- '(("Toggle Follow mode" . follow-mode)
- ("--")
- ("Recenter" . follow-recenter)
- ("--")
- ("Previous Window" . follow-previous-window)
- ("Next Windows" . follow-next-window)
- ("Last Window" . follow-last-window)
- ("First Window" . follow-first-window)
- ("--")
- ("Switch To Buffer (all windows)"
- . follow-switch-to-buffer-all)
- ("Switch To Buffer" . follow-switch-to-buffer)
- ("--")
- ("Delete Other Windows and Split"
- . follow-delete-other-windows-and-split)
- ("--")
- ("Scroll Down" . follow-scroll-down)
- ("Scroll Up" . follow-scroll-up)))
-
- ;; If there is a `tools' meny, we use it. However, we can't add a
- ;; minor-mode specific item to it (it's broken), so we make the
- ;; contents ghosted when not in use, and add ourselves to the
- ;; global map. If no `tools' menu is present, just make a
- ;; top-level menu visible when the mode is activated.
-
- (let ((tools-map (lookup-key (current-global-map) [menu-bar tools]))
- (last nil))
- (if (sequencep tools-map)
- (progn
- ;; Find the last entry in the menu and store it in `last'.
- (mapcar (function
- (lambda (x)
- (setq last (or (cdr-safe
- (cdr-safe
- (cdr-safe x)))
- last))))
- tools-map)
- (if last
- (progn
- (funcall (symbol-function 'define-key-after)
- tools-map [separator-follow] '("--") last)
- (funcall (symbol-function 'define-key-after)
- tools-map [follow] (cons "Follow" menumap)
- 'separator-follow))
- ;; Didn't find the last item, Adding to the top of
- ;; tools. (This will probably never happend...)
- (define-key (current-global-map) [menu-bar tools follow]
- (cons "Follow" menumap))))
- ;; No tools menu, add "Follow" to the menubar.
- (define-key follow-mode-map [menu-bar follow]
- (cons "Follow" menumap)))))
-
- ;;
- ;; XEmacs.
- ;;
-
- ;; place the menu in the `Tools' menu.
- (let ((menu '("Follow"
- :filter follow-menu-filter
- ["Scroll Up" follow-scroll-up t]
- ["Scroll Down" follow-scroll-down t]
- ["Delete Other Windows and Split"
- follow-delete-other-windows-and-split t]
- ["Switch To Buffer" follow-switch-to-buffer t]
- ["Switch To Buffer (all windows)"
- follow-switch-to-buffer-all t]
- ["First Window" follow-first-window t]
- ["Last Window" follow-last-window t]
- ["Next Windows" follow-next-window t]
- ["Previous Window" follow-previous-window t]
- ["Recenter" follow-recenter t]
- ["Deactivate" follow-mode t])))
-
- ;; Why not just `(set-buffer-menubar current-menubar)'? The
- ;; question is a very good question. The reason is that under
- ;; Emacs 19, neither `set-buffer-menubar' nor
- ;; `current-menubar' is defined, hence the byte-compiler will
- ;; warn.
- (funcall (symbol-function 'set-buffer-menubar)
- (symbol-value 'current-menubar))
- (funcall (symbol-function 'add-submenu) '("Tools") menu))
-
- ;; When the mode is not activated, only one item is visible:
- ;; "Activate".
- (defun follow-menu-filter (menu)
- (if follow-mode
- menu
- '(["Activate " follow-mode t]))))))
-
-
-;;; Register the follow mode keymap.
-(or (assq 'follow-mode minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons (cons 'follow-mode follow-mode-map) minor-mode-map-alist)))
-
-;;}}}
-;;{{{ Cache
-
-(let ((cmds follow-cache-command-list))
- (while cmds
- (put (car cmds) 'follow-mode-use-cache t)
- (setq cmds (cdr cmds))))
-
-;;}}}
-
-;;{{{ The mode
-
-;;;###autoload
-(defun turn-on-follow-mode ()
- "Turn on Follow mode. Please see the function `follow-mode'."
- (interactive)
- (follow-mode 1))
-
-
-;;;###autoload
-(defun turn-off-follow-mode ()
- "Turn off Follow mode. Please see the function `follow-mode'."
- (interactive)
- (follow-mode -1))
-
-
-;;;###autoload
-(defun follow-mode (arg)
- "Minor mode which combines windows into one tall virtual window.
-
-The feeling of a \"virtual window\" has been accomplished by the use
-of two major techniques:
-
-* The windows always displays adjacent sections of the buffer.
- This means that whenever one window is moved, all the
- others will follow. (Hence the name Follow Mode.)
-
-* Should the point (cursor) end up outside a window, another
- window displaying that point is selected, if possible. This
- makes it possible to walk between windows using normal cursor
- movement commands.
-
-Follow mode comes to its prime when used on a large screen and two
-side-by-side window are used. The user can, with the help of Follow
-mode, use two full-height windows as though they would have been
-one. Imagine yourself editing a large function, or section of text,
-and beeing able to use 144 lines instead of the normal 72... (your
-mileage may vary).
-
-To split one large window into two side-by-side windows, the commands
-`\\[split-window-horizontally]' or \
-`M-x follow-delete-other-windows-and-split' can be used.
-
-Only windows displayed in the same frame follow each-other.
-
-If the variable `follow-intercept-processes' is non-nil, Follow mode
-will listen to the output of processes and redisplay accordingly.
-\(This is the default.)
-
-When Follow mode is switched on, the hook `follow-mode-hook'
-is called. When turned off, `follow-mode-off-hook' is called.
-
-Keys specific to Follow mode:
-\\{follow-mode-map}"
- (interactive "P")
- (make-local-variable 'follow-mode)
- (put 'follow-mode 'permanent-local t)
- (let ((follow-mode-orig follow-mode))
- (setq follow-mode
- (if (null arg)
- (not follow-mode)
- (> (prefix-numeric-value arg) 0)))
- (if (and follow-mode follow-intercept-processes)
- (follow-intercept-process-output))
- (cond ((and follow-mode (not follow-mode-orig)) ; On
- ;; XEmacs: If this is non-nil, the window will scroll before
- ;; the point will have a chance to get into the next window.
- (if (boundp 'scroll-on-clipped-lines)
- (set 'scroll-on-clipped-lines nil))
- (force-mode-line-update)
- (add-hook 'post-command-hook 'follow-post-command-hook t)
- (if (boundp 'post-command-idle-hook)
- (add-hook 'post-command-idle-hook
- 'follow-avoid-tail-recenter t))
- (run-hooks 'follow-mode-hook))
-
- ((and (not follow-mode) follow-mode-orig) ; Off
- (force-mode-line-update)
- (run-hooks 'follow-mode-off-hook)))))
-
-
-;; Register follow-mode as a minor mode.
-
-(if (fboundp 'add-minor-mode)
- ;; XEmacs
- (funcall (symbol-function 'add-minor-mode)
- 'follow-mode 'follow-mode-line-text)
- (or (assq 'follow-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(follow-mode follow-mode-line-text) minor-mode-alist))))
-
-;;}}}
-;;{{{ Find file hook
-
-;; This will start follow-mode whenever a new file is loaded, if
-;; the variable `follow-auto' is non-nil.
-
-(add-hook 'find-file-hooks 'follow-find-file-hook t)
-
-(defun follow-find-file-hook ()
- "Find-file hook for Follow Mode. See the variable `follow-auto'."
- (if follow-auto (follow-mode t)))
-
-;;}}}
-
-;;{{{ User functions
-
-;;;
-;;; User functions usable when in Follow mode.
-;;;
-
-;;{{{ Scroll
-
-;; `scroll-up' and `-down', but for windows in Follow Mode.
-;;
-;; Almost like the real thing, excpet when the cursor ends up outside
-;; the top or bottom... In our case however, we end up outside the
-;; window and hence we are recenterd. Should we let `recenter' handle
-;; the point position we would never leave the selected window. To do
-;; it ourselves we would need to do our own redisplay, which is easier
-;; said than done. (Why didn't I do a real display abstraction from
-;; the beginning?)
-;;
-;; We must sometimes set `follow-internal-force-redisplay', otherwise
-;; our post-command-hook will move our windows back into the old
-;; position... (This would also be corrected if we would have had a
-;; good redisplay abstraction.)
-
-(defun follow-scroll-up (&optional arg)
- "Scroll text in a Follow Mode window chain up.
-
-If called with no ARG, the `next-screen-context-lines' last lines of
-the bottom window in the chain will be visible in the top window.
-
-If called with an argument, scroll ARG lines up.
-Negative ARG means scroll downward.
-
-Works like `scroll-up' when not in Follow Mode."
- (interactive "P")
- (cond ((not (and (boundp 'follow-mode) follow-mode))
- (scroll-up arg))
- (arg
- (save-excursion (scroll-up arg))
- (setq follow-internal-force-redisplay t))
- (t
- (let* ((windows (follow-all-followers))
- (end (window-end (car (reverse windows)))))
- (if (eq end (point-max))
- (signal 'end-of-buffer nil)
- (select-window (car windows))
- (goto-char end)
- (vertical-motion (- next-screen-context-lines))
- (set-window-start (car windows) (point)))))))
-
-
-(defun follow-scroll-down (&optional arg)
- "Scroll text in a Follow Mode window chain down.
-
-If called with no ARG, the `next-screen-context-lines' top lines of
-the top window in the chain will be visible in the bottom window.
-
-If called with an argument, scroll ARG lines down.
-Negative ARG means scroll upward.
-
-Works like `scroll-up' when not in Follow Mode."
- (interactive "P")
- (cond ((not (and (boundp 'follow-mode) follow-mode))
- (scroll-up arg))
- (arg
- (save-excursion (scroll-down arg)))
- (t
- (let* ((windows (follow-all-followers))
- (win (car (reverse windows)))
- (start (window-start (car windows))))
- (if (eq start (point-min))
- (signal 'beginning-of-buffer nil)
- (select-window win)
- (goto-char start)
- (vertical-motion (- (- (window-height win)
- 1
- next-screen-context-lines)))
- (set-window-start win (point))
- (goto-char start)
- (vertical-motion (- next-screen-context-lines 1))
- (setq follow-internal-force-redisplay t))))))
-
-;;}}}
-;;{{{ Buffer
-
-;;;###autoload
-(defun follow-delete-other-windows-and-split (&optional arg)
- "Create two side by side windows and enter Follow Mode.
-
-Execute this command to display as much as possible of the text
-in the selected window. All other windows, in the current
-frame, are deleted and the selected window is split in two
-side-by-side windows. Follow Mode is activated, hence the
-two windows always will display two successive pages.
-\(If one window is moved, the other one will follow.)
-
-If ARG is positive, the leftmost window is selected. If it negative,
-the rightmost is selected. If ARG is nil, the leftmost window is
-selected if the original window is the first one in the frame.
-
-To bind this command to a hotkey, place the following line
-in your `~/.emacs' file, replacing [f7] by your favourite key:
- (global-set-key [f7] 'follow-delete-other-windows-and-split)"
- (interactive "P")
- (let ((other (or (and (null arg)
- (not (eq (selected-window)
- (frame-first-window (selected-frame)))))
- (and arg
- (< (prefix-numeric-value arg) 0))))
- (start (window-start)))
- (delete-other-windows)
- (split-window-horizontally)
- (if other
- (progn
- (other-window 1)
- (set-window-start (selected-window) start)
- (setq follow-internal-force-redisplay t)))
- (follow-mode 1)))
-
-(defun follow-switch-to-buffer (buffer)
- "Show BUFFER in all windows in the current Follow Mode window chain."
- (interactive "BSwitch to Buffer: ")
- (let ((orig-window (selected-window))
- (windows (follow-all-followers)))
- (while windows
- (select-window (car windows))
- (switch-to-buffer buffer)
- (setq windows (cdr windows)))
- (select-window orig-window)))
-
-
-(defun follow-switch-to-buffer-all (&optional buffer)
- "Show BUFFER in all windows on this frame.
-Defaults to current buffer."
- (interactive (list (read-buffer "Switch to Buffer: "
- (current-buffer))))
- (or buffer (setq buffer (current-buffer)))
- (let ((orig-window (selected-window)))
- (walk-windows
- (function
- (lambda (win)
- (select-window win)
- (switch-to-buffer buffer))))
- (select-window orig-window)
- (follow-redisplay)))
-
-
-(defun follow-switch-to-current-buffer-all ()
- "Show current buffer in all windows on this frame, and enter Follow Mode.
-
-To bind this command to a hotkey place the following line
-in your `~/.emacs' file:
- (global-set-key [f7] 'follow-switch-to-current-buffer-all)"
- (interactive)
- (or (and (boundp 'follow-mode) follow-mode)
- (follow-mode 1))
- (follow-switch-to-buffer-all))
-
-;;}}}
-;;{{{ Movement
-
-;; Note, these functions are not very useful, atleast not unless you
-;; rebind the rather cumbersome key sequence `C-c . p'.
-
-(defun follow-next-window ()
- "Select the next window showing the same buffer."
- (interactive)
- (let ((succ (cdr (follow-split-followers (follow-all-followers)))))
- (if succ
- (select-window (car succ))
- (error "%s" "No more windows"))))
-
-
-(defun follow-previous-window ()
- "Select the previous window showing the same buffer."
- (interactive)
- (let ((pred (car (follow-split-followers (follow-all-followers)))))
- (if pred
- (select-window (car pred))
- (error "%s" "No more windows"))))
-
-
-(defun follow-first-window ()
- "Select the first window in the frame showing the same buffer."
- (interactive)
- (select-window (car (follow-all-followers))))
-
-
-(defun follow-last-window ()
- "Select the last window in the frame showing the same buffer."
- (interactive)
- (select-window (car (reverse (follow-all-followers)))))
-
-;;}}}
-;;{{{ Redraw
-
-(defun follow-recenter (&optional arg)
- "Recenter the middle window around the point,
-and rearrange all other windows around the middle window.
-
-With a positive argument, place the current line ARG lines
-from the top. With a negative, place it -ARG lines from the
-bottom."
- (interactive "P")
- (if arg
- (let ((p (point))
- (arg (prefix-numeric-value arg)))
- (if (>= arg 0)
- ;; Recenter relative to the top.
- (progn
- (follow-first-window)
- (goto-char p)
- (recenter arg))
- ;; Recenter relative to the bottom.
- (follow-last-window)
- (goto-char p)
- (recenter arg)
- ;; Otherwise, our post-command-hook will move the window
- ;; right back.
- (setq follow-internal-force-redisplay t)))
- ;; Recenter in the middle.
- (let* ((dest (point))
- (windows (follow-all-followers))
- (win (nth (/ (- (length windows) 1) 2) windows)))
- (select-window win)
- (goto-char dest)
- (recenter)
- ;;(setq follow-internal-force-redisplay t)
- )))
-
-
-(defun follow-redraw ()
- "Arrange windows displaying the same buffer in successor order.
-This function can be called even if the buffer is not in Follow mode.
-
-Hopefully, there should be no reason to call this function when in
-Follow mode since the windows should always be aligned."
- (interactive)
- (sit-for 0)
- (follow-redisplay))
-
-;;}}}
-;;{{{ End of buffer
-
-(defun follow-end-of-buffer (&optional arg)
- "Move point to the end of the buffer. Follow Mode style.
-
-If the end is not visible, it will be displayed in the last possible
-window in the Follow Mode window chain.
-
-The mark is left at the previous position. With arg N, put point N/10
-of the way from the true end."
- (interactive "P")
- (let ((followers (follow-all-followers))
- (pos (point)))
- (cond (arg
- (select-window (car (reverse followers))))
- ((follow-select-if-end-visible
- (follow-windows-start-end followers)))
- (t
- (select-window (car (reverse followers)))))
- (goto-char pos)
- (end-of-buffer arg)))
-
-;;}}}
-
-;;}}}
-
-;;{{{ Display
-
-;;;; The display routines
-
-;;{{{ Information gathering functions
-
-(defun follow-all-followers (&optional testwin)
- "Return all windows displaying the same buffer as the TESTWIN.
-The list contains only windows displayed in the same frame as TESTWIN.
-If TESTWIN is nil the selected window is used."
- (or (and testwin (window-live-p testwin))
- (setq testwin (selected-window)))
- (let* ((top (frame-first-window (window-frame testwin)))
- (win top)
- (done nil)
- (windows '())
- (buffer (window-buffer testwin)))
- (while (and (not done) win)
- (if (eq (window-buffer win) buffer)
- (setq windows (cons win windows)))
- (setq win (next-window win 'not))
- (if (eq win top)
- (setq done t)))
- (nreverse windows)))
-
-
-(defun follow-split-followers (windows &optional win)
- "Split the WINDOWS into the sets: predecessors and successors.
-Return `(PRED . SUCC)' where `PRED' and `SUCC' are ordered starting
-from the selected window."
- (or win
- (setq win (selected-window)))
- (let ((pred '()))
- (while (not (eq (car windows) win))
- (setq pred (cons (car windows) pred))
- (setq windows (cdr windows)))
- (cons pred (cdr windows))))
-
-
-;; Try to optimize this function for speed!
-
-(defun follow-calc-win-end (&optional win)
- "Calculate the presumed window end for WIN.
-
-Actually, the position returned is the start of the next
-window, normally is the end plus one.
-
-If WIN is nil, the selected window is used.
-
-Returns (end-pos end-of-buffer-p)"
- (if follow-emacs-version-xemacs-p
- ;; XEmacs can calculate the end of the window by using
- ;; the 'guarantee options. GOOD!
- (let ((end (window-end win t)))
- (if (= end (funcall (symbol-function 'point-max)
- (window-buffer win)))
- (list end t)
- (list (+ end 1) nil)))
- ;; Emacs 19: We have to calculate the end by ourselves.
- ;; This code works on both XEmacs and Emacs 19, but now
- ;; that XEmacs has got custom-written code, this could
- ;; be optimized for Emacs 19.
- (let ((orig-win (and win (selected-window)))
- height
- buffer-end-p)
- (if win (select-window win))
- (prog1
- (save-excursion
- (goto-char (window-start))
- (setq height (- (window-height) 1))
- (setq buffer-end-p
- (if (bolp)
- (not (= height (vertical-motion height)))
- (save-restriction
- ;; Fix a mis-feature in `vertical-motion':
- ;; The start of the window is assumed to
- ;; coinside with the start of a line.
- (narrow-to-region (point) (point-max))
- (not (= height (vertical-motion height))))))
- (list (point) buffer-end-p))
- (if orig-win
- (select-window orig-win))))))
-
-
-;; Can't use `save-window-excursion' since it triggers a redraw.
-(defun follow-calc-win-start (windows pos win)
- "Calculate where WIN will start if the first in WINDOWS start at POS.
-
-If WIN is nil the point below all windows is returned."
- (let (start)
- (while (and windows (not (eq (car windows) win)))
- (setq start (window-start (car windows)))
- (set-window-start (car windows) pos 'noforce)
- (setq pos (car (inline (follow-calc-win-end (car windows)))))
- (set-window-start (car windows) start 'noforce)
- (setq windows (cdr windows)))
- pos))
-
-
-;; The result from `follow-windows-start-end' is cached when using
-;; a handful simple commands, like cursor movement commands.
-
-(defsubst follow-cache-valid-p (windows)
- "Test if the cached value of `follow-windows-start-end' can be used.
-Note that this handles the case when the cache has been set to nil."
- (let ((res t)
- (cache follow-windows-start-end-cache))
- (while (and res windows cache)
- (setq res (and (eq (car windows)
- (car (car cache)))
- (eq (window-start (car windows))
- (car (cdr (car cache))))))
- (setq windows (cdr windows))
- (setq cache (cdr cache)))
- (and res (null windows) (null cache))))
-
-
-(defsubst follow-invalidate-cache ()
- "Force `follow-windows-start-end' to recalculate the end of the window."
- (setq follow-windows-start-end-cache nil))
-
-
-;; Build a list of windows and their start and end positions.
-;; Useful to avoid calculating start/end position whenever they are needed.
-;; The list has the format:
-;; ((Win Start End End-of-buffer-visible-p) ...)
-
-;; Used to have a `save-window-excursion', but it obviously triggered
-;; redraws of the display. Check if I used it for anything.
-
-
-(defun follow-windows-start-end (windows)
- "Builds a list of (WIN START END BUFFER-END-P) for every window in WINDOWS."
- (if (follow-cache-valid-p windows)
- follow-windows-start-end-cache
- (let ((win-start-end '())
- (orig-win (selected-window)))
- (while windows
- (select-window (car windows))
- (setq win-start-end
- (cons (cons (car windows)
- (cons (window-start)
- (follow-calc-win-end)))
- win-start-end))
- (setq windows (cdr windows)))
- (select-window orig-win)
- (setq follow-windows-start-end-cache (nreverse win-start-end))
- follow-windows-start-end-cache)))
-
-
-(defsubst follow-pos-visible (pos win win-start-end)
- "Non-nil when POS is visible in WIN."
- (let ((wstart-wend-bend (cdr (assq win win-start-end))))
- (and (>= pos (car wstart-wend-bend))
- (or (< pos (car (cdr wstart-wend-bend)))
- (nth 2 wstart-wend-bend)))))
-
-
-;; By `aligned' we mean that for all adjecent windows, the end of the
-;; first is equal with the start of the successor. The first window
-;; should start at a full screen line.
-
-(defsubst follow-windows-aligned-p (win-start-end)
- "Non-nil if the follower WINDOWS are alinged."
- (let ((res t))
- (save-excursion
- (goto-char (window-start (car (car win-start-end))))
- (if (bolp)
- nil
- (vertical-motion 0 (car (car win-start-end)))
- (setq res (eq (point) (window-start (car (car win-start-end)))))))
- (while (and res (cdr win-start-end))
- ;; At least two followers left
- (setq res (eq (car (cdr (cdr (car win-start-end))))
- (car (cdr (car (cdr win-start-end))))))
- (setq win-start-end (cdr win-start-end)))
- res))
-
-
-;; Check if the point is visible in all windows. (So that
-;; no one will be recentered.)
-
-(defun follow-point-visible-all-windows-p (win-start-end)
- "Non-nil when the window-point is visible in all windows."
- (let ((res t))
- (while (and res win-start-end)
- (setq res (follow-pos-visible (window-point (car (car win-start-end)))
- (car (car win-start-end))
- win-start-end))
- (setq win-start-end (cdr win-start-end)))
- res))
-
-
-;; Make sure WIN always starts at the beginning of an whole screen
-;; line. If WIN is not aligned the start is updated which probably
-;; will lead to a redisplay of the screen later on.
-;;
-;; This is used with the first window in a follow chain. The reason
-;; is that we want to detect that the point is outside the window.
-;; (Without the update, the start of the window will move as the
-;; user presses BackSpace, and the other window redisplay routines
-;; will move the start of the window in the wrong direction.)
-
-(defun follow-update-window-start (win)
- "Make sure that the start of WIN starts at a full screen line."
- (save-excursion
- (goto-char (window-start win))
- (if (bolp)
- nil
- (vertical-motion 0 win)
- (if (eq (point) (window-start win))
- nil
- (vertical-motion 1 win)
- (set-window-start win (point) 'noforce)))))
-
-;;}}}
-;;{{{ Selection functions
-
-;; Make a window in WINDOWS selected if it currently
-;; is displaying the position DEST.
-;;
-;; We don't select a window if it just has been moved.
-
-(defun follow-select-if-visible (dest win-start-end)
- "Select and return a window, if DEST is visible in it.
-Return the selected window."
- (let ((win nil))
- (while (and (not win) win-start-end)
- ;; Don't select a window which was just moved. This makes it
- ;; possible to later select the last window after a `end-of-buffer'
- ;; command.
- (if (follow-pos-visible dest (car (car win-start-end)) win-start-end)
- (progn
- (setq win (car (car win-start-end)))
- (select-window win)))
- (setq win-start-end (cdr win-start-end)))
- win))
-
-
-;; Lets select a window showing the end. Make sure we only select it if it
-;; it wasn't just moved here. (i.e. M-> shall not unconditionally place
-;; the point in the selected window.)
-;;
-;; (Compability cludge: in Emacs 19 `window-end' is equal to `point-max';
-;; in XEmacs, it is equal to `point-max + 1'. Should I really bother
-;; checking `window-end' now when I check `end-of-buffer' explicitylt?)
-
-(defun follow-select-if-end-visible (win-start-end)
- "Select and return a window, if end is visible in it."
- (let ((win nil))
- (while (and (not win) win-start-end)
- ;; Don't select a window which was just moved. This makes it
- ;; possible to later select the last window after a `end-of-buffer'
- ;; command.
- (if (and (eq (point-max) (nth 2 (car win-start-end)))
- (nth 3 (car win-start-end))
- (eq (point-max) (min (point-max)
- (window-end (car (car win-start-end))))))
- (progn
- (setq win (car (car win-start-end)))
- (select-window win)))
- (setq win-start-end (cdr win-start-end)))
- win))
-
-
-;; Select a window which will display the point if the windows would
-;; be redisplayed with the first window fixed. This is useful for
-;; example when the user has pressed return at the bottom of a window
-;; as the point is not visible in any window.
-
-(defun follow-select-if-visible-from-first (dest windows)
- "Select and return a window with DEST, if WINDOWS are redrawn from top."
- (let ((win nil)
- end-pos-end-p)
- (save-excursion
- (goto-char (window-start (car windows)))
- ;; Make sure the line start in the beginning of a real screen
- ;; line.
- (vertical-motion 0 (car windows))
- (if (< dest (point))
- ;; Above the start, not visible.
- nil
- ;; At or below the start. Check the windows.
- (save-window-excursion
- (while (and (not win) windows)
- (set-window-start (car windows) (point) 'noforce)
- (setq end-pos-end-p (follow-calc-win-end (car windows)))
- (goto-char (car end-pos-end-p))
- ;; Visible, if dest above end, or if eob is visible inside
- ;; the window.
- (if (or (car (cdr end-pos-end-p))
- (< dest (point)))
- (setq win (car windows))
- (setq windows (cdr windows)))))))
- (if win
- (select-window win))
- win))
-
-
-;;}}}
-;;{{{ Redisplay
-
-;; Redraw all the windows on the screen, starting with the top window.
-;; The window used as as marker is WIN, or the selcted window if WIN
-;; is nil.
-
-(defun follow-redisplay (&optional windows win)
- "Reposition the WINDOWS around WIN.
-Should the point be too close to the roof we redisplay everything
-from the top. WINDOWS should contain a list of windows to
-redisplay, it is assumed that WIN is a member of the list.
-Should WINDOWS be nil, the windows displaying the
-same buffer as WIN, in the current frame, are used.
-Should WIN be nil, the selected window is used."
- (or win
- (setq win (selected-window)))
- (or windows
- (setq windows (follow-all-followers win)))
- (follow-downward windows (follow-calculate-first-window-start windows win)))
-
-
-;; Redisplay a chain of windows. Start every window directly after the
-;; end of the previous window, to make sure long lines are displayed
-;; correctly.
-
-(defun follow-downward (windows pos)
- "Redisplay all WINDOWS starting at POS."
- (while windows
- (set-window-start (car windows) pos)
- (setq pos (car (follow-calc-win-end (car windows))))
- (setq windows (cdr windows))))
-
-
-;;(defun follow-downward (windows pos)
-;; "Redisplay all WINDOWS starting at POS."
-;; (let (p)
-;; (while windows
-;; (setq p (window-point (car windows)))
-;; (set-window-start (car windows) pos)
-;; (set-window-point (car windows) (max p pos))
-;; (setq pos (car (follow-calc-win-end (car windows))))
-;; (setq windows (cdr windows)))))
-
-
-;; Return the start of the first window.
-;;
-;; First, estimate the position. It the value is not perfect (i.e. we
-;; have somewhere splited a line between windows) we try to enhance
-;; the value.
-;;
-;; The guess is always perfect if no long lines is split between
-;; windows.
-;;
-;; The worst case peformace of probably very bad, but it is very
-;; unlikely that we ever will miss the correct start by more than one
-;; or two lines.
-
-(defun follow-calculate-first-window-start (windows &optional win start)
- "Calculate the start of the first window.
-
-WINDOWS is a chain of windows to work with. WIN is the window
-to recenter around. It is assumed that WIN starts at position
-START."
- (or win
- (setq win (selected-window)))
- (or start
- (setq start (window-start win)))
- (let ((guess (follow-estimate-first-window-start windows win start)))
- (if (car guess)
- (cdr guess)
- ;; The guess wasn't exact, try to enhance it.
- (let ((win-start (follow-calc-win-start windows (cdr guess) win)))
- (cond ((= win-start start)
- (follow-debug-message "exact")
- (cdr guess))
- ((< win-start start)
- (follow-debug-message "above")
- (follow-calculate-first-window-start-from-above
- windows (cdr guess) win start))
- (t
- (follow-debug-message "below")
- (follow-calculate-first-window-start-from-below
- windows (cdr guess) win start)))))))
-
-
-;; `exact' is disabled due to XEmacs and fonts of variable
-;; height.
-(defun follow-estimate-first-window-start (windows win start)
- "Estimate the position of the first window.
-
-Returns (EXACT . POS). If EXACT is non-nil, POS is the starting
-position of the first window. Otherwise it is a good guess."
- (let ((pred (car (follow-split-followers windows win)))
- (exact nil))
- (save-excursion
- (goto-char start)
- ;(setq exact (bolp))
- (vertical-motion 0 win)
- (while pred
- (vertical-motion (- 1 (window-height (car pred))) (car pred))
- (if (not (bolp))
- (setq exact nil))
- (setq pred (cdr pred)))
- (cons exact (point)))))
-
-
-;; Find the starting point, start at GUESS and search downward.
-;; The returned point is always a point below GUESS.
-
-(defun follow-calculate-first-window-start-from-above
- (windows guess win start)
- (save-excursion
- (let ((done nil)
- win-start
- res)
- (goto-char guess)
- (while (not done)
- (if (not (= (vertical-motion 1 (car windows)) 1))
- ;; Hit bottom! (Can we really do this?)
- ;; We'll keep it, since it ensures termination.
- (progn
- (setq done t)
- (setq res (point-max)))
- (setq win-start (follow-calc-win-start windows (point) win))
- (if (>= win-start start)
- (progn
- (setq done t)
- (setq res (point))))))
- res)))
-
-
-;; Find the starting point, start at GUESS and search upward. Return
-;; a point on the same line as GUESS, or above.
-;;
-;; (Is this ever used? I must make sure it works just in case it is
-;; ever called.)
-
-(defun follow-calculate-first-window-start-from-below
- (windows guess &optional win start)
- (setq win (or win (selected-window)))
- (setq start (or start (window-start win)))
- (save-excursion
- (let ((done nil)
- win-start
- res)
- ;; Always calculate what happend when no line is displayed in the first
- ;; window. (The `previous' res is needed below!)
- (goto-char guess)
- (vertical-motion 0 (car windows))
- (setq res (point))
- (while (not done)
- (if (not (= (vertical-motion -1 (car windows)) -1))
- ;; Hit roof!
- (progn
- (setq done t)
- (setq res (point-min)))
- (setq win-start (follow-calc-win-start windows (point) win))
- (cond ((= win-start start) ; Perfect match, use this value
- (setq done t)
- (setq res (point)))
- ((< win-start start) ; Walked to far, use preious result
- (setq done t))
- (t ; Store result for next iteration
- (setq res (point))))))
- res)))
-
-;;}}}
-;;{{{ Avoid tail recenter
-
-;; This sets the window internal flag `force_start'. The effect is that
-;; windows only displaying the tail isn't recentered.
-;; Has to be called before every redisplay... (Great isn't it?)
-;;
-;; XEmacs doesn't recenter the tail, GOOD!
-;;
-;; A window displaying only the tail, is a windows whose
-;; window-start position is equal to (point-max) of the buffer it
-;; displays.
-;;
-;; This function is also added to `post-command-idle-hook', introduced
-;; in Emacs 19.30. This is needed since the vaccine injected by the
-;; call from `post-command-hook' only works until the next redisplay.
-;; It is possible that the functions in the `post-command-idle-hook'
-;; can cause a redisplay, and hence a new vaccine is needed.
-;;
-;; Sometimes, calling this function could actually cause a redisplay,
-;; especially if it is placed in the debug filter section. I must
-;; investigate this further...
-
-(defun follow-avoid-tail-recenter (&rest rest)
- "Make sure windows displaying the end of a buffer aren't recentered.
-
-This is done by reading and rewriting the start positon of
-non-first windows in Follow Mode."
- (if follow-avoid-tail-recenter-p
- (let* ((orig-buffer (current-buffer))
- (top (frame-first-window (selected-frame)))
- (win top)
- (who '()) ; list of (buffer . frame)
- start
- pair) ; (buffer . frame)
- ;; If the only window in the frame is a minibuffer
- ;; window, `next-window' will never find it again...
- (if (window-minibuffer-p top)
- nil
- (while ;; look, no body!
- (progn
- (setq start (window-start win))
- (set-buffer (window-buffer win))
- (setq pair (cons (window-buffer win) (window-frame win)))
- (if (member pair who)
- (if (and (boundp 'follow-mode) follow-mode
- (eq (point-max) start))
- ;; Write the same window start back, but don't
- ;; set the NOFORCE flag.
- (set-window-start win start))
- (setq who (cons pair who)))
- (setq win (next-window win 'not t))
- (not (eq win top)))) ;; Loop while this is true.
- (set-buffer orig-buffer)))))
-
-;;}}}
-
-;;}}}
-;;{{{ Post Command Hook
-
-;;; The magic little box. This function is called after every command.
-
-;; This is not as complicated as it seems. It is simply a list of common
-;; display situations and the actions to take, plus commands for redrawing
-;; the screen if it should be unaligned.
-;;
-;; We divide the check into two parts; whether we are at the end or not.
-;; This is due to the fact that the end can actaually be visible
-;; in several window even though they are aligned.
-
-(defun follow-post-command-hook ()
- "Ensure that the windows in Follow mode are adjecent after each command."
- (setq follow-inside-post-command-hook t)
- (if (or (not (input-pending-p))
- ;; Sometimes, in XEmacs, mouse events are not handled
- ;; properly by `input-pending-p'. A typical example is
- ;; when clicking on a node in `info'.
- (and (boundp 'current-mouse-event)
- (symbol-value 'current-mouse-event)
- (fboundp 'button-event-p)
- (funcall (symbol-function 'button-event-p)
- (symbol-value 'current-mouse-event))))
- ;; Work in the selected window, not in the current buffer.
- (let ((orig-buffer (current-buffer))
- (win (selected-window)))
- (set-buffer (window-buffer win))
- (or (and (symbolp this-command)
- (get this-command 'follow-mode-use-cache))
- (follow-invalidate-cache))
- (if (and (boundp 'follow-mode) follow-mode
- (not (window-minibuffer-p win)))
- ;; The buffer shown in the selected window is in follow
- ;; mode, lets find the current state of the display and
- ;; cache the result for speed (i.e. `aligned' and `visible'.)
- (let* ((windows (inline (follow-all-followers win)))
- (dest (point))
- (win-start-end (inline
- (follow-update-window-start (car windows))
- (follow-windows-start-end windows)))
- (aligned (follow-windows-aligned-p win-start-end))
- (visible (follow-pos-visible dest win win-start-end)))
- (if (not (and aligned visible))
- (follow-invalidate-cache))
- (inline (follow-avoid-tail-recenter))
- ;; Select a window to display the point.
- (or follow-internal-force-redisplay
- (progn
- (if (eq dest (point-max))
- ;; We're at the end, we have be be careful since
- ;; the display can be aligned while `dest' can
- ;; be visible in several windows.
- (cond
- ;; Select the current window, but only when
- ;; the display is correct. (When inserting
- ;; character in a tail window, the display is
- ;; not correct, as they are shown twice.)
- ;;
- ;; Never stick to the current window after a
- ;; deletion. The reason is cosmetic, when
- ;; typing `DEL' in a window showing only the
- ;; end of the file, character are removed
- ;; from the window above, which is very
- ;; unintuitive.
- ((and visible
- aligned
- (not (memq this-command
- '(backward-delete-char
- delete-backward-char
- backward-delete-char-untabify
- kill-region))))
- (follow-debug-message "Max: same"))
- ;; If the end is visible, and the window
- ;; doesn't seems like it just has been moved,
- ;; select it.
- ((follow-select-if-end-visible win-start-end)
- (follow-debug-message "Max: end visible")
- (setq visible t)
- (setq aligned nil)
- (goto-char dest))
- ;; Just show the end...
- (t
- (follow-debug-message "Max: default")
- (select-window (car (reverse windows)))
- (goto-char dest)
- (setq visible nil)
- (setq aligned nil)))
-
- ;; We're not at the end, here life is much simpler.
- (cond
- ;; This is the normal case!
- ;; It should be optimized for speed.
- ((and visible aligned)
- (follow-debug-message "same"))
- ;; Pick a position in any window. If the
- ;; display is ok, this will pick the `correct'
- ;; window. If the display is wierd do this
- ;; anyway, this will be the case after a delete
- ;; at the beginning of the window.
- ((follow-select-if-visible dest win-start-end)
- (follow-debug-message "visible")
- (setq visible t)
- (goto-char dest))
- ;; Not visible anywhere else, lets pick this one.
- ;; (Is this case used?)
- (visible
- (follow-debug-message "visible in selected."))
- ;; Far out!
- ((eq dest (point-min))
- (follow-debug-message "min")
- (select-window (car windows))
- (goto-char dest)
- (set-window-start (selected-window) (point-min))
- (setq win-start-end (follow-windows-start-end windows))
- (follow-invalidate-cache)
- (setq visible t)
- (setq aligned nil))
- ;; If we can position the cursor without moving the first
- ;; window, do it. This is the case which catches `RET'
- ;; at the bottom of a window.
- ((follow-select-if-visible-from-first dest windows)
- (follow-debug-message "Below first")
- (setq visible t)
- (setq aligned t)
- (follow-redisplay windows (car windows))
- (goto-char dest))
- ;; None of the above. For simplicity, we stick to the
- ;; selected window.
- (t
- (follow-debug-message "None")
- (setq visible nil)
- (setq aligned nil))))
- ;; If a new window has been selected, make sure that the
- ;; old is not scrolled when the point is outside the
- ;; window.
- (or (eq win (selected-window))
- (let ((p (window-point win)))
- (set-window-start win (window-start win) nil)
- (set-window-point win p)))))
- ;; Make sure the point is visible in the selected window.
- ;; (This could lead to a scroll.)
- (if (or visible
- (follow-pos-visible dest win win-start-end))
- nil
- (sit-for 0)
- (follow-avoid-tail-recenter)
- (setq win-start-end (follow-windows-start-end windows))
- (follow-invalidate-cache)
- (setq aligned nil))
- ;; Redraw the windows whenever needed.
- (if (or follow-internal-force-redisplay
- (not (or aligned
- (follow-windows-aligned-p win-start-end)))
- (not (inline (follow-point-visible-all-windows-p
- win-start-end))))
- (progn
- (setq follow-internal-force-redisplay nil)
- (follow-redisplay windows (selected-window))
- (setq win-start-end (follow-windows-start-end windows))
- (follow-invalidate-cache)
- ;; When the point ends up in another window. This
- ;; happends when dest is in the beginning of the
- ;; file and the selected window is not the first.
- ;; It can also, in rare situations happend when
- ;; long lines are used and there is a big
- ;; difference between the width of the windows.
- ;; (When scrolling one line in a wide window which
- ;; will cause a move larger that an entire small
- ;; window.)
- (if (follow-pos-visible dest win win-start-end)
- nil
- (follow-select-if-visible dest win-start-end)
- (goto-char dest))))
-
- ;; If the region is visible, make it look good when spanning
- ;; multiple windows.
- (if (or (and (boundp 'mark-active) (symbol-value 'mark-active))
- (and (fboundp 'region-active-p)
- (funcall (symbol-function 'region-active-p))))
- (follow-maximize-region
- (selected-window) windows win-start-end))
-
- (inline (follow-avoid-tail-recenter))
- ;; DEBUG
- ;;(if (not (follow-windows-aligned-p
- ;; (follow-windows-start-end windows)))
- ;; (message "follow-mode: windows still unaligend!"))
- ;; END OF DEBUG
- ) ; Matches (let*
- ;; Buffer not in follow mode:
- ;; We still must update the windows displaying the tail so that
- ;; Emacs won't recenter them.
- (follow-avoid-tail-recenter))
- (set-buffer orig-buffer)))
- (setq follow-inside-post-command-hook nil))
-
-;;}}}
-;;{{{ The region
-
-;; Tries to make the highlighted area representing the region look
-;; good when spanning several windows.
-;;
-;; Not perfect, as the point can't be placed at window end, only at
-;; end-1. Whis will highlight a little bit in windows above
-;; the current.
-
-(defun follow-maximize-region (win windows win-start-end)
- "Make a highlighted region stretching multiple windows look good
-when in Follow mode."
- (let* ((all (follow-split-followers windows win))
- (pred (car all))
- (succ (cdr all))
- data)
- (while pred
- (setq data (assq (car pred) win-start-end))
- (set-window-point (car pred) (max (nth 1 data) (- (nth 2 data) 1)))
- (setq pred (cdr pred)))
- (while succ
- (set-window-point (car succ) (nth 1 (assq (car succ) win-start-end)))
- (setq succ (cdr succ)))))
-
-;;}}}
-;;{{{ Scroll bar
-
-;;;; Scroll-bar support code.
-
-;;; Why is it needed? Well, if the selected window is in follow mode,
-;;; all its follower stick to it blindly. If one of them is scrolled,
-;;; it immediately returns to the original position when the mouse is
-;;; released. If the selected window is not a follower of the dragged
-;;; window the windows will be unaligned.
-
-;;; The advices doesn't get compiled. Aestetically, this might be a
-;;; problem but in practical life it isn't.
-
-;;; Discussion: Now when the other windows in the chain follow the
-;;; dragged, should we really select it?
-
-(cond ((fboundp 'scroll-bar-drag)
- ;;;
- ;;; Emacs 19 style scrollbars.
- ;;;
-
- ;; Select the dragged window if it is a follower of the
- ;; selected window.
- ;;
- ;; Generate advices of the form:
- ;; (defadvice scroll-bar-drag (after follow-scroll-bar-drag activate)
- ;; "Adviced by `follow-mode'."
- ;; (follow-redraw-after-event (ad-get-arg 0)))
- (let ((cmds '(scroll-bar-drag
- scroll-bar-drag-1 ; Executed at every move.
- scroll-bar-scroll-down
- scroll-bar-scroll-up
- scroll-bar-set-window-start)))
- (while cmds
- (eval
- (` (defadvice (, (intern (symbol-name (car cmds))))
- (after
- (, (intern (concat "follow-" (symbol-name (car cmds)))))
- activate)
- "Adviced by Follow Mode."
- (follow-redraw-after-event (ad-get-arg 0)))))
- (setq cmds (cdr cmds))))
-
-
- (defun follow-redraw-after-event (event)
- "Adviced by Follow mode."
- (condition-case nil
- (let* ((orig-win (selected-window))
- (win (nth 0 (funcall
- (symbol-function 'event-start) event)))
- (fmode (assq 'follow-mode
- (buffer-local-variables
- (window-buffer win)))))
- (if (and fmode (cdr fmode))
- ;; The selected window is in follow-mode
- (progn
- ;; Recenter around the dragged window.
- (select-window win)
- (follow-redisplay)
- (select-window orig-win))))
- (error nil))))
-
-
- ((fboundp 'scrollbar-vertical-drag)
- ;;;
- ;;; XEmacs style scrollbars.
- ;;;
-
- ;; Advice all scrollbar functions on the form:
- ;;
- ;; (defadvice scrollbar-line-down
- ;; (after follow-scrollbar-line-down activate)
- ;; (follow-xemacs-scrollbar-support (ad-get-arg 0)))
-
- (let ((cmds '(scrollbar-line-down ; Window
- scrollbar-line-up
- scrollbar-page-down ; Object
- scrollbar-page-up
- scrollbar-to-bottom ; Window
- scrollbar-to-top
- scrollbar-vertical-drag ; Object
- )))
-
- (while cmds
- (eval
- (` (defadvice (, (intern (symbol-name (car cmds))))
- (after
- (, (intern (concat "follow-" (symbol-name (car cmds)))))
- activate)
- "Adviced by `follow-mode'."
- (follow-xemacs-scrollbar-support (ad-get-arg 0)))))
- (setq cmds (cdr cmds))))
-
-
- (defun follow-xemacs-scrollbar-support (window)
- "Redraw windows showing the same buffer as shown in WINDOW.
-WINDOW is either the dragged window, or a cons containing the
-window as its first element. This is called while the user drags
-the scrollbar.
-
-WINDOW can be an object or a window."
- (condition-case nil
- (progn
- (if (consp window)
- (setq window (car window)))
- (let ((fmode (assq 'follow-mode
- (buffer-local-variables
- (window-buffer window))))
- (orig-win (selected-window)))
- (if (and fmode (cdr fmode))
- (progn
- ;; Recenter around the dragged window.
- (select-window window)
- (follow-redisplay)
- (select-window orig-win)))))
- (error nil)))))
-
-;;}}}
-;;{{{ Process output
-
-;;; The following sections installs a spy which listens to process
-;;; output and tries to reposition the windows whose buffers are in
-;;; Follow mode. We play safe as much as possible...
-;;;
-;;; When follow-mode is activated all active processes are
-;;; intercepted. All new processes which change their filter function
-;;; using `set-process-filter' are also intercepted. The reason is
-;;; that a process can cause a redisplay recentering "tail" windows.
-;;; Note that it doesn't hurt to spy on more processes than needed.
-;;;
-;;; Technically, we set the process filter to `follow-generic-filter'.
-;;; The original filter is stored in `follow-process-filter-alist'.
-;;; Our generic filter calls the original filter, or inserts the
-;;; output into the buffer, if the buffer originally didn't have an
-;;; output filter. It also makes sure that the windows connected to
-;;; the buffer are aligned.
-;;;
-;;; Discussion: How to we find processes which doesn't call
-;;; `set-process-filter'? (How often are processes created in a
-;;; buffer after Follow mode are activated?)
-;;;
-;;; Discussion: Should we also advice `process-filter' to make our
-;;; filter invisible to others?
-
-;;{{{ Advice for `set-process-filter'
-
-;; Do not call this with 'follow-generic-filter as the name of the
-;; filter...
-
-(defadvice set-process-filter (before follow-set-process-filter activate)
- "Follow Mode listens to calls to this function to make
-sure process output will be displayed correctly in buffers
-in which the mode is activated.
-
-Follow Mode inserts its own process filter to do its
-magic stuff before the real process filter is called."
- (if follow-intercept-processes
- (progn
- (setq follow-process-filter-alist
- (delq (assq (ad-get-arg 0) follow-process-filter-alist)
- follow-process-filter-alist))
- (follow-tidy-process-filter-alist)
- (cond ((eq (ad-get-arg 1) t))
- ((eq (ad-get-arg 1) nil)
- (ad-set-arg 1 'follow-generic-filter))
- (t
- (setq follow-process-filter-alist
- (cons (cons (ad-get-arg 0) (ad-get-arg 1))
- follow-process-filter-alist))
- (ad-set-arg 1 'follow-generic-filter))))))
-
-
-(defun follow-call-set-process-filter (proc filter)
- "Call original `set-process-filter' without the Follow mode advice."
- (ad-disable-advice 'set-process-filter 'before
- 'follow-set-process-filter)
- (ad-activate 'set-process-filter)
- (prog1
- (set-process-filter proc filter)
- (ad-enable-advice 'set-process-filter 'before
- 'follow-set-process-filter)
- (ad-activate 'set-process-filter)))
-
-
-(defadvice process-filter (after follow-process-filter activate)
- "Normally when Follow mode is activated all processes has the
-process filter set to `follow-generic-filter'. With this advice,
-the original process filter is returned."
- (cond ((eq ad-return-value 'follow-generic-filter)
- (setq ad-return-value
- (cdr-safe (assq (ad-get-arg 0)
- follow-process-filter-alist))))))
-
-
-(defun follow-call-process-filter (proc)
- "Call original `process-filter' without the Follow mode advice."
- (ad-disable-advice 'process-filter 'after
- 'follow-process-filter)
- (ad-activate 'process-filter)
- (prog1
- (process-filter proc)
- (ad-enable-advice 'process-filter 'after
- 'follow-process-filter)
- (ad-activate 'process-filter)))
-
-
-(defun follow-tidy-process-filter-alist ()
- "Remove old processes from `follow-process-filter-alist'."
- (let ((alist follow-process-filter-alist)
- (ps (process-list))
- (new ()))
- (while alist
- (if (and (not (memq (process-status (car (car alist)))
- '(exit signal closed nil)))
- (memq (car (car alist)) ps))
- (setq new (cons (car alist) new)))
- (setq alist (cdr alist)))
- (setq follow-process-filter-alist new)))
-
-;;}}}
-;;{{{ Start/stop interception of processes.
-
-;; Normally, all new processed are intercepted by our `set-process-filter'.
-;; This is needed to intercept old processed which were started before we were
-;; loaded, and processes we have forgotten by calling
-;; `follow-stop-intercept-process-output'.
-
-(defun follow-intercept-process-output ()
- "Intercept all active processes.
-
-This is needed so that Follow Mode can track all display events in the
-system. (See `follow-mode')"
- (interactive)
- (let ((list (process-list)))
- (while list
- (if (eq (process-filter (car list)) 'follow-generic-filter)
- nil
- ;; The custom `set-process-filter' defined above.
- (set-process-filter (car list) (process-filter (car list))))
- (setq list (cdr list))))
- (setq follow-intercept-processes t))
-
-
-(defun follow-stop-intercept-process-output ()
- "Stop Follow Mode from spying on processes.
-
-All current spypoints are removed and no new will be added.
-
-The effect is that Follow mode won't be able to handle buffers
-connected to processes.
-
-The only reason to call this function is if the Follow mode spy filter
-would interfere with some other package. If this happens, please
-report this using the `follow-submit-feedback' function."
- (interactive)
- (follow-tidy-process-filter-alist)
- (let ((list (process-list)))
- (while list
- (if (eq (process-filter (car list)) 'follow-generic-filter)
- (progn
- (follow-call-set-process-filter
- (car list)
- (cdr-safe (assq (car list) follow-process-filter-alist)))
- (setq follow-process-filter-alist
- (delq (assq (car list) follow-process-filter-alist)
- follow-process-filter-alist))))
- (setq list (cdr list))))
- (setq follow-intercept-processes nil))
-
-;;}}}
-;;{{{ The filter
-
-;;; The following section is a naive method to make buffers with
-;;; process output to work with Follow mode. Whenever the start of the
-;;; window displaying the buffer is moved, we moves it back to its
-;;; original position and try to select a new window. (If we fail,
-;;; the normal redisplay functions of Emacs will scroll it right
-;;; back!)
-
-(defun follow-generic-filter (proc output)
- "Process output filter for process connected to buffers in Follow mode."
- (let* ((old-buffer (current-buffer))
- (orig-win (selected-window))
- (buf (process-buffer proc))
- (win (and buf (if (eq buf (window-buffer orig-win))
- orig-win
- (get-buffer-window buf t))))
- (return-to-orig-win (and win (not (eq win orig-win))))
- (orig-window-start (and win (window-start win))))
-
- ;; If input is pending, the `sit-for' below won't redraw the
- ;; display. In that case, calling `follow-avoid-tail-recenter' may
- ;; provoke the process hadnling code to sceduling a redisplay.
- ;(or (input-pending-p)
- ; (follow-avoid-tail-recenter))
-
- ;; Output the `output'.
- (let ((filter (cdr-safe (assq proc follow-process-filter-alist))))
- (cond
- ;; Call the original filter function
- (filter
- (funcall filter proc output))
-
- ;; No filter, but we've got a buffer. Just output into it.
- (buf
- (set-buffer buf)
- (if (not (marker-buffer (process-mark proc)))
- (set-marker (process-mark proc) (point-max)))
- (let ((moving (= (point) (process-mark proc)))
- (odeactivate (and (boundp 'deactivate-mark)
- (symbol-value 'deactivate-mark)))
- (old-buffer-read-only buffer-read-only))
- (setq buffer-read-only nil)
- (save-excursion
- (goto-char (process-mark proc))
- ;; `insert-before-markers' just in case the users next
- ;; command is M-y.
- (insert-before-markers output)
- (set-marker (process-mark proc) (point)))
- (if moving (goto-char (process-mark proc)))
- (if (boundp 'deactivate-mark)
- ;; This could really be
- ;; (setq deactivate-mark odeactivate)
- ;; but this raises an error when compiling on XEmacs.
- (funcall (symbol-function 'set)
- 'deactivate-mark odeactivate))
- (setq buffer-read-only old-buffer-read-only)))))
-
- ;; If we're in follow mode, do our stuff. Select a new window and
- ;; redisplay. (Actually, it is redundant to check `buf', but I
- ;; feel it's more correct.)
- (if (and buf win (window-live-p win))
- (progn
- (set-buffer buf)
- (if (and (boundp 'follow-mode) follow-mode)
- (progn
- (select-window win)
- (let* ((windows (follow-all-followers win))
- (win-start-end (follow-windows-start-end windows))
- (new-window-start (window-start win))
- (new-window-point (window-point win)))
- (cond
- ;; The window was moved. Move it back and
- ;; select a new. If no better could be found,
- ;; we stick the the new start position. This
- ;; is used when the original process filter
- ;; tries to position the cursor at the bottom
- ;; of the window. Example: `lyskom'.
- ((not (eq orig-window-start new-window-start))
- (follow-debug-message "filter: Moved")
- (set-window-start win orig-window-start)
- (follow-redisplay windows win)
- (setq win-start-end (follow-windows-start-end windows))
- (follow-select-if-visible new-window-point
- win-start-end)
- (goto-char new-window-point)
- (if (eq win (selected-window))
- (set-window-start win new-window-start))
- (setq win-start-end (follow-windows-start-end windows)))
- ;; Stick to this window, if point is visible in it.
- ((pos-visible-in-window-p new-window-point)
- (follow-debug-message "filter: Visible in window"))
- ;; Avoid redisplaying the first window. If the
- ;; point is visible at a window below,
- ;; redisplay and select it.
- ((follow-select-if-visible-from-first
- new-window-point windows)
- (follow-debug-message "filter: Seen from first")
- (follow-redisplay windows (car windows))
- (goto-char new-window-point)
- (setq win-start-end
- (follow-windows-start-end windows)))
- ;; None of the above. We stick to the current window.
- (t
- (follow-debug-message "filter: nothing")))
-
- ;; Here we have slected a window. Make sure the
- ;; windows are aligned and the point is visible
- ;; in the selected window.
- (if (and (not (follow-pos-visible
- (point) (selected-window) win-start-end))
- (not return-to-orig-win))
- (progn
- (sit-for 0)
- (setq win-start-end
- (follow-windows-start-end windows))))
-
- (if (or follow-internal-force-redisplay
- (not (follow-windows-aligned-p win-start-end)))
- (follow-redisplay windows)))))))
-
- ;; return to the original window.
- (if return-to-orig-win
- (select-window orig-win))
- (set-buffer old-buffer))
-
- (follow-invalidate-cache)
-
- ;; Normally, if the display has been changed, it is redrawn. All
- ;; windows showing only the end of a buffer is unconditionally
- ;; recentered, we can't prevent it by calling
- ;; `follow-avoid-tail-recenter'.
- ;;
- ;; By performing a redisplay on our own, Emacs need not perform
- ;; the above described redisplay. (However, bu performing it when
- ;; there are input available just seems to make things worse.)
- (if (and follow-avoid-tail-recenter-p
- (not (input-pending-p)))
- (sit-for 0)))
-
-;;}}}
-
-;;}}}
-;;{{{ Window size change
-
-;; In Emacs 19.29, the functions in `window-size-change-functions' are
-;; called every time a window in a frame changes size. Most notably, it
-;; is called after the frame has been resized.
-;;
-;; We basically call our post-command-hook for every buffer which is
-;; visible in any window in the resized frame, which is in follow-mode.
-;;
-;; Since this function can be called indirectly from
-;; `follow-post-command-hook' we have a potential infinite loop. We
-;; handle this problem by simply not doing anything at all in this
-;; situation. The variable `follow-inside-post-command-hook' contains
-;; information about whether the execution actually is inside the
-;; post-command-hook or not.
-
-(if (boundp 'window-size-change-functions)
- (add-hook 'window-size-change-functions 'follow-window-size-change))
-
-
-(defun follow-window-size-change (frame)
- "Redraw all windows in FRAME, when in Follow mode."
- ;; Below, we call `post-command-hook'. This makes sure that we
- ;; doesn't start a mutally recursive endless loop.
- (if follow-inside-post-command-hook
- nil
- (let ((buffers '())
- (orig-window (selected-window))
- (orig-buffer (current-buffer))
- (orig-frame (selected-frame))
- windows
- buf)
- (select-frame frame)
- (unwind-protect
- (walk-windows
- (function
- (lambda (win)
- (setq buf (window-buffer win))
- (if (memq buf buffers)
- nil
- (set-buffer buf)
- (if (and (boundp 'follow-mode)
- follow-mode)
- (progn
- (setq windows (follow-all-followers win))
- (if (memq orig-window windows)
- (progn
- ;; Make sure we're redrawing around the
- ;; selected window.
- ;;
- ;; We must be really careful not to do this
- ;; when we are (indirectly) called by
- ;; `post-command-hook'.
- (select-window orig-window)
- (follow-post-command-hook)
- (setq orig-window (selected-window)))
- (follow-redisplay windows win))
- (setq buffers (cons buf buffers))))))))
- (select-frame orig-frame)
- (set-buffer orig-buffer)
- (select-window orig-window)))))
-
-;;}}}
-
-;;{{{ XEmacs isearch
-
-;; In XEmacs, isearch often finds matches in other windows than the
-;; currently selected. However, when exiting the old window
-;; configuration is restored, with the exception of the beginning of
-;; the start of the window for the selected window. This is not much
-;; help for us.
-;;
-;; We overwrite the stored window configuration with the current,
-;; unless we are in `slow-search-mode', i.e. only a few lines
-;; of text is visible.
-
-(if follow-emacs-version-xemacs-p
- (defadvice isearch-done (before follow-isearch-done activate)
- (if (and (boundp 'follow-mode)
- follow-mode
- (boundp 'isearch-window-configuration)
- isearch-window-configuration
- (boundp 'isearch-slow-terminal-mode)
- (not isearch-slow-terminal-mode))
- (let ((buf (current-buffer)))
- (setq isearch-window-configuration
- (current-window-configuration))
- (set-buffer buf)))))
-
-;;}}}
-;;{{{ Tail window handling
-
-;;; In Emacs (not XEmacs) windows showing nothing are sometimes
-;;; recentered. When in Follow Mode, this is not desireable for
-;;; non-first windows in the window chain. This section tries to
-;;; make the windows stay where they should be.
-;;;
-;;; If the display is updated, all windows starting at (point-max) are
-;;; going to be recentered at the next redisplay, unless we do a
-;;; read-and-write cycle to update the `force' flag inside the windows.
-;;;
-;;; In 19.30, a new varible `window-scroll-functions' is called every
-;;; time a window is recentered. It is not perfect for our situation,
-;;; since when it is called for a tail window, it is to late. However,
-;;; if it is called for another window, we can try to update our
-;;; windows.
-;;;
-;;; By patching `sit-for' we can make sure that to catch all explicit
-;;; updates initiated by lisp programs. Internal calls, on the other
-;;; hand, are not handled.
-;;;
-;;; Please note that the function `follow-avoid-tail-recenter' is also
-;;; called from other places, e.g. `post-command-hook' and
-;;; `post-command-idle-hook'.
-
-;; If this function is called it is to late for this window, but
-;; we might save other windows from beeing recentered.
-
-(if (and follow-avoid-tail-recenter-p (boundp 'window-scroll-functions))
- (add-hook 'window-scroll-functions 'follow-avoid-tail-recenter t))
-
-
-;; This prevents all packages which calls `sit-for' directly
-;; to recenter tail windows.
-
-(if follow-avoid-tail-recenter-p
- (defadvice sit-for (before follow-sit-for activate)
- "Adviced by Follow Mode.
-
-Avoid to recenter windows displaying only the end of a file as when
-displaying a short file in two windows, using Follow Mode."
- (follow-avoid-tail-recenter)))
-
-
-;; Without this advice, `mouse-drag-region' would start to recenter
-;; tail windows.
-
-(if (and follow-avoid-tail-recenter-p
- (fboundp 'move-overlay))
- (defadvice move-overlay (before follow-move-overlay activate)
- "Adviced by Follow Mode. Don't recenter windows showing only
-the end of a buffer. This prevents `mouse-drag-region' from
-messing things up."
- (follow-avoid-tail-recenter)))
-
-;;}}}
-;;{{{ profile support
-
-;; The following (non-evaluated) section can be used to
-;; profile this package using `elp'.
-;;
-;; Invalid indentation on purpose!
-
-(cond (nil
-(setq elp-function-list
- '(window-end
- vertical-motion
- ; sit-for ;; elp can't handle advices...
- follow-mode
- follow-all-followers
- follow-split-followers
- follow-redisplay
- follow-downward
- follow-calculate-first-window-start
- follow-estimate-first-window-start
- follow-calculate-first-window-start-from-above
- follow-calculate-first-window-start-from-below
- follow-calc-win-end
- follow-calc-win-start
- follow-pos-visible
- follow-windows-start-end
- follow-cache-valid-p
- follow-select-if-visible
- follow-select-if-visible-from-first
- follow-windows-aligned-p
- follow-point-visible-all-windows-p
- follow-avoid-tail-recenter
- follow-update-window-start
- follow-post-command-hook
- ))))
-
-;;}}}
-
-;;{{{ The end
-
-;;;
-;;; We're done!
-;;;
-
-(provide 'follow)
-
-;;}}}
-
-;; /------------------------------------------------------------------------\
-;; | "I [..] am rarely happier then when spending an entire day programming |
-;; | my computer to perform automatically a task that it would otherwise |
-;; | take me a good ten seconds to do by hand. Ten seconds, I tell myself, |
-;; | is ten seconds. Time is valuable and ten seconds' worth of it is well |
-;; | worth the investment of a day's happy activity working out a way to |
-;; | save it". -- Douglas Adams, "Last Chance to See" |
-;; \------------------------------------------------------------------------/
-
-;;; follow.el ends here
diff --git a/lisp/font-lock.el b/lisp/font-lock.el
deleted file mode 100644
index 0117d5f5c94..00000000000
--- a/lisp/font-lock.el
+++ /dev/null
@@ -1,2409 +0,0 @@
-;;; font-lock.el --- Electric font lock mode
-
-;; Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: jwz, then rms, then sm <simon@gnu.ai.mit.edu>
-;; Maintainer: FSF
-;; Keywords: languages, faces
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Font Lock mode is a minor mode that causes your comments to be displayed in
-;; one face, strings in another, reserved words in another, and so on.
-;;
-;; Comments will be displayed in `font-lock-comment-face'.
-;; Strings will be displayed in `font-lock-string-face'.
-;; Regexps are used to display selected patterns in other faces.
-;;
-;; To make the text you type be fontified, use M-x font-lock-mode RET.
-;; When this minor mode is on, the faces of the current line are updated with
-;; every insertion or deletion.
-;;
-;; To turn Font Lock mode on automatically, add this to your ~/.emacs file:
-;;
-;; (add-hook 'emacs-lisp-mode-hook 'turn-on-font-lock)
-;;
-;; Or if you want to turn Font Lock mode on in many modes:
-;;
-;; (global-font-lock-mode t)
-;;
-;; Fontification for a particular mode may be available in a number of levels
-;; of decoration. The higher the level, the more decoration, but the more time
-;; it takes to fontify. See the variable `font-lock-maximum-decoration', and
-;; also the variable `font-lock-maximum-size'. Support modes for Font Lock
-;; mode can be used to speed up Font Lock mode. See `font-lock-support-mode'.
-
-;;; How Font Lock mode supports modes or is supported by modes:
-
-;; Modes that support Font Lock mode do so by defining one or more variables
-;; whose values specify the fontification. Font Lock mode knows of these
-;; variable names from (a) the buffer local variable `font-lock-defaults', if
-;; non-nil, or (b) the global variable `font-lock-defaults-alist', if the major
-;; mode has an entry. (Font Lock mode is set up via (a) where a mode's
-;; patterns are distributed with the mode's package library, and (b) where a
-;; mode's patterns are distributed with font-lock.el itself. An example of (a)
-;; is Pascal mode, an example of (b) is Lisp mode. Normally, the mechanism is
-;; (a); (b) is used where it is not clear which package library should contain
-;; the pattern definitions.) Font Lock mode chooses which variable to use for
-;; fontification based on `font-lock-maximum-decoration'.
-
-;;; Constructing patterns:
-
-;; See the documentation for the variable `font-lock-keywords'.
-;;
-;; Nasty regexps of the form "bar\\(\\|lo\\)\\|f\\(oo\\|u\\(\\|bar\\)\\)\\|lo"
-;; are made thusly: (make-regexp '("foo" "fu" "fubar" "bar" "barlo" "lo")) for
-;; efficiency. See /pub/gnu/emacs/elisp-archive/functions/make-regexp.el.Z on
-;; archive.cis.ohio-state.edu for this and other functions not just by simon.
-
-;;; Adding patterns for modes that already support Font Lock:
-
-;; Though Font Lock highlighting patterns already exist for many modes, it's
-;; likely there's something that you want fontified that currently isn't, even
-;; at the maximum fontification level. You can add highlighting patterns via
-;; `font-lock-add-keywords'. For example, say in some C
-;; header file you #define the token `and' to expand to `&&', etc., to make
-;; your C code almost readable. In your ~/.emacs there could be:
-;;
-;; (font-lock-add-keywords 'c-mode '("\\<\\(and\\|or\\|not\\)\\>"))
-;;
-;; Some modes provide specific ways to modify patterns based on the values of
-;; other variables. For example, additional C types can be specified via the
-;; variable `c-font-lock-extra-types'.
-
-;;; Adding patterns for modes that do not support Font Lock:
-
-;; Not all modes support Font Lock mode. If you (as a user of the mode) add
-;; patterns for a new mode, you must define in your ~/.emacs a variable or
-;; variables that specify regexp fontification. Then, you should indicate to
-;; Font Lock mode, via the mode hook setting `font-lock-defaults', exactly what
-;; support is required. For example, say Foo mode should have the following
-;; regexps fontified case-sensitively, and comments and strings should not be
-;; fontified automagically. In your ~/.emacs there could be:
-;;
-;; (defvar foo-font-lock-keywords
-;; '(("\\<\\(one\\|two\\|three\\)\\>" . font-lock-keyword-face)
-;; ("\\<\\(four\\|five\\|six\\)\\>" . font-lock-type-face))
-;; "Default expressions to highlight in Foo mode.")
-;;
-;; (add-hook 'foo-mode-hook
-;; (function (lambda ()
-;; (make-local-variable 'font-lock-defaults)
-;; (setq font-lock-defaults '(foo-font-lock-keywords t)))))
-
-;;; Adding Font Lock support for modes:
-
-;; Of course, it would be better that the mode already supports Font Lock mode.
-;; The package author would do something similar to above. The mode must
-;; define at the top-level a variable or variables that specify regexp
-;; fontification. Then, the mode command should indicate to Font Lock mode,
-;; via `font-lock-defaults', exactly what support is required. For example,
-;; say Bar mode should have the following regexps fontified case-insensitively,
-;; and comments and strings should be fontified automagically. In bar.el there
-;; could be:
-;;
-;; (defvar bar-font-lock-keywords
-;; '(("\\<\\(uno\\|due\\|tre\\)\\>" . font-lock-keyword-face)
-;; ("\\<\\(quattro\\|cinque\\|sei\\)\\>" . font-lock-type-face))
-;; "Default expressions to highlight in Bar mode.")
-;;
-;; and within `bar-mode' there could be:
-;;
-;; (make-local-variable 'font-lock-defaults)
-;; (setq font-lock-defaults '(bar-font-lock-keywords nil t))
-
-;; What is fontification for? You might say, "It's to make my code look nice."
-;; I think it should be for adding information in the form of cues. These cues
-;; should provide you with enough information to both (a) distinguish between
-;; different items, and (b) identify the item meanings, without having to read
-;; the items and think about it. Therefore, fontification allows you to think
-;; less about, say, the structure of code, and more about, say, why the code
-;; doesn't work. Or maybe it allows you to think less and drift off to sleep.
-;;
-;; So, here are my opinions/advice/guidelines:
-;;
-;; - Highlight conceptual objects, such as function and variable names, and
-;; different objects types differently, i.e., (a) and (b) above, highlight
-;; function names differently to variable names.
-;; - Keep the faces distinct from each other as far as possible.
-;; i.e., (a) above.
-;; - Use the same face for the same conceptual object, across all modes.
-;; i.e., (b) above, all modes that have items that can be thought of as, say,
-;; keywords, should be highlighted with the same face, etc.
-;; - Make the face attributes fit the concept as far as possible.
-;; i.e., function names might be a bold colour such as blue, comments might
-;; be a bright colour such as red, character strings might be brown, because,
-;; err, strings are brown (that was not the reason, please believe me).
-;; - Don't use a non-nil OVERRIDE unless you have a good reason.
-;; Only use OVERRIDE for special things that are easy to define, such as the
-;; way `...' quotes are treated in strings and comments in Emacs Lisp mode.
-;; Don't use it to, say, highlight keywords in commented out code or strings.
-;; - Err, that's it.
-
-;;; Code:
-
-;; User variables.
-
-(defvar font-lock-verbose (* 0 1024)
- "*If non-nil, means show status messages for buffer fontification.
-If a number, only buffers greater than this size have fontification messages.")
-
-;;;###autoload
-(defvar font-lock-maximum-decoration nil
- "*Maximum decoration level for fontification.
-If nil, use the default decoration (typically the minimum available).
-If t, use the maximum decoration available.
-If a number, use that level of decoration (or if not available the maximum).
-If a list, each element should be a cons pair of the form (MAJOR-MODE . LEVEL),
-where MAJOR-MODE is a symbol or t (meaning the default). For example:
- ((c-mode . t) (c++-mode . 2) (t . 1))
-means use the maximum decoration available for buffers in C mode, level 2
-decoration for buffers in C++ mode, and level 1 decoration otherwise.")
-
-;;;###autoload
-(defvar font-lock-maximum-size (* 250 1024)
- "*Maximum size of a buffer for buffer fontification.
-Only buffers less than this can be fontified when Font Lock mode is turned on.
-If nil, means size is irrelevant.
-If a list, each element should be a cons pair of the form (MAJOR-MODE . SIZE),
-where MAJOR-MODE is a symbol or t (meaning the default). For example:
- ((c-mode . 256000) (c++-mode . 256000) (rmail-mode . 1048576))
-means that the maximum size is 250K for buffers in C or C++ modes, one megabyte
-for buffers in Rmail mode, and size is irrelevant otherwise.")
-
-;; Fontification variables:
-
-;; Originally these variable values were face names such as `bold' etc.
-;; Now we create our own faces, but we keep these variables for compatibility
-;; and they give users another mechanism for changing face appearance.
-;; We now allow a FACENAME in `font-lock-keywords' to be any expression that
-;; returns a face. So the easiest thing is to continue using these variables,
-;; rather than sometimes evaling FACENAME and sometimes not.
-(defvar font-lock-comment-face 'font-lock-comment-face
- "Face to use for comments.")
-
-(defvar font-lock-string-face 'font-lock-string-face
- "Face to use for strings.")
-
-(defvar font-lock-keyword-face 'font-lock-keyword-face
- "Face to use for keywords.")
-
-(defvar font-lock-builtin-face 'font-lock-builtin-face
- "Face to use for builtins.")
-
-(defvar font-lock-function-name-face 'font-lock-function-name-face
- "Face to use for function names.")
-
-(defvar font-lock-variable-name-face 'font-lock-variable-name-face
- "Face to use for variable names.")
-
-(defvar font-lock-type-face 'font-lock-type-face
- "Face to use for type names.")
-
-(defvar font-lock-reference-face 'font-lock-reference-face
- "Face to use for reference names.")
-
-(defvar font-lock-warning-face 'font-lock-warning-face
- "Face to use for things that should stand out.")
-
-(defvar font-lock-keywords nil
- "*A list of the keywords to highlight.
-Each element should be of the form:
-
- MATCHER
- (MATCHER . MATCH)
- (MATCHER . FACENAME)
- (MATCHER . HIGHLIGHT)
- (MATCHER HIGHLIGHT ...)
- (eval . FORM)
-
-where HIGHLIGHT should be either MATCH-HIGHLIGHT or MATCH-ANCHORED.
-
-FORM is an expression, whose value should be a keyword element, evaluated when
-the keyword is (first) used in a buffer. This feature can be used to provide a
-keyword that can only be generated when Font Lock mode is actually turned on.
-
-For highlighting single items, typically only MATCH-HIGHLIGHT is required.
-However, if an item or (typically) items are to be highlighted following the
-instance of another item (the anchor) then MATCH-ANCHORED may be required.
-
-MATCH-HIGHLIGHT should be of the form:
-
- (MATCH FACENAME OVERRIDE LAXMATCH)
-
-Where MATCHER can be either the regexp to search for, or the function name to
-call to make the search (called with one argument, the limit of the search).
-MATCH is the subexpression of MATCHER to be highlighted. FACENAME is an
-expression whose value is the face name to use. FACENAME's default attributes
-may be defined in `font-lock-face-attributes'.
-
-OVERRIDE and LAXMATCH are flags. If OVERRIDE is t, existing fontification may
-be overwritten. If `keep', only parts not already fontified are highlighted.
-If `prepend' or `append', existing fontification is merged with the new, in
-which the new or existing fontification, respectively, takes precedence.
-If LAXMATCH is non-nil, no error is signaled if there is no MATCH in MATCHER.
-
-For example, an element of the form highlights (if not already highlighted):
-
- \"\\\\\\=<foo\\\\\\=>\" Discrete occurrences of \"foo\" in the value of the
- variable `font-lock-keyword-face'.
- (\"fu\\\\(bar\\\\)\" . 1) Substring \"bar\" within all occurrences of \"fubar\" in
- the value of `font-lock-keyword-face'.
- (\"fubar\" . fubar-face) Occurrences of \"fubar\" in the value of `fubar-face'.
- (\"foo\\\\|bar\" 0 foo-bar-face t)
- Occurrences of either \"foo\" or \"bar\" in the value
- of `foo-bar-face', even if already highlighted.
-
-MATCH-ANCHORED should be of the form:
-
- (MATCHER PRE-MATCH-FORM POST-MATCH-FORM MATCH-HIGHLIGHT ...)
-
-Where MATCHER is as for MATCH-HIGHLIGHT with one exception. The limit of the
-search is currently guaranteed to be (no greater than) the end of the line.
-PRE-MATCH-FORM and POST-MATCH-FORM are evaluated before the first, and after
-the last, instance MATCH-ANCHORED's MATCHER is used. Therefore they can be
-used to initialise before, and cleanup after, MATCHER is used. Typically,
-PRE-MATCH-FORM is used to move to some position relative to the original
-MATCHER, before starting with MATCH-ANCHORED's MATCHER. POST-MATCH-FORM might
-be used to move, before resuming with MATCH-ANCHORED's parent's MATCHER.
-
-For example, an element of the form highlights (if not already highlighted):
-
- (\"\\\\\\=<anchor\\\\\\=>\" (0 anchor-face) (\"\\\\\\=<item\\\\\\=>\" nil nil (0 item-face)))
-
- Discrete occurrences of \"anchor\" in the value of `anchor-face', and subsequent
- discrete occurrences of \"item\" (on the same line) in the value of `item-face'.
- (Here PRE-MATCH-FORM and POST-MATCH-FORM are nil. Therefore \"item\" is
- initially searched for starting from the end of the match of \"anchor\", and
- searching for subsequent instance of \"anchor\" resumes from where searching
- for \"item\" concluded.)
-
-Note that the MATCH-ANCHORED feature is experimental; in the future, we may
-replace it with other ways of providing this functionality.
-
-These regular expressions should not match text which spans lines. While
-\\[font-lock-fontify-buffer] handles multi-line patterns correctly, updating
-when you edit the buffer does not, since it considers text one line at a time.
-
-Be very careful composing regexps for this list;
-the wrong pattern can dramatically slow things down!")
-(make-variable-buffer-local 'font-lock-keywords)
-
-;; This variable is used by mode packages that support Font Lock mode by
-;; defining their own keywords to use for `font-lock-keywords'. (The mode
-;; command should make it buffer-local and set it to provide the set up.)
-(defvar font-lock-defaults nil
- "If set by a major mode, should be the defaults for Font Lock mode.
-The value should be like the `cdr' of an item in `font-lock-defaults-alist'.")
-
-;; This variable is used where font-lock.el itself supplies the keywords.
-(defvar font-lock-defaults-alist
- (let (;; We use `beginning-of-defun', rather than nil, for SYNTAX-BEGIN.
- ;; Thus the calculation of the cache is usually faster but not
- ;; infallible, so we risk mis-fontification. sm.
- (c-mode-defaults
- '((c-font-lock-keywords c-font-lock-keywords-1
- c-font-lock-keywords-2 c-font-lock-keywords-3)
- nil nil ((?_ . "w")) beginning-of-defun
- (font-lock-comment-start-regexp . "/[*/]")
- (font-lock-mark-block-function . mark-defun)))
- (c++-mode-defaults
- '((c++-font-lock-keywords c++-font-lock-keywords-1
- c++-font-lock-keywords-2 c++-font-lock-keywords-3)
- nil nil ((?_ . "w") (?~ . "w")) beginning-of-defun
- (font-lock-comment-start-regexp . "/[*/]")
- (font-lock-mark-block-function . mark-defun)))
- (objc-mode-defaults
- '((objc-font-lock-keywords objc-font-lock-keywords-1
- objc-font-lock-keywords-2 objc-font-lock-keywords-3)
- nil nil ((?_ . "w") (?$ . "w")) nil
- (font-lock-comment-start-regexp . "/[*/]")
- (font-lock-mark-block-function . mark-defun)))
- (java-mode-defaults
- '((java-font-lock-keywords java-font-lock-keywords-1
- java-font-lock-keywords-2 java-font-lock-keywords-3)
- nil nil ((?_ . "w") (?$ . "w") (?. . "w")) nil
- (font-lock-comment-start-regexp . "/[*/]")
- (font-lock-mark-block-function . mark-defun)))
- (lisp-mode-defaults
- '((lisp-font-lock-keywords
- lisp-font-lock-keywords-1 lisp-font-lock-keywords-2)
- nil nil (("+-*/.<>=!?$%_&~^:" . "w")) beginning-of-defun
- (font-lock-comment-start-regexp . ";")
- (font-lock-mark-block-function . mark-defun)))
- (scheme-mode-defaults
- '(scheme-font-lock-keywords
- nil t (("+-*/.<>=!?$%_&~^:" . "w")) beginning-of-defun
- (font-lock-comment-start-regexp . ";")
- (font-lock-mark-block-function . mark-defun)))
- ;; For TeX modes we could use `backward-paragraph' for the same reason.
- ;; But we don't, because paragraph breaks are arguably likely enough to
- ;; occur within a genuine syntactic block to make it too risky.
- ;; However, we do specify a MARK-BLOCK function as that cannot result
- ;; in a mis-fontification even if it might not fontify enough. --sm.
- (tex-mode-defaults
- '(tex-font-lock-keywords nil nil ((?$ . "\"")) nil
- (font-lock-comment-start-regexp . "%")
- (font-lock-mark-block-function . mark-paragraph)))
- )
- (list
- (cons 'c-mode c-mode-defaults)
- (cons 'c++-mode c++-mode-defaults)
- (cons 'objc-mode objc-mode-defaults)
- (cons 'java-mode java-mode-defaults)
- (cons 'emacs-lisp-mode lisp-mode-defaults)
- (cons 'inferior-scheme-mode scheme-mode-defaults)
- (cons 'latex-mode tex-mode-defaults)
- (cons 'lisp-mode lisp-mode-defaults)
- (cons 'lisp-interaction-mode lisp-mode-defaults)
- (cons 'plain-tex-mode tex-mode-defaults)
- (cons 'scheme-mode scheme-mode-defaults)
- (cons 'scheme-interaction-mode scheme-mode-defaults)
- (cons 'slitex-mode tex-mode-defaults)
- (cons 'tex-mode tex-mode-defaults)))
- "Alist of default major mode and Font Lock defaults.
-Each item should be a list of the form:
-
- (MAJOR-MODE . (KEYWORDS KEYWORDS-ONLY CASE-FOLD SYNTAX-ALIST SYNTAX-BEGIN
- ...))
-
-where MAJOR-MODE is a symbol. KEYWORDS may be a symbol (a variable or function
-whose value is the keywords to use for fontification) or a list of symbols.
-If KEYWORDS-ONLY is non-nil, syntactic fontification (strings and comments) is
-not performed. If CASE-FOLD is non-nil, the case of the keywords is ignored
-when fontifying. If SYNTAX-ALIST is non-nil, it should be a list of cons pairs
-of the form (CHAR-OR-STRING . STRING) used to set the local Font Lock syntax
-table, for keyword and syntactic fontification (see `modify-syntax-entry').
-
-If SYNTAX-BEGIN is non-nil, it should be a function with no args used to move
-backwards outside any enclosing syntactic block, for syntactic fontification.
-Typical values are `beginning-of-line' (i.e., the start of the line is known to
-be outside a syntactic block), or `beginning-of-defun' for programming modes or
-`backward-paragraph' for textual modes (i.e., the mode-dependent function is
-known to move outside a syntactic block). If nil, the beginning of the buffer
-is used as a position outside of a syntactic block, in the worst case.
-
-These item elements are used by Font Lock mode to set the variables
-`font-lock-keywords', `font-lock-keywords-only',
-`font-lock-keywords-case-fold-search', `font-lock-syntax-table' and
-`font-lock-beginning-of-syntax-function', respectively.
-
-Further item elements are alists of the form (VARIABLE . VALUE) and are in no
-particular order. Each VARIABLE is made buffer-local before set to VALUE.
-
-Currently, appropriate variables include `font-lock-mark-block-function'.
-If this is non-nil, it should be a function with no args used to mark any
-enclosing block of text, for fontification via \\[font-lock-fontify-block].
-Typical values are `mark-defun' for programming modes or `mark-paragraph' for
-textual modes (i.e., the mode-dependent function is known to put point and mark
-around a text block relevant to that mode).
-
-Other variables include those for buffer-specialised fontification functions,
-`font-lock-fontify-buffer-function', `font-lock-unfontify-buffer-function',
-`font-lock-fontify-region-function', `font-lock-unfontify-region-function',
-`font-lock-comment-start-regexp', `font-lock-inhibit-thing-lock' and
-`font-lock-maximum-size'.")
-
-(defvar font-lock-keywords-alist nil
- "*Alist of `font-lock-keywords' local to a `major-mode'.
-This is normally set via `font-lock-add-keywords'.")
-
-(defvar font-lock-keywords-only nil
- "*Non-nil means Font Lock should not fontify comments or strings.
-This is normally set via `font-lock-defaults'.")
-
-(defvar font-lock-keywords-case-fold-search nil
- "*Non-nil means the patterns in `font-lock-keywords' are case-insensitive.
-This is normally set via `font-lock-defaults'.")
-
-(defvar font-lock-syntax-table nil
- "Non-nil means use this syntax table for fontifying.
-If this is nil, the major mode's syntax table is used.
-This is normally set via `font-lock-defaults'.")
-
-;; If this is nil, we only use the beginning of the buffer if we can't use
-;; `font-lock-cache-position' and `font-lock-cache-state'.
-(defvar font-lock-beginning-of-syntax-function nil
- "*Non-nil means use this function to move back outside of a syntactic block.
-When called with no args it should leave point at the beginning of any
-enclosing syntactic block.
-If this is nil, the beginning of the buffer is used (in the worst case).
-This is normally set via `font-lock-defaults'.")
-
-(defvar font-lock-mark-block-function nil
- "*Non-nil means use this function to mark a block of text.
-When called with no args it should leave point at the beginning of any
-enclosing textual block and mark at the end.
-This is normally set via `font-lock-defaults'.")
-
-(defvar font-lock-comment-start-regexp nil
- "*Regexp to match the start of a comment.
-This need not discriminate between genuine comments and quoted comment
-characters or comment characters within strings.
-If nil, `comment-start-skip' is used instead; see that variable for more info.
-This is normally set via `font-lock-defaults'.")
-
-(defvar font-lock-fontify-buffer-function 'font-lock-default-fontify-buffer
- "Function to use for fontifying the buffer.
-This is normally set via `font-lock-defaults'.")
-
-(defvar font-lock-unfontify-buffer-function 'font-lock-default-unfontify-buffer
- "Function to use for unfontifying the buffer.
-This is used when turning off Font Lock mode.
-This is normally set via `font-lock-defaults'.")
-
-(defvar font-lock-fontify-region-function 'font-lock-default-fontify-region
- "Function to use for fontifying a region.
-It should take two args, the beginning and end of the region, and an optional
-third arg VERBOSE. If non-nil, the function should print status messages.
-This is normally set via `font-lock-defaults'.")
-
-(defvar font-lock-unfontify-region-function 'font-lock-default-unfontify-region
- "Function to use for unfontifying a region.
-It should take two args, the beginning and end of the region.
-This is normally set via `font-lock-defaults'.")
-
-(defvar font-lock-inhibit-thing-lock nil
- "List of Font Lock mode related modes that should not be turned on.
-Currently, valid mode names as `fast-lock-mode' and `lazy-lock-mode'.
-This is normally set via `font-lock-defaults'.")
-
-(defvar font-lock-mode nil) ; For the modeline.
-(defvar font-lock-fontified nil) ; Whether we have fontified the buffer.
-
-;;;###autoload
-(defvar font-lock-mode-hook nil
- "Function or functions to run on entry to Font Lock mode.")
-
-;; Font Lock mode.
-
-(eval-when-compile
- ;;
- ;; We don't do this at the top-level as we only use non-autoloaded macros.
- (require 'cl)
- ;;
- ;; Borrowed from lazy-lock.el.
- ;; We use this to preserve or protect things when modifying text properties.
- (defmacro save-buffer-state (varlist &rest body)
- "Bind variables according to VARLIST and eval BODY restoring buffer state."
- (` (let* ((,@ (append varlist
- '((modified (buffer-modified-p))
- (inhibit-read-only t) (buffer-undo-list t)
- before-change-functions after-change-functions
- deactivate-mark buffer-file-name buffer-file-truename))))
- (,@ body)
- (when (and (not modified) (buffer-modified-p))
- (set-buffer-modified-p nil)))))
- (put 'save-buffer-state 'lisp-indent-function 1))
-
-;;;###autoload
-(defun font-lock-mode (&optional arg)
- "Toggle Font Lock mode.
-With arg, turn Font Lock mode on if and only if arg is positive.
-
-When Font Lock mode is enabled, text is fontified as you type it:
-
- - Comments are displayed in `font-lock-comment-face';
- - Strings are displayed in `font-lock-string-face';
- - Certain other expressions are displayed in other faces according to the
- value of the variable `font-lock-keywords'.
-
-You can enable Font Lock mode in any major mode automatically by turning on in
-the major mode's hook. For example, put in your ~/.emacs:
-
- (add-hook 'c-mode-hook 'turn-on-font-lock)
-
-Alternatively, you can use Global Font Lock mode to automagically turn on Font
-Lock mode in buffers whose major mode supports it and whose major mode is one
-of `font-lock-global-modes'. For example, put in your ~/.emacs:
-
- (global-font-lock-mode t)
-
-There are a number of support modes that may be used to speed up Font Lock mode
-in various ways, specified via the variable `font-lock-support-mode'. Where
-major modes support different levels of fontification, you can use the variable
-`font-lock-maximum-decoration' to specify which level you generally prefer.
-When you turn Font Lock mode on/off the buffer is fontified/defontified, though
-fontification occurs only if the buffer is less than `font-lock-maximum-size'.
-
-For example, to specify that Font Lock mode use use Lazy Lock mode as a support
-mode and use maximum levels of fontification, put in your ~/.emacs:
-
- (setq font-lock-support-mode 'lazy-lock-mode)
- (setq font-lock-maximum-decoration t)
-
-To fontify a buffer, without turning on Font Lock mode and regardless of buffer
-size, you can use \\[font-lock-fontify-buffer].
-
-To fontify a block (the function or paragraph containing point, or a number of
-lines around point), perhaps because modification on the current line caused
-syntactic change on other lines, you can use \\[font-lock-fontify-block].
-
-The default Font Lock mode highlighting are normally selected via the variable
-`font-lock-maximum-decoration'. You can add your own highlighting for some
-mode, by calling `font-lock-add-keywords'.
-
-The default Font Lock mode faces and their attributes are defined in the
-variable `font-lock-face-attributes', and Font Lock mode default settings in
-the variable `font-lock-defaults-alist'. You can set your own default settings
-for some mode, by setting a buffer local value for `font-lock-defaults', via
-its mode hook."
- (interactive "P")
- ;; Don't turn on Font Lock mode if we don't have a display (we're running a
- ;; batch job) or if the buffer is invisible (the name starts with a space).
- (let ((on-p (and (not noninteractive)
- (not (eq (aref (buffer-name) 0) ?\ ))
- (if arg
- (> (prefix-numeric-value arg) 0)
- (not font-lock-mode)))))
- (set (make-local-variable 'font-lock-mode) on-p)
- ;; Turn on Font Lock mode.
- (when on-p
- (make-local-hook 'after-change-functions)
- (add-hook 'after-change-functions 'font-lock-after-change-function nil t)
- (font-lock-set-defaults)
- (font-lock-turn-on-thing-lock)
- (run-hooks 'font-lock-mode-hook)
- ;; Fontify the buffer if we have to.
- (let ((max-size (font-lock-value-in-major-mode font-lock-maximum-size)))
- (cond (font-lock-fontified
- nil)
- ((or (null max-size) (> max-size (buffer-size)))
- (font-lock-fontify-buffer))
- (font-lock-verbose
- (message "Fontifying %s...buffer too big" (buffer-name))))))
- ;; Turn off Font Lock mode.
- (unless on-p
- (remove-hook 'after-change-functions 'font-lock-after-change-function t)
- (font-lock-unfontify-buffer)
- (font-lock-turn-off-thing-lock)
- (font-lock-unset-defaults))
- (force-mode-line-update)))
-
-;;;###autoload
-(defun turn-on-font-lock ()
- "Turn on Font Lock mode conditionally.
-Turn on only if the terminal can display it."
- (when window-system
- (font-lock-mode t)))
-
-;;;###autoload
-(defun font-lock-add-keywords (major-mode keywords &optional append)
- "Add highlighting KEYWORDS for MAJOR-MODE.
-MODE should be a symbol, the major mode command name, such as `c-mode' or nil.
-If nil, highlighting keywords are added for the current buffer.
-KEYWORDS should be a list; see the variable `font-lock-keywords'.
-By default they are added at the beginning of the current highlighting list.
-If optional argument APPEND is `set', they are used to replace the current
-highlighting list. If APPEND has any other value, e.g., t, they are added at
-the end of the current highlighting list.
-
-For example:
-
- (font-lock-add-keywords 'c-mode
- '((\"\\\\\\=<\\\\(FIXME\\\\):\" 1 font-lock-warning-face prepend)
- (\"\\\\\\=<\\\\(and\\\\|or\\\\|not\\\\)\\\\\\=>\" . font-lock-keyword-face)))
-
-adds two fontification patterns for C mode, to fontify `FIXME:' words, even in
-comments, and to fontify `and', `or' and `not' words as keywords."
- (cond (major-mode
- ;; If MAJOR-MODE is non-nil, add the KEYWORDS and APPEND spec to
- ;; `font-lock-keywords-alist' so `font-lock-set-defaults' uses them.
- (let ((spec (cons keywords append)) cell)
- (if (setq cell (assq major-mode font-lock-keywords-alist))
- (setcdr cell (append (cdr cell) (list spec)))
- (push (list major-mode spec) font-lock-keywords-alist))))
- (font-lock-mode
- ;; Otherwise if Font Lock mode is on, set or add the keywords now.
- (if (eq append 'set)
- (setq font-lock-keywords keywords)
- (let ((old (if (eq (car-safe font-lock-keywords) t)
- (cdr font-lock-keywords)
- font-lock-keywords)))
- (setq font-lock-keywords (if append
- (append old keywords)
- (append keywords old))))))))
-
-;; Global Font Lock mode.
-;;
-;; A few people have hassled in the past for a way to make it easier to turn on
-;; Font Lock mode, without the user needing to know for which modes s/he has to
-;; turn it on, perhaps the same way hilit19.el/hl319.el does. I've always
-;; balked at that way, as I see it as just re-moulding the same problem in
-;; another form. That is; some person would still have to keep track of which
-;; modes (which may not even be distributed with Emacs) support Font Lock mode.
-;; The list would always be out of date. And that person might have to be me.
-
-;; Implementation.
-;;
-;; In a previous discussion the following hack came to mind. It is a gross
-;; hack, but it generally works. We use the convention that major modes start
-;; by calling the function `kill-all-local-variables', which in turn runs
-;; functions on the hook variable `change-major-mode-hook'. We attach our
-;; function `font-lock-change-major-mode' to that hook. Of course, when this
-;; hook is run, the major mode is in the process of being changed and we do not
-;; know what the final major mode will be. So, `font-lock-change-major-mode'
-;; only (a) notes the name of the current buffer, and (b) adds our function
-;; `turn-on-font-lock-if-enabled' to the hook variables `find-file-hooks' and
-;; `post-command-hook' (for buffers that are not visiting files). By the time
-;; the functions on the first of these hooks to be run are run, the new major
-;; mode is assumed to be in place. This way we get a Font Lock function run
-;; when a major mode is turned on, without knowing major modes or their hooks.
-;;
-;; Naturally this requires that (a) major modes run `kill-all-local-variables',
-;; as they are supposed to do, and (b) the major mode is in place after the
-;; file is visited or the command that ran `kill-all-local-variables' has
-;; finished, whichever the sooner. Arguably, any major mode that does not
-;; follow the convension (a) is broken, and I can't think of any reason why (b)
-;; would not be met (except `gnudoit' on non-files). However, it is not clean.
-;;
-;; Probably the cleanest solution is to have each major mode function run some
-;; hook, e.g., `major-mode-hook', but maybe implementing that change is
-;; impractical. I am personally against making `setq' a macro or be advised,
-;; or have a special function such as `set-major-mode', but maybe someone can
-;; come up with another solution?
-
-;; User interface.
-;;
-;; Although Global Font Lock mode is a pseudo-mode, I think that the user
-;; interface should conform to the usual Emacs convention for modes, i.e., a
-;; command to toggle the feature (`global-font-lock-mode') with a variable for
-;; finer control of the mode's behaviour (`font-lock-global-modes').
-;;
-;; The feature should not be enabled by loading font-lock.el, since other
-;; mechanisms for turning on Font Lock mode, such as M-x font-lock-mode RET or
-;; (add-hook 'c-mode-hook 'turn-on-font-lock), would cause Font Lock mode to be
-;; turned on everywhere. That would not be intuitive or informative because
-;; loading a file tells you nothing about the feature or how to control it. It
-;; would also be contrary to the Principle of Least Surprise.
-
-(defvar font-lock-buffers nil) ; For remembering buffers.
-(defvar global-font-lock-mode nil)
-
-;;;###autoload
-(defvar font-lock-global-modes t
- "*Modes for which Font Lock mode is automagically turned on.
-Global Font Lock mode is controlled by the `global-font-lock-mode' command.
-If nil, means no modes have Font Lock mode automatically turned on.
-If t, all modes that support Font Lock mode have it automatically turned on.
-If a list, it should be a list of `major-mode' symbol names for which Font Lock
-mode should be automatically turned on. The sense of the list is negated if it
-begins with `not'. For example:
- (c-mode c++-mode)
-means that Font Lock mode is turned on for buffers in C and C++ modes only.")
-
-;;;###autoload
-(defun global-font-lock-mode (&optional arg message)
- "Toggle Global Font Lock mode.
-With prefix ARG, turn Global Font Lock mode on if and only if ARG is positive.
-Displays a message saying whether the mode is on or off if MESSAGE is non-nil.
-Returns the new status of Global Font Lock mode (non-nil means on).
-
-When Global Font Lock mode is enabled, Font Lock mode is automagically
-turned on in a buffer if its major mode is one of `font-lock-global-modes'."
- (interactive "P\np")
- (let ((off-p (if arg
- (<= (prefix-numeric-value arg) 0)
- global-font-lock-mode)))
- (if off-p
- (remove-hook 'find-file-hooks 'turn-on-font-lock-if-enabled)
- (add-hook 'find-file-hooks 'turn-on-font-lock-if-enabled)
- (add-hook 'post-command-hook 'turn-on-font-lock-if-enabled)
- (setq font-lock-buffers (buffer-list)))
- (when message
- (message "Global Font Lock mode is now %s." (if off-p "OFF" "ON")))
- (setq global-font-lock-mode (not off-p))))
-
-(defun font-lock-change-major-mode ()
- ;; Turn off Font Lock mode if it's on.
- (when font-lock-mode
- (font-lock-mode nil))
- ;; Gross hack warning: Delicate readers should avert eyes now.
- ;; Something is running `kill-all-local-variables', which generally means the
- ;; major mode is being changed. Run `turn-on-font-lock-if-enabled' after the
- ;; file is visited or the current command has finished.
- (when global-font-lock-mode
- (add-hook 'post-command-hook 'turn-on-font-lock-if-enabled)
- (add-to-list 'font-lock-buffers (current-buffer))))
-
-(defun turn-on-font-lock-if-enabled ()
- ;; Gross hack warning: Delicate readers should avert eyes now.
- ;; Turn on Font Lock mode if it's supported by the major mode and enabled by
- ;; the user.
- (remove-hook 'post-command-hook 'turn-on-font-lock-if-enabled)
- (while font-lock-buffers
- (if (buffer-live-p (car font-lock-buffers))
- (save-excursion
- (set-buffer (car font-lock-buffers))
- (if (and (or font-lock-defaults
- (assq major-mode font-lock-defaults-alist))
- (or (eq font-lock-global-modes t)
- (if (eq (car-safe font-lock-global-modes) 'not)
- (not (memq major-mode (cdr font-lock-global-modes)))
- (memq major-mode font-lock-global-modes))))
- (let (inhibit-quit)
- (turn-on-font-lock)))))
- (setq font-lock-buffers (cdr font-lock-buffers))))
-
-(add-hook 'change-major-mode-hook 'font-lock-change-major-mode)
-
-;; End of Global Font Lock mode.
-
-;; Font Lock Support mode.
-;;
-;; This is the code used to interface font-lock.el with any of its add-on
-;; packages, and provide the user interface. Packages that have their own
-;; local buffer fontification functions (see below) may have to call
-;; `font-lock-after-fontify-buffer' and/or `font-lock-after-unfontify-buffer'
-;; themselves.
-
-;;;###autoload
-(defvar font-lock-support-mode nil
- "*Support mode for Font Lock mode.
-Support modes speed up Font Lock mode by being choosy about when fontification
-occurs. Known support modes are Fast Lock mode (symbol `fast-lock-mode') and
-Lazy Lock mode (symbol `lazy-lock-mode'). See those modes for more info.
-If nil, means support for Font Lock mode is never performed.
-If a symbol, use that support mode.
-If a list, each element should be of the form (MAJOR-MODE . SUPPORT-MODE),
-where MAJOR-MODE is a symbol or t (meaning the default). For example:
- ((c-mode . fast-lock-mode) (c++-mode . fast-lock-mode) (t . lazy-lock-mode))
-means that Fast Lock mode is used to support Font Lock mode for buffers in C or
-C++ modes, and Lazy Lock mode is used to support Font Lock mode otherwise.
-
-The value of this variable is used when Font Lock mode is turned on.")
-
-(defvar fast-lock-mode nil)
-(defvar lazy-lock-mode nil)
-
-(defun font-lock-turn-on-thing-lock ()
- (let ((thing-mode (font-lock-value-in-major-mode font-lock-support-mode)))
- (cond ((eq thing-mode 'fast-lock-mode)
- (fast-lock-mode t))
- ((eq thing-mode 'lazy-lock-mode)
- (lazy-lock-mode t)))))
-
-(defun font-lock-turn-off-thing-lock ()
- (cond (fast-lock-mode
- (fast-lock-mode nil))
- (lazy-lock-mode
- (lazy-lock-mode nil))))
-
-(defun font-lock-after-fontify-buffer ()
- (cond (fast-lock-mode
- (fast-lock-after-fontify-buffer))
- (lazy-lock-mode
- (lazy-lock-after-fontify-buffer))))
-
-(defun font-lock-after-unfontify-buffer ()
- (cond (fast-lock-mode
- (fast-lock-after-unfontify-buffer))
- (lazy-lock-mode
- (lazy-lock-after-unfontify-buffer))))
-
-;; End of Font Lock Support mode.
-
-;; Fontification functions.
-
-;;;###autoload
-(defun font-lock-fontify-buffer ()
- "Fontify the current buffer the way `font-lock-mode' would."
- (interactive)
- (let ((font-lock-verbose (or font-lock-verbose (interactive-p))))
- (funcall font-lock-fontify-buffer-function)))
-
-(defun font-lock-unfontify-buffer ()
- (funcall font-lock-unfontify-buffer-function))
-
-(defun font-lock-fontify-region (beg end &optional loudly)
- (funcall font-lock-fontify-region-function beg end loudly))
-
-(defun font-lock-unfontify-region (beg end)
- (funcall font-lock-unfontify-region-function beg end))
-
-(defun font-lock-default-fontify-buffer ()
- (let ((verbose (if (numberp font-lock-verbose)
- (> (buffer-size) font-lock-verbose)
- font-lock-verbose)))
- (if verbose (message "Fontifying %s..." (buffer-name)))
- ;; Make sure we have the right `font-lock-keywords' etc.
- (if (not font-lock-mode) (font-lock-set-defaults))
- ;; Make sure we fontify etc. in the whole buffer.
- (save-restriction
- (widen)
- (condition-case nil
- (save-excursion
- (save-match-data
- (font-lock-fontify-region (point-min) (point-max) verbose)
- (font-lock-after-fontify-buffer)
- (setq font-lock-fontified t)))
- ;; We don't restore the old fontification, so it's best to unfontify.
- (quit (font-lock-unfontify-buffer))))
- (if verbose (message "Fontifying %s...%s" (buffer-name)
- (if font-lock-fontified "done" "quit")))))
-
-(defun font-lock-default-unfontify-buffer ()
- (save-restriction
- (widen)
- (font-lock-unfontify-region (point-min) (point-max))
- (font-lock-after-unfontify-buffer)
- (setq font-lock-fontified nil)))
-
-(defun font-lock-default-fontify-region (beg end loudly)
- (save-buffer-state ((old-syntax-table (syntax-table)))
- (unwind-protect
- (save-restriction
- (widen)
- ;; Use the fontification syntax table, if any.
- (when font-lock-syntax-table
- (set-syntax-table font-lock-syntax-table))
- ;; Now do the fontification.
- (font-lock-unfontify-region beg end)
- (unless font-lock-keywords-only
- (font-lock-fontify-syntactically-region beg end loudly))
- (font-lock-fontify-keywords-region beg end loudly))
- ;; Clean up.
- (set-syntax-table old-syntax-table))))
-
-;; The following must be rethought, since keywords can override fontification.
-; ;; Now scan for keywords, but not if we are inside a comment now.
-; (or (and (not font-lock-keywords-only)
-; (let ((state (parse-partial-sexp beg end nil nil
-; font-lock-cache-state)))
-; (or (nth 4 state) (nth 7 state))))
-; (font-lock-fontify-keywords-region beg end))
-
-(defun font-lock-default-unfontify-region (beg end)
- (save-buffer-state nil
- (remove-text-properties beg end '(face nil))))
-
-;; Called when any modification is made to buffer text.
-(defun font-lock-after-change-function (beg end old-len)
- (save-excursion
- (save-match-data
- ;; Rescan between start of lines enclosing the region.
- (font-lock-fontify-region
- (progn (goto-char beg) (beginning-of-line) (point))
- (progn (goto-char (+ end old-len)) (forward-line 1) (point))))))
-
-(defun font-lock-fontify-block (&optional arg)
- "Fontify some lines the way `font-lock-fontify-buffer' would.
-The lines could be a function or paragraph, or a specified number of lines.
-If ARG is given, fontify that many lines before and after point, or 16 lines if
-no ARG is given and `font-lock-mark-block-function' is nil.
-If `font-lock-mark-block-function' non-nil and no ARG is given, it is used to
-delimit the region to fontify."
- (interactive "P")
- (let (font-lock-beginning-of-syntax-function deactivate-mark)
- ;; Make sure we have the right `font-lock-keywords' etc.
- (if (not font-lock-mode) (font-lock-set-defaults))
- (save-excursion
- (save-match-data
- (condition-case error-data
- (if (or arg (not font-lock-mark-block-function))
- (let ((lines (if arg (prefix-numeric-value arg) 16)))
- (font-lock-fontify-region
- (save-excursion (forward-line (- lines)) (point))
- (save-excursion (forward-line lines) (point))))
- (funcall font-lock-mark-block-function)
- (font-lock-fontify-region (point) (mark)))
- ((error quit) (message "Fontifying block...%s" error-data)))))))
-
-(define-key facemenu-keymap "\M-g" 'font-lock-fontify-block)
-
-;; Syntactic fontification functions.
-
-;; These record the parse state at a particular position, always the start of a
-;; line. Used to make `font-lock-fontify-syntactically-region' faster.
-;; Previously, `font-lock-cache-position' was just a buffer position. However,
-;; under certain situations, this occasionally resulted in mis-fontification.
-;; I think those "situations" were deletion with Lazy Lock mode's deferral.
-(defvar font-lock-cache-state nil)
-(defvar font-lock-cache-position nil)
-
-(defun font-lock-fontify-syntactically-region (start end &optional loudly)
- "Put proper face on each string and comment between START and END.
-START should be at the beginning of a line."
- (let ((synstart (cond (font-lock-comment-start-regexp
- (concat "\\s\"\\|" font-lock-comment-start-regexp))
- (comment-start-skip
- (concat "\\s\"\\|" comment-start-skip))
- (t
- "\\s\"")))
- (cache (marker-position font-lock-cache-position))
- state prev here beg)
- (if loudly (message "Fontifying %s... (syntactically...)" (buffer-name)))
- (goto-char start)
- ;;
- ;; Find the state at the `beginning-of-line' before `start'.
- (if (eq start cache)
- ;; Use the cache for the state of `start'.
- (setq state font-lock-cache-state)
- ;; Find the state of `start'.
- (if (null font-lock-beginning-of-syntax-function)
- ;; Use the state at the previous cache position, if any, or
- ;; otherwise calculate from `point-min'.
- (if (or (null cache) (< start cache))
- (setq state (parse-partial-sexp (point-min) start))
- (setq state (parse-partial-sexp cache start nil nil
- font-lock-cache-state)))
- ;; Call the function to move outside any syntactic block.
- (funcall font-lock-beginning-of-syntax-function)
- (setq state (parse-partial-sexp (point) start)))
- ;; Cache the state and position of `start'.
- (setq font-lock-cache-state state)
- (set-marker font-lock-cache-position start))
- ;;
- ;; If the region starts inside a string, show the extent of it.
- (when (nth 3 state)
- (setq here (point))
- (while (and (re-search-forward "\\s\"" end 'move)
- ;; Verify the state so we don't get fooled by quoting.
- (nth 3 (parse-partial-sexp here (point) nil nil state))))
- (put-text-property here (point) 'face font-lock-string-face)
- (setq state (parse-partial-sexp here (point) nil nil state)))
- ;;
- ;; Likewise for a comment.
- (when (or (nth 4 state) (nth 7 state))
- (let ((comstart (cond (font-lock-comment-start-regexp
- font-lock-comment-start-regexp)
- (comment-start-skip
- (concat "\\s<\\|" comment-start-skip))
- (t
- "\\s<")))
- (count 1))
- (setq here (point))
- (condition-case nil
- (save-restriction
- (narrow-to-region (point-min) end)
- ;; Go back to the real start of the comment.
- (re-search-backward comstart)
- (forward-comment 1)
- ;; If there is more than one comment type, then the previous
- ;; comment start might not be the real comment start.
- ;; For example, in C++ code, `here' might be on a line following
- ;; a // comment that is actually within a /* */ comment.
- (while (<= (point) here)
- (goto-char here)
- (re-search-backward comstart nil nil (incf count))
- (forward-comment 1))
- ;; Go back to the real end of the comment.
- (skip-chars-backward " \t"))
- (error (goto-char end)))
- (put-text-property here (point) 'face font-lock-comment-face)
- (setq state (parse-partial-sexp here (point) nil nil state))))
- ;;
- ;; Find each interesting place between here and `end'.
- (while (and (< (point) end)
- (setq prev (point))
- (re-search-forward synstart end t)
- (setq state (parse-partial-sexp prev (point) nil nil state)))
- (cond ((nth 3 state)
- ;;
- ;; Found a real string start.
- (setq here (point) beg (match-beginning 0))
- (condition-case nil
- (save-restriction
- (narrow-to-region (point-min) end)
- (goto-char (scan-sexps beg 1)))
- (error (goto-char end)))
- (put-text-property beg (point) 'face font-lock-string-face)
- (setq state (parse-partial-sexp here (point) nil nil state)))
- ((or (nth 4 state) (nth 7 state))
- ;;
- ;; Found a real comment start.
- (setq here (point) beg (or (match-end 1) (match-beginning 0)))
- (goto-char beg)
- (condition-case nil
- (save-restriction
- (narrow-to-region (point-min) end)
- (forward-comment 1)
- (skip-chars-backward " \t"))
- (error (goto-char end)))
- (put-text-property beg (point) 'face font-lock-comment-face)
- (setq state (parse-partial-sexp here (point) nil nil state)))))))
-
-;;; Additional text property functions.
-
-;; The following three text property functions are not generally available (and
-;; it's not certain that they should be) so they are inlined for speed.
-;; The case for `fillin-text-property' is simple; it may or not be generally
-;; useful. (Since it is used here, it is useful in at least one place.;-)
-;; However, the case for `append-text-property' and `prepend-text-property' is
-;; more complicated. Should they remove duplicate property values or not? If
-;; so, should the first or last duplicate item remain? Or the one that was
-;; added? In our implementation, the first duplicate remains.
-
-(defsubst font-lock-fillin-text-property (start end prop value &optional object)
- "Fill in one property of the text from START to END.
-Arguments PROP and VALUE specify the property and value to put where none are
-already in place. Therefore existing property values are not overwritten.
-Optional argument OBJECT is the string or buffer containing the text."
- (let ((start (text-property-any start end prop nil object)) next)
- (while start
- (setq next (next-single-property-change start prop object end))
- (put-text-property start next prop value object)
- (setq start (text-property-any next end prop nil object)))))
-
-;; This function (from simon's unique.el) is rewritten and inlined for speed.
-;(defun unique (list function)
-; "Uniquify LIST, deleting elements using FUNCTION.
-;Return the list with subsequent duplicate items removed by side effects.
-;FUNCTION is called with an element of LIST and a list of elements from LIST,
-;and should return the list of elements with occurrences of the element removed,
-;i.e., a function such as `delete' or `delq'.
-;This function will work even if LIST is unsorted. See also `uniq'."
-; (let ((list list))
-; (while list
-; (setq list (setcdr list (funcall function (car list) (cdr list))))))
-; list)
-
-(defsubst font-lock-unique (list)
- "Uniquify LIST, deleting elements using `delq'.
-Return the list with subsequent duplicate items removed by side effects."
- (let ((list list))
- (while list
- (setq list (setcdr list (delq (car list) (cdr list))))))
- list)
-
-;; A generalisation of `facemenu-add-face' for any property, but without the
-;; removal of inactive faces via `facemenu-discard-redundant-faces' and special
-;; treatment of `default'. Uses `unique' to remove duplicate property values.
-(defsubst font-lock-prepend-text-property (start end prop value &optional object)
- "Prepend to one property of the text from START to END.
-Arguments PROP and VALUE specify the property and value to prepend to the value
-already in place. The resulting property values are always lists, and unique.
-Optional argument OBJECT is the string or buffer containing the text."
- (let ((val (if (listp value) value (list value))) next prev)
- (while (/= start end)
- (setq next (next-single-property-change start prop object end)
- prev (get-text-property start prop object))
- (put-text-property
- start next prop
- (font-lock-unique (append val (if (listp prev) prev (list prev))))
- object)
- (setq start next))))
-
-(defsubst font-lock-append-text-property (start end prop value &optional object)
- "Append to one property of the text from START to END.
-Arguments PROP and VALUE specify the property and value to append to the value
-already in place. The resulting property values are always lists, and unique.
-Optional argument OBJECT is the string or buffer containing the text."
- (let ((val (if (listp value) value (list value))) next prev)
- (while (/= start end)
- (setq next (next-single-property-change start prop object end)
- prev (get-text-property start prop object))
- (put-text-property
- start next prop
- (font-lock-unique (append (if (listp prev) prev (list prev)) val))
- object)
- (setq start next))))
-
-;;; Regexp fontification functions.
-
-(defsubst font-lock-apply-highlight (highlight)
- "Apply HIGHLIGHT following a match.
-HIGHLIGHT should be of the form MATCH-HIGHLIGHT, see `font-lock-keywords'."
- (let* ((match (nth 0 highlight))
- (start (match-beginning match)) (end (match-end match))
- (override (nth 2 highlight)))
- (cond ((not start)
- ;; No match but we might not signal an error.
- (or (nth 3 highlight)
- (error "No match %d in highlight %S" match highlight)))
- ((not override)
- ;; Cannot override existing fontification.
- (or (text-property-not-all start end 'face nil)
- (put-text-property start end 'face (eval (nth 1 highlight)))))
- ((eq override t)
- ;; Override existing fontification.
- (put-text-property start end 'face (eval (nth 1 highlight))))
- ((eq override 'prepend)
- ;; Prepend to existing fontification.
- (font-lock-prepend-text-property start end 'face
- (eval (nth 1 highlight))))
- ((eq override 'append)
- ;; Append to existing fontification.
- (font-lock-append-text-property start end 'face
- (eval (nth 1 highlight))))
- ((eq override 'keep)
- ;; Keep existing fontification.
- (font-lock-fillin-text-property start end 'face
- (eval (nth 1 highlight)))))))
-
-(defsubst font-lock-fontify-anchored-keywords (keywords limit)
- "Fontify according to KEYWORDS until LIMIT.
-KEYWORDS should be of the form MATCH-ANCHORED, see `font-lock-keywords'."
- (let ((matcher (nth 0 keywords)) (lowdarks (nthcdr 3 keywords)) highlights)
- ;; Until we come up with a cleaner solution, we make LIMIT the end of line.
- (save-excursion (end-of-line) (setq limit (min limit (point))))
- ;; Evaluate PRE-MATCH-FORM.
- (eval (nth 1 keywords))
- (save-match-data
- ;; Find an occurrence of `matcher' before `limit'.
- (while (if (stringp matcher)
- (re-search-forward matcher limit t)
- (funcall matcher limit))
- ;; Apply each highlight to this instance of `matcher'.
- (setq highlights lowdarks)
- (while highlights
- (font-lock-apply-highlight (car highlights))
- (setq highlights (cdr highlights)))))
- ;; Evaluate POST-MATCH-FORM.
- (eval (nth 2 keywords))))
-
-(defun font-lock-fontify-keywords-region (start end &optional loudly)
- "Fontify according to `font-lock-keywords' between START and END.
-START should be at the beginning of a line."
- (let ((case-fold-search font-lock-keywords-case-fold-search)
- (keywords (cdr (if (eq (car-safe font-lock-keywords) t)
- font-lock-keywords
- (font-lock-compile-keywords))))
- (bufname (buffer-name)) (count 0)
- keyword matcher highlights)
- ;;
- ;; Fontify each item in `font-lock-keywords' from `start' to `end'.
- (while keywords
- (if loudly (message "Fontifying %s... (regexps..%s)" bufname
- (make-string (incf count) ?.)))
- ;;
- ;; Find an occurrence of `matcher' from `start' to `end'.
- (setq keyword (car keywords) matcher (car keyword))
- (goto-char start)
- (while (if (stringp matcher)
- (re-search-forward matcher end t)
- (funcall matcher end))
- ;; Apply each highlight to this instance of `matcher', which may be
- ;; specific highlights or more keywords anchored to `matcher'.
- (setq highlights (cdr keyword))
- (while highlights
- (if (numberp (car (car highlights)))
- (font-lock-apply-highlight (car highlights))
- (font-lock-fontify-anchored-keywords (car highlights) end))
- (setq highlights (cdr highlights))))
- (setq keywords (cdr keywords)))))
-
-;; Various functions.
-
-(defun font-lock-compile-keywords (&optional keywords)
- ;; Compile `font-lock-keywords' into the form (t KEYWORD ...) where KEYWORD
- ;; is the (MATCHER HIGHLIGHT ...) shown in the variable's doc string.
- (let ((keywords (or keywords font-lock-keywords)))
- (setq font-lock-keywords
- (if (eq (car-safe keywords) t)
- keywords
- (cons t (mapcar 'font-lock-compile-keyword keywords))))))
-
-(defun font-lock-compile-keyword (keyword)
- (cond ((nlistp keyword) ; MATCHER
- (list keyword '(0 font-lock-keyword-face)))
- ((eq (car keyword) 'eval) ; (eval . FORM)
- (font-lock-compile-keyword (eval (cdr keyword))))
- ((eq (car-safe (cdr keyword)) 'quote) ; (MATCHER . 'FORM)
- ;; If FORM is a FACENAME then quote it. Otherwise ignore the quote.
- (if (symbolp (nth 2 keyword))
- (list (car keyword) (list 0 (cdr keyword)))
- (font-lock-compile-keyword (cons (car keyword) (nth 2 keyword)))))
- ((numberp (cdr keyword)) ; (MATCHER . MATCH)
- (list (car keyword) (list (cdr keyword) 'font-lock-keyword-face)))
- ((symbolp (cdr keyword)) ; (MATCHER . FACENAME)
- (list (car keyword) (list 0 (cdr keyword))))
- ((nlistp (nth 1 keyword)) ; (MATCHER . HIGHLIGHT)
- (list (car keyword) (cdr keyword)))
- (t ; (MATCHER HIGHLIGHT ...)
- keyword)))
-
-(defun font-lock-value-in-major-mode (alist)
- ;; Return value in ALIST for `major-mode', or ALIST if it is not an alist.
- ;; Structure is ((MAJOR-MODE . VALUE) ...) where MAJOR-MODE may be t.
- (if (consp alist)
- (cdr (or (assq major-mode alist) (assq t alist)))
- alist))
-
-(defun font-lock-choose-keywords (keywords level)
- ;; Return LEVELth element of KEYWORDS. A LEVEL of nil is equal to a
- ;; LEVEL of 0, a LEVEL of t is equal to (1- (length KEYWORDS)).
- (cond ((symbolp keywords)
- keywords)
- ((numberp level)
- (or (nth level keywords) (car (reverse keywords))))
- ((eq level t)
- (car (reverse keywords)))
- (t
- (car keywords))))
-
-(defvar font-lock-set-defaults nil) ; Whether we have set up defaults.
-
-(defun font-lock-set-defaults ()
- "Set fontification defaults appropriately for this mode.
-Sets various variables using `font-lock-defaults' (or, if nil, using
-`font-lock-defaults-alist') and `font-lock-maximum-decoration'."
- ;; Set face defaults.
- (font-lock-make-faces)
- ;; Set fontification defaults.
- (make-local-variable 'font-lock-fontified)
- ;; Set iff not previously set.
- (unless font-lock-set-defaults
- (set (make-local-variable 'font-lock-set-defaults) t)
- (set (make-local-variable 'font-lock-cache-state) nil)
- (set (make-local-variable 'font-lock-cache-position) (make-marker))
- (let* ((defaults (or font-lock-defaults
- (cdr (assq major-mode font-lock-defaults-alist))))
- (keywords
- (font-lock-choose-keywords (nth 0 defaults)
- (font-lock-value-in-major-mode font-lock-maximum-decoration)))
- (local (cdr (assq major-mode font-lock-keywords-alist))))
- ;; Regexp fontification?
- (setq font-lock-keywords (if (fboundp keywords)
- (funcall keywords)
- (eval keywords)))
- ;; Local fontification?
- (while local
- (font-lock-add-keywords nil (car (car local)) (cdr (car local)))
- (setq local (cdr local)))
- ;; Syntactic fontification?
- (when (nth 1 defaults)
- (set (make-local-variable 'font-lock-keywords-only) t))
- ;; Case fold during regexp fontification?
- (when (nth 2 defaults)
- (set (make-local-variable 'font-lock-keywords-case-fold-search) t))
- ;; Syntax table for regexp and syntactic fontification?
- (when (nth 3 defaults)
- (let ((slist (nth 3 defaults)))
- (set (make-local-variable 'font-lock-syntax-table)
- (copy-syntax-table (syntax-table)))
- (while slist
- ;; The character to modify may be a single CHAR or a STRING.
- (let ((chars (if (numberp (car (car slist)))
- (list (car (car slist)))
- (mapcar 'identity (car (car slist)))))
- (syntax (cdr (car slist))))
- (while chars
- (modify-syntax-entry (car chars) syntax
- font-lock-syntax-table)
- (setq chars (cdr chars)))
- (setq slist (cdr slist))))))
- ;; Syntax function for syntactic fontification?
- (when (nth 4 defaults)
- (set (make-local-variable 'font-lock-beginning-of-syntax-function)
- (nth 4 defaults)))
- ;; Variable alist?
- (let ((alist (nthcdr 5 defaults)))
- (while alist
- (set (make-local-variable (car (car alist))) (cdr (car alist)))
- (setq alist (cdr alist)))))))
-
-(defun font-lock-unset-defaults ()
- "Unset fontification defaults. See `font-lock-set-defaults'."
- (setq font-lock-set-defaults nil
- font-lock-keywords nil
- font-lock-keywords-only nil
- font-lock-keywords-case-fold-search nil
- font-lock-syntax-table nil
- font-lock-beginning-of-syntax-function nil)
- (let* ((defaults (or font-lock-defaults
- (cdr (assq major-mode font-lock-defaults-alist))))
- (alist (nthcdr 5 defaults)))
- (while alist
- (set (car (car alist)) (default-value (car (car alist))))
- (setq alist (cdr alist)))))
-
-;; Colour etc. support.
-
-;; This section of code is crying out for revision.
-
-;; To begin with, `display-type' and `background-mode' are `frame-parameters'
-;; so we don't have to calculate them here anymore. But all the face stuff
-;; should be frame-local (and thus display-local) anyway. Because we're not
-;; sure what support Emacs is going to have for general frame-local face
-;; attributes, we leave this section of code as it is. For now. --sm.
-
-(defvar font-lock-display-type nil
- "A symbol indicating the display Emacs is running under.
-The symbol should be one of `color', `grayscale' or `mono'.
-If Emacs guesses this display attribute wrongly, either set this variable in
-your `~/.emacs' or set the resource `Emacs.displayType' in your `~/.Xdefaults'.
-See also `font-lock-background-mode' and `font-lock-face-attributes'.")
-
-(defvar font-lock-background-mode nil
- "A symbol indicating the Emacs background brightness.
-The symbol should be one of `light' or `dark'.
-If Emacs guesses this frame attribute wrongly, either set this variable in
-your `~/.emacs' or set the resource `Emacs.backgroundMode' in your
-`~/.Xdefaults'.
-See also `font-lock-display-type' and `font-lock-face-attributes'.")
-
-(defvar font-lock-face-attributes nil
- "A list of default attributes to use for face attributes.
-Each element of the list should be of the form
-
- (FACE FOREGROUND BACKGROUND BOLD-P ITALIC-P UNDERLINE-P)
-
-where FACE could be one of the face symbols `font-lock-comment-face',
-`font-lock-string-face', `font-lock-keyword-face', `font-lock-builtin-face',
-`font-lock-type-face', `font-lock-function-name-face',
-`font-lock-variable-name-face', `font-lock-reference-face' and
-`font-lock-warning-face', or any other face symbols and attributes may be
-specified here and used in `font-lock-keywords'.
-
-Subsequent element items should be the attributes for the corresponding
-Font Lock mode faces. Attributes FOREGROUND and BACKGROUND should be strings
-\(default if nil), while BOLD-P, ITALIC-P, and UNDERLINE-P should specify the
-corresponding face attributes (yes if non-nil).
-
-Emacs uses default attributes based on display type and background brightness.
-See variables `font-lock-display-type' and `font-lock-background-mode'.
-
-Resources can be used to over-ride these face attributes. For example, the
-resource `Emacs.font-lock-comment-face.attributeUnderline' can be used to
-specify the UNDERLINE-P attribute for face `font-lock-comment-face'.")
-
-(defun font-lock-make-faces (&optional override)
- "Make faces from `font-lock-face-attributes'.
-A default list is used if this is nil.
-If optional OVERRIDE is non-nil, faces that already exist are reset.
-See `font-lock-make-face' and `list-faces-display'."
- ;; We don't need to `setq' any of these variables, but the user can see what
- ;; is being used if we do.
- (unless font-lock-display-type
- (setq font-lock-display-type
- (let ((display-resource (x-get-resource ".displayType" "DisplayType")))
- (cond (display-resource (intern (downcase display-resource)))
- ((x-display-color-p) 'color)
- ((x-display-grayscale-p) 'grayscale)
- (t 'mono)))))
- (unless font-lock-background-mode
- (setq font-lock-background-mode
- (let ((bg-resource (x-get-resource ".backgroundMode" "BackgroundMode"))
- (params (frame-parameters)))
- (cond (bg-resource (intern (downcase bg-resource)))
- ((eq system-type 'ms-dos)
- (if (string-match "light" (cdr (assq 'background-color params)))
- 'light
- 'dark))
- ((< (apply '+ (x-color-values
- (cdr (assq 'background-color params))))
- (* (apply '+ (x-color-values "white")) .6))
- 'dark)
- (t 'light)))))
- (let ((face-attributes
- (let ((light-bg (eq font-lock-background-mode 'light)))
- (cond ((memq font-lock-display-type '(mono monochrome))
- ;; Emacs 19.25's font-lock defaults:
- ;;'((font-lock-comment-face nil nil nil t nil)
- ;; (font-lock-string-face nil nil nil nil t)
- ;; (font-lock-keyword-face nil nil t nil nil)
- ;; (font-lock-function-name-face nil nil t t nil)
- ;; (font-lock-type-face nil nil nil t nil))
- (list '(font-lock-comment-face nil nil t t nil)
- '(font-lock-string-face nil nil nil t nil)
- '(font-lock-keyword-face nil nil t nil nil)
- '(font-lock-builtin-face nil nil t nil nil)
- (list
- 'font-lock-function-name-face
- (cdr (assq 'background-color (frame-parameters)))
- (cdr (assq 'foreground-color (frame-parameters)))
- t nil nil)
- '(font-lock-variable-name-face nil nil t t nil)
- '(font-lock-type-face nil nil t nil t)
- '(font-lock-reference-face nil nil t nil t)
- (list
- 'font-lock-warning-face
- (cdr (assq 'background-color (frame-parameters)))
- (cdr (assq 'foreground-color (frame-parameters)))
- t nil nil)))
- ((memq font-lock-display-type '(grayscale greyscale
- grayshade greyshade))
- (list
- (list 'font-lock-comment-face
- (if light-bg "DimGray" "LightGray") nil t t nil)
- (list 'font-lock-string-face
- (if light-bg "DimGray" "LightGray") nil nil t nil)
- (list 'font-lock-keyword-face
- nil (if light-bg "LightGray" "DimGray") t nil nil)
- (list 'font-lock-builtin-face
- nil (if light-bg "LightGray" "DimGray") t nil nil)
- (list 'font-lock-function-name-face
- (cdr (assq 'background-color (frame-parameters)))
- (cdr (assq 'foreground-color (frame-parameters)))
- t nil nil)
- (list 'font-lock-variable-name-face
- nil (if light-bg "Gray90" "DimGray") t t nil)
- (list 'font-lock-type-face
- nil (if light-bg "Gray80" "DimGray") t nil nil)
- (list 'font-lock-reference-face
- nil (if light-bg "LightGray" "Gray50") t nil t)
- (list 'font-lock-warning-face
- (cdr (assq 'background-color (frame-parameters)))
- (cdr (assq 'foreground-color (frame-parameters)))
- t nil nil)))
- (light-bg ; light colour background
- '((font-lock-comment-face "Firebrick")
- (font-lock-string-face "RosyBrown")
- (font-lock-keyword-face "Purple")
- (font-lock-builtin-face "Orchid")
- (font-lock-function-name-face "Blue")
- (font-lock-variable-name-face "DarkGoldenrod")
- (font-lock-type-face "DarkOliveGreen")
- (font-lock-reference-face "CadetBlue")
- (font-lock-warning-face "Red" nil t nil nil)))
- (t ; dark colour background
- '((font-lock-comment-face "OrangeRed")
- (font-lock-string-face "LightSalmon")
- (font-lock-keyword-face "Cyan")
- (font-lock-builtin-face "LightSteelBlue")
- (font-lock-function-name-face "LightSkyBlue")
- (font-lock-variable-name-face "LightGoldenrod")
- (font-lock-type-face "PaleGreen")
- (font-lock-reference-face "Aquamarine")
- (font-lock-warning-face "Pink" nil t nil nil)))))))
- (while face-attributes
- (unless (assq (car (car face-attributes)) font-lock-face-attributes)
- (push (car face-attributes) font-lock-face-attributes))
- (setq face-attributes (cdr face-attributes))))
- ;; Now make the faces if we have to.
- (mapcar (function
- (lambda (face-attributes)
- (let ((face (nth 0 face-attributes)))
- (cond (override
- ;; We can stomp all over it anyway. Get outta my face!
- (font-lock-make-face face-attributes))
- ((and (boundp face) (facep (symbol-value face)))
- ;; The variable exists and is already bound to a face.
- nil)
- ((facep face)
- ;; We already have a face so we bind the variable to it.
- (set face face))
- (t
- ;; No variable or no face.
- (font-lock-make-face face-attributes))))))
- font-lock-face-attributes))
-
-(defun font-lock-make-face (face-attributes)
- "Make a face from FACE-ATTRIBUTES.
-FACE-ATTRIBUTES should be like an element `font-lock-face-attributes', so that
-the face name is the first item in the list. A variable with the same name as
-the face is also set; its value is the face name."
- (let* ((face (nth 0 face-attributes))
- (face-name (symbol-name face))
- (set-p (function (lambda (face-name resource)
- (x-get-resource (concat face-name ".attribute" resource)
- (concat "Face.Attribute" resource)))))
- (on-p (function (lambda (face-name resource)
- (let ((set (funcall set-p face-name resource)))
- (and set (member (downcase set) '("on" "true"))))))))
- (make-face face)
- (add-to-list 'facemenu-unlisted-faces face)
- ;; Set attributes not set from X resources (and therefore `make-face').
- (or (funcall set-p face-name "Foreground")
- (condition-case nil
- (set-face-foreground face (nth 1 face-attributes))
- (error nil)))
- (or (funcall set-p face-name "Background")
- (condition-case nil
- (set-face-background face (nth 2 face-attributes))
- (error nil)))
- (if (funcall set-p face-name "Bold")
- (and (funcall on-p face-name "Bold") (make-face-bold face nil t))
- (and (nth 3 face-attributes) (make-face-bold face nil t)))
- (if (funcall set-p face-name "Italic")
- (and (funcall on-p face-name "Italic") (make-face-italic face nil t))
- (and (nth 4 face-attributes) (make-face-italic face nil t)))
- (or (funcall set-p face-name "Underline")
- (set-face-underline-p face (nth 5 face-attributes)))
- (set face face)))
-
-;;; Various regexp information shared by several modes.
-;;; Information specific to a single mode should go in its load library.
-
-;; The C/C++/Objective-C/Java support is in cc-font.el loaded by cc-mode.el.
-;; The below function should stay in font-lock.el, since it is used by many
-;; other libraries.
-
-(defun font-lock-match-c-style-declaration-item-and-skip-to-next (limit)
- "Match, and move over, any declaration/definition item after point.
-Matches after point, but ignores leading whitespace and `*' characters.
-Does not move further than LIMIT.
-
-The expected syntax of a declaration/definition item is `word', possibly ending
-with optional whitespace and a `('. Everything following the item (but
-belonging to it) is expected to by skip-able by `scan-sexps', and items are
-expected to be separated with a `,' and to be terminated with a `;'.
-
-Thus the regexp matches after point: word (
- ^^^^ ^
-Where the match subexpressions are: 1 2
-
-The item is delimited by (match-beginning 1) and (match-end 1).
-If (match-beginning 2) is non-nil, the item is followed by a `('.
-
-This function could be MATCHER in a MATCH-ANCHORED `font-lock-keywords' item."
- (when (looking-at "[ \t*]*\\(\\sw+\\)[ \t]*\\((\\)?")
- (save-match-data
- (condition-case nil
- (save-restriction
- ;; Restrict to the end of line, currently guaranteed to be LIMIT.
- (narrow-to-region (point-min) limit)
- (goto-char (match-end 1))
- ;; Move over any item value, etc., to the next item.
- (while (not (looking-at "[ \t]*\\(\\(,\\)\\|;\\|$\\)"))
- (goto-char (or (scan-sexps (point) 1) (point-max))))
- (goto-char (match-end 2)))
- (error t)))))
-
-
-(defconst lisp-font-lock-keywords-1
- (eval-when-compile
- (list
- ;; Anything not a variable or type declaration is fontified as a function.
- ;; It would be cleaner to allow preceding whitespace, but it would also be
- ;; about five times slower.
- (list (concat "^(\\(def\\("
- ;; Variable declarations.
- "\\(const\\|custom\\|var\\)\\|"
- ;; Structure declarations.
- "\\(class\\|struct\\|type\\)\\|"
- ;; Everything else is a function declaration.
- "\\sw+"
- "\\)\\)\\>"
- ;; Any whitespace and declared object.
- "[ \t'\(]*"
- "\\(\\sw+\\)?")
- '(1 font-lock-keyword-face)
- '(5 (cond ((match-beginning 3) font-lock-variable-name-face)
- ((match-beginning 4) font-lock-type-face)
- (t font-lock-function-name-face))
- nil t))
- ))
- "Subdued level highlighting for Lisp modes.")
-
-(defconst lisp-font-lock-keywords-2
- (append lisp-font-lock-keywords-1
- (eval-when-compile
- (list
- ;;
- ;; Control structures. Common ELisp and CLisp forms combined.
-; (make-regexp
-; '("cond" "if" "while" "let\\*?" "prog[nv12*]?" "inline" "catch" "throw"
-; "save-restriction" "save-excursion" "save-window-excursion"
-; "save-selected-window" "save-match-data" "save-current-buffer"
-; "unwind-protect" "condition-case" "track-mouse" "dont-compile"
-; "eval-after-load" "eval-and-compile" "eval-when-compile"
-; "when" "unless" "do" "flet" "labels" "return" "return-from"
-; "with-output-to-temp-buffer" "with-timeout" "with-current-buffer"
-; "with-temp-buffer" "with-temp-file"))
- (cons (concat "(\\("
- "c\\(atch\\|ond\\(\\|ition-case\\)\\)\\|"
- "do\\(\\|nt-compile\\)\\|"
- "eval-\\(a\\(fter-load\\|nd-compile\\)\\|"
- "when-compile\\)\\|flet\\|i\\(f\\|nline\\)\\|"
- "l\\(abels\\|et\\*?\\)\\|prog[nv12*]?\\|"
- "return\\(\\|-from\\)\\|"
- "save-\\(current-buffer\\|excursion\\|match-data\\|"
- "restriction\\|selected-window\\|window-excursion\\)\\|"
- "t\\(hrow\\|rack-mouse\\)\\|un\\(less\\|wind-protect\\)\\|"
- "w\\(h\\(en\\|ile\\)\\|ith-\\(current-buffer\\|"
- "output-to-temp-buffer\\|"
- "t\\(emp-\\(buffer\\|file\\)\\|imeout\\)\\)\\)"
- "\\)\\>")
- 1)
- ;;
- ;; Feature symbols as references.
- '("(\\(featurep\\|provide\\|require\\)\\>[ \t']*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-reference-face nil t))
- ;;
- ;; Words inside \\[] tend to be for `substitute-command-keys'.
- '("\\\\\\\\\\[\\(\\sw+\\)]" 1 font-lock-reference-face prepend)
- ;;
- ;; Words inside `' tend to be symbol names.
- '("`\\(\\sw\\sw+\\)'" 1 font-lock-reference-face prepend)
- ;;
- ;; CLisp `:' keywords as builtins.
- '("\\<:\\sw\\sw+\\>" 0 font-lock-builtin-face)
- ;;
- ;; ELisp and CLisp `&' keywords as types.
- '("\\<\\&\\sw+\\>" . font-lock-type-face)
- )))
- "Gaudy level highlighting for Lisp modes.")
-
-
-(defvar lisp-font-lock-keywords lisp-font-lock-keywords-1
- "Default expressions to highlight in Lisp modes.")
-
-
-(defvar scheme-font-lock-keywords
- (eval-when-compile
- (list
- ;;
- ;; Declarations. Hannes Haug <hannes.haug@student.uni-tuebingen.de> says
- ;; this works for SOS, STklos, SCOOPS, Meroon and Tiny CLOS.
- (list (concat "(\\(define\\("
- ;; Function names.
- "\\(\\|-\\(generic\\(\\|-procedure\\)\\|method\\)\\)\\|"
- ;; Macro names, as variable names. A bit dubious, this.
- "\\(-syntax\\)\\|"
- ;; Class names.
- "-class"
- "\\)\\)\\>"
- ;; Any whitespace and declared object.
- "[ \t]*(?"
- "\\(\\sw+\\)?")
- '(1 font-lock-keyword-face)
- '(7 (cond ((match-beginning 3) font-lock-function-name-face)
- ((match-beginning 6) font-lock-variable-name-face)
- (t font-lock-type-face))
- nil t))
- ;;
- ;; Control structures.
-;(make-regexp '("begin" "call-with-current-continuation" "call/cc"
-; "call-with-input-file" "call-with-output-file" "case" "cond"
-; "do" "else" "for-each" "if" "lambda"
-; "let\\*?" "let-syntax" "letrec" "letrec-syntax"
-; ;; Hannes Haug <hannes.haug@student.uni-tuebingen.de> wants:
-; "and" "or" "delay"
-; ;; Stefan Monnier <stefan.monnier@epfl.ch> says don't bother:
-; ;;"quasiquote" "quote" "unquote" "unquote-splicing"
-; "map" "syntax" "syntax-rules"))
- (cons
- (concat "(\\("
- "and\\|begin\\|c\\(a\\(ll\\(-with-\\(current-continuation\\|"
- "input-file\\|output-file\\)\\|/cc\\)\\|se\\)\\|ond\\)\\|"
- "d\\(elay\\|o\\)\\|else\\|for-each\\|if\\|"
- "l\\(ambda\\|et\\(-syntax\\|\\*?\\|rec\\(\\|-syntax\\)\\)\\)\\|"
- "map\\|or\\|syntax\\(\\|-rules\\)"
- "\\)\\>") 1)
- ;;
- ;; David Fox <fox@graphics.cs.nyu.edu> for SOS/STklos class specifiers.
- '("\\<<\\sw+>\\>" . font-lock-type-face)
- ;;
- ;; Scheme `:' keywords as references.
- '("\\<:\\sw+\\>" . font-lock-reference-face)
- ))
- "Default expressions to highlight in Scheme modes.")
-
-
-(defvar tex-font-lock-keywords
-; ;; Regexps updated with help from Ulrik Dickow <dickow@nbi.dk>.
-; '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}"
-; 2 font-lock-function-name-face)
-; ("\\\\\\(cite\\|label\\|pageref\\|ref\\){\\([^} \t\n]+\\)}"
-; 2 font-lock-reference-face)
-; ;; It seems a bit dubious to use `bold' and `italic' faces since we might
-; ;; not be able to display those fonts.
-; ("{\\\\bf\\([^}]+\\)}" 1 'bold keep)
-; ("{\\\\\\(em\\|it\\|sl\\)\\([^}]+\\)}" 2 'italic keep)
-; ("\\\\\\([a-zA-Z@]+\\|.\\)" . font-lock-keyword-face)
-; ("^[ \t\n]*\\\\def[\\\\@]\\(\\w+\\)" 1 font-lock-function-name-face keep))
- ;; Rewritten and extended for LaTeX2e by Ulrik Dickow <dickow@nbi.dk>.
- '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}"
- 2 font-lock-function-name-face)
- ("\\\\\\(cite\\|label\\|pageref\\|ref\\){\\([^} \t\n]+\\)}"
- 2 font-lock-reference-face)
- ("^[ \t]*\\\\def\\\\\\(\\(\\w\\|@\\)+\\)" 1 font-lock-function-name-face)
- "\\\\\\([a-zA-Z@]+\\|.\\)"
- ;; It seems a bit dubious to use `bold' and `italic' faces since we might
- ;; not be able to display those fonts.
- ;; LaTeX2e: \emph{This is emphasized}.
- ("\\\\emph{\\([^}]+\\)}" 1 'italic keep)
- ;; LaTeX2e: \textbf{This is bold}, \textit{...}, \textsl{...}
- ("\\\\text\\(\\(bf\\)\\|it\\|sl\\){\\([^}]+\\)}"
- 3 (if (match-beginning 2) 'bold 'italic) keep)
- ;; Old-style bf/em/it/sl. Stop at `\\' and un-escaped `&', for good tables.
- ("\\\\\\(\\(bf\\)\\|em\\|it\\|sl\\)\\>\\(\\([^}&\\]\\|\\\\[^\\]\\)+\\)"
- 3 (if (match-beginning 2) 'bold 'italic) keep))
- "Default expressions to highlight in TeX modes.")
-
-;;; User choices.
-
-;; These provide a means to fontify types not defined by the language. Those
-;; types might be the user's own or they might be generally accepted and used.
-;; Generally excepted types are used to provide default variable values.
-
-(defvar c-font-lock-extra-types '("FILE" "\\sw+_t")
- "*List of extra types to fontify in C mode.
-Each list item should be a regexp without word-delimiters or parentheses.
-For example, a value of (\"FILE\" \"\\\\sw+_t\") means the word FILE and words
-ending in _t are treated as type names.")
-
-(defvar c++-font-lock-extra-types nil
- "*List of extra types to fontify in C++ mode.
-Each list item should be a regexp without word-delimiters or parentheses.
-For example, a value of (\"String\") means the word String is treated as a type
-name.")
-
-(defvar objc-font-lock-extra-types '("Class" "BOOL" "IMP" "SEL")
- "*List of extra types to fontify in Objective-C mode.
-Each list item should be a regexp without word-delimiters or parentheses.
-For example, a value of (\"Class\" \"BOOL\" \"IMP\" \"SEL\") means the words
-Class, BOOL, IMP and SEL are treated as type names.")
-
-(defvar java-font-lock-extra-types '("[A-Z\300-\326\330-\337]\\sw+")
- "*List of extra types to fontify in Java mode.
-Each list item should be a regexp without word-delimiters or parentheses.
-For example, a value of (\"[A-Z\300-\326\330-\337]\\\\sw+\") means capitalised
-words (and words conforming to the Java id spec) are treated as type names.")
-
-;;; C.
-
-;; [Murmur murmur murmur] Maestro, drum-roll please... [Murmur murmur murmur.]
-;; Ahem. [Murmur murmur murmur] Lay-dees an Gennel-men. [Murmur murmur shhh!]
-;; I am most proud and humbly honoured today [murmur murmur cough] to present
-;; to you good people, the winner of the Second Millennium Award for The Most
-;; Hairy Language Syntax. [Ahhh!] All rise please. [Shuffle shuffle
-;; shuffle.] And a round of applause please. For... The C Language! [Roar.]
-;;
-;; Thank you... You are too kind... It is with a feeling of great privilege
-;; and indeed emotion [sob] that I accept this award. It has been a long hard
-;; road. But we know our destiny. And our future. For we must not rest.
-;; There are more tokens to overload, more shoehorn, more methodologies. But
-;; more is a plus! [Ha ha ha.] And more means plus! [Ho ho ho.] The future
-;; is C++! [Ohhh!] The Third Millennium Award will be ours! [Roar.]
-
-(defconst c-font-lock-keywords-1 nil
- "Subdued level highlighting for C mode.")
-
-(defconst c-font-lock-keywords-2 nil
- "Medium level highlighting for C mode.
-See also `c-font-lock-extra-types'.")
-
-(defconst c-font-lock-keywords-3 nil
- "Gaudy level highlighting for C mode.
-See also `c-font-lock-extra-types'.")
-
-(let ((c-keywords
-; ("break" "continue" "do" "else" "for" "if" "return" "switch" "while")
- "break\\|continue\\|do\\|else\\|for\\|if\\|return\\|switch\\|while")
- (c-type-types
-; ("auto" "extern" "register" "static" "typedef" "struct" "union" "enum"
-; "signed" "unsigned" "short" "long" "int" "char" "float" "double"
-; "void" "volatile" "const")
- `(mapconcat 'identity
- (cons
- (,@ (concat "auto\\|c\\(har\\|onst\\)\\|double\\|" ; 6 ()s deep.
- "e\\(num\\|xtern\\)\\|float\\|int\\|long\\|register\\|"
- "s\\(hort\\|igned\\|t\\(atic\\|ruct\\)\\)\\|typedef\\|"
- "un\\(ion\\|signed\\)\\|vo\\(id\\|latile\\)"))
- c-font-lock-extra-types)
- "\\|"))
- )
- (setq c-font-lock-keywords-1
- (list
- ;;
- ;; These are all anchored at the beginning of line for speed.
- ;; Note that `c++-font-lock-keywords-1' depends on `c-font-lock-keywords-1'.
- ;;
- ;; Fontify function name definitions (GNU style; without type on line).
- '("^\\(\\sw+\\)[ \t]*(" 1 font-lock-function-name-face)
- ;;
- ;; Fontify error directives.
- '("^#[ \t]*error[ \t]+\\(.+\\)" 1 font-lock-warning-face prepend)
- ;;
- ;; Fontify filenames in #include <...> preprocessor directives as strings.
- '("^#[ \t]*\\(import\\|include\\)[ \t]+\\(<[^>\"\n]*>?\\)"
- 2 font-lock-string-face)
- ;;
- ;; Fontify function macro names.
- '("^#[ \t]*define[ \t]+\\(\\sw+\\)(" 1 font-lock-function-name-face)
- ;;
- ;; Fontify symbol names in #elif or #if ... defined preprocessor directives.
- '("^#[ \t]*\\(elif\\|if\\)\\>"
- ("\\<\\(defined\\)\\>[ \t]*(?\\(\\sw+\\)?" nil nil
- (1 font-lock-reference-face) (2 font-lock-variable-name-face nil t)))
- ;;
- ;; Fontify otherwise as symbol names, and the preprocessor directive names.
- '("^#[ \t]*\\(\\sw+\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-reference-face) (2 font-lock-variable-name-face nil t))
- ))
-
- (setq c-font-lock-keywords-2
- (append c-font-lock-keywords-1
- (list
- ;;
- ;; Simple regexps for speed.
- ;;
- ;; Fontify all type specifiers.
- `(eval .
- (cons (concat "\\<\\(" (,@ c-type-types) "\\)\\>") 'font-lock-type-face))
- ;;
- ;; Fontify all builtin keywords (except case, default and goto; see below).
- (concat "\\<\\(" c-keywords "\\)\\>")
- ;;
- ;; Fontify case/goto keywords and targets, and case default/goto tags.
- '("\\<\\(case\\|goto\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-reference-face nil t))
- ;; Anders Lindgren <andersl@csd.uu.se> points out that it is quicker to use
- ;; MATCH-ANCHORED to effectively anchor the regexp on the left.
- '(":" ("^[ \t]*\\(\\sw+\\)[ \t]*:"
- (beginning-of-line) (end-of-line)
- (1 font-lock-reference-face)))
- )))
-
- (setq c-font-lock-keywords-3
- (append c-font-lock-keywords-2
- ;;
- ;; More complicated regexps for more complete highlighting for types.
- ;; We still have to fontify type specifiers individually, as C is so hairy.
- (list
- ;;
- ;; Fontify all storage classes and type specifiers, plus their items.
- `(eval .
- (list (concat "\\<\\(" (,@ c-type-types) "\\)\\>"
- "\\([ \t*&]+\\sw+\\>\\)*")
- ;; Fontify each declaration item.
- '(font-lock-match-c-style-declaration-item-and-skip-to-next
- ;; Start with point after all type specifiers.
- (goto-char (or (match-beginning 8) (match-end 1)))
- ;; Finish with point after first type specifier.
- (goto-char (match-end 1))
- ;; Fontify as a variable or function name.
- (1 (if (match-beginning 2)
- font-lock-function-name-face
- font-lock-variable-name-face)))))
- ;;
- ;; Fontify structures, or typedef names, plus their items.
- '("\\(}\\)[ \t*]*\\sw"
- (font-lock-match-c-style-declaration-item-and-skip-to-next
- (goto-char (match-end 1)) nil
- (1 (if (match-beginning 2)
- font-lock-function-name-face
- font-lock-variable-name-face))))
- ;;
- ;; Fontify anything at beginning of line as a declaration or definition.
- '("^\\(\\sw+\\)\\>\\([ \t*]+\\sw+\\>\\)*"
- (1 font-lock-type-face)
- (font-lock-match-c-style-declaration-item-and-skip-to-next
- (goto-char (or (match-beginning 2) (match-end 1))) nil
- (1 (if (match-beginning 2)
- font-lock-function-name-face
- font-lock-variable-name-face))))
- )))
- )
-
-(defvar c-font-lock-keywords c-font-lock-keywords-1
- "Default expressions to highlight in C mode.
-See also `c-font-lock-extra-types'.")
-
-;;; C++.
-
-(defconst c++-font-lock-keywords-1 nil
- "Subdued level highlighting for C++ mode.")
-
-(defconst c++-font-lock-keywords-2 nil
- "Medium level highlighting for C++ mode.
-See also `c++-font-lock-extra-types'.")
-
-(defconst c++-font-lock-keywords-3 nil
- "Gaudy level highlighting for C++ mode.
-See also `c++-font-lock-extra-types'.")
-
-(defun font-lock-match-c++-style-declaration-item-and-skip-to-next (limit)
- ;; Regexp matches after point: word<word>::word (
- ;; ^^^^ ^^^^ ^^^^ ^
- ;; Where the match subexpressions are: 1 3 5 6
- ;;
- ;; Item is delimited by (match-beginning 1) and (match-end 1).
- ;; If (match-beginning 3) is non-nil, that part of the item incloses a `<>'.
- ;; If (match-beginning 5) is non-nil, that part of the item follows a `::'.
- ;; If (match-beginning 6) is non-nil, the item is followed by a `('.
- (when (looking-at (eval-when-compile
- (concat "[ \t*&]*\\(\\sw+\\)"
- "\\(<\\(\\sw+\\)[ \t*&]*>\\)?"
- "\\(::\\**\\(\\sw+\\)\\)?"
- "[ \t]*\\((\\)?")))
- (save-match-data
- (condition-case nil
- (save-restriction
- ;; Restrict to the end of line, currently guaranteed to be LIMIT.
- (narrow-to-region (point-min) limit)
- (goto-char (match-end 1))
- ;; Move over any item value, etc., to the next item.
- (while (not (looking-at "[ \t]*\\(\\(,\\)\\|;\\|$\\)"))
- (goto-char (or (scan-sexps (point) 1) (point-max))))
- (goto-char (match-end 2)))
- (error t)))))
-
-(let* ((c++-keywords
-; ("break" "continue" "do" "else" "for" "if" "return" "switch" "while"
-; "asm" "catch" "delete" "new" "operator" "sizeof" "this" "throw" "try"
-; ;; Eric Hopper <hopper@omnifarious.mn.org> says these are new.
-; "static_cast" "dynamic_cast" "const_cast" "reinterpret_cast")
- (concat "asm\\|break\\|c\\(atch\\|on\\(st_cast\\|tinue\\)\\)\\|"
- "d\\(elete\\|o\\|ynamic_cast\\)\\|else\\|for\\|if\\|new\\|"
- "operator\\|re\\(interpret_cast\\|turn\\)\\|"
- "s\\(izeof\\|tatic_cast\\|"
- "witch\\)\\|t\\(h\\(is\\|row\\)\\|ry\\)\\|while"))
- (c++-operators
- (mapconcat 'identity
- (mapcar 'regexp-quote
- ;; Taken from Stroustrup, minus keywords otherwise fontified.
- (sort '("+" "-" "*" "/" "%" "^" "&" "|" "~" "!" "=" "<" ">"
- "+=" "-=" "*=" "/=" "%=" "^=" "&=" "|=" "<<" ">>"
- ">>=" "<<=" "==" "!=" "<=" ">=" "&&" "||" "++" "--"
- "->*" "," "->" "[]" "()")
- (function (lambda (a b) (> (length a) (length b))))))
- "\\|"))
- (c++-type-types
-; ("auto" "extern" "register" "static" "typedef" "struct" "union" "enum"
-; "signed" "unsigned" "short" "long" "int" "char" "float" "double"
-; "void" "volatile" "const" "inline" "friend" "bool"
-; "virtual" "complex" "template"
-; ;; Eric Hopper <hopper@omnifarious.mn.org> says these are new.
-; "namespace" "using")
- `(mapconcat 'identity
- (cons
- (,@ (concat "auto\\|bool\\|c\\(har\\|o\\(mplex\\|nst\\)\\)\\|"
- "double\\|e\\(num\\|xtern\\)\\|f\\(loat\\|riend\\)\\|"
- "in\\(line\\|t\\)\\|long\\|namespace\\|register\\|"
- "s\\(hort\\|igned\\|t\\(atic\\|ruct\\)\\)\\|"
- "t\\(emplate\\|ypedef\\)\\|"
- "u\\(n\\(ion\\|signed\\)\\|sing\\)\\|"
- "v\\(irtual\\|o\\(id\\|latile\\)\\)")) ; 12 ()s deep.
- c++-font-lock-extra-types)
- "\\|"))
- (c++-type-suffix "\\(<\\(\\sw+\\)[ \t*&]*>\\)?\\(::\\**\\(\\sw+\\)\\)?")
- (c++-type-spec (concat "\\(\\sw+\\)\\>" c++-type-suffix))
- )
- (setq c++-font-lock-keywords-1
- (append
- ;;
- ;; The list `c-font-lock-keywords-1' less that for function names.
- (cdr c-font-lock-keywords-1)
- (list
- ;;
- ;; Class names etc.
- (list (concat "\\<\\(class\\|public\\|private\\|protected\\)\\>[ \t]*"
- "\\(" c++-type-spec "\\)?")
- '(1 font-lock-type-face)
- '(3 (if (match-beginning 6)
- font-lock-type-face
- font-lock-function-name-face) nil t)
- '(5 font-lock-function-name-face nil t)
- '(7 font-lock-function-name-face nil t))
- ;;
- ;; Fontify function name definitions, possibly incorporating class names.
- (list (concat "^" c++-type-spec "[ \t]*(")
- '(1 (if (or (match-beginning 2) (match-beginning 4))
- font-lock-type-face
- font-lock-function-name-face))
- '(3 font-lock-function-name-face nil t)
- '(5 font-lock-function-name-face nil t))
- )))
-
- (setq c++-font-lock-keywords-2
- (append c++-font-lock-keywords-1
- (list
- ;;
- ;; The list `c-font-lock-keywords-2' for C++ plus operator overloading.
- `(eval .
- (cons (concat "\\<\\(" (,@ c++-type-types) "\\)\\>")
- 'font-lock-type-face))
- ;;
- ;; Fontify operator overloading.
- (list (concat "\\<\\(operator\\)\\>[ \t]*\\(" c++-operators "\\)?")
- '(1 font-lock-keyword-face)
- '(2 font-lock-builtin-face nil t))
- ;;
- ;; Fontify case/goto keywords and targets, and case default/goto tags.
- '("\\<\\(case\\|goto\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-reference-face nil t))
- '(":" ("^[ \t]*\\(\\sw+\\)[ \t]*:\\($\\|[^:]\\)"
- (beginning-of-line) (end-of-line)
- (1 font-lock-reference-face)))
- ;;
- ;; Fontify other builtin keywords.
- (cons (concat "\\<\\(" c++-keywords "\\)\\>") 'font-lock-keyword-face)
- ;;
- ;; Eric Hopper <hopper@omnifarious.mn.org> says `true' and `false' are new.
- '("\\<\\(false\\|true\\)\\>" . font-lock-reference-face)
- )))
-
- (setq c++-font-lock-keywords-3
- (append c++-font-lock-keywords-2
- ;;
- ;; More complicated regexps for more complete highlighting for types.
- (list
- ;;
- ;; Fontify all storage classes and type specifiers, plus their items.
- `(eval .
- (list (concat "\\<\\(" (,@ c++-type-types) "\\)\\>" (,@ c++-type-suffix)
- "\\([ \t*&]+" (,@ c++-type-spec) "\\)*")
- ;; Fontify each declaration item.
- '(font-lock-match-c++-style-declaration-item-and-skip-to-next
- ;; Start with point after all type specifiers.
- (goto-char (or (match-beginning 18) (match-end 1)))
- ;; Finish with point after first type specifier.
- (goto-char (match-end 1))
- ;; Fontify as a variable or function name.
- (1 (cond ((or (match-beginning 2) (match-beginning 4))
- font-lock-type-face)
- ((match-beginning 6) font-lock-function-name-face)
- (t font-lock-variable-name-face)))
- (3 font-lock-function-name-face nil t)
- (5 (if (match-beginning 6)
- font-lock-function-name-face
- font-lock-variable-name-face) nil t))))
- ;;
- ;; Fontify structures, or typedef names, plus their items.
- '("\\(}\\)[ \t*]*\\sw"
- (font-lock-match-c++-style-declaration-item-and-skip-to-next
- (goto-char (match-end 1)) nil
- (1 (if (match-beginning 6)
- font-lock-function-name-face
- font-lock-variable-name-face))))
- ;;
- ;; Fontify anything at beginning of line as a declaration or definition.
- (list (concat "^\\(" c++-type-spec "[ \t*&]*\\)+")
- '(font-lock-match-c++-style-declaration-item-and-skip-to-next
- (goto-char (match-beginning 1))
- (goto-char (match-end 1))
- (1 (cond ((or (match-beginning 2) (match-beginning 4))
- font-lock-type-face)
- ((match-beginning 6) font-lock-function-name-face)
- (t font-lock-variable-name-face)))
- (3 font-lock-function-name-face nil t)
- (5 (if (match-beginning 6)
- font-lock-function-name-face
- font-lock-variable-name-face) nil t)))
- )))
- )
-
-(defvar c++-font-lock-keywords c++-font-lock-keywords-1
- "Default expressions to highlight in C++ mode.
-See also `c++-font-lock-extra-types'.")
-
-;;; Objective-C.
-
-(defconst objc-font-lock-keywords-1 nil
- "Subdued level highlighting for Objective-C mode.")
-
-(defconst objc-font-lock-keywords-2 nil
- "Medium level highlighting for Objective-C mode.
-See also `objc-font-lock-extra-types'.")
-
-(defconst objc-font-lock-keywords-3 nil
- "Gaudy level highlighting for Objective-C mode.
-See also `objc-font-lock-extra-types'.")
-
-;; Regexps written with help from Stephen Peters <speters@us.oracle.com> and
-;; Jacques Duthen Prestataire <duthen@cegelec-red.fr>.
-(let ((objc-keywords
-; (make-regexp
-; '("break" "continue" "do" "else" "for" "if" "return" "switch" "while"
-; "sizeof" "self" "super"))
- (concat "break\\|continue\\|do\\|else\\|for\\|if\\|return\\|"
- "s\\(elf\\|izeof\\|uper\\|witch\\)\\|while"))
- (objc-type-types
- `(mapconcat 'identity
- (cons
-; '("auto" "extern" "register" "static" "typedef" "struct" "union"
-; "enum" "signed" "unsigned" "short" "long" "int" "char"
-; "float" "double" "void" "volatile" "const"
-; "id" "oneway" "in" "out" "inout" "bycopy" "byref")
- (,@ (concat "auto\\|by\\(copy\\|ref\\)\\|c\\(har\\|onst\\)\\|"
- "double\\|e\\(num\\|xtern\\)\\|float\\|"
- "i\\([dn]\\|n\\(out\\|t\\)\\)\\|long\\|"
- "o\\(neway\\|ut\\)\\|register\\|s\\(hort\\|igned\\|"
- "t\\(atic\\|ruct\\)\\)\\|typedef\\|"
- "un\\(ion\\|signed\\)\\|vo\\(id\\|latile\\)"))
- objc-font-lock-extra-types)
- "\\|"))
- )
- (setq objc-font-lock-keywords-1
- (append
- ;;
- ;; The list `c-font-lock-keywords-1' less that for function names.
- (cdr c-font-lock-keywords-1)
- (list
- ;;
- ;; Fontify compiler directives.
- '("@\\(\\sw+\\)\\>"
- (1 font-lock-keyword-face)
- ("\\=[ \t:<(,]*\\(\\sw+\\)" nil nil
- (1 font-lock-function-name-face)))
- ;;
- ;; Fontify method names and arguments. Oh Lordy!
- ;; First, on the same line as the function declaration.
- '("^[+-][ \t]*\\(PRIVATE\\)?[ \t]*\\((\\([^)\n]+\\))\\)?[ \t]*\\(\\sw+\\)"
- (1 font-lock-type-face nil t)
- (3 font-lock-type-face nil t)
- (4 font-lock-function-name-face)
- ("\\=[ \t]*\\(\\sw+\\)?:[ \t]*\\((\\([^)\n]+\\))\\)?[ \t]*\\(\\sw+\\)"
- nil nil
- (1 font-lock-function-name-face nil t)
- (3 font-lock-type-face nil t)
- (4 font-lock-variable-name-face)))
- ;; Second, on lines following the function declaration.
- '(":" ("^[ \t]*\\(\\sw+\\)?:[ \t]*\\((\\([^)\n]+\\))\\)?[ \t]*\\(\\sw+\\)"
- (beginning-of-line) (end-of-line)
- (1 font-lock-function-name-face nil t)
- (3 font-lock-type-face nil t)
- (4 font-lock-variable-name-face)))
- )))
-
- (setq objc-font-lock-keywords-2
- (append objc-font-lock-keywords-1
- (list
- ;;
- ;; Simple regexps for speed.
- ;;
- ;; Fontify all type specifiers.
- `(eval .
- (cons (concat "\\<\\(" (,@ objc-type-types) "\\)\\>")
- 'font-lock-type-face))
- ;;
- ;; Fontify all builtin keywords (except case, default and goto; see below).
- (concat "\\<\\(" objc-keywords "\\)\\>")
- ;;
- ;; Fontify case/goto keywords and targets, and case default/goto tags.
- '("\\<\\(case\\|goto\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-reference-face nil t))
- ;; Fontify tags iff sole statement on line, otherwise we detect selectors.
- '(":" ("^[ \t]*\\(\\sw+\\)[ \t]*:[ \t]*$"
- (beginning-of-line) (end-of-line)
- (1 font-lock-reference-face)))
- ;;
- ;; Fontify null object pointers.
- '("\\<\\(Nil\\|nil\\)\\>" 1 font-lock-reference-face)
- )))
-
- (setq objc-font-lock-keywords-3
- (append objc-font-lock-keywords-2
- ;;
- ;; More complicated regexps for more complete highlighting for types.
- ;; We still have to fontify type specifiers individually, as C is so hairy.
- (list
- ;;
- ;; Fontify all storage classes and type specifiers, plus their items.
- `(eval .
- (list (concat "\\<\\(" (,@ objc-type-types) "\\)\\>"
- "\\([ \t*&]+\\sw+\\>\\)*")
- ;; Fontify each declaration item.
- '(font-lock-match-c-style-declaration-item-and-skip-to-next
- ;; Start with point after all type specifiers.
- (goto-char (or (match-beginning 2) (match-end 1)))
- ;; Finish with point after first type specifier.
- (goto-char (match-end 1))
- ;; Fontify as a variable or function name.
- (1 (if (match-beginning 2)
- font-lock-function-name-face
- font-lock-variable-name-face)))))
- ;;
- ;; Fontify structures, or typedef names, plus their items.
- '("\\(}\\)[ \t*]*\\sw"
- (font-lock-match-c-style-declaration-item-and-skip-to-next
- (goto-char (match-end 1)) nil
- (1 (if (match-beginning 2)
- font-lock-function-name-face
- font-lock-variable-name-face))))
- ;;
- ;; Fontify anything at beginning of line as a declaration or definition.
- '("^\\(\\sw+\\)\\>\\([ \t*]+\\sw+\\>\\)*"
- (1 font-lock-type-face)
- (font-lock-match-c-style-declaration-item-and-skip-to-next
- (goto-char (or (match-beginning 2) (match-end 1))) nil
- (1 (if (match-beginning 2)
- font-lock-function-name-face
- font-lock-variable-name-face))))
- )))
- )
-
-(defvar objc-font-lock-keywords objc-font-lock-keywords-1
- "Default expressions to highlight in Objective-C mode.
-See also `objc-font-lock-extra-types'.")
-
-;;; Java.
-
-(defconst java-font-lock-keywords-1 nil
- "Subdued level highlighting for Java mode.")
-
-(defconst java-font-lock-keywords-2 nil
- "Medium level highlighting for Java mode.
-See also `java-font-lock-extra-types'.")
-
-(defconst java-font-lock-keywords-3 nil
- "Gaudy level highlighting for Java mode.
-See also `java-font-lock-extra-types'.")
-
-;; Regexps written with help from Fred White <fwhite@bbn.com> and
-;; Anders Lindgren <andersl@csd.uu.se>.
-(let ((java-keywords
- (concat "\\<\\("
-; (make-regexp
-; '("catch" "do" "else" "super" "this" "finally" "for" "if"
-;; ;; Anders Lindgren <andersl@csd.uu.se> says these have gone.
-;; "cast" "byvalue" "future" "generic" "operator" "var"
-;; "inner" "outer" "rest"
-; "interface" "return" "switch" "throw" "try" "while")
- "catch\\|do\\|else\\|f\\(inally\\|or\\)\\|"
- "i\\(f\\|nterface\\)\\|return\\|s\\(uper\\|witch\\)\\|"
- "t\\(h\\(is\\|row\\)\\|ry\\)\\|while"
- "\\)\\>"))
- ;;
- ;; These are immediately followed by an object name.
- (java-minor-types
- (mapconcat 'identity
- '("boolean" "char" "byte" "short" "int" "long" "float" "double" "void")
- "\\|"))
- ;;
- ;; These are eventually followed by an object name.
- (java-major-types
-; (make-regexp
-; '("abstract" "const" "final" "synchronized" "transient" "static"
-;; ;; Anders Lindgren <andersl@csd.uu.se> says this has gone.
-;; "threadsafe"
-; "volatile" "public" "private" "protected" "native")
- (concat "abstract\\|const\\|final\\|native\\|"
- "p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|"
- "s\\(tatic\\|ynchronized\\)\\|transient\\|volatile"))
- ;;
- ;; Random types immediately followed by an object name.
- (java-other-types
- '(mapconcat 'identity (cons "\\sw+\\.\\sw+" java-font-lock-extra-types)
- "\\|"))
- )
- (setq java-font-lock-keywords-1
- (list
- ;;
- ;; Fontify class names.
- '("\\<\\(class\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-type-face) (2 font-lock-function-name-face nil t))
- ;;
- ;; Fontify package names in import directives.
- '("\\<\\(import\\|package\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-reference-face nil t))
- ))
-
- (setq java-font-lock-keywords-2
- (append java-font-lock-keywords-1
- (list
- ;;
- ;; Fontify all builtin type specifiers.
- (cons (concat "\\<\\(" java-minor-types "\\|" java-major-types "\\)\\>")
- 'font-lock-type-face)
- ;;
- ;; Fontify all builtin keywords (except below).
- (concat "\\<\\(" java-keywords "\\)\\>")
- ;;
- ;; Fontify keywords and targets, and case default/goto tags.
- (list "\\<\\(break\\|case\\|continue\\|goto\\)\\>[ \t]*\\(\\sw+\\)?"
- '(1 font-lock-keyword-face) '(2 font-lock-reference-face nil t))
- '(":" ("^[ \t]*\\(\\sw+\\)[ \t]*:"
- (beginning-of-line) (end-of-line)
- (1 font-lock-reference-face)))
- ;;
- ;; Fontify keywords and types; the first can be followed by a type list.
- (list (concat "\\<\\("
- "implements\\|throws\\|"
- "\\(extends\\|instanceof\\|new\\)"
- "\\)\\>[ \t]*\\(\\sw+\\)?")
- '(1 font-lock-keyword-face) '(3 font-lock-type-face nil t)
- '("\\=[ \t]*,[ \t]*\\(\\sw+\\)"
- (if (match-beginning 2) (goto-char (match-end 2))) nil
- (1 font-lock-type-face)))
- ;;
- ;; Fontify all constants.
- '("\\<\\(false\\|null\\|true\\)\\>" . font-lock-reference-face)
- ;;
- ;; Javadoc tags within comments.
- '("@\\(author\\|exception\\|return\\|see\\|version\\)\\>"
- (1 font-lock-reference-face prepend))
- '("@\\(param\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-reference-face prepend)
- (2 font-lock-variable-name-face prepend t))
- )))
-
- (setq java-font-lock-keywords-3
- (append java-font-lock-keywords-2
- ;;
- ;; More complicated regexps for more complete highlighting for types.
- ;; We still have to fontify type specifiers individually, as Java is hairy.
- (list
- ;;
- ;; Fontify random types in casts.
- `(eval .
- (list (concat "(\\(" (,@ java-other-types) "\\))"
- "[ \t]*\\(\\sw\\|[\"\(]\\)")
- ;; Fontify the type name.
- '(1 font-lock-type-face)))
- ;;
- ;; Fontify random types immediately followed by an item or items.
- `(eval .
- (list (concat "\\<\\(" (,@ java-other-types) "\\)\\>"
- "\\([ \t]*\\[[ \t]*\\]\\)*"
- "[ \t]*\\sw")
- ;; Fontify the type name.
- '(1 font-lock-type-face)))
- `(eval .
- (list (concat "\\<\\(" (,@ java-other-types) "\\)\\>"
- "\\([ \t]*\\[[ \t]*\\]\\)*"
- "\\([ \t]*\\sw\\)")
- ;; Fontify each declaration item.
- '(font-lock-match-c-style-declaration-item-and-skip-to-next
- ;; Start and finish with point after the type specifier.
- (goto-char (match-beginning 3)) (goto-char (match-beginning 3))
- ;; Fontify as a variable or function name.
- (1 (if (match-beginning 2)
- font-lock-function-name-face
- font-lock-variable-name-face)))))
- ;;
- ;; Fontify those that are immediately followed by an item or items.
- (list (concat "\\<\\(" java-minor-types "\\)\\>"
- "\\([ \t]*\\[[ \t]*\\]\\)*")
- ;; Fontify each declaration item.
- '(font-lock-match-c-style-declaration-item-and-skip-to-next
- ;; Start and finish with point after the type specifier.
- nil (goto-char (match-end 0))
- ;; Fontify as a variable or function name.
- (1 (if (match-beginning 2)
- font-lock-function-name-face
- font-lock-variable-name-face))))
- ;;
- ;; Fontify those that are eventually followed by an item or items.
- (list (concat "\\<\\(" java-major-types "\\)\\>"
- "\\([ \t]+\\sw+\\>"
- "\\([ \t]*\\[[ \t]*\\]\\)*"
- "\\)*")
- ;; Fontify each declaration item.
- '(font-lock-match-c-style-declaration-item-and-skip-to-next
- ;; Start with point after all type specifiers.
- (goto-char (or (match-beginning 2) (match-end 1)))
- ;; Finish with point after first type specifier.
- (goto-char (match-end 1))
- ;; Fontify as a variable or function name.
- (1 (if (match-beginning 2)
- font-lock-function-name-face
- font-lock-variable-name-face))))
- )))
- )
-
-(defvar java-font-lock-keywords java-font-lock-keywords-1
- "Default expressions to highlight in Java mode.
-See also `java-font-lock-extra-types'.")
-
-;; Install ourselves:
-
-(unless (assq 'font-lock-mode minor-mode-alist)
- (push '(font-lock-mode " Font") minor-mode-alist))
-
-;; Provide ourselves:
-
-(provide 'font-lock)
-
-;;; font-lock.el ends here
diff --git a/lisp/format.el b/lisp/format.el
deleted file mode 100644
index 0b0910cef66..00000000000
--- a/lisp/format.el
+++ /dev/null
@@ -1,813 +0,0 @@
-;;; format.el --- read and save files in multiple formats
-
-;; Copyright (c) 1994, 1995 Free Software Foundation
-
-;; Author: Boris Goldowsky <boris@gnu.ai.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This file defines a unified mechanism for saving & loading files stored
-;; in different formats. `format-alist' contains information that directs
-;; Emacs to call an encoding or decoding function when reading or writing
-;; files that match certain conditions.
-;;
-;; When a file is visited, its format is determined by matching the
-;; beginning of the file against regular expressions stored in
-;; `format-alist'. If this fails, you can manually translate the buffer
-;; using `format-decode-buffer'. In either case, the formats used are
-;; listed in the variable `buffer-file-format', and become the default
-;; format for saving the buffer. To save a buffer in a different format,
-;; change this variable, or use `format-write-file'.
-;;
-;; Auto-save files are normally created in the same format as the visited
-;; file, but the variable `auto-save-file-format' can be set to a
-;; particularly fast or otherwise preferred format to be used for
-;; auto-saving (or nil to do no encoding on auto-save files, but then you
-;; risk losing any text-properties in the buffer).
-;;
-;; You can manually translate a buffer into or out of a particular format
-;; with the functions `format-encode-buffer' and `format-decode-buffer'.
-;; To translate just the region use the functions `format-encode-region'
-;; and `format-decode-region'.
-;;
-;; You can define a new format by writing the encoding and decoding
-;; functions, and adding an entry to `format-alist'. See enriched.el for
-;; an example of how to implement a file format. There are various
-;; functions defined in this file that may be useful for writing the
-;; encoding and decoding functions:
-;; * `format-annotate-region' and `format-deannotate-region' allow a
-;; single alist of information to be used for encoding and decoding.
-;; The alist defines a correspondence between strings in the file
-;; ("annotations") and text-properties in the buffer.
-;; * `format-replace-strings' is similarly useful for doing simple
-;; string->string translations in a reversible manner.
-
-;;; Code:
-
-(put 'buffer-file-format 'permanent-local t)
-
-(defvar format-alist
- '((text/enriched "Extended MIME text/enriched format."
- "Content-[Tt]ype:[ \t]*text/enriched"
- enriched-decode enriched-encode t enriched-mode)
- (plain "Standard ASCII format, no text properties."
- ;; Plain only exists so that there is an obvious neutral choice in
- ;; the completion list.
- nil nil nil nil nil))
- "List of information about understood file formats.
-Elements are of the form \(NAME DOC-STR REGEXP FROM-FN TO-FN MODIFY MODE-FN).
-NAME is a symbol, which is stored in `buffer-file-format'.
-DOC-STR should be a single line providing more information about the
- format. It is currently unused, but in the future will be shown to
- the user if they ask for more information.
-REGEXP is a regular expression to match against the beginning of the file;
- it should match only files in that format.
-FROM-FN is called to decode files in that format; it gets two args, BEGIN
- and END, and can make any modifications it likes, returning the new
- end. It must make sure that the beginning of the file no longer
- matches REGEXP, or else it will get called again.
-TO-FN is called to encode a region into that format; it is passed three
- arguments: BEGIN, END, and BUFFER. BUFFER is the original buffer that
- the data being written came from, which the function could use, for
- example, to find the values of local variables. TO-FN should either
- return a list of annotations like `write-region-annotate-functions',
- or modify the region and return the new end.
-MODIFY, if non-nil, means the TO-FN wants to modify the region. If nil,
- TO-FN will not make any changes but will instead return a list of
- annotations.
-MODE-FN, if specified, is called when visiting a file with that format.")
-
-;;; Basic Functions (called from Lisp)
-
-(defun format-annotate-function (format from to orig-buf)
- "Returns annotations for writing region as FORMAT.
-FORMAT is a symbol naming one of the formats defined in `format-alist',
-it must be a single symbol, not a list like `buffer-file-format'.
-FROM and TO delimit the region to be operated on in the current buffer.
-ORIG-BUF is the original buffer that the data came from.
-This function works like a function on `write-region-annotate-functions':
-it either returns a list of annotations, or returns with a different buffer
-current, which contains the modified text to write.
-
-For most purposes, consider using `format-encode-region' instead."
- ;; This function is called by write-region (actually build-annotations)
- ;; for each element of buffer-file-format.
- (let* ((info (assq format format-alist))
- (to-fn (nth 4 info))
- (modify (nth 5 info)))
- (if to-fn
- (if modify
- ;; To-function wants to modify region. Copy to safe place.
- (let ((copy-buf (get-buffer-create " *Format Temp*")))
- (copy-to-buffer copy-buf from to)
- (set-buffer copy-buf)
- (format-insert-annotations write-region-annotations-so-far from)
- (funcall to-fn (point-min) (point-max) orig-buf)
- nil)
- ;; Otherwise just call function, it will return annotations.
- (funcall to-fn from to orig-buf)))))
-
-(defun format-decode (format length &optional visit-flag)
- ;; This function is called by insert-file-contents whenever a file is read.
- "Decode text from any known FORMAT.
-FORMAT is a symbol appearing in `format-alist' or a list of such symbols,
-or nil, in which case this function tries to guess the format of the data by
-matching against the regular expressions in `format-alist'. After a match is
-found and the region decoded, the alist is searched again from the beginning
-for another match.
-
-Second arg LENGTH is the number of characters following point to operate on.
-If optional third arg VISIT-FLAG is true, set `buffer-file-format'
-to the list of formats used, and call any mode functions defined for those
-formats.
-
-Returns the new length of the decoded region.
-
-For most purposes, consider using `format-decode-region' instead."
- (let ((mod (buffer-modified-p))
- (begin (point))
- (end (+ (point) length)))
- (if (null format)
- ;; Figure out which format it is in, remember list in `format'.
- (let ((try format-alist))
- (while try
- (let* ((f (car try))
- (regexp (nth 2 f))
- (p (point)))
- (if (and regexp (looking-at regexp)
- (< (match-end 0) (+ begin length)))
- (progn
- (setq format (cons (car f) format))
- ;; Decode it
- (if (nth 3 f) (setq end (funcall (nth 3 f) begin end)))
- ;; Call visit function if required
- (if (and visit-flag (nth 6 f)) (funcall (nth 6 f) 1))
- ;; Safeguard against either of the functions changing pt.
- (goto-char p)
- ;; Rewind list to look for another format
- (setq try format-alist))
- (setq try (cdr try))))))
- ;; Deal with given format(s)
- (or (listp format) (setq format (list format)))
- (let ((do format) f)
- (while do
- (or (setq f (assq (car do) format-alist))
- (error "Unknown format" (car do)))
- ;; Decode:
- (if (nth 3 f) (setq end (funcall (nth 3 f) begin end)))
- ;; Call visit function if required
- (if (and visit-flag (nth 6 f)) (funcall (nth 6 f) 1))
- (setq do (cdr do)))))
- (if visit-flag
- (setq buffer-file-format format))
- (set-buffer-modified-p mod)
- ;; Return new length of region
- (- end begin)))
-
-;;;
-;;; Interactive functions & entry points
-;;;
-
-(defun format-decode-buffer (&optional format)
- "Translate the buffer from some FORMAT.
-If the format is not specified, this function attempts to guess.
-`buffer-file-format' is set to the format used, and any mode-functions
-for the format are called."
- (interactive
- (list (format-read "Translate buffer from format (default: guess): ")))
- (save-excursion
- (goto-char (point-min))
- (format-decode format (buffer-size) t)))
-
-(defun format-decode-region (from to &optional format)
- "Decode the region from some format.
-Arg FORMAT is optional; if omitted the format will be determined by looking
-for identifying regular expressions at the beginning of the region."
- (interactive
- (list (region-beginning) (region-end)
- (format-read "Translate region from format (default: guess): ")))
- (save-excursion
- (goto-char from)
- (format-decode format (- to from) nil)))
-
-(defun format-encode-buffer (&optional format)
- "Translate the buffer into FORMAT.
-FORMAT defaults to `buffer-file-format'. It is a symbol naming one of the
-formats defined in `format-alist', or a list of such symbols."
- (interactive
- (list (format-read (format "Translate buffer to format (default %s): "
- buffer-file-format))))
- (format-encode-region (point-min) (point-max) format))
-
-(defun format-encode-region (beg end &optional format)
- "Translate the region into some FORMAT.
-FORMAT defaults to `buffer-file-format', it is a symbol naming
-one of the formats defined in `format-alist', or a list of such symbols."
- (interactive
- (list (region-beginning) (region-end)
- (format-read (format "Translate region to format (default %s): "
- buffer-file-format))))
- (if (null format) (setq format buffer-file-format))
- (if (symbolp format) (setq format (list format)))
- (save-excursion
- (goto-char end)
- (let ((cur-buf (current-buffer))
- (end (point-marker)))
- (while format
- (let* ((info (assq (car format) format-alist))
- (to-fn (nth 4 info))
- (modify (nth 5 info))
- result)
- (if to-fn
- (if modify
- (setq end (funcall to-fn beg end (current-buffer)))
- (format-insert-annotations
- (funcall to-fn beg end (current-buffer)))))
- (setq format (cdr format)))))))
-
-(defun format-write-file (filename format)
- "Write current buffer into a FILE using some FORMAT.
-Makes buffer visit that file and sets the format as the default for future
-saves. If the buffer is already visiting a file, you can specify a directory
-name as FILE, to write a file of the same old name in that directory."
- (interactive
- ;; Same interactive spec as write-file, plus format question.
- (let* ((file (if buffer-file-name
- (read-file-name "Write file: "
- nil nil nil nil)
- (read-file-name "Write file: "
- (cdr (assq 'default-directory
- (buffer-local-variables)))
- nil nil (buffer-name))))
- (fmt (format-read (format "Write file `%s' in format: "
- (file-name-nondirectory file)))))
- (list file fmt)))
- (setq buffer-file-format format)
- (write-file filename))
-
-(defun format-find-file (filename format)
- "Find the file FILE using data format FORMAT.
-If FORMAT is nil then do not do any format conversion."
- (interactive
- ;; Same interactive spec as write-file, plus format question.
- (let* ((file (read-file-name "Find file: "))
- (fmt (format-read (format "Read file `%s' in format: "
- (file-name-nondirectory file)))))
- (list file fmt)))
- (let ((format-alist nil))
- (find-file filename))
- (if format
- (format-decode-buffer format)))
-
-(defun format-insert-file (filename format &optional beg end)
- "Insert the contents of file FILE using data format FORMAT.
-If FORMAT is nil then do not do any format conversion.
-The optional third and fourth arguments BEG and END specify
-the part of the file to read.
-
-The return value is like the value of `insert-file-contents':
-a list (ABSOLUTE-FILE-NAME . SIZE)."
- (interactive
- ;; Same interactive spec as write-file, plus format question.
- (let* ((file (read-file-name "Find file: "))
- (fmt (format-read (format "Read file `%s' in format: "
- (file-name-nondirectory file)))))
- (list file fmt)))
- (let (value size)
- (let ((format-alist nil))
- (setq value (insert-file-contents filename nil beg end))
- (setq size (nth 1 value)))
- (if format
- (setq size (format-decode size format)
- value (cons (car value) size)))
- value))
-
-(defun format-read (&optional prompt)
- "Read and return the name of a format.
-Return value is a list, like `buffer-file-format'; it may be nil.
-Formats are defined in `format-alist'. Optional arg is the PROMPT to use."
- (let* ((table (mapcar (lambda (x) (list (symbol-name (car x))))
- format-alist))
- (ans (completing-read (or prompt "Format: ") table nil t)))
- (if (not (equal "" ans)) (list (intern ans)))))
-
-
-;;;
-;;; Below are some functions that may be useful in writing encoding and
-;;; decoding functions for use in format-alist.
-;;;
-
-(defun format-replace-strings (alist &optional reverse beg end)
- "Do multiple replacements on the buffer.
-ALIST is a list of (from . to) pairs, which should be proper arguments to
-`search-forward' and `replace-match' respectively.
-Optional 2nd arg REVERSE, if non-nil, means the pairs are (to . from), so that
-you can use the same list in both directions if it contains only literal
-strings.
-Optional args BEGIN and END specify a region of the buffer to operate on."
- (save-excursion
- (save-restriction
- (or beg (setq beg (point-min)))
- (if end (narrow-to-region (point-min) end))
- (while alist
- (let ((from (if reverse (cdr (car alist)) (car (car alist))))
- (to (if reverse (car (cdr alist)) (cdr (car alist)))))
- (goto-char beg)
- (while (search-forward from nil t)
- (goto-char (match-beginning 0))
- (insert to)
- (set-text-properties (- (point) (length to)) (point)
- (text-properties-at (point)))
- (delete-region (point) (+ (point) (- (match-end 0)
- (match-beginning 0)))))
- (setq alist (cdr alist)))))))
-
-;;; Some list-manipulation functions that we need.
-
-(defun format-delq-cons (cons list)
- "Remove the given CONS from LIST by side effect,
-and return the new LIST. Since CONS could be the first element
-of LIST, write `\(setq foo \(format-delq-cons element foo))' to be sure of
-changing the value of `foo'."
- (if (eq cons list)
- (cdr list)
- (let ((p list))
- (while (not (eq (cdr p) cons))
- (if (null p) (error "format-delq-cons: not an element."))
- (setq p (cdr p)))
- ;; Now (cdr p) is the cons to delete
- (setcdr p (cdr cons))
- list)))
-
-(defun format-make-relatively-unique (a b)
- "Delete common elements of lists A and B, return as pair.
-Compares using `equal'."
- (let* ((acopy (copy-sequence a))
- (bcopy (copy-sequence b))
- (tail acopy))
- (while tail
- (let ((dup (member (car tail) bcopy))
- (next (cdr tail)))
- (if dup (setq acopy (format-delq-cons tail acopy)
- bcopy (format-delq-cons dup bcopy)))
- (setq tail next)))
- (cons acopy bcopy)))
-
-(defun format-common-tail (a b)
- "Given two lists that have a common tail, return it.
-Compares with `equal', and returns the part of A that is equal to the
-equivalent part of B. If even the last items of the two are not equal,
-returns nil."
- (let ((la (length a))
- (lb (length b)))
- ;; Make sure they are the same length
- (if (> la lb)
- (setq a (nthcdr (- la lb) a))
- (setq b (nthcdr (- lb la) b))))
- (while (not (equal a b))
- (setq a (cdr a)
- b (cdr b)))
- a)
-
-(defun format-reorder (items order)
- "Arrange ITEMS to following partial ORDER.
-Elements of ITEMS equal to elements of ORDER will be rearranged to follow the
-ORDER. Unmatched items will go last."
- (if order
- (let ((item (member (car order) items)))
- (if item
- (cons (car item)
- (format-reorder (format-delq-cons item items)
- (cdr order)))
- (format-reorder items (cdr order))))
- items))
-
-(put 'face 'format-list-valued t) ; These text-properties take values
-(put 'unknown 'format-list-valued t) ; that are lists, the elements of which
- ; should be considered separately.
- ; See format-deannotate-region and
- ; format-annotate-region.
-
-;;;
-;;; Decoding
-;;;
-
-(defun format-deannotate-region (from to translations next-fn)
- "Translate annotations in the region into text properties.
-This sets text properties between FROM to TO as directed by the
-TRANSLATIONS and NEXT-FN arguments.
-
-NEXT-FN is a function that searches forward from point for an annotation.
-It should return a list of 4 elements: \(BEGIN END NAME POSITIVE). BEGIN and
-END are buffer positions bounding the annotation, NAME is the name searched
-for in TRANSLATIONS, and POSITIVE should be non-nil if this annotation marks
-the beginning of a region with some property, or nil if it ends the region.
-NEXT-FN should return nil if there are no annotations after point.
-
-The basic format of the TRANSLATIONS argument is described in the
-documentation for the `format-annotate-region' function. There are some
-additional things to keep in mind for decoding, though:
-
-When an annotation is found, the TRANSLATIONS list is searched for a
-text-property name and value that corresponds to that annotation. If the
-text-property has several annotations associated with it, it will be used only
-if the other annotations are also in effect at that point. The first match
-found whose annotations are all present is used.
-
-The text property thus determined is set to the value over the region between
-the opening and closing annotations. However, if the text-property name has a
-non-nil `format-list-valued' property, then the value will be consed onto the
-surrounding value of the property, rather than replacing that value.
-
-There are some special symbols that can be used in the \"property\" slot of
-the TRANSLATIONS list: PARAMETER and FUNCTION \(spelled in uppercase).
-Annotations listed under the pseudo-property PARAMETER are considered to be
-arguments of the immediately surrounding annotation; the text between the
-opening and closing parameter annotations is deleted from the buffer but saved
-as a string. The surrounding annotation should be listed under the
-pseudo-property FUNCTION. Instead of inserting a text-property for this
-annotation, the function listed in the VALUE slot is called to make whatever
-changes are appropriate. The function's first two arguments are the START and
-END locations, and the rest of the arguments are any PARAMETERs found in that
-region.
-
-Any annotations that are found by NEXT-FN but not defined by TRANSLATIONS
-are saved as values of the `unknown' text-property \(which is list-valued).
-The TRANSLATIONS list should usually contain an entry of the form
- \(unknown \(nil format-annotate-value))
-to write these unknown annotations back into the file."
- (save-excursion
- (save-restriction
- (narrow-to-region (point-min) to)
- (goto-char from)
- (let (next open-ans todo loc unknown-ans)
- (while (setq next (funcall next-fn))
- (let* ((loc (nth 0 next))
- (end (nth 1 next))
- (name (nth 2 next))
- (positive (nth 3 next))
- (found nil))
-
- ;; Delete the annotation
- (delete-region loc end)
- (if positive
- ;; Positive annotations are stacked, remembering location
- (setq open-ans (cons (list name loc) open-ans))
- ;; It is a negative annotation:
- ;; Close the top annotation & add its text property.
- ;; If the file's nesting is messed up, the close might not match
- ;; the top thing on the open-annotations stack.
- ;; If no matching annotation is open, just ignore the close.
- (if (not (assoc name open-ans))
- (message "Extra closing annotation (%s) in file" name)
- ;; If one is open, but not on the top of the stack, close
- ;; the things in between as well. Set `found' when the real
- ;; one is closed.
- (while (not found)
- (let* ((top (car open-ans)) ; first on stack: should match.
- (top-name (car top))
- (start (car (cdr top))) ; location of start
- (params (cdr (cdr top))) ; parameters
- (aalist translations)
- (matched nil))
- (if (equal name top-name)
- (setq found t)
- (message "Improper nesting in file."))
- ;; Look through property names in TRANSLATIONS
- (while aalist
- (let ((prop (car (car aalist)))
- (alist (cdr (car aalist))))
- ;; And look through values for each property
- (while alist
- (let ((value (car (car alist)))
- (ans (cdr (car alist))))
- (if (member top-name ans)
- ;; This annotation is listed, but still have to
- ;; check if multiple annotations are satisfied
- (if (member 'nil (mapcar
- (lambda (r)
- (assoc r open-ans))
- ans))
- nil ; multiple ans not satisfied
- ;; Yes, all set.
- ;; If there are multiple annotations going
- ;; into one text property, adjust the
- ;; begin points of the other annotations
- ;; so that we don't get double marking.
- (let ((to-reset ans)
- this-one)
- (while to-reset
- (setq this-one
- (assoc (car to-reset)
- (cdr open-ans)))
- (if this-one
- (setcdr this-one (list loc)))
- (setq to-reset (cdr to-reset))))
- ;; Set loop variables to nil so loop
- ;; will exit.
- (setq alist nil aalist nil matched t
- ;; pop annotation off stack.
- open-ans (cdr open-ans))
- (cond
- ;; Check for pseudo-properties
- ((eq prop 'PARAMETER)
- ;; This is a parameter of the top open ann:
- ;; delete text and use as arg.
- (if open-ans
- ;; (If nothing open, discard).
- (setq open-ans
- (cons (append (car open-ans)
- (list
- (buffer-substring
- start loc)))
- (cdr open-ans))))
- (delete-region start loc))
- ((eq prop 'FUNCTION)
- ;; Not a property, but a function to call.
- (let ((rtn (apply value start loc params)))
- (if rtn (setq todo (cons rtn todo)))))
- (t
- ;; Normal property/value pair
- (setq todo
- (cons (list start loc prop value)
- todo)))))))
- (setq alist (cdr alist))))
- (setq aalist (cdr aalist)))
- (if matched
- nil
- ;; Didn't find any match for the annotation:
- ;; Store as value of text-property `unknown'.
- (setq open-ans (cdr open-ans))
- (setq todo (cons (list start loc 'unknown top-name)
- todo))
- (setq unknown-ans (cons name unknown-ans)))))))))
-
- ;; Once entire file has been scanned, add the properties.
- (while todo
- (let* ((item (car todo))
- (from (nth 0 item))
- (to (nth 1 item))
- (prop (nth 2 item))
- (val (nth 3 item)))
-
- (put-text-property
- from to prop
- (cond ((numberp val) ; add to ambient value if numeric
- (+ val (or (get-text-property from prop) 0)))
- ((get prop 'format-list-valued) ; value gets consed onto
- ; list-valued properties
- (let ((prev (get-text-property from prop)))
- (cons val (if (listp prev) prev (list prev)))))
- (t val)))) ; normally, just set to val.
- (setq todo (cdr todo)))
-
- (if unknown-ans
- (message "Unknown annotations: %s" unknown-ans))))))
-
-;;;
-;;; Encoding
-;;;
-
-(defun format-insert-annotations (list &optional offset)
- "Apply list of annotations to buffer as `write-region' would.
-Inserts each element of the given LIST of buffer annotations at its
-appropriate place. Use second arg OFFSET if the annotations' locations are
-not relative to the beginning of the buffer: annotations will be inserted
-at their location-OFFSET+1 \(ie, the offset is treated as the character number
-of the first character in the buffer)."
- (if (not offset)
- (setq offset 0)
- (setq offset (1- offset)))
- (let ((l (reverse list)))
- (while l
- (goto-char (- (car (car l)) offset))
- (insert (cdr (car l)))
- (setq l (cdr l)))))
-
-(defun format-annotate-value (old new)
- "Return OLD and NEW as a \(close . open) annotation pair.
-Useful as a default function for TRANSLATIONS alist when the value of the text
-property is the name of the annotation that you want to use, as it is for the
-`unknown' text property."
- (cons (if old (list old))
- (if new (list new))))
-
-(defun format-annotate-region (from to trans format-fn ignore)
- "Generate annotations for text properties in the region.
-Searches for changes between FROM and TO, and describes them with a list of
-annotations as defined by alist TRANSLATIONS and FORMAT-FN. IGNORE lists text
-properties not to consider; any text properties that are neither ignored nor
-listed in TRANSLATIONS are warned about.
-If you actually want to modify the region, give the return value of this
-function to `format-insert-annotations'.
-
-Format of the TRANSLATIONS argument:
-
-Each element is a list whose car is a PROPERTY, and the following
-elements are VALUES of that property followed by the names of zero or more
-ANNOTATIONS. Whenever the property takes on that value, the annotations
-\(as formatted by FORMAT-FN) are inserted into the file.
-When the property stops having that value, the matching negated annotation
-will be inserted \(it may actually be closed earlier and reopened, if
-necessary, to keep proper nesting).
-
-If the property's value is a list, then each element of the list is dealt with
-separately.
-
-If a VALUE is numeric, then it is assumed that there is a single annotation
-and each occurrence of it increments the value of the property by that number.
-Thus, given the entry \(left-margin \(4 \"indent\")), if the left margin
-changes from 4 to 12, two <indent> annotations will be generated.
-
-If the VALUE is nil, then instead of annotations, a function should be
-specified. This function is used as a default: it is called for all
-transitions not explicitly listed in the table. The function is called with
-two arguments, the OLD and NEW values of the property. It should return
-lists of annotations like `format-annotate-location' does.
-
- The same structure can be used in reverse for reading files."
- (let ((all-ans nil) ; All annotations - becomes return value
- (open-ans nil) ; Annotations not yet closed
- (loc nil) ; Current location
- (not-found nil)) ; Properties that couldn't be saved
- (while (or (null loc)
- (and (setq loc (next-property-change loc nil to))
- (< loc to)))
- (or loc (setq loc from))
- (let* ((ans (format-annotate-location loc (= loc from) ignore trans))
- (neg-ans (format-reorder (aref ans 0) open-ans))
- (pos-ans (aref ans 1))
- (ignored (aref ans 2)))
- (setq not-found (append ignored not-found)
- ignore (append ignored ignore))
- ;; First do the negative (closing) annotations
- (while neg-ans
- ;; Check if it's missing. This can happen (eg, a numeric property
- ;; going negative can generate closing annotations before there are
- ;; any open). Warn user & ignore.
- (if (not (member (car neg-ans) open-ans))
- (message "Can't close %s: not open." (car neg-ans))
- (while (not (equal (car neg-ans) (car open-ans)))
- ;; To close anno. N, need to first close ans 1 to N-1,
- ;; remembering to re-open them later.
- (setq pos-ans (cons (car open-ans) pos-ans))
- (setq all-ans
- (cons (cons loc (funcall format-fn (car open-ans) nil))
- all-ans))
- (setq open-ans (cdr open-ans)))
- ;; Now remove the one we're really interested in from open list.
- (setq open-ans (cdr open-ans))
- ;; And put the closing annotation here.
- (setq all-ans
- (cons (cons loc (funcall format-fn (car neg-ans) nil))
- all-ans)))
- (setq neg-ans (cdr neg-ans)))
- ;; Now deal with positive (opening) annotations
- (let ((p pos-ans))
- (while pos-ans
- (setq open-ans (cons (car pos-ans) open-ans))
- (setq all-ans
- (cons (cons loc (funcall format-fn (car pos-ans) t))
- all-ans))
- (setq pos-ans (cdr pos-ans))))))
-
- ;; Close any annotations still open
- (while open-ans
- (setq all-ans
- (cons (cons to (funcall format-fn (car open-ans) nil))
- all-ans))
- (setq open-ans (cdr open-ans)))
- (if not-found
- (message "These text properties could not be saved:\n %s"
- not-found))
- (nreverse all-ans)))
-
-;;; Internal functions for format-annotate-region.
-
-(defun format-annotate-location (loc all ignore trans)
- "Return annotation(s) needed at LOCATION.
-This includes any properties that change between LOC-1 and LOC.
-If ALL is true, don't look at previous location, but generate annotations for
-all non-nil properties.
-Third argument IGNORE is a list of text-properties not to consider.
-
-Return value is a vector of 3 elements:
-1. List of names of the annotations to close
-2. List of the names of annotations to open.
-3. List of properties that were ignored or couldn't be annotated."
- (let* ((prev-loc (1- loc))
- (before-plist (if all nil (text-properties-at prev-loc)))
- (after-plist (text-properties-at loc))
- p negatives positives prop props not-found)
- ;; make list of all property names involved
- (setq p before-plist)
- (while p
- (if (not (memq (car p) props))
- (setq props (cons (car p) props)))
- (setq p (cdr (cdr p))))
- (setq p after-plist)
- (while p
- (if (not (memq (car p) props))
- (setq props (cons (car p) props)))
- (setq p (cdr (cdr p))))
-
- (while props
- (setq prop (car props)
- props (cdr props))
- (if (memq prop ignore)
- nil ; If it's been ignored before, ignore it now.
- (let ((before (if all nil (car (cdr (memq prop before-plist)))))
- (after (car (cdr (memq prop after-plist)))))
- (if (equal before after)
- nil ; no change; ignore
- (let ((result (format-annotate-single-property-change
- prop before after trans)))
- (if (not result)
- (setq not-found (cons prop not-found))
- (setq negatives (nconc negatives (car result))
- positives (nconc positives (cdr result)))))))))
- (vector negatives positives not-found)))
-
-(defun format-annotate-single-property-change (prop old new trans)
- "Return annotations for PROPERTY changing from OLD to NEW.
-These are searched for in the TRANSLATIONS alist.
-If NEW does not appear in the list, but there is a default function, then that
-function is called.
-Annotations to open and to close are returned as a dotted pair."
- (let ((prop-alist (cdr (assoc prop trans)))
- default)
- (if (not prop-alist)
- nil
- ;; If property is numeric, nil means 0
- (cond ((and (numberp old) (null new))
- (setq new 0))
- ((and (numberp new) (null old))
- (setq old 0)))
- ;; If either old or new is a list, have to treat both that way.
- (if (or (consp old) (consp new))
- (let* ((old (if (listp old) old (list old)))
- (new (if (listp new) new (list new)))
- (tail (format-common-tail old new))
- close open)
- (while old
- (setq close
- (append (car (format-annotate-atomic-property-change
- prop-alist (car old) nil))
- close)
- old (cdr old)))
- (while new
- (setq open
- (append (cdr (format-annotate-atomic-property-change
- prop-alist nil (car new)))
- open)
- new (cdr new)))
- (format-make-relatively-unique close open))
- (format-annotate-atomic-property-change prop-alist old new)))))
-
-(defun format-annotate-atomic-property-change (prop-alist old new)
- "Internal function annotate a single property change.
-PROP-ALIST is the relevant segment of a TRANSLATIONS list.
-OLD and NEW are the values."
- (cond
- ;; Numerical annotation - use difference
- ((and (numberp old) (numberp new))
- (let* ((entry (progn
- (while (and (car (car prop-alist))
- (not (numberp (car (car prop-alist)))))
- (setq prop-alist (cdr prop-alist)))
- (car prop-alist)))
- (increment (car (car prop-alist)))
- (n (ceiling (/ (float (- new old)) (float increment))))
- (anno (car (cdr (car prop-alist)))))
- (if (> n 0)
- (cons nil (make-list n anno))
- (cons (make-list (- n) anno) nil))))
-
- ;; Standard annotation
- (t (let ((close (and old (cdr (assoc old prop-alist))))
- (open (and new (cdr (assoc new prop-alist)))))
- (if (or close open)
- (format-make-relatively-unique close open)
- ;; Call "Default" function, if any
- (let ((default (assq nil prop-alist)))
- (if default
- (funcall (car (cdr default)) old new))))))))
-
-;; format.el ends here
diff --git a/lisp/forms-pass.el b/lisp/forms-pass.el
deleted file mode 100644
index 1a7db41e20a..00000000000
--- a/lisp/forms-pass.el
+++ /dev/null
@@ -1,25 +0,0 @@
-;;; forms-pass.el --- passwd file demo for forms-mode
-
-;; This demo visits your passwd file.
-
-;; use yp if present
-(or (file-exists-p (setq forms-file "/var/yp/src/passwd"))
- (setq forms-file "/etc/passwd"))
-
-(setq forms-read-only t) ; to make sure
-(setq forms-field-sep ":")
-(setq forms-number-of-fields 7)
-
-(setq forms-format-list
- (list
- "====== Visiting " forms-file " ======\n\n"
- "User : " 1
- " Uid: " 3
- " Gid: " 4
- "\n\n"
- "Name : " 5
- "\n\n"
- "Home : " 6
- "\n\n"
- "Shell: " 7
- "\n"))
diff --git a/lisp/forms.el b/lisp/forms.el
deleted file mode 100644
index 0aa5f0f7130..00000000000
--- a/lisp/forms.el
+++ /dev/null
@@ -1,2049 +0,0 @@
-;;; forms.el --- Forms mode: edit a file as a form to fill in
-
-;; Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Johan Vromans <jvromans@squirrel.nl>
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Visit a file using a form.
-;;
-;; === Naming conventions
-;;
-;; The names of all variables and functions start with 'forms-'.
-;; Names which start with 'forms--' are intended for internal use, and
-;; should *NOT* be used from the outside.
-;;
-;; All variables are buffer-local, to enable multiple forms visits
-;; simultaneously.
-;; Variable `forms--mode-setup' is local to *ALL* buffers, for it
-;; controls if forms-mode has been enabled in a buffer.
-;;
-;; === How it works ===
-;;
-;; Forms mode means visiting a data file which is supposed to consist
-;; of records each containing a number of fields. The records are
-;; separated by a newline, the fields are separated by a user-defined
-;; field separator (default: TAB).
-;; When shown, a record is transferred to an Emacs buffer and
-;; presented using a user-defined form. One record is shown at a
-;; time.
-;;
-;; Forms mode is a composite mode. It involves two files, and two
-;; buffers.
-;; The first file, called the control file, defines the name of the
-;; data file and the forms format. This file buffer will be used to
-;; present the forms.
-;; The second file holds the actual data. The buffer of this file
-;; will be buried, for it is never accessed directly.
-;;
-;; Forms mode is invoked using M-x forms-find-file control-file .
-;; Alternatively `forms-find-file-other-window' can be used.
-;;
-;; You may also visit the control file, and switch to forms mode by hand
-;; with M-x forms-mode .
-;;
-;; Automatic mode switching is supported if you specify
-;; "-*- forms -*-" in the first line of the control file.
-;;
-;; The control file is visited, evaluated using `eval-current-buffer',
-;; and should set at least the following variables:
-;;
-;; forms-file [string]
-;; The name of the data file.
-;;
-;; forms-number-of-fields [integer]
-;; The number of fields in each record.
-;;
-;; forms-format-list [list]
-;; Formatting instructions.
-;;
-;; `forms-format-list' should be a list, each element containing
-;;
-;; - a string, e.g. "hello". The string is inserted in the forms
-;; "as is".
-;;
-;; - an integer, denoting a field number.
-;; The contents of this field are inserted at this point.
-;; Fields are numbered starting with number one.
-;;
-;; - a function call, e.g. (insert "text").
-;; This function call is dynamically evaluated and should return a
-;; string. It should *NOT* have side-effects on the forms being
-;; constructed. The current fields are available to the function
-;; in the variable `forms-fields', they should *NOT* be modified.
-;;
-;; - a lisp symbol, that must evaluate to one of the above.
-;;
-;; Optional variables which may be set in the control file:
-;;
-;; forms-field-sep [string, default TAB]
-;; The field separator used to separate the
-;; fields in the data file. It may be a string.
-;;
-;; forms-read-only [bool, default nil]
-;; Non-nil means that the data file is visited
-;; read-only (view mode) as opposed to edit mode.
-;; If no write access to the data file is
-;; possible, view mode is enforced.
-;;
-;; forms-check-number-of-fields [bool, default t]
-;; If non-nil, a warning will be issued whenever
-;; a record is found that does not have the number
-;; of fields specified by `forms-number-of-fields'.
-;;
-;; forms-multi-line [string, default "^K"]
-;; If non-null the records of the data file may
-;; contain fields that can span multiple lines in
-;; the form.
-;; This variable denotes the separator character
-;; to be used for this purpose. Upon display, all
-;; occurrences of this character are translated
-;; to newlines. Upon storage they are translated
-;; back to the separator character.
-;;
-;; forms-forms-scroll [bool, default nil]
-;; Non-nil means: rebind locally the commands that
-;; perform `scroll-up' or `scroll-down' to use
-;; `forms-next-field' resp. `forms-prev-field'.
-;;
-;; forms-forms-jump [bool, default nil]
-;; Non-nil means: rebind locally the commands that
-;;
-;; forms-insert-after [bool, default nil]
-;; Non-nil means: inserts of new records go after
-;; current record, also initial position is at last
-;; record.
-;;
-;; forms-read-file-filter [symbol, default nil]
-;; If not nil: this should be the name of a
-;; function that is called after the forms data file
-;; has been read. It can be used to transform
-;; the contents of the file into a format more suitable
-;; for forms-mode processing.
-;;
-;; forms-write-file-filter [symbol, default nil]
-;; If not nil: this should be the name of a
-;; function that is called before the forms data file
-;; is written (saved) to disk. It can be used to undo
-;; the effects of `forms-read-file-filter', if any.
-;;
-;; forms-new-record-filter [symbol, default nil]
-;; If not nil: this should be the name of a
-;; function that is called when a new
-;; record is created. It can be used to fill in
-;; the new record with default fields, for example.
-;;
-;; forms-modified-record-filter [symbol, default nil]
-;; If not nil: this should be the name of a
-;; function that is called when a record has
-;; been modified. It is called after the fields
-;; are parsed. It can be used to register
-;; modification dates, for example.
-;;
-;; forms-use-text-properties [bool, see text for default]
-;; This variable controls if forms mode should use
-;; text properties to protect the form text from being
-;; modified (using text-property `read-only').
-;; Also, the read-write fields are shown using a
-;; distinct face, if possible.
-;; As of emacs 19.29, the `intangible' text property
-;; is used to prevent moving into read-only fields.
-;; This variable defaults to t if running Emacs 19
-;; with text properties.
-;; The default face to show read-write fields is
-;; copied from face `region'.
-;;
-;; forms-ro-face [symbol, default 'default]
-;; This is the face that is used to show
-;; read-only text on the screen.If used, this
-;; variable should be set to a symbol that is a
-;; valid face.
-;; E.g.
-;; (make-face 'my-face)
-;; (setq forms-ro-face 'my-face)
-;;
-;; forms-rw-face [symbol, default 'region]
-;; This is the face that is used to show
-;; read-write text on the screen.
-;;
-;; After evaluating the control file, its buffer is cleared and used
-;; for further processing.
-;; The data file (as designated by `forms-file') is visited in a buffer
-;; `forms--file-buffer' which will not normally be shown.
-;; Great malfunctioning may be expected if this file/buffer is modified
-;; outside of this package while it is being visited!
-;;
-;; Normal operation is to transfer one line (record) from the data file,
-;; split it into fields (into `forms--the-record-list'), and display it
-;; using the specs in `forms-format-list'.
-;; A format routine `forms--format' is built upon startup to format
-;; the records according to `forms-format-list'.
-;;
-;; When a form is changed the record is updated as soon as this form
-;; is left. The contents of the form are parsed using information
-;; obtained from `forms-format-list', and the fields which are
-;; deduced from the form are modified. Fields not shown on the forms
-;; retain their original values. The newly formed record then
-;; replaces the contents of the old record in `forms--file-buffer'.
-;; A parse routine `forms--parser' is built upon startup to parse
-;; the records.
-;;
-;; Two exit functions exist: `forms-exit' and `forms-exit-no-save'.
-;; `forms-exit' saves the data to the file, if modified.
-;; `forms-exit-no-save` does not. However, if `forms-exit-no-save'
-;; is executed and the file buffer has been modified, Emacs will ask
-;; questions anyway.
-;;
-;; Other functions provided by forms mode are:
-;;
-;; paging (forward, backward) by record
-;; jumping (first, last, random number)
-;; searching
-;; creating and deleting records
-;; reverting the form (NOT the file buffer)
-;; switching edit <-> view mode v.v.
-;; jumping from field to field
-;;
-;; As an documented side-effect: jumping to the last record in the
-;; file (using forms-last-record) will adjust forms--total-records if
-;; needed.
-;;
-;; The forms buffer can be in on eof two modes: edit mode or view
-;; mode. View mode is a read-only mode, you cannot modify the
-;; contents of the buffer.
-;;
-;; Edit mode commands:
-;;
-;; TAB forms-next-field
-;; \C-c TAB forms-next-field
-;; \C-c < forms-first-record
-;; \C-c > forms-last-record
-;; \C-c ? describe-mode
-;; \C-c \C-k forms-delete-record
-;; \C-c \C-q forms-toggle-read-only
-;; \C-c \C-o forms-insert-record
-;; \C-c \C-l forms-jump-record
-;; \C-c \C-n forms-next-record
-;; \C-c \C-p forms-prev-record
-;; \C-c \C-r forms-search-backward
-;; \C-c \C-s forms-search-forward
-;; \C-c \C-x forms-exit
-;;
-;; Read-only mode commands:
-;;
-;; SPC forms-next-record
-;; DEL forms-prev-record
-;; ? describe-mode
-;; \C-q forms-toggle-read-only
-;; l forms-jump-record
-;; n forms-next-record
-;; p forms-prev-record
-;; r forms-search-backward
-;; s forms-search-forward
-;; x forms-exit
-;;
-;; Of course, it is also possible to use the \C-c prefix to obtain the
-;; same command keys as in edit mode.
-;;
-;; The following bindings are available, independent of the mode:
-;;
-;; [next] forms-next-record
-;; [prior] forms-prev-record
-;; [begin] forms-first-record
-;; [end] forms-last-record
-;; [S-TAB] forms-prev-field
-;; [backtab] forms-prev-field
-;;
-;; For convenience, TAB is always bound to `forms-next-field', so you
-;; don't need the C-c prefix for this command.
-;;
-;; As mentioned above (see `forms-forms-scroll' and `forms-forms-jump')
-;; the bindings of standard functions `scroll-up', `scroll-down',
-;; `beginning-of-buffer' and `end-of-buffer' can be locally replaced with
-;; forms mode functions next/prev record and first/last
-;; record.
-;;
-;; `local-write-file hook' is defined to save the actual data file
-;; instead of the buffer data, `revert-file-hook' is defined to
-;; revert a forms to original.
-
-;;; Code:
-
-;;; Global variables and constants:
-
-(provide 'forms) ;;; official
-(provide 'forms-mode) ;;; for compatibility
-
-(defconst forms-version (substring "$Revision: 2.20 $" 11 -2)
- "The version number of forms-mode (as string). The complete RCS id is:
-
- $Id: forms.el,v 2.20 1996/03/01 20:31:29 jv Exp $")
-
-(defvar forms-mode-hooks nil
- "Hook functions to be run upon entering Forms mode.")
-
-;;; Mandatory variables - must be set by evaluating the control file.
-
-(defvar forms-file nil
- "Name of the file holding the data.")
-
-(defvar forms-format-list nil
- "List of formatting specifications.")
-
-(defvar forms-number-of-fields nil
- "Number of fields per record.")
-
-;;; Optional variables with default values.
-
-(defvar forms-check-number-of-fields t
- "*If non-nil, warn about records with wrong number of fields.")
-
-(defvar forms-field-sep "\t"
- "Field separator character (default TAB).")
-
-(defvar forms-read-only nil
- "Non-nil means: visit the file in view (read-only) mode.
-\(Defaults to the write access on the data file).")
-
-(defvar forms-multi-line "\C-k"
- "If not nil: use this character to separate multi-line fields (default C-k).")
-
-(defvar forms-forms-scroll nil
- "*Non-nil means replace scroll-up/down commands in Forms mode.
-The replacement commands performs forms-next/prev-record.")
-
-(defvar forms-forms-jump nil
- "*Non-nil means redefine beginning/end-of-buffer in Forms mode.
-The replacement commands performs forms-first/last-record.")
-
-(defvar forms-read-file-filter nil
- "The name of a function that is called after reading the data file.
-This can be used to change the contents of the file to something more
-suitable for forms processing.")
-
-(defvar forms-write-file-filter nil
- "The name of a function that is called before writing the data file.
-This can be used to undo the effects of form-read-file-hook.")
-
-(defvar forms-new-record-filter nil
- "The name of a function that is called when a new record is created.")
-
-(defvar forms-modified-record-filter nil
- "The name of a function that is called when a record has been modified.")
-
-(defvar forms-fields nil
- "List with fields of the current forms. First field has number 1.
-This variable is for use by the filter routines only.
-The contents may NOT be modified.")
-
-(defvar forms-use-text-properties (fboundp 'set-text-properties)
- "*Non-nil means: use emacs-19 text properties.
-Defaults to t if this emacs is capable of handling text properties.")
-
-(defvar forms-insert-after nil
- "*Non-nil means: inserts of new records go after current record.
-Also, initial position is at last record.")
-
-(defvar forms-ro-face 'default
- "The face (a symbol) that is used to display read-only text on the screen.")
-
-(defvar forms-rw-face 'region
- "The face (a symbol) that is used to display read-write text on the screen.")
-
-;;; Internal variables.
-
-(defvar forms--file-buffer nil
- "Buffer which holds the file data")
-
-(defvar forms--total-records 0
- "Total number of records in the data file.")
-
-(defvar forms--current-record 0
- "Number of the record currently on the screen.")
-
-(defvar forms-mode-map nil
- "Keymap for form buffer.")
-(defvar forms-mode-ro-map nil
- "Keymap for form buffer in view mode.")
-(defvar forms-mode-edit-map nil
- "Keymap for form buffer in edit mode.")
-
-(defvar forms--markers nil
- "Field markers in the screen.")
-
-(defvar forms--dyntexts nil
- "Dynamic texts (resulting from function calls) on the screen.")
-
-(defvar forms--the-record-list nil
- "List of strings of the current record, as parsed from the file.")
-
-(defvar forms--search-regexp nil
- "Last regexp used by forms-search functions.")
-
-(defvar forms--format nil
- "Formatting routine.")
-
-(defvar forms--parser nil
- "Forms parser routine.")
-
-(defvar forms--mode-setup nil
- "To keep track of forms-mode being set-up.")
-(make-variable-buffer-local 'forms--mode-setup)
-
-(defvar forms--dynamic-text nil
- "Array that holds dynamic texts to insert between fields.")
-
-(defvar forms--elements nil
- "Array with the order in which the fields are displayed.")
-
-(defvar forms--ro-face nil
- "Face used to represent read-only data on the screen.")
-
-(defvar forms--rw-face nil
- "Face used to represent read-write data on the screen.")
-
-;;;###autoload
-(defun forms-mode (&optional primary)
- "Major mode to visit files in a field-structured manner using a form.
-
-Commands: Equivalent keys in read-only mode:
- TAB forms-next-field TAB
- \\C-c TAB forms-next-field
- \\C-c < forms-first-record <
- \\C-c > forms-last-record >
- \\C-c ? describe-mode ?
- \\C-c \\C-k forms-delete-record
- \\C-c \\C-q forms-toggle-read-only q
- \\C-c \\C-o forms-insert-record
- \\C-c \\C-l forms-jump-record l
- \\C-c \\C-n forms-next-record n
- \\C-c \\C-p forms-prev-record p
- \\C-c \\C-r forms-search-reverse r
- \\C-c \\C-s forms-search-forward s
- \\C-c \\C-x forms-exit x
-"
- (interactive)
-
- ;; This is not a simple major mode, as usual. Therefore, forms-mode
- ;; takes an optional argument `primary' which is used for the
- ;; initial set-up. Normal use would leave `primary' to nil.
- ;; A global buffer-local variable `forms--mode-setup' has the same
- ;; effect but makes it possible to auto-invoke forms-mode using
- ;; `find-file'.
- ;; Note: although it seems logical to have `make-local-variable'
- ;; executed where the variable is first needed, I have deliberately
- ;; placed all calls in this function.
-
- ;; Primary set-up: evaluate buffer and check if the mandatory
- ;; variables have been set.
- (if (or primary (not forms--mode-setup))
- (progn
- ;;(message "forms: setting up...")
- (kill-all-local-variables)
-
- ;; Make mandatory variables.
- (make-local-variable 'forms-file)
- (make-local-variable 'forms-number-of-fields)
- (make-local-variable 'forms-format-list)
-
- ;; Make optional variables.
- (make-local-variable 'forms-field-sep)
- (make-local-variable 'forms-read-only)
- (make-local-variable 'forms-multi-line)
- (make-local-variable 'forms-forms-scroll)
- (make-local-variable 'forms-forms-jump)
- (make-local-variable 'forms-insert-after)
- (make-local-variable 'forms-use-text-properties)
-
- ;; Filter functions.
- (make-local-variable 'forms-read-file-filter)
- (make-local-variable 'forms-write-file-filter)
- (make-local-variable 'forms-new-record-filter)
- (make-local-variable 'forms-modified-record-filter)
-
- ;; Make sure no filters exist.
- (setq forms-read-file-filter nil)
- (setq forms-write-file-filter nil)
- (setq forms-new-record-filter nil)
- (setq forms-modified-record-filter nil)
-
- ;; If running Emacs 19 under X, setup faces to show read-only and
- ;; read-write fields.
- (if (fboundp 'make-face)
- (progn
- (make-local-variable 'forms-ro-face)
- (make-local-variable 'forms-rw-face)))
-
- ;; eval the buffer, should set variables
- ;;(message "forms: processing control file...")
- ;; If enable-local-eval is not set to t the user is asked first.
- (if (or (eq enable-local-eval t)
- (yes-or-no-p
- (concat "Evaluate lisp code in buffer "
- (buffer-name) " to display forms ")))
- (eval-current-buffer)
- (error "`enable-local-eval' inhibits buffer evaluation"))
-
- ;; Check if the mandatory variables make sense.
- (or forms-file
- (error (concat "Forms control file error: "
- "'forms-file' has not been set")))
-
- ;; Check forms-field-sep first, since it can be needed to
- ;; construct a default format list.
- (or (stringp forms-field-sep)
- (error (concat "Forms control file error: "
- "'forms-field-sep' is not a string")))
-
- (if forms-number-of-fields
- (or (and (numberp forms-number-of-fields)
- (> forms-number-of-fields 0))
- (error (concat "Forms control file error: "
- "'forms-number-of-fields' must be a number > 0")))
- (or (null forms-format-list)
- (error (concat "Forms control file error: "
- "'forms-number-of-fields' has not been set"))))
-
- (or forms-format-list
- (forms--intuit-from-file))
-
- (if forms-multi-line
- (if (and (stringp forms-multi-line)
- (eq (length forms-multi-line) 1))
- (if (string= forms-multi-line forms-field-sep)
- (error (concat "Forms control file error: "
- "'forms-multi-line' is equal to 'forms-field-sep'")))
- (error (concat "Forms control file error: "
- "'forms-multi-line' must be nil or a one-character string"))))
- (or (fboundp 'set-text-properties)
- (setq forms-use-text-properties nil))
-
- ;; Validate and process forms-format-list.
- ;;(message "forms: pre-processing format list...")
- (forms--process-format-list)
-
- ;; Build the formatter and parser.
- ;;(message "forms: building formatter...")
- (make-local-variable 'forms--format)
- (make-local-variable 'forms--markers)
- (make-local-variable 'forms--dyntexts)
- (make-local-variable 'forms--elements)
- ;;(message "forms: building parser...")
- (forms--make-format)
- (make-local-variable 'forms--parser)
- (forms--make-parser)
- ;;(message "forms: building parser... done.")
-
- ;; Check if record filters are defined.
- (if (and forms-new-record-filter
- (not (fboundp forms-new-record-filter)))
- (error (concat "Forms control file error: "
- "'forms-new-record-filter' is not a function")))
-
- (if (and forms-modified-record-filter
- (not (fboundp forms-modified-record-filter)))
- (error (concat "Forms control file error: "
- "'forms-modified-record-filter' is not a function")))
-
- ;; The filters acces the contents of the forms using `forms-fields'.
- (make-local-variable 'forms-fields)
-
- ;; Dynamic text support.
- (make-local-variable 'forms--dynamic-text)
-
- ;; Prevent accidental overwrite of the control file and autosave.
- (set-visited-file-name nil)
-
- ;; Prepare this buffer for further processing.
- (setq buffer-read-only nil)
- (erase-buffer)
-
- ;;(message "forms: setting up... done.")
- ))
-
- ;; initialization done
- (setq forms--mode-setup t)
-
- ;; Copy desired faces to the actual variables used by the forms formatter.
- (if (fboundp 'make-face)
- (progn
- (make-local-variable 'forms--ro-face)
- (make-local-variable 'forms--rw-face)
- (if forms-read-only
- (progn
- (setq forms--ro-face forms-ro-face)
- (setq forms--rw-face forms-ro-face))
- (setq forms--ro-face forms-ro-face)
- (setq forms--rw-face forms-rw-face))))
-
- ;; Make more local variables.
- (make-local-variable 'forms--file-buffer)
- (make-local-variable 'forms--total-records)
- (make-local-variable 'forms--current-record)
- (make-local-variable 'forms--the-record-list)
- (make-local-variable 'forms--search-regexp)
-
- ; The keymaps are global, so multiple forms mode buffers can share them.
- ;(make-local-variable 'forms-mode-map)
- ;(make-local-variable 'forms-mode-ro-map)
- ;(make-local-variable 'forms-mode-edit-map)
- (if forms-mode-map ; already defined
- nil
- ;;(message "forms: building keymap...")
- (forms--mode-commands)
- ;;(message "forms: building keymap... done.")
- )
-
- ;; set the major mode indicator
- (setq major-mode 'forms-mode)
- (setq mode-name "Forms")
-
- ;; find the data file
- (setq forms--file-buffer (find-file-noselect forms-file))
-
- ;; Pre-transform.
- (let ((read-file-filter forms-read-file-filter)
- (write-file-filter forms-write-file-filter))
- (if read-file-filter
- (save-excursion
- (set-buffer forms--file-buffer)
- (let ((inhibit-read-only t)
- (file-modified (buffer-modified-p)))
- (run-hooks 'read-file-filter)
- (if (not file-modified) (set-buffer-modified-p nil)))
- (if write-file-filter
- (progn
- (make-variable-buffer-local 'local-write-file-hooks)
- (setq local-write-file-hooks (list write-file-filter)))))
- (if write-file-filter
- (save-excursion
- (set-buffer forms--file-buffer)
- (make-variable-buffer-local 'local-write-file-hooks)
- (setq local-write-file-hooks (list write-file-filter))))))
-
- ;; count the number of records, and set see if it may be modified
- (let (ro)
- (setq forms--total-records
- (save-excursion
- (prog1
- (progn
- ;;(message "forms: counting records...")
- (set-buffer forms--file-buffer)
- (bury-buffer (current-buffer))
- (setq ro buffer-read-only)
- (count-lines (point-min) (point-max)))
- ;;(message "forms: counting records... done.")
- )))
- (if ro
- (setq forms-read-only t)))
-
- ;;(message "forms: proceeding setup...")
-
- ;; Since we aren't really implementing a minor mode, we hack the modeline
- ;; directly to get the text " View " into forms-read-only form buffers. For
- ;; that reason, this variable must be buffer only.
- (make-local-variable 'minor-mode-alist)
- (setq minor-mode-alist (list (list 'forms-read-only " View")))
-
- ;;(message "forms: proceeding setup (keymaps)...")
- (forms--set-keymaps)
- ;;(message "forms: proceeding setup (commands)...")
- (forms--change-commands)
-
- ;;(message "forms: proceeding setup (buffer)...")
- (set-buffer-modified-p nil)
-
- (if (= forms--total-records 0)
- ;;(message "forms: proceeding setup (new file)...")
- (progn
- (insert
- "GNU Emacs Forms Mode version " forms-version "\n\n"
- (if (file-exists-p forms-file)
- (concat "No records available in file `" forms-file "'\n\n")
- (format "Creating new file `%s'\nwith %d field%s per record\n\n"
- forms-file forms-number-of-fields
- (if (= 1 forms-number-of-fields) "" "s")))
- "Use " (substitute-command-keys "\\[forms-insert-record]")
- " to create new records.\n")
- (setq forms--current-record 1)
- (setq buffer-read-only t)
- (set-buffer-modified-p nil))
-
- ;; setup the first (or current) record to show
- (if (< forms--current-record 1)
- (setq forms--current-record 1))
- (forms-jump-record forms--current-record)
- )
-
- (if forms-insert-after
- (forms-last-record)
- (forms-first-record))
-
- ;; user customising
- ;;(message "forms: proceeding setup (user hooks)...")
- (run-hooks 'forms-mode-hooks)
- ;;(message "forms: setting up... done.")
-
- ;; be helpful
- (forms--help)
-)
-
-(defun forms--process-format-list ()
- ;; Validate `forms-format-list' and set some global variables.
- ;; Symbols in the list are evaluated, and consecutive strings are
- ;; concatenated.
- ;; Array `forms--elements' is constructed that contains the order
- ;; of the fields on the display. This array is used by
- ;; `forms--parser-using-text-properties' to extract the fields data
- ;; from the form on the screen.
- ;; Upon completion, `forms-format-list' is guaranteed correct, so
- ;; `forms--make-format' and `forms--make-parser' do not need to perform
- ;; any checks.
-
- ;; Verify that `forms-format-list' is not nil.
- (or forms-format-list
- (error (concat "Forms control file error: "
- "'forms-format-list' has not been set")))
- ;; It must be a list.
- (or (listp forms-format-list)
- (error (concat "Forms control file error: "
- "'forms-format-list' is not a list")))
-
- ;; Assume every field is painted once.
- ;; `forms--elements' will grow if needed.
- (setq forms--elements (make-vector forms-number-of-fields nil))
-
- (let ((the-list forms-format-list) ; the list of format elements
- (this-item 0) ; element in list
- (prev-item nil)
- (field-num 0)) ; highest field number
-
- (setq forms-format-list nil) ; gonna rebuild
-
- (while the-list
-
- (let ((el (car-safe the-list))
- (rem (cdr-safe the-list)))
-
- ;; If it is a symbol, eval it first.
- (if (and (symbolp el)
- (boundp el))
- (setq el (eval el)))
-
- (cond
-
- ;; Try string ...
- ((stringp el)
- (if (stringp prev-item) ; try to concatenate strings
- (setq prev-item (concat prev-item el))
- (if prev-item
- (setq forms-format-list
- (append forms-format-list (list prev-item) nil)))
- (setq prev-item el)))
-
- ;; Try numeric ...
- ((numberp el)
-
- ;; Validate range.
- (if (or (<= el 0)
- (> el forms-number-of-fields))
- (error (concat "Forms format error: "
- "field number %d out of range 1..%d")
- el forms-number-of-fields))
-
- ;; Store forms order.
- (if (> field-num (length forms--elements))
- (setq forms--elements (vconcat forms--elements (1- el)))
- (aset forms--elements field-num (1- el)))
- (setq field-num (1+ field-num))
-
- (if prev-item
- (setq forms-format-list
- (append forms-format-list (list prev-item) nil)))
- (setq prev-item el))
-
- ;; Try function ...
- ((listp el)
-
- ;; Validate.
- (or (fboundp (car-safe el))
- (error (concat "Forms format error: "
- "not a function %S")
- (car-safe el)))
-
- ;; Shift.
- (if prev-item
- (setq forms-format-list
- (append forms-format-list (list prev-item) nil)))
- (setq prev-item el))
-
- ;; else
- (t
- (error (concat "Forms format error: "
- "invalid element %S")
- el)))
-
- ;; Advance to next element of the list.
- (setq the-list rem)))
-
- ;; Append last item.
- (if prev-item
- (progn
- (setq forms-format-list
- (append forms-format-list (list prev-item) nil))
- ;; Append a newline if the last item is a field.
- ;; This prevents parsing problems.
- ;; Also it makes it possible to insert an empty last field.
- (if (numberp prev-item)
- (setq forms-format-list
- (append forms-format-list (list "\n") nil))))))
-
- (forms--debug 'forms-format-list
- 'forms--elements))
-
-;; Special treatment for read-only segments.
-;;
-;; If text is inserted between two read-only segments, it inherits the
-;; read-only properties. This is not what we want.
-;; To solve this, read-only segments get the `insert-in-front-hooks'
-;; property set with a function that temporarily switches the properties
-;; of the first character of the segment to read-write, so the new
-;; text gets the right properties.
-;; The `post-command-hook' is used to restore the original properties.
-
-(defvar forms--iif-start nil
- "Record start of modification command.")
-(defvar forms--iif-properties nil
- "Original properties of the character being overridden.")
-
-(defun forms--iif-hook (begin end)
- "`insert-in-front-hooks' function for read-only segments."
-
- ;; Note start location. By making it a marker that points one
- ;; character beyond the actual location, it is guaranteed to move
- ;; correctly if text is inserted.
- (or forms--iif-start
- (setq forms--iif-start (copy-marker (1+ (point)))))
-
- ;; Check if there is special treatment required.
- (if (or (<= forms--iif-start 2)
- (get-text-property (- forms--iif-start 2)
- 'read-only))
- (progn
- ;; Fetch current properties.
- (setq forms--iif-properties
- (text-properties-at (1- forms--iif-start)))
-
- ;; Replace them.
- (let ((inhibit-read-only t))
- (set-text-properties
- (1- forms--iif-start) forms--iif-start
- (list 'face forms--rw-face 'front-sticky '(face))))
-
- ;; Enable `post-command-hook' to restore the properties.
- (setq post-command-hook
- (append (list 'forms--iif-post-command-hook) post-command-hook)))
-
- ;; No action needed. Clear marker.
- (setq forms--iif-start nil)))
-
-(defun forms--iif-post-command-hook ()
- "`post-command-hook' function for read-only segments."
-
- ;; Disable `post-command-hook'.
- (setq post-command-hook
- (delq 'forms--iif-hook-post-command-hook post-command-hook))
-
- ;; Restore properties.
- (if forms--iif-start
- (let ((inhibit-read-only t))
- (set-text-properties
- (1- forms--iif-start) forms--iif-start
- forms--iif-properties)))
-
- ;; Cleanup.
- (setq forms--iif-start nil))
-
-(defvar forms--marker)
-(defvar forms--dyntext)
-
-(defun forms--make-format ()
- "Generate `forms--format' using the information in `forms-format-list'."
-
- ;; The real work is done using a mapcar of `forms--make-format-elt' on
- ;; `forms-format-list'.
- ;; This function sets up the necessary environment, and decides
- ;; which function to mapcar.
-
- (let ((forms--marker 0)
- (forms--dyntext 0))
- (setq
- forms--format
- (if forms-use-text-properties
- (` (lambda (arg)
- (let ((inhibit-read-only t))
- (,@ (apply 'append
- (mapcar 'forms--make-format-elt-using-text-properties
- forms-format-list)))
- ;; Prevent insertion before the first text.
- (,@ (if (numberp (car forms-format-list))
- nil
- '((add-text-properties (point-min) (1+ (point-min))
- '(front-sticky (read-only intangible))))))
- ;; Prevent insertion after the last text.
- (remove-text-properties (1- (point)) (point)
- '(rear-nonsticky)))
- (setq forms--iif-start nil)))
- (` (lambda (arg)
- (,@ (apply 'append
- (mapcar 'forms--make-format-elt forms-format-list)))))))
-
- ;; We have tallied the number of markers and dynamic texts,
- ;; so we can allocate the arrays now.
- (setq forms--markers (make-vector forms--marker nil))
- (setq forms--dyntexts (make-vector forms--dyntext nil)))
- (forms--debug 'forms--format))
-
-(defun forms--make-format-elt-using-text-properties (el)
- "Helper routine to generate format function."
-
- ;; The format routine `forms--format' will look like
- ;;
- ;; ;; preamble
- ;; (lambda (arg)
- ;; (let ((inhibit-read-only t))
- ;;
- ;; ;; A string, e.g. "text: ".
- ;; (set-text-properties
- ;; (point)
- ;; (progn (insert "text: ") (point))
- ;; (list 'face forms--ro-face
- ;; 'read-only 1
- ;; 'insert-in-front-hooks 'forms--iif-hook
- ;; 'rear-nonsticky '(read-only face insert-in-front-hooks)))
- ;;
- ;; ;; A field, e.g. 6.
- ;; (let ((here (point)))
- ;; (aset forms--markers 0 (point-marker))
- ;; (insert (elt arg 5))
- ;; (or (= (point) here)
- ;; (set-text-properties
- ;; here (point)
- ;; (list 'face forms--rw-face
- ;; 'front-sticky '(face))))
- ;;
- ;; ;; Another string, e.g. "\nmore text: ".
- ;; (set-text-properties
- ;; (point)
- ;; (progn (insert "\nmore text: ") (point))
- ;; (list 'face forms--ro-face
- ;; 'read-only 2
- ;; 'insert-in-front-hooks 'forms--iif-hook
- ;; 'rear-nonsticky '(read-only face insert-in-front-hooks)))
- ;;
- ;; ;; A function, e.g. (tocol 40).
- ;; (set-text-properties
- ;; (point)
- ;; (progn
- ;; (insert (aset forms--dyntexts 0 (tocol 40)))
- ;; (point))
- ;; (list 'face forms--ro-face
- ;; 'read-only 2
- ;; 'insert-in-front-hooks 'forms--iif-hook
- ;; 'rear-nonsticky '(read-only face insert-in-front-hooks)))
- ;;
- ;; ;; Prevent insertion before the first text.
- ;; (add-text-properties (point-min) (1+ (point-min))
- ;; '(front-sticky (read-only))))))
- ;; ;; Prevent insertion after the last text.
- ;; (remove-text-properties (1- (point)) (point)
- ;; '(rear-nonsticky)))
- ;;
- ;; ;; wrap up
- ;; (setq forms--iif-start nil)
- ;; ))
-
- (cond
- ((stringp el)
-
- (` ((set-text-properties
- (point) ; start at point
- (progn ; until after insertion
- (insert (, el))
- (point))
- (list 'face forms--ro-face ; read-only appearance
- 'read-only (,@ (list (1+ forms--marker)))
- 'intangible t
- 'insert-in-front-hooks '(forms--iif-hook)
- 'rear-nonsticky '(face read-only insert-in-front-hooks
- intangible))))))
-
- ((numberp el)
- (` ((let ((here (point)))
- (aset forms--markers
- (, (prog1 forms--marker
- (setq forms--marker (1+ forms--marker))))
- (point-marker))
- (insert (elt arg (, (1- el))))
- (or (= (point) here)
- (set-text-properties
- here (point)
- (list 'face forms--rw-face
- 'front-sticky '(face))))))))
-
- ((listp el)
- (` ((set-text-properties
- (point)
- (progn
- (insert (aset forms--dyntexts
- (, (prog1 forms--dyntext
- (setq forms--dyntext (1+ forms--dyntext))))
- (, el)))
- (point))
- (list 'face forms--ro-face
- 'read-only (,@ (list (1+ forms--marker)))
- 'intangible t
- 'insert-in-front-hooks '(forms--iif-hook)
- 'rear-nonsticky '(read-only face insert-in-front-hooks
- intangible))))))
-
- ;; end of cond
- ))
-
-(defun forms--make-format-elt (el)
- "Helper routine to generate format function."
-
- ;; If we're not using text properties, the format routine
- ;; `forms--format' will look like
- ;;
- ;; (lambda (arg)
- ;; ;; a string, e.g. "text: "
- ;; (insert "text: ")
- ;; ;; a field, e.g. 6
- ;; (aset forms--markers 0 (point-marker))
- ;; (insert (elt arg 5))
- ;; ;; another string, e.g. "\nmore text: "
- ;; (insert "\nmore text: ")
- ;; ;; a function, e.g. (tocol 40)
- ;; (insert (aset forms--dyntexts 0 (tocol 40)))
- ;; ... )
-
- (cond
- ((stringp el)
- (` ((insert (, el)))))
- ((numberp el)
- (prog1
- (` ((aset forms--markers (, forms--marker) (point-marker))
- (insert (elt arg (, (1- el))))))
- (setq forms--marker (1+ forms--marker))))
- ((listp el)
- (prog1
- (` ((insert (aset forms--dyntexts (, forms--dyntext) (, el)))))
- (setq forms--dyntext (1+ forms--dyntext))))))
-
-(defvar forms--field)
-(defvar forms--recordv)
-(defvar forms--seen-text)
-
-(defun forms--make-parser ()
- "Generate `forms--parser' from the information in `forms-format-list'."
-
- ;; If we can use text properties, we simply set it to
- ;; `forms--parser-using-text-properties'.
- ;; Otherwise, the function is constructed using a mapcar of
- ;; `forms--make-parser-elt on `forms-format-list'.
-
- (setq
- forms--parser
- (if forms-use-text-properties
- (function forms--parser-using-text-properties)
- (let ((forms--field nil)
- (forms--seen-text nil)
- (forms--dyntext 0))
-
- ;; Note: we add a nil element to the list passed to `mapcar',
- ;; see `forms--make-parser-elt' for details.
- (` (lambda nil
- (let (here)
- (goto-char (point-min))
- (,@ (apply 'append
- (mapcar
- 'forms--make-parser-elt
- (append forms-format-list (list nil)))))))))))
-
- (forms--debug 'forms--parser))
-
-(defun forms--parser-using-text-properties ()
- "Extract field info from forms when using text properties."
-
- ;; Using text properties, we can simply jump to the markers, and
- ;; extract the information up to the following read-only segment.
-
- (let ((i 0)
- here there)
- (while (< i (length forms--markers))
- (goto-char (setq here (aref forms--markers i)))
- (if (get-text-property here 'read-only)
- (aset forms--recordv (aref forms--elements i) nil)
- (if (setq there
- (next-single-property-change here 'read-only))
- (aset forms--recordv (aref forms--elements i)
- (buffer-substring-no-properties here there))
- (aset forms--recordv (aref forms--elements i)
- (buffer-substring-no-properties here (point-max)))))
- (setq i (1+ i)))))
-
-(defun forms--make-parser-elt (el)
- "Helper routine to generate forms parser function."
-
- ;; The parse routine will look like:
- ;;
- ;; (lambda nil
- ;; (let (here)
- ;; (goto-char (point-min))
- ;;
- ;; ;; "text: "
- ;; (if (not (looking-at "text: "))
- ;; (error "Parse error: cannot find \"text: \""))
- ;; (forward-char 6) ; past "text: "
- ;;
- ;; ;; 6
- ;; ;; "\nmore text: "
- ;; (setq here (point))
- ;; (if (not (search-forward "\nmore text: " nil t nil))
- ;; (error "Parse error: cannot find \"\\nmore text: \""))
- ;; (aset forms--recordv 5 (buffer-substring-no-properties here (- (point) 12)))
- ;;
- ;; ;; (tocol 40)
- ;; (let ((forms--dyntext (car-safe forms--dynamic-text)))
- ;; (if (not (looking-at (regexp-quote forms--dyntext)))
- ;; (error "Parse error: not looking at \"%s\"" forms--dyntext))
- ;; (forward-char (length forms--dyntext))
- ;; (setq forms--dynamic-text (cdr-safe forms--dynamic-text)))
- ;; ...
- ;; ;; final flush (due to terminator sentinel, see below)
- ;; (aset forms--recordv 7 (buffer-substring-no-properties (point) (point-max)))
-
- (cond
- ((stringp el)
- (prog1
- (if forms--field
- (` ((setq here (point))
- (if (not (search-forward (, el) nil t nil))
- (error "Parse error: cannot find \"%s\"" (, el)))
- (aset forms--recordv (, (1- forms--field))
- (buffer-substring-no-properties here
- (- (point) (, (length el)))))))
- (` ((if (not (looking-at (, (regexp-quote el))))
- (error "Parse error: not looking at \"%s\"" (, el)))
- (forward-char (, (length el))))))
- (setq forms--seen-text t)
- (setq forms--field nil)))
- ((numberp el)
- (if forms--field
- (error "Cannot parse adjacent fields %d and %d"
- forms--field el)
- (setq forms--field el)
- nil))
- ((null el)
- (if forms--field
- (` ((aset forms--recordv (, (1- forms--field))
- (buffer-substring-no-properties (point) (point-max)))))))
- ((listp el)
- (prog1
- (if forms--field
- (` ((let ((here (point))
- (forms--dyntext (aref forms--dyntexts (, forms--dyntext))))
- (if (not (search-forward forms--dyntext nil t nil))
- (error "Parse error: cannot find \"%s\"" forms--dyntext))
- (aset forms--recordv (, (1- forms--field))
- (buffer-substring-no-properties here
- (- (point) (length forms--dyntext)))))))
- (` ((let ((forms--dyntext (aref forms--dyntexts (, forms--dyntext))))
- (if (not (looking-at (regexp-quote forms--dyntext)))
- (error "Parse error: not looking at \"%s\"" forms--dyntext))
- (forward-char (length forms--dyntext))))))
- (setq forms--dyntext (1+ forms--dyntext))
- (setq forms--seen-text t)
- (setq forms--field nil)))
- ))
-
-(defun forms--intuit-from-file ()
- "Get number of fields and a default form using the data file."
-
- ;; If `forms-number-of-fields' is not set, get it from the data file.
- (if (null forms-number-of-fields)
-
- ;; Need a file to do this.
- (if (not (file-exists-p forms-file))
- (error "Need existing file or explicit 'forms-number-of-records'.")
-
- ;; Visit the file and extract the first record.
- (setq forms--file-buffer (find-file-noselect forms-file))
- (let ((read-file-filter forms-read-file-filter)
- (the-record))
- (setq the-record
- (save-excursion
- (set-buffer forms--file-buffer)
- (let ((inhibit-read-only t))
- (run-hooks 'read-file-filter))
- (goto-char (point-min))
- (forms--get-record)))
-
- ;; This may be overkill, but try to avoid interference with
- ;; the normal processing.
- (kill-buffer forms--file-buffer)
-
- ;; Count the number of fields in `the-record'.
- (let (the-result
- (start-pos 0)
- found-pos
- (field-sep-length (length forms-field-sep)))
- (setq forms-number-of-fields 1)
- (while (setq found-pos
- (string-match forms-field-sep the-record start-pos))
- (progn
- (setq forms-number-of-fields (1+ forms-number-of-fields))
- (setq start-pos (+ field-sep-length found-pos))))))))
-
- ;; Construct default format list.
- (setq forms-format-list (list "Forms file \"" forms-file "\".\n\n"))
- (let ((i 0))
- (while (<= (setq i (1+ i)) forms-number-of-fields)
- (setq forms-format-list
- (append forms-format-list
- (list (format "%4d: " i) i "\n"))))))
-
-(defun forms--set-keymaps ()
- "Set the keymaps used in this mode."
-
- (use-local-map (if forms-read-only
- forms-mode-ro-map
- forms-mode-edit-map)))
-
-(defun forms--mode-commands ()
- "Fill the Forms mode keymaps."
-
- ;; `forms-mode-map' is always accessible via \C-c prefix.
- (setq forms-mode-map (make-keymap))
- (define-key forms-mode-map "\t" 'forms-next-field)
- (define-key forms-mode-map "\C-k" 'forms-delete-record)
- (define-key forms-mode-map "\C-q" 'forms-toggle-read-only)
- (define-key forms-mode-map "\C-o" 'forms-insert-record)
- (define-key forms-mode-map "\C-l" 'forms-jump-record)
- (define-key forms-mode-map "\C-n" 'forms-next-record)
- (define-key forms-mode-map "\C-p" 'forms-prev-record)
- (define-key forms-mode-map "\C-r" 'forms-search-backward)
- (define-key forms-mode-map "\C-s" 'forms-search-forward)
- (define-key forms-mode-map "\C-x" 'forms-exit)
- (define-key forms-mode-map "<" 'forms-first-record)
- (define-key forms-mode-map ">" 'forms-last-record)
- (define-key forms-mode-map "\C-?" 'forms-prev-record)
-
- ;; `forms-mode-ro-map' replaces the local map when in read-only mode.
- (setq forms-mode-ro-map (make-keymap))
- (suppress-keymap forms-mode-ro-map)
- (define-key forms-mode-ro-map "\C-c" forms-mode-map)
- (define-key forms-mode-ro-map "\t" 'forms-next-field)
- (define-key forms-mode-ro-map "q" 'forms-toggle-read-only)
- (define-key forms-mode-ro-map "l" 'forms-jump-record)
- (define-key forms-mode-ro-map "n" 'forms-next-record)
- (define-key forms-mode-ro-map "p" 'forms-prev-record)
- (define-key forms-mode-ro-map "r" 'forms-search-backward)
- (define-key forms-mode-ro-map "s" 'forms-search-forward)
- (define-key forms-mode-ro-map "x" 'forms-exit)
- (define-key forms-mode-ro-map "<" 'forms-first-record)
- (define-key forms-mode-ro-map ">" 'forms-last-record)
- (define-key forms-mode-ro-map "?" 'describe-mode)
- (define-key forms-mode-ro-map " " 'forms-next-record)
- (forms--mode-commands1 forms-mode-ro-map)
- (forms--mode-menu-ro forms-mode-ro-map)
-
- ;; This is the normal, local map.
- (setq forms-mode-edit-map (make-keymap))
- (define-key forms-mode-edit-map "\t" 'forms-next-field)
- (define-key forms-mode-edit-map "\C-c" forms-mode-map)
- (forms--mode-commands1 forms-mode-edit-map)
- (forms--mode-menu-edit forms-mode-edit-map)
- )
-
-(defun forms--mode-menu-ro (map)
-;;; Menu initialisation
-; (define-key map [menu-bar] (make-sparse-keymap))
- (define-key map [menu-bar forms]
- (cons "Forms" (make-sparse-keymap "Forms")))
- (define-key map [menu-bar forms menu-forms-exit]
- '("Exit Forms Mode" . forms-exit))
- (define-key map [menu-bar forms menu-forms-sep1]
- '("----"))
- (define-key map [menu-bar forms menu-forms-save]
- '("Save Data" . forms-save-buffer))
- (define-key map [menu-bar forms menu-forms-print]
- '("Print Data" . forms-print))
- (define-key map [menu-bar forms menu-forms-describe]
- '("Describe Mode" . describe-mode))
- (define-key map [menu-bar forms menu-forms-toggle-ro]
- '("Toggle View/Edit" . forms-toggle-read-only))
- (define-key map [menu-bar forms menu-forms-jump-record]
- '("Jump" . forms-jump-record))
- (define-key map [menu-bar forms menu-forms-search-backward]
- '("Search Backward" . forms-search-backward))
- (define-key map [menu-bar forms menu-forms-search-forward]
- '("Search Forward" . forms-search-forward))
- (define-key map [menu-bar forms menu-forms-delete-record]
- '("Delete" . forms-delete-record))
- (define-key map [menu-bar forms menu-forms-insert-record]
- '("Insert" . forms-insert-record))
- (define-key map [menu-bar forms menu-forms-sep2]
- '("----"))
- (define-key map [menu-bar forms menu-forms-last-record]
- '("Last Record" . forms-last-record))
- (define-key map [menu-bar forms menu-forms-first-record]
- '("First Record" . forms-first-record))
- (define-key map [menu-bar forms menu-forms-prev-record]
- '("Previous Record" . forms-prev-record))
- (define-key map [menu-bar forms menu-forms-next-record]
- '("Next Record" . forms-next-record))
- (define-key map [menu-bar forms menu-forms-sep3]
- '("----"))
- (define-key map [menu-bar forms menu-forms-prev-field]
- '("Previous Field" . forms-prev-field))
- (define-key map [menu-bar forms menu-forms-next-field]
- '("Next Field" . forms-next-field))
- (put 'forms-insert-record 'menu-enable '(not forms-read-only))
- (put 'forms-delete-record 'menu-enable '(not forms-read-only))
-)
-(defun forms--mode-menu-edit (map)
-;;; Menu initialisation
-; (define-key map [menu-bar] (make-sparse-keymap))
- (define-key map [menu-bar forms]
- (cons "Forms" (make-sparse-keymap "Forms")))
- (define-key map [menu-bar forms menu-forms-edit--exit]
- '("Exit" . forms-exit))
- (define-key map [menu-bar forms menu-forms-edit-sep1]
- '("----"))
- (define-key map [menu-bar forms menu-forms-edit-save]
- '("Save Data" . forms-save-buffer))
- (define-key map [menu-bar forms menu-forms-edit-print]
- '("Print Data" . forms-print))
- (define-key map [menu-bar forms menu-forms-edit-describe]
- '("Describe Mode" . describe-mode))
- (define-key map [menu-bar forms menu-forms-edit-toggle-ro]
- '("Toggle View/Edit" . forms-toggle-read-only))
- (define-key map [menu-bar forms menu-forms-edit-jump-record]
- '("Jump" . forms-jump-record))
- (define-key map [menu-bar forms menu-forms-edit-search-backward]
- '("Search Backward" . forms-search-backward))
- (define-key map [menu-bar forms menu-forms-edit-search-forward]
- '("Search Forward" . forms-search-forward))
- (define-key map [menu-bar forms menu-forms-edit-delete-record]
- '("Delete" . forms-delete-record))
- (define-key map [menu-bar forms menu-forms-edit-insert-record]
- '("Insert" . forms-insert-record))
- (define-key map [menu-bar forms menu-forms-edit-sep2]
- '("----"))
- (define-key map [menu-bar forms menu-forms-edit-last-record]
- '("Last Record" . forms-last-record))
- (define-key map [menu-bar forms menu-forms-edit-first-record]
- '("First Record" . forms-first-record))
- (define-key map [menu-bar forms menu-forms-edit-prev-record]
- '("Previous Record" . forms-prev-record))
- (define-key map [menu-bar forms menu-forms-edit-next-record]
- '("Next Record" . forms-next-record))
- (define-key map [menu-bar forms menu-forms-edit-sep3]
- '("----"))
- (define-key map [menu-bar forms menu-forms-edit-prev-field]
- '("Previous Field" . forms-prev-field))
- (define-key map [menu-bar forms menu-forms-edit-next-field]
- '("Next Field" . forms-next-field))
- (put 'forms-insert-record 'menu-enable '(not forms-read-only))
- (put 'forms-delete-record 'menu-enable '(not forms-read-only))
-)
-
-(defun forms--mode-commands1 (map)
- "Helper routine to define keys."
- (define-key map [TAB] 'forms-next-field)
- (define-key map [S-tab] 'forms-prev-field)
- (define-key map [next] 'forms-next-record)
- (define-key map [prior] 'forms-prev-record)
- (define-key map [begin] 'forms-first-record)
- (define-key map [last] 'forms-last-record)
- (define-key map [backtab] 'forms-prev-field)
- )
-
-;;; Changed functions
-
-(defun forms--change-commands ()
- "Localize some commands for Forms mode."
-
- ;; scroll-down -> forms-prev-record
- ;; scroll-up -> forms-next-record
- (if forms-forms-scroll
- (progn
- (substitute-key-definition 'scroll-up 'forms-next-record
- (current-local-map)
- (current-global-map))
- (substitute-key-definition 'scroll-down 'forms-prev-record
- (current-local-map)
- (current-global-map))))
- ;;
- ;; beginning-of-buffer -> forms-first-record
- ;; end-of-buffer -> forms-end-record
- (if forms-forms-jump
- (progn
- (substitute-key-definition 'beginning-of-buffer 'forms-first-record
- (current-local-map)
- (current-global-map))
- (substitute-key-definition 'end-of-buffer 'forms-last-record
- (current-local-map)
- (current-global-map))))
- ;;
- ;; Save buffer
- (local-set-key "\C-x\C-s" 'forms-save-buffer)
- ;;
- ;; We have our own revert function - use it.
- (make-local-variable 'revert-buffer-function)
- (setq revert-buffer-function 'forms--revert-buffer)
-
- t)
-
-(defun forms--help ()
- "Initial help for Forms mode."
- (message "%s" (substitute-command-keys (concat
- "\\[forms-next-record]:next"
- " \\[forms-prev-record]:prev"
- " \\[forms-first-record]:first"
- " \\[forms-last-record]:last"
- " \\[describe-mode]:help"))))
-
-(defun forms--trans (subj arg rep)
- "Translate in SUBJ all chars ARG into char REP. ARG and REP should
- be single-char strings."
- (let ((i 0)
- (x (length subj))
- (re (regexp-quote arg))
- (k (string-to-char rep)))
- (while (setq i (string-match re subj i))
- (aset subj i k)
- (setq i (1+ i)))))
-
-(defun forms--exit (query &optional save)
- "Internal exit from forms mode function."
-
- (let ((buf (buffer-name forms--file-buffer)))
- (forms--checkmod)
- (if (and save
- (buffer-modified-p forms--file-buffer))
- (forms-save-buffer))
- (save-excursion
- (set-buffer forms--file-buffer)
- (delete-auto-save-file-if-necessary)
- (kill-buffer (current-buffer)))
- (if (get-buffer buf) ; not killed???
- (if save
- (progn
- (beep)
- (message "Problem saving buffers?")))
- (delete-auto-save-file-if-necessary)
- (kill-buffer (current-buffer)))))
-
-(defun forms--get-record ()
- "Fetch the current record from the file buffer."
-
- ;; This function is executed in the context of the `forms--file-buffer'.
-
- (or (bolp)
- (beginning-of-line nil))
- (let ((here (point)))
- (prog2
- (end-of-line)
- (buffer-substring-no-properties here (point))
- (goto-char here))))
-
-(defun forms--show-record (the-record)
- "Format THE-RECORD and display it in the current buffer."
-
- ;; Split the-record.
- (let (the-result
- (start-pos 0)
- found-pos
- (field-sep-length (length forms-field-sep)))
- (if forms-multi-line
- (forms--trans the-record forms-multi-line "\n"))
- ;; Add an extra separator (makes splitting easy).
- (setq the-record (concat the-record forms-field-sep))
- (while (setq found-pos (string-match forms-field-sep the-record start-pos))
- (let ((ent (substring the-record start-pos found-pos)))
- (setq the-result
- (append the-result (list ent)))
- (setq start-pos (+ field-sep-length found-pos))))
- (setq forms--the-record-list the-result))
-
- (setq buffer-read-only nil)
- (if forms-use-text-properties
- (let ((inhibit-read-only t))
- (set-text-properties (point-min) (point-max) nil)))
- (erase-buffer)
-
- ;; Verify the number of fields, extend forms--the-record-list if needed.
- (if (= (length forms--the-record-list) forms-number-of-fields)
- nil
- (if (null forms-check-number-of-fields)
- nil
- (beep)
- (message "Warning: this record has %d fields instead of %d"
- (length forms--the-record-list) forms-number-of-fields))
- (if (< (length forms--the-record-list) forms-number-of-fields)
- (setq forms--the-record-list
- (append forms--the-record-list
- (make-list
- (- forms-number-of-fields
- (length forms--the-record-list))
- "")))))
-
- ;; Call the formatter function.
- (setq forms-fields (append (list nil) forms--the-record-list nil))
- (funcall forms--format forms--the-record-list)
-
- ;; Prepare.
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- (setq buffer-read-only forms-read-only)
- (setq mode-line-process
- (concat " " forms--current-record "/" forms--total-records)))
-
-(defun forms--parse-form ()
- "Parse contents of form into list of strings."
- ;; The contents of the form are parsed, and a new list of strings
- ;; is constructed.
- ;; A vector with the strings from the original record is
- ;; constructed, which is updated with the new contents. Therefore
- ;; fields which were not in the form are not modified.
- ;; Finally, the vector is transformed into a list for further processing.
-
- (let (forms--recordv)
-
- ;; Build the vector.
- (setq forms--recordv (vconcat forms--the-record-list))
-
- ;; Parse the form and update the vector.
- (let ((forms--dynamic-text forms--dynamic-text))
- (funcall forms--parser))
-
- (if forms-modified-record-filter
- ;; As a service to the user, we add a zeroth element so she
- ;; can use the same indices as in the forms definition.
- (let ((the-fields (vconcat [nil] forms--recordv)))
- (setq the-fields (funcall forms-modified-record-filter the-fields))
- (cdr (append the-fields nil)))
-
- ;; Transform to a list and return.
- (append forms--recordv nil))))
-
-(defun forms--update ()
- "Update current record with contents of form.
-As a side effect: sets `forms--the-record-list'."
-
- (if forms-read-only
- (progn
- (message "Read-only buffer!")
- (beep))
-
- (let (the-record)
- ;; Build new record.
- (setq forms--the-record-list (forms--parse-form))
- (setq the-record
- (mapconcat 'identity forms--the-record-list forms-field-sep))
-
- (if (string-match (regexp-quote forms-field-sep)
- (mapconcat 'identity forms--the-record-list ""))
- (error "Field separator occurs in record - update refused!"))
-
- ;; Handle multi-line fields, if allowed.
- (if forms-multi-line
- (forms--trans the-record "\n" forms-multi-line))
-
- ;; A final sanity check before updating.
- (if (string-match "\n" the-record)
- (progn
- (message "Multi-line fields in this record - update refused!")
- (beep))
-
- (save-excursion
- (set-buffer forms--file-buffer)
- ;; Use delete-region instead of kill-region, to avoid
- ;; adding junk to the kill-ring.
- (delete-region (save-excursion (beginning-of-line) (point))
- (save-excursion (end-of-line) (point)))
- (insert the-record)
- (beginning-of-line))))))
-
-(defun forms--checkmod ()
- "Check if this form has been modified, and call forms--update if so."
- (if (buffer-modified-p nil)
- (let ((here (point)))
- (forms--update)
- (set-buffer-modified-p nil)
- (goto-char here))))
-
-;;; Start and exit
-
-;;;###autoload
-(defun forms-find-file (fn)
- "Visit a file in Forms mode."
- (interactive "fForms file: ")
- (let ((enable-local-eval t)
- (enable-local-variables t))
- (find-file-read-only fn)
- (or forms--mode-setup (forms-mode t))))
-
-;;;###autoload
-(defun forms-find-file-other-window (fn)
- "Visit a file in Forms mode in other window."
- (interactive "fFbrowse file in other window: ")
- (let ((enable-local-eval t)
- (enable-local-variables t))
- (find-file-other-window fn)
- (or forms--mode-setup (forms-mode t))))
-
-(defun forms-exit (query)
- "Normal exit from Forms mode. Modified buffers are saved."
- (interactive "P")
- (forms--exit query t))
-
-(defun forms-exit-no-save (query)
- "Exit from Forms mode without saving buffers."
- (interactive "P")
- (forms--exit query nil))
-
-;;; Navigating commands
-
-(defun forms-next-record (arg)
- "Advance to the ARGth following record."
- (interactive "P")
- (forms-jump-record (+ forms--current-record (prefix-numeric-value arg)) t))
-
-(defun forms-prev-record (arg)
- "Advance to the ARGth previous record."
- (interactive "P")
- (forms-jump-record (- forms--current-record (prefix-numeric-value arg)) t))
-
-(defun forms-jump-record (arg &optional relative)
- "Jump to a random record."
- (interactive "NRecord number: ")
-
- ;; Verify that the record number is within range.
- (if (or (> arg forms--total-records)
- (<= arg 0))
- (progn
- (beep)
- ;; Don't give the message if just paging.
- (if (not relative)
- (message "Record number %d out of range 1..%d"
- arg forms--total-records))
- )
-
- ;; Flush.
- (forms--checkmod)
-
- ;; Calculate displacement.
- (let ((disp (- arg forms--current-record))
- (cur forms--current-record))
-
- ;; `forms--show-record' needs it now.
- (setq forms--current-record arg)
-
- ;; Get the record and show it.
- (forms--show-record
- (save-excursion
- (set-buffer forms--file-buffer)
- (beginning-of-line)
-
- ;; Move, and adjust the amount if needed (shouldn't happen).
- (if relative
- (if (zerop disp)
- nil
- (setq cur (+ cur disp (- (forward-line disp)))))
- (setq cur (+ cur disp (- (goto-line arg)))))
-
- (forms--get-record)))
-
- ;; This shouldn't happen.
- (if (/= forms--current-record cur)
- (progn
- (setq forms--current-record cur)
- (beep)
- (message "Stuck at record %d" cur))))))
-
-(defun forms-first-record ()
- "Jump to first record."
- (interactive)
- (forms-jump-record 1))
-
-(defun forms-last-record ()
- "Jump to last record.
-As a side effect: re-calculates the number of records in the data file."
- (interactive)
- (let
- ((numrec
- (save-excursion
- (set-buffer forms--file-buffer)
- (count-lines (point-min) (point-max)))))
- (if (= numrec forms--total-records)
- nil
- (beep)
- (setq forms--total-records numrec)
- (message "Warning: number of records changed to %d" forms--total-records)))
- (forms-jump-record forms--total-records))
-
-;;; Other commands
-
-(defun forms-toggle-read-only (arg)
- "Toggles read-only mode of a forms mode buffer.
-With an argument, enables read-only mode if the argument is positive.
-Otherwise enables edit mode if the visited file is writable."
-
- (interactive "P")
-
- (if (if arg
- ;; Negative arg means switch it off.
- (<= (prefix-numeric-value arg) 0)
- ;; No arg means toggle.
- forms-read-only)
-
- ;; Enable edit mode, if possible.
- (let ((ro forms-read-only))
- (if (save-excursion
- (set-buffer forms--file-buffer)
- buffer-read-only)
- (progn
- (setq forms-read-only t)
- (message "No write access to `%s'" forms-file)
- (beep))
- (setq forms-read-only nil))
- (if (equal ro forms-read-only)
- nil
- (forms-mode)))
-
- ;; Enable view mode.
- (if forms-read-only
- nil
- (forms--checkmod) ; sync
- (setq forms-read-only t)
- (forms-mode))))
-
-;; Sample:
-;; (defun my-new-record-filter (the-fields)
-;; ;; numbers are relative to 1
-;; (aset the-fields 4 (current-time-string))
-;; (aset the-fields 6 (user-login-name))
-;; the-list)
-;; (setq forms-new-record-filter 'my-new-record-filter)
-
-(defun forms-insert-record (arg)
- "Create a new record before the current one.
-With ARG: store the record after the current one.
-If `forms-new-record-filter' contains the name of a function,
-it is called to fill (some of) the fields with default values.
-If `forms-insert-after is non-nil, the default behavior is to insert
-after the current record."
-
- (interactive "P")
-
- (if forms-read-only
- (error ""))
-
- (let (ln the-list the-record)
-
- (if (or (and arg forms-insert-after)
- (and (not arg) (not forms-insert-after)))
- (setq ln forms--current-record)
- (setq ln (1+ forms--current-record)))
-
- (forms--checkmod)
- (if forms-new-record-filter
- ;; As a service to the user, we add a zeroth element so she
- ;; can use the same indices as in the forms definition.
- (let ((the-fields (make-vector (1+ forms-number-of-fields) "")))
- (setq the-fields (funcall forms-new-record-filter the-fields))
- (setq the-list (cdr (append the-fields nil))))
- (setq the-list (make-list forms-number-of-fields "")))
-
- (setq the-record
- (mapconcat
- 'identity
- the-list
- forms-field-sep))
-
- (save-excursion
- (set-buffer forms--file-buffer)
- (goto-line ln)
- (open-line 1)
- (insert the-record)
- (beginning-of-line))
-
- (setq forms--current-record ln))
-
- (setq forms--total-records (1+ forms--total-records))
- (forms-jump-record forms--current-record))
-
-(defun forms-delete-record (arg)
- "Deletes a record. With a prefix argument: don't ask."
- (interactive "P")
-
- (if forms-read-only
- (error ""))
-
- (forms--checkmod)
- (if (or arg
- (y-or-n-p "Really delete this record? "))
- (let ((ln forms--current-record))
- (save-excursion
- (set-buffer forms--file-buffer)
- (goto-line ln)
- ;; Use delete-region instead of kill-region, to avoid
- ;; adding junk to the kill-ring.
- (delete-region (progn (beginning-of-line) (point))
- (progn (beginning-of-line 2) (point))))
- (setq forms--total-records (1- forms--total-records))
- (if (> forms--current-record forms--total-records)
- (setq forms--current-record forms--total-records))
- (forms-jump-record forms--current-record)))
- (message ""))
-
-(defun forms-search-forward (regexp)
- "Search forward for record containing REGEXP."
- (interactive
- (list (read-string (concat "Search forward for"
- (if forms--search-regexp
- (concat " ("
- forms--search-regexp
- ")"))
- ": "))))
- (if (equal "" regexp)
- (setq regexp forms--search-regexp))
- (forms--checkmod)
-
- (let (the-line the-record here
- (fld-sep forms-field-sep))
- (if (save-excursion
- (set-buffer forms--file-buffer)
- (setq here (point))
- (end-of-line)
- (if (null (re-search-forward regexp nil t))
- (progn
- (goto-char here)
- (message "\"%s\" not found" regexp)
- nil)
- (setq the-record (forms--get-record))
- (setq the-line (1+ (count-lines (point-min) (point))))))
- (progn
- (setq forms--current-record the-line)
- (forms--show-record the-record)
- (re-search-forward regexp nil t))))
- (setq forms--search-regexp regexp))
-
-(defun forms-search-backward (regexp)
- "Search backward for record containing REGEXP."
- (interactive
- (list (read-string (concat "Search backward for"
- (if forms--search-regexp
- (concat " ("
- forms--search-regexp
- ")"))
- ": "))))
- (if (equal "" regexp)
- (setq regexp forms--search-regexp))
- (forms--checkmod)
-
- (let (the-line the-record here
- (fld-sep forms-field-sep))
- (if (save-excursion
- (set-buffer forms--file-buffer)
- (setq here (point))
- (beginning-of-line)
- (if (null (re-search-backward regexp nil t))
- (progn
- (goto-char here)
- (message "\"%s\" not found" regexp)
- nil)
- (setq the-record (forms--get-record))
- (setq the-line (1+ (count-lines (point-min) (point))))))
- (progn
- (setq forms--current-record the-line)
- (forms--show-record the-record)
- (re-search-forward regexp nil t))))
- (setq forms--search-regexp regexp))
-
-(defun forms-save-buffer (&optional args)
- "Forms mode replacement for save-buffer.
-It saves the data buffer instead of the forms buffer.
-Calls `forms-write-file-filter' before writing out the data."
- (interactive "p")
- (forms--checkmod)
- (let ((read-file-filter forms-read-file-filter))
- (save-excursion
- (set-buffer forms--file-buffer)
- (let ((inhibit-read-only t))
- (save-buffer args)
- (if read-file-filter
- (run-hooks 'read-file-filter))
- (set-buffer-modified-p nil))))
- t)
-
-(defun forms--revert-buffer (&optional arg noconfirm)
- "Reverts current form to un-modified."
- (interactive "P")
- (if (or noconfirm
- (yes-or-no-p "Revert form to unmodified? "))
- (progn
- (set-buffer-modified-p nil)
- (forms-jump-record forms--current-record))))
-
-(defun forms-next-field (arg)
- "Jump to ARG-th next field."
- (interactive "p")
-
- (let ((i 0)
- (here (point))
- there
- (cnt 0)
- (inhibit-point-motion-hooks t))
-
- (if (zerop arg)
- (setq cnt 1)
- (setq cnt (+ cnt arg)))
-
- (if (catch 'done
- (while (< i (length forms--markers))
- (if (or (null (setq there (aref forms--markers i)))
- (<= there here))
- nil
- (if (<= (setq cnt (1- cnt)) 0)
- (progn
- (goto-char there)
- (throw 'done t))))
- (setq i (1+ i))))
- nil
- (goto-char (aref forms--markers 0)))))
-
-(defun forms-prev-field (arg)
- "Jump to ARG-th previous field."
- (interactive "p")
-
- (let ((i (length forms--markers))
- (here (point))
- there
- (cnt 0)
- (inhibit-point-motion-hooks t))
-
- (if (zerop arg)
- (setq cnt 1)
- (setq cnt (+ cnt arg)))
-
- (if (catch 'done
- (while (> i 0)
- (setq i ( 1- i))
- (if (or (null (setq there (aref forms--markers i)))
- (>= there here))
- nil
- (if (<= (setq cnt (1- cnt)) 0)
- (progn
- (goto-char there)
- (throw 'done t))))))
- nil
- (goto-char (aref forms--markers (1- (length forms--markers)))))))
-
-(defun forms-print ()
- "Send the records to the printer with 'print-buffer', one record per page."
- (interactive)
- (let ((inhibit-read-only t)
- (save-record forms--current-record)
- (nb-record 1)
- (record nil))
- (while (<= nb-record forms--total-records)
- (forms-jump-record nb-record)
- (setq record (buffer-string))
- (save-excursion
- (set-buffer (get-buffer-create "*forms-print*"))
- (goto-char (buffer-end 1))
- (insert record)
- (setq buffer-read-only nil)
- (if (< nb-record forms--total-records)
- (insert "\n \n")))
- (setq nb-record (1+ nb-record)))
- (save-excursion
- (set-buffer "*forms-print*")
- (print-buffer)
- (set-buffer-modified-p nil)
- (kill-buffer (current-buffer)))
- (forms-jump-record save-record)))
-
-;;;
-;;; Special service
-;;;
-(defun forms-enumerate (the-fields)
- "Take a quoted list of symbols, and set their values to sequential numbers.
-The first symbol gets number 1, the second 2 and so on.
-It returns the highest number.
-
-Usage: (setq forms-number-of-fields
- (forms-enumerate
- '(field1 field2 field2 ...)))"
-
- (let ((the-index 0))
- (while the-fields
- (setq the-index (1+ the-index))
- (let ((el (car-safe the-fields)))
- (setq the-fields (cdr-safe the-fields))
- (set el the-index)))
- the-index))
-
-;;; Debugging
-
-(defvar forms--debug nil
- "*Enables forms-mode debugging if not nil.")
-
-(defun forms--debug (&rest args)
- "Internal debugging routine."
- (if forms--debug
- (let ((ret nil))
- (while args
- (let ((el (car-safe args)))
- (setq args (cdr-safe args))
- (if (stringp el)
- (setq ret (concat ret el))
- (setq ret (concat ret (prin1-to-string el) " = "))
- (if (boundp el)
- (let ((vel (eval el)))
- (setq ret (concat ret (prin1-to-string vel) "\n")))
- (setq ret (concat ret "<unbound>" "\n")))
- (if (fboundp el)
- (setq ret (concat ret (prin1-to-string (symbol-function el))
- "\n"))))))
- (save-excursion
- (set-buffer (get-buffer-create "*forms-mode debug*"))
- (if (zerop (buffer-size))
- (emacs-lisp-mode))
- (goto-char (point-max))
- (insert ret)))))
-
-;;; forms.el ends here.
diff --git a/lisp/frame.el b/lisp/frame.el
deleted file mode 100644
index c97a6d3ab7f..00000000000
--- a/lisp/frame.el
+++ /dev/null
@@ -1,727 +0,0 @@
-;;; frame.el --- multi-frame management independent of window systems.
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(defvar frame-creation-function nil
- "Window-system dependent function to call to create a new frame.
-The window system startup file should set this to its frame creation
-function, which should take an alist of parameters as its argument.")
-
-;;; The initial value given here for used to ask for a minibuffer.
-;;; But that's not necessary, because the default is to have one.
-;;; By not specifying it here, we let an X resource specify it.
-(defvar initial-frame-alist nil
- "Alist of frame parameters for creating the initial X window frame.
-You can set this in your `.emacs' file; for example,
- (setq initial-frame-alist '((top . 1) (left . 1) (width . 80) (height . 55)))
-Parameters specified here supersede the values given in `default-frame-alist'.
-
-If the value calls for a frame without a minibuffer, and you have not created
-a minibuffer frame on your own, one is created according to
-`minibuffer-frame-alist'.
-
-You can specify geometry-related options for just the initial frame
-by setting this variable in your `.emacs' file; however, they won't
-take effect until Emacs reads `.emacs', which happens after first creating
-the frame. If you want the frame to have the proper geometry as soon
-as it appears, you need to use this three-step process:
-* Specify X resources to give the geometry you want.
-* Set `default-frame-alist' to override these options so that they
- don't affect subsequent frames.
-* Set `initial-frame-alist' in a way that matches the X resources,
- to override what you put in `default-frame-alist'.")
-
-(defvar minibuffer-frame-alist '((width . 80) (height . 2))
- "Alist of frame parameters for initially creating a minibuffer frame.
-You can set this in your `.emacs' file; for example,
- (setq minibuffer-frame-alist
- '((top . 1) (left . 1) (width . 80) (height . 2)))
-Parameters specified here supersede the values given in
-`default-frame-alist'.")
-
-(defvar pop-up-frame-alist nil
- "Alist of frame parameters used when creating pop-up frames.
-Pop-up frames are used for completions, help, and the like.
-This variable can be set in your init file, like this:
- (setq pop-up-frame-alist '((width . 80) (height . 20)))
-These supersede the values given in `default-frame-alist'.")
-
-(setq pop-up-frame-function
- (function (lambda ()
- (make-frame pop-up-frame-alist))))
-
-(defvar special-display-frame-alist
- '((height . 14) (width . 80) (unsplittable . t))
- "*Alist of frame parameters used when creating special frames.
-Special frames are used for buffers whose names are in
-`special-display-buffer-names' and for buffers whose names match
-one of the regular expressions in `special-display-regexps'.
-This variable can be set in your init file, like this:
- (setq special-display-frame-alist '((width . 80) (height . 20)))
-These supersede the values given in `default-frame-alist'.")
-
-;; Display BUFFER in its own frame, reusing an existing window if any.
-;; Return the window chosen.
-;; Currently we do not insist on selecting the window within its frame.
-;; If ARGS is an alist, use it as a list of frame parameter specs.
-;; If ARGS is a list whose car is a symbol,
-;; use (car ARGS) as a function to do the work.
-;; Pass it BUFFER as first arg, and (cdr ARGS) gives the rest of the args.
-(defun special-display-popup-frame (buffer &optional args)
- (if (and args (symbolp (car args)))
- (apply (car args) buffer (cdr args))
- (let ((window (get-buffer-window buffer t)))
- (if window
- ;; If we have a window already, make it visible.
- (let ((frame (window-frame window)))
- (make-frame-visible frame)
- (raise-frame frame)
- window)
- ;; If no window yet, make one in a new frame.
- (let ((frame (make-frame (append args special-display-frame-alist))))
- (set-window-buffer (frame-selected-window frame) buffer)
- (set-window-dedicated-p (frame-selected-window frame) t)
- (frame-selected-window frame))))))
-
-;; Handle delete-frame events from the X server.
-(defun handle-delete-frame (event)
- (interactive "e")
- (let ((frame (posn-window (event-start event)))
- (i 0)
- (tail (frame-list)))
- (while tail
- (and (frame-visible-p (car tail))
- (not (eq (car tail) frame))
- (setq i (1+ i)))
- (setq tail (cdr tail)))
- (if (> i 0)
- (delete-frame frame t)
- ;; Gildea@x.org says it is ok to ask questions before terminating.
- (save-buffers-kill-emacs))))
-
-;;;; Arrangement of frames at startup
-
-;;; 1) Load the window system startup file from the lisp library and read the
-;;; high-priority arguments (-q and the like). The window system startup
-;;; file should create any frames specified in the window system defaults.
-;;;
-;;; 2) If no frames have been opened, we open an initial text frame.
-;;;
-;;; 3) Once the init file is done, we apply any newly set parameters
-;;; in initial-frame-alist to the frame.
-
-;; These are now called explicitly at the proper times,
-;; since that is easier to understand.
-;; Actually using hooks within Emacs is bad for future maintenance. --rms.
-;; (add-hook 'before-init-hook 'frame-initialize)
-;; (add-hook 'window-setup-hook 'frame-notice-user-settings)
-
-;;; If we create the initial frame, this is it.
-(defvar frame-initial-frame nil)
-
-;; Record the parameters used in frame-initialize to make the initial frame.
-(defvar frame-initial-frame-alist)
-
-(defvar frame-initial-geometry-arguments nil)
-
-;;; startup.el calls this function before loading the user's init
-;;; file - if there is no frame with a minibuffer open now, create
-;;; one to display messages while loading the init file.
-(defun frame-initialize ()
-
- ;; Are we actually running under a window system at all?
- (if (and window-system (not noninteractive) (not (eq window-system 'pc)))
- (progn
- ;; Turn on special-display processing only if there's a window system.
- (setq special-display-function 'special-display-popup-frame)
-
- ;; If there is no frame with a minibuffer besides the terminal
- ;; frame, then we need to create the opening frame. Make sure
- ;; it has a minibuffer, but let initial-frame-alist omit the
- ;; minibuffer spec.
- (or (delq terminal-frame (minibuffer-frame-list))
- (progn
- (setq frame-initial-frame-alist
- (append initial-frame-alist default-frame-alist))
- ;; Record these with their default values
- ;; if they don't have any values explicitly.
- (or (assq 'vertical-scroll-bars frame-initial-frame-alist)
- (setq frame-initial-frame-alist
- (cons '(vertical-scroll-bars . t)
- frame-initial-frame-alist)))
- (or (assq 'horizontal-scroll-bars frame-initial-frame-alist)
- (setq frame-initial-frame-alist
- (cons '(horizontal-scroll-bars . t)
- frame-initial-frame-alist)))
- (setq default-minibuffer-frame
- (setq frame-initial-frame
- (make-frame initial-frame-alist)))
- ;; Delete any specifications for window geometry parameters
- ;; so that we won't reapply them in frame-notice-user-settings.
- ;; It would be wrong to reapply them then,
- ;; because that would override explicit user resizing.
- (setq initial-frame-alist
- (frame-remove-geometry-params initial-frame-alist))))
- ;; At this point, we know that we have a frame open, so we
- ;; can delete the terminal frame.
- (delete-frame terminal-frame)
- (setq terminal-frame nil))
-
- ;; No, we're not running a window system. Use make-terminal-frame if
- ;; we support that feature, otherwise arrange to cause errors.
- (or (eq window-system 'pc)
- (setq frame-creation-function
- (if (fboundp 'make-terminal-frame)
- 'make-terminal-frame
- (function
- (lambda (parameters)
- (error
- "Can't create multiple frames without a window system"))))))))
-
-;;; startup.el calls this function after loading the user's init
-;;; file. Now default-frame-alist and initial-frame-alist contain
-;;; information to which we must react; do what needs to be done.
-(defun frame-notice-user-settings ()
-
- ;; Make menu-bar-mode and default-frame-alist consistent.
- (if (boundp 'menu-bar-mode)
- (let ((default (assq 'menu-bar-lines default-frame-alist)))
- (if default
- (setq menu-bar-mode (not (eq (cdr default) 0)))
- (setq default-frame-alist
- (cons (cons 'menu-bar-lines (if menu-bar-mode 1 0))
- default-frame-alist)))))
-
- ;; Creating and deleting frames may shift the selected frame around,
- ;; and thus the current buffer. Protect against that. We don't
- ;; want to use save-excursion here, because that may also try to set
- ;; the buffer of the selected window, which fails when the selected
- ;; window is the minibuffer.
- (let ((old-buffer (current-buffer)))
-
- ;; If the initial frame is still around, apply initial-frame-alist
- ;; and default-frame-alist to it.
- (if (frame-live-p frame-initial-frame)
-
- ;; The initial frame we create above always has a minibuffer.
- ;; If the user wants to remove it, or make it a minibuffer-only
- ;; frame, then we'll have to delete the current frame and make a
- ;; new one; you can't remove or add a root window to/from an
- ;; existing frame.
- ;;
- ;; NOTE: default-frame-alist was nil when we created the
- ;; existing frame. We need to explicitly include
- ;; default-frame-alist in the parameters of the screen we
- ;; create here, so that its new value, gleaned from the user's
- ;; .emacs file, will be applied to the existing screen.
- (if (not (eq (cdr (or (assq 'minibuffer initial-frame-alist)
- (assq 'minibuffer default-frame-alist)
- '(minibuffer . t)))
- t))
- ;; Create the new frame.
- (let (parms new)
- ;; If the frame isn't visible yet, wait till it is.
- ;; If the user has to position the window,
- ;; Emacs doesn't know its real position until
- ;; the frame is seen to be visible.
- (while (not (cdr (assq 'visibility
- (frame-parameters frame-initial-frame))))
- (sleep-for 1))
- (setq parms (frame-parameters frame-initial-frame))
- ;; Get rid of `name' unless it was specified explicitly before.
- (or (assq 'name frame-initial-frame-alist)
- (setq parms (delq (assq 'name parms) parms)))
- (setq parms (append initial-frame-alist
- default-frame-alist
- parms
- nil))
- ;; Get rid of `reverse', because that was handled
- ;; when we first made the frame.
- (setq parms (cons '(reverse) (delq (assq 'reverse parms) parms)))
- (if (assq 'height frame-initial-geometry-arguments)
- (setq parms (frame-delete-all 'height parms)))
- (if (assq 'width frame-initial-geometry-arguments)
- (setq parms (frame-delete-all 'width parms)))
- (if (assq 'left frame-initial-geometry-arguments)
- (setq parms (frame-delete-all 'left parms)))
- (if (assq 'top frame-initial-geometry-arguments)
- (setq parms (frame-delete-all 'top parms)))
- (setq new
- (make-frame
- ;; Use the geometry args that created the existing
- ;; frame, rather than the parms we get for it.
- (append frame-initial-geometry-arguments
- '((user-size . t) (user-position . t))
- parms)))
- ;; The initial frame, which we are about to delete, may be
- ;; the only frame with a minibuffer. If it is, create a
- ;; new one.
- (or (delq frame-initial-frame (minibuffer-frame-list))
- (make-initial-minibuffer-frame nil))
-
- ;; If the initial frame is serving as a surrogate
- ;; minibuffer frame for any frames, we need to wean them
- ;; onto a new frame. The default-minibuffer-frame
- ;; variable must be handled similarly.
- (let ((users-of-initial
- (filtered-frame-list
- (function (lambda (frame)
- (and (not (eq frame frame-initial-frame))
- (eq (window-frame
- (minibuffer-window frame))
- frame-initial-frame)))))))
- (if (or users-of-initial
- (eq default-minibuffer-frame frame-initial-frame))
-
- ;; Choose an appropriate frame. Prefer frames which
- ;; are only minibuffers.
- (let* ((new-surrogate
- (car
- (or (filtered-frame-list
- (function
- (lambda (frame)
- (eq (cdr (assq 'minibuffer
- (frame-parameters frame)))
- 'only))))
- (minibuffer-frame-list))))
- (new-minibuffer (minibuffer-window new-surrogate)))
-
- (if (eq default-minibuffer-frame frame-initial-frame)
- (setq default-minibuffer-frame new-surrogate))
-
- ;; Wean the frames using frame-initial-frame as
- ;; their minibuffer frame.
- (mapcar
- (function
- (lambda (frame)
- (modify-frame-parameters
- frame (list (cons 'minibuffer new-minibuffer)))))
- users-of-initial))))
-
- ;; Redirect events enqueued at this frame to the new frame.
- ;; Is this a good idea?
- (redirect-frame-focus frame-initial-frame new)
-
- ;; Finally, get rid of the old frame.
- (delete-frame frame-initial-frame t))
-
- ;; Otherwise, we don't need all that rigamarole; just apply
- ;; the new parameters.
- (let (newparms allparms tail)
- (setq allparms (append initial-frame-alist
- default-frame-alist))
- (if (assq 'height frame-initial-geometry-arguments)
- (setq allparms (frame-delete-all 'height allparms)))
- (if (assq 'width frame-initial-geometry-arguments)
- (setq allparms (frame-delete-all 'width allparms)))
- (if (assq 'left frame-initial-geometry-arguments)
- (setq allparms (frame-delete-all 'left allparms)))
- (if (assq 'top frame-initial-geometry-arguments)
- (setq allparms (frame-delete-all 'top allparms)))
- (setq tail allparms)
- ;; Find just the parms that have changed since we first
- ;; made this frame. Those are the ones actually set by
- ;; the init file. For those parms whose values we already knew
- ;; (such as those spec'd by command line options)
- ;; it is undesirable to specify the parm again
- ;; once the user has seen the frame and been able to alter it
- ;; manually.
- (while tail
- (let (newval oldval)
- (setq oldval (assq (car (car tail))
- frame-initial-frame-alist))
- (setq newval (cdr (assq (car (car tail)) allparms)))
- (or (and oldval (eq (cdr oldval) newval))
- (setq newparms
- (cons (cons (car (car tail)) newval) newparms))))
- (setq tail (cdr tail)))
- (setq newparms (nreverse newparms))
- (modify-frame-parameters frame-initial-frame
- newparms)
- (if (assq 'font newparms)
- (frame-update-faces frame-initial-frame)))))
-
- ;; Restore the original buffer.
- (set-buffer old-buffer)
-
- ;; Make sure the initial frame can be GC'd if it is ever deleted.
- ;; Make sure frame-notice-user-settings does nothing if called twice.
- (setq frame-initial-frame nil)))
-
-(defun make-initial-minibuffer-frame (display)
- (let ((parms (append minibuffer-frame-alist '((minibuffer . only)))))
- (if display
- (make-frame-on-display display parms)
- (make-frame parms))))
-
-;; Delete from ALIST all elements whose car is KEY.
-;; Return the modified alist.
-(defun frame-delete-all (key alist)
- (setq alist (copy-sequence alist))
- (let ((tail alist))
- (while tail
- (if (eq (car (car tail)) key)
- (setq alist (delq (car tail) alist)))
- (setq tail (cdr tail)))
- alist))
-
-;;;; Creation of additional frames, and other frame miscellanea
-
-;;; Return some frame other than the current frame, creating one if
-;;; necessary. Note that the minibuffer frame, if separate, is not
-;;; considered (see next-frame).
-(defun get-other-frame ()
- (let ((s (if (equal (next-frame (selected-frame)) (selected-frame))
- (make-frame)
- (next-frame (selected-frame)))))
- s))
-
-(defun next-multiframe-window ()
- "Select the next window, regardless of which frame it is on."
- (interactive)
- (select-window (next-window (selected-window)
- (> (minibuffer-depth) 0)
- t)))
-
-(defun previous-multiframe-window ()
- "Select the previous window, regardless of which frame it is on."
- (interactive)
- (select-window (previous-window (selected-window)
- (> (minibuffer-depth) 0)
- t)))
-
-(defun make-frame-on-display (display &optional parameters)
- "Make a frame on display DISPLAY.
-The optional second argument PARAMETERS specifies additional frame parameters."
- (interactive "sMake frame on display: ")
- (make-frame (cons (cons 'display display) parameters)))
-
-(defun make-frame-command ()
- "Make a new frame, and select it if the terminal displays only one frame."
- (interactive)
- (if (and window-system (not (eq window-system 'pc)))
- (make-frame)
- (select-frame (make-frame))))
-
-;; Alias, kept temporarily.
-(defalias 'new-frame 'make-frame)
-(defun make-frame (&optional parameters)
- "Create a new frame, displaying the current buffer.
-
-Optional argument PARAMETERS is an alist of parameters for the new
-frame. Specifically, PARAMETERS is a list of pairs, each having
-the form (NAME . VALUE).
-
-Here are some of the parameters allowed (not a complete list):
-
-\(name . STRING) - The frame should be named STRING.
-
-\(height . NUMBER) - The frame should be NUMBER text lines high. If
- this parameter is present, the width parameter must also be
- given.
-
-\(width . NUMBER) - The frame should be NUMBER characters in width.
- If this parameter is present, the height parameter must also
- be given.
-
-\(minibuffer . t) - the frame should have a minibuffer
-\(minibuffer . nil) - the frame should have no minibuffer
-\(minibuffer . only) - the frame should contain only a minibuffer
-\(minibuffer . WINDOW) - the frame should use WINDOW as its minibuffer window."
- (interactive)
- (let ((nframe))
- (run-hooks 'before-make-frame-hook)
- (setq nframe (funcall frame-creation-function parameters))
- (run-hooks 'after-make-frame-hook)
- nframe))
-
-(defun filtered-frame-list (predicate)
- "Return a list of all live frames which satisfy PREDICATE."
- (let ((frames (frame-list))
- good-frames)
- (while (consp frames)
- (if (funcall predicate (car frames))
- (setq good-frames (cons (car frames) good-frames)))
- (setq frames (cdr frames)))
- good-frames))
-
-(defun minibuffer-frame-list ()
- "Return a list of all frames with their own minibuffers."
- (filtered-frame-list
- (function (lambda (frame)
- (eq frame (window-frame (minibuffer-window frame)))))))
-
-(defun frame-remove-geometry-params (param-list)
- "Return the parameter list PARAM-LIST, but with geometry specs removed.
-This deletes all bindings in PARAM-LIST for `top', `left', `width',
-`height', `user-size' and `user-position' parameters.
-Emacs uses this to avoid overriding explicit moves and resizings from
-the user during startup."
- (setq param-list (cons nil param-list))
- (let ((tail param-list))
- (while (consp (cdr tail))
- (if (and (consp (car (cdr tail)))
- (memq (car (car (cdr tail)))
- '(height width top left user-position user-size)))
- (progn
- (setq frame-initial-geometry-arguments
- (cons (car (cdr tail)) frame-initial-geometry-arguments))
- (setcdr tail (cdr (cdr tail))))
- (setq tail (cdr tail)))))
- (setq frame-initial-geometry-arguments
- (nreverse frame-initial-geometry-arguments))
- (cdr param-list))
-
-
-(defun other-frame (arg)
- "Select the ARG'th different visible frame, and raise it.
-All frames are arranged in a cyclic order.
-This command selects the frame ARG steps away in that order.
-A negative ARG moves in the opposite order."
- (interactive "p")
- (let ((frame (selected-frame)))
- (while (> arg 0)
- (setq frame (next-frame frame))
- (while (not (eq (frame-visible-p frame) t))
- (setq frame (next-frame frame)))
- (setq arg (1- arg)))
- (while (< arg 0)
- (setq frame (previous-frame frame))
- (while (not (eq (frame-visible-p frame) t))
- (setq frame (previous-frame frame)))
- (setq arg (1+ arg)))
- (raise-frame frame)
- (select-frame frame)
- (set-mouse-position (selected-frame) (1- (frame-width)) 0)))
-
-;;;; Frame configurations
-
-(defun current-frame-configuration ()
- "Return a list describing the positions and states of all frames.
-Its car is `frame-configuration'.
-Each element of the cdr is a list of the form (FRAME ALIST WINDOW-CONFIG),
-where
- FRAME is a frame object,
- ALIST is an association list specifying some of FRAME's parameters, and
- WINDOW-CONFIG is a window configuration object for FRAME."
- (cons 'frame-configuration
- (mapcar (function
- (lambda (frame)
- (list frame
- (frame-parameters frame)
- (current-window-configuration frame))))
- (frame-list))))
-
-(defun set-frame-configuration (configuration &optional nodelete)
- "Restore the frames to the state described by CONFIGURATION.
-Each frame listed in CONFIGURATION has its position, size, window
-configuration, and other parameters set as specified in CONFIGURATION.
-Ordinarily, this function deletes all existing frames not
-listed in CONFIGURATION. But if optional second argument NODELETE
-is given and non-nil, the unwanted frames are iconified instead."
- (or (frame-configuration-p configuration)
- (signal 'wrong-type-argument
- (list 'frame-configuration-p configuration)))
- (let ((config-alist (cdr configuration))
- frames-to-delete)
- (mapcar (function
- (lambda (frame)
- (let ((parameters (assq frame config-alist)))
- (if parameters
- (progn
- (modify-frame-parameters
- frame
- ;; Since we can't set a frame's minibuffer status,
- ;; we might as well omit the parameter altogether.
- (let* ((parms (nth 1 parameters))
- (mini (assq 'minibuffer parms)))
- (if mini (setq parms (delq mini parms)))
- parms))
- (set-window-configuration (nth 2 parameters)))
- (setq frames-to-delete (cons frame frames-to-delete))))))
- (frame-list))
- (if nodelete
- ;; Note: making frames invisible here was tried
- ;; but led to some strange behavior--each time the frame
- ;; was made visible again, the window manager asked afresh
- ;; for where to put it.
- (mapcar 'iconify-frame frames-to-delete)
- (mapcar 'delete-frame frames-to-delete))))
-
-;;;; Convenience functions for accessing and interactively changing
-;;;; frame parameters.
-
-(defun frame-height (&optional frame)
- "Return number of lines available for display on FRAME.
-If FRAME is omitted, describe the currently selected frame."
- (cdr (assq 'height (frame-parameters frame))))
-
-(defun frame-width (&optional frame)
- "Return number of columns available for display on FRAME.
-If FRAME is omitted, describe the currently selected frame."
- (cdr (assq 'width (frame-parameters frame))))
-
-(defun set-default-font (font-name)
- "Set the font of the selected frame to FONT.
-When called interactively, prompt for the name of the font to use.
-To get the frame's current default font, use `frame-parameters'."
- (interactive "sFont name: ")
- (modify-frame-parameters (selected-frame)
- (list (cons 'font font-name)))
- ;; Update faces that want a bold or italic version of the default font.
- (frame-update-faces (selected-frame)))
-
-(defun set-background-color (color-name)
- "Set the background color of the selected frame to COLOR.
-When called interactively, prompt for the name of the color to use.
-To get the frame's current background color, use `frame-parameters'."
- (interactive "sColor: ")
- (modify-frame-parameters (selected-frame)
- (list (cons 'background-color color-name)))
- (frame-update-face-colors (selected-frame)))
-
-(defun set-foreground-color (color-name)
- "Set the foreground color of the selected frame to COLOR.
-When called interactively, prompt for the name of the color to use.
-To get the frame's current foreground color, use `frame-parameters'."
- (interactive "sColor: ")
- (modify-frame-parameters (selected-frame)
- (list (cons 'foreground-color color-name)))
- (frame-update-face-colors (selected-frame)))
-
-(defun set-cursor-color (color-name)
- "Set the text cursor color of the selected frame to COLOR.
-When called interactively, prompt for the name of the color to use.
-To get the frame's current cursor color, use `frame-parameters'."
- (interactive "sColor: ")
- (modify-frame-parameters (selected-frame)
- (list (cons 'cursor-color color-name))))
-
-(defun set-mouse-color (color-name)
- "Set the color of the mouse pointer of the selected frame to COLOR.
-When called interactively, prompt for the name of the color to use.
-To get the frame's current mouse color, use `frame-parameters'."
- (interactive "sColor: ")
- (modify-frame-parameters (selected-frame)
- (list (cons 'mouse-color color-name))))
-
-(defun set-border-color (color-name)
- "Set the color of the border of the selected frame to COLOR.
-When called interactively, prompt for the name of the color to use.
-To get the frame's current border color, use `frame-parameters'."
- (interactive "sColor: ")
- (modify-frame-parameters (selected-frame)
- (list (cons 'border-color color-name))))
-
-(defun auto-raise-mode (arg)
- "Toggle whether or not the selected frame should auto-raise.
-With arg, turn auto-raise mode on if and only if arg is positive.
-Note that this controls Emacs's own auto-raise feature.
-Some window managers allow you to enable auto-raise for certain windows.
-You can use that for Emacs windows if you wish, but if you do,
-that is beyond the control of Emacs and this command has no effect on it."
- (interactive "P")
- (if (null arg)
- (setq arg
- (if (cdr (assq 'auto-raise (frame-parameters (selected-frame))))
- -1 1)))
- (modify-frame-parameters (selected-frame)
- (list (cons 'auto-raise (> arg 0)))))
-
-(defun auto-lower-mode (arg)
- "Toggle whether or not the selected frame should auto-lower.
-With arg, turn auto-lower mode on if and only if arg is positive.
-Note that this controls Emacs's own auto-lower feature.
-Some window managers allow you to enable auto-lower for certain windows.
-You can use that for Emacs windows if you wish, but if you do,
-that is beyond the control of Emacs and this command has no effect on it."
- (interactive "P")
- (if (null arg)
- (setq arg
- (if (cdr (assq 'auto-lower (frame-parameters (selected-frame))))
- -1 1)))
- (modify-frame-parameters (selected-frame)
- (list (cons 'auto-lower (> arg 0)))))
-
-(defvar scroll-bar-side 'left
- "*Specify which side scroll bars should be on. Value is `left' or `right'.")
-
-(defun toggle-scroll-bar (arg)
- "Toggle whether or not the selected frame has vertical scroll bars.
-With arg, turn vertical scroll bars on if and only if arg is positive."
- (interactive "P")
- (if (null arg)
- (setq arg
- (if (cdr (assq 'vertical-scroll-bars
- (frame-parameters (selected-frame))))
- -1 1)))
- (modify-frame-parameters (selected-frame)
- (list (cons 'vertical-scroll-bars
- (if (> arg 0)
- scroll-bar-side)))))
-
-(defun toggle-horizontal-scroll-bar (arg)
- "Toggle whether or not the selected frame has horizontal scroll bars.
-With arg, turn horizontal scroll bars on if and only if arg is positive.
-Horizontal scroll bars aren't implemented yet."
- (interactive "P")
- (error "Horizontal scroll bars aren't implemented yet"))
-
-
-;;;; Aliases for backward compatibility with Emacs 18.
-(defalias 'screen-height 'frame-height)
-(defalias 'screen-width 'frame-width)
-
-(defun set-screen-width (cols &optional pretend)
- "Obsolete function to change the size of the screen to 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 frame should not be changed.\n\
-This function is provided only for compatibility with Emacs 18; new code\n\
-should use `set-frame-width instead'."
- (set-frame-width (selected-frame) cols pretend))
-
-(defun set-screen-height (lines &optional pretend)
- "Obsolete function to change the height of the screen to 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\
-This function is provided only for compatibility with Emacs 18; new code\n\
-should use `set-frame-width' instead."
- (set-frame-height (selected-frame) lines pretend))
-
-(make-obsolete 'screen-height 'frame-height)
-(make-obsolete 'screen-width 'frame-width)
-(make-obsolete 'set-screen-width 'set-frame-width)
-(make-obsolete 'set-screen-height 'set-frame-height)
-
-
-;;;; Key bindings
-
-(define-key ctl-x-5-map "2" 'make-frame-command)
-(define-key ctl-x-5-map "0" 'delete-frame)
-(define-key ctl-x-5-map "o" 'other-frame)
-
-(provide 'frame)
-
-;;; frame.el ends here
diff --git a/lisp/gnus-cache.el b/lisp/gnus-cache.el
deleted file mode 100644
index cb770a8c619..00000000000
--- a/lisp/gnus-cache.el
+++ /dev/null
@@ -1,623 +0,0 @@
-;;; gnus-cache.el --- cache interface for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'gnus)
-(eval-when-compile (require 'cl))
-
-(defvar gnus-cache-directory
- (nnheader-concat gnus-directory "cache/")
- "*The directory where cached articles will be stored.")
-
-(defvar gnus-cache-active-file
- (concat (file-name-as-directory gnus-cache-directory) "active")
- "*The cache active file.")
-
-(defvar gnus-cache-enter-articles '(ticked dormant)
- "*Classes of articles to enter into the cache.")
-
-(defvar gnus-cache-remove-articles '(read)
- "*Classes of articles to remove from the cache.")
-
-(defvar gnus-uncacheable-groups nil
- "*Groups that match this regexp will not be cached.
-
-If you want to avoid caching your nnml groups, you could set this
-variable to \"^nnml\".")
-
-
-
-;;; Internal variables.
-
-(defvar gnus-cache-buffer nil)
-(defvar gnus-cache-active-hashtb nil)
-(defvar gnus-cache-active-altered nil)
-
-(eval-and-compile
- (autoload 'nnml-generate-nov-databases-1 "nnml")
- (autoload 'nnvirtual-find-group-art "nnvirtual"))
-
-
-
-;;; Functions called from Gnus.
-
-(defun gnus-cache-open ()
- "Initialize the cache."
- (when (or (file-exists-p gnus-cache-directory)
- (and gnus-use-cache
- (not (eq gnus-use-cache 'passive))))
- (gnus-cache-read-active)))
-
-(condition-case ()
- (gnus-add-shutdown 'gnus-cache-close 'gnus)
- ;; Complexities of byte-compiling makes this kludge necessary. Eeek.
- (error nil))
-
-(defun gnus-cache-close ()
- "Shut down the cache."
- (gnus-cache-write-active)
- (gnus-cache-save-buffers)
- (setq gnus-cache-active-hashtb nil))
-
-(defun gnus-cache-save-buffers ()
- ;; save the overview buffer if it exists and has been modified
- ;; delete empty cache subdirectories
- (if (null gnus-cache-buffer)
- ()
- (let ((buffer (cdr gnus-cache-buffer))
- (overview-file (gnus-cache-file-name
- (car gnus-cache-buffer) ".overview")))
- ;; write the overview only if it was modified
- (if (buffer-modified-p buffer)
- (save-excursion
- (set-buffer buffer)
- (if (> (buffer-size) 0)
- ;; non-empty overview, write it out
- (progn
- (gnus-make-directory (file-name-directory overview-file))
- (write-region (point-min) (point-max)
- overview-file nil 'quietly))
- ;; empty overview file, remove it
- (and (file-exists-p overview-file)
- (delete-file overview-file))
- ;; if possible, remove group's cache subdirectory
- (condition-case nil
- ;; FIXME: we can detect the error type and warn the user
- ;; of any inconsistencies (articles w/o nov entries?).
- ;; for now, just be conservative...delete only if safe -- sj
- (delete-directory (file-name-directory overview-file))
- (error nil)))))
- ;; kill the buffer, it's either unmodified or saved
- (gnus-kill-buffer buffer)
- (setq gnus-cache-buffer nil))))
-
-(defun gnus-cache-possibly-enter-article
- (group article headers ticked dormant unread &optional force)
- (when (and (or force (not (eq gnus-use-cache 'passive)))
- (numberp article)
- (> article 0)
- (vectorp headers)) ; This might be a dummy article.
- ;; If this is a virtual group, we find the real group.
- (when (gnus-virtual-group-p group)
- (let ((result (nnvirtual-find-group-art
- (gnus-group-real-name group) article)))
- (setq group (car result)
- headers (copy-sequence headers))
- (mail-header-set-number headers (cdr result))))
- (let ((number (mail-header-number headers))
- file dir)
- (when (and (> number 0) ; Reffed article.
- (or (not gnus-uncacheable-groups)
- (not (string-match gnus-uncacheable-groups group)))
- (or force
- (gnus-cache-member-of-class
- gnus-cache-enter-articles ticked dormant unread))
- (not (file-exists-p (setq file (gnus-cache-file-name
- group number)))))
- ;; Possibly create the cache directory.
- (or (file-exists-p (setq dir (file-name-directory file)))
- (gnus-make-directory dir))
- ;; Save the article in the cache.
- (if (file-exists-p file)
- t ; The article already is saved.
- (save-excursion
- (set-buffer nntp-server-buffer)
- (let ((gnus-use-cache nil))
- (gnus-request-article-this-buffer number group))
- (when (> (buffer-size) 0)
- (write-region (point-min) (point-max) file nil 'quiet)
- (gnus-cache-change-buffer group)
- (set-buffer (cdr gnus-cache-buffer))
- (goto-char (point-max))
- (forward-line -1)
- (while (condition-case ()
- (and (not (bobp))
- (> (read (current-buffer)) number))
- (error
- ;; The line was malformed, so we just remove it!!
- (gnus-delete-line)
- t))
- (forward-line -1))
- (if (bobp)
- (if (not (eobp))
- (progn
- (beginning-of-line)
- (if (< (read (current-buffer)) number)
- (forward-line 1)))
- (beginning-of-line))
- (forward-line 1))
- (beginning-of-line)
- ;; [number subject from date id references chars lines xref]
- (insert (format "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n"
- (mail-header-number headers)
- (mail-header-subject headers)
- (mail-header-from headers)
- (mail-header-date headers)
- (mail-header-id headers)
- (or (mail-header-references headers) "")
- (or (mail-header-chars headers) "")
- (or (mail-header-lines headers) "")
- (or (mail-header-xref headers) "")))
- ;; Update the active info.
- (set-buffer gnus-summary-buffer)
- (gnus-cache-update-active group number)
- (push article gnus-newsgroup-cached)
- (gnus-summary-update-secondary-mark article))
- t))))))
-
-(defun gnus-cache-enter-remove-article (article)
- "Mark ARTICLE for later possible removal."
- (when article
- (push article gnus-cache-removable-articles)))
-
-(defun gnus-cache-possibly-remove-articles ()
- "Possibly remove some of the removable articles."
- (if (not (gnus-virtual-group-p gnus-newsgroup-name))
- (gnus-cache-possibly-remove-articles-1)
- (let ((arts gnus-cache-removable-articles)
- ga)
- (while arts
- (when (setq ga (nnvirtual-find-group-art
- (gnus-group-real-name gnus-newsgroup-name) (pop arts)))
- (let ((gnus-cache-removable-articles (list (cdr ga)))
- (gnus-newsgroup-name (car ga)))
- (gnus-cache-possibly-remove-articles-1)))))
- (setq gnus-cache-removable-articles nil)))
-
-(defun gnus-cache-possibly-remove-articles-1 ()
- "Possibly remove some of the removable articles."
- (unless (eq gnus-use-cache 'passive)
- (let ((articles gnus-cache-removable-articles)
- (cache-articles gnus-newsgroup-cached)
- article)
- (gnus-cache-change-buffer gnus-newsgroup-name)
- (while articles
- (if (memq (setq article (pop articles)) cache-articles)
- ;; The article was in the cache, so we see whether we are
- ;; supposed to remove it from the cache.
- (gnus-cache-possibly-remove-article
- article (memq article gnus-newsgroup-marked)
- (memq article gnus-newsgroup-dormant)
- (or (memq article gnus-newsgroup-unreads)
- (memq article gnus-newsgroup-unselected))))))
- ;; The overview file might have been modified, save it
- ;; safe because we're only called at group exit anyway.
- (gnus-cache-save-buffers)))
-
-(defun gnus-cache-request-article (article group)
- "Retrieve ARTICLE in GROUP from the cache."
- (let ((file (gnus-cache-file-name group article))
- (buffer-read-only nil))
- (when (file-exists-p file)
- (erase-buffer)
- (gnus-kill-all-overlays)
- (insert-file-contents file)
- t)))
-
-(defun gnus-cache-possibly-alter-active (group active)
- "Alter the ACTIVE info for GROUP to reflect the articles in the cache."
- (when gnus-cache-active-hashtb
- (let ((cache-active (gnus-gethash group gnus-cache-active-hashtb)))
- (and cache-active
- (< (car cache-active) (car active))
- (setcar active (car cache-active)))
- (and cache-active
- (> (cdr cache-active) (cdr active))
- (setcdr active (cdr cache-active))))))
-
-(defun gnus-cache-retrieve-headers (articles group &optional fetch-old)
- "Retrieve the headers for ARTICLES in GROUP."
- (let ((cached
- (setq gnus-newsgroup-cached (gnus-cache-articles-in-group group))))
- (if (not cached)
- ;; No cached articles here, so we just retrieve them
- ;; the normal way.
- (let ((gnus-use-cache nil))
- (gnus-retrieve-headers articles group fetch-old))
- (let ((uncached-articles (gnus-sorted-intersection
- (gnus-sorted-complement articles cached)
- articles))
- (cache-file (gnus-cache-file-name group ".overview"))
- type)
- ;; We first retrieve all the headers that we don't have in
- ;; the cache.
- (let ((gnus-use-cache nil))
- (when uncached-articles
- (setq type (and articles
- (gnus-retrieve-headers
- uncached-articles group fetch-old)))))
- (gnus-cache-save-buffers)
- ;; Then we insert the cached headers.
- (save-excursion
- (cond
- ((not (file-exists-p cache-file))
- ;; There are no cached headers.
- type)
- ((null type)
- ;; There were no uncached headers (or retrieval was
- ;; unsuccessful), so we use the cached headers exclusively.
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (insert-file-contents cache-file)
- 'nov)
- ((eq type 'nov)
- ;; We have both cached and uncached NOV headers, so we
- ;; braid them.
- (gnus-cache-braid-nov group cached)
- type)
- (t
- ;; We braid HEADs.
- (gnus-cache-braid-heads group (gnus-sorted-intersection
- cached articles))
- type)))))))
-
-(defun gnus-cache-enter-article (&optional n)
- "Enter the next N articles into the cache.
-If not given a prefix, use the process marked articles instead.
-Returns the list of articles entered."
- (interactive "P")
- (gnus-set-global-variables)
- (let ((articles (gnus-summary-work-articles n))
- article out)
- (while articles
- (setq article (pop articles))
- (when (gnus-cache-possibly-enter-article
- gnus-newsgroup-name article (gnus-summary-article-header article)
- nil nil nil t)
- (push article out))
- (gnus-summary-remove-process-mark article)
- (gnus-summary-update-secondary-mark article))
- (gnus-summary-next-subject 1)
- (gnus-summary-position-point)
- (nreverse out)))
-
-(defun gnus-cache-remove-article (n)
- "Remove the next N articles from the cache.
-If not given a prefix, use the process marked articles instead.
-Returns the list of articles removed."
- (interactive "P")
- (gnus-set-global-variables)
- (gnus-cache-change-buffer gnus-newsgroup-name)
- (let ((articles (gnus-summary-work-articles n))
- article out)
- (while articles
- (setq article (pop articles))
- (when (gnus-cache-possibly-remove-article article nil nil nil t)
- (push article out))
- (gnus-summary-remove-process-mark article)
- (gnus-summary-update-secondary-mark article))
- (gnus-summary-next-subject 1)
- (gnus-summary-position-point)
- (nreverse out)))
-
-(defun gnus-cached-article-p (article)
- "Say whether ARTICLE is cached in the current group."
- (memq article gnus-newsgroup-cached))
-
-;;; Internal functions.
-
-(defun gnus-cache-change-buffer (group)
- (and gnus-cache-buffer
- ;; See if the current group's overview cache has been loaded.
- (or (string= group (car gnus-cache-buffer))
- ;; Another overview cache is current, save it.
- (gnus-cache-save-buffers)))
- ;; if gnus-cache buffer is nil, create it
- (or gnus-cache-buffer
- ;; Create cache buffer
- (save-excursion
- (setq gnus-cache-buffer
- (cons group
- (set-buffer (get-buffer-create " *gnus-cache-overview*"))))
- (buffer-disable-undo (current-buffer))
- ;; Insert the contents of this group's cache overview.
- (erase-buffer)
- (let ((file (gnus-cache-file-name group ".overview")))
- (and (file-exists-p file)
- (insert-file-contents file)))
- ;; We have a fresh (empty/just loaded) buffer,
- ;; mark it as unmodified to save a redundant write later.
- (set-buffer-modified-p nil))))
-
-;; Return whether an article is a member of a class.
-(defun gnus-cache-member-of-class (class ticked dormant unread)
- (or (and ticked (memq 'ticked class))
- (and dormant (memq 'dormant class))
- (and unread (memq 'unread class))
- (and (not unread) (not ticked) (not dormant) (memq 'read class))))
-
-(defun gnus-cache-file-name (group article)
- (concat (file-name-as-directory gnus-cache-directory)
- (file-name-as-directory
- (if (gnus-use-long-file-name 'not-cache)
- group
- (let ((group (concat group "")))
- (if (string-match ":" group)
- (aset group (match-beginning 0) ?/))
- (nnheader-replace-chars-in-string group ?. ?/))))
- (if (stringp article) article (int-to-string article))))
-
-(defun gnus-cache-update-article (group article)
- "If ARTICLE is in the cache, remove it and re-enter it."
- (when (gnus-cache-possibly-remove-article article nil nil nil t)
- (let ((gnus-use-cache nil))
- (gnus-cache-possibly-enter-article
- gnus-newsgroup-name article (gnus-summary-article-header article)
- nil nil nil t))))
-
-(defun gnus-cache-possibly-remove-article (article ticked dormant unread
- &optional force)
- "Possibly remove ARTICLE from the cache."
- (let ((group gnus-newsgroup-name)
- (number article)
- file)
- ;; If this is a virtual group, we find the real group.
- (when (gnus-virtual-group-p group)
- (let ((result (nnvirtual-find-group-art
- (gnus-group-real-name group) article)))
- (setq group (car result)
- number (cdr result))))
- (setq file (gnus-cache-file-name group number))
- (when (and (file-exists-p file)
- (or force
- (gnus-cache-member-of-class
- gnus-cache-remove-articles ticked dormant unread)))
- (save-excursion
- (delete-file file)
- (set-buffer (cdr gnus-cache-buffer))
- (goto-char (point-min))
- (if (or (looking-at (concat (int-to-string number) "\t"))
- (search-forward (concat "\n" (int-to-string number) "\t")
- (point-max) t))
- (delete-region (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point)))))
- (setq gnus-newsgroup-cached
- (delq article gnus-newsgroup-cached))
- (gnus-summary-update-secondary-mark article)
- t)))
-
-(defun gnus-cache-articles-in-group (group)
- "Return a sorted list of cached articles in GROUP."
- (let ((dir (file-name-directory (gnus-cache-file-name group 1)))
- articles)
- (when (file-exists-p dir)
- (sort (mapcar (lambda (name) (string-to-int name))
- (directory-files dir nil "^[0-9]+$" t))
- '<))))
-
-(defun gnus-cache-braid-nov (group cached)
- (let ((cache-buf (get-buffer-create " *gnus-cache*"))
- beg end)
- (gnus-cache-save-buffers)
- (save-excursion
- (set-buffer cache-buf)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert-file-contents (gnus-cache-file-name group ".overview"))
- (goto-char (point-min))
- (insert "\n")
- (goto-char (point-min)))
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (while cached
- (while (and (not (eobp))
- (< (read (current-buffer)) (car cached)))
- (forward-line 1))
- (beginning-of-line)
- (save-excursion
- (set-buffer cache-buf)
- (if (search-forward (concat "\n" (int-to-string (car cached)) "\t")
- nil t)
- (setq beg (progn (beginning-of-line) (point))
- end (progn (end-of-line) (point)))
- (setq beg nil)))
- (if beg (progn (insert-buffer-substring cache-buf beg end)
- (insert "\n")))
- (setq cached (cdr cached)))
- (kill-buffer cache-buf)))
-
-(defun gnus-cache-braid-heads (group cached)
- (let ((cache-buf (get-buffer-create " *gnus-cache*")))
- (save-excursion
- (set-buffer cache-buf)
- (buffer-disable-undo (current-buffer))
- (erase-buffer))
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (while cached
- (while (and (not (eobp))
- (looking-at "2.. +\\([0-9]+\\) ")
- (< (progn (goto-char (match-beginning 1))
- (read (current-buffer)))
- (car cached)))
- (search-forward "\n.\n" nil 'move))
- (beginning-of-line)
- (save-excursion
- (set-buffer cache-buf)
- (erase-buffer)
- (insert-file-contents (gnus-cache-file-name group (car cached)))
- (goto-char (point-min))
- (insert "220 ")
- (princ (car cached) (current-buffer))
- (insert " Article retrieved.\n")
- (search-forward "\n\n" nil 'move)
- (delete-region (point) (point-max))
- (forward-char -1)
- (insert "."))
- (insert-buffer-substring cache-buf)
- (setq cached (cdr cached)))
- (kill-buffer cache-buf)))
-
-;;;###autoload
-(defun gnus-jog-cache ()
- "Go through all groups and put the articles into the cache."
- (interactive)
- (let ((gnus-mark-article-hook nil)
- (gnus-expert-user t)
- (nnmail-spool-file nil)
- (gnus-use-dribble-file nil)
- (gnus-novice-user nil)
- (gnus-large-newsgroup nil))
- ;; Start Gnus.
- (gnus)
- ;; Go through all groups...
- (gnus-group-mark-buffer)
- (gnus-group-universal-argument
- nil nil
- (lambda ()
- (gnus-summary-read-group nil nil t)
- ;; ... and enter the articles into the cache.
- (when (eq major-mode 'gnus-summary-mode)
- (gnus-uu-mark-buffer)
- (gnus-cache-enter-article)
- (kill-buffer (current-buffer)))))))
-
-(defun gnus-cache-read-active (&optional force)
- "Read the cache active file."
- (unless (file-exists-p gnus-cache-directory)
- (make-directory gnus-cache-directory t))
- (if (not (and (file-exists-p gnus-cache-active-file)
- (or force (not gnus-cache-active-hashtb))))
- ;; There is no active file, so we generate one.
- (gnus-cache-generate-active)
- ;; We simply read the active file.
- (save-excursion
- (gnus-set-work-buffer)
- (insert-file-contents gnus-cache-active-file)
- (gnus-active-to-gnus-format
- nil (setq gnus-cache-active-hashtb
- (gnus-make-hashtable
- (count-lines (point-min) (point-max)))))
- (setq gnus-cache-active-altered nil))))
-
-(defun gnus-cache-write-active (&optional force)
- "Write the active hashtb to the active file."
- (when (or force
- (and gnus-cache-active-hashtb
- gnus-cache-active-altered))
- (save-excursion
- (gnus-set-work-buffer)
- (mapatoms
- (lambda (sym)
- (when (and sym (boundp sym))
- (insert (format "%s %d %d y\n"
- (symbol-name sym) (cdr (symbol-value sym))
- (car (symbol-value sym))))))
- gnus-cache-active-hashtb)
- (gnus-make-directory (file-name-directory gnus-cache-active-file))
- (write-region
- (point-min) (point-max) gnus-cache-active-file nil 'silent))
- ;; Mark the active hashtb as unaltered.
- (setq gnus-cache-active-altered nil)))
-
-(defun gnus-cache-update-active (group number &optional low)
- "Update the upper bound of the active info of GROUP to NUMBER.
-If LOW, update the lower bound instead."
- (let ((active (gnus-gethash group gnus-cache-active-hashtb)))
- (if (null active)
- ;; We just create a new active entry for this group.
- (gnus-sethash group (cons number number) gnus-cache-active-hashtb)
- ;; Update the lower or upper bound.
- (if low
- (setcar active number)
- (setcdr active number))
- ;; Mark the active hashtb as altered.
- (setq gnus-cache-active-altered t))))
-
-;;;###autoload
-(defun gnus-cache-generate-active (&optional directory)
- "Generate the cache active file."
- (interactive)
- (let* ((top (null directory))
- (directory (expand-file-name (or directory gnus-cache-directory)))
- (files (directory-files directory 'full))
- (group
- (if top
- ""
- (string-match
- (concat "^" (file-name-as-directory
- (expand-file-name gnus-cache-directory)))
- (directory-file-name directory))
- (nnheader-replace-chars-in-string
- (substring (directory-file-name directory) (match-end 0))
- ?/ ?.)))
- nums alphs)
- (when top
- (gnus-message 5 "Generating the cache active file...")
- (setq gnus-cache-active-hashtb (gnus-make-hashtable 123)))
- ;; Separate articles from all other files and directories.
- (while files
- (if (string-match "^[0-9]+$" (file-name-nondirectory (car files)))
- (push (string-to-int (file-name-nondirectory (pop files))) nums)
- (push (pop files) alphs)))
- ;; If we have nums, then this is probably a valid group.
- (when (setq nums (sort nums '<))
- (gnus-sethash group (cons (car nums) (gnus-last-element nums))
- gnus-cache-active-hashtb))
- ;; Go through all the other files.
- (while alphs
- (when (and (file-directory-p (car alphs))
- (not (string-match "^\\.\\.?$"
- (file-name-nondirectory (car alphs)))))
- ;; We descend directories.
- (gnus-cache-generate-active (car alphs)))
- (setq alphs (cdr alphs)))
- ;; Write the new active file.
- (when top
- (gnus-cache-write-active t)
- (gnus-message 5 "Generating the cache active file...done"))))
-
-;;;###autoload
-(defun gnus-cache-generate-nov-databases (dir)
- "Generate NOV files recursively starting in DIR."
- (interactive (list gnus-cache-directory))
- (gnus-cache-close)
- (let ((nnml-generate-active-function 'identity))
- (nnml-generate-nov-databases-1 dir)))
-
-(provide 'gnus-cache)
-
-;;; gnus-cache.el ends here
diff --git a/lisp/gnus-cite.el b/lisp/gnus-cite.el
deleted file mode 100644
index bc85ea42be0..00000000000
--- a/lisp/gnus-cite.el
+++ /dev/null
@@ -1,732 +0,0 @@
-;;; gnus-cite.el --- parse citations in articles for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Per Abrahamsen <abraham@iesd.auc.dk>
-;; Keywords: news, mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'gnus)
-(require 'gnus-msg)
-(require 'gnus-ems)
-(eval-when-compile (require 'cl))
-
-(eval-and-compile
- (autoload 'gnus-article-add-button "gnus-vis"))
-
-;;; Customization:
-
-(defvar gnus-cited-text-button-line-format "%(%{[...]%}%)\n"
- "Format of cited text buttons.")
-
-(defvar gnus-cited-lines-visible nil
- "The number of lines of hidden cited text to remain visible.")
-
-(defvar gnus-cite-parse-max-size 25000
- "Maximum article size (in bytes) where parsing citations is allowed.
-Set it to nil to parse all articles.")
-
-(defvar gnus-cite-prefix-regexp
- "^[]>|:}+ ]*[]>|:}+]\\(.*>\\)?\\|^.*>"
- "Regexp matching the longest possible citation prefix on a line.")
-
-(defvar gnus-cite-max-prefix 20
- "Maximum possible length for a citation prefix.")
-
-(defvar gnus-supercite-regexp
- (concat "^\\(" gnus-cite-prefix-regexp "\\)? *"
- ">>>>> +\"\\([^\"\n]+\\)\" +==")
- "Regexp matching normal Supercite attribution lines.
-The first grouping must match prefixes added by other packages.")
-
-(defvar gnus-supercite-secondary-regexp "^.*\"\\([^\"\n]+\\)\" +=="
- "Regexp matching mangled Supercite attribution lines.
-The first regexp group should match the Supercite attribution.")
-
-(defvar gnus-cite-minimum-match-count 2
- "Minimum number of identical prefixes before we believe it's a citation.")
-
-;see gnus-cus.el
-;(defvar gnus-cite-face-list
-; (if (eq gnus-display-type 'color)
-; (if (eq gnus-background-mode 'dark) 'light 'dark)
-; '(italic))
-; "Faces used for displaying different citations.
-;It is either a list of face names, or one of the following special
-;values:
-
-;dark: Create faces from `gnus-face-dark-name-list'.
-;light: Create faces from `gnus-face-light-name-list'.
-
-;The variable `gnus-make-foreground' determines whether the created
-;faces change the foreground or the background colors.")
-
-(defvar gnus-cite-attribution-prefix "in article\\|in <"
- "Regexp matching the beginning of an attribution line.")
-
-(defvar gnus-cite-attribution-suffix
- "\\(wrote\\|writes\\|said\\|says\\):[ \t]*$"
- "Regexp matching the end of an attribution line.
-The text matching the first grouping will be used as a button.")
-
-;see gnus-cus.el
-;(defvar gnus-cite-attribution-face 'underline
-; "Face used for attribution lines.
-;It is merged with the face for the cited text belonging to the attribution.")
-
-;see gnus-cus.el
-;(defvar gnus-cite-hide-percentage 50
-; "Only hide cited text if it is larger than this percent of the body.")
-
-;see gnus-cus.el
-;(defvar gnus-cite-hide-absolute 10
-; "Only hide cited text if there is at least this number of cited lines.")
-
-;see gnus-cus.el
-;(defvar gnus-face-light-name-list
-; '("light blue" "light cyan" "light yellow" "light pink"
-; "pale green" "beige" "orange" "magenta" "violet" "medium purple"
-; "turquoise")
-; "Names of light colors.")
-
-;see gnus-cus.el
-;(defvar gnus-face-dark-name-list
-; '("dark salmon" "firebrick"
-; "dark green" "dark orange" "dark khaki" "dark violet"
-; "dark turquoise")
-; "Names of dark colors.")
-
-;;; Internal Variables:
-
-(defvar gnus-cite-article nil)
-
-(defvar gnus-cite-prefix-alist nil)
-;; Alist of citation prefixes.
-;; The cdr is a list of lines with that prefix.
-
-(defvar gnus-cite-attribution-alist nil)
-;; Alist of attribution lines.
-;; The car is a line number.
-;; The cdr is the prefix for the citation started by that line.
-
-(defvar gnus-cite-loose-prefix-alist nil)
-;; Alist of citation prefixes that have no matching attribution.
-;; The cdr is a list of lines with that prefix.
-
-(defvar gnus-cite-loose-attribution-alist nil)
-;; Alist of attribution lines that have no matching citation.
-;; Each member has the form (WROTE IN PREFIX TAG), where
-;; WROTE: is the attribution line number
-;; IN: is the line number of the previous line if part of the same attribution,
-;; PREFIX: Is the citation prefix of the attribution line(s), and
-;; TAG: Is a Supercite tag, if any.
-
-(defvar gnus-cited-text-button-line-format-alist
- `((?b beg ?d)
- (?e end ?d)
- (?l (- end beg) ?d)))
-(defvar gnus-cited-text-button-line-format-spec nil)
-
-;;; Commands:
-
-(defun gnus-article-highlight-citation (&optional force)
- "Highlight cited text.
-Each citation in the article will be highlighted with a different face.
-The faces are taken from `gnus-cite-face-list'.
-Attribution lines are highlighted with the same face as the
-corresponding citation merged with `gnus-cite-attribution-face'.
-
-Text is considered cited if at least `gnus-cite-minimum-match-count'
-lines matches `gnus-cite-prefix-regexp' with the same prefix.
-
-Lines matching `gnus-cite-attribution-suffix' and perhaps
-`gnus-cite-attribution-prefix' are considered attribution lines."
- (interactive (list 'force))
- ;; Create dark or light faces if necessary.
- (cond ((eq gnus-cite-face-list 'light)
- (setq gnus-cite-face-list
- (mapcar 'gnus-make-face gnus-face-light-name-list)))
- ((eq gnus-cite-face-list 'dark)
- (setq gnus-cite-face-list
- (mapcar 'gnus-make-face gnus-face-dark-name-list))))
- (save-excursion
- (set-buffer gnus-article-buffer)
- (gnus-cite-parse-maybe force)
- (let ((buffer-read-only nil)
- (alist gnus-cite-prefix-alist)
- (faces gnus-cite-face-list)
- (inhibit-point-motion-hooks t)
- face entry prefix skip numbers number face-alist)
- ;; Loop through citation prefixes.
- (while alist
- (setq entry (car alist)
- alist (cdr alist)
- prefix (car entry)
- numbers (cdr entry)
- face (car faces)
- faces (or (cdr faces) gnus-cite-face-list)
- face-alist (cons (cons prefix face) face-alist))
- (while numbers
- (setq number (car numbers)
- numbers (cdr numbers))
- (and (not (assq number gnus-cite-attribution-alist))
- (not (assq number gnus-cite-loose-attribution-alist))
- (gnus-cite-add-face number prefix face))))
- ;; Loop through attribution lines.
- (setq alist gnus-cite-attribution-alist)
- (while alist
- (setq entry (car alist)
- alist (cdr alist)
- number (car entry)
- prefix (cdr entry)
- skip (gnus-cite-find-prefix number)
- face (cdr (assoc prefix face-alist)))
- ;; Add attribution button.
- (goto-line number)
- (if (re-search-forward gnus-cite-attribution-suffix
- (save-excursion (end-of-line 1) (point))
- t)
- (gnus-article-add-button (match-beginning 1) (match-end 1)
- 'gnus-cite-toggle prefix))
- ;; Highlight attribution line.
- (gnus-cite-add-face number skip face)
- (gnus-cite-add-face number skip gnus-cite-attribution-face))
- ;; Loop through attribution lines.
- (setq alist gnus-cite-loose-attribution-alist)
- (while alist
- (setq entry (car alist)
- alist (cdr alist)
- number (car entry)
- skip (gnus-cite-find-prefix number))
- (gnus-cite-add-face number skip gnus-cite-attribution-face)))))
-
-(defun gnus-dissect-cited-text ()
- "Dissect the article buffer looking for cited text."
- (save-excursion
- (set-buffer gnus-article-buffer)
- (gnus-cite-parse-maybe)
- (let ((alist gnus-cite-prefix-alist)
- prefix numbers number marks m)
- ;; Loop through citation prefixes.
- (while alist
- (setq numbers (pop alist)
- prefix (pop numbers))
- (while numbers
- (setq number (pop numbers))
- (goto-char (point-min))
- (forward-line number)
- (push (cons (point-marker) "") marks)
- (while (and numbers
- (= (1- number) (car numbers)))
- (setq number (pop numbers)))
- (goto-char (point-min))
- (forward-line (1- number))
- (push (cons (point-marker) prefix) marks)))
- (goto-char (point-min))
- (search-forward "\n\n" nil t)
- (push (cons (point-marker) "") marks)
- (goto-char (point-max))
- (re-search-backward gnus-signature-separator nil t)
- (push (cons (point-marker) "") marks)
- (setq marks (sort marks (lambda (m1 m2) (< (car m1) (car m2)))))
- (let* ((omarks marks))
- (setq marks nil)
- (while (cdr omarks)
- (if (= (caar omarks) (caadr omarks))
- (progn
- (unless (equal (cdar omarks) "")
- (push (car omarks) marks))
- (unless (equal (cdadr omarks) "")
- (push (cadr omarks) marks))
- (setq omarks (cdr omarks)))
- (push (car omarks) marks))
- (setq omarks (cdr omarks)))
- (when (car omarks)
- (push (car omarks) marks))
- (setq marks (setq m (nreverse marks)))
- (while (cddr m)
- (if (and (equal (cdadr m) "")
- (equal (cdar m) (cdaddr m))
- (goto-char (caadr m))
- (forward-line 1)
- (= (point) (caaddr m)))
- (setcdr m (cdddr m))
- (setq m (cdr m))))
- marks))))
-
-
-(defun gnus-article-fill-cited-article (&optional force)
- "Do word wrapping in the current article."
- (interactive (list t))
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil)
- (inhibit-point-motion-hooks t)
- (marks (gnus-dissect-cited-text))
- (adaptive-fill-mode nil))
- (save-restriction
- (while (cdr marks)
- (widen)
- (narrow-to-region (caar marks) (caadr marks))
- (let ((adaptive-fill-regexp
- (concat "^" (regexp-quote (cdar marks)) " *"))
- (fill-prefix (cdar marks)))
- (fill-region (point-min) (point-max)))
- (set-marker (caar marks) nil)
- (setq marks (cdr marks)))
- (when marks
- (set-marker (caar marks) nil))))))
-
-(defun gnus-article-hide-citation (&optional arg force)
- "Toggle hiding of all cited text except attribution lines.
-See the documentation for `gnus-article-highlight-citation'.
-If given a negative prefix, always show; if given a positive prefix,
-always hide."
- (interactive (append (gnus-hidden-arg) (list 'force)))
- (setq gnus-cited-text-button-line-format-spec
- (gnus-parse-format gnus-cited-text-button-line-format
- gnus-cited-text-button-line-format-alist t))
- (unless (gnus-article-check-hidden-text 'cite arg)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil)
- (marks (gnus-dissect-cited-text))
- (inhibit-point-motion-hooks t)
- (props (nconc (list 'gnus-type 'cite)
- gnus-hidden-properties))
- beg end)
- (while marks
- (setq beg nil
- end nil)
- (while (and marks (string= (cdar marks) ""))
- (setq marks (cdr marks)))
- (when marks
- (setq beg (caar marks)))
- (while (and marks (not (string= (cdar marks) "")))
- (setq marks (cdr marks)))
- (when marks
- (setq end (caar marks)))
- ;; Skip past lines we want to leave visible.
- (when (and beg end gnus-cited-lines-visible)
- (goto-char beg)
- (forward-line gnus-cited-lines-visible)
- (if (>= (point) end)
- (setq beg nil)
- (setq beg (point-marker))))
- (when (and beg end)
- (gnus-add-text-properties beg end props)
- (goto-char beg)
- (unless (save-excursion (search-backward "\n\n" nil t))
- (insert "\n"))
- (gnus-article-add-button
- (point)
- (progn (eval gnus-cited-text-button-line-format-spec) (point))
- `gnus-article-toggle-cited-text (cons beg end))
- (set-marker beg (point))))))))
-
-(defun gnus-article-toggle-cited-text (region)
- "Toggle hiding the text in REGION."
- (let (buffer-read-only)
- (funcall
- (if (text-property-any
- (car region) (1- (cdr region))
- (car gnus-hidden-properties) (cadr gnus-hidden-properties))
- 'remove-text-properties 'gnus-add-text-properties)
- (car region) (cdr region) gnus-hidden-properties)))
-
-(defun gnus-article-hide-citation-maybe (&optional arg force)
- "Toggle hiding of cited text that has an attribution line.
-If given a negative prefix, always show; if given a positive prefix,
-always hide.
-This will do nothing unless at least `gnus-cite-hide-percentage'
-percent and at least `gnus-cite-hide-absolute' lines of the body is
-cited text with attributions. When called interactively, these two
-variables are ignored.
-See also the documentation for `gnus-article-highlight-citation'."
- (interactive (append (gnus-hidden-arg) (list 'force)))
- (unless (gnus-article-check-hidden-text 'cite arg)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (gnus-cite-parse-maybe force)
- (goto-char (point-min))
- (search-forward "\n\n" nil t)
- (let ((start (point))
- (atts gnus-cite-attribution-alist)
- (buffer-read-only nil)
- (inhibit-point-motion-hooks t)
- (hiden 0)
- total)
- (goto-char (point-max))
- (re-search-backward gnus-signature-separator nil t)
- (setq total (count-lines start (point)))
- (while atts
- (setq hiden (+ hiden (length (cdr (assoc (cdar atts)
- gnus-cite-prefix-alist))))
- atts (cdr atts)))
- (if (or force
- (and (> (* 100 hiden) (* gnus-cite-hide-percentage total))
- (> hiden gnus-cite-hide-absolute)))
- (progn
- (setq atts gnus-cite-attribution-alist)
- (while atts
- (setq total (cdr (assoc (cdar atts) gnus-cite-prefix-alist))
- atts (cdr atts))
- (while total
- (setq hiden (car total)
- total (cdr total))
- (goto-line hiden)
- (or (assq hiden gnus-cite-attribution-alist)
- (gnus-add-text-properties
- (point) (progn (forward-line 1) (point))
- (nconc (list 'gnus-type 'cite)
- gnus-hidden-properties)))))))))))
-
-(defun gnus-article-hide-citation-in-followups ()
- "Hide cited text in non-root articles."
- (interactive)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((article (cdr gnus-article-current)))
- (unless (save-excursion
- (set-buffer gnus-summary-buffer)
- (gnus-article-displayed-root-p article))
- (gnus-article-hide-citation)))))
-
-;;; Internal functions:
-
-(defun gnus-cite-parse-maybe (&optional force)
- ;; Parse if the buffer has changes since last time.
- (if (equal gnus-cite-article gnus-article-current)
- ()
- ;;Reset parser information.
- (setq gnus-cite-prefix-alist nil
- gnus-cite-attribution-alist nil
- gnus-cite-loose-prefix-alist nil
- gnus-cite-loose-attribution-alist nil)
- ;; Parse if not too large.
- (if (and (not force)
- gnus-cite-parse-max-size
- (> (buffer-size) gnus-cite-parse-max-size))
- ()
- (setq gnus-cite-article (cons (car gnus-article-current)
- (cdr gnus-article-current)))
- (gnus-cite-parse))))
-
-(defun gnus-cite-parse ()
- ;; Parse and connect citation prefixes and attribution lines.
-
- ;; Parse current buffer searching for citation prefixes.
- (goto-char (point-min))
- (or (search-forward "\n\n" nil t)
- (goto-char (point-max)))
- (let ((line (1+ (count-lines (point-min) (point))))
- (case-fold-search t)
- (max (save-excursion
- (goto-char (point-max))
- (re-search-backward gnus-signature-separator nil t)
- (point)))
- alist entry start begin end numbers prefix)
- ;; Get all potential prefixes in `alist'.
- (while (< (point) max)
- ;; Each line.
- (setq begin (point)
- end (progn (beginning-of-line 2) (point))
- start end)
- (goto-char begin)
- ;; Ignore standard Supercite attribution prefix.
- (if (looking-at gnus-supercite-regexp)
- (if (match-end 1)
- (setq end (1+ (match-end 1)))
- (setq end (1+ begin))))
- ;; Ignore very long prefixes.
- (if (> end (+ (point) gnus-cite-max-prefix))
- (setq end (+ (point) gnus-cite-max-prefix)))
- (while (re-search-forward gnus-cite-prefix-regexp (1- end) t)
- ;; Each prefix.
- (setq end (match-end 0)
- prefix (buffer-substring begin end))
- (gnus-set-text-properties 0 (length prefix) nil prefix)
- (setq entry (assoc prefix alist))
- (if entry
- (setcdr entry (cons line (cdr entry)))
- (setq alist (cons (list prefix line) alist)))
- (goto-char begin))
- (goto-char start)
- (setq line (1+ line)))
- ;; We got all the potential prefixes. Now create
- ;; `gnus-cite-prefix-alist' containing the oldest prefix for each
- ;; line that appears at least gnus-cite-minimum-match-count
- ;; times. First sort them by length. Longer is older.
- (setq alist (sort alist (lambda (a b)
- (> (length (car a)) (length (car b))))))
- (while alist
- (setq entry (car alist)
- prefix (car entry)
- numbers (cdr entry)
- alist (cdr alist))
- (cond ((null numbers)
- ;; No lines with this prefix that wasn't also part of
- ;; a longer prefix.
- )
- ((< (length numbers) gnus-cite-minimum-match-count)
- ;; Too few lines with this prefix. We keep it a bit
- ;; longer in case it is an exact match for an attribution
- ;; line, but we don't remove the line from other
- ;; prefixes.
- (setq gnus-cite-prefix-alist
- (cons entry gnus-cite-prefix-alist)))
- (t
- (setq gnus-cite-prefix-alist (cons entry
- gnus-cite-prefix-alist))
- ;; Remove articles from other prefixes.
- (let ((loop alist)
- current)
- (while loop
- (setq current (car loop)
- loop (cdr loop))
- (setcdr current
- (gnus-set-difference (cdr current) numbers))))))))
- ;; No citations have been connected to attribution lines yet.
- (setq gnus-cite-loose-prefix-alist (append gnus-cite-prefix-alist nil))
-
- ;; Parse current buffer searching for attribution lines.
- (goto-char (point-min))
- (search-forward "\n\n" nil t)
- (while (re-search-forward gnus-cite-attribution-suffix (point-max) t)
- (let* ((start (match-beginning 0))
- (end (match-end 0))
- (wrote (count-lines (point-min) end))
- (prefix (gnus-cite-find-prefix wrote))
- ;; Check previous line for an attribution leader.
- (tag (progn
- (beginning-of-line 1)
- (and (looking-at gnus-supercite-secondary-regexp)
- (buffer-substring (match-beginning 1)
- (match-end 1)))))
- (in (progn
- (goto-char start)
- (and (re-search-backward gnus-cite-attribution-prefix
- (save-excursion
- (beginning-of-line 0)
- (point))
- t)
- (not (re-search-forward gnus-cite-attribution-suffix
- start t))
- (count-lines (point-min) (1+ (point)))))))
- (if (eq wrote in)
- (setq in nil))
- (goto-char end)
- (setq gnus-cite-loose-attribution-alist
- (cons (list wrote in prefix tag)
- gnus-cite-loose-attribution-alist))))
- ;; Find exact supercite citations.
- (gnus-cite-match-attributions 'small nil
- (lambda (prefix tag)
- (if tag
- (concat "\\`"
- (regexp-quote prefix) "[ \t]*"
- (regexp-quote tag) ">"))))
- ;; Find loose supercite citations after attributions.
- (gnus-cite-match-attributions 'small t
- (lambda (prefix tag)
- (if tag (concat "\\<"
- (regexp-quote tag)
- "\\>"))))
- ;; Find loose supercite citations anywhere.
- (gnus-cite-match-attributions 'small nil
- (lambda (prefix tag)
- (if tag (concat "\\<"
- (regexp-quote tag)
- "\\>"))))
- ;; Find nested citations after attributions.
- (gnus-cite-match-attributions 'small-if-unique t
- (lambda (prefix tag)
- (concat "\\`" (regexp-quote prefix) ".+")))
- ;; Find nested citations anywhere.
- (gnus-cite-match-attributions 'small nil
- (lambda (prefix tag)
- (concat "\\`" (regexp-quote prefix) ".+")))
- ;; Remove loose prefixes with too few lines.
- (let ((alist gnus-cite-loose-prefix-alist)
- entry)
- (while alist
- (setq entry (car alist)
- alist (cdr alist))
- (if (< (length (cdr entry)) gnus-cite-minimum-match-count)
- (setq gnus-cite-prefix-alist
- (delq entry gnus-cite-prefix-alist)
- gnus-cite-loose-prefix-alist
- (delq entry gnus-cite-loose-prefix-alist)))))
- ;; Find flat attributions.
- (gnus-cite-match-attributions 'first t nil)
- ;; Find any attributions (are we getting desperate yet?).
- (gnus-cite-match-attributions 'first nil nil))
-
-(defun gnus-cite-match-attributions (sort after fun)
- ;; Match all loose attributions and citations (SORT AFTER FUN) .
- ;;
- ;; If SORT is `small', the citation with the shortest prefix will be
- ;; used, if it is `first' the first prefix will be used, if it is
- ;; `small-if-unique' the shortest prefix will be used if the
- ;; attribution line does not share its own prefix with other
- ;; loose attribution lines, otherwise the first prefix will be used.
- ;;
- ;; If AFTER is non-nil, only citations after the attribution line
- ;; will be considered.
- ;;
- ;; If FUN is non-nil, it will be called with the arguments (WROTE
- ;; PREFIX TAG) and expected to return a regular expression. Only
- ;; citations whose prefix matches the regular expression will be
- ;; considered.
- ;;
- ;; WROTE is the attribution line number.
- ;; PREFIX is the attribution line prefix.
- ;; TAG is the Supercite tag on the attribution line.
- (let ((atts gnus-cite-loose-attribution-alist)
- (case-fold-search t)
- att wrote in prefix tag regexp limit smallest best size)
- (while atts
- (setq att (car atts)
- atts (cdr atts)
- wrote (nth 0 att)
- in (nth 1 att)
- prefix (nth 2 att)
- tag (nth 3 att)
- regexp (if fun (funcall fun prefix tag) "")
- size (cond ((eq sort 'small) t)
- ((eq sort 'first) nil)
- (t (< (length (gnus-cite-find-loose prefix)) 2)))
- limit (if after wrote -1)
- smallest 1000000
- best nil)
- (let ((cites gnus-cite-loose-prefix-alist)
- cite candidate numbers first compare)
- (while cites
- (setq cite (car cites)
- cites (cdr cites)
- candidate (car cite)
- numbers (cdr cite)
- first (apply 'min numbers)
- compare (if size (length candidate) first))
- (and (> first limit)
- regexp
- (string-match regexp candidate)
- (< compare smallest)
- (setq best cite
- smallest compare))))
- (if (null best)
- ()
- (setq gnus-cite-loose-attribution-alist
- (delq att gnus-cite-loose-attribution-alist))
- (setq gnus-cite-attribution-alist
- (cons (cons wrote (car best)) gnus-cite-attribution-alist))
- (if in
- (setq gnus-cite-attribution-alist
- (cons (cons in (car best)) gnus-cite-attribution-alist)))
- (if (memq best gnus-cite-loose-prefix-alist)
- (let ((loop gnus-cite-prefix-alist)
- (numbers (cdr best))
- current)
- (setq gnus-cite-loose-prefix-alist
- (delq best gnus-cite-loose-prefix-alist))
- (while loop
- (setq current (car loop)
- loop (cdr loop))
- (if (eq current best)
- ()
- (setcdr current (gnus-set-difference (cdr current) numbers))
- (if (null (cdr current))
- (setq gnus-cite-loose-prefix-alist
- (delq current gnus-cite-loose-prefix-alist)
- atts (delq current atts)))))))))))
-
-(defun gnus-cite-find-loose (prefix)
- ;; Return a list of loose attribution lines prefixed by PREFIX.
- (let* ((atts gnus-cite-loose-attribution-alist)
- att line lines)
- (while atts
- (setq att (car atts)
- line (car att)
- atts (cdr atts))
- (if (string-equal (gnus-cite-find-prefix line) prefix)
- (setq lines (cons line lines))))
- lines))
-
-(defun gnus-cite-add-face (number prefix face)
- ;; At line NUMBER, ignore PREFIX and add FACE to the rest of the line.
- (when face
- (let ((inhibit-point-motion-hooks t)
- from to)
- (goto-line number)
- (unless (eobp) ;; Sometimes things become confused.
- (forward-char (length prefix))
- (skip-chars-forward " \t")
- (setq from (point))
- (end-of-line 1)
- (skip-chars-backward " \t")
- (setq to (point))
- (when (< from to)
- (gnus-overlay-put (gnus-make-overlay from to) 'face face))))))
-
-(defun gnus-cite-toggle (prefix)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil)
- (numbers (cdr (assoc prefix gnus-cite-prefix-alist)))
- (inhibit-point-motion-hooks t)
- number)
- (while numbers
- (setq number (car numbers)
- numbers (cdr numbers))
- (goto-line number)
- (cond ((get-text-property (point) 'invisible)
- (remove-text-properties (point) (progn (forward-line 1) (point))
- gnus-hidden-properties))
- ((assq number gnus-cite-attribution-alist))
- (t
- (gnus-add-text-properties
- (point) (progn (forward-line 1) (point))
- (nconc (list 'gnus-type 'cite)
- gnus-hidden-properties))))))))
-
-(defun gnus-cite-find-prefix (line)
- ;; Return citation prefix for LINE.
- (let ((alist gnus-cite-prefix-alist)
- (prefix "")
- entry)
- (while alist
- (setq entry (car alist)
- alist (cdr alist))
- (if (memq line (cdr entry))
- (setq prefix (car entry))))
- prefix))
-
-(gnus-add-shutdown 'gnus-cache-close 'gnus)
-
-(defun gnus-cache-close ()
- (setq gnus-cite-prefix-alist nil))
-
-(gnus-ems-redefine)
-
-(provide 'gnus-cite)
-
-;;; gnus-cite.el ends here
diff --git a/lisp/gnus-cus.el b/lisp/gnus-cus.el
deleted file mode 100644
index a83d578bec1..00000000000
--- a/lisp/gnus-cus.el
+++ /dev/null
@@ -1,683 +0,0 @@
-;;; gnus-cus.el --- User friendly customization of Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-;;
-;; Author: Per Abrahamsen <abraham@iesd.auc.dk>
-;; Keywords: help, news
-;; Version: 0.1
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'custom)
-(require 'gnus-ems)
-(require 'browse-url)
-(eval-when-compile (require 'cl))
-
-;; The following is just helper functions and data, not meant to be set
-;; by the user.
-(defun gnus-make-face (color)
- ;; Create entry for face with COLOR.
- (custom-face-lookup color nil nil nil nil nil))
-
-(defvar gnus-face-light-name-list
- '("light blue" "light cyan" "light yellow" "light pink"
- "pale green" "beige" "orange" "magenta" "violet" "medium purple"
- "turquoise"))
-
-(defvar gnus-face-dark-name-list
- (list
- ;; Not all servers have dark blue in rgb.txt.
- (if (and (eq window-system 'x) (x-color-defined-p "dark blue"))
- "dark blue"
- "royal blue")
- "firebrick" "dark green" "OrangeRed"
- "dark khaki" "dark violet" "SteelBlue4"))
-; CornflowerBlue SeaGreen OrangeRed SteelBlue4 DeepPink3
-; DarkOlviveGreen4
-
-(custom-declare '()
- '((tag . "Gnus")
- (doc . "\
-The coffee-brewing, all singing, all dancing, kitchen sink newsreader.")
- (type . group)
- (data
- ((tag . "Visual")
- (doc . "\
-Gnus can be made colorful and fun or grey and dull as you wish.")
- (type . group)
- (data
- ((tag . "Visual")
- (doc . "Enable visual features.
-If `visual' is disabled, there will be no menus and few faces. Most of
-the visual customization options below will be ignored. Gnus will use
-less space and be faster as a result.")
- (default .
- (summary-highlight group-highlight
- article-highlight
- mouse-face
- summary-menu group-menu article-menu
- tree-highlight menu highlight
- browse-menu server-menu
- page-marker tree-menu binary-menu pick-menu
- grouplens-menu))
- (name . gnus-visual)
- (type . sexp))
- ((tag . "WWW Browser")
- (doc . "\
-WWW Browser to call when clicking on an URL button in the article buffer.
-
-You can choose between one of the predefined browsers, or `Other'.")
- (name . browse-url-browser-function)
- (calculate . (cond ((boundp 'browse-url-browser-function)
- browse-url-browser-function)
- ((fboundp 'w3-fetch)
- 'w3-fetch)
- ((eq window-system 'x)
- 'gnus-netscape-open-url)))
- (type . choice)
- (data
- ((tag . "W3")
- (type . const)
- (default . w3-fetch))
- ((tag . "Netscape")
- (type . const)
- (default . browse-url-netscape))
- ((prompt . "Other")
- (doc . "\
-You must specify the name of a Lisp function here. The lisp function
-should open a WWW browser when called with an URL (a string).
-")
- (default . __uninitialized__)
- (type . symbol))))
- ((tag . "Mouse Face")
- (doc . "\
-Face used for group or summary buffer mouse highlighting.
-The line beneath the mouse pointer will be highlighted with this
-face.")
- (name . gnus-mouse-face)
- (calculate . (condition-case ()
- (if (gnus-visual-p 'mouse-face 'highlight)
- (if (boundp 'gnus-mouse-face)
- gnus-mouse-face
- 'highlight)
- 'default)
- (error 'default)))
- (type . face))
- ((tag . "Article Display")
- (doc . "Controls how the article buffer will look.
-
-If you leave the list empty, the article will appear exactly as it is
-stored on the disk. The list entries will hide or highlight various
-parts of the article, making it easier to find the information you
-want.")
- (name . gnus-article-display-hook)
- (type . list)
- (calculate
- . (if (and (string-match "xemacs" emacs-version)
- (featurep 'xface))
- '(gnus-article-hide-headers-if-wanted
- gnus-article-hide-boring-headers
- gnus-article-treat-overstrike
- gnus-article-maybe-highlight
- gnus-article-display-x-face)
- '(gnus-article-hide-headers-if-wanted
- gnus-article-hide-boring-headers
- gnus-article-treat-overstrike
- gnus-article-maybe-highlight)))
- (data
- ((type . repeat)
- (header . nil)
- (data
- (tag . "Filter")
- (type . choice)
- (data
- ((tag . "Treat Overstrike")
- (doc . "\
-Convert use of overstrike into bold and underline.
-
-Two identical letters separated by a backspace are displayed as a
-single bold letter, while a letter followed by a backspace and an
-underscore will be displayed as a single underlined letter. This
-technique was developed for old line printers (think about it), and is
-still in use on some newsgroups, in particular the ClariNet
-hierarchy.
-")
- (type . const)
- (default .
- gnus-article-treat-overstrike))
- ((tag . "Word Wrap")
- (doc . "\
-Format too long lines.
-")
- (type . const)
- (default . gnus-article-word-wrap))
- ((tag . "Remove CR")
- (doc . "\
-Remove carriage returns from an article.
-")
- (type . const)
- (default . gnus-article-remove-cr))
- ((tag . "Display X-Face")
- (doc . "\
-Look for an X-Face header and display it if present.
-
-See also `X Face Command' for a definition of the external command
-used for decoding and displaying the face.
-")
- (type . const)
- (default . gnus-article-display-x-face))
- ((tag . "Unquote Printable")
- (doc . "\
-Transform MIME quoted printable into 8-bit characters.
-
-Quoted printable is often seen by strings like `=EF' where you would
-expect a non-English letter.
-")
- (type . const)
- (default .
- gnus-article-de-quoted-unreadable))
- ((tag . "Universal Time")
- (doc . "\
-Convert date header to universal time.
-")
- (type . const)
- (default . gnus-article-date-ut))
- ((tag . "Local Time")
- (doc . "\
-Convert date header to local timezone.
-")
- (type . const)
- (default . gnus-article-date-local))
- ((tag . "Lapsed Time")
- (doc . "\
-Replace date header with a header showing the articles age.
-")
- (type . const)
- (default . gnus-article-date-lapsed))
- ((tag . "Highlight")
- (doc . "\
-Highlight headers, citations, signature, and buttons.
-")
- (type . const)
- (default . gnus-article-highlight))
- ((tag . "Maybe Highlight")
- (doc . "\
-Highlight headers, signature, and buttons if `Visual' is turned on.
-")
- (type . const)
- (default .
- gnus-article-maybe-highlight))
- ((tag . "Highlight Some")
- (doc . "\
-Highlight headers, signature, and buttons.
-")
- (type . const)
- (default . gnus-article-highlight-some))
- ((tag . "Highlight Headers")
- (doc . "\
-Highlight headers as specified by `Article Header Highlighting'.
-")
- (type . const)
- (default .
- gnus-article-highlight-headers))
- ((tag . "Highlight Signature")
- (doc . "\
-Highlight the signature as specified by `Article Signature Face'.
-")
- (type . const)
- (default .
- gnus-article-highlight-signature))
- ((tag . "Citation")
- (doc . "\
-Highlight the citations as specified by `Citation Faces'.
-")
- (type . const)
- (default .
- gnus-article-highlight-citation))
- ((tag . "Hide")
- (doc . "\
-Hide unwanted headers, excess citation, and the signature.
-")
- (type . const)
- (default . gnus-article-hide))
- ((tag . "Hide Headers If Wanted")
- (doc . "\
-Hide headers, but allow user to display them with `t' or `v'.
-")
- (type . const)
- (default .
- gnus-article-hide-headers-if-wanted))
- ((tag . "Hide Headers")
- (doc . "\
-Hide unwanted headers and possibly sort them as well.
-Most likely you want to use `Hide Headers If Wanted' instead.
-")
- (type . const)
- (default . gnus-article-hide-headers))
- ((tag . "Hide Signature")
- (doc . "\
-Hide the signature.
-")
- (type . const)
- (default . gnus-article-hide-signature))
- ((tag . "Hide Excess Citations")
- (doc . "\
-Hide excess citation.
-
-Excess is defined by `Citation Hide Percentage' and `Citation Hide Absolute'.
-")
- (type . const)
- (default .
- gnus-article-hide-citation-maybe))
- ((tag . "Hide Citations")
- (doc . "\
-Hide all cited text.
-")
- (type . const)
- (default . gnus-article-hide-citation))
- ((tag . "Add Buttons")
- (doc . "\
-Make URL's into clickable buttons.
-")
- (type . const)
- (default . gnus-article-add-buttons))
- ((prompt . "Other")
- (doc . "\
-Name of Lisp function to call.
-
-Push the `Filter' button to select one of the predefined filters.
-")
- (type . symbol)))))))
- ((tag . "Article Button Face")
- (doc . "\
-Face used for highlighting buttons in the article buffer.
-
-An article button is a piece of text that you can activate by pressing
-`RET' or `mouse-2' above it.")
- (name . gnus-article-button-face)
- (default . bold)
- (type . face))
- ((tag . "Article Mouse Face")
- (doc . "\
-Face used for mouse highlighting in the article buffer.
-
-Article buttons will be displayed in this face when the cursor is
-above them.")
- (name . gnus-article-mouse-face)
- (default . highlight)
- (type . face))
- ((tag . "Article Signature Face")
- (doc . "\
-Face used for highlighting a signature in the article buffer.")
- (name . gnus-signature-face)
- (default . italic)
- (type . face))
- ((tag . "Article Header Highlighting")
- (doc . "\
-Controls highlighting of article header.
-
-Below is a list of article header names, and the faces used for
-displaying the name and content of the header. The `Header' field
-should contain the name of the header. The field actually contains a
-regular expression that should match the beginning of the header line,
-but if you don't know what a regular expression is, just write the
-name of the header. The second field is the `Name' field, which
-determines how the the header name (i.e. the part of the header left
-of the `:') is displayed. The third field is the `Content' field,
-which determines how the content (i.e. the part of the header right of
-the `:') is displayed.
-
-If you leave the last `Header' field in the list empty, the `Name' and
-`Content' fields will determine how headers not listed above are
-displayed.
-
-If you only want to change the display of the name part for a specific
-header, specify `None' in the `Content' field. Similarly, specify
-`None' in the `Name' field if you only want to leave the name part
-alone.")
- (name . gnus-header-face-alist)
- (type . list)
- (calculate
- . (cond
- ((not (eq gnus-display-type 'color))
- '(("" bold italic)))
- ((eq gnus-background-mode 'dark)
- (list
- (list "From" nil
- (custom-face-lookup "light blue" nil nil t t nil))
- (list "Subject" nil
- (custom-face-lookup "pink" nil nil t t nil))
- (list "Newsgroups:.*," nil
- (custom-face-lookup "yellow" nil nil t t nil))
- (list
- ""
- (custom-face-lookup "cyan" nil nil t nil nil)
- (custom-face-lookup "forestgreen" nil nil nil t
- nil))))
- (t
- (list
- (list "From" nil
- (custom-face-lookup "MidnightBlue" nil nil t t nil))
- (list "Subject" nil
- (custom-face-lookup "firebrick" nil nil t t nil))
- (list "Newsgroups:.*," nil
- (custom-face-lookup "indianred" nil nil t t nil))
- (list ""
- (custom-face-lookup
- "DarkGreen" nil nil t nil nil)
- (custom-face-lookup "DarkGreen" nil nil
- nil t nil))))))
- (data
- ((type . repeat)
- (header . nil)
- (data
- (type . list)
- (compact . t)
- (data
- ((type . string)
- (prompt . "Header")
- (tag . "Header "))
- "\n "
- ((type . face)
- (prompt . "Name")
- (tag . "Name "))
- "\n "
- ((type . face)
- (tag . "Content"))
- "\n")))))
- ((tag . "Attribution Face")
- (doc . "\
-Face used for attribution lines.
-It is merged with the face for the cited text belonging to the attribution.")
- (name . gnus-cite-attribution-face)
- (default . underline)
- (type . face))
- ((tag . "Citation Faces")
- (doc . "\
-List of faces used for highlighting citations.
-
-When there are citations from multiple articles in the same message,
-Gnus will try to give each citation from each article its own face.
-This should make it easier to see who wrote what.")
- (name . gnus-cite-face-list)
- (import . gnus-custom-import-cite-face-list)
- (type . list)
- (calculate . (cond ((not (eq gnus-display-type 'color))
- '(italic))
- ((eq gnus-background-mode 'dark)
- (mapcar 'gnus-make-face
- gnus-face-light-name-list))
- (t
- (mapcar 'gnus-make-face
- gnus-face-dark-name-list))))
- (data
- ((type . repeat)
- (header . nil)
- (data (type . face)
- (tag . "Face")))))
- ((tag . "Citation Hide Percentage")
- (doc . "\
-Only hide excess citation if above this percentage of the body.")
- (name . gnus-cite-hide-percentage)
- (default . 50)
- (type . integer))
- ((tag . "Citation Hide Absolute")
- (doc . "\
-Only hide excess citation if above this number of lines in the body.")
- (name . gnus-cite-hide-absolute)
- (default . 10)
- (type . integer))
- ((tag . "Summary Selected Face")
- (doc . "\
-Face used for highlighting the current article in the summary buffer.")
- (name . gnus-summary-selected-face)
- (default . underline)
- (type . face))
- ((tag . "Summary Line Highlighting")
- (doc . "\
-Controls the highlighting of summary buffer lines.
-
-Below is a list of `Form'/`Face' pairs. When deciding how a a
-particular summary line should be displayed, each form is
-evaluated. The content of the face field after the first true form is
-used. You can change how those summary lines are displayed, by
-editing the face field.
-
-It is also possible to change and add form fields, but currently that
-requires an understanding of Lisp expressions. Hopefully this will
-change in a future release. For now, you can use the following
-variables in the Lisp expression:
-
-score: The article's score
-default: The default article score.
-below: The score below which articles are automatically marked as read.
-mark: The article's mark.")
- (name . gnus-summary-highlight)
- (type . list)
- (calculate
- . (cond
- ((not (eq gnus-display-type 'color))
- '(((> score default) . bold)
- ((< score default) . italic)))
- ((eq gnus-background-mode 'dark)
- (list
- (cons
- '(= mark gnus-canceled-mark)
- (custom-face-lookup "yellow" "black" nil
- nil nil nil))
- (cons '(and (> score default)
- (or (= mark gnus-dormant-mark)
- (= mark gnus-ticked-mark)))
- (custom-face-lookup
- "pink" nil nil t nil nil))
- (cons '(and (< score default)
- (or (= mark gnus-dormant-mark)
- (= mark gnus-ticked-mark)))
- (custom-face-lookup "pink" nil nil
- nil t nil))
- (cons '(or (= mark gnus-dormant-mark)
- (= mark gnus-ticked-mark))
- (custom-face-lookup
- "pink" nil nil nil nil nil))
-
- (cons
- '(and (> score default) (= mark gnus-ancient-mark))
- (custom-face-lookup "medium blue" nil nil t
- nil nil))
- (cons
- '(and (< score default) (= mark gnus-ancient-mark))
- (custom-face-lookup "SkyBlue" nil nil
- nil t nil))
- (cons
- '(= mark gnus-ancient-mark)
- (custom-face-lookup "SkyBlue" nil nil
- nil nil nil))
- (cons '(and (> score default) (= mark gnus-unread-mark))
- (custom-face-lookup "white" nil nil t
- nil nil))
- (cons '(and (< score default) (= mark gnus-unread-mark))
- (custom-face-lookup "white" nil nil
- nil t nil))
- (cons '(= mark gnus-unread-mark)
- (custom-face-lookup
- "white" nil nil nil nil nil))
-
- (cons '(> score default) 'bold)
- (cons '(< score default) 'italic)))
- (t
- (list
- (cons
- '(= mark gnus-canceled-mark)
- (custom-face-lookup
- "yellow" "black" nil nil nil nil))
- (cons '(and (> score default)
- (or (= mark gnus-dormant-mark)
- (= mark gnus-ticked-mark)))
- (custom-face-lookup "firebrick" nil nil
- t nil nil))
- (cons '(and (< score default)
- (or (= mark gnus-dormant-mark)
- (= mark gnus-ticked-mark)))
- (custom-face-lookup "firebrick" nil nil
- nil t nil))
- (cons
- '(or (= mark gnus-dormant-mark)
- (= mark gnus-ticked-mark))
- (custom-face-lookup
- "firebrick" nil nil nil nil nil))
-
- (cons '(and (> score default) (= mark gnus-ancient-mark))
- (custom-face-lookup "RoyalBlue" nil nil
- t nil nil))
- (cons '(and (< score default) (= mark gnus-ancient-mark))
- (custom-face-lookup "RoyalBlue" nil nil
- nil t nil))
- (cons
- '(= mark gnus-ancient-mark)
- (custom-face-lookup
- "RoyalBlue" nil nil nil nil nil))
-
- (cons '(and (> score default) (/= mark gnus-unread-mark))
- (custom-face-lookup "DarkGreen" nil nil
- t nil nil))
- (cons '(and (< score default) (/= mark gnus-unread-mark))
- (custom-face-lookup "DarkGreen" nil nil
- nil t nil))
- (cons
- '(/= mark gnus-unread-mark)
- (custom-face-lookup "DarkGreen" nil nil
- nil nil nil))
-
- (cons '(> score default) 'bold)
- (cons '(< score default) 'italic)))))
- (data
- ((type . repeat)
- (header . nil)
- (data (type . pair)
- (compact . t)
- (data ((type . sexp)
- (width . 60)
- (tag . "Form"))
- "\n "
- ((type . face)
- (tag . "Face"))
- "\n")))))
-
- ((tag . "Group Line Highlighting")
- (doc . "\
-Controls the highlighting of group buffer lines.
-
-Below is a list of `Form'/`Face' pairs. When deciding how a a
-particular group line should be displayed, each form is
-evaluated. The content of the face field after the first true form is
-used. You can change how those group lines are displayed by
-editing the face field.
-
-It is also possible to change and add form fields, but currently that
-requires an understanding of Lisp expressions. Hopefully this will
-change in a future release. For now, you can use the following
-variables in the Lisp expression:
-
-group: The name of the group.
-unread: The number of unread articles in the group.
-method: The select method used.
-mailp: Whether it's a mail group or not.
-level: The level of the group.
-score: The score of the group.
-ticked: The number of ticked articles.")
- (name . gnus-group-highlight)
- (type . list)
- (calculate
- . (cond
- ((not (eq gnus-display-type 'color))
- '((mailp . bold)
- ((= unread 0) . italic)))
- ((eq gnus-background-mode 'dark)
- `(((and (not mailp) (eq level 1)) .
- ,(custom-face-lookup "PaleTurquoise" nil nil t))
- ((and (not mailp) (eq level 2)) .
- ,(custom-face-lookup "turquoise" nil nil t))
- ((and (not mailp) (eq level 3)) .
- ,(custom-face-lookup "MediumTurquoise" nil nil t))
- ((and (not mailp) (>= level 4)) .
- ,(custom-face-lookup "DarkTurquoise" nil nil t))
- ((and mailp (eq level 1)) .
- ,(custom-face-lookup "aquamarine1" nil nil t))
- ((and mailp (eq level 2)) .
- ,(custom-face-lookup "aquamarine2" nil nil t))
- ((and mailp (eq level 3)) .
- ,(custom-face-lookup "aquamarine3" nil nil t))
- ((and mailp (>= level 4)) .
- ,(custom-face-lookup "aquamarine4" nil nil t))
- ))
- (t
- `(((and (not mailp) (<= level 3)) .
- ,(custom-face-lookup "ForestGreen" nil nil t))
- ((and (not mailp) (eq level 4)) .
- ,(custom-face-lookup "DarkGreen" nil nil t))
- ((and (not mailp) (eq level 5)) .
- ,(custom-face-lookup "CadetBlue4" nil nil t))
- ((and mailp (eq level 1)) .
- ,(custom-face-lookup "DeepPink3" nil nil t))
- ((and mailp (eq level 2)) .
- ,(custom-face-lookup "HotPink3" nil nil t))
- ((and mailp (eq level 3)) .
- ,(custom-face-lookup
- ;; Not all servers have dark magenta in rgb.txt.
- (if (and (eq window-system 'x)
- (x-color-defined-p "dark magenta"))
- "dark magenta"
- "maroon")
- nil nil t))
- ((and mailp (eq level 4)) .
- ,(custom-face-lookup "DeepPink4" nil nil t))
- ((and mailp (> level 4)) .
- ,(custom-face-lookup "DarkOrchid4" nil nil t))
- ))))
- (data
- ((type . repeat)
- (header . nil)
- (data (type . pair)
- (compact . t)
- (data ((type . sexp)
- (width . 60)
- (tag . "Form"))
- "\n "
- ((type . face)
- (tag . "Face"))
- "\n")))))
-
- ;; Do not define `gnus-button-alist' before we have
- ;; some `complexity' attribute so we can hide it from
- ;; beginners.
- )))))
-
-(defun gnus-custom-import-cite-face-list (custom alist)
- ;; Backward compatible grokking of light and dark.
- (cond ((eq alist 'light)
- (setq alist (mapcar 'gnus-make-face gnus-face-light-name-list)))
- ((eq alist 'dark)
- (setq alist (mapcar 'gnus-make-face gnus-face-dark-name-list))))
- (funcall (custom-super custom 'import) custom alist))
-
-(provide 'gnus-cus)
-
-;;; gnus-cus.el ends here
diff --git a/lisp/gnus-demon.el b/lisp/gnus-demon.el
deleted file mode 100644
index 431eb3220ca..00000000000
--- a/lisp/gnus-demon.el
+++ /dev/null
@@ -1,222 +0,0 @@
-;;; gnus-demon.el --- daemonic Gnus behaviour
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'gnus)
-
-(eval-when-compile (require 'cl))
-
-(defvar gnus-demon-handlers nil
- "Alist of daemonic handlers to be run at intervals.
-Each handler is a list on the form
-
-\(FUNCTION TIME IDLE)
-
-FUNCTION is the function to be called.
-TIME is the number of `gnus-demon-timestep's between each call.
-If nil, never call. If t, call each `gnus-demon-timestep'.
-If IDLE is t, only call if Emacs has been idle for a while. If IDLE
-is a number, only call when Emacs has been idle more than this number
-of `gnus-demon-timestep's. If IDLE is nil, don't care about
-idleness. If IDLE is a number and TIME is nil, then call once each
-time Emacs has been idle for IDLE `gnus-demon-timestep's.")
-
-(defvar gnus-demon-timestep 60
- "*Number of seconds in each demon timestep.")
-
-;;; Internal variables.
-
-(defvar gnus-demon-timer nil)
-(defvar gnus-demon-idle-has-been-called nil)
-(defvar gnus-demon-idle-time 0)
-(defvar gnus-demon-handler-state nil)
-(defvar gnus-demon-is-idle nil)
-(defvar gnus-demon-last-keys nil)
-
-(eval-and-compile
- (autoload 'timezone-parse-date "timezone")
- (autoload 'timezone-make-arpa-date "timezone"))
-
-;;; Functions.
-
-(defun gnus-demon-add-handler (function time idle)
- "Add the handler FUNCTION to be run at TIME and IDLE."
- ;; First remove any old handlers that use this function.
- (gnus-demon-remove-handler function)
- ;; Then add the new one.
- (push (list function time idle) gnus-demon-handlers)
- (gnus-demon-init))
-
-(defun gnus-demon-remove-handler (function &optional no-init)
- "Remove the handler FUNCTION from the list of handlers."
- (setq gnus-demon-handlers
- (delq (assq function gnus-demon-handlers)
- gnus-demon-handlers))
- (or no-init (gnus-demon-init)))
-
-(defun gnus-demon-init ()
- "Initialize the Gnus daemon."
- (interactive)
- (gnus-demon-cancel)
- (if (null gnus-demon-handlers)
- () ; Nothing to do.
- ;; Set up timer.
- (setq gnus-demon-timer
- (nnheader-run-at-time
- gnus-demon-timestep gnus-demon-timestep 'gnus-demon))
- ;; Reset control variables.
- (setq gnus-demon-handler-state
- (mapcar
- (lambda (handler)
- (list (car handler) (gnus-demon-time-to-step (nth 1 handler))
- (nth 2 handler)))
- gnus-demon-handlers))
- (setq gnus-demon-idle-time 0)
- (setq gnus-demon-idle-has-been-called nil)
- (setq gnus-use-demon t)))
-
-(gnus-add-shutdown 'gnus-demon-cancel 'gnus)
-
-(defun gnus-demon-cancel ()
- "Cancel any Gnus daemons."
- (interactive)
- (and gnus-demon-timer
- (nnheader-cancel-timer gnus-demon-timer))
- (setq gnus-demon-timer nil
- gnus-use-demon nil))
-
-(defun gnus-demon-is-idle-p ()
- "Whether Emacs is idle or not."
- ;; We do this simply by comparing the 100 most recent keystrokes
- ;; with the ones we had last time. If they are the same, one might
- ;; guess that Emacs is indeed idle. This only makes sense if one
- ;; calls this function seldom -- like once a minute, which is what
- ;; we do here.
- (let ((keys (recent-keys)))
- (or (equal keys gnus-demon-last-keys)
- (progn
- (setq gnus-demon-last-keys keys)
- nil))))
-
-(defun gnus-demon-time-to-step (time)
- "Find out how many seconds to TIME, which is on the form \"17:43\"."
- (if (not (stringp time))
- time
- (let* ((date (current-time-string))
- (dv (timezone-parse-date date))
- (tdate (timezone-make-arpa-date
- (string-to-number (aref dv 0))
- (string-to-number (aref dv 1))
- (string-to-number (aref dv 2)) time
- (or (aref dv 4) "UT")))
- (nseconds (gnus-time-minus
- (gnus-encode-date tdate) (gnus-encode-date date))))
- (round
- (/ (if (< nseconds 0)
- (+ nseconds (* 60 60 24))
- nseconds) gnus-demon-timestep)))))
-
-(defun gnus-demon ()
- "The Gnus daemon that takes care of running all Gnus handlers."
- ;; Increase or reset the time Emacs has been idle.
- (if (gnus-demon-is-idle-p)
- (incf gnus-demon-idle-time)
- (setq gnus-demon-idle-time 0)
- (setq gnus-demon-idle-has-been-called nil))
- ;; Then we go through all the handler and call those that are
- ;; sufficiently ripe.
- (let ((handlers gnus-demon-handler-state)
- handler time idle)
- (while handlers
- (setq handler (pop handlers))
- (cond
- ((numberp (setq time (nth 1 handler)))
- ;; These handlers use a regular timeout mechanism. We decrease
- ;; the timer if it hasn't reached zero yet.
- (or (zerop time)
- (setcar (nthcdr 1 handler) (decf time)))
- (and (zerop time) ; If the timer now is zero...
- (or (not (setq idle (nth 2 handler))) ; Don't care about idle.
- (and (numberp idle) ; Numerical idle...
- (< idle gnus-demon-idle-time)) ; Idle timed out.
- gnus-demon-is-idle) ; Or just need to be idle.
- ;; So we call the handler.
- (progn
- (funcall (car handler))
- ;; And reset the timer.
- (setcar (nthcdr 1 handler)
- (gnus-demon-time-to-step
- (nth 1 (assq (car handler) gnus-demon-handlers)))))))
- ;; These are only supposed to be called when Emacs is idle.
- ((null (setq idle (nth 2 handler)))
- ;; We do nothing.
- )
- ((not (numberp idle))
- ;; We want to call this handler each and every time that
- ;; Emacs is idle.
- (funcall (car handler)))
- (t
- ;; We want to call this handler only if Emacs has been idle
- ;; for a specified number of timesteps.
- (and (not (memq (car handler) gnus-demon-idle-has-been-called))
- (< idle gnus-demon-idle-time)
- (progn
- (funcall (car handler))
- ;; Make sure the handler won't be called once more in
- ;; this idle-cycle.
- (push (car handler) gnus-demon-idle-has-been-called))))))))
-
-(defun gnus-demon-add-nocem ()
- "Add daemonic NoCeM handling to Gnus."
- (gnus-demon-add-handler 'gnus-demon-scan-nocem 60 t))
-
-(defun gnus-demon-scan-nocem ()
- "Scan NoCeM groups for NoCeM messages."
- (gnus-nocem-scan-groups))
-
-(defun gnus-demon-add-disconnection ()
- "Add daemonic server disconnection to Gnus."
- (gnus-demon-add-handler 'gnus-demon-close-connections nil 30))
-
-(defun gnus-demon-close-connections ()
- (gnus-close-backends))
-
-(defun gnus-demon-add-scanmail ()
- "Add daemonic scanning of mail from the mail backends."
- (gnus-demon-add-handler 'gnus-demon-scan-mail 120 60))
-
-(defun gnus-demon-scan-mail ()
- (let ((servers gnus-opened-servers)
- server)
- (while (setq server (car (pop servers)))
- (and (gnus-check-backend-function 'request-scan (car server))
- (or (gnus-server-opened server)
- (gnus-open-server server))
- (gnus-request-scan nil server)))))
-
-(provide 'gnus-demon)
-
-;;; gnus-demon.el ends here
diff --git a/lisp/gnus-edit.el b/lisp/gnus-edit.el
deleted file mode 100644
index 4ac5e6777a1..00000000000
--- a/lisp/gnus-edit.el
+++ /dev/null
@@ -1,630 +0,0 @@
-;;; gnus-edit.el --- Gnus SCORE file editing
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-;;
-;; Author: Per Abrahamsen <abraham@iesd.auc.dk>
-;; Keywords: news, help
-;; Version: 0.2
-
-;;; Commentary:
-;;
-;; Type `M-x gnus-score-customize RET' to invoke.
-
-;;; Code:
-
-(require 'custom)
-(require 'gnus-score)
-(eval-when-compile (require 'cl))
-
-(defconst gnus-score-custom-data
- '((tag . "Score")
- (doc . "Customization of Gnus SCORE files.
-
-SCORE files allow you to assign a score to each article when you enter
-a group, and automatically mark the articles as read or delete them
-based on the score. In the summary buffer you can use the score to
-sort the articles by score (`C-c C-s C-s') or to jump to the unread
-article with the highest score (`,').")
- (type . group)
- (data "\n"
- ((header . nil)
- (doc . "Name of SCORE file to customize.
-
-Enter the name in the `File' field, then push the [Load] button to
-load it. When done editing, push the [Save] button to save the file.
-
-Several score files may apply to each group, and several groups may
-use the same score file. This is controlled implicitly by the name of
-the score file and the value of the global variable
-`gnus-score-find-score-files-function', and explicitly by the the
-`Files' and `Exclude Files' entries.")
- (compact . t)
- (type . group)
- (data ((tag . "Load")
- (type . button)
- (query . gnus-score-custom-load))
- ((tag . "Save")
- (type . button)
- (query . gnus-score-custom-save))
- ((name . file)
- (tag . "File")
- (directory . gnus-kill-files-directory)
- (default-file . "SCORE")
- (type . file))))
- ((name . files)
- (tag . "Files")
- (doc . "\
-List of score files to load when the the current score file is loaded.
-You can use this to share score entries between multiple score files.
-
-Push the `[INS]' button add a score file to the list, or `[DEL]' to
-delete a score file from the list.")
- (type . list)
- (data ((type . repeat)
- (header . nil)
- (data (type . file)
- (directory . gnus-kill-files-directory)))))
- ((name . exclude-files)
- (tag . "Exclude Files")
- (doc . "\
-List of score files to exclude when the the current score file is loaded.
-You can use this if you have a score file you want to share between a
-number of newsgroups, except for the newsgroup this score file
-matches. [ Did anyone get that? ]
-
-Push the `[INS]' button add a score file to the list, or `[DEL]' to
-delete a score file from the list.")
- (type . list)
- (data ((type . repeat)
- (header . nil)
- (data (type . file)
- (directory . gnus-kill-files-directory)))))
- ((name . mark)
- (tag . "Mark")
- (doc . "\
-Articles below this score will be automatically marked as read.
-
-This means that when you enter the summary buffer, the articles will
-be shown but will already be marked as read. You can then press `x'
-to get rid of them entirely.
-
-By default articles with a negative score will be marked as read. To
-change this, push the `Mark' button, and choose `Integer'. You can
-then enter a value in the `Mark' field.")
- (type . gnus-score-custom-maybe-type))
- ((name . expunge)
- (tag . "Expunge")
- (doc . "\
-Articles below this score will not be shown in the summary buffer.")
- (type . gnus-score-custom-maybe-type))
- ((name . mark-and-expunge)
- (tag . "Mark and Expunge")
- (doc . "\
-Articles below this score will be marked as read, but not shown.
-
-Someone should explain me the difference between this and `expunge'
-alone or combined with `mark'.")
- (type . gnus-score-custom-maybe-type))
- ((name . eval)
- (tag . "Eval")
- (doc . "\
-Evaluate this lisp expression when the entering summary buffer.")
- (type . sexp))
- ((name . read-only)
- (tag . "Read Only")
- (doc . "Read-only score files will not be updated or saved.
-Except from this buffer, of course!")
- (type . toggle))
- ((type . doc)
- (doc . "\
-Each news header has an associated list of score entries.
-You can use the [INS] buttons to add new score entries anywhere in the
-list, or the [DEL] buttons to delete specific score entries.
-
-Each score entry should specify a string that should be matched with
-the content actual header in order to determine whether the entry
-applies to that header. Enter that string in the `Match' field.
-
-If the score entry matches, the articles score will be adjusted with
-some amount. Enter that amount in the in the `Score' field. You
-should specify a positive amount for score entries that matches
-articles you find interesting, and a negative amount for score entries
-matching articles you would rather avoid. The final score for the
-article will be the sum of the score of all score entries that match
-the article.
-
-The score entry can be either permanent or expirable. To make the
-entry permanent, push the `Date' button and choose the `Permanent'
-entry. To make the entry expirable, choose instead the `Integer'
-entry. After choosing the you can enter the date the score entry was
-last matched in the `Date' field. The date will be automatically
-updated each time the score entry matches an article. When the date
-become too old, the the score entry will be removed.
-
-For your convenience, the date is specified as the number of days
-elapsed since the (imaginary) Gregorian date Sunday, December 31, 1
-BC.
-
-Finally, you can choose what kind of match you want to perform by
-pushing the `Type' button. For most entries you can choose between
-`Exact' which mean the header content must be exactly identical to the
-match string, or `Substring' meaning the match string should be
-somewhere in the header content, or even `Regexp' to use Emacs regular
-expression matching. The last choice is `Fuzzy' which is like `Exact'
-except that whitespace derivations, a beginning `Re:' or a terminating
-parenthetical remark are all ignored. Each of the four types have a
-variant which will ignore case in the comparison. That variant is
-indicated with a `(fold)' after its name."))
- ((name . from)
- (tag . "From")
- (doc . "Scoring based on the authors email address.")
- (type . gnus-score-custom-string-type))
- ((name . subject)
- (tag . "Subject")
- (doc . "Scoring based on the articles subject.")
- (type . gnus-score-custom-string-type))
- ((name . followup)
- (tag . "Followup")
- (doc . "Scoring based on who the article is a followup to.
-
-If you want to see all followups to your own articles, add an entry
-with a positive score matching your email address here. You can also
-put an entry with a negative score matching someone who is so annoying
-that you don't even want to see him quoted in followups.")
- (type . gnus-score-custom-string-type))
- ((name . xref)
- (tag . "Xref")
- (doc . "Scoring based on article crossposting.
-
-If you want to score based on which newsgroups an article is posted
-to, this is the header to use. The syntax is a little different from
-the `Newsgroups' header, but scoring in `Xref' is much faster. As an
-example, to match all crossposted articles match on `:.*:' using the
-`Regexp' type.")
- (type . gnus-score-custom-string-type))
- ((name . references)
- (tag . "References")
- (doc . "Scoring based on article references.
-
-The `References' header gives you an alternative way to score on
-followups. If you for example want to see follow all discussions
-where people from `iesd.auc.dk' school participate, you can add a
-substring match on `iesd.auc.dk>' on this header.")
- (type . gnus-score-custom-string-type))
- ((name . message-id)
- (tag . "Message-ID")
- (doc . "Scoring based on the articles message-id.
-
-This isn't very useful, but Lars like completeness. You can use it to
-match all messaged generated by recent Gnus version with a `Substring'
-match on `.fsf@'.")
- (type . gnus-score-custom-string-type))
- ((type . doc)
- (doc . "\
-WARNING: Scoring on the following three pseudo headers is very slow!
-Scoring on any of the real headers use a technique that avoids
-scanning the entire article, only the actual headers you score on are
-scanned, and this scanning has been heavily optimized. Using just a
-single entry for one the three pseudo-headers `Head', `Body', and
-`All' will require GNUS to retrieve and scan the entire article, which
-can be very slow on large groups. However, if you add one entry for
-any of these headers, you can just as well add several. Each
-subsequent entry cost relatively little extra time."))
- ((name . head)
- (tag . "Head")
- (doc . "Scoring based on the article header.
-
-Instead of matching the content of a single header, the entire header
-section of the article is matched. You can use this to match on
-arbitrary headers, foe example to single out TIN lusers, use a substring
-match on `Newsreader: TIN'. That should get 'em!")
- (type . gnus-score-custom-string-type))
- ((name . body)
- (tag . "Body")
- (doc . "Scoring based on the article body.
-
-If you think any article that mentions `Kibo' is inherently
-interesting, do a substring match on His name. You Are Allowed.")
- (type . gnus-score-custom-string-type))
- ((name . all)
- (tag . "All")
- (doc . "Scoring based on the whole article.")
- (type . gnus-score-custom-string-type))
- ((name . date)
- (tag . "Date")
- (doc . "Scoring based on article date.
-
-You can change the score of articles that have been posted before,
-after, or at a specific date. You should add the date in the `Match'
-field, and then select `before', `after', or `at' by pushing the
-`Type' button. Imagine you want to lower the score of very old
-articles, or want to raise the score of articles from the future (such
-things happen!). Then you can't use date scoring for that. In fact,
-I can't imagine anything you would want to use this for.
-
-For your convenience, the date is specified in Usenet date format.")
- (type . gnus-score-custom-date-type))
- ((type . doc)
- (doc . "\
-The Lines and Chars headers use integer based scoring.
-
-This means that you should write an integer in the `Match' field, and
-the push the `Type' field to if the `Chars' or `Lines' header should
-be larger, equal, or smaller than the number you wrote in the match
-field."))
- ((name . chars)
- (tag . "Characters")
- (doc . "Scoring based on the number of characters in the article.")
- (type . gnus-score-custom-integer-type))
- ((name . lines)
- (tag . "Lines")
- (doc . "Scoring based on the number of lines in the article.")
- (type . gnus-score-custom-integer-type))
- ((name . orphan)
- (tag . "Orphan")
- (doc . "Score to add to articles with no parents.")
- (type . gnus-score-custom-maybe-type))
- ((name . adapt)
- (tag . "Adapt")
- (doc . "Adapting the score files to your newsreading habits.
-
-When you have finished reading a group GNUS can automatically create
-new score entries based on which articles you read and which you
-skipped. This is normally controlled by the two global variables
-`gnus-use-adaptive-scoring' and `gnus-default-adaptive-score-alist',
-The first determines whether adaptive scoring should be enabled or
-not, while the second determines what score entries should be created.
-
-You can overwrite the setting of `gnus-use-adaptive-scoring' by
-selecting `Enable' or `Disable' by pressing the `Adapt' button.
-Selecting `Custom' will allow you to specify the exact adaptation
-rules (overwriting `gnus-default-adaptive-score-alist').")
- (type . choice)
- (data ((tag . "Default")
- (default . nil)
- (type . const))
- ((tag . "Enable")
- (default . t)
- (type . const))
- ((tag . "Disable")
- (default . ignore)
- (type . const))
- ((tag . "Custom")
- (doc . "Customization of adaptive scoring.
-
-Each time you read an article it will be marked as read. Likewise, if
-you delete it it will be marked as deleted, and if you tick it it will
-be marked as ticked. When you leave a group, GNUS can automatically
-create score file entries based on these marks, so next time you enter
-the group articles with subjects that you read last time have higher
-score and articles with subjects that deleted will have lower score.
-
-Below is a list of such marks. You can insert new marks to the list
-by pushing on one of the `[INS]' buttons in the left margin to create
-a new entry and then pushing the `Mark' button to select the mark.
-For each mark there is another list, this time of article headers,
-which determine how the mark should affect that header. The `[INS]'
-buttons of this list are indented to indicate that the belong to the
-mark above. Push the `Header' button to choose a header, and then
-enter a score value in the `Score' field.
-
-For each article that are marked with `Mark' when you leave the
-group, a temporary score entry for the articles `Header' with the
-value of `Score' will be added the adapt file. If the score entry
-already exists, `Score' will be added to its value. If you understood
-that, you are smart.
-
-You can select the special value `Other' when pressing the `Mark' or
-`Header' buttons. This is because Lars might add more useful values
-there. If he does, it is up to you to figure out what they are named.")
- (type . list)
- (default . ((__uninitialized__)))
- (data ((type . repeat)
- (header . nil)
- (data . ((type . list)
- (header . nil)
- (compact . t)
- (data ((type . choice)
- (tag . "Mark")
- (data ((tag . "Unread")
- (default . gnus-unread-mark)
- (type . const))
- ((tag . "Ticked")
- (default . gnus-ticked-mark)
- (type . const))
- ((tag . "Dormant")
- (default . gnus-dormant-mark)
- (type . const))
- ((tag . "Deleted")
- (default . gnus-del-mark)
- (type . const))
- ((tag . "Read")
- (default . gnus-read-mark)
- (type . const))
- ((tag . "Expirable")
- (default . gnus-expirable-mark)
- (type . const))
- ((tag . "Killed")
- (default . gnus-killed-mark)
- (type . const))
- ((tag . "Kill-file")
- (default . gnus-kill-file-mark)
- (type . const))
- ((tag . "Low-score")
- (default . gnus-low-score-mark)
- (type . const))
- ((tag . "Catchup")
- (default . gnus-catchup-mark)
- (type . const))
- ((tag . "Ancient")
- (default . gnus-ancient-mark)
- (type . const))
- ((tag . "Canceled")
- (default . gnus-canceled-mark)
- (type . const))
- ((prompt . "Other")
- (default . ??)
- (type . sexp))))
- ((type . repeat)
- (prefix . " ")
- (data . ((type . list)
- (compact . t)
- (data ((tag . "Header")
- (type . choice)
- (data ((tag . "Subject")
- (default . subject)
- (type . const))
- ((prompt . "From")
- (tag . "From ")
- (default . from)
- (type . const))
- ((prompt . "Other")
- (width . 7)
- (default . nil)
- (type . symbol))))
- ((tag . "Score")
- (type . integer))))))))))))))
- ((name . local)
- (tag . "Local")
- (doc . "\
-List of local variables to set when this score file is loaded.
-
-Using this entry can provide a convenient way to set variables that
-will affect the summary mode for only some specific groups, i.e. those
-groups matched by the current score file.")
- (type . list)
- (data ((type . repeat)
- (header . nil)
- (data . ((type . list)
- (compact . t)
- (data ((tag . "Name")
- (width . 26)
- (type . symbol))
- ((tag . "Value")
- (width . 26)
- (type . sexp)))))))))))
-
-(defconst gnus-score-custom-type-properties
- '((gnus-score-custom-maybe-type
- (type . choice)
- (data ((type . integer)
- (default . 0))
- ((tag . "Default")
- (type . const)
- (default . nil))))
- (gnus-score-custom-string-type
- (type . list)
- (data ((type . repeat)
- (header . nil)
- (data . ((type . list)
- (compact . t)
- (data ((tag . "Match")
- (width . 59)
- (type . string))
- "\n "
- ((tag . "Score")
- (type . integer))
- ((tag . "Date")
- (type . choice)
- (data ((type . integer)
- (default . 0)
- (width . 9))
- ((tag . "Permanent")
- (type . const)
- (default . nil))))
- ((tag . "Type")
- (type . choice)
- (data ((tag . "Exact")
- (default . E)
- (type . const))
- ((tag . "Substring")
- (default . S)
- (type . const))
- ((tag . "Regexp")
- (default . R)
- (type . const))
- ((tag . "Fuzzy")
- (default . F)
- (type . const))
- ((tag . "Exact (fold)")
- (default . e)
- (type . const))
- ((tag . "Substring (fold)")
- (default . s)
- (type . const))
- ((tag . "Regexp (fold)")
- (default . r)
- (type . const))
- ((tag . "Fuzzy (fold)")
- (default . f)
- (type . const))))))))))
- (gnus-score-custom-integer-type
- (type . list)
- (data ((type . repeat)
- (header . nil)
- (data . ((type . list)
- (compact . t)
- (data ((tag . "Match")
- (type . integer))
- ((tag . "Score")
- (type . integer))
- ((tag . "Date")
- (type . choice)
- (data ((type . integer)
- (default . 0)
- (width . 9))
- ((tag . "Permanent")
- (type . const)
- (default . nil))))
- ((tag . "Type")
- (type . choice)
- (data ((tag . "<")
- (default . <)
- (type . const))
- ((tag . ">")
- (default . >)
- (type . const))
- ((tag . "=")
- (default . =)
- (type . const))
- ((tag . ">=")
- (default . >=)
- (type . const))
- ((tag . "<=")
- (default . <=)
- (type . const))))))))))
- (gnus-score-custom-date-type
- (type . list)
- (data ((type . repeat)
- (header . nil)
- (data . ((type . list)
- (compact . t)
- (data ((tag . "Match")
- (width . 59)
- (type . string))
- "\n "
- ((tag . "Score")
- (type . integer))
- ((tag . "Date")
- (type . choice)
- (data ((type . integer)
- (default . 0)
- (width . 9))
- ((tag . "Permanent")
- (type . const)
- (default . nil))))
- ((tag . "Type")
- (type . choice)
- (data ((tag . "Before")
- (default . before)
- (type . const))
- ((tag . "After")
- (default . after)
- (type . const))
- ((tag . "At")
- (default . at)
- (type . const))))))))))))
-
-(defvar gnus-score-custom-file nil
- "Name of SCORE file being customized.")
-
-(defun gnus-score-customize ()
- "Create a buffer for editing gnus SCORE files."
- (interactive)
- (let (gnus-score-alist)
- (custom-buffer-create "*Score Edit*" gnus-score-custom-data
- gnus-score-custom-type-properties
- 'gnus-score-custom-set
- 'gnus-score-custom-get
- 'gnus-score-custom-save))
- (make-local-variable 'gnus-score-custom-file)
- (setq gnus-score-custom-file
- (expand-file-name "SCORE" gnus-kill-files-directory))
- (make-local-variable 'gnus-score-alist)
- (setq gnus-score-alist nil)
- (custom-reset-all))
-
-(defun gnus-score-custom-get (name)
- (if (eq name 'file)
- gnus-score-custom-file
- (let ((entry (assoc (symbol-name name) gnus-score-alist)))
- (if entry
- (mapcar 'gnus-score-custom-sanify (cdr entry))
- (setq entry (assoc name gnus-score-alist))
- (if (or (memq name '(files exclude-files local))
- (and (eq name 'adapt)
- (not (symbolp (car (cdr entry))))))
- (cdr entry)
- (car (cdr entry)))))))
-
-(defun gnus-score-custom-set (name value)
- (cond ((eq name 'file)
- (setq gnus-score-custom-file value))
- ((assoc (symbol-name name) gnus-score-alist)
- (if value
- (setcdr (assoc (symbol-name name) gnus-score-alist) value)
- (setq gnus-score-alist (delq (assoc (symbol-name name)
- gnus-score-alist)
- gnus-score-alist))))
- ((assoc (symbol-name name) gnus-header-index)
- (if value
- (setq gnus-score-alist
- (cons (cons (symbol-name name) value) gnus-score-alist))))
- ((assoc name gnus-score-alist)
- (cond ((null value)
- (setq gnus-score-alist (delq (assoc name gnus-score-alist)
- gnus-score-alist)))
- ((and (listp value) (not (eq name 'eval)))
- (setcdr (assoc name gnus-score-alist) value))
- (t
- (setcdr (assoc name gnus-score-alist) (list value)))))
- ((null value))
- ((and (listp value) (not (eq name 'eval)))
- (setq gnus-score-alist (cons (cons name value) gnus-score-alist)))
- (t
- (setq gnus-score-alist
- (cons (cons name (list value)) gnus-score-alist)))))
-
-(defun gnus-score-custom-sanify (entry)
- (list (nth 0 entry)
- (or (nth 1 entry) gnus-score-interactive-default-score)
- (nth 2 entry)
- (cond ((null (nth 3 entry))
- 's)
- ((memq (nth 3 entry) '(before after at >= <=))
- (nth 3 entry))
- (t
- (intern (substring (symbol-name (nth 3 entry)) 0 1))))))
-
-(defvar gnus-score-cache nil)
-
-(defun gnus-score-custom-load ()
- (interactive)
- (let ((file (custom-name-value 'file)))
- (if (eq file custom-nil)
- (error "You must specify a file name"))
- (setq file (expand-file-name file gnus-kill-files-directory))
- (gnus-score-load file)
- (setq gnus-score-custom-file file)
- (custom-reset-all)
- (gnus-message 4 "Loaded")))
-
-(defun gnus-score-custom-save ()
- (interactive)
- (custom-apply-all)
- (gnus-score-remove-from-cache gnus-score-custom-file)
- (let ((file gnus-score-custom-file)
- (score gnus-score-alist)
- emacs-lisp-mode-hook)
- (save-excursion
- (set-buffer (get-buffer-create "*Score*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (pp score (current-buffer))
- (gnus-make-directory (file-name-directory file))
- (write-region (point-min) (point-max) file nil 'silent)
- (kill-buffer (current-buffer))))
- (gnus-message 4 "Saved"))
-
-(provide 'gnus-edit)
-
-;;; gnus-edit.el end here
diff --git a/lisp/gnus-ems.el b/lisp/gnus-ems.el
deleted file mode 100644
index fb19e6cf711..00000000000
--- a/lisp/gnus-ems.el
+++ /dev/null
@@ -1,242 +0,0 @@
-;;; gnus-ems.el --- functions for making Gnus work under different Emacsen
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(eval-when-compile (require 'cl))
-
-(defvar gnus-mouse-2 [mouse-2])
-
-(defalias 'gnus-make-overlay 'make-overlay)
-(defalias 'gnus-overlay-put 'overlay-put)
-(defalias 'gnus-move-overlay 'move-overlay)
-(defalias 'gnus-overlay-end 'overlay-end)
-(defalias 'gnus-extent-detached-p 'ignore)
-(defalias 'gnus-extent-start-open 'ignore)
-(defalias 'gnus-set-text-properties 'set-text-properties)
-(defalias 'gnus-group-remove-excess-properties 'ignore)
-(defalias 'gnus-topic-remove-excess-properties 'ignore)
-(defalias 'gnus-appt-select-lowest-window 'appt-select-lowest-window)
-(defalias 'gnus-mail-strip-quoted-names 'mail-strip-quoted-names)
-(defalias 'gnus-make-local-hook 'make-local-hook)
-(defalias 'gnus-add-hook 'add-hook)
-(defalias 'gnus-character-to-event 'identity)
-(defalias 'gnus-add-text-properties 'add-text-properties)
-(defalias 'gnus-put-text-property 'put-text-property)
-(defalias 'gnus-mode-line-buffer-identification 'identity)
-
-
-(eval-and-compile
- (autoload 'gnus-xmas-define "gnus-xmas")
- (autoload 'gnus-xmas-redefine "gnus-xmas")
- (autoload 'appt-select-lowest-window "appt.el"))
-
-(or (fboundp 'mail-file-babyl-p)
- (fset 'mail-file-babyl-p 'rmail-file-p))
-
-;;; Mule functions.
-
-(defun gnus-mule-cite-add-face (number prefix face)
- ;; At line NUMBER, ignore PREFIX and add FACE to the rest of the line.
- (if face
- (let ((inhibit-point-motion-hooks t)
- from to)
- (goto-line number)
- (if (boundp 'MULE)
- (forward-char (chars-in-string prefix))
- (forward-char (length prefix)))
- (skip-chars-forward " \t")
- (setq from (point))
- (end-of-line 1)
- (skip-chars-backward " \t")
- (setq to (point))
- (if (< from to)
- (gnus-overlay-put (gnus-make-overlay from to) 'face face)))))
-
-(defun gnus-mule-max-width-function (el max-width)
- (` (let* ((val (eval (, el)))
- (valstr (if (numberp val)
- (int-to-string val) val)))
- (if (> (length valstr) (, max-width))
- (truncate-string valstr (, max-width))
- valstr))))
-
-(eval-and-compile
- (if (string-match "XEmacs\\|Lucid" emacs-version)
- ()
-
- (defvar gnus-mouse-face-prop 'mouse-face
- "Property used for highlighting mouse regions.")
-
- (defvar gnus-article-x-face-command
- "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | xv -quit -"
- "String or function to be executed to display an X-Face header.
-If it is a string, the command will be executed in a sub-shell
-asynchronously. The compressed face will be piped to this command.")
-
- ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
- (defvar gnus-display-type
- (condition-case nil
- (let ((display-resource (x-get-resource ".displayType" "DisplayType")))
- (cond (display-resource (intern (downcase display-resource)))
- ((x-display-color-p) 'color)
- ((x-display-grayscale-p) 'grayscale)
- (t 'mono)))
- (error 'mono))
- "A symbol indicating the display Emacs is running under.
-The symbol should be one of `color', `grayscale' or `mono'. If Emacs
-guesses this display attribute wrongly, either set this variable in
-your `~/.emacs' or set the resource `Emacs.displayType' in your
-`~/.Xdefaults'. See also `gnus-background-mode'.
-
-This is a meta-variable that will affect what default values other
-variables get. You would normally not change this variable, but
-pounce directly on the real variables themselves.")
-
- (defvar gnus-background-mode
- (condition-case nil
- (let ((bg-resource (x-get-resource ".backgroundMode"
- "BackgroundMode"))
- (params (frame-parameters)))
- (cond (bg-resource (intern (downcase bg-resource)))
- ((and (cdr (assq 'background-color params))
- (< (apply '+ (x-color-values
- (cdr (assq 'background-color params))))
- (* (apply '+ (x-color-values "white")) .6)))
- 'dark)
- (t 'light)))
- (error 'light))
- "A symbol indicating the Emacs background brightness.
-The symbol should be one of `light' or `dark'.
-If Emacs guesses this frame attribute wrongly, either set this variable in
-your `~/.emacs' or set the resource `Emacs.backgroundMode' in your
-`~/.Xdefaults'.
-See also `gnus-display-type'.
-
-This is a meta-variable that will affect what default values other
-variables get. You would normally not change this variable, but
-pounce directly on the real variables themselves."))
-
- (cond
- ((string-match "XEmacs\\|Lucid" emacs-version)
- (gnus-xmas-define))
-
- ((or (not (boundp 'emacs-minor-version))
- (< emacs-minor-version 30))
- ;; Remove the `intangible' prop.
- (let ((props (and (boundp 'gnus-hidden-properties)
- gnus-hidden-properties)))
- (while (and props (not (eq (car (cdr props)) 'intangible)))
- (setq props (cdr props)))
- (and props (setcdr props (cdr (cdr (cdr props))))))
- (or (fboundp 'buffer-substring-no-properties)
- (defun buffer-substring-no-properties (beg end)
- (format "%s" (buffer-substring beg end)))))
-
- ((boundp 'MULE)
- (provide 'gnusutil))))
-
-(eval-and-compile
- (cond
- ((not window-system)
- (defun gnus-dummy-func (&rest args))
- (let ((funcs '(mouse-set-point set-face-foreground
- set-face-background x-popup-menu)))
- (while funcs
- (or (fboundp (car funcs))
- (fset (car funcs) 'gnus-dummy-func))
- (setq funcs (cdr funcs))))))
- (or (fboundp 'file-regular-p)
- (defun file-regular-p (file)
- (and (not (file-directory-p file))
- (not (file-symlink-p file))
- (file-exists-p file))))
- (or (fboundp 'face-list)
- (defun face-list (&rest args))))
-
-(eval-and-compile
- (let ((case-fold-search t))
- (cond
- ((string-match "windows-nt\\|os/2\\|emx" (format "%s" system-type))
- (setq nnheader-file-name-translation-alist
- (append nnheader-file-name-translation-alist
- '((?: . ?_)
- (?+ . ?-))))))))
-
-(defvar gnus-tmp-unread)
-(defvar gnus-tmp-replied)
-(defvar gnus-tmp-score-char)
-(defvar gnus-tmp-indentation)
-(defvar gnus-tmp-opening-bracket)
-(defvar gnus-tmp-lines)
-(defvar gnus-tmp-name)
-(defvar gnus-tmp-closing-bracket)
-(defvar gnus-tmp-subject-or-nil)
-
-(defun gnus-ems-redefine ()
- (cond
- ((string-match "XEmacs\\|Lucid" emacs-version)
- (gnus-xmas-redefine))
-
- ((boundp 'MULE)
- ;; Mule definitions
- (defalias 'gnus-truncate-string 'truncate-string)
-
- (fset 'gnus-summary-make-display-table (lambda () nil))
- (fset 'gnus-cite-add-face 'gnus-mule-cite-add-face)
- (fset 'gnus-max-width-function 'gnus-mule-max-width-function)
-
- (if (boundp 'gnus-check-before-posting)
- (setq gnus-check-before-posting
- (delq 'long-lines
- (delq 'control-chars gnus-check-before-posting))))
-
- (defun gnus-summary-line-format-spec ()
- (insert gnus-tmp-unread gnus-tmp-replied
- gnus-tmp-score-char gnus-tmp-indentation)
- (put-text-property
- (point)
- (progn
- (insert
- gnus-tmp-opening-bracket
- (format "%4d: %-20s"
- gnus-tmp-lines
- (if (> (length gnus-tmp-name) 20)
- (truncate-string gnus-tmp-name 20)
- gnus-tmp-name))
- gnus-tmp-closing-bracket)
- (point))
- gnus-mouse-face-prop gnus-mouse-face)
- (insert " " gnus-tmp-subject-or-nil "\n"))
- )))
-
-
-(provide 'gnus-ems)
-
-;; Local Variables:
-;; byte-compile-warnings: '(redefine callargs)
-;; End:
-
-;;; gnus-ems.el ends here
diff --git a/lisp/gnus-gl.el b/lisp/gnus-gl.el
deleted file mode 100644
index 54997d2c9a9..00000000000
--- a/lisp/gnus-gl.el
+++ /dev/null
@@ -1,872 +0,0 @@
-;;; gnus-gl.el --- an interface to GroupLens for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Brad Miller <bmiller@cs.umn.edu>
-;; Keywords: news, score
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; GroupLens software and documentation is copyright (c) 1995 by Paul
-;; Resnick (Massachusetts Institute of Technology); Brad Miller, John
-;; Riedl, Jon Herlocker, and Joseph Konstan (University of Minnesota),
-;; and David Maltz (Carnegie-Mellon University).
-;;
-;; Permission to use, copy, modify, and distribute this documentation
-;; for non-commercial and commercial purposes without fee is hereby
-;; granted provided that this copyright notice and permission notice
-;; appears in all copies and that the names of the individuals and
-;; institutions holding this copyright are not used in advertising or
-;; publicity pertaining to this software without specific, written
-;; prior permission. The copyright holders make no representations
-;; about the suitability of this software and documentation for any
-;; purpose. It is provided ``as is'' without express or implied
-;; warranty.
-;;
-;; The copyright holders request that they be notified of
-;; modifications of this code. Please send electronic mail to
-;; grouplens@cs.umn.edu for more information or to announce derived
-;; works.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Author: Brad Miller
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; User Documentation:
-;; To use GroupLens you must load this file.
-;; You must also register a pseudonym with the Better Bit Bureau.
-;; http://www.cs.umn.edu/Research/GroupLens
-;;
-;; ---------------- For your .emacs or .gnus file ----------------
-;;
-;; As of version 2.5, grouplens now works as a minor mode of
-;; gnus-summary-mode. To get make that work you just need a couple of
-;; hooks.
-;; (setq gnus-use-grouplens t)
-;; (setq grouplens-pseudonym "")
-;; (setq grouplens-bbb-host "grouplens.cs.umn.edu")
-;;
-;; (setq gnus-summary-default-score 0)
-;;
-;; USING GROUPLENS
-;; How do I Rate an article??
-;; Before you type n to go to the next article, hit a number from 1-5
-;; Type r in the summary buffer and you will be prompted.
-;; Note that when you're in grouplens-minor-mode 'r' maskes the
-;; usual reply binding for 'r'
-;;
-;; What if, Gasp, I find a bug???
-;; Please type M-x gnus-gl-submit-bug-report. This will set up a
-;; mail buffer with the state of variables and buffers that will help
-;; me debug the problem. A short description up front would help too!
-;;
-;; How do I display the prediction for an aritcle:
-;; If you set the gnus-summary-line-format as shown above, the score
-;; (prediction) will be shown automatically.
-;;
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Programmer Notes
-;; 10/9/95
-;; gnus-scores-articles contains the articles
-;; When scoring is done, the call tree looks something like:
-;; gnus-possibly-score-headers
-;; ==> gnus-score-headers
-;; ==> gnus-score-load-file
-;; ==> get-all-mids (from the eval form)
-;;
-;; it would be nice to have one that gets called after all the other
-;; headers have been scored.
-;; we may want a variable gnus-grouplens-scale-factor
-;; and gnus-grouplens-offset this would probably be either -3 or 0
-;; to make the scores centered around zero or not.
-;; Notes 10/12/95
-;; According to Lars, Norse god of gnus, the simple way to insert a
-;; call to an external function is to have a function added to the
-;; variable gnus-score-find-files-function This new function
-;; gnus-grouplens-score-alist will return a core alist that
-;; has (("message-id" ("<message-id-xxxx>" score) ("<message-id-xxxy>" score))
-;; This seems like it would be pretty inefficient, though workable.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; TODO
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; 3. Add some more ways to rate messages
-;; 4. Better error handling for token timeouts.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; bugs
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-
-;;; Code:
-
-(require 'gnus-score)
-(require 'cl)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;; User variables
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defvar gnus-summary-grouplens-line-format
- "%U%R%z%l%I%(%[%4L: %-20,20n%]%) %s\n"
- "*The line format spec in summary GroupLens mode buffers.")
-
-(defvar grouplens-pseudonym ""
- "User's pseudonym. This pseudonym is obtained during the registration process")
-
-(defvar grouplens-bbb-host "grouplens.cs.umn.edu"
- "Host where the bbbd is running" )
-
-(defvar grouplens-bbb-port 9000
- "Port where the bbbd is listening" )
-
-(defvar grouplens-newsgroups
- '("comp.lang.c++" "rec.humor" "rec.food.recipes" "comp.groupware"
- "mn.general" "rec.arts.movies" "rec.arts.movies.current-films"
- "comp.lang.java" "comp.os.linux.announce" "comp.os.linux.misc"
- "comp.os.linux.development.apps" "comp.os.linux.development.system")
- "*Groups that are part of the GroupLens experiment.")
-
-(defvar grouplens-prediction-display 'prediction-spot
- "valid values are:
- prediction-spot -- an * corresponding to the prediction between 1 and 5,
- confidence-interval -- a numeric confidence interval
- prediction-bar -- |##### | the longer the bar, the better the article,
- confidence-bar -- | ----- } the prediction is in the middle of the bar,
- confidence-spot -- ) * | the spot gets bigger with more confidence,
- prediction-num -- plain-old numeric value,
- confidence-plus-minus -- prediction +/i confidence")
-
-(defvar grouplens-score-offset 0
- "Offset the prediction by this value.
-Setting this variable to -2 would have the following effect on
-GroupLens scores:
-
- 1 --> -2
- 2 --> -1
- 3 --> 0
- 4 --> 1
- 5 --> 2
-
-The reason is that a user might want to do this is to combine
-GroupLens predictions with scores calculated by other score methods.")
-
-(defvar grouplens-score-scale-factor 1
- "This variable allows the user to magnify the effect of GroupLens scores.
-The scale factor is applied after the offset.")
-
-(defvar gnus-grouplens-override-scoring 'override
- "Tell Grouplens to override the normal Gnus scoring mechanism.
-GroupLens scores can be combined with gnus scores in one of three ways.
-'override -- just use grouplens predictions for grouplens groups
-'combine -- combine grouplens scores with gnus scores
-'separate -- treat grouplens scores completely separate from gnus")
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;; Program global variables
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defvar grouplens-bbb-token "0"
- "Current session token number")
-
-(defvar grouplens-bbb-process nil
- "Process Id of current bbbd network stream process")
-
-(defvar grouplens-bbb-buffer nil
- "Buffer associated with the BBBD process")
-
-(defvar grouplens-rating-alist nil
- "Current set of message-id rating pairs")
-
-(defvar grouplens-current-hashtable (make-hash-table :test 'equal :size 100))
-;; this seems like a pretty ugly way to get around the problem, but If
-;; I don't do this, then the compiler complains when I call gethash
-;;
-(eval-when-compile (setq grouplens-current-hashtable
- (make-hash-table :test 'equal :size 100)))
-
-(defvar grouplens-current-group nil)
-
-(defvar bbb-mid-list nil)
-
-(defvar bbb-alist nil)
-
-(defvar bbb-timeout-secs 10
- "Number of seconds to wait for some response from the BBB.
-If this times out we give up and assume that something has died..." )
-
-(defvar grouplens-previous-article nil
- "Message-ID of the last article read.")
-
-(defvar bbb-read-point)
-(defvar bbb-response-point)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;; Utility Functions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun bbb-connect-to-bbbd (host port)
- (unless grouplens-bbb-buffer
- (setq grouplens-bbb-buffer
- (get-buffer-create (format " *BBBD trace: %s*" host)))
- (save-excursion
- (set-buffer grouplens-bbb-buffer)
- (make-local-variable 'bbb-read-point)
- (setq bbb-read-point (point-min))))
- ;; clear the trace buffer of old output
- (save-excursion
- (set-buffer grouplens-bbb-buffer)
- (erase-buffer))
- ;; open the connection to the server
- (setq grouplens-bbb-process nil)
- (catch 'done
- (condition-case error
- (setq grouplens-bbb-process
- (open-network-stream "BBBD" grouplens-bbb-buffer host port))
- (error (gnus-message 3 "Error: Failed to connect to BBB")
- nil))
- (and (null grouplens-bbb-process)
- (throw 'done nil))
- ;; (set-process-filter grouplens-bbb-process 'bbb-process-filter)
- (save-excursion
- (set-buffer grouplens-bbb-buffer)
- (setq bbb-read-point (point-min))
- (or (bbb-read-response grouplens-bbb-process)
- (throw 'done nil))))
- grouplens-bbb-process)
-
-;; (defun bbb-process-filter (process output)
-;; (save-excursion
-;; (set-buffer (bbb-process-buffer process))
-;; (goto-char (point-max))
-;; (insert output)))
-
-(defun bbb-send-command (process command)
- (goto-char (point-max))
- (insert command)
- (insert "\r\n")
- (setq bbb-read-point (point))
- (setq bbb-response-point (point))
- (set-marker (process-mark process) (point)) ; process output also comes here
- (process-send-string process command)
- (process-send-string process "\r\n"))
-
-(defun bbb-read-response (process) ; &optional return-response-string)
- "This function eats the initial response of OK or ERROR from the BBB."
- (let ((case-fold-search nil)
- match-end)
- (goto-char bbb-read-point)
- (while (and (not (search-forward "\r\n" nil t))
- (accept-process-output process bbb-timeout-secs))
- (goto-char bbb-read-point))
- (setq match-end (point))
- (goto-char bbb-read-point)
- (setq bbb-read-point match-end)
- (looking-at "OK")))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;; Login Functions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun bbb-login ()
- "return the token number if login is successful, otherwise return nil"
- (interactive)
- (setq grouplens-bbb-token nil)
- (if (not (equal grouplens-pseudonym ""))
- (let ((bbb-process
- (bbb-connect-to-bbbd grouplens-bbb-host grouplens-bbb-port)))
- (if bbb-process
- (save-excursion
- (set-buffer (process-buffer bbb-process))
- (bbb-send-command bbb-process
- (concat "login " grouplens-pseudonym))
- (if (bbb-read-response bbb-process)
- (setq grouplens-bbb-token (bbb-extract-token-number))
- (gnus-message 3 "Error: Grouplens login failed")))))
- (gnus-message 3 "Error: you must set a pseudonym"))
- grouplens-bbb-token)
-
-(defun bbb-extract-token-number ()
- (let ((token-pos (search-forward "token=" nil t) ))
- (if (looking-at "[0-9]+")
- (buffer-substring token-pos (match-end 0)))))
-
-(gnus-add-shutdown 'bbb-logout 'gnus)
-
-(defun bbb-logout ()
- "logout of bbb session"
- (let ((bbb-process
- (bbb-connect-to-bbbd grouplens-bbb-host grouplens-bbb-port)))
- (if bbb-process
- (save-excursion
- (set-buffer (process-buffer bbb-process))
- (bbb-send-command bbb-process (concat "logout " grouplens-bbb-token))
- (bbb-read-response bbb-process))
- nil)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;; Get Predictions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun bbb-build-mid-scores-alist (groupname)
- "this function can be called as part of the function to return the
-list of score files to use. See the gnus variable
-gnus-score-find-score-files-function.
-
-*Note:* If you want to use grouplens scores along with calculated scores,
-you should see the offset and scale variables. At this point, I don't
-recommend using both scores and grouplens predictions together."
- (setq grouplens-current-group groupname)
- (if (member groupname grouplens-newsgroups)
- (let* ((mid-list (bbb-get-all-mids))
- (predict-list (bbb-get-predictions mid-list groupname)))
- (setq grouplens-previous-article nil)
- ;; scores-alist should be a list of lists:
- ;; ((("message-id" ("<mid1>" score1 nil s) ("<mid2> score2 nil s))))
- ;;`((("message-id" . ,predict-list))) ; Yes, this is the return value
- (list (list (list (append (list "message-id") predict-list)))))
- nil))
-
-(defun bbb-get-predictions (midlist groupname)
- "Ask the bbb for predictions, and build up the score alist."
- (if (or (null grouplens-bbb-token)
- (equal grouplens-bbb-token "0"))
- (progn
- (gnus-message 3 "Error: You are not logged in to a BBB")
- nil)
- (gnus-message 5 "Fetching Predictions...")
- (let (predict-list
- (predict-command (bbb-build-predict-command midlist groupname
- grouplens-bbb-token))
- (bbb-process (bbb-connect-to-bbbd grouplens-bbb-host
- grouplens-bbb-port)))
- (if bbb-process
- (save-excursion
- (set-buffer (process-buffer bbb-process))
- (bbb-send-command bbb-process predict-command)
- (if (bbb-read-response bbb-process)
- (setq predict-list (bbb-get-prediction-response bbb-process))
- (gnus-message 1 "Invalid Token, login and try again")
- (ding))))
- (setq bbb-alist predict-list))))
-
-(defun bbb-get-all-mids ()
- (let ((index (nth 1 (assoc "message-id" gnus-header-index)))
- (articles gnus-newsgroup-headers)
- art this)
- (setq bbb-mid-list nil)
- (while articles
- (progn (setq art (car articles)
- this (aref art index)
- articles (cdr articles))
- (setq bbb-mid-list (cons this bbb-mid-list))))
- bbb-mid-list))
-
-(defun bbb-build-predict-command (mlist grpname token)
- (let ((cmd (concat "getpredictions " token " " grpname "\r\n"))
- art)
- (while mlist
- (setq art (car mlist)
- cmd (concat cmd art "\r\n")
- mlist (cdr mlist)))
- (setq cmd (concat cmd ".\r\n"))
- cmd))
-
-(defun bbb-get-prediction-response (process)
- (let ((case-fold-search nil)
- match-end)
- (goto-char bbb-read-point)
- (while (and (not (search-forward ".\r\n" nil t))
- (accept-process-output process bbb-timeout-secs))
- (goto-char bbb-read-point))
- (setq match-end (point))
- (goto-char (+ bbb-response-point 4)) ;; we ought to be right before OK
- (bbb-build-response-alist)))
-
-;; build-response-alist assumes that the cursor has been positioned at
-;; the first line of the list of mid/rating pairs. For now we will
-;; use a prediction of 99 to signify no prediction. Ultimately, we
-;; should just ignore messages with no predictions.
-(defun bbb-build-response-alist ()
- (let ((resp nil)
- (match-end (point)))
- (setq grouplens-current-hashtable (make-hash-table :test 'equal :size 100))
- (while
- (cond ((looking-at "\\(<.*>\\) :nopred=")
- (push `(,(bbb-get-mid) ,gnus-summary-default-score nil s) resp)
- (forward-line 1)
- t)
- ((looking-at "\\(<.*>\\) :pred=\\([0-9]\.[0-9][0-9]\\) :conflow=\\([0-9]\.[0-9][0-9]\\) :confhigh=\\([0-9]\.[0-9][0-9]\\)")
- (push `(,(bbb-get-mid) ,(bbb-get-pred) nil s) resp)
- (cl-puthash (bbb-get-mid)
- (list (bbb-get-pred) (bbb-get-confl) (bbb-get-confh))
- grouplens-current-hashtable)
- (forward-line 1)
- t)
- ((looking-at "\\(<.*>\\) :pred=\\([0-9]\.[0-9][0-9]\\)")
- (push `(,(bbb-get-mid) ,(bbb-get-pred) nil s) resp)
- (cl-puthash (bbb-get-mid)
- (list (bbb-get-pred) 0 0)
- grouplens-current-hashtable)
- (forward-line 1)
- t)
- (t nil)))
- resp))
-
-;; these two functions assume that there is an active match lying
-;; around. Where the first parenthesized expression is the
-;; message-id, and the second is the prediction. Since gnus assumes
-;; that scores are integer values?? we round the prediction.
-(defun bbb-get-mid ()
- (buffer-substring (match-beginning 1) (match-end 1)))
-
-(defun bbb-get-pred ()
- (let ((tpred (string-to-number (buffer-substring
- (match-beginning 2)
- (match-end 2)))))
- (if (> tpred 0)
- (round (* grouplens-score-scale-factor (+ grouplens-score-offset tpred)))
- 1)))
-
-(defun bbb-get-confl ()
- (string-to-number (buffer-substring (match-beginning 3) (match-end 3))))
-
-(defun bbb-get-confh ()
- (string-to-number (buffer-substring (match-beginning 4) (match-end 4))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;; Prediction Display
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defconst grplens-rating-range 4.0)
-(defconst grplens-maxrating 5)
-(defconst grplens-minrating 1)
-(defconst grplens-predstringsize 12)
-
-(defvar gnus-tmp-score)
-(defun bbb-grouplens-score (header)
- (if (eq gnus-grouplens-override-scoring 'separate)
- (bbb-grouplens-other-score header)
- (let* ((rate-string (make-string 12 ? ))
- (mid (aref header (nth 1 (assoc "message-id" gnus-header-index))))
- (hashent (gethash mid grouplens-current-hashtable))
- (iscore gnus-tmp-score)
- (low (car (cdr hashent)))
- (high (car (cdr (cdr hashent)))))
- (aset rate-string 0 ?|)
- (aset rate-string 11 ?|)
- (unless (member grouplens-current-group grouplens-newsgroups)
- (unless (equal grouplens-prediction-display 'prediction-num)
- (cond ((< iscore 0)
- (setq iscore 1))
- ((> iscore 5)
- (setq iscore 5))))
- (setq low 0)
- (setq high 0))
- (if (and (bbb-valid-score iscore)
- (not (null mid)))
- (cond
- ;; prediction-spot
- ((equal grouplens-prediction-display 'prediction-spot)
- (setq rate-string (bbb-fmt-prediction-spot rate-string iscore)))
- ;; confidence-interval
- ((equal grouplens-prediction-display 'confidence-interval)
- (setq rate-string (bbb-fmt-confidence-interval iscore low high)))
- ;; prediction-bar
- ((equal grouplens-prediction-display 'prediction-bar)
- (setq rate-string (bbb-fmt-prediction-bar rate-string iscore)))
- ;; confidence-bar
- ((equal grouplens-prediction-display 'confidence-bar)
- (setq rate-string (format "| %4.2f |" iscore)))
- ;; confidence-spot
- ((equal grouplens-prediction-display 'confidence-spot)
- (setq rate-string (format "| %4.2f |" iscore)))
- ;; prediction-num
- ((equal grouplens-prediction-display 'prediction-num)
- (setq rate-string (bbb-fmt-prediction-num iscore)))
- ;; confidence-plus-minus
- ((equal grouplens-prediction-display 'confidence-plus-minus)
- (setq rate-string (bbb-fmt-confidence-plus-minus iscore low high))
- )
- (t (gnus-message 3 "Invalid prediction display type")))
- (aset rate-string 5 ?N) (aset rate-string 6 ?A))
- rate-string)))
-
-;;
-;; Gnus user format function that doesn't depend on
-;; bbb-build-mid-scores-alist being used as the score function, but is
-;; instead called from gnus-select-group-hook. -- LAB
-(defun bbb-grouplens-other-score (header)
- (if (not (member grouplens-current-group grouplens-newsgroups))
- ;; Return an empty string
- ""
- (let* ((rate-string (make-string 12 ? ))
- (mid (aref header (nth 1 (assoc "message-id" gnus-header-index))))
- (hashent (gethash mid grouplens-current-hashtable))
- (pred (or (nth 0 hashent) 0))
- (low (nth 1 hashent))
- (high (nth 2 hashent)))
- ;; Init rate-string
- (aset rate-string 0 ?|)
- (aset rate-string 11 ?|)
- (unless (equal grouplens-prediction-display 'prediction-num)
- (cond ((< pred 0)
- (setq pred 1))
- ((> pred 5)
- (setq pred 5))))
- ;; If no entry in BBB hash mark rate string as NA and return
- (cond
- ((null hashent)
- (aset rate-string 5 ?N)
- (aset rate-string 6 ?A)
- rate-string)
-
- ((equal grouplens-prediction-display 'prediction-spot)
- (bbb-fmt-prediction-spot rate-string pred))
-
- ((equal grouplens-prediction-display 'confidence-interval)
- (bbb-fmt-confidence-interval pred low high))
-
- ((equal grouplens-prediction-display 'prediction-bar)
- (bbb-fmt-prediction-bar rate-string pred))
-
- ((equal grouplens-prediction-display 'confidence-bar)
- (format "| %4.2f |" pred))
-
- ((equal grouplens-prediction-display 'confidence-spot)
- (format "| %4.2f |" pred))
-
- ((equal grouplens-prediction-display 'prediction-num)
- (bbb-fmt-prediction-num pred))
-
- ((equal grouplens-prediction-display 'confidence-plus-minus)
- (bbb-fmt-confidence-plus-minus pred low high))
-
- (t
- (gnus-message 3 "Invalid prediction display type")
- (aset rate-string 0 ?|)
- (aset rate-string 11 ?|)
- rate-string)))))
-
-(defun bbb-valid-score (score)
- (or (equal grouplens-prediction-display 'prediction-num)
- (and (>= score grplens-minrating)
- (<= score grplens-maxrating))))
-
-(defun bbb-requires-confidence (format-type)
- (or (equal format-type 'confidence-plus-minus)
- (equal format-type 'confidence-spot)
- (equal format-type 'confidence-interval)))
-
-(defun bbb-have-confidence (clow chigh)
- (not (or (null clow)
- (null chigh))))
-
-(defun bbb-fmt-prediction-spot (rate-string score)
- (aset rate-string
- (round (* (/ (- score grplens-minrating) grplens-rating-range)
- (+ (- grplens-predstringsize 4) 1.49)))
- ?*)
- rate-string)
-
-(defun bbb-fmt-confidence-interval (score low high)
- (if (bbb-have-confidence low high)
- (format "|%4.2f-%4.2f |" low high)
- (bbb-fmt-prediction-num score)))
-
-(defun bbb-fmt-confidence-plus-minus (score low high)
- (if (bbb-have-confidence low high)
- (format "|%3.1f+/-%4.2f|" score (/ (- high low) 2.0))
- (bbb-fmt-prediction-num score)))
-
-(defun bbb-fmt-prediction-bar (rate-string score)
- (let* ((i 1)
- (step (/ grplens-rating-range (- grplens-predstringsize 4)))
- (half-step (/ step 2))
- (loc (- grplens-minrating half-step)))
- (while (< i (- grplens-predstringsize 2))
- (if (> score loc)
- (aset rate-string i ?#)
- (aset rate-string i ? ))
- (setq i (+ i 1))
- (setq loc (+ loc step)))
- )
- rate-string)
-
-(defun bbb-fmt-prediction-num (score)
- (format "| %4.2f |" score))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;; Put Ratings
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; The message-id for the current article can be found in
-;; (aref gnus-current-headers (nth 1 (assoc "message-id" gnus-header-index)))
-
-(defun bbb-put-ratings ()
- (if (and grouplens-rating-alist
- (member gnus-newsgroup-name grouplens-newsgroups))
- (let ((bbb-process (bbb-connect-to-bbbd grouplens-bbb-host
- grouplens-bbb-port))
- (rate-command (bbb-build-rate-command grouplens-rating-alist)))
- (if bbb-process
- (save-excursion
- (set-buffer (process-buffer bbb-process))
- (gnus-message 5 "Sending Ratings...")
- (bbb-send-command bbb-process rate-command)
- (if (bbb-read-response bbb-process)
- (setq grouplens-rating-alist nil)
- (gnus-message 1
- "Token timed out: call bbb-login and quit again")
- (ding))
- (gnus-message 5 "Sending Ratings...Done"))
- (gnus-message 3 "No BBB connection")))
- (setq grouplens-rating-alist nil)))
-
-(defun bbb-build-rate-command (rate-alist)
- (let (this
- (cmd (concat "putratings " grouplens-bbb-token
- " " grouplens-current-group " \r\n")))
- (while rate-alist
- (setq this (car rate-alist)
- cmd (concat cmd (car this) " :rating=" (cadr this) ".00"
- " :time=" (cddr this) "\r\n")
- rate-alist (cdr rate-alist)))
- (concat cmd ".\r\n")))
-
-;; Interactive rating functions.
-(defun bbb-summary-rate-article (rating &optional midin)
- (interactive "nRating: ")
- (when (member gnus-newsgroup-name grouplens-newsgroups)
- (let ((mid (or midin (bbb-get-current-id))))
- (if (and rating
- (>= rating grplens-minrating)
- (<= rating grplens-maxrating)
- mid)
- (let ((oldrating (assoc mid grouplens-rating-alist)))
- (if oldrating
- (setcdr oldrating (cons rating 0))
- (push `(,mid . (,rating . 0)) grouplens-rating-alist))
- (gnus-summary-mark-article nil (int-to-string rating)))
- (gnus-message 3 "Invalid rating")))))
-
-(defun grouplens-next-unread-article (rating)
- "Select unread article after current one."
- (interactive "P")
- (if rating (bbb-summary-rate-article rating))
- (gnus-summary-next-unread-article))
-
-(defun grouplens-best-unread-article (rating)
- "Select unread article after current one."
- (interactive "P")
- (if rating (bbb-summary-rate-article rating))
- (gnus-summary-best-unread-article))
-
-(defun grouplens-summary-catchup-and-exit (rating)
- "Mark all articles not marked as unread in this newsgroup as read,
- then exit. If prefix argument ALL is non-nil, all articles are
- marked as read."
- (interactive "P")
- (if rating
- (bbb-summary-rate-article rating))
- (if (numberp rating)
- (gnus-summary-catchup-and-exit)
- (gnus-summary-catchup-and-exit rating)))
-
-(defun grouplens-score-thread (score)
- "Raise the score of the articles in the current thread with SCORE."
- (interactive "nRating: ")
- (let (e)
- (save-excursion
- (let ((articles (gnus-summary-articles-in-thread)))
- (while articles
- (gnus-summary-goto-subject (car articles))
- (gnus-set-global-variables)
- (bbb-summary-rate-article score
- (mail-header-id
- (gnus-summary-article-header
- (car articles))))
- (setq articles (cdr articles))))
- (setq e (point)))
- (let ((gnus-summary-check-current t))
- (or (zerop (gnus-summary-next-subject 1 t))
- (goto-char e))))
- (gnus-summary-recenter)
- (gnus-summary-position-point)
- (gnus-set-mode-line 'summary))
-
-
-(defun bbb-get-current-id ()
- (if gnus-current-headers
- (aref gnus-current-headers
- (nth 1 (assoc "message-id" gnus-header-index)))
- (gnus-message 3 "You must select an article before you rate it")))
-
-(defun bbb-grouplens-group-p (group)
- "Say whether GROUP is a GroupLens group."
- (if (member group grouplens-newsgroups) " (GroupLens Enhanced)" ""))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; TIME SPENT READING
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defvar grouplens-current-starting-time nil)
-
-(defun grouplens-start-timer ()
- (setq grouplens-current-starting-time (current-time)))
-
-(defun grouplens-elapsed-time ()
- (let ((et (bbb-time-float (current-time))))
- (- et (bbb-time-float grouplens-current-starting-time))))
-
-(defun bbb-time-float (timeval)
- (+ (* (car timeval) 65536)
- (cadr timeval)))
-
-(defun grouplens-do-time ()
- (when (member gnus-newsgroup-name grouplens-newsgroups)
- (when grouplens-previous-article
- (let ((elapsed-time (grouplens-elapsed-time))
- (oldrating (assoc grouplens-previous-article
- grouplens-rating-alist)))
- (if (not oldrating)
- (push `(,grouplens-previous-article . (0 . ,elapsed-time))
- grouplens-rating-alist)
- (setcdr oldrating (cons (cadr oldrating) elapsed-time)))))
- (grouplens-start-timer)
- (setq grouplens-previous-article (bbb-get-current-id))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; BUG REPORTING
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defconst gnus-gl-version "gnus-gl.el 2.12")
-(defconst gnus-gl-maintainer-address "grouplens-bug@cs.umn.edu")
-(defun gnus-gl-submit-bug-report ()
- "Submit via mail a bug report on gnus-gl"
- (interactive)
- (require 'reporter)
- (reporter-submit-bug-report gnus-gl-maintainer-address
- (concat "gnus-gl.el " gnus-gl-version)
- (list 'grouplens-pseudonym
- 'grouplens-bbb-host
- 'grouplens-bbb-port
- 'grouplens-newsgroups
- 'grouplens-bbb-token
- 'grouplens-bbb-process
- 'grouplens-current-group
- 'grouplens-previous-article
- 'grouplens-mid-list
- 'bbb-alist)
- nil
- 'gnus-gl-get-trace))
-
-(defun gnus-gl-get-trace ()
- "Insert the contents of the BBBD trace buffer"
- (if grouplens-bbb-buffer (insert-buffer grouplens-bbb-buffer)))
-
-;;;
-;;; Additions to make gnus-grouplens-mode Warning Warning!!
-;;; This version of the gnus-grouplens-mode does
-;;; not work with gnus-5.x. The "old" way of
-;;; setting up GroupLens still works however.
-;;;
-(defvar gnus-grouplens-mode nil
- "Minor mode for providing a GroupLens interface in Gnus summary buffers.")
-
-(defvar gnus-grouplens-mode-map nil)
-
-(unless gnus-grouplens-mode-map
- (setq gnus-grouplens-mode-map (make-keymap))
- (gnus-define-keys
- gnus-grouplens-mode-map
- "n" grouplens-next-unread-article
- "r" bbb-summary-rate-article
- "k" grouplens-score-thread
- "c" grouplens-summary-catchup-and-exit
- "," grouplens-best-unread-article))
-
-(defun gnus-grouplens-make-menu-bar ()
- (unless (boundp 'gnus-grouplens-menu)
- (easy-menu-define
- gnus-grouplens-menu gnus-grouplens-mode-map ""
- '("GroupLens"
- ["Login" bbb-login t]
- ["Rate" bbb-summary-rate-article t]
- ["Next article" grouplens-next-unread-article t]
- ["Best article" grouplens-best-unread-article t]
- ["Raise thread" grouplens-score-thread t]
- ["Report bugs" gnus-gl-submit-bug-report t]))))
-
-(defun gnus-grouplens-mode (&optional arg)
- "Minor mode for providing a GroupLens interface in Gnus summary buffers."
- (interactive "P")
- (when (and (eq major-mode 'gnus-summary-mode)
- (member gnus-newsgroup-name grouplens-newsgroups))
- (make-local-variable 'gnus-grouplens-mode)
- (setq gnus-grouplens-mode
- (if (null arg) (not gnus-grouplens-mode)
- (> (prefix-numeric-value arg) 0)))
- (when gnus-grouplens-mode
- (if (not (fboundp 'make-local-hook))
- (add-hook 'gnus-select-article-hook 'grouplens-do-time)
- (make-local-hook 'gnus-select-article-hook)
- (add-hook 'gnus-select-article-hook 'grouplens-do-time nil 'local))
- (if (not (fboundp 'make-local-hook))
- (add-hook 'gnus-exit-group-hook 'bbb-put-ratings)
- (make-local-hook 'gnus-exit-group-hook)
- (add-hook 'gnus-exit-group-hook 'bbb-put-ratings nil 'local))
- (make-local-variable 'gnus-score-find-score-files-function)
- (cond ((eq gnus-grouplens-override-scoring 'combine)
- ;; either add bbb-buld-mid-scores-alist to a list
- ;; or make a list
- (if (listp gnus-score-find-score-files-function)
- (setq gnus-score-find-score-files-function
- (append 'bbb-build-mid-scores-alist
- gnus-score-find-score-files-function ))
- (setq gnus-score-find-score-files-function
- (list gnus-score-find-score-files-function
- 'bbb-build-mid-scores-alist))))
- ;; leave the gnus-score-find-score-files variable alone
- ((eq gnus-grouplens-override-scoring 'separate)
- (add-hook 'gnus-select-group-hook
- '(lambda()
- (bbb-build-mid-scores-alist gnus-newsgroup-name))))
- ;; default is to override
- (t (setq gnus-score-find-score-files-function
- 'bbb-build-mid-scores-alist)))
- (make-local-variable 'gnus-summary-line-format)
- (setq gnus-summary-line-format
- gnus-summary-grouplens-line-format)
- (make-local-variable 'gnus-summary-line-format-spec)
- (setq gnus-summary-line-format-spec nil)
-
- ;; Set up the menu.
- (when (and menu-bar-mode
- (gnus-visual-p 'grouplens-menu 'menu))
- (gnus-grouplens-make-menu-bar))
- (unless (assq 'gnus-grouplens-mode minor-mode-alist)
- (push '(gnus-grouplens-mode " GroupLens") minor-mode-alist))
- (unless (assq 'gnus-grouplens-mode minor-mode-map-alist)
- (push (cons 'gnus-grouplens-mode gnus-grouplens-mode-map)
- minor-mode-map-alist))
- (run-hooks 'gnus-grouplens-mode-hook))))
-
-(provide 'gnus-gl)
-
-;;; gnus-gl.el ends here
diff --git a/lisp/gnus-kill.el b/lisp/gnus-kill.el
deleted file mode 100644
index 8c88c2347b8..00000000000
--- a/lisp/gnus-kill.el
+++ /dev/null
@@ -1,655 +0,0 @@
-;;; gnus-kill.el --- kill commands for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'gnus)
-(eval-when-compile (require 'cl))
-
-(defvar gnus-kill-file-mode-hook nil
- "*A hook for Gnus kill file mode.")
-
-(defvar gnus-kill-expiry-days 7
- "*Number of days before expiring unused kill file entries.")
-
-(defvar gnus-kill-save-kill-file nil
- "*If non-nil, will save kill files after processing them.")
-
-(defvar gnus-winconf-kill-file nil)
-
-
-
-(defmacro gnus-raise (field expression level)
- `(gnus-kill ,field ,expression
- (function (gnus-summary-raise-score ,level)) t))
-
-(defmacro gnus-lower (field expression level)
- `(gnus-kill ,field ,expression
- (function (gnus-summary-raise-score (- ,level))) t))
-
-;;;
-;;; Gnus Kill File Mode
-;;;
-
-(defvar gnus-kill-file-mode-map nil)
-
-(unless gnus-kill-file-mode-map
- (gnus-define-keymap
- (setq gnus-kill-file-mode-map (copy-keymap emacs-lisp-mode-map))
- "\C-c\C-k\C-s" gnus-kill-file-kill-by-subject
- "\C-c\C-k\C-a" gnus-kill-file-kill-by-author
- "\C-c\C-k\C-t" gnus-kill-file-kill-by-thread
- "\C-c\C-k\C-x" gnus-kill-file-kill-by-xref
- "\C-c\C-a" gnus-kill-file-apply-buffer
- "\C-c\C-e" gnus-kill-file-apply-last-sexp
- "\C-c\C-c" gnus-kill-file-exit))
-
-(defun gnus-kill-file-mode ()
- "Major mode for editing kill files.
-
-If you are using this mode - you probably shouldn't. Kill files
-perform badly and paint with a pretty broad brush. Score files, on
-the other hand, are vastly faster (40x speedup) and give you more
-control over what to do.
-
-In addition to Emacs-Lisp Mode, the following commands are available:
-
-\\{gnus-kill-file-mode-map}
-
- A kill file contains Lisp expressions to be applied to a selected
-newsgroup. The purpose is to mark articles as read on the basis of
-some set of regexps. A global kill file is applied to every newsgroup,
-and a local kill file is applied to a specified newsgroup. Since a
-global kill file is applied to every newsgroup, for better performance
-use a local one.
-
- A kill file can contain any kind of Emacs Lisp expressions expected
-to be evaluated in the Summary buffer. Writing Lisp programs for this
-purpose is not so easy because the internal working of Gnus must be
-well-known. For this reason, Gnus provides a general function which
-does this easily for non-Lisp programmers.
-
- The `gnus-kill' function executes commands available in Summary Mode
-by their key sequences. `gnus-kill' should be called with FIELD,
-REGEXP and optional COMMAND and ALL. FIELD is a string representing
-the header field or an empty string. If FIELD is an empty string, the
-entire article body is searched for. REGEXP is a string which is
-compared with FIELD value. COMMAND is a string representing a valid
-key sequence in Summary mode or Lisp expression. COMMAND defaults to
-'(gnus-summary-mark-as-read nil \"X\"). Make sure that COMMAND is
-executed in the Summary buffer. If the second optional argument ALL
-is non-nil, the COMMAND is applied to articles which are already
-marked as read or unread. Articles which are marked are skipped over
-by default.
-
- For example, if you want to mark articles of which subjects contain
-the string `AI' as read, a possible kill file may look like:
-
- (gnus-kill \"Subject\" \"AI\")
-
- If you want to mark articles with `D' instead of `X', you can use
-the following expression:
-
- (gnus-kill \"Subject\" \"AI\" \"d\")
-
-In this example it is assumed that the command
-`gnus-summary-mark-as-read-forward' is assigned to `d' in Summary Mode.
-
- It is possible to delete unnecessary headers which are marked with
-`X' in a kill file as follows:
-
- (gnus-expunge \"X\")
-
- If the Summary buffer is empty after applying kill files, Gnus will
-exit the selected newsgroup normally. If headers which are marked
-with `D' are deleted in a kill file, it is impossible to read articles
-which are marked as read in the previous Gnus sessions. Marks other
-than `D' should be used for articles which should really be deleted.
-
-Entry to this mode calls emacs-lisp-mode-hook and
-gnus-kill-file-mode-hook with no arguments, if that value is non-nil."
- (interactive)
- (kill-all-local-variables)
- (use-local-map gnus-kill-file-mode-map)
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (setq major-mode 'gnus-kill-file-mode)
- (setq mode-name "Kill")
- (lisp-mode-variables nil)
- (run-hooks 'emacs-lisp-mode-hook 'gnus-kill-file-mode-hook))
-
-(defun gnus-kill-file-edit-file (newsgroup)
- "Begin editing a kill file for NEWSGROUP.
-If NEWSGROUP is nil, the global kill file is selected."
- (interactive "sNewsgroup: ")
- (let ((file (gnus-newsgroup-kill-file newsgroup)))
- (gnus-make-directory (file-name-directory file))
- ;; Save current window configuration if this is first invocation.
- (or (and (get-file-buffer file)
- (get-buffer-window (get-file-buffer file)))
- (setq gnus-winconf-kill-file (current-window-configuration)))
- ;; Hack windows.
- (let ((buffer (find-file-noselect file)))
- (cond ((get-buffer-window buffer)
- (pop-to-buffer buffer))
- ((eq major-mode 'gnus-group-mode)
- (gnus-configure-windows 'group) ;Take all windows.
- (pop-to-buffer buffer))
- ((eq major-mode 'gnus-summary-mode)
- (gnus-configure-windows 'article)
- (pop-to-buffer gnus-article-buffer)
- (bury-buffer gnus-article-buffer)
- (switch-to-buffer buffer))
- (t ;No good rules.
- (find-file-other-window file))))
- (gnus-kill-file-mode)))
-
-;; Fix by Sudish Joseph <joseph@cis.ohio-state.edu>.
-(defun gnus-kill-set-kill-buffer ()
- (let* ((file (gnus-newsgroup-kill-file gnus-newsgroup-name))
- (buffer (find-file-noselect file)))
- (set-buffer buffer)
- (gnus-kill-file-mode)
- (bury-buffer buffer)))
-
-(defun gnus-kill-file-enter-kill (field regexp &optional dont-move)
- ;; Enter kill file entry.
- ;; FIELD: String containing the name of the header field to kill.
- ;; REGEXP: The string to kill.
- (save-excursion
- (let (string)
- (or (eq major-mode 'gnus-kill-file-mode)
- (gnus-kill-set-kill-buffer))
- (unless dont-move
- (goto-char (point-max)))
- (insert (setq string (format "(gnus-kill %S %S)\n" field regexp)))
- (gnus-kill-file-apply-string string))))
-
-(defun gnus-kill-file-kill-by-subject ()
- "Kill by subject."
- (interactive)
- (gnus-kill-file-enter-kill
- "Subject"
- (if (vectorp gnus-current-headers)
- (regexp-quote
- (gnus-simplify-subject (mail-header-subject gnus-current-headers)))
- "") t))
-
-(defun gnus-kill-file-kill-by-author ()
- "Kill by author."
- (interactive)
- (gnus-kill-file-enter-kill
- "From"
- (if (vectorp gnus-current-headers)
- (regexp-quote (mail-header-from gnus-current-headers))
- "") t))
-
-(defun gnus-kill-file-kill-by-thread ()
- "Kill by author."
- (interactive)
- (gnus-kill-file-enter-kill
- "References"
- (if (vectorp gnus-current-headers)
- (regexp-quote (mail-header-id gnus-current-headers))
- "")))
-
-(defun gnus-kill-file-kill-by-xref ()
- "Kill by Xref."
- (interactive)
- (let ((xref (and (vectorp gnus-current-headers)
- (mail-header-xref gnus-current-headers)))
- (start 0)
- group)
- (if xref
- (while (string-match " \\([^ \t]+\\):" xref start)
- (setq start (match-end 0))
- (if (not (string=
- (setq group
- (substring xref (match-beginning 1) (match-end 1)))
- gnus-newsgroup-name))
- (gnus-kill-file-enter-kill
- "Xref" (concat " " (regexp-quote group) ":") t)))
- (gnus-kill-file-enter-kill "Xref" "" t))))
-
-(defun gnus-kill-file-raise-followups-to-author (level)
- "Raise score for all followups to the current author."
- (interactive "p")
- (let ((name (mail-header-from gnus-current-headers))
- string)
- (save-excursion
- (gnus-kill-set-kill-buffer)
- (goto-char (point-min))
- (setq name (read-string (concat "Add " level
- " to followup articles to: ")
- (regexp-quote name)))
- (setq
- string
- (format
- "(gnus-kill %S %S '(gnus-summary-temporarily-raise-by-thread %S))\n"
- "From" name level))
- (insert string)
- (gnus-kill-file-apply-string string))
- (gnus-message
- 6 "Added temporary score file entry for followups to %s." name)))
-
-(defun gnus-kill-file-apply-buffer ()
- "Apply current buffer to current newsgroup."
- (interactive)
- (if (and gnus-current-kill-article
- (get-buffer gnus-summary-buffer))
- ;; Assume newsgroup is selected.
- (gnus-kill-file-apply-string (buffer-string))
- (ding) (gnus-message 2 "No newsgroup is selected.")))
-
-(defun gnus-kill-file-apply-string (string)
- "Apply STRING to current newsgroup."
- (interactive)
- (let ((string (concat "(progn \n" string "\n)")))
- (save-excursion
- (save-window-excursion
- (pop-to-buffer gnus-summary-buffer)
- (eval (car (read-from-string string)))))))
-
-(defun gnus-kill-file-apply-last-sexp ()
- "Apply sexp before point in current buffer to current newsgroup."
- (interactive)
- (if (and gnus-current-kill-article
- (get-buffer gnus-summary-buffer))
- ;; Assume newsgroup is selected.
- (let ((string
- (buffer-substring
- (save-excursion (forward-sexp -1) (point)) (point))))
- (save-excursion
- (save-window-excursion
- (pop-to-buffer gnus-summary-buffer)
- (eval (car (read-from-string string))))))
- (ding) (gnus-message 2 "No newsgroup is selected.")))
-
-(defun gnus-kill-file-exit ()
- "Save a kill file, then return to the previous buffer."
- (interactive)
- (save-buffer)
- (let ((killbuf (current-buffer)))
- ;; We don't want to return to article buffer.
- (and (get-buffer gnus-article-buffer)
- (bury-buffer gnus-article-buffer))
- ;; Delete the KILL file windows.
- (delete-windows-on killbuf)
- ;; Restore last window configuration if available.
- (and gnus-winconf-kill-file
- (set-window-configuration gnus-winconf-kill-file))
- (setq gnus-winconf-kill-file nil)
- ;; Kill the KILL file buffer. Suggested by tale@pawl.rpi.edu.
- (kill-buffer killbuf)))
-
-;; For kill files
-
-(defun gnus-Newsgroup-kill-file (newsgroup)
- "Return the name of a kill file for NEWSGROUP.
-If NEWSGROUP is nil, return the global kill file instead."
- (cond ((or (null newsgroup)
- (string-equal newsgroup ""))
- ;; The global kill file is placed at top of the directory.
- (expand-file-name gnus-kill-file-name gnus-kill-files-directory))
- (gnus-use-long-file-name
- ;; Append ".KILL" to capitalized newsgroup name.
- (expand-file-name (concat (gnus-capitalize-newsgroup newsgroup)
- "." gnus-kill-file-name)
- gnus-kill-files-directory))
- (t
- ;; Place "KILL" under the hierarchical directory.
- (expand-file-name (concat (gnus-newsgroup-directory-form newsgroup)
- "/" gnus-kill-file-name)
- gnus-kill-files-directory))))
-
-(defun gnus-expunge (marks)
- "Remove lines marked with MARKS."
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (gnus-summary-limit-to-marks marks 'reverse)))
-
-(defun gnus-apply-kill-file-unless-scored ()
- "Apply .KILL file, unless a .SCORE file for the same newsgroup exists."
- (cond ((file-exists-p (gnus-score-file-name gnus-newsgroup-name))
- ;; Ignores global KILL.
- (if (file-exists-p (gnus-newsgroup-kill-file gnus-newsgroup-name))
- (gnus-message 3 "Note: Ignoring %s.KILL; preferring .SCORE"
- gnus-newsgroup-name))
- 0)
- ((or (file-exists-p (gnus-newsgroup-kill-file nil))
- (file-exists-p (gnus-newsgroup-kill-file gnus-newsgroup-name)))
- (gnus-apply-kill-file-internal))
- (t
- 0)))
-
-(defun gnus-apply-kill-file-internal ()
- "Apply a kill file to the current newsgroup.
-Returns the number of articles marked as read."
- (let* ((kill-files (list (gnus-newsgroup-kill-file nil)
- (gnus-newsgroup-kill-file gnus-newsgroup-name)))
- (unreads (length gnus-newsgroup-unreads))
- (gnus-summary-inhibit-highlight t)
- beg)
- (setq gnus-newsgroup-kill-headers nil)
- ;; If there are any previously scored articles, we remove these
- ;; from the `gnus-newsgroup-headers' list that the score functions
- ;; will see. This is probably pretty wasteful when it comes to
- ;; conses, but is, I think, faster than having to assq in every
- ;; single score function.
- (let ((files kill-files))
- (while files
- (if (file-exists-p (car files))
- (let ((headers gnus-newsgroup-headers))
- (if gnus-kill-killed
- (setq gnus-newsgroup-kill-headers
- (mapcar (lambda (header) (mail-header-number header))
- headers))
- (while headers
- (or (gnus-member-of-range
- (mail-header-number (car headers))
- gnus-newsgroup-killed)
- (setq gnus-newsgroup-kill-headers
- (cons (mail-header-number (car headers))
- gnus-newsgroup-kill-headers)))
- (setq headers (cdr headers))))
- (setq files nil))
- (setq files (cdr files)))))
- (if (not gnus-newsgroup-kill-headers)
- ()
- (save-window-excursion
- (save-excursion
- (while kill-files
- (if (not (file-exists-p (car kill-files)))
- ()
- (gnus-message 6 "Processing kill file %s..." (car kill-files))
- (find-file (car kill-files))
- (gnus-add-current-to-buffer-list)
- (goto-char (point-min))
-
- (if (consp (condition-case nil (read (current-buffer))
- (error nil)))
- (gnus-kill-parse-gnus-kill-file)
- (gnus-kill-parse-rn-kill-file))
-
- (gnus-message
- 6 "Processing kill file %s...done" (car kill-files)))
- (setq kill-files (cdr kill-files)))))
-
- (gnus-set-mode-line 'summary)
-
- (if beg
- (let ((nunreads (- unreads (length gnus-newsgroup-unreads))))
- (or (eq nunreads 0)
- (gnus-message 6 "Marked %d articles as read" nunreads))
- nunreads)
- 0))))
-
-;; Parse a Gnus killfile.
-(defun gnus-score-insert-help (string alist idx)
- (save-excursion
- (pop-to-buffer "*Score Help*")
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert string ":\n\n")
- (while alist
- (insert (format " %c: %s\n" (caar alist) (nth idx (car alist))))
- (setq alist (cdr alist)))))
-
-(defun gnus-kill-parse-gnus-kill-file ()
- (goto-char (point-min))
- (gnus-kill-file-mode)
- (let (beg form)
- (while (progn
- (setq beg (point))
- (setq form (condition-case () (read (current-buffer))
- (error nil))))
- (or (listp form)
- (error "Illegal kill entry (possibly rn kill file?): %s" form))
- (if (or (eq (car form) 'gnus-kill)
- (eq (car form) 'gnus-raise)
- (eq (car form) 'gnus-lower))
- (progn
- (delete-region beg (point))
- (insert (or (eval form) "")))
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (condition-case () (eval form) (error nil)))))
- (and (buffer-modified-p)
- gnus-kill-save-kill-file
- (save-buffer))
- (set-buffer-modified-p nil)))
-
-;; Parse an rn killfile.
-(defun gnus-kill-parse-rn-kill-file ()
- (goto-char (point-min))
- (gnus-kill-file-mode)
- (let ((mod-to-header
- '((?a . "")
- (?h . "")
- (?f . "from")
- (?: . "subject")))
- (com-to-com
- '((?m . " ")
- (?j . "X")))
- pattern modifier commands)
- (while (not (eobp))
- (if (not (looking-at "[ \t]*/\\([^/]*\\)/\\([ahfcH]\\)?:\\([a-z=:]*\\)"))
- ()
- (setq pattern (buffer-substring (match-beginning 1) (match-end 1)))
- (setq modifier (if (match-beginning 2) (char-after (match-beginning 2))
- ?s))
- (setq commands (buffer-substring (match-beginning 3) (match-end 3)))
-
- ;; The "f:+" command marks everything *but* the matches as read,
- ;; so we simply first match everything as read, and then unmark
- ;; PATTERN later.
- (and (string-match "\\+" commands)
- (progn
- (gnus-kill "from" ".")
- (setq commands "m")))
-
- (gnus-kill
- (or (cdr (assq modifier mod-to-header)) "subject")
- pattern
- (if (string-match "m" commands)
- '(gnus-summary-mark-as-unread nil " ")
- '(gnus-summary-mark-as-read nil "X"))
- nil t))
- (forward-line 1))))
-
-;; Kill changes and new format by suggested by JWZ and Sudish Joseph
-;; <joseph@cis.ohio-state.edu>.
-(defun gnus-kill (field regexp &optional exe-command all silent)
- "If FIELD of an article matches REGEXP, execute COMMAND.
-Optional 1st argument COMMAND is default to
- (gnus-summary-mark-as-read nil \"X\").
-If optional 2nd argument ALL is non-nil, articles marked are also applied to.
-If FIELD is an empty string (or nil), entire article body is searched for.
-COMMAND must be a lisp expression or a string representing a key sequence."
- ;; We don't want to change current point nor window configuration.
- (let ((old-buffer (current-buffer)))
- (save-excursion
- (save-window-excursion
- ;; Selected window must be summary buffer to execute keyboard
- ;; macros correctly. See command_loop_1.
- (switch-to-buffer gnus-summary-buffer 'norecord)
- (goto-char (point-min)) ;From the beginning.
- (let ((kill-list regexp)
- (date (current-time-string))
- (command (or exe-command '(gnus-summary-mark-as-read
- nil gnus-kill-file-mark)))
- kill kdate prev)
- (if (listp kill-list)
- ;; It is a list.
- (if (not (consp (cdr kill-list)))
- ;; It's of the form (regexp . date).
- (if (zerop (gnus-execute field (car kill-list)
- command nil (not all)))
- (if (> (gnus-days-between date (cdr kill-list))
- gnus-kill-expiry-days)
- (setq regexp nil))
- (setcdr kill-list date))
- (while (setq kill (car kill-list))
- (if (consp kill)
- ;; It's a temporary kill.
- (progn
- (setq kdate (cdr kill))
- (if (zerop (gnus-execute
- field (car kill) command nil (not all)))
- (if (> (gnus-days-between date kdate)
- gnus-kill-expiry-days)
- ;; Time limit has been exceeded, so we
- ;; remove the match.
- (if prev
- (setcdr prev (cdr kill-list))
- (setq regexp (cdr regexp))))
- ;; Successful kill. Set the date to today.
- (setcdr kill date)))
- ;; It's a permanent kill.
- (gnus-execute field kill command nil (not all)))
- (setq prev kill-list)
- (setq kill-list (cdr kill-list))))
- (gnus-execute field kill-list command nil (not all))))))
- (switch-to-buffer old-buffer)
- (if (and (eq major-mode 'gnus-kill-file-mode) regexp (not silent))
- (gnus-pp-gnus-kill
- (nconc (list 'gnus-kill field
- (if (consp regexp) (list 'quote regexp) regexp))
- (if (or exe-command all) (list (list 'quote exe-command)))
- (if all (list t) nil))))))
-
-(defun gnus-pp-gnus-kill (object)
- (if (or (not (consp (nth 2 object)))
- (not (consp (cdr (nth 2 object))))
- (and (eq 'quote (car (nth 2 object)))
- (not (consp (cdadr (nth 2 object))))))
- (concat "\n" (prin1-to-string object))
- (save-excursion
- (set-buffer (get-buffer-create "*Gnus PP*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert (format "\n(%S %S\n '(" (nth 0 object) (nth 1 object)))
- (let ((klist (cadr (nth 2 object)))
- (first t))
- (while klist
- (insert (if first (progn (setq first nil) "") "\n ")
- (prin1-to-string (car klist)))
- (setq klist (cdr klist))))
- (insert ")")
- (and (nth 3 object)
- (insert "\n "
- (if (and (consp (nth 3 object))
- (not (eq 'quote (car (nth 3 object)))))
- "'" "")
- (prin1-to-string (nth 3 object))))
- (and (nth 4 object)
- (insert "\n t"))
- (insert ")")
- (prog1
- (buffer-substring (point-min) (point-max))
- (kill-buffer (current-buffer))))))
-
-(defun gnus-execute-1 (function regexp form header)
- (save-excursion
- (let (did-kill)
- (if (null header)
- nil ;Nothing to do.
- (if function
- ;; Compare with header field.
- (let (value)
- (and header
- (progn
- (setq value (funcall function header))
- ;; Number (Lines:) or symbol must be converted to string.
- (or (stringp value)
- (setq value (prin1-to-string value)))
- (setq did-kill (string-match regexp value)))
- (cond ((stringp form) ;Keyboard macro.
- (execute-kbd-macro form))
- ((gnus-functionp form)
- (funcall form))
- (t
- (eval form)))))
- ;; Search article body.
- (let ((gnus-current-article nil) ;Save article pointer.
- (gnus-last-article nil)
- (gnus-break-pages nil) ;No need to break pages.
- (gnus-mark-article-hook nil)) ;Inhibit marking as read.
- (gnus-message
- 6 "Searching for article: %d..." (mail-header-number header))
- (gnus-article-setup-buffer)
- (gnus-article-prepare (mail-header-number header) t)
- (if (save-excursion
- (set-buffer gnus-article-buffer)
- (goto-char (point-min))
- (setq did-kill (re-search-forward regexp nil t)))
- (if (stringp form) ;Keyboard macro.
- (execute-kbd-macro form)
- (eval form))))))
- did-kill)))
-
-(defun gnus-execute (field regexp form &optional backward ignore-marked)
- "If FIELD of article header matches REGEXP, execute lisp FORM (or a string).
-If FIELD is an empty string (or nil), entire article body is searched for.
-If optional 1st argument BACKWARD is non-nil, do backward instead.
-If optional 2nd argument IGNORE-MARKED is non-nil, articles which are
-marked as read or ticked are ignored."
- (save-excursion
- (let ((killed-no 0)
- function article header)
- (cond
- ;; Search body.
- ((or (null field)
- (string-equal field ""))
- (setq function nil))
- ;; Get access function of header field.
- ((fboundp
- (setq function
- (intern-soft
- (concat "mail-header-" (downcase field)))))
- (setq function `(lambda (h) (,function h))))
- ;; Signal error.
- (t
- (error "Unknown header field: \"%s\"" field)))
- ;; Starting from the current article.
- (while (or
- ;; First article.
- (and (not article)
- (setq article (gnus-summary-article-number)))
- ;; Find later articles.
- (setq article
- (gnus-summary-search-forward
- (not ignore-marked) nil backward)))
- (and (or (null gnus-newsgroup-kill-headers)
- (memq article gnus-newsgroup-kill-headers))
- (vectorp (setq header (gnus-summary-article-header article)))
- (gnus-execute-1 function regexp form header)
- (setq killed-no (1+ killed-no))))
- ;; Return the number of killed articles.
- killed-no)))
-
-(provide 'gnus-kill)
-
-;;; gnus-kill.el ends here
diff --git a/lisp/gnus-mh.el b/lisp/gnus-mh.el
deleted file mode 100644
index 02317a22eeb..00000000000
--- a/lisp/gnus-mh.el
+++ /dev/null
@@ -1,105 +0,0 @@
-;;; gnus-mh.el --- mh-e interface for Gnus
-;; Copyright (C) 1994,95,96 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; 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).
-
-;;; Code:
-
-(require 'mh-e)
-(require 'mh-comp)
-(require 'gnus)
-(require 'gnus-msg)
-(eval-when-compile (require 'cl))
-
-(defun gnus-summary-save-article-folder (&optional arg)
- "Append the current article to an mh folder.
-If N is a positive number, save the N next articles.
-If N is a negative number, save the N previous articles.
-If N is nil and any articles have been marked with the process mark,
-save those articles instead."
- (interactive "P")
- (let ((gnus-default-article-saver 'gnus-summary-save-in-folder))
- (gnus-summary-save-article arg)))
-
-(defun gnus-summary-save-in-folder (&optional folder)
- "Save this article to MH folder (using `rcvstore' in MH library).
-Optional argument FOLDER specifies folder name."
- ;; Thanks to yuki@flab.Fujitsu.JUNET and ohm@kaba.junet.
- (mh-find-path)
- (let ((folder
- (cond ((and (eq folder 'default)
- gnus-newsgroup-last-folder)
- gnus-newsgroup-last-folder)
- (folder folder)
- (t (mh-prompt-for-folder
- "Save article in"
- (funcall gnus-folder-save-name gnus-newsgroup-name
- gnus-current-headers gnus-newsgroup-last-folder)
- t))))
- (errbuf (get-buffer-create " *Gnus rcvstore*"))
- ;; Find the rcvstore program.
- (exec-path (if mh-lib (cons mh-lib exec-path) exec-path)))
- (gnus-eval-in-buffer-window gnus-original-article-buffer
- (save-restriction
- (widen)
- (unwind-protect
- (call-process-region
- (point-min) (point-max) "rcvstore" nil errbuf nil folder)
- (set-buffer errbuf)
- (if (zerop (buffer-size))
- (message "Article saved in folder: %s" folder)
- (message "%s" (buffer-string)))
- (kill-buffer errbuf))))
- (setq gnus-newsgroup-last-folder folder)))
-
-(defun gnus-Folder-save-name (newsgroup headers &optional last-folder)
- "Generate folder name from NEWSGROUP, HEADERS, and optional LAST-FOLDER.
-If variable `gnus-use-long-file-name' is nil, it is +News.group.
-Otherwise, it is like +news/group."
- (or last-folder
- (concat "+"
- (if gnus-use-long-file-name
- (gnus-capitalize-newsgroup newsgroup)
- (gnus-newsgroup-directory-form newsgroup)))))
-
-(defun gnus-folder-save-name (newsgroup headers &optional last-folder)
- "Generate folder name from NEWSGROUP, HEADERS, and optional LAST-FOLDER.
-If variable `gnus-use-long-file-name' is nil, it is +news.group.
-Otherwise, it is like +news/group."
- (or last-folder
- (concat "+"
- (if gnus-use-long-file-name
- newsgroup
- (gnus-newsgroup-directory-form newsgroup)))))
-
-(provide 'gnus-mh)
-
-;;; gnus-mh.el ends here
diff --git a/lisp/gnus-msg.el b/lisp/gnus-msg.el
deleted file mode 100644
index 53e915af4c2..00000000000
--- a/lisp/gnus-msg.el
+++ /dev/null
@@ -1,929 +0,0 @@
-;;; gnus-msg.el --- mail and post interface for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'gnus)
-(require 'gnus-ems)
-(require 'message)
-(eval-when-compile (require 'cl))
-
-;; Added by Sudish Joseph <joseph@cis.ohio-state.edu>.
-(defvar gnus-post-method nil
- "*Preferred method for posting USENET news.
-If this variable is nil, Gnus will use the current method to decide
-which method to use when posting. If it is non-nil, it will override
-the current method. This method will not be used in mail groups and
-the like, only in \"real\" newsgroups.
-
-The value must be a valid method as discussed in the documentation of
-`gnus-select-method'. It can also be a list of methods. If that is
-the case, the user will be queried for what select method to use when
-posting.")
-
-(defvar gnus-outgoing-message-group nil
- "*All outgoing messages will be put in this group.
-If you want to store all your outgoing mail and articles in the group
-\"nnml:archive\", you set this variable to that value. This variable
-can also be a list of group names.
-
-If you want to have greater control over what group to put each
-message in, you can set this variable to a function that checks the
-current newsgroup name and then returns a suitable group name (or list
-of names).")
-
-(defvar gnus-mailing-list-groups nil
- "*Regexp matching groups that are really mailing lists.
-This is useful when you're reading a mailing list that has been
-gatewayed to a newsgroup, and you want to followup to an article in
-the group.")
-
-(defvar gnus-sent-message-ids-file
- (nnheader-concat gnus-directory "Sent-Message-IDs")
- "File where Gnus saves a cache of sent message ids.")
-
-(defvar gnus-sent-message-ids-length 1000
- "The number of sent Message-IDs to save.")
-
-;;; Internal variables.
-
-(defvar gnus-message-buffer "*Mail Gnus*")
-(defvar gnus-article-copy nil)
-(defvar gnus-last-posting-server nil)
-
-(eval-and-compile
- (autoload 'gnus-uu-post-news "gnus-uu" nil t)
- (autoload 'news-setup "rnewspost")
- (autoload 'news-reply-mode "rnewspost")
- (autoload 'rmail-dont-reply-to "mail-utils")
- (autoload 'rmail-output "rmailout"))
-
-
-;;;
-;;; Gnus Posting Functions
-;;;
-
-(gnus-define-keys
- (gnus-summary-send-map "S" gnus-summary-mode-map)
- "p" gnus-summary-post-news
- "f" gnus-summary-followup
- "F" gnus-summary-followup-with-original
- "c" gnus-summary-cancel-article
- "s" gnus-summary-supersede-article
- "r" gnus-summary-reply
- "R" gnus-summary-reply-with-original
- "m" gnus-summary-mail-other-window
- "u" gnus-uu-post-news
- "om" gnus-summary-mail-forward
- "op" gnus-summary-post-forward
- "Om" gnus-uu-digest-mail-forward
- "Op" gnus-uu-digest-post-forward)
-
-(gnus-define-keys
- (gnus-send-bounce-map "D" gnus-summary-send-map)
- "b" gnus-summary-resend-bounced-mail
-; "c" gnus-summary-send-draft
- "r" gnus-summary-resend-message)
-
-;;; Internal functions.
-
-(defvar gnus-article-reply nil)
-(defmacro gnus-setup-message (config &rest forms)
- (let ((winconf (make-symbol "winconf"))
- (buffer (make-symbol "buffer"))
- (article (make-symbol "article")))
- `(let ((,winconf (current-window-configuration))
- (,buffer (current-buffer))
- (,article (and gnus-article-reply (gnus-summary-article-number)))
- (message-header-setup-hook
- (copy-sequence message-header-setup-hook)))
- (add-hook 'message-header-setup-hook 'gnus-inews-insert-gcc)
- (add-hook 'message-header-setup-hook 'gnus-inews-insert-archive-gcc)
- ,@forms
- (gnus-inews-add-send-actions ,winconf ,buffer ,article)
- (setq gnus-message-buffer (current-buffer))
- (gnus-configure-windows ,config t))))
-
-(defun gnus-inews-add-send-actions (winconf buffer article)
- (gnus-make-local-hook 'message-sent-hook)
- (gnus-add-hook 'message-sent-hook 'gnus-inews-do-gcc nil t)
- (setq message-post-method
- `(lambda (arg)
- (gnus-post-method arg ,gnus-newsgroup-name)))
- (setq message-newsreader (setq message-mailer (gnus-extended-version)))
- (message-add-action
- `(set-window-configuration ,winconf) 'exit 'postpone 'kill)
- (message-add-action
- `(when (buffer-name ,buffer)
- (save-excursion
- (set-buffer ,buffer)
- ,(when article
- `(gnus-summary-mark-article-as-replied ,article))))
- 'send))
-
-(put 'gnus-setup-message 'lisp-indent-function 1)
-(put 'gnus-setup-message 'lisp-indent-hook 1)
-(put 'gnus-setup-message 'edebug-form-spec '(form body))
-
-;;; Post news commands of Gnus group mode and summary mode
-
-(defun gnus-group-mail ()
- "Start composing a mail."
- (interactive)
- (gnus-setup-message 'message
- (message-mail)))
-
-(defun gnus-group-post-news (&optional arg)
- "Start composing a news message.
-If ARG, post to the group under point.
-If ARG is 1, prompt for a group name."
- (interactive "P")
- ;; Bind this variable here to make message mode hooks
- ;; work ok.
- (let ((gnus-newsgroup-name
- (if arg
- (if (= 1 (prefix-numeric-value arg))
- (completing-read "Newsgroup: " gnus-active-hashtb nil
- (gnus-read-active-file-p))
- (gnus-group-group-name))
- "")))
- (gnus-post-news 'post gnus-newsgroup-name)))
-
-(defun gnus-summary-post-news ()
- "Start composing a news message."
- (interactive)
- (gnus-set-global-variables)
- (gnus-post-news 'post gnus-newsgroup-name))
-
-(defun gnus-summary-followup (yank &optional force-news)
- "Compose a followup to an article.
-If prefix argument YANK is non-nil, original article is yanked automatically."
- (interactive
- (list (and current-prefix-arg
- (gnus-summary-work-articles 1))))
- (gnus-set-global-variables)
- (when yank
- (gnus-summary-goto-subject (car yank)))
- (save-window-excursion
- (gnus-summary-select-article))
- (let ((headers (gnus-summary-article-header (gnus-summary-article-number)))
- (gnus-newsgroup-name gnus-newsgroup-name))
- ;; Send a followup.
- (gnus-post-news nil gnus-newsgroup-name
- headers gnus-article-buffer
- yank nil force-news)))
-
-(defun gnus-summary-followup-with-original (n &optional force-news)
- "Compose a followup to an article and include the original article."
- (interactive "P")
- (gnus-summary-followup (gnus-summary-work-articles n) force-news))
-
-(defun gnus-inews-yank-articles (articles)
- (let (beg article)
- (while (setq article (pop articles))
- (save-window-excursion
- (set-buffer gnus-summary-buffer)
- (gnus-summary-select-article nil nil nil article)
- (gnus-summary-remove-process-mark article))
- (gnus-copy-article-buffer)
- (let ((message-reply-buffer gnus-article-copy)
- (message-reply-headers gnus-current-headers))
- (message-yank-original)
- (setq beg (or beg (mark t))))
- (when articles (insert "\n")))
-
- (push-mark)
- (goto-char beg)))
-
-(defun gnus-summary-cancel-article (n)
- "Cancel an article you posted."
- (interactive "P")
- (gnus-set-global-variables)
- (let ((articles (gnus-summary-work-articles n))
- (message-post-method
- `(lambda (arg)
- (gnus-post-method nil ,gnus-newsgroup-name)))
- article)
- (while (setq article (pop articles))
- (when (gnus-summary-select-article t nil nil article)
- (when (gnus-eval-in-buffer-window
- gnus-original-article-buffer (message-cancel-news))
- (gnus-summary-mark-as-read article gnus-canceled-mark)
- (gnus-cache-remove-article 1))
- (gnus-article-hide-headers-if-wanted))
- (gnus-summary-remove-process-mark article))))
-
-(defun gnus-summary-supersede-article ()
- "Compose an article that will supersede a previous article.
-This is done simply by taking the old article and adding a Supersedes
-header line with the old Message-ID."
- (interactive)
- (gnus-set-global-variables)
- (let ((article (gnus-summary-article-number)))
- (gnus-setup-message 'reply-yank
- (gnus-summary-select-article t)
- (set-buffer gnus-original-article-buffer)
- (message-supersede)
- (push
- `((lambda ()
- (gnus-cache-possibly-remove-article ,article nil nil nil t)))
- message-send-actions))))
-
-
-
-(defun gnus-copy-article-buffer (&optional article-buffer)
- ;; make a copy of the article buffer with all text properties removed
- ;; this copy is in the buffer gnus-article-copy.
- ;; if ARTICLE-BUFFER is nil, gnus-article-buffer is used
- ;; this buffer should be passed to all mail/news reply/post routines.
- (setq gnus-article-copy (get-buffer-create " *gnus article copy*"))
- (buffer-disable-undo gnus-article-copy)
- (or (memq gnus-article-copy gnus-buffer-list)
- (setq gnus-buffer-list (cons gnus-article-copy gnus-buffer-list)))
- (let ((article-buffer (or article-buffer gnus-article-buffer))
- end beg contents)
- (when (and (get-buffer article-buffer)
- (buffer-name (get-buffer article-buffer)))
- (save-excursion
- (set-buffer article-buffer)
- (save-restriction
- (widen)
- (setq contents (format "%s" (buffer-string)))
- (set-buffer gnus-original-article-buffer)
- (goto-char (point-min))
- (while (looking-at message-unix-mail-delimiter)
- (forward-line 1))
- (setq beg (point))
- (setq end (or (search-forward "\n\n" nil t) (point)))
- (set-buffer gnus-article-copy)
- (erase-buffer)
- (insert contents)
- (delete-region (goto-char (point-min))
- (or (search-forward "\n\n" nil t) (point)))
- (insert-buffer-substring gnus-original-article-buffer beg end)))
- gnus-article-copy)))
-
-(defun gnus-post-news (post &optional group header article-buffer yank subject
- force-news)
- (when article-buffer
- (gnus-copy-article-buffer))
- (let ((gnus-article-reply article-buffer))
- (gnus-setup-message (cond (yank 'reply-yank)
- (article-buffer 'reply)
- (t 'message))
- (let* ((group (or group gnus-newsgroup-name))
- (pgroup group)
- to-address to-group mailing-list to-list)
- (when group
- (setq to-address (gnus-group-get-parameter group 'to-address)
- to-group (gnus-group-get-parameter group 'to-group)
- to-list (gnus-group-get-parameter group 'to-list)
- mailing-list (when gnus-mailing-list-groups
- (string-match gnus-mailing-list-groups group))
- group (gnus-group-real-name group)))
- (if (or (and to-group
- (gnus-news-group-p to-group))
- force-news
- (and (gnus-news-group-p
- (or pgroup gnus-newsgroup-name)
- (if header (mail-header-number header)
- gnus-current-article))
- (not mailing-list)
- (not to-list)
- (not to-address)))
- ;; This is news.
- (if post
- (message-news (or to-group group))
- (set-buffer gnus-article-copy)
- (message-followup))
- ;; The is mail.
- (if post
- (progn
- (message-mail (or to-address to-list))
- ;; Arrange for mail groups that have no `to-address' to
- ;; get that when the user sends off the mail.
- (push (list 'gnus-inews-add-to-address group)
- message-send-actions))
- (set-buffer gnus-article-copy)
- (message-wide-reply to-address)))
- (when yank
- (gnus-inews-yank-articles yank))))))
-
-(defun gnus-post-method (arg group &optional silent)
- "Return the posting method based on GROUP and ARG.
-If SILENT, don't prompt the user."
- (let ((group-method (gnus-find-method-for-group group)))
- (cond
- ;; If the group-method is nil (which shouldn't happen) we use
- ;; the default method.
- ((null arg)
- (or gnus-post-method gnus-select-method message-post-method))
- ;; We want this group's method.
- ((and arg (not (eq arg 0)))
- group-method)
- ;; We query the user for a post method.
- ((or arg
- (and gnus-post-method
- (listp (car gnus-post-method))))
- (let* ((methods
- ;; Collect all methods we know about.
- (append
- (when gnus-post-method
- (if (listp (car gnus-post-method))
- gnus-post-method
- (list gnus-post-method)))
- gnus-secondary-select-methods
- (list gnus-select-method)
- (list group-method)))
- method-alist post-methods method)
- ;; Weed out all mail methods.
- (while methods
- (setq method (gnus-server-get-method "" (pop methods)))
- (when (or (gnus-method-option-p method 'post)
- (gnus-method-option-p method 'post-mail))
- (push method post-methods)))
- ;; Create a name-method alist.
- (setq method-alist
- (mapcar
- (lambda (m)
- (list (concat (cadr m) " (" (symbol-name (car m)) ")") m))
- post-methods))
- ;; Query the user.
- (cadr
- (assoc
- (setq gnus-last-posting-server
- (if (and silent
- gnus-last-posting-server)
- ;; Just use the last value.
- gnus-last-posting-server
- (completing-read
- "Posting method: " method-alist nil t
- (cons (or gnus-last-posting-server "") 0))))
- method-alist))))
- ;; Override normal method.
- ((and gnus-post-method
- (or (gnus-method-option-p group-method 'post)
- (gnus-method-option-p group-method 'post-mail)))
- gnus-post-method)
- ;; Perhaps this is a mail group?
- ((and (not (gnus-member-of-valid 'post group))
- (not (gnus-method-option-p group-method 'post-mail)))
- group-method)
- ;; Use the normal select method.
- (t gnus-select-method))))
-
-(defun gnus-inews-narrow-to-headers ()
- (widen)
- (narrow-to-region
- (goto-char (point-min))
- (or (and (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$") nil t)
- (match-beginning 0))
- (point-max)))
- (goto-char (point-min)))
-
-;;;
-;;; Check whether the message has been sent already.
-;;;
-
-(defvar gnus-inews-sent-ids nil)
-
-(defun gnus-inews-reject-message ()
- "Check whether this message has already been sent."
- (when gnus-sent-message-ids-file
- (let ((message-id (save-restriction (gnus-inews-narrow-to-headers)
- (mail-fetch-field "message-id")))
- end)
- (when message-id
- (unless gnus-inews-sent-ids
- (condition-case ()
- (load t t t)
- (error nil)))
- (if (member message-id gnus-inews-sent-ids)
- ;; Reject this message.
- (not (gnus-yes-or-no-p
- (format "Message %s already sent. Send anyway? "
- message-id)))
- (push message-id gnus-inews-sent-ids)
- ;; Chop off the last Message-IDs.
- (when (setq end (nthcdr gnus-sent-message-ids-length
- gnus-inews-sent-ids))
- (setcdr end nil))
- (nnheader-temp-write gnus-sent-message-ids-file
- (prin1 `(setq gnus-inews-sent-ids ',gnus-inews-sent-ids)
- (current-buffer)))
- nil)))))
-
-
-
-;; Dummy to avoid byte-compile warning.
-(defvar nnspool-rejected-article-hook)
-
-;;; Since the X-Newsreader/X-Mailer are ``vanity'' headers, they might
-;;; as well include the Emacs version as well.
-;;; The following function works with later GNU Emacs, and XEmacs.
-(defun gnus-extended-version ()
- "Stringified Gnus version and Emacs version"
- (interactive)
- (concat
- gnus-version
- "/"
- (cond
- ((string-match "^\\([0-9]+\\.[0-9]+\\)\\.[.0-9]+$" emacs-version)
- (concat "Emacs " (substring emacs-version
- (match-beginning 1)
- (match-end 1))))
- ((string-match "\\([A-Z]*[Mm][Aa][Cc][Ss]\\)" emacs-version)
- (concat (substring emacs-version
- (match-beginning 1)
- (match-end 1))
- (format " %d.%d" emacs-major-version emacs-minor-version)))
- (t emacs-version))))
-
-;; Written by "Mr. Per Persson" <pp@solace.mh.se>.
-(defun gnus-inews-insert-mime-headers ()
- (goto-char (point-min))
- (let ((mail-header-separator
- (progn
- (goto-char (point-min))
- (if (and (search-forward (concat "\n" mail-header-separator "\n")
- nil t)
- (not (search-backward "\n\n" nil t)))
- mail-header-separator
- ""))))
- (or (mail-position-on-field "Mime-Version")
- (insert "1.0")
- (cond ((save-restriction
- (widen)
- (goto-char (point-min))
- (re-search-forward "[\200-\377]" nil t))
- (or (mail-position-on-field "Content-Type")
- (insert "text/plain; charset=ISO-8859-1"))
- (or (mail-position-on-field "Content-Transfer-Encoding")
- (insert "8bit")))
- (t (or (mail-position-on-field "Content-Type")
- (insert "text/plain; charset=US-ASCII"))
- (or (mail-position-on-field "Content-Transfer-Encoding")
- (insert "7bit")))))))
-
-
-;;;
-;;; Gnus Mail Functions
-;;;
-
-;;; Mail reply commands of Gnus summary mode
-
-(defun gnus-summary-reply (&optional yank)
- "Reply mail to news author.
-If prefix argument YANK is non-nil, original article is yanked automatically."
- (interactive
- (list (and current-prefix-arg
- (gnus-summary-work-articles 1))))
- ;; Bug fix by jbw@bigbird.bu.edu (Joe Wells)
- ;; Stripping headers should be specified with mail-yank-ignored-headers.
- (gnus-set-global-variables)
- (when yank
- (gnus-summary-goto-subject (car yank)))
- (let ((gnus-article-reply t))
- (gnus-setup-message (if yank 'reply-yank 'reply)
- (gnus-summary-select-article)
- (set-buffer (gnus-copy-article-buffer))
- (message-reply nil nil (gnus-group-get-parameter
- gnus-newsgroup-name 'broken-reply-to))
- (when yank
- (gnus-inews-yank-articles yank)))))
-
-(defun gnus-summary-reply-with-original (n)
- "Reply mail to news author with original article."
- (interactive "P")
- (gnus-summary-reply (gnus-summary-work-articles n)))
-
-(defun gnus-summary-mail-forward (&optional post)
- "Forward the current message to another user."
- (interactive "P")
- (gnus-set-global-variables)
- (gnus-setup-message 'forward
- (gnus-summary-select-article)
- (set-buffer gnus-original-article-buffer)
- (message-forward post)))
-
-(defun gnus-summary-resend-message (address)
- "Resend the current article to ADDRESS."
- (interactive "sResend message to: ")
- (gnus-summary-select-article)
- (save-excursion
- (set-buffer gnus-original-article-buffer)
- (message-resend address)))
-
-(defun gnus-summary-post-forward ()
- "Forward the current article to a newsgroup."
- (interactive)
- (gnus-summary-mail-forward t))
-
-(defvar gnus-nastygram-message
- "The following article was inappropriately posted to %s.\n"
- "Format string to insert in nastygrams.
-The current group name will be inserted at \"%s\".")
-
-(defun gnus-summary-mail-nastygram (n)
- "Send a nastygram to the author of the current article."
- (interactive "P")
- (if (or gnus-expert-user
- (gnus-y-or-n-p
- "Really send a nastygram to the author of the current article? "))
- (let ((group gnus-newsgroup-name))
- (gnus-summary-reply-with-original n)
- (set-buffer gnus-message-buffer)
- (insert (format gnus-nastygram-message group))
- (message-send-and-exit))))
-
-(defun gnus-summary-mail-other-window ()
- "Compose mail in other window."
- (interactive)
- (gnus-setup-message 'message
- (message-mail)))
-
-(defun gnus-mail-parse-comma-list ()
- (let (accumulated
- beg)
- (skip-chars-forward " ")
- (while (not (eobp))
- (setq beg (point))
- (skip-chars-forward "^,")
- (while (zerop
- (save-excursion
- (save-restriction
- (let ((i 0))
- (narrow-to-region beg (point))
- (goto-char beg)
- (logand (progn
- (while (search-forward "\"" nil t)
- (incf i))
- (if (zerop i) 2 i)) 2)))))
- (skip-chars-forward ",")
- (skip-chars-forward "^,"))
- (skip-chars-backward " ")
- (setq accumulated
- (cons (buffer-substring beg (point))
- accumulated))
- (skip-chars-forward "^,")
- (skip-chars-forward ", "))
- accumulated))
-
-(defun gnus-mail-yank-original ()
- (interactive)
- (save-excursion
- (mail-yank-original nil))
- (or mail-yank-hooks mail-citation-hook
- (run-hooks 'news-reply-header-hook)))
-
-(defun gnus-inews-add-to-address (group)
- (let ((to-address (mail-fetch-field "to")))
- (when (and to-address
- (gnus-alive-p))
- ;; This mail group doesn't have a `to-list', so we add one
- ;; here. Magic!
- (gnus-group-add-parameter group (cons 'to-list to-address)))))
-
-(defun gnus-put-message ()
- "Put the current message in some group and return to Gnus."
- (interactive)
- (let ((reply gnus-article-reply)
- (winconf gnus-prev-winconf)
- (group gnus-newsgroup-name))
-
- (or (and group (not (gnus-group-read-only-p group)))
- (setq group (read-string "Put in group: " nil
- (gnus-writable-groups))))
- (and (gnus-gethash group gnus-newsrc-hashtb)
- (error "No such group: %s" group))
-
- (save-excursion
- (save-restriction
- (widen)
- (gnus-inews-narrow-to-headers)
- (let (gnus-deletable-headers)
- (if (message-news-p)
- (message-generate-headers message-required-news-headers)
- (message-generate-headers message-required-mail-headers)))
- (goto-char (point-max))
- (insert "Gcc: " group "\n")
- (widen)))
-
- (gnus-inews-do-gcc)
-
- (if (get-buffer gnus-group-buffer)
- (progn
- (if (gnus-buffer-exists-p (car-safe reply))
- (progn
- (set-buffer (car reply))
- (and (cdr reply)
- (gnus-summary-mark-article-as-replied
- (cdr reply)))))
- (and winconf (set-window-configuration winconf))))))
-
-(defun gnus-article-mail (yank)
- "Send a reply to the address near point.
-If YANK is non-nil, include the original article."
- (interactive "P")
- (let ((address
- (buffer-substring
- (save-excursion (re-search-backward "[ \t\n]" nil t) (1+ (point)))
- (save-excursion (re-search-forward "[ \t\n]" nil t) (1- (point))))))
- (when address
- (message-reply address)
- (when yank
- (gnus-inews-yank-articles (list (cdr gnus-article-current)))))))
-
-(defun gnus-bug ()
- "Send a bug report to the Gnus maintainers."
- (interactive)
- (gnus-setup-message 'bug
- (delete-other-windows)
- (switch-to-buffer "*Gnus Help Bug*")
- (erase-buffer)
- (insert gnus-bug-message)
- (goto-char (point-min))
- (message-pop-to-buffer "*Gnus Bug*")
- (message-setup `((To . ,gnus-maintainer) (Subject . "")))
- (push `(gnus-bug-kill-buffer) message-send-actions)
- (goto-char (point-min))
- (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
- (forward-line 1)
- (insert (gnus-version) "\n")
- (insert (emacs-version))
- (insert "\n\n\n\n\n")
- (gnus-debug)
- (goto-char (point-min))
- (search-forward "Subject: " nil t)
- (message "")))
-
-(defun gnus-bug-kill-buffer ()
- (and (get-buffer "*Gnus Help Bug*")
- (kill-buffer "*Gnus Help Bug*")))
-
-(defun gnus-debug ()
- "Attemps to go through the Gnus source file and report what variables have been changed.
-The source file has to be in the Emacs load path."
- (interactive)
- (let ((files '("gnus.el" "gnus-msg.el" "gnus-score.el" "nnmail.el"
- "message.el"))
- file dirs expr olist sym)
- (gnus-message 4 "Please wait while we snoop your variables...")
- (sit-for 0)
- (save-excursion
- (set-buffer (get-buffer-create " *gnus bug info*"))
- (buffer-disable-undo (current-buffer))
- (while files
- (erase-buffer)
- (setq dirs load-path)
- (while dirs
- (if (or (not (car dirs))
- (not (stringp (car dirs)))
- (not (file-exists-p
- (setq file (concat (file-name-as-directory
- (car dirs)) (car files))))))
- (setq dirs (cdr dirs))
- (setq dirs nil)
- (insert-file-contents file)
- (goto-char (point-min))
- (if (not (re-search-forward "^;;* *Internal variables" nil t))
- (gnus-message 4 "Malformed sources in file %s" file)
- (narrow-to-region (point-min) (point))
- (goto-char (point-min))
- (while (setq expr (condition-case ()
- (read (current-buffer)) (error nil)))
- (condition-case ()
- (and (eq (car expr) 'defvar)
- (stringp (nth 3 expr))
- (or (not (boundp (nth 1 expr)))
- (not (equal (eval (nth 2 expr))
- (symbol-value (nth 1 expr)))))
- (setq olist (cons (nth 1 expr) olist)))
- (error nil))))))
- (setq files (cdr files)))
- (kill-buffer (current-buffer)))
- (when (setq olist (nreverse olist))
- (insert "------------------ Environment follows ------------------\n\n"))
- (while olist
- (if (boundp (car olist))
- (condition-case ()
- (pp `(setq ,(car olist)
- ,(if (or (consp (setq sym (symbol-value (car olist))))
- (and (symbolp sym)
- (not (or (eq sym nil)
- (eq sym t)))))
- (list 'quote (symbol-value (car olist)))
- (symbol-value (car olist))))
- (current-buffer))
- (error
- (format "(setq %s 'whatever)\n" (car olist))))
- (insert ";; (makeunbound '" (symbol-name (car olist)) ")\n"))
- (setq olist (cdr olist)))
- (insert "\n\n")
- ;; Remove any null chars - they seem to cause trouble for some
- ;; mailers. (Byte-compiled output from the stuff above.)
- (goto-char (point-min))
- (while (re-search-forward "[\000\200]" nil t)
- (replace-match "" t t))))
-
-;;; Treatment of rejected articles.
-;;; Bounced mail.
-
-(defun gnus-summary-resend-bounced-mail (&optional fetch)
- "Re-mail the current message.
-This only makes sense if the current message is a bounce message than
-contains some mail you have written which has been bounced back to
-you.
-If FETCH, try to fetch the article that this is a reply to, if indeed
-this is a reply."
- (interactive "P")
- (gnus-summary-select-article t)
- (set-buffer gnus-original-article-buffer)
- (gnus-setup-message 'compose-bounce
- (let* ((references (mail-fetch-field "references"))
- (parent (and references (gnus-parent-id references))))
- (message-bounce)
- ;; If there are references, we fetch the article we answered to.
- (and fetch parent
- (gnus-summary-refer-article parent)
- (gnus-summary-show-all-headers)))))
-
-;;; Gcc handling.
-
-;; Do Gcc handling, which copied the message over to some group.
-(defun gnus-inews-do-gcc (&optional gcc)
- (when (gnus-alive-p)
- (save-excursion
- (save-restriction
- (message-narrow-to-headers)
- (let ((gcc (or gcc (mail-fetch-field "gcc" nil t)))
- (cur (current-buffer))
- groups group method)
- (when gcc
- (message-remove-header "gcc")
- (widen)
- (setq groups (message-tokenize-header gcc " ,"))
- ;; Copy the article over to some group(s).
- (while (setq group (pop groups))
- (gnus-check-server
- (setq method
- (cond ((and (null (gnus-get-info group))
- (eq (car gnus-message-archive-method)
- (car
- (gnus-server-to-method
- (gnus-group-method group)))))
- ;; If the group doesn't exist, we assume
- ;; it's an archive group...
- gnus-message-archive-method)
- ;; Use the method.
- ((gnus-info-method (gnus-get-info group))
- (gnus-info-method (gnus-get-info group)))
- ;; Find the method.
- (t (gnus-group-method group)))))
- (gnus-check-server method)
- (unless (gnus-request-group group t method)
- (gnus-request-create-group group method))
- (save-excursion
- (nnheader-set-temp-buffer " *acc*")
- (insert-buffer-substring cur)
- (goto-char (point-min))
- (when (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$")
- nil t)
- (replace-match "" t t ))
- (unless (gnus-request-accept-article group method t)
- (gnus-message 1 "Couldn't store article in group %s: %s"
- group (gnus-status-message method))
- (sit-for 2))
- (kill-buffer (current-buffer))))))))))
-
-(defun gnus-inews-insert-gcc ()
- "Insert Gcc headers based on `gnus-outgoing-message-group'."
- (save-excursion
- (save-restriction
- (gnus-inews-narrow-to-headers)
- (let* ((group gnus-outgoing-message-group)
- (gcc (cond
- ((gnus-functionp group)
- (funcall group))
- ((or (stringp group) (list group))
- group))))
- (when gcc
- (insert "Gcc: "
- (if (stringp gcc) gcc
- (mapconcat 'identity gcc " "))
- "\n"))))))
-
-(defun gnus-inews-insert-archive-gcc (&optional group)
- "Insert the Gcc to say where the article is to be archived."
- (let* ((var gnus-message-archive-group)
- (group (or group gnus-newsgroup-name ""))
- result
- (groups
- (cond
- ((null gnus-message-archive-method)
- ;; Ignore.
- nil)
- ((stringp var)
- ;; Just a single group.
- (list var))
- ((null var)
- ;; We don't want this.
- nil)
- ((and (listp var) (stringp (car var)))
- ;; A list of groups.
- var)
- ((gnus-functionp var)
- ;; A function.
- (funcall var group))
- (t
- ;; An alist of regexps/functions/forms.
- (while (and var
- (not
- (setq result
- (cond
- ((stringp (caar var))
- ;; Regexp.
- (when (string-match (caar var) group)
- (cdar var)))
- ((gnus-functionp (car var))
- ;; Function.
- (funcall (car var) group))
- (t
- (eval (car var)))))))
- (setq var (cdr var)))
- result)))
- name)
- (when groups
- (when (stringp groups)
- (setq groups (list groups)))
- (save-excursion
- (save-restriction
- (gnus-inews-narrow-to-headers)
- (goto-char (point-max))
- (insert "Gcc: ")
- (while (setq name (pop groups))
- (insert (if (string-match ":" name)
- name
- (gnus-group-prefixed-name
- name gnus-message-archive-method)))
- (if groups (insert " ")))
- (insert "\n"))))))
-
-(defun gnus-summary-send-draft ()
- "Enter a mail/post buffer to edit and send the draft."
- (interactive)
- (gnus-set-global-variables)
- (let (buf)
- (if (not (setq buf (gnus-request-restore-buffer
- (gnus-summary-article-number) gnus-newsgroup-name)))
- (error "Couldn't restore the article")
- (switch-to-buffer buf)
- (when (eq major-mode 'news-reply-mode)
- (local-set-key "\C-c\C-c" 'gnus-inews-news))
- ;; Insert the separator.
- (goto-char (point-min))
- (search-forward "\n\n")
- (forward-char -1)
- (insert mail-header-separator)
- ;; Configure windows.
- (let ((gnus-draft-buffer (current-buffer)))
- (gnus-configure-windows 'draft t)
- (goto-char (point))))))
-
-(gnus-add-shutdown 'gnus-inews-close 'gnus)
-
-(defun gnus-inews-close ()
- (setq gnus-inews-sent-ids nil))
-
-;;; Allow redefinition of functions.
-
-(gnus-ems-redefine)
-
-(provide 'gnus-msg)
-
-;;; gnus-msg.el ends here
diff --git a/lisp/gnus-nocem.el b/lisp/gnus-nocem.el
deleted file mode 100644
index 89f27773b8c..00000000000
--- a/lisp/gnus-nocem.el
+++ /dev/null
@@ -1,247 +0,0 @@
-;;; gnus-nocem.el --- NoCeM pseudo-cancellation treatment
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'gnus)
-(require 'nnmail)
-(eval-when-compile (require 'cl))
-
-(defvar gnus-nocem-groups
- '("alt.nocem.misc" "news.admin.net-abuse.announce")
- "*List of groups that will be searched for NoCeM messages.")
-
-(defvar gnus-nocem-issuers
- '("Automoose-1" ; The CancelMoose[tm] on autopilot.
- "clewis@ferret.ocunix.on.ca;" ; Chris Lewis -- Canadian angel & despammer.
- "jem@xpat.com;" ; John Milburn -- despammer in Korea.
- "red@redpoll.mrfs.oh.us (Richard E. Depew)" ; Spew/bincancel guy.
- )
- "*List of NoCeM issuers to pay attention to.")
-
-(defvar gnus-nocem-directory
- (concat (file-name-as-directory gnus-article-save-directory) "NoCeM/")
- "*Directory where NoCeM files will be stored.")
-
-(defvar gnus-nocem-expiry-wait 15
- "*Number of days to keep NoCeM headers in the cache.")
-
-(defvar gnus-nocem-verifyer nil
- "*Function called to verify that the NoCeM message is valid.
-One likely value is `mc-verify'. If the function in this variable
-isn't bound, the message will be used unconditionally.")
-
-;;; Internal variables
-
-(defvar gnus-nocem-active nil)
-(defvar gnus-nocem-alist nil)
-(defvar gnus-nocem-touched-alist nil)
-(defvar gnus-nocem-hashtb nil)
-
-;;; Functions
-
-(defun gnus-nocem-active-file ()
- (concat (file-name-as-directory gnus-nocem-directory) "active"))
-
-(defun gnus-nocem-cache-file ()
- (concat (file-name-as-directory gnus-nocem-directory) "cache"))
-
-(defun gnus-nocem-scan-groups ()
- "Scan all NoCeM groups for new NoCeM messages."
- (interactive)
- (let ((groups gnus-nocem-groups)
- group active gactive articles)
- (or (file-exists-p gnus-nocem-directory)
- (make-directory gnus-nocem-directory t))
- ;; Load any previous NoCeM headers.
- (gnus-nocem-load-cache)
- ;; Read the active file if it hasn't been read yet.
- (and (file-exists-p (gnus-nocem-active-file))
- (not gnus-nocem-active)
- (condition-case ()
- (load (gnus-nocem-active-file) t t t)
- (error nil)))
- ;; Go through all groups and see whether new articles have
- ;; arrived.
- (while (setq group (pop groups))
- (if (not (setq gactive (gnus-activate-group group)))
- () ; This group doesn't exist.
- (setq active (nth 1 (assoc group gnus-nocem-active)))
- (when (and (not (< (cdr gactive) (car gactive))) ; Empty group.
- (or (not active)
- (< (cdr active) (cdr gactive))))
- ;; Ok, there are new articles in this group, se we fetch the
- ;; headers.
- (save-excursion
- (let ((dependencies (make-vector 10 nil))
- (buffer (nnheader-set-temp-buffer " *Gnus NoCeM*"))
- headers)
- (setq headers
- (if (eq 'nov
- (gnus-retrieve-headers
- (setq articles
- (gnus-uncompress-range
- (cons
- (if active (1+ (cdr active))
- (car gactive))
- (cdr gactive))))
- group))
- (gnus-get-newsgroup-headers-xover
- articles nil dependencies)
- (gnus-get-newsgroup-headers dependencies)))
- (while headers
- ;; We take a closer look on all articles that have
- ;; "@@NCM" in the subject.
- (when (string-match "@@NCM"
- (mail-header-subject (car headers)))
- (gnus-nocem-check-article group (car headers)))
- (setq headers (cdr headers)))
- (kill-buffer (current-buffer)))))
- (setq gnus-nocem-active
- (cons (list group gactive)
- (delq (assoc group gnus-nocem-active)
- gnus-nocem-active)))))
- ;; Save the results, if any.
- (gnus-nocem-save-cache)
- (gnus-nocem-save-active)))
-
-(defun gnus-nocem-check-article (group header)
- "Check whether the current article is an NCM article and that we want it."
- ;; Get the article.
- (gnus-message 7 "Checking article %d in %s for NoCeM..."
- (mail-header-number header) group)
- (let ((date (mail-header-date header))
- issuer b e)
- (when (or (not date)
- (nnmail-time-less
- (nnmail-time-since (nnmail-date-to-time date))
- (nnmail-days-to-time gnus-nocem-expiry-wait)))
- (gnus-request-article-this-buffer (mail-header-number header) group)
- (goto-char (point-min))
- ;; The article has to have proper NoCeM headers.
- (when (and (setq b (search-forward "\n@@BEGIN NCM HEADERS\n" nil t))
- (setq e (search-forward "\n@@BEGIN NCM BODY\n" nil t)))
- ;; We get the name of the issuer.
- (narrow-to-region b e)
- (setq issuer (mail-fetch-field "issuer"))
- (and (member issuer gnus-nocem-issuers) ; We like her...
- (gnus-nocem-verify-issuer issuer) ; She is who she says she is..
- (gnus-nocem-enter-article)))))) ; We gobble the message.
-
-(defun gnus-nocem-verify-issuer (person)
- "Verify using PGP that the canceler is who she says she is."
- (widen)
- (if (fboundp gnus-nocem-verifyer)
- (funcall gnus-nocem-verifyer)
- ;; If we don't have MailCrypt, then we use the message anyway.
- t))
-
-(defun gnus-nocem-enter-article ()
- "Enter the current article into the NoCeM cache."
- (goto-char (point-min))
- (let ((b (search-forward "\n@@BEGIN NCM BODY\n" nil t))
- (e (search-forward "\n@@END NCM BODY\n" nil t))
- (buf (current-buffer))
- ncm id)
- (when (and b e)
- (narrow-to-region b (1+ (match-beginning 0)))
- (goto-char (point-min))
- (while (search-forward "\t" nil t)
- (when (condition-case nil
- (boundp (let ((obarray gnus-active-hashtb)) (read buf)))
- (error nil))
- (beginning-of-line)
- (while (= (following-char) ?\t)
- (forward-line -1))
- (setq id (buffer-substring (point) (1- (search-forward "\t"))))
- (push id ncm)
- (gnus-sethash id t gnus-nocem-hashtb)
- (forward-line 1)
- (while (= (following-char) ?\t)
- (forward-line 1))))
- (when ncm
- (setq gnus-nocem-touched-alist t)
- (push (cons (let ((time (current-time))) (setcdr (cdr time) nil) time)
- ncm)
- gnus-nocem-alist)))))
-
-(defun gnus-nocem-load-cache ()
- "Load the NoCeM cache."
- (unless gnus-nocem-alist
- ;; The buffer doesn't exist, so we create it and load the NoCeM
- ;; cache.
- (when (file-exists-p (gnus-nocem-cache-file))
- (load (gnus-nocem-cache-file) t t t)
- (gnus-nocem-alist-to-hashtb))))
-
-(defun gnus-nocem-save-cache ()
- "Save the NoCeM cache."
- (when (and gnus-nocem-alist
- gnus-nocem-touched-alist)
- (nnheader-temp-write (gnus-nocem-cache-file)
- (prin1 `(setq gnus-nocem-alist ',gnus-nocem-alist) (current-buffer)))
- (setq gnus-nocem-touched-alist nil)))
-
-(defun gnus-nocem-save-active ()
- "Save the NoCeM active file."
- (nnheader-temp-write (gnus-nocem-active-file)
- (prin1 `(setq gnus-nocem-active ',gnus-nocem-active) (current-buffer))))
-
-(defun gnus-nocem-alist-to-hashtb ()
- "Create a hashtable from the Message-IDs we have."
- (let* ((alist gnus-nocem-alist)
- (pprev (cons nil alist))
- (prev pprev)
- (expiry (nnmail-days-to-time gnus-nocem-expiry-wait))
- entry)
- (setq gnus-nocem-hashtb (gnus-make-hashtable (* (length alist) 51)))
- (while (setq entry (car alist))
- (if (not (nnmail-time-less (nnmail-time-since (car entry)) expiry))
- ;; This entry has expired, so we remove it.
- (setcdr prev (cdr alist))
- (setq prev alist)
- ;; This is ok, so we enter it into the hashtable.
- (setq entry (cdr entry))
- (while entry
- (gnus-sethash (car entry) t gnus-nocem-hashtb)
- (setq entry (cdr entry))))
- (setq alist (cdr alist)))))
-
-(gnus-add-shutdown 'gnus-nocem-close 'gnus)
-
-(defun gnus-nocem-close ()
- "Clear internal NoCeM variables."
- (setq gnus-nocem-alist nil
- gnus-nocem-hashtb nil
- gnus-nocem-active nil
- gnus-nocem-touched-alist nil))
-
-(defun gnus-nocem-unwanted-article-p (id)
- "Say whether article ID in the current group is wanted."
- (gnus-gethash id gnus-nocem-hashtb))
-
-(provide 'gnus-nocem)
-
-;;; gnus-nocem.el ends here
diff --git a/lisp/gnus-salt.el b/lisp/gnus-salt.el
deleted file mode 100644
index b5e38677212..00000000000
--- a/lisp/gnus-salt.el
+++ /dev/null
@@ -1,654 +0,0 @@
-;;; gnus-salt.el --- alternate summary mode interfaces for Gnus
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'gnus)
-(eval-when-compile (require 'cl))
-
-;;;
-;;; gnus-pick-mode
-;;;
-
-(defvar gnus-pick-mode nil
- "Minor mode for providing a pick-and-read interface in Gnus summary buffers.")
-
-(defvar gnus-pick-display-summary nil
- "*Display summary while reading.")
-
-(defvar gnus-pick-mode-hook nil
- "Hook run in summary pick mode buffers.")
-
-;;; Internal variables.
-
-(defvar gnus-pick-mode-map nil)
-
-(unless gnus-pick-mode-map
- (setq gnus-pick-mode-map (make-sparse-keymap))
-
- (gnus-define-keys
- gnus-pick-mode-map
- "t" gnus-uu-mark-thread
- "T" gnus-uu-unmark-thread
- " " gnus-summary-mark-as-processable
- "u" gnus-summary-unmark-as-processable
- "U" gnus-summary-unmark-all-processable
- "v" gnus-uu-mark-over
- "r" gnus-uu-mark-region
- "R" gnus-uu-unmark-region
- "e" gnus-uu-mark-by-regexp
- "E" gnus-uu-mark-by-regexp
- "b" gnus-uu-mark-buffer
- "B" gnus-uu-unmark-buffer
- "\r" gnus-pick-start-reading))
-
-(defun gnus-pick-make-menu-bar ()
- (unless (boundp 'gnus-pick-menu)
- (easy-menu-define
- gnus-pick-menu gnus-pick-mode-map ""
- '("Pick"
- ("Pick"
- ["Article" gnus-summary-mark-as-processable t]
- ["Thread" gnus-uu-mark-thread t]
- ["Region" gnus-uu-mark-region t]
- ["Regexp" gnus-uu-mark-regexp t]
- ["Buffer" gnus-uu-mark-buffer t])
- ("Unpick"
- ["Article" gnus-summary-unmark-as-processable t]
- ["Thread" gnus-uu-unmark-thread t]
- ["Region" gnus-uu-unmark-region t]
- ["Regexp" gnus-uu-unmark-regexp t]
- ["Buffer" gnus-uu-unmark-buffer t])
- ["Start reading" gnus-pick-start-reading t]
- ["Switch pick mode off" gnus-pick-mode gnus-pick-mode]))))
-
-(defun gnus-pick-mode (&optional arg)
- "Minor mode for providing a pick-and-read interface in Gnus summary buffers.
-
-\\{gnus-pick-mode-map}"
- (interactive "P")
- (when (eq major-mode 'gnus-summary-mode)
- (make-local-variable 'gnus-pick-mode)
- (setq gnus-pick-mode
- (if (null arg) (not gnus-pick-mode)
- (> (prefix-numeric-value arg) 0)))
- (when gnus-pick-mode
- ;; Make sure that we don't select any articles upon group entry.
- (make-local-variable 'gnus-auto-select-first)
- (setq gnus-auto-select-first nil)
- ;; Set up the menu.
- (when (and menu-bar-mode
- (gnus-visual-p 'pick-menu 'menu))
- (gnus-pick-make-menu-bar))
- (unless (assq 'gnus-pick-mode minor-mode-alist)
- (push '(gnus-pick-mode " Pick") minor-mode-alist))
- (unless (assq 'gnus-pick-mode minor-mode-map-alist)
- (push (cons 'gnus-pick-mode gnus-pick-mode-map)
- minor-mode-map-alist))
- (run-hooks 'gnus-pick-mode-hook))))
-
-(defun gnus-pick-start-reading (&optional catch-up)
- "Start reading the picked articles.
-If given a prefix, mark all unpicked articles as read."
- (interactive "P")
- (unless gnus-newsgroup-processable
- (error "No articles have been picked"))
- (gnus-summary-limit-to-articles nil)
- (when catch-up
- (gnus-summary-limit-mark-excluded-as-read))
- (gnus-summary-first-unread-article)
- (gnus-configure-windows (if gnus-pick-display-summary 'article 'pick) t))
-
-
-;;;
-;;; gnus-binary-mode
-;;;
-
-(defvar gnus-binary-mode nil
- "Minor mode for provind a binary group interface in Gnus summary buffers.")
-
-(defvar gnus-binary-mode-hook nil
- "Hook run in summary binary mode buffers.")
-
-(defvar gnus-binary-mode-map nil)
-
-(unless gnus-binary-mode-map
- (setq gnus-binary-mode-map (make-sparse-keymap))
-
- (gnus-define-keys
- gnus-binary-mode-map
- "g" gnus-binary-show-article))
-
-(defun gnus-binary-make-menu-bar ()
- (unless (boundp 'gnus-binary-menu)
- (easy-menu-define
- gnus-binary-menu gnus-binary-mode-map ""
- '("Pick"
- ["Switch binary mode off" gnus-binary-mode t]))))
-
-(defun gnus-binary-mode (&optional arg)
- "Minor mode for providing a binary group interface in Gnus summary buffers."
- (interactive "P")
- (when (eq major-mode 'gnus-summary-mode)
- (make-local-variable 'gnus-binary-mode)
- (setq gnus-binary-mode
- (if (null arg) (not gnus-binary-mode)
- (> (prefix-numeric-value arg) 0)))
- (when gnus-binary-mode
- ;; Make sure that we don't select any articles upon group entry.
- (make-local-variable 'gnus-auto-select-first)
- (setq gnus-auto-select-first nil)
- (make-local-variable 'gnus-summary-display-article-function)
- (setq gnus-summary-display-article-function 'gnus-binary-display-article)
- ;; Set up the menu.
- (when (and menu-bar-mode
- (gnus-visual-p 'binary-menu 'menu))
- (gnus-binary-make-menu-bar))
- (unless (assq 'gnus-binary-mode minor-mode-alist)
- (push '(gnus-binary-mode " Binary") minor-mode-alist))
- (unless (assq 'gnus-binary-mode minor-mode-map-alist)
- (push (cons 'gnus-binary-mode gnus-binary-mode-map)
- minor-mode-map-alist))
- (run-hooks 'gnus-binary-mode-hook))))
-
-(defun gnus-binary-display-article (article &optional all-header)
- "Run ARTICLE through the binary decode functions."
- (when (gnus-summary-goto-subject article)
- (let ((gnus-view-pseudos 'automatic))
- (gnus-uu-decode-uu))))
-
-(defun gnus-binary-show-article (&optional arg)
- "Bypass the binary functions and show the article."
- (interactive "P")
- (let (gnus-summary-display-article-function)
- (gnus-summary-show-article arg)))
-
-;;;
-;;; gnus-tree-mode
-;;;
-
-(defvar gnus-tree-line-format "%(%[%3,3n%]%)"
- "Format of tree elements.")
-
-(defvar gnus-tree-minimize-window t
- "If non-nil, minimize the tree buffer window.
-If a number, never let the tree buffer grow taller than that number of
-lines.")
-
-(defvar gnus-selected-tree-face 'modeline
- "*Face used for highlighting selected articles in the thread tree.")
-
-(defvar gnus-tree-brackets '((?\[ . ?\]) (?\( . ?\))
- (?\{ . ?\}) (?< . ?>))
- "Brackets used in tree nodes.")
-
-(defvar gnus-tree-parent-child-edges '(?- ?\\ ?|)
- "Charaters used to connect parents with children.")
-
-(defvar gnus-tree-mode-line-format "Gnus: %%b %S %Z"
- "*The format specification for the tree mode line.")
-
-(defvar gnus-generate-tree-function 'gnus-generate-vertical-tree
- "*Function for generating a thread tree.
-Two predefined functions are available:
-`gnus-generate-horizontal-tree' and `gnus-generate-vertical-tree'.")
-
-(defvar gnus-tree-mode-hook nil
- "*Hook run in tree mode buffers.")
-
-;;; Internal variables.
-
-(defvar gnus-tree-line-format-alist
- `((?n gnus-tmp-name ?s)
- (?f gnus-tmp-from ?s)
- (?N gnus-tmp-number ?d)
- (?\[ gnus-tmp-open-bracket ?c)
- (?\] gnus-tmp-close-bracket ?c)
- (?s gnus-tmp-subject ?s)))
-
-(defvar gnus-tree-mode-line-format-alist gnus-summary-mode-line-format-alist)
-
-(defvar gnus-tree-mode-line-format-spec nil)
-(defvar gnus-tree-line-format-spec nil)
-
-(defvar gnus-tree-node-length nil)
-(defvar gnus-selected-tree-overlay nil)
-
-(defvar gnus-tree-displayed-thread nil)
-
-(defvar gnus-tree-mode-map nil)
-(put 'gnus-tree-mode 'mode-class 'special)
-
-(unless gnus-tree-mode-map
- (setq gnus-tree-mode-map (make-keymap))
- (suppress-keymap gnus-tree-mode-map)
- (gnus-define-keys
- gnus-tree-mode-map
- "\r" gnus-tree-select-article
- gnus-mouse-2 gnus-tree-pick-article
- "\C-?" gnus-tree-read-summary-keys
-
- "\C-c\C-i" gnus-info-find-node)
-
- (substitute-key-definition
- 'undefined 'gnus-tree-read-summary-keys gnus-tree-mode-map))
-
-(defun gnus-tree-make-menu-bar ()
- (unless (boundp 'gnus-tree-menu)
- (easy-menu-define
- gnus-tree-menu gnus-tree-mode-map ""
- '("Tree"
- ["Select article" gnus-tree-select-article t]))))
-
-(defun gnus-tree-mode ()
- "Major mode for displaying thread trees."
- (interactive)
- (setq gnus-tree-mode-line-format-spec
- (gnus-parse-format gnus-tree-mode-line-format
- gnus-summary-mode-line-format-alist))
- (setq gnus-tree-line-format-spec
- (gnus-parse-format gnus-tree-line-format
- gnus-tree-line-format-alist t))
- (when (and menu-bar-mode
- (gnus-visual-p 'tree-menu 'menu))
- (gnus-tree-make-menu-bar))
- (kill-all-local-variables)
- (gnus-simplify-mode-line)
- (setq mode-name "Tree")
- (setq major-mode 'gnus-tree-mode)
- (use-local-map gnus-tree-mode-map)
- (buffer-disable-undo (current-buffer))
- (setq buffer-read-only t)
- (setq truncate-lines t)
- (save-excursion
- (gnus-set-work-buffer)
- (gnus-tree-node-insert (make-mail-header "") nil)
- (setq gnus-tree-node-length (1- (point))))
- (run-hooks 'gnus-tree-mode-hook))
-
-(defun gnus-tree-read-summary-keys (&optional arg)
- "Read a summary buffer key sequence and execute it."
- (interactive "P")
- (let ((buf (current-buffer))
- win)
- (gnus-article-read-summary-keys arg nil t)
- (when (setq win (get-buffer-window buf))
- (select-window win)
- (when gnus-selected-tree-overlay
- (goto-char (or (gnus-overlay-end gnus-selected-tree-overlay) 1)))
- (gnus-tree-minimize))))
-
-(defun gnus-tree-select-article (article)
- "Select the article under point, if any."
- (interactive (list (gnus-tree-article-number)))
- (let ((buf (current-buffer)))
- (when article
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (gnus-summary-goto-article article))
- (select-window (get-buffer-window buf)))))
-
-(defun gnus-tree-pick-article (e)
- "Select the article under the mouse pointer."
- (interactive "e")
- (mouse-set-point e)
- (gnus-tree-select-article (gnus-tree-article-number)))
-
-(defun gnus-tree-article-number ()
- (get-text-property (point) 'gnus-number))
-
-(defun gnus-tree-article-region (article)
- "Return a cons with BEG and END of the article region."
- (let ((pos (text-property-any (point-min) (point-max) 'gnus-number article)))
- (when pos
- (cons pos (next-single-property-change pos 'gnus-number)))))
-
-(defun gnus-tree-goto-article (article)
- (let ((pos (text-property-any (point-min) (point-max) 'gnus-number article)))
- (when pos
- (goto-char pos))))
-
-(defun gnus-tree-recenter ()
- "Center point in the tree window."
- (let ((selected (selected-window))
- (tree-window (get-buffer-window gnus-tree-buffer t)))
- (when tree-window
- (select-window tree-window)
- (when gnus-selected-tree-overlay
- (goto-char (or (gnus-overlay-end gnus-selected-tree-overlay) 1)))
- (let* ((top (cond ((< (window-height) 4) 0)
- ((< (window-height) 7) 1)
- (t 2)))
- (height (1- (window-height)))
- (bottom (save-excursion (goto-char (point-max))
- (forward-line (- height))
- (point))))
- ;; Set the window start to either `bottom', which is the biggest
- ;; possible valid number, or the second line from the top,
- ;; whichever is the least.
- (set-window-start
- tree-window (min bottom (save-excursion
- (forward-line (- top)) (point)))))
- (select-window selected))))
-
-(defun gnus-get-tree-buffer ()
- "Return the tree buffer properly initialized."
- (save-excursion
- (set-buffer (get-buffer-create gnus-tree-buffer))
- (unless (eq major-mode 'gnus-tree-mode)
- (gnus-add-current-to-buffer-list)
- (gnus-tree-mode))
- (current-buffer)))
-
-(defun gnus-tree-minimize ()
- (when (and gnus-tree-minimize-window
- (not (one-window-p)))
- (let ((windows 0)
- tot-win-height)
- (walk-windows (lambda (window) (incf windows)))
- (setq tot-win-height
- (- (frame-height)
- (* window-min-height (1- windows))
- 2))
- (let* ((window-min-height 2)
- (height (count-lines (point-min) (point-max)))
- (min (max (1- window-min-height) height))
- (tot (if (numberp gnus-tree-minimize-window)
- (min gnus-tree-minimize-window min)
- min))
- (win (get-buffer-window (current-buffer)))
- (wh (and win (1- (window-height win)))))
- (setq tot (min tot tot-win-height))
- (when (and win
- (not (eq tot wh)))
- (let ((selected (selected-window)))
- (select-window win)
- (enlarge-window (- tot wh))
- (select-window selected)))))))
-
-;;; Generating the tree.
-
-(defun gnus-tree-node-insert (header sparse &optional adopted)
- (let* ((dummy (stringp header))
- (header (if (vectorp header) header
- (progn
- (setq header (make-mail-header "*****"))
- (mail-header-set-number header 0)
- (mail-header-set-lines header 0)
- (mail-header-set-chars header 0)
- header)))
- (gnus-tmp-from (mail-header-from header))
- (gnus-tmp-subject (mail-header-subject header))
- (gnus-tmp-number (mail-header-number header))
- (gnus-tmp-name
- (cond
- ((string-match "(.+)" gnus-tmp-from)
- (substring gnus-tmp-from
- (1+ (match-beginning 0)) (1- (match-end 0))))
- ((string-match "<[^>]+> *$" gnus-tmp-from)
- (let ((beg (match-beginning 0)))
- (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
- (substring gnus-tmp-from (1+ (match-beginning 0))
- (1- (match-end 0))))
- (substring gnus-tmp-from 0 beg))))
- ((memq gnus-tmp-number sparse)
- "***")
- (t gnus-tmp-from)))
- (gnus-tmp-open-bracket
- (cond ((memq gnus-tmp-number sparse)
- (caadr gnus-tree-brackets))
- (dummy (caaddr gnus-tree-brackets))
- (adopted (car (nth 3 gnus-tree-brackets)))
- (t (caar gnus-tree-brackets))))
- (gnus-tmp-close-bracket
- (cond ((memq gnus-tmp-number sparse)
- (cdadr gnus-tree-brackets))
- (adopted (cdr (nth 3 gnus-tree-brackets)))
- (dummy
- (cdaddr gnus-tree-brackets))
- (t (cdar gnus-tree-brackets))))
- (buffer-read-only nil)
- beg end)
- (gnus-add-text-properties
- (setq beg (point))
- (setq end (progn (eval gnus-tree-line-format-spec) (point)))
- (list 'gnus-number gnus-tmp-number))
- (when (or t (gnus-visual-p 'tree-highlight 'highlight))
- (gnus-tree-highlight-node gnus-tmp-number beg end))))
-
-(defun gnus-tree-highlight-node (article beg end)
- "Highlight current line according to `gnus-summary-highlight'."
- (let ((list gnus-summary-highlight)
- face)
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (let* ((score (or (cdr (assq article gnus-newsgroup-scored))
- gnus-summary-default-score 0))
- (default gnus-summary-default-score)
- (mark (or (gnus-summary-article-mark article) gnus-unread-mark)))
- ;; Eval the cars of the lists until we find a match.
- (while (and list
- (not (eval (caar list))))
- (setq list (cdr list)))))
- (unless (eq (setq face (cdar list)) (get-text-property beg 'face))
- (gnus-put-text-property
- beg end 'face
- (if (boundp face) (symbol-value face) face)))))
-
-(defun gnus-tree-indent (level)
- (insert (make-string (1- (* (1+ gnus-tree-node-length) level)) ? )))
-
-(defvar gnus-tmp-limit)
-(defvar gnus-tmp-sparse)
-(defvar gnus-tmp-indent)
-
-(defun gnus-generate-tree (thread)
- "Generate a thread tree for THREAD."
- (save-excursion
- (set-buffer (gnus-get-tree-buffer))
- (let ((buffer-read-only nil)
- (gnus-tmp-indent 0))
- (erase-buffer)
- (funcall gnus-generate-tree-function thread 0)
- (gnus-set-mode-line 'tree)
- (goto-char (point-min))
- (gnus-tree-minimize)
- (gnus-tree-recenter)
- (let ((selected (selected-window)))
- (when (get-buffer-window (set-buffer gnus-tree-buffer) t)
- (select-window (get-buffer-window (set-buffer gnus-tree-buffer) t))
- (gnus-horizontal-recenter)
- (select-window selected))))))
-
-(defun gnus-generate-horizontal-tree (thread level &optional dummyp adopted)
- "Generate a horizontal tree."
- (let* ((dummy (stringp (car thread)))
- (do (or dummy
- (memq (mail-header-number (car thread)) gnus-tmp-limit)))
- col beg)
- (if (not do)
- ;; We don't want this article.
- (setq thread (cdr thread))
- (if (not (bolp))
- ;; Not the first article on the line, so we insert a "-".
- (insert (car gnus-tree-parent-child-edges))
- ;; If the level isn't zero, then we insert some indentation.
- (unless (zerop level)
- (gnus-tree-indent level)
- (insert (cadr gnus-tree-parent-child-edges))
- (setq col (- (setq beg (point)) (gnus-point-at-bol) 1))
- ;; Draw "|" lines upwards.
- (while (progn
- (forward-line -1)
- (forward-char col)
- (= (following-char) ? ))
- (delete-char 1)
- (insert (caddr gnus-tree-parent-child-edges)))
- (goto-char beg)))
- (setq dummyp nil)
- ;; Insert the article node.
- (gnus-tree-node-insert (pop thread) gnus-tmp-sparse adopted))
- (if (null thread)
- ;; End of the thread, so we go to the next line.
- (unless (bolp)
- (insert "\n"))
- ;; Recurse downwards in all children of this article.
- (while thread
- (gnus-generate-horizontal-tree
- (pop thread) (if do (1+ level) level)
- (or dummyp dummy) dummy)))))
-
-(defsubst gnus-tree-indent-vertical ()
- (let ((len (- (* (1+ gnus-tree-node-length) gnus-tmp-indent)
- (- (point) (gnus-point-at-bol)))))
- (when (> len 0)
- (insert (make-string len ? )))))
-
-(defsubst gnus-tree-forward-line (n)
- (while (>= (decf n) 0)
- (unless (zerop (forward-line 1))
- (end-of-line)
- (insert "\n")))
- (end-of-line))
-
-(defun gnus-generate-vertical-tree (thread level &optional dummyp adopted)
- "Generate a vertical tree."
- (let* ((dummy (stringp (car thread)))
- (do (or dummy
- (memq (mail-header-number (car thread)) gnus-tmp-limit)))
- beg)
- (if (not do)
- ;; We don't want this article.
- (setq thread (cdr thread))
- (if (not (save-excursion (beginning-of-line) (bobp)))
- ;; Not the first article on the line, so we insert a "-".
- (progn
- (gnus-tree-indent-vertical)
- (insert (make-string (/ gnus-tree-node-length 2) ? ))
- (insert (caddr gnus-tree-parent-child-edges))
- (gnus-tree-forward-line 1))
- ;; If the level isn't zero, then we insert some indentation.
- (unless (zerop gnus-tmp-indent)
- (gnus-tree-forward-line (1- (* 2 level)))
- (gnus-tree-indent-vertical)
- (delete-char -1)
- (insert (cadr gnus-tree-parent-child-edges))
- (setq beg (point))
- ;; Draw "-" lines leftwards.
- (while (progn
- (forward-char -2)
- (= (following-char) ? ))
- (delete-char 1)
- (insert (car gnus-tree-parent-child-edges)))
- (goto-char beg)
- (gnus-tree-forward-line 1)))
- (setq dummyp nil)
- ;; Insert the article node.
- (gnus-tree-indent-vertical)
- (gnus-tree-node-insert (pop thread) gnus-tmp-sparse adopted)
- (gnus-tree-forward-line 1))
- (if (null thread)
- ;; End of the thread, so we go to the next line.
- (progn
- (goto-char (point-min))
- (end-of-line)
- (incf gnus-tmp-indent))
- ;; Recurse downwards in all children of this article.
- (while thread
- (gnus-generate-vertical-tree
- (pop thread) (if do (1+ level) level)
- (or dummyp dummy) dummy)))))
-
-;;; Interface functions.
-
-(defun gnus-possibly-generate-tree (article &optional force)
- "Generate the thread tree for ARTICLE if it isn't displayed already."
- (when (save-excursion
- (set-buffer gnus-summary-buffer)
- (and gnus-use-trees
- (vectorp (gnus-summary-article-header article))))
- (save-excursion
- (let ((top (save-excursion
- (set-buffer gnus-summary-buffer)
- (gnus-cut-thread
- (gnus-remove-thread
- (mail-header-id
- (gnus-summary-article-header article)) t))))
- (gnus-tmp-limit gnus-newsgroup-limit)
- (gnus-tmp-sparse gnus-newsgroup-sparse))
- (when (or force
- (not (eq top gnus-tree-displayed-thread)))
- (gnus-generate-tree top)
- (setq gnus-tree-displayed-thread top))))))
-
-(defun gnus-tree-open (group)
- (gnus-get-tree-buffer))
-
-(defun gnus-tree-close (group)
- ;(gnus-kill-buffer gnus-tree-buffer)
- )
-
-(defun gnus-highlight-selected-tree (article)
- "Highlight the selected article in the tree."
- (let ((buf (current-buffer))
- region)
- (set-buffer gnus-tree-buffer)
- (when (setq region (gnus-tree-article-region article))
- (when (or (not gnus-selected-tree-overlay)
- (gnus-extent-detached-p gnus-selected-tree-overlay))
- ;; Create a new overlay.
- (gnus-overlay-put
- (setq gnus-selected-tree-overlay (gnus-make-overlay 1 2))
- 'face gnus-selected-tree-face))
- ;; Move the overlay to the article.
- (gnus-move-overlay
- gnus-selected-tree-overlay (goto-char (car region)) (cdr region))
- (gnus-tree-minimize)
- (gnus-tree-recenter)
- (let ((selected (selected-window)))
- (when (get-buffer-window (set-buffer gnus-tree-buffer) t)
- (select-window (get-buffer-window (set-buffer gnus-tree-buffer) t))
- (gnus-horizontal-recenter)
- (select-window selected))))
- ;; If we remove this save-excursion, it updates the wrong mode lines?!?
- (save-excursion
- (set-buffer gnus-tree-buffer)
- (gnus-set-mode-line 'tree))
- (set-buffer buf)))
-
-(defun gnus-tree-highlight-article (article face)
- (save-excursion
- (set-buffer (gnus-get-tree-buffer))
- (let (region)
- (when (setq region (gnus-tree-article-region article))
- (gnus-put-text-property (car region) (cdr region) 'face face)
- (set-window-point
- (get-buffer-window (current-buffer) t) (cdr region))))))
-
-;;; Allow redefinition of functions.
-(gnus-ems-redefine)
-
-(provide 'gnus-salt)
-
-;;; gnus-salt.el ends here
diff --git a/lisp/gnus-scomo.el b/lisp/gnus-scomo.el
deleted file mode 100644
index 668941c05e2..00000000000
--- a/lisp/gnus-scomo.el
+++ /dev/null
@@ -1,110 +0,0 @@
-;;; gnus-scomo.el --- mode for editing Gnus score files
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news, mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'easymenu)
-(require 'timezone)
-(eval-when-compile (require 'cl))
-
-(defvar gnus-score-mode-hook nil
- "*Hook run in score mode buffers.")
-
-(defvar gnus-score-menu-hook nil
- "*Hook run after creating the score mode menu.")
-
-(defvar gnus-score-edit-exit-function nil
- "Function run on exit from the score buffer.")
-
-(defvar gnus-score-mode-map nil)
-(unless gnus-score-mode-map
- (setq gnus-score-mode-map (copy-keymap emacs-lisp-mode-map))
- (define-key gnus-score-mode-map "\C-c\C-c" 'gnus-score-edit-exit)
- (define-key gnus-score-mode-map "\C-c\C-d" 'gnus-score-edit-insert-date)
- (define-key gnus-score-mode-map "\C-c\C-p" 'gnus-score-pretty-print))
-
-;;;###autoload
-(defun gnus-score-mode ()
- "Mode for editing Gnus score files.
-This mode is an extended emacs-lisp mode.
-
-\\{gnus-score-mode-map}"
- (interactive)
- (kill-all-local-variables)
- (use-local-map gnus-score-mode-map)
- (when menu-bar-mode
- (gnus-score-make-menu-bar))
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (setq major-mode 'gnus-score-mode)
- (setq mode-name "Score")
- (lisp-mode-variables nil)
- (make-local-variable 'gnus-score-edit-exit-function)
- (run-hooks 'emacs-lisp-mode-hook 'gnus-score-mode-hook))
-
-(defun gnus-score-make-menu-bar ()
- (unless (boundp 'gnus-score-menu)
- (easy-menu-define
- gnus-score-menu gnus-score-mode-map ""
- '("Score"
- ["Exit" gnus-score-edit-exit t]
- ["Insert date" gnus-score-edit-insert-date t]
- ["Format" gnus-score-pretty-print t]))
- (run-hooks 'gnus-score-menu-hook)))
-
-(defun gnus-score-edit-insert-date ()
- "Insert date in numerical format."
- (interactive)
- (princ (gnus-score-day-number (current-time)) (current-buffer)))
-
-(defun gnus-score-pretty-print ()
- "Format the current score file."
- (interactive)
- (goto-char (point-min))
- (let ((form (read (current-buffer))))
- (erase-buffer)
- (pp form (current-buffer)))
- (goto-char (point-min)))
-
-(defun gnus-score-edit-exit ()
- "Stop editing the score file."
- (interactive)
- (unless (file-exists-p (file-name-directory (buffer-file-name)))
- (make-directory (file-name-directory (buffer-file-name)) t))
- (save-buffer)
- (bury-buffer (current-buffer))
- (let ((buf (current-buffer)))
- (when gnus-score-edit-exit-function
- (funcall gnus-score-edit-exit-function))
- (when (eq buf (current-buffer))
- (switch-to-buffer (other-buffer (current-buffer))))))
-
-(defun gnus-score-day-number (time)
- (let ((dat (decode-time time)))
- (timezone-absolute-from-gregorian
- (nth 4 dat) (nth 3 dat) (nth 5 dat))))
-
-(provide 'gnus-scomo)
-
-;;; gnus-scomo.el ends here
diff --git a/lisp/gnus-score.el b/lisp/gnus-score.el
deleted file mode 100644
index 523fa13587f..00000000000
--- a/lisp/gnus-score.el
+++ /dev/null
@@ -1,2258 +0,0 @@
-;;; gnus-score.el --- scoring code for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Per Abrahamsen <amanda@iesd.auc.dk>
-;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'gnus)
-(eval-when-compile (require 'cl))
-
-(defvar gnus-global-score-files nil
- "*List of global score files and directories.
-Set this variable if you want to use people's score files. One entry
-for each score file or each score file directory. Gnus will decide
-by itself what score files are applicable to which group.
-
-Say you want to use the single score file
-\"/ftp.ifi.uio.no@ftp:/pub/larsi/ding/score/soc.motss.SCORE\" and all
-score files in the \"/ftp.some-where:/pub/score\" directory.
-
- (setq gnus-global-score-files
- '(\"/ftp.ifi.uio.no:/pub/larsi/ding/score/soc.motss.SCORE\"
- \"/ftp.some-where:/pub/score\"))")
-
-(defvar gnus-score-file-single-match-alist nil
- "*Alist mapping regexps to lists of score files.
-Each element of this alist should be of the form
- (\"REGEXP\" [ \"SCORE-FILE-1\" ] [ \"SCORE-FILE-2\" ] ... )
-
-If the name of a group is matched by REGEXP, the corresponding scorefiles
-will be used for that group.
-The first match found is used, subsequent matching entries are ignored (to
-use multiple matches, see gnus-score-file-multiple-match-alist).
-
-These score files are loaded in addition to any files returned by
-gnus-score-find-score-files-function (which see).")
-
-(defvar gnus-score-file-multiple-match-alist nil
- "*Alist mapping regexps to lists of score files.
-Each element of this alist should be of the form
- (\"REGEXP\" [ \"SCORE-FILE-1\" ] [ \"SCORE-FILE-2\" ] ... )
-
-If the name of a group is matched by REGEXP, the corresponding scorefiles
-will be used for that group.
-If multiple REGEXPs match a group, the score files corresponding to each
-match will be used (for only one match to be used, see
-gnus-score-file-single-match-alist).
-
-These score files are loaded in addition to any files returned by
-gnus-score-find-score-files-function (which see).")
-
-(defvar gnus-score-file-suffix "SCORE"
- "*Suffix of the score files.")
-
-(defvar gnus-adaptive-file-suffix "ADAPT"
- "*Suffix of the adaptive score files.")
-
-(defvar gnus-score-find-score-files-function 'gnus-score-find-bnews
- "*Function used to find score files.
-The function will be called with the group name as the argument, and
-should return a list of score files to apply to that group. The score
-files do not actually have to exist.
-
-Predefined values are:
-
-gnus-score-find-single: Only apply the group's own score file.
-gnus-score-find-hierarchical: Also apply score files from parent groups.
-gnus-score-find-bnews: Apply score files whose names matches.
-
-See the documentation to these functions for more information.
-
-This variable can also be a list of functions to be called. Each
-function should either return a list of score files, or a list of
-score alists.")
-
-(defvar gnus-score-interactive-default-score 1000
- "*Scoring commands will raise/lower the score with this number as the default.")
-
-(defvar gnus-score-expiry-days 7
- "*Number of days before unused score file entries are expired.
-If this variable is nil, no score file entries will be expired.")
-
-(defvar gnus-update-score-entry-dates t
- "*In non-nil, update matching score entry dates.
-If this variable is nil, then score entries that provide matches
-will be expired along with non-matching score entries.")
-
-(defvar gnus-orphan-score nil
- "*All orphans get this score added. Set in the score file.")
-
-(defvar gnus-default-adaptive-score-alist
- '((gnus-kill-file-mark)
- (gnus-unread-mark)
- (gnus-read-mark (from 3) (subject 30))
- (gnus-catchup-mark (subject -10))
- (gnus-killed-mark (from -1) (subject -20))
- (gnus-del-mark (from -2) (subject -15)))
-"*Alist of marks and scores.")
-
-(defvar gnus-score-mimic-keymap nil
- "*Have the score entry functions pretend that they are a keymap.")
-
-(defvar gnus-score-exact-adapt-limit 10
- "*Number that says how long a match has to be before using substring matching.
-When doing adaptive scoring, one normally uses fuzzy or substring
-matching. However, if the header one matches is short, the possibility
-for false positives is great, so if the length of the match is less
-than this variable, exact matching will be used.
-
-If this variable is nil, exact matching will always be used.")
-
-(defvar gnus-score-uncacheable-files "ADAPT$"
- "*All score files that match this regexp will not be cached.")
-
-(defvar gnus-score-default-header nil
- "Default header when entering new scores.
-
-Should be one of the following symbols.
-
- a: from
- s: subject
- b: body
- h: head
- i: message-id
- t: references
- x: xref
- l: lines
- d: date
- f: followup
-
-If nil, the user will be asked for a header.")
-
-(defvar gnus-score-default-type nil
- "Default match type when entering new scores.
-
-Should be one of the following symbols.
-
- s: substring
- e: exact string
- f: fuzzy string
- r: regexp string
- b: before date
- a: at date
- n: this date
- <: less than number
- >: greater than number
- =: equal to number
-
-If nil, the user will be asked for a match type.")
-
-(defvar gnus-score-default-fold nil
- "Use case folding for new score file entries iff not nil.")
-
-(defvar gnus-score-default-duration nil
- "Default duration of effect when entering new scores.
-
-Should be one of the following symbols.
-
- t: temporary
- p: permanent
- i: immediate
-
-If nil, the user will be asked for a duration.")
-
-(defvar gnus-score-after-write-file-function nil
- "*Function called with the name of the score file just written to disk.")
-
-
-
-;; Internal variables.
-
-(defvar gnus-internal-global-score-files nil)
-(defvar gnus-score-file-list nil)
-
-(defvar gnus-short-name-score-file-cache nil)
-
-(defvar gnus-score-help-winconf nil)
-(defvar gnus-adaptive-score-alist gnus-default-adaptive-score-alist)
-(defvar gnus-score-trace nil)
-(defvar gnus-score-edit-buffer nil)
-
-(defvar gnus-score-alist nil
- "Alist containing score information.
-The keys can be symbols or strings. The following symbols are defined.
-
-touched: If this alist has been modified.
-mark: Automatically mark articles below this.
-expunge: Automatically expunge articles below this.
-files: List of other score files to load when loading this one.
-eval: Sexp to be evaluated when the score file is loaded.
-
-String entries have the form (HEADER (MATCH TYPE SCORE DATE) ...)
-where HEADER is the header being scored, MATCH is the string we are
-looking for, TYPE is a flag indicating whether it should use regexp or
-substring matching, SCORE is the score to add and DATE is the date
-of the last successful match.")
-
-(defvar gnus-score-cache nil)
-(defvar gnus-scores-articles nil)
-(defvar gnus-score-index nil)
-
-
-(defconst gnus-header-index
- ;; Name to index alist.
- '(("number" 0 gnus-score-integer)
- ("subject" 1 gnus-score-string)
- ("from" 2 gnus-score-string)
- ("date" 3 gnus-score-date)
- ("message-id" 4 gnus-score-string)
- ("references" 5 gnus-score-string)
- ("chars" 6 gnus-score-integer)
- ("lines" 7 gnus-score-integer)
- ("xref" 8 gnus-score-string)
- ("head" -1 gnus-score-body)
- ("body" -1 gnus-score-body)
- ("all" -1 gnus-score-body)
- ("followup" 2 gnus-score-followup)
- ("thread" 5 gnus-score-thread)))
-
-(eval-and-compile
- (autoload 'gnus-uu-ctl-map "gnus-uu" nil nil 'keymap))
-
-;;; Summary mode score maps.
-
-(gnus-define-keys
- (gnus-summary-score-map "V" gnus-summary-mode-map)
- "s" gnus-summary-set-score
- "a" gnus-summary-score-entry
- "S" gnus-summary-current-score
- "c" gnus-score-change-score-file
- "m" gnus-score-set-mark-below
- "x" gnus-score-set-expunge-below
- "R" gnus-summary-rescore
- "e" gnus-score-edit-current-scores
- "f" gnus-score-edit-file
- "F" gnus-score-flush-cache
- "t" gnus-score-find-trace
- "C" gnus-score-customize)
-
-;; Summary score file commands
-
-;; Much modification of the kill (ahem, score) code and lots of the
-;; functions are written by Per Abrahamsen <amanda@iesd.auc.dk>.
-
-(defun gnus-summary-lower-score (&optional score)
- "Make a score entry based on the current article.
-The user will be prompted for header to score on, match type,
-permanence, and the string to be used. The numerical prefix will be
-used as score."
- (interactive "P")
- (gnus-summary-increase-score (- (gnus-score-default score))))
-
-(defvar gnus-score-default-header nil
- "*The default header to score on when entering a score rule interactively.")
-
-(defvar gnus-score-default-type nil
- "*The default score type to use when entering a score rule interactively.")
-
-(defvar gnus-score-default-duration nil
- "*The default score duration to use on when entering a score rule interactively.")
-
-(defun gnus-score-kill-help-buffer ()
- (when (get-buffer "*Score Help*")
- (kill-buffer "*Score Help*")
- (and gnus-score-help-winconf
- (set-window-configuration gnus-score-help-winconf))))
-
-(defun gnus-summary-increase-score (&optional score)
- "Make a score entry based on the current article.
-The user will be prompted for header to score on, match type,
-permanence, and the string to be used. The numerical prefix will be
-used as score."
- (interactive "P")
- (gnus-set-global-variables)
- (let* ((nscore (gnus-score-default score))
- (prefix (if (< nscore 0) ?L ?I))
- (increase (> nscore 0))
- (char-to-header
- '((?a "from" nil nil string)
- (?s "subject" nil nil string)
- (?b "body" "" nil body-string)
- (?h "head" "" nil body-string)
- (?i "message-id" nil t string)
- (?t "references" "message-id" nil string)
- (?x "xref" nil nil string)
- (?l "lines" nil nil number)
- (?d "date" nil nil date)
- (?f "followup" nil nil string)
- (?T "thread" nil nil string)))
- (char-to-type
- '((?s s "substring" string)
- (?e e "exact string" string)
- (?f f "fuzzy string" string)
- (?r r "regexp string" string)
- (?z s "substring" body-string)
- (?p s "regexp string" body-string)
- (?b before "before date" date)
- (?a at "at date" date)
- (?n now "this date" date)
- (?< < "less than number" number)
- (?> > "greater than number" number)
- (?= = "equal to number" number)))
- (char-to-perm
- (list (list ?t (current-time-string) "temporary")
- '(?p perm "permanent") '(?i now "immediate")))
- (mimic gnus-score-mimic-keymap)
- (hchar (and gnus-score-default-header
- (aref (symbol-name gnus-score-default-header) 0)))
- (tchar (and gnus-score-default-type
- (aref (symbol-name gnus-score-default-type) 0)))
- (pchar (and gnus-score-default-duration
- (aref (symbol-name gnus-score-default-duration) 0)))
- entry temporary type match)
-
- (unwind-protect
- (progn
-
- ;; First we read the header to score.
- (while (not hchar)
- (if mimic
- (progn
- (sit-for 1)
- (message "%c-" prefix))
- (message "%s header (%s?): " (if increase "Increase" "Lower")
- (mapconcat (lambda (s) (char-to-string (car s)))
- char-to-header "")))
- (setq hchar (read-char))
- (when (or (= hchar ??) (= hchar ?\C-h))
- (setq hchar nil)
- (gnus-score-insert-help "Match on header" char-to-header 1)))
-
- (gnus-score-kill-help-buffer)
- (unless (setq entry (assq (downcase hchar) char-to-header))
- (if mimic (error "%c %c" prefix hchar) (error "")))
-
- (when (/= (downcase hchar) hchar)
- ;; This was a majuscle, so we end reading and set the defaults.
- (if mimic (message "%c %c" prefix hchar) (message ""))
- (setq tchar (or tchar ?s)
- pchar (or pchar ?t)))
-
- ;; We continue reading - the type.
- (while (not tchar)
- (if mimic
- (progn
- (sit-for 1) (message "%c %c-" prefix hchar))
- (message "%s header '%s' with match type (%s?): "
- (if increase "Increase" "Lower")
- (nth 1 entry)
- (mapconcat (lambda (s)
- (if (eq (nth 4 entry)
- (nth 3 s))
- (char-to-string (car s))
- ""))
- char-to-type "")))
- (setq tchar (read-char))
- (when (or (= tchar ??) (= tchar ?\C-h))
- (setq tchar nil)
- (gnus-score-insert-help
- "Match type"
- (delq nil
- (mapcar (lambda (s)
- (if (eq (nth 4 entry)
- (nth 3 s))
- s nil))
- char-to-type ))
- 2)))
-
- (gnus-score-kill-help-buffer)
- (unless (setq type (nth 1 (assq (downcase tchar) char-to-type)))
- (if mimic (error "%c %c" prefix hchar) (error "")))
-
- (when (/= (downcase tchar) tchar)
- ;; It was a majuscle, so we end reading and the the default.
- (if mimic (message "%c %c %c" prefix hchar tchar)
- (message ""))
- (setq pchar (or pchar ?p)))
-
- ;; We continue reading.
- (while (not pchar)
- (if mimic
- (progn
- (sit-for 1) (message "%c %c %c-" prefix hchar tchar))
- (message "%s permanence (%s?): " (if increase "Increase" "Lower")
- (mapconcat (lambda (s) (char-to-string (car s)))
- char-to-perm "")))
- (setq pchar (read-char))
- (when (or (= pchar ??) (= pchar ?\C-h))
- (setq pchar nil)
- (gnus-score-insert-help "Match permanence" char-to-perm 2)))
-
- (gnus-score-kill-help-buffer)
- (if mimic (message "%c %c %c" prefix hchar tchar pchar)
- (message ""))
- (unless (setq temporary (cadr (assq pchar char-to-perm)))
- (if mimic
- (error "%c %c %c %c" prefix hchar tchar pchar)
- (error ""))))
- ;; Always kill the score help buffer.
- (gnus-score-kill-help-buffer))
-
- ;; We have all the data, so we enter this score.
- (setq match (if (string= (nth 2 entry) "") ""
- (gnus-summary-header (or (nth 2 entry) (nth 1 entry)))))
-
- ;; Modify the match, perhaps.
- (cond
- ((equal (nth 1 entry) "xref")
- (when (string-match "^Xref: *" match)
- (setq match (substring match (match-end 0))))
- (when (string-match "^[^:]* +" match)
- (setq match (substring match (match-end 0))))))
-
- (when (memq type '(r R regexp Regexp))
- (setq match (regexp-quote match)))
-
- (gnus-summary-score-entry
- (nth 1 entry) ; Header
- match ; Match
- type ; Type
- (if (eq 's score) nil score) ; Score
- (if (eq 'perm temporary) ; Temp
- nil
- temporary)
- (not (nth 3 entry))) ; Prompt
- ))
-
-(defun gnus-score-insert-help (string alist idx)
- (setq gnus-score-help-winconf (current-window-configuration))
- (save-excursion
- (set-buffer (get-buffer-create "*Score Help*"))
- (buffer-disable-undo (current-buffer))
- (delete-windows-on (current-buffer))
- (erase-buffer)
- (insert string ":\n\n")
- (let ((max -1)
- (list alist)
- (i 0)
- n width pad format)
- ;; find the longest string to display
- (while list
- (setq n (length (nth idx (car list))))
- (or (> max n)
- (setq max n))
- (setq list (cdr list)))
- (setq max (+ max 4)) ; %c, `:', SPACE, a SPACE at end
- (setq n (/ (1- (window-width)) max)) ; items per line
- (setq width (/ (1- (window-width)) n)) ; width of each item
- ;; insert `n' items, each in a field of width `width'
- (while alist
- (if (< i n)
- ()
- (setq i 0)
- (delete-char -1) ; the `\n' takes a char
- (insert "\n"))
- (setq pad (- width 3))
- (setq format (concat "%c: %-" (int-to-string pad) "s"))
- (insert (format format (caar alist) (nth idx (car alist))))
- (setq alist (cdr alist))
- (setq i (1+ i))))
- ;; display ourselves in a small window at the bottom
- (gnus-appt-select-lowest-window)
- (split-window)
- (pop-to-buffer "*Score Help*")
- (let ((window-min-height 1))
- (shrink-window-if-larger-than-buffer))
- (select-window (get-buffer-window gnus-summary-buffer))))
-
-(defun gnus-summary-header (header &optional no-err)
- ;; Return HEADER for current articles, or error.
- (let ((article (gnus-summary-article-number))
- headers)
- (if article
- (if (and (setq headers (gnus-summary-article-header article))
- (vectorp headers))
- (aref headers (nth 1 (assoc header gnus-header-index)))
- (if no-err
- nil
- (error "Pseudo-articles can't be scored")))
- (if no-err
- (error "No article on current line")
- nil))))
-
-(defun gnus-newsgroup-score-alist ()
- (or
- (let ((param-file (gnus-group-get-parameter
- gnus-newsgroup-name 'score-file)))
- (when param-file
- (gnus-score-load param-file)))
- (gnus-score-load
- (gnus-score-file-name gnus-newsgroup-name)))
- gnus-score-alist)
-
-(defsubst gnus-score-get (symbol &optional alist)
- ;; Get SYMBOL's definition in ALIST.
- (cdr (assoc symbol
- (or alist
- gnus-score-alist
- (gnus-newsgroup-score-alist)))))
-
-(defun gnus-summary-score-entry
- (header match type score date &optional prompt silent)
- "Enter score file entry.
-HEADER is the header being scored.
-MATCH is the string we are looking for.
-TYPE is the match type: substring, regexp, exact, fuzzy.
-SCORE is the score to add.
-DATE is the expire date, or nil for no expire, or 'now for immediate expire.
-If optional argument `PROMPT' is non-nil, allow user to edit match.
-If optional argument `SILENT' is nil, show effect of score entry."
- (interactive
- (list (completing-read "Header: "
- gnus-header-index
- (lambda (x) (fboundp (nth 2 x)))
- t)
- (read-string "Match: ")
- (if (y-or-n-p "Use regexp match? ") 'r 's)
- (and current-prefix-arg
- (prefix-numeric-value current-prefix-arg))
- (cond ((not (y-or-n-p "Add to score file? "))
- 'now)
- ((y-or-n-p "Expire kill? ")
- (current-time-string))
- (t nil))))
- ;; Regexp is the default type.
- (if (eq type t) (setq type 'r))
- ;; Simplify matches...
- (cond ((or (eq type 'r) (eq type 's) (eq type nil))
- (setq match (if match (gnus-simplify-subject-re match) "")))
- ((eq type 'f)
- (setq match (gnus-simplify-subject-fuzzy match))))
- (let ((score (gnus-score-default score))
- (header (format "%s" (downcase header)))
- new)
- (and prompt (setq match (read-string
- (format "Match %s on %s, %s: "
- (cond ((eq date 'now)
- "now")
- ((stringp date)
- "temp")
- (t "permanent"))
- header
- (if (< score 0) "lower" "raise"))
- (if (numberp match)
- (int-to-string match)
- match))))
-
- ;; Get rid of string props.
- (setq match (format "%s" match))
-
- ;; If this is an integer comparison, we transform from string to int.
- (and (eq (nth 2 (assoc header gnus-header-index)) 'gnus-score-integer)
- (setq match (string-to-int match)))
-
- (unless (eq date 'now)
- ;; Add the score entry to the score file.
- (when (= score gnus-score-interactive-default-score)
- (setq score nil))
- (let ((old (gnus-score-get header))
- elem)
- (setq new
- (cond
- (type (list match score (and date (gnus-day-number date)) type))
- (date (list match score (gnus-day-number date)))
- (score (list match score))
- (t (list match))))
- ;; We see whether we can collapse some score entries.
- ;; This isn't quite correct, because there may be more elements
- ;; later on with the same key that have matching elems... Hm.
- (if (and old
- (setq elem (assoc match old))
- (eq (nth 3 elem) (nth 3 new))
- (or (and (numberp (nth 2 elem)) (numberp (nth 2 new)))
- (and (not (nth 2 elem)) (not (nth 2 new)))))
- ;; Yup, we just add this new score to the old elem.
- (setcar (cdr elem) (+ (or (nth 1 elem)
- gnus-score-interactive-default-score)
- (or (nth 1 new)
- gnus-score-interactive-default-score)))
- ;; Nope, we have to add a new elem.
- (gnus-score-set header (if old (cons new old) (list new))))
- (gnus-score-set 'touched '(t))))
-
- ;; Score the current buffer.
- (unless silent
- (if (and (>= (nth 1 (assoc header gnus-header-index)) 0)
- (eq (nth 2 (assoc header gnus-header-index))
- 'gnus-score-string))
- (gnus-summary-score-effect header match type score)
- (gnus-summary-rescore)))
-
- ;; Return the new scoring rule.
- new))
-
-(defun gnus-summary-score-effect (header match type score)
- "Simulate the effect of a score file entry.
-HEADER is the header being scored.
-MATCH is the string we are looking for.
-TYPE is a flag indicating if it is a regexp or substring.
-SCORE is the score to add."
- (interactive (list (completing-read "Header: "
- gnus-header-index
- (lambda (x) (fboundp (nth 2 x)))
- t)
- (read-string "Match: ")
- (y-or-n-p "Use regexp match? ")
- (prefix-numeric-value current-prefix-arg)))
- (save-excursion
- (or (and (stringp match) (> (length match) 0))
- (error "No match"))
- (goto-char (point-min))
- (let ((regexp (cond ((eq type 'f)
- (gnus-simplify-subject-fuzzy match))
- ((eq type 'r)
- match)
- ((eq type 'e)
- (concat "\\`" (regexp-quote match) "\\'"))
- (t
- (regexp-quote match)))))
- (while (not (eobp))
- (let ((content (gnus-summary-header header 'noerr))
- (case-fold-search t))
- (and content
- (if (if (eq type 'f)
- (string-equal (gnus-simplify-subject-fuzzy content)
- regexp)
- (string-match regexp content))
- (gnus-summary-raise-score score))))
- (beginning-of-line 2)))))
-
-(defun gnus-summary-score-crossposting (score date)
- ;; Enter score file entry for current crossposting.
- ;; SCORE is the score to add.
- ;; DATE is the expire date.
- (let ((xref (gnus-summary-header "xref"))
- (start 0)
- group)
- (or xref (error "This article is not crossposted"))
- (while (string-match " \\([^ \t]+\\):" xref start)
- (setq start (match-end 0))
- (if (not (string=
- (setq group
- (substring xref (match-beginning 1) (match-end 1)))
- gnus-newsgroup-name))
- (gnus-summary-score-entry
- "xref" (concat " " group ":") nil score date t)))))
-
-
-;;;
-;;; Gnus Score Files
-;;;
-
-;; All score code written by Per Abrahamsen <abraham@iesd.auc.dk>.
-
-;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
-(defun gnus-score-set-mark-below (score)
- "Automatically mark articles with score below SCORE as read."
- (interactive
- (list (or (and current-prefix-arg (prefix-numeric-value current-prefix-arg))
- (string-to-int (read-string "Mark below: ")))))
- (setq score (or score gnus-summary-default-score 0))
- (gnus-score-set 'mark (list score))
- (gnus-score-set 'touched '(t))
- (setq gnus-summary-mark-below score)
- (gnus-score-update-lines))
-
-(defun gnus-score-update-lines ()
- "Update all lines in the summary buffer."
- (save-excursion
- (goto-char (point-min))
- (while (not (eobp))
- (gnus-summary-update-line)
- (forward-line 1))))
-
-(defun gnus-score-update-all-lines ()
- "Update all lines in the summary buffer, even the hidden ones."
- (save-excursion
- (goto-char (point-min))
- (let (hidden)
- (while (not (eobp))
- (when (gnus-summary-show-thread)
- (push (point) hidden))
- (gnus-summary-update-line)
- (forward-line 1))
- ;; Re-hide the hidden threads.
- (while hidden
- (goto-char (pop hidden))
- (gnus-summary-hide-thread)))))
-
-(defun gnus-score-set-expunge-below (score)
- "Automatically expunge articles with score below SCORE."
- (interactive
- (list (or (and current-prefix-arg (prefix-numeric-value current-prefix-arg))
- (string-to-int (read-string "Expunge below: ")))))
- (setq score (or score gnus-summary-default-score 0))
- (gnus-score-set 'expunge (list score))
- (gnus-score-set 'touched '(t)))
-
-(defun gnus-score-followup-article (&optional score)
- "Add SCORE to all followups to the article in the current buffer."
- (interactive "P")
- (setq score (gnus-score-default score))
- (when (gnus-buffer-live-p gnus-summary-buffer)
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (let ((id (mail-fetch-field "message-id")))
- (when id
- (set-buffer gnus-summary-buffer)
- (gnus-summary-score-entry
- "references" (concat id "[ \t]*$") 'r
- score (current-time-string) nil t)))))))
-
-(defun gnus-score-followup-thread (&optional score)
- "Add SCORE to all later articles in the thread the current buffer is part of."
- (interactive "P")
- (setq score (gnus-score-default score))
- (when (gnus-buffer-live-p gnus-summary-buffer)
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (let ((id (mail-fetch-field "message-id")))
- (when id
- (set-buffer gnus-summary-buffer)
- (gnus-summary-score-entry
- "references" id 's
- score (current-time-string))))))))
-
-(defun gnus-score-set (symbol value &optional alist)
- ;; Set SYMBOL to VALUE in ALIST.
- (let* ((alist
- (or alist
- gnus-score-alist
- (gnus-newsgroup-score-alist)))
- (entry (assoc symbol alist)))
- (cond ((gnus-score-get 'read-only alist)
- ;; This is a read-only score file, so we do nothing.
- )
- (entry
- (setcdr entry value))
- ((null alist)
- (error "Empty alist"))
- (t
- (setcdr alist
- (cons (cons symbol value) (cdr alist)))))))
-
-(defun gnus-summary-raise-score (n)
- "Raise the score of the current article by N."
- (interactive "p")
- (gnus-set-global-variables)
- (gnus-summary-set-score (+ (gnus-summary-article-score)
- (or n gnus-score-interactive-default-score ))))
-
-(defun gnus-summary-set-score (n)
- "Set the score of the current article to N."
- (interactive "p")
- (gnus-set-global-variables)
- (save-excursion
- (gnus-summary-show-thread)
- (let ((buffer-read-only nil))
- ;; Set score.
- (gnus-summary-update-mark
- (if (= n (or gnus-summary-default-score 0)) ?
- (if (< n (or gnus-summary-default-score 0))
- gnus-score-below-mark gnus-score-over-mark)) 'score))
- (let* ((article (gnus-summary-article-number))
- (score (assq article gnus-newsgroup-scored)))
- (if score (setcdr score n)
- (setq gnus-newsgroup-scored
- (cons (cons article n) gnus-newsgroup-scored))))
- (gnus-summary-update-line)))
-
-(defun gnus-summary-current-score ()
- "Return the score of the current article."
- (interactive)
- (gnus-set-global-variables)
- (gnus-message 1 "%s" (gnus-summary-article-score)))
-
-(defun gnus-score-change-score-file (file)
- "Change current score alist."
- (interactive
- (list (read-file-name "Change to score file: " gnus-kill-files-directory)))
- (gnus-score-load-file file)
- (gnus-set-mode-line 'summary))
-
-(defvar gnus-score-edit-exit-function)
-(defun gnus-score-edit-current-scores (file)
- "Edit the current score alist."
- (interactive (list gnus-current-score-file))
- (let ((winconf (current-window-configuration)))
- (and (buffer-name gnus-summary-buffer) (gnus-score-save))
- (gnus-make-directory (file-name-directory file))
- (setq gnus-score-edit-buffer (find-file-noselect file))
- (gnus-configure-windows 'edit-score)
- (gnus-score-mode)
- (setq gnus-score-edit-exit-function 'gnus-score-edit-done)
- (make-local-variable 'gnus-prev-winconf)
- (setq gnus-prev-winconf winconf))
- (gnus-message
- 4 (substitute-command-keys
- "\\<gnus-score-mode-map>\\[gnus-score-edit-exit] to save edits")))
-
-(defun gnus-score-edit-file (file)
- "Edit a score file."
- (interactive
- (list (read-file-name "Edit score file: " gnus-kill-files-directory)))
- (gnus-make-directory (file-name-directory file))
- (and (buffer-name gnus-summary-buffer) (gnus-score-save))
- (let ((winconf (current-window-configuration)))
- (setq gnus-score-edit-buffer (find-file-noselect file))
- (gnus-configure-windows 'edit-score)
- (gnus-score-mode)
- (setq gnus-score-edit-exit-function 'gnus-score-edit-done)
- (make-local-variable 'gnus-prev-winconf)
- (setq gnus-prev-winconf winconf))
- (gnus-message
- 4 (substitute-command-keys
- "\\<gnus-score-mode-map>\\[gnus-score-edit-exit] to save edits")))
-
-(defun gnus-score-load-file (file)
- ;; Load score file FILE. Returns a list a retrieved score-alists.
- (let* ((file (expand-file-name
- (or (and (string-match
- (concat "^" (expand-file-name
- gnus-kill-files-directory))
- (expand-file-name file))
- file)
- (concat (file-name-as-directory gnus-kill-files-directory)
- file))))
- (cached (assoc file gnus-score-cache))
- (global (member file gnus-internal-global-score-files))
- lists alist)
- (if cached
- ;; The score file was already loaded.
- (setq alist (cdr cached))
- ;; We load the score file.
- (setq gnus-score-alist nil)
- (setq alist (gnus-score-load-score-alist file))
- ;; We add '(touched) to the alist to signify that it hasn't been
- ;; touched (yet).
- (or (assq 'touched alist) (setq alist (cons (list 'touched nil) alist)))
- ;; If it is a global score file, we make it read-only.
- (and global
- (not (assq 'read-only alist))
- (setq alist (cons (list 'read-only t) alist)))
- (setq gnus-score-cache
- (cons (cons file alist) gnus-score-cache)))
- (let ((a alist)
- found)
- (while a
- ;; Downcase all header names.
- (when (stringp (caar a))
- (setcar (car a) (downcase (caar a)))
- (setq found t))
- (pop a))
- ;; If there are actual scores in the alist, we add it to the
- ;; return value of this function.
- (when found
- (setq lists (list alist))))
- ;; Treat the other possible atoms in the score alist.
- (let ((mark (car (gnus-score-get 'mark alist)))
- (expunge (car (gnus-score-get 'expunge alist)))
- (mark-and-expunge (car (gnus-score-get 'mark-and-expunge alist)))
- (files (gnus-score-get 'files alist))
- (exclude-files (gnus-score-get 'exclude-files alist))
- (orphan (car (gnus-score-get 'orphan alist)))
- (adapt (gnus-score-get 'adapt alist))
- (thread-mark-and-expunge
- (car (gnus-score-get 'thread-mark-and-expunge alist)))
- (adapt-file (car (gnus-score-get 'adapt-file alist)))
- (local (gnus-score-get 'local alist))
- (eval (car (gnus-score-get 'eval alist))))
- ;; We do not respect eval and files atoms from global score
- ;; files.
- (and files (not global)
- (setq lists (apply 'append lists
- (mapcar (lambda (file)
- (gnus-score-load-file file))
- (if adapt-file (cons adapt-file files)
- files)))))
- (and eval (not global) (eval eval))
- ;; We then expand any exclude-file directives.
- (setq gnus-scores-exclude-files
- (nconc
- (mapcar
- (lambda (sfile)
- (expand-file-name sfile (file-name-directory file)))
- exclude-files) gnus-scores-exclude-files))
- (if (not local)
- ()
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (while local
- (and (consp (car local))
- (symbolp (caar local))
- (progn
- (make-local-variable (caar local))
- (set (caar local) (nth 1 (car local)))))
- (setq local (cdr local)))))
- (if orphan (setq gnus-orphan-score orphan))
- (setq gnus-adaptive-score-alist
- (cond ((equal adapt '(t))
- (setq gnus-newsgroup-adaptive t)
- gnus-default-adaptive-score-alist)
- ((equal adapt '(ignore))
- (setq gnus-newsgroup-adaptive nil))
- ((consp adapt)
- (setq gnus-newsgroup-adaptive t)
- adapt)
- (t
- ;;(setq gnus-newsgroup-adaptive gnus-use-adaptive-scoring)
- gnus-default-adaptive-score-alist)))
- (setq gnus-thread-expunge-below
- (or thread-mark-and-expunge gnus-thread-expunge-below))
- (setq gnus-summary-mark-below
- (or mark mark-and-expunge gnus-summary-mark-below))
- (setq gnus-summary-expunge-below
- (or expunge mark-and-expunge gnus-summary-expunge-below))
- (setq gnus-newsgroup-adaptive-score-file
- (or adapt-file gnus-newsgroup-adaptive-score-file)))
- (setq gnus-current-score-file file)
- (setq gnus-score-alist alist)
- lists))
-
-(defun gnus-score-load (file)
- ;; Load score FILE.
- (let ((cache (assoc file gnus-score-cache)))
- (if cache
- (setq gnus-score-alist (cdr cache))
- (setq gnus-score-alist nil)
- (gnus-score-load-score-alist file)
- (or gnus-score-alist
- (setq gnus-score-alist (copy-alist '((touched nil)))))
- (setq gnus-score-cache
- (cons (cons file gnus-score-alist) gnus-score-cache)))))
-
-(defun gnus-score-remove-from-cache (file)
- (setq gnus-score-cache
- (delq (assoc file gnus-score-cache) gnus-score-cache)))
-
-(defun gnus-score-load-score-alist (file)
- (let (alist)
- (if (not (file-readable-p file))
- (setq gnus-score-alist nil)
- (save-excursion
- (gnus-set-work-buffer)
- (insert-file-contents file)
- (goto-char (point-min))
- ;; Only do the loading if the score file isn't empty.
- (when (save-excursion (re-search-forward "[()0-9a-zA-Z]" nil t))
- (setq alist
- (condition-case ()
- (read (current-buffer))
- (error
- (progn
- (gnus-message 3 "Problem with score file %s" file)
- (ding)
- (sit-for 2)
- nil))))))
- (if (eq (car alist) 'setq)
- ;; This is an old-style score file.
- (setq gnus-score-alist (gnus-score-transform-old-to-new alist))
- (setq gnus-score-alist alist))
- ;; Check the syntax of the score file.
- (setq gnus-score-alist
- (gnus-score-check-syntax gnus-score-alist file)))))
-
-(defun gnus-score-check-syntax (alist file)
- "Check the syntax of the score ALIST."
- (cond
- ((null alist)
- nil)
- ((not (consp alist))
- (gnus-message 1 "Score file is not a list: %s" file)
- (ding)
- nil)
- (t
- (let ((a alist)
- sr err s type)
- (while (and a (not err))
- (setq
- err
- (cond
- ((not (listp (car a)))
- (format "Illegal score element %s in %s" (car a) file))
- ((stringp (caar a))
- (cond
- ((not (listp (setq sr (cdar a))))
- (format "Illegal header match %s in %s" (nth 1 (car a)) file))
- (t
- (setq type (caar a))
- (while (and sr (not err))
- (setq s (pop sr))
- (setq
- err
- (cond
- ((if (member (downcase type) '("lines" "chars"))
- (not (numberp (car s)))
- (not (stringp (car s))))
- (format "Illegal match %s in %s" (car s) file))
- ((and (cadr s) (not (integerp (cadr s))))
- (format "Non-integer score %s in %s" (cadr s) file))
- ((and (caddr s) (not (integerp (caddr s))))
- (format "Non-integer date %s in %s" (caddr s) file))
- ((and (cadddr s) (not (symbolp (cadddr s))))
- (format "Non-symbol match type %s in %s" (cadddr s) file)))))
- err)))))
- (setq a (cdr a)))
- (if err
- (progn
- (ding)
- (gnus-message 3 err)
- (sit-for 2)
- nil)
- alist)))))
-
-(defun gnus-score-transform-old-to-new (alist)
- (let* ((alist (nth 2 alist))
- out entry)
- (if (eq (car alist) 'quote)
- (setq alist (nth 1 alist)))
- (while alist
- (setq entry (car alist))
- (if (stringp (car entry))
- (let ((scor (cdr entry)))
- (setq out (cons entry out))
- (while scor
- (setcar scor
- (list (caar scor) (nth 2 (car scor))
- (and (nth 3 (car scor))
- (gnus-day-number (nth 3 (car scor))))
- (if (nth 1 (car scor)) 'r 's)))
- (setq scor (cdr scor))))
- (setq out (cons (if (not (listp (cdr entry)))
- (list (car entry) (cdr entry))
- entry)
- out)))
- (setq alist (cdr alist)))
- (cons (list 'touched t) (nreverse out))))
-
-(defun gnus-score-save ()
- ;; Save all score information.
- (let ((cache gnus-score-cache))
- (save-excursion
- (setq gnus-score-alist nil)
- (set-buffer (get-buffer-create "*Score*"))
- (buffer-disable-undo (current-buffer))
- (let (entry score file)
- (while cache
- (setq entry (car cache)
- cache (cdr cache)
- file (car entry)
- score (cdr entry))
- (if (or (not (equal (gnus-score-get 'touched score) '(t)))
- (gnus-score-get 'read-only score)
- (and (file-exists-p file)
- (not (file-writable-p file))))
- ()
- (setq score (setcdr entry (delq (assq 'touched score) score)))
- (erase-buffer)
- (let (emacs-lisp-mode-hook)
- (if (string-match
- (concat (regexp-quote gnus-adaptive-file-suffix)
- "$") file)
- ;; This is an adaptive score file, so we do not run
- ;; it through `pp'. These files can get huge, and
- ;; are not meant to be edited by human hands.
- (prin1 score (current-buffer))
- ;; This is a normal score file, so we print it very
- ;; prettily.
- (pp score (current-buffer))))
- (if (not (gnus-make-directory (file-name-directory file)))
- ()
- ;; If the score file is empty, we delete it.
- (if (zerop (buffer-size))
- (delete-file file)
- ;; There are scores, so we write the file.
- (when (file-writable-p file)
- (write-region (point-min) (point-max) file nil 'silent)
- (and gnus-score-after-write-file-function
- (funcall gnus-score-after-write-file-function file)))))
- (and gnus-score-uncacheable-files
- (string-match gnus-score-uncacheable-files file)
- (gnus-score-remove-from-cache file)))))
- (kill-buffer (current-buffer)))))
-
-(defun gnus-score-headers (score-files &optional trace)
- ;; Score `gnus-newsgroup-headers'.
- (let (scores news)
- ;; PLM: probably this is not the best place to clear orphan-score
- (setq gnus-orphan-score nil)
- (setq gnus-scores-articles nil)
- (setq gnus-scores-exclude-files nil)
- ;; Load the score files.
- (while score-files
- (if (stringp (car score-files))
- ;; It is a string, which means that it's a score file name,
- ;; so we load the score file and add the score alist to
- ;; the list of alists.
- (setq scores (nconc (gnus-score-load-file (car score-files)) scores))
- ;; It is an alist, so we just add it to the list directly.
- (setq scores (nconc (car score-files) scores)))
- (setq score-files (cdr score-files)))
- ;; Prune the score files that are to be excluded, if any.
- (when gnus-scores-exclude-files
- (let ((s scores)
- c)
- (while s
- (and (setq c (rassq (car s) gnus-score-cache))
- (member (car c) gnus-scores-exclude-files)
- (setq scores (delq (car s) scores)))
- (setq s (cdr s)))))
- (setq news scores)
- ;; Do the scoring.
- (while news
- (setq scores news
- news nil)
- (when (and gnus-summary-default-score
- scores)
- (let* ((entries gnus-header-index)
- (now (gnus-day-number (current-time-string)))
- (expire (and gnus-score-expiry-days
- (- now gnus-score-expiry-days)))
- (headers gnus-newsgroup-headers)
- (current-score-file gnus-current-score-file)
- entry header new)
- (gnus-message 5 "Scoring...")
- ;; Create articles, an alist of the form `(HEADER . SCORE)'.
- (while (setq header (pop headers))
- ;; WARNING: The assq makes the function O(N*S) while it could
- ;; be written as O(N+S), where N is (length gnus-newsgroup-headers)
- ;; and S is (length gnus-newsgroup-scored).
- (or (assq (mail-header-number header) gnus-newsgroup-scored)
- (setq gnus-scores-articles ;Total of 2 * N cons-cells used.
- (cons (cons header (or gnus-summary-default-score 0))
- gnus-scores-articles))))
-
- (save-excursion
- (set-buffer (get-buffer-create "*Headers*"))
- (buffer-disable-undo (current-buffer))
-
- ;; Set the global variant of this variable.
- (setq gnus-current-score-file current-score-file)
- ;; score orphans
- (when gnus-orphan-score
- (setq gnus-score-index
- (nth 1 (assoc "references" gnus-header-index)))
- (gnus-score-orphans gnus-orphan-score))
- ;; Run each header through the score process.
- (while entries
- (setq entry (pop entries)
- header (nth 0 entry)
- gnus-score-index (nth 1 (assoc header gnus-header-index)))
- (when (< 0 (apply 'max (mapcar
- (lambda (score)
- (length (gnus-score-get header score)))
- scores)))
- ;; Call the scoring function for this type of "header".
- (when (setq new (funcall (nth 2 entry) scores header
- now expire trace))
- (push new news))))
- ;; Remove the buffer.
- (kill-buffer (current-buffer)))
-
- ;; Add articles to `gnus-newsgroup-scored'.
- (while gnus-scores-articles
- (or (= gnus-summary-default-score (cdar gnus-scores-articles))
- (setq gnus-newsgroup-scored
- (cons (cons (mail-header-number
- (caar gnus-scores-articles))
- (cdar gnus-scores-articles))
- gnus-newsgroup-scored)))
- (setq gnus-scores-articles (cdr gnus-scores-articles)))
-
- (gnus-message 5 "Scoring...done"))))))
-
-
-(defun gnus-get-new-thread-ids (articles)
- (let ((index (nth 1 (assoc "message-id" gnus-header-index)))
- (refind gnus-score-index)
- id-list art this tref)
- (while articles
- (setq art (car articles)
- this (aref (car art) index)
- tref (aref (car art) refind)
- articles (cdr articles))
- (if (string-equal tref "") ;no references line
- (setq id-list (cons this id-list))))
- id-list))
-
-;; Orphan functions written by plm@atcmp.nl (Peter Mutsaers).
-(defun gnus-score-orphans (score)
- (let ((new-thread-ids (gnus-get-new-thread-ids gnus-scores-articles))
- alike articles art arts this last this-id)
-
- (setq gnus-scores-articles (sort gnus-scores-articles 'gnus-score-string<)
- articles gnus-scores-articles)
-
- ;;more or less the same as in gnus-score-string
- (erase-buffer)
- (while articles
- (setq art (car articles)
- this (aref (car art) gnus-score-index)
- articles (cdr articles))
- ;;completely skip if this is empty (not a child, so not an orphan)
- (if (not (string= this ""))
- (if (equal last this)
- ;; O(N*H) cons-cells used here, where H is the number of
- ;; headers.
- (setq alike (cons art alike))
- (if last
- (progn
- ;; Insert the line, with a text property on the
- ;; terminating newline referring to the articles with
- ;; this line.
- (insert last ?\n)
- (put-text-property (1- (point)) (point) 'articles alike)))
- (setq alike (list art)
- last this))))
- (and last ; Bwadr, duplicate code.
- (progn
- (insert last ?\n)
- (put-text-property (1- (point)) (point) 'articles alike)))
-
- ;; PLM: now delete those lines that contain an entry from new-thread-ids
- (while new-thread-ids
- (setq this-id (car new-thread-ids)
- new-thread-ids (cdr new-thread-ids))
- (goto-char (point-min))
- (while (search-forward this-id nil t)
- ;; found a match. remove this line
- (beginning-of-line)
- (kill-line 1)))
-
- ;; now for each line: update its articles with score by moving to
- ;; every end-of-line in the buffer and read the articles property
- (goto-char (point-min))
- (while (eq 0 (progn
- (end-of-line)
- (setq arts (get-text-property (point) 'articles))
- (while arts
- (setq art (car arts)
- arts (cdr arts))
- (setcdr art (+ score (cdr art))))
- (forward-line))))))
-
-
-(defun gnus-score-integer (scores header now expire &optional trace)
- (let ((gnus-score-index (nth 1 (assoc header gnus-header-index)))
- entries alist)
-
- ;; Find matches.
- (while scores
- (setq alist (car scores)
- scores (cdr scores)
- entries (assoc header alist))
- (while (cdr entries) ;First entry is the header index.
- (let* ((rest (cdr entries))
- (kill (car rest))
- (match (nth 0 kill))
- (type (or (nth 3 kill) '>))
- (score (or (nth 1 kill) gnus-score-interactive-default-score))
- (date (nth 2 kill))
- (found nil)
- (match-func (if (or (eq type '>) (eq type '<) (eq type '<=)
- (eq type '>=) (eq type '=))
- type
- (error "Illegal match type: %s" type)))
- (articles gnus-scores-articles))
- ;; Instead of doing all the clever stuff that
- ;; `gnus-score-string' does to minimize searches and stuff,
- ;; I will assume that people generally will put so few
- ;; matches on numbers that any cleverness will take more
- ;; time than one would gain.
- (while articles
- (and (funcall match-func
- (or (aref (caar articles) gnus-score-index) 0)
- match)
- (progn
- (and trace (setq gnus-score-trace
- (cons
- (cons
- (car-safe (rassq alist gnus-score-cache))
- kill)
- gnus-score-trace)))
- (setq found t)
- (setcdr (car articles) (+ score (cdar articles)))))
- (setq articles (cdr articles)))
- ;; Update expire date
- (cond ((null date)) ;Permanent entry.
- ((and found gnus-update-score-entry-dates) ;Match, update date.
- (gnus-score-set 'touched '(t) alist)
- (setcar (nthcdr 2 kill) now))
- ((and expire (< date expire)) ;Old entry, remove.
- (gnus-score-set 'touched '(t) alist)
- (setcdr entries (cdr rest))
- (setq rest entries)))
- (setq entries rest)))))
- nil)
-
-(defun gnus-score-date (scores header now expire &optional trace)
- (let ((gnus-score-index (nth 1 (assoc header gnus-header-index)))
- entries alist)
-
- ;; Find matches.
- (while scores
- (setq alist (car scores)
- scores (cdr scores)
- entries (assoc header alist))
- (while (cdr entries) ;First entry is the header index.
- (let* ((rest (cdr entries))
- (kill (car rest))
- (match (timezone-make-date-sortable (nth 0 kill)))
- (type (or (nth 3 kill) 'before))
- (score (or (nth 1 kill) gnus-score-interactive-default-score))
- (date (nth 2 kill))
- (found nil)
- (match-func
- (cond ((eq type 'after) 'string<)
- ((eq type 'before) 'gnus-string>)
- ((eq type 'at) 'string=)
- (t (error "Illegal match type: %s" type))))
- (articles gnus-scores-articles)
- l)
- ;; Instead of doing all the clever stuff that
- ;; `gnus-score-string' does to minimize searches and stuff,
- ;; I will assume that people generally will put so few
- ;; matches on numbers that any cleverness will take more
- ;; time than one would gain.
- (while articles
- (and
- (setq l (aref (caar articles) gnus-score-index))
- (funcall match-func match (timezone-make-date-sortable l))
- (progn
- (and trace (setq gnus-score-trace
- (cons
- (cons
- (car-safe (rassq alist gnus-score-cache))
- kill)
- gnus-score-trace)))
- (setq found t)
- (setcdr (car articles) (+ score (cdar articles)))))
- (setq articles (cdr articles)))
- ;; Update expire date
- (cond ((null date)) ;Permanent entry.
- ((and found gnus-update-score-entry-dates) ;Match, update date.
- (gnus-score-set 'touched '(t) alist)
- (setcar (nthcdr 2 kill) now))
- ((and expire (< date expire)) ;Old entry, remove.
- (gnus-score-set 'touched '(t) alist)
- (setcdr entries (cdr rest))
- (setq rest entries)))
- (setq entries rest)))))
- nil)
-
-(defun gnus-score-body (scores header now expire &optional trace)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (setq gnus-scores-articles
- (sort gnus-scores-articles
- (lambda (a1 a2)
- (< (mail-header-number (car a1))
- (mail-header-number (car a2))))))
- (save-restriction
- (let* ((buffer-read-only nil)
- (articles gnus-scores-articles)
- (all-scores scores)
- (request-func (cond ((string= "head" header)
- 'gnus-request-head)
- ((string= "body" header)
- 'gnus-request-body)
- (t 'gnus-request-article)))
- entries alist ofunc article last)
- (when articles
- (while (cdr articles)
- (setq articles (cdr articles)))
- (setq last (mail-header-number (caar articles)))
- (setq articles gnus-scores-articles)
- ;; Not all backends support partial fetching. In that case,
- ;; we just fetch the entire article.
- (or (gnus-check-backend-function
- (and (string-match "^gnus-" (symbol-name request-func))
- (intern (substring (symbol-name request-func)
- (match-end 0))))
- gnus-newsgroup-name)
- (progn
- (setq ofunc request-func)
- (setq request-func 'gnus-request-article)))
- (while articles
- (setq article (mail-header-number (caar articles)))
- (gnus-message 7 "Scoring on article %s of %s..." article last)
- (when (funcall request-func article gnus-newsgroup-name)
- (widen)
- (goto-char (point-min))
- ;; If just parts of the article is to be searched, but the
- ;; backend didn't support partial fetching, we just narrow
- ;; to the relevant parts.
- (if ofunc
- (if (eq ofunc 'gnus-request-head)
- (narrow-to-region
- (point)
- (or (search-forward "\n\n" nil t) (point-max)))
- (narrow-to-region
- (or (search-forward "\n\n" nil t) (point))
- (point-max))))
- (setq scores all-scores)
- ;; Find matches.
- (while scores
- (setq alist (car scores)
- scores (cdr scores)
- entries (assoc header alist))
- (while (cdr entries) ;First entry is the header index.
- (let* ((rest (cdr entries))
- (kill (car rest))
- (match (nth 0 kill))
- (type (or (nth 3 kill) 's))
- (score (or (nth 1 kill)
- gnus-score-interactive-default-score))
- (date (nth 2 kill))
- (found nil)
- (case-fold-search
- (not (or (eq type 'R) (eq type 'S)
- (eq type 'Regexp) (eq type 'String))))
- (search-func
- (cond ((or (eq type 'r) (eq type 'R)
- (eq type 'regexp) (eq type 'Regexp))
- 're-search-forward)
- ((or (eq type 's) (eq type 'S)
- (eq type 'string) (eq type 'String))
- 'search-forward)
- (t
- (error "Illegal match type: %s" type)))))
- (goto-char (point-min))
- (if (funcall search-func match nil t)
- ;; Found a match, update scores.
- (progn
- (setcdr (car articles) (+ score (cdar articles)))
- (setq found t)
- (and trace (setq gnus-score-trace
- (cons
- (cons
- (car-safe
- (rassq alist gnus-score-cache))
- kill)
- gnus-score-trace)))))
- ;; Update expire date
- (cond
- ((null date)) ;Permanent entry.
- ((and found gnus-update-score-entry-dates) ;Match, update date.
- (gnus-score-set 'touched '(t) alist)
- (setcar (nthcdr 2 kill) now))
- ((and expire (< date expire)) ;Old entry, remove.
- (gnus-score-set 'touched '(t) alist)
- (setcdr entries (cdr rest))
- (setq rest entries)))
- (setq entries rest)))))
- (setq articles (cdr articles)))))))
- nil)
-
-(defun gnus-score-followup (scores header now expire &optional trace thread)
- ;; Insert the unique article headers in the buffer.
- (let ((gnus-score-index (nth 1 (assoc header gnus-header-index)))
- (current-score-file gnus-current-score-file)
- (all-scores scores)
- ;; gnus-score-index is used as a free variable.
- alike last this art entries alist articles
- new news)
-
- ;; Change score file to the adaptive score file. All entries that
- ;; this function makes will be put into this file.
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (gnus-score-load-file
- (or gnus-newsgroup-adaptive-score-file
- (gnus-score-file-name
- gnus-newsgroup-name gnus-adaptive-file-suffix))))
-
- (setq gnus-scores-articles (sort gnus-scores-articles 'gnus-score-string<)
- articles gnus-scores-articles)
-
- (erase-buffer)
- (while articles
- (setq art (car articles)
- this (aref (car art) gnus-score-index)
- articles (cdr articles))
- (if (equal last this)
- (setq alike (cons art alike))
- (if last
- (progn
- (insert last ?\n)
- (put-text-property (1- (point)) (point) 'articles alike)))
- (setq alike (list art)
- last this)))
- (and last ; Bwadr, duplicate code.
- (progn
- (insert last ?\n)
- (put-text-property (1- (point)) (point) 'articles alike)))
-
- ;; Find matches.
- (while scores
- (setq alist (car scores)
- scores (cdr scores)
- entries (assoc header alist))
- (while (cdr entries) ;First entry is the header index.
- (let* ((rest (cdr entries))
- (kill (car rest))
- (match (nth 0 kill))
- (type (or (nth 3 kill) 's))
- (score (or (nth 1 kill) gnus-score-interactive-default-score))
- (date (nth 2 kill))
- (found nil)
- (mt (aref (symbol-name type) 0))
- (case-fold-search
- (not (or (= mt ?R) (= mt ?S) (= mt ?E) (= mt ?F))))
- (dmt (downcase mt))
- (search-func
- (cond ((= dmt ?r) 're-search-forward)
- ((or (= dmt ?e) (= dmt ?s) (= dmt ?f)) 'search-forward)
- (t (error "Illegal match type: %s" type))))
- arts art)
- (goto-char (point-min))
- (if (= dmt ?e)
- (while (funcall search-func match nil t)
- (and (= (progn (beginning-of-line) (point))
- (match-beginning 0))
- (= (progn (end-of-line) (point))
- (match-end 0))
- (progn
- (setq found (setq arts (get-text-property
- (point) 'articles)))
- ;; Found a match, update scores.
- (while arts
- (setq art (car arts)
- arts (cdr arts))
- (gnus-score-add-followups
- (car art) score all-scores thread))))
- (end-of-line))
- (while (funcall search-func match nil t)
- (end-of-line)
- (setq found (setq arts (get-text-property (point) 'articles)))
- ;; Found a match, update scores.
- (while (setq art (pop arts))
- (when (setq new (gnus-score-add-followups
- (car art) score all-scores thread))
- (push new news)))))
- ;; Update expire date
- (cond ((null date)) ;Permanent entry.
- ((and found gnus-update-score-entry-dates) ;Match, update date.
- (gnus-score-set 'touched '(t) alist)
- (setcar (nthcdr 2 kill) now))
- ((and expire (< date expire)) ;Old entry, remove.
- (gnus-score-set 'touched '(t) alist)
- (setcdr entries (cdr rest))
- (setq rest entries)))
- (setq entries rest))))
- ;; We change the score file back to the previous one.
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (gnus-score-load-file current-score-file))
- (list (cons "references" news))))
-
-(defun gnus-score-add-followups (header score scores &optional thread)
- "Add a score entry to the adapt file."
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (let* ((id (mail-header-id header))
- (scores (car scores))
- entry dont)
- ;; Don't enter a score if there already is one.
- (while (setq entry (pop scores))
- (and (equal "references" (car entry))
- (or (null (nth 3 (cadr entry)))
- (eq 's (nth 3 (cadr entry))))
- (assoc id entry)
- (setq dont t)))
- (unless dont
- (gnus-summary-score-entry
- (if thread "thread" "references")
- id 's score (current-time-string) nil t)))))
-
-(defun gnus-score-string (score-list header now expire &optional trace)
- ;; Score ARTICLES according to HEADER in SCORE-LIST.
- ;; Update matching entries to NOW and remove unmatched entries older
- ;; than EXPIRE.
-
- ;; Insert the unique article headers in the buffer.
- (let ((gnus-score-index (nth 1 (assoc header gnus-header-index)))
- ;; gnus-score-index is used as a free variable.
- alike last this art entries alist articles scores fuzzy)
-
- ;; Sorting the articles costs os O(N*log N) but will allow us to
- ;; only match with each unique header. Thus the actual matching
- ;; will be O(M*U) where M is the number of strings to match with,
- ;; and U is the number of unique headers. It is assumed (but
- ;; untested) this will be a net win because of the large constant
- ;; factor involved with string matching.
- (setq gnus-scores-articles (sort gnus-scores-articles 'gnus-score-string<)
- articles gnus-scores-articles)
-
- (erase-buffer)
- (while articles
- (setq art (car articles)
- this (aref (car art) gnus-score-index)
- articles (cdr articles))
- (if (equal last this)
- ;; O(N*H) cons-cells used here, where H is the number of
- ;; headers.
- (setq alike (cons art alike))
- (if last
- (progn
- ;; Insert the line, with a text property on the
- ;; terminating newline referring to the articles with
- ;; this line.
- (insert last ?\n)
- (put-text-property (1- (point)) (point) 'articles alike)))
- (setq alike (list art)
- last this)))
- (and last ; Bwadr, duplicate code.
- (progn
- (insert last ?\n)
- (put-text-property (1- (point)) (point) 'articles alike)))
-
- ;; Find ordinary matches.
- (setq scores score-list)
- (while scores
- (setq alist (car scores)
- scores (cdr scores)
- entries (assoc header alist))
- (while (cdr entries) ;First entry is the header index.
- (let* ((rest (cdr entries))
- (kill (car rest))
- (match (nth 0 kill))
- (type (or (nth 3 kill) 's))
- (score (or (nth 1 kill) gnus-score-interactive-default-score))
- (date (nth 2 kill))
- (found nil)
- (mt (aref (symbol-name type) 0))
- (case-fold-search
- (not (or (= mt ?R) (= mt ?S) (= mt ?E) (= mt ?F))))
- (dmt (downcase mt))
- (search-func
- (cond ((= dmt ?r) 're-search-forward)
- ((or (= dmt ?e) (= dmt ?s) (= dmt ?f)) 'search-forward)
- (t (error "Illegal match type: %s" type))))
- arts art)
- (if (= dmt ?f)
- (setq fuzzy t)
- ;; Do non-fuzzy matching.
- (goto-char (point-min))
- (if (= dmt ?e)
- ;; Do exact matching.
- (while (and (not (eobp))
- (funcall search-func match nil t))
- (and (= (progn (beginning-of-line) (point))
- (match-beginning 0))
- (= (progn (end-of-line) (point))
- (match-end 0))
- (progn
- (setq found (setq arts (get-text-property
- (point) 'articles)))
- ;; Found a match, update scores.
- (if trace
- (while arts
- (setq art (car arts)
- arts (cdr arts))
- (setcdr art (+ score (cdr art)))
- (setq gnus-score-trace
- (cons
- (cons
- (car-safe
- (rassq alist gnus-score-cache))
- kill)
- gnus-score-trace)))
- (while arts
- (setq art (car arts)
- arts (cdr arts))
- (setcdr art (+ score (cdr art)))))))
- (forward-line 1))
- ;; Do regexp and substring matching.
- (and (string= match "") (setq match "\n"))
- (while (and (not (eobp))
- (funcall search-func match nil t))
- (goto-char (match-beginning 0))
- (end-of-line)
- (setq found (setq arts (get-text-property (point) 'articles)))
- ;; Found a match, update scores.
- (if trace
- (while arts
- (setq art (pop arts))
- (setcdr art (+ score (cdr art)))
- (push (cons
- (car-safe (rassq alist gnus-score-cache))
- kill)
- gnus-score-trace))
- (while arts
- (setq art (pop arts))
- (setcdr art (+ score (cdr art)))))
- (forward-line 1)))
- ;; Update expire date
- (cond
- ((null date)) ;Permanent entry.
- ((and found gnus-update-score-entry-dates) ;Match, update date.
- (gnus-score-set 'touched '(t) alist)
- (setcar (nthcdr 2 kill) now))
- ((and expire (< date expire)) ;Old entry, remove.
- (gnus-score-set 'touched '(t) alist)
- (setcdr entries (cdr rest))
- (setq rest entries))))
- (setq entries rest))))
-
- ;; Find fuzzy matches.
- (when fuzzy
- (setq scores score-list)
- (gnus-simplify-buffer-fuzzy)
- (while scores
- (setq alist (car scores)
- scores (cdr scores)
- entries (assoc header alist))
- (while (cdr entries) ;First entry is the header index.
- (let* ((rest (cdr entries))
- (kill (car rest))
- (match (nth 0 kill))
- (type (or (nth 3 kill) 's))
- (score (or (nth 1 kill) gnus-score-interactive-default-score))
- (date (nth 2 kill))
- (found nil)
- (mt (aref (symbol-name type) 0))
- (case-fold-search (not (= mt ?F)))
- (dmt (downcase mt))
- arts art)
- (when (= dmt ?f)
- (goto-char (point-min))
- (while (and (not (eobp))
- (search-forward match nil t))
- (when (and (= (progn (beginning-of-line) (point))
- (match-beginning 0))
- (= (progn (end-of-line) (point))
- (match-end 0)))
- (setq found (setq arts (get-text-property
- (point) 'articles)))
- ;; Found a match, update scores.
- (if trace
- (while arts
- (setq art (pop arts))
- (setcdr art (+ score (cdr art)))
- (push (cons
- (car-safe (rassq alist gnus-score-cache))
- kill)
- gnus-score-trace))
- (while arts
- (setq art (pop arts))
- (setcdr art (+ score (cdr art))))))
- (forward-line 1))
- ;; Update expire date
- (unless trace
- (cond
- ((null date)) ;Permanent entry.
- ((and found gnus-update-score-entry-dates) ;Match, update date.
- (gnus-score-set 'touched '(t) alist)
- (setcar (nthcdr 2 kill) now))
- ((and expire (< date expire)) ;Old entry, remove.
- (gnus-score-set 'touched '(t) alist)
- (setcdr entries (cdr rest))
- (setq rest entries)))))
- (setq entries rest))))))
- nil)
-
-(defun gnus-score-string< (a1 a2)
- ;; Compare headers in articles A2 and A2.
- ;; The header index used is the free variable `gnus-score-index'.
- (string-lessp (aref (car a1) gnus-score-index)
- (aref (car a2) gnus-score-index)))
-
-(defun gnus-score-build-cons (article)
- ;; Build a `gnus-newsgroup-scored' type cons from ARTICLE.
- (cons (mail-header-number (car article)) (cdr article)))
-
-(defun gnus-current-score-file-nondirectory (&optional score-file)
- (let ((score-file (or score-file gnus-current-score-file)))
- (if score-file
- (gnus-short-group-name (file-name-nondirectory score-file))
- "none")))
-
-(defun gnus-score-adaptive ()
- (save-excursion
- (let* ((malist (gnus-copy-sequence gnus-adaptive-score-alist))
- (alist malist)
- (date (current-time-string))
- (data gnus-newsgroup-data)
- elem headers match)
- ;; First we transform the adaptive rule alist into something
- ;; that's faster to process.
- (while malist
- (setq elem (car malist))
- (if (symbolp (car elem))
- (setcar elem (symbol-value (car elem))))
- (setq elem (cdr elem))
- (while elem
- (setcdr (car elem)
- (cons (if (eq (caar elem) 'followup)
- "references"
- (symbol-name (caar elem)))
- (cdar elem)))
- (setcar (car elem)
- `(lambda (h)
- (,(intern
- (concat "mail-header-"
- (if (eq (caar elem) 'followup)
- "message-id"
- (downcase (symbol-name (caar elem))))))
- h)))
- (setq elem (cdr elem)))
- (setq malist (cdr malist)))
- ;; We change the score file to the adaptive score file.
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (gnus-score-load-file
- (or gnus-newsgroup-adaptive-score-file
- (gnus-score-file-name
- gnus-newsgroup-name gnus-adaptive-file-suffix))))
- ;; The we score away.
- (while data
- (setq elem (cdr (assq (gnus-data-mark (car data)) alist)))
- (if (or (not elem)
- (gnus-data-pseudo-p (car data)))
- ()
- (when (setq headers (gnus-data-header (car data)))
- (while elem
- (setq match (funcall (caar elem) headers))
- (gnus-summary-score-entry
- (nth 1 (car elem)) match
- (cond
- ((numberp match)
- '=)
- ((equal (nth 1 (car elem)) "date")
- 'a)
- (t
- ;; Whether we use substring or exact matches are controlled
- ;; here.
- (if (or (not gnus-score-exact-adapt-limit)
- (< (length match) gnus-score-exact-adapt-limit))
- 'e
- (if (equal (nth 1 (car elem)) "subject")
- 'f 's))))
- (nth 2 (car elem)) date nil t)
- (setq elem (cdr elem)))))
- (setq data (cdr data))))))
-
-(defun gnus-score-edit-done ()
- (let ((bufnam (buffer-file-name (current-buffer)))
- (winconf gnus-prev-winconf))
- (and winconf (set-window-configuration winconf))
- (gnus-score-remove-from-cache bufnam)
- (gnus-score-load-file bufnam)))
-
-(defun gnus-score-find-trace ()
- "Find all score rules that applies to the current article."
- (interactive)
- (let ((gnus-newsgroup-headers
- (list (gnus-summary-article-header)))
- (gnus-newsgroup-scored nil)
- (buf (current-buffer))
- trace)
- (when (get-buffer "*Gnus Scores*")
- (save-excursion
- (set-buffer "*Gnus Scores*")
- (erase-buffer)))
- (setq gnus-score-trace nil)
- (gnus-possibly-score-headers 'trace)
- (if (not (setq trace gnus-score-trace))
- (gnus-error 1 "No score rules apply to the current article.")
- (pop-to-buffer "*Gnus Scores*")
- (gnus-add-current-to-buffer-list)
- (erase-buffer)
- (while trace
- (insert (format "%S -> %s\n" (cdar trace)
- (file-name-nondirectory (caar trace))))
- (setq trace (cdr trace)))
- (goto-char (point-min))
- (pop-to-buffer buf))))
-
-(defun gnus-summary-rescore ()
- "Redo the entire scoring process in the current summary."
- (interactive)
- (gnus-score-save)
- (setq gnus-score-cache nil)
- (setq gnus-newsgroup-scored nil)
- (gnus-possibly-score-headers)
- (gnus-score-update-all-lines))
-
-(defun gnus-score-flush-cache ()
- "Flush the cache of score files."
- (interactive)
- (gnus-score-save)
- (setq gnus-score-cache nil
- gnus-score-alist nil
- gnus-short-name-score-file-cache nil)
- (gnus-message 6 "The score cache is now flushed"))
-
-(gnus-add-shutdown 'gnus-score-close 'gnus)
-
-(defvar gnus-score-file-alist-cache nil)
-
-(defun gnus-score-close ()
- "Clear all internal score variables."
- (setq gnus-score-cache nil
- gnus-internal-global-score-files nil
- gnus-score-file-list nil
- gnus-score-file-alist-cache nil))
-
-;; Summary score marking commands.
-
-(defun gnus-summary-raise-same-subject-and-select (score)
- "Raise articles which has the same subject with SCORE and select the next."
- (interactive "p")
- (let ((subject (gnus-summary-article-subject)))
- (gnus-summary-raise-score score)
- (while (gnus-summary-find-subject subject)
- (gnus-summary-raise-score score))
- (gnus-summary-next-article t)))
-
-(defun gnus-summary-raise-same-subject (score)
- "Raise articles which has the same subject with SCORE."
- (interactive "p")
- (let ((subject (gnus-summary-article-subject)))
- (gnus-summary-raise-score score)
- (while (gnus-summary-find-subject subject)
- (gnus-summary-raise-score score))
- (gnus-summary-next-subject 1 t)))
-
-(defun gnus-score-default (level)
- (if level (prefix-numeric-value level)
- gnus-score-interactive-default-score))
-
-(defun gnus-summary-raise-thread (&optional score)
- "Raise the score of the articles in the current thread with SCORE."
- (interactive "P")
- (setq score (gnus-score-default score))
- (let (e)
- (save-excursion
- (let ((articles (gnus-summary-articles-in-thread)))
- (while articles
- (gnus-summary-goto-subject (car articles))
- (gnus-summary-raise-score score)
- (setq articles (cdr articles))))
- (setq e (point)))
- (let ((gnus-summary-check-current t))
- (or (zerop (gnus-summary-next-subject 1 t))
- (goto-char e))))
- (gnus-summary-recenter)
- (gnus-summary-position-point)
- (gnus-set-mode-line 'summary))
-
-(defun gnus-summary-lower-same-subject-and-select (score)
- "Raise articles which has the same subject with SCORE and select the next."
- (interactive "p")
- (gnus-summary-raise-same-subject-and-select (- score)))
-
-(defun gnus-summary-lower-same-subject (score)
- "Raise articles which has the same subject with SCORE."
- (interactive "p")
- (gnus-summary-raise-same-subject (- score)))
-
-(defun gnus-summary-lower-thread (&optional score)
- "Lower score of articles in the current thread with SCORE."
- (interactive "P")
- (gnus-summary-raise-thread (- (1- (gnus-score-default score)))))
-
-;;; Finding score files.
-
-(defun gnus-score-score-files (group)
- "Return a list of all possible score files."
- ;; Search and set any global score files.
- (and gnus-global-score-files
- (or gnus-internal-global-score-files
- (gnus-score-search-global-directories gnus-global-score-files)))
- ;; Fix the kill-file dir variable.
- (setq gnus-kill-files-directory
- (file-name-as-directory gnus-kill-files-directory))
- ;; If we can't read it, there are no score files.
- (if (not (file-exists-p (expand-file-name gnus-kill-files-directory)))
- (setq gnus-score-file-list nil)
- (if (not (gnus-use-long-file-name 'not-score))
- ;; We do not use long file names, so we have to do some
- ;; directory traversing.
- (setq gnus-score-file-list
- (cons nil
- (or gnus-short-name-score-file-cache
- (prog2
- (gnus-message 6 "Finding all score files...")
- (setq gnus-short-name-score-file-cache
- (gnus-score-score-files-1
- gnus-kill-files-directory))
- (gnus-message 6 "Finding all score files...done")))))
- ;; We want long file names.
- (when (or (not gnus-score-file-list)
- (not (car gnus-score-file-list))
- (gnus-file-newer-than gnus-kill-files-directory
- (car gnus-score-file-list)))
- (setq gnus-score-file-list
- (cons (nth 5 (file-attributes gnus-kill-files-directory))
- (nreverse
- (directory-files
- gnus-kill-files-directory t
- (gnus-score-file-regexp)))))))
- (cdr gnus-score-file-list)))
-
-(defun gnus-score-score-files-1 (dir)
- "Return all possible score files under DIR."
- (let ((files (directory-files (expand-file-name dir) t nil t))
- (regexp (gnus-score-file-regexp))
- out file)
- (while (setq file (pop files))
- (cond
- ;; Ignore "." and "..".
- ((member (file-name-nondirectory file) '("." ".."))
- nil)
- ;; Recurse down directories.
- ((file-directory-p file)
- (setq out (nconc (gnus-score-score-files-1 file) out)))
- ;; Add files to the list of score files.
- ((string-match regexp file)
- (push file out))))
- (or out
- ;; Return a dummy value.
- (list "~/News/this.file.does.not.exist.SCORE"))))
-
-(defun gnus-score-file-regexp ()
- "Return a regexp that match all score files."
- (concat "\\(" (regexp-quote gnus-score-file-suffix )
- "\\|" (regexp-quote gnus-adaptive-file-suffix) "\\)\\'"))
-
-(defun gnus-score-find-bnews (group)
- "Return a list of score files for GROUP.
-The score files are those files in the ~/News/ directory which matches
-GROUP using BNews sys file syntax."
- (let* ((sfiles (append (gnus-score-score-files group)
- gnus-internal-global-score-files))
- (kill-dir (file-name-as-directory
- (expand-file-name gnus-kill-files-directory)))
- (klen (length kill-dir))
- (score-regexp (gnus-score-file-regexp))
- (trans (cdr (assq ?: nnheader-file-name-translation-alist)))
- ofiles not-match regexp)
- (save-excursion
- (set-buffer (get-buffer-create "*gnus score files*"))
- (buffer-disable-undo (current-buffer))
- ;; Go through all score file names and create regexp with them
- ;; as the source.
- (while sfiles
- (erase-buffer)
- (insert (car sfiles))
- (goto-char (point-min))
- ;; First remove the suffix itself.
- (when (re-search-forward (concat "." score-regexp) nil t)
- (replace-match "" t t)
- (goto-char (point-min))
- (if (looking-at (regexp-quote kill-dir))
- ;; If the file name was just "SCORE", `klen' is one character
- ;; too much.
- (delete-char (min (1- (point-max)) klen))
- (goto-char (point-max))
- (search-backward "/")
- (delete-region (1+ (point)) (point-min)))
- ;; If short file names were used, we have to translate slashes.
- (goto-char (point-min))
- (let ((regexp (concat
- "[/:" (if trans (char-to-string trans) "") "]")))
- (while (re-search-forward regexp nil t)
- (replace-match "." t t)))
- ;; Cludge to get rid of "nntp+" problems.
- (goto-char (point-min))
- (and (looking-at "nn[a-z]+\\+")
- (progn
- (search-forward "+")
- (forward-char -1)
- (insert "\\")))
- ;; Kludge to deal with "++".
- (goto-char (point-min))
- (while (search-forward "++" nil t)
- (replace-match "\\+\\+" t t))
- ;; Translate "all" to ".*".
- (goto-char (point-min))
- (while (search-forward "all" nil t)
- (replace-match ".*" t t))
- (goto-char (point-min))
- ;; Deal with "not."s.
- (if (looking-at "not.")
- (progn
- (setq not-match t)
- (setq regexp (buffer-substring 5 (point-max))))
- (setq regexp (buffer-substring 1 (point-max)))
- (setq not-match nil))
- ;; Finally - if this resulting regexp matches the group name,
- ;; we add this score file to the list of score files
- ;; applicable to this group.
- (if (or (and not-match
- (not (string-match regexp group)))
- (and (not not-match)
- (string-match regexp group)))
- (setq ofiles (cons (car sfiles) ofiles))))
- (setq sfiles (cdr sfiles)))
- (kill-buffer (current-buffer))
- ;; Slight kludge here - the last score file returned should be
- ;; the local score file, whether it exists or not. This is so
- ;; that any score commands the user enters will go to the right
- ;; file, and not end up in some global score file.
- (let ((localscore (gnus-score-file-name group)))
- (setq ofiles (cons localscore (delete localscore ofiles))))
- (nreverse ofiles))))
-
-(defun gnus-score-find-single (group)
- "Return list containing the score file for GROUP."
- (list (or gnus-newsgroup-adaptive-score-file
- (gnus-score-file-name group gnus-adaptive-file-suffix))
- (gnus-score-file-name group)))
-
-(defun gnus-score-find-hierarchical (group)
- "Return list of score files for GROUP.
-This includes the score file for the group and all its parents."
- (let ((all (copy-sequence '(nil)))
- (start 0))
- (while (string-match "\\." group (1+ start))
- (setq start (match-beginning 0))
- (setq all (cons (substring group 0 start) all)))
- (setq all (cons group all))
- (nconc
- (mapcar (lambda (newsgroup)
- (gnus-score-file-name newsgroup gnus-adaptive-file-suffix))
- (setq all (nreverse all)))
- (mapcar 'gnus-score-file-name all))))
-
-(defun gnus-score-find-alist (group)
- "Return list of score files for GROUP.
-The list is determined from the variable gnus-score-file-alist."
- (let ((alist gnus-score-file-multiple-match-alist)
- score-files)
- ;; if this group has been seen before, return the cached entry
- (if (setq score-files (assoc group gnus-score-file-alist-cache))
- (cdr score-files) ;ensures caching groups with no matches
- ;; handle the multiple match alist
- (while alist
- (and (string-match (caar alist) group)
- (setq score-files
- (nconc score-files (copy-sequence (cdar alist)))))
- (setq alist (cdr alist)))
- (setq alist gnus-score-file-single-match-alist)
- ;; handle the single match alist
- (while alist
- (and (string-match (caar alist) group)
- ;; progn used just in case ("regexp") has no files
- ;; and score-files is still nil. -sj
- ;; this can be construed as a "stop searching here" feature :>
- ;; and used to simplify regexps in the single-alist
- (progn
- (setq score-files
- (nconc score-files (copy-sequence (cdar alist))))
- (setq alist nil)))
- (setq alist (cdr alist)))
- ;; cache the score files
- (setq gnus-score-file-alist-cache
- (cons (cons group score-files) gnus-score-file-alist-cache))
- score-files)))
-
-(defun gnus-possibly-score-headers (&optional trace)
- (let ((funcs gnus-score-find-score-files-function)
- score-files)
- ;; Make sure funcs is a list.
- (and funcs
- (not (listp funcs))
- (setq funcs (list funcs)))
- ;; Get the initial score files for this group.
- (when funcs
- (setq score-files (gnus-score-find-alist gnus-newsgroup-name)))
- ;; Go through all the functions for finding score files (or actual
- ;; scores) and add them to a list.
- (while funcs
- (when (gnus-functionp (car funcs))
- (setq score-files
- (nconc score-files (funcall (car funcs) gnus-newsgroup-name))))
- (setq funcs (cdr funcs)))
- ;; Check whether there is a `score-file' group parameter.
- (let ((param-file (gnus-group-get-parameter
- gnus-newsgroup-name 'score-file)))
- (when param-file
- (push param-file score-files)))
- ;; Do the scoring if there are any score files for this group.
- (when score-files
- (gnus-score-headers score-files trace))))
-
-(defun gnus-score-file-name (newsgroup &optional suffix)
- "Return the name of a score file for NEWSGROUP."
- (let ((suffix (or suffix gnus-score-file-suffix)))
- (nnheader-translate-file-chars
- (cond
- ((or (null newsgroup)
- (string-equal newsgroup ""))
- ;; The global score file is placed at top of the directory.
- (expand-file-name
- suffix gnus-kill-files-directory))
- ((gnus-use-long-file-name 'not-score)
- ;; Append ".SCORE" to newsgroup name.
- (expand-file-name (concat (gnus-newsgroup-savable-name newsgroup)
- "." suffix)
- gnus-kill-files-directory))
- (t
- ;; Place "SCORE" under the hierarchical directory.
- (expand-file-name (concat (gnus-newsgroup-directory-form newsgroup)
- "/" suffix)
- gnus-kill-files-directory))))))
-
-(defun gnus-score-search-global-directories (files)
- "Scan all global score directories for score files."
- ;; Set the variable `gnus-internal-global-score-files' to all
- ;; available global score files.
- (interactive (list gnus-global-score-files))
- (let (out)
- (while files
- (if (string-match "/$" (car files))
- (setq out (nconc (directory-files
- (car files) t
- (concat (gnus-score-file-regexp) "$"))))
- (setq out (cons (car files) out)))
- (setq files (cdr files)))
- (setq gnus-internal-global-score-files out)))
-
-(defun gnus-score-default-fold-toggle ()
- "Toggle folding for new score file entries."
- (interactive)
- (setq gnus-score-default-fold (not gnus-score-default-fold))
- (if gnus-score-default-fold
- (gnus-message 1 "New score file entries will be case insensitive.")
- (gnus-message 1 "New score file entries will be case sensitive.")))
-
-(provide 'gnus-score)
-
-;;; gnus-score.el ends here
diff --git a/lisp/gnus-setup.el b/lisp/gnus-setup.el
deleted file mode 100644
index 20613d8bebd..00000000000
--- a/lisp/gnus-setup.el
+++ /dev/null
@@ -1,210 +0,0 @@
-;;; gnus-setup.el --- Initialization & Setup for Gnus 5
-;; Copyright (C) 1995, 96 Free Software Foundation, Inc.
-
-;; Author: Steven L. Baur <steve@miranova.com>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-;; My head is starting to spin with all the different mail/news packages.
-;; Stop The Madness!
-
-;; Given that Emacs Lisp byte codes may be diverging, it is probably best
-;; not to byte compile this, and just arrange to have the .el loaded out
-;; of .emacs.
-
-;;; Code:
-
-(defvar running-xemacs (string-match "XEmacs\\|Lucid" emacs-version))
-
-(defvar gnus-emacs-lisp-directory (if running-xemacs
- "/usr/local/lib/xemacs/"
- "/usr/local/share/emacs/")
- "Directory where Emacs site lisp is located.")
-
-(defvar gnus-gnus-lisp-directory (concat gnus-emacs-lisp-directory
- "gnus-5.0.15/lisp/")
- "Directory where Gnus Emacs lisp is found.")
-
-(defvar gnus-sgnus-lisp-directory (concat gnus-emacs-lisp-directory
- "sgnus/lisp/")
- "Directory where September Gnus Emacs lisp is found.")
-
-(defvar gnus-tm-lisp-directory (concat gnus-emacs-lisp-directory
- "site-lisp/")
- "Directory where TM Emacs lisp is found.")
-
-(defvar gnus-mailcrypt-lisp-directory (concat gnus-emacs-lisp-directory
- "site-lisp/mailcrypt-3.4/")
- "Directory where Mailcrypt Emacs Lisp is found.")
-
-(defvar gnus-bbdb-lisp-directory (concat gnus-emacs-lisp-directory
- "site-lisp/bbdb-1.50/")
- "Directory where Big Brother Database is found.")
-
-(defvar gnus-use-tm t
- "Set this if you want MIME support for Gnus")
-(defvar gnus-use-mhe nil
- "Set this if you want to use MH-E for mail reading")
-(defvar gnus-use-rmail nil
- "Set this if you want to use RMAIL for mail reading")
-(defvar gnus-use-sendmail t
- "Set this if you want to use SENDMAIL for mail reading")
-(defvar gnus-use-vm nil
- "Set this if you want to use the VM package for mail reading")
-(defvar gnus-use-sc t
- "Set this if you want to use Supercite")
-(defvar gnus-use-mailcrypt t
- "Set this if you want to use Mailcrypt for dealing with PGP messages")
-(defvar gnus-use-bbdb nil
- "Set this if you want to use the Big Brother DataBase")
-(defvar gnus-use-september nil
- "Set this if you are using the experimental September Gnus")
-
-(let ((gnus-directory (if gnus-use-september
- gnus-sgnus-lisp-directory
- gnus-gnus-lisp-directory)))
- (if (null (member gnus-directory load-path))
- (setq load-path (cons gnus-directory load-path))))
-
-;;; Tools for MIME by
-;;; UMEDA Masanobu <umerin@mse.kyutech.ac.jp>
-;;; MORIOKA Tomohiko <morioka@jaist.ac.jp>
-
-(if gnus-use-tm
- (progn
- (if (null (member gnus-tm-lisp-directory load-path))
- (setq load-path (cons gnus-tm-lisp-directory load-path)))
- (load "mime-setup")))
-
-;;; Mailcrypt by
-;;; Jin Choi <jin@atype.com>
-;;; Patrick LoPresti <patl@lcs.mit.edu>
-
-(if gnus-use-mailcrypt
- (progn
- (if (null (member gnus-mailcrypt-lisp-directory load-path))
- (setq load-path (cons gnus-mailcrypt-lisp-directory load-path)))
- (autoload 'mc-install-write-mode "mailcrypt" nil t)
- (autoload 'mc-install-read-mode "mailcrypt" nil t)
- (add-hook 'message-mode-hook 'mc-install-write-mode)
- (add-hook 'gnus-summary-mode-hook 'mc-install-read-mode)
- (if gnus-use-mhe
- (progn
- (add-hook 'mh-folder-mode-hook 'mc-install-read-mode)
- (add-hook 'mh-letter-mode-hook 'mc-install-write-mode)))))
-
-;;; BBDB by
-;;; Jamie Zawinski <jwz@lucid.com>
-
-(if gnus-use-bbdb
- (progn
- (if (null (member gnus-bbdb-lisp-directory load-path))
- (setq load-path (cons gnus-bbdb-lisp-directory load-path)))
- (autoload 'bbdb "bbdb-com"
- "Insidious Big Brother Database" t)
- (autoload 'bbdb-name "bbdb-com"
- "Insidious Big Brother Database" t)
- (autoload 'bbdb-company "bbdb-com"
- "Insidious Big Brother Database" t)
- (autoload 'bbdb-net "bbdb-com"
- "Insidious Big Brother Database" t)
- (autoload 'bbdb-notes "bbdb-com"
- "Insidious Big Brother Database" t)
-
- (if gnus-use-vm
- (progn
- (autoload 'bbdb-insinuate-vm "bbdb-vm"
- "Hook BBDB into VM" t)))
-
- (if gnus-use-rmail
- (progn
- (autoload 'bbdb-insinuate-rmail "bbdb-rmail"
- "Hook BBDB into RMAIL" t)
- (add-hook 'rmail-mode-hook 'bbdb-insinuate-rmail)))
-
- (if gnus-use-mhe
- (progn
- (autoload 'bbdb-insinuate-mh "bbdb-mh"
- "Hook BBDB into MH-E" t)
- (add-hook 'mh-folder-mode-hook 'bbdb-insinuate-mh)))
-
- (autoload 'bbdb-insinuate-gnus "bbdb-gnus"
- "Hook BBDB into Gnus" t)
- (add-hook 'gnus-startup-hook 'bbdb-insinuate-gnus)
-
- (if gnus-use-sendmail
- (progn
- (autoload 'bbdb-insinuate-sendmail "bbdb"
- "Insidious Big Brother Database" t)
- (add-hook 'mail-setup-hook 'bbdb-insinuate-sendmail)
- (add-hook 'message-setup-hook 'bbdb-insinuate-sendmail)))))
-
-(if gnus-use-sc
- (progn
- (add-hook 'mail-citation-hook 'sc-cite-original)
- (setq message-cite-function 'sc-cite-original)
- (autoload 'sc-cite-original "supercite")))
-
-;;;### (autoloads (gnus-batch-score gnus-fetch-group gnus gnus-slave gnus-no-server gnus-update-format) "gnus" "lisp/gnus.el" (12473 2137))
-;;; Generated autoloads from lisp/gnus.el
-
-(autoload 'gnus-update-format "gnus" "\
-Update the format specification near point." t nil)
-
-(autoload 'gnus-slave-no-server "gnus" "\
-Read network news as a slave without connecting to local server." t nil)
-
-(autoload 'gnus-no-server "gnus" "\
-Read network news.
-If ARG is a positive number, Gnus will use that as the
-startup level. If ARG is nil, Gnus will be started at level 2.
-If ARG is non-nil and not a positive number, Gnus will
-prompt the user for the name of an NNTP server to use.
-As opposed to `gnus', this command will not connect to the local server." t nil)
-
-(autoload 'gnus-slave "gnus" "\
-Read news as a slave." t nil)
-
-(autoload 'gnus "gnus" "\
-Read network news.
-If ARG is non-nil and a positive number, Gnus will use that as the
-startup level. If ARG is non-nil and not a positive number, Gnus will
-prompt the user for the name of an NNTP server to use." t nil)
-
-(autoload 'gnus-fetch-group "gnus" "\
-Start Gnus if necessary and enter GROUP.
-Returns whether the fetching was successful or not." t nil)
-
-(defalias 'gnus-batch-kill 'gnus-batch-score)
-
-(autoload 'gnus-batch-score "gnus" "\
-Run batched scoring.
-Usage: emacs -batch -l gnus -f gnus-batch-score <newsgroups> ...
-Newsgroups is a list of strings in Bnews format. If you want to score
-the comp hierarchy, you'd say \"comp.all\". If you would not like to
-score the alt hierarchy, you'd say \"!alt.all\"." t nil)
-
-;;;***
-
-(provide 'gnus-setup)
-
-(run-hooks 'gnus-setup-load-hook)
-
-;;; gnus-setup.el ends here
diff --git a/lisp/gnus-soup.el b/lisp/gnus-soup.el
deleted file mode 100644
index c4a8fd798b9..00000000000
--- a/lisp/gnus-soup.el
+++ /dev/null
@@ -1,563 +0,0 @@
-;;; gnus-soup.el --- SOUP packet writing support for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Per Abrahamsen <abraham@iesd.auc.dk>
-;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news, mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'gnus-msg)
-(require 'gnus)
-(eval-when-compile (require 'cl))
-
-;;; User Variables:
-
-(defvar gnus-soup-directory "~/SoupBrew/"
- "*Directory containing an unpacked SOUP packet.")
-
-(defvar gnus-soup-replies-directory (concat gnus-soup-directory "SoupReplies/")
- "*Directory where Gnus will do processing of replies.")
-
-(defvar gnus-soup-prefix-file "gnus-prefix"
- "*Name of the file where Gnus stores the last used prefix.")
-
-(defvar gnus-soup-packer "tar cf - %s | gzip > $HOME/Soupout%d.tgz"
- "Format string command for packing a SOUP packet.
-The SOUP files will be inserted where the %s is in the string.
-This string MUST contain both %s and %d. The file number will be
-inserted where %d appears.")
-
-(defvar gnus-soup-unpacker "gunzip -c %s | tar xvf -"
- "*Format string command for unpacking a SOUP packet.
-The SOUP packet file name will be inserted at the %s.")
-
-(defvar gnus-soup-packet-directory "~/"
- "*Where gnus-soup will look for REPLIES packets.")
-
-(defvar gnus-soup-packet-regexp "Soupin"
- "*Regular expression matching SOUP REPLIES packets in `gnus-soup-packet-directory'.")
-
-(defvar gnus-soup-ignored-headers "^Xref:"
- "*Regexp to match headers to be removed when brewing SOUP packets.")
-
-;;; Internal Variables:
-
-(defvar gnus-soup-encoding-type ?n
- "*Soup encoding type.
-`n' is news format, `m' is Unix mbox format, and `M' is MMDF mailbox
-format.")
-
-(defvar gnus-soup-index-type ?c
- "*Soup index type.
-`n' means no index file and `c' means standard Cnews overview
-format.")
-
-(defvar gnus-soup-areas nil)
-(defvar gnus-soup-last-prefix nil)
-(defvar gnus-soup-prev-prefix nil)
-(defvar gnus-soup-buffers nil)
-
-;;; Access macros:
-
-(defmacro gnus-soup-area-prefix (area)
- `(aref ,area 0))
-(defmacro gnus-soup-set-area-prefix (area prefix)
- `(aset ,area 0 ,prefix))
-(defmacro gnus-soup-area-name (area)
- `(aref ,area 1))
-(defmacro gnus-soup-area-encoding (area)
- `(aref ,area 2))
-(defmacro gnus-soup-area-description (area)
- `(aref ,area 3))
-(defmacro gnus-soup-area-number (area)
- `(aref ,area 4))
-(defmacro gnus-soup-area-set-number (area value)
- `(aset ,area 4 ,value))
-
-(defmacro gnus-soup-encoding-format (encoding)
- `(aref ,encoding 0))
-(defmacro gnus-soup-encoding-index (encoding)
- `(aref ,encoding 1))
-(defmacro gnus-soup-encoding-kind (encoding)
- `(aref ,encoding 2))
-
-(defmacro gnus-soup-reply-prefix (reply)
- `(aref ,reply 0))
-(defmacro gnus-soup-reply-kind (reply)
- `(aref ,reply 1))
-(defmacro gnus-soup-reply-encoding (reply)
- `(aref ,reply 2))
-
-;;; Commands:
-
-(defun gnus-soup-send-replies ()
- "Unpack and send all replies in the reply packet."
- (interactive)
- (let ((packets (directory-files
- gnus-soup-packet-directory t gnus-soup-packet-regexp)))
- (while packets
- (and (gnus-soup-send-packet (car packets))
- (delete-file (car packets)))
- (setq packets (cdr packets)))))
-
-(defun gnus-soup-add-article (n)
- "Add the current article to SOUP packet.
-If N is a positive number, add the N next articles.
-If N is a negative number, add the N previous articles.
-If N is nil and any articles have been marked with the process mark,
-move those articles instead."
- (interactive "P")
- (gnus-set-global-variables)
- (let* ((articles (gnus-summary-work-articles n))
- (tmp-buf (get-buffer-create "*soup work*"))
- (area (gnus-soup-area gnus-newsgroup-name))
- (prefix (gnus-soup-area-prefix area))
- headers)
- (buffer-disable-undo tmp-buf)
- (save-excursion
- (while articles
- ;; Find the header of the article.
- (set-buffer gnus-summary-buffer)
- (when (setq headers (gnus-summary-article-header (car articles)))
- ;; Put the article in a buffer.
- (set-buffer tmp-buf)
- (when (gnus-request-article-this-buffer
- (car articles) gnus-newsgroup-name)
- (save-restriction
- (message-narrow-to-head)
- (message-remove-header gnus-soup-ignored-headers t))
- (gnus-soup-store gnus-soup-directory prefix headers
- gnus-soup-encoding-type
- gnus-soup-index-type)
- (gnus-soup-area-set-number
- area (1+ (or (gnus-soup-area-number area) 0)))))
- ;; Mark article as read.
- (set-buffer gnus-summary-buffer)
- (gnus-summary-remove-process-mark (car articles))
- (gnus-summary-mark-as-read (car articles) gnus-souped-mark)
- (setq articles (cdr articles)))
- (kill-buffer tmp-buf))
- (gnus-soup-save-areas)))
-
-(defun gnus-soup-pack-packet ()
- "Make a SOUP packet from the SOUP areas."
- (interactive)
- (gnus-soup-read-areas)
- (gnus-soup-pack gnus-soup-directory gnus-soup-packer))
-
-(defun gnus-group-brew-soup (n)
- "Make a soup packet from the current group.
-Uses the process/prefix convention."
- (interactive "P")
- (let ((groups (gnus-group-process-prefix n)))
- (while groups
- (gnus-group-remove-mark (car groups))
- (gnus-soup-group-brew (car groups) t)
- (setq groups (cdr groups)))
- (gnus-soup-save-areas)))
-
-(defun gnus-brew-soup (&optional level)
- "Go through all groups on LEVEL or less and make a soup packet."
- (interactive "P")
- (let ((level (or level gnus-level-subscribed))
- (newsrc (cdr gnus-newsrc-alist)))
- (while newsrc
- (and (<= (nth 1 (car newsrc)) level)
- (gnus-soup-group-brew (caar newsrc) t))
- (setq newsrc (cdr newsrc)))
- (gnus-soup-save-areas)))
-
-;;;###autoload
-(defun gnus-batch-brew-soup ()
- "Brew a SOUP packet from groups mention on the command line.
-Will use the remaining command line arguments as regular expressions
-for matching on group names.
-
-For instance, if you want to brew on all the nnml groups, as well as
-groups with \"emacs\" in the name, you could say something like:
-
-$ emacs -batch -f gnus-batch-brew-soup ^nnml \".*emacs.*\""
- (interactive)
- )
-
-;;; Internal Functions:
-
-;; Store the current buffer.
-(defun gnus-soup-store (directory prefix headers format index)
- ;; Create the directory, if needed.
- (or (file-directory-p directory)
- (gnus-make-directory directory))
- (let* ((msg-buf (find-file-noselect
- (concat directory prefix ".MSG")))
- (idx-buf (if (= index ?n)
- nil
- (find-file-noselect
- (concat directory prefix ".IDX"))))
- (article-buf (current-buffer))
- from head-line beg type)
- (setq gnus-soup-buffers (cons msg-buf (delq msg-buf gnus-soup-buffers)))
- (buffer-disable-undo msg-buf)
- (and idx-buf
- (progn
- (setq gnus-soup-buffers (cons idx-buf gnus-soup-buffers))
- (buffer-disable-undo idx-buf)))
- (save-excursion
- ;; Make sure the last char in the buffer is a newline.
- (goto-char (point-max))
- (or (= (current-column) 0)
- (insert "\n"))
- ;; Find the "from".
- (goto-char (point-min))
- (setq from
- (gnus-mail-strip-quoted-names
- (or (mail-fetch-field "from")
- (mail-fetch-field "really-from")
- (mail-fetch-field "sender"))))
- (goto-char (point-min))
- ;; Depending on what encoding is supposed to be used, we make
- ;; a soup header.
- (setq head-line
- (cond
- ((= gnus-soup-encoding-type ?n)
- (format "#! rnews %d\n" (buffer-size)))
- ((= gnus-soup-encoding-type ?m)
- (while (search-forward "\nFrom " nil t)
- (replace-match "\n>From " t t))
- (concat "From " (or from "unknown")
- " " (current-time-string) "\n"))
- ((= gnus-soup-encoding-type ?M)
- "\^a\^a\^a\^a\n")
- (t (error "Unsupported type: %c" gnus-soup-encoding-type))))
- ;; Insert the soup header and the article in the MSG buf.
- (set-buffer msg-buf)
- (goto-char (point-max))
- (insert head-line)
- (setq beg (point))
- (insert-buffer-substring article-buf)
- ;; Insert the index in the IDX buf.
- (cond ((= index ?c)
- (set-buffer idx-buf)
- (gnus-soup-insert-idx beg headers))
- ((/= index ?n)
- (error "Unknown index type: %c" type)))
- ;; Return the MSG buf.
- msg-buf)))
-
-(defun gnus-soup-group-brew (group &optional not-all)
- "Enter GROUP and add all articles to a SOUP package.
-If NOT-ALL, don't pack ticked articles."
- (let ((gnus-expert-user t)
- (gnus-large-newsgroup nil)
- (entry (gnus-gethash group gnus-newsrc-hashtb)))
- (when (or (null entry)
- (eq (car entry) t)
- (and (car entry)
- (> (car entry) 0))
- (and (not not-all)
- (gnus-range-length (cdr (assq 'tick (gnus-info-marks
- (nth 2 entry)))))))
- (when (gnus-summary-read-group group nil t)
- (setq gnus-newsgroup-processable
- (reverse
- (if (not not-all)
- (append gnus-newsgroup-marked gnus-newsgroup-unreads)
- gnus-newsgroup-unreads)))
- (gnus-soup-add-article nil)
- (gnus-summary-exit)))))
-
-(defun gnus-soup-insert-idx (offset header)
- ;; [number subject from date id references chars lines xref]
- (goto-char (point-max))
- (insert
- (format "%d\t%s\t%s\t%s\t%s\t%s\t%d\t%s\t\t\n"
- offset
- (or (mail-header-subject header) "(none)")
- (or (mail-header-from header) "(nobody)")
- (or (mail-header-date header) "")
- (or (mail-header-id header)
- (concat "soup-dummy-id-"
- (mapconcat
- (lambda (time) (int-to-string time))
- (current-time) "-")))
- (or (mail-header-references header) "")
- (or (mail-header-chars header) 0)
- (or (mail-header-lines header) "0"))))
-
-(defun gnus-soup-save-areas ()
- (gnus-soup-write-areas)
- (save-excursion
- (let (buf)
- (while gnus-soup-buffers
- (setq buf (car gnus-soup-buffers)
- gnus-soup-buffers (cdr gnus-soup-buffers))
- (if (not (buffer-name buf))
- ()
- (set-buffer buf)
- (and (buffer-modified-p) (save-buffer))
- (kill-buffer (current-buffer)))))
- (gnus-soup-write-prefixes)))
-
-(defun gnus-soup-write-prefixes ()
- (let ((prefix gnus-soup-last-prefix))
- (save-excursion
- (while prefix
- (gnus-set-work-buffer)
- (insert (format "(setq gnus-soup-prev-prefix %d)\n" (cdar prefix)))
- (gnus-make-directory (caar prefix))
- (write-region (point-min) (point-max)
- (concat (caar prefix) gnus-soup-prefix-file)
- nil 'nomesg)
- (setq prefix (cdr prefix))))))
-
-(defun gnus-soup-pack (dir packer)
- (let* ((files (mapconcat 'identity
- '("AREAS" "*.MSG" "*.IDX" "INFO"
- "LIST" "REPLIES" "COMMANDS" "ERRORS")
- " "))
- (packer (if (< (string-match "%s" packer)
- (string-match "%d" packer))
- (format packer files
- (string-to-int (gnus-soup-unique-prefix dir)))
- (format packer
- (string-to-int (gnus-soup-unique-prefix dir))
- files)))
- (dir (expand-file-name dir)))
- (or (file-directory-p dir)
- (gnus-make-directory dir))
- (setq gnus-soup-areas nil)
- (gnus-message 4 "Packing %s..." packer)
- (if (zerop (call-process shell-file-name
- nil nil nil shell-command-switch
- (concat "cd " dir " ; " packer)))
- (progn
- (call-process shell-file-name nil nil nil shell-command-switch
- (concat "cd " dir " ; rm " files))
- (gnus-message 4 "Packing...done" packer))
- (error "Couldn't pack packet."))))
-
-(defun gnus-soup-parse-areas (file)
- "Parse soup area file FILE.
-The result is a of vectors, each containing one entry from the AREA file.
-The vector contain five strings,
- [prefix name encoding description number]
-though the two last may be nil if they are missing."
- (let (areas)
- (save-excursion
- (set-buffer (find-file-noselect file 'force))
- (buffer-disable-undo (current-buffer))
- (goto-char (point-min))
- (while (not (eobp))
- (setq areas
- (cons (vector (gnus-soup-field)
- (gnus-soup-field)
- (gnus-soup-field)
- (and (eq (preceding-char) ?\t)
- (gnus-soup-field))
- (and (eq (preceding-char) ?\t)
- (string-to-int (gnus-soup-field))))
- areas))
- (if (eq (preceding-char) ?\t)
- (beginning-of-line 2)))
- (kill-buffer (current-buffer)))
- areas))
-
-(defun gnus-soup-parse-replies (file)
- "Parse soup REPLIES file FILE.
-The result is a of vectors, each containing one entry from the REPLIES
-file. The vector contain three strings, [prefix name encoding]."
- (let (replies)
- (save-excursion
- (set-buffer (find-file-noselect file))
- (buffer-disable-undo (current-buffer))
- (goto-char (point-min))
- (while (not (eobp))
- (setq replies
- (cons (vector (gnus-soup-field) (gnus-soup-field)
- (gnus-soup-field))
- replies))
- (if (eq (preceding-char) ?\t)
- (beginning-of-line 2)))
- (kill-buffer (current-buffer)))
- replies))
-
-(defun gnus-soup-field ()
- (prog1
- (buffer-substring (point) (progn (skip-chars-forward "^\t\n") (point)))
- (forward-char 1)))
-
-(defun gnus-soup-read-areas ()
- (or gnus-soup-areas
- (setq gnus-soup-areas
- (gnus-soup-parse-areas (concat gnus-soup-directory "AREAS")))))
-
-(defun gnus-soup-write-areas ()
- "Write the AREAS file."
- (interactive)
- (when gnus-soup-areas
- (nnheader-temp-write (concat gnus-soup-directory "AREAS")
- (let ((areas gnus-soup-areas)
- area)
- (while (setq area (pop areas))
- (insert
- (format
- "%s\t%s\t%s%s\n"
- (gnus-soup-area-prefix area)
- (gnus-soup-area-name area)
- (gnus-soup-area-encoding area)
- (if (or (gnus-soup-area-description area)
- (gnus-soup-area-number area))
- (concat "\t" (or (gnus-soup-area-description
- area) "")
- (if (gnus-soup-area-number area)
- (concat "\t" (int-to-string
- (gnus-soup-area-number area)))
- "")) ""))))))))
-
-(defun gnus-soup-write-replies (dir areas)
- "Write a REPLIES file in DIR containing AREAS."
- (nnheader-temp-write (concat dir "REPLIES")
- (let (area)
- (while (setq area (pop areas))
- (insert (format "%s\t%s\t%s\n"
- (gnus-soup-reply-prefix area)
- (gnus-soup-reply-kind area)
- (gnus-soup-reply-encoding area)))))))
-
-(defun gnus-soup-area (group)
- (gnus-soup-read-areas)
- (let ((areas gnus-soup-areas)
- (real-group (gnus-group-real-name group))
- area result)
- (while areas
- (setq area (car areas)
- areas (cdr areas))
- (if (equal (gnus-soup-area-name area) real-group)
- (setq result area)))
- (or result
- (setq result
- (vector (gnus-soup-unique-prefix)
- real-group
- (format "%c%c%c"
- gnus-soup-encoding-type
- gnus-soup-index-type
- (if (gnus-member-of-valid 'mail group) ?m ?n))
- nil nil)
- gnus-soup-areas (cons result gnus-soup-areas)))
- result))
-
-(defun gnus-soup-unique-prefix (&optional dir)
- (let* ((dir (file-name-as-directory (or dir gnus-soup-directory)))
- (entry (assoc dir gnus-soup-last-prefix))
- gnus-soup-prev-prefix)
- (if entry
- ()
- (and (file-exists-p (concat dir gnus-soup-prefix-file))
- (condition-case nil
- (load (concat dir gnus-soup-prefix-file) nil t t)
- (error nil)))
- (setq gnus-soup-last-prefix
- (cons (setq entry (cons dir (or gnus-soup-prev-prefix 0)))
- gnus-soup-last-prefix)))
- (setcdr entry (1+ (cdr entry)))
- (gnus-soup-write-prefixes)
- (int-to-string (cdr entry))))
-
-(defun gnus-soup-unpack-packet (dir unpacker packet)
- "Unpack PACKET into DIR using UNPACKER.
-Return whether the unpacking was successful."
- (gnus-make-directory dir)
- (gnus-message 4 "Unpacking: %s" (format unpacker packet))
- (prog1
- (zerop (call-process
- shell-file-name nil nil nil shell-command-switch
- (format "cd %s ; %s" (expand-file-name dir)
- (format unpacker packet))))
- (gnus-message 4 "Unpacking...done")))
-
-(defun gnus-soup-send-packet (packet)
- (gnus-soup-unpack-packet
- gnus-soup-replies-directory gnus-soup-unpacker packet)
- (let ((replies (gnus-soup-parse-replies
- (concat gnus-soup-replies-directory "REPLIES"))))
- (save-excursion
- (while replies
- (let* ((msg-file (concat gnus-soup-replies-directory
- (gnus-soup-reply-prefix (car replies))
- ".MSG"))
- (msg-buf (and (file-exists-p msg-file)
- (find-file-noselect msg-file)))
- (tmp-buf (get-buffer-create " *soup send*"))
- beg end)
- (cond
- ((/= (gnus-soup-encoding-format
- (gnus-soup-reply-encoding (car replies))) ?n)
- (error "Unsupported encoding"))
- ((null msg-buf)
- t)
- (t
- (buffer-disable-undo msg-buf)
- (buffer-disable-undo tmp-buf)
- (set-buffer msg-buf)
- (goto-char (point-min))
- (while (not (eobp))
- (or (looking-at "#! *rnews +\\([0-9]+\\)")
- (error "Bad header."))
- (forward-line 1)
- (setq beg (point)
- end (+ (point) (string-to-int
- (buffer-substring
- (match-beginning 1) (match-end 1)))))
- (switch-to-buffer tmp-buf)
- (erase-buffer)
- (insert-buffer-substring msg-buf beg end)
- (goto-char (point-min))
- (search-forward "\n\n")
- (forward-char -1)
- (insert mail-header-separator)
- (setq message-newsreader (setq message-mailer
- (gnus-extended-version)))
- (cond
- ((string= (gnus-soup-reply-kind (car replies)) "news")
- (gnus-message 5 "Sending news message to %s..."
- (mail-fetch-field "newsgroups"))
- (sit-for 1)
- (funcall message-send-news-function))
- ((string= (gnus-soup-reply-kind (car replies)) "mail")
- (gnus-message 5 "Sending mail to %s..."
- (mail-fetch-field "to"))
- (sit-for 1)
- (message-send-mail))
- (t
- (error "Unknown reply kind")))
- (set-buffer msg-buf)
- (goto-char end))
- (delete-file (buffer-file-name))
- (kill-buffer msg-buf)
- (kill-buffer tmp-buf)
- (gnus-message 4 "Sent packet"))))
- (setq replies (cdr replies)))
- t)))
-
-(provide 'gnus-soup)
-
-;;; gnus-soup.el ends here
diff --git a/lisp/gnus-srvr.el b/lisp/gnus-srvr.el
deleted file mode 100644
index 7a29e0f7532..00000000000
--- a/lisp/gnus-srvr.el
+++ /dev/null
@@ -1,708 +0,0 @@
-;;; gnus-srvr.el --- virtual server support for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'gnus)
-(eval-when-compile (require 'cl))
-
-(defvar gnus-server-mode-hook nil
- "Hook run in `gnus-server-mode' buffers.")
-
-(defconst gnus-server-line-format " {%(%h:%w%)} %s\n"
- "Format of server lines.
-It works along the same lines as a normal formatting string,
-with some simple extensions.")
-
-(defvar gnus-server-mode-line-format "Gnus List of servers"
- "The format specification for the server mode line.")
-
-(defvar gnus-server-exit-hook nil
- "*Hook run when exiting the server buffer.")
-
-;;; Internal variables.
-
-(defvar gnus-inserted-opened-servers nil)
-
-(defvar gnus-server-line-format-alist
- `((?h how ?s)
- (?n name ?s)
- (?w where ?s)
- (?s status ?s)))
-
-(defvar gnus-server-mode-line-format-alist
- `((?S news-server ?s)
- (?M news-method ?s)
- (?u user-defined ?s)))
-
-(defvar gnus-server-line-format-spec nil)
-(defvar gnus-server-mode-line-format-spec nil)
-(defvar gnus-server-killed-servers nil)
-
-(defvar gnus-server-mode-map)
-
-(defvar gnus-server-menu-hook nil
- "*Hook run after the creation of the server mode menu.")
-
-(defun gnus-server-make-menu-bar ()
- (gnus-visual-turn-off-edit-menu 'server)
- (unless (boundp 'gnus-server-server-menu)
- (easy-menu-define
- gnus-server-server-menu gnus-server-mode-map ""
- '("Server"
- ["Add" gnus-server-add-server t]
- ["Browse" gnus-server-read-server t]
- ["List" gnus-server-list-servers t]
- ["Kill" gnus-server-kill-server t]
- ["Yank" gnus-server-yank-server t]
- ["Copy" gnus-server-copy-server t]
- ["Edit" gnus-server-edit-server t]
- ["Exit" gnus-server-exit t]
- ))
-
- (easy-menu-define
- gnus-server-connections-menu gnus-server-mode-map ""
- '("Connections"
- ["Open" gnus-server-open-server t]
- ["Close" gnus-server-close-server t]
- ["Deny" gnus-server-deny-server t]
- ["Reset" gnus-server-remove-denials t]
- ))
-
- (run-hooks 'gnus-server-menu-hook)))
-
-(defvar gnus-server-mode-map nil)
-(put 'gnus-server-mode 'mode-class 'special)
-
-(unless gnus-server-mode-map
- (setq gnus-server-mode-map (make-sparse-keymap))
- (suppress-keymap gnus-server-mode-map)
-
- (gnus-define-keys
- gnus-server-mode-map
- " " gnus-server-read-server
- "\r" gnus-server-read-server
- gnus-mouse-2 gnus-server-pick-server
- "q" gnus-server-exit
- "l" gnus-server-list-servers
- "k" gnus-server-kill-server
- "y" gnus-server-yank-server
- "c" gnus-server-copy-server
- "a" gnus-server-add-server
- "e" gnus-server-edit-server
-
- "O" gnus-server-open-server
- "C" gnus-server-close-server
- "D" gnus-server-deny-server
- "R" gnus-server-remove-denials
-
- "\C-c\C-i" gnus-info-find-node))
-
-(defun gnus-server-mode ()
- "Major mode for listing and editing servers.
-
-All normal editing commands are switched off.
-\\<gnus-server-mode-map>
-For more in-depth information on this mode, read the manual
-(`\\[gnus-info-find-node]').
-
-The following commands are available:
-
-\\{gnus-server-mode-map}"
- (interactive)
- (when (and menu-bar-mode
- (gnus-visual-p 'server-menu 'menu))
- (gnus-server-make-menu-bar))
- (kill-all-local-variables)
- (gnus-simplify-mode-line)
- (setq major-mode 'gnus-server-mode)
- (setq mode-name "Server")
- ; (gnus-group-set-mode-line)
- (setq mode-line-process nil)
- (use-local-map gnus-server-mode-map)
- (buffer-disable-undo (current-buffer))
- (setq truncate-lines t)
- (setq buffer-read-only t)
- (run-hooks 'gnus-server-mode-hook))
-
-(defun gnus-server-insert-server-line (name method)
- (let* ((how (car method))
- (where (nth 1 method))
- (elem (assoc method gnus-opened-servers))
- (status (cond ((eq (nth 1 elem) 'denied)
- "(denied)")
- ((or (gnus-server-opened method)
- (eq (nth 1 elem) 'ok))
- "(opened)")
- (t
- "(closed)"))))
- (beginning-of-line)
- (gnus-add-text-properties
- (point)
- (prog1 (1+ (point))
- ;; Insert the text.
- (eval gnus-server-line-format-spec))
- (list 'gnus-server (intern name)))))
-
-(defun gnus-enter-server-buffer ()
- "Set up the server buffer."
- (gnus-server-setup-buffer)
- (gnus-configure-windows 'server)
- (gnus-server-prepare))
-
-(defun gnus-server-setup-buffer ()
- "Initialize the server buffer."
- (unless (get-buffer gnus-server-buffer)
- (save-excursion
- (set-buffer (get-buffer-create gnus-server-buffer))
- (gnus-server-mode)
- (when gnus-carpal
- (gnus-carpal-setup-buffer 'server)))))
-
-(defun gnus-server-prepare ()
- (setq gnus-server-mode-line-format-spec
- (gnus-parse-format gnus-server-mode-line-format
- gnus-server-mode-line-format-alist))
- (setq gnus-server-line-format-spec
- (gnus-parse-format gnus-server-line-format
- gnus-server-line-format-alist t))
- (let ((alist gnus-server-alist)
- (buffer-read-only nil)
- (opened gnus-opened-servers)
- done server op-ser)
- (erase-buffer)
- (setq gnus-inserted-opened-servers nil)
- ;; First we do the real list of servers.
- (while alist
- (push (cdr (setq server (pop alist))) done)
- (when (and server (car server) (cdr server))
- (gnus-server-insert-server-line (car server) (cdr server))))
- ;; Then we insert the list of servers that have been opened in
- ;; this session.
- (while opened
- (unless (member (caar opened) done)
- (gnus-server-insert-server-line
- (setq op-ser (format "%s:%s" (caaar opened) (nth 1 (caar opened))))
- (caar opened))
- (push (list op-ser (caar opened)) gnus-inserted-opened-servers))
- (setq opened (cdr opened))))
- (goto-char (point-min))
- (gnus-server-position-point))
-
-(defun gnus-server-server-name ()
- (let ((server (get-text-property (gnus-point-at-bol) 'gnus-server)))
- (and server (symbol-name server))))
-
-(defalias 'gnus-server-position-point 'gnus-goto-colon)
-
-(defconst gnus-server-edit-buffer "*Gnus edit server*")
-
-(defun gnus-server-update-server (server)
- (save-excursion
- (set-buffer gnus-server-buffer)
- (let* ((buffer-read-only nil)
- (entry (assoc server gnus-server-alist))
- (oentry (assoc (gnus-server-to-method server)
- gnus-opened-servers)))
- (when entry
- (gnus-dribble-enter
- (concat "(gnus-server-set-info \"" server "\" '"
- (prin1-to-string (cdr entry)) ")")))
- (when (or entry oentry)
- ;; Buffer may be narrowed.
- (save-restriction
- (widen)
- (when (gnus-server-goto-server server)
- (gnus-delete-line))
- (if entry
- (gnus-server-insert-server-line (car entry) (cdr entry))
- (gnus-server-insert-server-line
- (format "%s:%s" (caar oentry) (nth 1 (car oentry)))
- (car oentry)))
- (gnus-server-position-point))))))
-
-(defun gnus-server-set-info (server info)
- ;; Enter a select method into the virtual server alist.
- (when (and server info)
- (gnus-dribble-enter
- (concat "(gnus-server-set-info \"" server "\" '"
- (prin1-to-string info) ")"))
- (let* ((server (nth 1 info))
- (entry (assoc server gnus-server-alist)))
- (if entry (setcdr entry info)
- (setq gnus-server-alist
- (nconc gnus-server-alist (list (cons server info))))))))
-
-;;; Interactive server functions.
-
-(defun gnus-server-kill-server (server)
- "Kill the server on the current line."
- (interactive (list (gnus-server-server-name)))
- (unless (gnus-server-goto-server server)
- (if server (error "No such server: %s" server)
- (error "No server on the current line")))
- (unless (assoc server gnus-server-alist)
- (error "Read-only server %s" server))
- (gnus-dribble-enter "")
- (let ((buffer-read-only nil))
- (gnus-delete-line))
- (setq gnus-server-killed-servers
- (cons (assoc server gnus-server-alist) gnus-server-killed-servers))
- (setq gnus-server-alist (delq (car gnus-server-killed-servers)
- gnus-server-alist))
- (gnus-server-position-point))
-
-(defun gnus-server-yank-server ()
- "Yank the previously killed server."
- (interactive)
- (or gnus-server-killed-servers
- (error "No killed servers to be yanked"))
- (let ((alist gnus-server-alist)
- (server (gnus-server-server-name))
- (killed (car gnus-server-killed-servers)))
- (if (not server)
- (setq gnus-server-alist (nconc gnus-server-alist (list killed)))
- (if (string= server (caar gnus-server-alist))
- (setq gnus-server-alist (cons killed gnus-server-alist))
- (while (and (cdr alist)
- (not (string= server (caadr alist))))
- (setq alist (cdr alist)))
- (if alist
- (setcdr alist (cons killed (cdr alist)))
- (setq gnus-server-alist (list killed)))))
- (gnus-server-update-server (car killed))
- (setq gnus-server-killed-servers (cdr gnus-server-killed-servers))
- (gnus-server-position-point)))
-
-(defun gnus-server-exit ()
- "Return to the group buffer."
- (interactive)
- (kill-buffer (current-buffer))
- (switch-to-buffer gnus-group-buffer)
- (run-hooks 'gnus-server-exit-hook))
-
-(defun gnus-server-list-servers ()
- "List all available servers."
- (interactive)
- (let ((cur (gnus-server-server-name)))
- (gnus-server-prepare)
- (if cur (gnus-server-goto-server cur)
- (goto-char (point-max))
- (forward-line -1))
- (gnus-server-position-point)))
-
-(defun gnus-server-set-status (method status)
- "Make METHOD have STATUS."
- (let ((entry (assoc method gnus-opened-servers)))
- (if entry
- (setcar (cdr entry) status)
- (push (list method status) gnus-opened-servers))))
-
-(defun gnus-opened-servers-remove (method)
- "Remove METHOD from the list of opened servers."
- (setq gnus-opened-servers (delq (assoc method gnus-opened-servers)
- gnus-opened-servers)))
-
-(defun gnus-server-open-server (server)
- "Force an open of SERVER."
- (interactive (list (gnus-server-server-name)))
- (let ((method (gnus-server-to-method server)))
- (or method (error "No such server: %s" server))
- (gnus-server-set-status method 'ok)
- (prog1
- (or (gnus-open-server method)
- (progn (message "Couldn't open %s" server) nil))
- (gnus-server-update-server server)
- (gnus-server-position-point))))
-
-(defun gnus-server-close-server (server)
- "Close SERVER."
- (interactive (list (gnus-server-server-name)))
- (let ((method (gnus-server-to-method server)))
- (or method (error "No such server: %s" server))
- (gnus-server-set-status method 'closed)
- (prog1
- (gnus-close-server method)
- (gnus-server-update-server server)
- (gnus-server-position-point))))
-
-(defun gnus-server-deny-server (server)
- "Make sure SERVER will never be attempted opened."
- (interactive (list (gnus-server-server-name)))
- (let ((method (gnus-server-to-method server)))
- (or method (error "No such server: %s" server))
- (gnus-server-set-status method 'denied))
- (gnus-server-update-server server)
- (gnus-server-position-point)
- t)
-
-(defun gnus-server-remove-denials ()
- "Make all denied servers into closed servers."
- (interactive)
- (let ((servers gnus-opened-servers))
- (while servers
- (when (eq (nth 1 (car servers)) 'denied)
- (setcar (nthcdr 1 (car servers)) 'closed))
- (setq servers (cdr servers))))
- (gnus-server-list-servers))
-
-(defun gnus-server-copy-server (from to)
- (interactive
- (list
- (or (gnus-server-server-name)
- (error "No server on the current line"))
- (read-string "Copy to: ")))
- (or from (error "No server on current line"))
- (or (and to (not (string= to ""))) (error "No name to copy to"))
- (and (assoc to gnus-server-alist) (error "%s already exists" to))
- (or (assoc from gnus-server-alist)
- (error "%s: no such server" from))
- (let ((to-entry (gnus-copy-sequence (assoc from gnus-server-alist))))
- (setcar to-entry to)
- (setcar (nthcdr 2 to-entry) to)
- (setq gnus-server-killed-servers
- (cons to-entry gnus-server-killed-servers))
- (gnus-server-yank-server)))
-
-(defun gnus-server-add-server (how where)
- (interactive
- (list (intern (completing-read "Server method: "
- gnus-valid-select-methods nil t))
- (read-string "Server name: ")))
- (setq gnus-server-killed-servers
- (cons (list where how where) gnus-server-killed-servers))
- (gnus-server-yank-server))
-
-(defun gnus-server-goto-server (server)
- "Jump to a server line."
- (interactive
- (list (completing-read "Goto server: " gnus-server-alist nil t)))
- (let ((to (text-property-any (point-min) (point-max)
- 'gnus-server (intern server))))
- (and to
- (progn
- (goto-char to)
- (gnus-server-position-point)))))
-
-(defun gnus-server-edit-server (server)
- "Edit the server on the current line."
- (interactive (list (gnus-server-server-name)))
- (unless server
- (error "No server on current line"))
- (unless (assoc server gnus-server-alist)
- (error "This server can't be edited"))
- (let ((winconf (current-window-configuration))
- (info (cdr (assoc server gnus-server-alist))))
- (gnus-close-server info)
- (get-buffer-create gnus-server-edit-buffer)
- (gnus-configure-windows 'edit-server)
- (gnus-add-current-to-buffer-list)
- (emacs-lisp-mode)
- (make-local-variable 'gnus-prev-winconf)
- (setq gnus-prev-winconf winconf)
- (use-local-map (copy-keymap (current-local-map)))
- (let ((done-func '(lambda ()
- "Exit editing mode and update the information."
- (interactive)
- (gnus-server-edit-server-done 'group))))
- (setcar (cdr (nth 4 done-func)) server)
- (local-set-key "\C-c\C-c" done-func))
- (erase-buffer)
- (insert ";; Type `C-c C-c' after you have edited the server.\n\n")
- (insert (pp-to-string info))))
-
-(defun gnus-server-edit-server-done (server)
- (interactive)
- (set-buffer (get-buffer-create gnus-server-edit-buffer))
- (goto-char (point-min))
- (let ((form (read (current-buffer)))
- (winconf gnus-prev-winconf))
- (gnus-server-set-info server form)
- (kill-buffer (current-buffer))
- (and winconf (set-window-configuration winconf))
- (set-buffer gnus-server-buffer)
- (gnus-server-update-server server)
- (gnus-server-list-servers)
- (gnus-server-position-point)))
-
-(defun gnus-server-read-server (server)
- "Browse a server."
- (interactive (list (gnus-server-server-name)))
- (let ((buf (current-buffer)))
- (prog1
- (gnus-browse-foreign-server (gnus-server-to-method server) buf)
- (save-excursion
- (set-buffer buf)
- (gnus-server-update-server (gnus-server-server-name))
- (gnus-server-position-point)))))
-
-(defun gnus-server-pick-server (e)
- (interactive "e")
- (mouse-set-point e)
- (gnus-server-read-server (gnus-server-server-name)))
-
-
-;;;
-;;; Browse Server Mode
-;;;
-
-(defvar gnus-browse-menu-hook nil
- "*Hook run after the creation of the browse mode menu.")
-
-(defvar gnus-browse-mode-hook nil)
-(defvar gnus-browse-mode-map nil)
-(put 'gnus-browse-mode 'mode-class 'special)
-
-(unless gnus-browse-mode-map
- (setq gnus-browse-mode-map (make-keymap))
- (suppress-keymap gnus-browse-mode-map)
-
- (gnus-define-keys
- gnus-browse-mode-map
- " " gnus-browse-read-group
- "=" gnus-browse-select-group
- "n" gnus-browse-next-group
- "p" gnus-browse-prev-group
- "\177" gnus-browse-prev-group
- "N" gnus-browse-next-group
- "P" gnus-browse-prev-group
- "\M-n" gnus-browse-next-group
- "\M-p" gnus-browse-prev-group
- "\r" gnus-browse-select-group
- "u" gnus-browse-unsubscribe-current-group
- "l" gnus-browse-exit
- "L" gnus-browse-exit
- "q" gnus-browse-exit
- "Q" gnus-browse-exit
- "\C-c\C-c" gnus-browse-exit
- "?" gnus-browse-describe-briefly
-
- "\C-c\C-i" gnus-info-find-node))
-
-(defun gnus-browse-make-menu-bar ()
- (gnus-visual-turn-off-edit-menu 'browse)
- (or
- (boundp 'gnus-browse-menu)
- (progn
- (easy-menu-define
- gnus-browse-menu gnus-browse-mode-map ""
- '("Browse"
- ["Subscribe" gnus-browse-unsubscribe-current-group t]
- ["Read" gnus-browse-read-group t]
- ["Select" gnus-browse-read-group t]
- ["Next" gnus-browse-next-group t]
- ["Prev" gnus-browse-next-group t]
- ["Exit" gnus-browse-exit t]
- ))
- (run-hooks 'gnus-browse-menu-hook))))
-
-(defvar gnus-browse-current-method nil)
-(defvar gnus-browse-return-buffer nil)
-
-(defvar gnus-browse-buffer "*Gnus Browse Server*")
-
-(defun gnus-browse-foreign-server (method &optional return-buffer)
- "Browse the server METHOD."
- (setq gnus-browse-current-method method)
- (setq gnus-browse-return-buffer return-buffer)
- (let ((gnus-select-method method)
- groups group)
- (gnus-message 5 "Connecting to %s..." (nth 1 method))
- (cond
- ((not (gnus-check-server method))
- (gnus-message
- 1 "Unable to contact server: %s" (gnus-status-message method))
- nil)
- ((not (gnus-request-list method))
- (gnus-message
- 1 "Couldn't request list: %s" (gnus-status-message method))
- nil)
- (t
- (get-buffer-create gnus-browse-buffer)
- (gnus-add-current-to-buffer-list)
- (and gnus-carpal (gnus-carpal-setup-buffer 'browse))
- (gnus-configure-windows 'browse)
- (buffer-disable-undo (current-buffer))
- (let ((buffer-read-only nil))
- (erase-buffer))
- (gnus-browse-mode)
- (setq mode-line-buffer-identification
- (list
- (format
- "Gnus: %%b {%s:%s}" (car method) (cadr method))))
- (save-excursion
- (set-buffer nntp-server-buffer)
- (let ((cur (current-buffer)))
- (goto-char (point-min))
- (or (string= gnus-ignored-newsgroups "")
- (delete-matching-lines gnus-ignored-newsgroups))
- (while (re-search-forward
- "\\(^[^ \t]+\\)[ \t]+[0-9]+[ \t]+[0-9]+" nil t)
- (goto-char (match-end 1))
- (setq groups (cons (cons (match-string 1)
- (max 0 (- (1+ (read cur)) (read cur))))
- groups)))))
- (setq groups (sort groups
- (lambda (l1 l2)
- (string< (car l1) (car l2)))))
- (let ((buffer-read-only nil))
- (while groups
- (setq group (car groups))
- (insert
- (format "K%7d: %s\n" (cdr group) (car group)))
- (setq groups (cdr groups))))
- (switch-to-buffer (current-buffer))
- (goto-char (point-min))
- (gnus-group-position-point)
- (gnus-message 5 "Connecting to %s...done" (nth 1 method))
- t))))
-
-(defun gnus-browse-mode ()
- "Major mode for browsing a foreign server.
-
-All normal editing commands are switched off.
-
-\\<gnus-browse-mode-map>
-The only things you can do in this buffer is
-
-1) `\\[gnus-browse-unsubscribe-current-group]' to subscribe to a group.
-The group will be inserted into the group buffer upon exit from this
-buffer.
-
-2) `\\[gnus-browse-read-group]' to read a group ephemerally.
-
-3) `\\[gnus-browse-exit]' to return to the group buffer."
- (interactive)
- (kill-all-local-variables)
- (when (and menu-bar-mode
- (gnus-visual-p 'browse-menu 'menu))
- (gnus-browse-make-menu-bar))
- (gnus-simplify-mode-line)
- (setq major-mode 'gnus-browse-mode)
- (setq mode-name "Browse Server")
- (setq mode-line-process nil)
- (use-local-map gnus-browse-mode-map)
- (buffer-disable-undo (current-buffer))
- (setq truncate-lines t)
- (setq buffer-read-only t)
- (run-hooks 'gnus-browse-mode-hook))
-
-(defun gnus-browse-read-group (&optional no-article)
- "Enter the group at the current line."
- (interactive)
- (let ((group (gnus-browse-group-name)))
- (or (gnus-group-read-ephemeral-group
- group gnus-browse-current-method nil
- (cons (current-buffer) 'browse))
- (error "Couldn't enter %s" group))))
-
-(defun gnus-browse-select-group ()
- "Select the current group."
- (interactive)
- (gnus-browse-read-group 'no))
-
-(defun gnus-browse-next-group (n)
- "Go to the next group."
- (interactive "p")
- (prog1
- (forward-line n)
- (gnus-group-position-point)))
-
-(defun gnus-browse-prev-group (n)
- "Go to the next group."
- (interactive "p")
- (gnus-browse-next-group (- n)))
-
-(defun gnus-browse-unsubscribe-current-group (arg)
- "(Un)subscribe to the next ARG groups."
- (interactive "p")
- (when (eobp)
- (error "No group at current line."))
- (let ((ward (if (< arg 0) -1 1))
- (arg (abs arg)))
- (while (and (> arg 0)
- (not (eobp))
- (gnus-browse-unsubscribe-group)
- (zerop (gnus-browse-next-group ward)))
- (decf arg))
- (gnus-group-position-point)
- (if (/= 0 arg) (gnus-message 7 "No more newsgroups"))
- arg))
-
-(defun gnus-browse-group-name ()
- (save-excursion
- (beginning-of-line)
- (when (re-search-forward ": \\(.*\\)$" (gnus-point-at-eol) t)
- (gnus-group-prefixed-name (match-string 1) gnus-browse-current-method))))
-
-(defun gnus-browse-unsubscribe-group ()
- "Toggle subscription of the current group in the browse buffer."
- (let ((sub nil)
- (buffer-read-only nil)
- group)
- (save-excursion
- (beginning-of-line)
- ;; If this group it killed, then we want to subscribe it.
- (if (= (following-char) ?K) (setq sub t))
- (setq group (gnus-browse-group-name))
- (delete-char 1)
- (if sub
- (progn
- (gnus-group-change-level
- (list t group gnus-level-default-subscribed
- nil nil gnus-browse-current-method)
- gnus-level-default-subscribed gnus-level-killed
- (and (car (nth 1 gnus-newsrc-alist))
- (gnus-gethash (car (nth 1 gnus-newsrc-alist))
- gnus-newsrc-hashtb))
- t)
- (insert ? ))
- (gnus-group-change-level
- group gnus-level-killed gnus-level-default-subscribed)
- (insert ?K)))
- t))
-
-(defun gnus-browse-exit ()
- "Quit browsing and return to the group buffer."
- (interactive)
- (when (eq major-mode 'gnus-browse-mode)
- (kill-buffer (current-buffer)))
- ;; Insert the newly subscribed groups in the group buffer.
- (save-excursion
- (set-buffer gnus-group-buffer)
- (gnus-group-list-groups nil))
- (if gnus-browse-return-buffer
- (gnus-configure-windows 'server 'force)
- (gnus-configure-windows 'group 'force)))
-
-(defun gnus-browse-describe-briefly ()
- "Give a one line description of the group mode commands."
- (interactive)
- (gnus-message 6
- (substitute-command-keys "\\<gnus-browse-mode-map>\\[gnus-group-next-group]:Forward \\[gnus-group-prev-group]:Backward \\[gnus-browse-exit]:Exit \\[gnus-info-find-node]:Run Info \\[gnus-browse-describe-briefly]:This help")))
-
-(provide 'gnus-srvr)
-
-;;; gnus-srvr.el ends here.
diff --git a/lisp/gnus-topic.el b/lisp/gnus-topic.el
deleted file mode 100644
index 774b149a5a4..00000000000
--- a/lisp/gnus-topic.el
+++ /dev/null
@@ -1,1057 +0,0 @@
-;;; gnus-topic.el --- a folding minor mode for Gnus group buffers
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Ilja Weis <kult@uni-paderborn.de>
-;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'gnus)
-(eval-when-compile (require 'cl))
-
-(defvar gnus-topic-mode nil
- "Minor mode for Gnus group buffers.")
-
-(defvar gnus-topic-mode-hook nil
- "Hook run in topic mode buffers.")
-
-(defvar gnus-topic-line-format "%i[ %(%{%n%}%) -- %A ]%v\n"
- "Format of topic lines.
-It works along the same lines as a normal formatting string,
-with some simple extensions.
-
-%i Indentation based on topic level.
-%n Topic name.
-%v Nothing if the topic is visible, \"...\" otherwise.
-%g Number of groups in the topic.
-%a Number of unread articles in the groups in the topic.
-%A Number of unread articles in the groups in the topic and its subtopics.
-")
-
-(defvar gnus-topic-indent-level 2
- "*How much each subtopic should be indented.")
-
-;; Internal variables.
-
-(defvar gnus-topic-active-topology nil)
-(defvar gnus-topic-active-alist nil)
-
-(defvar gnus-topology-checked-p nil
- "Whether the topology has been checked in this session.")
-
-(defvar gnus-topic-killed-topics nil)
-(defvar gnus-topic-inhibit-change-level nil)
-(defvar gnus-topic-tallied-groups nil)
-
-(defconst gnus-topic-line-format-alist
- `((?n name ?s)
- (?v visible ?s)
- (?i indentation ?s)
- (?g number-of-groups ?d)
- (?a (gnus-topic-articles-in-topic entries) ?d)
- (?A total-number-of-articles ?d)
- (?l level ?d)))
-
-(defvar gnus-topic-line-format-spec nil)
-
-;; Functions.
-
-(defun gnus-group-topic-name ()
- "The name of the topic on the current line."
- (let ((topic (get-text-property (gnus-point-at-bol) 'gnus-topic)))
- (and topic (symbol-name topic))))
-
-(defun gnus-group-topic-level ()
- "The level of the topic on the current line."
- (get-text-property (gnus-point-at-bol) 'gnus-topic-level))
-
-(defun gnus-group-topic-unread ()
- "The number of unread articles in topic on the current line."
- (get-text-property (gnus-point-at-bol) 'gnus-topic-unread))
-
-(defun gnus-topic-unread (topic)
- "Return the number of unread articles in TOPIC."
- (or (save-excursion
- (and (gnus-topic-goto-topic topic)
- (gnus-group-topic-unread)))
- 0))
-
-(defun gnus-topic-init-alist ()
- "Initialize the topic structures."
- (setq gnus-topic-topology
- (cons (list "Gnus" 'visible)
- (mapcar (lambda (topic)
- (list (list (car topic) 'visible)))
- '(("misc")))))
- (setq gnus-topic-alist
- (list (cons "misc"
- (mapcar (lambda (info) (gnus-info-group info))
- (cdr gnus-newsrc-alist)))
- (list "Gnus")))
- (gnus-topic-enter-dribble))
-
-(defun gnus-group-prepare-topics (level &optional all lowest regexp list-topic topic-level)
- "List all newsgroups with unread articles of level LEVEL or lower, and
-use the `gnus-group-topics' to sort the groups.
-If ALL is non-nil, list groups that have no unread articles.
-If LOWEST is non-nil, list all newsgroups of level LOWEST or higher."
- (set-buffer gnus-group-buffer)
- (let ((buffer-read-only nil)
- (lowest (or lowest 1)))
-
- (setq gnus-topic-tallied-groups nil)
-
- (when (or (not gnus-topic-alist)
- (not gnus-topology-checked-p))
- (gnus-topic-check-topology))
-
- (unless list-topic
- (erase-buffer))
-
- ;; List dead groups?
- (when (and (>= level gnus-level-zombie) (<= lowest gnus-level-zombie))
- (gnus-group-prepare-flat-list-dead
- (setq gnus-zombie-list (sort gnus-zombie-list 'string<))
- gnus-level-zombie ?Z
- regexp))
-
- (when (and (>= level gnus-level-killed) (<= lowest gnus-level-killed))
- (gnus-group-prepare-flat-list-dead
- (setq gnus-killed-list (sort gnus-killed-list 'string<))
- gnus-level-killed ?K
- regexp))
-
- ;; Use topics.
- (when (< lowest gnus-level-zombie)
- (if list-topic
- (let ((top (gnus-topic-find-topology list-topic)))
- (gnus-topic-prepare-topic (cdr top) (car top)
- (or topic-level level) all))
- (gnus-topic-prepare-topic gnus-topic-topology 0
- (or topic-level level) all))))
-
- (gnus-group-set-mode-line)
- (setq gnus-group-list-mode (cons level all))
- (run-hooks 'gnus-group-prepare-hook))
-
-(defun gnus-topic-prepare-topic (topicl level &optional list-level all silent)
- "Insert TOPIC into the group buffer.
-If SILENT, don't insert anything. Return the number of unread
-articles in the topic and its subtopics."
- (let* ((type (pop topicl))
- (entries (gnus-topic-find-groups (car type) list-level all))
- (visiblep (and (eq (nth 1 type) 'visible) (not silent)))
- (gnus-group-indentation
- (make-string (* gnus-topic-indent-level level) ? ))
- (beg (progn (beginning-of-line) (point)))
- (topicl (reverse topicl))
- (all-entries entries)
- (unread 0)
- (topic (car type))
- info entry end active)
- ;; Insert any sub-topics.
- (while topicl
- (incf unread
- (gnus-topic-prepare-topic
- (pop topicl) (1+ level) list-level all
- (not visiblep))))
- (setq end (point))
- (goto-char beg)
- ;; Insert all the groups that belong in this topic.
- (while (setq entry (pop entries))
- (when visiblep
- (if (stringp entry)
- ;; Dead groups.
- (gnus-group-insert-group-line
- entry (if (member entry gnus-zombie-list) 8 9)
- nil (- (1+ (cdr (setq active (gnus-active entry))))
- (car active)) nil)
- ;; Living groups.
- (when (setq info (nth 2 entry))
- (gnus-group-insert-group-line
- (gnus-info-group info)
- (gnus-info-level info) (gnus-info-marks info)
- (car entry) (gnus-info-method info)))))
- (when (and (listp entry)
- (numberp (car entry))
- (not (member (gnus-info-group (setq info (nth 2 entry)))
- gnus-topic-tallied-groups)))
- (push (gnus-info-group info) gnus-topic-tallied-groups)
- (incf unread (car entry))))
- (goto-char beg)
- ;; Insert the topic line.
- (unless silent
- (gnus-extent-start-open (point))
- (gnus-topic-insert-topic-line
- (car type) visiblep
- (not (eq (nth 2 type) 'hidden))
- level all-entries unread))
- (goto-char end)
- unread))
-
-(defun gnus-topic-find-groups (topic &optional level all)
- "Return entries for all visible groups in TOPIC."
- (let ((groups (cdr (assoc topic gnus-topic-alist)))
- info clevel unread group lowest params visible-groups entry active)
- (setq lowest (or lowest 1))
- (setq level (or level 7))
- ;; We go through the newsrc to look for matches.
- (while groups
- (setq entry (gnus-gethash (setq group (pop groups)) gnus-newsrc-hashtb)
- info (nth 2 entry)
- params (gnus-info-params info)
- active (gnus-active group)
- unread (or (car entry)
- (and (not (equal group "dummy.group"))
- active
- (- (1+ (cdr active)) (car active))))
- clevel (or (gnus-info-level info)
- (if (member group gnus-zombie-list) 8 9)))
- (and
- unread ; nil means that the group is dead.
- (<= clevel level)
- (>= clevel lowest) ; Is inside the level we want.
- (or all
- (if (eq unread t)
- gnus-group-list-inactive-groups
- (> unread 0))
- (and gnus-list-groups-with-ticked-articles
- (cdr (assq 'tick (gnus-info-marks info))))
- ; Has right readedness.
- ;; Check for permanent visibility.
- (and gnus-permanently-visible-groups
- (string-match gnus-permanently-visible-groups group))
- (memq 'visible params)
- (cdr (assq 'visible params)))
- ;; Add this group to the list of visible groups.
- (push (or entry group) visible-groups)))
- (nreverse visible-groups)))
-
-(defun gnus-topic-remove-topic (&optional insert total-remove hide in-level)
- "Remove the current topic."
- (let ((topic (gnus-group-topic-name))
- (level (gnus-group-topic-level))
- (beg (progn (beginning-of-line) (point)))
- buffer-read-only)
- (when topic
- (while (and (zerop (forward-line 1))
- (> (or (gnus-group-topic-level) (1+ level)) level)))
- (delete-region beg (point))
- (setcar (cdadr (gnus-topic-find-topology topic))
- (if insert 'visible 'invisible))
- (when hide
- (setcdr (cdadr (gnus-topic-find-topology topic))
- (list hide)))
- (unless total-remove
- (gnus-topic-insert-topic topic in-level)))))
-
-(defun gnus-topic-insert-topic (topic &optional level)
- "Insert TOPIC."
- (gnus-group-prepare-topics
- (car gnus-group-list-mode) (cdr gnus-group-list-mode)
- nil nil topic level))
-
-(defun gnus-topic-fold (&optional insert)
- "Remove/insert the current topic."
- (let ((topic (gnus-group-topic-name)))
- (when topic
- (save-excursion
- (if (not (gnus-group-active-topic-p))
- (gnus-topic-remove-topic
- (or insert (not (gnus-topic-visible-p))))
- (let ((gnus-topic-topology gnus-topic-active-topology)
- (gnus-topic-alist gnus-topic-active-alist)
- (gnus-group-list-mode (cons 5 t)))
- (gnus-topic-remove-topic
- (or insert (not (gnus-topic-visible-p))) nil nil 9)))))))
-
-(defun gnus-group-topic-p ()
- "Return non-nil if the current line is a topic."
- (gnus-group-topic-name))
-
-(defun gnus-topic-visible-p ()
- "Return non-nil if the current topic is visible."
- (get-text-property (gnus-point-at-bol) 'gnus-topic-visible))
-
-(defun gnus-topic-insert-topic-line (name visiblep shownp level entries
- &optional unread)
- (let* ((visible (if visiblep "" "..."))
- (indentation (make-string (* gnus-topic-indent-level level) ? ))
- (total-number-of-articles unread)
- (number-of-groups (length entries))
- (active-topic (eq gnus-topic-alist gnus-topic-active-alist)))
- (beginning-of-line)
- ;; Insert the text.
- (gnus-add-text-properties
- (point)
- (prog1 (1+ (point))
- (eval gnus-topic-line-format-spec)
- (gnus-topic-remove-excess-properties)1)
- (list 'gnus-topic (intern name)
- 'gnus-topic-level level
- 'gnus-topic-unread unread
- 'gnus-active active-topic
- 'gnus-topic-visible visiblep))))
-
-(defun gnus-topic-previous-topic (topic)
- "Return the previous topic on the same level as TOPIC."
- (let ((top (cddr (gnus-topic-find-topology
- (gnus-topic-parent-topic topic)))))
- (unless (equal topic (caaar top))
- (while (and top (not (equal (caaadr top) topic)))
- (setq top (cdr top)))
- (caaar top))))
-
-(defun gnus-topic-parent-topic (topic &optional topology)
- "Return the parent of TOPIC."
- (unless topology
- (setq topology gnus-topic-topology))
- (let ((parent (car (pop topology)))
- result found)
- (while (and topology
- (not (setq found (equal (caaar topology) topic)))
- (not (setq result (gnus-topic-parent-topic topic
- (car topology)))))
- (setq topology (cdr topology)))
- (or result (and found parent))))
-
-(defun gnus-topic-next-topic (topic &optional previous)
- "Return the next sibling of TOPIC."
- (let ((topology gnus-topic-topology)
- (parentt (cddr (gnus-topic-find-topology
- (gnus-topic-parent-topic topic))))
- prev)
- (while (and parentt
- (not (equal (caaar parentt) topic)))
- (setq prev (caaar parentt)
- parentt (cdr parentt)))
- (if previous
- prev
- (caaadr parentt))))
-
-(defun gnus-topic-find-topology (topic &optional topology level remove)
- "Return the topology of TOPIC."
- (unless topology
- (setq topology gnus-topic-topology)
- (setq level 0))
- (let ((top topology)
- result)
- (if (equal (caar topology) topic)
- (progn
- (when remove
- (delq topology remove))
- (cons level topology))
- (setq topology (cdr topology))
- (while (and topology
- (not (setq result (gnus-topic-find-topology
- topic (car topology) (1+ level)
- (and remove top)))))
- (setq topology (cdr topology)))
- result)))
-
-(gnus-add-shutdown 'gnus-topic-close 'gnus)
-
-(defun gnus-topic-close ()
- (setq gnus-topic-active-topology nil
- gnus-topic-active-alist nil
- gnus-topic-killed-topics nil
- gnus-topic-tallied-groups nil
- gnus-topology-checked-p nil))
-
-(defun gnus-topic-check-topology ()
- ;; The first time we set the topology to whatever we have
- ;; gotten here, which can be rather random.
- (unless gnus-topic-alist
- (gnus-topic-init-alist))
-
- (setq gnus-topology-checked-p t)
- (let ((topics (gnus-topic-list))
- (alist gnus-topic-alist)
- changed)
- (while alist
- (unless (member (caar alist) topics)
- (nconc gnus-topic-topology
- (list (list (list (caar alist) 'visible))))
- (setq changed t))
- (setq alist (cdr alist)))
- (when changed
- (gnus-topic-enter-dribble)))
- (let* ((tgroups (apply 'append (mapcar (lambda (entry) (cdr entry))
- gnus-topic-alist)))
- (entry (assoc (caar gnus-topic-topology) gnus-topic-alist))
- (newsrc gnus-newsrc-alist)
- group)
- (while newsrc
- (unless (member (setq group (gnus-info-group (pop newsrc))) tgroups)
- (setcdr entry (cons group (cdr entry)))))))
-
-(defvar gnus-tmp-topics nil)
-(defun gnus-topic-list (&optional topology)
- (unless topology
- (setq topology gnus-topic-topology
- gnus-tmp-topics nil))
- (push (caar topology) gnus-tmp-topics)
- (mapcar 'gnus-topic-list (cdr topology))
- gnus-tmp-topics)
-
-(defun gnus-topic-enter-dribble ()
- (gnus-dribble-enter
- (format "(setq gnus-topic-topology '%S)" gnus-topic-topology)))
-
-(defun gnus-topic-articles-in-topic (entries)
- (let ((total 0)
- number)
- (while entries
- (when (numberp (setq number (car (pop entries))))
- (incf total number)))
- total))
-
-(defun gnus-group-topic (group)
- "Return the topic GROUP is a member of."
- (let ((alist gnus-topic-alist)
- out)
- (while alist
- (when (member group (cdar alist))
- (setq out (caar alist)
- alist nil))
- (setq alist (cdr alist)))
- out))
-
-(defun gnus-topic-goto-topic (topic)
- "Go to TOPIC."
- (when topic
- (gnus-goto-char (text-property-any (point-min) (point-max)
- 'gnus-topic (intern topic)))))
-
-(defun gnus-group-parent-topic ()
- "Return the name of the current topic."
- (let ((result
- (or (get-text-property (point) 'gnus-topic)
- (save-excursion
- (and (gnus-goto-char (previous-single-property-change
- (point) 'gnus-topic))
- (get-text-property (max (1- (point)) (point-min))
- 'gnus-topic))))))
- (when result
- (symbol-name result))))
-
-(defun gnus-topic-update-topic ()
- "Update all parent topics to the current group."
- (when (and (eq major-mode 'gnus-group-mode)
- gnus-topic-mode)
- (let ((group (gnus-group-group-name))
- (buffer-read-only nil))
- (when (and group (gnus-get-info group)
- (gnus-topic-goto-topic (gnus-group-parent-topic)))
- (gnus-topic-update-topic-line (gnus-group-topic-name))
- (gnus-group-goto-group group)
- (gnus-group-position-point)))))
-
-(defun gnus-topic-goto-missing-group (group)
- "Place point where GROUP is supposed to be inserted."
- (let* ((topic (gnus-group-topic group))
- (groups (cdr (assoc topic gnus-topic-alist)))
- (g (cdr (member group groups)))
- (unfound t))
- (while (and g unfound)
- (when (gnus-group-goto-group (pop g))
- (beginning-of-line)
- (setq unfound nil)))
- (when unfound
- (setq g (cdr (member group (reverse groups))))
- (while (and g unfound)
- (when (gnus-group-goto-group (pop g))
- (forward-line 1)
- (setq unfound nil)))
- (when unfound
- (gnus-topic-goto-topic topic)
- (forward-line 1)))))
-
-(defun gnus-topic-update-topic-line (topic-name &optional reads)
- (let* ((top (gnus-topic-find-topology topic-name))
- (type (cadr top))
- (children (cddr top))
- (entries (gnus-topic-find-groups
- (car type) (car gnus-group-list-mode)
- (cdr gnus-group-list-mode)))
- (parent (gnus-topic-parent-topic topic-name))
- (all-entries entries)
- (unread 0)
- old-unread entry)
- (when (gnus-topic-goto-topic (car type))
- ;; Tally all the groups that belong in this topic.
- (if reads
- (setq unread (- (gnus-group-topic-unread) reads))
- (while children
- (incf unread (gnus-topic-unread (caar (pop children)))))
- (while (setq entry (pop entries))
- (when (numberp (car entry))
- (incf unread (car entry)))))
- (setq old-unread (gnus-group-topic-unread))
- ;; Insert the topic line.
- (gnus-topic-insert-topic-line
- (car type) (gnus-topic-visible-p)
- (not (eq (nth 2 type) 'hidden))
- (gnus-group-topic-level) all-entries unread)
- (gnus-delete-line))
- (when parent
- (forward-line -1)
- (gnus-topic-update-topic-line
- parent (- old-unread (gnus-group-topic-unread))))
- unread))
-
-(defun gnus-topic-grok-active (&optional force)
- "Parse all active groups and create topic structures for them."
- ;; First we make sure that we have really read the active file.
- (when (or force
- (not gnus-topic-active-alist))
- (let (groups)
- ;; Get a list of all groups available.
- (mapatoms (lambda (g) (when (symbol-value g)
- (push (symbol-name g) groups)))
- gnus-active-hashtb)
- (setq groups (sort groups 'string<))
- ;; Init the variables.
- (setq gnus-topic-active-topology (list (list "" 'visible)))
- (setq gnus-topic-active-alist nil)
- ;; Descend the top-level hierarchy.
- (gnus-topic-grok-active-1 gnus-topic-active-topology groups)
- ;; Set the top-level topic names to something nice.
- (setcar (car gnus-topic-active-topology) "Gnus active")
- (setcar (car gnus-topic-active-alist) "Gnus active"))))
-
-(defun gnus-topic-grok-active-1 (topology groups)
- (let* ((name (caar topology))
- (prefix (concat "^" (regexp-quote name)))
- tgroups ntopology group)
- (while (and groups
- (string-match prefix (setq group (car groups))))
- (if (not (string-match "\\." group (match-end 0)))
- ;; There are no further hierarchies here, so we just
- ;; enter this group into the list belonging to this
- ;; topic.
- (push (pop groups) tgroups)
- ;; New sub-hierarchy, so we add it to the topology.
- (nconc topology (list (setq ntopology
- (list (list (substring
- group 0 (match-end 0))
- 'invisible)))))
- ;; Descend the hierarchy.
- (setq groups (gnus-topic-grok-active-1 ntopology groups))))
- ;; We remove the trailing "." from the topic name.
- (setq name
- (if (string-match "\\.$" name)
- (substring name 0 (match-beginning 0))
- name))
- ;; Add this topic and its groups to the topic alist.
- (push (cons name (nreverse tgroups)) gnus-topic-active-alist)
- (setcar (car topology) name)
- ;; We return the rest of the groups that didn't belong
- ;; to this topic.
- groups))
-
-(defun gnus-group-active-topic-p ()
- "Return whether the current active comes from the active topics."
- (save-excursion
- (beginning-of-line)
- (get-text-property (point) 'gnus-active)))
-
-;;; Topic mode, commands and keymap.
-
-(defvar gnus-topic-mode-map nil)
-(defvar gnus-group-topic-map nil)
-
-(unless gnus-topic-mode-map
- (setq gnus-topic-mode-map (make-sparse-keymap))
-
- ;; Override certain group mode keys.
- (gnus-define-keys
- gnus-topic-mode-map
- "=" gnus-topic-select-group
- "\r" gnus-topic-select-group
- " " gnus-topic-read-group
- "\C-k" gnus-topic-kill-group
- "\C-y" gnus-topic-yank-group
- "\M-g" gnus-topic-get-new-news-this-topic
- "AT" gnus-topic-list-active
- gnus-mouse-2 gnus-mouse-pick-topic)
-
- ;; Define a new submap.
- (gnus-define-keys
- (gnus-group-topic-map "T" gnus-group-mode-map)
- "#" gnus-topic-mark-topic
- "\M-#" gnus-topic-unmark-topic
- "n" gnus-topic-create-topic
- "m" gnus-topic-move-group
- "D" gnus-topic-remove-group
- "c" gnus-topic-copy-group
- "h" gnus-topic-hide-topic
- "s" gnus-topic-show-topic
- "M" gnus-topic-move-matching
- "C" gnus-topic-copy-matching
- "\C-i" gnus-topic-indent
- [tab] gnus-topic-indent
- "r" gnus-topic-rename
- "\177" gnus-topic-delete))
-
-(defun gnus-topic-make-menu-bar ()
- (unless (boundp 'gnus-topic-menu)
- (easy-menu-define
- gnus-topic-menu gnus-topic-mode-map ""
- '("Topics"
- ["Toggle topics" gnus-topic-mode t]
- ("Groups"
- ["Copy" gnus-topic-copy-group t]
- ["Move" gnus-topic-move-group t]
- ["Remove" gnus-topic-remove-group t]
- ["Copy matching" gnus-topic-copy-matching t]
- ["Move matching" gnus-topic-move-matching t])
- ("Topics"
- ["Show" gnus-topic-show-topic t]
- ["Hide" gnus-topic-hide-topic t]
- ["Delete" gnus-topic-delete t]
- ["Rename" gnus-topic-rename t]
- ["Create" gnus-topic-create-topic t]
- ["Mark" gnus-topic-mark-topic t]
- ["Indent" gnus-topic-indent t])
- ["List active" gnus-topic-list-active t]))))
-
-(defun gnus-topic-mode (&optional arg redisplay)
- "Minor mode for topicsifying Gnus group buffers."
- (interactive (list current-prefix-arg t))
- (when (eq major-mode 'gnus-group-mode)
- (make-local-variable 'gnus-topic-mode)
- (setq gnus-topic-mode
- (if (null arg) (not gnus-topic-mode)
- (> (prefix-numeric-value arg) 0)))
- ;; Infest Gnus with topics.
- (when gnus-topic-mode
- (when (and menu-bar-mode
- (gnus-visual-p 'topic-menu 'menu))
- (gnus-topic-make-menu-bar))
- (setq gnus-topic-line-format-spec
- (gnus-parse-format gnus-topic-line-format
- gnus-topic-line-format-alist t))
- (unless (assq 'gnus-topic-mode minor-mode-alist)
- (push '(gnus-topic-mode " Topic") minor-mode-alist))
- (unless (assq 'gnus-topic-mode minor-mode-map-alist)
- (push (cons 'gnus-topic-mode gnus-topic-mode-map)
- minor-mode-map-alist))
- (add-hook 'gnus-summary-exit-hook 'gnus-topic-update-topic)
- (add-hook 'gnus-group-catchup-group-hook 'gnus-topic-update-topic)
- (add-hook 'gnus-group-update-group-hook 'gnus-topic-update-topic)
- (make-local-variable 'gnus-group-prepare-function)
- (setq gnus-group-prepare-function 'gnus-group-prepare-topics)
- (make-local-variable 'gnus-group-goto-next-group-function)
- (setq gnus-group-goto-next-group-function
- 'gnus-topic-goto-next-group)
- (setq gnus-group-change-level-function 'gnus-topic-change-level)
- (setq gnus-goto-missing-group-function 'gnus-topic-goto-missing-group)
- (make-local-variable 'gnus-group-indentation-function)
- (setq gnus-group-indentation-function
- 'gnus-topic-group-indentation)
- (setq gnus-topology-checked-p nil)
- ;; We check the topology.
- (when gnus-newsrc-alist
- (gnus-topic-check-topology))
- (run-hooks 'gnus-topic-mode-hook))
- ;; Remove topic infestation.
- (unless gnus-topic-mode
- (remove-hook 'gnus-summary-exit-hook 'gnus-topic-update-topic)
- (remove-hook 'gnus-group-change-level-function
- 'gnus-topic-change-level)
- (setq gnus-group-prepare-function 'gnus-group-prepare-flat))
- (when redisplay
- (gnus-group-list-groups))))
-
-(defun gnus-topic-select-group (&optional all)
- "Select this newsgroup.
-No article is selected automatically.
-If ALL is non-nil, already read articles become readable.
-If ALL is a number, fetch this number of articles."
- (interactive "P")
- (if (gnus-group-topic-p)
- (let ((gnus-group-list-mode
- (if all (cons (if (numberp all) all 7) t) gnus-group-list-mode)))
- (gnus-topic-fold all))
- (gnus-group-select-group all)))
-
-(defun gnus-mouse-pick-topic (e)
- "Select the group or topic under the mouse pointer."
- (interactive "e")
- (mouse-set-point e)
- (gnus-topic-read-group nil))
-
-(defun gnus-topic-read-group (&optional all no-article group)
- "Read news in this newsgroup.
-If the prefix argument ALL is non-nil, already read articles become
-readable. IF ALL is a number, fetch this number of articles. If the
-optional argument NO-ARTICLE is non-nil, no article will be
-auto-selected upon group entry. If GROUP is non-nil, fetch that
-group."
- (interactive "P")
- (if (gnus-group-topic-p)
- (let ((gnus-group-list-mode
- (if all (cons (if (numberp all) all 7) t) gnus-group-list-mode)))
- (gnus-topic-fold all))
- (gnus-group-read-group all no-article group)))
-
-(defun gnus-topic-create-topic (topic parent &optional previous full-topic)
- (interactive
- (list
- (read-string "New topic: ")
- (gnus-group-parent-topic)))
- ;; Check whether this topic already exists.
- (when (gnus-topic-find-topology topic)
- (error "Topic aleady exists"))
- (unless parent
- (setq parent (caar gnus-topic-topology)))
- (let ((top (cdr (gnus-topic-find-topology parent)))
- (full-topic (or full-topic `((,topic visible)))))
- (unless top
- (error "No such parent topic: %s" parent))
- (if previous
- (progn
- (while (and (cdr top)
- (not (equal (caaadr top) previous)))
- (setq top (cdr top)))
- (setcdr top (cons full-topic (cdr top))))
- (nconc top (list full-topic)))
- (unless (assoc topic gnus-topic-alist)
- (push (list topic) gnus-topic-alist)))
- (gnus-topic-enter-dribble)
- (gnus-group-list-groups)
- (gnus-topic-goto-topic topic))
-
-(defun gnus-topic-move-group (n topic &optional copyp)
- "Move the next N groups to TOPIC.
-If COPYP, copy the groups instead."
- (interactive
- (list current-prefix-arg
- (completing-read "Move to topic: " gnus-topic-alist nil t)))
- (let ((groups (gnus-group-process-prefix n))
- (topicl (assoc topic gnus-topic-alist))
- entry)
- (mapcar (lambda (g)
- (gnus-group-remove-mark g)
- (when (and
- (setq entry (assoc (gnus-group-parent-topic)
- gnus-topic-alist))
- (not copyp))
- (setcdr entry (gnus-delete-first g (cdr entry))))
- (nconc topicl (list g)))
- groups)
- (gnus-group-position-point))
- (gnus-topic-enter-dribble)
- (gnus-group-list-groups))
-
-(defun gnus-topic-remove-group ()
- "Remove the current group from the topic."
- (interactive)
- (let ((topicl (assoc (gnus-group-parent-topic) gnus-topic-alist))
- (group (gnus-group-group-name))
- (buffer-read-only nil))
- (when (and topicl group)
- (gnus-delete-line)
- (gnus-delete-first group topicl))
- (gnus-group-position-point)))
-
-(defun gnus-topic-copy-group (n topic)
- "Copy the current group to a topic."
- (interactive
- (list current-prefix-arg
- (completing-read "Copy to topic: " gnus-topic-alist nil t)))
- (gnus-topic-move-group n topic t))
-
-(defun gnus-topic-group-indentation ()
- (make-string
- (* gnus-topic-indent-level
- (or (save-excursion
- (gnus-topic-goto-topic (gnus-group-parent-topic))
- (gnus-group-topic-level)) 0)) ? ))
-
-(defun gnus-topic-change-level (group level oldlevel)
- "Run when changing levels to enter/remove groups from topics."
- (save-excursion
- (set-buffer gnus-group-buffer)
- (when (and gnus-topic-mode
- gnus-topic-alist
- (not gnus-topic-inhibit-change-level))
- ;; Remove the group from the topics.
- (when (and (< oldlevel gnus-level-zombie)
- (>= level gnus-level-zombie))
- (let (alist)
- (forward-line -1)
- (when (setq alist (assoc (gnus-group-parent-topic) gnus-topic-alist))
- (setcdr alist (gnus-delete-first group (cdr alist))))))
- ;; If the group is subscribed. then we enter it into the topics.
- (when (and (< level gnus-level-zombie)
- (>= oldlevel gnus-level-zombie))
- (let* ((prev (gnus-group-group-name))
- (gnus-topic-inhibit-change-level t)
- (gnus-group-indentation
- (make-string
- (* gnus-topic-indent-level
- (or (save-excursion
- (gnus-topic-goto-topic (gnus-group-parent-topic))
- (gnus-group-topic-level)) 0)) ? ))
- (yanked (list group))
- alist talist end)
- ;; Then we enter the yanked groups into the topics they belong
- ;; to.
- (when (setq alist (assoc (save-excursion
- (forward-line -1)
- (or
- (gnus-group-parent-topic)
- (caar gnus-topic-topology)))
- gnus-topic-alist))
- (setq talist alist)
- (when (stringp yanked)
- (setq yanked (list yanked)))
- (if (not prev)
- (nconc alist yanked)
- (if (not (cdr alist))
- (setcdr alist (nconc yanked (cdr alist)))
- (while (and (not end) (cdr alist))
- (when (equal (cadr alist) prev)
- (setcdr alist (nconc yanked (cdr alist)))
- (setq end t))
- (setq alist (cdr alist)))
- (unless end
- (nconc talist yanked))))))
- (gnus-topic-update-topic)))))
-
-(defun gnus-topic-goto-next-group (group props)
- "Go to group or the next group after group."
- (if (null group)
- (gnus-topic-goto-topic (symbol-name (cadr (memq 'gnus-topic props))))
- (if (gnus-group-goto-group group)
- t
- ;; The group is no longer visible.
- (let* ((list (assoc (gnus-group-parent-topic) gnus-topic-alist))
- (after (cdr (member group (cdr list)))))
- ;; First try to put point on a group after the current one.
- (while (and after
- (not (gnus-group-goto-group (car after))))
- (setq after (cdr after)))
- ;; Then try to put point on a group before point.
- (unless after
- (setq after (cdr (member group (reverse (cdr list)))))
- (while (and after
- (not (gnus-group-goto-group (car after))))
- (setq after (cdr after))))
- ;; Finally, just put point on the topic.
- (unless after
- (gnus-topic-goto-topic (car list))
- (setq after nil))
- t))))
-
-(defun gnus-topic-kill-group (&optional n discard)
- "Kill the next N groups."
- (interactive "P")
- (if (gnus-group-topic-p)
- (let ((topic (gnus-group-topic-name)))
- (gnus-topic-remove-topic nil t)
- (push (gnus-topic-find-topology topic nil nil gnus-topic-topology)
- gnus-topic-killed-topics))
- (gnus-group-kill-group n discard)
- (gnus-topic-update-topic)))
-
-(defun gnus-topic-yank-group (&optional arg)
- "Yank the last topic."
- (interactive "p")
- (if gnus-topic-killed-topics
- (let ((previous
- (or (gnus-group-topic-name)
- (gnus-topic-next-topic (gnus-group-parent-topic))))
- (item (cdr (pop gnus-topic-killed-topics))))
- (gnus-topic-create-topic
- (caar item) (gnus-topic-parent-topic previous) previous
- item)
- (gnus-topic-goto-topic (caar item)))
- (let* ((prev (gnus-group-group-name))
- (gnus-topic-inhibit-change-level t)
- (gnus-group-indentation
- (make-string
- (* gnus-topic-indent-level
- (or (save-excursion
- (gnus-topic-goto-topic (gnus-group-parent-topic))
- (gnus-group-topic-level)) 0)) ? ))
- yanked alist)
- ;; We first yank the groups the normal way...
- (setq yanked (gnus-group-yank-group arg))
- ;; Then we enter the yanked groups into the topics they belong
- ;; to.
- (setq alist (assoc (save-excursion
- (forward-line -1)
- (gnus-group-parent-topic))
- gnus-topic-alist))
- (when (stringp yanked)
- (setq yanked (list yanked)))
- (if (not prev)
- (nconc alist yanked)
- (if (not (cdr alist))
- (setcdr alist (nconc yanked (cdr alist)))
- (while (cdr alist)
- (when (equal (cadr alist) prev)
- (setcdr alist (nconc yanked (cdr alist)))
- (setq alist nil))
- (setq alist (cdr alist))))))
- (gnus-topic-update-topic)))
-
-(defun gnus-topic-hide-topic ()
- "Hide all subtopics under the current topic."
- (interactive)
- (when (gnus-group-parent-topic)
- (gnus-topic-goto-topic (gnus-group-parent-topic))
- (gnus-topic-remove-topic nil nil 'hidden)))
-
-(defun gnus-topic-show-topic ()
- "Show the hidden topic."
- (interactive)
- (when (gnus-group-topic-p)
- (gnus-topic-remove-topic t nil 'shown)))
-
-(defun gnus-topic-mark-topic (topic &optional unmark)
- "Mark all groups in the topic with the process mark."
- (interactive (list (gnus-group-parent-topic)))
- (save-excursion
- (let ((groups (gnus-topic-find-groups topic 9 t)))
- (while groups
- (funcall (if unmark 'gnus-group-remove-mark 'gnus-group-set-mark)
- (gnus-info-group (nth 2 (pop groups))))))))
-
-(defun gnus-topic-unmark-topic (topic &optional unmark)
- "Remove the process mark from all groups in the topic."
- (interactive (list (gnus-group-parent-topic)))
- (gnus-topic-mark-topic topic t))
-
-(defun gnus-topic-get-new-news-this-topic (&optional n)
- "Check for new news in the current topic."
- (interactive "P")
- (if (not (gnus-group-topic-p))
- (gnus-group-get-new-news-this-group n)
- (gnus-topic-mark-topic (gnus-group-topic-name))
- (gnus-group-get-new-news-this-group)))
-
-(defun gnus-topic-move-matching (regexp topic &optional copyp)
- "Move all groups that match REGEXP to some topic."
- (interactive
- (let (topic)
- (nreverse
- (list
- (setq topic (completing-read "Move to topic: " gnus-topic-alist nil t))
- (read-string (format "Move to %s (regexp): " topic))))))
- (gnus-group-mark-regexp regexp)
- (gnus-topic-move-group nil topic copyp))
-
-(defun gnus-topic-copy-matching (regexp topic &optional copyp)
- "Copy all groups that match REGEXP to some topic."
- (interactive
- (let (topic)
- (nreverse
- (list
- (setq topic (completing-read "Copy to topic: " gnus-topic-alist nil t))
- (read-string (format "Copy to %s (regexp): " topic))))))
- (gnus-topic-move-matching regexp topic t))
-
-(defun gnus-topic-delete (topic)
- "Delete a topic."
- (interactive (list (gnus-group-topic-name)))
- (unless topic
- (error "No topic to be deleted"))
- (let ((entry (assoc topic gnus-topic-alist))
- (buffer-read-only nil))
- (when (cdr entry)
- (error "Topic not empty"))
- ;; Delete if visible.
- (when (gnus-topic-goto-topic topic)
- (gnus-delete-line))
- ;; Remove from alist.
- (setq gnus-topic-alist (delq entry gnus-topic-alist))
- ;; Remove from topology.
- (gnus-topic-find-topology topic nil nil 'delete)))
-
-(defun gnus-topic-rename (old-name new-name)
- "Rename a topic."
- (interactive
- (let ((topic (gnus-group-parent-topic)))
- (list topic
- (read-string (format "Rename %s to: " topic)))))
- (let ((top (gnus-topic-find-topology old-name))
- (entry (assoc old-name gnus-topic-alist)))
- (when top
- (setcar (cadr top) new-name))
- (when entry
- (setcar entry new-name))
- (gnus-group-list-groups)))
-
-(defun gnus-topic-indent (&optional unindent)
- "Indent a topic -- make it a sub-topic of the previous topic.
-If UNINDENT, remove an indentation."
- (interactive "P")
- (if unindent
- (gnus-topic-unindent)
- (let* ((topic (gnus-group-parent-topic))
- (parent (gnus-topic-previous-topic topic)))
- (unless parent
- (error "Nothing to indent %s into" topic))
- (when topic
- (gnus-topic-goto-topic topic)
- (gnus-topic-kill-group)
- (gnus-topic-create-topic
- topic parent nil (cdr (pop gnus-topic-killed-topics)))
- (or (gnus-topic-goto-topic topic)
- (gnus-topic-goto-topic parent))))))
-
-(defun gnus-topic-unindent ()
- "Unindent a topic."
- (interactive)
- (let* ((topic (gnus-group-parent-topic))
- (parent (gnus-topic-parent-topic topic))
- (grandparent (gnus-topic-parent-topic parent)))
- (unless grandparent
- (error "Nothing to indent %s into" topic))
- (when topic
- (gnus-topic-goto-topic topic)
- (gnus-topic-kill-group)
- (gnus-topic-create-topic
- topic grandparent (gnus-topic-next-topic parent)
- (cdr (pop gnus-topic-killed-topics)))
- (gnus-topic-goto-topic topic))))
-
-(defun gnus-topic-list-active (&optional force)
- "List all groups that Gnus knows about in a topicsified fashion.
-If FORCE, always re-read the active file."
- (interactive "P")
- (when force
- (gnus-get-killed-groups))
- (gnus-topic-grok-active force)
- (let ((gnus-topic-topology gnus-topic-active-topology)
- (gnus-topic-alist gnus-topic-active-alist)
- gnus-killed-list gnus-zombie-list)
- (gnus-group-list-groups 9 nil 1)))
-
-(provide 'gnus-topic)
-
-;;; gnus-topic.el ends here
diff --git a/lisp/gnus-uu.el b/lisp/gnus-uu.el
deleted file mode 100644
index bd23e9edeba..00000000000
--- a/lisp/gnus-uu.el
+++ /dev/null
@@ -1,1951 +0,0 @@
-;;; gnus-uu.el --- extract (uu)encoded files in Gnus
-;; Copyright (C) 1985,86,87,93,94,95,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Created: 2 Oct 1993
-;; Keyword: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'gnus)
-(require 'gnus-msg)
-(eval-when-compile (require 'cl))
-
-;; Default viewing action rules
-
-(defvar gnus-uu-default-view-rules
- '(("\\.te?xt$\\|\\.doc$\\|read.*me\\|\\.c?$\\|\\.h$\\|\\.bat$\\|\\.asm$\\|makefile" "cat %s | sed s/\r//g")
- ("\\.pas$" "cat %s | sed s/\r//g")
- ("\\.[1-9]$" "groff -mandoc -Tascii %s | sed s/\b.//g")
- ("\\.\\(jpe?g\\|gif\\|tiff?\\|p[pgb]m\\|xwd\\|xbm\\|pcx\\)$" "xv")
- ("\\.tga$" "tgatoppm %s | xv -")
- ("\\.\\(wav\\|aiff\\|hcom\\|u[blw]\\|s[bfw]\\|voc\\|smp\\)$"
- "sox -v .5 %s -t .au -u - > /dev/audio")
- ("\\.au$" "cat %s > /dev/audio")
- ("\\.midi?$" "playmidi -f")
- ("\\.mod$" "str32")
- ("\\.ps$" "ghostview")
- ("\\.dvi$" "xdvi")
- ("\\.html$" "xmosaic")
- ("\\.mpe?g$" "mpeg_play")
- ("\\.\\(flc\\|fli\\|rle\\|iff\\|pfx\\|avi\\|sme\\|rpza\\|dl\\|qt\\|rsrc\\|mov\\)$" "xanim")
- ("\\.\\(tar\\|arj\\|zip\\|zoo\\|arc\\|gz\\|Z\\|lzh\\|ar\\|lha\\)$"
- "gnus-uu-archive"))
- "*Default actions to be taken when the user asks to view a file.
-To change the behaviour, you can either edit this variable or set
-`gnus-uu-user-view-rules' to something useful.
-
-For example:
-
-To make gnus-uu use 'xli' to display JPEG and GIF files, put the
-following in your .emacs file:
-
- (setq gnus-uu-user-view-rules '((\"jpg$\\\\|gif$\" \"xli\")))
-
-Both these variables are lists of lists with two string elements. The
-first string is a regular expression. If the file name matches this
-regular expression, the command in the second string is executed with
-the file as an argument.
-
-If the command string contains \"%s\", the file name will be inserted
-at that point in the command string. If there's no \"%s\" in the
-command string, the file name will be appended to the command string
-before executing.
-
-There are several user variables to tailor the behaviour of gnus-uu to
-your needs. First we have `gnus-uu-user-view-rules', which is the
-variable gnus-uu first consults when trying to decide how to view a
-file. If this variable contains no matches, gnus-uu examines the
-default rule variable provided in this package. If gnus-uu finds no
-match here, it uses `gnus-uu-user-view-rules-end' to try to make a
-match.")
-
-(defvar gnus-uu-user-view-rules nil
- "*Variable detailing what actions are to be taken to view a file.
-See the documentation on the `gnus-uu-default-view-rules' variable for
-details.")
-
-(defvar gnus-uu-user-view-rules-end
- '(("" "file"))
- "*Variable saying what actions are to be taken if no rule matched the file name.
-See the documentation on the `gnus-uu-default-view-rules' variable for
-details.")
-
-;; Default unpacking commands
-
-(defvar gnus-uu-default-archive-rules
- '(("\\.tar$" "tar xf")
- ("\\.zip$" "unzip -o")
- ("\\.ar$" "ar x")
- ("\\.arj$" "unarj x")
- ("\\.zoo$" "zoo -e")
- ("\\.\\(lzh\\|lha\\)$" "lha x")
- ("\\.Z$" "uncompress")
- ("\\.gz$" "gunzip")
- ("\\.arc$" "arc -x")))
-
-(defvar gnus-uu-destructive-archivers
- (list "uncompress" "gunzip"))
-
-(defvar gnus-uu-user-archive-rules nil
- "*A list that can be set to override the default archive unpacking commands.
-To use, for instance, 'untar' to unpack tar files and 'zip -x' to
-unpack zip files, say the following:
- (setq gnus-uu-user-archive-rules
- '((\"\\\\.tar$\" \"untar\")
- (\"\\\\.zip$\" \"zip -x\")))")
-
-(defvar gnus-uu-ignore-files-by-name nil
- "*A regular expression saying what files should not be viewed based on name.
-If, for instance, you want gnus-uu to ignore all .au and .wav files,
-you could say something like
-
- (setq gnus-uu-ignore-files-by-name \"\\\\.au$\\\\|\\\\.wav$\")
-
-Note that this variable can be used in conjunction with the
-`gnus-uu-ignore-files-by-type' variable.")
-
-(defvar gnus-uu-ignore-files-by-type nil
- "*A regular expression saying what files that shouldn't be viewed, based on MIME file type.
-If, for instance, you want gnus-uu to ignore all audio files and all mpegs,
-you could say something like
-
- (setq gnus-uu-ignore-files-by-type \"audio/\\\\|video/mpeg\")
-
-Note that this variable can be used in conjunction with the
-`gnus-uu-ignore-files-by-name' variable.")
-
-;; Pseudo-MIME support
-
-(defconst gnus-uu-ext-to-mime-list
- '(("\\.gif$" "image/gif")
- ("\\.jpe?g$" "image/jpeg")
- ("\\.tiff?$" "image/tiff")
- ("\\.xwd$" "image/xwd")
- ("\\.pbm$" "image/pbm")
- ("\\.pgm$" "image/pgm")
- ("\\.ppm$" "image/ppm")
- ("\\.xbm$" "image/xbm")
- ("\\.pcx$" "image/pcx")
- ("\\.tga$" "image/tga")
- ("\\.ps$" "image/postscript")
- ("\\.fli$" "video/fli")
- ("\\.wav$" "audio/wav")
- ("\\.aiff$" "audio/aiff")
- ("\\.hcom$" "audio/hcom")
- ("\\.voc$" "audio/voc")
- ("\\.smp$" "audio/smp")
- ("\\.mod$" "audio/mod")
- ("\\.dvi$" "image/dvi")
- ("\\.mpe?g$" "video/mpeg")
- ("\\.au$" "audio/basic")
- ("\\.\\(te?xt\\|doc\\|c\\|h\\)$" "text/plain")
- ("\\.\\(c\\|h\\)$" "text/source")
- ("read.*me" "text/plain")
- ("\\.html$" "text/html")
- ("\\.bat$" "text/bat")
- ("\\.[1-6]$" "text/man")
- ("\\.flc$" "video/flc")
- ("\\.rle$" "video/rle")
- ("\\.pfx$" "video/pfx")
- ("\\.avi$" "video/avi")
- ("\\.sme$" "video/sme")
- ("\\.rpza$" "video/prza")
- ("\\.dl$" "video/dl")
- ("\\.qt$" "video/qt")
- ("\\.rsrc$" "video/rsrc")
- ("\\..*$" "unknown/unknown")))
-
-;; Various variables users may set
-
-(defvar gnus-uu-tmp-dir "/tmp/"
- "*Variable saying where gnus-uu is to do its work.
-Default is \"/tmp/\".")
-
-(defvar gnus-uu-do-not-unpack-archives nil
- "*Non-nil means that gnus-uu won't peek inside archives looking for files to display.
-Default is nil.")
-
-(defvar gnus-uu-ignore-default-view-rules nil
- "*Non-nil means that gnus-uu will ignore the default viewing rules.
-Only the user viewing rules will be consulted. Default is nil.")
-
-(defvar gnus-uu-grabbed-file-functions nil
- "*Functions run on each file after successful decoding.
-They will be called with the name of the file as the argument.
-Likely functions you can use in this list are `gnus-uu-grab-view'
-and `gnus-uu-grab-move'.")
-
-(defvar gnus-uu-ignore-default-archive-rules nil
- "*Non-nil means that gnus-uu will ignore the default archive unpacking commands.
-Only the user unpacking commands will be consulted. Default is nil.")
-
-(defvar gnus-uu-kill-carriage-return t
- "*Non-nil means that gnus-uu will strip all carriage returns from articles.
-Default is t.")
-
-(defvar gnus-uu-view-with-metamail nil
- "*Non-nil means that files will be viewed with metamail.
-The gnus-uu viewing functions will be ignored and gnus-uu will try
-to guess at a content-type based on file name suffixes. Default
-it nil.")
-
-(defvar gnus-uu-unmark-articles-not-decoded nil
- "*Non-nil means that gnus-uu will mark articles that were unsuccessfully decoded as unread.
-Default is nil.")
-
-(defvar gnus-uu-correct-stripped-uucode nil
- "*Non-nil means that gnus-uu will *try* to fix uuencoded files that have had trailing spaces deleted.
-Default is nil.")
-
-(defvar gnus-uu-save-in-digest nil
- "*Non-nil means that gnus-uu, when asked to save without decoding, will save in digests.
-If this variable is nil, gnus-uu will just save everything in a
-file without any embellishments. The digesting almost conforms to RFC1153 -
-no easy way to specify any meaningful volume and issue numbers were found,
-so I simply dropped them.")
-
-(defvar gnus-uu-digest-headers
- '("^Date:" "^From:" "^To:" "^Cc:" "^Subject:" "^Message-ID:" "^Keywords:"
- "^Summary:" "^References:")
- "*List of regexps to match headers included in digested messages.
-The headers will be included in the sequence they are matched.")
-
-(defvar gnus-uu-save-separate-articles nil
- "*Non-nil means that gnus-uu will save articles in separate files.")
-
-;; Internal variables
-
-(defvar gnus-uu-saved-article-name nil)
-
-(defconst gnus-uu-begin-string "^begin[ \t]+[0-7][0-7][0-7][ \t]+\\(.*\\)$")
-(defconst gnus-uu-end-string "^end[ \t]*$")
-
-(defconst gnus-uu-body-line "^M")
-(let ((i 61))
- (while (> (setq i (1- i)) 0)
- (setq gnus-uu-body-line (concat gnus-uu-body-line "[^a-z]")))
- (setq gnus-uu-body-line (concat gnus-uu-body-line ".?$")))
-
-;"^M.............................................................?$"
-
-(defconst gnus-uu-shar-begin-string "^#! */bin/sh")
-
-(defvar gnus-uu-shar-file-name nil)
-(defconst gnus-uu-shar-name-marker "begin [0-7][0-7][0-7][ \t]+\\(\\(\\w\\|\\.\\)*\\b\\)")
-
-(defconst gnus-uu-postscript-begin-string "^%!PS-")
-(defconst gnus-uu-postscript-end-string "^%%EOF$")
-
-(defvar gnus-uu-file-name nil)
-(defconst gnus-uu-uudecode-process nil)
-(defvar gnus-uu-binhex-article-name nil)
-
-(defvar gnus-uu-work-dir nil)
-
-(defconst gnus-uu-output-buffer-name " *Gnus UU Output*")
-
-(defvar gnus-uu-default-dir gnus-article-save-directory)
-(defvar gnus-uu-digest-from-subject nil)
-
-;; Keymaps
-
-(gnus-define-keys
- (gnus-uu-mark-map "P" gnus-summary-mark-map)
- "p" gnus-summary-mark-as-processable
- "u" gnus-summary-unmark-as-processable
- "U" gnus-summary-unmark-all-processable
- "v" gnus-uu-mark-over
- "s" gnus-uu-mark-series
- "r" gnus-uu-mark-region
- "R" gnus-uu-mark-by-regexp
- "t" gnus-uu-mark-thread
- "T" gnus-uu-unmark-thread
- "a" gnus-uu-mark-all
- "b" gnus-uu-mark-buffer
- "S" gnus-uu-mark-sparse)
-
-(gnus-define-keys
- (gnus-uu-extract-map "X" gnus-summary-mode-map)
- ;;"x" gnus-uu-extract-any
- ;;"m" gnus-uu-extract-mime
- "u" gnus-uu-decode-uu
- "U" gnus-uu-decode-uu-and-save
- "s" gnus-uu-decode-unshar
- "S" gnus-uu-decode-unshar-and-save
- "o" gnus-uu-decode-save
- "O" gnus-uu-decode-save
- "b" gnus-uu-decode-binhex
- "B" gnus-uu-decode-binhex
- "p" gnus-uu-decode-postscript
- "P" gnus-uu-decode-postscript-and-save)
-
-(gnus-define-keys
- (gnus-uu-extract-view-map "v" gnus-uu-extract-map)
- "u" gnus-uu-decode-uu-view
- "U" gnus-uu-decode-uu-and-save-view
- "s" gnus-uu-decode-unshar-view
- "S" gnus-uu-decode-unshar-and-save-view
- "o" gnus-uu-decode-save-view
- "O" gnus-uu-decode-save-view
- "b" gnus-uu-decode-binhex-view
- "B" gnus-uu-decode-binhex-view
- "p" gnus-uu-decode-postscript-view
- "P" gnus-uu-decode-postscript-and-save-view)
-
-
-;; Commands.
-
-(defun gnus-uu-decode-uu (&optional n)
- "Uudecodes the current article."
- (interactive "P")
- (gnus-uu-decode-with-method 'gnus-uu-uustrip-article n))
-
-(defun gnus-uu-decode-uu-and-save (n dir)
- "Decodes and saves the resulting file."
- (interactive
- (list current-prefix-arg
- (file-name-as-directory
- (read-file-name "Uudecode and save in dir: "
- gnus-uu-default-dir
- gnus-uu-default-dir t))))
- (gnus-uu-decode-with-method 'gnus-uu-uustrip-article n dir nil nil t))
-
-(defun gnus-uu-decode-unshar (&optional n)
- "Unshars the current article."
- (interactive "P")
- (gnus-uu-decode-with-method 'gnus-uu-unshar-article n nil nil 'scan t))
-
-(defun gnus-uu-decode-unshar-and-save (n dir)
- "Unshars and saves the current article."
- (interactive
- (list current-prefix-arg
- (file-name-as-directory
- (read-file-name "Unshar and save in dir: "
- gnus-uu-default-dir
- gnus-uu-default-dir t))))
- (gnus-uu-decode-with-method 'gnus-uu-unshar-article n dir nil 'scan t))
-
-(defun gnus-uu-decode-save (n file)
- "Saves the current article."
- (interactive
- (list current-prefix-arg
- (read-file-name
- (if gnus-uu-save-separate-articles
- "Save articles is dir: "
- "Save articles in file: ")
- gnus-uu-default-dir
- gnus-uu-default-dir)))
- (setq gnus-uu-saved-article-name file)
- (gnus-uu-decode-with-method 'gnus-uu-save-article n nil t))
-
-(defun gnus-uu-decode-binhex (n dir)
- "Unbinhexes the current article."
- (interactive
- (list current-prefix-arg
- (file-name-as-directory
- (read-file-name "Unbinhex and save in dir: "
- gnus-uu-default-dir
- gnus-uu-default-dir))))
- (setq gnus-uu-binhex-article-name
- (make-temp-name (concat gnus-uu-work-dir "binhex")))
- (gnus-uu-decode-with-method 'gnus-uu-binhex-article n dir))
-
-(defun gnus-uu-decode-uu-view (&optional n)
- "Uudecodes and views the current article."
- (interactive "P")
- (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
- (gnus-uu-decode-uu n)))
-
-(defun gnus-uu-decode-uu-and-save-view (n dir)
- "Decodes, views and saves the resulting file."
- (interactive
- (list current-prefix-arg
- (read-file-name "Uudecode, view and save in dir: "
- gnus-uu-default-dir
- gnus-uu-default-dir t)))
- (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
- (gnus-uu-decode-uu-and-save n dir)))
-
-(defun gnus-uu-decode-unshar-view (&optional n)
- "Unshars and views the current article."
- (interactive "P")
- (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
- (gnus-uu-decode-unshar n)))
-
-(defun gnus-uu-decode-unshar-and-save-view (n dir)
- "Unshars and saves the current article."
- (interactive
- (list current-prefix-arg
- (read-file-name "Unshar, view and save in dir: "
- gnus-uu-default-dir
- gnus-uu-default-dir t)))
- (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
- (gnus-uu-decode-unshar-and-save n dir)))
-
-(defun gnus-uu-decode-save-view (n file)
- "Saves and views the current article."
- (interactive
- (list current-prefix-arg
- (read-file-name (if gnus-uu-save-separate-articles
- "Save articles is dir: "
- "Save articles in file: ")
- gnus-uu-default-dir gnus-uu-default-dir)))
- (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
- (gnus-uu-decode-save n file)))
-
-(defun gnus-uu-decode-binhex-view (n file)
- "Unbinhexes and views the current article."
- (interactive
- (list current-prefix-arg
- (read-file-name "Unbinhex, view and save in dir: "
- gnus-uu-default-dir gnus-uu-default-dir)))
- (setq gnus-uu-binhex-article-name
- (make-temp-name (concat gnus-uu-work-dir "binhex")))
- (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
- (gnus-uu-decode-binhex n file)))
-
-
-;; Digest and forward articles
-
-(defun gnus-uu-digest-mail-forward (&optional n post)
- "Digests and forwards all articles in this series."
- (interactive "P")
- (let ((gnus-uu-save-in-digest t)
- (file (make-temp-name (concat gnus-uu-tmp-dir "forward")))
- buf subject from)
- (setq gnus-uu-digest-from-subject nil)
- (gnus-uu-decode-save n file)
- (setq buf (switch-to-buffer (get-buffer-create " *gnus-uu-forward*")))
- (gnus-add-current-to-buffer-list)
- (erase-buffer)
- (delete-other-windows)
- (insert-file file)
- (let ((fs gnus-uu-digest-from-subject))
- (if (not fs)
- ()
- (setq from (caar fs)
- subject (gnus-simplify-subject-fuzzy (cdar fs))
- fs (cdr fs))
- (while (and fs (or from subject))
- (and from
- (or (string= from (caar fs))
- (setq from nil)))
- (and subject
- (or (string= (gnus-simplify-subject-fuzzy (cdar fs))
- subject)
- (setq subject nil)))
- (setq fs (cdr fs))))
- (or subject (setq subject "Digested Articles"))
- (or from (setq from "Various")))
- (goto-char (point-min))
- (and (re-search-forward "^Subject: ")
- (progn
- (delete-region (point) (gnus-point-at-eol))
- (insert subject)))
- (goto-char (point-min))
- (and (re-search-forward "^From: ")
- (progn
- (delete-region (point) (gnus-point-at-eol))
- (insert from)))
- (message-forward post)
- (delete-file file)
- (kill-buffer buf)
- (setq gnus-uu-digest-from-subject nil)))
-
-(defun gnus-uu-digest-post-forward (&optional n)
- "Digest and forward to a newsgroup."
- (interactive "P")
- (gnus-uu-digest-mail-forward n t))
-
-;; Process marking.
-
-(defun gnus-uu-mark-by-regexp (regexp &optional unmark)
- "Ask for a regular expression and set the process mark on all articles that match."
- (interactive (list (read-from-minibuffer "Mark (regexp): ")))
- (gnus-set-global-variables)
- (let ((articles (gnus-uu-find-articles-matching regexp)))
- (while articles
- (if unmark
- (gnus-summary-remove-process-mark (pop articles))
- (gnus-summary-set-process-mark (pop articles))))
- (message ""))
- (gnus-summary-position-point))
-
-(defun gnus-uu-unmark-by-regexp (regexp &optional unmark)
- "Ask for a regular expression and remove the process mark on all articles that match."
- (interactive (list (read-from-minibuffer "Mark (regexp): ")))
- (gnus-uu-mark-by-regexp regexp t))
-
-(defun gnus-uu-mark-series ()
- "Mark the current series with the process mark."
- (interactive)
- (gnus-set-global-variables)
- (let ((articles (gnus-uu-find-articles-matching)))
- (while articles
- (gnus-summary-set-process-mark (car articles))
- (setq articles (cdr articles)))
- (message ""))
- (gnus-summary-position-point))
-
-(defun gnus-uu-mark-region (beg end &optional unmark)
- "Set the process mark on all articles between point and mark."
- (interactive "r")
- (gnus-set-global-variables)
- (save-excursion
- (goto-char beg)
- (while (< (point) end)
- (if unmark
- (gnus-summary-remove-process-mark (gnus-summary-article-number))
- (gnus-summary-set-process-mark (gnus-summary-article-number)))
- (forward-line 1)))
- (gnus-summary-position-point))
-
-(defun gnus-uu-unmark-region (beg end)
- "Remove the process mark from all articles between point and mark."
- (interactive "r")
- (gnus-uu-mark-region beg end t))
-
-(defun gnus-uu-mark-buffer ()
- "Set the process mark on all articles in the buffer."
- (interactive)
- (gnus-uu-mark-region (point-min) (point-max)))
-
-(defun gnus-uu-unmark-buffer ()
- "Remove the process mark on all articles in the buffer."
- (interactive)
- (gnus-uu-mark-region (point-min) (point-max) t))
-
-(defun gnus-uu-mark-thread ()
- "Marks all articles downwards in this thread."
- (interactive)
- (gnus-set-global-variables)
- (let ((level (gnus-summary-thread-level)))
- (while (and (gnus-summary-set-process-mark (gnus-summary-article-number))
- (zerop (gnus-summary-next-subject 1))
- (> (gnus-summary-thread-level) level))))
- (gnus-summary-position-point))
-
-(defun gnus-uu-unmark-thread ()
- "Unmarks all articles downwards in this thread."
- (interactive)
- (gnus-set-global-variables)
- (let ((level (gnus-summary-thread-level)))
- (while (and (gnus-summary-remove-process-mark
- (gnus-summary-article-number))
- (zerop (gnus-summary-next-subject 1))
- (> (gnus-summary-thread-level) level))))
- (gnus-summary-position-point))
-
-(defun gnus-uu-mark-over (&optional score)
- "Mark all articles with a score over SCORE (the prefix.)"
- (interactive "P")
- (let ((score (gnus-score-default score))
- (data gnus-newsgroup-data))
- (save-excursion
- (while data
- (when (> (or (cdr (assq (gnus-data-number (caar data))
- gnus-newsgroup-scored))
- gnus-summary-default-score 0)
- score)
- (gnus-summary-set-process-mark (caar data)))
- (setq data (cdr data))))
- (gnus-summary-position-point)))
-
-(defun gnus-uu-mark-sparse ()
- "Mark all series that have some articles marked."
- (interactive)
- (gnus-set-global-variables)
- (let ((marked (nreverse gnus-newsgroup-processable))
- subject articles total headers)
- (or marked (error "No articles marked with the process mark"))
- (setq gnus-newsgroup-processable nil)
- (save-excursion
- (while marked
- (and (vectorp (setq headers
- (gnus-summary-article-header (car marked))))
- (setq subject (mail-header-subject headers)
- articles (gnus-uu-find-articles-matching
- (gnus-uu-reginize-string subject))
- total (nconc total articles)))
- (while articles
- (gnus-summary-set-process-mark (car articles))
- (setcdr marked (delq (car articles) (cdr marked)))
- (setq articles (cdr articles)))
- (setq marked (cdr marked)))
- (setq gnus-newsgroup-processable (nreverse total)))
- (gnus-summary-position-point)))
-
-(defun gnus-uu-mark-all ()
- "Mark all articles in \"series\" order."
- (interactive)
- (gnus-set-global-variables)
- (setq gnus-newsgroup-processable nil)
- (save-excursion
- (let ((data gnus-newsgroup-data)
- number)
- (while data
- (when (and (not (memq (setq number (gnus-data-number (car data)))
- gnus-newsgroup-processable))
- (vectorp (gnus-data-header (car data))))
- (gnus-summary-goto-subject number)
- (gnus-uu-mark-series))
- (setq data (cdr data)))))
- (gnus-summary-position-point))
-
-;; All PostScript functions written by Erik Selberg <speed@cs.washington.edu>.
-
-(defun gnus-uu-decode-postscript (&optional n)
- "Gets postscript of the current article."
- (interactive "P")
- (gnus-uu-decode-with-method 'gnus-uu-decode-postscript-article n))
-
-(defun gnus-uu-decode-postscript-view (&optional n)
- "Gets and views the current article."
- (interactive "P")
- (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
- (gnus-uu-decode-postscript n)))
-
-(defun gnus-uu-decode-postscript-and-save (n dir)
- "Extracts postscript and saves the current article."
- (interactive
- (list current-prefix-arg
- (file-name-as-directory
- (read-file-name "Save in dir: "
- gnus-uu-default-dir
- gnus-uu-default-dir t))))
- (gnus-uu-decode-with-method 'gnus-uu-decode-postscript-article
- n dir nil nil t))
-
-(defun gnus-uu-decode-postscript-and-save-view (n dir)
- "Decodes, views and saves the resulting file."
- (interactive
- (list current-prefix-arg
- (read-file-name "Where do you want to save the file(s)? "
- gnus-uu-default-dir
- gnus-uu-default-dir t)))
- (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
- (gnus-uu-decode-postscript-and-save n dir)))
-
-
-;; Internal functions.
-
-(defun gnus-uu-decode-with-method (method n &optional save not-insert
- scan cdir)
- (gnus-uu-initialize scan)
- (if save (setq gnus-uu-default-dir save))
- ;; Create the directory we save to.
- (when (and scan cdir save
- (not (file-exists-p save)))
- (make-directory save t))
- (let ((articles (gnus-uu-get-list-of-articles n))
- files)
- (setq files (gnus-uu-grab-articles articles method t))
- (let ((gnus-current-article (car articles)))
- (and scan (setq files (gnus-uu-scan-directory gnus-uu-work-dir))))
- (and save (gnus-uu-save-files files save))
- (if (eq gnus-uu-do-not-unpack-archives nil)
- (setq files (gnus-uu-unpack-files files)))
- (setq files (nreverse (gnus-uu-get-actions files)))
- (or not-insert (not gnus-insert-pseudo-articles)
- (gnus-summary-insert-pseudos files save))))
-
-(defun gnus-uu-scan-directory (dir &optional rec)
- "Return a list of all files under DIR."
- (let ((files (directory-files dir t))
- out file)
- (while (setq file (pop files))
- (unless (member (file-name-nondirectory file) '("." ".."))
- (push (list (cons 'name file)
- (cons 'article gnus-current-article))
- out)
- (when (file-directory-p file)
- (setq out (nconc (gnus-uu-scan-directory file t) out)))))
- (if rec
- out
- (nreverse out))))
-
-(defun gnus-uu-save-files (files dir)
- "Save FILES in DIR."
- (let ((len (length files))
- (reg (concat "^" (regexp-quote gnus-uu-work-dir)))
- to-file file fromdir)
- (while (setq file (cdr (assq 'name (pop files))))
- (when (file-exists-p file)
- (string-match reg file)
- (setq fromdir (substring file (match-end 0)))
- (if (file-directory-p file)
- (unless (file-exists-p (concat dir fromdir))
- (make-directory (concat dir fromdir) t))
- (setq to-file (concat dir fromdir))
- (when (or (not (file-exists-p to-file))
- (gnus-y-or-n-p (format "%s exists; overwrite? " to-file)))
- (copy-file file to-file t t)))))
- (gnus-message 5 "Saved %d file%s" len (if (= len 1) "" "s"))))
-
-;; Functions for saving and possibly digesting articles without
-;; any decoding.
-
-;; Function called by gnus-uu-grab-articles to treat each article.
-(defun gnus-uu-save-article (buffer in-state)
- (cond
- (gnus-uu-save-separate-articles
- (save-excursion
- (set-buffer buffer)
- (write-region 1 (point-max) (concat gnus-uu-saved-article-name
- gnus-current-article))
- (cond ((eq in-state 'first) (list gnus-uu-saved-article-name 'begin))
- ((eq in-state 'first-and-last) (list gnus-uu-saved-article-name
- 'begin 'end))
- ((eq in-state 'last) (list 'end))
- (t (list 'middle)))))
- ((not gnus-uu-save-in-digest)
- (save-excursion
- (set-buffer buffer)
- (write-region 1 (point-max) gnus-uu-saved-article-name t)
- (cond ((eq in-state 'first) (list gnus-uu-saved-article-name 'begin))
- ((eq in-state 'first-and-last) (list gnus-uu-saved-article-name
- 'begin 'end))
- ((eq in-state 'last) (list 'end))
- (t (list 'middle)))))
- (t
- (let ((header (gnus-summary-article-header)))
- (setq gnus-uu-digest-from-subject
- (cons (cons (mail-header-from header)
- (mail-header-subject header))
- gnus-uu-digest-from-subject)))
- (let ((name (file-name-nondirectory gnus-uu-saved-article-name))
- (delim (concat "^" (make-string 30 ?-) "$"))
- beg subj headers headline sorthead body end-string state)
- (if (or (eq in-state 'first)
- (eq in-state 'first-and-last))
- (progn
- (setq state (list 'begin))
- (save-excursion (set-buffer (get-buffer-create "*gnus-uu-body*"))
- (erase-buffer))
- (save-excursion
- (set-buffer (get-buffer-create "*gnus-uu-pre*"))
- (erase-buffer)
- (insert (format
- "Date: %s\nFrom: %s\nSubject: %s Digest\n\nTopics:\n"
- (current-time-string) name name))))
- (if (not (eq in-state 'end))
- (setq state (list 'middle))))
- (save-excursion
- (set-buffer (get-buffer "*gnus-uu-body*"))
- (goto-char (setq beg (point-max)))
- (save-excursion
- (save-restriction
- (set-buffer buffer)
- (let (buffer-read-only)
- (gnus-set-text-properties (point-min) (point-max) nil)
- ;; These two are necessary for XEmacs 19.12 fascism.
- (put-text-property (point-min) (point-max) 'invisible nil)
- (put-text-property (point-min) (point-max) 'intangible nil))
- (goto-char (point-min))
- (re-search-forward "\n\n")
- ;; Quote all 30-dash lines.
- (save-excursion
- (while (re-search-forward delim nil t)
- (beginning-of-line)
- (delete-char 1)
- (insert " ")))
- (setq body (buffer-substring (1- (point)) (point-max)))
- (narrow-to-region (point-min) (point))
- (if (not (setq headers gnus-uu-digest-headers))
- (setq sorthead (buffer-substring (point-min) (point-max)))
- (while headers
- (setq headline (car headers))
- (setq headers (cdr headers))
- (goto-char (point-min))
- (while (re-search-forward headline nil t)
- (setq sorthead
- (concat sorthead
- (buffer-substring
- (match-beginning 0)
- (or (and (re-search-forward "^[^ \t]" nil t)
- (1- (point)))
- (progn (forward-line 1) (point)))))))))
- (widen)))
- (insert sorthead) (goto-char (point-max))
- (insert body) (goto-char (point-max))
- (insert (concat "\n" (make-string 30 ?-) "\n\n"))
- (goto-char beg)
- (if (re-search-forward "^Subject: \\(.*\\)$" nil t)
- (progn
- (setq subj (buffer-substring (match-beginning 1) (match-end 1)))
- (save-excursion
- (set-buffer (get-buffer "*gnus-uu-pre*"))
- (insert (format " %s\n" subj))))))
- (if (or (eq in-state 'last)
- (eq in-state 'first-and-last))
- (progn
- (save-excursion
- (set-buffer (get-buffer "*gnus-uu-pre*"))
- (insert (format "\n\n%s\n\n" (make-string 70 ?-)))
- (write-region 1 (point-max) gnus-uu-saved-article-name))
- (save-excursion
- (set-buffer (get-buffer "*gnus-uu-body*"))
- (goto-char (point-max))
- (insert
- (concat (setq end-string (format "End of %s Digest" name))
- "\n"))
- (insert (concat (make-string (length end-string) ?*) "\n"))
- (write-region 1 (point-max) gnus-uu-saved-article-name t))
- (kill-buffer (get-buffer "*gnus-uu-pre*"))
- (kill-buffer (get-buffer "*gnus-uu-body*"))
- (setq state (cons 'end state))))
- (if (memq 'begin state)
- (cons gnus-uu-saved-article-name state)
- state)))))
-
-;; Binhex treatment - not very advanced.
-
-(defconst gnus-uu-binhex-body-line
- "^[^:]...............................................................$")
-(defconst gnus-uu-binhex-begin-line
- "^:...............................................................$")
-(defconst gnus-uu-binhex-end-line
- ":$")
-
-(defun gnus-uu-binhex-article (buffer in-state)
- (let (state start-char)
- (save-excursion
- (set-buffer buffer)
- (widen)
- (goto-char (point-min))
- (if (not (re-search-forward gnus-uu-binhex-begin-line nil t))
- (if (not (re-search-forward gnus-uu-binhex-body-line nil t))
- (setq state (list 'wrong-type))))
-
- (if (memq 'wrong-type state)
- ()
- (beginning-of-line)
- (setq start-char (point))
- (if (looking-at gnus-uu-binhex-begin-line)
- (progn
- (setq state (list 'begin))
- (write-region 1 1 gnus-uu-binhex-article-name))
- (setq state (list 'middle)))
- (goto-char (point-max))
- (re-search-backward (concat gnus-uu-binhex-body-line "\\|"
- gnus-uu-binhex-end-line) nil t)
- (if (looking-at gnus-uu-binhex-end-line)
- (setq state (if (memq 'begin state)
- (cons 'end state)
- (list 'end))))
- (beginning-of-line)
- (forward-line 1)
- (if (file-exists-p gnus-uu-binhex-article-name)
- (append-to-file start-char (point) gnus-uu-binhex-article-name))))
- (if (memq 'begin state)
- (cons gnus-uu-binhex-article-name state)
- state)))
-
-;; PostScript
-
-(defun gnus-uu-decode-postscript-article (process-buffer in-state)
- (let ((state (list 'ok))
- start-char end-char file-name)
- (save-excursion
- (set-buffer process-buffer)
- (goto-char (point-min))
- (if (not (re-search-forward gnus-uu-postscript-begin-string nil t))
- (setq state (list 'wrong-type))
- (beginning-of-line)
- (setq start-char (point))
- (if (not (re-search-forward gnus-uu-postscript-end-string nil t))
- (setq state (list 'wrong-type))
- (setq end-char (point))
- (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
- (insert-buffer-substring process-buffer start-char end-char)
- (setq file-name (concat gnus-uu-work-dir
- (cdr gnus-article-current) ".ps"))
- (write-region (point-min) (point-max) file-name)
- (setq state (list file-name 'begin 'end)))))
- state))
-
-
-;; Find actions.
-
-(defun gnus-uu-get-actions (files)
- (let ((ofiles files)
- action name)
- (while files
- (setq name (cdr (assq 'name (car files))))
- (and
- (setq action (gnus-uu-get-action name))
- (setcar files (nconc (list (if (string= action "gnus-uu-archive")
- (cons 'action "file")
- (cons 'action action))
- (cons 'execute (gnus-uu-command
- action name)))
- (car files))))
- (setq files (cdr files)))
- ofiles))
-
-(defun gnus-uu-get-action (file-name)
- (let (action)
- (setq action
- (gnus-uu-choose-action
- file-name
- (append
- gnus-uu-user-view-rules
- (if gnus-uu-ignore-default-view-rules
- nil
- gnus-uu-default-view-rules)
- gnus-uu-user-view-rules-end)))
- (if (and (not (string= (or action "") "gnus-uu-archive"))
- gnus-uu-view-with-metamail)
- (if (setq action
- (gnus-uu-choose-action file-name gnus-uu-ext-to-mime-list))
- (setq action (format "metamail -d -b -c \"%s\"" action))))
- action))
-
-
-;; Functions for treating subjects and collecting series.
-
-(defun gnus-uu-reginize-string (string)
- ;; Takes a string and puts a \ in front of every special character;
- ;; ignores any leading "version numbers" thingies that they use in
- ;; the comp.binaries groups, and either replaces anything that looks
- ;; like "2/3" with "[0-9]+/[0-9]+" or, if it can't find something
- ;; like that, replaces the last two numbers with "[0-9]+". This, in
- ;; my experience, should get most postings of a series.
- (let ((count 2)
- (vernum "v[0-9]+[a-z][0-9]+:")
- beg)
- (save-excursion
- (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert (regexp-quote string))
- (setq beg 1)
-
- (setq case-fold-search nil)
- (goto-char (point-min))
- (if (looking-at vernum)
- (progn
- (replace-match vernum t t)
- (setq beg (length vernum))))
-
- (goto-char beg)
- (if (re-search-forward "[ \t]*[0-9]+/[0-9]+" nil t)
- (replace-match " [0-9]+/[0-9]+")
-
- (goto-char beg)
- (if (re-search-forward "[0-9]+[ \t]*of[ \t]*[0-9]+" nil t)
- (replace-match "[0-9]+ of [0-9]+")
-
- (end-of-line)
- (while (and (re-search-backward "[0-9]" nil t) (> count 0))
- (while (and
- (looking-at "[0-9]")
- (< 1 (goto-char (1- (point))))))
- (re-search-forward "[0-9]+" nil t)
- (replace-match "[0-9]+")
- (backward-char 5)
- (setq count (1- count)))))
-
- (goto-char beg)
- (while (re-search-forward "[ \t]+" nil t)
- (replace-match "[ \t]*" t t))
-
- (buffer-substring 1 (point-max)))))
-
-(defun gnus-uu-get-list-of-articles (n)
- ;; If N is non-nil, the article numbers of the N next articles
- ;; will be returned.
- ;; If any articles have been marked as processable, they will be
- ;; returned.
- ;; Failing that, articles that have subjects that are part of the
- ;; same "series" as the current will be returned.
- (let (articles)
- (cond
- (n
- (let ((backward (< n 0))
- (n (abs n)))
- (save-excursion
- (while (and (> n 0)
- (setq articles (cons (gnus-summary-article-number)
- articles))
- (gnus-summary-search-forward nil nil backward))
- (setq n (1- n))))
- (nreverse articles)))
- (gnus-newsgroup-processable
- (reverse gnus-newsgroup-processable))
- (t
- (gnus-uu-find-articles-matching)))))
-
-(defun gnus-uu-string< (l1 l2)
- (string< (car l1) (car l2)))
-
-(defun gnus-uu-find-articles-matching
- (&optional subject only-unread do-not-translate)
- ;; Finds all articles that matches the regexp SUBJECT. If it is
- ;; nil, the current article name will be used. If ONLY-UNREAD is
- ;; non-nil, only unread articles are chosen. If DO-NOT-TRANSLATE is
- ;; non-nil, article names are not equalized before sorting.
- (let ((subject (or subject
- (gnus-uu-reginize-string (gnus-summary-article-subject))))
- list-of-subjects)
- (save-excursion
- (if (not subject)
- ()
- ;; Collect all subjects matching subject.
- (let ((case-fold-search t)
- (data gnus-newsgroup-data)
- subj mark d)
- (while data
- (setq d (pop data))
- (and (not (gnus-data-pseudo-p d))
- (or (not only-unread)
- (= (setq mark (gnus-data-mark d))
- gnus-unread-mark)
- (= mark gnus-ticked-mark)
- (= mark gnus-dormant-mark))
- (setq subj (mail-header-subject (gnus-data-header d)))
- (string-match subject subj)
- (setq list-of-subjects
- (cons (cons subj (gnus-data-number d))
- list-of-subjects)))))
-
- ;; Expand numbers, sort, and return the list of article
- ;; numbers.
- (mapcar (lambda (sub) (cdr sub))
- (sort (gnus-uu-expand-numbers
- list-of-subjects
- (not do-not-translate))
- 'gnus-uu-string<))))))
-
-(defun gnus-uu-expand-numbers (string-list &optional translate)
- ;; Takes a list of strings and "expands" all numbers in all the
- ;; strings. That is, this function makes all numbers equal length by
- ;; prepending lots of zeroes before each number. This is to ease later
- ;; sorting to find out what sequence the articles are supposed to be
- ;; decoded in. Returns the list of expanded strings.
- (let ((out-list string-list)
- string)
- (save-excursion
- (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
- (buffer-disable-undo (current-buffer))
- (while string-list
- (erase-buffer)
- (insert (caar string-list))
- ;; Translate multiple spaces to one space.
- (goto-char (point-min))
- (while (re-search-forward "[ \t]+" nil t)
- (replace-match " "))
- ;; Translate all characters to "a".
- (goto-char (point-min))
- (if translate
- (while (re-search-forward "[A-Za-z]" nil t)
- (replace-match "a" t t)))
- ;; Expand numbers.
- (goto-char (point-min))
- (while (re-search-forward "[0-9]+" nil t)
- (replace-match
- (format "%06d"
- (string-to-int (buffer-substring
- (match-beginning 0) (match-end 0))))))
- (setq string (buffer-substring 1 (point-max)))
- (setcar (car string-list) string)
- (setq string-list (cdr string-list))))
- out-list))
-
-
-;; `gnus-uu-grab-articles' is the general multi-article treatment
-;; function. It takes a list of articles to be grabbed and a function
-;; to apply to each article.
-;;
-;; The function to be called should take two parameters. The first
-;; parameter is the article buffer. The function should leave the
-;; result, if any, in this buffer. Most treatment functions will just
-;; generate files...
-;;
-;; The second parameter is the state of the list of articles, and can
-;; have four values: `first', `middle', `last' and `first-and-last'.
-;;
-;; The function should return a list. The list may contain the
-;; following symbols:
-;; `error' if an error occurred
-;; `begin' if the beginning of an encoded file has been received
-;; If the list returned contains a `begin', the first element of
-;; the list *must* be a string with the file name of the decoded
-;; file.
-;; `end' if the the end of an encoded file has been received
-;; `middle' if the article was a body part of an encoded file
-;; `wrong-type' if the article was not a part of an encoded file
-;; `ok', which can be used everything is ok
-
-(defvar gnus-uu-has-been-grabbed nil)
-
-(defun gnus-uu-unmark-list-of-grabbed (&optional dont-unmark-last-article)
- (let (art)
- (if (not (and gnus-uu-has-been-grabbed
- gnus-uu-unmark-articles-not-decoded))
- ()
- (if dont-unmark-last-article
- (progn
- (setq art (car gnus-uu-has-been-grabbed))
- (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed))))
- (while gnus-uu-has-been-grabbed
- (gnus-summary-tick-article (car gnus-uu-has-been-grabbed) t)
- (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed)))
- (if dont-unmark-last-article
- (setq gnus-uu-has-been-grabbed (list art))))))
-
-;; This function takes a list of articles and a function to apply to
-;; each article grabbed.
-;;
-;; This function returns a list of files decoded if the grabbing and
-;; the process-function has been successful and nil otherwise.
-(defun gnus-uu-grab-articles (articles process-function
- &optional sloppy limit no-errors)
- (let ((state 'first)
- has-been-begin article result-file result-files process-state
- gnus-summary-display-article-function
- gnus-article-display-hook gnus-article-prepare-hook
- article-series files)
-
- (while (and articles
- (not (memq 'error process-state))
- (or sloppy
- (not (memq 'end process-state))))
-
- (setq article (pop articles))
- (push article article-series)
-
- (unless articles
- (if (eq state 'first)
- (setq state 'first-and-last)
- (setq state 'last)))
-
- (let ((part (gnus-uu-part-number article)))
- (gnus-message 6 "Getting article %d%s..."
- article (if (string= part "") "" (concat ", " part))))
- (gnus-summary-display-article article)
-
- ;; Push the article to the processing function.
- (save-excursion
- (set-buffer gnus-original-article-buffer)
- (let ((buffer-read-only nil))
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (setq process-state
- (funcall process-function
- gnus-original-article-buffer state)))))
-
- (gnus-summary-remove-process-mark article)
-
- ;; If this is the beginning of a decoded file, we push it
- ;; on to a list.
- (when (or (memq 'begin process-state)
- (and (or (eq state 'first)
- (eq state 'first-and-last))
- (memq 'ok process-state)))
- (if has-been-begin
- ;; If there is a `result-file' here, that means that the
- ;; file was unsuccessfully decoded, so we delete it.
- (when (and result-file
- (file-exists-p result-file))
- (delete-file result-file)))
- (when (memq 'begin process-state)
- (setq result-file (car process-state)))
- (setq has-been-begin t))
-
- ;; Check whether we have decoded one complete file.
- (when (memq 'end process-state)
- (setq article-series nil)
- (setq has-been-begin nil)
- (if (stringp result-file)
- (setq files (list result-file))
- (setq files result-file))
- (setq result-file (car files))
- (while files
- (push (list (cons 'name (pop files))
- (cons 'article article))
- result-files))
- ;; Allow user-defined functions to be run on this file.
- (when gnus-uu-grabbed-file-functions
- (let ((funcs gnus-uu-grabbed-file-functions))
- (unless (listp funcs)
- (setq funcs (list funcs)))
- (while funcs
- (funcall (pop funcs) result-file))))
- ;; Check whether we have decoded enough articles.
- (and limit (= (length result-files) limit)
- (setq articles nil)))
-
- ;; If this is the last article to be decoded, and
- ;; we still haven't reached the end, then we delete
- ;; the partially decoded file.
- (and (or (eq state 'last) (eq state 'first-and-last))
- (not (memq 'end process-state))
- result-file
- (file-exists-p result-file)
- (delete-file result-file))
-
- ;; If this was a file of the wrong sort, then
- (when (and (or (memq 'wrong-type process-state)
- (memq 'error process-state))
- gnus-uu-unmark-articles-not-decoded)
- (gnus-summary-tick-article article t))
-
- ;; Set the new series state.
- (if (and (not has-been-begin)
- (not sloppy)
- (or (memq 'end process-state)
- (memq 'middle process-state)))
- (progn
- (setq process-state (list 'error))
- (gnus-message 2 "No begin part at the beginning")
- (sleep-for 2))
- (setq state 'middle)))
-
- ;; When there are no result-files, then something must be wrong.
- (if result-files
- (message "")
- (cond
- ((not has-been-begin)
- (gnus-message 2 "Wrong type file"))
- ((memq 'error process-state)
- (gnus-message 2 "An error occurred during decoding"))
- ((not (or (memq 'ok process-state)
- (memq 'end process-state)))
- (gnus-message 2 "End of articles reached before end of file")))
- ;; Make unsuccessfully decoded articles unread.
- (when gnus-uu-unmark-articles-not-decoded
- (while article-series
- (gnus-summary-tick-article (pop article-series) t))))
-
- result-files))
-
-(defun gnus-uu-grab-view (file)
- "View FILE using the gnus-uu methods."
- (let ((action (gnus-uu-get-action file)))
- (gnus-execute-command
- (if (string-match "%" action)
- (format action file)
- (concat action " " file))
- (eq gnus-view-pseudos 'not-confirm))))
-
-(defun gnus-uu-grab-move (file)
- "Move FILE to somewhere."
- (when gnus-uu-default-dir
- (let ((to-file (concat (file-name-as-directory gnus-uu-default-dir)
- (file-name-nondirectory file))))
- (rename-file file to-file)
- (unless (file-exists-p file)
- (make-symbolic-link to-file file)))))
-
-(defun gnus-uu-part-number (article)
- (let* ((header (gnus-summary-article-header article))
- (subject (and header (mail-header-subject header))))
- (if (and subject
- (string-match "[0-9]+ */[0-9]+\\|[0-9]+ * of *[0-9]+" subject))
- (match-string 0 subject)
- "")))
-
-(defun gnus-uu-uudecode-sentinel (process event)
- (delete-process (get-process process)))
-
-(defun gnus-uu-uustrip-article (process-buffer in-state)
- ;; Uudecodes a file asynchronously.
- (save-excursion
- (set-buffer process-buffer)
- (let ((state (list 'wrong-type))
- process-connection-type case-fold-search buffer-read-only
- files start-char)
- (goto-char (point-min))
-
- ;; Deal with ^M at the end of the lines.
- (when gnus-uu-kill-carriage-return
- (save-excursion
- (while (search-forward "\r" nil t)
- (delete-backward-char 1))))
-
- (while (or (re-search-forward gnus-uu-begin-string nil t)
- (re-search-forward gnus-uu-body-line nil t))
- (setq state (list 'ok))
- ;; Ok, we are at the first uucoded line.
- (beginning-of-line)
- (setq start-char (point))
-
- (if (not (looking-at gnus-uu-begin-string))
- (setq state (list 'middle))
- ;; This is the beginning of an uuencoded article.
- ;; We replace certain characters that could make things messy.
- (setq gnus-uu-file-name
- (let ((nnheader-file-name-translation-alist
- '((?/ . ?,) (? . ?_) (?* . ?_) (?$ . ?_))))
- (nnheader-translate-file-chars (match-string 1))))
-
- ;; Remove any non gnus-uu-body-line right after start.
- (forward-line 1)
- (while (and (not (eobp))
- (not (looking-at gnus-uu-body-line)))
- (gnus-delete-line))
-
- ;; If a process is running, we kill it.
- (when (and gnus-uu-uudecode-process
- (memq (process-status gnus-uu-uudecode-process)
- '(run stop)))
- (delete-process gnus-uu-uudecode-process)
- (gnus-uu-unmark-list-of-grabbed t))
-
- ;; Start a new uudecoding process.
- (setq gnus-uu-uudecode-process
- (start-process
- "*uudecode*"
- (get-buffer-create gnus-uu-output-buffer-name)
- shell-file-name shell-command-switch
- (format "cd %s ; uudecode" gnus-uu-work-dir)))
- (set-process-sentinel
- gnus-uu-uudecode-process 'gnus-uu-uudecode-sentinel)
- (setq state (list 'begin))
- (push (concat gnus-uu-work-dir gnus-uu-file-name) files))
-
- ;; We look for the end of the thing to be decoded.
- (if (re-search-forward gnus-uu-end-string nil t)
- (setq state (cons 'end state))
- (goto-char (point-max))
- (re-search-backward gnus-uu-body-line nil t))
-
- (forward-line 1)
-
- (when gnus-uu-uudecode-process
- (when (memq (process-status gnus-uu-uudecode-process) '(run stop))
- ;; Try to correct mishandled uucode.
- (when gnus-uu-correct-stripped-uucode
- (gnus-uu-check-correct-stripped-uucode start-char (point)))
-
- ;; Send the text to the process.
- (condition-case nil
- (process-send-region
- gnus-uu-uudecode-process start-char (point))
- (error
- (progn
- (delete-process gnus-uu-uudecode-process)
- (gnus-message 2 "gnus-uu: Couldn't uudecode")
- (setq state (list 'wrong-type)))))
-
- (if (memq 'end state)
- (progn
- ;; Send an EOF, just in case.
- (condition-case ()
- (process-send-eof gnus-uu-uudecode-process)
- (error nil))
- (while (memq (process-status gnus-uu-uudecode-process)
- '(open run))
- (accept-process-output gnus-uu-uudecode-process 1)))
- (when (or (not gnus-uu-uudecode-process)
- (not (memq (process-status gnus-uu-uudecode-process)
- '(run stop))))
- (setq state (list 'wrong-type)))))))
-
- (if (memq 'begin state)
- (cons (if (= (length files) 1) (car files) files) state)
- state))))
-
-;; This function is used by `gnus-uu-grab-articles' to treat
-;; a shared article.
-(defun gnus-uu-unshar-article (process-buffer in-state)
- (let ((state (list 'ok))
- start-char)
- (save-excursion
- (set-buffer process-buffer)
- (goto-char (point-min))
- (if (not (re-search-forward gnus-uu-shar-begin-string nil t))
- (setq state (list 'wrong-type))
- (beginning-of-line)
- (setq start-char (point))
- (call-process-region
- start-char (point-max) shell-file-name nil
- (get-buffer-create gnus-uu-output-buffer-name) nil
- shell-command-switch (concat "cd " gnus-uu-work-dir " ; sh"))))
- state))
-
-;; Returns the name of what the shar file is going to unpack.
-(defun gnus-uu-find-name-in-shar ()
- (let ((oldpoint (point))
- res)
- (goto-char (point-min))
- (if (re-search-forward gnus-uu-shar-name-marker nil t)
- (setq res (buffer-substring (match-beginning 1) (match-end 1))))
- (goto-char oldpoint)
- res))
-
-;; `gnus-uu-choose-action' chooses what action to perform given the name
-;; and `gnus-uu-file-action-list'. Returns either nil if no action is
-;; found, or the name of the command to run if such a rule is found.
-(defun gnus-uu-choose-action (file-name file-action-list &optional no-ignore)
- (let ((action-list (copy-sequence file-action-list))
- (case-fold-search t)
- rule action)
- (and
- (or no-ignore
- (and (not
- (and gnus-uu-ignore-files-by-name
- (string-match gnus-uu-ignore-files-by-name file-name)))
- (not
- (and gnus-uu-ignore-files-by-type
- (string-match gnus-uu-ignore-files-by-type
- (or (gnus-uu-choose-action
- file-name gnus-uu-ext-to-mime-list t)
- ""))))))
- (while (not (or (eq action-list ()) action))
- (setq rule (car action-list))
- (setq action-list (cdr action-list))
- (if (string-match (car rule) file-name)
- (setq action (cadr rule)))))
- action))
-
-(defun gnus-uu-treat-archive (file-path)
- ;; Unpacks an archive. Returns t if unpacking is successful.
- (let ((did-unpack t)
- action command dir)
- (setq action (gnus-uu-choose-action
- file-path (append gnus-uu-user-archive-rules
- (if gnus-uu-ignore-default-archive-rules
- nil
- gnus-uu-default-archive-rules))))
-
- (if (not action) (error "No unpackers for the file %s" file-path))
-
- (string-match "/[^/]*$" file-path)
- (setq dir (substring file-path 0 (match-beginning 0)))
-
- (if (member action gnus-uu-destructive-archivers)
- (copy-file file-path (concat file-path "~") t))
-
- (setq command (format "cd %s ; %s" dir (gnus-uu-command action file-path)))
-
- (save-excursion
- (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
- (erase-buffer))
-
- (gnus-message 5 "Unpacking: %s..." (gnus-uu-command action file-path))
-
- (if (= 0 (call-process shell-file-name nil
- (get-buffer-create gnus-uu-output-buffer-name)
- nil shell-command-switch command))
- (message "")
- (gnus-message 2 "Error during unpacking of archive")
- (setq did-unpack nil))
-
- (if (member action gnus-uu-destructive-archivers)
- (rename-file (concat file-path "~") file-path t))
-
- did-unpack))
-
-(defun gnus-uu-dir-files (dir)
- (let ((dirs (directory-files dir t "[^/][^\\.][^\\.]?$"))
- files file)
- (while dirs
- (if (file-directory-p (setq file (car dirs)))
- (setq files (append files (gnus-uu-dir-files file)))
- (setq files (cons file files)))
- (setq dirs (cdr dirs)))
- files))
-
-(defun gnus-uu-unpack-files (files &optional ignore)
- ;; Go through FILES and look for files to unpack.
- (let* ((totfiles (gnus-uu-ls-r gnus-uu-work-dir))
- (ofiles files)
- file did-unpack)
- (while files
- (setq file (cdr (assq 'name (car files))))
- (if (and (not (member file ignore))
- (equal (gnus-uu-get-action (file-name-nondirectory file))
- "gnus-uu-archive"))
- (progn
- (setq did-unpack (cons file did-unpack))
- (or (gnus-uu-treat-archive file)
- (gnus-message 2 "Error during unpacking of %s" file))
- (let* ((newfiles (gnus-uu-ls-r gnus-uu-work-dir))
- (nfiles newfiles))
- (while nfiles
- (or (member (car nfiles) totfiles)
- (setq ofiles (cons (list (cons 'name (car nfiles))
- (cons 'original file))
- ofiles)))
- (setq nfiles (cdr nfiles)))
- (setq totfiles newfiles))))
- (setq files (cdr files)))
- (if did-unpack
- (gnus-uu-unpack-files ofiles (append did-unpack ignore))
- ofiles)))
-
-(defun gnus-uu-ls-r (dir)
- (let* ((files (gnus-uu-directory-files dir t))
- (ofiles files))
- (while files
- (if (file-directory-p (car files))
- (progn
- (setq ofiles (delete (car files) ofiles))
- (setq ofiles (append ofiles (gnus-uu-ls-r (car files))))))
- (setq files (cdr files)))
- ofiles))
-
-;; Various stuff
-
-(defun gnus-uu-directory-files (dir &optional full)
- (let (files out file)
- (setq files (directory-files dir full))
- (while files
- (setq file (car files))
- (setq files (cdr files))
- (or (member (file-name-nondirectory file) '("." ".."))
- (setq out (cons file out))))
- (setq out (nreverse out))
- out))
-
-(defun gnus-uu-check-correct-stripped-uucode (start end)
- (save-excursion
- (let (found beg length)
- (if (not gnus-uu-correct-stripped-uucode)
- ()
- (goto-char start)
-
- (if (re-search-forward " \\|`" end t)
- (progn
- (goto-char start)
- (while (not (eobp))
- (progn
- (if (looking-at "\n") (replace-match ""))
- (forward-line 1))))
-
- (while (not (eobp))
- (if (looking-at (concat gnus-uu-begin-string "\\|"
- gnus-uu-end-string))
- ()
- (if (not found)
- (progn
- (beginning-of-line)
- (setq beg (point))
- (end-of-line)
- (setq length (- (point) beg))))
- (setq found t)
- (beginning-of-line)
- (setq beg (point))
- (end-of-line)
- (if (not (= length (- (point) beg)))
- (insert (make-string (- length (- (point) beg)) ? ))))
- (forward-line 1)))))))
-
-(defvar gnus-uu-tmp-alist nil)
-
-(defun gnus-uu-initialize (&optional scan)
- (let (entry)
- (if (and (not scan)
- (if (setq entry (assoc gnus-newsgroup-name gnus-uu-tmp-alist))
- (if (file-exists-p (cdr entry))
- (setq gnus-uu-work-dir (cdr entry))
- (setq gnus-uu-tmp-alist (delq entry gnus-uu-tmp-alist))
- nil)))
- t
- (setq gnus-uu-tmp-dir (file-name-as-directory
- (expand-file-name gnus-uu-tmp-dir)))
- (if (not (file-directory-p gnus-uu-tmp-dir))
- (error "Temp directory %s doesn't exist" gnus-uu-tmp-dir)
- (if (not (file-writable-p gnus-uu-tmp-dir))
- (error "Temp directory %s can't be written to"
- gnus-uu-tmp-dir)))
-
- (setq gnus-uu-work-dir
- (make-temp-name (concat gnus-uu-tmp-dir "gnus")))
- (if (not (file-directory-p gnus-uu-work-dir))
- (gnus-make-directory gnus-uu-work-dir))
- (set-file-modes gnus-uu-work-dir 448)
- (setq gnus-uu-work-dir (file-name-as-directory gnus-uu-work-dir))
- (setq gnus-uu-tmp-alist (cons (cons gnus-newsgroup-name gnus-uu-work-dir)
- gnus-uu-tmp-alist)))))
-
-
-;; Kills the temporary uu buffers, kills any processes, etc.
-(defun gnus-uu-clean-up ()
- (let (buf pst)
- (and gnus-uu-uudecode-process
- (memq (process-status (or gnus-uu-uudecode-process "nevair"))
- '(stop run))
- (delete-process gnus-uu-uudecode-process))
- (and (setq buf (get-buffer gnus-uu-output-buffer-name))
- (kill-buffer buf))))
-
-;; Inputs an action and a file and returns a full command, putting
-;; quotes round the file name and escaping any quotes in the file name.
-(defun gnus-uu-command (action file)
- (let ((ofile ""))
- (while (string-match "!\\|`\\|\"\\|\\$\\|\\\\\\|&" file)
- (progn
- (setq ofile
- (concat ofile (substring file 0 (match-beginning 0)) "\\"
- (substring file (match-beginning 0) (match-end 0))))
- (setq file (substring file (1+ (match-beginning 0))))))
- (setq ofile (concat "\"" ofile file "\""))
- (if (string-match "%s" action)
- (format action ofile)
- (concat action " " ofile))))
-
-(defun gnus-uu-delete-work-dir (&optional dir)
- "Delete recursively all files and directories under `gnus-uu-work-dir'."
- (if dir
- (gnus-message 7 "Deleting directory %s..." dir)
- (setq dir gnus-uu-work-dir))
- (when (and dir
- (file-exists-p dir))
- (let ((files (directory-files dir t nil t))
- file)
- (while (setq file (pop files))
- (unless (member (file-name-nondirectory file) '("." ".."))
- (if (file-directory-p file)
- (gnus-uu-delete-work-dir file)
- (gnus-message 9 "Deleting file %s..." file)
- (delete-file file))))
- (delete-directory dir)))
- (gnus-message 7 ""))
-
-;; Initializing
-
-(add-hook 'gnus-exit-group-hook 'gnus-uu-clean-up)
-(add-hook 'gnus-exit-group-hook 'gnus-uu-delete-work-dir)
-
-
-
-;;;
-;;; uuencoded posting
-;;;
-
-;; Any function that is to be used as and encoding method will take two
-;; parameters: PATH-NAME and FILE-NAME. (E.g. "/home/gaga/spiral.jpg"
-;; and "spiral.jpg", respectively.) The function should return nil if
-;; the encoding wasn't successful.
-(defvar gnus-uu-post-encode-method 'gnus-uu-post-encode-uuencode
- "Function used for encoding binary files.
-There are three functions supplied with gnus-uu for encoding files:
-`gnus-uu-post-encode-uuencode', which does straight uuencoding;
-`gnus-uu-post-encode-mime', which encodes with base64 and adds MIME
-headers; and `gnus-uu-post-encode-mime-uuencode', which encodes with
-uuencode and adds MIME headers.")
-
-(defvar gnus-uu-post-include-before-composing nil
- "Non-nil means that gnus-uu will ask for a file to encode before you compose the article.
-If this variable is t, you can either include an encoded file with
-\\[gnus-uu-post-insert-binary-in-article] or have one included for you when you post the article.")
-
-(defvar gnus-uu-post-length 990
- "Maximum length of an article.
-The encoded file will be split into how many articles it takes to
-post the entire file.")
-
-(defvar gnus-uu-post-threaded nil
- "Non-nil means that gnus-uu will post the encoded file in a thread.
-This may not be smart, as no other decoder I have seen are able to
-follow threads when collecting uuencoded articles. (Well, I have seen
-one package that does that - gnus-uu, but somehow, I don't think that
-counts...) Default is nil.")
-
-(defvar gnus-uu-post-separate-description t
- "Non-nil means that the description will be posted in a separate article.
-The first article will typically be numbered (0/x). If this variable
-is nil, the description the user enters will be included at the
-beginning of the first article, which will be numbered (1/x). Default
-is t.")
-
-(defvar gnus-uu-post-binary-separator "--binary follows this line--")
-(defvar gnus-uu-post-message-id nil)
-(defvar gnus-uu-post-inserted-file-name nil)
-(defvar gnus-uu-winconf-post-news nil)
-
-(defun gnus-uu-post-news ()
- "Compose an article and post an encoded file."
- (interactive)
- (setq gnus-uu-post-inserted-file-name nil)
- (setq gnus-uu-winconf-post-news (current-window-configuration))
-
- (gnus-summary-post-news)
-
- (use-local-map (copy-keymap (current-local-map)))
- (local-set-key "\C-c\C-c" 'gnus-summary-edit-article-done)
- (local-set-key "\C-c\C-c" 'gnus-uu-post-news-inews)
- (local-set-key "\C-c\C-s" 'gnus-uu-post-news-inews)
- (local-set-key "\C-c\C-i" 'gnus-uu-post-insert-binary-in-article)
-
- (if gnus-uu-post-include-before-composing
- (save-excursion (setq gnus-uu-post-inserted-file-name
- (gnus-uu-post-insert-binary)))))
-
-(defun gnus-uu-post-insert-binary-in-article ()
- "Inserts an encoded file in the buffer.
-The user will be asked for a file name."
- (interactive)
- (save-excursion
- (setq gnus-uu-post-inserted-file-name (gnus-uu-post-insert-binary))))
-
-;; Encodes with uuencode and substitutes all spaces with backticks.
-(defun gnus-uu-post-encode-uuencode (path file-name)
- (if (gnus-uu-post-encode-file "uuencode" path file-name)
- (progn
- (goto-char (point-min))
- (forward-line 1)
- (while (re-search-forward " " nil t)
- (replace-match "`"))
- t)))
-
-;; Encodes with uuencode and adds MIME headers.
-(defun gnus-uu-post-encode-mime-uuencode (path file-name)
- (if (gnus-uu-post-encode-uuencode path file-name)
- (progn
- (gnus-uu-post-make-mime file-name "x-uue")
- t)))
-
-;; Encodes with base64 and adds MIME headers
-(defun gnus-uu-post-encode-mime (path file-name)
- (if (gnus-uu-post-encode-file "mmencode" path file-name)
- (progn
- (gnus-uu-post-make-mime file-name "base64")
- t)))
-
-;; Adds MIME headers.
-(defun gnus-uu-post-make-mime (file-name encoding)
- (goto-char (point-min))
- (insert (format "Content-Type: %s; name=\"%s\"\n"
- (gnus-uu-choose-action file-name gnus-uu-ext-to-mime-list)
- file-name))
- (insert (format "Content-Transfer-Encoding: %s\n\n" encoding))
- (save-restriction
- (set-buffer gnus-message-buffer)
- (goto-char (point-min))
- (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
- (forward-line -1)
- (narrow-to-region 1 (point))
- (or (mail-fetch-field "mime-version")
- (progn
- (widen)
- (insert "MIME-Version: 1.0\n")))
- (widen)))
-
-;; Encodes a file PATH with COMMAND, leaving the result in the
-;; current buffer.
-(defun gnus-uu-post-encode-file (command path file-name)
- (= 0 (call-process shell-file-name nil t nil shell-command-switch
- (format "%s %s %s" command path file-name))))
-
-(defun gnus-uu-post-news-inews ()
- "Posts the composed news article and encoded file.
-If no file has been included, the user will be asked for a file."
- (interactive)
-
- (let (file-name)
-
- (if gnus-uu-post-inserted-file-name
- (setq file-name gnus-uu-post-inserted-file-name)
- (setq file-name (gnus-uu-post-insert-binary)))
-
- (if gnus-uu-post-threaded
- (let ((message-required-news-headers
- (if (memq 'Message-ID message-required-news-headers)
- message-required-news-headers
- (cons 'Message-ID message-required-news-headers)))
- gnus-inews-article-hook)
-
- (setq gnus-inews-article-hook (if (listp gnus-inews-article-hook)
- gnus-inews-article-hook
- (list gnus-inews-article-hook)))
- (setq gnus-inews-article-hook
- (cons
- '(lambda ()
- (save-excursion
- (goto-char (point-min))
- (if (re-search-forward "^Message-ID: \\(.*\\)$" nil t)
- (setq gnus-uu-post-message-id
- (buffer-substring
- (match-beginning 1) (match-end 1)))
- (setq gnus-uu-post-message-id nil))))
- gnus-inews-article-hook))
- (gnus-uu-post-encoded file-name t))
- (gnus-uu-post-encoded file-name nil)))
- (setq gnus-uu-post-inserted-file-name nil)
- (and gnus-uu-winconf-post-news
- (set-window-configuration gnus-uu-winconf-post-news)))
-
-;; Asks for a file to encode, encodes it and inserts the result in
-;; the current buffer. Returns the file name the user gave.
-(defun gnus-uu-post-insert-binary ()
- (let ((uuencode-buffer-name "*uuencode buffer*")
- file-path uubuf file-name)
-
- (setq file-path (read-file-name
- "What file do you want to encode? "))
- (if (not (file-exists-p file-path))
- (error "%s: No such file" file-path))
-
- (goto-char (point-max))
- (insert (format "\n%s\n" gnus-uu-post-binary-separator))
-
- (if (string-match "^~/" file-path)
- (setq file-path (concat "$HOME" (substring file-path 1))))
- (if (string-match "/[^/]*$" file-path)
- (setq file-name (substring file-path (1+ (match-beginning 0))))
- (setq file-name file-path))
-
- (unwind-protect
- (if (save-excursion
- (set-buffer (setq uubuf
- (get-buffer-create uuencode-buffer-name)))
- (erase-buffer)
- (funcall gnus-uu-post-encode-method file-path file-name))
- (insert-buffer-substring uubuf)
- (error "Encoding unsuccessful"))
- (kill-buffer uubuf))
- file-name))
-
-;; Posts the article and all of the encoded file.
-(defun gnus-uu-post-encoded (file-name &optional threaded)
- (let ((send-buffer-name "*uuencode send buffer*")
- (encoded-buffer-name "*encoded buffer*")
- (top-string "[ cut here %s (%s %d/%d) %s gnus-uu ]")
- (separator (concat mail-header-separator "\n\n"))
- uubuf length parts header i end beg
- beg-line minlen buf post-buf whole-len beg-binary end-binary)
-
- (setq post-buf (current-buffer))
-
- (goto-char (point-min))
- (if (not (re-search-forward
- (if gnus-uu-post-separate-description
- (concat "^" (regexp-quote gnus-uu-post-binary-separator)
- "$")
- (concat "^" (regexp-quote mail-header-separator) "$")) nil t))
- (error "Internal error: No binary/header separator"))
- (beginning-of-line)
- (forward-line 1)
- (setq beg-binary (point))
- (setq end-binary (point-max))
-
- (save-excursion
- (set-buffer (setq uubuf (get-buffer-create encoded-buffer-name)))
- (erase-buffer)
- (insert-buffer-substring post-buf beg-binary end-binary)
- (goto-char (point-min))
- (setq length (count-lines 1 (point-max)))
- (setq parts (/ length gnus-uu-post-length))
- (if (not (< (% length gnus-uu-post-length) 4))
- (setq parts (1+ parts))))
-
- (if gnus-uu-post-separate-description
- (forward-line -1))
- (kill-region (point) (point-max))
-
- (goto-char (point-min))
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$") nil t)
- (beginning-of-line)
- (setq header (buffer-substring 1 (point)))
-
- (goto-char (point-min))
- (if (not gnus-uu-post-separate-description)
- ()
- (if (and (not threaded) (re-search-forward "^Subject: " nil t))
- (progn
- (end-of-line)
- (insert (format " (0/%d)" parts))))
- (message-send))
-
- (save-excursion
- (setq i 1)
- (setq beg 1)
- (while (not (> i parts))
- (set-buffer (get-buffer-create send-buffer-name))
- (erase-buffer)
- (insert header)
- (if (and threaded gnus-uu-post-message-id)
- (insert (format "References: %s\n" gnus-uu-post-message-id)))
- (insert separator)
- (setq whole-len
- (- 62 (length (format top-string "" file-name i parts ""))))
- (if (> 1 (setq minlen (/ whole-len 2)))
- (setq minlen 1))
- (setq
- beg-line
- (format top-string
- (make-string minlen ?-)
- file-name i parts
- (make-string
- (if (= 0 (% whole-len 2)) (1- minlen) minlen) ?-)))
-
- (goto-char (point-min))
- (if (not (re-search-forward "^Subject: " nil t))
- ()
- (if (not threaded)
- (progn
- (end-of-line)
- (insert (format " (%d/%d)" i parts)))
- (if (or (and (= i 2) gnus-uu-post-separate-description)
- (and (= i 1) (not gnus-uu-post-separate-description)))
- (replace-match "Subject: Re: "))))
-
- (goto-char (point-max))
- (save-excursion
- (set-buffer uubuf)
- (goto-char beg)
- (if (= i parts)
- (goto-char (point-max))
- (forward-line gnus-uu-post-length))
- (if (and (= (1+ i) parts) (< (count-lines (point) (point-max)) 4))
- (forward-line -4))
- (setq end (point)))
- (insert-buffer-substring uubuf beg end)
- (insert beg-line)
- (insert "\n")
- (setq beg end)
- (setq i (1+ i))
- (goto-char (point-min))
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$") nil t)
- (beginning-of-line)
- (forward-line 2)
- (if (re-search-forward
- (concat "^" (regexp-quote gnus-uu-post-binary-separator) "$")
- nil t)
- (progn
- (replace-match "")
- (forward-line 1)))
- (insert beg-line)
- (insert "\n")
- (let (message-sent-message-via)
- (message-send))))
-
- (and (setq buf (get-buffer send-buffer-name))
- (kill-buffer buf))
- (and (setq buf (get-buffer encoded-buffer-name))
- (kill-buffer buf))
-
- (if (not gnus-uu-post-separate-description)
- (progn
- (set-buffer-modified-p nil)
- (and (fboundp 'bury-buffer) (bury-buffer))))))
-
-(provide 'gnus-uu)
-
-;; gnus-uu.el ends here
diff --git a/lisp/gnus-vis.el b/lisp/gnus-vis.el
deleted file mode 100644
index 0258368cce8..00000000000
--- a/lisp/gnus-vis.el
+++ /dev/null
@@ -1,1615 +0,0 @@
-;;; gnus-vis.el --- display-oriented parts of Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Per Abrahamsen <abraham@iesd.auc.dk>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'gnus)
-(require 'gnus-ems)
-(require 'easymenu)
-(require 'custom)
-(require 'browse-url)
-(require 'gnus-score)
-(eval-when-compile (require 'cl))
-
-(defvar gnus-group-menu-hook nil
- "*Hook run after the creation of the group mode menu.")
-
-(defvar gnus-summary-menu-hook nil
- "*Hook run after the creation of the summary mode menu.")
-
-(defvar gnus-article-menu-hook nil
- "*Hook run after the creation of the article mode menu.")
-
-;;; Summary highlights.
-
-;(defvar gnus-summary-highlight-properties
-; '((unread "ForestGreen" "green")
-; (ticked "Firebrick" "pink")
-; (read "black" "white")
-; (low italic italic)
-; (high bold bold)
-; (canceled "yellow/black" "black/yellow")))
-
-;(defvar gnus-summary-highlight-translation
-; '(((unread (= mark gnus-unread-mark))
-; (ticked (or (= mark gnus-ticked-mark) (= mark gnus-dormant-mark)))
-; (read (not (or (= mark gnus-unread-mark) (= mark gnus-dormant-mark)
-; (= mark gnus-ticked-mark) (= mark gnus-canceled-mark))))
-; (canceled (= mark gnus-canceled-mark)))
-; ((low (< score gnus-summary-default-score))
-; (high (> score gnus-summary-default-score)))))
-
-;(defun gnus-visual-map-face-translation ()
-; (let ((props gnus-summary-highlight-properties)
-; (trans gnus-summary-highlight-translation)
-; map)
-; (while props)))
-
-;see gnus-cus.el
-;(defvar gnus-summary-selected-face 'underline
-; "*Face used for highlighting the current article in the summary buffer.")
-
-;see gnus-cus.el
-;(defvar gnus-summary-highlight
-; (cond ((not (eq gnus-display-type 'color))
-; '(((> score default) . bold)
-; ((< score default) . italic)))
-; ((eq gnus-background-mode 'dark)
-; (list (cons '(= mark gnus-canceled-mark)
-; (custom-face-lookup "yellow" "black" nil nil nil nil))
-; (cons '(and (> score default)
-; (or (= mark gnus-dormant-mark)
-; (= mark gnus-ticked-mark)))
-; (custom-face-lookup "pink" nil nil t nil nil))
-; (cons '(and (< score default)
-; (or (= mark gnus-dormant-mark)
-; (= mark gnus-ticked-mark)))
-; (custom-face-lookup "pink" nil nil nil t nil))
-; (cons '(or (= mark gnus-dormant-mark)
-; (= mark gnus-ticked-mark))
-; (custom-face-lookup "pink" nil nil nil nil nil))
-
-; (cons '(and (> score default) (= mark gnus-ancient-mark))
-; (custom-face-lookup "SkyBlue" nil nil t nil nil))
-; (cons '(and (< score default) (= mark gnus-ancient-mark))
-; (custom-face-lookup "SkyBlue" nil nil nil t nil))
-; (cons '(= mark gnus-ancient-mark)
-; (custom-face-lookup "SkyBlue" nil nil nil nil nil))
-
-; (cons '(and (> score default) (= mark gnus-unread-mark))
-; (custom-face-lookup "white" nil nil t nil nil))
-; (cons '(and (< score default) (= mark gnus-unread-mark))
-; (custom-face-lookup "white" nil nil nil t nil))
-; (cons '(= mark gnus-unread-mark)
-; (custom-face-lookup "white" nil nil nil nil nil))
-
-; (cons '(> score default) 'bold)
-; (cons '(< score default) 'italic)))
-; (t
-; (list (cons '(= mark gnus-canceled-mark)
-; (custom-face-lookup "yellow" "black" nil nil nil nil))
-; (cons '(and (> score default)
-; (or (= mark gnus-dormant-mark)
-; (= mark gnus-ticked-mark)))
-; (custom-face-lookup "firebrick" nil nil t nil nil))
-; (cons '(and (< score default)
-; (or (= mark gnus-dormant-mark)
-; (= mark gnus-ticked-mark)))
-; (custom-face-lookup "firebrick" nil nil nil t nil))
-; (cons '(or (= mark gnus-dormant-mark)
-; (= mark gnus-ticked-mark))
-; (custom-face-lookup "firebrick" nil nil nil nil nil))
-
-; (cons '(and (> score default) (= mark gnus-ancient-mark))
-; (custom-face-lookup "RoyalBlue" nil nil t nil nil))
-; (cons '(and (< score default) (= mark gnus-ancient-mark))
-; (custom-face-lookup "RoyalBlue" nil nil nil t nil))
-; (cons '(= mark gnus-ancient-mark)
-; (custom-face-lookup "RoyalBlue" nil nil nil nil nil))
-
-; (cons '(and (> score default) (/= mark gnus-unread-mark))
-; (custom-face-lookup "DarkGreen" nil nil t nil nil))
-; (cons '(and (< score default) (/= mark gnus-unread-mark))
-; (custom-face-lookup "DarkGreen" nil nil nil t nil))
-; (cons '(/= mark gnus-unread-mark)
-; (custom-face-lookup "DarkGreen" nil nil nil nil nil))
-
-; (cons '(> score default) 'bold)
-; (cons '(< score default) 'italic))))
-; "*Alist of `(FORM . FACE)'.
-;Summary lines are highlighted with the FACE for the first FORM which
-;evaluate to a non-nil value.
-
-;Point will be at the beginning of the line when FORM is evaluated.
-;The following can be used for convenience:
-
-;score: (gnus-summary-article-score)
-;default: gnus-summary-default-score
-;below: gnus-summary-mark-below
-;mark: (gnus-summary-article-mark)
-
-;The latter can be used like this:
-; ((= mark gnus-replied-mark) . underline)")
-
-;;; article highlights
-
-;see gnus-cus.el
-;(defvar gnus-header-face-alist
-; (cond ((not (eq gnus-display-type 'color))
-; '(("" bold italic)))
-; ((eq gnus-background-mode 'dark)
-; (list (list "From" nil
-; (custom-face-lookup "SkyBlue" nil nil t t nil))
-; (list "Subject" nil
-; (custom-face-lookup "pink" nil nil t t nil))
-; (list "Newsgroups:.*," nil
-; (custom-face-lookup "yellow" nil nil t t nil))
-; (list ""
-; (custom-face-lookup "cyan" nil nil t nil nil)
-; (custom-face-lookup "green" nil nil nil t nil))))
-; (t
-; (list (list "From" nil
-; (custom-face-lookup "RoyalBlue" nil nil t t nil))
-; (list "Subject" nil
-; (custom-face-lookup "firebrick" nil nil t t nil))
-; (list "Newsgroups:.*," nil
-; (custom-face-lookup "red" nil nil t t nil))
-; (list ""
-; (custom-face-lookup "DarkGreen" nil nil t nil nil)
-; (custom-face-lookup "DarkGreen" nil nil nil t nil)))))
-; "Alist of headers and faces used for highlighting them.
-;The entries in the list has the form `(REGEXP NAME CONTENT)', where
-;REGEXP is a regular expression matching the beginning of the header,
-;NAME is the face used for highlighting the header name and CONTENT is
-;the face used for highlighting the header content.
-
-;The first non-nil NAME or CONTENT with a matching REGEXP in the list
-;will be used.")
-
-
-;see gnus-cus.el
-;(defvar gnus-make-foreground t
-; "Non nil means foreground color to highlight citations.")
-
-;see gnus-cus.el
-;(defvar gnus-article-button-face 'bold
-; "Face used for text buttons.")
-
-;see gnus-cus.el
-;(defvar gnus-article-mouse-face (if (boundp 'gnus-mouse-face)
-; gnus-mouse-face
-; 'highlight)
-; "Face used when the mouse is over the button.")
-
-;see gnus-cus.el
-;(defvar gnus-signature-face 'italic
-; "Face used for signature.")
-
-(defvar gnus-button-url-regexp "\\b\\(s?https?\\|ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\):\\(//[-a-zA-Z0-9_.]+:[0-9]*\\)?[-\\wa-zA-Z0-9_=!?#$@~`%&*+|\\/.,]*[-\\wa-zA-Z0-9_=#$@~`%&*+|\\/]"
- "*Regular expression that matches URLs.")
-
-(defvar gnus-button-alist
- `(("\\bin\\( +article\\)? +\\(<\\([^\n @<>]+@[^\n @<>]+\\)>\\)" 2
- t gnus-button-message-id 3)
- ("\\(<?\\(url: ?\\)?news:\\([^>\n\t ]*\\)>?\\)" 1 t
- gnus-button-message-id 3)
- ("\\(<URL: *\\)?mailto: *\\([^> \n\t]+\\)>?" 0 t gnus-button-reply 2)
- ;; Next regexp stolen from highlight-headers.el.
- ;; Modified by Vladimir Alexiev.
- (,gnus-button-url-regexp 0 t gnus-button-url 0)
- ;; This is how URLs _should_ be embedded in text... It should go
- ;; last to avoid matching only a subset of the URL, depending on
- ;; how it was broken across lines.
- ("<URL:\\([^>]+\\)>" 0 t gnus-button-url 1))
- "Alist of regexps matching buttons in article bodies.
-
-Each entry has the form (REGEXP BUTTON FORM CALLBACK PAR...), where
-REGEXP: is the string matching text around the button,
-BUTTON: is the number of the regexp grouping actually matching the button,
-FORM: is a lisp expression which must eval to true for the button to
-be added,
-CALLBACK: is the function to call when the user push this button, and each
-PAR: is a number of a regexp grouping whose text will be passed to CALLBACK.
-
-CALLBACK can also be a variable, in that case the value of that
-variable it the real callback function.")
-
-(defvar gnus-header-button-alist
- `(("^\\(References\\|Message-I[Dd]\\):" "<[^>]+>"
- 0 t gnus-button-message-id 0)
- ("^\\(From\\|Reply-To\\): " ": *\\(.+\\)$" 1 t gnus-button-reply 0)
- ("^\\(Cc\\|To\\):" "[^ \t\n<>,()\"]+@[^ \t\n<>,()\"]+"
- 0 t gnus-button-mailto 0)
- ("^X-[Uu][Rr][Ll]:" ,gnus-button-url-regexp 0 t gnus-button-url 0)
- ("^[^:]+:" ,gnus-button-url-regexp 0 t gnus-button-url 0)
- ("^[^:]+:" "\\(<\\(url: \\)?news:\\([^>\n ]*\\)>\\)" 1 t
- gnus-button-message-id 3))
- "Alist of headers and regexps to match buttons in article heads.
-
-This alist is very similar to `gnus-button-alist', except that each
-alist has an additional HEADER element first in each entry:
-
-\(HEADER REGEXP BUTTON FORM CALLBACK PAR)
-
-HEADER is a regexp to match a header. For a fuller explanation, see
-`gnus-button-alist'.")
-
-;see gnus-cus.el
-;(eval-when-compile
-; (defvar browse-url-browser-function))
-
-;;; Group mode highlighting.
-
-;see gnus-cus.el
-;(defvar gnus-group-highlight nil
-; "Group lines are highlighted with the FACE for the first FORM which
-;evaluate to a non-nil value.
-;
-;Point will be at the beginning of the line when FORM is evaluated.
-;Variables bound when these forms are evaluated include:
-;
-;group: The group name.
-;unread: The number of unread articles.
-;method: The select method.
-;mailp: Whether the select method is a mail method.
-;level: The level of the group.
-;score: The score of the group.
-;ticked: The number of ticked articles in the group.
-;")
-
-
-;;; Internal variables.
-
-(defvar gnus-button-marker-list nil)
-
-
-
-(eval-and-compile
- (autoload 'nnkiboze-generate-groups "nnkiboze")
- (autoload 'gnus-cite-parse-maybe "gnus-cite" nil t))
-
-;;;
-;;; gnus-menu
-;;;
-
-(defun gnus-visual-turn-off-edit-menu (type)
- (define-key (symbol-value (intern (format "gnus-%s-mode-map" type)))
- [menu-bar edit] 'undefined))
-
-;; Newsgroup buffer
-
-(defun gnus-group-make-menu-bar ()
- (gnus-visual-turn-off-edit-menu 'group)
- (or
- (boundp 'gnus-group-reading-menu)
- (progn
- (easy-menu-define
- gnus-group-reading-menu gnus-group-mode-map ""
- '("Group"
- ["Read" gnus-group-read-group (gnus-group-group-name)]
- ["Select" gnus-group-select-group (gnus-group-group-name)]
- ["See old articles" (gnus-group-select-group 'all)
- :keys "C-u SPC" :active (gnus-group-group-name)]
- ["Catch up" gnus-group-catchup-current (gnus-group-group-name)]
- ["Catch up all articles" gnus-group-catchup-current-all
- (gnus-group-group-name)]
- ["Check for new articles" gnus-group-get-new-news-this-group
- (gnus-group-group-name)]
- ["Toggle subscription" gnus-group-unsubscribe-current-group
- (gnus-group-group-name)]
- ["Kill" gnus-group-kill-group (gnus-group-group-name)]
- ["Yank" gnus-group-yank-group gnus-list-of-killed-groups]
- ["Describe" gnus-group-describe-group (gnus-group-group-name)]
- ["Fetch FAQ" gnus-group-fetch-faq (gnus-group-group-name)]
- ["Edit kill file" gnus-group-edit-local-kill
- (gnus-group-group-name)]
- ;; Actually one should check, if any of the marked groups gives t for
- ;; (gnus-check-backend-function 'request-expire-articles ...)
- ["Expire articles" gnus-group-expire-articles
- (or (and (gnus-group-group-name)
- (gnus-check-backend-function
- 'request-expire-articles
- (gnus-group-group-name))) gnus-group-marked)]
- ["Set group level" gnus-group-set-current-level
- (gnus-group-group-name)]
- ["Select quick" gnus-group-quick-select-group (gnus-group-group-name)]
- ))
-
- (easy-menu-define
- gnus-group-group-menu gnus-group-mode-map ""
- '("Groups"
- ("Listing"
- ["List unread subscribed groups" gnus-group-list-groups t]
- ["List (un)subscribed groups" gnus-group-list-all-groups t]
- ["List killed groups" gnus-group-list-killed gnus-killed-list]
- ["List zombie groups" gnus-group-list-zombies gnus-zombie-list]
- ["List level..." gnus-group-list-level t]
- ["Describe all groups" gnus-group-describe-all-groups t]
- ["Group apropos..." gnus-group-apropos t]
- ["Group and description apropos..." gnus-group-description-apropos t]
- ["List groups matching..." gnus-group-list-matching t]
- ["List all groups matching..." gnus-group-list-all-matching t]
- ["List active file" gnus-group-list-active t])
- ("Sort"
- ["Default sort" gnus-group-sort-groups
- (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
- ["Sort by method" gnus-group-sort-groups-by-method
- (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
- ["Sort by rank" gnus-group-sort-groups-by-rank
- (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
- ["Sort by score" gnus-group-sort-groups-by-score
- (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
- ["Sort by level" gnus-group-sort-groups-by-level
- (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
- ["Sort by unread" gnus-group-sort-groups-by-unread
- (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
- ["Sort by name" gnus-group-sort-groups-by-alphabet
- (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))])
- ("Mark"
- ["Mark group" gnus-group-mark-group
- (and (gnus-group-group-name)
- (not (memq (gnus-group-group-name) gnus-group-marked)))]
- ["Unmark group" gnus-group-unmark-group
- (and (gnus-group-group-name)
- (memq (gnus-group-group-name) gnus-group-marked))]
- ["Unmark all" gnus-group-unmark-all-groups gnus-group-marked]
- ["Mark regexp..." gnus-group-mark-regexp t]
- ["Mark region" gnus-group-mark-region t]
- ["Mark buffer" gnus-group-mark-buffer t]
- ["Execute command" gnus-group-universal-argument
- (or gnus-group-marked (gnus-group-group-name))])
- ("Subscribe"
- ["Subscribe to random group" gnus-group-unsubscribe-group t]
- ["Kill all newsgroups in region" gnus-group-kill-region t]
- ["Kill all zombie groups" gnus-group-kill-all-zombies
- gnus-zombie-list]
- ["Kill all groups on level..." gnus-group-kill-level t])
- ("Foreign groups"
- ["Make a foreign group" gnus-group-make-group t]
- ["Add a directory group" gnus-group-make-directory-group t]
- ["Add the help group" gnus-group-make-help-group t]
- ["Add the archive group" gnus-group-make-archive-group t]
- ["Make a doc group" gnus-group-make-doc-group t]
- ["Make a kiboze group" gnus-group-make-kiboze-group t]
- ["Make a virtual group" gnus-group-make-empty-virtual t]
- ["Add a group to a virtual" gnus-group-add-to-virtual t]
- ["Rename group" gnus-group-rename-group
- (gnus-check-backend-function
- 'request-rename-group (gnus-group-group-name))]
- ["Delete group" gnus-group-delete-group
- (gnus-check-backend-function
- 'request-delete-group (gnus-group-group-name))])
- ("Editing groups"
- ["Parameters" gnus-group-edit-group-parameters
- (gnus-group-group-name)]
- ["Select method" gnus-group-edit-group-method
- (gnus-group-group-name)]
- ["Info" gnus-group-edit-group (gnus-group-group-name)])
- ("Score file"
- ["Flush cache" gnus-score-flush-cache
- (or gnus-score-cache gnus-short-name-score-file-cache)])
- ("Move"
- ["Next" gnus-group-next-group t]
- ["Previous" gnus-group-prev-group t]
- ["Next unread" gnus-group-next-unread-group t]
- ["Previous unread" gnus-group-prev-unread-group t]
- ["Next unread same level" gnus-group-next-unread-group-same-level t]
- ["Previous unread same level"
- gnus-group-previous-unread-group-same-level t]
- ["Jump to group" gnus-group-jump-to-group t]
- ["First unread group" gnus-group-first-unread-group t]
- ["Best unread group" gnus-group-best-unread-group t])
- ["Transpose" gnus-group-transpose-groups
- (gnus-group-group-name)]
- ["Read a directory as a group..." gnus-group-enter-directory t]
- ))
-
- (easy-menu-define
- gnus-group-misc-menu gnus-group-mode-map ""
- '("Misc"
- ["Send a bug report" gnus-bug t]
- ["Send a mail" gnus-group-mail t]
- ["Post an article..." gnus-group-post-news t]
- ["Customize score file" gnus-score-customize t]
- ["Check for new news" gnus-group-get-new-news t]
- ["Activate all groups" gnus-activate-all-groups t]
- ["Delete bogus groups" gnus-group-check-bogus-groups t]
- ["Find new newsgroups" gnus-find-new-newsgroups t]
- ["Restart Gnus" gnus-group-restart t]
- ["Read init file" gnus-group-read-init-file t]
- ["Browse foreign server" gnus-group-browse-foreign-server t]
- ["Enter server buffer" gnus-group-enter-server-mode t]
- ["Expire all expirable articles" gnus-group-expire-all-groups t]
- ["Generate any kiboze groups" nnkiboze-generate-groups t]
- ["Gnus version" gnus-version t]
- ["Save .newsrc files" gnus-group-save-newsrc t]
- ["Suspend Gnus" gnus-group-suspend t]
- ["Clear dribble buffer" gnus-group-clear-dribble t]
- ["Exit from Gnus" gnus-group-exit t]
- ["Exit without saving" gnus-group-quit t]
- ["Edit global kill file" gnus-group-edit-global-kill t]
- ["Read manual" gnus-info-find-node t]
- ["Toggle topics" gnus-topic-mode t]
- ("SOUP"
- ["Pack replies" nnsoup-pack-replies (fboundp 'nnsoup-request-group)]
- ["Send replies" gnus-soup-send-replies
- (fboundp 'gnus-soup-pack-packet)]
- ["Pack packet" gnus-soup-pack-packet (fboundp 'gnus-soup-pack-packet)]
- ["Save areas" gnus-soup-save-areas (fboundp 'gnus-soup-pack-packet)]
- ["Brew SOUP" gnus-soup-brew-soup (fboundp 'gnus-soup-pack-packet)])
- ))
- (run-hooks 'gnus-group-menu-hook)
- )))
-
-;; Summary buffer
-(defun gnus-summary-make-menu-bar ()
- (gnus-visual-turn-off-edit-menu 'summary)
-
- (unless (boundp 'gnus-summary-misc-menu)
-
- (easy-menu-define
- gnus-summary-misc-menu gnus-summary-mode-map ""
- '("Misc"
- ("Mark"
- ("Read"
- ["Mark as read" gnus-summary-mark-as-read-forward t]
- ["Mark same subject and select"
- gnus-summary-kill-same-subject-and-select t]
- ["Mark same subject" gnus-summary-kill-same-subject t]
- ["Catchup" gnus-summary-catchup t]
- ["Catchup all" gnus-summary-catchup-all t]
- ["Catchup to here" gnus-summary-catchup-to-here t]
- ["Catchup region" gnus-summary-mark-region-as-read t]
- ["Mark excluded" gnus-summary-limit-mark-excluded-as-read t])
- ("Various"
- ["Tick" gnus-summary-tick-article-forward t]
- ["Mark as dormant" gnus-summary-mark-as-dormant t]
- ["Remove marks" gnus-summary-clear-mark-forward t]
- ["Set expirable mark" gnus-summary-mark-as-expirable t]
- ["Set bookmark" gnus-summary-set-bookmark t]
- ["Remove bookmark" gnus-summary-remove-bookmark t])
- ("Limit"
- ["Marks..." gnus-summary-limit-to-marks t]
- ["Subject..." gnus-summary-limit-to-subject t]
- ["Author..." gnus-summary-limit-to-author t]
- ["Score" gnus-summary-limit-to-score t]
- ["Unread" gnus-summary-limit-to-unread t]
- ["Non-dormant" gnus-summary-limit-exclude-dormant t]
- ["Articles" gnus-summary-limit-to-articles t]
- ["Pop limit" gnus-summary-pop-limit t]
- ["Show dormant" gnus-summary-limit-include-dormant t]
- ["Hide childless dormant"
- gnus-summary-limit-exclude-childless-dormant t]
- ;;["Hide thread" gnus-summary-limit-exclude-thread t]
- ["Show expunged" gnus-summary-show-all-expunged t])
- ("Process mark"
- ["Set mark" gnus-summary-mark-as-processable t]
- ["Remove mark" gnus-summary-unmark-as-processable t]
- ["Remove all marks" gnus-summary-unmark-all-processable t]
- ["Mark above" gnus-uu-mark-over t]
- ["Mark series" gnus-uu-mark-series t]
- ["Mark region" gnus-uu-mark-region t]
- ["Mark by regexp..." gnus-uu-mark-by-regexp t]
- ["Mark all" gnus-uu-mark-all t]
- ["Mark buffer" gnus-uu-mark-buffer t]
- ["Mark sparse" gnus-uu-mark-sparse t]
- ["Mark thread" gnus-uu-mark-thread t]
- ["Unmark thread" gnus-uu-unmark-thread t]))
- ("Scroll article"
- ["Page forward" gnus-summary-next-page t]
- ["Page backward" gnus-summary-prev-page t]
- ["Line forward" gnus-summary-scroll-up t])
- ("Move"
- ["Next unread article" gnus-summary-next-unread-article t]
- ["Previous unread article" gnus-summary-prev-unread-article t]
- ["Next article" gnus-summary-next-article t]
- ["Previous article" gnus-summary-prev-article t]
- ["Next unread subject" gnus-summary-next-unread-subject t]
- ["Previous unread subject" gnus-summary-prev-unread-subject t]
- ["Next article same subject" gnus-summary-next-same-subject t]
- ["Previous article same subject" gnus-summary-prev-same-subject t]
- ["First unread article" gnus-summary-first-unread-article t]
- ["Best unread article" gnus-summary-best-unread-article t]
- ["Go to subject number..." gnus-summary-goto-subject t]
- ["Go to article number..." gnus-summary-goto-article t]
- ["Go to the last article" gnus-summary-goto-last-article t]
- ["Pop article off history" gnus-summary-pop-article t])
- ("Sort"
- ["Sort by number" gnus-summary-sort-by-number t]
- ["Sort by author" gnus-summary-sort-by-author t]
- ["Sort by subject" gnus-summary-sort-by-subject t]
- ["Sort by date" gnus-summary-sort-by-date t]
- ["Sort by score" gnus-summary-sort-by-score t])
- ("Exit"
- ["Catchup and exit" gnus-summary-catchup-and-exit t]
- ["Catchup all and exit" gnus-summary-catchup-and-exit t]
- ["Catchup and goto next" gnus-summary-catchup-and-goto-next-group t]
- ["Exit group" gnus-summary-exit t]
- ["Exit group without updating" gnus-summary-exit-no-update t]
- ["Exit and goto next group" gnus-summary-next-group t]
- ["Exit and goto prev group" gnus-summary-prev-group t]
- ["Reselect group" gnus-summary-reselect-current-group t]
- ["Rescan group" gnus-summary-rescan-group t])
- ("Help"
- ["Fetch group FAQ" gnus-summary-fetch-faq t]
- ["Describe group" gnus-summary-describe-group t]
- ["Read manual" gnus-info-find-node t])
- ("Cache"
- ["Enter article" gnus-cache-enter-article t]
- ["Remove article" gnus-cache-remove-article t])
- ("Modes"
- ["Pick and read" gnus-pick-mode t]
- ["Binary" gnus-binary-mode t])
- ["Filter articles..." gnus-summary-execute-command t]
- ["Run command on subjects..." gnus-summary-universal-argument t]
- ["Toggle line truncation" gnus-summary-toggle-truncation t]
- ["Expand window" gnus-summary-expand-window t]
- ["Expire expirable articles" gnus-summary-expire-articles
- (gnus-check-backend-function
- 'request-expire-articles gnus-newsgroup-name)]
- ["Edit local kill file" gnus-summary-edit-local-kill t]
- ["Edit main kill file" gnus-summary-edit-global-kill t]
- ))
-
- (easy-menu-define
- gnus-summary-kill-menu gnus-summary-mode-map ""
- (cons
- "Score"
- (nconc
- (list
- ["Enter score..." gnus-summary-score-entry t])
- (gnus-visual-score-map 'increase)
- (gnus-visual-score-map 'lower)
- '(("Mark"
- ["Kill below" gnus-summary-kill-below t]
- ["Mark above" gnus-summary-mark-above t]
- ["Tick above" gnus-summary-tick-above t]
- ["Clear above" gnus-summary-clear-above t])
- ["Current score" gnus-summary-current-score t]
- ["Set score" gnus-summary-set-score t]
- ["Customize score file" gnus-score-customize t]
- ["Switch current score file..." gnus-score-change-score-file t]
- ["Set mark below..." gnus-score-set-mark-below t]
- ["Set expunge below..." gnus-score-set-expunge-below t]
- ["Edit current score file" gnus-score-edit-current-scores t]
- ["Edit score file" gnus-score-edit-file t]
- ["Trace score" gnus-score-find-trace t]
- ["Rescore buffer" gnus-summary-rescore t]
- ["Increase score..." gnus-summary-increase-score t]
- ["Lower score..." gnus-summary-lower-score t]))))
-
- '(("Default header"
- ["Ask" (gnus-score-set-default 'gnus-score-default-header nil)
- :style radio
- :selected (null gnus-score-default-header)]
- ["From" (gnus-score-set-default 'gnus-score-default-header 'a)
- :style radio
- :selected (eq gnus-score-default-header 'a)]
- ["Subject" (gnus-score-set-default 'gnus-score-default-header 's)
- :style radio
- :selected (eq gnus-score-default-header 's)]
- ["Article body"
- (gnus-score-set-default 'gnus-score-default-header 'b)
- :style radio
- :selected (eq gnus-score-default-header 'b )]
- ["All headers"
- (gnus-score-set-default 'gnus-score-default-header 'h)
- :style radio
- :selected (eq gnus-score-default-header 'h )]
- ["Message-Id" (gnus-score-set-default 'gnus-score-default-header 'i)
- :style radio
- :selected (eq gnus-score-default-header 'i )]
- ["Thread" (gnus-score-set-default 'gnus-score-default-header 't)
- :style radio
- :selected (eq gnus-score-default-header 't )]
- ["Crossposting"
- (gnus-score-set-default 'gnus-score-default-header 'x)
- :style radio
- :selected (eq gnus-score-default-header 'x )]
- ["Lines" (gnus-score-set-default 'gnus-score-default-header 'l)
- :style radio
- :selected (eq gnus-score-default-header 'l )]
- ["Date" (gnus-score-set-default 'gnus-score-default-header 'd)
- :style radio
- :selected (eq gnus-score-default-header 'd )]
- ["Followups to author"
- (gnus-score-set-default 'gnus-score-default-header 'f)
- :style radio
- :selected (eq gnus-score-default-header 'f )])
- ("Default type"
- ["Ask" (gnus-score-set-default 'gnus-score-default-type nil)
- :style radio
- :selected (null gnus-score-default-type)]
- ;; The `:active' key is commented out in the following,
- ;; because the GNU Emacs hack to support radio buttons use
- ;; active to indicate which button is selected.
- ["Substring" (gnus-score-set-default 'gnus-score-default-type 's)
- :style radio
- ;; :active (not (memq gnus-score-default-header '(l d)))
- :selected (eq gnus-score-default-type 's)]
- ["Regexp" (gnus-score-set-default 'gnus-score-default-type 'r)
- :style radio
- ;; :active (not (memq gnus-score-default-header '(l d)))
- :selected (eq gnus-score-default-type 'r)]
- ["Exact" (gnus-score-set-default 'gnus-score-default-type 'e)
- :style radio
- ;; :active (not (memq gnus-score-default-header '(l d)))
- :selected (eq gnus-score-default-type 'e)]
- ["Fuzzy" (gnus-score-set-default 'gnus-score-default-type 'f)
- :style radio
- ;; :active (not (memq gnus-score-default-header '(l d)))
- :selected (eq gnus-score-default-type 'f)]
- ["Before date" (gnus-score-set-default 'gnus-score-default-type 'b)
- :style radio
- ;; :active (eq (gnus-score-default-header 'd))
- :selected (eq gnus-score-default-type 'b)]
- ["At date" (gnus-score-set-default 'gnus-score-default-type 'n)
- :style radio
- ;; :active (eq (gnus-score-default-header 'd))
- :selected (eq gnus-score-default-type 'n)]
- ["After date" (gnus-score-set-default 'gnus-score-default-type 'a)
- :style radio
- ;; :active (eq (gnus-score-default-header 'd))
- :selected (eq gnus-score-default-type 'a)]
- ["Less than number"
- (gnus-score-set-default 'gnus-score-default-type '<)
- :style radio
- ;; :active (eq (gnus-score-default-header 'l))
- :selected (eq gnus-score-default-type '<)]
- ["Equal to number"
- (gnus-score-set-default 'gnus-score-default-type '=)
- :style radio
- ;; :active (eq (gnus-score-default-header 'l))
- :selected (eq gnus-score-default-type '=)]
- ["Greater than number"
- (gnus-score-set-default 'gnus-score-default-type '>)
- :style radio
- ;; :active (eq (gnus-score-default-header 'l))
- :selected (eq gnus-score-default-type '>)])
- ["Default fold" gnus-score-default-fold-toggle
- :style toggle
- :selected gnus-score-default-fold]
- ("Default duration"
- ["Ask" (gnus-score-set-default 'gnus-score-default-duration nil)
- :style radio
- :selected (null gnus-score-default-duration)]
- ["Permanent"
- (gnus-score-set-default 'gnus-score-default-duration 'p)
- :style radio
- :selected (eq gnus-score-default-duration 'p)]
- ["Temporary"
- (gnus-score-set-default 'gnus-score-default-duration 't)
- :style radio
- :selected (eq gnus-score-default-duration 't)]
- ["Immediate"
- (gnus-score-set-default 'gnus-score-default-duration 'i)
- :style radio
- :selected (eq gnus-score-default-duration 'i)]))
-
- (easy-menu-define
- gnus-summary-article-menu gnus-summary-mode-map ""
- '("Article"
- ("Hide"
- ["All" gnus-article-hide t]
- ["Headers" gnus-article-hide-headers t]
- ["Signature" gnus-article-hide-signature t]
- ["Citation" gnus-article-hide-citation t]
- ["PGP" gnus-article-hide-pgp t]
- ["Boring headers" gnus-article-hide-boring-headers t])
- ("Highlight"
- ["All" gnus-article-highlight t]
- ["Headers" gnus-article-highlight-headers t]
- ["Signature" gnus-article-highlight-signature t]
- ["Citation" gnus-article-highlight-citation t])
- ("Date"
- ["Local" gnus-article-date-local t]
- ["UT" gnus-article-date-ut t]
- ["Original" gnus-article-date-original t]
- ["Lapsed" gnus-article-date-lapsed t])
- ("Filter"
- ["Overstrike" gnus-article-treat-overstrike t]
- ["Word wrap" gnus-article-fill-cited-article t]
- ["CR" gnus-article-remove-cr t]
- ["Trailing blank lines" gnus-article-remove-trailing-blank-lines t]
- ["Show X-Face" gnus-article-display-x-face t]
- ["Quoted-Printable" gnus-article-de-quoted-unreadable t]
- ["Rot 13" gnus-summary-caesar-message t]
- ["Add buttons" gnus-article-add-buttons t]
- ["Add buttons to head" gnus-article-add-buttons-to-head t]
- ["Stop page breaking" gnus-summary-stop-page-breaking t]
- ["Toggle MIME" gnus-summary-toggle-mime t]
- ["Verbose header" gnus-summary-verbose-headers t]
- ["Toggle header" gnus-summary-toggle-header t])
- ("Output"
- ["Save in default format" gnus-summary-save-article t]
- ["Save in file" gnus-summary-save-article-file t]
- ["Save in Unix mail format" gnus-summary-save-article-mail t]
- ["Save in MH folder" gnus-summary-save-article-folder t]
- ["Save in VM folder" gnus-summary-save-article-vm t]
- ["Save in RMAIL mbox" gnus-summary-save-article-rmail t]
- ["Save body in file" gnus-summary-save-article-body-file t]
- ["Pipe through a filter" gnus-summary-pipe-output t]
- ["Add to SOUP packet" gnus-soup-add-article t])
- ("Backend"
- ["Respool article..." gnus-summary-respool-article t]
- ["Move article..." gnus-summary-move-article
- (gnus-check-backend-function
- 'request-move-article gnus-newsgroup-name)]
- ["Copy article..." gnus-summary-copy-article t]
- ["Crosspost article..." gnus-summary-crosspost-article
- (gnus-check-backend-function
- 'request-replace-article gnus-newsgroup-name)]
- ["Import file..." gnus-summary-import-article t]
- ["Edit article" gnus-summary-edit-article
- (not (gnus-group-read-only-p))]
- ["Delete article" gnus-summary-delete-article
- (gnus-check-backend-function
- 'request-expire-articles gnus-newsgroup-name)]
- ["Query respool" gnus-summary-respool-query t]
- ["Delete expirable articles" gnus-summary-expire-articles-now
- (gnus-check-backend-function
- 'request-expire-articles gnus-newsgroup-name)])
- ("Extract"
- ["Uudecode" gnus-uu-decode-uu t]
- ["Uudecode and save" gnus-uu-decode-uu-and-save t]
- ["Unshar" gnus-uu-decode-unshar t]
- ["Unshar and save" gnus-uu-decode-unshar-and-save t]
- ["Save" gnus-uu-decode-save t]
- ["Binhex" gnus-uu-decode-binhex t]
- ["Postscript" gnus-uu-decode-postscript t])
- ["Enter digest buffer" gnus-summary-enter-digest-group t]
- ["Isearch article..." gnus-summary-isearch-article t]
- ["Search articles forward..." gnus-summary-search-article-forward t]
- ["Search articles backward..." gnus-summary-search-article-backward t]
- ["Beginning of the article" gnus-summary-beginning-of-article t]
- ["End of the article" gnus-summary-end-of-article t]
- ["Fetch parent of article" gnus-summary-refer-parent-article t]
- ["Fetch referenced articles" gnus-summary-refer-references t]
- ["Fetch article with id..." gnus-summary-refer-article t]
- ["Redisplay" gnus-summary-show-article t]))
-
- (easy-menu-define
- gnus-summary-thread-menu gnus-summary-mode-map ""
- '("Threads"
- ["Toggle threading" gnus-summary-toggle-threads t]
- ["Hide threads" gnus-summary-hide-all-threads t]
- ["Show threads" gnus-summary-show-all-threads t]
- ["Hide thread" gnus-summary-hide-thread t]
- ["Show thread" gnus-summary-show-thread t]
- ["Go to next thread" gnus-summary-next-thread t]
- ["Go to previous thread" gnus-summary-prev-thread t]
- ["Go down thread" gnus-summary-down-thread t]
- ["Go up thread" gnus-summary-up-thread t]
- ["Top of thread" gnus-summary-top-thread t]
- ["Mark thread as read" gnus-summary-kill-thread t]
- ["Lower thread score" gnus-summary-lower-thread t]
- ["Raise thread score" gnus-summary-raise-thread t]
- ["Rethread current" gnus-summary-rethread-current t]
- ))
-
- (easy-menu-define
- gnus-summary-post-menu gnus-summary-mode-map ""
- '("Post"
- ["Post an article" gnus-summary-post-news t]
- ["Followup" gnus-summary-followup t]
- ["Followup and yank" gnus-summary-followup-with-original t]
- ["Supersede article" gnus-summary-supersede-article t]
- ["Cancel article" gnus-summary-cancel-article t]
- ["Reply" gnus-summary-reply t]
- ["Reply and yank" gnus-summary-reply-with-original t]
- ["Mail forward" gnus-summary-mail-forward t]
- ["Post forward" gnus-summary-post-forward t]
- ["Digest and mail" gnus-uu-digest-mail-forward t]
- ["Digest and post" gnus-uu-digest-post-forward t]
- ["Resend message" gnus-summary-resend-message t]
- ["Send bounced mail" gnus-summary-resend-bounced-mail t]
- ["Send a mail" gnus-summary-mail-other-window t]
- ["Uuencode and post" gnus-uu-post-news t]
- ;;("Draft"
- ;;["Send" gnus-summary-send-draft t]
- ;;["Send bounced" gnus-resend-bounced-mail t])
- ))
- (run-hooks 'gnus-summary-menu-hook)
- ))
-
-(defun gnus-score-set-default (var value)
- "A version of set that updates the GNU Emacs menu-bar."
- (set var value)
- ;; It is the message that forces the active status to be updated.
- (message ""))
-
-(defun gnus-visual-score-map (type)
- (if t
- nil
- (let ((headers '(("author" "from" string)
- ("subject" "subject" string)
- ("article body" "body" string)
- ("article head" "head" string)
- ("xref" "xref" string)
- ("lines" "lines" number)
- ("followups to author" "followup" string)))
- (types '((number ("less than" <)
- ("greater than" >)
- ("equal" =))
- (string ("substring" s)
- ("exact string" e)
- ("fuzzy string" f)
- ("regexp" r))))
- (perms '(("temporary" (current-time-string))
- ("permanent" nil)
- ("immediate" now)))
- header)
- (list
- (apply
- 'nconc
- (list
- (if (eq type 'lower)
- "Lower score"
- "Increase score"))
- (let (outh)
- (while headers
- (setq header (car headers))
- (setq outh
- (cons
- (apply
- 'nconc
- (list (car header))
- (let ((ts (cdr (assoc (nth 2 header) types)))
- outt)
- (while ts
- (setq outt
- (cons
- (apply
- 'nconc
- (list (caar ts))
- (let ((ps perms)
- outp)
- (while ps
- (setq outp
- (cons
- (vector
- (caar ps)
- (list
- 'gnus-summary-score-entry
- (nth 1 header)
- (if (or (string= (nth 1 header)
- "head")
- (string= (nth 1 header)
- "body"))
- ""
- (list 'gnus-summary-header
- (nth 1 header)))
- (list 'quote (nth 1 (car ts)))
- (list 'gnus-score-default nil)
- (nth 1 (car ps))
- t)
- t)
- outp))
- (setq ps (cdr ps)))
- (list (nreverse outp))))
- outt))
- (setq ts (cdr ts)))
- (list (nreverse outt))))
- outh))
- (setq headers (cdr headers)))
- (list (nreverse outh))))))))
-
-;; Article buffer
-(defun gnus-article-make-menu-bar ()
- (gnus-visual-turn-off-edit-menu 'summary)
- (or
- (boundp 'gnus-article-article-menu)
- (progn
- (easy-menu-define
- gnus-article-article-menu gnus-article-mode-map ""
- '("Article"
- ["Scroll forwards" gnus-article-goto-next-page t]
- ["Scroll backwards" gnus-article-goto-prev-page t]
- ["Show summary" gnus-article-show-summary t]
- ["Fetch Message-ID at point" gnus-article-refer-article t]
- ["Mail to address at point" gnus-article-mail t]
- ))
-
- (easy-menu-define
- gnus-article-treatment-menu gnus-article-mode-map ""
- '("Treatment"
- ["Hide headers" gnus-article-hide-headers t]
- ["Hide signature" gnus-article-hide-signature t]
- ["Hide citation" gnus-article-hide-citation t]
- ["Treat overstrike" gnus-article-treat-overstrike t]
- ["Remove carriage return" gnus-article-remove-cr t]
- ["Remove quoted-unreadable" gnus-article-de-quoted-unreadable t]
- ))
- (run-hooks 'gnus-article-menu-hook))))
-
-;;;
-;;; summary highlights
-;;;
-
-(defun gnus-highlight-selected-summary ()
- ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
- ;; Highlight selected article in summary buffer
- (if gnus-summary-selected-face
- (save-excursion
- (let* ((beg (progn (beginning-of-line) (point)))
- (end (progn (end-of-line) (point)))
- ;; Fix by Mike Dugan <dugan@bucrf16.bu.edu>.
- (from (if (get-text-property beg gnus-mouse-face-prop)
- beg
- (1+ (or (next-single-property-change
- beg gnus-mouse-face-prop nil end)
- beg))))
- (to (1- (or (next-single-property-change
- from gnus-mouse-face-prop nil end)
- end))))
- ;; If no mouse-face prop on line (e.g. xemacs) we
- ;; will have to = from = end, so we highlight the
- ;; entire line instead.
- (if (= (+ to 2) from)
- (progn
- (setq from beg)
- (setq to end)))
- (if gnus-newsgroup-selected-overlay
- (gnus-move-overlay gnus-newsgroup-selected-overlay
- from to (current-buffer))
- (setq gnus-newsgroup-selected-overlay (gnus-make-overlay from to))
- (gnus-overlay-put gnus-newsgroup-selected-overlay 'face
- gnus-summary-selected-face))))))
-
-;; New implementation by Christian Limpach <Christian.Limpach@nice.ch>.
-(defun gnus-summary-highlight-line ()
- "Highlight current line according to `gnus-summary-highlight'."
- (let* ((list gnus-summary-highlight)
- (p (point))
- (end (progn (end-of-line) (point)))
- ;; now find out where the line starts and leave point there.
- (beg (progn (beginning-of-line) (point)))
- (article (gnus-summary-article-number))
- (score (or (cdr (assq (or article gnus-current-article)
- gnus-newsgroup-scored))
- gnus-summary-default-score 0))
- (mark (or (gnus-summary-article-mark) gnus-unread-mark))
- (inhibit-read-only t))
- ;; Eval the cars of the lists until we find a match.
- (let ((default gnus-summary-default-score))
- (while (and list
- (not (eval (caar list))))
- (setq list (cdr list))))
- (let ((face (cdar list)))
- (unless (eq face (get-text-property beg 'face))
- (gnus-put-text-property
- beg end 'face
- (setq face (if (boundp face) (symbol-value face) face)))
- (when gnus-summary-highlight-line-function
- (funcall gnus-summary-highlight-line-function article face))))
- (goto-char p)))
-
-(defun gnus-group-highlight-line ()
- "Highlight the current line according to `gnus-group-highlight'."
- (let* ((list gnus-group-highlight)
- (p (point))
- (end (progn (end-of-line) (point)))
- ;; now find out where the line starts and leave point there.
- (beg (progn (beginning-of-line) (point)))
- (group (gnus-group-group-name))
- (entry (gnus-group-entry group))
- (unread (if (numberp (car entry)) (car entry) 0))
- (info (nth 2 entry))
- (method (gnus-server-get-method group (gnus-info-method info)))
- (marked (gnus-info-marks info))
- (mailp (memq 'mail (assoc (symbol-name
- (car (or method gnus-select-method)))
- gnus-valid-select-methods)))
- (level (or (gnus-info-level info) 9))
- (score (or (gnus-info-score info) 0))
- (ticked (gnus-range-length (cdr (assq 'tick marked))))
- (inhibit-read-only t))
- ;; Eval the cars of the lists until we find a match.
- (while (and list
- (not (eval (caar list))))
- (setq list (cdr list)))
- (let ((face (cdar list)))
- (unless (eq face (get-text-property beg 'face))
- (gnus-put-text-property
- beg end 'face
- (setq face (if (boundp face) (symbol-value face) face)))
- (gnus-extent-start-open beg)))
- (goto-char p)))
-
-;;;
-;;; gnus-carpal
-;;;
-
-(defvar gnus-carpal-group-buffer-buttons
- '(("next" . gnus-group-next-unread-group)
- ("prev" . gnus-group-prev-unread-group)
- ("read" . gnus-group-read-group)
- ("select" . gnus-group-select-group)
- ("catch-up" . gnus-group-catchup-current)
- ("new-news" . gnus-group-get-new-news-this-group)
- ("toggle-sub" . gnus-group-unsubscribe-current-group)
- ("subscribe" . gnus-group-unsubscribe-group)
- ("kill" . gnus-group-kill-group)
- ("yank" . gnus-group-yank-group)
- ("describe" . gnus-group-describe-group)
- "list"
- ("subscribed" . gnus-group-list-groups)
- ("all" . gnus-group-list-all-groups)
- ("killed" . gnus-group-list-killed)
- ("zombies" . gnus-group-list-zombies)
- ("matching" . gnus-group-list-matching)
- ("post" . gnus-group-post-news)
- ("mail" . gnus-group-mail)
- ("rescan" . gnus-group-get-new-news)
- ("browse-foreign" . gnus-group-browse-foreign)
- ("exit" . gnus-group-exit)))
-
-(defvar gnus-carpal-summary-buffer-buttons
- '("mark"
- ("read" . gnus-summary-mark-as-read-forward)
- ("tick" . gnus-summary-tick-article-forward)
- ("clear" . gnus-summary-clear-mark-forward)
- ("expirable" . gnus-summary-mark-as-expirable)
- "move"
- ("scroll" . gnus-summary-next-page)
- ("next-unread" . gnus-summary-next-unread-article)
- ("prev-unread" . gnus-summary-prev-unread-article)
- ("first" . gnus-summary-first-unread-article)
- ("best" . gnus-summary-best-unread-article)
- "article"
- ("headers" . gnus-summary-toggle-header)
- ("uudecode" . gnus-uu-decode-uu)
- ("enter-digest" . gnus-summary-enter-digest-group)
- ("fetch-parent" . gnus-summary-refer-parent-article)
- "mail"
- ("move" . gnus-summary-move-article)
- ("copy" . gnus-summary-copy-article)
- ("respool" . gnus-summary-respool-article)
- "threads"
- ("lower" . gnus-summary-lower-thread)
- ("kill" . gnus-summary-kill-thread)
- "post"
- ("post" . gnus-summary-post-news)
- ("mail" . gnus-summary-mail)
- ("followup" . gnus-summary-followup-with-original)
- ("reply" . gnus-summary-reply-with-original)
- ("cancel" . gnus-summary-cancel-article)
- "misc"
- ("exit" . gnus-summary-exit)
- ("fed-up" . gnus-summary-catchup-and-goto-next-group)))
-
-(defvar gnus-carpal-server-buffer-buttons
- '(("add" . gnus-server-add-server)
- ("browse" . gnus-server-browse-server)
- ("list" . gnus-server-list-servers)
- ("kill" . gnus-server-kill-server)
- ("yank" . gnus-server-yank-server)
- ("copy" . gnus-server-copy-server)
- ("exit" . gnus-server-exit)))
-
-(defvar gnus-carpal-browse-buffer-buttons
- '(("subscribe" . gnus-browse-unsubscribe-current-group)
- ("exit" . gnus-browse-exit)))
-
-(defvar gnus-carpal-group-buffer "*Carpal Group*")
-(defvar gnus-carpal-summary-buffer "*Carpal Summary*")
-(defvar gnus-carpal-server-buffer "*Carpal Server*")
-(defvar gnus-carpal-browse-buffer "*Carpal Browse*")
-
-(defvar gnus-carpal-attached-buffer nil)
-
-(defvar gnus-carpal-mode-hook nil
- "*Hook run in carpal mode buffers.")
-
-(defvar gnus-carpal-button-face 'bold
- "*Face used on carpal buttons.")
-
-(defvar gnus-carpal-header-face 'bold-italic
- "*Face used on carpal buffer headers.")
-
-(defvar gnus-carpal-mode-map nil)
-(put 'gnus-carpal-mode 'mode-class 'special)
-
-(if gnus-carpal-mode-map
- nil
- (setq gnus-carpal-mode-map (make-keymap))
- (suppress-keymap gnus-carpal-mode-map)
- (define-key gnus-carpal-mode-map " " 'gnus-carpal-select)
- (define-key gnus-carpal-mode-map "\r" 'gnus-carpal-select)
- (define-key gnus-carpal-mode-map gnus-mouse-2 'gnus-carpal-mouse-select))
-
-(defun gnus-carpal-mode ()
- "Major mode for clicking buttons.
-
-All normal editing commands are switched off.
-\\<gnus-carpal-mode-map>
-The following commands are available:
-
-\\{gnus-carpal-mode-map}"
- (interactive)
- (kill-all-local-variables)
- (setq mode-line-modified "-- ")
- (setq major-mode 'gnus-carpal-mode)
- (setq mode-name "Gnus Carpal")
- (setq mode-line-process nil)
- (use-local-map gnus-carpal-mode-map)
- (buffer-disable-undo (current-buffer))
- (setq buffer-read-only t)
- (make-local-variable 'gnus-carpal-attached-buffer)
- (run-hooks 'gnus-carpal-mode-hook))
-
-(defun gnus-carpal-setup-buffer (type)
- (let ((buffer (symbol-value (intern (format "gnus-carpal-%s-buffer" type)))))
- (if (get-buffer buffer)
- ()
- (save-excursion
- (set-buffer (get-buffer-create buffer))
- (gnus-carpal-mode)
- (setq gnus-carpal-attached-buffer
- (intern (format "gnus-%s-buffer" type)))
- (gnus-add-current-to-buffer-list)
- (let ((buttons (symbol-value
- (intern (format "gnus-carpal-%s-buffer-buttons"
- type))))
- (buffer-read-only nil)
- button)
- (while buttons
- (setq button (car buttons)
- buttons (cdr buttons))
- (if (stringp button)
- (gnus-set-text-properties
- (point)
- (prog2 (insert button) (point) (insert " "))
- (list 'face gnus-carpal-header-face))
- (gnus-set-text-properties
- (point)
- (prog2 (insert (car button)) (point) (insert " "))
- (list 'gnus-callback (cdr button)
- 'face gnus-carpal-button-face
- gnus-mouse-face-prop 'highlight))))
- (let ((fill-column (- (window-width) 2)))
- (fill-region (point-min) (point-max)))
- (set-window-point (get-buffer-window (current-buffer))
- (point-min)))))))
-
-(defun gnus-carpal-select ()
- "Select the button under point."
- (interactive)
- (let ((func (get-text-property (point) 'gnus-callback)))
- (if (null func)
- ()
- (pop-to-buffer (symbol-value gnus-carpal-attached-buffer))
- (call-interactively func))))
-
-(defun gnus-carpal-mouse-select (event)
- "Select the button under the mouse pointer."
- (interactive "e")
- (mouse-set-point event)
- (gnus-carpal-select))
-
-;;;
-;;; article highlights
-;;;
-
-;; Written by Per Abrahamsen <abraham@iesd.auc.dk>.
-
-;;; Internal Variables:
-
-(defvar gnus-button-regexp nil)
-;; Regexp matching any of the regexps from `gnus-button-alist'.
-
-(defvar gnus-button-last nil)
-;; The value of `gnus-button-alist' when `gnus-button-regexp' was build.
-
-;;; Commands:
-
-(defun gnus-article-push-button (event)
- "Check text under the mouse pointer for a callback function.
-If the text under the mouse pointer has a `gnus-callback' property,
-call it with the value of the `gnus-data' text property."
- (interactive "e")
- (set-buffer (window-buffer (posn-window (event-start event))))
- (let* ((pos (posn-point (event-start event)))
- (data (get-text-property pos 'gnus-data))
- (fun (get-text-property pos 'gnus-callback)))
- (if fun (funcall fun data))))
-
-(defun gnus-article-press-button ()
- "Check text at point for a callback function.
-If the text at point has a `gnus-callback' property,
-call it with the value of the `gnus-data' text property."
- (interactive)
- (let* ((data (get-text-property (point) 'gnus-data))
- (fun (get-text-property (point) 'gnus-callback)))
- (if fun (funcall fun data))))
-
-(defun gnus-article-prev-button (n)
- "Move point to N buttons backward.
-If N is negative, move forward instead."
- (interactive "p")
- (gnus-article-next-button (- n)))
-
-(defun gnus-article-next-button (n)
- "Move point to N buttons forward.
-If N is negative, move backward instead."
- (interactive "p")
- (let ((function (if (< n 0) 'previous-single-property-change
- 'next-single-property-change))
- (inhibit-point-motion-hooks t)
- (backward (< n 0))
- (limit (if (< n 0) (point-min) (point-max))))
- (setq n (abs n))
- (while (and (not (= limit (point)))
- (> n 0))
- ;; Skip past the current button.
- (when (get-text-property (point) 'gnus-callback)
- (goto-char (funcall function (point) 'gnus-callback nil limit)))
- ;; Go to the next (or previous) button.
- (gnus-goto-char (funcall function (point) 'gnus-callback nil limit))
- ;; Put point at the start of the button.
- (when (and backward (not (get-text-property (point) 'gnus-callback)))
- (goto-char (funcall function (point) 'gnus-callback nil limit)))
- ;; Skip past intangible buttons.
- (when (get-text-property (point) 'intangible)
- (incf n))
- (decf n))
- (unless (zerop n)
- (gnus-message 5 "No more buttons"))
- n))
-
-(defun gnus-article-highlight (&optional force)
- "Highlight current article.
-This function calls `gnus-article-highlight-headers',
-`gnus-article-highlight-citation',
-`gnus-article-highlight-signature', and `gnus-article-add-buttons' to
-do the highlighting. See the documentation for those functions."
- (interactive (list 'force))
- (gnus-article-highlight-headers)
- (gnus-article-highlight-citation force)
- (gnus-article-highlight-signature)
- (gnus-article-add-buttons force)
- (gnus-article-add-buttons-to-head))
-
-(defun gnus-article-highlight-some (&optional force)
- "Highlight current article.
-This function calls `gnus-article-highlight-headers',
-`gnus-article-highlight-signature', and `gnus-article-add-buttons' to
-do the highlighting. See the documentation for those functions."
- (interactive (list 'force))
- (gnus-article-highlight-headers)
- (gnus-article-highlight-signature)
- (gnus-article-add-buttons))
-
-(defun gnus-article-highlight-headers ()
- "Highlight article headers as specified by `gnus-header-face-alist'."
- (interactive)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (save-restriction
- (let ((alist gnus-header-face-alist)
- (buffer-read-only nil)
- (case-fold-search t)
- (inhibit-point-motion-hooks t)
- entry regexp header-face field-face from hpoints fpoints)
- (goto-char (point-min))
- (when (search-forward "\n\n" nil t)
- (narrow-to-region (1- (point)) (point-min))
- (while (setq entry (pop alist))
- (goto-char (point-min))
- (setq regexp (concat "^\\("
- (if (string-equal "" (nth 0 entry))
- "[^\t ]"
- (nth 0 entry))
- "\\)")
- header-face (nth 1 entry)
- field-face (nth 2 entry))
- (while (and (re-search-forward regexp nil t)
- (not (eobp)))
- (beginning-of-line)
- (setq from (point))
- (or (search-forward ":" nil t)
- (forward-char 1))
- (when (and header-face
- (not (memq (point) hpoints)))
- (push (point) hpoints)
- (gnus-put-text-property from (point) 'face header-face))
- (when (and field-face
- (not (memq (setq from (point)) fpoints)))
- (push from fpoints)
- (if (re-search-forward "^[^ \t]" nil t)
- (forward-char -2)
- (goto-char (point-max)))
- (gnus-put-text-property from (point) 'face field-face)))))))))
-
-(defun gnus-article-highlight-signature ()
- "Highlight the signature in an article.
-It does this by highlighting everything after
-`gnus-signature-separator' using `gnus-signature-face'."
- (interactive)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil)
- (inhibit-point-motion-hooks t))
- (save-restriction
- (when (and gnus-signature-face
- (gnus-narrow-to-signature))
- (gnus-overlay-put (gnus-make-overlay (point-min) (point-max))
- 'face gnus-signature-face)
- (widen)
- (re-search-backward gnus-signature-separator nil t)
- (let ((start (match-beginning 0))
- (end (set-marker (make-marker) (1+ (match-end 0)))))
- (gnus-article-add-button start (1- end) 'gnus-signature-toggle
- end)))))))
-
-(defun gnus-article-add-buttons (&optional force)
- "Find external references in the article and make buttons of them.
-\"External references\" are things like Message-IDs and URLs, as
-specified by `gnus-button-alist'."
- (interactive (list 'force))
- (save-excursion
- (set-buffer gnus-article-buffer)
- ;; Remove all old markers.
- (while gnus-button-marker-list
- (set-marker (pop gnus-button-marker-list) nil))
- (let ((buffer-read-only nil)
- (inhibit-point-motion-hooks t)
- (case-fold-search t)
- (alist gnus-button-alist)
- beg entry regexp)
- (goto-char (point-min))
- ;; We skip the headers.
- (unless (search-forward "\n\n" nil t)
- (goto-char (point-max)))
- (setq beg (point))
- (while (setq entry (pop alist))
- (setq regexp (car entry))
- (goto-char beg)
- (while (re-search-forward regexp nil t)
- (let* ((start (and entry (match-beginning (nth 1 entry))))
- (end (and entry (match-end (nth 1 entry))))
- (from (match-beginning 0)))
- (when (or (eq t (nth 1 entry))
- (eval (nth 1 entry)))
- ;; That optional form returned non-nil, so we add the
- ;; button.
- (gnus-article-add-button
- start end 'gnus-button-push
- (car (push (set-marker (make-marker) from)
- gnus-button-marker-list))))))))))
-
-;; Add buttons to the head of an article.
-(defun gnus-article-add-buttons-to-head ()
- "Add buttons to the head of the article."
- (interactive)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil)
- (inhibit-point-motion-hooks t)
- (case-fold-search t)
- (alist gnus-header-button-alist)
- entry beg end)
- (nnheader-narrow-to-headers)
- (while alist
- ;; Each alist entry.
- (setq entry (car alist)
- alist (cdr alist))
- (goto-char (point-min))
- (while (re-search-forward (car entry) nil t)
- ;; Each header matching the entry.
- (setq beg (match-beginning 0))
- (setq end (or (and (re-search-forward "^[^ \t]" nil t)
- (match-beginning 0))
- (point-max)))
- (goto-char beg)
- (while (re-search-forward (nth 1 entry) end t)
- ;; Each match within a header.
- (let* ((from (match-beginning 0))
- (entry (cdr entry))
- (start (match-beginning (nth 1 entry)))
- (end (match-end (nth 1 entry)))
- (form (nth 2 entry)))
- (goto-char (match-end 0))
- (and (eval form)
- (gnus-article-add-button
- start end (nth 3 entry)
- (buffer-substring (match-beginning (nth 4 entry))
- (match-end (nth 4 entry)))))))
- (goto-char end))))
- (widen)))
-
-;;; External functions:
-
-(defun gnus-article-add-button (from to fun &optional data)
- "Create a button between FROM and TO with callback FUN and data DATA."
- (and gnus-article-button-face
- (gnus-overlay-put (gnus-make-overlay from to)
- 'face gnus-article-button-face))
- (gnus-add-text-properties
- from to
- (nconc (and gnus-article-mouse-face
- (list gnus-mouse-face-prop gnus-article-mouse-face))
- (list 'gnus-callback fun)
- (and data (list 'gnus-data data)))))
-
-;;; Internal functions:
-
-(defun gnus-signature-toggle (end)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil)
- (inhibit-point-motion-hooks t))
- (if (get-text-property end 'invisible)
- (gnus-unhide-text end (point-max))
- (gnus-hide-text end (point-max) gnus-hidden-properties)))))
-
-(defun gnus-button-entry ()
- ;; Return the first entry in `gnus-button-alist' matching this place.
- (let ((alist gnus-button-alist)
- (entry nil))
- (while alist
- (setq entry (pop alist))
- (if (looking-at (car entry))
- (setq alist nil)
- (setq entry nil)))
- entry))
-
-(defun gnus-button-push (marker)
- ;; Push button starting at MARKER.
- (save-excursion
- (set-buffer gnus-article-buffer)
- (goto-char marker)
- (let* ((entry (gnus-button-entry))
- (inhibit-point-motion-hooks t)
- (fun (nth 3 entry))
- (args (mapcar (lambda (group)
- (let ((string (buffer-substring
- (match-beginning group)
- (match-end group))))
- (gnus-set-text-properties
- 0 (length string) nil string)
- string))
- (nthcdr 4 entry))))
- (cond
- ((fboundp fun)
- (apply fun args))
- ((and (boundp fun)
- (fboundp (symbol-value fun)))
- (apply (symbol-value fun) args))
- (t
- (gnus-message 1 "You must define `%S' to use this button"
- (cons fun args)))))))
-
-(defun gnus-button-message-id (message-id)
- "Fetch MESSAGE-ID."
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (gnus-summary-refer-article message-id)))
-
-(defun gnus-button-mailto (address)
- ;; Mail to ADDRESS.
- (set-buffer (gnus-copy-article-buffer))
- (message-reply address))
-
-(defun gnus-button-reply (address)
- ;; Reply to ADDRESS.
- (message-reply address))
-
-(defun gnus-button-url (address)
- "Browse ADDRESS."
- (funcall browse-url-browser-function
- ;; Zap whitespace in case <URL:...> contained it.
- ;; (Whitespace illegal in raw URL.)
- (let ((stripped-address address))
- (while (string-match "\\s +\\|\n+" stripped-address)
- (setq stripped-address (replace-match "" t t stripped-address)))
- stripped-address)))
-
-;;; Next/prev buttons in the article buffer.
-
-(defvar gnus-next-page-line-format "%{%(Next page...%)%}\n")
-(defvar gnus-prev-page-line-format "%{%(Previous page...%)%}\n")
-
-(defvar gnus-prev-page-map nil)
-(unless gnus-prev-page-map
- (setq gnus-prev-page-map (make-sparse-keymap))
- (define-key gnus-prev-page-map gnus-mouse-2 'gnus-button-prev-page)
- (define-key gnus-prev-page-map "\r" 'gnus-button-prev-page))
-
-(defun gnus-insert-prev-page-button ()
- (let ((buffer-read-only nil))
- (gnus-eval-format
- gnus-prev-page-line-format nil
- `(gnus-prev t local-map ,gnus-prev-page-map
- gnus-callback gnus-article-button-prev-page))))
-
-(defvar gnus-next-page-map nil)
-(unless gnus-next-page-map
- (setq gnus-next-page-map (make-keymap))
- (suppress-keymap gnus-prev-page-map)
- (define-key gnus-next-page-map gnus-mouse-2 'gnus-button-next-page)
- (define-key gnus-next-page-map "\r" 'gnus-button-next-page))
-
-(defun gnus-button-next-page ()
- "Go to the next page."
- (interactive)
- (let ((win (selected-window)))
- (select-window (get-buffer-window gnus-article-buffer t))
- (gnus-article-next-page)
- (select-window win)))
-
-(defun gnus-button-prev-page ()
- "Go to the prev page."
- (interactive)
- (let ((win (selected-window)))
- (select-window (get-buffer-window gnus-article-buffer t))
- (gnus-article-prev-page)
- (select-window win)))
-
-(defun gnus-insert-next-page-button ()
- (let ((buffer-read-only nil))
- (gnus-eval-format gnus-next-page-line-format nil
- `(gnus-next t local-map ,gnus-next-page-map
- gnus-callback
- gnus-article-button-next-page))))
-
-(defun gnus-article-button-next-page (arg)
- "Go to the next page."
- (interactive "P")
- (let ((win (selected-window)))
- (select-window (get-buffer-window gnus-article-buffer t))
- (gnus-article-next-page)
- (select-window win)))
-
-(defun gnus-article-button-prev-page (arg)
- "Go to the prev page."
- (interactive "P")
- (let ((win (selected-window)))
- (select-window (get-buffer-window gnus-article-buffer t))
- (gnus-article-prev-page)
- (select-window win)))
-
-;;; Compatibility Functions:
-
-(or (fboundp 'rassoc)
- ;; Introduced in Emacs 19.29.
- (defun rassoc (elt list)
- "Return non-nil if ELT is `equal' to the cdr of an element of LIST.
-The value is actually the element of LIST whose cdr is ELT."
- (let (result)
- (while list
- (setq result (car list))
- (if (equal (cdr result) elt)
- (setq list nil)
- (setq result nil
- list (cdr list))))
- result)))
-
-; (require 'gnus-cus)
-(gnus-ems-redefine)
-(provide 'gnus-vis)
-
-;;; gnus-vis.el ends here
diff --git a/lisp/gnus-vm.el b/lisp/gnus-vm.el
deleted file mode 100644
index ecfc0e93880..00000000000
--- a/lisp/gnus-vm.el
+++ /dev/null
@@ -1,111 +0,0 @@
-;;; gnus-vm.el --- vm interface for Gnus
-;; Copyright (C) 1994,95,96 Free Software Foundation, Inc.
-
-;; Author: Per Persson <pp@solace.mh.se>
-;; Keywords: news, mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Major contributors:
-;; Christian Limpach <Christian.Limpach@nice.ch>
-;; Some code stolen from:
-;; Rick Sladkey <jrs@world.std.com>
-
-;;; Code:
-
-(require 'sendmail)
-(require 'message)
-(require 'gnus)
-(require 'gnus-msg)
-
-(eval-when-compile
- (autoload 'vm-mode "vm")
- (autoload 'vm-save-message "vm")
- (autoload 'vm-forward-message "vm")
- (autoload 'vm-reply "vm")
- (autoload 'vm-mail "vm"))
-
-(defvar gnus-vm-inhibit-window-system nil
- "Inhibit loading `win-vm' if using a window-system.
-Has to be set before gnus-vm is loaded.")
-
-(or gnus-vm-inhibit-window-system
- (condition-case nil
- (if window-system
- (require 'win-vm))
- (error nil)))
-
-(if (not (featurep 'vm))
- (load "vm"))
-
-(defun gnus-vm-make-folder (&optional buffer)
- (let ((article (or buffer (current-buffer)))
- (tmp-folder (generate-new-buffer " *tmp-folder*"))
- (start (point-min))
- (end (point-max)))
- (set-buffer tmp-folder)
- (insert-buffer-substring article start end)
- (goto-char (point-min))
- (if (looking-at "^\\(From [^ ]+ \\).*$")
- (replace-match (concat "\\1" (current-time-string)))
- (insert "From " gnus-newsgroup-name " "
- (current-time-string) "\n"))
- (while (re-search-forward "\n\nFrom " nil t)
- (replace-match "\n\n>From "))
- ;; insert a newline, otherwise the last line gets lost
- (goto-char (point-max))
- (insert "\n")
- (vm-mode)
- tmp-folder))
-
-(defun gnus-summary-save-article-vm (&optional arg)
- "Append the current article to a vm folder.
-If N is a positive number, save the N next articles.
-If N is a negative number, save the N previous articles.
-If N is nil and any articles have been marked with the process mark,
-save those articles instead."
- (interactive "P")
- (let ((gnus-default-article-saver 'gnus-summary-save-in-vm))
- (gnus-summary-save-article arg)))
-
-(defun gnus-summary-save-in-vm (&optional folder)
- (interactive)
- (let ((default-name
- (funcall gnus-mail-save-name gnus-newsgroup-name
- gnus-current-headers gnus-newsgroup-last-mail)))
- (setq folder
- (cond ((eq folder 'default) default-name)
- (folder folder)
- (t (gnus-read-save-file-name
- "Save article in VM folder:" default-name))))
- (gnus-make-directory (file-name-directory folder))
- (set-buffer gnus-original-article-buffer)
- (save-excursion
- (save-restriction
- (widen)
- (let ((vm-folder (gnus-vm-make-folder)))
- (vm-save-message folder)
- (kill-buffer vm-folder))))
- ;; Remember the directory name to save articles.
- (setq gnus-newsgroup-last-mail folder)))
-
-(provide 'gnus-vm)
-
-;;; gnus-vm.el ends here.
diff --git a/lisp/gnus.el b/lisp/gnus.el
deleted file mode 100644
index f50ca034de1..00000000000
--- a/lisp/gnus.el
+++ /dev/null
@@ -1,17270 +0,0 @@
-;;; gnus.el --- a newsreader for GNU Emacs
-;; Copyright (C) 1987,88,89,90,93,94,95,96 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(eval '(run-hooks 'gnus-load-hook))
-
-(require 'mail-utils)
-(require 'timezone)
-(require 'nnheader)
-(require 'nnmail)
-(require 'backquote)
-(require 'nnoo)
-
-(eval-when-compile (require 'cl))
-
-(defvar gnus-directory (or (getenv "SAVEDIR") "~/News/")
- "*Directory variable from which all other Gnus file variables are derived.")
-
-;; Site dependent variables. These variables should be defined in
-;; paths.el.
-
-(defvar gnus-default-nntp-server nil
- "Specify a default NNTP server.
-This variable should be defined in paths.el, and should never be set
-by the user.
-If you want to change servers, you should use `gnus-select-method'.
-See the documentation to that variable.")
-
-(defvar gnus-backup-default-subscribed-newsgroups
- '("news.announce.newusers" "news.groups.questions" "gnu.emacs.gnus")
- "Default default new newsgroups the first time Gnus is run.
-Should be set in paths.el, and shouldn't be touched by the user.")
-
-(defvar gnus-local-organization nil
- "String with a description of what organization (if any) the user belongs to.
-The ORGANIZATION environment variable is used instead if it is defined.
-If this variable contains a function, this function will be called
-with the current newsgroup name as the argument. The function should
-return a string.
-
-In any case, if the string (either in the variable, in the environment
-variable, or returned by the function) is a file name, the contents of
-this file will be used as the organization.")
-
-;; Customization variables
-
-;; Don't touch this variable.
-(defvar gnus-nntp-service "nntp"
- "*NNTP service name (\"nntp\" or 119).
-This is an obsolete variable, which is scarcely used. If you use an
-nntp server for your newsgroup and want to change the port number
-used to 899, you would say something along these lines:
-
- (setq gnus-select-method '(nntp \"my.nntp.server\" (nntp-port-number 899)))")
-
-(defvar gnus-nntpserver-file "/etc/nntpserver"
- "*A file with only the name of the nntp server in it.")
-
-;; This function is used to check both the environment variable
-;; NNTPSERVER and the /etc/nntpserver file to see whether one can find
-;; an nntp server name default.
-(defun gnus-getenv-nntpserver ()
- (or (getenv "NNTPSERVER")
- (and (file-readable-p gnus-nntpserver-file)
- (save-excursion
- (set-buffer (get-buffer-create " *gnus nntp*"))
- (buffer-disable-undo (current-buffer))
- (insert-file-contents gnus-nntpserver-file)
- (let ((name (buffer-string)))
- (prog1
- (if (string-match "^[ \t\n]*$" name)
- nil
- name)
- (kill-buffer (current-buffer))))))))
-
-(defvar gnus-select-method
- (nconc
- (list 'nntp (or (condition-case ()
- (gnus-getenv-nntpserver)
- (error nil))
- (if (and gnus-default-nntp-server
- (not (string= gnus-default-nntp-server "")))
- gnus-default-nntp-server)
- (system-name)))
- (if (or (null gnus-nntp-service)
- (equal gnus-nntp-service "nntp"))
- nil
- (list gnus-nntp-service)))
- "*Default method for selecting a newsgroup.
-This variable should be a list, where the first element is how the
-news is to be fetched, the second is the address.
-
-For instance, if you want to get your news via NNTP from
-\"flab.flab.edu\", you could say:
-
-(setq gnus-select-method '(nntp \"flab.flab.edu\"))
-
-If you want to use your local spool, say:
-
-(setq gnus-select-method (list 'nnspool (system-name)))
-
-If you use this variable, you must set `gnus-nntp-server' to nil.
-
-There is a lot more to know about select methods and virtual servers -
-see the manual for details.")
-
-(defvar gnus-message-archive-method
- `(nnfolder
- "archive"
- (nnfolder-directory ,(nnheader-concat message-directory "archive"))
- (nnfolder-active-file
- ,(nnheader-concat message-directory "archive/active"))
- (nnfolder-get-new-mail nil)
- (nnfolder-inhibit-expiry t))
- "*Method used for archiving messages you've sent.
-This should be a mail method.
-
-It's probably not a very effective to change this variable once you've
-run Gnus once. After doing that, you must edit this server from the
-server buffer.")
-
-(defvar gnus-message-archive-group nil
- "*Name of the group in which to save the messages you've written.
-This can either be a string, a list of strings; or an alist
-of regexps/functions/forms to be evaluated to return a string (or a list
-of strings). The functions are called with the name of the current
-group (or nil) as a parameter.
-
-Normally the group names returned by this variable should be
-unprefixed -- which implictly means \"store on the archive server\".
-However, you may wish to store the message on some other server. In
-that case, just return a fully prefixed name of the group --
-\"nnml+private:mail.misc\", for instance.")
-
-(defvar gnus-refer-article-method nil
- "*Preferred method for fetching an article by Message-ID.
-If you are reading news from the local spool (with nnspool), fetching
-articles by Message-ID is painfully slow. By setting this method to an
-nntp method, you might get acceptable results.
-
-The value of this variable must be a valid select method as discussed
-in the documentation of `gnus-select-method'.")
-
-(defvar gnus-secondary-select-methods nil
- "*A list of secondary methods that will be used for reading news.
-This is a list where each element is a complete select method (see
-`gnus-select-method').
-
-If, for instance, you want to read your mail with the nnml backend,
-you could set this variable:
-
-(setq gnus-secondary-select-methods '((nnml \"\")))")
-
-(defvar gnus-secondary-servers nil
- "*List of NNTP servers that the user can choose between interactively.
-To make Gnus query you for a server, you have to give `gnus' a
-non-numeric prefix - `C-u M-x gnus', in short.")
-
-(defvar gnus-nntp-server nil
- "*The name of the host running the NNTP server.
-This variable is semi-obsolete. Use the `gnus-select-method'
-variable instead.")
-
-(defvar gnus-startup-file "~/.newsrc"
- "*Your `.newsrc' file.
-`.newsrc-SERVER' will be used instead if that exists.")
-
-(defvar gnus-init-file "~/.gnus"
- "*Your Gnus elisp startup file.
-If a file with the .el or .elc suffixes exist, it will be read
-instead.")
-
-(defvar gnus-group-faq-directory
- '("/ftp@mirrors.aol.com:/pub/rtfm/usenet/"
- "/ftp@sunsite.auc.dk:/pub/usenet/"
- "/ftp@sunsite.doc.ic.ac.uk:/pub/usenet/news-faqs/"
- "/ftp@src.doc.ic.ac.uk:/usenet/news-FAQS/"
- "/ftp@ftp.seas.gwu.edu:/pub/rtfm/"
- "/ftp@rtfm.mit.edu:/pub/usenet/"
- "/ftp@ftp.uni-paderborn.de:/pub/FAQ/"
- "/ftp@ftp.sunet.se:/pub/usenet/"
- "/ftp@nctuccca.edu.tw:/USENET/FAQ/"
- "/ftp@hwarang.postech.ac.kr:/pub/usenet/"
- "/ftp@ftp.hk.super.net:/mirror/faqs/")
- "*Directory where the group FAQs are stored.
-This will most commonly be on a remote machine, and the file will be
-fetched by ange-ftp.
-
-This variable can also be a list of directories. In that case, the
-first element in the list will be used by default. The others can
-be used when being prompted for a site.
-
-Note that Gnus uses an aol machine as the default directory. If this
-feels fundamentally unclean, just think of it as a way to finally get
-something of value back from them.
-
-If the default site is too slow, try one of these:
-
- North America: mirrors.aol.com /pub/rtfm/usenet
- ftp.seas.gwu.edu /pub/rtfm
- rtfm.mit.edu /pub/usenet
- Europe: ftp.uni-paderborn.de /pub/FAQ
- src.doc.ic.ac.uk /usenet/news-FAQS
- ftp.sunet.se /pub/usenet
- sunsite.auc.dk /pub/usenet
- Asia: nctuccca.edu.tw /USENET/FAQ
- hwarang.postech.ac.kr /pub/usenet
- ftp.hk.super.net /mirror/faqs")
-
-(defvar gnus-group-archive-directory
- "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/"
- "*The address of the (ding) archives.")
-
-(defvar gnus-group-recent-archive-directory
- "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list-recent/"
- "*The address of the most recent (ding) articles.")
-
-(defvar gnus-default-subscribed-newsgroups nil
- "*This variable lists what newsgroups should be subscribed the first time Gnus is used.
-It should be a list of strings.
-If it is `t', Gnus will not do anything special the first time it is
-started; it'll just use the normal newsgroups subscription methods.")
-
-(defvar gnus-use-cross-reference t
- "*Non-nil means that cross referenced articles will be marked as read.
-If nil, ignore cross references. If t, mark articles as read in
-subscribed newsgroups. If neither t nor nil, mark as read in all
-newsgroups.")
-
-(defvar gnus-single-article-buffer t
- "*If non-nil, display all articles in the same buffer.
-If nil, each group will get its own article buffer.")
-
-(defvar gnus-use-dribble-file t
- "*Non-nil means that Gnus will use a dribble file to store user updates.
-If Emacs should crash without saving the .newsrc files, complete
-information can be restored from the dribble file.")
-
-(defvar gnus-dribble-directory nil
- "*The directory where dribble files will be saved.
-If this variable is nil, the directory where the .newsrc files are
-saved will be used.")
-
-(defvar gnus-asynchronous nil
- "*If non-nil, Gnus will supply backends with data needed for async article fetching.")
-
-(defvar gnus-kill-summary-on-exit t
- "*If non-nil, kill the summary buffer when you exit from it.
-If nil, the summary will become a \"*Dead Summary*\" buffer, and
-it will be killed sometime later.")
-
-(defvar gnus-large-newsgroup 200
- "*The number of articles which indicates a large newsgroup.
-If the number of articles in a newsgroup is greater than this value,
-confirmation is required for selecting the newsgroup.")
-
-;; Suggested by Andrew Eskilsson <pi92ae@lelle.pt.hk-r.se>.
-(defvar gnus-no-groups-message "No news is horrible news"
- "*Message displayed by Gnus when no groups are available.")
-
-(defvar gnus-use-long-file-name (not (memq system-type '(usg-unix-v xenix)))
- "*Non-nil means that the default name of a file to save articles in is the group name.
-If it's nil, the directory form of the group name is used instead.
-
-If this variable is a list, and the list contains the element
-`not-score', long file names will not be used for score files; if it
-contains the element `not-save', long file names will not be used for
-saving; and if it contains the element `not-kill', long file names
-will not be used for kill files.
-
-Note that the default for this variable varies according to what system
-type you're using. On `usg-unix-v' and `xenix' this variable defaults
-to nil while on all other systems it defaults to t.")
-
-(defvar gnus-article-save-directory gnus-directory
- "*Name of the directory articles will be saved in (default \"~/News\").")
-
-(defvar gnus-kill-files-directory gnus-directory
- "*Name of the directory where kill files will be stored (default \"~/News\").")
-
-(defvar gnus-default-article-saver 'gnus-summary-save-in-rmail
- "*A function to save articles in your favorite format.
-The function must be interactively callable (in other words, it must
-be an Emacs command).
-
-Gnus provides the following functions:
-
-* gnus-summary-save-in-rmail (Rmail format)
-* gnus-summary-save-in-mail (Unix mail format)
-* gnus-summary-save-in-folder (MH folder)
-* gnus-summary-save-in-file (article format).
-* gnus-summary-save-in-vm (use VM's folder format).")
-
-(defvar gnus-prompt-before-saving 'always
- "*This variable says how much prompting is to be done when saving articles.
-If it is nil, no prompting will be done, and the articles will be
-saved to the default files. If this variable is `always', each and
-every article that is saved will be preceded by a prompt, even when
-saving large batches of articles. If this variable is neither nil not
-`always', there the user will be prompted once for a file name for
-each invocation of the saving commands.")
-
-(defvar gnus-rmail-save-name (function gnus-plain-save-name)
- "*A function generating a file name to save articles in Rmail format.
-The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE.")
-
-(defvar gnus-mail-save-name (function gnus-plain-save-name)
- "*A function generating a file name to save articles in Unix mail format.
-The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE.")
-
-(defvar gnus-folder-save-name (function gnus-folder-save-name)
- "*A function generating a file name to save articles in MH folder.
-The function is called with NEWSGROUP, HEADERS, and optional LAST-FOLDER.")
-
-(defvar gnus-file-save-name (function gnus-numeric-save-name)
- "*A function generating a file name to save articles in article format.
-The function is called with NEWSGROUP, HEADERS, and optional
-LAST-FILE.")
-
-(defvar gnus-split-methods
- '((gnus-article-archive-name))
- "*Variable used to suggest where articles are to be saved.
-For instance, if you would like to save articles related to Gnus in
-the file \"gnus-stuff\", and articles related to VM in \"vm-stuff\",
-you could set this variable to something like:
-
- '((\"^Subject:.*gnus\\|^Newsgroups:.*gnus\" \"gnus-stuff\")
- (\"^Subject:.*vm\\|^Xref:.*vm\" \"vm-stuff\"))
-
-This variable is an alist where the where the key is the match and the
-value is a list of possible files to save in if the match is non-nil.
-
-If the match is a string, it is used as a regexp match on the
-article. If the match is a symbol, that symbol will be funcalled
-from the buffer of the article to be saved with the newsgroup as the
-parameter. If it is a list, it will be evaled in the same buffer.
-
-If this form or function returns a string, this string will be used as
-a possible file name; and if it returns a non-nil list, that list will
-be used as possible file names.")
-
-(defvar gnus-move-split-methods nil
- "*Variable used to suggest where articles are to be moved to.
-It uses the same syntax as the `gnus-split-methods' variable.")
-
-(defvar gnus-save-score nil
- "*If non-nil, save group scoring info.")
-
-(defvar gnus-use-adaptive-scoring nil
- "*If non-nil, use some adaptive scoring scheme.")
-
-(defvar gnus-use-cache 'passive
- "*If nil, Gnus will ignore the article cache.
-If `passive', it will allow entering (and reading) articles
-explicitly entered into the cache. If anything else, use the
-cache to the full extent of the law.")
-
-(defvar gnus-use-trees nil
- "*If non-nil, display a thread tree buffer.")
-
-(defvar gnus-use-grouplens nil
- "*If non-nil, use GroupLens ratings.")
-
-(defvar gnus-keep-backlog nil
- "*If non-nil, Gnus will keep read articles for later re-retrieval.
-If it is a number N, then Gnus will only keep the last N articles
-read. If it is neither nil nor a number, Gnus will keep all read
-articles. This is not a good idea.")
-
-(defvar gnus-use-nocem nil
- "*If non-nil, Gnus will read NoCeM cancel messages.")
-
-(defvar gnus-use-demon nil
- "If non-nil, Gnus might use some demons.")
-
-(defvar gnus-use-scoring t
- "*If non-nil, enable scoring.")
-
-(defvar gnus-use-picons nil
- "*If non-nil, display picons.")
-
-(defvar gnus-fetch-old-headers nil
- "*Non-nil means that Gnus will try to build threads by grabbing old headers.
-If an unread article in the group refers to an older, already read (or
-just marked as read) article, the old article will not normally be
-displayed in the Summary buffer. If this variable is non-nil, Gnus
-will attempt to grab the headers to the old articles, and thereby
-build complete threads. If it has the value `some', only enough
-headers to connect otherwise loose threads will be displayed.
-This variable can also be a number. In that case, no more than that
-number of old headers will be fetched.
-
-The server has to support NOV for any of this to work.")
-
-;see gnus-cus.el
-;(defvar gnus-visual t
-; "*If non-nil, will do various highlighting.
-;If nil, no mouse highlights (or any other highlights) will be
-;performed. This might speed up Gnus some when generating large group
-;and summary buffers.")
-
-(defvar gnus-novice-user t
- "*Non-nil means that you are a usenet novice.
-If non-nil, verbose messages may be displayed and confirmations may be
-required.")
-
-(defvar gnus-expert-user nil
- "*Non-nil means that you will never be asked for confirmation about anything.
-And that means *anything*.")
-
-(defvar gnus-verbose 7
- "*Integer that says how verbose Gnus should be.
-The higher the number, the more messages Gnus will flash to say what
-it's doing. At zero, Gnus will be totally mute; at five, Gnus will
-display most important messages; and at ten, Gnus will keep on
-jabbering all the time.")
-
-(defvar gnus-keep-same-level nil
- "*Non-nil means that the next newsgroup after the current will be on the same level.
-When you type, for instance, `n' after reading the last article in the
-current newsgroup, you will go to the next newsgroup. If this variable
-is nil, the next newsgroup will be the next from the group
-buffer.
-If this variable is non-nil, Gnus will either put you in the
-next newsgroup with the same level, or, if no such newsgroup is
-available, the next newsgroup with the lowest possible level higher
-than the current level.
-If this variable is `best', Gnus will make the next newsgroup the one
-with the best level.")
-
-(defvar gnus-summary-make-false-root 'adopt
- "*nil means that Gnus won't gather loose threads.
-If the root of a thread has expired or been read in a previous
-session, the information necessary to build a complete thread has been
-lost. Instead of having many small sub-threads from this original thread
-scattered all over the summary buffer, Gnus can gather them.
-
-If non-nil, Gnus will try to gather all loose sub-threads from an
-original thread into one large thread.
-
-If this variable is non-nil, it should be one of `none', `adopt',
-`dummy' or `empty'.
-
-If this variable is `none', Gnus will not make a false root, but just
-present the sub-threads after another.
-If this variable is `dummy', Gnus will create a dummy root that will
-have all the sub-threads as children.
-If this variable is `adopt', Gnus will make one of the \"children\"
-the parent and mark all the step-children as such.
-If this variable is `empty', the \"children\" are printed with empty
-subject fields. (Or rather, they will be printed with a string
-given by the `gnus-summary-same-subject' variable.)")
-
-(defvar gnus-summary-gather-exclude-subject "^ *$\\|^(none)$"
- "*A regexp to match subjects to be excluded from loose thread gathering.
-As loose thread gathering is done on subjects only, that means that
-there can be many false gatherings performed. By rooting out certain
-common subjects, gathering might become saner.")
-
-(defvar gnus-summary-gather-subject-limit nil
- "*Maximum length of subject comparisons when gathering loose threads.
-Use nil to compare full subjects. Setting this variable to a low
-number will help gather threads that have been corrupted by
-newsreaders chopping off subject lines, but it might also mean that
-unrelated articles that have subject that happen to begin with the
-same few characters will be incorrectly gathered.
-
-If this variable is `fuzzy', Gnus will use a fuzzy algorithm when
-comparing subjects.")
-
-(defvar gnus-simplify-ignored-prefixes nil
- "*Regexp, matches for which are removed from subject lines when simplifying.")
-
-(defvar gnus-build-sparse-threads nil
- "*If non-nil, fill in the gaps in threads.
-If `some', only fill in the gaps that are needed to tie loose threads
-together. If `more', fill in all leaf nodes that Gnus can find. If
-non-nil and non-`some', fill in all gaps that Gnus manages to guess.")
-
-(defvar gnus-summary-thread-gathering-function 'gnus-gather-threads-by-subject
- "Function used for gathering loose threads.
-There are two pre-defined functions: `gnus-gather-threads-by-subject',
-which only takes Subjects into consideration; and
-`gnus-gather-threads-by-references', which compared the References
-headers of the articles to find matches.")
-
-;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
-(defvar gnus-summary-same-subject ""
- "*String indicating that the current article has the same subject as the previous.
-This variable will only be used if the value of
-`gnus-summary-make-false-root' is `empty'.")
-
-(defvar gnus-summary-goto-unread t
- "*If non-nil, marking commands will go to the next unread article.
-If `never', \\<gnus-summary-mode-map>\\[gnus-summary-next-page] will go to the next article,
-whether it is read or not.")
-
-(defvar gnus-group-goto-unread t
- "*If non-nil, movement commands will go to the next unread and subscribed group.")
-
-(defvar gnus-goto-next-group-when-activating t
- "*If non-nil, the \\<gnus-group-mode-map>\\[gnus-group-get-new-news-this-group] command will advance point to the next group.")
-
-(defvar gnus-check-new-newsgroups t
- "*Non-nil means that Gnus will add new newsgroups at startup.
-If this variable is `ask-server', Gnus will ask the server for new
-groups since the last time it checked. This means that the killed list
-is no longer necessary, so you could set `gnus-save-killed-list' to
-nil.
-
-A variant is to have this variable be a list of select methods. Gnus
-will then use the `ask-server' method on all these select methods to
-query for new groups from all those servers.
-
-Eg.
- (setq gnus-check-new-newsgroups
- '((nntp \"some.server\") (nntp \"other.server\")))
-
-If this variable is nil, then you have to tell Gnus explicitly to
-check for new newsgroups with \\<gnus-group-mode-map>\\[gnus-find-new-newsgroups].")
-
-(defvar gnus-check-bogus-newsgroups nil
- "*Non-nil means that Gnus will check and remove bogus newsgroup at startup.
-If this variable is nil, then you have to tell Gnus explicitly to
-check for bogus newsgroups with \\<gnus-group-mode-map>\\[gnus-group-check-bogus-groups].")
-
-(defvar gnus-read-active-file t
- "*Non-nil means that Gnus will read the entire active file at startup.
-If this variable is nil, Gnus will only know about the groups in your
-`.newsrc' file.
-
-If this variable is `some', Gnus will try to only read the relevant
-parts of the active file from the server. Not all servers support
-this, and it might be quite slow with other servers, but this should
-generally be faster than both the t and nil value.
-
-If you set this variable to nil or `some', you probably still want to
-be told about new newsgroups that arrive. To do that, set
-`gnus-check-new-newsgroups' to `ask-server'. This may not work
-properly with all servers.")
-
-(defvar gnus-level-subscribed 5
- "*Groups with levels less than or equal to this variable are subscribed.")
-
-(defvar gnus-level-unsubscribed 7
- "*Groups with levels less than or equal to this variable are unsubscribed.
-Groups with levels less than `gnus-level-subscribed', which should be
-less than this variable, are subscribed.")
-
-(defvar gnus-level-zombie 8
- "*Groups with this level are zombie groups.")
-
-(defvar gnus-level-killed 9
- "*Groups with this level are killed.")
-
-(defvar gnus-level-default-subscribed 3
- "*New subscribed groups will be subscribed at this level.")
-
-(defvar gnus-level-default-unsubscribed 6
- "*New unsubscribed groups will be unsubscribed at this level.")
-
-(defvar gnus-activate-level (1+ gnus-level-subscribed)
- "*Groups higher than this level won't be activated on startup.
-Setting this variable to something log might save lots of time when
-you have many groups that you aren't interested in.")
-
-(defvar gnus-activate-foreign-newsgroups 4
- "*If nil, Gnus will not check foreign newsgroups at startup.
-If it is non-nil, it should be a number between one and nine. Foreign
-newsgroups that have a level lower or equal to this number will be
-activated on startup. For instance, if you want to active all
-subscribed newsgroups, but not the rest, you'd set this variable to
-`gnus-level-subscribed'.
-
-If you subscribe to lots of newsgroups from different servers, startup
-might take a while. By setting this variable to nil, you'll save time,
-but you won't be told how many unread articles there are in the
-groups.")
-
-(defvar gnus-save-newsrc-file t
- "*Non-nil means that Gnus will save the `.newsrc' file.
-Gnus always saves its own startup file, which is called
-\".newsrc.eld\". The file called \".newsrc\" is in a format that can
-be readily understood by other newsreaders. If you don't plan on
-using other newsreaders, set this variable to nil to save some time on
-exit.")
-
-(defvar gnus-save-killed-list t
- "*If non-nil, save the list of killed groups to the startup file.
-If you set this variable to nil, you'll save both time (when starting
-and quitting) and space (both memory and disk), but it will also mean
-that Gnus has no record of which groups are new and which are old, so
-the automatic new newsgroups subscription methods become meaningless.
-
-You should always set `gnus-check-new-newsgroups' to `ask-server' or
-nil if you set this variable to nil.")
-
-(defvar gnus-interactive-catchup t
- "*If non-nil, require your confirmation when catching up a group.")
-
-(defvar gnus-interactive-exit t
- "*If non-nil, require your confirmation when exiting Gnus.")
-
-(defvar gnus-kill-killed t
- "*If non-nil, Gnus will apply kill files to already killed articles.
-If it is nil, Gnus will never apply kill files to articles that have
-already been through the scoring process, which might very well save lots
-of time.")
-
-(defvar gnus-extract-address-components 'gnus-extract-address-components
- "*Function for extracting address components from a From header.
-Two pre-defined function exist: `gnus-extract-address-components',
-which is the default, quite fast, and too simplistic solution, and
-`mail-extract-address-components', which works much better, but is
-slower.")
-
-(defvar gnus-summary-default-score 0
- "*Default article score level.
-If this variable is nil, scoring will be disabled.")
-
-(defvar gnus-summary-zcore-fuzz 0
- "*Fuzziness factor for the zcore in the summary buffer.
-Articles with scores closer than this to `gnus-summary-default-score'
-will not be marked.")
-
-(defvar gnus-simplify-subject-fuzzy-regexp nil
- "*Strings to be removed when doing fuzzy matches.
-This can either be a regular expression or list of regular expressions
-that will be removed from subject strings if fuzzy subject
-simplification is selected.")
-
-(defvar gnus-permanently-visible-groups nil
- "*Regexp to match groups that should always be listed in the group buffer.
-This means that they will still be listed when there are no unread
-articles in the groups.")
-
-(defvar gnus-list-groups-with-ticked-articles t
- "*If non-nil, list groups that have only ticked articles.
-If nil, only list groups that have unread articles.")
-
-(defvar gnus-group-default-list-level gnus-level-subscribed
- "*Default listing level.
-Ignored if `gnus-group-use-permanent-levels' is non-nil.")
-
-(defvar gnus-group-use-permanent-levels nil
- "*If non-nil, once you set a level, Gnus will use this level.")
-
-(defvar gnus-group-list-inactive-groups t
- "*If non-nil, inactive groups will be listed.")
-
-(defvar gnus-show-mime nil
- "*If non-nil, do mime processing of articles.
-The articles will simply be fed to the function given by
-`gnus-show-mime-method'.")
-
-(defvar gnus-strict-mime t
- "*If nil, MIME-decode even if there is no Mime-Version header in the article.")
-
-(defvar gnus-show-mime-method 'metamail-buffer
- "*Function to process a MIME message.
-The function is called from the article buffer.")
-
-(defvar gnus-decode-encoded-word-method (lambda ())
- "*Function to decode a MIME encoded-words.
-The function is called from the article buffer.")
-
-(defvar gnus-show-threads t
- "*If non-nil, display threads in summary mode.")
-
-(defvar gnus-thread-hide-subtree nil
- "*If non-nil, hide all threads initially.
-If threads are hidden, you have to run the command
-`gnus-summary-show-thread' by hand or use `gnus-select-article-hook'
-to expose hidden threads.")
-
-(defvar gnus-thread-hide-killed t
- "*If non-nil, hide killed threads automatically.")
-
-(defvar gnus-thread-ignore-subject nil
- "*If non-nil, ignore subjects and do all threading based on the Reference header.
-If nil, which is the default, articles that have different subjects
-from their parents will start separate threads.")
-
-(defvar gnus-thread-operation-ignore-subject t
- "*If non-nil, subjects will be ignored when doing thread commands.
-This affects commands like `gnus-summary-kill-thread' and
-`gnus-summary-lower-thread'.
-
-If this variable is nil, articles in the same thread with different
-subjects will not be included in the operation in question. If this
-variable is `fuzzy', only articles that have subjects that are fuzzily
-equal will be included.")
-
-(defvar gnus-thread-indent-level 4
- "*Number that says how much each sub-thread should be indented.")
-
-(defvar gnus-ignored-newsgroups
- (purecopy (mapconcat 'identity
- '("^to\\." ; not "real" groups
- "^[0-9. \t]+ " ; all digits in name
- "[][\"#'()]" ; bogus characters
- )
- "\\|"))
- "*A regexp to match uninteresting newsgroups in the active file.
-Any lines in the active file matching this regular expression are
-removed from the newsgroup list before anything else is done to it,
-thus making them effectively non-existent.")
-
-(defvar gnus-ignored-headers
- "^Path:\\|^Posting-Version:\\|^Article-I.D.:\\|^Expires:\\|^Date-Received:\\|^References:\\|^Control:\\|^Xref:\\|^Lines:\\|^Posted:\\|^Relay-Version:\\|^Message-ID:\\|^Nf-ID:\\|^Nf-From:\\|^Approved:\\|^Sender:\\|^Received:\\|^Mail-from:"
- "*All headers that match this regexp will be hidden.
-This variable can also be a list of regexps of headers to be ignored.
-If `gnus-visible-headers' is non-nil, this variable will be ignored.")
-
-(defvar gnus-visible-headers "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-"
- "*All headers that do not match this regexp will be hidden.
-This variable can also be a list of regexp of headers to remain visible.
-If this variable is non-nil, `gnus-ignored-headers' will be ignored.")
-
-(defvar gnus-sorted-header-list
- '("^From:" "^Subject:" "^Summary:" "^Keywords:" "^Newsgroups:" "^To:"
- "^Cc:" "^Date:" "^Organization:")
- "*This variable is a list of regular expressions.
-If it is non-nil, headers that match the regular expressions will
-be placed first in the article buffer in the sequence specified by
-this list.")
-
-(defvar gnus-boring-article-headers
- '(empty followup-to reply-to)
- "*Headers that are only to be displayed if they have interesting data.
-Possible values in this list are `empty', `newsgroups', `followup-to',
-`reply-to', and `date'.")
-
-(defvar gnus-show-all-headers nil
- "*If non-nil, don't hide any headers.")
-
-(defvar gnus-save-all-headers t
- "*If non-nil, don't remove any headers before saving.")
-
-(defvar gnus-saved-headers gnus-visible-headers
- "*Headers to keep if `gnus-save-all-headers' is nil.
-If `gnus-save-all-headers' is non-nil, this variable will be ignored.
-If that variable is nil, however, all headers that match this regexp
-will be kept while the rest will be deleted before saving.")
-
-(defvar gnus-inhibit-startup-message nil
- "*If non-nil, the startup message will not be displayed.")
-
-(defvar gnus-signature-separator "^-- *$"
- "Regexp matching signature separator.")
-
-(defvar gnus-signature-limit nil
- "Provide a limit to what is considered a signature.
-If it is a number, no signature may not be longer (in characters) than
-that number. If it is a function, the function will be called without
-any parameters, and if it returns nil, there is no signature in the
-buffer. If it is a string, it will be used as a regexp. If it
-matches, the text in question is not a signature.")
-
-(defvar gnus-auto-extend-newsgroup t
- "*If non-nil, extend newsgroup forward and backward when requested.")
-
-(defvar gnus-auto-select-first t
- "*If nil, don't select the first unread article when entering a group.
-If this variable is `best', select the highest-scored unread article
-in the group. If neither nil nor `best', select the first unread
-article.
-
-If you want to prevent automatic selection of the first unread article
-in some newsgroups, set the variable to nil in
-`gnus-select-group-hook'.")
-
-(defvar gnus-auto-select-next t
- "*If non-nil, offer to go to the next group from the end of the previous.
-If the value is t and the next newsgroup is empty, Gnus will exit
-summary mode and go back to group mode. If the value is neither nil
-nor t, Gnus will select the following unread newsgroup. In
-particular, if the value is the symbol `quietly', the next unread
-newsgroup will be selected without any confirmation, and if it is
-`almost-quietly', the next group will be selected without any
-confirmation if you are located on the last article in the group.
-Finally, if this variable is `slightly-quietly', the `Z n' command
-will go to the next group without confirmation.")
-
-(defvar gnus-auto-select-same nil
- "*If non-nil, select the next article with the same subject.")
-
-(defvar gnus-summary-check-current nil
- "*If non-nil, consider the current article when moving.
-The \"unread\" movement commands will stay on the same line if the
-current article is unread.")
-
-(defvar gnus-auto-center-summary t
- "*If non-nil, always center the current summary buffer.
-In particular, if `vertical' do only vertical recentering. If non-nil
-and non-`vertical', do both horizontal and vertical recentering.")
-
-(defvar gnus-break-pages t
- "*If non-nil, do page breaking on articles.
-The page delimiter is specified by the `gnus-page-delimiter'
-variable.")
-
-(defvar gnus-page-delimiter "^\^L"
- "*Regexp describing what to use as article page delimiters.
-The default value is \"^\^L\", which is a form linefeed at the
-beginning of a line.")
-
-(defvar gnus-use-full-window t
- "*If non-nil, use the entire Emacs screen.")
-
-(defvar gnus-window-configuration nil
- "Obsolete variable. See `gnus-buffer-configuration'.")
-
-(defvar gnus-window-min-width 2
- "*Minimum width of Gnus buffers.")
-
-(defvar gnus-window-min-height 1
- "*Minimum height of Gnus buffers.")
-
-(defvar gnus-buffer-configuration
- '((group
- (vertical 1.0
- (group 1.0 point)
- (if gnus-carpal '(group-carpal 4))))
- (summary
- (vertical 1.0
- (summary 1.0 point)
- (if gnus-carpal '(summary-carpal 4))))
- (article
- (cond
- (gnus-use-picons
- '(frame 1.0
- (vertical 1.0
- (summary 0.25 point)
- (if gnus-carpal '(summary-carpal 4))
- (article 1.0))
- (vertical ((height . 5) (width . 15)
- (user-position . t)
- (left . -1) (top . 1))
- (picons 1.0))))
- (gnus-use-trees
- '(vertical 1.0
- (summary 0.25 point)
- (tree 0.25)
- (article 1.0)))
- (t
- '(vertical 1.0
- (summary 0.25 point)
- (if gnus-carpal '(summary-carpal 4))
- (article 1.0)))))
- (server
- (vertical 1.0
- (server 1.0 point)
- (if gnus-carpal '(server-carpal 2))))
- (browse
- (vertical 1.0
- (browse 1.0 point)
- (if gnus-carpal '(browse-carpal 2))))
- (message
- (vertical 1.0
- (message 1.0 point)))
- (pick
- (vertical 1.0
- (article 1.0 point)))
- (info
- (vertical 1.0
- (info 1.0 point)))
- (summary-faq
- (vertical 1.0
- (summary 0.25)
- (faq 1.0 point)))
- (edit-group
- (vertical 1.0
- (group 0.5)
- (edit-group 1.0 point)))
- (edit-server
- (vertical 1.0
- (server 0.5)
- (edit-server 1.0 point)))
- (edit-score
- (vertical 1.0
- (summary 0.25)
- (edit-score 1.0 point)))
- (post
- (vertical 1.0
- (post 1.0 point)))
- (reply
- (vertical 1.0
- (article-copy 0.5)
- (message 1.0 point)))
- (forward
- (vertical 1.0
- (message 1.0 point)))
- (reply-yank
- (vertical 1.0
- (message 1.0 point)))
- (mail-bounce
- (vertical 1.0
- (article 0.5)
- (message 1.0 point)))
- (draft
- (vertical 1.0
- (draft 1.0 point)))
- (pipe
- (vertical 1.0
- (summary 0.25 point)
- (if gnus-carpal '(summary-carpal 4))
- ("*Shell Command Output*" 1.0)))
- (bug
- (vertical 1.0
- ("*Gnus Help Bug*" 0.5)
- ("*Gnus Bug*" 1.0 point)))
- (compose-bounce
- (vertical 1.0
- (article 0.5)
- (message 1.0 point))))
- "Window configuration for all possible Gnus buffers.
-This variable is a list of lists. Each of these lists has a NAME and
-a RULE. The NAMEs are commonsense names like `group', which names a
-rule used when displaying the group buffer; `summary', which names a
-rule for what happens when you enter a group and do not display an
-article buffer; and so on. See the value of this variable for a
-complete list of NAMEs.
-
-Each RULE is a list of vectors. The first element in this vector is
-the name of the buffer to be displayed; the second element is the
-percentage of the screen this buffer is to occupy (a number in the
-0.0-0.99 range); the optional third element is `point', which should
-be present to denote which buffer point is to go to after making this
-buffer configuration.")
-
-(defvar gnus-window-to-buffer
- '((group . gnus-group-buffer)
- (summary . gnus-summary-buffer)
- (article . gnus-article-buffer)
- (server . gnus-server-buffer)
- (browse . "*Gnus Browse Server*")
- (edit-group . gnus-group-edit-buffer)
- (edit-server . gnus-server-edit-buffer)
- (group-carpal . gnus-carpal-group-buffer)
- (summary-carpal . gnus-carpal-summary-buffer)
- (server-carpal . gnus-carpal-server-buffer)
- (browse-carpal . gnus-carpal-browse-buffer)
- (edit-score . gnus-score-edit-buffer)
- (message . gnus-message-buffer)
- (mail . gnus-message-buffer)
- (post-news . gnus-message-buffer)
- (faq . gnus-faq-buffer)
- (picons . "*Picons*")
- (tree . gnus-tree-buffer)
- (info . gnus-info-buffer)
- (article-copy . gnus-article-copy)
- (draft . gnus-draft-buffer))
- "Mapping from short symbols to buffer names or buffer variables.")
-
-(defvar gnus-carpal nil
- "*If non-nil, display clickable icons.")
-
-(defvar gnus-subscribe-newsgroup-method 'gnus-subscribe-zombies
- "*Function called with a group name when new group is detected.
-A few pre-made functions are supplied: `gnus-subscribe-randomly'
-inserts new groups at the beginning of the list of groups;
-`gnus-subscribe-alphabetically' inserts new groups in strict
-alphabetic order; `gnus-subscribe-hierarchically' inserts new groups
-in hierarchical newsgroup order; `gnus-subscribe-interactively' asks
-for your decision; `gnus-subscribe-killed' kills all new groups;
-`gnus-subscribe-zombies' will make all new groups into zombies.")
-
-;; Suggested by a bug report by Hallvard B Furuseth.
-;; <h.b.furuseth@usit.uio.no>.
-(defvar gnus-subscribe-options-newsgroup-method
- (function gnus-subscribe-alphabetically)
- "*This function is called to subscribe newsgroups mentioned on \"options -n\" lines.
-If, for instance, you want to subscribe to all newsgroups in the
-\"no\" and \"alt\" hierarchies, you'd put the following in your
-.newsrc file:
-
-options -n no.all alt.all
-
-Gnus will the subscribe all new newsgroups in these hierarchies with
-the subscription method in this variable.")
-
-(defvar gnus-subscribe-hierarchical-interactive nil
- "*If non-nil, Gnus will offer to subscribe hierarchically.
-When a new hierarchy appears, Gnus will ask the user:
-
-'alt.binaries': Do you want to subscribe to this hierarchy? ([d]ys):
-
-If the user pressed `d', Gnus will descend the hierarchy, `y' will
-subscribe to all newsgroups in the hierarchy and `s' will skip this
-hierarchy in its entirety.")
-
-(defvar gnus-group-sort-function 'gnus-group-sort-by-alphabet
- "*Function used for sorting the group buffer.
-This function will be called with group info entries as the arguments
-for the groups to be sorted. Pre-made functions include
-`gnus-group-sort-by-alphabet', `gnus-group-sort-by-unread',
-`gnus-group-sort-by-level', `gnus-group-sort-by-score', and
-`gnus-group-sort-by-rank'.
-
-This variable can also be a list of sorting functions. In that case,
-the most significant sort function should be the last function in the
-list.")
-
-;; Mark variables suggested by Thomas Michanek
-;; <Thomas.Michanek@telelogic.se>.
-(defvar gnus-unread-mark ?
- "*Mark used for unread articles.")
-(defvar gnus-ticked-mark ?!
- "*Mark used for ticked articles.")
-(defvar gnus-dormant-mark ??
- "*Mark used for dormant articles.")
-(defvar gnus-del-mark ?r
- "*Mark used for del'd articles.")
-(defvar gnus-read-mark ?R
- "*Mark used for read articles.")
-(defvar gnus-expirable-mark ?E
- "*Mark used for expirable articles.")
-(defvar gnus-killed-mark ?K
- "*Mark used for killed articles.")
-(defvar gnus-souped-mark ?F
- "*Mark used for killed articles.")
-(defvar gnus-kill-file-mark ?X
- "*Mark used for articles killed by kill files.")
-(defvar gnus-low-score-mark ?Y
- "*Mark used for articles with a low score.")
-(defvar gnus-catchup-mark ?C
- "*Mark used for articles that are caught up.")
-(defvar gnus-replied-mark ?A
- "*Mark used for articles that have been replied to.")
-(defvar gnus-cached-mark ?*
- "*Mark used for articles that are in the cache.")
-(defvar gnus-saved-mark ?S
- "*Mark used for articles that have been saved to.")
-(defvar gnus-process-mark ?#
- "*Process mark.")
-(defvar gnus-ancient-mark ?O
- "*Mark used for ancient articles.")
-(defvar gnus-sparse-mark ?Q
- "*Mark used for sparsely reffed articles.")
-(defvar gnus-canceled-mark ?G
- "*Mark used for canceled articles.")
-(defvar gnus-score-over-mark ?+
- "*Score mark used for articles with high scores.")
-(defvar gnus-score-below-mark ?-
- "*Score mark used for articles with low scores.")
-(defvar gnus-empty-thread-mark ?
- "*There is no thread under the article.")
-(defvar gnus-not-empty-thread-mark ?=
- "*There is a thread under the article.")
-
-(defvar gnus-view-pseudo-asynchronously nil
- "*If non-nil, Gnus will view pseudo-articles asynchronously.")
-
-(defvar gnus-view-pseudos nil
- "*If `automatic', pseudo-articles will be viewed automatically.
-If `not-confirm', pseudos will be viewed automatically, and the user
-will not be asked to confirm the command.")
-
-(defvar gnus-view-pseudos-separately t
- "*If non-nil, one pseudo-article will be created for each file to be viewed.
-If nil, all files that use the same viewing command will be given as a
-list of parameters to that command.")
-
-(defvar gnus-insert-pseudo-articles t
- "*If non-nil, insert pseudo-articles when decoding articles.")
-
-(defvar gnus-group-line-format "%M%S%p%P%5y: %(%g%)%l\n"
- "*Format of group lines.
-It works along the same lines as a normal formatting string,
-with some simple extensions.
-
-%M Only marked articles (character, \"*\" or \" \")
-%S Whether the group is subscribed (character, \"U\", \"K\", \"Z\" or \" \")
-%L Level of subscribedness (integer)
-%N Number of unread articles (integer)
-%I Number of dormant articles (integer)
-%i Number of ticked and dormant (integer)
-%T Number of ticked articles (integer)
-%R Number of read articles (integer)
-%t Total number of articles (integer)
-%y Number of unread, unticked articles (integer)
-%G Group name (string)
-%g Qualified group name (string)
-%D Group description (string)
-%s Select method (string)
-%o Moderated group (char, \"m\")
-%p Process mark (char)
-%O Moderated group (string, \"(m)\" or \"\")
-%P Topic indentation (string)
-%l Whether there are GroupLens predictions for this group (string)
-%n Select from where (string)
-%z A string that look like `<%s:%n>' if a foreign select method is used
-%u User defined specifier. The next character in the format string should
- be a letter. Gnus will call the function gnus-user-format-function-X,
- where X is the letter following %u. The function will be passed the
- current header as argument. The function should return a string, which
- will be inserted into the buffer just like information from any other
- group specifier.
-
-Text between %( and %) will be highlighted with `gnus-mouse-face' when
-the mouse point move inside the area. There can only be one such area.
-
-Note that this format specification is not always respected. For
-reasons of efficiency, when listing killed groups, this specification
-is ignored altogether. If the spec is changed considerably, your
-output may end up looking strange when listing both alive and killed
-groups.
-
-If you use %o or %O, reading the active file will be slower and quite
-a bit of extra memory will be used. %D will also worsen performance.
-Also note that if you change the format specification to include any
-of these specs, you must probably re-start Gnus to see them go into
-effect.")
-
-(defvar gnus-summary-line-format "%U%R%z%I%(%[%4L: %-20,20n%]%) %s\n"
- "*The format specification of the lines in the summary buffer.
-
-It works along the same lines as a normal formatting string,
-with some simple extensions.
-
-%N Article number, left padded with spaces (string)
-%S Subject (string)
-%s Subject if it is at the root of a thread, and \"\" otherwise (string)
-%n Name of the poster (string)
-%a Extracted name of the poster (string)
-%A Extracted address of the poster (string)
-%F Contents of the From: header (string)
-%x Contents of the Xref: header (string)
-%D Date of the article (string)
-%d Date of the article (string) in DD-MMM format
-%M Message-id of the article (string)
-%r References of the article (string)
-%c Number of characters in the article (integer)
-%L Number of lines in the article (integer)
-%I Indentation based on thread level (a string of spaces)
-%T A string with two possible values: 80 spaces if the article
- is on thread level two or larger and 0 spaces on level one
-%R \"A\" if this article has been replied to, \" \" otherwise (character)
-%U Status of this article (character, \"R\", \"K\", \"-\" or \" \")
-%[ Opening bracket (character, \"[\" or \"<\")
-%] Closing bracket (character, \"]\" or \">\")
-%> Spaces of length thread-level (string)
-%< Spaces of length (- 20 thread-level) (string)
-%i Article score (number)
-%z Article zcore (character)
-%t Number of articles under the current thread (number).
-%e Whether the thread is empty or not (character).
-%l GroupLens score (string).
-%u User defined specifier. The next character in the format string should
- be a letter. Gnus will call the function gnus-user-format-function-X,
- where X is the letter following %u. The function will be passed the
- current header as argument. The function should return a string, which
- will be inserted into the summary just like information from any other
- summary specifier.
-
-Text between %( and %) will be highlighted with `gnus-mouse-face'
-when the mouse point is placed inside the area. There can only be one
-such area.
-
-The %U (status), %R (replied) and %z (zcore) specs have to be handled
-with care. For reasons of efficiency, Gnus will compute what column
-these characters will end up in, and \"hard-code\" that. This means that
-it is illegal to have these specs after a variable-length spec. Well,
-you might not be arrested, but your summary buffer will look strange,
-which is bad enough.
-
-The smart choice is to have these specs as for to the left as
-possible.
-
-This restriction may disappear in later versions of Gnus.")
-
-(defvar gnus-summary-dummy-line-format
- "* %(: :%) %S\n"
- "*The format specification for the dummy roots in the summary buffer.
-It works along the same lines as a normal formatting string,
-with some simple extensions.
-
-%S The subject")
-
-(defvar gnus-summary-mode-line-format "Gnus: %%b [%A] %Z"
- "*The format specification for the summary mode line.
-It works along the same lines as a normal formatting string,
-with some simple extensions:
-
-%G Group name
-%p Unprefixed group name
-%A Current article number
-%V Gnus version
-%U Number of unread articles in the group
-%e Number of unselected articles in the group
-%Z A string with unread/unselected article counts
-%g Shortish group name
-%S Subject of the current article
-%u User-defined spec
-%s Current score file name
-%d Number of dormant articles
-%r Number of articles that have been marked as read in this session
-%E Number of articles expunged by the score files")
-
-(defvar gnus-article-mode-line-format "Gnus: %%b %S"
- "*The format specification for the article mode line.
-See `gnus-summary-mode-line-format' for a closer description.")
-
-(defvar gnus-group-mode-line-format "Gnus: %%b {%M%:%S}"
- "*The format specification for the group mode line.
-It works along the same lines as a normal formatting string,
-with some simple extensions:
-
-%S The native news server.
-%M The native select method.
-%: \":\" if %S isn't \"\".")
-
-(defvar gnus-valid-select-methods
- '(("nntp" post address prompt-address)
- ("nnspool" post address)
- ("nnvirtual" post-mail virtual prompt-address)
- ("nnmbox" mail respool address)
- ("nnml" mail respool address)
- ("nnmh" mail respool address)
- ("nndir" post-mail prompt-address address)
- ("nneething" none address prompt-address)
- ("nndoc" none address prompt-address)
- ("nnbabyl" mail address respool)
- ("nnkiboze" post virtual)
- ("nnsoup" post-mail address)
- ("nndraft" post-mail)
- ("nnfolder" mail respool address))
- "An alist of valid select methods.
-The first element of each list lists should be a string with the name
-of the select method. The other elements may be be the category of
-this method (ie. `post', `mail', `none' or whatever) or other
-properties that this method has (like being respoolable).
-If you implement a new select method, all you should have to change is
-this variable. I think.")
-
-(defvar gnus-updated-mode-lines '(group article summary tree)
- "*List of buffers that should update their mode lines.
-The list may contain the symbols `group', `article' and `summary'. If
-the corresponding symbol is present, Gnus will keep that mode line
-updated with information that may be pertinent.
-If this variable is nil, screen refresh may be quicker.")
-
-;; Added by Keinonen Kari <kk85613@cs.tut.fi>.
-(defvar gnus-mode-non-string-length nil
- "*Max length of mode-line non-string contents.
-If this is nil, Gnus will take space as is needed, leaving the rest
-of the modeline intact.")
-
-;see gnus-cus.el
-;(defvar gnus-mouse-face 'highlight
-; "*Face used for mouse highlighting in Gnus.
-;No mouse highlights will be done if `gnus-visual' is nil.")
-
-(defvar gnus-summary-mark-below 0
- "*Mark all articles with a score below this variable as read.
-This variable is local to each summary buffer and usually set by the
-score file.")
-
-(defvar gnus-article-sort-functions '(gnus-article-sort-by-number)
- "*List of functions used for sorting articles in the summary buffer.
-This variable is only used when not using a threaded display.")
-
-(defvar gnus-thread-sort-functions '(gnus-thread-sort-by-number)
- "*List of functions used for sorting threads in the summary buffer.
-By default, threads are sorted by article number.
-
-Each function takes two threads and return non-nil if the first thread
-should be sorted before the other. If you use more than one function,
-the primary sort function should be the last. You should probably
-always include `gnus-thread-sort-by-number' in the list of sorting
-functions -- preferably first.
-
-Ready-mady functions include `gnus-thread-sort-by-number',
-`gnus-thread-sort-by-author', `gnus-thread-sort-by-subject',
-`gnus-thread-sort-by-date', `gnus-thread-sort-by-score' and
-`gnus-thread-sort-by-total-score' (see `gnus-thread-score-function').")
-
-(defvar gnus-thread-score-function '+
- "*Function used for calculating the total score of a thread.
-
-The function is called with the scores of the article and each
-subthread and should then return the score of the thread.
-
-Some functions you can use are `+', `max', or `min'.")
-
-(defvar gnus-summary-expunge-below nil
- "All articles that have a score less than this variable will be expunged.")
-
-(defvar gnus-thread-expunge-below nil
- "All threads that have a total score less than this variable will be expunged.
-See `gnus-thread-score-function' for en explanation of what a
-\"thread score\" is.")
-
-(defvar gnus-auto-subscribed-groups
- "^nnml\\|^nnfolder\\|^nnmbox\\|^nnmh\\|^nnbabyl"
- "*All new groups that match this regexp will be subscribed automatically.
-Note that this variable only deals with new groups. It has no effect
-whatsoever on old groups.
-
-New groups that match this regexp will not be handled by
-`gnus-subscribe-newsgroup-method'. Instead, they will
-be subscribed using `gnus-subscribe-options-newsgroup-method'.")
-
-(defvar gnus-options-subscribe nil
- "*All new groups matching this regexp will be subscribed unconditionally.
-Note that this variable deals only with new newsgroups. This variable
-does not affect old newsgroups.
-
-New groups that match this regexp will not be handled by
-`gnus-subscribe-newsgroup-method'. Instead, they will
-be subscribed using `gnus-subscribe-options-newsgroup-method'.")
-
-(defvar gnus-options-not-subscribe nil
- "*All new groups matching this regexp will be ignored.
-Note that this variable deals only with new newsgroups. This variable
-does not affect old (already subscribed) newsgroups.")
-
-(defvar gnus-auto-expirable-newsgroups nil
- "*Groups in which to automatically mark read articles as expirable.
-If non-nil, this should be a regexp that should match all groups in
-which to perform auto-expiry. This only makes sense for mail groups.")
-
-(defvar gnus-total-expirable-newsgroups nil
- "*Groups in which to perform expiry of all read articles.
-Use with extreme caution. All groups that match this regexp will be
-expiring - which means that all read articles will be deleted after
-(say) one week. (This only goes for mail groups and the like, of
-course.)")
-
-(defvar gnus-group-uncollapsed-levels 1
- "Number of group name elements to leave alone when making a short group name.")
-
-(defvar gnus-hidden-properties '(invisible t intangible t)
- "Property list to use for hiding text.")
-
-(defvar gnus-modtime-botch nil
- "*Non-nil means .newsrc should be deleted prior to save.
-Its use is due to the bogus appearance that .newsrc was modified on
-disc.")
-
-;; Hooks.
-
-(defvar gnus-group-mode-hook nil
- "*A hook for Gnus group mode.")
-
-(defvar gnus-summary-mode-hook nil
- "*A hook for Gnus summary mode.
-This hook is run before any variables are set in the summary buffer.")
-
-(defvar gnus-article-mode-hook nil
- "*A hook for Gnus article mode.")
-
-(defvar gnus-summary-prepare-exit-hook nil
- "*A hook called when preparing to exit from the summary buffer.
-It calls `gnus-summary-expire-articles' by default.")
-(add-hook 'gnus-summary-prepare-exit-hook 'gnus-summary-expire-articles)
-
-(defvar gnus-summary-exit-hook nil
- "*A hook called on exit from the summary buffer.")
-
-(defvar gnus-group-catchup-group-hook nil
- "*A hook run when catching up a group from the group buffer.")
-
-(defvar gnus-group-update-group-hook nil
- "*A hook called when updating group lines.")
-
-(defvar gnus-open-server-hook nil
- "*A hook called just before opening connection to the news server.")
-
-(defvar gnus-load-hook nil
- "*A hook run while Gnus is loaded.")
-
-(defvar gnus-startup-hook nil
- "*A hook called at startup.
-This hook is called after Gnus is connected to the NNTP server.")
-
-(defvar gnus-get-new-news-hook nil
- "*A hook run just before Gnus checks for new news.")
-
-(defvar gnus-after-getting-new-news-hook nil
- "*A hook run after Gnus checks for new news.")
-
-(defvar gnus-group-prepare-function 'gnus-group-prepare-flat
- "*A function that is called to generate the group buffer.
-The function is called with three arguments: The first is a number;
-all group with a level less or equal to that number should be listed,
-if the second is non-nil, empty groups should also be displayed. If
-the third is non-nil, it is a number. No groups with a level lower
-than this number should be displayed.
-
-The only current function implemented is `gnus-group-prepare-flat'.")
-
-(defvar gnus-group-prepare-hook nil
- "*A hook called after the group buffer has been generated.
-If you want to modify the group buffer, you can use this hook.")
-
-(defvar gnus-summary-prepare-hook nil
- "*A hook called after the summary buffer has been generated.
-If you want to modify the summary buffer, you can use this hook.")
-
-(defvar gnus-summary-generate-hook nil
- "*A hook run just before generating the summary buffer.
-This hook is commonly used to customize threading variables and the
-like.")
-
-(defvar gnus-article-prepare-hook nil
- "*A hook called after an article has been prepared in the article buffer.
-If you want to run a special decoding program like nkf, use this hook.")
-
-;(defvar gnus-article-display-hook nil
-; "*A hook called after the article is displayed in the article buffer.
-;The hook is designed to change the contents of the article
-;buffer. Typical functions that this hook may contain are
-;`gnus-article-hide-headers' (hide selected headers),
-;`gnus-article-maybe-highlight' (perform fancy article highlighting),
-;`gnus-article-hide-signature' (hide signature) and
-;`gnus-article-treat-overstrike' (turn \"^H_\" into bold characters).")
-;(add-hook 'gnus-article-display-hook 'gnus-article-hide-headers-if-wanted)
-;(add-hook 'gnus-article-display-hook 'gnus-article-treat-overstrike)
-;(add-hook 'gnus-article-display-hook 'gnus-article-maybe-highlight)
-
-(defvar gnus-article-x-face-too-ugly nil
- "Regexp matching posters whose face shouldn't be shown automatically.")
-
-(defvar gnus-select-group-hook nil
- "*A hook called when a newsgroup is selected.
-
-If you'd like to simplify subjects like the
-`gnus-summary-next-same-subject' command does, you can use the
-following hook:
-
- (setq gnus-select-group-hook
- (list
- (lambda ()
- (mapcar (lambda (header)
- (mail-header-set-subject
- header
- (gnus-simplify-subject
- (mail-header-subject header) 're-only)))
- gnus-newsgroup-headers))))")
-
-(defvar gnus-select-article-hook nil
- "*A hook called when an article is selected.")
-
-(defvar gnus-apply-kill-hook '(gnus-apply-kill-file)
- "*A hook called to apply kill files to a group.
-This hook is intended to apply a kill file to the selected newsgroup.
-The function `gnus-apply-kill-file' is called by default.
-
-Since a general kill file is too heavy to use only for a few
-newsgroups, I recommend you to use a lighter hook function. For
-example, if you'd like to apply a kill file to articles which contains
-a string `rmgroup' in subject in newsgroup `control', you can use the
-following hook:
-
- (setq gnus-apply-kill-hook
- (list
- (lambda ()
- (cond ((string-match \"control\" gnus-newsgroup-name)
- (gnus-kill \"Subject\" \"rmgroup\")
- (gnus-expunge \"X\"))))))")
-
-(defvar gnus-visual-mark-article-hook
- (list 'gnus-highlight-selected-summary)
- "*Hook run after selecting an article in the summary buffer.
-It is meant to be used for highlighting the article in some way. It
-is not run if `gnus-visual' is nil.")
-
-(defvar gnus-parse-headers-hook nil
- "*A hook called before parsing the headers.")
-(add-hook 'gnus-parse-headers-hook 'gnus-decode-rfc1522)
-
-(defvar gnus-exit-group-hook nil
- "*A hook called when exiting (not quitting) summary mode.")
-
-(defvar gnus-suspend-gnus-hook nil
- "*A hook called when suspending (not exiting) Gnus.")
-
-(defvar gnus-exit-gnus-hook nil
- "*A hook called when exiting Gnus.")
-
-(defvar gnus-after-exiting-gnus-hook nil
- "*A hook called after exiting Gnus.")
-
-(defvar gnus-save-newsrc-hook nil
- "*A hook called before saving any of the newsrc files.")
-
-(defvar gnus-save-quick-newsrc-hook nil
- "*A hook called just before saving the quick newsrc file.
-Can be used to turn version control on or off.")
-
-(defvar gnus-save-standard-newsrc-hook nil
- "*A hook called just before saving the standard newsrc file.
-Can be used to turn version control on or off.")
-
-(defvar gnus-summary-update-hook
- (list 'gnus-summary-highlight-line)
- "*A hook called when a summary line is changed.
-The hook will not be called if `gnus-visual' is nil.
-
-The default function `gnus-summary-highlight-line' will
-highlight the line according to the `gnus-summary-highlight'
-variable.")
-
-(defvar gnus-group-update-hook '(gnus-group-highlight-line)
- "*A hook called when a group line is changed.
-The hook will not be called if `gnus-visual' is nil.
-
-The default function `gnus-group-highlight-line' will
-highlight the line according to the `gnus-group-highlight'
-variable.")
-
-(defvar gnus-mark-article-hook '(gnus-summary-mark-read-and-unread-as-read)
- "*A hook called when an article is selected for the first time.
-The hook is intended to mark an article as read (or unread)
-automatically when it is selected.")
-
-(defvar gnus-group-change-level-function nil
- "Function run when a group level is changed.
-It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
-
-;; Remove any hilit infestation.
-(add-hook 'gnus-startup-hook
- (lambda ()
- (remove-hook 'gnus-summary-prepare-hook
- 'hilit-rehighlight-buffer-quietly)
- (remove-hook 'gnus-summary-prepare-hook 'hilit-install-line-hooks)
- (setq gnus-mark-article-hook
- '(gnus-summary-mark-read-and-unread-as-read))
- (remove-hook 'gnus-article-prepare-hook
- 'hilit-rehighlight-buffer-quietly)))
-
-
-;; Internal variables
-
-(defvar gnus-tree-buffer "*Tree*"
- "Buffer where Gnus thread trees are displayed.")
-
-;; Dummy variable.
-(defvar gnus-use-generic-from nil)
-
-(defvar gnus-thread-indent-array nil)
-(defvar gnus-thread-indent-array-level gnus-thread-indent-level)
-
-(defvar gnus-newsrc-file-version nil)
-
-(defvar gnus-method-history nil)
-;; Variable holding the user answers to all method prompts.
-
-(defvar gnus-group-history nil)
-;; Variable holding the user answers to all group prompts.
-
-(defvar gnus-server-alist nil
- "List of available servers.")
-
-(defvar gnus-group-indentation-function nil)
-
-(defvar gnus-topic-indentation "") ;; Obsolete variable.
-
-(defvar gnus-goto-missing-group-function nil)
-
-(defvar gnus-override-subscribe-method nil)
-
-(defvar gnus-group-goto-next-group-function nil
- "Function to override finding the next group after listing groups.")
-
-(defconst gnus-article-mark-lists
- '((marked . tick) (replied . reply)
- (expirable . expire) (killed . killed)
- (bookmarks . bookmark) (dormant . dormant)
- (scored . score) (saved . save)
- (cached . cache)
- ))
-
-;; Avoid highlighting in kill files.
-(defvar gnus-summary-inhibit-highlight nil)
-(defvar gnus-newsgroup-selected-overlay nil)
-
-(defvar gnus-inhibit-hiding nil)
-(defvar gnus-group-indentation "")
-(defvar gnus-inhibit-limiting nil)
-(defvar gnus-created-frames nil)
-
-(defvar gnus-article-mode-map nil)
-(defvar gnus-dribble-buffer nil)
-(defvar gnus-headers-retrieved-by nil)
-(defvar gnus-article-reply nil)
-(defvar gnus-override-method nil)
-(defvar gnus-article-check-size nil)
-
-(defvar gnus-current-score-file nil)
-(defvar gnus-newsgroup-adaptive-score-file nil)
-(defvar gnus-scores-exclude-files nil)
-
-(defvar gnus-opened-servers nil)
-
-(defvar gnus-current-move-group nil)
-(defvar gnus-current-copy-group nil)
-(defvar gnus-current-crosspost-group nil)
-
-(defvar gnus-newsgroup-dependencies nil)
-(defvar gnus-newsgroup-async nil)
-(defconst gnus-group-edit-buffer "*Gnus edit newsgroup*")
-
-(defvar gnus-newsgroup-adaptive nil)
-
-(defvar gnus-summary-display-table nil)
-(defvar gnus-summary-display-article-function nil)
-
-(defvar gnus-summary-highlight-line-function nil
- "Function called after highlighting a summary line.")
-
-(defvar gnus-group-line-format-alist
- `((?M gnus-tmp-marked-mark ?c)
- (?S gnus-tmp-subscribed ?c)
- (?L gnus-tmp-level ?d)
- (?N (cond ((eq number t) "*" )
- ((numberp number)
- (int-to-string
- (+ number
- (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked)))
- (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))))))
- (t number)) ?s)
- (?R gnus-tmp-number-of-read ?s)
- (?t gnus-tmp-number-total ?d)
- (?y gnus-tmp-number-of-unread ?s)
- (?I (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) ?d)
- (?T (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))) ?d)
- (?i (+ (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked)))
- (gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))) ?d)
- (?g gnus-tmp-group ?s)
- (?G gnus-tmp-qualified-group ?s)
- (?c (gnus-short-group-name gnus-tmp-group) ?s)
- (?D gnus-tmp-newsgroup-description ?s)
- (?o gnus-tmp-moderated ?c)
- (?O gnus-tmp-moderated-string ?s)
- (?p gnus-tmp-process-marked ?c)
- (?s gnus-tmp-news-server ?s)
- (?n gnus-tmp-news-method ?s)
- (?P gnus-group-indentation ?s)
- (?l gnus-tmp-grouplens ?s)
- (?z gnus-tmp-news-method-string ?s)
- (?u gnus-tmp-user-defined ?s)))
-
-(defvar gnus-summary-line-format-alist
- `((?N ,(macroexpand '(mail-header-number gnus-tmp-header)) ?d)
- (?S ,(macroexpand '(mail-header-subject gnus-tmp-header)) ?s)
- (?s gnus-tmp-subject-or-nil ?s)
- (?n gnus-tmp-name ?s)
- (?A (car (cdr (funcall gnus-extract-address-components gnus-tmp-from)))
- ?s)
- (?a (or (car (funcall gnus-extract-address-components gnus-tmp-from))
- gnus-tmp-from) ?s)
- (?F gnus-tmp-from ?s)
- (?x ,(macroexpand '(mail-header-xref gnus-tmp-header)) ?s)
- (?D ,(macroexpand '(mail-header-date gnus-tmp-header)) ?s)
- (?d (gnus-dd-mmm (mail-header-date gnus-tmp-header)) ?s)
- (?M ,(macroexpand '(mail-header-id gnus-tmp-header)) ?s)
- (?r ,(macroexpand '(mail-header-references gnus-tmp-header)) ?s)
- (?c (or (mail-header-chars gnus-tmp-header) 0) ?d)
- (?L gnus-tmp-lines ?d)
- (?I gnus-tmp-indentation ?s)
- (?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s)
- (?R gnus-tmp-replied ?c)
- (?\[ gnus-tmp-opening-bracket ?c)
- (?\] gnus-tmp-closing-bracket ?c)
- (?\> (make-string gnus-tmp-level ? ) ?s)
- (?\< (make-string (max 0 (- 20 gnus-tmp-level)) ? ) ?s)
- (?i gnus-tmp-score ?d)
- (?z gnus-tmp-score-char ?c)
- (?l (bbb-grouplens-score gnus-tmp-header) ?s)
- (?V (gnus-thread-total-score (and (boundp 'thread) (car thread))) ?d)
- (?U gnus-tmp-unread ?c)
- (?t (gnus-summary-number-of-articles-in-thread
- (and (boundp 'thread) (car thread)) gnus-tmp-level)
- ?d)
- (?e (gnus-summary-number-of-articles-in-thread
- (and (boundp 'thread) (car thread)) gnus-tmp-level t)
- ?c)
- (?u gnus-tmp-user-defined ?s))
- "An alist of format specifications that can appear in summary lines,
-and what variables they correspond with, along with the type of the
-variable (string, integer, character, etc).")
-
-(defvar gnus-summary-dummy-line-format-alist
- `((?S gnus-tmp-subject ?s)
- (?N gnus-tmp-number ?d)
- (?u gnus-tmp-user-defined ?s)))
-
-(defvar gnus-summary-mode-line-format-alist
- `((?G gnus-tmp-group-name ?s)
- (?g (gnus-short-group-name gnus-tmp-group-name) ?s)
- (?p (gnus-group-real-name gnus-tmp-group-name) ?s)
- (?A gnus-tmp-article-number ?d)
- (?Z gnus-tmp-unread-and-unselected ?s)
- (?V gnus-version ?s)
- (?U gnus-tmp-unread-and-unticked ?d)
- (?S gnus-tmp-subject ?s)
- (?e gnus-tmp-unselected ?d)
- (?u gnus-tmp-user-defined ?s)
- (?d (length gnus-newsgroup-dormant) ?d)
- (?t (length gnus-newsgroup-marked) ?d)
- (?r (length gnus-newsgroup-reads) ?d)
- (?E gnus-newsgroup-expunged-tally ?d)
- (?s (gnus-current-score-file-nondirectory) ?s)))
-
-(defvar gnus-article-mode-line-format-alist
- gnus-summary-mode-line-format-alist)
-
-(defvar gnus-group-mode-line-format-alist
- `((?S gnus-tmp-news-server ?s)
- (?M gnus-tmp-news-method ?s)
- (?u gnus-tmp-user-defined ?s)
- (?: gnus-tmp-colon ?s)))
-
-(defvar gnus-have-read-active-file nil)
-
-(defconst gnus-maintainer
- "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)"
- "The mail address of the Gnus maintainers.")
-
-(defconst gnus-version-number "5.3"
- "Version number for this version of Gnus.")
-
-(defconst gnus-version (format "Gnus v%s" gnus-version-number)
- "Version string for this version of Gnus.")
-
-(defvar gnus-info-nodes
- '((gnus-group-mode "(gnus)The Group Buffer")
- (gnus-summary-mode "(gnus)The Summary Buffer")
- (gnus-article-mode "(gnus)The Article Buffer")
- (gnus-server-mode "(gnus)The Server Buffer")
- (gnus-browse-mode "(gnus)Browse Foreign Server")
- (gnus-tree-mode "(gnus)Tree Display")
- )
- "Alist of major modes and related Info nodes.")
-
-(defvar gnus-group-buffer "*Group*")
-(defvar gnus-summary-buffer "*Summary*")
-(defvar gnus-article-buffer "*Article*")
-(defvar gnus-server-buffer "*Server*")
-
-(defvar gnus-work-buffer " *gnus work*")
-
-(defvar gnus-original-article-buffer " *Original Article*")
-(defvar gnus-original-article nil)
-
-(defvar gnus-buffer-list nil
- "Gnus buffers that should be killed on exit.")
-
-(defvar gnus-slave nil
- "Whether this Gnus is a slave or not.")
-
-(defvar gnus-variable-list
- '(gnus-newsrc-options gnus-newsrc-options-n
- gnus-newsrc-last-checked-date
- gnus-newsrc-alist gnus-server-alist
- gnus-killed-list gnus-zombie-list
- gnus-topic-topology gnus-topic-alist
- gnus-format-specs)
- "Gnus variables saved in the quick startup file.")
-
-(defvar gnus-newsrc-options nil
- "Options line in the .newsrc file.")
-
-(defvar gnus-newsrc-options-n nil
- "List of regexps representing groups to be subscribed/ignored unconditionally.")
-
-(defvar gnus-newsrc-last-checked-date nil
- "Date Gnus last asked server for new newsgroups.")
-
-(defvar gnus-topic-topology nil
- "The complete topic hierarchy.")
-
-(defvar gnus-topic-alist nil
- "The complete topic-group alist.")
-
-(defvar gnus-newsrc-alist nil
- "Assoc list of read articles.
-gnus-newsrc-hashtb should be kept so that both hold the same information.")
-
-(defvar gnus-newsrc-hashtb nil
- "Hashtable of gnus-newsrc-alist.")
-
-(defvar gnus-killed-list nil
- "List of killed newsgroups.")
-
-(defvar gnus-killed-hashtb nil
- "Hash table equivalent of gnus-killed-list.")
-
-(defvar gnus-zombie-list nil
- "List of almost dead newsgroups.")
-
-(defvar gnus-description-hashtb nil
- "Descriptions of newsgroups.")
-
-(defvar gnus-list-of-killed-groups nil
- "List of newsgroups that have recently been killed by the user.")
-
-(defvar gnus-active-hashtb nil
- "Hashtable of active articles.")
-
-(defvar gnus-moderated-list nil
- "List of moderated newsgroups.")
-
-(defvar gnus-group-marked nil)
-
-(defvar gnus-current-startup-file nil
- "Startup file for the current host.")
-
-(defvar gnus-last-search-regexp nil
- "Default regexp for article search command.")
-
-(defvar gnus-last-shell-command nil
- "Default shell command on article.")
-
-(defvar gnus-current-select-method nil
- "The current method for selecting a newsgroup.")
-
-(defvar gnus-group-list-mode nil)
-
-(defvar gnus-article-internal-prepare-hook nil)
-
-(defvar gnus-newsgroup-name nil)
-(defvar gnus-newsgroup-begin nil)
-(defvar gnus-newsgroup-end nil)
-(defvar gnus-newsgroup-last-rmail nil)
-(defvar gnus-newsgroup-last-mail nil)
-(defvar gnus-newsgroup-last-folder nil)
-(defvar gnus-newsgroup-last-file nil)
-(defvar gnus-newsgroup-auto-expire nil)
-(defvar gnus-newsgroup-active nil)
-
-(defvar gnus-newsgroup-data nil)
-(defvar gnus-newsgroup-data-reverse nil)
-(defvar gnus-newsgroup-limit nil)
-(defvar gnus-newsgroup-limits nil)
-
-(defvar gnus-newsgroup-unreads nil
- "List of unread articles in the current newsgroup.")
-
-(defvar gnus-newsgroup-unselected nil
- "List of unselected unread articles in the current newsgroup.")
-
-(defvar gnus-newsgroup-reads nil
- "Alist of read articles and article marks in the current newsgroup.")
-
-(defvar gnus-newsgroup-expunged-tally nil)
-
-(defvar gnus-newsgroup-marked nil
- "List of ticked articles in the current newsgroup (a subset of unread art).")
-
-(defvar gnus-newsgroup-killed nil
- "List of ranges of articles that have been through the scoring process.")
-
-(defvar gnus-newsgroup-cached nil
- "List of articles that come from the article cache.")
-
-(defvar gnus-newsgroup-saved nil
- "List of articles that have been saved.")
-
-(defvar gnus-newsgroup-kill-headers nil)
-
-(defvar gnus-newsgroup-replied nil
- "List of articles that have been replied to in the current newsgroup.")
-
-(defvar gnus-newsgroup-expirable nil
- "List of articles in the current newsgroup that can be expired.")
-
-(defvar gnus-newsgroup-processable nil
- "List of articles in the current newsgroup that can be processed.")
-
-(defvar gnus-newsgroup-bookmarks nil
- "List of articles in the current newsgroup that have bookmarks.")
-
-(defvar gnus-newsgroup-dormant nil
- "List of dormant articles in the current newsgroup.")
-
-(defvar gnus-newsgroup-scored nil
- "List of scored articles in the current newsgroup.")
-
-(defvar gnus-newsgroup-headers nil
- "List of article headers in the current newsgroup.")
-
-(defvar gnus-newsgroup-threads nil)
-
-(defvar gnus-newsgroup-prepared nil
- "Whether the current group has been prepared properly.")
-
-(defvar gnus-newsgroup-ancient nil
- "List of `gnus-fetch-old-headers' articles in the current newsgroup.")
-
-(defvar gnus-newsgroup-sparse nil)
-
-(defvar gnus-current-article nil)
-(defvar gnus-article-current nil)
-(defvar gnus-current-headers nil)
-(defvar gnus-have-all-headers nil)
-(defvar gnus-last-article nil)
-(defvar gnus-newsgroup-history nil)
-(defvar gnus-current-kill-article nil)
-
-;; Save window configuration.
-(defvar gnus-prev-winconf nil)
-
-(defvar gnus-summary-mark-positions nil)
-(defvar gnus-group-mark-positions nil)
-
-(defvar gnus-reffed-article-number nil)
-
-;;; Let the byte-compiler know that we know about this variable.
-(defvar rmail-default-rmail-file)
-
-(defvar gnus-cache-removable-articles nil)
-
-(defvar gnus-dead-summary nil)
-
-(defconst gnus-summary-local-variables
- '(gnus-newsgroup-name
- gnus-newsgroup-begin gnus-newsgroup-end
- gnus-newsgroup-last-rmail gnus-newsgroup-last-mail
- gnus-newsgroup-last-folder gnus-newsgroup-last-file
- gnus-newsgroup-auto-expire gnus-newsgroup-unreads
- gnus-newsgroup-unselected gnus-newsgroup-marked
- gnus-newsgroup-reads gnus-newsgroup-saved
- gnus-newsgroup-replied gnus-newsgroup-expirable
- gnus-newsgroup-processable gnus-newsgroup-killed
- gnus-newsgroup-bookmarks gnus-newsgroup-dormant
- gnus-newsgroup-headers gnus-newsgroup-threads
- gnus-newsgroup-prepared gnus-summary-highlight-line-function
- gnus-current-article gnus-current-headers gnus-have-all-headers
- gnus-last-article gnus-article-internal-prepare-hook
- gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay
- gnus-newsgroup-scored gnus-newsgroup-kill-headers
- gnus-newsgroup-async gnus-thread-expunge-below
- gnus-score-alist gnus-current-score-file gnus-summary-expunge-below
- (gnus-summary-mark-below . global)
- gnus-newsgroup-active gnus-scores-exclude-files
- gnus-newsgroup-history gnus-newsgroup-ancient
- gnus-newsgroup-sparse
- (gnus-newsgroup-adaptive . gnus-use-adaptive-scoring)
- gnus-newsgroup-adaptive-score-file
- (gnus-newsgroup-expunged-tally . 0)
- gnus-cache-removable-articles gnus-newsgroup-cached
- gnus-newsgroup-data gnus-newsgroup-data-reverse
- gnus-newsgroup-limit gnus-newsgroup-limits)
- "Variables that are buffer-local to the summary buffers.")
-
-(defconst gnus-bug-message
- "Sending a bug report to the Gnus Towers.
-========================================
-
-The buffer below is a mail buffer. When you press `C-c C-c', it will
-be sent to the Gnus Bug Exterminators.
-
-At the bottom of the buffer you'll see lots of variable settings.
-Please do not delete those. They will tell the Bug People what your
-environment is, so that it will be easier to locate the bugs.
-
-If you have found a bug that makes Emacs go \"beep\", set
-debug-on-error to t (`M-x set-variable RET debug-on-error RET t RET')
-and include the backtrace in your bug report.
-
-Please describe the bug in annoying, painstaking detail.
-
-Thank you for your help in stamping out bugs.
-")
-
-;;; End of variables.
-
-;; Define some autoload functions Gnus might use.
-(eval-and-compile
-
- ;; This little mapcar goes through the list below and marks the
- ;; symbols in question as autoloaded functions.
- (mapcar
- (lambda (package)
- (let ((interactive (nth 1 (memq ':interactive package))))
- (mapcar
- (lambda (function)
- (let (keymap)
- (when (consp function)
- (setq keymap (car (memq 'keymap function)))
- (setq function (car function)))
- (autoload function (car package) nil interactive keymap)))
- (if (eq (nth 1 package) ':interactive)
- (cdddr package)
- (cdr package)))))
- '(("metamail" metamail-buffer)
- ("info" Info-goto-node)
- ("hexl" hexl-hex-string-to-integer)
- ("pp" pp pp-to-string pp-eval-expression)
- ("mail-extr" mail-extract-address-components)
- ("nnmail" nnmail-split-fancy nnmail-article-group)
- ("nnvirtual" nnvirtual-catchup-group)
- ("timezone" timezone-make-date-arpa-standard timezone-fix-time
- timezone-make-sortable-date timezone-make-time-string)
- ("rmailout" rmail-output)
- ("rmail" rmail-insert-rmail-file-header rmail-count-new-messages
- rmail-show-message)
- ("gnus-soup" :interactive t
- gnus-group-brew-soup gnus-brew-soup gnus-soup-add-article
- gnus-soup-send-replies gnus-soup-save-areas gnus-soup-pack-packet)
- ("nnsoup" nnsoup-pack-replies)
- ("score-mode" :interactive t gnus-score-mode)
- ("gnus-mh" gnus-mh-mail-setup gnus-summary-save-article-folder
- gnus-Folder-save-name gnus-folder-save-name)
- ("gnus-mh" :interactive t gnus-summary-save-in-folder)
- ("gnus-vis" gnus-group-make-menu-bar gnus-summary-make-menu-bar
- gnus-server-make-menu-bar gnus-article-make-menu-bar
- gnus-browse-make-menu-bar gnus-highlight-selected-summary
- gnus-summary-highlight-line gnus-carpal-setup-buffer
- gnus-group-highlight-line
- gnus-article-add-button gnus-insert-next-page-button
- gnus-insert-prev-page-button gnus-visual-turn-off-edit-menu)
- ("gnus-vis" :interactive t
- gnus-article-push-button gnus-article-press-button
- gnus-article-highlight gnus-article-highlight-some
- gnus-article-highlight-headers gnus-article-highlight-signature
- gnus-article-add-buttons gnus-article-add-buttons-to-head
- gnus-article-next-button gnus-article-prev-button)
- ("gnus-demon" gnus-demon-add-nocem gnus-demon-add-scanmail
- gnus-demon-add-disconnection gnus-demon-add-handler
- gnus-demon-remove-handler)
- ("gnus-demon" :interactive t
- gnus-demon-init gnus-demon-cancel)
- ("gnus-salt" gnus-highlight-selected-tree gnus-possibly-generate-tree
- gnus-tree-open gnus-tree-close)
- ("gnus-nocem" gnus-nocem-scan-groups gnus-nocem-close
- gnus-nocem-unwanted-article-p)
- ("gnus-srvr" gnus-enter-server-buffer gnus-server-set-info)
- ("gnus-srvr" gnus-browse-foreign-server)
- ("gnus-cite" :interactive t
- gnus-article-highlight-citation gnus-article-hide-citation-maybe
- gnus-article-hide-citation gnus-article-fill-cited-article
- gnus-article-hide-citation-in-followups)
- ("gnus-kill" gnus-kill gnus-apply-kill-file-internal
- gnus-kill-file-edit-file gnus-kill-file-raise-followups-to-author
- gnus-execute gnus-expunge)
- ("gnus-cache" gnus-cache-possibly-enter-article gnus-cache-save-buffers
- gnus-cache-possibly-remove-articles gnus-cache-request-article
- gnus-cache-retrieve-headers gnus-cache-possibly-alter-active
- gnus-cache-enter-remove-article gnus-cached-article-p
- gnus-cache-open gnus-cache-close gnus-cache-update-article)
- ("gnus-cache" :interactive t gnus-jog-cache gnus-cache-enter-article
- gnus-cache-remove-article)
- ("gnus-score" :interactive t
- gnus-summary-increase-score gnus-summary-lower-score
- gnus-score-flush-cache gnus-score-close
- gnus-score-raise-same-subject-and-select
- gnus-score-raise-same-subject gnus-score-default
- gnus-score-raise-thread gnus-score-lower-same-subject-and-select
- gnus-score-lower-same-subject gnus-score-lower-thread
- gnus-possibly-score-headers gnus-summary-raise-score
- gnus-summary-set-score gnus-summary-current-score)
- ("gnus-score"
- (gnus-summary-score-map keymap) gnus-score-save gnus-score-headers
- gnus-current-score-file-nondirectory gnus-score-adaptive
- gnus-score-find-trace gnus-score-file-name)
- ("gnus-edit" :interactive t gnus-score-customize)
- ("gnus-topic" :interactive t gnus-topic-mode)
- ("gnus-topic" gnus-topic-remove-group)
- ("gnus-salt" :interactive t gnus-pick-mode gnus-binary-mode)
- ("gnus-uu" (gnus-uu-extract-map keymap) (gnus-uu-mark-map keymap))
- ("gnus-uu" :interactive t
- gnus-uu-digest-mail-forward gnus-uu-digest-post-forward
- gnus-uu-mark-series gnus-uu-mark-region gnus-uu-mark-buffer
- gnus-uu-mark-by-regexp gnus-uu-mark-all
- gnus-uu-mark-sparse gnus-uu-mark-thread gnus-uu-decode-uu
- gnus-uu-decode-uu-and-save gnus-uu-decode-unshar
- gnus-uu-decode-unshar-and-save gnus-uu-decode-save
- gnus-uu-decode-binhex gnus-uu-decode-uu-view
- gnus-uu-decode-uu-and-save-view gnus-uu-decode-unshar-view
- gnus-uu-decode-unshar-and-save-view gnus-uu-decode-save-view
- gnus-uu-decode-binhex-view)
- ("gnus-msg" (gnus-summary-send-map keymap)
- gnus-mail-yank-original gnus-mail-send-and-exit
- gnus-article-mail gnus-new-mail gnus-mail-reply)
- ("gnus-msg" :interactive t
- gnus-group-post-news gnus-group-mail gnus-summary-post-news
- gnus-summary-followup gnus-summary-followup-with-original
- gnus-summary-cancel-article gnus-summary-supersede-article
- gnus-post-news gnus-inews-news
- gnus-summary-reply gnus-summary-reply-with-original
- gnus-summary-mail-forward gnus-summary-mail-other-window
- gnus-bug)
- ("gnus-picon" :interactive t gnus-article-display-picons
- gnus-group-display-picons gnus-picons-article-display-x-face
- gnus-picons-display-x-face)
- ("gnus-gl" bbb-login bbb-logout bbb-grouplens-group-p
- gnus-grouplens-mode)
- ("smiley" :interactive t gnus-smiley-display)
- ("gnus-vm" gnus-vm-mail-setup)
- ("gnus-vm" :interactive t gnus-summary-save-in-vm
- gnus-summary-save-article-vm))))
-
-
-
-;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
-;; If you want the cursor to go somewhere else, set these two
-;; functions in some startup hook to whatever you want.
-(defalias 'gnus-summary-position-point 'gnus-goto-colon)
-(defalias 'gnus-group-position-point 'gnus-goto-colon)
-
-;;; Various macros and substs.
-
-(defun gnus-header-from (header)
- (mail-header-from header))
-
-(defmacro gnus-eval-in-buffer-window (buffer &rest forms)
- "Pop to BUFFER, evaluate FORMS, and then return to the original window."
- (let ((tempvar (make-symbol "GnusStartBufferWindow"))
- (w (make-symbol "w"))
- (buf (make-symbol "buf")))
- `(let* ((,tempvar (selected-window))
- (,buf ,buffer)
- (,w (get-buffer-window ,buf 'visible)))
- (unwind-protect
- (progn
- (if ,w
- (select-window ,w)
- (pop-to-buffer ,buf))
- ,@forms)
- (select-window ,tempvar)))))
-
-(put 'gnus-eval-in-buffer-window 'lisp-indent-function 1)
-(put 'gnus-eval-in-buffer-window 'lisp-indent-hook 1)
-(put 'gnus-eval-in-buffer-window 'edebug-form-spec '(form body))
-
-(defmacro gnus-gethash (string hashtable)
- "Get hash value of STRING in HASHTABLE."
- `(symbol-value (intern-soft ,string ,hashtable)))
-
-(defmacro gnus-sethash (string value hashtable)
- "Set hash value. Arguments are STRING, VALUE, and HASHTABLE."
- `(set (intern ,string ,hashtable) ,value))
-
-(defmacro gnus-intern-safe (string hashtable)
- "Set hash value. Arguments are STRING, VALUE, and HASHTABLE."
- `(let ((symbol (intern ,string ,hashtable)))
- (or (boundp symbol)
- (set symbol nil))
- symbol))
-
-(defmacro gnus-group-unread (group)
- "Get the currently computed number of unread articles in GROUP."
- `(car (gnus-gethash ,group gnus-newsrc-hashtb)))
-
-(defmacro gnus-group-entry (group)
- "Get the newsrc entry for GROUP."
- `(gnus-gethash ,group gnus-newsrc-hashtb))
-
-(defmacro gnus-active (group)
- "Get active info on GROUP."
- `(gnus-gethash ,group gnus-active-hashtb))
-
-(defmacro gnus-set-active (group active)
- "Set GROUP's active info."
- `(gnus-sethash ,group ,active gnus-active-hashtb))
-
-;; modified by MORIOKA Tomohiko <morioka@jaist.ac.jp>
-;; function `substring' might cut on a middle of multi-octet
-;; character.
-(defun gnus-truncate-string (str width)
- (substring str 0 width))
-
-;; Added by Geoffrey T. Dairiki <dairiki@u.washington.edu>. A safe way
-;; to limit the length of a string. This function is necessary since
-;; `(substr "abc" 0 30)' pukes with "Args out of range".
-(defsubst gnus-limit-string (str width)
- (if (> (length str) width)
- (substring str 0 width)
- str))
-
-(defsubst gnus-simplify-subject-re (subject)
- "Remove \"Re:\" from subject lines."
- (if (string-match "^[Rr][Ee]: *" subject)
- (substring subject (match-end 0))
- subject))
-
-(defsubst gnus-functionp (form)
- "Return non-nil if FORM is funcallable."
- (or (and (symbolp form) (fboundp form))
- (and (listp form) (eq (car form) 'lambda))))
-
-(defsubst gnus-goto-char (point)
- (and point (goto-char point)))
-
-(defmacro gnus-buffer-exists-p (buffer)
- `(let ((buffer ,buffer))
- (and buffer
- (funcall (if (stringp buffer) 'get-buffer 'buffer-name)
- buffer))))
-
-(defmacro gnus-kill-buffer (buffer)
- `(let ((buf ,buffer))
- (if (gnus-buffer-exists-p buf)
- (kill-buffer buf))))
-
-(defsubst gnus-point-at-bol ()
- "Return point at the beginning of the line."
- (let ((p (point)))
- (beginning-of-line)
- (prog1
- (point)
- (goto-char p))))
-
-(defsubst gnus-point-at-eol ()
- "Return point at the end of the line."
- (let ((p (point)))
- (end-of-line)
- (prog1
- (point)
- (goto-char p))))
-
-(defun gnus-alive-p ()
- "Say whether Gnus is running or not."
- (and gnus-group-buffer
- (get-buffer gnus-group-buffer)))
-
-(defun gnus-delete-first (elt list)
- "Delete by side effect the first occurrence of ELT as a member of LIST."
- (if (equal (car list) elt)
- (cdr list)
- (let ((total list))
- (while (and (cdr list)
- (not (equal (cadr list) elt)))
- (setq list (cdr list)))
- (when (cdr list)
- (setcdr list (cddr list)))
- total)))
-
-;; Delete the current line (and the next N lines.);
-(defmacro gnus-delete-line (&optional n)
- `(delete-region (progn (beginning-of-line) (point))
- (progn (forward-line ,(or n 1)) (point))))
-
-;; Suggested by Brian Edmonds <edmonds@cs.ubc.ca>.
-(defvar gnus-init-inhibit nil)
-(defun gnus-read-init-file (&optional inhibit-next)
- (if gnus-init-inhibit
- (setq gnus-init-inhibit nil)
- (setq gnus-init-inhibit inhibit-next)
- (and gnus-init-file
- ;; Don't load .gnus if -q option was used.
- init-file-user
- (or (and (file-exists-p gnus-init-file)
- ;; Don't try to load a directory.
- (not (file-directory-p gnus-init-file)))
- (file-exists-p (concat gnus-init-file ".el"))
- (file-exists-p (concat gnus-init-file ".elc")))
- (condition-case var
- (load gnus-init-file nil t)
- (error
- (error "Error in %s: %s" gnus-init-file var))))))
-
-;; Info access macros.
-
-(defmacro gnus-info-group (info)
- `(nth 0 ,info))
-(defmacro gnus-info-rank (info)
- `(nth 1 ,info))
-(defmacro gnus-info-read (info)
- `(nth 2 ,info))
-(defmacro gnus-info-marks (info)
- `(nth 3 ,info))
-(defmacro gnus-info-method (info)
- `(nth 4 ,info))
-(defmacro gnus-info-params (info)
- `(nth 5 ,info))
-
-(defmacro gnus-info-level (info)
- `(let ((rank (gnus-info-rank ,info)))
- (if (consp rank)
- (car rank)
- rank)))
-(defmacro gnus-info-score (info)
- `(let ((rank (gnus-info-rank ,info)))
- (or (and (consp rank) (cdr rank)) 0)))
-
-(defmacro gnus-info-set-group (info group)
- `(setcar ,info ,group))
-(defmacro gnus-info-set-rank (info rank)
- `(setcar (nthcdr 1 ,info) ,rank))
-(defmacro gnus-info-set-read (info read)
- `(setcar (nthcdr 2 ,info) ,read))
-(defmacro gnus-info-set-marks (info marks)
- `(setcar (nthcdr 3 ,info) ,marks))
-(defmacro gnus-info-set-method (info method)
- `(setcar (nthcdr 4 ,info) ,method))
-(defmacro gnus-info-set-params (info params)
- `(setcar (nthcdr 5 ,info) ,params))
-
-(defmacro gnus-info-set-level (info level)
- `(let ((rank (cdr ,info)))
- (if (consp (car rank))
- (setcar (car rank) ,level)
- (setcar rank ,level))))
-(defmacro gnus-info-set-score (info score)
- `(let ((rank (cdr ,info)))
- (if (consp (car rank))
- (setcdr (car rank) ,score)
- (setcar rank (cons (car rank) ,score)))))
-
-(defmacro gnus-get-info (group)
- `(nth 2 (gnus-gethash ,group gnus-newsrc-hashtb)))
-
-(defun gnus-byte-code (func)
- "Return a form that can be `eval'ed based on FUNC."
- (let ((fval (symbol-function func)))
- (if (byte-code-function-p fval)
- (let ((flist (append fval nil)))
- (setcar flist 'byte-code)
- flist)
- (cons 'progn (cddr fval)))))
-
-;; Find out whether the gnus-visual TYPE is wanted.
-(defun gnus-visual-p (&optional type class)
- (and gnus-visual ; Has to be non-nil, at least.
- (if (not type) ; We don't care about type.
- gnus-visual
- (if (listp gnus-visual) ; It's a list, so we check it.
- (or (memq type gnus-visual)
- (memq class gnus-visual))
- t))))
-
-;;; Load the compatability functions.
-
-(require 'gnus-cus)
-(require 'gnus-ems)
-
-
-;;;
-;;; Shutdown
-;;;
-
-(defvar gnus-shutdown-alist nil)
-
-(defun gnus-add-shutdown (function &rest symbols)
- "Run FUNCTION whenever one of SYMBOLS is shut down."
- (push (cons function symbols) gnus-shutdown-alist))
-
-(defun gnus-shutdown (symbol)
- "Shut down everything that waits for SYMBOL."
- (let ((alist gnus-shutdown-alist)
- entry)
- (while (setq entry (pop alist))
- (when (memq symbol (cdr entry))
- (funcall (car entry))))))
-
-
-
-;; Format specs. The chunks below are the machine-generated forms
-;; that are to be evaled as the result of the default format strings.
-;; We write them in here to get them byte-compiled. That way the
-;; default actions will be quite fast, while still retaining the full
-;; flexibility of the user-defined format specs.
-
-;; First we have lots of dummy defvars to let the compiler know these
-;; are really dynamic variables.
-
-(defvar gnus-tmp-unread)
-(defvar gnus-tmp-replied)
-(defvar gnus-tmp-score-char)
-(defvar gnus-tmp-indentation)
-(defvar gnus-tmp-opening-bracket)
-(defvar gnus-tmp-lines)
-(defvar gnus-tmp-name)
-(defvar gnus-tmp-closing-bracket)
-(defvar gnus-tmp-subject-or-nil)
-(defvar gnus-tmp-subject)
-(defvar gnus-tmp-marked)
-(defvar gnus-tmp-marked-mark)
-(defvar gnus-tmp-subscribed)
-(defvar gnus-tmp-process-marked)
-(defvar gnus-tmp-number-of-unread)
-(defvar gnus-tmp-group-name)
-(defvar gnus-tmp-group)
-(defvar gnus-tmp-article-number)
-(defvar gnus-tmp-unread-and-unselected)
-(defvar gnus-tmp-news-method)
-(defvar gnus-tmp-news-server)
-(defvar gnus-tmp-article-number)
-(defvar gnus-mouse-face)
-(defvar gnus-mouse-face-prop)
-
-(defun gnus-summary-line-format-spec ()
- (insert gnus-tmp-unread gnus-tmp-replied
- gnus-tmp-score-char gnus-tmp-indentation)
- (gnus-put-text-property
- (point)
- (progn
- (insert
- gnus-tmp-opening-bracket
- (format "%4d: %-20s"
- gnus-tmp-lines
- (if (> (length gnus-tmp-name) 20)
- (substring gnus-tmp-name 0 20)
- gnus-tmp-name))
- gnus-tmp-closing-bracket)
- (point))
- gnus-mouse-face-prop gnus-mouse-face)
- (insert " " gnus-tmp-subject-or-nil "\n"))
-
-(defvar gnus-summary-line-format-spec
- (gnus-byte-code 'gnus-summary-line-format-spec))
-
-(defun gnus-summary-dummy-line-format-spec ()
- (insert "* ")
- (gnus-put-text-property
- (point)
- (progn
- (insert ": :")
- (point))
- gnus-mouse-face-prop gnus-mouse-face)
- (insert " " gnus-tmp-subject "\n"))
-
-(defvar gnus-summary-dummy-line-format-spec
- (gnus-byte-code 'gnus-summary-dummy-line-format-spec))
-
-(defun gnus-group-line-format-spec ()
- (insert gnus-tmp-marked-mark gnus-tmp-subscribed
- gnus-tmp-process-marked
- gnus-group-indentation
- (format "%5s: " gnus-tmp-number-of-unread))
- (gnus-put-text-property
- (point)
- (progn
- (insert gnus-tmp-group "\n")
- (1- (point)))
- gnus-mouse-face-prop gnus-mouse-face))
-(defvar gnus-group-line-format-spec
- (gnus-byte-code 'gnus-group-line-format-spec))
-
-(defvar gnus-format-specs
- `((version . ,emacs-version)
- (group ,gnus-group-line-format ,gnus-group-line-format-spec)
- (summary-dummy ,gnus-summary-dummy-line-format
- ,gnus-summary-dummy-line-format-spec)
- (summary ,gnus-summary-line-format ,gnus-summary-line-format-spec)))
-
-(defvar gnus-article-mode-line-format-spec nil)
-(defvar gnus-summary-mode-line-format-spec nil)
-(defvar gnus-group-mode-line-format-spec nil)
-
-;;; Phew. All that gruft is over, fortunately.
-
-
-;;;
-;;; Gnus Utility Functions
-;;;
-
-(defun gnus-extract-address-components (from)
- (let (name address)
- ;; First find the address - the thing with the @ in it. This may
- ;; not be accurate in mail addresses, but does the trick most of
- ;; the time in news messages.
- (if (string-match "\\b[^@ \t<>]+[!@][^@ \t<>]+\\b" from)
- (setq address (substring from (match-beginning 0) (match-end 0))))
- ;; Then we check whether the "name <address>" format is used.
- (and address
- ;; Fix by MORIOKA Tomohiko <morioka@jaist.ac.jp>
- ;; Linear white space is not required.
- (string-match (concat "[ \t]*<" (regexp-quote address) ">") from)
- (and (setq name (substring from 0 (match-beginning 0)))
- ;; Strip any quotes from the name.
- (string-match "\".*\"" name)
- (setq name (substring name 1 (1- (match-end 0))))))
- ;; If not, then "address (name)" is used.
- (or name
- (and (string-match "(.+)" from)
- (setq name (substring from (1+ (match-beginning 0))
- (1- (match-end 0)))))
- (and (string-match "()" from)
- (setq name address))
- ;; Fix by MORIOKA Tomohiko <morioka@jaist.ac.jp>.
- ;; XOVER might not support folded From headers.
- (and (string-match "(.*" from)
- (setq name (substring from (1+ (match-beginning 0))
- (match-end 0)))))
- ;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
- (list (or name from) (or address from))))
-
-(defun gnus-fetch-field (field)
- "Return the value of the header FIELD of current article."
- (save-excursion
- (save-restriction
- (let ((case-fold-search t)
- (inhibit-point-motion-hooks t))
- (nnheader-narrow-to-headers)
- (message-fetch-field field)))))
-
-(defun gnus-goto-colon ()
- (beginning-of-line)
- (search-forward ":" (gnus-point-at-eol) t))
-
-;;;###autoload
-(defun gnus-update-format (var)
- "Update the format specification near point."
- (interactive
- (list
- (save-excursion
- (eval-defun nil)
- ;; Find the end of the current word.
- (re-search-forward "[ \t\n]" nil t)
- ;; Search backward.
- (when (re-search-backward "\\(gnus-[-a-z]+-line-format\\)" nil t)
- (match-string 1)))))
- (let* ((type (intern (progn (string-match "gnus-\\([-a-z]+\\)-line" var)
- (match-string 1 var))))
- (entry (assq type gnus-format-specs))
- value spec)
- (when entry
- (setq gnus-format-specs (delq entry gnus-format-specs)))
- (set
- (intern (format "%s-spec" var))
- (gnus-parse-format (setq value (symbol-value (intern var)))
- (symbol-value (intern (format "%s-alist" var)))
- (not (string-match "mode" var))))
- (setq spec (symbol-value (intern (format "%s-spec" var))))
- (push (list type value spec) gnus-format-specs)
-
- (pop-to-buffer "*Gnus Format*")
- (erase-buffer)
- (lisp-interaction-mode)
- (insert (pp-to-string spec))))
-
-(defun gnus-update-format-specifications (&optional force)
- "Update all (necessary) format specifications."
- ;; Make the indentation array.
- (gnus-make-thread-indent-array)
-
- ;; See whether all the stored info needs to be flushed.
- (when (or force
- (not (equal emacs-version
- (cdr (assq 'version gnus-format-specs)))))
- (setq gnus-format-specs nil))
-
- ;; Go through all the formats and see whether they need updating.
- (let ((types '(summary summary-dummy group
- summary-mode group-mode article-mode))
- new-format entry type val)
- (while (setq type (pop types))
- ;; Jump to the proper buffer to find out the value of
- ;; the variable, if possible. (It may be buffer-local.)
- (save-excursion
- (let ((buffer (intern (format "gnus-%s-buffer" type)))
- val)
- (when (and (boundp buffer)
- (setq val (symbol-value buffer))
- (get-buffer val)
- (buffer-name (get-buffer val)))
- (set-buffer (get-buffer val)))
- (setq new-format (symbol-value
- (intern (format "gnus-%s-line-format" type))))))
- (setq entry (cdr (assq type gnus-format-specs)))
- (if (and entry
- (equal (car entry) new-format))
- ;; Use the old format.
- (set (intern (format "gnus-%s-line-format-spec" type))
- (cadr entry))
- ;; This is a new format.
- (setq val
- (if (not (stringp new-format))
- ;; This is a function call or something.
- new-format
- ;; This is a "real" format.
- (gnus-parse-format
- new-format
- (symbol-value
- (intern (format "gnus-%s-line-format-alist"
- (if (eq type 'article-mode)
- 'summary-mode type))))
- (not (string-match "mode$" (symbol-name type))))))
- ;; Enter the new format spec into the list.
- (if entry
- (progn
- (setcar (cdr entry) val)
- (setcar entry new-format))
- (push (list type new-format val) gnus-format-specs))
- (set (intern (format "gnus-%s-line-format-spec" type)) val))))
-
- (unless (assq 'version gnus-format-specs)
- (push (cons 'version emacs-version) gnus-format-specs))
-
- (gnus-update-group-mark-positions)
- (gnus-update-summary-mark-positions))
-
-(defun gnus-update-summary-mark-positions ()
- "Compute where the summary marks are to go."
- (save-excursion
- (when (and gnus-summary-buffer
- (get-buffer gnus-summary-buffer)
- (buffer-name (get-buffer gnus-summary-buffer)))
- (set-buffer gnus-summary-buffer))
- (let ((gnus-replied-mark 129)
- (gnus-score-below-mark 130)
- (gnus-score-over-mark 130)
- (thread nil)
- (gnus-visual nil)
- (spec gnus-summary-line-format-spec)
- pos)
- (save-excursion
- (gnus-set-work-buffer)
- (let ((gnus-summary-line-format-spec spec))
- (gnus-summary-insert-line
- [0 "" "" "" "" "" 0 0 ""] 0 nil 128 t nil "" nil 1)
- (goto-char (point-min))
- (setq pos (list (cons 'unread (and (search-forward "\200" nil t)
- (- (point) 2)))))
- (goto-char (point-min))
- (push (cons 'replied (and (search-forward "\201" nil t)
- (- (point) 2)))
- pos)
- (goto-char (point-min))
- (push (cons 'score (and (search-forward "\202" nil t) (- (point) 2)))
- pos)))
- (setq gnus-summary-mark-positions pos))))
-
-(defun gnus-update-group-mark-positions ()
- (save-excursion
- (let ((gnus-process-mark 128)
- (gnus-group-marked '("dummy.group"))
- (gnus-active-hashtb (make-vector 10 0)))
- (gnus-set-active "dummy.group" '(0 . 0))
- (gnus-set-work-buffer)
- (gnus-group-insert-group-line "dummy.group" 0 nil 0 nil)
- (goto-char (point-min))
- (setq gnus-group-mark-positions
- (list (cons 'process (and (search-forward "\200" nil t)
- (- (point) 2))))))))
-
-(defvar gnus-mouse-face-0 'highlight)
-(defvar gnus-mouse-face-1 'highlight)
-(defvar gnus-mouse-face-2 'highlight)
-(defvar gnus-mouse-face-3 'highlight)
-(defvar gnus-mouse-face-4 'highlight)
-
-(defun gnus-mouse-face-function (form type)
- `(gnus-put-text-property
- (point) (progn ,@form (point))
- gnus-mouse-face-prop
- ,(if (equal type 0)
- 'gnus-mouse-face
- `(quote ,(symbol-value (intern (format "gnus-mouse-face-%d" type)))))))
-
-(defvar gnus-face-0 'bold)
-(defvar gnus-face-1 'italic)
-(defvar gnus-face-2 'bold-italic)
-(defvar gnus-face-3 'bold)
-(defvar gnus-face-4 'bold)
-
-(defun gnus-face-face-function (form type)
- `(gnus-put-text-property
- (point) (progn ,@form (point))
- 'face ',(symbol-value (intern (format "gnus-face-%d" type)))))
-
-(defun gnus-max-width-function (el max-width)
- (or (numberp max-width) (signal 'wrong-type-argument '(numberp max-width)))
- (if (symbolp el)
- `(if (> (length ,el) ,max-width)
- (substring ,el 0 ,max-width)
- ,el)
- `(let ((val (eval ,el)))
- (if (numberp val)
- (setq val (int-to-string val)))
- (if (> (length val) ,max-width)
- (substring val 0 ,max-width)
- val))))
-
-(defun gnus-parse-format (format spec-alist &optional insert)
- ;; This function parses the FORMAT string with the help of the
- ;; SPEC-ALIST and returns a list that can be eval'ed to return the
- ;; string. If the FORMAT string contains the specifiers %( and %)
- ;; the text between them will have the mouse-face text property.
- (if (string-match
- "\\`\\(.*\\)%[0-9]?[{(]\\(.*\\)%[0-9]?[})]\\(.*\n?\\)\\'"
- format)
- (gnus-parse-complex-format format spec-alist)
- ;; This is a simple format.
- (gnus-parse-simple-format format spec-alist insert)))
-
-(defun gnus-parse-complex-format (format spec-alist)
- (save-excursion
- (gnus-set-work-buffer)
- (insert format)
- (goto-char (point-min))
- (while (re-search-forward "\"" nil t)
- (replace-match "\\\"" nil t))
- (goto-char (point-min))
- (insert "(\"")
- (while (re-search-forward "%\\([0-9]+\\)?\\([{}()]\\)" nil t)
- (let ((number (if (match-beginning 1)
- (match-string 1) "0"))
- (delim (aref (match-string 2) 0)))
- (if (or (= delim ?\() (= delim ?\{))
- (replace-match (concat "\"(" (if (= delim ?\() "mouse" "face")
- " " number " \""))
- (replace-match "\")\""))))
- (goto-char (point-max))
- (insert "\")")
- (goto-char (point-min))
- (let ((form (read (current-buffer))))
- (cons 'progn (gnus-complex-form-to-spec form spec-alist)))))
-
-(defun gnus-complex-form-to-spec (form spec-alist)
- (delq nil
- (mapcar
- (lambda (sform)
- (if (stringp sform)
- (gnus-parse-simple-format sform spec-alist t)
- (funcall (intern (format "gnus-%s-face-function" (car sform)))
- (gnus-complex-form-to-spec (cddr sform) spec-alist)
- (nth 1 sform))))
- form)))
-
-(defun gnus-parse-simple-format (format spec-alist &optional insert)
- ;; This function parses the FORMAT string with the help of the
- ;; SPEC-ALIST and returns a list that can be eval'ed to return a
- ;; string.
- (let ((max-width 0)
- spec flist fstring newspec elem beg result dontinsert)
- (save-excursion
- (gnus-set-work-buffer)
- (insert format)
- (goto-char (point-min))
- (while (re-search-forward "%[-0-9]*\\(,[0-9]+\\)?\\([^0-9]\\)\\(.\\)?"
- nil t)
- (if (= (setq spec (string-to-char (match-string 2))) ?%)
- (setq newspec "%"
- beg (1+ (match-beginning 0)))
- ;; First check if there are any specs that look anything like
- ;; "%12,12A", ie. with a "max width specification". These have
- ;; to be treated specially.
- (if (setq beg (match-beginning 1))
- (setq max-width
- (string-to-int
- (buffer-substring
- (1+ (match-beginning 1)) (match-end 1))))
- (setq max-width 0)
- (setq beg (match-beginning 2)))
- ;; Find the specification from `spec-alist'.
- (unless (setq elem (cdr (assq spec spec-alist)))
- (setq elem '("*" ?s)))
- ;; Treat user defined format specifiers specially.
- (when (eq (car elem) 'gnus-tmp-user-defined)
- (setq elem
- (list
- (list (intern (concat "gnus-user-format-function-"
- (match-string 3)))
- 'gnus-tmp-header) ?s))
- (delete-region (match-beginning 3) (match-end 3)))
- (if (not (zerop max-width))
- (let ((el (car elem)))
- (cond ((= (cadr elem) ?c)
- (setq el (list 'char-to-string el)))
- ((= (cadr elem) ?d)
- (setq el (list 'int-to-string el))))
- (setq flist (cons (gnus-max-width-function el max-width)
- flist))
- (setq newspec ?s))
- (progn
- (setq flist (cons (car elem) flist))
- (setq newspec (cadr elem)))))
- ;; Remove the old specification (and possibly a ",12" string).
- (delete-region beg (match-end 2))
- ;; Insert the new specification.
- (goto-char beg)
- (insert newspec))
- (setq fstring (buffer-substring 1 (point-max))))
- ;; Do some postprocessing to increase efficiency.
- (setq
- result
- (cond
- ;; Emptyness.
- ((string= fstring "")
- nil)
- ;; Not a format string.
- ((not (string-match "%" fstring))
- (list fstring))
- ;; A format string with just a single string spec.
- ((string= fstring "%s")
- (list (car flist)))
- ;; A single character.
- ((string= fstring "%c")
- (list (car flist)))
- ;; A single number.
- ((string= fstring "%d")
- (setq dontinsert)
- (if insert
- (list `(princ ,(car flist)))
- (list `(int-to-string ,(car flist)))))
- ;; Just lots of chars and strings.
- ((string-match "\\`\\(%[cs]\\)+\\'" fstring)
- (nreverse flist))
- ;; A single string spec at the beginning of the spec.
- ((string-match "\\`%[sc][^%]+\\'" fstring)
- (list (car flist) (substring fstring 2)))
- ;; A single string spec in the middle of the spec.
- ((string-match "\\`\\([^%]+\\)%[sc]\\([^%]+\\)\\'" fstring)
- (list (match-string 1 fstring) (car flist) (match-string 2 fstring)))
- ;; A single string spec in the end of the spec.
- ((string-match "\\`\\([^%]+\\)%[sc]\\'" fstring)
- (list (match-string 1 fstring) (car flist)))
- ;; A more complex spec.
- (t
- (list (cons 'format (cons fstring (nreverse flist)))))))
-
- (if insert
- (when result
- (if dontinsert
- result
- (cons 'insert result)))
- (cond ((stringp result)
- result)
- ((consp result)
- (cons 'concat result))
- (t "")))))
-
-(defun gnus-eval-format (format &optional alist props)
- "Eval the format variable FORMAT, using ALIST.
-If PROPS, insert the result."
- (let ((form (gnus-parse-format format alist props)))
- (if props
- (gnus-add-text-properties (point) (progn (eval form) (point)) props)
- (eval form))))
-
-(defun gnus-remove-text-with-property (prop)
- "Delete all text in the current buffer with text property PROP."
- (save-excursion
- (goto-char (point-min))
- (while (not (eobp))
- (while (get-text-property (point) prop)
- (delete-char 1))
- (goto-char (next-single-property-change (point) prop nil (point-max))))))
-
-(defun gnus-set-work-buffer ()
- (if (get-buffer gnus-work-buffer)
- (progn
- (set-buffer gnus-work-buffer)
- (erase-buffer))
- (set-buffer (get-buffer-create gnus-work-buffer))
- (kill-all-local-variables)
- (buffer-disable-undo (current-buffer))
- (gnus-add-current-to-buffer-list)))
-
-;; Article file names when saving.
-
-(defun gnus-Numeric-save-name (newsgroup headers &optional last-file)
- "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
-If variable `gnus-use-long-file-name' is nil, it is ~/News/News.group/num.
-Otherwise, it is like ~/News/news/group/num."
- (let ((default
- (expand-file-name
- (concat (if (gnus-use-long-file-name 'not-save)
- (gnus-capitalize-newsgroup newsgroup)
- (gnus-newsgroup-directory-form newsgroup))
- "/" (int-to-string (mail-header-number headers)))
- gnus-article-save-directory)))
- (if (and last-file
- (string-equal (file-name-directory default)
- (file-name-directory last-file))
- (string-match "^[0-9]+$" (file-name-nondirectory last-file)))
- default
- (or last-file default))))
-
-(defun gnus-numeric-save-name (newsgroup headers &optional last-file)
- "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
-If variable `gnus-use-long-file-name' is non-nil, it is
-~/News/news.group/num. Otherwise, it is like ~/News/news/group/num."
- (let ((default
- (expand-file-name
- (concat (if (gnus-use-long-file-name 'not-save)
- newsgroup
- (gnus-newsgroup-directory-form newsgroup))
- "/" (int-to-string (mail-header-number headers)))
- gnus-article-save-directory)))
- (if (and last-file
- (string-equal (file-name-directory default)
- (file-name-directory last-file))
- (string-match "^[0-9]+$" (file-name-nondirectory last-file)))
- default
- (or last-file default))))
-
-(defun gnus-Plain-save-name (newsgroup headers &optional last-file)
- "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
-If variable `gnus-use-long-file-name' is non-nil, it is
-~/News/News.group. Otherwise, it is like ~/News/news/group/news."
- (or last-file
- (expand-file-name
- (if (gnus-use-long-file-name 'not-save)
- (gnus-capitalize-newsgroup newsgroup)
- (concat (gnus-newsgroup-directory-form newsgroup) "/news"))
- gnus-article-save-directory)))
-
-(defun gnus-plain-save-name (newsgroup headers &optional last-file)
- "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
-If variable `gnus-use-long-file-name' is non-nil, it is
-~/News/news.group. Otherwise, it is like ~/News/news/group/news."
- (or last-file
- (expand-file-name
- (if (gnus-use-long-file-name 'not-save)
- newsgroup
- (concat (gnus-newsgroup-directory-form newsgroup) "/news"))
- gnus-article-save-directory)))
-
-;; For subscribing new newsgroup
-
-(defun gnus-subscribe-hierarchical-interactive (groups)
- (let ((groups (sort groups 'string<))
- prefixes prefix start ans group starts)
- (while groups
- (setq prefixes (list "^"))
- (while (and groups prefixes)
- (while (not (string-match (car prefixes) (car groups)))
- (setq prefixes (cdr prefixes)))
- (setq prefix (car prefixes))
- (setq start (1- (length prefix)))
- (if (and (string-match "[^\\.]\\." (car groups) start)
- (cdr groups)
- (setq prefix
- (concat "^" (substring (car groups) 0 (match-end 0))))
- (string-match prefix (cadr groups)))
- (progn
- (setq prefixes (cons prefix prefixes))
- (message "Descend hierarchy %s? ([y]nsq): "
- (substring prefix 1 (1- (length prefix))))
- (while (not (memq (setq ans (read-char)) '(?y ?\n ?n ?s ?q)))
- (ding)
- (message "Descend hierarchy %s? ([y]nsq): "
- (substring prefix 1 (1- (length prefix)))))
- (cond ((= ans ?n)
- (while (and groups
- (string-match prefix
- (setq group (car groups))))
- (setq gnus-killed-list
- (cons group gnus-killed-list))
- (gnus-sethash group group gnus-killed-hashtb)
- (setq groups (cdr groups)))
- (setq starts (cdr starts)))
- ((= ans ?s)
- (while (and groups
- (string-match prefix
- (setq group (car groups))))
- (gnus-sethash group group gnus-killed-hashtb)
- (gnus-subscribe-alphabetically (car groups))
- (setq groups (cdr groups)))
- (setq starts (cdr starts)))
- ((= ans ?q)
- (while groups
- (setq group (car groups))
- (setq gnus-killed-list (cons group gnus-killed-list))
- (gnus-sethash group group gnus-killed-hashtb)
- (setq groups (cdr groups))))
- (t nil)))
- (message "Subscribe %s? ([n]yq)" (car groups))
- (while (not (memq (setq ans (read-char)) '(?y ?\n ?q ?n)))
- (ding)
- (message "Subscribe %s? ([n]yq)" (car groups)))
- (setq group (car groups))
- (cond ((= ans ?y)
- (gnus-subscribe-alphabetically (car groups))
- (gnus-sethash group group gnus-killed-hashtb))
- ((= ans ?q)
- (while groups
- (setq group (car groups))
- (setq gnus-killed-list (cons group gnus-killed-list))
- (gnus-sethash group group gnus-killed-hashtb)
- (setq groups (cdr groups))))
- (t
- (setq gnus-killed-list (cons group gnus-killed-list))
- (gnus-sethash group group gnus-killed-hashtb)))
- (setq groups (cdr groups)))))))
-
-(defun gnus-subscribe-randomly (newsgroup)
- "Subscribe new NEWSGROUP by making it the first newsgroup."
- (gnus-subscribe-newsgroup newsgroup))
-
-(defun gnus-subscribe-alphabetically (newgroup)
- "Subscribe new NEWSGROUP and insert it in alphabetical order."
- (let ((groups (cdr gnus-newsrc-alist))
- before)
- (while (and (not before) groups)
- (if (string< newgroup (caar groups))
- (setq before (caar groups))
- (setq groups (cdr groups))))
- (gnus-subscribe-newsgroup newgroup before)))
-
-(defun gnus-subscribe-hierarchically (newgroup)
- "Subscribe new NEWSGROUP and insert it in hierarchical newsgroup order."
- ;; Basic ideas by mike-w@cs.aukuni.ac.nz (Mike Williams)
- (save-excursion
- (set-buffer (find-file-noselect gnus-current-startup-file))
- (let ((groupkey newgroup)
- before)
- (while (and (not before) groupkey)
- (goto-char (point-min))
- (let ((groupkey-re
- (concat "^\\(" (regexp-quote groupkey) ".*\\)[!:]")))
- (while (and (re-search-forward groupkey-re nil t)
- (progn
- (setq before (match-string 1))
- (string< before newgroup)))))
- ;; Remove tail of newsgroup name (eg. a.b.c -> a.b)
- (setq groupkey
- (if (string-match "^\\(.*\\)\\.[^.]+$" groupkey)
- (substring groupkey (match-beginning 1) (match-end 1)))))
- (gnus-subscribe-newsgroup newgroup before))
- (kill-buffer (current-buffer))))
-
-(defun gnus-subscribe-interactively (group)
- "Subscribe the new GROUP interactively.
-It is inserted in hierarchical newsgroup order if subscribed. If not,
-it is killed."
- (if (gnus-y-or-n-p (format "Subscribe new newsgroup: %s " group))
- (gnus-subscribe-hierarchically group)
- (push group gnus-killed-list)))
-
-(defun gnus-subscribe-zombies (group)
- "Make the new GROUP into a zombie group."
- (push group gnus-zombie-list))
-
-(defun gnus-subscribe-killed (group)
- "Make the new GROUP a killed group."
- (push group gnus-killed-list))
-
-(defun gnus-subscribe-newsgroup (newsgroup &optional next)
- "Subscribe new NEWSGROUP.
-If NEXT is non-nil, it is inserted before NEXT. Otherwise it is made
-the first newsgroup."
- ;; We subscribe the group by changing its level to `subscribed'.
- (gnus-group-change-level
- newsgroup gnus-level-default-subscribed
- gnus-level-killed (gnus-gethash (or next "dummy.group") gnus-newsrc-hashtb))
- (gnus-message 5 "Subscribe newsgroup: %s" newsgroup))
-
-;; For directories
-
-(defun gnus-newsgroup-directory-form (newsgroup)
- "Make hierarchical directory name from NEWSGROUP name."
- (let ((newsgroup (gnus-newsgroup-savable-name newsgroup))
- (len (length newsgroup))
- idx)
- ;; If this is a foreign group, we don't want to translate the
- ;; entire name.
- (if (setq idx (string-match ":" newsgroup))
- (aset newsgroup idx ?/)
- (setq idx 0))
- ;; Replace all occurrences of `.' with `/'.
- (while (< idx len)
- (if (= (aref newsgroup idx) ?.)
- (aset newsgroup idx ?/))
- (setq idx (1+ idx)))
- newsgroup))
-
-(defun gnus-newsgroup-savable-name (group)
- ;; Replace any slashes in a group name (eg. an ange-ftp nndoc group)
- ;; with dots.
- (nnheader-replace-chars-in-string group ?/ ?.))
-
-(defun gnus-make-directory (dir)
- "Make DIRECTORY recursively."
- ;; Why don't we use `(make-directory dir 'parents)'? That's just one
- ;; of the many mysteries of the universe.
- (let* ((dir (expand-file-name dir default-directory))
- dirs err)
- (if (string-match "/$" dir)
- (setq dir (substring dir 0 (match-beginning 0))))
- ;; First go down the path until we find a directory that exists.
- (while (not (file-exists-p dir))
- (setq dirs (cons dir dirs))
- (string-match "/[^/]+$" dir)
- (setq dir (substring dir 0 (match-beginning 0))))
- ;; Then create all the subdirs.
- (while (and dirs (not err))
- (condition-case ()
- (make-directory (car dirs))
- (error (setq err t)))
- (setq dirs (cdr dirs)))
- ;; We return whether we were successful or not.
- (not dirs)))
-
-(defun gnus-capitalize-newsgroup (newsgroup)
- "Capitalize NEWSGROUP name."
- (and (not (zerop (length newsgroup)))
- (concat (char-to-string (upcase (aref newsgroup 0)))
- (substring newsgroup 1))))
-
-;; Various... things.
-
-(defun gnus-simplify-subject (subject &optional re-only)
- "Remove `Re:' and words in parentheses.
-If RE-ONLY is non-nil, strip leading `Re:'s only."
- (let ((case-fold-search t)) ;Ignore case.
- ;; Remove `Re:', `Re^N:', `Re(n)', and `Re[n]:'.
- (when (string-match "\\`\\(re\\([[(^][0-9]+[])]?\\)?:[ \t]*\\)+" subject)
- (setq subject (substring subject (match-end 0))))
- ;; Remove uninteresting prefixes.
- (if (and (not re-only)
- gnus-simplify-ignored-prefixes
- (string-match gnus-simplify-ignored-prefixes subject))
- (setq subject (substring subject (match-end 0))))
- ;; Remove words in parentheses from end.
- (unless re-only
- (while (string-match "[ \t\n]*([^()]*)[ \t\n]*\\'" subject)
- (setq subject (substring subject 0 (match-beginning 0)))))
- ;; Return subject string.
- subject))
-
-;; Remove any leading "re:"s, any trailing paren phrases, and simplify
-;; all whitespace.
-;; Written by Stainless Steel Rat <ratinox@ccs.neu.edu>.
-(defun gnus-simplify-buffer-fuzzy ()
- (let ((case-fold-search t))
- (goto-char (point-min))
- (while (search-forward "\t" nil t)
- (replace-match " " t t))
- (goto-char (point-min))
- (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *" nil t)
- (goto-char (match-beginning 0))
- (while (or
- (looking-at "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *")
- (looking-at "^[[].*: .*[]]$"))
- (goto-char (point-min))
- (while (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *"
- nil t)
- (replace-match "" t t))
- (goto-char (point-min))
- (while (re-search-forward "^[[].*: .*[]]$" nil t)
- (goto-char (match-end 0))
- (delete-char -1)
- (delete-region
- (progn (goto-char (match-beginning 0)))
- (re-search-forward ":"))))
- (goto-char (point-min))
- (while (re-search-forward " *[[{(][^()\n]*[]})] *$" nil t)
- (replace-match "" t t))
- (goto-char (point-min))
- (while (re-search-forward " +" nil t)
- (replace-match " " t t))
- (goto-char (point-min))
- (while (re-search-forward " $" nil t)
- (replace-match "" t t))
- (goto-char (point-min))
- (while (re-search-forward "^ +" nil t)
- (replace-match "" t t))
- (goto-char (point-min))
- (when gnus-simplify-subject-fuzzy-regexp
- (if (listp gnus-simplify-subject-fuzzy-regexp)
- (let ((list gnus-simplify-subject-fuzzy-regexp))
- (while list
- (goto-char (point-min))
- (while (re-search-forward (car list) nil t)
- (replace-match "" t t))
- (setq list (cdr list))))
- (while (re-search-forward gnus-simplify-subject-fuzzy-regexp nil t)
- (replace-match "" t t))))))
-
-(defun gnus-simplify-subject-fuzzy (subject)
- "Siplify a subject string fuzzily."
- (save-excursion
- (gnus-set-work-buffer)
- (let ((case-fold-search t))
- (insert subject)
- (inline (gnus-simplify-buffer-fuzzy))
- (buffer-string))))
-
-;; Add the current buffer to the list of buffers to be killed on exit.
-(defun gnus-add-current-to-buffer-list ()
- (or (memq (current-buffer) gnus-buffer-list)
- (setq gnus-buffer-list (cons (current-buffer) gnus-buffer-list))))
-
-(defun gnus-string> (s1 s2)
- (not (or (string< s1 s2)
- (string= s1 s2))))
-
-(defun gnus-read-active-file-p ()
- "Say whether the active file has been read from `gnus-select-method'."
- (memq gnus-select-method gnus-have-read-active-file))
-
-;;; General various misc type functions.
-
-(defun gnus-clear-system ()
- "Clear all variables and buffers."
- ;; Clear Gnus variables.
- (let ((variables gnus-variable-list))
- (while variables
- (set (car variables) nil)
- (setq variables (cdr variables))))
- ;; Clear other internal variables.
- (setq gnus-list-of-killed-groups nil
- gnus-have-read-active-file nil
- gnus-newsrc-alist nil
- gnus-newsrc-hashtb nil
- gnus-killed-list nil
- gnus-zombie-list nil
- gnus-killed-hashtb nil
- gnus-active-hashtb nil
- gnus-moderated-list nil
- gnus-description-hashtb nil
- gnus-current-headers nil
- gnus-thread-indent-array nil
- gnus-newsgroup-headers nil
- gnus-newsgroup-name nil
- gnus-server-alist nil
- gnus-group-list-mode nil
- gnus-opened-servers nil
- gnus-group-mark-positions nil
- gnus-newsgroup-data nil
- gnus-newsgroup-unreads nil
- nnoo-state-alist nil
- gnus-current-select-method nil)
- (gnus-shutdown 'gnus)
- ;; Kill the startup file.
- (and gnus-current-startup-file
- (get-file-buffer gnus-current-startup-file)
- (kill-buffer (get-file-buffer gnus-current-startup-file)))
- ;; Clear the dribble buffer.
- (gnus-dribble-clear)
- ;; Kill global KILL file buffer.
- (when (get-file-buffer (gnus-newsgroup-kill-file nil))
- (kill-buffer (get-file-buffer (gnus-newsgroup-kill-file nil))))
- (gnus-kill-buffer nntp-server-buffer)
- ;; Kill Gnus buffers.
- (while gnus-buffer-list
- (gnus-kill-buffer (pop gnus-buffer-list)))
- ;; Remove Gnus frames.
- (gnus-kill-gnus-frames))
-
-(defun gnus-kill-gnus-frames ()
- "Kill all frames Gnus has created."
- (while gnus-created-frames
- (when (frame-live-p (car gnus-created-frames))
- ;; We slap a condition-case around this `delete-frame' to ensure
- ;; against errors if we try do delete the single frame that's left.
- (condition-case ()
- (delete-frame (car gnus-created-frames))
- (error nil)))
- (pop gnus-created-frames)))
-
-(defun gnus-windows-old-to-new (setting)
- ;; First we take care of the really, really old Gnus 3 actions.
- (when (symbolp setting)
- (setq setting
- ;; Take care of ooold GNUS 3.x values.
- (cond ((eq setting 'SelectArticle) 'article)
- ((memq setting '(SelectSubject ExpandSubject)) 'summary)
- ((memq setting '(SelectNewsgroup ExitNewsgroup)) 'group)
- (t setting))))
- (if (or (listp setting)
- (not (and gnus-window-configuration
- (memq setting '(group summary article)))))
- setting
- (let* ((setting (if (eq setting 'group)
- (if (assq 'newsgroup gnus-window-configuration)
- 'newsgroup
- 'newsgroups) setting))
- (elem (cadr (assq setting gnus-window-configuration)))
- (total (apply '+ elem))
- (types '(group summary article))
- (pbuf (if (eq setting 'newsgroups) 'group 'summary))
- (i 0)
- perc
- out)
- (while (< i 3)
- (or (not (numberp (nth i elem)))
- (zerop (nth i elem))
- (progn
- (setq perc (if (= i 2)
- 1.0
- (/ (float (nth 0 elem)) total)))
- (setq out (cons (if (eq pbuf (nth i types))
- (list (nth i types) perc 'point)
- (list (nth i types) perc))
- out))))
- (setq i (1+ i)))
- `(vertical 1.0 ,@(nreverse out)))))
-
-;;;###autoload
-(defun gnus-add-configuration (conf)
- "Add the window configuration CONF to `gnus-buffer-configuration'."
- (setq gnus-buffer-configuration
- (cons conf (delq (assq (car conf) gnus-buffer-configuration)
- gnus-buffer-configuration))))
-
-(defvar gnus-frame-list nil)
-
-(defun gnus-configure-frame (split &optional window)
- "Split WINDOW according to SPLIT."
- (unless window
- (setq window (get-buffer-window (current-buffer))))
- (select-window window)
- ;; This might be an old-stylee buffer config.
- (when (vectorp split)
- (setq split (append split nil)))
- (when (or (consp (car split))
- (vectorp (car split)))
- (push 1.0 split)
- (push 'vertical split))
- ;; The SPLIT might be something that is to be evaled to
- ;; return a new SPLIT.
- (while (and (not (assq (car split) gnus-window-to-buffer))
- (gnus-functionp (car split)))
- (setq split (eval split)))
- (let* ((type (car split))
- (subs (cddr split))
- (len (if (eq type 'horizontal) (window-width) (window-height)))
- (total 0)
- (window-min-width (or gnus-window-min-width window-min-width))
- (window-min-height (or gnus-window-min-height window-min-height))
- s result new-win rest comp-subs size sub)
- (cond
- ;; Nothing to do here.
- ((null split))
- ;; Don't switch buffers.
- ((null type)
- (and (memq 'point split) window))
- ;; This is a buffer to be selected.
- ((not (memq type '(frame horizontal vertical)))
- (let ((buffer (cond ((stringp type) type)
- (t (cdr (assq type gnus-window-to-buffer)))))
- buf)
- (unless buffer
- (error "Illegal buffer type: %s" type))
- (unless (setq buf (get-buffer (if (symbolp buffer)
- (symbol-value buffer) buffer)))
- (setq buf (get-buffer-create (if (symbolp buffer)
- (symbol-value buffer) buffer))))
- (switch-to-buffer buf)
- ;; We return the window if it has the `point' spec.
- (and (memq 'point split) window)))
- ;; This is a frame split.
- ((eq type 'frame)
- (unless gnus-frame-list
- (setq gnus-frame-list (list (window-frame
- (get-buffer-window (current-buffer))))))
- (let ((i 0)
- params frame fresult)
- (while (< i (length subs))
- ;; Frame parameter is gotten from the sub-split.
- (setq params (cadr (elt subs i)))
- ;; It should be a list.
- (unless (listp params)
- (setq params nil))
- ;; Create a new frame?
- (unless (setq frame (elt gnus-frame-list i))
- (nconc gnus-frame-list (list (setq frame (make-frame params))))
- (push frame gnus-created-frames))
- ;; Is the old frame still alive?
- (unless (frame-live-p frame)
- (setcar (nthcdr i gnus-frame-list)
- (setq frame (make-frame params))))
- ;; Select the frame in question and do more splits there.
- (select-frame frame)
- (setq fresult (or (gnus-configure-frame (elt subs i)) fresult))
- (incf i))
- ;; Select the frame that has the selected buffer.
- (when fresult
- (select-frame (window-frame fresult)))))
- ;; This is a normal split.
- (t
- (when (> (length subs) 0)
- ;; First we have to compute the sizes of all new windows.
- (while subs
- (setq sub (append (pop subs) nil))
- (while (and (not (assq (car sub) gnus-window-to-buffer))
- (gnus-functionp (car sub)))
- (setq sub (eval sub)))
- (when sub
- (push sub comp-subs)
- (setq size (cadar comp-subs))
- (cond ((equal size 1.0)
- (setq rest (car comp-subs))
- (setq s 0))
- ((floatp size)
- (setq s (floor (* size len))))
- ((integerp size)
- (setq s size))
- (t
- (error "Illegal size: %s" size)))
- ;; Try to make sure that we are inside the safe limits.
- (cond ((zerop s))
- ((eq type 'horizontal)
- (setq s (max s window-min-width)))
- ((eq type 'vertical)
- (setq s (max s window-min-height))))
- (setcar (cdar comp-subs) s)
- (incf total s)))
- ;; Take care of the "1.0" spec.
- (if rest
- (setcar (cdr rest) (- len total))
- (error "No 1.0 specs in %s" split))
- ;; The we do the actual splitting in a nice recursive
- ;; fashion.
- (setq comp-subs (nreverse comp-subs))
- (while comp-subs
- (if (null (cdr comp-subs))
- (setq new-win window)
- (setq new-win
- (split-window window (cadar comp-subs)
- (eq type 'horizontal))))
- (setq result (or (gnus-configure-frame
- (car comp-subs) window) result))
- (select-window new-win)
- (setq window new-win)
- (setq comp-subs (cdr comp-subs))))
- ;; Return the proper window, if any.
- (when result
- (select-window result))))))
-
-(defvar gnus-frame-split-p nil)
-
-(defun gnus-configure-windows (setting &optional force)
- (setq setting (gnus-windows-old-to-new setting))
- (let ((split (if (symbolp setting)
- (cadr (assq setting gnus-buffer-configuration))
- setting))
- all-visible)
-
- (setq gnus-frame-split-p nil)
-
- (unless split
- (error "No such setting: %s" setting))
-
- (if (and (setq all-visible (gnus-all-windows-visible-p split))
- (not force))
- ;; All the windows mentioned are already visible, so we just
- ;; put point in the assigned buffer, and do not touch the
- ;; winconf.
- (select-window all-visible)
-
- ;; Either remove all windows or just remove all Gnus windows.
- (let ((frame (selected-frame)))
- (unwind-protect
- (if gnus-use-full-window
- ;; We want to remove all other windows.
- (if (not gnus-frame-split-p)
- ;; This is not a `frame' split, so we ignore the
- ;; other frames.
- (delete-other-windows)
- ;; This is a `frame' split, so we delete all windows
- ;; on all frames.
- (mapcar
- (lambda (frame)
- (unless (eq (cdr (assq 'minibuffer
- (frame-parameters frame)))
- 'only)
- (select-frame frame)
- (delete-other-windows)))
- (frame-list)))
- ;; Just remove some windows.
- (gnus-remove-some-windows)
- (switch-to-buffer nntp-server-buffer))
- (select-frame frame)))
-
- (switch-to-buffer nntp-server-buffer)
- (gnus-configure-frame split (get-buffer-window (current-buffer))))))
-
-(defun gnus-all-windows-visible-p (split)
- "Say whether all buffers in SPLIT are currently visible.
-In particular, the value returned will be the window that
-should have point."
- (let ((stack (list split))
- (all-visible t)
- type buffer win buf)
- (while (and (setq split (pop stack))
- all-visible)
- ;; Be backwards compatible.
- (when (vectorp split)
- (setq split (append split nil)))
- (when (or (consp (car split))
- (vectorp (car split)))
- (push 1.0 split)
- (push 'vertical split))
- ;; The SPLIT might be something that is to be evaled to
- ;; return a new SPLIT.
- (while (and (not (assq (car split) gnus-window-to-buffer))
- (gnus-functionp (car split)))
- (setq split (eval split)))
-
- (setq type (elt split 0))
- (cond
- ;; Nothing here.
- ((null split) t)
- ;; A buffer.
- ((not (memq type '(horizontal vertical frame)))
- (setq buffer (cond ((stringp type) type)
- (t (cdr (assq type gnus-window-to-buffer)))))
- (unless buffer
- (error "Illegal buffer type: %s" type))
- (when (setq buf (get-buffer (if (symbolp buffer)
- (symbol-value buffer)
- buffer)))
- (setq win (get-buffer-window buf t)))
- (if win
- (when (memq 'point split)
- (setq all-visible win))
- (setq all-visible nil)))
- (t
- (when (eq type 'frame)
- (setq gnus-frame-split-p t))
- (setq stack (append (cddr split) stack)))))
- (unless (eq all-visible t)
- all-visible)))
-
-(defun gnus-window-top-edge (&optional window)
- (nth 1 (window-edges window)))
-
-(defun gnus-remove-some-windows ()
- (let ((buffers gnus-window-to-buffer)
- buf bufs lowest-buf lowest)
- (save-excursion
- ;; Remove windows on all known Gnus buffers.
- (while buffers
- (setq buf (cdar buffers))
- (if (symbolp buf)
- (setq buf (and (boundp buf) (symbol-value buf))))
- (and buf
- (get-buffer-window buf)
- (progn
- (setq bufs (cons buf bufs))
- (pop-to-buffer buf)
- (if (or (not lowest)
- (< (gnus-window-top-edge) lowest))
- (progn
- (setq lowest (gnus-window-top-edge))
- (setq lowest-buf buf)))))
- (setq buffers (cdr buffers)))
- ;; Remove windows on *all* summary buffers.
- (walk-windows
- (lambda (win)
- (let ((buf (window-buffer win)))
- (if (string-match "^\\*Summary" (buffer-name buf))
- (progn
- (setq bufs (cons buf bufs))
- (pop-to-buffer buf)
- (if (or (not lowest)
- (< (gnus-window-top-edge) lowest))
- (progn
- (setq lowest-buf buf)
- (setq lowest (gnus-window-top-edge)))))))))
- (and lowest-buf
- (progn
- (pop-to-buffer lowest-buf)
- (switch-to-buffer nntp-server-buffer)))
- (while bufs
- (and (not (eq (car bufs) lowest-buf))
- (delete-windows-on (car bufs)))
- (setq bufs (cdr bufs))))))
-
-(defun gnus-version (&optional arg)
- "Version number of this version of Gnus.
-If ARG, insert string at point."
- (interactive "P")
- (let ((methods gnus-valid-select-methods)
- (mess gnus-version)
- meth)
- ;; Go through all the legal select methods and add their version
- ;; numbers to the total version string. Only the backends that are
- ;; currently in use will have their message numbers taken into
- ;; consideration.
- (while methods
- (setq meth (intern (concat (caar methods) "-version")))
- (and (boundp meth)
- (stringp (symbol-value meth))
- (setq mess (concat mess "; " (symbol-value meth))))
- (setq methods (cdr methods)))
- (if arg
- (insert (message mess))
- (message mess))))
-
-(defun gnus-info-find-node ()
- "Find Info documentation of Gnus."
- (interactive)
- ;; Enlarge info window if needed.
- (let ((mode major-mode)
- gnus-info-buffer)
- (Info-goto-node (cadr (assq mode gnus-info-nodes)))
- (setq gnus-info-buffer (current-buffer))
- (gnus-configure-windows 'info)))
-
-(defun gnus-days-between (date1 date2)
- ;; Return the number of days between date1 and date2.
- (- (gnus-day-number date1) (gnus-day-number date2)))
-
-(defun gnus-day-number (date)
- (let ((dat (mapcar (lambda (s) (and s (string-to-int s)) )
- (timezone-parse-date date))))
- (timezone-absolute-from-gregorian
- (nth 1 dat) (nth 2 dat) (car dat))))
-
-(defun gnus-encode-date (date)
- "Convert DATE to internal time."
- (let* ((parse (timezone-parse-date date))
- (date (mapcar (lambda (d) (and d (string-to-int d))) parse))
- (time (mapcar 'string-to-int (timezone-parse-time (aref parse 3)))))
- (encode-time (caddr time) (cadr time) (car time)
- (caddr date) (cadr date) (car date) (nth 4 date))))
-
-(defun gnus-time-minus (t1 t2)
- "Subtract two internal times."
- (let ((borrow (< (cadr t1) (cadr t2))))
- (list (- (car t1) (car t2) (if borrow 1 0))
- (- (+ (if borrow 65536 0) (cadr t1)) (cadr t2)))))
-
-(defun gnus-file-newer-than (file date)
- (let ((fdate (nth 5 (file-attributes file))))
- (or (> (car fdate) (car date))
- (and (= (car fdate) (car date))
- (> (nth 1 fdate) (nth 1 date))))))
-
-(defmacro gnus-local-set-keys (&rest plist)
- "Set the keys in PLIST in the current keymap."
- `(gnus-define-keys-1 (current-local-map) ',plist))
-
-(defmacro gnus-define-keys (keymap &rest plist)
- "Define all keys in PLIST in KEYMAP."
- `(gnus-define-keys-1 (quote ,keymap) (quote ,plist)))
-
-(put 'gnus-define-keys 'lisp-indent-function 1)
-(put 'gnus-define-keys 'lisp-indent-hook 1)
-(put 'gnus-define-keymap 'lisp-indent-function 1)
-(put 'gnus-define-keymap 'lisp-indent-hook 1)
-
-(defmacro gnus-define-keymap (keymap &rest plist)
- "Define all keys in PLIST in KEYMAP."
- `(gnus-define-keys-1 ,keymap (quote ,plist)))
-
-(defun gnus-define-keys-1 (keymap plist)
- (when (null keymap)
- (error "Can't set keys in a null keymap"))
- (cond ((symbolp keymap)
- (setq keymap (symbol-value keymap)))
- ((keymapp keymap))
- ((listp keymap)
- (set (car keymap) nil)
- (define-prefix-command (car keymap))
- (define-key (symbol-value (caddr keymap)) (cadr keymap) (car keymap))
- (setq keymap (symbol-value (car keymap)))))
- (let (key)
- (while plist
- (when (symbolp (setq key (pop plist)))
- (setq key (symbol-value key)))
- (define-key keymap key (pop plist)))))
-
-(defun gnus-group-read-only-p (&optional group)
- "Check whether GROUP supports editing or not.
-If GROUP is nil, `gnus-newsgroup-name' will be checked instead. Note
-that that variable is buffer-local to the summary buffers."
- (let ((group (or group gnus-newsgroup-name)))
- (not (gnus-check-backend-function 'request-replace-article group))))
-
-(defun gnus-group-total-expirable-p (group)
- "Check whether GROUP is total-expirable or not."
- (let ((params (gnus-info-params (gnus-get-info group))))
- (or (memq 'total-expire params)
- (cdr (assq 'total-expire params)) ; (total-expire . t)
- (and gnus-total-expirable-newsgroups ; Check var.
- (string-match gnus-total-expirable-newsgroups group)))))
-
-(defun gnus-group-auto-expirable-p (group)
- "Check whether GROUP is total-expirable or not."
- (let ((params (gnus-info-params (gnus-get-info group))))
- (or (memq 'auto-expire params)
- (cdr (assq 'auto-expire params)) ; (auto-expire . t)
- (and gnus-auto-expirable-newsgroups ; Check var.
- (string-match gnus-auto-expirable-newsgroups group)))))
-
-(defun gnus-virtual-group-p (group)
- "Say whether GROUP is virtual or not."
- (memq 'virtual (assoc (symbol-name (car (gnus-find-method-for-group group)))
- gnus-valid-select-methods)))
-
-(defun gnus-news-group-p (group &optional article)
- "Return non-nil if GROUP (and ARTICLE) come from a news server."
- (or (gnus-member-of-valid 'post group) ; Ordinary news group.
- (and (gnus-member-of-valid 'post-mail group) ; Combined group.
- (eq (gnus-request-type group article) 'news))))
-
-(defsubst gnus-simplify-subject-fully (subject)
- "Simplify a subject string according to the user's wishes."
- (cond
- ((null gnus-summary-gather-subject-limit)
- (gnus-simplify-subject-re subject))
- ((eq gnus-summary-gather-subject-limit 'fuzzy)
- (gnus-simplify-subject-fuzzy subject))
- ((numberp gnus-summary-gather-subject-limit)
- (gnus-limit-string (gnus-simplify-subject-re subject)
- gnus-summary-gather-subject-limit))
- (t
- subject)))
-
-(defsubst gnus-subject-equal (s1 s2 &optional simple-first)
- "Check whether two subjects are equal. If optional argument
-simple-first is t, first argument is already simplified."
- (cond
- ((null simple-first)
- (equal (gnus-simplify-subject-fully s1)
- (gnus-simplify-subject-fully s2)))
- (t
- (equal s1
- (gnus-simplify-subject-fully s2)))))
-
-;; Returns a list of writable groups.
-(defun gnus-writable-groups ()
- (let ((alist gnus-newsrc-alist)
- groups group)
- (while (setq group (car (pop alist)))
- (unless (gnus-group-read-only-p group)
- (push group groups)))
- (nreverse groups)))
-
-(defun gnus-completing-read (default prompt &rest args)
- ;; Like `completing-read', except that DEFAULT is the default argument.
- (let* ((prompt (if default
- (concat prompt " (default " default ") ")
- (concat prompt " ")))
- (answer (apply 'completing-read prompt args)))
- (if (or (null answer) (zerop (length answer)))
- default
- answer)))
-
-;; Two silly functions to ensure that all `y-or-n-p' questions clear
-;; the echo area.
-(defun gnus-y-or-n-p (prompt)
- (prog1
- (y-or-n-p prompt)
- (message "")))
-
-(defun gnus-yes-or-no-p (prompt)
- (prog1
- (yes-or-no-p prompt)
- (message "")))
-
-;; Check whether to use long file names.
-(defun gnus-use-long-file-name (symbol)
- ;; The variable has to be set...
- (and gnus-use-long-file-name
- ;; If it isn't a list, then we return t.
- (or (not (listp gnus-use-long-file-name))
- ;; If it is a list, and the list contains `symbol', we
- ;; return nil.
- (not (memq symbol gnus-use-long-file-name)))))
-
-;; I suspect there's a better way, but I haven't taken the time to do
-;; it yet. -erik selberg@cs.washington.edu
-(defun gnus-dd-mmm (messy-date)
- "Return a string like DD-MMM from a big messy string"
- (let ((datevec (condition-case () (timezone-parse-date messy-date)
- (error nil))))
- (if (not datevec)
- "??-???"
- (format "%2s-%s"
- (condition-case ()
- ;; Make sure leading zeroes are stripped.
- (number-to-string (string-to-number (aref datevec 2)))
- (error "??"))
- (capitalize
- (or (car
- (nth (1- (string-to-number (aref datevec 1)))
- timezone-months-assoc))
- "???"))))))
-
-(defun gnus-mode-string-quote (string)
- "Quote all \"%\" in STRING."
- (save-excursion
- (gnus-set-work-buffer)
- (insert string)
- (goto-char (point-min))
- (while (search-forward "%" nil t)
- (insert "%"))
- (buffer-string)))
-
-;; Make a hash table (default and minimum size is 255).
-;; Optional argument HASHSIZE specifies the table size.
-(defun gnus-make-hashtable (&optional hashsize)
- (make-vector (if hashsize (max (gnus-create-hash-size hashsize) 255) 255) 0))
-
-;; Make a number that is suitable for hashing; bigger than MIN and one
-;; less than 2^x.
-(defun gnus-create-hash-size (min)
- (let ((i 1))
- (while (< i min)
- (setq i (* 2 i)))
- (1- i)))
-
-;; Show message if message has a lower level than `gnus-verbose'.
-;; Guideline for numbers:
-;; 1 - error messages, 3 - non-serious error messages, 5 - messages
-;; for things that take a long time, 7 - not very important messages
-;; on stuff, 9 - messages inside loops.
-(defun gnus-message (level &rest args)
- (if (<= level gnus-verbose)
- (apply 'message args)
- ;; We have to do this format thingy here even if the result isn't
- ;; shown - the return value has to be the same as the return value
- ;; from `message'.
- (apply 'format args)))
-
-(defun gnus-error (level &rest args)
- "Beep an error if LEVEL is equal to or less than `gnus-verbose'."
- (when (<= (floor level) gnus-verbose)
- (apply 'message args)
- (ding)
- (let (duration)
- (when (and (floatp level)
- (not (zerop (setq duration (* 10 (- level (floor level)))))))
- (sit-for duration))))
- nil)
-
-;; Generate a unique new group name.
-(defun gnus-generate-new-group-name (leaf)
- (let ((name leaf)
- (num 0))
- (while (gnus-gethash name gnus-newsrc-hashtb)
- (setq name (concat leaf "<" (int-to-string (setq num (1+ num))) ">")))
- name))
-
-(defsubst gnus-hide-text (b e props)
- "Set text PROPS on the B to E region, extending `intangible' 1 past B."
- (gnus-add-text-properties b e props)
- (when (memq 'intangible props)
- (gnus-put-text-property (max (1- b) (point-min))
- b 'intangible (cddr (memq 'intangible props)))))
-
-(defsubst gnus-unhide-text (b e)
- "Remove hidden text properties from region between B and E."
- (remove-text-properties b e gnus-hidden-properties)
- (when (memq 'intangible gnus-hidden-properties)
- (gnus-put-text-property (max (1- b) (point-min))
- b 'intangible nil)))
-
-(defun gnus-hide-text-type (b e type)
- "Hide text of TYPE between B and E."
- (gnus-hide-text b e (cons 'gnus-type (cons type gnus-hidden-properties))))
-
-(defun gnus-parent-headers (headers &optional generation)
- "Return the headers of the GENERATIONeth parent of HEADERS."
- (unless generation
- (setq generation 1))
- (let (references parent)
- (while (and headers (not (zerop generation)))
- (setq references (mail-header-references headers))
- (when (and references
- (setq parent (gnus-parent-id references))
- (setq headers (car (gnus-id-to-thread parent))))
- (decf generation)))
- headers))
-
-(defun gnus-parent-id (references)
- "Return the last Message-ID in REFERENCES."
- (when (and references
- (string-match "\\(<[^\n<>]+>\\)[ \t\n]*\\'" references))
- (substring references (match-beginning 1) (match-end 1))))
-
-(defun gnus-split-references (references)
- "Return a list of Message-IDs in REFERENCES."
- (let ((beg 0)
- ids)
- (while (string-match "<[^>]+>" references beg)
- (push (substring references (match-beginning 0) (setq beg (match-end 0)))
- ids))
- (nreverse ids)))
-
-(defun gnus-buffer-live-p (buffer)
- "Say whether BUFFER is alive or not."
- (and buffer
- (get-buffer buffer)
- (buffer-name (get-buffer buffer))))
-
-(defun gnus-ephemeral-group-p (group)
- "Say whether GROUP is ephemeral or not."
- (gnus-group-get-parameter group 'quit-config))
-
-(defun gnus-group-quit-config (group)
- "Return the quit-config of GROUP."
- (gnus-group-get-parameter group 'quit-config))
-
-(defun gnus-simplify-mode-line ()
- "Make mode lines a bit simpler."
- (setq mode-line-modified "-- ")
- (when (listp mode-line-format)
- (make-local-variable 'mode-line-format)
- (setq mode-line-format (copy-sequence mode-line-format))
- (when (equal (nth 3 mode-line-format) " ")
- (setcar (nthcdr 3 mode-line-format) " "))))
-
-;;; List and range functions
-
-(defun gnus-last-element (list)
- "Return last element of LIST."
- (while (cdr list)
- (setq list (cdr list)))
- (car list))
-
-(defun gnus-copy-sequence (list)
- "Do a complete, total copy of a list."
- (if (and (consp list) (not (consp (cdr list))))
- (cons (car list) (cdr list))
- (mapcar (lambda (elem) (if (consp elem)
- (if (consp (cdr elem))
- (gnus-copy-sequence elem)
- (cons (car elem) (cdr elem)))
- elem))
- list)))
-
-(defun gnus-set-difference (list1 list2)
- "Return a list of elements of LIST1 that do not appear in LIST2."
- (let ((list1 (copy-sequence list1)))
- (while list2
- (setq list1 (delq (car list2) list1))
- (setq list2 (cdr list2)))
- list1))
-
-(defun gnus-sorted-complement (list1 list2)
- "Return a list of elements of LIST1 that do not appear in LIST2.
-Both lists have to be sorted over <."
- (let (out)
- (if (or (null list1) (null list2))
- (or list1 list2)
- (while (and list1 list2)
- (cond ((= (car list1) (car list2))
- (setq list1 (cdr list1)
- list2 (cdr list2)))
- ((< (car list1) (car list2))
- (setq out (cons (car list1) out))
- (setq list1 (cdr list1)))
- (t
- (setq out (cons (car list2) out))
- (setq list2 (cdr list2)))))
- (nconc (nreverse out) (or list1 list2)))))
-
-(defun gnus-intersection (list1 list2)
- (let ((result nil))
- (while list2
- (if (memq (car list2) list1)
- (setq result (cons (car list2) result)))
- (setq list2 (cdr list2)))
- result))
-
-(defun gnus-sorted-intersection (list1 list2)
- ;; LIST1 and LIST2 have to be sorted over <.
- (let (out)
- (while (and list1 list2)
- (cond ((= (car list1) (car list2))
- (setq out (cons (car list1) out)
- list1 (cdr list1)
- list2 (cdr list2)))
- ((< (car list1) (car list2))
- (setq list1 (cdr list1)))
- (t
- (setq list2 (cdr list2)))))
- (nreverse out)))
-
-(defun gnus-set-sorted-intersection (list1 list2)
- ;; LIST1 and LIST2 have to be sorted over <.
- ;; This function modifies LIST1.
- (let* ((top (cons nil list1))
- (prev top))
- (while (and list1 list2)
- (cond ((= (car list1) (car list2))
- (setq prev list1
- list1 (cdr list1)
- list2 (cdr list2)))
- ((< (car list1) (car list2))
- (setcdr prev (cdr list1))
- (setq list1 (cdr list1)))
- (t
- (setq list2 (cdr list2)))))
- (setcdr prev nil)
- (cdr top)))
-
-(defun gnus-compress-sequence (numbers &optional always-list)
- "Convert list of numbers to a list of ranges or a single range.
-If ALWAYS-LIST is non-nil, this function will always release a list of
-ranges."
- (let* ((first (car numbers))
- (last (car numbers))
- result)
- (if (null numbers)
- nil
- (if (not (listp (cdr numbers)))
- numbers
- (while numbers
- (cond ((= last (car numbers)) nil) ;Omit duplicated number
- ((= (1+ last) (car numbers)) ;Still in sequence
- (setq last (car numbers)))
- (t ;End of one sequence
- (setq result
- (cons (if (= first last) first
- (cons first last)) result))
- (setq first (car numbers))
- (setq last (car numbers))))
- (setq numbers (cdr numbers)))
- (if (and (not always-list) (null result))
- (if (= first last) (list first) (cons first last))
- (nreverse (cons (if (= first last) first (cons first last))
- result)))))))
-
-(defalias 'gnus-uncompress-sequence 'gnus-uncompress-range)
-(defun gnus-uncompress-range (ranges)
- "Expand a list of ranges into a list of numbers.
-RANGES is either a single range on the form `(num . num)' or a list of
-these ranges."
- (let (first last result)
- (cond
- ((null ranges)
- nil)
- ((not (listp (cdr ranges)))
- (setq first (car ranges))
- (setq last (cdr ranges))
- (while (<= first last)
- (setq result (cons first result))
- (setq first (1+ first)))
- (nreverse result))
- (t
- (while ranges
- (if (atom (car ranges))
- (if (numberp (car ranges))
- (setq result (cons (car ranges) result)))
- (setq first (caar ranges))
- (setq last (cdar ranges))
- (while (<= first last)
- (setq result (cons first result))
- (setq first (1+ first))))
- (setq ranges (cdr ranges)))
- (nreverse result)))))
-
-(defun gnus-add-to-range (ranges list)
- "Return a list of ranges that has all articles from both RANGES and LIST.
-Note: LIST has to be sorted over `<'."
- (if (not ranges)
- (gnus-compress-sequence list t)
- (setq list (copy-sequence list))
- (or (listp (cdr ranges))
- (setq ranges (list ranges)))
- (let ((out ranges)
- ilist lowest highest temp)
- (while (and ranges list)
- (setq ilist list)
- (setq lowest (or (and (atom (car ranges)) (car ranges))
- (caar ranges)))
- (while (and list (cdr list) (< (cadr list) lowest))
- (setq list (cdr list)))
- (if (< (car ilist) lowest)
- (progn
- (setq temp list)
- (setq list (cdr list))
- (setcdr temp nil)
- (setq out (nconc (gnus-compress-sequence ilist t) out))))
- (setq highest (or (and (atom (car ranges)) (car ranges))
- (cdar ranges)))
- (while (and list (<= (car list) highest))
- (setq list (cdr list)))
- (setq ranges (cdr ranges)))
- (if list
- (setq out (nconc (gnus-compress-sequence list t) out)))
- (setq out (sort out (lambda (r1 r2)
- (< (or (and (atom r1) r1) (car r1))
- (or (and (atom r2) r2) (car r2))))))
- (setq ranges out)
- (while ranges
- (if (atom (car ranges))
- (if (cdr ranges)
- (if (atom (cadr ranges))
- (if (= (1+ (car ranges)) (cadr ranges))
- (progn
- (setcar ranges (cons (car ranges)
- (cadr ranges)))
- (setcdr ranges (cddr ranges))))
- (if (= (1+ (car ranges)) (caadr ranges))
- (progn
- (setcar (cadr ranges) (car ranges))
- (setcar ranges (cadr ranges))
- (setcdr ranges (cddr ranges))))))
- (if (cdr ranges)
- (if (atom (cadr ranges))
- (if (= (1+ (cdar ranges)) (cadr ranges))
- (progn
- (setcdr (car ranges) (cadr ranges))
- (setcdr ranges (cddr ranges))))
- (if (= (1+ (cdar ranges)) (caadr ranges))
- (progn
- (setcdr (car ranges) (cdadr ranges))
- (setcdr ranges (cddr ranges)))))))
- (setq ranges (cdr ranges)))
- out)))
-
-(defun gnus-remove-from-range (ranges list)
- "Return a list of ranges that has all articles from LIST removed from RANGES.
-Note: LIST has to be sorted over `<'."
- ;; !!! This function shouldn't look like this, but I've got a headache.
- (gnus-compress-sequence
- (gnus-sorted-complement
- (gnus-uncompress-range ranges) list)))
-
-(defun gnus-member-of-range (number ranges)
- (if (not (listp (cdr ranges)))
- (and (>= number (car ranges))
- (<= number (cdr ranges)))
- (let ((not-stop t))
- (while (and ranges
- (if (numberp (car ranges))
- (>= number (car ranges))
- (>= number (caar ranges)))
- not-stop)
- (if (if (numberp (car ranges))
- (= number (car ranges))
- (and (>= number (caar ranges))
- (<= number (cdar ranges))))
- (setq not-stop nil))
- (setq ranges (cdr ranges)))
- (not not-stop))))
-
-(defun gnus-range-length (range)
- "Return the length RANGE would have if uncompressed."
- (length (gnus-uncompress-range range)))
-
-(defun gnus-sublist-p (list sublist)
- "Test whether all elements in SUBLIST are members of LIST."
- (let ((sublistp t))
- (while sublist
- (unless (memq (pop sublist) list)
- (setq sublistp nil
- sublist nil)))
- sublistp))
-
-
-;;;
-;;; Gnus group mode
-;;;
-
-(defvar gnus-group-mode-map nil)
-(put 'gnus-group-mode 'mode-class 'special)
-
-(unless gnus-group-mode-map
- (setq gnus-group-mode-map (make-keymap))
- (suppress-keymap gnus-group-mode-map)
-
- (gnus-define-keys gnus-group-mode-map
- " " gnus-group-read-group
- "=" gnus-group-select-group
- "\r" gnus-group-select-group
- "\M-\r" gnus-group-quick-select-group
- "j" gnus-group-jump-to-group
- "n" gnus-group-next-unread-group
- "p" gnus-group-prev-unread-group
- "\177" gnus-group-prev-unread-group
- [delete] gnus-group-prev-unread-group
- "N" gnus-group-next-group
- "P" gnus-group-prev-group
- "\M-n" gnus-group-next-unread-group-same-level
- "\M-p" gnus-group-prev-unread-group-same-level
- "," gnus-group-best-unread-group
- "." gnus-group-first-unread-group
- "u" gnus-group-unsubscribe-current-group
- "U" gnus-group-unsubscribe-group
- "c" gnus-group-catchup-current
- "C" gnus-group-catchup-current-all
- "l" gnus-group-list-groups
- "L" gnus-group-list-all-groups
- "m" gnus-group-mail
- "g" gnus-group-get-new-news
- "\M-g" gnus-group-get-new-news-this-group
- "R" gnus-group-restart
- "r" gnus-group-read-init-file
- "B" gnus-group-browse-foreign-server
- "b" gnus-group-check-bogus-groups
- "F" gnus-find-new-newsgroups
- "\C-c\C-d" gnus-group-describe-group
- "\M-d" gnus-group-describe-all-groups
- "\C-c\C-a" gnus-group-apropos
- "\C-c\M-\C-a" gnus-group-description-apropos
- "a" gnus-group-post-news
- "\ek" gnus-group-edit-local-kill
- "\eK" gnus-group-edit-global-kill
- "\C-k" gnus-group-kill-group
- "\C-y" gnus-group-yank-group
- "\C-w" gnus-group-kill-region
- "\C-x\C-t" gnus-group-transpose-groups
- "\C-c\C-l" gnus-group-list-killed
- "\C-c\C-x" gnus-group-expire-articles
- "\C-c\M-\C-x" gnus-group-expire-all-groups
- "V" gnus-version
- "s" gnus-group-save-newsrc
- "z" gnus-group-suspend
-; "Z" gnus-group-clear-dribble
- "q" gnus-group-exit
- "Q" gnus-group-quit
- "?" gnus-group-describe-briefly
- "\C-c\C-i" gnus-info-find-node
- "\M-e" gnus-group-edit-group-method
- "^" gnus-group-enter-server-mode
- gnus-mouse-2 gnus-mouse-pick-group
- "<" beginning-of-buffer
- ">" end-of-buffer
- "\C-c\C-b" gnus-bug
- "\C-c\C-s" gnus-group-sort-groups
- "t" gnus-topic-mode
- "\C-c\M-g" gnus-activate-all-groups
- "\M-&" gnus-group-universal-argument
- "#" gnus-group-mark-group
- "\M-#" gnus-group-unmark-group)
-
- (gnus-define-keys (gnus-group-mark-map "M" gnus-group-mode-map)
- "m" gnus-group-mark-group
- "u" gnus-group-unmark-group
- "w" gnus-group-mark-region
- "m" gnus-group-mark-buffer
- "r" gnus-group-mark-regexp
- "U" gnus-group-unmark-all-groups)
-
- (gnus-define-keys (gnus-group-group-map "G" gnus-group-mode-map)
- "d" gnus-group-make-directory-group
- "h" gnus-group-make-help-group
- "a" gnus-group-make-archive-group
- "k" gnus-group-make-kiboze-group
- "m" gnus-group-make-group
- "E" gnus-group-edit-group
- "e" gnus-group-edit-group-method
- "p" gnus-group-edit-group-parameters
- "v" gnus-group-add-to-virtual
- "V" gnus-group-make-empty-virtual
- "D" gnus-group-enter-directory
- "f" gnus-group-make-doc-group
- "r" gnus-group-rename-group
- "\177" gnus-group-delete-group
- [delete] gnus-group-delete-group)
-
- (gnus-define-keys (gnus-group-soup-map "s" gnus-group-group-map)
- "b" gnus-group-brew-soup
- "w" gnus-soup-save-areas
- "s" gnus-soup-send-replies
- "p" gnus-soup-pack-packet
- "r" nnsoup-pack-replies)
-
- (gnus-define-keys (gnus-group-sort-map "S" gnus-group-group-map)
- "s" gnus-group-sort-groups
- "a" gnus-group-sort-groups-by-alphabet
- "u" gnus-group-sort-groups-by-unread
- "l" gnus-group-sort-groups-by-level
- "v" gnus-group-sort-groups-by-score
- "r" gnus-group-sort-groups-by-rank
- "m" gnus-group-sort-groups-by-method)
-
- (gnus-define-keys (gnus-group-list-map "A" gnus-group-mode-map)
- "k" gnus-group-list-killed
- "z" gnus-group-list-zombies
- "s" gnus-group-list-groups
- "u" gnus-group-list-all-groups
- "A" gnus-group-list-active
- "a" gnus-group-apropos
- "d" gnus-group-description-apropos
- "m" gnus-group-list-matching
- "M" gnus-group-list-all-matching
- "l" gnus-group-list-level)
-
- (gnus-define-keys (gnus-group-score-map "W" gnus-group-mode-map)
- "f" gnus-score-flush-cache)
-
- (gnus-define-keys (gnus-group-help-map "H" gnus-group-mode-map)
- "f" gnus-group-fetch-faq)
-
- (gnus-define-keys (gnus-group-sub-map "S" gnus-group-mode-map)
- "l" gnus-group-set-current-level
- "t" gnus-group-unsubscribe-current-group
- "s" gnus-group-unsubscribe-group
- "k" gnus-group-kill-group
- "y" gnus-group-yank-group
- "w" gnus-group-kill-region
- "\C-k" gnus-group-kill-level
- "z" gnus-group-kill-all-zombies))
-
-(defun gnus-group-mode ()
- "Major mode for reading news.
-
-All normal editing commands are switched off.
-\\<gnus-group-mode-map>
-The group buffer lists (some of) the groups available. For instance,
-`\\[gnus-group-list-groups]' will list all subscribed groups with unread articles, while `\\[gnus-group-list-zombies]'
-lists all zombie groups.
-
-Groups that are displayed can be entered with `\\[gnus-group-read-group]'. To subscribe
-to a group not displayed, type `\\[gnus-group-unsubscribe-group]'.
-
-For more in-depth information on this mode, read the manual (`\\[gnus-info-find-node]').
-
-The following commands are available:
-
-\\{gnus-group-mode-map}"
- (interactive)
- (when (and menu-bar-mode
- (gnus-visual-p 'group-menu 'menu))
- (gnus-group-make-menu-bar))
- (kill-all-local-variables)
- (gnus-simplify-mode-line)
- (setq major-mode 'gnus-group-mode)
- (setq mode-name "Group")
- (gnus-group-set-mode-line)
- (setq mode-line-process nil)
- (use-local-map gnus-group-mode-map)
- (buffer-disable-undo (current-buffer))
- (setq truncate-lines t)
- (setq buffer-read-only t)
- (gnus-make-local-hook 'post-command-hook)
- (gnus-add-hook 'post-command-hook 'gnus-clear-inboxes-moved nil t)
- (run-hooks 'gnus-group-mode-hook))
-
-(defun gnus-clear-inboxes-moved ()
- (setq nnmail-moved-inboxes nil))
-
-(defun gnus-mouse-pick-group (e)
- "Enter the group under the mouse pointer."
- (interactive "e")
- (mouse-set-point e)
- (gnus-group-read-group nil))
-
-;; Look at LEVEL and find out what the level is really supposed to be.
-;; If LEVEL is non-nil, LEVEL will be returned, if not, what happens
-;; will depend on whether `gnus-group-use-permanent-levels' is used.
-(defun gnus-group-default-level (&optional level number-or-nil)
- (cond
- (gnus-group-use-permanent-levels
- (or (setq gnus-group-use-permanent-levels
- (or level (if (numberp gnus-group-use-permanent-levels)
- gnus-group-use-permanent-levels
- (or gnus-group-default-list-level
- gnus-level-subscribed))))
- gnus-group-default-list-level gnus-level-subscribed))
- (number-or-nil
- level)
- (t
- (or level gnus-group-default-list-level gnus-level-subscribed))))
-
-;;;###autoload
-(defun gnus-slave-no-server (&optional arg)
- "Read network news as a slave, without connecting to local server"
- (interactive "P")
- (gnus-no-server arg t))
-
-;;;###autoload
-(defun gnus-no-server (&optional arg slave)
- "Read network news.
-If ARG is a positive number, Gnus will use that as the
-startup level. If ARG is nil, Gnus will be started at level 2.
-If ARG is non-nil and not a positive number, Gnus will
-prompt the user for the name of an NNTP server to use.
-As opposed to `gnus', this command will not connect to the local server."
- (interactive "P")
- (let ((val (or arg (1- gnus-level-default-subscribed))))
- (gnus val t slave)
- (make-local-variable 'gnus-group-use-permanent-levels)
- (setq gnus-group-use-permanent-levels val)))
-
-;;;###autoload
-(defun gnus-slave (&optional arg)
- "Read news as a slave."
- (interactive "P")
- (gnus arg nil 'slave))
-
-;;;###autoload
-(defun gnus-other-frame (&optional arg)
- "Pop up a frame to read news."
- (interactive "P")
- (if (get-buffer gnus-group-buffer)
- (let ((pop-up-frames t))
- (gnus arg))
- (select-frame (make-frame))
- (gnus arg)))
-
-;;;###autoload
-(defun gnus (&optional arg dont-connect slave)
- "Read network news.
-If ARG is non-nil and a positive number, Gnus will use that as the
-startup level. If ARG is non-nil and not a positive number, Gnus will
-prompt the user for the name of an NNTP server to use."
- (interactive "P")
-
- (if (get-buffer gnus-group-buffer)
- (progn
- (switch-to-buffer gnus-group-buffer)
- (gnus-group-get-new-news))
-
- (gnus-clear-system)
- (nnheader-init-server-buffer)
- (gnus-read-init-file)
- (setq gnus-slave slave)
-
- (gnus-group-setup-buffer)
- (let ((buffer-read-only nil))
- (erase-buffer)
- (if (not gnus-inhibit-startup-message)
- (progn
- (gnus-group-startup-message)
- (sit-for 0))))
-
- (let ((level (and (numberp arg) (> arg 0) arg))
- did-connect)
- (unwind-protect
- (progn
- (or dont-connect
- (setq did-connect
- (gnus-start-news-server (and arg (not level))))))
- (if (and (not dont-connect)
- (not did-connect))
- (gnus-group-quit)
- (run-hooks 'gnus-startup-hook)
- ;; NNTP server is successfully open.
-
- ;; Find the current startup file name.
- (setq gnus-current-startup-file
- (gnus-make-newsrc-file gnus-startup-file))
-
- ;; Read the dribble file.
- (when (or gnus-slave gnus-use-dribble-file)
- (gnus-dribble-read-file))
-
- ;; Allow using GroupLens predictions.
- (when gnus-use-grouplens
- (bbb-login)
- (add-hook 'gnus-summary-mode-hook 'gnus-grouplens-mode))
-
- (gnus-summary-make-display-table)
- ;; Do the actual startup.
- (gnus-setup-news nil level dont-connect)
- ;; Generate the group buffer.
- (gnus-group-list-groups level)
- (gnus-group-first-unread-group)
- (gnus-configure-windows 'group)
- (gnus-group-set-mode-line))))))
-
-(defun gnus-unload ()
- "Unload all Gnus features."
- (interactive)
- (or (boundp 'load-history)
- (error "Sorry, `gnus-unload' is not implemented in this Emacs version."))
- (let ((history load-history)
- feature)
- (while history
- (and (string-match "^\\(gnus\\|nn\\)" (caar history))
- (setq feature (cdr (assq 'provide (car history))))
- (unload-feature feature 'force))
- (setq history (cdr history)))))
-
-(defun gnus-compile ()
- "Byte-compile the user-defined format specs."
- (interactive)
- (let ((entries gnus-format-specs)
- entry gnus-tmp-func)
- (save-excursion
- (gnus-message 7 "Compiling format specs...")
-
- (while entries
- (setq entry (pop entries))
- (if (eq (car entry) 'version)
- (setq gnus-format-specs (delq entry gnus-format-specs))
- (when (and (listp (caddr entry))
- (not (eq 'byte-code (caaddr entry))))
- (fset 'gnus-tmp-func
- `(lambda () ,(caddr entry)))
- (byte-compile 'gnus-tmp-func)
- (setcar (cddr entry) (gnus-byte-code 'gnus-tmp-func)))))
-
- (push (cons 'version emacs-version) gnus-format-specs)
-
- (gnus-message 7 "Compiling user specs...done"))))
-
-(defun gnus-indent-rigidly (start end arg)
- "Indent rigidly using only spaces and no tabs."
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (indent-rigidly start end arg)
- (goto-char (point-min))
- (while (search-forward "\t" nil t)
- (replace-match " " t t)))))
-
-(defun gnus-group-startup-message (&optional x y)
- "Insert startup message in current buffer."
- ;; Insert the message.
- (erase-buffer)
- (insert
- (format " %s
- _ ___ _ _
- _ ___ __ ___ __ _ ___
- __ _ ___ __ ___
- _ ___ _
- _ _ __ _
- ___ __ _
- __ _
- _ _ _
- _ _ _
- _ _ _
- __ ___
- _ _ _ _
- _ _
- _ _
- _ _
- _
- __
-
-"
- ""))
- ;; And then hack it.
- (gnus-indent-rigidly (point-min) (point-max)
- (/ (max (- (window-width) (or x 46)) 0) 2))
- (goto-char (point-min))
- (forward-line 1)
- (let* ((pheight (count-lines (point-min) (point-max)))
- (wheight (window-height))
- (rest (- wheight pheight)))
- (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n)))
- ;; Fontify some.
- (goto-char (point-min))
- (and (search-forward "Praxis" nil t)
- (gnus-put-text-property (match-beginning 0) (match-end 0) 'face 'bold))
- (goto-char (point-min))
- (let* ((mode-string (gnus-group-set-mode-line)))
- (setq mode-line-buffer-identification
- (list (concat gnus-version (substring (car mode-string) 4))))
- (set-buffer-modified-p t)))
-
-(defun gnus-group-setup-buffer ()
- (or (get-buffer gnus-group-buffer)
- (progn
- (switch-to-buffer gnus-group-buffer)
- (gnus-add-current-to-buffer-list)
- (gnus-group-mode)
- (and gnus-carpal (gnus-carpal-setup-buffer 'group)))))
-
-(defun gnus-group-list-groups (&optional level unread lowest)
- "List newsgroups with level LEVEL or lower that have unread articles.
-Default is all subscribed groups.
-If argument UNREAD is non-nil, groups with no unread articles are also
-listed."
- (interactive (list (if current-prefix-arg
- (prefix-numeric-value current-prefix-arg)
- (or
- (gnus-group-default-level nil t)
- gnus-group-default-list-level
- gnus-level-subscribed))))
- (or level
- (setq level (car gnus-group-list-mode)
- unread (cdr gnus-group-list-mode)))
- (setq level (gnus-group-default-level level))
- (gnus-group-setup-buffer) ;May call from out of group buffer
- (gnus-update-format-specifications)
- (let ((case-fold-search nil)
- (props (text-properties-at (gnus-point-at-bol)))
- (group (gnus-group-group-name)))
- (set-buffer gnus-group-buffer)
- (funcall gnus-group-prepare-function level unread lowest)
- (if (zerop (buffer-size))
- (gnus-message 5 gnus-no-groups-message)
- (goto-char (point-max))
- (when (or (not gnus-group-goto-next-group-function)
- (not (funcall gnus-group-goto-next-group-function
- group props)))
- (if (not group)
- ;; Go to the first group with unread articles.
- (gnus-group-search-forward t)
- ;; Find the right group to put point on. If the current group
- ;; has disappeared in the new listing, try to find the next
- ;; one. If no next one can be found, just leave point at the
- ;; first newsgroup in the buffer.
- (if (not (gnus-goto-char
- (text-property-any
- (point-min) (point-max)
- 'gnus-group (gnus-intern-safe group gnus-active-hashtb))))
- (let ((newsrc (cdddr (gnus-gethash group gnus-newsrc-hashtb))))
- (while (and newsrc
- (not (gnus-goto-char
- (text-property-any
- (point-min) (point-max) 'gnus-group
- (gnus-intern-safe
- (caar newsrc) gnus-active-hashtb)))))
- (setq newsrc (cdr newsrc)))
- (or newsrc (progn (goto-char (point-max))
- (forward-line -1)))))))
- ;; Adjust cursor point.
- (gnus-group-position-point))))
-
-(defun gnus-group-list-level (level &optional all)
- "List groups on LEVEL.
-If ALL (the prefix), also list groups that have no unread articles."
- (interactive "nList groups on level: \nP")
- (gnus-group-list-groups level all level))
-
-(defun gnus-group-prepare-flat (level &optional all lowest regexp)
- "List all newsgroups with unread articles of level LEVEL or lower.
-If ALL is non-nil, list groups that have no unread articles.
-If LOWEST is non-nil, list all newsgroups of level LOWEST or higher.
-If REGEXP, only list groups matching REGEXP."
- (set-buffer gnus-group-buffer)
- (let ((buffer-read-only nil)
- (newsrc (cdr gnus-newsrc-alist))
- (lowest (or lowest 1))
- info clevel unread group params)
- (erase-buffer)
- (if (< lowest gnus-level-zombie)
- ;; List living groups.
- (while newsrc
- (setq info (car newsrc)
- group (gnus-info-group info)
- params (gnus-info-params info)
- newsrc (cdr newsrc)
- unread (car (gnus-gethash group gnus-newsrc-hashtb)))
- (and unread ; This group might be bogus
- (or (not regexp)
- (string-match regexp group))
- (<= (setq clevel (gnus-info-level info)) level)
- (>= clevel lowest)
- (or all ; We list all groups?
- (if (eq unread t) ; Unactivated?
- gnus-group-list-inactive-groups ; We list unactivated
- (> unread 0)) ; We list groups with unread articles
- (and gnus-list-groups-with-ticked-articles
- (cdr (assq 'tick (gnus-info-marks info))))
- ; And groups with tickeds
- ;; Check for permanent visibility.
- (and gnus-permanently-visible-groups
- (string-match gnus-permanently-visible-groups
- group))
- (memq 'visible params)
- (cdr (assq 'visible params)))
- (gnus-group-insert-group-line
- group (gnus-info-level info)
- (gnus-info-marks info) unread (gnus-info-method info)))))
-
- ;; List dead groups.
- (and (>= level gnus-level-zombie) (<= lowest gnus-level-zombie)
- (gnus-group-prepare-flat-list-dead
- (setq gnus-zombie-list (sort gnus-zombie-list 'string<))
- gnus-level-zombie ?Z
- regexp))
- (and (>= level gnus-level-killed) (<= lowest gnus-level-killed)
- (gnus-group-prepare-flat-list-dead
- (setq gnus-killed-list (sort gnus-killed-list 'string<))
- gnus-level-killed ?K regexp))
-
- (gnus-group-set-mode-line)
- (setq gnus-group-list-mode (cons level all))
- (run-hooks 'gnus-group-prepare-hook)))
-
-(defun gnus-group-prepare-flat-list-dead (groups level mark regexp)
- ;; List zombies and killed lists somewhat faster, which was
- ;; suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>. It does
- ;; this by ignoring the group format specification altogether.
- (let (group)
- (if regexp
- ;; This loop is used when listing groups that match some
- ;; regexp.
- (while groups
- (setq group (pop groups))
- (when (string-match regexp group)
- (gnus-add-text-properties
- (point) (prog1 (1+ (point))
- (insert " " mark " *: " group "\n"))
- (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb)
- 'gnus-unread t
- 'gnus-level level))))
- ;; This loop is used when listing all groups.
- (while groups
- (gnus-add-text-properties
- (point) (prog1 (1+ (point))
- (insert " " mark " *: "
- (setq group (pop groups)) "\n"))
- (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb)
- 'gnus-unread t
- 'gnus-level level))))))
-
-(defmacro gnus-group-real-name (group)
- "Find the real name of a foreign newsgroup."
- `(let ((gname ,group))
- (if (string-match ":[^:]+$" gname)
- (substring gname (1+ (match-beginning 0)))
- gname)))
-
-(defsubst gnus-server-add-address (method)
- (let ((method-name (symbol-name (car method))))
- (if (and (memq 'address (assoc method-name gnus-valid-select-methods))
- (not (assq (intern (concat method-name "-address")) method)))
- (append method (list (list (intern (concat method-name "-address"))
- (nth 1 method))))
- method)))
-
-(defsubst gnus-server-get-method (group method)
- ;; Input either a server name, and extended server name, or a
- ;; select method, and return a select method.
- (cond ((stringp method)
- (gnus-server-to-method method))
- ((equal method gnus-select-method)
- gnus-select-method)
- ((and (stringp (car method)) group)
- (gnus-server-extend-method group method))
- ((and method (not group)
- (equal (cadr method) ""))
- method)
- (t
- (gnus-server-add-address method))))
-
-(defun gnus-server-to-method (server)
- "Map virtual server names to select methods."
- (or
- ;; Is this a method, perhaps?
- (and server (listp server) server)
- ;; Perhaps this is the native server?
- (and (equal server "native") gnus-select-method)
- ;; It should be in the server alist.
- (cdr (assoc server gnus-server-alist))
- ;; If not, we look through all the opened server
- ;; to see whether we can find it there.
- (let ((opened gnus-opened-servers))
- (while (and opened
- (not (equal server (format "%s:%s" (caaar opened)
- (cadaar opened)))))
- (pop opened))
- (caar opened))))
-
-(defmacro gnus-method-equal (ss1 ss2)
- "Say whether two servers are equal."
- `(let ((s1 ,ss1)
- (s2 ,ss2))
- (or (equal s1 s2)
- (and (= (length s1) (length s2))
- (progn
- (while (and s1 (member (car s1) s2))
- (setq s1 (cdr s1)))
- (null s1))))))
-
-(defun gnus-server-equal (m1 m2)
- "Say whether two methods are equal."
- (let ((m1 (cond ((null m1) gnus-select-method)
- ((stringp m1) (gnus-server-to-method m1))
- (t m1)))
- (m2 (cond ((null m2) gnus-select-method)
- ((stringp m2) (gnus-server-to-method m2))
- (t m2))))
- (gnus-method-equal m1 m2)))
-
-(defun gnus-servers-using-backend (backend)
- "Return a list of known servers using BACKEND."
- (let ((opened gnus-opened-servers)
- out)
- (while opened
- (when (eq backend (caaar opened))
- (push (caar opened) out))
- (pop opened))
- out))
-
-(defun gnus-archive-server-wanted-p ()
- "Say whether the user wants to use the archive server."
- (cond
- ((or (not gnus-message-archive-method)
- (not gnus-message-archive-group))
- nil)
- ((and gnus-message-archive-method gnus-message-archive-group)
- t)
- (t
- (let ((active (cadr (assq 'nnfolder-active-file
- gnus-message-archive-method))))
- (and active
- (file-exists-p active))))))
-
-(defun gnus-group-prefixed-name (group method)
- "Return the whole name from GROUP and METHOD."
- (and (stringp method) (setq method (gnus-server-to-method method)))
- (concat (format "%s" (car method))
- (if (and
- (or (assoc (format "%s" (car method))
- (gnus-methods-using 'address))
- (gnus-server-equal method gnus-message-archive-method))
- (nth 1 method)
- (not (string= (nth 1 method) "")))
- (concat "+" (nth 1 method)))
- ":" group))
-
-(defun gnus-group-real-prefix (group)
- "Return the prefix of the current group name."
- (if (string-match "^[^:]+:" group)
- (substring group 0 (match-end 0))
- ""))
-
-(defun gnus-group-method (group)
- "Return the server or method used for selecting GROUP."
- (let ((prefix (gnus-group-real-prefix group)))
- (if (equal prefix "")
- gnus-select-method
- (let ((servers gnus-opened-servers)
- (server "")
- backend possible found)
- (if (string-match "^[^\\+]+\\+" prefix)
- (setq backend (intern (substring prefix 0 (1- (match-end 0))))
- server (substring prefix (match-end 0) (1- (length prefix))))
- (setq backend (intern (substring prefix 0 (1- (length prefix))))))
- (while servers
- (when (eq (caaar servers) backend)
- (setq possible (caar servers))
- (when (equal (cadaar servers) server)
- (setq found (caar servers))))
- (pop servers))
- (or (car (rassoc found gnus-server-alist))
- found
- (car (rassoc possible gnus-server-alist))
- possible
- (list backend server))))))
-
-(defsubst gnus-secondary-method-p (method)
- "Return whether METHOD is a secondary select method."
- (let ((methods gnus-secondary-select-methods)
- (gmethod (gnus-server-get-method nil method)))
- (while (and methods
- (not (equal (gnus-server-get-method nil (car methods))
- gmethod)))
- (setq methods (cdr methods)))
- methods))
-
-(defun gnus-group-foreign-p (group)
- "Say whether a group is foreign or not."
- (and (not (gnus-group-native-p group))
- (not (gnus-group-secondary-p group))))
-
-(defun gnus-group-native-p (group)
- "Say whether the group is native or not."
- (not (string-match ":" group)))
-
-(defun gnus-group-secondary-p (group)
- "Say whether the group is secondary or not."
- (gnus-secondary-method-p (gnus-find-method-for-group group)))
-
-(defun gnus-group-get-parameter (group &optional symbol)
- "Returns the group parameters for GROUP.
-If SYMBOL, return the value of that symbol in the group parameters."
- (let ((params (gnus-info-params (gnus-get-info group))))
- (if symbol
- (gnus-group-parameter-value params symbol)
- params)))
-
-(defun gnus-group-parameter-value (params symbol)
- "Return the value of SYMBOL in group PARAMS."
- (or (car (memq symbol params)) ; It's either a simple symbol
- (cdr (assq symbol params)))) ; or a cons.
-
-(defun gnus-group-add-parameter (group param)
- "Add parameter PARAM to GROUP."
- (let ((info (gnus-get-info group)))
- (if (not info)
- () ; This is a dead group. We just ignore it.
- ;; Cons the new param to the old one and update.
- (gnus-group-set-info (cons param (gnus-info-params info))
- group 'params))))
-
-(defun gnus-group-set-parameter (group name value)
- "Set parameter NAME to VALUE in GROUP."
- (let ((info (gnus-get-info group)))
- (if (not info)
- () ; This is a dead group. We just ignore it.
- (let ((old-params (gnus-info-params info))
- (new-params (list (cons name value))))
- (while old-params
- (if (or (not (listp (car old-params)))
- (not (eq (caar old-params) name)))
- (setq new-params (append new-params (list (car old-params)))))
- (setq old-params (cdr old-params)))
- (gnus-group-set-info new-params group 'params)))))
-
-(defun gnus-group-add-score (group &optional score)
- "Add SCORE to the GROUP score.
-If SCORE is nil, add 1 to the score of GROUP."
- (let ((info (gnus-get-info group)))
- (when info
- (gnus-info-set-score info (+ (gnus-info-score info) (or score 1))))))
-
-(defun gnus-summary-bubble-group ()
- "Increase the score of the current group.
-This is a handy function to add to `gnus-summary-exit-hook' to
-increase the score of each group you read."
- (gnus-group-add-score gnus-newsgroup-name))
-
-(defun gnus-group-set-info (info &optional method-only-group part)
- (let* ((entry (gnus-gethash
- (or method-only-group (gnus-info-group info))
- gnus-newsrc-hashtb))
- (part-info info)
- (info (if method-only-group (nth 2 entry) info))
- method)
- (when method-only-group
- (unless entry
- (error "Trying to change non-existent group %s" method-only-group))
- ;; We have received parts of the actual group info - either the
- ;; select method or the group parameters. We first check
- ;; whether we have to extend the info, and if so, do that.
- (let ((len (length info))
- (total (if (eq part 'method) 5 6)))
- (when (< len total)
- (setcdr (nthcdr (1- len) info)
- (make-list (- total len) nil)))
- ;; Then we enter the new info.
- (setcar (nthcdr (1- total) info) part-info)))
- (unless entry
- ;; This is a new group, so we just create it.
- (save-excursion
- (set-buffer gnus-group-buffer)
- (setq method (gnus-info-method info))
- (when (gnus-server-equal method "native")
- (setq method nil))
- (save-excursion
- (set-buffer gnus-group-buffer)
- (if method
- ;; It's a foreign group...
- (gnus-group-make-group
- (gnus-group-real-name (gnus-info-group info))
- (if (stringp method) method
- (prin1-to-string (car method)))
- (and (consp method)
- (nth 1 (gnus-info-method info))))
- ;; It's a native group.
- (gnus-group-make-group (gnus-info-group info))))
- (gnus-message 6 "Note: New group created")
- (setq entry
- (gnus-gethash (gnus-group-prefixed-name
- (gnus-group-real-name (gnus-info-group info))
- (or (gnus-info-method info) gnus-select-method))
- gnus-newsrc-hashtb))))
- ;; Whether it was a new group or not, we now have the entry, so we
- ;; can do the update.
- (if entry
- (progn
- (setcar (nthcdr 2 entry) info)
- (when (and (not (eq (car entry) t))
- (gnus-active (gnus-info-group info)))
- (setcar entry (length (gnus-list-of-unread-articles (car info))))))
- (error "No such group: %s" (gnus-info-group info)))))
-
-(defun gnus-group-set-method-info (group select-method)
- (gnus-group-set-info select-method group 'method))
-
-(defun gnus-group-set-params-info (group params)
- (gnus-group-set-info params group 'params))
-
-(defun gnus-group-update-group-line ()
- "Update the current line in the group buffer."
- (let* ((buffer-read-only nil)
- (group (gnus-group-group-name))
- (entry (and group (gnus-gethash group gnus-newsrc-hashtb)))
- gnus-group-indentation)
- (when group
- (and entry
- (not (gnus-ephemeral-group-p group))
- (gnus-dribble-enter
- (concat "(gnus-group-set-info '"
- (prin1-to-string (nth 2 entry)) ")")))
- (setq gnus-group-indentation (gnus-group-group-indentation))
- (gnus-delete-line)
- (gnus-group-insert-group-line-info group)
- (forward-line -1)
- (gnus-group-position-point))))
-
-(defun gnus-group-insert-group-line-info (group)
- "Insert GROUP on the current line."
- (let ((entry (gnus-gethash group gnus-newsrc-hashtb))
- active info)
- (if entry
- (progn
- ;; (Un)subscribed group.
- (setq info (nth 2 entry))
- (gnus-group-insert-group-line
- group (gnus-info-level info) (gnus-info-marks info)
- (or (car entry) t) (gnus-info-method info)))
- ;; This group is dead.
- (gnus-group-insert-group-line
- group
- (if (member group gnus-zombie-list) gnus-level-zombie gnus-level-killed)
- nil
- (if (setq active (gnus-active group))
- (- (1+ (cdr active)) (car active)) 0)
- nil))))
-
-(defun gnus-group-insert-group-line (gnus-tmp-group gnus-tmp-level
- gnus-tmp-marked number
- gnus-tmp-method)
- "Insert a group line in the group buffer."
- (let* ((gnus-tmp-active (gnus-active gnus-tmp-group))
- (gnus-tmp-number-total
- (if gnus-tmp-active
- (1+ (- (cdr gnus-tmp-active) (car gnus-tmp-active)))
- 0))
- (gnus-tmp-number-of-unread
- (if (numberp number) (int-to-string (max 0 number))
- "*"))
- (gnus-tmp-number-of-read
- (if (numberp number)
- (int-to-string (max 0 (- gnus-tmp-number-total number)))
- "*"))
- (gnus-tmp-subscribed
- (cond ((<= gnus-tmp-level gnus-level-subscribed) ? )
- ((<= gnus-tmp-level gnus-level-unsubscribed) ?U)
- ((= gnus-tmp-level gnus-level-zombie) ?Z)
- (t ?K)))
- (gnus-tmp-qualified-group (gnus-group-real-name gnus-tmp-group))
- (gnus-tmp-newsgroup-description
- (if gnus-description-hashtb
- (or (gnus-gethash gnus-tmp-group gnus-description-hashtb) "")
- ""))
- (gnus-tmp-moderated
- (if (member gnus-tmp-group gnus-moderated-list) ?m ? ))
- (gnus-tmp-moderated-string
- (if (eq gnus-tmp-moderated ?m) "(m)" ""))
- (gnus-tmp-method
- (gnus-server-get-method gnus-tmp-group gnus-tmp-method))
- (gnus-tmp-news-server (or (cadr gnus-tmp-method) ""))
- (gnus-tmp-news-method (or (car gnus-tmp-method) ""))
- (gnus-tmp-news-method-string
- (if gnus-tmp-method
- (format "(%s:%s)" (car gnus-tmp-method)
- (cadr gnus-tmp-method)) ""))
- (gnus-tmp-marked-mark
- (if (and (numberp number)
- (zerop number)
- (cdr (assq 'tick gnus-tmp-marked)))
- ?* ? ))
- (gnus-tmp-process-marked
- (if (member gnus-tmp-group gnus-group-marked)
- gnus-process-mark ? ))
- (gnus-tmp-grouplens
- (or (and gnus-use-grouplens
- (bbb-grouplens-group-p gnus-tmp-group))
- ""))
- (buffer-read-only nil)
- header gnus-tmp-header) ; passed as parameter to user-funcs.
- (beginning-of-line)
- (gnus-add-text-properties
- (point)
- (prog1 (1+ (point))
- ;; Insert the text.
- (eval gnus-group-line-format-spec))
- `(gnus-group ,(gnus-intern-safe gnus-tmp-group gnus-active-hashtb)
- gnus-unread ,(if (numberp number)
- (string-to-int gnus-tmp-number-of-unread)
- t)
- gnus-marked ,gnus-tmp-marked-mark
- gnus-indentation ,gnus-group-indentation
- gnus-level ,gnus-tmp-level))
- (when (inline (gnus-visual-p 'group-highlight 'highlight))
- (forward-line -1)
- (run-hooks 'gnus-group-update-hook)
- (forward-line))
- ;; Allow XEmacs to remove front-sticky text properties.
- (gnus-group-remove-excess-properties)))
-
-(defun gnus-group-update-group (group &optional visible-only)
- "Update all lines where GROUP appear.
-If VISIBLE-ONLY is non-nil, the group won't be displayed if it isn't
-already."
- (save-excursion
- (set-buffer gnus-group-buffer)
- ;; The buffer may be narrowed.
- (save-restriction
- (widen)
- (let ((ident (gnus-intern-safe group gnus-active-hashtb))
- (loc (point-min))
- found buffer-read-only)
- ;; Enter the current status into the dribble buffer.
- (let ((entry (gnus-gethash group gnus-newsrc-hashtb)))
- (if (and entry (not (gnus-ephemeral-group-p group)))
- (gnus-dribble-enter
- (concat "(gnus-group-set-info '" (prin1-to-string (nth 2 entry))
- ")"))))
- ;; Find all group instances. If topics are in use, each group
- ;; may be listed in more than once.
- (while (setq loc (text-property-any
- loc (point-max) 'gnus-group ident))
- (setq found t)
- (goto-char loc)
- (let ((gnus-group-indentation (gnus-group-group-indentation)))
- (gnus-delete-line)
- (gnus-group-insert-group-line-info group)
- (save-excursion
- (forward-line -1)
- (run-hooks 'gnus-group-update-group-hook)))
- (setq loc (1+ loc)))
- (unless (or found visible-only)
- ;; No such line in the buffer, find out where it's supposed to
- ;; go, and insert it there (or at the end of the buffer).
- (if gnus-goto-missing-group-function
- (funcall gnus-goto-missing-group-function group)
- (let ((entry (cddr (gnus-gethash group gnus-newsrc-hashtb))))
- (while (and entry (car entry)
- (not
- (gnus-goto-char
- (text-property-any
- (point-min) (point-max)
- 'gnus-group (gnus-intern-safe
- (caar entry) gnus-active-hashtb)))))
- (setq entry (cdr entry)))
- (or entry (goto-char (point-max)))))
- ;; Finally insert the line.
- (let ((gnus-group-indentation (gnus-group-group-indentation)))
- (gnus-group-insert-group-line-info group)
- (save-excursion
- (forward-line -1)
- (run-hooks 'gnus-group-update-group-hook))))
- (gnus-group-set-mode-line)))))
-
-(defun gnus-group-set-mode-line ()
- "Update the mode line in the group buffer."
- (when (memq 'group gnus-updated-mode-lines)
- ;; Yes, we want to keep this mode line updated.
- (save-excursion
- (set-buffer gnus-group-buffer)
- (let* ((gformat (or gnus-group-mode-line-format-spec
- (setq gnus-group-mode-line-format-spec
- (gnus-parse-format
- gnus-group-mode-line-format
- gnus-group-mode-line-format-alist))))
- (gnus-tmp-news-server (cadr gnus-select-method))
- (gnus-tmp-news-method (car gnus-select-method))
- (gnus-tmp-colon (if (equal gnus-tmp-news-server "") "" ":"))
- (max-len 60)
- gnus-tmp-header ;Dummy binding for user-defined formats
- ;; Get the resulting string.
- (modified
- (and gnus-dribble-buffer
- (buffer-name gnus-dribble-buffer)
- (buffer-modified-p gnus-dribble-buffer)
- (save-excursion
- (set-buffer gnus-dribble-buffer)
- (not (zerop (buffer-size))))))
- (mode-string (eval gformat)))
- ;; Say whether the dribble buffer has been modified.
- (setq mode-line-modified
- (if modified "---*- " "----- "))
- ;; If the line is too long, we chop it off.
- (when (> (length mode-string) max-len)
- (setq mode-string (substring mode-string 0 (- max-len 4))))
- (prog1
- (setq mode-line-buffer-identification
- (gnus-mode-line-buffer-identification
- (list mode-string)))
- (set-buffer-modified-p modified))))))
-
-(defun gnus-group-group-name ()
- "Get the name of the newsgroup on the current line."
- (let ((group (get-text-property (gnus-point-at-bol) 'gnus-group)))
- (and group (symbol-name group))))
-
-(defun gnus-group-group-level ()
- "Get the level of the newsgroup on the current line."
- (get-text-property (gnus-point-at-bol) 'gnus-level))
-
-(defun gnus-group-group-indentation ()
- "Get the indentation of the newsgroup on the current line."
- (or (get-text-property (gnus-point-at-bol) 'gnus-indentation)
- (and gnus-group-indentation-function
- (funcall gnus-group-indentation-function))
- ""))
-
-(defun gnus-group-group-unread ()
- "Get the number of unread articles of the newsgroup on the current line."
- (get-text-property (gnus-point-at-bol) 'gnus-unread))
-
-(defun gnus-group-search-forward (&optional backward all level first-too)
- "Find the next newsgroup with unread articles.
-If BACKWARD is non-nil, find the previous newsgroup instead.
-If ALL is non-nil, just find any newsgroup.
-If LEVEL is non-nil, find group with level LEVEL, or higher if no such
-group exists.
-If FIRST-TOO, the current line is also eligible as a target."
- (let ((way (if backward -1 1))
- (low gnus-level-killed)
- (beg (point))
- pos found lev)
- (if (and backward (progn (beginning-of-line)) (bobp))
- nil
- (or first-too (forward-line way))
- (while (and
- (not (eobp))
- (not (setq
- found
- (and (or all
- (and
- (let ((unread
- (get-text-property (point) 'gnus-unread)))
- (and (numberp unread) (> unread 0)))
- (setq lev (get-text-property (point)
- 'gnus-level))
- (<= lev gnus-level-subscribed)))
- (or (not level)
- (and (setq lev (get-text-property (point)
- 'gnus-level))
- (or (= lev level)
- (and (< lev low)
- (< level lev)
- (progn
- (setq low lev)
- (setq pos (point))
- nil))))))))
- (zerop (forward-line way)))))
- (if found
- (progn (gnus-group-position-point) t)
- (goto-char (or pos beg))
- (and pos t))))
-
-;;; Gnus group mode commands
-
-;; Group marking.
-
-(defun gnus-group-mark-group (n &optional unmark no-advance)
- "Mark the current group."
- (interactive "p")
- (let ((buffer-read-only nil)
- group)
- (while (and (> n 0)
- (not (eobp)))
- (when (setq group (gnus-group-group-name))
- ;; Update the mark.
- (beginning-of-line)
- (forward-char
- (or (cdr (assq 'process gnus-group-mark-positions)) 2))
- (delete-char 1)
- (if unmark
- (progn
- (insert " ")
- (setq gnus-group-marked (delete group gnus-group-marked)))
- (insert "#")
- (setq gnus-group-marked
- (cons group (delete group gnus-group-marked)))))
- (or no-advance (gnus-group-next-group 1))
- (decf n))
- (gnus-summary-position-point)
- n))
-
-(defun gnus-group-unmark-group (n)
- "Remove the mark from the current group."
- (interactive "p")
- (gnus-group-mark-group n 'unmark)
- (gnus-group-position-point))
-
-(defun gnus-group-unmark-all-groups ()
- "Unmark all groups."
- (interactive)
- (let ((groups gnus-group-marked))
- (save-excursion
- (while groups
- (gnus-group-remove-mark (pop groups)))))
- (gnus-group-position-point))
-
-(defun gnus-group-mark-region (unmark beg end)
- "Mark all groups between point and mark.
-If UNMARK, remove the mark instead."
- (interactive "P\nr")
- (let ((num (count-lines beg end)))
- (save-excursion
- (goto-char beg)
- (- num (gnus-group-mark-group num unmark)))))
-
-(defun gnus-group-mark-buffer (&optional unmark)
- "Mark all groups in the buffer.
-If UNMARK, remove the mark instead."
- (interactive "P")
- (gnus-group-mark-region unmark (point-min) (point-max)))
-
-(defun gnus-group-mark-regexp (regexp)
- "Mark all groups that match some regexp."
- (interactive "sMark (regexp): ")
- (let ((alist (cdr gnus-newsrc-alist))
- group)
- (while alist
- (when (string-match regexp (setq group (gnus-info-group (pop alist))))
- (gnus-group-set-mark group))))
- (gnus-group-position-point))
-
-(defun gnus-group-remove-mark (group)
- "Remove the process mark from GROUP and move point there.
-Return nil if the group isn't displayed."
- (if (gnus-group-goto-group group)
- (save-excursion
- (gnus-group-mark-group 1 'unmark t)
- t)
- (setq gnus-group-marked
- (delete group gnus-group-marked))
- nil))
-
-(defun gnus-group-set-mark (group)
- "Set the process mark on GROUP."
- (if (gnus-group-goto-group group)
- (save-excursion
- (gnus-group-mark-group 1 nil t))
- (setq gnus-group-marked (cons group (delete group gnus-group-marked)))))
-
-(defun gnus-group-universal-argument (arg &optional groups func)
- "Perform any command on all groups accoring to the process/prefix convention."
- (interactive "P")
- (let ((groups (or groups (gnus-group-process-prefix arg)))
- group func)
- (if (eq (setq func (or func
- (key-binding
- (read-key-sequence
- (substitute-command-keys
- "\\<gnus-group-mode-map>\\[gnus-group-universal-argument]")))))
- 'undefined)
- (gnus-error 1 "Undefined key")
- (while groups
- (gnus-group-remove-mark (setq group (pop groups)))
- (command-execute func))))
- (gnus-group-position-point))
-
-(defun gnus-group-process-prefix (n)
- "Return a list of groups to work on.
-Take into consideration N (the prefix) and the list of marked groups."
- (cond
- (n
- (setq n (prefix-numeric-value n))
- ;; There is a prefix, so we return a list of the N next
- ;; groups.
- (let ((way (if (< n 0) -1 1))
- (n (abs n))
- group groups)
- (save-excursion
- (while (and (> n 0)
- (setq group (gnus-group-group-name)))
- (setq groups (cons group groups))
- (setq n (1- n))
- (gnus-group-next-group way)))
- (nreverse groups)))
- ((and (boundp 'transient-mark-mode)
- transient-mark-mode
- (boundp 'mark-active)
- mark-active)
- ;; Work on the region between point and mark.
- (let ((max (max (point) (mark)))
- groups)
- (save-excursion
- (goto-char (min (point) (mark)))
- (while
- (and
- (push (gnus-group-group-name) groups)
- (zerop (gnus-group-next-group 1))
- (< (point) max)))
- (nreverse groups))))
- (gnus-group-marked
- ;; No prefix, but a list of marked articles.
- (reverse gnus-group-marked))
- (t
- ;; Neither marked articles or a prefix, so we return the
- ;; current group.
- (let ((group (gnus-group-group-name)))
- (and group (list group))))))
-
-;; Selecting groups.
-
-(defun gnus-group-read-group (&optional all no-article group)
- "Read news in this newsgroup.
-If the prefix argument ALL is non-nil, already read articles become
-readable. IF ALL is a number, fetch this number of articles. If the
-optional argument NO-ARTICLE is non-nil, no article will be
-auto-selected upon group entry. If GROUP is non-nil, fetch that
-group."
- (interactive "P")
- (let ((group (or group (gnus-group-group-name)))
- number active marked entry)
- (or group (error "No group on current line"))
- (setq marked (nth 3 (nth 2 (setq entry (gnus-gethash
- group gnus-newsrc-hashtb)))))
- ;; This group might be a dead group. In that case we have to get
- ;; the number of unread articles from `gnus-active-hashtb'.
- (setq number
- (cond ((numberp all) all)
- (entry (car entry))
- ((setq active (gnus-active group))
- (- (1+ (cdr active)) (car active)))))
- (gnus-summary-read-group
- group (or all (and (numberp number)
- (zerop (+ number (gnus-range-length
- (cdr (assq 'tick marked)))
- (gnus-range-length
- (cdr (assq 'dormant marked)))))))
- no-article)))
-
-(defun gnus-group-select-group (&optional all)
- "Select this newsgroup.
-No article is selected automatically.
-If ALL is non-nil, already read articles become readable.
-If ALL is a number, fetch this number of articles."
- (interactive "P")
- (gnus-group-read-group all t))
-
-(defun gnus-group-quick-select-group (&optional all)
- "Select the current group \"quickly\".
-This means that no highlighting or scoring will be performed."
- (interactive "P")
- (let (gnus-visual
- gnus-score-find-score-files-function
- gnus-apply-kill-hook
- gnus-summary-expunge-below)
- (gnus-group-read-group all t)))
-
-(defun gnus-group-visible-select-group (&optional all)
- "Select the current group without hiding any articles."
- (interactive "P")
- (let ((gnus-inhibit-limiting t))
- (gnus-group-read-group all t)))
-
-;;;###autoload
-(defun gnus-fetch-group (group)
- "Start Gnus if necessary and enter GROUP.
-Returns whether the fetching was successful or not."
- (interactive "sGroup name: ")
- (or (get-buffer gnus-group-buffer)
- (gnus))
- (gnus-group-read-group nil nil group))
-
-;; Enter a group that is not in the group buffer. Non-nil is returned
-;; if selection was successful.
-(defun gnus-group-read-ephemeral-group
- (group method &optional activate quit-config)
- (let ((group (if (gnus-group-foreign-p group) group
- (gnus-group-prefixed-name group method))))
- (gnus-sethash
- group
- `(t nil (,group ,gnus-level-default-subscribed nil nil ,method
- ((quit-config . ,(if quit-config quit-config
- (cons (current-buffer) 'summary))))))
- gnus-newsrc-hashtb)
- (set-buffer gnus-group-buffer)
- (or (gnus-check-server method)
- (error "Unable to contact server: %s" (gnus-status-message method)))
- (if activate (or (gnus-request-group group)
- (error "Couldn't request group")))
- (condition-case ()
- (gnus-group-read-group t t group)
- (error nil)
- (quit nil))))
-
-(defun gnus-group-jump-to-group (group)
- "Jump to newsgroup GROUP."
- (interactive
- (list (completing-read
- "Group: " gnus-active-hashtb nil
- (gnus-read-active-file-p)
- nil
- 'gnus-group-history)))
-
- (when (equal group "")
- (error "Empty group name"))
-
- (when (string-match "[\000-\032]" group)
- (error "Control characters in group: %s" group))
-
- (let ((b (text-property-any
- (point-min) (point-max)
- 'gnus-group (gnus-intern-safe group gnus-active-hashtb))))
- (unless (gnus-ephemeral-group-p group)
- (if b
- ;; Either go to the line in the group buffer...
- (goto-char b)
- ;; ... or insert the line.
- (or
- (gnus-active group)
- (gnus-activate-group group)
- (error "%s error: %s" group (gnus-status-message group)))
-
- (gnus-group-update-group group)
- (goto-char (text-property-any
- (point-min) (point-max)
- 'gnus-group (gnus-intern-safe group gnus-active-hashtb)))))
- ;; Adjust cursor point.
- (gnus-group-position-point)))
-
-(defun gnus-group-goto-group (group)
- "Goto to newsgroup GROUP."
- (when group
- (let ((b (text-property-any (point-min) (point-max)
- 'gnus-group (gnus-intern-safe
- group gnus-active-hashtb))))
- (and b (goto-char b)))))
-
-(defun gnus-group-next-group (n)
- "Go to next N'th newsgroup.
-If N is negative, search backward instead.
-Returns the difference between N and the number of skips actually
-done."
- (interactive "p")
- (gnus-group-next-unread-group n t))
-
-(defun gnus-group-next-unread-group (n &optional all level)
- "Go to next N'th unread newsgroup.
-If N is negative, search backward instead.
-If ALL is non-nil, choose any newsgroup, unread or not.
-If LEVEL is non-nil, choose the next group with level LEVEL, or, if no
-such group can be found, the next group with a level higher than
-LEVEL.
-Returns the difference between N and the number of skips actually
-made."
- (interactive "p")
- (let ((backward (< n 0))
- (n (abs n)))
- (while (and (> n 0)
- (gnus-group-search-forward
- backward (or (not gnus-group-goto-unread) all) level))
- (setq n (1- n)))
- (if (/= 0 n) (gnus-message 7 "No more%s newsgroups%s" (if all "" " unread")
- (if level " on this level or higher" "")))
- n))
-
-(defun gnus-group-prev-group (n)
- "Go to previous N'th newsgroup.
-Returns the difference between N and the number of skips actually
-done."
- (interactive "p")
- (gnus-group-next-unread-group (- n) t))
-
-(defun gnus-group-prev-unread-group (n)
- "Go to previous N'th unread newsgroup.
-Returns the difference between N and the number of skips actually
-done."
- (interactive "p")
- (gnus-group-next-unread-group (- n)))
-
-(defun gnus-group-next-unread-group-same-level (n)
- "Go to next N'th unread newsgroup on the same level.
-If N is negative, search backward instead.
-Returns the difference between N and the number of skips actually
-done."
- (interactive "p")
- (gnus-group-next-unread-group n t (gnus-group-group-level))
- (gnus-group-position-point))
-
-(defun gnus-group-prev-unread-group-same-level (n)
- "Go to next N'th unread newsgroup on the same level.
-Returns the difference between N and the number of skips actually
-done."
- (interactive "p")
- (gnus-group-next-unread-group (- n) t (gnus-group-group-level))
- (gnus-group-position-point))
-
-(defun gnus-group-best-unread-group (&optional exclude-group)
- "Go to the group with the highest level.
-If EXCLUDE-GROUP, do not go to that group."
- (interactive)
- (goto-char (point-min))
- (let ((best 100000)
- unread best-point)
- (while (not (eobp))
- (setq unread (get-text-property (point) 'gnus-unread))
- (if (and (numberp unread) (> unread 0))
- (progn
- (if (and (get-text-property (point) 'gnus-level)
- (< (get-text-property (point) 'gnus-level) best)
- (or (not exclude-group)
- (not (equal exclude-group (gnus-group-group-name)))))
- (progn
- (setq best (get-text-property (point) 'gnus-level))
- (setq best-point (point))))))
- (forward-line 1))
- (if best-point (goto-char best-point))
- (gnus-summary-position-point)
- (and best-point (gnus-group-group-name))))
-
-(defun gnus-group-first-unread-group ()
- "Go to the first group with unread articles."
- (interactive)
- (prog1
- (let ((opoint (point))
- unread)
- (goto-char (point-min))
- (if (or (eq (setq unread (gnus-group-group-unread)) t) ; Not active.
- (and (numberp unread) ; Not a topic.
- (not (zerop unread))) ; Has unread articles.
- (zerop (gnus-group-next-unread-group 1))) ; Next unread group.
- (point) ; Success.
- (goto-char opoint)
- nil)) ; Not success.
- (gnus-group-position-point)))
-
-(defun gnus-group-enter-server-mode ()
- "Jump to the server buffer."
- (interactive)
- (gnus-enter-server-buffer))
-
-(defun gnus-group-make-group (name &optional method address)
- "Add a new newsgroup.
-The user will be prompted for a NAME, for a select METHOD, and an
-ADDRESS."
- (interactive
- (cons
- (read-string "Group name: ")
- (let ((method
- (completing-read
- "Method: " (append gnus-valid-select-methods gnus-server-alist)
- nil t nil 'gnus-method-history)))
- (cond ((assoc method gnus-valid-select-methods)
- (list method
- (if (memq 'prompt-address
- (assoc method gnus-valid-select-methods))
- (read-string "Address: ")
- "")))
- ((assoc method gnus-server-alist)
- (list method))
- (t
- (list method ""))))))
-
- (let* ((meth (and method (if address (list (intern method) address)
- method)))
- (nname (if method (gnus-group-prefixed-name name meth) name))
- backend info)
- (when (gnus-gethash nname gnus-newsrc-hashtb)
- (error "Group %s already exists" nname))
- ;; Subscribe to the new group.
- (gnus-group-change-level
- (setq info (list t nname gnus-level-default-subscribed nil nil meth))
- gnus-level-default-subscribed gnus-level-killed
- (and (gnus-group-group-name)
- (gnus-gethash (gnus-group-group-name)
- gnus-newsrc-hashtb))
- t)
- ;; Make it active.
- (gnus-set-active nname (cons 1 0))
- (or (gnus-ephemeral-group-p name)
- (gnus-dribble-enter
- (concat "(gnus-group-set-info '" (prin1-to-string (cdr info)) ")")))
- ;; Insert the line.
- (gnus-group-insert-group-line-info nname)
- (forward-line -1)
- (gnus-group-position-point)
-
- ;; Load the backend and try to make the backend create
- ;; the group as well.
- (when (assoc (symbol-name (setq backend (car (gnus-server-get-method
- nil meth))))
- gnus-valid-select-methods)
- (require backend))
- (gnus-check-server meth)
- (and (gnus-check-backend-function 'request-create-group nname)
- (gnus-request-create-group nname))
- t))
-
-(defun gnus-group-delete-group (group &optional force)
- "Delete the current group. Only meaningful with mail groups.
-If FORCE (the prefix) is non-nil, all the articles in the group will
-be deleted. This is \"deleted\" as in \"removed forever from the face
-of the Earth\". There is no undo. The user will be prompted before
-doing the deletion."
- (interactive
- (list (gnus-group-group-name)
- current-prefix-arg))
- (or group (error "No group to rename"))
- (or (gnus-check-backend-function 'request-delete-group group)
- (error "This backend does not support group deletion"))
- (prog1
- (if (not (gnus-yes-or-no-p
- (format
- "Do you really want to delete %s%s? "
- group (if force " and all its contents" ""))))
- () ; Whew!
- (gnus-message 6 "Deleting group %s..." group)
- (if (not (gnus-request-delete-group group force))
- (gnus-error 3 "Couldn't delete group %s" group)
- (gnus-message 6 "Deleting group %s...done" group)
- (gnus-group-goto-group group)
- (gnus-group-kill-group 1 t)
- (gnus-sethash group nil gnus-active-hashtb)
- t))
- (gnus-group-position-point)))
-
-(defun gnus-group-rename-group (group new-name)
- (interactive
- (list
- (gnus-group-group-name)
- (progn
- (or (gnus-check-backend-function
- 'request-rename-group (gnus-group-group-name))
- (error "This backend does not support renaming groups"))
- (read-string "New group name: "))))
-
- (or (gnus-check-backend-function 'request-rename-group group)
- (error "This backend does not support renaming groups"))
-
- (or group (error "No group to rename"))
- (and (string-match "^[ \t]*$" new-name)
- (error "Not a valid group name"))
-
- ;; We find the proper prefixed name.
- (setq new-name
- (gnus-group-prefixed-name
- (gnus-group-real-name new-name)
- (gnus-info-method (gnus-get-info group))))
-
- (gnus-message 6 "Renaming group %s to %s..." group new-name)
- (prog1
- (if (not (gnus-request-rename-group group new-name))
- (gnus-error 3 "Couldn't rename group %s to %s" group new-name)
- ;; We rename the group internally by killing it...
- (gnus-group-goto-group group)
- (gnus-group-kill-group)
- ;; ... changing its name ...
- (setcar (cdar gnus-list-of-killed-groups) new-name)
- ;; ... and then yanking it. Magic!
- (gnus-group-yank-group)
- (gnus-set-active new-name (gnus-active group))
- (gnus-message 6 "Renaming group %s to %s...done" group new-name)
- new-name)
- (gnus-group-position-point)))
-
-(defun gnus-group-edit-group (group &optional part)
- "Edit the group on the current line."
- (interactive (list (gnus-group-group-name)))
- (let* ((part (or part 'info))
- (done-func `(lambda ()
- "Exit editing mode and update the information."
- (interactive)
- (gnus-group-edit-group-done ',part ,group)))
- (winconf (current-window-configuration))
- info)
- (or group (error "No group on current line"))
- (or (setq info (gnus-get-info group))
- (error "Killed group; can't be edited"))
- (set-buffer (get-buffer-create gnus-group-edit-buffer))
- (gnus-configure-windows 'edit-group)
- (gnus-add-current-to-buffer-list)
- (emacs-lisp-mode)
- ;; Suggested by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
- (use-local-map (copy-keymap emacs-lisp-mode-map))
- (local-set-key "\C-c\C-c" done-func)
- (make-local-variable 'gnus-prev-winconf)
- (setq gnus-prev-winconf winconf)
- (erase-buffer)
- (insert
- (cond
- ((eq part 'method)
- ";; Type `C-c C-c' after editing the select method.\n\n")
- ((eq part 'params)
- ";; Type `C-c C-c' after editing the group parameters.\n\n")
- ((eq part 'info)
- ";; Type `C-c C-c' after editing the group info.\n\n")))
- (insert
- (pp-to-string
- (cond ((eq part 'method)
- (or (gnus-info-method info) "native"))
- ((eq part 'params)
- (gnus-info-params info))
- (t info)))
- "\n")))
-
-(defun gnus-group-edit-group-method (group)
- "Edit the select method of GROUP."
- (interactive (list (gnus-group-group-name)))
- (gnus-group-edit-group group 'method))
-
-(defun gnus-group-edit-group-parameters (group)
- "Edit the group parameters of GROUP."
- (interactive (list (gnus-group-group-name)))
- (gnus-group-edit-group group 'params))
-
-(defun gnus-group-edit-group-done (part group)
- "Get info from buffer, update variables and jump to the group buffer."
- (set-buffer (get-buffer-create gnus-group-edit-buffer))
- (goto-char (point-min))
- (let* ((form (read (current-buffer)))
- (winconf gnus-prev-winconf)
- (method (cond ((eq part 'info) (nth 4 form))
- ((eq part 'method) form)
- (t nil)))
- (info (cond ((eq part 'info) form)
- ((eq part 'method) (gnus-get-info group))
- (t nil)))
- (new-group (if info
- (if (or (not method)
- (gnus-server-equal
- gnus-select-method method))
- (gnus-group-real-name (car info))
- (gnus-group-prefixed-name
- (gnus-group-real-name (car info)) method))
- nil)))
- (when (and new-group
- (not (equal new-group group)))
- (when (gnus-group-goto-group group)
- (gnus-group-kill-group 1))
- (gnus-activate-group new-group))
- ;; Set the info.
- (if (and info new-group)
- (progn
- (setq info (gnus-copy-sequence info))
- (setcar info new-group)
- (unless (gnus-server-equal method "native")
- (unless (nthcdr 3 info)
- (nconc info (list nil nil)))
- (unless (nthcdr 4 info)
- (nconc info (list nil)))
- (gnus-info-set-method info method))
- (gnus-group-set-info info))
- (gnus-group-set-info form (or new-group group) part))
- (kill-buffer (current-buffer))
- (and winconf (set-window-configuration winconf))
- (set-buffer gnus-group-buffer)
- (gnus-group-update-group (or new-group group))
- (gnus-group-position-point)))
-
-(defun gnus-group-make-help-group ()
- "Create the Gnus documentation group."
- (interactive)
- (let ((path load-path)
- (name (gnus-group-prefixed-name "gnus-help" '(nndoc "gnus-help")))
- file dir)
- (and (gnus-gethash name gnus-newsrc-hashtb)
- (error "Documentation group already exists"))
- (while path
- (setq dir (file-name-as-directory (expand-file-name (pop path)))
- file nil)
- (when (or (file-exists-p (setq file (concat dir "gnus-tut.txt")))
- (file-exists-p
- (setq file (concat (file-name-directory
- (directory-file-name dir))
- "etc/gnus-tut.txt"))))
- (setq path nil)))
- (if (not file)
- (gnus-message 1 "Couldn't find doc group")
- (gnus-group-make-group
- (gnus-group-real-name name)
- (list 'nndoc "gnus-help"
- (list 'nndoc-address file)
- (list 'nndoc-article-type 'mbox)))))
- (gnus-group-position-point))
-
-(defun gnus-group-make-doc-group (file type)
- "Create a group that uses a single file as the source."
- (interactive
- (list (read-file-name "File name: ")
- (and current-prefix-arg 'ask)))
- (when (eq type 'ask)
- (let ((err "")
- char found)
- (while (not found)
- (message
- "%sFile type (mbox, babyl, digest, forward, mmfd, guess) [mbdfag]: "
- err)
- (setq found (cond ((= (setq char (read-char)) ?m) 'mbox)
- ((= char ?b) 'babyl)
- ((= char ?d) 'digest)
- ((= char ?f) 'forward)
- ((= char ?a) 'mmfd)
- (t (setq err (format "%c unknown. " char))
- nil))))
- (setq type found)))
- (let* ((file (expand-file-name file))
- (name (gnus-generate-new-group-name
- (gnus-group-prefixed-name
- (file-name-nondirectory file) '(nndoc "")))))
- (gnus-group-make-group
- (gnus-group-real-name name)
- (list 'nndoc (file-name-nondirectory file)
- (list 'nndoc-address file)
- (list 'nndoc-article-type (or type 'guess))))))
-
-(defun gnus-group-make-archive-group (&optional all)
- "Create the (ding) Gnus archive group of the most recent articles.
-Given a prefix, create a full group."
- (interactive "P")
- (let ((group (gnus-group-prefixed-name
- (if all "ding.archives" "ding.recent") '(nndir ""))))
- (and (gnus-gethash group gnus-newsrc-hashtb)
- (error "Archive group already exists"))
- (gnus-group-make-group
- (gnus-group-real-name group)
- (list 'nndir (if all "hpc" "edu")
- (list 'nndir-directory
- (if all gnus-group-archive-directory
- gnus-group-recent-archive-directory))))))
-
-(defun gnus-group-make-directory-group (dir)
- "Create an nndir group.
-The user will be prompted for a directory. The contents of this
-directory will be used as a newsgroup. The directory should contain
-mail messages or news articles in files that have numeric names."
- (interactive
- (list (read-file-name "Create group from directory: ")))
- (or (file-exists-p dir) (error "No such directory"))
- (or (file-directory-p dir) (error "Not a directory"))
- (let ((ext "")
- (i 0)
- group)
- (while (or (not group) (gnus-gethash group gnus-newsrc-hashtb))
- (setq group
- (gnus-group-prefixed-name
- (concat (file-name-as-directory (directory-file-name dir))
- ext)
- '(nndir "")))
- (setq ext (format "<%d>" (setq i (1+ i)))))
- (gnus-group-make-group
- (gnus-group-real-name group)
- (list 'nndir group (list 'nndir-directory dir)))))
-
-(defun gnus-group-make-kiboze-group (group address scores)
- "Create an nnkiboze group.
-The user will be prompted for a name, a regexp to match groups, and
-score file entries for articles to include in the group."
- (interactive
- (list
- (read-string "nnkiboze group name: ")
- (read-string "Source groups (regexp): ")
- (let ((headers (mapcar (lambda (group) (list group))
- '("subject" "from" "number" "date" "message-id"
- "references" "chars" "lines" "xref"
- "followup" "all" "body" "head")))
- scores header regexp regexps)
- (while (not (equal "" (setq header (completing-read
- "Match on header: " headers nil t))))
- (setq regexps nil)
- (while (not (equal "" (setq regexp (read-string
- (format "Match on %s (string): "
- header)))))
- (setq regexps (cons (list regexp nil nil 'r) regexps)))
- (setq scores (cons (cons header regexps) scores)))
- scores)))
- (gnus-group-make-group group "nnkiboze" address)
- (nnheader-temp-write (gnus-score-file-name (concat "nnkiboze:" group))
- (let (emacs-lisp-mode-hook)
- (pp scores (current-buffer)))))
-
-(defun gnus-group-add-to-virtual (n vgroup)
- "Add the current group to a virtual group."
- (interactive
- (list current-prefix-arg
- (completing-read "Add to virtual group: " gnus-newsrc-hashtb nil t
- "nnvirtual:")))
- (or (eq (car (gnus-find-method-for-group vgroup)) 'nnvirtual)
- (error "%s is not an nnvirtual group" vgroup))
- (let* ((groups (gnus-group-process-prefix n))
- (method (gnus-info-method (gnus-get-info vgroup))))
- (setcar (cdr method)
- (concat
- (nth 1 method) "\\|"
- (mapconcat
- (lambda (s)
- (gnus-group-remove-mark s)
- (concat "\\(^" (regexp-quote s) "$\\)"))
- groups "\\|"))))
- (gnus-group-position-point))
-
-(defun gnus-group-make-empty-virtual (group)
- "Create a new, fresh, empty virtual group."
- (interactive "sCreate new, empty virtual group: ")
- (let* ((method (list 'nnvirtual "^$"))
- (pgroup (gnus-group-prefixed-name group method)))
- ;; Check whether it exists already.
- (and (gnus-gethash pgroup gnus-newsrc-hashtb)
- (error "Group %s already exists." pgroup))
- ;; Subscribe the new group after the group on the current line.
- (gnus-subscribe-group pgroup (gnus-group-group-name) method)
- (gnus-group-update-group pgroup)
- (forward-line -1)
- (gnus-group-position-point)))
-
-(defun gnus-group-enter-directory (dir)
- "Enter an ephemeral nneething group."
- (interactive "DDirectory to read: ")
- (let* ((method (list 'nneething dir '(nneething-read-only t)))
- (leaf (gnus-group-prefixed-name
- (file-name-nondirectory (directory-file-name dir))
- method))
- (name (gnus-generate-new-group-name leaf)))
- (unless (gnus-group-read-ephemeral-group
- name method t
- (cons (current-buffer)
- (if (eq major-mode 'gnus-summary-mode)
- 'summary 'group)))
- (error "Couldn't enter %s" dir))))
-
-;; Group sorting commands
-;; Suggested by Joe Hildebrand <hildjj@idaho.fuentez.com>.
-
-(defun gnus-group-sort-groups (func &optional reverse)
- "Sort the group buffer according to FUNC.
-If REVERSE, reverse the sorting order."
- (interactive (list gnus-group-sort-function
- current-prefix-arg))
- (let ((func (cond
- ((not (listp func)) func)
- ((null func) func)
- ((= 1 (length func)) (car func))
- (t `(lambda (t1 t2)
- ,(gnus-make-sort-function
- (reverse func)))))))
- ;; We peel off the dummy group from the alist.
- (when func
- (when (equal (car (gnus-info-group gnus-newsrc-alist)) "dummy.group")
- (pop gnus-newsrc-alist))
- ;; Do the sorting.
- (setq gnus-newsrc-alist
- (sort gnus-newsrc-alist func))
- (when reverse
- (setq gnus-newsrc-alist (nreverse gnus-newsrc-alist)))
- ;; Regenerate the hash table.
- (gnus-make-hashtable-from-newsrc-alist)
- (gnus-group-list-groups))))
-
-(defun gnus-group-sort-groups-by-alphabet (&optional reverse)
- "Sort the group buffer alphabetically by group name.
-If REVERSE, sort in reverse order."
- (interactive "P")
- (gnus-group-sort-groups 'gnus-group-sort-by-alphabet reverse))
-
-(defun gnus-group-sort-groups-by-unread (&optional reverse)
- "Sort the group buffer by number of unread articles.
-If REVERSE, sort in reverse order."
- (interactive "P")
- (gnus-group-sort-groups 'gnus-group-sort-by-unread reverse))
-
-(defun gnus-group-sort-groups-by-level (&optional reverse)
- "Sort the group buffer by group level.
-If REVERSE, sort in reverse order."
- (interactive "P")
- (gnus-group-sort-groups 'gnus-group-sort-by-level reverse))
-
-(defun gnus-group-sort-groups-by-score (&optional reverse)
- "Sort the group buffer by group score.
-If REVERSE, sort in reverse order."
- (interactive "P")
- (gnus-group-sort-groups 'gnus-group-sort-by-score reverse))
-
-(defun gnus-group-sort-groups-by-rank (&optional reverse)
- "Sort the group buffer by group rank.
-If REVERSE, sort in reverse order."
- (interactive "P")
- (gnus-group-sort-groups 'gnus-group-sort-by-rank reverse))
-
-(defun gnus-group-sort-groups-by-method (&optional reverse)
- "Sort the group buffer alphabetically by backend name.
-If REVERSE, sort in reverse order."
- (interactive "P")
- (gnus-group-sort-groups 'gnus-group-sort-by-method reverse))
-
-(defun gnus-group-sort-by-alphabet (info1 info2)
- "Sort alphabetically."
- (string< (gnus-info-group info1) (gnus-info-group info2)))
-
-(defun gnus-group-sort-by-unread (info1 info2)
- "Sort by number of unread articles."
- (let ((n1 (car (gnus-gethash (gnus-info-group info1) gnus-newsrc-hashtb)))
- (n2 (car (gnus-gethash (gnus-info-group info2) gnus-newsrc-hashtb))))
- (< (or (and (numberp n1) n1) 0)
- (or (and (numberp n2) n2) 0))))
-
-(defun gnus-group-sort-by-level (info1 info2)
- "Sort by level."
- (< (gnus-info-level info1) (gnus-info-level info2)))
-
-(defun gnus-group-sort-by-method (info1 info2)
- "Sort alphabetically by backend name."
- (string< (symbol-name (car (gnus-find-method-for-group
- (gnus-info-group info1) info1)))
- (symbol-name (car (gnus-find-method-for-group
- (gnus-info-group info2) info2)))))
-
-(defun gnus-group-sort-by-score (info1 info2)
- "Sort by group score."
- (< (gnus-info-score info1) (gnus-info-score info2)))
-
-(defun gnus-group-sort-by-rank (info1 info2)
- "Sort by level and score."
- (let ((level1 (gnus-info-level info1))
- (level2 (gnus-info-level info2)))
- (or (< level1 level2)
- (and (= level1 level2)
- (> (gnus-info-score info1) (gnus-info-score info2))))))
-
-;; Group catching up.
-
-(defun gnus-group-clear-data (n)
- "Clear all marks and read ranges from the current group."
- (interactive "P")
- (let ((groups (gnus-group-process-prefix n))
- group info)
- (while (setq group (pop groups))
- (setq info (gnus-get-info group))
- (gnus-info-set-read info nil)
- (when (gnus-info-marks info)
- (gnus-info-set-marks info nil))
- (gnus-get-unread-articles-in-group info (gnus-active group) t)
- (when (gnus-group-goto-group group)
- (gnus-group-remove-mark group)
- (gnus-group-update-group-line)))))
-
-(defun gnus-group-catchup-current (&optional n all)
- "Mark all articles not marked as unread in current newsgroup as read.
-If prefix argument N is numeric, the ARG next newsgroups will be
-caught up. If ALL is non-nil, marked articles will also be marked as
-read. Cross references (Xref: header) of articles are ignored.
-The difference between N and actual number of newsgroups that were
-caught up is returned."
- (interactive "P")
- (unless (gnus-group-group-name)
- (error "No group on the current line"))
- (if (not (or (not gnus-interactive-catchup) ;Without confirmation?
- gnus-expert-user
- (gnus-y-or-n-p
- (if all
- "Do you really want to mark all articles as read? "
- "Mark all unread articles as read? "))))
- n
- (let ((groups (gnus-group-process-prefix n))
- (ret 0))
- (while groups
- ;; Virtual groups have to be given special treatment.
- (let ((method (gnus-find-method-for-group (car groups))))
- (if (eq 'nnvirtual (car method))
- (nnvirtual-catchup-group
- (gnus-group-real-name (car groups)) (nth 1 method) all)))
- (gnus-group-remove-mark (car groups))
- (if (>= (gnus-group-group-level) gnus-level-zombie)
- (gnus-message 2 "Dead groups can't be caught up")
- (if (prog1
- (gnus-group-goto-group (car groups))
- (gnus-group-catchup (car groups) all))
- (gnus-group-update-group-line)
- (setq ret (1+ ret))))
- (setq groups (cdr groups)))
- (gnus-group-next-unread-group 1)
- ret)))
-
-(defun gnus-group-catchup-current-all (&optional n)
- "Mark all articles in current newsgroup as read.
-Cross references (Xref: header) of articles are ignored."
- (interactive "P")
- (gnus-group-catchup-current n 'all))
-
-(defun gnus-group-catchup (group &optional all)
- "Mark all articles in GROUP as read.
-If ALL is non-nil, all articles are marked as read.
-The return value is the number of articles that were marked as read,
-or nil if no action could be taken."
- (let* ((entry (gnus-gethash group gnus-newsrc-hashtb))
- (num (car entry)))
- ;; Do the updating only if the newsgroup isn't killed.
- (if (not (numberp (car entry)))
- (gnus-message 1 "Can't catch up; non-active group")
- ;; Do auto-expirable marks if that's required.
- (when (gnus-group-auto-expirable-p group)
- (gnus-add-marked-articles
- group 'expire (gnus-list-of-unread-articles group))
- (when all
- (let ((marks (nth 3 (nth 2 entry))))
- (gnus-add-marked-articles
- group 'expire (gnus-uncompress-range (cdr (assq 'tick marks))))
- (gnus-add-marked-articles
- group 'expire (gnus-uncompress-range (cdr (assq 'tick marks)))))))
- (when entry
- (gnus-update-read-articles group nil)
- ;; Also nix out the lists of marks and dormants.
- (when all
- (gnus-add-marked-articles group 'tick nil nil 'force)
- (gnus-add-marked-articles group 'dormant nil nil 'force))
- (run-hooks 'gnus-group-catchup-group-hook)
- num))))
-
-(defun gnus-group-expire-articles (&optional n)
- "Expire all expirable articles in the current newsgroup."
- (interactive "P")
- (let ((groups (gnus-group-process-prefix n))
- group)
- (unless groups
- (error "No groups to expire"))
- (while (setq group (pop groups))
- (gnus-group-remove-mark group)
- (when (gnus-check-backend-function 'request-expire-articles group)
- (gnus-message 6 "Expiring articles in %s..." group)
- (let* ((info (gnus-get-info group))
- (expirable (if (gnus-group-total-expirable-p group)
- (cons nil (gnus-list-of-read-articles group))
- (assq 'expire (gnus-info-marks info))))
- (expiry-wait (gnus-group-get-parameter group 'expiry-wait)))
- (when expirable
- (setcdr
- expirable
- (gnus-compress-sequence
- (if expiry-wait
- ;; We set the expiry variables to the groupp
- ;; parameter.
- (let ((nnmail-expiry-wait-function nil)
- (nnmail-expiry-wait expiry-wait))
- (gnus-request-expire-articles
- (gnus-uncompress-sequence (cdr expirable)) group))
- ;; Just expire using the normal expiry values.
- (gnus-request-expire-articles
- (gnus-uncompress-sequence (cdr expirable)) group))))
- (gnus-close-group group))
- (gnus-message 6 "Expiring articles in %s...done" group)))
- (gnus-group-position-point))))
-
-(defun gnus-group-expire-all-groups ()
- "Expire all expirable articles in all newsgroups."
- (interactive)
- (save-excursion
- (gnus-message 5 "Expiring...")
- (let ((gnus-group-marked (mapcar (lambda (info) (gnus-info-group info))
- (cdr gnus-newsrc-alist))))
- (gnus-group-expire-articles nil)))
- (gnus-group-position-point)
- (gnus-message 5 "Expiring...done"))
-
-(defun gnus-group-set-current-level (n level)
- "Set the level of the next N groups to LEVEL."
- (interactive
- (list
- current-prefix-arg
- (string-to-int
- (let ((s (read-string
- (format "Level (default %s): "
- (or (gnus-group-group-level)
- gnus-level-default-subscribed)))))
- (if (string-match "^\\s-*$" s)
- (int-to-string (or (gnus-group-group-level)
- gnus-level-default-subscribed))
- s)))))
- (or (and (>= level 1) (<= level gnus-level-killed))
- (error "Illegal level: %d" level))
- (let ((groups (gnus-group-process-prefix n))
- group)
- (while (setq group (pop groups))
- (gnus-group-remove-mark group)
- (gnus-message 6 "Changed level of %s from %d to %d"
- group (or (gnus-group-group-level) gnus-level-killed)
- level)
- (gnus-group-change-level
- group level (or (gnus-group-group-level) gnus-level-killed))
- (gnus-group-update-group-line)))
- (gnus-group-position-point))
-
-(defun gnus-group-unsubscribe-current-group (&optional n)
- "Toggle subscription of the current group.
-If given numerical prefix, toggle the N next groups."
- (interactive "P")
- (let ((groups (gnus-group-process-prefix n))
- group)
- (while groups
- (setq group (car groups)
- groups (cdr groups))
- (gnus-group-remove-mark group)
- (gnus-group-unsubscribe-group
- group (if (<= (gnus-group-group-level) gnus-level-subscribed)
- gnus-level-default-unsubscribed
- gnus-level-default-subscribed) t)
- (gnus-group-update-group-line))
- (gnus-group-next-group 1)))
-
-(defun gnus-group-unsubscribe-group (group &optional level silent)
- "Toggle subscription to GROUP.
-Killed newsgroups are subscribed. If SILENT, don't try to update the
-group line."
- (interactive
- (list (completing-read
- "Group: " gnus-active-hashtb nil
- (gnus-read-active-file-p)
- nil
- 'gnus-group-history)))
- (let ((newsrc (gnus-gethash group gnus-newsrc-hashtb)))
- (cond
- ((string-match "^[ \t]$" group)
- (error "Empty group name"))
- (newsrc
- ;; Toggle subscription flag.
- (gnus-group-change-level
- newsrc (if level level (if (<= (nth 1 (nth 2 newsrc))
- gnus-level-subscribed)
- (1+ gnus-level-subscribed)
- gnus-level-default-subscribed)))
- (unless silent
- (gnus-group-update-group group)))
- ((and (stringp group)
- (or (not (gnus-read-active-file-p))
- (gnus-active group)))
- ;; Add new newsgroup.
- (gnus-group-change-level
- group
- (if level level gnus-level-default-subscribed)
- (or (and (member group gnus-zombie-list)
- gnus-level-zombie)
- gnus-level-killed)
- (and (gnus-group-group-name)
- (gnus-gethash (gnus-group-group-name) gnus-newsrc-hashtb)))
- (unless silent
- (gnus-group-update-group group)))
- (t (error "No such newsgroup: %s" group)))
- (gnus-group-position-point)))
-
-(defun gnus-group-transpose-groups (n)
- "Move the current newsgroup up N places.
-If given a negative prefix, move down instead. The difference between
-N and the number of steps taken is returned."
- (interactive "p")
- (or (gnus-group-group-name)
- (error "No group on current line"))
- (gnus-group-kill-group 1)
- (prog1
- (forward-line (- n))
- (gnus-group-yank-group)
- (gnus-group-position-point)))
-
-(defun gnus-group-kill-all-zombies ()
- "Kill all zombie newsgroups."
- (interactive)
- (setq gnus-killed-list (nconc gnus-zombie-list gnus-killed-list))
- (setq gnus-zombie-list nil)
- (gnus-group-list-groups))
-
-(defun gnus-group-kill-region (begin end)
- "Kill newsgroups in current region (excluding current point).
-The killed newsgroups can be yanked by using \\[gnus-group-yank-group]."
- (interactive "r")
- (let ((lines
- ;; Count lines.
- (save-excursion
- (count-lines
- (progn
- (goto-char begin)
- (beginning-of-line)
- (point))
- (progn
- (goto-char end)
- (beginning-of-line)
- (point))))))
- (goto-char begin)
- (beginning-of-line) ;Important when LINES < 1
- (gnus-group-kill-group lines)))
-
-(defun gnus-group-kill-group (&optional n discard)
- "Kill the next N groups.
-The killed newsgroups can be yanked by using \\[gnus-group-yank-group].
-However, only groups that were alive can be yanked; already killed
-groups or zombie groups can't be yanked.
-The return value is the name of the group that was killed, or a list
-of groups killed."
- (interactive "P")
- (let ((buffer-read-only nil)
- (groups (gnus-group-process-prefix n))
- group entry level out)
- (if (< (length groups) 10)
- ;; This is faster when there are few groups.
- (while groups
- (push (setq group (pop groups)) out)
- (gnus-group-remove-mark group)
- (setq level (gnus-group-group-level))
- (gnus-delete-line)
- (when (and (not discard)
- (setq entry (gnus-gethash group gnus-newsrc-hashtb)))
- (push (cons (car entry) (nth 2 entry))
- gnus-list-of-killed-groups))
- (gnus-group-change-level
- (if entry entry group) gnus-level-killed (if entry nil level)))
- ;; If there are lots and lots of groups to be killed, we use
- ;; this thing instead.
- (let (entry)
- (setq groups (nreverse groups))
- (while groups
- (gnus-group-remove-mark (setq group (pop groups)))
- (gnus-delete-line)
- (push group gnus-killed-list)
- (setq gnus-newsrc-alist
- (delq (assoc group gnus-newsrc-alist)
- gnus-newsrc-alist))
- (when gnus-group-change-level-function
- (funcall gnus-group-change-level-function group 9 3))
- (cond
- ((setq entry (gnus-gethash group gnus-newsrc-hashtb))
- (push (cons (car entry) (nth 2 entry))
- gnus-list-of-killed-groups)
- (setcdr (cdr entry) (cdddr entry)))
- ((member group gnus-zombie-list)
- (setq gnus-zombie-list (delete group gnus-zombie-list)))))
- (gnus-make-hashtable-from-newsrc-alist)))
-
- (gnus-group-position-point)
- (if (< (length out) 2) (car out) (nreverse out))))
-
-(defun gnus-group-yank-group (&optional arg)
- "Yank the last newsgroups killed with \\[gnus-group-kill-group],
-inserting it before the current newsgroup. The numeric ARG specifies
-how many newsgroups are to be yanked. The name of the newsgroup yanked
-is returned, or (if several groups are yanked) a list of yanked groups
-is returned."
- (interactive "p")
- (setq arg (or arg 1))
- (let (info group prev out)
- (while (>= (decf arg) 0)
- (if (not (setq info (pop gnus-list-of-killed-groups)))
- (error "No more newsgroups to yank"))
- (push (setq group (nth 1 info)) out)
- ;; Find which newsgroup to insert this one before - search
- ;; backward until something suitable is found. If there are no
- ;; other newsgroups in this buffer, just make this newsgroup the
- ;; first newsgroup.
- (setq prev (gnus-group-group-name))
- (gnus-group-change-level
- info (gnus-info-level (cdr info)) gnus-level-killed
- (and prev (gnus-gethash prev gnus-newsrc-hashtb))
- t)
- (gnus-group-insert-group-line-info group))
- (forward-line -1)
- (gnus-group-position-point)
- (if (< (length out) 2) (car out) (nreverse out))))
-
-(defun gnus-group-kill-level (level)
- "Kill all groups that is on a certain LEVEL."
- (interactive "nKill all groups on level: ")
- (cond
- ((= level gnus-level-zombie)
- (setq gnus-killed-list
- (nconc gnus-zombie-list gnus-killed-list))
- (setq gnus-zombie-list nil))
- ((and (< level gnus-level-zombie)
- (> level 0)
- (or gnus-expert-user
- (gnus-yes-or-no-p
- (format
- "Do you really want to kill all groups on level %d? "
- level))))
- (let* ((prev gnus-newsrc-alist)
- (alist (cdr prev)))
- (while alist
- (if (= (gnus-info-level (car alist)) level)
- (progn
- (push (gnus-info-group (car alist)) gnus-killed-list)
- (setcdr prev (cdr alist)))
- (setq prev alist))
- (setq alist (cdr alist)))
- (gnus-make-hashtable-from-newsrc-alist)
- (gnus-group-list-groups)))
- (t
- (error "Can't kill; illegal level: %d" level))))
-
-(defun gnus-group-list-all-groups (&optional arg)
- "List all newsgroups with level ARG or lower.
-Default is gnus-level-unsubscribed, which lists all subscribed and most
-unsubscribed groups."
- (interactive "P")
- (gnus-group-list-groups (or arg gnus-level-unsubscribed) t))
-
-;; Redefine this to list ALL killed groups if prefix arg used.
-;; Rewritten by engstrom@src.honeywell.com (Eric Engstrom).
-(defun gnus-group-list-killed (&optional arg)
- "List all killed newsgroups in the group buffer.
-If ARG is non-nil, list ALL killed groups known to Gnus. This may
-entail asking the server for the groups."
- (interactive "P")
- ;; Find all possible killed newsgroups if arg.
- (when arg
- (gnus-get-killed-groups))
- (if (not gnus-killed-list)
- (gnus-message 6 "No killed groups")
- (let (gnus-group-list-mode)
- (funcall gnus-group-prepare-function
- gnus-level-killed t gnus-level-killed))
- (goto-char (point-min)))
- (gnus-group-position-point))
-
-(defun gnus-group-list-zombies ()
- "List all zombie newsgroups in the group buffer."
- (interactive)
- (if (not gnus-zombie-list)
- (gnus-message 6 "No zombie groups")
- (let (gnus-group-list-mode)
- (funcall gnus-group-prepare-function
- gnus-level-zombie t gnus-level-zombie))
- (goto-char (point-min)))
- (gnus-group-position-point))
-
-(defun gnus-group-list-active ()
- "List all groups that are available from the server(s)."
- (interactive)
- ;; First we make sure that we have really read the active file.
- (unless (gnus-read-active-file-p)
- (let ((gnus-read-active-file t))
- (gnus-read-active-file)))
- ;; Find all groups and sort them.
- (let ((groups
- (sort
- (let (list)
- (mapatoms
- (lambda (sym)
- (and (boundp sym)
- (symbol-value sym)
- (setq list (cons (symbol-name sym) list))))
- gnus-active-hashtb)
- list)
- 'string<))
- (buffer-read-only nil))
- (erase-buffer)
- (while groups
- (gnus-group-insert-group-line-info (pop groups)))
- (goto-char (point-min))))
-
-(defun gnus-activate-all-groups (level)
- "Activate absolutely all groups."
- (interactive (list 7))
- (let ((gnus-activate-level level)
- (gnus-activate-foreign-newsgroups level))
- (gnus-group-get-new-news)))
-
-(defun gnus-group-get-new-news (&optional arg)
- "Get newly arrived articles.
-If ARG is a number, it specifies which levels you are interested in
-re-scanning. If ARG is non-nil and not a number, this will force
-\"hard\" re-reading of the active files from all servers."
- (interactive "P")
- (run-hooks 'gnus-get-new-news-hook)
- ;; We might read in new NoCeM messages here.
- (when (and gnus-use-nocem
- (null arg))
- (gnus-nocem-scan-groups))
- ;; If ARG is not a number, then we read the active file.
- (when (and arg (not (numberp arg)))
- (let ((gnus-read-active-file t))
- (gnus-read-active-file))
- (setq arg nil))
-
- (setq arg (gnus-group-default-level arg t))
- (if (and gnus-read-active-file (not arg))
- (progn
- (gnus-read-active-file)
- (gnus-get-unread-articles arg))
- (let ((gnus-read-active-file (if arg nil gnus-read-active-file)))
- (gnus-get-unread-articles arg)))
- (run-hooks 'gnus-after-getting-new-news-hook)
- (gnus-group-list-groups))
-
-(defun gnus-group-get-new-news-this-group (&optional n)
- "Check for newly arrived news in the current group (and the N-1 next groups).
-The difference between N and the number of newsgroup checked is returned.
-If N is negative, this group and the N-1 previous groups will be checked."
- (interactive "P")
- (let* ((groups (gnus-group-process-prefix n))
- (ret (if (numberp n) (- n (length groups)) 0))
- (beg (unless n (point)))
- group)
- (while (setq group (pop groups))
- (gnus-group-remove-mark group)
- (if (gnus-activate-group group 'scan)
- (progn
- (gnus-get-unread-articles-in-group
- (gnus-get-info group) (gnus-active group) t)
- (unless (gnus-virtual-group-p group)
- (gnus-close-group group))
- (gnus-group-update-group group))
- (if (eq (gnus-server-status (gnus-find-method-for-group group))
- 'denied)
- (gnus-error "Server denied access")
- (gnus-error 3 "%s error: %s" group (gnus-status-message group)))))
- (when beg (goto-char beg))
- (when gnus-goto-next-group-when-activating
- (gnus-group-next-unread-group 1 t))
- (gnus-summary-position-point)
- ret))
-
-(defun gnus-group-fetch-faq (group &optional faq-dir)
- "Fetch the FAQ for the current group."
- (interactive
- (list
- (and (gnus-group-group-name)
- (gnus-group-real-name (gnus-group-group-name)))
- (cond (current-prefix-arg
- (completing-read
- "Faq dir: " (and (listp gnus-group-faq-directory)
- (mapcar (lambda (file) (list file))
- gnus-group-faq-directory)))))))
- (or faq-dir
- (setq faq-dir (if (listp gnus-group-faq-directory)
- (car gnus-group-faq-directory)
- gnus-group-faq-directory)))
- (or group (error "No group name given"))
- (let ((file (concat (file-name-as-directory faq-dir)
- (gnus-group-real-name group))))
- (if (not (file-exists-p file))
- (error "No such file: %s" file)
- (find-file file))))
-
-(defun gnus-group-describe-group (force &optional group)
- "Display a description of the current newsgroup."
- (interactive (list current-prefix-arg (gnus-group-group-name)))
- (let* ((method (gnus-find-method-for-group group))
- (mname (gnus-group-prefixed-name "" method))
- desc)
- (when (and force
- gnus-description-hashtb)
- (gnus-sethash mname nil gnus-description-hashtb))
- (or group (error "No group name given"))
- (and (or (and gnus-description-hashtb
- ;; We check whether this group's method has been
- ;; queried for a description file.
- (gnus-gethash mname gnus-description-hashtb))
- (setq desc (gnus-group-get-description group))
- (gnus-read-descriptions-file method))
- (gnus-message 1
- (or desc (gnus-gethash group gnus-description-hashtb)
- "No description available")))))
-
-;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
-(defun gnus-group-describe-all-groups (&optional force)
- "Pop up a buffer with descriptions of all newsgroups."
- (interactive "P")
- (and force (setq gnus-description-hashtb nil))
- (if (not (or gnus-description-hashtb
- (gnus-read-all-descriptions-files)))
- (error "Couldn't request descriptions file"))
- (let ((buffer-read-only nil)
- b)
- (erase-buffer)
- (mapatoms
- (lambda (group)
- (setq b (point))
- (insert (format " *: %-20s %s\n" (symbol-name group)
- (symbol-value group)))
- (gnus-add-text-properties
- b (1+ b) (list 'gnus-group group
- 'gnus-unread t 'gnus-marked nil
- 'gnus-level (1+ gnus-level-subscribed))))
- gnus-description-hashtb)
- (goto-char (point-min))
- (gnus-group-position-point)))
-
-;; Suggested by by Daniel Quinlan <quinlan@best.com>.
-(defun gnus-group-apropos (regexp &optional search-description)
- "List all newsgroups that have names that match a regexp."
- (interactive "sGnus apropos (regexp): ")
- (let ((prev "")
- (obuf (current-buffer))
- groups des)
- ;; Go through all newsgroups that are known to Gnus.
- (mapatoms
- (lambda (group)
- (and (symbol-name group)
- (string-match regexp (symbol-name group))
- (setq groups (cons (symbol-name group) groups))))
- gnus-active-hashtb)
- ;; Also go through all descriptions that are known to Gnus.
- (when search-description
- (mapatoms
- (lambda (group)
- (and (string-match regexp (symbol-value group))
- (gnus-active (symbol-name group))
- (setq groups (cons (symbol-name group) groups))))
- gnus-description-hashtb))
- (if (not groups)
- (gnus-message 3 "No groups matched \"%s\"." regexp)
- ;; Print out all the groups.
- (save-excursion
- (pop-to-buffer "*Gnus Help*")
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (setq groups (sort groups 'string<))
- (while groups
- ;; Groups may be entered twice into the list of groups.
- (if (not (string= (car groups) prev))
- (progn
- (insert (setq prev (car groups)) "\n")
- (if (and gnus-description-hashtb
- (setq des (gnus-gethash (car groups)
- gnus-description-hashtb)))
- (insert " " des "\n"))))
- (setq groups (cdr groups)))
- (goto-char (point-min))))
- (pop-to-buffer obuf)))
-
-(defun gnus-group-description-apropos (regexp)
- "List all newsgroups that have names or descriptions that match a regexp."
- (interactive "sGnus description apropos (regexp): ")
- (if (not (or gnus-description-hashtb
- (gnus-read-all-descriptions-files)))
- (error "Couldn't request descriptions file"))
- (gnus-group-apropos regexp t))
-
-;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
-(defun gnus-group-list-matching (level regexp &optional all lowest)
- "List all groups with unread articles that match REGEXP.
-If the prefix LEVEL is non-nil, it should be a number that says which
-level to cut off listing groups.
-If ALL, also list groups with no unread articles.
-If LOWEST, don't list groups with level lower than LOWEST.
-
-This command may read the active file."
- (interactive "P\nsList newsgroups matching: ")
- ;; First make sure active file has been read.
- (when (and level
- (> (prefix-numeric-value level) gnus-level-killed))
- (gnus-get-killed-groups))
- (gnus-group-prepare-flat (or level gnus-level-subscribed)
- all (or lowest 1) regexp)
- (goto-char (point-min))
- (gnus-group-position-point))
-
-(defun gnus-group-list-all-matching (level regexp &optional lowest)
- "List all groups that match REGEXP.
-If the prefix LEVEL is non-nil, it should be a number that says which
-level to cut off listing groups.
-If LOWEST, don't list groups with level lower than LOWEST."
- (interactive "P\nsList newsgroups matching: ")
- (gnus-group-list-matching (or level gnus-level-killed) regexp t lowest))
-
-;; Suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>.
-(defun gnus-group-save-newsrc (&optional force)
- "Save the Gnus startup files.
-If FORCE, force saving whether it is necessary or not."
- (interactive "P")
- (gnus-save-newsrc-file force))
-
-(defun gnus-group-restart (&optional arg)
- "Force Gnus to read the .newsrc file."
- (interactive "P")
- (when (gnus-yes-or-no-p
- (format "Are you sure you want to read %s? "
- gnus-current-startup-file))
- (gnus-save-newsrc-file)
- (gnus-setup-news 'force)
- (gnus-group-list-groups arg)))
-
-(defun gnus-group-read-init-file ()
- "Read the Gnus elisp init file."
- (interactive)
- (gnus-read-init-file))
-
-(defun gnus-group-check-bogus-groups (&optional silent)
- "Check bogus newsgroups.
-If given a prefix, don't ask for confirmation before removing a bogus
-group."
- (interactive "P")
- (gnus-check-bogus-newsgroups (and (not silent) (not gnus-expert-user)))
- (gnus-group-list-groups))
-
-(defun gnus-group-edit-global-kill (&optional article group)
- "Edit the global kill file.
-If GROUP, edit that local kill file instead."
- (interactive "P")
- (setq gnus-current-kill-article article)
- (gnus-kill-file-edit-file group)
- (gnus-message
- 6
- (substitute-command-keys
- (format "Editing a %s kill file (Type \\[gnus-kill-file-exit] to exit)"
- (if group "local" "global")))))
-
-(defun gnus-group-edit-local-kill (article group)
- "Edit a local kill file."
- (interactive (list nil (gnus-group-group-name)))
- (gnus-group-edit-global-kill article group))
-
-(defun gnus-group-force-update ()
- "Update `.newsrc' file."
- (interactive)
- (gnus-save-newsrc-file))
-
-(defun gnus-group-suspend ()
- "Suspend the current Gnus session.
-In fact, cleanup buffers except for group mode buffer.
-The hook gnus-suspend-gnus-hook is called before actually suspending."
- (interactive)
- (run-hooks 'gnus-suspend-gnus-hook)
- ;; Kill Gnus buffers except for group mode buffer.
- (let* ((group-buf (get-buffer gnus-group-buffer))
- ;; Do this on a separate list in case the user does a ^G before we finish
- (gnus-buffer-list
- (delete group-buf (delete gnus-dribble-buffer
- (append gnus-buffer-list nil)))))
- (while gnus-buffer-list
- (gnus-kill-buffer (pop gnus-buffer-list)))
- (gnus-kill-gnus-frames)
- (when group-buf
- (setq gnus-buffer-list (list group-buf))
- (bury-buffer group-buf)
- (delete-windows-on group-buf t))))
-
-(defun gnus-group-clear-dribble ()
- "Clear all information from the dribble buffer."
- (interactive)
- (gnus-dribble-clear)
- (gnus-message 7 "Cleared dribble buffer"))
-
-(defun gnus-group-exit ()
- "Quit reading news after updating .newsrc.eld and .newsrc.
-The hook `gnus-exit-gnus-hook' is called before actually exiting."
- (interactive)
- (when
- (or noninteractive ;For gnus-batch-kill
- (not gnus-interactive-exit) ;Without confirmation
- gnus-expert-user
- (gnus-y-or-n-p "Are you sure you want to quit reading news? "))
- (run-hooks 'gnus-exit-gnus-hook)
- ;; Offer to save data from non-quitted summary buffers.
- (gnus-offer-save-summaries)
- ;; Save the newsrc file(s).
- (gnus-save-newsrc-file)
- ;; Kill-em-all.
- (gnus-close-backends)
- ;; Reset everything.
- (gnus-clear-system)
- ;; Allow the user to do things after cleaning up.
- (run-hooks 'gnus-after-exiting-gnus-hook)))
-
-(defun gnus-close-backends ()
- ;; Send a close request to all backends that support such a request.
- (let ((methods gnus-valid-select-methods)
- func)
- (while methods
- (if (fboundp (setq func (intern (concat (caar methods)
- "-request-close"))))
- (funcall func))
- (setq methods (cdr methods)))))
-
-(defun gnus-group-quit ()
- "Quit reading news without updating .newsrc.eld or .newsrc.
-The hook `gnus-exit-gnus-hook' is called before actually exiting."
- (interactive)
- (when (or noninteractive ;For gnus-batch-kill
- (zerop (buffer-size))
- (not (gnus-server-opened gnus-select-method))
- gnus-expert-user
- (not gnus-current-startup-file)
- (gnus-yes-or-no-p
- (format "Quit reading news without saving %s? "
- (file-name-nondirectory gnus-current-startup-file))))
- (run-hooks 'gnus-exit-gnus-hook)
- (if gnus-use-full-window
- (delete-other-windows)
- (gnus-remove-some-windows))
- (gnus-dribble-save)
- (gnus-close-backends)
- (gnus-clear-system)
- ;; Allow the user to do things after cleaning up.
- (run-hooks 'gnus-after-exiting-gnus-hook)))
-
-(defun gnus-offer-save-summaries ()
- "Offer to save all active summary buffers."
- (save-excursion
- (let ((buflist (buffer-list))
- buffers bufname)
- ;; Go through all buffers and find all summaries.
- (while buflist
- (and (setq bufname (buffer-name (car buflist)))
- (string-match "Summary" bufname)
- (save-excursion
- (set-buffer bufname)
- ;; We check that this is, indeed, a summary buffer.
- (and (eq major-mode 'gnus-summary-mode)
- ;; Also make sure this isn't bogus.
- gnus-newsgroup-prepared))
- (push bufname buffers))
- (setq buflist (cdr buflist)))
- ;; Go through all these summary buffers and offer to save them.
- (when buffers
- (map-y-or-n-p
- "Update summary buffer %s? "
- (lambda (buf) (set-buffer buf) (gnus-summary-exit))
- buffers)))))
-
-(defun gnus-group-describe-briefly ()
- "Give a one line description of the group mode commands."
- (interactive)
- (gnus-message 7 (substitute-command-keys "\\<gnus-group-mode-map>\\[gnus-group-read-group]:Select \\[gnus-group-next-unread-group]:Forward \\[gnus-group-prev-unread-group]:Backward \\[gnus-group-exit]:Exit \\[gnus-info-find-node]:Run Info \\[gnus-group-describe-briefly]:This help")))
-
-(defun gnus-group-browse-foreign-server (method)
- "Browse a foreign news server.
-If called interactively, this function will ask for a select method
- (nntp, nnspool, etc.) and a server address (eg. nntp.some.where).
-If not, METHOD should be a list where the first element is the method
-and the second element is the address."
- (interactive
- (list (let ((how (completing-read
- "Which backend: "
- (append gnus-valid-select-methods gnus-server-alist)
- nil t (cons "nntp" 0) 'gnus-method-history)))
- ;; We either got a backend name or a virtual server name.
- ;; If the first, we also need an address.
- (if (assoc how gnus-valid-select-methods)
- (list (intern how)
- ;; Suggested by mapjph@bath.ac.uk.
- (completing-read
- "Address: "
- (mapcar (lambda (server) (list server))
- gnus-secondary-servers)))
- ;; We got a server name, so we find the method.
- (gnus-server-to-method how)))))
- (gnus-browse-foreign-server method))
-
-
-;;;
-;;; Gnus summary mode
-;;;
-
-(defvar gnus-summary-mode-map nil)
-
-(put 'gnus-summary-mode 'mode-class 'special)
-
-(unless gnus-summary-mode-map
- (setq gnus-summary-mode-map (make-keymap))
- (suppress-keymap gnus-summary-mode-map)
-
- ;; Non-orthogonal keys
-
- (gnus-define-keys gnus-summary-mode-map
- " " gnus-summary-next-page
- "\177" gnus-summary-prev-page
- [delete] gnus-summary-prev-page
- "\r" gnus-summary-scroll-up
- "n" gnus-summary-next-unread-article
- "p" gnus-summary-prev-unread-article
- "N" gnus-summary-next-article
- "P" gnus-summary-prev-article
- "\M-\C-n" gnus-summary-next-same-subject
- "\M-\C-p" gnus-summary-prev-same-subject
- "\M-n" gnus-summary-next-unread-subject
- "\M-p" gnus-summary-prev-unread-subject
- "." gnus-summary-first-unread-article
- "," gnus-summary-best-unread-article
- "\M-s" gnus-summary-search-article-forward
- "\M-r" gnus-summary-search-article-backward
- "<" gnus-summary-beginning-of-article
- ">" gnus-summary-end-of-article
- "j" gnus-summary-goto-article
- "^" gnus-summary-refer-parent-article
- "\M-^" gnus-summary-refer-article
- "u" gnus-summary-tick-article-forward
- "!" gnus-summary-tick-article-forward
- "U" gnus-summary-tick-article-backward
- "d" gnus-summary-mark-as-read-forward
- "D" gnus-summary-mark-as-read-backward
- "E" gnus-summary-mark-as-expirable
- "\M-u" gnus-summary-clear-mark-forward
- "\M-U" gnus-summary-clear-mark-backward
- "k" gnus-summary-kill-same-subject-and-select
- "\C-k" gnus-summary-kill-same-subject
- "\M-\C-k" gnus-summary-kill-thread
- "\M-\C-l" gnus-summary-lower-thread
- "e" gnus-summary-edit-article
- "#" gnus-summary-mark-as-processable
- "\M-#" gnus-summary-unmark-as-processable
- "\M-\C-t" gnus-summary-toggle-threads
- "\M-\C-s" gnus-summary-show-thread
- "\M-\C-h" gnus-summary-hide-thread
- "\M-\C-f" gnus-summary-next-thread
- "\M-\C-b" gnus-summary-prev-thread
- "\M-\C-u" gnus-summary-up-thread
- "\M-\C-d" gnus-summary-down-thread
- "&" gnus-summary-execute-command
- "c" gnus-summary-catchup-and-exit
- "\C-w" gnus-summary-mark-region-as-read
- "\C-t" gnus-summary-toggle-truncation
- "?" gnus-summary-mark-as-dormant
- "\C-c\M-\C-s" gnus-summary-limit-include-expunged
- "\C-c\C-s\C-n" gnus-summary-sort-by-number
- "\C-c\C-s\C-a" gnus-summary-sort-by-author
- "\C-c\C-s\C-s" gnus-summary-sort-by-subject
- "\C-c\C-s\C-d" gnus-summary-sort-by-date
- "\C-c\C-s\C-i" gnus-summary-sort-by-score
- "=" gnus-summary-expand-window
- "\C-x\C-s" gnus-summary-reselect-current-group
- "\M-g" gnus-summary-rescan-group
- "w" gnus-summary-stop-page-breaking
- "\C-c\C-r" gnus-summary-caesar-message
- "\M-t" gnus-summary-toggle-mime
- "f" gnus-summary-followup
- "F" gnus-summary-followup-with-original
- "C" gnus-summary-cancel-article
- "r" gnus-summary-reply
- "R" gnus-summary-reply-with-original
- "\C-c\C-f" gnus-summary-mail-forward
- "o" gnus-summary-save-article
- "\C-o" gnus-summary-save-article-mail
- "|" gnus-summary-pipe-output
- "\M-k" gnus-summary-edit-local-kill
- "\M-K" gnus-summary-edit-global-kill
- "V" gnus-version
- "\C-c\C-d" gnus-summary-describe-group
- "q" gnus-summary-exit
- "Q" gnus-summary-exit-no-update
- "\C-c\C-i" gnus-info-find-node
- gnus-mouse-2 gnus-mouse-pick-article
- "m" gnus-summary-mail-other-window
- "a" gnus-summary-post-news
- "x" gnus-summary-limit-to-unread
- "s" gnus-summary-isearch-article
- "t" gnus-article-hide-headers
- "g" gnus-summary-show-article
- "l" gnus-summary-goto-last-article
- "\C-c\C-v\C-v" gnus-uu-decode-uu-view
- "\C-d" gnus-summary-enter-digest-group
- "\C-c\C-b" gnus-bug
- "*" gnus-cache-enter-article
- "\M-*" gnus-cache-remove-article
- "\M-&" gnus-summary-universal-argument
- "\C-l" gnus-recenter
- "I" gnus-summary-increase-score
- "L" gnus-summary-lower-score
-
- "V" gnus-summary-score-map
- "X" gnus-uu-extract-map
- "S" gnus-summary-send-map)
-
- ;; Sort of orthogonal keymap
- (gnus-define-keys (gnus-summary-mark-map "M" gnus-summary-mode-map)
- "t" gnus-summary-tick-article-forward
- "!" gnus-summary-tick-article-forward
- "d" gnus-summary-mark-as-read-forward
- "r" gnus-summary-mark-as-read-forward
- "c" gnus-summary-clear-mark-forward
- " " gnus-summary-clear-mark-forward
- "e" gnus-summary-mark-as-expirable
- "x" gnus-summary-mark-as-expirable
- "?" gnus-summary-mark-as-dormant
- "b" gnus-summary-set-bookmark
- "B" gnus-summary-remove-bookmark
- "#" gnus-summary-mark-as-processable
- "\M-#" gnus-summary-unmark-as-processable
- "S" gnus-summary-limit-include-expunged
- "C" gnus-summary-catchup
- "H" gnus-summary-catchup-to-here
- "\C-c" gnus-summary-catchup-all
- "k" gnus-summary-kill-same-subject-and-select
- "K" gnus-summary-kill-same-subject
- "P" gnus-uu-mark-map)
-
- (gnus-define-keys (gnus-summary-mscore-map "V" gnus-summary-mode-map)
- "c" gnus-summary-clear-above
- "u" gnus-summary-tick-above
- "m" gnus-summary-mark-above
- "k" gnus-summary-kill-below)
-
- (gnus-define-keys (gnus-summary-limit-map "/" gnus-summary-mode-map)
- "/" gnus-summary-limit-to-subject
- "n" gnus-summary-limit-to-articles
- "w" gnus-summary-pop-limit
- "s" gnus-summary-limit-to-subject
- "a" gnus-summary-limit-to-author
- "u" gnus-summary-limit-to-unread
- "m" gnus-summary-limit-to-marks
- "v" gnus-summary-limit-to-score
- "D" gnus-summary-limit-include-dormant
- "d" gnus-summary-limit-exclude-dormant
- ;; "t" gnus-summary-limit-exclude-thread
- "E" gnus-summary-limit-include-expunged
- "c" gnus-summary-limit-exclude-childless-dormant
- "C" gnus-summary-limit-mark-excluded-as-read)
-
- (gnus-define-keys (gnus-summary-goto-map "G" gnus-summary-mode-map)
- "n" gnus-summary-next-unread-article
- "p" gnus-summary-prev-unread-article
- "N" gnus-summary-next-article
- "P" gnus-summary-prev-article
- "\C-n" gnus-summary-next-same-subject
- "\C-p" gnus-summary-prev-same-subject
- "\M-n" gnus-summary-next-unread-subject
- "\M-p" gnus-summary-prev-unread-subject
- "f" gnus-summary-first-unread-article
- "b" gnus-summary-best-unread-article
- "j" gnus-summary-goto-article
- "g" gnus-summary-goto-subject
- "l" gnus-summary-goto-last-article
- "p" gnus-summary-pop-article)
-
- (gnus-define-keys (gnus-summary-thread-map "T" gnus-summary-mode-map)
- "k" gnus-summary-kill-thread
- "l" gnus-summary-lower-thread
- "i" gnus-summary-raise-thread
- "T" gnus-summary-toggle-threads
- "t" gnus-summary-rethread-current
- "^" gnus-summary-reparent-thread
- "s" gnus-summary-show-thread
- "S" gnus-summary-show-all-threads
- "h" gnus-summary-hide-thread
- "H" gnus-summary-hide-all-threads
- "n" gnus-summary-next-thread
- "p" gnus-summary-prev-thread
- "u" gnus-summary-up-thread
- "o" gnus-summary-top-thread
- "d" gnus-summary-down-thread
- "#" gnus-uu-mark-thread
- "\M-#" gnus-uu-unmark-thread)
-
- (gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map)
- "c" gnus-summary-catchup-and-exit
- "C" gnus-summary-catchup-all-and-exit
- "E" gnus-summary-exit-no-update
- "Q" gnus-summary-exit
- "Z" gnus-summary-exit
- "n" gnus-summary-catchup-and-goto-next-group
- "R" gnus-summary-reselect-current-group
- "G" gnus-summary-rescan-group
- "N" gnus-summary-next-group
- "P" gnus-summary-prev-group)
-
- (gnus-define-keys (gnus-summary-article-map "A" gnus-summary-mode-map)
- " " gnus-summary-next-page
- "n" gnus-summary-next-page
- "\177" gnus-summary-prev-page
- [delete] gnus-summary-prev-page
- "p" gnus-summary-prev-page
- "\r" gnus-summary-scroll-up
- "<" gnus-summary-beginning-of-article
- ">" gnus-summary-end-of-article
- "b" gnus-summary-beginning-of-article
- "e" gnus-summary-end-of-article
- "^" gnus-summary-refer-parent-article
- "r" gnus-summary-refer-parent-article
- "R" gnus-summary-refer-references
- "g" gnus-summary-show-article
- "s" gnus-summary-isearch-article)
-
- (gnus-define-keys (gnus-summary-wash-map "W" gnus-summary-mode-map)
- "b" gnus-article-add-buttons
- "B" gnus-article-add-buttons-to-head
- "o" gnus-article-treat-overstrike
- ;; "w" gnus-article-word-wrap
- "w" gnus-article-fill-cited-article
- "c" gnus-article-remove-cr
- "L" gnus-article-remove-trailing-blank-lines
- "q" gnus-article-de-quoted-unreadable
- "f" gnus-article-display-x-face
- "l" gnus-summary-stop-page-breaking
- "r" gnus-summary-caesar-message
- "t" gnus-article-hide-headers
- "v" gnus-summary-verbose-headers
- "m" gnus-summary-toggle-mime)
-
- (gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
- "a" gnus-article-hide
- "h" gnus-article-hide-headers
- "b" gnus-article-hide-boring-headers
- "s" gnus-article-hide-signature
- "c" gnus-article-hide-citation
- "p" gnus-article-hide-pgp
- "\C-c" gnus-article-hide-citation-maybe)
-
- (gnus-define-keys (gnus-summary-wash-highlight-map "H" gnus-summary-wash-map)
- "a" gnus-article-highlight
- "h" gnus-article-highlight-headers
- "c" gnus-article-highlight-citation
- "s" gnus-article-highlight-signature)
-
- (gnus-define-keys (gnus-summary-wash-time-map "T" gnus-summary-wash-map)
- "z" gnus-article-date-ut
- "u" gnus-article-date-ut
- "l" gnus-article-date-local
- "e" gnus-article-date-lapsed
- "o" gnus-article-date-original)
-
- (gnus-define-keys (gnus-summary-help-map "H" gnus-summary-mode-map)
- "v" gnus-version
- "f" gnus-summary-fetch-faq
- "d" gnus-summary-describe-group
- "h" gnus-summary-describe-briefly
- "i" gnus-info-find-node)
-
- (gnus-define-keys (gnus-summary-backend-map "B" gnus-summary-mode-map)
- "e" gnus-summary-expire-articles
- "\M-\C-e" gnus-summary-expire-articles-now
- "\177" gnus-summary-delete-article
- [delete] gnus-summary-delete-article
- "m" gnus-summary-move-article
- "r" gnus-summary-respool-article
- "w" gnus-summary-edit-article
- "c" gnus-summary-copy-article
- "B" gnus-summary-crosspost-article
- "q" gnus-summary-respool-query
- "i" gnus-summary-import-article)
-
- (gnus-define-keys (gnus-summary-save-map "O" gnus-summary-mode-map)
- "o" gnus-summary-save-article
- "m" gnus-summary-save-article-mail
- "r" gnus-summary-save-article-rmail
- "f" gnus-summary-save-article-file
- "b" gnus-summary-save-article-body-file
- "h" gnus-summary-save-article-folder
- "v" gnus-summary-save-article-vm
- "p" gnus-summary-pipe-output
- "s" gnus-soup-add-article)
- )
-
-
-
-(defun gnus-summary-mode (&optional group)
- "Major mode for reading articles.
-
-All normal editing commands are switched off.
-\\<gnus-summary-mode-map>
-Each line in this buffer represents one article. To read an
-article, you can, for instance, type `\\[gnus-summary-next-page]'. To move forwards
-and backwards while displaying articles, type `\\[gnus-summary-next-unread-article]' and `\\[gnus-summary-prev-unread-article]',
-respectively.
-
-You can also post articles and send mail from this buffer. To
-follow up an article, type `\\[gnus-summary-followup]'. To mail a reply to the author
-of an article, type `\\[gnus-summary-reply]'.
-
-There are approx. one gazillion commands you can execute in this
-buffer; read the info pages for more information (`\\[gnus-info-find-node]').
-
-The following commands are available:
-
-\\{gnus-summary-mode-map}"
- (interactive)
- (when (and menu-bar-mode
- (gnus-visual-p 'summary-menu 'menu))
- (gnus-summary-make-menu-bar))
- (kill-all-local-variables)
- (gnus-summary-make-local-variables)
- (gnus-make-thread-indent-array)
- (gnus-simplify-mode-line)
- (setq major-mode 'gnus-summary-mode)
- (setq mode-name "Summary")
- (make-local-variable 'minor-mode-alist)
- (use-local-map gnus-summary-mode-map)
- (buffer-disable-undo (current-buffer))
- (setq buffer-read-only t) ;Disable modification
- (setq truncate-lines t)
- (setq selective-display t)
- (setq selective-display-ellipses t) ;Display `...'
- (setq buffer-display-table gnus-summary-display-table)
- (setq gnus-newsgroup-name group)
- (make-local-variable 'gnus-summary-line-format)
- (make-local-variable 'gnus-summary-line-format-spec)
- (make-local-variable 'gnus-summary-mark-positions)
- (gnus-make-local-hook 'post-command-hook)
- (gnus-add-hook 'post-command-hook 'gnus-clear-inboxes-moved nil t)
- (run-hooks 'gnus-summary-mode-hook))
-
-(defun gnus-summary-make-local-variables ()
- "Make all the local summary buffer variables."
- (let ((locals gnus-summary-local-variables)
- global local)
- (while (setq local (pop locals))
- (if (consp local)
- (progn
- (if (eq (cdr local) 'global)
- ;; Copy the global value of the variable.
- (setq global (symbol-value (car local)))
- ;; Use the value from the list.
- (setq global (eval (cdr local))))
- (make-local-variable (car local))
- (set (car local) global))
- ;; Simple nil-valued local variable.
- (make-local-variable local)
- (set local nil)))))
-
-(defun gnus-summary-make-display-table ()
- ;; Change the display table. Odd characters have a tendency to mess
- ;; up nicely formatted displays - we make all possible glyphs
- ;; display only a single character.
-
- ;; We start from the standard display table, if any.
- (setq gnus-summary-display-table
- (or (copy-sequence standard-display-table)
- (make-display-table)))
- ;; Nix out all the control chars...
- (let ((i 32))
- (while (>= (setq i (1- i)) 0)
- (aset gnus-summary-display-table i [??])))
- ;; ... but not newline and cr, of course. (cr is necessary for the
- ;; selective display).
- (aset gnus-summary-display-table ?\n nil)
- (aset gnus-summary-display-table ?\r nil)
- ;; We nix out any glyphs over 126 that are not set already.
- (let ((i 256))
- (while (>= (setq i (1- i)) 127)
- ;; Only modify if the entry is nil.
- (or (aref gnus-summary-display-table i)
- (aset gnus-summary-display-table i [??])))))
-
-(defun gnus-summary-clear-local-variables ()
- (let ((locals gnus-summary-local-variables))
- (while locals
- (if (consp (car locals))
- (and (vectorp (caar locals))
- (set (caar locals) nil))
- (and (vectorp (car locals))
- (set (car locals) nil)))
- (setq locals (cdr locals)))))
-
-;; Summary data functions.
-
-(defmacro gnus-data-number (data)
- `(car ,data))
-
-(defmacro gnus-data-set-number (data number)
- `(setcar ,data ,number))
-
-(defmacro gnus-data-mark (data)
- `(nth 1 ,data))
-
-(defmacro gnus-data-set-mark (data mark)
- `(setcar (nthcdr 1 ,data) ,mark))
-
-(defmacro gnus-data-pos (data)
- `(nth 2 ,data))
-
-(defmacro gnus-data-set-pos (data pos)
- `(setcar (nthcdr 2 ,data) ,pos))
-
-(defmacro gnus-data-header (data)
- `(nth 3 ,data))
-
-(defmacro gnus-data-level (data)
- `(nth 4 ,data))
-
-(defmacro gnus-data-unread-p (data)
- `(= (nth 1 ,data) gnus-unread-mark))
-
-(defmacro gnus-data-pseudo-p (data)
- `(consp (nth 3 ,data)))
-
-(defmacro gnus-data-find (number)
- `(assq ,number gnus-newsgroup-data))
-
-(defmacro gnus-data-find-list (number &optional data)
- `(let ((bdata ,(or data 'gnus-newsgroup-data)))
- (memq (assq ,number bdata)
- bdata)))
-
-(defmacro gnus-data-make (number mark pos header level)
- `(list ,number ,mark ,pos ,header ,level))
-
-(defun gnus-data-enter (after-article number mark pos header level offset)
- (let ((data (gnus-data-find-list after-article)))
- (or data (error "No such article: %d" after-article))
- (setcdr data (cons (gnus-data-make number mark pos header level)
- (cdr data)))
- (setq gnus-newsgroup-data-reverse nil)
- (gnus-data-update-list (cddr data) offset)))
-
-(defun gnus-data-enter-list (after-article list &optional offset)
- (when list
- (let ((data (and after-article (gnus-data-find-list after-article)))
- (ilist list))
- (or data (not after-article) (error "No such article: %d" after-article))
- ;; Find the last element in the list to be spliced into the main
- ;; list.
- (while (cdr list)
- (setq list (cdr list)))
- (if (not data)
- (progn
- (setcdr list gnus-newsgroup-data)
- (setq gnus-newsgroup-data ilist)
- (and offset (gnus-data-update-list (cdr list) offset)))
- (setcdr list (cdr data))
- (setcdr data ilist)
- (and offset (gnus-data-update-list (cdr data) offset)))
- (setq gnus-newsgroup-data-reverse nil))))
-
-(defun gnus-data-remove (article &optional offset)
- (let ((data gnus-newsgroup-data))
- (if (= (gnus-data-number (car data)) article)
- (setq gnus-newsgroup-data (cdr gnus-newsgroup-data)
- gnus-newsgroup-data-reverse nil)
- (while (cdr data)
- (and (= (gnus-data-number (cadr data)) article)
- (progn
- (setcdr data (cddr data))
- (and offset (gnus-data-update-list (cdr data) offset))
- (setq data nil
- gnus-newsgroup-data-reverse nil)))
- (setq data (cdr data))))))
-
-(defmacro gnus-data-list (backward)
- `(if ,backward
- (or gnus-newsgroup-data-reverse
- (setq gnus-newsgroup-data-reverse
- (reverse gnus-newsgroup-data)))
- gnus-newsgroup-data))
-
-(defun gnus-data-update-list (data offset)
- "Add OFFSET to the POS of all data entries in DATA."
- (while data
- (setcar (nthcdr 2 (car data)) (+ offset (nth 2 (car data))))
- (setq data (cdr data))))
-
-(defun gnus-data-compute-positions ()
- "Compute the positions of all articles."
- (let ((data gnus-newsgroup-data)
- pos)
- (while data
- (when (setq pos (text-property-any
- (point-min) (point-max)
- 'gnus-number (gnus-data-number (car data))))
- (gnus-data-set-pos (car data) (+ pos 3)))
- (setq data (cdr data)))))
-
-(defun gnus-summary-article-pseudo-p (article)
- "Say whether this article is a pseudo article or not."
- (not (vectorp (gnus-data-header (gnus-data-find article)))))
-
-(defun gnus-article-parent-p (number)
- "Say whether this article is a parent or not."
- (let ((data (gnus-data-find-list number)))
- (and (cdr data) ; There has to be an article after...
- (< (gnus-data-level (car data)) ; And it has to have a higher level.
- (gnus-data-level (nth 1 data))))))
-
-(defun gnus-article-children (number)
- "Return a list of all children to NUMBER."
- (let* ((data (gnus-data-find-list number))
- (level (gnus-data-level (car data)))
- children)
- (setq data (cdr data))
- (while (and data
- (= (gnus-data-level (car data)) (1+ level)))
- (push (gnus-data-number (car data)) children)
- (setq data (cdr data)))
- children))
-
-(defmacro gnus-summary-skip-intangible ()
- "If the current article is intangible, then jump to a different article."
- '(let ((to (get-text-property (point) 'gnus-intangible)))
- (and to (gnus-summary-goto-subject to))))
-
-(defmacro gnus-summary-article-intangible-p ()
- "Say whether this article is intangible or not."
- '(get-text-property (point) 'gnus-intangible))
-
-;; Some summary mode macros.
-
-(defmacro gnus-summary-article-number ()
- "The article number of the article on the current line.
-If there isn's an article number here, then we return the current
-article number."
- '(progn
- (gnus-summary-skip-intangible)
- (or (get-text-property (point) 'gnus-number)
- (gnus-summary-last-subject))))
-
-(defmacro gnus-summary-article-header (&optional number)
- `(gnus-data-header (gnus-data-find
- ,(or number '(gnus-summary-article-number)))))
-
-(defmacro gnus-summary-thread-level (&optional number)
- `(if (and (eq gnus-summary-make-false-root 'dummy)
- (get-text-property (point) 'gnus-intangible))
- 0
- (gnus-data-level (gnus-data-find
- ,(or number '(gnus-summary-article-number))))))
-
-(defmacro gnus-summary-article-mark (&optional number)
- `(gnus-data-mark (gnus-data-find
- ,(or number '(gnus-summary-article-number)))))
-
-(defmacro gnus-summary-article-pos (&optional number)
- `(gnus-data-pos (gnus-data-find
- ,(or number '(gnus-summary-article-number)))))
-
-(defalias 'gnus-summary-subject-string 'gnus-summary-article-subject)
-(defmacro gnus-summary-article-subject (&optional number)
- "Return current subject string or nil if nothing."
- `(let ((headers
- ,(if number
- `(gnus-data-header (assq ,number gnus-newsgroup-data))
- '(gnus-data-header (assq (gnus-summary-article-number)
- gnus-newsgroup-data)))))
- (and headers
- (vectorp headers)
- (mail-header-subject headers))))
-
-(defmacro gnus-summary-article-score (&optional number)
- "Return current article score."
- `(or (cdr (assq ,(or number '(gnus-summary-article-number))
- gnus-newsgroup-scored))
- gnus-summary-default-score 0))
-
-(defun gnus-summary-article-children (&optional number)
- (let* ((data (gnus-data-find-list (or number (gnus-summary-article-number))))
- (level (gnus-data-level (car data)))
- l children)
- (while (and (setq data (cdr data))
- (> (setq l (gnus-data-level (car data))) level))
- (and (= (1+ level) l)
- (setq children (cons (gnus-data-number (car data))
- children))))
- (nreverse children)))
-
-(defun gnus-summary-article-parent (&optional number)
- (let* ((data (gnus-data-find-list (or number (gnus-summary-article-number))
- (gnus-data-list t)))
- (level (gnus-data-level (car data))))
- (if (zerop level)
- () ; This is a root.
- ;; We search until we find an article with a level less than
- ;; this one. That function has to be the parent.
- (while (and (setq data (cdr data))
- (not (< (gnus-data-level (car data)) level))))
- (and data (gnus-data-number (car data))))))
-
-(defun gnus-unread-mark-p (mark)
- "Say whether MARK is the unread mark."
- (= mark gnus-unread-mark))
-
-(defun gnus-read-mark-p (mark)
- "Say whether MARK is one of the marks that mark as read.
-This is all marks except unread, ticked, dormant, and expirable."
- (not (or (= mark gnus-unread-mark)
- (= mark gnus-ticked-mark)
- (= mark gnus-dormant-mark)
- (= mark gnus-expirable-mark))))
-
-;; Saving hidden threads.
-
-(put 'gnus-save-hidden-threads 'lisp-indent-function 0)
-(put 'gnus-save-hidden-threads 'lisp-indent-hook 0)
-(put 'gnus-save-hidden-threads 'edebug-form-spec '(body))
-
-(defmacro gnus-save-hidden-threads (&rest forms)
- "Save hidden threads, eval FORMS, and restore the hidden threads."
- (let ((config (make-symbol "config")))
- `(let ((,config (gnus-hidden-threads-configuration)))
- (unwind-protect
- (progn
- ,@forms)
- (gnus-restore-hidden-threads-configuration ,config)))))
-
-(defun gnus-hidden-threads-configuration ()
- "Return the current hidden threads configuration."
- (save-excursion
- (let (config)
- (goto-char (point-min))
- (while (search-forward "\r" nil t)
- (push (1- (point)) config))
- config)))
-
-(defun gnus-restore-hidden-threads-configuration (config)
- "Restore hidden threads configuration from CONFIG."
- (let (point buffer-read-only)
- (while (setq point (pop config))
- (when (and (< point (point-max))
- (goto-char point)
- (= (following-char) ?\n))
- (subst-char-in-region point (1+ point) ?\n ?\r)))))
-
-;; Various summary mode internalish functions.
-
-(defun gnus-mouse-pick-article (e)
- (interactive "e")
- (mouse-set-point e)
- (gnus-summary-next-page nil t))
-
-(defun gnus-summary-setup-buffer (group)
- "Initialize summary buffer."
- (let ((buffer (concat "*Summary " group "*")))
- (if (get-buffer buffer)
- (progn
- (set-buffer buffer)
- (setq gnus-summary-buffer (current-buffer))
- (not gnus-newsgroup-prepared))
- ;; Fix by Sudish Joseph <joseph@cis.ohio-state.edu>
- (setq gnus-summary-buffer (set-buffer (get-buffer-create buffer)))
- (gnus-add-current-to-buffer-list)
- (gnus-summary-mode group)
- (when gnus-carpal
- (gnus-carpal-setup-buffer 'summary))
- (unless gnus-single-article-buffer
- (make-local-variable 'gnus-article-buffer)
- (make-local-variable 'gnus-article-current)
- (make-local-variable 'gnus-original-article-buffer))
- (setq gnus-newsgroup-name group)
- t)))
-
-(defun gnus-set-global-variables ()
- ;; Set the global equivalents of the summary buffer-local variables
- ;; to the latest values they had. These reflect the summary buffer
- ;; that was in action when the last article was fetched.
- (when (eq major-mode 'gnus-summary-mode)
- (setq gnus-summary-buffer (current-buffer))
- (let ((name gnus-newsgroup-name)
- (marked gnus-newsgroup-marked)
- (unread gnus-newsgroup-unreads)
- (headers gnus-current-headers)
- (data gnus-newsgroup-data)
- (summary gnus-summary-buffer)
- (article-buffer gnus-article-buffer)
- (original gnus-original-article-buffer)
- (gac gnus-article-current)
- (score-file gnus-current-score-file))
- (save-excursion
- (set-buffer gnus-group-buffer)
- (setq gnus-newsgroup-name name)
- (setq gnus-newsgroup-marked marked)
- (setq gnus-newsgroup-unreads unread)
- (setq gnus-current-headers headers)
- (setq gnus-newsgroup-data data)
- (setq gnus-article-current gac)
- (setq gnus-summary-buffer summary)
- (setq gnus-article-buffer article-buffer)
- (setq gnus-original-article-buffer original)
- (setq gnus-current-score-file score-file)))))
-
-(defun gnus-summary-last-article-p (&optional article)
- "Return whether ARTICLE is the last article in the buffer."
- (if (not (setq article (or article (gnus-summary-article-number))))
- t ; All non-existant numbers are the last article. :-)
- (not (cdr (gnus-data-find-list article)))))
-
-(defun gnus-summary-insert-dummy-line (gnus-tmp-subject gnus-tmp-number)
- "Insert a dummy root in the summary buffer."
- (beginning-of-line)
- (gnus-add-text-properties
- (point) (progn (eval gnus-summary-dummy-line-format-spec) (point))
- (list 'gnus-number gnus-tmp-number 'gnus-intangible gnus-tmp-number)))
-
-(defun gnus-make-thread-indent-array ()
- (let ((n 200))
- (unless (and gnus-thread-indent-array
- (= gnus-thread-indent-level gnus-thread-indent-array-level))
- (setq gnus-thread-indent-array (make-vector 201 "")
- gnus-thread-indent-array-level gnus-thread-indent-level)
- (while (>= n 0)
- (aset gnus-thread-indent-array n
- (make-string (* n gnus-thread-indent-level) ? ))
- (setq n (1- n))))))
-
-(defun gnus-summary-insert-line
- (gnus-tmp-header gnus-tmp-level gnus-tmp-current gnus-tmp-unread
- gnus-tmp-replied gnus-tmp-expirable gnus-tmp-subject-or-nil
- &optional gnus-tmp-dummy gnus-tmp-score gnus-tmp-process)
- (let* ((gnus-tmp-indentation (aref gnus-thread-indent-array gnus-tmp-level))
- (gnus-tmp-lines (mail-header-lines gnus-tmp-header))
- (gnus-tmp-score (or gnus-tmp-score gnus-summary-default-score 0))
- (gnus-tmp-score-char
- (if (or (null gnus-summary-default-score)
- (<= (abs (- gnus-tmp-score gnus-summary-default-score))
- gnus-summary-zcore-fuzz)) ?
- (if (< gnus-tmp-score gnus-summary-default-score)
- gnus-score-below-mark gnus-score-over-mark)))
- (gnus-tmp-replied (cond (gnus-tmp-process gnus-process-mark)
- ((memq gnus-tmp-current gnus-newsgroup-cached)
- gnus-cached-mark)
- (gnus-tmp-replied gnus-replied-mark)
- ((memq gnus-tmp-current gnus-newsgroup-saved)
- gnus-saved-mark)
- (t gnus-unread-mark)))
- (gnus-tmp-from (mail-header-from gnus-tmp-header))
- (gnus-tmp-name
- (cond
- ((string-match "(.+)" gnus-tmp-from)
- (substring gnus-tmp-from
- (1+ (match-beginning 0)) (1- (match-end 0))))
- ((string-match "<[^>]+> *$" gnus-tmp-from)
- (let ((beg (match-beginning 0)))
- (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
- (substring gnus-tmp-from (1+ (match-beginning 0))
- (1- (match-end 0))))
- (substring gnus-tmp-from 0 beg))))
- (t gnus-tmp-from)))
- (gnus-tmp-subject (mail-header-subject gnus-tmp-header))
- (gnus-tmp-number (mail-header-number gnus-tmp-header))
- (gnus-tmp-opening-bracket (if gnus-tmp-dummy ?\< ?\[))
- (gnus-tmp-closing-bracket (if gnus-tmp-dummy ?\> ?\]))
- (buffer-read-only nil))
- (when (string= gnus-tmp-name "")
- (setq gnus-tmp-name gnus-tmp-from))
- (or (numberp gnus-tmp-lines) (setq gnus-tmp-lines 0))
- (gnus-put-text-property
- (point)
- (progn (eval gnus-summary-line-format-spec) (point))
- 'gnus-number gnus-tmp-number)
- (when (gnus-visual-p 'summary-highlight 'highlight)
- (forward-line -1)
- (run-hooks 'gnus-summary-update-hook)
- (forward-line 1))))
-
-(defun gnus-summary-update-line (&optional dont-update)
- ;; Update summary line after change.
- (when (and gnus-summary-default-score
- (not gnus-summary-inhibit-highlight))
- (let* ((gnus-summary-inhibit-highlight t) ; Prevent recursion.
- (article (gnus-summary-article-number))
- (score (gnus-summary-article-score article)))
- (unless dont-update
- (if (and gnus-summary-mark-below
- (< (gnus-summary-article-score)
- gnus-summary-mark-below))
- ;; This article has a low score, so we mark it as read.
- (when (memq article gnus-newsgroup-unreads)
- (gnus-summary-mark-article-as-read gnus-low-score-mark))
- (when (eq (gnus-summary-article-mark) gnus-low-score-mark)
- ;; This article was previously marked as read on account
- ;; of a low score, but now it has risen, so we mark it as
- ;; unread.
- (gnus-summary-mark-article-as-unread gnus-unread-mark)))
- (gnus-summary-update-mark
- (if (or (null gnus-summary-default-score)
- (<= (abs (- score gnus-summary-default-score))
- gnus-summary-zcore-fuzz)) ?
- (if (< score gnus-summary-default-score)
- gnus-score-below-mark gnus-score-over-mark)) 'score))
- ;; Do visual highlighting.
- (when (gnus-visual-p 'summary-highlight 'highlight)
- (run-hooks 'gnus-summary-update-hook)))))
-
-(defvar gnus-tmp-new-adopts nil)
-
-(defun gnus-summary-number-of-articles-in-thread (thread &optional level char)
- ;; Sum up all elements (and sub-elements) in a list.
- (let* ((number
- ;; Fix by Luc Van Eycken <Luc.VanEycken@esat.kuleuven.ac.be>.
- (cond
- ((and (consp thread) (cdr thread))
- (apply
- '+ 1 (mapcar
- 'gnus-summary-number-of-articles-in-thread (cdr thread))))
- ((null thread)
- 1)
- ((memq (mail-header-number (car thread)) gnus-newsgroup-limit)
- 1)
- (t 0))))
- (when (and level (zerop level) gnus-tmp-new-adopts)
- (incf number
- (apply '+ (mapcar
- 'gnus-summary-number-of-articles-in-thread
- gnus-tmp-new-adopts))))
- (if char
- (if (> number 1) gnus-not-empty-thread-mark
- gnus-empty-thread-mark)
- number)))
-
-(defun gnus-summary-set-local-parameters (group)
- "Go through the local params of GROUP and set all variable specs in that list."
- (let ((params (gnus-info-params (gnus-get-info group)))
- elem)
- (while params
- (setq elem (car params)
- params (cdr params))
- (and (consp elem) ; Has to be a cons.
- (consp (cdr elem)) ; The cdr has to be a list.
- (symbolp (car elem)) ; Has to be a symbol in there.
- (not (memq (car elem)
- '(quit-config to-address to-list to-group)))
- (progn ; So we set it.
- (make-local-variable (car elem))
- (set (car elem) (eval (nth 1 elem))))))))
-
-(defun gnus-summary-read-group (group &optional show-all no-article
- kill-buffer no-display)
- "Start reading news in newsgroup GROUP.
-If SHOW-ALL is non-nil, already read articles are also listed.
-If NO-ARTICLE is non-nil, no article is selected initially.
-If NO-DISPLAY, don't generate a summary buffer."
- (gnus-message 5 "Retrieving newsgroup: %s..." group)
- (let* ((new-group (gnus-summary-setup-buffer group))
- (quit-config (gnus-group-quit-config group))
- (did-select (and new-group (gnus-select-newsgroup group show-all))))
- (cond
- ;; This summary buffer exists already, so we just select it.
- ((not new-group)
- (gnus-set-global-variables)
- (when kill-buffer
- (gnus-kill-or-deaden-summary kill-buffer))
- (gnus-configure-windows 'summary 'force)
- (gnus-set-mode-line 'summary)
- (gnus-summary-position-point)
- (message "")
- t)
- ;; We couldn't select this group.
- ((null did-select)
- (when (and (eq major-mode 'gnus-summary-mode)
- (not (equal (current-buffer) kill-buffer)))
- (kill-buffer (current-buffer))
- (if (not quit-config)
- (progn
- (set-buffer gnus-group-buffer)
- (gnus-group-jump-to-group group)
- (gnus-group-next-unread-group 1))
- (if (not (buffer-name (car quit-config)))
- (gnus-configure-windows 'group 'force)
- (set-buffer (car quit-config))
- (and (eq major-mode 'gnus-summary-mode)
- (gnus-set-global-variables))
- (gnus-configure-windows (cdr quit-config)))))
- (gnus-message 3 "Can't select group")
- nil)
- ;; The user did a `C-g' while prompting for number of articles,
- ;; so we exit this group.
- ((eq did-select 'quit)
- (and (eq major-mode 'gnus-summary-mode)
- (not (equal (current-buffer) kill-buffer))
- (kill-buffer (current-buffer)))
- (when kill-buffer
- (gnus-kill-or-deaden-summary kill-buffer))
- (if (not quit-config)
- (progn
- (set-buffer gnus-group-buffer)
- (gnus-group-jump-to-group group)
- (gnus-group-next-unread-group 1)
- (gnus-configure-windows 'group 'force))
- (if (not (buffer-name (car quit-config)))
- (gnus-configure-windows 'group 'force)
- (set-buffer (car quit-config))
- (and (eq major-mode 'gnus-summary-mode)
- (gnus-set-global-variables))
- (gnus-configure-windows (cdr quit-config))))
- ;; Finally signal the quit.
- (signal 'quit nil))
- ;; The group was successfully selected.
- (t
- (gnus-set-global-variables)
- ;; Save the active value in effect when the group was entered.
- (setq gnus-newsgroup-active
- (gnus-copy-sequence
- (gnus-active gnus-newsgroup-name)))
- ;; You can change the summary buffer in some way with this hook.
- (run-hooks 'gnus-select-group-hook)
- ;; Set any local variables in the group parameters.
- (gnus-summary-set-local-parameters gnus-newsgroup-name)
- (gnus-update-format-specifications)
- ;; Do score processing.
- (when gnus-use-scoring
- (gnus-possibly-score-headers))
- ;; Check whether to fill in the gaps in the threads.
- (when gnus-build-sparse-threads
- (gnus-build-sparse-threads))
- ;; Find the initial limit.
- (if gnus-show-threads
- (if show-all
- (let ((gnus-newsgroup-dormant nil))
- (gnus-summary-initial-limit show-all))
- (gnus-summary-initial-limit show-all))
- (setq gnus-newsgroup-limit
- (mapcar
- (lambda (header) (mail-header-number header))
- gnus-newsgroup-headers)))
- ;; Generate the summary buffer.
- (unless no-display
- (gnus-summary-prepare))
- (when gnus-use-trees
- (gnus-tree-open group)
- (setq gnus-summary-highlight-line-function
- 'gnus-tree-highlight-article))
- ;; If the summary buffer is empty, but there are some low-scored
- ;; articles or some excluded dormants, we include these in the
- ;; buffer.
- (when (and (zerop (buffer-size))
- (not no-display))
- (cond (gnus-newsgroup-dormant
- (gnus-summary-limit-include-dormant))
- ((and gnus-newsgroup-scored show-all)
- (gnus-summary-limit-include-expunged))))
- ;; Function `gnus-apply-kill-file' must be called in this hook.
- (run-hooks 'gnus-apply-kill-hook)
- (if (and (zerop (buffer-size))
- (not no-display))
- (progn
- ;; This newsgroup is empty.
- (gnus-summary-catchup-and-exit nil t) ;Without confirmations.
- (gnus-message 6 "No unread news")
- (when kill-buffer
- (gnus-kill-or-deaden-summary kill-buffer))
- ;; Return nil from this function.
- nil)
- ;; Hide conversation thread subtrees. We cannot do this in
- ;; gnus-summary-prepare-hook since kill processing may not
- ;; work with hidden articles.
- (and gnus-show-threads
- gnus-thread-hide-subtree
- (gnus-summary-hide-all-threads))
- ;; Show first unread article if requested.
- (if (and (not no-article)
- (not no-display)
- gnus-newsgroup-unreads
- gnus-auto-select-first)
- (unless (if (eq gnus-auto-select-first 'best)
- (gnus-summary-best-unread-article)
- (gnus-summary-first-unread-article))
- (gnus-configure-windows 'summary))
- ;; Don't select any articles, just move point to the first
- ;; article in the group.
- (goto-char (point-min))
- (gnus-summary-position-point)
- (gnus-set-mode-line 'summary)
- (gnus-configure-windows 'summary 'force))
- ;; If we are in async mode, we send some info to the backend.
- (when gnus-newsgroup-async
- (gnus-request-asynchronous gnus-newsgroup-name gnus-newsgroup-data))
- (when kill-buffer
- (gnus-kill-or-deaden-summary kill-buffer))
- (when (get-buffer-window gnus-group-buffer t)
- ;; Gotta use windows, because recenter does wierd stuff if
- ;; the current buffer ain't the displayed window.
- (let ((owin (selected-window)))
- (select-window (get-buffer-window gnus-group-buffer t))
- (when (gnus-group-goto-group group)
- (recenter))
- (select-window owin))))
- ;; Mark this buffer as "prepared".
- (setq gnus-newsgroup-prepared t)
- t))))
-
-(defun gnus-summary-prepare ()
- "Generate the summary buffer."
- (let ((buffer-read-only nil))
- (erase-buffer)
- (setq gnus-newsgroup-data nil
- gnus-newsgroup-data-reverse nil)
- (run-hooks 'gnus-summary-generate-hook)
- ;; Generate the buffer, either with threads or without.
- (when gnus-newsgroup-headers
- (gnus-summary-prepare-threads
- (if gnus-show-threads
- (gnus-sort-gathered-threads
- (funcall gnus-summary-thread-gathering-function
- (gnus-sort-threads
- (gnus-cut-threads (gnus-make-threads)))))
- ;; Unthreaded display.
- (gnus-sort-articles gnus-newsgroup-headers))))
- (setq gnus-newsgroup-data (nreverse gnus-newsgroup-data))
- ;; Call hooks for modifying summary buffer.
- (goto-char (point-min))
- (run-hooks 'gnus-summary-prepare-hook)))
-
-(defun gnus-gather-threads-by-subject (threads)
- "Gather threads by looking at Subject headers."
- (if (not gnus-summary-make-false-root)
- threads
- (let ((hashtb (gnus-make-hashtable 1023))
- (prev threads)
- (result threads)
- subject hthread whole-subject)
- (while threads
- (setq whole-subject (mail-header-subject (caar threads)))
- (setq subject
- (cond
- ;; Truncate the subject.
- ((numberp gnus-summary-gather-subject-limit)
- (setq subject (gnus-simplify-subject-re whole-subject))
- (if (> (length subject) gnus-summary-gather-subject-limit)
- (substring subject 0 gnus-summary-gather-subject-limit)
- subject))
- ;; Fuzzily simplify it.
- ((eq 'fuzzy gnus-summary-gather-subject-limit)
- (gnus-simplify-subject-fuzzy whole-subject))
- ;; Just remove the leading "Re:".
- (t
- (gnus-simplify-subject-re whole-subject))))
-
- (if (and gnus-summary-gather-exclude-subject
- (string-match gnus-summary-gather-exclude-subject
- subject))
- () ; We don't want to do anything with this article.
- ;; We simplify the subject before looking it up in the
- ;; hash table.
-
- (if (setq hthread (gnus-gethash subject hashtb))
- (progn
- ;; We enter a dummy root into the thread, if we
- ;; haven't done that already.
- (unless (stringp (caar hthread))
- (setcar hthread (list whole-subject (car hthread))))
- ;; We add this new gathered thread to this gathered
- ;; thread.
- (setcdr (car hthread)
- (nconc (cdar hthread) (list (car threads))))
- ;; Remove it from the list of threads.
- (setcdr prev (cdr threads))
- (setq threads prev))
- ;; Enter this thread into the hash table.
- (gnus-sethash subject threads hashtb)))
- (setq prev threads)
- (setq threads (cdr threads)))
- result)))
-
-(defun gnus-gather-threads-by-references (threads)
- "Gather threads by looking at References headers."
- (let ((idhashtb (gnus-make-hashtable 1023))
- (thhashtb (gnus-make-hashtable 1023))
- (prev threads)
- (result threads)
- ids references id gthread gid entered)
- (while threads
- (when (setq references (mail-header-references (caar threads)))
- (setq id (mail-header-id (caar threads)))
- (setq ids (gnus-split-references references))
- (setq entered nil)
- (while ids
- (if (not (setq gid (gnus-gethash (car ids) idhashtb)))
- (progn
- (gnus-sethash (car ids) id idhashtb)
- (gnus-sethash id threads thhashtb))
- (setq gthread (gnus-gethash gid thhashtb))
- (unless entered
- ;; We enter a dummy root into the thread, if we
- ;; haven't done that already.
- (unless (stringp (caar gthread))
- (setcar gthread (list (mail-header-subject (caar gthread))
- (car gthread))))
- ;; We add this new gathered thread to this gathered
- ;; thread.
- (setcdr (car gthread)
- (nconc (cdar gthread) (list (car threads)))))
- ;; Add it into the thread hash table.
- (gnus-sethash id gthread thhashtb)
- (setq entered t)
- ;; Remove it from the list of threads.
- (setcdr prev (cdr threads))
- (setq threads prev))
- (setq ids (cdr ids))))
- (setq prev threads)
- (setq threads (cdr threads)))
- result))
-
-(defun gnus-sort-gathered-threads (threads)
- "Sort subtreads inside each gathered thread by article number."
- (let ((result threads))
- (while threads
- (when (stringp (caar threads))
- (setcdr (car threads)
- (sort (cdar threads) 'gnus-thread-sort-by-number)))
- (setq threads (cdr threads)))
- result))
-
-(defun gnus-make-threads ()
- "Go through the dependency hashtb and find the roots. Return all threads."
- (let (threads)
- (mapatoms
- (lambda (refs)
- (unless (car (symbol-value refs))
- ;; These threads do not refer back to any other articles,
- ;; so they're roots.
- (setq threads (append (cdr (symbol-value refs)) threads))))
- gnus-newsgroup-dependencies)
- threads))
-
-(defun gnus-build-sparse-threads ()
- (let ((headers gnus-newsgroup-headers)
- (deps gnus-newsgroup-dependencies)
- header references generation relations
- cthread subject child end pthread relation)
- ;; First we create an alist of generations/relations, where
- ;; generations is how much we trust the ralation, and the relation
- ;; is parent/child.
- (gnus-message 7 "Making sparse threads...")
- (save-excursion
- (nnheader-set-temp-buffer " *gnus sparse threads*")
- (while (setq header (pop headers))
- (when (and (setq references (mail-header-references header))
- (not (string= references "")))
- (insert references)
- (setq child (mail-header-id header)
- subject (mail-header-subject header))
- (setq generation 0)
- (while (search-backward ">" nil t)
- (setq end (1+ (point)))
- (when (search-backward "<" nil t)
- (push (list (incf generation)
- child (setq child (buffer-substring (point) end))
- subject)
- relations)))
- (push (list (1+ generation) child nil subject) relations)
- (erase-buffer)))
- (kill-buffer (current-buffer)))
- ;; Sort over trustworthiness.
- (setq relations (sort relations (lambda (r1 r2) (< (car r1) (car r2)))))
- (while (setq relation (pop relations))
- (when (if (boundp (setq cthread (intern (cadr relation) deps)))
- (unless (car (symbol-value cthread))
- ;; Make this article the parent of these threads.
- (setcar (symbol-value cthread)
- (vector gnus-reffed-article-number
- (cadddr relation)
- "" ""
- (cadr relation)
- (or (caddr relation) "") 0 0 "")))
- (set cthread (list (vector gnus-reffed-article-number
- (cadddr relation)
- "" "" (cadr relation)
- (or (caddr relation) "") 0 0 ""))))
- (push gnus-reffed-article-number gnus-newsgroup-limit)
- (push gnus-reffed-article-number gnus-newsgroup-sparse)
- (push (cons gnus-reffed-article-number gnus-sparse-mark)
- gnus-newsgroup-reads)
- (decf gnus-reffed-article-number)
- ;; Make this new thread the child of its parent.
- (if (boundp (setq pthread (intern (or (caddr relation) "none") deps)))
- (setcdr (symbol-value pthread)
- (nconc (cdr (symbol-value pthread))
- (list (symbol-value cthread))))
- (set pthread (list nil (symbol-value cthread))))))
- (gnus-message 7 "Making sparse threads...done")))
-
-(defun gnus-build-old-threads ()
- ;; Look at all the articles that refer back to old articles, and
- ;; fetch the headers for the articles that aren't there. This will
- ;; build complete threads - if the roots haven't been expired by the
- ;; server, that is.
- (let (id heads)
- (mapatoms
- (lambda (refs)
- (when (not (car (symbol-value refs)))
- (setq heads (cdr (symbol-value refs)))
- (while heads
- (if (memq (mail-header-number (caar heads))
- gnus-newsgroup-dormant)
- (setq heads (cdr heads))
- (setq id (symbol-name refs))
- (while (and (setq id (gnus-build-get-header id))
- (not (car (gnus-gethash
- id gnus-newsgroup-dependencies)))))
- (setq heads nil)))))
- gnus-newsgroup-dependencies)))
-
-(defun gnus-build-get-header (id)
- ;; Look through the buffer of NOV lines and find the header to
- ;; ID. Enter this line into the dependencies hash table, and return
- ;; the id of the parent article (if any).
- (let ((deps gnus-newsgroup-dependencies)
- found header)
- (prog1
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (while (and (not found) (search-forward id nil t))
- (beginning-of-line)
- (setq found (looking-at
- (format "^[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t%s"
- (regexp-quote id))))
- (or found (beginning-of-line 2)))
- (when found
- (beginning-of-line)
- (and
- (setq header (gnus-nov-parse-line
- (read (current-buffer)) deps))
- (gnus-parent-id (mail-header-references header)))))
- (when header
- (let ((number (mail-header-number header)))
- (push number gnus-newsgroup-limit)
- (push header gnus-newsgroup-headers)
- (if (memq number gnus-newsgroup-unselected)
- (progn
- (push number gnus-newsgroup-unreads)
- (setq gnus-newsgroup-unselected
- (delq number gnus-newsgroup-unselected)))
- (push number gnus-newsgroup-ancient)))))))
-
-(defun gnus-summary-update-article (article &optional iheader)
- "Update ARTICLE in the summary buffer."
- (set-buffer gnus-summary-buffer)
- (let* ((header (or iheader (gnus-summary-article-header article)))
- (id (mail-header-id header))
- (data (gnus-data-find article))
- (thread (gnus-id-to-thread id))
- (references (mail-header-references header))
- (parent
- (gnus-id-to-thread
- (or (gnus-parent-id
- (if (and references
- (not (equal "" references)))
- references))
- "none")))
- (buffer-read-only nil)
- (old (car thread))
- (number (mail-header-number header))
- pos)
- (when thread
- ;; !!! Should this be in or not?
- (unless iheader
- (setcar thread nil))
- (when parent
- (delq thread parent))
- (if (gnus-summary-insert-subject id header iheader)
- ;; Set the (possibly) new article number in the data structure.
- (gnus-data-set-number data (gnus-id-to-article id))
- (setcar thread old)
- nil))))
-
-(defun gnus-rebuild-thread (id)
- "Rebuild the thread containing ID."
- (let ((buffer-read-only nil)
- current thread data)
- (if (not gnus-show-threads)
- (setq thread (list (car (gnus-id-to-thread id))))
- ;; Get the thread this article is part of.
- (setq thread (gnus-remove-thread id)))
- (setq current (save-excursion
- (and (zerop (forward-line -1))
- (gnus-summary-article-number))))
- ;; If this is a gathered thread, we have to go some re-gathering.
- (when (stringp (car thread))
- (let ((subject (car thread))
- roots thr)
- (setq thread (cdr thread))
- (while thread
- (unless (memq (setq thr (gnus-id-to-thread
- (gnus-root-id
- (mail-header-id (caar thread)))))
- roots)
- (push thr roots))
- (setq thread (cdr thread)))
- ;; We now have all (unique) roots.
- (if (= (length roots) 1)
- ;; All the loose roots are now one solid root.
- (setq thread (car roots))
- (setq thread (cons subject (gnus-sort-threads roots))))))
- (let (threads)
- ;; We then insert this thread into the summary buffer.
- (let (gnus-newsgroup-data gnus-newsgroup-threads)
- (gnus-summary-prepare-threads (gnus-cut-threads (list thread)))
- (setq data (nreverse gnus-newsgroup-data))
- (setq threads gnus-newsgroup-threads))
- ;; We splice the new data into the data structure.
- (gnus-data-enter-list current data)
- (gnus-data-compute-positions)
- (setq gnus-newsgroup-threads (nconc threads gnus-newsgroup-threads)))))
-
-(defun gnus-number-to-header (number)
- "Return the header for article NUMBER."
- (let ((headers gnus-newsgroup-headers))
- (while (and headers
- (not (= number (mail-header-number (car headers)))))
- (pop headers))
- (when headers
- (car headers))))
-
-(defun gnus-id-to-thread (id)
- "Return the (sub-)thread where ID appears."
- (gnus-gethash id gnus-newsgroup-dependencies))
-
-(defun gnus-id-to-article (id)
- "Return the article number of ID."
- (let ((thread (gnus-id-to-thread id)))
- (when (and thread
- (car thread))
- (mail-header-number (car thread)))))
-
-(defun gnus-id-to-header (id)
- "Return the article headers of ID."
- (car (gnus-id-to-thread id)))
-
-(defun gnus-article-displayed-root-p (article)
- "Say whether ARTICLE is a root(ish) article."
- (let ((level (gnus-summary-thread-level article))
- (refs (mail-header-references (gnus-summary-article-header article)))
- particle)
- (cond
- ((null level) nil)
- ((zerop level) t)
- ((null refs) t)
- ((null (gnus-parent-id refs)) t)
- ((and (= 1 level)
- (null (setq particle (gnus-id-to-article
- (gnus-parent-id refs))))
- (null (gnus-summary-thread-level particle)))))))
-
-(defun gnus-root-id (id)
- "Return the id of the root of the thread where ID appears."
- (let (last-id prev)
- (while (and id (setq prev (car (gnus-gethash
- id gnus-newsgroup-dependencies))))
- (setq last-id id
- id (gnus-parent-id (mail-header-references prev))))
- last-id))
-
-(defun gnus-remove-thread (id &optional dont-remove)
- "Remove the thread that has ID in it."
- (let ((dep gnus-newsgroup-dependencies)
- headers thread last-id)
- ;; First go up in this thread until we find the root.
- (setq last-id (gnus-root-id id))
- (setq headers (list (car (gnus-id-to-thread last-id))
- (caadr (gnus-id-to-thread last-id))))
- ;; We have now found the real root of this thread. It might have
- ;; been gathered into some loose thread, so we have to search
- ;; through the threads to find the thread we wanted.
- (let ((threads gnus-newsgroup-threads)
- sub)
- (while threads
- (setq sub (car threads))
- (if (stringp (car sub))
- ;; This is a gathered threads, so we look at the roots
- ;; below it to find whether this article in in this
- ;; gathered root.
- (progn
- (setq sub (cdr sub))
- (while sub
- (when (member (caar sub) headers)
- (setq thread (car threads)
- threads nil
- sub nil))
- (setq sub (cdr sub))))
- ;; It's an ordinary thread, so we check it.
- (when (eq (car sub) (car headers))
- (setq thread sub
- threads nil)))
- (setq threads (cdr threads)))
- ;; If this article is in no thread, then it's a root.
- (if thread
- (unless dont-remove
- (setq gnus-newsgroup-threads (delq thread gnus-newsgroup-threads)))
- (setq thread (gnus-gethash last-id dep)))
- (when thread
- (prog1
- thread ; We return this thread.
- (unless dont-remove
- (if (stringp (car thread))
- (progn
- ;; If we use dummy roots, then we have to remove the
- ;; dummy root as well.
- (when (eq gnus-summary-make-false-root 'dummy)
- ;; Uhm.
- )
- (setq thread (cdr thread))
- (while thread
- (gnus-remove-thread-1 (car thread))
- (setq thread (cdr thread))))
- (gnus-remove-thread-1 thread))))))))
-
-(defun gnus-remove-thread-1 (thread)
- "Remove the thread THREAD recursively."
- (let ((number (mail-header-number (car thread)))
- pos)
- (when (setq pos (text-property-any
- (point-min) (point-max) 'gnus-number number))
- (goto-char pos)
- (gnus-delete-line)
- (gnus-data-remove number))
- (setq thread (cdr thread))
- (while thread
- (gnus-remove-thread-1 (pop thread)))))
-
-(defun gnus-sort-threads (threads)
- "Sort THREADS."
- (if (not gnus-thread-sort-functions)
- threads
- (let ((func (if (= 1 (length gnus-thread-sort-functions))
- (car gnus-thread-sort-functions)
- `(lambda (t1 t2)
- ,(gnus-make-sort-function
- (reverse gnus-thread-sort-functions))))))
- (gnus-message 7 "Sorting threads...")
- (prog1
- (sort threads func)
- (gnus-message 7 "Sorting threads...done")))))
-
-(defun gnus-sort-articles (articles)
- "Sort ARTICLES."
- (when gnus-article-sort-functions
- (let ((func (if (= 1 (length gnus-article-sort-functions))
- (car gnus-article-sort-functions)
- `(lambda (t1 t2)
- ,(gnus-make-sort-function
- (reverse gnus-article-sort-functions))))))
- (gnus-message 7 "Sorting articles...")
- (prog1
- (setq gnus-newsgroup-headers (sort articles func))
- (gnus-message 7 "Sorting articles...done")))))
-
-(defun gnus-make-sort-function (funs)
- "Return a composite sort condition based on the functions in FUNC."
- (if (cdr funs)
- `(or (,(car funs) t1 t2)
- (and (not (,(car funs) t2 t1))
- ,(gnus-make-sort-function (cdr funs))))
- `(,(car funs) t1 t2)))
-
-;; Written by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
-(defmacro gnus-thread-header (thread)
- ;; Return header of first article in THREAD.
- ;; Note that THREAD must never, ever be anything else than a variable -
- ;; using some other form will lead to serious barfage.
- (or (symbolp thread) (signal 'wrong-type-argument '(symbolp thread)))
- ;; (8% speedup to gnus-summary-prepare, just for fun :-)
- (list 'byte-code "\10\211:\203\17\0\211@;\203\16\0A@@\207" ;
- (vector thread) 2))
-
-(defsubst gnus-article-sort-by-number (h1 h2)
- "Sort articles by article number."
- (< (mail-header-number h1)
- (mail-header-number h2)))
-
-(defun gnus-thread-sort-by-number (h1 h2)
- "Sort threads by root article number."
- (gnus-article-sort-by-number
- (gnus-thread-header h1) (gnus-thread-header h2)))
-
-(defsubst gnus-article-sort-by-author (h1 h2)
- "Sort articles by root author."
- (string-lessp
- (let ((extract (funcall
- gnus-extract-address-components
- (mail-header-from h1))))
- (or (car extract) (cdr extract)))
- (let ((extract (funcall
- gnus-extract-address-components
- (mail-header-from h2))))
- (or (car extract) (cdr extract)))))
-
-(defun gnus-thread-sort-by-author (h1 h2)
- "Sort threads by root author."
- (gnus-article-sort-by-author
- (gnus-thread-header h1) (gnus-thread-header h2)))
-
-(defsubst gnus-article-sort-by-subject (h1 h2)
- "Sort articles by root subject."
- (string-lessp
- (downcase (gnus-simplify-subject-re (mail-header-subject h1)))
- (downcase (gnus-simplify-subject-re (mail-header-subject h2)))))
-
-(defun gnus-thread-sort-by-subject (h1 h2)
- "Sort threads by root subject."
- (gnus-article-sort-by-subject
- (gnus-thread-header h1) (gnus-thread-header h2)))
-
-(defsubst gnus-article-sort-by-date (h1 h2)
- "Sort articles by root article date."
- (string-lessp
- (inline (gnus-sortable-date (mail-header-date h1)))
- (inline (gnus-sortable-date (mail-header-date h2)))))
-
-(defun gnus-thread-sort-by-date (h1 h2)
- "Sort threads by root article date."
- (gnus-article-sort-by-date
- (gnus-thread-header h1) (gnus-thread-header h2)))
-
-(defsubst gnus-article-sort-by-score (h1 h2)
- "Sort articles by root article score.
-Unscored articles will be counted as having a score of zero."
- (> (or (cdr (assq (mail-header-number h1)
- gnus-newsgroup-scored))
- gnus-summary-default-score 0)
- (or (cdr (assq (mail-header-number h2)
- gnus-newsgroup-scored))
- gnus-summary-default-score 0)))
-
-(defun gnus-thread-sort-by-score (h1 h2)
- "Sort threads by root article score."
- (gnus-article-sort-by-score
- (gnus-thread-header h1) (gnus-thread-header h2)))
-
-(defun gnus-thread-sort-by-total-score (h1 h2)
- "Sort threads by the sum of all scores in the thread.
-Unscored articles will be counted as having a score of zero."
- (> (gnus-thread-total-score h1) (gnus-thread-total-score h2)))
-
-(defun gnus-thread-total-score (thread)
- ;; This function find the total score of THREAD.
- (cond ((null thread)
- 0)
- ((consp thread)
- (if (stringp (car thread))
- (apply gnus-thread-score-function 0
- (mapcar 'gnus-thread-total-score-1 (cdr thread)))
- (gnus-thread-total-score-1 thread)))
- (t
- (gnus-thread-total-score-1 (list thread)))))
-
-(defun gnus-thread-total-score-1 (root)
- ;; This function find the total score of the thread below ROOT.
- (setq root (car root))
- (apply gnus-thread-score-function
- (or (append
- (mapcar 'gnus-thread-total-score
- (cdr (gnus-gethash (mail-header-id root)
- gnus-newsgroup-dependencies)))
- (if (> (mail-header-number root) 0)
- (list (or (cdr (assq (mail-header-number root)
- gnus-newsgroup-scored))
- gnus-summary-default-score 0))))
- (list gnus-summary-default-score)
- '(0))))
-
-;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
-(defvar gnus-tmp-prev-subject nil)
-(defvar gnus-tmp-false-parent nil)
-(defvar gnus-tmp-root-expunged nil)
-(defvar gnus-tmp-dummy-line nil)
-
-(defun gnus-summary-prepare-threads (threads)
- "Prepare summary buffer from THREADS and indentation LEVEL.
-THREADS is either a list of `(PARENT [(CHILD1 [(GRANDCHILD ...]...) ...])'
-or a straight list of headers."
- (gnus-message 7 "Generating summary...")
-
- (setq gnus-newsgroup-threads threads)
- (beginning-of-line)
-
- (let ((gnus-tmp-level 0)
- (default-score (or gnus-summary-default-score 0))
- (gnus-visual-p (gnus-visual-p 'summary-highlight 'highlight))
- thread number subject stack state gnus-tmp-gathered beg-match
- new-roots gnus-tmp-new-adopts thread-end
- gnus-tmp-header gnus-tmp-unread
- gnus-tmp-replied gnus-tmp-subject-or-nil
- gnus-tmp-dummy gnus-tmp-indentation gnus-tmp-lines gnus-tmp-score
- gnus-tmp-score-char gnus-tmp-from gnus-tmp-name
- gnus-tmp-number gnus-tmp-opening-bracket gnus-tmp-closing-bracket)
-
- (setq gnus-tmp-prev-subject nil)
-
- (if (vectorp (car threads))
- ;; If this is a straight (sic) list of headers, then a
- ;; threaded summary display isn't required, so we just create
- ;; an unthreaded one.
- (gnus-summary-prepare-unthreaded threads)
-
- ;; Do the threaded display.
-
- (while (or threads stack gnus-tmp-new-adopts new-roots)
-
- (if (and (= gnus-tmp-level 0)
- (not (setq gnus-tmp-dummy-line nil))
- (or (not stack)
- (= (caar stack) 0))
- (not gnus-tmp-false-parent)
- (or gnus-tmp-new-adopts new-roots))
- (if gnus-tmp-new-adopts
- (setq gnus-tmp-level (if gnus-tmp-root-expunged 0 1)
- thread (list (car gnus-tmp-new-adopts))
- gnus-tmp-header (caar thread)
- gnus-tmp-new-adopts (cdr gnus-tmp-new-adopts))
- (if new-roots
- (setq thread (list (car new-roots))
- gnus-tmp-header (caar thread)
- new-roots (cdr new-roots))))
-
- (if threads
- ;; If there are some threads, we do them before the
- ;; threads on the stack.
- (setq thread threads
- gnus-tmp-header (caar thread))
- ;; There were no current threads, so we pop something off
- ;; the stack.
- (setq state (car stack)
- gnus-tmp-level (car state)
- thread (cdr state)
- stack (cdr stack)
- gnus-tmp-header (caar thread))))
-
- (setq gnus-tmp-false-parent nil)
- (setq gnus-tmp-root-expunged nil)
- (setq thread-end nil)
-
- (if (stringp gnus-tmp-header)
- ;; The header is a dummy root.
- (cond
- ((eq gnus-summary-make-false-root 'adopt)
- ;; We let the first article adopt the rest.
- (setq gnus-tmp-new-adopts (nconc gnus-tmp-new-adopts
- (cddar thread)))
- (setq gnus-tmp-gathered
- (nconc (mapcar
- (lambda (h) (mail-header-number (car h)))
- (cddar thread))
- gnus-tmp-gathered))
- (setq thread (cons (list (caar thread)
- (cadar thread))
- (cdr thread)))
- (setq gnus-tmp-level -1
- gnus-tmp-false-parent t))
- ((eq gnus-summary-make-false-root 'empty)
- ;; We print adopted articles with empty subject fields.
- (setq gnus-tmp-gathered
- (nconc (mapcar
- (lambda (h) (mail-header-number (car h)))
- (cddar thread))
- gnus-tmp-gathered))
- (setq gnus-tmp-level -1))
- ((eq gnus-summary-make-false-root 'dummy)
- ;; We remember that we probably want to output a dummy
- ;; root.
- (setq gnus-tmp-dummy-line gnus-tmp-header)
- (setq gnus-tmp-prev-subject gnus-tmp-header))
- (t
- ;; We do not make a root for the gathered
- ;; sub-threads at all.
- (setq gnus-tmp-level -1)))
-
- (setq number (mail-header-number gnus-tmp-header)
- subject (mail-header-subject gnus-tmp-header))
-
- (cond
- ;; If the thread has changed subject, we might want to make
- ;; this subthread into a root.
- ((and (null gnus-thread-ignore-subject)
- (not (zerop gnus-tmp-level))
- gnus-tmp-prev-subject
- (not (inline
- (gnus-subject-equal gnus-tmp-prev-subject subject))))
- (setq new-roots (nconc new-roots (list (car thread)))
- thread-end t
- gnus-tmp-header nil))
- ;; If the article lies outside the current limit,
- ;; then we do not display it.
- ((and (not (memq number gnus-newsgroup-limit))
- (not gnus-tmp-dummy-line))
- (setq gnus-tmp-gathered
- (nconc (mapcar
- (lambda (h) (mail-header-number (car h)))
- (cdar thread))
- gnus-tmp-gathered))
- (setq gnus-tmp-new-adopts (if (cdar thread)
- (append gnus-tmp-new-adopts
- (cdar thread))
- gnus-tmp-new-adopts)
- thread-end t
- gnus-tmp-header nil)
- (when (zerop gnus-tmp-level)
- (setq gnus-tmp-root-expunged t)))
- ;; Perhaps this article is to be marked as read?
- ((and gnus-summary-mark-below
- (< (or (cdr (assq number gnus-newsgroup-scored))
- default-score)
- gnus-summary-mark-below)
- ;; Don't touch sparse articles.
- (not (memq number gnus-newsgroup-sparse))
- (not (memq number gnus-newsgroup-ancient)))
- (setq gnus-newsgroup-unreads
- (delq number gnus-newsgroup-unreads))
- (if gnus-newsgroup-auto-expire
- (push number gnus-newsgroup-expirable)
- (push (cons number gnus-low-score-mark)
- gnus-newsgroup-reads))))
-
- (when gnus-tmp-header
- ;; We may have an old dummy line to output before this
- ;; article.
- (when gnus-tmp-dummy-line
- (gnus-summary-insert-dummy-line
- gnus-tmp-dummy-line (mail-header-number gnus-tmp-header))
- (setq gnus-tmp-dummy-line nil))
-
- ;; Compute the mark.
- (setq
- gnus-tmp-unread
- (cond
- ((memq number gnus-newsgroup-unreads) gnus-unread-mark)
- ((memq number gnus-newsgroup-marked) gnus-ticked-mark)
- ((memq number gnus-newsgroup-dormant) gnus-dormant-mark)
- ((memq number gnus-newsgroup-expirable) gnus-expirable-mark)
- (t (or (cdr (assq number gnus-newsgroup-reads))
- gnus-ancient-mark))))
-
- (push (gnus-data-make number gnus-tmp-unread (1+ (point))
- gnus-tmp-header gnus-tmp-level)
- gnus-newsgroup-data)
-
- ;; Actually insert the line.
- (setq
- gnus-tmp-subject-or-nil
- (cond
- ((and gnus-thread-ignore-subject
- gnus-tmp-prev-subject
- (not (inline (gnus-subject-equal
- gnus-tmp-prev-subject subject))))
- subject)
- ((zerop gnus-tmp-level)
- (if (and (eq gnus-summary-make-false-root 'empty)
- (memq number gnus-tmp-gathered)
- gnus-tmp-prev-subject
- (inline (gnus-subject-equal
- gnus-tmp-prev-subject subject)))
- gnus-summary-same-subject
- subject))
- (t gnus-summary-same-subject)))
- (if (and (eq gnus-summary-make-false-root 'adopt)
- (= gnus-tmp-level 1)
- (memq number gnus-tmp-gathered))
- (setq gnus-tmp-opening-bracket ?\<
- gnus-tmp-closing-bracket ?\>)
- (setq gnus-tmp-opening-bracket ?\[
- gnus-tmp-closing-bracket ?\]))
- (setq
- gnus-tmp-indentation
- (aref gnus-thread-indent-array gnus-tmp-level)
- gnus-tmp-lines (mail-header-lines gnus-tmp-header)
- gnus-tmp-score (or (cdr (assq number gnus-newsgroup-scored))
- gnus-summary-default-score 0)
- gnus-tmp-score-char
- (if (or (null gnus-summary-default-score)
- (<= (abs (- gnus-tmp-score gnus-summary-default-score))
- gnus-summary-zcore-fuzz)) ?
- (if (< gnus-tmp-score gnus-summary-default-score)
- gnus-score-below-mark gnus-score-over-mark))
- gnus-tmp-replied
- (cond ((memq number gnus-newsgroup-processable)
- gnus-process-mark)
- ((memq number gnus-newsgroup-cached)
- gnus-cached-mark)
- ((memq number gnus-newsgroup-replied)
- gnus-replied-mark)
- ((memq number gnus-newsgroup-saved)
- gnus-saved-mark)
- (t gnus-unread-mark))
- gnus-tmp-from (mail-header-from gnus-tmp-header)
- gnus-tmp-name
- (cond
- ((string-match "(.+)" gnus-tmp-from)
- (substring gnus-tmp-from
- (1+ (match-beginning 0)) (1- (match-end 0))))
- ((string-match "<[^>]+> *$" gnus-tmp-from)
- (setq beg-match (match-beginning 0))
- (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
- (substring gnus-tmp-from (1+ (match-beginning 0))
- (1- (match-end 0))))
- (substring gnus-tmp-from 0 beg-match)))
- (t gnus-tmp-from)))
- (when (string= gnus-tmp-name "")
- (setq gnus-tmp-name gnus-tmp-from))
- (or (numberp gnus-tmp-lines) (setq gnus-tmp-lines 0))
- (gnus-put-text-property
- (point)
- (progn (eval gnus-summary-line-format-spec) (point))
- 'gnus-number number)
- (when gnus-visual-p
- (forward-line -1)
- (run-hooks 'gnus-summary-update-hook)
- (forward-line 1))
-
- (setq gnus-tmp-prev-subject subject)))
-
- (when (nth 1 thread)
- (push (cons (max 0 gnus-tmp-level) (nthcdr 1 thread)) stack))
- (incf gnus-tmp-level)
- (setq threads (if thread-end nil (cdar thread)))
- (unless threads
- (setq gnus-tmp-level 0)))))
- (gnus-message 7 "Generating summary...done"))
-
-(defun gnus-summary-prepare-unthreaded (headers)
- "Generate an unthreaded summary buffer based on HEADERS."
- (let (header number mark)
-
- (while headers
- ;; We may have to root out some bad articles...
- (when (memq (setq number (mail-header-number
- (setq header (pop headers))))
- gnus-newsgroup-limit)
- ;; Mark article as read when it has a low score.
- (when (and gnus-summary-mark-below
- (< (or (cdr (assq number gnus-newsgroup-scored))
- gnus-summary-default-score 0)
- gnus-summary-mark-below)
- (not (memq number gnus-newsgroup-ancient)))
- (setq gnus-newsgroup-unreads
- (delq number gnus-newsgroup-unreads))
- (if gnus-newsgroup-auto-expire
- (push number gnus-newsgroup-expirable)
- (push (cons number gnus-low-score-mark)
- gnus-newsgroup-reads)))
-
- (setq mark
- (cond
- ((memq number gnus-newsgroup-marked) gnus-ticked-mark)
- ((memq number gnus-newsgroup-dormant) gnus-dormant-mark)
- ((memq number gnus-newsgroup-unreads) gnus-unread-mark)
- ((memq number gnus-newsgroup-expirable) gnus-expirable-mark)
- (t (or (cdr (assq number gnus-newsgroup-reads))
- gnus-ancient-mark))))
- (setq gnus-newsgroup-data
- (cons (gnus-data-make number mark (1+ (point)) header 0)
- gnus-newsgroup-data))
- (gnus-summary-insert-line
- header 0 nil mark (memq number gnus-newsgroup-replied)
- (memq number gnus-newsgroup-expirable)
- (mail-header-subject header) nil
- (cdr (assq number gnus-newsgroup-scored))
- (memq number gnus-newsgroup-processable))))))
-
-(defun gnus-select-newsgroup (group &optional read-all)
- "Select newsgroup GROUP.
-If READ-ALL is non-nil, all articles in the group are selected."
- (let* ((entry (gnus-gethash group gnus-newsrc-hashtb))
- (info (nth 2 entry))
- articles fetched-articles cached)
-
- (or (gnus-check-server
- (setq gnus-current-select-method (gnus-find-method-for-group group)))
- (error "Couldn't open server"))
-
- (or (and entry (not (eq (car entry) t))) ; Either it's active...
- (gnus-activate-group group) ; Or we can activate it...
- (progn ; Or we bug out.
- (when (equal major-mode 'gnus-summary-mode)
- (kill-buffer (current-buffer)))
- (error "Couldn't request group %s: %s"
- group (gnus-status-message group))))
-
- (unless (gnus-request-group group t)
- (when (equal major-mode 'gnus-summary-mode)
- (kill-buffer (current-buffer)))
- (error "Couldn't request group %s: %s"
- group (gnus-status-message group)))
-
- (setq gnus-newsgroup-name group)
- (setq gnus-newsgroup-unselected nil)
- (setq gnus-newsgroup-unreads (gnus-list-of-unread-articles group))
-
- (and gnus-asynchronous
- (gnus-check-backend-function
- 'request-asynchronous gnus-newsgroup-name)
- (setq gnus-newsgroup-async
- (gnus-request-asynchronous gnus-newsgroup-name)))
-
- ;; Adjust and set lists of article marks.
- (when info
- (gnus-adjust-marked-articles info))
-
- ;; Kludge to avoid having cached articles nixed out in virtual groups.
- (when (gnus-virtual-group-p group)
- (setq cached gnus-newsgroup-cached))
-
- (setq gnus-newsgroup-unreads
- (gnus-set-difference
- (gnus-set-difference gnus-newsgroup-unreads gnus-newsgroup-marked)
- gnus-newsgroup-dormant))
-
- (setq gnus-newsgroup-processable nil)
-
- (setq articles (gnus-articles-to-read group read-all))
-
- (cond
- ((null articles)
- ;;(gnus-message 3 "Couldn't select newsgroup -- no articles to display")
- 'quit)
- ((eq articles 0) nil)
- (t
- ;; Init the dependencies hash table.
- (setq gnus-newsgroup-dependencies
- (gnus-make-hashtable (length articles)))
- ;; Retrieve the headers and read them in.
- (gnus-message 5 "Fetching headers for %s..." gnus-newsgroup-name)
- (setq gnus-newsgroup-headers
- (if (eq 'nov
- (setq gnus-headers-retrieved-by
- (gnus-retrieve-headers
- articles gnus-newsgroup-name
- ;; We might want to fetch old headers, but
- ;; not if there is only 1 article.
- (and gnus-fetch-old-headers
- (or (and
- (not (eq gnus-fetch-old-headers 'some))
- (not (numberp gnus-fetch-old-headers)))
- (> (length articles) 1))))))
- (gnus-get-newsgroup-headers-xover articles)
- (gnus-get-newsgroup-headers)))
- (gnus-message 5 "Fetching headers for %s...done" gnus-newsgroup-name)
-
- ;; Kludge to avoid having cached articles nixed out in virtual groups.
- (when cached
- (setq gnus-newsgroup-cached cached))
-
- ;; Set the initial limit.
- (setq gnus-newsgroup-limit (copy-sequence articles))
- ;; Remove canceled articles from the list of unread articles.
- (setq gnus-newsgroup-unreads
- (gnus-set-sorted-intersection
- gnus-newsgroup-unreads
- (setq fetched-articles
- (mapcar (lambda (headers) (mail-header-number headers))
- gnus-newsgroup-headers))))
- ;; Removed marked articles that do not exist.
- (gnus-update-missing-marks
- (gnus-sorted-complement fetched-articles articles))
- ;; We might want to build some more threads first.
- (and gnus-fetch-old-headers
- (eq gnus-headers-retrieved-by 'nov)
- (gnus-build-old-threads))
- ;; Check whether auto-expire is to be done in this group.
- (setq gnus-newsgroup-auto-expire
- (gnus-group-auto-expirable-p group))
- ;; Set up the article buffer now, if necessary.
- (unless gnus-single-article-buffer
- (gnus-article-setup-buffer))
- ;; First and last article in this newsgroup.
- (when gnus-newsgroup-headers
- (setq gnus-newsgroup-begin
- (mail-header-number (car gnus-newsgroup-headers))
- gnus-newsgroup-end
- (mail-header-number
- (gnus-last-element gnus-newsgroup-headers))))
- (setq gnus-reffed-article-number -1)
- ;; GROUP is successfully selected.
- (or gnus-newsgroup-headers t)))))
-
-(defun gnus-articles-to-read (group read-all)
- ;; Find out what articles the user wants to read.
- (let* ((articles
- ;; Select all articles if `read-all' is non-nil, or if there
- ;; are no unread articles.
- (if (or read-all
- (and (zerop (length gnus-newsgroup-marked))
- (zerop (length gnus-newsgroup-unreads))))
- (gnus-uncompress-range (gnus-active group))
- (sort (append gnus-newsgroup-dormant gnus-newsgroup-marked
- (copy-sequence gnus-newsgroup-unreads))
- '<)))
- (scored-list (gnus-killed-articles gnus-newsgroup-killed articles))
- (scored (length scored-list))
- (number (length articles))
- (marked (+ (length gnus-newsgroup-marked)
- (length gnus-newsgroup-dormant)))
- (select
- (cond
- ((numberp read-all)
- read-all)
- (t
- (condition-case ()
- (cond
- ((and (or (<= scored marked) (= scored number))
- (numberp gnus-large-newsgroup)
- (> number gnus-large-newsgroup))
- (let ((input
- (read-string
- (format
- "How many articles from %s (default %d): "
- gnus-newsgroup-name number))))
- (if (string-match "^[ \t]*$" input) number input)))
- ((and (> scored marked) (< scored number)
- (> (- scored number) 20))
- (let ((input
- (read-string
- (format "%s %s (%d scored, %d total): "
- "How many articles from"
- group scored number))))
- (if (string-match "^[ \t]*$" input)
- number input)))
- (t number))
- (quit nil))))))
- (setq select (if (stringp select) (string-to-number select) select))
- (if (or (null select) (zerop select))
- select
- (if (and (not (zerop scored)) (<= (abs select) scored))
- (progn
- (setq articles (sort scored-list '<))
- (setq number (length articles)))
- (setq articles (copy-sequence articles)))
-
- (if (< (abs select) number)
- (if (< select 0)
- ;; Select the N oldest articles.
- (setcdr (nthcdr (1- (abs select)) articles) nil)
- ;; Select the N most recent articles.
- (setq articles (nthcdr (- number select) articles))))
- (setq gnus-newsgroup-unselected
- (gnus-sorted-intersection
- gnus-newsgroup-unreads
- (gnus-sorted-complement gnus-newsgroup-unreads articles)))
- articles)))
-
-(defun gnus-killed-articles (killed articles)
- (let (out)
- (while articles
- (if (inline (gnus-member-of-range (car articles) killed))
- (setq out (cons (car articles) out)))
- (setq articles (cdr articles)))
- out))
-
-(defun gnus-uncompress-marks (marks)
- "Uncompress the mark ranges in MARKS."
- (let ((uncompressed '(score bookmark))
- out)
- (while marks
- (if (memq (caar marks) uncompressed)
- (push (car marks) out)
- (push (cons (caar marks) (gnus-uncompress-range (cdar marks))) out))
- (setq marks (cdr marks)))
- out))
-
-(defun gnus-adjust-marked-articles (info)
- "Set all article lists and remove all marks that are no longer legal."
- (let* ((marked-lists (gnus-info-marks info))
- (active (gnus-active (gnus-info-group info)))
- (min (car active))
- (max (cdr active))
- (types gnus-article-mark-lists)
- (uncompressed '(score bookmark killed))
- marks var articles article mark)
-
- (while marked-lists
- (setq marks (pop marked-lists))
- (set (setq var (intern (format "gnus-newsgroup-%s"
- (car (rassq (setq mark (car marks))
- types)))))
- (if (memq (car marks) uncompressed) (cdr marks)
- (gnus-uncompress-range (cdr marks))))
-
- (setq articles (symbol-value var))
-
- ;; All articles have to be subsets of the active articles.
- (cond
- ;; Adjust "simple" lists.
- ((memq mark '(tick dormant expirable reply save))
- (while articles
- (when (or (< (setq article (pop articles)) min) (> article max))
- (set var (delq article (symbol-value var))))))
- ;; Adjust assocs.
- ((memq mark uncompressed)
- (while articles
- (when (or (not (consp (setq article (pop articles))))
- (< (car article) min)
- (> (car article) max))
- (set var (delq article (symbol-value var))))))))))
-
-(defun gnus-update-missing-marks (missing)
- "Go through the list of MISSING articles and remove them mark lists."
- (when missing
- (let ((types gnus-article-mark-lists)
- var m)
- ;; Go through all types.
- (while types
- (setq var (intern (format "gnus-newsgroup-%s" (car (pop types)))))
- (when (symbol-value var)
- ;; This list has articles. So we delete all missing articles
- ;; from it.
- (setq m missing)
- (while m
- (set var (delq (pop m) (symbol-value var)))))))))
-
-(defun gnus-update-marks ()
- "Enter the various lists of marked articles into the newsgroup info list."
- (let ((types gnus-article-mark-lists)
- (info (gnus-get-info gnus-newsgroup-name))
- (uncompressed '(score bookmark killed))
- type list newmarked symbol)
- (when info
- ;; Add all marks lists that are non-nil to the list of marks lists.
- (while types
- (setq type (pop types))
- (when (setq list (symbol-value
- (setq symbol
- (intern (format "gnus-newsgroup-%s"
- (car type))))))
- (push (cons (cdr type)
- (if (memq (cdr type) uncompressed) list
- (gnus-compress-sequence
- (set symbol (sort list '<)) t)))
- newmarked)))
-
- ;; Enter these new marks into the info of the group.
- (if (nthcdr 3 info)
- (setcar (nthcdr 3 info) newmarked)
- ;; Add the marks lists to the end of the info.
- (when newmarked
- (setcdr (nthcdr 2 info) (list newmarked))))
-
- ;; Cut off the end of the info if there's nothing else there.
- (let ((i 5))
- (while (and (> i 2)
- (not (nth i info)))
- (when (nthcdr (decf i) info)
- (setcdr (nthcdr i info) nil)))))))
-
-(defun gnus-add-marked-articles (group type articles &optional info force)
- ;; Add ARTICLES of TYPE to the info of GROUP.
- ;; If INFO is non-nil, use that info. If FORCE is non-nil, don't
- ;; add, but replace marked articles of TYPE with ARTICLES.
- (let ((info (or info (gnus-get-info group)))
- (uncompressed '(score bookmark killed))
- marked m)
- (or (not info)
- (and (not (setq marked (nthcdr 3 info)))
- (or (null articles)
- (setcdr (nthcdr 2 info)
- (list (list (cons type (gnus-compress-sequence
- articles t)))))))
- (and (not (setq m (assq type (car marked))))
- (or (null articles)
- (setcar marked
- (cons (cons type (gnus-compress-sequence articles t) )
- (car marked)))))
- (if force
- (if (null articles)
- (setcar (nthcdr 3 info)
- (delq (assq type (car marked)) (car marked)))
- (setcdr m (gnus-compress-sequence articles t)))
- (setcdr m (gnus-compress-sequence
- (sort (nconc (gnus-uncompress-range (cdr m))
- (copy-sequence articles)) '<) t))))))
-
-(defun gnus-set-mode-line (where)
- "This function sets the mode line of the article or summary buffers.
-If WHERE is `summary', the summary mode line format will be used."
- ;; Is this mode line one we keep updated?
- (when (memq where gnus-updated-mode-lines)
- (let (mode-string)
- (save-excursion
- ;; We evaluate this in the summary buffer since these
- ;; variables are buffer-local to that buffer.
- (set-buffer gnus-summary-buffer)
- ;; We bind all these variables that are used in the `eval' form
- ;; below.
- (let* ((mformat (symbol-value
- (intern
- (format "gnus-%s-mode-line-format-spec" where))))
- (gnus-tmp-group-name gnus-newsgroup-name)
- (gnus-tmp-article-number (or gnus-current-article 0))
- (gnus-tmp-unread gnus-newsgroup-unreads)
- (gnus-tmp-unread-and-unticked (length gnus-newsgroup-unreads))
- (gnus-tmp-unselected (length gnus-newsgroup-unselected))
- (gnus-tmp-unread-and-unselected
- (cond ((and (zerop gnus-tmp-unread-and-unticked)
- (zerop gnus-tmp-unselected)) "")
- ((zerop gnus-tmp-unselected)
- (format "{%d more}" gnus-tmp-unread-and-unticked))
- (t (format "{%d(+%d) more}"
- gnus-tmp-unread-and-unticked
- gnus-tmp-unselected))))
- (gnus-tmp-subject
- (if (and gnus-current-headers
- (vectorp gnus-current-headers))
- (gnus-mode-string-quote
- (mail-header-subject gnus-current-headers)) ""))
- max-len
- gnus-tmp-header);; passed as argument to any user-format-funcs
- (setq mode-string (eval mformat))
- (setq max-len (max 4 (if gnus-mode-non-string-length
- (- (window-width)
- gnus-mode-non-string-length)
- (length mode-string))))
- ;; We might have to chop a bit of the string off...
- (when (> (length mode-string) max-len)
- (setq mode-string
- (concat (gnus-truncate-string mode-string (- max-len 3))
- "...")))
- ;; Pad the mode string a bit.
- (setq mode-string (format (format "%%-%ds" max-len) mode-string))))
- ;; Update the mode line.
- (setq mode-line-buffer-identification
- (gnus-mode-line-buffer-identification
- (list mode-string)))
- (set-buffer-modified-p t))))
-
-(defun gnus-create-xref-hashtb (from-newsgroup headers unreads)
- "Go through the HEADERS list and add all Xrefs to a hash table.
-The resulting hash table is returned, or nil if no Xrefs were found."
- (let* ((virtual (gnus-virtual-group-p from-newsgroup))
- (prefix (if virtual "" (gnus-group-real-prefix from-newsgroup)))
- (xref-hashtb (make-vector 63 0))
- start group entry number xrefs header)
- (while headers
- (setq header (pop headers))
- (when (and (setq xrefs (mail-header-xref header))
- (not (memq (setq number (mail-header-number header))
- unreads)))
- (setq start 0)
- (while (string-match "\\([^ ]+\\)[:/]\\([0-9]+\\)" xrefs start)
- (setq start (match-end 0))
- (setq group (if prefix
- (concat prefix (substring xrefs (match-beginning 1)
- (match-end 1)))
- (substring xrefs (match-beginning 1) (match-end 1))))
- (setq number
- (string-to-int (substring xrefs (match-beginning 2)
- (match-end 2))))
- (if (setq entry (gnus-gethash group xref-hashtb))
- (setcdr entry (cons number (cdr entry)))
- (gnus-sethash group (cons number nil) xref-hashtb)))))
- (and start xref-hashtb)))
-
-(defun gnus-mark-xrefs-as-read (from-newsgroup headers unreads)
- "Look through all the headers and mark the Xrefs as read."
- (let ((virtual (gnus-virtual-group-p from-newsgroup))
- name entry info xref-hashtb idlist method nth4)
- (save-excursion
- (set-buffer gnus-group-buffer)
- (when (setq xref-hashtb
- (gnus-create-xref-hashtb from-newsgroup headers unreads))
- (mapatoms
- (lambda (group)
- (unless (string= from-newsgroup (setq name (symbol-name group)))
- (setq idlist (symbol-value group))
- ;; Dead groups are not updated.
- (and (prog1
- (setq entry (gnus-gethash name gnus-newsrc-hashtb)
- info (nth 2 entry))
- (if (stringp (setq nth4 (gnus-info-method info)))
- (setq nth4 (gnus-server-to-method nth4))))
- ;; Only do the xrefs if the group has the same
- ;; select method as the group we have just read.
- (or (gnus-methods-equal-p
- nth4 (gnus-find-method-for-group from-newsgroup))
- virtual
- (equal nth4 (setq method (gnus-find-method-for-group
- from-newsgroup)))
- (and (equal (car nth4) (car method))
- (equal (nth 1 nth4) (nth 1 method))))
- gnus-use-cross-reference
- (or (not (eq gnus-use-cross-reference t))
- virtual
- ;; Only do cross-references on subscribed
- ;; groups, if that is what is wanted.
- (<= (gnus-info-level info) gnus-level-subscribed))
- (gnus-group-make-articles-read name idlist))))
- xref-hashtb)))))
-
-(defun gnus-group-make-articles-read (group articles)
- (let* ((num 0)
- (entry (gnus-gethash group gnus-newsrc-hashtb))
- (info (nth 2 entry))
- (active (gnus-active group))
- range)
- ;; First peel off all illegal article numbers.
- (if active
- (let ((ids articles)
- id first)
- (while ids
- (setq id (car ids))
- (if (and first (> id (cdr active)))
- (progn
- ;; We'll end up in this situation in one particular
- ;; obscure situation. If you re-scan a group and get
- ;; a new article that is cross-posted to a different
- ;; group that has not been re-scanned, you might get
- ;; crossposted article that has a higher number than
- ;; Gnus believes possible. So we re-activate this
- ;; group as well. This might mean doing the
- ;; crossposting thingy will *increase* the number
- ;; of articles in some groups. Tsk, tsk.
- (setq active (or (gnus-activate-group group) active))))
- (if (or (> id (cdr active))
- (< id (car active)))
- (setq articles (delq id articles)))
- (setq ids (cdr ids)))))
- ;; If the read list is nil, we init it.
- (and active
- (null (gnus-info-read info))
- (> (car active) 1)
- (gnus-info-set-read info (cons 1 (1- (car active)))))
- ;; Then we add the read articles to the range.
- (gnus-info-set-read
- info
- (setq range
- (gnus-add-to-range
- (gnus-info-read info) (setq articles (sort articles '<)))))
- ;; Then we have to re-compute how many unread
- ;; articles there are in this group.
- (if active
- (progn
- (cond
- ((not range)
- (setq num (- (1+ (cdr active)) (car active))))
- ((not (listp (cdr range)))
- (setq num (- (cdr active) (- (1+ (cdr range))
- (car range)))))
- (t
- (while range
- (if (numberp (car range))
- (setq num (1+ num))
- (setq num (+ num (- (1+ (cdar range)) (caar range)))))
- (setq range (cdr range)))
- (setq num (- (cdr active) num))))
- ;; Update the number of unread articles.
- (setcar entry num)
- ;; Update the group buffer.
- (gnus-group-update-group group t)))))
-
-(defun gnus-methods-equal-p (m1 m2)
- (let ((m1 (or m1 gnus-select-method))
- (m2 (or m2 gnus-select-method)))
- (or (equal m1 m2)
- (and (eq (car m1) (car m2))
- (or (not (memq 'address (assoc (symbol-name (car m1))
- gnus-valid-select-methods)))
- (equal (nth 1 m1) (nth 1 m2)))))))
-
-(defsubst gnus-header-value ()
- (buffer-substring (match-end 0) (gnus-point-at-eol)))
-
-(defvar gnus-newsgroup-none-id 0)
-
-(defun gnus-get-newsgroup-headers (&optional dependencies force-new)
- (let ((cur nntp-server-buffer)
- (dependencies
- (or dependencies
- (save-excursion (set-buffer gnus-summary-buffer)
- gnus-newsgroup-dependencies)))
- headers id id-dep ref-dep end ref)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (run-hooks 'gnus-parse-headers-hook)
- (let ((case-fold-search t)
- in-reply-to header p lines)
- (goto-char (point-min))
- ;; Search to the beginning of the next header. Error messages
- ;; do not begin with 2 or 3.
- (while (re-search-forward "^[23][0-9]+ " nil t)
- (setq id nil
- ref nil)
- ;; This implementation of this function, with nine
- ;; search-forwards instead of the one re-search-forward and
- ;; a case (which basically was the old function) is actually
- ;; about twice as fast, even though it looks messier. You
- ;; can't have everything, I guess. Speed and elegance
- ;; doesn't always go hand in hand.
- (setq
- header
- (vector
- ;; Number.
- (prog1
- (read cur)
- (end-of-line)
- (setq p (point))
- (narrow-to-region (point)
- (or (and (search-forward "\n.\n" nil t)
- (- (point) 2))
- (point))))
- ;; Subject.
- (progn
- (goto-char p)
- (if (search-forward "\nsubject: " nil t)
- (gnus-header-value) "(none)"))
- ;; From.
- (progn
- (goto-char p)
- (if (search-forward "\nfrom: " nil t)
- (gnus-header-value) "(nobody)"))
- ;; Date.
- (progn
- (goto-char p)
- (if (search-forward "\ndate: " nil t)
- (gnus-header-value) ""))
- ;; Message-ID.
- (progn
- (goto-char p)
- (if (search-forward "\nmessage-id: " nil t)
- (setq id (gnus-header-value))
- ;; If there was no message-id, we just fake one to make
- ;; subsequent routines simpler.
- (setq id (concat "none+"
- (int-to-string
- (setq gnus-newsgroup-none-id
- (1+ gnus-newsgroup-none-id)))))))
- ;; References.
- (progn
- (goto-char p)
- (if (search-forward "\nreferences: " nil t)
- (progn
- (setq end (point))
- (prog1
- (gnus-header-value)
- (setq ref
- (buffer-substring
- (progn
- (end-of-line)
- (search-backward ">" end t)
- (1+ (point)))
- (progn
- (search-backward "<" end t)
- (point))))))
- ;; Get the references from the in-reply-to header if there
- ;; were no references and the in-reply-to header looks
- ;; promising.
- (if (and (search-forward "\nin-reply-to: " nil t)
- (setq in-reply-to (gnus-header-value))
- (string-match "<[^>]+>" in-reply-to))
- (setq ref (substring in-reply-to (match-beginning 0)
- (match-end 0)))
- (setq ref ""))))
- ;; Chars.
- 0
- ;; Lines.
- (progn
- (goto-char p)
- (if (search-forward "\nlines: " nil t)
- (if (numberp (setq lines (read cur)))
- lines 0)
- 0))
- ;; Xref.
- (progn
- (goto-char p)
- (and (search-forward "\nxref: " nil t)
- (gnus-header-value)))))
- ;; We do the threading while we read the headers. The
- ;; message-id and the last reference are both entered into
- ;; the same hash table. Some tippy-toeing around has to be
- ;; done in case an article has arrived before the article
- ;; which it refers to.
- (if (boundp (setq id-dep (intern id dependencies)))
- (if (and (car (symbol-value id-dep))
- (not force-new))
- ;; An article with this Message-ID has already
- ;; been seen, so we ignore this one, except we add
- ;; any additional Xrefs (in case the two articles
- ;; came from different servers).
- (progn
- (mail-header-set-xref
- (car (symbol-value id-dep))
- (concat (or (mail-header-xref
- (car (symbol-value id-dep))) "")
- (or (mail-header-xref header) "")))
- (setq header nil))
- (setcar (symbol-value id-dep) header))
- (set id-dep (list header)))
- (when header
- (if (boundp (setq ref-dep (intern ref dependencies)))
- (setcdr (symbol-value ref-dep)
- (nconc (cdr (symbol-value ref-dep))
- (list (symbol-value id-dep))))
- (set ref-dep (list nil (symbol-value id-dep))))
- (setq headers (cons header headers)))
- (goto-char (point-max))
- (widen))
- (nreverse headers)))))
-
-;; The following macros and functions were written by Felix Lee
-;; <flee@cse.psu.edu>.
-
-(defmacro gnus-nov-read-integer ()
- '(prog1
- (if (= (following-char) ?\t)
- 0
- (let ((num (condition-case nil (read buffer) (error nil))))
- (if (numberp num) num 0)))
- (or (eobp) (forward-char 1))))
-
-(defmacro gnus-nov-skip-field ()
- '(search-forward "\t" eol 'move))
-
-(defmacro gnus-nov-field ()
- '(buffer-substring (point) (if (gnus-nov-skip-field) (1- (point)) eol)))
-
-;; Goes through the xover lines and returns a list of vectors
-(defun gnus-get-newsgroup-headers-xover (sequence &optional
- force-new dependencies)
- "Parse the news overview data in the server buffer, and return a
-list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
- ;; Get the Xref when the users reads the articles since most/some
- ;; NNTP servers do not include Xrefs when using XOVER.
- (setq gnus-article-internal-prepare-hook '(gnus-article-get-xrefs))
- (let ((cur nntp-server-buffer)
- (dependencies (or dependencies gnus-newsgroup-dependencies))
- number headers header)
- (save-excursion
- (set-buffer nntp-server-buffer)
- ;; Allow the user to mangle the headers before parsing them.
- (run-hooks 'gnus-parse-headers-hook)
- (goto-char (point-min))
- (while (and sequence (not (eobp)))
- (setq number (read cur))
- (while (and sequence (< (car sequence) number))
- (setq sequence (cdr sequence)))
- (and sequence
- (eq number (car sequence))
- (progn
- (setq sequence (cdr sequence))
- (if (setq header
- (inline (gnus-nov-parse-line
- number dependencies force-new)))
- (setq headers (cons header headers)))))
- (forward-line 1))
- (setq headers (nreverse headers)))
- headers))
-
-;; This function has to be called with point after the article number
-;; on the beginning of the line.
-(defun gnus-nov-parse-line (number dependencies &optional force-new)
- (let ((none 0)
- (eol (gnus-point-at-eol))
- (buffer (current-buffer))
- header ref id id-dep ref-dep)
-
- ;; overview: [num subject from date id refs chars lines misc]
- (narrow-to-region (point) eol)
- (or (eobp) (forward-char))
-
- (condition-case nil
- (setq header
- (vector
- number ; number
- (gnus-nov-field) ; subject
- (gnus-nov-field) ; from
- (gnus-nov-field) ; date
- (setq id (or (gnus-nov-field)
- (concat "none+"
- (int-to-string
- (setq none (1+ none)))))) ; id
- (progn
- (save-excursion
- (let ((beg (point)))
- (search-forward "\t" eol)
- (if (search-backward ">" beg t)
- (setq ref
- (buffer-substring
- (1+ (point))
- (search-backward "<" beg t)))
- (setq ref nil))))
- (gnus-nov-field)) ; refs
- (gnus-nov-read-integer) ; chars
- (gnus-nov-read-integer) ; lines
- (if (= (following-char) ?\n)
- nil
- (gnus-nov-field)) ; misc
- ))
- (error (progn
- (gnus-error 4 "Strange nov line")
- (setq header nil)
- (goto-char eol))))
-
- (widen)
-
- ;; We build the thread tree.
- (when header
- (if (boundp (setq id-dep (intern id dependencies)))
- (if (and (car (symbol-value id-dep))
- (not force-new))
- ;; An article with this Message-ID has already been seen,
- ;; so we ignore this one, except we add any additional
- ;; Xrefs (in case the two articles came from different
- ;; servers.
- (progn
- (mail-header-set-xref
- (car (symbol-value id-dep))
- (concat (or (mail-header-xref
- (car (symbol-value id-dep))) "")
- (or (mail-header-xref header) "")))
- (setq header nil))
- (setcar (symbol-value id-dep) header))
- (set id-dep (list header))))
- (when header
- (if (boundp (setq ref-dep (intern (or ref "none") dependencies)))
- (setcdr (symbol-value ref-dep)
- (nconc (cdr (symbol-value ref-dep))
- (list (symbol-value id-dep))))
- (set ref-dep (list nil (symbol-value id-dep)))))
- header))
-
-(defun gnus-article-get-xrefs ()
- "Fill in the Xref value in `gnus-current-headers', if necessary.
-This is meant to be called in `gnus-article-internal-prepare-hook'."
- (let ((headers (save-excursion (set-buffer gnus-summary-buffer)
- gnus-current-headers)))
- (or (not gnus-use-cross-reference)
- (not headers)
- (and (mail-header-xref headers)
- (not (string= (mail-header-xref headers) "")))
- (let ((case-fold-search t)
- xref)
- (save-restriction
- (nnheader-narrow-to-headers)
- (goto-char (point-min))
- (if (or (and (eq (downcase (following-char)) ?x)
- (looking-at "Xref:"))
- (search-forward "\nXref:" nil t))
- (progn
- (goto-char (1+ (match-end 0)))
- (setq xref (buffer-substring (point)
- (progn (end-of-line) (point))))
- (mail-header-set-xref headers xref))))))))
-
-(defun gnus-summary-insert-subject (id &optional old-header use-old-header)
- "Find article ID and insert the summary line for that article."
- (let ((header (if (and old-header use-old-header)
- old-header (gnus-read-header id)))
- (number (and (numberp id) id))
- pos)
- (when header
- ;; Rebuild the thread that this article is part of and go to the
- ;; article we have fetched.
- (when (and (not gnus-show-threads)
- old-header)
- (when (setq pos (text-property-any
- (point-min) (point-max) 'gnus-number
- (mail-header-number old-header)))
- (goto-char pos)
- (gnus-delete-line)
- (gnus-data-remove (mail-header-number old-header))))
- (when old-header
- (mail-header-set-number header (mail-header-number old-header)))
- (setq gnus-newsgroup-sparse
- (delq (setq number (mail-header-number header))
- gnus-newsgroup-sparse))
- (setq gnus-newsgroup-ancient (delq number gnus-newsgroup-ancient))
- (gnus-rebuild-thread (mail-header-id header))
- (gnus-summary-goto-subject number nil t))
- (when (and (numberp number)
- (> number 0))
- ;; We have to update the boundaries even if we can't fetch the
- ;; article if ID is a number -- so that the next `P' or `N'
- ;; command will fetch the previous (or next) article even
- ;; if the one we tried to fetch this time has been canceled.
- (and (> number gnus-newsgroup-end)
- (setq gnus-newsgroup-end number))
- (and (< number gnus-newsgroup-begin)
- (setq gnus-newsgroup-begin number))
- (setq gnus-newsgroup-unselected
- (delq number gnus-newsgroup-unselected)))
- ;; Report back a success?
- (and header (mail-header-number header))))
-
-(defun gnus-summary-work-articles (n)
- "Return a list of articles to be worked upon. The prefix argument,
-the list of process marked articles, and the current article will be
-taken into consideration."
- (cond
- (n
- ;; A numerical prefix has been given.
- (let ((backward (< n 0))
- (n (abs (prefix-numeric-value n)))
- articles article)
- (save-excursion
- (while
- (and (> n 0)
- (push (setq article (gnus-summary-article-number))
- articles)
- (if backward
- (gnus-summary-find-prev nil article)
- (gnus-summary-find-next nil article)))
- (decf n)))
- (nreverse articles)))
- ((and (boundp 'transient-mark-mode)
- transient-mark-mode
- mark-active)
- ;; Work on the region between point and mark.
- (let ((max (max (point) (mark)))
- articles article)
- (save-excursion
- (goto-char (min (point) (mark)))
- (while
- (and
- (push (setq article (gnus-summary-article-number)) articles)
- (gnus-summary-find-next nil article)
- (< (point) max)))
- (nreverse articles))))
- (gnus-newsgroup-processable
- ;; There are process-marked articles present.
- (reverse gnus-newsgroup-processable))
- (t
- ;; Just return the current article.
- (list (gnus-summary-article-number)))))
-
-(defun gnus-summary-search-group (&optional backward use-level)
- "Search for next unread newsgroup.
-If optional argument BACKWARD is non-nil, search backward instead."
- (save-excursion
- (set-buffer gnus-group-buffer)
- (if (gnus-group-search-forward
- backward nil (if use-level (gnus-group-group-level) nil))
- (gnus-group-group-name))))
-
-(defun gnus-summary-best-group (&optional exclude-group)
- "Find the name of the best unread group.
-If EXCLUDE-GROUP, do not go to this group."
- (save-excursion
- (set-buffer gnus-group-buffer)
- (save-excursion
- (gnus-group-best-unread-group exclude-group))))
-
-(defun gnus-summary-find-next (&optional unread article backward)
- (if backward (gnus-summary-find-prev)
- (let* ((dummy (gnus-summary-article-intangible-p))
- (article (or article (gnus-summary-article-number)))
- (arts (gnus-data-find-list article))
- result)
- (when (and (not dummy)
- (or (not gnus-summary-check-current)
- (not unread)
- (not (gnus-data-unread-p (car arts)))))
- (setq arts (cdr arts)))
- (when (setq result
- (if unread
- (progn
- (while arts
- (when (gnus-data-unread-p (car arts))
- (setq result (car arts)
- arts nil))
- (setq arts (cdr arts)))
- result)
- (car arts)))
- (goto-char (gnus-data-pos result))
- (gnus-data-number result)))))
-
-(defun gnus-summary-find-prev (&optional unread article)
- (let* ((eobp (eobp))
- (article (or article (gnus-summary-article-number)))
- (arts (gnus-data-find-list article (gnus-data-list 'rev)))
- result)
- (when (and (not eobp)
- (or (not gnus-summary-check-current)
- (not unread)
- (not (gnus-data-unread-p (car arts)))))
- (setq arts (cdr arts)))
- (if (setq result
- (if unread
- (progn
- (while arts
- (and (gnus-data-unread-p (car arts))
- (setq result (car arts)
- arts nil))
- (setq arts (cdr arts)))
- result)
- (car arts)))
- (progn
- (goto-char (gnus-data-pos result))
- (gnus-data-number result)))))
-
-(defun gnus-summary-find-subject (subject &optional unread backward article)
- (let* ((simp-subject (gnus-simplify-subject-fully subject))
- (article (or article (gnus-summary-article-number)))
- (articles (gnus-data-list backward))
- (arts (gnus-data-find-list article articles))
- result)
- (when (or (not gnus-summary-check-current)
- (not unread)
- (not (gnus-data-unread-p (car arts))))
- (setq arts (cdr arts)))
- (while arts
- (and (or (not unread)
- (gnus-data-unread-p (car arts)))
- (vectorp (gnus-data-header (car arts)))
- (gnus-subject-equal
- simp-subject (mail-header-subject (gnus-data-header (car arts))) t)
- (setq result (car arts)
- arts nil))
- (setq arts (cdr arts)))
- (and result
- (goto-char (gnus-data-pos result))
- (gnus-data-number result))))
-
-(defun gnus-summary-search-forward (&optional unread subject backward)
- "Search forward for an article.
-If UNREAD, look for unread articles. If SUBJECT, look for
-articles with that subject. If BACKWARD, search backward instead."
- (cond (subject (gnus-summary-find-subject subject unread backward))
- (backward (gnus-summary-find-prev unread))
- (t (gnus-summary-find-next unread))))
-
-(defun gnus-recenter (&optional n)
- "Center point in window and redisplay frame.
-Also do horizontal recentering."
- (interactive "P")
- (when (and gnus-auto-center-summary
- (not (eq gnus-auto-center-summary 'vertical)))
- (gnus-horizontal-recenter))
- (recenter n))
-
-(defun gnus-summary-recenter ()
- "Center point in the summary window.
-If `gnus-auto-center-summary' is nil, or the article buffer isn't
-displayed, no centering will be performed."
- ;; Suggested by earle@mahendo.JPL.NASA.GOV (Greg Earle).
- ;; Recenter only when requested. Suggested by popovich@park.cs.columbia.edu.
- (let* ((top (cond ((< (window-height) 4) 0)
- ((< (window-height) 7) 1)
- (t 2)))
- (height (1- (window-height)))
- (bottom (save-excursion (goto-char (point-max))
- (forward-line (- height))
- (point)))
- (window (get-buffer-window (current-buffer))))
- ;; The user has to want it.
- (when gnus-auto-center-summary
- (when (get-buffer-window gnus-article-buffer)
- ;; Only do recentering when the article buffer is displayed,
- ;; Set the window start to either `bottom', which is the biggest
- ;; possible valid number, or the second line from the top,
- ;; whichever is the least.
- (set-window-start
- window (min bottom (save-excursion
- (forward-line (- top)) (point)))))
- ;; Do horizontal recentering while we're at it.
- (when (and (get-buffer-window (current-buffer) t)
- (not (eq gnus-auto-center-summary 'vertical)))
- (let ((selected (selected-window)))
- (select-window (get-buffer-window (current-buffer) t))
- (gnus-summary-position-point)
- (gnus-horizontal-recenter)
- (select-window selected))))))
-
-(defun gnus-horizontal-recenter ()
- "Recenter the current buffer horizontally."
- (if (< (current-column) (/ (window-width) 2))
- (set-window-hscroll (get-buffer-window (current-buffer) t) 0)
- (let* ((orig (point))
- (end (window-end (get-buffer-window (current-buffer) t)))
- (max 0))
- ;; Find the longest line currently displayed in the window.
- (goto-char (window-start))
- (while (and (not (eobp))
- (< (point) end))
- (end-of-line)
- (setq max (max max (current-column)))
- (forward-line 1))
- (goto-char orig)
- ;; Scroll horizontally to center (sort of) the point.
- (if (> max (window-width))
- (set-window-hscroll
- (get-buffer-window (current-buffer) t)
- (min (- (current-column) (/ (window-width) 3))
- (+ 2 (- max (window-width)))))
- (set-window-hscroll (get-buffer-window (current-buffer) t) 0))
- max)))
-
-;; Function written by Stainless Steel Rat <ratinox@ccs.neu.edu>.
-(defun gnus-short-group-name (group &optional levels)
- "Collapse GROUP name LEVELS."
- (let* ((name "")
- (foreign "")
- (depth 0)
- (skip 1)
- (levels (or levels
- (progn
- (while (string-match "\\." group skip)
- (setq skip (match-end 0)
- depth (+ depth 1)))
- depth))))
- (if (string-match ":" group)
- (setq foreign (substring group 0 (match-end 0))
- group (substring group (match-end 0))))
- (while group
- (if (and (string-match "\\." group)
- (> levels (- gnus-group-uncollapsed-levels 1)))
- (setq name (concat name (substring group 0 1))
- group (substring group (match-end 0))
- levels (- levels 1)
- name (concat name "."))
- (setq name (concat foreign name group)
- group nil)))
- name))
-
-(defun gnus-summary-jump-to-group (newsgroup)
- "Move point to NEWSGROUP in group mode buffer."
- ;; Keep update point of group mode buffer if visible.
- (if (eq (current-buffer) (get-buffer gnus-group-buffer))
- (save-window-excursion
- ;; Take care of tree window mode.
- (if (get-buffer-window gnus-group-buffer)
- (pop-to-buffer gnus-group-buffer))
- (gnus-group-jump-to-group newsgroup))
- (save-excursion
- ;; Take care of tree window mode.
- (if (get-buffer-window gnus-group-buffer)
- (pop-to-buffer gnus-group-buffer)
- (set-buffer gnus-group-buffer))
- (gnus-group-jump-to-group newsgroup))))
-
-;; This function returns a list of article numbers based on the
-;; difference between the ranges of read articles in this group and
-;; the range of active articles.
-(defun gnus-list-of-unread-articles (group)
- (let* ((read (gnus-info-read (gnus-get-info group)))
- (active (gnus-active group))
- (last (cdr active))
- first nlast unread)
- ;; If none are read, then all are unread.
- (if (not read)
- (setq first (car active))
- ;; If the range of read articles is a single range, then the
- ;; first unread article is the article after the last read
- ;; article. Sounds logical, doesn't it?
- (if (not (listp (cdr read)))
- (setq first (1+ (cdr read)))
- ;; `read' is a list of ranges.
- (if (/= (setq nlast (or (and (numberp (car read)) (car read))
- (caar read))) 1)
- (setq first 1))
- (while read
- (if first
- (while (< first nlast)
- (setq unread (cons first unread))
- (setq first (1+ first))))
- (setq first (1+ (if (atom (car read)) (car read) (cdar read))))
- (setq nlast (if (atom (cadr read)) (cadr read) (caadr read)))
- (setq read (cdr read)))))
- ;; And add the last unread articles.
- (while (<= first last)
- (setq unread (cons first unread))
- (setq first (1+ first)))
- ;; Return the list of unread articles.
- (nreverse unread)))
-
-(defun gnus-list-of-read-articles (group)
- "Return a list of unread, unticked and non-dormant articles."
- (let* ((info (gnus-get-info group))
- (marked (gnus-info-marks info))
- (active (gnus-active group)))
- (and info active
- (gnus-set-difference
- (gnus-sorted-complement
- (gnus-uncompress-range active)
- (gnus-list-of-unread-articles group))
- (append
- (gnus-uncompress-range (cdr (assq 'dormant marked)))
- (gnus-uncompress-range (cdr (assq 'tick marked))))))))
-
-;; Various summary commands
-
-(defun gnus-summary-universal-argument (arg)
- "Perform any operation on all articles that are process/prefixed."
- (interactive "P")
- (gnus-set-global-variables)
- (let ((articles (gnus-summary-work-articles arg))
- func article)
- (if (eq
- (setq
- func
- (key-binding
- (read-key-sequence
- (substitute-command-keys
- "\\<gnus-summary-mode-map>\\[gnus-summary-universal-argument]"
- ))))
- 'undefined)
- (gnus-error 1 "Undefined key")
- (save-excursion
- (while articles
- (gnus-summary-goto-subject (setq article (pop articles)))
- (command-execute func)
- (gnus-summary-remove-process-mark article)))))
- (gnus-summary-position-point))
-
-(defun gnus-summary-toggle-truncation (&optional arg)
- "Toggle truncation of summary lines.
-With arg, turn line truncation on iff arg is positive."
- (interactive "P")
- (setq truncate-lines
- (if (null arg) (not truncate-lines)
- (> (prefix-numeric-value arg) 0)))
- (redraw-display))
-
-(defun gnus-summary-reselect-current-group (&optional all rescan)
- "Exit and then reselect the current newsgroup.
-The prefix argument ALL means to select all articles."
- (interactive "P")
- (gnus-set-global-variables)
- (when (gnus-ephemeral-group-p gnus-newsgroup-name)
- (error "Ephemeral groups can't be reselected"))
- (let ((current-subject (gnus-summary-article-number))
- (group gnus-newsgroup-name))
- (setq gnus-newsgroup-begin nil)
- (gnus-summary-exit)
- ;; We have to adjust the point of group mode buffer because the
- ;; current point was moved to the next unread newsgroup by
- ;; exiting.
- (gnus-summary-jump-to-group group)
- (when rescan
- (save-excursion
- (gnus-group-get-new-news-this-group 1)))
- (gnus-group-read-group all t)
- (gnus-summary-goto-subject current-subject nil t)))
-
-(defun gnus-summary-rescan-group (&optional all)
- "Exit the newsgroup, ask for new articles, and select the newsgroup."
- (interactive "P")
- (gnus-summary-reselect-current-group all t))
-
-(defun gnus-summary-update-info ()
- (let* ((group gnus-newsgroup-name))
- (when gnus-newsgroup-kill-headers
- (setq gnus-newsgroup-killed
- (gnus-compress-sequence
- (nconc
- (gnus-set-sorted-intersection
- (gnus-uncompress-range gnus-newsgroup-killed)
- (setq gnus-newsgroup-unselected
- (sort gnus-newsgroup-unselected '<)))
- (setq gnus-newsgroup-unreads
- (sort gnus-newsgroup-unreads '<))) t)))
- (unless (listp (cdr gnus-newsgroup-killed))
- (setq gnus-newsgroup-killed (list gnus-newsgroup-killed)))
- (let ((headers gnus-newsgroup-headers))
- (run-hooks 'gnus-exit-group-hook)
- (unless gnus-save-score
- (setq gnus-newsgroup-scored nil))
- ;; Set the new ranges of read articles.
- (gnus-update-read-articles
- group (append gnus-newsgroup-unreads gnus-newsgroup-unselected))
- ;; Set the current article marks.
- (gnus-update-marks)
- ;; Do the cross-ref thing.
- (when gnus-use-cross-reference
- (gnus-mark-xrefs-as-read group headers gnus-newsgroup-unreads))
- ;; Do adaptive scoring, and possibly save score files.
- (when gnus-newsgroup-adaptive
- (gnus-score-adaptive))
- (when gnus-use-scoring
- (gnus-score-save))
- ;; Do not switch windows but change the buffer to work.
- (set-buffer gnus-group-buffer)
- (or (gnus-ephemeral-group-p gnus-newsgroup-name)
- (gnus-group-update-group group)))))
-
-(defun gnus-summary-exit (&optional temporary)
- "Exit reading current newsgroup, and then return to group selection mode.
-gnus-exit-group-hook is called with no arguments if that value is non-nil."
- (interactive)
- (gnus-set-global-variables)
- (gnus-kill-save-kill-buffer)
- (let* ((group gnus-newsgroup-name)
- (quit-config (gnus-group-quit-config gnus-newsgroup-name))
- (mode major-mode)
- (buf (current-buffer)))
- (run-hooks 'gnus-summary-prepare-exit-hook)
- ;; If we have several article buffers, we kill them at exit.
- (unless gnus-single-article-buffer
- (gnus-kill-buffer gnus-original-article-buffer)
- (setq gnus-article-current nil))
- (when gnus-use-cache
- (gnus-cache-possibly-remove-articles)
- (gnus-cache-save-buffers))
- (when gnus-use-trees
- (gnus-tree-close group))
- ;; Make all changes in this group permanent.
- (unless quit-config
- (gnus-summary-update-info))
- (gnus-close-group group)
- ;; Make sure where I was, and go to next newsgroup.
- (set-buffer gnus-group-buffer)
- (unless quit-config
- (gnus-group-jump-to-group group))
- (run-hooks 'gnus-summary-exit-hook)
- (unless quit-config
- (gnus-group-next-unread-group 1))
- (if temporary
- nil ;Nothing to do.
- ;; If we have several article buffers, we kill them at exit.
- (unless gnus-single-article-buffer
- (gnus-kill-buffer gnus-article-buffer)
- (gnus-kill-buffer gnus-original-article-buffer)
- (setq gnus-article-current nil))
- (set-buffer buf)
- (if (not gnus-kill-summary-on-exit)
- (gnus-deaden-summary)
- ;; We set all buffer-local variables to nil. It is unclear why
- ;; this is needed, but if we don't, buffer-local variables are
- ;; not garbage-collected, it seems. This would the lead to en
- ;; ever-growing Emacs.
- (gnus-summary-clear-local-variables)
- (when (get-buffer gnus-article-buffer)
- (bury-buffer gnus-article-buffer))
- ;; We clear the global counterparts of the buffer-local
- ;; variables as well, just to be on the safe side.
- (gnus-configure-windows 'group 'force)
- (gnus-summary-clear-local-variables)
- ;; Return to group mode buffer.
- (if (eq mode 'gnus-summary-mode)
- (gnus-kill-buffer buf)))
- (setq gnus-current-select-method gnus-select-method)
- (pop-to-buffer gnus-group-buffer)
- ;; Clear the current group name.
- (if (not quit-config)
- (progn
- (gnus-group-jump-to-group group)
- (gnus-group-next-unread-group 1)
- (gnus-configure-windows 'group 'force))
- (if (not (buffer-name (car quit-config)))
- (gnus-configure-windows 'group 'force)
- (set-buffer (car quit-config))
- (and (eq major-mode 'gnus-summary-mode)
- (gnus-set-global-variables))
- (gnus-configure-windows (cdr quit-config))))
- (unless quit-config
- (setq gnus-newsgroup-name nil)))))
-
-(defalias 'gnus-summary-quit 'gnus-summary-exit-no-update)
-(defun gnus-summary-exit-no-update (&optional no-questions)
- "Quit reading current newsgroup without updating read article info."
- (interactive)
- (gnus-set-global-variables)
- (let* ((group gnus-newsgroup-name)
- (quit-config (gnus-group-quit-config group)))
- (when (or no-questions
- gnus-expert-user
- (gnus-y-or-n-p "Do you really wanna quit reading this group? "))
- ;; If we have several article buffers, we kill them at exit.
- (unless gnus-single-article-buffer
- (gnus-kill-buffer gnus-article-buffer)
- (gnus-kill-buffer gnus-original-article-buffer)
- (setq gnus-article-current nil))
- (if (not gnus-kill-summary-on-exit)
- (gnus-deaden-summary)
- (gnus-close-group group)
- (gnus-summary-clear-local-variables)
- (set-buffer gnus-group-buffer)
- (gnus-summary-clear-local-variables)
- (when (get-buffer gnus-summary-buffer)
- (kill-buffer gnus-summary-buffer)))
- (unless gnus-single-article-buffer
- (setq gnus-article-current nil))
- (when gnus-use-trees
- (gnus-tree-close group))
- (when (get-buffer gnus-article-buffer)
- (bury-buffer gnus-article-buffer))
- ;; Return to the group buffer.
- (gnus-configure-windows 'group 'force)
- ;; Clear the current group name.
- (setq gnus-newsgroup-name nil)
- (when (equal (gnus-group-group-name) group)
- (gnus-group-next-unread-group 1))
- (when quit-config
- (if (not (buffer-name (car quit-config)))
- (gnus-configure-windows 'group 'force)
- (set-buffer (car quit-config))
- (when (eq major-mode 'gnus-summary-mode)
- (gnus-set-global-variables))
- (gnus-configure-windows (cdr quit-config)))))))
-
-;;; Dead summaries.
-
-(defvar gnus-dead-summary-mode-map nil)
-
-(if gnus-dead-summary-mode-map
- nil
- (setq gnus-dead-summary-mode-map (make-keymap))
- (suppress-keymap gnus-dead-summary-mode-map)
- (substitute-key-definition
- 'undefined 'gnus-summary-wake-up-the-dead gnus-dead-summary-mode-map)
- (let ((keys '("\C-d" "\r" "\177")))
- (while keys
- (define-key gnus-dead-summary-mode-map
- (pop keys) 'gnus-summary-wake-up-the-dead))))
-
-(defvar gnus-dead-summary-mode nil
- "Minor mode for Gnus summary buffers.")
-
-(defun gnus-dead-summary-mode (&optional arg)
- "Minor mode for Gnus summary buffers."
- (interactive "P")
- (when (eq major-mode 'gnus-summary-mode)
- (make-local-variable 'gnus-dead-summary-mode)
- (setq gnus-dead-summary-mode
- (if (null arg) (not gnus-dead-summary-mode)
- (> (prefix-numeric-value arg) 0)))
- (when gnus-dead-summary-mode
- (unless (assq 'gnus-dead-summary-mode minor-mode-alist)
- (push '(gnus-dead-summary-mode " Dead") minor-mode-alist))
- (unless (assq 'gnus-dead-summary-mode minor-mode-map-alist)
- (push (cons 'gnus-dead-summary-mode gnus-dead-summary-mode-map)
- minor-mode-map-alist)))))
-
-(defun gnus-deaden-summary ()
- "Make the current summary buffer into a dead summary buffer."
- ;; Kill any previous dead summary buffer.
- (when (and gnus-dead-summary
- (buffer-name gnus-dead-summary))
- (save-excursion
- (set-buffer gnus-dead-summary)
- (when gnus-dead-summary-mode
- (kill-buffer (current-buffer)))))
- ;; Make this the current dead summary.
- (setq gnus-dead-summary (current-buffer))
- (gnus-dead-summary-mode 1)
- (let ((name (buffer-name)))
- (when (string-match "Summary" name)
- (rename-buffer
- (concat (substring name 0 (match-beginning 0)) "Dead "
- (substring name (match-beginning 0))) t))))
-
-(defun gnus-kill-or-deaden-summary (buffer)
- "Kill or deaden the summary BUFFER."
- (when (and (buffer-name buffer)
- (not gnus-single-article-buffer))
- (save-excursion
- (set-buffer buffer)
- (gnus-kill-buffer gnus-article-buffer)
- (gnus-kill-buffer gnus-original-article-buffer)))
- (cond (gnus-kill-summary-on-exit
- (when (and gnus-use-trees
- (and (get-buffer buffer)
- (buffer-name (get-buffer buffer))))
- (save-excursion
- (set-buffer (get-buffer buffer))
- (gnus-tree-close gnus-newsgroup-name)))
- (gnus-kill-buffer buffer))
- ((and (get-buffer buffer)
- (buffer-name (get-buffer buffer)))
- (save-excursion
- (set-buffer buffer)
- (gnus-deaden-summary)))))
-
-(defun gnus-summary-wake-up-the-dead (&rest args)
- "Wake up the dead summary buffer."
- (interactive)
- (gnus-dead-summary-mode -1)
- (let ((name (buffer-name)))
- (when (string-match "Dead " name)
- (rename-buffer
- (concat (substring name 0 (match-beginning 0))
- (substring name (match-end 0))) t)))
- (gnus-message 3 "This dead summary is now alive again"))
-
-;; Suggested by Andrew Eskilsson <pi92ae@pt.hk-r.se>.
-(defun gnus-summary-fetch-faq (&optional faq-dir)
- "Fetch the FAQ for the current group.
-If FAQ-DIR (the prefix), prompt for a directory to search for the faq
-in."
- (interactive
- (list
- (if current-prefix-arg
- (completing-read
- "Faq dir: " (and (listp gnus-group-faq-directory)
- gnus-group-faq-directory)))))
- (let (gnus-faq-buffer)
- (and (setq gnus-faq-buffer
- (gnus-group-fetch-faq gnus-newsgroup-name faq-dir))
- (gnus-configure-windows 'summary-faq))))
-
-;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
-(defun gnus-summary-describe-group (&optional force)
- "Describe the current newsgroup."
- (interactive "P")
- (gnus-group-describe-group force gnus-newsgroup-name))
-
-(defun gnus-summary-describe-briefly ()
- "Describe summary mode commands briefly."
- (interactive)
- (gnus-message 6
- (substitute-command-keys "\\<gnus-summary-mode-map>\\[gnus-summary-next-page]:Select \\[gnus-summary-next-unread-article]:Forward \\[gnus-summary-prev-unread-article]:Backward \\[gnus-summary-exit]:Exit \\[gnus-info-find-node]:Run Info \\[gnus-summary-describe-briefly]:This help")))
-
-;; Walking around group mode buffer from summary mode.
-
-(defun gnus-summary-next-group (&optional no-article target-group backward)
- "Exit current newsgroup and then select next unread newsgroup.
-If prefix argument NO-ARTICLE is non-nil, no article is selected
-initially. If NEXT-GROUP, go to this group. If BACKWARD, go to
-previous group instead."
- (interactive "P")
- (gnus-set-global-variables)
- (let ((current-group gnus-newsgroup-name)
- (current-buffer (current-buffer))
- entered)
- ;; First we semi-exit this group to update Xrefs and all variables.
- ;; We can't do a real exit, because the window conf must remain
- ;; the same in case the user is prompted for info, and we don't
- ;; want the window conf to change before that...
- (gnus-summary-exit t)
- (while (not entered)
- ;; Then we find what group we are supposed to enter.
- (set-buffer gnus-group-buffer)
- (gnus-group-jump-to-group current-group)
- (setq target-group
- (or target-group
- (if (eq gnus-keep-same-level 'best)
- (gnus-summary-best-group gnus-newsgroup-name)
- (gnus-summary-search-group backward gnus-keep-same-level))))
- (if (not target-group)
- ;; There are no further groups, so we return to the group
- ;; buffer.
- (progn
- (gnus-message 5 "Returning to the group buffer")
- (setq entered t)
- (set-buffer current-buffer)
- (gnus-summary-exit))
- ;; We try to enter the target group.
- (gnus-group-jump-to-group target-group)
- (let ((unreads (gnus-group-group-unread)))
- (if (and (or (eq t unreads)
- (and unreads (not (zerop unreads))))
- (gnus-summary-read-group
- target-group nil no-article current-buffer))
- (setq entered t)
- (setq current-group target-group
- target-group nil)))))))
-
-(defun gnus-summary-prev-group (&optional no-article)
- "Exit current newsgroup and then select previous unread newsgroup.
-If prefix argument NO-ARTICLE is non-nil, no article is selected initially."
- (interactive "P")
- (gnus-summary-next-group no-article nil t))
-
-;; Walking around summary lines.
-
-(defun gnus-summary-first-subject (&optional unread)
- "Go to the first unread subject.
-If UNREAD is non-nil, go to the first unread article.
-Returns the article selected or nil if there are no unread articles."
- (interactive "P")
- (prog1
- (cond
- ;; Empty summary.
- ((null gnus-newsgroup-data)
- (gnus-message 3 "No articles in the group")
- nil)
- ;; Pick the first article.
- ((not unread)
- (goto-char (gnus-data-pos (car gnus-newsgroup-data)))
- (gnus-data-number (car gnus-newsgroup-data)))
- ;; No unread articles.
- ((null gnus-newsgroup-unreads)
- (gnus-message 3 "No more unread articles")
- nil)
- ;; Find the first unread article.
- (t
- (let ((data gnus-newsgroup-data))
- (while (and data
- (not (gnus-data-unread-p (car data))))
- (setq data (cdr data)))
- (if data
- (progn
- (goto-char (gnus-data-pos (car data)))
- (gnus-data-number (car data)))))))
- (gnus-summary-position-point)))
-
-(defun gnus-summary-next-subject (n &optional unread dont-display)
- "Go to next N'th summary line.
-If N is negative, go to the previous N'th subject line.
-If UNREAD is non-nil, only unread articles are selected.
-The difference between N and the actual number of steps taken is
-returned."
- (interactive "p")
- (let ((backward (< n 0))
- (n (abs n)))
- (while (and (> n 0)
- (if backward
- (gnus-summary-find-prev unread)
- (gnus-summary-find-next unread)))
- (setq n (1- n)))
- (if (/= 0 n) (gnus-message 7 "No more%s articles"
- (if unread " unread" "")))
- (unless dont-display
- (gnus-summary-recenter)
- (gnus-summary-position-point))
- n))
-
-(defun gnus-summary-next-unread-subject (n)
- "Go to next N'th unread summary line."
- (interactive "p")
- (gnus-summary-next-subject n t))
-
-(defun gnus-summary-prev-subject (n &optional unread)
- "Go to previous N'th summary line.
-If optional argument UNREAD is non-nil, only unread article is selected."
- (interactive "p")
- (gnus-summary-next-subject (- n) unread))
-
-(defun gnus-summary-prev-unread-subject (n)
- "Go to previous N'th unread summary line."
- (interactive "p")
- (gnus-summary-next-subject (- n) t))
-
-(defun gnus-summary-goto-subject (article &optional force silent)
- "Go the subject line of ARTICLE.
-If FORCE, also allow jumping to articles not currently shown."
- (let ((b (point))
- (data (gnus-data-find article)))
- ;; We read in the article if we have to.
- (and (not data)
- force
- (gnus-summary-insert-subject article (and (vectorp force) force) t)
- (setq data (gnus-data-find article)))
- (goto-char b)
- (if (not data)
- (progn
- (unless silent
- (gnus-message 3 "Can't find article %d" article))
- nil)
- (goto-char (gnus-data-pos data))
- article)))
-
-;; Walking around summary lines with displaying articles.
-
-(defun gnus-summary-expand-window (&optional arg)
- "Make the summary buffer take up the entire Emacs frame.
-Given a prefix, will force an `article' buffer configuration."
- (interactive "P")
- (gnus-set-global-variables)
- (if arg
- (gnus-configure-windows 'article 'force)
- (gnus-configure-windows 'summary 'force)))
-
-(defun gnus-summary-display-article (article &optional all-header)
- "Display ARTICLE in article buffer."
- (gnus-set-global-variables)
- (if (null article)
- nil
- (prog1
- (if gnus-summary-display-article-function
- (funcall gnus-summary-display-article-function article all-header)
- (gnus-article-prepare article all-header))
- (run-hooks 'gnus-select-article-hook)
- (unless (zerop gnus-current-article)
- (gnus-summary-goto-subject gnus-current-article))
- (gnus-summary-recenter)
- (when gnus-use-trees
- (gnus-possibly-generate-tree article)
- (gnus-highlight-selected-tree article))
- ;; Successfully display article.
- (gnus-article-set-window-start
- (cdr (assq article gnus-newsgroup-bookmarks))))))
-
-(defun gnus-summary-select-article (&optional all-headers force pseudo article)
- "Select the current article.
-If ALL-HEADERS is non-nil, show all header fields. If FORCE is
-non-nil, the article will be re-fetched even if it already present in
-the article buffer. If PSEUDO is non-nil, pseudo-articles will also
-be displayed."
- ;; Make sure we are in the summary buffer to work around bbdb bug.
- (unless (eq major-mode 'gnus-summary-mode)
- (set-buffer gnus-summary-buffer))
- (let ((article (or article (gnus-summary-article-number)))
- (all-headers (not (not all-headers))) ;Must be T or NIL.
- gnus-summary-display-article-function
- did)
- (and (not pseudo)
- (gnus-summary-article-pseudo-p article)
- (error "This is a pseudo-article."))
- (prog1
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (if (or (and gnus-single-article-buffer
- (or (null gnus-current-article)
- (null gnus-article-current)
- (null (get-buffer gnus-article-buffer))
- (not (eq article (cdr gnus-article-current)))
- (not (equal (car gnus-article-current)
- gnus-newsgroup-name))))
- (and (not gnus-single-article-buffer)
- (or (null gnus-current-article)
- (not (eq gnus-current-article article))))
- force)
- ;; The requested article is different from the current article.
- (prog1
- (gnus-summary-display-article article all-headers)
- (setq did article))
- (if (or all-headers gnus-show-all-headers)
- (gnus-article-show-all-headers))
- 'old))
- (if did
- (gnus-article-set-window-start
- (cdr (assq article gnus-newsgroup-bookmarks)))))))
-
-(defun gnus-summary-set-current-mark (&optional current-mark)
- "Obsolete function."
- nil)
-
-(defun gnus-summary-next-article (&optional unread subject backward push)
- "Select the next article.
-If UNREAD, only unread articles are selected.
-If SUBJECT, only articles with SUBJECT are selected.
-If BACKWARD, the previous article is selected instead of the next."
- (interactive "P")
- (gnus-set-global-variables)
- (cond
- ;; Is there such an article?
- ((and (gnus-summary-search-forward unread subject backward)
- (or (gnus-summary-display-article (gnus-summary-article-number))
- (eq (gnus-summary-article-mark) gnus-canceled-mark)))
- (gnus-summary-position-point))
- ;; If not, we try the first unread, if that is wanted.
- ((and subject
- gnus-auto-select-same
- (gnus-summary-first-unread-article))
- (gnus-summary-position-point)
- (gnus-message 6 "Wrapped"))
- ;; Try to get next/previous article not displayed in this group.
- ((and gnus-auto-extend-newsgroup
- (not unread) (not subject))
- (gnus-summary-goto-article
- (if backward (1- gnus-newsgroup-begin) (1+ gnus-newsgroup-end))
- nil t))
- ;; Go to next/previous group.
- (t
- (or (gnus-ephemeral-group-p gnus-newsgroup-name)
- (gnus-summary-jump-to-group gnus-newsgroup-name))
- (let ((cmd last-command-char)
- (group
- (if (eq gnus-keep-same-level 'best)
- (gnus-summary-best-group gnus-newsgroup-name)
- (gnus-summary-search-group backward gnus-keep-same-level))))
- ;; For some reason, the group window gets selected. We change
- ;; it back.
- (select-window (get-buffer-window (current-buffer)))
- ;; Select next unread newsgroup automagically.
- (cond
- ((or (not gnus-auto-select-next)
- (not cmd))
- (gnus-message 7 "No more%s articles" (if unread " unread" "")))
- ((or (eq gnus-auto-select-next 'quietly)
- (and (eq gnus-auto-select-next 'slightly-quietly)
- push)
- (and (eq gnus-auto-select-next 'almost-quietly)
- (gnus-summary-last-article-p)))
- ;; Select quietly.
- (if (gnus-ephemeral-group-p gnus-newsgroup-name)
- (gnus-summary-exit)
- (gnus-message 7 "No more%s articles (%s)..."
- (if unread " unread" "")
- (if group (concat "selecting " group)
- "exiting"))
- (gnus-summary-next-group nil group backward)))
- (t
- (gnus-summary-walk-group-buffer
- gnus-newsgroup-name cmd unread backward)))))))
-
-(defun gnus-summary-walk-group-buffer (from-group cmd unread backward)
- (let ((keystrokes '((?\C-n (gnus-group-next-unread-group 1))
- (?\C-p (gnus-group-prev-unread-group 1))))
- keve key group ended)
- (save-excursion
- (set-buffer gnus-group-buffer)
- (gnus-summary-jump-to-group from-group)
- (setq group
- (if (eq gnus-keep-same-level 'best)
- (gnus-summary-best-group gnus-newsgroup-name)
- (gnus-summary-search-group backward gnus-keep-same-level))))
- (while (not ended)
- (gnus-message
- 5 "No more%s articles%s" (if unread " unread" "")
- (if (and group
- (not (gnus-ephemeral-group-p gnus-newsgroup-name)))
- (format " (Type %s for %s [%s])"
- (single-key-description cmd) group
- (car (gnus-gethash group gnus-newsrc-hashtb)))
- (format " (Type %s to exit %s)"
- (single-key-description cmd)
- gnus-newsgroup-name)))
- ;; Confirm auto selection.
- (setq key (car (setq keve (gnus-read-event-char))))
- (setq ended t)
- (cond
- ((assq key keystrokes)
- (let ((obuf (current-buffer)))
- (switch-to-buffer gnus-group-buffer)
- (and group
- (gnus-group-jump-to-group group))
- (eval (cadr (assq key keystrokes)))
- (setq group (gnus-group-group-name))
- (switch-to-buffer obuf))
- (setq ended nil))
- ((equal key cmd)
- (if (or (not group)
- (gnus-ephemeral-group-p gnus-newsgroup-name))
- (gnus-summary-exit)
- (gnus-summary-next-group nil group backward)))
- (t
- (push (cdr keve) unread-command-events))))))
-
-(defun gnus-read-event-char ()
- "Get the next event."
- (let ((event (read-event)))
- (cons (and (numberp event) event) event)))
-
-(defun gnus-summary-next-unread-article ()
- "Select unread article after current one."
- (interactive)
- (gnus-summary-next-article t (and gnus-auto-select-same
- (gnus-summary-article-subject))))
-
-(defun gnus-summary-prev-article (&optional unread subject)
- "Select the article after the current one.
-If UNREAD is non-nil, only unread articles are selected."
- (interactive "P")
- (gnus-summary-next-article unread subject t))
-
-(defun gnus-summary-prev-unread-article ()
- "Select unred article before current one."
- (interactive)
- (gnus-summary-prev-article t (and gnus-auto-select-same
- (gnus-summary-article-subject))))
-
-(defun gnus-summary-next-page (&optional lines circular)
- "Show next page of the selected article.
-If at the end of the current article, select the next article.
-LINES says how many lines should be scrolled up.
-
-If CIRCULAR is non-nil, go to the start of the article instead of
-selecting the next article when reaching the end of the current
-article."
- (interactive "P")
- (setq gnus-summary-buffer (current-buffer))
- (gnus-set-global-variables)
- (let ((article (gnus-summary-article-number))
- (endp nil))
- (gnus-configure-windows 'article)
- (if (eq (cdr (assq article gnus-newsgroup-reads)) gnus-canceled-mark)
- (if (and (eq gnus-summary-goto-unread 'never)
- (not (gnus-summary-last-article-p article)))
- (gnus-summary-next-article)
- (gnus-summary-next-unread-article))
- (if (or (null gnus-current-article)
- (null gnus-article-current)
- (/= article (cdr gnus-article-current))
- (not (equal (car gnus-article-current) gnus-newsgroup-name)))
- ;; Selected subject is different from current article's.
- (gnus-summary-display-article article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (setq endp (gnus-article-next-page lines)))
- (if endp
- (cond (circular
- (gnus-summary-beginning-of-article))
- (lines
- (gnus-message 3 "End of message"))
- ((null lines)
- (if (and (eq gnus-summary-goto-unread 'never)
- (not (gnus-summary-last-article-p article)))
- (gnus-summary-next-article)
- (gnus-summary-next-unread-article)))))))
- (gnus-summary-recenter)
- (gnus-summary-position-point)))
-
-(defun gnus-summary-prev-page (&optional lines)
- "Show previous page of selected article.
-Argument LINES specifies lines to be scrolled down."
- (interactive "P")
- (gnus-set-global-variables)
- (let ((article (gnus-summary-article-number)))
- (gnus-configure-windows 'article)
- (if (or (null gnus-current-article)
- (null gnus-article-current)
- (/= article (cdr gnus-article-current))
- (not (equal (car gnus-article-current) gnus-newsgroup-name)))
- ;; Selected subject is different from current article's.
- (gnus-summary-display-article article)
- (gnus-summary-recenter)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (gnus-article-prev-page lines))))
- (gnus-summary-position-point))
-
-(defun gnus-summary-scroll-up (lines)
- "Scroll up (or down) one line current article.
-Argument LINES specifies lines to be scrolled up (or down if negative)."
- (interactive "p")
- (gnus-set-global-variables)
- (gnus-configure-windows 'article)
- (gnus-summary-show-thread)
- (when (eq (gnus-summary-select-article nil nil 'pseudo) 'old)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (cond ((> lines 0)
- (if (gnus-article-next-page lines)
- (gnus-message 3 "End of message")))
- ((< lines 0)
- (gnus-article-prev-page (- lines))))))
- (gnus-summary-recenter)
- (gnus-summary-position-point))
-
-(defun gnus-summary-next-same-subject ()
- "Select next article which has the same subject as current one."
- (interactive)
- (gnus-set-global-variables)
- (gnus-summary-next-article nil (gnus-summary-article-subject)))
-
-(defun gnus-summary-prev-same-subject ()
- "Select previous article which has the same subject as current one."
- (interactive)
- (gnus-set-global-variables)
- (gnus-summary-prev-article nil (gnus-summary-article-subject)))
-
-(defun gnus-summary-next-unread-same-subject ()
- "Select next unread article which has the same subject as current one."
- (interactive)
- (gnus-set-global-variables)
- (gnus-summary-next-article t (gnus-summary-article-subject)))
-
-(defun gnus-summary-prev-unread-same-subject ()
- "Select previous unread article which has the same subject as current one."
- (interactive)
- (gnus-set-global-variables)
- (gnus-summary-prev-article t (gnus-summary-article-subject)))
-
-(defun gnus-summary-first-unread-article ()
- "Select the first unread article.
-Return nil if there are no unread articles."
- (interactive)
- (gnus-set-global-variables)
- (prog1
- (if (gnus-summary-first-subject t)
- (progn
- (gnus-summary-show-thread)
- (gnus-summary-first-subject t)
- (gnus-summary-display-article (gnus-summary-article-number))))
- (gnus-summary-position-point)))
-
-(defun gnus-summary-best-unread-article ()
- "Select the unread article with the highest score."
- (interactive)
- (gnus-set-global-variables)
- (let ((best -1000000)
- (data gnus-newsgroup-data)
- article score)
- (while data
- (and (gnus-data-unread-p (car data))
- (> (setq score
- (gnus-summary-article-score (gnus-data-number (car data))))
- best)
- (setq best score
- article (gnus-data-number (car data))))
- (setq data (cdr data)))
- (prog1
- (if article
- (gnus-summary-goto-article article)
- (error "No unread articles"))
- (gnus-summary-position-point))))
-
-(defun gnus-summary-last-subject ()
- "Go to the last displayed subject line in the group."
- (let ((article (gnus-data-number (car (gnus-data-list t)))))
- (when article
- (gnus-summary-goto-subject article))))
-
-(defun gnus-summary-goto-article (article &optional all-headers force)
- "Fetch ARTICLE and display it if it exists.
-If ALL-HEADERS is non-nil, no header lines are hidden."
- (interactive
- (list
- (string-to-int
- (completing-read
- "Article number: "
- (mapcar (lambda (number) (list (int-to-string number)))
- gnus-newsgroup-limit)))
- current-prefix-arg
- t))
- (prog1
- (if (gnus-summary-goto-subject article force)
- (gnus-summary-display-article article all-headers)
- (gnus-message 4 "Couldn't go to article %s" article) nil)
- (gnus-summary-position-point)))
-
-(defun gnus-summary-goto-last-article ()
- "Go to the previously read article."
- (interactive)
- (prog1
- (and gnus-last-article
- (gnus-summary-goto-article gnus-last-article))
- (gnus-summary-position-point)))
-
-(defun gnus-summary-pop-article (number)
- "Pop one article off the history and go to the previous.
-NUMBER articles will be popped off."
- (interactive "p")
- (let (to)
- (setq gnus-newsgroup-history
- (cdr (setq to (nthcdr number gnus-newsgroup-history))))
- (if to
- (gnus-summary-goto-article (car to))
- (error "Article history empty")))
- (gnus-summary-position-point))
-
-;; Summary commands and functions for limiting the summary buffer.
-
-(defun gnus-summary-limit-to-articles (n)
- "Limit the summary buffer to the next N articles.
-If not given a prefix, use the process marked articles instead."
- (interactive "P")
- (gnus-set-global-variables)
- (prog1
- (let ((articles (gnus-summary-work-articles n)))
- (setq gnus-newsgroup-processable nil)
- (gnus-summary-limit articles))
- (gnus-summary-position-point)))
-
-(defun gnus-summary-pop-limit (&optional total)
- "Restore the previous limit.
-If given a prefix, remove all limits."
- (interactive "P")
- (gnus-set-global-variables)
- (when total
- (setq gnus-newsgroup-limits
- (list (mapcar (lambda (h) (mail-header-number h))
- gnus-newsgroup-headers))))
- (unless gnus-newsgroup-limits
- (error "No limit to pop"))
- (prog1
- (gnus-summary-limit nil 'pop)
- (gnus-summary-position-point)))
-
-(defun gnus-summary-limit-to-subject (subject &optional header)
- "Limit the summary buffer to articles that have subjects that match a regexp."
- (interactive "sRegexp: ")
- (unless header
- (setq header "subject"))
- (when (not (equal "" subject))
- (prog1
- (let ((articles (gnus-summary-find-matching
- (or header "subject") subject 'all)))
- (or articles (error "Found no matches for \"%s\"" subject))
- (gnus-summary-limit articles))
- (gnus-summary-position-point))))
-
-(defun gnus-summary-limit-to-author (from)
- "Limit the summary buffer to articles that have authors that match a regexp."
- (interactive "sRegexp: ")
- (gnus-summary-limit-to-subject from "from"))
-
-(defalias 'gnus-summary-delete-marked-as-read 'gnus-summary-limit-to-unread)
-(make-obsolete
- 'gnus-summary-delete-marked-as-read 'gnus-summary-limit-to-unread)
-
-(defun gnus-summary-limit-to-unread (&optional all)
- "Limit the summary buffer to articles that are not marked as read.
-If ALL is non-nil, limit strictly to unread articles."
- (interactive "P")
- (if all
- (gnus-summary-limit-to-marks (char-to-string gnus-unread-mark))
- (gnus-summary-limit-to-marks
- ;; Concat all the marks that say that an article is read and have
- ;; those removed.
- (list gnus-del-mark gnus-read-mark gnus-ancient-mark
- gnus-killed-mark gnus-kill-file-mark
- gnus-low-score-mark gnus-expirable-mark
- gnus-canceled-mark gnus-catchup-mark gnus-sparse-mark)
- 'reverse)))
-
-(defalias 'gnus-summary-delete-marked-with 'gnus-summary-limit-to-marks)
-(make-obsolete 'gnus-summary-delete-marked-with 'gnus-summary-limit-to-marks)
-
-(defun gnus-summary-limit-to-marks (marks &optional reverse)
- "Limit the summary buffer to articles that are marked with MARKS (e.g. \"DK\").
-If REVERSE, limit the summary buffer to articles that are not marked
-with MARKS. MARKS can either be a string of marks or a list of marks.
-Returns how many articles were removed."
- (interactive "sMarks: ")
- (gnus-set-global-variables)
- (prog1
- (let ((data gnus-newsgroup-data)
- (marks (if (listp marks) marks
- (append marks nil))) ; Transform to list.
- articles)
- (while data
- (and (if reverse (not (memq (gnus-data-mark (car data)) marks))
- (memq (gnus-data-mark (car data)) marks))
- (setq articles (cons (gnus-data-number (car data)) articles)))
- (setq data (cdr data)))
- (gnus-summary-limit articles))
- (gnus-summary-position-point)))
-
-(defun gnus-summary-limit-to-score (&optional score)
- "Limit to articles with score at or above SCORE."
- (interactive "P")
- (gnus-set-global-variables)
- (setq score (if score
- (prefix-numeric-value score)
- (or gnus-summary-default-score 0)))
- (let ((data gnus-newsgroup-data)
- articles)
- (while data
- (when (>= (gnus-summary-article-score (gnus-data-number (car data)))
- score)
- (push (gnus-data-number (car data)) articles))
- (setq data (cdr data)))
- (prog1
- (gnus-summary-limit articles)
- (gnus-summary-position-point))))
-
-(defun gnus-summary-limit-include-dormant ()
- "Display all the hidden articles that are marked as dormant."
- (interactive)
- (gnus-set-global-variables)
- (or gnus-newsgroup-dormant
- (error "There are no dormant articles in this group"))
- (prog1
- (gnus-summary-limit (append gnus-newsgroup-dormant gnus-newsgroup-limit))
- (gnus-summary-position-point)))
-
-(defun gnus-summary-limit-exclude-dormant ()
- "Hide all dormant articles."
- (interactive)
- (gnus-set-global-variables)
- (prog1
- (gnus-summary-limit-to-marks (list gnus-dormant-mark) 'reverse)
- (gnus-summary-position-point)))
-
-(defun gnus-summary-limit-exclude-childless-dormant ()
- "Hide all dormant articles that have no children."
- (interactive)
- (gnus-set-global-variables)
- (let ((data (gnus-data-list t))
- articles d children)
- ;; Find all articles that are either not dormant or have
- ;; children.
- (while (setq d (pop data))
- (when (or (not (= (gnus-data-mark d) gnus-dormant-mark))
- (and (setq children
- (gnus-article-children (gnus-data-number d)))
- (let (found)
- (while children
- (when (memq (car children) articles)
- (setq children nil
- found t))
- (pop children))
- found)))
- (push (gnus-data-number d) articles)))
- ;; Do the limiting.
- (prog1
- (gnus-summary-limit articles)
- (gnus-summary-position-point))))
-
-(defun gnus-summary-limit-mark-excluded-as-read (&optional all)
- "Mark all unread excluded articles as read.
-If ALL, mark even excluded ticked and dormants as read."
- (interactive "P")
- (let ((articles (gnus-sorted-complement
- (sort
- (mapcar (lambda (h) (mail-header-number h))
- gnus-newsgroup-headers)
- '<)
- (sort gnus-newsgroup-limit '<)))
- article)
- (setq gnus-newsgroup-unreads nil)
- (if all
- (setq gnus-newsgroup-dormant nil
- gnus-newsgroup-marked nil
- gnus-newsgroup-reads
- (nconc
- (mapcar (lambda (n) (cons n gnus-catchup-mark)) articles)
- gnus-newsgroup-reads))
- (while (setq article (pop articles))
- (unless (or (memq article gnus-newsgroup-dormant)
- (memq article gnus-newsgroup-marked))
- (push (cons article gnus-catchup-mark) gnus-newsgroup-reads))))))
-
-(defun gnus-summary-limit (articles &optional pop)
- (if pop
- ;; We pop the previous limit off the stack and use that.
- (setq articles (car gnus-newsgroup-limits)
- gnus-newsgroup-limits (cdr gnus-newsgroup-limits))
- ;; We use the new limit, so we push the old limit on the stack.
- (setq gnus-newsgroup-limits
- (cons gnus-newsgroup-limit gnus-newsgroup-limits)))
- ;; Set the limit.
- (setq gnus-newsgroup-limit articles)
- (let ((total (length gnus-newsgroup-data))
- (data (gnus-data-find-list (gnus-summary-article-number)))
- (gnus-summary-mark-below nil) ; Inhibit this.
- found)
- ;; This will do all the work of generating the new summary buffer
- ;; according to the new limit.
- (gnus-summary-prepare)
- ;; Hide any threads, possibly.
- (and gnus-show-threads
- gnus-thread-hide-subtree
- (gnus-summary-hide-all-threads))
- ;; Try to return to the article you were at, or one in the
- ;; neighborhood.
- (if data
- ;; We try to find some article after the current one.
- (while data
- (and (gnus-summary-goto-subject
- (gnus-data-number (car data)) nil t)
- (setq data nil
- found t))
- (setq data (cdr data))))
- (or found
- ;; If there is no data, that means that we were after the last
- ;; article. The same goes when we can't find any articles
- ;; after the current one.
- (progn
- (goto-char (point-max))
- (gnus-summary-find-prev)))
- ;; We return how many articles were removed from the summary
- ;; buffer as a result of the new limit.
- (- total (length gnus-newsgroup-data))))
-
-(defsubst gnus-invisible-cut-children (threads)
- (let ((num 0))
- (while threads
- (when (memq (mail-header-number (caar threads)) gnus-newsgroup-limit)
- (incf num))
- (pop threads))
- (< num 2)))
-
-(defsubst gnus-cut-thread (thread)
- "Go forwards in the thread until we find an article that we want to display."
- (when (or (eq gnus-fetch-old-headers 'some)
- (eq gnus-build-sparse-threads 'some)
- (eq gnus-build-sparse-threads 'more))
- ;; Deal with old-fetched headers and sparse threads.
- (while (and
- thread
- (or
- (memq (mail-header-number (car thread)) gnus-newsgroup-sparse)
- (memq (mail-header-number (car thread)) gnus-newsgroup-ancient))
- (or (<= (length (cdr thread)) 1)
- (gnus-invisible-cut-children (cdr thread))))
- (setq thread (cadr thread))))
- thread)
-
-(defun gnus-cut-threads (threads)
- "Cut off all uninteresting articles from the beginning of threads."
- (when (or (eq gnus-fetch-old-headers 'some)
- (eq gnus-build-sparse-threads 'some)
- (eq gnus-build-sparse-threads 'more))
- (let ((th threads))
- (while th
- (setcar th (gnus-cut-thread (car th)))
- (setq th (cdr th)))))
- ;; Remove nixed out threads.
- (delq nil threads))
-
-(defun gnus-summary-initial-limit (&optional show-if-empty)
- "Figure out what the initial limit is supposed to be on group entry.
-This entails weeding out unwanted dormants, low-scored articles,
-fetch-old-headers verbiage, and so on."
- ;; Most groups have nothing to remove.
- (if (or gnus-inhibit-limiting
- (and (null gnus-newsgroup-dormant)
- (not (eq gnus-fetch-old-headers 'some))
- (null gnus-summary-expunge-below)
- (not (eq gnus-build-sparse-threads 'some))
- (not (eq gnus-build-sparse-threads 'more))
- (null gnus-thread-expunge-below)
- (not gnus-use-nocem)))
- () ; Do nothing.
- (push gnus-newsgroup-limit gnus-newsgroup-limits)
- (setq gnus-newsgroup-limit nil)
- (mapatoms
- (lambda (node)
- (unless (car (symbol-value node))
- ;; These threads have no parents -- they are roots.
- (let ((nodes (cdr (symbol-value node)))
- thread)
- (while nodes
- (if (and gnus-thread-expunge-below
- (< (gnus-thread-total-score (car nodes))
- gnus-thread-expunge-below))
- (gnus-expunge-thread (pop nodes))
- (setq thread (pop nodes))
- (gnus-summary-limit-children thread))))))
- gnus-newsgroup-dependencies)
- ;; If this limitation resulted in an empty group, we might
- ;; pop the previous limit and use it instead.
- (when (and (not gnus-newsgroup-limit)
- show-if-empty)
- (setq gnus-newsgroup-limit (pop gnus-newsgroup-limits)))
- gnus-newsgroup-limit))
-
-(defun gnus-summary-limit-children (thread)
- "Return 1 if this subthread is visible and 0 if it is not."
- ;; First we get the number of visible children to this thread. This
- ;; is done by recursing down the thread using this function, so this
- ;; will really go down to a leaf article first, before slowly
- ;; working its way up towards the root.
- (when thread
- (let ((children
- (if (cdr thread)
- (apply '+ (mapcar 'gnus-summary-limit-children
- (cdr thread)))
- 0))
- (number (mail-header-number (car thread)))
- score)
- (if (or
- ;; If this article is dormant and has absolutely no visible
- ;; children, then this article isn't visible.
- (and (memq number gnus-newsgroup-dormant)
- (= children 0))
- ;; If this is "fetch-old-headered" and there is only one
- ;; visible child (or less), then we don't want this article.
- (and (eq gnus-fetch-old-headers 'some)
- (memq number gnus-newsgroup-ancient)
- (zerop children))
- ;; If this is a sparsely inserted article with no children,
- ;; we don't want it.
- (and (eq gnus-build-sparse-threads 'some)
- (memq number gnus-newsgroup-sparse)
- (zerop children))
- ;; If we use expunging, and this article is really
- ;; low-scored, then we don't want this article.
- (when (and gnus-summary-expunge-below
- (< (setq score
- (or (cdr (assq number gnus-newsgroup-scored))
- gnus-summary-default-score))
- gnus-summary-expunge-below))
- ;; We increase the expunge-tally here, but that has
- ;; nothing to do with the limits, really.
- (incf gnus-newsgroup-expunged-tally)
- ;; We also mark as read here, if that's wanted.
- (when (and gnus-summary-mark-below
- (< score gnus-summary-mark-below))
- (setq gnus-newsgroup-unreads
- (delq number gnus-newsgroup-unreads))
- (if gnus-newsgroup-auto-expire
- (push number gnus-newsgroup-expirable)
- (push (cons number gnus-low-score-mark)
- gnus-newsgroup-reads)))
- t)
- (and gnus-use-nocem
- (gnus-nocem-unwanted-article-p (mail-header-id (car thread)))))
- ;; Nope, invisible article.
- 0
- ;; Ok, this article is to be visible, so we add it to the limit
- ;; and return 1.
- (setq gnus-newsgroup-limit (cons number gnus-newsgroup-limit))
- 1))))
-
-(defun gnus-expunge-thread (thread)
- "Mark all articles in THREAD as read."
- (let* ((number (mail-header-number (car thread))))
- (incf gnus-newsgroup-expunged-tally)
- ;; We also mark as read here, if that's wanted.
- (setq gnus-newsgroup-unreads
- (delq number gnus-newsgroup-unreads))
- (if gnus-newsgroup-auto-expire
- (push number gnus-newsgroup-expirable)
- (push (cons number gnus-low-score-mark)
- gnus-newsgroup-reads)))
- ;; Go recursively through all subthreads.
- (mapcar 'gnus-expunge-thread (cdr thread)))
-
-;; Summary article oriented commands
-
-(defun gnus-summary-refer-parent-article (n)
- "Refer parent article N times.
-The difference between N and the number of articles fetched is returned."
- (interactive "p")
- (gnus-set-global-variables)
- (while
- (and
- (> n 0)
- (let* ((header (gnus-summary-article-header))
- (ref
- ;; If we try to find the parent of the currently
- ;; displayed article, then we take a look at the actual
- ;; References header, since this is slightly more
- ;; reliable than the References field we got from the
- ;; server.
- (if (and (eq (mail-header-number header)
- (cdr gnus-article-current))
- (equal gnus-newsgroup-name
- (car gnus-article-current)))
- (save-excursion
- (set-buffer gnus-original-article-buffer)
- (nnheader-narrow-to-headers)
- (prog1
- (message-fetch-field "references")
- (widen)))
- ;; It's not the current article, so we take a bet on
- ;; the value we got from the server.
- (mail-header-references header))))
- (if (setq ref (or ref (mail-header-references header)))
- (or (gnus-summary-refer-article (gnus-parent-id ref))
- (gnus-message 1 "Couldn't find parent"))
- (gnus-message 1 "No references in article %d"
- (gnus-summary-article-number))
- nil)))
- (setq n (1- n)))
- (gnus-summary-position-point)
- n)
-
-(defun gnus-summary-refer-references ()
- "Fetch all articles mentioned in the References header.
-Return how many articles were fetched."
- (interactive)
- (gnus-set-global-variables)
- (let ((ref (mail-header-references (gnus-summary-article-header)))
- (current (gnus-summary-article-number))
- (n 0))
- ;; For each Message-ID in the References header...
- (while (string-match "<[^>]*>" ref)
- (incf n)
- ;; ... fetch that article.
- (gnus-summary-refer-article
- (prog1 (match-string 0 ref)
- (setq ref (substring ref (match-end 0))))))
- (gnus-summary-goto-subject current)
- (gnus-summary-position-point)
- n))
-
-(defun gnus-summary-refer-article (message-id)
- "Fetch an article specified by MESSAGE-ID."
- (interactive "sMessage-ID: ")
- (when (and (stringp message-id)
- (not (zerop (length message-id))))
- ;; Construct the correct Message-ID if necessary.
- ;; Suggested by tale@pawl.rpi.edu.
- (unless (string-match "^<" message-id)
- (setq message-id (concat "<" message-id)))
- (unless (string-match ">$" message-id)
- (setq message-id (concat message-id ">")))
- (let* ((header (gnus-id-to-header message-id))
- (sparse (and header
- (memq (mail-header-number header)
- gnus-newsgroup-sparse))))
- (if header
- (prog1
- ;; The article is present in the buffer, to we just go to it.
- (gnus-summary-goto-article
- (mail-header-number header) nil header)
- (when sparse
- (gnus-summary-update-article (mail-header-number header))))
- ;; We fetch the article
- (let ((gnus-override-method
- (and (gnus-news-group-p gnus-newsgroup-name)
- gnus-refer-article-method))
- number)
- ;; Start the special refer-article method, if necessary.
- (when (and gnus-refer-article-method
- (gnus-news-group-p gnus-newsgroup-name))
- (gnus-check-server gnus-refer-article-method))
- ;; Fetch the header, and display the article.
- (if (setq number (gnus-summary-insert-subject message-id))
- (gnus-summary-select-article nil nil nil number)
- (gnus-message 3 "Couldn't fetch article %s" message-id)))))))
-
-(defun gnus-summary-enter-digest-group (&optional force)
- "Enter a digest group based on the current article."
- (interactive "P")
- (gnus-set-global-variables)
- (gnus-summary-select-article)
- (let ((name (format "%s-%d"
- (gnus-group-prefixed-name
- gnus-newsgroup-name (list 'nndoc ""))
- gnus-current-article))
- (ogroup gnus-newsgroup-name)
- (case-fold-search t)
- (buf (current-buffer))
- dig)
- (save-excursion
- (setq dig (nnheader-set-temp-buffer " *gnus digest buffer*"))
- (insert-buffer-substring gnus-original-article-buffer)
- (narrow-to-region
- (goto-char (point-min))
- (or (search-forward "\n\n" nil t) (point)))
- (goto-char (point-min))
- (delete-matching-lines "^\\(Path\\):\\|^From ")
- (widen))
- (unwind-protect
- (if (gnus-group-read-ephemeral-group
- name `(nndoc ,name (nndoc-address
- ,(get-buffer dig))
- (nndoc-article-type ,(if force 'digest 'guess))) t)
- ;; Make all postings to this group go to the parent group.
- (nconc (gnus-info-params (gnus-get-info name))
- (list (cons 'to-group ogroup)))
- ;; Couldn't select this doc group.
- (switch-to-buffer buf)
- (gnus-set-global-variables)
- (gnus-configure-windows 'summary)
- (gnus-message 3 "Article couldn't be entered?"))
- (kill-buffer dig))))
-
-(defun gnus-summary-isearch-article (&optional regexp-p)
- "Do incremental search forward on the current article.
-If REGEXP-P (the prefix) is non-nil, do regexp isearch."
- (interactive "P")
- (gnus-set-global-variables)
- (gnus-summary-select-article)
- (gnus-configure-windows 'article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (goto-char (point-min))
- (isearch-forward regexp-p)))
-
-(defun gnus-summary-search-article-forward (regexp &optional backward)
- "Search for an article containing REGEXP forward.
-If BACKWARD, search backward instead."
- (interactive
- (list (read-string
- (format "Search article %s (regexp%s): "
- (if current-prefix-arg "backward" "forward")
- (if gnus-last-search-regexp
- (concat ", default " gnus-last-search-regexp)
- "")))
- current-prefix-arg))
- (gnus-set-global-variables)
- (if (string-equal regexp "")
- (setq regexp (or gnus-last-search-regexp ""))
- (setq gnus-last-search-regexp regexp))
- (unless (gnus-summary-search-article regexp backward)
- (error "Search failed: \"%s\"" regexp)))
-
-(defun gnus-summary-search-article-backward (regexp)
- "Search for an article containing REGEXP backward."
- (interactive
- (list (read-string
- (format "Search article backward (regexp%s): "
- (if gnus-last-search-regexp
- (concat ", default " gnus-last-search-regexp)
- "")))))
- (gnus-summary-search-article-forward regexp 'backward))
-
-(defun gnus-summary-search-article (regexp &optional backward)
- "Search for an article containing REGEXP.
-Optional argument BACKWARD means do search for backward.
-`gnus-select-article-hook' is not called during the search."
- (let ((gnus-select-article-hook nil) ;Disable hook.
- (gnus-article-display-hook nil)
- (gnus-mark-article-hook nil) ;Inhibit marking as read.
- (re-search
- (if backward
- 're-search-backward 're-search-forward))
- (sum (current-buffer))
- (found nil))
- (gnus-save-hidden-threads
- (gnus-summary-select-article)
- (set-buffer gnus-article-buffer)
- (when backward
- (forward-line -1))
- (while (not found)
- (gnus-message 7 "Searching article: %d..." (cdr gnus-article-current))
- (if (if backward
- (re-search-backward regexp nil t)
- (re-search-forward regexp nil t))
- ;; We found the regexp.
- (progn
- (setq found 'found)
- (beginning-of-line)
- (set-window-start
- (get-buffer-window (current-buffer))
- (point))
- (forward-line 1)
- (set-buffer sum))
- ;; We didn't find it, so we go to the next article.
- (set-buffer sum)
- (if (not (if backward (gnus-summary-find-prev)
- (gnus-summary-find-next)))
- ;; No more articles.
- (setq found t)
- ;; Select the next article and adjust point.
- (gnus-summary-select-article)
- (set-buffer gnus-article-buffer)
- (widen)
- (goto-char (if backward (point-max) (point-min))))))
- (gnus-message 7 ""))
- ;; Return whether we found the regexp.
- (when (eq found 'found)
- (gnus-summary-show-thread)
- (gnus-summary-goto-subject gnus-current-article)
- (gnus-summary-position-point)
- t)))
-
-(defun gnus-summary-find-matching (header regexp &optional backward unread
- not-case-fold)
- "Return a list of all articles that match REGEXP on HEADER.
-The search stars on the current article and goes forwards unless
-BACKWARD is non-nil. If BACKWARD is `all', do all articles.
-If UNREAD is non-nil, only unread articles will
-be taken into consideration. If NOT-CASE-FOLD, case won't be folded
-in the comparisons."
- (let ((data (if (eq backward 'all) gnus-newsgroup-data
- (gnus-data-find-list
- (gnus-summary-article-number) (gnus-data-list backward))))
- (func `(lambda (h) (,(intern (concat "mail-header-" header)) h)))
- (case-fold-search (not not-case-fold))
- articles d)
- (or (fboundp (intern (concat "mail-header-" header)))
- (error "%s is not a valid header" header))
- (while data
- (setq d (car data))
- (and (or (not unread) ; We want all articles...
- (gnus-data-unread-p d)) ; Or just unreads.
- (vectorp (gnus-data-header d)) ; It's not a pseudo.
- (string-match regexp (funcall func (gnus-data-header d))) ; Match.
- (setq articles (cons (gnus-data-number d) articles))) ; Success!
- (setq data (cdr data)))
- (nreverse articles)))
-
-(defun gnus-summary-execute-command (header regexp command &optional backward)
- "Search forward for an article whose HEADER matches REGEXP and execute COMMAND.
-If HEADER is an empty string (or nil), the match is done on the entire
-article. If BACKWARD (the prefix) is non-nil, search backward instead."
- (interactive
- (list (let ((completion-ignore-case t))
- (completing-read
- "Header name: "
- (mapcar (lambda (string) (list string))
- '("Number" "Subject" "From" "Lines" "Date"
- "Message-ID" "Xref" "References" "Body"))
- nil 'require-match))
- (read-string "Regexp: ")
- (read-key-sequence "Command: ")
- current-prefix-arg))
- (when (equal header "Body")
- (setq header ""))
- (gnus-set-global-variables)
- ;; Hidden thread subtrees must be searched as well.
- (gnus-summary-show-all-threads)
- ;; We don't want to change current point nor window configuration.
- (save-excursion
- (save-window-excursion
- (gnus-message 6 "Executing %s..." (key-description command))
- ;; We'd like to execute COMMAND interactively so as to give arguments.
- (gnus-execute header regexp
- `(lambda () (call-interactively ',(key-binding command)))
- backward)
- (gnus-message 6 "Executing %s...done" (key-description command)))))
-
-(defun gnus-summary-beginning-of-article ()
- "Scroll the article back to the beginning."
- (interactive)
- (gnus-set-global-variables)
- (gnus-summary-select-article)
- (gnus-configure-windows 'article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (widen)
- (goto-char (point-min))
- (and gnus-break-pages (gnus-narrow-to-page))))
-
-(defun gnus-summary-end-of-article ()
- "Scroll to the end of the article."
- (interactive)
- (gnus-set-global-variables)
- (gnus-summary-select-article)
- (gnus-configure-windows 'article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (widen)
- (goto-char (point-max))
- (recenter -3)
- (and gnus-break-pages (gnus-narrow-to-page))))
-
-(defun gnus-summary-show-article (&optional arg)
- "Force re-fetching of the current article.
-If ARG (the prefix) is non-nil, show the raw article without any
-article massaging functions being run."
- (interactive "P")
- (gnus-set-global-variables)
- (if (not arg)
- ;; Select the article the normal way.
- (gnus-summary-select-article nil 'force)
- ;; Bind the article treatment functions to nil.
- (let ((gnus-have-all-headers t)
- gnus-article-display-hook
- gnus-article-prepare-hook
- gnus-break-pages
- gnus-visual)
- (gnus-summary-select-article nil 'force)))
- (gnus-summary-goto-subject gnus-current-article)
-; (gnus-configure-windows 'article)
- (gnus-summary-position-point))
-
-(defun gnus-summary-verbose-headers (&optional arg)
- "Toggle permanent full header display.
-If ARG is a positive number, turn header display on.
-If ARG is a negative number, turn header display off."
- (interactive "P")
- (gnus-set-global-variables)
- (gnus-summary-toggle-header arg)
- (setq gnus-show-all-headers
- (cond ((or (not (numberp arg))
- (zerop arg))
- (not gnus-show-all-headers))
- ((natnump arg)
- t))))
-
-(defun gnus-summary-toggle-header (&optional arg)
- "Show the headers if they are hidden, or hide them if they are shown.
-If ARG is a positive number, show the entire header.
-If ARG is a negative number, hide the unwanted header lines."
- (interactive "P")
- (gnus-set-global-variables)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let* ((buffer-read-only nil)
- (inhibit-point-motion-hooks t)
- (hidden (text-property-any
- (goto-char (point-min)) (search-forward "\n\n")
- 'invisible t))
- e)
- (goto-char (point-min))
- (when (search-forward "\n\n" nil t)
- (delete-region (point-min) (1- (point))))
- (goto-char (point-min))
- (save-excursion
- (set-buffer gnus-original-article-buffer)
- (goto-char (point-min))
- (setq e (1- (or (search-forward "\n\n" nil t) (point-max)))))
- (insert-buffer-substring gnus-original-article-buffer 1 e)
- (let ((gnus-inhibit-hiding t))
- (run-hooks 'gnus-article-display-hook))
- (if (or (not hidden) (and (numberp arg) (< arg 0)))
- (gnus-article-hide-headers)))))
-
-(defun gnus-summary-show-all-headers ()
- "Make all header lines visible."
- (interactive)
- (gnus-set-global-variables)
- (gnus-article-show-all-headers))
-
-(defun gnus-summary-toggle-mime (&optional arg)
- "Toggle MIME processing.
-If ARG is a positive number, turn MIME processing on."
- (interactive "P")
- (gnus-set-global-variables)
- (setq gnus-show-mime
- (if (null arg) (not gnus-show-mime)
- (> (prefix-numeric-value arg) 0)))
- (gnus-summary-select-article t 'force))
-
-(defun gnus-summary-caesar-message (&optional arg)
- "Caesar rotate the current article by 13.
-The numerical prefix specifies how manu places to rotate each letter
-forward."
- (interactive "P")
- (gnus-set-global-variables)
- (gnus-summary-select-article)
- (let ((mail-header-separator ""))
- (gnus-eval-in-buffer-window gnus-article-buffer
- (save-restriction
- (widen)
- (let ((start (window-start))
- buffer-read-only)
- (message-caesar-buffer-body arg)
- (set-window-start (get-buffer-window (current-buffer)) start))))))
-
-(defun gnus-summary-stop-page-breaking ()
- "Stop page breaking in the current article."
- (interactive)
- (gnus-set-global-variables)
- (gnus-summary-select-article)
- (gnus-eval-in-buffer-window gnus-article-buffer
- (widen)))
-
-(defun gnus-summary-move-article (&optional n to-newsgroup select-method action)
- "Move the current article to a different newsgroup.
-If N is a positive number, move the N next articles.
-If N is a negative number, move the N previous articles.
-If N is nil and any articles have been marked with the process mark,
-move those articles instead.
-If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
-If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
-re-spool using this method.
-
-For this function to work, both the current newsgroup and the
-newsgroup that you want to move to have to support the `request-move'
-and `request-accept' functions."
- (interactive "P")
- (unless action (setq action 'move))
- (gnus-set-global-variables)
- ;; Check whether the source group supports the required functions.
- (cond ((and (eq action 'move)
- (not (gnus-check-backend-function
- 'request-move-article gnus-newsgroup-name)))
- (error "The current group does not support article moving"))
- ((and (eq action 'crosspost)
- (not (gnus-check-backend-function
- 'request-replace-article gnus-newsgroup-name)))
- (error "The current group does not support article editing")))
- (let ((articles (gnus-summary-work-articles n))
- (prefix (gnus-group-real-prefix gnus-newsgroup-name))
- (names '((move "Move" "Moving")
- (copy "Copy" "Copying")
- (crosspost "Crosspost" "Crossposting")))
- (copy-buf (save-excursion
- (nnheader-set-temp-buffer " *copy article*")))
- art-group to-method new-xref article to-groups)
- (unless (assq action names)
- (error "Unknown action %s" action))
- ;; Read the newsgroup name.
- (when (and (not to-newsgroup)
- (not select-method))
- (setq to-newsgroup
- (gnus-read-move-group-name
- (cadr (assq action names))
- (symbol-value (intern (format "gnus-current-%s-group" action)))
- articles prefix))
- (set (intern (format "gnus-current-%s-group" action)) to-newsgroup))
- (setq to-method (or select-method
- (gnus-group-name-to-method to-newsgroup)))
- ;; Check the method we are to move this article to...
- (or (gnus-check-backend-function 'request-accept-article (car to-method))
- (error "%s does not support article copying" (car to-method)))
- (or (gnus-check-server to-method)
- (error "Can't open server %s" (car to-method)))
- (gnus-message 6 "%s to %s: %s..."
- (caddr (assq action names))
- (or (car select-method) to-newsgroup) articles)
- (while articles
- (setq article (pop articles))
- (setq
- art-group
- (cond
- ;; Move the article.
- ((eq action 'move)
- (gnus-request-move-article
- article ; Article to move
- gnus-newsgroup-name ; From newsgrouo
- (nth 1 (gnus-find-method-for-group
- gnus-newsgroup-name)) ; Server
- (list 'gnus-request-accept-article
- to-newsgroup (list 'quote select-method)
- (not articles)) ; Accept form
- (not articles))) ; Only save nov last time
- ;; Copy the article.
- ((eq action 'copy)
- (save-excursion
- (set-buffer copy-buf)
- (gnus-request-article-this-buffer article gnus-newsgroup-name)
- (gnus-request-accept-article
- to-newsgroup select-method (not articles))))
- ;; Crosspost the article.
- ((eq action 'crosspost)
- (let ((xref (mail-header-xref (gnus-summary-article-header article))))
- (setq new-xref (concat gnus-newsgroup-name ":" article))
- (if (and xref (not (string= xref "")))
- (progn
- (when (string-match "^Xref: " xref)
- (setq xref (substring xref (match-end 0))))
- (setq new-xref (concat xref " " new-xref)))
- (setq new-xref (concat (system-name) " " new-xref)))
- (save-excursion
- (set-buffer copy-buf)
- (gnus-request-article-this-buffer article gnus-newsgroup-name)
- (nnheader-replace-header "xref" new-xref)
- (gnus-request-accept-article
- to-newsgroup select-method (not articles)))))))
- (if (not art-group)
- (gnus-message 1 "Couldn't %s article %s"
- (cadr (assq action names)) article)
- (let* ((entry
- (or
- (gnus-gethash (car art-group) gnus-newsrc-hashtb)
- (gnus-gethash
- (gnus-group-prefixed-name
- (car art-group)
- (or select-method
- (gnus-find-method-for-group to-newsgroup)))
- gnus-newsrc-hashtb)))
- (info (nth 2 entry))
- (to-group (gnus-info-group info)))
- ;; Update the group that has been moved to.
- (when (and info
- (memq action '(move copy)))
- (unless (member to-group to-groups)
- (push to-group to-groups))
-
- (unless (memq article gnus-newsgroup-unreads)
- (gnus-info-set-read
- info (gnus-add-to-range (gnus-info-read info)
- (list (cdr art-group)))))
-
- ;; Copy any marks over to the new group.
- (let ((marks gnus-article-mark-lists)
- (to-article (cdr art-group)))
-
- ;; See whether the article is to be put in the cache.
- (when gnus-use-cache
- (gnus-cache-possibly-enter-article
- to-group to-article
- (let ((header (copy-sequence
- (gnus-summary-article-header article))))
- (mail-header-set-number header to-article)
- header)
- (memq article gnus-newsgroup-marked)
- (memq article gnus-newsgroup-dormant)
- (memq article gnus-newsgroup-unreads)))
-
- (while marks
- (when (memq article (symbol-value
- (intern (format "gnus-newsgroup-%s"
- (caar marks)))))
- ;; If the other group is the same as this group,
- ;; then we have to add the mark to the list.
- (when (equal to-group gnus-newsgroup-name)
- (set (intern (format "gnus-newsgroup-%s" (caar marks)))
- (cons to-article
- (symbol-value
- (intern (format "gnus-newsgroup-%s"
- (caar marks)))))))
- ;; Copy mark to other group.
- (gnus-add-marked-articles
- to-group (cdar marks) (list to-article) info))
- (setq marks (cdr marks)))))
-
- ;; Update the Xref header in this article to point to
- ;; the new crossposted article we have just created.
- (when (eq action 'crosspost)
- (save-excursion
- (set-buffer copy-buf)
- (gnus-request-article-this-buffer article gnus-newsgroup-name)
- (nnheader-replace-header
- "xref" (concat new-xref " " (gnus-group-prefixed-name
- (car art-group) to-method)
- ":" (cdr art-group)))
- (gnus-request-replace-article
- article gnus-newsgroup-name (current-buffer)))))
-
- (gnus-summary-goto-subject article)
- (when (eq action 'move)
- (gnus-summary-mark-article article gnus-canceled-mark)))
- (gnus-summary-remove-process-mark article))
- ;; Re-activate all groups that have been moved to.
- (while to-groups
- (gnus-activate-group (pop to-groups)))
-
- (gnus-kill-buffer copy-buf)
- (gnus-summary-position-point)
- (gnus-set-mode-line 'summary)))
-
-(defun gnus-summary-copy-article (&optional n to-newsgroup select-method)
- "Move the current article to a different newsgroup.
-If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
-If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
-re-spool using this method."
- (interactive "P")
- (gnus-summary-move-article n nil select-method 'copy))
-
-(defun gnus-summary-crosspost-article (&optional n)
- "Crosspost the current article to some other group."
- (interactive "P")
- (gnus-summary-move-article n nil nil 'crosspost))
-
-(defvar gnus-summary-respool-default-method nil
- "Default method for respooling an article.
-If nil, use to the current newsgroup method.")
-
-(defun gnus-summary-respool-article (&optional n method)
- "Respool the current article.
-The article will be squeezed through the mail spooling process again,
-which means that it will be put in some mail newsgroup or other
-depending on `nnmail-split-methods'.
-If N is a positive number, respool the N next articles.
-If N is a negative number, respool the N previous articles.
-If N is nil and any articles have been marked with the process mark,
-respool those articles instead.
-
-Respooling can be done both from mail groups and \"real\" newsgroups.
-In the former case, the articles in question will be moved from the
-current group into whatever groups they are destined to. In the
-latter case, they will be copied into the relevant groups."
- (interactive
- (list current-prefix-arg
- (let* ((methods (gnus-methods-using 'respool))
- (methname
- (symbol-name (or gnus-summary-respool-default-method
- (car (gnus-find-method-for-group
- gnus-newsgroup-name)))))
- (method
- (gnus-completing-read
- methname "What backend do you want to use when respooling?"
- methods nil t nil 'gnus-method-history))
- ms)
- (cond
- ((zerop (length (setq ms (gnus-servers-using-backend method))))
- (list (intern method) ""))
- ((= 1 (length ms))
- (car ms))
- (t
- (cdr (completing-read
- "Server name: "
- (mapcar (lambda (m) (cons (cadr m) m)) ms) nil t)))))))
- (gnus-set-global-variables)
- (unless method
- (error "No method given for respooling"))
- (if (assoc (symbol-name
- (car (gnus-find-method-for-group gnus-newsgroup-name)))
- (gnus-methods-using 'respool))
- (gnus-summary-move-article n nil method)
- (gnus-summary-copy-article n nil method)))
-
-(defun gnus-summary-import-article (file)
- "Import a random file into a mail newsgroup."
- (interactive "fImport file: ")
- (gnus-set-global-variables)
- (let ((group gnus-newsgroup-name)
- (now (current-time))
- atts lines)
- (or (gnus-check-backend-function 'request-accept-article group)
- (error "%s does not support article importing" group))
- (or (file-readable-p file)
- (not (file-regular-p file))
- (error "Can't read %s" file))
- (save-excursion
- (set-buffer (get-buffer-create " *import file*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert-file-contents file)
- (goto-char (point-min))
- (unless (nnheader-article-p)
- ;; This doesn't look like an article, so we fudge some headers.
- (setq atts (file-attributes file)
- lines (count-lines (point-min) (point-max)))
- (insert "From: " (read-string "From: ") "\n"
- "Subject: " (read-string "Subject: ") "\n"
- "Date: " (timezone-make-date-arpa-standard
- (current-time-string (nth 5 atts))
- (current-time-zone now)
- (current-time-zone now)) "\n"
- "Message-ID: " (message-make-message-id) "\n"
- "Lines: " (int-to-string lines) "\n"
- "Chars: " (int-to-string (nth 7 atts)) "\n\n"))
- (gnus-request-accept-article group nil t)
- (kill-buffer (current-buffer)))))
-
-(defun gnus-summary-expire-articles (&optional now)
- "Expire all articles that are marked as expirable in the current group."
- (interactive)
- (gnus-set-global-variables)
- (when (gnus-check-backend-function
- 'request-expire-articles gnus-newsgroup-name)
- ;; This backend supports expiry.
- (let* ((total (gnus-group-total-expirable-p gnus-newsgroup-name))
- (expirable (if total
- (gnus-list-of-read-articles gnus-newsgroup-name)
- (setq gnus-newsgroup-expirable
- (sort gnus-newsgroup-expirable '<))))
- (expiry-wait (if now 'immediate
- (gnus-group-get-parameter
- gnus-newsgroup-name 'expiry-wait)))
- es)
- (when expirable
- ;; There are expirable articles in this group, so we run them
- ;; through the expiry process.
- (gnus-message 6 "Expiring articles...")
- ;; The list of articles that weren't expired is returned.
- (if expiry-wait
- (let ((nnmail-expiry-wait-function nil)
- (nnmail-expiry-wait expiry-wait))
- (setq es (gnus-request-expire-articles
- expirable gnus-newsgroup-name)))
- (setq es (gnus-request-expire-articles
- expirable gnus-newsgroup-name)))
- (or total (setq gnus-newsgroup-expirable es))
- ;; We go through the old list of expirable, and mark all
- ;; really expired articles as nonexistent.
- (unless (eq es expirable) ;If nothing was expired, we don't mark.
- (let ((gnus-use-cache nil))
- (while expirable
- (unless (memq (car expirable) es)
- (when (gnus-data-find (car expirable))
- (gnus-summary-mark-article
- (car expirable) gnus-canceled-mark)))
- (setq expirable (cdr expirable)))))
- (gnus-message 6 "Expiring articles...done")))))
-
-(defun gnus-summary-expire-articles-now ()
- "Expunge all expirable articles in the current group.
-This means that *all* articles that are marked as expirable will be
-deleted forever, right now."
- (interactive)
- (gnus-set-global-variables)
- (or gnus-expert-user
- (gnus-y-or-n-p
- "Are you really, really, really sure you want to delete all these messages? ")
- (error "Phew!"))
- (gnus-summary-expire-articles t))
-
-;; Suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>.
-(defun gnus-summary-delete-article (&optional n)
- "Delete the N next (mail) articles.
-This command actually deletes articles. This is not a marking
-command. The article will disappear forever from your life, never to
-return.
-If N is negative, delete backwards.
-If N is nil and articles have been marked with the process mark,
-delete these instead."
- (interactive "P")
- (gnus-set-global-variables)
- (or (gnus-check-backend-function 'request-expire-articles
- gnus-newsgroup-name)
- (error "The current newsgroup does not support article deletion."))
- ;; Compute the list of articles to delete.
- (let ((articles (gnus-summary-work-articles n))
- not-deleted)
- (if (and gnus-novice-user
- (not (gnus-y-or-n-p
- (format "Do you really want to delete %s forever? "
- (if (> (length articles) 1)
- (format "these %s articles" (length articles))
- "this article")))))
- ()
- ;; Delete the articles.
- (setq not-deleted (gnus-request-expire-articles
- articles gnus-newsgroup-name 'force))
- (while articles
- (gnus-summary-remove-process-mark (car articles))
- ;; The backend might not have been able to delete the article
- ;; after all.
- (or (memq (car articles) not-deleted)
- (gnus-summary-mark-article (car articles) gnus-canceled-mark))
- (setq articles (cdr articles))))
- (gnus-summary-position-point)
- (gnus-set-mode-line 'summary)
- not-deleted))
-
-(defun gnus-summary-edit-article (&optional force)
- "Enter into a buffer and edit the current article.
-This will have permanent effect only in mail groups.
-If FORCE is non-nil, allow editing of articles even in read-only
-groups."
- (interactive "P")
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (gnus-set-global-variables)
- (when (and (not force)
- (gnus-group-read-only-p))
- (error "The current newsgroup does not support article editing."))
- (gnus-summary-select-article t nil t)
- (gnus-configure-windows 'article)
- (select-window (get-buffer-window gnus-article-buffer))
- (gnus-message 6 "C-c C-c to end edits")
- (setq buffer-read-only nil)
- (text-mode)
- (use-local-map (copy-keymap (current-local-map)))
- (local-set-key "\C-c\C-c" 'gnus-summary-edit-article-done)
- (buffer-enable-undo)
- (widen)
- (goto-char (point-min))
- (search-forward "\n\n" nil t)))
-
-(defun gnus-summary-edit-article-done ()
- "Make edits to the current article permanent."
- (interactive)
- (if (gnus-group-read-only-p)
- (progn
- (let ((beep (not (eq major-mode 'text-mode))))
- (gnus-summary-edit-article-postpone)
- (when beep
- (gnus-error
- 3 "The current newsgroup does not support article editing."))))
- (let ((buf (format "%s" (buffer-string))))
- (erase-buffer)
- (insert buf)
- (if (not (gnus-request-replace-article
- (cdr gnus-article-current) (car gnus-article-current)
- (current-buffer)))
- (error "Couldn't replace article.")
- (gnus-article-mode)
- (use-local-map gnus-article-mode-map)
- (setq buffer-read-only t)
- (buffer-disable-undo (current-buffer))
- (gnus-configure-windows 'summary)
- (gnus-summary-update-article (cdr gnus-article-current))
- (when gnus-use-cache
- (gnus-cache-update-article
- (car gnus-article-current) (cdr gnus-article-current)))
- (when gnus-keep-backlog
- (gnus-backlog-remove-article
- (car gnus-article-current) (cdr gnus-article-current))))
- (save-excursion
- (when (get-buffer gnus-original-article-buffer)
- (set-buffer gnus-original-article-buffer)
- (setq gnus-original-article nil)))
- (setq gnus-article-current nil
- gnus-current-article nil)
- (run-hooks 'gnus-article-display-hook)
- (and (gnus-visual-p 'summary-highlight 'highlight)
- (run-hooks 'gnus-visual-mark-article-hook)))))
-
-(defun gnus-summary-edit-article-postpone ()
- "Postpone changes to the current article."
- (interactive)
- (gnus-article-mode)
- (use-local-map gnus-article-mode-map)
- (setq buffer-read-only t)
- (buffer-disable-undo (current-buffer))
- (gnus-configure-windows 'summary)
- (and (gnus-visual-p 'summary-highlight 'highlight)
- (run-hooks 'gnus-visual-mark-article-hook)))
-
-(defun gnus-summary-respool-query ()
- "Query where the respool algorithm would put this article."
- (interactive)
- (gnus-set-global-variables)
- (gnus-summary-select-article)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (save-restriction
- (goto-char (point-min))
- (search-forward "\n\n")
- (narrow-to-region (point-min) (point))
- (pp-eval-expression
- (list 'quote (mapcar 'car (nnmail-article-group 'identity)))))))
-
-;; Summary marking commands.
-
-(defun gnus-summary-kill-same-subject-and-select (&optional unmark)
- "Mark articles which has the same subject as read, and then select the next.
-If UNMARK is positive, remove any kind of mark.
-If UNMARK is negative, tick articles."
- (interactive "P")
- (gnus-set-global-variables)
- (if unmark
- (setq unmark (prefix-numeric-value unmark)))
- (let ((count
- (gnus-summary-mark-same-subject
- (gnus-summary-article-subject) unmark)))
- ;; Select next unread article. If auto-select-same mode, should
- ;; select the first unread article.
- (gnus-summary-next-article t (and gnus-auto-select-same
- (gnus-summary-article-subject)))
- (gnus-message 7 "%d article%s marked as %s"
- count (if (= count 1) " is" "s are")
- (if unmark "unread" "read"))))
-
-(defun gnus-summary-kill-same-subject (&optional unmark)
- "Mark articles which has the same subject as read.
-If UNMARK is positive, remove any kind of mark.
-If UNMARK is negative, tick articles."
- (interactive "P")
- (gnus-set-global-variables)
- (if unmark
- (setq unmark (prefix-numeric-value unmark)))
- (let ((count
- (gnus-summary-mark-same-subject
- (gnus-summary-article-subject) unmark)))
- ;; If marked as read, go to next unread subject.
- (if (null unmark)
- ;; Go to next unread subject.
- (gnus-summary-next-subject 1 t))
- (gnus-message 7 "%d articles are marked as %s"
- count (if unmark "unread" "read"))))
-
-(defun gnus-summary-mark-same-subject (subject &optional unmark)
- "Mark articles with same SUBJECT as read, and return marked number.
-If optional argument UNMARK is positive, remove any kinds of marks.
-If optional argument UNMARK is negative, mark articles as unread instead."
- (let ((count 1))
- (save-excursion
- (cond
- ((null unmark) ; Mark as read.
- (while (and
- (progn
- (gnus-summary-mark-article-as-read gnus-killed-mark)
- (gnus-summary-show-thread) t)
- (gnus-summary-find-subject subject))
- (setq count (1+ count))))
- ((> unmark 0) ; Tick.
- (while (and
- (progn
- (gnus-summary-mark-article-as-unread gnus-ticked-mark)
- (gnus-summary-show-thread) t)
- (gnus-summary-find-subject subject))
- (setq count (1+ count))))
- (t ; Mark as unread.
- (while (and
- (progn
- (gnus-summary-mark-article-as-unread gnus-unread-mark)
- (gnus-summary-show-thread) t)
- (gnus-summary-find-subject subject))
- (setq count (1+ count)))))
- (gnus-set-mode-line 'summary)
- ;; Return the number of marked articles.
- count)))
-
-(defun gnus-summary-mark-as-processable (n &optional unmark)
- "Set the process mark on the next N articles.
-If N is negative, mark backward instead. If UNMARK is non-nil, remove
-the process mark instead. The difference between N and the actual
-number of articles marked is returned."
- (interactive "p")
- (gnus-set-global-variables)
- (let ((backward (< n 0))
- (n (abs n)))
- (while (and
- (> n 0)
- (if unmark
- (gnus-summary-remove-process-mark
- (gnus-summary-article-number))
- (gnus-summary-set-process-mark (gnus-summary-article-number)))
- (zerop (gnus-summary-next-subject (if backward -1 1) nil t)))
- (setq n (1- n)))
- (if (/= 0 n) (gnus-message 7 "No more articles"))
- (gnus-summary-recenter)
- (gnus-summary-position-point)
- n))
-
-(defun gnus-summary-unmark-as-processable (n)
- "Remove the process mark from the next N articles.
-If N is negative, mark backward instead. The difference between N and
-the actual number of articles marked is returned."
- (interactive "p")
- (gnus-set-global-variables)
- (gnus-summary-mark-as-processable n t))
-
-(defun gnus-summary-unmark-all-processable ()
- "Remove the process mark from all articles."
- (interactive)
- (gnus-set-global-variables)
- (save-excursion
- (while gnus-newsgroup-processable
- (gnus-summary-remove-process-mark (car gnus-newsgroup-processable))))
- (gnus-summary-position-point))
-
-(defun gnus-summary-mark-as-expirable (n)
- "Mark N articles forward as expirable.
-If N is negative, mark backward instead. The difference between N and
-the actual number of articles marked is returned."
- (interactive "p")
- (gnus-set-global-variables)
- (gnus-summary-mark-forward n gnus-expirable-mark))
-
-(defun gnus-summary-mark-article-as-replied (article)
- "Mark ARTICLE replied and update the summary line."
- (setq gnus-newsgroup-replied (cons article gnus-newsgroup-replied))
- (let ((buffer-read-only nil))
- (when (gnus-summary-goto-subject article)
- (gnus-summary-update-secondary-mark article))))
-
-(defun gnus-summary-set-bookmark (article)
- "Set a bookmark in current article."
- (interactive (list (gnus-summary-article-number)))
- (gnus-set-global-variables)
- (if (or (not (get-buffer gnus-article-buffer))
- (not gnus-current-article)
- (not gnus-article-current)
- (not (equal gnus-newsgroup-name (car gnus-article-current))))
- (error "No current article selected"))
- ;; Remove old bookmark, if one exists.
- (let ((old (assq article gnus-newsgroup-bookmarks)))
- (if old (setq gnus-newsgroup-bookmarks
- (delq old gnus-newsgroup-bookmarks))))
- ;; Set the new bookmark, which is on the form
- ;; (article-number . line-number-in-body).
- (setq gnus-newsgroup-bookmarks
- (cons
- (cons article
- (save-excursion
- (set-buffer gnus-article-buffer)
- (count-lines
- (min (point)
- (save-excursion
- (goto-char (point-min))
- (search-forward "\n\n" nil t)
- (point)))
- (point))))
- gnus-newsgroup-bookmarks))
- (gnus-message 6 "A bookmark has been added to the current article."))
-
-(defun gnus-summary-remove-bookmark (article)
- "Remove the bookmark from the current article."
- (interactive (list (gnus-summary-article-number)))
- (gnus-set-global-variables)
- ;; Remove old bookmark, if one exists.
- (let ((old (assq article gnus-newsgroup-bookmarks)))
- (if old
- (progn
- (setq gnus-newsgroup-bookmarks
- (delq old gnus-newsgroup-bookmarks))
- (gnus-message 6 "Removed bookmark."))
- (gnus-message 6 "No bookmark in current article."))))
-
-;; Suggested by Daniel Quinlan <quinlan@best.com>.
-(defun gnus-summary-mark-as-dormant (n)
- "Mark N articles forward as dormant.
-If N is negative, mark backward instead. The difference between N and
-the actual number of articles marked is returned."
- (interactive "p")
- (gnus-set-global-variables)
- (gnus-summary-mark-forward n gnus-dormant-mark))
-
-(defun gnus-summary-set-process-mark (article)
- "Set the process mark on ARTICLE and update the summary line."
- (setq gnus-newsgroup-processable
- (cons article
- (delq article gnus-newsgroup-processable)))
- (when (gnus-summary-goto-subject article)
- (gnus-summary-show-thread)
- (gnus-summary-update-secondary-mark article)))
-
-(defun gnus-summary-remove-process-mark (article)
- "Remove the process mark from ARTICLE and update the summary line."
- (setq gnus-newsgroup-processable (delq article gnus-newsgroup-processable))
- (when (gnus-summary-goto-subject article)
- (gnus-summary-show-thread)
- (gnus-summary-update-secondary-mark article)))
-
-(defun gnus-summary-set-saved-mark (article)
- "Set the process mark on ARTICLE and update the summary line."
- (push article gnus-newsgroup-saved)
- (when (gnus-summary-goto-subject article)
- (gnus-summary-update-secondary-mark article)))
-
-(defun gnus-summary-mark-forward (n &optional mark no-expire)
- "Mark N articles as read forwards.
-If N is negative, mark backwards instead. Mark with MARK, ?r by default.
-The difference between N and the actual number of articles marked is
-returned."
- (interactive "p")
- (gnus-set-global-variables)
- (let ((backward (< n 0))
- (gnus-summary-goto-unread
- (and gnus-summary-goto-unread
- (not (eq gnus-summary-goto-unread 'never))
- (not (memq mark (list gnus-unread-mark
- gnus-ticked-mark gnus-dormant-mark)))))
- (n (abs n))
- (mark (or mark gnus-del-mark)))
- (while (and (> n 0)
- (gnus-summary-mark-article nil mark no-expire)
- (zerop (gnus-summary-next-subject
- (if backward -1 1)
- (and gnus-summary-goto-unread
- (not (eq gnus-summary-goto-unread 'never)))
- t)))
- (setq n (1- n)))
- (if (/= 0 n) (gnus-message 7 "No more %sarticles" (if mark "" "unread ")))
- (gnus-summary-recenter)
- (gnus-summary-position-point)
- (gnus-set-mode-line 'summary)
- n))
-
-(defun gnus-summary-mark-article-as-read (mark)
- "Mark the current article quickly as read with MARK."
- (let ((article (gnus-summary-article-number)))
- (setq gnus-newsgroup-unreads (delq article gnus-newsgroup-unreads))
- (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
- (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
- (setq gnus-newsgroup-reads
- (cons (cons article mark) gnus-newsgroup-reads))
- ;; Possibly remove from cache, if that is used.
- (and gnus-use-cache (gnus-cache-enter-remove-article article))
- ;; Allow the backend to change the mark.
- (setq mark (gnus-request-update-mark gnus-newsgroup-name article mark))
- ;; Check for auto-expiry.
- (when (and gnus-newsgroup-auto-expire
- (or (= mark gnus-killed-mark) (= mark gnus-del-mark)
- (= mark gnus-catchup-mark) (= mark gnus-low-score-mark)
- (= mark gnus-ancient-mark)
- (= mark gnus-read-mark) (= mark gnus-souped-mark)))
- (setq mark gnus-expirable-mark)
- (push article gnus-newsgroup-expirable))
- ;; Set the mark in the buffer.
- (gnus-summary-update-mark mark 'unread)
- t))
-
-(defun gnus-summary-mark-article-as-unread (mark)
- "Mark the current article quickly as unread with MARK."
- (let ((article (gnus-summary-article-number)))
- (if (< article 0)
- (gnus-error 1 "Unmarkable article")
- (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
- (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
- (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable))
- (setq gnus-newsgroup-reads (delq article gnus-newsgroup-reads))
- (cond ((= mark gnus-ticked-mark)
- (push article gnus-newsgroup-marked))
- ((= mark gnus-dormant-mark)
- (push article gnus-newsgroup-dormant))
- (t
- (push article gnus-newsgroup-unreads)))
- (setq gnus-newsgroup-reads
- (delq (assq article gnus-newsgroup-reads)
- gnus-newsgroup-reads))
-
- ;; See whether the article is to be put in the cache.
- (and gnus-use-cache
- (vectorp (gnus-summary-article-header article))
- (save-excursion
- (gnus-cache-possibly-enter-article
- gnus-newsgroup-name article
- (gnus-summary-article-header article)
- (= mark gnus-ticked-mark)
- (= mark gnus-dormant-mark) (= mark gnus-unread-mark))))
-
- ;; Fix the mark.
- (gnus-summary-update-mark mark 'unread))
- t))
-
-(defun gnus-summary-mark-article (&optional article mark no-expire)
- "Mark ARTICLE with MARK. MARK can be any character.
-Four MARK strings are reserved: `? ' (unread), `?!' (ticked),
-`??' (dormant) and `?E' (expirable).
-If MARK is nil, then the default character `?D' is used.
-If ARTICLE is nil, then the article on the current line will be
-marked."
- ;; The mark might be a string.
- (and (stringp mark)
- (setq mark (aref mark 0)))
- ;; If no mark is given, then we check auto-expiring.
- (and (not no-expire)
- gnus-newsgroup-auto-expire
- (or (not mark)
- (and (numberp mark)
- (or (= mark gnus-killed-mark) (= mark gnus-del-mark)
- (= mark gnus-catchup-mark) (= mark gnus-low-score-mark)
- (= mark gnus-read-mark) (= mark gnus-souped-mark))))
- (setq mark gnus-expirable-mark))
- (let* ((mark (or mark gnus-del-mark))
- (article (or article (gnus-summary-article-number))))
- (or article (error "No article on current line"))
- (if (or (= mark gnus-unread-mark)
- (= mark gnus-ticked-mark)
- (= mark gnus-dormant-mark))
- (gnus-mark-article-as-unread article mark)
- (gnus-mark-article-as-read article mark))
-
- ;; See whether the article is to be put in the cache.
- (and gnus-use-cache
- (not (= mark gnus-canceled-mark))
- (vectorp (gnus-summary-article-header article))
- (save-excursion
- (gnus-cache-possibly-enter-article
- gnus-newsgroup-name article
- (gnus-summary-article-header article)
- (= mark gnus-ticked-mark)
- (= mark gnus-dormant-mark) (= mark gnus-unread-mark))))
-
- (if (gnus-summary-goto-subject article nil t)
- (let ((buffer-read-only nil))
- (gnus-summary-show-thread)
- ;; Fix the mark.
- (gnus-summary-update-mark mark 'unread)
- t))))
-
-(defun gnus-summary-update-secondary-mark (article)
- "Update the secondary (read, process, cache) mark."
- (gnus-summary-update-mark
- (cond ((memq article gnus-newsgroup-processable)
- gnus-process-mark)
- ((memq article gnus-newsgroup-cached)
- gnus-cached-mark)
- ((memq article gnus-newsgroup-replied)
- gnus-replied-mark)
- ((memq article gnus-newsgroup-saved)
- gnus-saved-mark)
- (t gnus-unread-mark))
- 'replied)
- (when (gnus-visual-p 'summary-highlight 'highlight)
- (run-hooks 'gnus-summary-update-hook))
- t)
-
-(defun gnus-summary-update-mark (mark type)
- (beginning-of-line)
- (let ((forward (cdr (assq type gnus-summary-mark-positions)))
- (buffer-read-only nil))
- (when (and forward
- (<= (+ forward (point)) (point-max)))
- ;; Go to the right position on the line.
- (goto-char (+ forward (point)))
- ;; Replace the old mark with the new mark.
- (subst-char-in-region (point) (1+ (point)) (following-char) mark)
- ;; Optionally update the marks by some user rule.
- (when (eq type 'unread)
- (gnus-data-set-mark
- (gnus-data-find (gnus-summary-article-number)) mark)
- (gnus-summary-update-line (eq mark gnus-unread-mark))))))
-
-(defun gnus-mark-article-as-read (article &optional mark)
- "Enter ARTICLE in the pertinent lists and remove it from others."
- ;; Make the article expirable.
- (let ((mark (or mark gnus-del-mark)))
- (if (= mark gnus-expirable-mark)
- (setq gnus-newsgroup-expirable (cons article gnus-newsgroup-expirable))
- (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable)))
- ;; Remove from unread and marked lists.
- (setq gnus-newsgroup-unreads (delq article gnus-newsgroup-unreads))
- (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
- (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
- (push (cons article mark) gnus-newsgroup-reads)
- ;; Possibly remove from cache, if that is used.
- (when gnus-use-cache
- (gnus-cache-enter-remove-article article))))
-
-(defun gnus-mark-article-as-unread (article &optional mark)
- "Enter ARTICLE in the pertinent lists and remove it from others."
- (let ((mark (or mark gnus-ticked-mark)))
- (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
- (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
- (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable))
- (setq gnus-newsgroup-unreads (delq article gnus-newsgroup-unreads))
- (cond ((= mark gnus-ticked-mark)
- (push article gnus-newsgroup-marked))
- ((= mark gnus-dormant-mark)
- (push article gnus-newsgroup-dormant))
- (t
- (push article gnus-newsgroup-unreads)))
- (setq gnus-newsgroup-reads
- (delq (assq article gnus-newsgroup-reads)
- gnus-newsgroup-reads))))
-
-(defalias 'gnus-summary-mark-as-unread-forward
- 'gnus-summary-tick-article-forward)
-(make-obsolete 'gnus-summary-mark-as-unread-forward
- 'gnus-summary-tick-article-forward)
-(defun gnus-summary-tick-article-forward (n)
- "Tick N articles forwards.
-If N is negative, tick backwards instead.
-The difference between N and the number of articles ticked is returned."
- (interactive "p")
- (gnus-summary-mark-forward n gnus-ticked-mark))
-
-(defalias 'gnus-summary-mark-as-unread-backward
- 'gnus-summary-tick-article-backward)
-(make-obsolete 'gnus-summary-mark-as-unread-backward
- 'gnus-summary-tick-article-backward)
-(defun gnus-summary-tick-article-backward (n)
- "Tick N articles backwards.
-The difference between N and the number of articles ticked is returned."
- (interactive "p")
- (gnus-summary-mark-forward (- n) gnus-ticked-mark))
-
-(defalias 'gnus-summary-mark-as-unread 'gnus-summary-tick-article)
-(make-obsolete 'gnus-summary-mark-as-unread 'gnus-summary-tick-article)
-(defun gnus-summary-tick-article (&optional article clear-mark)
- "Mark current article as unread.
-Optional 1st argument ARTICLE specifies article number to be marked as unread.
-Optional 2nd argument CLEAR-MARK remove any kinds of mark."
- (interactive)
- (gnus-summary-mark-article article (if clear-mark gnus-unread-mark
- gnus-ticked-mark)))
-
-(defun gnus-summary-mark-as-read-forward (n)
- "Mark N articles as read forwards.
-If N is negative, mark backwards instead.
-The difference between N and the actual number of articles marked is
-returned."
- (interactive "p")
- (gnus-summary-mark-forward n gnus-del-mark t))
-
-(defun gnus-summary-mark-as-read-backward (n)
- "Mark the N articles as read backwards.
-The difference between N and the actual number of articles marked is
-returned."
- (interactive "p")
- (gnus-summary-mark-forward (- n) gnus-del-mark t))
-
-(defun gnus-summary-mark-as-read (&optional article mark)
- "Mark current article as read.
-ARTICLE specifies the article to be marked as read.
-MARK specifies a string to be inserted at the beginning of the line."
- (gnus-summary-mark-article article mark))
-
-(defun gnus-summary-clear-mark-forward (n)
- "Clear marks from N articles forward.
-If N is negative, clear backward instead.
-The difference between N and the number of marks cleared is returned."
- (interactive "p")
- (gnus-summary-mark-forward n gnus-unread-mark))
-
-(defun gnus-summary-clear-mark-backward (n)
- "Clear marks from N articles backward.
-The difference between N and the number of marks cleared is returned."
- (interactive "p")
- (gnus-summary-mark-forward (- n) gnus-unread-mark))
-
-(defun gnus-summary-mark-unread-as-read ()
- "Intended to be used by `gnus-summary-mark-article-hook'."
- (when (memq gnus-current-article gnus-newsgroup-unreads)
- (gnus-summary-mark-article gnus-current-article gnus-read-mark)))
-
-(defun gnus-summary-mark-read-and-unread-as-read ()
- "Intended to be used by `gnus-summary-mark-article-hook'."
- (let ((mark (gnus-summary-article-mark)))
- (when (or (gnus-unread-mark-p mark)
- (gnus-read-mark-p mark))
- (gnus-summary-mark-article gnus-current-article gnus-read-mark))))
-
-(defun gnus-summary-mark-region-as-read (point mark all)
- "Mark all unread articles between point and mark as read.
-If given a prefix, mark all articles between point and mark as read,
-even ticked and dormant ones."
- (interactive "r\nP")
- (save-excursion
- (let (article)
- (goto-char point)
- (beginning-of-line)
- (while (and
- (< (point) mark)
- (progn
- (when (or all
- (memq (setq article (gnus-summary-article-number))
- gnus-newsgroup-unreads))
- (gnus-summary-mark-article article gnus-del-mark))
- t)
- (gnus-summary-find-next))))))
-
-(defun gnus-summary-mark-below (score mark)
- "Mark articles with score less than SCORE with MARK."
- (interactive "P\ncMark: ")
- (gnus-set-global-variables)
- (setq score (if score
- (prefix-numeric-value score)
- (or gnus-summary-default-score 0)))
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (goto-char (point-min))
- (while
- (progn
- (and (< (gnus-summary-article-score) score)
- (gnus-summary-mark-article nil mark))
- (gnus-summary-find-next)))))
-
-(defun gnus-summary-kill-below (&optional score)
- "Mark articles with score below SCORE as read."
- (interactive "P")
- (gnus-set-global-variables)
- (gnus-summary-mark-below score gnus-killed-mark))
-
-(defun gnus-summary-clear-above (&optional score)
- "Clear all marks from articles with score above SCORE."
- (interactive "P")
- (gnus-set-global-variables)
- (gnus-summary-mark-above score gnus-unread-mark))
-
-(defun gnus-summary-tick-above (&optional score)
- "Tick all articles with score above SCORE."
- (interactive "P")
- (gnus-set-global-variables)
- (gnus-summary-mark-above score gnus-ticked-mark))
-
-(defun gnus-summary-mark-above (score mark)
- "Mark articles with score over SCORE with MARK."
- (interactive "P\ncMark: ")
- (gnus-set-global-variables)
- (setq score (if score
- (prefix-numeric-value score)
- (or gnus-summary-default-score 0)))
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (goto-char (point-min))
- (while (and (progn
- (if (> (gnus-summary-article-score) score)
- (gnus-summary-mark-article nil mark))
- t)
- (gnus-summary-find-next)))))
-
-;; Suggested by Daniel Quinlan <quinlan@best.com>.
-(defalias 'gnus-summary-show-all-expunged 'gnus-summary-limit-include-expunged)
-(defun gnus-summary-limit-include-expunged ()
- "Display all the hidden articles that were expunged for low scores."
- (interactive)
- (gnus-set-global-variables)
- (let ((buffer-read-only nil))
- (let ((scored gnus-newsgroup-scored)
- headers h)
- (while scored
- (or (gnus-summary-goto-subject (caar scored))
- (and (setq h (gnus-summary-article-header (caar scored)))
- (< (cdar scored) gnus-summary-expunge-below)
- (setq headers (cons h headers))))
- (setq scored (cdr scored)))
- (or headers (error "No expunged articles hidden."))
- (goto-char (point-min))
- (gnus-summary-prepare-unthreaded (nreverse headers)))
- (goto-char (point-min))
- (gnus-summary-position-point)))
-
-(defun gnus-summary-catchup (&optional all quietly to-here not-mark)
- "Mark all articles not marked as unread in this newsgroup as read.
-If prefix argument ALL is non-nil, all articles are marked as read.
-If QUIETLY is non-nil, no questions will be asked.
-If TO-HERE is non-nil, it should be a point in the buffer. All
-articles before this point will be marked as read.
-The number of articles marked as read is returned."
- (interactive "P")
- (gnus-set-global-variables)
- (prog1
- (if (or quietly
- (not gnus-interactive-catchup) ;Without confirmation?
- gnus-expert-user
- (gnus-y-or-n-p
- (if all
- "Mark absolutely all articles as read? "
- "Mark all unread articles as read? ")))
- (if (and not-mark
- (not gnus-newsgroup-adaptive)
- (not gnus-newsgroup-auto-expire))
- (progn
- (when all
- (setq gnus-newsgroup-marked nil
- gnus-newsgroup-dormant nil))
- (setq gnus-newsgroup-unreads nil))
- ;; We actually mark all articles as canceled, which we
- ;; have to do when using auto-expiry or adaptive scoring.
- (gnus-summary-show-all-threads)
- (if (gnus-summary-first-subject (not all))
- (while (and
- (if to-here (< (point) to-here) t)
- (gnus-summary-mark-article-as-read gnus-catchup-mark)
- (gnus-summary-find-next (not all)))))
- (unless to-here
- (setq gnus-newsgroup-unreads nil))
- (gnus-set-mode-line 'summary)))
- (let ((method (gnus-find-method-for-group gnus-newsgroup-name)))
- (if (and (not to-here) (eq 'nnvirtual (car method)))
- (nnvirtual-catchup-group
- (gnus-group-real-name gnus-newsgroup-name) (nth 1 method) all)))
- (gnus-summary-position-point)))
-
-(defun gnus-summary-catchup-to-here (&optional all)
- "Mark all unticked articles before the current one as read.
-If ALL is non-nil, also mark ticked and dormant articles as read."
- (interactive "P")
- (gnus-set-global-variables)
- (save-excursion
- (gnus-save-hidden-threads
- (let ((beg (point)))
- ;; We check that there are unread articles.
- (when (or all (gnus-summary-find-prev))
- (gnus-summary-catchup all t beg)))))
- (gnus-summary-position-point))
-
-(defun gnus-summary-catchup-all (&optional quietly)
- "Mark all articles in this newsgroup as read."
- (interactive "P")
- (gnus-set-global-variables)
- (gnus-summary-catchup t quietly))
-
-(defun gnus-summary-catchup-and-exit (&optional all quietly)
- "Mark all articles not marked as unread in this newsgroup as read, then exit.
-If prefix argument ALL is non-nil, all articles are marked as read."
- (interactive "P")
- (gnus-set-global-variables)
- (gnus-summary-catchup all quietly nil 'fast)
- ;; Select next newsgroup or exit.
- (if (eq gnus-auto-select-next 'quietly)
- (gnus-summary-next-group nil)
- (gnus-summary-exit)))
-
-(defun gnus-summary-catchup-all-and-exit (&optional quietly)
- "Mark all articles in this newsgroup as read, and then exit."
- (interactive "P")
- (gnus-set-global-variables)
- (gnus-summary-catchup-and-exit t quietly))
-
-;; Suggested by "Arne Eofsson" <arne@hodgkin.mbi.ucla.edu>.
-(defun gnus-summary-catchup-and-goto-next-group (&optional all)
- "Mark all articles in this group as read and select the next group.
-If given a prefix, mark all articles, unread as well as ticked, as
-read."
- (interactive "P")
- (gnus-set-global-variables)
- (save-excursion
- (gnus-summary-catchup all))
- (gnus-summary-next-article t nil nil t))
-
-;; Thread-based commands.
-
-(defun gnus-summary-articles-in-thread (&optional article)
- "Return a list of all articles in the current thread.
-If ARTICLE is non-nil, return all articles in the thread that starts
-with that article."
- (let* ((article (or article (gnus-summary-article-number)))
- (data (gnus-data-find-list article))
- (top-level (gnus-data-level (car data)))
- (top-subject
- (cond ((null gnus-thread-operation-ignore-subject)
- (gnus-simplify-subject-re
- (mail-header-subject (gnus-data-header (car data)))))
- ((eq gnus-thread-operation-ignore-subject 'fuzzy)
- (gnus-simplify-subject-fuzzy
- (mail-header-subject (gnus-data-header (car data)))))
- (t nil)))
- (end-point (save-excursion
- (if (gnus-summary-go-to-next-thread)
- (point) (point-max))))
- articles)
- (while (and data
- (< (gnus-data-pos (car data)) end-point))
- (when (or (not top-subject)
- (string= top-subject
- (if (eq gnus-thread-operation-ignore-subject 'fuzzy)
- (gnus-simplify-subject-fuzzy
- (mail-header-subject
- (gnus-data-header (car data))))
- (gnus-simplify-subject-re
- (mail-header-subject
- (gnus-data-header (car data)))))))
- (push (gnus-data-number (car data)) articles))
- (unless (and (setq data (cdr data))
- (> (gnus-data-level (car data)) top-level))
- (setq data nil)))
- ;; Return the list of articles.
- (nreverse articles)))
-
-(defun gnus-summary-rethread-current ()
- "Rethread the thread the current article is part of."
- (interactive)
- (gnus-set-global-variables)
- (let* ((gnus-show-threads t)
- (article (gnus-summary-article-number))
- (id (mail-header-id (gnus-summary-article-header)))
- (gnus-newsgroup-threads (list (gnus-id-to-thread (gnus-root-id id)))))
- (unless id
- (error "No article on the current line"))
- (gnus-rebuild-thread id)
- (gnus-summary-goto-subject article)))
-
-(defun gnus-summary-reparent-thread ()
- "Make current article child of the marked (or previous) article.
-
-Note that the re-threading will only work if `gnus-thread-ignore-subject'
-is non-nil or the Subject: of both articles are the same."
- (interactive)
- (or (not (gnus-group-read-only-p))
- (error "The current newsgroup does not support article editing."))
- (or (<= (length gnus-newsgroup-processable) 1)
- (error "No more than one article may be marked."))
- (save-window-excursion
- (let ((gnus-article-buffer " *reparent*")
- (current-article (gnus-summary-article-number))
- ; first grab the marked article, otherwise one line up.
- (parent-article (if (not (null gnus-newsgroup-processable))
- (car gnus-newsgroup-processable)
- (save-excursion
- (if (eq (forward-line -1) 0)
- (gnus-summary-article-number)
- (error "Beginning of summary buffer."))))))
- (or (not (eq current-article parent-article))
- (error "An article may not be self-referential."))
- (let ((message-id (mail-header-id
- (gnus-summary-article-header parent-article))))
- (or (and message-id (not (equal message-id "")))
- (error "No message-id in desired parent."))
- (gnus-summary-select-article t t nil current-article)
- (set-buffer gnus-article-buffer)
- (setq buffer-read-only nil)
- (let ((buf (format "%s" (buffer-string))))
- (erase-buffer)
- (insert buf))
- (goto-char (point-min))
- (if (search-forward-regexp "^References: " nil t)
- (insert message-id " " )
- (insert "References: " message-id "\n"))
- (or (gnus-request-replace-article current-article
- (car gnus-article-current)
- gnus-article-buffer)
- (error "Couldn't replace article."))
- (set-buffer gnus-summary-buffer)
- (gnus-summary-unmark-all-processable)
- (gnus-summary-rethread-current)
- (gnus-message 3 "Article %d is now the child of article %d."
- current-article parent-article)))))
-
-(defun gnus-summary-toggle-threads (&optional arg)
- "Toggle showing conversation threads.
-If ARG is positive number, turn showing conversation threads on."
- (interactive "P")
- (gnus-set-global-variables)
- (let ((current (or (gnus-summary-article-number) gnus-newsgroup-end)))
- (setq gnus-show-threads
- (if (null arg) (not gnus-show-threads)
- (> (prefix-numeric-value arg) 0)))
- (gnus-summary-prepare)
- (gnus-summary-goto-subject current)
- (gnus-summary-position-point)))
-
-(defun gnus-summary-show-all-threads ()
- "Show all threads."
- (interactive)
- (gnus-set-global-variables)
- (save-excursion
- (let ((buffer-read-only nil))
- (subst-char-in-region (point-min) (point-max) ?\^M ?\n t)))
- (gnus-summary-position-point))
-
-(defun gnus-summary-show-thread ()
- "Show thread subtrees.
-Returns nil if no thread was there to be shown."
- (interactive)
- (gnus-set-global-variables)
- (let ((buffer-read-only nil)
- (orig (point))
- ;; first goto end then to beg, to have point at beg after let
- (end (progn (end-of-line) (point)))
- (beg (progn (beginning-of-line) (point))))
- (prog1
- ;; Any hidden lines here?
- (search-forward "\r" end t)
- (subst-char-in-region beg end ?\^M ?\n t)
- (goto-char orig)
- (gnus-summary-position-point))))
-
-(defun gnus-summary-hide-all-threads ()
- "Hide all thread subtrees."
- (interactive)
- (gnus-set-global-variables)
- (save-excursion
- (goto-char (point-min))
- (gnus-summary-hide-thread)
- (while (zerop (gnus-summary-next-thread 1 t))
- (gnus-summary-hide-thread)))
- (gnus-summary-position-point))
-
-(defun gnus-summary-hide-thread ()
- "Hide thread subtrees.
-Returns nil if no threads were there to be hidden."
- (interactive)
- (gnus-set-global-variables)
- (let ((buffer-read-only nil)
- (start (point))
- (article (gnus-summary-article-number)))
- (goto-char start)
- ;; Go forward until either the buffer ends or the subthread
- ;; ends.
- (when (and (not (eobp))
- (or (zerop (gnus-summary-next-thread 1 t))
- (goto-char (point-max))))
- (prog1
- (if (and (> (point) start)
- (search-backward "\n" start t))
- (progn
- (subst-char-in-region start (point) ?\n ?\^M)
- (gnus-summary-goto-subject article))
- (goto-char start)
- nil)
- ;;(gnus-summary-position-point)
- ))))
-
-(defun gnus-summary-go-to-next-thread (&optional previous)
- "Go to the same level (or less) next thread.
-If PREVIOUS is non-nil, go to previous thread instead.
-Return the article number moved to, or nil if moving was impossible."
- (let ((level (gnus-summary-thread-level))
- (way (if previous -1 1))
- (beg (point)))
- (forward-line way)
- (while (and (not (eobp))
- (< level (gnus-summary-thread-level)))
- (forward-line way))
- (if (eobp)
- (progn
- (goto-char beg)
- nil)
- (setq beg (point))
- (prog1
- (gnus-summary-article-number)
- (goto-char beg)))))
-
-(defun gnus-summary-go-to-next-thread-old (&optional previous)
- "Go to the same level (or less) next thread.
-If PREVIOUS is non-nil, go to previous thread instead.
-Return the article number moved to, or nil if moving was impossible."
- (if (and (eq gnus-summary-make-false-root 'dummy)
- (gnus-summary-article-intangible-p))
- (let ((beg (point)))
- (while (and (zerop (forward-line 1))
- (not (gnus-summary-article-intangible-p))
- (not (zerop (save-excursion
- (gnus-summary-thread-level))))))
- (if (eobp)
- (progn
- (goto-char beg)
- nil)
- (point)))
- (let* ((level (gnus-summary-thread-level))
- (article (gnus-summary-article-number))
- (data (cdr (gnus-data-find-list article (gnus-data-list previous))))
- oart)
- (while data
- (if (<= (gnus-data-level (car data)) level)
- (setq oart (gnus-data-number (car data))
- data nil)
- (setq data (cdr data))))
- (and oart
- (gnus-summary-goto-subject oart)))))
-
-(defun gnus-summary-next-thread (n &optional silent)
- "Go to the same level next N'th thread.
-If N is negative, search backward instead.
-Returns the difference between N and the number of skips actually
-done.
-
-If SILENT, don't output messages."
- (interactive "p")
- (gnus-set-global-variables)
- (let ((backward (< n 0))
- (n (abs n))
- old dum int)
- (while (and (> n 0)
- (gnus-summary-go-to-next-thread backward))
- (decf n))
- (unless silent
- (gnus-summary-position-point))
- (when (and (not silent) (/= 0 n))
- (gnus-message 7 "No more threads"))
- n))
-
-(defun gnus-summary-prev-thread (n)
- "Go to the same level previous N'th thread.
-Returns the difference between N and the number of skips actually
-done."
- (interactive "p")
- (gnus-set-global-variables)
- (gnus-summary-next-thread (- n)))
-
-(defun gnus-summary-go-down-thread ()
- "Go down one level in the current thread."
- (let ((children (gnus-summary-article-children)))
- (and children
- (gnus-summary-goto-subject (car children)))))
-
-(defun gnus-summary-go-up-thread ()
- "Go up one level in the current thread."
- (let ((parent (gnus-summary-article-parent)))
- (and parent
- (gnus-summary-goto-subject parent))))
-
-(defun gnus-summary-down-thread (n)
- "Go down thread N steps.
-If N is negative, go up instead.
-Returns the difference between N and how many steps down that were
-taken."
- (interactive "p")
- (gnus-set-global-variables)
- (let ((up (< n 0))
- (n (abs n)))
- (while (and (> n 0)
- (if up (gnus-summary-go-up-thread)
- (gnus-summary-go-down-thread)))
- (setq n (1- n)))
- (gnus-summary-position-point)
- (if (/= 0 n) (gnus-message 7 "Can't go further"))
- n))
-
-(defun gnus-summary-up-thread (n)
- "Go up thread N steps.
-If N is negative, go up instead.
-Returns the difference between N and how many steps down that were
-taken."
- (interactive "p")
- (gnus-set-global-variables)
- (gnus-summary-down-thread (- n)))
-
-(defun gnus-summary-top-thread ()
- "Go to the top of the thread."
- (interactive)
- (gnus-set-global-variables)
- (while (gnus-summary-go-up-thread))
- (gnus-summary-article-number))
-
-(defun gnus-summary-kill-thread (&optional unmark)
- "Mark articles under current thread as read.
-If the prefix argument is positive, remove any kinds of marks.
-If the prefix argument is negative, tick articles instead."
- (interactive "P")
- (gnus-set-global-variables)
- (when unmark
- (setq unmark (prefix-numeric-value unmark)))
- (let ((articles (gnus-summary-articles-in-thread)))
- (save-excursion
- ;; Expand the thread.
- (gnus-summary-show-thread)
- ;; Mark all the articles.
- (while articles
- (gnus-summary-goto-subject (car articles))
- (cond ((null unmark)
- (gnus-summary-mark-article-as-read gnus-killed-mark))
- ((> unmark 0)
- (gnus-summary-mark-article-as-unread gnus-unread-mark))
- (t
- (gnus-summary-mark-article-as-unread gnus-ticked-mark)))
- (setq articles (cdr articles))))
- ;; Hide killed subtrees.
- (and (null unmark)
- gnus-thread-hide-killed
- (gnus-summary-hide-thread))
- ;; If marked as read, go to next unread subject.
- (if (null unmark)
- ;; Go to next unread subject.
- (gnus-summary-next-subject 1 t)))
- (gnus-set-mode-line 'summary))
-
-;; Summary sorting commands
-
-(defun gnus-summary-sort-by-number (&optional reverse)
- "Sort summary buffer by article number.
-Argument REVERSE means reverse order."
- (interactive "P")
- (gnus-summary-sort 'number reverse))
-
-(defun gnus-summary-sort-by-author (&optional reverse)
- "Sort summary buffer by author name alphabetically.
-If case-fold-search is non-nil, case of letters is ignored.
-Argument REVERSE means reverse order."
- (interactive "P")
- (gnus-summary-sort 'author reverse))
-
-(defun gnus-summary-sort-by-subject (&optional reverse)
- "Sort summary buffer by subject alphabetically. `Re:'s are ignored.
-If case-fold-search is non-nil, case of letters is ignored.
-Argument REVERSE means reverse order."
- (interactive "P")
- (gnus-summary-sort 'subject reverse))
-
-(defun gnus-summary-sort-by-date (&optional reverse)
- "Sort summary buffer by date.
-Argument REVERSE means reverse order."
- (interactive "P")
- (gnus-summary-sort 'date reverse))
-
-(defun gnus-summary-sort-by-score (&optional reverse)
- "Sort summary buffer by score.
-Argument REVERSE means reverse order."
- (interactive "P")
- (gnus-summary-sort 'score reverse))
-
-(defun gnus-summary-sort (predicate reverse)
- "Sort summary buffer by PREDICATE. REVERSE means reverse order."
- (gnus-set-global-variables)
- (let* ((thread (intern (format "gnus-thread-sort-by-%s" predicate)))
- (article (intern (format "gnus-article-sort-by-%s" predicate)))
- (gnus-thread-sort-functions
- (list
- (if (not reverse)
- thread
- `(lambda (t1 t2)
- (,thread t2 t1)))))
- (gnus-article-sort-functions
- (list
- (if (not reverse)
- article
- `(lambda (t1 t2)
- (,article t2 t1)))))
- (buffer-read-only)
- (gnus-summary-prepare-hook nil))
- ;; We do the sorting by regenerating the threads.
- (gnus-summary-prepare)
- ;; Hide subthreads if needed.
- (when (and gnus-show-threads gnus-thread-hide-subtree)
- (gnus-summary-hide-all-threads)))
- ;; If in async mode, we send some info to the backend.
- (when gnus-newsgroup-async
- (gnus-request-asynchronous
- gnus-newsgroup-name gnus-newsgroup-data)))
-
-(defun gnus-sortable-date (date)
- "Make sortable string by string-lessp from DATE.
-Timezone package is used."
- (condition-case ()
- (progn
- (setq date (inline (timezone-fix-time
- date nil
- (aref (inline (timezone-parse-date date)) 4))))
- (inline
- (timezone-make-sortable-date
- (aref date 0) (aref date 1) (aref date 2)
- (inline
- (timezone-make-time-string
- (aref date 3) (aref date 4) (aref date 5))))))
- (error "")))
-
-;; Summary saving commands.
-
-(defun gnus-summary-save-article (&optional n not-saved)
- "Save the current article using the default saver function.
-If N is a positive number, save the N next articles.
-If N is a negative number, save the N previous articles.
-If N is nil and any articles have been marked with the process mark,
-save those articles instead.
-The variable `gnus-default-article-saver' specifies the saver function."
- (interactive "P")
- (gnus-set-global-variables)
- (let ((articles (gnus-summary-work-articles n))
- (save-buffer (save-excursion
- (nnheader-set-temp-buffer " *Gnus Save*")))
- file header article)
- (while articles
- (setq header (gnus-summary-article-header
- (setq article (pop articles))))
- (if (not (vectorp header))
- ;; This is a pseudo-article.
- (if (assq 'name header)
- (gnus-copy-file (cdr (assq 'name header)))
- (gnus-message 1 "Article %d is unsaveable" article))
- ;; This is a real article.
- (save-window-excursion
- (gnus-summary-select-article t nil nil article))
- (save-excursion
- (set-buffer save-buffer)
- (erase-buffer)
- (insert-buffer-substring gnus-original-article-buffer))
- (unless gnus-save-all-headers
- ;; Remove headers accoring to `gnus-saved-headers'.
- (let ((gnus-visible-headers
- (or gnus-saved-headers gnus-visible-headers))
- (gnus-article-buffer save-buffer))
- (gnus-article-hide-headers 1 t)))
- (save-window-excursion
- (if (not gnus-default-article-saver)
- (error "No default saver is defined.")
- ;; !!! Magic! The saving functions all save
- ;; `gnus-original-article-buffer' (or so they think),
- ;; but we bind that variable to our save-buffer.
- (set-buffer gnus-article-buffer)
- (let ((gnus-original-article-buffer save-buffer))
- (set-buffer gnus-summary-buffer)
- (setq file (funcall
- gnus-default-article-saver
- (cond
- ((not gnus-prompt-before-saving)
- 'default)
- ((eq gnus-prompt-before-saving 'always)
- nil)
- (t file)))))))
- (gnus-summary-remove-process-mark article)
- (unless not-saved
- (gnus-summary-set-saved-mark article))))
- (gnus-kill-buffer save-buffer)
- (gnus-summary-position-point)
- n))
-
-(defun gnus-summary-pipe-output (&optional arg)
- "Pipe the current article to a subprocess.
-If N is a positive number, pipe the N next articles.
-If N is a negative number, pipe the N previous articles.
-If N is nil and any articles have been marked with the process mark,
-pipe those articles instead."
- (interactive "P")
- (gnus-set-global-variables)
- (let ((gnus-default-article-saver 'gnus-summary-save-in-pipe))
- (gnus-summary-save-article arg t))
- (gnus-configure-windows 'pipe))
-
-(defun gnus-summary-save-article-mail (&optional arg)
- "Append the current article to an mail file.
-If N is a positive number, save the N next articles.
-If N is a negative number, save the N previous articles.
-If N is nil and any articles have been marked with the process mark,
-save those articles instead."
- (interactive "P")
- (gnus-set-global-variables)
- (let ((gnus-default-article-saver 'gnus-summary-save-in-mail))
- (gnus-summary-save-article arg)))
-
-(defun gnus-summary-save-article-rmail (&optional arg)
- "Append the current article to an rmail file.
-If N is a positive number, save the N next articles.
-If N is a negative number, save the N previous articles.
-If N is nil and any articles have been marked with the process mark,
-save those articles instead."
- (interactive "P")
- (gnus-set-global-variables)
- (let ((gnus-default-article-saver 'gnus-summary-save-in-rmail))
- (gnus-summary-save-article arg)))
-
-(defun gnus-summary-save-article-file (&optional arg)
- "Append the current article to a file.
-If N is a positive number, save the N next articles.
-If N is a negative number, save the N previous articles.
-If N is nil and any articles have been marked with the process mark,
-save those articles instead."
- (interactive "P")
- (gnus-set-global-variables)
- (let ((gnus-default-article-saver 'gnus-summary-save-in-file))
- (gnus-summary-save-article arg)))
-
-(defun gnus-summary-save-article-body-file (&optional arg)
- "Append the current article body to a file.
-If N is a positive number, save the N next articles.
-If N is a negative number, save the N previous articles.
-If N is nil and any articles have been marked with the process mark,
-save those articles instead."
- (interactive "P")
- (gnus-set-global-variables)
- (let ((gnus-default-article-saver 'gnus-summary-save-body-in-file))
- (gnus-summary-save-article arg)))
-
-(defun gnus-get-split-value (methods)
- "Return a value based on the split METHODS."
- (let (split-name method result match)
- (when methods
- (save-excursion
- (set-buffer gnus-original-article-buffer)
- (save-restriction
- (nnheader-narrow-to-headers)
- (while methods
- (goto-char (point-min))
- (setq method (pop methods))
- (setq match (car method))
- (when (cond
- ((stringp match)
- ;; Regular expression.
- (condition-case ()
- (re-search-forward match nil t)
- (error nil)))
- ((gnus-functionp match)
- ;; Function.
- (save-restriction
- (widen)
- (setq result (funcall match gnus-newsgroup-name))))
- ((consp match)
- ;; Form.
- (save-restriction
- (widen)
- (setq result (eval match)))))
- (setq split-name (append (cdr method) split-name))
- (cond ((stringp result)
- (push result split-name))
- ((consp result)
- (setq split-name (append result split-name)))))))))
- split-name))
-
-(defun gnus-read-move-group-name (prompt default articles prefix)
- "Read a group name."
- (let* ((split-name (gnus-get-split-value gnus-move-split-methods))
- (minibuffer-confirm-incomplete nil) ; XEmacs
- group-map
- (dum (mapatoms
- (lambda (g)
- (and (boundp g)
- (symbol-name g)
- (memq 'respool
- (assoc (symbol-name
- (car (gnus-find-method-for-group
- (symbol-name g))))
- gnus-valid-select-methods))
- (push (list (symbol-name g)) group-map)))
- gnus-active-hashtb))
- (prom
- (format "%s %s to:"
- prompt
- (if (> (length articles) 1)
- (format "these %d articles" (length articles))
- "this article")))
- (to-newsgroup
- (cond
- ((null split-name)
- (gnus-completing-read default prom
- group-map nil nil prefix
- 'gnus-group-history))
- ((= 1 (length split-name))
- (gnus-completing-read (car split-name) prom group-map
- nil nil nil
- 'gnus-group-history))
- (t
- (gnus-completing-read nil prom
- (mapcar (lambda (el) (list el))
- (nreverse split-name))
- nil nil nil
- 'gnus-group-history)))))
- (when to-newsgroup
- (if (or (string= to-newsgroup "")
- (string= to-newsgroup prefix))
- (setq to-newsgroup (or default "")))
- (or (gnus-active to-newsgroup)
- (gnus-activate-group to-newsgroup)
- (if (gnus-y-or-n-p (format "No such group: %s. Create it? "
- to-newsgroup))
- (or (and (gnus-request-create-group
- to-newsgroup (gnus-group-name-to-method to-newsgroup))
- (gnus-activate-group to-newsgroup nil nil
- (gnus-group-name-to-method
- to-newsgroup)))
- (error "Couldn't create group %s" to-newsgroup)))
- (error "No such group: %s" to-newsgroup)))
- to-newsgroup))
-
-(defun gnus-read-save-file-name (prompt default-name)
- (let* ((split-name (gnus-get-split-value gnus-split-methods))
- (file
- ;; Let the split methods have their say.
- (cond
- ;; No split name was found.
- ((null split-name)
- (read-file-name
- (concat prompt " (default "
- (file-name-nondirectory default-name) ") ")
- (file-name-directory default-name)
- default-name))
- ;; A single split name was found
- ((= 1 (length split-name))
- (let* ((name (car split-name))
- (dir (cond ((file-directory-p name)
- (file-name-as-directory name))
- ((file-exists-p name) name)
- (t gnus-article-save-directory))))
- (read-file-name
- (concat prompt " (default " name ") ")
- dir name)))
- ;; A list of splits was found.
- (t
- (setq split-name (nreverse split-name))
- (let (result)
- (let ((file-name-history (nconc split-name file-name-history)))
- (setq result
- (read-file-name
- (concat prompt " (`M-p' for defaults) ")
- gnus-article-save-directory
- (car split-name))))
- (car (push result file-name-history)))))))
- ;; If we have read a directory, we append the default file name.
- (when (file-directory-p file)
- (setq file (concat (file-name-as-directory file)
- (file-name-nondirectory default-name))))
- ;; Possibly translate some charaters.
- (nnheader-translate-file-chars file)))
-
-(defun gnus-article-archive-name (group)
- "Return the first instance of an \"Archive-name\" in the current buffer."
- (let ((case-fold-search t))
- (when (re-search-forward "archive-name: *\\([^ \n\t]+\\)[ \t]*$" nil t)
- (match-string 1))))
-
-(defun gnus-summary-save-in-rmail (&optional filename)
- "Append this article to Rmail file.
-Optional argument FILENAME specifies file name.
-Directory to save to is default to `gnus-article-save-directory'."
- (interactive)
- (gnus-set-global-variables)
- (let ((default-name
- (funcall gnus-rmail-save-name gnus-newsgroup-name
- gnus-current-headers gnus-newsgroup-last-rmail)))
- (setq filename
- (cond ((eq filename 'default)
- default-name)
- (filename filename)
- (t (gnus-read-save-file-name
- "Save in rmail file:" default-name))))
- (gnus-make-directory (file-name-directory filename))
- (gnus-eval-in-buffer-window gnus-original-article-buffer
- (save-excursion
- (save-restriction
- (widen)
- (gnus-output-to-rmail filename))))
- ;; Remember the directory name to save articles
- (setq gnus-newsgroup-last-rmail filename)))
-
-(defun gnus-summary-save-in-mail (&optional filename)
- "Append this article to Unix mail file.
-Optional argument FILENAME specifies file name.
-Directory to save to is default to `gnus-article-save-directory'."
- (interactive)
- (gnus-set-global-variables)
- (let ((default-name
- (funcall gnus-mail-save-name gnus-newsgroup-name
- gnus-current-headers gnus-newsgroup-last-mail)))
- (setq filename
- (cond ((eq filename 'default)
- default-name)
- (filename filename)
- (t (gnus-read-save-file-name
- "Save in Unix mail file:" default-name))))
- (setq filename
- (expand-file-name filename
- (and default-name
- (file-name-directory default-name))))
- (gnus-make-directory (file-name-directory filename))
- (gnus-eval-in-buffer-window gnus-original-article-buffer
- (save-excursion
- (save-restriction
- (widen)
- (if (and (file-readable-p filename) (mail-file-babyl-p filename))
- (gnus-output-to-rmail filename)
- (let ((mail-use-rfc822 t))
- (rmail-output filename 1 t t))))))
- ;; Remember the directory name to save articles.
- (setq gnus-newsgroup-last-mail filename)))
-
-(defun gnus-summary-save-in-file (&optional filename)
- "Append this article to file.
-Optional argument FILENAME specifies file name.
-Directory to save to is default to `gnus-article-save-directory'."
- (interactive)
- (gnus-set-global-variables)
- (let ((default-name
- (funcall gnus-file-save-name gnus-newsgroup-name
- gnus-current-headers gnus-newsgroup-last-file)))
- (setq filename
- (cond ((eq filename 'default)
- default-name)
- (filename filename)
- (t (gnus-read-save-file-name
- "Save in file:" default-name))))
- (gnus-make-directory (file-name-directory filename))
- (gnus-eval-in-buffer-window gnus-original-article-buffer
- (save-excursion
- (save-restriction
- (widen)
- (gnus-output-to-file filename))))
- ;; Remember the directory name to save articles.
- (setq gnus-newsgroup-last-file filename)))
-
-(defun gnus-summary-save-body-in-file (&optional filename)
- "Append this article body to a file.
-Optional argument FILENAME specifies file name.
-The directory to save in defaults to `gnus-article-save-directory'."
- (interactive)
- (gnus-set-global-variables)
- (let ((default-name
- (funcall gnus-file-save-name gnus-newsgroup-name
- gnus-current-headers gnus-newsgroup-last-file)))
- (setq filename
- (cond ((eq filename 'default)
- default-name)
- (filename filename)
- (t (gnus-read-save-file-name
- "Save body in file:" default-name))))
- (gnus-make-directory (file-name-directory filename))
- (gnus-eval-in-buffer-window gnus-original-article-buffer
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (and (search-forward "\n\n" nil t)
- (narrow-to-region (point) (point-max)))
- (gnus-output-to-file filename))))
- ;; Remember the directory name to save articles.
- (setq gnus-newsgroup-last-file filename)))
-
-(defun gnus-summary-save-in-pipe (&optional command)
- "Pipe this article to subprocess."
- (interactive)
- (gnus-set-global-variables)
- (setq command
- (cond ((eq command 'default)
- gnus-last-shell-command)
- (command command)
- (t (read-string "Shell command on article: "
- gnus-last-shell-command))))
- (if (string-equal command "")
- (setq command gnus-last-shell-command))
- (gnus-eval-in-buffer-window gnus-article-buffer
- (save-restriction
- (widen)
- (shell-command-on-region (point-min) (point-max) command nil)))
- (setq gnus-last-shell-command command))
-
-;; Summary extract commands
-
-(defun gnus-summary-insert-pseudos (pslist &optional not-view)
- (let ((buffer-read-only nil)
- (article (gnus-summary-article-number))
- after-article b e)
- (or (gnus-summary-goto-subject article)
- (error (format "No such article: %d" article)))
- (gnus-summary-position-point)
- ;; If all commands are to be bunched up on one line, we collect
- ;; them here.
- (if gnus-view-pseudos-separately
- ()
- (let ((ps (setq pslist (sort pslist 'gnus-pseudos<)))
- files action)
- (while ps
- (setq action (cdr (assq 'action (car ps))))
- (setq files (list (cdr (assq 'name (car ps)))))
- (while (and ps (cdr ps)
- (string= (or action "1")
- (or (cdr (assq 'action (cadr ps))) "2")))
- (setq files (cons (cdr (assq 'name (cadr ps))) files))
- (setcdr ps (cddr ps)))
- (if (not files)
- ()
- (if (not (string-match "%s" action))
- (setq files (cons " " files)))
- (setq files (cons " " files))
- (and (assq 'execute (car ps))
- (setcdr (assq 'execute (car ps))
- (funcall (if (string-match "%s" action)
- 'format 'concat)
- action
- (mapconcat (lambda (f) f) files " ")))))
- (setq ps (cdr ps)))))
- (if (and gnus-view-pseudos (not not-view))
- (while pslist
- (and (assq 'execute (car pslist))
- (gnus-execute-command (cdr (assq 'execute (car pslist)))
- (eq gnus-view-pseudos 'not-confirm)))
- (setq pslist (cdr pslist)))
- (save-excursion
- (while pslist
- (setq after-article (or (cdr (assq 'article (car pslist)))
- (gnus-summary-article-number)))
- (gnus-summary-goto-subject after-article)
- (forward-line 1)
- (setq b (point))
- (insert " " (file-name-nondirectory
- (cdr (assq 'name (car pslist))))
- ": " (or (cdr (assq 'execute (car pslist))) "") "\n")
- (setq e (point))
- (forward-line -1) ; back to `b'
- (gnus-add-text-properties
- b (1- e) (list 'gnus-number gnus-reffed-article-number
- gnus-mouse-face-prop gnus-mouse-face))
- (gnus-data-enter
- after-article gnus-reffed-article-number
- gnus-unread-mark b (car pslist) 0 (- e b))
- (push gnus-reffed-article-number gnus-newsgroup-unreads)
- (setq gnus-reffed-article-number (1- gnus-reffed-article-number))
- (setq pslist (cdr pslist)))))))
-
-(defun gnus-pseudos< (p1 p2)
- (let ((c1 (cdr (assq 'action p1)))
- (c2 (cdr (assq 'action p2))))
- (and c1 c2 (string< c1 c2))))
-
-(defun gnus-request-pseudo-article (props)
- (cond ((assq 'execute props)
- (gnus-execute-command (cdr (assq 'execute props)))))
- (let ((gnus-current-article (gnus-summary-article-number)))
- (run-hooks 'gnus-mark-article-hook)))
-
-(defun gnus-execute-command (command &optional automatic)
- (save-excursion
- (gnus-article-setup-buffer)
- (set-buffer gnus-article-buffer)
- (setq buffer-read-only nil)
- (let ((command (if automatic command (read-string "Command: " command)))
- ;; Just binding this here doesn't help, because there might
- ;; be output from the process after exiting the scope of
- ;; this `let'.
- ;; (buffer-read-only nil)
- )
- (erase-buffer)
- (insert "$ " command "\n\n")
- (if gnus-view-pseudo-asynchronously
- (start-process "gnus-execute" nil shell-file-name
- shell-command-switch command)
- (call-process shell-file-name nil t nil
- shell-command-switch command)))))
-
-(defun gnus-copy-file (file &optional to)
- "Copy FILE to TO."
- (interactive
- (list (read-file-name "Copy file: " default-directory)
- (read-file-name "Copy file to: " default-directory)))
- (gnus-set-global-variables)
- (or to (setq to (read-file-name "Copy file to: " default-directory)))
- (and (file-directory-p to)
- (setq to (concat (file-name-as-directory to)
- (file-name-nondirectory file))))
- (copy-file file to))
-
-;; Summary kill commands.
-
-(defun gnus-summary-edit-global-kill (article)
- "Edit the \"global\" kill file."
- (interactive (list (gnus-summary-article-number)))
- (gnus-set-global-variables)
- (gnus-group-edit-global-kill article))
-
-(defun gnus-summary-edit-local-kill ()
- "Edit a local kill file applied to the current newsgroup."
- (interactive)
- (gnus-set-global-variables)
- (setq gnus-current-headers (gnus-summary-article-header))
- (gnus-set-global-variables)
- (gnus-group-edit-local-kill
- (gnus-summary-article-number) gnus-newsgroup-name))
-
-
-;;;
-;;; Gnus article mode
-;;;
-
-(put 'gnus-article-mode 'mode-class 'special)
-
-(if gnus-article-mode-map
- nil
- (setq gnus-article-mode-map (make-keymap))
- (suppress-keymap gnus-article-mode-map)
-
- (gnus-define-keys gnus-article-mode-map
- " " gnus-article-goto-next-page
- "\177" gnus-article-goto-prev-page
- [delete] gnus-article-goto-prev-page
- "\C-c^" gnus-article-refer-article
- "h" gnus-article-show-summary
- "s" gnus-article-show-summary
- "\C-c\C-m" gnus-article-mail
- "?" gnus-article-describe-briefly
- gnus-mouse-2 gnus-article-push-button
- "\r" gnus-article-press-button
- "\t" gnus-article-next-button
- "\M-\t" gnus-article-prev-button
- "<" beginning-of-buffer
- ">" end-of-buffer
- "\C-c\C-i" gnus-info-find-node
- "\C-c\C-b" gnus-bug)
-
- (substitute-key-definition
- 'undefined 'gnus-article-read-summary-keys gnus-article-mode-map))
-
-(defun gnus-article-mode ()
- "Major mode for displaying an article.
-
-All normal editing commands are switched off.
-
-The following commands are available:
-
-\\<gnus-article-mode-map>
-\\[gnus-article-next-page]\t Scroll the article one page forwards
-\\[gnus-article-prev-page]\t Scroll the article one page backwards
-\\[gnus-article-refer-article]\t Go to the article referred to by an article id near point
-\\[gnus-article-show-summary]\t Display the summary buffer
-\\[gnus-article-mail]\t Send a reply to the address near point
-\\[gnus-article-describe-briefly]\t Describe the current mode briefly
-\\[gnus-info-find-node]\t Go to the Gnus info node"
- (interactive)
- (when (and menu-bar-mode
- (gnus-visual-p 'article-menu 'menu))
- (gnus-article-make-menu-bar))
- (kill-all-local-variables)
- (gnus-simplify-mode-line)
- (setq mode-name "Article")
- (setq major-mode 'gnus-article-mode)
- (make-local-variable 'minor-mode-alist)
- (or (assq 'gnus-show-mime minor-mode-alist)
- (setq minor-mode-alist
- (cons (list 'gnus-show-mime " MIME") minor-mode-alist)))
- (use-local-map gnus-article-mode-map)
- (make-local-variable 'page-delimiter)
- (setq page-delimiter gnus-page-delimiter)
- (buffer-disable-undo (current-buffer))
- (setq buffer-read-only t) ;Disable modification
- (run-hooks 'gnus-article-mode-hook))
-
-(defun gnus-article-setup-buffer ()
- "Initialize the article buffer."
- (let* ((name (if gnus-single-article-buffer "*Article*"
- (concat "*Article " gnus-newsgroup-name "*")))
- (original
- (progn (string-match "\\*Article" name)
- (concat " *Original Article"
- (substring name (match-end 0))))))
- (setq gnus-article-buffer name)
- (setq gnus-original-article-buffer original)
- ;; This might be a variable local to the summary buffer.
- (unless gnus-single-article-buffer
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (setq gnus-article-buffer name)
- (setq gnus-original-article-buffer original)
- (gnus-set-global-variables))
- (make-local-variable 'gnus-summary-buffer))
- ;; Init original article buffer.
- (save-excursion
- (set-buffer (get-buffer-create gnus-original-article-buffer))
- (buffer-disable-undo (current-buffer))
- (setq major-mode 'gnus-original-article-mode)
- (make-local-variable 'gnus-original-article))
- (if (get-buffer name)
- (save-excursion
- (set-buffer name)
- (buffer-disable-undo (current-buffer))
- (setq buffer-read-only t)
- (gnus-add-current-to-buffer-list)
- (or (eq major-mode 'gnus-article-mode)
- (gnus-article-mode))
- (current-buffer))
- (save-excursion
- (set-buffer (get-buffer-create name))
- (gnus-add-current-to-buffer-list)
- (gnus-article-mode)
- (current-buffer)))))
-
-;; Set article window start at LINE, where LINE is the number of lines
-;; from the head of the article.
-(defun gnus-article-set-window-start (&optional line)
- (set-window-start
- (get-buffer-window gnus-article-buffer t)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (goto-char (point-min))
- (if (not line)
- (point-min)
- (gnus-message 6 "Moved to bookmark")
- (search-forward "\n\n" nil t)
- (forward-line line)
- (point)))))
-
-(defun gnus-kill-all-overlays ()
- "Delete all overlays in the current buffer."
- (when (fboundp 'overlay-lists)
- (let* ((overlayss (overlay-lists))
- (buffer-read-only nil)
- (overlays (nconc (car overlayss) (cdr overlayss))))
- (while overlays
- (delete-overlay (pop overlays))))))
-
-(defun gnus-request-article-this-buffer (article group)
- "Get an article and insert it into this buffer."
- (let (do-update-line)
- (prog1
- (save-excursion
- (erase-buffer)
- (gnus-kill-all-overlays)
- (setq group (or group gnus-newsgroup-name))
-
- ;; Open server if it has closed.
- (gnus-check-server (gnus-find-method-for-group group))
-
- ;; Using `gnus-request-article' directly will insert the article into
- ;; `nntp-server-buffer' - so we'll save some time by not having to
- ;; copy it from the server buffer into the article buffer.
-
- ;; We only request an article by message-id when we do not have the
- ;; headers for it, so we'll have to get those.
- (when (stringp article)
- (let ((gnus-override-method gnus-refer-article-method))
- (gnus-read-header article)))
-
- ;; If the article number is negative, that means that this article
- ;; doesn't belong in this newsgroup (possibly), so we find its
- ;; message-id and request it by id instead of number.
- (when (and (numberp article)
- gnus-summary-buffer
- (get-buffer gnus-summary-buffer)
- (buffer-name (get-buffer gnus-summary-buffer)))
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (let ((header (gnus-summary-article-header article)))
- (if (< article 0)
- (cond
- ((memq article gnus-newsgroup-sparse)
- ;; This is a sparse gap article.
- (setq do-update-line article)
- (setq article (mail-header-id header))
- (let ((gnus-override-method gnus-refer-article-method))
- (gnus-read-header article))
- (setq gnus-newsgroup-sparse
- (delq article gnus-newsgroup-sparse)))
- ((vectorp header)
- ;; It's a real article.
- (setq article (mail-header-id header)))
- (t
- ;; It is an extracted pseudo-article.
- (setq article 'pseudo)
- (gnus-request-pseudo-article header))))
-
- (let ((method (gnus-find-method-for-group
- gnus-newsgroup-name)))
- (if (not (eq (car method) 'nneething))
- ()
- (let ((dir (concat (file-name-as-directory (nth 1 method))
- (mail-header-subject header))))
- (if (file-directory-p dir)
- (progn
- (setq article 'nneething)
- (gnus-group-enter-directory dir)))))))))
-
- (cond
- ;; Refuse to select canceled articles.
- ((and (numberp article)
- gnus-summary-buffer
- (get-buffer gnus-summary-buffer)
- (buffer-name (get-buffer gnus-summary-buffer))
- (eq (cdr (save-excursion
- (set-buffer gnus-summary-buffer)
- (assq article gnus-newsgroup-reads)))
- gnus-canceled-mark))
- nil)
- ;; We first check `gnus-original-article-buffer'.
- ((and (get-buffer gnus-original-article-buffer)
- (numberp article)
- (save-excursion
- (set-buffer gnus-original-article-buffer)
- (and (equal (car gnus-original-article) group)
- (eq (cdr gnus-original-article) article))))
- (insert-buffer-substring gnus-original-article-buffer)
- 'article)
- ;; Check the backlog.
- ((and gnus-keep-backlog
- (gnus-backlog-request-article group article (current-buffer)))
- 'article)
- ;; Check the cache.
- ((and gnus-use-cache
- (numberp article)
- (gnus-cache-request-article article group))
- 'article)
- ;; Get the article and put into the article buffer.
- ((or (stringp article) (numberp article))
- (let ((gnus-override-method
- (and (stringp article) gnus-refer-article-method))
- (buffer-read-only nil))
- (erase-buffer)
- (gnus-kill-all-overlays)
- (if (gnus-request-article article group (current-buffer))
- (progn
- (and gnus-keep-backlog
- (numberp article)
- (gnus-backlog-enter-article
- group article (current-buffer)))
- 'article))))
- ;; It was a pseudo.
- (t article)))
-
- ;; Take the article from the original article buffer
- ;; and place it in the buffer it's supposed to be in.
- (when (and (get-buffer gnus-article-buffer)
- ;;(numberp article)
- (equal (buffer-name (current-buffer))
- (buffer-name (get-buffer gnus-article-buffer))))
- (save-excursion
- (if (get-buffer gnus-original-article-buffer)
- (set-buffer (get-buffer gnus-original-article-buffer))
- (set-buffer (get-buffer-create gnus-original-article-buffer))
- (buffer-disable-undo (current-buffer))
- (setq major-mode 'gnus-original-article-mode)
- (setq buffer-read-only t)
- (gnus-add-current-to-buffer-list))
- (let (buffer-read-only)
- (erase-buffer)
- (insert-buffer-substring gnus-article-buffer))
- (setq gnus-original-article (cons group article))))
-
- ;; Update sparse articles.
- (when (and do-update-line
- (or (numberp article)
- (stringp article)))
- (let ((buf (current-buffer)))
- (set-buffer gnus-summary-buffer)
- (gnus-summary-update-article do-update-line)
- (gnus-summary-goto-subject do-update-line nil t)
- (set-window-point (get-buffer-window (current-buffer) t)
- (point))
- (set-buffer buf))))))
-
-(defun gnus-read-header (id &optional header)
- "Read the headers of article ID and enter them into the Gnus system."
- (let ((group gnus-newsgroup-name)
- (gnus-override-method
- (and (gnus-news-group-p gnus-newsgroup-name)
- gnus-refer-article-method))
- where)
- ;; First we check to see whether the header in question is already
- ;; fetched.
- (if (stringp id)
- ;; This is a Message-ID.
- (setq header (or header (gnus-id-to-header id)))
- ;; This is an article number.
- (setq header (or header (gnus-summary-article-header id))))
- (if (and header
- (not (memq (mail-header-number header) gnus-newsgroup-sparse)))
- ;; We have found the header.
- header
- ;; We have to really fetch the header to this article.
- (when (setq where (gnus-request-head id group))
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-max))
- (insert ".\n")
- (goto-char (point-min))
- (insert "211 ")
- (princ (cond
- ((numberp id) id)
- ((cdr where) (cdr where))
- (header (mail-header-number header))
- (t gnus-reffed-article-number))
- (current-buffer))
- (insert " Article retrieved.\n"))
- ;(when (and header
- ; (memq (mail-header-number header) gnus-newsgroup-sparse))
- ; (setcar (gnus-id-to-thread id) nil))
- (if (not (setq header (car (gnus-get-newsgroup-headers))))
- () ; Malformed head.
- (unless (memq (mail-header-number header) gnus-newsgroup-sparse)
- (if (and (stringp id)
- (not (string= (gnus-group-real-name group)
- (car where))))
- ;; If we fetched by Message-ID and the article came
- ;; from a different group, we fudge some bogus article
- ;; numbers for this article.
- (mail-header-set-number header gnus-reffed-article-number))
- (decf gnus-reffed-article-number)
- (gnus-remove-header (mail-header-number header))
- (push header gnus-newsgroup-headers)
- (setq gnus-current-headers header)
- (push (mail-header-number header) gnus-newsgroup-limit))
- header)))))
-
-(defun gnus-remove-header (number)
- "Remove header NUMBER from `gnus-newsgroup-headers'."
- (if (and gnus-newsgroup-headers
- (= number (mail-header-number (car gnus-newsgroup-headers))))
- (pop gnus-newsgroup-headers)
- (let ((headers gnus-newsgroup-headers))
- (while (and (cdr headers)
- (not (= number (mail-header-number (cadr headers)))))
- (pop headers))
- (when (cdr headers)
- (setcdr headers (cddr headers))))))
-
-(defun gnus-article-prepare (article &optional all-headers header)
- "Prepare ARTICLE in article mode buffer.
-ARTICLE should either be an article number or a Message-ID.
-If ARTICLE is an id, HEADER should be the article headers.
-If ALL-HEADERS is non-nil, no headers are hidden."
- (save-excursion
- ;; Make sure we start in a summary buffer.
- (unless (eq major-mode 'gnus-summary-mode)
- (set-buffer gnus-summary-buffer))
- (setq gnus-summary-buffer (current-buffer))
- ;; Make sure the connection to the server is alive.
- (unless (gnus-server-opened
- (gnus-find-method-for-group gnus-newsgroup-name))
- (gnus-check-server (gnus-find-method-for-group gnus-newsgroup-name))
- (gnus-request-group gnus-newsgroup-name t))
- (let* ((article (if header (mail-header-number header) article))
- (summary-buffer (current-buffer))
- (internal-hook gnus-article-internal-prepare-hook)
- (group gnus-newsgroup-name)
- result)
- (save-excursion
- (gnus-article-setup-buffer)
- (set-buffer gnus-article-buffer)
- ;; Deactivate active regions.
- (when (and (boundp 'transient-mark-mode)
- transient-mark-mode)
- (setq mark-active nil))
- (if (not (setq result (let ((buffer-read-only nil))
- (gnus-request-article-this-buffer
- article group))))
- ;; There is no such article.
- (save-excursion
- (when (and (numberp article)
- (not (memq article gnus-newsgroup-sparse)))
- (setq gnus-article-current
- (cons gnus-newsgroup-name article))
- (set-buffer gnus-summary-buffer)
- (setq gnus-current-article article)
- (gnus-summary-mark-article article gnus-canceled-mark))
- (unless (memq article gnus-newsgroup-sparse)
- (gnus-error
- 1 "No such article (may have expired or been canceled)")))
- (if (or (eq result 'pseudo) (eq result 'nneething))
- (progn
- (save-excursion
- (set-buffer summary-buffer)
- (setq gnus-last-article gnus-current-article
- gnus-newsgroup-history (cons gnus-current-article
- gnus-newsgroup-history)
- gnus-current-article 0
- gnus-current-headers nil
- gnus-article-current nil)
- (if (eq result 'nneething)
- (gnus-configure-windows 'summary)
- (gnus-configure-windows 'article))
- (gnus-set-global-variables))
- (gnus-set-mode-line 'article))
- ;; The result from the `request' was an actual article -
- ;; or at least some text that is now displayed in the
- ;; article buffer.
- (if (and (numberp article)
- (not (eq article gnus-current-article)))
- ;; Seems like a new article has been selected.
- ;; `gnus-current-article' must be an article number.
- (save-excursion
- (set-buffer summary-buffer)
- (setq gnus-last-article gnus-current-article
- gnus-newsgroup-history (cons gnus-current-article
- gnus-newsgroup-history)
- gnus-current-article article
- gnus-current-headers
- (gnus-summary-article-header gnus-current-article)
- gnus-article-current
- (cons gnus-newsgroup-name gnus-current-article))
- (unless (vectorp gnus-current-headers)
- (setq gnus-current-headers nil))
- (gnus-summary-show-thread)
- (run-hooks 'gnus-mark-article-hook)
- (gnus-set-mode-line 'summary)
- (and (gnus-visual-p 'article-highlight 'highlight)
- (run-hooks 'gnus-visual-mark-article-hook))
- ;; Set the global newsgroup variables here.
- ;; Suggested by Jim Sisolak
- ;; <sisolak@trans4.neep.wisc.edu>.
- (gnus-set-global-variables)
- (setq gnus-have-all-headers
- (or all-headers gnus-show-all-headers))
- (and gnus-use-cache
- (vectorp (gnus-summary-article-header article))
- (gnus-cache-possibly-enter-article
- group article
- (gnus-summary-article-header article)
- (memq article gnus-newsgroup-marked)
- (memq article gnus-newsgroup-dormant)
- (memq article gnus-newsgroup-unreads)))))
- (when (or (numberp article)
- (stringp article))
- ;; Hooks for getting information from the article.
- ;; This hook must be called before being narrowed.
- (let (buffer-read-only)
- (run-hooks 'internal-hook)
- (run-hooks 'gnus-article-prepare-hook)
- ;; Decode MIME message.
- (if gnus-show-mime
- (if (or (not gnus-strict-mime)
- (gnus-fetch-field "Mime-Version"))
- (funcall gnus-show-mime-method)
- (funcall gnus-decode-encoded-word-method)))
- ;; Perform the article display hooks.
- (run-hooks 'gnus-article-display-hook))
- ;; Do page break.
- (goto-char (point-min))
- (and gnus-break-pages (gnus-narrow-to-page)))
- (gnus-set-mode-line 'article)
- (gnus-configure-windows 'article)
- (goto-char (point-min))
- t))))))
-
-(defun gnus-article-show-all-headers ()
- "Show all article headers in article mode buffer."
- (save-excursion
- (gnus-article-setup-buffer)
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil))
- (gnus-unhide-text (point-min) (point-max)))))
-
-(defun gnus-article-hide-headers-if-wanted ()
- "Hide unwanted headers if `gnus-have-all-headers' is nil.
-Provided for backwards compatibility."
- (or (save-excursion (set-buffer gnus-summary-buffer) gnus-have-all-headers)
- gnus-inhibit-hiding
- (gnus-article-hide-headers)))
-
-(defsubst gnus-article-header-rank ()
- "Give the rank of the string HEADER as given by `gnus-sorted-header-list'."
- (let ((list gnus-sorted-header-list)
- (i 0))
- (while list
- (when (looking-at (car list))
- (setq list nil))
- (setq list (cdr list))
- (incf i))
- i))
-
-(defun gnus-article-hide-headers (&optional arg delete)
- "Toggle whether to hide unwanted headers and possibly sort them as well.
-If given a negative prefix, always show; if given a positive prefix,
-always hide."
- (interactive (gnus-hidden-arg))
- (if (gnus-article-check-hidden-text 'headers arg)
- ;; Show boring headers as well.
- (gnus-article-show-hidden-text 'boring-headers)
- ;; This function might be inhibited.
- (unless gnus-inhibit-hiding
- (save-excursion
- (set-buffer gnus-article-buffer)
- (save-restriction
- (let ((buffer-read-only nil)
- (props (nconc (list 'gnus-type 'headers)
- gnus-hidden-properties))
- (max (1+ (length gnus-sorted-header-list)))
- (ignored (when (not (stringp gnus-visible-headers))
- (cond ((stringp gnus-ignored-headers)
- gnus-ignored-headers)
- ((listp gnus-ignored-headers)
- (mapconcat 'identity gnus-ignored-headers
- "\\|")))))
- (visible
- (cond ((stringp gnus-visible-headers)
- gnus-visible-headers)
- ((and gnus-visible-headers
- (listp gnus-visible-headers))
- (mapconcat 'identity gnus-visible-headers "\\|"))))
- (inhibit-point-motion-hooks t)
- want-list beg)
- ;; First we narrow to just the headers.
- (widen)
- (goto-char (point-min))
- ;; Hide any "From " lines at the beginning of (mail) articles.
- (while (looking-at "From ")
- (forward-line 1))
- (unless (bobp)
- (if delete
- (delete-region (point-min) (point))
- (gnus-hide-text (point-min) (point) props)))
- ;; Then treat the rest of the header lines.
- (narrow-to-region
- (point)
- (progn (search-forward "\n\n" nil t) (forward-line -1) (point)))
- ;; Then we use the two regular expressions
- ;; `gnus-ignored-headers' and `gnus-visible-headers' to
- ;; select which header lines is to remain visible in the
- ;; article buffer.
- (goto-char (point-min))
- (while (re-search-forward "^[^ \t]*:" nil t)
- (beginning-of-line)
- ;; We add the headers we want to keep to a list and delete
- ;; them from the buffer.
- (gnus-put-text-property
- (point) (1+ (point)) 'message-rank
- (if (or (and visible (looking-at visible))
- (and ignored
- (not (looking-at ignored))))
- (gnus-article-header-rank)
- (+ 2 max)))
- (forward-line 1))
- (message-sort-headers-1)
- (when (setq beg (text-property-any
- (point-min) (point-max) 'message-rank (+ 2 max)))
- ;; We make the unwanted headers invisible.
- (if delete
- (delete-region beg (point-max))
- ;; Suggested by Sudish Joseph <joseph@cis.ohio-state.edu>.
- (gnus-hide-text-type beg (point-max) 'headers))
- ;; Work around XEmacs lossage.
- (gnus-put-text-property (point-min) beg 'invisible nil))))))))
-
-(defun gnus-article-hide-boring-headers (&optional arg)
- "Toggle hiding of headers that aren't very interesting.
-If given a negative prefix, always show; if given a positive prefix,
-always hide."
- (interactive (gnus-hidden-arg))
- (unless (gnus-article-check-hidden-text 'boring-headers arg)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (save-restriction
- (let ((buffer-read-only nil)
- (list gnus-boring-article-headers)
- (inhibit-point-motion-hooks t)
- elem)
- (nnheader-narrow-to-headers)
- (while list
- (setq elem (pop list))
- (goto-char (point-min))
- (cond
- ;; Hide empty headers.
- ((eq elem 'empty)
- (while (re-search-forward "^[^:]+:[ \t]\n[^ \t]" nil t)
- (forward-line -1)
- (gnus-hide-text-type
- (progn (beginning-of-line) (point))
- (progn
- (end-of-line)
- (if (re-search-forward "^[^ \t]" nil t)
- (match-beginning 0)
- (point-max)))
- 'boring-headers)))
- ;; Hide boring Newsgroups header.
- ((eq elem 'newsgroups)
- (when (equal (message-fetch-field "newsgroups")
- (gnus-group-real-name gnus-newsgroup-name))
- (gnus-article-hide-header "newsgroups")))
- ((eq elem 'followup-to)
- (when (equal (message-fetch-field "followup-to")
- (message-fetch-field "newsgroups"))
- (gnus-article-hide-header "followup-to")))
- ((eq elem 'reply-to)
- (let ((from (message-fetch-field "from"))
- (reply-to (message-fetch-field "reply-to")))
- (when (and
- from reply-to
- (equal
- (nth 1 (funcall gnus-extract-address-components from))
- (nth 1 (funcall gnus-extract-address-components
- reply-to))))
- (gnus-article-hide-header "reply-to"))))
- ((eq elem 'date)
- (let ((date (message-fetch-field "date")))
- (when (and date
- (< (gnus-days-between date (current-time-string))
- 4))
- (gnus-article-hide-header "date")))))))))))
-
-(defun gnus-article-hide-header (header)
- (save-excursion
- (goto-char (point-min))
- (when (re-search-forward (concat "^" header ":") nil t)
- (gnus-hide-text-type
- (progn (beginning-of-line) (point))
- (progn
- (end-of-line)
- (if (re-search-forward "^[^ \t]" nil t)
- (match-beginning 0)
- (point-max)))
- 'boring-headers))))
-
-;; Written by Per Abrahamsen <amanda@iesd.auc.dk>.
-(defun gnus-article-treat-overstrike ()
- "Translate overstrikes into bold text."
- (interactive)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil))
- (while (search-forward "\b" nil t)
- (let ((next (following-char))
- (previous (char-after (- (point) 2))))
- (cond
- ((eq next previous)
- (gnus-put-text-property (- (point) 2) (point) 'invisible t)
- (gnus-put-text-property (point) (1+ (point)) 'face 'bold))
- ((eq next ?_)
- (gnus-put-text-property (1- (point)) (1+ (point)) 'invisible t)
- (gnus-put-text-property
- (- (point) 2) (1- (point)) 'face 'underline))
- ((eq previous ?_)
- (gnus-put-text-property (- (point) 2) (point) 'invisible t)
- (gnus-put-text-property
- (point) (1+ (point)) 'face 'underline))))))))
-
-(defun gnus-article-word-wrap ()
- "Format too long lines."
- (interactive)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil))
- (widen)
- (goto-char (point-min))
- (search-forward "\n\n" nil t)
- (end-of-line 1)
- (let ((paragraph-start "^[>|#:<;* ]*[ \t]*$")
- (adaptive-fill-regexp "[ \t]*\\([|#:<;>*]+ *\\)?")
- (adaptive-fill-mode t))
- (while (not (eobp))
- (and (>= (current-column) (min fill-column (window-width)))
- (/= (preceding-char) ?:)
- (fill-paragraph nil))
- (end-of-line 2))))))
-
-(defun gnus-article-remove-cr ()
- "Remove carriage returns from an article."
- (interactive)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil))
- (goto-char (point-min))
- (while (search-forward "\r" nil t)
- (replace-match "" t t)))))
-
-(defun gnus-article-remove-trailing-blank-lines ()
- "Remove all trailing blank lines from the article."
- (interactive)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil))
- (goto-char (point-max))
- (delete-region
- (point)
- (progn
- (while (looking-at "^[ \t]*$")
- (forward-line -1))
- (forward-line 1)
- (point))))))
-
-(defun gnus-article-display-x-face (&optional force)
- "Look for an X-Face header and display it if present."
- (interactive (list 'force))
- (save-excursion
- (set-buffer gnus-article-buffer)
- ;; Delete the old process, if any.
- (when (process-status "gnus-x-face")
- (delete-process "gnus-x-face"))
- (let ((inhibit-point-motion-hooks t)
- (case-fold-search nil)
- from)
- (save-restriction
- (nnheader-narrow-to-headers)
- (setq from (message-fetch-field "from"))
- (goto-char (point-min))
- (when (and gnus-article-x-face-command
- (or force
- ;; Check whether this face is censored.
- (not gnus-article-x-face-too-ugly)
- (and gnus-article-x-face-too-ugly from
- (not (string-match gnus-article-x-face-too-ugly
- from))))
- ;; Has to be present.
- (re-search-forward "^X-Face: " nil t))
- ;; We now have the area of the buffer where the X-Face is stored.
- (let ((beg (point))
- (end (1- (re-search-forward "^\\($\\|[^ \t]\\)" nil t))))
- ;; We display the face.
- (if (symbolp gnus-article-x-face-command)
- ;; The command is a lisp function, so we call it.
- (if (gnus-functionp gnus-article-x-face-command)
- (funcall gnus-article-x-face-command beg end)
- (error "%s is not a function" gnus-article-x-face-command))
- ;; The command is a string, so we interpret the command
- ;; as a, well, command, and fork it off.
- (let ((process-connection-type nil))
- (process-kill-without-query
- (start-process
- "gnus-x-face" nil shell-file-name shell-command-switch
- gnus-article-x-face-command))
- (process-send-region "gnus-x-face" beg end)
- (process-send-eof "gnus-x-face")))))))))
-
-(defalias 'gnus-headers-decode-quoted-printable 'gnus-decode-rfc1522)
-(defun gnus-decode-rfc1522 ()
- "Hack to remove QP encoding from headers."
- (let ((case-fold-search t)
- (inhibit-point-motion-hooks t)
- (buffer-read-only nil)
- string)
- (save-restriction
- (narrow-to-region
- (goto-char (point-min))
- (or (search-forward "\n\n" nil t) (point-max)))
-
- (goto-char (point-min))
- (while (re-search-forward
- "=\\?iso-8859-1\\?q\\?\\([^?\t\n]*\\)\\?=" nil t)
- (setq string (match-string 1))
- (narrow-to-region (match-beginning 0) (match-end 0))
- (delete-region (point-min) (point-max))
- (insert string)
- (gnus-mime-decode-quoted-printable (goto-char (point-min)) (point-max))
- (subst-char-in-region (point-min) (point-max) ?_ ? )
- (widen)
- (goto-char (point-min))))))
-
-(defun gnus-article-de-quoted-unreadable (&optional force)
- "Do a naive translation of a quoted-printable-encoded article.
-This is in no way, shape or form meant as a replacement for real MIME
-processing, but is simply a stop-gap measure until MIME support is
-written.
-If FORCE, decode the article whether it is marked as quoted-printable
-or not."
- (interactive (list 'force))
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((case-fold-search t)
- (buffer-read-only nil)
- (type (gnus-fetch-field "content-transfer-encoding")))
- (gnus-decode-rfc1522)
- (when (or force
- (and type (string-match "quoted-printable" (downcase type))))
- (goto-char (point-min))
- (search-forward "\n\n" nil 'move)
- (gnus-mime-decode-quoted-printable (point) (point-max))))))
-
-(defun gnus-mime-decode-quoted-printable (from to)
- "Decode Quoted-Printable in the region between FROM and TO."
- (interactive "r")
- (goto-char from)
- (while (search-forward "=" to t)
- (cond ((eq (following-char) ?\n)
- (delete-char -1)
- (delete-char 1))
- ((looking-at "[0-9A-F][0-9A-F]")
- (subst-char-in-region
- (1- (point)) (point) ?=
- (hexl-hex-string-to-integer
- (buffer-substring (point) (+ 2 (point)))))
- (delete-char 2))
- ((looking-at "=")
- (delete-char 1))
- ((gnus-message 3 "Malformed MIME quoted-printable message")))))
-
-(defun gnus-article-hide-pgp (&optional arg)
- "Toggle hiding of any PGP headers and signatures in the current article.
-If given a negative prefix, always show; if given a positive prefix,
-always hide."
- (interactive (gnus-hidden-arg))
- (unless (gnus-article-check-hidden-text 'pgp arg)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((props (nconc (list 'gnus-type 'pgp) gnus-hidden-properties))
- buffer-read-only beg end)
- (widen)
- (goto-char (point-min))
- ;; Hide the "header".
- (and (search-forward "\n-----BEGIN PGP SIGNED MESSAGE-----\n" nil t)
- (gnus-hide-text (match-beginning 0) (match-end 0) props))
- (setq beg (point))
- ;; Hide the actual signature.
- (and (search-forward "\n-----BEGIN PGP SIGNATURE-----\n" nil t)
- (setq end (1+ (match-beginning 0)))
- (gnus-hide-text
- end
- (if (search-forward "\n-----END PGP SIGNATURE-----\n" nil t)
- (match-end 0)
- ;; Perhaps we shouldn't hide to the end of the buffer
- ;; if there is no end to the signature?
- (point-max))
- props))
- ;; Hide "- " PGP quotation markers.
- (when (and beg end)
- (narrow-to-region beg end)
- (goto-char (point-min))
- (while (re-search-forward "^- " nil t)
- (gnus-hide-text (match-beginning 0) (match-end 0) props))
- (widen))))))
-
-(defun gnus-article-hide-signature (&optional arg)
- "Hide the signature in the current article.
-If given a negative prefix, always show; if given a positive prefix,
-always hide."
- (interactive (gnus-hidden-arg))
- (unless (gnus-article-check-hidden-text 'signature arg)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (save-restriction
- (let ((buffer-read-only nil))
- (when (gnus-narrow-to-signature)
- (gnus-hide-text-type (point-min) (point-max) 'signature)))))))
-
-(defun gnus-article-strip-leading-blank-lines ()
- "Remove all blank lines from the beginning of the article."
- (interactive)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let (buffer-read-only)
- (goto-char (point-min))
- (when (search-forward "\n\n" nil t)
- (while (looking-at "[ \t]$")
- (gnus-delete-line))))))
-
-(defvar mime::preview/content-list)
-(defvar mime::preview-content-info/point-min)
-(defun gnus-narrow-to-signature ()
- "Narrow to the signature."
- (widen)
- (if (and (boundp 'mime::preview/content-list)
- mime::preview/content-list)
- (let ((pcinfo (car (last mime::preview/content-list))))
- (condition-case ()
- (narrow-to-region
- (funcall (intern "mime::preview-content-info/point-min") pcinfo)
- (point-max))
- (error nil))))
- (goto-char (point-max))
- (when (re-search-backward gnus-signature-separator nil t)
- (forward-line 1)
- (when (or (null gnus-signature-limit)
- (and (numberp gnus-signature-limit)
- (< (- (point-max) (point)) gnus-signature-limit))
- (and (gnus-functionp gnus-signature-limit)
- (funcall gnus-signature-limit))
- (and (stringp gnus-signature-limit)
- (not (re-search-forward gnus-signature-limit nil t))))
- (narrow-to-region (point) (point-max))
- t)))
-
-(defun gnus-hidden-arg ()
- "Return the current prefix arg as a number, or 0 if no prefix."
- (list (if current-prefix-arg
- (prefix-numeric-value current-prefix-arg)
- 0)))
-
-(defun gnus-article-check-hidden-text (type arg)
- "Return nil if hiding is necessary.
-Arg can be nil or a number. Nil and positive means hide, negative
-means show, 0 means toggle."
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((hide (gnus-article-hidden-text-p type)))
- (cond
- ((or (null arg)
- (> arg 0))
- nil)
- ((< arg 0)
- (gnus-article-show-hidden-text type))
- (t
- (if (eq hide 'hidden)
- (gnus-article-show-hidden-text type)
- nil))))))
-
-(defun gnus-article-hidden-text-p (type)
- "Say whether the current buffer contains hidden text of type TYPE."
- (let ((pos (text-property-any (point-min) (point-max) 'gnus-type type)))
- (when pos
- (if (get-text-property pos 'invisible)
- 'hidden
- 'shown))))
-
-(defun gnus-article-hide (&optional arg force)
- "Hide all the gruft in the current article.
-This means that PGP stuff, signatures, cited text and (some)
-headers will be hidden.
-If given a prefix, show the hidden text instead."
- (interactive (list current-prefix-arg 'force))
- (gnus-article-hide-headers arg)
- (gnus-article-hide-pgp arg)
- (gnus-article-hide-citation-maybe arg force)
- (gnus-article-hide-signature arg))
-
-(defun gnus-article-show-hidden-text (type &optional hide)
- "Show all hidden text of type TYPE.
-If HIDE, hide the text instead."
- (save-excursion
- (set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil)
- (inhibit-point-motion-hooks t)
- (beg (point-min)))
- (while (gnus-goto-char (text-property-any
- beg (point-max) 'gnus-type type))
- (setq beg (point))
- (forward-char)
- (if hide
- (gnus-hide-text beg (point) gnus-hidden-properties)
- (gnus-unhide-text beg (point)))
- (setq beg (point)))
- t)))
-
-(defvar gnus-article-time-units
- `((year . ,(* 365.25 24 60 60))
- (week . ,(* 7 24 60 60))
- (day . ,(* 24 60 60))
- (hour . ,(* 60 60))
- (minute . 60)
- (second . 1))
- "Mapping from time units to seconds.")
-
-(defun gnus-article-date-ut (&optional type highlight)
- "Convert DATE date to universal time in the current article.
-If TYPE is `local', convert to local time; if it is `lapsed', output
-how much time has lapsed since DATE."
- (interactive (list 'ut t))
- (let* ((header (or gnus-current-headers
- (gnus-summary-article-header) ""))
- (date (and (vectorp header) (mail-header-date header)))
- (date-regexp "^Date: \\|^X-Sent: ")
- (now (current-time))
- (inhibit-point-motion-hooks t)
- bface eface)
- (when (and date (not (string= date "")))
- (save-excursion
- (set-buffer gnus-article-buffer)
- (save-restriction
- (nnheader-narrow-to-headers)
- (let ((buffer-read-only nil))
- ;; Delete any old Date headers.
- (if (re-search-forward date-regexp nil t)
- (progn
- (setq bface (get-text-property (gnus-point-at-bol) 'face)
- eface (get-text-property (1- (gnus-point-at-eol))
- 'face))
- (message-remove-header date-regexp t)
- (beginning-of-line))
- (goto-char (point-max)))
- (insert (gnus-make-date-line date type))
- ;; Do highlighting.
- (forward-line -1)
- (when (and (gnus-visual-p 'article-highlight 'highlight)
- (looking-at "\\([^:]+\\): *\\(.*\\)$"))
- (gnus-put-text-property (match-beginning 1) (match-end 1)
- 'face bface)
- (gnus-put-text-property (match-beginning 2) (match-end 2)
- 'face eface))))))))
-
-(defun gnus-make-date-line (date type)
- "Return a DATE line of TYPE."
- (cond
- ;; Convert to the local timezone. We have to slap a
- ;; `condition-case' round the calls to the timezone
- ;; functions since they aren't particularly resistant to
- ;; buggy dates.
- ((eq type 'local)
- (concat "Date: " (condition-case ()
- (timezone-make-date-arpa-standard date)
- (error date))
- "\n"))
- ;; Convert to Universal Time.
- ((eq type 'ut)
- (concat "Date: "
- (condition-case ()
- (timezone-make-date-arpa-standard date nil "UT")
- (error date))
- "\n"))
- ;; Get the original date from the article.
- ((eq type 'original)
- (concat "Date: " date "\n"))
- ;; Do an X-Sent lapsed format.
- ((eq type 'lapsed)
- ;; If the date is seriously mangled, the timezone
- ;; functions are liable to bug out, so we condition-case
- ;; the entire thing.
- (let* ((now (current-time))
- (real-time
- (condition-case ()
- (gnus-time-minus
- (gnus-encode-date
- (timezone-make-date-arpa-standard
- (current-time-string now)
- (current-time-zone now) "UT"))
- (gnus-encode-date
- (timezone-make-date-arpa-standard
- date nil "UT")))
- (error '(0 0))))
- (real-sec (+ (* (float (car real-time)) 65536)
- (cadr real-time)))
- (sec (abs real-sec))
- num prev)
- (cond
- ((equal real-time '(0 0))
- "X-Sent: Unknown\n")
- ((zerop sec)
- "X-Sent: Now\n")
- (t
- (concat
- "X-Sent: "
- ;; This is a bit convoluted, but basically we go
- ;; through the time units for years, weeks, etc,
- ;; and divide things to see whether that results
- ;; in positive answers.
- (mapconcat
- (lambda (unit)
- (if (zerop (setq num (ffloor (/ sec (cdr unit)))))
- ;; The (remaining) seconds are too few to
- ;; be divided into this time unit.
- ""
- ;; It's big enough, so we output it.
- (setq sec (- sec (* num (cdr unit))))
- (prog1
- (concat (if prev ", " "") (int-to-string
- (floor num))
- " " (symbol-name (car unit))
- (if (> num 1) "s" ""))
- (setq prev t))))
- gnus-article-time-units "")
- ;; If dates are odd, then it might appear like the
- ;; article was sent in the future.
- (if (> real-sec 0)
- " ago\n"
- " in the future\n"))))))
- (t
- (error "Unknown conversion type: %s" type))))
-
-(defun gnus-article-date-local (&optional highlight)
- "Convert the current article date to the local timezone."
- (interactive (list t))
- (gnus-article-date-ut 'local highlight))
-
-(defun gnus-article-date-original (&optional highlight)
- "Convert the current article date to what it was originally.
-This is only useful if you have used some other date conversion
-function and want to see what the date was before converting."
- (interactive (list t))
- (gnus-article-date-ut 'original highlight))
-
-(defun gnus-article-date-lapsed (&optional highlight)
- "Convert the current article date to time lapsed since it was sent."
- (interactive (list t))
- (gnus-article-date-ut 'lapsed highlight))
-
-(defun gnus-article-maybe-highlight ()
- "Do some article highlighting if `gnus-visual' is non-nil."
- (if (gnus-visual-p 'article-highlight 'highlight)
- (gnus-article-highlight-some)))
-
-;;; Article savers.
-
-(defun gnus-output-to-rmail (file-name)
- "Append the current article to an Rmail file named FILE-NAME."
- (require 'rmail)
- ;; Most of these codes are borrowed from rmailout.el.
- (setq file-name (expand-file-name file-name))
- (setq rmail-default-rmail-file file-name)
- (let ((artbuf (current-buffer))
- (tmpbuf (get-buffer-create " *Gnus-output*")))
- (save-excursion
- (or (get-file-buffer file-name)
- (file-exists-p file-name)
- (if (gnus-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")))
- (set-buffer tmpbuf)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert-buffer-substring artbuf)
- (gnus-convert-article-to-rmail)
- ;; Decide whether to append to a file or to an Emacs buffer.
- (let ((outbuf (get-file-buffer file-name)))
- (if (not outbuf)
- (append-to-file (point-min) (point-max) file-name)
- ;; File has been visited, in buffer OUTBUF.
- (set-buffer outbuf)
- (let ((buffer-read-only nil)
- (msg (and (boundp 'rmail-current-message)
- (symbol-value 'rmail-current-message))))
- ;; If MSG is non-nil, buffer is in RMAIL mode.
- (if msg
- (progn (widen)
- (narrow-to-region (point-max) (point-max))))
- (insert-buffer-substring tmpbuf)
- (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)))))))
- (kill-buffer tmpbuf)))
-
-(defun gnus-output-to-file (file-name)
- "Append the current article to a file named FILE-NAME."
- (let ((artbuf (current-buffer)))
- (nnheader-temp-write nil
- (insert-buffer-substring artbuf)
- ;; Append newline at end of the buffer as separator, and then
- ;; save it to file.
- (goto-char (point-max))
- (insert "\n")
- (append-to-file (point-min) (point-max) file-name))))
-
-(defun gnus-convert-article-to-rmail ()
- "Convert article in current buffer to Rmail message format."
- (let ((buffer-read-only nil))
- ;; Convert article directly into Babyl format.
- ;; Suggested by Rob Austein <sra@lcs.mit.edu>
- (goto-char (point-min))
- (insert "\^L\n0, unseen,,\n*** EOOH ***\n")
- (while (search-forward "\n\^_" nil t) ;single char
- (replace-match "\n^_" t t)) ;2 chars: "^" and "_"
- (goto-char (point-max))
- (insert "\^_")))
-
-(defun gnus-narrow-to-page (&optional arg)
- "Narrow the article buffer to a page.
-If given a numerical ARG, move forward ARG pages."
- (interactive "P")
- (setq arg (if arg (prefix-numeric-value arg) 0))
- (save-excursion
- (set-buffer gnus-article-buffer)
- (goto-char (point-min))
- (widen)
- (when (gnus-visual-p 'page-marker)
- (let ((buffer-read-only nil))
- (gnus-remove-text-with-property 'gnus-prev)
- (gnus-remove-text-with-property 'gnus-next)))
- (when
- (cond ((< arg 0)
- (re-search-backward page-delimiter nil 'move (1+ (abs arg))))
- ((> arg 0)
- (re-search-forward page-delimiter nil 'move arg)))
- (goto-char (match-end 0)))
- (narrow-to-region
- (point)
- (if (re-search-forward page-delimiter nil 'move)
- (match-beginning 0)
- (point)))
- (when (and (gnus-visual-p 'page-marker)
- (not (= (point-min) 1)))
- (save-excursion
- (goto-char (point-min))
- (gnus-insert-prev-page-button)))
- (when (and (gnus-visual-p 'page-marker)
- (not (= (1- (point-max)) (buffer-size))))
- (save-excursion
- (goto-char (point-max))
- (gnus-insert-next-page-button)))))
-
-;; Article mode commands
-
-(defun gnus-article-goto-next-page ()
- "Show the next page of the article."
- (interactive)
- (when (gnus-article-next-page)
- (gnus-article-read-summary-keys nil (gnus-character-to-event ?n))))
-
-(defun gnus-article-goto-prev-page ()
- "Show the next page of the article."
- (interactive)
- (if (bobp) (gnus-article-read-summary-keys nil (gnus-character-to-event ?n))
- (gnus-article-prev-page nil)))
-
-(defun gnus-article-next-page (&optional lines)
- "Show the next page of the current article.
-If end of article, return non-nil. Otherwise return nil.
-Argument LINES specifies lines to be scrolled up."
- (interactive "p")
- (move-to-window-line -1)
- ;; Fixed by enami@ptgd.sony.co.jp (enami tsugutomo)
- (if (save-excursion
- (end-of-line)
- (and (pos-visible-in-window-p) ;Not continuation line.
- (eobp)))
- ;; Nothing in this page.
- (if (or (not gnus-break-pages)
- (save-excursion
- (save-restriction
- (widen) (forward-line 1) (eobp)))) ;Real end-of-buffer?
- t ;Nothing more.
- (gnus-narrow-to-page 1) ;Go to next page.
- nil)
- ;; More in this page.
- (condition-case ()
- (scroll-up lines)
- (end-of-buffer
- ;; Long lines may cause an end-of-buffer error.
- (goto-char (point-max))))
- (move-to-window-line 0)
- nil))
-
-(defun gnus-article-prev-page (&optional lines)
- "Show previous page of current article.
-Argument LINES specifies lines to be scrolled down."
- (interactive "p")
- (move-to-window-line 0)
- (if (and gnus-break-pages
- (bobp)
- (not (save-restriction (widen) (bobp)))) ;Real beginning-of-buffer?
- (progn
- (gnus-narrow-to-page -1) ;Go to previous page.
- (goto-char (point-max))
- (recenter -1))
- (prog1
- (condition-case ()
- (scroll-down lines)
- (error nil))
- (move-to-window-line 0))))
-
-(defun gnus-article-refer-article ()
- "Read article specified by message-id around point."
- (interactive)
- (let ((point (point)))
- (search-forward ">" nil t) ;Move point to end of "<....>".
- (if (re-search-backward "\\(<[^<> \t\n]+>\\)" nil t)
- (let ((message-id (match-string 1)))
- (goto-char point)
- (set-buffer gnus-summary-buffer)
- (gnus-summary-refer-article message-id))
- (goto-char (point))
- (error "No references around point"))))
-
-(defun gnus-article-show-summary ()
- "Reconfigure windows to show summary buffer."
- (interactive)
- (gnus-configure-windows 'article)
- (gnus-summary-goto-subject gnus-current-article))
-
-(defun gnus-article-describe-briefly ()
- "Describe article mode commands briefly."
- (interactive)
- (gnus-message 6
- (substitute-command-keys "\\<gnus-article-mode-map>\\[gnus-article-goto-next-page]:Next page \\[gnus-article-goto-prev-page]:Prev page \\[gnus-article-show-summary]:Show summary \\[gnus-info-find-node]:Run Info \\[gnus-article-describe-briefly]:This help")))
-
-(defun gnus-article-summary-command ()
- "Execute the last keystroke in the summary buffer."
- (interactive)
- (let ((obuf (current-buffer))
- (owin (current-window-configuration))
- func)
- (switch-to-buffer gnus-summary-buffer 'norecord)
- (setq func (lookup-key (current-local-map) (this-command-keys)))
- (call-interactively func)
- (set-buffer obuf)
- (set-window-configuration owin)
- (set-window-point (get-buffer-window (current-buffer)) (point))))
-
-(defun gnus-article-summary-command-nosave ()
- "Execute the last keystroke in the summary buffer."
- (interactive)
- (let (func)
- (pop-to-buffer gnus-summary-buffer 'norecord)
- (setq func (lookup-key (current-local-map) (this-command-keys)))
- (call-interactively func)))
-
-(defun gnus-article-read-summary-keys (&optional arg key not-restore-window)
- "Read a summary buffer key sequence and execute it from the article buffer."
- (interactive "P")
- (let ((nosaves
- '("q" "Q" "c" "r" "R" "\C-c\C-f" "m" "a" "f" "F"
- "Zc" "ZC" "ZE" "ZQ" "ZZ" "Zn" "ZR" "ZG" "ZN" "ZP"
- "=" "^" "\M-^" "|"))
- (nosave-but-article
- '("A\r"))
- keys)
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (push (or key last-command-event) unread-command-events)
- (setq keys (read-key-sequence nil)))
- (message "")
-
- (if (or (member keys nosaves)
- (member keys nosave-but-article))
- (let (func)
- (save-window-excursion
- (pop-to-buffer gnus-summary-buffer 'norecord)
- (setq func (lookup-key (current-local-map) keys)))
- (if (not func)
- (ding)
- (set-buffer gnus-summary-buffer)
- (call-interactively func))
- (when (member keys nosave-but-article)
- (pop-to-buffer gnus-article-buffer 'norecord)))
- (let ((obuf (current-buffer))
- (owin (current-window-configuration))
- (opoint (point))
- func in-buffer)
- (if not-restore-window
- (pop-to-buffer gnus-summary-buffer 'norecord)
- (switch-to-buffer gnus-summary-buffer 'norecord))
- (setq in-buffer (current-buffer))
- (if (setq func (lookup-key (current-local-map) keys))
- (call-interactively func)
- (ding))
- (when (eq in-buffer (current-buffer))
- (set-buffer obuf)
- (unless not-restore-window
- (set-window-configuration owin))
- (set-window-point (get-buffer-window (current-buffer)) opoint))))))
-
-
-;;;
-;;; Kill file handling.
-;;;
-
-;;;###autoload
-(defalias 'gnus-batch-kill 'gnus-batch-score)
-;;;###autoload
-(defun gnus-batch-score ()
- "Run batched scoring.
-Usage: emacs -batch -l gnus -f gnus-batch-score <newsgroups> ...
-Newsgroups is a list of strings in Bnews format. If you want to score
-the comp hierarchy, you'd say \"comp.all\". If you would not like to
-score the alt hierarchy, you'd say \"!alt.all\"."
- (interactive)
- (let* ((yes-and-no
- (gnus-newsrc-parse-options
- (apply (function concat)
- (mapcar (lambda (g) (concat g " "))
- command-line-args-left))))
- (gnus-expert-user t)
- (nnmail-spool-file nil)
- (gnus-use-dribble-file nil)
- (yes (car yes-and-no))
- (no (cdr yes-and-no))
- group newsrc entry
- ;; Disable verbose message.
- gnus-novice-user gnus-large-newsgroup)
- ;; Eat all arguments.
- (setq command-line-args-left nil)
- ;; Start Gnus.
- (gnus)
- ;; Apply kills to specified newsgroups in command line arguments.
- (setq newsrc (cdr gnus-newsrc-alist))
- (while newsrc
- (setq group (caar newsrc))
- (setq entry (gnus-gethash group gnus-newsrc-hashtb))
- (if (and (<= (nth 1 (car newsrc)) gnus-level-subscribed)
- (and (car entry)
- (or (eq (car entry) t)
- (not (zerop (car entry)))))
- (if yes (string-match yes group) t)
- (or (null no) (not (string-match no group))))
- (progn
- (gnus-summary-read-group group nil t nil t)
- (and (eq (current-buffer) (get-buffer gnus-summary-buffer))
- (gnus-summary-exit))))
- (setq newsrc (cdr newsrc)))
- ;; Exit Emacs.
- (switch-to-buffer gnus-group-buffer)
- (gnus-group-save-newsrc)))
-
-(defun gnus-apply-kill-file ()
- "Apply a kill file to the current newsgroup.
-Returns the number of articles marked as read."
- (if (or (file-exists-p (gnus-newsgroup-kill-file nil))
- (file-exists-p (gnus-newsgroup-kill-file gnus-newsgroup-name)))
- (gnus-apply-kill-file-internal)
- 0))
-
-(defun gnus-kill-save-kill-buffer ()
- (let ((file (gnus-newsgroup-kill-file gnus-newsgroup-name)))
- (when (get-file-buffer file)
- (save-excursion
- (set-buffer (get-file-buffer file))
- (and (buffer-modified-p) (save-buffer))
- (kill-buffer (current-buffer))))))
-
-(defvar gnus-kill-file-name "KILL"
- "Suffix of the kill files.")
-
-(defun gnus-newsgroup-kill-file (newsgroup)
- "Return the name of a kill file name for NEWSGROUP.
-If NEWSGROUP is nil, return the global kill file name instead."
- (cond
- ;; The global KILL file is placed at top of the directory.
- ((or (null newsgroup)
- (string-equal newsgroup ""))
- (expand-file-name gnus-kill-file-name
- gnus-kill-files-directory))
- ;; Append ".KILL" to newsgroup name.
- ((gnus-use-long-file-name 'not-kill)
- (expand-file-name (concat (gnus-newsgroup-savable-name newsgroup)
- "." gnus-kill-file-name)
- gnus-kill-files-directory))
- ;; Place "KILL" under the hierarchical directory.
- (t
- (expand-file-name (concat (gnus-newsgroup-directory-form newsgroup)
- "/" gnus-kill-file-name)
- gnus-kill-files-directory))))
-
-
-;;;
-;;; Dribble file
-;;;
-
-(defvar gnus-dribble-ignore nil)
-(defvar gnus-dribble-eval-file nil)
-
-(defun gnus-dribble-file-name ()
- "Return the dribble file for the current .newsrc."
- (concat
- (if gnus-dribble-directory
- (concat (file-name-as-directory gnus-dribble-directory)
- (file-name-nondirectory gnus-current-startup-file))
- gnus-current-startup-file)
- "-dribble"))
-
-(defun gnus-dribble-enter (string)
- "Enter STRING into the dribble buffer."
- (if (and (not gnus-dribble-ignore)
- gnus-dribble-buffer
- (buffer-name gnus-dribble-buffer))
- (let ((obuf (current-buffer)))
- (set-buffer gnus-dribble-buffer)
- (insert string "\n")
- (set-window-point (get-buffer-window (current-buffer)) (point-max))
- (bury-buffer gnus-dribble-buffer)
- (set-buffer obuf))))
-
-(defun gnus-dribble-read-file ()
- "Read the dribble file from disk."
- (let ((dribble-file (gnus-dribble-file-name)))
- (save-excursion
- (set-buffer (setq gnus-dribble-buffer
- (get-buffer-create
- (file-name-nondirectory dribble-file))))
- (gnus-add-current-to-buffer-list)
- (erase-buffer)
- (setq buffer-file-name dribble-file)
- (auto-save-mode t)
- (buffer-disable-undo (current-buffer))
- (bury-buffer (current-buffer))
- (set-buffer-modified-p nil)
- (let ((auto (make-auto-save-file-name))
- (gnus-dribble-ignore t)
- modes)
- (when (or (file-exists-p auto) (file-exists-p dribble-file))
- ;; Load whichever file is newest -- the auto save file
- ;; or the "real" file.
- (if (file-newer-than-file-p auto dribble-file)
- (insert-file-contents auto)
- (insert-file-contents dribble-file))
- (unless (zerop (buffer-size))
- (set-buffer-modified-p t))
- ;; Set the file modes to reflect the .newsrc file modes.
- (save-buffer)
- (when (and (file-exists-p gnus-current-startup-file)
- (setq modes (file-modes gnus-current-startup-file)))
- (set-file-modes dribble-file modes))
- ;; Possibly eval the file later.
- (when (gnus-y-or-n-p
- "Auto-save file exists. Do you want to read it? ")
- (setq gnus-dribble-eval-file t)))))))
-
-(defun gnus-dribble-eval-file ()
- (when gnus-dribble-eval-file
- (setq gnus-dribble-eval-file nil)
- (save-excursion
- (let ((gnus-dribble-ignore t))
- (set-buffer gnus-dribble-buffer)
- (eval-buffer (current-buffer))))))
-
-(defun gnus-dribble-delete-file ()
- (when (file-exists-p (gnus-dribble-file-name))
- (delete-file (gnus-dribble-file-name)))
- (when gnus-dribble-buffer
- (save-excursion
- (set-buffer gnus-dribble-buffer)
- (let ((auto (make-auto-save-file-name)))
- (if (file-exists-p auto)
- (delete-file auto))
- (erase-buffer)
- (set-buffer-modified-p nil)))))
-
-(defun gnus-dribble-save ()
- (when (and gnus-dribble-buffer
- (buffer-name gnus-dribble-buffer))
- (save-excursion
- (set-buffer gnus-dribble-buffer)
- (save-buffer))))
-
-(defun gnus-dribble-clear ()
- (when (gnus-buffer-exists-p gnus-dribble-buffer)
- (save-excursion
- (set-buffer gnus-dribble-buffer)
- (erase-buffer)
- (set-buffer-modified-p nil)
- (setq buffer-saved-size (buffer-size)))))
-
-
-;;;
-;;; Server Communication
-;;;
-
-(defun gnus-start-news-server (&optional confirm)
- "Open a method for getting news.
-If CONFIRM is non-nil, the user will be asked for an NNTP server."
- (let (how)
- (if gnus-current-select-method
- ;; Stream is already opened.
- nil
- ;; Open NNTP server.
- (if (null gnus-nntp-service) (setq gnus-nntp-server nil))
- (if confirm
- (progn
- ;; Read server name with completion.
- (setq gnus-nntp-server
- (completing-read "NNTP server: "
- (mapcar (lambda (server) (list server))
- (cons (list gnus-nntp-server)
- gnus-secondary-servers))
- nil nil gnus-nntp-server))))
-
- (if (and gnus-nntp-server
- (stringp gnus-nntp-server)
- (not (string= gnus-nntp-server "")))
- (setq gnus-select-method
- (cond ((or (string= gnus-nntp-server "")
- (string= gnus-nntp-server "::"))
- (list 'nnspool (system-name)))
- ((string-match "^:" gnus-nntp-server)
- (list 'nnmh gnus-nntp-server
- (list 'nnmh-directory
- (file-name-as-directory
- (expand-file-name
- (concat "~/" (substring
- gnus-nntp-server 1)))))
- (list 'nnmh-get-new-mail nil)))
- (t
- (list 'nntp gnus-nntp-server)))))
-
- (setq how (car gnus-select-method))
- (cond ((eq how 'nnspool)
- (require 'nnspool)
- (gnus-message 5 "Looking up local news spool..."))
- ((eq how 'nnmh)
- (require 'nnmh)
- (gnus-message 5 "Looking up mh spool..."))
- (t
- (require 'nntp)))
- (setq gnus-current-select-method gnus-select-method)
- (run-hooks 'gnus-open-server-hook)
- (or
- ;; gnus-open-server-hook might have opened it
- (gnus-server-opened gnus-select-method)
- (gnus-open-server gnus-select-method)
- (gnus-y-or-n-p
- (format
- "%s (%s) open error: '%s'. Continue? "
- (car gnus-select-method) (cadr gnus-select-method)
- (gnus-status-message gnus-select-method)))
- (gnus-error 1 "Couldn't open server on %s"
- (nth 1 gnus-select-method))))))
-
-(defun gnus-check-group (group)
- "Try to make sure that the server where GROUP exists is alive."
- (let ((method (gnus-find-method-for-group group)))
- (or (gnus-server-opened method)
- (gnus-open-server method))))
-
-(defun gnus-check-server (&optional method silent)
- "Check whether the connection to METHOD is down.
-If METHOD is nil, use `gnus-select-method'.
-If it is down, start it up (again)."
- (let ((method (or method gnus-select-method)))
- ;; Transform virtual server names into select methods.
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (if (gnus-server-opened method)
- ;; The stream is already opened.
- t
- ;; Open the server.
- (unless silent
- (gnus-message 5 "Opening %s server%s..." (car method)
- (if (equal (nth 1 method) "") ""
- (format " on %s" (nth 1 method)))))
- (run-hooks 'gnus-open-server-hook)
- (prog1
- (gnus-open-server method)
- (unless silent
- (message ""))))))
-
-(defun gnus-get-function (method function &optional noerror)
- "Return a function symbol based on METHOD and FUNCTION."
- ;; Translate server names into methods.
- (unless method
- (error "Attempted use of a nil select method"))
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (let ((func (intern (format "%s-%s" (car method) function))))
- ;; If the functions isn't bound, we require the backend in
- ;; question.
- (unless (fboundp func)
- (require (car method))
- (when (and (not (fboundp func))
- (not noerror))
- ;; This backend doesn't implement this function.
- (error "No such function: %s" func)))
- func))
-
-
-;;;
-;;; Interface functions to the backends.
-;;;
-
-(defun gnus-open-server (method)
- "Open a connection to METHOD."
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (let ((elem (assoc method gnus-opened-servers)))
- ;; If this method was previously denied, we just return nil.
- (if (eq (nth 1 elem) 'denied)
- (progn
- (gnus-message 1 "Denied server")
- nil)
- ;; Open the server.
- (let ((result
- (funcall (gnus-get-function method 'open-server)
- (nth 1 method) (nthcdr 2 method))))
- ;; If this hasn't been opened before, we add it to the list.
- (unless elem
- (setq elem (list method nil)
- gnus-opened-servers (cons elem gnus-opened-servers)))
- ;; Set the status of this server.
- (setcar (cdr elem) (if result 'ok 'denied))
- ;; Return the result from the "open" call.
- result))))
-
-(defun gnus-close-server (method)
- "Close the connection to METHOD."
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (funcall (gnus-get-function method 'close-server) (nth 1 method)))
-
-(defun gnus-request-list (method)
- "Request the active file from METHOD."
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (funcall (gnus-get-function method 'request-list) (nth 1 method)))
-
-(defun gnus-request-list-newsgroups (method)
- "Request the newsgroups file from METHOD."
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (funcall (gnus-get-function method 'request-list-newsgroups) (nth 1 method)))
-
-(defun gnus-request-newgroups (date method)
- "Request all new groups since DATE from METHOD."
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (funcall (gnus-get-function method 'request-newgroups)
- date (nth 1 method)))
-
-(defun gnus-server-opened (method)
- "Check whether a connection to METHOD has been opened."
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (funcall (gnus-get-function method 'server-opened) (nth 1 method)))
-
-(defun gnus-status-message (method)
- "Return the status message from METHOD.
-If METHOD is a string, it is interpreted as a group name. The method
-this group uses will be queried."
- (let ((method (if (stringp method) (gnus-find-method-for-group method)
- method)))
- (funcall (gnus-get-function method 'status-message) (nth 1 method))))
-
-(defun gnus-request-group (group &optional dont-check method)
- "Request GROUP. If DONT-CHECK, no information is required."
- (let ((method (or method (gnus-find-method-for-group group))))
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (funcall (gnus-get-function method 'request-group)
- (gnus-group-real-name group) (nth 1 method) dont-check)))
-
-(defun gnus-request-asynchronous (group &optional articles)
- "Request that GROUP behave asynchronously.
-ARTICLES is the `data' of the group."
- (let ((method (gnus-find-method-for-group group)))
- (funcall (gnus-get-function method 'request-asynchronous)
- (gnus-group-real-name group) (nth 1 method) articles)))
-
-(defun gnus-list-active-group (group)
- "Request active information on GROUP."
- (let ((method (gnus-find-method-for-group group))
- (func 'list-active-group))
- (when (gnus-check-backend-function func group)
- (funcall (gnus-get-function method func)
- (gnus-group-real-name group) (nth 1 method)))))
-
-(defun gnus-request-group-description (group)
- "Request a description of GROUP."
- (let ((method (gnus-find-method-for-group group))
- (func 'request-group-description))
- (when (gnus-check-backend-function func group)
- (funcall (gnus-get-function method func)
- (gnus-group-real-name group) (nth 1 method)))))
-
-(defun gnus-close-group (group)
- "Request the GROUP be closed."
- (let ((method (gnus-find-method-for-group group)))
- (funcall (gnus-get-function method 'close-group)
- (gnus-group-real-name group) (nth 1 method))))
-
-(defun gnus-retrieve-headers (articles group &optional fetch-old)
- "Request headers for ARTICLES in GROUP.
-If FETCH-OLD, retrieve all headers (or some subset thereof) in the group."
- (let ((method (gnus-find-method-for-group group)))
- (if (and gnus-use-cache (numberp (car articles)))
- (gnus-cache-retrieve-headers articles group fetch-old)
- (funcall (gnus-get-function method 'retrieve-headers)
- articles (gnus-group-real-name group) (nth 1 method)
- fetch-old))))
-
-(defun gnus-retrieve-groups (groups method)
- "Request active information on GROUPS from METHOD."
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (funcall (gnus-get-function method 'retrieve-groups) groups (nth 1 method)))
-
-(defun gnus-request-type (group &optional article)
- "Return the type (`post' or `mail') of GROUP (and ARTICLE)."
- (let ((method (gnus-find-method-for-group group)))
- (if (not (gnus-check-backend-function 'request-type (car method)))
- 'unknown
- (funcall (gnus-get-function method 'request-type)
- (gnus-group-real-name group) article))))
-
-(defun gnus-request-update-mark (group article mark)
- "Return the type (`post' or `mail') of GROUP (and ARTICLE)."
- (let ((method (gnus-find-method-for-group group)))
- (if (not (gnus-check-backend-function 'request-update-mark (car method)))
- mark
- (funcall (gnus-get-function method 'request-update-mark)
- (gnus-group-real-name group) article mark))))
-
-(defun gnus-request-article (article group &optional buffer)
- "Request the ARTICLE in GROUP.
-ARTICLE can either be an article number or an article Message-ID.
-If BUFFER, insert the article in that group."
- (let ((method (gnus-find-method-for-group group)))
- (funcall (gnus-get-function method 'request-article)
- article (gnus-group-real-name group) (nth 1 method) buffer)))
-
-(defun gnus-request-head (article group)
- "Request the head of ARTICLE in GROUP."
- (let* ((method (gnus-find-method-for-group group))
- (head (gnus-get-function method 'request-head t)))
- (if (fboundp head)
- (funcall head article (gnus-group-real-name group) (nth 1 method))
- (let ((res (gnus-request-article article group)))
- (when res
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (when (search-forward "\n\n" nil t)
- (delete-region (1- (point)) (point-max)))
- (nnheader-fold-continuation-lines)))
- res))))
-
-(defun gnus-request-body (article group)
- "Request the body of ARTICLE in GROUP."
- (let ((method (gnus-find-method-for-group group)))
- (funcall (gnus-get-function method 'request-body)
- article (gnus-group-real-name group) (nth 1 method))))
-
-(defun gnus-request-post (method)
- "Post the current buffer using METHOD."
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (funcall (gnus-get-function method 'request-post) (nth 1 method)))
-
-(defun gnus-request-scan (group method)
- "Request a SCAN being performed in GROUP from METHOD.
-If GROUP is nil, all groups on METHOD are scanned."
- (let ((method (if group (gnus-find-method-for-group group) method)))
- (funcall (gnus-get-function method 'request-scan)
- (and group (gnus-group-real-name group)) (nth 1 method))))
-
-(defsubst gnus-request-update-info (info method)
- "Request that METHOD update INFO."
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (when (gnus-check-backend-function 'request-update-info (car method))
- (funcall (gnus-get-function method 'request-update-info)
- (gnus-group-real-name (gnus-info-group info))
- info (nth 1 method))))
-
-(defun gnus-request-expire-articles (articles group &optional force)
- (let ((method (gnus-find-method-for-group group)))
- (funcall (gnus-get-function method 'request-expire-articles)
- articles (gnus-group-real-name group) (nth 1 method)
- force)))
-
-(defun gnus-request-move-article
- (article group server accept-function &optional last)
- (let ((method (gnus-find-method-for-group group)))
- (funcall (gnus-get-function method 'request-move-article)
- article (gnus-group-real-name group)
- (nth 1 method) accept-function last)))
-
-(defun gnus-request-accept-article (group method &optional last)
- ;; Make sure there's a newline at the end of the article.
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (when (and (not method)
- (stringp group))
- (setq method (gnus-group-name-to-method group)))
- (goto-char (point-max))
- (unless (bolp)
- (insert "\n"))
- (let ((func (car (or method (gnus-find-method-for-group group)))))
- (funcall (intern (format "%s-request-accept-article" func))
- (if (stringp group) (gnus-group-real-name group) group)
- (cadr method)
- last)))
-
-(defun gnus-request-replace-article (article group buffer)
- (let ((func (car (gnus-find-method-for-group group))))
- (funcall (intern (format "%s-request-replace-article" func))
- article (gnus-group-real-name group) buffer)))
-
-(defun gnus-request-associate-buffer (group)
- (let ((method (gnus-find-method-for-group group)))
- (funcall (gnus-get-function method 'request-associate-buffer)
- (gnus-group-real-name group))))
-
-(defun gnus-request-restore-buffer (article group)
- "Request a new buffer restored to the state of ARTICLE."
- (let ((method (gnus-find-method-for-group group)))
- (funcall (gnus-get-function method 'request-restore-buffer)
- article (gnus-group-real-name group) (nth 1 method))))
-
-(defun gnus-request-create-group (group &optional method)
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (let ((method (or method (gnus-find-method-for-group group))))
- (funcall (gnus-get-function method 'request-create-group)
- (gnus-group-real-name group) (nth 1 method))))
-
-(defun gnus-request-delete-group (group &optional force)
- (let ((method (gnus-find-method-for-group group)))
- (funcall (gnus-get-function method 'request-delete-group)
- (gnus-group-real-name group) force (nth 1 method))))
-
-(defun gnus-request-rename-group (group new-name)
- (let ((method (gnus-find-method-for-group group)))
- (funcall (gnus-get-function method 'request-rename-group)
- (gnus-group-real-name group)
- (gnus-group-real-name new-name) (nth 1 method))))
-
-(defun gnus-member-of-valid (symbol group)
- "Find out if GROUP has SYMBOL as part of its \"valid\" spec."
- (memq symbol (assoc
- (symbol-name (car (gnus-find-method-for-group group)))
- gnus-valid-select-methods)))
-
-(defun gnus-method-option-p (method option)
- "Return non-nil if select METHOD has OPTION as a parameter."
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- (memq option (assoc (format "%s" (car method))
- gnus-valid-select-methods)))
-
-(defun gnus-server-extend-method (group method)
- ;; This function "extends" a virtual server. If the server is
- ;; "hello", and the select method is ("hello" (my-var "something"))
- ;; in the group "alt.alt", this will result in a new virtual server
- ;; called "hello+alt.alt".
- (let ((entry
- (gnus-copy-sequence
- (if (equal (car method) "native") gnus-select-method
- (cdr (assoc (car method) gnus-server-alist))))))
- (setcar (cdr entry) (concat (nth 1 entry) "+" group))
- (nconc entry (cdr method))))
-
-(defun gnus-server-status (method)
- "Return the status of METHOD."
- (nth 1 (assoc method gnus-opened-servers)))
-
-(defun gnus-group-name-to-method (group)
- "Return a select method suitable for GROUP."
- (if (string-match ":" group)
- (let ((server (substring group 0 (match-beginning 0))))
- (if (string-match "\\+" server)
- (list (intern (substring server 0 (match-beginning 0)))
- (substring server (match-end 0)))
- (list (intern server) "")))
- gnus-select-method))
-
-(defun gnus-find-method-for-group (group &optional info)
- "Find the select method that GROUP uses."
- (or gnus-override-method
- (and (not group)
- gnus-select-method)
- (let ((info (or info (gnus-get-info group)))
- method)
- (if (or (not info)
- (not (setq method (gnus-info-method info)))
- (equal method "native"))
- gnus-select-method
- (setq method
- (cond ((stringp method)
- (gnus-server-to-method method))
- ((stringp (car method))
- (gnus-server-extend-method group method))
- (t
- method)))
- (cond ((equal (cadr method) "")
- method)
- ((null (cadr method))
- (list (car method) ""))
- (t
- (gnus-server-add-address method)))))))
-
-(defun gnus-check-backend-function (func group)
- "Check whether GROUP supports function FUNC."
- (let ((method (if (stringp group) (car (gnus-find-method-for-group group))
- group)))
- (fboundp (intern (format "%s-%s" method func)))))
-
-(defun gnus-methods-using (feature)
- "Find all methods that have FEATURE."
- (let ((valids gnus-valid-select-methods)
- outs)
- (while valids
- (if (memq feature (car valids))
- (setq outs (cons (car valids) outs)))
- (setq valids (cdr valids)))
- outs))
-
-
-;;;
-;;; Active & Newsrc File Handling
-;;;
-
-(defun gnus-setup-news (&optional rawfile level dont-connect)
- "Setup news information.
-If RAWFILE is non-nil, the .newsrc file will also be read.
-If LEVEL is non-nil, the news will be set up at level LEVEL."
- (let ((init (not (and gnus-newsrc-alist gnus-active-hashtb (not rawfile)))))
-
- (when init
- ;; Clear some variables to re-initialize news information.
- (setq gnus-newsrc-alist nil
- gnus-active-hashtb nil)
- ;; Read the newsrc file and create `gnus-newsrc-hashtb'.
- (gnus-read-newsrc-file rawfile))
-
- (when (and (not (assoc "archive" gnus-server-alist))
- (gnus-archive-server-wanted-p))
- (push (cons "archive" gnus-message-archive-method)
- gnus-server-alist))
-
- ;; If we don't read the complete active file, we fill in the
- ;; hashtb here.
- (if (or (null gnus-read-active-file)
- (eq gnus-read-active-file 'some))
- (gnus-update-active-hashtb-from-killed))
-
- ;; Read the active file and create `gnus-active-hashtb'.
- ;; If `gnus-read-active-file' is nil, then we just create an empty
- ;; hash table. The partial filling out of the hash table will be
- ;; done in `gnus-get-unread-articles'.
- (and gnus-read-active-file
- (not level)
- (gnus-read-active-file))
-
- (or gnus-active-hashtb
- (setq gnus-active-hashtb (make-vector 4095 0)))
-
- ;; Initialize the cache.
- (when gnus-use-cache
- (gnus-cache-open))
-
- ;; Possibly eval the dribble file.
- (and init (or gnus-use-dribble-file gnus-slave) (gnus-dribble-eval-file))
-
- ;; Slave Gnusii should then clear the dribble buffer.
- (when (and init gnus-slave)
- (gnus-dribble-clear))
-
- (gnus-update-format-specifications)
-
- ;; See whether we need to read the description file.
- (if (and (string-match "%[-,0-9]*D" gnus-group-line-format)
- (not gnus-description-hashtb)
- (not dont-connect)
- gnus-read-active-file)
- (gnus-read-all-descriptions-files))
-
- ;; Find new newsgroups and treat them.
- (if (and init gnus-check-new-newsgroups (not level)
- (gnus-check-server gnus-select-method))
- (gnus-find-new-newsgroups))
-
- ;; We might read in new NoCeM messages here.
- (when (and gnus-use-nocem
- (not level)
- (not dont-connect))
- (gnus-nocem-scan-groups))
-
- ;; Find the number of unread articles in each non-dead group.
- (let ((gnus-read-active-file (and (not level) gnus-read-active-file)))
- (gnus-get-unread-articles level))
-
- (if (and init gnus-check-bogus-newsgroups
- gnus-read-active-file (not level)
- (gnus-server-opened gnus-select-method))
- (gnus-check-bogus-newsgroups))))
-
-(defun gnus-find-new-newsgroups (&optional arg)
- "Search for new newsgroups and add them.
-Each new newsgroup will be treated with `gnus-subscribe-newsgroup-method.'
-The `-n' option line from .newsrc is respected.
-If ARG (the prefix), use the `ask-server' method to query
-the server for new groups."
- (interactive "P")
- (let ((check (if (or (and arg (not (listp gnus-check-new-newsgroups)))
- (null gnus-read-active-file)
- (eq gnus-read-active-file 'some))
- 'ask-server gnus-check-new-newsgroups)))
- (unless (gnus-check-first-time-used)
- (if (or (consp check)
- (eq check 'ask-server))
- ;; Ask the server for new groups.
- (gnus-ask-server-for-new-groups)
- ;; Go through the active hashtb and look for new groups.
- (let ((groups 0)
- group new-newsgroups)
- (gnus-message 5 "Looking for new newsgroups...")
- (unless gnus-have-read-active-file
- (gnus-read-active-file))
- (setq gnus-newsrc-last-checked-date (current-time-string))
- (unless gnus-killed-hashtb
- (gnus-make-hashtable-from-killed))
- ;; Go though every newsgroup in `gnus-active-hashtb' and compare
- ;; with `gnus-newsrc-hashtb' and `gnus-killed-hashtb'.
- (mapatoms
- (lambda (sym)
- (if (or (null (setq group (symbol-name sym)))
- (not (boundp sym))
- (null (symbol-value sym))
- (gnus-gethash group gnus-killed-hashtb)
- (gnus-gethash group gnus-newsrc-hashtb))
- ()
- (let ((do-sub (gnus-matches-options-n group)))
- (cond
- ((eq do-sub 'subscribe)
- (setq groups (1+ groups))
- (gnus-sethash group group gnus-killed-hashtb)
- (funcall gnus-subscribe-options-newsgroup-method group))
- ((eq do-sub 'ignore)
- nil)
- (t
- (setq groups (1+ groups))
- (gnus-sethash group group gnus-killed-hashtb)
- (if gnus-subscribe-hierarchical-interactive
- (setq new-newsgroups (cons group new-newsgroups))
- (funcall gnus-subscribe-newsgroup-method group)))))))
- gnus-active-hashtb)
- (when new-newsgroups
- (gnus-subscribe-hierarchical-interactive new-newsgroups))
- ;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
- (if (> groups 0)
- (gnus-message 6 "%d new newsgroup%s arrived."
- groups (if (> groups 1) "s have" " has"))
- (gnus-message 6 "No new newsgroups.")))))))
-
-(defun gnus-matches-options-n (group)
- ;; Returns `subscribe' if the group is to be unconditionally
- ;; subscribed, `ignore' if it is to be ignored, and nil if there is
- ;; no match for the group.
-
- ;; First we check the two user variables.
- (cond
- ((and gnus-options-subscribe
- (string-match gnus-options-subscribe group))
- 'subscribe)
- ((and gnus-auto-subscribed-groups
- (string-match gnus-auto-subscribed-groups group))
- 'subscribe)
- ((and gnus-options-not-subscribe
- (string-match gnus-options-not-subscribe group))
- 'ignore)
- ;; Then we go through the list that was retrieved from the .newsrc
- ;; file. This list has elements on the form
- ;; `(REGEXP . {ignore,subscribe})'. The first match found (the list
- ;; is in the reverse order of the options line) is returned.
- (t
- (let ((regs gnus-newsrc-options-n))
- (while (and regs
- (not (string-match (caar regs) group)))
- (setq regs (cdr regs)))
- (and regs (cdar regs))))))
-
-(defun gnus-ask-server-for-new-groups ()
- (let* ((date (or gnus-newsrc-last-checked-date (current-time-string)))
- (methods (cons gnus-select-method
- (nconc
- (when (gnus-archive-server-wanted-p)
- (list "archive"))
- (append
- (and (consp gnus-check-new-newsgroups)
- gnus-check-new-newsgroups)
- gnus-secondary-select-methods))))
- (groups 0)
- (new-date (current-time-string))
- group new-newsgroups got-new method hashtb
- gnus-override-subscribe-method)
- ;; Go through both primary and secondary select methods and
- ;; request new newsgroups.
- (while (setq method (gnus-server-get-method nil (pop methods)))
- (setq new-newsgroups nil)
- (setq gnus-override-subscribe-method method)
- (when (and (gnus-check-server method)
- (gnus-request-newgroups date method))
- (save-excursion
- (setq got-new t)
- (setq hashtb (gnus-make-hashtable 100))
- (set-buffer nntp-server-buffer)
- ;; Enter all the new groups into a hashtable.
- (gnus-active-to-gnus-format method hashtb 'ignore))
- ;; Now all new groups from `method' are in `hashtb'.
- (mapatoms
- (lambda (group-sym)
- (if (or (null (setq group (symbol-name group-sym)))
- (not (boundp group-sym))
- (null (symbol-value group-sym))
- (gnus-gethash group gnus-newsrc-hashtb)
- (member group gnus-zombie-list)
- (member group gnus-killed-list))
- ;; The group is already known.
- ()
- ;; Make this group active.
- (when (symbol-value group-sym)
- (gnus-set-active group (symbol-value group-sym)))
- ;; Check whether we want it or not.
- (let ((do-sub (gnus-matches-options-n group)))
- (cond
- ((eq do-sub 'subscribe)
- (incf groups)
- (gnus-sethash group group gnus-killed-hashtb)
- (funcall gnus-subscribe-options-newsgroup-method group))
- ((eq do-sub 'ignore)
- nil)
- (t
- (incf groups)
- (gnus-sethash group group gnus-killed-hashtb)
- (if gnus-subscribe-hierarchical-interactive
- (push group new-newsgroups)
- (funcall gnus-subscribe-newsgroup-method group)))))))
- hashtb))
- (when new-newsgroups
- (gnus-subscribe-hierarchical-interactive new-newsgroups)))
- ;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
- (when (> groups 0)
- (gnus-message 6 "%d new newsgroup%s arrived."
- groups (if (> groups 1) "s have" " has")))
- (and got-new (setq gnus-newsrc-last-checked-date new-date))
- got-new))
-
-(defun gnus-check-first-time-used ()
- (if (or (> (length gnus-newsrc-alist) 1)
- (file-exists-p gnus-startup-file)
- (file-exists-p (concat gnus-startup-file ".el"))
- (file-exists-p (concat gnus-startup-file ".eld")))
- nil
- (gnus-message 6 "First time user; subscribing you to default groups")
- (unless (gnus-read-active-file-p)
- (gnus-read-active-file))
- (setq gnus-newsrc-last-checked-date (current-time-string))
- (let ((groups gnus-default-subscribed-newsgroups)
- group)
- (if (eq groups t)
- nil
- (setq groups (or groups gnus-backup-default-subscribed-newsgroups))
- (mapatoms
- (lambda (sym)
- (if (null (setq group (symbol-name sym)))
- ()
- (let ((do-sub (gnus-matches-options-n group)))
- (cond
- ((eq do-sub 'subscribe)
- (gnus-sethash group group gnus-killed-hashtb)
- (funcall gnus-subscribe-options-newsgroup-method group))
- ((eq do-sub 'ignore)
- nil)
- (t
- (setq gnus-killed-list (cons group gnus-killed-list)))))))
- gnus-active-hashtb)
- (while groups
- (if (gnus-active (car groups))
- (gnus-group-change-level
- (car groups) gnus-level-default-subscribed gnus-level-killed))
- (setq groups (cdr groups)))
- (gnus-group-make-help-group)
- (and gnus-novice-user
- (gnus-message 7 "`A k' to list killed groups"))))))
-
-(defun gnus-subscribe-group (group previous &optional method)
- (gnus-group-change-level
- (if method
- (list t group gnus-level-default-subscribed nil nil method)
- group)
- gnus-level-default-subscribed gnus-level-killed previous t))
-
-;; `gnus-group-change-level' is the fundamental function for changing
-;; subscription levels of newsgroups. This might mean just changing
-;; from level 1 to 2, which is pretty trivial, from 2 to 6 or back
-;; again, which subscribes/unsubscribes a group, which is equally
-;; trivial. Changing from 1-7 to 8-9 means that you kill a group, and
-;; from 8-9 to 1-7 means that you remove the group from the list of
-;; killed (or zombie) groups and add them to the (kinda) subscribed
-;; groups. And last but not least, moving from 8 to 9 and 9 to 8,
-;; which is trivial.
-;; ENTRY can either be a string (newsgroup name) or a list (if
-;; FROMKILLED is t, it's a list on the format (NUM INFO-LIST),
-;; otherwise it's a list in the format of the `gnus-newsrc-hashtb'
-;; entries.
-;; LEVEL is the new level of the group, OLDLEVEL is the old level and
-;; PREVIOUS is the group (in hashtb entry format) to insert this group
-;; after.
-(defun gnus-group-change-level (entry level &optional oldlevel
- previous fromkilled)
- (let (group info active num)
- ;; Glean what info we can from the arguments
- (if (consp entry)
- (if fromkilled (setq group (nth 1 entry))
- (setq group (car (nth 2 entry))))
- (setq group entry))
- (if (and (stringp entry)
- oldlevel
- (< oldlevel gnus-level-zombie))
- (setq entry (gnus-gethash entry gnus-newsrc-hashtb)))
- (if (and (not oldlevel)
- (consp entry))
- (setq oldlevel (gnus-info-level (nth 2 entry)))
- (setq oldlevel (or oldlevel 9)))
- (if (stringp previous)
- (setq previous (gnus-gethash previous gnus-newsrc-hashtb)))
-
- (if (and (>= oldlevel gnus-level-zombie)
- (gnus-gethash group gnus-newsrc-hashtb))
- ;; We are trying to subscribe a group that is already
- ;; subscribed.
- () ; Do nothing.
-
- (or (gnus-ephemeral-group-p group)
- (gnus-dribble-enter
- (format "(gnus-group-change-level %S %S %S %S %S)"
- group level oldlevel (car (nth 2 previous)) fromkilled)))
-
- ;; Then we remove the newgroup from any old structures, if needed.
- ;; If the group was killed, we remove it from the killed or zombie
- ;; list. If not, and it is in fact going to be killed, we remove
- ;; it from the newsrc hash table and assoc.
- (cond
- ((>= oldlevel gnus-level-zombie)
- (if (= oldlevel gnus-level-zombie)
- (setq gnus-zombie-list (delete group gnus-zombie-list))
- (setq gnus-killed-list (delete group gnus-killed-list))))
- (t
- (if (and (>= level gnus-level-zombie)
- entry)
- (progn
- (gnus-sethash (car (nth 2 entry)) nil gnus-newsrc-hashtb)
- (if (nth 3 entry)
- (setcdr (gnus-gethash (car (nth 3 entry))
- gnus-newsrc-hashtb)
- (cdr entry)))
- (setcdr (cdr entry) (cdddr entry))))))
-
- ;; Finally we enter (if needed) the list where it is supposed to
- ;; go, and change the subscription level. If it is to be killed,
- ;; we enter it into the killed or zombie list.
- (cond
- ((>= level gnus-level-zombie)
- ;; Remove from the hash table.
- (gnus-sethash group nil gnus-newsrc-hashtb)
- ;; We do not enter foreign groups into the list of dead
- ;; groups.
- (unless (gnus-group-foreign-p group)
- (if (= level gnus-level-zombie)
- (setq gnus-zombie-list (cons group gnus-zombie-list))
- (setq gnus-killed-list (cons group gnus-killed-list)))))
- (t
- ;; If the list is to be entered into the newsrc assoc, and
- ;; it was killed, we have to create an entry in the newsrc
- ;; hashtb format and fix the pointers in the newsrc assoc.
- (if (< oldlevel gnus-level-zombie)
- ;; It was alive, and it is going to stay alive, so we
- ;; just change the level and don't change any pointers or
- ;; hash table entries.
- (setcar (cdaddr entry) level)
- (if (listp entry)
- (setq info (cdr entry)
- num (car entry))
- (setq active (gnus-active group))
- (setq num
- (if active (- (1+ (cdr active)) (car active)) t))
- ;; Check whether the group is foreign. If so, the
- ;; foreign select method has to be entered into the
- ;; info.
- (let ((method (or gnus-override-subscribe-method
- (gnus-group-method group))))
- (if (eq method gnus-select-method)
- (setq info (list group level nil))
- (setq info (list group level nil nil method)))))
- (unless previous
- (setq previous
- (let ((p gnus-newsrc-alist))
- (while (cddr p)
- (setq p (cdr p)))
- p)))
- (setq entry (cons info (cddr previous)))
- (if (cdr previous)
- (progn
- (setcdr (cdr previous) entry)
- (gnus-sethash group (cons num (cdr previous))
- gnus-newsrc-hashtb))
- (setcdr previous entry)
- (gnus-sethash group (cons num previous)
- gnus-newsrc-hashtb))
- (when (cdr entry)
- (setcdr (gnus-gethash (caadr entry) gnus-newsrc-hashtb) entry)))))
- (when gnus-group-change-level-function
- (funcall gnus-group-change-level-function group level oldlevel)))))
-
-(defun gnus-kill-newsgroup (newsgroup)
- "Obsolete function. Kills a newsgroup."
- (gnus-group-change-level
- (gnus-gethash newsgroup gnus-newsrc-hashtb) gnus-level-killed))
-
-(defun gnus-check-bogus-newsgroups (&optional confirm)
- "Remove bogus newsgroups.
-If CONFIRM is non-nil, the user has to confirm the deletion of every
-newsgroup."
- (let ((newsrc (cdr gnus-newsrc-alist))
- bogus group entry info)
- (gnus-message 5 "Checking bogus newsgroups...")
- (unless (gnus-read-active-file-p)
- (gnus-read-active-file))
- (when (gnus-read-active-file-p)
- ;; Find all bogus newsgroup that are subscribed.
- (while newsrc
- (setq info (pop newsrc)
- group (gnus-info-group info))
- (unless (or (gnus-active group) ; Active
- (gnus-info-method info) ; Foreign
- (and confirm
- (not (gnus-y-or-n-p
- (format "Remove bogus newsgroup: %s " group)))))
- ;; Found a bogus newsgroup.
- (push group bogus)))
- ;; Remove all bogus subscribed groups by first killing them, and
- ;; then removing them from the list of killed groups.
- (while bogus
- (when (setq entry (gnus-gethash (setq group (pop bogus))
- gnus-newsrc-hashtb))
- (gnus-group-change-level entry gnus-level-killed)
- (setq gnus-killed-list (delete group gnus-killed-list))))
- ;; Then we remove all bogus groups from the list of killed and
- ;; zombie groups. They are are removed without confirmation.
- (let ((dead-lists '(gnus-killed-list gnus-zombie-list))
- killed)
- (while dead-lists
- (setq killed (symbol-value (car dead-lists)))
- (while killed
- (unless (gnus-active (setq group (pop killed)))
- ;; The group is bogus.
- ;; !!!Slow as hell.
- (set (car dead-lists)
- (delete group (symbol-value (car dead-lists))))))
- (setq dead-lists (cdr dead-lists))))
- (gnus-message 5 "Checking bogus newsgroups...done"))))
-
-(defun gnus-check-duplicate-killed-groups ()
- "Remove duplicates from the list of killed groups."
- (interactive)
- (let ((killed gnus-killed-list))
- (while killed
- (gnus-message 9 "%d" (length killed))
- (setcdr killed (delete (car killed) (cdr killed)))
- (setq killed (cdr killed)))))
-
-;; We want to inline a function from gnus-cache, so we cheat here:
-(eval-when-compile
- (provide 'gnus)
- (setq gnus-directory (or (getenv "SAVEDIR") "~/News/"))
- (require 'gnus-cache))
-
-(defun gnus-get-unread-articles-in-group (info active &optional update)
- (when active
- ;; Allow the backend to update the info in the group.
- (when (and update
- (gnus-request-update-info
- info (gnus-find-method-for-group (gnus-info-group info))))
- (gnus-activate-group (gnus-info-group info) nil t))
- (let* ((range (gnus-info-read info))
- (num 0))
- ;; If a cache is present, we may have to alter the active info.
- (when (and gnus-use-cache info)
- (inline (gnus-cache-possibly-alter-active
- (gnus-info-group info) active)))
- ;; Modify the list of read articles according to what articles
- ;; are available; then tally the unread articles and add the
- ;; number to the group hash table entry.
- (cond
- ((zerop (cdr active))
- (setq num 0))
- ((not range)
- (setq num (- (1+ (cdr active)) (car active))))
- ((not (listp (cdr range)))
- ;; Fix a single (num . num) range according to the
- ;; active hash table.
- ;; Fix by Carsten Bormann <cabo@Informatik.Uni-Bremen.DE>.
- (and (< (cdr range) (car active)) (setcdr range (1- (car active))))
- (and (> (cdr range) (cdr active)) (setcdr range (cdr active)))
- ;; Compute number of unread articles.
- (setq num (max 0 (- (cdr active) (- (1+ (cdr range)) (car range))))))
- (t
- ;; The read list is a list of ranges. Fix them according to
- ;; the active hash table.
- ;; First peel off any elements that are below the lower
- ;; active limit.
- (while (and (cdr range)
- (>= (car active)
- (or (and (atom (cadr range)) (cadr range))
- (caadr range))))
- (if (numberp (car range))
- (setcar range
- (cons (car range)
- (or (and (numberp (cadr range))
- (cadr range))
- (cdadr range))))
- (setcdr (car range)
- (or (and (numberp (nth 1 range)) (nth 1 range))
- (cdadr range))))
- (setcdr range (cddr range)))
- ;; Adjust the first element to be the same as the lower limit.
- (if (and (not (atom (car range)))
- (< (cdar range) (car active)))
- (setcdr (car range) (1- (car active))))
- ;; Then we want to peel off any elements that are higher
- ;; than the upper active limit.
- (let ((srange range))
- ;; Go past all legal elements.
- (while (and (cdr srange)
- (<= (or (and (atom (cadr srange))
- (cadr srange))
- (caadr srange)) (cdr active)))
- (setq srange (cdr srange)))
- (if (cdr srange)
- ;; Nuke all remaining illegal elements.
- (setcdr srange nil))
-
- ;; Adjust the final element.
- (if (and (not (atom (car srange)))
- (> (cdar srange) (cdr active)))
- (setcdr (car srange) (cdr active))))
- ;; Compute the number of unread articles.
- (while range
- (setq num (+ num (- (1+ (or (and (atom (car range)) (car range))
- (cdar range)))
- (or (and (atom (car range)) (car range))
- (caar range)))))
- (setq range (cdr range)))
- (setq num (max 0 (- (cdr active) num)))))
- ;; Set the number of unread articles.
- (when info
- (setcar (gnus-gethash (gnus-info-group info) gnus-newsrc-hashtb) num))
- num)))
-
-;; Go though `gnus-newsrc-alist' and compare with `gnus-active-hashtb'
-;; and compute how many unread articles there are in each group.
-(defun gnus-get-unread-articles (&optional level)
- (let* ((newsrc (cdr gnus-newsrc-alist))
- (level (or level gnus-activate-level (1+ gnus-level-subscribed)))
- (foreign-level
- (min
- (cond ((and gnus-activate-foreign-newsgroups
- (not (numberp gnus-activate-foreign-newsgroups)))
- (1+ gnus-level-subscribed))
- ((numberp gnus-activate-foreign-newsgroups)
- gnus-activate-foreign-newsgroups)
- (t 0))
- level))
- info group active method)
- (gnus-message 5 "Checking new news...")
-
- (while newsrc
- (setq active (gnus-active (setq group (gnus-info-group
- (setq info (pop newsrc))))))
-
- ;; Check newsgroups. If the user doesn't want to check them, or
- ;; they can't be checked (for instance, if the news server can't
- ;; be reached) we just set the number of unread articles in this
- ;; newsgroup to t. This means that Gnus thinks that there are
- ;; unread articles, but it has no idea how many.
- (if (and (setq method (gnus-info-method info))
- (not (gnus-server-equal
- gnus-select-method
- (setq method (gnus-server-get-method nil method))))
- (not (gnus-secondary-method-p method)))
- ;; These groups are foreign. Check the level.
- (when (<= (gnus-info-level info) foreign-level)
- (setq active (gnus-activate-group group 'scan))
- (unless (inline (gnus-virtual-group-p group))
- (inline (gnus-close-group group)))
- (when (fboundp (intern (concat (symbol-name (car method))
- "-request-update-info")))
- (inline (gnus-request-update-info info method))))
- ;; These groups are native or secondary.
- (when (and (<= (gnus-info-level info) level)
- (not gnus-read-active-file))
- (setq active (gnus-activate-group group 'scan))
- (inline (gnus-close-group group))))
-
- ;; Get the number of unread articles in the group.
- (if active
- (inline (gnus-get-unread-articles-in-group info active))
- ;; The group couldn't be reached, so we nix out the number of
- ;; unread articles and stuff.
- (gnus-set-active group nil)
- (setcar (gnus-gethash group gnus-newsrc-hashtb) t)))
-
- (gnus-message 5 "Checking new news...done")))
-
-;; Create a hash table out of the newsrc alist. The `car's of the
-;; alist elements are used as keys.
-(defun gnus-make-hashtable-from-newsrc-alist ()
- (let ((alist gnus-newsrc-alist)
- (ohashtb gnus-newsrc-hashtb)
- prev)
- (setq gnus-newsrc-hashtb (gnus-make-hashtable (length alist)))
- (setq alist
- (setq prev (setq gnus-newsrc-alist
- (if (equal (caar gnus-newsrc-alist)
- "dummy.group")
- gnus-newsrc-alist
- (cons (list "dummy.group" 0 nil) alist)))))
- (while alist
- (gnus-sethash
- (caar alist)
- (cons (and ohashtb (car (gnus-gethash (caar alist) ohashtb)))
- prev)
- gnus-newsrc-hashtb)
- (setq prev alist
- alist (cdr alist)))))
-
-(defun gnus-make-hashtable-from-killed ()
- "Create a hash table from the killed and zombie lists."
- (let ((lists '(gnus-killed-list gnus-zombie-list))
- list)
- (setq gnus-killed-hashtb
- (gnus-make-hashtable
- (+ (length gnus-killed-list) (length gnus-zombie-list))))
- (while (setq list (pop lists))
- (setq list (symbol-value list))
- (while list
- (gnus-sethash (car list) (pop list) gnus-killed-hashtb)))))
-
-(defun gnus-activate-group (group &optional scan dont-check method)
- ;; Check whether a group has been activated or not.
- ;; If SCAN, request a scan of that group as well.
- (let ((method (or method (gnus-find-method-for-group group)))
- active)
- (and (gnus-check-server method)
- ;; We escape all bugs and quit here to make it possible to
- ;; continue if a group is so out-there that it reports bugs
- ;; and stuff.
- (progn
- (and scan
- (gnus-check-backend-function 'request-scan (car method))
- (gnus-request-scan group method))
- t)
- (condition-case ()
- (gnus-request-group group dont-check method)
- ; (error nil)
- (quit nil))
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- ;; Parse the result we got from `gnus-request-group'.
- (and (looking-at "[0-9]+ [0-9]+ \\([0-9]+\\) [0-9]+")
- (progn
- (goto-char (match-beginning 1))
- (gnus-set-active
- group (setq active (cons (read (current-buffer))
- (read (current-buffer)))))
- ;; Return the new active info.
- active))))))
-
-(defun gnus-update-read-articles (group unread)
- "Update the list of read and ticked articles in GROUP using the
-UNREAD and TICKED lists.
-Note: UNSELECTED has to be sorted over `<'.
-Returns whether the updating was successful."
- (let* ((active (or gnus-newsgroup-active (gnus-active group)))
- (entry (gnus-gethash group gnus-newsrc-hashtb))
- (info (nth 2 entry))
- (prev 1)
- (unread (sort (copy-sequence unread) '<))
- read)
- (if (or (not info) (not active))
- ;; There is no info on this group if it was, in fact,
- ;; killed. Gnus stores no information on killed groups, so
- ;; there's nothing to be done.
- ;; One could store the information somewhere temporarily,
- ;; perhaps... Hmmm...
- ()
- ;; Remove any negative articles numbers.
- (while (and unread (< (car unread) 0))
- (setq unread (cdr unread)))
- ;; Remove any expired article numbers
- (while (and unread (< (car unread) (car active)))
- (setq unread (cdr unread)))
- ;; Compute the ranges of read articles by looking at the list of
- ;; unread articles.
- (while unread
- (if (/= (car unread) prev)
- (setq read (cons (if (= prev (1- (car unread))) prev
- (cons prev (1- (car unread)))) read)))
- (setq prev (1+ (car unread)))
- (setq unread (cdr unread)))
- (when (<= prev (cdr active))
- (setq read (cons (cons prev (cdr active)) read)))
- ;; Enter this list into the group info.
- (gnus-info-set-read
- info (if (> (length read) 1) (nreverse read) read))
- ;; Set the number of unread articles in gnus-newsrc-hashtb.
- (gnus-get-unread-articles-in-group info (gnus-active group))
- t)))
-
-(defun gnus-make-articles-unread (group articles)
- "Mark ARTICLES in GROUP as unread."
- (let* ((info (nth 2 (or (gnus-gethash group gnus-newsrc-hashtb)
- (gnus-gethash (gnus-group-real-name group)
- gnus-newsrc-hashtb))))
- (ranges (gnus-info-read info))
- news article)
- (while articles
- (when (gnus-member-of-range
- (setq article (pop articles)) ranges)
- (setq news (cons article news))))
- (when news
- (gnus-info-set-read
- info (gnus-remove-from-range (gnus-info-read info) (nreverse news)))
- (gnus-group-update-group group t))))
-
-;; Enter all dead groups into the hashtb.
-(defun gnus-update-active-hashtb-from-killed ()
- (let ((hashtb (setq gnus-active-hashtb (make-vector 4095 0)))
- (lists (list gnus-killed-list gnus-zombie-list))
- killed)
- (while lists
- (setq killed (car lists))
- (while killed
- (gnus-sethash (car killed) nil hashtb)
- (setq killed (cdr killed)))
- (setq lists (cdr lists)))))
-
-(defun gnus-get-killed-groups ()
- "Go through the active hashtb and all all unknown groups as killed."
- ;; First make sure active file has been read.
- (unless (gnus-read-active-file-p)
- (let ((gnus-read-active-file t))
- (gnus-read-active-file)))
- (or gnus-killed-hashtb (gnus-make-hashtable-from-killed))
- ;; Go through all newsgroups that are known to Gnus - enlarge kill list.
- (mapatoms
- (lambda (sym)
- (let ((groups 0)
- (group (symbol-name sym)))
- (if (or (null group)
- (gnus-gethash group gnus-killed-hashtb)
- (gnus-gethash group gnus-newsrc-hashtb))
- ()
- (let ((do-sub (gnus-matches-options-n group)))
- (if (or (eq do-sub 'subscribe) (eq do-sub 'ignore))
- ()
- (setq groups (1+ groups))
- (setq gnus-killed-list
- (cons group gnus-killed-list))
- (gnus-sethash group group gnus-killed-hashtb))))))
- gnus-active-hashtb))
-
-;; Get the active file(s) from the backend(s).
-(defun gnus-read-active-file ()
- (gnus-group-set-mode-line)
- (let ((methods
- (append
- (if (gnus-check-server gnus-select-method)
- ;; The native server is available.
- (cons gnus-select-method gnus-secondary-select-methods)
- ;; The native server is down, so we just do the
- ;; secondary ones.
- gnus-secondary-select-methods)
- ;; Also read from the archive server.
- (when (gnus-archive-server-wanted-p)
- (list "archive"))))
- list-type)
- (setq gnus-have-read-active-file nil)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (while methods
- (let* ((method (if (stringp (car methods))
- (gnus-server-get-method nil (car methods))
- (car methods)))
- (where (nth 1 method))
- (mesg (format "Reading active file%s via %s..."
- (if (and where (not (zerop (length where))))
- (concat " from " where) "")
- (car method))))
- (gnus-message 5 mesg)
- (when (gnus-check-server method)
- ;; Request that the backend scan its incoming messages.
- (and (gnus-check-backend-function 'request-scan (car method))
- (gnus-request-scan nil method))
- (cond
- ((and (eq gnus-read-active-file 'some)
- (gnus-check-backend-function 'retrieve-groups (car method)))
- (let ((newsrc (cdr gnus-newsrc-alist))
- (gmethod (gnus-server-get-method nil method))
- groups info)
- (while (setq info (pop newsrc))
- (when (gnus-server-equal
- (gnus-find-method-for-group
- (gnus-info-group info) info)
- gmethod)
- (push (gnus-group-real-name (gnus-info-group info))
- groups)))
- (when groups
- (gnus-check-server method)
- (setq list-type (gnus-retrieve-groups groups method))
- (cond
- ((not list-type)
- (gnus-error
- 1.2 "Cannot read partial active file from %s server."
- (car method)))
- ((eq list-type 'active)
- (gnus-active-to-gnus-format method gnus-active-hashtb))
- (t
- (gnus-groups-to-gnus-format method gnus-active-hashtb))))))
- (t
- (if (not (gnus-request-list method))
- (unless (equal method gnus-message-archive-method)
- (gnus-error 1 "Cannot read active file from %s server."
- (car method)))
- (gnus-message 5 mesg)
- (gnus-active-to-gnus-format method gnus-active-hashtb)
- ;; We mark this active file as read.
- (push method gnus-have-read-active-file)
- (gnus-message 5 "%sdone" mesg))))))
- (setq methods (cdr methods))))))
-
-;; Read an active file and place the results in `gnus-active-hashtb'.
-(defun gnus-active-to-gnus-format (&optional method hashtb ignore-errors)
- (unless method
- (setq method gnus-select-method))
- (let ((cur (current-buffer))
- (hashtb (or hashtb
- (if (and gnus-active-hashtb
- (not (equal method gnus-select-method)))
- gnus-active-hashtb
- (setq gnus-active-hashtb
- (if (equal method gnus-select-method)
- (gnus-make-hashtable
- (count-lines (point-min) (point-max)))
- (gnus-make-hashtable 4096)))))))
- ;; Delete unnecessary lines.
- (goto-char (point-min))
- (while (search-forward "\nto." nil t)
- (delete-region (1+ (match-beginning 0))
- (progn (forward-line 1) (point))))
- (or (string= gnus-ignored-newsgroups "")
- (progn
- (goto-char (point-min))
- (delete-matching-lines gnus-ignored-newsgroups)))
- ;; Make the group names readable as a lisp expression even if they
- ;; contain special characters.
- ;; Fix by Luc Van Eycken <Luc.VanEycken@esat.kuleuven.ac.be>.
- (goto-char (point-max))
- (while (re-search-backward "[][';?()#]" nil t)
- (insert ?\\))
- ;; If these are groups from a foreign select method, we insert the
- ;; group prefix in front of the group names.
- (and method (not (gnus-server-equal
- (gnus-server-get-method nil method)
- (gnus-server-get-method nil gnus-select-method)))
- (let ((prefix (gnus-group-prefixed-name "" method)))
- (goto-char (point-min))
- (while (and (not (eobp))
- (progn (insert prefix)
- (zerop (forward-line 1)))))))
- ;; Store the active file in a hash table.
- (goto-char (point-min))
- (if (string-match "%[oO]" gnus-group-line-format)
- ;; Suggested by Brian Edmonds <edmonds@cs.ubc.ca>.
- ;; If we want information on moderated groups, we use this
- ;; loop...
- (let* ((mod-hashtb (make-vector 7 0))
- (m (intern "m" mod-hashtb))
- group max min)
- (while (not (eobp))
- (condition-case nil
- (progn
- (narrow-to-region (point) (gnus-point-at-eol))
- (setq group (let ((obarray hashtb)) (read cur)))
- (if (and (numberp (setq max (read cur)))
- (numberp (setq min (read cur)))
- (progn
- (skip-chars-forward " \t")
- (not
- (or (= (following-char) ?=)
- (= (following-char) ?x)
- (= (following-char) ?j)))))
- (set group (cons min max))
- (set group nil))
- ;; Enter moderated groups into a list.
- (if (eq (let ((obarray mod-hashtb)) (read cur)) m)
- (setq gnus-moderated-list
- (cons (symbol-name group) gnus-moderated-list))))
- (error
- (and group
- (symbolp group)
- (set group nil))))
- (widen)
- (forward-line 1)))
- ;; And if we do not care about moderation, we use this loop,
- ;; which is faster.
- (let (group max min)
- (while (not (eobp))
- (condition-case ()
- (progn
- (narrow-to-region (point) (gnus-point-at-eol))
- ;; group gets set to a symbol interned in the hash table
- ;; (what a hack!!) - jwz
- (setq group (let ((obarray hashtb)) (read cur)))
- (if (and (numberp (setq max (read cur)))
- (numberp (setq min (read cur)))
- (progn
- (skip-chars-forward " \t")
- (not
- (or (= (following-char) ?=)
- (= (following-char) ?x)
- (= (following-char) ?j)))))
- (set group (cons min max))
- (set group nil)))
- (error
- (progn
- (and group
- (symbolp group)
- (set group nil))
- (or ignore-errors
- (gnus-message 3 "Warning - illegal active: %s"
- (buffer-substring
- (gnus-point-at-bol) (gnus-point-at-eol)))))))
- (widen)
- (forward-line 1))))))
-
-(defun gnus-groups-to-gnus-format (method &optional hashtb)
- ;; Parse a "groups" active file.
- (let ((cur (current-buffer))
- (hashtb (or hashtb
- (if (and method gnus-active-hashtb)
- gnus-active-hashtb
- (setq gnus-active-hashtb
- (gnus-make-hashtable
- (count-lines (point-min) (point-max)))))))
- (prefix (and method
- (not (gnus-server-equal
- (gnus-server-get-method nil method)
- (gnus-server-get-method nil gnus-select-method)))
- (gnus-group-prefixed-name "" method))))
-
- (goto-char (point-min))
- ;; We split this into to separate loops, one with the prefix
- ;; and one without to speed the reading up somewhat.
- (if prefix
- (let (min max opoint group)
- (while (not (eobp))
- (condition-case ()
- (progn
- (read cur) (read cur)
- (setq min (read cur)
- max (read cur)
- opoint (point))
- (skip-chars-forward " \t")
- (insert prefix)
- (goto-char opoint)
- (set (let ((obarray hashtb)) (read cur))
- (cons min max)))
- (error (and group (symbolp group) (set group nil))))
- (forward-line 1)))
- (let (min max group)
- (while (not (eobp))
- (condition-case ()
- (if (= (following-char) ?2)
- (progn
- (read cur) (read cur)
- (setq min (read cur)
- max (read cur))
- (set (setq group (let ((obarray hashtb)) (read cur)))
- (cons min max))))
- (error (and group (symbolp group) (set group nil))))
- (forward-line 1))))))
-
-(defun gnus-read-newsrc-file (&optional force)
- "Read startup file.
-If FORCE is non-nil, the .newsrc file is read."
- ;; Reset variables that might be defined in the .newsrc.eld file.
- (let ((variables gnus-variable-list))
- (while variables
- (set (car variables) nil)
- (setq variables (cdr variables))))
- (let* ((newsrc-file gnus-current-startup-file)
- (quick-file (concat newsrc-file ".el")))
- (save-excursion
- ;; We always load the .newsrc.eld file. If always contains
- ;; much information that can not be gotten from the .newsrc
- ;; file (ticked articles, killed groups, foreign methods, etc.)
- (gnus-read-newsrc-el-file quick-file)
-
- (if (and (file-exists-p gnus-current-startup-file)
- (or force
- (and (file-newer-than-file-p newsrc-file quick-file)
- (file-newer-than-file-p newsrc-file
- (concat quick-file "d")))
- (not gnus-newsrc-alist)))
- ;; We read the .newsrc file. Note that if there if a
- ;; .newsrc.eld file exists, it has already been read, and
- ;; the `gnus-newsrc-hashtb' has been created. While reading
- ;; the .newsrc file, Gnus will only use the information it
- ;; can find there for changing the data already read -
- ;; ie. reading the .newsrc file will not trash the data
- ;; already read (except for read articles).
- (save-excursion
- (gnus-message 5 "Reading %s..." newsrc-file)
- (set-buffer (find-file-noselect newsrc-file))
- (buffer-disable-undo (current-buffer))
- (gnus-newsrc-to-gnus-format)
- (kill-buffer (current-buffer))
- (gnus-message 5 "Reading %s...done" newsrc-file)))
-
- ;; Read any slave files.
- (unless gnus-slave
- (gnus-master-read-slave-newsrc))
-
- ;; Convert old to new.
- (gnus-convert-old-newsrc))))
-
-(defun gnus-continuum-version (version)
- "Return VERSION as a floating point number."
- (when (or (string-match "^\\([^ ]+\\)? ?Gnus v?\\([0-9.]+\\)$" version)
- (string-match "^\\(.?\\)gnus-\\([0-9.]+\\)$" version))
- (let* ((alpha (and (match-beginning 1) (match-string 1 version)))
- (number (match-string 2 version))
- major minor least)
- (string-match "\\([0-9]\\)\\.\\([0-9]+\\)\\.?\\([0-9]+\\)?" number)
- (setq major (string-to-number (match-string 1 number)))
- (setq minor (string-to-number (match-string 2 number)))
- (setq least (if (match-beginning 3)
- (string-to-number (match-string 3 number))
- 0))
- (string-to-number
- (if (zerop major)
- (format "%s00%02d%02d"
- (cond
- ((member alpha '("(ding)" "d")) "4.99")
- ((member alpha '("September" "s")) "5.01")
- ((member alpha '("Red" "r")) "5.03"))
- minor least)
- (format "%d.%02d%02d" major minor least))))))
-
-(defun gnus-convert-old-newsrc ()
- "Convert old newsrc into the new format, if needed."
- (let ((fcv (and gnus-newsrc-file-version
- (gnus-continuum-version gnus-newsrc-file-version))))
- (cond
- ;; No .newsrc.eld file was loaded.
- ((null fcv) nil)
- ;; Gnus 5 .newsrc.eld was loaded.
- ((< fcv (gnus-continuum-version "September Gnus v0.1"))
- (gnus-convert-old-ticks)))))
-
-(defun gnus-convert-old-ticks ()
- (let ((newsrc (cdr gnus-newsrc-alist))
- marks info dormant ticked)
- (while (setq info (pop newsrc))
- (when (setq marks (gnus-info-marks info))
- (setq dormant (cdr (assq 'dormant marks))
- ticked (cdr (assq 'tick marks)))
- (when (or dormant ticked)
- (gnus-info-set-read
- info
- (gnus-add-to-range
- (gnus-info-read info)
- (nconc (gnus-uncompress-range dormant)
- (gnus-uncompress-range ticked)))))))))
-
-(defun gnus-read-newsrc-el-file (file)
- (let ((ding-file (concat file "d")))
- ;; We always, always read the .eld file.
- (gnus-message 5 "Reading %s..." ding-file)
- (let (gnus-newsrc-assoc)
- (condition-case nil
- (load ding-file t t t)
- (error
- (gnus-error 1 "Error in %s" ding-file)))
- (when gnus-newsrc-assoc
- (setq gnus-newsrc-alist gnus-newsrc-assoc)))
- (gnus-make-hashtable-from-newsrc-alist)
- (when (file-newer-than-file-p file ding-file)
- ;; Old format quick file
- (gnus-message 5 "Reading %s..." file)
- ;; The .el file is newer than the .eld file, so we read that one
- ;; as well.
- (gnus-read-old-newsrc-el-file file))))
-
-;; Parse the old-style quick startup file
-(defun gnus-read-old-newsrc-el-file (file)
- (let (newsrc killed marked group m info)
- (prog1
- (let ((gnus-killed-assoc nil)
- gnus-marked-assoc gnus-newsrc-alist gnus-newsrc-assoc)
- (prog1
- (condition-case nil
- (load file t t t)
- (error nil))
- (setq newsrc gnus-newsrc-assoc
- killed gnus-killed-assoc
- marked gnus-marked-assoc)))
- (setq gnus-newsrc-alist nil)
- (while (setq group (pop newsrc))
- (if (setq info (gnus-get-info (car group)))
- (progn
- (gnus-info-set-read info (cddr group))
- (gnus-info-set-level
- info (if (nth 1 group) gnus-level-default-subscribed
- gnus-level-default-unsubscribed))
- (setq gnus-newsrc-alist (cons info gnus-newsrc-alist)))
- (push (setq info
- (list (car group)
- (if (nth 1 group) gnus-level-default-subscribed
- gnus-level-default-unsubscribed)
- (cddr group)))
- gnus-newsrc-alist))
- ;; Copy marks into info.
- (when (setq m (assoc (car group) marked))
- (unless (nthcdr 3 info)
- (nconc info (list nil)))
- (gnus-info-set-marks
- info (list (cons 'tick (gnus-compress-sequence
- (sort (cdr m) '<) t))))))
- (setq newsrc killed)
- (while newsrc
- (setcar newsrc (caar newsrc))
- (setq newsrc (cdr newsrc)))
- (setq gnus-killed-list killed))
- ;; The .el file version of this variable does not begin with
- ;; "options", while the .eld version does, so we just add it if it
- ;; isn't there.
- (and
- gnus-newsrc-options
- (progn
- (and (not (string-match "^ *options" gnus-newsrc-options))
- (setq gnus-newsrc-options (concat "options " gnus-newsrc-options)))
- (and (not (string-match "\n$" gnus-newsrc-options))
- (setq gnus-newsrc-options (concat gnus-newsrc-options "\n")))
- ;; Finally, if we read some options lines, we parse them.
- (or (string= gnus-newsrc-options "")
- (gnus-newsrc-parse-options gnus-newsrc-options))))
-
- (setq gnus-newsrc-alist (nreverse gnus-newsrc-alist))
- (gnus-make-hashtable-from-newsrc-alist)))
-
-(defun gnus-make-newsrc-file (file)
- "Make server dependent file name by catenating FILE and server host name."
- (let* ((file (expand-file-name file nil))
- (real-file (concat file "-" (nth 1 gnus-select-method))))
- (if (or (file-exists-p real-file)
- (file-exists-p (concat real-file ".el"))
- (file-exists-p (concat real-file ".eld")))
- real-file file)))
-
-(defun gnus-newsrc-to-gnus-format ()
- (setq gnus-newsrc-options "")
- (setq gnus-newsrc-options-n nil)
-
- (or gnus-active-hashtb
- (setq gnus-active-hashtb (make-vector 4095 0)))
- (let ((buf (current-buffer))
- (already-read (> (length gnus-newsrc-alist) 1))
- group subscribed options-symbol newsrc Options-symbol
- symbol reads num1)
- (goto-char (point-min))
- ;; We intern the symbol `options' in the active hashtb so that we
- ;; can `eq' against it later.
- (set (setq options-symbol (intern "options" gnus-active-hashtb)) nil)
- (set (setq Options-symbol (intern "Options" gnus-active-hashtb)) nil)
-
- (while (not (eobp))
- ;; We first read the first word on the line by narrowing and
- ;; then reading into `gnus-active-hashtb'. Most groups will
- ;; already exist in that hashtb, so this will save some string
- ;; space.
- (narrow-to-region
- (point)
- (progn (skip-chars-forward "^ \t!:\n") (point)))
- (goto-char (point-min))
- (setq symbol
- (and (/= (point-min) (point-max))
- (let ((obarray gnus-active-hashtb)) (read buf))))
- (widen)
- ;; Now, the symbol we have read is either `options' or a group
- ;; name. If it is an options line, we just add it to a string.
- (cond
- ((or (eq symbol options-symbol)
- (eq symbol Options-symbol))
- (setq gnus-newsrc-options
- ;; This concating is quite inefficient, but since our
- ;; thorough studies show that approx 99.37% of all
- ;; .newsrc files only contain a single options line, we
- ;; don't give a damn, frankly, my dear.
- (concat gnus-newsrc-options
- (buffer-substring
- (gnus-point-at-bol)
- ;; Options may continue on the next line.
- (or (and (re-search-forward "^[^ \t]" nil 'move)
- (progn (beginning-of-line) (point)))
- (point)))))
- (forward-line -1))
- (symbol
- ;; Group names can be just numbers.
- (when (numberp symbol)
- (setq symbol (intern (int-to-string symbol) gnus-active-hashtb)))
- (or (boundp symbol) (set symbol nil))
- ;; It was a group name.
- (setq subscribed (= (following-char) ?:)
- group (symbol-name symbol)
- reads nil)
- (if (eolp)
- ;; If the line ends here, this is clearly a buggy line, so
- ;; we put point a the beginning of line and let the cond
- ;; below do the error handling.
- (beginning-of-line)
- ;; We skip to the beginning of the ranges.
- (skip-chars-forward "!: \t"))
- ;; We are now at the beginning of the list of read articles.
- ;; We read them range by range.
- (while
- (cond
- ((looking-at "[0-9]+")
- ;; We narrow and read a number instead of buffer-substring/
- ;; string-to-int because it's faster. narrow/widen is
- ;; faster than save-restriction/narrow, and save-restriction
- ;; produces a garbage object.
- (setq num1 (progn
- (narrow-to-region (match-beginning 0) (match-end 0))
- (read buf)))
- (widen)
- ;; If the next character is a dash, then this is a range.
- (if (= (following-char) ?-)
- (progn
- ;; We read the upper bound of the range.
- (forward-char 1)
- (if (not (looking-at "[0-9]+"))
- ;; This is a buggy line, by we pretend that
- ;; it's kinda OK. Perhaps the user should be
- ;; dinged?
- (setq reads (cons num1 reads))
- (setq reads
- (cons
- (cons num1
- (progn
- (narrow-to-region (match-beginning 0)
- (match-end 0))
- (read buf)))
- reads))
- (widen)))
- ;; It was just a simple number, so we add it to the
- ;; list of ranges.
- (setq reads (cons num1 reads)))
- ;; If the next char in ?\n, then we have reached the end
- ;; of the line and return nil.
- (/= (following-char) ?\n))
- ((= (following-char) ?\n)
- ;; End of line, so we end.
- nil)
- (t
- ;; Not numbers and not eol, so this might be a buggy
- ;; line...
- (or (eobp)
- ;; If it was eob instead of ?\n, we allow it.
- (progn
- ;; The line was buggy.
- (setq group nil)
- (gnus-error 3.1 "Mangled line: %s"
- (buffer-substring (gnus-point-at-bol)
- (gnus-point-at-eol)))))
- nil))
- ;; Skip past ", ". Spaces are illegal in these ranges, but
- ;; we allow them, because it's a common mistake to put a
- ;; space after the comma.
- (skip-chars-forward ", "))
-
- ;; We have already read .newsrc.eld, so we gently update the
- ;; data in the hash table with the information we have just
- ;; read.
- (when group
- (let ((info (gnus-get-info group))
- level)
- (if info
- ;; There is an entry for this file in the alist.
- (progn
- (gnus-info-set-read info (nreverse reads))
- ;; We update the level very gently. In fact, we
- ;; only change it if there's been a status change
- ;; from subscribed to unsubscribed, or vice versa.
- (setq level (gnus-info-level info))
- (cond ((and (<= level gnus-level-subscribed)
- (not subscribed))
- (setq level (if reads
- gnus-level-default-unsubscribed
- (1+ gnus-level-default-unsubscribed))))
- ((and (> level gnus-level-subscribed) subscribed)
- (setq level gnus-level-default-subscribed)))
- (gnus-info-set-level info level))
- ;; This is a new group.
- (setq info (list group
- (if subscribed
- gnus-level-default-subscribed
- (if reads
- (1+ gnus-level-subscribed)
- gnus-level-default-unsubscribed))
- (nreverse reads))))
- (setq newsrc (cons info newsrc))))))
- (forward-line 1))
-
- (setq newsrc (nreverse newsrc))
-
- (if (not already-read)
- ()
- ;; We now have two newsrc lists - `newsrc', which is what we
- ;; have read from .newsrc, and `gnus-newsrc-alist', which is
- ;; what we've read from .newsrc.eld. We have to merge these
- ;; lists. We do this by "attaching" any (foreign) groups in the
- ;; gnus-newsrc-alist to the (native) group that precedes them.
- (let ((rc (cdr gnus-newsrc-alist))
- (prev gnus-newsrc-alist)
- entry mentry)
- (while rc
- (or (null (nth 4 (car rc))) ; It's a native group.
- (assoc (caar rc) newsrc) ; It's already in the alist.
- (if (setq entry (assoc (caar prev) newsrc))
- (setcdr (setq mentry (memq entry newsrc))
- (cons (car rc) (cdr mentry)))
- (setq newsrc (cons (car rc) newsrc))))
- (setq prev rc
- rc (cdr rc)))))
-
- (setq gnus-newsrc-alist newsrc)
- ;; We make the newsrc hashtb.
- (gnus-make-hashtable-from-newsrc-alist)
-
- ;; Finally, if we read some options lines, we parse them.
- (or (string= gnus-newsrc-options "")
- (gnus-newsrc-parse-options gnus-newsrc-options))))
-
-;; Parse options lines to find "options -n !all rec.all" and stuff.
-;; The return value will be a list on the form
-;; ((regexp1 . ignore)
-;; (regexp2 . subscribe)...)
-;; When handling new newsgroups, groups that match a `ignore' regexp
-;; will be ignored, and groups that match a `subscribe' regexp will be
-;; subscribed. A line like
-;; options -n !all rec.all
-;; will lead to a list that looks like
-;; (("^rec\\..+" . subscribe)
-;; ("^.+" . ignore))
-;; So all "rec.*" groups will be subscribed, while all the other
-;; groups will be ignored. Note that "options -n !all rec.all" is very
-;; different from "options -n rec.all !all".
-(defun gnus-newsrc-parse-options (options)
- (let (out eol)
- (save-excursion
- (gnus-set-work-buffer)
- (insert (regexp-quote options))
- ;; First we treat all continuation lines.
- (goto-char (point-min))
- (while (re-search-forward "\n[ \t]+" nil t)
- (replace-match " " t t))
- ;; Then we transform all "all"s into ".+"s.
- (goto-char (point-min))
- (while (re-search-forward "\\ball\\b" nil t)
- (replace-match ".+" t t))
- (goto-char (point-min))
- ;; We remove all other options than the "-n" ones.
- (while (re-search-forward "[ \t]-[^n][^-]*" nil t)
- (replace-match " ")
- (forward-char -1))
- (goto-char (point-min))
-
- ;; We are only interested in "options -n" lines - we
- ;; ignore the other option lines.
- (while (re-search-forward "[ \t]-n" nil t)
- (setq eol
- (or (save-excursion
- (and (re-search-forward "[ \t]-n" (gnus-point-at-eol) t)
- (- (point) 2)))
- (gnus-point-at-eol)))
- ;; Search for all "words"...
- (while (re-search-forward "[^ \t,\n]+" eol t)
- (if (= (char-after (match-beginning 0)) ?!)
- ;; If the word begins with a bang (!), this is a "not"
- ;; spec. We put this spec (minus the bang) and the
- ;; symbol `ignore' into the list.
- (setq out (cons (cons (concat
- "^" (buffer-substring
- (1+ (match-beginning 0))
- (match-end 0)))
- 'ignore) out))
- ;; There was no bang, so this is a "yes" spec.
- (setq out (cons (cons (concat "^" (match-string 0))
- 'subscribe) out)))))
-
- (setq gnus-newsrc-options-n out))))
-
-(defun gnus-save-newsrc-file (&optional force)
- "Save .newsrc file."
- ;; Note: We cannot save .newsrc file if all newsgroups are removed
- ;; from the variable gnus-newsrc-alist.
- (when (and (or gnus-newsrc-alist gnus-killed-list)
- gnus-current-startup-file)
- (save-excursion
- (if (and (or gnus-use-dribble-file gnus-slave)
- (not force)
- (or (not gnus-dribble-buffer)
- (not (buffer-name gnus-dribble-buffer))
- (zerop (save-excursion
- (set-buffer gnus-dribble-buffer)
- (buffer-size)))))
- (gnus-message 4 "(No changes need to be saved)")
- (run-hooks 'gnus-save-newsrc-hook)
- (if gnus-slave
- (gnus-slave-save-newsrc)
- ;; Save .newsrc.
- (when gnus-save-newsrc-file
- (gnus-message 5 "Saving %s..." gnus-current-startup-file)
- (gnus-gnus-to-newsrc-format)
- (gnus-message 5 "Saving %s...done" gnus-current-startup-file))
- ;; Save .newsrc.eld.
- (set-buffer (get-buffer-create " *Gnus-newsrc*"))
- (make-local-variable 'version-control)
- (setq version-control 'never)
- (setq buffer-file-name
- (concat gnus-current-startup-file ".eld"))
- (setq default-directory (file-name-directory buffer-file-name))
- (gnus-add-current-to-buffer-list)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (gnus-message 5 "Saving %s.eld..." gnus-current-startup-file)
- (gnus-gnus-to-quick-newsrc-format)
- (run-hooks 'gnus-save-quick-newsrc-hook)
- (save-buffer)
- (kill-buffer (current-buffer))
- (gnus-message
- 5 "Saving %s.eld...done" gnus-current-startup-file))
- (gnus-dribble-delete-file)
- (gnus-group-set-mode-line)))))
-
-(defun gnus-gnus-to-quick-newsrc-format ()
- "Insert Gnus variables such as gnus-newsrc-alist in lisp format."
- (insert ";; Gnus startup file.\n")
- (insert ";; Never delete this file - touch .newsrc instead to force Gnus\n")
- (insert ";; to read .newsrc.\n")
- (insert "(setq gnus-newsrc-file-version "
- (prin1-to-string gnus-version) ")\n")
- (let ((variables
- (if gnus-save-killed-list gnus-variable-list
- ;; Remove the `gnus-killed-list' from the list of variables
- ;; to be saved, if required.
- (delq 'gnus-killed-list (copy-sequence gnus-variable-list))))
- ;; Peel off the "dummy" group.
- (gnus-newsrc-alist (cdr gnus-newsrc-alist))
- variable)
- ;; Insert the variables into the file.
- (while variables
- (when (and (boundp (setq variable (pop variables)))
- (symbol-value variable))
- (insert "(setq " (symbol-name variable) " '")
- (prin1 (symbol-value variable) (current-buffer))
- (insert ")\n")))))
-
-(defun gnus-gnus-to-newsrc-format ()
- ;; Generate and save the .newsrc file.
- (save-excursion
- (set-buffer (create-file-buffer gnus-current-startup-file))
- (let ((newsrc (cdr gnus-newsrc-alist))
- (standard-output (current-buffer))
- info ranges range method)
- (setq buffer-file-name gnus-current-startup-file)
- (setq default-directory (file-name-directory buffer-file-name))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- ;; Write options.
- (if gnus-newsrc-options (insert gnus-newsrc-options))
- ;; Write subscribed and unsubscribed.
- (while (setq info (pop newsrc))
- ;; Don't write foreign groups to .newsrc.
- (when (or (null (setq method (gnus-info-method info)))
- (equal method "native")
- (gnus-server-equal method gnus-select-method))
- (insert (gnus-info-group info)
- (if (> (gnus-info-level info) gnus-level-subscribed)
- "!" ":"))
- (when (setq ranges (gnus-info-read info))
- (insert " ")
- (if (not (listp (cdr ranges)))
- (if (= (car ranges) (cdr ranges))
- (princ (car ranges))
- (princ (car ranges))
- (insert "-")
- (princ (cdr ranges)))
- (while (setq range (pop ranges))
- (if (or (atom range) (= (car range) (cdr range)))
- (princ (or (and (atom range) range) (car range)))
- (princ (car range))
- (insert "-")
- (princ (cdr range)))
- (if ranges (insert ",")))))
- (insert "\n")))
- (make-local-variable 'version-control)
- (setq version-control 'never)
- ;; It has been reported that sometime the modtime on the .newsrc
- ;; file seems to be off. We really do want to overwrite it, so
- ;; we clear the modtime here before saving. It's a bit odd,
- ;; though...
- ;; sometimes the modtime clear isn't sufficient. most brute force:
- ;; delete the silly thing entirely first. but this fails to provide
- ;; such niceties as .newsrc~ creation.
- (if gnus-modtime-botch
- (delete-file gnus-startup-file)
- (clear-visited-file-modtime))
- (run-hooks 'gnus-save-standard-newsrc-hook)
- (save-buffer)
- (kill-buffer (current-buffer)))))
-
-
-;;;
-;;; Slave functions.
-;;;
-
-(defun gnus-slave-save-newsrc ()
- (save-excursion
- (set-buffer gnus-dribble-buffer)
- (let ((slave-name
- (make-temp-name (concat gnus-current-startup-file "-slave-"))))
- (write-region (point-min) (point-max) slave-name nil 'nomesg))))
-
-(defun gnus-master-read-slave-newsrc ()
- (let ((slave-files
- (directory-files
- (file-name-directory gnus-current-startup-file)
- t (concat
- "^" (regexp-quote
- (concat
- (file-name-nondirectory gnus-current-startup-file)
- "-slave-")))
- t))
- file)
- (if (not slave-files)
- () ; There are no slave files to read.
- (gnus-message 7 "Reading slave newsrcs...")
- (save-excursion
- (set-buffer (get-buffer-create " *gnus slave*"))
- (buffer-disable-undo (current-buffer))
- (setq slave-files
- (sort (mapcar (lambda (file)
- (list (nth 5 (file-attributes file)) file))
- slave-files)
- (lambda (f1 f2)
- (or (< (caar f1) (caar f2))
- (< (nth 1 (car f1)) (nth 1 (car f2)))))))
- (while slave-files
- (erase-buffer)
- (setq file (nth 1 (car slave-files)))
- (insert-file-contents file)
- (if (condition-case ()
- (progn
- (eval-buffer (current-buffer))
- t)
- (error
- (gnus-error 3.2 "Possible error in %s" file)
- nil))
- (or gnus-slave ; Slaves shouldn't delete these files.
- (condition-case ()
- (delete-file file)
- (error nil))))
- (setq slave-files (cdr slave-files))))
- (gnus-message 7 "Reading slave newsrcs...done"))))
-
-
-;;;
-;;; Group description.
-;;;
-
-(defun gnus-read-all-descriptions-files ()
- (let ((methods (cons gnus-select-method
- (nconc
- (when (gnus-archive-server-wanted-p)
- (list "archive"))
- gnus-secondary-select-methods))))
- (while methods
- (gnus-read-descriptions-file (car methods))
- (setq methods (cdr methods)))
- t))
-
-(defun gnus-read-descriptions-file (&optional method)
- (let ((method (or method gnus-select-method))
- group)
- (when (stringp method)
- (setq method (gnus-server-to-method method)))
- ;; We create the hashtable whether we manage to read the desc file
- ;; to avoid trying to re-read after a failed read.
- (or gnus-description-hashtb
- (setq gnus-description-hashtb
- (gnus-make-hashtable (length gnus-active-hashtb))))
- ;; Mark this method's desc file as read.
- (gnus-sethash (gnus-group-prefixed-name "" method) "Has read"
- gnus-description-hashtb)
-
- (gnus-message 5 "Reading descriptions file via %s..." (car method))
- (cond
- ((not (gnus-check-server method))
- (gnus-message 1 "Couldn't open server")
- nil)
- ((not (gnus-request-list-newsgroups method))
- (gnus-message 1 "Couldn't read newsgroups descriptions")
- nil)
- (t
- (save-excursion
- (save-restriction
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (when (or (search-forward "\n.\n" nil t)
- (goto-char (point-max)))
- (beginning-of-line)
- (narrow-to-region (point-min) (point)))
- ;; If these are groups from a foreign select method, we insert the
- ;; group prefix in front of the group names.
- (and method (not (gnus-server-equal
- (gnus-server-get-method nil method)
- (gnus-server-get-method nil gnus-select-method)))
- (let ((prefix (gnus-group-prefixed-name "" method)))
- (goto-char (point-min))
- (while (and (not (eobp))
- (progn (insert prefix)
- (zerop (forward-line 1)))))))
- (goto-char (point-min))
- (while (not (eobp))
- ;; If we get an error, we set group to 0, which is not a
- ;; symbol...
- (setq group
- (condition-case ()
- (let ((obarray gnus-description-hashtb))
- ;; Group is set to a symbol interned in this
- ;; hash table.
- (read nntp-server-buffer))
- (error 0)))
- (skip-chars-forward " \t")
- ;; ... which leads to this line being effectively ignored.
- (and (symbolp group)
- (set group (buffer-substring
- (point) (progn (end-of-line) (point)))))
- (forward-line 1))))
- (gnus-message 5 "Reading descriptions file...done")
- t))))
-
-(defun gnus-group-get-description (group)
- "Get the description of a group by sending XGTITLE to the server."
- (when (gnus-request-group-description group)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (when (looking-at "[^ \t]+[ \t]+\\(.*\\)")
- (match-string 1)))))
-
-
-;;;
-;;; Buffering of read articles.
-;;;
-
-(defvar gnus-backlog-buffer " *Gnus Backlog*")
-(defvar gnus-backlog-articles nil)
-(defvar gnus-backlog-hashtb nil)
-
-(defun gnus-backlog-buffer ()
- "Return the backlog buffer."
- (or (get-buffer gnus-backlog-buffer)
- (save-excursion
- (set-buffer (get-buffer-create gnus-backlog-buffer))
- (buffer-disable-undo (current-buffer))
- (setq buffer-read-only t)
- (gnus-add-current-to-buffer-list)
- (get-buffer gnus-backlog-buffer))))
-
-(defun gnus-backlog-setup ()
- "Initialize backlog variables."
- (unless gnus-backlog-hashtb
- (setq gnus-backlog-hashtb (make-vector 1023 0))))
-
-(gnus-add-shutdown 'gnus-backlog-shutdown 'gnus)
-
-(defun gnus-backlog-shutdown ()
- "Clear all backlog variables and buffers."
- (when (get-buffer gnus-backlog-buffer)
- (kill-buffer gnus-backlog-buffer))
- (setq gnus-backlog-hashtb nil
- gnus-backlog-articles nil))
-
-(defun gnus-backlog-enter-article (group number buffer)
- (gnus-backlog-setup)
- (let ((ident (intern (concat group ":" (int-to-string number))
- gnus-backlog-hashtb))
- b)
- (if (memq ident gnus-backlog-articles)
- () ; It's already kept.
- ;; Remove the oldest article, if necessary.
- (and (numberp gnus-keep-backlog)
- (>= (length gnus-backlog-articles) gnus-keep-backlog)
- (gnus-backlog-remove-oldest-article))
- (setq gnus-backlog-articles (cons ident gnus-backlog-articles))
- ;; Insert the new article.
- (save-excursion
- (set-buffer (gnus-backlog-buffer))
- (let (buffer-read-only)
- (goto-char (point-max))
- (or (bolp) (insert "\n"))
- (setq b (point))
- (insert-buffer-substring buffer)
- ;; Tag the beginning of the article with the ident.
- (gnus-put-text-property b (1+ b) 'gnus-backlog ident))))))
-
-(defun gnus-backlog-remove-oldest-article ()
- (save-excursion
- (set-buffer (gnus-backlog-buffer))
- (goto-char (point-min))
- (if (zerop (buffer-size))
- () ; The buffer is empty.
- (let ((ident (get-text-property (point) 'gnus-backlog))
- buffer-read-only)
- ;; Remove the ident from the list of articles.
- (when ident
- (setq gnus-backlog-articles (delq ident gnus-backlog-articles)))
- ;; Delete the article itself.
- (delete-region
- (point) (next-single-property-change
- (1+ (point)) 'gnus-backlog nil (point-max)))))))
-
-(defun gnus-backlog-remove-article (group number)
- "Remove article NUMBER in GROUP from the backlog."
- (when (numberp number)
- (gnus-backlog-setup)
- (let ((ident (intern (concat group ":" (int-to-string number))
- gnus-backlog-hashtb))
- beg end)
- (when (memq ident gnus-backlog-articles)
- ;; It was in the backlog.
- (save-excursion
- (set-buffer (gnus-backlog-buffer))
- (let (buffer-read-only)
- (when (setq beg (text-property-any
- (point-min) (point-max) 'gnus-backlog
- ident))
- ;; Find the end (i. e., the beginning of the next article).
- (setq end
- (next-single-property-change
- (1+ beg) 'gnus-backlog (current-buffer) (point-max)))
- (delete-region beg end)
- ;; Return success.
- t)))))))
-
-(defun gnus-backlog-request-article (group number buffer)
- (when (numberp number)
- (gnus-backlog-setup)
- (let ((ident (intern (concat group ":" (int-to-string number))
- gnus-backlog-hashtb))
- beg end)
- (when (memq ident gnus-backlog-articles)
- ;; It was in the backlog.
- (save-excursion
- (set-buffer (gnus-backlog-buffer))
- (if (not (setq beg (text-property-any
- (point-min) (point-max) 'gnus-backlog
- ident)))
- ;; It wasn't in the backlog after all.
- (ignore
- (setq gnus-backlog-articles (delq ident gnus-backlog-articles)))
- ;; Find the end (i. e., the beginning of the next article).
- (setq end
- (next-single-property-change
- (1+ beg) 'gnus-backlog (current-buffer) (point-max)))))
- (let ((buffer-read-only nil))
- (erase-buffer)
- (insert-buffer-substring gnus-backlog-buffer beg end)
- t)))))
-
-;; Allow redefinition of Gnus functions.
-
-(gnus-ems-redefine)
-
-(provide 'gnus)
-
-;;; gnus.el ends here
diff --git a/lisp/goto-addr.el b/lisp/goto-addr.el
deleted file mode 100644
index ecf64b3dcfb..00000000000
--- a/lisp/goto-addr.el
+++ /dev/null
@@ -1,241 +0,0 @@
-;;; goto-addr.el --- click to browse URL or to send to e-mail address
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Eric Ding <ericding@mit.edu>
-;; Maintainer: Eric Ding <ericding@mit.edu>
-;; Created: 15 Aug 1995
-;; Keywords: mh-e, www, mouse, mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package allows you to click or hit a key sequence while on a
-;; URL or e-mail address, and either load the URL into a browser of
-;; your choice using the browse-url package, or if it's an e-mail
-;; address, to send an e-mail to that address. By default, we bind to
-;; the [mouse-2] and the [C-c return] key sequences.
-
-;; INSTALLATION
-;;
-;; To use goto-address in a particular mode (for example, while
-;; reading mail in mh-e), add something like this in your .emacs file:
-;;
-;; (add-hook 'mh-show-mode-hook 'goto-address)
-;;
-;; By default, goto-address now sends using `mail' instead of `mh-send'.
-;; To use mh-e to send mail, add the following to your .emacs file:
-;;
-;; (setq goto-address-mail-method 'goto-address-send-using-mh-e)
-;;
-;; The mouse click method is bound to [mouse-2] on highlighted URL's or
-;; e-mail addresses only; it functions normally everywhere else. To bind
-;; another mouse click to the function, add the following to your .emacs
-;; (for example):
-;;
-;; (setq goto-address-highlight-keymap
-;; (let ((m (make-sparse-keymap)))
-;; (define-key m [S-mouse-2] 'goto-address-at-mouse)
-;; m))
-;;
-
-;; BUG REPORTS
-;;
-;; Please send bug reports to me at ericding@mit.edu.
-
-;; Known bugs/features:
-;; * goto-address-mail-regexp only catches foo@bar.org style addressing,
-;; not stuff like X.400 addresses, etc.
-;; * regexp also catches Message-Id line, since it is in the format of
-;; an Internet e-mail address (like Compuserve addresses)
-;; * If show buffer is fontified after goto-address-fontify is run
-;; (say, using font-lock-fontify-buffer), then font-lock face will
-;; override goto-address faces.
-
-;;; Code:
-
-(require 'browse-url)
-
-;;; I don't expect users to want fontify'ing without highlighting.
-(defvar goto-address-fontify-p t
- "*If t, URL's and e-mail addresses in buffer are fontified.
-But only if `goto-address-highlight-p' is also non-nil.")
-
-(defvar goto-address-highlight-p t
- "*If t, URL's and e-mail addresses in buffer are highlighted.")
-
-(defvar goto-address-fontify-maximum-size 30000
- "*Maximum size of file in which to fontify and/or highlight URL's.")
-
-(defvar goto-address-mail-regexp
- "[-a-zA-Z0-9._]+@\\([-a-zA-z0-9_]+\\.\\)+[a-zA-Z0-9]+"
- "A regular expression probably matching an e-mail address.")
-
-(defvar goto-address-url-regexp
- (concat "\\b\\(s?https?\\|ftp\\|file\\|gopher\\|news\\|"
- "telnet\\|wais\\):\\(//[-a-zA-Z0-9_.]+:"
- "[0-9]*\\)?[-a-zA-Z0-9_=?#$@~`%&*+|\\/.,]*"
- "[-a-zA-Z0-9_=#$@~`%&*+|\\/]")
- "A regular expression probably matching a URL.")
-
-(defvar goto-address-mail-method
- 'goto-address-send-using-mail
- "*Function to compose mail.
-Two pre-made functions are `goto-address-send-using-mail' (sendmail);
-and `goto-address-send-using-mh-e' (MH-E).")
-
-(defvar goto-address-highlight-keymap
- (let ((m (make-sparse-keymap)))
- (define-key m [mouse-2] 'goto-address-at-mouse)
- m)
- "keymap to hold goto-addr's mouse key defs under highlighted URLs.")
-
-(defvar goto-address-url-face 'bold
- "*Face to use for URLs.")
-
-(defvar goto-address-url-mouse-face 'highlight
- "*Face to use for URLs when the mouse is on them.")
-
-(defvar goto-address-mail-face 'italic
- "*Face to use for e-mail addresses.")
-
-(defvar goto-address-mail-mouse-face 'secondary-selection
- "*Face to use for e-mail addresses when the mouse is on them.")
-
-(defun goto-address-fontify ()
- "Fontify the URL's and e-mail addresses in the current buffer.
-This function implements `goto-address-highlight-p'
-and `goto-address-fontify-p'."
- (save-excursion
- (let ((inhibit-read-only t)
- (inhibit-point-motion-hooks t)
- (modified (buffer-modified-p)))
- (goto-char (point-min))
- (if (< (- (point-max) (point)) goto-address-fontify-maximum-size)
- (progn
- (while (re-search-forward goto-address-url-regexp nil t)
- (let* ((s (match-beginning 0))
- (e (match-end 0))
- (this-overlay (make-overlay s e)))
- (and goto-address-fontify-p
- (overlay-put this-overlay 'face goto-address-url-face))
- (overlay-put this-overlay
- 'mouse-face goto-address-url-mouse-face)
- (overlay-put this-overlay
- 'local-map goto-address-highlight-keymap)))
- (goto-char (point-min))
- (while (re-search-forward goto-address-mail-regexp nil t)
- (let* ((s (match-beginning 0))
- (e (match-end 0))
- (this-overlay (make-overlay s e)))
- (and goto-address-fontify-p
- (overlay-put this-overlay 'face goto-address-mail-face))
- (overlay-put this-overlay 'mouse-face
- goto-address-mail-mouse-face)
- (overlay-put this-overlay
- 'local-map goto-address-highlight-keymap)))))
- (and (buffer-modified-p)
- (not modified)
- (set-buffer-modified-p nil)))))
-
-;;; code to find and goto addresses; much of this has been blatantly
-;;; snarfed from browse-url.el
-
-;;;###autoload
-(defun goto-address-at-mouse (event)
- "Send to the e-mail address or load the URL clicked with the mouse.
-Send mail to address at position of mouse click. See documentation for
-`goto-address-find-address-at-point'. If no address is found
-there, then load the URL at or before the position of the mouse click."
- (interactive "e")
- (save-excursion
- (let ((posn (event-start event)))
- (set-buffer (window-buffer (posn-window posn)))
- (goto-char (posn-point posn))
- (let ((address
- (save-excursion (goto-address-find-address-at-point))))
- (if (string-equal address "")
- (let ((url (browse-url-url-at-point)))
- (if (string-equal url "")
- (error "No e-mail address or URL found")
- (funcall browse-url-browser-function url)))
- (funcall goto-address-mail-method address))))))
-
-;;;###autoload
-(defun goto-address-at-point ()
- "Send to the e-mail address or load the URL at point.
-Send mail to address at point. See documentation for
-`goto-address-find-address-at-point'. If no address is found
-there, then load the URL at or before point."
- (interactive)
- (save-excursion
- (let ((address (save-excursion (goto-address-find-address-at-point))))
- (if (string-equal address "")
- (let ((url (browse-url-url-at-point)))
- (if (string-equal url "")
- (error "No e-mail address or URL found")
- (funcall browse-url-browser-function url)))
- (funcall goto-address-mail-method address)))))
-
-(defun goto-address-find-address-at-point ()
- "Find e-mail address around or before point.
-Then search backwards to beginning of line for the start of an e-mail
-address. If no e-mail address found, return the empty string."
- (let ((bol (save-excursion (beginning-of-line) (point))))
- (re-search-backward "[^-_A-z0-9.@]" bol 'lim)
- (if (or (looking-at goto-address-mail-regexp) ; already at start
- (let ((eol (save-excursion (end-of-line) (point))))
- (and (re-search-forward goto-address-mail-regexp eol 'lim)
- (goto-char (match-beginning 0)))))
- (buffer-substring (match-beginning 0) (match-end 0))
- "")))
-
-(defun goto-address-send-using-mh-e (to)
- (require 'mh-comp)
- (mh-find-path)
- (let ((cc (mh-read-address "Cc: "))
- (subject (read-string "Subject: "))
- (config (current-window-configuration)))
- (delete-other-windows)
- (mh-send-sub to cc subject config)))
-
-(fset 'goto-address-send-using-mhe 'goto-address-send-using-mh-e)
-
-(defun goto-address-send-using-mail (to)
- (mail-other-window nil to)
- (and (goto-char (point-min))
- (end-of-line 2)))
-
-;;;###autoload
-(defun goto-address ()
- "Sets up goto-address functionality in the current buffer.
-Allows user to use mouse/keyboard command to click to go to a URL
-or to send e-mail.
-By default, goto-address binds to mouse-2 and C-c RET.
-
-Also fontifies the buffer appropriately (see `goto-address-fontify-p' and
-`goto-address-highlight-p' for more information)."
- (interactive)
- (local-set-key "\C-c\r" 'goto-address-at-point)
- (if goto-address-highlight-p
- (goto-address-fontify)))
-
-(provide 'goto-addr)
-
-;;; goto-addr.el ends here.
diff --git a/lisp/gud.el b/lisp/gud.el
deleted file mode 100644
index ad279c082d7..00000000000
--- a/lisp/gud.el
+++ /dev/null
@@ -1,1628 +0,0 @@
-;;; gud.el --- Grand Unified Debugger mode for gdb, dbx, etc. under Emacs
-
-;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
-;; Maintainer: FSF
-;; Keywords: unix, tools
-
-;; Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The ancestral gdb.el was by W. Schelter <wfs@rascal.ics.utexas.edu>
-;; It was later rewritten by rms. Some ideas were due to Masanobu.
-;; Grand Unification (sdb/dbx support) by Eric S. Raymond <esr@thyrsus.com>
-;; The overloading code was then rewritten by Barry Warsaw <bwarsaw@cen.com>,
-;; who also hacked the mode to use comint.el. Shane Hartman <shane@spr.com>
-;; added support for xdb (HPUX debugger). Rick Sladkey <jrs@world.std.com>
-;; wrote the GDB command completion code. Dave Love <d.love@dl.ac.uk>
-;; added the IRIX kluge, re-implemented the Mips-ish variant and added
-;; a menu. Brian D. Carlstrom <bdc@ai.mit.edu> combined the IRIX kluge with
-;; the gud-xdb-directories hack producing gud-dbx-directories.
-
-;;; Code:
-
-(require 'comint)
-(require 'etags)
-
-;; ======================================================================
-;; GUD commands must be visible in C buffers visited by GUD
-
-(defvar gud-key-prefix "\C-x\C-a"
- "Prefix of all GUD commands valid in C buffers.")
-
-(global-set-key (concat gud-key-prefix "\C-l") 'gud-refresh)
-(define-key ctl-x-map " " 'gud-break) ;; backward compatibility hack
-
-(defvar gud-marker-filter nil)
-(put 'gud-marker-filter 'permanent-local t)
-(defvar gud-find-file nil)
-(put 'gud-find-file 'permanent-local t)
-
-(defun gud-marker-filter (&rest args)
- (apply gud-marker-filter args))
-
-(defun gud-find-file (file)
- ;; Don't get confused by double slashes in the name that comes from GDB.
- (while (string-match "//+" file)
- (setq file (replace-match "/" t t file)))
- (funcall gud-find-file file))
-
-;; Keymap definitions for menu bar entries common to all debuggers and
-;; slots for debugger-dependent ones in sensible places. (Defined here
-;; before use.)
-(defvar gud-menu-map (make-sparse-keymap "Gud") nil)
-(define-key gud-menu-map [refresh] '("Refresh" . gud-refresh))
-(define-key gud-menu-map [remove] '("Remove Breakpoint" . gud-remove))
-(define-key gud-menu-map [tbreak] nil) ; gdb, sdb and xdb
-(define-key gud-menu-map [break] '("Set Breakpoint" . gud-break))
-(define-key gud-menu-map [up] nil) ; gdb, dbx, and xdb
-(define-key gud-menu-map [down] nil) ; gdb, dbx, and xdb
-(define-key gud-menu-map [print] '("Print Expression" . gud-print))
-(define-key gud-menu-map [finish] nil) ; gdb or xdb
-(define-key gud-menu-map [stepi] '("Step Instruction" . gud-stepi))
-(define-key gud-menu-map [step] '("Step Line" . gud-step))
-(define-key gud-menu-map [next] '("Next Line" . gud-next))
-(define-key gud-menu-map [cont] '("Continue" . gud-cont))
-
-;; ======================================================================
-;; command definition
-
-;; This macro is used below to define some basic debugger interface commands.
-;; Of course you may use `gud-def' with any other debugger command, including
-;; user defined ones.
-
-;; A macro call like (gud-def FUNC NAME KEY DOC) expands to a form
-;; which defines FUNC to send the command NAME to the debugger, gives
-;; it the docstring DOC, and binds that function to KEY in the GUD
-;; major mode. The function is also bound in the global keymap with the
-;; GUD prefix.
-
-(defmacro gud-def (func cmd key &optional doc)
- "Define FUNC to be a command sending STR and bound to KEY, with
-optional doc string DOC. Certain %-escapes in the string arguments
-are interpreted specially if present. These are:
-
- %f name (without directory) of current source file.
- %d directory of current source file.
- %l number of current source line
- %e text of the C lvalue or function-call expression surrounding point.
- %a text of the hexadecimal address surrounding point
- %p prefix argument to the command (if any) as a number
-
- The `current' source file is the file of the current buffer (if
-we're in a C file) or the source file current at the last break or
-step (if we're in the GUD buffer).
- The `current' line is that of the current buffer (if we're in a
-source file) or the source line number at the last break or step (if
-we're in the GUD buffer)."
- (list 'progn
- (list 'defun func '(arg)
- (or doc "")
- '(interactive "p")
- (list 'gud-call cmd 'arg))
- (if key
- (list 'define-key
- '(current-local-map)
- (concat "\C-c" key)
- (list 'quote func)))
- (if key
- (list 'global-set-key
- (list 'concat 'gud-key-prefix key)
- (list 'quote func)))))
-
-;; Where gud-display-frame should put the debugging arrow. This is
-;; set by the marker-filter, which scans the debugger's output for
-;; indications of the current program counter.
-(defvar gud-last-frame nil)
-
-;; Used by gud-refresh, which should cause gud-display-frame to redisplay
-;; the last frame, even if it's been called before and gud-last-frame has
-;; been set to nil.
-(defvar gud-last-last-frame nil)
-
-;; All debugger-specific information is collected here.
-;; Here's how it works, in case you ever need to add a debugger to the mode.
-;;
-;; Each entry must define the following at startup:
-;;
-;;<name>
-;; comint-prompt-regexp
-;; gud-<name>-massage-args
-;; gud-<name>-marker-filter
-;; gud-<name>-find-file
-;;
-;; The job of the massage-args method is to modify the given list of
-;; debugger arguments before running the debugger.
-;;
-;; The job of the marker-filter method is to detect file/line markers in
-;; strings and set the global gud-last-frame to indicate what display
-;; action (if any) should be triggered by the marker. Note that only
-;; whatever the method *returns* is displayed in the buffer; thus, you
-;; can filter the debugger's output, interpreting some and passing on
-;; the rest.
-;;
-;; The job of the find-file method is to visit and return the buffer indicated
-;; by the car of gud-tag-frame. This may be a file name, a tag name, or
-;; something else. It would be good if it also copied the Gud menubar entry.
-
-;; ======================================================================
-;; gdb functions
-
-;;; History of argument lists passed to gdb.
-(defvar gud-gdb-history nil)
-
-(defun gud-gdb-massage-args (file args)
- (cons "-fullname" args))
-
-(defvar gud-gdb-marker-regexp
- (concat "\032\032\\([^" path-separator "\n]*\\)" path-separator
- "\\([0-9]*\\)" path-separator ".*\n"))
-
-;; There's no guarantee that Emacs will hand the filter the entire
-;; marker at once; it could be broken up across several strings. We
-;; might even receive a big chunk with several markers in it. If we
-;; receive a chunk of text which looks like it might contain the
-;; beginning of a marker, we save it here between calls to the
-;; filter.
-(defvar gud-marker-acc "")
-(make-variable-buffer-local 'gud-marker-acc)
-
-(defun gud-gdb-marker-filter (string)
- (setq gud-marker-acc (concat gud-marker-acc string))
- (let ((output ""))
-
- ;; Process all the complete markers in this chunk.
- (while (string-match gud-gdb-marker-regexp gud-marker-acc)
- (setq
-
- ;; Extract the frame position from the marker.
- gud-last-frame
- (cons (substring gud-marker-acc (match-beginning 1) (match-end 1))
- (string-to-int (substring gud-marker-acc
- (match-beginning 2)
- (match-end 2))))
-
- ;; Append any text before the marker to the output we're going
- ;; to return - we don't include the marker in this text.
- output (concat output
- (substring gud-marker-acc 0 (match-beginning 0)))
-
- ;; Set the accumulator to the remaining text.
- gud-marker-acc (substring gud-marker-acc (match-end 0))))
-
- ;; Does the remaining text look like it might end with the
- ;; beginning of another marker? If it does, then keep it in
- ;; gud-marker-acc until we receive the rest of it. Since we
- ;; know the full marker regexp above failed, it's pretty simple to
- ;; test for marker starts.
- (if (string-match "\032.*\\'" gud-marker-acc)
- (progn
- ;; Everything before the potential marker start can be output.
- (setq output (concat output (substring gud-marker-acc
- 0 (match-beginning 0))))
-
- ;; Everything after, we save, to combine with later input.
- (setq gud-marker-acc
- (substring gud-marker-acc (match-beginning 0))))
-
- (setq output (concat output gud-marker-acc)
- gud-marker-acc ""))
-
- output))
-
-(defun gud-gdb-find-file (f)
- (save-excursion
- (let ((buf (find-file-noselect f)))
- (set-buffer buf)
- (gud-make-debug-menu)
- (local-set-key [menu-bar debug tbreak]
- '("Temporary Breakpoint" . gud-tbreak))
- (local-set-key [menu-bar debug finish] '("Finish Function" . gud-finish))
- (local-set-key [menu-bar debug up] '("Up Stack" . gud-up))
- (local-set-key [menu-bar debug down] '("Down Stack" . gud-down))
- buf)))
-
-(defvar gdb-minibuffer-local-map nil
- "Keymap for minibuffer prompting of gdb startup command.")
-(if gdb-minibuffer-local-map
- ()
- (setq gdb-minibuffer-local-map (copy-keymap minibuffer-local-map))
- (define-key
- gdb-minibuffer-local-map "\C-i" 'comint-dynamic-complete-filename))
-
-;;;###autoload
-(defun gdb (command-line)
- "Run gdb on program FILE in buffer *gud-FILE*.
-The directory containing FILE becomes the initial working directory
-and source-file directory for your debugger."
- (interactive
- (list (read-from-minibuffer "Run gdb (like this): "
- (if (consp gud-gdb-history)
- (car gud-gdb-history)
- "gdb ")
- gdb-minibuffer-local-map nil
- '(gud-gdb-history . 1))))
-
- (gud-common-init command-line 'gud-gdb-massage-args
- 'gud-gdb-marker-filter 'gud-gdb-find-file)
-
- (gud-def gud-break "break %f:%l" "\C-b" "Set breakpoint at current line.")
- (gud-def gud-tbreak "tbreak %f:%l" "\C-t" "Set temporary breakpoint at current line.")
- (gud-def gud-remove "clear %f:%l" "\C-d" "Remove breakpoint at current line")
- (gud-def gud-step "step %p" "\C-s" "Step one source line with display.")
- (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.")
- (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).")
- (gud-def gud-cont "cont" "\C-r" "Continue with display.")
- (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
- (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
- (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
- (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.")
-
- (local-set-key "\C-i" 'gud-gdb-complete-command)
- (local-set-key [menu-bar debug tbreak] '("Temporary Breakpoint" . gud-tbreak))
- (local-set-key [menu-bar debug finish] '("Finish Function" . gud-finish))
- (local-set-key [menu-bar debug up] '("Up Stack" . gud-up))
- (local-set-key [menu-bar debug down] '("Down Stack" . gud-down))
- (setq comint-prompt-regexp "^(.*gdb[+]?) *")
- (setq paragraph-start comint-prompt-regexp)
- (run-hooks 'gdb-mode-hook)
- )
-
-;; One of the nice features of GDB is its impressive support for
-;; context-sensitive command completion. We preserve that feature
-;; in the GUD buffer by using a GDB command designed just for Emacs.
-
-;; The completion process filter indicates when it is finished.
-(defvar gud-gdb-complete-in-progress)
-
-;; Since output may arrive in fragments we accumulate partials strings here.
-(defvar gud-gdb-complete-string)
-
-;; We need to know how much of the completion to chop off.
-(defvar gud-gdb-complete-break)
-
-;; The completion list is constructed by the process filter.
-(defvar gud-gdb-complete-list)
-
-(defvar gud-comint-buffer nil)
-
-(defun gud-gdb-complete-command ()
- "Perform completion on the GDB command preceding point.
-This is implemented using the GDB `complete' command which isn't
-available with older versions of GDB."
- (interactive)
- (let* ((end (point))
- (command (save-excursion
- (beginning-of-line)
- (and (looking-at comint-prompt-regexp)
- (goto-char (match-end 0)))
- (buffer-substring (point) end)))
- command-word)
- ;; Find the word break. This match will always succeed.
- (string-match "\\(\\`\\| \\)\\([^ ]*\\)\\'" command)
- (setq gud-gdb-complete-break (match-beginning 2)
- command-word (substring command gud-gdb-complete-break))
- ;; Temporarily install our filter function.
- (let ((gud-marker-filter 'gud-gdb-complete-filter))
- ;; Issue the command to GDB.
- (gud-basic-call (concat "complete " command))
- (setq gud-gdb-complete-in-progress t
- gud-gdb-complete-string nil
- gud-gdb-complete-list nil)
- ;; Slurp the output.
- (while gud-gdb-complete-in-progress
- (accept-process-output (get-buffer-process gud-comint-buffer))))
- ;; Protect against old versions of GDB.
- (and gud-gdb-complete-list
- (string-match "^Undefined command: \"complete\""
- (car gud-gdb-complete-list))
- (error "This version of GDB doesn't support the `complete' command."))
- ;; Sort the list like readline.
- (setq gud-gdb-complete-list
- (sort gud-gdb-complete-list (function string-lessp)))
- ;; Remove duplicates.
- (let ((first gud-gdb-complete-list)
- (second (cdr gud-gdb-complete-list)))
- (while second
- (if (string-equal (car first) (car second))
- (setcdr first (setq second (cdr second)))
- (setq first second
- second (cdr second)))))
- ;; Add a trailing single quote if there is a unique completion
- ;; and it contains an odd number of unquoted single quotes.
- (and (= (length gud-gdb-complete-list) 1)
- (let ((str (car gud-gdb-complete-list))
- (pos 0)
- (count 0))
- (while (string-match "\\([^'\\]\\|\\\\'\\)*'" str pos)
- (setq count (1+ count)
- pos (match-end 0)))
- (and (= (mod count 2) 1)
- (setq gud-gdb-complete-list (list (concat str "'"))))))
- ;; Let comint handle the rest.
- (comint-dynamic-simple-complete command-word gud-gdb-complete-list)))
-
-;; The completion process filter is installed temporarily to slurp the
-;; output of GDB up to the next prompt and build the completion list.
-(defun gud-gdb-complete-filter (string)
- (setq string (concat gud-gdb-complete-string string))
- (while (string-match "\n" string)
- (setq gud-gdb-complete-list
- (cons (substring string gud-gdb-complete-break (match-beginning 0))
- gud-gdb-complete-list))
- (setq string (substring string (match-end 0))))
- (if (string-match comint-prompt-regexp string)
- (progn
- (setq gud-gdb-complete-in-progress nil)
- string)
- (progn
- (setq gud-gdb-complete-string string)
- "")))
-
-
-;; ======================================================================
-;; sdb functions
-
-;;; History of argument lists passed to sdb.
-(defvar gud-sdb-history nil)
-
-(defvar gud-sdb-needs-tags (not (file-exists-p "/var"))
- "If nil, we're on a System V Release 4 and don't need the tags hack.")
-
-(defvar gud-sdb-lastfile nil)
-
-(defun gud-sdb-massage-args (file args) args)
-
-(defun gud-sdb-marker-filter (string)
- (setq gud-marker-acc
- (if gud-marker-acc (concat gud-marker-acc string) string))
- (let (start)
- ;; Process all complete markers in this chunk
- (while
- (cond
- ;; System V Release 3.2 uses this format
- ((string-match "\\(^\\|\n\\)\\*?\\(0x\\w* in \\)?\\([^:\n]*\\):\\([0-9]*\\):.*\n"
- gud-marker-acc start)
- (setq gud-last-frame
- (cons
- (substring gud-marker-acc (match-beginning 3) (match-end 3))
- (string-to-int
- (substring gud-marker-acc (match-beginning 4) (match-end 4))))))
- ;; System V Release 4.0 quite often clumps two lines together
- ((string-match "^\\(BREAKPOINT\\|STEPPED\\) process [0-9]+ function [^ ]+ in \\(.+\\)\n\\([0-9]+\\):"
- gud-marker-acc start)
- (setq gud-sdb-lastfile
- (substring gud-marker-acc (match-beginning 2) (match-end 2)))
- (setq gud-last-frame
- (cons
- gud-sdb-lastfile
- (string-to-int
- (substring gud-marker-acc (match-beginning 3) (match-end 3))))))
- ;; System V Release 4.0
- ((string-match "^\\(BREAKPOINT\\|STEPPED\\) process [0-9]+ function [^ ]+ in \\(.+\\)\n"
- gud-marker-acc start)
- (setq gud-sdb-lastfile
- (substring gud-marker-acc (match-beginning 2) (match-end 2))))
- ((and gud-sdb-lastfile (string-match "^\\([0-9]+\\):"
- gud-marker-acc start))
- (setq gud-last-frame
- (cons
- gud-sdb-lastfile
- (string-to-int
- (substring gud-marker-acc (match-beginning 1) (match-end 1))))))
- (t
- (setq gud-sdb-lastfile nil)))
- (setq start (match-end 0)))
-
- ;; Search for the last incomplete line in this chunk
- (while (string-match "\n" gud-marker-acc start)
- (setq start (match-end 0)))
-
- ;; If we have an incomplete line, store it in gud-marker-acc.
- (setq gud-marker-acc (substring gud-marker-acc (or start 0))))
- string)
-
-(defun gud-sdb-find-file (f)
- (save-excursion
- (let ((buf (if gud-sdb-needs-tags
- (find-tag-noselect f)
- (find-file-noselect f))))
- (set-buffer buf)
- (gud-make-debug-menu)
- (local-set-key [menu-bar debug tbreak] '("Temporary Breakpoint" . gud-tbreak))
- buf)))
-
-;;;###autoload
-(defun sdb (command-line)
- "Run sdb on program FILE in buffer *gud-FILE*.
-The directory containing FILE becomes the initial working directory
-and source-file directory for your debugger."
- (interactive
- (list (read-from-minibuffer "Run sdb (like this): "
- (if (consp gud-sdb-history)
- (car gud-sdb-history)
- "sdb ")
- nil nil
- '(gud-sdb-history . 1))))
- (if (and gud-sdb-needs-tags
- (not (and (boundp 'tags-file-name)
- (stringp tags-file-name)
- (file-exists-p tags-file-name))))
- (error "The sdb support requires a valid tags table to work."))
-
- (gud-common-init command-line 'gud-sdb-massage-args
- 'gud-sdb-marker-filter 'gud-sdb-find-file)
-
- (gud-def gud-break "%l b" "\C-b" "Set breakpoint at current line.")
- (gud-def gud-tbreak "%l c" "\C-t" "Set temporary breakpoint at current line.")
- (gud-def gud-remove "%l d" "\C-d" "Remove breakpoint at current line")
- (gud-def gud-step "s %p" "\C-s" "Step one source line with display.")
- (gud-def gud-stepi "i %p" "\C-i" "Step one instruction with display.")
- (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).")
- (gud-def gud-cont "c" "\C-r" "Continue with display.")
- (gud-def gud-print "%e/" "\C-p" "Evaluate C expression at point.")
-
- (setq comint-prompt-regexp "\\(^\\|\n\\)\\*")
- (setq paragraph-start comint-prompt-regexp)
- (local-set-key [menu-bar debug tbreak]
- '("Temporary Breakpoint" . gud-tbreak))
- (run-hooks 'sdb-mode-hook)
- )
-
-;; ======================================================================
-;; dbx functions
-
-;;; History of argument lists passed to dbx.
-(defvar gud-dbx-history nil)
-
-(defvar gud-dbx-directories nil
- "*A list of directories that dbx should search for source code.
-If nil, only source files in the program directory
-will be known to dbx.
-
-The file names should be absolute, or relative to the directory
-containing the executable being debugged.")
-
-(defun gud-dbx-massage-args (file args)
- (nconc (let ((directories gud-dbx-directories)
- (result nil))
- (while directories
- (setq result (cons (car directories) (cons "-I" result)))
- (setq directories (cdr directories)))
- (nreverse result))
- args))
-
-(defun gud-dbx-file-name (f)
- "Transform a relative file name to an absolute file name, for dbx."
- (let ((result nil))
- (if (file-exists-p f)
- (setq result (expand-file-name f))
- (let ((directories gud-dbx-directories))
- (while directories
- (let ((path (concat (car directories) "/" f)))
- (if (file-exists-p path)
- (setq result (expand-file-name path)
- directories nil)))
- (setq directories (cdr directories)))))
- result))
-
-(defun gud-dbx-marker-filter (string)
- (setq gud-marker-acc (if gud-marker-acc (concat gud-marker-acc string) string))
-
- (let (start)
- ;; Process all complete markers in this chunk.
- (while (or (string-match
- "stopped in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\""
- gud-marker-acc start)
- (string-match
- "signal .* in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\""
- gud-marker-acc start))
- (setq gud-last-frame
- (cons
- (substring gud-marker-acc (match-beginning 2) (match-end 2))
- (string-to-int
- (substring gud-marker-acc (match-beginning 1) (match-end 1))))
- start (match-end 0)))
-
- ;; Search for the last incomplete line in this chunk
- (while (string-match "\n" gud-marker-acc start)
- (setq start (match-end 0)))
-
- ;; If the incomplete line APPEARS to begin with another marker, keep it
- ;; in the accumulator. Otherwise, clear the accumulator to avoid an
- ;; unnecessary concat during the next call.
- (setq gud-marker-acc
- (if (string-match "\\(stopped\\|signal\\)" gud-marker-acc start)
- (substring gud-marker-acc (match-beginning 0))
- nil)))
- string)
-
-;; Functions for Mips-style dbx. Given the option `-emacs', documented in
-;; OSF1, not necessarily elsewhere, it produces markers similar to gdb's.
-(defvar gud-mips-p
- (or (string-match "^mips-[^-]*-ultrix" system-configuration)
- ;; We haven't tested gud on this system:
- (string-match "^mips-[^-]*-riscos" system-configuration)
- ;; It's documented on OSF/1.3
- (string-match "^mips-[^-]*-osf1" system-configuration)
- (string-match "^alpha-[^-]*-osf" system-configuration))
- "Non-nil to assume the MIPS/OSF dbx conventions (argument `-emacs').")
-
-(defun gud-mipsdbx-massage-args (file args)
- (cons "-emacs" args))
-
-;; This is just like the gdb one except for the regexps since we need to cope
-;; with an optional breakpoint number in [] before the ^Z^Z
-(defun gud-mipsdbx-marker-filter (string)
- (setq gud-marker-acc (concat gud-marker-acc string))
- (let ((output ""))
-
- ;; Process all the complete markers in this chunk.
- (while (string-match
- ;; This is like th gdb marker but with an optional
- ;; leading break point number like `[1] '
- "[][ 0-9]*\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n"
- gud-marker-acc)
- (setq
-
- ;; Extract the frame position from the marker.
- gud-last-frame
- (cons (substring gud-marker-acc (match-beginning 1) (match-end 1))
- (string-to-int (substring gud-marker-acc
- (match-beginning 2)
- (match-end 2))))
-
- ;; Append any text before the marker to the output we're going
- ;; to return - we don't include the marker in this text.
- output (concat output
- (substring gud-marker-acc 0 (match-beginning 0)))
-
- ;; Set the accumulator to the remaining text.
- gud-marker-acc (substring gud-marker-acc (match-end 0))))
-
- ;; Does the remaining text look like it might end with the
- ;; beginning of another marker? If it does, then keep it in
- ;; gud-marker-acc until we receive the rest of it. Since we
- ;; know the full marker regexp above failed, it's pretty simple to
- ;; test for marker starts.
- (if (string-match "[][ 0-9]*\032.*\\'" gud-marker-acc)
- (progn
- ;; Everything before the potential marker start can be output.
- (setq output (concat output (substring gud-marker-acc
- 0 (match-beginning 0))))
-
- ;; Everything after, we save, to combine with later input.
- (setq gud-marker-acc
- (substring gud-marker-acc (match-beginning 0))))
-
- (setq output (concat output gud-marker-acc)
- gud-marker-acc ""))
-
- output))
-
-;; The dbx in IRIX is a pain. It doesn't print the file name when
-;; stopping at a breakpoint (but you do get it from the `up' and
-;; `down' commands...). The only way to extract the information seems
-;; to be with a `file' command, although the current line number is
-;; available in $curline. Thus we have to look for output which
-;; appears to indicate a breakpoint. Then we prod the dbx sub-process
-;; to output the information we want with a combination of the
-;; `printf' and `file' commands as a pseudo marker which we can
-;; recognise next time through the marker-filter. This would be like
-;; the gdb marker but you can't get the file name without a newline...
-;; Note that gud-remove won't work since Irix dbx expects a breakpoint
-;; number rather than a line number etc. Maybe this could be made to
-;; work by listing all the breakpoints and picking the one(s) with the
-;; correct line number, but life's too short.
-;; d.love@dl.ac.uk (Dave Love) can be blamed for this
-
-(defvar gud-irix-p
- (and (string-match "^mips-[^-]*-irix" system-configuration)
- (not (string-match "irix[6-9]\\.[1-9]" system-configuration)))
- "Non-nil to assume the interface appropriate for IRIX dbx.
-This works in IRIX 4, 5 and 6, but `gud-dbx-use-stopformat-p' provides
-a better solution in 6.1 upwards.")
-(defvar gud-dbx-use-stopformat-p
- (string-match "irix[6-9]\\.[1-9]" system-configuration)
- "Non-nil to use the dbx feature present at least from Irix 6.1
- whereby $stopformat=1 produces an output format compatiable with
- `gud-dbx-marker-filter'.")
-;; [Irix dbx seems to be a moving target. The dbx output changed
-;; subtly sometime between OS v4.0.5 and v5.2 so that, for instance,
-;; the output from `up' is no longer spotted by gud (and it's probably
-;; not distinctive enough to try to match it -- use C-<, C->
-;; exclusively) . For 5.3 and 6.0, the $curline variable changed to
-;; `long long'(why?!), so the printf stuff needed changing. The line
-;; number was cast to `long' as a compromise between the new `long
-;; long' and the original `int'. This is reported not to work in 6.2,
-;; so it's changed back to int -- don't make your sources too long.
-;; From Irix6.1 (but not 6.0?) dbx supports an undocumented feature
-;; whereby `set $stopformat=1' reportedly produces output compatible
-;; with `gud-dbx-marker-filter', which we prefer.
-
-;; The process filter is also somewhat
-;; unreliable, sometimes not spotting the markers; I don't know
-;; whether there's anything that can be done about that. It would be
-;; much better if SGI could be persuaded to (re?)instate the MIPS
-;; -emacs flag for gdb-like output (which ought to be possible as most
-;; of the communication I've had over it has been from sgi.com).]
-
-;; this filter is influenced by the xdb one rather than the gdb one
-(defun gud-irixdbx-marker-filter (string)
- (let (result (case-fold-search nil))
- (if (or (string-match comint-prompt-regexp string)
- (string-match ".*\012" string))
- (setq result (concat gud-marker-acc string)
- gud-marker-acc "")
- (setq gud-marker-acc (concat gud-marker-acc string)))
- (if result
- (cond
- ;; look for breakpoint or signal indication e.g.:
- ;; [2] Process 1267 (pplot) stopped at [params:338 ,0x400ec0]
- ;; Process 1281 (pplot) stopped at [params:339 ,0x400ec8]
- ;; Process 1270 (pplot) Floating point exception [._read._read:16 ,0x452188]
- ((string-match
- "^\\(\\[[0-9]+] \\)?Process +[0-9]+ ([^)]*) [^[]+\\[[^]\n]*]\n"
- result)
- ;; prod dbx into printing out the line number and file
- ;; name in a form we can grok as below
- (process-send-string (get-buffer-process gud-comint-buffer)
- "printf \"\032\032%1d:\",(int)$curline;file\n"))
- ;; look for result of, say, "up" e.g.:
- ;; .pplot.pplot(0x800) ["src/pplot.f":261, 0x400c7c]
- ;; (this will also catch one of the lines printed by "where")
- ((string-match
- "^[^ ][^[]*\\[\"\\([^\"]+\\)\":\\([0-9]+\\), [^]]+]\n"
- result)
- (let ((file (substring result (match-beginning 1)
- (match-end 1))))
- (if (file-exists-p file)
- (setq gud-last-frame
- (cons
- (substring
- result (match-beginning 1) (match-end 1))
- (string-to-int
- (substring
- result (match-beginning 2) (match-end 2)))))))
- result)
- ((string-match ; kluged-up marker as above
- "\032\032\\([0-9]*\\):\\(.*\\)\n" result)
- (let ((file (gud-dbx-file-name
- (substring result (match-beginning 2) (match-end 2)))))
- (if (and file (file-exists-p file))
- (setq gud-last-frame
- (cons
- file
- (string-to-int
- (substring
- result (match-beginning 1) (match-end 1)))))))
- (setq result (substring result 0 (match-beginning 0))))))
- (or result "")))
-
-(defun gud-dbx-find-file (f)
- (save-excursion
- (let ((realf (gud-dbx-file-name f)))
- (if realf
- (let ((buf (find-file-noselect realf)))
- (set-buffer buf)
- (gud-make-debug-menu)
- (local-set-key [menu-bar debug up] '("Up Stack" . gud-up))
- (local-set-key [menu-bar debug down] '("Down Stack" . gud-down))
- buf)
- nil))))
-
-;;;###autoload
-(defun dbx (command-line)
- "Run dbx on program FILE in buffer *gud-FILE*.
-The directory containing FILE becomes the initial working directory
-and source-file directory for your debugger."
- (interactive
- (list (read-from-minibuffer "Run dbx (like this): "
- (if (consp gud-dbx-history)
- (car gud-dbx-history)
- "dbx ")
- nil nil
- '(gud-dbx-history . 1))))
-
- (cond
- (gud-mips-p
- (gud-common-init command-line 'gud-mipsdbx-massage-args
- 'gud-mipsdbx-marker-filter 'gud-dbx-find-file))
- (gud-irix-p
- (gud-common-init command-line 'gud-dbx-massage-args
- 'gud-irixdbx-marker-filter 'gud-dbx-find-file))
- (t
- (gud-common-init command-line 'gud-dbx-massage-args
- 'gud-dbx-marker-filter 'gud-dbx-find-file)))
-
- (cond
- (gud-mips-p
- (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
- (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
- (gud-def gud-break "stop at \"%f\":%l"
- "\C-b" "Set breakpoint at current line.")
- (gud-def gud-finish "return" "\C-f" "Finish executing current function."))
- (gud-irix-p
- (gud-def gud-break "stop at \"%d%f\":%l"
- "\C-b" "Set breakpoint at current line.")
- (gud-def gud-finish "return" "\C-f" "Finish executing current function.")
- (gud-def gud-up "up %p; printf \"\032\032%1d:\",(int)$curline;file\n"
- "<" "Up (numeric arg) stack frames.")
- (gud-def gud-down "down %p; printf \"\032\032%1d:\",(int)$curline;file\n"
- ">" "Down (numeric arg) stack frames.")
- ;; Make dbx give out the source location info that we need.
- (process-send-string (get-buffer-process gud-comint-buffer)
- "printf \"\032\032%1d:\",(int)$curline;file\n"))
- (gud-dbx-use-stopformat-p
- (process-send-string (get-buffer-process gud-comint-buffer)
- "set $stopformat=1\n"))
- (t
- (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
- (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
- (gud-def gud-break "file \"%d%f\"\nstop at %l"
- "\C-b" "Set breakpoint at current line.")))
-
- (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
- (gud-def gud-step "step %p" "\C-s" "Step one line with display.")
- (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.")
- (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).")
- (gud-def gud-cont "cont" "\C-r" "Continue with display.")
- (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.")
-
- (setq comint-prompt-regexp "^[^)\n]*dbx) *")
- (setq paragraph-start comint-prompt-regexp)
- (local-set-key [menu-bar debug up] '("Up Stack" . gud-up))
- (local-set-key [menu-bar debug down] '("Down Stack" . gud-down))
- (run-hooks 'dbx-mode-hook)
- )
-
-;; ======================================================================
-;; xdb (HP PARISC debugger) functions
-
-;;; History of argument lists passed to xdb.
-(defvar gud-xdb-history nil)
-
-(defvar gud-xdb-directories nil
- "*A list of directories that xdb should search for source code.
-If nil, only source files in the program directory
-will be known to xdb.
-
-The file names should be absolute, or relative to the directory
-containing the executable being debugged.")
-
-(defun gud-xdb-massage-args (file args)
- (nconc (let ((directories gud-xdb-directories)
- (result nil))
- (while directories
- (setq result (cons (car directories) (cons "-d" result)))
- (setq directories (cdr directories)))
- (nreverse result))
- args))
-
-(defun gud-xdb-file-name (f)
- "Transform a relative pathname to a full pathname in xdb mode"
- (let ((result nil))
- (if (file-exists-p f)
- (setq result (expand-file-name f))
- (let ((directories gud-xdb-directories))
- (while directories
- (let ((path (concat (car directories) "/" f)))
- (if (file-exists-p path)
- (setq result (expand-file-name path)
- directories nil)))
- (setq directories (cdr directories)))))
- result))
-
-;; xdb does not print the lines all at once, so we have to accumulate them
-(defun gud-xdb-marker-filter (string)
- (let (result)
- (if (or (string-match comint-prompt-regexp string)
- (string-match ".*\012" string))
- (setq result (concat gud-marker-acc string)
- gud-marker-acc "")
- (setq gud-marker-acc (concat gud-marker-acc string)))
- (if result
- (if (or (string-match "\\([^\n \t:]+\\): [^:]+: \\([0-9]+\\)[: ]"
- result)
- (string-match "[^: \t]+:[ \t]+\\([^:]+\\): [^:]+: \\([0-9]+\\):"
- result))
- (let ((line (string-to-int
- (substring result (match-beginning 2) (match-end 2))))
- (file (gud-xdb-file-name
- (substring result (match-beginning 1) (match-end 1)))))
- (if file
- (setq gud-last-frame (cons file line))))))
- (or result "")))
-
-(defun gud-xdb-find-file (f)
- (save-excursion
- (let ((realf (gud-xdb-file-name f)))
- (if realf
- (let ((buf (find-file-noselect realf)))
- (set-buffer buf)
- (gud-make-debug-menu)
- (local-set-key [menu-bar debug tbreak]
- '("Temporary Breakpoint" . gud-tbreak))
- (local-set-key [menu-bar debug finish]
- '("Finish Function" . gud-finish))
- (local-set-key [menu-bar debug up] '("Up Stack" . gud-up))
- (local-set-key [menu-bar debug down] '("Down Stack" . gud-down))
- buf)
- nil))))
-
-;;;###autoload
-(defun xdb (command-line)
- "Run xdb on program FILE in buffer *gud-FILE*.
-The directory containing FILE becomes the initial working directory
-and source-file directory for your debugger.
-
-You can set the variable 'gud-xdb-directories' to a list of program source
-directories if your program contains sources from more than one directory."
- (interactive
- (list (read-from-minibuffer "Run xdb (like this): "
- (if (consp gud-xdb-history)
- (car gud-xdb-history)
- "xdb ")
- nil nil
- '(gud-xdb-history . 1))))
-
- (gud-common-init command-line 'gud-xdb-massage-args
- 'gud-xdb-marker-filter 'gud-xdb-find-file)
-
- (gud-def gud-break "b %f:%l" "\C-b" "Set breakpoint at current line.")
- (gud-def gud-tbreak "b %f:%l\\t" "\C-t"
- "Set temporary breakpoint at current line.")
- (gud-def gud-remove "db" "\C-d" "Remove breakpoint at current line")
- (gud-def gud-step "s %p" "\C-s" "Step one line with display.")
- (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).")
- (gud-def gud-cont "c" "\C-r" "Continue with display.")
- (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
- (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
- (gud-def gud-finish "bu\\t" "\C-f" "Finish executing current function.")
- (gud-def gud-print "p %e" "\C-p" "Evaluate C expression at point.")
-
- (setq comint-prompt-regexp "^>")
- (setq paragraph-start comint-prompt-regexp)
- (local-set-key [menu-bar debug tbreak] '("Temporary Breakpoint" . gud-tbreak))
- (local-set-key [menu-bar debug finish] '("Finish Function" . gud-finish))
- (local-set-key [menu-bar debug up] '("Up Stack" . gud-up))
- (local-set-key [menu-bar debug down] '("Down Stack" . gud-down))
- (run-hooks 'xdb-mode-hook))
-
-;; ======================================================================
-;; perldb functions
-
-;;; History of argument lists passed to perldb.
-(defvar gud-perldb-history nil)
-
-(defun gud-perldb-massage-args (file args)
- (cond ((equal (car args) "-e")
- (cons "-d"
- (cons (car args)
- (cons (nth 1 args)
- (cons "--" (cons "-emacs" (cdr (cdr args))))))))
- (t
- (cons "-d" (cons (car args) (cons "-emacs" (cdr args)))))))
-
-;; There's no guarantee that Emacs will hand the filter the entire
-;; marker at once; it could be broken up across several strings. We
-;; might even receive a big chunk with several markers in it. If we
-;; receive a chunk of text which looks like it might contain the
-;; beginning of a marker, we save it here between calls to the
-;; filter.
-(defvar gud-perldb-marker-acc "")
-
-(defun gud-perldb-marker-filter (string)
- (setq gud-marker-acc (concat gud-marker-acc string))
- (let ((output ""))
-
- ;; Process all the complete markers in this chunk.
- (while (string-match "\032\032\\(\\([a-zA-Z]:\\)?[^:\n]*\\):\\([0-9]*\\):.*\n"
- gud-marker-acc)
- (setq
-
- ;; Extract the frame position from the marker.
- gud-last-frame
- (cons (substring gud-marker-acc (match-beginning 1) (match-end 1))
- (string-to-int (substring gud-marker-acc
- (match-beginning 3)
- (match-end 3))))
-
- ;; Append any text before the marker to the output we're going
- ;; to return - we don't include the marker in this text.
- output (concat output
- (substring gud-marker-acc 0 (match-beginning 0)))
-
- ;; Set the accumulator to the remaining text.
- gud-marker-acc (substring gud-marker-acc (match-end 0))))
-
- ;; Does the remaining text look like it might end with the
- ;; beginning of another marker? If it does, then keep it in
- ;; gud-marker-acc until we receive the rest of it. Since we
- ;; know the full marker regexp above failed, it's pretty simple to
- ;; test for marker starts.
- (if (string-match "\032.*\\'" gud-marker-acc)
- (progn
- ;; Everything before the potential marker start can be output.
- (setq output (concat output (substring gud-marker-acc
- 0 (match-beginning 0))))
-
- ;; Everything after, we save, to combine with later input.
- (setq gud-marker-acc
- (substring gud-marker-acc (match-beginning 0))))
-
- (setq output (concat output gud-marker-acc)
- gud-marker-acc ""))
-
- output))
-
-(defun gud-perldb-find-file (f)
- (save-excursion
- (let ((buf (find-file-noselect f)))
- (set-buffer buf)
- (gud-make-debug-menu)
- buf)))
-
-(defvar perldb-command-name "perl"
- "File name for executing Perl.")
-
-;;;###autoload
-(defun perldb (command-line)
- "Run perldb on program FILE in buffer *gud-FILE*.
-The directory containing FILE becomes the initial working directory
-and source-file directory for your debugger."
- (interactive
- (list (read-from-minibuffer "Run perldb (like this): "
- (if (consp gud-perldb-history)
- (car gud-perldb-history)
- (concat perldb-command-name
- " "
- (or (buffer-file-name)
- "-e 0"))
- " ")
- nil nil
- '(gud-perldb-history . 1))))
-
- (gud-common-init command-line 'gud-perldb-massage-args
- 'gud-perldb-marker-filter 'gud-perldb-find-file)
-
- (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.")
- (gud-def gud-remove "d %l" "\C-d" "Remove breakpoint at current line")
- (gud-def gud-step "s" "\C-s" "Step one source line with display.")
- (gud-def gud-next "n" "\C-n" "Step one line (skip functions).")
- (gud-def gud-cont "c" "\C-r" "Continue with display.")
-; (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
-; (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
-; (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
- (gud-def gud-print "%e" "\C-p" "Evaluate perl expression at point.")
-
- (setq comint-prompt-regexp "^ DB<+[0-9]+>+ ")
- (setq paragraph-start comint-prompt-regexp)
- (run-hooks 'perldb-mode-hook)
- )
-
-;;
-;; End of debugger-specific information
-;;
-
-
-;;; When we send a command to the debugger via gud-call, it's annoying
-;;; to see the command and the new prompt inserted into the debugger's
-;;; buffer; we have other ways of knowing the command has completed.
-;;;
-;;; If the buffer looks like this:
-;;; --------------------
-;;; (gdb) set args foo bar
-;;; (gdb) -!-
-;;; --------------------
-;;; (the -!- marks the location of point), and we type `C-x SPC' in a
-;;; source file to set a breakpoint, we want the buffer to end up like
-;;; this:
-;;; --------------------
-;;; (gdb) set args foo bar
-;;; Breakpoint 1 at 0x92: file make-docfile.c, line 49.
-;;; (gdb) -!-
-;;; --------------------
-;;; Essentially, the old prompt is deleted, and the command's output
-;;; and the new prompt take its place.
-;;;
-;;; Not echoing the command is easy enough; you send it directly using
-;;; process-send-string, and it never enters the buffer. However,
-;;; getting rid of the old prompt is trickier; you don't want to do it
-;;; when you send the command, since that will result in an annoying
-;;; flicker as the prompt is deleted, redisplay occurs while Emacs
-;;; waits for a response from the debugger, and the new prompt is
-;;; inserted. Instead, we'll wait until we actually get some output
-;;; from the subprocess before we delete the prompt. If the command
-;;; produced no output other than a new prompt, that prompt will most
-;;; likely be in the first chunk of output received, so we will delete
-;;; the prompt and then replace it with an identical one. If the
-;;; command produces output, the prompt is moving anyway, so the
-;;; flicker won't be annoying.
-;;;
-;;; So - when we want to delete the prompt upon receipt of the next
-;;; chunk of debugger output, we position gud-delete-prompt-marker at
-;;; the start of the prompt; the process filter will notice this, and
-;;; delete all text between it and the process output marker. If
-;;; gud-delete-prompt-marker points nowhere, we leave the current
-;;; prompt alone.
-(defvar gud-delete-prompt-marker nil)
-
-
-(defun gud-mode ()
- "Major mode for interacting with an inferior debugger process.
-
- You start it up with one of the commands M-x gdb, M-x sdb, M-x dbx,
-M-x perldb, or M-x xdb. Each entry point finishes by executing a
-hook; `gdb-mode-hook', `sdb-mode-hook', `dbx-mode-hook',
-`perldb-mode-hook', or `xdb-mode-hook' respectively.
-
-After startup, the following commands are available in both the GUD
-interaction buffer and any source buffer GUD visits due to a breakpoint stop
-or step operation:
-
-\\[gud-break] sets a breakpoint at the current file and line. In the
-GUD buffer, the current file and line are those of the last breakpoint or
-step. In a source buffer, they are the buffer's file and current line.
-
-\\[gud-remove] removes breakpoints on the current file and line.
-
-\\[gud-refresh] displays in the source window the last line referred to
-in the gud buffer.
-
-\\[gud-step], \\[gud-next], and \\[gud-stepi] do a step-one-line,
-step-one-line (not entering function calls), and step-one-instruction
-and then update the source window with the current file and position.
-\\[gud-cont] continues execution.
-
-\\[gud-print] tries to find the largest C lvalue or function-call expression
-around point, and sends it to the debugger for value display.
-
-The above commands are common to all supported debuggers except xdb which
-does not support stepping instructions.
-
-Under gdb, sdb and xdb, \\[gud-tbreak] behaves exactly like \\[gud-break],
-except that the breakpoint is temporary; that is, it is removed when
-execution stops on it.
-
-Under gdb, dbx, and xdb, \\[gud-up] pops up through an enclosing stack
-frame. \\[gud-down] drops back down through one.
-
-If you are using gdb or xdb, \\[gud-finish] runs execution to the return from
-the current function and stops.
-
-All the keystrokes above are accessible in the GUD buffer
-with the prefix C-c, and in all buffers through the prefix C-x C-a.
-
-All pre-defined functions for which the concept make sense repeat
-themselves the appropriate number of times if you give a prefix
-argument.
-
-You may use the `gud-def' macro in the initialization hook to define other
-commands.
-
-Other commands for interacting with the debugger process are inherited from
-comint mode, which see."
- (interactive)
- (comint-mode)
- (setq major-mode 'gud-mode)
- (setq mode-name "Debugger")
- (setq mode-line-process '(":%s"))
- (use-local-map comint-mode-map)
- (gud-make-debug-menu)
- (define-key (current-local-map) "\C-c\C-l" 'gud-refresh)
- (make-local-variable 'gud-last-frame)
- (setq gud-last-frame nil)
- (make-local-variable 'comint-prompt-regexp)
- ;; Don't put repeated commands in command history many times.
- (make-local-variable 'comint-input-ignoredups)
- (setq comint-input-ignoredups t)
- (make-local-variable 'paragraph-start)
- (make-local-variable 'gud-delete-prompt-marker)
- (setq gud-delete-prompt-marker (make-marker))
- (run-hooks 'gud-mode-hook))
-
-;; Chop STRING into words separated by SPC or TAB and return a list of them.
-(defun gud-chop-words (string)
- (let ((i 0) (beg 0)
- (len (length string))
- (words nil))
- (while (< i len)
- (if (memq (aref string i) '(?\t ? ))
- (progn
- (setq words (cons (substring string beg i) words)
- beg (1+ i))
- (while (and (< beg len) (memq (aref string beg) '(?\t ? )))
- (setq beg (1+ beg)))
- (setq i (1+ beg)))
- (setq i (1+ i))))
- (if (< beg len)
- (setq words (cons (substring string beg) words)))
- (nreverse words)))
-
-;; Perform initializations common to all debuggers.
-;; The first arg is the specified command line,
-;; which starts with the program to debug.
-;; The other three args specify the values to use
-;; for local variables in the debugger buffer.
-(defun gud-common-init (command-line massage-args marker-filter find-file)
- (let* ((words (gud-chop-words command-line))
- (program (car words))
- ;; Extract the file name from WORDS
- ;; and put t in its place.
- ;; Later on we will put the modified file name arg back there.
- (file-word (let ((w (cdr words)))
- (while (and w (= ?- (aref (car w) 0)))
- (setq w (cdr w)))
- (and w
- (prog1 (car w)
- (setcar w t)))))
- (file-subst
- (and file-word (substitute-in-file-name file-word)))
- (args (cdr words))
- ;; If a directory was specified, expand the file name.
- ;; Otherwise, don't expand it, so GDB can use the PATH.
- ;; A file name without directory is literally valid
- ;; only if the file exists in ., and in that case,
- ;; omitting the expansion here has no visible effect.
- (file (and file-word
- (if (file-name-directory file-subst)
- (expand-file-name file-subst)
- file-subst)))
- (filepart (and file-word (concat "-" (file-name-nondirectory file)))))
- (switch-to-buffer (concat "*gud" filepart "*"))
- ;; Set default-directory to the file's directory.
- (and file-word
- ;; Don't set default-directory if no directory was specified.
- ;; In that case, either the file is found in the current directory,
- ;; in which case this setq is a no-op,
- ;; or it is found by searching PATH,
- ;; in which case we don't know what directory it was found in.
- (file-name-directory file)
- (setq default-directory (file-name-directory file)))
- (or (bolp) (newline))
- (insert "Current directory is " default-directory "\n")
- ;; Put the substituted and expanded file name back in its place.
- (let ((w args))
- (while (and w (not (eq (car w) t)))
- (setq w (cdr w)))
- (if w
- (setcar w file)))
- (apply 'make-comint (concat "gud" filepart) program nil
- (funcall massage-args file args)))
- ;; Since comint clobbered the mode, we don't set it until now.
- (gud-mode)
- (make-local-variable 'gud-marker-filter)
- (setq gud-marker-filter marker-filter)
- (make-local-variable 'gud-find-file)
- (setq gud-find-file find-file)
-
- (set-process-filter (get-buffer-process (current-buffer)) 'gud-filter)
- (set-process-sentinel (get-buffer-process (current-buffer)) 'gud-sentinel)
- (gud-set-buffer)
- )
-
-(defun gud-set-buffer ()
- (cond ((eq major-mode 'gud-mode)
- (setq gud-comint-buffer (current-buffer)))))
-
-(defvar gud-filter-defer-flag nil
- "Non-nil means don't process anything from the debugger right now.
-It is saved for when this flag is not set.")
-
-(defvar gud-filter-pending-text nil
- "Non-nil means this is text that has been saved for later in `gud-filter'.")
-
-;; These functions are responsible for inserting output from your debugger
-;; into the buffer. The hard work is done by the method that is
-;; the value of gud-marker-filter.
-
-(defun gud-filter (proc string)
- ;; Here's where the actual buffer insertion is done
- (let (output process-window)
- (if (buffer-name (process-buffer proc))
- (if gud-filter-defer-flag
- ;; If we can't process any text now,
- ;; save it for later.
- (setq gud-filter-pending-text
- (concat (or gud-filter-pending-text "") string))
-
- ;; If we have to ask a question during the processing,
- ;; defer any additional text that comes from the debugger
- ;; during that time.
- (let ((gud-filter-defer-flag t))
- ;; Process now any text we previously saved up.
- (if gud-filter-pending-text
- (setq string (concat gud-filter-pending-text string)
- gud-filter-pending-text nil))
- (save-excursion
- (set-buffer (process-buffer proc))
- ;; If we have been so requested, delete the debugger prompt.
- (if (marker-buffer gud-delete-prompt-marker)
- (progn
- (delete-region (process-mark proc) gud-delete-prompt-marker)
- (set-marker gud-delete-prompt-marker nil)))
- ;; Save the process output, checking for source file markers.
- (setq output (gud-marker-filter string))
- ;; Check for a filename-and-line number.
- ;; 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.
- (setq process-window
- (and gud-last-frame
- (>= (point) (process-mark proc))
- (get-buffer-window (current-buffer))))
-
- ;; Let the comint filter do the actual insertion.
- ;; That lets us inherit various comint features.
- (comint-output-filter proc output)))
-
- ;; Put the arrow on the source line.
- ;; This must be outside of the save-excursion
- ;; in case the source file is our current buffer.
- (if process-window
- (save-selected-window
- (select-window process-window)
- (gud-display-frame))
- ;; We have to be in the proper buffer, (process-buffer proc),
- ;; but not in a save-excursion, because that would restore point.
- (let ((old-buf (current-buffer)))
- (set-buffer (process-buffer proc))
- (unwind-protect
- (gud-display-frame)
- (set-buffer old-buf))))
-
- ;; If we deferred text that arrived during this processing,
- ;; handle it now.
- (if gud-filter-pending-text
- (gud-filter proc ""))))))
-
-(defun gud-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-update)
- (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 gud buffer.
- (set-buffer obuf))))))
-
-(defun gud-display-frame ()
- "Find and obey the last filename-and-line marker from the debugger.
-Obeying it means displaying in another window the specified file and line."
- (interactive)
- (if gud-last-frame
- (progn
- (gud-set-buffer)
- (gud-display-line (car gud-last-frame) (cdr gud-last-frame))
- (setq gud-last-last-frame gud-last-frame
- gud-last-frame nil))))
-
-;; 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.
-;; Most of the trickiness in here comes from wanting to preserve the current
-;; region-restriction if that's possible. We use an explicit display-buffer
-;; to get around the fact that this is called inside a save-excursion.
-
-(defun gud-display-line (true-file line)
- (let* ((last-nonmenu-event t) ; Prevent use of dialog box for questions.
- (buffer
- (save-excursion
- (or (eq (current-buffer) gud-comint-buffer)
- (set-buffer gud-comint-buffer))
- (gud-find-file true-file)))
- (window (and buffer (or (get-buffer-window buffer)
- (display-buffer buffer))))
- (pos))
- (if buffer
- (progn
- (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)))))
-
-;;; The gud-call function must do the right thing whether its invoking
-;;; keystroke is from the GUD buffer itself (via major-mode binding)
-;;; or a C buffer. In the former case, we want to supply data from
-;;; gud-last-frame. Here's how we do it:
-
-(defun gud-format-command (str arg)
- (let ((insource (not (eq (current-buffer) gud-comint-buffer)))
- (frame (or gud-last-frame gud-last-last-frame))
- result)
- (while (and str (string-match "\\([^%]*\\)%\\([adeflp]\\)" str))
- (let ((key (string-to-char (substring str (match-beginning 2))))
- subst)
- (cond
- ((eq key ?f)
- (setq subst (file-name-nondirectory (if insource
- (buffer-file-name)
- (car frame)))))
- ((eq key ?d)
- (setq subst (file-name-directory (if insource
- (buffer-file-name)
- (car frame)))))
- ((eq key ?l)
- (setq subst (if insource
- (save-excursion
- (beginning-of-line)
- (save-restriction (widen)
- (1+ (count-lines 1 (point)))))
- (cdr frame))))
- ((eq key ?e)
- (setq subst (gud-find-c-expr)))
- ((eq key ?a)
- (setq subst (gud-read-address)))
- ((eq key ?p)
- (setq subst (if arg (int-to-string arg) ""))))
- (setq result (concat result
- (substring str (match-beginning 1) (match-end 1))
- subst)))
- (setq str (substring str (match-end 2))))
- ;; There might be text left in STR when the loop ends.
- (concat result str)))
-
-(defun gud-read-address ()
- "Return a string containing the core-address found in the buffer at point."
- (save-excursion
- (let ((pt (point)) found begin)
- (setq found (if (search-backward "0x" (- pt 7) t) (point)))
- (cond
- (found (forward-char 2)
- (buffer-substring found
- (progn (re-search-forward "[^0-9a-f]")
- (forward-char -1)
- (point))))
- (t (setq begin (progn (re-search-backward "[^0-9]")
- (forward-char 1)
- (point)))
- (forward-char 1)
- (re-search-forward "[^0-9]")
- (forward-char -1)
- (buffer-substring begin (point)))))))
-
-(defun gud-call (fmt &optional arg)
- (let ((msg (gud-format-command fmt arg)))
- (message "Command: %s" msg)
- (sit-for 0)
- (gud-basic-call msg)))
-
-(defun gud-basic-call (command)
- "Invoke the debugger COMMAND displaying source in other window."
- (interactive)
- (gud-set-buffer)
- (let ((command (concat command "\n"))
- (proc (get-buffer-process gud-comint-buffer)))
- (or proc (error "Current buffer has no process"))
- ;; Arrange for the current prompt to get deleted.
- (save-excursion
- (set-buffer gud-comint-buffer)
- (goto-char (process-mark proc))
- (beginning-of-line)
- (if (looking-at comint-prompt-regexp)
- (set-marker gud-delete-prompt-marker (point))))
- (process-send-string proc command)))
-
-(defun gud-refresh (&optional arg)
- "Fix up a possibly garbled display, and redraw the arrow."
- (interactive "P")
- (recenter arg)
- (or gud-last-frame (setq gud-last-frame gud-last-last-frame))
- (gud-display-frame))
-
-
-(defun gud-new-keymap (map)
- "Return a new keymap which inherits from MAP and has name `Gud'."
- (nconc (make-sparse-keymap "Gud") map))
-
-(defun gud-make-debug-menu ()
- "Make sure the current local map has a [menu-bar debug] submap.
-If it doesn't, replace it with a new map that inherits it,
-and create such a submap in that new map."
- (if (and (current-local-map)
- (lookup-key (current-local-map) [menu-bar debug]))
- nil
- (use-local-map (gud-new-keymap (current-local-map)))
- (define-key (current-local-map) [menu-bar debug]
- (cons "Gud" (gud-new-keymap gud-menu-map)))))
-
-;;; Code for parsing expressions out of C code. The single entry point is
-;;; find-c-expr, which tries to return an lvalue expression from around point.
-;;;
-;;; The rest of this file is a hacked version of gdbsrc.el by
-;;; Debby Ayers <ayers@asc.slb.com>,
-;;; Rich Schaefer <schaefer@asc.slb.com> Schlumberger, Austin, Tx.
-
-(defun gud-find-c-expr ()
- "Returns the C expr that surrounds point."
- (interactive)
- (save-excursion
- (let (p expr test-expr)
- (setq p (point))
- (setq expr (gud-innermost-expr))
- (setq test-expr (gud-prev-expr))
- (while (and test-expr (gud-expr-compound test-expr expr))
- (let ((prev-expr expr))
- (setq expr (cons (car test-expr) (cdr expr)))
- (goto-char (car expr))
- (setq test-expr (gud-prev-expr))
- ;; If we just pasted on the condition of an if or while,
- ;; throw it away again.
- (if (member (buffer-substring (car test-expr) (cdr test-expr))
- '("if" "while" "for"))
- (setq test-expr nil
- expr prev-expr))))
- (goto-char p)
- (setq test-expr (gud-next-expr))
- (while (gud-expr-compound expr test-expr)
- (setq expr (cons (car expr) (cdr test-expr)))
- (setq test-expr (gud-next-expr))
- )
- (buffer-substring (car expr) (cdr expr)))))
-
-(defun gud-innermost-expr ()
- "Returns the smallest expr that point is in; move point to beginning of it.
-The expr is represented as a cons cell, where the car specifies the point in
-the current buffer that marks the beginning of the expr and the cdr specifies
-the character after the end of the expr."
- (let ((p (point)) begin end)
- (gud-backward-sexp)
- (setq begin (point))
- (gud-forward-sexp)
- (setq end (point))
- (if (>= p end)
- (progn
- (setq begin p)
- (goto-char p)
- (gud-forward-sexp)
- (setq end (point)))
- )
- (goto-char begin)
- (cons begin end)))
-
-(defun gud-backward-sexp ()
- "Version of `backward-sexp' that catches errors."
- (condition-case nil
- (backward-sexp)
- (error t)))
-
-(defun gud-forward-sexp ()
- "Version of `forward-sexp' that catches errors."
- (condition-case nil
- (forward-sexp)
- (error t)))
-
-(defun gud-prev-expr ()
- "Returns the previous expr, point is set to beginning of that expr.
-The expr is represented as a cons cell, where the car specifies the point in
-the current buffer that marks the beginning of the expr and the cdr specifies
-the character after the end of the expr"
- (let ((begin) (end))
- (gud-backward-sexp)
- (setq begin (point))
- (gud-forward-sexp)
- (setq end (point))
- (goto-char begin)
- (cons begin end)))
-
-(defun gud-next-expr ()
- "Returns the following expr, point is set to beginning of that expr.
-The expr is represented as a cons cell, where the car specifies the point in
-the current buffer that marks the beginning of the expr and the cdr specifies
-the character after the end of the expr."
- (let ((begin) (end))
- (gud-forward-sexp)
- (gud-forward-sexp)
- (setq end (point))
- (gud-backward-sexp)
- (setq begin (point))
- (cons begin end)))
-
-(defun gud-expr-compound-sep (span-start span-end)
- "Scan from SPAN-START to SPAN-END for punctuation characters.
-If `->' is found, return `?.'. If `.' is found, return `?.'.
-If any other punctuation is found, return `??'.
-If no punctuation is found, return `? '."
- (let ((result ?\ )
- (syntax))
- (while (< span-start span-end)
- (setq syntax (char-syntax (char-after span-start)))
- (cond
- ((= syntax ?\ ) t)
- ((= syntax ?.) (setq syntax (char-after span-start))
- (cond
- ((= syntax ?.) (setq result ?.))
- ((and (= syntax ?-) (= (char-after (+ span-start 1)) ?>))
- (setq result ?.)
- (setq span-start (+ span-start 1)))
- (t (setq span-start span-end)
- (setq result ??)))))
- (setq span-start (+ span-start 1)))
- result))
-
-(defun gud-expr-compound (first second)
- "Non-nil if concatenating FIRST and SECOND makes a single C expression.
-The two exprs are represented as a cons cells, where the car
-specifies the point in the current buffer that marks the beginning of the
-expr and the cdr specifies the character after the end of the expr.
-Link exprs of the form:
- Expr -> Expr
- Expr . Expr
- Expr (Expr)
- Expr [Expr]
- (Expr) Expr
- [Expr] Expr"
- (let ((span-start (cdr first))
- (span-end (car second))
- (syntax))
- (setq syntax (gud-expr-compound-sep span-start span-end))
- (cond
- ((= (car first) (car second)) nil)
- ((= (cdr first) (cdr second)) nil)
- ((= syntax ?.) t)
- ((= syntax ?\ )
- (setq span-start (char-after (- span-start 1)))
- (setq span-end (char-after span-end))
- (cond
- ((= span-start ?)) t)
- ((= span-start ?]) t)
- ((= span-end ?() t)
- ((= span-end ?[) t)
- (t nil)))
- (t nil))))
-
-(provide 'gud)
-
-;;; gud.el ends here
diff --git a/lisp/help-macro.el b/lisp/help-macro.el
deleted file mode 100644
index ff9c71b3ee0..00000000000
--- a/lisp/help-macro.el
+++ /dev/null
@@ -1,177 +0,0 @@
-;;; help-macro.el --- Makes command line help such as help-for-help
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Lynn Slater <lrs@indetech.com>
-;; Created: : Mon Oct 1 11:42:39 1990
-;; Adapted-By: ESR
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This file supplies the macro make-help-screen which constructs
-;; single character dispatching with browsable help such as that provided
-;; by help-for-help. This can be used to make many modes easier to use; for
-;; example, the Gnu Emacs Empire Tool uses this for every "nested" mode map
-;; called from the main mode map.
-
-;; The name of this package was changed from help-screen.el to
-;; help-macro.el in order to fit in a 14-character limit.
-
-;;-> *********************** Example of use *********************************
-
-;;->(make-help-screen help-for-empire-redistribute-map
-;;-> "c:civ m:mil p:population f:food ?"
-;;-> "You have discovered the GEET redistribution commands
-;;-> From here, you can use the following options:
-;;->
-;;->c Redistribute civs from overfull sectors into connected underfull ones
-;;-> The functions typically named by empire-ideal-civ-fcn control
-;;-> based in part on empire-sector-civ-threshold
-;;->m Redistribute military using levels given by empire-ideal-mil-fcn
-;;->p Redistribute excess population to highways for max pop growth
-;;-> Excess is any sector so full babies will not be born.
-;;->f Even out food on highways to highway min and leave levels
-;;-> This is good to pump max food to all warehouses/dist pts
-;;->
-;;->
-;;->Use \\[help-for-empire-redistribute-map] for help on redistribution.
-;;->Use \\[help-for-empire-extract-map] for help on data extraction.
-;;->Please use \\[describe-key] to find out more about any of the other keys."
-;;-> empire-shell-redistribute-map)
-
-;;-> (define-key c-mp "\C-h" 'help-for-empire-redistribute-map)
-;;-> (define-key c-mp help-character 'help-for-empire-redistribute-map)
-
-;;; Change Log:
-;;
-;; 22-Jan-1991 Lynn Slater x2048
-;; Last Modified: Mon Oct 1 11:43:52 1990 #3 (Lynn Slater)
-;; documented better
-
-;;; Code:
-
-(provide 'help-macro)
-(require 'backquote)
-
-;;;###autoload
-(defvar three-step-help nil
- "*Non-nil means give more info about Help command in three steps.
-The three steps are simple prompt, prompt with all options,
-and window listing and describing the options.
-A value of nil means skip the middle step, so that
-\\[help-command] \\[help-command] gives the window that lists the options.")
-
-(defmacro make-help-screen (fname help-line help-text helped-map)
- "Construct help-menu function name FNAME.
-When invoked, FNAME shows HELP-LINE and reads a command using HELPED-MAP.
-If the command is the help character, FNAME displays HELP-TEXT
-and continues trying to read a command using HELPED-MAP.
-When FNAME finally does get a command, it executes that command
-and then returns."
- (` (defun (, fname) ()
- (, help-text)
- (interactive)
- (let ((line-prompt
- (substitute-command-keys (, help-line))))
- (if three-step-help
- (message "%s" line-prompt))
- (let* ((help-screen (documentation (quote (, fname))))
- ;; We bind overriding-local-map for very small
- ;; sections, *excluding* where we switch buffers
- ;; and where we execute the chosen help command.
- (local-map (make-sparse-keymap))
- (minor-mode-map-alist nil)
- (prev-frame (selected-frame))
- config new-frame key char)
- (unwind-protect
- (progn
- (setcdr local-map (, helped-map))
- (define-key local-map [t] 'undefined)
- (if three-step-help
- (progn
- (setq key (let ((overriding-local-map local-map))
- (read-key-sequence nil)))
- ;; Make the HELP key translate to C-h.
- (if (lookup-key function-key-map key)
- (setq key (lookup-key function-key-map key)))
- (setq char (aref key 0)))
- (setq char ??))
- (if (or (eq char ??) (eq char help-char)
- (memq char help-event-list))
- (progn
- (setq config (current-window-configuration))
- (switch-to-buffer-other-window "*Help*")
- (and (fboundp 'make-frame)
- (not (eq (window-frame (selected-window))
- prev-frame))
- (setq new-frame (window-frame (selected-window))
- config nil))
- (erase-buffer)
- (insert help-screen)
- (help-mode)
- (goto-char (point-min))
- (while (or (memq char (append help-event-list
- (cons help-char '(?? ?\C-v ?\ ?\177 delete backspace ?\M-v))))
- (eq (car-safe char) 'switch-frame)
- (equal key "\M-v"))
- (condition-case nil
- (progn
- (if (eq (car-safe char) 'switch-frame)
- (handle-switch-frame char))
- (if (memq char '(?\C-v ?\ ))
- (scroll-up))
- (if (or (memq char '(?\177 ?\M-v
- delete backspace))
- (equal key "\M-v"))
- (scroll-down)))
- (error nil))
- (let ((cursor-in-echo-area t)
- (overriding-local-map local-map))
- (setq key (read-key-sequence
- (format "Type one of the options listed%s: "
- (if (pos-visible-in-window-p
- (point-max))
- "" " or Space to scroll")))
- char (aref key 0))))))
- ;; Mouse clicks are not part of the help feature,
- ;; so reexecute them in the standard environment.
- (if (listp char)
- (setq unread-command-events
- (cons char unread-command-events)
- config nil)
- (let ((defn (lookup-key local-map key)))
- (if defn
- (progn
- (if config
- (progn
- (set-window-configuration config)
- (setq config nil)))
- (if new-frame
- (progn (iconify-frame new-frame)
- (setq new-frame nil)))
- (call-interactively defn))
- (ding)))))
- (if new-frame (iconify-frame new-frame))
- (if config
- (set-window-configuration config))))))
- ))
-
-;;; help-macro.el
-
diff --git a/lisp/help.el b/lisp/help.el
deleted file mode 100644
index 9f4c2cf352b..00000000000
--- a/lisp/help.el
+++ /dev/null
@@ -1,705 +0,0 @@
-;;; help.el --- help commands for Emacs
-
-;; Copyright (C) 1985, 1986, 1993, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: help, internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This code implements GNU Emacs' on-line help system, the one invoked by
-;;`M-x help-for-help'.
-
-;;; Code:
-
-;; Get the macro make-help-screen when this is compiled,
-;; or run interpreted, but not when the compiled code is loaded.
-(eval-when-compile (require 'help-macro))
-
-(defvar help-map (make-sparse-keymap)
- "Keymap for characters following the Help key.")
-
-(defvar help-mode-map (make-sparse-keymap)
- "Keymap for help mode.")
-
-(define-key global-map (char-to-string help-char) 'help-command)
-(define-key global-map [help] 'help-command)
-(define-key global-map [f1] 'help-command)
-(fset 'help-command help-map)
-
-(define-key help-map (char-to-string help-char) 'help-for-help)
-(define-key help-map [help] 'help-for-help)
-(define-key help-map [f1] '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 "\C-p" 'describe-project)
-(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 "F" 'view-emacs-FAQ)
-
-(define-key help-map "i" 'info)
-(define-key help-map "\C-f" 'Info-goto-emacs-command-node)
-(define-key help-map "\C-k" 'Info-goto-emacs-key-command-node)
-(define-key help-map "\C-i" 'word-help)
-
-(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 "p" 'finder-by-keyword)
-(autoload 'finder-by-keyword "finder"
- "Find packages matching a given keyword." t)
-
-(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)
-
-(define-key help-map "q" 'help-quit)
-
-(defvar help-font-lock-keywords
- (eval-when-compile
- (let ((name-char "[-+a-zA-Z0-9_*]") (sym-char "[-+a-zA-Z0-9_:*]"))
- (list
- ;;
- ;; The symbol itself.
- (list (concat "\\`\\(" name-char "+\\)\\(\\(:\\)\\|\\('\\)\\)")
- '(1 (if (match-beginning 3)
- font-lock-function-name-face
- font-lock-variable-name-face)))
- ;;
- ;; Words inside `' which tend to be symbol names.
- (list (concat "`\\(" sym-char sym-char "+\\)'")
- 1 'font-lock-reference-face t)
- ;;
- ;; CLisp `:' keywords as references.
- (list (concat "\\<:" sym-char "+\\>") 0 'font-lock-reference-face t))))
- "Default expressions to highlight in Help mode.")
-
-(defun help-mode ()
- "Major mode for viewing help text.
-Entry to this mode runs the normal hook `help-mode-hook'.
-Commands:
-\\{help-mode-map}"
- (interactive)
- (kill-all-local-variables)
- (use-local-map help-mode-map)
- (setq mode-name "Help")
- (setq major-mode 'help-mode)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(help-font-lock-keywords))
- (view-mode)
- (run-hooks 'help-mode-hook))
-
-(defun help-quit ()
- (interactive)
- nil)
-
-(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 buffer-auto-save-file-name nil)
- (insert-file-contents (expand-file-name "TUTORIAL" data-directory))
- (goto-char (point-min))
- (search-forward "\n<<")
- (beginning-of-line)
- (delete-region (point) (progn (end-of-line) (point)))
- (let ((n (- (window-height (selected-window))
- (count-lines (point-min) (point))
- 6)))
- (if (< n 12)
- (newline n)
- ;; Some people get confused by the large gap.
- (newline (/ n 2))
- (insert "[Middle of page left blank for didactic purposes. "
- "Text continues below]")
- (newline (- n (/ n 2)))))
- (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: ")
- ;; If this key seq ends with a down event, discard the
- ;; following click or drag event. Otherwise that would
- ;; erase the message.
- (let ((type (aref key (1- (length key)))))
- (if (listp type) (setq type (car type)))
- (and (symbolp type)
- (memq 'down (event-modifiers type))
- (read-event)))
- (save-excursion
- (let ((modifiers (event-modifiers (aref key 0)))
- window position)
- ;; For a mouse button event, go to the button it applies to
- ;; to get the right key bindings. And go to the right place
- ;; in case the keymap depends on where you clicked.
- (if (or (memq 'click modifiers) (memq 'down modifiers)
- (memq 'drag modifiers))
- (setq window (posn-window (event-start (aref key 0)))
- position (posn-point (event-start (aref key 0)))))
- (if (windowp window)
- (progn
- (set-buffer (window-buffer window))
- (goto-char position)))
- ;; Ok, now look up the key and name the command.
- (let ((defn (key-binding key)))
- (if (or (null defn) (integerp defn))
- (message "%s is undefined" (key-description key))
- (message (if (windowp window)
- "%s at that spot runs the command %s"
- "%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 optional argument FUNCTION to it.
-If FUNCTION is nil, applies `message' to it, thus printing it."
- (and (not (get-buffer-window standard-output))
- (let ((first-message
- (cond ((special-display-p (buffer-name standard-output))
- ;; If the help output buffer is a special display buffer,
- ;; don't say anything about how to get rid of it.
- ;; First of all, the user will do that with the window
- ;; manager, not with Emacs.
- ;; Secondly, the buffer has not been displayed yet,
- ;; so we don't know whether its frame will be selected.
- nil)
- ((not (one-window-p t))
- "Type \\[switch-to-buffer-other-window] RET to restore the other window.")
- (pop-up-windows
- "Type \\[delete-other-windows] to remove help window.")
- (t
- "Type \\[switch-to-buffer] RET to remove help window."))))
- (funcall (or function 'message)
- (concat
- (if first-message
- (substitute-command-keys first-message)
- "")
- (if first-message " " "")
- ;; If the help buffer will go in a separate frame,
- ;; it's no use mentioning a command to scroll, so don't.
- (if (special-display-p (buffer-name standard-output))
- nil
- (if (same-window-p (buffer-name standard-output))
- ;; Say how to scroll this window.
- (substitute-command-keys
- "\\[scroll-up] to scroll the help.")
- ;; Say how to scroll some other window.
- (substitute-command-keys
- "\\[scroll-other-window] to scroll the help."))))))))
-
-(defun describe-key (key)
- "Display documentation of the function invoked by KEY. KEY is a string."
- (interactive "kDescribe key: ")
- ;; If this key seq ends with a down event, discard the
- ;; following click or drag event. Otherwise that would
- ;; erase the message.
- (let ((type (aref key (1- (length key)))))
- (if (listp type) (setq type (car type)))
- (and (symbolp type)
- (memq 'down (event-modifiers type))
- (read-event)))
- (save-excursion
- (let ((modifiers (event-modifiers (aref key 0)))
- window position)
- ;; For a mouse button event, go to the button it applies to
- ;; to get the right key bindings. And go to the right place
- ;; in case the keymap depends on where you clicked.
- (if (or (memq 'click modifiers) (memq 'down modifiers)
- (memq 'drag modifiers))
- (setq window (posn-window (event-start (aref key 0)))
- position (posn-point (event-start (aref key 0)))))
- (if (windowp window)
- (progn
- (set-buffer (window-buffer window))
- (goto-char position)))
- (let ((defn (key-binding key)))
- (if (or (null defn) (integerp defn))
- (message "%s is undefined" (key-description key))
- (with-output-to-temp-buffer "*Help*"
- (princ (key-description key))
- (if (windowp window)
- (princ " at that spot"))
- (princ " runs the command ")
- (prin1 defn)
- (princ ":\n")
- (let ((doc (documentation defn)))
- (if doc
- (progn (terpri)
- (princ doc))
- (princ "not documented")))
- (save-excursion
- (set-buffer standard-output)
- (help-mode))
- (print-help-return-message)))))))
-
-(defun describe-mode ()
- "Display documentation of current major mode and minor modes.
-For this to work correctly for a minor mode, the mode's indicator variable
-\(listed in `minor-mode-alist') must also be a function whose documentation
-describes the minor mode."
- (interactive)
- (with-output-to-temp-buffer "*Help*"
- (let ((minor-modes minor-mode-alist)
- (first t))
- (while minor-modes
- (let* ((minor-mode (car (car minor-modes)))
- (indicator (car (cdr (car minor-modes)))))
- ;; Document a minor mode if it is listed in minor-mode-alist,
- ;; bound locally in this buffer, non-nil, and has a function
- ;; definition.
- (if (and (symbol-value minor-mode)
- (fboundp minor-mode))
- (let ((pretty-minor-mode minor-mode))
- (if (string-match "-mode$" (symbol-name minor-mode))
- (setq pretty-minor-mode
- (capitalize
- (substring (symbol-name minor-mode)
- 0 (match-beginning 0)))))
- (while (and indicator (symbolp indicator))
- (setq indicator (symbol-value indicator)))
- (if first
- (princ "The minor modes are described first,
-followed by the major mode, which is described on the last page.\n\f\n"))
- (setq first nil)
- (princ (format "%s minor mode (%s):\n"
- pretty-minor-mode
- (if indicator
- (format "indicator%s" indicator)
- "no indicator")))
- (princ (documentation minor-mode))
- (princ "\n\f\n"))))
- (setq minor-modes (cdr minor-modes))))
- (princ mode-name)
- (princ " mode:\n")
- (princ (documentation major-mode))
- (save-excursion
- (set-buffer standard-output)
- (help-mode))
- (print-help-return-message)))
-
-;; So keyboard macro definitions are documented correctly
-(fset 'defining-kbd-macro (symbol-function 'start-kbd-macro))
-
-(defun describe-distribution ()
- "Display info on how to obtain the latest version of GNU Emacs."
- (interactive)
- (find-file-read-only
- (expand-file-name "DISTRIB" data-directory)))
-
-(defun describe-copying ()
- "Display info on how you may redistribute copies of GNU Emacs."
- (interactive)
- (find-file-read-only
- (expand-file-name "COPYING" data-directory))
- (goto-char (point-min)))
-
-(defun describe-project ()
- "Display info on the GNU project."
- (interactive)
- (find-file-read-only
- (expand-file-name "GNU" data-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 describe-prefix-bindings ()
- "Describe the bindings of the prefix used to reach this command.
-The prefix described consists of all but the last event
-of the key sequence that ran this command."
- (interactive)
- (let* ((key (this-command-keys)))
- (describe-bindings
- (if (stringp key)
- (substring key 0 (1- (length key)))
- (let ((prefix (make-vector (1- (length key)) nil))
- (i 0))
- (while (< i (length prefix))
- (aset prefix i (aref key i))
- (setq i (1+ i)))
- prefix)))))
-;; Make C-h after a prefix, when not specifically bound,
-;; run describe-prefix-bindings.
-(setq prefix-help-command 'describe-prefix-bindings)
-
-(defun view-emacs-news ()
- "Display info on recent changes to Emacs."
- (interactive)
- (find-file-read-only (expand-file-name "NEWS" data-directory)))
-
-(defun view-emacs-FAQ ()
- "Display the Emacs Frequently Asked Questions (FAQ) file."
- (interactive)
- (find-file-read-only (expand-file-name "FAQ" data-directory)))
-
-(defun view-lossage ()
- "Display last 100 input keystrokes."
- (interactive)
- (with-output-to-temp-buffer "*Help*"
- (princ (mapconcat (function (lambda (key)
- (if (or (integerp key)
- (symbolp key)
- (listp key))
- (single-key-description key)
- (prin1-to-string key nil))))
- (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"))
- (help-mode))
- (print-help-return-message)))
-
-(defalias 'help 'help-for-help)
-(make-help-screen help-for-help
- "a b c f C-f i k C-k l m n p s t v w C-c C-d C-n C-w, or ? for more help:"
- "You have typed \\[help-command], the help character. Type a Help option:
-\(Use SPC or DEL to scroll through this text. Type \\<help-map>\\[help-quit] to exit the Help command.)
-
-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.
-C-f Info-goto-emacs-command-node. Type a function name;
- it takes you to the Info node for that command.
-F view-emacs-FAQ. Shows emacs frequently asked questions file.
-i info. The info documentation reader.
-k describe-key. Type a command key sequence;
- it displays the full documentation.
-C-k Info-goto-emacs-key-command-node. Type a command key sequence;
- it takes you to the Info node for the command bound to that key.
-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.
-p finder-by-keyword. Find packages matching a given topic keyword.
-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-p print information about the GNU project.
-C-w print information on absence of warranty for GNU Emacs."
- help-map)
-
-;; Return a function which is called by the list containing point.
-;; If that gives no function, return a function whose name is around point.
-;; If that doesn't give a function, return nil.
-(defun function-called-at-point ()
- (or (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))
- (condition-case ()
- (let ((stab (syntax-table)))
- (unwind-protect
- (save-excursion
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (or (not (zerop (skip-syntax-backward "_w")))
- (eq (char-syntax (following-char)) ?w)
- (eq (char-syntax (following-char)) ?_)
- (forward-sexp -1))
- (skip-chars-forward "'")
- (let ((obj (read (current-buffer))))
- (and (symbolp obj) (fboundp obj) obj)))
- (set-syntax-table stab)))
- (error nil))))
-
-(defun describe-function-find-file (function)
- (let ((files load-history)
- file functions)
- (while files
- (if (memq function (cdr (car files)))
- (setq file (car (car files)) files nil))
- (setq files (cdr files)))
- file))
-
-(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)))))
- (if function
- (with-output-to-temp-buffer "*Help*"
- (prin1 function)
- (princ ": ")
- (let* ((def (symbol-function function))
- file-name
- (beg (if (commandp def) "an interactive " "a ")))
- (princ (cond ((or (stringp def)
- (vectorp def))
- "a keyboard macro")
- ((subrp def)
- (concat beg "built-in function"))
- ((byte-code-function-p def)
- (concat beg "compiled Lisp function"))
- ((symbolp def)
- (format "alias for `%s'" def))
- ((eq (car-safe def) 'lambda)
- (concat beg "Lisp function"))
- ((eq (car-safe def) 'macro)
- "a Lisp macro")
- ((eq (car-safe def) 'mocklisp)
- "a mocklisp function")
- ((eq (car-safe def) 'autoload)
- (setq file-name (nth 1 def))
- (format "%s autoloaded Lisp %s"
- (if (commandp def) "an interactive" "an")
- (if (nth 4 def) "macro" "function")
- ))
- (t "")))
- (or file-name
- (setq file-name (describe-function-find-file function)))
- (if file-name
- (progn
- (princ " in `")
- ;; We used to add .el to the file name,
- ;; but that's completely wrong when the user used load-file.
- (princ file-name)
- (princ "'")))
- (princ ".")
- (terpri)
- (let ((arglist (cond ((byte-code-function-p def)
- (car (append def nil)))
- ((eq (car-safe def) 'lambda)
- (nth 1 def))
- (t t))))
- (if (listp arglist)
- (progn
- (princ (cons function
- (mapcar (lambda (arg)
- (if (memq arg '(&optional &rest))
- arg
- (intern (upcase (symbol-name arg)))))
- arglist)))
- (terpri))))
- (let ((doc (documentation function)))
- (if doc
- (progn (terpri)
- (princ doc))
- (princ "not documented"))))
- (print-help-return-message)
- (save-excursion
- (set-buffer standard-output)
- (help-mode)
- ;; Return the text we displayed.
- (buffer-string)))
- (message "You didn't specify a function")))
-
-;; We return 0 if we can't find a variable to return.
-(defun variable-at-point ()
- (condition-case ()
- (let ((stab (syntax-table)))
- (unwind-protect
- (save-excursion
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (or (not (zerop (skip-syntax-backward "_w")))
- (eq (char-syntax (following-char)) ?w)
- (eq (char-syntax (following-char)) ?_)
- (forward-sexp -1))
- (skip-chars-forward "'")
- (let ((obj (read (current-buffer))))
- (or (and (symbolp obj) (boundp obj) obj)
- 0)))
- (set-syntax-table stab)))
- (error 0)))
-
-(defun describe-variable (variable)
- "Display the full documentation of VARIABLE (a symbol).
-Returns the documentation as a string, also."
- (interactive
- (let ((v (variable-at-point))
- (enable-recursive-minibuffers t)
- val)
- (setq val (completing-read (if (symbolp v)
- (format "Describe variable (default %s): " v)
- "Describe variable: ")
- obarray 'boundp t))
- (list (if (equal val "")
- v (intern val)))))
- (if (symbolp variable)
- (let (valvoid)
- (with-output-to-temp-buffer "*Help*"
- (prin1 variable)
- (if (not (boundp variable))
- (progn
- (princ " is void")
- (terpri)
- (setq valvoid t))
- (princ "'s value is ")
- (terpri)
- (pp (symbol-value variable))
- (terpri))
- (if (local-variable-p variable)
- (progn
- (princ (format "Local in buffer %s; " (buffer-name)))
- (if (not (default-boundp variable))
- (princ "globally void")
- (princ "global value is ")
- (terpri)
- (pp (default-value variable)))
- (terpri)))
- (terpri)
- (save-current-buffer
- (set-buffer standard-output)
- (if (> (count-lines (point-min) (point-max)) 10)
- (progn
- (goto-char (point-min))
- (if valvoid
- (forward-line 1)
- (forward-sexp 1)
- (delete-region (point) (progn (end-of-line) (point)))
- (insert "'s value is shown below.\n\n")
- (save-excursion
- (insert "\n\nValue:"))))))
- (princ "Documentation:")
- (terpri)
- (let ((doc (documentation-property variable 'variable-documentation)))
- (princ (or doc "not documented as a variable.")))
- (print-help-return-message)
- (save-excursion
- (set-buffer standard-output)
- (help-mode)
- ;; Return the text we displayed.
- (buffer-string))))
- (message "You did not specify a variable")))
-
-(defun where-is (definition)
- "Print message listing key sequences that invoke specified command.
-Argument is a command definition, usually a symbol with a function definition."
- (interactive
- (let ((fn (function-called-at-point))
- (enable-recursive-minibuffers t)
- val)
- (setq val (completing-read (if fn
- (format "Where is command (default %s): " fn)
- "Where is command: ")
- obarray 'fboundp t))
- (list (if (equal val "")
- fn (intern val)))))
- (let* ((keys (where-is-internal definition overriding-local-map nil nil))
- (keys1 (mapconcat 'key-description keys ", ")))
- (if (> (length keys1) 0)
- (message "%s is on %s" definition keys1)
- (message "%s is not on any key" definition)))
- nil)
-
-(defun locate-library (library &optional nosuffix path interactive-call)
- "Show the precise file name of Emacs library LIBRARY.
-This command searches the directories in `load-path' like `M-x load-library'
-to find the file that `M-x load-library RET LIBRARY RET' would load.
-Optional second arg NOSUFFIX non-nil means don't add suffixes `.elc' or `.el'
-to the specified name LIBRARY.
-
-If the optional third arg PATH is specified, that list of directories
-is used instead of `load-path'."
- (interactive (list (read-string "Locate library: ")
- nil nil
- t))
- (let (result)
- (catch 'answer
- (mapcar
- (lambda (dir)
- (mapcar
- (lambda (suf)
- (let ((try (expand-file-name (concat library suf) dir)))
- (and (file-readable-p try)
- (null (file-directory-p try))
- (progn
- (setq result try)
- (throw 'answer try)))))
- (if nosuffix
- '("")
- (let ((basic '(".elc" ".el" ""))
- (compressed '(".Z" ".gz" "")))
- ;; If autocompression mode is on,
- ;; consider all combinations of library suffixes
- ;; and compression suffixes.
- (if (rassq 'jka-compr-handler file-name-handler-alist)
- (apply 'nconc
- (mapcar (lambda (compelt)
- (mapcar (lambda (baselt)
- (concat baselt compelt))
- basic))
- compressed))
- basic)))))
- (or path load-path)))
- (and interactive-call
- (if result
- (message "Library is file %s" result)
- (message "No library %s in search path" library)))
- result))
-
-;;; help.el ends here
diff --git a/lisp/hexl.el b/lisp/hexl.el
deleted file mode 100644
index 56f05de37cd..00000000000
--- a/lisp/hexl.el
+++ /dev/null
@@ -1,789 +0,0 @@
-;;; hexl.el --- edit a file in a hex dump format using the hexl filter.
-
-;; Copyright (C) 1989, 1994 Free Software Foundation, Inc.
-
-;; Author: Keith Gabryelski <ag@wheaties.ai.mit.edu>
-;; Maintainer: FSF
-;; Keywords: data
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package implements a major mode for editing binary files. It uses
-;; a program called hexl, supplied with the GNU Emacs distribution, that
-;; can filter a binary into an editable format or from the format back into
-;; binary. For full instructions, invoke `hexl-mode' on an empty buffer and
-;; do `M-x describe-mode'.
-;;
-;; 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.
-
-;;; Code:
-
-;;
-;; vars here
-;;
-
-(defvar hexl-program "hexl"
- "The program that will hexlify and dehexlify its stdin.
-`hexl-program' will always be concatenated with `hexl-options'
-and \"-de\" when dehexlifying 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 %s" exec-directory hexl-program hexl-options)
- "The command to use to hexlify a buffer.")
-
-(defvar dehexlify-command
- (format "%s%s -de %s" exec-directory hexl-program hexl-options)
- "The command to use to unhexlify a buffer.")
-
-(defvar hexl-max-address 0
- "Maximum offset into hexl buffer.")
-
-(defvar hexl-mode-map nil)
-
-(defvar hexl-mode-old-local-map)
-(defvar hexl-mode-old-mode-name)
-(defvar hexl-mode-old-major-mode)
-(defvar hexl-mode-old-write-contents-hooks)
-(defvar hexl-mode-old-require-final-newline)
-(defvar hexl-mode-old-syntax-table)
-
-;; routines
-
-;;;###autoload
-(defun hexl-mode (&optional arg)
- "\\<hexl-mode-map>
-A major mode for editing 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-mode-exit] will exit hexl-mode.
-
-Note: saving the file with any of the usual Emacs commands
-will actually convert it back to binary format while saving.
-
-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")
-
- (let ((modified (buffer-modified-p))
- (inhibit-read-only t)
- (original-point (1- (point)))
- max-address)
- (and (eobp) (not (bobp))
- (setq original-point (1- original-point)))
- (if (not (or (eq arg 1) (not arg)))
- ;; if no argument then we guess at hexl-max-address
- (setq max-address (+ (* (/ (1- (buffer-size)) 68) 16) 15))
- (setq max-address (1- (buffer-size)))
- (hexlify-buffer)
- (set-buffer-modified-p modified))
- (make-local-variable 'hexl-max-address)
- (setq hexl-max-address max-address)
- (hexl-goto-address original-point))
-
- ;; We do not turn off the old major mode; instead we just
- ;; override most of it. That way, we can restore it perfectly.
- (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)
-
- (make-local-variable 'hexl-mode-old-syntax-table)
- (setq hexl-mode-old-syntax-table (syntax-table))
- (set-syntax-table (standard-syntax-table))
-
- (make-local-variable 'hexl-mode-old-write-contents-hooks)
- (setq hexl-mode-old-write-contents-hooks write-contents-hooks)
- (make-local-variable 'write-contents-hooks)
- (add-hook 'write-contents-hooks 'hexl-save-buffer)
-
- (make-local-variable 'hexl-mode-old-require-final-newline)
- (setq hexl-mode-old-require-final-newline require-final-newline)
- (make-local-variable 'require-final-newline)
- (setq require-final-newline nil)
-
- ;; Add hooks to rehexlify or dehexlify on various events.
- (make-local-hook 'after-revert-hook)
- (add-hook 'after-revert-hook 'hexl-after-revert-hook nil t)
-
- (make-local-hook 'change-major-mode-hook)
- (add-hook 'change-major-mode-hook 'hexl-maybe-dehexlify-buffer nil t))
- (run-hooks 'hexl-mode-hook))
-
-(defun hexl-after-revert-hook ()
- (hexlify-buffer)
- (set-buffer-modified-p nil))
-
-(defvar hexl-in-save-buffer nil)
-
-(defun hexl-save-buffer ()
- "Save a hexl format buffer as binary in visited file if modified."
- (interactive)
- (if hexl-in-save-buffer nil
- (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)
- ;; Prevent infinite recursion.
- (let ((hexl-in-save-buffer t)
- (buffer-file-type t)) ; for ms-dos
- (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))
- ;; Return t to indicate we have saved t
- t))
-
-;;;###autoload
-(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: ")
- (if (or (eq system-type 'ms-dos) (eq system-type 'windows-nt))
- (find-file-binary filename)
- (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))
- (inhibit-read-only t)
- (original-point (1+ (hexl-current-address))))
- (dehexlify-buffer)
- (remove-hook 'write-contents-hooks 'hexl-save-buffer)
- (set-buffer-modified-p modified)
- (goto-char original-point)))
-
- (remove-hook 'after-revert-hook 'hexl-after-revert-hook t)
- (remove-hook 'change-major-mode-hook 'hexl-maybe-dehexlify-buffer t)
-
- (setq write-contents-hooks hexl-mode-old-write-contents-hooks)
- (setq require-final-newline hexl-mode-old-require-final-newline)
- (setq mode-name hexl-mode-old-mode-name)
- (use-local-map hexl-mode-old-local-map)
- (set-syntax-table hexl-mode-old-syntax-table)
- (setq major-mode hexl-mode-old-major-mode)
- (force-mode-line-update))
-
-(defun hexl-maybe-dehexlify-buffer ()
- "Convert a hexl format buffer to binary.
-Ask the user for confirmation."
- (if (y-or-n-p "Convert contents back to binary format? ")
- (let ((modified (buffer-modified-p))
- (inhibit-read-only t)
- (original-point (1+ (hexl-current-address))))
- (dehexlify-buffer)
- (remove-hook 'write-contents-hooks 'hexl-save-buffer)
- (set-buffer-modified-p modified)
- (goto-char original-point))))
-
-(defun hexl-current-address (&optional validate)
- "Return current hexl-address."
- (interactive)
- (let ((current-column (- (% (point) 68) 11))
- (hexl-address 0))
- (if (< current-column 0)
- (if validate
- (error "Point is not on a character in the file")
- (setq current-column 0)))
- (setq hexl-address
- (+ (* (/ (point) 68) 16)
- (if (>= current-column 41)
- (- current-column 41)
- (/ (- 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))))
- (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 ()
- "Go to beginning of 1k boundary."
- (interactive)
- (hexl-goto-address (logand (hexl-current-address) -1024)))
-
-(defun hexl-end-of-1k-page ()
- "Go to end of 1k boundary."
- (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 ()
- "Go to beginning of 512 byte boundary."
- (interactive)
- (hexl-goto-address (logand (hexl-current-address) -512)))
-
-(defun hexl-end-of-512b-page ()
- "Go to end of 512 byte boundary."
- (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
-
-;;;###autoload
-(defun hexlify-buffer ()
- "Convert a binary buffer to hexl format.
-This discards the buffer's undo information."
- (interactive)
- (and buffer-undo-list
- (or (y-or-n-p "Converting to hexl format discards undo info; ok? ")
- (error "Aborted")))
- (setq buffer-undo-list nil)
- (let ((binary-process-output nil) ; for Ms-Dos
- (binary-process-input t)
- (buffer-undo-list t))
- (shell-command-on-region (point-min) (point-max) hexlify-command t)))
-
-(defun dehexlify-buffer ()
- "Convert a hexl format buffer to binary.
-This discards the buffer's undo information."
- (interactive)
- (and buffer-undo-list
- (or (y-or-n-p "Converting from hexl format discards undo info; ok? ")
- (error "Aborted")))
- (setq buffer-undo-list nil)
- (let ((binary-process-output t) ; for Ms-Dos
- (binary-process-input nil)
- (buffer-undo-list t))
- (shell-command-on-region (point-min) (point-max) dehexlify-command t)))
-
-(defun hexl-char-after-point ()
- "Return char for ASCII hex digits at point."
- (hexl-htoi (char-after (point))
- (char-after (1+ (point)))))
-
-(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 "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 "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 t)))
- (while (> num 0)
- (let ((hex-position
- (+ (* (/ address 16) 68)
- 11
- (* 2 (% address 16))
- (/ (% address 16) 2)))
- (ascii-position
- (+ (* (/ address 16) 68) 52 (% address 16)))
- at-ascii-position)
- (if (= (point) ascii-position)
- (setq at-ascii-position t))
- (goto-char hex-position)
- (delete-char 2)
- (insert (format "%02x" ch))
- (goto-char ascii-position)
- (delete-char 1)
- (insert (hexl-printable-character ch))
- (or (eq address hexl-max-address)
- (setq address (1+ address)))
- (hexl-goto-address address)
- (if at-ascii-position
- (progn
- (beginning-of-line)
- (forward-char 51)
- (forward-char (% address 16)))))
- (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 [left] 'hexl-backward-char)
- (define-key hexl-mode-map [right] 'hexl-forward-char)
- (define-key hexl-mode-map [up] 'hexl-previous-line)
- (define-key hexl-mode-map [down] 'hexl-next-line)
- (define-key hexl-mode-map [M-left] 'hexl-backward-short)
- (define-key hexl-mode-map [M-right] 'hexl-forward-short)
- (define-key hexl-mode-map [next] 'hexl-scroll-up)
- (define-key hexl-mode-map [prior] 'hexl-scroll-down)
- (define-key hexl-mode-map [home] 'hexl-beginning-of-buffer)
- (define-key hexl-mode-map [deletechar] 'undefined)
- (define-key hexl-mode-map [deleteline] 'undefined)
- (define-key hexl-mode-map [insertline] 'undefined)
- (define-key hexl-mode-map [S-delete] 'undefined)
- (define-key hexl-mode-map "\177" 'undefined)
-
- (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 (char-to-string help-char)) 'help-command))
- (define-key hexl-mode-map (char-to-string help-char) '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" 'undefined)
- (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" 'undefined)
- (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[" 'hexl-beginning-of-1k-page)
- (define-key hexl-mode-map "\C-x]" 'hexl-end-of-1k-page)
- (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))
-
-;;; hexl.el ends here
diff --git a/lisp/hilit19.el b/lisp/hilit19.el
deleted file mode 100644
index 9694d7dd0c3..00000000000
--- a/lisp/hilit19.el
+++ /dev/null
@@ -1,1512 +0,0 @@
-;;; hilit19.el --- customizable highlighting for Emacs19
-
-;; Copyright (c) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Jonathan Stigelman <stig@hackvan.com>
-;; Keywords: faces
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Hilit19.el is a customizable highlighting package for Emacs19. It supports
-;; not only source code highlighting, but also Info, RMAIL, VM, gnus...
-;; Hilit19 knows (or thinks it knows) how to highlight emacs buffers in
-;; about 25 different modes.
-;;
-;; WHERE TO GET THE LATEST VERSIONS OF HILIT19.EL (beta and release),
-;; PLUS LOTS OF OTHER *WAY COOL* STUFF VIA ANONYMOUS FTP:
-;;
-;; ftp.hackvan.com:/pub/stig/src/elisp/hilit19.el.gz
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; TO SUBMIT BUG REPORTS (or feedback of any sort)...
-;;
-;; M-x hilit-submit-feedback RET
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; hilit19.el,v 2.19 1993/09/08 18:44:10 stig Release
-;;
-;; LCD Archive Entry:
-;; hilit19|Jonathan Stigelman|stig@hackvan.com|
-;; Comprehensive (and comparatively fast) regex-based highlighting for Emacs 19|
-;; 1993/09/08 18:44:10|Release 2.19|~/packages/hilit19.el.Z|
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; GENERAL OVERVIEW
-;;
-;; This package installs numerous hooks to colorfully highlight your
-;; source code buffers as well as mail and news buffers. Most
-;; programming languages have predefined highlighting patterns.
-;; Just load hilit19 and files will be automatically highlighted as
-;; they're loaded.
-;;
-;; Rehighlight a buffer by typing C-S-l (control-shift-lowercase-L).
-;;
-;; If, when you edit the buffer, the coloring gets messed up, just
-;; redraw and the coloring will be adjusted. If automatic highlighting
-;; in the current buffer has been turned off, then typing C-u C-S-l will
-;; force a rehighlight of the entire buffer.
-;;
-;; Hilit19 can build faces by examining the names that you give to them
-;; For example, green/black-bold-italic-underline would be created as
-;; a face with a green foreground, and a black background, using a
-;; bold-italic font...with underlining for good measure.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; SETUP -- In your .emacs:
-;;
-;;
-;; (cond (window-system
-;; (setq hilit-mode-enable-list '(not text-mode)
-;; hilit-background-mode 'light
-;; hilit-inhibit-hooks nil
-;; hilit-inhibit-rebinding nil)
-;;
-;; (require 'hilit19)
-;; ))
-;;
-;; If you like font-lock-mode and want to use both packages, then you can
-;; disable hilit for the modes in which you want to use font-lock by listing
-;; said modes in hilit-mode-enable-list.
-;;
-;; (hilit-translate type 'RoyalBlue ; enable highlighting in C/C++
-;; string nil) ; disable string highlighting
-;;
-;; To get 100% of the utility of hilit19, you may also have to apply the
-;; patches below for info.el and vm5.33L_19/vm-summary.el
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; SETUP -- Are you using the right font for Emacs?
-;;
-;; Emacs cannot properly find bold and italic fonts unless you specify a
-;; verbose X11 font name. If you specify a font for emacs in your
-;; .Xdefaults, it *MUST* be specified using the long form of the font name.
-;; Here's a good font menu:
-;;
-;; (setq
-;; x-fixed-font-alist
-;; '("Font Menu"
-;; ("Misc"
-;; ("6x12" "-misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-*-1")
-;; ("6x13" "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-*-1")
-;; ("lucida 13"
-;; "-b&h-lucidatypewriter-medium-r-normal-sans-0-0-0-0-m-0-*-1")
-;; ("7x13" "-misc-fixed-medium-r-normal--13-120-75-75-c-70-*-1")
-;; ("7x14" "-misc-fixed-medium-r-normal--14-130-75-75-c-70-*-1")
-;; ("9x15" "-misc-fixed-medium-r-normal--15-140-*-*-c-*-*-1")
-;; ("")
-;; ("clean 8x8" "-schumacher-clean-medium-r-normal--*-80-*-*-c-*-*-1")
-;; ("clean 8x14" "-schumacher-clean-medium-r-normal--*-140-*-*-c-*-*-1")
-;; ("clean 8x10" "-schumacher-clean-medium-r-normal--*-100-*-*-c-*-*-1")
-;; ("clean 8x16" "-schumacher-clean-medium-r-normal--*-160-*-*-c-*-*-1")
-;; ("")
-;; ("sony 8x16" "-sony-fixed-medium-r-normal--16-120-100-100-c-80-*-1")
-;; ("")
-;; ("-- Courier --")
-;; ("Courier 10" "-adobe-courier-medium-r-normal--*-100-*-*-m-*-*-1")
-;; ("Courier 12" "-adobe-courier-medium-r-normal--*-120-*-*-m-*-*-1")
-;; ("Courier 14" "-adobe-courier-medium-r-normal--*-140-*-*-m-*-*-1")
-;; ("Courier 18" "-adobe-courier-medium-r-normal--*-180-*-*-m-*-*-1")
-;; ("Courier 18-b" "-adobe-courier-bold-r-normal--*-180-*-*-m-*-*-1")
-;; )))
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; KNOWN BUGS/TO DO LIST/HELP WANTED/APPLY WITHIN
-;;
-;; * unbalanced, unescaped double quote characters can confuse hilit19.
-;; This will be fixed someday, so don't bug me about it.
-;;
-;; * ALTHOUGH HILIT19 IS FASTER THAN FONT-LOCK-MODE...
-;; For various reasons, the speed of the package could still stand to be
-;; improved. If you care to do a little profiling and make things tighter...
-;;
-;; * hilit-toggle-highlight is flaky when auto-rehighlight is neither t nor nil.
-;; Does anyone actually USE this? I think I might just remove it.
-;;
-;; PROJECTS THAT YOU CAN TAKE OVER BECAUSE I DON'T MUCH CARE ABOUT THEM...
-;;
-;; * Moved hilit-wysiwyg-replace here from my version of man.el, this is not
-;; a bug. The bug is that I don't have a reverse operation yet...just a
-;; stub Wysiwyg-anything really belongs in a package of its own.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; Thanks to the following people for their input:
-;; ebert@enpc.enpc.fr (Rolf EBERT), ada, LaTeX & bibtex highlights
-;; Vivek Khera <khera@cs.duke.edu>, gnus hooks + random advice & patches
-;; brian@athe.WUstl.EDU (Brian Dunford-Shore), prolog highlights
-;; John Ladwig <jladwig@soils.umn.edu>, 1st pass nroff highlights
-;; campo@sunthpi3.difi.unipi.it (Massimo Campostrini), fortran highlights
-;; jayb@laplace.MATH.ColoState.EDU (Jay Bourland), 1st pass dired
-;; Yoshio Turner <yoshio@CS.UCLA.EDU>, modula 2 highlights
-;; Fritz Knabe <knabe@ecrc.de>, advice & patches
-;; Alon Albert <alon@milcse.rtsg.mot.com>, advice & patches
-;; dana@thumper.bellcore.com (Dana A. Chee), working on the multi-frame bug
-;; derway@ndc.com (Don Erway), for breaking it...
-;; moss_r@summer.chem.su.oz.au (Richard Moss), first pass at add-pattern
-;; Olivier Lecarme <ol@aiguemarine.unice.fr>, Pascal & Icon patterns
-;;
-;; With suggestions and minor regex patches from numerous others...
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; hilit19.el,v
-;; Revision 2.19 1993/09/08 18:44:10 stig
-;; installed patch for elusive bug in hilit-rehighlight-region that caused
-;; hilit-unhighlight-region to hang in an infinite loop.
-;;
-;; Revision 2.18 1993/08/27 03:51:00 stig
-;; minor mods to lisp-mode and c/c++ mode patterns
-;;
-;; Revision 2.17 1993/08/25 02:19:17 stig
-;; work-around for bug in next-overlay-change that caused dired and jargon-mode
-;; to hang in an endless loop. Perhaps other modes were doing this too.
-;;
-;; Revision 2.16 1993/08/22 19:46:00 stig
-;; bug fix for next-overlay-change and accompanying change to
-;; hilit-unhighlight-region
-;;
-;; Revision 2.15 1993/08/20 12:16:22 stig
-;; minor change to fortran patterns
-;;
-;; Revision 2.14 1993/08/17 14:12:10 stig
-;; added default face mapping for 'formula' which is needed for new latex
-;; patterns.
-;;
-;; twiddled the calendar-mode patterns a bit.
-;;
-;; Revision 2.13 1993/08/16 04:33:54 stig
-;; hilit-set-mode-patterns was screwing up two part patterns. it doesn't now.
-;;
-;; Revision 2.12 1993/08/16 00:16:41 stig
-;; changed references to default-bold-italic to just bold-italic because the
-;; font for that face is maintained by emacs.
-;;
-;; the pattern matcher now starts its searches from the end of the most
-;; recently highlighted region (which is not necessarily the end of the most
-;; recently matched regex).
-;;
-;; multiple errors in pattern matcher now just give an error instead of lots of
-;; annoying messages and dings.
-;;
-;; no longer use vm-summary-mode-hooks.
-;;
-;; some code moved from hilit-highlight-region to hilit-set-mode-patterns.
-;; This will affect you if you pass your patterns directly to
-;; hilit-highlight-region....use a pseudo-mode instead.
-;;
-;; pattern changes to C/C++, latex, texinfo, fortran, nroff, etc.
-;;
-;; Revision 2.11 1993/08/13 12:12:37 stig
-;; removed some crufty commented-out code
-;;
-;; diverged lisp-mode and emacs-lisp-mode...also added lisp keywords.
-;;
-;; Revision 2.10 1993/08/13 09:47:06 stig
-;; added calendar-mode, icon-mode and pascal-mode patterns
-;;
-;; commented out hilit-toggle-highlight because I want to phase it out entirely
-;;
-;; Revision 2.9 1993/08/13 08:44:22 stig
-;; added optional case-fold argument to hilit-set-mode-patterns, this case-fold
-;; parameter is now stored in hilit-patterns-alist.
-;;
-;; Revision 2.8 1993/08/12 22:05:03 stig
-;; fixed some typos in documentation
-;;
-;; twiddled some of the color defaults for dark backgrounds
-;;
-;; always get 'mono color defaults if (not (x-display-color-p))
-;;
-;; added hilit-rehighlight-buffer-quietly to dired-after-readin-hook
-;;
-;; fixed bug in hilit-string-find that mishandled strings of the form: "\\"
-;;
-;; NEW FUNCTION: hilit-add-mode-pattern... kinda like add-hook for patterns
-;;
-;; fixed minor pattern bugs for latex-mode and emacs-lisp-mode
-;;
-;; Revision 2.7 1993/07/30 02:43:01 stig
-;; added const to the list of modifiers for C/C++ types
-;;
-;; Revision 2.6 1993/07/30 00:30:54 stig
-;; now permit selection of arbitrary subexpressions for highlighting...
-;; fixed keyword patterns for C/C++ using this technique.
-;;
-;; Revision 2.5 1993/07/28 05:02:56 stig
-;; improvements to makefile regular expressions
-;; removed about 130 lines just by compacting the big defconst for
-;; hilit-face-translation-table into a mapcar and defining a separate table
-;; of default faces.
-;;
-;; Revision 2.4 1993/07/27 14:09:05 stig
-;; documented another "known problem" to "head off gripe mail at the pass."
-;;
-;; Revision 2.3 1993/07/27 02:15:49 stig
-;; (hilit-lookup-face-create) incorporated patch which improves its behavior
-;; with more than one frame... Still can't have bold on the same face in two
-;; different fonts sizes at the same time...
-;;
-;; Revision 2.2 1993/07/27 02:02:59 stig
-;; vastly improved the makefile patterns
-;; added hook for mh-show-mode
-;;
-;; Revision 2.1 1993/07/24 17:46:21 stig
-;; Phasing out Info-select-hook... Version 19.18 will use Info-selection-hook.
-;;
-;; Revision 2.0 1993/07/24 13:50:10 stig
-;; better documentation and added the function hilit-submit-feedback.
-;; C-S-l (control shift l) repaints the buffer. Other bindings are optional.
-;; multi-line highlights no longer cause problems when
-;; hilit-auto-rehighlight is 'visible
-;; added hilit-predefined-face-list...
-;; changed name of hilit-mode-alist to hilit-patterns-alist
-;; added hilit-message-quietly to mail-setup-hook
-;; added hilit-parser-alist which can be used to apply different patterns to
-;; different parts of a buffer. This could be integrated in a far more
-;; elegant manner, but it presently serves the purpose of not applying
-;; message header patterns to message bodies in mail-mode and its kin.
-;; hilit-set-mode-patterns now takes a list of modes and an optional parse-fn
-;;
-
-;;;;;; AND THIS CAN BE APPLIED TO VM 5.33L_19
-;;
-;; *** ../site/vm5.33L_19/vm-summary.el Fri Jun 4 22:17:11 1993
-;; --- ./vm-summary.el Tue Jun 22 16:39:30 1993
-;; ***************
-;; *** 152,158 ****
-;; (insert "->")
-;; (delete-char 2)
-;; (forward-char -2)
-;; ! (and w vm-auto-center-summary (vm-auto-center-summary))))
-;; (and old-window (select-window old-window)))))))
-;;
-;; (defun vm-mark-for-display-update (message)
-;; --- 152,159 ----
-;; (insert "->")
-;; (delete-char 2)
-;; (forward-char -2)
-;; ! (and w vm-auto-center-summary (vm-auto-center-summary))
-;; ! (run-hooks 'vm-summary-pointer-hook)))
-;; (and old-window (select-window old-window)))))))
-;;
-;; (defun vm-mark-for-display-update (message)
-;;
-;;;;;;
-
-;;; Code:
-
-;; User Options:
-
-(defvar hilit-quietly nil
- "* If non-nil, this inhibits progress indicators during highlighting")
-
-(defvar hilit-auto-highlight t
- "* T if we should highlight all buffers as we find 'em, nil to disable
- automatic highlighting by the find-file hook.")
-
-(defvar hilit-auto-highlight-maxout 60000 ; hilit19 keeps getting bigger...
- "* auto-highlight is disabled in buffers larger than this")
-
-(defvar hilit-auto-rehighlight t
- "* If this is non-nil, then hilit-redraw and hilit-recenter will also
- rehighlight part or all of the current buffer. T will rehighlight the
- whole buffer, a NUMBER will rehighlight that many lines before and after
- the cursor, and the symbol 'visible' will rehighlight only the visible
- portion of the current buffer. This variable is buffer-local.")
-
-(make-variable-buffer-local 'hilit-auto-rehighlight)
-
-(defvar hilit-auto-rehighlight-fallback '(20000 . 100)
- "* Cons of the form (THRESHOLD . FALLBACK), where FALLBACK is assigned to
- hilit-auto-rehighlight if the size of a newly opened buffer is larger than
- THRESHOLD.")
-
-(defvar hilit-face-check t
- "* T slows down highlighting but permits the user to change fonts without
- losing bold and italic faces... T causes hilit-lookup-face-create to dig
- through the frame parameters for the current window every time it's called.
- If you never change fonts in emacs, set this to NIL.")
-
-;; Variables which must be set before loading hilit19.
-
-(defvar hilit-inhibit-rebinding nil
- "If non-nil, this inhibits replacement of recenter, yank, and yank-pop.")
-
-(defvar hilit-inhibit-hooks nil
- "If non-nil, this inhibits installation of hooks for Info, gnus, & vm.")
-
-(defvar hilit-background-mode 'light
- "'mono inhibits color, 'dark or 'light indicate the background brightness.")
-
-(defvar hilit-mode-enable-list nil
- "If a list of modes to exclusively enable or specifically disable.
-The sense of the list is negated if it begins with the symbol 'not'.
-Set this variable before you load hilit19.
-
-Ex: (perl-mode jargon-mode c-mode) ; just perl, C, and jargon modes
- (not text-mode) ; all modes except text mode")
-
-;; Variables that are not generally modified directly
-
-(defvar hilit-parser-alist nil
- "alist of major-mode values and parsers called by hilit-rehighlight-buffer.
-
-Parsers for a given mode are IGNORED for partial rehighlights...maybe you'd
-like to make this more universal?")
-
-(defvar hilit-patterns-alist nil
- "alist of major-mode values and default highlighting patterns
-
-A highlighting pattern is a list of the form (start end face), where
-start is a regex, end is either a regex or a match number for start, and face
-is the name of an entry in hilit-face-translation-table, the name of a face,
-or nil (which disables the pattern).
-
-Each entry in the alist is of the form:
- (mode . (case-fold pattern [pattern ...]))
-
-See the hilit-lookup-face-create documentation for valid face names.")
-
-(defvar hilit-predefined-face-list (face-list)
- "List of faces with which hilit-lookup-face-create will NOT tamper.
-
-If hilit19 is dumped into emacs at your site, you may have to set this in
-your init file.")
-
-(eval-when-compile (setq byte-optimize t))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Use this to report bugs:
-
-(eval-when-compile (require 'reporter)) ; no compilation gripes
-
-(defun hilit-submit-feedback ()
- "Submit feedback on hilit19 to the author: stig@hackvan.com"
- (interactive)
- (require 'reporter)
- (and (y-or-n-p "Do you really want to submit a report on hilit19? ")
- (reporter-submit-bug-report
- "Jonathan Stigelman <stig@hackvan.com>"
- "hilit19.el (Release 2.19)"
- (and (y-or-n-p "Do you need to include a dump hilit variables? ")
- (append
- '(
- hilit-quietly hilit-inhibit-hooks
- hilit-background-mode hilit-mode-enable-list
- hilit-auto-highlight hilit-auto-highlight-maxout
- hilit-auto-rehighlight hilit-auto-rehighlight-fallback
- hilit-face-check
- )
- (and (y-or-n-p "Have you modified the standard patterns? ")
- (yes-or-no-p "Are your patterns *REALLY* relevant? ")
- '(hilit-parser-alist
- hilit-patterns-alist
- hilit-predefined-face-list
- ))))
- (function
- (lambda ()
- (and (y-or-n-p "Is this a problem with font display? ")
- (insert "\nFrame Configuration:\n====================\n"
- (prin1-to-string (frame-configuration-to-register ?F))
- "\n"
- ))))
- nil
- (concat
- "This is (check all that apply, and delete what's irrelevant):\n"
- " [ ] a _MASSIVE_THANK_YOU_ for writing hilit19.el\n"
- " [ ] An invitation to attend the next Hackers Conference\n"
- " [ ] You're a RIGHTEOUS HACKER, what are your rates?\n"
- " [ ] I've used the force and read the source, but I'M CONFUSED\n"
- " [ ] a PATCH. (output of 'diff -uw old.el new.el' or 'diff -cw')\n"
- " [ ] a SERIOUS AND REPRODUCIBLE BUG that is not an EMACS bug\n"
- " - I *swear* that it's not already mentioned in the KNOWN BUGS\n"
- " - I HAVE CHECKED ftp.hackvan.com:/pub/stig/src/elisp/hilit19.el.gz\n"
- " for a newer release that fixes the problem.\n"
- " >> I HAVE ALSO CHECKED ftp.hackvan.com:/pub/stig/src/elisp/hl319.el.gz\n"
- " This is the alpha version...what will become hilit19 (Beta 3.0).\n"
- "\n"
- "Hey Stig, I *know* you're busy but...\n"))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; These faces are either a valid face name, or nil
-;; if you want to change them, you must do so AFTER hilit19 is loaded
-
-(defconst hilit-default-face-table
- '(
- ;; used for C/C++ and Emacs Lisp and perl
- (comment firebrick-italic moccasin italic)
- (include purple Plum1 bold-italic)
- (define ForestGreen-bold green bold)
- (defun blue-bold cyan-bold bold-italic)
- (decl RoyalBlue cyan bold)
- (type nil yellow nil)
- (keyword RoyalBlue cyan bold-italic)
- (label red-underline orange-underlined underline)
- (string grey40 orange underline)
-
- ;; some further faces for Ada
- (struct black-bold white-bold bold)
- (glob-struct magenta Plum1 default-bold-underline)
- (named-param DarkGoldenrod Goldenrod underline)
-
- ;; and another one for LaTeX
- (crossref DarkGoldenrod Goldenrod underline)
- (formula Goldenrod DarkGoldenrod underline)
-
- ;; compilation buffers
- (active-error default/pink-bold default/DeepPink-bold default-underline)
- (error red-bold yellow bold)
- (warning blue-italic green italic)
-
- ;; Makefiles (some faces borrowed from C/C++ too)
- (rule blue-bold-underline cyan-underline default-bold-underline)
-
- ;; VM, GNUS and Text mode
- (msg-subject blue-bold yellow bold)
- (msg-from purple-bold green bold)
- (msg-header firebrick-bold cyan italic)
- (msg-separator black/tan-bold black/lightblue nil)
- (msg-quote ForestGreen pink italic)
-
- (summary-seen grey40 white nil)
- (summary-killed grey50 white nil)
- (summary-Xed OliveDrab2 green nil)
- (summary-deleted firebrick white italic)
- (summary-unread RoyalBlue yellow bold)
- (summary-new blue-bold yellow-bold bold-italic)
- (summary-current default/skyblue-bold green/dimgrey-bold reverse-default)
-
- (gnus-group-unsubscribed grey50 white nil)
- (gnus-group-empty nil nil nil)
- (gnus-group-full ForestGreen green italic)
- (gnus-group-overflowing firebrick red bold-italic)
-
- ;; dired mode
- (dired-directory blue-bold cyan bold)
- (dired-link firebrick-italic green italic)
- (dired-ignored ForestGreen moccasin nil)
- (dired-deleted red-bold-italic orange bold-italic)
- (dired-marked purple Plum1 nil)
-
- ;; Info-mode, and jargon-mode.el and prep.ai.mit.edu:/pub/gnu/jargon*
- (jargon-entry blue-bold cyan bold)
- (jargon-xref purple-bold Plum1 italic)
- (jargon-keyword firebrick-underline yellow underline)
- )
- "alist of default faces (face . (light-default dark-default mono-default))
-
-There is no way for the user to modify this table such that it will have any
-effect upon the translations used by hilit19. Instead, use the function
-hilit-translate AFTER hilit19 has been loaded.
-
-See also the documentation for hilit-lookup-face-create.")
-
-(defconst hilit-face-translation-table
- (let ((index (or (and (x-display-color-p)
- (cdr (assq hilit-background-mode
- '((light . 1) (dark . 2)))))
- 3)))
- (mapcar (function (lambda (x) (cons (car x) (nth index x))))
- hilit-default-face-table))
- "alist that maps symbolic face-names to real face names")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; To translate one face to another...
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defmacro hilit-translate (&rest args)
- "(hilit-translate FROM TO FROM TO ...): translate each face FROM to the
-value of its TO face. This is like setq for faces.
-
-The function hilit-lookup-face-create will repeatedly translate until no more
-translations for the face exist in the translation table.
-
-See the documentation for hilit-lookup-face-create for names of valid faces."
- (or (zerop (% (length args) 2))
- (error "wrong number of args"))
- (let (cmdl from to)
- (while args
- (setq from (car args) to (nth 1 args) args (nthcdr 2 args)
- cmdl (cons (list 'hilit-associate ''hilit-face-translation-table
- (list 'quote from) to)
- cmdl)))
- (cons 'progn cmdl)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; This function actually translates and then creates the faces...
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun hilit-lookup-face-create (face &optional force)
- "Get a FACE, or create it if it doesn't exist. In order for it to
-properly create the face, the following naming convention must be used:
- [reverse-](fgcolor[/bgcolor])[-bold][-italic][-underline]
-Example: (hilit-lookup-face-create 'comment-face) might create and return 'red
-
-Each color is either the name of an X color (see .../X11/lib/X11/rgb.txt),
-a hexadecimal specification of the form \"hex-[0-9A-Fa-f]+\", or \"default\".
-
-An optional argument, FORCE, will cause the face to be recopied from the
-default...which is probably of use only if you've changed fonts.
-
-See the documentation for hilit-translate and hilit-face-translation-table."
-
-;; translate the face ...
- (let ((trec t) visited)
- (while trec
- (cond ((memq face visited) (error "face translation loop: %S" visited))
- (t (setq visited (cons face visited)
- trec (assq face hilit-face-translation-table))
- (and trec (setq face (cdr trec)))))))
-
- ;; make the face if we need to...
- (let* ((fn (symbol-name face))
- (frame (selected-frame))
- (basefont (cdr (assq 'font (frame-parameters frame))))
- error fgcolor bgcolor)
- (cond
- ((or (null face)
- (memq face hilit-predefined-face-list))
- ;; do nothing if the face is nil or if it's predefined.
- )
- ((or force
- (not (memq face (face-list)))
- (and hilit-face-check
- (not (string= (get face 'basefont) basefont))))
- (copy-face 'default 'scratch-face)
- (if (string-match "^reverse-?" fn)
- (progn (invert-face 'scratch-face)
- (setq fn (substring fn (match-end 0)))))
-
- ;; parse foreground color
- (if (string-match "^\\(hex-\\)?\\([A-Za-z0-9]+\\)" fn)
- (setq fgcolor (concat
- (if (match-beginning 1) "#")
- (substring fn (match-beginning 2) (match-end 2)))
- fn (substring fn (match-end 0)))
- (error "bad face name %S" face))
-
- ;; parse background color
- (if (string-match "^/\\(hex-\\)?\\([A-Za-z0-9]+\\)" fn)
- (setq bgcolor (concat
- (and (match-beginning 1) "#")
- (substring fn (match-beginning 2) (match-end 2)))
- fn (substring fn (match-end 0))))
-
- (and (string= "default" fgcolor) (setq fgcolor nil))
- (and (string= "default" bgcolor) (setq bgcolor nil))
-
- ;; catch errors if we can't allocate the color(s)
- (condition-case nil
- (progn (set-face-foreground 'scratch-face fgcolor)
- (set-face-background 'scratch-face bgcolor)
- (copy-face 'scratch-face face)
- (put face 'basefont basefont))
- (error (message "couldn't allocate color for '%s'"
- (symbol-name face))
- (setq face 'default)
- (setq error t)))
- (or error
- ;; don't bother w/ bold or italic if we didn't get the color
- ;; we wanted, but ignore errors making the face bold or italic
- ;; if the font isn't available, there's nothing to do about it...
- (progn
- (set-face-font face nil frame)
- (set-face-underline-p face (string-match "underline" fn))
- (if (string-match ".*bold" fn)
- ;; make face bold in all frames
- (make-face-bold face nil 'noerr))
- (if (string-match ".*italic" fn)
- ;; make face italic in all frames
- (make-face-italic face nil 'noerr))
- ))
- )))
- face)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Region Highlight/Unhighlight code (Both overlay and text-property versions)
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defsubst hilit-region-set-face (start end face-name &optional prio prop)
- "Highlight region from START to END using FACE and, optionally, PRIO.
-The optional 5th arg, PROP is a property to set instead of 'hilit."
- (let ((overlay (make-overlay start end)))
- (overlay-put overlay 'face face-name)
- (overlay-put overlay (or prop 'hilit) t)
- (and prio (overlay-put overlay 'priority prio))))
-
-(defun hilit-unhighlight-region (start end &optional quietly)
- "Unhighlights the region from START to END, optionally in a QUIET way"
- (interactive "r")
- (or quietly hilit-quietly (message "Unhighlighting"))
- (let ((lstart 0))
- (while (and start (> start lstart) (< start end))
- (mapcar (function (lambda (ovr)
- (and (overlay-get ovr 'hilit) (delete-overlay ovr))))
- (overlays-at start))
- (setq lstart start start (next-overlay-change start))))
- (or quietly hilit-quietly (message "Done unhighlighting")))
-
-;;;; These functions use text properties instead of overlays. Text properties
-;;;; are copied through kill and yank...which might be convenient, but is not
-;;;; terribly efficient as of 19.12, ERGO it's been disabled
-;;
-;;(defsubst hilit-region-set-face (start end face-name &optional prio prop)
-;; "Highlight region from START to END using FACE and, optionally, PRIO.
-;;The optional 5th arg, PROP is a property to set instead of 'hilit."
-;; (put-text-property start end 'face face-name)
-;; )
-;;
-;;(defun hilit-unhighlight-region (start end &optional quietly)
-;; "Unhighlights the region from START to END, optionally in a QUIET way"
-;; (interactive "r")
-;; (let ((buffer-read-only nil)
-;; (bm (buffer-modified-p)))
-;; (remove-text-properties start end '(face))
-;; (set-buffer-modified-p bm)))
-;;;;
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Pattern Application code and user functions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun hilit-highlight-region (start end &optional patterns quietly)
- "Highlights the area of the buffer between START and END (the region when
-interactive). Without the optional PATTERNS argument, the pattern for
-major-mode is used. If PATTERNS is a symbol, then the patterns associated
-with that symbol are used. QUIETLY suppresses progress messages if
-non-nil."
- (interactive "r")
- (cond ((null patterns)
- (setq patterns (cdr (assq major-mode hilit-patterns-alist))))
- ((symbolp patterns)
- (setq patterns (cdr (assq patterns hilit-patterns-alist)))))
- ;; txt prop: (setq patterns (reverse patterns))
- (let ((case-fold-search (car patterns))
- (prio (1- (length patterns)))
- ;; txt prop: (buffer-read-only nil)
- ;; txt prop: (bm (buffer-modified-p))
- p pstart pend face mstart (puke-count 0))
- ;; txt prop: (unwind-protect
- (setq patterns (cdr patterns)) ; remove case-fold from head of pattern
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (while patterns
- (setq p (car patterns))
- (setq pstart (car p)
- pend (nth 1 p)
- face (hilit-lookup-face-create (nth 2 p)))
- (if (not face) ; skipped if nil
- nil
- (or quietly hilit-quietly
- (message "highlighting %d: %s%s" prio pstart
- (if (stringp pend) (concat " ... " pend) "")))
- (goto-char (point-min))
- (condition-case msg
- (cond
- ((symbolp pstart)
- ;; inner loop -- special function to find pattern
- (let (region)
- (while (setq region (funcall pstart pend))
- (hilit-region-set-face (car region) (cdr region)
- face prio))))
- ((stringp pend)
- ;; inner loop -- regex-start ... regex-end
- (while (re-search-forward pstart nil t nil)
- (goto-char (setq mstart (match-beginning 0)))
- (if (re-search-forward pend nil t nil)
- (hilit-region-set-face mstart (match-end 0)
- face prio)
- (forward-char 1))))
- ((numberp pend)
- ;; inner loop -- just one regex to match whole pattern
- (while (re-search-forward pstart nil t nil)
- (goto-char (match-end pend))
- (hilit-region-set-face (match-beginning pend)
- (match-end pend) face prio)))
- (t (error "malformed pattern")))
- (error (if (> (setq puke-count (1+ puke-count)) 1)
- (error msg)
- (message "Error: '%s'" msg)
- (ding) (sit-for 4)))))
- (setq prio (1- prio)
- patterns (cdr patterns)))
- ))
- (or quietly hilit-quietly (message "")) ; "Done highlighting"
- ;; txt prop: (set-buffer-modified-p bm)) ; unwind protection
- ))
-
-(defun hilit-rehighlight-region (start end &optional quietly)
- "Re-highlights the region, optionally in a QUIET way"
- (interactive "r")
- (save-restriction
- (widen)
- (setq start (apply 'min start (mapcar 'overlay-start (overlays-at start)))
- end (apply 'max end (mapcar 'overlay-end (overlays-at end))))
- (hilit-unhighlight-region start end quietly)
- (hilit-highlight-region start end nil quietly)))
-
-(defun hilit-rehighlight-buffer (&optional quietly)
- "Re-highlights the buffer, optionally in a QUIET way"
- (interactive "")
- (let ((parse-fn (cdr (assq major-mode hilit-parser-alist))))
- (if parse-fn
- (funcall parse-fn quietly)
- (hilit-rehighlight-region (point-min) (point-max) quietly)))
- nil)
-
-(defun hilit-rehighlight-buffer-quietly ()
- (hilit-rehighlight-buffer t))
-
-(defun hilit-rehighlight-message (quietly)
- "Highlight a buffer containing a news article or mail message."
- (save-excursion
- (goto-char (point-min))
- (re-search-forward "^$" nil 'noerr)
- (hilit-unhighlight-region (point-min) (point-max) quietly)
- (hilit-highlight-region (point-min) (point) 'msg-header quietly)
- (hilit-highlight-region (point) (point-max) 'msg-body quietly)))
-
-(defalias 'hilit-highlight-buffer 'hilit-rehighlight-buffer)
-
-;; Well, I want to remove this function...there's one sure way to find out if
-;; anyone uses it or not...and that's to comment it out.
-;;
-;; (defun hilit-toggle-highlight (arg)
-;; "Locally toggle highlighting. With arg, forces highlighting off."
-;; (interactive "P")
-;; ;; FIXME -- this loses numeric information in hilit-auto-rehighlight
-;; (setq hilit-auto-rehighlight
-;; (and (not arg) (not hilit-auto-rehighlight)))
-;; (if hilit-auto-rehighlight
-;; (hilit-rehighlight-buffer)
-;; (hilit-unhighlight-region (point-min) (point-max)))
-;; (message "Rehighlighting is set to %s" hilit-auto-rehighlight))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; HOOKS
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun hilit-find-file-hook ()
- "Find-file hook for hilit package. See the variable hilit-auto-highlight."
- (cond ((and hilit-auto-highlight
- (assq major-mode hilit-patterns-alist))
- (if (> buffer-saved-size (car hilit-auto-rehighlight-fallback))
- (setq hilit-auto-rehighlight
- (cdr hilit-auto-rehighlight-fallback)))
- (if (> buffer-saved-size hilit-auto-highlight-maxout)
- nil
- (let ((bm (buffer-modified-p)))
- (hilit-rehighlight-buffer)
- (set-buffer-modified-p bm))))))
-
-(defun hilit-repaint-command (arg)
- "Rehighlights according to the value of hilit-auto-rehighlight, or the
-prefix argument if that is specified.
-\t\\[hilit-repaint-command]\t\trepaint according to hilit-auto-rehighlight
-\t^U \\[hilit-repaint-command]\trepaint entire buffer
-\t^U - \\[hilit-repaint-command]\trepaint visible portion of buffer
-\t^U n \\[hilit-repaint-command]\trepaint n lines to either side of point"
- (interactive "P")
- (let (st en quietly)
- (or arg (setq arg hilit-auto-rehighlight))
- (cond ((or (eq arg 'visible) (eq arg '-))
- (setq st (window-start) en (window-end) quietly t))
- ((numberp arg)
- (setq st (save-excursion (forward-line (- arg)) (point))
- en (save-excursion (forward-line arg) (point))))
- (arg
- (hilit-rehighlight-buffer)))
- (if st
- (hilit-rehighlight-region st en quietly))))
-
-(defun hilit-recenter (arg)
- "Recenter, then rehighlight according to hilit-auto-rehighlight. If called
-with an unspecified prefix argument (^U but no number), then a rehighlight of
-the entire buffer is forced."
- (interactive "P")
- (recenter arg)
- ;; force display update
- (sit-for 0)
- (hilit-repaint-command (consp arg)))
-
-(defun hilit-yank (arg)
- "Yank with rehighlighting"
- (interactive "*P")
- (let ((transient-mark-mode nil))
- (yank arg)
- (and hilit-auto-rehighlight
- (hilit-rehighlight-region (region-beginning) (region-end) t))
- (setq this-command 'yank)))
-
-(defun hilit-yank-pop (arg)
- "Yank-pop with rehighlighting"
- (interactive "*p")
- (let ((transient-mark-mode nil))
- (yank-pop arg)
- (and hilit-auto-rehighlight
- (hilit-rehighlight-region (region-beginning) (region-end) t))
- (setq this-command 'yank)))
-
-;;; this line highlighting stuff is untested. play with it only if you feel
-;;; adventurous...don't ask me to fix it...though you're welcome to. -- Stig
-;;
-;; (defun hilit-rehighlight-line-quietly (&rest args)
-;; "Quietly rehighlight just this line.
-;; Useful as an after change hook in VM/gnus summary buffers and dired buffers.
-;; If only there were an after-change-function, that is..."
-;; (save-excursion
-;; (push-mark nil t)
-;; (hilit-rehighlight-yank-region)
-;; (and orig-achange-function (apply orig-achange-function args))))
-;;
-;; (defun hilit-install-line-hooks ()
-;; (make-variable-buffer-local 'after-change-function)
-;; (make-local-variable 'orig-achange-function)
-;; (setq orig-achange-function after-change-function)
-;; (setq after-change-function 'hilit-rehighlight-line-quietly))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Wysiwyg Stuff... take it away and build a whole package around it!
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; ; For the Jargon-impaired, WYSIWYG === What You See Is What You Get
-;; ; Sure, it sucks to type. Oh, well.
-;; (defun hilit-wysiwyg-replace ()
-;; "Replace overstruck text with normal text that's been overlaid with the
-;; appropriate text attribute. Suitable for a find-file hook."
-;; (save-excursion
-;; (goto-char (point-min))
-;; (let ((wysb (hilit-lookup-face-create 'wysiwyg-bold))
-;; (wysu (hilit-lookup-face-create 'wysiwyg-underline))
-;; (bmod (buffer-modified-p)))
-;; (while (re-search-forward "\\(.\b.\\)+" nil t)
-;; (let ((st (match-beginning 0)) (en (match-end 0)))
-;; (goto-char st)
-;; (if (looking-at "_")
-;; (hilit-region-set-face st en wysu 100 'wysiwyg)
-;; (hilit-region-set-face st en wysb 100 'wysiwyg))
-;; (while (and (< (point) en) (looking-at ".\b"))
-;; (replace-match "") (forward-char))
-;; ))
-;; (set-buffer-modified-p bmod))))
-;;
-;; ; is this more appropriate as a write-file-hook or a write-contents-hook?
-;; (defun hilit-wysiwyg-write-repair ()
-;; "Replace wysiwyg overlays with overstrike text."
-;; (message "*sigh* hilit-wysiwyg-write-repair not implemented yet")
-;;
-;; For efficiency, this hook should copy the current buffer to a scratch
-;; buffer and do its overstriking there. Overlays are not copied, so it'll
-;; be necessary to hop back and forth. This is OK since you're not fiddling
-;; with--making or deleting--any overlays. THEN write the new buffer,
-;; delete it, and RETURN T. << important
-;;
-;; Just so you know...there is already an emacs function called
-;; underline-region that does underlining. I think that the thing to do is
-;; extend that to do overstriking as well.
-;;
-;; (while (< start end)
-;; (mapcar (function (lambda (ovr)
-;; (and (overlay-get ovr 'hilit) (delete-overlay ovr))))
-;; (overlays-at start))
-;; (setq start (next-overlay-change start)))
-;; nil)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Initialization.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(and (not hilit-inhibit-rebinding)
- window-system
- (progn
- (substitute-key-definition 'yank 'hilit-yank
- (current-global-map))
- (substitute-key-definition 'yank-pop 'hilit-yank-pop
- (current-global-map))
- (substitute-key-definition 'recenter 'hilit-recenter
- (current-global-map))))
-
-(global-set-key [?\C-\S-l] 'hilit-repaint-command)
-
-(and window-system
- (add-hook 'find-file-hooks 'hilit-find-file-hook t))
-
-(eval-when-compile (require 'gnus)) ; no compilation gripes
-
-(and (not hilit-inhibit-hooks)
- window-system
- (condition-case c
- (progn
-
- ;; BUFFER highlights...
- (mapcar (function
- (lambda (hook)
- (add-hook hook 'hilit-rehighlight-buffer-quietly)))
- '(
- Info-selection-hook
-
-;; runs too early vm-summary-mode-hooks
- vm-summary-pointer-hook
- vm-preview-message-hook
- vm-show-message-hook
-
- rmail-show-message-hook
- mail-setup-hook
- mh-show-mode-hook
-
- dired-after-readin-hook
- ))
- )
- (error (message "Error loading highlight hooks: %s" c)
- (ding) (sit-for 1))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Default patterns for various modes.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;; do I need this? I changed the defconst to a defvar because defconst is
-;;; inappropriate, but I don't know why I wanted hilit-patterns-alist to be
-;;; reset on every reload...
-
-(setq hilit-patterns-alist nil)
-
-(defun hilit-associate (alist key val)
- "creates, or destructively replaces, the pair (key . val) in alist"
- (let ((oldentry (assq key (eval alist))))
- (if oldentry
- (setcdr oldentry val)
- (set alist (cons (cons key val) (eval alist))))))
-
-(defun hilit-set-mode-patterns (modelist patterns
- &optional parse-fn case-fold)
- "Sets the default highlighting patterns for MODE to PATTERNS.
-See the variable hilit-mode-enable-list.
-
-Takes optional arguments PARSE-FN and CASE-FOLD."
- ;; change pattern
- (mapcar (function (lambda (p)
- (and (stringp (car p))
- (null (nth 1 p))
- (setcar (cdr p) 0))))
- patterns)
- (setq patterns (cons case-fold patterns))
-
- (or (consp modelist) (setq modelist (list modelist)))
- (let (ok (flip (eq (car hilit-mode-enable-list) 'not)))
- (mapcar (function
- (lambda (m)
- (setq ok (or (null hilit-mode-enable-list)
- (memq m hilit-mode-enable-list)))
- (and flip (setq ok (not ok)))
- (and ok
- (progn
- (and parse-fn
- (hilit-associate 'hilit-parser-alist m parse-fn))
- (hilit-associate 'hilit-patterns-alist m patterns)))))
- modelist)))
-
-(defun hilit-add-pattern (pstart pend face &optional mode first)
- "Highlight pstart with face for the current major-mode.
-Optionally, place the new pattern first in the pattern list"
- (interactive "sPattern start regex: \nsPattern end regex (default none): \nxFace: ")
-
- (and (equal pstart "") (error "Must specify starting regex"))
- (cond ((equal pend "") (setq pend 0))
- ((string-match "^[0-9]+$" pend) (setq pend (string-to-int pend))))
- (or mode (setq mode major-mode))
- (let ((old-patterns (cdr (assq mode hilit-patterns-alist)))
- (new-pat (list pstart pend face)))
- (cond ((not old-patterns)
- (hilit-set-mode-patterns mode (list new-pat)))
- (first
- (setcdr old-patterns (cons new-pat (cdr old-patterns))))
- (t
- (nconc old-patterns (list new-pat)))))
- (and (interactive-p) (hilit-rehighlight-buffer)))
-
-(defun hilit-string-find (qchar)
- "looks for a string and returns (start . end) or NIL. The argument QCHAR
-is the character that would precede a character constant double quote.
-Finds strings delimited by double quotes. The first double quote may not be
-preceded by QCHAR and the closing double quote may not be preceded by an odd
-number of backslashes."
- (let (st en)
- (while (and (search-forward "\"" nil t)
- (eq qchar (char-after (1- (setq st (match-beginning 0)))))))
- (while (and (search-forward "\"" nil t)
- (save-excursion
- (setq en (point))
- (forward-char -1)
- (skip-chars-backward "\\\\")
- (forward-char 1)
- (not (zerop (% (- en (point)) 2))))))
- (and en (cons st en))))
-
-;; return types on same line...
-;; ("^[a-zA-z].*\\(\\w\\|[$_]\\)+\\s *\\(\\(\\w\\|[$_]\\)+\\s *((\\|(\\)[^)]*)+" nil defun)
-
-;; On another note, a working pattern for grabbing function definitions for C is
-;;
-;; ("^[a-zA-Z_]+.*[;{]$" nil ForestGreen) ; global defns ( start at col 1 )
-;; ("^[a-zA-Z_]+.*(" ")" defun)
-;; ; defuns assumed to start at col 1, not with # or {
-;;
-;; this will make external declarations/definitions green, and function
-;; definitions the defun face. Hmmm - seems to work for me anyway.
-
-(let ((comments '(("/\\*" "\\*/" comment)))
- (c++-comments '(("//.*$" nil comment)
- ("^/.*$" nil comment)))
- (strings '((hilit-string-find ?' string)))
- (preprocessor '(("^#[ \t]*\\(undef\\|define\\).*$" "[^\\]$" define)
- ("^#.*$" nil include))))
-
- (hilit-set-mode-patterns
- '(c-mode c++-c-mode elec-c-mode)
- (append
- comments strings preprocessor
- '(
- ;; function decls are expected to have types on the previous line
- ("^\\(\\w\\|[$_]\\)+\\s *\\(\\(\\w\\|[$_]\\)+\\s *((\\|(\\)[^)]*)+" nil defun)
- ("^\\(typedef\\|struct\\|union\\|enum\\).*$" nil decl)
- ;; datatype -- black magic regular expression
- ("[ \n\t({]\\(\\(const\\|register\\|volatile\\|unsigned\\|extern\\|static\\)\\s +\\)*\\(\\(\\w\\|[$_]\\)+_t\\|float\\|double\\|void\\|char\\|short\\|int\\|long\\|FILE\\|\\(\\(struct\\|union\\|enum\\)\\([ \t]+\\(\\w\\|[$_]\\)*\\)\\)\\)\\(\\s +\\*+)?\\|[ \n\t;()]\\)" nil type)
- ;; key words
- ("[^_]\\<\\(return\\|goto\\|if\\|else\\|case\\|default\\|switch\\|break\\|continue\\|while\\|do\\|for\\)\\>[^_]" 1 keyword)
- )))
-
- (hilit-set-mode-patterns
- 'c++-mode
- (append
- comments c++-comments strings preprocessor
- '(
- ;; function decls are expected to have types on the previous line
- ("^\\(\\(\\w\\|[$_]\\)+::\\)?\\(\\w\\|[$_]\\)+\\s *\\(\\(\\w\\|[$_]\\)+\\s *((\\|(\\)[^)]*)+" nil defun)
- ("^\\(\\(\\w\\|[$_]\\)+[ \t]*::[ \t]*\\)?\\(\\(\\w\\|[$_]\\)+\\|operator.*\\)\\s *\\(\\(\\w\\|[$_]\\)+\\s *((\\|(\\)[^)]*)+" nil defun)
- ("^\\(template\\|typedef\\|struct\\|union\\|class\\|enum\\|public\\|private\\|protected\\).*$" nil decl)
- ;; datatype -- black magic regular expression
- ("[ \n\t({]\\(\\(const\\|register\\|volatile\\|unsigned\\|extern\\|static\\)\\s +\\)*\\(\\(\\w\\|[$_]\\)+_t\\|float\\|double\\|void\\|char\\|short\\|int\\|long\\|FILE\\|\\(\\(struct\\|union\\|enum\\|class\\)\\([ \t]+\\(\\w\\|[$_]\\)*\\)\\)\\)\\(\\s +\\*+)?\\|[ \n\t;()]\\)" nil type)
- ;; key words
- ("[^_]\\<\\(return\\|goto\\|if\\|else\\|case\\|default\\|switch\\|break\\|continue\\|while\\|do\\|for\\|public\\|protected\\|private\\|delete\\|new\\)\\>[^_]"
- 1 keyword))))
-
- (hilit-set-mode-patterns
- '(objc-mode objective-C-mode)
- (append
- comments c++-comments strings preprocessor
- '(
- ;; function decls are expected to have types on the previous line
- ("^\\(\\(\\w\\|[$_]\\)+::\\)?\\(\\w\\|[$_]\\)+\\s *\\(\\(\\w\\|[$_]\\)+\\s *((\\|(\\)[^)]*)+" nil defun)
- ("^\\(\\(\\w\\|[$_]\\)+[ \t]*::[ \t]*\\)?\\(\\(\\w\\|[$_]\\)+\\|operator.*\\)\\s *\\(\\(\\w\\|[$_]\\)+\\s *((\\|(\\)[^)]*)+" nil defun)
-
- ("^\\(template\\|typedef\\|struct\\|union\\|class\\|enum\\|public\\|private\\|protected\\).*$" nil decl)
- ;; datatype -- black magic regular expression
- ("[ \n\t({]\\(\\(const\\|register\\|volatile\\|unsigned\\|extern\\|static\\)\\s +\\)*\\(\\(\\w\\|[$_]\\)+_t\\|float\\|double\\|void\\|char\\|short\\|int\\|long\\|FILE\\|\\(\\(struct\\|union\\|enum\\|class\\)\\([ \t]+\\(\\w\\|[$_]\\)*\\)\\)\\)\\(\\s +\\*+)?\\|[ \n\t;()]\\)" nil type)
- ;; key words
- ("[^_]\\<\\(return\\|goto\\|if\\|else\\|case\\|default\\|switch\\|break\\|continue\\|while\\|do\\|for\\|public\\|protected\\|private\\|interface\\|implementation\\|end\\|super\\|self\\)\\>[^_]"
- 1 keyword))))
- )
-
-(hilit-set-mode-patterns
- 'perl-mode
- '(("\\s #.*$" nil comment)
- ("^#.*$" nil comment)
- ("\"[^\\\"]*\\(\\\\\\(.\\|\n\\)[^\\\"]*\\)*\"" nil string)
- ("^\\(__....?__\\|\\s *\\sw+:\\)" nil label)
- ("^require.*$" nil include)
- ("^package.*$" nil decl)
- ("^\\s *sub\\s +\\(\\w\\|[_']\\)+" nil defun)
- ("\\b\\(do\\|if\\|unless\\|while\\|until\\|else\\|elsif\\|for\\|foreach\\|continue\\|next\\|redo\\|last\\|goto\\|return\\|die\\|exit\\)\\b" nil keyword)))
-
-(hilit-set-mode-patterns
- 'ada-mode
- '(;; comments
- ("--.*$" nil comment)
- ;; main structure
- ("[ \t\n]procedure[ \t]" "\\([ \t]\\(is\\|renames\\)\\|);\\)" glob-struct)
- ("[ \t\n]task[ \t]" "[ \t]is" glob-struct)
- ("[ \t\n]function[ \t]" "return[ \t]+[A-Za-z_0-9]+[ \t]*\\(is\\|;\\|renames\\)" glob-struct)
- ("[ \t\n]package[ \t]" "[ \t]\\(is\\|renames\\)" glob-struct)
- ;; if there is nothing before "private", it is part of the structure
- ("^[ \t]*private[ \t\n]" nil glob-struct)
- ;; if there is no indentation before the "end", then it is most
- ;; probably the end of the package
- ("^end.*$" ";" glob-struct)
- ;; program structure -- "null", "delay" and "terminate" omitted
- ("[ \n\t]\\(in\\|out\\|select\\|if\\|else\\|case\\|when\\|and\\|or\\|not\\|accept\\|loop\\|do\\|then\\|elsif\\|else\\|for\\|while\\|exit\\)[ \n\t;]" nil struct)
- ;; block structure
- ("[ \n\t]\\(begin\\|end\\|declare\\|exception\\|generic\\|raise\\|return\\|package\\|body\\)[ \n\t;]" nil struct)
- ;; type declaration
- ("^[ \t]*\\(type\\|subtype\\).*$" ";" decl)
- ("[ \t]+is record.*$" "end record;" decl)
- ;; "pragma", "with", and "use" are close to C cpp directives
- ("^[ \t]*\\(with\\|pragma\\|use\\)" ";" include)
- ;; nice for named parameters, but not so beautiful in case statements
- ("[A-Za-z_0-9.]+[ \t]*=>" nil named-param)
- ;; string constants probably not everybody likes this one
- ("\"" ".*\"" string)))
-
-(hilit-set-mode-patterns
- 'fortran-mode
- '(("^[*Cc].*$" nil comment)
- ("'[^'\n]*'" nil string)
- ("\\(^[ \t]*[0-9]+\\|[ \t]continue[ \t\n]\\|format\\)" nil define)
- ("[ \t]\\(do\\|do[ \t]*[0-9]+\\|go[ \t]*to[ \t]*[0-9]+\\|end[ \t]*do\\|if\\|else[ \t]*if\\|then\\|else\\|end[ \t]*if\\)[ \t\n(]" nil define)
- ("[ \t]\\(call\\|program\\|subroutine\\|function\\|stop\\|return\\|end\\|include\\)[ \t\n]" nil include)
- ("[ \t]\\(parameter[\t\n ]*([^)]*)\\|data\\|save\\|common[ \t\n]*/[^/]*/\\)"
- nil decl)
- ("^ ." nil type)
- ("implicit[ \t]*none" nil decl)
- ("\\([ \t]\\|implicit[ \t]*\\)\\(dimension\\|integer\\|real\\|double[ \t]*precision\\|character\\|logical\\|complex\\|double[ \t]*complex\\)\\([*][0-9]*\\|[ \t\n]\\)" nil keyword)
- )
- nil 'case-insensitive)
-
-(hilit-set-mode-patterns
- '(m2-mode modula-2-mode)
- '(("(\\*" "\\*)" comment)
- (hilit-string-find ?\\ string)
- ("^[ \t]*PROCEDURE[ \t]+\\w+[^ \t(;]*" nil defun)
- ("\\<\\(RECORD\\|ARRAY\\|OF\\|POINTER\\|TO\\|BEGIN\\|END\\|FOR\\|IF\\|THEN\\|ELSE\\|ELSIF\\|CASE\\|WHILE\\|DO\\|MODULE\\|FROM\\|RETURN\\|IMPORT\\|EXPORT\\|VAR\\|LOOP\\|UNTIL\\|\\DEFINITION\\|IMPLEMENTATION\\|AND\\|OR\\|NOT\\|CONST\\|TYPE\\|QUALIFIED\\)\\>" nil keyword)
- )
- nil 'case-insensitive)
-
-(hilit-set-mode-patterns 'prolog-mode
- '(("/\\*" "\\*/" comment)
- ("%.*$" nil comment)
- (":-" nil defun)
- ("!" nil label)
- ("\"[^\\\"]*\\(\\\\\\(.\\|\n\\)[^\\\"]*\\)*\"" nil string)
- ("\\b\\(is\\|mod\\)\\b" nil keyword)
- ("\\(->\\|-->\\|;\\|==\\|\\\\==\\|=<\\|>=\\|<\\|>\\|=\\|\\\\=\\|=:=\\|=\\\.\\\.\\|\\\\\\\+\\)" nil decl)
- ("\\(\\\[\\||\\|\\\]\\)" nil include)))
-
-(hilit-set-mode-patterns
- '(
- LaTeX-mode japanese-LaTeX-mode SliTeX-mode
- japanese-SliTeX-mode FoilTeX-mode latex-mode
- )
- '(
- ;; comments
- ("[^\\]%.*$" nil comment)
-
- ;; the following two match \foo[xx]{xx} or \foo*{xx} or \foo{xx}
- ("\\\\\\(sub\\)*\\(paragraph\\|section\\)\\(\*\\|\\[.*\\]\\)?{" "}"
- keyword)
- ("\\\\\\(chapter\\|part\\)\\(\*\\|\\[.*\\]\\)?{" "}" keyword)
- ("\\\\footnote\\(mark\\|text\\)?{" "}" keyword)
- ("\\\\[a-z]+box" nil keyword)
- ("\\\\\\(v\\|h\\)space\\(\*\\)?{" "}" keyword)
-
- ;; (re-)define new commands/environments/counters
- ("\\\\\\(re\\)?new\\(environment\\|command\\){" "}" defun)
- ("\\\\new\\(length\\|theorem\\|counter\\){" "}" defun)
-
- ;; various declarations/definitions
- ("\\\\\\(setlength\\|settowidth\\|addtolength\\|setcounter\\|addtocounter\\)" nil define)
- ("\\\\\\(title\\|author\\|date\\|thanks\\){" "}" define)
-
- ("\\\\documentstyle\\(\\[.*\\]\\)?{" "}" decl)
- ("\\\\\\(begin\\|end\\|nofiles\\|includeonly\\){" "}" decl)
- ("\\\\\\(raggedright\\|makeindex\\|makeglossary\\|maketitle\\)\\b" nil
- decl)
- ("\\\\\\(pagestyle\\|thispagestyle\\|pagenumbering\\){" "}" decl)
- ("\\\\\\(normalsize\\|small\\|footnotesize\\|scriptsize\\|tiny\\|large\\|Large\\|LARGE\\|huge\\|Huge\\)\\b" nil decl)
- ("\\\\\\(appendix\\|tableofcontents\\|listoffigures\\|listoftables\\)\\b"
- nil decl)
- ("\\\\\\(bf\\|em\\|it\\|rm\\|sf\\|sl\\|ss\\|tt\\)\\b" nil decl)
-
- ;; label-like things
- ("\\\\item\\(\\[[^]]*\\]\\)?" nil label)
- ("\\\\caption\\(\\[[^]]*\\]\\)?{" "}" label)
-
- ;; formulas
- ("[^\\]\\\\(" "\\\\)" formula) ; \( \)
- ("[^\\]\\\\\\[" "\\\\\\]" formula) ; \[ \]
- ("[^\\$]\\(\\$\\(\\$[^$]*\\$\\|[^$]*\\)\\$\\)" 1 formula) ; '$...$' or '$$...$$'
-
- ;; things that bring in external files
- ("\\\\\\(include\\|input\\|bibliography\\){" "}" include)
-
- ;; "wysiwyg" emphasis -- these don't work with nested expressions
- ;; ("{\\\\\\(em\\|it\\|sl\\)" "}" italic)
- ;; ("{\\\\bf" "}" bold)
-
- ("``" "''" string)
-
- ;; things that do some sort of cross-reference
- ("\\\\\\(\\(no\\)?cite\\|\\(page\\)?ref\\|label\\|index\\|glossary\\){" "}" crossref)
- ))
-
-(hilit-set-mode-patterns
- 'bibtex-mode
- '(;;(";.*$" nil comment)
- ("%.*$" nil comment)
- ("@[a-zA-Z]+" nil keyword)
- ("{[ \t]*[-a-z:_A-Z0-9]+," nil label) ; is wrong sometimes
- ("^[ \t]*[a-zA-Z]+[ \t]*=" nil define)))
-
-(hilit-set-mode-patterns
- 'compilation-mode
- '(
- ("^[-_.\"A-Za-z0-9]+\\(:\\|, line \\)[0-9]+: warning:.*$" nil warning)
- ("^[-_.\"A-Za-z0-9]+\\(:\\|, line \\)[0-9]+:.*$" nil error)
- ))
-
-(hilit-set-mode-patterns
- 'makefile-mode
- '(("^#.*$" nil comment)
- ("[^$]#.*$" nil comment)
- ;; rules
- ("^[^ \t\n]*%[^ \t\n]*[ \t]*::?[ \t]*[^ \t\n]*[ \t]*\\(#.*\\)?$" nil rule)
- ("^[.][A-Za-z][A-Za-z]?\..*$" nil rule)
- ;; variable definition
- ("^[_A-Za-z0-9]+[ \t]*\+?=" nil define)
- ("\\( \\|:=\\)[_A-Za-z0-9]+[ \t]*\\+=" nil define)
- ;; variable references
- ("\\$\\([^ \t\n{(]\\|[{(]@?[_A-Za-z0-9:.,%/=]+[)}]\\)" nil keyword)
- ("^[A-Za-z0-9.,/_-]+[ \t]*:.*$" nil defun)
- ("^include " nil include)))
-
-(let* ((header-patterns '(("^Subject:.*$" nil msg-subject)
- ("^From:.*$" nil msg-from)
- ("^--text follows this line--$" nil msg-separator)
- ("^[A-Za-z][A-Za-z0-9-]+:" nil msg-header)))
- (body-patterns '(("^\\(In article\\|[ \t]*\\w*[]<>}|]\\).*$"
- nil msg-quote)))
- (message-patterns (append header-patterns body-patterns)))
- (hilit-set-mode-patterns 'msg-header header-patterns)
- (hilit-set-mode-patterns 'msg-body body-patterns)
- (hilit-set-mode-patterns '(vm-mode text-mode mail-mode rmail-mode
- gnus-article-mode news-reply-mode mh-show-mode)
- message-patterns
- 'hilit-rehighlight-message))
-
-(hilit-set-mode-patterns
- 'gnus-group-mode
- '(("^ U.*$" nil gnus-group-unsubscribed)
- ("^\\*? +[01]?[0-9]:.*$" nil gnus-group-empty)
- ("^ +[2-9][0-9]:.*$" nil gnus-group-full)
- ("^ +[0-9][0-9][0-9]+:.*$" nil gnus-group-overflowing)))
-
-(hilit-set-mode-patterns
- 'vm-summary-mode
- '(("^ .*$" nil summary-seen)
- ("^->.*$" nil summary-current)
- ("^ D.*$" nil summary-deleted)
- ("^ U.*$" nil summary-unread)
- ("^ N.*$" nil summary-new)))
-
-
-;;; this will match only comments w/ an even (zero is even) number of quotes...
-;;; which is still inadequate because it matches comments in multi-line strings
-;;; how anal do you want to get about never highlighting comments in strings?
-;;; I could twiddle with this forever and still it wouldn't be perfect.
-;;; (";\\([^\"\n]*\"[^\"\n]*\"\\)*[^\"\n]*$" nil comment)
-
-(hilit-set-mode-patterns
- '(emacs-lisp-mode lisp-interaction-mode)
- '(
- (";.*" nil comment)
-
-;;; This almost works...but I think I'll stick with the parser function
-;;;("[^?]\\(\"\\(\"\\||\\([^\"]+\\|[\\]\\([\\][\\]\\)*\"\\)*\"\\)\\)" 1 string)
- (hilit-string-find ?\\ string)
-
- ("^\\s *(def\\(un\\|macro\\|advice\\|alias\\|subst\\)[ \t\n]"
- "\\()\\|nil\\)" defun)
- ("^\\s *(defvar\\s +\\S +" nil decl)
- ("^\\s *(defconst\\s +\\S +" nil define)
- ("^\\s *(\\(provide\\|require\\|\\(auto\\)?load\\).*$" nil include)
- ("\\s *\\&\\(rest\\|optional\\)\\s *" nil keyword)
- ("(\\(let\\*?\\|cond\\|if\\|or\\|and\\|map\\(car\\|concat\\)\\|prog[n1*]?\\|while\\|lambda\\|function\\|set\\([qf]\\|car\\|cdr\\)?\\|nconc\\|eval-when-compile\\|condition-case\\|unwind-protect\\|catch\\|throw\\|error\\)[ \t\n]" 1 keyword)
- ))
-
-(hilit-set-mode-patterns
- '(lisp-mode ilisp-mode)
- '(
- (";.*" nil comment)
- ("#|" "|#" comment)
-;;; This almost works...but I think I'll stick with the parser function
-;;;("[^?]\\(\"\\(\"\\||\\([^\"]+\\|[\\]\\([\\][\\]\\)*\"\\)*\"\\)\\)" 1 string)
- (hilit-string-find ?\\ string)
-
- ;; this is waaaaaaaay too slow
- ;; ("^\\s *(def\\(un\\|macro\\|advice\\|alias\\|method\\|subst\\)\\s \\S +[ \t\n]+\\(nil\\|(\\(([^()]*)\\|[^()]+\\)*)\\)" nil defun)
- ("^\\s *(def\\(un\\|macro\\|advice\\|subst\\|method\\)\\s " "\\()\\|nil\\)" defun)
-
- ("^\\s *(\\(def\\(var\\|type\\|parameter\\)\\|declare\\)\\s +\\S +" nil decl)
- ("^\\s *(def\\(const\\(ant\\)?\\|class\\|struct\\)\\s \\S +[ \t\n]+" nil define)
- ("^\\s *(\\(provide\\|require\\|\\(auto\\)?load\\).*$" nil include)
- ("[ \t]\\&\\(key\\|rest\\|optional\\|aux\\)\\s *" nil keyword)
- ("(\\(let\\*?\\|locally\\|cond\\|if\\*?\\|or\\|and\\|map\\(car\\|c[ao]n\\)?\\|prog[nv1*]?\\|while\\|when\\|unless\\|do\\(\\*\\|list\\|times\\)\\|list\\|lambda\\|function\\|values\\|set\\([qf]\\|car\\|cdr\\)?\\|rplac[ad]\\|nconc\\|block\\|go\\|return\\(-from\\)?\\|[ec]?\\(type\\)?case\\|multiple-value-\\(bind\\|setq\\|list\\|call\\|prog1\\)\\|unwind-protect\\|handler-case\\|catch\\|throw\\|eval-when\\(-compile\\)?\\)[ \t\n]" 1 keyword)
- ))
-
-
-(hilit-set-mode-patterns
- 'plain-tex-mode
- '(("^%%.*$" nil comment)
- ("{\\\\em\\([^}]+\\)}" nil comment)
- ("\\(\\\\\\w+\\)" nil keyword)
- ("{\\\\bf\\([^}]+\\)}" nil keyword)
- ("^[ \t\n]*\\\\def[\\\\@]\\(\\w+\\)" nil defun)
- ("\\\\\\(begin\\|end\\){\\([A-Za-z0-9\\*]+\\)}" nil defun)
- ;; ("[^\\\\]\\$\\([^$]*\\)\\$" nil string)
- ("\\$\\([^$]*\\)\\$" nil string)
- ))
-
-;; Reasonable extensions would include smarter parameter handling for such
-;; things as the .IX and .I macros, which alternate the handling of following
-;; arguments.
-
-(hilit-set-mode-patterns
- 'nroff-mode
- '(("^\\.[\\\][\\\"].*$" nil comment)
- ("^\\.so .*$" nil include)
- ("^\\.[ST]H.*$" nil defun)
-;; ("^[^\\.].*\"[^\\\"]*\\(\\\\\\(.\\)[^\\\"]*\\)*\"" nil string)
- ("\"" "[^\\]\"" string)
- ("^\\.[A-Z12\\\\].*$" nil define)
- ("\\([\\\][^ ]*\\)" nil keyword)
- ("^\\.[A-Z].*$" nil keyword))
- nil 'case-insensitive)
-
-(hilit-set-mode-patterns
- 'texinfo-mode
- '(("^\\(@c\\|@comment\\)\\>.*$" nil comment)
- ("@\\(emph\\|strong\\|b\\|i\\){[^}]+}" nil comment)
-;; seems broken
-;; ("\\$[^$]*\\$" nil string)
- ("@\\(file\\|kbd\\|key\\){[^}]+}" nil string)
- ("^\\*.*$" nil defun)
- ("@\\(if\\w+\\|format\\|item\\)\\b.*$" nil defun)
- ("@end +[A-Za-z0-9]+[ \t]*$" nil defun)
- ("@\\(samp\\|code\\|var\\){[^}]+}" nil defun)
- ("@\\w+\\({[^}]+}\\)?" nil keyword)
- ))
-
-(hilit-set-mode-patterns
- 'dired-mode
- (append
- '(("^D.*$" nil dired-deleted)
- ("^\\*.*$" nil dired-marked)
- ("^ d.*$" nil dired-directory)
- ("^ l.*$" nil dired-link)
- ("^ -.*#.*#$" nil dired-ignored))
- (list (cons
- (concat "^ .*\\("
- (mapconcat 'regexp-quote completion-ignored-extensions "\\|")
- "\\)$")
- '(nil dired-ignored)))))
-
-(hilit-set-mode-patterns
- 'jargon-mode
- '(("^:[^:]*:" nil jargon-entry)
- ("{[^}]*}+" nil jargon-xref)))
-
-(hilit-set-mode-patterns
- 'Info-mode
- '(("^\\* [^:]+:+" nil jargon-entry)
- ("\\*[Nn]ote\\b[^:]+:+" nil jargon-xref)
- (" \\(Next\\|Prev\\|Up\\):" nil jargon-xref)
- ("- \\(Variable\\|Function\\|Macro\\|Command\\|Special Form\\|User Option\\):.*$"
- nil jargon-keyword))) ; lisp manual
-
-(hilit-set-mode-patterns
- 'calendar-mode
- '(("[A-Z][a-z]+ [0-9]+" nil define) ; month and year
- ("S M Tu W Th F S" nil label))) ; week days
-
-(hilit-set-mode-patterns
- 'asm-mode
- '(("/\\*" "\\*/" comment)
- ("^#[ \t]*\\(undef\\|define\\).*$" "[^\\]$" define)
- ("^#.*$" nil include)
- ;; labels
- ("^.+:" nil defun)
- ;; assembler directives
- ("^[ \t]*\\..*$" nil decl)
- ;; register names
- ("\\$[a-z0-9]+" nil string)
- ;; mnemonics
- ("^[ \t]*[a-z]+" nil struct)))
-
-(hilit-set-mode-patterns
- 'pascal-mode
- '(("(\\*" "\\*)" comment)
- ("{" "}" comment)
- ;; Doesn't work when there are strings in comments....
- ;; ("'[^']*'" nil string)
- ("^#.*$" nil include)
- ("^[ \t]*\\(procedure\\|function\\)[ \t]+\\w+[^ \t(;]*" nil defun)
- ("\\<\\(program\\|begin\\|end\\)\\>" nil defun)
- ("\\<\\(external\\|forward\\)\\>" nil include)
- ("\\<\\(label\\|const\\|type\\|var\\)\\>" nil define)
- ("\\<\\(record\\|array\\|file\\)\\>" nil type)
- ("\\<\\(of\\|to\\|for\\|if\\|then\\|else\\|case\\|while\\|do\\|until\\|and\\|or\\|not\\|with\\|repeat\\)\\>" nil keyword)
- )
- nil 'case-insensitive)
-
-(hilit-set-mode-patterns
- 'icon-mode
- '(("#.*$" nil comment)
- ("\"[^\\\"]*\\(\\\\.[^\\\"]*\\)*\"" nil string)
- ;; charsets: these do not work because of a conflict with strings
- ;; ("'[^\\']*\\(\\\\.[^\\']*\\)*'" nil string)
- ("^[ \t]*procedure[ \t]+\\w+[ \t]*(" ")" defun)
- ("^[ \t]*record.*(" ")" include)
- ("^[ \t]*\\(global\\|link\\)[ \t\n]+[A-Za-z_0-9]+\\([ \t\n]*,[ \t\n]*[A-Za-z_0-9]+\\)*" nil include)
- ("^[ \t]*\\(local\\|static\\)[ \t\n]+[A-Za-z_0-9]+\\([ \t\n]*,[ \t\n]*[A-Za-z_0-9]+\\)*" nil decl)
- ("\\<\\(initial\\|end\\)\\>" nil glob-struct)
- ("\\<\\(while\\|until\\|return\\|every\\|if\\|then\\|else\\|to\\|case\\|of\\|suspend\\|create\\|do\\|repeat\\|break\\)\\>" nil keyword)
- ))
-
-;; as you can see, I had two similar problems for Pascal and Icon. In
-;; Pascal, strings are delimited with ' and an embedded quote is doubled,
-;; thus string syntax would be extremely simple. However, if a string
-;; occurs within a comment, the following text is considered a string.
-;;
-;; In Icon, strings are similar to C ones, but there are also charsets,
-;; delimited with simple quotes. I could not manage to use both regexps at
-;; the same time.
-
-;; The problem I have with my patterns for Icon is that this language has a
-;; string similar constant to the C one (but a string can be cut on several
-;; lines, if terminated by a dash and continued with initial blanks, like
-;; this:
-;; "This is a somewhat long -
-;; string, written on three -
-;; successive lines"
-;; in order to insert a double quote in a string, you have to escape it
-;; with a \), bu also a character set constant (named a charset), which
-;; uses single quotes instead of double ones. It would seem intuitive to
-;; highlight both constants in the same way.
-
-
-(provide 'hilit19)
-
-;;; hilit19 ends here.
diff --git a/lisp/hippie-exp.el b/lisp/hippie-exp.el
deleted file mode 100644
index caa479d9ec8..00000000000
--- a/lisp/hippie-exp.el
+++ /dev/null
@@ -1,1127 +0,0 @@
-;;; hippie-exp.el --- expand text trying various ways to find its expansion.
-
-;; Copyright (C) 1992 Free Software Foundation, Inc.
-
-;; Author: Anders Holst <aho@sans.kth.se>
-;; Last change: 6 August 1995
-;; Version: 1.4
-;; Keywords: abbrev
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; `hippie-expand' is a single function for a lot of different kinds
-;; of completions and expansions. Called repeatedly it tries all
-;; possible completions in succession.
-;; Which kinds of completions to try, and in which order, is
-;; determined by the contents of `hippie-expand-try-functions-list'.
-;; Much customization of `hippie-expand' can be made by changing the
-;; order of, removing, or inserting new functions in this list.
-;; Given a positive numeric argument, `hippie-expand' jumps directly
-;; ARG functions forward in this list. Given some other argument
-;; (a negative argument or just Ctrl-U) it undoes the tried
-;; completion.
-;;
-;; If the variable `hippie-expand-verbose' is non-nil, `hippie-expand'
-;; outputs in a message which try-function in the list that is used
-;; currently (ie. was used currently and will be tried first the next
-;; time).
-;; The variable `hippie-expand-max-buffers' determines in how many
-;; buffers, apart from the current, to search for expansions in. It
-;; is used by the try-functions named "-all-buffers".
-;; The variable `hippie-expand-ignore-buffers' is a list of regexps
-;; matching buffer names (as strings) or major modes (as atoms) of
-;; buffers that should not be searched by the try-functions named
-;; "-all-buffers".
-;; See also the macro `make-hippie-expand-function' below.
-;;
-;; A short description of the current try-functions in this file:
-;; `try-complete-file-name' : very convenient to have in any buffer,
-;; and not just in the minibuffer or (some) shell-mode. It goes
-;; through all possible completions instead of just completing as
-;; much as is unique.
-;; `try-complete-file-name-partially' : To insert in the list just
-;; before `try-complete-file-name' for those who want first to get
-;; a file name completed only as many characters as is unique.
-;; `try-expand-all-abbrevs' : can be removed if you don't use abbrevs.
-;; Otherwise it looks through all abbrev-tables, starting with
-;; the local followed by the global.
-;; `try-expand-line' : Searches the buffer for an entire line that
-;; begins exactly as the current line. Convenient sometimes, for
-;; example as a substitute for (or complement to) the history
-;; list in shell-like buffers. At other times, only confusing.
-;; `try-expand-line-all-buffers' : Like `try-expand-line' but searches
-;; in all buffers (except the current). (This may be a little
-;; slow, don't use it unless you are really fond of `hippie-expand'.)
-;; `try-expand-list' : Tries to expand the text back to the nearest
-;; open delimiter, to a whole list from the buffer. Convenient for
-;; example when writing lisp or TeX.
-;; `try-expand-list-all-buffers' : Like `try-expand-list' but searches
-;; in all buffers (except the current).
-;; `try-expand-dabbrev' : works exactly as dabbrev-expand (but of
-;; course in a way compatible with the other try-functions).
-;; `try-expand-dabbrev-all-buffers' : perhaps the most useful of them,
-;; like `dabbrev-expand' but searches all Emacs buffers (except the
-;; current) for matching words. (No, I don't find this one
-;; particularly slow.)
-;; `try-expand-dabbrev-visible': Searches the currently visible parts of
-;; all windows. Can be put before `try-expand-dabbrev-all-buffers' to
-;; first try the expansions you can see.
-;; `try-expand-dabbrev-from-kill': Searches the kill ring for a suitable
-;; completion of the word. Good to have, just in case the word was not
-;; found elsewhere.
-;; `try-expand-whole-kill' : Tries to complete text with a whole entry
-;; from the kill ring. May be good if you don't know how far up in
-;; the kill-ring the required entry is, and don't want to mess with
-;; "Choose Next Paste".
-;; `try-complete-lisp-symbol' : like `lisp-complete-symbol', but goes
-;; through all possibilities instead of completing what is unique.
-;; Might be tedious (usually a lot of possible completions) and
-;; since its function is much like `lisp-complete-symbol', which
-;; already has a key of its own, you might want to remove this.
-;; `try-complete-lisp-symbol-partially' : To insert in the list just
-;; before `try-complete-lisp-symbol' for those who first want to get
-;; completion of what is unique in the name.
-;;
-;; Not all of the above functions are by default in
-;; `hippie-expand-try-functions-list'. This variable is better set
-;; in ".emacs" to make `hippie-expand' behave maximally convenient
-;; according to personal taste. Also, instead of loading the
-;; variable with all kinds of try-functions above, it might be an
-;; idea to use `make-hippie-expand-function' to construct different
-;; `hippie-expand'-like functions, with different try-lists and bound
-;; to different keys. It is also possible to make
-;; `hippie-expand-try-functions-list' a buffer local variable, and
-;; let it depend on the mode (by setting it in the mode-hooks).
-;;
-;; To write new try-functions, consider the following:
-;; Each try-function takes one argument OLD which is nil the first
-;; time the function is called and true in succeeding calls for the
-;; same string to complete. The first time the function has to
-;; extract the string before point to complete, and substitute the
-;; first completion alternative for it. On following calls it has to
-;; substitute the next possible completion for the last tried string.
-;; The try-function is to return t as long as it finds new
-;; possible completions. When there are no more alternatives it has
-;; to restore the text before point to its original contents, and
-;; return nil (don't beep or message or anything).
-;; The try-function can (should) use the following functions:
-;; `he-init-string' : Initializes the text to substitute to the
-;; contents of the region BEGIN to END. Also sets the variable
-;; `he-search-string' to the text to expand.
-;; `he-substitute-string' : substitutes STR into the region
-;; initialized with `he-init-string'. (An optional second argument
-;; TRANS-CASE non-nil, means transfer of case from the abbreviation
-;; to the expansion is ok if that is enabled in the buffer.)
-;; `he-reset-string' : Resets the initialized region to its original
-;; contents.
-;; There is also a variable: `he-tried-table' which is meant to contain
-;; all tried expansions so far. The try-function can check this
-;; variable to see whether an expansion has already been tried
-;; (hint: `he-string-member').
-;;
-;; Known bugs
-;;
-;; It may happen that some completion suggestion occurs twice, in
-;; spite of the use of `he-tried-table' to prevent that. This is
-;; because different try-functions may try to complete different
-;; lengths of text, and thus put different amounts of the
-;; text in `he-tried-table'. Anyway this seems to occur seldom enough
-;; not to be too disturbing. Also it should NOT be possible for the
-;; opposite situation to occur, that `hippie-expand' misses some
-;; suggestion because it thinks it has already tried it.
-;;
-;; Acknowledgement
-;;
-;; I want to thank Mikael Djurfeldt in discussions with whom the idea
-;; of this function took form.
-;; I am also grateful to all those who have given me suggestions on
-;; how to improve it, and all those who helped to find and remove bugs.
-;;
-
-;;; Code:
-
-(defvar he-num -1)
-
-(defvar he-string-beg (make-marker))
-
-(defvar he-string-end (make-marker))
-
-(defvar he-search-string ())
-
-(defvar he-expand-list ())
-
-(defvar he-tried-table ())
-
-(defvar he-search-loc (make-marker))
-
-(defvar he-search-loc2 ())
-
-(defvar he-search-bw ())
-
-(defvar he-search-bufs ())
-
-(defvar he-searched-n-bufs ())
-
-(defvar he-search-window ())
-
-;;;###autoload
-(defvar hippie-expand-try-functions-list '(try-complete-file-name-partially
- try-complete-file-name
- try-expand-all-abbrevs
- try-expand-list
- try-expand-line
- try-expand-dabbrev
- try-expand-dabbrev-all-buffers
- try-expand-dabbrev-from-kill
- try-complete-lisp-symbol-partially
- try-complete-lisp-symbol)
- "The list of expansion functions tried in order by `hippie-expand'.
-To change the behavior of `hippie-expand', remove, change the order of,
-or insert functions in this list.")
-
-;;;###autoload
-(defvar hippie-expand-verbose t
- "*Non-nil makes `hippie-expand' output which function it is trying.")
-
-;;;###autoload
-(defvar hippie-expand-max-buffers ()
- "*The maximum number of buffers (apart from the current) searched.
-If nil, all buffers are searched.")
-
-;;;###autoload
-(defvar hippie-expand-ignore-buffers '("^ \\*.*\\*$" dired-mode)
- "*A list specifying which buffers not to search (if not current).
-Can contain both regexps matching buffer names (as strings) and major modes
-\(as atoms)")
-
-;;;###autoload
-(defun hippie-expand (arg)
- "Try to expand text before point, using multiple methods.
-The expansion functions in `hippie-expand-try-functions-list' are
-tried in order, until a possible expansion is found. Repeated
-application of `hippie-expand' inserts successively possible
-expansions.
-With a positive numeric argument, jumps directly to the ARG next
-function in this list. With a negative argument or just \\[universal-argument],
-undoes the expansion."
- (interactive "P")
- (if (or (not arg)
- (and (integerp arg) (> arg 0)))
- (let ((first (or (= he-num -1)
- (not (equal this-command last-command)))))
- (if first
- (progn
- (setq he-num -1)
- (setq he-tried-table nil)))
- (if arg
- (if (not first) (he-reset-string))
- (setq arg 0))
- (let ((i (max (+ he-num arg) 0)))
- (while (not (or (>= i (length hippie-expand-try-functions-list))
- (apply (nth i hippie-expand-try-functions-list)
- (list (= he-num i)))))
- (setq i (1+ i)))
- (setq he-num i))
- (if (>= he-num (length hippie-expand-try-functions-list))
- (progn
- (setq he-num -1)
- (if first
- (message "No expansion found")
- (message "No further expansions found"))
- (ding))
- (if (and hippie-expand-verbose
- (not (window-minibuffer-p (selected-window))))
- (message "Using %s"
- (prin1-to-string (nth he-num
- hippie-expand-try-functions-list))))))
- (if (and (>= he-num 0)
- (eq (marker-buffer he-string-beg) (current-buffer)))
- (progn
- (setq he-num -1)
- (he-reset-string)
- (if (and hippie-expand-verbose
- (not (window-minibuffer-p (selected-window))))
- (message "Undoing expansions"))))))
-
-;; Initializes the region to expand (to between BEG and END).
-(defun he-init-string (beg end)
- (set-marker he-string-beg beg)
- (set-marker he-string-end end)
- (setq he-search-string (buffer-substring beg end)))
-
-;; Resets the expanded region to its original contents.
-(defun he-reset-string ()
- (let ((newpos (point-marker)))
- (goto-char he-string-beg)
- (insert he-search-string)
- (delete-region (point) he-string-end)
- (goto-char newpos)))
-
-;; Substitutes an expansion STR into the correct region (the region
-;; initialized with `he-init-string').
-;; An optional argument TRANS-CASE means that it is ok to transfer case
-;; from the abbreviation to the expansion if that is possible, and is
-;; enabled in the buffer.
-(defun he-substitute-string (str &optional trans-case)
- (let ((trans-case (and trans-case
- case-replace
- case-fold-search))
- (newpos (point-marker))
- (subst ()))
- (goto-char he-string-beg)
- (setq subst (if trans-case (he-transfer-case he-search-string str) str))
- (setq he-tried-table (cons subst he-tried-table))
- (insert subst)
- (delete-region (point) he-string-end)
- (goto-char newpos)))
-
-(defun he-capitalize-first (str)
- (save-match-data
- (if (string-match "\\Sw*\\(\\sw\\).*" str)
- (let ((res (downcase str))
- (no (match-beginning 1)))
- (aset res no (upcase (aref str no)))
- res)
- str)))
-
-(defun he-ordinary-case-p (str)
- (or (string= str (downcase str))
- (string= str (upcase str))
- (string= str (capitalize str))
- (string= str (he-capitalize-first str))))
-
-(defun he-transfer-case (from-str to-str)
- (cond ((string= from-str (substring to-str 0 (min (length from-str)
- (length to-str))))
- to-str)
- ((not (he-ordinary-case-p to-str))
- to-str)
- ((string= from-str (downcase from-str))
- (downcase to-str))
- ((string= from-str (upcase from-str))
- (upcase to-str))
- ((string= from-str (he-capitalize-first from-str))
- (he-capitalize-first to-str))
- ((string= from-str (capitalize from-str))
- (capitalize to-str))
- (t
- to-str)))
-
-
-;; Check if STR is a member of LST.
-;; Transform to the final case if optional TRANS-CASE is non-NIL.
-(defun he-string-member (str lst &optional trans-case)
- (if str
- (member (if (and trans-case
- case-replace
- case-fold-search)
- (he-transfer-case he-search-string str)
- str)
- lst)))
-
-;; Check if STR matches any regexp in LST.
-;; Ignore possible non-strings in LST.
-(defun he-regexp-member (str lst)
- (while (and lst
- (or (not (stringp (car lst)))
- (not (string-match (car lst) str))))
- (setq lst (cdr lst)))
- lst)
-
-;; For the real hippie-expand enthusiast: A macro that makes it
-;; possible to use many functions like hippie-expand, but with
-;; different try-functions-lists.
-;; Usage is for example:
-;; (fset 'my-complete-file (make-hippie-expand-function
-;; '(try-complete-file-name-partially
-;; try-complete-file-name)))
-;; (fset 'my-complete-line (make-hippie-expand-function
-;; '(try-expand-line
-;; try-expand-line-all-buffers)))
-;;
-;;;###autoload
-(defmacro make-hippie-expand-function (try-list &optional verbose)
- "Construct a function similar to `hippie-expand'.
-Make it use the expansion functions in TRY-LIST. An optional second
-argument VERBOSE non-nil makes the function verbose."
- (` (function (lambda (arg)
- (, (concat
- "Try to expand text before point, using the following functions: \n"
- (mapconcat 'prin1-to-string (eval try-list) ", ")))
- (interactive "P")
- (let ((hippie-expand-try-functions-list (, try-list))
- (hippie-expand-verbose (, verbose)))
- (hippie-expand arg))))))
-
-
-;;; Here follows the try-functions and their requisites:
-
-
-(defun try-complete-file-name (old)
- "Try to complete text as a file name.
-The argument OLD has to be nil the first call of this function, and t
-for subsequent calls (for further possible completions of the same
-string). It returns t if a new completion is found, nil otherwise."
- (if (not old)
- (progn
- (he-init-string (he-file-name-beg) (point))
- (let ((name-part (he-file-name-nondirectory he-search-string))
- (dir-part (expand-file-name (or (he-file-name-directory
- he-search-string) ""))))
- (if (not (he-string-member name-part he-tried-table))
- (setq he-tried-table (cons name-part he-tried-table)))
- (if (and (not (equal he-search-string ""))
- (he-file-directory-p dir-part))
- (setq he-expand-list (sort (file-name-all-completions
- name-part
- dir-part)
- 'string-lessp))
- (setq he-expand-list ())))))
-
- (while (and he-expand-list
- (he-string-member (car he-expand-list) he-tried-table))
- (setq he-expand-list (cdr he-expand-list)))
- (if (null he-expand-list)
- (progn
- (if old (he-reset-string))
- ())
- (let ((filename (he-concat-directory-file-name
- (he-file-name-directory he-search-string)
- (car he-expand-list))))
- (he-substitute-string filename)
- (setq he-tried-table (cons (car he-expand-list) (cdr he-tried-table)))
- (setq he-expand-list (cdr he-expand-list))
- t)))
-
-(defun try-complete-file-name-partially (old)
- "Try to complete text as a file name, as many characters as unique.
-The argument OLD has to be nil the first call of this function. It
-returns t if a unique, possibly partial, completion is found, nil
-otherwise."
- (let ((expansion ()))
- (if (not old)
- (progn
- (he-init-string (he-file-name-beg) (point))
- (let ((name-part (he-file-name-nondirectory he-search-string))
- (dir-part (expand-file-name (or (he-file-name-directory
- he-search-string) ""))))
- (if (and (not (equal he-search-string ""))
- (he-file-directory-p dir-part))
- (setq expansion (file-name-completion name-part
- dir-part)))
- (if (or (eq expansion t)
- (string= expansion name-part)
- (he-string-member expansion he-tried-table))
- (setq expansion ())))))
-
- (if (not expansion)
- (progn
- (if old (he-reset-string))
- ())
- (let ((filename (he-concat-directory-file-name
- (he-file-name-directory he-search-string)
- expansion)))
- (he-substitute-string filename)
- (setq he-tried-table (cons expansion (cdr he-tried-table)))
- t))))
-
-(defvar he-file-name-chars
- (cond ((memq system-type '(vax-vms axp-vms))
- "-a-zA-Z0-9_/.,~^#$+=:\\[\\]")
- ((memq system-type '(ms-dos windows-nt))
- "-a-zA-Z0-9_/.,~^#$+=:\\\\")
- (t ;; More strange file formats ?
- "-a-zA-Z0-9_/.,~^#$+="))
- "Characters that are considered part of the file name to expand.")
-
-(defun he-file-name-beg ()
- (save-excursion
- (skip-chars-backward he-file-name-chars)
- (point)))
-
-;; Thanks go to Richard Levitte <levitte@e.kth.se> who helped to make these
-;; work under VMS, and to David Hughes <ukchugd@ukpmr.cs.philips.nl> who
-;; helped to make it work on PC.
-(defun he-file-name-nondirectory (file)
- "Fix to make `file-name-nondirectory' work for hippie-expand under VMS."
- (if (memq system-type '(axp-vms vax-vms))
- (let ((n (file-name-nondirectory file)))
- (if (string-match "^\\(\\[.*\\)\\.\\([^\\.]*\\)$" n)
- (concat "[." (substring n (match-beginning 2) (match-end 2)))
- n))
- (file-name-nondirectory file)))
-
-(defun he-file-name-directory (file)
- "Fix to make `file-name-directory' work for hippie-expand under VMS."
- (if (memq system-type '(axp-vms vax-vms))
- (let ((n (file-name-nondirectory file))
- (d (file-name-directory file)))
- (if (string-match "^\\(\\[.*\\)\\.\\([^\\.]*\\)$" n)
- (concat d (substring n (match-beginning 1) (match-end 1)) "]")
- d))
- (file-name-directory file)))
-
-(defun he-file-directory-p (file)
- "Fix to make `file-directory-p' work for hippie-expand under VMS."
- (if (memq system-type '(vax-vms axp-vms))
- (or (file-directory-p file)
- (file-directory-p (concat file "[000000]")))
- (file-directory-p file)))
-
-(defun he-concat-directory-file-name (dir-part name-part)
- "Try to slam together two parts of a file specification, system dependently."
- (cond ((null dir-part) name-part)
- ((memq system-type '(axp-vms vax-vms))
- (if (and (string= (substring dir-part -1) "]")
- (string= (substring name-part 0 2) "[."))
- (concat (substring dir-part 0 -1) (substring name-part 1))
- (concat dir-part name-part)))
- ((memq system-type '(ms-dos w32))
- (if (and (string-match "\\\\" dir-part)
- (not (string-match "/" dir-part))
- (= (aref name-part (1- (length name-part))) ?/))
- (aset name-part (1- (length name-part)) ?\\))
- (concat dir-part name-part))
- (t
- (concat dir-part name-part))))
-
-(defun try-complete-lisp-symbol (old)
- "Try to complete word as an Emacs Lisp symbol.
-The argument OLD has to be nil the first call of this function, and t
-for subsequent calls (for further possible completions of the same
-string). It returns t if a new completion is found, nil otherwise."
- (if (not old)
- (progn
- (he-init-string (he-lisp-symbol-beg) (point))
- (if (not (he-string-member he-search-string he-tried-table))
- (setq he-tried-table (cons he-search-string he-tried-table)))
- (setq he-expand-list
- (and (not (equal he-search-string ""))
- (sort (all-completions he-search-string obarray
- (function (lambda (sym)
- (or (boundp sym)
- (fboundp sym)
- (symbol-plist sym)))))
- 'string-lessp)))))
- (while (and he-expand-list
- (he-string-member (car he-expand-list) he-tried-table))
- (setq he-expand-list (cdr he-expand-list)))
- (if (null he-expand-list)
- (progn
- (if old (he-reset-string))
- ())
- (progn
- (he-substitute-string (car he-expand-list))
- (setq he-expand-list (cdr he-expand-list))
- t)))
-
-(defun try-complete-lisp-symbol-partially (old)
- "Try to complete as an Emacs Lisp symbol, as many characters as unique.
-The argument OLD has to be nil the first call of this function. It
-returns t if a unique, possibly partial, completion is found, nil
-otherwise."
- (let ((expansion ()))
- (if (not old)
- (progn
- (he-init-string (he-lisp-symbol-beg) (point))
- (if (not (string= he-search-string ""))
- (setq expansion
- (try-completion he-search-string obarray
- (function (lambda (sym)
- (or (boundp sym)
- (fboundp sym)
- (symbol-plist sym)))))))
- (if (or (eq expansion t)
- (string= expansion he-search-string)
- (he-string-member expansion he-tried-table))
- (setq expansion ()))))
-
- (if (not expansion)
- (progn
- (if old (he-reset-string))
- ())
- (progn
- (he-substitute-string expansion)
- t))))
-
-(defun he-lisp-symbol-beg ()
- (let ((skips "-a-zA-Z0-9_."))
- (save-excursion
- (skip-chars-backward skips)
- (point))))
-
-(defun try-expand-line (old)
- "Try to complete the current line to an entire line in the buffer.
-The argument OLD has to be nil the first call of this function, and t
-for subsequent calls (for further possible completions of the same
-string). It returns t if a new completion is found, nil otherwise."
- (let ((expansion ())
- (strip-prompt (and (get-buffer-process (current-buffer))
- comint-prompt-regexp)))
- (if (not old)
- (progn
- (he-init-string (he-line-beg strip-prompt) (point))
- (set-marker he-search-loc he-string-beg)
- (setq he-search-bw t)))
-
- (if (not (equal he-search-string ""))
- (save-excursion
- ;; Try looking backward unless inhibited.
- (if he-search-bw
- (progn
- (goto-char he-search-loc)
- (setq expansion (he-line-search he-search-string
- strip-prompt t))
- (set-marker he-search-loc (point))
- (if (not expansion)
- (progn
- (set-marker he-search-loc he-string-end)
- (setq he-search-bw ())))))
-
- (if (not expansion) ; Then look forward.
- (progn
- (goto-char he-search-loc)
- (setq expansion (he-line-search he-search-string
- strip-prompt nil))
- (set-marker he-search-loc (point))))))
-
- (if (not expansion)
- (progn
- (if old (he-reset-string))
- ())
- (progn
- (he-substitute-string expansion t)
- t))))
-
-(defun try-expand-line-all-buffers (old)
- "Try to complete the current line, searching all other buffers.
-The argument OLD has to be nil the first call of this function, and t
-for subsequent calls (for further possible completions of the same
-string). It returns t if a new completion is found, nil otherwise."
- (let ((expansion ())
- (strip-prompt (and (get-buffer-process (current-buffer))
- comint-prompt-regexp))
- (buf (current-buffer))
- (orig-case-fold-search case-fold-search))
- (if (not old)
- (progn
- (he-init-string (he-line-beg strip-prompt) (point))
- (setq he-search-bufs (buffer-list))
- (setq he-searched-n-bufs 0)
- (set-marker he-search-loc 1 (car he-search-bufs))))
-
- (if (not (equal he-search-string ""))
- (while (and he-search-bufs
- (not expansion)
- (or (not hippie-expand-max-buffers)
- (< he-searched-n-bufs hippie-expand-max-buffers)))
- (set-buffer (car he-search-bufs))
- (if (and (not (eq (current-buffer) buf))
- (not (memq major-mode hippie-expand-ignore-buffers))
- (not (he-regexp-member (buffer-name)
- hippie-expand-ignore-buffers)))
- (save-excursion
- (goto-char he-search-loc)
- (setq strip-prompt (and (get-buffer-process (current-buffer))
- comint-prompt-regexp))
- (setq expansion (let ((case-fold-search orig-case-fold-search))
- (he-line-search he-search-string
- strip-prompt nil)))
- (set-marker he-search-loc (point))
- (if (not expansion)
- (progn
- (setq he-search-bufs (cdr he-search-bufs))
- (setq he-searched-n-bufs (1+ he-searched-n-bufs))
- (set-marker he-search-loc 1 (car he-search-bufs)))))
- (setq he-search-bufs (cdr he-search-bufs))
- (set-marker he-search-loc 1 (car he-search-bufs)))))
-
- (set-buffer buf)
- (if (not expansion)
- (progn
- (if old (he-reset-string))
- ())
- (progn
- (he-substitute-string expansion t)
- t))))
-
-(defun he-line-search (str strip-prompt reverse)
- (let ((result ()))
- (while (and (not result)
- (if reverse
- (re-search-backward
- (he-line-search-regexp str strip-prompt)
- nil t)
- (re-search-forward
- (he-line-search-regexp str strip-prompt)
- nil t)))
- (setq result (buffer-substring (match-beginning 2) (match-end 2)))
- (if (he-string-member result he-tried-table t)
- (setq result nil))) ; if already in table, ignore
- result))
-
-(defun he-line-beg (strip-prompt)
- (save-excursion
- (if (re-search-backward (he-line-search-regexp "" strip-prompt)
- (save-excursion (beginning-of-line)
- (point)) t)
- (match-beginning 2)
- (point))))
-
-(defun he-line-search-regexp (pat strip-prompt)
- (if strip-prompt
- (concat "\\(" comint-prompt-regexp "\\|^\\s-*\\)\\("
- (regexp-quote pat)
- "[^\n]*[^ \t\n]\\)")
- (concat "^\\(\\s-*\\)\\("
- (regexp-quote pat)
- "[^\n]*[^ \t\n]\\)")))
-
-(defun try-expand-list (old)
- "Try to complete the current beginning of a list.
-The argument OLD has to be nil the first call of this function, and t
-for subsequent calls (for further possible completions of the same
-string). It returns t if a new completion is found, nil otherwise."
- (let ((expansion ()))
- (if (not old)
- (progn
- (he-init-string (he-list-beg) (point))
- (set-marker he-search-loc he-string-beg)
- (setq he-search-bw t)))
-
- (if (not (equal he-search-string ""))
- (save-excursion
- ;; Try looking backward unless inhibited.
- (if he-search-bw
- (progn
- (goto-char he-search-loc)
- (setq expansion (he-list-search he-search-string t))
- (set-marker he-search-loc (point))
- (if (not expansion)
- (progn
- (set-marker he-search-loc he-string-end)
- (setq he-search-bw ())))))
-
- (if (not expansion) ; Then look forward.
- (progn
- (goto-char he-search-loc)
- (setq expansion (he-list-search he-search-string nil))
- (set-marker he-search-loc (point))))))
-
- (if (not expansion)
- (progn
- (if old (he-reset-string))
- ())
- (progn
- (he-substitute-string expansion t)
- t))))
-
-(defun try-expand-list-all-buffers (old)
- "Try to complete the current list, searching all other buffers.
-The argument OLD has to be nil the first call of this function, and t
-for subsequent calls (for further possible completions of the same
-string). It returns t if a new completion is found, nil otherwise."
- (let ((expansion ())
- (buf (current-buffer))
- (orig-case-fold-search case-fold-search))
- (if (not old)
- (progn
- (he-init-string (he-list-beg) (point))
- (setq he-search-bufs (buffer-list))
- (setq he-searched-n-bufs 0)
- (set-marker he-search-loc 1 (car he-search-bufs))))
-
- (if (not (equal he-search-string ""))
- (while (and he-search-bufs
- (not expansion)
- (or (not hippie-expand-max-buffers)
- (< he-searched-n-bufs hippie-expand-max-buffers)))
- (set-buffer (car he-search-bufs))
- (if (and (not (eq (current-buffer) buf))
- (not (memq major-mode hippie-expand-ignore-buffers))
- (not (he-regexp-member (buffer-name)
- hippie-expand-ignore-buffers)))
- (save-excursion
- (goto-char he-search-loc)
- (setq expansion (let ((case-fold-search orig-case-fold-search))
- (he-list-search he-search-string nil)))
- (set-marker he-search-loc (point))
- (if (not expansion)
- (progn
- (setq he-search-bufs (cdr he-search-bufs))
- (setq he-searched-n-bufs (1+ he-searched-n-bufs))
- (set-marker he-search-loc 1 (car he-search-bufs)))))
- (setq he-search-bufs (cdr he-search-bufs))
- (set-marker he-search-loc 1 (car he-search-bufs)))))
-
- (set-buffer buf)
- (if (not expansion)
- (progn
- (if old (he-reset-string))
- ())
- (progn
- (he-substitute-string expansion t)
- t))))
-
-(defun he-list-search (str reverse)
- (let ((result ())
- beg pos err)
- (while (and (not result)
- (if reverse
- (search-backward str nil t)
- (search-forward str nil t)))
- (setq pos (point))
- (setq beg (match-beginning 0))
- (goto-char beg)
- (setq err ())
- (condition-case ()
- (forward-list 1)
- (error (setq err t)))
- (if (and reverse
- (> (point) he-string-beg))
- (setq err t))
- (if (not err)
- (progn
- (setq result (buffer-substring beg (point)))
- (if (he-string-member result he-tried-table t)
- (setq result nil)))) ; if already in table, ignore
- (goto-char pos))
- result))
-
-(defun he-list-beg ()
- (save-excursion
- (condition-case ()
- (backward-up-list 1)
- (error ()))
- (point)))
-
-(defun try-expand-all-abbrevs (old)
- "Try to expand word before point according to all abbrev tables.
-The argument OLD has to be nil the first call of this function, and t
-for subsequent calls (for further possible expansions of the same
-string). It returns t if a new expansion is found, nil otherwise."
- (if (not old)
- (progn
- (he-init-string (he-dabbrev-beg) (point))
- (setq he-expand-list
- (and (not (equal he-search-string ""))
- (mapcar (function (lambda (sym)
- (if (and (boundp sym) (vectorp (eval sym)))
- (abbrev-expansion (downcase he-search-string)
- (eval sym)))))
- (append '(local-abbrev-table
- global-abbrev-table)
- abbrev-table-name-list))))))
- (while (and he-expand-list
- (or (not (car he-expand-list))
- (he-string-member (car he-expand-list) he-tried-table t)))
- (setq he-expand-list (cdr he-expand-list)))
- (if (null he-expand-list)
- (progn
- (if old (he-reset-string))
- ())
- (progn
- (he-substitute-string (car he-expand-list) t)
- (setq he-expand-list (cdr he-expand-list))
- t)))
-
-(defun try-expand-dabbrev (old)
- "Try to expand word \"dynamically\", searching the current buffer.
-The argument OLD has to be nil the first call of this function, and t
-for subsequent calls (for further possible expansions of the same
-string). It returns t if a new expansion is found, nil otherwise."
- (let ((expansion ()))
- (if (not old)
- (progn
- (he-init-string (he-dabbrev-beg) (point))
- (set-marker he-search-loc he-string-beg)
- (setq he-search-bw t)))
-
- (if (not (equal he-search-string ""))
- (save-excursion
- ;; Try looking backward unless inhibited.
- (if he-search-bw
- (progn
- (goto-char he-search-loc)
- (setq expansion (he-dabbrev-search he-search-string t))
- (set-marker he-search-loc (point))
- (if (not expansion)
- (progn
- (set-marker he-search-loc he-string-end)
- (setq he-search-bw ())))))
-
- (if (not expansion) ; Then look forward.
- (progn
- (goto-char he-search-loc)
- (setq expansion (he-dabbrev-search he-search-string nil))
- (set-marker he-search-loc (point))))))
-
- (if (not expansion)
- (progn
- (if old (he-reset-string))
- ())
- (progn
- (he-substitute-string expansion t)
- t))))
-
-(defun try-expand-dabbrev-all-buffers (old)
- "Tries to expand word \"dynamically\", searching all other buffers.
-The argument OLD has to be nil the first call of this function, and t
-for subsequent calls (for further possible expansions of the same
-string). It returns t if a new expansion is found, nil otherwise."
- (let ((expansion ())
- (buf (current-buffer))
- (orig-case-fold-search case-fold-search))
- (if (not old)
- (progn
- (he-init-string (he-dabbrev-beg) (point))
- (setq he-search-bufs (buffer-list))
- (setq he-searched-n-bufs 0)
- (set-marker he-search-loc 1 (car he-search-bufs))))
-
- (if (not (equal he-search-string ""))
- (while (and he-search-bufs
- (not expansion)
- (or (not hippie-expand-max-buffers)
- (< he-searched-n-bufs hippie-expand-max-buffers)))
- (set-buffer (car he-search-bufs))
- (if (and (not (eq (current-buffer) buf))
- (not (memq major-mode hippie-expand-ignore-buffers))
- (not (he-regexp-member (buffer-name)
- hippie-expand-ignore-buffers)))
- (save-excursion
- (goto-char he-search-loc)
- (setq expansion (let ((case-fold-search orig-case-fold-search))
- (he-dabbrev-search he-search-string nil)))
- (set-marker he-search-loc (point))
- (if (not expansion)
- (progn
- (setq he-search-bufs (cdr he-search-bufs))
- (setq he-searched-n-bufs (1+ he-searched-n-bufs))
- (set-marker he-search-loc 1 (car he-search-bufs)))))
- (setq he-search-bufs (cdr he-search-bufs))
- (set-marker he-search-loc 1 (car he-search-bufs)))))
-
- (set-buffer buf)
- (if (not expansion)
- (progn
- (if old (he-reset-string))
- ())
- (progn
- (he-substitute-string expansion t)
- t))))
-
-;; Thanks go to Jeff Dairiki <dairiki@faraday.apl.washington.edu> who
-;; suggested this one.
-(defun try-expand-dabbrev-visible (old)
- "Try to expand word \"dynamically\", searching visible window parts.
-The argument OLD has to be nil the first call of this function, and t
-for subsequent calls (for further possible expansions of the same
-string). It returns t if a new expansion is found, nil otherwise."
- (let ((expansion ())
- (buf (current-buffer))
- (flag (if (frame-visible-p (window-frame (selected-window)))
- 'visible t)))
- (if (not old)
- (progn
- (he-init-string (he-dabbrev-beg) (point))
- (setq he-search-window (selected-window))
- (set-marker he-search-loc
- (window-start he-search-window)
- (window-buffer he-search-window))))
-
- (while (and (not (equal he-search-string ""))
- (marker-position he-search-loc)
- (not expansion))
- (save-excursion
- (set-buffer (marker-buffer he-search-loc))
- (goto-char he-search-loc)
- (setq expansion (he-dabbrev-search he-search-string ()
- (window-end he-search-window)))
- (if (and expansion
- (eq (marker-buffer he-string-beg) (current-buffer))
- (eq (marker-position he-string-beg) (match-beginning 0)))
- (setq expansion (he-dabbrev-search he-search-string ()
- (window-end he-search-window))))
- (set-marker he-search-loc (point) (current-buffer)))
- (if (not expansion)
- (progn
- (setq he-search-window (next-window he-search-window nil flag))
- (if (eq he-search-window (selected-window))
- (set-marker he-search-loc nil)
- (set-marker he-search-loc (window-start he-search-window)
- (window-buffer he-search-window))))))
-
- (set-buffer buf)
- (if (not expansion)
- (progn
- (if old (he-reset-string))
- ())
- (progn
- (he-substitute-string expansion t)
- t))))
-
-(defun he-dabbrev-search (pattern &optional reverse limit)
- (let ((result ())
- (regpat (if (eq (char-syntax (aref pattern 0)) ?_)
- (concat (regexp-quote pattern) "\\(\\sw\\|\\s_\\)+")
- (concat "\\<" (regexp-quote pattern) "\\(\\sw\\|\\s_\\)+"))))
- (while (and (not result)
- (if reverse
- (re-search-backward regpat limit t)
- (re-search-forward regpat limit t)))
- (setq result (buffer-substring (match-beginning 0) (match-end 0)))
- (if (or (and (> (match-beginning 0) (point-min))
- (memq (char-syntax (char-after (1- (match-beginning 0))))
- '(?_ ?w)))
- (he-string-member result he-tried-table t))
- (setq result nil))) ; ignore if bad prefix or already in table
- result))
-
-(defvar he-dabbrev-skip-space ()
- "Non-NIL means tolerate trailing spaces in the abbreviation to expand.")
-
-(defun he-dabbrev-beg ()
- (let ((op (point)))
- (save-excursion
- (if he-dabbrev-skip-space
- (skip-syntax-backward ". "))
- (if (= (skip-syntax-backward "w_") 0)
- op
- (point)))))
-
-(defun try-expand-dabbrev-from-kill (old)
- "Try to expand word \"dynamically\", searching the kill ring.
-The argument OLD has to be nil the first call of this function, and t
-for subsequent calls (for further possible completions of the same
-string). It returns t if a new completion is found, nil otherwise."
- (let ((expansion ()))
- (if (not old)
- (progn
- (he-init-string (he-dabbrev-beg) (point))
- (setq he-expand-list
- (if (not (equal he-search-string ""))
- kill-ring))
- (setq he-search-loc2 0)))
- (if (not (equal he-search-string ""))
- (setq expansion (he-dabbrev-kill-search he-search-string)))
- (if (not expansion)
- (progn
- (if old (he-reset-string))
- ())
- (progn
- (he-substitute-string expansion t)
- t))))
-
-(defun he-dabbrev-kill-search (pattern)
- (let ((result ())
- (regpat (if (eq (char-syntax (aref pattern 0)) ?_)
- (concat (regexp-quote pattern) "\\(\\sw\\|\\s_\\)+")
- (concat "\\<" (regexp-quote pattern) "\\(\\sw\\|\\s_\\)+")))
- (killstr (car he-expand-list)))
- (while (and (not result)
- he-expand-list)
- (while (and (not result)
- (string-match regpat killstr he-search-loc2))
- (setq result (substring killstr (match-beginning 0) (match-end 0)))
- (setq he-search-loc2 (1+ (match-beginning 0)))
- (if (or (and (> (match-beginning 0) 0)
- (memq (char-syntax (aref killstr (1- (match-beginning 0))))
- '(?_ ?w)))
- (he-string-member result he-tried-table t))
- (setq result nil))) ; ignore if bad prefix or already in table
- (if (and (not result)
- he-expand-list)
- (progn
- (setq he-expand-list (cdr he-expand-list))
- (setq killstr (car he-expand-list))
- (setq he-search-loc2 0))))
- result))
-
-(defun try-expand-whole-kill (old)
- "Try to complete text with something from the kill ring.
-The argument OLD has to be nil the first call of this function, and t
-for subsequent calls (for further possible completions of the same
-string). It returns t if a new completion is found, nil otherwise."
- (let ((expansion ()))
- (if (not old)
- (progn
- (he-init-string (he-kill-beg) (point))
- (if (not (he-string-member he-search-string he-tried-table))
- (setq he-tried-table (cons he-search-string he-tried-table)))
- (setq he-expand-list
- (if (not (equal he-search-string ""))
- kill-ring))
- (setq he-search-loc2 ())))
- (if (not (equal he-search-string ""))
- (setq expansion (he-whole-kill-search he-search-string)))
- (if (not expansion)
- (progn
- (if old (he-reset-string))
- ())
- (progn
- (he-substitute-string expansion)
- t))))
-
-(defun he-whole-kill-search (str)
- (let ((case-fold-search ())
- (result ())
- (str (regexp-quote str))
- (killstr (car he-expand-list))
- (pos -1))
- (while (and (not result)
- he-expand-list)
- (if (not he-search-loc2)
- (while (setq pos (string-match str killstr (1+ pos)))
- (setq he-search-loc2 (cons pos he-search-loc2))))
- (while (and (not result)
- he-search-loc2)
- (setq pos (car he-search-loc2))
- (setq he-search-loc2 (cdr he-search-loc2))
- (save-excursion
- (goto-char he-string-beg)
- (if (and (>= (- (point) pos) (point-min)) ; avoid some string GC
- (eq (char-after (- (point) pos)) (aref killstr 0))
- (search-backward (substring killstr 0 pos)
- (- (point) pos) t))
- (setq result (substring killstr pos))))
- (if (and result
- (he-string-member result he-tried-table))
- (setq result nil))) ; ignore if already in table
- (if (and (not result)
- he-expand-list)
- (progn
- (setq he-expand-list (cdr he-expand-list))
- (setq killstr (car he-expand-list))
- (setq pos -1))))
- result))
-
-(defun he-kill-beg ()
- (let ((op (point)))
- (save-excursion
- (skip-syntax-backward "^w_")
- (if (= (skip-syntax-backward "w_") 0)
- op
- (point)))))
-
-
-(provide 'hippie-exp)
-
-;;; hippie-exp.el ends here
diff --git a/lisp/hscroll.el b/lisp/hscroll.el
deleted file mode 100644
index 7dd3674527d..00000000000
--- a/lisp/hscroll.el
+++ /dev/null
@@ -1,233 +0,0 @@
-;;; hscroll.el: Minor mode to automatically scroll truncated lines horizontally
-;;; Copyright (C) 1992, 1993, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Wayne Mesard <wmesard@esd.sgi.com>
-;; Keywords: display
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:a
-;;
-;; Automatically scroll horizontally when the point moves off the
-;; left or right edge of the window.
-;;
-;; - Type "M-x hscroll-mode" to enable it in the current buffer.
-;; - Type "M-x hscroll-global-mode" to enable it in every buffer.
-;; - "turn-on-hscroll" is useful in mode hooks as in:
-;; (add-hook 'text-mode-hook 'turn-on-hscroll)
-;;
-;; - hscroll-margin controls how close the cursor can get to the edge
-;; of the window.
-;; - hscroll-step-percent controls how far to jump once we decide to do so.
-;;
-;; Most users won't want to mess with the other variables defined
-;; here. But they're all documented, and they all start with
-;; "hscroll-" if you're curious.
-;;
-;; Oh, you should also know that if you set the hscroll-margin and
-;; hscroll-step-percent large enough, you can get an interesting, but
-;; undesired ping-pong effect as the point bounces from one edge to
-;; the other.
-;;
-;; wmesard@sgi.com
-
-;;; Code:
-
-;;;
-;;; PUBLIC VARIABLES
-;;;
-
-(defvar hscroll-version "2.2")
-
-(defvar hscroll-margin 5
- "*How many columns away from the edge of the window point is allowed to get
-before HScroll will horizontally scroll the window.")
-
-(defvar hscroll-snap-threshold 30
- "*When point is this many columns (or less) from the left edge of the document,
-don't do any horizontal scrolling. In other words, be biased towards the left
-edge of the document.
- Set this variable to zero to disable this bias.")
-
-(defvar hscroll-step-percent 25
- "*How far away to place the point from the window's edge when scrolling.
-Expressed as a percentage of the window's width.")
-
-(defvar hscroll-mode-name " Hscr"
- "*Horizontal scrolling mode line indicator.
-Set this to nil to conserve valuable mode line space.")
-
-(or (assq 'hscroll-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(hscroll-mode hscroll-mode-name) minor-mode-alist)))
-
-
-;;;
-;;; PRIVATE VARIABLES
-;;;
-
-(defvar hscroll-mode nil
- "Non-nil if HScroll mode is enabled.")
-(make-variable-buffer-local 'hscroll-mode)
-
-
-(defvar hscroll-old-truncate-local nil)
-(defvar hscroll-old-truncate-was-global nil)
-(make-variable-buffer-local 'hscroll-old-truncate)
-(make-variable-buffer-local 'hscroll-old-truncate-was-global)
-
-(defvar hscroll-old-truncate-default nil)
-
-;;;
-;;; PUBLIC COMMANDS
-;;;
-
-;;;###autoload
-(defun turn-on-hscroll ()
- "Unconditionally turn on Hscroll mode in the current buffer."
- (hscroll-mode 1))
-
-;;;###autoload
-(defun hscroll-mode (&optional arg)
- "Toggle HScroll mode in the current buffer.
-With ARG, turn HScroll mode on if ARG is positive, off otherwise.
-In HScroll mode, truncated lines will automatically scroll left or
-right when point gets near either edge of the window.
- See also \\[hscroll-global-mode]."
- (interactive "P")
- (make-local-hook 'post-command-hook)
- (let ((newmode (if (null arg)
- (not hscroll-mode)
- (> (prefix-numeric-value arg) 0))))
-
- (if newmode
- ;; turn it on
- (if (not hscroll-mode)
- ;; it was off
- (let ((localp (local-variable-p 'truncate-lines)))
- (if localp
- (setq hscroll-old-truncate-local truncate-lines))
- (setq hscroll-old-truncate-was-global (not localp))
- (setq truncate-lines t)
- (add-hook 'post-command-hook
- (function hscroll-window-maybe) nil t)
- ))
- ;; turn it off
- (if hscroll-mode
- ;; it was on
- (progn
- (if hscroll-old-truncate-was-global
- (kill-local-variable 'truncate-lines)
- (setq truncate-lines hscroll-old-truncate-local))
- (if (not truncate-lines)
- (set-window-hscroll (selected-window) 0))
- (remove-hook 'post-command-hook
- (function hscroll-window-maybe) t)
- ))
- )
-
- (setq hscroll-mode newmode)
- (force-mode-line-update nil)
- ))
-
-
-;;;###autoload
-(defun hscroll-global-mode (&optional arg)
- "Toggle HScroll mode in all buffers.
-With ARG, turn HScroll mode on if ARG is positive, off otherwise.
-If a buffer ever has HScroll mode set locally (via \\[hscroll-mode]),
-it will forever use the local value (i.e., \\[hscroll-global-mode]
-will have no effect on it).
- See also \\[hscroll-mode]."
- (interactive "P")
- (let* ((oldmode (default-value 'hscroll-mode))
- (newmode (if (null arg)
- (not oldmode)
- (> (prefix-numeric-value arg) 0))))
-
- (if newmode
- ;; turn it on
- (if (not hscroll-mode)
- ;; it was off
- (progn
- (setq hscroll-old-truncate-default (default-value truncate-lines))
- (setq hscroll-old-truncate-was-global t)
- (setq-default truncate-lines t)
- (add-hook 'post-command-hook (function hscroll-window-maybe))
- ))
- ;; turn it off
- (if hscroll-mode
- ;; it was on
- (progn
- (setq-default truncate-lines hscroll-old-truncate-default)
- (remove-hook 'post-command-hook (function hscroll-window-maybe))
- ))
- )
-
- (setq-default hscroll-mode newmode)
- (force-mode-line-update t)
- ))
-
-(defun hscroll-window-maybe ()
- "Scroll horizontally if point is off or nearly off the edge of the window.
-This is called automatically when in HScroll mode, but it can be explicitly
-invoked as well (i.e., it can be bound to a key)."
- (interactive)
- ;; Only consider scrolling if truncate-lines is true,
- ;; the window is already scrolled or partial-widths is true and this is
- ;; a partial width window. See display_text_line() in xdisp.c.
- (if (and hscroll-mode
- (or truncate-lines
- (not (zerop (window-hscroll)))
- (and truncate-partial-width-windows
- (< (window-width) (frame-width)))))
- (let ((linelen (save-excursion (end-of-line) (current-column)))
- (rightmost-char (+ (window-width) (window-hscroll)))
- )
- (if (< (current-column) hscroll-snap-threshold)
- (set-window-hscroll
- (selected-window)
- (- (window-hscroll)))
- (if (>= (current-column)
- (- rightmost-char hscroll-margin
- ;; Off-by-one if the left edge is scrolled
- (if (not (zerop (window-hscroll))) 1 0)
- ;; Off by one if the right edge is scrolled
- (if (> linelen rightmost-char) 1 0)
- ))
- ;; Scroll to the left a proportion of the window's width.
- (set-window-hscroll
- (selected-window)
- (- (+ (current-column)
- (/ (* (window-width) hscroll-step-percent) 100))
- (window-width)))
- (if (< (current-column) (+ (window-hscroll) hscroll-margin))
- ;; Scroll to the right a proportion of the window's width.
- (set-window-hscroll
- (selected-window)
- (- (current-column) (/ (* (window-width) hscroll-step-percent) 100)))
- )))
- )))
-
-;;;
-;;; It's not a bug, it's a *feature*
-;;;
-
-(provide 'hscroll)
-
-;;; hscroll.el ends here
diff --git a/lisp/icomplete.el b/lisp/icomplete.el
deleted file mode 100644
index 025af152a9d..00000000000
--- a/lisp/icomplete.el
+++ /dev/null
@@ -1,287 +0,0 @@
-;;; icomplete.el --- minibuffer completion incremental feedback
-
-;; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Ken Manheimer <klm@nist.gov>
-;; Maintainer: Ken Manheimer <klm@nist.gov>
-;; Created: Mar 1993 klm@nist.gov - first release to usenet
-;; Keywords: help, abbrev
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Loading this package implements a more fine-grained minibuffer
-;; completion feedback scheme. Prospective completions are concisely
-;; indicated within the minibuffer itself, with each successive
-;; keystroke.
-
-;; See 'icomplete-completions' docstring for a description of the
-;; icomplete display format.
-
-;; See the `icomplete-minibuffer-setup-hook' docstring for a means to
-;; customize icomplete setup for interoperation with other
-;; minibuffer-oriented packages.
-
-;; To activate icomplete mode, simply load the package. You can
-;; subsequently deactivate it by invoking the function icomplete-mode
-;; with a negative prefix-arg (C-U -1 ESC-x icomplete-mode). Also,
-;; you can prevent activation of the mode during package load by
-;; first setting the variable `icomplete-mode' to nil. Icompletion
-;; can be enabled any time after the package is loaded by invoking
-;; icomplete-mode without a prefix arg.
-
-;; Thanks to everyone for their suggestions for refinements of this
-;; package. I particularly have to credit Michael Cook, who
-;; implemented an incremental completion style in his 'iswitch'
-;; functions that served as a model for icomplete. Some other
-;; contributors: Noah Freidman (restructuring as minor mode), Colin
-;; Rafferty (lemacs reconciliation), Lars Lindberg, RMS, and
-;; others.
-
-;; klm.
-
-;;; Code:
-
-;;;_* Provide
-(provide 'icomplete)
-
-;;;_* User Customization variables
-
-;;;_* Initialization
-;;;_ = icomplete-minibuffer-setup-hook
-(defvar icomplete-minibuffer-setup-hook nil
- "*Icomplete-specific customization of minibuffer setup.
-
-This hook is run during minibuffer setup iff icomplete will be active.
-It is intended for use in customizing icomplete for interoperation
-with other packages. For instance:
-
- \(add-hook 'icomplete-minibuffer-setup-hook
- \(function
- \(lambda ()
- \(make-local-variable 'resize-minibuffer-window-max-height)
- \(setq resize-minibuffer-window-max-height 3))))
-
-will constrain rsz-mini to a maximum minibuffer height of 3 lines when
-icompletion is occurring.")
-
-;;;_ + Internal Variables
-;;;_ = icomplete-mode
-(defvar icomplete-mode t
- "Non-nil enables incremental minibuffer completion, once
-`\\[icomplete-mode]' function has set things up.")
-;;;_ = icomplete-eoinput 1
-(defvar icomplete-eoinput 1
- "Point where minibuffer input ends and completion info begins.")
-(make-variable-buffer-local 'icomplete-eoinput)
-;;;_ = icomplete-pre-command-hook
-(defvar icomplete-pre-command-hook nil
- "Incremental-minibuffer-completion pre-command-hook.
-
-Is run in minibuffer before user input when `icomplete-mode' is non-nil.
-Use `icomplete-mode' function to set it up properly for incremental
-minibuffer completion.")
-(add-hook 'icomplete-pre-command-hook 'icomplete-tidy)
-;;;_ = icomplete-post-command-hook
-(defvar icomplete-post-command-hook nil
- "Incremental-minibuffer-completion post-command-hook.
-
-Is run in minibuffer after user input when `icomplete-mode' is non-nil.
-Use `icomplete-mode' function to set it up properly for incremental
-minibuffer completion.")
-(add-hook 'icomplete-post-command-hook 'icomplete-exhibit)
-
-;;;_ > icomplete-mode (&optional prefix)
-;;;###autoload
-(defun icomplete-mode (&optional prefix)
- "Activate incremental minibuffer completion for this emacs session,
-or deactivate with negative prefix arg."
- (interactive "p")
- (or prefix (setq prefix 0))
- (cond ((>= prefix 0)
- (setq icomplete-mode t)
- ;; The following is not really necessary after first time -
- ;; no great loss.
- (add-hook 'minibuffer-setup-hook 'icomplete-minibuffer-setup))
- (t (setq icomplete-mode nil))))
-
-;;;_ > icomplete-simple-completing-p ()
-(defun icomplete-simple-completing-p ()
-
- "Non-nil if current window is minibuffer that's doing simple completion.
-
-Conditions are:
- the selected window is a minibuffer,
- and not in the middle of macro execution,
- and minibuffer-completion-table is not a symbol (which would
- indicate some non-standard, non-simple completion mechanism,
- like file-name and other custom-func completions)."
-
- (and (window-minibuffer-p (selected-window))
- (not executing-kbd-macro)
- (not (symbolp minibuffer-completion-table))))
-
-;;;_ > icomplete-minibuffer-setup ()
-;;;###autoload
-(defun icomplete-minibuffer-setup ()
- "Run in minibuffer on activation to establish incremental completion.
-Usually run by inclusion in `minibuffer-setup-hook'."
- (cond ((and icomplete-mode (icomplete-simple-completing-p))
- (make-local-hook 'pre-command-hook)
- (add-hook 'pre-command-hook
- (function (lambda ()
- (run-hooks 'icomplete-pre-command-hook)))
- nil t)
- (make-local-hook 'post-command-hook)
- (add-hook 'post-command-hook
- (function (lambda ()
- (run-hooks 'icomplete-post-command-hook)))
- nil t)
- (run-hooks 'icomplete-minibuffer-setup-hook))))
-
-;;;_* Completion
-
-;;;_ > icomplete-tidy ()
-(defun icomplete-tidy ()
- "Remove completions display \(if any) prior to new user input.
-Should be run in on the minibuffer `pre-command-hook'. See `icomplete-mode'
-and `minibuffer-setup-hook'."
- (if (icomplete-simple-completing-p)
- (if (and (boundp 'icomplete-eoinput)
- icomplete-eoinput)
-
- (if (> icomplete-eoinput (point-max))
- ;; Oops, got rug pulled out from under us - reinit:
- (setq icomplete-eoinput (point-max))
- (let ((buffer-undo-list buffer-undo-list )) ; prevent entry
- (delete-region icomplete-eoinput (point-max))))
-
- ;; Reestablish the local variable 'cause minibuffer-setup is weird:
- (make-local-variable 'icomplete-eoinput)
- (setq icomplete-eoinput 1))))
-
-;;;_ > icomplete-exhibit ()
-(defun icomplete-exhibit ()
- "Insert icomplete completions display.
-Should be run via minibuffer `post-command-hook'. See `icomplete-mode'
-and `minibuffer-setup-hook'."
- (if (icomplete-simple-completing-p)
- (let ((contents (buffer-substring (point-min)(point-max)))
- (buffer-undo-list t))
- (save-excursion
- (goto-char (point-max))
- ; Register the end of input, so we
- ; know where the extra stuff
- ; (match-status info) begins:
- (if (not (boundp 'icomplete-eoinput))
- ;; In case it got wiped out by major mode business:
- (make-local-variable 'icomplete-eoinput))
- (setq icomplete-eoinput (point))
- ; Insert the match-status information:
- (if (> (point-max) 1)
- (insert-string
- (icomplete-completions contents
- minibuffer-completion-table
- minibuffer-completion-predicate
- (not
- minibuffer-completion-confirm))))))))
-
-;;;_ > icomplete-completions (name candidates predicate require-match)
-(defun icomplete-completions (name candidates predicate require-match)
- "Identify prospective candidates for minibuffer completion.
-
-The display is updated with each minibuffer keystroke during
-minibuffer completion.
-
-Prospective completion suffixes (if any) are displayed, bracketed by
-one of \(), \[], or \{} pairs. The choice of brackets is as follows:
-
- \(...) - a single prospect is identified and matching is enforced,
- \[...] - a single prospect is identified but matching is optional, or
- \{...} - multiple prospects, separated by commas, are indicated, and
- further input is required to distinguish a single one.
-
-The displays for unambiguous matches have ` [Matched]' appended
-\(whether complete or not), or ` \[No matches]', if no eligible
-matches exist."
-
- (let ((comps (all-completions name candidates predicate))
- ; "-determined" - only one candidate
- (open-bracket-determined (if require-match "(" "["))
- (close-bracket-determined (if require-match ")" "]"))
- ;"-prospects" - more than one candidate
- (open-bracket-prospects "{")
- (close-bracket-prospects "}")
- )
- (cond ((null comps) (format " %sNo matches%s"
- open-bracket-determined
- close-bracket-determined))
- ((null (cdr comps)) ;one match
- (concat (if (and (> (length (car comps))
- (length name)))
- (concat open-bracket-determined
- (substring (car comps) (length name))
- close-bracket-determined)
- "")
- " [Matched]"))
- (t ;multiple matches
- (let* ((most (try-completion name candidates predicate))
- (most-len (length most))
- most-is-exact
- (alternatives
- (apply
- (function concat)
- (cdr (apply
- (function nconc)
- (mapcar '(lambda (com)
- (if (= (length com) most-len)
- ;; Most is one exact match,
- ;; note that and leave out
- ;; for later indication:
- (progn
- (setq most-is-exact t)
- ())
- (list ","
- (substring com
- most-len))))
- comps))))))
- (concat (and (> most-len (length name))
- (concat open-bracket-determined
- (substring most (length name))
- close-bracket-determined))
- open-bracket-prospects
- (if most-is-exact
- (concat "," alternatives)
- alternatives)
- close-bracket-prospects))))))
-
-;;;_ + Initialization
-;;; If user hasn't setq-default icomplete-mode to nil, then setup for
-;;; activation:
-(if icomplete-mode
- (icomplete-mode))
-
-
-;;;_* Local emacs vars.
-;;;Local variables:
-;;;outline-layout: (-2 :)
-;;;End:
-
-;;; icomplete.el ends here
-
diff --git a/lisp/ielm.el b/lisp/ielm.el
deleted file mode 100644
index afc2fa3a858..00000000000
--- a/lisp/ielm.el
+++ /dev/null
@@ -1,472 +0,0 @@
-;;; ielm.el --- interaction mode for Emacs Lisp
-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-
-;; Author: David Smith <maa036@lancaster.ac.uk>
-;; Created: 25 Feb 1994
-;; Keywords: lisp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Provides a nice interface to evaluating Emacs Lisp expressions.
-;; Input is handled by the comint package, and output is passed
-;; through the pretty-printer.
-
-;; To install: copy this file to a directory in your load-path, and
-;; add the following line to your .emacs file:
-;;
-;; (autoload 'ielm "ielm" "Start an inferior Emacs Lisp session" t)
-;;
-;; For completion to work, the comint.el from FSF Emacs 19.23 is
-;; required. If you do not have it, or if you are running Lemacs,
-;; also add the following code to your .emacs:
-;;
-;; (setq ielm-mode-hook
-;; '(lambda nil
-;; (define-key ielm-map "\t"
-;; '(lambda nil (interactive) (or (ielm-tab)
-;; (lisp-complete-symbol))))))
-
-;; To start: M-x ielm. Type C-h m in the *ielm* buffer for more info.
-
-;; The latest version is available by WWW from
-;; http://mathssun5.lancs.ac.uk:2080/~maa036/elisp/dir.html
-;; or by anonymous FTP from
-;; /anonymous@wingra.stat.wisc.edu:pub/src/emacs-lisp/ielm.el.gz
-;; or from the author: David M. Smith <maa036@lancaster.ac.uk>
-
-;;; Code:
-
-(require 'comint)
-(require 'pp)
-
-;;; User variables
-
-(defvar ielm-noisy t
- "*If non-nil, IELM will beep on error.")
-
-(defvar ielm-prompt "ELISP> "
- "Prompt used in IELM.")
-
-(defvar ielm-dynamic-return t
- "*Controls whether \\<ielm-map>\\[ielm-return] has intelligent behaviour in IELM.
-If non-nil, \\[ielm-return] evaluates input for complete sexps, or inserts a newline
-and indents for incomplete sexps. If nil, always inserts newlines.")
-
-(defvar ielm-dynamic-multiline-inputs t
- "*Force multiline inputs to start from column zero?
-If non-nil, after entering the first line of an incomplete sexp, a newline
-will be inserted after the prompt, moving the input to the next line.
-This gives more frame width for large indented sexps, and allows functions
-such as `edebug-defun' to work with such inputs.")
-
-(defvar ielm-mode-hook nil
- "*Hooks to be run when IELM (`inferior-emacs-lisp-mode') is started.")
-
-;;; System variables
-
-(defvar ielm-working-buffer nil
- "Buffer in which IELM sexps will be evaluated.
-This variable is buffer-local.")
-
-(defvar ielm-header
- (concat
- "*** Welcome to IELM version "
- (substring "$Revision: 1.7 $" 11 -2)
- " *** Type (describe-mode) for help.\n"
- "IELM has ABSOLUTELY NO WARRANTY; type (describe-no-warranty) for details.\n")
- "Message to display when IELM is started.")
-
-(defvar ielm-map nil)
-(if ielm-map nil
- (if (string-match "Lucid" emacs-version)
- ;; Lemacs
- (progn
- (setq ielm-map (make-sparse-keymap))
- (set-keymap-parent ielm-map comint-mode-map))
- ;; FSF
- (setq ielm-map (cons 'keymap comint-mode-map)))
- (define-key ielm-map "\t" 'comint-dynamic-complete)
- (define-key ielm-map "\C-m" 'ielm-return)
- (define-key ielm-map "\C-j" 'ielm-send-input)
- (define-key ielm-map "\e\C-x" 'eval-defun) ; for consistency with
- (define-key ielm-map "\e\t" 'lisp-complete-symbol) ; lisp-interaction-mode
- ;; These bindings are from shared-lisp-mode-map -- can you inherit
- ;; from more than one keymap??
- (define-key ielm-map "\e\C-q" 'indent-sexp)
- (define-key ielm-map "\177" 'backward-delete-char-untabify)
- ;; Some convenience bindings for setting the working buffer
- (define-key ielm-map "\C-c\C-b" 'ielm-change-working-buffer)
- (define-key ielm-map "\C-c\C-f" 'ielm-display-working-buffer)
- (define-key ielm-map "\C-c\C-v" 'ielm-print-working-buffer))
-
-(defvar ielm-font-lock-keywords
- (list
- (cons (concat "^" (regexp-quote ielm-prompt)) 'font-lock-keyword-face)
- '("\\(^\\*\\*\\*[^*]+\\*\\*\\*\\)\\(.*$\\)" (1 font-lock-comment-face) (2 font-lock-reference-face)))
- "Additional expressions to highlight in ielm buffers.")
-
-;;; Completion stuff
-
-(defun ielm-tab nil
- "Possibly indent the current line as lisp code."
- (interactive)
- (if (or (eq (preceding-char) ?\n)
- (eq (char-syntax (preceding-char)) ? ))
- (progn
- (ielm-indent-line)
- t)))
-
-(defun ielm-complete-symbol nil
- "Complete the lisp symbol before point."
- ;; A wrapper for lisp-complete symbol that returns non-nil if
- ;; completion has occurred
- (let* ((btick (buffer-modified-tick))
- (cbuffer (get-buffer "*Completions*"))
- (ctick (and cbuffer (buffer-modified-tick cbuffer))))
- (lisp-complete-symbol)
- ;; completion has occurred if:
- (or
- ;; the buffer has been modified
- (not (= btick (buffer-modified-tick)))
- ;; a completions buffer has been modified or created
- (if cbuffer
- (not (= ctick (buffer-modified-tick cbuffer)))
- (get-buffer "*Completions*")))))
-
-(defun ielm-complete-filename nil
- "Dynamically complete filename before point, if in a string."
- (if (nth 3 (parse-partial-sexp comint-last-input-start (point)))
- (comint-dynamic-complete-filename)))
-
-(defun ielm-indent-line nil
- "Indent the current line as Lisp code if it is not a prompt line."
- (if (save-excursion
- (beginning-of-line)
- (looking-at comint-prompt-regexp)) nil
- (lisp-indent-line)))
-
-;;; Working buffer manipulation
-
-(defun ielm-print-working-buffer nil
- "Print the current IELM working buffer's name in the echo area."
- (interactive)
- (message "The current working buffer is: %s" (buffer-name ielm-working-buffer)))
-
-(defun ielm-display-working-buffer nil
- "Display the current IELM working buffer.
-Don't forget that selecting that buffer will change its value of `point'
-to its value of `window-point'!"
- (interactive)
- (display-buffer ielm-working-buffer)
- (ielm-print-working-buffer))
-
-(defun ielm-change-working-buffer (buf)
- "Change the current IELM working buffer to BUF.
-This is the buffer in which all sexps entered at the IELM prompt are
-evaluated. You can achieve the same effect with a call to
-`set-buffer' at the IELM prompt."
- (interactive "bSet working buffer to: ")
- (setq ielm-working-buffer (or (get-buffer buf) (error "No such buffer")))
- (ielm-print-working-buffer))
-
-;;; Other bindings
-
-(defun ielm-return nil
- "Newline and indent, or evaluate the sexp before the prompt.
-Complete sexps are evaluated; for incomplete sexps inserts a newline
-and indents. If however `ielm-dynamic-return' is nil, this always
-simply inserts a newline."
- (interactive)
- (if ielm-dynamic-return
- (let ((state
- (save-excursion
- (end-of-line)
- (parse-partial-sexp (ielm-pm)
- (point)))))
- (if (and (< (car state) 1) (not (nth 3 state)))
- (ielm-send-input)
- (if (and ielm-dynamic-multiline-inputs
- (save-excursion
- (beginning-of-line)
- (looking-at comint-prompt-regexp)))
- (save-excursion
- (goto-char (ielm-pm))
- (newline 1)))
- (newline-and-indent)))
- (newline)))
-
-(defun ielm-input-sender (proc input)
- ;; Just sets the variable ielm-input, which is in the scope of
- ;; `ielm-send-input's call.
- (setq ielm-input input))
-
-(defun ielm-send-input nil
- "Evaluate the Emacs Lisp expression after the prompt."
- (interactive)
- (let ((buf (current-buffer))
- ielm-input) ; set by ielm-input-sender
- (comint-send-input) ; update history, markers etc.
- (ielm-eval-input ielm-input)))
-
-;;; Utility functions
-
-(defun ielm-is-whitespace (string)
- "Return non-nil if STRING is all whitespace."
- (or (string= string "") (string-match "\\`[ \t\n]+\\'" string)))
-
-(defun ielm-format-errors (errlist)
- (let ((result ""))
- (while errlist
- (setq result (concat result (prin1-to-string (car errlist)) ", "))
- (setq errlist (cdr errlist)))
- (substring result 0 -2)))
-
-
-(defun ielm-format-error (err)
- ;; Return a string form of the error ERR.
- (format "%s%s"
- (or (get (car err) 'error-message) "Peculiar error")
- (if (cdr err)
- (format ": %s" (ielm-format-errors (cdr err)))
- "")))
-
-;;; Evaluation
-
-(defun ielm-eval-input (ielm-string)
- "Evaluate the Lisp expression IELM-STRING, and pretty-print the result."
- ;; This is the function that actually `sends' the input to the
- ;; `inferior Lisp process'. All comint-send-input does is works out
- ;; what that input is. What this function does is evaluates that
- ;; input and produces `output' which gets inserted into the buffer,
- ;; along with a new prompt. A better way of doing this might have
- ;; been to actually send the output to the `cat' process, and write
- ;; this as in output filter that converted sexps in the output
- ;; stream to their evaluated value. But that would have involved
- ;; more process coordination than I was happy to deal with.
- ;;
- ;; NOTE: all temporary variables in this function will be in scope
- ;; during the eval, and so need to have non-clashing names.
- (let (ielm-form ; form to evaluate
- ielm-pos ; End posn of parse in string
- ielm-result ; Result, or error message
- ielm-error-type ; string, nil if no error
- (ielm-output "") ; result to display
- (ielm-wbuf ielm-working-buffer) ; current buffer after evaluation
- (ielm-pmark (ielm-pm)))
- (if (not (ielm-is-whitespace ielm-string))
- (progn
- (condition-case err
- (let (rout)
- (setq rout (read-from-string ielm-string))
- (setq ielm-form (car rout))
- (setq ielm-pos (cdr rout)))
- (error (setq ielm-result (ielm-format-error err))
- (setq ielm-error-type "Read error")))
- (if ielm-error-type nil
- ;; Make sure working buffer has not been killed
- (if (not (buffer-name ielm-working-buffer))
- (setq ielm-result "Working buffer has been killed"
- ielm-error-type "IELM Error"
- ielm-wbuf (current-buffer))
- (if (ielm-is-whitespace (substring ielm-string ielm-pos))
- ;; need this awful let convolution to work around
- ;; an Emacs bug involving local vbls and let binding
- (let ((:save :)
- (::save ::)
- (:::save :::))
- (save-excursion
- (set-buffer ielm-working-buffer)
- (condition-case err
- (let ((: :save)
- (:: ::save)
- (::: :::save)
- (ielm-obuf (current-buffer)))
- (setq ielm-result (eval ielm-form))
- (setq ielm-wbuf (current-buffer))
- ;; The eval may have changed current-buffer;
- ;; need to set it back here to avoid a bug
- ;; in let. Don't want to use save-excursion
- ;; because we want to allow changes in point.
- (set-buffer ielm-obuf))
- (error (setq ielm-result (ielm-format-error err))
- (setq ielm-error-type "Eval error"))
- (quit (setq ielm-result "Quit during evaluation")
- (setq ielm-error-type "Eval error")))))
- (setq ielm-error-type "IELM error")
- (setq ielm-result "More than one sexp in input"))))
-
- ;; If the eval changed the current buffer, mention it here
- (if (eq ielm-wbuf ielm-working-buffer) nil
- (message "current buffer is now: %s" ielm-wbuf)
- (setq ielm-working-buffer ielm-wbuf))
-
- (goto-char ielm-pmark)
- (if (not ielm-error-type)
- (condition-case err
- ;; Self-referential objects cause loops in the printer, so
- ;; trap quits here. May as well do errors, too
- (setq ielm-output (concat ielm-output (pp-to-string ielm-result)))
- (error (setq ielm-error-type "IELM Error")
- (setq ielm-result "Error during pretty-printing (bug in pp)"))
- (quit (setq ielm-error-type "IELM Error")
- (setq ielm-result "Quit during pretty-printing"))))
- (if ielm-error-type
- (progn
- (if ielm-noisy (ding))
- (setq ielm-output (concat ielm-output "*** " ielm-error-type " *** "))
- (setq ielm-output (concat ielm-output ielm-result)))
- ;; There was no error, so shift the ::: values
- (setq ::: ::)
- (setq :: :)
- (setq : ielm-result))
- (setq ielm-output (concat ielm-output "\n"))))
- (setq ielm-output (concat ielm-output ielm-prompt))
- (comint-output-filter (ielm-process) ielm-output)))
-
-;;; Process and marker utilities
-
-(defun ielm-process nil
- ;; Return the current buffer's process.
- (get-buffer-process (current-buffer)))
-
-(defun ielm-pm nil
- ;; Return the process mark of the current buffer.
- (process-mark (get-buffer-process (current-buffer))))
-
-(defun ielm-set-pm (pos)
- ;; Set the process mark in the current buffer to POS.
- (set-marker (process-mark (get-buffer-process (current-buffer))) pos))
-
-;;; Major mode
-
-(defun inferior-emacs-lisp-mode nil
- "Major mode for interactively evaluating Emacs Lisp expressions.
-Uses the interface provided by `comint-mode' (which see).
-
-* \\<ielm-map>\\[ielm-send-input] evaluates the sexp following the prompt. There must be at most
- one top-level sexp per prompt.
-
-* \\[ielm-return] inserts a newline and indents, or evaluates a
- complete expression (but see variable `ielm-dynamic-return').
- Inputs longer than one line are moved to the line following the
- prompt (but see variable `ielm-dynamic-multiline-inputs').
-
-* \\[comint-dynamic-complete] completes Lisp symbols (or filenames, within strings),
- or indents the line if there is nothing to complete.
-
-During evaluations, the values of the variables `:', `::', and `:::'
-are the results of the previous, second previous and third previous
-evaluations respectively.
-
-The current working buffer may be changed (with a call to
-`set-buffer', or with \\[ielm-change-working-buffer]), and its value
-is preserved between successive evaluations. In this way, expressions
-may be evaluated in a different buffer than the *ielm* buffer.
-Display the name of the working buffer with \\[ielm-print-working-buffer],
-or the buffer itself with \\[ielm-display-working-buffer].
-
-Expressions evaluated by IELM are not subject to `debug-on-quit' or
-`debug-on-error'.
-
-The behaviour of IELM may be customised with the following variables:
-* To stop beeping on error, set `ielm-noisy' to nil
-* If you don't like the prompt, you can change it by setting `ielm-prompt'.
-* Set `ielm-dynamic-return' to nil for bindings like `lisp-interaction-mode'
-* Entry to this mode runs `comint-mode-hook' and `ielm-mode-hook'
- (in that order).
-
-Customised bindings may be defined in `ielm-map', which currently contains:
-\\{ielm-map}"
- (interactive)
- (comint-mode)
- (setq comint-prompt-regexp (concat "^" (regexp-quote ielm-prompt)))
- (make-local-variable 'paragraph-start)
- (setq paragraph-start comint-prompt-regexp)
- (setq comint-input-sender 'ielm-input-sender)
- (setq comint-process-echoes nil)
- (setq comint-dynamic-complete-functions
- '(ielm-tab comint-replace-by-expanded-history ielm-complete-filename ielm-complete-symbol))
- (setq comint-get-old-input 'ielm-get-old-input)
-
- (setq major-mode 'inferior-emacs-lisp-mode)
- (setq mode-name "IELM")
- (use-local-map ielm-map)
- (set-syntax-table emacs-lisp-mode-syntax-table)
-
- (make-local-variable 'indent-line-function)
- (make-local-variable 'ielm-working-buffer)
- (setq ielm-working-buffer (current-buffer))
- (setq indent-line-function 'ielm-indent-line)
- (make-local-variable 'fill-paragraph-function)
- (setq fill-paragraph-function 'lisp-fill-paragraph)
-
- ;; Value holders
- (setq : nil)
- (make-local-variable ':)
- (setq :: nil)
- (make-local-variable '::)
- (setq ::: nil)
- (make-local-variable ':::)
-
- ;; font-lock support
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults
- '(ielm-font-lock-keywords nil nil ((?: . "w") (?- . "w") (?* . "w"))))
-
- ;; A dummy process to keep comint happy. It will never get any input
- (if (comint-check-proc (current-buffer)) nil
- (start-process "ielm" (current-buffer) "cat")
- (process-kill-without-query (ielm-process))
- (goto-char (point-max))
- ;; Add a silly header
- (insert ielm-header)
- (ielm-set-pm (point-max))
- (comint-output-filter (ielm-process) ielm-prompt)
- (set-marker comint-last-input-start (ielm-pm))
- (set-process-filter (get-buffer-process (current-buffer)) 'comint-output-filter))
- (run-hooks 'ielm-mode-hook))
-
-(defun ielm-get-old-input nil
- ;; Return the previous input surrounding point
- (save-excursion
- (beginning-of-line)
- (if (looking-at comint-prompt-regexp) nil
- (re-search-backward comint-prompt-regexp))
- (comint-skip-prompt)
- (buffer-substring (point) (progn (forward-sexp 1) (point)))))
-
-;;; User command
-
-;;;###autoload (add-hook 'same-window-buffer-names "*ielm*")
-
-;;;###autoload
-(defun ielm nil
- "Interactively evaluate Emacs Lisp expressions.
-Switches to the buffer `*ielm*', or creates it if it does not exist."
- (interactive)
- (if (comint-check-proc "*ielm*")
- nil
- (save-excursion
- (set-buffer (get-buffer-create "*ielm*"))
- (inferior-emacs-lisp-mode)))
- (pop-to-buffer "*ielm*"))
-
-;;; ielm.el ends here
diff --git a/lisp/imenu.el b/lisp/imenu.el
deleted file mode 100644
index 1ddd70dcfd2..00000000000
--- a/lisp/imenu.el
+++ /dev/null
@@ -1,920 +0,0 @@
-;;; imenu.el --- Framework for mode-specific buffer indexes.
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Ake Stenhoff <etxaksf@aom.ericsson.se>
-;; Lars Lindberg <lli@sypro.cap.se>
-;; Created: 8 Feb 1994
-;; Keywords: tools
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Purpose of this package:
-;; To present a framework for mode-specific buffer indexes.
-;; A buffer index is an alist of names and buffer positions.
-;; For instance all functions in a C-file and their positions.
-;;
-;; How it works:
-
-;; A mode-specific function is called to generate the index. It is
-;; then presented to the user, who can choose from this index.
-;;
-;; The package comes with a set of example functions for how to
-;; utilize this package.
-
-;; There are *examples* for index gathering functions/regular
-;; expressions for C/C++ and Lisp/Emacs Lisp but it is easy to
-;; customize for other modes. A function for jumping to the chosen
-;; index position is also supplied.
-
-;;; Thanks goes to
-;; [simon] - Simon Leinen simon@lia.di.epfl.ch
-;; [dean] - Dean Andrews ada@unison.com
-;; [alon] - Alon Albert al@mercury.co.il
-;; [greg] - Greg Thompson gregt@porsche.visix.COM
-;; [wolfgang] - Wolfgang Bangerth zcg51122@rpool1.rus.uni-stuttgart.de
-;; [kai] - Kai Grossjohann grossjoh@linus.informatik.uni-dortmund.de
-;; [david] - David M. Smith dsmith@stats.adelaide.edu.au
-;; [christian] - Christian Egli Christian.Egli@hcsd.hac.com
-;; [karl] - Karl Fogel kfogel@floss.life.uiuc.edu
-
-;;; Code
-
-(eval-when-compile (require 'cl))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;
-;;; Customizable variables
-;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defvar imenu-auto-rescan nil
- "*Non-nil means Imenu should always rescan the buffers.")
-
-(defvar imenu-auto-rescan-maxout 60000
- "* auto-rescan is disabled in buffers larger than this.
-This variable is buffer-local.")
-
-(defvar imenu-always-use-completion-buffer-p nil
- "*Set this to non-nil for displaying the index in a completion buffer.
-
-Non-nil means always display the index in a completion buffer.
-Nil means display the index as a mouse menu when the mouse was
-used to invoke `imenu'.
-`never' means never automatically display a listing of any kind.")
-
-(defvar imenu-sort-function nil
- "*The function to use for sorting the index mouse-menu.
-
-Affects only the mouse index menu.
-
-Set this to nil if you don't want any sorting (faster).
-The items in the menu are then presented in the order they were found
-in the buffer.
-
-Set it to `imenu--sort-by-name' if you want alphabetic sorting.
-
-The function should take two arguments and return T if the first
-element should come before the second. The arguments are cons cells;
-\(NAME . POSITION). Look at `imenu--sort-by-name' for an example.")
-
-(defvar imenu-max-items 25
- "*Maximum number of elements in an mouse menu for Imenu.")
-
-(defvar imenu-scanning-message "Scanning buffer for index...%2d%%"
- "*Progress message during the index scanning of the buffer.
-If non-nil, user gets a message during the scanning of the buffer.
-
-Relevant only if the mode-specific function that creates the buffer
-index use `imenu-progress-message'.")
-
-(defvar imenu-space-replacement "^"
- "*The replacement string for spaces in index names.
-Used when presenting the index in a completion-buffer to make the
-names work as tokens.")
-
-(defvar imenu-level-separator ":"
- "*The separator between index names of different levels.
-Used for making mouse-menu titles and for flattening nested indexes
-with name concatenation.")
-
-;;;###autoload
-(defvar imenu-generic-expression nil
- "The regex pattern to use for creating a buffer index.
-
-If non-nil this pattern is passed to `imenu--generic-function'
-to create a buffer index.
-
-The value should be an alist with elements that look like this:
- (MENU-TITLE REGEXP INDEX)
-or like this:
- (MENU-TITLE REGEXP INDEX FUNCTION ARGUMENTS...)
-with zero or more ARGUMENTS. The former format creates a simple element in
-the index alist when it matches; the latter creates a special element
-of the form (NAME FUNCTION NAME POSITION-MARKER ARGUMENTS...)
-with FUNCTION and ARGUMENTS beiong copied from `imenu-generic-expression'.
-
-MENU-TITLE is a string used as the title for the submenu or nil if the
-entries are not nested.
-
-REGEXP is a regexp that should match a construct in the buffer that is
-to be displayed in the menu; i.e., function or variable definitions,
-etc. It contains a substring which is the name to appear in the
-menu. See the info section on Regexps for more information.
-
-INDEX points to the substring in REGEXP that contains the name (of the
-function, variable or type) that is to appear in the menu.
-
-For emacs-lisp-mode for example PATTERN would look like:
-
-'((nil \"^\\\\s-*(def\\\\(un\\\\|subst\\\\|macro\\\\|advice\\\\)\\\\s-+\\\\([-A-Za-z0-9+]+\\\\)\" 2)
- (\"*Vars*\" \"^\\\\s-*(def\\\\(var\\\\|const\\\\)\\\\s-+\\\\([-A-Za-z0-9+]+\\\\)\" 2)
- (\"*Types*\" \"^\\\\s-*(def\\\\(type\\\\|struct\\\\|class\\\\|ine-condition\\\\)\\\\s-+\\\\([-A-Za-z0-9+]+\\\\)\" 2))
-
-The variable is buffer-local.")
-
-;;;###autoload
-(make-variable-buffer-local 'imenu-generic-expression)
-
-;;;; Hooks
-
-(defvar imenu-create-index-function 'imenu-default-create-index-function
- "The function to use for creating a buffer index.
-
-It should be a function that takes no arguments and returns an index
-of the current buffer as an alist.
-
-Simple elements in the alist look like (INDEX-NAME . INDEX-POSITION).
-Special elements look like (INDEX-NAME FUNCTION ARGUMENTS...).
-A nested sub-alist element looks like (INDEX-NAME SUB-ALIST).
-The function `imenu--subalist-p' tests an element and returns t
- if it is a sub-alist.
-
-This function is called within a `save-excursion'.
-
-The variable is buffer-local.")
-(make-variable-buffer-local 'imenu-create-index-function)
-
-(defvar imenu-prev-index-position-function 'beginning-of-defun
- "Function for finding the next index position.
-
-If `imenu-create-index-function' is set to
-`imenu-default-create-index-function', then you must set this variable
-to a function that will find the next index, looking backwards in the
-file.
-
-The function should leave point at the place to be connected to the
-index and it should return nil when it doesn't find another index.")
-(make-variable-buffer-local 'imenu-prev-index-position-function)
-
-(defvar imenu-extract-index-name-function nil
- "Function for extracting the index name.
-
-This function is called after the function pointed out by
-`imenu-prev-index-position-function'.")
-(make-variable-buffer-local 'imenu-extract-index-name-function)
-
-(defun imenu--subalist-p (item)
- (and (consp (cdr item)) (listp (cadr item))
- (not (eq (caadr item) 'lambda))))
-
-;;;
-;;; Macro to display a progress message.
-;;; RELPOS is the relative position to display.
-;;; If RELPOS is nil, then the relative position in the buffer
-;;; is calculated.
-;;; PREVPOS is the variable in which we store the last position displayed.
-(defmacro imenu-progress-message (prevpos &optional relpos reverse)
- (` (and
- imenu-scanning-message
- (let ((pos (, (if relpos
- relpos
- (` (imenu--relative-position (, reverse)))))))
- (if (, (if relpos t
- (` (> pos (+ 5 (, prevpos))))))
- (progn
- (message imenu-scanning-message pos)
- (setq (, prevpos) pos)))))))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;
-;;;; Some examples of functions utilizing the framework of this
-;;;; package.
-;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; Return the current/previous sexp and the location of the sexp (its
-;; beginning) without moving the point.
-(defun imenu-example--name-and-position ()
- (save-excursion
- (forward-sexp -1)
- (let ((beg (point))
- (end (progn (forward-sexp) (point)))
- (marker (make-marker)))
- (set-marker marker beg)
- (cons (buffer-substring beg end)
- marker))))
-
-;;;
-;;; Lisp
-;;;
-
-(defun imenu-example--lisp-extract-index-name ()
- ;; Example of a candidate for `imenu-extract-index-name-function'.
- ;; This will generate a flat index of definitions in a lisp file.
- (save-match-data
- (and (looking-at "(def")
- (condition-case nil
- (progn
- (down-list 1)
- (forward-sexp 2)
- (let ((beg (point))
- (end (progn (forward-sexp -1) (point))))
- (buffer-substring beg end)))
- (error nil)))))
-
-(defun imenu-example--create-lisp-index ()
- ;; Example of a candidate for `imenu-create-index-function'.
- ;; It will generate a nested index of definitions.
- (let ((index-alist '())
- (index-var-alist '())
- (index-type-alist '())
- (index-unknown-alist '())
- prev-pos)
- (goto-char (point-max))
- (imenu-progress-message prev-pos 0)
- ;; Search for the function
- (while (beginning-of-defun)
- (imenu-progress-message prev-pos nil t)
- (save-match-data
- (and (looking-at "(def")
- (save-excursion
- (down-list 1)
- (cond
- ((looking-at "def\\(var\\|const\\)")
- (forward-sexp 2)
- (push (imenu-example--name-and-position)
- index-var-alist))
- ((looking-at "def\\(un\\|subst\\|macro\\|advice\\)")
- (forward-sexp 2)
- (push (imenu-example--name-and-position)
- index-alist))
- ((looking-at "def\\(type\\|struct\\|class\\|ine-condition\\)")
- (forward-sexp 2)
- (if (= (char-after (1- (point))) ?\))
- (progn
- (forward-sexp -1)
- (down-list 1)
- (forward-sexp 1)))
- (push (imenu-example--name-and-position)
- index-type-alist))
- (t
- (forward-sexp 2)
- (push (imenu-example--name-and-position)
- index-unknown-alist)))))))
- (imenu-progress-message prev-pos 100)
- (and index-var-alist
- (push (cons "Variables" index-var-alist)
- index-alist))
- (and index-type-alist
- (push (cons "Types" index-type-alist)
- index-alist))
- (and index-unknown-alist
- (push (cons "Syntax-unknown" index-unknown-alist)
- index-alist))
- index-alist))
-
-;; Regular expression to find C functions
-(defvar imenu-example--function-name-regexp-c
- (concat
- "^[a-zA-Z0-9]+[ \t]?" ; type specs; there can be no
- "\\([a-zA-Z0-9_*]+[ \t]+\\)?" ; more than 3 tokens, right?
- "\\([a-zA-Z0-9_*]+[ \t]+\\)?"
- "\\([*&]+[ \t]*\\)?" ; pointer
- "\\([a-zA-Z0-9_*]+\\)[ \t]*(" ; name
- ))
-
-(defun imenu-example--create-c-index (&optional regexp)
- (let ((index-alist '())
- prev-pos char)
- (goto-char (point-min))
- (imenu-progress-message prev-pos 0)
- ;; Search for the function
- (save-match-data
- (while (re-search-forward
- (or regexp imenu-example--function-name-regexp-c)
- nil t)
- (imenu-progress-message prev-pos)
- (backward-up-list 1)
- (save-excursion
- (goto-char (scan-sexps (point) 1))
- (setq char (following-char)))
- ;; Skip this function name if it is a prototype declaration.
- (if (not (eq char ?\;))
- (push (imenu-example--name-and-position) index-alist))))
- (imenu-progress-message prev-pos 100)
- (nreverse index-alist)))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;
-;;; Internal variables
-;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; The item to use in the index for rescanning the buffer.
-(defconst imenu--rescan-item '("*Rescan*" . -99))
-
-;; The latest buffer index.
-;; Buffer local.
-(defvar imenu--index-alist nil)
-(make-variable-buffer-local 'imenu--index-alist)
-
-;; The latest buffer index used to update the menu bar menu.
-(defvar imenu--last-menubar-index-alist nil)
-(make-variable-buffer-local 'imenu--last-menubar-index-alist)
-
-;; History list for 'jump-to-function-in-buffer'.
-;; Making this buffer local caused it not to work!
-(defvar imenu--history-list nil)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;
-;;; Internal support functions
-;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;;
-;;; Sort function
-;;; Sorts the items depending on their index name.
-;;; An item look like (NAME . POSITION).
-;;;
-(defun imenu--sort-by-name (item1 item2)
- (string-lessp (car item1) (car item2)))
-
-(defun imenu--relative-position (&optional reverse)
- ;; Support function to calculate relative position in buffer
- ;; Beginning of buffer is 0 and end of buffer is 100
- ;; If REVERSE is non-nil then the beginning is 100 and the end is 0.
- (let ((pos (point))
- (total (buffer-size)))
- (and reverse (setq pos (- total pos)))
- (if (> total 50000)
- ;; Avoid overflow from multiplying by 100!
- (/ (1- pos) (max (/ total 100) 1))
- (/ (* 100 (1- pos)) (max total 1)))))
-
-;; Split LIST into sublists of max length N.
-;; Example (imenu--split '(1 2 3 4 5 6 7 8) 3)-> '((1 2 3) (4 5 6) (7 8))
-(defun imenu--split (list n)
- (let ((remain list)
- (result '())
- (sublist '())
- (i 0))
- (while remain
- (push (pop remain) sublist)
- (incf i)
- (and (= i n)
- ;; We have finished a sublist
- (progn (push (nreverse sublist) result)
- (setq i 0)
- (setq sublist '()))))
- ;; There might be a sublist (if the length of LIST mod n is != 0)
- ;; that has to be added to the result list.
- (and sublist
- (push (nreverse sublist) result))
- (nreverse result)))
-
-;;; Split the alist MENULIST into a nested alist, if it is long enough.
-;;; In any case, add TITLE to the front of the alist.
-(defun imenu--split-menu (menulist title)
- (let (keep-at-top tail)
- (if (memq imenu--rescan-item menulist)
- (setq keep-at-top (cons imenu--rescan-item nil)
- menulist (delq imenu--rescan-item menulist)))
- (setq tail menulist)
- (while tail
- (if (imenu--subalist-p (car tail))
- (setq keep-at-top (cons (car tail) keep-at-top)
- menulist (delq (car tail) menulist)))
- (setq tail (cdr tail)))
- (if imenu-sort-function
- (setq menulist
- (sort
- (let ((res nil)
- (oldlist menulist))
- ;; Copy list method from the cl package `copy-list'
- (while (consp oldlist) (push (pop oldlist) res))
- (prog1 (nreverse res) (setcdr res oldlist)))
- imenu-sort-function)))
- (if (> (length menulist) imenu-max-items)
- (let ((count 0))
- (setq menulist
- (mapcar
- (function
- (lambda (menu)
- (cons (format "From: %s" (caar menu)) menu)))
- (imenu--split menulist imenu-max-items)))))
- (cons title
- (nconc (nreverse keep-at-top) menulist))))
-
-;;; Split up each long alist that are nested within ALIST
-;;; into nested alists.
-(defun imenu--split-submenus (alist)
- (mapcar (function (lambda (elt)
- (if (and (consp elt)
- (stringp (car elt))
- (listp (cdr elt)))
- (imenu--split-menu (cdr elt) (car elt))
- elt)))
- alist))
-
-(defun imenu--make-index-alist (&optional noerror)
- "Create an index-alist for the definitions in the current buffer.
-
-Simple elements in the alist look like (INDEX-NAME . INDEX-POSITION).
-Special elements look like (INDEX-NAME FUNCTION ARGUMENTS...).
-A nested sub-alist element looks like (INDEX-NAME SUB-ALIST).
-The function `imenu--subalist-p' tests an element and returns t
- if it is a sub-alist.
-
-There is one simple element with negative POSITION; that's intended
-as a way for the user to ask to recalculate the buffer's index alist."
- (or (and imenu--index-alist
- (or (not imenu-auto-rescan)
- (and imenu-auto-rescan
- (> (buffer-size) imenu-auto-rescan-maxout))))
- ;; Get the index
- (setq imenu--index-alist
- (save-excursion
- (save-restriction
- (widen)
- (funcall imenu-create-index-function)))))
- (or imenu--index-alist noerror
- (error "No items suitable for an index found in this buffer"))
- (or imenu--index-alist
- (setq imenu--index-alist (list nil)))
- ;; Add a rescan option to the index.
- (cons imenu--rescan-item imenu--index-alist))
-
-;;; Find all markers in alist and makes
-;;; them point nowhere.
-;;; The top-level call uses nil as the argument;
-;;; non-nil arguments are in recursivecalls.
-(defvar imenu--cleanup-seen)
-
-(defun imenu--cleanup (&optional alist)
- ;; If alist is provided use that list.
- ;; If not, empty the table of lists already seen
- ;; and use imenu--index-alist.
- (if alist
- (setq imenu--cleanup-seen (cons alist imenu--cleanup-seen))
- (setq alist imenu--index-alist imenu--cleanup-seen (list alist)))
-
- (and alist
- (mapcar
- (function
- (lambda (item)
- (cond
- ((markerp (cdr item))
- (set-marker (cdr item) nil))
- ;; Don't process one alist twice.
- ((memq (cdr item) imenu--cleanup-seen))
- ((imenu--subalist-p item)
- (imenu--cleanup (cdr item))))))
- alist)
- t))
-
-(defun imenu--create-keymap-2 (alist counter &optional commands)
- (let ((map nil))
- (mapcar
- (function
- (lambda (item)
- (cond
- ((imenu--subalist-p item)
- (append (list (setq counter (1+ counter))
- (car item) 'keymap (car item))
- (imenu--create-keymap-2 (cdr item) (+ counter 10) commands)))
- (t
- (let ((end (if commands `(lambda () (interactive)
- (imenu--menubar-select ',item))
- (cons '(nil) item))))
- (cons (car item)
- (cons (car item) end))))
- )))
- alist)))
-
-;; If COMMANDS is non-nil, make a real keymap
-;; with a real command used as the definition.
-;; If it is nil, make something suitable for x-popup-menu.
-(defun imenu--create-keymap-1 (title alist &optional commands)
- (append (list 'keymap title) (imenu--create-keymap-2 alist 0 commands)))
-
-
-(defun imenu--in-alist (str alist)
- "Check whether the string STR is contained in multi-level ALIST."
- (let (elt head tail res)
- (setq res nil)
- (while alist
- (setq elt (car alist)
- tail (cdr elt)
- alist (cdr alist)
- head (car elt))
- ;; A nested ALIST element looks like
- ;; (INDEX-NAME (INDEX-NAME . INDEX-POSITION) ...)
- ;; while a bottom-level element looks like
- ;; (INDEX-NAME . INDEX-POSITION)
- ;; We are only interested in the bottom-level elements, so we need to
- ;; recurse if TAIL is a list.
- (cond ((listp tail)
- (if (setq res (imenu--in-alist str tail))
- (setq alist nil)))
- ((string= str head)
- (setq alist nil res elt))))
- res))
-
-(defun imenu-default-create-index-function ()
- "*Wrapper for index searching functions.
-
-Moves point to end of buffer and then repeatedly calls
-`imenu-prev-index-position-function' and `imenu-extract-index-name-function'.
-Their results are gathered into an index alist."
- ;; These should really be done by setting imenu-create-index-function
- ;; in these major modes. But save that change for later.
- (cond ((and (fboundp imenu-prev-index-position-function)
- (fboundp imenu-extract-index-name-function))
- (let ((index-alist '())
- prev-pos name)
- (goto-char (point-max))
- (imenu-progress-message prev-pos 0 t)
- ;; Search for the function
- (while (funcall imenu-prev-index-position-function)
- (imenu-progress-message prev-pos nil t)
- (save-excursion
- (setq name (funcall imenu-extract-index-name-function)))
- (and (stringp name)
- (push (cons name (point)) index-alist)))
- (imenu-progress-message prev-pos 100 t)
- index-alist))
- ;; Use generic expression if possible.
- ((and imenu-generic-expression)
- (imenu--generic-function imenu-generic-expression))
- (t
- (error "The mode `%s' does not support Imenu" mode-name))))
-
-(defun imenu--replace-spaces (name replacement)
- ;; Replace all spaces in NAME with REPLACEMENT.
- ;; That second argument should be a string.
- (mapconcat
- (function
- (lambda (ch)
- (if (char-equal ch ?\ )
- replacement
- (char-to-string ch))))
- name
- ""))
-
-(defun imenu--flatten-index-alist (index-alist &optional concat-names prefix)
- ;; Takes a nested INDEX-ALIST and returns a flat index alist.
- ;; If optional CONCAT-NAMES is non-nil, then a nested index has its
- ;; name and a space concatenated to the names of the children.
- ;; Third argument PREFIX is for internal use only.
- (mapcan
- (function
- (lambda (item)
- (let* ((name (car item))
- (pos (cdr item))
- (new-prefix (and concat-names
- (if prefix
- (concat prefix imenu-level-separator name)
- name))))
- (cond
- ((or (markerp pos) (numberp pos))
- (list (cons new-prefix pos)))
- (t
- (imenu--flatten-index-alist pos new-prefix))))))
- index-alist))
-
-;;;
-;;; Generic index gathering function.
-;;;
-
-(defun imenu--generic-function (patterns)
-;; Built on some ideas that Erik Naggum <erik@naggum.no> once posted
-;; to comp.emacs
- "Return an index of the current buffer as an alist.
-
-PATTERN is an alist with elements that look like this: (MENU-TITLE
-REGEXP INDEX).
-
-MENU-TITLE is a string used as the title for the submenu or nil if the
-entries are not nested.
-
-REGEXP is a regexp that should match a construct in the buffer that is
-to be displayed in the menu; i.e., function or variable definitions,
-etc. It contains a substring which is the name to appear in the
-menu. See the info section on Regexps for more information.
-
-INDEX points to the substring in REGEXP that contains the name (of the
-function, variable or type) that is to appear in the menu.
-
-For emacs-lisp-mode for example PATTERN would look like:
-
-'((nil \"^\\\\s-*(def\\\\(un\\\\|subst\\\\|macro\\\\|advice\\\\)\\\\s-+\\\\([-A-Za-z0-9]+\\\\)\" 2)
- (\"*Vars*\" \"^\\\\s-*(def\\\\(var\\\\|const\\\\)\\\\s-+\\\\([-A-Za-z0-9]+\\\\)\" 2)
- (\"*Types*\" \"^\\\\s-*(def\\\\(type\\\\|struct\\\\|class\\\\|ine-condition\\\\)\\\\s-+\\\\([-A-Za-z0-9]+\\\\)\" 2))'
-
-Returns an index of the current buffer as an alist. The elements in
-the alist look like: (INDEX-NAME . INDEX-POSITION). They may also be
-nested index lists like (INDEX-NAME . INDEX-ALIST) depending on
-pattern.
-
-\(imenu--generic-function PATTERN\)."
-
- (let ((index-alist (list 'dummy))
- (found nil)
- (global-regexp
- (concat "\\("
- (mapconcat
- (function (lambda (pattern) (identity (cadr pattern))))
- patterns "\\)\\|\\(")
- "\\)"))
- prev-pos)
-
- (goto-char (point-max))
- (imenu-progress-message prev-pos 0 t)
- (save-match-data
- (while (re-search-backward global-regexp nil t)
- (imenu-progress-message prev-pos nil t)
- (setq found nil)
- (save-excursion
- (goto-char (match-beginning 0))
- (mapcar
- (function
- (lambda (pat)
- (let ((menu-title (car pat))
- (regexp (cadr pat))
- (index (caddr pat))
- (function (cadddr pat))
- (rest (cddddr pat)))
- (if (and (not found) ; Only allow one entry;
- (looking-at regexp))
- (let ((beg (make-marker))
- (end (match-end index)))
- (set-marker beg (match-beginning index))
- (setq found t)
- (push
- (let ((name
- (buffer-substring-no-properties beg end)))
- (if function
- (nconc (list name function name beg)
- rest)
- (cons name beg)))
- (cdr
- (or (assoc menu-title index-alist)
- (car (push
- (cons menu-title '())
- index-alist))))))))))
- patterns))))
- (imenu-progress-message prev-pos 100 t)
- (let ((main-element (assq nil index-alist)))
- (nconc (delq main-element (delq 'dummy index-alist))
- (cdr main-element)))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;
-;;; The main functions for this package!
-;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun imenu--completion-buffer (index-alist &optional prompt)
- "Let the user select from INDEX-ALIST in a completion buffer with PROMPT.
-
-Returns t for rescan and otherwise a position number."
- ;; Create a list for this buffer only when needed.
- (let (name choice
- (prepared-index-alist
- (mapcar
- (function
- (lambda (item)
- (cons (imenu--replace-spaces (car item) imenu-space-replacement)
- (cdr item))))
- index-alist)))
- (if (eq imenu-always-use-completion-buffer-p 'never)
- (setq name (completing-read (or prompt "Index item: ")
- prepared-index-alist
- nil t nil 'imenu--history-list))
- (save-window-excursion
- ;; Display the completion buffer
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list
- (all-completions "" prepared-index-alist )))
- (let ((minibuffer-setup-hook
- (function (lambda ()
- (let ((buffer (current-buffer)))
- (save-excursion
- (set-buffer "*Completions*")
- (setq completion-reference-buffer buffer)))))))
- ;; Make a completion question
- (setq name (completing-read (or prompt "Index item: ")
- prepared-index-alist
- nil t nil 'imenu--history-list)))))
- (cond ((not (stringp name))
- nil)
- ((string= name (car imenu--rescan-item))
- t)
- (t
- (setq choice (assoc name prepared-index-alist))
- (if (imenu--subalist-p choice)
- (imenu--completion-buffer (cdr choice) prompt)
- choice)))))
-
-(defun imenu--mouse-menu (index-alist event &optional title)
- "Let the user select from a buffer index from a mouse menu.
-
-INDEX-ALIST is the buffer index and EVENT is a mouse event.
-
-Returns t for rescan and otherwise an element or subelement of INDEX-ALIST."
- (setq index-alist (imenu--split-submenus index-alist))
- (let* ((menu (imenu--split-menu index-alist
- (or title (buffer-name))))
- position)
- (setq menu (imenu--create-keymap-1 (car menu)
- (if (< 1 (length (cdr menu)))
- (cdr menu)
- (cdr (car (cdr menu))))))
- (setq position (x-popup-menu event menu))
- (cond ((eq position nil)
- position)
- ;; If one call to x-popup-menu handled the nested menus,
- ;; find the result by looking down the menus here.
- ((and (listp position)
- (numberp (car position))
- (stringp (nth (1- (length position)) position)))
- (let ((final menu))
- (while position
- (setq final (assoc (car position) final))
- (setq position (cdr position)))
- (or (string= (car final) (car imenu--rescan-item))
- (cdr (cdr (cdr final))))))
- ;; If x-popup-menu went just one level and found a leaf item,
- ;; return the INDEX-ALIST element for that.
- ((and (consp position)
- (stringp (car position))
- (null (cdr position)))
- (or (string= (car position) (car imenu--rescan-item))
- (assq (car position) index-alist)))
- ;; If x-popup-menu went just one level
- ;; and found a non-leaf item (a submenu),
- ;; recurse to handle the rest.
- ((listp position)
- (imenu--mouse-menu position event
- (if title
- (concat title imenu-level-separator
- (car (rassq position index-alist)))
- (car (rassq position index-alist))))))))
-
-(defun imenu-choose-buffer-index (&optional prompt alist)
- "Let the user select from a buffer index and return the chosen index.
-
-If the user originally activated this function with the mouse, a mouse
-menu is used. Otherwise a completion buffer is used and the user is
-prompted with PROMPT.
-
-If you call this function with index alist ALIST, then it lets the user
-select from ALIST.
-
-With no index alist ALIST, it calls `imenu--make-index-alist' to
-create the index alist.
-
-If `imenu-always-use-completion-buffer-p' is non-nil, then the
-completion buffer is always used, no matter if the mouse was used or
-not.
-
-The returned value is of the form (INDEX-NAME . INDEX-POSITION)."
- (let (index-alist
- (mouse-triggered (listp last-nonmenu-event))
- (result t) )
- ;; If selected by mouse, see to that the window where the mouse is
- ;; really is selected.
- (and mouse-triggered
- (not (equal last-nonmenu-event '(menu-bar)))
- (let ((window (posn-window (event-start last-nonmenu-event))))
- (or (framep window) (null window) (select-window window))))
- ;; Create a list for this buffer only when needed.
- (while (eq result t)
- (setq index-alist (if alist alist (imenu--make-index-alist)))
- (setq result
- (if (and mouse-triggered
- (not imenu-always-use-completion-buffer-p))
- (imenu--mouse-menu index-alist last-nonmenu-event)
- (imenu--completion-buffer index-alist prompt)))
- (and (eq result t)
- (imenu--cleanup)
- (setq imenu--index-alist nil)))
- result))
-
-;;;###autoload
-(defun imenu-add-to-menubar (name)
- "Adds an `imenu' entry to the menu bar for the current buffer.
-NAME is a string used to name the menu bar item.
-See the command `imenu' for more information."
- (interactive "sImenu menu item name: ")
- (let ((newmap (make-sparse-keymap))
- (menu-bar (lookup-key (current-local-map) [menu-bar])))
- (define-key newmap [menu-bar]
- (append (make-sparse-keymap) menu-bar))
- (define-key newmap [menu-bar index]
- (cons name (nconc (make-sparse-keymap "Imenu")
- (make-sparse-keymap))))
- (use-local-map (append newmap (current-local-map))))
- (add-hook 'menu-bar-update-hook 'imenu-update-menubar))
-
-(defvar imenu-buffer-menubar nil)
-
-(defun imenu-update-menubar ()
- (and (current-local-map)
- (keymapp (lookup-key (current-local-map) [menu-bar index]))
- (let ((index-alist (imenu--make-index-alist t)))
- ;; Don't bother updating if the index-alist has not changed
- ;; since the last time we did it.
- (or (equal index-alist imenu--last-menubar-index-alist)
- (let (menu menu1 old)
- (setq imenu--last-menubar-index-alist index-alist)
- (setq index-alist (imenu--split-submenus index-alist))
- (setq menu (imenu--split-menu index-alist
- (buffer-name)))
- (setq menu1 (imenu--create-keymap-1 (car menu)
- (if (< 1 (length (cdr menu)))
- (cdr menu)
- (cdr (car (cdr menu))))
- t))
- (setq old (lookup-key (current-local-map) [menu-bar index]))
- (setcdr old (cdr menu1)))))))
-
-(defun imenu--menubar-select (item)
- "Use Imenu to select the function or variable named in this menu item."
- (if (equal item '("*Rescan*" . -99))
- (progn
- (imenu--cleanup)
- (setq imenu--index-alist nil)
- (imenu-update-menubar))
- (imenu item)))
-
-;;;###autoload
-(defun imenu (index-item)
- "Jump to a place in the buffer chosen using a buffer menu or mouse menu.
-See `imenu-choose-buffer-index' for more information."
- (interactive (list (imenu-choose-buffer-index)))
- ;; Convert a string to an alist element.
- (if (stringp index-item)
- (setq index-item (assoc index-item (imenu--make-index-alist))))
- (and index-item
- (progn
- (push-mark)
- (cond
- ((markerp (cdr index-item))
- (if (or (< (marker-position (cdr index-item)) (point-min))
- (> (marker-position (cdr index-item)) (point-max)))
- ;; widen if outside narrowing
- (widen))
- (goto-char (marker-position (cdr index-item))))
- ((imenu--subalist-p index-item)
- (if (or (< (cdr index-item) (point-min))
- (> (cdr index-item) (point-max)))
- ;; widen if outside narrowing
- (widen))
- (goto-char (cdr index-item)))
- ((integerp (cdr index-item))
- (if (or (< (cdr index-item) (point-min))
- (> (cdr index-item) (point-max)))
- ;; widen if outside narrowing
- (widen))
- (goto-char (cdr index-item)))
- (t
- ;; A special item with a function.
- (let ((function (cadr index-item))
- (rest (cddr index-item)))
- (apply function (car index-item) rest)))))))
-
-(provide 'imenu)
-
-;;; imenu.el ends here
diff --git a/lisp/indent.el b/lisp/indent.el
deleted file mode 100644
index c1e2fc2e132..00000000000
--- a/lisp/indent.el
+++ /dev/null
@@ -1,467 +0,0 @@
-;;; indent.el --- indentation commands for Emacs
-
-;; Copyright (C) 1985, 1995 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Commands for making and changing indentation in text. These are
-;; described in the Emacs manual.
-
-;;; Code:
-
-(defvar standard-indent 4 "\
-Default number of columns for margin-changing functions to indent.")
-
-(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 (&optional prefix-arg)
- "Indent line in proper way for current major mode."
- (interactive "P")
- (if (eq indent-line-function 'indent-to-left-margin)
- (insert-tab prefix-arg)
- (if prefix-arg
- (funcall indent-line-function prefix-arg)
- (funcall indent-line-function))))
-
-(defun insert-tab (&optional prefix-arg)
- (let ((count (prefix-numeric-value prefix-arg)))
- (if abbrev-mode
- (expand-abbrev))
- (if indent-tabs-mode
- (insert-char ?\t count)
- (indent-to (* tab-width (+ count (/ (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))
- eol-flag)
- (save-excursion
- (skip-chars-forward " \t")
- (setq eol-flag (eolp)))
- (or eol-flag
- (indent-to (max 0 (+ indent arg)) 0))
- (delete-region (point) (progn (skip-chars-forward " \t") (point))))
- (forward-line 1))
- (move-marker end nil)))
-
-(defun indent-line-to (column)
- "Indent current line to COLUMN.
-This function removes or adds spaces and tabs at beginning of line
-only if necessary. It leaves point at end of indentation."
- (back-to-indentation)
- (let ((cur-col (current-column)))
- (cond ((< cur-col column)
- (if (> (- column (* (/ cur-col tab-width) tab-width)) tab-width)
- (delete-region (point)
- (progn (skip-chars-backward " ") (point))))
- (indent-to column))
- ((> cur-col column) ; too far right (after tab?)
- (delete-region (progn (move-to-column column t) (point))
- (progn (back-to-indentation) (point)))))))
-
-(defun current-left-margin ()
- "Return the left margin to use for this line.
-This is the value of the buffer-local variable `left-margin' plus the value
-of the `left-margin' text-property at the start of the line."
- (save-excursion
- (back-to-indentation)
- (max 0
- (+ left-margin (or (get-text-property
- (if (and (eobp) (not (bobp)))
- (1- (point)) (point))
- 'left-margin) 0)))))
-
-(defun move-to-left-margin (&optional n force)
- "Move to the left margin of the current line.
-With optional argument, move forward N-1 lines first.
-The column moved to is the one given by the `current-left-margin' function.
-If the line's indentation appears to be wrong, and this command is called
-interactively or with optional argument FORCE, it will be fixed."
- (interactive (list (prefix-numeric-value current-prefix-arg) t))
- (beginning-of-line n)
- (skip-chars-forward " \t")
- (let ((lm (current-left-margin))
- (cc (current-column)))
- (cond ((> cc lm)
- (if (> (move-to-column lm force) lm)
- ;; If lm is in a tab and we are not forcing, move before tab
- (backward-char 1)))
- ((and force (< cc lm))
- (indent-to-left-margin)))))
-
-;; This is the default indent-line-function,
-;; used in Fundamental Mode, Text Mode, etc.
-(defun indent-to-left-margin ()
- "Indent current line to the column given by `current-left-margin'."
- (indent-line-to (current-left-margin)))
-
-(defun delete-to-left-margin (&optional from to)
- "Remove left margin indentation from a region.
-This deletes to the column given by `current-left-margin'.
-In no case will it delete non-whitespace.
-Args FROM and TO are optional; default is the whole buffer."
- (save-excursion
- (goto-char (or to (point-max)))
- (setq to (point-marker))
- (goto-char (or from (point-min)))
- (or (bolp) (forward-line 1))
- (while (< (point) to)
- (delete-region (point) (progn (move-to-left-margin nil t) (point)))
- (forward-line 1))
- (move-marker to nil)))
-
-(defun set-left-margin (from to lm)
- "Set the left margin of the region to WIDTH.
-If `auto-fill-mode' is active, re-fill the region to fit the new margin."
- (interactive "r\nNSet left margin to column: ")
- (if (interactive-p) (setq lm (prefix-numeric-value lm)))
- (save-excursion
- ;; If inside indentation, start from BOL.
- (goto-char from)
- (skip-chars-backward " \t")
- (if (bolp) (setq from (point)))
- ;; Place end after whitespace
- (goto-char to)
- (skip-chars-forward " \t")
- (setq to (point-marker)))
- ;; Delete margin indentation first, but keep paragraph indentation.
- (delete-to-left-margin from to)
- (put-text-property from to 'left-margin lm)
- (indent-rigidly from to lm)
- (if auto-fill-function (save-excursion (fill-region from to nil t t)))
- (move-marker to nil))
-
-(defun set-right-margin (from to lm)
- "Set the right margin of the region to WIDTH.
-If `auto-fill-mode' is active, re-fill the region to fit the new margin."
- (interactive "r\nNSet right margin to width: ")
- (if (interactive-p) (setq lm (prefix-numeric-value lm)))
- (save-excursion
- (goto-char from)
- (skip-chars-backward " \t")
- (if (bolp) (setq from (point))))
- (put-text-property from to 'right-margin lm)
- (if auto-fill-function (save-excursion (fill-region from to nil t t))))
-
-(defun alter-text-property (from to prop func &optional object)
- "Programmatically change value of a text-property.
-For each region between FROM and TO that has a single value for PROPERTY,
-apply FUNCTION to that value and sets the property to the function's result.
-Optional fifth argument OBJECT specifies the string or buffer to operate on."
- (let ((begin from)
- end val)
- (while (setq val (get-text-property begin prop object)
- end (text-property-not-all begin to prop val object))
- (put-text-property begin end prop (funcall func val) object)
- (setq begin end))
- (if (< begin to)
- (put-text-property begin to prop (funcall func val) object))))
-
-(defun increase-left-margin (from to inc)
- "Increase or decrease the left-margin of the region.
-With no prefix argument, this adds `standard-indent' of indentation.
-A prefix arg (optional third arg INC noninteractively) specifies the amount
-to change the margin by, in characters.
-If `auto-fill-mode' is active, re-fill the region to fit the new margin."
- (interactive "*r\nP")
- (setq inc (if inc (prefix-numeric-value inc) standard-indent))
- (save-excursion
- (goto-char from)
- (skip-chars-backward " \t")
- (if (bolp) (setq from (point)))
- (goto-char to)
- (setq to (point-marker)))
- (alter-text-property from to 'left-margin
- (lambda (v) (max (- left-margin) (+ inc (or v 0)))))
- (indent-rigidly from to inc)
- (if auto-fill-function (save-excursion (fill-region from to nil t t)))
- (move-marker to nil))
-
-(defun decrease-left-margin (from to inc)
- "Make the left margin of the region smaller.
-With no prefix argument, decrease the indentation by `standard-indent'.
-A prefix arg (optional third arg INC noninteractively) specifies the amount
-to change the margin by, in characters.
-If `auto-fill-mode' is active, re-fill the region to fit the new margin."
- (interactive "*r\nP")
- (setq inc (if inc (prefix-numeric-value inc) standard-indent))
- (increase-left-margin from to (- inc)))
-
-(defun increase-right-margin (from to inc)
- "Increase the right-margin of the region.
-With no prefix argument, increase the right margin by `standard-indent'.
-A prefix arg (optional third arg INC noninteractively) specifies the amount
-to change the margin by, in characters. A negative argument decreases
-the right margin width.
-If `auto-fill-mode' is active, re-fill the region to fit the new margin."
- (interactive "r\nP")
- (if (interactive-p)
- (setq inc (if inc (prefix-numeric-value current-prefix-arg)
- standard-indent)))
- (save-excursion
- (alter-text-property from to 'right-margin
- (lambda (v) (+ inc (or v 0))))
- (if auto-fill-function
- (fill-region from to nil t t))))
-
-(defun decrease-right-margin (from to inc)
- "Make the right margin of the region smaller.
-With no prefix argument, decrease the right margin by `standard-indent'.
-A prefix arg (optional third arg INC noninteractively) specifies the amount
-of width to remove, in characters. A negative argument increases
-the right margin width.
-If `auto-fill-mode' is active, re-fills region to fit in new margin."
- (interactive "*r\nP")
- (setq inc (if inc (prefix-numeric-value inc) standard-indent))
- (increase-right-margin from to (- inc)))
-
-(defun beginning-of-line-text (&optional n)
- "Move to the beginning of the text on this line.
-With optional argument, move forward N-1 lines first.
-From the beginning of the line, moves past the left-margin indentation, the
-fill-prefix, and any indentation used for centering or right-justifying the
-line, but does not move past any whitespace that was explicitly inserted
-\(such as a tab used to indent the first line of a paragraph)."
- (interactive "p")
- (beginning-of-line n)
- (skip-chars-forward " \t")
- ;; Skip over fill-prefix.
- (if (and fill-prefix
- (not (string-equal fill-prefix "")))
- (if (equal fill-prefix
- (buffer-substring
- (point) (min (point-max) (+ (length fill-prefix) (point)))))
- (forward-char (length fill-prefix)))
- (if (and adaptive-fill-mode adaptive-fill-regexp
- (looking-at adaptive-fill-regexp))
- (goto-char (match-end 0))))
- ;; Skip centering or flushright indentation
- (if (memq (current-justification) '(center right))
- (skip-chars-forward " \t")))
-
-(defvar indent-region-function nil
- "Short cut function to indent region using `indent-according-to-mode'.
-A value of nil means really run `indent-according-to-mode' on each line.")
-
-(defun indent-region (start end column)
- "Indent each nonblank line in the region.
-With no argument, indent each line using `indent-according-to-mode',
-or use `indent-region-function' to do the whole region if that's non-nil.
-If there is a fill prefix, make each line start with the fill prefix.
-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 column)
- (if fill-prefix
- (save-excursion
- (goto-char end)
- (setq end (point-marker))
- (goto-char start)
- (let ((regexp (regexp-quote fill-prefix)))
- (while (< (point) end)
- (or (looking-at regexp)
- (and (bolp) (eolp))
- (insert fill-prefix))
- (forward-line 1))))
- (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)
- (or (and (bolp) (eolp))
- (funcall indent-line-function))
- (forward-line 1))
- (move-marker end nil))))
- (setq column (prefix-numeric-value column))
- (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 column 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'.
-This should be a list of integers, ordered from smallest to largest.")
-
-(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 \\<edit-tab-stops-map>\\[edit-tab-stops-note-changes] 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)
- (and abbrev-mode (= (char-syntax (preceding-char)) ?w)
- (expand-abbrev))
- (let ((tabs tab-stop-list))
- (while (and tabs (>= (current-column) (car tabs)))
- (setq tabs (cdr tabs)))
- (if tabs
- (let ((opoint (point)))
- (skip-chars-backward " \t")
- (delete-region (point) opoint)
- (indent-to (car tabs)))
- (insert ?\ ))))
-
-(defun move-to-tab-stop ()
- "Move point 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)
- (let ((tabs tab-stop-list))
- (while (and tabs (>= (current-column) (car tabs)))
- (setq tabs (cdr tabs)))
- (if tabs
- (let ((before (point)))
- (move-to-column (car tabs) t)
- (save-excursion
- (goto-char before)
- ;; If we just added a tab, or moved over one,
- ;; delete any superfluous spaces before the old point.
- (if (and (eq (preceding-char) ?\ )
- (eq (following-char) ?\t))
- (let ((tabend (* (/ (current-column) tab-width) tab-width)))
- (while (and (> (current-column) tabend)
- (eq (preceding-char) ?\ ))
- (forward-char -1))
- (delete-region (point) before))))))))
-
-(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)
-
-;;; indent.el ends here
diff --git a/lisp/info.el b/lisp/info.el
deleted file mode 100644
index 63076dfa93b..00000000000
--- a/lisp/info.el
+++ /dev/null
@@ -1,1968 +0,0 @@
-;;; info.el --- info package for Emacs.
-
-;; Copyright (C) 1985, 1986, 1992, 1993, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: help
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Note that nowadays we expect info files to be made using makeinfo.
-
-;;; Code:
-
-(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-mode-map>\\[Info-edit] command in Info can edit the current node.
-This is convenient if you want to write info files by hand.
-However, we recommend that you not do this.
-It is better to write a Texinfo file and generate the Info file from that,
-because that gives you a printed manual as well.")
-
-(defvar Info-enable-active-nodes nil
- "Non-nil allows Info to execute Lisp code associated with nodes.
-The Lisp code is executed when the node is selected.")
-(put 'Info-enable-active-nodes 'risky-local-variable t)
-
-(defvar Info-fontify t
- "*Non-nil enables highlighting and fonts in Info nodes.")
-
-(defvar Info-fontify-maximum-menu-size 30000
- "*Maximum size of menu to fontify if `Info-fontify' is non-nil.")
-
-(defvar Info-directory-list
- (let ((path (getenv "INFOPATH"))
- ;; This is for older Emacs versions
- ;; which might get this info.el from the Texinfo distribution.
- (path-separator (if (boundp 'path-separator) path-separator
- (if (eq system-type 'ms-dos) ";" ":")))
- (source (expand-file-name "info/" source-directory))
- (sibling (if installation-directory
- (expand-file-name "info/" installation-directory)))
- alternative)
- (if path
- (let ((list nil)
- idx)
- (while (> (length path) 0)
- (setq idx (or (string-match path-separator path) (length path))
- list (cons (substring path 0 idx) list)
- path (substring path (min (1+ idx)
- (length path)))))
- (nreverse list))
- (if (and sibling (file-exists-p sibling))
- (setq alternative sibling)
- (setq alternative source))
- (if (or (member alternative Info-default-directory-list)
- (not (file-exists-p alternative))
- ;; On DOS/NT, we use movable executables always,
- ;; and we must always find the Info dir at run time.
- (if (or (eq system-type 'ms-dos) (eq system-type 'windows-nt))
- nil
- ;; Use invocation-directory for Info only if we used it for
- ;; exec-directory also.
- (not (string= exec-directory
- (expand-file-name "lib-src/"
- installation-directory)))))
- Info-default-directory-list
- (reverse (cons alternative
- (cdr (reverse Info-default-directory-list)))))))
- "List of directories to search for Info documentation files.
-nil means not yet initialized. In this case, Info uses the environment
-variable INFOPATH to initialize it, or `Info-default-directory-list'
-if there is no INFOPATH variable in the environment.
-The last element of `Info-default-directory-list' is the directory
-where Emacs installs the Info files that come with it.
-
-If you run the Emacs executable from the `src' directory in the Emacs
-source tree, the `info' directory in the source tree is used as the last
-element, in place of the installation Info directory. This is useful
-when you run a version of Emacs without installing it.")
-
-(defvar Info-additional-directory-list nil
- "List of additional directories to search for Info documentation files.
-These directories are not searched for merging the `dir' file.")
-
-(defvar Info-current-file nil
- "Info file that Info is now looking at, or nil.
-This is the name that was specified in Info, not the actual file name.
-It doesn't contain directory names or file name extensions added by Info.")
-
-(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.")
-
-(defvar Info-current-file-completions nil
- "Cached completion list for current Info file.")
-
-(defvar Info-index-alternatives nil
- "List of possible matches for last Info-index command.")
-
-(defvar Info-standalone nil
- "Non-nil if Emacs was started solely as an Info browser.")
-
-(defvar Info-suffix-list
- (if (eq system-type 'ms-dos)
- '( (".gz" . "gunzip")
- (".z" . "gunzip")
- (".inf" . nil)
- ("" . nil))
- '( (".info.Z" . "uncompress")
- (".info.Y" . "unyabba")
- (".info.gz" . "gunzip")
- (".info.z" . "gunzip")
- (".info" . nil)
- (".Z" . "uncompress")
- (".Y" . "unyabba")
- (".gz" . "gunzip")
- (".z" . "gunzip")
- ("" . nil)))
- "List of file name suffixes and associated decoding commands.
-Each entry should be (SUFFIX . STRING); the file is given to
-the command as standard input. If STRING is nil, no decoding is done.
-Because the SUFFIXes are tried in order, the empty string should
-be last in the list.")
-
-;; Concatenate SUFFIX onto FILENAME. SUFFIX should start with a dot.
-;; First, on ms-dos, delete some of the extension in FILENAME
-;; to make room.
-(defun info-insert-file-contents-1 (filename suffix)
- (if (not (eq system-type 'ms-dos))
- (concat filename suffix)
- (let* ((sans-exts (file-name-sans-extension filename))
- ;; How long is the extension in FILENAME (not counting the dot).
- (ext-len (max 0 (- (length filename) (length sans-exts) 1)))
- ext-left)
- ;; SUFFIX starts with a dot. If FILENAME already has one,
- ;; get rid of the one in SUFFIX (unless suffix is empty).
- (or (and (<= ext-len 0)
- (not (eq (aref filename (1- (length filename))) ?.)))
- (= (length suffix) 0)
- (setq suffix (substring suffix 1)))
- ;; How many chars of that extension should we keep?
- (setq ext-left (min ext-len (max 0 (- 3 (length suffix)))))
- ;; Get rid of the rest of the extension, and add SUFFIX.
- (concat (substring filename 0 (- (length filename)
- (- ext-len ext-left)))
- suffix))))
-
-(defun info-insert-file-contents (filename &optional visit)
- "Insert the contents of an info file in the current buffer.
-Do the right thing if the file has been compressed or zipped."
- (let ((tail Info-suffix-list)
- fullname decoder)
- (if (file-exists-p filename)
- ;; FILENAME exists--see if that name contains a suffix.
- ;; If so, set DECODE accordingly.
- (progn
- (while (and tail
- (not (string-match
- (concat (regexp-quote (car (car tail))) "$")
- filename)))
- (setq tail (cdr tail)))
- (setq fullname filename
- decoder (cdr (car tail))))
- ;; Try adding suffixes to FILENAME and see if we can find something.
- (while (and tail
- (not (file-exists-p (info-insert-file-contents-1
- filename (car (car tail))))))
- (setq tail (cdr tail)))
- ;; If we found a file with a suffix, set DECODER according to the suffix
- ;; and set FULLNAME to the file's actual name.
- (setq fullname (info-insert-file-contents-1 filename (car (car tail)))
- decoder (cdr (car tail)))
- (or tail
- (error "Can't find %s or any compressed version of it" filename)))
- ;; check for conflict with jka-compr
- (if (and (featurep 'jka-compr)
- (jka-compr-installed-p)
- (jka-compr-get-compression-info fullname))
- (setq decoder nil))
- (insert-file-contents fullname visit)
- (if decoder
- (let ((buffer-read-only nil)
- (default-directory (or (file-name-directory fullname)
- default-directory)))
- (call-process-region (point-min) (point-max) decoder t t)))))
-
-;;;###autoload (add-hook 'same-window-buffer-names "*info*")
-
-;;;###autoload
-(defun info (&optional file)
- "Enter Info, the documentation browser.
-Optional argument FILE specifies the file to examine;
-the default is the top-level directory of Info.
-
-In interactive use, a prefix argument directs this command
-to read a file name from the minibuffer.
-
-The search path for Info files is in the variable `Info-directory-list'.
-The top-level Info directory is made by combining all the files named `dir'
-in all the directories in that path."
- (interactive (if current-prefix-arg
- (list (read-file-name "Info file name: " nil nil t))))
- (if file
- (Info-goto-node (concat "(" file ")"))
- (if (get-buffer "*info*")
- (pop-to-buffer "*info*")
- (Info-directory))))
-
-;;;###autoload
-(defun info-standalone ()
- "Run Emacs as a standalone Info reader.
-Usage: emacs -f info-standalone [filename]
-In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself."
- (setq Info-standalone t)
- (if (and command-line-args-left
- (not (string-match "^-" (car command-line-args-left))))
- (condition-case err
- (progn
- (info (car command-line-args-left))
- (setq command-line-args-left (cdr command-line-args-left)))
- (error (send-string-to-terminal
- (format "%s\n" (if (eq (car-safe err) 'error)
- (nth 1 err) err)))
- (save-buffers-kill-emacs)))
- (info)))
-
-;; 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 temp-downcase found)
- (setq filename (substitute-in-file-name filename))
- (if (string= (downcase filename) "dir")
- (setq found t)
- (let ((dirs (if (string-match "^\\./" filename)
- ;; If specified name starts with `./'
- ;; then just try current directory.
- '("./")
- (if (file-name-absolute-p filename)
- ;; No point in searching for an
- ;; absolute file name
- '(nil)
- (if Info-additional-directory-list
- (append Info-directory-list
- Info-additional-directory-list)
- Info-directory-list)))))
- ;; Search the directory list for file FILENAME.
- (while (and dirs (not found))
- (setq temp (expand-file-name filename (car dirs)))
- (setq temp-downcase
- (expand-file-name (downcase filename) (car dirs)))
- ;; Try several variants of specified name.
- (let ((suffix-list Info-suffix-list))
- (while (and suffix-list (not found))
- (cond ((file-exists-p
- (info-insert-file-contents-1
- temp (car (car suffix-list))))
- (setq found temp))
- ((file-exists-p
- (info-insert-file-contents-1
- temp-downcase (car (car suffix-list))))
- (setq found temp-downcase)))
- (setq suffix-list (cdr suffix-list))))
- (setq dirs (cdr dirs)))))
- (if found
- (setq filename found)
- (error "Info file %s does not exist" filename))))
- ;; 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.
- (pop-to-buffer "*info*")
- (buffer-disable-undo (current-buffer))
- (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
- Info-current-file-completions nil
- buffer-file-name nil)
- (erase-buffer)
- (if (eq filename t)
- (Info-insert-dir)
- (info-insert-file-contents filename t)
- (setq default-directory (file-name-directory filename)))
- (set-buffer-modified-p nil)
- ;; 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)
- ;; Use string-equal, not equal, to ignore text props.
- (or (string-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*"))
- (buffer-disable-undo (current-buffer))
- (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
- (if (eq filename t) "dir" filename))))
- ;; Use string-equal, not equal, to ignore text props.
- (if (string-equal nodename "*")
- (progn (setq Info-current-node nodename)
- (Info-set-mode-line))
- ;; Search file for a suitable node.
- (let ((guesspos (point-min))
- (regexp (concat "Node: *" (regexp-quote nodename) " *[,\t\n\177]")))
- ;; 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.
- (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 (null Info-history)
- (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)))
-
-;; Cache the contents of the (virtual) dir file, once we have merged
-;; it for the first time, so we can save time subsequently.
-(defvar Info-dir-contents nil)
-
-;; Cache for the directory we decided to use for the default-directory
-;; of the merged dir text.
-(defvar Info-dir-contents-directory nil)
-
-;; Record the file attributes of all the files from which we
-;; constructed Info-dir-contents.
-(defvar Info-dir-file-attributes nil)
-
-;; Construct the Info directory node by merging the files named `dir'
-;; from various directories. Set the *info* buffer's
-;; default-directory to the first directory we actually get any text
-;; from.
-(defun Info-insert-dir ()
- (if (and Info-dir-contents Info-dir-file-attributes
- ;; Verify that none of the files we used has changed
- ;; since we used it.
- (eval (cons 'and
- (mapcar '(lambda (elt)
- (let ((curr (file-attributes (car elt))))
- ;; Don't compare the access time.
- (if curr (setcar (nthcdr 4 curr) 0))
- (setcar (nthcdr 4 (cdr elt)) 0)
- (equal (cdr elt) curr)))
- Info-dir-file-attributes))))
- (insert Info-dir-contents)
- (let ((dirs Info-directory-list)
- buffers buffer others nodes dirs-done)
-
- (setq Info-dir-file-attributes nil)
-
- ;; Search the directory list for the directory file.
- (while dirs
- (let ((truename (file-truename (expand-file-name (car dirs)))))
- (or (member truename dirs-done)
- (member (directory-file-name truename) dirs-done)
- ;; Try several variants of specified name.
- ;; Try upcasing, appending `.info', or both.
- (let* (file
- (attrs
- (or
- (progn (setq file (expand-file-name "dir" truename))
- (file-attributes file))
- (progn (setq file (expand-file-name "DIR" truename))
- (file-attributes file))
- (progn (setq file (expand-file-name "dir.info" truename))
- (file-attributes file))
- (progn (setq file (expand-file-name "DIR.INFO" truename))
- (file-attributes file)))))
- (setq dirs-done
- (cons truename
- (cons (directory-file-name truename)
- dirs-done)))
- (if attrs
- (save-excursion
- (or buffers
- (message "Composing main Info directory..."))
- (set-buffer (generate-new-buffer "info dir"))
- (insert-file-contents file)
- (setq buffers (cons (current-buffer) buffers)
- Info-dir-file-attributes
- (cons (cons file attrs)
- Info-dir-file-attributes))))))
- (or (cdr dirs) (setq Info-dir-contents-directory
- (file-name-as-directory (car dirs))))
- (setq dirs (cdr dirs))))
-
- (or buffers
- (error "Can't find the Info directory node"))
- ;; Distinguish the dir file that comes with Emacs from all the
- ;; others. Yes, that is really what this is supposed to do.
- ;; If it doesn't work, fix it.
- (setq buffer (car buffers)
- others (cdr buffers))
-
- ;; Insert the entire original dir file as a start; note that we've
- ;; already saved its default directory to use as the default
- ;; directory for the whole concatenation.
- (insert-buffer buffer)
-
- ;; Look at each of the other buffers one by one.
- (while others
- (let ((other (car others)))
- ;; In each, find all the menus.
- (save-excursion
- (set-buffer other)
- (goto-char (point-min))
- ;; Find each menu, and add an elt to NODES for it.
- (while (re-search-forward "^\\* Menu:" nil t)
- (let (beg nodename end)
- (forward-line 1)
- (setq beg (point))
- (search-backward "\n\^_")
- (search-forward "Node: ")
- (setq nodename (Info-following-node-name))
- (search-forward "\n\^_" nil 'move)
- (beginning-of-line)
- (setq end (point))
- (setq nodes (cons (list nodename other beg end) nodes))))))
- (setq others (cdr others)))
- ;; Add to the main menu a menu item for each other node.
- (re-search-forward "^\\* Menu:")
- (forward-line 1)
- (let ((menu-items '("top"))
- (nodes nodes)
- (case-fold-search t)
- (end (save-excursion (search-forward "\^_" nil t) (point))))
- (while nodes
- (let ((nodename (car (car nodes))))
- (save-excursion
- (or (member (downcase nodename) menu-items)
- (re-search-forward (concat "^\\* "
- (regexp-quote nodename)
- "::")
- end t)
- (progn
- (insert "* " nodename "::" "\n")
- (setq menu-items (cons nodename menu-items))))))
- (setq nodes (cdr nodes))))
- ;; Now take each node of each of the other buffers
- ;; and merge it into the main buffer.
- (while nodes
- (let ((nodename (car (car nodes))))
- (goto-char (point-min))
- ;; Find the like-named node in the main buffer.
- (if (re-search-forward (concat "\n\^_.*\n.*Node: "
- (regexp-quote nodename)
- "[,\n\t]")
- nil t)
- (progn
- (search-forward "\n\^_" nil 'move)
- (beginning-of-line)
- (insert "\n"))
- ;; If none exists, add one.
- (goto-char (point-max))
- (insert "\^_\nFile: dir\tNode: " nodename "\n\n* Menu:\n\n"))
- ;; Merge the text from the other buffer's menu
- ;; into the menu in the like-named node in the main buffer.
- (apply 'insert-buffer-substring (cdr (car nodes))))
- (setq nodes (cdr nodes)))
- ;; Kill all the buffers we just made.
- (while buffers
- (kill-buffer (car buffers))
- (setq buffers (cdr buffers)))
- (message "Composing main Info directory...done"))
- (setq Info-dir-contents (buffer-string)))
- (setq default-directory Info-dir-contents-directory))
-
-(defun Info-read-subfile (nodepos)
- ;; NODEPOS is either a position (in the Info file as a whole,
- ;; not relative to a subfile) or the name of a subfile.
- (let (lastfilepos
- lastfilename)
- (if (numberp nodepos)
- (save-excursion
- (set-buffer (marker-buffer Info-tag-table-marker))
- (goto-char (point-min))
- (search-forward "\n\^_")
- (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)))
- ;; read in version 19 stops at the end of number.
- ;; Advance to the next line.
- (forward-line 1)
- (if (> thisfilepos nodepos)
- (throw 'foo t))
- (setq lastfilename thisfilename)
- (setq lastfilepos thisfilepos))
- (forward-line 1)))))
- (setq lastfilename nodepos)
- (setq lastfilepos 0))
- (set-buffer (get-buffer "*info*"))
- (or (equal Info-current-subfile lastfilename)
- (let ((buffer-read-only nil))
- (setq buffer-file-name nil)
- (widen)
- (erase-buffer)
- (info-insert-file-contents lastfilename)
- (set-buffer-modified-p nil)
- (setq Info-current-subfile lastfilename)))
- (goto-char (point-min))
- (search-forward "\n\^_")
- (if (numberp nodepos)
- (+ (- 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-no-properties (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))
- (if Info-fontify (Info-fontify-node))
- (run-hooks 'Info-selection-hook))))
-
-(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 (list (Info-read-node-name "Goto 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))))
- (if transient-mark-mode (deactivate-mark))
- (Info-find-node (if (equal filename "") nil filename)
- (if (equal nodename "") "Top" nodename))))
-
-;; This function is used as the "completion table" while reading a node name.
-;; It does completion using the alist in completion-table
-;; unless STRING starts with an open-paren.
-(defun Info-read-node-name-1 (string predicate code)
- (let ((no-completion (and (> (length string) 0) (eq (aref string 0) ?\())))
- (cond ((eq code nil)
- (if no-completion
- string
- (try-completion string completion-table predicate)))
- ((eq code t)
- (if no-completion
- nil
- (all-completions string completion-table predicate)))
- ((eq code 'lambda)
- (if no-completion
- t
- (assoc string completion-table))))))
-
-(defun Info-read-node-name (prompt &optional default)
- (let* ((completion-ignore-case t)
- (completion-table (Info-build-node-completions))
- (nodename (completing-read prompt 'Info-read-node-name-1)))
- (if (equal nodename "")
- (or default
- (Info-read-node-name prompt))
- nodename)))
-
-(defun Info-build-node-completions ()
- (or Info-current-file-completions
- (let ((compl nil))
- (save-excursion
- (save-restriction
- (if (marker-buffer Info-tag-table-marker)
- (progn
- (set-buffer (marker-buffer Info-tag-table-marker))
- (widen)
- (goto-char Info-tag-table-marker)
- (while (re-search-forward "\nNode: \\(.*\\)\177" nil t)
- (setq compl
- (cons (list (buffer-substring (match-beginning 1)
- (match-end 1)))
- compl))))
- (widen)
- (goto-char (point-min))
- (while (search-forward "\n\^_" nil t)
- (forward-line 1)
- (let ((beg (point)))
- (forward-line 1)
- (if (re-search-backward "Node: *\\([^,\n]*\\) *[,\n\t]"
- beg t)
- (setq compl
- (cons (list (buffer-substring (match-beginning 1)
- (match-end 1)))
- compl))))))))
- (setq Info-current-file-completions compl))))
-
-(defun Info-restore-point (hl)
- "If this node has been visited, restore the point value when we left."
- (while hl
- (if (and (equal (nth 0 (car hl)) Info-current-file)
- ;; Use string-equal, not equal, to ignore text props.
- (string-equal (nth 1 (car hl)) Info-current-node))
- (progn
- (goto-char (nth 2 (car hl)))
- (setq hl nil)) ;terminate the while at next iter
- (setq hl (cdr hl)))))
-
-(defvar Info-last-search nil
- "Default regexp for \\<Info-mode-map>\\[Info-search] 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 transient-mark-mode (deactivate-mark))
- (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))
- (ostart (window-start))
- (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 osubfile)
- (goto-char opoint)
- (Info-select-node)
- (set-window-start (selected-window) ostart)))))
- (widen)
- (goto-char found)
- (Info-select-node)
- ;; Use string-equal, not equal, to ignore text props.
- (or (and (string-equal onode Info-current-node)
- (equal ofile Info-current-file))
- (setq Info-history (cons (list ofile onode opoint)
- Info-history)))))
-
-;; Extract the value of the node-pointer named NAME.
-;; If there is none, use ERRORNAME in the error message;
-;; if ERRORNAME is nil, just return nil.
-(defun Info-extract-pointer (name &optional errorname)
- (save-excursion
- (goto-char (point-min))
- (forward-line 1)
- (if (re-search-backward (concat name ":") nil t)
- (progn
- (goto-char (match-end 0))
- (Info-following-node-name))
- (if (eq errorname t)
- nil
- (error "Node has no %s" (capitalize (or errorname name)))))))
-
-;; Return the node name in the buffer following point.
-;; ALLOWEDCHARS, if non-nil, goes within [...] to make a regexp
-;; saying which chas may appear in the node name.
-(defun Info-following-node-name (&optional allowedchars)
- (skip-chars-forward " \t")
- (buffer-substring-no-properties
- (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"))
- (Info-restore-point Info-history))
-
-(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 default alt-default (start-point (point)) str i bol eol)
- (save-excursion
- ;; Store end and beginning of line.
- (end-of-line)
- (setq eol (point))
- (beginning-of-line)
- (setq bol (point))
-
- (goto-char (point-min))
- (while (re-search-forward "\\*note[ \n\t]*\\([^:]*\\):" nil t)
- (setq str (buffer-substring
- (match-beginning 1)
- (1- (point))))
- ;; See if this one should be the default.
- (and (null default)
- (<= (match-beginning 0) start-point)
- (<= start-point (point))
- (setq default t))
- ;; See if this one should be the alternate default.
- (and (null alt-default)
- (and (<= bol (match-beginning 0))
- (<= (point) eol))
- (setq alt-default t))
- (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)))
- ;; Record as a completion and perhaps as default.
- (if (eq default t) (setq default str))
- (if (eq alt-default t) (setq alt-default str))
- ;; Don't add this string if it's a duplicate.
- ;; We use a loop instead of "(assoc str completions)" because
- ;; we want to do a case-insensitive compare.
- (let ((tail completions)
- (tem (downcase str)))
- (while (and tail
- (not (string-equal tem (downcase (car (car tail))))))
- (setq tail (cdr tail)))
- (or tail
- (setq completions
- (cons (cons str nil)
- completions))))))
- ;; If no good default was found, try an alternate.
- (or default
- (setq default alt-default))
- ;; If only one cross-reference found, then make it default.
- (if (eq (length completions) 1)
- (setq default (car (car completions))))
- (if completions
- (let ((input (completing-read (if default
- (concat "Follow reference named: ("
- default ") ")
- "Follow reference named: ")
- completions nil t)))
- (list (if (equal input "")
- default input)))
- (error "No cross-references in this node"))))
- (let (target beg i (str (concat "\\*note " (regexp-quote 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-no-properties 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 ?\ ))
- ;; Collapse multiple spaces.
- (while (string-match " +" str)
- (setq str (replace-match " " t t str)))
- str))
-
-;; No one calls this.
-;;(defun Info-menu-item-sequence (list)
-;; (while list
-;; (Info-menu (car list))
-;; (setq list (cdr list))))
-
-(defun Info-complete-menu-item (string predicate action)
- (let ((case-fold-search t))
- (cond ((eq action nil)
- (let (completions
- (pattern (concat "\n\\* \\("
- (regexp-quote string)
- "[^:\t\n]*\\):")))
- (save-excursion
- (set-buffer Info-complete-menu-buffer)
- (goto-char (point-min))
- (search-forward "\n* Menu:")
- (while (re-search-forward pattern nil t)
- (setq completions (cons (cons (format "%s"
- (buffer-substring
- (match-beginning 1)
- (match-end 1)))
- (match-beginning 1))
- completions))))
- (try-completion string completions predicate)))
- ((eq action t)
- (let (completions
- (pattern (concat "\n\\* \\("
- (regexp-quote string)
- "[^:\t\n]*\\):")))
- (save-excursion
- (set-buffer Info-complete-menu-buffer)
- (goto-char (point-min))
- (search-forward "\n* Menu:")
- (while (re-search-forward pattern nil t)
- (setq completions (cons (cons (format "%s"
- (buffer-substring
- (match-beginning 1)
- (match-end 1)))
- (match-beginning 1))
- completions))))
- (all-completions string completions predicate)))
- (t
- (save-excursion
- (set-buffer Info-complete-menu-buffer)
- (goto-char (point-min))
- (search-forward "\n* Menu:")
- (re-search-forward (concat "\n\\* "
- (regexp-quote string)
- ":")
- nil t))))))
-
-
-(defun Info-menu (menu-item)
- "Go to node for menu item named (or abbreviated) NAME.
-Completion is allowed, and the menu item point is on is the default."
- (interactive
- (let ((completions '())
- ;; If point is within a menu item, use that item as the default
- (default nil)
- (p (point))
- beg
- (last nil))
- (save-excursion
- (goto-char (point-min))
- (if (not (search-forward "\n* menu:" nil t))
- (error "No menu in this node"))
- (setq beg (point))
- (and (< (point) p)
- (save-excursion
- (goto-char p)
- (end-of-line)
- (re-search-backward "\n\\* \\([^:\t\n]*\\):" beg t)
- (setq default (format "%s" (buffer-substring
- (match-beginning 1)
- (match-end 1)))))))
- (let ((item nil))
- (while (null item)
- (setq item (let ((completion-ignore-case t)
- (Info-complete-menu-buffer (current-buffer)))
- (completing-read (if default
- (format "Menu item (default %s): "
- default)
- "Menu item: ")
- 'Info-complete-menu-item nil t)))
- ;; we rely on the fact 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))))
- ;; there is a problem here in that if several menu items have the same
- ;; name you can only go to the node of the first with this command.
- (Info-goto-node (Info-extract-menu-item menu-item)))
-
-(defun Info-extract-menu-item (menu-item)
- (setq menu-item (regexp-quote menu-item))
- (save-excursion
- (goto-char (point-min))
- (or (search-forward "\n* menu:" nil t)
- (error "No menu in this node"))
- (or (re-search-forward (concat "\n\\* " menu-item ":") nil t)
- (re-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)))
-
-;; If COUNT is nil, use the last item in the menu.
-(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"))
- (if count
- (or (search-forward "\n* " nil t count)
- (error "Too few items in menu"))
- (while (search-forward "\n* " nil t)
- nil))
- (Info-extract-menu-node-name)))
-
-(defun Info-nth-menu-item ()
- "Go to the node of the Nth menu item.
-N is the digit argument used to invoke this command."
- (interactive)
- (Info-goto-node
- (Info-extract-menu-counting
- (- (aref (this-command-keys) (1- (length (this-command-keys)))) ?0))))
-
-(defun Info-top-node ()
- "Go to the Top node of this file."
- (interactive)
- (Info-goto-node "Top"))
-
-(defun Info-final-node ()
- "Go to the final node in this file."
- (interactive)
- (Info-goto-node "Top")
- (let (Info-history)
- ;; Go to the last node in the menu of Top.
- (Info-goto-node (Info-extract-menu-counting nil))
- ;; If the last node in the menu is not last in pointer structure,
- ;; move forward until we can't go any farther.
- (while (Info-forward-node t t) nil)
- ;; Then keep moving down to last subnode, unless we reach an index.
- (while (and (not (string-match "\\<index\\>" Info-current-node))
- (save-excursion (search-forward "\n* Menu:" nil t)))
- (Info-goto-node (Info-extract-menu-counting nil)))))
-
-(defun Info-forward-node (&optional not-down no-error)
- "Go forward one node, considering all nodes as forming one sequence."
- (interactive)
- (goto-char (point-min))
- (forward-line 1)
- ;; three possibilities, in order of priority:
- ;; 1. next node is in a menu in this node (but not in an index)
- ;; 2. next node is next at same level
- ;; 3. next node is up and next
- (cond ((and (not not-down)
- (save-excursion (search-forward "\n* menu:" nil t))
- (not (string-match "\\<index\\>" Info-current-node)))
- (Info-goto-node (Info-extract-menu-counting 1))
- t)
- ((save-excursion (search-backward "next:" nil t))
- (Info-next)
- t)
- ((and (save-excursion (search-backward "up:" nil t))
- ;; Use string-equal, not equal, to ignore text props.
- (not (string-equal (downcase (Info-extract-pointer "up"))
- "top")))
- (let ((old-node Info-current-node))
- (Info-up)
- (let (Info-history success)
- (unwind-protect
- (setq success (Info-forward-node t no-error))
- (or success (Info-goto-node old-node))))))
- (no-error nil)
- (t (error "No pointer forward from this node"))))
-
-(defun Info-backward-node ()
- "Go backward one node, considering all nodes as forming one sequence."
- (interactive)
- (let ((prevnode (Info-extract-pointer "prev[ious]*" t))
- (upnode (Info-extract-pointer "up" t)))
- (cond ((and upnode (string-match "(" upnode))
- (error "First node in file"))
- ((and upnode (or (null prevnode)
- ;; Use string-equal, not equal,
- ;; to ignore text properties.
- (string-equal (downcase prevnode)
- (downcase upnode))))
- (Info-up))
- (prevnode
- ;; If we move back at the same level,
- ;; go down to find the last subnode*.
- (Info-prev)
- (let (Info-history)
- (while (and (not (string-match "\\<index\\>" Info-current-node))
- (save-excursion (search-forward "\n* Menu:" nil t)))
- (Info-goto-node (Info-extract-menu-counting nil)))))
- (t
- (error "No pointer backward from this node")))))
-
-(defun Info-exit ()
- "Exit Info by selecting some other buffer."
- (interactive)
- (if Info-standalone
- (save-buffers-kill-emacs)
- (switch-to-buffer (prog1 (other-buffer (current-buffer))
- (bury-buffer (current-buffer))))))
-
-(defun Info-next-menu-item ()
- (interactive)
- (save-excursion
- (forward-line -1)
- (search-forward "\n* menu:" nil t)
- (or (search-forward "\n* " nil t)
- (error "No more items in menu"))
- (Info-goto-node (Info-extract-menu-node-name))))
-
-(defun Info-last-menu-item ()
- (interactive)
- (save-excursion
- (forward-line 1)
- (let ((beg (save-excursion
- (and (search-backward "\n* menu:" nil t)
- (point)))))
- (or (and beg (search-backward "\n* " beg t))
- (error "No previous items in menu")))
- (Info-goto-node (save-excursion
- (goto-char (match-end 0))
- (Info-extract-menu-node-name)))))
-
-(defmacro Info-no-error (&rest body)
- (list 'condition-case nil (cons 'progn (append body '(t))) '(error nil)))
-
-(defun Info-next-preorder ()
- "Go to the next subnode or the next node, or go up a level."
- (interactive)
- (cond ((Info-no-error (Info-next-menu-item)))
- ((Info-no-error (Info-next)))
- ((Info-no-error (Info-up))
- ;; Since we have already gone thru all the items in this menu,
- ;; go up to the end of this node.
- (goto-char (point-max))
- ;; Since logically we are done with the node with that menu,
- ;; move on from it.
- (Info-next-preorder))
- (t
- (error "No more nodes"))))
-
-(defun Info-last-preorder ()
- "Go to the last node, popping up a level if there is none."
- (interactive)
- (cond ((Info-no-error
- (Info-last-menu-item)
- ;; If we go down a menu item, go to the end of the node
- ;; so we can scroll back through it.
- (goto-char (point-max)))
- ;; Keep going down, as long as there are nested menu nodes.
- (while (Info-no-error
- (Info-last-menu-item)
- ;; If we go down a menu item, go to the end of the node
- ;; so we can scroll back through it.
- (goto-char (point-max))))
- (recenter -1))
- ((Info-no-error (Info-prev))
- (goto-char (point-max))
- (while (Info-no-error
- (Info-last-menu-item)
- ;; If we go down a menu item, go to the end of the node
- ;; so we can scroll back through it.
- (goto-char (point-max))))
- (recenter -1))
- ((Info-no-error (Info-up))
- (goto-char (point-min))
- (or (search-forward "\n* Menu:" nil t)
- (goto-char (point-max))))
- (t (error "No previous nodes"))))
-
-(defun Info-scroll-up ()
- "Scroll one screenful forward in Info, considering all nodes as one sequence.
-Once you scroll far enough in a node that its menu appears on the screen
-but after point, the next scroll moves into its first subnode.
-
-When you scroll past the end of a node, that goes to the next node; if
-this node has no successor, it moves to the parent node's successor,
-and so on. If point is inside the menu of a node, it moves to
-subnode indicated by the following menu item. (That case won't
-normally result from this command, but can happen in other ways.)"
-
- (interactive)
- (if (or (< (window-start) (point-min))
- (> (window-start) (point-max)))
- (set-window-start (selected-window) (point)))
- (let ((virtual-end (save-excursion
- (goto-char (point-min))
- (if (search-forward "\n* Menu:" nil t)
- (point)
- (point-max)))))
- (if (or (< virtual-end (window-start))
- (pos-visible-in-window-p virtual-end))
- (Info-next-preorder)
- (scroll-up))))
-
-(defun Info-scroll-down ()
- "Scroll one screenful back in Info, considering all nodes as one sequence.
-Within the menu of a node, this goes to its last subnode.
-When you scroll past the beginning of a node, that goes to the
-previous node or back up to the parent node."
- (interactive)
- (if (or (< (window-start) (point-min))
- (> (window-start) (point-max)))
- (set-window-start (selected-window) (point)))
- (let* ((current-point (point))
- (virtual-end (save-excursion
- (beginning-of-line)
- (setq current-point (point))
- (goto-char (point-min))
- (search-forward "\n* Menu:"
- current-point
- t))))
- (if (or virtual-end (pos-visible-in-window-p (point-min)))
- (Info-last-preorder)
- (scroll-down))))
-
-(defun Info-next-reference (&optional recur)
- "Move cursor to the next cross-reference or menu item in the node."
- (interactive)
- (let ((pat "\\*note[ \n\t]*\\([^:]*\\):\\|^\\* .*:")
- (old-pt (point)))
- (or (eobp) (forward-char 1))
- (or (re-search-forward pat nil t)
- (progn
- (goto-char (point-min))
- (or (re-search-forward pat nil t)
- (progn
- (goto-char old-pt)
- (error "No cross references in this node")))))
- (goto-char (match-beginning 0))
- (if (looking-at "\\* Menu:")
- (if recur
- (error "No cross references in this node")
- (Info-next-reference t)))))
-
-(defun Info-prev-reference (&optional recur)
- "Move cursor to the previous cross-reference or menu item in the node."
- (interactive)
- (let ((pat "\\*note[ \n\t]*\\([^:]*\\):\\|^\\* .*:")
- (old-pt (point)))
- (or (re-search-backward pat nil t)
- (progn
- (goto-char (point-max))
- (or (re-search-backward pat nil t)
- (progn
- (goto-char old-pt)
- (error "No cross references in this node")))))
- (goto-char (match-beginning 0))
- (if (looking-at "\\* Menu:")
- (if recur
- (error "No cross references in this node")
- (Info-prev-reference t)))))
-
-(defun Info-index (topic)
- "Look up a string in the index for this file.
-The index is defined as the first node in the top-level menu whose
-name contains the word \"Index\", plus any immediately following
-nodes whose names also contain the word \"Index\".
-If there are no exact matches to the specified topic, this chooses
-the first match which is a case-insensitive substring of a topic.
-Use the `,' command to see the other matches.
-Give a blank topic name to go to the Index node itself."
- (interactive "sIndex topic: ")
- (let ((orignode Info-current-node)
- (rnode nil)
- (pattern (format "\n\\* \\([^\n:]*%s[^\n:]*\\):[ \t]*\\([^.\n]*\\)\\.[ \t]*\\([0-9]*\\)"
- (regexp-quote topic)))
- node)
- (Info-goto-node "Top")
- (or (search-forward "\n* menu:" nil t)
- (error "No index"))
- (or (re-search-forward "\n\\* \\(.*\\<Index\\>\\)" nil t)
- (error "No index"))
- (goto-char (match-beginning 1))
- ;; Here, and subsequently in this function,
- ;; we bind Info-history to nil for internal node-switches
- ;; so that we don't put junk in the history.
- ;; In the first Info-goto-node call, above, we do update the history
- ;; because that is what the user's previous node choice into it.
- (let ((Info-history nil))
- (Info-goto-node (Info-extract-menu-node-name)))
- (or (equal topic "")
- (let ((matches nil)
- (exact nil)
- (Info-history nil)
- found)
- (while
- (progn
- (goto-char (point-min))
- (while (re-search-forward pattern nil t)
- (setq matches
- (cons (list (buffer-substring (match-beginning 1)
- (match-end 1))
- (buffer-substring (match-beginning 2)
- (match-end 2))
- Info-current-node
- (string-to-int (concat "0"
- (buffer-substring
- (match-beginning 3)
- (match-end 3)))))
- matches)))
- (and (setq node (Info-extract-pointer "next" t))
- (string-match "\\<Index\\>" node)))
- (Info-goto-node node))
- (or matches
- (progn
- (Info-goto-node orignode)
- (error "No `%s' in index" topic)))
- ;; Here it is a feature that assoc is case-sensitive.
- (while (setq found (assoc topic matches))
- (setq exact (cons found exact)
- matches (delq found matches)))
- (setq Info-index-alternatives (nconc exact (nreverse matches)))
- (Info-index-next 0)))))
-
-(defun Info-index-next (num)
- "Go to the next matching index item from the last `i' command."
- (interactive "p")
- (or Info-index-alternatives
- (error "No previous `i' command"))
- (while (< num 0)
- (setq num (+ num (length Info-index-alternatives))))
- (while (> num 0)
- (setq Info-index-alternatives
- (nconc (cdr Info-index-alternatives)
- (list (car Info-index-alternatives)))
- num (1- num)))
- (Info-goto-node (nth 1 (car Info-index-alternatives)))
- (if (> (nth 3 (car Info-index-alternatives)) 0)
- (forward-line (nth 3 (car Info-index-alternatives)))
- (forward-line 3) ; don't search in headers
- (let ((name (car (car Info-index-alternatives))))
- (Info-find-index-name name)))
- (message "Found `%s' in %s. %s"
- (car (car Info-index-alternatives))
- (nth 2 (car Info-index-alternatives))
- (if (cdr Info-index-alternatives)
- "(Press `,' for more)"
- "(Only match)")))
-
-(defun Info-find-index-name (name)
- "Move point to the place within the current node where NAME is defined."
- (if (or (re-search-forward (format
- "[a-zA-Z]+: %s\\( \\|$\\)"
- (regexp-quote name)) nil t)
- (search-forward (format "`%s'" name) nil t)
- (and (string-match "\\`.*\\( (.*)\\)\\'" name)
- (search-forward
- (format "`%s'" (substring name 0 (match-beginning 1)))
- nil t))
- (search-forward name nil t))
- (beginning-of-line)
- (goto-char (point-min))))
-
-(defun Info-undefined ()
- "Make command be undefined in Info."
- (interactive)
- (ding))
-
-(defun Info-help ()
- "Enter the Info tutorial."
- (interactive)
- (delete-other-windows)
- (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))
- (help-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 (not (eq ?\ (setq ch (read-event))))
- (progn (setq unread-command-events (list ch)) nil)
- flag))
- (scroll-up)))
- (bury-buffer "*Help*")))
-
-(defun Info-get-token (pos start all &optional errorstring)
- "Return the token around POS,
-POS must be somewhere inside the token
-START is a regular expression which will match the
- beginning of the tokens delimited string
-ALL is a regular expression with a single
- parenthesized subpattern which is the token to be
- returned. E.g. '{\(.*\)}' would return any string
- enclosed in braces around POS.
-SIG optional fourth argument, controls action on no match
- nil: return nil
- t: beep
- a string: signal an error, using that string."
- (save-excursion
- (goto-char pos)
- ;; First look for a match for START that goes across POS.
- (while (and (not (bobp)) (> (point) (- pos (length start)))
- (not (looking-at start)))
- (forward-char -1))
- ;; If we did not find one, search back for START
- ;; (this finds only matches that end at or before POS).
- (or (looking-at start)
- (progn
- (goto-char pos)
- (re-search-backward start (max (point-min) (- pos 200)) 'yes)))
- (let (found)
- (while (and (re-search-forward all (min (point-max) (+ pos 200)) 'yes)
- (not (setq found (and (<= (match-beginning 0) pos)
- (> (match-end 0) pos))))))
- (if (and found (<= (match-beginning 0) pos)
- (> (match-end 0) pos))
- (buffer-substring (match-beginning 1) (match-end 1))
- (cond ((null errorstring)
- nil)
- ((eq errorstring t)
- (beep)
- nil)
- (t
- (error "No %s around position %d" errorstring pos)))))))
-
-(defun Info-mouse-follow-nearest-node (click)
- "\\<Info-mode-map>Follow a node reference near point.
-Like \\[Info-menu], \\[Info-follow-reference], \\[Info-next], \\[Info-prev] or \\[Info-up] command, depending on where you click.
-At end of the node's text, moves to the next node, or up if none."
- (interactive "e")
- (let* ((start (event-start click))
- (window (car start))
- (pos (car (cdr start))))
- (select-window window)
- (goto-char pos))
- (and (not (Info-try-follow-nearest-node))
- (save-excursion (forward-line 1) (eobp))
- (Info-next-preorder)))
-
-(defun Info-follow-nearest-node ()
- "\\<Info-mode-map>Follow a node reference near point.
-Like \\[Info-menu], \\[Info-follow-reference], \\[Info-next], \\[Info-prev] or \\[Info-up] command, depending on where point is.
-If no reference to follow, moves to the next node, or up if none."
- (interactive)
- (or (Info-try-follow-nearest-node)
- (Info-next-preorder)))
-
-;; Common subroutine.
-(defun Info-try-follow-nearest-node ()
- "Follow a node reference near point. Return non-nil if successful."
- (let (node)
- (cond
- ((setq node (Info-get-token (point) "\\*note[ \n]"
- "\\*note[ \n]\\([^:]*\\):"))
- (Info-follow-reference node))
- ((setq node (Info-get-token (point) "\\* " "\\* \\([^:]*\\)::"))
- (Info-goto-node node))
- ((setq node (Info-get-token (point) "\\* " "\\* \\([^:]*\\):"))
- (Info-menu node))
- ((setq node (Info-get-token (point) "Up: " "Up: \\([^,\n\t]*\\)"))
- (Info-goto-node node))
- ((setq node (Info-get-token (point) "Next: " "Next: \\([^,\n\t]*\\)"))
- (Info-goto-node node))
- ((setq node (Info-get-token (point) "File: " "File: \\([^,\n\t]*\\)"))
- (Info-goto-node "Top"))
- ((setq node (Info-get-token (point) "Prev: " "Prev: \\([^,\n\t]*\\)"))
- (Info-goto-node node)))
- node))
-
-(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 " " 'Info-scroll-up)
- (define-key Info-mode-map "\C-m" 'Info-follow-nearest-node)
- (define-key Info-mode-map "\t" 'Info-next-reference)
- (define-key Info-mode-map "\e\t" 'Info-prev-reference)
- (define-key Info-mode-map "1" 'Info-nth-menu-item)
- (define-key Info-mode-map "2" 'Info-nth-menu-item)
- (define-key Info-mode-map "3" 'Info-nth-menu-item)
- (define-key Info-mode-map "4" 'Info-nth-menu-item)
- (define-key Info-mode-map "5" 'Info-nth-menu-item)
- (define-key Info-mode-map "6" 'Info-nth-menu-item)
- (define-key Info-mode-map "7" 'Info-nth-menu-item)
- (define-key Info-mode-map "8" 'Info-nth-menu-item)
- (define-key Info-mode-map "9" 'Info-nth-menu-item)
- (define-key Info-mode-map "0" 'undefined)
- (define-key Info-mode-map "?" 'Info-summary)
- (define-key Info-mode-map "]" 'Info-forward-node)
- (define-key Info-mode-map "[" 'Info-backward-node)
- (define-key Info-mode-map "<" 'Info-top-node)
- (define-key Info-mode-map ">" 'Info-final-node)
- (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 "i" 'Info-index)
- (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)
- ;; For consistency with Rmail.
- (define-key Info-mode-map "\M-s" 'Info-search)
- (define-key Info-mode-map "t" 'Info-top-node)
- (define-key Info-mode-map "u" 'Info-up)
- (define-key Info-mode-map "," 'Info-index-next)
- (define-key Info-mode-map "\177" 'Info-scroll-down)
- (define-key Info-mode-map [mouse-2] 'Info-mouse-follow-nearest-node)
- )
-
-(defun Info-check-pointer (item)
- ;; Non-nil if ITEM is present in this node.
- (condition-case nil
- (Info-extract-pointer item)
- (error nil)))
-
-(easy-menu-define Info-mode-menu Info-mode-map
- "Menu for info files."
- '("Info"
- ["Up" Info-up (Info-check-pointer "up")]
- ["Next" Info-next (Info-check-pointer "next")]
- ["Previous" Info-prev (Info-check-pointer "prev[ious]*")]
- ("Menu item" ["You should never see this" report-emacs-bug t])
- ("Reference" ["You should never see this" report-emacs-bug t])
- ["Search..." Info-search t]
- ["Goto node..." Info-goto-node t]
- ["Last" Info-last Info-history]
- ["Exit" Info-exit t]))
-
-(defvar Info-menu-last-node nil)
-;; Last node the menu was created for.
-
-(defun Info-menu-update ()
- ;; Update the Info menu for the current node.
- (condition-case nil
- (if (or (not (eq major-mode 'Info-mode))
- (eq Info-current-node Info-menu-last-node))
- ()
- ;; Update menu menu.
- (let* ((Info-complete-menu-buffer (current-buffer))
- (items (nreverse (condition-case nil
- (Info-complete-menu-item
- "" (lambda (e) t) t)
- (error nil))))
- entries current
- (number 0))
- (while (and items (< number 9))
- (setq current (car items)
- items (cdr items)
- number (1+ number))
- (setq entries (cons `[,current
- (Info-menu ,current)
- :keys ,(format "%d" number)]
- entries)))
- (if items
- (setq entries (cons ["Other..." Info-menu t] entries)))
- (or entries
- (setq entries (list ["No menu" nil nil])))
- (easy-menu-change '("Info") "Menu item" (nreverse entries)))
- ;; Update reference menu. Code stolen from `Info-follow-reference'.
- (let ((items nil)
- str i entries current
- (number 0))
- (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 items
- (cons str items))))
- (while (and items (< number 9))
- (setq current (car items)
- items (cdr items)
- number (1+ number))
- (setq entries (cons `[,current
- (Info-follow-reference ,current)
- t]
- entries)))
- (if items
- (setq entries (cons ["Other..." Info-follow-reference t]
- entries)))
- (or entries
- (setq entries (list ["No references" nil nil])))
- (easy-menu-change '("Info") "Reference" (nreverse entries)))
- ;; Update last seen node.
- (setq Info-menu-last-node (current-buffer)))
- ;; Try to avoid entering infinite beep mode in case of errors.
- (error (ding))))
-
-
-;; Info mode is suitable only for specially formatted data.
-(put 'info-mode 'mode-class 'special)
-
-(defun Info-mode ()
- "\\<Info-mode-map>
-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.
-
-\\[Info-help] Invoke the Info tutorial.
-
-Selecting other nodes:
-\\[Info-mouse-follow-nearest-node]
- Follow a node reference you click on.
- This works with menu items, cross references, and
- the \"next\", \"previous\" and \"up\", depending on where you click.
-\\[Info-next] Move to the \"next\" node of this node.
-\\[Info-prev] Move to the \"previous\" node of this node.
-\\[Info-up] Move \"up\" from this node.
-\\[Info-menu] Pick menu item specified by name (or abbreviation).
- Picking a menu item causes another node to be selected.
-\\[Info-directory] Go to the Info directory node.
-\\[Info-follow-reference] Follow a cross reference. Reads name of reference.
-\\[Info-last] Move to the last node you were at.
-\\[Info-index] Look up a topic in this file's Index and move to that node.
-\\[Info-index-next] (comma) Move to the next match from a previous `i' command.
-
-Moving within a node:
-\\[Info-scroll-up] Normally, scroll forward a full screen. If the end of the buffer is
-already visible, try to go to the next menu entry, or up if there is none.
-\\[Info-scroll-down] Normally, scroll backward. If the beginning of the buffer is
-already visible, try to go to the previous menu entry, or up if there is none.
-\\[beginning-of-buffer] Go to beginning of node.
-
-Advanced commands:
-\\[Info-exit] Quit Info: reselect previously selected buffer.
-\\[Info-edit] 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.
-\\[Info-goto-node] Move to node specified by name.
- You may include a filename as well, as (FILENAME)NODENAME.
-\\[universal-argument] \\[info] Move to new Info file with completion.
-\\[Info-search] Search through this Info file for specified regexp,
- and select the node in which the next occurrence is found.
-\\[Info-next-reference] Move cursor to next cross-reference or menu item.
-\\[Info-prev-reference] Move cursor to previous cross-reference or menu item."
- (kill-all-local-variables)
- (setq major-mode 'Info-mode)
- (setq mode-name "Info")
- (setq tab-width 8)
- (use-local-map Info-mode-map)
- (make-local-hook 'activate-menubar-hook)
- (add-hook 'activate-menubar-hook 'Info-menu-update nil t)
- (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)
- (make-local-variable 'Info-index-alternatives)
- (if (memq (framep (selected-frame)) '(x pc w32))
- (progn
- (make-face 'info-node)
- (make-face 'info-menu-5)
- (make-face 'info-xref)
- (or (face-differs-from-default-p 'info-node)
- (if (face-differs-from-default-p 'bold-italic)
- (copy-face 'bold-italic 'info-node)
- (copy-face 'bold 'info-node)))
- (or (face-differs-from-default-p 'info-menu-5)
- (set-face-underline-p 'info-menu-5 t))
- (or (face-differs-from-default-p 'info-xref)
- (copy-face 'bold 'info-xref)))
- (setq Info-fontify nil))
- (Info-set-mode-line)
- (run-hooks 'Info-mode-hook))
-
-(defvar Info-edit-map nil
- "Local keymap used within `e' command of Info.")
-(if Info-edit-map
- nil
- (setq Info-edit-map (nconc (make-sparse-keymap) text-mode-map))
- (define-key Info-edit-map "\C-c\C-c" 'Info-cease-edit))
-
-;; Info-edit mode is suitable only for specially formatted data.
-(put 'info-edit-mode 'mode-class 'special)
-
-(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}"
- (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)
- (force-mode-line-update)
- (buffer-enable-undo (current-buffer))
- (run-hooks 'Info-edit-mode-hook))
-
-(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"))
- (Info-edit-mode)
- (message "%s" (substitute-command-keys
- "Editing: Type \\<Info-edit-map>\\[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)
- (force-mode-line-update)
- (and (marker-position Info-tag-table-marker)
- (buffer-modified-p)
- (message "Tags may have changed. Use Info-tagify if necessary")))
-
-(defvar Info-file-list-for-emacs
- '("ediff" "forms" "gnus" "info" ("mh" . "mh-e") "sc")
- "List of Info files that describe Emacs commands.
-An element can be a file name, or a list of the form (PREFIX . FILE)
-where PREFIX is a name prefix and FILE is the file to look in.
-If the element is just a file name, the file name also serves as the prefix.")
-
-(defun Info-find-emacs-command-nodes (command)
- "Return a list of locations documenting COMMAND.
-The `info-file' property of COMMAND says which Info manual to search.
-If COMMAND has no property, the variable `Info-file-list-for-emacs'
-defines heuristics for which Info manual to try.
-The locations are of the format used in Info-history, i.e.
-\(FILENAME NODENAME BUFFERPOS\)."
- (let ((where '())
- (cmd-desc (concat "^\\* " (regexp-quote (symbol-name command))
- ":\\s *\\(.*\\)\\.$"))
- (info-file "emacs")) ;default
- ;; Determine which info file this command is documented in.
- (if (get command 'info-file)
- (setq info-file (get command 'info-file))
- ;; If it doesn't say explicitly, test its name against
- ;; various prefixes that we know.
- (let ((file-list Info-file-list-for-emacs))
- (while file-list
- (let* ((elt (car file-list))
- (name (if (consp elt)
- (car elt)
- elt))
- (file (if (consp elt) (cdr elt) elt))
- (regexp (concat "\\`" (regexp-quote name)
- "\\(\\'\\|-\\)")))
- (if (string-match regexp (symbol-name command))
- (setq info-file file file-list nil))
- (setq file-list (cdr file-list))))))
- (save-excursion
- (condition-case nil
- (Info-find-node info-file "Command Index")
- ;; Some manuals may not have a separate Command Index node,
- ;; so try just Index instead.
- (error
- (Info-find-node info-file "Index")))
- ;; Take the index node off the Info history.
- (setq Info-history (cdr Info-history))
- (goto-char (point-max))
- (while (re-search-backward cmd-desc nil t)
- (setq where (cons (list Info-current-file
- (buffer-substring
- (match-beginning 1)
- (match-end 1))
- 0)
- where)))
- where)))
-
-;;;###autoload
-(defun Info-goto-emacs-command-node (command)
- "Go to the Info node in the Emacs manual for command COMMAND.
-The command is found by looking up in Emacs manual's Command Index
-or in another manual found via COMMAND's `info-file' property or
-the variable `Info-file-list-for-emacs'."
- (interactive "CFind documentation for command: ")
- (or (commandp command)
- (signal 'wrong-type-argument (list 'commandp command)))
- (let ((where (Info-find-emacs-command-nodes command)))
- (if where
- (let ((num-matches (length where)))
- ;; Get Info running, and pop to it in another window.
- (save-window-excursion
- (info))
- (pop-to-buffer "*info*")
- (Info-find-node (car (car where))
- (car (cdr (car where))))
- (if (> num-matches 1)
- (progn
- ;; Info-find-node already pushed (car where) onto
- ;; Info-history. Put the other nodes that were found on
- ;; the history.
- (setq Info-history (nconc (cdr where) Info-history))
- (message "Found %d other entr%s. Use %s to see %s."
- (1- num-matches)
- (if (> num-matches 2) "ies" "y")
- (substitute-command-keys "\\[Info-last]")
- (if (> num-matches 2) "them" "it")))))
- (error "Couldn't find documentation for %s" command))))
-
-;;;###autoload
-(defun Info-goto-emacs-key-command-node (key)
- "Go to the Info node in the Emacs manual the command bound to KEY, a string.
-Interactively, if the binding is execute-extended-command, a command is read.
-The command is found by looking up in Emacs manual's Command Index
-or in another manual found via COMMAND's `info-file' property or
-the variable `Info-file-list-for-emacs'."
- (interactive "kFind documentation for key:")
- (let ((command (key-binding key)))
- (cond ((null command)
- (message "%s is undefined" (key-description key)))
- ((and (interactive-p)
- (eq command 'execute-extended-command))
- (Info-goto-emacs-command-node
- (read-command "Find documentation for command: ")))
- (t
- (Info-goto-emacs-command-node command)))))
-
-(defvar Info-title-face-alist
- '((?* bold underline)
- (?= bold-italic underline)
- (?- italic underline))
- "*Alist of face or list of faces to use for pseudo-underlined titles.
-The alist key is the character the title is underlined with (?*, ?= or ?-).")
-
-(defun Info-fontify-node ()
- (save-excursion
- (let ((buffer-read-only nil))
- (goto-char (point-min))
- (if (looking-at "^File: [^,: \t]+,?[ \t]+")
- (progn
- (goto-char (match-end 0))
- (while
- (looking-at "[ \t]*[^:, \t\n]+:[ \t]+\\([^:,\t\n]+\\),?")
- (goto-char (match-end 0))
- (put-text-property (match-beginning 1) (match-end 1)
- 'face 'info-xref)
- (put-text-property (match-beginning 1) (match-end 1)
- 'mouse-face 'highlight))))
- (goto-char (point-min))
- (while (re-search-forward "\n\\([^ \t\n].+\\)\n\\(\\*+\\|=+\\|-+\\)$"
- nil t)
- (put-text-property (match-beginning 1) (match-end 1)
- 'face
- (cdr (assq (preceding-char) Info-title-face-alist)))
- (put-text-property (match-end 1) (match-end 2)
- 'invisible t))
- (goto-char (point-min))
- (while (re-search-forward "\\*Note[ \n\t]+\\([^:]*\\):" nil t)
- (if (= (char-after (1- (match-beginning 0))) ?\") ; hack
- nil
- (put-text-property (match-beginning 1) (match-end 1)
- 'face 'info-xref)
- (put-text-property (match-beginning 1) (match-end 1)
- 'mouse-face 'highlight)))
- (goto-char (point-min))
- (if (and (search-forward "\n* Menu:" nil t)
- (not (string-match "\\<Index\\>" Info-current-node))
- ;; Don't take time to annotate huge menus
- (< (- (point-max) (point)) Info-fontify-maximum-menu-size))
- (let ((n 0))
- (while (re-search-forward "^\\* \\([^:\t\n]*\\):" nil t)
- (setq n (1+ n))
- (if (memq n '(5 9)) ; visual aids to help with 1-9 keys
- (put-text-property (match-beginning 0)
- (1+ (match-beginning 0))
- 'face 'info-menu-5))
- (put-text-property (match-beginning 1) (match-end 1)
- 'face 'info-node)
- (put-text-property (match-beginning 1) (match-end 1)
- 'mouse-face 'highlight))))
- (set-buffer-modified-p nil))))
-
-(provide 'info)
-
-;;; info.el ends here
diff --git a/lisp/informat.el b/lisp/informat.el
deleted file mode 100644
index 0b195b9e620..00000000000
--- a/lisp/informat.el
+++ /dev/null
@@ -1,429 +0,0 @@
-;;; informat.el --- info support functions package for Emacs
-
-;; Copyright (C) 1986 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: help
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(require 'info)
-
-;;;###autoload
-(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.
- (message "Tagifying %s ..." (file-name-nondirectory (buffer-file-name)))
- (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)
- ;; We want the 0-origin character position of the ^_.
- ;; That is the same as the Emacs (1-origin) position
- ;; of the newline before it.
- (let ((beg (match-beginning 0)))
- (forward-line 2)
- (if (re-search-backward regexp beg t)
- (setq list
- (cons (list (buffer-substring-no-properties
- (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))))))
- (message "Tagifying %s ... done" (file-name-nondirectory (buffer-file-name))))
-
-;;;###autoload
-(defun Info-split ()
- "Split an info file into an indirect file plus bounded-size subfiles.
-Each subfile will be up to 50,000 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" (1- (car (car subfiles))))
- "\n")
- (setq subfiles (cdr subfiles)))
- (goto-char start)
- (insert "\^_\nIndirect:\n")
- (search-forward "\nTag Table:\n")
- (insert "(Indirect)\n")))
-
-;;;###autoload
-(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-no-properties
- (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-no-properties
- (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-no-properties
- (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-no-properties
- (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)))
- (if (looking-at "\^_\n")
- (forward-line 1))
- (or (looking-at "End tag table\n")
- (throw 'losing 'z))
- nil))))
-
-;;;###autoload
-(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-disable-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
- (Info-tagify))))
- (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-no-properties
- (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))))
-
-;;; informat.el ends here
diff --git a/lisp/international/iso-acc.el b/lisp/international/iso-acc.el
deleted file mode 100644
index 9f3fa7a53e6..00000000000
--- a/lisp/international/iso-acc.el
+++ /dev/null
@@ -1,419 +0,0 @@
-;;; iso-acc.el --- minor mode providing electric accent keys
-
-;; Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
-
-;; Author: Johan Vromans
-;; Maintainer: FSF
-;; Keywords: i18n
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Function `iso-accents-mode' activates a minor mode in which
-;; typewriter "dead keys" are emulated. The purpose of this emulation
-;; is to provide a simple means for inserting accented characters
-;; according to the ISO-8859-1 character set.
-;;
-;; In `iso-accents-mode', pseudo accent characters are used to
-;; introduce accented keys. The pseudo-accent characters are:
-;;
-;; ' (minute) -> grave accent
-;; ` (backtick) -> acute accent
-;; " (second) -> diaeresis
-;; ^ (caret) -> circumflex
-;; ~ (tilde) -> tilde over the character
-;; / (slash) -> slash through the character.
-;; Also: /A is A-with-ring and /E is AE ligature.
-;;
-;; The action taken depends on the key that follows the pseudo accent.
-;; In general:
-;;
-;; pseudo-accent + appropriate letter -> accented letter
-;; pseudo-accent + space -> pseudo-accent
-;; pseudo-accent + pseudo-accent -> accent (if available)
-;; pseudo-accent + other -> pseudo-accent + other
-;;
-;; If the pseudo-accent is followed by anything else than a
-;; self-insert-command, the dead-key code is terminated, the
-;; pseudo-accent inserted 'as is' and the bell is rung to signal this.
-;;
-;; Function `iso-accents-mode' can be used to enable the iso accents
-;; minor mode, or disable it.
-
-;; If you want only some of these characters to serve as accents,
-;; add a language to `iso-languages' which specifies the accent characters
-;; that you want, then select the language with `iso-accents-customize'.
-
-;;; Code:
-
-(provide 'iso-acc)
-
-(defvar iso-languages
- '(("catalan"
- ;; Note this includes some extra characters used in Spanish,
- ;; on the idea that someone who uses Catalan is likely to use Spanish
- ;; as well.
- (?' (?A . ?\301) (?E . ?\311) (?I . ?\315) (?O . ?\323) (?U . ?\332)
- (?a . ?\341) (?e . ?\351) (?i . ?\355) (?o . ?\363) (?u . ?\372)
- (?\ . ?'))
- (?` (?A . ?\300) (?E . ?\310) (?O . ?\322)
- (?a . ?\340) (?e . ?\350) (?o . ?\362) (?\ . ?`))
- (?\" (?I . ?\317) (?U . ?\334) (?i . ?\357) (?u . ?\374) (?\ . ?\"))
- (?\~ (?C . ?\307) (?N . ?\321) (?c . ?\347) (?n . ?\361)
- (?> . ?\273) (?< . ?\253) (?! . ?\241) (?? . ?\277)
- (?\ . ?\~)))
-
- ("esperanto"
- (?^ (?H . ?\246) (?J . ?\254) (?h . ?\266) (?j . ?\274) (?C . ?\306)
- (?G . ?\330) (?S . ?\336) (?c . ?\346) (?g . ?\370) (?s . ?\376)
- (?^ . ?^) (?\ . ?^))
- (?~ (?U . ?\335) (?u . ?\375) (?\ . ?~)))
-
- ("french"
- (?' (?E . ?\311) (?C . ?\307) (?e . ?\351) (?c . ?\347) (?\ . ?'))
- (?` (?A . ?\300) (?E . ?\310) (?U . ?\331)
- (?a . ?\340) (?e . ?\350) (?u . ?\371) (?\ . ?`))
- (?^ (?A . ?\302) (?E . ?\312) (?I . ?\316) (?O . ?\324) (?U . ?\333)
- (?a . ?\342) (?e . ?\352) (?i . ?\356) (?o . ?\364) (?u . ?\373)
- (?\ . ?^))
- (?\" (?E . ?\313) (?I . ?\317)
- (?e . ?\353) (?i . ?\357) (?\ . ?\"))
- (?\~ (?< . ?\253) (?> . ?\273) (?C . ?\307) (?c . ?\347) (?\ . ?\~)))
-
- ("german"
- (?\" (?A . ?\304) (?O . ?\326) (?U . ?\334)
- (?a . ?\344) (?o . ?\366) (?u . ?\374) (?s . ?\337) (?\ . ?\")))
-
- ("irish"
- (?' (?A . ?\301) (?E . ?\311) (?I . ?\315) (?O . ?\323) (?U . ?\332)
- (?a . ?\341) (?e . ?\351) (?i . ?\355) (?o . ?\363) (?u . ?\372)
- (?\ . ?')))
-
- ("latin-1"
- (?' (?A . ?\301) (?E . ?\311) (?I . ?\315) (?O . ?\323) (?U . ?\332)
- (?Y . ?\335) (?a . ?\341) (?e . ?\351) (?i . ?\355) (?o . ?\363)
- (?u . ?\372) (?y . ?\375) (?' . ?\264) (?\ . ?'))
- (?` (?A . ?\300) (?E . ?\310) (?I . ?\314) (?O . ?\322) (?U . ?\331)
- (?a . ?\340) (?e . ?\350) (?i . ?\354) (?o . ?\362) (?u . ?\371)
- (?` . ?`) (?\ . ?`))
- (?^ (?A . ?\302) (?E . ?\312) (?I . ?\316) (?O . ?\324) (?U . ?\333)
- (?a . ?\342) (?e . ?\352) (?i . ?\356) (?o . ?\364) (?u . ?\373)
- (?^ . ?^) (?\ . ?^))
- (?\" (?A . ?\304) (?E . ?\313) (?I . ?\317) (?O . ?\326) (?U . ?\334)
- (?a . ?\344) (?e . ?\353) (?i . ?\357) (?o . ?\366) (?s . ?\337)
- (?u . ?\374) (?y . ?\377) (?\" . ?\250) (?\ . ?\"))
- (?\~ (?A . ?\303) (?C . ?\307) (?D . ?\320) (?N . ?\321) (?O . ?\325)
- (?T . ?\336) (?a . ?\343) (?c . ?\347) (?d . ?\360) (?n . ?\361)
- (?o . ?\365) (?t . ?\376) (?> . ?\273) (?< . ?\253) (?\~ . ?\270)
- (?! . ?\241) (?? . ?\277)
- (?\ . ?\~))
- (?\/ (?A . ?\305) (?E . ?\306) (?O . ?\330) (?a . ?\345) (?e . ?\346)
- (?o . ?\370) (?\/ . ?\260) (?\ . ?\/)))
-
- ("latin-2"
- (?' (?A . ?\301) (?C . ?\306) (?D . ?\320) (?E . ?\311) (?I . ?\315)
- (?L . ?\305) (?N . ?\321) (?O . ?\323) (?R . ?\300) (?S . ?\246)
- (?U . ?\332) (?Y . ?\335) (?Z . ?\254) (?a . ?\341) (?c . ?\346)
- (?d . ?\360) (?e . ?\351) (?i . ?\355) (?l . ?\345) (?n . ?\361)
- (?o . ?\363) (?r . ?\340) (?s . ?\266) (?u . ?\372) (?y . ?\375)
- (?z . ?\274) (?' . ?\264) (?\ . ?'))
- (?` (?A . ?\241) (?C . ?\307) (?E . ?\312) (?L . ?\243) (?S . ?\252)
- (?T . ?\336) (?Z . ?\257) (?a . ?\261) (?l . ?\263) (?c . ?\347)
- (?e . ?\352) (?s . ?\272) (?t . ?\376) (?z . ?\277) (?` . ?\252)
- (?. . ?\377) (?\ . ?`))
- (?^ (?A . ?\302) (?O . ?\324) (?a . ?\342) (?o . ?\364)
- (?^ . ?^) ; no special code?
- (?\ . ?^))
- (?\" (?A . ?\304) (?E . ?\313) (?O . ?\326) (?U . ?\334) (?a . ?\344)
- (?e . ?\353) (?o . ?\366) (?s . ?\337) (?u . ?\374) (?\" . ?\250)
- (?\ . ?\"))
- (?\~ (?A . ?\303) (?C . ?\310) (?D . ?\317) (?L . ?\245) (?N . ?\322)
- (?O . ?\325) (?R . ?\330) (?S . ?\251) (?T . ?\253) (?U . ?\333)
- (?Z . ?\256) (?a . ?\323) (?c . ?\350) (?d . ?\357) (?l . ?\265)
- (?n . ?\362) (?o . ?\365) (?r . ?\370) (?s . ?\271) (?t . ?\273)
- (?u . ?\373) (?z . ?\276)
- (?v . ?\242) ; v accent
- (?\~ . ?\242) ; v accent
- (?\. . ?\270) ; cedilla accent
- (?\ . ?\~)))
-
- ("latin-3"
- (?' (?A . ?\301) (?E . ?\311) (?I . ?\315) (?O . ?\323) (?U . ?\332)
- (?a . ?\341) (?e . ?\351) (?i . ?\355) (?o . ?\363) (?u . ?\372)
- (?' . ?\264) (?\ . ?'))
- (?` (?A . ?\300) (?E . ?\310) (?I . ?\314) (?O . ?\322) (?U . ?\331)
- (?a . ?\340) (?e . ?\350) (?i . ?\354) (?o . ?\362) (?u . ?\371)
- (?` . ?`) (?\ . ?`))
- (?^ (?A . ?\302) (?E . ?\312) (?I . ?\316) (?O . ?\324) (?U . ?\333)
- (?a . ?\342) (?e . ?\352) (?i . ?\356) (?o . ?\364) (?u . ?\373)
- (?H . ?\246) (?J . ?\254) (?h . ?\266) (?j . ?\274) (?C . ?\306)
- (?G . ?\330) (?S . ?\336) (?c . ?\346) (?g . ?\370) (?s . ?\376)
- (?^ . ?^) (?\ . ?^))
- (?\" (?A . ?\304) (?E . ?\313) (?I . ?\317) (?O . ?\326) (?U . ?\334)
- (?a . ?\344) (?e . ?\353) (?i . ?\357) (?o . ?\366) (?s . ?\337)
- (?u . ?\374) (?\" . ?\250) (?\ . ?\"))
- (?~ (?A . ?\303) (?C . ?\307) (?D . ?\320) (?N . ?\321) (?O . ?\325)
- (?a . ?\343) (?c . ?\347) (?d . ?\360) (?n . ?\361) (?o . ?\365)
- (?$ . ?\245) (?S . ?\252) (?s . ?\272) (?G . ?\253) (?g . ?\273)
- (?U . ?\335) (?u . ?\375) (?` . ?\242) (?~ . ?\270) (?\ . ?~))
- (?/ (?H . ?\241) (?# . ?\243) (?$ . ?\244) (?r . ?\256) (?h . ?\261)
- (?I . ?\251) (?Z . ?\257) (?i . ?\271) (?z . ?\277) (?C . ?\305)
- (?G . ?\325) (?c . ?\345) (?g . ?\365) (?. . ?\377) (?/ . ?\260)
- (?\ . ?/)))
-
- ("portuguese"
- (?' (?A . ?\301) (?E . ?\311) (?I . ?\315) (?O . ?\323) (?U . ?\332)
- (?C . ?\307) (?a . ?\341) (?e . ?\351) (?i . ?\355) (?o . ?\363)
- (?u . ?\372) (?c . ?\347) (?\ . ?'))
- (?` (?A . ?\300) (?a . ?\340) (?\ . ?`))
- (?^ (?A . ?\302) (?E . ?\312) (?O . ?\324) (?a . ?\342) (?e . ?\352)
- (?o . ?\364) (?\ . ?^))
- (?\" (?U . ?\334) (?u . ?\374) (?\ . ?\"))
- (?\~ (?A . ?\303) (?O . ?\325) (?a . ?\343) (?o . ?\365) (?\ . ?\~)))
-
- ("spanish"
- (?' (?A . ?\301) (?E . ?\311) (?I . ?\315) (?O . ?\323) (?U . ?\332)
- (?a . ?\341) (?e . ?\351) (?i . ?\355) (?o . ?\363) (?u . ?\372)
- (?\ . ?'))
- (?\" (?U . ?\334) (?u . ?\374) (?\ . ?\"))
- (?\~ (?N . ?\321) (?n . ?\361) (?> . ?\273) (?< . ?\253) (?! . ?\241)
- (?? . ?\277) (?\ . ?\~))))
- "List of language-specific customizations for the ISO Accents mode.
-
-Each element of the list is of the form
-
- (LANGUAGE
- (PSEUDO-ACCENT MAPPINGS)
- (PSEUDO-ACCENT MAPPINGS)
- ...)
-
-LANGUAGE is a string naming the language.
-PSEUDO-ACCENT is a char specifying an accent key.
-MAPPINGS are cons cells of the form (CHAR . ISO-CHAR).
-
-The net effect is that the key sequence PSEUDO-ACCENT CHAR is mapped
-to ISO-CHAR on input.")
-
-(defvar iso-language nil
- "Language for which ISO Accents mode is currently customized.
-Change it with the `iso-accents-customize' function.")
-
-(defvar iso-accents-list nil
- "Association list for ISO accent combinations, for the chosen language.")
-
-(defvar iso-accents-mode nil
- "*Non-nil enables ISO Accents mode.
-Setting this variable makes it local to the current buffer.
-See the function `iso-accents-mode'.")
-(make-variable-buffer-local 'iso-accents-mode)
-
-(defvar iso-accents-enable '(?' ?` ?^ ?\" ?~ ?/)
- "*List of accent keys that become prefixes in ISO Accents mode.
-The default is (?' ?` ?^ ?\" ?~ ?/), which contains all the supported
-accent keys. If you set this variable to a list in which some of those
-characters are missing, the missing ones do not act as accents.
-
-Note that if you specify a language with `iso-accents-customize',
-that can also turn off certain prefixes (whichever ones are not needed in
-the language you choose).")
-
-(defun iso-accents-accent-key (prompt)
- "Modify the following character by adding an accent to it."
- ;; Pick up the accent character.
- (if (and iso-accents-mode
- (memq last-input-char iso-accents-enable))
- (iso-accents-compose prompt)
- (char-to-string last-input-char)))
-
-(defun iso-accents-compose (prompt)
- (let* ((first-char last-input-char)
- (list (assq first-char iso-accents-list))
- ;; Wait for the second key and look up the combination.
- (second-char (if (or prompt
- (not (eq (key-binding "a")
- 'self-insert-command))
- ;; Not at start of a key sequence.
- (> (length (this-single-command-keys)) 1)
- ;; Called from anything but the command loop.
- this-command)
- (progn
- (message "%s%c"
- (or prompt "Compose with ")
- first-char)
- (read-event))
- (insert first-char)
- (prog1 (read-event)
- (delete-region (1- (point)) (point)))))
- (entry (cdr (assq second-char list))))
- (if entry
- ;; Found it: return the mapped char
- (vector entry)
- ;; Otherwise, advance and schedule the second key for execution.
- (setq unread-command-events (list second-char))
- (vector first-char))))
-
-;; It is a matter of taste if you want the minor mode indicated
-;; in the mode line...
-;; If so, uncomment the next four lines.
-;; (or (assq 'iso-accents-mode minor-mode-map-alist)
-;; (setq minor-mode-alist
-;; (append minor-mode-alist
-;; '((iso-accents-mode " ISO-Acc")))))
-
-;;;###autoload
-(defun iso-accents-mode (&optional arg)
- "Toggle ISO Accents mode, in which accents modify the following letter.
-This permits easy insertion of accented characters according to ISO-8859-1.
-When Iso-accents mode is enabled, accent character keys
-\(`, ', \", ^, / and ~) do not self-insert; instead, they modify the following
-letter key so that it inserts an ISO accented letter.
-
-You can customize ISO Accents mode to a particular language
-with the command `iso-accents-customize'.
-
-Special combinations: ~c gives a c with cedilla,
-~d gives an Icelandic eth (d with dash).
-~t gives an Icelandic thorn.
-\"s gives German sharp s.
-/a gives a with ring.
-/e gives an a-e ligature.
-~< and ~> give guillemots.
-~! gives an inverted exclamation mark.
-~? gives an inverted question mark.
-
-With an argument, a positive argument enables ISO Accents mode,
-and a negative argument disables it."
-
- (interactive "P")
-
- (if (if arg
- ;; Negative arg means switch it off.
- (<= (prefix-numeric-value arg) 0)
- ;; No arg means toggle.
- iso-accents-mode)
- (setq iso-accents-mode nil)
-
- ;; Enable electric accents.
- (setq iso-accents-mode t)))
-
-(defun iso-accents-customize (language)
- "Customize the ISO accents machinery for a particular language.
-It selects the customization based on the specifications in the
-`iso-languages' variable."
- (interactive (list (completing-read "Language: " iso-languages nil t)))
- (let ((table (assoc language iso-languages))
- all-accents tail)
- (if (not table)
- (error "Unknown language '%s'" language)
- (setq iso-language language
- iso-accents-list (cdr table))
- (if key-translation-map
- (substitute-key-definition
- 'iso-accents-accent-key nil key-translation-map)
- (setq key-translation-map (make-sparse-keymap)))
- ;; Set up translations for all the characters that are used as
- ;; accent prefixes in this language.
- (setq tail iso-accents-list)
- (while tail
- (define-key key-translation-map (vector (car (car tail)))
- 'iso-accents-accent-key)
- (setq tail (cdr tail))))))
-
-(defun iso-accentuate (start end)
- "Convert two-character sequences in region into accented characters.
-Noninteractively, this operates on text from START to END.
-This uses the same conversion that ISO Accents mode uses for type-in."
- (interactive "r")
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (goto-char start)
- (forward-char 1)
- (let (entry)
- (while (< (point) end)
- (if (and (memq (preceding-char) iso-accents-enable)
- (setq entry (cdr (assq (following-char) (assq (preceding-char) iso-accents-list)))))
- (progn
- (forward-char -1)
- (delete-char 2)
- (insert entry)
- (setq end (1- end)))
- (forward-char 1)))))))
-
-(defun iso-accent-rassoc-unit (value alist)
- (let (elt acc)
- (while (and alist (not elt))
- (setq acc (car (car alist))
- elt (car (rassq value (cdr (car alist))))
- alist (cdr alist)))
- (if elt
- (cons acc elt))))
-
-(defun iso-unaccentuate (start end)
- "Convert accented characters in the region into two-character sequences.
-Noninteractively, this operates on text from START to END.
-This uses the opposite of the conversion done by ISO Accents mode for type-in."
- (interactive "r")
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (goto-char start)
- (let (entry)
- (while (< (point) end)
- (if (and (> (following-char) 127)
- (setq entry (iso-accent-rassoc-unit (following-char)
- iso-accents-list)))
- (progn
- (delete-char 1)
- (insert (car entry) (cdr entry))
- (setq end (1+ end)))
- (forward-char 1)))))))
-
-(defun iso-deaccentuate (start end)
- "Convert accented characters in the region into unaccented characters.
-Noninteractively, this operates on text from START to END."
- (interactive "r")
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (goto-char start)
- (let (entry)
- (while (< (point) end)
- (if (and (> (following-char) 127)
- (setq entry (iso-accent-rassoc-unit (following-char)
- iso-accents-list)))
- (progn
- (delete-char 1)
- (insert (cdr entry)))
- (forward-char 1)))))))
-
-;; Set up the default settings.
-(iso-accents-customize "latin-1")
-
-;; Use Iso-Accents mode in the minibuffer
-;; if it was in use in the previous buffer.
-(defun iso-acc-minibuf-setup ()
- (setq iso-accents-mode
- (save-excursion
- (set-buffer (window-buffer minibuffer-scroll-window))
- iso-accents-mode)))
-
-(add-hook 'minibuffer-setup-hook 'iso-acc-minibuf-setup)
-
-;;; iso-acc.el ends here
diff --git a/lisp/international/iso-ascii.el b/lisp/international/iso-ascii.el
deleted file mode 100644
index abed6a37df5..00000000000
--- a/lisp/international/iso-ascii.el
+++ /dev/null
@@ -1,146 +0,0 @@
-;;; iso-ascii.el --- set up char tables for ISO 8859/1 on ASCII terminals.
-
-;; Copyright (C) 1987, 1995 Free Software Foundation, Inc.
-
-;; Author: Howard Gayle
-;; Maintainer: FSF
-;; Keywords: i18n
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Written by Howard Gayle. See display-table.el for details.
-
-;; This code sets up to display ISO 8859/1 characters on plain
-;; ASCII terminals. The display strings for the characters are
-;; more-or-less based on TeX.
-
-;;; Code:
-
-(require 'disp-table)
-
-(defvar iso-ascii-convenient nil
- "*Non-nil means `iso-ascii' should aim for convenience, not precision.")
-
-(defun iso-ascii-display (code string &optional convenient-string)
- (if iso-ascii-convenient
- (setq string (or convenient-string string))
- (setq string (concat "{" string "}")))
- (standard-display-ascii code string))
-
-(iso-ascii-display 160 "_" " ") ; NBSP (no-break space)
-(iso-ascii-display 161 "!") ; inverted exclamation mark
-(iso-ascii-display 162 "c") ; cent sign
-(iso-ascii-display 163 "GBP") ; pound sign
-(iso-ascii-display 164 "$") ; general currency sign
-(iso-ascii-display 165 "JPY") ; yen sign
-(iso-ascii-display 166 "|") ; broken vertical line
-(iso-ascii-display 167 "S" "(S)") ; section sign
-(iso-ascii-display 168 "\"") ; diaeresis
-(iso-ascii-display 169 "C" "(C)") ; copyright sign
-(iso-ascii-display 170 "_a") ; ordinal indicator, feminine
-(iso-ascii-display 171 "<<") ; left angle quotation mark
-(iso-ascii-display 172 "~") ; not sign
-(iso-ascii-display 173 "-") ; soft hyphen
-(iso-ascii-display 174 "R" "(R)") ; registered sign
-(iso-ascii-display 175 "=") ; macron
-(iso-ascii-display 176 "o") ; degree sign
-(iso-ascii-display 177 "+-") ; plus or minus sign
-(iso-ascii-display 178 "2") ; superscript two
-(iso-ascii-display 179 "3") ; superscript three
-(iso-ascii-display 180 "'") ; acute accent
-(iso-ascii-display 181 "u") ; micro sign
-(iso-ascii-display 182 "P" "{P}") ; pilcrow
-(iso-ascii-display 183 ".") ; middle dot
-(iso-ascii-display 184 ",") ; cedilla
-(iso-ascii-display 185 "1") ; superscript one
-(iso-ascii-display 186 "_o") ; ordinal indicator, masculine
-(iso-ascii-display 187 ">>") ; right angle quotation mark
-(iso-ascii-display 188 "1/4") ; fraction one-quarter
-(iso-ascii-display 189 "1/2") ; fraction one-half
-(iso-ascii-display 190 "3/4") ; fraction three-quarters
-(iso-ascii-display 191 "?") ; inverted question mark
-(iso-ascii-display 192 "`A") ; A with grave accent
-(iso-ascii-display 193 "'A") ; A with acute accent
-(iso-ascii-display 194 "^A") ; A with circumflex accent
-(iso-ascii-display 195 "~A") ; A with tilde
-(iso-ascii-display 196 "\"A") ; A with diaeresis or umlaut mark
-(iso-ascii-display 197 "AA") ; A with ring
-(iso-ascii-display 198 "AE") ; AE diphthong
-(iso-ascii-display 199 ",C") ; C with cedilla
-(iso-ascii-display 200 "`E") ; E with grave accent
-(iso-ascii-display 201 "'E") ; E with acute accent
-(iso-ascii-display 202 "^E") ; E with circumflex accent
-(iso-ascii-display 203 "\"E") ; E with diaeresis or umlaut mark
-(iso-ascii-display 204 "`I") ; I with grave accent
-(iso-ascii-display 205 "'I") ; I with acute accent
-(iso-ascii-display 206 "^I") ; I with circumflex accent
-(iso-ascii-display 207 "\"I") ; I with diaeresis or umlaut mark
-(iso-ascii-display 208 "-D") ; D with stroke, Icelandic eth
-(iso-ascii-display 209 "~N") ; N with tilde
-(iso-ascii-display 210 "`O") ; O with grave accent
-(iso-ascii-display 211 "'O") ; O with acute accent
-(iso-ascii-display 212 "^O") ; O with circumflex accent
-(iso-ascii-display 213 "~O") ; O with tilde
-(iso-ascii-display 214 "\"O") ; O with diaeresis or umlaut mark
-(iso-ascii-display 215 "x") ; multiplication sign
-(iso-ascii-display 216 "/O") ; O with slash
-(iso-ascii-display 217 "`U") ; U with grave accent
-(iso-ascii-display 218 "'U") ; U with acute accent
-(iso-ascii-display 219 "^U") ; U with circumflex accent
-(iso-ascii-display 220 "\"U") ; U with diaeresis or umlaut mark
-(iso-ascii-display 221 "'Y") ; Y with acute accent
-(iso-ascii-display 222 "TH") ; capital thorn, Icelandic
-(iso-ascii-display 223 "ss") ; small sharp s, German
-(iso-ascii-display 224 "`a") ; a with grave accent
-(iso-ascii-display 225 "'a") ; a with acute accent
-(iso-ascii-display 226 "^a") ; a with circumflex accent
-(iso-ascii-display 227 "~a") ; a with tilde
-(iso-ascii-display 228 "\"a") ; a with diaeresis or umlaut mark
-(iso-ascii-display 229 "aa") ; a with ring
-(iso-ascii-display 230 "ae") ; ae diphthong
-(iso-ascii-display 231 ",c") ; c with cedilla
-(iso-ascii-display 232 "`e") ; e with grave accent
-(iso-ascii-display 233 "'e") ; e with acute accent
-(iso-ascii-display 234 "^e") ; e with circumflex accent
-(iso-ascii-display 235 "\"e") ; e with diaeresis or umlaut mark
-(iso-ascii-display 236 "`i") ; i with grave accent
-(iso-ascii-display 237 "'i") ; i with acute accent
-(iso-ascii-display 238 "^i") ; i with circumflex accent
-(iso-ascii-display 239 "\"i") ; i with diaeresis or umlaut mark
-(iso-ascii-display 240 "-d") ; d with stroke, Icelandic eth
-(iso-ascii-display 241 "~n") ; n with tilde
-(iso-ascii-display 242 "`o") ; o with grave accent
-(iso-ascii-display 243 "'o") ; o with acute accent
-(iso-ascii-display 244 "^o") ; o with circumflex accent
-(iso-ascii-display 245 "~o") ; o with tilde
-(iso-ascii-display 246 "\"o") ; o with diaeresis or umlaut mark
-(iso-ascii-display 247 "/") ; division sign
-(iso-ascii-display 248 "/o") ; o with slash
-(iso-ascii-display 249 "`u") ; u with grave accent
-(iso-ascii-display 250 "'u") ; u with acute accent
-(iso-ascii-display 251 "^u") ; u with circumflex accent
-(iso-ascii-display 252 "\"u") ; u with diaeresis or umlaut mark
-(iso-ascii-display 253 "'y") ; y with acute accent
-(iso-ascii-display 254 "th") ; small thorn, Icelandic
-(iso-ascii-display 255 "\"y") ; small y with diaeresis or umlaut mark
-
-(provide 'iso-ascii)
-
-;;; iso-ascii.el ends here
diff --git a/lisp/international/iso-cvt.el b/lisp/international/iso-cvt.el
deleted file mode 100644
index 150eed2a9f6..00000000000
--- a/lisp/international/iso-cvt.el
+++ /dev/null
@@ -1,717 +0,0 @@
-;;; iso-cvt.el --- translate to ISO 8859-1 from/to net/TeX conventions
-;; This file was formerly called gm-lingo.el.
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Michael Gschwind <mike@vlsivie.tuwien.ac.at>
-;; Keywords: tex, iso, latin, i18n
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This lisp code serves two purposes, both of which involve
-;; the translation of various conventions for representing European
-;; character sets to ISO 8859-1.
-
-;; Net support:
-;; Various conventions exist in Newsgroups on how to represent national
-;; characters. The functions provided here translate these net conventions
-;; to ISO.
-;;
-;; Calling `iso-german' will turn the net convention for umlauts ("a etc.)
-;; into ISO latin1 umlauts for easy reading.
-;; 'iso-spanish' will turn net conventions for representing spanish
-;; to ISO latin1. (Note that accents are omitted in news posts most
-;; of the time, only enye is escaped.)
-
-;; TeX support
-;; This mode installs hooks which change TeX files to ISO Latin-1 for
-;; simplified editing. When the TeX file is saved, ISO latin1 characters are
-;; translated back to escape sequences.
-;;
-;; An alternative is a TeX style that handles 8 bit ISO files
-;; (available on ftp.vlsivie.tuwien.ac.at in /pub/8bit)
-;; - but these files are difficult to transmit ... so while the net is
-;; still @ 7 bit this may be useful
-
-;;; TO DO:
-;; The net support should install hooks (like TeX support does)
-;; which recognizes certain news groups and translates all articles from
-;; those groups.
-;;
-;; Cover more cases for translation (There is an infinite number of ways to
-;; represent accented characters in TeX)
-
-;;; SEE ALSO:
-;; If you are interested in questions related to using the ISO 8859-1
-;; characters set (configuring emacs, Unix, etc. to use ISO), then you
-;; can get the ISO 8859-1 FAQ via anonymous ftp from
-;; ftp.vlsivie.tuwien.ac.at in /pub/bit/FAQ-ISO-8859-1
-
-;;; Code:
-
-(provide 'iso-cvt)
-
-(defvar iso-spanish-trans-tab
- '(
- ("~n" "ñ")
- ("\([a-zA-Z]\)#" "\\1ñ")
- ("~N" "Ñ")
- ("\\([-a-zA-Z\"`]\\)\"u" "\\1ü")
- ("\\([-a-zA-Z\"`]\\)\"U" "\\1Ü")
- ("\\([-a-zA-Z]\\)'o" "\\1ó")
- ("\\([-a-zA-Z]\\)'O" "\\Ó")
- ("\\([-a-zA-Z]\\)'e" "\\1é")
- ("\\([-a-zA-Z]\\)'E" "\\1É")
- ("\\([-a-zA-Z]\\)'a" "\\1á")
- ("\\([-a-zA-Z]\\)'A" "\\1A")
- ("\\([-a-zA-Z]\\)'i" "\\1í")
- ("\\([-a-zA-Z]\\)'I" "\\1Í")
- )
- "Spanish translation table.")
-
-(defun iso-translate-conventions (trans-tab)
- "Use the translation table TRANS-TAB to translate the current buffer."
- (save-excursion
- (goto-char (point-min))
- (let ((work-tab trans-tab)
- (buffer-read-only nil)
- (case-fold-search nil))
- (while work-tab
- (save-excursion
- (let ((trans-this (car work-tab)))
- (while (re-search-forward (car trans-this) nil t)
- (replace-match (car (cdr trans-this)) t nil)))
- (setq work-tab (cdr work-tab)))))))
-
-(defun iso-spanish ()
- "Translate net conventions for Spanish to ISO 8859-1."
- (interactive)
- (iso-translate-conventions iso-spanish-trans-tab))
-
-(defvar iso-aggressive-german-trans-tab
- '(
- ("\"a" "ä")
- ("\"A" "Ä")
- ("\"o" "ö")
- ("\"O" "Ö")
- ("\"u" "ü")
- ("\"U" "Ü")
- ("\"s" "ß")
- ("\\\\3" "ß")
- )
- "German translation table.
-This table uses an aggressive translation approach and may erroneously
-translate too much.")
-
-(defvar iso-conservative-german-trans-tab
- '(
- ("\\([-a-zA-Z\"`]\\)\"a" "\\1ä")
- ("\\([-a-zA-Z\"`]\\)\"A" "\\1Ä")
- ("\\([-a-zA-Z\"`]\\)\"o" "\\1ö")
- ("\\([-a-zA-Z\"`]\\)\"O" "\\1Ö")
- ("\\([-a-zA-Z\"`]\\)\"u" "\\1ü")
- ("\\([-a-zA-Z\"`]\\)\"U" "\\1Ü")
- ("\\([-a-zA-Z\"`]\\)\"s" "\\1ß")
- ("\\([-a-zA-Z\"`]\\)\\\\3" "\\1ß")
- )
- "German translation table.
-This table uses a conservative translation approach and may translate too
-little.")
-
-
-(defvar iso-german-trans-tab iso-aggressive-german-trans-tab
- "Currently active translation table for German.")
-
-(defun iso-german ()
- "Translate net conventions for German to ISO 8859-1."
- (interactive)
- (iso-translate-conventions iso-german-trans-tab))
-
-(defvar iso-iso2tex-trans-tab
- '(
- ("ä" "{\\\\\"a}")
- ("à" "{\\\\`a}")
- ("á" "{\\\\'a}")
- ("ã" "{\\\\~a}")
- ("â" "{\\\\^a}")
- ("ë" "{\\\\\"e}")
- ("è" "{\\\\`e}")
- ("é" "{\\\\'e}")
- ("ê" "{\\\\^e}")
- ("ï" "{\\\\\"\\\\i}")
- ("ì" "{\\\\`\\\\i}")
- ("í" "{\\\\'\\\\i}")
- ("î" "{\\\\^\\\\i}")
- ("ö" "{\\\\\"o}")
- ("ò" "{\\\\`o}")
- ("ó" "{\\\\'o}")
- ("õ" "{\\\\~o}")
- ("ô" "{\\\\^o}")
- ("ü" "{\\\\\"u}")
- ("ù" "{\\\\`u}")
- ("ú" "{\\\\'u}")
- ("û" "{\\\\^u}")
- ("Ä" "{\\\\\"A}")
- ("À" "{\\\\`A}")
- ("Á" "{\\\\'A}")
- ("Ã" "{\\\\~A}")
- ("Â" "{\\\\^A}")
- ("Ë" "{\\\\\"E}")
- ("È" "{\\\\`E}")
- ("É" "{\\\\'E}")
- ("Ê" "{\\\\^E}")
- ("Ï" "{\\\\\"I}")
- ("Ì" "{\\\\`I}")
- ("Í" "{\\\\'I}")
- ("Î" "{\\\\^I}")
- ("Ö" "{\\\\\"O}")
- ("Ò" "{\\\\`O}")
- ("Ó" "{\\\\'O}")
- ("Õ" "{\\\\~O}")
- ("Ô" "{\\\\^O}")
- ("Ü" "{\\\\\"U}")
- ("Ù" "{\\\\`U}")
- ("Ú" "{\\\\'U}")
- ("Û" "{\\\\^U}")
- ("ñ" "{\\\\~n}")
- ("Ñ" "{\\\\~N}")
- ("ç" "{\\\\c c}")
- ("Ç" "{\\\\c C}")
- ("ß" "{\\\\ss}")
- ("\306" "{\\\\AE}")
- ("\346" "{\\\\ae}")
- ("\305" "{\\\\AA}")
- ("\345" "{\\\\aa}")
- ("\251" "{\\\\copyright}")
- ("£" "{\\\\pounds}")
- ("¶" "{\\\\P}")
- ("§" "{\\\\S}")
- ("¿" "{?`}")
- ("¡" "{!`}")
- )
- "Translation table for translating ISO 8859-1 characters to TeX sequences.")
-
-
-
-
-(defun iso-iso2tex ()
- "Translate ISO 8859-1 characters to TeX sequences."
- (interactive)
- (iso-translate-conventions iso-iso2tex-trans-tab))
-
-
-(defvar iso-tex2iso-trans-tab
- '(
- ("{\\\\\"a}" "ä")
- ("{\\\\`a}" "à")
- ("{\\\\'a}" "á")
- ("{\\\\~a}" "ã")
- ("{\\\\^a}" "â")
- ("{\\\\\"e}" "ë")
- ("{\\\\`e}" "è")
- ("{\\\\'e}" "é")
- ("{\\\\^e}" "ê")
- ("{\\\\\"\\\\i}" "ï")
- ("{\\\\`\\\\i}" "ì")
- ("{\\\\'\\\\i}" "í")
- ("{\\\\^\\\\i}" "î")
- ("{\\\\\"i}" "ï")
- ("{\\\\`i}" "ì")
- ("{\\\\'i}" "í")
- ("{\\\\^i}" "î")
- ("{\\\\\"o}" "ö")
- ("{\\\\`o}" "ò")
- ("{\\\\'o}" "ó")
- ("{\\\\~o}" "õ")
- ("{\\\\^o}" "ô")
- ("{\\\\\"u}" "ü")
- ("{\\\\`u}" "ù")
- ("{\\\\'u}" "ú")
- ("{\\\\^u}" "û")
- ("{\\\\\"A}" "Ä")
- ("{\\\\`A}" "À")
- ("{\\\\'A}" "Á")
- ("{\\\\~A}" "Ã")
- ("{\\\\^A}" "Â")
- ("{\\\\\"E}" "Ë")
- ("{\\\\`E}" "È")
- ("{\\\\'E}" "É")
- ("{\\\\^E}" "Ê")
- ("{\\\\\"I}" "Ï")
- ("{\\\\`I}" "Ì")
- ("{\\\\'I}" "Í")
- ("{\\\\^I}" "Î")
- ("{\\\\\"O}" "Ö")
- ("{\\\\`O}" "Ò")
- ("{\\\\'O}" "Ó")
- ("{\\\\~O}" "Õ")
- ("{\\\\^O}" "Ô")
- ("{\\\\\"U}" "Ü")
- ("{\\\\`U}" "Ù")
- ("{\\\\'U}" "Ú")
- ("{\\\\^U}" "Û")
- ("{\\\\~n}" "ñ")
- ("{\\\\~N}" "Ñ")
- ("{\\\\c c}" "ç")
- ("{\\\\c C}" "Ç")
- ("\\\\\"a" "ä")
- ("\\\\`a" "à")
- ("\\\\'a" "á")
- ("\\\\~a" "ã")
- ("\\\\^a" "â")
- ("\\\\\"e" "ë")
- ("\\\\`e" "è")
- ("\\\\'e" "é")
- ("\\\\^e" "ê")
- ("\\\\\"\\\\i" "ï")
- ("\\\\`\\\\i" "ì")
- ("\\\\'\\\\i" "í")
- ("\\\\^\\\\i" "î")
- ("\\\\\"i" "ï")
- ("\\\\`i" "ì")
- ("\\\\'i" "í")
- ("\\\\^i" "î")
- ("\\\\\"o" "ö")
- ("\\\\`o" "ò")
- ("\\\\'o" "ó")
- ("\\\\~o" "õ")
- ("\\\\^o" "ô")
- ("\\\\\"u" "ü")
- ("\\\\`u" "ù")
- ("\\\\'u" "ú")
- ("\\\\^u" "û")
- ("\\\\\"A" "Ä")
- ("\\\\`A" "À")
- ("\\\\'A" "Á")
- ("\\\\~A" "Ã")
- ("\\\\^A" "Â")
- ("\\\\\"E" "Ë")
- ("\\\\`E" "È")
- ("\\\\'E" "É")
- ("\\\\^E" "Ê")
- ("\\\\\"I" "Ï")
- ("\\\\`I" "Ì")
- ("\\\\'I" "Í")
- ("\\\\^I" "Î")
- ("\\\\\"O" "Ö")
- ("\\\\`O" "Ò")
- ("\\\\'O" "Ó")
- ("\\\\~O" "Õ")
- ("\\\\^O" "Ô")
- ("\\\\\"U" "Ü")
- ("\\\\`U" "Ù")
- ("\\\\'U" "Ú")
- ("\\\\^U" "Û")
- ("\\\\~n" "ñ")
- ("\\\\~N" "Ñ")
- ("\\\\\"{a}" "ä")
- ("\\\\`{a}" "à")
- ("\\\\'{a}" "á")
- ("\\\\~{a}" "ã")
- ("\\\\^{a}" "â")
- ("\\\\\"{e}" "ë")
- ("\\\\`{e}" "è")
- ("\\\\'{e}" "é")
- ("\\\\^{e}" "ê")
- ("\\\\\"{\\\\i}" "ï")
- ("\\\\`{\\\\i}" "ì")
- ("\\\\'{\\\\i}" "í")
- ("\\\\^{\\\\i}" "î")
- ("\\\\\"{i}" "ï")
- ("\\\\`{i}" "ì")
- ("\\\\'{i}" "í")
- ("\\\\^{i}" "î")
- ("\\\\\"{o}" "ö")
- ("\\\\`{o}" "ò")
- ("\\\\'{o}" "ó")
- ("\\\\~{o}" "õ")
- ("\\\\^{o}" "ô")
- ("\\\\\"{u}" "ü")
- ("\\\\`{u}" "ù")
- ("\\\\'{u}" "ú")
- ("\\\\^{u}" "û")
- ("\\\\\"{A}" "Ä")
- ("\\\\`{A}" "À")
- ("\\\\'{A}" "Á")
- ("\\\\~{A}" "Ã")
- ("\\\\^{A}" "Â")
- ("\\\\\"{E}" "Ë")
- ("\\\\`{E}" "È")
- ("\\\\'{E}" "É")
- ("\\\\^{E}" "Ê")
- ("\\\\\"{I}" "Ï")
- ("\\\\`{I}" "Ì")
- ("\\\\'{I}" "Í")
- ("\\\\^{I}" "Î")
- ("\\\\\"{O}" "Ö")
- ("\\\\`{O}" "Ò")
- ("\\\\'{O}" "Ó")
- ("\\\\~{O}" "Õ")
- ("\\\\^{O}" "Ô")
- ("\\\\\"{U}" "Ü")
- ("\\\\`{U}" "Ù")
- ("\\\\'{U}" "Ú")
- ("\\\\^{U}" "Û")
- ("\\\\~{n}" "ñ")
- ("\\\\~{N}" "Ñ")
- ("\\\\c{c}" "ç")
- ("\\\\c{C}" "Ç")
- ("{\\\\ss}" "ß")
- ("{\\\\AE}" "\306")
- ("{\\\\ae}" "\346")
- ("{\\\\AA}" "\305")
- ("{\\\\aa}" "\345")
- ("{\\\\copyright}" "\251")
- ("\\\\copyright{}" "\251")
- ("{\\\\pounds}" "£" )
- ("{\\\\P}" "¶" )
- ("{\\\\S}" "§" )
- ("\\\\pounds{}" "£" )
- ("\\\\P{}" "¶" )
- ("\\\\S{}" "§" )
- ("{\\?`}" "¿")
- ("{!`}" "¡")
- ("\\?`" "¿")
- ("!`" "¡")
- )
- "Translation table for translating TeX sequences to ISO 8859-1 characters.
-This table is not exhaustive (and due to TeX's power can never be). It only
-contains commonly used sequences.")
-
-(defun iso-tex2iso ()
- "Translate TeX sequences to ISO 8859-1 characters."
- (interactive)
- (iso-translate-conventions iso-tex2iso-trans-tab))
-
-(defvar iso-gtex2iso-trans-tab
- '(
- ("{\\\\\"a}" "ä")
- ("{\\\\`a}" "à")
- ("{\\\\'a}" "á")
- ("{\\\\~a}" "ã")
- ("{\\\\^a}" "â")
- ("{\\\\\"e}" "ë")
- ("{\\\\`e}" "è")
- ("{\\\\'e}" "é")
- ("{\\\\^e}" "ê")
- ("{\\\\\"\\\\i}" "ï")
- ("{\\\\`\\\\i}" "ì")
- ("{\\\\'\\\\i}" "í")
- ("{\\\\^\\\\i}" "î")
- ("{\\\\\"i}" "ï")
- ("{\\\\`i}" "ì")
- ("{\\\\'i}" "í")
- ("{\\\\^i}" "î")
- ("{\\\\\"o}" "ö")
- ("{\\\\`o}" "ò")
- ("{\\\\'o}" "ó")
- ("{\\\\~o}" "õ")
- ("{\\\\^o}" "ô")
- ("{\\\\\"u}" "ü")
- ("{\\\\`u}" "ù")
- ("{\\\\'u}" "ú")
- ("{\\\\^u}" "û")
- ("{\\\\\"A}" "Ä")
- ("{\\\\`A}" "À")
- ("{\\\\'A}" "Á")
- ("{\\\\~A}" "Ã")
- ("{\\\\^A}" "Â")
- ("{\\\\\"E}" "Ë")
- ("{\\\\`E}" "È")
- ("{\\\\'E}" "É")
- ("{\\\\^E}" "Ê")
- ("{\\\\\"I}" "Ï")
- ("{\\\\`I}" "Ì")
- ("{\\\\'I}" "Í")
- ("{\\\\^I}" "Î")
- ("{\\\\\"O}" "Ö")
- ("{\\\\`O}" "Ò")
- ("{\\\\'O}" "Ó")
- ("{\\\\~O}" "Õ")
- ("{\\\\^O}" "Ô")
- ("{\\\\\"U}" "Ü")
- ("{\\\\`U}" "Ù")
- ("{\\\\'U}" "Ú")
- ("{\\\\^U}" "Û")
- ("{\\\\~n}" "ñ")
- ("{\\\\~N}" "Ñ")
- ("{\\\\c c}" "ç")
- ("{\\\\c C}" "Ç")
- ("\\\\\"a" "ä")
- ("\\\\`a" "à")
- ("\\\\'a" "á")
- ("\\\\~a" "ã")
- ("\\\\^a" "â")
- ("\\\\\"e" "ë")
- ("\\\\`e" "è")
- ("\\\\'e" "é")
- ("\\\\^e" "ê")
- ("\\\\\"\\\\i" "ï")
- ("\\\\`\\\\i" "ì")
- ("\\\\'\\\\i" "í")
- ("\\\\^\\\\i" "î")
- ("\\\\\"i" "ï")
- ("\\\\`i" "ì")
- ("\\\\'i" "í")
- ("\\\\^i" "î")
- ("\\\\\"o" "ö")
- ("\\\\`o" "ò")
- ("\\\\'o" "ó")
- ("\\\\~o" "õ")
- ("\\\\^o" "ô")
- ("\\\\\"u" "ü")
- ("\\\\`u" "ù")
- ("\\\\'u" "ú")
- ("\\\\^u" "û")
- ("\\\\\"A" "Ä")
- ("\\\\`A" "À")
- ("\\\\'A" "Á")
- ("\\\\~A" "Ã")
- ("\\\\^A" "Â")
- ("\\\\\"E" "Ë")
- ("\\\\`E" "È")
- ("\\\\'E" "É")
- ("\\\\^E" "Ê")
- ("\\\\\"I" "Ï")
- ("\\\\`I" "Ì")
- ("\\\\'I" "Í")
- ("\\\\^I" "Î")
- ("\\\\\"O" "Ö")
- ("\\\\`O" "Ò")
- ("\\\\'O" "Ó")
- ("\\\\~O" "Õ")
- ("\\\\^O" "Ô")
- ("\\\\\"U" "Ü")
- ("\\\\`U" "Ù")
- ("\\\\'U" "Ú")
- ("\\\\^U" "Û")
- ("\\\\~n" "ñ")
- ("\\\\~N" "Ñ")
- ("\\\\\"{a}" "ä")
- ("\\\\`{a}" "à")
- ("\\\\'{a}" "á")
- ("\\\\~{a}" "ã")
- ("\\\\^{a}" "â")
- ("\\\\\"{e}" "ë")
- ("\\\\`{e}" "è")
- ("\\\\'{e}" "é")
- ("\\\\^{e}" "ê")
- ("\\\\\"{\\\\i}" "ï")
- ("\\\\`{\\\\i}" "ì")
- ("\\\\'{\\\\i}" "í")
- ("\\\\^{\\\\i}" "î")
- ("\\\\\"{i}" "ï")
- ("\\\\`{i}" "ì")
- ("\\\\'{i}" "í")
- ("\\\\^{i}" "î")
- ("\\\\\"{o}" "ö")
- ("\\\\`{o}" "ò")
- ("\\\\'{o}" "ó")
- ("\\\\~{o}" "õ")
- ("\\\\^{o}" "ô")
- ("\\\\\"{u}" "ü")
- ("\\\\`{u}" "ù")
- ("\\\\'{u}" "ú")
- ("\\\\^{u}" "û")
- ("\\\\\"{A}" "Ä")
- ("\\\\`{A}" "À")
- ("\\\\'{A}" "Á")
- ("\\\\~{A}" "Ã")
- ("\\\\^{A}" "Â")
- ("\\\\\"{E}" "Ë")
- ("\\\\`{E}" "È")
- ("\\\\'{E}" "É")
- ("\\\\^{E}" "Ê")
- ("\\\\\"{I}" "Ï")
- ("\\\\`{I}" "Ì")
- ("\\\\'{I}" "Í")
- ("\\\\^{I}" "Î")
- ("\\\\\"{O}" "Ö")
- ("\\\\`{O}" "Ò")
- ("\\\\'{O}" "Ó")
- ("\\\\~{O}" "Õ")
- ("\\\\^{O}" "Ô")
- ("\\\\\"{U}" "Ü")
- ("\\\\`{U}" "Ù")
- ("\\\\'{U}" "Ú")
- ("\\\\^{U}" "Û")
- ("\\\\~{n}" "ñ")
- ("\\\\~{N}" "Ñ")
- ("\\\\c{c}" "ç")
- ("\\\\c{C}" "Ç")
- ("{\\\\ss}" "ß")
- ("{\\\\AE}" "\306")
- ("{\\\\ae}" "\346")
- ("{\\\\AA}" "\305")
- ("{\\\\aa}" "\345")
- ("{\\\\copyright}" "\251")
- ("\\\\copyright{}" "\251")
- ("{\\\\pounds}" "£" )
- ("{\\\\P}" "¶" )
- ("{\\\\S}" "§" )
- ("\\\\pounds{}" "£" )
- ("\\\\P{}" "¶" )
- ("\\\\S{}" "§" )
- ("?`" "¿")
- ("!`" "¡")
- ("{?`}" "¿")
- ("{!`}" "¡")
- ("\"a" "ä")
- ("\"A" "Ä")
- ("\"o" "ö")
- ("\"O" "Ö")
- ("\"u" "ü")
- ("\"U" "Ü")
- ("\"s" "ß")
- ("\\\\3" "ß")
- )
- "Translation table for translating German TeX sequences to ISO 8859-1.
-This table is not exhaustive (and due to TeX's power can never be). It only
-contains commonly used sequences.")
-
-(defvar iso-iso2gtex-trans-tab
- '(
- ("ä" "\"a")
- ("à" "{\\\\`a}")
- ("á" "{\\\\'a}")
- ("ã" "{\\\\~a}")
- ("â" "{\\\\^a}")
- ("ë" "{\\\\\"e}")
- ("è" "{\\\\`e}")
- ("é" "{\\\\'e}")
- ("ê" "{\\\\^e}")
- ("ï" "{\\\\\"\\\\i}")
- ("ì" "{\\\\`\\\\i}")
- ("í" "{\\\\'\\\\i}")
- ("î" "{\\\\^\\\\i}")
- ("ö" "\"o")
- ("ò" "{\\\\`o}")
- ("ó" "{\\\\'o}")
- ("õ" "{\\\\~o}")
- ("ô" "{\\\\^o}")
- ("ü" "\"u")
- ("ù" "{\\\\`u}")
- ("ú" "{\\\\'u}")
- ("û" "{\\\\^u}")
- ("Ä" "\"A")
- ("À" "{\\\\`A}")
- ("Á" "{\\\\'A}")
- ("Ã" "{\\\\~A}")
- ("Â" "{\\\\^A}")
- ("Ë" "{\\\\\"E}")
- ("È" "{\\\\`E}")
- ("É" "{\\\\'E}")
- ("Ê" "{\\\\^E}")
- ("Ï" "{\\\\\"I}")
- ("Ì" "{\\\\`I}")
- ("Í" "{\\\\'I}")
- ("Î" "{\\\\^I}")
- ("Ö" "\"O")
- ("Ò" "{\\\\`O}")
- ("Ó" "{\\\\'O}")
- ("Õ" "{\\\\~O}")
- ("Ô" "{\\\\^O}")
- ("Ü" "\"U")
- ("Ù" "{\\\\`U}")
- ("Ú" "{\\\\'U}")
- ("Û" "{\\\\^U}")
- ("ñ" "{\\\\~n}")
- ("Ñ" "{\\\\~N}")
- ("ç" "{\\\\c c}")
- ("Ç" "{\\\\c C}")
- ("ß" "\"s")
- ("\306" "{\\\\AE}")
- ("\346" "{\\\\ae}")
- ("\305" "{\\\\AA}")
- ("\345" "{\\\\aa}")
- ("\251" "{\\\\copyright}")
- ("£" "{\\\\pounds}")
- ("¶" "{\\\\P}")
- ("§" "{\\\\S}")
- ("¿" "{?`}")
- ("¡" "{!`}")
- )
- "Translation table for translating ISO 8859-1 characters to German TeX.")
-
-(defun iso-gtex2iso ()
- "Translate German TeX sequences to ISO 8859-1 characters."
- (interactive)
- (iso-translate-conventions iso-gtex2iso-trans-tab))
-
-
-(defun iso-iso2gtex ()
- "Translate ISO 8859-1 characters to German TeX sequences."
- (interactive)
- (iso-translate-conventions iso-iso2gtex-trans-tab))
-
-
-(defun iso-german-tex-p ()
- "Check if tex buffer is German LaTeX."
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (re-search-forward "\\\\documentstyle\\[.*german.*\\]" nil t))))
-
-(defun iso-fix-iso2tex ()
- "Turn ISO 8859-1 (aka. ISO Latin-1) buffer into TeX sequences.
-If German TeX is used, German TeX sequences are generated."
- (if (or (equal major-mode 'latex-mode)
- (equal major-mode 'LaTeX-mode)) ; AucTeX wants this
- (if (iso-german-tex-p)
- (iso-iso2gtex)
- (iso-iso2tex)))
- (if (or (equal major-mode 'tex-mode)
- (equal major-mode 'TeX-mode) ; AucTeX wants this
- (equal major-mode 'plain-tex-mode))
- (iso-iso2tex)))
-
-(defun iso-fix-tex2iso ()
- "Turn TeX sequences into ISO 8859-1 (aka. ISO Latin-1) characters.
-This function recognizes German TeX buffers."
- (if (or (equal major-mode 'latex-mode)
- (equal major-mode 'Latex-mode)) ; AucTeX wants this
- (if (iso-german-tex-p)
- (iso-gtex2iso)
- (iso-tex2iso)))
- (if (or (equal major-mode 'tex-mode)
- (equal major-mode 'TeX-mode) ; AucTeX wants this
- (equal major-mode 'plain-tex-mode))
- (iso-tex2iso)))
-
-(defun iso-cvt-ffh ()
- "find-file-hook for iso-cvt.el."
- (iso-fix-tex2iso)
- (set-buffer-modified-p nil))
-
-(defun iso-cvt-wfh ()
- "write file hook for iso-cvt.el."
- (iso-fix-iso2tex))
-
-(defun iso-cvt-ash ()
- "after save hook for iso-cvt.el."
- (iso-fix-tex2iso)
- (set-buffer-modified-p nil))
-
-(add-hook 'find-file-hooks 'iso-cvt-ffh)
-(add-hook 'write-file-hooks 'iso-cvt-wfh)
-(add-hook 'after-save-hook 'iso-cvt-ash)
-
-;;; iso-cvt.el ends here
diff --git a/lisp/international/iso-insert.el b/lisp/international/iso-insert.el
deleted file mode 100644
index 870fc1afeea..00000000000
--- a/lisp/international/iso-insert.el
+++ /dev/null
@@ -1,629 +0,0 @@
-;;; iso-insert.el --- insert functions for ISO 8859/1.
-
-;; Copyright (C) 1987, 1994 Free Software Foundation, Inc.
-
-;; Author: Howard Gayle
-;; Maintainer: FSF
-;; Keywords: i18n
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Written by Howard Gayle. See case-table.el for details.
-
-;;; Code:
-
-(defun insert-no-break-space ()
- (interactive "*")
- (insert 160)
-)
-
-(defun insert-inverted-exclamation-mark ()
- (interactive "*")
- (insert 161)
-)
-
-(defun insert-cent-sign ()
- (interactive "*")
- (insert 162)
-)
-
-(defun insert-pound-sign ()
- (interactive "*")
- (insert 163)
-)
-
-(defun insert-general-currency-sign ()
- (interactive "*")
- (insert 164)
-)
-
-(defun insert-yen-sign ()
- (interactive "*")
- (insert 165)
-)
-
-(defun insert-broken-vertical-line ()
- (interactive "*")
- (insert 166)
-)
-
-(defun insert-section-sign ()
- (interactive "*")
- (insert 167)
-)
-
-(defun insert-diaeresis ()
- (interactive "*")
- (insert 168)
-)
-
-(defun insert-copyright-sign ()
- (interactive "*")
- (insert 169)
-)
-
-(defun insert-ordinal-indicator-feminine ()
- (interactive "*")
- (insert 170)
-)
-
-(defun insert-angle-quotation-mark-left ()
- (interactive "*")
- (insert 171)
-)
-
-(defun insert-not-sign ()
- (interactive "*")
- (insert 172)
-)
-
-(defun insert-soft-hyphen ()
- (interactive "*")
- (insert 173)
-)
-
-(defun insert-registered-sign ()
- (interactive "*")
- (insert 174)
-)
-
-(defun insert-macron ()
- (interactive "*")
- (insert 175)
-)
-
-(defun insert-degree-sign ()
- (interactive "*")
- (insert 176)
-)
-
-(defun insert-plus-or-minus-sign ()
- (interactive "*")
- (insert 177)
-)
-
-(defun insert-superscript-two ()
- (interactive "*")
- (insert 178)
-)
-
-(defun insert-superscript-three ()
- (interactive "*")
- (insert 179)
-)
-
-(defun insert-acute-accent ()
- (interactive "*")
- (insert 180)
-)
-
-(defun insert-micro-sign ()
- (interactive "*")
- (insert 181)
-)
-
-(defun insert-pilcrow ()
- (interactive "*")
- (insert 182)
-)
-
-(defun insert-middle-dot ()
- (interactive "*")
- (insert 183)
-)
-
-(defun insert-cedilla ()
- (interactive "*")
- (insert 184)
-)
-
-(defun insert-superscript-one ()
- (interactive "*")
- (insert 185)
-)
-
-(defun insert-ordinal-indicator-masculine ()
- (interactive "*")
- (insert 186)
-)
-
-(defun insert-angle-quotation-mark-right ()
- (interactive "*")
- (insert 187)
-)
-
-(defun insert-fraction-one-quarter ()
- (interactive "*")
- (insert 188)
-)
-
-(defun insert-fraction-one-half ()
- (interactive "*")
- (insert 189)
-)
-
-(defun insert-fraction-three-quarters ()
- (interactive "*")
- (insert 190)
-)
-
-(defun insert-inverted-question-mark ()
- (interactive "*")
- (insert 191)
-)
-
-(defun insert-A-grave ()
- (interactive "*")
- (insert 192)
-)
-
-(defun insert-A-acute ()
- (interactive "*")
- (insert 193)
-)
-
-(defun insert-A-circumflex ()
- (interactive "*")
- (insert 194)
-)
-
-(defun insert-A-tilde ()
- (interactive "*")
- (insert 195)
-)
-
-(defun insert-A-umlaut ()
- (interactive "*")
- (insert 196)
-)
-
-(defun insert-A-ring ()
- (interactive "*")
- (insert 197)
-)
-
-(defun insert-AE ()
- (interactive "*")
- (insert 198)
-)
-
-(defun insert-C-cedilla ()
- (interactive "*")
- (insert 199)
-)
-
-(defun insert-E-grave ()
- (interactive "*")
- (insert 200)
-)
-
-(defun insert-E-acute ()
- (interactive "*")
- (insert 201)
-)
-
-(defun insert-E-circumflex ()
- (interactive "*")
- (insert 202)
-)
-
-(defun insert-E-umlaut ()
- (interactive "*")
- (insert 203)
-)
-
-(defun insert-I-grave ()
- (interactive "*")
- (insert 204)
-)
-
-(defun insert-I-acute ()
- (interactive "*")
- (insert 205)
-)
-
-(defun insert-I-circumflex ()
- (interactive "*")
- (insert 206)
-)
-
-(defun insert-I-umlaut ()
- (interactive "*")
- (insert 207)
-)
-
-(defun insert-D-stroke ()
- (interactive "*")
- (insert 208)
-)
-
-(defun insert-N-tilde ()
- (interactive "*")
- (insert 209)
-)
-
-(defun insert-O-grave ()
- (interactive "*")
- (insert 210)
-)
-
-(defun insert-O-acute ()
- (interactive "*")
- (insert 211)
-)
-
-(defun insert-O-circumflex ()
- (interactive "*")
- (insert 212)
-)
-
-(defun insert-O-tilde ()
- (interactive "*")
- (insert 213)
-)
-
-(defun insert-O-umlaut ()
- (interactive "*")
- (insert 214)
-)
-
-(defun insert-multiplication-sign ()
- (interactive "*")
- (insert 215)
-)
-
-(defun insert-O-slash ()
- (interactive "*")
- (insert 216)
-)
-
-(defun insert-U-grave ()
- (interactive "*")
- (insert 217)
-)
-
-(defun insert-U-acute ()
- (interactive "*")
- (insert 218)
-)
-
-(defun insert-U-circumflex ()
- (interactive "*")
- (insert 219)
-)
-
-(defun insert-U-umlaut ()
- (interactive "*")
- (insert 220)
-)
-
-(defun insert-Y-acute ()
- (interactive "*")
- (insert 221)
-)
-
-(defun insert-THORN ()
- (interactive "*")
- (insert 222)
-)
-
-(defun insert-ss ()
- (interactive "*")
- (insert 223)
-)
-
-(defun insert-a-grave ()
- (interactive "*")
- (insert 224)
-)
-
-(defun insert-a-acute ()
- (interactive "*")
- (insert 225)
-)
-
-(defun insert-a-circumflex ()
- (interactive "*")
- (insert 226)
-)
-
-(defun insert-a-tilde ()
- (interactive "*")
- (insert 227)
-)
-
-(defun insert-a-umlaut ()
- (interactive "*")
- (insert 228)
-)
-
-(defun insert-a-ring ()
- (interactive "*")
- (insert 229)
-)
-
-(defun insert-ae ()
- (interactive "*")
- (insert 230)
-)
-
-(defun insert-c-cedilla ()
- (interactive "*")
- (insert 231)
-)
-
-(defun insert-e-grave ()
- (interactive "*")
- (insert 232)
-)
-
-(defun insert-e-acute ()
- (interactive "*")
- (insert 233)
-)
-
-(defun insert-e-circumflex ()
- (interactive "*")
- (insert 234)
-)
-
-(defun insert-e-umlaut ()
- (interactive "*")
- (insert 235)
-)
-
-(defun insert-i-grave ()
- (interactive "*")
- (insert 236)
-)
-
-(defun insert-i-acute ()
- (interactive "*")
- (insert 237)
-)
-
-(defun insert-i-circumflex ()
- (interactive "*")
- (insert 238)
-)
-
-(defun insert-i-umlaut ()
- (interactive "*")
- (insert 239)
-)
-
-(defun insert-d-stroke ()
- (interactive "*")
- (insert 240)
-)
-
-(defun insert-n-tilde ()
- (interactive "*")
- (insert 241)
-)
-
-(defun insert-o-grave ()
- (interactive "*")
- (insert 242)
-)
-
-(defun insert-o-acute ()
- (interactive "*")
- (insert 243)
-)
-
-(defun insert-o-circumflex ()
- (interactive "*")
- (insert 244)
-)
-
-(defun insert-o-tilde ()
- (interactive "*")
- (insert 245)
-)
-
-(defun insert-o-umlaut ()
- (interactive "*")
- (insert 246)
-)
-
-(defun insert-division-sign ()
- (interactive "*")
- (insert 247)
-)
-
-(defun insert-o-slash ()
- (interactive "*")
- (insert 248)
-)
-
-(defun insert-u-grave ()
- (interactive "*")
- (insert 249)
-)
-
-(defun insert-u-acute ()
- (interactive "*")
- (insert 250)
-)
-
-(defun insert-u-circumflex ()
- (interactive "*")
- (insert 251)
-)
-
-(defun insert-u-umlaut ()
- (interactive "*")
- (insert 252)
-)
-
-(defun insert-y-acute ()
- (interactive "*")
- (insert 253)
-)
-
-(defun insert-thorn ()
- (interactive "*")
- (insert 254)
-)
-
-(defun insert-y-umlaut ()
- (interactive "*")
- (insert 255)
-)
-
-(defvar 8859-1-map nil "Keymap for ISO 8859/1 character insertion.")
-(if 8859-1-map nil
- (setq 8859-1-map (make-keymap))
- (define-key 8859-1-map " " 'insert-no-break-space)
- (define-key 8859-1-map "!" 'insert-inverted-exclamation-mark)
- (define-key 8859-1-map "\"" (make-sparse-keymap))
- (define-key 8859-1-map "\"\"" 'insert-diaeresis)
- (define-key 8859-1-map "\"A" 'insert-A-umlaut)
- (define-key 8859-1-map "\"E" 'insert-E-umlaut)
- (define-key 8859-1-map "\"I" 'insert-I-umlaut)
- (define-key 8859-1-map "\"O" 'insert-O-umlaut)
- (define-key 8859-1-map "\"U" 'insert-U-umlaut)
- (define-key 8859-1-map "\"a" 'insert-a-umlaut)
- (define-key 8859-1-map "\"e" 'insert-e-umlaut)
- (define-key 8859-1-map "\"i" 'insert-i-umlaut)
- (define-key 8859-1-map "\"o" 'insert-o-umlaut)
- (define-key 8859-1-map "\"u" 'insert-u-umlaut)
- (define-key 8859-1-map "\"y" 'insert-y-umlaut)
- (define-key 8859-1-map "'" (make-sparse-keymap))
- (define-key 8859-1-map "''" 'insert-acute-accent)
- (define-key 8859-1-map "'A" 'insert-A-acute)
- (define-key 8859-1-map "'E" 'insert-E-acute)
- (define-key 8859-1-map "'I" 'insert-I-acute)
- (define-key 8859-1-map "'O" 'insert-O-acute)
- (define-key 8859-1-map "'U" 'insert-U-acute)
- (define-key 8859-1-map "'Y" 'insert-Y-acute)
- (define-key 8859-1-map "'a" 'insert-a-acute)
- (define-key 8859-1-map "'e" 'insert-e-acute)
- (define-key 8859-1-map "'i" 'insert-i-acute)
- (define-key 8859-1-map "'o" 'insert-o-acute)
- (define-key 8859-1-map "'u" 'insert-u-acute)
- (define-key 8859-1-map "'y" 'insert-y-acute)
- (define-key 8859-1-map "$" 'insert-general-currency-sign)
- (define-key 8859-1-map "+" 'insert-plus-or-minus-sign)
- (define-key 8859-1-map "," (make-sparse-keymap))
- (define-key 8859-1-map ",," 'insert-cedilla)
- (define-key 8859-1-map ",C" 'insert-C-cedilla)
- (define-key 8859-1-map ",c" 'insert-c-cedilla)
- (define-key 8859-1-map "-" 'insert-soft-hyphen)
- (define-key 8859-1-map "." 'insert-middle-dot)
- (define-key 8859-1-map "/" (make-sparse-keymap))
- (define-key 8859-1-map "//" 'insert-division-sign)
- (define-key 8859-1-map "/O" 'insert-O-slash)
- (define-key 8859-1-map "/o" 'insert-o-slash)
- (define-key 8859-1-map "1" (make-sparse-keymap))
- (define-key 8859-1-map "1/" (make-sparse-keymap))
- (define-key 8859-1-map "1/2" 'insert-fraction-one-half)
- (define-key 8859-1-map "1/4" 'insert-fraction-one-quarter)
- (define-key 8859-1-map "3" (make-sparse-keymap))
- (define-key 8859-1-map "3/" (make-sparse-keymap))
- (define-key 8859-1-map "3/4" 'insert-fraction-three-quarters)
- (define-key 8859-1-map "<" 'insert-angle-quotation-mark-left)
- (define-key 8859-1-map "=" 'insert-macron)
- (define-key 8859-1-map ">" 'insert-angle-quotation-mark-right)
- (define-key 8859-1-map "?" 'insert-inverted-question-mark)
- (define-key 8859-1-map "A" 'insert-A-ring)
- (define-key 8859-1-map "E" 'insert-AE)
- (define-key 8859-1-map "C" 'insert-copyright-sign)
- (define-key 8859-1-map "D" 'insert-D-stroke)
- (define-key 8859-1-map "L" 'insert-pound-sign)
- (define-key 8859-1-map "P" 'insert-pilcrow)
- (define-key 8859-1-map "R" 'insert-registered-sign)
- (define-key 8859-1-map "S" 'insert-section-sign)
- (define-key 8859-1-map "T" 'insert-THORN)
- (define-key 8859-1-map "Y" 'insert-yen-sign)
- (define-key 8859-1-map "^" (make-sparse-keymap))
- (define-key 8859-1-map "^1" 'insert-superscript-one)
- (define-key 8859-1-map "^2" 'insert-superscript-two)
- (define-key 8859-1-map "^3" 'insert-superscript-three)
- (define-key 8859-1-map "^A" 'insert-A-circumflex)
- (define-key 8859-1-map "^E" 'insert-E-circumflex)
- (define-key 8859-1-map "^I" 'insert-I-circumflex)
- (define-key 8859-1-map "^O" 'insert-O-circumflex)
- (define-key 8859-1-map "^U" 'insert-U-circumflex)
- (define-key 8859-1-map "^a" 'insert-a-circumflex)
- (define-key 8859-1-map "^e" 'insert-e-circumflex)
- (define-key 8859-1-map "^i" 'insert-i-circumflex)
- (define-key 8859-1-map "^o" 'insert-o-circumflex)
- (define-key 8859-1-map "^u" 'insert-u-circumflex)
- (define-key 8859-1-map "_" (make-sparse-keymap))
- (define-key 8859-1-map "_a" 'insert-ordinal-indicator-feminine)
- (define-key 8859-1-map "_o" 'insert-ordinal-indicator-masculine)
- (define-key 8859-1-map "`" (make-sparse-keymap))
- (define-key 8859-1-map "`A" 'insert-A-grave)
- (define-key 8859-1-map "`E" 'insert-E-grave)
- (define-key 8859-1-map "`I" 'insert-I-grave)
- (define-key 8859-1-map "`O" 'insert-O-grave)
- (define-key 8859-1-map "`U" 'insert-U-grave)
- (define-key 8859-1-map "`a" 'insert-a-grave)
- (define-key 8859-1-map "`e" 'insert-e-grave)
- (define-key 8859-1-map "`i" 'insert-i-grave)
- (define-key 8859-1-map "`o" 'insert-o-grave)
- (define-key 8859-1-map "`u" 'insert-u-grave)
- (define-key 8859-1-map "a" 'insert-a-ring)
- (define-key 8859-1-map "e" 'insert-ae)
- (define-key 8859-1-map "c" 'insert-cent-sign)
- (define-key 8859-1-map "d" 'insert-d-stroke)
- (define-key 8859-1-map "o" 'insert-degree-sign)
- (define-key 8859-1-map "s" 'insert-ss)
- (define-key 8859-1-map "t" 'insert-thorn)
- (define-key 8859-1-map "u" 'insert-micro-sign)
- (define-key 8859-1-map "x" 'insert-multiplication-sign)
- (define-key 8859-1-map "|" 'insert-broken-vertical-line)
- (define-key 8859-1-map "~" (make-sparse-keymap))
- (define-key 8859-1-map "~A" 'insert-A-tilde)
- (define-key 8859-1-map "~N" 'insert-N-tilde)
- (define-key 8859-1-map "~O" 'insert-O-tilde)
- (define-key 8859-1-map "~a" 'insert-a-tilde)
- (define-key 8859-1-map "~n" 'insert-n-tilde)
- (define-key 8859-1-map "~o" 'insert-o-tilde)
- (define-key 8859-1-map "~~" 'insert-not-sign)
- (if (not (lookup-key global-map "\C-x8"))
- (define-key global-map "\C-x8" 8859-1-map))
-)
-
-(provide 'iso-insert)
-
-;;; iso-insert.el ends here
diff --git a/lisp/international/iso-swed.el b/lisp/international/iso-swed.el
deleted file mode 100644
index 30ede7c30de..00000000000
--- a/lisp/international/iso-swed.el
+++ /dev/null
@@ -1,151 +0,0 @@
-;;; iso-swed.el --- set up char tables for ISO 8859/1 for Swedish/Finnish ttys
-
-;; Copyright (C) 1987 Free Software Foundation, Inc.
-
-;; Author: Howard Gayle
-;; Maintainer: FSF
-;; Keywords: i18n
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Written by Howard Gayle. See case-table.el for details.
-
-;;; Code:
-
-;; This code sets up to display ISO 8859/1 characters on
-;; terminals that have ASCII in the G0 set and a Swedish/Finnish
-;; version of ISO 646 in the G1 set. The G1 set differs from
-;; ASCII as follows:
-;;
-;; ASCII G1
-;; $ general currency sign
-;; @ capital E with acute accent
-;; [ capital A with diaeresis or umlaut mark
-;; \ capital O with diaeresis or umlaut mark
-;; ] capital A with ring
-;; ^ capital U with diaeresis or umlaut mark
-;; ` small e with acute accent
-;; { small a with diaeresis or umlaut mark
-;; | small o with diaeresis or umlaut mark
-;; } small a with ring
-;; ~ small u with diaeresis or umlaut mark
-
-(require 'disp-table)
-
-(standard-display-ascii 160 "{_}") ; NBSP (no-break space)
-(standard-display-ascii 161 "{!}") ; inverted exclamation mark
-(standard-display-ascii 162 "{c}") ; cent sign
-(standard-display-ascii 163 "{GBP}") ; pound sign
-(standard-display-g1 164 ?$) ; general currency sign
-(standard-display-ascii 165 "{JPY}") ; yen sign
-(standard-display-ascii 166 "{|}") ; broken vertical line
-(standard-display-ascii 167 "{S}") ; section sign
-(standard-display-ascii 168 "{\"}") ; diaeresis
-(standard-display-ascii 169 "{C}") ; copyright sign
-(standard-display-ascii 170 "{_a}") ; ordinal indicator, feminine
-(standard-display-ascii 171 "{<<}") ; left angle quotation mark
-(standard-display-ascii 172 "{~}") ; not sign
-(standard-display-ascii 173 "{-}") ; soft hyphen
-(standard-display-ascii 174 "{R}") ; registered sign
-(standard-display-ascii 175 "{=}") ; macron
-(standard-display-ascii 176 "{o}") ; degree sign
-(standard-display-ascii 177 "{+-}") ; plus or minus sign
-(standard-display-ascii 178 "{2}") ; superscript two
-(standard-display-ascii 179 "{3}") ; superscript three
-(standard-display-ascii 180 "{'}") ; acute accent
-(standard-display-ascii 181 "{u}") ; micro sign
-(standard-display-ascii 182 "{P}") ; pilcrow
-(standard-display-ascii 183 "{.}") ; middle dot
-(standard-display-ascii 184 "{,}") ; cedilla
-(standard-display-ascii 185 "{1}") ; superscript one
-(standard-display-ascii 186 "{_o}") ; ordinal indicator, masculine
-(standard-display-ascii 187 "{>>}") ; right angle quotation mark
-(standard-display-ascii 188 "{1/4}") ; fraction one-quarter
-(standard-display-ascii 189 "{1/2}") ; fraction one-half
-(standard-display-ascii 190 "{3/4}") ; fraction three-quarters
-(standard-display-ascii 191 "{?}") ; inverted question mark
-(standard-display-ascii 192 "{`A}") ; A with grave accent
-(standard-display-ascii 193 "{'A}") ; A with acute accent
-(standard-display-ascii 194 "{^A}") ; A with circumflex accent
-(standard-display-ascii 195 "{~A}") ; A with tilde
-(standard-display-g1 196 ?[) ; A with diaeresis or umlaut mark
-(standard-display-g1 197 ?]) ; A with ring
-(standard-display-ascii 198 "{AE}") ; AE diphthong
-(standard-display-ascii 199 "{,C}") ; C with cedilla
-(standard-display-ascii 200 "{`E}") ; E with grave accent
-(standard-display-g1 201 ?@) ; E with acute accent
-(standard-display-ascii 202 "{^E}") ; E with circumflex accent
-(standard-display-ascii 203 "{\"E}") ; E with diaeresis or umlaut mark
-(standard-display-ascii 204 "{`I}") ; I with grave accent
-(standard-display-ascii 205 "{'I}") ; I with acute accent
-(standard-display-ascii 206 "{^I}") ; I with circumflex accent
-(standard-display-ascii 207 "{\"I}") ; I with diaeresis or umlaut mark
-(standard-display-ascii 208 "{-D}") ; D with stroke, Icelandic eth
-(standard-display-ascii 209 "{~N}") ; N with tilde
-(standard-display-ascii 210 "{`O}") ; O with grave accent
-(standard-display-ascii 211 "{'O}") ; O with acute accent
-(standard-display-ascii 212 "{^O}") ; O with circumflex accent
-(standard-display-ascii 213 "{~O}") ; O with tilde
-(standard-display-g1 214 ?\\) ; O with diaeresis or umlaut mark
-(standard-display-ascii 215 "{x}") ; multiplication sign
-(standard-display-ascii 216 "{/O}") ; O with slash
-(standard-display-ascii 217 "{`U}") ; U with grave accent
-(standard-display-ascii 218 "{'U}") ; U with acute accent
-(standard-display-ascii 219 "{^U}") ; U with circumflex accent
-(standard-display-g1 220 ?^) ; U with diaeresis or umlaut mark
-(standard-display-ascii 221 "{'Y}") ; Y with acute accent
-(standard-display-ascii 222 "{TH}") ; capital thorn, Icelandic
-(standard-display-ascii 223 "{ss}") ; small sharp s, German
-(standard-display-ascii 224 "{`a}") ; a with grave accent
-(standard-display-ascii 225 "{'a}") ; a with acute accent
-(standard-display-ascii 226 "{^a}") ; a with circumflex accent
-(standard-display-ascii 227 "{~a}") ; a with tilde
-(standard-display-g1 228 ?{) ; a with diaeresis or umlaut mark
-(standard-display-g1 229 ?}) ; a with ring
-(standard-display-ascii 230 "{ae}") ; ae diphthong
-(standard-display-ascii 231 "{,c}") ; c with cedilla
-(standard-display-ascii 232 "{`e}") ; e with grave accent
-(standard-display-g1 233 ?`) ; e with acute accent
-(standard-display-ascii 234 "{^e}") ; e with circumflex accent
-(standard-display-ascii 235 "{\"e}") ; e with diaeresis or umlaut mark
-(standard-display-ascii 236 "{`i}") ; i with grave accent
-(standard-display-ascii 237 "{'i}") ; i with acute accent
-(standard-display-ascii 238 "{^i}") ; i with circumflex accent
-(standard-display-ascii 239 "{\"i}") ; i with diaeresis or umlaut mark
-(standard-display-ascii 240 "{-d}") ; d with stroke, Icelandic eth
-(standard-display-ascii 241 "{~n}") ; n with tilde
-(standard-display-ascii 242 "{`o}") ; o with grave accent
-(standard-display-ascii 243 "{'o}") ; o with acute accent
-(standard-display-ascii 244 "{^o}") ; o with circumflex accent
-(standard-display-ascii 245 "{~o}") ; o with tilde
-(standard-display-g1 246 ?|) ; o with diaeresis or umlaut mark
-(standard-display-ascii 247 "{/}") ; division sign
-(standard-display-ascii 248 "{/o}") ; o with slash
-(standard-display-ascii 249 "{`u}") ; u with grave accent
-(standard-display-ascii 250 "{'u}") ; u with acute accent
-(standard-display-ascii 251 "{^u}") ; u with circumflex accent
-(standard-display-g1 252 ?~) ; u with diaeresis or umlaut mark
-(standard-display-ascii 253 "{'y}") ; y with acute accent
-(standard-display-ascii 254 "{th}") ; small thorn, Icelandic
-(standard-display-ascii 255 "{\"y}") ; small y with diaeresis or umlaut mark
-
-(provide 'iso-swed)
-
-;;; iso-swed.el ends here
diff --git a/lisp/international/iso-transl.el b/lisp/international/iso-transl.el
deleted file mode 100644
index 4b39ccea632..00000000000
--- a/lisp/international/iso-transl.el
+++ /dev/null
@@ -1,259 +0,0 @@
-;;; iso-transl.el --- keyboard input definitions for ISO 8859/1.
-
-;; Copyright (C) 1987, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Howard Gayle
-;; Maintainer: FSF
-;; Keywords: i18n
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Loading this package defines three ways of entering the non-ASCII
-;; printable characters with codes above 127: the prefix C-x 8, or the
-;; Alt key, or a dead accent key. For example, you can enter uppercase
-;; A-umlaut as `C-x 8 " A' or `Alt-" A' (if you have an Alt key) or
-;; `umlaut A' (if you have an umlaut/diaeresis key).
-
-;;; Code:
-
-(defvar iso-transl-dead-key-alist
- '((?\' . mute-acute)
- (?\` . mute-grave)
- (?\" . mute-diaeresis)
- (?^ . mute-asciicircum)
- (?\~ . mute-asciitilde)
- (?\' . dead-acute)
- (?\` . dead-grave)
- (?\" . dead-diaeresis)
- (?^ . dead-asciicircum)
- (?\~ . dead-asciitilde)
- (?^ . dead-circum)
- (?^ . dead-circumflex)
- (?\~ . dead-tilde)
- ;; Someone reports that these keys don't work if shifted.
- ;; This might fix it--no word yet.
- (?\' . S-dead-acute)
- (?\` . S-dead-grave)
- (?\" . S-dead-diaeresis)
- (?^ . S-dead-asciicircum)
- (?\~ . S-dead-asciitilde)
- (?^ . S-dead-circum)
- (?^ . S-dead-circumflex)
- (?\~ . S-dead-tilde))
- "Mapping of ASCII characters to their corresponding dead-key symbols.")
-
-;; The two-character mnemonics are intended to be available in all languages.
-;; The ones beginning with `*' have one-character synonyms, but a
-;; language-specific table might override the short form for its own use.
-(defvar iso-transl-char-map
- '(("* " . [160])(" " . [160])
- ("*!" . [161])("!" . [161])
- ("\"\"" . [168])
- ("\"A" . [196])
- ("\"E" . [203])
- ("\"I" . [207])
- ("\"O" . [214])
- ("\"U" . [220])
- ("\"a" . [228])
- ("\"e" . [235])
- ("\"i" . [239])
- ("\"o" . [246])
- ("\"s" . [223])
- ("\"u" . [252])
- ("\"y" . [255])
- ("''" . [180])
- ("'A" . [193])
- ("'E" . [201])
- ("'I" . [205])
- ("'O" . [211])
- ("'U" . [218])
- ("'Y" . [221])
- ("'a" . [225])
- ("'e" . [233])
- ("'i" . [237])
- ("'o" . [243])
- ("'u" . [250])
- ("'y" . [253])
- ("*$" . [164])("$" . [164])
- ("*+" . [177])("+" . [177])
- (",," . [184])
- (",C" . [199])
- (",c" . [231])
- ("*-" . [173])("-" . [173])
- ("*." . [183])("." . [183])
- ("//" . [247])
- ("/A" . [197])
- ("/E" . [198])
- ("/O" . [216])
- ("/a" . [229])
- ("/e" . [230])
- ("/o" . [248])
- ("1/2" . [189])
- ("1/4" . [188])
- ("3/4" . [190])
- ("*<" . [171])("<" . [171])
- ("*=" . [175])("=" . [175])
- ("*>" . [187])(">" . [187])
- ("*?" . [191])("?" . [191])
- ("*C" . [169])("C" . [169])
- ("*L" . [163])("L" . [163])
- ("*P" . [182])("P" . [182])
- ("*R" . [174])("R" . [174])
- ("*S" . [167])("S" . [167])
- ("*Y" . [165])("Y" . [165])
- ("^1" . [185])
- ("^2" . [178])
- ("^3" . [179])
- ("^A" . [194])
- ("^E" . [202])
- ("^I" . [206])
- ("^O" . [212])
- ("^U" . [219])
- ("^a" . [226])
- ("^e" . [234])
- ("^i" . [238])
- ("^o" . [244])
- ("^u" . [251])
- ("_a" . [170])
- ("_o" . [186])
- ("`A" . [192])
- ("`E" . [200])
- ("`I" . [204])
- ("`O" . [210])
- ("`U" . [217])
- ("`a" . [224])
- ("`e" . [232])
- ("`i" . [236])
- ("`o" . [242])
- ("`u" . [249])
- ("*c" . [162])("c" . [162])
- ("*o" . [176])("o" . [176])
- ("*u" . [181])("u" . [181])
- ("*m" . [181])("m" . [181])
- ("*x" . [215])("x" . [215])
- ("*|" . [166])("|" . [166])
- ("~A" . [195])
- ("~D" . [208])
- ("~N" . [209])
- ("~O" . [213])
- ("~T" . [222])
- ("~a" . [227])
- ("~d" . [240])
- ("~n" . [241])
- ("~o" . [245])
- ("~t" . [254])
- ("~~" . [172])
- ("' " . "'")
- ("` " . "`")
- ("\" " . "\"")
- ("^ " . "^")
- ("~ " . "~"))
- "Alist of character translations for entering ISO characters.
-Each element has the form (STRING . VECTOR).
-The sequence STRING of ASCII chars translates into the
-sequence VECTOR. (VECTOR is normally one character long.)")
-
-;; Language-specific translation lists.
-(defvar iso-transl-language-alist
- '(("Esperanto"
- ("C" . [198])
- ("G" . [216])
- ("H" . [166])
- ("J" . [172])
- ("S" . [222])
- ("U" . [221])
- ("c" . [230])
- ("g" . [248])
- ("h" . [182])
- ("j" . [188])
- ("s" . [254])
- ("u" . [253]))
- ("French"
- ("C" . [199])
- ("c" . [231]))
- ("German"
- ("A" . [196])
- ("O" . [214])
- ("U" . [220])
- ("a" . [228])
- ("o" . [246])
- ("s" . [223])
- ("u" . [252]))
- ("Portuguese"
- ("C" . [199])
- ("c" . [231]))
- ("Spanish"
- ("!" . [161])
- ("?" . [191])
- ("N" . [241])
- ("n" . [209]))))
-
-(defvar iso-transl-ctl-x-8-map nil
- "Keymap for C-x 8 prefix.")
-(or iso-transl-ctl-x-8-map
- (setq iso-transl-ctl-x-8-map (make-sparse-keymap)))
-(or key-translation-map
- (setq key-translation-map (make-sparse-keymap)))
-(define-key key-translation-map "\C-x8" iso-transl-ctl-x-8-map)
-
-;; For each entry in the alist, we'll make up to three ways to generate
-;; the character in question: the prefix `C-x 8'; the ALT modifier on
-;; the first key of the sequence; and (if applicable) replacing the first
-;; key of the sequence with the corresponding dead key. For example, a
-;; character associated with the string "~n" can be input with `C-x 8 ~ n'
-;; or `Alt-~ n' or `mute-asciitilde n'.
-(defun iso-transl-define-keys (alist)
- (while alist
- (define-key iso-transl-ctl-x-8-map (car (car alist)) (cdr (car alist)))
- (let ((inchar (aref (car (car alist)) 0))
- (vec (vconcat (car (car alist))))
- (tail iso-transl-dead-key-alist))
- (aset vec 0 (logior (aref vec 0) ?\A-\^@))
- (define-key key-translation-map vec (cdr (car alist)))
- (define-key isearch-mode-map (vector (aref vec 0)) nil)
- (while tail
- (if (eq (car (car tail)) inchar)
- (let ((deadvec (copy-sequence vec))
- (deadkey (cdr (car tail))))
- (aset deadvec 0 deadkey)
- (define-key isearch-mode-map (vector deadkey) nil)
- (define-key key-translation-map deadvec (cdr (car alist)))))
- (setq tail (cdr tail))))
- (setq alist (cdr alist))))
-
-(defun iso-transl-set-language (lang)
- (interactive (list (let ((completion-ignore-case t))
- (completing-read "Set which language? "
- iso-transl-language-alist nil t))))
- (iso-transl-define-keys (cdr (assoc lang iso-transl-language-alist))))
-
-
-;; The standard mapping comes automatically. You can partially overlay it
-;; with a language-specific mapping by using `M-x iso-transl-set-language'.
-(iso-transl-define-keys iso-transl-char-map)
-
-(define-key isearch-mode-map "\C-x" nil)
-(define-key isearch-mode-map [?\C-x t] 'isearch-other-control-char)
-(define-key isearch-mode-map "\C-x8" nil)
-
-
-(provide 'iso-transl)
-
-;;; iso-transl.el ends here
diff --git a/lisp/international/latin-2.el b/lisp/international/latin-2.el
deleted file mode 100644
index 62029cdb9b2..00000000000
--- a/lisp/international/latin-2.el
+++ /dev/null
@@ -1,94 +0,0 @@
-;;; iso02-syn.el --- set up case-conversion and syntax tables for ISO 8859-2
-;;; (ISO latin2, i.e. East Block character set)
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Michael Gschwind (mike@vlsivie.tuwien.ac.at)
-;; Keywords: i18n
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Written by Michael Gschwind. See case-table.el for details.
-
-;;; Code:
-
-(require 'case-table)
-
-(let ((downcase (standard-case-table)))
- (set-case-syntax 160 " " downcase) ; NBSP (no-break space)
- (set-case-syntax-pair 161 177 downcase) ; A with hook
- (set-case-syntax 162 "w" downcase) ; u accent
- (set-case-syntax-pair 163 179 downcase) ; L with slash
- (set-case-syntax 164 "w" downcase) ; general currency sign
- (set-case-syntax-pair 165 181 downcase) ; L with v
- (set-case-syntax-pair 166 182 downcase) ; S with acute accent
- (set-case-syntax 167 "w" downcase) ; section sign
- (set-case-syntax 168 "w" downcase) ; diaeresis
- (set-case-syntax-pair 169 185 downcase) ; S with v
- (set-case-syntax-pair 170 186 downcase) ; S with cedilla
- (set-case-syntax-pair 171 187 downcase) ; T with v
- (set-case-syntax-pair 172 188 downcase) ; Z with acute accent
- (set-case-syntax 173 "_" downcase) ; soft hyphen
- (set-case-syntax-pair 174 190 downcase) ; Z with v
- (set-case-syntax-pair 175 191 downcase) ; Z with dot
- (set-case-syntax 176 "_" downcase) ; degree sign
- (set-case-syntax 178 "w" downcase) ; hook accent
- (set-case-syntax 180 "w" downcase) ; acute accent
- (set-case-syntax 183 "_" downcase) ; v accent
- (set-case-syntax 184 "w" downcase) ; cedilla
- (set-case-syntax 189 "w" downcase) ; Hungarian '' accent
- (set-case-syntax-pair 192 224 downcase) ; R with acute accent
- (set-case-syntax-pair 193 225 downcase) ; A with acute accent
- (set-case-syntax-pair 194 226 downcase) ; A with circumflex accent
- (set-case-syntax-pair 195 227 downcase) ; A with u accent
- (set-case-syntax-pair 196 228 downcase) ; A with diaeresis or umlaut mark
- (set-case-syntax-pair 197 229 downcase) ; L with acute accent
- (set-case-syntax-pair 198 230 downcase) ; C with acute accent
- (set-case-syntax-pair 199 231 downcase) ; C with cedilla
- (set-case-syntax-pair 200 232 downcase) ; C with v accent
- (set-case-syntax-pair 201 233 downcase) ; E with acute accent
- (set-case-syntax-pair 202 234 downcase) ; E with hook
- (set-case-syntax-pair 203 235 downcase) ; E with diaeresis
- (set-case-syntax-pair 204 236 downcase) ; E with v accent
- (set-case-syntax-pair 205 237 downcase) ; I with acute accent
- (set-case-syntax-pair 206 238 downcase) ; I with circumflex accent
- (set-case-syntax-pair 207 239 downcase) ; D with v accent
- (set-case-syntax-pair 208 240 downcase) ; D with stroke
- (set-case-syntax-pair 209 241 downcase) ; N with acute accent
- (set-case-syntax-pair 210 242 downcase) ; N with v accent
- (set-case-syntax-pair 211 243 downcase) ; O with acute accent
- (set-case-syntax-pair 212 244 downcase) ; O with circumflex accent
- (set-case-syntax-pair 213 245 downcase) ; O with Hungarian accent
- (set-case-syntax-pair 214 246 downcase) ; O with diaeresis or umlaut mark
- (set-case-syntax 215 "_" downcase) ; multiplication sign
- (set-case-syntax-pair 216 248 downcase) ; R with v accent
- (set-case-syntax-pair 217 249 downcase) ; U with ring
- (set-case-syntax-pair 218 250 downcase) ; U with acute accent
- (set-case-syntax-pair 219 251 downcase) ; U with Hungaraian accent
- (set-case-syntax-pair 220 252 downcase) ; U with diaeresis or umlaut mark
- (set-case-syntax-pair 221 253 downcase) ; Y with acute accent
- (set-case-syntax-pair 222 254 downcase) ; T with hook
- (set-case-syntax 223 "w" downcase) ; small sharp s, German
- (set-case-syntax 247 "_" downcase) ; division sign
- (set-case-syntax 255 "w" downcase) ; dot accent
-)
-
-(provide 'iso02-syn)
-
-;;; iso-syntax.el ends here
diff --git a/lisp/international/swedish.el b/lisp/international/swedish.el
deleted file mode 100644
index b3b73a41f48..00000000000
--- a/lisp/international/swedish.el
+++ /dev/null
@@ -1,154 +0,0 @@
-;;; swedish.el --- miscellaneous functions for dealing with Swedish.
-
-;; Copyright (C) 1988 Free Software Foundation, Inc.
-
-;; Author: Howard Gayle
-;; Maintainer: FSF
-;; Keywords: i18n
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;; Written by Howard Gayle. See case-table.el for details.
-
-;; See iso-swed.el for a description of the character set.
-
-(require 'iso-syntax)
-
-(defvar swedish-re
- "[ \t\n]\\(och\\|att\\|en\\|{r\\|\\[R\\|p}\\|P\\]\\|som\\|det\\|av\\|den\\|f|r\\|F\\\\R\\)[ \t\n.,?!:;'\")}]"
- "Regular expression for common Swedish words.")
-
-(defvar swascii-to-8859-trans
- (let ((string (make-string 256 ? ))
- (i 0))
- (while (< i 256)
- (aset string i i)
- (setq i (1+ i)))
- (aset string ?\[ 196)
- (aset string ?\] 197)
- (aset string ?\\ 214)
- (aset string ?^ 220)
- (aset string ?\{ 228)
- (aset string ?\} 229)
- (aset string ?\` 233)
- (aset string ?\| 246)
- (aset string ?~ 252)
- string)
- "Trans table from SWASCII to 8859.")
-
-; $ is not converted because it almost always means US
-; dollars, not general currency sign. @ is not converted
-; because it is more likely to be an at sign in a mail address
-; than an E with acute accent.
-
-(defun swascii-to-8859-buffer ()
- "Convert characters in buffer from Swedish/Finnish-ascii to ISO 8859/1.
-Works even on read-only buffers. `$' and `@' are not converted."
- (interactive)
- (let ((buffer-read-only nil))
- (translate-region (point-min) (point-max) swascii-to-8859-trans)))
-
-(defun swascii-to-8859-buffer-maybe ()
- "Call swascii-to-8859-buffer if the buffer looks like Swedish-ascii.
-Leaves point just after the word that looks Swedish."
- (interactive)
- (let ((case-fold-search t))
- (if (re-search-forward swedish-re nil t)
- (swascii-to-8859-buffer))))
-
-(setq rmail-show-message-hook 'swascii-to-8859-buffer-maybe)
-
-(or (boundp 'news-group-hook-alist) (setq news-group-hook-alist nil))
-(setq news-group-hook-alist
- (append '(("^swnet." . swascii-to-8859-buffer-maybe))
- news-group-hook-alist))
-
-(defvar 8859-to-swascii-trans
- (let ((string (make-string 256 ? ))
- (i 0))
- (while (< i 256)
- (aset string i i)
- (setq i (1+ i)))
- (aset string 164 ?$)
- (aset string 196 ?\[)
- (aset string 197 ?\])
- (aset string 201 ?@)
- (aset string 214 ?\\)
- (aset string 220 ?^)
- (aset string 228 ?\{)
- (aset string 229 ?\})
- (aset string 233 ?\`)
- (aset string 246 ?\|)
- (aset string 252 ?~)
- string)
- "8859 to SWASCII trans table.")
-
-(defun 8859-to-swascii-buffer ()
- "Convert characters in buffer from ISO 8859/1 to Swedish/Finnish-ascii."
- (interactive "*")
- (translate-region (point-min) (point-max) 8859-to-swascii-trans))
-
-(setq mail-send-hook '8859-to-swascii-buffer)
-(setq news-inews-hook '8859-to-swascii-buffer)
-
-;; It's not clear what purpose is served by a separate
-;; Swedish mode that differs from Text mode only in having
-;; a separate abbrev table. Nothing says that the abbrevs you
-;; define in Text mode have to be English!
-
-;(defvar swedish-mode-abbrev-table nil
-; "Abbrev table used while in swedish mode.")
-;(define-abbrev-table 'swedish-mode-abbrev-table ())
-
-;(defun swedish-mode ()
-; "Major mode for editing Swedish text intended for humans to
-;read. Special commands:\\{text-mode-map}
-;Turning on swedish-mode calls the value of the variable
-;text-mode-hook, if that value is non-nil."
-; (interactive)
-; (kill-all-local-variables)
-; (use-local-map text-mode-map)
-; (setq mode-name "Swedish")
-; (setq major-mode 'swedish-mode)
-; (setq local-abbrev-table swedish-mode-abbrev-table)
-; (set-syntax-table text-mode-syntax-table)
-; (run-hooks 'text-mode-hook))
-
-;(defun indented-swedish-mode ()
-; "Major mode for editing indented Swedish text intended for
-;humans to read.\\{indented-text-mode-map}
-;Turning on indented-swedish-mode calls the value of the
-;variable text-mode-hook, if that value is non-nil."
-; (interactive)
-; (kill-all-local-variables)
-; (use-local-map text-mode-map)
-; (define-abbrev-table 'swedish-mode-abbrev-table ())
-; (setq local-abbrev-table swedish-mode-abbrev-table)
-; (set-syntax-table text-mode-syntax-table)
-; (make-local-variable 'indent-line-function)
-; (setq indent-line-function 'indent-relative-maybe)
-; (use-local-map indented-text-mode-map)
-; (setq mode-name "Indented Swedish")
-; (setq major-mode 'indented-swedish-mode)
-; (run-hooks 'text-mode-hook))
-
-(provide 'swedish)
-
-;;; swedish.el ends here
diff --git a/lisp/isearch.el b/lisp/isearch.el
deleted file mode 100644
index 28fe63335d0..00000000000
--- a/lisp/isearch.el
+++ /dev/null
@@ -1,1451 +0,0 @@
-;;; isearch.el --- incremental search minor mode.
-
-;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Instructions
-
-;; For programmed use of isearch-mode, e.g. calling (isearch-forward),
-;; isearch-mode behaves modally and does not return until the search
-;; is completed. It uses a recursive-edit to behave this way. Note:
-;; gnus does it wrong: (call-interactively 'isearch-forward).
-
-;; The key bindings active within isearch-mode are defined below in
-;; `isearch-mode-map' which is given bindings close to the default
-;; characters of the original isearch.el. With `isearch-mode',
-;; however, you can bind multi-character keys and it should be easier
-;; to add new commands. One bug though: keys with meta-prefix cannot
-;; be longer than two chars. Also see minibuffer-local-isearch-map
-;; for bindings active during `isearch-edit-string'.
-
-;; Note to emacs version 19 users: isearch-mode should work even if
-;; you switch windows with the mouse, in which case isearch-mode is
-;; terminated automatically before the switch. This is true of lemacs
-;; too, with a few more cleanups I've neglected in this release.
-;; No one has supplied patches for epoch yet.
-
-;; The search ring and completion commands automatically put you in
-;; the minibuffer to edit the string. This gives you a chance to
-;; modify the search string before executing the search. There are
-;; three commands to terminate the editing: C-s and C-r exit the
-;; minibuffer and search forward and reverse respectively, while C-m
-;; exits and does a nonincremental search.
-
-;; Exiting immediately from isearch uses isearch-edit-string instead
-;; of nonincremental-search, if search-nonincremental-instead is non-nil.
-;; The name of this option should probably be changed if we decide to
-;; keep the behavior. No point in forcing nonincremental search until
-;; the last possible moment.
-
-;; TODO
-;; - Integrate the emacs 19 generalized command history.
-;; - Think about incorporating query-replace.
-;; - Hooks and options for failed search.
-
-;;; Change Log:
-
-;; Changes before those recorded in ChangeLog:
-
-;; Revision 1.4 92/09/14 16:26:02 liberte
-;; Added prefix args to isearch-forward, etc. to switch between
-;; string and regular expression searching.
-;; Added some support for lemacs.
-;; Added general isearch-highlight option - but only for lemacs so far.
-;; Added support for frame switching in emacs 19.
-;; Added word search option to isearch-edit-string.
-;; Renamed isearch-quit to isearch-abort.
-;; Numerous changes to comments and doc strings.
-;;
-;; Revision 1.3 92/06/29 13:10:08 liberte
-;; Moved modal isearch-mode handling into isearch-mode.
-;; Got rid of buffer-local isearch variables.
-;; isearch-edit-string used by ring adjustments, completion, and
-;; nonincremental searching. C-s and C-r are additional exit commands.
-;; Renamed all regex to regexp.
-;; Got rid of found-start and found-point globals.
-;; Generalized handling of upper-case chars.
-
-;; Revision 1.2 92/05/27 11:33:57 liberte
-;; Emacs version 19 has a search ring, which is supported here.
-;; Other fixes found in the version 19 isearch are included here.
-;;
-;; Also see variables search-caps-disable-folding,
-;; search-nonincremental-instead, search-whitespace-regexp, and
-;; commands isearch-toggle-regexp, isearch-edit-string.
-;;
-;; semi-modal isearching is supported.
-
-;; Changes for 1.1
-;; 3/18/92 Fixed invalid-regexp.
-;; 3/18/92 Fixed yanking in regexps.
-
-;;; Code:
-
-
-;;; Some additional options and constants.
-
-(defvar 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.")
-
-(defvar search-upper-case 'not-yanks
- "*If non-nil, upper case chars disable case fold searching.
-That is, upper and lower case chars must match exactly.
-This applies no matter where the chars come from, but does not
-apply to chars in regexps that are prefixed with `\\'.
-If this value is `not-yanks', yanked text is always downcased.")
-
-(defvar search-nonincremental-instead t
- "*If non-nil, do a nonincremental search instead if exiting immediately.
-Actually, `isearch-edit-string' is called to let you enter the search
-string, and RET terminates editing and does a nonincremental search.")
-
-(defvar search-whitespace-regexp "\\s-+"
- "*If non-nil, regular expression to match a sequence of whitespace chars.
-You might want to use something like \"[ \\t\\r\\n]+\" instead.")
-
-(defvar search-highlight nil
- "*Non-nil means incremental search highlights the current match.")
-
-(defvar isearch-mode-hook nil
- "Function(s) to call after starting up an incremental search.")
-
-(defvar isearch-mode-end-hook nil
- "Function(s) to call after terminating an incremental search.")
-
-;;; Search ring.
-
-(defvar search-ring nil
- "List of search string sequences.")
-(defvar regexp-search-ring nil
- "List of regular expression search string sequences.")
-
-(defvar search-ring-max 16
- "*Maximum length of search ring before oldest elements are thrown away.")
-(defvar regexp-search-ring-max 16
- "*Maximum length of regexp search ring before oldest elements are thrown away.")
-
-(defvar search-ring-yank-pointer nil
- "Index in `search-ring' of last string reused.
-nil if none yet.")
-(defvar regexp-search-ring-yank-pointer nil
- "Index in `regexp-search-ring' of last string reused.
-nil if none yet.")
-
-(defvar search-ring-update nil
- "*Non-nil if advancing or retreating in the search ring should cause search.
-Default value, nil, means edit the string instead.")
-
-;;; Define isearch-mode keymap.
-
-(defvar isearch-mode-map nil
- "Keymap for isearch-mode.")
-
-(or isearch-mode-map
- (let* ((i 0)
- (map (make-keymap)))
- (or (vectorp (nth 1 map))
- (error "The initialization of isearch-mode-map must be updated"))
- ;; Give this map a vector 256 long, for dense binding
- ;; of a larger range of ordinary characters.
- (setcar (cdr map) (make-vector 256 nil))
-
- ;; Make function keys, etc, exit the search.
- (define-key map [t] 'isearch-other-control-char)
- ;; Control chars, by default, end isearch mode transparently.
- ;; We need these explicit definitions because, in a dense keymap,
- ;; the binding for t does not affect characters.
- ;; We use a dense keymap to save space.
- (while (< i ?\ )
- (define-key map (make-string 1 i) 'isearch-other-control-char)
- (setq i (1+ i)))
-
- ;; Printing chars extend the search string by default.
- (setq i ?\ )
- (while (< i (length (nth 1 map)))
- (define-key map (vector i) 'isearch-printing-char)
- (setq i (1+ i)))
-
- ;; To handle local bindings with meta char prefix keys, define
- ;; another full keymap. This must be done for any other prefix
- ;; keys as well, one full keymap per char of the prefix key. It
- ;; would be simpler to disable the global keymap, and/or have a
- ;; default local key binding for any key not otherwise bound.
- (let ((meta-map (make-sparse-keymap)))
- (define-key map (char-to-string meta-prefix-char) meta-map)
- (define-key map [escape] meta-map))
- (define-key map (vector meta-prefix-char t) 'isearch-other-meta-char)
-
- ;; Several non-printing chars change the searching behavior.
- (define-key map "\C-s" 'isearch-repeat-forward)
- (define-key map "\C-r" 'isearch-repeat-backward)
- (define-key map "\177" 'isearch-delete-char)
- (define-key map "\C-g" 'isearch-abort)
- ;; This assumes \e is the meta-prefix-char.
- (or (= ?\e meta-prefix-char)
- (error "Inconsistency in isearch.el"))
- (define-key map "\e\e\e" 'isearch-cancel)
- (define-key map [escape escape escape] 'isearch-cancel)
-
- (define-key map "\C-q" 'isearch-quote-char)
-
- (define-key map "\r" 'isearch-exit)
- (define-key map "\C-j" 'isearch-printing-char)
- (define-key map "\t" 'isearch-printing-char)
- (define-key map " " 'isearch-whitespace-chars)
-
- (define-key map "\C-w" 'isearch-yank-word)
- (define-key map "\C-y" 'isearch-yank-line)
-
- ;; Define keys for regexp chars * ? |.
- ;; Nothing special for + because it matches at least once.
- (define-key map "*" 'isearch-*-char)
- (define-key map "?" 'isearch-*-char)
- (define-key map "|" 'isearch-|-char)
-
-;;; Turned off because I find I expect to get the global definition--rms.
-;;; ;; Instead bind C-h to special help command for isearch-mode.
-;;; (define-key map "\C-h" 'isearch-mode-help)
-
- (define-key map "\M-n" 'isearch-ring-advance)
- (define-key map "\M-p" 'isearch-ring-retreat)
- (define-key map "\M-y" 'isearch-yank-kill)
-
- (define-key map "\M-\t" 'isearch-complete)
-
- ;; Pass frame events transparently so they won't exit the search.
- ;; In particular, if we have more than one display open, then a
- ;; switch-frame might be generated by someone typing at another keyboard.
- (define-key map [switch-frame] nil)
- (define-key map [delete-frame] nil)
- (define-key map [iconify-frame] nil)
- (define-key map [make-frame-visible] nil)
-
- (setq isearch-mode-map map)
- ))
-
-;; Some bindings you may want to put in your isearch-mode-hook.
-;; Suggest some alternates...
-;; (define-key isearch-mode-map "\C-t" 'isearch-toggle-case-fold)
-;; (define-key isearch-mode-map "\C-t" 'isearch-toggle-regexp)
-;; (define-key isearch-mode-map "\C-^" 'isearch-edit-string)
-
-
-(defvar minibuffer-local-isearch-map nil
- "Keymap for editing isearch strings in the minibuffer.")
-
-(or minibuffer-local-isearch-map
- (let ((map (copy-keymap minibuffer-local-map)))
- (define-key map "\r" 'isearch-nonincremental-exit-minibuffer)
- (define-key map "\M-n" 'isearch-ring-advance-edit)
- (define-key map "\M-p" 'isearch-ring-retreat-edit)
- (define-key map "\M-\t" 'isearch-complete-edit)
- (define-key map "\C-s" 'isearch-forward-exit-minibuffer)
- (define-key map "\C-r" 'isearch-reverse-exit-minibuffer)
- (setq minibuffer-local-isearch-map map)
- ))
-
-;; Internal variables declared globally for byte-compiler.
-;; These are all set with setq while isearching
-;; and bound locally while editing the search string.
-
-(defvar isearch-forward nil) ; Searching in the forward direction.
-(defvar isearch-regexp nil) ; Searching for a regexp.
-(defvar isearch-word nil) ; Searching for words.
-
-(defvar isearch-cmds nil) ; Stack of search status sets.
-(defvar isearch-string "") ; The current search string.
-(defvar isearch-message "") ; text-char-description version of isearch-string
-
-(defvar isearch-success t) ; Searching is currently successful.
-(defvar isearch-invalid-regexp nil) ; Regexp not well formed.
-(defvar isearch-within-brackets nil) ; Regexp has unclosed [.
-(defvar isearch-other-end nil) ; Start (end) of match if forward (backward).
-(defvar isearch-wrapped nil) ; Searching restarted from the top (bottom).
-(defvar isearch-barrier 0)
-(defvar isearch-just-started nil)
-
-; case-fold-search while searching.
-; either nil, t, or 'yes. 'yes means the same as t except that mixed
-; case in the search string is ignored.
-(defvar isearch-case-fold-search nil)
-
-(defvar isearch-adjusted nil)
-(defvar isearch-slow-terminal-mode nil)
-;;; If t, using a small window.
-(defvar isearch-small-window nil)
-(defvar isearch-opoint 0)
-;;; The window configuration active at the beginning of the search.
-(defvar isearch-window-configuration nil)
-
-;; Flag to indicate a yank occurred, so don't move the cursor.
-(defvar isearch-yank-flag nil)
-
-;;; A function to be called after each input character is processed.
-;;; (It is not called after characters that exit the search.)
-;;; It is only set from an optional argument to `isearch-mode'.
-(defvar isearch-op-fun nil)
-
-;;; Is isearch-mode in a recursive edit for modal searching.
-(defvar isearch-recursive-edit nil)
-
-;;; Should isearch be terminated after doing one search?
-(defvar isearch-nonincremental nil)
-
-;; New value of isearch-forward after isearch-edit-string.
-(defvar isearch-new-forward nil)
-
-
-;; Minor-mode-alist changes - kind of redundant with the
-;; echo area, but if isearching in multiple windows, it can be useful.
-
-(or (assq 'isearch-mode minor-mode-alist)
- (nconc minor-mode-alist
- (list '(isearch-mode isearch-mode))))
-
-(defvar isearch-mode nil) ;; Name of the minor mode, if non-nil.
-(make-variable-buffer-local 'isearch-mode)
-
-(define-key global-map "\C-s" 'isearch-forward)
-(define-key esc-map "\C-s" 'isearch-forward-regexp)
-(define-key global-map "\C-r" 'isearch-backward)
-(define-key esc-map "\C-r" 'isearch-backward-regexp)
-
-;;; Entry points to isearch-mode.
-;;; These four functions should replace those in loaddefs.el
-;;; An alternative is to defalias isearch-forward etc to isearch-mode,
-;;; and look at this-command to set the options accordingly.
-
-(defun isearch-forward (&optional regexp-p no-recursive-edit)
- "\
-Do incremental search forward.
-With a prefix argument, do an incremental regular expression search instead.
-\\<isearch-mode-map>
-As you type characters, they add to the search string and are found.
-The following non-printing keys are bound in `isearch-mode-map'.
-
-Type \\[isearch-delete-char] to cancel characters from end of search string.
-Type \\[isearch-exit] to exit, leaving point at location found.
-Type LFD (C-j) to match end of line.
-Type \\[isearch-repeat-forward] to search again forward,\
- \\[isearch-repeat-backward] to search again backward.
-Type \\[isearch-yank-word] to yank word from buffer onto end of search\
- string and search for it.
-Type \\[isearch-yank-line] to yank rest of line onto end of search string\
- and search for it.
-Type \\[isearch-yank-kill] to yank the last string of killed text.
-Type \\[isearch-quote-char] to quote control character to search for it.
-\\[isearch-abort] while searching or when search has failed cancels input\
- back to what has
- been found successfully.
-\\[isearch-abort] when search is successful aborts and moves point to\
- starting point.
-
-Also supported is a search ring of the previous 16 search strings.
-Type \\[isearch-ring-advance] to search for the next item in the search ring.
-Type \\[isearch-ring-retreat] to search for the previous item in the search\
- ring.
-Type \\[isearch-complete] to complete the search string using the search ring.
-
-The above keys, bound in `isearch-mode-map', are often controlled by
- options; do M-x apropos on search-.* to find them.
-Other control and meta characters terminate the search
- and are then executed normally (depending on `search-exit-option').
-Likewise for function keys and mouse button events.
-
-If this function is called non-interactively, it does not return to
-the calling function until the search is done."
-
- (interactive "P\np")
- (isearch-mode t (not (null regexp-p)) nil (not no-recursive-edit)))
-
-(defun isearch-forward-regexp (&optional not-regexp no-recursive-edit)
- "\
-Do incremental search forward for regular expression.
-With a prefix argument, do a regular string search instead.
-Like ordinary incremental search except that your input
-is treated as a regexp. See \\[isearch-forward] for more info."
- (interactive "P\np")
- (isearch-mode t (null not-regexp) nil (not no-recursive-edit)))
-
-(defun isearch-backward (&optional regexp-p no-recursive-edit)
- "\
-Do incremental search backward.
-With a prefix argument, do a regular expression search instead.
-See \\[isearch-forward] for more information."
- (interactive "P\np")
- (isearch-mode nil (not (null regexp-p)) nil (not no-recursive-edit)))
-
-(defun isearch-backward-regexp (&optional not-regexp no-recursive-edit)
- "\
-Do incremental search backward for regular expression.
-With a prefix argument, do a regular string search instead.
-Like ordinary incremental search except that your input
-is treated as a regexp. See \\[isearch-forward] for more info."
- (interactive "P\np")
- (isearch-mode nil (null not-regexp) nil (not no-recursive-edit)))
-
-
-(defun isearch-mode-help ()
- (interactive)
- (describe-function 'isearch-forward)
- (isearch-update))
-
-
-;; isearch-mode only sets up incremental search for the minor mode.
-;; All the work is done by the isearch-mode commands.
-
-;; Not used yet:
-;;(defvar isearch-commands '(isearch-forward isearch-backward
-;; isearch-forward-regexp isearch-backward-regexp)
-;; "List of commands for which isearch-mode does not recursive-edit.")
-
-
-(defun isearch-mode (forward &optional regexp op-fun recursive-edit word-p)
- "Start isearch minor mode. Called by `isearch-forward', etc.
-
-\\{isearch-mode-map}"
-
- ;; Initialize global vars.
- (setq isearch-forward forward
- isearch-regexp regexp
- isearch-word word-p
- isearch-op-fun op-fun
- isearch-case-fold-search case-fold-search
- isearch-string ""
- isearch-message ""
- isearch-cmds nil
- isearch-success t
- isearch-wrapped nil
- isearch-barrier (point)
- isearch-adjusted nil
- isearch-yank-flag nil
- isearch-invalid-regexp nil
- isearch-within-brackets nil
- isearch-slow-terminal-mode (and (<= baud-rate search-slow-speed)
- (> (window-height)
- (* 4 search-slow-window-lines)))
- isearch-other-end nil
- isearch-small-window nil
- isearch-just-started t
-
- isearch-opoint (point)
- search-ring-yank-pointer nil
- regexp-search-ring-yank-pointer nil)
- (looking-at "")
- (setq isearch-window-configuration
- (if isearch-slow-terminal-mode (current-window-configuration) nil))
-
- ;; Maybe make minibuffer frame visible and/or raise it.
- (let ((frame (window-frame (minibuffer-window))))
- (if (not (memq (frame-live-p frame) '(nil t)))
- (progn
- (make-frame-visible frame)
- (if minibuffer-auto-raise
- (raise-frame frame)))))
-
- (setq isearch-mode " Isearch") ;; forward? regexp?
- (force-mode-line-update)
-
- (isearch-push-state)
-
- (setq overriding-terminal-local-map isearch-mode-map)
- (isearch-update)
- (run-hooks 'isearch-mode-hook)
-
- (add-hook 'mouse-leave-buffer-hook 'isearch-done)
-
- ;; isearch-mode can be made modal (in the sense of not returning to
- ;; the calling function until searching is completed) by entering
- ;; a recursive-edit and exiting it when done isearching.
- (if recursive-edit
- (let ((isearch-recursive-edit t))
- (recursive-edit)))
- isearch-success)
-
-
-;; Some high level utilities. Others below.
-
-(defun isearch-update ()
- ;; Called after each command to update the display.
- (if (null unread-command-events)
- (progn
- (if (not (input-pending-p))
- (isearch-message))
- (if (and isearch-slow-terminal-mode
- (not (or isearch-small-window
- (pos-visible-in-window-p))))
- (let ((found-point (point)))
- (setq isearch-small-window t)
- (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)))
- (if isearch-other-end
- (if (< isearch-other-end (point)) ; isearch-forward?
- (isearch-highlight isearch-other-end (point))
- (isearch-highlight (point) isearch-other-end))
- (isearch-dehighlight nil))
- ))
- (setq ;; quit-flag nil not for isearch-mode
- isearch-adjusted nil
- isearch-yank-flag nil)
- )
-
-(defun isearch-done (&optional nopush edit)
- (remove-hook 'mouse-leave-buffer-hook 'isearch-done)
- ;; Called by all commands that terminate isearch-mode.
- ;; If NOPUSH is non-nil, we don't push the string on the search ring.
- (setq overriding-terminal-local-map nil)
- ;; (setq pre-command-hook isearch-old-pre-command-hook) ; for lemacs
- (isearch-dehighlight t)
- (let ((found-start (window-start (selected-window)))
- (found-point (point)))
- (if isearch-window-configuration
- (set-window-configuration isearch-window-configuration))
-
- (if isearch-small-window
- (goto-char found-point)
- ;; Exiting the save-window-excursion clobbers window-start; restore it.
- (set-window-start (selected-window) found-start t))
-
- ;; If there was movement, mark the starting position.
- ;; Maybe should test difference between and set mark iff > threshold.
- (if (/= (point) isearch-opoint)
- (or (and transient-mark-mode mark-active)
- (progn
- (push-mark isearch-opoint t)
- (or executing-kbd-macro (> (minibuffer-depth) 0)
- (message "Mark saved where search started"))))))
-
- (setq isearch-mode nil)
- (force-mode-line-update)
-
- (if (and (> (length isearch-string) 0) (not nopush))
- ;; Update the ring data.
- (isearch-update-ring isearch-string isearch-regexp))
-
- (run-hooks 'isearch-mode-end-hook)
- (and (not edit) isearch-recursive-edit (exit-recursive-edit)))
-
-(defun isearch-update-ring (string &optional regexp)
- "Add STRING to the beginning of the search ring.
-REGEXP says which ring to use."
- (if regexp
- (if (or (null regexp-search-ring)
- (not (string= string (car regexp-search-ring))))
- (progn
- (setq regexp-search-ring
- (cons string regexp-search-ring))
- (if (> (length regexp-search-ring) regexp-search-ring-max)
- (setcdr (nthcdr (1- search-ring-max) regexp-search-ring)
- nil))))
- (if (or (null search-ring)
- (not (string= string (car search-ring))))
- (progn
- (setq search-ring (cons string search-ring))
- (if (> (length search-ring) search-ring-max)
- (setcdr (nthcdr (1- search-ring-max) search-ring) nil))))))
-
-;;; Switching buffers should first terminate isearch-mode.
-;;; This is done quite differently for each variant of emacs.
-;;; For lemacs, see Exiting in lemacs below
-
-;; For Emacs 19, the frame switch event is handled.
-(defun isearch-switch-frame-handler ()
- (interactive) ;; Is this necessary?
- ;; First terminate isearch-mode.
- (isearch-done)
- (handle-switch-frame (car (cdr (isearch-last-command-char)))))
-
-
-;; Commands active while inside of the isearch minor mode.
-
-(defun isearch-exit ()
- "Exit search normally.
-However, if this is the first command after starting incremental
-search and `search-nonincremental-instead' is non-nil, do a
-nonincremental search instead via `isearch-edit-string'."
- (interactive)
- (if (and search-nonincremental-instead
- (= 0 (length isearch-string)))
- (let ((isearch-nonincremental t))
- (isearch-edit-string)))
- (isearch-done))
-
-
-(defun isearch-edit-string ()
- "Edit the search string in the minibuffer.
-The following additional command keys are active while editing.
-\\<minibuffer-local-isearch-map>
-\\[exit-minibuffer] to resume incremental searching with the edited string.
-\\[isearch-nonincremental-exit-minibuffer] to do one nonincremental search.
-\\[isearch-forward-exit-minibuffer] to resume isearching forward.
-\\[isearch-reverse-exit-minibuffer] to resume isearching backward.
-\\[isearch-ring-advance-edit] to replace the search string with the next item in the search ring.
-\\[isearch-ring-retreat-edit] to replace the search string with the previous item in the search ring.
-\\[isearch-complete-edit] to complete the search string using the search ring.
-\\<isearch-mode-map>
-If first char entered is \\[isearch-yank-word], then do word search instead."
-
- ;; This code is very hairy for several reasons, explained in the code.
- ;; Mainly, isearch-mode must be terminated while editing and then restarted.
- ;; If there were a way to catch any change of buffer from the minibuffer,
- ;; this could be simplified greatly.
- ;; Editing doesn't back up the search point. Should it?
- (interactive)
- (condition-case err
- (progn
- (let ((isearch-nonincremental isearch-nonincremental)
-
- ;; Locally bind all isearch global variables to protect them
- ;; from recursive isearching.
- ;; isearch-string -message and -forward are not bound
- ;; so they may be changed. Instead, save the values.
- (isearch-new-string isearch-string)
- (isearch-new-message isearch-message)
- (isearch-new-forward isearch-forward)
- (isearch-new-word isearch-word)
-
- (isearch-regexp isearch-regexp)
- (isearch-op-fun isearch-op-fun)
- (isearch-cmds isearch-cmds)
- (isearch-success isearch-success)
- (isearch-wrapped isearch-wrapped)
- (isearch-barrier isearch-barrier)
- (isearch-adjusted isearch-adjusted)
- (isearch-yank-flag isearch-yank-flag)
- (isearch-invalid-regexp isearch-invalid-regexp)
- (isearch-within-brackets isearch-within-brackets)
- ;;; Don't bind this. We want isearch-search, below, to set it.
- ;;; And the old value won't matter after that.
- ;;; (isearch-other-end isearch-other-end)
- ;;; Perhaps some of these other variables should be bound for a
- ;;; shorter period, ending before the next isearch-search.
- ;;; But there doesn't seem to be a real bug, so let's not risk it now.
- (isearch-opoint isearch-opoint)
- (isearch-slow-terminal-mode isearch-slow-terminal-mode)
- (isearch-small-window isearch-small-window)
- (isearch-recursive-edit isearch-recursive-edit)
- ;; Save current configuration so we can restore it here.
- (isearch-window-configuration (current-window-configuration))
- )
-
- ;; Actually terminate isearching until editing is done.
- ;; This is so that the user can do anything without failure,
- ;; like switch buffers and start another isearch, and return.
- (condition-case err
- (isearch-done t t)
- (exit nil)) ; was recursive editing
-
- (isearch-message) ;; for read-char
- (unwind-protect
- (let* (;; Why does following read-char echo?
- ;;(echo-keystrokes 0) ;; not needed with above message
- (e (let ((cursor-in-echo-area t))
- (read-event)))
- ;; Binding minibuffer-history-symbol to nil is a work-around
- ;; for some incompatibility with gmhist.
- (minibuffer-history-symbol)
- (message-log-max nil))
- ;; If the first character the user types when we prompt them
- ;; for a string is the yank-word character, then go into
- ;; word-search mode. Otherwise unread that character and
- ;; read a key the normal way.
- ;; Word search does not apply (yet) to regexp searches,
- ;; no check is made here.
- (message (isearch-message-prefix nil nil t))
- (if (eq 'isearch-yank-word
- (lookup-key isearch-mode-map (vector e)))
- (setq isearch-word t;; so message-prefix is right
- isearch-new-word t)
- (cancel-kbd-macro-events)
- (isearch-unread e))
- (setq cursor-in-echo-area nil)
- (setq isearch-new-string
- (let (junk-ring)
- (read-from-minibuffer
- (isearch-message-prefix nil nil isearch-nonincremental)
- isearch-string
- minibuffer-local-isearch-map nil
- 'junk-ring))
- isearch-new-message
- (mapconcat 'isearch-text-char-description
- isearch-new-string "")))
- ;; Always resume isearching by restarting it.
- (isearch-mode isearch-forward
- isearch-regexp
- isearch-op-fun
- nil
- isearch-word)
-
- ;; Copy new local values to isearch globals
- (setq isearch-string isearch-new-string
- isearch-message isearch-new-message
- isearch-forward isearch-new-forward
- isearch-word isearch-new-word))
-
- ;; Empty isearch-string means use default.
- (if (= 0 (length isearch-string))
- (setq isearch-string (or (car (if isearch-regexp
- regexp-search-ring
- search-ring))
- ""))
- ;; This used to set the last search string,
- ;; but I think it is not right to do that here.
- ;; Only the string actually used should be saved.
- ))
-
- ;; Push the state as of before this C-s.
- (isearch-push-state)
-
- ;; Reinvoke the pending search.
- (isearch-search)
- (isearch-update)
- (if isearch-nonincremental
- (progn
- ;; (sit-for 1) ;; needed if isearch-done does: (message "")
- (isearch-done))))
-
- (quit ; handle abort-recursive-edit
- (isearch-abort) ;; outside of let to restore outside global values
- )))
-
-(defun isearch-nonincremental-exit-minibuffer ()
- (interactive)
- (setq isearch-nonincremental t)
- (exit-minibuffer))
-
-(defun isearch-forward-exit-minibuffer ()
- (interactive)
- (setq isearch-new-forward t)
- (exit-minibuffer))
-
-(defun isearch-reverse-exit-minibuffer ()
- (interactive)
- (setq isearch-new-forward nil)
- (exit-minibuffer))
-
-(defun isearch-cancel ()
- "Terminate the search and go back to the starting point."
- (interactive)
- (goto-char isearch-opoint)
- (isearch-done t)
- (signal 'quit nil)) ; and pass on quit signal
-
-(defun isearch-abort ()
- "Abort incremental search mode if searching is successful, signaling quit.
-Otherwise, revert to previous successful search and continue searching.
-Use `isearch-exit' to quit without signaling."
- (interactive)
-;; (ding) signal instead below, if quitting
- (discard-input)
- (if isearch-success
- ;; If search is successful, move back to starting point
- ;; and really do quit.
- (progn (goto-char isearch-opoint)
- (setq isearch-success nil)
- (isearch-done t) ; exit isearch
- (signal 'quit nil)) ; and pass on quit signal
- ;; If search is failing, or has an incomplete regexp,
- ;; rub out until it is once more successful.
- (while (or (not isearch-success) isearch-invalid-regexp)
- (isearch-pop-state))
- (isearch-update)))
-
-(defun isearch-repeat (direction)
- ;; Utility for isearch-repeat-forward and -backward.
- (if (eq isearch-forward (eq direction 'forward))
- ;; C-s in forward or C-r in reverse.
- (if (equal isearch-string "")
- ;; If search string is empty, use last one.
- (setq isearch-string
- (or (if isearch-regexp
- (car regexp-search-ring)
- (car search-ring))
- "")
- isearch-message
- (mapconcat 'isearch-text-char-description
- isearch-string ""))
- ;; If already have what to search for, repeat it.
- (or isearch-success
- (progn
- (goto-char (if isearch-forward (point-min) (point-max)))
- (setq isearch-wrapped t))))
- ;; C-s in reverse or C-r in forward, change direction.
- (setq isearch-forward (not isearch-forward)))
-
- (setq isearch-barrier (point)) ; For subsequent \| if regexp.
-
- (if (equal isearch-string "")
- (setq isearch-success t)
- (if (and isearch-success (equal (match-end 0) (match-beginning 0))
- (not isearch-just-started))
- ;; If repeating a search that found
- ;; an empty string, ensure we advance.
- (if (if isearch-forward (eobp) (bobp))
- ;; If there's nowhere to advance to, fail (and wrap next time).
- (progn
- (setq isearch-success nil)
- (ding))
- (forward-char (if isearch-forward 1 -1))
- (isearch-search))
- (isearch-search)))
-
- (isearch-push-state)
- (isearch-update))
-
-(defun isearch-repeat-forward ()
- "Repeat incremental search forwards."
- (interactive)
- (isearch-repeat 'forward))
-
-(defun isearch-repeat-backward ()
- "Repeat incremental search backwards."
- (interactive)
- (isearch-repeat 'backward))
-
-(defun isearch-toggle-regexp ()
- "Toggle regexp searching on or off."
- ;; The status stack is left unchanged.
- (interactive)
- (setq isearch-regexp (not isearch-regexp))
- (if isearch-regexp (setq isearch-word nil))
- (isearch-update))
-
-(defun isearch-toggle-case-fold ()
- "Toggle case folding in searching on or off."
- (interactive)
- (setq isearch-case-fold-search
- (if isearch-case-fold-search nil 'yes))
- (let ((message-log-max nil))
- (message "%s%s [case %ssensitive]"
- (isearch-message-prefix nil nil isearch-nonincremental)
- isearch-message
- (if isearch-case-fold-search "in" "")))
- (setq isearch-adjusted t)
- (sit-for 1)
- (isearch-update))
-
-(defun isearch-delete-char ()
- "Discard last input item and move point back.
-If no previous match was done, just beep."
- (interactive)
- (if (null (cdr isearch-cmds))
- (ding)
- (isearch-pop-state))
- (isearch-update))
-
-
-(defun isearch-yank (chunk)
- ;; Helper for isearch-yank-word and isearch-yank-line
- ;; CHUNK should be word, line or kill.
- (let ((string (cond
- ((eq chunk 'kill)
- (current-kill 0))
- (t
- (save-excursion
- (and (not isearch-forward) isearch-other-end
- (goto-char isearch-other-end))
- (buffer-substring
- (point)
- (save-excursion
- (cond
- ((eq chunk 'word)
- (forward-word 1))
- ((eq chunk 'line)
- (end-of-line)))
- (point))))))))
- ;; Downcase the string if not supposed to case-fold yanked strings.
- (if (and isearch-case-fold-search
- (eq 'not-yanks search-upper-case))
- (setq string (downcase string)))
- (if isearch-regexp (setq string (regexp-quote string)))
- (setq isearch-string (concat isearch-string string)
- isearch-message
- (concat isearch-message
- (mapconcat 'isearch-text-char-description
- string ""))
- ;; Don't move cursor in reverse search.
- isearch-yank-flag t))
- (isearch-search-and-update))
-
-(defun isearch-yank-kill ()
- "Pull string from kill ring into search string."
- (interactive)
- (isearch-yank 'kill))
-
-(defun isearch-yank-word ()
- "Pull next word from buffer into search string."
- (interactive)
- (isearch-yank 'word))
-
-(defun isearch-yank-line ()
- "Pull rest of line from buffer into search string."
- (interactive)
- (isearch-yank 'line))
-
-
-(defun isearch-search-and-update ()
- ;; Do the search and update the display.
- (if (and (not isearch-success)
- ;; unsuccessful regexp search may become
- ;; successful by addition of characters which
- ;; make isearch-string valid
- (not isearch-regexp))
- nil
- ;; In reverse search, adding stuff at
- ;; the end may cause zero or many more chars to be
- ;; matched, in the string following point.
- ;; Allow all those possibilities without moving point as
- ;; long as the match does not extend past search origin.
- (if (and (not isearch-forward) (not isearch-adjusted)
- (condition-case ()
- (let ((case-fold-search isearch-case-fold-search))
- (looking-at (if isearch-regexp isearch-string
- (regexp-quote isearch-string))))
- (error nil))
- (or isearch-yank-flag
- (<= (match-end 0)
- (min isearch-opoint isearch-barrier))))
- (setq isearch-success t
- isearch-invalid-regexp nil
- isearch-within-brackets nil
- isearch-other-end (match-end 0))
- ;; Not regexp, not reverse, or no match at point.
- (if (and isearch-other-end (not isearch-adjusted))
- (goto-char (if isearch-forward isearch-other-end
- (min isearch-opoint
- isearch-barrier
- (1+ isearch-other-end)))))
- (isearch-search)
- ))
- (isearch-push-state)
- (if isearch-op-fun (funcall isearch-op-fun))
- (isearch-update))
-
-
-;; *, ?, and | chars can make a regexp more liberal.
-;; They can make a regexp match sooner or make it succeed instead of failing.
-;; So go back to place last successful search started
-;; or to the last ^S/^R (barrier), whichever is nearer.
-;; + needs no special handling because the string must match at least once.
-
-(defun isearch-*-char ()
- "Handle * and ? specially in regexps."
- (interactive)
- (if isearch-regexp
-
- (progn
- (setq isearch-adjusted t)
- ;; Get the isearch-other-end from before the last search.
- ;; We want to start from there,
- ;; so that we don't retreat farther than that.
- ;; (car isearch-cmds) is after last search;
- ;; (car (cdr isearch-cmds)) is from before it.
- (let ((cs (nth 5 (car (cdr isearch-cmds)))))
- (setq cs (or cs isearch-barrier))
- (goto-char
- (if isearch-forward
- (max cs isearch-barrier)
- (min cs isearch-barrier))))))
- (isearch-process-search-char (isearch-last-command-char)))
-
-
-(defun isearch-|-char ()
- "If in regexp search, jump to the barrier."
- (interactive)
- (if isearch-regexp
- (progn
- (setq isearch-adjusted t)
- (goto-char isearch-barrier)))
- (isearch-process-search-char (isearch-last-command-char)))
-
-
-(defalias 'isearch-other-control-char 'isearch-other-meta-char)
-
-(defun isearch-other-meta-char ()
- "Exit the search normally and reread this key sequence.
-But only if `search-exit-option' is non-nil, the default.
-If it is the symbol `edit', the search string is edited in the minibuffer
-and the meta character is unread so that it applies to editing the string."
- (interactive)
- (let* ((key (this-command-keys))
- (main-event (aref key 0))
- (keylist (listify-key-sequence key)))
- (cond ((and (= (length key) 1)
- (let ((lookup (lookup-key function-key-map key)))
- (not (or (null lookup) (integerp lookup)
- (keymapp lookup)))))
- ;; Handle a function key that translates into something else.
- ;; If the key has a global definition too,
- ;; exit and unread the key itself, so its global definition runs.
- ;; Otherwise, unread the translation,
- ;; so that the translated key takes effect within isearch.
- (cancel-kbd-macro-events)
- (if (lookup-key global-map key)
- (progn
- (isearch-done)
- (apply 'isearch-unread keylist))
- (apply 'isearch-unread
- (listify-key-sequence (lookup-key function-key-map key)))))
- (
- ;; Handle an undefined shifted control character
- ;; by downshifting it if that makes it defined.
- ;; (As read-key-sequence would normally do,
- ;; if we didn't have a default definition.)
- (let ((mods (event-modifiers main-event)))
- (and (integerp main-event)
- (memq 'shift mods)
- (memq 'control mods)
- (lookup-key isearch-mode-map
- (let ((copy (copy-sequence key)))
- (aset copy 0
- (- main-event (- ?\C-\S-a ?\C-a)))
- copy)
- nil)))
- (setcar keylist (- main-event (- ?\C-\S-a ?\C-a)))
- (cancel-kbd-macro-events)
- (apply 'isearch-unread keylist))
- ((eq search-exit-option 'edit)
- (apply 'isearch-unread keylist)
- (isearch-edit-string))
- (search-exit-option
- (let (window)
- (cancel-kbd-macro-events)
- (apply 'isearch-unread keylist)
- ;; Properly handle scroll-bar and mode-line clicks
- ;; for which a dummy prefix event was generated as (aref key 0).
- (and (> (length key) 1)
- (symbolp (aref key 0))
- (listp (aref key 1))
- (not (numberp (posn-point (event-start (aref key 1)))))
- ;; Convert the event back into its raw form,
- ;; with the dummy prefix implicit in the mouse event,
- ;; so it will get split up once again.
- (progn (setq unread-command-events
- (cdr unread-command-events))
- (setq main-event (car unread-command-events))
- (setcar (cdr (event-start main-event))
- (car (nth 1 (event-start main-event))))))
- ;; If we got a mouse click, maybe it was read with the buffer
- ;; it was clicked on. If so, that buffer, not the current one,
- ;; is in isearch mode. So end the search in that buffer.
- (if (and (listp main-event)
- (setq window (posn-window (event-start main-event)))
- (windowp window))
- (save-excursion
- (set-buffer (window-buffer window))
- (isearch-done))
- (isearch-done))))
- (t;; otherwise nil
- (isearch-process-search-string key key)))))
-
-(defun isearch-quote-char ()
- "Quote special characters for incremental search."
- (interactive)
- (isearch-process-search-char (read-quoted-char (isearch-message t))))
-
-(defun isearch-return-char ()
- "Convert return into newline for incremental search.
-Obsolete."
- (interactive)
- (isearch-process-search-char ?\n))
-
-(defun isearch-printing-char ()
- "Add this ordinary printing character to the search string and search."
- (interactive)
- (isearch-process-search-char (isearch-last-command-char)))
-
-(defun isearch-whitespace-chars ()
- "Match all whitespace chars, if in regexp mode.
-If you want to search for just a space, type C-q SPC."
- (interactive)
- (if isearch-regexp
- (if (and search-whitespace-regexp (not isearch-within-brackets)
- (not isearch-invalid-regexp))
- (isearch-process-search-string search-whitespace-regexp " ")
- (isearch-printing-char))
- (progn
- ;; This way of doing word search doesn't correctly extend current search.
- ;; (setq isearch-word t)
- ;; (setq isearch-adjusted t)
- ;; (goto-char isearch-barrier)
- (isearch-printing-char))))
-
-(defun isearch-process-search-char (char)
- ;; Append the char to the search string, update the message and re-search.
- (isearch-process-search-string
- (isearch-char-to-string char)
- (isearch-text-char-description char)))
-
-(defun isearch-process-search-string (string message)
- (setq isearch-string (concat isearch-string string)
- isearch-message (concat isearch-message message))
- (isearch-search-and-update))
-
-
-;; Search Ring
-
-(defun isearch-ring-adjust1 (advance)
- ;; Helper for isearch-ring-adjust
- (let* ((ring (if isearch-regexp regexp-search-ring search-ring))
- (length (length ring))
- (yank-pointer-name (if isearch-regexp
- 'regexp-search-ring-yank-pointer
- 'search-ring-yank-pointer))
- (yank-pointer (eval yank-pointer-name)))
- (if (zerop length)
- ()
- (set yank-pointer-name
- (setq yank-pointer
- (mod (+ (or yank-pointer 0)
- (if advance -1 1))
- length)))
- (setq isearch-string (nth yank-pointer ring)
- isearch-message (mapconcat 'isearch-text-char-description
- isearch-string "")))))
-
-(defun isearch-ring-adjust (advance)
- ;; Helper for isearch-ring-advance and isearch-ring-retreat
- (isearch-ring-adjust1 advance)
- (if search-ring-update
- (progn
- (isearch-search)
- (isearch-update))
- (isearch-edit-string)
- )
- (isearch-push-state))
-
-(defun isearch-ring-advance ()
- "Advance to the next search string in the ring."
- ;; This could be more general to handle a prefix arg, but who would use it.
- (interactive)
- (isearch-ring-adjust 'advance))
-
-(defun isearch-ring-retreat ()
- "Retreat to the previous search string in the ring."
- (interactive)
- (isearch-ring-adjust nil))
-
-(defun isearch-ring-advance-edit (n)
- "Insert the next element of the search history into the minibuffer."
- (interactive "p")
- (let* ((yank-pointer-name (if isearch-regexp
- 'regexp-search-ring-yank-pointer
- 'search-ring-yank-pointer))
- (yank-pointer (eval yank-pointer-name))
- (ring (if isearch-regexp regexp-search-ring search-ring))
- (length (length ring)))
- (if (zerop length)
- ()
- (set yank-pointer-name
- (setq yank-pointer
- (mod (- (or yank-pointer 0) n)
- length)))
-
- (erase-buffer)
- (insert (nth yank-pointer ring))
- (goto-char (point-max)))))
-
-(defun isearch-ring-retreat-edit (n)
- "Inserts the previous element of the search history into the minibuffer."
- (interactive "p")
- (isearch-ring-advance-edit (- n)))
-
-;;(defun isearch-ring-adjust-edit (advance)
-;; "Use the next or previous search string in the ring while in minibuffer."
-;; (isearch-ring-adjust1 advance)
-;; (erase-buffer)
-;; (insert isearch-string))
-
-;;(defun isearch-ring-advance-edit ()
-;; (interactive)
-;; (isearch-ring-adjust-edit 'advance))
-
-;;(defun isearch-ring-retreat-edit ()
-;; "Retreat to the previous search string in the ring while in the minibuffer."
-;; (interactive)
-;; (isearch-ring-adjust-edit nil))
-
-
-(defun isearch-complete1 ()
- ;; Helper for isearch-complete and isearch-complete-edit
- ;; Return t if completion OK, nil if no completion exists.
- (let* ((ring (if isearch-regexp regexp-search-ring search-ring))
- (alist (mapcar (function (lambda (string) (list string))) ring))
- (completion-ignore-case case-fold-search)
- (completion (try-completion isearch-string alist)))
- (cond
- ((eq completion t)
- ;; isearch-string stays the same
- t)
- ((or completion ; not nil, must be a string
- (= 0 (length isearch-string))) ; shouldn't have to say this
- (if (equal completion isearch-string) ;; no extension?
- (progn
- (if completion-auto-help
- (with-output-to-temp-buffer "*Isearch completions*"
- (display-completion-list
- (all-completions isearch-string alist))))
- t)
- (and completion
- (setq isearch-string completion))))
- (t
- (message "No completion") ; waits a second if in minibuffer
- nil))))
-
-(defun isearch-complete ()
- "Complete the search string from the strings on the search ring.
-The completed string is then editable in the minibuffer.
-If there is no completion possible, say so and continue searching."
- (interactive)
- (if (isearch-complete1)
- (isearch-edit-string)
- ;; else
- (sit-for 1)
- (isearch-update)))
-
-(defun isearch-complete-edit ()
- "Same as `isearch-complete' except in the minibuffer."
- (interactive)
- (setq isearch-string (buffer-string))
- (if (isearch-complete1)
- (progn
- (erase-buffer)
- (insert isearch-string))))
-
-
-;; The search status stack (and isearch window-local variables, not used).
-;; Need a structure for this.
-
-(defun isearch-top-state ()
- (let ((cmd (car isearch-cmds)))
- (setq isearch-string (car cmd)
- isearch-message (car (cdr cmd))
- isearch-success (nth 3 cmd)
- isearch-forward (nth 4 cmd)
- isearch-other-end (nth 5 cmd)
- isearch-word (nth 6 cmd)
- isearch-invalid-regexp (nth 7 cmd)
- isearch-wrapped (nth 8 cmd)
- isearch-barrier (nth 9 cmd)
- isearch-within-brackets (nth 10 cmd)
- isearch-case-fold-search (nth 11 cmd))
- (goto-char (car (cdr (cdr cmd))))))
-
-(defun isearch-pop-state ()
- (setq isearch-cmds (cdr isearch-cmds))
- (isearch-top-state)
- )
-
-(defun isearch-push-state ()
- (setq isearch-cmds
- (cons (list isearch-string isearch-message (point)
- isearch-success isearch-forward isearch-other-end
- isearch-word
- isearch-invalid-regexp isearch-wrapped isearch-barrier
- isearch-within-brackets isearch-case-fold-search)
- isearch-cmds)))
-
-
-;; Message string
-
-(defun isearch-message (&optional c-q-hack ellipsis)
- ;; Generate and print the message string.
- (let ((cursor-in-echo-area ellipsis)
- (m (concat
- (isearch-message-prefix c-q-hack ellipsis isearch-nonincremental)
- isearch-message
- (isearch-message-suffix c-q-hack ellipsis)
- )))
- (if c-q-hack
- m
- (let ((message-log-max nil))
- (message "%s" m)))))
-
-(defun isearch-message-prefix (&optional c-q-hack ellipsis nonincremental)
- ;; 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 isearch-invalid-regexp ellipsis
- (condition-case ()
- (progn (re-search-forward isearch-string (point) t)
- (setq isearch-invalid-regexp nil
- isearch-within-brackets nil))
- (error nil)))
- ;; If currently failing, display no ellipsis.
- (or isearch-success (setq ellipsis nil))
- (let ((m (concat (if isearch-success "" "failing ")
- (if (and isearch-wrapped
- (if isearch-forward
- (> (point) isearch-opoint)
- (< (point) isearch-opoint)))
- "over")
- (if isearch-wrapped "wrapped ")
- (if isearch-word "word " "")
- (if isearch-regexp "regexp " "")
- (if nonincremental "search" "I-search")
- (if isearch-forward ": " " backward: ")
- )))
- (aset m 0 (upcase (aref m 0)))
- m))
-
-
-(defun isearch-message-suffix (&optional c-q-hack ellipsis)
- (concat (if c-q-hack "^Q" "")
- (if isearch-invalid-regexp
- (concat " [" isearch-invalid-regexp "]")
- "")))
-
-
-;;; Searching
-
-(defun isearch-search ()
- ;; Do the search with the current search string.
- (isearch-message nil t)
- (if (and (eq isearch-case-fold-search t) search-upper-case)
- (setq isearch-case-fold-search
- (isearch-no-upper-case-p isearch-string isearch-regexp)))
- (condition-case lossage
- (let ((inhibit-quit nil)
- (case-fold-search isearch-case-fold-search))
- (if isearch-regexp (setq isearch-invalid-regexp nil))
- (setq isearch-within-brackets nil)
- (setq isearch-success
- (funcall
- (cond (isearch-word
- (if isearch-forward
- 'word-search-forward 'word-search-backward))
- (isearch-regexp
- (if isearch-forward
- 're-search-forward 're-search-backward))
- (t
- (if isearch-forward 'search-forward 'search-backward)))
- isearch-string nil t))
- (setq isearch-just-started nil)
- (if isearch-success
- (setq isearch-other-end
- (if isearch-forward (match-beginning 0) (match-end 0)))))
-
- (quit (isearch-unread ?\C-g)
- (setq isearch-success nil))
-
- (invalid-regexp
- (setq isearch-invalid-regexp (car (cdr lossage)))
- (setq isearch-within-brackets (string-match "\\`Unmatched \\["
- isearch-invalid-regexp))
- (if (string-match
- "\\`Premature \\|\\`Unmatched \\|\\`Invalid "
- isearch-invalid-regexp)
- (setq isearch-invalid-regexp "incomplete input")))
- (error
- ;; stack overflow in regexp search.
- (setq isearch-invalid-regexp (car (cdr lossage)))))
-
- (if isearch-success
- nil
- ;; Ding if failed this time after succeeding last time.
- (and (nth 3 (car isearch-cmds))
- (ding))
- (goto-char (nth 2 (car isearch-cmds)))))
-
-
-
-;;; Highlighting
-
-(defvar isearch-overlay nil)
-
-(defun isearch-highlight (beg end)
- (if (or (null search-highlight) (null window-system))
- nil
- (or isearch-overlay (setq isearch-overlay (make-overlay beg end)))
- (move-overlay isearch-overlay beg end (current-buffer))
- (overlay-put isearch-overlay 'face
- (if (internal-find-face 'isearch nil)
- 'isearch 'region))))
-
-(defun isearch-dehighlight (totally)
- (if isearch-overlay
- (delete-overlay isearch-overlay)))
-
-;;; General utilities
-
-
-(defun isearch-no-upper-case-p (string regexp-flag)
- "Return t if there are no upper case chars in STRING.
-If REGEXP-FLAG is non-nil, disregard letters preceded by `\\' (but not `\\\\')
-since they have special meaning in a regexp."
- (let (quote-flag (i 0) (len (length string)) found)
- (while (and (not found) (< i len))
- (let ((char (aref string i)))
- (if (and regexp-flag (eq char ?\\))
- (setq quote-flag (not quote-flag))
- (if (and (not quote-flag) (not (eq char (downcase char))))
- (setq found t))))
- (setq i (1+ i)))
- (not found)))
-
-;; Portability functions to support various Emacs versions.
-
-(defun isearch-char-to-string (c)
- (make-string 1 c))
-
-(defun isearch-text-char-description (c)
- (if (and (integerp c) (or (< c ?\ ) (= c ?\^?)))
- (text-char-description c)
- (isearch-char-to-string c)))
-
-;; General function to unread characters or events.
-;; Also insert them in a keyboard macro being defined.
-(defun isearch-unread (&rest char-or-events)
- (mapcar 'store-kbd-macro-event char-or-events)
- (setq unread-command-events
- (append char-or-events unread-command-events)))
-
-(defun isearch-last-command-char ()
- ;; General function to return the last command character.
- last-command-char)
-
-;;; isearch.el ends here
diff --git a/lisp/iso02-acc.el b/lisp/iso02-acc.el
deleted file mode 100644
index 585670ad802..00000000000
--- a/lisp/iso02-acc.el
+++ /dev/null
@@ -1,124 +0,0 @@
-;;; iso02-acc.el --- electric accent keys for Eastern Europe (ISO latin2)
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(defvar iso-accents-list
- '(((?' ?A) ?\301)
- ((?' ?C) ?\306)
- ((?' ?D) ?\320)
- ((?' ?E) ?\311)
- ((?' ?I) ?\315)
- ((?' ?L) ?\305)
- ((?' ?N) ?\321)
- ((?' ?O) ?\323)
- ((?' ?R) ?\300)
- ((?' ?S) ?\246)
- ((?' ?U) ?\332)
- ((?' ?Y) ?\335)
- ((?' ?Z) ?\254)
- ((?' ?a) ?\341)
- ((?' ?c) ?\346)
- ((?' ?d) ?\360)
- ((?' ?e) ?\351)
- ((?' ?i) ?\355)
- ((?' ?l) ?\345)
- ((?' ?n) ?\361)
- ((?' ?o) ?\363)
- ((?' ?r) ?\340)
- ((?' ?s) ?\266)
- ((?' ?u) ?\372)
- ((?' ?y) ?\375)
- ((?' ?z) ?\274)
- ((?' ?') ?\264)
- ((?' ? ) ?')
- ((?` ?A) ?\241)
- ((?` ?C) ?\307)
- ((?` ?E) ?\312)
- ((?` ?L) ?\243)
- ((?` ?S) ?\252)
- ((?` ?T) ?\336)
- ((?` ?Z) ?\257)
- ((?` ?a) ?\261)
- ((?` ?l) ?\263)
- ((?` ?c) ?\347)
- ((?` ?e) ?\352)
- ((?` ?s) ?\272)
- ((?` ?t) ?\376)
- ((?` ?z) ?\277)
- ((?` ? ) ?`)
- ((?` ?`) ?\252)
- ((?` ?.) ?\377)
- ((?^ ?A) ?\302)
- ((?^ ?O) ?\324)
- ((?^ ?a) ?\342)
- ((?^ ?o) ?\364)
- ((?^ ? ) ?^)
- ((?^ ?^) ?^) ; no special code?
- ((?\" ?A) ?\304)
- ((?\" ?E) ?\313)
- ((?\" ?O) ?\326)
- ((?\" ?U) ?\334)
- ((?\" ?a) ?\344)
- ((?\" ?e) ?\353)
- ((?\" ?o) ?\366)
- ((?\" ?s) ?\337)
- ((?\" ?u) ?\374)
- ((?\" ? ) ?\")
- ((?\" ?\") ?\250)
- ((?\~ ?A) ?\303)
- ((?\~ ?C) ?\310)
- ((?\~ ?D) ?\317)
- ((?\~ ?L) ?\245)
- ((?\~ ?N) ?\322)
- ((?\~ ?O) ?\325)
- ((?\~ ?R) ?\330)
- ((?\~ ?S) ?\251)
- ((?\~ ?T) ?\253)
- ((?\~ ?U) ?\333)
- ((?\~ ?Z) ?\256)
- ((?\~ ?a) ?\323)
- ((?\~ ?c) ?\350)
- ((?\~ ?d) ?\357)
- ((?\~ ?l) ?\265)
- ((?\~ ?n) ?\362)
- ((?\~ ?o) ?\365)
- ((?\~ ?r) ?\370)
- ((?\~ ?s) ?\271)
- ((?\~ ?t) ?\273)
- ((?\~ ?u) ?\373)
- ((?\~ ?z) ?\276)
- ((?\~ ?\ ) ?\~)
- ((?\~ ?v) ?\242) ;; v accent
- ((?\~ ?\~) ?\242) ;; v accent
- ((?\~ ?\.) ?\270) ;; cedilla accent
- )
- "Association list for ISO latin-2 accent combinations.")
-
-(defvar iso-accents-enable '(?' ?` ?^ ?\" ?~)
- "*List of accent keys that become prefixes in ISO Accents mode.
-The default is (?' ?` ?^ ?\" ?~), which contains all the supported
-accent keys. For certain languages, you might want to remove some of
-those characters that are not actually used.")
-
-(require 'iso-acc)
-
-;;; iso02-acc.el ends here
diff --git a/lisp/jka-compr.el b/lisp/jka-compr.el
deleted file mode 100644
index ef1a25f591a..00000000000
--- a/lisp/jka-compr.el
+++ /dev/null
@@ -1,842 +0,0 @@
-;;; jka-compr.el --- reading/writing/loading compressed files
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: jka@ece.cmu.edu (Jay K. Adams)
-;; Keywords: data
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package implements low-level support for reading, writing,
-;; and loading compressed files. It hooks into the low-level file
-;; I/O functions (including write-region and insert-file-contents) so
-;; that they automatically compress or uncompress a file if the file
-;; appears to need it (based on the extension of the file name).
-;; Packages like Rmail, VM, GNUS, and Info should be able to work
-;; with compressed files without modification.
-
-
-;; INSTRUCTIONS:
-;;
-;; To use jka-compr, simply load this package, and edit as usual.
-;; Its operation should be transparent to the user (except for
-;; messages appearing when a file is being compressed or
-;; uncompressed).
-;;
-;; The variable, jka-compr-compression-info-list can be used to
-;; customize jka-compr to work with other compression programs.
-;; The default value of this variable allows jka-compr to work with
-;; Unix compress and gzip.
-;;
-;; If you are concerned about the stderr output of gzip and other
-;; compression/decompression programs showing up in your buffers, you
-;; should set the discard-error flag in the compression-info-list.
-;; This will cause the stderr of all programs to be discarded.
-;; However, it also causes emacs to call compression/uncompression
-;; programs through a shell (which is specified by jka-compr-shell).
-;; This may be a drag if, on your system, starting up a shell is
-;; slow.
-;;
-;; If you don't want messages about compressing and decompressing
-;; to show up in the echo area, you can set the compress-name and
-;; decompress-name fields of the jka-compr-compression-info-list to
-;; nil.
-
-
-;; APPLICATION NOTES:
-;;
-;; crypt++
-;; jka-compr can coexist with crpyt++ if you take all the decompression
-;; entries out of the crypt-encoding-list. Clearly problems will arise if
-;; you have two programs trying to compress/decompress files. jka-compr
-;; will not "work with" crypt++ in the following sense: you won't be able to
-;; decode encrypted compressed files--that is, files that have been
-;; compressed then encrypted (in that order). Theoretically, crypt++ and
-;; jka-compr could properly handle a file that has been encrypted then
-;; compressed, but there is little point in trying to compress an encrypted
-;; file.
-;;
-
-
-;; ACKNOWLEDGMENTS
-;;
-;; jka-compr is a V19 adaptation of jka-compr for V18 of Emacs. Many people
-;; have made helpful suggestions, reported bugs, and even fixed bugs in
-;; jka-compr. I recall the following people as being particularly helpful.
-;;
-;; Jean-loup Gailly
-;; David Hughes
-;; Richard Pieri
-;; Daniel Quinlan
-;; Chris P. Ross
-;; Rick Sladkey
-;;
-;; Andy Norman's ange-ftp was the inspiration for the original jka-compr for
-;; Version 18 of Emacs.
-;;
-;; After I had made progress on the original jka-compr for V18, I learned of a
-;; package written by Kazushi Jam Marukawa, called jam-zcat, that did exactly
-;; what I was trying to do. I looked over the jam-zcat source code and
-;; probably got some ideas from it.
-;;
-
-;;; Code:
-
-(defvar jka-compr-shell "sh"
- "*Shell to be used for calling compression programs.
-The value of this variable only matters if you want to discard the
-stderr of a compression/decompression program (see the documentation
-for `jka-compr-compression-info-list').")
-
-
-(defvar jka-compr-use-shell t)
-
-
-;;; I have this defined so that .Z files are assumed to be in unix
-;;; compress format; and .gz files, in gzip format.
-(defvar jka-compr-compression-info-list
- ;;[regexp
- ;; compr-message compr-prog compr-args
- ;; uncomp-message uncomp-prog uncomp-args
- ;; can-append auto-mode-flag]
- '(["\\.Z\\(~\\|\\.~[0-9]+~\\)?\\'"
- "compressing" "compress" ("-c")
- "uncompressing" "uncompress" ("-c")
- nil t]
- ["\\.tgz\\'"
- "zipping" "gzip" ("-c" "-q")
- "unzipping" "gzip" ("-c" "-q" "-d")
- t nil]
- ["\\.gz\\(~\\|\\.~[0-9]+~\\)?\\'"
- "zipping" "gzip" ("-c" "-q")
- "unzipping" "gzip" ("-c" "-q" "-d")
- t t])
-
- "List of vectors that describe available compression techniques.
-Each element, which describes a compression technique, is a vector of
-the form [REGEXP COMPRESS-MSG COMPRESS-PROGRAM COMPRESS-ARGS
-UNCOMPRESS-MSG UNCOMPRESS-PROGRAM UNCOMPRESS-ARGS
-APPEND-FLAG EXTENSION], where:
-
- regexp is a regexp that matches filenames that are
- compressed with this format
-
- compress-msg is the message to issue to the user when doing this
- type of compression (nil means no message)
-
- compress-program is a program that performs this compression
-
- compress-args is a list of args to pass to the compress program
-
- uncompress-msg is the message to issue to the user when doing this
- type of uncompression (nil means no message)
-
- uncompress-program is a program that performs this compression
-
- uncompress-args is a list of args to pass to the uncompress program
-
- append-flag is non-nil if this compression technique can be
- appended
-
- auto-mode flag non-nil means strip the regexp from file names
- before attempting to set the mode.
-
-Because of the way `call-process' is defined, discarding the stderr output of
-a program adds the overhead of starting a shell each time the program is
-invoked.")
-
-(defvar jka-compr-mode-alist-additions
- (list (cons "\\.tgz\\'" 'tar-mode))
- "A list of pairs to add to auto-mode-alist when jka-compr is installed.")
-
-(defvar jka-compr-file-name-handler-entry
- nil
- "The entry in `file-name-handler-alist' used by the jka-compr I/O functions.")
-
-;;; Functions for accessing the return value of jka-compr-get-compression-info
-(defun jka-compr-info-regexp (info) (aref info 0))
-(defun jka-compr-info-compress-message (info) (aref info 1))
-(defun jka-compr-info-compress-program (info) (aref info 2))
-(defun jka-compr-info-compress-args (info) (aref info 3))
-(defun jka-compr-info-uncompress-message (info) (aref info 4))
-(defun jka-compr-info-uncompress-program (info) (aref info 5))
-(defun jka-compr-info-uncompress-args (info) (aref info 6))
-(defun jka-compr-info-can-append (info) (aref info 7))
-(defun jka-compr-info-strip-extension (info) (aref info 8))
-
-
-(defun jka-compr-get-compression-info (filename)
- "Return information about the compression scheme of FILENAME.
-The determination as to which compression scheme, if any, to use is
-based on the filename itself and `jka-compr-compression-info-list'."
- (catch 'compression-info
- (let ((case-fold-search nil))
- (mapcar
- (function (lambda (x)
- (and (string-match (jka-compr-info-regexp x) filename)
- (throw 'compression-info x))))
- jka-compr-compression-info-list)
- nil)))
-
-
-(put 'compression-error 'error-conditions '(compression-error file-error error))
-
-
-(defvar jka-compr-acceptable-retval-list '(0 2 141))
-
-
-(defun jka-compr-error (prog args infile message &optional errfile)
-
- (let ((errbuf (get-buffer-create " *jka-compr-error*"))
- (curbuf (current-buffer)))
- (set-buffer errbuf)
- (widen) (erase-buffer)
- (insert (format "Error while executing \"%s %s < %s\"\n\n"
- prog
- (mapconcat 'identity args " ")
- infile))
-
- (and errfile
- (insert-file-contents errfile))
-
- (set-buffer curbuf)
- (display-buffer errbuf))
-
- (signal 'compression-error (list "Opening input file" (format "error %s" message) infile)))
-
-
-(defvar jka-compr-dd-program
- "/bin/dd")
-
-
-(defvar jka-compr-dd-blocksize 256)
-
-
-(defun jka-compr-partial-uncompress (prog message args infile beg len)
- "Call program PROG with ARGS args taking input from INFILE.
-Fourth and fifth args, BEG and LEN, specify which part of the output
-to keep: LEN chars starting BEG chars from the beginning."
- (let* ((skip (/ beg jka-compr-dd-blocksize))
- (prefix (- beg (* skip jka-compr-dd-blocksize)))
- (count (and len (1+ (/ (+ len prefix) jka-compr-dd-blocksize))))
- (start (point))
- (err-file (jka-compr-make-temp-name))
- (run-string (format "%s %s 2> %s | %s bs=%d skip=%d %s 2> /dev/null"
- prog
- (mapconcat 'identity args " ")
- err-file
- jka-compr-dd-program
- jka-compr-dd-blocksize
- skip
- ;; dd seems to be unreliable about
- ;; providing the last block. So, always
- ;; read one more than you think you need.
- (if count (concat "count=" (1+ count)) ""))))
-
- (unwind-protect
- (or (memq (call-process jka-compr-shell
- infile t nil "-c"
- run-string)
- jka-compr-acceptable-retval-list)
-
- (jka-compr-error prog args infile message err-file))
-
- (jka-compr-delete-temp-file err-file))
-
- ;; Delete the stuff after what we want, if there is any.
- (and
- len
- (< (+ start prefix len) (point))
- (delete-region (+ start prefix len) (point)))
-
- ;; Delete the stuff before what we want.
- (delete-region start (+ start prefix))))
-
-
-(defun jka-compr-call-process (prog message infile output temp args)
- (if jka-compr-use-shell
-
- (let ((err-file (jka-compr-make-temp-name)))
-
- (unwind-protect
-
- (or (memq
- (call-process jka-compr-shell infile
- (if (stringp output) nil output)
- nil
- "-c"
- (format "%s %s 2> %s %s"
- prog
- (mapconcat 'identity args " ")
- err-file
- (if (stringp output)
- (concat "> " output)
- "")))
- jka-compr-acceptable-retval-list)
-
- (jka-compr-error prog args infile message err-file))
-
- (jka-compr-delete-temp-file err-file)))
-
- (or (zerop
- (apply 'call-process
- prog
- infile
- (if (stringp output) temp output)
- nil
- args))
- (jka-compr-error prog args infile message))
-
- (and (stringp output)
- (let ((cbuf (current-buffer)))
- (set-buffer temp)
- (write-region (point-min) (point-max) output)
- (erase-buffer)
- (set-buffer cbuf)))))
-
-
-;;; Support for temp files. Much of this was inspired if not lifted
-;;; from ange-ftp.
-
-(defvar jka-compr-temp-name-template
- (expand-file-name "jka-com"
- (or (getenv "TMPDIR") "/tmp/"))
- "Prefix added to all temp files created by jka-compr.
-There should be no more than seven characters after the final `/'")
-
-(defvar jka-compr-temp-name-table (make-vector 31 nil))
-
-(defun jka-compr-make-temp-name (&optional local-copy)
- "This routine will return the name of a new file."
- (let* ((lastchar ?a)
- (prevchar ?a)
- (template (concat jka-compr-temp-name-template "aa"))
- (lastpos (1- (length template)))
- (not-done t)
- file
- entry)
-
- (while not-done
- (aset template lastpos lastchar)
- (setq file (concat (make-temp-name template) "#"))
- (setq entry (intern file jka-compr-temp-name-table))
- (if (or (get entry 'active)
- (file-exists-p file))
-
- (progn
- (setq lastchar (1+ lastchar))
- (if (> lastchar ?z)
- (progn
- (setq prevchar (1+ prevchar))
- (setq lastchar ?a)
- (if (> prevchar ?z)
- (error "Can't allocate temp file.")
- (aset template (1- lastpos) prevchar)))))
-
- (put entry 'active (not local-copy))
- (setq not-done nil)))
-
- file))
-
-
-(defun jka-compr-delete-temp-file (temp)
-
- (put (intern temp jka-compr-temp-name-table)
- 'active nil)
-
- (condition-case ()
- (delete-file temp)
- (error nil)))
-
-
-(defun jka-compr-write-region (start end file &optional append visit)
- (let* ((filename (expand-file-name file))
- (visit-file (if (stringp visit) (expand-file-name visit) filename))
- (info (jka-compr-get-compression-info visit-file)))
-
- (if info
-
- (let ((can-append (jka-compr-info-can-append info))
- (compress-program (jka-compr-info-compress-program info))
- (compress-message (jka-compr-info-compress-message info))
- (uncompress-program (jka-compr-info-uncompress-program info))
- (uncompress-message (jka-compr-info-uncompress-message info))
- (compress-args (jka-compr-info-compress-args info))
- (uncompress-args (jka-compr-info-uncompress-args info))
- (base-name (file-name-nondirectory visit-file))
- temp-file cbuf temp-buffer)
-
- (setq cbuf (current-buffer)
- temp-buffer (get-buffer-create " *jka-compr-wr-temp*"))
- (set-buffer temp-buffer)
- (widen) (erase-buffer)
- (set-buffer cbuf)
-
- (if (and append
- (not can-append)
- (file-exists-p filename))
-
- (let* ((local-copy (file-local-copy filename))
- (local-file (or local-copy filename)))
-
- (setq temp-file local-file))
-
- (setq temp-file (jka-compr-make-temp-name)))
-
- (and
- compress-message
- (message "%s %s..." compress-message base-name))
-
- (jka-compr-run-real-handler 'write-region
- (list start end temp-file t 'dont))
-
- (jka-compr-call-process compress-program
- (concat compress-message
- " " base-name)
- temp-file
- temp-buffer
- nil
- compress-args)
-
- (set-buffer temp-buffer)
- (jka-compr-run-real-handler 'write-region
- (list (point-min) (point-max)
- filename
- (and append can-append) 'dont))
- (erase-buffer)
- (set-buffer cbuf)
-
- (jka-compr-delete-temp-file temp-file)
-
- (and
- compress-message
- (message "%s %s...done" compress-message base-name))
-
- (cond
- ((eq visit t)
- (setq buffer-file-name filename)
- (set-visited-file-modtime))
- ((stringp visit)
- (setq buffer-file-name visit)
- (let ((buffer-file-name filename))
- (set-visited-file-modtime))))
-
- (and (or (eq visit t)
- (eq visit nil)
- (stringp visit))
- (message "Wrote %s" visit-file))
-
- nil)
-
- (jka-compr-run-real-handler 'write-region
- (list start end filename append visit)))))
-
-
-(defun jka-compr-insert-file-contents (file &optional visit beg end replace)
- (barf-if-buffer-read-only)
-
- (and (or beg end)
- visit
- (error "Attempt to visit less than an entire file"))
-
- (let* ((filename (expand-file-name file))
- (info (jka-compr-get-compression-info filename)))
-
- (if info
-
- (let ((uncompress-message (jka-compr-info-uncompress-message info))
- (uncompress-program (jka-compr-info-uncompress-program info))
- (uncompress-args (jka-compr-info-uncompress-args info))
- (base-name (file-name-nondirectory filename))
- (notfound nil)
- (local-copy
- (jka-compr-run-real-handler 'file-local-copy (list filename)))
- local-file
- size start)
-
- (setq local-file (or local-copy filename))
-
- (and
- visit
- (setq buffer-file-name filename))
-
- (unwind-protect ; to make sure local-copy gets deleted
-
- (progn
-
- (and
- uncompress-message
- (message "%s %s..." uncompress-message base-name))
-
- (condition-case error-code
-
- (progn
- (if replace
- (goto-char (point-min)))
- (setq start (point))
- (if (or beg end)
- (jka-compr-partial-uncompress uncompress-program
- (concat uncompress-message
- " " base-name)
- uncompress-args
- local-file
- (or beg 0)
- (if (and beg end)
- (- end beg)
- end))
- ;; If visiting, bind off buffer-file-name so that
- ;; file-locking will not ask whether we should
- ;; really edit the buffer.
- (let ((buffer-file-name
- (if visit nil buffer-file-name)))
- (jka-compr-call-process uncompress-program
- (concat uncompress-message
- " " base-name)
- local-file
- t
- nil
- uncompress-args)))
- (setq size (- (point) start))
- (if replace
- (let* ((del-beg (point))
- (del-end (+ del-beg size)))
- (delete-region del-beg
- (min del-end (point-max)))))
- (goto-char start))
- (error
- (if (and (eq (car error-code) 'file-error)
- (eq (nth 3 error-code) local-file))
- (if visit
- (setq notfound error-code)
- (signal 'file-error
- (cons "Opening input file"
- (nthcdr 2 error-code))))
- (signal (car error-code) (cdr error-code))))))
-
- (and
- local-copy
- (file-exists-p local-copy)
- (delete-file local-copy)))
-
- (and
- visit
- (progn
- (unlock-buffer)
- (setq buffer-file-name filename)
- (set-visited-file-modtime)))
-
- (and
- uncompress-message
- (message "%s %s...done" uncompress-message base-name))
-
- (and
- visit
- notfound
- (signal 'file-error
- (cons "Opening input file" (nth 2 notfound))))
-
- ;; Run the functions that insert-file-contents would.
- (let ((p after-insert-file-functions)
- (insval size))
- (while p
- (setq insval (funcall (car p) size))
- (if insval
- (progn
- (or (integerp insval)
- (signal 'wrong-type-argument
- (list 'integerp insval)))
- (setq size insval)))
- (setq p (cdr p))))
-
- (list filename size))
-
- (jka-compr-run-real-handler 'insert-file-contents
- (list file visit beg end replace)))))
-
-
-(defun jka-compr-file-local-copy (file)
- (let* ((filename (expand-file-name file))
- (info (jka-compr-get-compression-info filename)))
-
- (if info
-
- (let ((uncompress-message (jka-compr-info-uncompress-message info))
- (uncompress-program (jka-compr-info-uncompress-program info))
- (uncompress-args (jka-compr-info-uncompress-args info))
- (base-name (file-name-nondirectory filename))
- (local-copy
- (jka-compr-run-real-handler 'file-local-copy (list filename)))
- (temp-file (jka-compr-make-temp-name t))
- (temp-buffer (get-buffer-create " *jka-compr-flc-temp*"))
- (notfound nil)
- (cbuf (current-buffer))
- local-file)
-
- (setq local-file (or local-copy filename))
-
- (unwind-protect
-
- (progn
-
- (and
- uncompress-message
- (message "%s %s..." uncompress-message base-name))
-
- (set-buffer temp-buffer)
-
- (jka-compr-call-process uncompress-program
- (concat uncompress-message
- " " base-name)
- local-file
- t
- nil
- uncompress-args)
-
- (and
- uncompress-message
- (message "%s %s...done" uncompress-message base-name))
-
- (write-region
- (point-min) (point-max) temp-file nil 'dont))
-
- (and
- local-copy
- (file-exists-p local-copy)
- (delete-file local-copy))
-
- (set-buffer cbuf)
- (kill-buffer temp-buffer))
-
- temp-file)
-
- (jka-compr-run-real-handler 'file-local-copy (list filename)))))
-
-
-;;; Support for loading compressed files.
-(defun jka-compr-load (file &optional noerror nomessage nosuffix)
- "Documented as original."
-
- (let* ((local-copy (jka-compr-file-local-copy file))
- (load-file (or local-copy file)))
-
- (unwind-protect
-
- (let (inhibit-file-name-operation
- inhibit-file-name-handlers)
- (or nomessage
- (message "Loading %s..." file))
-
- (let ((load-force-doc-strings t))
- (load load-file noerror t t))
-
- (or nomessage
- (message "Loading %s...done." file)))
-
- (jka-compr-delete-temp-file local-copy))
-
- t))
-
-(defun jka-compr-byte-compiler-base-file-name (file)
- (let ((info (jka-compr-get-compression-info file)))
- (if (and info (jka-compr-info-strip-extension info))
- (save-match-data
- (substring file 0 (string-match (jka-compr-info-regexp info) file)))
- file)))
-
-(put 'write-region 'jka-compr 'jka-compr-write-region)
-(put 'insert-file-contents 'jka-compr 'jka-compr-insert-file-contents)
-(put 'file-local-copy 'jka-compr 'jka-compr-file-local-copy)
-(put 'load 'jka-compr 'jka-compr-load)
-(put 'byte-compiler-base-file-name 'jka-compr
- 'jka-compr-byte-compiler-base-file-name)
-
-(defun jka-compr-handler (operation &rest args)
- (save-match-data
- (let ((jka-op (get operation 'jka-compr)))
- (if jka-op
- (apply jka-op args)
- (jka-compr-run-real-handler operation args)))))
-
-;; If we are given an operation that we don't handle,
-;; call the Emacs primitive for that operation,
-;; and manipulate the inhibit variables
-;; to prevent the primitive from calling our handler again.
-(defun jka-compr-run-real-handler (operation args)
- (let ((inhibit-file-name-handlers
- (cons 'jka-compr-handler
- (and (eq inhibit-file-name-operation operation)
- inhibit-file-name-handlers)))
- (inhibit-file-name-operation operation))
- (apply operation args)))
-
-;;;###autoload(defun auto-compression-mode (&optional arg)
-;;;###autoload "\
-;;;###autoloadToggle automatic file compression and uncompression.
-;;;###autoloadWith prefix argument ARG, turn auto compression on if positive, else off.
-;;;###autoloadReturns the new status of auto compression (non-nil means on)."
-;;;###autoload (interactive "P")
-;;;###autoload (if (not (fboundp 'jka-compr-installed-p))
-;;;###autoload (progn
-;;;###autoload (require 'jka-compr)
-;;;###autoload ;; That turned the mode on, so make it initially off.
-;;;###autoload (toggle-auto-compression)))
-;;;###autoload (toggle-auto-compression arg t))
-
-(defun toggle-auto-compression (&optional arg message)
- "Toggle automatic file compression and uncompression.
-With prefix argument ARG, turn auto compression on if positive, else off.
-Returns the new status of auto compression (non-nil means on).
-If the argument MESSAGE is non-nil, it means to print a message
-saying whether the mode is now on or off."
- (interactive "P\np")
- (let* ((installed (jka-compr-installed-p))
- (flag (if (null arg)
- (not installed)
- (or (eq arg t) (listp arg) (and (integerp arg) (> arg 0))))))
-
- (cond
- ((and flag installed) t) ; already installed
-
- ((and (not flag) (not installed)) nil) ; already not installed
-
- (flag
- (jka-compr-install))
-
- (t
- (jka-compr-uninstall)))
-
-
- (and message
- (if flag
- (message "Automatic file (de)compression is now ON.")
- (message "Automatic file (de)compression is now OFF.")))
-
- flag))
-
-(defun jka-compr-build-file-regexp ()
- (concat
- "\\("
- (mapconcat
- 'jka-compr-info-regexp
- jka-compr-compression-info-list
- "\\)\\|\\(")
- "\\)"))
-
-
-(defun jka-compr-install ()
- "Install jka-compr.
-This adds entries to `file-name-handler-alist' and `auto-mode-alist'
-and `inhibit-first-line-modes-suffixes'."
-
- (setq jka-compr-file-name-handler-entry
- (cons (jka-compr-build-file-regexp) 'jka-compr-handler))
-
- (setq file-name-handler-alist (cons jka-compr-file-name-handler-entry
- file-name-handler-alist))
-
- (mapcar
- (function (lambda (x)
- (and (jka-compr-info-strip-extension x)
- ;; Make entries in auto-mode-alist so that modes
- ;; are chosen right according to the file names
- ;; sans `.gz'.
- (setq auto-mode-alist
- (cons (list (jka-compr-info-regexp x)
- nil 'jka-compr)
- auto-mode-alist))
- ;; Also add these regexps to
- ;; inhibit-first-line-modes-suffixes, so that a
- ;; -*- line in the first file of a compressed tar
- ;; file doesn't override tar-mode.
- (setq inhibit-first-line-modes-suffixes
- (cons (jka-compr-info-regexp x)
- inhibit-first-line-modes-suffixes)))))
- jka-compr-compression-info-list)
- (setq auto-mode-alist
- (append auto-mode-alist jka-compr-mode-alist-additions)))
-
-
-(defun jka-compr-uninstall ()
- "Uninstall jka-compr.
-This removes the entries in `file-name-handler-alist' and `auto-mode-alist'
-and `inhibit-first-line-modes-suffixes' that were added
-by `jka-compr-installed'."
- ;; Delete from inhibit-first-line-modes-suffixes
- ;; what jka-compr-install added.
- (mapcar
- (function (lambda (x)
- (and (jka-compr-info-strip-extension x)
- (setq inhibit-first-line-modes-suffixes
- (delete (jka-compr-info-regexp x)
- inhibit-first-line-modes-suffixes)))))
- jka-compr-compression-info-list)
-
- (let* ((fnha (cons nil file-name-handler-alist))
- (last fnha))
-
- (while (cdr last)
- (if (eq (cdr (car (cdr last))) 'jka-compr-handler)
- (setcdr last (cdr (cdr last)))
- (setq last (cdr last))))
-
- (setq file-name-handler-alist (cdr fnha)))
-
- (let* ((ama (cons nil auto-mode-alist))
- (last ama)
- entry)
-
- (while (cdr last)
- (setq entry (car (cdr last)))
- (if (or (member entry jka-compr-mode-alist-additions)
- (and (consp (cdr entry))
- (eq (nth 2 entry) 'jka-compr)))
- (setcdr last (cdr (cdr last)))
- (setq last (cdr last))))
-
- (setq auto-mode-alist (cdr ama))))
-
-
-(defun jka-compr-installed-p ()
- "Return non-nil if jka-compr is installed.
-The return value is the entry in `file-name-handler-alist' for jka-compr."
-
- (let ((fnha file-name-handler-alist)
- (installed nil))
-
- (while (and fnha (not installed))
- (and (eq (cdr (car fnha)) 'jka-compr-handler)
- (setq installed (car fnha)))
- (setq fnha (cdr fnha)))
-
- installed))
-
-
-;;; Add the file I/O hook if it does not already exist.
-;;; Make sure that jka-compr-file-name-handler-entry is eq to the
-;;; entry for jka-compr in file-name-handler-alist.
-(and (jka-compr-installed-p)
- (jka-compr-uninstall))
-
-(jka-compr-install)
-
-
-(provide 'jka-compr)
-
-;; jka-compr.el ends here.
diff --git a/lisp/kermit.el b/lisp/kermit.el
deleted file mode 100644
index 0eebc7aa082..00000000000
--- a/lisp/kermit.el
+++ /dev/null
@@ -1,149 +0,0 @@
-;;; kermit.el --- additions to shell mode for use with kermit, etc.
-
-;; Copyright (C) 1988 Free Software Foundation, Inc.
-
-;; Author: Jeff Norden <jeff@colgate.csnet>
-;; Created: 15 Feb 1988
-;; Keywords: comm
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; I'm not sure, but I think somebody asked about running kermit under shell
-;; mode a while ago. Anyway, here is some code that I find useful. The result
-;; is that I can log onto machines with primitive operating systems (VMS and
-;; ATT system V :-), and still have the features of shell-mode available for
-;; command history, etc. It's also handy to be able to run a file transfer in
-;; an emacs window. The transfer is in the "background", but you can also
-;; monitor or stop it easily.
-
-;; The ^\ key is bound to a function for sending escape sequences to kermit,
-;; and ^C^Q can be used to send any control characters needed thru to the
-;; system you connect to. A more serious problem is that some brain-dead
-;; systems will not recognize a ^J as an end-of-line character. So LFD is
-;; bound to a new function which acts just like CR usually does in shell-mode,
-;; but a ^M is sent as an end-of-line. Functions are also provided to swap the
-;; bindings of CR and LFD. I've also included a filter which will clean out
-;; any ^M's or ^@'s that get typed at you, but I don't really recommend it.
-;; There doesn't seem to be an acceptably fast way to do this via emacs-lisp.
-;; Invoking kermit by the command " kermit | tr -d '\015' " seems to work
-;; better (on my system anyway).
-
-;; Here's how I've been using this setup. We have several machines connected
-;; thru a fairly stupid terminal switch. If I want to connect to unix system,
-;; then I use the LFD key to talk to the switch, and ignore any ^M's in the
-;; buffer, and do a " stty -echo nl " after I log in. Then the only real
-;; difference from being in local shell-mode is that you need to type
-;; ^C^Q^C to send an interrupt, and ^C^Q^Z for a stop signal, etc. (since ^C^C
-;; just generates a local stop signal, which kermit ignores).
-;; To connect to a VMS system, I use a shell script to invoke kermit thru the
-;; tr filter, do "M-X kermit-send-cr", and then tell VMS that I'm on a
-;; half-duplex terminal.
-
-;; Some caveats:
-;; 1) Kermit under shell mode is a real pain if you don't have pty's. I
-;; recently discovered this on our 3b2/400. When kermit can't find a tty, it
-;; assumes it is supposed to be in remote mode. So the simple command "kermit"
-;; won't work in shell mode on such a system. You can get around this by using
-;; the -c (connect) command line option, which means you also have to specify a
-;; line and baud on the command line, as in "kermit -l /dev/tty53 -b 9600 -c".
-;; However, this will cause kermit to exit when the connection is closed. So
-;; in order to do a file transfer, you have to think ahead and and add -r
-;; (receive) to the command line. This means that you can't use the server
-;; feature. The only fix I can see is to muck around with the source code for
-;; kermit, although this probably wouldn't be too hard. What is needed is an
-;; option to force kermit to be local, to use stdin and stdout for interactive
-;; speech, and to forget about cbreak mode.
-
-;; Please let me know if any bugs turn up.
-;; Feb 1988, Jeff Norden - jeff@colgate.csnet
-
-;;; Code:
-
-(require 'shell)
-
-(defvar kermit-esc-char "\C-\\" "*Kermit's escape char")
-
-(defun kermit-esc ()
- "For sending escape sequences to a kermit running in shell mode."
- (interactive)
- (process-send-string
- (get-buffer-process (current-buffer))
- (concat kermit-esc-char (char-to-string (read-char)))))
-
-(defun kermit-send-char ()
- "Send an arbitrary character to a program in shell mode."
- (interactive)
- (process-send-string
- (get-buffer-process (current-buffer))
- (char-to-string (read-char))))
-
-(define-key shell-mode-map "\C-\\" 'kermit-esc)
-(define-key shell-mode-map "\C-c\C-q" 'kermit-send-char)
-;; 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."
- (interactive)
- (comint-send-input)
- (comint-send-string (get-buffer-process (current-buffer)) "\r"))
-
-;; This is backwards of what makes sense, but ...
-(define-key shell-mode-map "\n" 'kermit-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))
-
-(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-backward "[\r\C-a]+" beg t)
- (replace-match "")))))
-
-(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''."
- (interactive)
- (set-process-filter (get-buffer-process (current-buffer))
- 'kermit-clean-filter))
-
-(defun kermit-clean-off ()
- "Cancel a previous kermit-clean-shell-on command."
- (interactive)
- (set-process-filter (get-buffer-process (current-buffer)) nil))
-
-;;; kermit.el ends here
diff --git a/lisp/lazy-lock.el b/lisp/lazy-lock.el
deleted file mode 100644
index fffb0204c77..00000000000
--- a/lisp/lazy-lock.el
+++ /dev/null
@@ -1,1047 +0,0 @@
-;;; lazy-lock.el --- Lazy demand-driven fontification for fast Font Lock mode.
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Simon Marshall <simon@gnu.ai.mit.edu>
-;; Keywords: faces files
-;; Version: 2.07
-
-;;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Lazy Lock mode is a Font Lock support mode.
-;; It makes visiting buffers in Font Lock mode faster by making fontification
-;; be demand-driven, deferred and stealthy, so that fontification only occurs
-;; when, and where, necessary.
-;;
-;; See caveats and feedback below.
-;; See also the fast-lock package. (But don't use them at the same time!)
-
-;; Installation:
-;;
-;; Put in your ~/.emacs:
-;;
-;; (setq font-lock-support-mode 'lazy-lock-mode)
-;;
-;; Start up a new Emacs and use font-lock as usual (except that you can use the
-;; so-called "gaudier" fontification regexps on big files without frustration).
-;;
-;; In a buffer (which has `font-lock-mode' enabled) which is at least
-;; `lazy-lock-minimum-size' characters long, buffer fontification will not
-;; occur and only the visible portion of the buffer will be fontified. Motion
-;; around the buffer will fontify those visible portions not previously
-;; fontified. If stealth fontification is enabled, buffer fontification will
-;; occur in invisible parts of the buffer after `lazy-lock-stealth-time'
-;; seconds of idle time. If on-the-fly fontification is deferred, on-the-fly
-;; fontification will occur after `lazy-lock-defer-time' seconds of idle time.
-
-;; User-visible differences with version 1:
-;;
-;; - Version 2 can defer on-the-fly fontification. Therefore you need not, and
-;; should not, use defer-lock.el with this version of lazy-lock.el.
-;;
-;; A number of variables have changed meaning:
-;;
-;; - A value of nil for the variable `lazy-lock-minimum-size' means never turn
-;; on demand-driven fontification. In version 1 this meant always turn on
-;; demand-driven fontification. If you really want demand-driven fontification
-;; regardless of buffer size, set this variable to 0.
-;;
-;; - The variable `lazy-lock-stealth-lines' cannot have a nil value. In
-;; version 1 this meant use `window-height' as the maximum number of lines to
-;; fontify as a stealth chunk. This makes no sense; stealth fontification is
-;; of a buffer, not a window.
-
-;; Implementation differences with version 1:
-;;
-;; - Version 1 of lazy-lock.el is a bit of a hack. Version 1 demand-driven
-;; fontification, the core feature of lazy-lock.el, is implemented by placing a
-;; function on `post-command-hook'. This function fontifies where necessary,
-;; i.e., where a window scroll has occurred. However, there are a number of
-;; problems with using `post-command-hook':
-;;
-;; (a) As the name suggests, `post-command-hook' is run after every command,
-;; i.e., frequently and regardless of whether scrolling has occurred.
-;; (b) Scrolling can occur during a command, when `post-command-hook' is not
-;; run, i.e., it is not necessarily run after scrolling has occurred.
-;; (c) When `post-command-hook' is run, there is nothing to suggest where
-;; scrolling might have occurred, i.e., which windows have scrolled.
-;;
-;; Thus lazy-lock.el's function is called almost as often as possible, usually
-;; when it need not be called, yet it is not always called when it is needed.
-;; Also, lazy-lock.el's function must check each window to see if a scroll has
-;; occurred there. Worse still, lazy-lock.el's function must fontify a region
-;; twice as large as necessary to make sure the window is completely fontified.
-;; Basically, `post-command-hook' is completely inappropriate for lazy-lock.el.
-;;
-;; Ideally, we want to attach lazy-lock.el's function to a hook that is run
-;; only when scrolling occurs, e.g., `window-start' has changed, and tells us
-;; as much information as we need, i.e., the window and its new buffer region.
-;; Richard Stallman implemented a `window-scroll-functions' for Emacs 19.30.
-;; Functions on it are run when `window-start' has changed, and are supplied
-;; with the window and the window's new `window-start' position. (It would be
-;; better if it also supplied the window's new `window-end' position, but that
-;; is calculated as part of the redisplay process, and the functions on
-;; `window-scroll-functions' are run before redisplay has finished.) Thus, the
-;; hook deals with the above problems (a), (b) and (c).
-;;
-;; If only life was that easy. Version 2 demand-driven fontification is mostly
-;; implemented by placing a function on `window-scroll-functions'. However,
-;; not all scrolling occurs when `window-start' has changed. A change in
-;; window size, e.g., via C-x 1, or a significant deletion, e.g., of a number
-;; of lines, causes text previously invisible (i.e., after `window-end') to
-;; become visible without changing `window-start'. Arguably, these events are
-;; not scrolling events, but fontification must occur for lazy-lock.el to work.
-;; Hooks `window-size-change-functions' and `redisplay-end-trigger-functions'
-;; were added for these circumstances.
-;;
-;; Ben Wing thinks these hooks are "horribly horribly kludgy", and implemented
-;; a `pre-idle-hook', a `mother-of-all-post-command-hooks', for XEmacs 19.14.
-;; He then hacked up a version 1 lazy-lock.el to use `pre-idle-hook' rather
-;; than `post-command-hook'. Whereas functions on `post-command-hook' are
-;; called almost as often as possible, functions on `pre-idle-hook' really are
-;; called as often as possible, even when the mouse moves and, on some systems,
-;; while XEmacs is idle. Thus, the hook deals with the above problem (b), but
-;; unfortunately it makes (a) worse and does not address (c) at all.
-;;
-;; I freely admit that `redisplay-end-trigger-functions' and, to a much lesser
-;; extent, `window-size-change-functions' are not pretty. However, I feel that
-;; a `window-scroll-functions' feature is cleaner than a `pre-idle-hook', and
-;; the result is faster and smaller, less intrusive and more targeted, code.
-;; Since `pre-idle-hook' is pretty much like `post-command-hook', there is no
-;; point in making this version of lazy-lock.el work with it. Anyway, that's
-;; Lit 30 of my humble opinion.
-;;
-;; - Version 1 stealth fontification is also implemented by placing a function
-;; on `post-command-hook'. This function waits for a given amount of time,
-;; and, if Emacs remains idle, fontifies where necessary. Again, there are a
-;; number of problems with using `post-command-hook':
-;;
-;; (a) Functions on `post-command-hook' are run sequentially, so this function
-;; can interfere with other functions on the hook, and vice versa.
-;; (b) This function waits for a given amount of time, so it can interfere with
-;; various features that are dealt with by Emacs after a command, e.g.,
-;; region highlighting, asynchronous updating and keystroke echoing.
-;; (c) Fontification may be required during a command, when `post-command-hook'
-;; is not run. (Version 2 deferred fontification only.)
-;;
-;; Again, `post-command-hook' is completely inappropriate for lazy-lock.el.
-;; Richard Stallman and Morten Welinder implemented internal Timers and Idle
-;; Timers for Emacs 19.31. Functions can be run independently at given times
-;; or after given amounts of idle time. Thus, the feature deals with the above
-;; problems (a), (b) and (c). Version 2 deferral and stealth are implemented
-;; by functions on Idle Timers. (A function on XEmacs' `pre-idle-hook' is
-;; similar to an Emacs Idle Timer function with a fixed zero second timeout.)
-
-;; Caveats:
-;;
-;; Lazy Lock mode does not work efficiently with Outline mode.
-;; This is because when in Outline mode, although text may be not visible to
-;; you in the window, the text is visible to Emacs Lisp code (not surprisingly)
-;; and Lazy Lock fontifies it mercilessly. Maybe it will be fixed one day.
-;;
-;; Because buffer text is not necessarily fontified, other packages that expect
-;; buffer text to be fontified in Font Lock mode either might not work as
-;; expected, or might not display buffer text as expected. An example of the
-;; latter is `occur', which copies lines of buffer text into another buffer.
-;;
-;; In Emacs 19.30, Lazy Lock mode does not ensure that an existing buffer is
-;; fontified if it is made visible via a minibuffer-less command that replaces
-;; an existing window's buffer (e.g., via the Buffers menu). Upgrade!
-;;
-;; In Emacs 19.30, Lazy Lock mode does not work well with Transient Mark mode
-;; or modes based on Comint mode (e.g., Shell mode), and also interferes with
-;; the echoing of keystrokes in the minibuffer. This is because of the way
-;; deferral and stealth have to be implemented for Emacs 19.30. Upgrade!
-;;
-;; Currently XEmacs does not have the features to support this version of
-;; lazy-lock.el. Maybe it will one day.
-
-;; History:
-;;
-;; 1.15--2.00:
-;; - Rewrite for Emacs 19.30 and the features rms added to support lazy-lock.el
-;; so that it could work correctly and efficiently.
-;; - Many thanks to those who reported bugs, fixed bugs, made suggestions or
-;; otherwise contributed in the version 1 cycle; Jari Aalto, Kevin Broadey,
-;; Ulrik Dickow, Bill Dubuque, Bob Glickstein, Boris Goldowsky,
-;; Jonas Jarnestrom, David Karr, Michael Kifer, Erik Naggum, Rick Sladkey,
-;; Jim Thompson, Ben Wing, Ilya Zakharevich, and Richard Stallman.
-;; 2.00--2.01:
-;; - Made `lazy-lock-fontify-after-command' always `sit-for' and so redisplay
-;; - Use `buffer-name' not `buffer-live-p' (Bill Dubuque hint)
-;; - Made `lazy-lock-install' do `add-to-list' not `setq' of `current-buffer'
-;; - Made `lazy-lock-fontify-after-install' loop over buffer list
-;; - Made `lazy-lock-arrange-before-change' to arrange `window-end' triggering
-;; - Made `lazy-lock-let-buffer-state' wrap both `befter-change-functions'
-;; - Made `lazy-lock-fontify-region' do `condition-case' (Hyman Rosen report)
-;; 2.01--2.02:
-;; - Use `buffer-live-p' as `buffer-name' can barf (Richard Stanton report)
-;; - Made `lazy-lock-install' set `font-lock-fontified' (Kevin Davidson report)
-;; - Made `lazy-lock-install' add hooks only if needed
-;; - Made `lazy-lock-unstall' add `font-lock-after-change-function' if needed
-;; 2.02--2.03:
-;; - Made `lazy-lock-fontify-region' do `condition-case' for `quit' too
-;; - Made `lazy-lock-mode' respect the value of `font-lock-inhibit-thing-lock'
-;; - Added `lazy-lock-after-unfontify-buffer'
-;; - Removed `lazy-lock-fontify-after-install' hack
-;; - Made `lazy-lock-fontify-after-scroll' not `set-buffer' to `window-buffer'
-;; - Made `lazy-lock-fontify-after-trigger' not `set-buffer' to `window-buffer'
-;; - Made `lazy-lock-fontify-after-idle' be interruptible (Scott Burson hint)
-;; 2.03--2.04:
-;; - Rewrite for Emacs 19.31 idle timers
-;; - Renamed `buffer-windows' to `get-buffer-window-list'
-;; - Removed `buffer-live-p'
-;; - Made `lazy-lock-defer-after-change' always save `current-buffer'
-;; - Made `lazy-lock-fontify-after-defer' just process buffers
-;; - Made `lazy-lock-install-hooks' add hooks correctly (Kevin Broadey report)
-;; - Made `lazy-lock-install' cope if `lazy-lock-defer-time' is a list
-;; 2.04--2.05:
-;; - Rewrite for Common Lisp macros
-;; - Added `do-while' macro
-;; - Renamed `lazy-lock-let-buffer-state' macro to `save-buffer-state'
-;; - Returned `lazy-lock-fontify-after-install' hack (Darren Hall hint)
-;; - Added `lazy-lock-defer-on-scrolling' functionality (Scott Byer hint)
-;; - Made `lazy-lock-mode' wrap `font-lock-support-mode'
-;; 2.05--2.06:
-;; - Made `lazy-lock-fontify-after-defer' swap correctly (Scott Byer report)
-;; 2.06--2.07:
-;; - Added `lazy-lock-stealth-load' functionality (Rob Hooft hint)
-;; - Made `lazy-lock-unstall' call `lazy-lock-fontify-region' if needed
-;; - Made `lazy-lock-mode' call `lazy-lock-unstall' only if needed
-;; - Made `lazy-lock-defer-after-scroll' do `set-window-redisplay-end-trigger'
-;; - Added `lazy-lock-defer-contextually' functionality
-;; - Added `lazy-lock-defer-on-the-fly' from `lazy-lock-defer-time'
-;; - Renamed `lazy-lock-defer-driven' to `lazy-lock-defer-on-scrolling'
-;; - Removed `lazy-lock-submit-bug-report' and bade farewell
-
-;;; Code:
-
-(require 'font-lock)
-
-;; Make sure lazy-lock.el is supported.
-(if (if (save-match-data (string-match "Lucid\\|XEmacs" (emacs-version)))
- t
- (and (= emacs-major-version 19) (< emacs-minor-version 30)))
- (error "`lazy-lock' was written for Emacs 19.30 or later"))
-
-;; Flush out those lusers who didn't read all of the Commentary.
-(if (or (memq 'turn-on-defer-lock font-lock-mode-hook)
- (memq 'defer-lock-mode font-lock-mode-hook))
- (error "`lazy-lock' was written for use without `defer-lock'"))
-
-(eval-when-compile
- ;;
- ;; We don't do this at the top-level as idle timers are not necessarily used.
- (require 'timer)
- ;; We don't do this at the top-level as we only use non-autoloaded macros.
- (require 'cl)
- ;;
- ;; Well, shouldn't Lazy Lock mode be as lazy as possible?
- (setq byte-compile-dynamic t byte-compile-dynamic-docstrings t)
- ;; But, we make sure that the code is as zippy as can be.
- (setq byte-optimize t)
- ;;
- ;; We use this to preserve or protect things when modifying text properties.
- (defmacro save-buffer-state (varlist &rest body)
- "Bind variables according to VARLIST and eval BODY restoring buffer state."
- (` (let* ((,@ (append varlist
- '((modified (buffer-modified-p))
- (inhibit-read-only t) (buffer-undo-list t)
- before-change-functions after-change-functions
- deactivate-mark buffer-file-name buffer-file-truename))))
- (,@ body)
- (when (and (not modified) (buffer-modified-p))
- (set-buffer-modified-p nil)))))
- (put 'save-buffer-state 'lisp-indent-function 1)
- ;;
- ;; We use this for clarity and speed. Naughty but nice.
- (defmacro do-while (test &rest body)
- "(do-while TEST BODY...): eval BODY... and repeat if TEST yields non-nil.
-The order of execution is thus BODY, TEST, BODY, TEST and so on
-until TEST returns nil."
- (` (while (progn (,@ body) (, test)))))
- (put 'do-while 'lisp-indent-function (get 'while 'lisp-indent-function))
- ;;
- ;; We use this for clarity and speed. Borrowed from a future Emacs.
- (or (fboundp 'with-current-buffer)
- (defmacro with-current-buffer (buffer &rest body)
- "Execute the forms in BODY with BUFFER as the current buffer.
-The value returned is the value of the last form in BODY."
- (` (save-excursion (set-buffer (, buffer)) (,@ body)))))
- (put 'with-current-buffer 'lisp-indent-function 1))
-
-;(defun lazy-lock-submit-bug-report ()
-; "Submit via mail a bug report on lazy-lock.el."
-; (interactive)
-; (let ((reporter-prompt-for-summary-p t))
-; (reporter-submit-bug-report "simon@gnu.ai.mit.edu" "lazy-lock 2.07"
-; '(lazy-lock-minimum-size lazy-lock-defer-on-the-fly
-; lazy-lock-defer-on-scrolling lazy-lock-defer-contextually
-; lazy-lock-defer-time lazy-lock-stealth-time
-; lazy-lock-stealth-load lazy-lock-stealth-nice lazy-lock-stealth-lines
-; lazy-lock-stealth-verbose)
-; nil nil
-; (concat "Hi Si.,
-;
-;I want to report a bug. I've read the `Bugs' section of `Info' on Emacs, so I
-;know how to make a clear and unambiguous report. To reproduce the bug:
-;
-;Start a fresh editor via `" invocation-name " -no-init-file -no-site-file'.
-;In the `*scratch*' buffer, evaluate:"))))
-
-(defvar lazy-lock-mode nil)
-(defvar lazy-lock-buffers nil) ; for deferral
-(defvar lazy-lock-timers (cons nil nil)) ; for deferral and stealth
-
-;; User Variables:
-
-(defvar lazy-lock-minimum-size (* 25 1024)
- "*Minimum size of a buffer for demand-driven fontification.
-On-demand fontification occurs if the buffer size is greater than this value.
-If nil, means demand-driven fontification is never performed.
-If a list, each element should be a cons pair of the form (MAJOR-MODE . SIZE),
-where MAJOR-MODE is a symbol or t (meaning the default). For example:
- ((c-mode . 25600) (c++-mode . 25600) (rmail-mode . 1048576))
-means that the minimum size is 25K for buffers in C or C++ modes, one megabyte
-for buffers in Rmail mode, and size is irrelevant otherwise.
-
-The value of this variable is used when Lazy Lock mode is turned on.")
-
-(defvar lazy-lock-defer-on-the-fly t
- "*If non-nil, means fontification after a change should be deferred.
-If nil, means on-the-fly fontification is performed. This means when changes
-occur in the buffer, those areas are immediately fontified.
-If a list, it should be a list of `major-mode' symbol names for which deferred
-fontification should occur. The sense of the list is negated if it begins with
-`not'. For example:
- (c-mode c++-mode)
-means that on-the-fly fontification is deferred for buffers in C and C++ modes
-only, and deferral does not occur otherwise.
-
-The value of this variable is used when Lazy Lock mode is turned on.")
-
-(defvar lazy-lock-defer-on-scrolling nil
- "*If non-nil, means fontification after a scroll should be deferred.
-If nil, means demand-driven fontification is performed. This means when
-scrolling into unfontified areas of the buffer, those areas are immediately
-fontified. Thus scrolling never presents unfontified areas. However, since
-fontification occurs during scrolling, scrolling may be slow.
-If t, means defer-driven fontification is performed. This means fontification
-of those areas is deferred. Thus scrolling may present momentarily unfontified
-areas. However, since fontification does not occur during scrolling, scrolling
-will be faster than demand-driven fontification.
-If any other value, e.g., `eventually', means demand-driven fontification is
-performed until the buffer is fontified, then buffer fontification becomes
-defer-driven. Thus scrolling never presents unfontified areas until the buffer
-is first fontified, after which subsequent scrolling may present future buffer
-insertions momentarily unfontified. However, since fontification does not
-occur during scrolling after the buffer is first fontified, scrolling will
-become faster. (But, since contextual changes continually occur, such a value
-makes little sense if `lazy-lock-defer-contextually' is non-nil.)
-
-The value of this variable is used when Lazy Lock mode is turned on.")
-
-(defvar lazy-lock-defer-contextually 'syntax-driven
- "*If non-nil, means deferred fontification should be syntactically true.
-If nil, means deferred fontification occurs only on those lines modified. This
-means where modification on a line causes syntactic change on subsequent lines,
-those subsequent lines are not refontified to reflect their new context.
-If t, means deferred fontification occurs on those lines modified and all
-subsequent lines. This means those subsequent lines are refontified to reflect
-their new syntactic context, either immediately or when scrolling into them.
-If any other value, e.g., `syntax-driven', means deferred syntactically true
-fontification occurs only if syntactic fontification is performed using the
-buffer mode's syntax table, i.e., only if `font-lock-keywords-only' is nil.
-
-The value of this variable is used when Lazy Lock mode is turned on.")
-
-(defvar lazy-lock-defer-time
- (if (featurep 'lisp-float-type) (/ (float 1) (float 3)) 1)
- "*Time in seconds to delay before beginning deferred fontification.
-Deferred fontification occurs if there is no input within this time.
-If nil, means fontification is never deferred, regardless of the values of the
-variables `lazy-lock-defer-on-the-fly', `lazy-lock-defer-on-scrolling' and
-`lazy-lock-defer-contextually'.
-
-The value of this variable is used when Lazy Lock mode is turned on.")
-
-(defvar lazy-lock-stealth-time 30
- "*Time in seconds to delay before beginning stealth fontification.
-Stealth fontification occurs if there is no input within this time.
-If nil, means stealth fontification is never performed.
-
-The value of this variable is used when Lazy Lock mode is turned on.")
-
-(defvar lazy-lock-stealth-lines (if font-lock-maximum-decoration 100 250)
- "*Maximum size of a chunk of stealth fontification.
-Each iteration of stealth fontification can fontify this number of lines.
-To speed up input response during stealth fontification, at the cost of stealth
-taking longer to fontify, you could reduce the value of this variable.")
-
-(defvar lazy-lock-stealth-load
- (when (condition-case nil (load-average) (error)) 200)
- "*Load in percentage above which stealth fontification is suspended.
-Stealth fontification pauses when the system short-term load average (as
-returned by the function `load-average' if supported) goes above this level,
-thus reducing the demand that stealth fontification makes on the system.
-If nil, means stealth fontification is never suspended.
-To reduce machine load during stealth fontification, at the cost of stealth
-taking longer to fontify, you could reduce the value of this variable.
-See also `lazy-lock-stealth-nice'.")
-
-(defvar lazy-lock-stealth-nice
- (if (featurep 'lisp-float-type) (/ (float 1) (float 8)) 1)
- "*Time in seconds to pause between chunks of stealth fontification.
-Each iteration of stealth fontification is separated by this amount of time,
-thus reducing the demand that stealth fontification makes on the system.
-If nil, means stealth fontification is never paused.
-To reduce machine load during stealth fontification, at the cost of stealth
-taking longer to fontify, you could increase the value of this variable.
-See also `lazy-lock-stealth-load'.")
-
-(defvar lazy-lock-stealth-verbose
- (when (featurep 'lisp-float-type)
- (and font-lock-verbose (not lazy-lock-defer-contextually)))
- "*If non-nil, means stealth fontification should show status messages.")
-
-;; User Functions:
-
-;;;###autoload
-(defun lazy-lock-mode (&optional arg)
- "Toggle Lazy Lock mode.
-With arg, turn Lazy Lock mode on if and only if arg is positive. Enable it
-automatically in your `~/.emacs' by:
-
- (setq font-lock-support-mode 'lazy-lock-mode)
-
-When Lazy Lock mode is enabled, fontification can be lazy in a number of ways:
-
-- Demand-driven buffer fontification if `lazy-lock-minimum-size' is non-nil.
- This means initial fontification does not occur if the buffer is greater than
- `lazy-lock-minimum-size' characters in length. Instead, fontification occurs
- when necessary, such as when scrolling through the buffer would otherwise
- reveal unfontified areas. This is useful if buffer fontification is too slow
- for large buffers.
-
-- Deferred scroll fontification if `lazy-lock-defer-on-scrolling' is non-nil.
- This means demand-driven fontification does not occur as you scroll.
- Instead, fontification is deferred until after `lazy-lock-defer-time' seconds
- of Emacs idle time, while Emacs remains idle. This is useful if
- fontification is too slow to keep up with scrolling.
-
-- Deferred on-the-fly fontification if `lazy-lock-defer-on-the-fly' is non-nil.
- This means on-the-fly fontification does not occur as you type. Instead,
- fontification is deferred until after `lazy-lock-defer-time' seconds of Emacs
- idle time, while Emacs remains idle. This is useful if fontification is too
- slow to keep up with your typing.
-
-- Deferred context fontification if `lazy-lock-defer-contextually' is non-nil.
- This means fontification updates the buffer corresponding to true syntactic
- context, after `lazy-lock-defer-time' seconds of Emacs idle time, while Emacs
- remains idle. Otherwise, fontification occurs on modified lines only, and
- subsequent lines can remain fontified corresponding to previous syntactic
- contexts. This is useful where strings or comments span lines.
-
-- Stealthy buffer fontification if `lazy-lock-stealth-time' is non-nil.
- This means remaining unfontified areas of buffers are fontified if Emacs has
- been idle for `lazy-lock-stealth-time' seconds, while Emacs remains idle.
- This is useful if any buffer has any deferred fontification.
-
-Basic Font Lock mode on-the-fly fontification behaviour fontifies modified
-lines only. Thus, if `lazy-lock-defer-contextually' is non-nil, Lazy Lock mode
-on-the-fly fontification may fontify differently, albeit correctly. In any
-event, to refontify some lines you can use \\[font-lock-fontify-block].
-
-Stealth fontification only occurs while the system remains unloaded.
-If the system load rises above `lazy-lock-stealth-load' percent, stealth
-fontification is suspended. Stealth fontification intensity is controlled via
-the variable `lazy-lock-stealth-nice' and `lazy-lock-stealth-lines', and
-verbosity is controlled via the variable `lazy-lock-stealth-verbose'."
- (interactive "P")
- (let* ((was-on lazy-lock-mode)
- (now-on (unless (memq 'lazy-lock-mode font-lock-inhibit-thing-lock)
- (if arg (> (prefix-numeric-value arg) 0) (not was-on)))))
- (cond ((and now-on (not font-lock-mode))
- ;; Turned on `lazy-lock-mode' rather than `font-lock-mode'.
- (let ((font-lock-support-mode 'lazy-lock-mode))
- (font-lock-mode t)))
- (now-on
- ;; Turn ourselves on.
- (set (make-local-variable 'lazy-lock-mode) t)
- (lazy-lock-install))
- (was-on
- ;; Turn ourselves off.
- (set (make-local-variable 'lazy-lock-mode) nil)
- (lazy-lock-unstall)))))
-
-;;;###autoload
-(defun turn-on-lazy-lock ()
- "Unconditionally turn on Lazy Lock mode."
- (lazy-lock-mode t))
-
-(defun lazy-lock-install ()
- (let ((min-size (font-lock-value-in-major-mode lazy-lock-minimum-size))
- (defer-change (and lazy-lock-defer-time lazy-lock-defer-on-the-fly))
- (defer-scroll (and lazy-lock-defer-time lazy-lock-defer-on-scrolling))
- (defer-context (and lazy-lock-defer-time lazy-lock-defer-contextually
- (or (eq lazy-lock-defer-contextually t)
- (null font-lock-keywords-only)))))
- ;;
- ;; Tell Font Lock whether Lazy Lock will do fontification.
- (make-local-variable 'font-lock-fontified)
- (setq font-lock-fontified (and min-size (>= (buffer-size) min-size)))
- ;;
- ;; Add the text properties and fontify.
- (if (not font-lock-fontified)
- (lazy-lock-after-fontify-buffer)
- ;; Make sure we fontify in any existing windows showing the buffer.
- (let ((windows (get-buffer-window-list (current-buffer) 'nomini t)))
- (lazy-lock-after-unfontify-buffer)
- (while windows
- (lazy-lock-fontify-conservatively (car windows))
- (setq windows (cdr windows)))))
- ;;
- ;; Add the fontification hooks.
- (lazy-lock-install-hooks
- font-lock-fontified
- (cond ((eq (car-safe defer-change) 'not)
- (not (memq major-mode (cdr defer-change))))
- ((listp defer-change)
- (memq major-mode defer-change))
- (t
- defer-change))
- (eq defer-scroll t)
- defer-context)
- ;;
- ;; Add the fontification timers.
- (lazy-lock-install-timers
- (if (or defer-change defer-scroll defer-context) lazy-lock-defer-time)
- lazy-lock-stealth-time)))
-
-(defun lazy-lock-install-hooks (fontifying
- defer-change defer-scroll defer-context)
- ;;
- ;; Add hook if lazy-lock.el is fontifying on scrolling or is deferring.
- (when (or fontifying defer-change defer-scroll defer-context)
- (make-local-hook 'window-scroll-functions)
- (add-hook 'window-scroll-functions (if defer-scroll
- 'lazy-lock-defer-after-scroll
- 'lazy-lock-fontify-after-scroll)
- nil t))
- ;;
- ;; Add hook if lazy-lock.el is fontifying and is not deferring changes.
- (when (and fontifying (not defer-change) (not defer-context))
- (make-local-hook 'before-change-functions)
- (add-hook 'before-change-functions 'lazy-lock-arrange-before-change nil t))
- ;;
- ;; Replace Font Lock mode hook.
- (remove-hook 'after-change-functions 'font-lock-after-change-function t)
- (add-hook 'after-change-functions
- (cond ((and defer-change defer-context)
- 'lazy-lock-defer-rest-after-change)
- (defer-change
- 'lazy-lock-defer-line-after-change)
- (defer-context
- 'lazy-lock-fontify-rest-after-change)
- (t
- 'lazy-lock-fontify-line-after-change))
- nil t)
- ;;
- ;; Add package-specific hook.
- (make-local-hook 'outline-view-change-hook)
- (add-hook 'outline-view-change-hook 'lazy-lock-fontify-after-outline nil t))
-
-(defun lazy-lock-install-timers (dtime stime)
- ;; Schedule or re-schedule the deferral and stealth timers.
- ;; The layout of `lazy-lock-timers' is:
- ;; ((DEFER-TIME . DEFER-TIMER) (STEALTH-TIME . STEALTH-TIMER)
- ;; If an idle timeout has changed, cancel the existing idle timer (if there
- ;; is one) and schedule a new one (if the new idle timeout is non-nil).
- (unless (eq dtime (car (car lazy-lock-timers)))
- (let ((defer (car lazy-lock-timers)))
- (when (cdr defer)
- (cancel-timer (cdr defer)))
- (setcar lazy-lock-timers (cons dtime (and dtime
- (run-with-idle-timer dtime t 'lazy-lock-fontify-after-defer))))))
- (unless (eq stime (car (cdr lazy-lock-timers)))
- (let ((stealth (cdr lazy-lock-timers)))
- (when (cdr stealth)
- (cancel-timer (cdr stealth)))
- (setcdr lazy-lock-timers (cons stime (and stime
- (run-with-idle-timer stime t 'lazy-lock-fontify-after-idle)))))))
-
-(defun lazy-lock-unstall ()
- ;;
- ;; If Font Lock mode is still enabled, make sure that the buffer is
- ;; fontified, and reinstall its hook. We must do this first.
- (when font-lock-mode
- (when (lazy-lock-unfontified-p)
- (let ((verbose (if (numberp font-lock-verbose)
- (> (buffer-size) font-lock-verbose)
- font-lock-verbose)))
- (if verbose (message "Fontifying %s..." (buffer-name)))
- ;; Make sure we fontify etc. in the whole buffer.
- (save-restriction
- (widen)
- (lazy-lock-fontify-region (point-min) (point-max)))
- (if verbose (message "Fontifying %s...%s" (buffer-name)
- (if (lazy-lock-unfontified-p) "quit" "done")))))
- (add-hook 'after-change-functions 'font-lock-after-change-function nil t))
- ;;
- ;; Remove the text properties.
- (lazy-lock-after-unfontify-buffer)
- ;;
- ;; Remove the fontification hooks.
- (remove-hook 'window-scroll-functions 'lazy-lock-fontify-after-scroll t)
- (remove-hook 'window-scroll-functions 'lazy-lock-defer-after-scroll t)
- (remove-hook 'before-change-functions 'lazy-lock-arrange-before-change t)
- (remove-hook 'after-change-functions 'lazy-lock-fontify-line-after-change t)
- (remove-hook 'after-change-functions 'lazy-lock-fontify-rest-after-change t)
- (remove-hook 'after-change-functions 'lazy-lock-defer-line-after-change t)
- (remove-hook 'after-change-functions 'lazy-lock-defer-rest-after-change t)
- (remove-hook 'outline-view-change-hook 'lazy-lock-fontify-after-outline t))
-
-;; Hook functions.
-
-;; Lazy Lock mode intervenes when (1) a previously invisible buffer region
-;; becomes visible, i.e., for demand- or defer-driven on-the-scroll
-;; fontification, (2) a buffer modification occurs, i.e., for defer-driven
-;; on-the-fly fontification, (3) Emacs becomes idle, i.e., for fontification of
-;; deferred fontification and stealth fontification, and (4) other special
-;; occasions.
-
-;; 1. There are three ways whereby this can happen.
-;;
-;; (a) Scrolling the window, either explicitly (e.g., `scroll-up') or
-;; implicitly (e.g., `search-forward'). Here, `window-start' changes.
-;; Fontification occurs by adding `lazy-lock-fontify-after-scroll' (for
-;; demand-driven fontification) or `lazy-lock-defer-after-scroll' (for
-;; defer-driven fontification) to the hook `window-scroll-functions'.
-
-(defun lazy-lock-fontify-after-scroll (window window-start)
- ;; Called from `window-scroll-functions'.
- ;; Fontify WINDOW from WINDOW-START following the scroll. We cannot use
- ;; `window-end' so we work out what it would be via `vertical-motion'.
- (save-excursion
- (goto-char window-start)
- (vertical-motion (window-height window) window)
- (lazy-lock-fontify-region window-start (point)))
- ;; A prior deletion that did not cause scrolling, followed by a scroll, would
- ;; result in an unnecessary trigger after this if we did not cancel it now.
- (set-window-redisplay-end-trigger window nil))
-
-(defun lazy-lock-defer-after-scroll (window window-start)
- ;; Called from `window-scroll-functions'.
- ;; Defer fontification following the scroll. Save the current buffer so that
- ;; we subsequently fontify in all windows showing the buffer.
- (unless (memq (current-buffer) lazy-lock-buffers)
- (push (current-buffer) lazy-lock-buffers))
- ;; A prior deletion that did not cause scrolling, followed by a scroll, would
- ;; result in an unnecessary trigger after this if we did not cancel it now.
- (set-window-redisplay-end-trigger window nil))
-
-;; (b) Resizing the window, either explicitly (e.g., `enlarge-window') or
-;; implicitly (e.g., `delete-other-windows'). Here, `window-end' changes.
-;; Fontification occurs by adding `lazy-lock-fontify-after-resize' to the
-;; hook `window-size-change-functions'.
-
-(defun lazy-lock-fontify-after-resize (frame)
- ;; Called from `window-size-change-functions'.
- ;; Fontify windows in FRAME following the resize. We cannot use
- ;; `window-start' or `window-end' so we fontify conservatively.
- (save-excursion
- (save-selected-window
- (select-frame frame)
- (walk-windows (function (lambda (window)
- (set-buffer (window-buffer window))
- (when lazy-lock-mode
- (lazy-lock-fontify-conservatively window))
- (set-window-redisplay-end-trigger window nil)))
- 'nomini frame))))
-
-;; (c) Deletion in the buffer. Here, a `window-end' marker can become visible.
-;; Fontification occurs by adding `lazy-lock-arrange-before-change' to
-;; `before-change-functions' and `lazy-lock-fontify-after-trigger' to the
-;; hook `redisplay-end-trigger-functions'. Before every deletion, the
-;; marker `window-redisplay-end-trigger' position is set to the soon-to-be
-;; changed `window-end' position. If the marker becomes visible,
-;; `lazy-lock-fontify-after-trigger' gets called. Ouch. Note that we only
-;; have to deal with this eventuality if there is no on-the-fly deferral.
-
-(defun lazy-lock-arrange-before-change (beg end)
- ;; Called from `before-change-functions'.
- ;; Arrange that if text becomes visible it will be fontified (if a deletion
- ;; is pending, text might become visible at the bottom).
- (unless (eq beg end)
- (let ((windows (get-buffer-window-list (current-buffer) 'nomini t)) window)
- (while windows
- (setq window (car windows))
- (unless (markerp (window-redisplay-end-trigger window))
- (set-window-redisplay-end-trigger window (make-marker)))
- (set-marker (window-redisplay-end-trigger window) (window-end window))
- (setq windows (cdr windows))))))
-
-(defun lazy-lock-fontify-after-trigger (window trigger-point)
- ;; Called from `redisplay-end-trigger-functions'.
- ;; Fontify WINDOW from TRIGGER-POINT. We cannot use `window-end' so we work
- ;; out what it would be via `vertical-motion'.
- ;; We could probably just use `lazy-lock-fontify-after-scroll' without loss:
- ;; (lazy-lock-fontify-after-scroll window (window-start window))
- (save-excursion
- (goto-char (window-start window))
- (vertical-motion (window-height window) window)
- (lazy-lock-fontify-region trigger-point (point))))
-
-;; 2. Modified text must be marked as unfontified so it can be identified and
-;; fontified later when Emacs is idle. Deferral occurs by adding one of
-;; `lazy-lock-fontify-*-after-change' (for on-the-fly fontification) or
-;; `lazy-lock-defer-*-after-change' (for deferred fontification) to the
-;; hook `after-change-functions'.
-
-(defalias 'lazy-lock-fontify-line-after-change
- ;; Called from `after-change-functions'.
- ;; Fontify the current change.
- 'font-lock-after-change-function)
-
-(defun lazy-lock-fontify-rest-after-change (beg end old-len)
- ;; Called from `after-change-functions'.
- ;; Fontify the current change and defer fontification of the rest of the
- ;; buffer. Save the current buffer so that we subsequently fontify in all
- ;; windows showing the buffer.
- (lazy-lock-fontify-line-after-change beg end old-len)
- (save-buffer-state nil
- (unless (memq (current-buffer) lazy-lock-buffers)
- (push (current-buffer) lazy-lock-buffers))
- (remove-text-properties end (point-max) '(lazy-lock nil))))
-
-(defun lazy-lock-defer-line-after-change (beg end old-len)
- ;; Called from `after-change-functions'.
- ;; Defer fontification of the current change. Save the current buffer so
- ;; that we subsequently fontify in all windows showing the buffer.
- (save-buffer-state nil
- (unless (memq (current-buffer) lazy-lock-buffers)
- (push (current-buffer) lazy-lock-buffers))
- (remove-text-properties (max (1- beg) (point-min))
- (min (1+ end) (point-max))
- '(lazy-lock nil))))
-
-(defun lazy-lock-defer-rest-after-change (beg end old-len)
- ;; Called from `after-change-functions'.
- ;; Defer fontification of the rest of the buffer. Save the current buffer so
- ;; that we subsequently fontify in all windows showing the buffer.
- (save-buffer-state nil
- (unless (memq (current-buffer) lazy-lock-buffers)
- (push (current-buffer) lazy-lock-buffers))
- (remove-text-properties (max (1- beg) (point-min))
- (point-max)
- '(lazy-lock nil))))
-
-;; 3. Deferred fontification and stealth fontification are done from these two
-;; functions. They are set up as Idle Timers.
-
-(defun lazy-lock-fontify-after-defer ()
- ;; Called from `timer-idle-list'.
- ;; Fontify all windows where deferral has occurred for its buffer.
- (while (and lazy-lock-buffers (not (input-pending-p)))
- (let ((windows (get-buffer-window-list (car lazy-lock-buffers) 'nomini t)))
- (while windows
- (lazy-lock-fontify-window (car windows))
- (setq windows (cdr windows)))
- (setq lazy-lock-buffers (cdr lazy-lock-buffers))))
- ;; Add hook if fontification should now be defer-driven in this buffer.
- (when (and lazy-lock-mode lazy-lock-defer-on-scrolling
- (memq 'lazy-lock-fontify-after-scroll window-scroll-functions)
- (not (or (input-pending-p) (lazy-lock-unfontified-p))))
- (remove-hook 'window-scroll-functions 'lazy-lock-fontify-after-scroll t)
- (add-hook 'window-scroll-functions 'lazy-lock-defer-after-scroll nil t)))
-
-(defun lazy-lock-fontify-after-idle ()
- ;; Called from `timer-idle-list'.
- ;; Fontify all buffers that need it, stealthily while idle.
- (unless (or executing-kbd-macro (window-minibuffer-p (selected-window)))
- ;; Loop over all buffers, fontify stealthily for each if necessary.
- (let ((buffers (buffer-list)) (continue t) message message-log-max)
- (save-excursion
- (do-while (and buffers continue)
- (set-buffer (car buffers))
- (if (not (and lazy-lock-mode (lazy-lock-unfontified-p)))
- (setq continue (not (input-pending-p)))
- ;; Fontify regions in this buffer while there is no input.
- (do-while (and (lazy-lock-unfontified-p) continue)
- (if (and lazy-lock-stealth-load
- (> (car (load-average)) lazy-lock-stealth-load))
- ;; Wait a while before continuing with the loop.
- (progn
- (when message
- (message "Fontifying stealthily...suspended")
- (setq message nil))
- (setq continue (sit-for (or lazy-lock-stealth-time 30))))
- ;; Fontify a chunk.
- (when lazy-lock-stealth-verbose
- (if message
- (message "Fontifying stealthily... %2d%% of %s"
- (lazy-lock-percent-fontified) (buffer-name))
- (message "Fontifying stealthily...")
- (setq message t)))
- (lazy-lock-fontify-chunk)
- (setq continue (sit-for (or lazy-lock-stealth-nice 0))))))
- (setq buffers (cdr buffers))))
- (when message
- (message "Fontifying stealthily...%s" (if continue "done" "quit"))))))
-
-;; 4. Special circumstances.
-
-(defun lazy-lock-fontify-after-outline ()
- ;; Called from `outline-view-change-hook'.
- ;; Fontify windows showing the current buffer, as its visibility has changed.
- ;; This is a conspiracy hack between lazy-lock.el and noutline.el.
- (let ((windows (get-buffer-window-list (current-buffer) 'nomini t)))
- (while windows
- (lazy-lock-fontify-conservatively (car windows))
- (setq windows (cdr windows)))))
-
-(defun lazy-lock-after-fontify-buffer ()
- ;; Called from `font-lock-after-fontify-buffer'.
- ;; Mark the current buffer as fontified.
- ;; This is a conspiracy hack between lazy-lock.el and font-lock.el.
- (save-buffer-state nil
- (add-text-properties (point-min) (point-max) '(lazy-lock t))))
-
-(defun lazy-lock-after-unfontify-buffer ()
- ;; Called from `font-lock-after-unfontify-buffer'.
- ;; Mark the current buffer as unfontified.
- ;; This is a conspiracy hack between lazy-lock.el and font-lock.el.
- (save-buffer-state nil
- (remove-text-properties (point-min) (point-max) '(lazy-lock nil))))
-
-;; Fontification functions.
-
-;; If packages want to ensure that some region of the buffer is fontified, they
-;; should use this function. For an example, see ps-print.el.
-(defun lazy-lock-fontify-region (beg end)
- ;; Fontify between BEG and END, where necessary, in the current buffer.
- (when (setq beg (text-property-any beg end 'lazy-lock nil))
- (save-excursion
- (save-match-data
- (save-buffer-state
- ;; Ensure syntactic fontification is always correct.
- (font-lock-beginning-of-syntax-function next)
- ;; Find successive unfontified regions between BEG and END.
- (condition-case data
- (do-while beg
- (setq next (or (text-property-any beg end 'lazy-lock t) end))
- ;; Make sure the region end points are at beginning of line.
- (goto-char beg)
- (unless (bolp)
- (beginning-of-line)
- (setq beg (point)))
- (goto-char next)
- (unless (bolp)
- (forward-line)
- (setq next (point)))
- ;; Fontify the region, then flag it as fontified.
- (font-lock-fontify-region beg next)
- (add-text-properties beg next '(lazy-lock t))
- (setq beg (text-property-any next end 'lazy-lock nil)))
- ((error quit) (message "Fontifying region...%s" data))))))))
-
-(defun lazy-lock-fontify-chunk ()
- ;; Fontify the nearest chunk, for stealth, in the current buffer.
- (save-excursion
- (save-restriction
- (widen)
- ;; Move to end of line in case the character at point is not fontified.
- (end-of-line)
- ;; Find where the previous, and next, unfontified regions end, and begin.
- (let ((prev (previous-single-property-change (point) 'lazy-lock))
- (next (text-property-any (point) (point-max) 'lazy-lock nil)))
- ;; Fontify from the nearest unfontified position.
- (if (or (null prev) (and next (< (- next (point)) (- (point) prev))))
- ;; The next, or neither, region is the nearest not fontified.
- (lazy-lock-fontify-region
- (progn (goto-char (or next (point-min)))
- (beginning-of-line)
- (point))
- (progn (goto-char (or next (point-min)))
- (forward-line lazy-lock-stealth-lines)
- (point)))
- ;; The previous region is the nearest not fontified.
- (lazy-lock-fontify-region
- (progn (goto-char prev)
- (forward-line (- lazy-lock-stealth-lines))
- (point))
- (progn (goto-char prev)
- (forward-line)
- (point))))))))
-
-(defun lazy-lock-fontify-window (window)
- ;; Fontify in WINDOW between `window-start' and `window-end'.
- ;; We can only do this when we can use `window-start' and `window-end'.
- (with-current-buffer (window-buffer window)
- (lazy-lock-fontify-region (window-start window) (window-end window))))
-
-(defun lazy-lock-fontify-conservatively (window)
- ;; Fontify in WINDOW conservatively around point.
- ;; Where we cannot use `window-start' and `window-end' we do `window-height'
- ;; lines around point. That way we guarantee to have done enough.
- (with-current-buffer (window-buffer window)
- (lazy-lock-fontify-region
- (save-excursion
- (vertical-motion (- (window-height window)) window) (point))
- (save-excursion
- (vertical-motion (window-height window) window) (point)))))
-
-(defun lazy-lock-unfontified-p ()
- ;; Return non-nil if there is anywhere still to be fontified.
- (save-restriction
- (widen)
- (text-property-any (point-min) (point-max) 'lazy-lock nil)))
-
-(defun lazy-lock-percent-fontified ()
- ;; Return the percentage (of characters) of the buffer that are fontified.
- (save-restriction
- (widen)
- (let ((beg (point-min)) (size 0) next)
- ;; Find where the next fontified region begins.
- (while (setq beg (text-property-any beg (point-max) 'lazy-lock t))
- (setq next (or (text-property-any beg (point-max) 'lazy-lock nil)
- (point-max)))
- (incf size (- next beg))
- (setq beg next))
- ;; Float because using integer multiplication will frequently overflow.
- (truncate (* (/ (float size) (point-max)) 100)))))
-
-;; Version dependent workarounds and fixes.
-
-(when (if (save-match-data (string-match "Lucid\\|XEmacs" (emacs-version)))
- nil
- (and (= emacs-major-version 19) (= emacs-minor-version 30)))
- ;;
- ;; We use `post-command-idle-hook' for deferral and stealth. Oh Lordy.
- (defun lazy-lock-install-timers (foo bar)
- (add-hook 'post-command-idle-hook 'lazy-lock-fontify-post-command t)
- (add-hook 'post-command-idle-hook 'lazy-lock-fontify-post-idle t)
- (add-to-list 'lazy-lock-install (current-buffer))
- (add-hook 'post-command-hook 'lazy-lock-fontify-after-install))
- (defun lazy-lock-fontify-post-command ()
- (and lazy-lock-buffers (not executing-kbd-macro)
- (progn
- (and deactivate-mark (deactivate-mark))
- (sit-for
- (or (cdr-safe lazy-lock-defer-time) lazy-lock-defer-time 0)))
- (lazy-lock-fontify-after-defer)))
- (defun lazy-lock-fontify-post-idle ()
- (and lazy-lock-stealth-time (not executing-kbd-macro)
- (not (window-minibuffer-p (selected-window)))
- (progn
- (and deactivate-mark (deactivate-mark))
- (sit-for lazy-lock-stealth-time))
- (lazy-lock-fontify-after-idle)))
- ;;
- ;; Simulate running of `window-scroll-functions' in `set-window-buffer'.
- (defvar lazy-lock-install nil)
- (defun lazy-lock-fontify-after-install ()
- (remove-hook 'post-command-hook 'lazy-lock-fontify-after-install)
- (while lazy-lock-install
- (mapcar 'lazy-lock-fontify-conservatively
- (get-buffer-window-list (pop lazy-lock-install) 'nomini t)))))
-
-(when (consp lazy-lock-defer-time)
- ;;
- ;; In 2.06.04 and below, `lazy-lock-defer-time' could specify modes and time.
- (with-output-to-temp-buffer "*Help*"
- (princ "The value of the variable `lazy-lock-defer-time' was\n ")
- (princ lazy-lock-defer-time)
- (princ "\n")
- (princ "This variable cannot now be a list of modes and time, ")
- (princ "so instead use the forms:\n")
- (princ " (setq lazy-lock-defer-time ")
- (princ (cdr lazy-lock-defer-time))
- (princ ")\n")
- (princ " (setq lazy-lock-defer-on-the-fly '")
- (princ (car lazy-lock-defer-time))
- (princ ")\n")
- (princ "in your ~/.emacs. ")
- (princ "The above forms have been evaluated for this editor session,\n")
- (princ "but you should change your ~/.emacs now."))
- (setq lazy-lock-defer-on-the-fly (car lazy-lock-defer-time)
- lazy-lock-defer-time (cdr lazy-lock-defer-time)))
-
-(when (boundp 'lazy-lock-defer-driven)
- ;;
- ;; In 2.06.04 and below, `lazy-lock-defer-driven' was the variable name.
- (with-output-to-temp-buffer "*Help*"
- (princ "The value of the variable `lazy-lock-defer-driven' is set to ")
- (if (memq lazy-lock-defer-driven '(nil t))
- (princ lazy-lock-defer-driven)
- (princ "`")
- (princ lazy-lock-defer-driven)
- (princ "'"))
- (princ ".\n")
- (princ "This variable is now called `lazy-lock-defer-on-scrolling',\n")
- (princ "so instead use the form:\n")
- (princ " (setq lazy-lock-defer-on-scrolling ")
- (unless (memq lazy-lock-defer-driven '(nil t))
- (princ "'"))
- (princ lazy-lock-defer-driven)
- (princ ")\n")
- (princ "in your ~/.emacs. ")
- (princ "The above form has been evaluated for this editor session,\n")
- (princ "but you should change your ~/.emacs now."))
- (setq lazy-lock-defer-on-scrolling lazy-lock-defer-driven))
-
-;; Possibly absent.
-
-(unless (boundp 'font-lock-inhibit-thing-lock)
- ;; Font Lock mode uses this to direct Lazy and Fast Lock modes to stay off.
- (defvar font-lock-inhibit-thing-lock nil
- "List of Font Lock mode related modes that should not be turned on."))
-
-(unless (fboundp 'font-lock-value-in-major-mode)
- (defun font-lock-value-in-major-mode (alist)
- ;; Return value in ALIST for `major-mode'.
- (if (consp alist)
- (cdr (or (assq major-mode alist) (assq t alist)))
- alist)))
-
-(unless (fboundp 'get-buffer-window-list)
- ;; We use this to get all windows showing a buffer we have to fontify.
- (defun get-buffer-window-list (buffer &optional minibuf frame)
- "Return windows currently displaying BUFFER, or nil if none."
- (let ((buffer (if (bufferp buffer) buffer (get-buffer buffer))) windows)
- (walk-windows (function (lambda (window)
- (when (eq (window-buffer window) buffer)
- (push window windows))))
- minibuf frame)
- windows)))
-
-;; Install ourselves:
-
-(add-hook 'window-size-change-functions 'lazy-lock-fontify-after-resize)
-(add-hook 'redisplay-end-trigger-functions 'lazy-lock-fontify-after-trigger)
-
-(unless (assq 'lazy-lock-mode minor-mode-alist)
- (setq minor-mode-alist (append minor-mode-alist '((lazy-lock-mode nil)))))
-
-;; Provide ourselves:
-
-(provide 'lazy-lock)
-
-;;; lazy-lock.el ends here
diff --git a/lisp/ledit.el b/lisp/ledit.el
deleted file mode 100644
index f106abfe08b..00000000000
--- a/lisp/ledit.el
+++ /dev/null
@@ -1,155 +0,0 @@
-;;; ledit.el --- Emacs side of ledit interface
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keyword: languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This is a major mode for editing Liszt. See etc/LEDIT for details.
-
-;;; Code:
-
-;;; To do:
-;;; o lisp -> emacs side of things (grind-definition and find-definition)
-
-(defvar ledit-mode-map nil)
-
-(defconst ledit-zap-file (concat "/tmp/" (user-login-name) ".l1")
- "File name for data sent to Lisp by Ledit.")
-(defconst ledit-read-file (concat "/tmp/" (user-login-name) ".l2")
- "File name for data sent to Ledit by Lisp.")
-(defconst ledit-compile-file
- (concat "/tmp/" (user-login-name) ".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.")
-
-;;;###autoload
-(defconst ledit-save-files t "\
-*Non-nil means Ledit should save files before transferring to Lisp.")
-;;;###autoload
-(defconst ledit-go-to-lisp-string "%?lisp" "\
-*Shell commands to execute to resume Lisp job.")
-;;;###autoload
-(defconst ledit-go-to-liszt-string "%?liszt" "\
-*Shell commands to execute to resume Lisp compiler job.")
-
-(defun ledit-save-defun ()
- "Save the current defun in the ledit buffer"
- (interactive)
- (save-excursion
- (end-of-defun)
- (let ((end (point)))
- (beginning-of-defun)
- (append-to-buffer ledit-buffer (point) end))
- (message "Current defun saved for Lisp")))
-
-(defun ledit-save-region (beg end)
- "Save the current region in the ledit buffer"
- (interactive "r")
- (append-to-buffer ledit-buffer beg end)
- (message "Region saved for Lisp"))
-
-(defun ledit-zap-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."
- (interactive)
- (ledit-save-defun)
- (ledit-go-to-liszt))
-
-(defun ledit-zap-region-to-lisp (beg end)
- "Carry the current region to Lisp."
- (interactive "r")
- (ledit-save-region beg end)
- (ledit-go-to-lisp))
-
-(defun ledit-go-to-lisp ()
- "Suspend Emacs and restart a waiting Lisp job."
- (interactive)
- (if ledit-save-files
- (save-some-buffers))
- (if (get-buffer ledit-buffer)
- (save-excursion
- (set-buffer ledit-buffer)
- (goto-char (point-min))
- (write-region (point-min) (point-max) ledit-zap-file)
- (erase-buffer)))
- (suspend-emacs ledit-go-to-lisp-string)
- (load ledit-read-file t t))
-
-(defun ledit-go-to-liszt ()
- "Suspend Emacs and restart a waiting Liszt job."
- (interactive)
- (if ledit-save-files
- (save-some-buffers))
- (if (get-buffer ledit-buffer)
- (save-excursion
- (set-buffer ledit-buffer)
- (goto-char (point-min))
- (insert "(declare (macros t))\n")
- (write-region (point-min) (point-max) ledit-compile-file)
- (erase-buffer)))
- (suspend-emacs ledit-go-to-liszt-string)
- (load ledit-read-file t t))
-
-(defun ledit-setup ()
- "Set up key bindings for the Lisp/Emacs interface."
- (if (not ledit-mode-map)
- (progn (setq ledit-mode-map (nconc (make-sparse-keymap)
- shared-lisp-mode-map))))
- (define-key ledit-mode-map "\e\^d" 'ledit-save-defun)
- (define-key ledit-mode-map "\e\^r" 'ledit-save-region)
- (define-key ledit-mode-map "\^xz" 'ledit-go-to-lisp)
- (define-key ledit-mode-map "\e\^c" 'ledit-go-to-liszt))
-
-(ledit-setup)
-
-;;;###autoload
-(defun ledit-mode ()
- "\\<ledit-mode-map>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
- 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
- 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)"
- (interactive)
- (lisp-mode)
- (ledit-from-lisp-mode))
-
-;;;###autoload
-(defun ledit-from-lisp-mode ()
- (use-local-map ledit-mode-map)
- (setq mode-name "Ledit")
- (setq major-mode 'ledit-mode)
- (run-hooks 'ledit-mode-hook))
-
-;;; ledit.el ends here
diff --git a/lisp/loadhist.el b/lisp/loadhist.el
deleted file mode 100644
index 726ae22e8da..00000000000
--- a/lisp/loadhist.el
+++ /dev/null
@@ -1,149 +0,0 @@
-;;; loadhist.el --- lisp functions for working with feature groups
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
-;; Version: 1.0
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; These functions exploit the load-history system variable.
-;; Entry points include `unload-feature', `symbol-file', and `feature-file'.
-
-;;; Code:
-
-(defun symbol-file (sym)
- "Return the input source from which SYM was loaded.
-This is a file name, or nil if the source was a buffer with no associated file."
- (catch 'foundit
- (mapcar
- (function (lambda (x) (if (memq sym (cdr x)) (throw 'foundit (car x)))))
- load-history)
- nil))
-
-(defun feature-symbols (feature)
- "Return the file and list of symbols associated with a given FEATURE."
- (catch 'foundit
- (mapcar
- (function (lambda (x)
- (if (member (cons 'provide feature) (cdr x))
- (throw 'foundit x))))
- load-history)
- nil))
-
-(defun feature-file (feature)
- "Return the file name from which a given FEATURE was loaded.
-Actually, return the load argument, if any; this is sometimes the name of a
-Lisp file without an extension. If the feature came from an eval-buffer on
-a buffer with no associated file, or an eval-region, return nil."
- (if (not (featurep feature))
- (error "%s is not a currently loaded feature" (symbol-name feature))
- (car (feature-symbols feature))))
-
-(defun file-provides (file)
- "Return the list of features provided by FILE."
- (let ((symbols (cdr (assoc file load-history))) (provides nil))
- (mapcar
- (function (lambda (x)
- (if (and (consp x) (eq (car x) 'provide))
- (setq provides (cons (cdr x) provides)))))
- symbols)
- provides
- ))
-
-(defun file-requires (file)
- "Return the list of features required by FILE."
- (let ((symbols (cdr (assoc file load-history))) (requires nil))
- (mapcar
- (function (lambda (x)
- (if (and (consp x) (eq (car x) 'require))
- (setq requires (cons (cdr x) requires)))))
- symbols)
- requires
- ))
-
-(defun file-set-intersect (p q)
- ;; Return the set intersection of two lists
- (let ((ret nil))
- (mapcar
- (function (lambda (x) (if (memq x q) (setq ret (cons x ret)))))
- p)
- ret
- ))
-
-(defun file-dependents (file)
- "Return the list of loaded libraries that depend on FILE.
-This can include FILE itself."
- (let ((provides (file-provides file)) (dependents nil))
- (mapcar
- (function (lambda (x)
- (if (file-set-intersect provides (file-requires (car x)))
- (setq dependents (cons (car x) dependents)))))
- load-history)
- dependents
- ))
-
-(defun read-feature (prompt)
- "Read a feature name \(string\) from the minibuffer,
-prompting with PROMPT and completing from `features', and
-return the feature \(symbol\)."
- (intern (completing-read prompt
- (mapcar (function (lambda (feature)
- (list (symbol-name feature))))
- features)
- nil t)))
-
-;;;###autoload
-(defun unload-feature (feature &optional force)
- "Unload the library that provided FEATURE, restoring all its autoloads.
-If the feature is required by any other loaded code, and optional FORCE
-is nil, raise an error."
- (interactive (list (read-feature "Feature: ")))
- (if (not (featurep feature))
- (error "%s is not a currently loaded feature" (symbol-name feature)))
- (if (not force)
- (let* ((file (feature-file feature))
- (dependents (delete file (copy-sequence (file-dependents file)))))
- (if dependents
- (error "Loaded libraries %s depend on %s"
- (prin1-to-string dependents) file)
- )))
- (let* ((flist (feature-symbols feature)) (file (car flist)))
- (mapcar
- (function (lambda (x)
- (cond ((stringp x) nil)
- ((consp x)
- ;; Remove any feature names that this file provided.
- (if (eq (car x) 'provide)
- (setq features (delq (cdr x) features))))
- ((boundp x) (makunbound x))
- ((fboundp x)
- (fmakunbound x)
- (let ((aload (get x 'autoload)))
- (if aload (fset x (cons 'autoload aload))))))))
- (cdr flist))
- ;; Delete the load-history element for this file.
- (let ((elt (assoc file load-history)))
- (setq load-history (delq elt load-history)))))
-
-(provide 'loadhist)
-
-;;; loadhist.el ends here
diff --git a/lisp/loadup.el b/lisp/loadup.el
deleted file mode 100644
index 06770a7809b..00000000000
--- a/lisp/loadup.el
+++ /dev/null
@@ -1,253 +0,0 @@
-;;; loadup.el --- load up standardly loaded Lisp files for Emacs.
-
-;; Copyright (C) 1985, 1986, 1992, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This is loaded into a bare Emacs to make a dumpable one.
-
-;;; Code:
-
-(message "Using load-path %s" load-path)
-
-;;; We don't want to have any undo records in the dumped Emacs.
-(buffer-disable-undo "*scratch*")
-
-(load "subr")
-
-;; We specify .el in case someone compiled version.el by mistake.
-(load "version.el")
-
-(garbage-collect)
-(load "byte-run")
-(garbage-collect)
-(load "map-ynp")
-(garbage-collect)
-(load "bindings.el") ;Don't get confused if someone compiled this by mistake.
-(garbage-collect)
-(load "loaddefs.el") ;Don't get confused if someone compiled this by mistake.
-(garbage-collect)
-(load "simple")
-(garbage-collect)
-(load "help")
-(garbage-collect)
-(load "files")
-(garbage-collect)
-(load "format")
-(garbage-collect)
-(load "indent")
-(garbage-collect)
-(load "isearch")
-(garbage-collect)
-(load "window")
-(garbage-collect)
-(load "frame")
-(if (fboundp 'frame-face-alist)
- (progn
- (garbage-collect)
- (load "faces")
- (load "facemenu")))
-(if (fboundp 'track-mouse)
- (progn
- (garbage-collect)
- (load "mouse")
- (garbage-collect)
- (load "scroll-bar")
- (load "select")))
-(load "menu-bar")
-(garbage-collect)
-(load "paths.el") ;Don't get confused if someone compiled paths by mistake.
-(garbage-collect)
-(load "startup")
-(garbage-collect)
-(load "lisp")
-(garbage-collect)
-(load "page")
-(garbage-collect)
-(load "register")
-(garbage-collect)
-(load "paragraphs")
-(garbage-collect)
-(load "lisp-mode")
-(garbage-collect)
-(load "text-mode")
-(garbage-collect)
-(load "fill")
-(garbage-collect)
-(load "replace")
-(if (eq system-type 'vax-vms)
- (progn
- (garbage-collect)
- (load "vmsproc")))
-(garbage-collect)
-(load "abbrev")
-(garbage-collect)
-(load "buff-menu")
-(if (eq system-type 'vax-vms)
- (progn
- (garbage-collect)
- (load "vms-patch")))
-(if (eq system-type 'windows-nt)
- (progn
- (garbage-collect)
- (load "ls-lisp")
- (garbage-collect)
- (load "disp-table") ; needed to setup ibm-pc char set, see internal.el
- (garbage-collect)
- (load "dos-w32")
- (garbage-collect)
- (load "w32-fns")
- (garbage-collect)))
-(if (eq system-type 'ms-dos)
- (progn
- (load "ls-lisp")
- (garbage-collect)
- (load "dos-w32")
- (garbage-collect)
- (load "dos-fns")
- (garbage-collect)
- (load "disp-table") ; needed to setup ibm-pc char set, see internal.el
- (garbage-collect)))
-(if (fboundp 'atan) ; preload some constants and
- (progn ; floating pt. functions if
- (garbage-collect) ; we have float support.
- (load "float-sup")))
-
-(garbage-collect)
-(load "vc-hooks")
-(load "ediff-hook")
-
-;If you want additional libraries to be preloaded and their
-;doc strings kept in the DOC file rather than in core,
-;you may load them with a "site-load.el" file.
-;But you must also cause them to be scanned when the DOC file
-;is generated. For VMS, you must edit ../vms/makedoc.com.
-;For other systems, you must edit ../src/Makefile.in.
-(if (load "site-load" t)
- (garbage-collect))
-
-(if (fboundp 'x-popup-menu)
- (precompute-menubar-bindings))
-;; Turn on recording of which commands get rebound,
-;; for the sake of the next call to precompute-menubar-bindings.
-(setq define-key-rebound-commands nil)
-
-;; Determine which last version number to use
-;; based on the executables that now exist.
-(if (and (or (equal (nth 3 command-line-args) "dump")
- (equal (nth 4 command-line-args) "dump"))
- (not (eq system-type 'ms-dos)))
- (let* ((base (concat "emacs-" emacs-version "."))
- (files (file-name-all-completions base default-directory))
- (versions (mapcar (function (lambda (name)
- (string-to-int (substring name (length base)))))
- files)))
- (setq emacs-version (format "%s.%d"
- emacs-version
- (if versions
- (1+ (apply 'max versions))
- 1)))))
-
-;; Note: all compiled Lisp files loaded above this point
-;; must be among the ones parsed by make-docfile
-;; to construct DOC. Any that are not processed
-;; for DOC will not have doc strings in the dumped Emacs.
-
-(message "Finding pointers to doc strings...")
-(if (or (equal (nth 3 command-line-args) "dump")
- (equal (nth 4 command-line-args) "dump"))
- (let ((name 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)))))
- (if (memq system-type '(ms-dos windows-nt))
- (setq name (expand-file-name
- (if (fboundp 'x-create-frame) "DOC-X" "DOC") "../etc"))
- (setq name (concat (expand-file-name "../etc/DOC-") name))
- (if (file-exists-p name)
- (delete-file name))
- (copy-file (expand-file-name "../etc/DOC") name t))
- (Snarf-documentation (file-name-nondirectory name)))
- (Snarf-documentation "DOC"))
-(message "Finding pointers to doc strings...done")
-
-;Note: You can cause additional libraries to be preloaded
-;by writing a site-init.el that loads them.
-;See also "site-load" above.
-(load "site-init" t)
-(setq current-load-list nil)
-(garbage-collect)
-
-;;; At this point, we're ready to resume undo recording for scratch.
-(buffer-enable-undo "*scratch*")
-
-(if (or (equal (nth 3 command-line-args) "dump")
- (equal (nth 4 command-line-args) "dump"))
- (if (eq system-type 'vax-vms)
- (progn
- (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)))))
- (if (eq system-type 'ms-dos)
- (message "Dumping under the name emacs")
- (message "Dumping under names emacs and %s" name)))
- (condition-case ()
- (delete-file "emacs")
- (file-error nil))
- ;; We used to dump under the name xemacs, but that occasionally
- ;; confused people installing Emacs (they'd install the file
- ;; under the name `xemacs'), and it's inconsistent with every
- ;; other GNU product's build process.
- (dump-emacs "emacs" "temacs")
- (message "%d pure bytes used" pure-bytes-used)
- ;; Recompute NAME now, so that it isn't set when we dump.
- (if (not (memq system-type '(ms-dos windows-nt)))
- (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 "emacs" name t)))
- (kill-emacs)))
-
-;; Avoid error if user loads some more libraries now.
-(setq purify-flag nil)
-
-;; For machines with CANNOT_DUMP defined in config.h,
-;; this file must be loaded each time Emacs is run.
-;; So run the startup code now.
-
-(or (equal (nth 3 command-line-args) "dump")
- (equal (nth 4 command-line-args) "dump")
- (progn
- ;; Avoid loading loadup.el a second time!
- (setq command-line-args (cdr (cdr command-line-args)))
- (eval top-level)))
-
-;;; loadup.el ends here
diff --git a/lisp/locate.el b/lisp/locate.el
deleted file mode 100644
index 9084a1021bb..00000000000
--- a/lisp/locate.el
+++ /dev/null
@@ -1,365 +0,0 @@
-;; Locate.el: interface to the locate command
-
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Peter Breton <pbreton@i-kinetics.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Search a database of files and use dired commands on
-;; the result.
-;;
-
-;;;;; Building a database of files ;;;;;;;;;
-;;
-;; You can create a simple files database with a port of the Unix find command
-;; and one of the various Windows NT various scheduling utilities,
-;; for example the AT command from the NT Resource Kit, WinCron which is
-;; included with Microsoft FrontPage, or the shareware NTCron program.
-;;
-;; To set up a function which searches the files database, do something
-;; like this:
-;;
-;; (defvar locate-fcodes-file (concat my-home "/fcodes"))
-;; (defvar locate-make-command-line 'nt-locate-make-command-line)
-;;
-;; (defun nt-locate-make-command-line (arg)
-;; (cons "grep"
-;; (mapconcat 'identity
-;; (list "-i" arg locate-fcodes-file)
-;; " ")))
-;;
-;;;;;;;; ADVICE For dired-make-relative: ;;;;;;;;;
-;;
-;; For certain dired commands to work right, you should also include the
-;; following in your _emacs/.emacs:
-;;
-;; (defadvice dired-make-relative (before set-no-error activate)
-;; "For locate mode and Windows, don't return errors"
-;; (if (and (eq major-mode 'locate-mode)
-;; (memq system-type (list 'windows-nt 'ms-dos)))
-;; (ad-set-arg 2 t)
-;; ))
-;;
-;; Otherwise, dired-make-relative will give error messages like
-;; "FILENAME: not in directory tree growing at /"
-
-;;; Commentary:
-;;
-;; Locate.el provides an interface to a program which searches a
-;; database of file names. By default, this program is the GNU locate
-;; command, but it could also be the BSD-style find command, or even a
-;; user specified command.
-;;
-;; To use the BSD-style "fast find", or any other shell command of the
-;; form
-;;
-;; SHELLPROGRAM Name-to-find
-;;
-;; set the variable locate-command in your .emacs file.
-;;
-;; To use a more complicated expression, create a function which
-;; takes a string (the name to find) as input and returns a cons
-;; pair: the car should be the command to be executed, the cdr
-;; should be the arguments, concatenated into a string (including
-;; the name to find). Then do
-;;
-;; (setq locate-make-command-line 'my-locate-command-line)
-;;
-;; in your .emacs, using the name of your function in place of
-;; my-locate-command-line
-;;
-;; You should make sure that whichever command you use works correctly
-;; from a shell prompt. GNU locate and BSD find expect the file databases
-;; to either be in standard places or located via environment variables.
-;; If the latter, make sure these environment variables are set in
-;; your emacs process
-;;
-;; Locate-mode assumes that each line output from the locate-command
-;; consists exactly of a file name, possibly preceded or trailed by
-;; whitespace. If your file database has other information on the line (for
-;; example, the file size), you will need to redefine the function
-;; locate-get-file-positions to return a list consisting of the first
-;; character in the file name and the last character in the file name.
-;;
-;; To use locate-mode, simply type M-x locate and then the string
-;; you wish to find. You can use almost all of the dired commands in
-;; the resulting *Locate* buffer. It is worth noting that your commands
-;; do not, of course, affect the file database. For example, if you
-;; compress a file in the locate buffer, the actual file will be
-;; compressed, but the entry in the file database will not be
-;; affected. Consequently, the database and the filesystem will be out
-;; of sync until the next time the database is updated
-;;
-;; The command locate-with-filter keeps only lines matching a
-;; regular expression; this is often useful to constrain a big search.
-;;
-
-;;; Code:
-
-(eval-when-compile
- (require 'dired))
-
-;; Variables
-(defvar locate-command "locate"
- "*The executable program used to search a database of files.")
-
-(defvar locate-history-list nil
- "The history list used by the \\[locate] command.")
-
-(defvar locate-make-command-line 'locate-default-make-command-line
- "*Function used to create the locate command line.")
-
-(defvar locate-buffer-name "*Locate*"
- "*Name of the buffer to show results from the \\[locate] command.")
-
-(defvar locate-fcodes-file nil
- "*Database of filenames.")
-
-(defvar locate-mouse-face 'highlight
- "*Face used to highlight locate entries.")
-
-(defvar locate-header-face 'region
- "*Face used to highlight the locate header.")
-
-(defvar locate-current-filter nil)
-
-;; Functions
-
-(defun locate-default-make-command-line (search-string)
- (cons locate-command search-string))
-
-;;;### autoload
-(defun locate (search-string &optional filter)
- "Run the \\[locate] command, putting results in `*Locate*' buffer."
- (interactive
- (list (read-from-minibuffer "Locate: " nil nil
- nil 'locate-history-list)))
- (let* ((pop-up-windows 1)
- (locate-cmd-list (funcall locate-make-command-line search-string))
- (locate-cmd (car locate-cmd-list))
- (locate-cmd-args (cdr locate-cmd-list))
- (locate-proc)
- )
-
- ;; Find the Locate buffer
- (if (not (string-equal (buffer-name) locate-buffer-name))
- (switch-to-buffer-other-window locate-buffer-name))
-
- (locate-mode)
- (erase-buffer)
-
- (setq locate-current-filter filter)
-
- (call-process locate-cmd nil t nil locate-cmd-args)
- (if filter
- (locate-filter-output filter))
-
- (locate-do-setup)
- )
-)
-
-;;;### autoload
-(defun locate-with-filter (search-string filter)
- "Run the locate command with a filter."
- (interactive
- (list (read-from-minibuffer "Locate: " nil nil
- nil 'locate-history-list)
- (read-from-minibuffer "Filter: " nil nil
- nil 'grep-history)))
- (locate search-string filter))
-
-(defun locate-filter-output (filter)
- "Filter output from the locate command."
- (goto-char (point-min))
- (delete-non-matching-lines (regexp-quote filter)))
-
-(defvar locate-mode-map nil
- "Local keymap for Locate mode buffers.")
-(if locate-mode-map
- nil
-
- (require 'dired)
-
- (setq locate-mode-map (copy-keymap dired-mode-map))
-
- ;; Undefine Useless Dired Menu bars
- (define-key locate-mode-map [menu-bar Dired] 'undefined)
- (define-key locate-mode-map [menu-bar subdir] 'undefined)
-
- (define-key locate-mode-map [menu-bar mark executables] 'undefined)
- (define-key locate-mode-map [menu-bar mark directory] 'undefined)
- (define-key locate-mode-map [menu-bar mark directories] 'undefined)
- (define-key locate-mode-map [menu-bar mark symlinks] 'undefined)
-
- (define-key locate-mode-map [mouse-2] 'mouse-locate-view-file)
- (define-key locate-mode-map "\C-ct" 'locate-tags)
-
- (define-key locate-mode-map "U" 'dired-unmark-all-files-no-query)
-)
-
-;; This variable is used to indent the lines and then to search for
-;; the file name
-(defconst locate-filename-indentation 4
- "The amount of indentation for each file.")
-
-(defun locate-get-file-positions ()
- (save-excursion
- (end-of-line)
- (let ((eol (point)))
- (beginning-of-line)
-
- ;; Assumes names end at the end of the line
- (forward-char locate-filename-indentation)
- (list (point) eol))))
-
-;; From SQL-mode
-(defun current-line ()
- "Return the current line number, as an integer."
- (interactive)
- (+ (count-lines (point-min) (point))
- (if (eq (current-column) 0)
- 1
- 0)))
-
-(defun locate-get-filename ()
- (let ((pos (locate-get-file-positions))
- (lineno (current-line)))
- (and (not (eq lineno 1))
- (not (eq lineno 2))
- (buffer-substring (elt pos 0) (elt pos 1)))))
-
-(defun mouse-locate-view-file (event)
- "In Locate mode, view a file, using the mouse."
- (interactive "@e")
- (save-excursion
- (goto-char (posn-point (event-start event)))
- (view-file (locate-get-filename))))
-
-;; Define a mode for locate
-;; Default directory is set to "/" so that dired commands, which
-;; expect to be in a tree, will work properly
-(defun locate-mode ()
- "Major mode for the `*Locate*' buffer made by \\[locate]."
- (kill-all-local-variables)
- (use-local-map locate-mode-map)
- (setq major-mode 'locate-mode
- mode-name "Locate"
- default-directory "/"
- dired-subdir-alist (list (cons "/" (point-min-marker))))
- (make-local-variable 'dired-move-to-filename-regexp)
- (setq dired-move-to-filename-regexp
- (make-string locate-filename-indentation ?\ ))
- (make-local-variable 'dired-actual-switches)
- (setq dired-actual-switches "")
- (make-local-variable 'dired-permission-flags-regexp)
- (setq dired-permission-flags-regexp "^\\( \\)")
- (run-hooks 'locate-mode-hook))
-
-(defun locate-do-setup ()
- (let ((search-string (car locate-history-list)))
- (goto-char (point-min))
- (save-excursion
-
- ;; Nothing returned from locate command?
- (if (eobp)
- (progn
- (kill-buffer locate-buffer-name)
- (delete-window)
- (if locate-current-filter
- (error "Locate: no match for %s in database using filter %s"
- search-string locate-current-filter)
- (error "Locate: no match for %s in database" search-string))))
-
- (locate-insert-header search-string)
-
- (while (not (eobp))
- (insert-char ?\ locate-filename-indentation t)
- (locate-set-properties)
- (forward-line 1)))))
-
-(defun locate-set-properties ()
- (save-excursion
- (let ((pos (locate-get-file-positions)))
- (add-text-properties (elt pos 0) (elt pos 1)
- (list 'mouse-face locate-mouse-face)))))
-
-(defun locate-insert-header (search-string)
- (let ((locate-format-string "Matches for %s")
- (locate-regexp-match
- (concat " *Matches for \\(" (regexp-quote search-string) "\\)"))
- (locate-format-args (list search-string))
- )
-
- (if locate-fcodes-file
- (setq locate-format-string
- (concat locate-format-string " in %s")
- locate-regexp-match
- (concat locate-regexp-match
- " in \\("
- (regexp-quote locate-fcodes-file)
- "\\)")
- locate-format-args
- (append (list locate-fcodes-file) locate-format-args)))
-
- (if locate-current-filter
- (setq locate-format-string
- (concat locate-format-string " using filter %s")
- locate-regexp-match
- (concat locate-regexp-match
- " using filter "
- "\\("
- (regexp-quote locate-current-filter)
- "\\)")
- locate-format-args
- (append (list locate-current-filter) locate-format-args)))
-
- (setq locate-format-string
- (concat locate-format-string ": \n\n")
- locate-regexp-match
- (concat locate-regexp-match ": \n"))
-
- (insert (apply 'format locate-format-string (reverse locate-format-args)))
-
- (save-excursion
- (goto-char (point-min))
- (if (not (looking-at locate-regexp-match))
- nil
- (add-text-properties (match-beginning 1) (match-end 1)
- (list 'face locate-header-face))
- (and (match-beginning 2)
- (add-text-properties (match-beginning 2) (match-end 2)
- (list 'face locate-header-face)))
- (and (match-beginning 3)
- (add-text-properties (match-beginning 3) (match-end 3)
- (list 'face locate-header-face)))
- ))))
-
-(defun locate-tags ()
- "Visit a tags table in `*Locate*' mode."
- (interactive)
- (let ((tags-table (locate-get-filename)))
- (if (y-or-n-p (format "Visit tags table %s? " tags-table))
- (visit-tags-table tags-table)
- nil)))
-
-(provide 'locate)
-
-;;; locate.el ends here
diff --git a/lisp/lpr.el b/lisp/lpr.el
deleted file mode 100644
index 34956193642..00000000000
--- a/lisp/lpr.el
+++ /dev/null
@@ -1,188 +0,0 @@
-;;; lpr.el --- print Emacs buffer on line printer.
-
-;; Copyright (C) 1985, 1988, 1992, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: unix
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Commands to send the region or a buffer your printer. Entry points
-;; are `lpr-buffer', `print-buffer', lpr-region', or `print-region'; option
-;; variables include `lpr-switches' and `lpr-command'.
-
-;;; Code:
-
-;;;###autoload
-(defvar lpr-switches nil
- "*List of strings to pass as extra options for the printer program.
-See `lpr-command'.")
-
-(defvar lpr-add-switches (eq system-type 'berkeley-unix)
- "*Non-nil means construct -T and -J options for the printer program.
-These are made assuming that the program is `lpr';
-if you are using some other incompatible printer program,
-this variable should be nil.")
-
-;;;###autoload
-(defvar lpr-command
- (if (memq system-type '(usg-unix-v dgux hpux irix))
- "lp" "lpr")
- "*Name of program for printing a file.")
-
-;; Default is nil, because that enables us to use pr -f
-;; which is more reliable than pr with no args, which is what lpr -p does.
-(defvar lpr-headers-switches nil
- "*List of strings of options to request page headings in the printer program.
-If nil, we run `lpr-page-header-program' to make page headings
-and print the result.")
-
-(defvar print-region-function nil
- "Function to call to print the region on a printer.
-See definition of `print-region-1' for calling conventions.")
-
-(defvar lpr-page-header-program "pr"
- "*Name of program for adding page headers to a file.")
-
-(defvar lpr-page-header-switches '("-f")
- "*List of strings to use as options for the page-header-generating program.
-The variable `lpr-page-header-program' specifies the program to use.")
-
-;;;###autoload
-(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))
-
-;;;###autoload
-(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))
-
-;;;###autoload
-(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))
-
-;;;###autoload
-(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))
-
-(defun print-region-1 (start end switches page-headers)
- ;; On some MIPS system, having a space in the job name
- ;; crashes the printer demon. But using dashes looks ugly
- ;; and it seems to annoying to do for that MIPS system.
- (let ((name (concat (buffer-name) " Emacs buffer"))
- (title (concat (buffer-name) " Emacs buffer"))
- ;; On MS-DOS systems, make pipes use binary mode if the
- ;; original file is binary.
- (binary-process-input buffer-file-type)
- (binary-process-output buffer-file-type)
- (width tab-width)
- switch-string)
- (save-excursion
- (if page-headers
- (if lpr-headers-switches
- ;; It is possible to use an lpr option
- ;; to get page headers.
- (setq switches (append (if (stringp lpr-headers-switches)
- (list lpr-headers-switches)
- lpr-headers-switches)
- switches))))
- (setq switch-string
- (if switches (concat " with options "
- (mapconcat 'identity switches " "))
- ""))
- (message "Spooling%s..." switch-string)
- (if (/= tab-width 8)
- (let ((new-coords (print-region-new-buffer start end)))
- (setq start (car new-coords) end (cdr new-coords))
- (setq tab-width width)
- (save-excursion
- (goto-char end)
- (setq end (point-marker)))
- (untabify (point-min) (point-max))))
- (if page-headers
- (if lpr-headers-switches
- ;; We handled this above by modifying SWITCHES.
- nil
- ;; Run a separate program to get page headers.
- (let ((new-coords (print-region-new-buffer start end)))
- (setq start (car new-coords) end (cdr new-coords)))
- (apply 'call-process-region start end lpr-page-header-program
- t t nil
- (nconc (and lpr-add-switches
- (list "-h" title))
- lpr-page-header-switches))
- (setq start (point-min) end (point-max))))
- (apply (or print-region-function 'call-process-region)
- (nconc (list start end lpr-command
- nil nil nil)
- (nconc (and lpr-add-switches
- (list "-J" name))
- ;; These belong in pr if we are using that.
- (and lpr-add-switches lpr-headers-switches
- (list "-T" title))
- switches)))
- (if (markerp end)
- (set-marker end nil))
- (message "Spooling%s...done" switch-string))))
-
-;; This function copies the text between start and end
-;; into a new buffer, makes that buffer current.
-;; It returns the new range to print from the new current buffer
-;; as (START . END).
-
-(defun print-region-new-buffer (ostart oend)
- (if (string= (buffer-name) " *spool temp*")
- (cons ostart oend)
- (let ((oldbuf (current-buffer)))
- (set-buffer (get-buffer-create " *spool temp*"))
- (widen) (erase-buffer)
- (insert-buffer-substring oldbuf ostart oend)
- (cons (point-min) (point-max)))))
-
-(defun printify-region (begin end)
- "Turn nonprinting characters (other than TAB, LF, SPC, RET, and FF)
-in the current buffer into printable representations as control or
-hexadecimal escapes."
- (interactive "r")
- (save-excursion
- (goto-char begin)
- (let (c)
- (while (re-search-forward "[\^@-\^h\^k\^n-\^_\177-\377]" end t)
- (setq c (preceding-char))
- (delete-backward-char 1)
- (insert
- (if (< c ?\ )
- (format "\\^%c" (+ c ?@))
- (format "\\%02x" c)))))))
-
-(provide 'lpr)
-
-;;; lpr.el ends here
diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el
deleted file mode 100644
index 158414664f3..00000000000
--- a/lisp/ls-lisp.el
+++ /dev/null
@@ -1,270 +0,0 @@
-;;; ls-lisp.el --- emulate insert-directory completely in Emacs Lisp
-
-;; Copyright (C) 1992, 1994 by Sebastian Kremer <sk@thp.uni-koeln.de>
-
-;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
-;; Keywords: unix
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; INSTALLATION =======================================================
-;;
-;; Put this file into your load-path. To use it, load it
-;; with (load "ls-lisp").
-
-;; OVERVIEW ===========================================================
-
-;; This file overloads the function insert-directory to implement it
-;; directly from Emacs lisp, without running `ls' in a subprocess.
-
-;; It is useful if you cannot afford to fork Emacs on a real memory UNIX,
-;; under VMS, or if you don't have the ls program, or if you want
-;; different format from what ls offers.
-
-;; This function uses regexps instead of shell
-;; wildcards. If you enter regexps remember to double each $ sign.
-;; For example, to include files *.el, enter `.*\.el$$',
-;; resulting in the regexp `.*\.el$'.
-
-;; RESTRICTIONS =====================================================
-
-;; * many ls switches are ignored, see docstring of `insert-directory'.
-
-;; * Only numeric uid/gid
-
-;; TODO ==============================================================
-
-;; Recognize some more ls switches: R F
-
-;;; Code:
-
-;;;###autoload
-(defvar ls-lisp-support-shell-wildcards t
- "*Non-nil means file patterns are treated as shell wildcards.
-nil means they are treated as Emacs regexps (for backward compatibility).
-This variable is checked by \\[insert-directory] only when `ls-lisp.el'
-package is used.")
-
-(defun insert-directory (file &optional switches wildcard full-directory-p)
- "Insert directory listing for FILE, formatted according to SWITCHES.
-Leaves point after the inserted text.
-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', so that a full listing is expected.
-
-This version of the function comes from `ls-lisp.el'. It doesn not
-run any external programs or shells. It supports ordinary shell
-wildcards if `ls-lisp-support-shell-wildcards' variable is non-nil;
-otherwise, it interprets wildcards as regular expressions to match
-file names.
-
-Not all `ls' switches are supported. The switches that work
-are: A a c i r S s t u"
- (let ((handler (find-file-name-handler file 'insert-directory)))
- (if handler
- (funcall handler 'insert-directory file switches
- wildcard full-directory-p)
- ;; Sometimes we get ".../foo*/" as FILE. While the shell and
- ;; `ls' don't mind, we certainly do, because it makes us think
- ;; there is no wildcard, only a directory name.
- (if (and ls-lisp-support-shell-wildcards
- (string-match "[[?*]" file))
- (progn
- (or (not (eq (aref file (1- (length file))) ?/))
- (setq file (substring file 0 (1- (length file)))))
- (setq wildcard t)))
- ;; Convert SWITCHES to a list of characters.
- (setq switches (append switches nil))
- (if wildcard
- (setq wildcard
- (if ls-lisp-support-shell-wildcards
- (wildcard-to-regexp (file-name-nondirectory file))
- (file-name-nondirectory file))
- file (file-name-directory file)))
- (if (or wildcard
- full-directory-p)
- (let* ((dir (file-name-as-directory file))
- (default-directory dir);; so that file-attributes works
- (sum 0)
- elt
- short
- (file-list (directory-files dir nil wildcard))
- file-alist
- (now (current-time))
- ;; do all bindings here for speed
- fil attr)
- (cond ((memq ?A switches)
- (setq file-list
- (ls-lisp-delete-matching "^\\.\\.?$" file-list)))
- ((not (memq ?a switches))
- ;; if neither -A nor -a, flush . files
- (setq file-list
- (ls-lisp-delete-matching "^\\." file-list))))
- (setq file-alist
- (mapcar
- (function
- (lambda (x)
- ;; file-attributes("~bogus") bombs
- (cons x (file-attributes (expand-file-name x)))))
- ;; inserting the call to directory-files right here
- ;; seems to stimulate an Emacs bug
- ;; ILLEGAL DATATYPE (#o37777777727) or #o67
- file-list))
- ;; ``Total'' line (filled in afterwards).
- (insert (if (car-safe file-alist)
- "total \007\n"
- ;; Shell says ``No match'' if no files match
- ;; the wildcard; let's say something similar.
- "(No match)\ntotal \007\n"))
- (setq file-alist
- (ls-lisp-handle-switches file-alist switches))
- (while file-alist
- (setq elt (car file-alist)
- file-alist (cdr file-alist)
- short (car elt)
- attr (cdr elt))
- (and attr
- (setq sum (+ sum (nth 7 attr)))
- (insert (ls-lisp-format short attr switches now))))
- ;; Fill in total size of all files:
- (save-excursion
- (search-backward "total \007")
- (goto-char (match-end 0))
- (delete-char -1)
- (insert (format "%d" (if (zerop sum) 0 (1+ (/ sum 1024)))))))
- ;; 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 (ls-lisp-format file (file-attributes file) switches
- (current-time)))))))
-
-(defun ls-lisp-delete-matching (regexp list)
- ;; Delete all elements matching REGEXP from LIST, return new list.
- ;; Should perhaps use setcdr for efficiency.
- (let (result)
- (while list
- (or (string-match regexp (car list))
- (setq result (cons (car list) result)))
- (setq list (cdr list)))
- result))
-
-(defun ls-lisp-handle-switches (file-alist switches)
- ;; FILE-ALIST's elements are (FILE . FILE-ATTRIBUTES).
- ;; Return new alist sorted according to SWITCHES which is a list of
- ;; characters. Default sorting is alphabetically.
- (let (index)
- (setq file-alist
- (sort file-alist
- (cond ((memq ?S switches) ; sorted on size
- (function
- (lambda (x y)
- ;; 7th file attribute is file size
- ;; Make largest file come first
- (< (nth 7 (cdr y))
- (nth 7 (cdr x))))))
- ((memq ?t switches) ; sorted on time
- (setq index (ls-lisp-time-index switches))
- (function
- (lambda (x y)
- (ls-lisp-time-lessp (nth index (cdr y))
- (nth index (cdr x))))))
- (t ; sorted alphabetically
- (function
- (lambda (x y)
- (string-lessp (car x)
- (car y)))))))))
- (if (memq ?r switches) ; reverse sort order
- (setq file-alist (nreverse file-alist)))
- file-alist)
-
-;; From Roland McGrath. Can use this to sort on time.
-(defun ls-lisp-time-lessp (time0 time1)
- (let ((hi0 (car time0))
- (hi1 (car time1))
- (lo0 (car (cdr time0)))
- (lo1 (car (cdr time1))))
- (or (< hi0 hi1)
- (and (= hi0 hi1)
- (< lo0 lo1)))))
-
-
-(defun ls-lisp-format (file-name file-attr switches now)
- (let ((file-type (nth 0 file-attr)))
- (concat (if (memq ?i switches) ; inode number
- (format "%6d " (nth 10 file-attr)))
- ;; nil is treated like "" in concat
- (if (memq ?s switches) ; size in K
- (format "%4d " (1+ (/ (nth 7 file-attr) 1024))))
- (nth 8 file-attr) ; permission bits
- ;; numeric uid/gid are more confusing than helpful
- ;; Emacs should be able to make strings of them.
- ;; user-login-name and user-full-name could take an
- ;; optional arg.
- (format " %3d %-8s %-8s %8d "
- (nth 1 file-attr) ; no. of links
- (if (= (user-uid) (nth 2 file-attr))
- (user-login-name)
- (int-to-string (nth 2 file-attr))) ; uid
- (if (eq system-type 'ms-dos)
- "root" ; everything is root on MSDOS.
- (int-to-string (nth 3 file-attr))) ; gid
- (nth 7 file-attr) ; size in bytes
- )
- (ls-lisp-format-time file-attr switches now)
- " "
- file-name
- (if (stringp file-type) ; is a symbolic link
- (concat " -> " file-type)
- "")
- "\n"
- )))
-
-(defun ls-lisp-time-index (switches)
- ;; Return index into file-attributes according to ls SWITCHES.
- (cond
- ((memq ?c switches) 6) ; last mode change
- ((memq ?u switches) 4) ; last access
- ;; default is last modtime
- (t 5)))
-
-(defun ls-lisp-format-time (file-attr switches now)
- ;; Format time string for file with attributes FILE-ATTR according
- ;; to SWITCHES (a list of ls option letters of which c and u are recognized).
- ;; Use the same method as `ls' to decide whether to show time-of-day or year,
- ;; depending on distance between file date and NOW.
- (let* ((time (nth (ls-lisp-time-index switches) file-attr))
- (diff16 (- (car time) (car now)))
- (diff (+ (ash diff16 16) (- (car (cdr time)) (car (cdr now)))))
- (past-cutoff (- (* 6 30 24 60 60))) ; 6 30-day months
- (future-cutoff (* 60 60))) ; 1 hour
- (format-time-string
- (if (and
- (<= past-cutoff diff) (<= diff future-cutoff)
- ;; Sanity check in case `diff' computation overflowed.
- (<= (1- (ash past-cutoff -16)) diff16)
- (<= diff16 (1+ (ash future-cutoff -16))))
- "%b %e %H:%M"
- "%b %e %Y")
- time)))
-
-(provide 'ls-lisp)
-
-;;; ls-lisp.el ends here
diff --git a/lisp/macros.el b/lisp/macros.el
deleted file mode 100644
index 6263a6957c2..00000000000
--- a/lisp/macros.el
+++ /dev/null
@@ -1,306 +0,0 @@
-;;; macros.el --- non-primitive commands for keyboard macros.
-
-;; Copyright (C) 1985, 86, 87, 92, 94, 95 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: abbrev
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Extension commands for keyboard macros. These permit you to assign
-;; a name to the last-defined keyboard macro, expand and insert the
-;; lisp corresponding to a macro, query the user from within a macro,
-;; or apply a macro to each line in the reason.
-
-;;; Code:
-
-;;;###autoload
-(defun name-last-kbd-macro (symbol)
- "Assign a name to the last keyboard macro defined.
-Argument SYMBOL 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."
- (interactive "SName for last kbd macro: ")
- (or last-kbd-macro
- (error "No keyboard macro defined"))
- (and (fboundp symbol)
- (not (stringp (symbol-function symbol)))
- (not (vectorp (symbol-function symbol)))
- (error "Function %s is already defined and not a keyboard macro."
- symbol))
- (if (string-equal symbol "")
- (error "No command name given"))
- (fset symbol last-kbd-macro))
-
-;;;###autoload
-(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).
-
-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."
- (interactive "CInsert kbd macro (name): \nP")
- (let (definition)
- (if (string= (symbol-name macroname) "")
- (progn
- (setq macroname 'last-kbd-macro definition last-kbd-macro)
- (insert "(setq "))
- (setq definition (symbol-function macroname))
- (insert "(fset '"))
- (prin1 macroname (current-buffer))
- (insert "\n ")
- (if (stringp definition)
- (let ((beg (point)) end)
- (prin1 definition (current-buffer))
- (setq end (point-marker))
- (goto-char beg)
- (while (< (point) end)
- (let ((char (following-char)))
- (cond ((= char 0)
- (delete-region (point) (1+ (point)))
- (insert "\\C-@"))
- ((< char 27)
- (delete-region (point) (1+ (point)))
- (insert "\\C-" (+ 96 char)))
- ((= char ?\C-\\)
- (delete-region (point) (1+ (point)))
- (insert "\\C-\\\\"))
- ((< char 32)
- (delete-region (point) (1+ (point)))
- (insert "\\C-" (+ 64 char)))
- ((< char 127)
- (forward-char 1))
- ((= char 127)
- (delete-region (point) (1+ (point)))
- (insert "\\C-?"))
- ((= char 128)
- (delete-region (point) (1+ (point)))
- (insert "\\M-\\C-@"))
- ((= char (aref "\M-\C-\\" 0))
- (delete-region (point) (1+ (point)))
- (insert "\\M-\\C-\\\\"))
- ((< char 155)
- (delete-region (point) (1+ (point)))
- (insert "\\M-\\C-" (- char 32)))
- ((< char 160)
- (delete-region (point) (1+ (point)))
- (insert "\\M-\\C-" (- char 64)))
- ((= char (aref "\M-\\" 0))
- (delete-region (point) (1+ (point)))
- (insert "\\M-\\\\"))
- ((< char 255)
- (delete-region (point) (1+ (point)))
- (insert "\\M-" (- char 128)))
- ((= char 255)
- (delete-region (point) (1+ (point)))
- (insert "\\M-\\C-?"))))))
- (if (vectorp definition)
- (let ((len (length definition)) (i 0) char mods)
- (while (< i len)
- (insert (if (zerop i) ?\[ ?\ ))
- (setq char (aref definition i)
- i (1+ i))
- (cond ((not (numberp char))
- (prin1 char (current-buffer)))
- (t
- (insert "?")
- (setq mods (event-modifiers char)
- char (event-basic-type char))
- (while mods
- (cond ((eq (car mods) 'control)
- (insert "\\C-"))
- ((eq (car mods) 'meta)
- (insert "\\M-"))
- ((eq (car mods) 'hyper)
- (insert "\\H-"))
- ((eq (car mods) 'super)
- (insert "\\s-"))
- ((eq (car mods) 'alt)
- (insert "\\A-"))
- ((and (eq (car mods) 'shift)
- (>= char ?a)
- (<= char ?z))
- (setq char (upcase char)))
- ((eq (car mods) 'shift)
- (insert "\\S-")))
- (setq mods (cdr mods)))
- (cond ((= char ?\\)
- (insert "\\\\"))
- ((= char 127)
- (insert "\\C-?"))
- ((< char 127)
- (insert char))
- (t (insert "\\" (format "%o" char)))))))
- (insert ?\]))
- (prin1 definition (current-buffer))))
- (insert ")\n")
- (if keys
- (let ((keys (where-is-internal macroname '(keymap))))
- (while keys
- (insert "(global-set-key ")
- (prin1 (car keys) (current-buffer))
- (insert " '")
- (prin1 macroname (current-buffer))
- (insert ")\n")
- (setq keys (cdr keys)))))))
-
-;;;###autoload
-(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, asks whether to continue running the macro.
-Your options are: \\<query-replace-map>
-\\[act] Finish this iteration normally and continue with the next.
-\\[skip] Skip the rest of this iteration, and start the next.
-\\[exit] Stop the macro entirely right now.
-\\[recenter] Redisplay the screen, then ask again.
-\\[edit] Enter recursive edit; ask again when you exit from that."
- (interactive "P")
- (or executing-kbd-macro
- defining-kbd-macro
- (error "Not defining or executing kbd macro"))
- (if flag
- (let (executing-kbd-macro defining-kbd-macro)
- (recursive-edit))
- (if (not executing-kbd-macro)
- nil
- (let ((loop t)
- (msg (substitute-command-keys
- "Proceed with macro?\\<query-replace-map>\
- (\\[act], \\[skip], \\[exit], \\[recenter], \\[edit]) ")))
- (while loop
- (let ((key (let ((executing-kbd-macro nil)
- (defining-kbd-macro nil))
- (message "%s" msg)
- (read-event)))
- def)
- (setq key (vector key))
- (setq def (lookup-key query-replace-map key))
- (cond ((eq def 'act)
- (setq loop nil))
- ((eq def 'skip)
- (setq loop nil)
- (setq executing-kbd-macro ""))
- ((eq def 'exit)
- (setq loop nil)
- (setq executing-kbd-macro t))
- ((eq def 'recenter)
- (recenter nil))
- ((eq def 'edit)
- (let (executing-kbd-macro defining-kbd-macro)
- (recursive-edit)))
- ((eq def 'quit)
- (setq quit-flag t))
- (t
- (or (eq def 'help)
- (ding))
- (with-output-to-temp-buffer "*Help*"
- (princ
- (substitute-command-keys
- "Specify how to proceed with keyboard macro execution.
-Possibilities: \\<query-replace-map>
-\\[act] Finish this iteration normally and continue with the next.
-\\[skip] Skip the rest of this iteration, and start the next.
-\\[exit] Stop the macro entirely right now.
-\\[recenter] Redisplay the screen, then ask again.
-\\[edit] Enter recursive edit; ask again when you exit from that."))
- (save-excursion
- (set-buffer standard-output)
- (help-mode)))))))))))
-
-;;;###autoload
-(defun apply-macro-to-region-lines (top bottom &optional macro)
- "For each complete line between point and mark, move to the beginning
-of the line, and run the last keyboard macro.
-
-When called from lisp, this function takes two arguments TOP and
-BOTTOM, describing the current region. TOP must be before BOTTOM.
-The optional third argument MACRO specifies a keyboard macro to
-execute.
-
-This is useful for quoting or unquoting included text, adding and
-removing comments, or producing tables where the entries are regular.
-
-For example, in Usenet articles, sections of text quoted from another
-author are indented, or have each line start with `>'. To quote a
-section of text, define a keyboard macro which inserts `>', put point
-and mark at opposite ends of the quoted section, and use
-`\\[apply-macro-to-region-lines]' to mark the entire section.
-
-Suppose you wanted to build a keyword table in C where each entry
-looked like this:
-
- { \"foo\", foo_data, foo_function },
- { \"bar\", bar_data, bar_function },
- { \"baz\", baz_data, baz_function },
-
-You could enter the names in this format:
-
- foo
- bar
- baz
-
-and write a macro to massage a word into a table entry:
-
- \\C-x (
- \\M-d { \"\\C-y\", \\C-y_data, \\C-y_function },
- \\C-x )
-
-and then select the region of un-tablified names and use
-`\\[apply-macro-to-region-lines]' to build the table from the names.
-"
- (interactive "r")
- (or macro
- (progn
- (if (null last-kbd-macro)
- (error "No keyboard macro has been defined."))
- (setq macro last-kbd-macro)))
- (save-excursion
- (let ((end-marker (progn
- (goto-char bottom)
- (beginning-of-line)
- (point-marker)))
- next-line-marker)
- (goto-char top)
- (if (not (bolp))
- (forward-line 1))
- (setq next-line-marker (point-marker))
- (while (< next-line-marker end-marker)
- (goto-char next-line-marker)
- (save-excursion
- (forward-line 1)
- (set-marker next-line-marker (point)))
- (save-excursion
- (execute-kbd-macro (or macro last-kbd-macro))))
- (set-marker end-marker nil)
- (set-marker next-line-marker nil))))
-
-;;;###autoload (define-key ctl-x-map "q" 'kbd-macro-query)
-
-;;; macros.el ends here
diff --git a/lisp/mail/blessmail.el b/lisp/mail/blessmail.el
deleted file mode 100644
index dc4c749c31a..00000000000
--- a/lisp/mail/blessmail.el
+++ /dev/null
@@ -1,69 +0,0 @@
-;;; blessmail.el --- Decide whether movemail needs special privileges.
-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This is loaded into a bare Emacs to create the blessmail script,
-;; which (on systems that need it) is used during installation
-;; to give appropriate permissions to movemail.
-;;
-;; It has to be done from lisp in order to be sure of getting the
-;; correct value of rmail-spool-directory.
-
-;;; Code:
-
-;; These are no longer needed because we run this in emacs instead of temacs.
-;; (message "Using load-path %s" load-path)
-;; (load "paths.el")
-;; It is not safe to load site-init.el here, because it might have things in it
-;; that won't load properly unless all the rest of Emacs is loaded.
-
-(let ((dirname (directory-file-name rmail-spool-directory))
- linkname attr modes)
- ;; Check for symbolic link
- (while (setq linkname (file-symlink-p dirname))
- (setq dirname (if (file-name-absolute-p linkname)
- linkname
- (concat (file-name-directory dirname) linkname))))
- (insert "#!/bin/sh\n")
- (setq attr (file-attributes dirname))
- (if (not (eq t (car attr)))
- (insert (format "echo %s is not a directory\n" rmail-spool-directory))
- (setq modes (nth 8 attr))
- (cond ((= ?w (aref modes 8))
- ;; Nothing needs to be done.
- )
- ((= ?w (aref modes 5))
- (insert "chgrp " (number-to-string (nth 3 attr))
- " $* && chmod g+s $*\n"))
- ((= ?w (aref modes 2))
- (insert "chown " (number-to-string (nth 2 attr))
- " $* && chmod u+s $*\n"))
- (t
- (insert "chown root $* && chmod u+s $*\n"))))
- (insert "echo mail directory = " dirname "\n"))
-(write-region (point-min) (point-max) "blessmail")
-(kill-emacs)
-
-;;; blessmail.el ends here
diff --git a/lisp/mail/emacsbug.el b/lisp/mail/emacsbug.el
deleted file mode 100644
index 6efd33ea05a..00000000000
--- a/lisp/mail/emacsbug.el
+++ /dev/null
@@ -1,153 +0,0 @@
-;;; emacsbug.el --- command to report Emacs bugs to appropriate mailing list.
-
-;; Copyright (C) 1985, 1994 Free Software Foundation, Inc.
-
-;; Author: K. Shane Hartman
-;; Maintainer: FSF
-;; Keywords: maint
-
-;; Not fully installed because it can work only on Internet hosts.
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; `M-x report-emacs-bug ' starts an email note to the Emacs maintainers
-;; describing a problem. Here's how it's done...
-
-;;; Code:
-
-;; >> This should be an address which is accessible to your machine,
-;; >> otherwise you can't use this file. It will only work on the
-;; >> internet with this address.
-
-(require 'sendmail)
-
-(defvar bug-gnu-emacs "bug-gnu-emacs@prep.ai.mit.edu"
- "Address of mailing list for GNU Emacs bugs.")
-
-(defvar report-emacs-bug-pretest-address "emacs-pretest-bug@gnu.ai.mit.edu"
- "Address of mailing list for GNU Emacs pretest bugs.")
-
-(defvar report-emacs-bug-orig-text nil
- "The automatically-created initial text of bug report.")
-
-;;;###autoload
-(defun report-emacs-bug (topic &optional recent-keys)
- "Report a bug in GNU Emacs.
-Prompts for bug subject. Leaves you in a mail buffer."
- ;; This strange form ensures that (recent-keys) is the value before
- ;; the bug subject string is read.
- (interactive (reverse (list (recent-keys) (read-string "Bug Subject: "))))
- (condition-case nil
- (let (user-point)
- (compose-mail (if (string-match "\\..*\\..*\\." emacs-version)
- ;; If there are four numbers in emacs-version,
- ;; this is a pretest version.
- report-emacs-bug-pretest-address
- bug-gnu-emacs)
- topic)
- ;; The rest of this does not execute
- ;; if the user was asked to confirm and said no.
- (goto-char (point-min))
- (re-search-forward (concat "^" (regexp-quote mail-header-separator) "\n"))
- (insert "In " (emacs-version) "\n")
- (if (and system-configuration-options
- (not (equal system-configuration-options "")))
- (insert "configured using `configure "
- system-configuration-options "'\n"))
- (insert "\n")
- (insert "Please describe exactly what actions triggered the bug\n"
- "and the precise symptoms of the bug:\n\n")
- (setq user-point (point))
- (insert "\n\n\n"
- "Recent input:\n")
- (let ((before-keys (point)))
- (insert (mapconcat (lambda (key)
- (if (or (integerp key)
- (symbolp key)
- (listp key))
- (single-key-description key)
- (prin1-to-string key nil)))
- (or recent-keys (recent-keys))
- " "))
- (save-restriction
- (narrow-to-region before-keys (point))
- (goto-char before-keys)
- (while (progn (move-to-column 50) (not (eobp)))
- (search-forward " " nil t)
- (insert "\n"))))
- (let ((message-buf (get-buffer "*Messages*")))
- (if message-buf
- (progn
- (insert "\n\nRecent messages:\n")
- (insert-buffer-substring message-buf
- (save-excursion
- (set-buffer message-buf)
- (goto-char (point-max))
- (forward-line -10)
- (point))
- (save-excursion
- (set-buffer message-buf)
- (point-max))))))
- ;; This is so the user has to type something
- ;; in order to send easily.
- (use-local-map (nconc (make-sparse-keymap) (current-local-map)))
- (define-key (current-local-map) "\C-c\C-i" 'report-emacs-bug-info)
- (with-output-to-temp-buffer "*Bug Help*"
- (princ (substitute-command-keys
- "Type \\[mail-send-and-exit] to send the bug report.\n"))
- (princ (substitute-command-keys
- "Type \\[kill-buffer] RET to cancel (don't send it).\n"))
- (terpri)
- (princ (substitute-command-keys
- "Type \\[report-emacs-bug-info] to visit in Info the Emacs Manual section
-about when and how to write a bug report,
-and what information to supply so that the bug can be fixed.
-Type SPC to scroll through this section and its subsections.")))
- ;; Make it less likely people will send empty messages.
- (make-local-variable 'mail-send-hook)
- (add-hook 'mail-send-hook 'report-emacs-bug-hook)
- (save-excursion
- (goto-char (point-max))
- (skip-chars-backward " \t\n")
- (make-local-variable 'report-emacs-bug-orig-text)
- (setq report-emacs-bug-orig-text (buffer-substring (point-min) (point))))
- (goto-char user-point))
- (error nil)))
-
-(defun report-emacs-bug-info ()
- "Go to the Info node on reporting Emacs bugs."
- (interactive)
- (info)
- (Info-directory)
- (Info-menu "emacs")
- (Info-goto-node "Bugs"))
-
-(defun report-emacs-bug-hook ()
- (save-excursion
- (goto-char (point-max))
- (skip-chars-backward " \t\n")
- (if (and (= (- (point) (point-min))
- (length report-emacs-bug-orig-text))
- (equal (buffer-substring (point-min) (point))
- report-emacs-bug-orig-text))
- (error "No text entered in bug report"))))
-
-(provide 'emacsbug)
-
-;;; emacsbug.el ends here
diff --git a/lisp/mail/mail-extr.el b/lisp/mail/mail-extr.el
deleted file mode 100644
index 931685c4de1..00000000000
--- a/lisp/mail/mail-extr.el
+++ /dev/null
@@ -1,1987 +0,0 @@
-;;; mail-extr.el --- extract full name and address from RFC 822 mail header.
-
-;; Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Joe Wells <jbw@cs.bu.edu>
-;; Maintainer: Jamie Zawinski <jwz@lucid.com>
-;; Version: 1.8
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; This file has been censored by the Communications Decency Act.
-;;; That law was passed under the guise of a ban on pornography, but
-;;; it bans far more than that. This file did not contain pornography,
-;;; but it was censored nonetheless.
-
-;;; For information on US government censorship of the Internet, and
-;;; what you can do to bring back freedom of the press, see the web
-;;; site http://www.vtw.org/
-
-;; The entry point of this code is
-;;
-;; mail-extract-address-components: (address)
-;;
-;; Given an RFC-822 ADDRESS, extract full name and canonical address.
-;; Returns a list of the form (FULL-NAME CANONICAL-ADDRESS).
-;; If no name can be extracted, FULL-NAME will be nil.
-;; ADDRESS may be a string or a buffer. If it is a buffer, the visible
-;; (narrowed) portion of the buffer will be interpreted as the address.
-;; (This feature exists so that the clever caller might be able to avoid
-;; consing a string.)
-;; If ADDRESS contains more than one RFC-822 address, only the first is
-;; returned.
-;;
-;; This code is more correct (and more heuristic) parser than the code in
-;; rfc822.el. And despite its size, it's fairly fast.
-;;
-;; There are two main benefits:
-;;
-;; 1. Higher probability of getting the correct full name for a human than
-;; any other package we know of. (On the other hand, it will cheerfully
-;; mangle non-human names/comments.)
-;; 2. Address part is put in a canonical form.
-;;
-;; The interface is not yet carved in stone; please give us suggestions.
-;;
-;; We have an extensive test-case collection of funny addresses if you want to
-;; work with the code. Developing this code requires frequent testing to
-;; make sure you're not breaking functionality. The test cases aren't included
-;; because they are over 100K.
-;;
-;; If you find an address that mail-extr fails on, please send it to the
-;; maintainer along with what you think the correct results should be. We do
-;; not consider it a bug if mail-extr mangles a comment that does not
-;; correspond to a real human full name, although we would prefer that
-;; mail-extr would return the comment as-is.
-;;
-;; Features:
-;;
-;; * Full name handling:
-;;
-;; * knows where full names can be found in an address.
-;; * avoids using empty comments and quoted text.
-;; * extracts full names from mailbox names.
-;; * recognizes common formats for comments after a full name.
-;; * puts a period and a space after each initial.
-;; * understands & referring to the mailbox name, capitalized.
-;; * strips name prefixes like "Prof.", etc.
-;; * understands what characters can occur in names (not just letters).
-;; * figures out middle initial from mailbox name.
-;; * removes funny nicknames.
-;; * keeps suffixes such as Jr., Sr., III, etc.
-;; * reorders "Last, First" type names.
-;;
-;; * Address handling:
-;;
-;; * parses rfc822 quoted text, comments, and domain literals.
-;; * parses rfc822 multi-line headers.
-;; * does something reasonable with rfc822 GROUP addresses.
-;; * handles many rfc822 noncompliant and garbage addresses.
-;; * canonicalizes addresses (after stripping comments/phrases outside <>).
-;; * converts ! addresses into .UUCP and %-style addresses.
-;; * converts rfc822 ROUTE addresses to %-style addresses.
-;; * truncates %-style addresses at leftmost fully qualified domain name.
-;; * handles local relative precedence of ! vs. % and @ (untested).
-;;
-;; It does almost no string creation. It primarily uses the built-in
-;; parsing routines with the appropriate syntax tables. This should
-;; result in greater speed.
-;;
-;; TODO:
-;;
-;; * handle all test cases. (This will take forever.)
-;; * software to pick the correct header to use (eg., "Senders-Name:").
-;; * multiple addresses in the "From:" header (almost all of the necessary
-;; code is there).
-;; * flag to not treat `,' as an address separator. (This is useful when
-;; there is a "From:" header but no "Sender:" header, because then there
-;; is only allowed to be one address.)
-;; * mailbox name does not necessarily contain full name.
-;; * fixing capitalization when it's all upper or lowercase. (Hard!)
-;; * some of the domain literal handling is missing. (But I've never even
-;; seen one of these in a mail address, so maybe no big deal.)
-;; * arrange to have syntax tables byte-compiled.
-;; * speed hacks.
-;; * delete unused variables.
-;; * arrange for testing with different relative precedences of ! vs. @
-;; and %.
-;; * insert documentation strings!
-;; * handle X.400-gatewayed addresses according to RFC 1148.
-
-;;; Change Log:
-;;
-;; Thu Feb 17 17:57:33 1994 Jamie Zawinski (jwz@lucid.com)
-;;
-;; * merged with jbw's latest version
-;;
-;; Wed Feb 9 21:56:27 1994 Jamie Zawinski (jwz@lucid.com)
-;;
-;; * high-bit chars in comments weren't treated as word syntax
-;;
-;; Sat Feb 5 03:13:40 1994 Jamie Zawinski (jwz@lucid.com)
-;;
-;; * call replace-match with fixed-case arg
-;;
-;; Thu Dec 16 21:56:45 1993 Jamie Zawinski (jwz@lucid.com)
-;;
-;; * some more cleanup, doc, added provide
-;;
-;; Tue Mar 23 21:23:18 1993 Joe Wells (jbw at csd.bu.edu)
-;;
-;; * Made mail-full-name-prefixes a user-customizable variable.
-;; Allow passing the address as a buffer as well as as a string.
-;; Allow [ and ] as name characters (Finnish character set).
-;;
-;; Mon Mar 22 21:20:56 1993 Joe Wells (jbw at bigbird.bu.edu)
-;;
-;; * Handle "null" addresses. Handle = used for spacing in mailbox
-;; name. Fix bug in handling of ROUTE-ADDR-type addresses that are
-;; missing their brackets. Handle uppercase "JR". Extract full
-;; names from X.400 addresses encoded in RFC-822. Fix bug in
-;; handling of multiple addresses where first has trailing comment.
-;; Handle more kinds of telephone extension lead-ins.
-;;
-;; Mon Mar 22 20:16:57 1993 Joe Wells (jbw at bigbird.bu.edu)
-;;
-;; * Handle HZ encoding for embedding GB encoded chinese characters.
-;;
-;; Mon Mar 22 00:46:12 1993 Joe Wells (jbw at bigbird.bu.edu)
-;;
-;; * Fixed too broad matching of ham radio call signs. Fixed bug in
-;; handling an unmatched ' in a name string. Enhanced recognition
-;; of when . in the mailbox name terminates the name portion.
-;; Narrowed conversion of . to space to only the necessary
-;; situation. Deal with VMS's stupid date stamps. Handle a unique
-;; way of introducing an alternate address. Fixed spacing bug I
-;; introduced in switching last name order. Fixed bug in handling
-;; address with ! and % but no @. Narrowed the cases in which
-;; certain trailing words are discarded.
-;;
-;; Sun Mar 21 21:41:06 1993 Joe Wells (jbw at bigbird.bu.edu)
-;;
-;; * Fixed bugs in handling GROUP addresses. Certain words in the
-;; middle of a name no longer terminate it. Handle LISTSERV list
-;; names. Ignore comment field containing mailbox name.
-;;
-;; Sun Mar 21 14:39:38 1993 Joe Wells (jbw at bigbird.bu.edu)
-;;
-;; * Moved variant-method code back into main function. Handle
-;; underscores as spaces in comments. Handle leading nickname. Add
-;; flag to ignore single-word names. Other changes.
-;;
-;; Mon Feb 1 22:23:31 1993 Joe Wells (jbw at bigbird.bu.edu)
-;;
-;; * Added in changes by Rod Whitby and Jamie Zawinski. This
-;; includes the flag mail-extr-guess-middle-initial and the fix for
-;; handling multiple addresses correctly. (Whitby just changed
-;; a > to a <.)
-;;
-;; Mon Apr 6 23:59:09 1992 Joe Wells (jbw at bigbird.bu.edu)
-;;
-;; * Cleaned up some more. Release version 1.0 to world.
-;;
-;; Sun Apr 5 19:39:08 1992 Joe Wells (jbw at bigbird.bu.edu)
-;;
-;; * Cleaned up full name extraction extensively.
-;;
-;; Sun Feb 2 14:45:24 1992 Joe Wells (jbw at bigbird.bu.edu)
-;;
-;; * Total rewrite. Integrated mail-canonicalize-address into
-;; mail-extract-address-components. Now handles GROUP addresses more
-;; or less correctly. Better handling of lots of different cases.
-;;
-;; Fri Jun 14 19:39:50 1991
-;; * Created.
-
-;;; Code:
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; User configuration variable definitions.
-;;
-
-(defvar mail-extr-guess-middle-initial nil
- "*Whether to try to guess middle initial from mail address.
-If true, then when we see an address like \"John Smith <jqs@host.com>\"
-we will assume that \"John Q. Smith\" is the fellow's name.")
-
-(defvar mail-extr-ignore-single-names t
- "*Whether to ignore a name that is just a single word.
-If true, then when we see an address like \"Idiot <dumb@stupid.com>\"
-we will act as though we couldn't find a full name in the address.")
-
-;; Matches a leading title that is not part of the name (does not
-;; contribute to uniquely identifying the person).
-(defvar mail-extr-full-name-prefixes
- (purecopy
- "\\(Prof\\|D[Rr]\\|Mrs?\\|Rev\\|Rabbi\\|SysOp\\|LCDR\\)\\.?[ \t\n]")
- "*Matches prefixes to the full name that identify a person's position.
-These are stripped from the full name because they do not contribute to
-uniquely identifying the person.")
-
-(defvar mail-extr-@-binds-tighter-than-! nil
- "*Whether the local mail transport agent looks at ! before @.")
-
-(defvar mail-extr-mangle-uucp nil
- "*Whether to throw away information in UUCP addresses
-by translating things like \"foo!bar!baz@host\" into \"baz@bar.UUCP\".")
-
-;;----------------------------------------------------------------------
-;; what orderings are meaningful?????
-;;(defvar mail-operator-precedence-list '(?! ?% ?@))
-;; Right operand of a % or a @ must be a domain name, period. No other
-;; operators allowed. Left operand of a @ is an address relative to that
-;; site.
-
-;; Left operand of a ! must be a domain name. Right operand is an
-;; arbitrary address.
-;;----------------------------------------------------------------------
-
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; Constant definitions.
-;;
-
-;; Codes in
-;; Names in ISO 8859-1 Name
-;; ISO 10XXX ISO 8859-2 in
-;; ISO 6937 ISO 10646 RFC Swedish
-;; etc. Hex Oct 1345 TeX Split ASCII Description
-;; --------- ---------- ---- --- ----- ----- -------------------------------
-;; %a E4 344 a: \"a ae { latin small a + diaeresis d
-;; %o F6 366 o: \"o oe | latin small o + diaeresis v
-;; @a E5 345 aa \oa aa } latin small a + ring above e
-;; %u FC 374 u: \"u ue ~ latin small u + diaeresis |
-;; /e E9 351 e' \'e ` latin small e + acute i
-;; %A C4 304 A: \"A AE [ latin capital a + diaeresis D
-;; %O D6 326 O: \"O OE \ latin capital o + diaeresis V
-;; @A C5 305 AA \oA AA ] latin capital a + ring above E
-;; %U DC 334 U: \"U UE ^ latin capital u + diaeresis \
-;; /E C9 311 E' \'E @ latin capital e + acute I
-
-;; NOTE: @a and @A are not in ISO 8859-2 (the codes mentioned above invoke
-;; /l and /L). Some of this data was retrieved from
-;; listserv@jhuvm.hcf.jhu.edu.
-
-;; Any character that can occur in a name, not counting characters that
-;; separate parts of a multipart name (hyphen and period).
-;; Yes, there are weird people with digits in their names.
-;; You will also notice the consideration for the
-;; Swedish/Finnish/Norwegian character set.
-(defconst mail-extr-all-letters-but-separators
- (purecopy "][A-Za-z{|}'~0-9`\200-\377"))
-
-;; Any character that can occur in a name in an RFC822 address including
-;; the separator (hyphen and possibly period) for multipart names.
-;; #### should . be in here?
-(defconst mail-extr-all-letters
- (purecopy (concat mail-extr-all-letters-but-separators "---")))
-
-;; Any character that can start a name.
-;; Keep this set as minimal as possible.
-(defconst mail-extr-first-letters (purecopy "A-Za-z\200-\377"))
-
-;; Any character that can end a name.
-;; Keep this set as minimal as possible.
-(defconst mail-extr-last-letters (purecopy "A-Za-z\200-\377`'."))
-
-(defconst mail-extr-leading-garbage
- (purecopy (format "[^%s]+" mail-extr-first-letters)))
-
-;; (defconst mail-extr-non-name-chars
-;; (purecopy (concat "^" mail-extr-all-letters ".")))
-;; (defconst mail-extr-non-begin-name-chars
-;; (purecopy (concat "^" mail-extr-first-letters)))
-;; (defconst mail-extr-non-end-name-chars
-;; (purecopy (concat "^" mail-extr-last-letters)))
-
-;; Matches an initial not followed by both a period and a space.
-;; (defconst mail-extr-bad-initials-pattern
-;; (purecopy
-;; (format "\\(\\([^%s]\\|\\`\\)[%s]\\)\\(\\.\\([^ ]\\)\\| \\|\\([^%s .]\\)\\|\\'\\)"
-;; mail-extr-all-letters mail-extr-first-letters mail-extr-all-letters)))
-
-;; Matches periods used instead of spaces. Must not match the period
-;; following an initial.
-(defconst mail-extr-bad-dot-pattern
- (purecopy
- (format "\\([%s][%s]\\)\\.+\\([%s]\\)"
- mail-extr-all-letters
- mail-extr-last-letters
- mail-extr-first-letters)))
-
-;; Matches an embedded or leading nickname that should be removed.
-;; (defconst mail-extr-nickname-pattern
-;; (purecopy
-;; (format "\\([ .]\\|\\`\\)[\"'`\[\(]\\([ .%s]+\\)[\]\"'\)] "
-;; mail-extr-all-letters)))
-
-;; Matches the occurrence of a generational name suffix, and the last
-;; character of the preceding name. This is important because we want to
-;; keep such suffixes: they help to uniquely identify the person.
-;; *** Perhaps this should be a user-customizable variable. However, the
-;; *** regular expression is fairly tricky to alter, so maybe not.
-(defconst mail-extr-full-name-suffix-pattern
- (purecopy
- (format
- "\\(,? ?\\([JjSs][Rr]\\.?\\|V?I+V?\\)\\)\\([^%s]\\([^%s]\\|\\'\\)\\|\\'\\)"
- mail-extr-all-letters mail-extr-all-letters)))
-
-(defconst mail-extr-roman-numeral-pattern (purecopy "V?I+V?\\b"))
-
-;; Matches a trailing uppercase (with other characters possible) acronym.
-;; Must not match a trailing uppercase last name or trailing initial
-(defconst mail-extr-weird-acronym-pattern
- (purecopy "\\([A-Z]+[-_/]\\|[A-Z][A-Z][A-Z]?\\b\\)"))
-
-;; Matches a mixed-case or lowercase name (not an initial).
-;; #### Match Latin1 lower case letters here too?
-;; (defconst mail-extr-mixed-case-name-pattern
-;; (purecopy
-;; (format
-;; "\\b\\([a-z][%s]*[%s]\\|[%s][%s]*[a-z][%s]*[%s]\\|[%s][%s]*[a-z]\\)"
-;; mail-extr-all-letters mail-extr-last-letters
-;; mail-extr-first-letters mail-extr-all-letters mail-extr-all-letters
-;; mail-extr-last-letters mail-extr-first-letters mail-extr-all-letters)))
-
-;; Matches a trailing alternative address.
-;; #### Match Latin1 letters here too?
-;; #### Match _ before @ here too?
-(defconst mail-extr-alternative-address-pattern
- (purecopy "\\(aka *\\)?[a-zA-Z.]+[!@][a-zA-Z.]"))
-
-;; Matches a variety of trailing comments not including comma-delimited
-;; comments.
-(defconst mail-extr-trailing-comment-start-pattern
- (purecopy " [-{]\\|--\\|[+@#></\;]"))
-
-;; Matches a name (not an initial).
-;; This doesn't force a word boundary at the end because sometimes a
-;; comment is separated by a `-' with no preceding space.
-(defconst mail-extr-name-pattern
- (purecopy (format "\\b[%s][%s]*[%s]"
- mail-extr-first-letters
- mail-extr-all-letters
- mail-extr-last-letters)))
-
-(defconst mail-extr-initial-pattern
- (purecopy (format "\\b[%s]\\([. ]\\|\\b\\)" mail-extr-first-letters)))
-
-;; Matches a single name before a comma.
-;; (defconst mail-extr-last-name-first-pattern
-;; (purecopy (concat "\\`" mail-extr-name-pattern ",")))
-
-;; Matches telephone extensions.
-(defconst mail-extr-telephone-extension-pattern
- (purecopy
- "\\(\\([Ee]xt\\|\\|[Tt]ph\\|[Tt]el\\|[Xx]\\).?\\)? *\\+?[0-9][- 0-9]+"))
-
-;; Matches ham radio call signs.
-;; Help from: Mat Maessen N2NJZ <maessm@rpi.edu>, Mark Feit
-;; <mark@era.com>, Michael Covington <mcovingt@ai.uga.edu>.
-;; Examples: DX504 DX515 K5MRU K8DHK KA9WGN KA9WGN KD3FU KD6EUI KD6HBW
-;; KE9TV KF0NV N1API N3FU N3GZE N3IGS N4KCC N7IKQ N9HHU W4YHF W6ANK WA2SUH
-;; WB7VZI N2NJZ NR3G KJ4KK AB4UM AL7NI KH6OH WN3KBT N4TMI W1A N0NZO
-(defconst mail-extr-ham-call-sign-pattern
- (purecopy "\\b\\(DX[0-9]+\\|[AKNW][A-Z]?[0-9][A-Z][A-Z]?[A-Z]?\\)"))
-
-;; Possible trailing suffixes: "\\(/\\(KT\\|A[AEG]\\|[R0-9]\\)\\)?"
-;; /KT == Temporary Technician (has CSC but not "real" license)
-;; /AA == Temporary Advanced
-;; /AE == Temporary Extra
-;; /AG == Temporary General
-;; /R == repeater
-;; /# == stations operating out of home district
-;; I don't include these in the regexp above because I can't imagine
-;; anyone putting them with their name in an e-mail address.
-
-;; Matches normal single-part name
-(defconst mail-extr-normal-name-pattern
- (purecopy (format "\\b[%s][%s]+[%s]"
- mail-extr-first-letters
- mail-extr-all-letters-but-separators
- mail-extr-last-letters)))
-
-;; Matches a single word name.
-;; (defconst mail-extr-one-name-pattern
-;; (purecopy (concat "\\`" mail-extr-normal-name-pattern "\\'")))
-
-;; Matches normal two names with missing middle initial
-;; The first name is not allowed to have a hyphen because this can cause
-;; false matches where the "middle initial" is actually the first letter
-;; of the second part of the first name.
-(defconst mail-extr-two-name-pattern
- (purecopy
- (concat "\\`\\(" mail-extr-normal-name-pattern
- "\\|" mail-extr-initial-pattern
- "\\) +\\(" mail-extr-name-pattern "\\)\\(,\\|\\'\\)")))
-
-(defconst mail-extr-listserv-list-name-pattern
- (purecopy "Multiple recipients of list \\([-A-Z]+\\)"))
-
-(defconst mail-extr-stupid-vms-date-stamp-pattern
- (purecopy
- "[0-9][0-9]-[JFMASOND][aepuco][nbrylgptvc]-[0-9][0-9][0-9][0-9] [0-9]+ *"))
-
-;;; HZ -- GB (PRC Chinese character encoding) in ASCII embedding protocol
-;;
-;; In ASCII mode, a byte is interpreted as an ASCII character, unless a '~' is
-;; encountered. The character '~' is an escape character. By convention, it
-;; must be immediately followed ONLY by '~', '{' or '\n' (<LF>), with the
-;; following special meaning.
-;;
-;; o The escape sequence '~~' is interpreted as a '~'.
-;; o The escape-to-GB sequence '~{' switches the mode from ASCII to GB.
-;; o The escape sequence '~\n' is a line-continuation marker to be consumed
-;; with no output produced.
-;;
-;; In GB mode, characters are interpreted two bytes at a time as (pure) GB
-;; codes until the escape-from-GB code '~}' is read. This code switches the
-;; mode from GB back to ASCII. (Note that the escape-from-GB code '~}'
-;; ($7E7D) is outside the defined GB range.)
-(defconst mail-extr-hz-embedded-gb-encoded-chinese-pattern
- (purecopy "~{\\([^~].\\|~[^\}]\\)+~}"))
-
-;; The leading optional lowercase letters are for a bastardized version of
-;; the encoding, as is the optional nature of the final slash.
-(defconst mail-extr-x400-encoded-address-pattern
- (purecopy "[a-z]?[a-z]?\\(/[A-Za-z]+\\(\\.[A-Za-z]+\\)?=[^/]+\\)+/?\\'"))
-
-(defconst mail-extr-x400-encoded-address-field-pattern-format
- (purecopy "/%s=\\([^/]+\\)\\(/\\|\\'\\)"))
-
-(defconst mail-extr-x400-encoded-address-surname-pattern
- ;; S stands for Surname (family name).
- (purecopy
- (format mail-extr-x400-encoded-address-field-pattern-format "[Ss]")))
-
-(defconst mail-extr-x400-encoded-address-given-name-pattern
- ;; G stands for Given name.
- (purecopy
- (format mail-extr-x400-encoded-address-field-pattern-format "[Gg]")))
-
-(defconst mail-extr-x400-encoded-address-full-name-pattern
- ;; PN stands for Personal Name. When used it represents the combination
- ;; of the G and S fields.
- ;; "The one system I used having this field asked it with the prompt
- ;; `Personal Name'. But they mapped it into G and S on outgoing real
- ;; X.400 addresses. As they mapped G and S into PN on incoming..."
- (purecopy
- (format mail-extr-x400-encoded-address-field-pattern-format "[Pp][Nn]")))
-
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; Syntax tables used for quick parsing.
-;;
-
-(defconst mail-extr-address-syntax-table (make-syntax-table))
-(defconst mail-extr-address-comment-syntax-table (make-syntax-table))
-(defconst mail-extr-address-domain-literal-syntax-table (make-syntax-table))
-(defconst mail-extr-address-text-comment-syntax-table (make-syntax-table))
-(defconst mail-extr-address-text-syntax-table (make-syntax-table))
-(mapcar
- (function
- (lambda (pair)
- (let ((syntax-table (symbol-value (car pair))))
- (mapcar
- (function
- (lambda (item)
- (if (eq 2 (length item))
- ;; modifying syntax of a single character
- (modify-syntax-entry (car item) (car (cdr item)) syntax-table)
- ;; modifying syntax of a range of characters
- (let ((char (nth 0 item))
- (bound (nth 1 item))
- (syntax (nth 2 item)))
- (while (<= char bound)
- (modify-syntax-entry char syntax syntax-table)
- (setq char (1+ char)))))))
- (cdr pair)))))
- '((mail-extr-address-syntax-table
- (?\000 ?\037 "w") ;control characters
- (?\040 " ") ;SPC
- (?! ?~ "w") ;printable characters
- (?\177 "w") ;DEL
- (?\200 ?\377 "w") ;high-bit-on characters
- (?\240 " ") ;nobreakspace
- (?\t " ")
- (?\r " ")
- (?\n " ")
- (?\( ".")
- (?\) ".")
- (?< ".")
- (?> ".")
- (?@ ".")
- (?, ".")
- (?\; ".")
- (?: ".")
- (?\\ "\\")
- (?\" "\"")
- (?. ".")
- (?\[ ".")
- (?\] ".")
- ;; % and ! aren't RFC822 characters, but it is convenient to pretend
- (?% ".")
- (?! ".") ;; this needs to be word-constituent when not in .UUCP mode
- )
- (mail-extr-address-comment-syntax-table
- (?\000 ?\377 "w")
- (?\040 " ")
- (?\240 " ")
- (?\t " ")
- (?\r " ")
- (?\n " ")
- (?\( "\(\)")
- (?\) "\)\(")
- (?\\ "\\"))
- (mail-extr-address-domain-literal-syntax-table
- (?\000 ?\377 "w")
- (?\040 " ")
- (?\240 " ")
- (?\t " ")
- (?\r " ")
- (?\n " ")
- (?\[ "\(\]") ;??????
- (?\] "\)\[") ;??????
- (?\\ "\\"))
- (mail-extr-address-text-comment-syntax-table
- (?\000 ?\377 "w")
- (?\040 " ")
- (?\240 " ")
- (?\t " ")
- (?\r " ")
- (?\n " ")
- (?\( "\(\)")
- (?\) "\)\(")
- (?\[ "\(\]")
- (?\] "\)\[")
- (?\{ "\(\}")
- (?\} "\)\{")
- (?\\ "\\")
- (?\" "\"")
- ;; (?\' "\)\`")
- ;; (?\` "\(\'")
- )
- (mail-extr-address-text-syntax-table
- (?\000 ?\177 ".")
- (?\200 ?\377 "w")
- (?\040 " ")
- (?\t " ")
- (?\r " ")
- (?\n " ")
- (?A ?Z "w")
- (?a ?z "w")
- (?- "w")
- (?\} "w")
- (?\{ "w")
- (?| "w")
- (?\' "w")
- (?~ "w")
- (?0 ?9 "w"))
- ))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; Utility functions and macros.
-;;
-
-(defmacro mail-extr-delete-char (n)
- ;; in v19, delete-char is compiled as a function call, but delete-region
- ;; is byte-coded, so it's much much faster.
- (list 'delete-region '(point) (list '+ '(point) n)))
-
-(defmacro mail-extr-skip-whitespace-forward ()
- ;; v19 fn skip-syntax-forward is more tasteful, but not byte-coded.
- '(skip-chars-forward " \t\n\r\240"))
-
-(defmacro mail-extr-skip-whitespace-backward ()
- ;; v19 fn skip-syntax-backward is more tasteful, but not byte-coded.
- '(skip-chars-backward " \t\n\r\240"))
-
-
-(defmacro mail-extr-undo-backslash-quoting (beg end)
- (`(save-excursion
- (save-restriction
- (narrow-to-region (, beg) (, end))
- (goto-char (point-min))
- ;; undo \ quoting
- (while (search-forward "\\" nil t)
- (mail-extr-delete-char -1)
- (or (eobp)
- (forward-char 1))
- )))))
-
-(defmacro mail-extr-nuke-char-at (pos)
- (` (save-excursion
- (goto-char (, pos))
- (mail-extr-delete-char 1)
- (insert ?\ ))))
-
-(put 'mail-extr-nuke-outside-range
- 'edebug-form-spec '(symbolp &optional form form atom))
-
-(defmacro mail-extr-nuke-outside-range (list-symbol
- beg-symbol end-symbol
- &optional no-replace)
- ;; LIST-SYMBOL names a variable holding a list of buffer positions
- ;; BEG-SYMBOL and END-SYMBOL name variables delimiting a range
- ;; Each element of LIST-SYMBOL which lies outside of the range is
- ;; deleted from the list.
- ;; Unless NO-REPLACE is true, at each of the positions in LIST-SYMBOL
- ;; which lie outside of the range, one character at that position is
- ;; replaced with a SPC.
- (or (memq no-replace '(t nil))
- (error "no-replace must be t or nil, evaluable at macroexpand-time"))
- (` (let ((temp (, list-symbol))
- ch)
- (while temp
- (setq ch (car temp))
- (cond ((or (> ch (, end-symbol))
- (< ch (, beg-symbol)))
- (,@ (if no-replace
- nil
- (` ((mail-extr-nuke-char-at ch)))))
- (setcar temp nil)))
- (setq temp (cdr temp)))
- (setq (, list-symbol) (delq nil (, list-symbol))))))
-
-(defun mail-extr-demarkerize (marker)
- ;; if arg is a marker, destroys the marker, then returns the old value.
- ;; otherwise returns the arg.
- (if (markerp marker)
- (let ((temp (marker-position marker)))
- (set-marker marker nil)
- temp)
- marker))
-
-(defun mail-extr-markerize (pos)
- ;; coerces pos to a marker if non-nil.
- (if (or (markerp pos) (null pos))
- pos
- (copy-marker pos)))
-
-(defmacro mail-extr-last (list)
- ;; Returns last element of LIST.
- ;; Could be a subst.
- (` (let ((list (, list)))
- (while (not (null (cdr list)))
- (setq list (cdr list)))
- (car list))))
-
-(defmacro mail-extr-safe-move-sexp (arg)
- ;; Safely skip over one balanced sexp, if there is one. Return t if success.
- (` (condition-case error
- (progn
- (goto-char (or (scan-sexps (point) (, arg)) (point)))
- t)
- (error
- ;; #### kludge kludge kludge kludge kludge kludge kludge !!!
- (if (string-equal (nth 1 error) "Unbalanced parentheses")
- nil
- (while t
- (signal (car error) (cdr error))))))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; The main function to grind addresses
-;;
-
-(defvar disable-initial-guessing-flag) ; dynamic assignment
-(defvar cbeg) ; dynamic assignment
-(defvar cend) ; dynamic assignment
-
-;;;###autoload
-(defun mail-extract-address-components (address)
- "Given an RFC-822 ADDRESS, extract full name and canonical address.
-Returns a list of the form (FULL-NAME CANONICAL-ADDRESS).
-If no name can be extracted, FULL-NAME will be nil.
-ADDRESS may be a string or a buffer. If it is a buffer, the visible
- (narrowed) portion of the buffer will be interpreted as the address.
- (This feature exists so that the clever caller might be able to avoid
- consing a string.)
-If ADDRESS contains more than one RFC-822 address, only the first is
- returned. Some day this function may be extended to extract multiple
- addresses, or perhaps return the position at which parsing stopped."
- (let ((canonicalization-buffer (get-buffer-create " *canonical address*"))
- (extraction-buffer (get-buffer-create " *extract address components*"))
- char
-;; multiple-addresses
- <-pos >-pos @-pos :-pos comma-pos !-pos %-pos \;-pos
- group-:-pos group-\;-pos route-addr-:-pos
- record-pos-symbol
- first-real-pos last-real-pos
- phrase-beg phrase-end
- cbeg cend ; dynamically set from -voodoo
- quote-beg quote-end
- atom-beg atom-end
- mbox-beg mbox-end
- \.-ends-name
- temp
-;; name-suffix
- fi mi li ; first, middle, last initial
- saved-%-pos saved-!-pos saved-@-pos
- domain-pos \.-pos insert-point
-;; mailbox-name-processed-flag
- disable-initial-guessing-flag ; dynamically set from -voodoo
- )
-
- (save-excursion
- (set-buffer extraction-buffer)
- (fundamental-mode)
- (kill-all-local-variables)
- (buffer-disable-undo extraction-buffer)
- (set-syntax-table mail-extr-address-syntax-table)
- (widen)
- (erase-buffer)
- (setq case-fold-search nil)
-
- ;; Insert extra space at beginning to allow later replacement with <
- ;; without having to move markers.
- (insert ?\ )
-
- ;; Insert the address itself.
- (cond ((stringp address)
- (insert address))
- ((bufferp address)
- (insert-buffer-substring address))
- (t
- (error "Invalid address: %s" address)))
-
- (set-text-properties (point-min) (point-max) nil)
-
- ;; stolen from rfc822.el
- ;; Unfold multiple lines.
- (goto-char (point-min))
- (while (re-search-forward "\\([^\\]\\(\\\\\\\\\\)*\\)\n[ \t]" nil t)
- (replace-match "\\1 " t))
-
- ;; first pass grabs useful information about address
- (goto-char (point-min))
- (while (progn
- (mail-extr-skip-whitespace-forward)
- (not (eobp)))
- (setq char (char-after (point)))
- (or first-real-pos
- (if (not (eq char ?\())
- (setq first-real-pos (point))))
- (cond
- ;; comment
- ((eq char ?\()
- (set-syntax-table mail-extr-address-comment-syntax-table)
- ;; only record the first non-empty comment's position
- (if (and (not cbeg)
- (save-excursion
- (forward-char 1)
- (mail-extr-skip-whitespace-forward)
- (not (eq ?\) (char-after (point))))))
- (setq cbeg (point)))
- ;; TODO: don't record if unbalanced
- (or (mail-extr-safe-move-sexp 1)
- (forward-char 1))
- (set-syntax-table mail-extr-address-syntax-table)
- (if (and cbeg
- (not cend))
- (setq cend (point))))
- ;; quoted text
- ((eq char ?\")
- ;; only record the first non-empty quote's position
- (if (and (not quote-beg)
- (save-excursion
- (forward-char 1)
- (mail-extr-skip-whitespace-forward)
- (not (eq ?\" (char-after (point))))))
- (setq quote-beg (point)))
- ;; TODO: don't record if unbalanced
- (or (mail-extr-safe-move-sexp 1)
- (forward-char 1))
- (if (and quote-beg
- (not quote-end))
- (setq quote-end (point))))
- ;; domain literals
- ((eq char ?\[)
- (set-syntax-table mail-extr-address-domain-literal-syntax-table)
- (or (mail-extr-safe-move-sexp 1)
- (forward-char 1))
- (set-syntax-table mail-extr-address-syntax-table))
- ;; commas delimit addresses when outside < > pairs.
- ((and (eq char ?,)
- (or (and (null <-pos)
- ;; Handle ROUTE-ADDR address that is missing its <.
- (not (eq ?@ (char-after (1+ (point))))))
- (and >-pos
- ;; handle weird munged addresses
- ;; BUG FIX: This test was reversed. Thanks to the
- ;; brilliant Rod Whitby <rwhitby@research.canon.oz.au>
- ;; for discovering this!
- (< (mail-extr-last <-pos) (car >-pos)))))
-;; It'd be great if some day this worked, but for now, punt.
-;; (setq multiple-addresses t)
-;; ;; *** Why do I want this:
-;; (mail-extr-delete-char 1)
-;; (narrow-to-region (point-min) (point))
- (delete-region (point) (point-max))
- (setq char ?\() ; HAVE I NO SHAME??
- )
- ;; record the position of various interesting chars, determine
- ;; legality later.
- ((setq record-pos-symbol
- (cdr (assq char
- '((?< . <-pos) (?> . >-pos) (?@ . @-pos)
- (?: . :-pos) (?, . comma-pos) (?! . !-pos)
- (?% . %-pos) (?\; . \;-pos)))))
- (set record-pos-symbol
- (cons (point) (symbol-value record-pos-symbol)))
- (forward-char 1))
- ((eq char ?.)
- (forward-char 1))
- ((memq char '(
- ;; comment terminator illegal
- ?\)
- ;; domain literal terminator illegal
- ?\]
- ;; \ allowed only within quoted strings,
- ;; domain literals, and comments
- ?\\
- ))
- (mail-extr-nuke-char-at (point))
- (forward-char 1))
- (t
- (forward-word 1)))
- (or (eq char ?\()
- ;; At the end of first address of a multiple address header.
- (and (eq char ?,)
- (eobp))
- (setq last-real-pos (point))))
-
- ;; Use only the leftmost <, if any. Replace all others with spaces.
- (while (cdr <-pos)
- (mail-extr-nuke-char-at (car <-pos))
- (setq <-pos (cdr <-pos)))
-
- ;; Use only the rightmost >, if any. Replace all others with spaces.
- (while (cdr >-pos)
- (mail-extr-nuke-char-at (nth 1 >-pos))
- (setcdr >-pos (nthcdr 2 >-pos)))
-
- ;; If multiple @s and a :, but no < and >, insert around buffer.
- ;; Example: @foo.bar.dom,@xxx.yyy.zzz:mailbox@aaa.bbb.ccc
- ;; This commonly happens on the UUCP "From " line. Ugh.
- (cond ((and (> (length @-pos) 1)
- (eq 1 (length :-pos)) ;TODO: check if between last two @s
- (not \;-pos)
- (not <-pos))
- (goto-char (point-min))
- (mail-extr-delete-char 1)
- (setq <-pos (list (point)))
- (insert ?<)))
-
- ;; If < but no >, insert > in rightmost possible position
- (cond ((and <-pos
- (null >-pos))
- (goto-char (point-max))
- (setq >-pos (list (point)))
- (insert ?>)))
-
- ;; If > but no <, replace > with space.
- (cond ((and >-pos
- (null <-pos))
- (mail-extr-nuke-char-at (car >-pos))
- (setq >-pos nil)))
-
- ;; Turn >-pos and <-pos into non-lists
- (setq >-pos (car >-pos)
- <-pos (car <-pos))
-
- ;; Trim other punctuation lists of items outside < > pair to handle
- ;; stupid MTAs.
- (cond (<-pos ; don't need to check >-pos also
- ;; handle bozo software that violates RFC 822 by sticking
- ;; punctuation marks outside of a < > pair
- (mail-extr-nuke-outside-range @-pos <-pos >-pos t)
- ;; RFC 822 says nothing about these two outside < >, but
- ;; remove those positions from the lists to make things
- ;; easier.
- (mail-extr-nuke-outside-range !-pos <-pos >-pos t)
- (mail-extr-nuke-outside-range %-pos <-pos >-pos t)))
-
- ;; Check for : that indicates GROUP list and for : part of
- ;; ROUTE-ADDR spec.
- ;; Can't possibly be more than two :. Nuke any extra.
- (while :-pos
- (setq temp (car :-pos)
- :-pos (cdr :-pos))
- (cond ((and <-pos >-pos
- (> temp <-pos)
- (< temp >-pos))
- (if (or route-addr-:-pos
- (< (length @-pos) 2)
- (> temp (car @-pos))
- (< temp (nth 1 @-pos)))
- (mail-extr-nuke-char-at temp)
- (setq route-addr-:-pos temp)))
- ((or (not <-pos)
- (and <-pos
- (< temp <-pos)))
- (setq group-:-pos temp))))
-
- ;; Nuke any ; that is in or to the left of a < > pair or to the left
- ;; of a GROUP starting :. Also, there may only be one ;.
- (while \;-pos
- (setq temp (car \;-pos)
- \;-pos (cdr \;-pos))
- (cond ((and <-pos >-pos
- (> temp <-pos)
- (< temp >-pos))
- (mail-extr-nuke-char-at temp))
- ((and (or (not group-:-pos)
- (> temp group-:-pos))
- (not group-\;-pos))
- (setq group-\;-pos temp))))
-
- ;; Nuke unmatched GROUP syntax characters.
- (cond ((and group-:-pos (not group-\;-pos))
- ;; *** Do I really need to erase it?
- (mail-extr-nuke-char-at group-:-pos)
- (setq group-:-pos nil)))
- (cond ((and group-\;-pos (not group-:-pos))
- ;; *** Do I really need to erase it?
- (mail-extr-nuke-char-at group-\;-pos)
- (setq group-\;-pos nil)))
-
- ;; Handle junk like ";@host.company.dom" that sendmail adds.
- ;; **** should I remember comment positions?
- (cond
- (group-\;-pos
- ;; this is fine for now
- (mail-extr-nuke-outside-range !-pos group-:-pos group-\;-pos t)
- (mail-extr-nuke-outside-range @-pos group-:-pos group-\;-pos t)
- (mail-extr-nuke-outside-range %-pos group-:-pos group-\;-pos t)
- (mail-extr-nuke-outside-range comma-pos group-:-pos group-\;-pos t)
- (and last-real-pos
- (> last-real-pos (1+ group-\;-pos))
- (setq last-real-pos (1+ group-\;-pos)))
- ;; *** This may be wrong:
- (and cend
- (> cend group-\;-pos)
- (setq cend nil
- cbeg nil))
- (and quote-end
- (> quote-end group-\;-pos)
- (setq quote-end nil
- quote-beg nil))
- ;; This was both wrong and unnecessary:
- ;;(narrow-to-region (point-min) group-\;-pos)
-
- ;; *** The entire handling of GROUP addresses seems rather lame.
- ;; *** It deserves a complete rethink, except that these addresses
- ;; *** are hardly ever seen.
- ))
-
- ;; Any commas must be between < and : of ROUTE-ADDR. Nuke any
- ;; others.
- ;; Hell, go ahead an nuke all of the commas.
- ;; **** This will cause problems when we start handling commas in
- ;; the PHRASE part .... no it won't ... yes it will ... ?????
- (mail-extr-nuke-outside-range comma-pos 1 1)
-
- ;; can only have multiple @s inside < >. The fact that some MTAs
- ;; put de-bracketed ROUTE-ADDRs in the UUCP-style "From " line is
- ;; handled above.
-
- ;; Locate PHRASE part of ROUTE-ADDR.
- (cond (<-pos
- (goto-char <-pos)
- (mail-extr-skip-whitespace-backward)
- (setq phrase-end (point))
- (goto-char (or ;;group-:-pos
- (point-min)))
- (mail-extr-skip-whitespace-forward)
- (if (< (point) phrase-end)
- (setq phrase-beg (point))
- (setq phrase-end nil))))
-
- ;; handle ROUTE-ADDRS with real ROUTEs.
- ;; If there are multiple @s, then we assume ROUTE-ADDR syntax, and
- ;; any % or ! must be semantically meaningless.
- ;; TODO: do this processing into canonicalization buffer
- (cond (route-addr-:-pos
- (setq !-pos nil
- %-pos nil
- >-pos (copy-marker >-pos)
- route-addr-:-pos (copy-marker route-addr-:-pos))
- (goto-char >-pos)
- (insert-before-markers ?X)
- (goto-char (car @-pos))
- (while (setq @-pos (cdr @-pos))
- (mail-extr-delete-char 1)
- (setq %-pos (cons (point-marker) %-pos))
- (insert "%")
- (goto-char (1- >-pos))
- (save-excursion
- (insert-buffer-substring extraction-buffer
- (car @-pos) route-addr-:-pos)
- (delete-region (car @-pos) route-addr-:-pos))
- (or (cdr @-pos)
- (setq saved-@-pos (list (point)))))
- (setq @-pos saved-@-pos)
- (goto-char >-pos)
- (mail-extr-delete-char -1)
- (mail-extr-nuke-char-at route-addr-:-pos)
- (mail-extr-demarkerize route-addr-:-pos)
- (setq route-addr-:-pos nil
- >-pos (mail-extr-demarkerize >-pos)
- %-pos (mapcar 'mail-extr-demarkerize %-pos))))
-
- ;; de-listify @-pos
- (setq @-pos (car @-pos))
-
- ;; TODO: remove comments in the middle of an address
-
- (set-buffer canonicalization-buffer)
- (fundamental-mode)
- (kill-all-local-variables)
- (buffer-disable-undo canonicalization-buffer)
- (set-syntax-table mail-extr-address-syntax-table)
- (setq case-fold-search nil)
-
- (widen)
- (erase-buffer)
- (insert-buffer-substring extraction-buffer)
-
- (if <-pos
- (narrow-to-region (progn
- (goto-char (1+ <-pos))
- (mail-extr-skip-whitespace-forward)
- (point))
- >-pos)
- (if (and first-real-pos last-real-pos)
- (narrow-to-region first-real-pos last-real-pos)
- ;; ****** Oh no! What if the address is completely empty!
- ;; *** Is this correct?
- (narrow-to-region (point-max) (point-max))
- ))
-
- (and @-pos %-pos
- (mail-extr-nuke-outside-range %-pos (point-min) @-pos))
- (and %-pos !-pos
- (mail-extr-nuke-outside-range !-pos (point-min) (car %-pos)))
- (and @-pos !-pos (not %-pos)
- (mail-extr-nuke-outside-range !-pos (point-min) @-pos))
-
- ;; Error condition:?? (and %-pos (not @-pos))
-
- ;; WARNING: THIS CODE IS DUPLICATED BELOW.
- (cond ((and %-pos
- (not @-pos))
- (goto-char (car %-pos))
- (mail-extr-delete-char 1)
- (setq @-pos (point))
- (insert "@")
- (setq %-pos (cdr %-pos))))
-
- (if mail-extr-mangle-uucp
- (cond (!-pos
- ;; **** I don't understand this save-restriction and the
- ;; narrow-to-region inside it. Why did I do that?
- (save-restriction
- (cond ((and @-pos
- mail-extr-@-binds-tighter-than-!)
- (goto-char @-pos)
- (setq %-pos (cons (point) %-pos)
- @-pos nil)
- (mail-extr-delete-char 1)
- (insert "%")
- (setq insert-point (point-max)))
- (mail-extr-@-binds-tighter-than-!
- (setq insert-point (point-max)))
- (%-pos
- (setq insert-point (mail-extr-last %-pos)
- saved-%-pos (mapcar 'mail-extr-markerize %-pos)
- %-pos nil
- @-pos (mail-extr-markerize @-pos)))
- (@-pos
- (setq insert-point @-pos)
- (setq @-pos (mail-extr-markerize @-pos)))
- (t
- (setq insert-point (point-max))))
- (narrow-to-region (point-min) insert-point)
- (setq saved-!-pos (car !-pos))
- (while !-pos
- (goto-char (point-max))
- (cond ((and (not @-pos)
- (not (cdr !-pos)))
- (setq @-pos (point))
- (insert-before-markers "@ "))
- (t
- (setq %-pos (cons (point) %-pos))
- (insert-before-markers "% ")))
- (backward-char 1)
- (insert-buffer-substring
- (current-buffer)
- (if (nth 1 !-pos)
- (1+ (nth 1 !-pos))
- (point-min))
- (car !-pos))
- (mail-extr-delete-char 1)
- (or (save-excursion
- (mail-extr-safe-move-sexp -1)
- (mail-extr-skip-whitespace-backward)
- (eq ?. (preceding-char)))
- (insert-before-markers
- (if (save-excursion
- (mail-extr-skip-whitespace-backward)
- (eq ?. (preceding-char)))
- ""
- ".")
- "uucp"))
- (setq !-pos (cdr !-pos))))
- (and saved-%-pos
- (setq %-pos (append (mapcar 'mail-extr-demarkerize
- saved-%-pos)
- %-pos)))
- (setq @-pos (mail-extr-demarkerize @-pos))
- (narrow-to-region (1+ saved-!-pos) (point-max)))))
-
- ;; WARNING: THIS CODE IS DUPLICATED ABOVE.
- (cond ((and %-pos
- (not @-pos))
- (goto-char (car %-pos))
- (mail-extr-delete-char 1)
- (setq @-pos (point))
- (insert "@")
- (setq %-pos (cdr %-pos))))
-
- (setq %-pos (nreverse %-pos))
- (cond (%-pos ; implies @-pos valid
- (setq temp %-pos)
- (catch 'truncated
- (while temp
- (goto-char (or (nth 1 temp)
- @-pos))
- (mail-extr-skip-whitespace-backward)
- (save-excursion
- (mail-extr-safe-move-sexp -1)
- (setq domain-pos (point))
- (mail-extr-skip-whitespace-backward)
- (setq \.-pos (eq ?. (preceding-char))))
- (cond ((and \.-pos
- ;; #### string consing
- (let ((s (intern-soft
- (buffer-substring domain-pos (point))
- mail-extr-all-top-level-domains)))
- (and s (get s 'domain-name))))
- (narrow-to-region (point-min) (point))
- (goto-char (car temp))
- (mail-extr-delete-char 1)
- (setq @-pos (point))
- (setcdr temp nil)
- (setq %-pos (delq @-pos %-pos))
- (insert "@")
- (throw 'truncated t)))
- (setq temp (cdr temp))))))
- (setq mbox-beg (point-min)
- mbox-end (if %-pos (car %-pos)
- (or @-pos
- (point-max))))
-
- ;; Done canonicalizing address.
-
- (set-buffer extraction-buffer)
-
- ;; Decide what part of the address to search to find the full name.
- (cond (
- ;; Example: "First M. Last" <fml@foo.bar.dom>
- (and phrase-beg
- (eq quote-beg phrase-beg)
- (<= quote-end phrase-end))
- (narrow-to-region (1+ quote-beg) (1- quote-end))
- (mail-extr-undo-backslash-quoting (point-min) (point-max)))
-
- ;; Example: First Last <fml@foo.bar.dom>
- (phrase-beg
- (narrow-to-region phrase-beg phrase-end))
-
- ;; Example: fml@foo.bar.dom (First M. Last)
- (cbeg
- (narrow-to-region (1+ cbeg) (1- cend))
- (mail-extr-undo-backslash-quoting (point-min) (point-max))
-
- ;; Deal with spacing problems
- (goto-char (point-min))
-; (cond ((not (search-forward " " nil t))
-; (goto-char (point-min))
-; (cond ((search-forward "_" nil t)
-; ;; Handle the *idiotic* use of underlines as spaces.
-; ;; Example: fml@foo.bar.dom (First_M._Last)
-; (goto-char (point-min))
-; (while (search-forward "_" nil t)
-; (replace-match " " t)))
-; ((search-forward "." nil t)
-; ;; Fix . used as space
-; ;; Example: danj1@cb.att.com (daniel.jacobson)
-; (goto-char (point-min))
-; (while (re-search-forward mail-extr-bad-dot-pattern nil t)
-; (replace-match "\\1 \\2" t))))))
- )
-
- ;; Otherwise we try to get the name from the mailbox portion
- ;; of the address.
- ;; Example: First_M_Last@foo.bar.dom
- (t
- ;; *** Work in canon buffer instead? No, can't. Hmm.
- (goto-char (point-max))
- (narrow-to-region (point) (point))
- (insert-buffer-substring canonicalization-buffer
- mbox-beg mbox-end)
- (goto-char (point-min))
-
- ;; Example: First_Last.XXX@foo.bar.dom
- (setq \.-ends-name (re-search-forward "[_0-9]" nil t))
-
- (goto-char (point-min))
-
- (if (not mail-extr-mangle-uucp)
- (modify-syntax-entry ?! "w" (syntax-table)))
-
- (while (progn
- (mail-extr-skip-whitespace-forward)
- (not (eobp)))
- (setq char (char-after (point)))
- (cond
- ((eq char ?\")
- (setq quote-beg (point))
- (or (mail-extr-safe-move-sexp 1)
- ;; TODO: handle this error condition!!!!!
- (forward-char 1))
- ;; take into account deletions
- (setq quote-end (- (point) 2))
- (save-excursion
- (backward-char 1)
- (mail-extr-delete-char 1)
- (goto-char quote-beg)
- (or (eobp)
- (mail-extr-delete-char 1)))
- (mail-extr-undo-backslash-quoting quote-beg quote-end)
- (or (eq ?\ (char-after (point)))
- (insert " "))
-;; (setq mailbox-name-processed-flag t)
- (setq \.-ends-name t))
- ((eq char ?.)
- (if (memq (char-after (1+ (point))) '(?_ ?=))
- (progn
- (forward-char 1)
- (mail-extr-delete-char 1)
- (insert ?\ ))
- (if \.-ends-name
- (narrow-to-region (point-min) (point))
- (mail-extr-delete-char 1)
- (insert " ")))
-;; (setq mailbox-name-processed-flag t)
- )
- ((memq (char-syntax char) '(?. ?\\))
- (mail-extr-delete-char 1)
- (insert " ")
-;; (setq mailbox-name-processed-flag t)
- )
- (t
- (setq atom-beg (point))
- (forward-word 1)
- (setq atom-end (point))
- (goto-char atom-beg)
- (save-restriction
- (narrow-to-region atom-beg atom-end)
- (cond
-
- ;; Handle X.400 addresses encoded in RFC-822.
- ;; *** This has to handle the case where it is
- ;; *** embedded in a quote too!
- ;; *** The input is being broken up into atoms
- ;; *** by periods!
- ((looking-at mail-extr-x400-encoded-address-pattern)
-
- ;; Copy the contents of the individual fields that
- ;; might hold name data to the beginning.
- (mapcar
- (function
- (lambda (field-pattern)
- (cond
- ((save-excursion
- (re-search-forward field-pattern nil t))
- (insert-buffer-substring (current-buffer)
- (match-beginning 1)
- (match-end 1))
- (insert " ")))))
- (list mail-extr-x400-encoded-address-given-name-pattern
- mail-extr-x400-encoded-address-surname-pattern
- mail-extr-x400-encoded-address-full-name-pattern))
-
- ;; Discard the rest, since it contains stuff like
- ;; routing information, not part of a name.
- (mail-extr-skip-whitespace-backward)
- (delete-region (point) (point-max))
-
- ;; Handle periods used for spacing.
- (while (re-search-forward mail-extr-bad-dot-pattern nil t)
- (replace-match "\\1 \\2" t))
-
-;; (setq mailbox-name-processed-flag t)
- )
-
- ;; Handle normal addresses.
- (t
- (goto-char (point-min))
- ;; Handle _ and = used for spacing.
- (while (re-search-forward "\\([^_=]+\\)[_=]" nil t)
- (replace-match "\\1 " t)
-;; (setq mailbox-name-processed-flag t)
- )
- (goto-char (point-max))))))))
-
- ;; undo the dirty deed
- (if (not mail-extr-mangle-uucp)
- (modify-syntax-entry ?! "." (syntax-table)))
- ;;
- ;; If we derived the name from the mailbox part of the address,
- ;; and we only got one word out of it, don't treat that as a
- ;; name. "foo@bar" --> (nil "foo@bar"), not ("foo" "foo@bar")
- ;; (if (not mailbox-name-processed-flag)
- ;; (delete-region (point-min) (point-max)))
- ))
-
- (set-syntax-table mail-extr-address-text-syntax-table)
-
- (mail-extr-voodoo mbox-beg mbox-end canonicalization-buffer)
- (goto-char (point-min))
-
- ;; If name is "First Last" and userid is "F?L", then assume
- ;; the middle initial is the second letter in the userid.
- ;; Initial code by Jamie Zawinski <jwz@lucid.com>
- ;; *** Make it work when there's a suffix as well.
- (goto-char (point-min))
- (cond ((and mail-extr-guess-middle-initial
- (not disable-initial-guessing-flag)
- (eq 3 (- mbox-end mbox-beg))
- (progn
- (goto-char (point-min))
- (looking-at mail-extr-two-name-pattern)))
- (setq fi (char-after (match-beginning 0))
- li (char-after (match-beginning 3)))
- (save-excursion
- (set-buffer canonicalization-buffer)
- ;; char-equal is ignoring case here, so no need to upcase
- ;; or downcase.
- (let ((case-fold-search t))
- (and (char-equal fi (char-after mbox-beg))
- (char-equal li (char-after (1- mbox-end)))
- (setq mi (char-after (1+ mbox-beg))))))
- (cond ((and mi
- ;; TODO: use better table than syntax table
- (eq ?w (char-syntax mi)))
- (goto-char (match-beginning 3))
- (insert (upcase mi) ". ")))))
-
- ;; Nuke name if it is the same as mailbox name.
- (let ((buffer-length (- (point-max) (point-min)))
- (i 0)
- (names-match-flag t))
- (cond ((and (> buffer-length 0)
- (eq buffer-length (- mbox-end mbox-beg)))
- (goto-char (point-max))
- (insert-buffer-substring canonicalization-buffer
- mbox-beg mbox-end)
- (while (and names-match-flag
- (< i buffer-length))
- (or (eq (downcase (char-after (+ i (point-min))))
- (downcase
- (char-after (+ i buffer-length (point-min)))))
- (setq names-match-flag nil))
- (setq i (1+ i)))
- (delete-region (+ (point-min) buffer-length) (point-max))
- (if names-match-flag
- (narrow-to-region (point) (point))))))
-
- ;; Nuke name if it's just one word.
- (goto-char (point-min))
- (and mail-extr-ignore-single-names
- (not (re-search-forward "[- ]" nil t))
- (narrow-to-region (point) (point)))
-
- ;; Result
- (list (if (not (= (point-min) (point-max)))
- (buffer-string))
- (progn
- (set-buffer canonicalization-buffer)
- (if (not (= (point-min) (point-max)))
- (buffer-string))))
- )))
-
-(defun mail-extr-voodoo (mbox-beg mbox-end canonicalization-buffer)
- (let ((word-count 0)
- (case-fold-search nil)
- mixed-case-flag lower-case-flag ;;upper-case-flag
- suffix-flag last-name-comma-flag
- ;;cbeg cend
- initial
- begin-again-flag
- drop-this-word-if-trailing-flag
- drop-last-word-if-trailing-flag
- word-found-flag
- this-word-beg last-word-beg
- name-beg name-end
- name-done-flag
- )
- (save-excursion
- (set-syntax-table mail-extr-address-text-syntax-table)
-
- ;; This was moved above.
- ;; Fix . used as space
- ;; But it belongs here because it occurs not only as
- ;; rypens@reks.uia.ac.be (Piet.Rypens)
- ;; but also as
- ;; "Piet.Rypens" <rypens@reks.uia.ac.be>
- ;;(goto-char (point-min))
- ;;(while (re-search-forward mail-extr-bad-dot-pattern nil t)
- ;; (replace-match "\\1 \\2" t))
-
- (cond ((not (search-forward " " nil t))
- (goto-char (point-min))
- (cond ((search-forward "_" nil t)
- ;; Handle the *idiotic* use of underlines as spaces.
- ;; Example: fml@foo.bar.dom (First_M._Last)
- (goto-char (point-min))
- (while (search-forward "_" nil t)
- (replace-match " " t)))
- ((search-forward "." nil t)
- ;; Fix . used as space
- ;; Example: danj1@cb.att.com (daniel.jacobson)
- (goto-char (point-min))
- (while (re-search-forward mail-extr-bad-dot-pattern nil t)
- (replace-match "\\1 \\2" t))))))
-
-
- ;; Loop over the words (and other junk) in the name.
- (goto-char (point-min))
- (while (not name-done-flag)
-
- (cond (word-found-flag
- ;; Last time through this loop we skipped over a word.
- (setq last-word-beg this-word-beg)
- (setq drop-last-word-if-trailing-flag
- drop-this-word-if-trailing-flag)
- (setq word-found-flag nil)))
-
- (cond (begin-again-flag
- ;; Last time through the loop we found something that
- ;; indicates we should pretend we are beginning again from
- ;; the start.
- (setq word-count 0)
- (setq last-word-beg nil)
- (setq drop-last-word-if-trailing-flag nil)
- (setq mixed-case-flag nil)
- (setq lower-case-flag nil)
-;; (setq upper-case-flag nil)
- (setq begin-again-flag nil)
- ))
-
- ;; Initialize for this iteration of the loop.
- (mail-extr-skip-whitespace-forward)
- (if (eq word-count 0) (narrow-to-region (point) (point-max)))
- (setq this-word-beg (point))
- (setq drop-this-word-if-trailing-flag nil)
-
- ;; Decide what to do based on what we are looking at.
- (cond
-
- ;; Delete title
- ((and (eq word-count 0)
- (looking-at mail-extr-full-name-prefixes))
- (goto-char (match-end 0))
- (narrow-to-region (point) (point-max)))
-
- ;; Stop after name suffix
- ((and (>= word-count 2)
- (looking-at mail-extr-full-name-suffix-pattern))
- (mail-extr-skip-whitespace-backward)
- (setq suffix-flag (point))
- (if (eq ?, (following-char))
- (forward-char 1)
- (insert ?,))
- ;; Enforce at least one space after comma
- (or (eq ?\ (following-char))
- (insert ?\ ))
- (mail-extr-skip-whitespace-forward)
- (cond ((memq (following-char) '(?j ?J ?s ?S))
- (capitalize-word 1)
- (if (eq (following-char) ?.)
- (forward-char 1)
- (insert ?.)))
- (t
- (upcase-word 1)))
- (setq word-found-flag t)
- (setq name-done-flag t))
-
- ;; Handle SCA names
- ((looking-at "MKA \\(.+\\)") ; "Mundanely Known As"
- (goto-char (match-beginning 1))
- (narrow-to-region (point) (point-max))
- (setq begin-again-flag t))
-
- ;; Check for initial last name followed by comma
- ((and (eq ?, (following-char))
- (eq word-count 1))
- (forward-char 1)
- (setq last-name-comma-flag t)
- (or (eq ?\ (following-char))
- (insert ?\ )))
-
- ;; Stop before trailing comma-separated comment
- ;; THIS CASE MUST BE AFTER THE PRECEDING CASES.
- ;; *** This case is redundant???
- ;;((eq ?, (following-char))
- ;; (setq name-done-flag t))
-
- ;; Delete parenthesized/quoted comment/nickname
- ((memq (following-char) '(?\( ?\{ ?\[ ?\" ?\' ?\`))
- (setq cbeg (point))
- (set-syntax-table mail-extr-address-text-comment-syntax-table)
- (cond ((memq (following-char) '(?\' ?\`))
- (or (search-forward "'" nil t
- (if (eq ?\' (following-char)) 2 1))
- (mail-extr-delete-char 1)))
- (t
- (or (mail-extr-safe-move-sexp 1)
- (goto-char (point-max)))))
- (set-syntax-table mail-extr-address-text-syntax-table)
- (setq cend (point))
- (cond
- ;; Handle case of entire name being quoted
- ((and (eq word-count 0)
- (looking-at " *\\'")
- (>= (- cend cbeg) 2))
- (narrow-to-region (1+ cbeg) (1- cend))
- (goto-char (point-min)))
- (t
- ;; Handle case of quoted initial
- (if (and (or (= 3 (- cend cbeg))
- (and (= 4 (- cend cbeg))
- (eq ?. (char-after (+ 2 cbeg)))))
- (not (looking-at " *\\'")))
- (setq initial (char-after (1+ cbeg)))
- (setq initial nil))
- (delete-region cbeg cend)
- (if initial
- (insert initial ". ")))))
-
- ;; Handle & substitution
- ((and (or (bobp)
- (eq ?\ (preceding-char)))
- (looking-at "&\\( \\|\\'\\)"))
- (mail-extr-delete-char 1)
- (capitalize-region
- (point)
- (progn
- (insert-buffer-substring canonicalization-buffer
- mbox-beg mbox-end)
- (point)))
- (setq disable-initial-guessing-flag t)
- (setq word-found-flag t))
-
- ;; Handle *Stupid* VMS date stamps
- ((looking-at mail-extr-stupid-vms-date-stamp-pattern)
- (replace-match "" t))
-
- ;; Handle Chinese characters.
- ((looking-at mail-extr-hz-embedded-gb-encoded-chinese-pattern)
- (goto-char (match-end 0))
- (setq word-found-flag t))
-
- ;; Skip initial garbage characters.
- ;; THIS CASE MUST BE AFTER THE PRECEDING CASES.
- ((and (eq word-count 0)
- (looking-at mail-extr-leading-garbage))
- (goto-char (match-end 0))
- ;; *** Skip backward over these???
- ;; (skip-chars-backward "& \"")
- (narrow-to-region (point) (point-max)))
-
- ;; Various stopping points
- ((or
-
- ;; Stop before ALL CAPS acronyms, if preceded by mixed-case
- ;; words. Example: XT-DEM.
- (and (>= word-count 2)
- mixed-case-flag
- (looking-at mail-extr-weird-acronym-pattern)
- (not (looking-at mail-extr-roman-numeral-pattern)))
-
- ;; Stop before trailing alternative address
- (looking-at mail-extr-alternative-address-pattern)
-
- ;; Stop before trailing comment not introduced by comma
- ;; THIS CASE MUST BE AFTER AN EARLIER CASE.
- (looking-at mail-extr-trailing-comment-start-pattern)
-
- ;; Stop before telephone numbers
- (looking-at mail-extr-telephone-extension-pattern))
- (setq name-done-flag t))
-
- ;; Delete ham radio call signs
- ((looking-at mail-extr-ham-call-sign-pattern)
- (delete-region (match-beginning 0) (match-end 0)))
-
- ;; Fixup initials
- ((looking-at mail-extr-initial-pattern)
- (or (eq (following-char) (upcase (following-char)))
- (setq lower-case-flag t))
- (forward-char 1)
- (if (eq ?. (following-char))
- (forward-char 1)
- (insert ?.))
- (or (eq ?\ (following-char))
- (insert ?\ ))
- (setq word-found-flag t))
-
- ;; Handle BITNET LISTSERV list names.
- ((and (eq word-count 0)
- (looking-at mail-extr-listserv-list-name-pattern))
- (narrow-to-region (match-beginning 1) (match-end 1))
- (setq word-found-flag t)
- (setq name-done-flag t))
-
- ;; Regular name words
- ((looking-at mail-extr-name-pattern)
- (setq name-beg (point))
- (setq name-end (match-end 0))
-
- ;; Certain words will be dropped if they are at the end.
- (and (>= word-count 2)
- (not lower-case-flag)
- (or
- ;; A trailing 4-or-more letter lowercase words preceded by
- ;; mixed case or uppercase words will be dropped.
- (looking-at "[a-z][a-z][a-z][a-z]+[ \t]*\\'")
- ;; Drop a trailing word which is terminated with a period.
- (eq ?. (char-after (1- name-end))))
- (setq drop-this-word-if-trailing-flag t))
-
- ;; Set the flags that indicate whether we have seen a lowercase
- ;; word, a mixed case word, and an uppercase word.
- (if (re-search-forward "[a-z]" name-end t)
- (if (progn
- (goto-char name-beg)
- (re-search-forward "[A-Z]" name-end t))
- (setq mixed-case-flag t)
- (setq lower-case-flag t))
-;; (setq upper-case-flag t)
- )
-
- (goto-char name-end)
- (setq word-found-flag t))
-
- (t
- (setq name-done-flag t)
- ))
-
- ;; Count any word that we skipped over.
- (if word-found-flag
- (setq word-count (1+ word-count))))
-
- ;; If the last thing in the name is 2 or more periods, or one or more
- ;; other sentence terminators (but not a single period) then keep them
- ;; and the preceding word. This is for the benefit of whole sentences
- ;; in the name field: it's better behavior than dropping the last word
- ;; of the sentence...
- (if (and (not suffix-flag)
- (looking-at "\\(\\.+\\|[?!;:.][?!;:.]+\\|[?!;:][?!;:.]*\\)\\'"))
- (goto-char (setq suffix-flag (point-max))))
-
- ;; Drop everything after point and certain trailing words.
- (narrow-to-region (point-min)
- (or (and drop-last-word-if-trailing-flag
- last-word-beg)
- (point)))
-
- ;; Xerox's mailers SUCK!!!!!!
- ;; We simply refuse to believe that any last name is PARC or ADOC.
- ;; If it looks like that is the last name, that there is no meaningful
- ;; here at all. Actually I guess it would be best to map patterns
- ;; like foo.hoser@xerox.com into foo@hoser.xerox.com, but I don't
- ;; actually know that that is what's going on.
- (cond ((not suffix-flag)
- (goto-char (point-min))
- (let ((case-fold-search t))
- (if (looking-at "[-A-Za-z_]+[. ]\\(PARC\\|ADOC\\)\\'")
- (erase-buffer)))))
-
- ;; If last name first put it at end (but before suffix)
- (cond (last-name-comma-flag
- (goto-char (point-min))
- (search-forward ",")
- (setq name-end (1- (point)))
- (goto-char (or suffix-flag (point-max)))
- (or (eq ?\ (preceding-char))
- (insert ?\ ))
- (insert-buffer-substring (current-buffer) (point-min) name-end)
- (goto-char name-end)
- (skip-chars-forward "\t ,")
- (narrow-to-region (point) (point-max))))
-
- ;; Delete leading and trailing junk characters.
- ;; *** This is probably completely unneeded now.
- ;;(goto-char (point-max))
- ;;(skip-chars-backward mail-extr-non-end-name-chars)
- ;;(if (eq ?. (following-char))
- ;; (forward-char 1))
- ;;(narrow-to-region (point)
- ;; (progn
- ;; (goto-char (point-min))
- ;; (skip-chars-forward mail-extr-non-begin-name-chars)
- ;; (point)))
-
- ;; Compress whitespace
- (goto-char (point-min))
- (while (re-search-forward "[ \t\n]+" nil t)
- (replace-match (if (eobp) "" " ") t))
- )))
-
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; Table of top-level domain names.
-;;
-;; This is used during address canonicalization; be careful of format changes.
-;; Keep in mind that the country abbreviations follow ISO-3166. There is
-;; a U.S. FIPS that specifies a different set of two-letter country
-;; abbreviations.
-
-(defconst mail-extr-all-top-level-domains
- (let ((ob (make-vector 509 0)))
- (mapcar
- (function
- (lambda (x)
- (put (intern (downcase (car x)) ob)
- 'domain-name
- (if (nth 2 x)
- (format (nth 2 x) (nth 1 x))
- (nth 1 x)))))
- '(
- ;; ISO 3166 codes:
- ("ae" "United Arab Emirates")
- ("ag" "Antigua and Barbuda")
- ("al" "Albania")
- ("ao" "Angola")
- ("aq" "Antarctica") ; continent
- ("ar" "Argentina" "Argentine Republic")
- ("at" "Austria" "The Republic of %s")
- ("au" "Australia")
- ("az" "Azerbaijan")
- ("bb" "Barbados")
- ("bd" "Bangladesh")
- ("be" "Belgium" "The Kingdom of %s")
- ("bf" "Burkina Faso")
- ("bg" "Bulgaria")
- ("bh" "Bahrain")
- ("bm" "Bermuda")
- ("bo" "Bolivia" "Republic of %s")
- ("br" "Brazil" "The Federative Republic of %s")
- ("bs" "Bahamas")
- ("bw" "Botswana")
- ("by" "Belarus")
- ("bz" "Belize")
- ("ca" "Canada")
- ("cg" "Congo")
- ("ch" "Switzerland" "The Swiss Confederation")
- ("ci" "Ivory Coast")
- ("cl" "Chile" "The Republic of %s")
- ("cm" "Cameroon") ; In .fr domain
- ("cn" "China" "The People's Republic of %s")
- ("co" "Colombia")
- ("cr" "Costa Rica" "The Republic of %s")
- ("cs" "Czechoslovakia")
- ("cu" "Cuba")
- ("cy" "Cyprus")
- ("cz" "Czech Republic")
- ("de" "Germany")
- ("dk" "Denmark")
- ("dm" "Dominica")
- ("do" "Dominican Republic" "The %s")
- ("dz" "Algeria")
- ("ec" "Ecuador" "The Republic of %s")
- ("ee" "Estonia")
- ("eg" "Egypt" "The Arab Republic of %s")
- ("er" "Eritrea")
- ("es" "Spain" "The Kingdom of %s")
- ("fi" "Finland" "The Republic of %s")
- ("fj" "Fiji")
- ("fo" "Faroe Islands")
- ("fr" "France")
- ("gb" "Great Britain")
- ("gd" "Grenada")
- ("ge" "Georgia")
- ("gf" "Guyana (Fr.)")
- ("gp" "Guadeloupe (Fr.)")
- ("gr" "Greece" "The Hellenic Republic (%s)")
- ("gt" "Guatemala")
- ("gu" "Guam (U.S.)")
- ("hk" "Hong Kong")
- ("hn" "Honduras")
- ("hr" "Croatia")
- ("ht" "Haiti")
- ("hu" "Hungary" "The Hungarian Republic") ;???
- ("id" "Indonesia")
- ("ie" "Ireland")
- ("il" "Israel" "The State of %s")
- ("in" "India" "The Republic of %s")
- ("ir" "Iran")
- ("is" "Iceland" "The Republic of %s")
- ("it" "Italy" "The Italian Republic")
- ("jm" "Jamaica")
- ("jp" "Japan")
- ("ke" "Kenya")
- ("kn" "St. Kitts, Nevis, and Anguilla")
- ("kp" "Korea (North)")
- ("kr" "Korea (South)")
- ("kw" "Kuwait")
- ("kz" "Kazakhstan")
- ("lb" "Lebanon")
- ("lc" "St. Lucia")
- ("li" "Liechtenstein")
- ("lk" "Sri Lanka" "The Democratic Socialist Republic of %s")
- ("ls" "Lesotho")
- ("lt" "Lithuania")
- ("lu" "Luxembourg")
- ("lv" "Latvia")
- ("ma" "Morocco")
- ("md" "Moldova")
- ("mg" "Madagascar")
- ("mk" "Macedonia")
- ("ml" "Mali")
- ("mo" "Macau")
- ("mt" "Malta")
- ("mu" "Mauritius")
- ("mw" "Malawi")
- ("mx" "Mexico" "The United Mexican States")
- ("my" "Malaysia" "%s (changed to Myanmar?)") ;???
- ("mz" "Mozambique")
- ("na" "Namibia")
- ("nc" "New Caledonia (Fr.)")
- ("ne" "Niger") ; In .fr domain
- ("ni" "Nicaragua" "The Republic of %s")
- ("nl" "Netherlands" "The Kingdom of the %s")
- ("no" "Norway" "The Kingdom of %s")
- ("np" "Nepal") ; Via .in domain
- ("nz" "New Zealand")
- ("pa" "Panama")
- ("pe" "Peru")
- ("pf" "Polynesia (Fr.)")
- ("pg" "Papua New Guinea")
- ("ph" "Philippines" "The Republic of the %s")
- ("pk" "Pakistan")
- ("pl" "Poland")
- ("pr" "Puerto Rico (U.S.)")
- ("pt" "Portugal" "The Portuguese Republic")
- ("py" "Paraguay")
- ("re" "Reunion (Fr.)") ; In .fr domain
- ("ro" "Romania")
- ("ru" "Russian Federation")
- ("sa" "Saudi Arabia")
- ("sc" "Seychelles")
- ("sd" "Sudan")
- ("se" "Sweden" "The Kingdom of %s")
- ("sg" "Singapore" "The Republic of %s")
- ("si" "Slovenia")
- ("sj" "Svalbard and Jan Mayen Is.") ; In .no domain
- ("sk" "Slovakia" "The Slovak Republic")
- ("sn" "Senegal")
- ("sr" "Suriname")
- ("su" "Soviet Union")
- ("sz" "Swaziland")
- ("tg" "Togo")
- ("th" "Thailand" "The Kingdom of %s")
- ("tm" "Turkmenistan") ; In .su domain
- ("tn" "Tunisia")
- ("tr" "Turkey" "The Republic of %s")
- ("tt" "Trinidad and Tobago")
- ("tw" "Taiwan")
- ("ua" "Ukraine")
- ("uk" "United Kingdom" "The %s of Great Britain and Northern Ireland")
- ("us" "United States" "The %s of America")
- ("uy" "Uruguay" "The Eastern Republic of %s")
- ("vc" "St. Vincent and the Grenadines")
- ("ve" "Venezuela" "The Republic of %s")
- ("vi" "Virgin Islands (U.S.)")
- ("vn" "Vietnam")
- ("vu" "Vanuatu")
- ("yu" "Yugoslavia" "The Socialist Federal Republic of %s")
- ("za" "South Africa" "The Republic of %s (or Zambia? Zaire?)")
- ("zw" "Zimbabwe" "Republic of %s")
- ;; Special top-level domains:
- ("arpa" t "Advanced Research Projects Agency (U.S. DoD)")
- ("bitnet" t "Because It's Time NET")
- ("com" t "Commercial")
- ("edu" t "Educational")
- ("gov" t "Government (U.S.)")
- ("int" t "International (NATO)")
- ("mil" t "Military (U.S.)")
- ("nato" t "North Atlantic Treaty Organization")
- ("net" t "Network")
- ("org" t "Non-profit Organization")
- ;;("unter-dom" t "? (Ger.)")
- ("uucp" t "Unix to Unix CoPy")
- ;;("fipnet" nil "?")
- ))
- ob))
-
-;;;###autoload
-(defun what-domain (domain)
- "Convert mail domain DOMAIN to the country it corresponds to."
- (interactive
- (let ((completion-ignore-case t))
- (list (completing-read "Domain: "
- mail-extr-all-top-level-domains nil t))))
- (or (setq domain (intern-soft (downcase domain)
- mail-extr-all-top-level-domains))
- (error "No such domain"))
- (message "%s: %s" (upcase (symbol-name domain)) (get domain 'domain-name)))
-
-
-;(let ((all nil))
-; (mapatoms #'(lambda (x)
-; (if (and (boundp x)
-; (string-match "^mail-extr-" (symbol-name x)))
-; (setq all (cons x all)))))
-; (setq all (sort all #'string-lessp))
-; (cons 'setq
-; (apply 'nconc (mapcar #'(lambda (x)
-; (list x (symbol-value x)))
-; all))))
-
-
-(provide 'mail-extr)
-
-;;; mail-extr.el ends here
diff --git a/lisp/mail/mail-hist.el b/lisp/mail/mail-hist.el
deleted file mode 100644
index 893ce40ddb7..00000000000
--- a/lisp/mail/mail-hist.el
+++ /dev/null
@@ -1,302 +0,0 @@
-;;; mail-hist.el --- Headers and message body history for outgoing mail.
-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-
-;; Author: Karl Fogel <kfogel@cs.oberlin.edu>
-;; Created: March, 1994
-;; Keywords: mail, history
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Thanks to Jim Blandy for mentioning ring.el. It saved a lot of
-;; time.
-;;
-;; To use this package, put it in a directory in your load-path, and
-;; put this in your .emacs file:
-;;
-;; (load "mail-hist" nil t)
-;;
-;; Or you could do it with autoloads and hooks in your .emacs:
-;;
-;; (add-hook 'mail-mode-hook 'mail-hist-define-keys)
-;; (add-hook 'mail-send-hook 'mail-hist-put-headers-into-history)
-;; (add-hook 'vm-mail-mode-hook 'mail-hist-define-keys) ;or rmail, etc
-;; (autoload 'mail-hist-define-keys "mail-hist")
-;; (autoload 'mail-hist-put-headers-into-history "mail-hist")
-;;
-;; Once it's installed, use M-p and M-n from mail headers to recover
-;; previous/next contents in the history for that header, or, in the
-;; body of the message, to recover previous/next text of the message.
-;; This only applies to outgoing mail -- mail-hist ignores received
-;; messages.
-;;
-;; Although repeated history requests do clear out the text from the
-;; previous request, an isolated request just inserts its text at
-;; point, so that you can mix the histories of different messages
-;; easily. This might be confusing at times, but there should be no
-;; problems that undo can't handle.
-
-;;; Code:
-(require 'ring)
-
-;;;###autoload
-(defun mail-hist-define-keys ()
- "Define keys for accessing mail header history. For use in hooks."
- (local-set-key "\M-p" 'mail-hist-previous-input)
- (local-set-key "\M-n" 'mail-hist-next-input))
-
-;;;###autoload
-(defun mail-hist-enable ()
- (add-hook 'mail-mode-hook 'mail-hist-define-keys)
- (add-hook 'mail-send-hook 'mail-hist-put-headers-into-history))
-
-(defvar mail-hist-header-ring-alist nil
- "Alist of form (header-name . history-ring).
-Used for knowing which history list to look in when the user asks for
-previous/next input.")
-
-(defvar mail-hist-history-size (or kill-ring-max 1729)
- "*The maximum number of elements in a mail field's history.
-Oldest elements are dumped first.")
-
-;;;###autoload
-(defvar mail-hist-keep-history t
- "*Non-nil means keep a history for headers and text of outgoing mail.")
-
-;; For handling repeated history requests
-(defvar mail-hist-access-count 0)
-
-(defvar mail-hist-last-bounds nil)
-;; (start . end) A pair indicating the buffer positions delimiting the
-;; last inserted history, so it can be replaced by a new input if the
-;; command is repeated.
-
-(defvar mail-hist-header-regexp "^[^:]*:"
- "Regular expression for matching headers in a mail message.")
-
-(defsubst mail-hist-current-header-name ()
- "Get name of mail header point is currently in, without the colon.
-Returns nil if not in a header, implying that point is in the body of
-the message."
- (if (save-excursion
- (re-search-backward (concat "^" (regexp-quote mail-header-separator)
- "$")
- nil t))
- nil ; then we are in the body of the message
- (save-excursion
- (let* ((body-start ; limit possibility of false headers
- (save-excursion
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$")
- nil t)))
- (name-start
- (re-search-backward mail-hist-header-regexp nil t))
- (name-end
- (prog2 (search-forward ":" body-start t) (1- (point)))))
- (and
- name-start
- name-end
- (downcase (buffer-substring-no-properties name-start name-end)))))))
-
-(defsubst mail-hist-forward-header (count)
- "Move forward COUNT headers (backward if COUNT is negative).
-If last/first header is encountered first, stop there and returns
-nil.
-
-Places point on the first non-whitespace on the line following the
-colon after the header name, or on the second space following that if
-the header is empty."
- (let ((boundary (save-excursion
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$")
- nil t))))
- (and
- boundary
- (let ((unstopped t))
- (setq boundary (save-excursion
- (goto-char boundary)
- (beginning-of-line)
- (1- (point))))
- (if (> count 0)
- (while (> count 0)
- (setq
- unstopped
- (re-search-forward mail-hist-header-regexp boundary t))
- (setq count (1- count)))
- ;; because the current header will match too.
- (setq count (1- count))
- ;; count is negative
- (while (< count 0)
- (setq
- unstopped
- (re-search-backward mail-hist-header-regexp nil t))
- (setq count (1+ count)))
- ;; we end up behind the header, so must move to the front
- (re-search-forward mail-hist-header-regexp boundary t))
- ;; Now we are right after the colon
- (and (looking-at "\\s-") (forward-char 1))
- ;; return nil if didn't go as far as asked, otherwise point
- unstopped))))
-
-(defsubst mail-hist-beginning-of-header ()
- "Move to the start of the current header.
-The start of the current header is defined as one space after the
-colon, or just after the colon if it is not followed by whitespace."
- ;; this is slick as all heck:
- (if (mail-hist-forward-header -1)
- (mail-hist-forward-header 1)
- (mail-hist-forward-header 1)
- (mail-hist-forward-header -1)))
-
-(defsubst mail-hist-current-header-contents ()
- "Get the contents of the mail header in which point is located."
- (save-excursion
- (mail-hist-beginning-of-header)
- (let ((start (point)))
- (or (mail-hist-forward-header 1)
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$")))
- (beginning-of-line)
- (buffer-substring start (1- (point))))))
-
-(defsubst mail-hist-get-header-ring (header)
- "Get HEADER's history ring, or nil if none.
-HEADER is a string without the colon."
- (setq header (downcase header))
- (cdr (assoc header mail-hist-header-ring-alist)))
-
-(defvar mail-hist-text-size-limit nil
- "*Don't store any header or body with more than this many characters.
-If the value is nil, that means no limit on text size.")
-
-(defun mail-hist-text-too-long-p (text)
- "Return t if TEXT does not exceed mail-hist's size limit.
-The variable `mail-hist-text-size-limit' defines this limit."
- (if mail-hist-text-size-limit
- (> (length text) mail-hist-text-size-limit)))
-
-(defsubst mail-hist-add-header-contents-to-ring (header &optional contents)
- "Add the contents of HEADER to the header history ring.
-Optional argument CONTENTS is a string which will be the contents
-\(instead of whatever's found in the header)."
- (setq header (downcase header))
- (let ((ctnts (or contents (mail-hist-current-header-contents)))
- (ring (cdr (assoc header mail-hist-header-ring-alist))))
- (if (mail-hist-text-too-long-p ctnts) (setq ctnts ""))
- (or ring
- ;; If the ring doesn't exist, we'll have to make it and add it
- ;; to the mail-header-ring-alist:
- (prog1
- (setq ring (make-ring mail-hist-history-size))
- (setq mail-hist-header-ring-alist
- (cons (cons header ring) mail-hist-header-ring-alist))))
- (ring-insert ring ctnts)))
-
-;;;###autoload
-(defun mail-hist-put-headers-into-history ()
- "Put headers and contents of this message into mail header history.
-Each header has its own independent history, as does the body of the
-message.
-
-This function normally would be called when the message is sent."
- (and
- mail-hist-keep-history
- (save-excursion
- (goto-char (point-min))
- (while (mail-hist-forward-header 1)
- (mail-hist-add-header-contents-to-ring
- (mail-hist-current-header-name)))
- (let ((body-contents
- (save-excursion
- (goto-char (point-min))
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$")
- nil)
- (forward-line 1)
- (buffer-substring (point) (point-max)))))
- (mail-hist-add-header-contents-to-ring "body" body-contents)))))
-
-(defun mail-hist-previous-input (header)
- "Insert the previous contents of this mail header or message body.
-Moves back through the history of sent mail messages. Each header has
-its own independent history, as does the body of the message.
-
-The history only contains the contents of outgoing messages, not
-received mail."
- (interactive (list (or (mail-hist-current-header-name) "body")))
- (setq header (downcase header))
- (let* ((ring (cdr (assoc header mail-hist-header-ring-alist)))
- (len (ring-length ring))
- (repeat (eq last-command 'mail-hist-input-access)))
- (if repeat
- (setq mail-hist-access-count
- (ring-plus1 mail-hist-access-count len))
- (setq mail-hist-access-count 0))
- (if (null ring)
- (progn
- (ding)
- (message "No history for \"%s\"." header))
- (if (ring-empty-p ring)
- (error "\"%s\" ring is empty." header)
- (and repeat
- (delete-region (car mail-hist-last-bounds)
- (cdr mail-hist-last-bounds)))
- (let ((start (point)))
- (insert (ring-ref ring mail-hist-access-count))
- (setq mail-hist-last-bounds (cons start (point)))
- (setq this-command 'mail-hist-input-access))))))
-
-(defun mail-hist-next-input (header)
- "Insert next contents of this mail header or message body.
-Moves back through the history of sent mail messages. Each header has
-its own independent history, as does the body of the message.
-
-Although you can do so, it does not make much sense to call this
-without having called `mail-hist-previous-header' first
-(\\[mail-hist-previous-header]).
-
-The history only contains the contents of outgoing messages, not
-received mail."
- (interactive (list (or (mail-hist-current-header-name) "body")))
- (setq header (downcase header))
- (let* ((ring (cdr (assoc header mail-hist-header-ring-alist)))
- (len (ring-length ring))
- (repeat (eq last-command 'mail-hist-input-access)))
- (if repeat
- (setq mail-hist-access-count
- (ring-minus1 mail-hist-access-count len))
- (setq mail-hist-access-count 0))
- (if (null ring)
- (progn
- (ding)
- (message "No history for \"%s\"." header))
- (if (ring-empty-p ring)
- (error "\"%s\" ring is empty." header)
- (and repeat
- (delete-region (car mail-hist-last-bounds)
- (cdr mail-hist-last-bounds)))
- (let ((start (point)))
- (insert (ring-ref ring mail-hist-access-count))
- (setq mail-hist-last-bounds (cons start (point)))
- (setq this-command 'mail-hist-input-access))))))
-
-(provide 'mail-hist)
-
-;; mail-hist.el ends here
diff --git a/lisp/mail/mail-utils.el b/lisp/mail/mail-utils.el
deleted file mode 100644
index ebf2f617789..00000000000
--- a/lisp/mail/mail-utils.el
+++ /dev/null
@@ -1,254 +0,0 @@
-;;; mail-utils.el --- utility functions used both by rmail and rnews
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: mail, news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Utility functions for mail and netnews handling. These handle fine
-;; points of header parsing.
-
-;;; Code:
-
-;;; We require lisp-mode to make sure that lisp-mode-syntax-table has
-;;; been initialized.
-(require 'lisp-mode)
-
-;;;###autoload
-(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.")
-
-;; Returns t if file FILE is an Rmail file.
-;;;###autoload
-(defun mail-file-babyl-p (file)
- (let ((buf (generate-new-buffer " *rmail-file-p*")))
- (unwind-protect
- (save-excursion
- (set-buffer buf)
- (insert-file-contents file nil 0 100)
- (looking-at "BABYL OPTIONS:"))
- (kill-buffer buf))))
-
-(defun mail-string-delete (string start end)
- "Returns a string containing all of STRING except the part
-from START (inclusive) to END (exclusive)."
- (if (null end) (substring string 0 start)
- (concat (substring string 0 start)
- (substring string end nil))))
-
-(defun mail-strip-quoted-names (address)
- "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 (null address)
- nil
- (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))))
-
- ;; 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
- (condition-case ()
- (forward-sexp 1)
- (error (goto-char (point-max))))
- (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 `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 "\\(,\\s-*\\|\\`\\)[^,]*<\\([^>,]*>\\)"
- 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)))
- (setq rmail-default-dont-reply-to-names "info-"))
-
-; 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'.
-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-login-name))
- "\\>"))))
- (let ((match (concat "\\(^\\|,\\)[ \t\n]*\\([^,\n]*!\\|\\)\\("
- rmail-dont-reply-to-names
- "\\|[^\,.<]*<\\(" rmail-dont-reply-to-names "\\)"
- "\\)"))
- (case-fold-search t)
- pos epos)
- (setq foo match)
- (while (setq pos (string-match match userids))
- (if (> pos 0) (setq pos (match-beginning 2)))
- (setq epos
- ;; Delete thru the next comma, plus whitespace after.
- (if (string-match ",[ \t\n]+" userids (match-end 0))
- (match-end 0)
- (length userids)))
- (setq userids
- (mail-string-delete
- userids pos epos)))
- ;; get rid of any trailing commas
- (if (setq pos (string-match "[ ,\t\n]*\\'" userids))
- (setq userids (substring userids 0 pos)))
- ;; remove leading spaces. they bother me.
- (if (string-match "\\s *" userids)
- (substring userids (match-end 0))
- userids)))
-
-;;;###autoload
-(defun mail-fetch-field (field-name &optional last all)
- "Return the value of the header field FIELD-NAME.
-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."
- (save-excursion
- (goto-char (point-min))
- (let ((case-fold-search t)
- (name (concat "^" (regexp-quote field-name) "[ \t]*:[ \t]*")))
- (if all
- (let ((value ""))
- (while (re-search-forward name nil t)
- (let ((opoint (point)))
- (while (progn (forward-line 1)
- (looking-at "[ \t]")))
- ;; Back up over newline, then trailing spaces or tabs
- (forward-char -1)
- (skip-chars-backward " \t" opoint)
- (setq value (concat value
- (if (string= value "") "" ", ")
- (buffer-substring-no-properties
- opoint (point))))))
- (and (not (string= value "")) value))
- (if (re-search-forward name nil t)
- (progn
- (if last (while (re-search-forward name nil t)))
- (let ((opoint (point)))
- (while (progn (forward-line 1)
- (looking-at "[ \t]")))
- ;; Back up over newline, then trailing spaces or tabs
- (forward-char -1)
- (skip-chars-backward " \t" opoint)
- (buffer-substring-no-properties opoint (point)))))))))
-
-;; Parse a list of tokens separated by commas.
-;; It runs from point to the end of the visible part of the buffer.
-;; Whitespace before or after tokens is ignored,
-;; but whitespace within tokens is kept.
-(defun mail-parse-comma-list ()
- (let (accumulated
- beg)
- (skip-chars-forward " ")
- (while (not (eobp))
- (setq beg (point))
- (skip-chars-forward "^,")
- (skip-chars-backward " ")
- (setq accumulated
- (cons (buffer-substring beg (point))
- accumulated))
- (skip-chars-forward "^,")
- (skip-chars-forward ", "))
- accumulated))
-
-(defun mail-comma-list-regexp (labels)
- (let (pos)
- (setq pos (or (string-match "[^ \t]" labels) 0))
- ;; Remove leading and trailing whitespace.
- (setq labels (substring labels pos (string-match "[ \t]*$" labels pos)))
- ;; Change each comma to \|, and flush surrounding whitespace.
- (while (setq pos (string-match "[ \t]*,[ \t]*" labels))
- (setq labels
- (concat (substring labels 0 pos)
- "\\|"
- (substring labels (match-end 0))))))
- labels)
-
-(defun mail-rfc822-time-zone (time)
- (let* ((sec (or (car (current-time-zone time)) 0))
- (absmin (/ (abs sec) 60)))
- (format "%c%02d%02d" (if (< sec 0) ?- ?+) (/ absmin 60) (% absmin 60))))
-
-(defun mail-rfc822-date ()
- (let* ((time (current-time))
- (s (current-time-string time)))
- (string-match "[^ ]+ +\\([^ ]+\\) +\\([^ ]+\\) \\([^ ]+\\) \\([^ ]+\\)" s)
- (concat (substring s (match-beginning 2) (match-end 2)) " "
- (substring s (match-beginning 1) (match-end 1)) " "
- (substring s (match-beginning 4) (match-end 4)) " "
- (substring s (match-beginning 3) (match-end 3)) " "
- (mail-rfc822-time-zone time))))
-
-(provide 'mail-utils)
-
-;;; mail-utils.el ends here
diff --git a/lisp/mail/mailabbrev.el b/lisp/mail/mailabbrev.el
deleted file mode 100644
index e69e10cdf5f..00000000000
--- a/lisp/mail/mailabbrev.el
+++ /dev/null
@@ -1,576 +0,0 @@
-;;; mailabbrev.el --- abbrev-expansion of mail aliases.
-
-;; Copyright (C) 1985, 1986, 87, 92, 93, 1996 Free Software Foundation, Inc.
-
-;; Author: Jamie Zawinski <jwz@lucid.com>
-;; Maintainer: Jamie Zawinski <jwz@lucid.com>
-;; Created: 19 Oct 90
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This file ensures that, when the point is in a To:, CC:, BCC:, or From:
-;; field, word-abbrevs are defined for each of your mail aliases. These
-;; aliases will be defined from your .mailrc file (or the file specified by
-;; the MAILRC environment variable) if it exists. Your mail aliases will
-;; expand any time you type a word-delimiter at the end of an abbreviation.
-;;
-;; What you see is what you get: if mailabbrev is in use when you type
-;; a name, and the name does not expand, you know it is not an abbreviation.
-;; However, if you yank abbreviations into the headers
-;; in a way that bypasses the check for abbreviations,
-;; they are expanded (but not visibly) when you send the message.
-;;
-;; Your mail alias abbrevs will be in effect only when the point is in an
-;; appropriate header field. When in the body of the message, or other
-;; header fields, the mail aliases will not expand. Rather, the normal
-;; mode-specific abbrev table (mail-mode-abbrev-table) will be used if
-;; defined. So if you use mail-mode specific abbrevs, this code will not
-;; adversely affect you. You can control which header fields the abbrevs
-;; are used in by changing the variable mail-abbrev-mode-regexp.
-;;
-;; If auto-fill mode is on, abbrevs will wrap at commas instead of at word
-;; boundaries; also, header continuation-lines will be properly indented.
-;;
-;; You can also insert a mail alias with mail-interactive-insert-alias
-;; (bound to C-c C-a), which prompts you for an alias (with completion)
-;; and inserts its expansion at point.
-;;
-;; This file fixes a bug in the old system which prohibited your .mailrc
-;; file from having lines like
-;;
-;; alias someone "John Doe <doe@quux.com>"
-;;
-;; That is, if you want an address to have embedded spaces, simply surround it
-;; with double-quotes. This is necessary because the format of the .mailrc
-;; file bogusly uses spaces as address delimiters. The following line defines
-;; an alias which expands to three addresses:
-;;
-;; alias foobar addr-1 addr-2 "address three <addr-3>"
-;;
-;; (This is bogus because mail-delivery programs want commas, not spaces,
-;; but that's what the file format is, so we have to live with it.)
-;;
-;; If you like, you can call the function define-mail-abbrev to define your
-;; mail aliases instead of using a .mailrc file. When you call it in this
-;; way, addresses are separated by commas.
-;;
-;; CAVEAT: This works on most Sun systems; I have been told that some versions
-;; of /bin/mail do not understand double-quotes in the .mailrc file. So you
-;; should make sure your version does before including verbose addresses like
-;; this. One solution to this, if you are on a system whose /bin/mail doesn't
-;; work that way, (and you still want to be able to /bin/mail to send mail in
-;; addition to emacs) is to define minimal aliases (without full names) in
-;; your .mailrc file, and use define-mail-abbrev to redefine them when sending
-;; mail from emacs; this way, mail sent from /bin/mail will work, and mail
-;; sent from emacs will be pretty.
-;;
-;; Aliases in the mailrc file may be nested. If you define aliases like
-;; alias group1 fred ethel
-;; alias group2 larry curly moe
-;; alias everybody group1 group2
-;; Then when you type "everybody" on the To: line, it will be expanded to
-;; fred, ethyl, larry, curly, moe
-;;
-;; Aliases may also contain forward references; the alias of "everybody" can
-;; precede the aliases of "group1" and "group2".
-;;
-;; This code also understands the "source" .mailrc command, for reading
-;; aliases from some other file as well.
-;;
-;; Aliases may contain hyphens, as in "alias foo-bar foo@bar"; word-abbrevs
-;; normally cannot contain hyphens, but this code works around that for the
-;; specific case of mail-alias word-abbrevs.
-;;
-;; To read in the contents of another .mailrc-type file from emacs, use the
-;; command Meta-X merge-mail-abbrevs. The rebuild-mail-abbrevs command is
-;; similar, but will delete existing aliases first.
-;;
-;; If you would like your aliases to be expanded when you type M-> or ^N to
-;; move out of the mail-header into the message body (instead of having to
-;; type SPC at the end of the abbrev before moving away) then you can do
-;;
-;; (add-hook
-;; 'mail-setup-hook
-;; '(lambda ()
-;; (substitute-key-definition 'next-line 'mail-abbrev-next-line
-;; mail-mode-map global-map)
-;; (substitute-key-definition 'end-of-buffer 'mail-abbrev-end-of-buffer
-;; mail-mode-map global-map)))
-;;
-;; If you want multiple addresses separated by a string other than ", " then
-;; you can set the variable mail-alias-separator-string to it. This has to
-;; be a comma bracketed by whitespace if you want any kind of reasonable
-;; behaviour.
-;;
-;; Thanks to Harald Hanche-Olsen, Michael Ernst, David Loeffler, and
-;; Noah Friedman for suggestions and bug reports.
-
-;; To use this package, do (add-hook 'mail-setup-hook 'mail-abbrevs-setup).
-
-;;; Code:
-
-(require 'sendmail)
-
-;; originally defined in sendmail.el - used to be an alist, now is a table.
-(defvar mail-abbrevs nil
- "Word-abbrev table of mail address aliases.
-If this is nil, it means the aliases have not yet been initialized and
-should be read from the .mailrc file. (This is distinct from there being
-no aliases, which is represented by this being a table with no entries.)")
-
-(defvar mail-abbrev-modtime nil
- "The modification time of your mail alias file when it was last examined.")
-
-(defun mail-abbrevs-sync-aliases ()
- (if (file-exists-p mail-personal-alias-file)
- (let ((modtime (nth 5 (file-attributes mail-personal-alias-file))))
- (if (not (equal mail-abbrev-modtime modtime))
- (progn
- (setq mail-abbrev-modtime modtime)
- (build-mail-abbrevs))))))
-
-;;;###autoload
-(defun mail-abbrevs-setup ()
- "Initialize use of the `mailabbrev' package."
- (if (and (not (vectorp mail-abbrevs))
- (file-exists-p mail-personal-alias-file))
- (progn
- (setq mail-abbrev-modtime
- (nth 5 (file-attributes mail-personal-alias-file)))
- (build-mail-abbrevs)))
- (mail-abbrevs-sync-aliases)
- (make-local-hook 'pre-abbrev-expand-hook)
- (add-hook 'pre-abbrev-expand-hook 'sendmail-pre-abbrev-expand-hook
- nil t)
- (abbrev-mode 1))
-
-;;;###autoload
-(defun build-mail-abbrevs (&optional file recursivep)
- "Read mail aliases from personal mail alias file and set `mail-abbrevs'.
-By default this is the file specified by `mail-personal-alias-file'."
- (setq file (expand-file-name (or file mail-personal-alias-file)))
- (if (vectorp mail-abbrevs)
- nil
- (setq mail-abbrevs nil)
- (define-abbrev-table 'mail-abbrevs '()))
- (message "Parsing %s..." file)
- (let ((buffer nil)
- (obuf (current-buffer)))
- (unwind-protect
- (progn
- (setq buffer (generate-new-buffer "mailrc"))
- (buffer-disable-undo buffer)
- (set-buffer buffer)
- (cond ((get-file-buffer file)
- (insert (save-excursion
- (set-buffer (get-file-buffer file))
- (buffer-substring (point-min) (point-max)))))
- ((not (file-exists-p file)))
- (t (insert-file-contents file)))
- ;; Don't lose if no final newline.
- (goto-char (point-max))
- (or (eq (preceding-char) ?\n) (newline))
- (goto-char (point-min))
- ;; Delete comments from the file
- (while (search-forward "# " nil t)
- (let ((p (- (point) 2)))
- (end-of-line)
- (delete-region p (point))))
- (goto-char (point-min))
- ;; handle "\\\n" continuation lines
- (while (not (eobp))
- (end-of-line)
- (if (= (preceding-char) ?\\)
- (progn (delete-char -1) (delete-char 1) (insert ?\ ))
- (forward-char 1)))
- (goto-char (point-min))
- (while (re-search-forward
- "^\\(a\\(lias\\)?\\|g\\(roup\\)?\\|source\\)[ \t]+" nil t)
- (beginning-of-line)
- (if (looking-at "source[ \t]+\\([^ \t\n]+\\)")
- (progn
- (end-of-line)
- (build-mail-abbrevs
- (substitute-in-file-name
- (buffer-substring (match-beginning 1) (match-end 1)))
- t))
- (re-search-forward "[ \t]+\\([^ \t\n]+\\)")
- (let* ((name (buffer-substring
- (match-beginning 1) (match-end 1)))
- (start (progn (skip-chars-forward " \t") (point))))
- (end-of-line)
-; (message "** %s \"%s\"" name (buffer-substring start (point)))(sit-for 1)
- (define-mail-abbrev
- name
- (buffer-substring start (point))
- t))))
- ;; Resolve forward references in .mailrc file.
- ;; This would happen automatically before the first abbrev was
- ;; expanded, but why not do it now.
- (or recursivep (mail-resolve-all-aliases))
- mail-abbrevs)
- (if buffer (kill-buffer buffer))
- (set-buffer obuf)))
- (message "Parsing %s... done" file))
-
-(defvar mail-alias-separator-string ", "
- "*A string inserted between addresses in multi-address mail aliases.
-This has to contain a comma, so \", \" is a reasonable value. You might
-also want something like \",\\n \" to get each address on its own line.")
-
-;; define-mail-abbrev sets this flag, which causes mail-resolve-all-aliases
-;; to be called before expanding abbrevs if it's necessary.
-(defvar mail-abbrev-aliases-need-to-be-resolved t)
-
-;; originally defined in mailalias.el ; build-mail-abbrevs calls this with
-;; stuff parsed from the .mailrc file.
-;;
-;;;###autoload
-(defun define-mail-abbrev (name definition &optional from-mailrc-file)
- "Define NAME as a mail alias abbrev that translates to DEFINITION.
-If DEFINITION contains multiple addresses, separate them with commas."
- ;; When this is called from build-mail-abbrevs, the third argument is
- ;; true, and we do some evil space->comma hacking like /bin/mail does.
- (interactive "sDefine mail alias: \nsDefine %s as mail alias for: ")
- ;; Read the defaults first, if we have not done so.
- (if (vectorp mail-abbrevs)
- nil
- (setq mail-abbrevs nil)
- (define-abbrev-table 'mail-abbrevs '())
- (if (file-exists-p mail-personal-alias-file)
- (build-mail-abbrevs)))
- ;; strip garbage from front and end
- (if (string-match "\\`[ \t\n,]+" definition)
- (setq definition (substring definition (match-end 0))))
- (if (string-match "[ \t\n,]+\\'" definition)
- (setq definition (substring definition 0 (match-beginning 0))))
- (let* ((result '())
- (L (length definition))
- (start (if (> L 0) 0))
- end)
- (while start
- ;; If we're reading from the mailrc file, then addresses are delimited
- ;; by spaces, and addresses with embedded spaces must be surrounded by
- ;; double-quotes. Otherwise, addresses are separated by commas.
- (if from-mailrc-file
- (if (eq ?\" (aref definition start))
- (setq start (1+ start)
- end (string-match "\"[ \t,]*" definition start))
- (setq end (string-match "[ \t,]+" definition start)))
- (setq end (string-match "[ \t\n,]*,[ \t\n,]*" definition start)))
- (setq result (cons (substring definition start end) result))
- (setq start (and end
- (/= (match-end 0) L)
- (match-end 0))))
- (setq definition (mapconcat (function identity)
- (nreverse result)
- mail-alias-separator-string)))
- (setq mail-abbrev-aliases-need-to-be-resolved t)
- (setq name (downcase name))
- ;; use an abbrev table instead of an alist for mail-abbrevs.
- (let ((abbrevs-changed abbrevs-changed)) ; protect this from being changed.
- (define-abbrev mail-abbrevs name definition 'mail-abbrev-expand-hook)))
-
-
-(defun mail-resolve-all-aliases ()
- "Resolve all forward references in the mail aliases table."
- (if mail-abbrev-aliases-need-to-be-resolved
- (progn
-;; (message "Resolving mail aliases...")
- (if (vectorp mail-abbrevs)
- (mapatoms (function mail-resolve-all-aliases-1) mail-abbrevs))
- (setq mail-abbrev-aliases-need-to-be-resolved nil)
-;; (message "Resolving mail aliases... done.")
- )))
-
-(defun mail-resolve-all-aliases-1 (sym &optional so-far)
- (if (memq sym so-far)
- (error "mail alias loop detected: %s"
- (mapconcat 'symbol-name (cons sym so-far) " <- ")))
- (let ((definition (and (boundp sym) (symbol-value sym))))
- (if definition
- (let ((result '())
- (start 0))
- (while start
- (let ((end (string-match "[ \t\n]*,[, \t\n]*" definition start)))
- (setq result (cons (substring definition start end) result)
- start (and end (match-end 0)))))
- (setq definition
- (mapconcat (function (lambda (x)
- (or (mail-resolve-all-aliases-1
- (intern-soft (downcase x) mail-abbrevs)
- (cons sym so-far))
- x)))
- (nreverse result)
- mail-alias-separator-string))
- (set sym definition))))
- (symbol-value sym))
-
-
-(defun mail-abbrev-expand-hook ()
- "For use as the fourth arg to `define-abbrev'.
-After expanding a mail-abbrev, if Auto Fill mode is on and we're past the
-fill-column, break the line at the previous comma, and indent the next line."
- ;; Disable abbrev mode to avoid recursion in indent-relative expanding
- ;; part of the abbrev expansion as an abbrev itself.
- (let ((abbrev-mode nil))
- (save-excursion
- (let ((p (point))
- bol comma fp)
- (beginning-of-line)
- (setq bol (point))
- (goto-char p)
- (while (and auto-fill-function
- (>= (current-column) fill-column)
- (search-backward "," bol t))
- (setq comma (point))
- (forward-char 1) ; Now we are just past the comma.
- (insert "\n")
- (delete-horizontal-space)
- (setq p (point))
- (indent-relative)
- (setq fp (buffer-substring p (point)))
- ;; Go to the end of the new line.
- (end-of-line)
- (if (> (current-column) fill-column)
- ;; It's still too long; do normal auto-fill.
- (let ((fill-prefix (or fp "\t")))
- (do-auto-fill)))
- ;; Resume the search.
- (goto-char comma)
- )))))
-
-;;; Syntax tables and abbrev-expansion
-
-(defvar mail-abbrev-mode-regexp
- "^\\(Resent-\\)?\\(To\\|From\\|CC\\|BCC\\|Reply-to\\):"
- "*Regexp to select mail-headers in which mail abbrevs should be expanded.
-This string will be handed to `looking-at' with point at the beginning
-of the current line; if it matches, abbrev mode will be turned on, otherwise
-it will be turned off. (You don't need to worry about continuation lines.)
-This should be set to match those mail fields in which you want abbreviations
-turned on.")
-
-(defvar mail-mode-header-syntax-table
- (let ((tab (copy-syntax-table text-mode-syntax-table)))
- ;; This makes the characters "@%!._-" be considered symbol-constituents
- ;; but not word-constituents, so forward-sexp will move you over an
- ;; entire address, but forward-word will only move you over a sequence
- ;; of alphanumerics. (Clearly the right thing.)
- (modify-syntax-entry ?@ "_" tab)
- (modify-syntax-entry ?% "_" tab)
- (modify-syntax-entry ?! "_" tab)
- (modify-syntax-entry ?. "_" tab)
- (modify-syntax-entry ?_ "_" tab)
- (modify-syntax-entry ?- "_" tab)
- (modify-syntax-entry ?< "(>" tab)
- (modify-syntax-entry ?> ")<" tab)
- tab)
- "The syntax table used in send-mail mode when in a mail-address header.
-`mail-mode-syntax-table' is used when the cursor is in the message body or in
-non-address headers.")
-
-(defvar mail-abbrev-syntax-table
- (let* ((tab (copy-syntax-table mail-mode-header-syntax-table))
- (_ (aref (standard-syntax-table) ?_))
- (w (aref (standard-syntax-table) ?w)))
- (map-char-table
- (function (lambda (key value)
- (if (equal value _)
- (set-char-table-range tab key w))))
- tab)
- tab)
- "The syntax-table used for abbrev-expansion purposes.
-This is not actually made the current syntax table of the buffer, but
-simply controls the set of characters which may be a part of the name
-of a mail alias.")
-
-
-(defun mail-abbrev-in-expansion-header-p ()
- "Whether point is in a mail-address header field."
- (let ((case-fold-search t))
- (and ;;
- ;; we are on an appropriate header line...
- (save-excursion
- (beginning-of-line)
- ;; skip backwards over continuation lines.
- (while (and (looking-at "^[ \t]")
- (not (= (point) (point-min))))
- (forward-line -1))
- ;; are we at the front of an appropriate header line?
- (looking-at mail-abbrev-mode-regexp))
- ;;
- ;; ...and we are before the mail-header-separator
- (< (point)
- (save-excursion
- (goto-char (point-min))
- (search-forward (concat "\n" mail-header-separator "\n")
- nil 0)
- (point))))))
-
-(defvar mail-mode-abbrev-table) ; quiet the compiler
-
-(defun sendmail-pre-abbrev-expand-hook ()
- (and (and mail-abbrevs (not (eq mail-abbrevs t)))
- (if (mail-abbrev-in-expansion-header-p)
- (progn
- ;;
- ;; We are in a To: (or CC:, or whatever) header, and
- ;; should use word-abbrevs to expand mail aliases.
-
- ;; Before anything else, resolve aliases if they need it.
- (and mail-abbrev-aliases-need-to-be-resolved
- (mail-resolve-all-aliases))
-
- ;; Now proceed with the abbrev section.
- ;; - First, install the mail-abbrevs as the word-abbrev table.
- ;; - Then install the mail-abbrev-syntax-table, which
- ;; temporarily marks all of the
- ;; non-alphanumeric-atom-characters (the "_"
- ;; syntax ones) as being normal word-syntax. We do this
- ;; because the C code for expand-abbrev only works on words,
- ;; and we want these characters to be considered words for
- ;; the purpose of abbrev expansion.
- ;; - Then we call expand-abbrev again, recursively, to do
- ;; the abbrev expansion with the above syntax table.
- ;; - Then we do a trick which tells the expand-abbrev frame
- ;; which invoked us to not continue (and thus not
- ;; expand twice.) This means that any abbrev expansion
- ;; will happen as a result of this function's call to
- ;; expand-abbrev, and not as a result of the call to
- ;; expand-abbrev which invoked *us*.
- ;; - Then we set the syntax table to
- ;; mail-mode-header-syntax-table, which doesn't have
- ;; anything to do with abbrev expansion, but
- ;; is just for the user's convenience (see its doc string.)
- ;;
-
- (setq local-abbrev-table mail-abbrevs)
-
- ;; If the character just typed was non-alpha-symbol-syntax,
- ;; then don't expand the abbrev now (that is, don't expand
- ;; when the user types -.) Check the character's syntax in
- ;; the mail-mode-header-syntax-table.
-
- (set-syntax-table mail-mode-header-syntax-table)
- (or (and (integerp last-command-char)
- (eq (char-syntax last-command-char) ?_))
- (let ((pre-abbrev-expand-hook nil)) ; That's us; don't loop.
- ;; Use this table so that abbrevs can have hyphens in them.
- (set-syntax-table mail-abbrev-syntax-table)
- (expand-abbrev)
- ;; Now set it back to what it was before.
- (set-syntax-table mail-mode-header-syntax-table)))
- (setq abbrev-start-location (point-max) ; This is the trick.
- abbrev-start-location-buffer (current-buffer)))
-
- ;; We're not in a mail header where mail aliases should
- ;; be expanded, then use the normal mail-mode abbrev table
- ;; (if any) and the normal mail-mode syntax table.
-
- (setq local-abbrev-table (and (boundp 'mail-mode-abbrev-table)
- mail-mode-abbrev-table))
- (set-syntax-table mail-mode-syntax-table))
- ))
-
-;;; utilities
-
-(defun merge-mail-abbrevs (file)
- "Merge mail aliases from the given file with existing ones."
- (interactive (list
- (let ((insert-default-directory t)
- (default-directory (expand-file-name "~/"))
- (def mail-personal-alias-file))
- (read-file-name
- (format "Read additional aliases from file: (default %s) "
- def)
- default-directory
- (expand-file-name def default-directory)
- t))))
- (build-mail-abbrevs file))
-
-(defun rebuild-mail-abbrevs (&optional file)
- "Rebuild all the mail aliases from the given file."
- (interactive (list
- (let ((insert-default-directory t)
- (default-directory (expand-file-name "~/"))
- (def mail-personal-alias-file))
- (read-file-name
- (format "Read mail aliases from file: (default %s) " def)
- default-directory
- (expand-file-name def default-directory)
- t))))
- (if (null file)
- (setq file buffer-file-name))
- (setq mail-abbrevs nil)
- (build-mail-abbrevs file))
-
-(defun mail-interactive-insert-alias (&optional alias)
- "Prompt for and insert a mail alias."
- (interactive (progn
- (if (not (vectorp mail-abbrevs)) (mail-abbrevs-setup))
- (list (completing-read "Expand alias: " mail-abbrevs nil t))))
- (if (not (vectorp mail-abbrevs)) (mail-abbrevs-setup))
- (insert (or (and alias (symbol-value (intern-soft alias mail-abbrevs))) ""))
- (mail-abbrev-expand-hook))
-
-(defun mail-abbrev-next-line (&optional arg)
- "Expand any mail abbrev, then 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. This goal column is stored
-in `goal-column', which is nil when there is none.
-
-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 (looking-at "[ \t]*\n") (expand-abbrev))
- (setq this-command 'next-line)
- (next-line arg))
-
-(defun mail-abbrev-end-of-buffer (&optional arg)
- "Expand any mail abbrev, then move point to end of buffer.
-Leave mark at previous position.
-With arg N, put point N/10 of the way from the true end.
-
-Don't use this command in Lisp programs!
-\(goto-char (point-max)) is faster and avoids clobbering the mark."
- (interactive "P")
- (if (looking-at "[ \t]*\n") (expand-abbrev))
- (setq this-command 'end-of-buffer)
- (end-of-buffer arg))
-
-(define-key mail-mode-map "\C-c\C-a" 'mail-interactive-insert-alias)
-
-;;(define-key mail-mode-map "\C-n" 'mail-abbrev-next-line)
-;;(define-key mail-mode-map "\M->" 'mail-abbrev-end-of-buffer)
-
-(provide 'mailabbrev)
-
-;;; mailabbrev.el ends here.
diff --git a/lisp/mail/mailalias.el b/lisp/mail/mailalias.el
deleted file mode 100644
index 0969f50ae29..00000000000
--- a/lisp/mail/mailalias.el
+++ /dev/null
@@ -1,441 +0,0 @@
-;;; mailalias.el --- expand and complete mailing address aliases
-
-;; Copyright (C) 1985, 1987, 1995, 1996 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Basic functions for defining and expanding mail aliases.
-;; These seal off the interface to the alias-definition parts of a
-;; .mailrc file formatted for BSD's Mail or USL's mailx.
-
-;;; Code:
-
-(require 'sendmail)
-
-(defvar mail-names t
- "Alist of local users, aliases and directory entries as available.
-When t this still needs to be initialized.
-This is the basis for `mail-complete'.")
-
-(defvar mail-local-names t
- "Alist of local users.
-When t this still needs to be initialized.")
-
-(defvar mail-directory-names t
- "Alist of mail address directory entries.
-When t this still needs to be initialized.")
-
-(defvar mail-address-field-regexp
- "^\\(Resent-\\)?\\(To\\|From\\|CC\\|BCC\\|Reply-to\\):")
-
-(defvar mail-complete-alist
- `((,mail-address-field-regexp mail-get-names pattern)
- ("Newsgroups:" . (if (boundp 'gnus-active-hashtb)
- gnus-active-hashtb
- (if (boundp news-group-article-assoc)
- news-group-article-assoc)))
- ("Followup-To:" . (mail-sentto-newsgroups))
- ;;("Distribution:" ???)
- )
- "Alist of header field and expression to return alist for completion.
-Expression may reference variable `pattern' which is the string being completed.
-If not on matching header, `mail-complete-function' gets called instead.")
-
-(defvar mail-complete-function 'ispell-complete-word
- "Function to call when completing outside `mail-complete-alist'-header.")
-
-
-(defvar mail-directory-function nil
- "Function to get completions from directory service or `nil' for none.
-See `mail-directory-requery'.")
-
-
-;; This is for when the directory is huge, or changes frequently.
-(defvar mail-directory-requery nil
- "When non-`nil' call `mail-directory-function' for each completion.
-In that case, one argument gets passed to the function, the partial string
-entered so far.")
-
-
-(defvar mail-directory-process nil
- "Unix command when `mail-directory-function' is `mail-directory-process'.
-This is a list of the form (COMMAND ARG ...), where each of the list elements
-is evaluated. When `mail-directory-requery' is non-`nil', during
-evaluation the variable `pattern' contains the partial input being completed.
-This might look like
-
- '(remote-shell-program \"HOST\" \"-nl\" \"USER\" \"COMMAND\")
-
-or
-
- '(remote-shell-program \"HOST\" \"-n\" \"COMMAND '^\" pattern \"'\")")
-
-(defvar mail-directory-stream ()
- "List of (HOST SERVICE) for stream connection to mail directory.")
-
-(defvar mail-directory-parser nil
- "How to interpret the output of `mail-directory-function'.
-Three types of values are possible:
-
- - nil means to gather each line as one name
- - regexp means first \\(grouping\\) in successive matches is name
- - function called at beginning of buffer that returns an alist of names")
-
-
-;; Called from sendmail-send-it, or similar functions,
-;; only if some mail aliases are defined.
-(defun expand-mail-aliases (beg end &optional exclude)
- "Expand all mail aliases in suitable header fields found between BEG and END.
-Suitable header fields are `To', `From', `CC' and `BCC', `Reply-to', and
-their `Resent-' variants.
-
-Optional second arg EXCLUDE may be a regular expression defining text to be
-removed from alias expansions."
- (sendmail-sync-aliases)
- (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 mail-address-field-regexp end t))
- (skip-chars-forward " \t")
- (let ((beg1 (point))
- end1 pos epos seplen
- ;; DISABLED-ALIASES records aliases temporarily disabled
- ;; while we scan text that resulted from expanding those aliases.
- ;; Each element is (ALIAS . TILL-WHEN), where TILL-WHEN
- ;; is where to reenable the alias (expressed as number of chars
- ;; counting from END1).
- (disabled-aliases nil))
- (re-search-forward "^[^ \t]" end 'move)
- (beginning-of-line)
- (skip-chars-backward " \t\n")
- (setq end1 (point-marker))
- (goto-char beg1)
- (while (< (point) end1)
- (setq pos (point))
- ;; Reenable any aliases which were disabled for ranges
- ;; that we have passed out of.
- (while (and disabled-aliases (> pos (- end1 (cdr (car disabled-aliases)))))
- (setq disabled-aliases (cdr disabled-aliases)))
- ;; EPOS gets position of end of next name;
- ;; SEPLEN gets length of whitespace&separator that follows it.
- (if (re-search-forward "[ \t]*[\n,][ \t]*" end1 t)
- (setq epos (match-beginning 0)
- seplen (- (point) epos))
- (setq epos (marker-position end1) seplen 0))
- (let (translation
- (string (buffer-substring-no-properties pos epos)))
- (if (and (not (assoc string disabled-aliases))
- (setq translation
- (cdr (assoc string mail-aliases))))
- (progn
- ;; This name is an alias. Disable it.
- (setq disabled-aliases (cons (cons string (- end1 epos))
- disabled-aliases))
- ;; Replace the alias with its expansion
- ;; 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.
- (goto-char epos)
- (forward-char seplen))))
- (set-marker end1 nil)))
- (set-marker end nil)))
-
-;; Called by mail-setup, or similar functions, only if the file specified
-;; by mail-personal-alias-file (usually `~/.mailrc') exists.
-(defun build-mail-aliases (&optional file)
- "Read mail aliases from personal aliases file and set `mail-aliases'.
-By default, this is the file specified by `mail-personal-alias-file'."
- (setq file (expand-file-name (or file mail-personal-alias-file)))
- (let ((buffer nil)
- (obuf (current-buffer)))
- (unwind-protect
- (progn
- (setq buffer (generate-new-buffer " mailrc"))
- (set-buffer buffer)
- (while file
- (cond ((get-file-buffer file)
- (insert (save-excursion
- (set-buffer (get-file-buffer file))
- (buffer-substring-no-properties
- (point-min) (point-max)))))
- ((file-exists-p file) (insert-file-contents file))
- ((file-exists-p (setq file (concat "~/" file)))
- (insert-file-contents file))
- (t (setq file nil)))
- ;; Don't lose if no final newline.
- (goto-char (point-max))
- (or (eq (preceding-char) ?\n) (newline))
- (goto-char (point-min))
- ;; handle "\\\n" continuation lines
- (while (not (eobp))
- (end-of-line)
- (if (= (preceding-char) ?\\)
- (progn (delete-char -1) (delete-char 1) (insert ?\ ))
- (forward-char 1)))
- (goto-char (point-min))
- ;; handle `source' directives -- Eddy/1994/May/25
- (cond ((re-search-forward "^source[ \t]+" nil t)
- (re-search-forward "\\S-+")
- (setq file (buffer-substring-no-properties
- (match-beginning 0) (match-end 0)))
- (beginning-of-line)
- (insert "# ") ; to ensure we don't re-process this file
- (beginning-of-line))
- (t (setq file nil))))
- (goto-char (point-min))
- (while (re-search-forward
- "^\\(a\\|alias\\|g\\|group\\)[ \t]+\\([^ \t]+\\)" nil t)
- (let* ((name (match-string 2))
- (start (progn (skip-chars-forward " \t") (point))))
- (end-of-line)
- (define-mail-alias
- name
- (buffer-substring-no-properties start (point))
- t)))
- mail-aliases)
- (if buffer (kill-buffer buffer))
- (set-buffer obuf))))
-
-;; Always autoloadable in case the user wants to define aliases
-;; interactively or in .emacs.
-;;;###autoload
-(defun define-mail-alias (name definition &optional from-mailrc-file)
- "Define NAME as a mail alias that translates to DEFINITION.
-This means that sending a message to NAME will actually send to DEFINITION.
-
-Normally, the addresses in DEFINITION must be separated by commas.
-If FROM-MAILRC-FILE is non-nil, then addresses in DEFINITION
-can be separated by spaces; an address can contain spaces
-if it is quoted with double-quotes."
-
- (interactive "sDefine mail alias: \nsDefine %s as mail alias for: ")
- ;; Read the defaults first, if we have not done so.
- (sendmail-sync-aliases)
- (if (eq mail-aliases t)
- (progn
- (setq mail-aliases nil)
- (if (file-exists-p mail-personal-alias-file)
- (build-mail-aliases))))
- ;; strip garbage from front and end
- (if (string-match "\\`[ \t\n,]+" definition)
- (setq definition (substring definition (match-end 0))))
- (if (string-match "[ \t\n,]+\\'" definition)
- (setq definition (substring definition 0 (match-beginning 0))))
- (let ((result '())
- ;; If DEFINITION is null string, avoid looping even once.
- (start (and (not (equal definition "")) 0))
- (L (length definition))
- end tem)
- (while start
- ;; If we're reading from the mailrc file, then addresses are delimited
- ;; by spaces, and addresses with embedded spaces must be surrounded by
- ;; double-quotes. Otherwise, addresses are separated by commas.
- (if from-mailrc-file
- (if (eq ?\" (aref definition start))
- (setq start (1+ start)
- end (string-match "\"[ \t,]*" definition start))
- (setq end (string-match "[ \t,]+" definition start)))
- (setq end (string-match "[ \t\n,]*,[ \t\n,]*" definition start)))
- (setq result (cons (substring definition start end) result))
- (setq start (and end
- (/= (match-end 0) L)
- (match-end 0))))
- (setq definition (mapconcat (function identity)
- (nreverse result)
- ", "))
- (setq tem (assoc name mail-aliases))
- (if tem
- (rplacd tem definition)
- (setq mail-aliases (cons (cons name definition) mail-aliases)
- mail-names t))))
-
-;;;###autoload
-(defun mail-complete (arg)
- "Perform completion on header field or word preceding point.
-Completable headers are according to `mail-complete-alist'. If none matches
-current header, calls `mail-complete-function' and passes prefix arg if any."
- (interactive "P")
- ;; Read the defaults first, if we have not done so.
- (sendmail-sync-aliases)
- (if (eq mail-aliases t)
- (progn
- (setq mail-aliases nil)
- (if (file-exists-p mail-personal-alias-file)
- (build-mail-aliases))))
- (let ((list mail-complete-alist))
- (if (and (save-excursion (search-forward
- (concat "\n" mail-header-separator "\n")
- nil t))
- (save-excursion
- (if (re-search-backward "^[^\t]" nil t)
- (while list
- (if (looking-at (car (car list)))
- (setq arg (cdr (car list))
- list ())
- (setq list (cdr list)))))
- arg))
- (let* ((end (point))
- (beg (save-excursion
- (skip-chars-backward "^ \t<,:")
- (point)))
- (pattern (buffer-substring beg end))
- completion)
- (setq list (eval arg)
- completion (try-completion pattern list))
- (cond ((eq completion t))
- ((null completion)
- (message "Can't find completion for \"%s\"" pattern)
- (ding))
- ((not (string= pattern completion))
- (delete-region beg end)
- (insert completion))
- (t
- (message "Making completion list...")
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list
- (all-completions pattern list)))
- (message "Making completion list...%s" "done"))))
- (funcall mail-complete-function arg))))
-
-(defun mail-get-names (pattern)
- "Fetch local users and global mail adresses for completion.
-Consults `/etc/passwd' and a directory service if one is set up via
-`mail-directory-function'."
- (if (eq mail-local-names t)
- (save-excursion
- (set-buffer (generate-new-buffer " passwd"))
- (insert-file-contents "/etc/passwd" nil nil nil t)
- (setq mail-local-names)
- (while (not (eobp))
- ;;Recognize lines like
- ;; nobody:*:65534:65534::/:
- ;; +demo::::::/bin/csh
- ;; +ethanb
- ;;while skipping
- ;; +@SOFTWARE
- (if (looking-at "\\+?\\([^:@\n+]+\\)")
- (add-to-list 'mail-local-names (list (match-string 1))))
- (beginning-of-line 2))
- (kill-buffer (current-buffer))))
- (if (or (eq mail-names t)
- (eq mail-directory-names t))
- (let (directory)
- (and mail-directory-function
- (eq mail-directory-names t)
- (setq directory
- (mail-directory (if mail-directory-requery pattern))))
- (if (or directory
- (eq mail-names t))
- (setq mail-names
- (sort (append (if (consp mail-aliases) mail-aliases)
- (if (consp mail-local-names)
- mail-local-names)
- directory)
- (lambda (a b)
- ;; should cache downcased strings
- (string< (downcase (car a))
- (downcase (car b)))))))
- (or mail-directory-requery
- (setq mail-directory-names directory))))
- mail-names)
-
-
-(defun mail-directory (pattern)
- "Call directory to get names matching PATTERN or all if `nil'.
-Calls `mail-directory-function' and applies `mail-directory-parser' to output."
- (save-excursion
- (message "Querying directory...")
- (set-buffer (generate-new-buffer " *mail-directory*"))
- (funcall mail-directory-function pattern)
- (goto-char 1)
- (let (directory)
- (if (stringp mail-directory-parser)
- (while (re-search-forward mail-directory-parser nil t)
- (setq directory
- `((,(match-string 1))
- ,@directory)))
- (if mail-directory-parser
- (setq directory (funcall mail-directory-parser))
- (while (not (eobp))
- (setq directory
- `((,(buffer-substring (point)
- (progn
- (forward-line)
- (if (bolp)
- (1- (point))
- (point)))))
- ,@directory)))))
- (kill-buffer (current-buffer))
- (message "Querying directory...done")
- directory)))
-
-
-(defun mail-directory-process (pattern)
- "Call a Unix process to output names in directory.
-See `mail-directory-process'."
- (apply 'call-process (eval (car mail-directory-process)) nil t nil
- (mapcar 'eval (cdr mail-directory-process))))
-
-;; This should handle a dialog. Currently expects port to spit out names.
-(defun mail-directory-stream (pattern)
- "Open a stream to retrieve names in directory.
-See `mail-directory-stream'."
- (let (mailalias-done)
- (set-process-sentinel
- (apply 'open-network-stream "mailalias" (current-buffer)
- mail-directory-stream)
- (lambda (x x)
- (setq mailalias-done t)))
- (while (not mailalias-done)
- (sit-for .1))))
-
-(defun mail-sentto-newsgroups ()
- "Return all entries from Newsgroups: header as completion alist."
- (save-excursion
- (if (mail-position-on-field "newsgroups" t)
- (let ((point (point))
- list)
- (while (< (skip-chars-backward "^:, \t\n") 0)
- (setq list `((,(buffer-substring (point) point))
- ,@list))
- (skip-chars-backward ", \t\n")
- (setq point (point)))
- list))))
-
-(provide 'mailalias)
-
-;;; mailalias.el ends here
diff --git a/lisp/mail/mailheader.el b/lisp/mail/mailheader.el
deleted file mode 100644
index 142b29c4f35..00000000000
--- a/lisp/mail/mailheader.el
+++ /dev/null
@@ -1,183 +0,0 @@
-;;; mailheader.el --- Mail header parsing, merging, formatting
-
-;; Copyright (C) 1996 by Free Software Foundation, Inc.
-
-;; Author: Erik Naggum <erik@arcana.naggum.no>
-;; Keywords: tools, mail, news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides an abstraction to RFC822-style messages, used in
-;; mail, news, and some other systems. The simple syntactic rules for such
-;; headers, such as quoting and line folding, are routinely reimplemented
-;; in many individual packages. This package removes the need for this
-;; redundancy by representing message headers as association lists,
-;; offering functions to extract the set of headers from a message, to
-;; parse individual headers, to merge sets of headers, and to format a set
-;; of headers.
-
-;; The car of each element in the message-header alist is a symbol whose
-;; print name is the name of the header, in all lower-case. The cdr of an
-;; element depends on the operation. After extracting headers from a
-;; messge, it is a string, the value of the header. An extracted set of
-;; headers may be parsed further, which may turn it into a list, whose car
-;; is the original value and whose subsequent elements depend on the
-;; header. For formatting, it is evaluated to obtain the strings to be
-;; inserted. For merging, one set of headers consists of strings, while
-;; the other set will be evaluated with the symbols in the first set of
-;; headers bound to their respective values.
-
-;;; Code:
-
-(eval-when-compile
- (require 'cl))
-
-;; Make the byte-compiler shut up.
-(defvar headers)
-
-(defun mail-header-extract ()
- "Extract headers from current buffer after point.
-Returns a header alist, where each element is a cons cell (name . value),
-where NAME is a symbol, and VALUE is the string value of the header having
-that name."
- (let ((message-headers ()) (top (point))
- start end)
- (while (and (setq start (point))
- (> (skip-chars-forward "^\0- :") 0)
- (= (following-char) ?:)
- (setq end (point))
- (progn (forward-char)
- (> (skip-chars-forward " \t") 0)))
- (let ((header (intern (downcase (buffer-substring start end))))
- (value (list (buffer-substring
- (point) (progn (end-of-line) (point))))))
- (while (progn (forward-char) (> (skip-chars-forward " \t") 0))
- (push (buffer-substring (point) (progn (end-of-line) (point)))
- value))
- (push (if (cdr value)
- (cons header (mapconcat #'identity (nreverse value) " "))
- (cons header (car value)))
- message-headers)))
- (goto-char top)
- (nreverse message-headers)))
-
-(defun mail-header-extract-no-properties ()
- "Extract headers from current buffer after point, without properties.
-Returns a header alist, where each element is a cons cell (name . value),
-where NAME is a symbol, and VALUE is the string value of the header having
-that name."
- (mapcar
- (lambda (elt)
- (set-text-properties 0 (length (cdr elt)) nil (cdr elt))
- elt)
- (mail-header-extract)))
-
-(defun mail-header-parse (parsing-rules headers)
- "Apply PARSING-RULES to HEADERS.
-PARSING-RULES is an alist whose keys are header names (symbols) and whose
-value is a parsing function. The function takes one argument, a string,
-and return a list of values, which will destructively replace the value
-associated with the key in HEADERS, after being prepended with the original
-value."
- (dolist (rule parsing-rules)
- (let ((header (assq (car rule) headers)))
- (when header
- (if (consp (cdr header))
- (setf (cddr header) (funcall (cdr rule) (cadr header)))
- (setf (cdr header)
- (cons (cdr header) (funcall (cdr rule) (cdr header))))))))
- headers)
-
-(defsubst mail-header (header &optional header-alist)
- "Return the value associated with header HEADER in HEADER-ALIST.
-If the value is a string, it is the original value of the header. If the
-value is a list, its first element is the original value of the header,
-with any subsequent elements bing the result of parsing the value.
-If HEADER-ALIST is nil, the dynamically bound variable `headers' is used."
- (cdr (assq header (or header-alist headers))))
-
-(defun mail-header-set (header value &optional header-alist)
- "Set the value associated with header HEADER to VALUE in HEADER-ALIST.
-HEADER-ALIST defaults to the dynamically bound variable `headers' if nil.
-See `mail-header' for the semantics of VALUE."
- (let* ((alist (or header-alist headers))
- (entry (assq header alist)))
- (if entry
- (setf (cdr entry) value)
- (nconc alist (list (cons header value)))))
- value)
-
-(defsetf mail-header (header &optional header-alist) (value)
- `(mail-header-set ,header ,value ,header-alist))
-
-(defun mail-header-merge (merge-rules headers)
- "Return a new header alist with MERGE-RULES applied to HEADERS.
-MERGE-RULES is an alist whose keys are header names (symbols) and whose
-values are forms to evaluate, the results of which are the new headers. It
-should be a string or a list of string. The first element may be nil to
-denote that the formatting functions must use the remaining elements, or
-skip the header altogether if there are no other elements.
- The macro `mail-header' can be used to access headers in HEADERS."
- (mapcar
- (lambda (rule)
- (cons (car rule) (eval (cdr rule))))
- merge-rules))
-
-(defvar mail-header-format-function
- (lambda (header value)
- "Function to format headers without a specified formatting function."
- (insert (capitalize (symbol-name header))
- ": "
- (if (consp value) (car value) value)
- "\n")))
-
-(defun mail-header-format (format-rules headers)
- "Use FORMAT-RULES to format HEADERS and insert into current buffer.
-FORMAT-RULES is an alist whose keys are header names (symbols), and whose
-values are functions that format the header, the results of which are
-inserted, unless it is nil. The function takes two arguments, the header
-symbol, and the value of that header. If the function itself is nil, the
-default action is to insert the value of the header, unless it is nil.
-The headers are inserted in the order of the FORMAT-RULES.
-A key of t represents any otherwise unmentioned headers.
-A key of nil has as its value a list of defaulted headers to ignore."
- (let ((ignore (append (cdr (assq nil format-rules))
- (mapcar #'car format-rules))))
- (dolist (rule format-rules)
- (let* ((header (car rule))
- (value (mail-header header)))
- (cond ((null header) 'ignore)
- ((eq header t)
- (dolist (defaulted headers)
- (unless (memq (car defaulted) ignore)
- (let* ((header (car defaulted))
- (value (cdr defaulted)))
- (if (cdr rule)
- (funcall (cdr rule) header value)
- (funcall mail-header-format-function header value))))))
- (value
- (if (cdr rule)
- (funcall (cdr rule) header value)
- (funcall mail-header-format-function header value))))))
- (insert "\n")))
-
-(provide 'mailheader)
-
-;;; mailheader.el ends here
diff --git a/lisp/mail/mailpost.el b/lisp/mail/mailpost.el
deleted file mode 100644
index 5ff33478698..00000000000
--- a/lisp/mail/mailpost.el
+++ /dev/null
@@ -1,103 +0,0 @@
-;;; mailpost.el --- RMAIL coupler to /usr/uci/post mailer
-
-;; This is in the public domain
-;; since Delp distributed it without a copyright notice in 1986.
-
-;; Author: Gary Delp <delp@huey.Udel.Edu>
-;; Maintainer: FSF
-;; Created: 13 Jan 1986
-;; Keywords: mail
-
-;;; Commentary:
-
-;; Yet another mail interface. this for the rmail system to provide
-;; the missing sendmail interface on systems without /usr/lib/sendmail,
-;; but with /usr/uci/post.
-
-;;; Code:
-
-(require 'mailalias)
-(require 'sendmail)
-
-;; (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."
- (let ((errbuf (if mail-interactive
- (generate-new-buffer " post-mail errors")
- 0))
- (temfile "/tmp/,rpost")
- (tembuf (generate-new-buffer " post-mail temp"))
- (case-fold-search nil)
- delimline
- (mailbuf (current-buffer)))
- (unwind-protect
- (save-excursion
- (set-buffer tembuf)
- (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 post-mail expects.
- (goto-char (point-min))
- (search-forward (concat "\n" mail-header-separator "\n"))
- (replace-match "\n\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"))
- ;; Find and handle any FCC fields.
- (let ((case-fold-search t))
- (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))))
- (write-file (setq temfile (make-temp-name temfile)))
- (set-file-modes temfile 384)
- (apply 'call-process
- (append (list (if (boundp 'post-mail-program)
- post-mail-program
- "/usr/uci/lib/mh/post")
- nil errbuf nil
- "-nofilter" "-msgid")
- (if mail-interactive '("-watch") '("-nowatch"))
- (list temfile)))
- (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)
- (switch-to-buffer errbuf)))))
-
-;;; mailpost.el ends here
diff --git a/lisp/mail/metamail.el b/lisp/mail/metamail.el
deleted file mode 100644
index 98ad5fb3a86..00000000000
--- a/lisp/mail/metamail.el
+++ /dev/null
@@ -1,200 +0,0 @@
-;;; metamail.el --- Metamail interface for GNU Emacs
-
-;; Copyright (C) 1993, 1996 Masanobu UMEDA
-
-;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp>
-;; Version: $Header: metamail.el,v 1.10 96/04/18 11:27:08 umerin Exp $
-;; Keywords: mail, news, mime, multimedia
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The latest version will be at:
-;; ftp://ftp.kyutech.ac.jp/pub/MultiMedia/mime/emacs-mime-tools.shar
-
-;; Note: Metamail does not have all options which is compatible with
-;; the environment variables. For that reason, matamail.el have to
-;; hack the environment variables. In addition, there is no way to
-;; display all header fields without extra informative body messages
-;; which are suppressed by "-q" option.
-
-;; The following definition is what I'm using with GNUS 4:
-;;(setq gnus-show-mime-method
-;; (function
-;; (lambda ()
-;; (metamail-interpret-header)
-;; (let ((metamail-switches ;Suppress header fields in a body.
-;; (append metamail-switches '("-q"))))
-;; (metamail-interpret-body)))))
-
-;; The idea of using metamail to process MIME messages is from
-;; gnus-mime.el by Spike <Spike@world.std.com>.
-
-;;; Code:
-
-(defvar metamail-program-name "metamail"
- "*Metamail program name.")
-
-(defvar metamail-mailer-name "emacs"
- "*Mailer name set to MM_MAILER environment variable.")
-
-(defvar metamail-environment '("KEYHEADS=*" "MM_QUIET=1")
- "*Environment variables passed to `metamail'.
-It must be a list of strings that have the format ENVVARNAME=VALUE.
-It is not expected to be altered globally by `set' or `setq'.
-Instead, change its value temporary using `let' or `let*' form.")
-
-(defvar metamail-switches '("-x" "-d" "-z")
- "*Switches for `metamail' program.
-`-z' is required to remove zap file.
-It is not expected to be altered globally by `set' or `setq'.
-Instead, change its value temporary using `let' or `let*' form.
-`-m MAILER' argument is automatically generated from the
-`metamail-mailer-name' variable.")
-
-;;;###autoload
-(defun metamail-interpret-header ()
- "Interpret a header part of a MIME message in current buffer.
-Its body part is not interpreted at all."
- (interactive)
- (save-excursion
- (let* ((buffer-read-only nil)
- (metamail-switches ;Inhibit processing an empty body.
- (append metamail-switches '("-c" "text/plain" "-E" "7bit")))
- (end (progn
- (goto-char (point-min))
- (search-forward "\n\n" nil 'move)
- ;; An extra newline is inserted by metamail if there
- ;; is no body part. So, insert a dummy body by
- ;; itself.
- (insert "\n")
- (point))))
- (metamail-region (point-min) end nil nil 'nodisplay)
- ;; Remove an extra newline inserted by myself.
- (goto-char (point-min))
- (if (search-forward "\n\n\n" nil t)
- (delete-char -1))
- )))
-
-;;;###autoload
-(defun metamail-interpret-body (&optional viewmode nodisplay)
- "Interpret a body part of a MIME message in current buffer.
-Optional argument VIEWMODE specifies the value of the
-EMACS_VIEW_MODE environment variable (defaulted to 1).
-Optional argument NODISPLAY non-nil means buffer is not
-redisplayed as output is inserted.
-Its header part is not interpreted at all."
- (interactive "p")
- (save-excursion
- (let ((contype nil)
- (encoding nil)
- (end (progn
- (goto-char (point-min))
- (search-forward "\n\n" nil t)
- (point))))
- ;; Find Content-Type and Content-Transfer-Encoding from the header.
- (save-restriction
- (narrow-to-region (point-min) end)
- (setq contype
- (or (mail-fetch-field "Content-Type") "text/plain"))
- (setq encoding
- (or (mail-fetch-field "Content-Transfer-Encoding") "7bit")))
- ;; Interpret the body part only.
- (let ((metamail-switches ;Process body part only.
- (append metamail-switches
- (list "-b" "-c" contype "-E" encoding))))
- (metamail-region end (point-max) viewmode nil nodisplay))
- ;; Mode specific hack.
- (cond ((eq major-mode 'rmail-mode)
- ;; Adjust the marker of this message if in Rmail mode buffer.
- (set-marker (aref rmail-message-vector (1+ rmail-current-message))
- (point-max))))
- )))
-
-;;;###autoload
-(defun metamail-buffer (&optional viewmode buffer nodisplay)
- "Process current buffer through `metamail'.
-Optional argument VIEWMODE specifies the value of the
-EMACS_VIEW_MODE environment variable (defaulted to 1).
-Optional argument BUFFER specifies a buffer to be filled (nil
-means current).
-Optional argument NODISPLAY non-nil means buffer is not
-redisplayed as output is inserted."
- (interactive "p")
- (metamail-region (point-min) (point-max) viewmode buffer nodisplay))
-
-;;;###autoload
-(defun metamail-region (beg end &optional viewmode buffer nodisplay)
- "Process current region through 'metamail'.
-Optional argument VIEWMODE specifies the value of the
-EMACS_VIEW_MODE environment variable (defaulted to 1).
-Optional argument BUFFER specifies a buffer to be filled (nil
-means current).
-Optional argument NODISPLAY non-nil means buffer is not
-redisplayed as output is inserted."
- (interactive "r\np")
- (let ((curbuf (current-buffer))
- (buffer-read-only nil)
- (metafile (make-temp-name "/tmp/metamail"))
- (option-environment
- (list (concat "EMACS_VIEW_MODE="
- (if (numberp viewmode) viewmode 1)))))
- (save-excursion
- ;; Gee! Metamail does not ouput to stdout if input comes from
- ;; stdin.
- (let ((selective-display nil) ;Disable ^M to nl translation.
- (kanji-fileio-code 2) ;Write in JIS code when nemacs.
- (file-coding-system ;Write in JUNET style when mule.
- (if (featurep 'mule) *junet*)))
- (write-region beg end metafile nil 'nomessage))
- (if buffer
- (set-buffer buffer))
- (setq buffer-read-only nil)
- ;; Clear destination buffer.
- (if (eq curbuf (current-buffer))
- (delete-region beg end)
- (delete-region (point-min) (point-max)))
- ;; We have to pass the environment variable KEYHEADS to display
- ;; all header fields. Metamail should have an optional argument
- ;; to pass such information directly.
- (let ((process-environment
- (append process-environment
- metamail-environment option-environment)))
- ;; Specify character coding system.
- (if (boundp 'NEMACS)
- (define-program-kanji-code nil metamail-program-name 2)) ;JIS
- (if (featurep 'mule)
- (define-program-coding-system nil metamail-program-name *junet*))
- (apply (function call-process)
- metamail-program-name
- nil
- t ;Output to current buffer
- (not nodisplay) ;Force redisplay
- (append metamail-switches
- (list "-m" (or metamail-mailer-name "emacs"))
- (list metafile))))
- ;; `metamail' may not delete the temporary file!
- (condition-case error
- (delete-file metafile)
- (error nil))
- )))
-
-(provide 'metamail)
-
-;;; metamail.el ends here
diff --git a/lisp/mail/mh-comp.el b/lisp/mail/mh-comp.el
deleted file mode 100644
index 25117cac6c2..00000000000
--- a/lisp/mail/mh-comp.el
+++ /dev/null
@@ -1,1052 +0,0 @@
-;;; mh-comp --- mh-e functions for composing messages
-;; Time-stamp: <95/08/19 17:48:59 gildea>
-
-;; Copyright (C) 1993, 1995 Free Software Foundation, Inc.
-
-;; This file is part of mh-e, part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Internal support for mh-e package.
-
-;;; Change Log:
-
-;; $Id: mh-comp.el,v 1.7 1995/11/03 02:28:52 kwzh Exp erik $
-
-;;; Code:
-
-(provide 'mh-comp)
-(require 'mh-utils)
-
-;;; Site customization (see also mh-utils.el):
-
-(defvar mh-send-prog "send"
- "Name of the MH send program.
-Some sites need to change this because of a name conflict.")
-
-(defvar mh-redist-full-contents nil
- "Non-nil if the `dist' command needs whole letter for redistribution.
-This is the case only when `send' is compiled with the BERK option.
-If MH will not allow you to redist a previously redist'd msg, set to nil.")
-
-
-(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-yank-hooks nil
- "Obsolete hook for modifying a citation just inserted in the mail buffer.
-Each hook function can find the citation between point and mark.
-And each hook function should leave point and mark around the citation
-text as modified.
-
-This is a normal hook, misnamed for historical reasons.
-It is semi-obsolete and is only used if mail-citation-hook is nil.")
-
-(defvar mail-citation-hook nil
- "*Hook for modifying a citation just inserted in the mail buffer.
-Each hook function can find the citation between point and mark.
-And each hook function should leave point and mark around the citation
-text as modified.
-
-If this hook is entirely empty (nil), the text of the message is inserted
-with mh-ins-buf-prefix prefixed to each line.
-
-See also the variable mh-yank-from-start-of-msg, which controls how
-much of the message passed to the hook.")
-
-;;; Copied from sendmail.el for Hyperbole
-(defvar mail-header-separator "--------"
- "*Line used by MH to separate headers from text in messages being composed.")
-
-;;; Personal preferences:
-
-(defvar mh-delete-yanked-msg-window nil
- "*Controls window display when a message is yanked by \\<mh-letter-mode-map>\\[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-letter-mode-map>\\[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-ins-buf-prefix "> "
- "*String to put before each non-blank line of a yanked or inserted message.
-\\<mh-letter-mode-map>Used when the message is inserted into an outgoing letter
-by \\[mh-insert-letter] or \\[mh-yank-cur-msg].")
-
-(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-folder-mode-map>`\\[mh-reply]' will use this
-value and it should be one of \"from\", \"to\", \"cc\", or \"all\".
-The values \"cc\" and \"all\" do the same thing.")
-
-(defvar mh-signature-file-name "~/.signature"
- "*Name of file containing the user's signature.
-Inserted into message by \\<mh-letter-mode-map>\\[mh-insert-signature].")
-
-(defvar mh-forward-subject-format "%s: %s"
- "*Format to generate the Subject: line contents for a forwarded message.
-The two string arguments to the format are the sender of the original
-message and the original subject line.")
-
-(defvar mh-comp-formfile "components"
- "Name of file to be used as a skeleton for composing messages.
-Default is \"components\". If not a complete path name, the file
-is searched for first in the user's MH directory, then in the
-system MH lib directory.")
-
-(defvar mh-repl-formfile "replcomps"
- "Name of file to be used as a skeleton for replying to messages.
-Default is \"replcomps\". If not a complete path name, the file
-is searched for first in the user's MH directory, then in the
-system MH lib directory.")
-
-;;; Hooks:
-
-(defvar mh-letter-mode-hook nil
- "Invoked in `mh-letter-mode' on a new letter.")
-
-(defvar mh-compose-letter-function nil
- "Invoked when setting up a letter draft.
-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-letter-mode-map>\\[mh-send-letter] command.")
-
-
-(defvar mh-rejected-letter-start
- (concat "^ ----- Unsent message follows -----$" ;from sendmail V5
- "\\|^ ----- Original message follows -----$" ;from sendmail V8
- "\\|^------- Unsent Draft$" ;from MH itself
- "\\|^---------- Original Message ----------$" ;from zmailer
- "\\|^ --- The unsent message follows ---$" ;from AIX mail system
- "\\|^ Your message follows:$" ;from MMDF-II
- "\\|^Content-Description: Returned Content$" ;1993 KJ sendmail
- )
- "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-new-draft-cleaned-headers
- "^Date:\\|^Received:\\|^Message-Id:\\|^From:\\|^Sender:\\|^Errors-To:\\|^Delivery-Date:\\|^Return-Path:"
- "Regexp of header lines to remove before offering a message as a new draft.
-Used by the \\<mh-folder-mode-map>`\\[mh-edit-again]' and `\\[mh-extract-rejected-mail]' commands.")
-
-(defvar mh-to-field-choices '(("t" . "To:") ("s" . "Subject:") ("c" . "Cc:")
- ("b" . "Bcc:") ("f" . "Fcc:") ("r" . "From:")
- ("d" . "Dcc:"))
- "Alist of (final-character . field-name) choices for mh-to-field.")
-
-(defvar mh-letter-mode-map (copy-keymap text-mode-map)
- "Keymap for composing mail.")
-
-(defvar mh-letter-mode-syntax-table nil
- "Syntax table used by mh-e while in MH-Letter mode.")
-
-(if mh-letter-mode-syntax-table
- ()
- (setq mh-letter-mode-syntax-table
- (make-syntax-table text-mode-syntax-table))
- (modify-syntax-entry ?% "." mh-letter-mode-syntax-table))
-
-
-;;;###autoload
-(defun mh-smail ()
- "Compose and send mail with the MH mail system.
-This function is an entry point to mh-e, the Emacs front end
-to the MH mail system.
-
-See documentation of `\\[mh-send]' for more details on composing mail."
- (interactive)
- (mh-find-path)
- (call-interactively 'mh-send))
-
-
-(defvar mh-error-if-no-draft nil) ;raise error over using old draft
-
-
-;;;###autoload
-(defun mh-smail-batch ()
- "Set up a mail composition draft with the MH mail system.
-This function is an entry point to mh-e, the Emacs front end
-to the MH mail system. This function does not prompt the user
-for any header fields, and thus is suitable for use by programs
-that want to create a mail buffer.
-Users should use `\\[mh-smail]' to compose mail."
- (mh-find-path)
- (let ((mh-error-if-no-draft t))
- (mh-send "" "" "")))
-
-
-(defun mh-edit-again (msg)
- "Clean-up a draft or a message previously sent and make it resendable.
-Default is the current message.
-The variable mh-new-draft-cleaned-headers specifies the headers to remove.
-See also documentation for `\\[mh-send]' function."
- (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) mh-new-draft-cleaned-headers nil)
- (goto-char (point-min))
- (save-buffer)
- (mh-compose-and-send-mail draft "" from-folder nil nil nil nil nil nil
- config)))
-
-
-(defun mh-extract-rejected-mail (msg)
- "Extract a letter returned by the mail system and make it resendable.
-Default is the current message. The variable mh-new-draft-cleaned-headers
-gives the headers to clean out of the original message.
-See also documentation for `\\[mh-send]' function."
- (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)
- (skip-chars-forward " \t\n")
- (delete-region (point-min) (point))
- (mh-clean-msg-header (point-min) mh-new-draft-cleaned-headers nil))
- (t
- (message "Does not appear to be a rejected letter.")))
- (goto-char (point-min))
- (save-buffer)
- (mh-compose-and-send-mail draft "" from-folder msg
- (mh-get-header-field "To:")
- (mh-get-header-field "From:")
- (mh-get-header-field "Cc:")
- nil nil config)))
-
-
-(defun mh-forward (to cc &optional msg-or-seq)
- "Forward a message or message sequence. Defaults to displayed message.
-If optional prefix argument provided, then prompt for the message sequence.
-See also documentation for `\\[mh-send]' function."
- (interactive (list (mh-read-address "To: ")
- (mh-read-address "Cc: ")
- (if current-prefix-arg
- (mh-read-seq-default "Forward" t)
- (mh-get-msg-num t))))
- (or msg-or-seq
- (setq msg-or-seq (mh-get-msg-num t)))
- (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)
- (save-buffer)))
- (t
- (mh-read-draft "" draft-name nil)))))
- (let (orig-from
- orig-subject)
- (goto-char (point-min))
- (re-search-forward "^------- Forwarded Message")
- (forward-line 1)
- (skip-chars-forward " \t\n")
- (save-restriction
- (narrow-to-region (point) (point-max))
- (setq orig-from (mh-get-header-field "From:"))
- (setq orig-subject (mh-get-header-field "Subject:")))
- (let ((forw-subject
- (mh-forwarded-letter-subject orig-from orig-subject)))
- (mh-insert-fields "Subject:" forw-subject)
- (goto-char (point-min))
- (re-search-forward "^------- Forwarded Message")
- (forward-line -1)
- (delete-other-windows)
- (if (numberp msg-or-seq)
- (mh-add-msgs-to-seq msg-or-seq 'forwarded t)
- (mh-add-msgs-to-seq (mh-seq-to-msgs msg-or-seq) 'forwarded t))
- (mh-compose-and-send-mail draft "" folder msg-or-seq
- to forw-subject cc
- mh-note-forw "Forwarded:"
- config)))))
-
-(defun mh-forwarded-letter-subject (from subject)
- ;; Return a Subject suitable for a forwarded message.
- ;; Original message has headers FROM and SUBJECT.
- (let ((addr-start (string-match "<" from))
- (comment (string-match "(" from)))
- (cond ((and addr-start (> addr-start 0))
- ;; Full Name <luser@host>
- (setq from (substring from 0 (1- addr-start))))
- (comment
- ;; luser@host (Full Name)
- (setq from (substring from (1+ comment) (1- (length from)))))))
- (format mh-forward-subject-format from subject))
-
-
-;;;###autoload
-(defun mh-smail-other-window ()
- "Compose and send mail in other window with the MH mail system.
-This function is an entry point to mh-e, the Emacs front end
-to the MH mail system.
-
-See documentation of `\\[mh-send]' for more details on composing mail."
- (interactive)
- (mh-find-path)
- (call-interactively 'mh-send-other-window))
-
-
-(defun mh-redistribute (to cc &optional 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 (mh-read-address "Redist-To: ")
- (mh-read-address "Redist-Cc: ")
- (mh-get-msg-num t)))
- (or msg
- (setq msg (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 mh-send-prog 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 mh-send-prog 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-reply (message &optional includep)
- "Reply to MESSAGE (default: current message).
-If optional prefix argument INCLUDEP provided, then include the message
-in the reply using filter mhl.reply in your MH directory.
-Prompts for type of addresses to reply to:
- from sender only,
- to sender and primary recipients,
- cc/all sender and all recipients.
-If the file named by `mh-repl-formfile' exists, it is used as a skeleton
-for the reply. See also documentation for `\\[mh-send]' function."
- (interactive (list (mh-get-msg-num t) current-prefix-arg))
- (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...")
- (mh-exec-cmd "repl" "-build" "-noquery" "-nodraftfolder"
- (if (stringp mh-repl-formfile) ;must be string, but we're paranoid
- (list "-form" mh-repl-formfile))
- mh-current-folder message
- (cond ((or (equal reply-to "from") (equal reply-to ""))
- '("-nocc" "all"))
- ((equal reply-to "to")
- '("-cc" "to"))
- ((or (equal reply-to "cc") (equal reply-to "all"))
- '("-cc" "all" "-nocc" "me")))
- (if includep
- '("-filter" "mhl.reply")))
- (let ((draft (mh-read-draft "reply"
- (expand-file-name "reply" mh-user-path)
- t)))
- (delete-other-windows)
- (save-buffer)
-
- (let ((to (mh-get-header-field "To:"))
- (subject (mh-get-header-field "Subject:"))
- (cc (mh-get-header-field "Cc:")))
- (goto-char (point-min))
- (mh-goto-header-end 1)
- (or includep
- (mh-in-show-buffer (show-buffer)
- (mh-display-msg message folder)))
- (mh-add-msgs-to-seq message 'answered t)
- (message "Composing a reply...done")
- (mh-compose-and-send-mail draft "" folder message to subject cc
- mh-note-repl "Replied:" config))))))
-
-
-(defun mh-send (to cc subject)
- "Compose and send a letter.
-The file named by `mh-comp-formfile' will be used as the form.
-Do not call this function from outside mh-e; use \\[mh-smail] instead.
-
-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 (list
- (mh-read-address "To: ")
- (mh-read-address "Cc: ")
- (read-string "Subject: ")))
- (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.
-Do not call this function from outside mh-e;
-use \\[mh-smail-other-window] instead.
-See also documentation for `\\[mh-send]' function."
- (interactive (list
- (mh-read-address "To: ")
- (mh-read-address "Cc: ")
- (read-string "Subject: ")))
- (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"
- (let (components)
- (cond
- ((file-exists-p
- (setq components
- (expand-file-name mh-comp-formfile mh-user-path)))
- components)
- ((file-exists-p
- (setq components
- (expand-file-name mh-comp-formfile mh-lib)))
- components)
- (t
- (error (format "Can't find components file \"%s\""
- components)))))
- nil)))
- (mh-insert-fields "To:" to "Subject:" subject "Cc:" cc)
- (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-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)
- (draft-file-name (mh-new-draft-name)))
- (pop-to-buffer (generate-new-buffer
- (format "draft-%s"
- (file-name-nondirectory draft-file-name))))
- (condition-case ()
- (insert-file-contents draft-file-name t)
- (file-error))
- (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)
- (cond ((and (file-exists-p draft-name)
- (not (equal draft-name initial-contents)))
- (insert-file-contents draft-name)
- (delete-file draft-name))))))
- (cond ((and initial-contents
- (or (zerop (buffer-size))
- (if (y-or-n-p
- (format "A draft exists. Use for %s? " use))
- (if mh-error-if-no-draft
- (error "A prior draft exists."))
- t)))
- (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
- (mh-exec-cmd-quiet t "mhpath" mh-draft-folder "new")
- (buffer-substring (point-min) (1- (point-max)))))
-
-
-(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-insert-fields (&rest name-values)
- ;; Insert the NAME-VALUE pairs in the current buffer.
- ;; If field NAME exists, append VALUE to it.
- ;; 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))))
- (cond ((equal value "")
- nil)
- ((mh-position-on-field field-name)
- (insert " " value))
- (t
- (insert field-name " " value "\n")))
- (setq name-values (cdr (cdr name-values)))))))
-
-
-(defun mh-position-on-field (field &optional ignore)
- ;; Move to the end of the FIELD in the header.
- ;; Move to end of entire header if FIELD not found.
- ;; Returns non-nil iff FIELD was found.
- ;; The optional second arg is for pre-version 4 compatibility.
- (if (mh-goto-header-field field)
- (progn
- (mh-header-field-end)
- t)))
-
-
-(defun mh-get-header-field (field)
- ;; Find and return the body of FIELD in the mail header.
- ;; Returns the empty string if the field is not in the header of the
- ;; current buffer.
- (if (mh-goto-header-field field)
- (progn
- (skip-chars-forward " \t") ;strip leading white space in body
- (let ((start (point)))
- (mh-header-field-end)
- (buffer-substring start (point))))
- ""))
-
-(fset 'mh-get-field 'mh-get-header-field) ;mh-e 4 compatibility
-
-(defun mh-goto-header-field (field)
- ;; Move to FIELD in the message header.
- ;; Move to the end of the FIELD name, which should end in a colon.
- ;; Returns T if found, NIL if not.
- (goto-char (point-min))
- (let ((case-fold-search t)
- (headers-end (save-excursion
- (mh-goto-header-end 0)
- (point))))
- (re-search-forward (format "^%s" field) headers-end t)))
-
-(defun mh-header-field-end ()
- ;; Move to the end of the current header field.
- ;; Handles RFC 822 continuation lines.
- (forward-line 1)
- (while (looking-at "^[ \t]")
- (forward-line 1))
- (backward-char 1)) ;to end of previous line
-
-
-(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)))
-
-
-(defun mh-read-address (prompt)
- ;; Read a To: or Cc: address, prompting in the minibuffer with PROMPT.
- ;; May someday do completion on aliases.
- (read-string prompt))
-
-
-
-;;; Mode for composing and sending a draft message.
-
-(defvar mh-sent-from-folder nil) ;Folder of msg assoc with this letter.
-
-(defvar mh-sent-from-msg nil) ;Number of msg assoc with this letter.
-
-(defvar mh-send-args nil) ;Extra args 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.
-
-(put 'mh-letter-mode 'mode-class 'special)
-
-;;;###autoload
-(defun mh-letter-mode ()
- "Mode for composing letters in mh-e.\\<mh-letter-mode-map>
-When you have finished composing, type \\[mh-send-letter] to send the message
-using the MH mail handling system.
-See the documentation for \\[mh-edit-mhn] for information on composing MIME
-messages.
-
-\\{mh-letter-mode-map}
-
-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.
-
- mh-ins-buf-prefix (\"> \")
- String to insert before each non-blank line of a message as it is
- inserted in a draft letter.
-
- mh-signature-file-name (\"~/.signature\")
- File to be inserted into message by \\[mh-insert-signature].
-
-Upon invoking mh-letter-mode, text-mode-hook and mh-letter-mode-hook are
-invoked with no args, if those values are non-nil."
-
- (interactive)
- (or mh-user-path (mh-find-path))
- (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)
- (make-local-variable 'mail-header-separator)
- (setq mail-header-separator "--------") ;for Hyperbole
- (use-local-map mh-letter-mode-map)
- (setq major-mode 'mh-letter-mode)
- (mh-set-mode-name "MH-Letter")
- (set-syntax-table mh-letter-mode-syntax-table)
- (run-hooks 'text-mode-hook)
- ;; if text-mode-hook turned on auto-fill, tune it for messages
- (cond ((and (boundp 'auto-fill-hook) auto-fill-hook) ;emacs 18
- (make-local-variable 'auto-fill-hook)
- (setq auto-fill-hook 'mh-auto-fill-for-letter)))
- (cond ((and (boundp 'auto-fill-function) auto-fill-function) ;emacs 19
- (make-local-variable 'auto-fill-function)
- (setq auto-fill-function 'mh-auto-fill-for-letter)))
- (run-hooks 'mh-letter-mode-hook))
-
-
-(defun mh-auto-fill-for-letter ()
- ;; Auto-fill in letters treats the header specially by inserting a tab
- ;; before continuation line.
- (if (mh-in-header-p)
- (let ((fill-prefix "\t"))
- (do-auto-fill))
- (do-auto-fill)))
-
-
-(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 (point-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 (the last keystroke
-of the command) according to the list in the variable mh-to-field-choices.
-Create the field if it does not exist. Set the mark to point before moving."
- (interactive)
- (expand-abbrev)
- (let ((target (cdr (or (assoc (char-to-string (logior last-input-char ?`))
- mh-to-field-choices)
- ;; also look for a char for version 4 compat
- (assoc (logior last-input-char ?`) mh-to-field-choices))))
- (case-fold-search t))
- (push-mark)
- (cond ((mh-position-on-field target)
- (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
- (if (mh-position-on-field "To:")
- (forward-line 1))
- (insert (format "%s \n" target))
- (backward-char 1)))))
-
-
-(defun mh-to-fcc (&optional folder)
- "Insert an Fcc: FOLDER field in the current message.
-Prompt for the field name with a completion list of the current folders."
- (interactive)
- (or folder
- (setq folder (mh-prompt-for-folder
- "Fcc"
- (or (and mh-default-folder-for-message-function
- (save-excursion
- (goto-char (point-min))
- (funcall mh-default-folder-for-message-function)))
- "")
- t)))
- (let ((last-input-char ?\C-f))
- (expand-abbrev)
- (save-excursion
- (mh-to-field)
- (insert (if (mh-folder-name-p folder)
- (substring folder 1)
- folder)))))
-
-
-(defun mh-insert-signature ()
- "Insert the file named by mh-signature-file-name at the current point."
- (interactive)
- (insert-file-contents mh-signature-file-name)
- (force-mode-line-update))
-
-
-(defun mh-check-whom ()
- "Verify recipients of the current letter, showing expansion of any aliases."
- (interactive)
- (let ((file-name buffer-file-name))
- (save-buffer)
- (message "Checking recipients...")
- (mh-in-show-buffer ("*Recipients*")
- (bury-buffer (current-buffer))
- (erase-buffer)
- (mh-exec-cmd-output "whom" t file-name))
- (message "Checking recipients...done")))
-
-
-
-;;; 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)
- mh-compose-letter-function)
- ;; run-hooks will not pass arguments.
- (let ((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)
- (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)
- (mh-exec-cmd-output mh-send-prog t "-watch" "-nopush"
- "-nodraftfolder" mh-send-args file-name)
- (goto-char (point-max)) ; show the interesting part
- (recenter -1)
- (set-buffer draft-buffer)) ; for annotation below
- (t
- (mh-exec-cmd-daemon mh-send-prog "-nodraftfolder" "-noverbose"
- mh-send-args 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-header-field "To:")
- (mh-get-header-field "Cc:"))))
-
- (cond ((or (not arg)
- (y-or-n-p "Kill draft buffer? "))
- (kill-buffer draft-buffer)
- (if config
- (set-window-configuration config))))
- (if arg
- (message "Sending...done")
- (message "Sending...backgrounded"))))
-
-
-(defun mh-insert-letter (folder message verbatim)
- "Insert a message into the current letter.
-Removes the message's headers using mh-invisible-headers. Prefixes
-each non-blank line with mh-ins-buf-prefix. Prompts for FOLDER and
-MESSAGE. If prefix argument VERBATIM provided, do not indent and do
-not delete headers. Leaves the mark before the letter and point after it."
- (interactive
- (list (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)
- "")))
- current-prefix-arg))
- (save-restriction
- (narrow-to-region (point) (point))
- (let ((start (point-min)))
- (if (equal message "") (setq message (int-to-string mh-sent-from-msg)))
- (mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear"
- (expand-file-name message
- (mh-expand-file-name folder)))
- (cond ((not verbatim)
- (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 ((if (boundp 'mark-active)
- mark-active ;Emacs 19
- (mark)) ;Emacs 18
- (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)
- (save-restriction
- (narrow-to-region to-point to-point)
- (push-mark)
- (insert mh-ins-str)
- (mh-insert-prefix-string mh-ins-buf-prefix)
- (insert "\n"))))
- (error "There is no current message")))
-
-
-(defun mh-insert-prefix-string (mh-ins-string)
- ;; Run mail-citation-hook to insert a prefix string before each line
- ;; in the buffer. Generality for supercite users.
- (set-mark (point-max))
- (goto-char (point-min))
- (cond (mail-citation-hook
- (run-hooks 'mail-citation-hook))
- (mh-yank-hooks ;old hook name
- (run-hooks 'mh-yank-hooks))
- (t
- (or (bolp) (forward-line 1))
- (let ((zmacs-regions nil)) ;so "(mark)" works in XEmacs
- (while (< (point) (mark))
- (insert mh-ins-string)
- (forward-line 1))))))
-
-
-(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")))
-
-
-;;; 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-d" '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-r" 'mh-to-field)
-(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-fd" '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-fr" 'mh-to-field)
-(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-i" 'mh-insert-letter)
-(define-key mh-letter-mode-map "\C-c\C-q" 'mh-fully-kill-draft)
-(define-key mh-letter-mode-map "\C-c\C-\\" 'mh-fully-kill-draft) ;if no C-q
-(define-key mh-letter-mode-map "\C-c\C-s" 'mh-insert-signature)
-(define-key mh-letter-mode-map "\C-c\C-^" 'mh-insert-signature) ;if no C-s
-(define-key mh-letter-mode-map "\C-c\C-w" 'mh-check-whom)
-(define-key mh-letter-mode-map "\C-c\C-y" 'mh-yank-cur-msg)
-(define-key mh-letter-mode-map "\C-c\C-c" 'mh-send-letter)
-(define-key mh-letter-mode-map "\C-c\C-m\C-f" 'mh-mhn-compose-forw)
-(define-key mh-letter-mode-map "\C-c\C-m\C-e" 'mh-mhn-compose-anon-ftp)
-(define-key mh-letter-mode-map "\C-c\C-m\C-t" 'mh-mhn-compose-external-compressed-tar)
-(define-key mh-letter-mode-map "\C-c\C-m\C-i" 'mh-mhn-compose-insertion)
-(define-key mh-letter-mode-map "\C-c\C-e" 'mh-edit-mhn)
-(define-key mh-letter-mode-map "\C-c\C-m\C-u" 'mh-revert-mhn-edit)
-
-;; "C-c /" prefix is used in mh-letter-mode by pgp.el
-
-;;; autoloads from mh-mime
-
-(autoload 'mh-mhn-compose-insertion "mh-mime"
- "Add a directive to insert a MIME message part from a file.
-This is the typical way to insert non-text parts in a message.
-See also \\[mh-edit-mhn]." t)
-
-(autoload 'mh-mhn-compose-anon-ftp "mh-mime"
- "Add a directive for a MIME anonymous ftp external body part.
-This directive tells MH to include a reference to a
-message/external-body part retrievable by anonymous FTP.
-See also \\[mh-edit-mhn]." t)
-
-(autoload 'mh-mhn-compose-external-compressed-tar "mh-mime"
- "Add a directive to include a MIME reference to a compressed tar file.
-The file should be available via anonymous ftp. This directive
-tells MH to include a reference to a message/external-body part.
-See also \\[mh-edit-mhn]." t)
-
-(autoload 'mh-mhn-compose-forw "mh-mime"
- "Add a forw directive to this message, to forward a message with MIME.
-This directive tells MH to include another message in this one.
-See also \\[mh-edit-mhn]." t)
-
-(autoload 'mh-edit-mhn "mh-mime"
- "Format the current draft for MIME, expanding any mhn directives.
-Process the current draft with the mhn program, which,
-using directives already inserted in the draft, fills in
-all the MIME components and header fields.
-This step should be done last just before sending the message.
-The mhn program is part of MH version 6.8 or later.
-The `\\[mh-revert-mhn-edit]' command undoes this command.
-For assistance with creating mhn directives to insert
-various types of components in a message, see
-\\[mh-mhn-compose-insertion] (generic insertion from a file),
-\\[mh-mhn-compose-anon-ftp] (external reference to file via anonymous ftp),
-\\[mh-mhn-compose-external-compressed-tar] \
-\(reference to compressed tar file via anonymous ftp), and
-\\[mh-mhn-compose-forw] (forward message)." t)
-
-(autoload 'mh-revert-mhn-edit "mh-mime"
- "Undoes the effect of \\[mh-edit-mhn] by reverting to the backup file.
-Optional non-nil argument means don't ask for confirmation." t)
diff --git a/lisp/mail/mh-e.el b/lisp/mail/mh-e.el
deleted file mode 100644
index 0a32ca2768d..00000000000
--- a/lisp/mail/mh-e.el
+++ /dev/null
@@ -1,1484 +0,0 @@
-;;; mh-e.el --- GNU Emacs interface to the MH mail system
-
-;; Copyright (C) 1985,86,87,88,90,92,93,94,95 Free Software Foundation, Inc.
-
-;; Maintainer: Stephen Gildea <gildea@lcs.mit.edu>
-;; Version: 5.0.2
-;; Keywords: mail
-;; Bug-reports: include `M-x mh-version' output in any correspondence
-
-;; This file is part of mh-e, part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; 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.
-
-;; MH (Message Handler) is a powerful mail reader. The MH newsgroup
-;; is comp.mail.mh; the mailing list is mh-users@ics.uci.edu (send to
-;; mh-users-request to be added). See the monthly Frequently Asked
-;; Questions posting there for information on getting MH and mh-e.
-
-;; mh-e is an Emacs interface to the MH mail system.
-;; The mailing list mh-e@x.org is for discussion of mh-e and
-;; announcements of new versions. Send a "subscribe" message to
-;; mh-e-request@x.org to be added. Do not report bugs here; mail
-;; them directly to the author (see top of mh-e.el source).
-;; Include the output of M-x mh-version in any bug report.
-
-;; mh-e works with GNU Emacs 18 or 19, and MH 6.
-
-;; NB. MH must have been compiled with the MHE compiler flag or several
-;; features necessary for mh-e will be missing from MH commands, specifically
-;; the -build switch to repl and forw.
-
-;; Your .emacs might benefit from these bindings:
-;; (global-set-key "\C-cr" 'mh-rmail)
-;; (global-set-key "\C-xm" 'mh-smail)
-;; (global-set-key "\C-x4m" 'mh-smail-other-window)
-
-;;; Change Log:
-
-;; 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 1988. gildea@lcs.mit.edu
-(defconst mh-e-RCS-id "$Id: mh-e.el,v 1.13 1996/01/25 01:02:59 kwzh Exp kwzh $")
-
-;;; Code:
-
-(provide 'mh-e)
-(require 'mh-utils)
-
-
-;;; Hooks:
-
-(defvar mh-folder-mode-hook nil
- "Invoked in MH-Folder mode on a new folder.")
-
-(defvar mh-inc-folder-hook nil
- "Invoked by \\<mh-folder-mode-map>`\\[mh-inc-folder]' after incorporating mail into a folder.")
-
-(defvar mh-show-hook nil
- "Invoked after \\<mh-folder-mode-map>`\\[mh-show]' shows a message.")
-
-(defvar mh-show-mode-hook nil
- "Invoked in MH-Show mode on each message.")
-
-(defvar mh-delete-msg-hook nil
- "Invoked after marking each message for deletion.")
-
-(defvar mh-refile-msg-hook nil
- "Invoked after marking each message for refiling.")
-
-(defvar mh-before-quit-hook nil
- "Invoked by \\<mh-folder-mode-map>`\\[mh-quit]' before quitting mh-e. See also mh-quit-hook.")
-
-(defvar mh-quit-hook nil
- "Invoked after \\<mh-folder-mode-map>`\\[mh-quit]' quits mh-e. See also mh-before-quit-hook.")
-
-
-
-;;; Personal preferences:
-
-(defvar mh-lpr-command-format "lpr -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 formatted
-message text is piped to this command when you type \\<mh-folder-mode-map>`\\[mh-print-msg]'.")
-
-(defvar mh-scan-prog "scan"
- "*Program to run to generate one-line-per-message listing of a folder.
-Normally \"scan\" or a file name linked to scan. This file is searched
-for relative to the mh-progs directory unless it is an absolute pathname.
-Automatically becomes buffer-local when set in any fashion.")
-(make-variable-buffer-local 'mh-scan-prog)
-
-(defvar mh-inc-prog "inc"
- "*Program to run to incorporate new mail into a folder.
-Normally \"inc\". This file is searched for relative to
-the mh-progs directory unless it is an absolute pathname.")
-
-(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-recenter-summary-p nil
- "*Recenter summary window when the show window is toggled off if non-nil.")
-
-(defvar mh-do-not-confirm nil
- "*Non-nil means do not prompt for confirmation before some mh-e commands.
-Affects non-recoverable commands such as mh-kill-folder and mh-undo-folder.")
-
-(defvar mh-store-default-directory nil
- "*Last directory used by \\[mh-store-msg]; default for next store.
-A directory name string, or nil to use current directory.")
-
-;;; Parameterize mh-e to work with different scan formats. The defaults work
-;;; with the standard MH scan listings, in which the first 4 characters on
-;;; the line are the message number, followed by two places for notations.
-
-(defvar mh-good-msg-regexp "^....[^D^]"
- "Regexp specifying 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-cur-scan-msg-regexp "^....\\+"
- "Regexp matching scan line for the cur message.")
-
-(defvar mh-note-deleted "D"
- "String whose first character is used to notate deleted messages.")
-
-(defvar mh-note-refiled "^"
- "String whose first character is used to notate refiled messages.")
-
-(defvar mh-note-cur "+"
- "String whose first character is used to notate the current message.")
-
-(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.")
-
-
-;;; Internal variables:
-
-(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-delete-list nil) ;List of msg numbers to delete.
-
-(defvar mh-refile-list nil) ;List of folder names in mh-seq-list.
-
-(defvar mh-next-direction 'forward) ;Direction to move to next message.
-
-(defvar mh-narrowed-to-seq nil) ;Sequence display is narrowed to or nil if not narrowed.
-
-(defvar mh-first-msg-num nil) ;Number of first msg in buffer.
-
-(defvar mh-last-msg-num nil) ;Number of last msg in buffer.
-
-(defvar mh-mode-line-annotation nil) ;Indiction this is not the full folder.
-
-;;; Macros and generic functions:
-
-(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 with MH, or, with arg, scan an MH mail folder.
-This function is an entry point to mh-e, the Emacs front end
-to the MH mail system."
- (interactive "P")
- (mh-find-path)
- (if arg
- (call-interactively 'mh-visit-folder)
- (mh-inc-folder)))
-
-
-;;; mh-smail and mh-smail-other-window have been moved to the new file
-;;; mh-comp.el, but Emacs 18 still looks for them here, so provide a
-;;; definition here, too, for a while.
-
-(defun mh-smail ()
- "Compose and send mail with the MH mail system.
-This function is an entry point to mh-e, the Emacs front end
-to the MH mail system."
- (interactive)
- (mh-find-path)
- (require 'mh-comp)
- (call-interactively 'mh-send))
-
-
-(defun mh-smail-other-window ()
- "Compose and send mail in other window with the MH mail system.
-This function is an entry point to mh-e, the Emacs front end
-to the MH mail system."
- (interactive)
- (mh-find-path)
- (require 'mh-comp)
- (call-interactively 'mh-send-other-window))
-
-
-
-;;; User executable mh-e commands:
-
-
-(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))))
- (mh-delete-msg-no-motion 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-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 [local-]write-file-hooks
-
-
-(defun mh-first-msg ()
- "Move to the first message."
- (interactive)
- (goto-char (point-min))
- (while (and (not (eobp)) (not (looking-at mh-valid-scan-line)))
- (forward-line 1)))
-
-
-(defun mh-header-display ()
- "Show the current message with all its headers.
-Displays headers that might have been suppressed by setting the
-variables `mh-clean-message-header' or `mhl-formfile', or by the fallback
-behavior of scrolling uninteresting headers off the top of the window.
-Type \"\\[mh-show]\" to show the message normally again."
- (interactive)
- (and (not mh-showing-with-headers)
- (or mhl-formfile mh-clean-message-header)
- (mh-invalidate-show-buffer))
- (let ((mhl-formfile nil)
- (mh-clean-message-header nil))
- (mh-show-msg nil)
- (mh-in-show-buffer (mh-show-buffer)
- (goto-char (point-min))
- (mh-recenter 0))
- (setq mh-showing-with-headers t)))
-
-
-(defun mh-inc-folder (&optional maildrop-name)
- "Inc(orporate)s new mail into the Inbox folder.
-Optional prefix argument specifies an alternate maildrop from the default.
-If the prefix argument is given, incorporates mail into the current
-folder, otherwise uses the folder named by `mh-inbox'.
-Runs `mh-inc-folder-hook' after incorporating new mail.
-Do not call this function from outside mh-e; use \\[mh-rmail] instead."
- (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 mh-inbox))
- (mh-make-folder mh-inbox)
- (setq mh-previous-window-config config))
- ((not (eq (current-buffer) (get-buffer mh-inbox)))
- (switch-to-buffer mh-inbox)
- (setq mh-previous-window-config config)))))
- (mh-get-new-mail maildrop-name)
- (run-hooks 'mh-inc-folder-hook))
-
-
-(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-next-undeleted-msg (&optional arg)
- "Move to the NTH next undeleted message in window."
- (interactive "p")
- (setq mh-next-direction 'forward)
- (forward-line 1)
- (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-refile-msg (msg-or-seq folder)
- "Refile MESSAGE(s) (default: displayed message) into FOLDER.
-If optional prefix argument provided, then prompt for message sequence."
- (interactive
- (list (if current-prefix-arg
- (mh-read-seq-default "Refile" t)
- (mh-get-msg-num t))
- (intern
- (mh-prompt-for-folder
- "Destination"
- (or (and mh-default-folder-for-message-function
- (let ((refile-file (mh-msg-filename (mh-get-msg-num t))))
- (save-excursion
- (set-buffer (get-buffer-create mh-temp-buffer))
- (erase-buffer)
- (insert-file-contents refile-file)
- (let ((buffer-file-name refile-file))
- (funcall mh-default-folder-for-message-function)))))
- (and (eq 'refile (car mh-last-destination))
- (symbol-name (cdr mh-last-destination)))
- "")
- t))))
- (setq mh-last-destination (cons 'refile folder))
- (if (numberp msg-or-seq)
- (mh-refile-a-msg msg-or-seq folder)
- (mh-map-to-seq-msgs 'mh-refile-a-msg msg-or-seq folder))
- (mh-next-msg))
-
-
-(defun mh-refile-or-write-again (message)
- "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 message (cdr mh-last-destination))
- (message "Destination folder: %s" (cdr mh-last-destination)))
- (t
- (apply 'mh-write-msg-to-file message (cdr mh-last-destination))
- (message "Destination: %s" (cdr mh-last-destination))))
- (mh-next-msg))
-
-
-(defun mh-quit ()
- "Quit the current mh-e folder.
-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)
- (mh-update-sequences)
- (mh-invalidate-show-buffer)
- (bury-buffer (current-buffer))
- (if (get-buffer mh-show-buffer)
- (bury-buffer mh-show-buffer))
- (if mh-previous-window-config
- (set-window-configuration mh-previous-window-config))
- (run-hooks 'mh-quit-hook))
-
-(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")
- (mh-in-show-buffer (mh-show-buffer)
- (scroll-down arg)))
-
-
-(defun mh-previous-undeleted-msg (&optional arg)
- "Move to the NTH 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-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-write-msg-to-file (msg file no-headers)
- "Append MESSAGE to the end of a FILE.
-If NO-HEADERS (prefix argument) is provided, write only the message body.
-Otherwise send the entire message including the headers."
- (interactive
- (list (mh-get-msg-num t)
- (let ((default-dir (if (eq 'write (car mh-last-destination))
- (file-name-directory (car (cdr mh-last-destination)))
- default-directory)))
- (read-file-name (format "Save message%s in file: "
- (if current-prefix-arg " body" ""))
- default-dir
- (if (eq 'write (car mh-last-destination))
- (car (cdr mh-last-destination))
- (expand-file-name "mail.out" default-dir))))
- current-prefix-arg))
- (let ((msg-file-to-output (mh-msg-filename msg))
- (output-file (mh-expand-file-name file)))
- (setq mh-last-destination (list 'write file (if no-headers 'no-headers)))
- (save-excursion
- (set-buffer (get-buffer-create mh-temp-buffer))
- (erase-buffer)
- (insert-file-contents msg-file-to-output)
- (goto-char (point-min))
- (if no-headers (search-forward "\n\n"))
- (append-to-file (point) (point-max) output-file))))
-
-
-(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 (msg-or-seq)
- "Undo the pending 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 (if current-prefix-arg
- (mh-read-seq-default "Undo" t)
- (mh-get-msg-num t))))
- (cond ((numberp msg-or-seq)
- (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"))))
- (t
- (mh-map-to-seq-msgs 'mh-undo-msg msg-or-seq)))
- ;; 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)))
-
-
-;;;###autoload
-(defun mh-version ()
- "Display version information about mh-e and the MH mail handling system."
- (interactive)
- (mh-find-progs)
- (set-buffer (get-buffer-create mh-temp-buffer))
- (erase-buffer)
- (insert " mh-e info:\n\nversion: " mh-e-RCS-id
- "\nEmacs: " emacs-version " on " (symbol-name system-type) " ")
- (condition-case ()
- (call-process "uname" nil t nil "-a")
- (file-error))
- (insert "\n\n MH info:\n\n" (expand-file-name "inc" mh-progs) ":\n")
- (let ((help-start (point)))
- (condition-case err-data
- (mh-exec-cmd-output "inc" nil "-help")
- (file-error (insert (mapconcat 'concat (cdr err-data) ": "))))
- (goto-char help-start)
- (search-forward "version: " nil t)
- (beginning-of-line)
- (delete-region help-start (point))
- (goto-char (point-min)))
- (display-buffer mh-temp-buffer))
-
-
-(defun mh-visit-folder (folder &optional range)
- "Visit FOLDER and display RANGE of messages.
-Do not call this function from outside mh-e; see \\[mh-rmail] instead."
- (interactive (list (mh-prompt-for-folder "Visit" mh-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-compat-quit ()
- "The \"b\" key is obsolescent; will assume you want \"\\[mh-quit]\" ..."
- ;; Was going to make it run mh-burst-digest, but got complaint that
- ;; 'b' should mean 'back', as it does in info, less, and rn.
- ;; This is a temporary compatibility function.
- (interactive)
- (message "%s" (documentation this-command))
- (sit-for 1)
- (call-interactively 'mh-quit))
-
-
-(defun mh-update-sequences ()
- "Update MH's Unseen sequence and current folder and message.
-Flush mh-e's state out to MH. The message at the cursor becomes current."
- (interactive)
- ;; mh-update-sequences is the opposite of mh-read-folder-sequences,
- ;; which updates mh-e's state from MH.
- (let ((folder-set (mh-update-unseen))
- (new-cur (mh-get-msg-num nil)))
- (if new-cur
- (let ((seq-entry (mh-find-seq 'cur)))
- (mh-remove-cur-notation)
- (setcdr seq-entry (list new-cur)) ;delete-seq-locally, add-msgs-to-seq
- (mh-define-sequence 'cur (list new-cur))
- (beginning-of-line)
- (if (looking-at mh-good-msg-regexp)
- (mh-notate nil mh-note-cur mh-cmd-note)))
- (or folder-set
- (save-excursion
- (mh-exec-cmd-quiet t "folder" mh-current-folder "-fast"))))))
-
-
-
-
-;;; 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)
- (setq mh-delete-list (cons msg mh-delete-list))
- (mh-add-msgs-to-seq msg 'deleted t)
- (mh-notate msg mh-note-deleted mh-cmd-note)
- (run-hooks 'mh-delete-msg-hook))))
-
-(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))
- (setq mh-refile-list (cons 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-note-refiled mh-cmd-note)
- (run-hooks 'mh-refile-msg-hook)))))
-
-
-(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))
- (setq mh-showing nil)
- (force-mode-line-update)
- (if mh-recenter-summary-p
- (mh-recenter 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-delete-msg-from-seq msg 'deleted t))
- (t
- (mh-mapc (function (lambda (dest)
- (mh-delete-msg-from-seq msg dest t)))
- mh-refile-list)))
- (mh-notate msg ? mh-cmd-note))
-
-
-
-
-;;; The folder data abstraction.
-
-(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-make-folder-mode-line))
-
-
-;;; Ensure new buffers won't get this mode if default-major-mode is nil.
-(put 'mh-folder-mode 'mode-class 'special)
-
-(defun mh-folder-mode ()
- "Major mh-e mode for \"editing\" an MH folder scan listing.\\<mh-folder-mode-map>
-You can show the message the cursor is pointing to, and step through the
-messages. Messages can be marked for deletion or refiling into another
-folder; these commands are executed all at once with a separate command.
-
-A prefix argument (\\[universal-argument]) to delete, refile, list, or undo
-applies the action to a message sequence.
-
-Here is a list of the standard keys for mh-e commands, grouped by function.
-This list is purposefully not customized; mh-e has a long history, and many
-alternate key bindings as a result. This list is to encourage users to use
-standard keys so the other keys can perhaps someday be put to new uses.
-
-t toggle show or scan-only mode
-RET show message, or back to top if already showing
-
-SPC page message forward
-DEL page message back
-
-n next message
-p previous message
-g go to message by number
-
-d mark for deletion
-o, ^ mark for output (refile) to another folder
-? show folder of pending refile
-u undo delete or refile marking
-
-x execute marked deletes and refiles
-i incorporate new mail
-
-m mail a new message
-r reply to a message
-f forward a message
-
-q quit mh-e
-
-M-f visit new folder
-M-r rescan this folder
-
-Here are all the commands with their current binding, listed in key order:
-\\{mh-folder-mode-map}
-
-Variables controlling mh-e operation are (defaults in parentheses):
-
- mh-recursive-folders (nil)
- Non-nil means commands which operate on folders do so recursively.
-
- 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-scan-prog (\"scan\")
- Program to run to generate one-line-per-message listing of a folder.
- Normally \"scan\" or a file name linked to scan. This file is searched
- for relative to the mh-progs directory unless it is an absolute pathname.
- Automatically becomes buffer-local when set in any fashion.
-
- 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.
-
- 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.
-
-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-Folder")
- (mh-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-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-msg-count nil ; Number of msgs in buffer
- 'mh-mode-line-annotation nil ; Indiction this is not the full folder
- 'mh-previous-window-config nil) ; Previous window configuration
- (setq truncate-lines t)
- (auto-save-mode -1)
- (setq buffer-offer-save t)
- (if (boundp 'local-write-file-hooks)
- (setq local-write-file-hooks '(mh-execute-commands)) ;Emacs 19
- (make-local-variable 'write-file-hooks)
- (setq write-file-hooks '(mh-execute-commands))) ;Emacs 18
- (make-local-variable 'revert-buffer-function)
- (setq revert-buffer-function 'mh-undo-folder)
- (or (assq 'mh-showing minor-mode-alist)
- (setq minor-mode-alist
- (cons '(mh-showing " Show") minor-mode-alist)))
- (run-hooks 'mh-folder-mode-hook))
-
-
-(defun mh-make-local-vars (&rest pairs)
- ;; Take VARIABLE-VALUE pairs and make 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)
- (cond ((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 &optional update)
- ;; scan folder over range RANGE.
- ;; If UPDATE, append the scan lines, otherwise replace.
- (let ((folder mh-current-folder)
- scan-start)
- (message "Scanning %s..." folder)
- (with-mh-folder-updating (nil)
- (if update
- (goto-char (point-max))
- (erase-buffer))
- (setq scan-start (point))
- (mh-exec-cmd-output mh-scan-prog nil
- "-noclear" "-noheader"
- "-width" (window-width)
- folder range)
- (goto-char scan-start)
- (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
- (setq mh-seq-list (mh-read-folder-sequences folder nil))
- (mh-notate-user-sequences)
- (or update
- (setq mh-mode-line-annotation
- (if (equal range "all")
- nil
- mh-partial-folder-mode-line-annotation)))
- (mh-make-folder-mode-line))
- (message "Scanning %s...done" folder)))
-
-
-(defun mh-get-new-mail (maildrop-name)
- ;; Read new mail from a maildrop into the current buffer.
- ;; Return in the current buffer.
- (let ((point-before-inc (point))
- (folder mh-current-folder)
- (new-mail-p nil))
- (with-mh-folder-updating (t)
- (if maildrop-name
- (message "inc %s -file %s..." folder maildrop-name)
- (message "inc %s..." folder))
- (setq mh-next-direction 'forward)
- (goto-char (point-max))
- (let ((start-of-inc (point)))
- (if maildrop-name
- ;; I think MH 5 used "-ms-file" instead of "-file",
- ;; which would make inc'ing from maildrops fail.
- (mh-exec-cmd-output mh-inc-prog nil folder
- "-file" (expand-file-name maildrop-name)
- "-width" (window-width)
- "-truncate")
- (mh-exec-cmd-output mh-inc-prog nil
- "-width" (window-width)))
- (if maildrop-name
- (message "inc %s -file %s...done" folder maildrop-name)
- (message "inc %s...done" folder))
- (goto-char start-of-inc)
- (cond ((save-excursion
- (re-search-forward "^inc: no mail" nil t))
- (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-remove-cur-notation)
- (setq new-mail-p t)))
- (keep-lines mh-valid-scan-line) ; Flush random scan lines
- (setq mh-seq-list (mh-read-folder-sequences folder t))
- (mh-notate-user-sequences)
- (if new-mail-p
- (progn
- (mh-make-folder-mode-line)
- (mh-goto-cur-msg))
- (goto-char point-before-inc))))))
-
-
-(defun mh-make-folder-mode-line (&optional ignored)
- ;; Set the fields of the mode line for a folder buffer.
- ;; The optional argument is now obsolete. It used to be used to pass
- ;; in what is now stored in the buffer-local variable
- ;; mh-mode-line-annotation.
- (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))
- (setq mh-msg-count (count-lines (point-min) (point-max)))
- (setq mode-line-buffer-identification
- (list (format "{%%b%s} %d msg%s"
- (if mh-mode-line-annotation
- (format "/%s" mh-mode-line-annotation)
- "")
- mh-msg-count
- (if (zerop mh-msg-count)
- "s"
- (if (> mh-msg-count 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 (1- (point-max)))
- 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 (aref mh-note-deleted 0))
- (eql char (aref mh-note-refiled 0))))
- (eql char (aref mh-note-cur 0)))
- (progn
- (delete-char 1)
- (insert " ")))
- (if remove-all-flags
- (progn
- (forward-char 1)
- (if (eql (following-char) (aref mh-note-seq 0))
- (progn
- (delete-char 1)
- (insert " ")))))
- (forward-line)))))
-
-
-(defun mh-remove-cur-notation ()
- ;; Remove old cur notation (cf mh-goto-cur-msg code).
- (let ((cur-msg (car (mh-seq-to-msgs 'cur))))
- (save-excursion
- (and cur-msg
- (mh-goto-msg cur-msg t t)
- (looking-at mh-cur-scan-msg-regexp)
- (mh-notate nil ? mh-cmd-note)))))
-
-(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 t))
- (mh-notate nil mh-note-cur mh-cmd-note)
- (mh-recenter 0)
- (mh-maybe-show cur-msg))
- (t
- (mh-last-msg)
- (message "No current message")))))
-
-
-(defun mh-process-or-undo-commands (folder)
- ;; If FOLDER has outstanding commands, then either process or discard them.
- ;; Called by functions like mh-sort-folder, so also invalidate show buffer.
- (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-update-unseen)
- (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
- (mh-update-unseen)
-
- ;; Then refile messages
- (mh-mapc
- (function
- (lambda (dest)
- (let ((msgs (mh-seq-to-msgs dest)))
- (cond (msgs
- (apply 'mh-exec-cmd "refile"
- "-src" folder (symbol-name dest)
- (mh-coalesce-msg-list msgs))
- (mh-delete-scan-msgs msgs))))))
- mh-refile-list)
- (setq mh-refile-list nil)
-
- ;; Now delete messages
- (cond (mh-delete-list
- (apply 'mh-exec-cmd "rmm" folder
- (mh-coalesce-msg-list mh-delete-list))
- (mh-delete-scan-msgs mh-delete-list)
- (setq mh-delete-list nil)))
-
- ;; 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"))))
-
- (and (buffer-file-name (get-buffer mh-show-buffer))
- (not (file-exists-p (buffer-file-name (get-buffer mh-show-buffer))))
- ;; If "inc" were to put a new msg in this file,
- ;; we would not notice, so mark it invalid now.
- (mh-invalidate-show-buffer))
-
- (setq mh-seq-list (mh-read-folder-sequences mh-current-folder nil))
- (mh-unmark-all-headers t)
- (mh-notate-user-sequences)
- (message "Processing deletes and refiles for %s...done" folder)))
-
-
-(defun mh-update-unseen ()
- ;; Flush updates to the Unseen sequence out to MH.
- ;; Return non-NIL iff set the MH folder.
- (if mh-seen-list
- (let* ((unseen-seq (mh-find-seq mh-unseen-seq))
- (unseen-msgs (mh-seq-msgs unseen-seq)))
- (if unseen-msgs
- (progn
- (mh-undefine-sequence mh-unseen-seq mh-seen-list)
- (while mh-seen-list
- (setq unseen-msgs (delq (car mh-seen-list) unseen-msgs))
- (setq mh-seen-list (cdr mh-seen-list)))
- (setcdr unseen-seq unseen-msgs)
- t) ;since we set the folder
- (setq mh-seen-list nil)))))
-
-
-(defun mh-delete-scan-msgs (msgs)
- ;; Delete the scan listing lines for each of the msgs in the LIST.
- (save-excursion
- (while msgs
- (if (mh-goto-msg (car msgs) t t)
- (mh-delete-line 1))
- (setq msgs (cdr msgs)))))
-
-
-(defun mh-outstanding-commands-p ()
- ;; Returns non-nil if there are outstanding deletes or refiles.
- (or mh-delete-list mh-refile-list))
-
-
-(defun mh-coalesce-msg-list (messages)
- ;; Give a list of MESSAGES, return a list of message number ranges.
- ;; Sort of the opposite of mh-read-msg-list, which expands ranges.
- ;; Message lists passed to MH programs go through this so
- ;; command line arguments won't exceed system limits.
- (let ((msgs (sort (copy-sequence messages) 'mh-greaterp))
- (range-high nil)
- (prev -1)
- (ranges nil))
- (while prev
- (if range-high
- (if (or (not (numberp prev))
- (not (eql (car msgs) (1- prev))))
- (progn ;non-sequential, flush old range
- (if (eql prev range-high)
- (setq ranges (cons range-high ranges))
- (setq ranges (cons (format "%s-%s" prev range-high) ranges)))
- (setq range-high nil))))
- (or range-high
- (setq range-high (car msgs))) ;start new or first range
- (setq prev (car msgs))
- (setq msgs (cdr msgs)))
- ranges))
-
-(defun mh-greaterp (msg1 msg2)
- ;; Sort two message indicators. Strings are "smaller" than numbers.
- ;; Legal values are things like "cur", "last", 1, and 1820.
- (if (numberp msg1)
- (if (numberp msg2)
- (> msg1 msg2)
- t)
- (if (numberp msg2)
- nil
- (string-lessp msg2 msg1))))
-
-
-
-;;; Basic sequence handling
-
-(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-read-folder-sequences (folder save-refiles)
- ;; Read and return the predefined sequences for a FOLDER.
- ;; If SAVE-REFILES is non-nil, then keep the sequences
- ;; that note messages to be refiled.
- (let ((seqs ()))
- (cond (save-refiles
- (mh-mapc (function (lambda (seq) ; Save the refiling sequences
- (if (mh-folder-name-p (mh-seq-name seq))
- (setq seqs (cons seq seqs)))))
- mh-seq-list)))
- (save-excursion
- (if (eq 0 (mh-exec-cmd-quiet nil "mark" folder "-list"))
- (progn
- ;; look for name in line of form "cur: 4" or "myseq (private): 23"
- (while (re-search-forward "^[^: ]+" nil t)
- (setq seqs (cons (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-read-msg-list ()
- ;; Return a list of message numbers from the current point to the end of
- ;; the line. Expands ranges into set of individual numbers.
- (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)
- (setq msgs (cons num msgs))
- (setq num (1+ num)))))
- ((not (zerop num)) ;"pick" outputs "0" to mean no match
- (setq msgs (cons num msgs)))))
- msgs))
-
-(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 mh-note-seq (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)
- (eq name mh-previous-seq)
- (mh-folder-name-p name)))
-
-
-(defun mh-delete-msg-from-seq (message sequence &optional internal-flag)
- "Delete MESSAGE from SEQUENCE. MESSAGE defaults to displayed message.
-From Lisp, optional third arg INTERNAL-FLAG non-nil means do not
-inform MH of the change."
- (interactive (list (mh-get-msg-num t)
- (mh-read-seq-default "Delete from" t)
- nil))
- (let ((entry (mh-find-seq sequence)))
- (cond (entry
- (mh-notate-if-in-one-seq message ? (1+ mh-cmd-note) sequence)
- (if (not internal-flag)
- (mh-undefine-sequence sequence (list message)))
- (setcdr entry (delq message (mh-seq-msgs entry)))))))
-
-
-(defun mh-undefine-sequence (seq msgs)
- ;; Remove from the SEQUENCE the list of MSGS.
- (mh-exec-cmd "mark" mh-current-folder "-delete"
- "-sequence" (symbol-name seq)
- (mh-coalesce-msg-list msgs)))
-
-
-(defun mh-define-sequence (seq msgs)
- ;; Define the SEQUENCE to contain the list of MSGS.
- ;; Do not mark pseudo-sequences or empty sequences.
- ;; Signals an error if SEQUENCE is an illegal name.
- (if (and msgs
- (not (mh-folder-name-p seq)))
- (save-excursion
- (mh-exec-cmd-error nil "mark" mh-current-folder "-add" "-zero"
- "-sequence" (symbol-name seq)
- (mh-coalesce-msg-list 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-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 nil)))
- (if (and (eq seq (car in-seqs)) (null (cdr in-seqs)))
- (mh-notate msg notation offset))))
-
-
-(defun mh-seq-containing-msg (msg &optional include-internal-p)
- ;; Return a list of the sequences containing MESSAGE.
- ;; If INCLUDE-INTERNAL-P non-nil, include mh-e internal sequences in list.
- (let ((l mh-seq-list)
- (seqs ()))
- (while l
- (and (memq msg (mh-seq-msgs (car l)))
- (or include-internal-p
- (not (mh-internal-seq (mh-seq-name (car l)))))
- (setq seqs (cons (mh-seq-name (car l)) seqs)))
- (setq l (cdr l)))
- seqs))
-
-
-
-
-;;; User prompting commands.
-
-
-(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)))
- (setq input (cons (car next) input))
- (setq start (cdr next))))
- (nreverse input)))
-
-
-
-;;; 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-compat-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 "\e#" 'mh-delete-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 "\ed" 'mh-redistribute)
-(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 "\en" 'mh-store-msg)
-(define-key mh-folder-mode-map "\ep" 'mh-pack-folder)
-(define-key mh-folder-mode-map "\eq" 'mh-list-sequences)
-(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 "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 "f" 'mh-forward)
-(define-key mh-folder-mode-map "m" 'mh-send)
-(define-key mh-folder-mode-map "s" 'mh-send)
-(define-key mh-folder-mode-map "r" 'mh-reply)
-(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 "g" 'mh-goto-msg)
-(define-key mh-folder-mode-map "\e<" 'mh-first-msg)
-(define-key mh-folder-mode-map "\e>" 'mh-last-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 "\r" 'mh-show)
-(define-key mh-folder-mode-map "." 'mh-show)
-(define-key mh-folder-mode-map "," 'mh-header-display)
-(define-key mh-folder-mode-map "u" 'mh-undo)
-(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)
-(define-key mh-folder-mode-map "^" 'mh-refile-msg)
-(define-key mh-folder-mode-map "\C-o" 'mh-write-msg-to-file)
-(define-key mh-folder-mode-map ">" 'mh-write-msg-to-file)
-(define-key mh-folder-mode-map "!" 'mh-refile-or-write-again)
-
-;; "C-c /" prefix is used in mh-folder-mode by pgp.el and mailcrypt
-
-
-
-;;;autoload the other mh-e parts
-
-;;; mh-comp
-
-(autoload 'mh-smail "mh-comp"
- "Compose and send mail with the MH mail system.
-This function is an entry point to mh-e, the Emacs front end
-to the MH mail system.
-See documentation of `\\[mh-send]' for more details on composing mail." t)
-
-(autoload 'mh-smail-other-window "mh-comp"
- "Compose and send mail in other window with the MH mail system.
-This function is an entry point to mh-e, the Emacs front end
-to the MH mail system.
-See documentation of `\\[mh-send]' for more details on composing mail." t)
-
-(autoload 'mh-edit-again "mh-comp"
- "Clean-up a draft or a message previously sent and make it resendable.
-Default is the current message.
-The variable mh-new-draft-cleaned-headers specifies the headers to remove.
-See also documentation for `\\[mh-send]' function." t)
-
-(autoload 'mh-extract-rejected-mail "mh-comp"
- "Extract a letter returned by the mail system and make it resendable.
-Default is the current message. The variable mh-new-draft-cleaned-headers
-gives the headers to clean out of the original message.
-See also documentation for `\\[mh-send]' function." t)
-
-(autoload 'mh-forward "mh-comp"
- "Forward a message or message sequence. Defaults to displayed message.
-If optional prefix argument provided, then prompt for the message sequence.
-See also documentation for `\\[mh-send]' function." t)
-
-(autoload 'mh-redistribute "mh-comp"
- "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." t)
-
-(autoload 'mh-reply "mh-comp"
- "Reply to a MESSAGE (default: displayed message).
-If optional prefix argument INCLUDEP provided, then include the message
-in the reply using filter mhl.reply in your MH directory.
-Prompts for type of addresses to reply to:
- from sender only,
- to sender and primary recipients,
- cc/all sender and all recipients.
-If the file named by `mh-repl-formfile' exists, it is used as a skeleton
-for the reply. See also documentation for `\\[mh-send]' function." t)
-
-(autoload 'mh-send "mh-comp"
- "Compose and send a letter.
-The file named by `mh-comp-formfile' will be used as the form.
-Do not call this function from outside mh-e; use \\[mh-smail] instead.
-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." t)
-
-(autoload 'mh-send-other-window "mh-comp"
- "Compose and send a letter in another window.
-Do not call this function from outside mh-e;
-use \\[mh-smail-other-window] instead.
-See also documentation for `\\[mh-send]' function." t)
-
-(autoload 'mh-letter-mode "mh-comp"
- "Mode for composing letters in mh-e.
-For more details, type \\[describe-mode] while in MH-Letter mode." t)
-
-
-;;; mh-funcs
-
-(autoload 'mh-burst-digest "mh-funcs"
- "Burst apart the current message, which should be a digest.
-The message is replaced by its table of contents and the messages from the
-digest are inserted into the folder after that message." t)
-
-(autoload 'mh-copy-msg "mh-funcs"
- "Copy to another FOLDER the specified MESSAGE(s) without deleting them.
-Default is the displayed message. If optional prefix argument is
-provided, then prompt for the message sequence." t)
-
-(autoload 'mh-kill-folder "mh-funcs"
- "Remove the current folder." t)
-
-(autoload 'mh-list-folders "mh-funcs"
- "List mail folders." t)
-
-(autoload 'mh-pack-folder "mh-funcs"
- "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." t)
-
-(autoload 'mh-pipe-msg "mh-funcs"
- "Pipe the current message through the given shell COMMAND.
-If INCLUDE-HEADERS (prefix argument) is provided, send the entire message.
-Otherwise just send the message's body without the headers." t)
-
-(autoload 'mh-page-digest "mh-funcs"
- "Advance displayed message to next digested message." t)
-
-(autoload 'mh-page-digest-backwards "mh-funcs"
- "Back up displayed message to previous digested message." t)
-
-(autoload 'mh-print-msg "mh-funcs"
- "Print MESSAGE(s) (default: displayed message) on printer.
-If optional prefix argument provided, then prompt for the message sequence.
-The variable mh-lpr-command-format is used to generate the print command.
-The messages are formatted by mhl. See the variable mhl-formfile." t)
-
-(autoload 'mh-sort-folder "mh-funcs"
- "Sort the messages in the current folder by date.
-Calls the MH program sortm to do the work.
-The arguments in the list mh-sortm-args are passed to sortm
-if this function is passed an argument." t)
-
-(autoload 'mh-undo-folder "mh-funcs"
- "Undo all commands in current folder." t)
-
-(autoload 'mh-store-msg "mh-funcs"
- "Store the file(s) contained in the current message into DIRECTORY.
-The message can contain a shar file or uuencoded file.
-Default directory is the last directory used, or initially the value of
-mh-store-default-directory or the current directory." t)
-
-(autoload 'mh-store-buffer "mh-funcs"
- "Store the file(s) contained in the current buffer into DIRECTORY.
-The buffer can contain a shar file or uuencoded file.
-Default directory is the last directory used, or initially the value of
-`mh-store-default-directory' or the current directory." t)
-
-
-;;; mh-pick
-
-(autoload 'mh-search-folder "mh-pick"
- "Search FOLDER for messages matching a pattern.
-Add the messages found to the sequence named `search'." t)
-
-;;; mh-seq
-
-(autoload 'mh-delete-seq "mh-seq"
- "Delete the SEQUENCE." t)
-(autoload 'mh-list-sequences "mh-seq"
- "List the sequences defined in FOLDER." t)
-(autoload 'mh-msg-is-in-seq "mh-seq"
- "Display the sequences that contain MESSAGE (default: displayed message)." t)
-(autoload 'mh-narrow-to-seq "mh-seq"
- "Restrict display of this folder to just messages in SEQUENCE
-Use \\[mh-widen] to undo this command." t)
-(autoload 'mh-put-msg-in-seq "mh-seq"
- "Add MESSAGE(s) (default: displayed message) to SEQUENCE.
-If optional prefix argument provided, then prompt for the message sequence." t)
-(autoload 'mh-widen "mh-seq"
- "Remove restrictions from current folder, thereby showing all messages." t)
-(autoload 'mh-rename-seq "mh-seq"
- "Rename SEQUENCE to have NEW-NAME." t)
-
-;;; mh-e.el ends here
diff --git a/lisp/mail/mh-funcs.el b/lisp/mail/mh-funcs.el
deleted file mode 100644
index cc1ce6aec1b..00000000000
--- a/lisp/mail/mh-funcs.el
+++ /dev/null
@@ -1,354 +0,0 @@
-;;; mh-funcs --- mh-e functions not everyone will use right away
-;; Time-stamp: <95/08/19 16:44:06 gildea>
-
-;; Copyright (C) 1993, 1995 Free Software Foundation, Inc.
-
-;; This file is part of mh-e, part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Internal support for mh-e package.
-;; Putting these functions in a separate file lets mh-e start up faster,
-;; since less Lisp code needs to be loaded all at once.
-
-;;; Change Log:
-
-;; $Id: mh-funcs.el,v 1.4 1995/11/03 02:29:34 kwzh Exp erik $
-
-;;; Code:
-
-(provide 'mh-funcs)
-(require 'mh-e)
-
-;;; customization
-
-(defvar mh-sortm-args nil
- "Extra arguments to have \\[mh-sort-folder] pass to the \"sortm\" command.
-The arguments are passed to sortm if \\[mh-sort-folder] is given a
-prefix argument. Normally default arguments to sortm are specified in the
-MH profile.
-For example, '(\"-nolimit\" \"-textfield\" \"subject\") is a useful setting.")
-
-(defvar mh-note-copied "C"
- "String whose first character is used to notate copied messages.")
-
-(defvar mh-note-printed "P"
- "String whose first character is used to notate printed messages.")
-
-;;; functions
-
-(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 messages 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")
- (with-mh-folder-updating (t)
- (beginning-of-line)
- (delete-region (point) (point-max)))
- (mh-regenerate-headers (format "%d-last" digest) t)
- (mh-goto-cur-msg)
- (message "Bursting digest...done")))
-
-
-(defun mh-copy-msg (msg-or-seq folder)
- "Copy the 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 (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 folder)
- (if (numberp msg-or-seq)
- (mh-notate msg-or-seq mh-note-copied mh-cmd-note)
- (mh-notate-seq msg-or-seq mh-note-copied mh-cmd-note)))
-
-(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))
- (if (null mh-folder-list)
- (mh-set-folder-list))
- (mh-set-folder-modified-p t) ; lock folder to kill it
- (mh-exec-cmd-daemon "rmf" folder)
- (setq mh-folder-list
- (delq (assoc folder mh-folder-list) mh-folder-list))
- (run-hooks 'mh-folder-list-change-hook)
- (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-list-folders ()
- "List mail folders."
- (interactive)
- (with-output-to-temp-buffer mh-temp-buffer
- (save-excursion
- (switch-to-buffer mh-temp-buffer)
- (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-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-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 t "folder" mh-current-folder "-pack"
- "-norecurse" "-fast"))
- (mh-regenerate-headers range))
-
-
-(defun mh-pipe-msg (command include-headers)
- "Pipe the current message through the given shell COMMAND.
-If INCLUDE-HEADERS (prefix argument) is provided, send the entire message.
-Otherwise just send the message's body without the headers."
- (interactive
- (list (read-string "Shell command on message: ") current-prefix-arg))
- (let ((msg-file-to-pipe (mh-msg-filename (mh-get-msg-num t)))
- (message-directory default-directory))
- (save-excursion
- (set-buffer (get-buffer-create mh-temp-buffer))
- (erase-buffer)
- (insert-file-contents msg-file-to-pipe)
- (goto-char (point-min))
- (if (not include-headers) (search-forward "\n\n"))
- (let ((default-directory message-directory))
- (shell-command-on-region (point) (point-max) command nil)))))
-
-
-(defun mh-page-digest ()
- "Advance displayed message to next digested message."
- (interactive)
- (mh-in-show-buffer (mh-show-buffer)
- ;; 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:
- (or (and (search-forward "\n\n" nil t)
- (re-search-forward "^From:" nil t))
- (error "No more messages in digest")))
- ;; 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)))
-
-
-(defun mh-page-digest-backwards ()
- "Back up displayed message to previous digested message."
- (interactive)
- (mh-in-show-buffer (mh-show-buffer)
- ;; Go to top of screen (in case user moved point).
- (move-to-window-line 0)
- (let ((case-fold-search nil))
- (beginning-of-line)
- (or (and (search-backward "\n\n" nil t)
- (re-search-backward "^From:" nil t))
- (error "No previous message in digest")))
- ;; Go back to previous blank line, then forward to the first non-blank.
- (if (search-backward "\n\n" nil t)
- (forward-line 2))
- (mh-recenter 0)))
-
-
-(defun mh-print-msg (msg-or-seq)
- "Print MESSAGE(s) (default: displayed message) on printer.
-If optional prefix argument provided, then prompt for the message sequence.
-The variable mh-lpr-command-format is used to generate the print command.
-The messages are formatted by mhl. See the variable mhl-formfile."
- (interactive (list (if current-prefix-arg
- (reverse (mh-seq-to-msgs
- (mh-read-seq-default "Print" t)))
- (mh-get-msg-num t))))
- (if (numberp msg-or-seq)
- (message "Printing message...")
- (message "Printing sequence..."))
- (let ((print-command
- (if (numberp 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 (numberp msg-or-seq)
- (format "%s/%d" mh-current-folder
- msg-or-seq)
- (format "Sequence from %s" mh-current-folder))))
- (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 (numberp msg-or-seq)
- (format "%s/%d" mh-current-folder
- msg-or-seq)
- (format "Sequence from %s"
- mh-current-folder)))))))
- (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 (numberp msg-or-seq)
- (mh-notate msg-or-seq mh-note-printed mh-cmd-note)
- (mh-notate-seq msg-or-seq mh-note-printed mh-cmd-note))
- (mh-add-msgs-to-seq msg-or-seq 'printed t)
- (if (numberp msg-or-seq)
- (message "Printing message...done")
- (message "Printing sequence...done"))))
-
-
-(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-sort-folder (&optional extra-args)
- "Sort the messages in the current folder by date.
-Calls the MH program sortm to do the work.
-The arguments in the list mh-sortm-args are passed to sortm
-if this function is passed an argument."
- (interactive "P")
- (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 (if extra-args mh-sortm-args))
- (message "Sorting folder...done")
- (mh-scan-folder mh-current-folder "all"))
-
-
-(defun mh-undo-folder (&rest ignore)
- "Undo all pending deletes and refiles 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-store-msg (directory)
- "Store the file(s) contained in the current message into DIRECTORY.
-The message can contain a shar file or uuencoded file.
-Default directory is the last directory used, or initially the value of
-mh-store-default-directory or the current directory."
- (interactive (list (let ((udir (or mh-store-default-directory default-directory)))
- (read-file-name "Store message in directory: "
- udir udir nil))))
- (let ((msg-file-to-store (mh-msg-filename (mh-get-msg-num t))))
- (save-excursion
- (set-buffer (get-buffer-create mh-temp-buffer))
- (erase-buffer)
- (insert-file-contents msg-file-to-store)
- (mh-store-buffer directory))))
-
-(defun mh-store-buffer (directory)
- "Store the file(s) contained in the current buffer into DIRECTORY.
-The buffer can contain a shar file or uuencoded file.
-Default directory is the last directory used, or initially the value of
-`mh-store-default-directory' or the current directory."
- (interactive (list (let ((udir (or mh-store-default-directory default-directory)))
- (read-file-name "Store buffer in directory: "
- udir udir nil))))
- (let ((store-directory (expand-file-name directory))
- (sh-start (save-excursion
- (goto-char (point-min))
- (if (re-search-forward
- "^#![ \t]*/bin/sh\\|^#\\|^: " nil t)
- (progn
- ;; The "cut here" pattern was removed from above
- ;; because it seemed to hurt more than help.
- ;; But keep this to make it easier to put it back.
- (if (looking-at "^[^a-z0-9\"]*cut here\\b")
- (forward-line 1))
- (beginning-of-line)
- (if (looking-at "^[#:]....+\n\\( ?\n\\)?end$")
- nil ;most likely end of a uuencode
- (point))))))
- (log-buffer (get-buffer-create "*Store Output*"))
- (command "sh")
- (uudecode-filename "(unknown filename)"))
- (if (not sh-start)
- (save-excursion
- (goto-char (point-min))
- (if (re-search-forward "^begin [0-7]+ " nil t)
- (setq uudecode-filename
- (buffer-substring (point)
- (progn (end-of-line) (point)))))))
- (save-excursion
- (set-buffer log-buffer)
- (erase-buffer)
- (if (not (file-directory-p store-directory))
- (progn
- (insert "mkdir " directory "\n")
- (call-process "mkdir" nil log-buffer t store-directory)))
- (insert "cd " directory "\n")
- (setq mh-store-default-directory directory)
- (if (not sh-start)
- (progn
- (setq command "uudecode")
- (insert uudecode-filename " being uudecoded...\n"))))
- (set-window-start (display-buffer log-buffer) 0) ;watch progress
- (let (value)
- (let ((default-directory (file-name-as-directory store-directory)))
- (setq value (call-process-region sh-start (point-max) command
- nil log-buffer t)))
- (set-buffer log-buffer)
- (mh-handle-process-error command value))
- (insert "\n(mh-store finished)\n")))
-
diff --git a/lisp/mail/mh-mime.el b/lisp/mail/mh-mime.el
deleted file mode 100644
index dcb12b5588b..00000000000
--- a/lisp/mail/mh-mime.el
+++ /dev/null
@@ -1,236 +0,0 @@
-;;; mh-mime --- mh-e support for composing MIME messages
-;; Time-stamp: <95/08/19 16:45:17 gildea>
-
-;; Copyright (C) 1993, 1995 Free Software Foundation, Inc.
-
-;; This file is part of mh-e, part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Internal support for mh-e package.
-;; Support for generating an mhn composition file.
-;; MIME is supported only by MH 6.8 or later.
-
-;;; Change Log:
-
-;; $Id: mh-mime.el,v 1.5 1995/11/03 02:29:49 kwzh Exp erik $
-
-;;; Code:
-
-(provide 'mh-mime)
-(require 'mh-comp)
-
-
-;; To do:
-;; paragraph code should not fill # lines if MIME enabled.
-;; implement mh-auto-edit-mhn (if non-nil, \\[mh-send-letter]
-;; invokes mh-edit-mhn automatically before sending.)
-;; actually, instead of mh-auto-edit-mhn,
-;; should read automhnproc from profile
-;; MIME option to mh-forward
-;; command to move to content-description insertion point
-
-(defvar mh-mhn-args nil
- "Extra arguments to have \\[mh-edit-mhn] pass to the \"mhn\" command.
-The arguments are passed to mhn if \\[mh-edit-mhn] is given a
-prefix argument. Normally default arguments to mhn are specified in the
-MH profile.")
-
-(defvar mh-edit-mhn-hook nil
- "Invoked on the formatted letter by \\<mh-letter-mode-map>\\[mh-edit-mhn].")
-
-;;;###autoload
-(defvar mh-mime-content-types
- '(("text/plain") ("text/richtext")
- ("multipart/mixed") ("multipart/alternative") ("multipart/digest")
- ("multipart/parallel")
- ("message/rfc822") ("message/partial") ("message/external-body")
- ("application/octet-stream") ("application/postscript")
- ("image/jpeg") ("image/gif")
- ("audio/basic")
- ("video/mpeg"))
- "Legal MIME content types. See documentation for \\[mh-edit-mhn].")
-
-(defun mh-mhn-compose-insertion (pathname type description)
- "Add a directive to insert a MIME message part from a file.
-This is the typical way to insert non-text parts in a message.
-Arguments are PATHNAME, which tells where to find the file, TYPE, the
-MIME content type, and DESCRIPTION, a line of text for the
-Content-description header. See also \\[mh-edit-mhn]."
- (interactive (list
- (read-file-name "Insert contents of: ")
- (completing-read "Content-type: "
- mh-mime-content-types nil nil nil)
- (read-string "Content-description: ")))
- (mh-mhn-compose-type pathname type description))
-
-(defun mh-mhn-compose-type (pathname type
- &optional description attributes comment)
- (beginning-of-line)
- (insert "#" type)
- (and attributes
- (insert "; " attributes))
- (and comment
- (insert " (" comment ")"))
- (insert " [")
- (and description
- (insert description))
- (insert "] " (expand-file-name pathname))
- (insert "\n"))
-
-
-(defun mh-mhn-compose-anon-ftp (host pathname type description)
- "Add a directive for a MIME anonymous ftp external body part.
-This directive tells MH to include a reference to a
-message/external-body part retrievable by anonymous FTP. Arguments
-are HOST and PATHNAME, which tell where to find the file, TYPE, the
-MIME content type, and DESCRIPTION, a line of text for the
-Content-description header. See also \\[mh-edit-mhn]."
- (interactive (list
- (read-string "Remote host: ")
- (read-string "Remote pathname: ")
- (completing-read "External Content-type: "
- mh-mime-content-types nil nil nil)
- (read-string "External Content-description: ")))
- (mh-mhn-compose-external-type "anon-ftp" host pathname
- type description))
-
-(defun mh-mhn-compose-external-compressed-tar (host pathname description)
- "Add a directive to include a MIME reference to a compressed tar file.
-The file should be available via anonymous ftp. This directive
-tells MH to include a reference to a message/external-body part.
-Arguments are HOST and PATHNAME, which tell where to find the file, and
-DESCRIPTION, a line of text for the Content-description header.
-See also \\[mh-edit-mhn]."
- (interactive (list
- (read-string "Remote host: ")
- (read-string "Remote pathname: ")
- (read-string "Tar file Content-description: ")))
- (mh-mhn-compose-external-type "anon-ftp" host pathname
- "application/octet-stream"
- description
- "type=tar; conversions=x-compress"
- "mode=image"))
-
-
-(defun mh-mhn-compose-external-type (access-type host pathname type
- &optional description
- attributes extra-params comment)
- (beginning-of-line)
- (insert "#@" type)
- (and attributes
- (insert "; " attributes))
- (and comment
- (insert " (" comment ") "))
- (insert " [")
- (and description
- (insert description))
- (insert "] ")
- (insert "access-type=" access-type "; ")
- (insert "site=" host)
- (insert "; name=" (file-name-nondirectory pathname))
- (insert "; directory=\"" (file-name-directory pathname) "\"")
- (and extra-params
- (insert "; " extra-params))
- (insert "\n"))
-
-(defun mh-mhn-compose-forw (&optional description folder messages)
- "Add a forw directive to this message, to forward a message with MIME.
-This directive tells MH to include the named messages in this one.
-Arguments are DESCRIPTION, a line of text for the Content-description header,
-and FOLDER and MESSAGES, which name the message(s) to be forwarded.
-See also \\[mh-edit-mhn]."
- (interactive (list
- (read-string "Forw Content-description: ")
- (mh-prompt-for-folder "Message from" mh-sent-from-folder nil)
- (read-string (format "Messages%s: "
- (if mh-sent-from-msg
- (format " [%d]" mh-sent-from-msg)
- "")))))
- (beginning-of-line)
- (insert "#forw [")
- (and description
- (not (string= description ""))
- (insert description))
- (insert "]")
- (and folder
- (not (string= folder ""))
- (insert " " folder))
- (if (and messages
- (not (string= messages "")))
- (let ((start (point)))
- (insert " " messages)
- (subst-char-in-region start (point) ?, ? ))
- (if mh-sent-from-msg
- (insert " " (int-to-string mh-sent-from-msg))))
- (insert "\n"))
-
-(defun mh-edit-mhn (&optional extra-args)
- "Format the current draft for MIME, expanding any mhn directives.
-Process the current draft with the mhn program, which,
-using directives already inserted in the draft, fills in
-all the MIME components and header fields.
-This step should be done last just before sending the message.
-The mhn program is part of MH version 6.8 or later.
-The `\\[mh-revert-mhn-edit]' command undoes this command.
-The arguments in the list `mh-mhn-args' are passed to mhn
-if this function is passed an argument.
-
-For assistance with creating mhn directives to insert
-various types of components in a message, see
-\\[mh-mhn-compose-insertion] (generic insertion from a file),
-\\[mh-mhn-compose-anon-ftp] (external reference to file via anonymous ftp),
-\\[mh-mhn-compose-external-compressed-tar] \
-\(reference to compressed tar file via anonymous ftp), and
-\\[mh-mhn-compose-forw] (forward message)."
- (interactive "*P")
- (save-buffer)
- (message "mhn editing...")
- (mh-exec-cmd-error (format "mhdraft=%s" buffer-file-name)
- "mhn" (if extra-args mh-mhn-args) buffer-file-name)
- (revert-buffer t t)
- (message "mhn editing...done")
- (run-hooks 'mh-edit-mhn-hook))
-
-
-(defun mh-revert-mhn-edit (noconfirm)
- "Undoes the effect of \\[mh-edit-mhn] by reverting to the backup file.
-Optional non-nil argument means don't ask for confirmation."
- (interactive "*P")
- (if (null buffer-file-name)
- (error "Buffer does not seem to be associated with any file"))
- (let ((backup-strings '("," "#"))
- backup-file)
- (while (and backup-strings
- (not (file-exists-p
- (setq backup-file
- (concat (file-name-directory buffer-file-name)
- (car backup-strings)
- (file-name-nondirectory buffer-file-name)
- ".orig")))))
- (setq backup-strings (cdr backup-strings)))
- (or backup-strings
- (error "mhn backup file for %s no longer exists!" buffer-file-name))
- (or noconfirm
- (yes-or-no-p (format "Revert buffer from file %s? "
- backup-file))
- (error "mhn edit revert not confirmed."))
- (let ((buffer-read-only nil))
- (erase-buffer)
- (insert-file-contents backup-file))
- (after-find-file nil)))
diff --git a/lisp/mail/mh-pick.el b/lisp/mail/mh-pick.el
deleted file mode 100644
index a297d5e6f5c..00000000000
--- a/lisp/mail/mh-pick.el
+++ /dev/null
@@ -1,195 +0,0 @@
-;;; mh-pick --- make a search pattern and search for a message in mh-e
-;; Time-stamp: <95/08/19 16:45:16 gildea>
-
-;; Copyright (C) 1993, 1995 Free Software Foundation, Inc.
-
-;; This file is part of mh-e, part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Internal support for mh-e package.
-
-;;; Change Log:
-
-;; $Id: mh-pick.el,v 1.4 1995/11/03 02:30:09 kwzh Exp erik $
-
-;;; Code:
-
-(provide 'mh-pick)
-(require 'mh-e)
-
-(defvar mh-pick-mode-hook nil
- "Invoked in `mh-pick-mode' on a new pattern.")
-
-;;; Internal variables:
-
-(defvar mh-pick-mode-map (make-sparse-keymap)
- "Keymap for searching folder.")
-
-(defvar mh-searching-folder nil) ;Folder this pick is searching.
-
-(defun mh-search-folder (folder)
- "Search FOLDER for messages matching a pattern.
-Add the messages found to the sequence named `search'."
- (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-make-pick-template ()
- ;; Initialize the current buffer with a template for a pick pattern.
- (erase-buffer)
- (insert "From: \n"
- "To: \n"
- "Cc: \n"
- "Date: \n"
- "Subject: \n"
- "---------\n")
- (mh-pick-mode)
- (goto-char (point-min))
- (end-of-line))
-
-(put 'mh-pick-mode 'mode-class 'special)
-
-(defun mh-pick-mode ()
- "Mode for creating search templates in mh-e.\\<mh-pick-mode-map>
-After each field name, enter the pattern to search for. If a field's
-value does not matter for the search, leave it empty. To search the
-entire message, supply the pattern in the \"body\" of the template.
-Each non-empty field must be matched for a message to be selected.
-To effect a logical \"or\", use \\[mh-search-folder] multiple times.
-When you have finished, type \\[mh-do-pick-search] to do the search.
-\\{mh-pick-mode-map}
-Turning on mh-pick-mode calls the value of the variable mh-pick-mode-hook
-if that value is non-nil."
- (interactive)
- (kill-all-local-variables)
- (make-local-variable 'mh-searching-folder)
- (use-local-map mh-pick-mode-map)
- (setq major-mode 'mh-pick-mode)
- (mh-set-mode-name "MH-Pick")
- (run-hooks 'mh-pick-mode-hook))
-
-
-(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.
-Add the messages found to the sequence named `search'."
- (interactive)
- (let ((pattern-buffer (buffer-name))
- (searching-buffer mh-searching-folder)
- range
- msgs
- (finding-messages t)
- (pattern nil)
- (new-buffer nil))
- (save-excursion
- (cond ((get-buffer searching-buffer)
- (set-buffer searching-buffer)
- (setq range (list (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 (and range
- (setq pattern (mh-next-pick-field pattern-buffer)))
- (setq msgs (mh-seq-from-command searching-buffer
- 'search
- (mh-list-to-string
- (list "pick" pattern searching-buffer
- "-list"
- (mh-coalesce-msg-list range)))))
- (setq range msgs)) ;restrict the pick range for next pass
- (message "Searching...done")
- (if new-buffer
- (mh-scan-folder searching-buffer msgs)
- (switch-to-buffer searching-buffer))
- (mh-add-msgs-to-seq msgs 'search)
- (delete-other-windows)))
-
-
-(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
- (if (eq 0 (apply 'mh-exec-cmd-quiet nil seq-command))
- ;; "pick" outputs one number per line
- (while (setq msg (car (mh-read-msg-list)))
- (setq msgs (cons msg msgs))
- (forward-line 1))))
- (set-buffer folder)
- (setq msgs (nreverse msgs)) ;put in ascending order
- msgs)))
-
-
-(defun mh-next-pick-field (buffer)
- ;; Return the next piece of a pick argument that can be extracted from the
- ;; BUFFER.
- ;; Return a list like ("--fieldname" "pattern") or ("-search" "bodypat")
- ;; or NIL if no pieces remain.
- (set-buffer buffer)
- (let ((case-fold-search t))
- (cond ((eobp)
- nil)
- ((re-search-forward "^\\([a-z][^: \t\n]*\\):[ \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))))
-
-;;; 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-d" '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-r" '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-fd" '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-fr" '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)
diff --git a/lisp/mail/mh-seq.el b/lisp/mail/mh-seq.el
deleted file mode 100644
index 59db6ee8f19..00000000000
--- a/lisp/mail/mh-seq.el
+++ /dev/null
@@ -1,237 +0,0 @@
-;;; mh-seq --- mh-e sequences support
-;; Time-stamp: <95/08/19 16:45:15 gildea>
-
-;; Copyright (C) 1993, 1995 Free Software Foundation, Inc.
-
-;; This file is part of mh-e, part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Internal support for mh-e package.
-
-;;; Change Log:
-
-;; $Id: mh-seq.el,v 1.5 1996/01/14 07:34:30 erik Exp kwzh $
-
-;;; Code:
-
-(provide 'mh-seq)
-(require 'mh-e)
-
-;;; Internal variables:
-
-(defvar mh-last-seq-used nil) ;Name of seq to which a msg was last added.
-
-(defvar mh-non-seq-mode-line-annotation nil) ;Saved value of mh-mode-line-annotation when narrowed to a seq.
-
-
-(defun mh-delete-seq (sequence)
- "Delete the SEQUENCE."
- (interactive (list (mh-read-seq-default "Delete" t)))
- (mh-map-to-seq-msgs 'mh-notate-if-in-one-seq sequence ? (1+ mh-cmd-note)
- sequence)
- (mh-undefine-sequence sequence '("all"))
- (mh-delete-seq-locally sequence))
-
-
-(defun mh-list-sequences (folder)
- "List the sequences defined in FOLDER."
- (interactive (list (mh-prompt-for-folder "List sequences in"
- mh-current-folder t)))
- (let ((temp-buffer mh-temp-buffer)
- (seq-list mh-seq-list))
- (with-output-to-temp-buffer temp-buffer
- (save-excursion
- (set-buffer temp-buffer)
- (erase-buffer)
- (message "Listing sequences ...")
- (insert "Sequences in folder " folder ":\n")
- (while seq-list
- (let ((name (mh-seq-name (car seq-list)))
- (sorted-seq-msgs
- (sort (copy-sequence (mh-seq-msgs (car seq-list))) '<))
- (last-col (- (window-width) 4))
- name-spec)
- (insert (setq name-spec (format "%20s:" name)))
- (while sorted-seq-msgs
- (if (> (current-column) last-col)
- (progn
- (insert "\n")
- (move-to-column (length name-spec))))
- (insert (format " %s" (car sorted-seq-msgs)))
- (setq sorted-seq-msgs (cdr sorted-seq-msgs)))
- (insert "\n"))
- (setq seq-list (cdr seq-list)))
- (goto-char (point-min))
- (message "Listing sequences...done")))))
-
-
-(defun mh-msg-is-in-seq (message)
- "Display the sequences that contain MESSAGE (default: current message)."
- (interactive (list (mh-get-msg-num t)))
- (message "Message %d is in sequences: %s"
- message
- (mapconcat 'concat
- (mh-list-to-string (mh-seq-containing-msg message t))
- " ")))
-
-
-(defun mh-narrow-to-seq (sequence)
- "Restrict display of this folder to just messages in SEQUENCE.
-Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
- (interactive (list (mh-read-seq "Narrow to" t)))
- (with-mh-folder-updating (t)
- (cond ((mh-seq-to-msgs sequence)
- (mh-widen)
- (let ((eob (point-max)))
- (mh-copy-seq-to-point sequence eob)
- (narrow-to-region eob (point-max))
- (make-variable-buffer-local 'mh-non-seq-mode-line-annotation)
- (setq mh-non-seq-mode-line-annotation mh-mode-line-annotation)
- (setq mh-mode-line-annotation (symbol-name sequence))
- (mh-make-folder-mode-line)
- (mh-recenter nil)
- (setq mh-narrowed-to-seq sequence)))
- (t
- (error "No messages in sequence `%s'" (symbol-name sequence))))))
-
-
-(defun mh-put-msg-in-seq (msg-or-seq sequence)
- "Add MESSAGE(s) (default: displayed message) to SEQUENCE.
-If optional prefix argument provided, then prompt for the message sequence."
- (interactive (list (if current-prefix-arg
- (mh-read-seq-default "Add messages from" t)
- (mh-get-msg-num t))
- (mh-read-seq-default "Add to" nil)))
- (if (not (mh-internal-seq sequence))
- (setq mh-last-seq-used sequence))
- (mh-add-msgs-to-seq (if (numberp msg-or-seq)
- msg-or-seq
- (mh-seq-to-msgs msg-or-seq))
- sequence))
-
-
-(defun mh-widen ()
- "Remove restrictions from current folder, thereby showing all messages."
- (interactive)
- (if mh-narrowed-to-seq
- (with-mh-folder-updating (t)
- (delete-region (point-min) (point-max))
- (widen)
- (setq mh-mode-line-annotation mh-non-seq-mode-line-annotation)
- (mh-make-folder-mode-line)))
- (setq mh-narrowed-to-seq nil))
-
-
-
-;;; Commands to manipulate sequences. Sequences are stored in an alist
-;;; of the form:
-;;; ((seq-name msgs ...) (seq-name msgs ...) ...)
-
-
-(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-last-seq-used
- (car (mh-seq-containing-msg (mh-get-msg-num nil) nil)))))
-
-
-(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 "%")
- (car (mh-seq-containing-msg (mh-get-msg-num t) nil)))
- ((equal input "") default)
- (t (intern input))))
- (msgs (mh-seq-to-msgs seq)))
- (if (and (null msgs) not-empty)
- (error "No messages in sequence `%s'" seq))
- seq))
-
-
-(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-rename-seq (sequence new-name)
- "Rename SEQUENCE to have NEW-NAME."
- (interactive (list (mh-read-seq "Old" t)
- (intern (read-string "New sequence name: "))))
- (let ((old-seq (mh-find-seq sequence)))
- (or old-seq
- (error "Sequence %s does not exist" sequence))
- ;; create new sequence first, since it might raise an error.
- (mh-define-sequence new-name (mh-seq-msgs old-seq))
- (mh-undefine-sequence sequence (mh-seq-msgs old-seq))
- (rplaca old-seq new-name)))
-
-
-(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-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-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 "-add"
- "-sequence" (symbol-name seq)
- (mh-coalesce-msg-list 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)
- (save-excursion
- (let ((beginning-of-line (point))
- end)
- (forward-line 1)
- (setq end (point))
- (goto-char location)
- (insert-buffer-substring (current-buffer) beginning-of-line end))))
-
diff --git a/lisp/mail/mh-utils.el b/lisp/mail/mh-utils.el
deleted file mode 100644
index d2505918c86..00000000000
--- a/lisp/mail/mh-utils.el
+++ /dev/null
@@ -1,953 +0,0 @@
-;;; mh-utils.el --- mh-e code needed for both sending and reading
-;; Time-stamp: <95/10/22 17:58:16 gildea>
-
-;; Copyright (C) 1993, 1995 Free Software Foundation, Inc.
-
-;; This file is part of mh-e, part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Internal support for mh-e package.
-
-;;; Change Log:
-
-;; $Id: mh-utils.el,v 1.9 1996/01/29 23:17:16 kwzh Exp rms $
-
-;;; Code:
-
-;;; Set for local environment:
-;;; mh-progs and mh-lib used to be set in paths.el, which tried to
-;;; figure out at build time which of several possible directories MH
-;;; was installed into. But if you installed MH after building Emacs,
-;;; this would almost certainly be wrong, so now we do it at run time.
-
-(defvar mh-progs nil
- "Directory containing MH commands, such as inc, repl, and rmm.")
-
-(defvar mh-lib nil
- "Directory containing the MH library.
-This directory contains, among other things,
-the mhl program and the components file.")
-
-;;;###autoload
-(put 'mh-progs 'risky-local-variable t)
-;;;###autoload
-(put 'mh-lib 'risky-local-variable t)
-
-;;; User preferences:
-
-(defvar mh-auto-folder-collect t
- "*Whether to start collecting MH folder names immediately in the background.
-Non-nil means start a background process collecting the names of all
-folders as soon as mh-e is loaded.")
-
-(defvar mh-recursive-folders nil
- "*If non-nil, then commands which operate on folders do so recursively.")
-
-(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 mh-invisible-headers
- "^Received: \\|^Message-Id: \\|^Remailed-\\|^Via: \\|^Mail-from: \\|^Return-Path: \\|^Delivery-Date: \\|^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-bury-show-buffer t
- "*Non-nil means that the displayed show buffer for a folder is buried.")
-
-(defvar mh-summary-height 4
- "*Number of lines in MH-Folder window (including the mode line).")
-
-(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 mhl-formfile nil
- "*Name of format file to be used by mhl to show and print messages.
-A value of T means use the default format file.
-Nil means don't use mhl to format messages when showing; mhl is still used,
-with the default format file, to format messages when printing them.
-The format used should specify a non-zero value for overflowoffset so
-the message continues to conform to RFC 822 and mh-e can parse the headers.")
-(put 'mhl-formfile 'info-file "mh-e")
-
-(defvar mh-default-folder-for-message-function nil
- "Function to select a default folder for refiling or Fcc.
-If set to a function, that function is called with no arguments by
-`\\[mh-refile-msg]' and `\\[mh-to-fcc]' to get a default when
-prompting the user for a folder. The function is called from within a
-save-excursion, with point at the start of the message. It should
-return the folder to offer as the refile or Fcc folder, as a string
-with a leading `+' sign. It can also return an empty string to use no
-default, or NIL to calculate the default the usual way.
-NOTE: This variable is not an ordinary hook;
-It may not be a list of functions.")
-
-(defvar mh-find-path-hook nil
- "Invoked by mh-find-path while reading the user's MH profile.")
-
-(defvar mh-folder-list-change-hook nil
- "Invoked whenever the cached folder list `mh-folder-list' is changed.")
-
-(defvar mh-show-buffer-mode-line-buffer-id "{show-%s} %d"
- "Format string to produce `mode-line-buffer-identification' for show buffers.
-First argument is folder name. Second is message number.")
-
-(defvar mh-cmd-note 4
- "Offset to insert notation.")
-
-(defvar mh-note-seq "%"
- "String whose first character is used to notate messages in a sequence.")
-
-;;; Internal bookkeeping variables:
-
-;; The value of `mh-folder-list-change-hook' is called whenever
-;; mh-folder-list variable is set.
-(defvar mh-folder-list nil) ;List of folder names for completion.
-
-;; Cached value of the `Path:' component in the user's MH profile.
-(defvar mh-user-path nil) ;User's mail folder directory.
-
-;; An mh-draft-folder of NIL means do not use a draft folder.
-;; Cached value of the `Draft-Folder:' component in the user's MH profile.
-(defvar mh-draft-folder nil) ;Name of folder containing draft messages.
-
-;; Cached value of the `Unseen-Sequence:' component in the user's MH profile.
-(defvar mh-unseen-seq nil) ;Name of the Unseen sequence.
-
-;; Cached value of the `Previous-Sequence:' component in the user's MH profile.
-(defvar mh-previous-seq nil) ;Name of the Previous sequence.
-
-;; Cached value of the `Inbox:' component in the user's MH profile,
-;; or "+inbox" if no such component.
-(defvar mh-inbox nil) ;Name of the Inbox folder.
-
-(defconst mh-temp-buffer " *mh-temp*") ;Name of mh-e scratch buffer.
-
-(defvar mh-previous-window-config nil) ;Window configuration before mh-e command.
-
-;;; Internal variables local to a folder.
-
-(defvar mh-current-folder nil) ;Name of current folder, a string.
-
-(defvar mh-show-buffer nil) ;Buffer that displays message for this folder.
-
-(defvar mh-folder-filename nil) ;Full path of directory for this folder.
-
-(defvar mh-msg-count nil) ;Number of msgs in buffer.
-
-(defvar mh-showing nil) ;If non-nil, show the message in a separate window.
-
-;;; This holds a documentation string used by describe-mode.
-(defun mh-showing ()
- "When moving to a new message in the Folder window,
-also show it in a separate Show window."
- nil)
-
-(defvar mh-seq-list nil) ;The sequences of this folder. An alist of (seq . msgs).
-
-(defvar mh-seen-list nil) ;List of displayed messages to be removed from the Unseen sequence.
-
-;; If non-nil, show buffer contains message with all headers.
-;; If nil, show buffer contains message processed normally.
-(defvar mh-showing-with-headers nil) ;Showing message with headers or normally.
-
-
-;;; mh-e macros
-
-(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
- (` (prog1
- (let ((mh-folder-updating-mod-flag (buffer-modified-p))
- (buffer-read-only nil)
- (buffer-file-name nil)) ;don't let the buffer get locked
- (prog1
- (progn
- (,@ body))
- (mh-set-folder-modified-p mh-folder-updating-mod-flag)))
- (,@ (if (not save-modification-flag-p)
- '((mh-set-folder-modified-p nil)))))))
-
-(put 'with-mh-folder-updating 'lisp-indent-hook 1)
-
-(defmacro mh-in-show-buffer (show-buffer &rest body)
- ;; Format is (mh-in-show-buffer (SHOW-BUFFER) &body BODY).
- ;; Display buffer SHOW-BUFFER in other window and execute BODY in it.
- ;; Stronger than save-excursion, weaker than save-window-excursion.
- (setq show-buffer (car show-buffer)) ; CL style
- (` (let ((mh-in-show-buffer-saved-window (selected-window)))
- (switch-to-buffer-other-window (, show-buffer))
- (if mh-bury-show-buffer (bury-buffer (current-buffer)))
- (unwind-protect
- (progn
- (,@ body))
- (select-window mh-in-show-buffer-saved-window)))))
-
-(put 'mh-in-show-buffer 'lisp-indent-hook 1)
-
-(defmacro mh-make-seq (name msgs) (list 'cons name msgs))
-
-(defmacro mh-seq-name (pair) (list 'car pair))
-
-(defmacro mh-seq-msgs (pair) (list 'cdr pair))
-
-
-;;; Ensure new buffers won't get this mode if default-major-mode is nil.
-(put 'mh-show-mode 'mode-class 'special)
-
-(defun mh-show-mode ()
- "Major mode for showing messages in mh-e.
-The value of mh-show-mode-hook is called when a new message is displayed."
- (kill-all-local-variables)
- (setq major-mode 'mh-show-mode)
- (mh-set-mode-name "MH-Show")
- (run-hooks 'mh-show-mode-hook))
-
-
-(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-show (&optional message)
- "Show MESSAGE (default: message at cursor).
-Force a two-window display with the folder window on top (size
-mh-summary-height) and the show buffer below it.
-If the message is already visible, display the start of the message.
-
-Display of the message is controlled by setting the variables
-`mh-clean-message-header' and `mhl-formfile'. The default behavior is
-to scroll uninteresting headers off the top of the window.
-Type \"\\[mh-header-display]\" to see the message with all its headers."
- (interactive)
- (and mh-showing-with-headers
- (or mhl-formfile mh-clean-message-header)
- (mh-invalidate-show-buffer))
- (mh-show-msg message))
-
-
-(defun mh-show-msg (msg)
- (if (not msg)
- (setq msg (mh-get-msg-num t)))
- (setq mh-showing t)
- (let ((folder mh-current-folder)
- (clean-message-header mh-clean-message-header)
- (show-window (get-buffer-window mh-show-buffer)))
- (if (not (eql (next-window (minibuffer-window)) (selected-window)))
- (delete-other-windows)) ; force ourself to the top window
- (mh-in-show-buffer (mh-show-buffer)
- (if (and show-window
- (equal (mh-msg-filename msg folder) buffer-file-name))
- (progn ;just back up to start
- (goto-char (point-min))
- (if (not clean-message-header)
- (mh-start-of-uncleaned-message)))
- (mh-display-msg msg folder))))
- (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)) (setq mh-seen-list (cons msg mh-seen-list)))
- (run-hooks 'mh-show-hook))
-
-
-(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))
- (if (not (file-exists-p msg-filename))
- (error "Message %d does not exist" msg-num))
- (set-buffer show-buffer)
- (cond ((not (equal msg-filename buffer-file-name))
- (mh-unvisit-file)
- (erase-buffer)
- ;; Changing contents, so this hook needs to be reinitialized.
- ;; pgp.el uses this.
- (if (boundp 'write-contents-hooks) ;Emacs 19
- (kill-local-variable 'write-contents-hooks))
- (if formfile
- (mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear"
- (if (stringp formfile)
- (list "-form" formfile))
- 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
- (mh-start-of-uncleaned-message)))
- ;; the parts of visiting we want to do (no locking)
- (or (eq buffer-undo-list t) ;don't save undo info for prev msgs
- (setq buffer-undo-list nil))
- (set-buffer-modified-p nil)
- (set-buffer-auto-saved)
- ;; the parts of set-visited-file-name we want to do (no locking)
- (setq buffer-file-name msg-filename)
- (setq buffer-backed-up nil)
- (auto-save-mode 1)
- (set-mark nil)
- (mh-show-mode)
- (setq mode-line-buffer-identification
- (list (format mh-show-buffer-mode-line-buffer-id
- folder msg-num)))
- (set-buffer folder)
- (setq mh-showing-with-headers nil)))))
-
-(defun mh-start-of-uncleaned-message ()
- ;; position uninteresting headers off the top of the window
- (let ((case-fold-search t))
- (re-search-forward
- "^To:\\|^Cc:\\|^From:\\|^Subject:\\|^Date:" nil t)
- (beginning-of-line)
- (mh-recenter 0)))
-
-
-(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)
- (mh-unvisit-file))))
-
-
-(defun mh-unvisit-file ()
- ;; Separate current buffer from the message file it was visiting.
- (or (not (buffer-modified-p))
- (null buffer-file-name) ;we've been here before
- (yes-or-no-p (format "Message %s modified; flush changes? "
- (file-name-nondirectory buffer-file-name)))
- (error "Flushing changes not confirmed"))
- (clear-visited-file-modtime)
- (unlock-buffer)
- (setq buffer-file-name nil))
-
-
-(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-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-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 'move)
- (backward-char 1))
- (narrow-to-region start (point))
- (goto-char (point-min))
- (if visible-headers
- (while (< (point) (point-max))
- (cond ((looking-at visible-headers)
- (forward-line 1)
- (while (looking-at "[ \t]") (forward-line 1)))
- (t
- (mh-delete-line 1)
- (while (looking-at "[ \t]")
- (mh-delete-line 1)))))
- (while (re-search-forward invisible-headers nil t)
- (beginning-of-line)
- (mh-delete-line 1)
- (while (looking-at "[ \t]")
- (mh-delete-line 1))))
- (unlock-buffer))))
-
-
-(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)))))
-
-
-(defun mh-delete-line (lines)
- ;; Delete version of kill-line.
- (delete-region (point) (progn (forward-line lines) (point))))
-
-
-(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)))))
-
-
-(defun mh-find-msg-get-num (step)
- ;; Return the message number of the message on the current scan line
- ;; or one nearby. Jumps over non-message lines, such as inc errors.
- ;; STEP tells whether to search forward or backward if we have to search.
- (or (mh-get-msg-num nil)
- (let ((msg-num nil)
- (nreverses 0))
- (while (and (not msg-num)
- (< nreverses 2))
- (cond ((eobp)
- (setq step -1)
- (setq nreverses (1+ nreverses)))
- ((bobp)
- (setq step 1)
- (setq nreverses (1+ nreverses))))
- (forward-line step)
- (setq msg-num (mh-get-msg-num nil)))
- msg-num)))
-
-(defun mh-goto-msg (number &optional no-error-if-no-message dont-show)
- "Position the cursor at message NUMBER.
-Optional non-nil second argument means return nil instead of
-signaling an error if message does not exist; in this case,
-the cursor is positioned near where the message would have been.
-Non-nil third argument means not to show the message."
- (interactive "NGo to message: ")
- (setq number (prefix-numeric-value number)) ;Emacs 19
- ;; This basic routine tries to be as fast as possible,
- ;; using a binary search and minimal regexps.
- (let ((cur-msg (mh-find-msg-get-num -1))
- (jump-size mh-msg-count))
- (while (and (> jump-size 1)
- cur-msg
- (not (eq cur-msg number)))
- (cond ((< cur-msg number)
- (setq jump-size (min (- number cur-msg)
- (ash (1+ jump-size) -1)))
- (forward-line jump-size)
- (setq cur-msg (mh-find-msg-get-num 1)))
- (t
- (setq jump-size (min (- cur-msg number)
- (ash (1+ jump-size) -1)))
- (forward-line (- jump-size))
- (setq cur-msg (mh-find-msg-get-num -1)))))
- (if (eq cur-msg number)
- (progn
- (beginning-of-line)
- (or dont-show
- (mh-maybe-show number)
- t))
- (if (not no-error-if-no-message)
- (error "No message %d" number)))))
-
-
-(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-get-profile-field (field)
- ;; Find and return the value of FIELD in the current buffer.
- ;; Returns NIL if the field is not in the buffer.
- (let ((case-fold-search t))
- (goto-char (point-min))
- (cond ((not (re-search-forward (format "^%s" field) nil t)) nil)
- ((looking-at "[\t ]*$") nil)
- (t
- (re-search-forward "[\t ]*\\([^\t \n].*\\)$" nil t)
- (let ((start (match-beginning 1)))
- (end-of-line)
- (buffer-substring start (point)))))))
-
-(defvar mail-user-agent 'mh-e-user-agent) ;from reporter.el 3.2
-
-(defun mh-find-path ()
- ;; Set mh-progs and mh-lib.
- ;; (This step is necessary if MH was installed after this Emacs was dumped.)
- ;; From profile file, set mh-user-path, mh-draft-folder,
- ;; mh-unseen-seq, mh-previous-seq, mh-inbox.
- (mh-find-progs)
- (save-excursion
- ;; Be sure profile is fully expanded before switching buffers
- (let ((profile (expand-file-name (or (getenv "MH") "~/.mh_profile"))))
- (set-buffer (get-buffer-create mh-temp-buffer))
- (setq buffer-offer-save nil) ;for people who set default to t
- (erase-buffer)
- (condition-case err
- (insert-file-contents profile)
- (file-error
- (mh-install profile err)))
- (setq mh-user-path (mh-get-profile-field "Path:"))
- (if (not 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 "~"))))
- (setq mh-draft-folder (mh-get-profile-field "Draft-Folder:"))
- (if mh-draft-folder
- (progn
- (if (not (mh-folder-name-p mh-draft-folder))
- (setq mh-draft-folder (format "+%s" mh-draft-folder)))
- (if (not (file-exists-p (mh-expand-file-name mh-draft-folder)))
- (error "Draft folder \"%s\" not found. Create it and try again."
- (mh-expand-file-name mh-draft-folder)))))
- (setq mh-inbox (mh-get-profile-field "Inbox:"))
- (cond ((not mh-inbox)
- (setq mh-inbox "+inbox"))
- ((not (mh-folder-name-p mh-inbox))
- (setq mh-inbox (format "+%s" mh-inbox))))
- (setq mh-unseen-seq (mh-get-profile-field "Unseen-Sequence:"))
- (if mh-unseen-seq
- (setq mh-unseen-seq (intern mh-unseen-seq))
- (setq mh-unseen-seq 'unseen)) ;old MH default?
- (setq mh-previous-seq (mh-get-profile-field "Previous-Sequence:"))
- (if mh-previous-seq
- (setq mh-previous-seq (intern mh-previous-seq)))
- (setq mail-user-agent 'mh-e-user-agent)
- (run-hooks 'mh-find-path-hook))))
-
-(defun mh-find-progs ()
- (or (file-exists-p (expand-file-name "inc" mh-progs))
- (setq mh-progs
- (or (mh-path-search exec-path "inc")
- (mh-path-search '("/usr/local/bin/mh/"
- "/usr/local/mh/"
- "/usr/bin/mh/" ;Ultrix 4.2
- "/usr/new/mh/" ;Ultrix <4.2
- "/usr/contrib/mh/bin/" ;BSDI
- "/usr/local/bin/"
- )
- "inc")
- mh-progs
- "/usr/local/bin/")))
- (or (file-exists-p (expand-file-name "mhl" mh-lib))
- (setq mh-lib
- (or (mh-path-search '("/usr/local/lib/mh/"
- "/usr/local/mh/lib/"
- "/usr/local/bin/mh/"
- "/usr/lib/mh/" ;Ultrix 4.2
- "/usr/new/lib/mh/" ;Ultrix <4.2
- "/usr/contrib/mh/lib/" ;BSDI
- )
- "mhl")
- (mh-path-search exec-path "mhl") ;unlikely
- mh-lib
- "/usr/local/lib/mh/"))))
-
-(defun mh-path-search (path file)
- ;; Search PATH, a list of directory names, for FILE.
- ;; Returns the element of PATH that contains FILE, or nil if not found.
- (while (and path
- (not (file-exists-p (expand-file-name file (car path)))))
- (setq path (cdr path)))
- (car path))
-
-(defvar mh-no-install nil) ;do not run install-mh
-
-(defun mh-install (profile error-val)
- ;; Called to do error recovery if we fail to read the profile file.
- ;; If possible, initialize the MH environment.
- (if (or (getenv "MH")
- (file-exists-p profile)
- mh-no-install)
- (signal (car error-val)
- (list (format "Cannot read MH profile \"%s\"" profile)
- (car (cdr (cdr error-val))))))
- ;; The "install-mh" command will output a short note which
- ;; mh-exec-cmd will display to the user.
- ;; The MH 5 version of install-mh might try prompt the user
- ;; for information, which would fail here.
- (mh-exec-cmd (expand-file-name "install-mh" mh-lib) "-auto")
- ;; now try again to read the profile file
- (erase-buffer)
- (condition-case err
- (insert-file-contents profile)
- (file-error
- (signal (car err) ;re-signal with more specific msg
- (list (format "Cannot read MH profile \"%s\"" profile)
- (car (cdr (cdr err))))))))
-
-
-(defun mh-set-folder-modified-p (flag)
- ;; Mark current folder as modified or unmodified according to FLAG.
- (set-buffer-modified-p flag))
-
-
-(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-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)
- (setq mh-seq-list (cons (mh-make-seq seq msgs) mh-seq-list))
- (if msgs (setcdr entry (append msgs (mh-seq-msgs entry)))))
- (cond ((not internal-flag)
- (mh-add-to-sequence seq msgs)
- (mh-notate-seq seq mh-note-seq (1+ mh-cmd-note))))))
-
-(autoload 'mh-add-to-sequence "mh-seq")
-(autoload 'mh-notate-seq "mh-seq")
-(autoload 'mh-read-seq-default "mh-seq")
-(autoload 'mh-map-to-seq-msgs "mh-seq")
-
-
-(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-mode-line-update t))
-
-
-(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.
- (if (null default)
- (setq default ""))
- (let* ((prompt (format "%s folder%s" prompt
- (if (equal "" default)
- "? "
- (format " [%s]? " default))))
- read-name folder-name)
- (if (null mh-folder-list)
- (mh-set-folder-list))
- (while (and (setq read-name (completing-read prompt mh-folder-list
- nil nil "+"))
- (equal read-name "")
- (equal default "")))
- (cond ((or (equal read-name "") (equal read-name "+"))
- (setq read-name default))
- ((not (mh-folder-name-p read-name))
- (setq read-name (format "+%s" read-name))))
- (setq folder-name read-name)
- (cond ((and (> (length folder-name) 0)
- (eql (aref folder-name (1- (length folder-name))) ?/))
- (setq folder-name (substring folder-name 0 -1))))
- (let ((new-file-p (not (file-exists-p (mh-expand-file-name folder-name)))))
- (cond ((and new-file-p
- (y-or-n-p
- (format "Folder %s does not exist. Create it? " folder-name)))
- (message "Creating %s" folder-name)
- (call-process "mkdir" nil nil nil (mh-expand-file-name folder-name))
- (message "Creating %s...done" folder-name)
- (setq mh-folder-list (cons (list read-name) mh-folder-list))
- (run-hooks 'mh-folder-list-change-hook))
- (new-file-p
- (error "Folder %s is not created" folder-name))
- ((not (file-directory-p (mh-expand-file-name folder-name)))
- (error "\"%s\" is not a directory"
- (mh-expand-file-name folder-name)))
- ((and (null (assoc read-name mh-folder-list))
- (null (assoc (concat read-name "/") mh-folder-list)))
- (setq mh-folder-list (cons (list read-name) mh-folder-list))
- (run-hooks 'mh-folder-list-change-hook))))
- folder-name))
-
-
-(defvar mh-make-folder-list-process nil) ;The background process collecting the folder list.
-
-(defvar mh-folder-list-temp nil) ;mh-folder-list as it is being built.
-
-(defvar mh-folder-list-partial-line "") ;Start of last incomplete line from folder process.
-
-(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. Format is in a form suitable for completing read.
- (message "Collecting folder names...")
- (if (not mh-make-folder-list-process)
- (mh-make-folder-list-background))
- (while (eq (process-status mh-make-folder-list-process) 'run)
- (accept-process-output mh-make-folder-list-process))
- (setq mh-folder-list mh-folder-list-temp)
- (run-hooks 'mh-folder-list-change-hook)
- (setq mh-folder-list-temp nil)
- (delete-process mh-make-folder-list-process)
- (setq mh-make-folder-list-process nil)
- (message "Collecting folder names...done"))
-
-(defun mh-make-folder-list-background ()
- ;; Start a background process to compute a list of the user's folders.
- ;; Call mh-set-folder-list to wait for the result.
- (cond
- ((not mh-make-folder-list-process)
- (mh-find-path)
- (let ((process-connection-type nil))
- (setq mh-make-folder-list-process
- (start-process "folders" nil (expand-file-name "folders" mh-progs)
- "-fast"
- (if mh-recursive-folders
- "-recurse"
- "-norecurse")))
- (set-process-filter mh-make-folder-list-process
- 'mh-make-folder-list-filter)
- (process-kill-without-query mh-make-folder-list-process)))))
-
-(defun mh-make-folder-list-filter (process output)
- ;; parse output from "folders -fast"
- (let ((position 0)
- line-end
- new-folder
- (prevailing-match-data (match-data)))
- (unwind-protect
- ;; make sure got complete line
- (while (setq line-end (string-match "\n" output position))
- (setq new-folder (format "+%s%s"
- mh-folder-list-partial-line
- (substring output position line-end)))
- (setq mh-folder-list-partial-line "")
- ;; is new folder a subfolder of previous?
- (if (and mh-folder-list-temp
- (string-match
- (regexp-quote
- (concat (car (car mh-folder-list-temp)) "/"))
- new-folder))
- ;; append slash to parent folder for better completion
- ;; (undone by mh-prompt-for-folder)
- (setq mh-folder-list-temp
- (cons
- (list new-folder)
- (cons
- (list (concat (car (car mh-folder-list-temp)) "/"))
- (cdr mh-folder-list-temp))))
- (setq mh-folder-list-temp
- (cons (list new-folder)
- mh-folder-list-temp)))
- (setq position (1+ line-end)))
- (store-match-data prevailing-match-data))
- (setq mh-folder-list-partial-line (substring output position))))
-
-
-(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) ?+)
- (and (> (length name) 0)
- (eql (aref name 0) ?+))))
-
-
-;;; Issue commands to MH.
-
-
-(defun mh-exec-cmd (command &rest args)
- ;; Execute mh-command COMMAND with ARGS.
- ;; The side effects are what is desired.
- ;; Any output is assumed to be an error and is shown to the user.
- ;; The output is not read or parsed by mh-e.
- (save-excursion
- (set-buffer (get-buffer-create mh-temp-buffer))
- (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-buffer)
- (sit-for 5)))))
-
-
-(defun mh-exec-cmd-error (env command &rest args)
- ;; In environment ENV, execute mh-command COMMAND with args ARGS.
- ;; ENV is nil or a string of space-separated "var=value" elements.
- ;; Signals an error if process does not complete successfully.
- (save-excursion
- (set-buffer (get-buffer-create mh-temp-buffer))
- (erase-buffer)
- (let ((status
- (if env
- ;; the shell hacks necessary here shows just how broken Unix is
- (apply 'call-process "/bin/sh" nil t nil "-c"
- (format "%s %s ${1+\"$@\"}"
- env
- (expand-file-name command mh-progs))
- command
- (mh-list-to-string args))
- (apply 'call-process
- (expand-file-name command mh-progs) nil t nil
- (mh-list-to-string args)))))
- (mh-handle-process-error command status))))
-
-
-(defun mh-exec-cmd-daemon (command &rest args)
- ;; Execute MH command COMMAND with ARGS in the background.
- ;; Any output from command is displayed in an asynchronous pop-up window.
- (save-excursion
- (set-buffer (get-buffer-create mh-temp-buffer))
- (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-buffer))
- (insert-before-markers output)
- (display-buffer mh-temp-buffer))
-
-
-(defun mh-exec-cmd-quiet (raise-error command &rest args)
- ;; Args are RAISE-ERROR, COMMANDS, ARGS....
- ;; Execute MH command COMMAND with ARGS. ARGS is a list of strings.
- ;; Return at start of mh-temp buffer, where output can be parsed and used.
- ;; Returns value of call-process, which is 0 for success,
- ;; unless RAISE-ERROR is non-nil, in which case an error is signaled
- ;; if call-process returns non-0.
- (set-buffer (get-buffer-create mh-temp-buffer))
- (erase-buffer)
- (let ((value
- (apply 'call-process
- (expand-file-name command mh-progs) nil t nil
- args)))
- (goto-char (point-min))
- (if raise-error
- (mh-handle-process-error command value)
- value)))
-
-
-(defun mh-exec-cmd-output (command display &rest args)
- ;; Execute MH command COMMAND with DISPLAY flag and ARGS.
- ;; Put the output into buffer after point. Set mark after inserted text.
- ;; Output is expected to be shown to user, not parsed by mh-e.
- (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-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.
- (apply 'mh-exec-cmd-output (expand-file-name command mh-lib) nil args))
-
-
-(defun mh-handle-process-error (command status)
- ;; Raise error if COMMAND returned non-0 STATUS, otherwise return STATUS.
- ;; STATUS is return value from call-process.
- ;; Program output is in current buffer.
- ;; If output is too long to include in error message, display the buffer.
- (cond ((eql status 0) ;success
- status)
- ((stringp status) ;kill string
- (error "%s: %s" command status))
- (t ;exit code
- (cond
- ((= (buffer-size) 0) ;program produced no error message
- (error "%s: exit code %d" command status))
- (t
- ;; will error message fit on one line?
- (goto-line 2)
- (if (and (< (buffer-size) (screen-width))
- (eobp))
- (error "%s"
- (buffer-substring 1 (progn (goto-char 1)
- (end-of-line)
- (point))))
- (display-buffer (current-buffer))
- (error "%s failed with status %d. See error message in other window."
- command status)))))))
-
-
-(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-list-to-string (l)
- ;; Flattens the list L and makes every element of the new list into a string.
- (nreverse (mh-list-to-string-1 l)))
-
-(defun mh-list-to-string-1 (l)
- (let ((new-list nil))
- (while l
- (cond ((null (car l)))
- ((symbolp (car l))
- (setq new-list (cons (symbol-name (car l)) new-list)))
- ((numberp (car l))
- (setq new-list (cons (int-to-string (car l)) new-list)))
- ((equal (car l) ""))
- ((stringp (car l)) (setq new-list (cons (car l) new-list)))
- ((listp (car l))
- (setq new-list (nconc (mh-list-to-string-1 (car l))
- new-list)))
- (t (error "Bad element in mh-list-to-string: %s" (car l))))
- (setq l (cdr l)))
- new-list))
-
-(provide 'mh-utils)
-
-(and (not noninteractive)
- mh-auto-folder-collect
- (let ((mh-no-install t)) ;only get folders if MH installed
- (condition-case err
- (mh-make-folder-list-background)
- (file-error)))) ;so don't complain if not installed
-
-;;; mh-utils.el ends here
diff --git a/lisp/mail/reporter.el b/lisp/mail/reporter.el
deleted file mode 100644
index 76d7108d1a0..00000000000
--- a/lisp/mail/reporter.el
+++ /dev/null
@@ -1,437 +0,0 @@
-;;; reporter.el --- customizable bug reporting of lisp programs
-
-;; Copyright (C) 1993 1994 1995 1996 Free Software Foundation, Inc.
-
-;; Author: 1993-1996 Barry A. Warsaw
-;; Created: 19-Apr-1993
-;; Version: 3.3
-;; Last Modified: 1996/07/02 00:39:09
-;; Keywords: maint mail tools
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; End User Interface
-;; ==================
-;; The variable `mail-user-agent' contains a symbol indicating which
-;; Emacs mail package end users would like to use to compose outgoing
-;; mail. See that variable for details.
-
-;; Lisp Package Authors
-;; ====================
-;; Reporter was written primarily for Emacs Lisp package authors so
-;; that their users can easily report bugs. When invoked,
-;; reporter-submit-bug-report will set up an outgoing mail buffer with
-;; the appropriate bug report address, including a lisp expression the
-;; maintainer of the package can eval to completely reproduce the
-;; environment in which the bug was observed (e.g. by using
-;; eval-last-sexp). This package proved especially useful during my
-;; development of cc-mode, which is highly dependent on its
-;; configuration variables.
-;;
-;; Do a "C-h f reporter-submit-bug-report" for more information.
-;; Here's an example usage:
-;;
-;;(defconst mypkg-version "9.801")
-;;(defconst mypkg-maintainer-address "mypkg-help@foo.com")
-;;(defun mypkg-submit-bug-report ()
-;; "Submit via mail a bug report on mypkg"
-;; (interactive)
-;; (reporter-submit-bug-report
-;; mypkg-maintainer-address
-;; (concat "mypkg.el " mypkg-version)
-;; (list 'mypkg-variable-1
-;; 'mypkg-variable-2
-;; ;; ...
-;; 'mypkg-variable-last)))
-
-;; Mailing List
-;; ============
-;; I've set up a Majordomo mailing list to report bugs or suggest
-;; enhancements, etc. This list's intended audience is elisp package
-;; authors who are using reporter and want to stay current with
-;; releases. Here are the relevant addresses:
-;;
-;; Administrivia: reporter-request@python.org
-;; Submissions: reporter@python.org
-
-;; Packages that currently use reporter are: cc-mode, supercite, elp,
-;; tcl, ediff, crypt++ (crypt), dired-x, rmailgen, mode-line, vm,
-;; mh-e, edebug, archie, viper, w3-mode, framepop, hl319, hilit19,
-;; pgp, eos, hm--html, efs.
-;;
-;; If you know of others, please email me!
-
-;;; Code:
-
-;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-;; Package author interface variables
-
-(defvar reporter-prompt-for-summary-p nil
- "Interface variable controlling prompting for problem summary.
-When non-nil, `reporter-submit-bug-report' prompts the user for a
-brief summary of the problem, and puts this summary on the Subject:
-line. If this variable is a string, that string is used as the prompt
-string.
-
-Default behavior is to not prompt (i.e. nil). If you want reporter to
-prompt, you should `let' bind this variable before calling
-`reporter-submit-bug-report'. Note that this variable is not
-buffer-local so you should never just `setq' it.")
-
-(defvar reporter-dont-compact-list nil
- "Interface variable controlling compacting of list values.
-When non-nil, this must be a list of variable symbols. When a
-variable containing a list value is formatted in the bug report mail
-buffer, it normally is compacted so that its value fits one the fewest
-number of lines. If the variable's symbol appears in this list, its
-value is printed in a more verbose style, specifically, one elemental
-sexp per line.
-
-Note that this variable is not buffer-local so you should never just
-`setq' it. If you want to changes its default value, you should `let'
-bind it.")
-
-;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-;; End of editable variables
-
-
-(defvar reporter-eval-buffer nil
- "Buffer to retrieve variable's value from.
-This is necessary to properly support the printing of buffer-local
-variables. Current buffer will always be the mail buffer being
-composed.")
-
-(defconst reporter-version "3.2"
- "Reporter version number.")
-
-(defvar reporter-initial-text nil
- "The automatically created initial text of a bug report.")
-(make-variable-buffer-local 'reporter-initial-text)
-
-
-
-;; status feedback to the user
-(defvar reporter-status-message nil)
-(defvar reporter-status-count nil)
-
-(defun reporter-update-status ()
- ;; periodically output a status message
- (if (zerop (% reporter-status-count 10))
- (progn
- (message reporter-status-message)
- (setq reporter-status-message (concat reporter-status-message "."))))
- (setq reporter-status-count (1+ reporter-status-count)))
-
-
-;; dumping/pretty printing of values
-(defun reporter-beautify-list (maxwidth compact-p)
- ;; pretty print a list
- (reporter-update-status)
- (let (linebreak indent-enclosing-p indent-p here)
- (condition-case nil ;loop exit
- (progn
- (down-list 1)
- (setq indent-enclosing-p t)
- (while t
- (setq here (point))
- (forward-sexp 1)
- (if (<= maxwidth (current-column))
- (if linebreak
- (progn
- (goto-char linebreak)
- (newline-and-indent)
- (setq linebreak nil))
- (goto-char here)
- (setq indent-p (reporter-beautify-list maxwidth compact-p))
- (goto-char here)
- (forward-sexp 1)
- (if indent-p
- (newline-and-indent))
- t)
- (if compact-p
- (setq linebreak (point))
- (newline-and-indent))
- ))
- t)
- (error indent-enclosing-p))))
-
-(defun reporter-lisp-indent (indent-point state)
- ;; a better lisp indentation style for bug reporting
- (save-excursion
- (goto-char (1+ (nth 1 state)))
- (current-column)))
-
-(defun reporter-dump-variable (varsym mailbuf)
- ;; Pretty-print the value of the variable in symbol VARSYM. MAILBUF
- ;; is the mail buffer being composed
- (reporter-update-status)
- (condition-case nil
- (let ((val (save-excursion
- (set-buffer reporter-eval-buffer)
- (symbol-value varsym)))
- (sym (symbol-name varsym))
- (print-escape-newlines t)
- (maxwidth (1- (window-width)))
- (here (point)))
- (insert " " sym " "
- (cond
- ((memq val '(t nil)) "")
- ((listp val) "'")
- ((symbolp val) "'")
- (t ""))
- (prin1-to-string val))
- (lisp-indent-line)
- ;; clean up lists, but only if the line as printed was long
- ;; enough to wrap
- (if (and val ;nil is a list, but short
- (listp val)
- (<= maxwidth (current-column)))
- (save-excursion
- (let ((compact-p (not (memq varsym reporter-dont-compact-list)))
- (lisp-indent-function 'reporter-lisp-indent))
- (goto-char here)
- (reporter-beautify-list maxwidth compact-p))))
- (insert "\n"))
- (void-variable
- (save-excursion
- (set-buffer mailbuf)
- (mail-position-on-field "X-Reporter-Void-Vars-Found")
- (end-of-line)
- (insert (symbol-name varsym) " ")))
- (error
- (error ""))))
-
-(defun reporter-dump-state (pkgname varlist pre-hooks post-hooks)
- ;; Dump the state of the mode specific variables.
- ;; PKGNAME contains the name of the mode as it will appear in the bug
- ;; report (you must explicitly concat any version numbers).
-
- ;; VARLIST is the list of variables to dump. Each element in
- ;; VARLIST can be a variable symbol, or a cons cell. If a symbol,
- ;; this will be passed to `reporter-dump-variable' for insertion
- ;; into the mail buffer. If a cons cell, the car must be a variable
- ;; symbol and the cdr must be a function which will be `funcall'd
- ;; with arguments the symbol and the mail buffer being composed. Use
- ;; this to write your own custom variable value printers for
- ;; specific variables.
-
- ;; Note that the global variable `reporter-eval-buffer' will be bound to
- ;; the buffer in which `reporter-submit-bug-report' was invoked. If you
- ;; want to print the value of a buffer local variable, you should wrap
- ;; the `eval' call in your custom printer inside a `set-buffer' (and
- ;; probably a `save-excursion'). `reporter-dump-variable' handles this
- ;; properly.
-
- ;; PRE-HOOKS is run after the emacs-version and PKGNAME are inserted, but
- ;; before the VARLIST is dumped. POST-HOOKS is run after the VARLIST is
- ;; dumped.
- (let ((buffer (current-buffer)))
- (set-buffer buffer)
- (insert "Emacs : " (emacs-version) "\n")
- (and pkgname
- (insert "Package: " pkgname "\n"))
- (run-hooks 'pre-hooks)
- (if (not varlist)
- nil
- (insert "\ncurrent state:\n==============\n")
- ;; create an emacs-lisp-mode buffer to contain the output, which
- ;; we'll later insert into the mail buffer
- (condition-case fault
- (let ((mailbuf (current-buffer))
- (elbuf (get-buffer-create " *tmp-reporter-buffer*")))
- (save-excursion
- (set-buffer elbuf)
- (emacs-lisp-mode)
- (erase-buffer)
- (insert "(setq\n")
- (lisp-indent-line)
- (mapcar
- (function
- (lambda (varsym-or-cons-cell)
- (let ((varsym (or (car-safe varsym-or-cons-cell)
- varsym-or-cons-cell))
- (printer (or (cdr-safe varsym-or-cons-cell)
- 'reporter-dump-variable)))
- (funcall printer varsym mailbuf)
- )))
- varlist)
- (lisp-indent-line)
- (insert ")\n"))
- (insert-buffer elbuf))
- (error
- (insert "State could not be dumped due to the following error:\n\n"
- (format "%s" fault)
- "\n\nYou should still send this bug report."))))
- (run-hooks 'post-hooks)
- ))
-
-
-(defun reporter-calculate-separator ()
- ;; returns the string regexp matching the mail separator
- (save-excursion
- (re-search-forward
- (concat
- "^\\(" ;beginning of line
- (mapconcat
- 'identity
- (list "[\t ]*" ;simple SMTP form
- "-+" ;mh-e form
- (regexp-quote
- mail-header-separator)) ;sendmail.el form
- "\\|") ;or them together
- "\\)$") ;end of line
- nil
- 'move) ;search for and move
- (buffer-substring (match-beginning 0) (match-end 0))))
-
-
-(defun reporter-compose-outgoing ()
- ;; compose the outgoing mail buffer, and return the selected
- ;; paradigm, with the current-buffer tacked onto the beginning of
- ;; the list.
- (let* ((agent mail-user-agent)
- (compose (get mail-user-agent 'composefunc)))
- ;; Sanity check. If this fails then we'll try to use the SENDMAIL
- ;; protocol, otherwise we must signal an error.
- (if (not (and compose (fboundp compose)))
- (progn
- (setq agent 'sendmail-user-agent
- compose (get agent 'composefunc))
- (if (not (and compose (fboundp compose)))
- (error "Could not find a valid `mail-user-agent'")
- (ding)
- (message "`%s' is an invalid `mail-user-agent'; using `sendmail-user-agent'"
- mail-user-agent)
- )))
- (funcall compose)
- agent))
-
-
-;;;###autoload
-(defun reporter-submit-bug-report
- (address pkgname varlist &optional pre-hooks post-hooks salutation)
- ;; Submit a bug report via mail.
-
- ;; ADDRESS is the email address for the package's maintainer. PKGNAME is
- ;; the name of the mode (you must explicitly concat any version numbers).
- ;; VARLIST is the list of variables to dump (see `reporter-dump-state'
- ;; for details). Optional PRE-HOOKS and POST-HOOKS are passed to
- ;; `reporter-dump-state'. Optional SALUTATION is inserted at the top of the
- ;; mail buffer, and point is left after the salutation.
-
- ;; This function will prompt for a summary if
- ;; reporter-prompt-for-summary-p is non-nil.
-
- ;; The mailer used is described in by the variable `mail-user-agent'.
- (let ((reporter-eval-buffer (current-buffer))
- final-resting-place
- after-sep-pos
- (reporter-status-message "Formatting bug report buffer...")
- (reporter-status-count 0)
- (problem (and reporter-prompt-for-summary-p
- (read-string (if (stringp reporter-prompt-for-summary-p)
- reporter-prompt-for-summary-p
- "(Very) brief summary of problem: "))))
- (agent (reporter-compose-outgoing))
- (mailbuf (current-buffer))
- hookvar)
- ;; do the work
- (require 'sendmail)
- ;; If mailbuf did not get made visible before, make it visible now.
- (let (same-window-buffer-names same-window-regexps)
- (pop-to-buffer mailbuf)
- ;; Just in case the original buffer is not visible now, bring it
- ;; back somewhere
- (display-buffer reporter-eval-buffer))
- (goto-char (point-min))
- ;; different mailers use different separators, some may not even
- ;; use mail-header-separator, but sendmail.el stuff must have this
- ;; variable bound.
- (let ((mail-header-separator (reporter-calculate-separator)))
- (mail-position-on-field "to")
- (insert address)
- ;; insert problem summary if available
- (if (and reporter-prompt-for-summary-p problem pkgname)
- (progn
- (mail-position-on-field "subject")
- (insert pkgname "; " problem)))
- ;; move point to the body of the message
- (mail-text)
- (forward-line 1)
- (setq after-sep-pos (point))
- (and salutation (insert "\n" salutation "\n\n"))
- (unwind-protect
- (progn
- (setq final-resting-place (point-marker))
- (insert "\n\n")
- (reporter-dump-state pkgname varlist pre-hooks post-hooks)
- (goto-char final-resting-place))
- (set-marker final-resting-place nil)))
-
- ;; save initial text and set up the `no-empty-submission' hook.
- ;; This only works for mailers that support a pre-send hook, and
- ;; for which the paradigm has a non-nil value for the `hookvar'
- ;; key in its agent (i.e. sendmail.el's mail-send-hook).
- (save-excursion
- (goto-char (point-max))
- (skip-chars-backward " \t\n")
- (setq reporter-initial-text (buffer-substring after-sep-pos (point))))
- (if (setq hookvar (get agent 'hookvar))
- (progn
- (make-variable-buffer-local hookvar)
- (add-hook hookvar 'reporter-bug-hook)))
-
- ;; compose the minibuf message and display this.
- (let* ((sendkey-whereis (where-is-internal
- (get agent 'sendfunc) nil t))
- (abortkey-whereis (where-is-internal
- (get agent 'abortfunc) nil t))
- (sendkey (if sendkey-whereis
- (key-description sendkey-whereis)
- "C-c C-c")) ; TBD: BOGUS hardcode
- (abortkey (if abortkey-whereis
- (key-description abortkey-whereis)
- "M-x kill-buffer")) ; TBD: BOGUS hardcode
- )
- (message "Please enter your report. Type %s to send, %s to abort."
- sendkey abortkey))
- ))
-
-(defun reporter-bug-hook ()
- ;; prohibit sending mail if empty bug report
- (let ((after-sep-pos
- (save-excursion
- (beginning-of-buffer)
- (re-search-forward (reporter-calculate-separator) (point-max) 'move)
- (forward-line 1)
- (point))))
- (save-excursion
- (goto-char (point-max))
- (skip-chars-backward " \t\n")
- (if (and (= (- (point) after-sep-pos)
- (length reporter-initial-text))
- (string= (buffer-substring after-sep-pos (point))
- reporter-initial-text))
- (error "Bug report was empty--not sent"))
- )))
-
-
-(provide 'reporter)
-;;; reporter.el ends here
diff --git a/lisp/mail/rfc822.el b/lisp/mail/rfc822.el
deleted file mode 100644
index 178dd943cb6..00000000000
--- a/lisp/mail/rfc822.el
+++ /dev/null
@@ -1,319 +0,0 @@
-;;; rfc822.el --- hairy rfc822 parser for mail and news and suchlike
-
-;; Copyright (C) 1986, 87, 1990 Free Software Foundation, Inc.
-
-;; Author: Richard Mlynarik <mly@eddie.mit.edu>
-;; Maintainer: FSF
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Support functions for parsing RFC-822 headers, used by mail and news
-;; modes.
-
-;;; Code:
-
-;; uses address-start free, throws to address
-(defun rfc822-bad-address (reason)
- (save-restriction
- (insert "_^_")
- (narrow-to-region address-start
- (if (re-search-forward "[,;]" nil t)
- (max (point-min) (1- (point)))
- (point-max)))
- ;; make the error string be suitable for inclusion in (...)
- (let ((losers '("\\" "(" ")" "\n")))
- (while losers
- (goto-char (point-min))
- (while (search-forward (car losers) nil t)
- (backward-char 1)
- (insert ?\\)
- (forward-char 1))
- (setq losers (cdr losers))))
- (goto-char (point-min)) (insert "(Unparsable address -- "
- reason
- ": \"")
- (goto-char (point-max)) (insert "\")"))
- (rfc822-nuke-whitespace)
- (throw 'address (buffer-substring address-start (point))))
-
-(defun rfc822-nuke-whitespace (&optional leave-space)
- (let (ch)
- (while (cond ((eobp)
- nil)
- ((= (setq ch (following-char)) ?\()
- (forward-char 1)
- (while (if (eobp)
- (rfc822-bad-address "Unbalanced comment (...)")
- (/= (setq ch (following-char)) ?\)))
- (cond ((looking-at "[^()\\]+")
- (replace-match ""))
- ((= ch ?\()
- (rfc822-nuke-whitespace))
- ((< (point) (1- (point-max)))
- (delete-char 2))
- (t
- (rfc822-bad-address "orphaned backslash"))))
- ;; delete remaining "()"
- (forward-char -1)
- (delete-char 2)
- t)
- ((memq ch '(?\ ?\t ?\n))
- (delete-region (point)
- (progn (skip-chars-forward " \t\n") (point)))
- t)
- (t
- nil)))
- (or (not leave-space)
- (eobp)
- (bobp)
- (= (preceding-char) ?\ )
- (insert ?\ ))))
-
-(defun rfc822-looking-at (regex &optional leave-space)
- (if (cond ((stringp regex)
- (if (looking-at regex)
- (progn (goto-char (match-end 0))
- t)))
- (t
- (if (and (not (eobp))
- (= (following-char) regex))
- (progn (forward-char 1)
- t))))
- (let ((tem (match-data)))
- (rfc822-nuke-whitespace leave-space)
- (store-match-data tem)
- t)))
-
-(defun rfc822-snarf-word ()
- ;; word is atom | quoted-string
- (cond ((= (following-char) ?\")
- ;; quoted-string
- (or (rfc822-looking-at "\"\\([^\"\\\n]\\|\\\\.\\|\\\\\n\\)*\"")
- (rfc822-bad-address "Unterminated quoted string")))
- ((rfc822-looking-at "[^][\000-\037\177-\377 ()<>@,;:\\\".]+")
- ;; atom
- )
- (t
- (rfc822-bad-address "Rubbish in address"))))
-
-(defun rfc822-snarf-words ()
- (rfc822-snarf-word)
- (while (rfc822-looking-at ?.)
- (rfc822-snarf-word)))
-
-(defun rfc822-snarf-subdomain ()
- ;; sub-domain is domain-ref | domain-literal
- (cond ((= (following-char) ?\[)
- ;; domain-ref
- (or (rfc822-looking-at "\\[\\([^][\\\n]\\|\\\\.\\|\\\\\n\\)*\\]")
- (rfc822-bad-address "Unterminated domain literal [...]")))
- ((rfc822-looking-at "[^][\000-\037\177-\377 ()<>@,;:\\\".]+")
- ;; domain-literal = atom
- )
- (t
- (rfc822-bad-address "Rubbish in host/domain specification"))))
-
-(defun rfc822-snarf-domain ()
- (rfc822-snarf-subdomain)
- (while (rfc822-looking-at ?.)
- (rfc822-snarf-subdomain)))
-
-(defun rfc822-snarf-frob-list (name separator terminator snarfer
- &optional return)
- (let ((first t)
- (list ())
- tem)
- (while (cond ((eobp)
- (rfc822-bad-address
- (format "End of addresses in middle of %s" name)))
- ((rfc822-looking-at terminator)
- nil)
- ((rfc822-looking-at separator)
- ;; multiple separators are allowed and do nothing.
- (while (rfc822-looking-at separator))
- t)
- (first
- t)
- (t
- (rfc822-bad-address
- (format "Gubbish in middle of %s" name))))
- (setq tem (funcall snarfer)
- first nil)
- (and return tem
- (setq list (if (listp tem)
- (nconc (reverse tem) list)
- (cons tem list)))))
- (nreverse list)))
-
-;; return either an address (a string) or a list of addresses
-(defun rfc822-addresses-1 (&optional allow-groups)
- ;; Looking for an rfc822 `address'
- ;; Either a group (1*word ":" [#mailbox] ";")
- ;; or a mailbox (addr-spec | 1*word route-addr)
- ;; addr-spec is (local-part "@" domain)
- ;; route-addr is ("<" [1#("@" domain) ":"] addr-spec ">")
- ;; local-part is (word *("." word))
- ;; word is (atom | quoted-string)
- ;; quoted-string is ("\([^\"\\n]\|\\.\|\\\n\)")
- ;; atom is [^\000-\037\177 ()<>@,;:\".[]]+
- ;; domain is sub-domain *("." sub-domain)
- ;; sub-domain is domain-ref | domain-literal
- ;; domain-literal is "[" *(dtext | quoted-pair) "]"
- ;; dtext is "[^][\\n"
- ;; domain-ref is atom
- (let ((address-start (point))
- (n 0))
- (catch 'address
- ;; optimize common cases:
- ;; foo
- ;; foo.bar@bar.zap
- ;; followed by "\\'\\|,\\|([^()\\]*)\\'"
- ;; other common cases are:
- ;; foo bar <foo.bar@baz.zap>
- ;; "foo bar" <foo.bar@baz.zap>
- ;; those aren't hacked yet.
- (if (and (rfc822-looking-at "[^][\000-\037\177-\377 ()<>@,;:\\\"]+\\(\\|@[^][\000-\037\177-\377 ()<>@,;:\\\"]+\\)" t)
- (progn (or (eobp)
- (rfc822-looking-at ?,))))
- (progn
- ;; rfc822-looking-at may have inserted a space
- (or (bobp) (/= (preceding-char) ?\ ) (delete-char -1))
- ;; relying on the fact that rfc822-looking-at <char>
- ;; doesn't mung match-data
- (throw 'address (buffer-substring address-start (match-end 0)))))
- (goto-char address-start)
- (while t
- (cond ((and (= n 1) (rfc822-looking-at ?@))
- ;; local-part@domain
- (rfc822-snarf-domain)
- (throw 'address
- (buffer-substring address-start (point))))
- ((rfc822-looking-at ?:)
- (cond ((not allow-groups)
- (rfc822-bad-address "A group name may not appear here"))
- ((= n 0)
- (rfc822-bad-address "No name for :...; group")))
- ;; group
- (throw 'address
- ;; return a list of addresses
- (rfc822-snarf-frob-list ":...; group" ?\, ?\;
- 'rfc822-addresses-1 t)))
- ((rfc822-looking-at ?<)
- (let ((start (point))
- (strip t))
- (cond ((rfc822-looking-at ?>)
- ;; empty path
- ())
- ((and (not (eobp)) (= (following-char) ?\@))
- ;; <@foo.bar,@baz:quux@abcd.efg>
- (rfc822-snarf-frob-list "<...> address" ?\, ?\:
- (function (lambda ()
- (if (rfc822-looking-at ?\@)
- (rfc822-snarf-domain)
- (rfc822-bad-address
- "Gubbish in route-addr")))))
- (rfc822-snarf-words)
- (or (rfc822-looking-at ?@)
- (rfc822-bad-address "Malformed <..@..> address"))
- (rfc822-snarf-domain)
- (setq strip nil))
- ((progn (rfc822-snarf-words) (rfc822-looking-at ?@))
- ; allow <foo> (losing unix seems to do this)
- (rfc822-snarf-domain)))
- (let ((end (point)))
- (if (rfc822-looking-at ?\>)
- (throw 'address
- (buffer-substring (if strip start (1- start))
- (if strip end (1+ end))))
- (rfc822-bad-address "Unterminated <...> address")))))
- ((looking-at "[^][\000-\037\177-\377 ()<>@,;:\\.]")
- ;; this allows "." to be part of the words preceding
- ;; an addr-spec, since many broken mailers output
- ;; "Hern K. Herklemeyer III
- ;; <yank@megadeath.dod.gods-own-country>"
- (let ((again t))
- (while again
- (or (= n 0) (bobp) (= (preceding-char) ?\ )
- (insert ?\ ))
- (rfc822-snarf-words)
- (setq n (1+ n))
- (setq again (or (rfc822-looking-at ?.)
- (looking-at "[^][\000-\037\177-\377 ()<>@,;:\\.]"))))))
- ((= n 0)
- (throw 'address nil))
- ((= n 1) ; allow "foo" (losing unix seems to do this)
- (throw 'address
- (buffer-substring address-start (point))))
- ((> n 1)
- (rfc822-bad-address "Missing comma between addresses or badly-formatted address"))
- ((or (eobp) (= (following-char) ?,))
- (rfc822-bad-address "Missing comma or route-spec"))
- (t
- (rfc822-bad-address "Strange character or missing comma")))))))
-
-
-(defun rfc822-addresses (header-text)
- (if (string-match "\\`[ \t]*\\([^][\000-\037\177-\377 ()<>@,;:\\\".]+\\)[ \t]*\\'"
- header-text)
- ;; Make very simple case moderately fast.
- (list (substring header-text (match-beginning 1) (match-end 1)))
- (let ((buf (generate-new-buffer " rfc822")))
- (unwind-protect
- (save-excursion
- (set-buffer buf)
- (make-local-variable 'case-fold-search)
- (setq case-fold-search nil) ;For speed(?)
- (insert header-text)
- ;; unfold continuation lines
- (goto-char (point-min))
-
- (while (re-search-forward "\\([^\\]\\(\\\\\\\\\\)*\\)\n[ \t]" nil t)
- (replace-match "\\1 " t))
-
- (goto-char (point-min))
- (rfc822-nuke-whitespace)
- (let ((list ())
- tem
- address-start); this is for rfc822-bad-address
- (while (not (eobp))
- (setq address-start (point))
- (setq tem
- (catch 'address ; this is for rfc822-bad-address
- (cond ((rfc822-looking-at ?\,)
- nil)
- ((looking-at "[][\000-\037\177-\377@;:\\.>)]")
- (forward-char)
- (rfc822-bad-address
- (format "Strange character \\%c found"
- (preceding-char))))
- (t
- (rfc822-addresses-1 t)))))
- (cond ((null tem))
- ((stringp tem)
- (setq list (cons tem list)))
- (t
- (setq list (nconc (nreverse tem) list)))))
- (nreverse list)))
- (and buf (kill-buffer buf))))))
-
-(provide 'rfc822)
-
-;;; rfc822.el ends here
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el
deleted file mode 100644
index 30493fea700..00000000000
--- a/lisp/mail/rmail.el
+++ /dev/null
@@ -1,2715 +0,0 @@
-;;; rmail.el --- main code of "RMAIL" mail reader for Emacs.
-
-;; Copyright (C) 1985,86,87,88,93,94,95,96 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;; 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.
-
-;; Extended by Bob Weiner of Motorola
-;; New features include: rmail and rmail-summary buffers remain
-;; synchronized and key bindings basically operate the same way in both
-;; buffers, summary by topic or by regular expression, rmail-reply-prefix
-;; variable, and a bury rmail buffer (wipe) command.
-;;
-
-(require 'mail-utils)
-
-;; For Emacs V18 compatibility
-(and (not (fboundp 'buffer-disable-undo))
- (fboundp 'buffer-flush-undo)
- (defalias 'buffer-disable-undo 'buffer-flush-undo))
-
-; These variables now declared in 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. Its name should end with a slash.")
-;(defvar rmail-file-name
-; (expand-file-name "~/RMAIL")
-; "")
-
-(defvar rmail-movemail-program nil
- "If non-nil, name of program for fetching new mail.")
-
-(defvar rmail-pop-password nil
- "*Password to use when reading mail from a POP server, if required.")
-
-(defvar rmail-pop-password-required nil
- "*Non-nil if a password is required when reading mail using POP.")
-
-;;;###autoload
-(defvar rmail-dont-reply-to-names nil "\
-*A regexp specifying names to prune of reply to messages.
-A value of nil means exclude your own name only.")
-
-;;;###autoload
-(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 customization file.")
-
-;;;###autoload
-(defvar rmail-ignored-headers "^via:\\|^mail-from:\\|^origin:\\|^status:\\|^received:\\|^x400-originator:\\|^x400-recipients:\\|^x400-received:\\|^x400-mts-identifier:\\|^x400-content-type:\\|^\\(resent-\\|\\)message-id:\\|^summary-line:\\|^resent-date:\\|^nntp-posting-host:\\|^path:\\|^x-char.*:\\|^x-face:\\|^x-mailer:"
- "*Regexp to match header fields that Rmail should normally hide.")
-
-;;;###autoload
-(defvar rmail-displayed-headers nil
- "*Regexp to match Header fields that Rmail should display.
-If nil, display all header fields except those matched by
-`rmail-ignored-headers'.")
-
-;;;###autoload
-(defvar rmail-retry-ignored-headers nil "\
-*Headers that should be stripped when retrying a failed message.")
-
-;;;###autoload
-(defvar rmail-highlighted-headers "^From:\\|^Subject:" "\
-*Regexp to match Header fields that Rmail should normally highlight.
-A value of nil means don't highlight.
-See also `rmail-highlight-face'.")
-
-;;;###autoload
-(defvar rmail-highlight-face nil "\
-*Face used by Rmail for highlighting headers.")
-
-;;;###autoload
-(defvar rmail-delete-after-output nil "\
-*Non-nil means automatically delete a message that is copied to a file.")
-
-;;;###autoload
-(defvar rmail-primary-inbox-list nil "\
-*List of files which are inboxes for user's primary mail file `~/RMAIL'.
-`nil' means the default, which is (\"/usr/spool/mail/$USER\")
-\(the name varies depending on the operating system,
-and the value of the environment variable MAIL overrides it).")
-
-;;;###autoload
-(defvar rmail-mail-new-frame nil
- "*Non-nil means Rmail makes a new frame for composing outgoing mail.")
-
-;;;###autoload
-(defvar rmail-secondary-file-directory "~/"
- "*Directory for additional secondary Rmail files.")
-;;;###autoload
-(defvar rmail-secondary-file-regexp "\\.xmail$"
- "*Regexp for which files are secondary Rmail files.")
-
-;;;###autoload
-(defvar rmail-mode-hook nil
- "List of functions to call when Rmail is invoked.")
-
-;;;###autoload
-(defvar rmail-get-new-mail-hook nil
- "List of functions to call when Rmail has retrieved new mail.")
-
-;;;###autoload
-(defvar rmail-show-message-hook nil
- "List of functions to call when Rmail displays a message.")
-
-;;;###autoload
-(defvar rmail-delete-message-hook nil
- "List of functions to call when Rmail deletes a message.
-When the hooks are called, the message has been marked deleted but is
-still the current message in the Rmail buffer.")
-
-;; These may be altered by site-init.el to match the format of mmdf files
-;; delimiting 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, a filter function for new messages in RMAIL.
-Called with region narrowed to the message, including headers,
-before obeying `rmail-ignored-headers'.")
-
-(defvar rmail-reply-prefix "Re: "
- "String to prepend to Subject line when replying to a message.")
-
-;; Some mailers use "Re(2):" or "Re^2:" or "Re: Re:" or "Re[2]".
-;; This pattern should catch all the common variants.
-(defvar rmail-reply-regexp "\\`\\(Re\\(([0-9]+)\\|\\[[0-9]+\\]\\|\\^[0-9]+\\)?: *\\)*"
- "Regexp to delete from Subject line before inserting `rmail-reply-prefix'.")
-
-(defvar rmail-display-summary nil
- "If non-nil, Rmail always displays the summary buffer.")
-
-(defvar rmail-mode-map nil)
-
-(defvar rmail-inbox-list nil)
-(defvar rmail-keywords 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)
-
-(defvar rmail-overlay-list nil)
-
-(defvar rmail-font-lock-keywords
- (eval-when-compile
- (let* ((cite-chars "[>|}]")
- (cite-prefix "A-Za-z")
- (cite-suffix (concat cite-prefix "0-9_.@-`'\"")))
- (list '("^\\(From\\|Sender\\):" . font-lock-function-name-face)
- '("^Reply-To:.*$" . font-lock-function-name-face)
- '("^Subject:" . font-lock-comment-face)
- '("^\\(To\\|Apparently-To\\|Cc\\):" . font-lock-keyword-face)
- ;; Use MATCH-ANCHORED to effectively anchor the regexp left side.
- `(,cite-chars
- (,(concat "\\=[ \t]*"
- "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
- cite-chars ".*")
- (beginning-of-line) (end-of-line)
- (0 font-lock-reference-face)))
- '("^\\(X-[A-Za-z0-9-]+\\|In-reply-to\\|Date\\):.*$"
- . font-lock-string-face))))
- "Additional expressions to highlight in Rmail mode.")
-
-;; 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 values specified to C-M-n, C-M-p, C-M-s or C-M-l.
-(defvar rmail-last-multi-labels nil)
-(defvar rmail-last-regexp nil)
-(defvar rmail-default-file "~/xmail"
- "*Default file name for \\[rmail-output].")
-(defvar rmail-default-rmail-file "~/XMAIL"
- "*Default file name for \\[rmail-output-to-rmail-file].")
-
-;;; Regexp matching the delimiter of messages in UNIX mail format
-;;; (UNIX From lines), minus the initial ^. Note that if you change
-;;; this expression, you must change the code in rmail-nuke-pinhead-header
-;;; that knows the exact ordering of the \\( \\) subexpressions.
-(defvar rmail-unix-mail-delimiter
- (let ((time-zone-regexp
- (concat "\\([A-Z]?[A-Z]?[A-Z][A-Z]\\( DST\\)?"
- "\\|[-+]?[0-9][0-9][0-9][0-9]"
- "\\|"
- "\\) *")))
- (concat
- "From "
-
- ;; Many things can happen to an RFC 822 mailbox before it is put into
- ;; a `From' line. The leading phrase can be stripped, e.g.
- ;; `Joe <@w.x:joe@y.z>' -> `<@w.x:joe@y.z>'. The <> can be stripped, e.g.
- ;; `<@x.y:joe@y.z>' -> `@x.y:joe@y.z'. Everything starting with a CRLF
- ;; can be removed, e.g.
- ;; From: joe@y.z (Joe K
- ;; User)
- ;; can yield `From joe@y.z (Joe K Fri Mar 22 08:11:15 1996', and
- ;; From: Joe User
- ;; <joe@y.z>
- ;; can yield `From Joe User Fri Mar 22 08:11:15 1996'.
- ;; The mailbox can be removed or be replaced by white space, e.g.
- ;; From: "Joe User"{space}{tab}
- ;; <joe@y.z>
- ;; can yield `From {space}{tab} Fri Mar 22 08:11:15 1996',
- ;; where {space} and {tab} represent the Ascii space and tab characters.
- ;; We want to match the results of any of these manglings.
- ;; The following regexp rejects names whose first characters are
- ;; obviously bogus, but after that anything goes.
- "\\([^\0-\b\n-\r\^?].*\\)? "
-
- ;; The time the message was sent.
- "\\([^\0-\r \^?]+\\) +" ; day of the week
- "\\([^\0-\r \^?]+\\) +" ; month
- "\\([0-3]?[0-9]\\) +" ; day of month
- "\\([0-2][0-9]:[0-5][0-9]\\(:[0-6][0-9]\\)?\\) *" ; time of day
-
- ;; Perhaps a time zone, specified by an abbreviation, or by a
- ;; numeric offset.
- time-zone-regexp
-
- ;; The year.
- " \\([0-9][0-9]+\\) *"
-
- ;; On some systems the time zone can appear after the year, too.
- time-zone-regexp
-
- ;; Old uucp cruft.
- "\\(remote from .*\\)?"
-
- "\n"))
- nil)
-
-;; Perform BODY in the summary buffer
-;; in such a way that its cursor is properly updated in its own window.
-(defmacro rmail-select-summary (&rest body)
- (` (let ((total rmail-total-messages))
- (if (rmail-summary-displayed)
- (let ((window (selected-window)))
- (save-excursion
- (unwind-protect
- (progn
- (pop-to-buffer rmail-summary-buffer)
- ;; rmail-total-messages is a buffer-local var
- ;; in the rmail buffer.
- ;; This way we make it available for the body
- ;; even tho the rmail buffer is not current.
- (let ((rmail-total-messages total))
- (,@ body)))
- (select-window window))))
- (save-excursion
- (set-buffer rmail-summary-buffer)
- (let ((rmail-total-messages total))
- (,@ body))))
- (rmail-maybe-display-summary))))
-
-;;;; *** Rmail Mode ***
-
-;;;###autoload
-(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 file name as argument; then performs rmail editing on
-that file, but does not copy any new mail into the file.
-Interactively, if you supply a prefix argument, then you
-have a chance to specify a file name with the minibuffer.
-
-If `rmail-display-summary' is non-nil, make a summary for this RMAIL file."
- (interactive (if current-prefix-arg
- (list (read-file-name "Run rmail on RMAIL file: "))))
- (let* ((file-name (expand-file-name (or file-name-arg rmail-file-name)))
- (existed (get-file-buffer file-name))
- run-mail-hook)
- ;; 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
- ;; Don't be confused by apparent local-variables spec
- ;; in the last message in the RMAIL file.
- (let ((enable-local-variables nil))
- (find-file file-name))
- (if (and (verify-visited-file-modtime existed)
- (eq major-mode 'rmail-mode))
- (progn (rmail-forget-messages)
- (rmail-set-message-counters))))
- (let ((enable-local-variables nil))
- (find-file file-name)))
- (if (eq major-mode 'rmail-edit-mode)
- (error "Exit Rmail Edit mode before getting new mail."))
- (if (and existed (> (buffer-size) 0))
- ;; Buffer not new and not empty; ensure in proper mode, but that's all.
- (or (eq major-mode 'rmail-mode)
- (progn (rmail-mode-2)
- (setq run-mail-hook t)))
- (setq run-mail-hook t)
- (rmail-mode-2)
- ;; 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))))
- (or (and (null file-name-arg)
- (rmail-get-new-mail))
- (rmail-show-message (rmail-first-unseen-message)))
- (if rmail-display-summary (rmail-summary))
- (rmail-construct-io-menu)
- (if run-mail-hook
- (run-hooks 'rmail-mode-hook))))
-
-;; Given the value of MAILPATH, return a list of inbox file names.
-;; This is turned off because it is not clear that the user wants
-;; all these inboxes to feed into the primary rmail file.
-; (defun rmail-convert-mailpath (string)
-; (let (idx list)
-; (while (setq idx (string-match "[%:]" string))
-; (let ((this (substring string 0 idx)))
-; (setq string (substring string (1+ idx)))
-; (setq list (cons (if (string-match "%" this)
-; (substring this 0 (string-match "%" this))
-; this)
-; list))))
-; list))
-
-; I have checked that adding "-*- rmail -*-" to the BABYL OPTIONS line
-; will not cause emacs 18.55 problems.
-
-(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: -*- rmail -*-\n")))
- ((equal (point-min) (point-max))
- ;; Empty RMAIL file. Just insert the header.
- (rmail-insert-rmail-file-header))
- (t
- ;; Non-empty file in non-RMAIL format. Add header and convert.
- (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
- (save-excursion
- (goto-char (point-max))
- (search-backward "\n\^_")
- (forward-char 2)
- (looking-at "\n*From ")))
- (let ((buffer-read-only nil))
- (message "Converting to Babyl format...")
- ;; If file needs conversion, convert it all,
- ;; except for the BABYL header.
- ;; (rmail-convert-to-babyl-format would delete the header.)
- (goto-char (point-min))
- (search-forward "\n\^_" nil t)
- (narrow-to-region (point) (point-max))
- (rmail-convert-to-babyl-format)
- (message "Converting to Babyl format...done")))))
-
-;;; I have checked that adding "-*- rmail -*-" to the BABYL OPTIONS line
-;;; will not cause emacs 18.55 problems.
-
-(defun rmail-insert-rmail-file-header ()
- (let ((buffer-read-only nil))
- (insert "BABYL OPTIONS: -*- rmail -*-
-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 "a" 'rmail-add-label)
- (define-key rmail-mode-map "b" 'rmail-bury)
- (define-key rmail-mode-map "c" 'rmail-continue)
- (define-key rmail-mode-map "d" 'rmail-delete-forward)
- (define-key rmail-mode-map "\C-d" 'rmail-delete-backward)
- (define-key rmail-mode-map "e" 'rmail-edit-current-message)
- (define-key rmail-mode-map "f" 'rmail-forward)
- (define-key rmail-mode-map "g" 'rmail-get-new-mail)
- (define-key rmail-mode-map "h" 'rmail-summary)
- (define-key rmail-mode-map "i" 'rmail-input)
- (define-key rmail-mode-map "j" 'rmail-show-message)
- (define-key rmail-mode-map "k" 'rmail-kill-label)
- (define-key rmail-mode-map "l" 'rmail-summary-by-labels)
- (define-key rmail-mode-map "\e\C-h" 'rmail-summary)
- (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 "\e\C-s" 'rmail-summary-by-regexp)
- (define-key rmail-mode-map "\e\C-t" 'rmail-summary-by-topic)
- (define-key rmail-mode-map "m" 'rmail-mail)
- (define-key rmail-mode-map "\em" 'rmail-retry-failure)
- (define-key rmail-mode-map "n" 'rmail-next-undeleted-message)
- (define-key rmail-mode-map "\en" 'rmail-next-message)
- (define-key rmail-mode-map "\e\C-n" 'rmail-next-labeled-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 "p" 'rmail-previous-undeleted-message)
- (define-key rmail-mode-map "\ep" 'rmail-previous-message)
- (define-key rmail-mode-map "\e\C-p" 'rmail-previous-labeled-message)
- (define-key rmail-mode-map "q" 'rmail-quit)
- (define-key rmail-mode-map "r" 'rmail-reply)
-;; I find I can't live without the default M-r command -- rms.
-;; (define-key rmail-mode-map "\er" 'rmail-search-backwards)
- (define-key rmail-mode-map "s" 'rmail-expunge-and-save)
- (define-key rmail-mode-map "\es" 'rmail-search)
- (define-key rmail-mode-map "t" 'rmail-toggle-header)
- (define-key rmail-mode-map "u" 'rmail-undelete-previous-message)
- (define-key rmail-mode-map "w" 'rmail-edit-current-message)
- (define-key rmail-mode-map "x" 'rmail-expunge)
- (define-key rmail-mode-map "." 'rmail-beginning-of-message)
- (define-key rmail-mode-map "<" 'rmail-first-message)
- (define-key rmail-mode-map ">" 'rmail-last-message)
- (define-key rmail-mode-map " " 'scroll-up)
- (define-key rmail-mode-map "\177" 'scroll-down)
- (define-key rmail-mode-map "?" 'describe-mode)
- (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-lines)
- (define-key rmail-mode-map "\C-c\C-s\C-k" 'rmail-sort-by-keywords)
- (define-key rmail-mode-map "\C-c\C-n" 'rmail-next-same-subject)
- (define-key rmail-mode-map "\C-c\C-p" 'rmail-previous-same-subject)
- )
-
-(define-key rmail-mode-map [menu-bar] (make-sparse-keymap))
-
-(define-key rmail-mode-map [menu-bar classify]
- (cons "Classify" (make-sparse-keymap "Classify")))
-
-(define-key rmail-mode-map [menu-bar classify input-menu]
- nil)
-
-(define-key rmail-mode-map [menu-bar classify output-menu]
- nil)
-
-(define-key rmail-mode-map [menu-bar classify output-inbox]
- '("Output (inbox)..." . rmail-output))
-
-(define-key rmail-mode-map [menu-bar classify output]
- '("Output (Rmail)..." . rmail-output-to-rmail-file))
-
-(define-key rmail-mode-map [menu-bar classify kill-label]
- '("Kill Label..." . rmail-kill-label))
-
-(define-key rmail-mode-map [menu-bar classify add-label]
- '("Add Label..." . rmail-add-label))
-
-(define-key rmail-mode-map [menu-bar summary]
- (cons "Summary" (make-sparse-keymap "Summary")))
-
-(define-key rmail-mode-map [menu-bar summary senders]
- '("By Senders..." . rmail-summary-by-senders))
-
-(define-key rmail-mode-map [menu-bar summary labels]
- '("By Labels..." . rmail-summary-by-labels))
-
-(define-key rmail-mode-map [menu-bar summary recipients]
- '("By Recipients..." . rmail-summary-by-recipients))
-
-(define-key rmail-mode-map [menu-bar summary topic]
- '("By Topic..." . rmail-summary-by-topic))
-
-(define-key rmail-mode-map [menu-bar summary regexp]
- '("By Regexp..." . rmail-summary-by-regexp))
-
-(define-key rmail-mode-map [menu-bar summary all]
- '("All" . rmail-summary))
-
-(define-key rmail-mode-map [menu-bar mail]
- (cons "Mail" (make-sparse-keymap "Mail")))
-
-(define-key rmail-mode-map [menu-bar mail rmail-get-new-mail]
- '("Get New Mail" . rmail-get-new-mail))
-
-(define-key rmail-mode-map [menu-bar mail lambda]
- '("----"))
-
-(define-key rmail-mode-map [menu-bar mail continue]
- '("Continue" . rmail-continue))
-
-(define-key rmail-mode-map [menu-bar mail resend]
- '("Re-send..." . rmail-resend))
-
-(define-key rmail-mode-map [menu-bar mail forward]
- '("Forward" . rmail-forward))
-
-(define-key rmail-mode-map [menu-bar mail retry]
- '("Retry" . rmail-retry-failure))
-
-(define-key rmail-mode-map [menu-bar mail reply]
- '("Reply" . rmail-reply))
-
-(define-key rmail-mode-map [menu-bar mail mail]
- '("Mail" . rmail-mail))
-
-(define-key rmail-mode-map [menu-bar delete]
- (cons "Delete" (make-sparse-keymap "Delete")))
-
-(define-key rmail-mode-map [menu-bar delete expunge/save]
- '("Expunge/Save" . rmail-expunge-and-save))
-
-(define-key rmail-mode-map [menu-bar delete expunge]
- '("Expunge" . rmail-expunge))
-
-(define-key rmail-mode-map [menu-bar delete undelete]
- '("Undelete" . rmail-undelete-previous-message))
-
-(define-key rmail-mode-map [menu-bar delete delete]
- '("Delete" . rmail-delete-forward))
-
-(define-key rmail-mode-map [menu-bar move]
- (cons "Move" (make-sparse-keymap "Move")))
-
-(define-key rmail-mode-map [menu-bar move search-back]
- '("Search Back..." . rmail-search-backwards))
-
-(define-key rmail-mode-map [menu-bar move search]
- '("Search..." . rmail-search))
-
-(define-key rmail-mode-map [menu-bar move previous]
- '("Previous Nondeleted" . rmail-previous-undeleted-message))
-
-(define-key rmail-mode-map [menu-bar move next]
- '("Next Nondeleted" . rmail-next-undeleted-message))
-
-(define-key rmail-mode-map [menu-bar move last]
- '("Last" . rmail-last-message))
-
-(define-key rmail-mode-map [menu-bar move first]
- '("First" . rmail-first-message))
-
-(define-key rmail-mode-map [menu-bar move previous]
- '("Previous" . rmail-previous-message))
-
-(define-key rmail-mode-map [menu-bar move next]
- '("Next" . rmail-next-message))
-
-;; Rmail mode is suitable only for specially formatted data.
-(put 'rmail-mode 'mode-class 'special)
-
-(defun rmail-mode-kill-summary ()
- (if rmail-summary-buffer (kill-buffer rmail-summary-buffer)))
-
-;;;###autoload
-(defun rmail-mode ()
- "Rmail Mode is used by \\<rmail-mode-map>\\[rmail] for editing Rmail files.
-All normal editing commands are turned off.
-Instead, these commands are available:
-
-\\[rmail-beginning-of-message] Move point to front of this message (same as \\[beginning-of-buffer]).
-\\[scroll-up] Scroll to next screen of this message.
-\\[scroll-down] Scroll to previous screen of this message.
-\\[rmail-next-undeleted-message] Move to Next non-deleted message.
-\\[rmail-previous-undeleted-message] Move to Previous non-deleted message.
-\\[rmail-next-message] Move to Next message whether deleted or not.
-\\[rmail-previous-message] Move to Previous message whether deleted or not.
-\\[rmail-first-message] Move to the first message in Rmail file.
-\\[rmail-last-message] Move to the last message in Rmail file.
-\\[rmail-show-message] Jump to message specified by numeric position in file.
-\\[rmail-search] Search for string and show message it is found in.
-\\[rmail-delete-forward] Delete this message, move to next nondeleted.
-\\[rmail-delete-backward] Delete this message, move to previous nondeleted.
-\\[rmail-undelete-previous-message] Undelete message. Tries current message, then earlier messages
- till a deleted message is found.
-\\[rmail-edit-current-message] Edit the current message. \\[rmail-cease-edit] to return to Rmail.
-\\[rmail-expunge] Expunge deleted messages.
-\\[rmail-expunge-and-save] Expunge and save the file.
-\\[rmail-quit] Quit Rmail: expunge, save, then switch to another buffer.
-\\[save-buffer] Save without expunging.
-\\[rmail-get-new-mail] Move new mail from system spool directory into this file.
-\\[rmail-mail] Mail a message (same as \\[mail-other-window]).
-\\[rmail-continue] Continue composing outgoing message started before.
-\\[rmail-reply] Reply to this message. Like \\[rmail-mail] but initializes some fields.
-\\[rmail-retry-failure] Send this message again. Used on a mailer failure message.
-\\[rmail-forward] Forward this message to another user.
-\\[rmail-output-to-rmail-file] Output this message to an Rmail file (append it).
-\\[rmail-output] Output this message to a Unix-format mail file (append it).
-\\[rmail-input] Input Rmail file. Run Rmail on that file.
-\\[rmail-add-label] Add label to message. It will be displayed in the mode line.
-\\[rmail-kill-label] Kill label. Remove a label from current message.
-\\[rmail-next-labeled-message] 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 \\[rmail-add-label].
-\\[rmail-previous-labeled-message] Move to Previous message with specified label
-\\[rmail-summary] Show headers buffer, with a one line summary of each message.
-\\[rmail-summary-by-labels] Summarize only messages with particular label(s).
-\\[rmail-summary-by-recipients] Summarize only messages with particular recipient(s).
-\\[rmail-summary-by-regexp] Summarize only messages with particular regexp(s).
-\\[rmail-summary-by-topic] Summarize only messages with subject line regexp(s).
-\\[rmail-toggle-header] Toggle display of complete header."
- (interactive)
- (rmail-mode-2)
- (rmail-set-message-counters)
- (rmail-show-message rmail-total-messages)
- (run-hooks 'rmail-mode-hook))
-
-(defun rmail-mode-2 ()
- (kill-all-local-variables)
- (rmail-mode-1)
- (rmail-variables))
-
-(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 in normal circumstances
- ;; because they contain no info except attribute changes
- ;; and deletion of messages.
- ;; The one exception is when messages are copied into an Rmail mode buffer.
- ;; rmail-output-to-rmail-file enables auto save when you do that.
- (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 'font-lock-defaults)
- (setq font-lock-defaults
- '(rmail-font-lock-keywords t nil nil nil
- (font-lock-maximum-size . nil)
- (font-lock-fontify-buffer-function . rmail-fontify-buffer-function)
- (font-lock-unfontify-buffer-function . rmail-unfontify-buffer-function)
- (font-lock-inhibit-thing-lock . (lazy-lock-mode fast-lock-mode))))
- (make-local-variable 'rmail-last-label)
- (make-local-variable 'rmail-last-regexp)
- (make-local-variable 'rmail-deleted-vector)
- (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 'rmail-overlay-list)
- (setq rmail-overlay-list nil)
- (make-local-variable 'version-control)
- (setq version-control 'never)
- (make-local-variable 'kill-buffer-hook)
- (add-hook 'kill-buffer-hook 'rmail-mode-kill-summary)
- (make-local-variable 'file-precious-flag)
- (setq file-precious-flag t)
- (make-local-variable 'rmail-message-vector)
- (make-local-variable 'rmail-inbox-list)
- (setq rmail-inbox-list (rmail-parse-file-inboxes))
- ;; Provide default set of inboxes for primary mail file ~/RMAIL.
- (and (null rmail-inbox-list)
- (or (equal buffer-file-name (expand-file-name rmail-file-name))
- (equal buffer-file-truename
- (abbreviate-file-name (file-truename rmail-file-name))))
- (setq rmail-inbox-list
- (or rmail-primary-inbox-list
- (list (or (getenv "MAIL")
- (concat rmail-spool-directory
- (user-login-name)))))))
- (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 (default-value '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-mode)))))
-
-;; 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 "\n\^_" 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)
- (if (rmail-summary-exists)
- (rmail-select-summary (set-buffer-modified-p nil))))
-
-(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
- (progn
- (replace-buffer-in-windows rmail-summary-buffer)
- (bury-buffer rmail-summary-buffer)))
- (let ((obuf (current-buffer)))
- (replace-buffer-in-windows obuf)
- (bury-buffer obuf)))
-
-(defun rmail-bury ()
- "Bury current Rmail buffer and its summary buffer."
- (interactive)
- ;; This let var was called rmail-buffer, but that interfered
- ;; with the buffer-local var used in summary buffers.
- (let ((buffer-to-bury (current-buffer)))
- (if (rmail-summary-exists)
- (let (window)
- (while (setq window (get-buffer-window rmail-summary-buffer))
- (set-window-buffer window (other-buffer rmail-summary-buffer)))
- (bury-buffer rmail-summary-buffer)))
- (switch-to-buffer (other-buffer (current-buffer)))
- (bury-buffer buffer-to-bury)))
-
-(defun rmail-duplicate-message ()
- "Create a duplicated copy of the current message.
-The duplicate copy goes into the Rmail file just after the
-original copy."
- (interactive)
- (widen)
- (let ((buffer-read-only nil)
- (number rmail-current-message)
- (string (buffer-substring (rmail-msgbeg rmail-current-message)
- (rmail-msgend rmail-current-message))))
- (goto-char (rmail-msgend rmail-current-message))
- (insert string)
- (rmail-forget-messages)
- (rmail-show-message number)
- (message "Message duplicated")))
-
-;;;###autoload
-(defun rmail-input (filename)
- "Run Rmail on file FILENAME."
- (interactive "FRun rmail on RMAIL file: ")
- (rmail filename))
-
-
-;; This used to scan subdirectories recursively, but someone pointed out
-;; that if the user wants that, person can put all the files in one dir.
-;; And the recursive scan was slow. So I took it out.
-;; rms, Sep 1996.
-(defun rmail-find-all-files (start)
- "Return list of file in dir START that match `rmail-secondary-file-regexp'."
- (if (file-accessible-directory-p start)
- ;; Don't sort here.
- (let* ((case-fold-search t)
- (files (directory-files start t rmail-secondary-file-regexp)))
- ;; Sort here instead of in directory-files
- ;; because this list is usually much shorter.
- (sort files 'string<))))
-
-(defun rmail-list-to-menu (menu-name l action &optional full-name)
- (let ((menu (make-sparse-keymap menu-name)))
- (mapcar
- (function (lambda (item)
- (let (command)
- (if (consp item)
- (progn
- (setq command
- (rmail-list-to-menu (car item) (cdr item)
- action
- (if full-name
- (concat full-name "/"
- (car item))
- (car item))))
- (setq name (car item)))
- (progn
- (setq name item)
- (setq command
- (list 'lambda () '(interactive)
- (list action
- (expand-file-name
- (if full-name
- (concat full-name "/" item)
- item)
- rmail-secondary-file-directory))))))
- (define-key menu (vector (intern name))
- (cons name command)))))
- (reverse l))
- menu))
-
-;; This command is always "disabled" when it appears in a menu.
-(put 'rmail-disable-menu 'menu-enable ''nil)
-
-(defun rmail-construct-io-menu ()
- (let ((files (rmail-find-all-files rmail-secondary-file-directory)))
- (if files
- (progn
- (define-key rmail-mode-map [menu-bar classify input-menu]
- (cons "Input Rmail File"
- (rmail-list-to-menu "Input Rmail File"
- files
- 'rmail-input)))
- (define-key rmail-mode-map [menu-bar classify output-menu]
- (cons "Output Rmail File"
- (rmail-list-to-menu "Output Rmail File"
- files
- 'rmail-output-to-rmail-file))))
-
- (define-key rmail-mode-map [menu-bar classify input-menu]
- '("Input Rmail File" . rmail-disable-menu))
- (define-key rmail-mode-map [menu-bar classify output-menu]
- '("Output Rmail File" . rmail-disable-menu)))))
-
-
-;;;; *** 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. By default, this is
-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.
-
-This function runs `rmail-get-new-mail-hook' before saving the updated file.
-It returns t if it got any new messages."
- (interactive
- (list (if current-prefix-arg
- (read-file-name "Get new mail from file: "))))
- (run-hooks 'rmail-before-get-new-mail-hook)
- ;; If the disk file has been changed from under us,
- ;; revert to it before we get new mail.
- (or (verify-visited-file-modtime (current-buffer))
- (find-file (buffer-file-name)))
- (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))
- (let ((all-files (if file-name (list file-name)
- rmail-inbox-list)))
- (unwind-protect
- (while all-files
- (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)
- success
- ;; Files to insert this time around.
- files
- ;; Last names of those files.
- file-last-names)
- ;; Pull files off all-files onto files
- ;; as long as there is no name conflict.
- ;; A conflict happens when two inbox file names
- ;; have the same last component.
- (while (and all-files
- (not (member (file-name-nondirectory (car all-files))
- file-last-names)))
- (setq files (cons (car all-files) files)
- file-last-names
- (cons (file-name-nondirectory (car all-files)) files))
- (setq all-files (cdr all-files)))
- ;; Put them back in their original order.
- (setq files (nreverse files))
-
- (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 files nil)
- (setq delete-files (rmail-insert-inbox-text files t)))
- ;; Scan the new text and convert each message to babyl format.
- (goto-char (point-min))
- (unwind-protect
- (save-excursion
- (setq new-messages (rmail-convert-to-babyl-format)
- success t))
- ;; If we could not convert the file's inboxes,
- ;; rename the files we tried to read
- ;; so we won't over and over again.
- (if (and (not file-name) (not success))
- (let ((delfiles delete-files)
- (count 0))
- (while delfiles
- (while (file-exists-p (format "RMAILOSE.%d" count))
- (setq count (1+ count)))
- (rename-file (car delfiles)
- (format "RMAILOSE.%d" count))
- (setq delfiles (cdr delfiles))))))
- (or (zerop new-messages)
- (let (success)
- (widen)
- (search-backward "\n\^_" nil t)
- (narrow-to-region (point) (point-max))
- (goto-char (1+ (point-min)))
- (rmail-count-new-messages)
- (run-hooks 'rmail-get-new-mail-hook)
- (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)"))
- nil)
- (if (rmail-summary-exists)
- (rmail-select-summary
- (rmail-update-summary)))
- (message "%d new message%s read"
- new-messages (if (= 1 new-messages) "" "s"))
- ;; Move to the first new message
- ;; unless we have other unseen messages before it.
- (rmail-show-message (rmail-first-unseen-message))
- (run-hooks 'rmail-after-get-new-mail-hook)
- t)))
- ;; Don't leave the buffer screwed up if we get a disk-full error.
- (rmail-show-message))))
-
-(defun rmail-insert-inbox-text (files renamep)
- ;; Detect a locked file now, so that we avoid moving mail
- ;; out of the real inbox file. (That could scare people.)
- (or (memq (file-locked-p buffer-file-name) '(nil t))
- (error "RMAIL file %s is locked"
- (file-name-nondirectory buffer-file-name)))
- (let (file tofile delete-files movemail popmail)
- (while files
- (setq file (file-truename
- (expand-file-name (substitute-in-file-name (car files))))
- tofile (expand-file-name
- ;; Generate name to move to from inbox name,
- ;; in case of multiple inboxes that need moving.
- (concat ".newmail-" (file-name-nondirectory file))
- ;; 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))))
- ;; Always use movemail to rename the file,
- ;; since there can be mailboxes in various directories.
- (setq movemail t)
-;;; ;; If getting from mail spool directory,
-;;; ;; use movemail to move rather than just renaming,
-;;; ;; so as to interlock with the mailer.
-;;; (setq movemail (string= file
-;;; (file-truename
-;;; (concat rmail-spool-directory
-;;; (file-name-nondirectory file)))))
- (setq popmail (string-match "^po:" (file-name-nondirectory file)))
- (if popmail (setq file (file-name-nondirectory file)
- renamep t))
- (if movemail
- (progn
- ;; 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 (user-login-name)
- file)))))
- (cond (popmail
- (if (and rmail-pop-password-required (not rmail-pop-password))
- (setq rmail-pop-password
- (rmail-read-passwd
- (format "Password for %s: "
- (substring file (+ popmail 3))))))
- (if (eq system-type 'windows-nt)
- ;; cannot have "po:" in file name
- (setq tofile
- (expand-file-name
- (concat ".newmail-pop-" (substring file (+ popmail 3)))
- (file-name-directory
- (expand-file-name buffer-file-name)))))
- (message "Getting mail from post office ..."))
- ((and (file-exists-p tofile)
- (/= 0 (nth 7 (file-attributes tofile))))
- (message "Getting mail from %s..." tofile))
- ((and (file-exists-p file)
- (/= 0 (nth 7 (file-attributes 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))
- ;; Try copying. If that fails (perhaps no space),
- ;; rename instead.
- (condition-case nil
- (copy-file file tofile nil)
- (error
- ;; Third arg is t so we can replace existing file TOFILE.
- (rename-file file tofile t)))
- ;; 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-disable-undo errors)
- (if rmail-pop-password
- (call-process
- (or rmail-movemail-program
- (expand-file-name "movemail" exec-directory))
- nil errors nil file tofile rmail-pop-password)
- (call-process
- (or rmail-movemail-program
- (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 "movemail: %s"
- (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 (size)
- (goto-char (point-max))
- (setq size (nth 1 (insert-file-contents tofile)))
- (goto-char (point-max))
- (or (= (preceding-char) ?\n)
- (zerop size)
- (insert ?\n))
- (setq delete-files (cons tofile delete-files))))
- (message "")
- (setq files (cdr files)))
- delete-files))
-
-(defun rmail-read-passwd (prompt &optional default)
- "Read a password, echoing `.' for each character typed.
-End with RET, LFD, or ESC. DEL or C-h rubs out. C-u kills line.
-Optional DEFAULT is password to start with."
- (let ((pass (if default default ""))
- (c 0)
- (echo-keystrokes 0)
- (cursor-in-echo-area t))
- (while (progn (message "%s%s"
- prompt
- (make-string (length pass) ?.))
- (setq c (read-char))
- (and (/= c ?\r) (/= c ?\n) (/= c ?\e)))
- (if (= c ?\C-u)
- (setq pass "")
- (if (and (/= c ?\b) (/= c ?\177))
- (setq pass (concat pass (char-to-string c)))
- (if (> (length pass) 0)
- (setq pass (substring pass 0 -1))))))
- (message "")
- (message nil)
- pass))
-
-;; the rmail-break-forwarded-messages feature is not implemented
-(defun rmail-convert-to-babyl-format ()
- (let ((count 0) start
- (case-fold-search nil)
- (invalid-input-resync
- (function (lambda ()
- (message "Invalid Babyl format in inbox!")
- (sit-for 3)
- ;; Try to get back in sync with a real message.
- (if (re-search-forward
- (concat mmdf-delim1 "\\|^From") nil t)
- (beginning-of-line)
- (goto-char (point-max)))))))
- (goto-char (point-min))
- (save-restriction
- (while (not (eobp))
- (cond ((looking-at "BABYL OPTIONS:");Babyl header
- (if (search-forward "\n\^_" nil t)
- ;; If we find the proper terminator, delete through there.
- (delete-region (point-min) (point))
- (funcall invalid-input-resync)
- (delete-region (point-min) (point))))
- ;; Babyl format message
- ((looking-at "\^L")
- (or (search-forward "\n\^_" nil t)
- (funcall invalid-input-resync))
- (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)
- (1- (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))))
- (string-to-int (buffer-substring beg eol)))))))
- (and size
- (if (and (natnump size)
- (<= (+ header-end size) (point-max))
- ;; Make sure this would put us at a position
- ;; that we could continue from.
- (save-excursion
- (goto-char (+ header-end size))
- (skip-chars-forward "\n")
- (or (eobp)
- (and (looking-at "BABYL OPTIONS:")
- (search-forward "\n\^_" nil t))
- (and (looking-at "\^L")
- (search-forward "\n\^_" nil t))
- (let ((case-fold-search t))
- (looking-at mmdf-delim1))
- (looking-at "From "))))
- (goto-char (+ header-end size))
- (message "Ignoring invalid Content-Length field")
- (sit-for 1 0 t))))
-
- (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 kludge is because some versions of sendmail.el
- ;; insert an extra newline at the beginning that shouldn't
- ;; be there. sendmail.el has been fixed, but old versions
- ;; may still be in use. -- rms, 7 May 1993.
- ((eolp) (delete-char 1))
- (t (error "Cannot convert to babyl format")))))
- count))
-
-;; Delete the "From ..." line, creating various other headers with
-;; information from it if they don't already exist. Now puts the
-;; original line into a mail-from: header line for debugging and for
-;; use by the rmail-output function.
-(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
- "Mail-from: \\&"
- ;; Keep and reformat the date if we don't
- ;; have a Date: field.
- (if has-date
- ""
- (concat
- "Date: \\2, \\4 \\3 \\9 \\5 "
-
- ;; The timezone could be matched by group 7 or group 10.
- ;; If neither of them matched, assume EST, since only
- ;; Easterners would be so sloppy.
- ;; It's a shame the substitution can't use "\\10".
- (cond
- ((/= (match-beginning 7) (match-end 7)) "\\7")
- ((/= (match-beginning 10) (match-end 10))
- (buffer-substring (match-beginning 10)
- (match-end 10)))
- (t "EST"))
- "\n"))
- ;; Keep and reformat the sender if we don't
- ;; have a From: field.
- (if has-from
- ""
- "From: \\1\n"))
- t)))))))
-
-;;;; *** 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)
- (let ((case-fold-search t))
- (while (looking-at "Summary-line:\\|Mail-From:")
- (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-message-filter (funcall rmail-message-filter))
- (if (or rmail-displayed-headers rmail-ignored-headers)
- (rmail-clear-headers))))
-
-(defun rmail-clear-headers (&optional ignored-headers)
- "Delete all header fields that Rmail should not show.
-If the optional argument IGNORED-HEADERS is non-nil,
-delete all header fields whose names match that regexp.
-Otherwise, if `rmail-displayed-headers' is non-nil,
-delete all header fields *except* those whose names match that regexp.
-Otherwise, delete all header fields whose names match `rmail-ignored-headers'."
- (if (search-forward "\n\n" nil t)
- (let ((case-fold-search t)
- (buffer-read-only nil))
- (if (and rmail-displayed-headers (null ignored-headers))
- (save-restriction
- (narrow-to-region (point-min) (point))
- (let (lim)
- (goto-char (point-min))
- (while (save-excursion
- (re-search-forward "\n[^ \t]")
- (and (not (eobp))
- (setq lim (1- (point)))))
- (if (save-excursion
- (re-search-forward rmail-displayed-headers lim t))
- (goto-char lim)
- (delete-region (point) lim))))
- (goto-char (point-min)))
- (or ignored-headers (setq ignored-headers rmail-ignored-headers))
- (save-restriction
- (narrow-to-region (point-min) (point))
- (while (progn
- (goto-char (point-min))
- (re-search-forward ignored-headers nil t))
- (beginning-of-line)
- (delete-region (point)
- (progn (re-search-forward "\n[^ \t]")
- (1- (point))))))))))
-
-(defun rmail-msg-is-pruned ()
- (rmail-maybe-set-message-counters)
- (save-restriction
- (save-excursion
- (narrow-to-region (rmail-msgbeg rmail-current-message) (point-max))
- (goto-char (point-min))
- (forward-line 1)
- (= (following-char) ?1))))
-
-(defun rmail-toggle-header (&optional arg)
- "Show original message header if pruned header currently shown, or vice versa.
-With argument ARG, show the message header pruned if ARG is greater than zero;
-otherwise, show it in full."
- (interactive "P")
- (let* ((buffer-read-only nil)
- (pruned (rmail-msg-is-pruned))
- (prune (if arg
- (> (prefix-numeric-value arg) 0)
- (not pruned))))
- (if (eq pruned prune)
- t
- (rmail-maybe-set-message-counters)
- (narrow-to-region (rmail-msgbeg rmail-current-message) (point-max))
- (if pruned
- (progn (goto-char (point-min))
- (forward-line 1)
- (delete-char 1)
- (insert ?0)
- (forward-line 1)
- (let ((case-fold-search t))
- (while (looking-at "Summary-Line:\\|Mail-From:")
- (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-highlight-headers))))
-
-;;;; *** 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)))))))))))
- ;; Note: we don't use save-restriction because that does not work right
- ;; if changes are made outside the saved restriction
- ;; before that restriction is restored.
- (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
- (format " %d/%d%s"
- rmail-current-message rmail-total-messages blurb))))
-
-;; Turn an attribute of a message on or off according to STATE.
-;; ATTR is the name of the attribute, as a string.
-;; MSGNUM is message number to change; nil means current message.
-(defun rmail-set-attribute (attr state &optional msgnum)
- (let ((omax (point-max-marker))
- (omin (point-min-marker))
- (buffer-read-only nil))
- (or msgnum (setq msgnum rmail-current-message))
- (if (> msgnum 0)
- (unwind-protect
- (save-excursion
- (widen)
- (goto-char (+ 3 (rmail-msgbeg msgnum)))
- (let ((curstate
- (not
- (null (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 msgnum state)))
- ;; Note: we don't use save-restriction because that does not work right
- ;; if changes are made outside the saved restriction
- ;; before that restriction is restored.
- (narrow-to-region omin omax)
- (set-marker omin nil)
- (set-marker omax nil)
- (if (= msgnum rmail-current-message)
- (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)
- (save-excursion
- (save-restriction
- (widen)
- (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.
-
-FUNCTION may not change the visible text of the message, but it may
-change the invisible header text."
- (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))
- ;; Note: we don't use save-restriction because that does not work right
- ;; if changes are made outside the saved restriction
- ;; before that restriction is restored.
- ;; Here we assume that changes made by FUNCTION
- ;; occur before the visible region of the message.
- (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 "\n\^_")
- (forward-char 1)
- (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 "\n\^_" nil t)
- (if (/= (point) (point-max)) (forward-char 1))
- (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 "\n\^_\^L\n" stop t)
- (forward-char 1)
- (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 no-summary)
- "Show message number N (prefix argument), counting from start of file.
-If summary buffer is currently displayed, update current message there also."
- (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)))
- (goto-char beg)
- (forward-line 1)
- ;; Clear the "unseen" attribute when we show a message.
- (rmail-set-attribute "unseen" nil)
- ;; Reformat the header, or else find the reformatted header.
- (let ((end (rmail-msgend n)))
- (if (= (following-char) ?0)
- (rmail-reformat-message beg end)
- (search-forward "\n*** EOOH ***\n" end t)
- (narrow-to-region (point) end)))
- (goto-char (point-min))
- (rmail-display-labels)
- (rmail-highlight-headers)
- (if transient-mark-mode (deactivate-mark))
- (run-hooks 'rmail-show-message-hook)
- ;; If there is a summary buffer, try to move to this message
- ;; in that buffer. But don't complain if this message
- ;; is not mentioned in the summary.
- ;; Don't do this at all if we were called on behalf
- ;; of cursor motion in the summary buffer.
- (and (rmail-summary-exists) (not no-summary)
- (let ((curr-msg rmail-current-message))
- (rmail-select-summary
- (rmail-summary-goto-msg curr-msg t t))))
- (if blurb
- (message blurb))))))
-
-;; Find all occurrences of certain fields, and highlight them.
-(defun rmail-highlight-headers ()
- ;; Do this only if the system supports faces.
- (if (and (fboundp 'internal-find-face)
- rmail-highlighted-headers)
- (save-excursion
- (search-forward "\n\n" nil 'move)
- (save-restriction
- (narrow-to-region (point-min) (point))
- (let ((case-fold-search t)
- (inhibit-read-only t)
- ;; Highlight with boldface if that is available.
- ;; Otherwise use the `highlight' face.
- (face (or rmail-highlight-face
- (if (face-differs-from-default-p 'bold)
- 'bold 'highlight)))
- ;; List of overlays to reuse.
- (overlays rmail-overlay-list))
- (goto-char (point-min))
- (while (re-search-forward rmail-highlighted-headers nil t)
- (skip-chars-forward " \t")
- (let ((beg (point))
- overlay)
- (while (progn (forward-line 1)
- (looking-at "[ \t]")))
- ;; Back up over newline, then trailing spaces or tabs
- (forward-char -1)
- (while (member (preceding-char) '(? ?\t))
- (forward-char -1))
- (if overlays
- ;; Reuse an overlay we already have.
- (progn
- (setq overlay (car overlays)
- overlays (cdr overlays))
- (overlay-put overlay 'face face)
- (move-overlay overlay beg (point)))
- ;; Make a new overlay and add it to
- ;; rmail-overlay-list.
- (setq overlay (make-overlay beg (point)))
- (overlay-put overlay 'face face)
- (setq rmail-overlay-list
- (cons overlay rmail-overlay-list))))))))))
-
-(defun rmail-next-message (n)
- "Show following message whether deleted or not.
-With prefix arg 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 arg 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 arg N, moves forward N non-deleted messages,
-or backward if N is negative.
-
-Returns t if a new message is being shown, nil otherwise."
- (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)
- (progn (rmail-show-message lastwin)
- t)
- (if (< n 0)
- (message "No previous nondeleted message"))
- (if (> n 0)
- (message "No following nondeleted message"))
- nil)))
-
-(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-first-message ()
- "Show first message in file."
- (interactive)
- (rmail-maybe-set-message-counters)
- (rmail-show-message 1))
-
-(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)))
-
-(defun rmail-message-recipients-p (msg recipients &optional primary-only)
- (save-restriction
- (goto-char (rmail-msgbeg msg))
- (search-forward "\n*** EOOH ***\n")
- (narrow-to-region (point) (progn (search-forward "\n\n") (point)))
- (or (string-match recipients (or (mail-fetch-field "To") ""))
- (string-match recipients (or (mail-fetch-field "From") ""))
- (if (not primary-only)
- (string-match recipients (or (mail-fetch-field "Cc") ""))))))
-
-(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)))
-
-(defvar rmail-search-last-regexp nil)
-(defun rmail-search (regexp &optional n)
- "Show message containing next match for REGEXP (but not the current msg).
-Prefix argument gives repeat count; negative argument means search
-backwards (through earlier messages).
-Interactively, empty argument means use same regexp used last time."
- (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
- (prefix-numeric-value current-prefix-arg))))
- (or n (setq n 1))
- (message "%sRmail search for %s..."
- (if (< n 0) "Reverse " "")
- regexp)
- (rmail-maybe-set-message-counters)
- (let ((omin (point-min))
- (omax (point-max))
- (opoint (point))
- win
- (reversep (< n 0))
- (msg rmail-current-message))
- (unwind-protect
- (progn
- (widen)
- (while (/= n 0)
- ;; 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))))
- (setq n (+ n (if reversep 1 -1)))))
- (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 "Search failed: %s" regexp)))))
-
-(defun rmail-search-backwards (regexp &optional n)
- "Show message containing previous match for REGEXP.
-Prefix argument gives repeat count; negative argument means search
-forward (through later messages).
-Interactively, empty argument means use same regexp used last time."
- (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
- (prefix-numeric-value current-prefix-arg))))
- (rmail-search regexp (- (or n 1))))
-
-;; Show the first message which has the `unseen' attribute.
-(defun rmail-first-unseen-message ()
- (rmail-maybe-set-message-counters)
- (let ((current 1)
- found)
- (save-restriction
- (widen)
- (while (and (not found) (<= current rmail-total-messages))
- (if (rmail-message-labels-p current ", ?\\(unseen\\),")
- (setq found current))
- (setq current (1+ current))))
-;; Let the caller show the message.
-;; (if found
-;; (rmail-show-message found))
- found))
-
-(defun rmail-next-same-subject (n)
- "Go to the next mail message having the same subject header.
-With prefix argument N, do this N times.
-If N is negative, go backwards instead."
- (interactive "p")
- (let ((subject (mail-fetch-field "Subject"))
- (forward (> n 0))
- (i rmail-current-message)
- search-regexp found)
- (if (string-match "Re:[ \t]*" subject)
- (setq subject (substring subject (match-end 0))))
- (setq search-regexp (concat "^Subject: *\\(Re: *\\)?"
- (regexp-quote subject)
- "\n"))
- (save-excursion
- (save-restriction
- (widen)
- (while (and (/= n 0)
- (if forward
- (< i rmail-total-messages)
- (> i 1)))
- (let (done)
- (while (and (not done)
- (if forward
- (< i rmail-total-messages)
- (> i 1)))
- (setq i (if forward (1+ i) (1- i)))
- (goto-char (rmail-msgbeg i))
- (search-forward "\n*** EOOH ***\n")
- (let ((beg (point)) end)
- (search-forward "\n\n")
- (setq end (point))
- (goto-char beg)
- (setq done (re-search-forward search-regexp end t))))
- (if done (setq found i)))
- (setq n (if forward (1- n) (1+ n))))))
- (if found
- (rmail-show-message found)
- (error "No %s message with same subject"
- (if forward "following" "previous")))))
-
-(defun rmail-previous-same-subject (n)
- "Go to the previous mail message having the same subject header.
-With prefix argument N, do this N times.
-If N is negative, go forwards instead."
- (interactive "p")
- (rmail-next-same-subject (- n)))
-
-;;;; *** 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)
- (run-hooks 'rmail-delete-message-hook))
-
-(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)
- (if (rmail-summary-exists)
- (save-excursion
- (set-buffer rmail-summary-buffer)
- (rmail-summary-mark-undeleted msg)))
- (rmail-maybe-display-summary))))
-
-(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.
-
-Returns t if a new message is displayed after the delete, or nil otherwise."
- (interactive "P")
- (rmail-set-attribute "deleted" t)
- (run-hooks 'rmail-delete-message-hook)
- (let ((del-msg rmail-current-message))
- (if (rmail-summary-exists)
- (rmail-select-summary
- (rmail-summary-mark-deleted del-msg)))
- (prog1 (rmail-next-undeleted-message (if backward -1 1))
- (rmail-maybe-display-summary))))
-
-(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))
-
-;; Compute the message number a given message would have after expunging.
-;; The present number of the message is OLDNUM.
-;; DELETEDVEC should be rmail-deleted-vector.
-;; The value is nil for a message that would be deleted.
-(defun rmail-msg-number-after-expunge (deletedvec oldnum)
- (if (or (null oldnum) (= (aref deletedvec oldnum) ?D))
- nil
- (let ((i 0)
- (newnum 0))
- (while (< i oldnum)
- (if (/= (aref deletedvec i) ?D)
- (setq newnum (1+ newnum)))
- (setq i (1+ i)))
- newnum)))
-
-(defun rmail-only-expunge ()
- "Actually erase all deleted messages in the file."
- (interactive)
- (message "Expunging deleted messages...")
- ;; Discard all undo records for this buffer.
- (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)
- (rmail-message-deleted-p 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.
- (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)
- (rmailbuf (current-buffer))
- (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)
-
- ;; Find each sendmail buffer that is set to reply
- ;; to a message in this buffer, and update its
- ;; message number.
- (let ((bufs (buffer-list)))
- (while bufs
- (save-excursion
- (set-buffer (car bufs))
- (and (boundp 'rmail-send-actions-rmail-buffer)
- (eq rmail-send-actions-rmail-buffer rmailbuf)
- (setq rmail-send-actions-rmail-msg-number
- (rmail-msg-number-after-expunge
- deleted
- rmail-send-actions-rmail-msg-number))))
- (setq bufs (cdr bufs))))
-
- (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))))
-
-(defun rmail-expunge ()
- "Erase deleted messages from Rmail file and summary buffer."
- (interactive)
- (rmail-only-expunge)
- (if (rmail-summary-exists)
- (rmail-select-summary
- (rmail-update-summary))))
-
-;;;; *** Rmail Mailing Commands ***
-
-(defun rmail-start-mail (&optional noerase to subject in-reply-to cc
- replybuffer sendactions same-window others)
- (let (yank-action)
- (if replybuffer
- (setq yank-action (list 'insert-buffer replybuffer)))
- (setq others (cons (cons "cc" cc) others))
- (setq others (cons (cons "in-reply-to" in-reply-to) others))
- (if same-window
- (compose-mail to subject others
- noerase nil
- yank-action sendactions)
- (if (and window-system rmail-mail-new-frame)
- (prog1
- (compose-mail to subject others
- noerase 'switch-to-buffer-other-frame
- yank-action sendactions)
- ;; This is not a standard frame parameter;
- ;; nothing except sendmail.el looks at it.
- (modify-frame-parameters (selected-frame)
- '((mail-dedicated-frame . t))))
- (compose-mail to subject others
- noerase 'switch-to-buffer-other-window
- yank-action sendactions)))))
-
-(defun rmail-mail ()
- "Send mail in another window.
-While composing the message, use \\[mail-yank-original] to yank the
-original message into it."
- (interactive)
- (rmail-start-mail nil nil nil nil nil (current-buffer)))
-
-(defun rmail-continue ()
- "Continue composing outgoing message previously being composed."
- (interactive)
- (rmail-start-mail t))
-
-(put 'rmail-send-actions-rmail-buffer 'permanent-local t)
-(put 'rmail-send-actions-rmail-msg-number 'permanent-local 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")
- (let (from reply-to cc subject date to message-id
- resent-to resent-cc resent-reply-to
- (msgnum rmail-current-message)
- (rmail-buffer (current-buffer)))
- (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 from (mail-fetch-field "from")
- reply-to (or (mail-fetch-field "reply-to" nil t)
- from)
- cc (and (not just-sender)
- (mail-fetch-field "cc" nil t))
- subject (mail-fetch-field "subject")
- date (mail-fetch-field "date")
- to (or (mail-fetch-field "to" nil t) "")
- message-id (mail-fetch-field "message-id")
- resent-reply-to (mail-fetch-field "resent-reply-to" t)
- resent-cc (and (not just-sender)
- (mail-fetch-field "resent-cc" nil t))
- resent-to (or (mail-fetch-field "resent-to" nil t) "")
-;;; resent-subject (mail-fetch-field "resent-subject")
-;;; resent-date (mail-fetch-field "resent-date")
-;;; resent-message-id (mail-fetch-field "resent-message-id")
- )))
- ;; Merge the resent-to and resent-cc into the to and cc.
- (if (and resent-to (not (equal resent-to "")))
- (if (not (equal to ""))
- (setq to (concat to ", " resent-to))
- (setq to resent-to)))
- (if (and resent-cc (not (equal resent-cc "")))
- (if (not (equal cc ""))
- (setq cc (concat cc ", " resent-cc))
- (setq cc resent-cc)))
- ;; Add `Re: ' to subject if not there already.
- (and (stringp subject)
- (setq subject
- (concat rmail-reply-prefix
- (if (string-match rmail-reply-regexp subject)
- (substring subject (match-end 0))
- subject))))
- (rmail-start-mail 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)
- (list (list '(lambda ()
- (let ((msgnum rmail-send-actions-rmail-msg-number))
- (save-excursion
- (set-buffer rmail-send-actions-rmail-buffer)
- (if msgnum
- (rmail-set-attribute "answered" t msgnum))))))))
- ;; We keep the rmail buffer and message number in these
- ;; buffer-local vars in the sendmail buffer,
- ;; so that rmail-only-expunge can relocate the message number.
- (make-local-variable 'rmail-send-actions-rmail-buffer)
- (make-local-variable 'rmail-send-actions-rmail-msg-number)
- (setq rmail-send-actions-rmail-buffer rmail-buffer)
- (setq rmail-send-actions-rmail-msg-number msgnum)))
-
-(defun rmail-make-in-reply-to-field (from date message-id)
- (cond ((not from)
- (if message-id
- message-id
- nil))
- (mail-use-rfc822
- (require 'rfc822)
- (let ((tem (car (rfc822-addresses from))))
- (if message-id
- (if (string-match
- (regexp-quote (if (string-match "@[^@]*\\'" tem)
- (substring tem 0 (match-beginning 0))
- tem))
- message-id)
- ;; Message-ID is sufficiently informative
- message-id
- (concat message-id " (" tem ")"))
- ;; Copy TEM, discarding text properties.
- (setq tem (copy-sequence tem))
- (set-text-properties 0 (length tem) nil tem)
- (setq tem (copy-sequence tem))
- ;; Use prin1 to fake RFC822 quoting
- (let ((field (prin1-to-string tem)))
- (if date
- (concat field "'s message of " date)
- field)))))
- ((let* ((foo "[^][\000-\037\177-\377()<>@,;:\\\" ]+")
- (bar "[^][\000-\037\177-\377()<>@,;:\\\"]+"))
- ;; Can't use format because format loses on \000 (unix *^&%*^&%$!!)
- (or (string-match (concat "\\`[ \t]*\\(" bar
- "\\)\\(<" foo "@" foo ">\\)?[ \t]*\\'")
- ;; "Unix Loser <Foo@bar.edu>" => "Unix Loser"
- from)
- (string-match (concat "\\`[ \t]*<" foo "@" foo ">[ \t]*(\\("
- bar "\\))[ \t]*\\'")
- ;; "<Bugs@bar.edu>" (Losing Unix) => "Losing Unix"
- from)))
- (let ((start (match-beginning 1))
- (end (match-end 1)))
- ;; Trim whitespace which above regexp match allows
- (while (and (< start end)
- (memq (aref from start) '(?\t ?\ )))
- (setq start (1+ start)))
- (while (and (< start end)
- (memq (aref from (1- end)) '(?\t ?\ )))
- (setq end (1- end)))
- (let ((field (substring from start end)))
- (if date (setq field (concat "message from " field " on " date)))
- (if message-id
- ;; "<AA259@bar.edu> (message from Unix Loser on 1-Apr-89)"
- (concat message-id " (" field ")")
- field))))
- (t
- ;; If we can't kludge it simply, do it correctly
- (let ((mail-use-rfc822 t))
- (rmail-make-in-reply-to-field from date message-id)))))
-
-(defun rmail-forward (resend)
- "Forward the current message to another user.
-With prefix argument, \"resend\" the message instead of forwarding it;
-see the documentation of `rmail-resend'."
- (interactive "P")
- (if resend
- (call-interactively 'rmail-resend)
- (let ((forward-buffer (current-buffer))
- (msgnum rmail-current-message)
- (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 (rmail-start-mail
- nil nil subject nil nil nil
- (list (list (function
- (lambda ()
- (let ((msgnum
- rmail-send-actions-rmail-msg-number))
- (save-excursion
- (set-buffer rmail-send-actions-rmail-buffer)
- (if msgnum
- (rmail-set-attribute
- "forwarded" t msgnum))))))))
- ;; 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.
- (and (not rmail-mail-new-frame) (one-window-p t)))
- ;; The mail buffer is now current.
- (save-excursion
- ;; We keep the rmail buffer and message number in these
- ;; buffer-local vars in the sendmail buffer,
- ;; so that rmail-only-expunge can relocate the message number.
- (make-local-variable 'rmail-send-actions-rmail-buffer)
- (make-local-variable 'rmail-send-actions-rmail-msg-number)
- (setq rmail-send-actions-rmail-buffer forward-buffer)
- (setq rmail-send-actions-rmail-msg-number msgnum)
- ;; Insert after header separator--before signature if any.
- (goto-char (point-min))
- (search-forward-regexp
- (concat "^" (regexp-quote mail-header-separator) "$"))
- (forward-line 1)
- (insert "------- Start of forwarded message -------\n")
- ;; Quote lines with `- ' if they start with `-'.
- (let ((beg (point)) end)
- (setq end (point-marker))
- (set-marker-insertion-type end t)
- (insert-buffer-substring forward-buffer)
- (goto-char beg)
- (while (re-search-forward "^-" nil t)
- (beginning-of-line)
- (insert "- ")
- (forward-line 1))
- (goto-char end)
- (skip-chars-backward "\n")
- (if (< (point) end)
- (forward-char 1))
- (delete-region (point) end)
- (set-marker end nil))
- (insert "------- End of forwarded message -------\n")
- (push-mark))))))
-
-(defun rmail-resend (address &optional from comment mail-alias-file)
- "Resend current message to ADDRESSES.
-ADDRESSES should be a single address, a string consisting of several
-addresses separated by commas, or a list of addresses.
-
-Optional FROM is the address to resend the message from, and
-defaults to the username of the person redistributing the message.
-Optional COMMENT is a string that will be inserted as a comment in the
-resent message.
-Optional ALIAS-FILE is alternate aliases file to be used by sendmail,
-typically for purposes of moderating a list."
- (interactive "sResend to: ")
- (require 'sendmail)
- (require 'mailalias)
- (if (not from) (setq from (user-login-name)))
- (let ((tembuf (generate-new-buffer " sendmail temp"))
- (mail-header-separator "")
- (case-fold-search nil)
- (mailbuf (current-buffer)))
- (unwind-protect
- (save-excursion
- ;;>> Copy message into temp buffer
- (set-buffer tembuf)
- (insert-buffer-substring mailbuf)
- (goto-char (point-min))
- ;; Delete any Sender field, since that's not specifiable.
- ; Only delete Sender fields in the actual header.
- (re-search-forward "^$" nil 'move)
- ; Using "while" here rather than "if" because some buggy mail
- ; software may have inserted multiple Sender fields.
- (while (re-search-backward "^Sender:" nil t)
- (let (beg)
- (setq beg (point))
- (forward-line 1)
- (while (looking-at "[ \t]")
- (forward-line 1))
- (delete-region beg (point))))
- ; Go back to the beginning of the buffer so the Resent- fields
- ; are inserted there.
- (goto-char (point-min))
- ;;>> Insert resent-from:
- (insert "Resent-From: " from "\n")
- (insert "Resent-Date: " (mail-rfc822-date) "\n")
- ;;>> Insert resent-to: and bcc if need be.
- (let ((before (point)))
- (if mail-self-blind
- (insert "Resent-Bcc: " (user-login-name) "\n"))
- (insert "Resent-To: " (if (stringp address)
- address
- (mapconcat 'identity address ",\n\t"))
- "\n")
- ;; Expand abbrevs in the recipients.
- (save-excursion
- (if (featurep 'mailabbrev)
- (let ((end (point-marker))
- (local-abbrev-table mail-abbrevs)
- (old-syntax-table (syntax-table)))
- (if (and (not (vectorp mail-abbrevs))
- (file-exists-p mail-personal-alias-file))
- (build-mail-abbrevs))
- (set-syntax-table mail-abbrev-syntax-table)
- (goto-char before)
- (while (and (< (point) end)
- (progn (forward-word 1)
- (<= (point) end)))
- (expand-abbrev))
- (set-syntax-table old-syntax-table))
- (expand-mail-aliases before (point)))))
- ;;>> Set up comment, if any.
- (if (and (sequencep comment) (not (zerop (length comment))))
- (let ((before (point))
- after)
- (insert comment)
- (or (eolp) (insert "\n"))
- (setq after (point))
- (goto-char before)
- (while (< (point) after)
- (insert "Resent-Comment: ")
- (forward-line 1))))
- ;; Don't expand aliases in the destination fields
- ;; of the original message.
- (let (mail-aliases)
- (funcall send-mail-function)))
- (kill-buffer tembuf))
- (rmail-set-attribute "resent" t rmail-current-message)))
-
-(defvar mail-unsent-separator
- (concat "^ *---+ +Unsent message follows +---+ *$\\|"
- "^ *---+ +Returned message +---+ *$\\|"
- "^Start of returned message$\\|"
- "^ *---+ +Original message +---+ *$\\|"
- "^ *--+ +begin message +--+ *$\\|"
- "^ *---+ +Original message follows +---+ *$\\|"
- "^|? *---+ +Message text follows: +---+ *|?$")
- "A regexp that matches the separator before the text of a failed message.")
-
-(defun rmail-retry-failure ()
- "Edit a mail message which is based on the contents of the current message.
-For a message rejected by the mail system, extract the interesting headers and
-the body of the original message.
-The variable `mail-unsent-separator' should match the string that
-delimits the returned original message.
-The variable `rmail-retry-ignored-headers' is a regular expression
-specifying headers which should not be copied into the new message."
- (interactive)
- (require 'mail-utils)
- (let ((rmail-buffer (current-buffer))
- (msgnum rmail-current-message)
- bounce-start bounce-end bounce-indent resending)
- (save-excursion
- ;; Narrow down to just the quoted original message
- (rmail-beginning-of-message)
- (let ((case-fold-search t))
- (if (search-forward "This is a MIME-encapsulated message\n\n--" nil t)
- (let ((codestring
- (buffer-substring (progn (beginning-of-line) (point))
- (progn (end-of-line) (point)))))
- (or (re-search-forward mail-unsent-separator nil t)
- (error "Cannot find beginning of header in failed message"))
- (or (and (search-forward codestring nil t)
- (search-forward "\n\n" nil t))
- (error "Cannot find end of Mime data in failed message"))
- (setq bounce-start (point))
- (save-excursion
- (goto-char (point-max))
- (search-backward codestring)
- (setq bounce-end (point)))
- (or (search-forward "\n\n" nil t)
- (error "Cannot find end of header in failed message")))
- (or (re-search-forward mail-unsent-separator nil t)
- (error "Cannot parse this as a failure message"))
- (skip-chars-forward "\n")
- ;; Support a style of failure message in which the original
- ;; message is indented, and included within lines saying
- ;; `Start of returned message' and `End of returned message'.
- (if (looking-at " +Received:")
- (progn
- (setq bounce-start (point))
- (skip-chars-forward " ")
- (setq bounce-indent (- (current-column)))
- (goto-char (point-max))
- (re-search-backward "^End of returned message$" nil t)
- (setq bounce-end (point)))
- ;; One message contained a few random lines before the old
- ;; message header. The first line of the message started with
- ;; two hyphens. A blank line followed these random lines.
- ;; The same line beginning with two hyphens was possibly
- ;; marking the end of the message.
- (if (looking-at "^--")
- (let ((boundary (buffer-substring-no-properties
- (point)
- (progn (end-of-line) (point)))))
- (search-forward "\n\n")
- (skip-chars-forward "\n")
- (setq bounce-start (point))
- (goto-char (point-max))
- (search-backward (concat "\n\n" boundary) bounce-start t)
- (setq bounce-end (point)))
- (setq bounce-start (point)
- bounce-end (point-max)))
- (or (search-forward "\n\n" nil t)
- (error "Cannot find end of header in failed message"))
- ))))
- ;; Start sending a new message; default header fields from the original.
- ;; Turn off the usual actions for initializing the message body
- ;; because we want to get only the text from the failure message.
- (let ((action
- ;; This function will be called when the user sends the retry.
- ;; It will mark the bounce message as "retried".
- (function (lambda ()
- (let ((msgnum rmail-send-actions-rmail-msg-number))
- (save-excursion
- (set-buffer rmail-send-actions-rmail-buffer)
- (if msgnum
- (rmail-set-attribute "retried" t msgnum)))))))
- mail-signature mail-setup-hook)
- (if (rmail-start-mail nil nil nil nil nil rmail-buffer
- (list (list action)))
- ;; Insert original text as initial text of new draft message.
- ;; Bind inhibit-read-only since the header delimiter
- ;; of the previous message was probably read-only.
- (let ((inhibit-read-only t))
- ;; We keep the rmail buffer and message number in these
- ;; buffer-local vars in the sendmail buffer,
- ;; so that the rmail-only-expunge can relocate the message number.
- (make-local-variable 'rmail-send-actions-rmail-buffer)
- (make-local-variable 'rmail-send-actions-rmail-msg-number)
- (setq rmail-send-actions-rmail-buffer rmail-buffer)
- (setq rmail-send-actions-rmail-msg-number msgnum)
- (erase-buffer)
- (insert-buffer-substring rmail-buffer bounce-start bounce-end)
- (goto-char (point-min))
- (if bounce-indent
- (indent-rigidly (point-min) (point-max) bounce-indent))
- (rmail-clear-headers rmail-retry-ignored-headers)
- (rmail-clear-headers "^sender:\\|^from:\\|^return-path:")
- (goto-char (point-min))
- (save-restriction
- (search-forward "\n\n")
- (forward-line -1)
- (narrow-to-region (point-min) (point))
- (setq resending (mail-fetch-field "resent-to"))
- (if mail-self-blind
- (if resending
- (insert "Resent-Bcc: " (user-login-name) "\n")
- (insert "BCC: " (user-login-name) "\n"))))
- (insert mail-header-separator)
- (mail-position-on-field (if resending "Resent-To" "To") t)
- (set-buffer rmail-buffer)
- (rmail-beginning-of-message))))))
-
-(defun rmail-summary-exists ()
- "Non-nil iff in an RMAIL buffer and an associated summary buffer exists.
-In fact, the non-nil value returned is the summary buffer itself."
- (and rmail-summary-buffer (buffer-name rmail-summary-buffer)
- rmail-summary-buffer))
-
-(defun rmail-summary-displayed ()
- "t iff in RMAIL buffer and an associated summary buffer is displayed."
- (and rmail-summary-buffer (get-buffer-window rmail-summary-buffer)))
-
-(defvar rmail-redisplay-summary nil
- "*Non-nil means Rmail should show the summary when it changes.
-This has an effect only if a summary buffer exists.")
-
-(defvar rmail-summary-window-size nil
- "*Non-nil means specify the height for an Rmail summary window.")
-
-;; Put the summary buffer back on the screen, if user wants that.
-(defun rmail-maybe-display-summary ()
- (let ((selected (selected-window))
- window)
- ;; If requested, make sure the summary is displayed.
- (and rmail-summary-buffer (buffer-name rmail-summary-buffer)
- rmail-redisplay-summary
- (if (get-buffer-window rmail-summary-buffer 0)
- ;; It's already in some frame; show that one.
- (let ((frame (window-frame
- (get-buffer-window rmail-summary-buffer 0))))
- (make-frame-visible frame)
- (raise-frame frame))
- (display-buffer rmail-summary-buffer)))
- ;; If requested, set the height of the summary window.
- (and rmail-summary-buffer (buffer-name rmail-summary-buffer)
- rmail-summary-window-size
- (setq window (get-buffer-window rmail-summary-buffer))
- ;; Don't try to change the size if just one window in frame.
- (not (eq window (frame-root-window (window-frame window))))
- (unwind-protect
- (progn
- (select-window window)
- (enlarge-window (- rmail-summary-window-size (window-height))))
- (select-window selected)))))
-
-;;;; *** Rmail Local Fontification ***
-
-(defun rmail-fontify-buffer-function ()
- ;; This function's symbol is bound to font-lock-fontify-buffer-function.
- (make-local-hook 'rmail-show-message-hook)
- (add-hook 'rmail-show-message-hook 'rmail-fontify-message nil t)
- ;; If we're already showing a message, fontify it now.
- (if rmail-current-message (rmail-fontify-message))
- ;; Prevent Font Lock mode from kicking in.
- (setq font-lock-fontified t))
-
-(defun rmail-unfontify-buffer-function ()
- ;; This function's symbol is bound to font-lock-fontify-unbuffer-function.
- (let ((modified (buffer-modified-p))
- (buffer-undo-list t) (inhibit-read-only t)
- before-change-functions after-change-functions
- buffer-file-name buffer-file-truename)
- (save-restriction
- (widen)
- (remove-hook 'rmail-show-message-hook 'rmail-fontify-message t)
- (remove-text-properties (point-min) (point-max) '(rmail-fontified nil))
- (font-lock-default-unfontify-buffer)
- (and (not modified) (buffer-modified-p) (set-buffer-modified-p nil)))))
-
-(defun rmail-fontify-message ()
- ;; Fontify the current message if it is not already fontified.
- (if (text-property-any (point-min) (point-max) 'rmail-fontified nil)
- (let ((modified (buffer-modified-p))
- (buffer-undo-list t) (inhibit-read-only t)
- before-change-functions after-change-functions
- buffer-file-name buffer-file-truename)
- (save-excursion
- (save-match-data
- (add-text-properties (point-min) (point-max) '(rmail-fontified t))
- (font-lock-fontify-region (point-min) (point-max))
- (and (not modified) (buffer-modified-p) (set-buffer-modified-p nil)))))))
-
-(provide 'rmail)
-
-;;; rmail.el ends here
diff --git a/lisp/mail/rmailedit.el b/lisp/mail/rmailedit.el
deleted file mode 100644
index 2f892981d19..00000000000
--- a/lisp/mail/rmailedit.el
+++ /dev/null
@@ -1,121 +0,0 @@
-;;; rmailedit.el --- "RMAIL edit mode" Edit the current message.
-
-;; Copyright (C) 1985, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(require 'rmail)
-
-(defvar rmail-edit-map nil)
-(if rmail-edit-map
- nil
- ;; Make a keymap that inherits text-mode-map.
- (setq rmail-edit-map (nconc (make-sparse-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))
-
-;; Rmail Edit mode is suitable only for specially formatted data.
-(put 'rmail-edit-mode 'mode-class 'special)
-
-(defun rmail-edit-mode ()
- "Major mode for editing the contents of an RMAIL message.
-The editing commands are the same as in Text mode, together with two commands
-to return to regular RMAIL:
- * rmail-abort-edit cancels the changes
- you have made and returns to RMAIL
- * rmail-cease-edit makes them permanent.
-\\{rmail-edit-map}"
- (use-local-map rmail-edit-map)
- (setq major-mode 'rmail-edit-mode)
- (setq mode-name "RMAIL Edit")
- (if (boundp 'mode-line-modified)
- (setq mode-line-modified (default-value 'mode-line-modified))
- (setq mode-line-format (default-value 'mode-line-format)))
- (if (rmail-summary-exists)
- (save-excursion
- (set-buffer rmail-summary-buffer)
- (rmail-summary-disable)))
- (run-hooks 'text-mode-hook 'rmail-edit-mode-hook))
-
-;;;###autoload
-(defun rmail-edit-current-message ()
- "Edit the contents of this message."
- (interactive)
- (rmail-edit-mode)
- (make-local-variable 'rmail-old-text)
- (setq rmail-old-text (buffer-substring (point-min) (point-max)))
- (setq buffer-read-only nil)
- (force-mode-line-update)
- (if (and (eq (key-binding "\C-c\C-c") 'rmail-cease-edit)
- (eq (key-binding "\C-c\C-]") 'rmail-abort-edit))
- (message "Editing: Type C-c C-c to return to Rmail, C-c C-] to abort")
- (message "%s" (substitute-command-keys
- "Editing: Type \\[rmail-cease-edit] to return to Rmail, \\[rmail-abort-edit] to abort"))))
-
-(defun rmail-cease-edit ()
- "Finish editing message; switch back to Rmail proper."
- (interactive)
- (if (rmail-summary-exists)
- (save-excursion
- (set-buffer rmail-summary-buffer)
- (rmail-summary-enable)))
- ;; Make sure buffer ends with a newline.
- (save-excursion
- (goto-char (point-max))
- (if (/= (preceding-char) ?\n)
- (insert "\n"))
- ;; Adjust the marker that points to the end of this message.
- (set-marker (aref rmail-message-vector (1+ rmail-current-message))
- (point)))
- (let ((old rmail-old-text))
- (force-mode-line-update)
- (rmail-mode-1)
- (if (and (= (length old) (- (point-max) (point-min)))
- (string= old (buffer-substring (point-min) (point-max))))
- ()
- (setq old nil)
- (rmail-set-attribute "edited" t)
- (if (boundp 'rmail-summary-vector)
- (progn
- (aset rmail-summary-vector (1- rmail-current-message) nil)
- (save-excursion
- (rmail-widen-to-current-msgbeg
- (function (lambda ()
- (forward-line 2)
- (if (looking-at "Summary-line: ")
- (let ((buffer-read-only nil))
- (delete-region (point)
- (progn (forward-line 1)
- (point))))))))
- (rmail-show-message))))))
- (setq buffer-read-only t))
-
-(defun rmail-abort-edit ()
- "Abort edit of current message; restore original contents."
- (interactive)
- (delete-region (point-min) (point-max))
- (insert rmail-old-text)
- (rmail-cease-edit)
- (rmail-highlight-headers))
-
-;;; rmailedit.el ends here
diff --git a/lisp/mail/rmailkwd.el b/lisp/mail/rmailkwd.el
deleted file mode 100644
index dfafab38e60..00000000000
--- a/lisp/mail/rmailkwd.el
+++ /dev/null
@@ -1,269 +0,0 @@
-;;; rmailkwd.el --- part of the "RMAIL" mail reader for Emacs.
-
-;; Copyright (C) 1985, 1988, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;; Global to all RMAIL buffers. It exists primarily for the sake of
-;; completion. It is better to use strings with the label functions
-;; and let them worry about making the label.
-
-(defvar rmail-label-obarray (make-vector 47 0))
-
-;; Named list of symbols representing valid message attributes in RMAIL.
-
-(defconst rmail-attributes
- (cons 'rmail-keywords
- (mapcar (function (lambda (s) (intern s rmail-label-obarray)))
- '("deleted" "answered" "filed" "forwarded" "unseen" "edited"
- "resent"))))
-
-(defconst rmail-deleted-label (intern "deleted" rmail-label-obarray))
-
-;; Named list of symbols representing valid message keywords in RMAIL.
-
-(defvar rmail-keywords)
-
-;;;###autoload
-(defun rmail-add-label (string)
- "Add LABEL to labels associated with current RMAIL message.
-Completion is performed over known labels when reading."
- (interactive (list (rmail-read-label "Add label")))
- (rmail-set-label string t))
-
-;;;###autoload
-(defun rmail-kill-label (string)
- "Remove LABEL from labels associated with current RMAIL message.
-Completion is performed over known labels when reading."
- (interactive (list (rmail-read-label "Remove label")))
- (rmail-set-label string nil))
-
-;;;###autoload
-(defun rmail-read-label (prompt)
- (if (not rmail-keywords) (rmail-parse-file-keywords))
- (let ((result
- (completing-read (concat prompt
- (if rmail-last-label
- (concat " (default "
- (symbol-name rmail-last-label)
- "): ")
- ": "))
- rmail-label-obarray
- nil
- nil)))
- (if (string= result "")
- rmail-last-label
- (setq rmail-last-label (rmail-make-label result t)))))
-
-(defun rmail-set-label (l state &optional n)
- (rmail-maybe-set-message-counters)
- (if (not n) (setq n rmail-current-message))
- (aset rmail-summary-vector (1- n) nil)
- (let* ((attribute (rmail-attribute-p l))
- (keyword (and (not attribute)
- (or (rmail-keyword-p l)
- (rmail-install-keyword l))))
- (label (or attribute keyword)))
- (if label
- (let ((omax (- (buffer-size) (point-max)))
- (omin (- (buffer-size) (point-min)))
- (buffer-read-only nil)
- (case-fold-search t))
- (unwind-protect
- (save-excursion
- (widen)
- (goto-char (rmail-msgbeg n))
- (forward-line 1)
- (if (not (looking-at "[01],"))
- nil
- (let ((start (1+ (point)))
- (bound))
- (narrow-to-region (point) (progn (end-of-line) (point)))
- (setq bound (point-max))
- (search-backward ",," nil t)
- (if attribute
- (setq bound (1+ (point)))
- (setq start (1+ (point))))
- (goto-char start)
-; (while (re-search-forward "[ \t]*,[ \t]*" nil t)
-; (replace-match ","))
-; (goto-char start)
- (if (re-search-forward
- (concat ", " (rmail-quote-label-name label) ",")
- bound
- 'move)
- (if (not state) (replace-match ","))
- (if state (insert " " (symbol-name label) ",")))
- (if (eq label rmail-deleted-label)
- (rmail-set-message-deleted-p n state)))))
- (narrow-to-region (- (buffer-size) omin) (- (buffer-size) omax))
- (if (= n rmail-current-message) (rmail-display-labels)))))))
-
-;; 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.
-
-;(defun rmail-message-label-p (label &optional n)
-; "Returns symbol if LABEL (attribute or keyword) on NTH or current message."
-; (rmail-message-labels-p (or n rmail-current-message) (regexp-quote label)))
-
-;(defun rmail-parse-message-labels (&optional n)
-; "Returns labels associated with NTH or current RMAIL message.
-;The result is a list of two lists of strings. The first is the
-;message attributes and the second is the message keywords."
-; (let (atts keys)
-; (save-restriction
-; (widen)
-; (goto-char (rmail-msgbeg (or n rmail-current-message)))
-; (forward-line 1)
-; (or (looking-at "[01],") (error "Malformed label line"))
-; (forward-char 2)
-; (while (looking-at "[ \t]*\\([^ \t\n,]+\\),")
-; (setq atts (cons (buffer-substring (match-beginning 1) (match-end 1))
-; atts))
-; (goto-char (match-end 0)))
-; (or (looking-at ",") (error "Malformed label line"))
-; (forward-char 1)
-; (while (looking-at "[ \t]*\\([^ \t\n,]+\\),")
-; (setq keys (cons (buffer-substring (match-beginning 1) (match-end 1))
-; keys))
-; (goto-char (match-end 0)))
-; (or (looking-at "[ \t]*$") (error "Malformed label line"))
-; (list (nreverse atts) (nreverse keys)))))
-
-(defun rmail-attribute-p (s)
- (let ((symbol (rmail-make-label s)))
- (if (memq symbol (cdr rmail-attributes)) symbol)))
-
-(defun rmail-keyword-p (s)
- (let ((symbol (rmail-make-label s)))
- (if (memq symbol (cdr (rmail-keywords))) symbol)))
-
-(defun rmail-make-label (s &optional forcep)
- (cond ((symbolp s) s)
- (forcep (intern (downcase s) rmail-label-obarray))
- (t (intern-soft (downcase s) rmail-label-obarray))))
-
-(defun rmail-force-make-label (s)
- (intern (downcase s) rmail-label-obarray))
-
-(defun rmail-quote-label-name (label)
- (regexp-quote (symbol-name (rmail-make-label label t))))
-
-;; Motion on messages with keywords.
-
-;;;###autoload
-(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.
-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))
-
-;;;###autoload
-(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.
-With prefix argument N moves forward N messages with these labels."
- (interactive "p\nsMove to next msg with labels: ")
- (if (string= labels "")
- (setq labels rmail-last-multi-labels))
- (or labels
- (error "No labels to find have been specified previously"))
- (setq rmail-last-multi-labels labels)
- (rmail-maybe-set-message-counters)
- (let ((lastwin rmail-current-message)
- (current rmail-current-message)
- (regexp (concat ", ?\\("
- (mail-comma-list-regexp labels)
- "\\),")))
- (save-restriction
- (widen)
- (while (and (> n 0) (< current rmail-total-messages))
- (setq current (1+ current))
- (if (rmail-message-labels-p current regexp)
- (setq lastwin current n (1- n))))
- (while (and (< n 0) (> current 1))
- (setq current (1- current))
- (if (rmail-message-labels-p current regexp)
- (setq lastwin current n (1+ n)))))
- (rmail-show-message lastwin)
- (if (< n 0)
- (message "No previous message with labels %s" labels))
- (if (> n 0)
- (message "No following message with labels %s" labels))))
-
-;;; Manipulate the file's Labels option.
-
-;; Return a list of symbols for all
-;; the keywords (labels) recorded in this file's Labels option.
-(defun rmail-keywords ()
- (or rmail-keywords (rmail-parse-file-keywords)))
-
-;; Set rmail-keywords to a list of symbols for all
-;; the keywords (labels) recorded in this file's Labels option.
-(defun rmail-parse-file-keywords ()
- (save-restriction
- (save-excursion
- (widen)
- (goto-char 1)
- (setq rmail-keywords
- (if (search-forward "\nLabels:" (rmail-msgbeg 1) t)
- (progn
- (narrow-to-region (point) (progn (end-of-line) (point)))
- (goto-char (point-min))
- (cons 'rmail-keywords
- (mapcar 'rmail-force-make-label
- (mail-parse-comma-list)))))))))
-
-;; Add WORD to the list in the file's Labels option.
-;; Any keyword used for the first time needs this done.
-(defun rmail-install-keyword (word)
- (let ((keyword (rmail-make-label word t))
- (keywords (rmail-keywords)))
- (if (not (or (rmail-attribute-p keyword)
- (rmail-keyword-p keyword)))
- (let ((omin (- (buffer-size) (point-min)))
- (omax (- (buffer-size) (point-max))))
- (unwind-protect
- (save-excursion
- (widen)
- (goto-char 1)
- (let ((case-fold-search t)
- (buffer-read-only nil))
- (or (search-forward "\nLabels:" nil t)
- (progn
- (end-of-line)
- (insert "\nLabels:")))
- (delete-region (point) (progn (end-of-line) (point)))
- (setcdr keywords (cons keyword (cdr keywords)))
- (while (setq keywords (cdr keywords))
- (insert (symbol-name (car keywords)) ","))
- (delete-char -1)))
- (narrow-to-region (- (buffer-size) omin)
- (- (buffer-size) omax)))))
- keyword))
-
-;;; rmailkwd.el ends here
diff --git a/lisp/mail/rmailmsc.el b/lisp/mail/rmailmsc.el
deleted file mode 100644
index 98926d8117e..00000000000
--- a/lisp/mail/rmailmsc.el
+++ /dev/null
@@ -1,55 +0,0 @@
-;;; rmailmsc.el --- miscellaneous support functions for the RMAIL mail reader
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;;;###autoload
-(defun set-rmail-inbox-list (file-name)
- "Set the inbox list of the current RMAIL file to FILE-NAME.
-You can specify one file name, or several names separated by commas.
-If FILE-NAME is empty, remove any existing inbox list."
- (interactive "sSet mailbox list to (comma-separated list of filenames): ")
- (save-excursion
- (let ((names (rmail-parse-file-inboxes))
- (standard-output nil))
- (if (or (not names)
- (y-or-n-p (concat "Replace "
- (mapconcat 'identity names ", ")
- "? ")))
- (let ((buffer-read-only nil))
- (widen)
- (goto-char (point-min))
- (search-forward "\n\^_")
- (re-search-backward "^Mail" nil t)
- (forward-line 0)
- (if (looking-at "Mail:")
- (delete-region (point)
- (progn (forward-line 1)
- (point))))
- (if (not (string= file-name ""))
- (insert-before-markers "Mail: " file-name "\n"))))))
- (setq rmail-inbox-list (rmail-parse-file-inboxes))
- (rmail-show-message rmail-current-message))
-
-;;; rmailmsc.el ends here
diff --git a/lisp/mail/rmailout.el b/lisp/mail/rmailout.el
deleted file mode 100644
index 29621cc955d..00000000000
--- a/lisp/mail/rmailout.el
+++ /dev/null
@@ -1,322 +0,0 @@
-;;; rmailout.el --- "RMAIL" mail reader for Emacs: output message to a file.
-
-;; Copyright (C) 1985, 1987, 1993, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(require 'rmail)
-
-;;;###autoload
-(defvar rmail-output-file-alist nil
- "*Alist matching regexps to suggested output Rmail files.
-This is a list of elements of the form (REGEXP . NAME-EXP).
-The suggestion is taken if REGEXP matches anywhere in the message buffer.
-NAME-EXP may be a string constant giving the file name to use,
-or more generally it may be any kind of expression that returns
-a file name as a string.")
-
-;;; There are functions elsewhere in Emacs that use this function; check
-;;; them out before you change the calling method.
-;;;###autoload
-(defun rmail-output-to-rmail-file (file-name &optional count)
- "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.
-If the file exists and is not an Rmail file,
-the message is appended in inbox format.
-
-The default file name comes from `rmail-default-rmail-file',
-which is updated to the name you use in this command.
-
-A prefix argument N says to output N consecutive messages
-starting with the current one. Deleted messages are skipped and don't count."
- (interactive
- (let ((default-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 (eval (cdr (car tail)))))
- (setq tail (cdr tail))))
- ;; If not suggestions, use same file as last time.
- (or answer rmail-default-rmail-file))))
- (list (setq rmail-default-rmail-file
- (let ((read-file
- (read-file-name
- (concat "Output message to Rmail file: (default "
- (file-name-nondirectory default-file)
- ") ")
- (file-name-directory default-file)
- default-file)))
- (if (file-directory-p read-file)
- (expand-file-name (file-name-nondirectory default-file)
- read-file)
- (expand-file-name
- (or read-file default-file)
- (file-name-directory default-file)))))
- (prefix-numeric-value current-prefix-arg))))
- (or count (setq count 1))
- (setq file-name
- (expand-file-name file-name
- (file-name-directory rmail-default-rmail-file)))
- (if (and (file-readable-p file-name) (not (mail-file-babyl-p file-name)))
- (rmail-output file-name count)
- (rmail-maybe-set-message-counters)
- (setq file-name (abbreviate-file-name file-name))
- (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
- ;; Temporarily turn off Deleted attribute.
- ;; Do this outside the save-restriction, since it would
- ;; shift the place in the buffer where the visible text starts.
- (if (rmail-message-deleted-p rmail-current-message)
- (progn (setq redelete t)
- (rmail-set-attribute "deleted" nil)))
- (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)
- ;; Output to a file.
- (if rmail-fields-not-to-output
- ;; Delete some fields while we output.
- (let ((obuf (current-buffer)))
- (set-buffer (get-buffer-create " rmail-out-temp"))
- (insert-buffer-substring obuf beg end)
- (rmail-delete-unwanted-fields)
- (append-to-file (point-min) (point-max) file-name)
- (set-buffer obuf)
- (kill-buffer (get-buffer " rmail-out-temp")))
- (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
- ;; Turn on auto save mode, if it's off in this
- ;; buffer but enabled by default.
- (and (not buffer-auto-save-file-name)
- auto-save-default
- (auto-save-mode t))
- (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-delete-unwanted-fields)
- (rmail-count-new-messages t)
- (if (rmail-summary-exists)
- (rmail-select-summary
- (rmail-update-summary)))
- (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-delete-unwanted-fields)))))))
- (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))))))
-
-;;;###autoload
-(defvar rmail-fields-not-to-output nil
- "*Regexp describing fields to exclude when outputting a message to a file.")
-
-;; Delete from the buffer header fields we don't want output.
-;; NOT-RMAIL if t means this buffer does not have the full header
-;; and *** EOOH *** that a message in an Rmail file has.
-(defun rmail-delete-unwanted-fields (&optional not-rmail)
- (if rmail-fields-not-to-output
- (save-excursion
- (goto-char (point-min))
- ;; Find the end of the header.
- (if (and (or not-rmail (search-forward "\n*** EOOH ***\n" nil t))
- (search-forward "\n\n" nil t))
- (let ((end (point-marker)))
- (goto-char (point-min))
- (while (re-search-forward rmail-fields-not-to-output end t)
- (beginning-of-line)
- (delete-region (point)
- (progn (forward-line 1) (point)))))))))
-
-;;; There are functions elsewhere in Emacs that use this function; check
-;;; them out before you change the calling method.
-;;;###autoload
-(defun rmail-output (file-name &optional count noattribute from-gnus)
- "Append this message to system-inbox-format 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.
-When called from lisp code, N may be omitted.
-
-If the pruned message header is shown on the current message, then
-messages will be appended with pruned headers; otherwise, messages
-will be appended with their original headers.
-
-The default file name comes from `rmail-default-file',
-which is updated to the name you use in this command.
-
-The optional third argument NOATTRIBUTE, if non-nil, says not
-to set the `filed' attribute, and not to display a message.
-
-The optional fourth argument FROM-GNUS is set when called from GNUS."
- (interactive
- (let ((default-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 (eval (cdr (car tail)))))
- (setq tail (cdr tail))))
- ;; If not suggestions, use same file as last time.
- (or answer rmail-default-file))))
- (list (setq rmail-default-file
- (let ((read-file
- (read-file-name
- (concat "Output message to Unix mail file: (default "
- (file-name-nondirectory default-file)
- ") ")
- (file-name-directory default-file)
- default-file)))
- (if (file-directory-p read-file)
- (expand-file-name (file-name-nondirectory default-file)
- read-file)
- (expand-file-name
- (or read-file default-file)
- (file-name-directory default-file)))))
- (prefix-numeric-value current-prefix-arg))))
- (or count (setq count 1))
- (setq file-name
- (expand-file-name file-name
- (and rmail-default-file
- (file-name-directory rmail-default-file))))
- (if (and (file-readable-p file-name) (mail-file-babyl-p file-name))
- (rmail-output-to-rmail-file file-name count)
- (let ((orig-count count)
- (rmailbuf (current-buffer))
- (case-fold-search t)
- (tembuf (get-buffer-create " rmail-output"))
- (original-headers-p
- (and (not from-gnus)
- (save-excursion
- (save-restriction
- (narrow-to-region (rmail-msgbeg rmail-current-message) (point-max))
- (goto-char (point-min))
- (forward-line 1)
- (= (following-char) ?0)))))
- header-beginning
- mail-from)
- (while (> count 0)
- (or from-gnus
- (setq mail-from
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (rmail-msgbeg rmail-current-message))
- (setq header-beginning (point))
- (search-forward "\n*** EOOH ***\n")
- (narrow-to-region header-beginning (point))
- (mail-fetch-field "Mail-From")))))
- (save-excursion
- (set-buffer tembuf)
- (erase-buffer)
- (insert-buffer-substring rmailbuf)
- (rmail-delete-unwanted-fields t)
- (insert "\n")
- (goto-char (point-min))
- (if mail-from
- (insert mail-from "\n")
- (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.)
- (let ((case-fold-search nil))
- (while (search-forward "\nFrom " nil t)
- (forward-char -5)
- (insert ?>)))
- (write-region (point-min) (point-max) file-name t
- (if noattribute 'nomsg)))
- (or noattribute
- (if (equal major-mode 'rmail-mode)
- (rmail-set-attribute "filed" t)))
- (setq count (1- count))
- (or from-gnus
- (let ((next-message-p
- (if rmail-delete-after-output
- (rmail-delete-forward)
- (if (> count 0)
- (rmail-next-undeleted-message 1))))
- (num-appended (- orig-count count)))
- (if (and next-message-p original-headers-p)
- (rmail-toggle-header))
- (if (and (> count 0) (not next-message-p))
- (progn
- (error
- (save-excursion
- (set-buffer rmailbuf)
- (format "Only %d message%s appended" num-appended
- (if (= num-appended 1) "" "s"))))
- (setq count 0))))))
- (kill-buffer tembuf))))
-
-;;; rmailout.el ends here
diff --git a/lisp/mail/rmailsort.el b/lisp/mail/rmailsort.el
deleted file mode 100644
index 4066890fea9..00000000000
--- a/lisp/mail/rmailsort.el
+++ /dev/null
@@ -1,245 +0,0 @@
-;;; rmailsort.el --- Rmail: sort messages.
-
-;; Copyright (C) 1990, 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp>
-;; Version: $Header: /home/fsf/rms/e19/lisp/RCS/rmailsort.el,v 1.24 1996/01/20 07:41:37 kwzh Exp rms $
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(require 'sort)
-
-;; For rmail-select-summary
-(require 'rmail)
-
-(autoload 'timezone-make-date-sortable "timezone")
-
-;; Sorting messages in Rmail buffer
-
-;;;###autoload
-(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-make-date-sortable
- (rmail-fetch-field msg "Date"))))))
-
-;;;###autoload
-(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))))))
-
-;;;###autoload
-(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)
- (downcase ;Canonical name
- (mail-strip-quoted-names
- (or (rmail-fetch-field msg "From")
- (rmail-fetch-field msg "Sender") "")))))))
-
-;;;###autoload
-(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)
- (downcase ;Canonical name
- (mail-strip-quoted-names
- (or (rmail-fetch-field msg "To")
- (rmail-fetch-field msg "Apparently-To") "")
- ))))))
-
-;;;###autoload
-(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))
-
-;;;###autoload
-(defun rmail-sort-by-lines (reverse)
- "Sort messages of current Rmail file by number of lines.
-If prefix argument REVERSE is non-nil, sort them in reverse order."
- (interactive "P")
- (rmail-sort-messages reverse
- (function
- (lambda (msg)
- (count-lines (rmail-msgbeg msg)
- (rmail-msgend msg))))))
-
-;;;###autoload
-(defun rmail-sort-by-keywords (reverse labels)
- "Sort messages of current Rmail file by labels.
-If prefix argument REVERSE is non-nil, sort them in reverse order.
-KEYWORDS is a comma-separated list of labels."
- (interactive "P\nsSort by labels: ")
- (or (string-match "[^ \t]" labels)
- (error "No labels specified"))
- (setq labels (concat (substring labels (match-beginning 0)) ","))
- (let (labelvec)
- (while (string-match "[ \t]*,[ \t]*" labels)
- (setq labelvec (cons
- (concat ", ?\\("
- (substring labels 0 (match-beginning 0))
- "\\),")
- labelvec))
- (setq labels (substring labels (match-end 0))))
- (setq labelvec (apply 'vector (nreverse labelvec)))
- (rmail-sort-messages reverse
- (function
- (lambda (msg)
- (let ((n 0))
- (while (and (< n (length labelvec))
- (not (rmail-message-labels-p
- msg (aref labelvec n))))
- (setq n (1+ n)))
- n))))))
-
-;; Basic functions
-
-(defun rmail-sort-messages (reverse keyfun)
- "Sort messages of current Rmail file.
-If 1st argument REVERSE is non-nil, sort them in reverse order.
-2nd argument KEYFUN is called with a message number, and should return a key."
- (save-excursion
- ;; If we are in a summary buffer, operate on the Rmail buffer.
- (if (eq major-mode 'rmail-summary-mode)
- (set-buffer rmail-buffer))
- (let ((buffer-read-only nil)
- (predicate nil) ;< or string-lessp
- (sort-lists nil))
- (message "Finding sort keys...")
- (widen)
- (let ((msgnum 1))
- (while (>= rmail-total-messages msgnum)
- (setq sort-lists
- (cons (list (funcall keyfun msgnum) ;Make sorting key
- (eq rmail-current-message msgnum) ;True if current
- (aref rmail-message-vector msgnum)
- (aref rmail-message-vector (1+ 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)))
- ;; Decide predicate: < or string-lessp
- (if (numberp (car (car sort-lists))) ;Is a key numeric?
- (setq predicate (function <))
- (setq predicate (function string-lessp)))
- (setq sort-lists
- (sort sort-lists
- (function
- (lambda (a b)
- (funcall predicate (car a) (car b))))))
- (if reverse (setq sort-lists (nreverse sort-lists)))
- ;; Now we enter critical region. So, keyboard quit is disabled.
- (message "Reordering messages...")
- (let ((inhibit-quit t) ;Inhibit quit
- (current-message nil)
- (msgnum 1)
- (msginfo nil))
- ;; There's little hope that we can easily undo after that.
- (buffer-disable-undo (current-buffer))
- (goto-char (rmail-msgbeg 1))
- ;; To force update of all markers.
- (insert-before-markers ?Z)
- (backward-char 1)
- ;; Now reorder messages.
- (while sort-lists
- (setq msginfo (car sort-lists))
- ;; Swap two messages.
- (insert-buffer-substring
- (current-buffer) (nth 2 msginfo) (nth 3 msginfo))
- (delete-region (nth 2 msginfo) (nth 3 msginfo))
- ;; Is current message?
- (if (nth 1 msginfo)
- (setq current-message msgnum))
- (setq sort-lists (cdr sort-lists))
- (if (zerop (% msgnum 10))
- (message "Reordering messages...%d" msgnum))
- (setq msgnum (1+ msgnum)))
- ;; Delete the garbage inserted before.
- (delete-char 1)
- (setq quit-flag nil)
- (buffer-enable-undo)
- (rmail-set-message-counters)
- (rmail-show-message current-message)
- (if (rmail-summary-exists)
- (rmail-select-summary
- (rmail-update-summary)))))))
-
-(defun rmail-fetch-field (msg field)
- "Return the value of the header FIELD of MSG.
-Arguments are MSG and FIELD."
- (save-restriction
- (widen)
- (let ((next (rmail-msgend msg)))
- (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))))
-
-(defun rmail-make-date-sortable (date)
- "Make DATE sortable using the function string-lessp."
- ;; Assume the default time zone is GMT.
- (timezone-make-date-sortable date "GMT" "GMT"))
-
-(provide 'rmailsort)
-
-;;; rmailsort.el ends here
diff --git a/lisp/mail/rmailsum.el b/lisp/mail/rmailsum.el
deleted file mode 100644
index 9c04ef524cf..00000000000
--- a/lisp/mail/rmailsum.el
+++ /dev/null
@@ -1,1531 +0,0 @@
-;;; rmailsum.el --- make summary buffers for the mail reader
-
-;; Copyright (C) 1985, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Extended by Bob Weiner of Motorola
-;; Provided all commands from rmail-mode in rmail-summary-mode and made key
-;; bindings in both modes wholly compatible.
-
-;;; Code:
-
-;; For rmail-select-summary
-(require 'rmail)
-
-;;;###autoload
-(defvar rmail-summary-scroll-between-messages t
- "*Non-nil means Rmail summary scroll commands move between messages.")
-
-;;;###autoload
-(defvar rmail-summary-line-count-flag t
- "*Non-nil if Rmail summary should show the number of lines in each message.")
-
-(defvar rmail-summary-font-lock-keywords
- '(("^....D.*" . font-lock-string-face) ; Deleted.
- ("^....-.*" . font-lock-type-face) ; Unread.
- ;; Neither of the below will be highlighted if either of the above are:
- ("^....[^D-] \\(......\\)" 1 font-lock-keyword-face) ; Date.
- ("{ \\([^}]+\\),}" 1 font-lock-comment-face)) ; Labels.
- "Additional expressions to highlight in Rmail Summary mode.")
-
-;; Entry points for making a summary buffer.
-
-;; Regenerate the contents of the summary
-;; using the same selection criterion as last time.
-;; M-x revert-buffer in a summary buffer calls this function.
-(defun rmail-update-summary (&rest ignore)
- (apply (car rmail-summary-redo) (cdr rmail-summary-redo)))
-
-;;;###autoload
-(defun rmail-summary ()
- "Display a summary of all messages, one line per message."
- (interactive)
- (rmail-new-summary "All" '(rmail-summary) nil))
-
-;;;###autoload
-(defun rmail-summary-by-labels (labels)
- "Display a summary of all messages with one or more LABELS.
-LABELS should be a string containing the desired labels, separated by commas."
- (interactive "sLabels to summarize by: ")
- (if (string= labels "")
- (setq labels (or rmail-last-multi-labels
- (error "No label specified"))))
- (setq rmail-last-multi-labels labels)
- (rmail-new-summary (concat "labels " labels)
- (list 'rmail-summary-by-labels labels)
- 'rmail-message-labels-p
- (concat ", \\(" (mail-comma-list-regexp labels) "\\),")))
-
-;;;###autoload
-(defun rmail-summary-by-recipients (recipients &optional primary-only)
- "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 regexps separated by commas."
- (interactive "sRecipients to summarize by: \nP")
- (rmail-new-summary
- (concat "recipients " recipients)
- (list 'rmail-summary-by-recipients recipients primary-only)
- 'rmail-message-recipients-p
- (mail-comma-list-regexp recipients) primary-only))
-
-;;;###autoload
-(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)
- (list 'rmail-summary-by-regexp regexp)
- 'rmail-message-regexp-p
- regexp))
-
-;; rmail-summary-by-topic
-;; 1989 R.A. Schnitzler
-
-;;;###autoload
-(defun rmail-summary-by-topic (subject &optional whole-message)
- "Display a summary of all messages with the given SUBJECT.
-Normally checks the Subject field of headers;
-but if WHOLE-MESSAGE is non-nil (prefix arg given),
- look in the whole message.
-SUBJECT is a string of regexps separated by commas."
- (interactive "sTopics to summarize by: \nP")
- (rmail-new-summary
- (concat "about " subject)
- (list 'rmail-summary-by-topic subject whole-message)
- 'rmail-message-subject-p
- (mail-comma-list-regexp subject) whole-message))
-
-(defun rmail-message-subject-p (msg subject &optional whole-message)
- (save-restriction
- (goto-char (rmail-msgbeg msg))
- (search-forward "\n*** EOOH ***\n")
- (narrow-to-region
- (point)
- (progn (search-forward (if whole-message "\^_" "\n\n")) (point)))
- (goto-char (point-min))
- (if whole-message (re-search-forward subject nil t)
- (string-match subject (or (mail-fetch-field "Subject") "")) )))
-
-;;;###autoload
-(defun rmail-summary-by-senders (senders)
- "Display a summary of all messages with the given SENDERS.
-SENDERS is a string of names separated by commas."
- (interactive "sSenders to summarize by: ")
- (rmail-new-summary
- (concat "senders " senders)
- (list 'rmail-summary-by-senders senders)
- 'rmail-message-senders-p
- (mail-comma-list-regexp senders)))
-
-(defun rmail-message-senders-p (msg senders)
- (save-restriction
- (goto-char (rmail-msgbeg msg))
- (search-forward "\n*** EOOH ***\n")
- (narrow-to-region (point) (progn (search-forward "\n\n") (point)))
- (string-match senders (or (mail-fetch-field "From") ""))))
-
-;; General making of a summary buffer.
-
-(defvar rmail-summary-symbol-number 0)
-
-(defun rmail-new-summary (description redo-form function &rest args)
- "Create a summary of selected messages.
-DESCRIPTION makes part of the mode line of the summary buffer.
-For each message, FUNCTION is applied to the message number and ARGS...
-and if the result is non-nil, that message is included.
-nil for FUNCTION means all messages."
- (message "Computing summary lines...")
- (let (sumbuf mesg was-in-summary)
- (save-excursion
- ;; Go to the Rmail buffer.
- (if (eq major-mode 'rmail-summary-mode)
- (progn
- (setq was-in-summary t)
- (set-buffer rmail-buffer)))
- ;; Find its summary buffer, or make one.
- (setq sumbuf
- (if (and rmail-summary-buffer
- (buffer-name rmail-summary-buffer))
- rmail-summary-buffer
- (generate-new-buffer (concat (buffer-name) "-summary"))))
- (setq mesg rmail-current-message)
- ;; Filter the messages; make or get their summary lines.
- (let ((summary-msgs ())
- (new-summary-line-count 0))
- (let ((msgnum 1)
- (buffer-read-only nil)
- (old-min (point-min-marker))
- (old-max (point-max-marker)))
- ;; Can't use save-restriction here; that doesn't work if we
- ;; plan to modify text outside the original restriction.
- (save-excursion
- (widen)
- (goto-char (point-min))
- (while (>= rmail-total-messages msgnum)
- (if (or (null function)
- (apply function (cons msgnum args)))
- (setq summary-msgs
- (cons (cons msgnum (rmail-make-summary-line msgnum))
- summary-msgs)))
- (setq msgnum (1+ msgnum)))
- (setq summary-msgs (nreverse summary-msgs)))
- (narrow-to-region old-min old-max))
- ;; Temporarily, while summary buffer is unfinished,
- ;; we "don't have" a summary.
- (setq rmail-summary-buffer nil)
- (save-excursion
- (let ((rbuf (current-buffer))
- (total rmail-total-messages))
- (set-buffer sumbuf)
- ;; Set up the summary buffer's contents.
- (let ((buffer-read-only nil))
- (erase-buffer)
- (while summary-msgs
- (princ (cdr (car summary-msgs)) sumbuf)
- (setq summary-msgs (cdr summary-msgs)))
- (goto-char (point-min)))
- ;; Set up the rest of its state and local variables.
- (setq buffer-read-only t)
- (rmail-summary-mode)
- (make-local-variable 'minor-mode-alist)
- (setq minor-mode-alist (list (list t (concat ": " description))))
- (setq rmail-buffer rbuf
- rmail-summary-redo redo-form
- rmail-total-messages total))))
- (setq rmail-summary-buffer sumbuf))
- ;; Now display the summary buffer and go to the right place in it.
- (or was-in-summary
- (progn
- (if (and (one-window-p)
- pop-up-windows (not pop-up-frames))
- ;; If there is just one window, put the summary on the top.
- (progn
- (split-window (selected-window) rmail-summary-window-size)
- (select-window (next-window (frame-first-window)))
- (pop-to-buffer sumbuf)
- ;; If pop-to-buffer did not use that window, delete that
- ;; window. (This can happen if it uses another frame.)
- (if (not (eq sumbuf (window-buffer (frame-first-window))))
- (delete-other-windows)))
- (pop-to-buffer sumbuf))
- (set-buffer rmail-buffer)
- ;; This is how rmail makes the summary buffer reappear.
- ;; We do this here to make the window the proper size.
- (rmail-select-summary nil)
- (set-buffer rmail-summary-buffer)))
- (rmail-summary-goto-msg mesg t t)
- (rmail-summary-construct-io-menu)
- (message "Computing summary lines...done")))
-
-;; Low levels of generating a summary.
-
-(defun rmail-make-summary-line (msg)
- (let ((line (or (aref rmail-summary-vector (1- msg))
- (progn
- (setq new-summary-line-count
- (1+ new-summary-line-count))
- (if (zerop (% new-summary-line-count 10))
- (message "Computing summary lines...%d"
- new-summary-line-count))
- (rmail-make-summary-line-1 msg)))))
- ;; Fix up the part of the summary that says "deleted" or "unseen".
- (aset line 4
- (if (rmail-message-deleted-p msg) ?\D
- (if (= ?0 (char-after (+ 3 (rmail-msgbeg msg))))
- ?\- ?\ )))
- line))
-
-(defun rmail-make-summary-line-1 (msg)
- (goto-char (rmail-msgbeg msg))
- (let* ((lim (save-excursion (forward-line 2) (point)))
- pos
- (labels
- (progn
- (forward-char 3)
- (concat
-; (if (save-excursion (re-search-forward ",answered," lim t))
-; "*" "")
-; (if (save-excursion (re-search-forward ",filed," lim t))
-; "!" "")
- (if (progn (search-forward ",,") (eolp))
- ""
- (concat "{"
- (buffer-substring (point)
- (progn (end-of-line) (point)))
- "} ")))))
- (line
- (progn
- (forward-line 1)
- (if (looking-at "Summary-line: ")
- (progn
- (goto-char (match-end 0))
- (setq line
- (buffer-substring (point)
- (progn (forward-line 1) (point)))))))))
- ;; Obsolete status lines lacking a # should be flushed.
- (and line
- (not (string-match "#" line))
- (progn
- (delete-region (point)
- (progn (forward-line -1) (point)))
- (setq line nil)))
- ;; If we didn't get a valid status line from the message,
- ;; make a new one and put it in the message.
- (or line
- (let* ((case-fold-search t)
- (next (rmail-msgend msg))
- (beg (if (progn (goto-char (rmail-msgbeg msg))
- (search-forward "\n*** EOOH ***\n" next t))
- (point)
- (forward-line 1)
- (point)))
- (end (progn (search-forward "\n\n" nil t) (point))))
- (save-restriction
- (narrow-to-region beg end)
- (goto-char beg)
- (setq line (rmail-make-basic-summary-line)))
- (goto-char (rmail-msgbeg msg))
- (forward-line 2)
- (insert "Summary-line: " line)))
- (setq pos (string-match "#" line))
- (aset rmail-summary-vector (1- msg)
- (concat (format "%4d " msg)
- (substring line 0 pos)
- labels
- (substring line (1+ pos))))))
-
-(defun rmail-make-basic-summary-line ()
- (goto-char (point-min))
- (concat (save-excursion
- (if (not (re-search-forward "^Date:" nil t))
- " "
- (cond ((re-search-forward "\\([^0-9:]\\)\\([0-3]?[0-9]\\)\\([- \t_]+\\)\\([adfjmnos][aceopu][bcglnprtvy]\\)"
- (save-excursion (end-of-line) (point)) t)
- (format "%2d-%3s"
- (string-to-int (buffer-substring
- (match-beginning 2)
- (match-end 2)))
- (buffer-substring
- (match-beginning 4) (match-end 4))))
- ((re-search-forward "\\([^a-z]\\)\\([adfjmnos][acepou][bcglnprtvy]\\)\\([-a-z \t_]*\\)\\([0-9][0-9]?\\)"
- (save-excursion (end-of-line) (point)) t)
- (format "%2d-%3s"
- (string-to-int (buffer-substring
- (match-beginning 4)
- (match-end 4)))
- (buffer-substring
- (match-beginning 2) (match-end 2))))
- ((re-search-forward "\\(19\\|20\\)\\([0-9][0-9]\\)-\\([01][0-9]\\)-\\([0-3][0-9]\\)"
- (save-excursion (end-of-line) (point)) t)
- (format "%2s%2s%2s"
- (buffer-substring
- (match-beginning 2) (match-end 2))
- (buffer-substring
- (match-beginning 3) (match-end 3))
- (buffer-substring
- (match-beginning 4) (match-end 4))))
- (t "??????"))))
- " "
- (save-excursion
- (if (not (re-search-forward "^From:[ \t]*" nil t))
- " "
- (let* ((from (mail-strip-quoted-names
- (buffer-substring
- (1- (point))
- ;; Get all the lines of the From field
- ;; so that we get a whole comment if there is one,
- ;; so that mail-strip-quoted-names can discard it.
- (let ((opoint (point)))
- (while (progn (forward-line 1)
- (looking-at "[ \t]")))
- ;; Back up over newline, then trailing spaces or tabs
- (forward-char -1)
- (skip-chars-backward " \t")
- (point)))))
- len mch lo)
- (if (string-match (concat "^\\("
- (regexp-quote (user-login-name))
- "\\($\\|@\\)\\|"
- (regexp-quote
- ;; Don't lose if run from init file
- ;; where user-mail-address is not
- ;; set yet.
- (or user-mail-address
- (concat (user-login-name) "@"
- (or mail-host-address
- (system-name)))))
- "\\>\\)")
- from)
- (save-excursion
- (goto-char (point-min))
- (if (not (re-search-forward "^To:[ \t]*" nil t))
- nil
- (setq from
- (concat "to: "
- (mail-strip-quoted-names
- (buffer-substring
- (point)
- (progn (end-of-line)
- (skip-chars-backward " \t")
- (point)))))))))
- (setq len (length from))
- (setq mch (string-match "[@%]" from))
- (format "%25s"
- (if (or (not mch) (<= len 25))
- (substring from (max 0 (- len 25)))
- (substring from
- (setq lo (cond ((< (- mch 14) 0) 0)
- ((< len (+ mch 11))
- (- len 25))
- (t (- mch 14))))
- (min len (+ lo 25))))))))
- (if rmail-summary-line-count-flag
- (save-excursion
- (save-restriction
- (widen)
- (let ((beg (rmail-msgbeg msgnum))
- (end (rmail-msgend msgnum))
- lines)
- (save-excursion
- (goto-char beg)
- ;; Count only lines in the reformatted header,
- ;; if we have reformatted it.
- (search-forward "\n*** EOOH ***\n" end t)
- (setq lines (count-lines (point) end)))
- (format (cond
- ((<= lines 9) " [%d]")
- ((<= lines 99) " [%d]")
- ((<= lines 999) " [%3d]")
- (t "[%d]"))
- lines))))
- " ")
- " #" ;The # is part of the format.
- (if (re-search-forward "^Subject:" nil t)
- (progn (skip-chars-forward " \t")
- (buffer-substring (point)
- (progn (end-of-line)
- (point))))
- (re-search-forward "[\n][\n]+" nil t)
- (buffer-substring (point) (progn (end-of-line) (point))))
- "\n"))
-
-;; Simple motion in a summary buffer.
-
-(defun rmail-summary-next-all (&optional number)
- (interactive "p")
- (forward-line (if number number 1))
- ;; It doesn't look nice to move forward past the last message line.
- (and (eobp) (> number 0)
- (forward-line -1))
- (display-buffer rmail-buffer))
-
-(defun rmail-summary-previous-all (&optional number)
- (interactive "p")
- (forward-line (- (if number number 1)))
- ;; It doesn't look nice to move forward past the last message line.
- (and (eobp) (< number 0)
- (forward-line -1))
- (display-buffer rmail-buffer))
-
-(defun rmail-summary-next-msg (&optional number)
- "Display next non-deleted msg from rmail file.
-With optional prefix argument NUMBER, moves forward this number of non-deleted
-messages, or backward if NUMBER is negative."
- (interactive "p")
- (forward-line 0)
- (and (> number 0) (end-of-line))
- (let ((count (if (< number 0) (- number) number))
- (search (if (> number 0) 're-search-forward 're-search-backward))
- (non-del-msg-found nil))
- (while (and (> count 0) (setq non-del-msg-found
- (or (funcall search "^....[^D]" nil t)
- non-del-msg-found)))
- (setq count (1- count))))
- (beginning-of-line)
- (display-buffer rmail-buffer))
-
-(defun rmail-summary-previous-msg (&optional number)
- (interactive "p")
- (rmail-summary-next-msg (- (if number number 1))))
-
-(defun rmail-summary-next-labeled-message (n labels)
- "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: ")
- (let (msg)
- (save-excursion
- (set-buffer rmail-buffer)
- (rmail-next-labeled-message n labels)
- (setq msg rmail-current-message))
- (rmail-summary-goto-msg msg)))
-
-(defun rmail-summary-previous-labeled-message (n labels)
- "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: ")
- (let (msg)
- (save-excursion
- (set-buffer rmail-buffer)
- (rmail-previous-labeled-message n labels)
- (setq msg rmail-current-message))
- (rmail-summary-goto-msg msg)))
-
-(defun rmail-summary-next-same-subject (n)
- "Go to the next message in the summary having the same subject.
-With prefix argument N, do this N times.
-If N is negative, go backwards."
- (interactive "p")
- (let (subject search-regexp i found
- (forward (> n 0)))
- (save-excursion
- (set-buffer rmail-buffer)
- (setq subject (mail-fetch-field "Subject"))
- (setq i rmail-current-message))
- (if (string-match "Re:[ \t]*" subject)
- (setq subject (substring subject (match-end 0))))
- (setq search-regexp (concat "^Subject: *\\(Re: *\\)?"
- (regexp-quote subject)
- "\n"))
- (save-excursion
- (while (and (/= n 0)
- (if forward
- (not (eobp))
- (not (bobp))))
- (let (done)
- (while (and (not done)
- (if forward
- (not (eobp))
- (not (bobp))))
- ;; Advance thru summary.
- (forward-line (if forward 1 -1))
- ;; Get msg number of this line.
- (setq i (string-to-int
- (buffer-substring (point)
- (min (point-max) (+ 5 (point))))))
- ;; See if that msg has desired subject.
- (save-excursion
- (set-buffer rmail-buffer)
- (save-restriction
- (widen)
- (goto-char (rmail-msgbeg i))
- (search-forward "\n*** EOOH ***\n")
- (let ((beg (point)) end)
- (search-forward "\n\n")
- (setq end (point))
- (goto-char beg)
- (setq done (re-search-forward search-regexp end t))))))
- (if done (setq found i)))
- (setq n (if forward (1- n) (1+ n)))))
- (if found
- (rmail-summary-goto-msg found)
- (error "No %s message with same subject"
- (if forward "following" "previous")))))
-
-(defun rmail-summary-previous-same-subject (n)
- "Go to the previous message in the summary having the same subject.
-With prefix argument N, do this N times.
-If N is negative, go forwards instead."
- (interactive "p")
- (rmail-summary-next-same-subject (- n)))
-
-;; Delete and undelete summary commands.
-
-(defun rmail-summary-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")
- (let (end)
- (rmail-summary-goto-msg)
- (pop-to-buffer rmail-buffer)
- (rmail-delete-message)
- (let ((del-msg rmail-current-message))
- (pop-to-buffer rmail-summary-buffer)
- (rmail-summary-mark-deleted del-msg)
- (while (and (not (if backward (bobp) (eobp)))
- (save-excursion (beginning-of-line)
- (looking-at " *[0-9]+D")))
- (forward-line (if backward -1 1)))
- ;; It looks ugly to move to the empty line at end of buffer.
- (and (eobp) (not backward)
- (forward-line -1)))))
-
-(defun rmail-summary-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-summary-delete-forward t))
-
-(defun rmail-summary-mark-deleted (&optional n undel)
- ;; Since third arg is t, this only alters the summary, not the Rmail buf.
- (and n (rmail-summary-goto-msg n t t))
- (or (eobp)
- (not (overlay-get rmail-summary-overlay 'face))
- (let ((buffer-read-only nil))
- (skip-chars-forward " ")
- (skip-chars-forward "[0-9]")
- (if undel
- (if (looking-at "D")
- (progn (delete-char 1) (insert " ")))
- (delete-char 1)
- (insert "D"))))
- (beginning-of-line))
-
-(defun rmail-summary-mark-undeleted (n)
- (rmail-summary-mark-deleted n t))
-
-(defun rmail-summary-deleted-p (&optional n)
- (save-excursion
- (and n (rmail-summary-goto-msg n nil t))
- (skip-chars-forward " ")
- (skip-chars-forward "[0-9]")
- (looking-at "D")))
-
-(defun rmail-summary-undelete (&optional arg)
- "Undelete current message.
-Optional prefix ARG means undelete ARG previous messages."
- (interactive "p")
- (if (/= arg 1)
- (rmail-summary-undelete-many arg)
- (let ((buffer-read-only nil)
- (opoint (point)))
- (end-of-line)
- (cond ((re-search-backward "\\(^ *[0-9]*\\)\\(D\\)" nil t)
- (replace-match "\\1 ")
- (rmail-summary-goto-msg)
- (pop-to-buffer rmail-buffer)
- (and (rmail-message-deleted-p rmail-current-message)
- (rmail-undelete-previous-message))
- (pop-to-buffer rmail-summary-buffer))
- (t (goto-char opoint))))))
-
-(defun rmail-summary-undelete-many (&optional n)
- "Undelete all deleted msgs, optional prefix arg N means undelete N prev msgs."
- (interactive "P")
- (save-excursion
- (set-buffer rmail-buffer)
- (let* ((init-msg (if n rmail-current-message rmail-total-messages))
- (rmail-current-message init-msg)
- (n (or n rmail-total-messages))
- (msgs-undeled 0))
- (while (and (> rmail-current-message 0)
- (< msgs-undeled n))
- (if (rmail-message-deleted-p rmail-current-message)
- (progn (rmail-set-attribute "deleted" nil)
- (setq msgs-undeled (1+ msgs-undeled))))
- (setq rmail-current-message (1- rmail-current-message)))
- (set-buffer rmail-summary-buffer)
- (setq rmail-current-message init-msg msgs-undeled 0)
- (while (and (> rmail-current-message 0)
- (< msgs-undeled n))
- (if (rmail-summary-deleted-p rmail-current-message)
- (progn (rmail-summary-mark-undeleted rmail-current-message)
- (setq msgs-undeled (1+ msgs-undeled))))
- (setq rmail-current-message (1- rmail-current-message))))
- (rmail-summary-goto-msg)))
-
-;; Rmail Summary mode is suitable only for specially formatted data.
-(put 'rmail-summary-mode 'mode-class 'special)
-
-(defun rmail-summary-mode ()
- "Rmail Summary Mode is invoked from Rmail Mode by using \\<rmail-mode-map>\\[rmail-summary].
-As commands are issued in the summary buffer, they are applied to the
-corresponding mail messages in the rmail buffer.
-
-All normal editing commands are turned off.
-Instead, nearly all the Rmail mode commands are available,
-though many of them move only among the messages in the summary.
-
-These additional commands exist:
-
-\\[rmail-summary-undelete-many] Undelete all or prefix arg deleted messages.
-\\[rmail-summary-wipe] Delete the summary and go to the Rmail buffer.
-
-Commands for sorting the summary:
-
-\\[rmail-summary-sort-by-date] Sort by date.
-\\[rmail-summary-sort-by-subject] Sort by subject.
-\\[rmail-summary-sort-by-author] Sort by author.
-\\[rmail-summary-sort-by-recipient] Sort by recipient.
-\\[rmail-summary-sort-by-correspondent] Sort by correspondent.
-\\[rmail-summary-sort-by-lines] Sort by lines.
-\\[rmail-summary-sort-by-keywords] Sort by keywords."
- (interactive)
- (kill-all-local-variables)
- (setq major-mode 'rmail-summary-mode)
- (setq mode-name "RMAIL Summary")
- (setq truncate-lines t)
- (setq buffer-read-only t)
- (set-syntax-table text-mode-syntax-table)
- (make-local-variable 'rmail-buffer)
- (make-local-variable 'rmail-total-messages)
- (make-local-variable 'rmail-current-message)
- (setq rmail-current-message nil)
- (make-local-variable 'rmail-summary-redo)
- (setq rmail-summary-redo nil)
- (make-local-variable 'revert-buffer-function)
- (make-local-hook 'post-command-hook)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(rmail-summary-font-lock-keywords t))
- (rmail-summary-enable)
- (run-hooks 'rmail-summary-mode-hook))
-
-;; Summary features need to be disabled during edit mode.
-(defun rmail-summary-disable ()
- (use-local-map text-mode-map)
- (remove-hook 'post-command-hook 'rmail-summary-rmail-update t)
- (setq revert-buffer-function nil))
-
-(defun rmail-summary-enable ()
- (use-local-map rmail-summary-mode-map)
- (add-hook 'post-command-hook 'rmail-summary-rmail-update nil t)
- (setq revert-buffer-function 'rmail-update-summary))
-
-(defvar rmail-summary-put-back-unseen nil
- "Used for communicating between calls to `rmail-summary-rmail-update'.
-If it moves to a message within an Incremental Search, and removes
-the `unseen' attribute from that message, it sets this flag
-so that if the next motion between messages is in the same Incremental
-Search, the `unseen' attribute is restored.")
-
-;; Show in Rmail the message described by the summary line that point is on,
-;; but only if the Rmail buffer is already visible.
-;; This is a post-command-hook in summary buffers.
-(defun rmail-summary-rmail-update ()
- (let (buffer-read-only)
- (save-excursion
- ;; If at end of buffer, pretend we are on the last text line.
- (if (eobp)
- (forward-line -1))
- (beginning-of-line)
- (skip-chars-forward " ")
- (let ((msg-num (string-to-int (buffer-substring
- (point)
- (progn (skip-chars-forward "0-9")
- (point))))))
- ;; Always leave `unseen' removed
- ;; if we get out of isearch mode.
- ;; Don't let a subsequent isearch restore that `unseen'.
- (if (not isearch-mode)
- (setq rmail-summary-put-back-unseen nil))
-
- (or (eq rmail-current-message msg-num)
- (let ((window (get-buffer-window rmail-buffer))
- (owin (selected-window)))
- (if isearch-mode
- (save-excursion
- (set-buffer rmail-buffer)
- ;; If we first saw the previous message in this search,
- ;; and we have gone to a different message while searching,
- ;; put back `unseen' on the former one.
- (rmail-set-attribute "unseen" t
- rmail-current-message)
- ;; Arrange to do that later, for the new current message,
- ;; if it still has `unseen'.
- (setq rmail-summary-put-back-unseen
- (rmail-message-labels-p msg-num ", ?\\(unseen\\),")))
- (setq rmail-summary-put-back-unseen nil))
-
- ;; Go to the desired message.
- (setq rmail-current-message msg-num)
-
- ;; Update the summary to show the message has been seen.
- (if (= (following-char) ?-)
- (progn
- (delete-char 1)
- (insert " ")))
-
- (if window
- ;; Using save-window-excursion would cause the new value
- ;; of point to get lost.
- (unwind-protect
- (progn
- (select-window window)
- (rmail-show-message msg-num t))
- (select-window owin))
- (if (buffer-name rmail-buffer)
- (save-excursion
- (set-buffer rmail-buffer)
- (rmail-show-message msg-num t))))))
- (rmail-summary-update-highlight nil)))))
-
-(defvar rmail-summary-mode-map nil)
-
-(if rmail-summary-mode-map
- nil
- (setq rmail-summary-mode-map (make-keymap))
- (suppress-keymap rmail-summary-mode-map)
- (define-key rmail-summary-mode-map "a" 'rmail-summary-add-label)
- (define-key rmail-summary-mode-map "b" 'rmail-summary-bury)
- (define-key rmail-summary-mode-map "c" 'rmail-summary-continue)
- (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 "e" 'rmail-summary-edit-current-message)
- (define-key rmail-summary-mode-map "f" 'rmail-summary-forward)
- (define-key rmail-summary-mode-map "g" 'rmail-summary-get-new-mail)
- (define-key rmail-summary-mode-map "h" 'rmail-summary)
- (define-key rmail-summary-mode-map "i" 'rmail-summary-input)
- (define-key rmail-summary-mode-map "j" 'rmail-summary-goto-msg)
- (define-key rmail-summary-mode-map "k" 'rmail-summary-kill-label)
- (define-key rmail-summary-mode-map "l" 'rmail-summary-by-labels)
- (define-key rmail-summary-mode-map "\e\C-h" 'rmail-summary)
- (define-key rmail-summary-mode-map "\e\C-l" 'rmail-summary-by-labels)
- (define-key rmail-summary-mode-map "\e\C-r" 'rmail-summary-by-recipients)
- (define-key rmail-summary-mode-map "\e\C-s" 'rmail-summary-by-regexp)
- (define-key rmail-summary-mode-map "\e\C-t" 'rmail-summary-by-topic)
- (define-key rmail-summary-mode-map "m" 'rmail-summary-mail)
- (define-key rmail-summary-mode-map "\M-m" 'rmail-summary-retry-failure)
- (define-key rmail-summary-mode-map "n" 'rmail-summary-next-msg)
- (define-key rmail-summary-mode-map "\en" 'rmail-summary-next-all)
- (define-key rmail-summary-mode-map "\e\C-n" 'rmail-summary-next-labeled-message)
- (define-key rmail-summary-mode-map "o" 'rmail-summary-output-to-rmail-file)
- (define-key rmail-summary-mode-map "\C-o" 'rmail-summary-output)
- (define-key rmail-summary-mode-map "p" 'rmail-summary-previous-msg)
- (define-key rmail-summary-mode-map "\ep" 'rmail-summary-previous-all)
- (define-key rmail-summary-mode-map "\e\C-p" 'rmail-summary-previous-labeled-message)
- (define-key rmail-summary-mode-map "q" 'rmail-summary-quit)
- (define-key rmail-summary-mode-map "r" 'rmail-summary-reply)
- (define-key rmail-summary-mode-map "s" 'rmail-summary-expunge-and-save)
- (define-key rmail-summary-mode-map "\es" 'rmail-summary-search)
- (define-key rmail-summary-mode-map "t" 'rmail-summary-toggle-header)
- (define-key rmail-summary-mode-map "u" 'rmail-summary-undelete)
- (define-key rmail-summary-mode-map "\M-u" 'rmail-summary-undelete-many)
- (define-key rmail-summary-mode-map "w" 'rmail-summary-wipe)
- (define-key rmail-summary-mode-map "x" 'rmail-summary-expunge)
- (define-key rmail-summary-mode-map "." 'rmail-summary-beginning-of-message)
- (define-key rmail-summary-mode-map "<" 'rmail-summary-first-message)
- (define-key rmail-summary-mode-map ">" 'rmail-summary-last-message)
- (define-key rmail-summary-mode-map " " 'rmail-summary-scroll-msg-up)
- (define-key rmail-summary-mode-map "\177" 'rmail-summary-scroll-msg-down)
- (define-key rmail-summary-mode-map "?" 'describe-mode)
- (define-key rmail-summary-mode-map "\C-c\C-n" 'rmail-summary-next-same-subject)
- (define-key rmail-summary-mode-map "\C-c\C-p" 'rmail-summary-previous-same-subject)
- (define-key rmail-summary-mode-map "\C-c\C-s\C-d"
- 'rmail-summary-sort-by-date)
- (define-key rmail-summary-mode-map "\C-c\C-s\C-s"
- 'rmail-summary-sort-by-subject)
- (define-key rmail-summary-mode-map "\C-c\C-s\C-a"
- 'rmail-summary-sort-by-author)
- (define-key rmail-summary-mode-map "\C-c\C-s\C-r"
- 'rmail-summary-sort-by-recipient)
- (define-key rmail-summary-mode-map "\C-c\C-s\C-c"
- 'rmail-summary-sort-by-correspondent)
- (define-key rmail-summary-mode-map "\C-c\C-s\C-l"
- 'rmail-summary-sort-by-lines)
- (define-key rmail-summary-mode-map "\C-c\C-s\C-k"
- 'rmail-summary-sort-by-keywords)
- )
-
-;;; Menu bar bindings.
-
-(define-key rmail-summary-mode-map [menu-bar] (make-sparse-keymap))
-
-(define-key rmail-summary-mode-map [menu-bar classify]
- (cons "Classify" (make-sparse-keymap "Classify")))
-
-(define-key rmail-summary-mode-map [menu-bar classify output-menu]
- '("Output (Rmail Menu)..." . rmail-summary-output-menu))
-
-(define-key rmail-summary-mode-map [menu-bar classify input-menu]
- '("Input Rmail File (menu)..." . rmail-input-menu))
-
-(define-key rmail-summary-mode-map [menu-bar classify input-menu]
- '(nil))
-
-(define-key rmail-summary-mode-map [menu-bar classify output-menu]
- '(nil))
-
-(define-key rmail-summary-mode-map [menu-bar classify output-inbox]
- '("Output (inbox)..." . rmail-summary-output))
-
-(define-key rmail-summary-mode-map [menu-bar classify output]
- '("Output (Rmail)..." . rmail-summary-output-to-rmail-file))
-
-(define-key rmail-summary-mode-map [menu-bar classify kill-label]
- '("Kill Label..." . rmail-summary-kill-label))
-
-(define-key rmail-summary-mode-map [menu-bar classify add-label]
- '("Add Label..." . rmail-summary-add-label))
-
-(define-key rmail-summary-mode-map [menu-bar summary]
- (cons "Summary" (make-sparse-keymap "Summary")))
-
-(define-key rmail-summary-mode-map [menu-bar summary senders]
- '("By Senders..." . rmail-summary-by-senders))
-
-(define-key rmail-summary-mode-map [menu-bar summary labels]
- '("By Labels..." . rmail-summary-by-labels))
-
-(define-key rmail-summary-mode-map [menu-bar summary recipients]
- '("By Recipients..." . rmail-summary-by-recipients))
-
-(define-key rmail-summary-mode-map [menu-bar summary topic]
- '("By Topic..." . rmail-summary-by-topic))
-
-(define-key rmail-summary-mode-map [menu-bar summary regexp]
- '("By Regexp..." . rmail-summary-by-regexp))
-
-(define-key rmail-summary-mode-map [menu-bar summary all]
- '("All" . rmail-summary))
-
-(define-key rmail-summary-mode-map [menu-bar mail]
- (cons "Mail" (make-sparse-keymap "Mail")))
-
-(define-key rmail-summary-mode-map [menu-bar mail rmail-summary-get-new-mail]
- '("Get New Mail" . rmail-summary-get-new-mail))
-
-(define-key rmail-summary-mode-map [menu-bar mail lambda]
- '("----"))
-
-(define-key rmail-summary-mode-map [menu-bar mail continue]
- '("Continue" . rmail-summary-continue))
-
-(define-key rmail-summary-mode-map [menu-bar mail resend]
- '("Re-send..." . rmail-summary-resend))
-
-(define-key rmail-summary-mode-map [menu-bar mail forward]
- '("Forward" . rmail-summary-forward))
-
-(define-key rmail-summary-mode-map [menu-bar mail retry]
- '("Retry" . rmail-summary-retry-failure))
-
-(define-key rmail-summary-mode-map [menu-bar mail reply]
- '("Reply" . rmail-summary-reply))
-
-(define-key rmail-summary-mode-map [menu-bar mail mail]
- '("Mail" . rmail-summary-mail))
-
-(define-key rmail-summary-mode-map [menu-bar delete]
- (cons "Delete" (make-sparse-keymap "Delete")))
-
-(define-key rmail-summary-mode-map [menu-bar delete expunge/save]
- '("Expunge/Save" . rmail-summary-expunge-and-save))
-
-(define-key rmail-summary-mode-map [menu-bar delete expunge]
- '("Expunge" . rmail-summary-expunge))
-
-(define-key rmail-summary-mode-map [menu-bar delete undelete]
- '("Undelete" . rmail-summary-undelete))
-
-(define-key rmail-summary-mode-map [menu-bar delete delete]
- '("Delete" . rmail-summary-delete-forward))
-
-(define-key rmail-summary-mode-map [menu-bar move]
- (cons "Move" (make-sparse-keymap "Move")))
-
-(define-key rmail-summary-mode-map [menu-bar move search-back]
- '("Search Back..." . rmail-summary-search-backward))
-
-(define-key rmail-summary-mode-map [menu-bar move search]
- '("Search..." . rmail-summary-search))
-
-(define-key rmail-summary-mode-map [menu-bar move previous]
- '("Previous Nondeleted" . rmail-summary-previous-msg))
-
-(define-key rmail-summary-mode-map [menu-bar move next]
- '("Next Nondeleted" . rmail-summary-next-msg))
-
-(define-key rmail-summary-mode-map [menu-bar move last]
- '("Last" . rmail-summary-last-message))
-
-(define-key rmail-summary-mode-map [menu-bar move first]
- '("First" . rmail-summary-first-message))
-
-(define-key rmail-summary-mode-map [menu-bar move previous]
- '("Previous" . rmail-summary-previous-all))
-
-(define-key rmail-summary-mode-map [menu-bar move next]
- '("Next" . rmail-summary-next-all))
-
-(defvar rmail-summary-overlay nil)
-(put 'rmail-summary-overlay 'permanent-local t)
-
-;; Go to message N in the summary buffer which is current,
-;; and in the corresponding Rmail buffer.
-;; If N is nil, use the message corresponding to point in the summary
-;; and move to that message in the Rmail buffer.
-
-;; If NOWARN, don't say anything if N is out of range.
-;; If SKIP-RMAIL, don't do anything to the Rmail buffer.
-
-(defun rmail-summary-goto-msg (&optional n nowarn skip-rmail)
- (interactive "P")
- (if (consp n) (setq n (prefix-numeric-value n)))
- (if (eobp) (forward-line -1))
- (beginning-of-line)
- (let* ((obuf (current-buffer))
- (buf rmail-buffer)
- (cur (point))
- message-not-found
- (curmsg (string-to-int
- (buffer-substring (point)
- (min (point-max) (+ 5 (point))))))
- (total (save-excursion (set-buffer buf) rmail-total-messages)))
- ;; If message number N was specified, find that message's line
- ;; or set message-not-found.
- ;; If N wasn't specified or that message can't be found.
- ;; set N by default.
- (if (not n)
- (setq n curmsg)
- (if (< n 1)
- (progn (message "No preceding message")
- (setq n 1)))
- (if (> n total)
- (progn (message "No following message")
- (goto-char (point-max))
- (rmail-summary-goto-msg nil nowarn skip-rmail)))
- (goto-char (point-min))
- (if (not (re-search-forward (format "^%4d[^0-9]" n) nil t))
- (progn (or nowarn (message "Message %d not found" n))
- (setq n curmsg)
- (setq message-not-found t)
- (goto-char cur))))
- (beginning-of-line)
- (skip-chars-forward " ")
- (skip-chars-forward "0-9")
- (save-excursion (if (= (following-char) ?-)
- (let ((buffer-read-only nil))
- (delete-char 1)
- (insert " "))))
- (rmail-summary-update-highlight message-not-found)
- (beginning-of-line)
- (if skip-rmail
- nil
- (let ((selwin (selected-window)))
- (unwind-protect
- (progn (pop-to-buffer buf)
- (rmail-show-message n))
- (select-window selwin)
- ;; The actions above can alter the current buffer. Preserve it.
- (set-buffer obuf))))))
-
-;; Update the highlighted line in an rmail summary buffer.
-;; That should be current. We highlight the line point is on.
-;; If NOT-FOUND is non-nil, we turn off highlighting.
-(defun rmail-summary-update-highlight (not-found)
- ;; Make sure we have an overlay to use.
- (or rmail-summary-overlay
- (progn
- (make-local-variable 'rmail-summary-overlay)
- (setq rmail-summary-overlay (make-overlay (point) (point)))))
- ;; If this message is in the summary, use the overlay to highlight it.
- ;; Otherwise, don't highlight anything.
- (if not-found
- (overlay-put rmail-summary-overlay 'face nil)
- (move-overlay rmail-summary-overlay
- (save-excursion (beginning-of-line)
- (skip-chars-forward " ")
- (point))
- (save-excursion (end-of-line) (point)))
- (overlay-put rmail-summary-overlay 'face 'highlight)))
-
-(defun rmail-summary-scroll-msg-up (&optional dist)
- "Scroll the Rmail window forward.
-If the Rmail window is displaying the end of a message,
-advance to the next message."
- (interactive "P")
- (if (eq dist '-)
- (rmail-summary-scroll-msg-down nil)
- (let ((rmail-buffer-window (get-buffer-window rmail-buffer)))
- (if rmail-buffer-window
- (if (let ((rmail-summary-window (selected-window)))
- (select-window rmail-buffer-window)
- (prog1
- ;; Is EOB visible in the buffer?
- (save-excursion
- (let ((ht (window-height (selected-window))))
- (move-to-window-line (- ht 2))
- (end-of-line)
- (eobp)))
- (select-window rmail-summary-window)))
- (if (not rmail-summary-scroll-between-messages)
- (error "End of buffer")
- (rmail-summary-next-msg (or dist 1)))
- (let ((other-window-scroll-buffer rmail-buffer))
- (scroll-other-window dist)))
- ;; If it isn't visible at all, show the beginning.
- (rmail-summary-beginning-of-message)))))
-
-(defun rmail-summary-scroll-msg-down (&optional dist)
- "Scroll the Rmail window backward.
-If the Rmail window is now displaying the beginning of a message,
-move to the previous message."
- (interactive "P")
- (if (eq dist '-)
- (rmail-summary-scroll-msg-up nil)
- (let ((rmail-buffer-window (get-buffer-window rmail-buffer)))
- (if rmail-buffer-window
- (if (let ((rmail-summary-window (selected-window)))
- (select-window rmail-buffer-window)
- (prog1
- ;; Is BOB visible in the buffer?
- (save-excursion
- (move-to-window-line 0)
- (beginning-of-line)
- (bobp))
- (select-window rmail-summary-window)))
- (if (not rmail-summary-scroll-between-messages)
- (error "Beginning of buffer")
- (rmail-summary-previous-msg (or dist 1)))
- (let ((other-window-scroll-buffer rmail-buffer))
- (scroll-other-window-down dist)))
- ;; If it isn't visible at all, show the beginning.
- (rmail-summary-beginning-of-message)))))
-
-(defun rmail-summary-beginning-of-message ()
- "Show current message from the beginning."
- (interactive)
- (if (and (one-window-p) (not pop-up-frames))
- ;; If there is just one window, put the summary on the top.
- (let ((buffer rmail-buffer))
- (split-window (selected-window) rmail-summary-window-size)
- (select-window (frame-first-window))
- (pop-to-buffer rmail-buffer)
- ;; If pop-to-buffer did not use that window, delete that
- ;; window. (This can happen if it uses another frame.)
- (or (eq buffer (window-buffer (next-window (frame-first-window))))
- (delete-other-windows)))
- (pop-to-buffer rmail-buffer))
- (beginning-of-buffer)
- (pop-to-buffer rmail-summary-buffer))
-
-(defun rmail-summary-bury ()
- "Bury the Rmail buffer and the Rmail summary buffer."
- (interactive)
- (let ((buffer-to-bury (current-buffer)))
- (let (window)
- (while (setq window (get-buffer-window rmail-buffer))
- (set-window-buffer window (other-buffer rmail-buffer)))
- (bury-buffer rmail-buffer))
- (switch-to-buffer (other-buffer buffer-to-bury))
- (bury-buffer buffer-to-bury)))
-
-(defun rmail-summary-quit ()
- "Quit out of Rmail and Rmail summary."
- (interactive)
- (rmail-summary-wipe)
- (rmail-quit))
-
-(defun rmail-summary-wipe ()
- "Kill and wipe away Rmail summary, remaining within Rmail."
- (interactive)
- (save-excursion (set-buffer rmail-buffer) (setq rmail-summary-buffer nil))
- (let ((local-rmail-buffer rmail-buffer))
- (kill-buffer (current-buffer))
- ;; Delete window if not only one.
- (if (not (eq (selected-window) (next-window nil 'no-minibuf)))
- (delete-window))
- ;; Switch windows to the rmail buffer, or switch to it in this window.
- (pop-to-buffer local-rmail-buffer)))
-
-(defun rmail-summary-expunge ()
- "Actually erase all deleted messages and recompute summary headers."
- (interactive)
- (save-excursion
- (set-buffer rmail-buffer)
- (rmail-only-expunge))
- (rmail-update-summary))
-
-(defun rmail-summary-expunge-and-save ()
- "Expunge and save RMAIL file."
- (interactive)
- (save-excursion
- (set-buffer rmail-buffer)
- (rmail-only-expunge))
- (rmail-update-summary)
- (save-excursion
- (set-buffer rmail-buffer)
- (save-buffer))
- (set-buffer-modified-p nil))
-
-(defun rmail-summary-get-new-mail ()
- "Get new mail and recompute summary headers."
- (interactive)
- (let (msg)
- (save-excursion
- (set-buffer rmail-buffer)
- (rmail-get-new-mail)
- ;; Get the proper new message number.
- (setq msg rmail-current-message))
- ;; Make sure that message is displayed.
- (or (zerop msg)
- (rmail-summary-goto-msg msg))))
-
-(defun rmail-summary-input (filename)
- "Run Rmail on file FILENAME."
- (interactive "FRun rmail on RMAIL file: ")
- ;; We switch windows here, then display the other Rmail file there.
- (pop-to-buffer rmail-buffer)
- (rmail filename))
-
-(defun rmail-summary-first-message ()
- "Show first message in Rmail file from summary buffer."
- (interactive)
- (beginning-of-buffer))
-
-(defun rmail-summary-last-message ()
- "Show last message in Rmail file from summary buffer."
- (interactive)
- (end-of-buffer)
- (forward-line -1))
-
-(defvar rmail-summary-edit-map nil)
-(if rmail-summary-edit-map
- nil
- (setq rmail-summary-edit-map
- (nconc (make-sparse-keymap) text-mode-map))
- (define-key rmail-summary-edit-map "\C-c\C-c" 'rmail-cease-edit)
- (define-key rmail-summary-edit-map "\C-c\C-]" 'rmail-abort-edit))
-
-(defun rmail-summary-edit-current-message ()
- "Edit the contents of this message."
- (interactive)
- (pop-to-buffer rmail-buffer)
- (rmail-edit-current-message)
- (use-local-map rmail-summary-edit-map))
-
-(defun rmail-summary-cease-edit ()
- "Finish editing message, then go back to Rmail summary buffer."
- (interactive)
- (rmail-cease-edit)
- (pop-to-buffer rmail-summary-buffer))
-
-(defun rmail-summary-abort-edit ()
- "Abort edit of current message; restore original contents.
-Go back to summary buffer."
- (interactive)
- (rmail-abort-edit)
- (pop-to-buffer rmail-summary-buffer))
-
-(defun rmail-summary-search-backward (regexp &optional n)
- "Show message containing next match for REGEXP.
-Prefix argument gives repeat count; negative argument means search
-backwards (through earlier messages).
-Interactively, empty argument means use same regexp used last time."
- (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
- (prefix-numeric-value current-prefix-arg))))
- ;; Don't use save-excursion because that prevents point from moving
- ;; properly in the summary buffer.
- (let ((buffer (current-buffer)))
- (unwind-protect
- (progn
- (set-buffer rmail-buffer)
- (rmail-search regexp (- n)))
- (set-buffer buffer))))
-
-(defun rmail-summary-search (regexp &optional n)
- "Show message containing next match for REGEXP.
-Prefix argument gives repeat count; negative argument means search
-backwards (through earlier messages).
-Interactively, empty argument means use same regexp used last time."
- (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
- (prefix-numeric-value current-prefix-arg))))
- ;; Don't use save-excursion because that prevents point from moving
- ;; properly in the summary buffer.
- (let ((buffer (current-buffer)))
- (unwind-protect
- (progn
- (set-buffer rmail-buffer)
- (rmail-search regexp n))
- (set-buffer buffer))))
-
-(defun rmail-summary-toggle-header ()
- "Show original message header if pruned header currently shown, or vice versa."
- (interactive)
- (save-excursion
- (set-buffer rmail-buffer)
- (rmail-toggle-header))
- ;; Inside save-excursion, some changes to point in the RMAIL buffer are lost.
- ;; Set point to point-min in the RMAIL buffer, if it is visible.
- (let ((window (get-buffer-window rmail-buffer)))
- (if window
- ;; Using save-window-excursion would lose the new value of point.
- (let ((owin (selected-window)))
- (unwind-protect
- (progn
- (select-window window)
- (goto-char (point-min)))
- (select-window owin))))))
-
-
-(defun rmail-summary-add-label (label)
- "Add LABEL to labels associated with current Rmail message.
-Completion is performed over known labels when reading."
- (interactive (list (save-excursion
- (set-buffer rmail-buffer)
- (rmail-read-label "Add label"))))
- (save-excursion
- (set-buffer rmail-buffer)
- (rmail-add-label label)))
-
-(defun rmail-summary-kill-label (label)
- "Remove LABEL from labels associated with current Rmail message.
-Completion is performed over known labels when reading."
- (interactive (list (save-excursion
- (set-buffer rmail-buffer)
- (rmail-read-label "Kill label"))))
- (save-excursion
- (set-buffer rmail-buffer)
- (rmail-set-label label nil)))
-
-;;;; *** Rmail Summary Mailing Commands ***
-
-(defun rmail-summary-mail ()
- "Send mail in another window.
-While composing the message, use \\[mail-yank-original] to yank the
-original message into it."
- (interactive)
- (let ((window (get-buffer-window rmail-buffer)))
- (if window
- (select-window window)
- (set-buffer rmail-buffer)))
- (rmail-start-mail nil nil nil nil nil (current-buffer))
- (use-local-map (copy-keymap (current-local-map)))
- (define-key (current-local-map)
- "\C-c\C-c" 'rmail-summary-send-and-exit))
-
-(defun rmail-summary-continue ()
- "Continue composing outgoing message previously being composed."
- (interactive)
- (let ((window (get-buffer-window rmail-buffer)))
- (if window
- (select-window window)
- (set-buffer rmail-buffer)))
- (rmail-start-mail t))
-
-(defun rmail-summary-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")
- (let ((window (get-buffer-window rmail-buffer)))
- (if window
- (select-window window)
- (set-buffer rmail-buffer)))
- (rmail-reply just-sender)
- (use-local-map (copy-keymap (current-local-map)))
- (define-key (current-local-map)
- "\C-c\C-c" 'rmail-summary-send-and-exit))
-
-(defun rmail-summary-retry-failure ()
- "Edit a mail message which is based on the contents of the current message.
-For a message rejected by the mail system, extract the interesting headers and
-the body of the original message; otherwise copy the current message."
- (interactive)
- (let ((window (get-buffer-window rmail-buffer)))
- (if window
- (select-window window)
- (set-buffer rmail-buffer)))
- (rmail-retry-failure)
- (use-local-map (copy-keymap (current-local-map)))
- (define-key (current-local-map)
- "\C-c\C-c" 'rmail-summary-send-and-exit))
-
-(defun rmail-summary-send-and-exit ()
- "Send mail reply and return to summary buffer."
- (interactive)
- (mail-send-and-exit t))
-
-(defun rmail-summary-forward (resend)
- "Forward the current message to another user.
-With prefix argument, \"resend\" the message instead of forwarding it;
-see the documentation of `rmail-resend'."
- (interactive "P")
- (save-excursion
- (let ((window (get-buffer-window rmail-buffer)))
- (if window
- (select-window window)
- (set-buffer rmail-buffer)))
- (rmail-forward resend)
- (use-local-map (copy-keymap (current-local-map)))
- (define-key (current-local-map)
- "\C-c\C-c" 'rmail-summary-send-and-exit)))
-
-(defun rmail-summary-resend ()
- "Resend current message using 'rmail-resend'."
- (interactive)
- (save-excursion
- (let ((window (get-buffer-window rmail-buffer)))
- (if window
- (select-window window)
- (set-buffer rmail-buffer)))
- (call-interactively 'rmail-resend)))
-
-;; Summary output commands.
-
-(defun rmail-summary-output-to-rmail-file (&optional 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)
- (save-excursion
- (set-buffer rmail-buffer)
- (let ((rmail-delete-after-output nil))
- (if file-name
- (rmail-output-to-rmail-file file-name)
- (call-interactively 'rmail-output-to-rmail-file))))
- (if rmail-delete-after-output
- (rmail-summary-delete-forward nil)))
-
-(defun rmail-summary-output-menu ()
- "Output current message to another Rmail file, chosen with a menu.
-Also set the default for subsequent \\[rmail-output-to-rmail-file] commands.
-The variables `rmail-secondary-file-directory' and
-`rmail-secondary-file-regexp' control which files are offered in the menu."
- (interactive)
- (save-excursion
- (set-buffer rmail-buffer)
- (let ((rmail-delete-after-output nil))
- (call-interactively 'rmail-output-menu)))
- (if rmail-delete-after-output
- (rmail-summary-delete-forward nil)))
-
-(defun rmail-summary-output ()
- "Append this message to Unix mail file named FILE-NAME."
- (interactive)
- (save-excursion
- (set-buffer rmail-buffer)
- (let ((rmail-delete-after-output nil))
- (call-interactively 'rmail-output)))
- (if rmail-delete-after-output
- (rmail-summary-delete-forward nil)))
-
-(defun rmail-summary-construct-io-menu ()
- (let ((files (rmail-find-all-files rmail-secondary-file-directory)))
- (if files
- (progn
- (define-key rmail-summary-mode-map [menu-bar classify input-menu]
- (cons "Input Rmail File"
- (rmail-list-to-menu "Input Rmail File"
- files
- 'rmail-summary-input)))
- (define-key rmail-summary-mode-map [menu-bar classify output-menu]
- (cons "Output Rmail File"
- (rmail-list-to-menu "Output Rmail File"
- files
- 'rmail-summary-output-to-rmail-file))))
- (define-key rmail-summary-mode-map [menu-bar classify input-menu]
- '("Input Rmail File" . rmail-disable-menu))
- (define-key rmail-summary-mode-map [menu-bar classify output-menu]
- '("Output Rmail File" . rmail-disable-menu)))))
-
-
-;; Sorting messages in Rmail Summary buffer.
-
-(defun rmail-summary-sort-by-date (reverse)
- "Sort messages of current Rmail summary by date.
-If prefix argument REVERSE is non-nil, sort them in reverse order."
- (interactive "P")
- (rmail-sort-from-summary (function rmail-sort-by-date) reverse))
-
-(defun rmail-summary-sort-by-subject (reverse)
- "Sort messages of current Rmail summary by subject.
-If prefix argument REVERSE is non-nil, sort them in reverse order."
- (interactive "P")
- (rmail-sort-from-summary (function rmail-sort-by-subject) reverse))
-
-(defun rmail-summary-sort-by-author (reverse)
- "Sort messages of current Rmail summary by author.
-If prefix argument REVERSE is non-nil, sort them in reverse order."
- (interactive "P")
- (rmail-sort-from-summary (function rmail-sort-by-author) reverse))
-
-(defun rmail-summary-sort-by-recipient (reverse)
- "Sort messages of current Rmail summary by recipient.
-If prefix argument REVERSE is non-nil, sort them in reverse order."
- (interactive "P")
- (rmail-sort-from-summary (function rmail-sort-by-recipient) reverse))
-
-(defun rmail-summary-sort-by-correspondent (reverse)
- "Sort messages of current Rmail summary by other correspondent.
-If prefix argument REVERSE is non-nil, sort them in reverse order."
- (interactive "P")
- (rmail-sort-from-summary (function rmail-sort-by-correspondent) reverse))
-
-(defun rmail-summary-sort-by-lines (reverse)
- "Sort messages of current Rmail summary by lines of the message.
-If prefix argument REVERSE is non-nil, sort them in reverse order."
- (interactive "P")
- (rmail-sort-from-summary (function rmail-sort-by-lines) reverse))
-
-(defun rmail-summary-sort-by-keywords (reverse labels)
- "Sort messages of current Rmail summary by keywords.
-If prefix argument REVERSE is non-nil, sort them in reverse order.
-KEYWORDS is a comma-separated list of labels."
- (interactive "P\nsSort by labels: ")
- (rmail-sort-from-summary
- (function (lambda (reverse)
- (rmail-sort-by-keywords reverse labels)))
- reverse))
-
-(defun rmail-sort-from-summary (sortfun reverse)
- "Sort Rmail messages from Summary buffer and update it after sorting."
- (require 'rmailsort)
- (let ((selwin (selected-window)))
- (unwind-protect
- (progn (pop-to-buffer rmail-buffer)
- (funcall sortfun reverse))
- (select-window selwin))))
-
-;;; rmailsum.el ends here
diff --git a/lisp/mail/rnews.el b/lisp/mail/rnews.el
deleted file mode 100644
index d748fe49958..00000000000
--- a/lisp/mail/rnews.el
+++ /dev/null
@@ -1,989 +0,0 @@
-;;; rnews.el --- USENET news reader for gnu emacs
-
-;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Change Log:
-
-;; Created Sun Mar 10,1985 at 21:35:01 ads and sundar@hernes.ai.mit.edu
-;; Should do the point pdl stuff sometime
-;; finito except pdl.... Sat Mar 16,1985 at 06:43:44
-;; lets keep the summary stuff out until we get it working ..
-;; sundar@hermes.ai.mit.edu Wed Apr 10,1985 at 16:32:06
-;; hack slash maim. mly@prep.ai.mit.edu Thu 18 Apr, 1985 06:11:14
-;; modified to correct reentrance bug, to not bother with groups that
-;; received no new traffic since last read completely, to find out
-;; what traffic a group has available much more quickly when
-;; possible, to do some completing reads for group names - should
-;; be much faster...
-;; KING@KESTREL.arpa, Thu Mar 13 09:03:28 1986
-;; made news-{next,previous}-group skip groups with no new messages; and
-;; added checking for unsubscribed groups to news-add-news-group
-;; tower@prep.ai.mit.edu Jul 18 1986
-;; bound rmail-output to C-o; and changed header-field commands binding to
-;; agree with the new C-c C-f usage in sendmail
-;; tower@prep Sep 3 1986
-;; added news-rotate-buffer-body
-;; tower@prep Oct 17 1986
-;; made messages more user friendly, cleaned up news-inews
-;; move posting and mail code to new file rnewpost.el
-;; tower@prep Oct 29 1986
-;; added caesar-region, rename news-caesar-buffer-body, hacked accordingly
-;; tower@prep Nov 21 1986
-;; added tower@prep 22 Apr 87
-
-;;; Code:
-
-(require 'mail-utils)
-
-(autoload 'rmail-output "rmailout"
- "Append this message to Unix mail file named FILE-NAME."
- t)
-
-(autoload 'news-reply "rnewspost"
- "Compose and post a reply to the current article on USENET.
-While composing the reply, use \\[mail-yank-original] to yank the original
-message into it."
- t)
-
-(autoload 'news-mail-other-window "rnewspost"
- "Send mail in another window.
-While composing the message, use \\[mail-yank-original] to yank the
-original message into it."
- t)
-
-(autoload 'news-post-news "rnewspost"
- "Begin editing a new USENET news article to be posted."
- t)
-
-(autoload 'news-mail-reply "rnewspost"
- "Mail a reply to the author of the current article.
-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.
-;(defvar news-path "/usr/spool/news/"
-; "The root directory below which all news files are stored.")
-
-(defvar news-startup-file "$HOME/.newsrc" "Contains ~/.newsrc")
-(defvar news-certification-file "$HOME/.news-dates" "Contains ~/.news-dates")
-
-;; random headers that we decide to ignore.
-(defvar news-ignored-headers
- "^Path:\\|^Posting-Version:\\|^Article-I.D.:\\|^Expires:\\|^Date-Received:\\|^References:\\|^Control:\\|^Xref:\\|^Lines:\\|^Posted:\\|^Relay-Version:\\|^Message-ID:\\|^Nf-ID:\\|^Nf-From:\\|^Approved:\\|^Sender:"
- "All random fields within the header of a message.")
-
-(defvar news-mode-map nil)
-(defvar news-read-first-time-p t)
-;; Contains the (dotified) news groups of which you are a member.
-(defvar news-user-group-list nil)
-
-(defvar news-current-news-group nil)
-(defvar news-current-group-begin nil)
-(defvar news-current-group-end nil)
-(defvar news-current-certifications nil
- "An assoc list of a group name and the time at which it is
-known that the group had no new traffic")
-(defvar news-current-certifiable nil
- "The time when the directory we are now working on was written")
-
-(defvar news-message-filter nil
- "User specifiable filter function that will be called during
-formatting of the news file")
-
-;(defvar news-mode-group-string "Starting-Up"
-; "Mode line group name info is held in this variable")
-(defvar news-list-of-files nil
- "Global variable in which we store the list of files
-associated with the current newsgroup")
-(defvar news-list-of-files-possibly-bogus nil
- "variable indicating we only are guessing at which files are available.
-Not currently used.")
-
-;; association list in which we store lists of the form
-;; (pointified-group-name (first last old-last))
-(defvar news-group-article-assoc nil)
-
-(defvar news-current-message-number 0 "Displayed Article Number")
-(defvar news-total-current-group 0 "Total no of messages in group")
-
-(defvar news-unsubscribe-groups ())
-(defvar news-point-pdl () "List of visited news messages.")
-(defvar news-no-jumps-p t)
-(defvar news-buffer () "Buffer into which news files are read.")
-
-(defmacro news-push (item ref)
- (list 'setq ref (list 'cons item ref)))
-
-(defmacro news-cadr (x) (list 'car (list 'cdr x)))
-(defmacro news-cdar (x) (list 'cdr (list 'car x)))
-(defmacro news-caddr (x) (list 'car (list 'cdr (list 'cdr x))))
-(defmacro news-cadar (x) (list 'car (list 'cdr (list 'car x))))
-(defmacro news-caadr (x) (list 'car (list 'car (list 'cdr x))))
-(defmacro news-cdadr (x) (list 'cdr (list 'car (list 'cdr x))))
-
-(defmacro news-wins (pfx index)
- (` (file-exists-p (concat (, pfx) "/" (int-to-string (, index))))))
-
-(defvar news-max-plausible-gap 2
- "* In an rnews directory, the maximum possible gap size.
-A gap is a sequence of missing messages between two messages that exist.
-An empty file does not contribute to a gap -- it ends one.")
-
-(defun news-find-first-and-last (prefix base)
- (and (news-wins prefix base)
- (cons (news-find-first-or-last prefix base -1)
- (news-find-first-or-last prefix base 1))))
-
-(defmacro news-/ (a1 a2)
-;; a form of / that guarantees that (/ -1 2) = 0
- (if (zerop (/ -1 2))
- (` (/ (, a1) (, a2)))
- (` (if (< (, a1) 0)
- (- (/ (- (, a1)) (, a2)))
- (/ (, a1) (, a2))))))
-
-(defun news-find-first-or-last (pfx base dirn)
- ;; first use powers of two to find a plausible ceiling
- (let ((original-dir dirn))
- (while (news-wins pfx (+ base dirn))
- (setq dirn (* dirn 2)))
- (setq dirn (news-/ dirn 2))
- ;; Then use a binary search to find the high water mark
- (let ((offset (news-/ dirn 2)))
- (while (/= offset 0)
- (if (news-wins pfx (+ base dirn offset))
- (setq dirn (+ dirn offset)))
- (setq offset (news-/ offset 2))))
- ;; If this high-water mark is bogus, recurse.
- (let ((offset (* news-max-plausible-gap original-dir)))
- (while (and (/= offset 0) (not (news-wins pfx (+ base dirn offset))))
- (setq offset (- offset original-dir)))
- (if (= offset 0)
- (+ base dirn)
- (news-find-first-or-last pfx (+ base dirn offset) original-dir)))))
-
-(defun 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."
- (interactive)
- (let ((last-buffer (buffer-name)))
- (make-local-variable 'rmail-last-file)
- (switch-to-buffer (setq news-buffer (get-buffer-create "*news*")))
- (news-mode)
- (setq news-buffer-save last-buffer)
- (setq buffer-read-only nil)
- (erase-buffer)
- (setq buffer-read-only t)
- (set-buffer-modified-p t)
- (sit-for 0)
- (message "Getting new USENET news...")
- (news-set-mode-line)
- (news-get-certifications)
- (news-get-new-news)))
-
-(defun news-group-certification (group)
- (cdr-safe (assoc group news-current-certifications)))
-
-
-(defun news-set-current-certifiable ()
- ;; Record the date that corresponds to the directory you are about to check
- (let ((file (concat news-path
- (string-subst-char ?/ ?. news-current-news-group))))
- (setq news-current-certifiable
- (nth 5 (file-attributes
- (or (file-symlink-p file) file))))))
-
-(defun news-get-certifications ()
- ;; Read the certified-read file from last session
- (save-excursion
- (save-window-excursion
- (setq news-current-certifications
- (car-safe
- (condition-case var
- (let*
- ((file (substitute-in-file-name news-certification-file))
- (buf (find-file-noselect file)))
- (and (file-exists-p file)
- (progn
- (switch-to-buffer buf 'norecord)
- (unwind-protect
- (read-from-string (buffer-string))
- (kill-buffer buf)))))
- (error nil)))))))
-
-(defun news-write-certifications ()
- ;; Write a certification file.
- ;; This is an assoc list of group names with doubletons that represent
- ;; mod times of the directory when group is read completely.
- (save-excursion
- (save-window-excursion
- (with-output-to-temp-buffer
- "*CeRtIfIcAtIoNs*"
- (print news-current-certifications))
- (let ((buf (get-buffer "*CeRtIfIcAtIoNs*")))
- (switch-to-buffer buf)
- (write-file (substitute-in-file-name news-certification-file))
- (kill-buffer buf)))))
-
-(defun news-set-current-group-certification ()
- (let ((cgc (assoc news-current-news-group news-current-certifications)))
- (if cgc (setcdr cgc news-current-certifiable)
- (news-push (cons news-current-news-group news-current-certifiable)
- news-current-certifications))))
-
-(defun news-set-minor-modes ()
- "Creates a minor mode list that has group name, total articles,
-and attribute for current article."
- (setq news-minor-modes (list (cons 'foo
- (concat news-current-message-number
- "/"
- news-total-current-group
- (news-get-attribute-string)))))
- ;; Detect Emacs versions 18.16 and up, which display
- ;; directly from news-minor-modes by using a list for mode-name.
- (or (boundp 'minor-mode-alist)
- (setq minor-modes news-minor-modes)))
-
-(defun news-set-message-counters ()
- "Scan through current news-groups filelist to figure out how many messages
-are there. Set counters for use with minor mode display."
- (if (null news-list-of-files)
- (setq news-current-message-number 0)))
-
-(if news-mode-map
- nil
- (setq news-mode-map (make-keymap))
- (suppress-keymap news-mode-map)
- (define-key news-mode-map "." 'beginning-of-buffer)
- (define-key news-mode-map " " 'scroll-up)
- (define-key news-mode-map "\177" 'scroll-down)
- (define-key news-mode-map "n" 'news-next-message)
- (define-key news-mode-map "c" 'news-make-link-to-message)
- (define-key news-mode-map "p" 'news-previous-message)
- (define-key news-mode-map "j" 'news-goto-message)
- (define-key news-mode-map "q" 'news-exit)
- (define-key news-mode-map "e" 'news-exit)
- (define-key news-mode-map "\ej" 'news-goto-news-group)
- (define-key news-mode-map "\en" 'news-next-group)
- (define-key news-mode-map "\ep" 'news-previous-group)
- (define-key news-mode-map "l" 'news-list-news-groups)
- (define-key news-mode-map "?" 'describe-mode)
- (define-key news-mode-map "g" 'news-get-new-news)
- (define-key news-mode-map "f" 'news-reply)
- (define-key news-mode-map "m" 'news-mail-other-window)
- (define-key news-mode-map "a" 'news-post-news)
- (define-key news-mode-map "r" 'news-mail-reply)
- (define-key news-mode-map "o" 'news-save-item-in-file)
- (define-key news-mode-map "\C-o" 'rmail-output)
- (define-key news-mode-map "t" 'news-show-all-headers)
- (define-key news-mode-map "x" 'news-force-update)
- (define-key news-mode-map "A" 'news-add-news-group)
- (define-key news-mode-map "u" 'news-unsubscribe-current-group)
- (define-key news-mode-map "U" 'news-unsubscribe-group)
- (define-key news-mode-map "\C-c\C-r" 'news-caesar-buffer-body))
-
-(defun news-mode ()
- "News Mode is used by M-x rnews for reading USENET Newsgroups articles.
-New readers can find additional help in newsgroup: news.announce.newusers .
-All normal editing commands are turned off.
-Instead, these commands are available:
-
-. move point to front of this news article (same as Meta-<).
-Space scroll to next screen of this news article.
-Delete scroll down previous page of this news article.
-n move to next news article, possibly next group.
-p move to previous news article, possibly previous group.
-j jump to news article specified by numeric position.
-M-j jump to news group.
-M-n goto next news group.
-M-p goto previous news group.
-l list all the news groups with current status.
-? print this help message.
-C-c C-r caesar rotate all letters by 13 places in the article's body (rot13).
-g get new USENET news.
-f post a reply article to USENET.
-a post an original news article.
-A add a newsgroup.
-o save the current article in the named file (append if file exists).
-C-o output this message to a Unix-format mail file (append it).
-c \"copy\" (actually link) current or prefix-arg msg to file.
- warning: target directory and message file must be on same device
- (UNIX magic)
-t show all the headers this news article originally had.
-q quit reading news after updating .newsrc file.
-e exit updating .newsrc file.
-m mail a news article. Same as C-x 4 m.
-x update last message seen to be the current message.
-r mail a reply to this news article. Like m but initializes some fields.
-u unsubscribe from current newsgroup.
-U unsubscribe from specified newsgroup."
- (interactive)
- (kill-all-local-variables)
- (make-local-variable 'news-read-first-time-p)
- (setq news-read-first-time-p t)
- (make-local-variable 'news-current-news-group)
-; (setq news-current-news-group "??")
- (make-local-variable 'news-current-group-begin)
- (setq news-current-group-begin 0)
- (make-local-variable 'news-current-message-number)
- (setq news-current-message-number 0)
- (make-local-variable 'news-total-current-group)
- (make-local-variable 'news-buffer-save)
- (make-local-variable 'version-control)
- (setq version-control 'never)
- (make-local-variable 'news-point-pdl)
-; This breaks it. I don't have time to figure out why. -- RMS
-; (make-local-variable 'news-group-article-assoc)
- (setq major-mode 'news-mode)
- (setq mode-line-process '(news-minor-modes))
- (setq mode-name "NEWS")
- (news-set-mode-line)
- (set-syntax-table text-mode-syntax-table)
- (use-local-map news-mode-map)
- (setq local-abbrev-table text-mode-abbrev-table)
- (run-hooks 'news-mode-hook))
-
-(defun string-subst-char (new old string)
- (let (index)
- (setq old (regexp-quote (char-to-string old))
- string (substring string 0))
- (while (setq index (string-match old string))
- (aset string index new)))
- string)
-
-;; update read message number
-(defmacro news-update-message-read (ngroup nno)
- (list 'setcar
- (list 'news-cdadr
- (list 'assoc ngroup 'news-group-article-assoc))
- nno))
-
-(defun news-parse-range (number-string)
- "Parse string representing range of numbers of he form <a>-<b>
-to a list (a . b)"
- (let ((n (string-match "-" number-string)))
- (if n
- (cons (string-to-int (substring number-string 0 n))
- (string-to-int (substring number-string (1+ n))))
- (setq n (string-to-int number-string))
- (cons n n))))
-
-;(defun is-in (elt lis)
-; (catch 'foo
-; (while lis
-; (if (equal (car lis) elt)
-; (throw 'foo t)
-; (setq lis (cdr lis))))))
-
-(defun news-get-new-news ()
- "Get new USENET news, if there is any for the current user."
- (interactive)
- (if (not (null news-user-group-list))
- (news-update-newsrc-file))
- (setq news-group-article-assoc ())
- (setq news-user-group-list ())
- (message "Looking up %s file..." news-startup-file)
- (let ((file (substitute-in-file-name news-startup-file))
- (temp-user-groups ()))
- (save-excursion
- (let ((newsrcbuf (find-file-noselect file))
- start end endofline tem)
- (set-buffer newsrcbuf)
- (goto-char 0)
- (while (search-forward ": " nil t)
- (setq end (point))
- (beginning-of-line)
- (setq start (point))
- (end-of-line)
- (setq endofline (point))
- (setq tem (buffer-substring start (- end 2)))
- (let ((range (news-parse-range
- (buffer-substring end endofline))))
- (if (assoc tem news-group-article-assoc)
- (message "You are subscribed twice to %s; I ignore second"
- tem)
- (setq temp-user-groups (cons tem temp-user-groups)
- news-group-article-assoc
- (cons (list tem (list (car range)
- (cdr range)
- (cdr range)))
- news-group-article-assoc)))))
- (kill-buffer newsrcbuf)))
- (setq temp-user-groups (nreverse temp-user-groups))
- (message "Prefrobnicating...")
- (switch-to-buffer news-buffer)
- (setq news-user-group-list temp-user-groups)
- (while (and temp-user-groups
- (not (news-read-files-into-buffer
- (car temp-user-groups) nil)))
- (setq temp-user-groups (cdr temp-user-groups)))
- (if (null temp-user-groups)
- (message "No news is good news.")
- (message ""))))
-
-(defun news-list-news-groups ()
- "Display all the news groups to which you belong."
- (interactive)
- (with-output-to-temp-buffer "*Newsgroups*"
- (save-excursion
- (set-buffer standard-output)
- (insert
- "News Group Msg No. News Group Msg No.\n")
- (insert
- "------------------------- -------------------------\n")
- (let ((temp news-user-group-list)
- (flag nil))
- (while temp
- (let ((item (assoc (car temp) news-group-article-assoc)))
- (insert (car item))
- (indent-to (if flag 52 20))
- (insert (int-to-string (news-cadr (news-cadr item))))
- (if flag
- (insert "\n")
- (indent-to 33))
- (setq temp (cdr temp) flag (not flag))))))))
-
-;; Mode line hack
-(defun news-set-mode-line ()
- "Set mode line string to something useful."
- (setq mode-line-process
- (concat " "
- (if (integerp news-current-message-number)
- (int-to-string news-current-message-number)
- "??")
- "/"
- (if (integerp news-current-group-end)
- (int-to-string news-current-group-end)
- news-current-group-end)))
- (setq mode-line-buffer-identification
- (concat "NEWS: "
- news-current-news-group
- ;; Enough spaces to pad group name to 17 positions.
- (substring " "
- 0 (max 0 (- 17 (length news-current-news-group))))))
- (set-buffer-modified-p t)
- (sit-for 0))
-
-(defun news-goto-news-group (gp)
- "Takes a string and goes to that news group."
- (interactive (list (completing-read "NewsGroup: "
- news-group-article-assoc)))
- (message "Jumping to news group %s..." gp)
- (news-select-news-group gp)
- (message "Jumping to news group %s... done." gp))
-
-(defun news-select-news-group (gp)
- (let ((grp (assoc gp news-group-article-assoc)))
- (if (null grp)
- (error "Group %s not subscribed to" gp)
- (progn
- (news-update-message-read news-current-news-group
- (news-cdar news-point-pdl))
- (news-read-files-into-buffer (car grp) nil)
- (news-set-mode-line)))))
-
-(defun news-goto-message (arg)
- "Goes to the article ARG in current newsgroup."
- (interactive "p")
- (if (null current-prefix-arg)
- (setq arg (read-no-blanks-input "Go to article: " "")))
- (news-select-message arg))
-
-(defun news-select-message (arg)
- (if (stringp arg) (setq arg (string-to-int arg)))
- (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 nil))
- (news-read-in-file file)
- (news-set-mode-line))
- (news-set-mode-line)
- (error "Article %d nonexistent" arg))))
-
-(defun news-force-update ()
- "updates the position of last article read in the current news group"
- (interactive)
- (setcdr (car news-point-pdl) news-current-message-number)
- (message "Updated to %d" news-current-message-number))
-
-(defun news-next-message (arg)
- "Move ARG messages forward within one newsgroup.
-Negative ARG moves backward.
-If ARG is 1 or -1, moves to next or previous newsgroup if at end."
- (interactive "p")
- (let ((no (+ arg news-current-message-number)))
- (if (or (< no news-current-group-begin)
- (> no news-current-group-end))
- (cond ((= arg 1)
- (news-set-current-group-certification)
- (news-next-group))
- ((= arg -1)
- (news-previous-group))
- (t (error "Article out of range")))
- (let ((plist (news-get-motion-lists
- news-current-message-number
- news-list-of-files)))
- (if (< arg 0)
- (news-select-message (nth (1- (- arg)) (car (cdr plist))))
- (news-select-message (nth (1- arg) (car plist))))))))
-
-(defun news-previous-message (arg)
- "Move ARG messages backward in current newsgroup.
-With no arg or arg of 1, move one message
-and move to previous newsgroup if at beginning.
-A negative ARG means move forward."
- (interactive "p")
- (news-next-message (- arg)))
-
-(defun news-move-to-group (arg)
- "Given arg move forward or backward to a new newsgroup."
- (let ((cg news-current-news-group))
- (let ((plist (news-get-motion-lists cg news-user-group-list))
- ngrp)
- (if (< arg 0)
- (or (setq ngrp (nth (1- (- arg)) (news-cadr plist)))
- (error "No previous news groups"))
- (or (setq ngrp (nth arg (car plist)))
- (error "No more news groups")))
- (news-select-news-group ngrp))))
-
-(defun news-next-group ()
- "Moves to the next user group."
- (interactive)
-; (message "Moving to next group...")
- (news-move-to-group 0)
- (while (null news-list-of-files)
- (news-move-to-group 0)))
-; (message "Moving to next group... done.")
-
-(defun news-previous-group ()
- "Moves to the previous user group."
- (interactive)
-; (message "Moving to previous group...")
- (news-move-to-group -1)
- (while (null news-list-of-files)
- (news-move-to-group -1)))
-; (message "Moving to previous group... done.")
-
-(defun news-get-motion-lists (arg listy)
- "Given a msgnumber/group this will return a list of two lists;
-one for moving forward and one for moving backward."
- (let ((temp listy)
- (result ()))
- (catch 'out
- (while temp
- (if (equal (car temp) arg)
- (throw 'out (cons (cdr temp) (list result)))
- (setq result (nconc (list (car temp)) result))
- (setq temp (cdr temp)))))))
-
-;; miscellaneous io routines
-(defun news-read-in-file (filename)
- (erase-buffer)
- (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)
- (message "(Empty file?)")
- (goto-char start))))
-
-(defun news-convert-format ()
- (save-excursion
- (save-restriction
- (let* ((start (point))
- (end (condition-case ()
- (progn (search-forward "\n\n") (point))
- (error nil)))
- has-from has-date)
- (cond (end
- (narrow-to-region start end)
- (goto-char start)
- (setq has-from (search-forward "\nFrom:" nil t))
- (cond ((and (not has-from) has-date)
- (goto-char start)
- (search-forward "\nDate:")
- (beginning-of-line)
- (kill-line) (kill-line)))
- (news-delete-headers start)
- (goto-char start)))))))
-
-(defun news-show-all-headers ()
- "Redisplay current news item with all original headers"
- (interactive)
- (let (news-ignored-headers
- (buffer-read-only ()))
- (erase-buffer)
- (news-set-mode-line)
- (news-read-in-file
- (concat news-path
- (string-subst-char ?/ ?. news-current-news-group)
- "/" (int-to-string news-current-message-number)))))
-
-(defun news-delete-headers (pos)
- (goto-char pos)
- (and (stringp news-ignored-headers)
- (while (re-search-forward news-ignored-headers nil t)
- (beginning-of-line)
- (delete-region (point)
- (progn (re-search-forward "\n[^ \t]")
- (forward-char -1)
- (point))))))
-
-(defun news-exit ()
- "Quit news reading session and update the .newsrc file."
- (interactive)
- (if (y-or-n-p "Do you really wanna quit reading news ? ")
- (progn (message "Updating %s..." news-startup-file)
- (news-update-newsrc-file)
- (news-write-certifications)
- (message "Updating %s... done" news-startup-file)
- (message "Now do some real work")
- (and (fboundp 'bury-buffer) (bury-buffer (current-buffer)))
- (switch-to-buffer news-buffer-save)
- (setq news-user-group-list ()))
- (message "")))
-
-(defun news-update-newsrc-file ()
- "Updates the .newsrc file in the users home dir."
- (let ((newsrcbuf (find-file-noselect
- (substitute-in-file-name news-startup-file)))
- (tem news-user-group-list)
- group)
- (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)
- (while tem
- (setq group (assoc (car tem) news-group-article-assoc))
- (if (= (news-cadr (news-cadr group)) (news-caddr (news-cadr group)))
- nil
- (goto-char 0)
- (if (search-forward (concat (car group) ": ") nil t)
- (kill-line nil)
- (insert (car group) ": \n") (backward-char 1))
- (insert (int-to-string (car (news-cadr group))) "-"
- (int-to-string (news-cadr (news-cadr group)))))
- (setq tem (cdr tem)))
- (while news-unsubscribe-groups
- (setq group (assoc (car news-unsubscribe-groups)
- news-group-article-assoc))
- (goto-char 0)
- (if (search-forward (concat (car group) ": ") nil t)
- (progn
- (backward-char 2)
- (kill-line nil)
- (insert "! " (int-to-string (car (news-cadr group)))
- "-" (int-to-string (news-cadr (news-cadr group))))))
- (setq news-unsubscribe-groups (cdr news-unsubscribe-groups)))
- (save-buffer)
- (kill-buffer (current-buffer)))))
-
-
-(defun news-unsubscribe-group (group)
- "Removes you from newgroup GROUP."
- (interactive (list (completing-read "Unsubscribe from group: "
- news-group-article-assoc)))
- (news-unsubscribe-internal group))
-
-(defun news-unsubscribe-current-group ()
- "Removes you from the newsgroup you are now reading."
- (interactive)
- (if (y-or-n-p "Do you really want to unsubscribe from this group ? ")
- (news-unsubscribe-internal news-current-news-group)))
-
-(defun news-unsubscribe-internal (group)
- (let ((tem (assoc group news-group-article-assoc)))
- (if tem
- (progn
- (setq news-unsubscribe-groups (cons group news-unsubscribe-groups))
- (news-update-message-read group (news-cdar news-point-pdl))
- (if (equal group news-current-news-group)
- (news-next-group))
- (message ""))
- (error "Not subscribed to group: %s" group))))
-
-(defun news-save-item-in-file (file)
- "Save the current article that is being read by appending to a file."
- (interactive "FSave item in file: ")
- (append-to-file (point-min) (point-max) file))
-
-(defun news-get-pruned-list-of-files (gp-list end-file-no)
- "Given a news group it finds all files in the news group.
-The arg must be in slashified format.
-Using ls was found to be too slow in a previous version."
- (let
- ((answer
- (and
- (not (and end-file-no
- (equal (news-set-current-certifiable)
- (news-group-certification gp-list))
- (setq news-list-of-files nil
- news-list-of-files-possibly-bogus t)))
- (let* ((file-directory (concat news-path
- (string-subst-char ?/ ?. gp-list)))
- tem
- (last-winner
- (and end-file-no
- (news-wins file-directory end-file-no)
- (news-find-first-or-last file-directory end-file-no 1))))
- (setq news-list-of-files-possibly-bogus t news-list-of-files nil)
- (if last-winner
- (progn
- (setq news-list-of-files-possibly-bogus t
- news-current-group-end last-winner)
- (while (> last-winner end-file-no)
- (news-push last-winner news-list-of-files)
- (setq last-winner (1- last-winner)))
- news-list-of-files)
- (if (or (not (file-directory-p file-directory))
- (not (file-readable-p file-directory)))
- nil
- (setq news-list-of-files
- (condition-case error
- (directory-files file-directory)
- (file-error
- (if (string= (nth 2 error) "permission denied")
- (message "Newsgroup %s is read-protected"
- gp-list)
- (signal 'file-error (cdr error)))
- nil)))
- (setq tem news-list-of-files)
- (while tem
- (if (or (not (string-match "^[0-9]*$" (car tem)))
- ;; don't get confused by directories that look like numbers
- (file-directory-p
- (concat file-directory "/" (car tem)))
- (<= (string-to-int (car tem)) end-file-no))
- (setq news-list-of-files
- (delq (car tem) news-list-of-files)))
- (setq tem (cdr tem)))
- (if (null news-list-of-files)
- (progn (setq news-current-group-end 0)
- nil)
- (setq news-list-of-files
- (mapcar 'string-to-int news-list-of-files))
- (setq news-list-of-files (sort news-list-of-files '<))
- (setq news-current-group-end
- (elt news-list-of-files
- (1- (length news-list-of-files))))
- news-list-of-files)))))))
- (or answer (progn (news-set-current-group-certification) nil))))
-
-(defun news-read-files-into-buffer (group reversep)
- (let* ((files-start-end (news-cadr (assoc group news-group-article-assoc)))
- (start-file-no (car files-start-end))
- (end-file-no (news-cadr files-start-end))
- (buffer-read-only nil))
- (setq news-current-news-group group)
- (setq news-current-message-number nil)
- (setq news-current-group-end nil)
- (news-set-mode-line)
- (news-get-pruned-list-of-files group end-file-no)
- (news-set-mode-line)
- ;; @@ should be a lot smarter than this if we have to move
- ;; @@ around correctly.
- (setq news-point-pdl (list (cons (car files-start-end)
- (news-cadr files-start-end))))
- (if (null news-list-of-files)
- (progn (erase-buffer)
- (setq news-current-group-end end-file-no)
- (setq news-current-group-begin end-file-no)
- (setq news-current-message-number end-file-no)
- (news-set-mode-line)
-; (message "No new articles in " group " group.")
- nil)
- (setq news-current-group-begin (car news-list-of-files))
- (if reversep
- (setq news-current-message-number news-current-group-end)
- (if (> (car news-list-of-files) end-file-no)
- (setcdr (car news-point-pdl) (car news-list-of-files)))
- (setq news-current-message-number news-current-group-begin))
- (news-set-message-counters)
- (news-set-mode-line)
- (news-read-in-file (concat news-path
- (string-subst-char ?/ ?. group)
- "/"
- (int-to-string
- news-current-message-number)))
- (news-set-message-counters)
- (news-set-mode-line)
- t)))
-
-(defun news-add-news-group (gp)
- "Resubscribe to or add a USENET news group named GROUP (a string)."
-; @@ (completing-read ...)
-; @@ could be based on news library file ../active (slightly fascist)
-; @@ or (expensive to compute) all directories under the news spool directory
- (interactive "sAdd news group: ")
- (let ((file-dir (concat news-path (string-subst-char ?/ ?. gp))))
- (save-excursion
- (if (null (assoc gp news-group-article-assoc))
- (let ((newsrcbuf (find-file-noselect
- (substitute-in-file-name news-startup-file))))
- (if (file-directory-p file-dir)
- (progn
- (switch-to-buffer newsrcbuf)
- (goto-char 0)
- (if (search-forward (concat gp "! ") nil t)
- (progn
- (message "Re-subscribing to group %s." gp)
- ;;@@ news-unsubscribe-groups isn't being used
- ;;(setq news-unsubscribe-groups
- ;; (delq gp news-unsubscribe-groups))
- (backward-char 2)
- (delete-char 1)
- (insert ":"))
- (progn
- (message
- "Added %s to your list of newsgroups." gp)
- (end-of-buffer)
- (insert gp ": 1-1\n")))
- (search-backward gp nil t)
- (let (start end endofline tem)
- (search-forward ": " nil t)
- (setq end (point))
- (beginning-of-line)
- (setq start (point))
- (end-of-line)
- (setq endofline (point))
- (setq tem (buffer-substring start (- end 2)))
- (let ((range (news-parse-range
- (buffer-substring end endofline))))
- (setq news-group-article-assoc
- (cons (list tem (list (car range)
- (cdr range)
- (cdr range)))
- news-group-article-assoc))))
- (save-buffer)
- (kill-buffer (current-buffer)))
- (message "Newsgroup %s doesn't exist." gp)))
- (message "Already subscribed to group %s." gp)))))
-
-(defun news-make-link-to-message (number newname)
- "Forges a link to an rnews message numbered number (current if no arg)
-Good for hanging on to a message that might or might not be
-automatically deleted."
- (interactive "P
-FName to link to message: ")
- (add-name-to-file
- (concat news-path
- (string-subst-char ?/ ?. news-current-news-group)
- "/" (if number
- (prefix-numeric-value number)
- news-current-message-number))
- newname))
-
-;;; caesar-region written by phr@prep.ai.mit.edu Nov 86
-;;; modified by tower@prep Nov 86
-(defun caesar-region (&optional n)
- "Caesar rotation of region by N, default 13, for decrypting netnews."
- (interactive (if current-prefix-arg ; Was there a prefix arg?
- (list (prefix-numeric-value current-prefix-arg))
- (list nil)))
- (cond ((not (numberp n)) (setq n 13))
- (t (setq n (mod n 26)))) ;canonicalize N
- (if (not (zerop n)) ; no action needed for a rot of 0
- (progn
- (if (or (not (boundp 'caesar-translate-table))
- (/= (aref caesar-translate-table ?a) (+ ?a n)))
- (let ((i 0) (lower "abcdefghijklmnopqrstuvwxyz") upper)
- (message "Building caesar-translate-table...")
- (setq caesar-translate-table (make-vector 256 0))
- (while (< i 256)
- (aset caesar-translate-table i i)
- (setq i (1+ i)))
- (setq lower (concat lower lower) upper (upcase lower) i 0)
- (while (< i 26)
- (aset caesar-translate-table (+ ?a i) (aref lower (+ i n)))
- (aset caesar-translate-table (+ ?A i) (aref upper (+ i n)))
- (setq i (1+ i)))
- (message "Building caesar-translate-table... done")))
- (let ((from (region-beginning))
- (to (region-end))
- (i 0) str len)
- (setq str (buffer-substring from to))
- (setq len (length str))
- (while (< i len)
- (aset str i (aref caesar-translate-table (aref str i)))
- (setq i (1+ i)))
- (goto-char from)
- (kill-region from to)
- (insert str)))))
-
-;;; news-caesar-buffer-body written by paul@media-lab.mit.edu Wed Oct 1, 1986
-;;; hacked further by tower@prep.ai.mit.edu
-(defun news-caesar-buffer-body (&optional rotnum)
- "Caesar rotates all letters in the current buffer by 13 places.
-Used to encode/decode possibly offensive messages (commonly in net.jokes).
-With prefix arg, specifies the number of places to rotate each letter forward.
-Mail and USENET news headers are not rotated."
- (interactive (if current-prefix-arg ; Was there a prefix arg?
- (list (prefix-numeric-value current-prefix-arg))
- (list nil)))
- (save-excursion
- (let ((buffer-status buffer-read-only))
- (setq buffer-read-only nil)
- ;; setup the region
- (set-mark (if (progn (goto-char (point-min))
- (search-forward
- (concat "\n"
- (if (equal major-mode 'news-mode)
- ""
- mail-header-separator)
- "\n") nil t))
- (point)
- (point-min)))
- (goto-char (point-max))
- (caesar-region rotnum)
- (setq buffer-read-only buffer-status))))
-
-(provide 'rnews)
-
-;;; rnews.el ends here
diff --git a/lisp/mail/rnewspost.el b/lisp/mail/rnewspost.el
deleted file mode 100644
index 3d6be2505f0..00000000000
--- a/lisp/mail/rnewspost.el
+++ /dev/null
@@ -1,439 +0,0 @@
-;;; rnewspost.el --- USENET news poster/mailer for GNU Emacs
-
-;; Copyright (C) 1985, 1986, 1987, 1995 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: mail, news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Change Log:
-
-;; moved posting and mail code from rnews.el
-;; tower@prep.ai.mit.edu Wed Oct 29 1986
-;; brought posting code almost up to the revision of RFC 850 for News 2.11
-;; - couldn't see handling the special meaning of the Keyword: poster
-;; - not worth the code space to support the old A news Title: (which
-;; Subject: replaced) and Article-I.D.: (which Message-ID: replaced)
-;; tower@prep Nov 86
-;; changed C-c C-r key-binding due to rename of news-caesar-buffer-body
-;; tower@prep 21 Nov 86
-;; added (require 'rnews) tower@prep 22 Apr 87
-;; restricted call of news-show-all-headers in news-post-news & news-reply
-;; tower@prep 28 Apr 87
-;; commented out Posting-Front-End to save USENET bytes tower@prep Jul 31 87
-;; commented out -n and -t args in news-inews tower@prep 15 Oct 87
-
-;Now in paths.el.
-;(defvar news-inews-program "inews"
-; "Function to post news.")
-
-;; Replying and posting news items are done by these functions.
-;; imported from rmail and modified to work with rnews ...
-;; Mon Mar 25,1985 at 03:07:04 ads@mit-hermes.
-;; this is done so that rnews can operate independently from rmail.el and
-;; sendmail and doesn't have to autoload these functions.
-;;
-;;; >> Nuked by Mly to autoload those functions again, as the duplication of
-;;; >> code was making maintenance too difficult.
-
-;;; Code:
-
-(require 'sendmail)
-(require 'rnews)
-
-(defvar news-reply-mode-map () "Mode map used by news-reply.")
-
-(or news-reply-mode-map
- (progn
- (setq news-reply-mode-map (make-keymap))
- (define-key news-reply-mode-map "\C-c\C-f\C-d" 'news-reply-distribution)
- (define-key news-reply-mode-map "\C-c\C-f\C-k" 'news-reply-keywords)
- (define-key news-reply-mode-map "\C-c\C-f\C-n" 'news-reply-newsgroups)
- (define-key news-reply-mode-map "\C-c\C-f\C-f" 'news-reply-followup-to)
- (define-key news-reply-mode-map "\C-c\C-f\C-s" 'mail-subject)
- (define-key news-reply-mode-map "\C-c\C-f\C-a" 'news-reply-summary)
- (define-key news-reply-mode-map "\C-c\C-t" 'mail-text)
- (define-key news-reply-mode-map "\C-c\C-r" 'news-caesar-buffer-body)
- (define-key news-reply-mode-map "\C-c\C-w" 'news-reply-signature)
- (define-key news-reply-mode-map "\C-c\C-y" 'news-reply-yank-original)
- (define-key news-reply-mode-map "\C-c\C-q" 'mail-fill-yanked-message)
- (define-key news-reply-mode-map "\C-c\C-c" 'news-inews)
- (define-key news-reply-mode-map "\C-c\C-s" 'news-inews)
- (define-key news-reply-mode-map [menu-bar] (make-sparse-keymap))
- (define-key news-reply-mode-map [menu-bar fields]
- (cons "Fields" (make-sparse-keymap "Fields")))
- (define-key news-reply-mode-map [menu-bar fields news-reply-distribution]
- '("Distribution" . news-reply-distribution))
- (define-key news-reply-mode-map [menu-bar fields news-reply-keywords]
- '("Keywords" . news-reply-keywords))
- (define-key news-reply-mode-map [menu-bar fields news-reply-newsgroups]
- '("Newsgroups" . news-reply-newsgroups))
- (define-key news-reply-mode-map [menu-bar fields news-reply-followup-to]
- '("Followup-to" . news-reply-followup-to))
- (define-key news-reply-mode-map [menu-bar fields mail-subject]
- '("Subject" . mail-subject))
- (define-key news-reply-mode-map [menu-bar fields news-reply-summary]
- '("Summary" . news-reply-summary))
- (define-key news-reply-mode-map [menu-bar fields mail-text]
- '("Text" . mail-text))
- (define-key news-reply-mode-map [menu-bar news]
- (cons "News" (make-sparse-keymap "News")))
- (define-key news-reply-mode-map [menu-bar news news-caesar-buffer-body]
- '("Rot13" . news-caesar-buffer-body))
- (define-key news-reply-mode-map [menu-bar news news-reply-yank-original]
- '("Yank Original" . news-reply-yank-original))
- (define-key news-reply-mode-map [menu-bar news mail-fill-yanked-message]
- '("Fill Yanked Messages" . mail-fill-yanked-message))
- (define-key news-reply-mode-map [menu-bar news news-inews]
- '("Send" . news-inews))))
-
-(defun news-reply-mode ()
- "Major mode for editing news to be posted on USENET.
-First-time posters are asked to please read the articles in newsgroup:
- news.announce.newusers .
-Like Text Mode but with these additional commands:
-
-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)."
- (interactive)
- ;; require...
- (or (fboundp 'mail-setup) (load "sendmail"))
- (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 news-reply-mode-map)
- (setq local-abbrev-table text-mode-abbrev-table)
- (setq major-mode 'news-reply-mode)
- (setq mode-name "News Reply")
- (make-local-variable 'paragraph-separate)
- (make-local-variable 'paragraph-start)
- (setq paragraph-start
- (concat "^" (regexp-quote mail-header-separator) "$\\|"
- paragraph-start))
- (setq paragraph-separate
- (concat "^" (regexp-quote mail-header-separator) "$\\|"
- paragraph-separate))
- (run-hooks 'text-mode-hook 'news-reply-mode-hook))
-
-(defvar news-reply-yank-from ""
- "Save `From:' field for `news-reply-yank-original'.")
-
-(defvar news-reply-yank-message-id ""
- "Save `Message-Id:' field for `news-reply-yank-original'.")
-
-(defun news-reply-yank-original (arg)
- "Insert the message being replied to, if any (in Mail mode).
-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")
- (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.")
-
-(defun news-reply-newsgroups ()
- "Move point to end of `Newsgroups:' field.
-RFC 850 constrains the `Newsgroups:' field to be a comma-separated list
-of valid newsgroup names at your site. For example,
- Newsgroups: news.misc,comp.misc,rec.misc"
- (interactive)
- (expand-abbrev)
- (goto-char (point-min))
- (mail-position-on-field "Newsgroups"))
-
-(defun news-reply-followup-to ()
- "Move point to end of `Followup-To:' field. Create the field if none.
-One usually requests followups to only one newsgroup.
-RFC 850 constrains the `Followup-To:' field to be a comma-separated list
-of valid newsgroups names at your site, and it must be a subset of the
-`Newsgroups:' field. For example:
- Newsgroups: news.misc,comp.misc,rec.misc,misc.misc,soc.misc
- Followup-To: news.misc,comp.misc,rec.misc"
- (interactive)
- (expand-abbrev)
- (or (mail-position-on-field "Followup-To" t)
- (progn (mail-position-on-field "newsgroups")
- (insert "\nFollowup-To: ")))
- ;; @@ could do a completing read based on the Newsgroups: field to
- ;; @@ fill in the Followup-To: field
-)
-
-(defun news-reply-distribution ()
- "Move point to end of `Distribution:' optional field.
-Create the field if none. Without this field the posting goes to all of
-USENET. The field is used to restrict the posting to parts of USENET."
- (interactive)
- (expand-abbrev)
- (mail-position-on-field "Distribution")
- ;; @@could do a completing read based on the news library file:
- ;; @@ ../distributions to fill in the field.
- )
-
-(defun news-reply-keywords ()
- "Move point to end of `Keywords:' optional field. Create the field if none.
-Used as an aid to the news reader, it can contain a few, well selected keywords
-identifying the message."
- (interactive)
- (expand-abbrev)
- (mail-position-on-field "Keywords"))
-
-(defun news-reply-summary ()
- "Move point to end of `Summary:' optional field. Create the field if none.
-Used as an aid to the news reader, it can contain a succinct
-summary (abstract) of the message."
- (interactive)
- (expand-abbrev)
- (mail-position-on-field "Summary"))
-
-(defun news-reply-signature ()
- "The inews program appends `~/.signature' automatically."
- (interactive)
- (message "Posting news will append your signature automatically."))
-
-(defun news-setup (to subject in-reply-to newsgroups replybuffer)
- "Set up the news reply or posting buffer with the proper headers and mode."
- (setq mail-reply-buffer replybuffer)
- (let ((mail-setup-hook nil)
- ;; Avoid inserting a signature.
- (mail-signature))
- (if (null to)
- ;; this hack is needed so that inews wont be confused by
- ;; 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)
- (beginning-of-line)
- (delete-region (point) (progn (forward-line 1) (point)))
- (goto-char (point-max)))
- (mail-setup to subject in-reply-to nil replybuffer nil))
- ;;;(mail-position-on-field "Posting-Front-End")
- ;;;(insert (emacs-version))
- (goto-char (point-max))
- (if (let ((case-fold-search t))
- (re-search-backward "^Subject:" (point-min) t))
- (progn (beginning-of-line)
- (insert "Newsgroups: " (or newsgroups "") "\n")
- (if (not newsgroups)
- (backward-char 1)
- (goto-char (point-max)))))
- (run-hooks 'news-setup-hook)))
-
-(defun news-inews ()
- "Send a news message using inews."
- (interactive)
- (let* (newsgroups subject
- (case-fold-search nil))
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (search-forward (concat "\n" mail-header-separator "\n"))
- (narrow-to-region (point-min) (point))
- (setq newsgroups (mail-fetch-field "newsgroups")
- subject (mail-fetch-field "subject")))
- (widen)
- (goto-char (point-min))
- (run-hooks 'news-inews-hook)
- (goto-char (point-min))
- (search-forward (concat "\n" mail-header-separator "\n"))
- (replace-match "\n\n")
- (goto-char (point-max))
- ;; require a newline at the end for inews to append .signature to
- (or (= (preceding-char) ?\n)
- (insert ?\n))
- (message "Posting to USENET...")
- (call-process-region (point-min) (point-max)
- news-inews-program nil 0 nil
- "-h") ; take all header lines!
- ;@@ setting of subject and newsgroups still needed?
- ;"-t" subject
- ;"-n" newsgroups
- (message "Posting to USENET... done")
- (goto-char (point-min)) ;restore internal header separator
- (search-forward "\n\n")
- (replace-match (concat "\n" mail-header-separator "\n"))
- (set-buffer-modified-p nil))
- (and (fboundp 'bury-buffer) (bury-buffer))))
-
-;@@ shares some code with news-reply and news-post-news
-(defun news-mail-reply ()
- "Mail a reply to the author of the current article.
-While composing the reply, use \\[news-reply-yank-original] to yank the
-original message into it."
- (interactive)
- (let (from cc subject date to reply-to message-id
- (buffer (current-buffer)))
- (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")
- date (mail-fetch-field "date")
- message-id (mail-fetch-field "message-id")))
- (setq to from)
- (pop-to-buffer "*mail*")
- (mail nil
- (if reply-to reply-to to)
- subject
- (let ((stop-pos (string-match " *at \\| *@ \\| *(\\| *<" from)))
- (concat (if stop-pos (substring from 0 stop-pos) from)
- "'s message "
- (if message-id
- (concat message-id " of ")
- "of ")
- date))
- nil
- buffer)))
-
-;@@ the guts of news-reply and news-post-news should be combined. -tower
-(defun news-reply ()
- "Compose and post a reply (aka a followup) to the current article on USENET.
-While composing the followup, use \\[news-reply-yank-original] to yank the
-original message into it."
- (interactive)
- (if (y-or-n-p "Are you sure you want to followup to all of USENET? ")
- (let (from cc subject date to followup-to newsgroups message-of
- references distribution message-id
- (buffer (current-buffer)))
- (save-restriction
- (and (not (= 0 (buffer-size))) ;@@real problem is non-existence of
- ;@@ of article file
- (equal major-mode 'news-mode) ;@@ if rmail-mode,
- ;@@ should show full headers
- (progn
- (news-show-all-headers) ;@@ should save/restore header state,
- ;@@ 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
- subject (mail-fetch-field "subject")
- date (mail-fetch-field "date")
- followup-to (mail-fetch-field "followup-to")
- newsgroups (or followup-to
- (mail-fetch-field "newsgroups"))
- references (mail-fetch-field "references")
- ;; @@ not handling old Article-I.D.: field
- distribution (mail-fetch-field "distribution")
- message-id (mail-fetch-field "message-id")
- news-reply-yank-message-id message-id)
- (pop-to-buffer "*post-news*")
- (news-reply-mode)
- (if (and (buffer-modified-p)
- (not
- (y-or-n-p "Unsent article being composed; erase it? ")))
- ()
- (progn
- (erase-buffer)
- (and subject
- (progn (if (string-match "\\`Re: " subject)
- (while (string-match "\\`Re: " subject)
- (setq subject (substring subject 4))))
- (setq subject (concat "Re: " subject))))
- (and from
- (progn
- (let ((stop-pos
- (string-match " *at \\| *@ \\| *(\\| *<" from)))
- (setq message-of
- (concat
- (if stop-pos (substring from 0 stop-pos) from)
- "'s message "
- (if message-id
- (concat message-id " of ")
- "of ")
- date)))))
- (news-setup
- nil
- subject
- message-of
- newsgroups
- buffer)
- (if followup-to
- (progn (news-reply-followup-to)
- (insert followup-to)))
- (if distribution
- (progn
- (mail-position-on-field "Distribution")
- (insert distribution)))
- (mail-position-on-field "References")
- (if references
- (insert references))
- (if (and references message-id)
- (insert " "))
- (if message-id
- (insert message-id))
- (goto-char (point-max))))))
- (message "")))
-
-;@@ the guts of news-reply and news-post-news should be combined. -tower
-;;;###autoload
-(defun news-post-news ()
- "Begin editing a new USENET news article to be posted.
-Type \\[describe-mode] once editing the article to get a list of commands."
- (interactive)
- (if (y-or-n-p "Are you sure you want to post to all of USENET? ")
- (let ((buffer (current-buffer)))
- (save-restriction
- (and (not (= 0 (buffer-size))) ;@@real problem is non-existence of
- ;@@ of article file
- (equal major-mode 'news-mode) ;@@ if rmail-mode,
- ;@@ should show full headers
- (progn
- (news-show-all-headers) ;@@ should save/restore header state,
- ;@@ 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")))
- (pop-to-buffer "*post-news*")
- (news-reply-mode)
- (if (and (buffer-modified-p)
- (not (y-or-n-p "Unsent article being composed; erase it? ")))
- () ;@@ not saving point from last time
- (progn (erase-buffer)
- (news-setup () () () () buffer))))
- (message "")))
-
-(defun news-mail-other-window ()
- "Send mail in another window.
-While composing the message, use \\[news-reply-yank-original] to yank the
-original message into it."
- (interactive)
- (mail-other-window nil nil nil nil nil (current-buffer)))
-
-;;; rnewspost.el ends here
diff --git a/lisp/mail/sendmail.el b/lisp/mail/sendmail.el
deleted file mode 100644
index 0f697450c5a..00000000000
--- a/lisp/mail/sendmail.el
+++ /dev/null
@@ -1,1228 +0,0 @@
-;;; sendmail.el --- mail sending commands for Emacs.
-
-;; Copyright (C) 1985, 86, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This mode provides mail-sending facilities from within Emacs. It is
-;; documented in the Emacs user's manual.
-
-;;; Code:
-
-;;;###autoload
-(defvar mail-from-style 'angles "\
-*Specifies how \"From:\" fields look.
-
-If `nil', they contain just the return address like:
- king@grassland.com
-If `parens', they look like:
- king@grassland.com (Elvis Parsley)
-If `angles', they look like:
- Elvis Parsley <king@grassland.com>")
-
-;;;###autoload
-(defvar 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.")
-
-;;;###autoload
-(defvar 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.")
-
-;;;###autoload
-(defvar 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.")
-
-;; Useful to set in site-init.el
-;;;###autoload
-(defvar send-mail-function 'sendmail-send-it "\
-Function to call to send the current buffer as mail.
-The headers should be delimited by a line whose contents
-match the variable `mail-header-separator'.")
-
-;;;###autoload
-(defvar mail-header-separator "--text follows this line--" "\
-*Line used to separate headers from text in messages being composed.")
-
-;; Set up mail-header-separator for use as a category text property.
-(put 'mail-header-separator 'rear-nonsticky '(category))
-;;; This was a nice idea, for preventing accidental modification of
-;;; the separator. But I found it also prevented or obstructed
-;;; certain deliberate operations, such as copying the separator line
-;;; up to the top to send myself a copy of an already sent outgoing message
-;;; and other things. So I turned it off. --rms.
-;;;(put 'mail-header-separator 'read-only t)
-
-;;;###autoload
-(defvar mail-archive-file-name nil "\
-*Name of file to write all outgoing messages in, or nil for none.
-This can be an inbox file or an Rmail file.")
-
-;;;###autoload
-(defvar mail-default-reply-to nil
- "*Address to insert as default Reply-to field of outgoing messages.
-If nil, it will be initialized from the REPLYTO environment variable
-when you first send mail.")
-
-;;;###autoload
-(defvar mail-alias-file nil
- "*If non-nil, the name of a file to use instead of `/usr/lib/aliases'.
-This file defines aliases to be expanded by the mailer; this is a different
-feature from that of defining aliases in `.mailrc' to be expanded in Emacs.
-This variable has no effect unless your system uses sendmail as its mailer.")
-
-;;;###autoload
-(defvar mail-personal-alias-file "~/.mailrc"
- "*If non-nil, the name of the user's personal mail alias file.
-This file typically should be in same format as the `.mailrc' file used by
-the `Mail' or `mailx' program.
-This file need not actually exist.")
-
-(defvar mail-setup-hook nil
- "Normal hook, run each time a new outgoing mail message is initialized.
-The function `mail-setup' runs this hook.")
-
-(defvar mail-aliases t
- "Alist of mail address aliases,
-or t meaning should be initialized from your mail aliases file.
-\(The file's name is normally `~/.mailrc', but your MAILRC environment
-variable can override that name.)
-The alias definitions in the file have this form:
- alias ALIAS MEANING")
-
-(defvar mail-alias-modtime nil
- "The modification time of your mail alias file when it was last examined.")
-
-(defvar mail-yank-prefix nil
- "*Prefix insert on lines of yanked message being replied to.
-nil means use indentation.")
-(defvar mail-indentation-spaces 3
- "*Number of spaces to insert at the beginning of each cited line.
-Used by `mail-yank-original' via `mail-indent-citation'.")
-(defvar mail-yank-hooks nil
- "Obsolete hook for modifying a citation just inserted in the mail buffer.
-Each hook function can find the citation between (point) and (mark t).
-And each hook function should leave point and mark around the citation
-text as modified.
-
-This is a normal hook, misnamed for historical reasons.
-It is semi-obsolete and mail agents should no longer use it.")
-
-(defvar mail-citation-hook nil
- "*Hook for modifying a citation just inserted in the mail buffer.
-Each hook function can find the citation between (point) and (mark t).
-And each hook function should leave point and mark around the citation
-text as modified.
-
-If this hook is entirely empty (nil), a default action is taken
-instead of no action.")
-
-(defvar mail-abbrevs-loaded nil)
-(defvar mail-mode-map nil)
-
-(autoload 'build-mail-aliases "mailalias"
- "Read mail aliases from user's personal aliases file 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' and their `Resent-' variants.
-Optional second arg EXCLUDE may be a regular expression defining text to be
-removed from alias expansions."
- nil)
-
-;;;###autoload
-(defvar mail-signature nil
- "*Text inserted at end of mail buffer when a message is initialized.
-If t, it means to insert the contents of the file `mail-signature-file'.")
-
-(defvar mail-signature-file "~/.signature"
- "*File containing the text inserted at end of mail buffer.")
-
-(defvar mail-reply-action nil)
-(defvar mail-send-actions nil
- "A list of actions to be performed upon successful sending of a message.")
-(put 'mail-reply-action 'permanent-local t)
-(put 'mail-send-actions 'permanent-local t)
-
-(defvar mail-default-headers nil
- "*A string containing header lines, to be inserted in outgoing messages.
-It is inserted before you edit the message,
-so you can edit or delete these lines.")
-
-(defvar mail-bury-selects-summary t
- "*If non-nil, try to show RMAIL summary buffer after returning from mail.
-The functions \\[mail-send-on-exit] or \\[mail-dont-send] select
-the RMAIL summary buffer before returning, if it exists and this variable
-is non-nil.")
-
-;; Note: could use /usr/ucb/mail instead of sendmail;
-;; options -t, and -v if not interactive.
-(defvar mail-mailer-swallows-blank-line
- (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)" system-configuration)
- (file-readable-p "/etc/sendmail.cf")
- (let ((buffer (get-buffer-create " *temp*")))
- (unwind-protect
- (save-excursion
- (set-buffer buffer)
- (insert-file-contents "/etc/sendmail.cf")
- (goto-char (point-min))
- (let ((case-fold-search nil))
- (re-search-forward "^OR\\>" nil t)))
- (kill-buffer buffer))))
- ;; According to RFC822, "The field-name must be composed of printable
- ;; ASCII characters (i.e. characters that have decimal values between
- ;; 33 and 126, except colon)", i.e. any chars except ctl chars,
- ;; space, or colon.
- '(looking-at "[ \t]\\|[][!\"#$%&'()*+,-./0-9;<=>?@A-Z\\\\^_`a-z{|}~]+:"))
- "Set this non-nil if the system's mailer runs the header and body together.
-\(This problem exists on Sunos 4 when sendmail is run in remote mode.)
-The value should be an expression to test whether the problem will
-actually occur.")
-
-(defvar mail-mode-syntax-table nil
- "Syntax table used while in mail mode.")
-
-(if (not mail-mode-syntax-table)
- (progn
- (setq mail-mode-syntax-table (copy-syntax-table text-mode-syntax-table))
- (modify-syntax-entry ?% ". " mail-mode-syntax-table)))
-
-(defvar mail-font-lock-keywords
- (eval-when-compile
- (let* ((cite-chars "[>|}]")
- (cite-prefix "A-Za-z")
- (cite-suffix (concat cite-prefix "0-9_.@-`'\"")))
- (list '("^To:" . font-lock-function-name-face)
- '("^B?CC:\\|^Reply-to:" . font-lock-keyword-face)
- '("^\\(Subject:\\)[ \t]*\\(.+\\)?"
- (1 font-lock-comment-face) (2 font-lock-type-face nil t))
- ;; Use EVAL to delay in case `mail-header-separator' gets changed.
- '(eval cons (concat "^" (regexp-quote mail-header-separator) "$")
- 'font-lock-comment-face)
- ;; Use MATCH-ANCHORED to effectively anchor the regexp left side.
- `(,cite-chars
- (,(concat "\\=[ \t]*"
- "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
- cite-chars ".*")
- (beginning-of-line) (end-of-line)
- (0 font-lock-reference-face)))
- '("^\\(X-[A-Za-z0-9-]+\\|In-reply-to\\):.*"
- . font-lock-string-face))))
- "Additional expressions to highlight in Mail mode.")
-
-(defvar mail-send-hook nil
- "Normal hook run before sending mail, in Mail mode.")
-
-(defun sendmail-sync-aliases ()
- (let ((modtime (nth 5 (file-attributes mail-personal-alias-file))))
- (or (equal mail-alias-modtime modtime)
- (setq mail-alias-modtime modtime
- mail-aliases t))))
-
-(defun mail-setup (to subject in-reply-to cc replybuffer actions)
- (or mail-default-reply-to
- (setq mail-default-reply-to (getenv "REPLYTO")))
- (sendmail-sync-aliases)
- (if (eq mail-aliases t)
- (progn
- (setq mail-aliases nil)
- (if (file-exists-p mail-personal-alias-file)
- (build-mail-aliases))))
- (setq mail-send-actions actions)
- (setq mail-reply-action replybuffer)
- (goto-char (point-min))
- (insert "To: ")
- (save-excursion
- (if to
- ;; 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")
- (address-start (point)))
- (insert to "\n")
- (fill-region-as-paragraph address-start (point-max)))
- (newline))
- (if cc
- (let ((fill-prefix "\t")
- (address-start (progn (insert "CC: ") (point))))
- (insert cc "\n")
- (fill-region-as-paragraph address-start (point-max))))
- (if in-reply-to
- (let ((fill-prefix "\t")
- (fill-column 78)
- (address-start (point)))
- (insert "In-reply-to: " in-reply-to "\n")
- (fill-region-as-paragraph address-start (point-max))))
- (insert "Subject: " (or subject "") "\n")
- (if mail-default-headers
- (insert mail-default-headers))
- (if mail-default-reply-to
- (insert "Reply-to: " mail-default-reply-to "\n"))
- (if mail-self-blind
- (insert "BCC: " user-mail-address "\n"))
- (if mail-archive-file-name
- (insert "FCC: " mail-archive-file-name "\n"))
- (put-text-property (point)
- (progn
- (insert mail-header-separator "\n")
- (1- (point)))
- 'category 'mail-header-separator)
- ;; Insert the signature. But remember the beginning of the message.
- (if to (setq to (point)))
- (cond ((eq mail-signature t)
- (if (file-exists-p mail-signature-file)
- (progn
- (insert "\n\n-- \n")
- (insert-file-contents mail-signature-file))))
- (mail-signature
- (insert mail-signature)))
- (goto-char (point-max))
- (or (bolp) (newline)))
- (if to (goto-char to))
- (or to subject in-reply-to
- (set-buffer-modified-p nil))
- (run-hooks 'mail-setup-hook))
-
-;;;###autoload
-(defun mail-mode ()
- "Major mode for editing mail to be sent.
-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 Subject:
- C-c C-f C-c move to CC: C-c C-f C-b move to BCC:
- C-c C-f C-f move to FCC:
-C-c C-t mail-text (move to beginning of message text).
-C-c C-w mail-signature (insert `mail-signature-file' file).
-C-c C-y mail-yank-original (insert current message, in Rmail).
-C-c C-q mail-fill-yanked-message (fill what was yanked).
-C-c C-v mail-sent-via (add a Sent-via field for each To or CC)."
- (interactive)
- (kill-all-local-variables)
- (make-local-variable 'mail-reply-action)
- (make-local-variable 'mail-send-actions)
- (set-syntax-table mail-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 'font-lock-defaults)
- (setq font-lock-defaults '(mail-font-lock-keywords t))
- (make-local-variable 'paragraph-separate)
- (make-local-variable 'paragraph-start)
- (make-local-variable 'normal-auto-fill-function)
- (setq normal-auto-fill-function 'mail-mode-auto-fill)
- (setq fill-paragraph-function 'mail-mode-fill-paragraph)
- ;; `-- ' precedes the signature. `-----' appears at the start of the
- ;; lines that delimit forwarded messages.
- ;; Lines containing just >= 3 dashes, perhaps after whitespace,
- ;; are also sometimes used and should be separators.
- (setq paragraph-start (concat (regexp-quote mail-header-separator)
- "$\\|[ \t]*[-_][-_][-_]+$\\|-- $\\|-----\\|"
- paragraph-start))
- (setq paragraph-separate (concat (regexp-quote mail-header-separator)
- "$\\|[ \t]*[-_][-_][-_]+$\\|-- $\\|-----\\|"
- paragraph-separate))
- (run-hooks 'text-mode-hook 'mail-mode-hook))
-
-(defun mail-mode-auto-fill ()
- "Carry out Auto Fill for Mail mode.
-If within the headers, this makes the new lines into continuation lines."
- (if (< (point)
- (save-excursion
- (goto-char (point-min))
- (if (search-forward mail-header-separator nil t)
- (point)
- 0)))
- (let ((old-line-start (save-excursion (beginning-of-line) (point))))
- (if (do-auto-fill)
- (save-excursion
- (beginning-of-line)
- (while (not (eq (point) old-line-start))
- (insert " ")
- (forward-line -1))
- t)))
- (do-auto-fill)))
-
-(defun mail-mode-fill-paragraph (arg)
- ;; Do something special only if within the headers.
- (if (< (point)
- (save-excursion
- (goto-char (point-min))
- (if (search-forward mail-header-separator nil t)
- (point)
- 0)))
- (let (beg end fieldname)
- (re-search-backward "^[-a-zA-Z]+:" nil 'yes)
- (setq beg (point))
- (setq fieldname
- (downcase (buffer-substring beg (1- (match-end 0)))))
- (forward-line 1)
- ;; Find continuation lines and get rid of their continuation markers.
- (while (looking-at "[ \t]")
- (delete-horizontal-space)
- (forward-line 1))
- (setq end (point-marker))
- (goto-char beg)
- ;; If this field contains addresses,
- ;; make sure we can fill after each address.
- (if (member fieldname
- '("to" "cc" "bcc" "from" "reply-to"
- "resent-to" "resent-cc" "resent-bcc"
- "resent-from" "resent-reply-to"))
- (while (search-forward "," end t)
- (or (looking-at "[ \t]")
- (insert " "))))
- (fill-region-as-paragraph beg end)
- ;; Mark all lines except the first as continuations.
- (goto-char beg)
- (forward-line 1)
- (while (< (point) end)
- (insert " ")
- (forward-line 1))
- (move-marker end nil)
- t)))
-
-;;; Set up keymap.
-
-(if mail-mode-map
- nil
- (setq mail-mode-map (nconc (make-sparse-keymap) text-mode-map))
- (define-key mail-mode-map "\M-\t" 'mail-complete)
- (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-f" 'mail-fcc)
- (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-f\C-r" 'mail-reply-to)
- (define-key mail-mode-map "\C-c\C-t" 'mail-text)
- (define-key mail-mode-map "\C-c\C-y" 'mail-yank-original)
- (define-key mail-mode-map "\C-c\C-r" 'mail-yank-region)
- (define-key mail-mode-map "\C-c\C-q" 'mail-fill-yanked-message)
- (define-key mail-mode-map "\C-c\C-w" 'mail-signature)
- (define-key mail-mode-map "\C-c\C-v" 'mail-sent-via)
- (define-key mail-mode-map "\C-c\C-c" 'mail-send-and-exit)
- (define-key mail-mode-map "\C-c\C-s" 'mail-send))
-
-(define-key mail-mode-map [menu-bar mail]
- (cons "Mail" (make-sparse-keymap "Mail")))
-
-(define-key mail-mode-map [menu-bar mail fill]
- '("Fill Citation" . mail-fill-yanked-message))
-
-(define-key mail-mode-map [menu-bar mail yank]
- '("Cite Original" . mail-yank-original))
-
-(define-key mail-mode-map [menu-bar mail signature]
- '("Insert Signature" . mail-signature))
-
-(define-key mail-mode-map [menu-bar mail cancel]
- '("Cancel" . mail-dont-send))
-
-(define-key mail-mode-map [menu-bar mail send-stay]
- '("Send, Keep Editing" . mail-send))
-
-(define-key mail-mode-map [menu-bar mail send]
- '("Send Message" . mail-send-and-exit))
-
-(define-key mail-mode-map [menu-bar headers]
- (cons "Headers" (make-sparse-keymap "Move to Header")))
-
-(define-key mail-mode-map [menu-bar headers reply-to]
- '("Reply-To" . mail-reply-to))
-
-(define-key mail-mode-map [menu-bar headers sent-via]
- '("Sent Via" . mail-sent-via))
-
-(define-key mail-mode-map [menu-bar headers text]
- '("Text" . mail-text))
-
-(define-key mail-mode-map [menu-bar headers bcc]
- '("Bcc" . mail-bcc))
-
-(define-key mail-mode-map [menu-bar headers fcc]
- '("Fcc" . mail-fcc))
-
-(define-key mail-mode-map [menu-bar headers cc]
- '("Cc" . mail-cc))
-
-(define-key mail-mode-map [menu-bar headers subject]
- '("Subject" . mail-subject))
-
-(define-key mail-mode-map [menu-bar headers to]
- '("To" . mail-to))
-
-;; User-level commands for sending.
-
-(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)
- (mail-bury arg))
-
-(defun mail-dont-send (arg)
- "Don't send the message you have been editing.
-Prefix arg means don't delete this window."
- (interactive "P")
- (mail-bury arg))
-
-(defun mail-bury (arg)
- "Bury this mail buffer."
- (let ((newbuf (other-buffer (current-buffer))))
- (bury-buffer (current-buffer))
- (if (and (or (window-dedicated-p (frame-selected-window))
- (assq 'mail-dedicated-frame (frame-parameters)))
- (not (null (delq (selected-frame) (visible-frame-list)))))
- (delete-frame (selected-frame))
- (let (rmail-flag summary-buffer)
- (and (not arg)
- (not (one-window-p))
- (save-excursion
- (set-buffer (window-buffer (next-window (selected-window) 'not)))
- (setq rmail-flag (eq major-mode 'rmail-mode))
- (setq summary-buffer
- (and mail-bury-selects-summary
- (boundp 'rmail-summary-buffer)
- rmail-summary-buffer
- (buffer-name rmail-summary-buffer)
- (not (get-buffer-window rmail-summary-buffer))
- rmail-summary-buffer))))
- (if rmail-flag
- ;; If the Rmail buffer has a summary, show that.
- (if summary-buffer (switch-to-buffer summary-buffer)
- (delete-window))
- (switch-to-buffer newbuf))))))
-
-(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)
- (if (if buffer-file-name
- (y-or-n-p "Send buffer contents as mail message? ")
- (or (buffer-modified-p)
- (y-or-n-p "Message already sent; resend? ")))
- (let ((inhibit-read-only t))
- (run-hooks 'mail-send-hook)
- (message "Sending...")
- (funcall send-mail-function)
- ;; Now perform actions on successful sending.
- (while mail-send-actions
- (condition-case nil
- (apply (car (car mail-send-actions))
- (cdr (car mail-send-actions)))
- (error))
- (setq mail-send-actions (cdr mail-send-actions)))
- (message "Sending...done")
- ;; If buffer has no file, mark it as unmodified and delete autosave.
- (if (not buffer-file-name)
- (progn
- (set-buffer-modified-p nil)
- (delete-auto-save-file-if-necessary t))))))
-
-;; This does the real work of sending a message via sendmail.
-;; It is called via the variable send-mail-function.
-
-(defun sendmail-send-it ()
- (require 'mail-utils)
- (let ((errbuf (if mail-interactive
- (generate-new-buffer " sendmail errors")
- 0))
- (tembuf (generate-new-buffer " sendmail temp"))
- (case-fold-search nil)
- resend-to-addresses
- delimline
- fcc-was-found
- (mailbuf (current-buffer)))
- (unwind-protect
- (save-excursion
- (set-buffer tembuf)
- (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))
- (sendmail-sync-aliases)
- (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))
- (goto-char (point-min))
- (while (re-search-forward "^Resent-\\(to\\|cc\\|bcc\\):" delimline t)
- (setq resend-to-addresses
- (save-restriction
- (narrow-to-region (point)
- (save-excursion
- (end-of-line)
- (point)))
- (append (mail-parse-comma-list)
- resend-to-addresses)))
- ;; Delete Resent-BCC ourselves
- (if (save-excursion (beginning-of-line)
- (looking-at "resent-bcc"))
- (delete-region (save-excursion (beginning-of-line) (point))
- (save-excursion (end-of-line) (1+ (point))))))
-;;; Apparently this causes a duplicate Sender.
-;;; ;; If the From is different than current user, insert Sender.
-;;; (goto-char (point-min))
-;;; (and (re-search-forward "^From:" delimline t)
-;;; (progn
-;;; (require 'mail-utils)
-;;; (not (string-equal
-;;; (mail-strip-quoted-names
-;;; (save-restriction
-;;; (narrow-to-region (point-min) delimline)
-;;; (mail-fetch-field "From")))
-;;; (user-login-name))))
-;;; (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\\)+\\b" delimline t)
- (replace-match "")
- ;; This one matches a Subject just before the header delimiter.
- (if (and (re-search-forward "^Subject:\\([ \t]*\n\\)+" delimline t)
- (= (match-end 0) delimline))
- (replace-match "")))
- ;; Put the "From:" field in unless for some odd reason
- ;; they put one in themselves.
- (goto-char (point-min))
- (if (not (re-search-forward "^From:" delimline t))
- (let* ((login user-mail-address)
- (fullname (user-full-name)))
- (cond ((eq mail-from-style 'angles)
- (insert "From: " fullname)
- (let ((fullname-start (+ (point-min) 6))
- (fullname-end (point-marker)))
- (goto-char fullname-start)
- ;; Look for a character that cannot appear unquoted
- ;; according to RFC 822.
- (if (re-search-forward "[^- !#-'*+/-9=?A-Z^-~]"
- fullname-end 1)
- (progn
- ;; Quote fullname, escaping specials.
- (goto-char fullname-start)
- (insert "\"")
- (while (re-search-forward "[\"\\]"
- fullname-end 1)
- (replace-match "\\\\\\&" t))
- (insert "\""))))
- (insert " <" login ">\n"))
- ((eq mail-from-style 'parens)
- (insert "From: " login " (")
- (let ((fullname-start (point)))
- (insert fullname)
- (let ((fullname-end (point-marker)))
- (goto-char fullname-start)
- ;; RFC 822 says \ and nonmatching parentheses
- ;; must be escaped in comments.
- ;; Escape every instance of ()\ ...
- (while (re-search-forward "[()\\]" fullname-end 1)
- (replace-match "\\\\\\&" t))
- ;; ... then undo escaping of matching parentheses,
- ;; including matching nested parentheses.
- (goto-char fullname-start)
- (while (re-search-forward
- "\\(\\=\\|[^\\]\\(\\\\\\\\\\)*\\)\\\\(\\(\\([^\\]\\|\\\\\\\\\\)*\\)\\\\)"
- fullname-end 1)
- (replace-match "\\1(\\3)" t)
- (goto-char fullname-start))))
- (insert ")\n"))
- ((null mail-from-style)
- (insert "From: " login "\n")))))
- ;; Insert an extra newline if we need it to work around
- ;; Sun's bug that swallows newlines.
- (goto-char (1+ delimline))
- (if (eval mail-mailer-swallows-blank-line)
- (newline))
- ;; Find and handle any FCC fields.
- (goto-char (point-min))
- (if (re-search-forward "^FCC:" delimline t)
- (progn
- (setq fcc-was-found t)
- (mail-do-fcc delimline)))
- (if mail-interactive
- (save-excursion
- (set-buffer errbuf)
- (erase-buffer))))
- (goto-char (point-min))
- (if (let ((case-fold-search t))
- (re-search-forward "^To:\\|^cc:\\|^bcc:\\|^resent-to:\
-\\|^resent-cc:\\|^resent-bcc:"
- delimline t))
- (let ((default-directory "/"))
- (apply 'call-process-region
- (append (list (point-min) (point-max)
- (if (boundp 'sendmail-program)
- sendmail-program
- "/usr/lib/sendmail")
- nil errbuf nil "-oi")
- ;; 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)))
- (and mail-alias-file
- (list (concat "-oA" mail-alias-file)))
- (if mail-interactive
- ;; These mean "report errors to terminal"
- ;; and "deliver interactively"
- '("-oep" "-odi")
- ;; These mean "report errors by mail"
- ;; and "deliver in background".
- '("-oem" "-odb"))
- ;; Get the addresses from the message
- ;; unless this is a resend.
- ;; We must not do that for a resend
- ;; because we would find the original addresses.
- ;; For a resend, include the specific addresses.
- (or resend-to-addresses
- '("-t")))))
- (or fcc-was-found
- (error "No recipients")))
- (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))
- (time (current-time))
- (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)
- ;; This initial newline is written out if the fcc file already exists.
- (insert "\nFrom " (user-login-name) " "
- (current-time-string time) "\n")
- ;; Insert the time zone before the year.
- (forward-char -1)
- (forward-word -1)
- (require 'mail-utils)
- (insert (mail-rfc822-time-zone time) " ")
- (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 (find-buffer-visiting (car fcc-list)))
- (curbuf (current-buffer))
- (beg (point-min)) (end (point-max))
- (beg2 (save-excursion (goto-char (point-min))
- (forward-line 2) (point))))
- (if buffer
- ;; File is present in a buffer => append to that buffer.
- (save-excursion
- (set-buffer buffer)
- ;; Keep the end of the accessible portion at the same place
- ;; unless it is the end of the buffer.
- (let ((max (if (/= (1+ (buffer-size)) (point-max))
- (point-max))))
- (unwind-protect
- ;; Code below lifted from rmailout.el
- ;; function rmail-output-to-rmail-file:
- (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 "\C-l\n0, unseen,,\n*** EOOH ***\n"
- "Date: " (mail-rfc822-date) "\n")
- (insert-buffer-substring curbuf beg2 end)
- (insert "\n\C-_")
- (goto-char (point-min))
- (widen)
- (search-backward "\n\^_")
- (narrow-to-region (point) (point-max))
- (rmail-count-new-messages t)
- (rmail-show-message msg)
- (setq max nil))
- ;; 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 curbuf beg end)))
- (if max (narrow-to-region (point-min) max)))))
- ;; Else append to the file directly.
- (if (and (file-exists-p (car fcc-list))
- (mail-file-babyl-p (car fcc-list)))
- ;; If the file is a Babyl file,
- ;; convert the message to Babyl format.
- (save-excursion
- (set-buffer (get-buffer-create " mail-temp"))
- (setq buffer-read-only nil)
- (erase-buffer)
- (insert "\C-l\n0, unseen,,\n*** EOOH ***\n"
- "Date: " (mail-rfc822-date) "\n")
- (insert-buffer-substring curbuf beg2 end)
- (insert "\n\C-_")
- (write-region (point-min) (point-max) (car fcc-list) t)
- (erase-buffer))
- (write-region
- (1+ (point-min)) (point-max) (car fcc-list) t))))
- (setq fcc-list (cdr fcc-list))))
- (kill-buffer tembuf)))
-
-(defun mail-sent-via ()
- "Make a Sent-via header line from each To or CC header line."
- (interactive)
- (save-excursion
- (goto-char (point-min))
- ;; find the header-separator
- (search-forward (concat "\n" mail-header-separator "\n"))
- (forward-line -1)
- ;; put a marker at the end of the header
- (let ((end (point-marker))
- (case-fold-search t)
- to-line)
- (goto-char (point-min))
- ;; search for the To: lines and make Sent-via: lines from them
- ;; search for the next To: line
- (while (re-search-forward "^\\(to\\|cc\\):" end t)
- ;; Grab this line plus all its continuations, sans the `to:'.
- (let ((to-line
- (buffer-substring (point)
- (progn
- (if (re-search-forward "^[^ \t\n]" end t)
- (backward-char 1)
- (goto-char end))
- (point)))))
- ;; Insert a copy, with altered header field name.
- (insert-before-markers "Sent-via:" to-line))))))
-
-(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-fcc (folder)
- "Add a new FCC field, with file name completion."
- (interactive "FFolder carbon copy: ")
- (expand-abbrev)
- (or (mail-position-on-field "fcc" t) ;Put new field after exiting FCC.
- (mail-position-on-field "to"))
- (insert "\nFCC: " folder))
-
-(defun mail-reply-to ()
- "Move point to end of Reply-To-field."
- (interactive)
- (expand-abbrev)
- (mail-position-on-field "Reply-To"))
-
-(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) "$"))
- (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-text ()
- "Move point to beginning of message text."
- (interactive)
- (expand-abbrev)
- (goto-char (point-min))
- (search-forward (concat "\n" mail-header-separator "\n")))
-
-(defun mail-signature (atpoint)
- "Sign letter with contents of the file `mail-signature-file'.
-Prefix arg means put contents at point."
- (interactive "P")
- (save-excursion
- (or atpoint
- (goto-char (point-max)))
- (skip-chars-backward " \t\n")
- (end-of-line)
- (or atpoint
- (delete-region (point) (point-max)))
- (insert "\n\n-- \n")
- (insert-file-contents (expand-file-name mail-signature-file))))
-
-(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-indent-citation ()
- "Modify text just inserted from a message to be cited.
-The inserted text should be the region.
-When this function returns, the region is again around the modified text.
-
-Normally, indent each nonblank line `mail-indentation-spaces' spaces.
-However, if `mail-yank-prefix' is non-nil, insert that prefix on each line."
- (mail-yank-clear-headers (region-beginning) (region-end))
- (if (null mail-yank-prefix)
- (indent-rigidly (region-beginning) (region-end)
- mail-indentation-spaces)
- (save-excursion
- (goto-char (region-beginning))
- (while (< (point) (region-end))
- (insert mail-yank-prefix)
- (forward-line 1)))))
-
-(defun mail-yank-original (arg)
- "Insert the message being replied to, if any (in rmail).
-Puts point after the text and mark before.
-Normally, indents each nonblank line ARG spaces (default 3).
-However, if `mail-yank-prefix' is non-nil, insert that prefix on each line.
-
-Just \\[universal-argument] as argument means don't indent, insert no prefix,
-and don't delete any header fields."
- (interactive "P")
- (if mail-reply-action
- (let ((start (point))
- (original mail-reply-action))
- (and (consp original) (eq (car original) 'insert-buffer)
- (setq original (nth 1 original)))
- (if (consp original)
- (apply (car original) (cdr original))
- ;; If the original message is in another window in the same frame,
- ;; delete that window to save screen space.
- ;; t means don't alter other frames.
- (delete-windows-on original t)
- (insert-buffer original))
- (if (consp arg)
- nil
- (goto-char start)
- (let ((mail-indentation-spaces (if arg (prefix-numeric-value arg)
- mail-indentation-spaces)))
- (if mail-citation-hook
- (run-hooks 'mail-citation-hook)
- (if mail-yank-hooks
- (run-hooks 'mail-yank-hooks)
- (mail-indent-citation)))))
- ;; This is like exchange-point-and-mark, but doesn't activate the mark.
- ;; It is cleaner to avoid activation, even though the command
- ;; loop would deactivate the mark because we inserted text.
- (goto-char (prog1 (mark t)
- (set-marker (mark-marker) (point) (current-buffer))))
- (if (not (eolp)) (insert ?\n)))))
-
-(defun mail-yank-clear-headers (start end)
- (if (< end start)
- (let (temp)
- (setq temp start start end end temp)))
- (if mail-yank-ignored-headers
- (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)))))))))
-
-(defun mail-yank-region (arg)
- "Insert the selected region from the message being replied to.
-Puts point after the text and mark before.
-Normally, indents each nonblank line ARG spaces (default 3).
-However, if `mail-yank-prefix' is non-nil, insert that prefix on each line.
-
-Just \\[universal-argument] as argument means don't indent, insert no prefix,
-and don't delete any header fields."
- (interactive "P")
- (and (consp mail-reply-action)
- (eq (car mail-reply-action) 'insert-buffer)
- (let ((buffer (nth 1 mail-reply-action))
- (start (point)))
- ;; Insert the citation text.
- (insert (with-current-buffer buffer
- (buffer-substring (point) (mark))))
- (push-mark start)
- ;; Indent or otherwise annotate the citation text.
- (if (consp arg)
- nil
- (let ((mail-indentation-spaces (if arg (prefix-numeric-value arg)
- mail-indentation-spaces)))
- (if mail-citation-hook
- (run-hooks 'mail-citation-hook)
- (if mail-yank-hooks
- (run-hooks 'mail-yank-hooks)
- (mail-indent-citation))))))))
-
-;; Put these last, to reduce chance of lossage from quitting in middle of loading the file.
-
-;;;###autoload
-(defun mail (&optional noerase to subject in-reply-to cc replybuffer actions)
- "Edit a message to be sent. Prefix arg means resume editing (don't erase).
-When this function returns, the buffer `*mail*' is selected.
-The value is t if the message was newly initialized; otherwise, nil.
-
-Optionally, the signature file `mail-signature-file' can be inserted at the
-end; see the variable `mail-signature'.
-
-\\<mail-mode-map>
-While editing message, type \\[mail-send-and-exit] 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.
-
-The normal hook `mail-setup-hook' is run after the message is
-initialized. It can add more default fields to the message.
-
-When calling from a program, the first argument if non-nil says
-not to erase the existing contents of the `*mail*' buffer.
-
-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 which contains an
- original message being replied to, or else an action
- of the form (FUNCTION . ARGS) which says how to insert the original.
- Or it can be nil, if not replying to anything.
-The seventh argument ACTIONS is a list of actions to take
- if/when the message is sent. Each action looks like (FUNCTION . ARGS);
- when the message is sent, we apply FUNCTION to ARGS.
- This is how Rmail arranges to mark messages `answered'."
- (interactive "P")
-;;; This is commented out because I found it was confusing in practice.
-;;; It is easy enough to rename *mail* by hand with rename-buffer
-;;; if you want to have multiple mail buffers.
-;;; And then you can control which messages to save. --rms.
-;;; (let ((index 1)
-;;; buffer)
-;;; ;; If requested, look for a mail buffer that is modified and go to it.
-;;; (if noerase
-;;; (progn
-;;; (while (and (setq buffer
-;;; (get-buffer (if (= 1 index) "*mail*"
-;;; (format "*mail*<%d>" index))))
-;;; (not (buffer-modified-p buffer)))
-;;; (setq index (1+ index)))
-;;; (if buffer (switch-to-buffer buffer)
-;;; ;; If none exists, start a new message.
-;;; ;; This will never re-use an existing unmodified mail buffer
-;;; ;; (since index is not 1 anymore). Perhaps it should.
-;;; (setq noerase nil))))
-;;; ;; Unless we found a modified message and are happy, start a new message.
-;;; (if (not noerase)
-;;; (progn
-;;; ;; Look for existing unmodified mail buffer.
-;;; (while (and (setq buffer
-;;; (get-buffer (if (= 1 index) "*mail*"
-;;; (format "*mail*<%d>" index))))
-;;; (buffer-modified-p buffer))
-;;; (setq index (1+ index)))
-;;; ;; If none, make a new one.
-;;; (or buffer
-;;; (setq buffer (generate-new-buffer "*mail*")))
-;;; ;; Go there and initialize it.
-;;; (switch-to-buffer buffer)
-;;; (erase-buffer)
-;;; (setq default-directory (expand-file-name "~/"))
-;;; (auto-save-mode auto-save-default)
-;;; (mail-mode)
-;;; (mail-setup to subject in-reply-to cc replybuffer actions)
-;;; (if (and buffer-auto-save-file-name
-;;; (file-exists-p buffer-auto-save-file-name))
-;;; (message "Auto save file for draft message exists; consider M-x mail-recover"))
-;;; t))
- (pop-to-buffer "*mail*")
- ;; Put the auto-save file in the home dir
- ;; to avoid any danger that it can't be written.
- (if (file-exists-p (expand-file-name "~/"))
- (setq default-directory (expand-file-name "~/")))
- (auto-save-mode auto-save-default)
- (mail-mode)
- ;; Disconnect the buffer from its visited file
- ;; (in case the user has actually visited a file *mail*).
-; (set-visited-file-name nil)
- (let (initialized)
- (and (not noerase)
- (or (not (buffer-modified-p))
- (y-or-n-p "Unsent message being composed; erase it? "))
- (let ((inhibit-read-only t))
- (erase-buffer)
- (mail-setup to subject in-reply-to cc replybuffer actions)
- (setq initialized t)))
- (if (and buffer-auto-save-file-name
- (file-exists-p buffer-auto-save-file-name))
- (message "Auto save file for draft message exists; consider M-x mail-recover"))
- initialized))
-
-(defun mail-recover ()
- "Reread contents of current buffer from its last auto-save file."
- (interactive)
- (let ((file-name (make-auto-save-file-name)))
- (cond ((save-window-excursion
- (if (not (eq system-type 'vax-vms))
- (with-output-to-temp-buffer "*Directory*"
- (buffer-disable-undo standard-output)
- (let ((default-directory "/"))
- (call-process
- "ls" nil standard-output nil "-l" file-name))))
- (yes-or-no-p (format "Recover auto save file %s? " file-name)))
- (let ((buffer-read-only nil))
- (erase-buffer)
- (insert-file-contents file-name nil)))
- (t (error "mail-recover cancelled")))))
-
-;;;###autoload
-(defun mail-other-window (&optional noerase to subject in-reply-to cc replybuffer sendactions)
- "Like `mail' command, but display mail buffer in another window."
- (interactive "P")
- (let ((pop-up-windows t)
- (special-display-buffer-names nil)
- (special-display-regexps nil)
- (same-window-buffer-names nil)
- (same-window-regexps nil))
- (pop-to-buffer "*mail*"))
- (mail noerase to subject in-reply-to cc replybuffer sendactions))
-
-;;;###autoload
-(defun mail-other-frame (&optional noerase to subject in-reply-to cc replybuffer sendactions)
- "Like `mail' command, but display mail buffer in another frame."
- (interactive "P")
- (let ((pop-up-frames t)
- (special-display-buffer-names nil)
- (special-display-regexps nil)
- (same-window-buffer-names nil)
- (same-window-regexps nil))
- (pop-to-buffer "*mail*"))
- (mail noerase to subject in-reply-to cc replybuffer sendactions))
-
-;;; Do not execute these when sendmail.el is loaded,
-;;; only in loaddefs.el.
-;;;###autoload (define-key ctl-x-map "m" 'mail)
-;;;###autoload (define-key ctl-x-4-map "m" 'mail-other-window)
-;;;###autoload (define-key ctl-x-5-map "m" 'mail-other-frame)
-
-;;;###autoload (add-hook 'same-window-buffer-names "*mail*")
-
-;;; Do not add anything but external entries on this page.
-
-(provide 'sendmail)
-
-;;; sendmail.el ends here
diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el
deleted file mode 100644
index 925a6ec2e83..00000000000
--- a/lisp/mail/smtpmail.el
+++ /dev/null
@@ -1,525 +0,0 @@
-;; Simple SMTP protocol (RFC 821) for sending mail
-
-;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Tomoji Kagatani <kagatani@rbc.ncl.omron.co.jp>
-;; Maintainer: Brian D. Carlstrom <bdc@ai.mit.edu>
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Send Mail to smtp host from smtpmail temp buffer.
-
-;; Please add these lines in your .emacs(_emacs).
-;;
-;;(setq send-mail-function 'smtpmail-send-it)
-;;(setq smtpmail-default-smtp-server "YOUR SMTP HOST")
-;;(setq smtpmail-smtp-service "smtp")
-;;(setq smtpmail-local-domain "YOUR DOMAIN NAME")
-;;(setq smtpmail-debug-info t)
-;;(load-library "smtpmail")
-;;(setq smtpmail-code-conv-from nil)
-;;(setq user-full-name "YOUR NAME HERE")
-
-;;; Code:
-
-(require 'sendmail)
-
-;;;
-(defvar smtpmail-default-smtp-server nil
- "*Specify default SMTP server.")
-
-(defvar smtpmail-smtp-server
- (or (getenv "SMTPSERVER") smtpmail-default-smtp-server)
- "*The name of the host running SMTP server.")
-
-(defvar smtpmail-smtp-service 25
- "*SMTP service port number. smtp or 25 .")
-
-(defvar smtpmail-local-domain nil
- "*Local domain name without a host name.
-If the function (system-name) returns the full internet address,
-don't define this value.")
-
-(defvar smtpmail-debug-info nil
- "*smtpmail debug info printout. messages and process buffer.")
-
-(defvar smtpmail-code-conv-from nil ;; *junet*
- "*smtpmail code convert from this code to *internal*..for tiny-mime..")
-
-;;;
-;;;
-;;;
-
-(defun smtpmail-send-it ()
- (require 'mail-utils)
- (let ((errbuf (if mail-interactive
- (generate-new-buffer " smtpmail errors")
- 0))
- (tembuf (generate-new-buffer " smtpmail temp"))
- (case-fold-search nil)
- resend-to-addresses
- delimline
- (mailbuf (current-buffer)))
- (unwind-protect
- (save-excursion
- (set-buffer tembuf)
- (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))
-;; (sendmail-synch-aliases)
- (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))
- (goto-char (point-min))
- (goto-char (point-min))
- (while (re-search-forward "^Resent-to:" delimline t)
- (setq resend-to-addresses
- (save-restriction
- (narrow-to-region (point)
- (save-excursion
- (end-of-line)
- (point)))
- (append (mail-parse-comma-list)
- resend-to-addresses))))
-;;; Apparently this causes a duplicate Sender.
-;;; ;; If the From is different than current user, insert Sender.
-;;; (goto-char (point-min))
-;;; (and (re-search-forward "^From:" delimline t)
-;;; (progn
-;;; (require 'mail-utils)
-;;; (not (string-equal
-;;; (mail-strip-quoted-names
-;;; (save-restriction
-;;; (narrow-to-region (point-min) delimline)
-;;; (mail-fetch-field "From")))
-;;; (user-login-name))))
-;;; (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 ""))
- ;; Put the "From:" field in unless for some odd reason
- ;; they put one in themselves.
- (goto-char (point-min))
- (if (not (re-search-forward "^From:" delimline t))
- (let* ((login user-mail-address)
- (fullname (user-full-name)))
- (cond ((eq mail-from-style 'angles)
- (insert "From: " fullname)
- (let ((fullname-start (+ (point-min) 6))
- (fullname-end (point-marker)))
- (goto-char fullname-start)
- ;; Look for a character that cannot appear unquoted
- ;; according to RFC 822.
- (if (re-search-forward "[^- !#-'*+/-9=?A-Z^-~]"
- fullname-end 1)
- (progn
- ;; Quote fullname, escaping specials.
- (goto-char fullname-start)
- (insert "\"")
- (while (re-search-forward "[\"\\]"
- fullname-end 1)
- (replace-match "\\\\\\&" t))
- (insert "\""))))
- (insert " <" login ">\n"))
- ((eq mail-from-style 'parens)
- (insert "From: " login " (")
- (let ((fullname-start (point)))
- (insert fullname)
- (let ((fullname-end (point-marker)))
- (goto-char fullname-start)
- ;; RFC 822 says \ and nonmatching parentheses
- ;; must be escaped in comments.
- ;; Escape every instance of ()\ ...
- (while (re-search-forward "[()\\]" fullname-end 1)
- (replace-match "\\\\\\&" t))
- ;; ... then undo escaping of matching parentheses,
- ;; including matching nested parentheses.
- (goto-char fullname-start)
- (while (re-search-forward
- "\\(\\=\\|[^\\]\\(\\\\\\\\\\)*\\)\\\\(\\(\\([^\\]\\|\\\\\\\\\\)*\\)\\\\)"
- fullname-end 1)
- (replace-match "\\1(\\3)" t)
- (goto-char fullname-start))))
- (insert ")\n"))
- ((null mail-from-style)
- (insert "From: " login "\n")))))
- ;; Insert an extra newline if we need it to work around
- ;; Sun's bug that swallows newlines.
- (goto-char (1+ delimline))
- (if (eval mail-mailer-swallows-blank-line)
- (newline))
- ;; Find and handle any FCC fields.
- (goto-char (point-min))
- (if (re-search-forward "^FCC:" delimline t)
- (mail-do-fcc delimline))
- (if mail-interactive
- (save-excursion
- (set-buffer errbuf)
- (erase-buffer))))
- ;;
- ;;
- ;;
- (setq smtpmail-address-buffer (generate-new-buffer "*smtp-mail*"))
- (setq smtpmail-recipient-address-list
- (or resend-to-addresses
- (smtpmail-deduce-address-list tembuf (point-min) delimline)))
- (kill-buffer smtpmail-address-buffer)
-
- (smtpmail-do-bcc delimline)
-
- (if (not (null smtpmail-recipient-address-list))
- (if (not (smtpmail-via-smtp smtpmail-recipient-address-list tembuf))
- (error "Sending failed; SMTP protocol error"))
- (error "Sending failed; no recipients"))
- )
- (kill-buffer tembuf)
- (if (bufferp errbuf)
- (kill-buffer errbuf)))))
-
-
-;(defun smtpmail-via-smtp (host,port,sender,destination,smtpmail-text-buffer)
-
-(defun smtpmail-fqdn ()
- (if smtpmail-local-domain
- (concat (system-name) "." smtpmail-local-domain)
- (system-name)))
-
-(defun smtpmail-via-smtp (recipient smtpmail-text-buffer)
- (let ((process nil)
- (host smtpmail-smtp-server)
- (port smtpmail-smtp-service)
- response-code
- greeting
- process-buffer)
- (unwind-protect
- (catch 'done
- ;; get or create the trace buffer
- (setq process-buffer
- (get-buffer-create (format "*trace of SMTP session to %s*" host)))
-
- ;; clear the trace buffer of old output
- (save-excursion
- (set-buffer process-buffer)
- (erase-buffer))
-
- ;; open the connection to the server
- (setq process (open-network-stream "SMTP" process-buffer host port))
- (and (null process) (throw 'done nil))
-
- ;; set the send-filter
- (set-process-filter process 'smtpmail-process-filter)
-
- (save-excursion
- (set-buffer process-buffer)
- (make-local-variable 'smtpmail-read-point)
- (setq smtpmail-read-point (point-min))
-
-
- (if (or (null (car (setq greeting (smtpmail-read-response process))))
- (not (integerp (car greeting)))
- (>= (car greeting) 400))
- (throw 'done nil)
- )
-
- ;; HELO
- (smtpmail-send-command process (format "HELO %s" (smtpmail-fqdn)))
-
- (if (or (null (car (setq response-code (smtpmail-read-response process))))
- (not (integerp (car response-code)))
- (>= (car response-code) 400))
- (throw 'done nil)
- )
-
- ;; MAIL FROM: <sender>
-; (smtpmail-send-command process (format "MAIL FROM:%s@%s" (user-login-name) (smtpmail-fqdn)))
- (smtpmail-send-command process (format "MAIL FROM: <%s>" user-mail-address))
-
- (if (or (null (car (setq response-code (smtpmail-read-response process))))
- (not (integerp (car response-code)))
- (>= (car response-code) 400))
- (throw 'done nil)
- )
-
- ;; RCPT TO: <recipient>
- (let ((n 0))
- (while (not (null (nth n recipient)))
- (smtpmail-send-command process (format "RCPT TO: <%s>" (nth n recipient)))
- (setq n (1+ n))
-
- (if (or (null (car (setq response-code (smtpmail-read-response process))))
- (not (integerp (car response-code)))
- (>= (car response-code) 400))
- (throw 'done nil)
- )
- ))
-
- ;; DATA
- (smtpmail-send-command process "DATA")
-
- (if (or (null (car (setq response-code (smtpmail-read-response process))))
- (not (integerp (car response-code)))
- (>= (car response-code) 400))
- (throw 'done nil)
- )
-
- ;; Mail contents
- (smtpmail-send-data process smtpmail-text-buffer)
-
- ;;DATA end "."
- (smtpmail-send-command process ".")
-
- (if (or (null (car (setq response-code (smtpmail-read-response process))))
- (not (integerp (car response-code)))
- (>= (car response-code) 400))
- (throw 'done nil)
- )
-
- ;;QUIT
-; (smtpmail-send-command process "QUIT")
-; (and (null (car (smtpmail-read-response process)))
-; (throw 'done nil))
- t ))
- (if process
- (save-excursion
- (set-buffer (process-buffer process))
- (smtpmail-send-command process "QUIT")
- (smtpmail-read-response process)
-
-; (if (or (null (car (setq response-code (smtpmail-read-response process))))
-; (not (integerp (car response-code)))
-; (>= (car response-code) 400))
-; (throw 'done nil)
-; )
- (delete-process process))))))
-
-
-(defun smtpmail-process-filter (process output)
- (save-excursion
- (set-buffer (process-buffer process))
- (goto-char (point-max))
- (insert output)))
-
-(defun smtpmail-read-response (process)
- (let ((case-fold-search nil)
- (response-string nil)
- (response-continue t)
- (return-value '(nil ""))
- match-end)
-
-; (setq response-string nil)
-; (setq response-continue t)
-; (setq return-value '(nil ""))
-
- (while response-continue
- (goto-char smtpmail-read-point)
- (while (not (search-forward "\r\n" nil t))
- (accept-process-output process)
- (goto-char smtpmail-read-point))
-
- (setq match-end (point))
- (if (null response-string)
- (setq response-string
- (buffer-substring smtpmail-read-point (- match-end 2))))
-
- (goto-char smtpmail-read-point)
- (if (looking-at "[0-9]+ ")
- (progn (setq response-continue nil)
-; (setq return-value response-string)
-
- (if smtpmail-debug-info
- (message response-string))
-
- (setq smtpmail-read-point match-end)
- (setq return-value
- (cons (string-to-int
- (buffer-substring (match-beginning 0) (match-end 0)))
- response-string)))
-
- (if (looking-at "[0-9]+-")
- (progn (setq smtpmail-read-point match-end)
- (setq response-continue t))
- (progn
- (setq smtpmail-read-point match-end)
- (setq response-continue nil)
- (setq return-value
- (cons nil response-string))
- )
- )))
- (setq smtpmail-read-point match-end)
- return-value))
-
-
-(defun smtpmail-send-command (process command)
- (goto-char (point-max))
- (if (= (aref command 0) ?P)
- (insert "PASS <omitted>\r\n")
- (insert command "\r\n"))
- (setq smtpmail-read-point (point))
- (process-send-string process command)
- (process-send-string process "\r\n"))
-
-(defun smtpmail-send-data-1 (process data)
- (goto-char (point-max))
-
- (if (not (null smtpmail-code-conv-from))
- (setq data (code-convert-string data smtpmail-code-conv-from *internal*)))
-
- (if smtpmail-debug-info
- (insert data "\r\n"))
-
- (setq smtpmail-read-point (point))
- ;; Escape "." at start of a line
- (if (eq (string-to-char data) ?.)
- (process-send-string process "."))
- (process-send-string process data)
- (process-send-string process "\r\n")
- )
-
-(defun smtpmail-send-data (process buffer)
- (let
- ((data-continue t)
- (sending-data nil)
- this-line
- this-line-end)
-
- (save-excursion
- (set-buffer buffer)
- (goto-char (point-min)))
-
- (while data-continue
- (save-excursion
- (set-buffer buffer)
- (beginning-of-line)
- (setq this-line (point))
- (end-of-line)
- (setq this-line-end (point))
- (setq sending-data nil)
- (setq sending-data (buffer-substring this-line this-line-end))
- (if (/= (forward-line 1) 0)
- (setq data-continue nil)))
-
- (smtpmail-send-data-1 process sending-data)
- )
- )
- )
-
-
-(defun smtpmail-deduce-address-list (smtpmail-text-buffer header-start header-end)
- "Get address list suitable for smtp RCPT TO: <address>."
- (require 'mail-utils) ;; pick up mail-strip-quoted-names
- (let
- ((case-fold-search t)
- (simple-address-list "")
- this-line
- this-line-end
- addr-regexp)
-
- (unwind-protect
- (save-excursion
- ;;
- (set-buffer smtpmail-address-buffer) (erase-buffer)
- (insert-buffer-substring smtpmail-text-buffer header-start header-end)
- (goto-char (point-min))
- ;; RESENT-* fields should stop processing of regular fields.
- (save-excursion
- (if (re-search-forward "^RESENT-TO:" header-end t)
- (setq addr-regexp "^\\(RESENT-TO:\\|RESENT-CC:\\|RESENT-BCC:\\)")
- (setq addr-regexp "^\\(TO:\\|CC:\\|BCC:\\)")))
-
- (while (re-search-forward addr-regexp header-end t)
- (replace-match "")
- (setq this-line (match-beginning 0))
- (forward-line 1)
- ;; get any continuation lines
- (while (and (looking-at "^[ \t]+") (< (point) header-end))
- (forward-line 1))
- (setq this-line-end (point-marker))
- (setq simple-address-list
- (concat simple-address-list " "
- (mail-strip-quoted-names (buffer-substring this-line this-line-end))))
- )
- (erase-buffer)
- (insert-string " ")
- (insert-string simple-address-list)
- (insert-string "\n")
- (subst-char-in-region (point-min) (point-max) 10 ? t);; newline --> blank
- (subst-char-in-region (point-min) (point-max) ?, ? t);; comma --> blank
- (subst-char-in-region (point-min) (point-max) 9 ? t);; tab --> blank
-
- (goto-char (point-min))
- ;; tidyness in case hook is not robust when it looks at this
- (while (re-search-forward "[ \t]+" header-end t) (replace-match " "))
-
- (goto-char (point-min))
- (let (recipient-address-list)
- (while (re-search-forward " \\([^ ]+\\) " (point-max) t)
- (backward-char 1)
- (setq recipient-address-list (cons (buffer-substring (match-beginning 1) (match-end 1))
- recipient-address-list))
- )
- (setq smtpmail-recipient-address-list recipient-address-list))
-
- )
- )
- )
- )
-
-
-(defun smtpmail-do-bcc (header-end)
- "Delete BCC: and their continuation lines from the header area.
-There may be multiple BCC: lines, and each may have arbitrarily
-many continuation lines."
- (let ((case-fold-search t))
- (save-excursion (goto-char (point-min))
- ;; iterate over all BCC: lines
- (while (re-search-forward "^BCC:" header-end t)
- (delete-region (match-beginning 0) (progn (forward-line 1) (point)))
- ;; get rid of any continuation lines
- (while (and (looking-at "^[ \t].*\n") (< (point) header-end))
- (replace-match ""))
- )
- ) ;; save-excursion
- ) ;; let
- )
-
-
-
-(provide 'smtpmail)
-
-;; smtpmail.el ends here
diff --git a/lisp/mail/supercite.el b/lisp/mail/supercite.el
deleted file mode 100644
index 8babd369099..00000000000
--- a/lisp/mail/supercite.el
+++ /dev/null
@@ -1,2020 +0,0 @@
-;;; supercite.el --- minor mode for citing mail and news replies
-
-;; Copyright (C) 1993 Free Software Foundation, Inc.
-
-;; Author: 1993 Barry A. Warsaw, Century Computing, Inc. <bwarsaw@cen.com>
-;; Maintainer: supercite-help@anthem.nlm.nih.gov
-;; Created: February 1993
-;; Version: 3.1
-;; Last Modified: 1993/09/22 18:58:46
-;; Keywords: mail, news
-
-;; supercite.el revision: 3.54
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; LCD Archive Entry
-;; supercite|Barry A. Warsaw|supercite-help@anthem.nlm.nih.gov
-;; |Mail and news reply citation package
-;; |1993/09/22 18:58:46|3.1|
-
-;; Code:
-
-
-(require 'regi)
-
-;; start user configuration variables
-;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-
-(defvar sc-auto-fill-region-p t
- "*If non-nil, automatically fill each paragraph after it has been cited.")
-
-(defvar sc-blank-lines-after-headers 1
- "*Number of blank lines to leave after mail headers have been nuked.
-Set to nil, to use whatever blank lines happen to occur naturally.")
-
-(defvar sc-citation-leader " "
- "*String comprising first part of a citation.")
-(defvar sc-citation-delimiter ">"
- "*String comprising third part of a citation.
-This string is used in both nested and non-nested citations.")
-(defvar sc-citation-separator " "
- "*String comprising fourth and last part of a citation.")
-
-(defvar sc-citation-leader-regexp "[ \t]*"
- "*Regexp describing citation leader for a cited line.
-This should NOT have a leading `^' character.")
-
-;; Nemacs and Mule users note: please see the texinfo manual for
-;; suggestions on setting these variables.
-(defvar sc-citation-root-regexp "[-._a-zA-Z0-9]*"
- "*Regexp describing variable root part of a citation for a cited line.
-This should NOT have a leading `^' character. See also
-`sc-citation-nonnested-root-regexp'.")
-(defvar sc-citation-nonnested-root-regexp "[-._a-zA-Z0-9]+"
- "*Regexp describing the variable root part of a nested citation.
-This should NOT have a leading `^' character. This variable is
-related to `sc-citation-root-regexp' but whereas that variable
-describes both nested and non-nested citation roots, this variable
-describes only nested citation roots.")
-(defvar sc-citation-delimiter-regexp "[>]+"
- "*Regexp describing citation delimiter for a cited line.
-This should NOT have a leading `^' character.")
-(defvar sc-citation-separator-regexp "[ \t]*"
- "*Regexp describing citation separator for a cited line.
-This should NOT have a leading `^' character.")
-
-(defvar sc-cite-blank-lines-p nil
- "*If non-nil, put a citation on blank lines.")
-
-(defvar sc-cite-frame-alist '()
- "*Alist for frame selection during citing.
-Each element of this list has the following form:
-
- (INFOKEY ((REGEXP . FRAME)
- (REGEXP . FRAME)
- (...)))
-
-Where INFOKEY is a key for `sc-mail-field', REGEXP is a regular
-expression to match against the INFOKEY's value. FRAME is a citation
-frame, or a variable containing a citation frame.")
-(defvar sc-uncite-frame-alist '()
- "*Alist for frame selection during unciting.
-See the variable `sc-cite-frame-alist' for details.")
-(defvar sc-recite-frame-alist '()
- "*Alist for frame selection during reciting.
-See the variable `sc-cite-frame-alist' for details.")
-
-(defvar sc-default-cite-frame
- '(;; initialize fill state and temporary variables when entering
- ;; frame. this makes things run much faster
- (begin (progn
- (sc-fill-if-different)
- (setq sc-tmp-nested-regexp (sc-cite-regexp "")
- sc-tmp-nonnested-regexp (sc-cite-regexp)
- sc-tmp-dumb-regexp
- (concat "\\("
- (sc-cite-regexp "")
- "\\)"
- (sc-cite-regexp sc-citation-nonnested-root-regexp))
- )))
- ;; blank lines mean paragraph separators, so fill the last cited
- ;; paragraph, unless sc-cite-blank-lines-p is non-nil, in which
- ;; case we treat blank lines just like any other line.
- ("^[ \t]*$" (if sc-cite-blank-lines-p
- (sc-cite-line)
- (sc-fill-if-different "")))
- ;; do nothing if looking at a reference tag. make sure that the
- ;; tag string isn't the empty string since this will match every
- ;; line. it cannot be nil.
- (sc-reference-tag-string (if (string= sc-reference-tag-string "")
- (list 'continue)
- nil))
- ;; this regexp catches nested citations in which the author cited
- ;; a non-nested citation with a dumb citer.
- (sc-tmp-dumb-regexp (sc-cite-coerce-dumb-citer))
- ;; if we are looking at a nested citation then add a citation level
- (sc-tmp-nested-regexp (sc-add-citation-level))
- ;; if we're looking at a non-nested citation, coerce it to our style
- (sc-tmp-nonnested-regexp (sc-cite-coerce-cited-line))
- ;; we must be looking at an uncited line. if we are in nested
- ;; citations, just add a citation level
- (sc-nested-citation-p (sc-add-citation-level))
- ;; we're looking at an uncited line and we are in non-nested
- ;; citations, so cite it with a non-nested citation
- (t (sc-cite-line))
- ;; be sure when we're done that we fill the last cited paragraph.
- (end (sc-fill-if-different ""))
- )
- "*Default REGI frame for citing a region.")
-
-(defvar sc-default-uncite-frame
- '(;; do nothing on a blank line
- ("^[ \t]*$" nil)
- ;; if the line is cited, uncite it
- ((sc-cite-regexp) (sc-uncite-line))
- )
- "*Default REGI frame for unciting a region.")
-
-(defvar sc-default-recite-frame
- '(;; initialize fill state when entering frame
- (begin (sc-fill-if-different))
- ;; do nothing on a blank line
- ("^[ \t]*$" nil)
- ;; if we're looking at a cited line, recite it
- ((sc-cite-regexp) (sc-recite-line (sc-cite-regexp)))
- ;; otherwise, the line is uncited, so just cite it
- (t (sc-cite-line))
- ;; be sure when we're done that we fill the last cited paragraph.
- (end (sc-fill-if-different ""))
- )
- "*Default REGI frame for reciting a region.")
-
-(defvar sc-cite-region-limit t
- "*This variable controls automatic citation of yanked text.
-Legal values are:
-
-non-nil -- cite the entire region, regardless of its size
-nil -- do not cite the region at all
-<integer> -- a number indicating the threshold for citation. When
- the number of lines in the region is greater than this
- value, a warning message will be printed and the region
- will not be cited. Lines in region are counted with
- `count-lines'.
-
-The gathering of attribution information is not affected by the value
-of this variable. The number of lines in the region is calculated
-*after* all mail headers are removed. This variable is only consulted
-during the initial citing via `sc-cite-original'.")
-
-(defvar sc-confirm-always-p t
- "*If non-nil, always confirm attribution string before citing text body.")
-
-(defvar sc-default-attribution "Anon"
- "*String used when author's attribution cannot be determined.")
-(defvar sc-default-author-name "Anonymous"
- "*String used when author's name cannot be determined.")
-
-(defvar sc-downcase-p nil
- "*Non-nil means downcase the attribution and citation strings.")
-
-(defvar sc-electric-circular-p t
- "*If non-nil, treat electric references as circular.")
-(defvar sc-electric-mode-hook nil
- "*Hook for `sc-electric-mode' electric references mode.")
-(defvar sc-electric-references-p nil
- "*Use electric references if non-nil.")
-
-(defvar sc-fixup-whitespace-p nil
- "*If non-nil, delete all leading white space before citing.")
-
-(defvar sc-load-hook nil
- "*Hook which gets run once after Supercite loads.")
-(defvar sc-pre-hook nil
- "*Hook which gets run before each invocation of `sc-cite-original'.")
-(defvar sc-post-hook nil
- "*Hook which gets run after each invocation of `sc-cite-original'.")
-
-(defvar sc-mail-warn-if-non-rfc822-p t
- "*Warn if mail headers don't conform to RFC822.")
-(defvar sc-mumble ""
- "*Value returned by `sc-mail-field' if field isn't in mail headers.")
-
-(defvar sc-name-filter-alist
- '(("^\\(Mr\\|Mrs\\|Ms\\|Dr\\)[.]?$" . 0)
- ("^\\(Jr\\|Sr\\)[.]?$" . last)
- ("^ASTS$" . 0)
- ("^[I]+$" . last))
- "*Name list components which are filtered out as noise.
-This variable contains an association list where each element is of
-the form: (REGEXP . POSITION).
-
-REGEXP is a regular expression which matches the name list component.
-Match is performed using `string-match'. POSITION is the position in
-the name list which can match the regular expression, starting at zero
-for the first element. Use `last' to match the last element in the
-list and `any' to match all elements.")
-
-(defvar sc-nested-citation-p nil
- "*Controls whether to use nested or non-nested citation style.
-Non-nil uses nested citations, nil uses non-nested citations.")
-
-(defvar sc-nuke-mail-headers 'all
- "*Controls mail header nuking.
-Used in conjunction with `sc-nuke-mail-header-list'. Legal values are:
-
-`all' -- nuke all mail headers
-`none' -- don't nuke any mail headers
-`specified' -- nuke headers specified in `sc-nuke-mail-header-list'
-`keep' -- keep headers specified in `sc-nuke-mail-header-list'")
-
-(defvar sc-nuke-mail-header-list nil
- "*List of mail header regexps to remove or keep in body of reply.
-This list contains regular expressions describing the mail headers to
-keep or nuke, depending on the value of `sc-nuke-mail-headers'.")
-
-(defvar sc-preferred-attribution-list
- '("sc-lastchoice" "x-attribution" "firstname" "initials" "lastname")
- "*Specifies what to use as the attribution string.
-Supercite creates a list of possible attributions when it scans the
-mail headers from the original message. Each attribution choice is
-associated with a key in an attribution alist. Supercite tries to
-pick a \"preferred\" attribution by matching the attribution alist
-keys against the elements in `sc-preferred-attribution-list' in order.
-The first non-empty string value found is used as the preferred
-attribution.
-
-Note that Supercite now honors the X-Attribution: mail field. If
-present in the original message, the value of this field should always
-be used to select the most preferred attribution since it reflects how
-the original author would like to be distinguished. It should be
-considered bad taste to put any attribution preference key before
-\"x-attribution\" in this list, except perhaps for \"sc-lastchoice\"
-\(see below).
-
-Supercite remembers the last attribution used when reciting an already
-cited paragraph. This attribution will always be saved with the
-\"sc-lastchoice\" key, which can be used in this list. Note that the
-last choice is always reset after every call of `sc-cite-original'.
-
-Barring error conditions, the following preferences are always present
-in the attribution alist:
-
-\"emailname\" -- email terminus name
-\"initials\" -- initials of author
-\"firstname\" -- first name of author
-\"lastname\" -- last name of author
-\"middlename-1\" -- first middle name of author
-\"middlename-2\" -- second middle name of author
-...
-
-Middle name indexes can be any positive integer greater than 0,
-although it is unlikely that many authors will supply more than one
-middle name, if that many. The string of all middle names is
-associated with the key \"middlenames\".")
-
-(defvar sc-attrib-selection-list nil
- "*An alist for selecting preferred attribution based on mail headers.
-Each element of this list has the following form:
-
- (INFOKEY ((REGEXP . ATTRIBUTION)
- (REGEXP . ATTRIBUTION)
- (...)))
-
-Where INFOKEY is a key for `sc-mail-field', REGEXP is a regular
-expression to match against the INFOKEY's value. ATTRIBUTION can be a
-string or a list. If its a string, then it is the attribution that is
-selected by `sc-select-attribution'. If it is a list, it is `eval'd
-and the return value must be a string, which is used as the selected
-attribution. Note that the variable `sc-preferred-attribution-list'
-must contain an element of the string \"sc-consult\" for this variable
-to be consulted during attribution selection.")
-
-(defvar sc-attribs-preselect-hook nil
- "*Hook to run before selecting an attribution.")
-(defvar sc-attribs-postselect-hook nil
- "*Hook to run after selecting an attribution, but before confirmation.")
-
-(defvar sc-pre-cite-hook nil
- "*Hook to run before citing a region of text.")
-(defvar sc-pre-uncite-hook nil
- "*Hook to run before unciting a region of text.")
-(defvar sc-pre-recite-hook nil
- "*Hook to run before reciting a region of text.")
-
-(defvar sc-preferred-header-style 4
- "*Index into `sc-rewrite-header-list' specifying preferred header style.
-Index zero accesses the first function in the list.")
-
-(defvar sc-reference-tag-string ">>>>> "
- "*String used at the beginning of built-in reference headers.")
-
-(defvar sc-rewrite-header-list
- '((sc-no-header)
- (sc-header-on-said)
- (sc-header-inarticle-writes)
- (sc-header-regarding-adds)
- (sc-header-attributed-writes)
- (sc-header-author-writes)
- (sc-header-verbose)
- (sc-no-blank-line-or-header)
- )
- "*List of reference header rewrite functions.
-The variable `sc-preferred-header-style' controls which function in
-this list is chosen for automatic reference header insertions.
-Electric reference mode will cycle through this list of functions.")
-
-(defvar sc-titlecue-regexp "\\s +-+\\s +"
- "*Regular expression describing the separator between names and titles.
-Set to nil to treat entire field as a name.")
-
-(defvar sc-use-only-preference-p nil
- "*Controls what happens when the preferred attribution cannot be found.
-If non-nil, then `sc-default-attribution' will be used. If nil, then
-some secondary scheme will be employed to find a suitable attribution
-string.")
-
-;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-;; end user configuration variables
-
-(defconst sc-version "3.1"
- "Supercite version number.")
-(defconst sc-help-address "supercite-help@anthem.nlm.nih.gov"
- "Address accepting submissions of bug reports.")
-
-(defvar sc-mail-info nil
- "Alist of mail header information gleaned from reply buffer.")
-(defvar sc-attributions nil
- "Alist of attributions for use when citing.")
-
-(defconst sc-emacs-features
- (let ((version 'v18)
- (flavor 'GNU))
- (if (string= (substring emacs-version 0 2) "19")
- (setq version 'v19))
- (if (string-match "Lucid" emacs-version)
- (setq flavor 'Lucid))
- ;; cobble up list
- (list version flavor))
- "A list describing what version of Emacs we're running on.
-Known flavors are:
-
-All GNU18's: (v18 GNU)
-FSF19.x : (v19 GNU)
-Lucid19.x : (v19 Lucid)")
-
-
-(defvar sc-tmp-nested-regexp nil
- "Temporary regepx describing nested citations.")
-(defvar sc-tmp-nonnested-regexp nil
- "Temporary regexp describing non-nested citations.")
-(defvar sc-tmp-dumb-regexp nil
- "Temp regexp describing non-nested citation cited with a nesting citer.")
-
-(defvar sc-minor-mode nil
- "Supercite minor mode on flag.")
-(defvar sc-mode-string " SC"
- "Supercite minor mode string.")
-
-(make-variable-buffer-local 'sc-mail-info)
-(make-variable-buffer-local 'sc-attributions)
-(make-variable-buffer-local 'sc-minor-mode)
-
-
-;; ======================================================================
-;; supercite keymaps
-
-(defvar sc-mode-map-prefix "\C-c\C-p"
- "*Key binding to install Supercite keymap.
-If this is nil, Supercite keymap is not installed.")
-
-(defvar sc-T-keymap ()
- "Keymap for sub-keymap of setting and toggling functions.")
-(if sc-T-keymap
- ()
- (setq sc-T-keymap (make-sparse-keymap))
- (define-key sc-T-keymap "a" 'sc-S-preferred-attribution-list)
- (define-key sc-T-keymap "b" 'sc-T-mail-nuke-blank-lines)
- (define-key sc-T-keymap "c" 'sc-T-confirm-always)
- (define-key sc-T-keymap "d" 'sc-T-downcase)
- (define-key sc-T-keymap "e" 'sc-T-electric-references)
- (define-key sc-T-keymap "f" 'sc-T-auto-fill-region)
- (define-key sc-T-keymap "h" 'sc-T-describe)
- (define-key sc-T-keymap "l" 'sc-S-cite-region-limit)
- (define-key sc-T-keymap "n" 'sc-S-mail-nuke-mail-headers)
- (define-key sc-T-keymap "N" 'sc-S-mail-header-nuke-list)
- (define-key sc-T-keymap "o" 'sc-T-electric-circular)
- (define-key sc-T-keymap "p" 'sc-S-preferred-header-style)
- (define-key sc-T-keymap "s" 'sc-T-nested-citation)
- (define-key sc-T-keymap "u" 'sc-T-use-only-preferences)
- (define-key sc-T-keymap "w" 'sc-T-fixup-whitespace)
- (define-key sc-T-keymap "?" 'sc-T-describe)
- )
-
-(defvar sc-mode-map ()
- "Keymap for Supercite quasi-mode.")
-(if sc-mode-map
- ()
- (setq sc-mode-map (make-sparse-keymap))
- (define-key sc-mode-map "c" 'sc-cite-region)
- (define-key sc-mode-map "f" 'sc-mail-field-query)
- (define-key sc-mode-map "g" 'sc-mail-process-headers)
- (define-key sc-mode-map "h" 'sc-describe)
- (define-key sc-mode-map "i" 'sc-insert-citation)
- (define-key sc-mode-map "o" 'sc-open-line)
- (define-key sc-mode-map "r" 'sc-recite-region)
- (define-key sc-mode-map "\C-p" 'sc-raw-mode-toggle)
- (define-key sc-mode-map "u" 'sc-uncite-region)
- (define-key sc-mode-map "v" 'sc-version)
- (define-key sc-mode-map "w" 'sc-insert-reference)
- (define-key sc-mode-map "\C-t" sc-T-keymap)
- (define-key sc-mode-map "\C-b" 'sc-submit-bug-report)
- (define-key sc-mode-map "?" 'sc-describe)
- )
-
-(defvar sc-electric-mode-map ()
- "Keymap for `sc-electric-mode' electric references mode.")
-(if sc-electric-mode-map
- nil
- (setq sc-electric-mode-map (make-sparse-keymap))
- (define-key sc-electric-mode-map "p" 'sc-eref-prev)
- (define-key sc-electric-mode-map "n" 'sc-eref-next)
- (define-key sc-electric-mode-map "s" 'sc-eref-setn)
- (define-key sc-electric-mode-map "j" 'sc-eref-jump)
- (define-key sc-electric-mode-map "x" 'sc-eref-abort)
- (define-key sc-electric-mode-map "q" 'sc-eref-abort)
- (define-key sc-electric-mode-map "\r" 'sc-eref-exit)
- (define-key sc-electric-mode-map "\n" 'sc-eref-exit)
- (define-key sc-electric-mode-map "g" 'sc-eref-goto)
- (define-key sc-electric-mode-map "?" 'describe-mode)
- (define-key sc-electric-mode-map "\C-h" 'describe-mode)
- (define-key sc-electric-mode-map [f1] 'describe-mode)
- (define-key sc-electric-mode-map [help] 'describe-mode)
- )
-
-(defvar sc-minibuffer-local-completion-map nil
- "Keymap for minibuffer confirmation of attribution strings.")
-(if sc-minibuffer-local-completion-map
- ()
- (setq sc-minibuffer-local-completion-map
- (copy-keymap minibuffer-local-completion-map))
- (define-key sc-minibuffer-local-completion-map "\C-t" 'sc-toggle-fn)
- (define-key sc-minibuffer-local-completion-map " " 'self-insert-command))
-
-(defvar sc-minibuffer-local-map nil
- "Keymap for minibuffer confirmation of attribution strings.")
-(if sc-minibuffer-local-map
- ()
- (setq sc-minibuffer-local-map (copy-keymap minibuffer-local-map))
- (define-key sc-minibuffer-local-map "\C-t" 'sc-toggle-fn))
-
-
-;; ======================================================================
-;; utility functions
-
-(defun sc-completing-read (prompt table &optional predicate require-match
- initial-contents history)
- "Compatibility between Emacs 18 and 19 `completing-read'.
-In version 18, the HISTORY argument is ignored."
- (if (memq 'v19 sc-emacs-features)
- (funcall 'completing-read prompt table predicate require-match
- initial-contents history)
- (funcall 'completing-read prompt table predicate require-match
- (or (car-safe initial-contents)
- initial-contents))))
-
-(defun sc-read-string (prompt &optional initial-contents history)
- "Compatibility between Emacs 18 and 19 `read-string'.
-In version 18, the HISTORY argument is ignored."
- (if (memq 'v19 sc-emacs-features)
- ;; maybe future versions will take a `history' argument:
- (read-string prompt initial-contents)
- (read-string prompt initial-contents)))
-
-(if (fboundp 'match-string)
- (defalias 'sc-submatch 'match-string)
- (defun sc-submatch (matchnum &optional string)
- "Returns `match-beginning' and `match-end' sub-expression for MATCHNUM.
-If optional STRING is provided, take sub-expression using `substring'
-of argument, otherwise use `buffer-substring' on current buffer. Note
-that `match-data' must have already been generated and no error
-checking is performed by this function."
- (if string
- (substring string (match-beginning matchnum) (match-end matchnum))
- (buffer-substring (match-beginning matchnum) (match-end matchnum)))))
-
-(if (fboundp 'member)
- (defalias 'sc-member 'member)
- (defun sc-member (elt list)
- "Like `memq', but uses `equal' instead of `eq'.
-Emacs19 has a builtin function `member' which does exactly this."
- (catch 'elt-is-member
- (while list
- (if (equal elt (car list))
- (throw 'elt-is-member list))
- (setq list (cdr list))))))
-
-;; One day maybe Emacs will have this...
-(if (fboundp 'string-text)
- (defalias 'sc-string-text 'string-text)
- (defun sc-string-text (string)
- "Return STRING with all text properties removed."
- (let ((string (copy-sequence string)))
- (set-text-properties 0 (length string) nil string)
- string)))
-
-(defun sc-ask (alist)
- "Ask a question in the minibuffer requiring a single character answer.
-This function is kind of an extension of `y-or-n-p' where a single
-letter is used to answer a question. Question is formed from ALIST
-which has members of the form: (WORD . LETTER). WORD is the long
-word form, while LETTER is the letter for selecting that answer. The
-selected letter is returned, or nil if the question was not answered.
-Note that WORD is a string and LETTER is a character. All LETTERs in
-the list should be unique."
- (let* ((prompt (concat
- (mapconcat (function (lambda (elt) (car elt))) alist ", ")
- "? ("
- (mapconcat
- (function
- (lambda (elt) (char-to-string (cdr elt)))) alist "/")
- ") "))
- (p prompt)
- (event
- (if (memq 'Lucid sc-emacs-features)
- (allocate-event)
- nil)))
- (while (stringp p)
- (if (let ((cursor-in-echo-area t)
- (inhibit-quit t))
- (message "%s" p)
- ;; lets be good neighbors and be compatible with all emacsen
- (cond
- ((memq 'v18 sc-emacs-features)
- (setq event (read-char)))
- ((memq 'Lucid sc-emacs-features)
- (next-command-event event))
- (t ; must be FSF19
- (setq event (read-event))))
- (prog1 quit-flag (setq quit-flag nil)))
- (progn
- (message "%s%s" p (single-key-description event))
- (and (memq 'Lucid sc-emacs-features)
- (deallocate-event event))
- (setq quit-flag nil)
- (signal 'quit '())))
- (let ((char
- (if (memq 'Lucid sc-emacs-features)
- (let* ((key (and (key-press-event-p event) (event-key event)))
- (char (and key (event-to-character event))))
- char)
- event))
- elt)
- (if char (setq char (downcase char)))
- (cond
- ((setq elt (rassq char alist))
- (message "%s%s" p (car elt))
- (setq p (cdr elt)))
- ((and (memq 'Lucid sc-emacs-features)
- (button-release-event-p event)) ; ignore them
- nil)
- (t
- (message "%s%s" p (single-key-description event))
- (if (memq 'Lucid sc-emacs-features)
- (ding nil 'y-or-n-p)
- (ding))
- (discard-input)
- (if (eq p prompt)
- (setq p (concat "Try again. " prompt)))))))
- (and (memq 'Lucid sc-emacs-features)
- (deallocate-event event))
- p))
-
-(defun sc-scan-info-alist (alist)
- "Find a match in the info alist that matches a regexp in ALIST."
- (let ((sc-mumble "")
- rtnvalue)
- (while alist
- (let* ((elem (car alist))
- (infokey (car elem))
- (infoval (sc-mail-field infokey))
- (mlist (car (cdr elem))))
- (while mlist
- (let* ((ml-elem (car mlist))
- (regexp (car ml-elem))
- (thing (cdr ml-elem)))
- (if (string-match regexp infoval)
- ;; we found a match, time to return
- (setq rtnvalue thing
- mlist nil
- alist nil)
- ;; else we didn't find a match
- (setq mlist (cdr mlist))
- ))) ;end of mlist loop
- (setq alist (cdr alist))
- )) ;end of alist loop
- rtnvalue))
-
-
-;; ======================================================================
-;; extract mail field information from headers in reply buffer
-
-;; holder variables for bc happiness
-(defvar sc-mail-headers-start nil
- "Start of header fields.")
-(defvar sc-mail-headers-end nil
- "End of header fields.")
-(defvar sc-mail-field-history nil
- "For minibuffer completion on mail field queries.")
-(defvar sc-mail-field-modification-history nil
- "For minibuffer completion on mail field modifications.")
-(defvar sc-mail-glom-frame
- '((begin (setq sc-mail-headers-start (point)))
- ("^x-attribution:[ \t]+.*$" (sc-mail-fetch-field t) nil t)
- ("^\\S +:.*$" (sc-mail-fetch-field) nil t)
- ("^$" (list 'abort '(step . 0)))
- ("^[ \t]+" (sc-mail-append-field))
- (sc-mail-warn-if-non-rfc822-p (sc-mail-error-in-mail-field))
- (end (setq sc-mail-headers-end (point))))
- "Regi frame for glomming mail header information.")
-
-;; regi functions
-(defun sc-mail-fetch-field (&optional attribs-p)
- "Insert a key and value into `sc-mail-info' alist.
-If optional ATTRIBS-P is non-nil, the key/value pair is placed in
-`sc-attributions' too."
- (if (string-match "^\\(\\S *\\)\\s *:\\s +\\(.*\\)$" curline)
- (let* ((key (downcase (sc-string-text (sc-submatch 1 curline))))
- (val (sc-string-text (sc-submatch 2 curline)))
- (keyval (cons key val)))
- (setq sc-mail-info (cons keyval sc-mail-info))
- (if attribs-p
- (setq sc-attributions (cons keyval sc-attributions)))
- ))
- nil)
-
-(defun sc-mail-append-field ()
- "Append a continuation line onto the last fetched mail field's info."
- (let ((keyval (car sc-mail-info)))
- (if (and keyval (string-match "^\\s *\\(.*\\)$" curline))
- (setcdr keyval (concat (cdr keyval) " "
- (sc-string-text (sc-submatch 1 curline))))))
- nil)
-
-(defun sc-mail-error-in-mail-field ()
- "Issue warning that mail headers don't conform to RFC 822."
- (let* ((len (min (length curline) 10))
- (ellipsis (if (< len (length curline)) "..." ""))
- (msg "Mail header \"%s%s\" doesn't conform to RFC 822. skipping..."))
- (message msg (substring curline 0 len) ellipsis))
- (beep)
- (sit-for 2)
- nil)
-
-;; mail header nuking
-(defvar sc-mail-last-header-nuked-p nil
- "True if the last header was nuked.")
-
-(defun sc-mail-nuke-line ()
- "Nuke the current mail header line."
- (delete-region (regi-pos 'bol) (regi-pos 'bonl))
- '((step . -1)))
-
-(defun sc-mail-nuke-header-line ()
- "Delete current-line and set up for possible continuation."
- (setq sc-mail-last-header-nuked-p t)
- (sc-mail-nuke-line))
-
-(defun sc-mail-nuke-continuation-line ()
- "Delete a continuation line if the last header line was deleted."
- (if sc-mail-last-header-nuked-p
- (sc-mail-nuke-line)))
-
-(defun sc-mail-cleanup-blank-lines ()
- "Leave some blank lines after original mail headers are nuked.
-The number of lines left is specified by `sc-blank-lines-after-headers'."
- (if sc-blank-lines-after-headers
- (save-restriction
- (widen)
- (skip-chars-backward " \t\n")
- (forward-line 1)
- (delete-blank-lines)
- (beginning-of-line)
- (if (looking-at "[ \t]*$")
- (delete-region (regi-pos 'bol) (regi-pos 'bonl)))
- (insert-char ?\n sc-blank-lines-after-headers)))
- nil)
-
-(defun sc-mail-build-nuke-frame ()
- "Build the regiframe for nuking mail headers."
- (let (every-func entry-func nonentry-func)
- (cond
- ((eq sc-nuke-mail-headers 'all)
- (setq every-func '(progn (forward-line -1) (sc-mail-nuke-line))))
- ((eq sc-nuke-mail-headers 'specified)
- (setq entry-func '(sc-mail-nuke-header-line)
- nonentry-func '(setq sc-mail-last-header-nuked-p nil)))
- ((eq sc-nuke-mail-headers 'keep)
- (setq entry-func '(setq sc-mail-last-header-nuked-p nil)
- nonentry-func '(sc-mail-nuke-header-line)))
- ;; we never get far enough to interpret a frame if s-n-m-h == 'none
- ((eq sc-nuke-mail-headers 'none))
- (t (error "Illegal value for sc-nuke-mail-headers: %s"
- sc-nuke-mail-headers))
- ) ; end-cond
- (append
- (and entry-func
- (regi-mapcar sc-nuke-mail-header-list entry-func nil t))
- (and nonentry-func (list (list "^\\S +:.*$" nonentry-func)))
- (and (not every-func)
- '(("^[ \t]+" (sc-mail-nuke-continuation-line))))
- '((begin (setq sc-mail-last-header-zapped-p nil)))
- '((end (sc-mail-cleanup-blank-lines)))
- (and every-func (list (list 'every every-func)))
- )))
-
-;; mail processing and zapping. this is the top level entry defun to
-;; all header processing.
-(defun sc-mail-process-headers (start end)
- "Process original mail message's mail headers.
-After processing, mail headers may be nuked. Header information is
-stored in `sc-mail-info', and any old information is lost unless an
-error occurs."
- (interactive "r")
- (let ((info (copy-alist sc-mail-info))
- (attribs (copy-alist sc-attributions)))
- (setq sc-mail-info nil
- sc-attributions nil)
- (regi-interpret sc-mail-glom-frame start end)
- (if (null sc-mail-info)
- (progn
- (message "No mail headers found! Restoring old information.")
- (setq sc-mail-info info
- sc-attributions attribs))
- (regi-interpret (sc-mail-build-nuke-frame)
- sc-mail-headers-start sc-mail-headers-end)
- )))
-
-
-;; let the user change mail field information
-(defun sc-mail-field (field)
- "Return the mail header field value associated with FIELD.
-If there was no mail header with FIELD as its key, return the value of
-`sc-mumble'. FIELD is case insensitive."
- (or (cdr (assoc (downcase field) sc-mail-info)) sc-mumble))
-
-(defun sc-mail-field-query (arg)
- "View the value of a mail field.
-With `\\[universal-argument]', prompts for action on mail field.
-Action can be one of: View, Modify, Add, or Delete."
- (interactive "P")
- (let* ((alist '(("view" . ?v) ("modify" . ?m) ("add" . ?a) ("delete" . ?d)))
- (action (if (not arg) ?v (sc-ask alist)))
- key)
- (if (not action)
- ()
- (setq key (sc-completing-read
- (concat (car (rassq action alist))
- " information key: ")
- sc-mail-info nil
- (if (eq action ?a) nil 'noexit)
- nil 'sc-mail-field-history))
- (cond
- ((eq action ?v)
- (message "%s: %s" key (cdr (assoc key sc-mail-info))))
- ((eq action ?d)
- (setq sc-mail-info (delq (assoc key sc-mail-info) sc-mail-info)))
- ((eq action ?m)
- (let ((keyval (assoc key sc-mail-info)))
- ;; first put initial value onto list if not already there
- (if (not (sc-member (cdr keyval)
- sc-mail-field-modification-history))
- (setq sc-mail-field-modification-history
- (cons (cdr keyval) sc-mail-field-modification-history)))
- (setcdr keyval (sc-read-string
- (concat key ": ") (cdr keyval)
- 'sc-mail-field-modification-history))))
- ((eq action ?a)
- (setq sc-mail-info
- (cons (cons key
- (sc-read-string (concat key ": "))) sc-mail-info)))
- ))))
-
-
-;; ======================================================================
-;; attributions
-
-(defvar sc-attribution-confirmation-history nil
- "History for confirmation of attribution strings.")
-(defvar sc-citation-confirmation-history nil
- "History for confirmation of attribution prefixes.")
-
-(defun sc-attribs-%@-addresses (from &optional delim)
- "Extract the author's email terminus from email address FROM.
-Match addresses of the style ``name%[stuff].'' when called with DELIM
-of \"%\" and addresses of the style ``[stuff]name@[stuff]'' when
-called with DELIM \"@\". If DELIM is nil or not provided, matches
-addresses of the style ``name''."
- (and (string-match (concat "[-a-zA-Z0-9_.]+" delim) from 0)
- (substring from
- (match-beginning 0)
- (- (match-end 0) (if (null delim) 0 1)))))
-
-(defun sc-attribs-!-addresses (from)
- "Extract the author's email terminus from email address FROM.
-Match addresses of the style ``[stuff]![stuff]...!name[stuff].''"
- (let ((eos (length from))
- (mstart (string-match "![-a-zA-Z0-9_.]+\\([^-!a-zA-Z0-9_.]\\|$\\)"
- from 0))
- (mend (match-end 0)))
- (and mstart
- (substring from (1+ mstart) (- mend (if (= mend eos) 0 1)))
- )))
-
-(defun sc-attribs-<>-addresses (from)
- "Extract the author's email terminus from email address FROM.
-Match addresses of the style ``<name[stuff]>.''"
- (and (string-match "<\\(.*\\)>" from)
- (sc-submatch 1 from)))
-
-(defun sc-get-address (from author)
- "Get the full email address path from FROM.
-AUTHOR is the author's name (which is removed from the address)."
- (let ((eos (length from)))
- (if (string-match (concat "\\(^\\|^\"\\)" author
- "\\(\\s +\\|\"\\s +\\)") from 0)
- (let ((address (substring from (match-end 0) eos)))
- (if (and (= (aref address 0) ?<)
- (= (aref address (1- (length address))) ?>))
- (substring address 1 (1- (length address)))
- address))
- (if (string-match "[-a-zA-Z0-9!@%._]+" from 0)
- (sc-submatch 0 from)
- "")
- )))
-
-(defun sc-attribs-emailname (from)
- "Get the email terminus name from FROM."
- (or
- (sc-attribs-%@-addresses from "%")
- (sc-attribs-%@-addresses from "@")
- (sc-attribs-!-addresses from)
- (sc-attribs-<>-addresses from)
- (sc-attribs-%@-addresses from)
- (substring from 0 10)))
-
-(defun sc-name-substring (string start end extend)
- "Extract the specified substring of STRING from START to END.
-EXTEND is the number of characters on each side to extend the
-substring."
- (and start
- (let ((sos (+ start extend))
- (eos (- end extend)))
- (substring string sos
- (or (string-match sc-titlecue-regexp string sos) eos)
- ))))
-
-(defun sc-attribs-extract-namestring (from)
- "Extract the name string from FROM.
-This should be the author's full name minus an optional title."
- (let ((namestring
- (or
- ;; If there is a <...> in the name,
- ;; treat everything before that as the full name.
- ;; Even if it contains parens, use the whole thing.
- ;; On the other hand, we do look for quotes in the usual way.
- (and (string-match " *<.*>" from 0)
- (let ((before-angles
- (sc-name-substring from 0 (match-beginning 0) 0)))
- (if (string-match "\".*\"" before-angles 0)
- (sc-name-substring
- before-angles (match-beginning 0) (match-end 0) 1)
- before-angles)))
- (sc-name-substring
- from (string-match "(.*)" from 0) (match-end 0) 1)
- (sc-name-substring
- from (string-match "\".*\"" from 0) (match-end 0) 1)
- (sc-name-substring
- from (string-match "\\([-.a-zA-Z0-9_]+\\s +\\)+<" from 0)
- (match-end 1) 0)
- (sc-attribs-emailname from))))
- ;; strip off any leading or trailing whitespace
- (if namestring
- (let ((bos 0)
- (eos (1- (length namestring))))
- (while (and (<= bos eos)
- (memq (aref namestring bos) '(32 ?\t)))
- (setq bos (1+ bos)))
- (while (and (> eos bos)
- (memq (aref namestring eos) '(32 ?\t)))
- (setq eos (1- eos)))
- (substring namestring bos (1+ eos))))))
-
-(defun sc-attribs-chop-namestring (namestring)
- "Convert NAMESTRING to a list of names.
-example: (sc-namestring-to-list \"John Xavier Doe\")
- => (\"John\" \"Xavier\" \"Doe\")"
- (if (string-match "\\([ \t]*\\)\\([^ \t._]+\\)\\([ \t]*\\)" namestring)
- (cons (sc-submatch 2 namestring)
- (sc-attribs-chop-namestring (substring namestring (match-end 3)))
- )))
-
-(defun sc-attribs-strip-initials (namelist)
- "Extract the author's initials from the NAMELIST."
- (mapconcat
- (function
- (lambda (name)
- (if (< 0 (length name))
- (substring name 0 1))))
- namelist ""))
-
-(defun sc-guess-attribution (&optional string)
- "Guess attribution string on current line.
-If attribution cannot be guessed, nil is returned. Optional STRING if
-supplied, is used instead of the line point is on in the current buffer."
- (let ((start 0)
- (string (or string (buffer-substring (regi-pos 'bol) (regi-pos 'eol))))
- attribution)
- (and
- (= start (or (string-match sc-citation-leader-regexp string start) -1))
- (setq start (match-end 0))
- (= start (or (string-match sc-citation-root-regexp string start) 1))
- (setq attribution (sc-submatch 0 string)
- start (match-end 0))
- (= start (or (string-match sc-citation-delimiter-regexp string start) -1))
- (setq start (match-end 0))
- (= start (or (string-match sc-citation-separator-regexp string start) -1))
- attribution)))
-
-(defun sc-attribs-filter-namelist (namelist)
- "Filter out noise in NAMELIST according to `sc-name-filter-alist'."
- (let ((elements (length namelist))
- (position -1)
- keepers filtered-list)
- (mapcar
- (function
- (lambda (name)
- (setq position (1+ position))
- (let ((keep-p t))
- (mapcar
- (function
- (lambda (filter)
- (let ((regexp (car filter))
- (pos (cdr filter)))
- (if (and (string-match regexp name)
- (or (and (numberp pos)
- (= pos position))
- (and (eq pos 'last)
- (= position (1- elements)))
- (eq pos 'any)))
- (setq keep-p nil))
- )))
- sc-name-filter-alist)
- (if keep-p
- (setq keepers (cons position keepers)))
- )))
- namelist)
- (mapcar
- (function
- (lambda (position)
- (setq filtered-list (cons (nth position namelist) filtered-list))
- ))
- keepers)
- filtered-list))
-
-(defun sc-attribs-chop-address (from)
- "Extract attribution information from FROM.
-This populates the `sc-attributions' with the list of possible attributions."
- (if (and (stringp from)
- (< 0 (length from)))
- (let* ((sc-mumble "")
- (namestring (sc-attribs-extract-namestring from))
- (namelist (sc-attribs-filter-namelist
- (sc-attribs-chop-namestring namestring)))
- (revnames (reverse (cdr namelist)))
- (firstname (car namelist))
- (midnames (reverse (cdr revnames)))
- (lastname (car revnames))
- (initials (sc-attribs-strip-initials namelist))
- (emailname (sc-attribs-emailname from))
- (n 1)
- author middlenames)
-
- ;; put basic information
- (setq
- ;; put middle names and build sc-author entry
- middlenames (mapconcat
- (function
- (lambda (midname)
- (let ((key-attribs (format "middlename-%d" n))
- (key-mail (format "sc-middlename-%d" n)))
- (setq
- sc-attributions (cons (cons key-attribs midname)
- sc-attributions)
- sc-mail-info (cons (cons key-mail midname)
- sc-mail-info)
- n (1+ n))
- midname)))
- midnames " ")
-
- author (concat firstname " " middlenames (and midnames " ") lastname)
-
- sc-attributions (append
- (list
- (cons "firstname" firstname)
- (cons "lastname" lastname)
- (cons "emailname" emailname)
- (cons "initials" initials))
- sc-attributions)
- sc-mail-info (append
- (list
- (cons "sc-firstname" firstname)
- (cons "sc-middlenames" middlenames)
- (cons "sc-lastname" lastname)
- (cons "sc-emailname" emailname)
- (cons "sc-initials" initials)
- (cons "sc-author" author)
- (cons "sc-from-address" (sc-get-address
- (sc-mail-field "from")
- namestring))
- (cons "sc-reply-address" (sc-get-address
- (sc-mail-field "reply-to")
- namestring))
- (cons "sc-sender-address" (sc-get-address
- (sc-mail-field "sender")
- namestring))
- )
- sc-mail-info)
- ))
- ;; from string is empty
- (setq sc-mail-info (cons (cons "sc-author" sc-default-author-name)
- sc-mail-info))))
-
-(defvar sc-attrib-or-cite nil
- "Used to toggle between attribution input or citation input.")
-
-(defun sc-toggle-fn ()
- "Toggle between attribution selection and citation selection.
-Only used during confirmation."
- (interactive)
- (setq sc-attrib-or-cite (not sc-attrib-or-cite))
- (throw 'sc-reconfirm t))
-
-(defun sc-select-attribution ()
- "Select an attribution from `sc-attributions'.
-
-Variables involved in selection process include:
- `sc-preferred-attribution-list'
- `sc-use-only-preference-p'
- `sc-confirm-always-p'
- `sc-default-attribution'
- `sc-attrib-selection-list'.
-
-Runs the hook `sc-attribs-preselect-hook' before selecting an
-attribution and the hook `sc-attribs-postselect-hook' after making the
-selection but before querying is performed. During
-`sc-attribs-postselect-hook' the variable `citation' is bound to the
-auto-selected citation string and the variable `attribution' is bound
-to the auto-selected attribution string."
- (run-hooks 'sc-attribs-preselect-hook)
- (let ((query-p sc-confirm-always-p)
- attribution citation
- (attriblist sc-preferred-attribution-list))
-
- ;; first cruise through sc-preferred-attribution-list looking for
- ;; a match in either sc-attributions or sc-mail-info. if the
- ;; element is "sc-consult", then we have to do the alist
- ;; consultation phase
- (while attriblist
- (let* ((preferred (car attriblist)))
- (cond
- ((string= preferred "sc-consult")
- ;; we've been told to consult the attribution vs. mail
- ;; header key alist. we do this until we find a match in
- ;; the sc-attrib-selection-list. if we do not find a match,
- ;; we continue scanning attriblist
- (let ((attrib (sc-scan-info-alist sc-attrib-selection-list)))
- (cond
- ((not attrib)
- (setq attriblist (cdr attriblist)))
- ((stringp attrib)
- (setq attribution attrib
- attriblist nil))
- ((listp attrib)
- (setq attribution (eval attrib)
- attriblist nil))
- (t (error "%s did not evaluate to a string or list!"
- "sc-attrib-selection-list"))
- )))
- ((setq attribution (cdr (assoc preferred sc-attributions)))
- (setq attriblist nil))
- (t
- (setq attriblist (cdr attriblist)))
- )))
-
- ;; if preference was not found, we may use a secondary method to
- ;; find a valid attribution
- (if (and (not attribution)
- (not sc-use-only-preference-p))
- ;; secondary method tries to find a preference in this order
- ;; 1. sc-lastchoice
- ;; 2. x-attribution
- ;; 3. firstname
- ;; 4. lastname
- ;; 5. initials
- ;; 6. first non-empty attribution in alist
- (setq attribution
- (or (cdr (assoc "sc-lastchoice" sc-attributions))
- (cdr (assoc "x-attribution" sc-attributions))
- (cdr (assoc "firstname" sc-attributions))
- (cdr (assoc "lastname" sc-attributions))
- (cdr (assoc "initials" sc-attributions))
- (cdr (car sc-attributions)))))
-
- ;; still couldn't find an attribution. we're now limited to using
- ;; the default attribution, but we'll force a query when this happens
- (if (not attribution)
- (setq attribution sc-default-attribution
- query-p t))
-
- ;; create the attribution prefix
- (setq citation (sc-make-citation attribution))
-
- ;; run the post selection hook before querying the user
- (run-hooks 'sc-attribs-postselect-hook)
-
- ;; query for confirmation
- (if query-p
- (let* ((query-alist (mapcar (function (lambda (entry)
- (list (cdr entry))))
- sc-attributions))
- (minibuffer-local-completion-map
- sc-minibuffer-local-completion-map)
- (minibuffer-local-map sc-minibuffer-local-map)
- (initial attribution)
- (completer-disable t) ; in case completer.el is used
- choice)
- (setq sc-attrib-or-cite nil) ; nil==attribution, t==citation
- (while
- (catch 'sc-reconfirm
- (string= "" (setq choice
- (if sc-attrib-or-cite
- (sc-read-string
- "Enter citation prefix: "
- citation
- 'sc-citation-confirmation-history)
- (sc-completing-read
- "Complete attribution name: "
- query-alist nil nil
- (cons initial 0)
- 'sc-attribution-confirmation-history)
- )))))
- (if sc-attrib-or-cite
- ;; since the citation was chosen, we have to guess at
- ;; the attribution
- (setq citation choice
- attribution (or (sc-guess-attribution citation)
- citation))
-
- (setq citation (sc-make-citation choice)
- attribution choice))
- ))
-
- ;; its possible that the user wants to downcase the citation and
- ;; attribution
- (if sc-downcase-p
- (setq citation (downcase citation)
- attribution (downcase attribution)))
-
- ;; set up mail info alist
- (let* ((ckey "sc-citation")
- (akey "sc-attribution")
- (ckeyval (assoc ckey sc-mail-info))
- (akeyval (assoc akey sc-mail-info)))
- (if ckeyval
- (setcdr ckeyval citation)
- (setq sc-mail-info
- (append (list (cons ckey citation)) sc-mail-info)))
- (if akeyval
- (setcdr akeyval attribution)
- (setq sc-mail-info
- (append (list (cons akey attribution)) sc-mail-info))))
-
- ;; set the sc-lastchoice attribution
- (let* ((lkey "sc-lastchoice")
- (lastchoice (assoc lkey sc-attributions)))
- (if lastchoice
- (setcdr lastchoice attribution)
- (setq sc-attributions
- (cons (cons lkey attribution) sc-attributions))))
- ))
-
-
-;; ======================================================================
-;; filladapt hooks for supercite 3.1. you shouldn't need anything
-;; extra to make gin-mode understand supercited lines. Even this
-;; stuff might not be entirely necessary...
-
-(defun sc-cite-regexp (&optional root-regexp)
- "Return a regexp describing a Supercited line.
-The regexp is the concatenation of `sc-citation-leader-regexp',
-`sc-citation-root-regexp', `sc-citation-delimiter-regexp', and
-`sc-citation-separator-regexp'. If optional ROOT-REGEXP is supplied,
-use it instead of `sc-citation-root-regexp'."
- (concat sc-citation-leader-regexp
- (or root-regexp sc-citation-root-regexp)
- sc-citation-delimiter-regexp
- sc-citation-separator-regexp))
-
-(defun sc-make-citation (attribution)
- "Make a non-nested citation from ATTRIBUTION."
- (concat sc-citation-leader
- attribution
- sc-citation-delimiter
- sc-citation-separator))
-
-(defun sc-setup-filladapt ()
- "Setup `filladapt-prefix-table' to handle Supercited paragraphs."
- (let* ((fa-sc-elt 'filladapt-supercite-included-text)
- (elt (rassq fa-sc-elt filladapt-prefix-table)))
- (if elt (setcar elt (sc-cite-regexp))
- (message "Filladapt doesn't seem to know about Supercite.")
- (beep))))
-
-
-;; ======================================================================
-;; citing and unciting regions of text
-
-(defvar sc-fill-begin 1
- "Buffer position to begin filling.")
-(defvar sc-fill-line-prefix ""
- "Fill prefix of previous line")
-
-;; filling
-(defun sc-fill-if-different (&optional prefix)
- "Fill the region bounded by `sc-fill-begin' and point.
-Only fill if optional PREFIX is different than `sc-fill-line-prefix'.
-If `sc-auto-fill-region-p' is nil, do not fill region. If PREFIX is
-not supplied, initialize fill variables. This is useful for a regi
-`begin' frame-entry."
- (if (not prefix)
- (setq sc-fill-line-prefix ""
- sc-fill-begin (regi-pos 'bol))
- (if (and sc-auto-fill-region-p
- (not (string= prefix sc-fill-line-prefix)))
- (let ((fill-prefix sc-fill-line-prefix))
- (if (not (string= fill-prefix ""))
- (fill-region sc-fill-begin (regi-pos 'bol)))
- (setq sc-fill-line-prefix prefix
- sc-fill-begin (regi-pos 'bol))))
- )
- nil)
-
-(defun sc-cite-coerce-cited-line ()
- "Coerce a Supercited line to look like our style."
- (let* ((attribution (sc-guess-attribution))
- (regexp (sc-cite-regexp attribution))
- (prefix (sc-make-citation attribution)))
- (if (and attribution
- (looking-at regexp))
- (progn
- (delete-region
- (match-beginning 0)
- (save-excursion
- (goto-char (match-end 0))
- (if (bolp) (forward-char -1))
- (point)))
- (insert prefix)
- (sc-fill-if-different prefix)))
- nil))
-
-(defun sc-cite-coerce-dumb-citer ()
- "Coerce a non-nested citation that's been cited with a dumb nesting citer."
- (delete-region (match-beginning 1) (match-end 1))
- (beginning-of-line)
- (sc-cite-coerce-cited-line))
-
-(defun sc-guess-nesting (&optional string)
- "Guess the citation nesting on the current line.
-If nesting cannot be guessed, nil is returned. Optional STRING if
-supplied, is used instead of the line point is on in the current
-buffer."
- (let ((start 0)
- (string (or string (buffer-substring (regi-pos 'bol) (regi-pos 'eol))))
- nesting)
- (and
- (= start (or (string-match sc-citation-leader-regexp string start) -1))
- (setq start (match-end 0))
- (= start (or (string-match sc-citation-delimiter-regexp string start) -1))
- (setq nesting (sc-submatch 0 string)
- start (match-end 0))
- (= start (or (string-match sc-citation-separator-regexp string start) -1))
- nesting)))
-
-(defun sc-add-citation-level ()
- "Add a citation level for nested citation style w/ coercion."
- (let* ((nesting (sc-guess-nesting))
- (citation (make-string (1+ (length nesting))
- (string-to-char sc-citation-delimiter)))
- (prefix (concat sc-citation-leader citation sc-citation-separator)))
- (if (looking-at (sc-cite-regexp ""))
- (delete-region (match-beginning 0) (match-end 0)))
- (insert prefix)
- (sc-fill-if-different prefix)))
-
-(defun sc-cite-line (&optional citation)
- "Cite a single line of uncited text.
-Optional CITATION overrides any citation automatically selected."
- (if sc-fixup-whitespace-p
- (fixup-whitespace))
- (let ((prefix (or citation
- (cdr (assoc "sc-citation" sc-mail-info))
- sc-default-attribution)))
- (insert prefix)
- (sc-fill-if-different prefix))
- nil)
-
-(defun sc-uncite-line ()
- "Remove citation from current line."
- (let ((cited (looking-at (sc-cite-regexp))))
- (if cited
- (delete-region (match-beginning 0) (match-end 0))))
- nil)
-
-(defun sc-recite-line (regexp)
- "Remove citation matching REGEXP from current line and recite line."
- (let ((cited (looking-at (concat "^" regexp)))
- (prefix (cdr (assoc "sc-citation" sc-mail-info))))
- (if cited
- (delete-region (match-beginning 0) (match-end 0)))
- (insert (or prefix sc-default-attribution))
- (sc-fill-if-different prefix))
- nil)
-
-;; interactive functions
-(defun sc-cite-region (start end &optional confirm-p)
- "Cite a region delineated by START and END.
-If optional CONFIRM-P is non-nil, the attribution is confirmed before
-its use in the citation string. This function first runs
-`sc-pre-cite-hook'."
- (interactive "r\nP")
- (undo-boundary)
- (let ((frame (or (sc-scan-info-alist sc-cite-frame-alist)
- sc-default-cite-frame))
- (sc-confirm-always-p (if confirm-p t sc-confirm-always-p)))
- (run-hooks 'sc-pre-cite-hook)
- (if (interactive-p)
- (sc-select-attribution))
- (regi-interpret frame start end)))
-
-(defun sc-uncite-region (start end)
- "Uncite a region delineated by START and END.
-First runs `sc-pre-uncite-hook'."
- (interactive "r")
- (undo-boundary)
- (let ((frame (or (sc-scan-info-alist sc-uncite-frame-alist)
- sc-default-uncite-frame)))
- (run-hooks 'sc-pre-uncite-hook)
- (regi-interpret frame start end)))
-
-(defun sc-recite-region (start end)
- "Recite a region delineated by START and END.
-First runs `sc-pre-recite-hook'."
- (interactive "r")
- (let ((sc-confirm-always-p t))
- (sc-select-attribution))
- (undo-boundary)
- (let ((frame (or (sc-scan-info-alist sc-recite-frame-alist)
- sc-default-recite-frame)))
- (run-hooks 'sc-pre-recite-hook)
- (regi-interpret frame start end)))
-
-
-;; ======================================================================
-;; building headers
-
-(defun sc-hdr (prefix field &optional sep return-nil-p)
- "Returns a concatenation of PREFIX and FIELD.
-If FIELD is not a string or is the empty string, the empty string will
-be returned. Optional third argument SEP is concatenated on the end if
-it is a string. Returns empty string, unless optional RETURN-NIL-P is
-non-nil."
- (if (and (stringp field)
- (not (string= field "")))
- (concat prefix field (or sep ""))
- (and (not return-nil-p) "")))
-
-(defun sc-whofrom ()
- "Return the value of (sc-mail-field \"from\") or nil."
- (let ((sc-mumble nil))
- (sc-mail-field "from")))
-
-(defun sc-no-header ()
- "Does nothing. Use this instead of nil to get a blank header."
- ())
-
-(defun sc-no-blank-line-or-header()
- "Similar to `sc-no-header' except it removes the preceding blank line."
- (if (not (bobp))
- (if (and (eolp)
- (progn (forward-line -1)
- (or (looking-at
- (concat "^" (regexp-quote mail-header-separator) "$"))
- (and (eq major-mode 'mh-letter-mode)
- (mh-in-header-p)))))
- (progn (forward-line)
- (let ((kill-lines-magic t))
- (kill-line))))))
-
-(defun sc-header-on-said ()
- "\"On <date>, <from> said:\" unless:
-1. the \"from\" field cannot be found, in which case nothing is inserted;
-2. the \"date\" field is missing in which case only the from part is printed."
- (let ((sc-mumble "")
- (whofrom (sc-whofrom)))
- (if whofrom
- (insert sc-reference-tag-string
- (sc-hdr "On " (sc-mail-field "date") ", ")
- whofrom " said:\n"))))
-
-(defun sc-header-inarticle-writes ()
- "\"In article <message-id>, <from> writes:\"
-Treats \"message-id\" and \"from\" fields similar to `sc-header-on-said'."
- (let ((sc-mumble "")
- (whofrom (sc-mail-field "from")))
- (if whofrom
- (insert sc-reference-tag-string
- (sc-hdr "In article " (sc-mail-field "message-id") ", ")
- whofrom " writes:\n"))))
-
-(defun sc-header-regarding-adds ()
- "\"Regarding <subject>; <from> adds:\"
-Treats \"subject\" and \"from\" fields similar to `sc-header-on-said'."
- (let ((sc-mumble "")
- (whofrom (sc-whofrom)))
- (if whofrom
- (insert sc-reference-tag-string
- (sc-hdr "Regarding " (sc-mail-field "subject") "; ")
- whofrom " adds:\n"))))
-
-(defun sc-header-attributed-writes ()
- "\"<sc-attribution>\" == <sc-author> <address> writes:
-Treats these fields in a similar manner to `sc-header-on-said'."
- (let ((sc-mumble "")
- (whofrom (sc-whofrom)))
- (if whofrom
- (insert sc-reference-tag-string
- (sc-hdr "\"" (sc-mail-field "sc-attribution") "\" == ")
- (sc-hdr "" (sc-mail-field "sc-author") " ")
- (or (sc-hdr "<" (sc-mail-field "sc-from-address") ">" t)
- (sc-hdr "<" (sc-mail-field "sc-reply-address") ">" t)
- "")
- " writes:\n"))))
-
-(defun sc-header-author-writes ()
- "<sc-author> writes:"
- (let ((sc-mumble "")
- (whofrom (sc-whofrom)))
- (if whofrom
- (insert sc-reference-tag-string
- (sc-hdr "" (sc-mail-field "sc-author"))
- " writes:\n"))))
-
-(defun sc-header-verbose ()
- "Very verbose, some say gross."
- (let ((sc-mumble "")
- (whofrom (sc-whofrom))
- (tag sc-reference-tag-string))
- (if whofrom
- (insert (sc-hdr (concat tag "On ") (sc-mail-field "date") ",\n")
- (or (sc-hdr tag (sc-mail-field "sc-author") "\n" t)
- (concat tag whofrom "\n"))
- (sc-hdr (concat tag "from the organization of ")
- (sc-mail-field "organization") "\n")
- (let ((rtag (concat tag "who can be reached at: ")))
- (or (sc-hdr rtag (sc-mail-field "sc-from-address") "\n" t)
- (sc-hdr rtag (sc-mail-field "sc-reply-address") "\n" t)
- ""))
- (sc-hdr
- (concat tag "(whose comments are cited below with \"")
- (sc-mail-field "sc-citation") "\"),\n")
- (sc-hdr (concat tag "had this to say in article ")
- (sc-mail-field "message-id") "\n")
- (sc-hdr (concat tag "in newsgroups ")
- (sc-mail-field "newsgroups") "\n")
- (sc-hdr (concat tag "concerning the subject of ")
- (sc-mail-field "subject") "\n")
- (sc-hdr (concat tag "(see ")
- (sc-mail-field "references")
- " for more details)\n")
- ))))
-
-
-;; ======================================================================
-;; header rewrites
-
-(defconst sc-electric-bufname " *sc-erefs* "
- "Supercite electric reference mode's buffer name.")
-(defvar sc-eref-style 0
- "Current electric reference style.")
-
-(defun sc-valid-index-p (index)
- "Returns INDEX if it is a valid index into `sc-rewrite-header-list'.
-Otherwise returns nil."
- ;; a number, and greater than or equal to zero
- ;; less than or equal to the last index
- (and (natnump index)
- (< index (length sc-rewrite-header-list))
- index))
-
-(defun sc-eref-insert-selected (&optional nomsg)
- "Insert the selected reference header in the current buffer.
-Optional NOMSG, if non-nil, inhibits printing messages, unless an
-error occurs."
- (let ((ref (nth sc-eref-style sc-rewrite-header-list)))
- (condition-case err
- (progn
- (eval ref)
- (let ((lines (count-lines (point-min) (point-max))))
- (or nomsg (message "Ref header %d [%d line%s]: %s"
- sc-eref-style lines
- (if (= lines 1) "" "s")
- ref))))
- (void-function
- (progn (message
- "Symbol's function definition is void: %s (Header %d)"
- (car (cdr err)) sc-eref-style)
- (beep)
- ))
- )))
-
-(defun sc-electric-mode (&optional arg)
- "
-Mode for viewing Supercite reference headers. Commands are:
-\n\\{sc-electric-mode-map}
-
-`sc-electric-mode' is not intended to be run interactively, but rather
-accessed through Supercite's electric reference feature. See
-`sc-insert-reference' for more details. Optional ARG is the initial
-header style to use, unless not supplied or invalid, in which case
-`sc-preferred-header-style' is used."
-
- (let ((info sc-mail-info))
-
- (setq sc-eref-style
- (or (sc-valid-index-p arg)
- (sc-valid-index-p sc-preferred-header-style)
- 0))
-
- (get-buffer-create sc-electric-bufname)
- ;; set up buffer and enter command loop
- (save-excursion
- (save-window-excursion
- (pop-to-buffer sc-electric-bufname)
- (kill-all-local-variables)
- (let ((sc-mail-info info)
- (buffer-read-only t)
- (mode-name "SC Electric Refs")
- (major-mode 'sc-electric-mode))
- (use-local-map sc-electric-mode-map)
- (sc-eref-show sc-eref-style)
- (run-hooks 'sc-electric-mode-hook)
- (recursive-edit)
- )))
-
- (and sc-eref-style
- (sc-eref-insert-selected))
- (kill-buffer sc-electric-bufname)
- ))
-
-;; functions for electric reference mode
-(defun sc-eref-show (index)
- "Show reference INDEX in `sc-rewrite-header-list'."
- (let ((msg "No %ing reference headers in list.")
- (last (length sc-rewrite-header-list)))
- (setq sc-eref-style
- (cond
- ((sc-valid-index-p index) index)
- ((< index 0)
- (if sc-electric-circular-p
- (1- last)
- (progn (error msg "preced") 0)))
- ((>= index last)
- (if sc-electric-circular-p
- 0
- (progn (error msg "follow") (1- last))))
- ))
- (save-excursion
- (set-buffer sc-electric-bufname)
- (let ((buffer-read-only nil))
- (erase-buffer)
- (goto-char (point-min))
- (sc-eref-insert-selected)
- ;; now shrink the window to just contain the electric reference
- ;; header.
- (let ((hdrlines (count-lines (point-min) (point-max)))
- (winlines (1- (window-height))))
- (if (/= hdrlines winlines)
- (if (> hdrlines winlines)
- ;; we have to enlarge the window
- (enlarge-window (- hdrlines winlines))
- ;; we have to shrink the window
- (shrink-window (- winlines (max hdrlines window-min-height)))
- )))
- ))))
-
-(defun sc-eref-next ()
- "Display next reference in other buffer."
- (interactive)
- (sc-eref-show (1+ sc-eref-style)))
-
-(defun sc-eref-prev ()
- "Display previous reference in other buffer."
- (interactive)
- (sc-eref-show (1- sc-eref-style)))
-
-(defun sc-eref-setn ()
- "Set reference header selected as preferred."
- (interactive)
- (setq sc-preferred-header-style sc-eref-style)
- (message "Preferred reference style set to header %d." sc-eref-style))
-
-(defun sc-eref-goto (refnum)
- "Show reference style indexed by REFNUM.
-If REFNUM is an invalid index, don't go to that reference and return
-nil."
- (interactive "NGoto Reference: ")
- (if (sc-valid-index-p refnum)
- (sc-eref-show refnum)
- (error "Invalid reference: %d. (Range: [%d .. %d])"
- refnum 0 (1- (length sc-rewrite-header-list)))
- ))
-
-(defun sc-eref-jump ()
- "Set reference header to preferred header."
- (interactive)
- (sc-eref-show sc-preferred-header-style))
-
-(defun sc-eref-abort ()
- "Exit from electric reference mode without inserting reference."
- (interactive)
- (setq sc-eref-style nil)
- (exit-recursive-edit))
-
-(defun sc-eref-exit ()
- "Exit from electric reference mode and insert selected reference."
- (interactive)
- (exit-recursive-edit))
-
-(defun sc-insert-reference (arg)
- "Insert, at point, a reference header in the body of the reply.
-Numeric ARG indicates which header style from `sc-rewrite-header-list'
-to use when rewriting the header. No supplied ARG indicates use of
-`sc-preferred-header-style'.
-
-With just `\\[universal-argument]', electric reference insert mode is
-entered, regardless of the value of `sc-electric-references-p'. See
-`sc-electric-mode' for more information."
- (interactive "P")
- (if (consp arg)
- (sc-electric-mode)
- (let ((preference (or (sc-valid-index-p arg)
- (sc-valid-index-p sc-preferred-header-style)
- sc-preferred-header-style
- 0)))
- (if sc-electric-references-p
- (sc-electric-mode preference)
- (sc-eref-insert-selected t)
- ))))
-
-
-;; ======================================================================
-;; variable toggling
-
-(defun sc-raw-mode-toggle ()
- "Toggle, in one fell swoop, two important SC variables:
-`sc-fixup-whitespace-p' and `sc-auto-fill-region-p'"
- (interactive)
- (setq sc-fixup-whitespace-p (not sc-fixup-whitespace-p)
- sc-auto-fill-region-p (not sc-auto-fill-region-p))
- (sc-set-mode-string)
- (force-mode-line-update))
-
-(defun sc-toggle-var (variable)
- "Boolean toggle VARIABLE's value.
-VARIABLE must be a bound symbol. Nil values change to t, non-nil
-values are changed to nil."
- (message "%s changed from %s to %s"
- variable (symbol-value variable)
- (set-variable variable (not (eval-expression variable))))
- (sc-set-mode-string))
-
-(defun sc-set-variable (var)
- "Set the Supercite VARIABLE.
-This function mimics `set-variable', except that the variable to set
-is determined non-interactively. The value is queried for in the
-minibuffer exactly the same way that `set-variable' does it.
-
-You can see the current value of the variable when the minibuffer is
-querying you by typing `C-h'. Note that the format is changed
-slightly from that used by `set-variable' -- the current value is
-printed just after the variable's name instead of at the bottom of the
-help window."
- (let* ((minibuffer-help-form
- '(funcall myhelp))
- (myhelp
- (function
- (lambda ()
- (with-output-to-temp-buffer "*Help*"
- (prin1 var)
- (if (boundp var)
- (let ((print-length 20))
- (princ "\t(Current value: ")
- (prin1 (symbol-value var))
- (princ ")")))
- (princ "\n\nDocumentation:\n")
- (princ (substring (documentation-property
- var
- 'variable-documentation)
- 1))
- (save-excursion
- (set-buffer standard-output)
- (help-mode))
- nil)))))
- (set var (eval-minibuffer (format "Set %s to value: " var))))
- (sc-set-mode-string))
-
-(defmacro sc-toggle-symbol (rootname)
- (list 'defun (intern (concat "sc-T-" rootname)) '()
- (list 'interactive)
- (list 'sc-toggle-var
- (list 'quote (intern (concat "sc-" rootname "-p"))))))
-
-(defmacro sc-setvar-symbol (rootname)
- (list 'defun (intern (concat "sc-S-" rootname)) '()
- (list 'interactive)
- (list 'sc-set-variable
- (list 'quote (intern (concat "sc-" rootname))))))
-
-(sc-toggle-symbol "confirm-always")
-(sc-toggle-symbol "downcase")
-(sc-toggle-symbol "electric-references")
-(sc-toggle-symbol "auto-fill-region")
-(sc-toggle-symbol "mail-nuke-blank-lines")
-(sc-toggle-symbol "nested-citation")
-(sc-toggle-symbol "electric-circular")
-(sc-toggle-symbol "use-only-preferences")
-(sc-toggle-symbol "fixup-whitespace")
-
-(sc-setvar-symbol "preferred-attribution-list")
-(sc-setvar-symbol "preferred-header-style")
-(sc-setvar-symbol "mail-nuke-mail-headers")
-(sc-setvar-symbol "mail-header-nuke-list")
-(sc-setvar-symbol "cite-region-limit")
-
-(defun sc-T-describe ()
- "
-
-Supercite provides a number of key bindings which simplify the process
-of setting or toggling certain variables controlling its operation.
-
-Note on function names in this list: all functions of the form
-`sc-S-<name>' actually call `sc-set-variable' on the corresponding
-`sc-<name>' variable. All functions of the form `sc-T-<name>' call
-`sc-toggle-var' on the corresponding `sc-<name>-p' variable.
-
-\\{sc-T-keymap}"
- (interactive)
- (describe-function 'sc-T-describe))
-
-(defun sc-set-mode-string ()
- "Update the minor mode string to show state of Supercite."
- (setq sc-mode-string
- (concat " SC"
- (if (or sc-auto-fill-region-p
- sc-fixup-whitespace-p)
- ":" "")
- (if sc-auto-fill-region-p "f" "")
- (if sc-fixup-whitespace-p "w" "")
- )))
-
-
-;; ======================================================================
-;; published interface to mail and news readers
-
-;;;###autoload
-(defun sc-cite-original ()
- "Workhorse citing function which performs the initial citation.
-This is callable from the various mail and news readers' reply
-function according to the agreed upon standard. See `\\[sc-describe]'
-for more details. `sc-cite-original' does not do any yanking of the
-original message but it does require a few things:
-
- 1) The reply buffer is the current buffer.
-
- 2) The original message has been yanked and inserted into the
- reply buffer.
-
- 3) Verbose mail headers from the original message have been
- inserted into the reply buffer directly before the text of the
- original message.
-
- 4) Point is at the beginning of the verbose headers.
-
- 5) Mark is at the end of the body of text to be cited.
-
-For Emacs 19's, the region need not be active (and typically isn't
-when this function is called. Also, the hook `sc-pre-hook' is run
-before, and `sc-post-hook' is run after the guts of this function."
- (run-hooks 'sc-pre-hook)
-
- ;; before we do anything, we want to insert the supercite keymap so
- ;; we can proceed from here
- (and sc-mode-map-prefix
- (local-set-key sc-mode-map-prefix sc-mode-map))
-
- ;; hack onto the minor mode alist, if it hasn't been done before,
- ;; then turn on the minor mode. also, set the minor mode string with
- ;; the values of fill and fixup whitespace variables
- (if (not (get 'minor-mode-alist 'sc-minor-mode))
- (progn
- (put 'minor-mode-alist 'sc-minor-mode 'sc-minor-mode)
- (setq minor-mode-alist
- (cons '(sc-minor-mode sc-mode-string) minor-mode-alist))
- ))
- (setq sc-minor-mode t)
- (sc-set-mode-string)
-
- (undo-boundary)
-
- ;; grab point and mark since the region is probably not active when
- ;; this function gets automatically called. we want point to be a
- ;; mark so any deleting before point works properly
- (let* ((zmacs-regions nil) ; for Lemacs
- (mark-active t) ; for FSFmacs
- (point (point-marker))
- (mark (copy-marker (mark-marker))))
-
- ;; make sure point comes before mark, not all functions are
- ;; interactive "r"
- (if (< mark point)
- (let ((tmp point))
- (setq point mark
- mark tmp)))
-
- ;; first process mail headers, and populate sc-mail-info
- (sc-mail-process-headers point mark)
-
- ;; now get possible attributions
- (sc-attribs-chop-address (or (sc-mail-field "from")
- (sc-mail-field "reply")
- (sc-mail-field "reply-to")
- (sc-mail-field "sender")))
- ;; select the attribution
- (sc-select-attribution)
-
- ;; cite the region, but first check the value of sc-cite-region-limit
- (let ((linecnt (count-lines point mark)))
- (and sc-cite-region-limit
- (if (or (not (numberp sc-cite-region-limit))
- (<= linecnt sc-cite-region-limit))
- (progn
- ;; cite the region and insert the header rewrite
- (sc-cite-region point mark)
- (goto-char point)
- (let ((sc-eref-style (or sc-preferred-header-style 0)))
- (if sc-electric-references-p
- (sc-electric-mode sc-eref-style)
- (sc-eref-insert-selected t))))
- (beep)
- (message
- "Region not cited. %d lines exceeds sc-cite-region-limit: %d"
- linecnt sc-cite-region-limit))))
-
- ;; finally, free the point-marker
- (set-marker point nil)
- (set-marker mark nil)
- )
- (run-hooks 'sc-post-hook)
- ;; post hook could have changed the variables
- (sc-set-mode-string))
-
-
-;; ======================================================================
-;; bug reporting and miscellaneous commands
-
-(defun sc-open-line (arg)
- "Like `open-line', but insert the citation prefix at the front of the line.
-With numeric ARG, inserts that many new lines."
- (interactive "p")
- (save-excursion
- (let ((start (point))
- (prefix (or (progn (beginning-of-line)
- (if (looking-at (sc-cite-regexp))
- (sc-submatch 0)))
- "")))
- (goto-char start)
- (open-line arg)
- (forward-line 1)
- (while (< 0 arg)
- (insert prefix)
- (forward-line 1)
- (setq arg (1- arg))
- ))))
-
-(defun sc-insert-citation (arg)
- "Insert citation string at beginning of current line if not already cited.
-With `\\[universal-argument]' insert citation even if line is already
-cited."
- (interactive "P")
- (save-excursion
- (beginning-of-line)
- (if (or (not (looking-at (sc-cite-regexp)))
- (looking-at "^[ \t]*$")
- (consp arg))
- (insert (sc-mail-field "sc-citation"))
- (error "Line is already cited."))))
-
-(defun sc-version (arg)
- "Echo the current version of Supercite in the minibuffer.
-With \\[universal-argument] (universal-argument), or if run non-interactively,
-inserts the version string in the current buffer instead."
- (interactive "P")
- (let ((verstr (format "Using Supercite.el %s" sc-version)))
- (if (or (consp arg)
- (not (interactive-p)))
- (insert "`sc-version' says: " verstr)
- (message verstr))))
-
-(defun sc-describe ()
- "
-Supercite is a package which provides a flexible mechanism for citing
-email and news replies. Please see the associated texinfo file for
-more information."
- (interactive)
- (describe-function 'sc-describe))
-
-(defun sc-submit-bug-report ()
- "Submit a bug report on Supercite via mail."
- (interactive)
- (require 'reporter)
- (and
- (y-or-n-p "Do you want to submit a report on Supercite? ")
- (reporter-submit-bug-report
- sc-help-address
- (concat "Supercite version " sc-version)
- (list
- 'sc-attrib-selection-list
- 'sc-auto-fill-region-p
- 'sc-blank-lines-after-headers
- 'sc-citation-leader
- 'sc-citation-delimiter
- 'sc-citation-separator
- 'sc-citation-leader-regexp
- 'sc-citation-root-regexp
- 'sc-citation-nonnested-root-regexp
- 'sc-citation-delimiter-regexp
- 'sc-citation-separator-regexp
- 'sc-cite-region-limit
- 'sc-confirm-always-p
- 'sc-default-attribution
- 'sc-default-author-name
- 'sc-downcase-p
- 'sc-electric-circular-p
- 'sc-electric-references-p
- 'sc-fixup-whitespace-p
- 'sc-mail-warn-if-non-rfc822-p
- 'sc-mumble
- 'sc-name-filter-alist
- 'sc-nested-citation-p
- 'sc-nuke-mail-headers
- 'sc-nuke-mail-header-list
- 'sc-preferred-attribution-list
- 'sc-preferred-header-style
- 'sc-reference-tag-string
- 'sc-rewrite-header-list
- 'sc-titlecue-regexp
- 'sc-use-only-preference-p
- ))))
-
-
-;; useful stuff
-(provide 'supercite)
-(run-hooks 'sc-load-hook)
-
-;;; supercite.el ends here
diff --git a/lisp/mail/undigest.el b/lisp/mail/undigest.el
deleted file mode 100644
index 3a3319ec1b5..00000000000
--- a/lisp/mail/undigest.el
+++ /dev/null
@@ -1,184 +0,0 @@
-;;; undigest.el --- digest-cracking support for the RMAIL mail reader
-
-;; Copyright (C) 1985, 1986, 1994, 1996 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; See Internet RFC 934
-
-;;; Code:
-
-(require 'rmail)
-
-;;;###autoload
-(defun undigestify-rmail-message ()
- "Break up a digest message into its constituent messages.
-Leaves original message, deleted, before the undigestified messages."
- (interactive)
- (widen)
- (let ((buffer-read-only nil)
- (msg-string (buffer-substring (rmail-msgbeg rmail-current-message)
- (rmail-msgend rmail-current-message))))
- (goto-char (rmail-msgend rmail-current-message))
- (narrow-to-region (point) (point))
- (insert msg-string)
- (narrow-to-region (point-min) (1- (point-max))))
- (let ((error t)
- (buffer-read-only nil))
- (unwind-protect
- (progn
- (save-restriction
- (goto-char (point-min))
- (delete-region (point-min)
- (progn (search-forward "\n*** EOOH ***\n")
- (point)))
- (insert "\^_\^L\n0, unseen,,\n*** EOOH ***\n")
- (narrow-to-region (point)
- (point-max))
- (let* ((fill-prefix "")
- (case-fold-search t)
- start
- (digest-name
- (mail-strip-quoted-names
- (or (save-restriction
- (search-forward "\n\n")
- (setq start (point))
- (narrow-to-region (point-min) (point))
- (goto-char (point-max))
- (or (mail-fetch-field "Reply-To")
- (mail-fetch-field "To")
- (mail-fetch-field "Apparently-To")
- (mail-fetch-field "From")))
- (error "Message is not a digest--bad header")))))
- (save-excursion
- (goto-char (point-max))
- (skip-chars-backward " \t\n")
- (let (found)
- ;; compensate for broken un*x digestifiers. Sigh Sigh.
- (while (and (> (point) start) (not found))
- (forward-line -1)
- (if (looking-at (concat "End of.*Digest.*\n"
- (regexp-quote "*********") "*"
- "\\(\n------*\\)*"))
- (setq found t)))
- (if (not found)
- (error "Message is not a digest--no end line"))))
- (re-search-forward (concat "^" (make-string 55 ?-) "-*\n*"))
- (replace-match "\^_\^L\n0, unseen,,\n*** EOOH ***\n")
- (save-restriction
- (narrow-to-region (point)
- (progn (search-forward "\n\n")
- (point)))
- (if (mail-fetch-field "To") nil
- (goto-char (point-min))
- (insert "To: " digest-name "\n")))
- (while (re-search-forward
- (concat "\n\n" (make-string 27 ?-) "-*\n*")
- nil t)
- (replace-match "\n\n\^_\^L\n0, unseen,,\n*** EOOH ***\n")
- (save-restriction
- (if (looking-at "End ")
- (insert "To: " digest-name "\n\n")
- (narrow-to-region (point)
- (progn (search-forward "\n\n"
- nil 'move)
- (point))))
- (if (mail-fetch-field "To")
- nil
- (goto-char (point-min))
- (insert "To: " digest-name "\n")))
- ;; Digestifiers may insert `- ' on lines that start with `-'.
- ;; Undo that.
- (save-excursion
- (goto-char (point-min))
- (if (re-search-forward
- "\n\n----------------------------*\n*"
- nil t)
- (let ((end (point-marker)))
- (goto-char (point-min))
- (while (re-search-forward "^- " end t)
- (delete-char -2)))))
- )))
- (setq error nil)
- (message "Message successfully undigestified")
- (let ((n rmail-current-message))
- (rmail-forget-messages)
- (rmail-show-message n)
- (rmail-delete-forward)
- (if (rmail-summary-exists)
- (rmail-select-summary
- (rmail-update-summary)))))
- (cond (error
- (narrow-to-region (point-min) (1+ (point-max)))
- (delete-region (point-min) (point-max))
- (rmail-show-message rmail-current-message))))))
-
-;;;###autoload
-(defun unforward-rmail-message ()
- "Extract a forwarded message from the containing message.
-This puts the forwarded message into a separate rmail message
-following the containing message."
- (interactive)
- ;; Don't use save-excursion because we don't want to restore point
- ;; in the case where we do not switch buffers.
- (let ((obuf (current-buffer)))
- (unwind-protect
- (progn
- ;; If we are in a summary buffer, switch to the Rmail buffer.
- (if (local-variable-p 'rmail-buffer)
- (set-buffer rmail-buffer))
- (narrow-to-region (rmail-msgbeg rmail-current-message)
- (rmail-msgend rmail-current-message))
- (goto-char (point-min))
- (let (beg end (buffer-read-only nil) msg-string who-forwarded-it)
- (setq who-forwarded-it (mail-fetch-field "From"))
- (if (re-search-forward "^----" nil t)
- nil
- (error "No forwarded message"))
- (forward-line 1)
- (setq beg (point))
- (if (re-search-forward "^----" nil t)
- (setq end (match-beginning 0))
- (error "No terminator for forwarded message"))
- (widen)
- (setq msg-string (buffer-substring beg end))
- (goto-char (rmail-msgend rmail-current-message))
- (narrow-to-region (point) (point))
- (insert "\^_\^L\n0, unseen,,\n*** EOOH ***\n")
- (narrow-to-region (point) (point))
- (insert "Forwarded-by: " who-forwarded-it "\n")
- (insert msg-string)
- (goto-char (point-min))
- (while (not (eobp))
- (if (looking-at "- ")
- (delete-region (point) (+ 2 (point))))
- (forward-line 1))
- (let ((n rmail-current-message))
- (rmail-forget-messages)
- (rmail-show-message n)
- (if (rmail-summary-exists)
- (rmail-select-summary
- (rmail-update-summary))))))
- (set-buffer obuf))))
-
-;;; undigest.el ends here
diff --git a/lisp/mail/unrmail.el b/lisp/mail/unrmail.el
deleted file mode 100644
index 05fe04899af..00000000000
--- a/lisp/mail/unrmail.el
+++ /dev/null
@@ -1,66 +0,0 @@
-;;; unrmail.el --- convert Rmail files to mailbox files.
-
-;;; Copyright (C) 1992 Free Software Foundation, Inc.
-
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(defvar command-line-args-left) ;Avoid 'free variable' warning
-
-;;;###autoload
-(defun batch-unrmail ()
- "Convert Rmail files to system inbox format.
-Specify the input Rmail file names as command line arguments.
-For each Rmail file, the corresponding output file name
-is made by adding `.mail' at the end.
-For example, invoke `emacs -batch -f batch-unrmail RMAIL'."
- ;; command-line-args-left is what is left of the command line (from startup.el)
- (if (not noninteractive)
- (error "`batch-unrmail' is to be used only with -batch"))
- (let ((error nil))
- (while command-line-args-left
- (or (unrmail (car command-line-args-left)
- (concat (car command-line-args-left) ".mail"))
- (setq error t))
- (setq command-line-args-left (cdr command-line-args-left)))
- (message "Done")
- (kill-emacs (if error 1 0))))
-
-;;;###autoload
-(defun unrmail (file to-file)
- "Convert Rmail file FILE to system inbox format file TO-FILE."
- (interactive "fUnrmail (rmail file): \nFUnrmail into (new mailbox file): ")
- (let ((message-count 0)
- ;; Prevent rmail from making, or switching to, a summary buffer.
- (rmail-display-summary nil)
- (rmail-delete-after-output nil))
- (rmail file)
- ;; Default the directory of TO-FILE based on where FILE is.
- (setq to-file (expand-file-name to-file default-directory))
- (message "Writing messages to %s..." to-file)
- (while (< message-count rmail-total-messages)
- (rmail-show-message
- (setq message-count (1+ message-count)))
- (rmail-toggle-header)
- (rmail-output to-file 1 t))
- (message "Writing messages to %s...done" to-file)))
-
-;;; unrmail.el ends here
diff --git a/lisp/mail/vms-pmail.el b/lisp/mail/vms-pmail.el
deleted file mode 100644
index 3dd2d664e76..00000000000
--- a/lisp/mail/vms-pmail.el
+++ /dev/null
@@ -1,117 +0,0 @@
-;;; vms-pmail.el --- use Emacs as the editor within VMS mail.
-
-;; Copyright (C) 1992 Free Software Foundation, Inc.
-
-;; Author: Roland B Roberts <roberts@nsrl31.nsrl.rochester.edu>
-;; Keywords: vms
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;;;
-;;; Quick hack to use emacs as mail editor. There are a *bunch* of
-;;; changes scattered throughout emacs to make this work, namely:
-;;; (1) mod to sysdep.c to allow emacs to attach to a process other
-;;; than the one that originally spawned it.
-;;; (2) mod to kepteditor.com to define the logical emacs_parent_pid
-;;; which is what sysdep.c looks for, and define the logical
-;;; emacs_command_args which contains the command line
-;;; (3) mod to re-parse command line arguments from emacs_command_args
-;;; then execute them as though emacs were just starting up.
-;;;
-(defun vms-pmail-save-and-exit ()
- "Save current buffer and exit emacs.
-If this emacs cannot be suspended, you will be prompted about modified
-buffers other than the mail buffer. BEWARE --- suspending emacs without
-saving your mail buffer causes mail to abort the send (potentially useful
-since the mail buffer is still here)."
- (interactive)
- (basic-save-buffer)
- (if (vms-system-info "LOGICAL" "DONT_SUSPEND_EMACS")
- (progn
- (save-some-buffers)
- (kill-emacs 1))
- (kill-buffer (current-buffer))
- (suspend-emacs)))
-
-(defun vms-pmail-abort ()
- "Mark buffer as unmodified and exit emacs.
-When the editor is exited without saving its buffer, VMS mail does not
-send a message. If you have other modified buffers you will be
-prompted for what to do with them."
- (interactive)
- (if (not (yes-or-no-p "Really abort mail? "))
- (ding)
- (not-modified)
- (if (vms-system-info "LOGICAL" "DONT_SUSPEND_EMACS")
- (progn
- (save-some-buffers)
- (kill-emacs 1))
- (kill-buffer (current-buffer))
- (suspend-emacs))))
-
-(defun vms-pmail-setup ()
- "Set up file assuming use by VMS MAIL utility.
-The buffer is put into text-mode, auto-save is turned off and the
-following bindings are established.
-
-\\[vms-pmail-save-and-exit] vms-pmail-save-and-exit
-\\[vms-pmail-abort] vms-pmail-abort
-
-All other emacs commands are still available."
- (interactive)
- (auto-save-mode -1)
- (text-mode)
- (let ((default (vms-system-info "LOGICAL" "SYS$SCRATCH"))
- (directory (file-name-directory (buffer-file-name)))
- (filename (file-name-nondirectory (buffer-file-name))))
- (if (string= directory "SYS$SCRATCH:")
- (progn
- (cd default)
- (setq buffer-file-name (concat default filename))))
- (use-local-map (copy-keymap (current-local-map)))
- (local-set-key "\C-c\C-c" 'vms-pmail-save-and-exit)
- (local-set-key "\C-c\C-g" 'vms-pmail-abort)))
-
-(defun indicate-mail-reply-text ()
- "Prepares received mail for re-sending by placing >'s on each line."
- (interactive)
- (goto-char (point-min))
- (while (not (eobp))
- (insert ">")
- (beginning-of-line)
- (forward-line 1))
- (set-buffer-modified-p nil)
- (goto-char (point-min)))
-
-(defun insert-signature ()
- "Moves to the end of the buffer and inserts a \"signature\" file.
-First try the file indicated by environment variable MAIL$TRAILER.
-If that fails, try the file \"~/.signature\".
-If neither file exists, fails quietly."
- (interactive)
- (end-of-buffer)
- (newline)
- (if (vms-system-info "LOGICAL" "MAIL$TRAILER")
- (if (file-attributes (vms-system-info "LOGICAL" "MAIL$TRAILER"))
- (insert-file-contents (vms-system-info "LOGICAL" "MAIL$TRAILER"))
- (if (file-attributes "~/.signature")
- (insert-file-contents "~/.signature")))))
-
-;;; vms-pmail.el ends here
diff --git a/lisp/makefile.nt b/lisp/makefile.nt
deleted file mode 100644
index 67699fecf3f..00000000000
--- a/lisp/makefile.nt
+++ /dev/null
@@ -1,42 +0,0 @@
-# Hacked up Nmake makefile for GNU Emacs
-# Geoff Voelker (voelker@cs.washington.edu)
-# Copyright (c) 1994 Free Software Foundation, Inc.
-#
-# This file is part of GNU Emacs.
-#
-# GNU Emacs is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# GNU Emacs is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Emacs; see the file COPYING. If not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-
-!include ..\nt\makefile.def
-
-all:
-
-#
-# Assuming INSTALL_DIR is defined, copy the elisp files to it
-#
-install:; - mkdir $(INSTALL_DIR)\lisp
- - $(DEL) .\same-dir.tst
- - $(DEL) $(INSTALL_DIR)\lisp\same-dir.tst
- echo SameDirTest > $(INSTALL_DIR)\lisp\same-dir.tst
- if not exist .\same-dir.tst $(CP_DIR) . $(INSTALL_DIR)\lisp
- - $(DEL) $(INSTALL_DIR)\lisp\same-dir.tst
-
-
-#
-# Maintenance
-#
-clean:; - $(DEL) *~
- - $(DEL_TREE) deleted
diff --git a/lisp/makesum.el b/lisp/makesum.el
deleted file mode 100644
index 9664513e004..00000000000
--- a/lisp/makesum.el
+++ /dev/null
@@ -1,114 +0,0 @@
-;;; makesum.el --- generate key binding summary for Emacs
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: help
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Displays a nice human-readable summary of all keybindings in a
-;; two-column format.
-
-;;; Code:
-
-;;;###autoload
-(defun make-command-summary ()
- "Make a summary of current key bindings in the buffer *Summary*.
-Previous contents of that buffer are killed first."
- (interactive)
- (message "Making command summary...")
- ;; This puts a description of bindings in a buffer called *Help*.
- (save-window-excursion
- (describe-bindings))
- (with-output-to-temp-buffer "*Summary*"
- (save-excursion
- (let ((cur-mode mode-name))
- (set-buffer standard-output)
- (erase-buffer)
- (insert-buffer-substring "*Help*")
- (goto-char (point-min))
- (delete-region (point) (progn (forward-line 1) (point)))
- (while (search-forward " " nil t)
- (replace-match " "))
- (goto-char (point-min))
- (while (search-forward "-@ " nil t)
- (replace-match "-SP"))
- (goto-char (point-min))
- (while (search-forward " .. ~ " nil t)
- (replace-match "SP .. ~"))
- (goto-char (point-min))
- (while (search-forward "C-?" nil t)
- (replace-match "DEL"))
- (goto-char (point-min))
- (while (search-forward "C-i" nil t)
- (replace-match "TAB"))
- (goto-char (point-min))
- (if (re-search-forward "^Local Bindings:" nil t)
- (progn
- (forward-char -1)
- (insert " for " cur-mode " Mode")
- (while (search-forward "??\n" nil t)
- (delete-region (point)
- (progn
- (forward-line -1)
- (point))))))
- (goto-char (point-min))
- (insert "Emacs command summary, " (substring (current-time-string) 0 10)
- ".\n")
- ;; Delete "key binding" and underlining of dashes.
- (delete-region (point) (progn (forward-line 2) (point)))
- (forward-line 1) ;Skip blank line
- (while (not (eobp))
- (let ((beg (point)))
- (or (re-search-forward "^$" nil t)
- (goto-char (point-max)))
- (double-column beg (point))
- (forward-line 1)))
- (goto-char (point-min)))))
- (message "Making command summary...done"))
-
-(defun double-column (start end)
- (interactive "r")
- (let (half cnt
- line lines nlines
- (from-end (- (point-max) end)))
- (setq nlines (count-lines start end))
- (if (<= nlines 1)
- nil
- (setq half (/ (1+ nlines) 2))
- (goto-char start)
- (save-excursion
- (forward-line half)
- (while (< half nlines)
- (setq half (1+ half))
- (setq line (buffer-substring (point) (save-excursion (end-of-line) (point))))
- (setq lines (cons line lines))
- (delete-region (point) (progn (forward-line 1) (point)))))
- (setq lines (nreverse lines))
- (while lines
- (end-of-line)
- (indent-to 41)
- (insert (car lines))
- (forward-line 1)
- (setq lines (cdr lines))))
- (goto-char (- (point-max) from-end))))
-
-;;; makesum.el ends here
diff --git a/lisp/man.el b/lisp/man.el
deleted file mode 100644
index ac535f0deca..00000000000
--- a/lisp/man.el
+++ /dev/null
@@ -1,1062 +0,0 @@
-;;; man.el --- browse UNIX manual pages
-
-;; Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
-
-;; Author: Barry A. Warsaw <bwarsaw@cen.com>
-;; Keywords: help
-;; Adapted-By: ESR, pot
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This code provides a function, `man', with which you can browse
-;; UNIX manual pages. Formatting is done in background so that you
-;; can continue to use your Emacs while processing is going on.
-;;
-;; The mode also supports hypertext-like following of manual page SEE
-;; ALSO references, and other features. See below or do `?' in a
-;; manual page buffer for details.
-
-;; ========== Credits and History ==========
-;; In mid 1991, several people posted some interesting improvements to
-;; man.el from the standard emacs 18.57 distribution. I liked many of
-;; these, but wanted everything in one single package, so I decided
-;; to incorporate them into a single manual browsing mode. While
-;; much of the code here has been rewritten, and some features added,
-;; these folks deserve lots of credit for providing the initial
-;; excellent packages on which this one is based.
-
-;; Nick Duffek <duffek@chaos.cs.brandeis.edu>, posted a very nice
-;; improvement which retrieved and cleaned the manpages in a
-;; background process, and which correctly deciphered such options as
-;; man -k.
-
-;; Eric Rose <erose@jessica.stanford.edu>, submitted manual.el which
-;; provided a very nice manual browsing mode.
-
-;; This package was available as `superman.el' from the LCD package
-;; for some time before it was accepted into Emacs 19. The entry
-;; point and some other names have been changed to make it a drop-in
-;; replacement for the old man.el package.
-
-;; Francesco Potorti` <pot@cnuce.cnr.it> cleaned it up thoroughly,
-;; making it faster, more robust and more tolerant of different
-;; systems' man idiosyncrasies.
-
-;; ========== Features ==========
-;; + Runs "man" in the background and pipes the results through a
-;; series of sed and awk scripts so that all retrieving and cleaning
-;; is done in the background. The cleaning commands are configurable.
-;; + Syntax is the same as Un*x man
-;; + Functionality is the same as Un*x man, including "man -k" and
-;; "man <section>", etc.
-;; + Provides a manual browsing mode with keybindings for traversing
-;; the sections of a manpage, following references in the SEE ALSO
-;; section, and more.
-;; + Multiple manpages created with the same man command are put into
-;; a narrowed buffer circular list.
-
-;; ============= TODO ===========
-;; - Add a command for printing.
-;; - The awk script deletes multiple blank lines. This behaviour does
-;; not allow to understand if there was indeed a blank line at the
-;; end or beginning of a page (after the header, or before the
-;; footer). A different algorithm should be used. It is easy to
-;; compute how many blank lines there are before and after the page
-;; headers, and after the page footer. But it is possible to compute
-;; the number of blank lines before the page footer by euristhics
-;; only. Is it worth doing?
-;; - Allow a user option to mean that all the manpages should go in
-;; the same buffer, where they can be browsed with M-n and M-p.
-;; - Allow completion on the manpage name when calling man. This
-;; requires a reliable list of places where manpages can be found. The
-;; drawback would be that if the list is not complete, the user might
-;; be led to believe that the manpages in the missing directories do
-;; not exist.
-
-
-;;; Code:
-
-(require 'assoc)
-
-;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-;; empty defvars (keep the compiler quiet)
-
-(defvar Man-notify)
-(defvar Man-current-page)
-(defvar Man-page-list)
-(defvar Man-filter-list nil
- "*Manpage cleaning filter command phrases.
-This variable contains a list of the following form:
-
-'((command-string phrase-string*)*)
-
-Each phrase-string is concatenated onto the command-string to form a
-command filter. The (standard) output (and standard error) of the Un*x
-man command is piped through each command filter in the order the
-commands appear in the association list. The final output is placed in
-the manpage buffer.")
-
-(defvar Man-original-frame)
-(defvar Man-arguments)
-(defvar Man-sections-alist)
-(defvar Man-refpages-alist)
-(defvar Man-uses-untabify-flag t
- "When non-nil use `untabify' instead of Man-untabify-command.")
-(defvar Man-page-mode-string)
-(defvar Man-sed-script nil
- "Script for sed to nuke backspaces and ANSI codes from manpages.")
-
-;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-;; user variables
-
-(defvar Man-fontify-manpage-flag t
- "*Make up the manpage with fonts.")
-
-(defvar Man-overstrike-face 'bold
- "*Face to use when fontifying overstrike.")
-
-(defvar Man-underline-face 'underline
- "*Face to use when fontifying underlining.")
-
-;; Use the value of the obsolete user option Man-notify, if set.
-(defvar Man-notify-method (if (boundp 'Man-notify) Man-notify 'friendly)
- "*Selects the behavior when manpage is ready.
-This variable may have one of the following values, where (sf) means
-that the frames are switched, so the manpage is displayed in the frame
-where the man command was called from:
-
-newframe -- put the manpage in its own frame (see `Man-frame-parameters')
-pushy -- make the manpage the current buffer in the current window
-bully -- make the manpage the current buffer and only window (sf)
-aggressive -- make the manpage the current buffer in the other window (sf)
-friendly -- display manpage in the other window but don't make current (sf)
-polite -- don't display manpage, but prints message and beep when ready
-quiet -- like `polite', but don't beep
-meek -- make no indication that the manpage is ready
-
-Any other value of `Man-notify-method' is equivalent to `meek'.")
-
-(defvar Man-frame-parameters nil
- "*Frame parameter list for creating a new frame for a manual page.")
-
-(defvar Man-downcase-section-letters-flag t
- "*Letters in sections are converted to lower case.
-Some Un*x man commands can't handle uppercase letters in sections, for
-example \"man 2V chmod\", but they are often displayed in the manpage
-with the upper case letter. When this variable is t, the section
-letter (e.g., \"2V\") is converted to lowercase (e.g., \"2v\") before
-being sent to the man background process.")
-
-(defvar Man-circular-pages-flag t
- "*If t, the manpage list is treated as circular for traversal.")
-
-(defvar Man-section-translations-alist
- (list
- '("3C++" . "3")
- ;; Some systems have a real 3x man section, so let's comment this.
- ;; '("3X" . "3") ; Xlib man pages
- '("3X11" . "3")
- '("1-UCB" . ""))
- "*Association list of bogus sections to real section numbers.
-Some manpages (e.g. the Sun C++ 2.1 manpages) have section numbers in
-their references which Un*x `man' does not recognize. This
-association list is used to translate those sections, when found, to
-the associated section number.")
-
-(defvar manual-program "man"
- "The name of the program that produces man pages.")
-
-(defvar Man-untabify-command "pr"
- "Command used for untabifying.")
-
-(defvar Man-untabify-command-args (list "-t" "-e")
- "List of arguments to be passed to Man-untabify-command (which see).")
-
-(defvar Man-sed-command "sed"
- "Command used for processing sed scripts.")
-
-(defvar Man-awk-command "awk"
- "Command used for processing awk scripts.")
-
-(defvar Man-mode-line-format
- '("" mode-line-modified
- mode-line-buffer-identification " "
- global-mode-string
- " " Man-page-mode-string
- " %[(" mode-name mode-line-process minor-mode-alist ")%]----"
- (-3 . "%p") "-%-")
- "Mode line format for manual mode buffer.")
-
-(defvar Man-mode-map nil
- "Keymap for Man mode.")
-
-(defvar Man-mode-hook nil
- "Hook run when Man mode is enabled.")
-
-(defvar Man-cooked-hook nil
- "Hook run after removing backspaces but before Man-mode processing.")
-
-(defvar Man-name-regexp "[-a-zA-Z0-9_][-a-zA-Z0-9_.]*"
- "Regular expression describing the name of a manpage (without section).")
-
-(defvar Man-section-regexp "[0-9][a-zA-Z+]*\\|[LNln]"
- "Regular expression describing a manpage section within parentheses.")
-
-(defvar Man-page-header-regexp
- (concat "^[ \t]*\\(" Man-name-regexp
- "(\\(" Man-section-regexp "\\))\\).*\\1")
- "Regular expression describing the heading of a page.")
-
-(defvar Man-heading-regexp "^\\([A-Z][A-Z ]+\\)$"
- "Regular expression describing a manpage heading entry.")
-
-(defvar Man-see-also-regexp "SEE ALSO"
- "Regular expression for SEE ALSO heading (or your equivalent).
-This regexp should not start with a `^' character.")
-
-(defvar Man-first-heading-regexp "^[ \t]*NAME$\\|^[ \t]*No manual entry fo.*$"
- "Regular expression describing first heading on a manpage.
-This regular expression should start with a `^' character.")
-
-(defvar Man-reference-regexp
- (concat "\\(" Man-name-regexp "\\)(\\(" Man-section-regexp "\\))")
- "Regular expression describing a reference in the SEE ALSO section.")
-
-(defvar Man-switches ""
- "Switches passed to the man command, as a single string.")
-
-(defvar Man-specified-section-option
- (if (string-match "-solaris[0-9.]*$" system-configuration)
- "-s"
- "")
- "Option that indicates a specified a manual section name.")
-
-;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-;; end user variables
-
-;; other variables and keymap initializations
-(make-variable-buffer-local 'Man-sections-alist)
-(make-variable-buffer-local 'Man-refpages-alist)
-(make-variable-buffer-local 'Man-page-list)
-(make-variable-buffer-local 'Man-current-page)
-(make-variable-buffer-local 'Man-page-mode-string)
-(make-variable-buffer-local 'Man-original-frame)
-(make-variable-buffer-local 'Man-arguments)
-
-(setq-default Man-sections-alist nil)
-(setq-default Man-refpages-alist nil)
-(setq-default Man-page-list nil)
-(setq-default Man-current-page 0)
-(setq-default Man-page-mode-string "1 of 1")
-
-(defconst Man-sysv-sed-script "\
-/\b/ { s/_\b//g
- s/\b_//g
- s/o\b+/o/g
- s/+\bo/o/g
- :ovstrk
- s/\\(.\\)\b\\1/\\1/g
- t ovstrk
- }
-/\e\\[[0-9][0-9]*m/ s///g"
- "Script for sysV-like sed to nuke backspaces and ANSI codes from manpages.")
-
-(defconst Man-berkeley-sed-script "\
-/\b/ { s/_\b//g\\
- s/\b_//g\\
- s/o\b+/o/g\\
- s/+\bo/o/g\\
- :ovstrk\\
- s/\\(.\\)\b\\1/\\1/g\\
- t ovstrk\\
- }\\
-/\e\\[[0-9][0-9]*m/ s///g"
- "Script for berkeley-like sed to nuke backspaces and ANSI codes from manpages.")
-
-(if Man-mode-map
- nil
- (setq Man-mode-map (make-keymap))
- (suppress-keymap Man-mode-map)
- (define-key Man-mode-map " " 'scroll-up)
- (define-key Man-mode-map "\177" 'scroll-down)
- (define-key Man-mode-map "n" 'Man-next-section)
- (define-key Man-mode-map "p" 'Man-previous-section)
- (define-key Man-mode-map "\en" 'Man-next-manpage)
- (define-key Man-mode-map "\ep" 'Man-previous-manpage)
- (define-key Man-mode-map ">" 'end-of-buffer)
- (define-key Man-mode-map "<" 'beginning-of-buffer)
- (define-key Man-mode-map "." 'beginning-of-buffer)
- (define-key Man-mode-map "r" 'Man-follow-manual-reference)
- (define-key Man-mode-map "g" 'Man-goto-section)
- (define-key Man-mode-map "s" 'Man-goto-see-also-section)
- (define-key Man-mode-map "k" 'Man-kill)
- (define-key Man-mode-map "q" 'Man-quit)
- (define-key Man-mode-map "m" 'man)
- (define-key Man-mode-map "?" 'describe-mode)
- )
-
-
-;; ======================================================================
-;; utilities
-
-(defun Man-init-defvars ()
- "Used for initialising variables based on the value of window-system.
-This is necessary if one wants to dump man.el with emacs."
-
- ;; The following is necessary until fonts are implemented on
- ;; terminals.
- (setq Man-fontify-manpage-flag (and Man-fontify-manpage-flag
- window-system))
-
- (setq Man-sed-script
- (cond
- (Man-fontify-manpage-flag
- nil)
- ((= 0 (call-process Man-sed-command nil nil nil Man-sysv-sed-script))
- Man-sysv-sed-script)
- ((= 0 (call-process Man-sed-command nil nil nil Man-berkeley-sed-script))
- Man-berkeley-sed-script)
- (t
- nil)))
-
- (setq Man-filter-list
- (list
- (cons
- Man-sed-command
- (list
- (if Man-sed-script
- (concat "-e '" Man-sed-script "'")
- "")
- "-e '/^[\001-\032][\001-\032]*$/d'"
- "-e '/\e[789]/s///g'"
- "-e '/Reformatting page. Wait/d'"
- "-e '/Reformatting entry. Wait/d'"
- "-e '/^[ \t]*Hewlett-Packard[ \t]Company[ \t]*-[ \t][0-9]*[ \t]-/d'"
- "-e '/^[ \t]*Hewlett-Packard[ \t]*-[ \t][0-9]*[ \t]-.*$/d'"
- "-e '/^[ \t][ \t]*-[ \t][0-9]*[ \t]-[ \t]*Formatted:.*[0-9]$/d'"
- "-e '/^[ \t]*Page[ \t][0-9]*.*(printed[ \t][0-9\\/]*)$/d'"
- "-e '/^Printed[ \t][0-9].*[0-9]$/d'"
- "-e '/^[ \t]*X[ \t]Version[ \t]1[01].*Release[ \t][0-9]/d'"
- "-e '/^[A-za-z].*Last[ \t]change:/d'"
- "-e '/^Sun[ \t]Release[ \t][0-9].*[0-9]$/d'"
- "-e '/[ \t]*Copyright [0-9]* UNIX System Laboratories, Inc.$/d'"
- "-e '/^[ \t]*Rev\\..*Page [0-9][0-9]*$/d'"
- ))
- (cons
- Man-awk-command
- (list
- "'\n"
- "BEGIN { blankline=0; anonblank=0; }\n"
- "/^$/ { if (anonblank==0) next; }\n"
- "{ anonblank=1; }\n"
- "/^$/ { blankline++; next; }\n"
- "{ if (blankline>0) { print \"\"; blankline=0; } print $0; }\n"
- "'"
- ))
- (if (not Man-uses-untabify-flag)
- (cons
- Man-untabify-command
- Man-untabify-command-args)
- )))
-)
-
-(defsubst Man-match-substring (&optional n string)
- "Return the substring matched by the last search.
-Optional arg N means return the substring matched by the Nth paren
-grouping. Optional second arg STRING means return a substring from
-that string instead of from the current buffer."
- (if (null n) (setq n 0))
- (if string
- (substring string (match-beginning n) (match-end n))
- (buffer-substring (match-beginning n) (match-end n))))
-
-(defsubst Man-make-page-mode-string ()
- "Formats part of the mode line for Man mode."
- (format "%s page %d of %d"
- (or (nth 2 (nth (1- Man-current-page) Man-page-list))
- "")
- Man-current-page
- (length Man-page-list)))
-
-(defsubst Man-build-man-command ()
- "Builds the entire background manpage and cleaning command."
- (let ((command (concat manual-program " " Man-switches " %s 2>/dev/null"))
- (flist Man-filter-list))
- (while (and flist (car flist))
- (let ((pcom (car (car flist)))
- (pargs (cdr (car flist))))
- (setq command
- (concat command " | " pcom " "
- (mapconcat '(lambda (phrase)
- (if (not (stringp phrase))
- (error "Malformed Man-filter-list"))
- phrase)
- pargs " ")))
- (setq flist (cdr flist))))
- command))
-
-(defun Man-translate-references (ref)
- "Translates REF from \"chmod(2V)\" to \"2v chmod\" style.
-Leave it as is if already in that style. Possibly downcase and
-translate the section (see the Man-downcase-section-letters-flag
-and the Man-section-translations-alist variables)."
- (let ((name "")
- (section "")
- (slist Man-section-translations-alist))
- (cond
- ;; "chmod(2V)" case ?
- ((string-match (concat "^" Man-reference-regexp "$") ref)
- (setq name (Man-match-substring 1 ref)
- section (Man-match-substring 2 ref)))
- ;; "2v chmod" case ?
- ((string-match (concat "^\\(" Man-section-regexp
- "\\) +\\(" Man-name-regexp "\\)$") ref)
- (setq name (Man-match-substring 2 ref)
- section (Man-match-substring 1 ref))))
- (if (string= name "")
- ref ; Return the reference as is
- (if Man-downcase-section-letters-flag
- (setq section (downcase section)))
- (while slist
- (let ((s1 (car (car slist)))
- (s2 (cdr (car slist))))
- (setq slist (cdr slist))
- (if Man-downcase-section-letters-flag
- (setq s1 (downcase s1)))
- (if (not (string= s1 section)) nil
- (setq section (if Man-downcase-section-letters-flag
- (downcase s2)
- s2)
- slist nil))))
- (concat Man-specified-section-option section " " name))))
-
-
-;; ======================================================================
-;; default man entry: get word under point
-
-(defsubst Man-default-man-entry ()
- "Make a guess at a default manual entry.
-This guess is based on the text surrounding the cursor, and the
-default section number is selected from `Man-auto-section-alist'."
- (let (default-title)
- (save-excursion
-
- ;; Default man entry title is any word the cursor is on, or if
- ;; cursor not on a word, then nearest preceding word. Cannot
- ;; use the current-word function because it skips the dots.
- (if (not (looking-at "[-a-zA-Z_.]"))
- (skip-chars-backward "^a-zA-Z"))
- (skip-chars-backward "-(a-zA-Z_0-9_.")
- (if (looking-at "(") (forward-char 1))
- (setq default-title
- (buffer-substring
- (point)
- (progn (skip-chars-forward "-a-zA-Z0-9_.") (point))))
-
- ;; If looking at something like ioctl(2) or brc(1M), include the
- ;; section number in the returned value. Remove text properties.
- (let ((result (concat
- default-title
- (if (looking-at
- (concat "[ \t]*([ \t]*\\("
- Man-section-regexp "\\)[ \t]*)"))
- (format "(%s)" (Man-match-substring 1))))))
- (set-text-properties 0 (length result) nil result)
- result))))
-
-
-;; ======================================================================
-;; Top level command and background process sentinel
-
-;; For compatibility with older versions.
-;;;###autoload
-(defalias 'manual-entry 'man)
-
-;;;###autoload
-(defun man (man-args)
- "Get a Un*x manual page and put it in a buffer.
-This command is the top-level command in the man package. It runs a Un*x
-command to retrieve and clean a manpage in the background and places the
-results in a Man mode (manpage browsing) buffer. See variable
-`Man-notify-method' for what happens when the buffer is ready.
-If a buffer already exists for this man page, it will display immediately."
- (interactive
- (list (let* ((default-entry (Man-default-man-entry))
- (input (read-string
- (format "Manual entry%s: "
- (if (string= default-entry "")
- ""
- (format " (default %s)" default-entry))))))
- (if (string= input "")
- (if (string= default-entry "")
- (error "No man args given")
- default-entry)
- input))))
-
- ;; Possibly translate the "subject(section)" syntax into the
- ;; "section subject" syntax and possibly downcase the section.
- (setq man-args (Man-translate-references man-args))
-
- (Man-getpage-in-background man-args))
-
-
-(defun Man-getpage-in-background (topic)
- "Uses TOPIC to build and fire off the manpage and cleaning command."
- (let* ((man-args topic)
- (bufname (concat "*Man " man-args "*"))
- (buffer (get-buffer bufname)))
- (if buffer
- (Man-notify-when-ready buffer)
- (require 'env)
- (message "Invoking %s %s in the background" manual-program man-args)
- (setq buffer (generate-new-buffer bufname))
- (save-excursion
- (set-buffer buffer)
- (setq Man-original-frame (selected-frame))
- (setq Man-arguments man-args))
- (let ((process-environment (copy-sequence process-environment)))
- ;; Prevent any attempt to use display terminal fanciness.
- (setenv "TERM" "dumb")
- (set-process-sentinel
- (start-process manual-program buffer "sh" "-c"
- (format (Man-build-man-command) man-args))
- 'Man-bgproc-sentinel)))))
-
-(defun Man-notify-when-ready (man-buffer)
- "Notify the user when MAN-BUFFER is ready.
-See the variable `Man-notify-method' for the different notification behaviors."
- (let ((saved-frame (save-excursion
- (set-buffer man-buffer)
- Man-original-frame)))
- (cond
- ((eq Man-notify-method 'newframe)
- ;; Since we run asynchronously, perhaps while Emacs is waiting
- ;; for input, we must not leave a different buffer current. We
- ;; can't rely on the editor command loop to reselect the
- ;; selected window's buffer.
- (save-excursion
- (set-buffer man-buffer)
- (make-frame Man-frame-parameters)))
- ((eq Man-notify-method 'pushy)
- (switch-to-buffer man-buffer))
- ((eq Man-notify-method 'bully)
- (and window-system
- (frame-live-p saved-frame)
- (select-frame saved-frame))
- (pop-to-buffer man-buffer)
- (delete-other-windows))
- ((eq Man-notify-method 'aggressive)
- (and window-system
- (frame-live-p saved-frame)
- (select-frame saved-frame))
- (pop-to-buffer man-buffer))
- ((eq Man-notify-method 'friendly)
- (and window-system
- (frame-live-p saved-frame)
- (select-frame saved-frame))
- (display-buffer man-buffer 'not-this-window))
- ((eq Man-notify-method 'polite)
- (beep)
- (message "Manual buffer %s is ready" (buffer-name man-buffer)))
- ((eq Man-notify-method 'quiet)
- (message "Manual buffer %s is ready" (buffer-name man-buffer)))
- ((or (eq Man-notify-method 'meek)
- t)
- (message ""))
- )))
-
-(defun Man-fontify-manpage ()
- "Convert overstriking and underlining to the correct fonts.
-Same for the ANSI bold and normal escape sequences."
- (interactive)
- (message "Please wait: making up the %s man page..." Man-arguments)
- (goto-char (point-min))
- (while (search-forward "\e[1m" nil t)
- (delete-backward-char 4)
- (put-text-property (point)
- (progn (if (search-forward "\e[0m" nil 'move)
- (delete-backward-char 4))
- (point))
- 'face Man-overstrike-face))
- (goto-char (point-min))
- (while (search-forward "_\b" nil t)
- (backward-delete-char 2)
- (put-text-property (point) (1+ (point)) 'face Man-underline-face))
- (goto-char (point-min))
- (while (search-forward "\b_" nil t)
- (backward-delete-char 2)
- (put-text-property (1- (point)) (point) 'face Man-underline-face))
- (goto-char (point-min))
- (while (re-search-forward "\\(.\\)\\(\b\\1\\)+" nil t)
- (replace-match "\\1")
- (put-text-property (1- (point)) (point) 'face Man-overstrike-face))
- (goto-char (point-min))
- (while (re-search-forward "o\b\\+\\|\\+\bo" nil t)
- (replace-match "o")
- (put-text-property (1- (point)) (point) 'face 'bold))
- (goto-char (point-min))
- (while (re-search-forward "[-|]\\(\b[-|]\\)+" nil t)
- (replace-match "+")
- (put-text-property (1- (point)) (point) 'face 'bold))
- ;; \255 is some kind of dash in Latin-1.
- (goto-char (point-min))
- (while (search-forward "\255" nil t) (replace-match "-"))
- (message "%s man page made up" Man-arguments))
-
-(defun Man-cleanup-manpage ()
- "Remove overstriking and underlining from the current buffer."
- (interactive)
- (message "Please wait: cleaning up the %s man page..."
- Man-arguments)
- (if (or (interactive-p) (not Man-sed-script))
- (progn
- (goto-char (point-min))
- (while (search-forward "_\b" nil t) (backward-delete-char 2))
- (goto-char (point-min))
- (while (search-forward "\b_" nil t) (backward-delete-char 2))
- (goto-char (point-min))
- (while (re-search-forward "\\(.\\)\\(\b\\1\\)+" nil t)
- (replace-match "\\1"))
- (goto-char (point-min))
- (while (re-search-forward "\e\\[[0-9]+m" nil t) (replace-match ""))
- (goto-char (point-min))
- (while (re-search-forward "o\b\\+\\|\\+\bo" nil t) (replace-match "o"))
- ))
- (goto-char (point-min))
- (while (re-search-forward "[-|]\\(\b[-|]\\)+" nil t) (replace-match "+"))
- ;; \255 is some kind of dash in Latin-1.
- (goto-char (point-min))
- (while (search-forward "\255" nil t) (replace-match "-"))
- (message "%s man page cleaned up" Man-arguments))
-
-(defun Man-bgproc-sentinel (process msg)
- "Manpage background process sentinel."
- (let ((Man-buffer (process-buffer process))
- (delete-buff nil)
- (err-mess nil))
-
- (if (null (buffer-name Man-buffer)) ;; deleted buffer
- (set-process-buffer process nil)
-
- (save-excursion
- (set-buffer Man-buffer)
- (let ((case-fold-search nil))
- (goto-char (point-min))
- (cond ((or (looking-at "No \\(manual \\)*entry for")
- (looking-at "[^\n]*: nothing appropriate$"))
- (setq err-mess (buffer-substring (point)
- (progn
- (end-of-line) (point)))
- delete-buff t))
- ((not (and (eq (process-status process) 'exit)
- (= (process-exit-status process) 0)))
- (setq err-mess
- (concat (buffer-name Man-buffer)
- ": process "
- (let ((eos (1- (length msg))))
- (if (= (aref msg eos) ?\n)
- (substring msg 0 eos) msg))))
- (goto-char (point-max))
- (insert (format "\nprocess %s" msg))
- )))
- (if delete-buff
- (kill-buffer Man-buffer)
- (if Man-fontify-manpage-flag
- (Man-fontify-manpage)
- (Man-cleanup-manpage))
- (run-hooks 'Man-cooked-hook)
- (Man-mode)
- (set-buffer-modified-p nil)
- )
- ;; Restore case-fold-search before calling
- ;; Man-notify-when-ready because it may switch buffers.
-
- (if (not delete-buff)
- (Man-notify-when-ready Man-buffer))
-
- (if err-mess
- (error err-mess))
- ))))
-
-
-;; ======================================================================
-;; set up manual mode in buffer and build alists
-
-(defun Man-mode ()
- "A mode for browsing Un*x manual pages.
-
-The following man commands are available in the buffer. Try
-\"\\[describe-key] <key> RET\" for more information:
-
-\\[man] Prompt to retrieve a new manpage.
-\\[Man-follow-manual-reference] Retrieve reference in SEE ALSO section.
-\\[Man-next-manpage] Jump to next manpage in circular list.
-\\[Man-previous-manpage] Jump to previous manpage in circular list.
-\\[Man-next-section] Jump to next manpage section.
-\\[Man-previous-section] Jump to previous manpage section.
-\\[Man-goto-section] Go to a manpage section.
-\\[Man-goto-see-also-section] Jumps to the SEE ALSO manpage section.
-\\[Man-quit] Deletes the manpage window, bury its buffer.
-\\[Man-kill] Deletes the manpage window, kill its buffer.
-\\[describe-mode] Prints this help text.
-
-The following variables may be of some use. Try
-\"\\[describe-variable] <variable-name> RET\" for more information:
-
-Man-notify-method What happens when manpage formatting is done.
-Man-downcase-section-letters-flag Force section letters to lower case.
-Man-circular-pages-flag Treat multiple manpage list as circular.
-Man-auto-section-alist List of major modes and their section numbers.
-Man-section-translations-alist List of section numbers and their Un*x equiv.
-Man-filter-list Background manpage filter command.
-Man-mode-line-format Mode line format for Man mode buffers.
-Man-mode-map Keymap bindings for Man mode buffers.
-Man-mode-hook Normal hook run on entry to Man mode.
-Man-section-regexp Regexp describing manpage section letters.
-Man-heading-regexp Regexp describing section headers.
-Man-see-also-regexp Regexp for SEE ALSO section (or your equiv).
-Man-first-heading-regexp Regexp for first heading on a manpage.
-Man-reference-regexp Regexp matching a references in SEE ALSO.
-Man-switches Background `man' command switches.
-
-The following key bindings are currently in effect in the buffer:
-\\{Man-mode-map}"
- (interactive)
- (setq major-mode 'Man-mode
- mode-name "Man"
- buffer-auto-save-file-name nil
- mode-line-format Man-mode-line-format
- truncate-lines t
- buffer-read-only t)
- (buffer-disable-undo (current-buffer))
- (auto-fill-mode -1)
- (use-local-map Man-mode-map)
- (Man-build-page-list)
- (Man-strip-page-headers)
- (Man-unindent)
- (Man-goto-page 1)
- (run-hooks 'Man-mode-hook))
-
-(defsubst Man-build-section-alist ()
- "Build the association list of manpage sections."
- (setq Man-sections-alist nil)
- (goto-char (point-min))
- (let ((case-fold-search nil))
- (while (re-search-forward Man-heading-regexp (point-max) t)
- (aput 'Man-sections-alist (Man-match-substring 1))
- (forward-line 1))))
-
-(defsubst Man-build-references-alist ()
- "Build the association list of references (in the SEE ALSO section)."
- (setq Man-refpages-alist nil)
- (save-excursion
- (if (Man-find-section Man-see-also-regexp)
- (let ((start (progn (forward-line 1) (point)))
- (end (progn
- (Man-next-section 1)
- (point)))
- hyphenated
- (runningpoint -1))
- (save-restriction
- (narrow-to-region start end)
- (goto-char (point-min))
- (back-to-indentation)
- (while (and (not (eobp)) (/= (point) runningpoint))
- (setq runningpoint (point))
- (if (re-search-forward Man-reference-regexp end t)
- (let* ((word (Man-match-substring 0))
- (len (1- (length word))))
- (if hyphenated
- (setq word (concat hyphenated word)
- hyphenated nil))
- (if (= (aref word len) ?-)
- (setq hyphenated (substring word 0 len))
- (aput 'Man-refpages-alist word))))
- (skip-chars-forward " \t\n,")))))))
-
-(defun Man-build-page-list ()
- "Build the list of separate manpages in the buffer."
- (setq Man-page-list nil)
- (let ((page-start (point-min))
- (page-end (point-max))
- (header ""))
- (goto-char page-start)
- ;; (switch-to-buffer (current-buffer))(debug)
- (while (not (eobp))
- (setq header
- (if (looking-at Man-page-header-regexp)
- (Man-match-substring 1)
- nil))
- ;; Go past both the current and the next Man-first-heading-regexp
- (if (re-search-forward Man-first-heading-regexp nil 'move 2)
- (let ((p (progn (beginning-of-line) (point))))
- ;; We assume that the page header is delimited by blank
- ;; lines and that it contains at most one blank line. So
- ;; if we back by three blank lines we will be sure to be
- ;; before the page header but not before the possible
- ;; previous page header.
- (search-backward "\n\n" nil t 3)
- (if (re-search-forward Man-page-header-regexp p 'move)
- (beginning-of-line))))
- (setq page-end (point))
- (setq Man-page-list (append Man-page-list
- (list (list (copy-marker page-start)
- (copy-marker page-end)
- header))))
- (setq page-start page-end)
- )))
-
-(defun Man-strip-page-headers ()
- "Strip all the page headers but the first from the manpage."
- (let ((buffer-read-only nil)
- (case-fold-search nil)
- (page-list Man-page-list)
- (page ())
- (header ""))
- (while page-list
- (setq page (car page-list))
- (and (nth 2 page)
- (goto-char (car page))
- (re-search-forward Man-first-heading-regexp nil t)
- (setq header (buffer-substring (car page) (match-beginning 0)))
- ;; Since the awk script collapses all successive blank
- ;; lines into one, and since we don't want to get rid of
- ;; the fast awk script, one must choose between adding
- ;; spare blank lines between pages when there were none and
- ;; deleting blank lines at page boundaries when there were
- ;; some. We choose the first, so we comment the following
- ;; line.
- ;; (setq header (concat "\n" header)))
- (while (search-forward header (nth 1 page) t)
- (replace-match "")))
- (setq page-list (cdr page-list)))))
-
-(defun Man-unindent ()
- "Delete the leading spaces that indent the manpage."
- (let ((buffer-read-only nil)
- (case-fold-search nil)
- (page-list Man-page-list))
- (while page-list
- (let ((page (car page-list))
- (indent "")
- (nindent 0))
- (narrow-to-region (car page) (car (cdr page)))
- (if Man-uses-untabify-flag
- (untabify (point-min) (point-max)))
- (if (catch 'unindent
- (goto-char (point-min))
- (if (not (re-search-forward Man-first-heading-regexp nil t))
- (throw 'unindent nil))
- (beginning-of-line)
- (setq indent (buffer-substring (point)
- (progn
- (skip-chars-forward " ")
- (point))))
- (setq nindent (length indent))
- (if (zerop nindent)
- (throw 'unindent nil))
- (setq indent (concat indent "\\|$"))
- (goto-char (point-min))
- (while (not (eobp))
- (if (looking-at indent)
- (forward-line 1)
- (throw 'unindent nil)))
- (goto-char (point-min)))
- (while (not (eobp))
- (or (eolp)
- (delete-char nindent))
- (forward-line 1)))
- (setq page-list (cdr page-list))
- ))))
-
-
-;; ======================================================================
-;; Man mode commands
-
-(defun Man-next-section (n)
- "Move point to Nth next section (default 1)."
- (interactive "p")
- (let ((case-fold-search nil))
- (if (looking-at Man-heading-regexp)
- (forward-line 1))
- (if (re-search-forward Man-heading-regexp (point-max) t n)
- (beginning-of-line)
- (goto-char (point-max)))))
-
-(defun Man-previous-section (n)
- "Move point to Nth previous section (default 1)."
- (interactive "p")
- (let ((case-fold-search nil))
- (if (looking-at Man-heading-regexp)
- (forward-line -1))
- (if (re-search-backward Man-heading-regexp (point-min) t n)
- (beginning-of-line)
- (goto-char (point-min)))))
-
-(defun Man-find-section (section)
- "Move point to SECTION if it exists, otherwise don't move point.
-Returns t if section is found, nil otherwise."
- (let ((curpos (point))
- (case-fold-search nil))
- (goto-char (point-min))
- (if (re-search-forward (concat "^" section) (point-max) t)
- (progn (beginning-of-line) t)
- (goto-char curpos)
- nil)
- ))
-
-(defun Man-goto-section ()
- "Query for section to move point to."
- (interactive)
- (aput 'Man-sections-alist
- (let* ((default (aheadsym Man-sections-alist))
- (completion-ignore-case t)
- chosen
- (prompt (concat "Go to section: (default " default ") ")))
- (setq chosen (completing-read prompt Man-sections-alist))
- (if (or (not chosen)
- (string= chosen ""))
- default
- chosen)))
- (Man-find-section (aheadsym Man-sections-alist)))
-
-(defun Man-goto-see-also-section ()
- "Move point the the \"SEE ALSO\" section.
-Actually the section moved to is described by `Man-see-also-regexp'."
- (interactive)
- (if (not (Man-find-section Man-see-also-regexp))
- (error (concat "No " Man-see-also-regexp
- " section found in the current manpage"))))
-
-(defun Man-follow-manual-reference (reference)
- "Get one of the manpages referred to in the \"SEE ALSO\" section.
-Specify which reference to use; default is based on word at point."
- (interactive
- (if (not Man-refpages-alist)
- (error "There are no references in the current man page")
- (list (let* ((default (or
- (car (all-completions
- (save-excursion
- (skip-syntax-backward "w()")
- (skip-chars-forward " \t")
- (let ((word (current-word)))
- ;; strip a trailing '-':
- (if (string-match "-$" word)
- (substring word 0
- (match-beginning 0))
- word)))
- Man-refpages-alist))
- (aheadsym Man-refpages-alist)))
- chosen
- (prompt (concat "Refer to: (default " default ") ")))
- (setq chosen (completing-read prompt Man-refpages-alist nil t))
- (if (or (not chosen)
- (string= chosen ""))
- default
- chosen)))))
- (if (not Man-refpages-alist)
- (error "Can't find any references in the current manpage")
- (aput 'Man-refpages-alist reference)
- (Man-getpage-in-background
- (Man-translate-references (aheadsym Man-refpages-alist)))))
-
-(defun Man-kill ()
- "Kill the buffer containing the manpage."
- (interactive)
- (let ((buff (current-buffer)))
- (delete-windows-on buff)
- (kill-buffer buff))
- (if (and window-system
- (or (eq Man-notify-method 'newframe)
- (and pop-up-frames
- (eq Man-notify-method 'bully))))
- (delete-frame)))
-
-(defun Man-quit ()
- "Bury the buffer containing the manpage."
- (interactive)
- (let ((buff (current-buffer)))
- (delete-windows-on buff)
- (bury-buffer buff))
- (if (and window-system
- (or (eq Man-notify-method 'newframe)
- (and pop-up-frames
- (eq Man-notify-method 'bully))))
- (delete-frame)))
-
-(defun Man-goto-page (page)
- "Go to the manual page on page PAGE."
- (interactive
- (if (not Man-page-list)
- (let ((args Man-arguments))
- (kill-buffer (current-buffer))
- (error "Can't find the %s manpage" args))
- (if (= (length Man-page-list) 1)
- (error "You're looking at the only manpage in the buffer")
- (list (read-minibuffer (format "Go to manpage [1-%d]: "
- (length Man-page-list)))))))
- (if (not Man-page-list)
- (let ((args Man-arguments))
- (kill-buffer (current-buffer))
- (error "Can't find the %s manpage" args)))
- (if (or (< page 1)
- (> page (length Man-page-list)))
- (error "No manpage %d found" page))
- (let* ((page-range (nth (1- page) Man-page-list))
- (page-start (car page-range))
- (page-end (car (cdr page-range))))
- (setq Man-current-page page
- Man-page-mode-string (Man-make-page-mode-string))
- (widen)
- (goto-char page-start)
- (narrow-to-region page-start page-end)
- (Man-build-section-alist)
- (Man-build-references-alist)
- (goto-char (point-min))))
-
-
-(defun Man-next-manpage ()
- "Find the next manpage entry in the buffer."
- (interactive)
- (if (= (length Man-page-list) 1)
- (error "This is the only manpage in the buffer"))
- (if (< Man-current-page (length Man-page-list))
- (Man-goto-page (1+ Man-current-page))
- (if Man-circular-pages-flag
- (Man-goto-page 1)
- (error "You're looking at the last manpage in the buffer"))))
-
-(defun Man-previous-manpage ()
- "Find the previous manpage entry in the buffer."
- (interactive)
- (if (= (length Man-page-list) 1)
- (error "This is the only manpage in the buffer"))
- (if (> Man-current-page 1)
- (Man-goto-page (1- Man-current-page))
- (if Man-circular-pages-flag
- (Man-goto-page (length Man-page-list))
- (error "You're looking at the first manpage in the buffer"))))
-
-;; Init the man package variables, if not already done.
-(Man-init-defvars)
-
-(provide 'man)
-
-;;; man.el ends here
diff --git a/lisp/map-ynp.el b/lisp/map-ynp.el
deleted file mode 100644
index bfe2ee7af4c..00000000000
--- a/lisp/map-ynp.el
+++ /dev/null
@@ -1,255 +0,0 @@
-;;; map-ynp.el --- General-purpose boolean question-asker.
-
-;; Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Roland McGrath <roland@gnu.ai.mit.edu>
-;; Keywords: lisp, extensions
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; map-y-or-n-p is a general-purpose question-asking function.
-;; It asks a series of y/n questions (a la y-or-n-p), and decides to
-;; applies an action to each element of a list based on the answer.
-;; The nice thing is that you also get some other possible answers
-;; to use, reminiscent of query-replace: ! to answer y to all remaining
-;; questions; ESC or q to answer n to all remaining questions; . to answer
-;; y once and then n for the remainder; and you can get help with C-h.
-
-;;; Code:
-
-(defun map-y-or-n-p (prompter actor list &optional help action-alist
- no-cursor-in-echo-area)
- "Ask a series of boolean questions.
-Takes args PROMPTER ACTOR LIST, and optional args HELP and ACTION-ALIST.
-
-LIST is a list of objects, or a function of no arguments to return the next
-object or nil.
-
-If PROMPTER is a string, the prompt is \(format PROMPTER OBJECT\). If not
-a string, PROMPTER is a function of one arg (an object from LIST), which
-returns a string to be used as the prompt for that object. If the return
-value is not a string, it may be nil to ignore the object or non-nil to act
-on the object without asking the user.
-
-ACTOR is a function of one arg (an object from LIST),
-which gets called with each object that the user answers `yes' for.
-
-If HELP is given, it is a list (OBJECT OBJECTS ACTION),
-where OBJECT is a string giving the singular noun for an elt of LIST;
-OBJECTS is the plural noun for elts of LIST, and ACTION is a transitive
-verb describing ACTOR. The default is \(\"object\" \"objects\" \"act on\"\).
-
-At the prompts, the user may enter y, Y, or SPC to act on that object;
-n, N, or DEL to skip that object; ! to act on all following objects;
-ESC or q to exit (skip all following objects); . (period) to act on the
-current object and then exit; or \\[help-command] to get help.
-
-If ACTION-ALIST is given, it is an alist (KEY FUNCTION HELP) of extra keys
-that will be accepted. KEY is a character; FUNCTION is a function of one
-arg (an object from LIST); HELP is a string. When the user hits KEY,
-FUNCTION is called. If it returns non-nil, the object is considered
-\"acted upon\", and the next object from LIST is processed. If it returns
-nil, the prompt is repeated for the same object.
-
-Final optional argument NO-CURSOR-IN-ECHO-AREA non-nil says not to set
-`cursor-in-echo-area' while prompting.
-
-This function uses `query-replace-map' to define the standard responses,
-but not all of the responses which `query-replace' understands
-are meaningful here.
-
-Returns the number of actions taken."
- (let* ((actions 0)
- user-keys mouse-event map prompt char elt tail def
- ;; Non-nil means we should use mouse menus to ask.
- use-menus
- delayed-switch-frame
- (next (if (or (and list (symbolp list))
- (subrp list)
- (byte-code-function-p list)
- (and (consp list)
- (eq (car list) 'lambda)))
- (function (lambda ()
- (setq elt (funcall list))))
- (function (lambda ()
- (if list
- (progn
- (setq elt (car list)
- list (cdr list))
- t)
- nil))))))
- (if (listp last-nonmenu-event)
- ;; Make a list describing a dialog box.
- (let ((object (capitalize (nth 0 help)))
- (objects (capitalize (nth 1 help)))
- (action (capitalize (nth 2 help))))
- (setq map (` (("Yes" . act) ("No" . skip) ("Quit" . exit)
- ((, (if help (concat action " " object " And Quit")
- "Do it and Quit")) . act-and-exit)
- ((, (if help (concat action " All " objects)
- "Do All")) . automatic)
- (,@ (mapcar (lambda (elt)
- (cons (capitalize (nth 2 elt))
- (vector (nth 1 elt))))
- action-alist))))
- use-menus t
- mouse-event last-nonmenu-event))
- (setq user-keys (if action-alist
- (concat (mapconcat (function
- (lambda (elt)
- (key-description
- (char-to-string (car elt)))))
- action-alist ", ")
- " ")
- "")
- ;; Make a map that defines each user key as a vector containing
- ;; its definition.
- map (cons 'keymap
- (append (mapcar (lambda (elt)
- (cons (car elt) (vector (nth 1 elt))))
- action-alist)
- query-replace-map))))
- (unwind-protect
- (progn
- (if (stringp prompter)
- (setq prompter (` (lambda (object)
- (format (, prompter) object)))))
- (while (funcall next)
- (setq prompt (funcall prompter elt))
- (cond ((stringp prompt)
- ;; Prompt the user about this object.
- (setq quit-flag nil)
- (if use-menus
- (setq def (or (x-popup-dialog (or mouse-event use-menus)
- (cons prompt map))
- 'quit))
- ;; Prompt in the echo area.
- (let ((cursor-in-echo-area (not no-cursor-in-echo-area))
- (message-log-max nil))
- (message "%s(y, n, !, ., q, %sor %s) "
- prompt user-keys
- (key-description (vector help-char)))
- (if minibuffer-auto-raise
- (raise-frame (window-frame (minibuffer-window))))
- (setq char (read-event))
- ;; Show the answer to the question.
- (message "%s(y, n, !, ., q, %sor %s) %s"
- prompt user-keys
- (key-description (vector help-char))
- (single-key-description char)))
- (setq def (lookup-key map (vector char))))
- (cond ((eq def 'exit)
- (setq next (function (lambda () nil))))
- ((eq def 'act)
- ;; Act on the object.
- (funcall actor elt)
- (setq actions (1+ actions)))
- ((eq def 'skip)
- ;; Skip the object.
- )
- ((eq def 'act-and-exit)
- ;; Act on the object and then exit.
- (funcall actor elt)
- (setq actions (1+ actions)
- next (function (lambda () nil))))
- ((or (eq def 'quit) (eq def 'exit-prefix))
- (setq quit-flag t)
- (setq next (` (lambda ()
- (setq next '(, next))
- '(, elt)))))
- ((eq def 'automatic)
- ;; Act on this and all following objects.
- (if (funcall prompter elt)
- (progn
- (funcall actor elt)
- (setq actions (1+ actions))))
- (while (funcall next)
- (if (funcall prompter elt)
- (progn
- (funcall actor elt)
- (setq actions (1+ actions))))))
- ((eq def 'help)
- (with-output-to-temp-buffer "*Help*"
- (princ
- (let ((object (if help (nth 0 help) "object"))
- (objects (if help (nth 1 help) "objects"))
- (action (if help (nth 2 help) "act on")))
- (concat
- (format "Type SPC or `y' to %s the current %s;
-DEL or `n' to skip the current %s;
-! to %s all remaining %s;
-ESC or `q' to exit;\n"
- action object object action objects)
- (mapconcat (function
- (lambda (elt)
- (format "%c to %s"
- (nth 0 elt)
- (nth 2 elt))))
- action-alist
- ";\n")
- (if action-alist ";\n")
- (format "or . (period) to %s \
-the current %s and exit."
- action object))))
- (save-excursion
- (set-buffer standard-output)
- (help-mode)))
-
- (setq next (` (lambda ()
- (setq next '(, next))
- '(, elt)))))
- ((vectorp def)
- ;; A user-defined key.
- (if (funcall (aref def 0) elt) ;Call its function.
- ;; The function has eaten this object.
- (setq actions (1+ actions))
- ;; Regurgitated; try again.
- (setq next (` (lambda ()
- (setq next '(, next))
- '(, elt))))))
- ((and (consp char)
- (eq (car char) 'switch-frame))
- ;; switch-frame event. Put it off until we're done.
- (setq delayed-switch-frame char)
- (setq next (` (lambda ()
- (setq next '(, next))
- '(, elt)))))
- (t
- ;; Random char.
- (message "Type %s for help."
- (key-description (vector help-char)))
- (beep)
- (sit-for 1)
- (setq next (` (lambda ()
- (setq next '(, next))
- '(, elt)))))))
- (prompt
- (funcall actor elt)
- (setq actions (1+ actions))))))
- (if delayed-switch-frame
- (setq unread-command-events
- (cons delayed-switch-frame unread-command-events))))
- ;; Clear the last prompt from the minibuffer.
- (let ((message-log-max nil))
- (message ""))
- ;; Return the number of actions that were taken.
- actions))
-
-;;; map-ynp.el ends here
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el
deleted file mode 100644
index c670e1ace41..00000000000
--- a/lisp/menu-bar.el
+++ /dev/null
@@ -1,700 +0,0 @@
-;;; menu-bar.el --- define a default menu bar.
-
-;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: RMS
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; Avishai Yacobi suggested some menu rearrangements.
-
-;;; Code:
-
-;;; User options:
-
-(defvar buffers-menu-max-size 10
- "*Maximum number of entries which may appear on the Buffers menu.
-If this is 10, then only the ten most-recently-selected buffers are shown.
-If this is nil, then all buffers are shown.
-A large number or nil slows down menu responsiveness.")
-
-;; Don't clobber an existing menu-bar keymap, to preserve any menu-bar key
-;; definitions made in loaddefs.el.
-(or (lookup-key global-map [menu-bar])
- (define-key global-map [menu-bar] (make-sparse-keymap "menu-bar")))
-(defvar menu-bar-help-menu (make-sparse-keymap "Help"))
-
-;; Force Help item to come last, after the major mode's own items.
-;; The symbol used to be called `help', but that gets confused with the
-;; help key.
-(setq menu-bar-final-items '(help-menu))
-
-(define-key global-map [menu-bar help-menu] (cons "Help" menu-bar-help-menu))
-(defvar menu-bar-search-menu (make-sparse-keymap "Search"))
-(define-key global-map [menu-bar search] (cons "Search" menu-bar-search-menu))
-(defvar menu-bar-edit-menu (make-sparse-keymap "Edit"))
-(define-key global-map [menu-bar edit] (cons "Edit" menu-bar-edit-menu))
-(defvar menu-bar-tools-menu (make-sparse-keymap "Tools"))
-(define-key global-map [menu-bar tools] (cons "Tools" menu-bar-tools-menu))
-(defvar menu-bar-files-menu (make-sparse-keymap "Files"))
-(define-key global-map [menu-bar files] (cons "Files" menu-bar-files-menu))
-
-;; This alias is for compatibility with 19.28 and before.
-(defvar menu-bar-file-menu menu-bar-files-menu)
-
-(defvar vc-menu-map (make-sparse-keymap "Version Control"))
-
-(define-key menu-bar-tools-menu [gdb] '("Debugger..." . gdb))
-(define-key menu-bar-tools-menu [compile] '("Compile..." . compile))
-(define-key menu-bar-tools-menu [grep] '("Search Files..." . grep))
-
-(define-key menu-bar-tools-menu [separator-1]
- '("--"))
-
-(define-key menu-bar-tools-menu [calendar] '("Display Calendar" . calendar))
-(define-key menu-bar-tools-menu [rmail] '("Send Mail" . compose-mail))
-(define-key menu-bar-tools-menu [rmail] '("Read Mail" . rmail))
-(define-key menu-bar-tools-menu [gnus] '("Read Net News" . gnus))
-
-(define-key menu-bar-tools-menu [separator-vc]
- '("--"))
-
-(define-key menu-bar-tools-menu [vc]
- (cons "Version Control" vc-menu-map))
-
-(define-key menu-bar-tools-menu [separator-compare]
- '("--"))
-
-(define-key menu-bar-tools-menu [epatch]
- '("Apply Patch" . menu-bar-epatch-menu))
-(define-key menu-bar-tools-menu [ediff-merge]
- '("Merge" . menu-bar-ediff-merge-menu))
-(define-key menu-bar-tools-menu [compare]
- '("Compare" . menu-bar-ediff-menu))
-
-(define-key menu-bar-tools-menu [separator-print]
- '("--"))
-
-(put 'print-region 'menu-enable 'mark-active)
-(put 'ps-print-region-with-faces 'menu-enable 'mark-active)
-
-(define-key menu-bar-tools-menu [ps-print-region]
- '("Postscript Print Region" . ps-print-region-with-faces))
-(define-key menu-bar-tools-menu [ps-print-buffer]
- '("Postscript Print Buffer" . ps-print-buffer-with-faces))
-(define-key menu-bar-tools-menu [print-region]
- '("Print Region" . print-region))
-(define-key menu-bar-tools-menu [print-buffer]
- '("Print Buffer" . print-buffer))
-
-(define-key menu-bar-files-menu [exit-emacs]
- '("Exit Emacs" . save-buffers-kill-emacs))
-
-(define-key menu-bar-files-menu [separator-exit]
- '("--"))
-
-(define-key menu-bar-files-menu [one-window]
- '("One Window" . delete-other-windows))
-
-(define-key menu-bar-files-menu [split-window]
- '("Split Window" . split-window-vertically))
-
-(if (fboundp 'delete-frame)
- (progn
- ;; Don't use delete-frame as event name
- ;; because that is a special event.
- (define-key menu-bar-files-menu [delete-this-frame]
- '("Delete Frame" . delete-frame))
- (define-key menu-bar-files-menu [make-frame-on-display]
- '("Open New Display..." . make-frame-on-display))
- (define-key menu-bar-files-menu [make-frame]
- '("Make New Frame" . make-frame))))
-
-(define-key menu-bar-files-menu [separator-buffers]
- '("--"))
-
-(define-key menu-bar-files-menu [kill-buffer]
- '("Kill Current Buffer" . kill-this-buffer))
-(define-key menu-bar-files-menu [insert-file]
- '("Insert File..." . insert-file))
-(define-key menu-bar-files-menu [revert-buffer]
- '("Revert Buffer" . revert-buffer))
-(define-key menu-bar-files-menu [write-file]
- '("Save Buffer As..." . write-file))
-(define-key menu-bar-files-menu [save-buffer] '("Save Buffer" . save-buffer))
-(define-key menu-bar-files-menu [dired] '("Open Directory..." . dired))
-(define-key menu-bar-files-menu [open-file] '("Open File..." . find-file))
-
-
-(defun nonincremental-search-forward (string)
- "Read a string and search for it nonincrementally."
- (interactive "sSearch for string: ")
- (if (equal string "")
- (search-forward (car search-ring))
- (isearch-update-ring string nil)
- (search-forward string)))
-
-(defun nonincremental-search-backward (string)
- "Read a string and search backward for it nonincrementally."
- (interactive "sSearch for string: ")
- (if (equal string "")
- (search-backward (car search-ring))
- (isearch-update-ring string nil)
- (search-backward string)))
-
-(defun nonincremental-re-search-forward (string)
- "Read a regular expression and search for it nonincrementally."
- (interactive "sSearch for regexp: ")
- (if (equal string "")
- (re-search-forward (car regexp-search-ring))
- (isearch-update-ring string t)
- (re-search-forward string)))
-
-(defun nonincremental-re-search-backward (string)
- "Read a regular expression and search backward for it nonincrementally."
- (interactive "sSearch for regexp: ")
- (if (equal string "")
- (re-search-backward (car regexp-search-ring))
- (isearch-update-ring string t)
- (re-search-backward string)))
-
-(defun nonincremental-repeat-search-forward ()
- "Search forward for the previous search string."
- (interactive)
- (search-forward (car search-ring)))
-
-(defun nonincremental-repeat-search-backward ()
- "Search backward for the previous search string."
- (interactive)
- (search-backward (car search-ring)))
-
-(defun nonincremental-repeat-re-search-forward ()
- "Search forward for the previous regular expression."
- (interactive)
- (re-search-forward (car regexp-search-ring)))
-
-(defun nonincremental-repeat-re-search-backward ()
- "Search backward for the previous regular expression."
- (interactive)
- (re-search-backward (car regexp-search-ring)))
-
-(define-key menu-bar-search-menu [query-replace-regexp]
- '("Query Replace Regexp..." . query-replace-regexp))
-(define-key menu-bar-search-menu [query-replace]
- '("Query Replace..." . query-replace))
-(define-key menu-bar-search-menu [find-tag]
- '("Find Tag..." . find-tag))
-(define-key menu-bar-search-menu [bookmark]
- '("Bookmarks" . menu-bar-bookmark-map))
-
-(define-key menu-bar-search-menu [separator-search]
- '("--"))
-
-(define-key menu-bar-search-menu [repeat-regexp-back]
- '("Repeat Regexp Backwards" . nonincremental-repeat-re-search-backward))
-(define-key menu-bar-search-menu [repeat-search-back]
- '("Repeat Backwards" . nonincremental-repeat-search-backward))
-(define-key menu-bar-search-menu [repeat-regexp-fwd]
- '("Repeat Regexp" . nonincremental-repeat-re-search-forward))
-(define-key menu-bar-search-menu [repeat-search-fwd]
- '("Repeat Search" . nonincremental-repeat-search-forward))
-
-(define-key menu-bar-search-menu [separator-repeat]
- '("--"))
-
-(define-key menu-bar-search-menu [re-search-backward]
- '("Regexp Search Backwards..." . nonincremental-re-search-backward))
-(define-key menu-bar-search-menu [search-backward]
- '("Search Backwards..." . nonincremental-search-backward))
-(define-key menu-bar-search-menu [re-search-forward]
- '("Regexp Search..." . nonincremental-re-search-forward))
-(define-key menu-bar-search-menu [search-forward]
- '("Search..." . nonincremental-search-forward))
-
-(if (fboundp 'start-process)
- (define-key menu-bar-edit-menu [spell] '("Spell" . ispell-menu-map)))
-(define-key menu-bar-edit-menu [fill] '("Fill" . fill-region))
-(define-key menu-bar-edit-menu [props] '("Text Properties" . facemenu-menu))
-
-(define-key menu-bar-edit-menu [separator-edit]
- '("--"))
-
-(define-key menu-bar-edit-menu [clear] '("Clear" . delete-region))
-
-(define-key menu-bar-edit-menu [paste] '("Paste Most Recent" . yank))
-
-(defvar yank-menu (cons "Select Yank" nil))
-(fset 'yank-menu (cons 'keymap yank-menu))
-(define-key menu-bar-edit-menu [select-paste] '("Select and Paste" . yank-menu))
-(define-key menu-bar-edit-menu [copy] '("Copy" . menu-bar-kill-ring-save))
-(define-key menu-bar-edit-menu [cut] '("Cut" . kill-region))
-(define-key menu-bar-edit-menu [undo] '("Undo" . undo))
-
-(defun menu-bar-kill-ring-save (beg end)
- (interactive "r")
- (if (mouse-region-match)
- (message "Select a region with the mouse does `copy' automatically")
- (kill-ring-save beg end)))
-
-(put 'fill-region 'menu-enable '(and mark-active (not buffer-read-only)))
-(put 'kill-region 'menu-enable '(and mark-active (not buffer-read-only)))
-(put 'menu-bar-kill-ring-save 'menu-enable 'mark-active)
-(put 'yank 'menu-enable '(and (x-selection-exists-p) (not buffer-read-only)))
-(put 'yank-menu 'menu-enable '(and (cdr yank-menu) (not buffer-read-only)))
-(put 'delete-region 'menu-enable '(and mark-active
- (not buffer-read-only)
- (not (mouse-region-match))))
-(put 'undo 'menu-enable '(and (not buffer-read-only)
- (if (eq last-command 'undo)
- pending-undo-list
- (consp buffer-undo-list))))
-(put 'query-replace 'menu-enable '(not buffer-read-only))
-(put 'query-replace-regexp 'menu-enable '(not buffer-read-only))
-
-(autoload 'ispell-menu-map "ispell" nil t 'keymap)
-
-;; These are alternative definitions for the cut, paste and copy
-;; menu items. Use them if your system expects these to use the clipboard.
-
-(put 'clipboard-kill-region 'menu-enable 'mark-active)
-(put 'clipboard-kill-ring-save 'menu-enable 'mark-active)
-(put 'clipboard-yank 'menu-enable
- '(or (x-selection-exists-p) (x-selection-exists-p 'CLIPBOARD)))
-
-(defun clipboard-yank ()
- "Reinsert the last stretch of killed text, or the clipboard contents."
- (interactive)
- (let ((x-select-enable-clipboard t))
- (yank)))
-
-(defun clipboard-kill-ring-save (beg end)
- "Copy region to kill ring, and save in the X clipboard."
- (interactive "r")
- (let ((x-select-enable-clipboard t))
- (kill-ring-save beg end)))
-
-(defun clipboard-kill-region (beg end)
- "Kill the region, and save it in the X clipboard."
- (interactive "r")
- (let ((x-select-enable-clipboard t))
- (kill-region beg end)))
-
-(defun menu-bar-enable-clipboard ()
- "Make CUT, PASTE and COPY (keys and menu bar items) use the clipboard.
-Do the same for the keys of the same name."
- (interactive)
- ;; We can't use constant list structure here because it becomes pure,
- ;; and because it gets modified with cache data.
- (define-key menu-bar-edit-menu [paste]
- (cons "Paste" 'clipboard-yank))
- (define-key menu-bar-edit-menu [copy]
- (cons "Copy" 'clipboard-kill-ring-save))
- (define-key menu-bar-edit-menu [cut]
- (cons "Cut" 'clipboard-kill-region))
-
- (define-key global-map [f20] 'clipboard-kill-region)
- (define-key global-map [f16] 'clipboard-kill-ring-save)
- (define-key global-map [f18] 'clipboard-yank)
- ;; X11R6 versions
- (define-key global-map [cut] 'clipboard-kill-region)
- (define-key global-map [copy] 'clipboard-kill-ring-save)
- (define-key global-map [paste] 'clipboard-yank))
-
-(define-key menu-bar-help-menu [emacs-version]
- '("Show Version" . emacs-version))
-(define-key menu-bar-help-menu [report-emacs-bug]
- '("Send Bug Report..." . report-emacs-bug))
-(define-key menu-bar-help-menu [finder-by-keyword]
- '("Find Lisp Packages..." . finder-by-keyword))
-(define-key menu-bar-help-menu [emacs-tutorial]
- '("Emacs Tutorial" . help-with-tutorial))
-(define-key menu-bar-help-menu [man]
- '("Man..." . manual-entry))
-(define-key menu-bar-help-menu [describe-variable]
- '("Describe Variable..." . describe-variable))
-(define-key menu-bar-help-menu [describe-function]
- '("Describe Function..." . describe-function))
-(define-key menu-bar-help-menu [describe-key]
- '("Describe Key..." . describe-key))
-(define-key menu-bar-help-menu [list-keybindings]
- '("List Keybindings" . describe-bindings))
-(define-key menu-bar-help-menu [command-apropos]
- '("Command Apropos..." . command-apropos))
-(define-key menu-bar-help-menu [describe-mode]
- '("Describe Mode" . describe-mode))
-(define-key menu-bar-help-menu [info] '("Browse Manuals" . info))
-(define-key menu-bar-help-menu [emacs-faq] '("Emacs FAQ" . view-emacs-FAQ))
-(define-key menu-bar-help-menu [emacs-news] '("Emacs News" . view-emacs-news))
-
-(defun kill-this-buffer () ; for the menubar
- "Kills the current buffer."
- (interactive)
- (kill-buffer (current-buffer)))
-
-(defun kill-this-buffer-enabled-p ()
- (let ((count 0)
- (buffers (buffer-list)))
- (while buffers
- (or (string-match "^ " (buffer-name (car buffers)))
- (setq count (1+ count)))
- (setq buffers (cdr buffers)))
- (and (not (window-minibuffer-p (frame-selected-window menu-updating-frame)))
- (> count 1))))
-
-(put 'kill-this-buffer 'menu-enable '(kill-this-buffer-enabled-p))
-
-(put 'save-buffer 'menu-enable
- '(and (buffer-modified-p)
- (not (window-minibuffer-p (frame-selected-window menu-updating-frame)))))
-
-(put 'write-file 'menu-enable
- '(not (window-minibuffer-p (frame-selected-window menu-updating-frame))))
-
-(put 'find-file 'menu-enable
- '(not (window-minibuffer-p (frame-selected-window menu-updating-frame))))
-
-(put 'dired 'menu-enable
- '(not (window-minibuffer-p (frame-selected-window menu-updating-frame))))
-
-(put 'insert-file 'menu-enable
- '(not (window-minibuffer-p (frame-selected-window menu-updating-frame))))
-
-(put 'revert-buffer 'menu-enable
- '(or revert-buffer-function revert-buffer-insert-file-contents-function
- (and (buffer-file-name)
- (or (buffer-modified-p)
- (not (verify-visited-file-modtime (current-buffer)))))))
-
-;; Permit deleting frame if it would leave a visible or iconified frame.
-(put 'delete-frame 'menu-enable
- '(delete-frame-enabled-p))
-
-(defun delete-frame-enabled-p ()
- "Return non-nil if `delete-frame' should be enabled in the menu bar."
- (let ((frames (frame-list))
- (count 0))
- (while frames
- (if (frame-visible-p (car frames))
- (setq count (1+ count)))
- (setq frames (cdr frames)))
- (> count 1)))
-
-(put 'advertised-undo 'menu-enable
- '(and (not (eq t buffer-undo-list))
- (if (eq last-command 'undo)
- (and (boundp 'pending-undo-list)
- pending-undo-list)
- buffer-undo-list)))
-
-(defvar yank-menu-length 20
- "*Maximum length to display in the yank-menu.")
-
-(defun menu-bar-update-yank-menu (string old)
- (let ((front (car (cdr yank-menu)))
- (menu-string (if (<= (length string) yank-menu-length)
- string
- (concat
- (substring string 0 (/ yank-menu-length 2))
- "..."
- (substring string (- (/ yank-menu-length 2)))))))
- ;; Don't let the menu string be all dashes
- ;; because that has a special meaning in a menu.
- (if (string-match "\\`-+\\'" menu-string)
- (setq menu-string (concat menu-string " ")))
- ;; If we're supposed to be extending an existing string, and that
- ;; string really is at the front of the menu, then update it in place.
- (if (and old (or (eq old (car front))
- (string= old (car front))))
- (progn
- (setcar front string)
- (setcar (cdr front) menu-string))
- (setcdr yank-menu
- (cons
- (cons string (cons menu-string 'menu-bar-select-yank))
- (cdr yank-menu)))))
- (if (> (length (cdr yank-menu)) kill-ring-max)
- (setcdr (nthcdr kill-ring-max yank-menu) nil)))
-
-(defun menu-bar-select-yank ()
- (interactive "*")
- (push-mark (point))
- (insert last-command-event))
-
-;; This definition is just to show what this looks like.
-;; It gets overridden below when menu-bar-update-buffers is called.
-(define-key global-map [menu-bar buffer]
- (cons "Buffers" (make-sparse-keymap "Buffers")))
-
-(defvar list-buffers-directory nil)
-
-(defvar menu-bar-update-buffers-maxbuf)
-
-(defun menu-bar-select-buffer ()
- (interactive)
- (switch-to-buffer last-command-event))
-
-(defun menu-bar-select-frame ()
- (interactive)
- (make-frame-visible last-command-event)
- (raise-frame last-command-event)
- (select-frame last-command-event))
-
-(defun menu-bar-update-buffers-1 (elt)
- (cons (format
- (format "%%%ds %%s%%s %%s" menu-bar-update-buffers-maxbuf)
- (cdr elt)
- (if (buffer-modified-p (car elt))
- "*" " ")
- (save-excursion
- (set-buffer (car elt))
- (if buffer-read-only "%" " "))
- (let ((file
- (or (buffer-file-name (car elt))
- (save-excursion
- (set-buffer (car elt))
- list-buffers-directory)
- "")))
- (setq file (or (file-name-directory file)
- ""))
- (if (> (length file) 20)
- (setq file (concat "..." (substring file -17))))
- file))
- (car elt)))
-
-(defvar menu-bar-buffers-menu-list-buffers-entry nil)
-
-(defun menu-bar-update-buffers ()
- ;; If user discards the Buffers item, play along.
- (and (lookup-key (current-global-map) [menu-bar buffer])
- (frame-or-buffer-changed-p)
- (let ((buffers (buffer-list))
- (frames (frame-list))
- (maxlen 0)
- buffers-menu frames-menu)
- ;; If requested, list only the N most recently selected buffers.
- (if (and (integerp buffers-menu-max-size)
- (> buffers-menu-max-size 1))
- (if (> (length buffers) buffers-menu-max-size)
- (setcdr (nthcdr buffers-menu-max-size buffers) nil)))
-
- ;; Make the menu of buffers proper.
- (setq buffers-menu
- (cons "Select Buffer"
- (let* ((buffer-list
- (mapcar 'list buffers))
- tail
- (menu-bar-update-buffers-maxbuf 0)
- alist
- head)
- ;; Put into each element of buffer-list
- ;; the name for actual display,
- ;; perhaps truncated in the middle.
- (setq tail buffer-list)
- (while tail
- (let ((name (buffer-name (car (car tail)))))
- (setcdr (car tail)
- (if (> (length name) 27)
- (concat (substring name 0 12)
- "..."
- (substring name -12))
- name)))
- (setq tail (cdr tail)))
- ;; Compute the maximum length of any name.
- (setq tail buffer-list)
- (while tail
- (or (eq ?\ (aref (cdr (car tail)) 0))
- (setq menu-bar-update-buffers-maxbuf
- (max menu-bar-update-buffers-maxbuf
- (length (cdr (car tail))))))
- (setq tail (cdr tail)))
- ;; Set ALIST to an alist of the form
- ;; ITEM-STRING . BUFFER
- (setq tail buffer-list)
- (while tail
- (let ((elt (car tail)))
- (or (eq ?\ (aref (cdr elt) 0))
- (setq alist (cons
- (menu-bar-update-buffers-1 elt)
- alist)))
- (and alist (> (length (car (car alist))) maxlen)
- (setq maxlen (length (car (car alist))))))
- (setq tail (cdr tail)))
- (setq alist (nreverse alist))
- ;; Make the menu item for list-buffers
- ;; or reuse the one we already have.
- ;; The advantage in reusing one
- ;; is that it already has the keyboard equivalent
- ;; cached, so we save the time to look that up again.
- (or menu-bar-buffers-menu-list-buffers-entry
- (setq menu-bar-buffers-menu-list-buffers-entry
- (cons
- 'list-buffers
- (cons
- ""
- 'list-buffers))))
- ;; Update the item string for menu's new width.
- (setcar (cdr menu-bar-buffers-menu-list-buffers-entry)
- (concat (make-string (max (- (/ maxlen 2) 8) 0)
- ?\ )
- "List All Buffers"))
- ;; Now make the actual list of items,
- ;; ending with the list-buffers item.
- (nconc (mapcar '(lambda (pair)
- ;; This is somewhat risque, to use
- ;; the buffer name itself as the event
- ;; type to define, but it works.
- ;; It would not work to use the buffer
- ;; since a buffer as an event has its
- ;; own meaning.
- (nconc (list (buffer-name (cdr pair))
- (car pair)
- (cons nil nil))
- 'menu-bar-select-buffer))
- alist)
- (list menu-bar-buffers-menu-list-buffers-entry)))))
-
-
- ;; Make a Frames menu if we have more than one frame.
- (if (cdr frames)
- (let ((name (concat (make-string (max (- (/ maxlen 2) 3) 0)
- ?\ )
- "Frames"))
- (frames-menu
- (cons 'keymap
- (cons "Select Frame"
- (mapcar '(lambda (frame)
- (nconc (list frame
- (cdr (assq 'name
- (frame-parameters frame)))
- (cons nil nil))
- 'menu-bar-select-frame))
- frames)))))
- ;; Put it underneath the Buffers menu.
- (setq buffers-menu (cons (cons 'frames (cons name frames-menu))
- buffers-menu))))
- (if buffers-menu
- (setq buffers-menu (cons 'keymap buffers-menu)))
- (define-key (current-global-map) [menu-bar buffer]
- (cons "Buffers" buffers-menu)))))
-
-(add-hook 'menu-bar-update-hook 'menu-bar-update-buffers)
-
-(menu-bar-update-buffers)
-
-;; this version is too slow
-;;;(defun format-buffers-menu-line (buffer)
-;;; "Returns a string to represent the given buffer in the Buffer menu.
-;;;nil means the buffer shouldn't be listed. You can redefine this."
-;;; (if (string-match "\\` " (buffer-name buffer))
-;;; nil
-;;; (save-excursion
-;;; (set-buffer buffer)
-;;; (let ((size (buffer-size)))
-;;; (format "%s%s %-19s %6s %-15s %s"
-;;; (if (buffer-modified-p) "*" " ")
-;;; (if buffer-read-only "%" " ")
-;;; (buffer-name)
-;;; size
-;;; mode-name
-;;; (or (buffer-file-name) ""))))))
-
-;;; Set up a menu bar menu for the minibuffer.
-
-(mapcar
- (function
- (lambda (map)
- (define-key map [menu-bar minibuf]
- (cons "Minibuf" (make-sparse-keymap "Minibuf")))))
- (list minibuffer-local-ns-map
- minibuffer-local-must-match-map
- minibuffer-local-isearch-map
- minibuffer-local-map
- minibuffer-local-completion-map))
-
-(mapcar
- (function
- (lambda (map)
- (define-key map [menu-bar minibuf ?\?]
- '("List Completions" . minibuffer-completion-help))
- (define-key map [menu-bar minibuf space]
- '("Complete Word" . minibuffer-complete-word))
- (define-key map [menu-bar minibuf tab]
- '("Complete" . minibuffer-complete))
- ))
- (list minibuffer-local-must-match-map
- minibuffer-local-completion-map))
-
-(mapcar
- (function
- (lambda (map)
- (define-key map [menu-bar minibuf quit]
- '("Quit" . keyboard-escape-quit))
- (define-key map [menu-bar minibuf return]
- '("Enter" . exit-minibuffer))
- ))
- (list minibuffer-local-ns-map
- minibuffer-local-must-match-map
- minibuffer-local-isearch-map
- minibuffer-local-map
- minibuffer-local-completion-map))
-
-(defvar menu-bar-mode nil)
-
-(defun menu-bar-mode (flag)
- "Toggle display of a menu bar on each frame.
-This command applies to all frames that exist and frames to be
-created in the future.
-With a numeric argument, if the argument is negative,
-turn off menu bars; otherwise, turn on menu bars."
- (interactive "P")
-
- ;; Make menu-bar-mode and default-frame-alist consistent.
- (let ((default (assq 'menu-bar-lines default-frame-alist)))
- (if default
- (setq menu-bar-mode (not (eq (cdr default) 0)))
- (setq default-frame-alist
- (cons (cons 'menu-bar-lines (if menu-bar-mode 1 0))
- default-frame-alist))))
-
- ;; Toggle or set the mode, according to FLAG.
- (setq menu-bar-mode (if (null flag) (not menu-bar-mode)
- (> (prefix-numeric-value flag) 0)))
-
- ;; Apply it to default-frame-alist.
- (let ((parameter (assq 'menu-bar-lines default-frame-alist)))
- (if (consp parameter)
- (setcdr parameter (if menu-bar-mode 1 0))
- (setq default-frame-alist
- (cons (cons 'menu-bar-lines (if menu-bar-mode 1 0))
- default-frame-alist))))
-
- ;; Apply it to existing frames.
- (let ((frames (frame-list)))
- (while frames
- (let ((height (cdr (assq 'height (frame-parameters (car frames))))))
- (modify-frame-parameters (car frames)
- (list (cons 'menu-bar-lines
- (if menu-bar-mode 1 0))))
- (modify-frame-parameters (car frames)
- (list (cons 'height height))))
- (setq frames (cdr frames)))))
-
-(provide 'menu-bar)
-
-;;; menu-bar.el ends here
diff --git a/lisp/message.el b/lisp/message.el
deleted file mode 100644
index edfe6fbdee7..00000000000
--- a/lisp/message.el
+++ /dev/null
@@ -1,2996 +0,0 @@
-;;; message.el --- composing mail and news messages
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: mail, news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This mode provides mail-sending facilities from within Emacs. It
-;; consists mainly of large chunks of code from the sendmail.el,
-;; gnus-msg.el and rnewspost.el files.
-
-;;; Code:
-
-(eval-when-compile
- (require 'cl))
-(require 'mailheader)
-(require 'rmail)
-(require 'nnheader)
-(require 'timezone)
-(require 'easymenu)
-(if (string-match "XEmacs\\|Lucid" emacs-version)
- (require 'mail-abbrevs)
- (require 'mailabbrev))
-
-(defvar message-directory "~/Mail/"
- "*Directory from which all other mail file variables are derived.")
-
-(defvar message-max-buffers 10
- "*How many buffers to keep before starting to kill them off.")
-
-(defvar message-send-rename-function nil
- "Function called to rename the buffer after sending it.")
-
-;;;###autoload
-(defvar message-fcc-handler-function 'rmail-output
- "*A function called to save outgoing articles.
-This function will be called with the name of the file to store the
-article in. The default function is `rmail-output' which saves in Unix
-mailbox format.")
-
-;;;###autoload
-(defvar message-courtesy-message
- "The following message is a courtesy copy of an article\nthat has been posted as well.\n\n"
- "*This is inserted at the start of a mailed copy of a posted message.
-If this variable is nil, no such courtesy message will be added.")
-
-;;;###autoload
-(defvar message-ignored-bounced-headers "^\\(Received\\|Return-Path\\):"
- "*Regexp that matches headers to be removed in resent bounced mail.")
-
-;;;###autoload
-(defvar message-from-style 'default
- "*Specifies how \"From\" headers look.
-
-If `nil', they contain just the return address like:
- king@grassland.com
-If `parens', they look like:
- king@grassland.com (Elvis Parsley)
-If `angles', they look like:
- Elvis Parsley <king@grassland.com>
-
-Otherwise, most addresses look like `angles', but they look like
-`parens' if `angles' would need quoting and `parens' would not.")
-
-;;;###autoload
-(defvar message-syntax-checks nil
- "Controls what syntax checks should not be performed on outgoing posts.
-To disable checking of long signatures, for instance, add
- `(signature . disabled)' to this list.
-
-Don't touch this variable unless you really know what you're doing.
-
-Checks include subject-cmsg multiple-headers sendsys message-id from
-long-lines control-chars size new-text redirected-followup signature
-approved sender empty empty-headers message-id from subject.")
-
-;;;###autoload
-(defvar message-required-news-headers
- '(From Newsgroups Subject Date Message-ID
- (optional . Organization) Lines
- (optional . X-Newsreader))
- "*Headers to be generated or prompted for when posting an article.
-RFC977 and RFC1036 require From, Date, Newsgroups, Subject,
-Message-ID. Organization, Lines, In-Reply-To, Expires, and
-X-Newsreader are optional. If don't you want message to insert some
-header, remove it from this list.")
-
-;;;###autoload
-(defvar message-required-mail-headers
- '(From Subject Date (optional . In-Reply-To) Message-ID Lines
- (optional . X-Mailer))
- "*Headers to be generated or prompted for when mailing a message.
-RFC822 required that From, Date, To, Subject and Message-ID be
-included. Organization, Lines and X-Mailer are optional.")
-
-;;;###autoload
-(defvar message-deletable-headers '(Message-ID Date)
- "*Headers to be deleted if they already exist and were generated by message previously.")
-
-;;;###autoload
-(defvar message-ignored-news-headers
- "^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:"
- "*Regexp of headers to be removed unconditionally before posting.")
-
-;;;###autoload
-(defvar message-ignored-mail-headers "^Gcc:\\|^Fcc:"
- "*Regexp of headers to be removed unconditionally before mailing.")
-
-;;;###autoload
-(defvar message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|Return-Path:\\|^Supersedes:"
- "*Header lines matching this regexp will be deleted before posting.
-It's best to delete old Path and Date headers before posting to avoid
-any confusion.")
-
-;;;###autoload
-(defvar message-signature-separator "^-- *$"
- "Regexp matching the signature separator.")
-
-;;;###autoload
-(defvar message-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.")
-
-;;;###autoload
-(defvar message-generate-new-buffers t
- "*Non-nil means that a new message buffer will be created whenever `mail-setup' is called.
-If this is a function, call that function with three parameters: The type,
-the to address and the group name. (Any of these may be nil.) The function
-should return the new buffer name.")
-
-;;;###autoload
-(defvar message-kill-buffer-on-exit nil
- "*Non-nil means that the message buffer will be killed after sending a message.")
-
-(defvar gnus-local-organization)
-(defvar message-user-organization
- (or (and (boundp 'gnus-local-organization)
- gnus-local-organization)
- (getenv "ORGANIZATION")
- t)
- "*String to be used as an Organization header.
-If t, use `message-user-organization-file'.")
-
-;;;###autoload
-(defvar message-user-organization-file "/usr/lib/news/organization"
- "*Local news organization file.")
-
-(defvar message-autosave-directory "~/"
- ; (concat (file-name-as-directory message-directory) "drafts/")
- "*Directory where message autosaves buffers.
-If nil, message won't autosave.")
-
-(defvar message-forward-start-separator
- "------- Start of forwarded message -------\n"
- "*Delimiter inserted before forwarded messages.")
-
-(defvar message-forward-end-separator
- "------- End of forwarded message -------\n"
- "*Delimiter inserted after forwarded messages.")
-
-;;;###autoload
-(defvar message-signature-before-forwarded-message t
- "*If non-nil, put the signature before any included forwarded message.")
-
-;;;###autoload
-(defvar message-included-forward-headers
- "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-\\|^Message-ID:\\|^References:"
- "*Regexp matching headers to be included in forwarded messages.")
-
-;;;###autoload
-(defvar message-ignored-resent-headers "^Return-receipt"
- "*All headers that match this regexp will be deleted when resending a message.")
-
-;;;###autoload
-(defvar message-ignored-cited-headers "."
- "Delete these headers from the messages you yank.")
-
-;; Useful to set in site-init.el
-;;;###autoload
-(defvar message-send-mail-function 'message-send-mail-with-sendmail
- "Function to call to send the current buffer as mail.
-The headers should be delimited by a line whose contents match the
-variable `mail-header-separator'.
-
-Legal values include `message-send-mail-with-mh' and
-`message-send-mail-with-sendmail', which is the default.")
-
-;;;###autoload
-(defvar message-send-news-function 'message-send-news
- "Function to call to send the current buffer as news.
-The headers should be delimited by a line whose contents match the
-variable `mail-header-separator'.")
-
-;;;###autoload
-(defvar message-reply-to-function nil
- "Function that should return a list of headers.
-This function should pick out addresses from the To, Cc, and From headers
-and respond with new To and Cc headers.")
-
-;;;###autoload
-(defvar message-wide-reply-to-function nil
- "Function that should return a list of headers.
-This function should pick out addresses from the To, Cc, and From headers
-and respond with new To and Cc headers.")
-
-;;;###autoload
-(defvar message-followup-to-function nil
- "Function that should return a list of headers.
-This function should pick out addresses from the To, Cc, and From headers
-and respond with new To and Cc headers.")
-
-;;;###autoload
-(defvar message-use-followup-to 'ask
- "*Specifies what to do with Followup-To header.
-If nil, ignore the header. If it is t, use its value, but query before
-using the \"poster\" value. If it is the symbol `ask', query the user
-whether to ignore the \"poster\" value. If it is the symbol `use',
-always use the value.")
-
-(defvar gnus-post-method)
-(defvar gnus-select-method)
-;;;###autoload
-(defvar message-post-method
- (cond ((and (boundp 'gnus-post-method)
- gnus-post-method)
- gnus-post-method)
- ((boundp 'gnus-select-method)
- gnus-select-method)
- (t '(nnspool "")))
- "Method used to post news.")
-
-;;;###autoload
-(defvar message-generate-headers-first nil
- "*If non-nil, generate all possible headers before composing.")
-
-(defvar message-setup-hook nil
- "Normal hook, run each time a new outgoing message is initialized.
-The function `message-setup' runs this hook.")
-
-(defvar message-signature-setup-hook nil
- "Normal hook, run each time a new outgoing message is initialized.
-It is run after the headers have been inserted and before
-the signature is inserted.")
-
-(defvar message-mode-hook
- (if (fboundp 'mail-abbrevs-setup)
- '(mail-abbrevs-setup)
- (list (intern "mail-aliases-setup")))
- "Hook run in message mode buffers.")
-
-(defvar message-header-hook nil
- "Hook run in a message mode buffer narrowed to the headers.")
-
-(defvar message-header-setup-hook nil
- "Hook called narrowed to the headers when setting up a message buffer.")
-
-;;;###autoload
-(defvar message-citation-line-function 'message-insert-citation-line
- "*Function called to insert the \"Whomever writes:\" line.")
-
-;;;###autoload
-(defvar message-yank-prefix "> "
- "*Prefix inserted on the lines of yanked messages.
-nil means use indentation.")
-
-(defvar message-indentation-spaces 3
- "*Number of spaces to insert at the beginning of each cited line.
-Used by `message-yank-original' via `message-yank-cite'.")
-
-;;;###autoload
-(defvar message-cite-function 'message-cite-original
- "*Function for citing an original message.")
-
-;;;###autoload
-(defvar message-indent-citation-function 'message-indent-citation
- "*Function for modifying a citation just inserted in the mail buffer.
-This can also be a list of functions. Each function can find the
-citation between (point) and (mark t). And each function should leave
-point and mark around the citation text as modified.")
-
-(defvar message-abbrevs-loaded nil)
-
-;;;###autoload
-(defvar message-signature t
- "*String to be inserted at the end of the message buffer.
-If t, the `message-signature-file' file will be inserted instead.
-If a function, the result from the function will be used instead.
-If a form, the result from the form will be used instead.")
-
-;;;###autoload
-(defvar message-signature-file "~/.signature"
- "*File containing the text inserted at end of message. buffer.")
-
-(defvar message-distribution-function nil
- "*Function called to return a Distribution header.")
-
-(defvar message-expires 14
- "*Number of days before your article expires.")
-
-(defvar message-user-path nil
- "If nil, use the NNTP server name in the Path header.
-If stringp, use this; if non-nil, use no host name (user name only).")
-
-(defvar message-reply-buffer nil)
-(defvar message-reply-headers nil)
-(defvar message-newsreader nil)
-(defvar message-mailer nil)
-(defvar message-sent-message-via nil)
-(defvar message-checksum nil)
-(defvar message-send-actions nil
- "A list of actions to be performed upon successful sending of a message.")
-(defvar message-exit-actions nil
- "A list of actions to be performed upon exiting after sending a message.")
-(defvar message-kill-actions nil
- "A list of actions to be performed before killing a message buffer.")
-(defvar message-postpone-actions nil
- "A list of actions to be performed after postponing a message.")
-
-;;;###autoload
-(defvar message-default-headers nil
- "*A string containing header lines to be inserted in outgoing messages.
-It is inserted before you edit the message, so you can edit or delete
-these lines.")
-
-;;;###autoload
-(defvar message-default-mail-headers nil
- "*A string of header lines to be inserted in outgoing mails.")
-
-;;;###autoload
-(defvar message-default-news-headers nil
- "*A string of header lines to be inserted in outgoing news articles.")
-
-;; Note: could use /usr/ucb/mail instead of sendmail;
-;; options -t, and -v if not interactive.
-(defvar message-mailer-swallows-blank-line
- (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)"
- system-configuration)
- (file-readable-p "/etc/sendmail.cf")
- (let ((buffer (get-buffer-create " *temp*")))
- (unwind-protect
- (save-excursion
- (set-buffer buffer)
- (insert-file-contents "/etc/sendmail.cf")
- (goto-char (point-min))
- (let ((case-fold-search nil))
- (re-search-forward "^OR\\>" nil t)))
- (kill-buffer buffer))))
- ;; According to RFC822, "The field-name must be composed of printable
- ;; ASCII characters (i.e. characters that have decimal values between
- ;; 33 and 126, except colon)", i.e. any chars except ctl chars,
- ;; space, or colon.
- '(looking-at "[ \t]\\|[][!\"#$%&'()*+,-./0-9;<=>?@A-Z\\\\^_`a-z{|}~]+:"))
- "Set this non-nil if the system's mailer runs the header and body together.
-\(This problem exists on Sunos 4 when sendmail is run in remote mode.)
-The value should be an expression to test whether the problem will
-actually occur.")
-
-(defvar message-mode-syntax-table
- (let ((table (copy-syntax-table text-mode-syntax-table)))
- (modify-syntax-entry ?% ". " table)
- table)
- "Syntax table used while in Message mode.")
-
-(defvar message-font-lock-keywords
- (let* ((cite-prefix "A-Za-z") (cite-suffix (concat cite-prefix "0-9_.@-")))
- (list '("^To:" . font-lock-function-name-face)
- '("^[GBF]?[Cc][Cc]:\\|^Reply-To:" . font-lock-keyword-face)
- '("^\\(Subject:\\)[ \t]*\\(.+\\)?"
- (1 font-lock-comment-face) (2 font-lock-type-face nil t))
- (list (concat "^\\(" (regexp-quote mail-header-separator) "\\)$")
- 1 'font-lock-comment-face)
- (cons (concat "^[ \t]*"
- "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
- "[>|}].*")
- 'font-lock-reference-face)
- '("^\\(X-[A-Za-z0-9-]+\\|In-reply-to\\):.*"
- . font-lock-string-face)))
- "Additional expressions to highlight in Message mode.")
-
-(defvar message-face-alist
- '((bold . bold-region)
- (underline . underline-region)
- (default . (lambda (b e)
- (unbold-region b e)
- (ununderline-region b e))))
- "Alist of mail and news faces for facemenu.
-The cdr of ech entry is a function for applying the face to a region.")
-
-(defvar message-send-hook nil
- "Hook run before sending messages.")
-
-(defvar message-sent-hook nil
- "Hook run after sending messages.")
-
-;;; Internal variables.
-
-(defvar message-buffer-list nil)
-
-;;; Regexp matching the delimiter of messages in UNIX mail format
-;;; (UNIX From lines), minus the initial ^.
-(defvar message-unix-mail-delimiter
- (let ((time-zone-regexp
- (concat "\\([A-Z]?[A-Z]?[A-Z][A-Z]\\( DST\\)?"
- "\\|[-+]?[0-9][0-9][0-9][0-9]"
- "\\|"
- "\\) *")))
- (concat
- "From "
-
- ;; Username, perhaps with a quoted section that can contain spaces.
- "\\("
- "[^ \n]*"
- "\\(\\|\".*\"[^ \n]*\\)"
- "\\|<[^<>\n]+>"
- "\\) ?"
-
- ;; The time the message was sent.
- "\\([^ \n]*\\) *" ; day of the week
- "\\([^ ]*\\) *" ; month
- "\\([0-9]*\\) *" ; day of month
- "\\([0-9:]*\\) *" ; time of day
-
- ;; Perhaps a time zone, specified by an abbreviation, or by a
- ;; numeric offset.
- time-zone-regexp
-
- ;; The year.
- " [0-9][0-9]\\([0-9]*\\) *"
-
- ;; On some systems the time zone can appear after the year, too.
- time-zone-regexp
-
- ;; Old uucp cruft.
- "\\(remote from .*\\)?"
-
- "\n")))
-
-(defvar message-unsent-separator
- (concat "^ *---+ +Unsent message follows +---+ *$\\|"
- "^ *---+ +Returned message +---+ *$\\|"
- "^Start of returned message$\\|"
- "^ *---+ +Original message +---+ *$\\|"
- "^ *--+ +begin message +--+ *$\\|"
- "^ *---+ +Original message follows +---+ *$\\|"
- "^|? *---+ +Message text follows: +---+ *|?$")
- "A regexp that matches the separator before the text of a failed message.")
-
-(defvar message-header-format-alist
- `((Newsgroups)
- (To . message-fill-address)
- (Cc . message-fill-address)
- (Subject)
- (In-Reply-To)
- (Fcc)
- (Bcc)
- (Date)
- (Organization)
- (Distribution)
- (Lines)
- (Expires)
- (Message-ID)
- (References . message-fill-header)
- (X-Mailer)
- (X-Newsreader))
- "Alist used for formatting headers.")
-
-(eval-and-compile
- (autoload 'message-setup-toolbar "messagexmas")
- (autoload 'mh-send-letter "mh-comp"))
-
-
-
-;;;
-;;; Utility functions.
-;;;
-
-(defun message-point-at-bol ()
- "Return point at the beginning of the line."
- (let ((p (point)))
- (beginning-of-line)
- (prog1
- (point)
- (goto-char p))))
-
-(defun message-point-at-eol ()
- "Return point at the end of the line."
- (let ((p (point)))
- (end-of-line)
- (prog1
- (point)
- (goto-char p))))
-
-;; Delete the current line (and the next N lines.);
-(defmacro message-delete-line (&optional n)
- `(delete-region (progn (beginning-of-line) (point))
- (progn (forward-line ,(or n 1)) (point))))
-
-(defun message-tokenize-header (header &optional separator)
- "Split HEADER into a list of header elements.
-\",\" is used as the separator."
- (let ((regexp (format "[%s]+" (or separator ",")))
- (beg 1)
- quoted elems)
- (save-excursion
- (message-set-work-buffer)
- (insert header)
- (goto-char (point-min))
- (while (not (eobp))
- (forward-char 1)
- (cond ((and (> (point) beg)
- (or (eobp)
- (and (looking-at regexp)
- (not quoted))))
- (push (buffer-substring beg (point)) elems)
- (setq beg (match-end 0)))
- ((= (following-char) ?\")
- (setq quoted (not quoted)))))
- (nreverse elems))))
-
-(defun message-fetch-field (header)
- "The same as `mail-fetch-field', only remove all newlines."
- (let ((value (mail-fetch-field header)))
- (when value
- (nnheader-replace-chars-in-string value ?\n ? ))))
-
-(defun message-fetch-reply-field (header)
- "Fetch FIELD from the message we're replying to."
- (when (and message-reply-buffer
- (buffer-name message-reply-buffer))
- (save-excursion
- (set-buffer message-reply-buffer)
- (message-fetch-field header))))
-
-(defun message-set-work-buffer ()
- (if (get-buffer " *message work*")
- (progn
- (set-buffer " *message work*")
- (erase-buffer))
- (set-buffer (get-buffer-create " *message work*"))
- (kill-all-local-variables)
- (buffer-disable-undo (current-buffer))))
-
-(defun message-functionp (form)
- "Return non-nil if FORM is funcallable."
- (or (and (symbolp form) (fboundp form))
- (and (listp form) (eq (car form) 'lambda))))
-
-(defun message-strip-subject-re (subject)
- "Remove \"Re:\" from subject lines."
- (if (string-match "^[Rr][Ee]: *" subject)
- (substring subject (match-end 0))
- subject))
-
-(defun message-remove-header (header &optional is-regexp first reverse)
- "Remove HEADER in the narrowed buffer.
-If REGEXP, HEADER is a regular expression.
-If FIRST, only remove the first instance of the header.
-Return the number of headers removed."
- (goto-char (point-min))
- (let ((regexp (if is-regexp header (concat "^" header ":")))
- (number 0)
- (case-fold-search t)
- last)
- (while (and (not (eobp))
- (not last))
- (if (if reverse
- (not (looking-at regexp))
- (looking-at regexp))
- (progn
- (incf number)
- (when first
- (setq last t))
- (delete-region
- (point)
- ;; There might be a continuation header, so we have to search
- ;; until we find a new non-continuation line.
- (progn
- (forward-line 1)
- (if (re-search-forward "^[^ \t]" nil t)
- (goto-char (match-beginning 0))
- (point-max)))))
- (forward-line 1)
- (if (re-search-forward "^[^ \t]" nil t)
- (goto-char (match-beginning 0))
- (point-max))))
- number))
-
-(defun message-narrow-to-headers ()
- "Narrow the buffer to the head of the message."
- (widen)
- (narrow-to-region
- (goto-char (point-min))
- (if (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "\n") nil t)
- (match-beginning 0)
- (point-max)))
- (goto-char (point-min)))
-
-(defun message-narrow-to-head ()
- "Narrow the buffer to the head of the message."
- (widen)
- (narrow-to-region
- (goto-char (point-min))
- (if (search-forward "\n\n" nil 1)
- (1- (point))
- (point-max)))
- (goto-char (point-min)))
-
-(defun message-news-p ()
- "Say whether the current buffer contains a news message."
- (save-excursion
- (save-restriction
- (message-narrow-to-headers)
- (message-fetch-field "newsgroups"))))
-
-(defun message-mail-p ()
- "Say whether the current buffer contains a mail message."
- (save-excursion
- (save-restriction
- (message-narrow-to-headers)
- (or (message-fetch-field "to")
- (message-fetch-field "cc")
- (message-fetch-field "bcc")))))
-
-(defun message-next-header ()
- "Go to the beginning of the next header."
- (beginning-of-line)
- (or (eobp) (forward-char 1))
- (not (if (re-search-forward "^[^ \t]" nil t)
- (beginning-of-line)
- (goto-char (point-max)))))
-
-(defun message-sort-headers-1 ()
- "Sort the buffer as headers using `message-rank' text props."
- (goto-char (point-min))
- (sort-subr
- nil 'message-next-header
- (lambda ()
- (message-next-header)
- (unless (bobp)
- (forward-char -1)))
- (lambda ()
- (or (get-text-property (point) 'message-rank)
- 0))))
-
-(defun message-sort-headers ()
- "Sort the headers of the current message according to `message-header-format-alist'."
- (interactive)
- (save-excursion
- (save-restriction
- (let ((max (1+ (length message-header-format-alist)))
- rank)
- (message-narrow-to-headers)
- (while (re-search-forward "^[^ \n]+:" nil t)
- (put-text-property
- (match-beginning 0) (1+ (match-beginning 0))
- 'message-rank
- (if (setq rank (length (memq (assq (intern (buffer-substring
- (match-beginning 0)
- (1- (match-end 0))))
- message-header-format-alist)
- message-header-format-alist)))
- (- max rank)
- (1+ max)))))
- (message-sort-headers-1))))
-
-(defmacro message-y-or-n-p (question show &rest text)
- "Ask QUESTION, displaying the rest of the arguments in a temporary buffer."
- `(message-talkative-question 'y-or-n-p ,question ,show ,@text))
-
-(defun message-talkative-question (ask question show &rest text)
- "Call FUNCTION with argument QUESTION, displaying the rest of the arguments in a temporary buffer if SHOW.
-The following arguments may contain lists of values."
- (if (and show
- (setq text (message-flatten-list text)))
- (save-window-excursion
- (save-excursion
- (with-output-to-temp-buffer " *MESSAGE information message*"
- (set-buffer " *MESSAGE information message*")
- (mapcar 'princ text)
- (goto-char (point-min))))
- (funcall ask question))
- (funcall ask question)))
-
-(defun message-flatten-list (&rest list)
- (message-flatten-list-1 list))
-
-(defun message-flatten-list-1 (list)
- (cond ((consp list)
- (apply 'nconc (mapcar 'message-flatten-list-1 list)))
- (list
- (list list))))
-
-
-;;;
-;;; Message mode
-;;;
-
-;;; Set up keymap.
-
-(defvar message-mode-map nil)
-
-(unless message-mode-map
- (setq message-mode-map (copy-keymap text-mode-map))
- (define-key message-mode-map "\C-c?" 'describe-mode)
-
- (define-key message-mode-map "\C-c\C-f\C-t" 'message-goto-to)
- (define-key message-mode-map "\C-c\C-f\C-b" 'message-goto-bcc)
- (define-key message-mode-map "\C-c\C-f\C-w" 'message-goto-fcc)
- (define-key message-mode-map "\C-c\C-f\C-c" 'message-goto-cc)
- (define-key message-mode-map "\C-c\C-f\C-s" 'message-goto-subject)
- (define-key message-mode-map "\C-c\C-f\C-r" 'message-goto-reply-to)
- (define-key message-mode-map "\C-c\C-f\C-n" 'message-goto-newsgroups)
- (define-key message-mode-map "\C-c\C-f\C-d" 'message-goto-distribution)
- (define-key message-mode-map "\C-c\C-f\C-f" 'message-goto-followup-to)
- (define-key message-mode-map "\C-c\C-f\C-k" 'message-goto-keywords)
- (define-key message-mode-map "\C-c\C-f\C-u" 'message-goto-summary)
- (define-key message-mode-map "\C-c\C-b" 'message-goto-body)
- (define-key message-mode-map "\C-c\C-i" 'message-goto-signature)
-
- (define-key message-mode-map "\C-c\C-t" 'message-insert-to)
- (define-key message-mode-map "\C-c\C-n" 'message-insert-newsgroups)
-
- (define-key message-mode-map "\C-c\C-y" 'message-yank-original)
- (define-key message-mode-map "\C-c\C-q" 'message-fill-yanked-message)
- (define-key message-mode-map "\C-c\C-w" 'message-insert-signature)
- (define-key message-mode-map "\C-c\C-r" 'message-caesar-buffer-body)
- (define-key message-mode-map "\C-c\C-o" 'message-sort-headers)
- (define-key message-mode-map "\C-c\M-r" 'message-rename-buffer)
-
- (define-key message-mode-map "\C-c\C-c" 'message-send-and-exit)
- (define-key message-mode-map "\C-c\C-s" 'message-send)
- (define-key message-mode-map "\C-c\C-k" 'message-kill-buffer)
- (define-key message-mode-map "\C-c\C-d" 'message-dont-send)
-
- (define-key message-mode-map "\t" 'message-tab))
-
-(easy-menu-define message-mode-menu message-mode-map
- "Message Menu."
- '("Message"
- "Go to Field:"
- "----"
- ["To" message-goto-to t]
- ["Subject" message-goto-subject t]
- ["Cc" message-goto-cc t]
- ["Reply-to" message-goto-reply-to t]
- ["Summary" message-goto-summary t]
- ["Keywords" message-goto-keywords t]
- ["Newsgroups" message-goto-newsgroups t]
- ["Followup-To" message-goto-followup-to t]
- ["Distribution" message-goto-distribution t]
- ["Body" message-goto-body t]
- ["Signature" message-goto-signature t]
- "----"
- "Miscellaneous Commands:"
- "----"
- ["Sort Headers" message-sort-headers t]
- ["Yank Original" message-yank-original t]
- ["Fill Yanked Message" message-fill-yanked-message t]
- ["Insert Signature" message-insert-signature t]
- ["Caesar (rot13) Message" message-caesar-buffer-body t]
- ["Rename buffer" message-rename-buffer t]
- ["Spellcheck" ispell-message t]
- "----"
- ["Send Message" message-send-and-exit t]
- ["Abort Message" message-dont-send t]))
-
-(defvar facemenu-add-face-function)
-(defvar facemenu-remove-face-function)
-
-;;;###autoload
-(defun message-mode ()
- "Major mode for editing mail and news to be sent.
-Like Text Mode but with these additional commands:
-C-c C-s message-send (send the message) C-c C-c message-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 Subject
- C-c C-f C-c move to Cc C-c C-f C-b move to Bcc
- C-c C-f C-f move to Fcc C-c C-f C-r move to Reply-To
- C-c C-f C-u move to Summary C-c C-f C-n move to Newsgroups
- C-c C-f C-k move to Keywords C-c C-f C-d move to Distribution
- C-c C-f C-o move to Followup-To
-C-c C-t message-insert-to (add a To header to a news followup)
-C-c C-n message-insert-newsgroups (add a Newsgroup header to a news reply)
-C-c C-b message-goto-body (move to beginning of message text).
-C-c C-i message-goto-signature (move to the beginning of the signature).
-C-c C-w message-insert-signature (insert `message-signature-file' file).
-C-c C-y message-yank-original (insert current message, if any).
-C-c C-q message-fill-yanked-message (fill what was yanked).
-C-c C-r message-caesar-buffer-body (rot13 the message body)."
- (interactive)
- (kill-all-local-variables)
- (make-local-variable 'message-reply-buffer)
- (setq message-reply-buffer nil)
- (make-local-variable 'message-send-actions)
- (make-local-variable 'message-exit-actions)
- (make-local-variable 'message-kill-actions)
- (make-local-variable 'message-postpone-actions)
- (set-syntax-table message-mode-syntax-table)
- (use-local-map message-mode-map)
- (setq local-abbrev-table text-mode-abbrev-table)
- (setq major-mode 'message-mode)
- (setq mode-name "Message")
- (setq buffer-offer-save t)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(message-font-lock-keywords t))
- (make-local-variable 'facemenu-add-face-function)
- (make-local-variable 'facemenu-remove-face-function)
- (setq facemenu-add-face-function
- (lambda (face end)
- (let ((face-fun (cdr (assq face message-face-alist))))
- (if face-fun
- (funcall face-fun (point) end)
- (error "Face %s not configured for %s mode" face mode-name)))
- "")
- facemenu-remove-face-function t)
- (make-local-variable 'paragraph-separate)
- (make-local-variable 'paragraph-start)
- (setq paragraph-start (concat (regexp-quote mail-header-separator)
- "$\\|[ \t]*[-_][-_][-_]+$\\|"
- "-- $\\|"
- paragraph-start))
- (setq paragraph-separate (concat (regexp-quote mail-header-separator)
- "$\\|[ \t]*[-_][-_][-_]+$\\|"
- "-- $\\|"
- paragraph-separate))
- (make-local-variable 'message-reply-headers)
- (setq message-reply-headers nil)
- (make-local-variable 'message-newsreader)
- (make-local-variable 'message-mailer)
- (make-local-variable 'message-post-method)
- (make-local-variable 'message-sent-message-via)
- (setq message-sent-message-via nil)
- (make-local-variable 'message-checksum)
- (setq message-checksum nil)
- ;;(when (fboundp 'mail-hist-define-keys)
- ;; (mail-hist-define-keys))
- (when (string-match "XEmacs\\|Lucid" emacs-version)
- (message-setup-toolbar))
- (easy-menu-add message-mode-menu message-mode-map)
- (run-hooks 'text-mode-hook 'message-mode-hook))
-
-
-
-;;;
-;;; Message mode commands
-;;;
-
-;;; Movement commands
-
-(defun message-goto-to ()
- "Move point to the To header."
- (interactive)
- (message-position-on-field "To"))
-
-(defun message-goto-subject ()
- "Move point to the Subject header."
- (interactive)
- (message-position-on-field "Subject"))
-
-(defun message-goto-cc ()
- "Move point to the Cc header."
- (interactive)
- (message-position-on-field "Cc" "To"))
-
-(defun message-goto-bcc ()
- "Move point to the Bcc header."
- (interactive)
- (message-position-on-field "Bcc" "Cc" "To"))
-
-(defun message-goto-fcc ()
- "Move point to the Fcc header."
- (interactive)
- (message-position-on-field "Fcc" "To" "Newsgroups"))
-
-(defun message-goto-reply-to ()
- "Move point to the Reply-To header."
- (interactive)
- (message-position-on-field "Reply-To" "Subject"))
-
-(defun message-goto-newsgroups ()
- "Move point to the Newsgroups header."
- (interactive)
- (message-position-on-field "Newsgroups"))
-
-(defun message-goto-distribution ()
- "Move point to the Distribution header."
- (interactive)
- (message-position-on-field "Distribution"))
-
-(defun message-goto-followup-to ()
- "Move point to the Followup-To header."
- (interactive)
- (message-position-on-field "Followup-To" "Newsgroups"))
-
-(defun message-goto-keywords ()
- "Move point to the Keywords header."
- (interactive)
- (message-position-on-field "Keywords" "Subject"))
-
-(defun message-goto-summary ()
- "Move point to the Summary header."
- (interactive)
- (message-position-on-field "Summary" "Subject"))
-
-(defun message-goto-body ()
- "Move point to the beginning of the message body."
- (interactive)
- (if (looking-at "[ \t]*\n") (expand-abbrev))
- (goto-char (point-min))
- (search-forward (concat "\n" mail-header-separator "\n") nil t))
-
-(defun message-goto-signature ()
- "Move point to the beginning of the message signature."
- (interactive)
- (goto-char (point-min))
- (or (re-search-forward message-signature-separator nil t)
- (goto-char (point-max))))
-
-
-
-(defun message-insert-to ()
- "Insert a To header that points to the author of the article being replied to."
- (interactive)
- (when (and (message-position-on-field "To")
- (mail-fetch-field "to")
- (not (string-match "\\` *\\'" (mail-fetch-field "to"))))
- (insert ", "))
- (insert (or (message-fetch-reply-field "reply-to")
- (message-fetch-reply-field "from") "")))
-
-(defun message-insert-newsgroups ()
- "Insert the Newsgroups header from the article being replied to."
- (interactive)
- (when (and (message-position-on-field "Newsgroups")
- (mail-fetch-field "newsgroups")
- (not (string-match "\\` *\\'" (mail-fetch-field "newsgroups"))))
- (insert ","))
- (insert (or (message-fetch-reply-field "newsgroups") "")))
-
-
-
-;;; Various commands
-
-(defun message-insert-signature (&optional force)
- "Insert a signature. See documentation for the `message-signature' variable."
- (interactive (list 0))
- (let* ((signature
- (cond ((and (null message-signature)
- (eq force 0))
- (save-excursion
- (goto-char (point-max))
- (not (re-search-backward
- message-signature-separator nil t))))
- ((and (null message-signature)
- force)
- t)
- ((message-functionp message-signature)
- (funcall message-signature))
- ((listp message-signature)
- (eval message-signature))
- (t message-signature)))
- (signature
- (cond ((stringp signature)
- signature)
- ((and (eq t signature)
- message-signature-file
- (file-exists-p message-signature-file))
- signature))))
- (when signature
-; ;; Remove blank lines at the end of the message.
- (goto-char (point-max))
-; (skip-chars-backward " \t\n")
-; (delete-region (point) (point-max))
- ;; Insert the signature.
- (unless (bolp)
- (insert "\n"))
- (insert "\n-- \n")
- (if (eq signature t)
- (insert-file-contents message-signature-file)
- (insert signature))
- (goto-char (point-max))
- (or (bolp) (insert "\n")))))
-
-(defvar message-caesar-translation-table nil)
-
-(defun message-caesar-region (b e &optional n)
- "Caesar rotation of region by N, default 13, for decrypting netnews."
- (interactive
- (list
- (min (point) (or (mark t) (point)))
- (max (point) (or (mark t) (point)))
- (when current-prefix-arg
- (prefix-numeric-value current-prefix-arg))))
-
- (setq n (if (numberp n) (mod n 26) 13)) ;canonize N
- (unless (or (zerop n) ; no action needed for a rot of 0
- (= b e)) ; no region to rotate
- ;; We build the table, if necessary.
- (when (or (not message-caesar-translation-table)
- (/= (aref message-caesar-translation-table ?a) (+ ?a n)))
- (let ((i -1)
- (table (make-string 256 0)))
- (while (< (incf i) 256)
- (aset table i i))
- (setq table
- (concat
- (substring table 0 ?A)
- (substring table (+ ?A n) (+ ?A n (- 26 n)))
- (substring table ?A (+ ?A n))
- (substring table (+ ?A 26) ?a)
- (substring table (+ ?a n) (+ ?a n (- 26 n)))
- (substring table ?a (+ ?a n))
- (substring table (+ ?a 26) 255)))
- (setq message-caesar-translation-table table)))
- ;; Then we translate the region. Do it this way to retain
- ;; text properties.
- (while (< b e)
- (subst-char-in-region
- b (1+ b) (char-after b)
- (aref message-caesar-translation-table (char-after b)))
- (incf b))))
-
-(defun message-caesar-buffer-body (&optional rotnum)
- "Caesar rotates all letters in the current buffer by 13 places.
-Used to encode/decode possibly offensive messages (commonly in net.jokes).
-With prefix arg, specifies the number of places to rotate each letter forward.
-Mail and USENET news headers are not rotated."
- (interactive (if current-prefix-arg
- (list (prefix-numeric-value current-prefix-arg))
- (list nil)))
- (save-excursion
- (save-restriction
- (when (message-goto-body)
- (narrow-to-region (point) (point-max)))
- (message-caesar-region (point-min) (point-max) rotnum))))
-
-(defun message-rename-buffer (&optional enter-string)
- "Rename the *message* buffer to \"*message* RECIPIENT\".
-If the function is run with a prefix, it will ask for a new buffer
-name, rather than giving an automatic name."
- (interactive "Pbuffer name: ")
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (narrow-to-region (point)
- (search-forward mail-header-separator nil 'end))
- (let* ((mail-to (if (message-news-p) (message-fetch-field "Newsgroups")
- (message-fetch-field "To")))
- (mail-trimmed-to
- (if (string-match "," mail-to)
- (concat (substring mail-to 0 (match-beginning 0)) ", ...")
- mail-to))
- (name-default (concat "*message* " mail-trimmed-to))
- (name (if enter-string
- (read-string "New buffer name: " name-default)
- name-default)))
- (rename-buffer name t)))))
-
-(defun message-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)
- (let ((fill-prefix message-yank-prefix))
- (fill-individual-paragraphs (point) (point-max) justifyp t))))
-
-(defun message-indent-citation ()
- "Modify text just inserted from a message to be cited.
-The inserted text should be the region.
-When this function returns, the region is again around the modified text.
-
-Normally, indent each nonblank line `message-indentation-spaces' spaces.
-However, if `message-yank-prefix' is non-nil, insert that prefix on each line."
- (let ((start (point)))
- ;; Remove unwanted headers.
- (when message-ignored-cited-headers
- (save-restriction
- (narrow-to-region
- (goto-char start)
- (if (search-forward "\n\n" nil t)
- (1- (point))
- (point)))
- (message-remove-header message-ignored-cited-headers t)))
- ;; Do the indentation.
- (if (null message-yank-prefix)
- (indent-rigidly start (mark t) message-indentation-spaces)
- (save-excursion
- (goto-char start)
- (while (< (point) (mark t))
- (insert message-yank-prefix)
- (forward-line 1)))
- (goto-char start))))
-
-(defun message-yank-original (&optional arg)
- "Insert the message being replied to, if any.
-Puts point before the text and mark after.
-Normally indents each nonblank line ARG spaces (default 3). However,
-if `message-yank-prefix' is non-nil, insert that prefix on each line.
-
-This function uses `message-cite-function' to do the actual citing.
-
-Just \\[universal-argument] as argument means don't indent, insert no
-prefix, and don't delete any headers."
- (interactive "P")
- (let ((modified (buffer-modified-p)))
- (when (and message-reply-buffer
- message-cite-function)
- (delete-windows-on message-reply-buffer t)
- (insert-buffer message-reply-buffer)
- (funcall message-cite-function)
- (message-exchange-point-and-mark)
- (unless (bolp)
- (insert ?\n))
- (unless modified
- (setq message-checksum (cons (message-checksum) (buffer-size)))))))
-
-(defun message-cite-original ()
- (let ((start (point))
- (functions
- (when message-indent-citation-function
- (if (listp message-indent-citation-function)
- message-indent-citation-function
- (list message-indent-citation-function)))))
- (goto-char start)
- (while functions
- (funcall (pop functions)))
- (when message-citation-line-function
- (unless (bolp)
- (insert "\n"))
- (funcall message-citation-line-function))))
-
-(defun message-insert-citation-line ()
- "Function that inserts a simple citation line."
- (when message-reply-headers
- (insert (mail-header-from message-reply-headers) " writes:\n\n")))
-
-(defun message-position-on-field (header &rest afters)
- (let ((case-fold-search t))
- (save-restriction
- (narrow-to-region
- (goto-char (point-min))
- (progn
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$"))
- (match-beginning 0)))
- (goto-char (point-min))
- (if (re-search-forward (concat "^" (regexp-quote header) ":") nil t)
- (progn
- (re-search-forward "^[^ \t]" nil 'move)
- (beginning-of-line)
- (skip-chars-backward "\n")
- t)
- (while (and afters
- (not (re-search-forward
- (concat "^" (regexp-quote (car afters)) ":")
- nil t)))
- (pop afters))
- (when afters
- (re-search-forward "^[^ \t]" nil 'move)
- (beginning-of-line))
- (insert header ": \n")
- (forward-char -1)
- nil))))
-
-(defun message-remove-signature ()
- "Remove the signature from the text between point and mark.
-The text will also be indented the normal way."
- (save-excursion
- (let ((start (point))
- mark)
- (if (not (re-search-forward message-signature-separator (mark t) t))
- ;; No signature here, so we just indent the cited text.
- (message-indent-citation)
- ;; Find the last non-empty line.
- (forward-line -1)
- (while (looking-at "[ \t]*$")
- (forward-line -1))
- (forward-line 1)
- (setq mark (set-marker (make-marker) (point)))
- (goto-char start)
- (message-indent-citation)
- ;; Enable undoing the deletion.
- (undo-boundary)
- (delete-region mark (mark t))
- (set-marker mark nil)))))
-
-
-
-;;;
-;;; Sending messages
-;;;
-
-(defun message-send-and-exit (&optional arg)
- "Send message like `message-send', then, if no errors, exit from mail buffer."
- (interactive "P")
- (let ((buf (current-buffer))
- (actions message-exit-actions))
- (when (and (message-send arg)
- (buffer-name buf))
- (if message-kill-buffer-on-exit
- (kill-buffer buf)
- (bury-buffer buf)
- (when (eq buf (current-buffer))
- (message-bury buf)))
- (message-do-actions actions))))
-
-(defun message-dont-send ()
- "Don't send the message you have been editing."
- (interactive)
- (message-bury (current-buffer))
- (message-do-actions message-postpone-actions))
-
-(defun message-kill-buffer ()
- "Kill the current buffer."
- (interactive)
- (let ((actions message-kill-actions))
- (kill-buffer (current-buffer))
- (message-do-actions actions)))
-
-(defun message-bury (buffer)
- "Bury this mail buffer."
- (let ((newbuf (other-buffer buffer)))
- (bury-buffer buffer)
- (if (and (fboundp 'frame-parameters)
- (cdr (assq 'dedicated (frame-parameters)))
- (not (null (delq (selected-frame) (visible-frame-list)))))
- (delete-frame (selected-frame))
- (switch-to-buffer newbuf))))
-
-(defun message-send (&optional arg)
- "Send the message in the current buffer.
-If `message-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 "P")
- (when (if buffer-file-name
- (y-or-n-p (format "Send buffer contents as %s message? "
- (if (message-mail-p)
- (if (message-news-p) "mail and news" "mail")
- "news")))
- (or (buffer-modified-p)
- (y-or-n-p "No changes in the buffer; really send? ")))
- ;; Make it possible to undo the coming changes.
- (undo-boundary)
- (let ((inhibit-read-only t))
- (put-text-property (point-min) (point-max) 'read-only nil))
- (message-fix-before-sending)
- (run-hooks 'message-send-hook)
- (message "Sending...")
- (when (and (or (not (message-news-p))
- (and (or (not (memq 'news message-sent-message-via))
- (y-or-n-p
- "Already sent message via news; resend? "))
- (funcall message-send-news-function arg)))
- (or (not (message-mail-p))
- (and (or (not (memq 'mail message-sent-message-via))
- (y-or-n-p
- "Already sent message via mail; resend? "))
- (message-send-mail arg))))
- (message-do-fcc)
- ;;(when (fboundp 'mail-hist-put-headers-into-history)
- ;; (mail-hist-put-headers-into-history))
- (run-hooks 'message-sent-hook)
- (message "Sending...done")
- ;; If buffer has no file, mark it as unmodified and delete autosave.
- (unless buffer-file-name
- (set-buffer-modified-p nil)
- (delete-auto-save-file-if-necessary t))
- ;; Delete other mail buffers and stuff.
- (message-do-send-housekeeping)
- (message-do-actions message-send-actions)
- ;; Return success.
- t)))
-
-(defun message-fix-before-sending ()
- "Do various things to make the message nice before sending it."
- ;; Make sure there's a newline at the end of the message.
- (goto-char (point-max))
- (unless (bolp)
- (insert "\n")))
-
-(defun message-add-action (action &rest types)
- "Add ACTION to be performed when doing an exit of type TYPES."
- (let (var)
- (while types
- (set (setq var (intern (format "message-%s-actions" (pop types))))
- (nconc (symbol-value var) (list action))))))
-
-(defun message-do-actions (actions)
- "Perform all actions in ACTIONS."
- ;; Now perform actions on successful sending.
- (while actions
- (condition-case nil
- (cond
- ;; A simple function.
- ((message-functionp (car actions))
- (funcall (car actions)))
- ;; Something to be evaled.
- (t
- (eval (car actions))))
- (error))
- (pop actions)))
-
-(defun message-send-mail (&optional arg)
- (require 'mail-utils)
- (let ((tembuf (generate-new-buffer " message temp"))
- (case-fold-search nil)
- (news (message-news-p))
- (mailbuf (current-buffer)))
- (save-restriction
- (message-narrow-to-headers)
- ;; Insert some headers.
- (let ((message-deletable-headers
- (if news nil message-deletable-headers)))
- (message-generate-headers message-required-mail-headers))
- ;; Let the user do all of the above.
- (run-hooks 'message-header-hook))
- (unwind-protect
- (save-excursion
- (set-buffer tembuf)
- (erase-buffer)
- (insert-buffer-substring mailbuf)
- ;; Remove some headers.
- (save-restriction
- (message-narrow-to-headers)
- ;; Remove some headers.
- (message-remove-header message-ignored-mail-headers t))
- (goto-char (point-max))
- ;; require one newline at the end.
- (or (= (preceding-char) ?\n)
- (insert ?\n))
- (when (and news
- (or (message-fetch-field "cc")
- (message-fetch-field "to")))
- (message-insert-courtesy-copy))
- (funcall message-send-mail-function))
- (kill-buffer tembuf))
- (set-buffer mailbuf)
- (push 'mail message-sent-message-via)))
-
-(defun message-send-mail-with-sendmail ()
- "Send off the prepared buffer with sendmail."
- (let ((errbuf (if message-interactive
- (generate-new-buffer " sendmail errors")
- 0))
- resend-to-addresses delimline)
- (let ((case-fold-search t))
- (save-restriction
- (message-narrow-to-headers)
- (setq resend-to-addresses (message-fetch-field "resent-to")))
- ;; 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))
- ;; Insert an extra newline if we need it to work around
- ;; Sun's bug that swallows newlines.
- (goto-char (1+ delimline))
- (when (eval message-mailer-swallows-blank-line)
- (newline))
- (when message-interactive
- (save-excursion
- (set-buffer errbuf)
- (erase-buffer))))
- (let ((default-directory "/"))
- (apply 'call-process-region
- (append (list (point-min) (point-max)
- (if (boundp 'sendmail-program)
- sendmail-program
- "/usr/lib/sendmail")
- nil errbuf nil "-oi")
- ;; Always specify who from,
- ;; since some systems have broken sendmails.
- (list "-f" (user-login-name))
- ;; These mean "report errors by mail"
- ;; and "deliver in background".
- (if (null message-interactive) '("-oem" "-odb"))
- ;; Get the addresses from the message
- ;; unless this is a resend.
- ;; We must not do that for a resend
- ;; because we would find the original addresses.
- ;; For a resend, include the specific addresses.
- (if resend-to-addresses
- (list resend-to-addresses)
- '("-t")))))
- (when message-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)))))
- (when (bufferp errbuf)
- (kill-buffer errbuf)))))
-
-(defun message-send-mail-with-mh ()
- "Send the prepared message buffer with mh."
- (let ((mh-previous-window-config nil)
- (name (make-temp-name
- (concat (file-name-as-directory message-autosave-directory)
- "msg."))))
- (setq buffer-file-name name)
- (mh-send-letter)
- (condition-case ()
- (delete-file name)
- (error nil))))
-
-(defun message-send-news (&optional arg)
- (let ((tembuf (generate-new-buffer " *message temp*"))
- (case-fold-search nil)
- (method (if (message-functionp message-post-method)
- (funcall message-post-method arg)
- message-post-method))
- (messbuf (current-buffer))
- (message-syntax-checks
- (if arg
- (cons '(existing-newsgroups . disabled)
- message-syntax-checks)
- message-syntax-checks))
- result)
- (save-restriction
- (message-narrow-to-headers)
- ;; Insert some headers.
- (message-generate-headers message-required-news-headers)
- ;; Let the user do all of the above.
- (run-hooks 'message-header-hook))
- (message-cleanup-headers)
- (when (message-check-news-syntax)
- (unwind-protect
- (save-excursion
- (set-buffer tembuf)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert-buffer-substring messbuf)
- ;; Remove some headers.
- (save-restriction
- (message-narrow-to-headers)
- ;; Remove some headers.
- (message-remove-header message-ignored-news-headers t))
- (goto-char (point-max))
- ;; require one newline at the end.
- (or (= (preceding-char) ?\n)
- (insert ?\n))
- (let ((case-fold-search t))
- ;; Remove the delimeter.
- (goto-char (point-min))
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "\n"))
- (replace-match "\n")
- (backward-char 1))
- (require (car method))
- (funcall (intern (format "%s-open-server" (car method)))
- (cadr method) (cddr method))
- (setq result
- (funcall (intern (format "%s-request-post" (car method))))))
- (kill-buffer tembuf))
- (set-buffer messbuf)
- (if result
- (push 'news message-sent-message-via)
- (message "Couldn't send message via news: %s"
- (nnheader-get-report (car method)))
- nil))))
-
-;;;
-;;; Header generation & syntax checking.
-;;;
-
-(defun message-check-news-syntax ()
- "Check the syntax of the message."
- (and
- ;; We narrow to the headers and check them first.
- (save-excursion
- (save-restriction
- (message-narrow-to-headers)
- (and
- ;; Check for commands in Subject.
- (or
- (message-check-element 'subject-cmsg)
- (save-excursion
- (if (string-match "^cmsg " (message-fetch-field "subject"))
- (y-or-n-p
- "The control code \"cmsg \" is in the subject. Really post? ")
- t)))
- ;; Check for multiple identical headers.
- (or (message-check-element 'multiple-headers)
- (save-excursion
- (let (found)
- (while (and (not found)
- (re-search-forward "^[^ \t:]+: " nil t))
- (save-excursion
- (or (re-search-forward
- (concat "^" (setq found
- (buffer-substring
- (match-beginning 0)
- (- (match-end 0) 2))))
- nil t)
- (setq found nil))))
- (if found
- (y-or-n-p
- (format "Multiple %s headers. Really post? " found))
- t))))
- ;; Check for Version and Sendsys.
- (or (message-check-element 'sendsys)
- (save-excursion
- (if (re-search-forward "^Sendsys:\\|^Version:" nil t)
- (y-or-n-p
- (format "The article contains a %s command. Really post? "
- (buffer-substring (match-beginning 0)
- (1- (match-end 0)))))
- t)))
- ;; See whether we can shorten Followup-To.
- (or (message-check-element 'shorten-followup-to)
- (let ((newsgroups (message-fetch-field "newsgroups"))
- (followup-to (message-fetch-field "followup-to"))
- to)
- (when (and newsgroups (string-match "," newsgroups)
- (not followup-to)
- (not
- (zerop
- (length
- (setq to (completing-read
- "Followups to: (default all groups) "
- (mapcar (lambda (g) (list g))
- (cons "poster"
- (message-tokenize-header
- newsgroups)))))))))
- (goto-char (point-min))
- (insert "Followup-To: " to "\n"))
- t))
- ;; Check "Shoot me".
- (or (message-check-element 'shoot)
- (save-excursion
- (if (re-search-forward
- "Message-ID.*.i-have-a-misconfigured-system-so-shoot-me"
- nil t)
- (y-or-n-p
- "You appear to have a misconfigured system. Really post? ")
- t)))
- ;; Check for Approved.
- (or (message-check-element 'approved)
- (save-excursion
- (if (re-search-forward "^Approved:" nil t)
- (y-or-n-p
- "The article contains an Approved header. Really post? ")
- t)))
- ;; Check the Message-Id header.
- (or (message-check-element 'message-id)
- (save-excursion
- (let* ((case-fold-search t)
- (message-id (message-fetch-field "message-id")))
- (or (not message-id)
- (and (string-match "@" message-id)
- (string-match "@[^\\.]*\\." message-id))
- (y-or-n-p
- (format
- "The Message-ID looks strange: \"%s\". Really post? "
- message-id))))))
- ;; Check the Subject header.
- (or
- (message-check-element 'subject)
- (save-excursion
- (let* ((case-fold-search t)
- (subject (message-fetch-field "subject")))
- (or
- (and subject
- (not (string-match "\\`[ \t]*\\'" subject)))
- (progn
- (message
- "The subject field is empty or missing. Posting is denied.")
- nil)))))
- ;; Check the Newsgroups & Followup-To headers.
- (or
- (message-check-element 'existing-newsgroups)
- (let* ((case-fold-search t)
- (newsgroups (message-fetch-field "newsgroups"))
- (followup-to (message-fetch-field "followup-to"))
- (groups (message-tokenize-header
- (if followup-to
- (concat newsgroups "," followup-to)
- newsgroups)))
- (hashtb (and (boundp 'gnus-active-hashtb)
- gnus-active-hashtb))
- errors)
- (if (not hashtb)
- t
- (while groups
- (when (and (not (boundp (intern (car groups) hashtb)))
- (not (equal (car groups) "poster")))
- (push (car groups) errors))
- (pop groups))
- (if (not errors)
- t
- (y-or-n-p
- (format
- "Really post to %s unknown group%s: %s "
- (if (= (length errors) 1) "this" "these")
- (if (= (length errors) 1) "" "s")
- (mapconcat 'identity errors ", ")))))))
- ;; Check the Newsgroups & Followup-To headers for syntax errors.
- (or
- (message-check-element 'valid-newsgroups)
- (let ((case-fold-search t)
- (headers '("Newsgroups" "Followup-To"))
- header error)
- (while (and headers (not error))
- (when (setq header (mail-fetch-field (car headers)))
- (if (or
- (not
- (string-match
- "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-.a-zA-Z0-9]+\\)*\\'"
- header))
- (memq
- nil (mapcar
- (lambda (g)
- (not (string-match "\\.\\'\\|\\.\\." g)))
- (message-tokenize-header header ","))))
- (setq error t)))
- (unless error
- (pop headers)))
- (if (not error)
- t
- (y-or-n-p
- (format "The %s header looks odd: \"%s\". Really post? "
- (car headers) header)))))
- ;; Check the From header.
- (or
- (save-excursion
- (let* ((case-fold-search t)
- (from (message-fetch-field "from")))
- (cond
- ((not from)
- (message "There is no From line. Posting is denied.")
- nil)
- ((not (string-match "@[^\\.]*\\." from))
- (message
- "Denied posting -- the From looks strange: \"%s\"." from)
- nil)
- ((string-match "@[^@]*@" from)
- (message
- "Denied posting -- two \"@\"'s in the From header: %s." from)
- nil)
- ((string-match "(.*).*(.*)" from)
- (message
- "Denied posting -- the From header looks strange: \"%s\"."
- from)
- nil)
- (t t))))))))
- ;; Check for long lines.
- (or (message-check-element 'long-lines)
- (save-excursion
- (goto-char (point-min))
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$"))
- (while (and
- (progn
- (end-of-line)
- (< (current-column) 80))
- (zerop (forward-line 1))))
- (or (bolp)
- (eobp)
- (y-or-n-p
- "You have lines longer than 79 characters. Really post? "))))
- ;; Check whether the article is empty.
- (or (message-check-element 'empty)
- (save-excursion
- (goto-char (point-min))
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$"))
- (forward-line 1)
- (let ((b (point)))
- (or (re-search-forward message-signature-separator nil t)
- (goto-char (point-max)))
- (beginning-of-line)
- (or (re-search-backward "[^ \n\t]" b t)
- (y-or-n-p "Empty article. Really post? ")))))
- ;; Check for control characters.
- (or (message-check-element 'control-chars)
- (save-excursion
- (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t)
- (y-or-n-p
- "The article contains control characters. Really post? ")
- t)))
- ;; Check excessive size.
- (or (message-check-element 'size)
- (if (> (buffer-size) 60000)
- (y-or-n-p
- (format "The article is %d octets long. Really post? "
- (buffer-size)))
- t))
- ;; Check whether any new text has been added.
- (or (message-check-element 'new-text)
- (not message-checksum)
- (not (and (eq (message-checksum) (car message-checksum))
- (eq (buffer-size) (cdr message-checksum))))
- (y-or-n-p
- "It looks like no new text has been added. Really post? "))
- ;; Check the length of the signature.
- (or
- (message-check-element 'signature)
- (progn
- (goto-char (point-max))
- (if (or (not (re-search-backward "^-- $" nil t))
- (search-forward message-forward-end-separator nil t))
- t
- (if (> (count-lines (point) (point-max)) 5)
- (y-or-n-p
- (format
- "Your .sig is %d lines; it should be max 4. Really post? "
- (count-lines (point) (point-max))))
- t))))))
-
-(defun message-check-element (type)
- "Returns non-nil if this type is not to be checked."
- (if (eq message-syntax-checks 'dont-check-for-anything-just-trust-me)
- t
- (let ((able (assq type message-syntax-checks)))
- (and (consp able)
- (eq (cdr able) 'disabled)))))
-
-(defun message-checksum ()
- "Return a \"checksum\" for the current buffer."
- (let ((sum 0))
- (save-excursion
- (goto-char (point-min))
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$"))
- (while (not (eobp))
- (when (not (looking-at "[ \t\n]"))
- (setq sum (logxor (ash sum 1) (following-char))))
- (forward-char 1)))
- sum))
-
-(defun message-do-fcc ()
- "Process Fcc headers in the current buffer."
- (let ((case-fold-search t)
- (buf (current-buffer))
- list file)
- (save-excursion
- (set-buffer (get-buffer-create " *message temp*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert-buffer-substring buf)
- (save-restriction
- (message-narrow-to-headers)
- (while (setq file (message-fetch-field "fcc"))
- (push file list)
- (message-remove-header "fcc" nil t)))
- (goto-char (point-min))
- (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
- (replace-match "" t t)
- ;; Process FCC operations.
- (while list
- (setq file (pop list))
- (if (string-match "^[ \t]*|[ \t]*\\(.*\\)[ \t]*$" file)
- ;; Pipe the article to the program in question.
- (call-process-region (point-min) (point-max) shell-file-name
- nil nil nil shell-command-switch
- (match-string 1 file))
- ;; Save the article.
- (setq file (expand-file-name file))
- (unless (file-exists-p (file-name-directory file))
- (make-directory (file-name-directory file) t))
- (if (and message-fcc-handler-function
- (not (eq message-fcc-handler-function 'rmail-output)))
- (funcall message-fcc-handler-function file)
- (if (and (file-readable-p file) (mail-file-babyl-p file))
- (rmail-output file 1 nil t)
- (let ((mail-use-rfc822 t))
- (rmail-output file 1 t t))))))
- (kill-buffer (current-buffer)))))
-
-(defun message-cleanup-headers ()
- "Do various automatic cleanups of the headers."
- ;; Remove empty lines in the header.
- (save-restriction
- (message-narrow-to-headers)
- (while (re-search-forward "^[ \t]*\n" nil t)
- (replace-match "" t t)))
-
- ;; Correct Newsgroups and Followup-To headers: change sequence of
- ;; spaces to comma and eliminate spaces around commas. Eliminate
- ;; embedded line breaks.
- (goto-char (point-min))
- (while (re-search-forward "^\\(Newsgroups\\|Followup-To\\): +" nil t)
- (save-restriction
- (narrow-to-region
- (point)
- (if (re-search-forward "^[^ \t]" nil t)
- (match-beginning 0)
- (forward-line 1)
- (point)))
- (goto-char (point-min))
- (while (re-search-forward "\n[ \t]+" nil t)
- (replace-match " " t t)) ;No line breaks (too confusing)
- (goto-char (point-min))
- (while (re-search-forward "[ \t\n]*,[ \t\n]*\\|[ \t]+" nil t)
- (replace-match "," t t))
- (goto-char (point-min))
- ;; Remove trailing commas.
- (when (re-search-forward ",+$" nil t)
- (replace-match "" t t)))))
-
-(defun message-make-date ()
- "Make a valid data header."
- (let ((now (current-time)))
- (timezone-make-date-arpa-standard
- (current-time-string now) (current-time-zone now))))
-
-(defun message-make-message-id ()
- "Make a unique Message-ID."
- (concat "<" (message-unique-id)
- (let ((psubject (save-excursion (message-fetch-field "subject"))))
- (if (and message-reply-headers
- (mail-header-references message-reply-headers)
- (mail-header-subject message-reply-headers)
- psubject
- (mail-header-subject message-reply-headers)
- (not (string=
- (message-strip-subject-re
- (mail-header-subject message-reply-headers))
- (message-strip-subject-re psubject))))
- "_-_" ""))
- "@" (message-make-fqdn) ">"))
-
-(defvar message-unique-id-char nil)
-
-;; If you ever change this function, make sure the new version
-;; cannot generate IDs that the old version could.
-;; You might for example insert a "." somewhere (not next to another dot
-;; or string boundary), or modify the "fsf" string.
-(defun message-unique-id ()
- ;; Don't use microseconds from (current-time), they may be unsupported.
- ;; Instead we use this randomly inited counter.
- (setq message-unique-id-char
- (% (1+ (or message-unique-id-char (logand (random t) (1- (lsh 1 20)))))
- ;; (current-time) returns 16-bit ints,
- ;; and 2^16*25 just fits into 4 digits i base 36.
- (* 25 25)))
- (let ((tm (current-time)))
- (concat
- (if (memq system-type '(ms-dos emx vax-vms))
- (let ((user (downcase (user-login-name))))
- (while (string-match "[^a-z0-9_]" user)
- (aset user (match-beginning 0) ?_))
- user)
- (message-number-base36 (user-uid) -1))
- (message-number-base36 (+ (car tm)
- (lsh (% message-unique-id-char 25) 16)) 4)
- (message-number-base36 (+ (nth 1 tm)
- (lsh (/ message-unique-id-char 25) 16)) 4)
- ;; Append the newsreader name, because while the generated
- ;; ID is unique to this newsreader, other newsreaders might
- ;; otherwise generate the same ID via another algorithm.
- ".fsf")))
-
-(defun message-number-base36 (num len)
- (if (if (< len 0) (<= num 0) (= len 0))
- ""
- (concat (message-number-base36 (/ num 36) (1- len))
- (char-to-string (aref "zyxwvutsrqponmlkjihgfedcba9876543210"
- (% num 36))))))
-
-(defun message-make-organization ()
- "Make an Organization header."
- (let* ((organization
- (or (getenv "ORGANIZATION")
- (when message-user-organization
- (if (message-functionp message-user-organization)
- (funcall message-user-organization)
- message-user-organization)))))
- (save-excursion
- (message-set-work-buffer)
- (cond ((stringp organization)
- (insert organization))
- ((and (eq t organization)
- message-user-organization-file
- (file-exists-p message-user-organization-file))
- (insert-file-contents message-user-organization-file)))
- (goto-char (point-min))
- (while (re-search-forward "[\t\n]+" nil t)
- (replace-match "" t t))
- (unless (zerop (buffer-size))
- (buffer-string)))))
-
-(defun message-make-lines ()
- "Count the number of lines and return numeric string."
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (re-search-forward
- (concat "^" (regexp-quote mail-header-separator) "$"))
- (forward-line 1)
- (int-to-string (count-lines (point) (point-max))))))
-
-(defun message-make-in-reply-to ()
- "Return the In-Reply-To header for this message."
- (when message-reply-headers
- (let ((from (mail-header-from message-reply-headers))
- (date (mail-header-date message-reply-headers)))
- (when from
- (let ((stop-pos
- (string-match " *at \\| *@ \\| *(\\| *<" from)))
- (concat (if stop-pos (substring from 0 stop-pos) from)
- "'s message of "
- (if (or (not date) (string= date ""))
- "(unknown date)" date)))))))
-
-(defun message-make-distribution ()
- "Make a Distribution header."
- (let ((orig-distribution (message-fetch-reply-field "distribution")))
- (cond ((message-functionp message-distribution-function)
- (funcall message-distribution-function))
- (t orig-distribution))))
-
-(defun message-make-expires ()
- "Return an Expires header based on `message-expires'."
- (let ((current (current-time))
- (future (* 1.0 message-expires 60 60 24)))
- ;; Add the future to current.
- (setcar current (+ (car current) (round (/ future (expt 2 16)))))
- (setcar (cdr current) (+ (nth 1 current) (% (round future) (expt 2 16))))
- ;; Return the date in the future in UT.
- (timezone-make-date-arpa-standard
- (current-time-string current) (current-time-zone current) '(0 "UT"))))
-
-(defun message-make-path ()
- "Return uucp path."
- (let ((login-name (user-login-name)))
- (cond ((null message-user-path)
- (concat (system-name) "!" login-name))
- ((stringp message-user-path)
- ;; Support GENERICPATH. Suggested by vixie@decwrl.dec.com.
- (concat message-user-path "!" login-name))
- (t login-name))))
-
-(defun message-make-from ()
- "Make a From header."
- (let* ((login (message-make-address))
- (fullname
- (or (and (boundp 'user-full-name)
- user-full-name)
- (user-full-name))))
- (when (string= fullname "&")
- (setq fullname (user-login-name)))
- (save-excursion
- (message-set-work-buffer)
- (cond
- ((or (null message-from-style)
- (equal fullname ""))
- (insert login))
- ((or (eq message-from-style 'angles)
- (and (not (eq message-from-style 'parens))
- ;; Use angles if no quoting is needed, or if parens would
- ;; need quoting too.
- (or (not (string-match "[^- !#-'*+/-9=?A-Z^-~]" fullname))
- (let ((tmp (concat fullname nil)))
- (while (string-match "([^()]*)" tmp)
- (aset tmp (match-beginning 0) ?-)
- (aset tmp (1- (match-end 0)) ?-))
- (string-match "[\\()]" tmp)))))
- (insert fullname)
- (goto-char (point-min))
- ;; Look for a character that cannot appear unquoted
- ;; according to RFC 822.
- (when (re-search-forward "[^- !#-'*+/-9=?A-Z^-~]" nil 1)
- ;; Quote fullname, escaping specials.
- (goto-char (point-min))
- (insert "\"")
- (while (re-search-forward "[\"\\]" nil 1)
- (replace-match "\\\\\\&" t))
- (insert "\""))
- (insert " <" login ">"))
- (t ; 'parens or default
- (insert login " (")
- (let ((fullname-start (point)))
- (insert fullname)
- (goto-char fullname-start)
- ;; RFC 822 says \ and nonmatching parentheses
- ;; must be escaped in comments.
- ;; Escape every instance of ()\ ...
- (while (re-search-forward "[()\\]" nil 1)
- (replace-match "\\\\\\&" t))
- ;; ... then undo escaping of matching parentheses,
- ;; including matching nested parentheses.
- (goto-char fullname-start)
- (while (re-search-forward
- "\\(\\=\\|[^\\]\\(\\\\\\\\\\)*\\)\\\\(\\(\\([^\\]\\|\\\\\\\\\\)*\\)\\\\)"
- nil 1)
- (replace-match "\\1(\\3)" t)
- (goto-char fullname-start)))
- (insert ")")))
- (buffer-string))))
-
-(defun message-make-sender ()
- "Return the \"real\" user address.
-This function tries to ignore all user modifications, and
-give as trustworthy answer as possible."
- (concat (user-login-name) "@" (system-name)))
-
-(defun message-make-address ()
- "Make the address of the user."
- (or (message-user-mail-address)
- (concat (user-login-name) "@" (message-make-domain))))
-
-(defun message-user-mail-address ()
- "Return the pertinent part of `user-mail-address'."
- (when user-mail-address
- (nth 1 (mail-extract-address-components user-mail-address))))
-
-(defun message-make-fqdn ()
- "Return user's fully qualified domain name."
- (let ((system-name (system-name))
- (user-mail (message-user-mail-address)))
- (cond
- ((string-match "[^.]\\.[^.]" system-name)
- ;; `system-name' returned the right result.
- system-name)
- ;; Try `mail-host-address'.
- ((and (boundp 'mail-host-address)
- (stringp mail-host-address)
- (string-match "\\." mail-host-address))
- mail-host-address)
- ;; We try `user-mail-address' as a backup.
- ((and (string-match "\\." user-mail)
- (string-match "@\\(.*\\)\\'" user-mail))
- (match-string 1 user-mail))
- ;; Default to this bogus thing.
- (t
- (concat system-name ".i-have-a-misconfigured-system-so-shoot-me")))))
-
-(defun message-make-host-name ()
- "Return the name of the host."
- (let ((fqdn (message-make-fqdn)))
- (string-match "^[^.]+\\." fqdn)
- (substring fqdn 0 (1- (match-end 0)))))
-
-(defun message-make-domain ()
- "Return the domain name."
- (or mail-host-address
- (message-make-fqdn)))
-
-(defun message-generate-headers (headers)
- "Prepare article HEADERS.
-Headers already prepared in the buffer are not modified."
- (save-restriction
- (message-narrow-to-headers)
- (let* ((Date (message-make-date))
- (Message-ID (message-make-message-id))
- (Organization (message-make-organization))
- (From (message-make-from))
- (Path (message-make-path))
- (Subject nil)
- (Newsgroups nil)
- (In-Reply-To (message-make-in-reply-to))
- (To nil)
- (Distribution (message-make-distribution))
- (Lines (message-make-lines))
- (X-Newsreader message-newsreader)
- (X-Mailer (and (not (message-fetch-field "X-Newsreader"))
- message-mailer))
- (Expires (message-make-expires))
- (case-fold-search t)
- header value elem)
- ;; First we remove any old generated headers.
- (let ((headers message-deletable-headers))
- (while headers
- (goto-char (point-min))
- (and (re-search-forward
- (concat "^" (symbol-name (car headers)) ": *") nil t)
- (get-text-property (1+ (match-beginning 0)) 'message-deletable)
- (message-delete-line))
- (pop headers)))
- ;; Go through all the required headers and see if they are in the
- ;; articles already. If they are not, or are empty, they are
- ;; inserted automatically - except for Subject, Newsgroups and
- ;; Distribution.
- (while headers
- (goto-char (point-min))
- (setq elem (pop headers))
- (if (consp elem)
- (if (eq (car elem) 'optional)
- (setq header (cdr elem))
- (setq header (car elem)))
- (setq header elem))
- (when (or (not (re-search-forward
- (concat "^" (downcase (symbol-name header)) ":")
- nil t))
- (progn
- ;; The header was found. We insert a space after the
- ;; colon, if there is none.
- (if (/= (following-char) ? ) (insert " ") (forward-char 1))
- ;; Find out whether the header is empty...
- (looking-at "[ \t]*$")))
- ;; So we find out what value we should insert.
- (setq value
- (cond
- ((and (consp elem) (eq (car elem) 'optional))
- ;; This is an optional header. If the cdr of this
- ;; is something that is nil, then we do not insert
- ;; this header.
- (setq header (cdr elem))
- (or (and (fboundp (cdr elem)) (funcall (cdr elem)))
- (and (boundp (cdr elem)) (symbol-value (cdr elem)))))
- ((consp elem)
- ;; The element is a cons. Either the cdr is a
- ;; string to be inserted verbatim, or it is a
- ;; function, and we insert the value returned from
- ;; this function.
- (or (and (stringp (cdr elem)) (cdr elem))
- (and (fboundp (cdr elem)) (funcall (cdr elem)))))
- ((and (boundp header) (symbol-value header))
- ;; The element is a symbol. We insert the value
- ;; of this symbol, if any.
- (symbol-value header))
- (t
- ;; We couldn't generate a value for this header,
- ;; so we just ask the user.
- (read-from-minibuffer
- (format "Empty header for %s; enter value: " header)))))
- ;; Finally insert the header.
- (when (and value
- (not (equal value "")))
- (save-excursion
- (if (bolp)
- (progn
- ;; This header didn't exist, so we insert it.
- (goto-char (point-max))
- (insert (symbol-name header) ": " value "\n")
- (forward-line -1))
- ;; The value of this header was empty, so we clear
- ;; totally and insert the new value.
- (delete-region (point) (message-point-at-eol))
- (insert value))
- ;; Add the deletable property to the headers that require it.
- (and (memq header message-deletable-headers)
- (progn (beginning-of-line) (looking-at "[^:]+: "))
- (add-text-properties
- (point) (match-end 0)
- '(message-deletable t face italic) (current-buffer)))))))
- ;; Insert new Sender if the From is strange.
- (let ((from (message-fetch-field "from"))
- (sender (message-fetch-field "sender"))
- (secure-sender (message-make-sender)))
- (when (and from
- (not (message-check-element 'sender))
- (not (string=
- (downcase
- (cadr (mail-extract-address-components from)))
- (downcase secure-sender)))
- (or (null sender)
- (not
- (string=
- (downcase
- (cadr (mail-extract-address-components sender)))
- (downcase secure-sender)))))
- (goto-char (point-min))
- ;; Rename any old Sender headers to Original-Sender.
- (when (re-search-forward "^Sender:" nil t)
- (beginning-of-line)
- (insert "Original-")
- (beginning-of-line))
- (insert "Sender: " secure-sender "\n"))))))
-
-(defun message-insert-courtesy-copy ()
- "Insert a courtesy message in mail copies of combined messages."
- (save-excursion
- (save-restriction
- (message-narrow-to-headers)
- (let ((newsgroups (message-fetch-field "newsgroups")))
- (when newsgroups
- (goto-char (point-max))
- (insert "Posted-To: " newsgroups "\n"))))
- (forward-line 1)
- (insert message-courtesy-message)))
-
-;;;
-;;; Setting up a message buffer
-;;;
-
-(defun message-fill-address (header value)
- (save-restriction
- (narrow-to-region (point) (point))
- (insert (capitalize (symbol-name header))
- ": "
- (if (consp value) (car value) value)
- "\n")
- (narrow-to-region (point-min) (1- (point-max)))
- (let (quoted last)
- (goto-char (point-min))
- (while (not (eobp))
- (skip-chars-forward "^,\"" (point-max))
- (if (or (= (following-char) ?,)
- (eobp))
- (when (not quoted)
- (if (and (> (current-column) 78)
- last)
- (progn
- (save-excursion
- (goto-char last)
- (insert "\n\t"))
- (setq last (1+ (point))))
- (setq last (1+ (point)))))
- (setq quoted (not quoted)))
- (unless (eobp)
- (forward-char 1))))
- (goto-char (point-max))
- (widen)
- (forward-line 1)))
-
-(defun message-fill-header (header value)
- (let ((begin (point))
- (fill-column 78)
- (fill-prefix "\t"))
- (insert (capitalize (symbol-name header))
- ": "
- (if (consp value) (car value) value)
- "\n")
- (save-restriction
- (narrow-to-region begin (point))
- (fill-region-as-paragraph begin (point))
- ;; Tapdance around looong Message-IDs.
- (forward-line -1)
- (when (looking-at "[ \t]*$")
- (message-delete-line))
- (goto-char begin)
- (re-search-forward ":" nil t)
- (when (looking-at "\n[ \t]+")
- (replace-match " " t t))
- (goto-char (point-max)))))
-
-(defun message-position-point ()
- "Move point to where the user probably wants to find it."
- (message-narrow-to-headers)
- (cond
- ((re-search-forward "^[^:]+:[ \t]*$" nil t)
- (search-backward ":" )
- (widen)
- (forward-char 1)
- (if (= (following-char) ? )
- (forward-char 1)
- (insert " ")))
- (t
- (goto-char (point-max))
- (widen)
- (forward-line 1)
- (unless (looking-at "$")
- (forward-line 2)))
- (sit-for 0)))
-
-(defun message-buffer-name (type &optional to group)
- "Return a new (unique) buffer name based on TYPE and TO."
- (cond
- ;; Check whether `message-generate-new-buffers' is a function,
- ;; and if so, call it.
- ((message-functionp message-generate-new-buffers)
- (funcall message-generate-new-buffers type to group))
- ;; Generate a new buffer name The Message Way.
- (message-generate-new-buffers
- (generate-new-buffer-name
- (concat "*" type
- (if to
- (concat " to "
- (or (car (mail-extract-address-components to))
- to) "")
- "")
- (if (and group (not (string= group ""))) (concat " on " group) "")
- "*")))
- ;; Use standard name.
- (t
- (format "*%s message*" type))))
-
-(defun message-pop-to-buffer (name)
- "Pop to buffer NAME, and warn if it already exists and is modified."
- (let ((buffer (get-buffer name)))
- (if (and buffer
- (buffer-name buffer))
- (progn
- (set-buffer (pop-to-buffer buffer))
- (when (and (buffer-modified-p)
- (not (y-or-n-p
- "Message already being composed; erase? ")))
- (error "Message being composed")))
- (set-buffer (pop-to-buffer name))))
- (erase-buffer)
- (message-mode))
-
-(defun message-do-send-housekeeping ()
- "Kill old message buffers."
- ;; We might have sent this buffer already. Delete it from the
- ;; list of buffers.
- (setq message-buffer-list (delq (current-buffer) message-buffer-list))
- (when (and message-max-buffers
- (>= (length message-buffer-list) message-max-buffers))
- ;; Kill the oldest buffer -- unless it has been changed.
- (let ((buffer (pop message-buffer-list)))
- (when (and (buffer-name buffer)
- (not (buffer-modified-p buffer)))
- (kill-buffer buffer))))
- ;; Rename the buffer.
- (if message-send-rename-function
- (funcall message-send-rename-function)
- (when (string-match "\\`\\*" (buffer-name))
- (rename-buffer
- (concat "*sent " (substring (buffer-name) (match-end 0))) t)))
- ;; Push the current buffer onto the list.
- (when message-max-buffers
- (setq message-buffer-list
- (nconc message-buffer-list (list (current-buffer))))))
-
-(defvar mc-modes-alist)
-(defun message-setup (headers &optional replybuffer actions)
- (when (and (boundp 'mc-modes-alist)
- (not (assq 'message-mode mc-modes-alist)))
- (push '(message-mode (encrypt . mc-encrypt-message)
- (sign . mc-sign-message))
- mc-modes-alist))
- (when actions
- (setq message-send-actions actions))
- (setq message-reply-buffer replybuffer)
- (goto-char (point-min))
- ;; Insert all the headers.
- (mail-header-format
- (let ((h headers)
- (alist message-header-format-alist))
- (while h
- (unless (assq (caar h) message-header-format-alist)
- (push (list (caar h)) alist))
- (pop h))
- alist)
- headers)
- (delete-region (point) (progn (forward-line -1) (point)))
- (when message-default-headers
- (insert message-default-headers))
- (put-text-property
- (point)
- (progn
- (insert mail-header-separator "\n")
- (1- (point)))
- 'read-only nil)
- (forward-line -1)
- (when (message-news-p)
- (when message-default-news-headers
- (insert message-default-news-headers))
- (when message-generate-headers-first
- (message-generate-headers
- (delq 'Lines
- (delq 'Subject
- (copy-sequence message-required-news-headers))))))
- (when (message-mail-p)
- (when message-default-mail-headers
- (insert message-default-mail-headers))
- (when message-generate-headers-first
- (message-generate-headers
- (delq 'Lines
- (delq 'Subject
- (copy-sequence message-required-mail-headers))))))
- (run-hooks 'message-signature-setup-hook)
- (message-insert-signature)
- (message-set-auto-save-file-name)
- (save-restriction
- (message-narrow-to-headers)
- (run-hooks 'message-header-setup-hook))
- (set-buffer-modified-p nil)
- (run-hooks 'message-setup-hook)
- (message-position-point)
- (undo-boundary))
-
-(defun message-set-auto-save-file-name ()
- "Associate the message buffer with a file in the drafts directory."
- (when message-autosave-directory
- (unless (file-exists-p message-autosave-directory)
- (make-directory message-autosave-directory t))
- (let ((name (make-temp-name
- (concat (file-name-as-directory message-autosave-directory)
- "msg."))))
- (setq buffer-auto-save-file-name
- (save-excursion
- (prog1
- (progn
- (set-buffer (get-buffer-create " *draft tmp*"))
- (setq buffer-file-name name)
- (make-auto-save-file-name))
- (kill-buffer (current-buffer)))))
- (clear-visited-file-modtime))))
-
-
-
-;;;
-;;; Commands for interfacing with message
-;;;
-
-;;;###autoload
-(defun message-mail (&optional to subject)
- "Start editing a mail message to be sent."
- (interactive)
- (message-pop-to-buffer (message-buffer-name "mail" to))
- (message-setup `((To . ,(or to "")) (Subject . ,(or subject "")))))
-
-;;;###autoload
-(defun message-news (&optional newsgroups subject)
- "Start editing a news article to be sent."
- (interactive)
- (message-pop-to-buffer (message-buffer-name "news" nil newsgroups))
- (message-setup `((Newsgroups . ,(or newsgroups ""))
- (Subject . ,(or subject "")))))
-
-;;;###autoload
-(defun message-reply (&optional to-address wide ignore-reply-to)
- "Start editing a reply to the article in the current buffer."
- (interactive)
- (let ((cur (current-buffer))
- from subject date reply-to to cc
- references message-id follow-to
- mct never-mct gnus-warning)
- (save-restriction
- (narrow-to-region
- (goto-char (point-min))
- (if (search-forward "\n\n" nil t)
- (1- (point))
- (point-max)))
- ;; Allow customizations to have their say.
- (if (not wide)
- ;; This is a regular reply.
- (if (message-functionp message-reply-to-function)
- (setq follow-to (funcall message-reply-to-function)))
- ;; This is a followup.
- (if (message-functionp message-wide-reply-to-function)
- (save-excursion
- (setq follow-to
- (funcall message-wide-reply-to-function)))))
- ;; Find all relevant headers we need.
- (setq from (message-fetch-field "from")
- date (message-fetch-field "date")
- subject (or (message-fetch-field "subject") "none")
- to (message-fetch-field "to")
- cc (message-fetch-field "cc")
- mct (message-fetch-field "mail-copies-to")
- reply-to (unless ignore-reply-to (message-fetch-field "reply-to"))
- references (message-fetch-field "references")
- message-id (message-fetch-field "message-id"))
- ;; Remove any (buggy) Re:'s that are present and make a
- ;; proper one.
- (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject)
- (setq subject (substring subject (match-end 0))))
- (setq subject (concat "Re: " subject))
-
- (when (and (setq gnus-warning (message-fetch-field "gnus-warning"))
- (string-match "<[^>]+>" gnus-warning))
- (setq message-id (match-string 0 gnus-warning)))
-
- ;; Handle special values of Mail-Copies-To.
- (when mct
- (cond ((equal (downcase mct) "never")
- (setq never-mct t)
- (setq mct nil))
- ((equal (downcase mct) "always")
- (setq mct (or reply-to from)))))
-
- (unless follow-to
- (if (or (not wide)
- to-address)
- (setq follow-to (list (cons 'To (or to-address reply-to from))))
- (let (ccalist)
- (save-excursion
- (message-set-work-buffer)
- (unless never-mct
- (insert (or reply-to from "")))
- (insert
- (if (bolp) "" ", ") (or to "")
- (if mct (concat (if (bolp) "" ", ") mct) "")
- (if cc (concat (if (bolp) "" ", ") cc) ""))
- ;; Remove addresses that match `rmail-dont-reply-to-names'.
- (insert (prog1 (rmail-dont-reply-to (buffer-string))
- (erase-buffer)))
- (goto-char (point-min))
- (setq ccalist
- (mapcar
- (lambda (addr)
- (cons (mail-strip-quoted-names addr) addr))
- (nreverse (mail-parse-comma-list))))
- (let ((s ccalist))
- (while s
- (setq ccalist (delq (assoc (car (pop s)) s) ccalist)))))
- (setq follow-to (list (cons 'To (cdr (pop ccalist)))))
- (when ccalist
- (push (cons 'Cc
- (mapconcat (lambda (addr) (cdr addr)) ccalist ", "))
- follow-to)))))
- (widen))
-
- (message-pop-to-buffer (message-buffer-name
- (if wide "wide reply" "reply") from
- (if wide to-address nil)))
-
- (setq message-reply-headers
- (vector 0 subject from date message-id references 0 0 ""))
-
- (message-setup
- `((Subject . ,subject)
- ,@follow-to
- ,@(if (or references message-id)
- `((References . ,(concat (or references "") (and references " ")
- (or message-id ""))))
- nil))
- cur)))
-
-;;;###autoload
-(defun message-wide-reply (&optional to-address)
- (interactive)
- (message-reply to-address t))
-
-;;;###autoload
-(defun message-followup ()
- (interactive)
- (let ((cur (current-buffer))
- from subject date reply-to mct
- references message-id follow-to
- followup-to distribution newsgroups gnus-warning)
- (save-restriction
- (narrow-to-region
- (goto-char (point-min))
- (if (search-forward "\n\n" nil t)
- (1- (point))
- (point-max)))
- (when (message-functionp message-followup-to-function)
- (setq follow-to
- (funcall message-followup-to-function)))
- (setq from (message-fetch-field "from")
- date (message-fetch-field "date")
- subject (or (message-fetch-field "subject") "none")
- references (message-fetch-field "references")
- message-id (message-fetch-field "message-id")
- followup-to (message-fetch-field "followup-to")
- newsgroups (message-fetch-field "newsgroups")
- reply-to (message-fetch-field "reply-to")
- distribution (message-fetch-field "distribution")
- mct (message-fetch-field "mail-copies-to"))
- (when (and (setq gnus-warning (message-fetch-field "gnus-warning"))
- (string-match "<[^>]+>" gnus-warning))
- (setq message-id (match-string 0 gnus-warning)))
- ;; Remove bogus distribution.
- (and (stringp distribution)
- (string-match "world" distribution)
- (setq distribution nil))
- ;; Remove any (buggy) Re:'s that are present and make a
- ;; proper one.
- (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject)
- (setq subject (substring subject (match-end 0))))
- (setq subject (concat "Re: " subject))
- (widen))
-
- (message-pop-to-buffer (message-buffer-name "followup" from newsgroups))
-
- (message-setup
- `((Subject . ,subject)
- ,@(cond
- (follow-to follow-to)
- ((and followup-to message-use-followup-to)
- (list
- (cond
- ((equal (downcase followup-to) "poster")
- (if (or (eq message-use-followup-to 'use)
- (message-y-or-n-p "Obey Followup-To: poster? " t "\
-You should normally obey the Followup-To: header.
-
-`Followup-To: poster' sends your response via e-mail instead of news.
-
-A typical situation where `Followup-To: poster' is used is when the poster
-does not read the newsgroup, so he wouldn't see any replies sent to it."))
- (cons 'To (or reply-to from ""))
- (cons 'Newsgroups newsgroups)))
- (t
- (if (or (equal followup-to newsgroups)
- (not (eq message-use-followup-to 'ask))
- (message-y-or-n-p
- (concat "Obey Followup-To: " followup-to "? ") t "\
-You should normally obey the Followup-To: header.
-
- `Followup-To: " followup-to "'
-directs your response to " (if (string-match "," followup-to)
- "the specified newsgroups"
- "that newsgroup only") ".
-
-If a message is posted to several newsgroups, Followup-To is often
-used to direct the following discussion to one newsgroup only,
-because discussions that are spread over several newsgroup tend to
-be fragmented and very difficult to follow.
-
-Also, some source/announcment newsgroups are not indented for discussion;
-responses here are directed to other newsgroups."))
- (cons 'Newsgroups followup-to)
- (cons 'Newsgroups newsgroups))))))
- (t
- `((Newsgroups . ,newsgroups))))
- ,@(and distribution (list (cons 'Distribution distribution)))
- (References . ,(concat (or references "") (and references " ")
- (or message-id "")))
- ,@(when (and mct
- (not (equal (downcase mct) "never")))
- (list (cons 'Cc (if (equal (downcase mct) "always")
- (or reply-to from "")
- mct)))))
-
- cur)
-
- (setq message-reply-headers
- (vector 0 subject from date message-id references 0 0 ""))))
-
-
-;;;###autoload
-(defun message-cancel-news ()
- "Cancel an article you posted."
- (interactive)
- (unless (message-news-p)
- (error "This is not a news article; canceling is impossible"))
- (when (yes-or-no-p "Do you really want to cancel this article? ")
- (let (from newsgroups message-id distribution buf)
- (save-excursion
- ;; Get header info. from original article.
- (save-restriction
- (message-narrow-to-head)
- (setq from (message-fetch-field "from")
- newsgroups (message-fetch-field "newsgroups")
- message-id (message-fetch-field "message-id")
- distribution (message-fetch-field "distribution")))
- ;; Make sure that this article was written by the user.
- (unless (string-equal
- (downcase (cadr (mail-extract-address-components from)))
- (downcase (message-make-address)))
- (error "This article is not yours"))
- ;; Make control message.
- (setq buf (set-buffer (get-buffer-create " *message cancel*")))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert "Newsgroups: " newsgroups "\n"
- "From: " (message-make-from) "\n"
- "Subject: cmsg cancel " message-id "\n"
- "Control: cancel " message-id "\n"
- (if distribution
- (concat "Distribution: " distribution "\n")
- "")
- mail-header-separator "\n"
- "This is a cancel message from " from ".\n")
- (message "Canceling your article...")
- (let ((message-syntax-checks 'dont-check-for-anything-just-trust-me))
- (funcall message-send-news-function))
- (message "Canceling your article...done")
- (kill-buffer buf)))))
-
-;;;###autoload
-(defun message-supersede ()
- "Start composing a message to supersede the current message.
-This is done simply by taking the old article and adding a Supersedes
-header line with the old Message-ID."
- (interactive)
- (let ((cur (current-buffer)))
- ;; Check whether the user owns the article that is to be superseded.
- (unless (string-equal
- (downcase (cadr (mail-extract-address-components
- (message-fetch-field "from"))))
- (downcase (message-make-address)))
- (error "This article is not yours"))
- ;; Get a normal message buffer.
- (message-pop-to-buffer (message-buffer-name "supersede"))
- (insert-buffer-substring cur)
- (message-narrow-to-head)
- ;; Remove unwanted headers.
- (when message-ignored-supersedes-headers
- (message-remove-header message-ignored-supersedes-headers t))
- (goto-char (point-min))
- (if (not (re-search-forward "^Message-ID: " nil t))
- (error "No Message-ID in this article")
- (replace-match "Supersedes: " t t))
- (goto-char (point-max))
- (insert mail-header-separator)
- (widen)
- (forward-line 1)))
-
-;;;###autoload
-(defun message-recover ()
- "Reread contents of current buffer from its last auto-save file."
- (interactive)
- (let ((file-name (make-auto-save-file-name)))
- (cond ((save-window-excursion
- (if (not (eq system-type 'vax-vms))
- (with-output-to-temp-buffer "*Directory*"
- (buffer-disable-undo standard-output)
- (let ((default-directory "/"))
- (call-process
- "ls" nil standard-output nil "-l" file-name))))
- (yes-or-no-p (format "Recover auto save file %s? " file-name)))
- (let ((buffer-read-only nil))
- (erase-buffer)
- (insert-file-contents file-name nil)))
- (t (error "message-recover cancelled")))))
-
-;;; Forwarding messages.
-
-(defun message-make-forward-subject ()
- "Return a Subject header suitable for the message in the current buffer."
- (concat "[" (or (message-fetch-field (if (message-news-p) "newsgroups" "from"))
- "(nowhere)")
- "] " (or (message-fetch-field "Subject") "")))
-
-;;;###autoload
-(defun message-forward (&optional news)
- "Forward the current message via mail.
-Optional NEWS will use news to forward instead of mail."
- (interactive "P")
- (let ((cur (current-buffer))
- (subject (message-make-forward-subject)))
- (if news (message-news nil subject) (message-mail nil subject))
- ;; Put point where we want it before inserting the forwarded
- ;; message.
- (if message-signature-before-forwarded-message
- (goto-char (point-max))
- (message-goto-body))
- ;; Make sure we're at the start of the line.
- (unless (eolp)
- (insert "\n"))
- ;; Narrow to the area we are to insert.
- (narrow-to-region (point) (point))
- ;; Insert the separators and the forwarded buffer.
- (insert message-forward-start-separator)
- (insert-buffer-substring cur)
- (goto-char (point-max))
- (insert message-forward-end-separator)
- (set-text-properties (point-min) (point-max) nil)
- ;; Remove all unwanted headers.
- (goto-char (point-min))
- (forward-line 1)
- (narrow-to-region (point) (if (search-forward "\n\n" nil t)
- (1- (point))
- (point)))
- (goto-char (point-min))
- (message-remove-header message-included-forward-headers t nil t)
- (widen)
- (message-position-point)))
-
-;;;###autoload
-(defun message-resend (address)
- "Resend the current article to ADDRESS."
- (interactive "sResend message to: ")
- (save-excursion
- (let ((cur (current-buffer))
- beg)
- ;; We first set up a normal mail buffer.
- (set-buffer (get-buffer-create " *message resend*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (message-setup `((To . ,address)))
- ;; Insert our usual headers.
- (message-generate-headers '(From Date To))
- (message-narrow-to-headers)
- ;; Rename them all to "Resent-*".
- (while (re-search-forward "^[A-Za-z]" nil t)
- (forward-char -1)
- (insert "Resent-"))
- (widen)
- (forward-line)
- (delete-region (point) (point-max))
- (setq beg (point))
- ;; Insert the message to be resent.
- (insert-buffer-substring cur)
- (goto-char (point-min))
- (search-forward "\n\n")
- (forward-char -1)
- (save-restriction
- (narrow-to-region beg (point))
- (message-remove-header message-ignored-resent-headers t)
- (goto-char (point-max)))
- (insert mail-header-separator)
- ;; Rename all old ("Also-")Resent headers.
- (while (re-search-backward "^\\(Also-\\)?Resent-" beg t)
- (beginning-of-line)
- (insert "Also-"))
- ;; Send it.
- (message-send-mail)
- (kill-buffer (current-buffer)))))
-
-;;;###autoload
-(defun message-bounce ()
- "Re-mail the current message.
-This only makes sense if the current message is a bounce message than
-contains some mail you have written which has been bounced back to
-you."
- (interactive)
- (let ((cur (current-buffer))
- boundary)
- (message-pop-to-buffer (message-buffer-name "bounce"))
- (insert-buffer-substring cur)
- (undo-boundary)
- (message-narrow-to-head)
- (if (and (message-fetch-field "Mime-Version")
- (setq boundary (message-fetch-field "Content-Type")))
- (if (string-match "boundary=\"\\([^\"]+\\)\"" boundary)
- (setq boundary (concat (match-string 1 boundary) " *\n"
- "Content-Type: message/rfc822"))
- (setq boundary nil)))
- (widen)
- (goto-char (point-min))
- (search-forward "\n\n" nil t)
- (or (and boundary
- (re-search-forward boundary nil t)
- (forward-line 2))
- (and (re-search-forward message-unsent-separator nil t)
- (forward-line 1))
- (and (search-forward "\n\n" nil t)
- (re-search-forward "^Return-Path:.*\n" nil t)))
- ;; We remove everything before the bounced mail.
- (delete-region
- (point-min)
- (if (re-search-forward "^[^ \n\t]+:" nil t)
- (match-beginning 0)
- (point)))
- (save-restriction
- (message-narrow-to-head)
- (message-remove-header message-ignored-bounced-headers t)
- (goto-char (point-max))
- (insert mail-header-separator))
- (message-position-point)))
-
-;;;
-;;; Interactive entry points for new message buffers.
-;;;
-
-;;;###autoload
-(defun message-mail-other-window (&optional to subject)
- "Like `message-mail' command, but display mail buffer in another window."
- (interactive)
- (let ((pop-up-windows t)
- (special-display-buffer-names nil)
- (special-display-regexps nil)
- (same-window-buffer-names nil)
- (same-window-regexps nil))
- (message-pop-to-buffer (message-buffer-name "mail" to)))
- (message-setup `((To . ,(or to "")) (Subject . ,(or subject "")))))
-
-;;;###autoload
-(defun message-mail-other-frame (&optional to subject)
- "Like `message-mail' command, but display mail buffer in another frame."
- (interactive)
- (let ((pop-up-frames t)
- (special-display-buffer-names nil)
- (special-display-regexps nil)
- (same-window-buffer-names nil)
- (same-window-regexps nil))
- (message-pop-to-buffer (message-buffer-name "mail" to)))
- (message-setup `((To . ,(or to "")) (Subject . ,(or subject "")))))
-
-;;;###autoload
-(defun message-news-other-window (&optional newsgroups subject)
- "Start editing a news article to be sent."
- (interactive)
- (let ((pop-up-windows t)
- (special-display-buffer-names nil)
- (special-display-regexps nil)
- (same-window-buffer-names nil)
- (same-window-regexps nil))
- (message-pop-to-buffer (message-buffer-name "news" nil newsgroups)))
- (message-setup `((Newsgroups . ,(or newsgroups ""))
- (Subject . ,(or subject "")))))
-
-;;;###autoload
-(defun message-news-other-frame (&optional newsgroups subject)
- "Start editing a news article to be sent."
- (interactive)
- (let ((pop-up-frames t)
- (special-display-buffer-names nil)
- (special-display-regexps nil)
- (same-window-buffer-names nil)
- (same-window-regexps nil))
- (message-pop-to-buffer (message-buffer-name "news" nil newsgroups)))
- (message-setup `((Newsgroups . ,(or newsgroups ""))
- (Subject . ,(or subject "")))))
-
-;;; underline.el
-
-;; This code should be moved to underline.el (from which it is stolen).
-
-;;;###autoload
-(defun bold-region (start end)
- "Bold all nonblank characters in the region.
-Works by overstriking characters.
-Called from program, takes two arguments START and END
-which specify the range to operate on."
- (interactive "r")
- (save-excursion
- (let ((end1 (make-marker)))
- (move-marker end1 (max start end))
- (goto-char (min start end))
- (while (< (point) end1)
- (or (looking-at "[_\^@- ]")
- (insert (following-char) "\b"))
- (forward-char 1)))))
-
-;;;###autoload
-(defun unbold-region (start end)
- "Remove all boldness (overstruck characters) in the region.
-Called from program, takes two arguments START and END
-which specify the range to operate on."
- (interactive "r")
- (save-excursion
- (let ((end1 (make-marker)))
- (move-marker end1 (max start end))
- (goto-char (min start end))
- (while (re-search-forward "\b" end1 t)
- (if (eq (following-char) (char-after (- (point) 2)))
- (delete-char -2))))))
-
-(fset 'message-exchange-point-and-mark 'exchange-point-and-mark)
-
-;; Support for toolbar
-(when (string-match "XEmacs\\|Lucid" emacs-version)
- (require 'messagexmas))
-
-;;; Group name completion.
-
-(defvar message-newgroups-header-regexp
- "^\\(Newsgroups\\|Followup-To\\|Posted-To\\):"
- "Regexp that match headers that lists groups.")
-
-(defun message-tab ()
- "Expand group names in Newsgroups and Followup-To headers.
-Do a `tab-to-tab-stop' if not in those headers."
- (interactive)
- (if (let ((mail-abbrev-mode-regexp message-newgroups-header-regexp))
- (mail-abbrev-in-expansion-header-p))
- (message-expand-group)
- (tab-to-tab-stop)))
-
-(defvar gnus-active-hashtb)
-(defun message-expand-group ()
- (let* ((b (save-excursion (skip-chars-backward "^, :\t\n") (point)))
- (completion-ignore-case t)
- (string (buffer-substring b (point)))
- (hashtb (and (boundp 'gnus-active-hashtb) gnus-active-hashtb))
- (completions (all-completions string hashtb))
- (cur (current-buffer))
- comp)
- (delete-region b (point))
- (cond
- ((= (length completions) 1)
- (if (string= (car completions) string)
- (progn
- (insert string)
- (message "Only matching group"))
- (insert (car completions))))
- ((and (setq comp (try-completion string hashtb))
- (not (string= comp string)))
- (insert comp))
- (t
- (insert string)
- (if (not comp)
- (message "No matching groups")
- (pop-to-buffer "*Completions*")
- (buffer-disable-undo (current-buffer))
- (let ((buffer-read-only nil))
- (erase-buffer)
- (let ((standard-output (current-buffer)))
- (display-completion-list (sort completions 'string<)))
- (goto-char (point-min))
- (pop-to-buffer cur)))))))
-
-(run-hooks 'message-load-hook)
-
-(provide 'message)
-
-;;; message.el ends here
diff --git a/lisp/misc.el b/lisp/misc.el
deleted file mode 100644
index fa480144074..00000000000
--- a/lisp/misc.el
+++ /dev/null
@@ -1,58 +0,0 @@
-;;; misc.el --- basic editing commands for Emacs
-
-;; Copyright (C) 1989 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(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)))
-
-;;; misc.el ends here
diff --git a/lisp/mldrag.el b/lisp/mldrag.el
deleted file mode 100644
index 45a10c2e18c..00000000000
--- a/lisp/mldrag.el
+++ /dev/null
@@ -1,228 +0,0 @@
-;;; mldrag.el --- mode line and vertical line dragging to resize windows
-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-
-;; Author: Kyle E. Jones <kyle@wonderworks.com>
-;; Keywords: mouse
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package lets you drag the modeline, vertical bar and
-;; scrollbar to resize windows. Suggested bindings are:
-;;
-;; (global-set-key [mode-line down-mouse-1] 'mldrag-drag-mode-line)
-;; (global-set-key [vertical-line down-mouse-1] 'mldrag-drag-vertical-line)
-;; (global-set-key [vertical-scroll-bar S-down-mouse-1]
-;; 'mldrag-drag-vertical-line)
-;;
-;; Put the bindings and (require 'mldrag) in your .emacs file.
-
-;;; Code:
-
-(provide 'mldrag)
-
-(defun mldrag-drag-mode-line (start-event)
- "Change the height of the current window with the mouse.
-This command should be bound to a down-mouse- event, and is most
-usefully bound with the `mode-line' prefix. Holding down a mouse
-button and moving the mouse up and down will make the clicked-on
-window taller or shorter."
- (interactive "e")
- (let ((done nil)
- (echo-keystrokes 0)
- (start-event-frame (window-frame (car (car (cdr start-event)))))
- (start-event-window (car (car (cdr start-event))))
- (start-nwindows (count-windows t))
- (old-selected-window (selected-window))
- should-enlarge-minibuffer
- event mouse minibuffer y top bot edges wconfig params growth)
- (setq params (frame-parameters))
- (if (and (not (setq minibuffer (cdr (assq 'minibuffer params))))
- (one-window-p t))
- (error "Attempt to resize sole window"))
- (unwind-protect
- (track-mouse
- (progn
- ;; enlarge-window only works on the selected window, so
- ;; we must select the window where the start event originated.
- ;; unwind-protect will restore the old selected window later.
- (select-window start-event-window)
- ;; if this is the bottommost ordinary window, then to
- ;; move its modeline the minibuffer must be enlarged.
- (setq should-enlarge-minibuffer
- (and minibuffer
- (not (one-window-p t))
- (= (nth 1 (window-edges minibuffer))
- (nth 3 (window-edges)))))
- ;; loop reading events and sampling the position of
- ;; the mouse.
- (while (not done)
- (setq event (read-event)
- mouse (mouse-position))
- ;; do nothing if
- ;; - there is a switch-frame event.
- ;; - the mouse isn't in the frame that we started in
- ;; - the mouse isn't in any Emacs frame
- ;; drag if
- ;; - there is a mouse-movement event
- ;; - there is a scroll-bar-movement event
- ;; (same as mouse movement for our purposes)
- ;; quit if
- ;; - there is a keyboard event or some other unknown event
- ;; unknown event.
- (cond ((integerp event)
- (setq done t))
- ((eq (car event) 'switch-frame)
- nil)
- ((not (memq (car event)
- '(mouse-movement scroll-bar-movement)))
- (setq done t))
- ((not (eq (car mouse) start-event-frame))
- nil)
- ((null (car (cdr mouse)))
- nil)
- (t
- (setq y (cdr (cdr mouse))
- edges (window-edges)
- top (nth 1 edges)
- bot (nth 3 edges))
- ;; scale back a move that would make the
- ;; window too short.
- (cond ((< (- y top -1) window-min-height)
- (setq y (+ top window-min-height -1))))
- ;; compute size change needed
- (setq growth (- y bot -1)
- wconfig (current-window-configuration))
- ;; grow/shrink minibuffer?
- (if should-enlarge-minibuffer
- (progn
- ;; yes. briefly select minibuffer so
- ;; enlarge-window will affect the
- ;; correct window.
- (select-window minibuffer)
- ;; scale back shrinkage if it would
- ;; make the minibuffer less than 1
- ;; line tall.
- (if (and (> growth 0)
- (< (- (window-height minibuffer)
- growth)
- 1))
- (setq growth (1- (window-height minibuffer))))
- (enlarge-window (- growth))
- (select-window start-event-window))
- ;; no. grow/shrink the selected window
- (enlarge-window growth))
- ;; if this window's growth caused another
- ;; window to be deleted because it was too
- ;; short, rescind the change.
- ;;
- ;; if size change caused space to be stolen
- ;; from a window above this one, rescind the
- ;; change, but only if we didn't grow/srhink
- ;; the minibuffer. minibuffer size changes
- ;; can cause all windows to shrink... no way
- ;; around it.
- (if (or (/= start-nwindows (count-windows t))
- (and (not should-enlarge-minibuffer)
- (/= top (nth 1 (window-edges)))))
- (set-window-configuration wconfig)))))))
- ;; restore the old selected window
- (select-window old-selected-window))))
-
-(defun mldrag-drag-vertical-line (start-event)
- "Change the width of the current window with the mouse.
-This command should be bound to a down-mouse- event, and is most
-usefully bound with the `vertical-line' or the `vertical-scroll-bar'
-prefix. Holding down a mouse button and moving the mouse left and
-right will make the clicked-on window thinner or wider."
- (interactive "e")
- (let ((done nil)
- (echo-keystrokes 0)
- (start-event-frame (window-frame (car (car (cdr start-event)))))
- (start-event-window (car (car (cdr start-event))))
- (start-nwindows (count-windows t))
- (old-selected-window (selected-window))
- event mouse x left right edges wconfig growth)
- (if (one-window-p t)
- (error "Attempt to resize sole ordinary window"))
- (if (= (nth 2 (window-edges start-event-window))
- (frame-width start-event-frame))
- (error "Attempt to drag rightmost scrollbar"))
- (unwind-protect
- (track-mouse
- (progn
- ;; enlarge-window only works on the selected window, so
- ;; we must select the window where the start event originated.
- ;; unwind-protect will restore the old selected window later.
- (select-window start-event-window)
- ;; loop reading events and sampling the position of
- ;; the mouse.
- (while (not done)
- (setq event (read-event)
- mouse (mouse-position))
- ;; do nothing if
- ;; - there is a switch-frame event.
- ;; - the mouse isn't in the frame that we started in
- ;; - the mouse isn't in any Emacs frame
- ;; drag if
- ;; - there is a mouse-movement event
- ;; - there is a scroll-bar-movement event
- ;; (same as mouse movement for our purposes)
- ;; quit if
- ;; - there is a keyboard event or some other unknown event
- ;; unknown event.
- (cond ((integerp event)
- (setq done t))
- ((eq (car event) 'switch-frame)
- nil)
- ((not (memq (car event)
- '(mouse-movement scroll-bar-movement)))
- (setq done t))
- ((not (eq (car mouse) start-event-frame))
- nil)
- ((null (car (cdr mouse)))
- nil)
- (t
- (setq x (car (cdr mouse))
- edges (window-edges)
- left (nth 0 edges)
- right (nth 2 edges))
- ;; scale back a move that would make the
- ;; window too thin.
- (cond ((< (- x left -1) window-min-width)
- (setq x (+ left window-min-width -1))))
- ;; compute size change needed
- (setq growth (- x right -1)
- wconfig (current-window-configuration))
- (enlarge-window growth t)
- ;; if this window's growth caused another
- ;; window to be deleted because it was too
- ;; thin, rescind the change.
- ;;
- ;; if size change caused space to be stolen
- ;; from a window to the left of this one,
- ;; rescind the change.
- (if (or (/= start-nwindows (count-windows t))
- (/= left (nth 0 (window-edges))))
- (set-window-configuration wconfig)))))))
- ;; restore the old selected window
- (select-window old-selected-window))))
-
-;; mldrag.el ends here
diff --git a/lisp/mouse-copy.el b/lisp/mouse-copy.el
deleted file mode 100644
index 56043ef3269..00000000000
--- a/lisp/mouse-copy.el
+++ /dev/null
@@ -1,249 +0,0 @@
-;;; mouse-copy.el -- one-click text copy and move
-
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: John Heidemann <johnh@ISI.EDU>
-;; Keywords: mouse
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; What is ``mouse-copy.el''?
-;;;
-;;; It provides one-click text copy and move. Rather than the
-;;; standard stroke-out-a-region (down-mouse-1, up-mouse-1) followed
-;;; by a yank (down-mouse-2, up-mouse-2 or C-y), you can now stroke
-;;; out a region and have it automatically pasted at the current
-;;; point. You can also move text just as easily. Although the
-;;; difference may not sound like much, it does make mousing text
-;;; around a lot easier, IMHO.
-;;;
-;;; If you like mouse-copy, you should also check out mouse-drag
-;;; for ``one-click scrolling''.
-;;;
-;;; To use mouse-copy, place the following in your .emacs file:
-;;; (require 'mouse-copy)
-;;; (global-set-key [M-down-mouse-1] 'mouse-drag-secondary-pasting)
-;;; (global-set-key [M-S-down-mouse-1] 'mouse-drag-secondary-moving)
-;;;
-;;; (These definitions override the old binding of M-mouse-1 to
-;;; mouse-drag-secondary. I find I don't use that command much so its
-;;; loss is not important, and it can be made up with a M-mouse-1
-;;; followed by a M-mouse-3. I personally reserve M-mouse bindings
-;;; for my window manager and bind everything to C-mouse.)
-;;;
-;;;
-;;; History and related work:
-;;;
-;;; One-click copying and moving was inspired by lemacs-19.8.
-;;; Throw-scrolling was inspired by MacPaint's ``hand'' and by Tk's
-;;; mouse-2 scrolling. The package mouse-scroll.el by Tom Wurgler
-;;; <twurgler@goodyear.com> is similar to mouse-drag-throw, but
-;;; doesn't pass clicks through.
-;;;
-;;; These functions have been tested in emacs version 19.30,
-;;; and this package has run in the past on 19.25-19.29.
-;;;
-;;; Originally mouse-copy was part of a larger package.
-;;; As of 11 July 96 the scrolling functions were split out
-;;; in preparation for incorporation into (the future) emacs-19.32.
-;;;
-;;;
-;;; Known Bugs:
-;;;
-;;; - Highlighting is sub-optimal under 19.29 and XFree86-3.1.1
-;;; (see \\[mouse-copy-work-around-drag-bug] for details).
-;;; - mouse-drag-secondary-pasting and mouse-drag-secondary-moving
-;;; require X11R5 (or better) and so fail under older versions
-;;; of Open Windows (like that present in Solaris/x86 2.1).
-;;;
-;;;
-;;; Future plans:
-;;;
-;;; I read about the chording features of Plan-9's Acme environment at
-;;; <http://swifty.dap.csiro.au/%7Ecameron/wily/auug.html>. I'd like
-;;; to incorporate some of these ideas into mouse-copy. The only
-;;; lose is that this is not the current Emacs Way Of Doing Things, so
-;;; there would be a learning curve for existing emacs users.
-;;;
-;;;
-;;; Thanks:
-;;;
-;;; Thanks to Kai Grossjohann
-;;; <grossjoh@dusty.informatik.uni-dortmund.de> for reporting bugs, to
-;;; Tom Wurgler <twurgler@goodyear.com> for reporting bugs and
-;;; suggesting fixes, and to Joel Graber <jgraber@ti.com> for
-;;; prompting me to do drag-scrolling and for an initial
-;;; implementation of horizontal drag-scrolling.
-;;;
-;;; -johnh, 11-Jul-96
-;;;
-;;;
-;;; Old changes, for reference:
-;;;
-;;; What's new with mouse-copy 2.22?
-;;;
-;;; - copy functions split out from mouse-extras.el
-;;; - support for emacs-19.{29,30,31} (no changes needed for the 31 port!)
-;;;
-;;;
-;;; What's new with mouse-extras 2.21?
-;;;
-;;; - support for emacs-19.{29,30}
-;;; - point now stays on the visible screen during horizontal scrolling
-;;; (bug identified and fix suggested by Tom Wurgler <twurgler@goodyear.com>)
-;;; - better work-around for lost-mouse-events bug (supports double/triple
-;;; clicks), see \\[mouse-extras-work-around-drag-bug] for details.
-;;; - work-around for lost-mouse-events bug now is OFF by default;
-;;; enable it if you have problems
-;;;
-
-
-
-;;; Code:
-
-;;
-;; move/paste code
-;;
-
-(defvar mouse-copy-last-paste-start nil
- "Internal to `mouse-drag-secondary-pasting'.")
-(defvar mouse-copy-last-paste-end nil
- "Internal to `mouse-drag-secondary-pasting'.")
-
-(defvar mouse-copy-have-drag-bug nil
- "Set to enable mouse-copy-work-around-drag-bug.
-See `mouse-copy-work-around-drag-bug' for details.")
-
-(defun mouse-copy-work-around-drag-bug (start-event end-event)
- "Code to work around a bug in post-19.29 emacs: it drops mouse-drag events.
-The problem occurs under XFree86-3.1.1 (X11R6pl11) but not under X11R5,
-and under post-19.29 but not early versions of emacs.
-
-19.29 and 19.30 seems to drop mouse drag events
-sometimes. (Reproducable under XFree86-3.1.1 (X11R6pl11) and
-XFree86-3.1.2 under Linux 1.2.x. Doesn't occur under X11R5 and SunOS
-4.1.1.)
-
-To see if you have the problem:
-Disable this routine (with (setq mouse-copy-have-drag-bug nil))..
-Click and drag for a while.
-If highlighting stops tracking, you have the bug.
-If you have the bug (or the real fix :-), please let me know."
-
- ;; To work-around, call mouse-set-secondary with a fake
- ;; drag event to set the overlay,
- ;; the load the x-selection.
- (save-excursion
- (let*
- ((start-posn (event-start start-event))
- (end-posn (event-end end-event))
- (end-buffer (window-buffer (posn-window end-posn)))
- ;; First, figure out the region (left as point/mark).
- (range (progn
- (set-buffer end-buffer)
- (mouse-start-end (posn-point start-posn)
- (posn-point end-posn)
- (1- (event-click-count start-event)))))
- (beg (car range))
- (end (car (cdr range))))
- ;; Second, set the overlay.
- (if mouse-secondary-overlay
- (move-overlay mouse-secondary-overlay beg end)
- (setq mouse-secondary-overlay (make-overlay beg (posn-point end))))
- (overlay-put mouse-secondary-overlay 'face 'secondary-selection)
- ;; Third, set the selection.
- ;; (setq me-beg beg me-end end me-range range) ; for debugging
- (set-buffer end-buffer)
- (x-set-selection 'SECONDARY (buffer-substring beg end)))))
-
-
-(defun mouse-drag-secondary-pasting (start-event)
- "Drag out a secondary selection, then paste it at the current point.
-
-To test this function, evaluate:
- (global-set-key [M-down-mouse-1] 'mouse-drag-secondary-pasting)
-put the point at one place, then click and drag over some other region."
- (interactive "e")
- ;; Work-around: We see and react to each part of a multi-click event
- ;; as it proceeds. For a triple-event, this means the double-event
- ;; has already copied something that the triple-event will re-copy
- ;; (a Bad Thing). We therefore undo the prior insertion if we're on
- ;; a multiple event.
- (if (and mouse-copy-last-paste-start
- (>= (event-click-count start-event) 2))
- (delete-region mouse-copy-last-paste-start
- mouse-copy-last-paste-end))
-
- ;; HACK: We assume that mouse-drag-secondary returns nil if
- ;; there's no secondary selection. This assumption holds as of
- ;; emacs-19.22 but is not documented. It's not clear that there's
- ;; any other way to get this information.
- (if (mouse-drag-secondary start-event)
- (progn
- (if mouse-copy-have-drag-bug
- (mouse-copy-work-around-drag-bug start-event last-input-event))
- ;; Remember what we do so we can undo it, if necessary.
- (setq mouse-copy-last-paste-start (point))
- (insert (x-get-selection 'SECONDARY))
- (setq mouse-copy-last-paste-end (point)))
- (setq mouse-copy-last-paste-start nil)))
-
-
-(defun mouse-kill-preserving-secondary ()
- "Kill the text in the secondary selection, but leave the selection set.
-
-This command is like \\[mouse-kill-secondary] (that is, the secondary
-selection is deleted and placed in the kill ring), except that it also
-leaves the secondary buffer active on exit.
-
-This command was derived from mouse-kill-secondary in emacs-19.28
-by johnh@ficus.cs.ucla.edu."
- (interactive)
- (let* ((keys (this-command-keys))
- (click (elt keys (1- (length keys)))))
- (or (eq (overlay-buffer mouse-secondary-overlay)
- (if (listp click)
- (window-buffer (posn-window (event-start click)))
- (current-buffer)))
- (error "Select or click on the buffer where the secondary selection is")))
- (save-excursion
- (set-buffer (overlay-buffer mouse-secondary-overlay))
- (kill-region (overlay-start mouse-secondary-overlay)
- (overlay-end mouse-secondary-overlay)))
- ;; (delete-overlay mouse-secondary-overlay)
- ;; (x-set-selection 'SECONDARY nil)
- ;; (setq mouse-secondary-overlay nil)
-)
-
-(defun mouse-drag-secondary-moving (start-event)
- "Sweep out a secondary selection, then move it to the current point."
- (interactive "e")
- ;; HACK: We assume that mouse-drag-secondary returns nil if
- ;; there's no secondary selection. This works as of emacs-19.22.
- ;; It's not clear that there's any other way to get this information.
- (if (mouse-drag-secondary start-event)
- (progn
- (mouse-kill-preserving-secondary)
- (insert (x-get-selection 'SECONDARY))))
-)
-
-(provide 'mouse-copy)
-
-;;; mouse-copy.el ends here
diff --git a/lisp/mouse-drag.el b/lisp/mouse-drag.el
deleted file mode 100644
index 6a5b7c4d216..00000000000
--- a/lisp/mouse-drag.el
+++ /dev/null
@@ -1,345 +0,0 @@
-;;; mouse-drag.el -- use mouse-2 to do a new style of scrolling
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: John Heidemann <johnh@ISI.EDU>
-;; Keywords: mouse
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; What is ``mouse-drag.el''?
-;;;
-;;; Doesn't that scroll bar seem far away when you want to scroll?
-;;; This module overloads mouse-2 to do ``throw'' scrolling. You
-;;; click and drag. The distance you move from your original click
-;;; turns into a scroll amount. The scroll amount is scaled
-;;; exponentially to make both large moves and short adjustments easy.
-;;; What this boils down to is that you can easily scroll around the
-;;; buffer without much mouse movement. Finally, clicks which aren't
-;;; drags are passed off to the old mouse-2 binding, so old mouse-2
-;;; operations (find-file in dired-mode, yanking in most other modes)
-;;; still work.
-;;;
-;;; There is an alternative way to scroll, ``drag'' scrolling. You
-;;; can click on a character and then drag it around, scrolling the
-;;; buffer with you. The character always stays under the mouse.
-;;; Compared to throw-scrolling, this approach provides direct
-;;; manipulation (nice) but requires more mouse movement
-;;; (unfortunate). It is offered as an alternative for those who
-;;; prefer it.
-;;;
-;;; If you like mouse-drag, you should also check out mouse-copy
-;;; for ``one-click text copy and move''.
-;;;
-;;; To use mouse-drag, place the following in your .emacs file:
-;;; (require 'mouse-drag)
-;;; -and either-
-;;; (global-set-key [down-mouse-2] 'mouse-drag-throw)
-;;; -or-
-;;; (global-set-key [down-mouse-2] 'mouse-drag-drag)
-;;;
-;;;
-;;;
-;;; Options:
-;;;
-;;; - reverse the throw-scroll direction with \\[mouse-throw-with-scroll-bar]
-;;; - work around a bug with \\[mouse-extras-work-around-drag-bug]
-;;;
-;;;
-;;; History and related work:
-;;;
-;;; One-click copying and moving was inspired by lemacs-19.8.
-;;; Throw-scrolling was inspired by MacPaint's ``hand'' and by Tk's
-;;; mouse-2 scrolling. The package mouse-scroll.el by Tom Wurgler
-;;; <twurgler@goodyear.com> is similar to mouse-drag-throw, but
-;;; doesn't pass clicks through.
-;;;
-;;; These functions have been tested in emacs version 19.30,
-;;; and this package has run in the past on 19.25-19.29.
-;;;
-;;; Originally mouse-drag was part of a larger package.
-;;; As of 11 July 96 the scrolling functions were split out
-;;; in preparation for incorporation into (the future) emacs-19.32.
-;;;
-;;;
-;;; Thanks:
-;;;
-;;; Thanks to Kai Grossjohann
-;;; <grossjoh@dusty.informatik.uni-dortmund.de> for reporting bugs, to
-;;; Tom Wurgler <twurgler@goodyear.com> for reporting bugs and
-;;; suggesting fixes, and to Joel Graber <jgraber@ti.com> for
-;;; prompting me to do drag-scrolling and for an initial
-;;; implementation of horizontal drag-scrolling.
-;;;
-;;; -johnh@isi.edu, 11-Jul-96
-;;;
-;;;
-;;; Old changes, for reference:
-;;;
-;;; What's new with mouse-extras 2.21?
-;;;
-;;; - support for emacs-19.{29,30}
-;;; - point now stays on the visible screen during horizontal scrolling
-;;; (bug identified and fix suggested by Tom Wurgler <twurgler@goodyear.com>)
-;;; - better work-around for lost-mouse-events bug (supports double/triple
-;;; clicks), see \\[mouse-extras-work-around-drag-bug] for details.
-;;; - work-around for lost-mouse-events bug now is OFF by default;
-;;; enable it if you have problems
-;;;
-
-
-
-;;; Code:
-
-;;
-;; scrolling code
-;;
-
-(defun mouse-drag-safe-scroll (row-delta &optional col-delta)
- "* Scroll down ROW-DELTA lines and right COL-DELTA, ignoring buffer edge errors.
-Keep the cursor on the screen as needed."
- (if (and row-delta
- (/= 0 row-delta))
- (condition-case nil ;; catch and ignore movement errors
- (scroll-down row-delta)
- (beginning-of-buffer (message "Beginning of buffer"))
- (end-of-buffer (message "End of buffer"))))
- (if (and col-delta
- (/= 0 col-delta))
- (progn
- (scroll-right col-delta)
- ;; Make sure that the point stays on the visible screen
- ;; (if truncation-lines in set).
- ;; This code mimics the behavior we automatically get
- ;; when doing vertical scrolling.
- ;; Problem identified and a fix suggested by Tom Wurgler.
- (cond
- ((< (current-column) (window-hscroll))
- (move-to-column (window-hscroll))) ; make on left column
- ((> (- (current-column) (window-hscroll) (window-width) -2) 0)
- (move-to-column (+ (window-width) (window-hscroll) -3)))))))
-
-(defun mouse-drag-repeatedly-safe-scroll (row-delta &optional col-delta)
- "* Scroll ROW-DELTA rows and COL-DELTA cols until an event happens."
- (while (sit-for mouse-scroll-delay)
- (mouse-drag-safe-scroll row-delta col-delta)))
-
-(defun mouse-drag-events-are-point-events-p (start-posn end-posn)
- "* Determine if START-POSN and END-POSN are \"close\"."
- (let*
- ((start-col-row (posn-col-row start-posn))
- (end-col-row (posn-col-row end-posn)))
- (and
-;; We no longer exclude things by time.
-;; (< (- (posn-timestamp end-posn) (posn-timestamp start-posn))
-;; (if (numberp double-click-time)
-;; (* 2 double-click-time) ;; stretch it a little
-;; 999999)) ;; non-numeric => check by position alone
- (= (car start-col-row) (car end-col-row))
- (= (cdr start-col-row) (cdr end-col-row)))))
-
-(defun mouse-drag-should-do-col-scrolling ()
- "* Determine if it's wise to enable col-scrolling for the current window."
- (or truncate-lines
- (> (window-hscroll (selected-window)) 0)
- (< (window-width) (screen-width))))
-
-(defvar mouse-throw-with-scroll-bar nil
- "* Set direction of mouse-throwing.
-If nil, the text moves in the direction the mouse moves.
-If t, the scroll bar moves in the direction the mouse moves.")
-(defconst mouse-throw-magnifier-with-scroll-bar
- [-16 -8 -4 -2 -1 0 0 0 1 2 4 8 16])
-(defconst mouse-throw-magnifier-with-mouse-movement
- [ 16 8 4 2 1 0 0 0 -1 -2 -4 -8 -16])
-(defconst mouse-throw-magnifier-min -6)
-(defconst mouse-throw-magnifier-max 6)
-
-(defun mouse-drag-throw (start-event)
- "\"Throw\" the page according to a mouse drag.
-
-A \"throw\" is scrolling the page at a speed relative to the distance
-from the original mouse click to the current mouse location. Try it;
-you'll like it. It's easier to observe than to explain.
-
-If the mouse is clicked and released in the same place of time we
-assume that the user didn't want to scdebugroll but wanted to whatever
-mouse-2 used to do, so we pass it through.
-
-Throw scrolling was inspired (but is not identical to) the \"hand\"
-option in MacPaint, or the middle button in Tk text widgets.
-
-If `mouse-throw-with-scroll-bar' is non-nil, then this command scrolls
-in the opposite direction. (Different people have different ideas
-about which direction is natural. Perhaps it has to do with which
-hemisphere you're in.)
-
-To test this function, evaluate:
- (global-set-key [down-mouse-2] 'mouse-drag-throw)"
- (interactive "e")
- ;; we want to do save-selected-window, but that requires 19.29
- (let* ((start-posn (event-start start-event))
- (start-window (posn-window start-posn))
- (start-row (cdr (posn-col-row start-posn)))
- (start-col (car (posn-col-row start-posn)))
- (old-selected-window (selected-window))
- event end row mouse-delta scroll-delta
- have-scrolled point-event-p old-binding
- window-last-row
- col mouse-col-delta window-last-col
- (scroll-col-delta 0)
- adjusted-mouse-col-delta
- adjusted-mouse-delta
- ;; be conservative about allowing horizontal scrolling
- (col-scrolling-p (mouse-drag-should-do-col-scrolling)))
- (select-window start-window)
- (track-mouse
- (while (progn
- (setq event (read-event)
- end (event-end event)
- row (cdr (posn-col-row end))
- col (car (posn-col-row end)))
- (or (mouse-movement-p event)
- (eq (car-safe event) 'switch-frame)))
- (if (eq start-window (posn-window end))
- (progn
- (setq mouse-delta (- start-row row)
- adjusted-mouse-delta
- (- (cond
- ((<= mouse-delta mouse-throw-magnifier-min)
- mouse-throw-magnifier-min)
- ((>= mouse-delta mouse-throw-magnifier-max)
- mouse-throw-magnifier-max)
- (t mouse-delta))
- mouse-throw-magnifier-min)
- scroll-delta (aref (if mouse-throw-with-scroll-bar
- mouse-throw-magnifier-with-scroll-bar
- mouse-throw-magnifier-with-mouse-movement)
- adjusted-mouse-delta))
- (if col-scrolling-p
- (setq mouse-col-delta (- start-col col)
- adjusted-mouse-col-delta
- (- (cond
- ((<= mouse-col-delta mouse-throw-magnifier-min)
- mouse-throw-magnifier-min)
- ((>= mouse-col-delta mouse-throw-magnifier-max)
- mouse-throw-magnifier-max)
- (t mouse-col-delta))
- mouse-throw-magnifier-min)
- scroll-col-delta (aref (if mouse-throw-with-scroll-bar
- mouse-throw-magnifier-with-scroll-bar
- mouse-throw-magnifier-with-mouse-movement)
- adjusted-mouse-col-delta)))))
- (if (or (/= 0 scroll-delta)
- (/= 0 scroll-col-delta))
- (progn
- (setq have-scrolled t)
- (mouse-drag-safe-scroll scroll-delta scroll-col-delta)
- (mouse-drag-repeatedly-safe-scroll scroll-delta scroll-col-delta))))) ;xxx
- ;; If it was a click and not a drag, prepare to pass the event on.
- ;; Note: We must determine the pass-through event before restoring
- ;; the window, but invoke it after. Sigh.
- (if (and (not have-scrolled)
- (mouse-drag-events-are-point-events-p start-posn end))
- (setq point-event-p t
- old-binding (key-binding
- (vector (event-basic-type start-event)))))
- ;; Now restore the old window.
- (select-window old-selected-window)
- ;; For clicks, call the old function.
- (if point-event-p
- (call-interactively old-binding))))
-
-(defun mouse-drag-drag (start-event)
- "\"Drag\" the page according to a mouse drag.
-
-Drag scrolling moves the page according to the movement of the mouse.
-You \"grab\" the character under the mouse and move it around.
-
-If the mouse is clicked and released in the same place of time we
-assume that the user didn't want to scroll but wanted to whatever
-mouse-2 used to do, so we pass it through.
-
-Drag scrolling is identical to the \"hand\" option in MacPaint, or the
-middle button in Tk text widgets.
-
-To test this function, evaluate:
- (global-set-key [down-mouse-2] 'mouse-drag-drag)"
- (interactive "e")
- ;; we want to do save-selected-window, but that requires 19.29
- (let* ((start-posn (event-start start-event))
- (start-window (posn-window start-posn))
- (start-row (cdr (posn-col-row start-posn)))
- (start-col (car (posn-col-row start-posn)))
- (old-selected-window (selected-window))
- event end row mouse-delta scroll-delta
- have-scrolled point-event-p old-binding
- window-last-row
- col mouse-col-delta window-last-col
- (scroll-col-delta 0)
- ;; be conservative about allowing horizontal scrolling
- (col-scrolling-p (mouse-drag-should-do-col-scrolling)))
- (select-window start-window)
- (setq window-last-row (- (window-height) 2)
- window-last-col (- (window-width) 2))
- (track-mouse
- (while (progn
- (setq event (read-event)
- end (event-end event)
- row (cdr (posn-col-row end))
- col (car (posn-col-row end)))
- (or (mouse-movement-p event)
- (eq (car-safe event) 'switch-frame)))
- ;; Scroll if see if we're on the edge.
- ;; NEEDSWORK: should handle mouse-in-other window.
- (cond
- ((not (eq start-window (posn-window end)))
- t) ; wait for return to original window
- ((<= row 0) (mouse-drag-repeatedly-safe-scroll -1 0))
- ((>= row window-last-row) (mouse-drag-repeatedly-safe-scroll 1 0))
- ((and col-scrolling-p (<= col 1)) (mouse-drag-repeatedly-safe-scroll 0 -1))
- ((and col-scrolling-p (>= col window-last-col)) (mouse-drag-repeatedly-safe-scroll 0 1))
- (t
- (setq scroll-delta (- row start-row)
- start-row row)
- (if col-scrolling-p
- (setq scroll-col-delta (- col start-col)
- start-col col))
- (if (or (/= 0 scroll-delta)
- (/= 0 scroll-col-delta))
- (progn
- (setq have-scrolled t)
- (mouse-drag-safe-scroll scroll-delta scroll-col-delta)))))))
- ;; If it was a click and not a drag, prepare to pass the event on.
- ;; Note: We must determine the pass-through event before restoring
- ;; the window, but invoke it after. Sigh.
- (if (and (not have-scrolled)
- (mouse-drag-events-are-point-events-p start-posn end))
- (setq point-event-p t
- old-binding (key-binding
- (vector (event-basic-type start-event)))))
- ;; Now restore the old window.
- (select-window old-selected-window)
- ;; For clicks, call the old function.
- (if point-event-p
- (call-interactively old-binding))))
-
-(provide 'mouse-drag)
-
-;;; mouse-drag.el ends here
diff --git a/lisp/mouse-sel.el b/lisp/mouse-sel.el
deleted file mode 100644
index fdcd9a3e623..00000000000
--- a/lisp/mouse-sel.el
+++ /dev/null
@@ -1,646 +0,0 @@
-;;; mouse-sel.el --- Multi-click selection support for Emacs 19
-
-;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Mike Williams <mikew@gopher.dosli.govt.nz>
-;; Keywords: mouse
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This module provides multi-click mouse support for GNU Emacs versions
-;; 19.18 and later. I've tried to make it behave more like standard X
-;; clients (eg. xterm) than the default Emacs 19 mouse selection handlers.
-;; Basically:
-;;
-;; * Clicking mouse-1 starts (cancels) selection, dragging extends it.
-;;
-;; * Clicking or dragging mouse-3 extends the selection as well.
-;;
-;; * Double-clicking on word constituents selects words.
-;; Double-clicking on symbol constituents selects symbols.
-;; Double-clicking on quotes or parentheses selects sexps.
-;; Double-clicking on whitespace selects whitespace.
-;; Triple-clicking selects lines.
-;; Quad-clicking selects paragraphs.
-;;
-;; * Selecting sets the region & X primary selection, but does NOT affect
-;; the kill-ring. Because the mouse handlers set the primary selection
-;; directly, mouse-sel sets the variables interprogram-cut-function
-;; and interprogram-paste-function to nil.
-;;
-;; * Clicking mouse-2 inserts the contents of the primary selection at
-;; the mouse position (or point, if mouse-yank-at-point is non-nil).
-;;
-;; * Pressing mouse-2 while selecting or extending copies selection
-;; to the kill ring. Pressing mouse-1 or mouse-3 kills it.
-;;
-;; * Double-clicking mouse-3 also kills selection.
-;;
-;; * M-mouse-1, M-mouse-2 & M-mouse-3 work similarly to mouse-1, mouse-2
-;; & mouse-3, but operate on the X secondary selection rather than the
-;; primary selection and region.
-;;
-;; This module requires my thingatpt.el module, which it uses to find the
-;; bounds of words, lines, sexps, etc.
-;;
-;; Thanks to KevinB@bartley.demon.co.uk for his useful input.
-;;
-;;--- Customisation -------------------------------------------------------
-;;
-;; * You may want to use none or more of following:
-;;
-;; ;; Enable region highlight
-;; (transient-mark-mode 1)
-;;
-;; ;; But only in the selected window
-;; (setq highlight-nonselected-windows nil)
-;;
-;; ;; Enable pending-delete
-;; (delete-selection-mode 1)
-;;
-;; * You can control the way mouse-sel binds its keys by setting the value
-;; of mouse-sel-default-bindings before loading mouse-sel.
-;;
-;; (a) If mouse-sel-default-bindings = t (the default)
-;;
-;; Mouse sets and insert selection
-;; mouse-1 mouse-select
-;; mouse-2 mouse-insert-selection
-;; mouse-3 mouse-extend
-;;
-;; Selection/kill-ring interaction is disabled
-;; interprogram-cut-function = nil
-;; interprogram-paste-function = nil
-;;
-;; (b) If mouse-sel-default-bindings = 'interprogram-cut-paste
-;;
-;; Mouse sets selection, and pastes from kill-ring
-;; mouse-1 mouse-select
-;; mouse-2 mouse-yank-at-click
-;; mouse-3 mouse-extend
-;;
-;; Selection/kill-ring interaction is retained
-;; interprogram-cut-function = x-select-text
-;; interprogram-paste-function = x-cut-buffer-or-selection-value
-;;
-;; What you lose is the ability to select some text in
-;; delete-selection-mode and yank over the top of it.
-;;
-;; (c) If mouse-sel-default-bindings = nil, no bindings are made.
-;;
-;; * By default, mouse-insert-selection (mouse-2) inserts the selection at
-;; the mouse position. You can tell it to insert at point instead with:
-;;
-;; (setq mouse-yank-at-point t)
-;;
-;; * I like to leave point at the end of the region nearest to where the
-;; mouse was, even though this makes region highlighting mis-leading (the
-;; cursor makes it look like one extra character is selected). You can
-;; disable this behaviour with:
-;;
-;; (setq mouse-sel-leave-point-near-mouse nil)
-;;
-;; * By default, mouse-select cycles the click count after 4 clicks. That
-;; is, clicking mouse-1 five times has the same effect as clicking it
-;; once, clicking six times has the same effect as clicking twice, etc.
-;; Disable this behaviour with:
-;;
-;; (setq mouse-sel-cycle-clicks nil)
-;;
-;; * The variables mouse-sel-{set,get}-selection-function control how the
-;; selection is handled. Under X Windows, these variables default so
-;; that the X primary selection is used. Under other windowing systems,
-;; alternate functions are used, which simply store the selection value
-;; in a variable.
-;;
-;; * You can change the selection highlight face by altering the properties
-;; of mouse-drag-overlay, eg.
-;;
-;; (overlay-put mouse-drag-overlay 'face 'bold)
-
-;;; Code:
-
-(provide 'mouse-sel)
-
-(require 'mouse)
-(require 'thingatpt)
-
-;;=== User Variables ======================================================
-
-(defvar mouse-sel-leave-point-near-mouse t
- "*Leave point near last mouse position.
-If non-nil, \\[mouse-select] and \\[mouse-extend] will leave point at the end
-of the region nearest to where the mouse last was.
-If nil, point will always be placed at the beginning of the region.")
-
-(defvar mouse-sel-cycle-clicks t
- "*If non-nil, \\[mouse-select] cycles the click-counts after 4 clicks.")
-
-(defvar mouse-sel-default-bindings t
- "Set to nil before loading `mouse-sel' to prevent default mouse bindings.")
-
-;;=== Internal Variables/Constants ========================================
-
-(defvar mouse-sel-primary-thing nil
- "Type of PRIMARY selection in current buffer.")
-(make-variable-buffer-local 'mouse-sel-primary-thing)
-
-(defvar mouse-sel-secondary-thing nil
- "Type of SECONDARY selection in current buffer.")
-(make-variable-buffer-local 'mouse-sel-secondary-thing)
-
-;; Ensure that secondary overlay is defined
-(if (overlayp mouse-secondary-overlay) nil
- (setq mouse-secondary-overlay (make-overlay 1 1))
- (overlay-put mouse-secondary-overlay 'face 'secondary-selection))
-
-(defconst mouse-sel-selection-alist
- '((PRIMARY mouse-drag-overlay mouse-sel-primary-thing)
- (SECONDARY mouse-secondary-overlay mouse-sel-secondary-thing))
- "Alist associating selections with variables. Each element is of
-the form:
-
- (SELECTION-NAME OVERLAY-SYMBOL SELECTION-THING-SYMBOL)
-
-where SELECTION-NAME = name of selection
- OVERLAY-SYMBOL = name of variable containing overlay to use
- SELECTION-THING-SYMBOL = name of variable where the current selection
- type for this selection should be stored.")
-
-(defvar mouse-sel-set-selection-function
- (function (lambda (selection value)
- (if (eq selection 'PRIMARY)
- (x-select-text value)
- (x-set-selection selection value))))
- "Function to call to set selection.
-Called with two arguments:
-
- SELECTION, the name of the selection concerned, and
- VALUE, the text to store.
-This sets the selection as well as the cut buffer for the older applications.
-Use (setq mouse-sel-set-selection-function 'x-set-selection) if you don't care
-for them.")
-
-(defvar mouse-sel-get-selection-function
- (function (lambda (selection)
- (if (eq selection 'PRIMARY)
- (x-cut-buffer-or-selection-value)
- (x-get-selection selection))))
- "Function to call to get the selection.
-Called with one argument:
-
- SELECTION: the name of the selection concerned.")
-
-;;=== Support/access functions ============================================
-
-(defun mouse-sel-determine-selection-thing (nclicks)
- "Determine what `thing' `mouse-sel' should operate on.
-The first argument is NCLICKS, is the number of consecutive
-mouse clicks at the same position.
-
-Double-clicking on word constituents selects words.
-Double-clicking on symbol constituents selects symbols.
-Double-clicking on quotes or parentheses selects sexps.
-Double-clicking on whitespace selects whitespace.
-Triple-clicking selects lines.
-Quad-clicking selects paragraphs.
-
-Feel free to re-define this function to support your own desired
-multi-click semantics."
- (let* ((next-char (char-after (point)))
- (char-syntax (if next-char (char-syntax next-char))))
- (if mouse-sel-cycle-clicks
- (setq nclicks (1+ (% (1- nclicks) 4))))
- (cond
- ((= nclicks 1) nil)
- ((= nclicks 3) 'line)
- ((>= nclicks 4) 'paragraph)
- ((memq char-syntax '(?\( ?\) ?\" ?')) 'sexp)
- ((memq next-char '(? ?\t ?\n)) 'whitespace)
- ((eq char-syntax ?_) 'symbol)
- ((eq char-syntax ?w) 'word))))
-
-(defun mouse-sel-set-selection (selection value)
- "Set the specified SELECTION to VALUE."
- (if mouse-sel-set-selection-function
- (funcall mouse-sel-set-selection-function selection value)
- (put 'mouse-sel-internal-selection selection value)))
-
-(defun mouse-sel-get-selection (selection)
- "Get the value of the specified SELECTION."
- (if mouse-sel-get-selection-function
- (funcall mouse-sel-get-selection-function selection)
- (get 'mouse-sel-internal-selection selection)))
-
-(defun mouse-sel-selection-overlay (selection)
- "Return overlay corresponding to SELECTION."
- (let ((symbol (nth 1 (assoc selection mouse-sel-selection-alist))))
- (or symbol (error "No overlay corresponding to %s selection" selection))
- (symbol-value symbol)))
-
-(defun mouse-sel-selection-thing (selection)
- "Return overlay corresponding to SELECTION."
- (let ((symbol (nth 2 (assoc selection mouse-sel-selection-alist))))
- (or symbol (error "No symbol corresponding to %s selection" selection))
- symbol))
-
-(defun mouse-sel-region-to-primary (orig-window)
- "Convert region to PRIMARY overlay and deactivate region.
-Argument ORIG-WINDOW specifies the window the cursor was in when the
-originating command was issued, and is used to determine whether the
-region was visible or not."
- (if transient-mark-mode
- (let ((overlay (mouse-sel-selection-overlay 'PRIMARY)))
- (cond
- ((and mark-active
- (or highlight-nonselected-windows
- (eq orig-window (selected-window))))
- ;; Region was visible, so convert region to overlay
- (move-overlay overlay (region-beginning) (region-end)
- (current-buffer)))
- ((eq orig-window (selected-window))
- ;; Point was visible, so set overlay at point
- (move-overlay overlay (point) (point) (current-buffer)))
- (t
- ;; Nothing was visible, so remove overlay
- (delete-overlay overlay)))
- (setq mark-active nil))))
-
-(defun mouse-sel-primary-to-region (&optional direction)
- "Convert PRIMARY overlay to region.
-Optional argument DIRECTION specifies the mouse drag direction: a value of
-1 indicates that the mouse was dragged left-to-right, otherwise it was
-dragged right-to-left."
- (let* ((overlay (mouse-sel-selection-overlay 'PRIMARY))
- (start (overlay-start overlay))
- (end (overlay-end overlay)))
- (if (eq start end)
- (progn
- (if start (goto-char start))
- (deactivate-mark))
- (if (and mouse-sel-leave-point-near-mouse (eq direction 1))
- (progn
- (goto-char end)
- (push-mark start 'nomsg 'active))
- (goto-char start)
- (push-mark end 'nomsg 'active)))
- (if transient-mark-mode (delete-overlay overlay))))
-
-(defmacro mouse-sel-eval-at-event-end (event &rest forms)
- "Evaluate forms at mouse position.
-Move to the end position of EVENT, execute FORMS, and restore original
-point and window."
- (`
- (let ((posn (event-end (, event))))
- (if posn (mouse-minibuffer-check (, event)))
- (if (and posn (not (windowp (posn-window posn))))
- (error "Cursor not in text area of window"))
- (let (orig-window orig-point-marker)
- (setq orig-window (selected-window))
- (if posn (select-window (posn-window posn)))
- (setq orig-point-marker (point-marker))
- (if (and posn (numberp (posn-point posn)))
- (goto-char (posn-point posn)))
- (unwind-protect
- (progn
- (,@ forms))
- (goto-char (marker-position orig-point-marker))
- (move-marker orig-point-marker nil)
- (select-window orig-window)
- )))))
-
-(put 'mouse-sel-eval-at-event-end 'lisp-indent-hook 1)
-
-;;=== Select ==============================================================
-
-(defun mouse-select (event)
- "Set region/selection using the mouse.
-
-Click sets point & mark to click position.
-Dragging extends region/selection.
-
-Multi-clicking selects word/lines/paragraphs, as determined by
-'mouse-sel-determine-selection-thing.
-
-Clicking mouse-2 while selecting copies selected text to the kill-ring.
-Clicking mouse-1 or mouse-3 kills the selected text.
-
-This should be bound to a down-mouse event."
- (interactive "@e")
- (let (direction)
- (unwind-protect
- (setq direction (mouse-select-internal 'PRIMARY event))
- (mouse-sel-primary-to-region direction))))
-
-(defun mouse-select-secondary (event)
- "Set secondary selection using the mouse.
-
-Click sets the start of the secondary selection to click position.
-Dragging extends the secondary selection.
-
-Multi-clicking selects word/lines/paragraphs, as determined by
-'mouse-sel-determine-selection-thing.
-
-Clicking mouse-2 while selecting copies selected text to the kill-ring.
-Clicking mouse-1 or mouse-3 kills the selected text.
-
-This should be bound to a down-mouse event."
- (interactive "e")
- (mouse-select-internal 'SECONDARY event))
-
-(defun mouse-select-internal (selection event)
- "Set SELECTION using the mouse."
- (mouse-sel-eval-at-event-end event
- (let ((thing-symbol (mouse-sel-selection-thing selection))
- (overlay (mouse-sel-selection-overlay selection)))
- (set thing-symbol
- (mouse-sel-determine-selection-thing (event-click-count event)))
- (let ((object-bounds (bounds-of-thing-at-point
- (symbol-value thing-symbol))))
- (if object-bounds
- (progn
- (move-overlay overlay
- (car object-bounds) (cdr object-bounds)
- (current-buffer)))
- (move-overlay overlay (point) (point) (current-buffer)))))
- (mouse-extend-internal selection)))
-
-;;=== Extend ==============================================================
-
-(defun mouse-extend (event)
- "Extend region/selection using the mouse."
- (interactive "e")
- (let ((orig-window (selected-window))
- direction)
- (select-window (posn-window (event-end event)))
- (unwind-protect
- (progn
- (mouse-sel-region-to-primary orig-window)
- (setq direction (mouse-extend-internal 'PRIMARY event)))
- (mouse-sel-primary-to-region direction))))
-
-(defun mouse-extend-secondary (event)
- "Extend secondary selection using the mouse."
- (interactive "e")
- (save-window-excursion
- (mouse-extend-internal 'SECONDARY event)))
-
-(defun mouse-extend-internal (selection &optional initial-event)
- "Extend specified SELECTION using the mouse.
-Track mouse-motion events, adjusting the SELECTION appropriately.
-Optional argument INITIAL-EVENT specifies an initial down-mouse event to
-process.
-
-See documentation for mouse-select-internal for more details."
- (mouse-sel-eval-at-event-end initial-event
- (let ((orig-cursor-type
- (cdr (assoc 'cursor-type (frame-parameters (selected-frame))))))
- (unwind-protect
-
- (let* ((thing-symbol (mouse-sel-selection-thing selection))
- (overlay (mouse-sel-selection-overlay selection))
- (orig-window (selected-window))
- (orig-window-frame (window-frame orig-window))
- (top (nth 1 (window-edges orig-window)))
- (bottom (nth 3 (window-edges orig-window)))
- (mark-active nil) ; inhibit normal region highlight
- (echo-keystrokes 0) ; don't echo mouse events
- min max
- direction
- event)
-
- ;; Get current bounds of overlay
- (if (eq (overlay-buffer overlay) (current-buffer))
- (setq min (overlay-start overlay)
- max (overlay-end overlay))
- (setq min (point)
- max min)
- (set thing-symbol nil))
-
-
- ;; Bar cursor
- (if (fboundp 'modify-frame-parameters)
- (modify-frame-parameters (selected-frame)
- '((cursor-type . bar))))
-
- ;; Handle dragging
- (track-mouse
-
- (while (if initial-event ; Use initial event
- (prog1
- (setq event initial-event)
- (setq initial-event nil))
- (setq event (read-event))
- (and (consp event)
- (memq (car event) '(mouse-movement switch-frame))))
-
- (let ((selection-thing (symbol-value thing-symbol))
- (end (event-end event)))
-
- (cond
-
- ;; Ignore any movement outside the frame
- ((eq (car-safe event) 'switch-frame) nil)
- ((and (posn-window end)
- (not (eq (let ((posn-w (posn-window end)))
- (if (windowp posn-w)
- (window-frame posn-w)
- posn-w))
- (window-frame orig-window)))) nil)
-
- ;; Different window, same frame
- ((not (eq (posn-window end) orig-window))
- (let ((end-row (cdr (cdr (mouse-position)))))
- (cond
- ((and end-row (not (bobp)) (< end-row top))
- (mouse-scroll-subr orig-window (- end-row top)
- overlay max))
- ((and end-row (not (eobp)) (>= end-row bottom))
- (mouse-scroll-subr orig-window (1+ (- end-row bottom))
- overlay min))
- )))
-
- ;; On the mode line
- ((eq (posn-point end) 'mode-line)
- (mouse-scroll-subr orig-window 1 overlay min))
-
- ;; In original window
- (t (goto-char (posn-point end)))
-
- )
-
- ;; Determine direction of drag
- (cond
- ((and (not direction) (not (eq min max)))
- (setq direction (if (< (point) (/ (+ min max) 2)) -1 1)))
- ((and (not (eq direction -1)) (<= (point) min))
- (setq direction -1))
- ((and (not (eq direction 1)) (>= (point) max))
- (setq direction 1)))
-
- (if (not selection-thing) nil
-
- ;; If dragging forward, goal is next character
- (if (and (eq direction 1) (not (eobp))) (forward-char 1))
-
- ;; Move to start/end of selected thing
- (let ((goal (point)))
- (goto-char (if (eq 1 direction) min max))
- (condition-case nil
- (progn
- (while (> (* direction (- goal (point))) 0)
- (forward-thing selection-thing direction))
- (let ((end (point)))
- (forward-thing selection-thing (- direction))
- (goto-char
- (if (> (* direction (- goal (point))) 0)
- end (point)))))
- (error))))
-
- ;; Move overlay
- (move-overlay overlay
- (if (eq 1 direction) min (point))
- (if (eq -1 direction) max (point))
- (current-buffer))
-
- ))) ; end track-mouse
-
- ;; Finish up after dragging
- (let ((overlay-start (overlay-start overlay))
- (overlay-end (overlay-end overlay)))
-
- ;; Set selection
- (if (not (eq overlay-start overlay-end))
- (mouse-sel-set-selection
- selection
- (buffer-substring overlay-start overlay-end)))
-
- ;; Handle copy/kill
- (let (this-command)
- (cond
- ((eq (event-basic-type last-input-event) 'mouse-2)
- (copy-region-as-kill overlay-start overlay-end)
- (read-event) (read-event))
- ((and (memq (event-basic-type last-input-event)
- '(mouse-1 mouse-3))
- (memq 'down (event-modifiers last-input-event)))
- (kill-region overlay-start overlay-end)
- (move-overlay overlay overlay-start overlay-start)
- (read-event) (read-event))
- ((and (eq (event-basic-type last-input-event) 'mouse-3)
- (memq 'double (event-modifiers last-input-event)))
- (kill-region overlay-start overlay-end)
- (move-overlay overlay overlay-start overlay-start)))))
-
- direction)
-
- ;; Restore cursor
- (if (fboundp 'modify-frame-parameters)
- (modify-frame-parameters
- (selected-frame) (list (cons 'cursor-type orig-cursor-type))))
-
- ))))
-
-;;=== Paste ===============================================================
-
-(defun mouse-insert-selection (event)
- "Insert the contents of the PRIMARY selection at mouse click.
-If `mouse-yank-at-point' is non-nil, insert at point instead."
- (interactive "e")
- (mouse-insert-selection-internal 'PRIMARY event))
-
-(defun mouse-insert-secondary (event)
- "Insert the contents of the SECONDARY selection at mouse click.
-If `mouse-yank-at-point' is non-nil, insert at point instead."
- (interactive "e")
- (mouse-insert-selection-internal 'SECONDARY event))
-
-(defun mouse-insert-selection-internal (selection event)
- "Insert the contents of the named SELECTION at mouse click.
-If `mouse-yank-at-point' is non-nil, insert at point instead."
- (or mouse-yank-at-point
- (mouse-set-point event))
- (if mouse-sel-get-selection-function
- (progn
- (push-mark (point) 'nomsg)
- (insert (or (funcall mouse-sel-get-selection-function selection) "")))))
-
-;;=== Handle loss of selections ===========================================
-
-(defun mouse-sel-lost-selection-hook (selection)
- "Remove the overlay for a lost selection."
- (let ((overlay (mouse-sel-selection-overlay selection)))
- (delete-overlay overlay)))
-
-(add-hook 'x-lost-selection-hooks 'mouse-sel-lost-selection-hook)
-
-;;=== Key bindings ========================================================
-
-(if (not mouse-sel-default-bindings) nil
-
- (global-unset-key [mouse-1])
- (global-unset-key [drag-mouse-1])
- (global-unset-key [mouse-3])
-
- (global-set-key [down-mouse-1] 'mouse-select)
- (global-set-key [down-mouse-3] 'mouse-extend)
-
- (global-unset-key [M-mouse-1])
- (global-unset-key [M-drag-mouse-1])
- (global-unset-key [M-mouse-3])
-
- (global-set-key [M-down-mouse-1] 'mouse-select-secondary)
- (global-set-key [M-down-mouse-3] 'mouse-extend-secondary)
-
- (if (eq mouse-sel-default-bindings 'interprogram-cut-paste) nil
-
- (global-set-key [mouse-2] 'mouse-insert-selection)
-
- (setq interprogram-cut-function nil
- interprogram-paste-function nil))
-
- (global-set-key [M-mouse-2] 'mouse-insert-secondary)
-
- )
-
-;;=== Bug reporting =======================================================
-
-(defconst mouse-sel-maintainer-address "mikew@gopher.dosli.govt.nz")
-
-(defun mouse-sel-submit-bug-report ()
- "Submit a bug report on mouse-sel.el via mail."
- (interactive)
- (require 'reporter)
- (reporter-submit-bug-report
- mouse-sel-maintainer-address
- (concat "mouse-sel.el "
- (or (condition-case nil mouse-sel-version (error))
- "(distributed with Emacs)"))
- (list 'transient-mark-mode
- 'delete-selection-mode
- 'mouse-sel-default-bindings
- 'mouse-sel-leave-point-near-mouse
- 'mouse-sel-cycle-clicks
- 'mouse-sel-selection-alist
- 'mouse-sel-set-selection-function
- 'mouse-sel-get-selection-function
- 'mouse-yank-at-point)))
-
-;; mouse-sel.el ends here.
diff --git a/lisp/mouse.el b/lisp/mouse.el
deleted file mode 100644
index 5613e73c3c1..00000000000
--- a/lisp/mouse.el
+++ /dev/null
@@ -1,1845 +0,0 @@
-;;; mouse.el --- window system-independent mouse support
-
-;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: hardware
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides various useful commands (including help
-;; system access) through the mouse. All this code assumes that mouse
-;; interpretation has been abstracted into Emacs input events.
-;;
-;; The code is rather X-dependent.
-
-;;; Code:
-
-;;; Utility functions.
-
-;;; Indent track-mouse like progn.
-(put 'track-mouse 'lisp-indent-function 0)
-
-(defvar mouse-yank-at-point nil
- "*If non-nil, mouse yank commands yank at point instead of at click.")
-
-;; Provide a mode-specific menu on a mouse button.
-
-(defun mouse-major-mode-menu (event prefix)
- "Pop up a mode-specific menu of mouse commands."
- ;; Switch to the window clicked on, because otherwise
- ;; the mode's commands may not make sense.
- (interactive "@e\nP")
- (let (;; This is where mouse-major-mode-menu-prefix
- ;; returns the prefix we should use (after menu-bar).
- ;; It is either nil or (SOME-SYMBOL).
- (mouse-major-mode-menu-prefix nil)
- ;; Make a keymap in which our last command leads to a menu
- (newmap (make-sparse-keymap (concat mode-name " Mode")))
- result)
- ;; Make our menu inherit from the desired keymap
- ;; which we want to display as the menu now.
- (set-keymap-parent newmap
- (mouse-major-mode-menu-1
- (and (current-local-map)
- (lookup-key (current-local-map) [menu-bar]))))
- (setq result (x-popup-menu t (list newmap)))
- (if result
- (let ((command (key-binding
- (apply 'vector (append '(menu-bar)
- mouse-major-mode-menu-prefix
- result)))))
- ;; Clear out echoing, which perhaps shows a prefix arg.
- (message "")
- (if command
- (progn
- (setq prefix-arg prefix)
- (command-execute command)))))))
-
-;; Compute and cache the equivalent keys in MENU and all its submenus.
-;;;(defun mouse-major-mode-menu-compute-equiv-keys (menu)
-;;; (and (eq (car menu) 'keymap)
-;;; (x-popup-menu nil menu))
-;;; (while menu
-;;; (and (consp (car menu))
-;;; (consp (cdr (car menu)))
-;;; (let ((tail (cdr (car menu))))
-;;; (while (and (consp tail)
-;;; (not (eq (car tail) 'keymap)))
-;;; (setq tail (cdr tail)))
-;;; (if (consp tail)
-;;; (mouse-major-mode-menu-compute-equiv-keys tail))))
-;;; (setq menu (cdr menu))))
-
-;; Given a mode's menu bar keymap,
-;; if it defines exactly one menu bar menu,
-;; return just that menu.
-;; Otherwise return a menu for all of them.
-(defun mouse-major-mode-menu-1 (menubar)
- (if menubar
- (let ((tail menubar)
- submap)
- (while tail
- (if (consp (car tail))
- (if submap
- (setq submap t)
- (setq submap (car tail))))
- (setq tail (cdr tail)))
- (if (eq submap t)
- menubar
- (setq mouse-major-mode-menu-prefix (list (car submap)))
- (cdr (cdr submap))))))
-
-;; Commands that operate on windows.
-
-(defun mouse-minibuffer-check (event)
- (let ((w (posn-window (event-start event))))
- (and (window-minibuffer-p w)
- (not (minibuffer-window-active-p w))
- (error "Minibuffer window is not active")))
- ;; Give temporary modes such as isearch a chance to turn off.
- (run-hooks 'mouse-leave-buffer-hook))
-
-(defun mouse-delete-window (click)
- "Delete the window you click on.
-This must be bound to a mouse click."
- (interactive "e")
- (mouse-minibuffer-check click)
- (delete-window (posn-window (event-start click))))
-
-(defun mouse-select-window (click)
- "Select the window clicked on; don't move point."
- (interactive "e")
- (mouse-minibuffer-check click)
- (let ((oframe (selected-frame))
- (frame (window-frame (posn-window (event-start click)))))
- (select-window (posn-window (event-start click)))
- (raise-frame frame)
- (select-frame frame)
- (or (eq frame oframe)
- (set-mouse-position (selected-frame) (1- (frame-width)) 0))))
-
-(defun mouse-tear-off-window (click)
- "Delete the window clicked on, and create a new frame displaying its buffer."
- (interactive "e")
- (mouse-minibuffer-check click)
- (let* ((window (posn-window (event-start click)))
- (buf (window-buffer window))
- (frame (make-frame)))
- (select-frame frame)
- (switch-to-buffer buf)
- (delete-window window)))
-
-(defun mouse-delete-other-windows ()
- "Delete all window except the one you click on."
- (interactive "@")
- (delete-other-windows))
-
-(defun mouse-split-window-vertically (click)
- "Select Emacs window mouse is on, then split it vertically in half.
-The window is split at the line clicked on.
-This command must be bound to a mouse click."
- (interactive "@e")
- (mouse-minibuffer-check click)
- (let ((start (event-start click)))
- (select-window (posn-window start))
- (let ((new-height (1+ (cdr (posn-col-row (event-end click)))))
- (first-line window-min-height)
- (last-line (- (window-height) window-min-height)))
- (if (< last-line first-line)
- (error "Window too short to split")
- (split-window-vertically
- (min (max new-height first-line) last-line))))))
-
-(defun mouse-split-window-horizontally (click)
- "Select Emacs window mouse is on, then split it horizontally in half.
-The window is split at the column clicked on.
-This command must be bound to a mouse click."
- (interactive "@e")
- (mouse-minibuffer-check click)
- (let ((start (event-start click)))
- (select-window (posn-window start))
- (let ((new-width (1+ (car (posn-col-row (event-end click)))))
- (first-col window-min-width)
- (last-col (- (window-width) window-min-width)))
- (if (< last-col first-col)
- (error "Window too narrow to split")
- (split-window-horizontally
- (min (max new-width first-col) last-col))))))
-
-(defun mouse-drag-mode-line (start-event)
- "Change the height of a window by dragging on the mode line."
- (interactive "e")
- ;; Give temporary modes such as isearch a chance to turn off.
- (run-hooks 'mouse-leave-buffer-hook)
- (let ((done nil)
- (echo-keystrokes 0)
- (start-event-frame (window-frame (car (car (cdr start-event)))))
- (start-event-window (car (car (cdr start-event))))
- (start-nwindows (count-windows t))
- (old-selected-window (selected-window))
- should-enlarge-minibuffer
- event mouse minibuffer y top bot edges wconfig params growth)
- (setq params (frame-parameters))
- (setq minibuffer (cdr (assq 'minibuffer params)))
- (track-mouse
- (progn
- ;; enlarge-window only works on the selected window, so
- ;; we must select the window where the start event originated.
- ;; unwind-protect will restore the old selected window later.
- (select-window start-event-window)
- ;; if this is the bottommost ordinary window, then to
- ;; move its modeline the minibuffer must be enlarged.
- (setq should-enlarge-minibuffer
- (and minibuffer
- (not (one-window-p t))
- (= (nth 1 (window-edges minibuffer))
- (nth 3 (window-edges)))))
- ;; loop reading events and sampling the position of
- ;; the mouse.
- (while (not done)
- (setq event (read-event)
- mouse (mouse-position))
- ;; do nothing if
- ;; - there is a switch-frame event.
- ;; - the mouse isn't in the frame that we started in
- ;; - the mouse isn't in any Emacs frame
- ;; drag if
- ;; - there is a mouse-movement event
- ;; - there is a scroll-bar-movement event
- ;; (same as mouse movement for our purposes)
- ;; quit if
- ;; - there is a keyboard event or some other unknown event
- ;; unknown event.
- (cond ((integerp event)
- (setq done t))
- ((eq (car event) 'switch-frame)
- nil)
- ((not (memq (car event)
- '(mouse-movement scroll-bar-movement)))
- (if (consp event)
- (setq unread-command-events
- (cons event unread-command-events)))
- (setq done t))
- ((not (eq (car mouse) start-event-frame))
- nil)
- ((null (car (cdr mouse)))
- nil)
- (t
- (setq y (cdr (cdr mouse))
- edges (window-edges)
- top (nth 1 edges)
- bot (nth 3 edges))
- ;; scale back a move that would make the
- ;; window too short.
- (cond ((< (- y top -1) window-min-height)
- (setq y (+ top window-min-height -1))))
- ;; compute size change needed
- (setq growth (- y bot -1)
- wconfig (current-window-configuration))
- ;; Check for an error case.
- (if (and (/= growth 0)
- (not minibuffer)
- (one-window-p t))
- (error "Attempt to resize sole window"))
- ;; grow/shrink minibuffer?
- (if should-enlarge-minibuffer
- (progn
- ;; yes. briefly select minibuffer so
- ;; enlarge-window will affect the
- ;; correct window.
- (select-window minibuffer)
- ;; scale back shrinkage if it would
- ;; make the minibuffer less than 1
- ;; line tall.
- (if (and (> growth 0)
- (< (- (window-height minibuffer)
- growth)
- 1))
- (setq growth (1- (window-height minibuffer))))
- (enlarge-window (- growth))
- (select-window start-event-window))
- ;; no. grow/shrink the selected window
- (enlarge-window growth))
- ;; if this window's growth caused another
- ;; window to be deleted because it was too
- ;; short, rescind the change.
- ;;
- ;; if size change caused space to be stolen
- ;; from a window above this one, rescind the
- ;; change, but only if we didn't grow/srhink
- ;; the minibuffer. minibuffer size changes
- ;; can cause all windows to shrink... no way
- ;; around it.
- (if (or (/= start-nwindows (count-windows t))
- (and (not should-enlarge-minibuffer)
- (/= top (nth 1 (window-edges)))))
- (set-window-configuration wconfig)))))))))
-
-(defun mouse-drag-vertical-line (start-event)
- "Change the width of a window by dragging on the vertical line."
- (interactive "e")
- ;; Give temporary modes such as isearch a chance to turn off.
- (run-hooks 'mouse-leave-buffer-hook)
- (let ((done nil)
- (echo-keystrokes 0)
- (start-event-frame (window-frame (car (car (cdr start-event)))))
- (start-event-window (car (car (cdr start-event))))
- (start-nwindows (count-windows t))
- (old-selected-window (selected-window))
- event mouse x left right edges wconfig growth)
- (if (one-window-p t)
- (error "Attempt to resize sole ordinary window"))
- (if (= (nth 2 (window-edges start-event-window))
- (frame-width start-event-frame))
- (error "Attempt to drag rightmost scrollbar"))
- (track-mouse
- (progn
- ;; enlarge-window only works on the selected window, so
- ;; we must select the window where the start event originated.
- ;; unwind-protect will restore the old selected window later.
- (select-window start-event-window)
- ;; loop reading events and sampling the position of
- ;; the mouse.
- (while (not done)
- (setq event (read-event)
- mouse (mouse-position))
- ;; do nothing if
- ;; - there is a switch-frame event.
- ;; - the mouse isn't in the frame that we started in
- ;; - the mouse isn't in any Emacs frame
- ;; drag if
- ;; - there is a mouse-movement event
- ;; - there is a scroll-bar-movement event
- ;; (same as mouse movement for our purposes)
- ;; quit if
- ;; - there is a keyboard event or some other unknown event
- ;; unknown event.
- (cond ((integerp event)
- (setq done t))
- ((eq (car event) 'switch-frame)
- nil)
- ((not (memq (car event)
- '(mouse-movement scroll-bar-movement)))
- (if (consp event)
- (setq unread-command-events
- (cons event unread-command-events)))
- (setq done t))
- ((not (eq (car mouse) start-event-frame))
- nil)
- ((null (car (cdr mouse)))
- nil)
- (t
- (setq x (car (cdr mouse))
- edges (window-edges)
- left (nth 0 edges)
- right (nth 2 edges))
- ;; scale back a move that would make the
- ;; window too thin.
- (cond ((< (- x left -1) window-min-width)
- (setq x (+ left window-min-width -1))))
- ;; compute size change needed
- (setq growth (- x right -1)
- wconfig (current-window-configuration))
- (enlarge-window growth t)
- ;; if this window's growth caused another
- ;; window to be deleted because it was too
- ;; thin, rescind the change.
- ;;
- ;; if size change caused space to be stolen
- ;; from a window to the left of this one,
- ;; rescind the change.
- (if (or (/= start-nwindows (count-windows t))
- (/= left (nth 0 (window-edges))))
- (set-window-configuration wconfig)))))))))
-
-(defun mouse-set-point (event)
- "Move point to the position clicked on with the mouse.
-This should be bound to a mouse click event type."
- (interactive "e")
- (mouse-minibuffer-check event)
- ;; Use event-end in case called from mouse-drag-region.
- ;; If EVENT is a click, event-end and event-start give same value.
- (let ((posn (event-end event)))
- (if (not (windowp (posn-window posn)))
- (error "Cursor not in text area of window"))
- (select-window (posn-window posn))
- (if (numberp (posn-point posn))
- (goto-char (posn-point posn)))))
-
-(defvar mouse-last-region-beg nil)
-(defvar mouse-last-region-end nil)
-(defvar mouse-last-region-tick nil)
-
-(defun mouse-region-match ()
- "Return non-nil if there's an active region that was set with the mouse."
- (and (mark t) mark-active
- (eq mouse-last-region-beg (region-beginning))
- (eq mouse-last-region-end (region-end))
- (eq mouse-last-region-tick (buffer-modified-tick))))
-
-(defun mouse-set-region (click)
- "Set the region to the text dragged over, and copy to kill ring.
-This should be bound to a mouse drag event."
- (interactive "e")
- (mouse-minibuffer-check click)
- (let ((posn (event-start click))
- (end (event-end click)))
- (select-window (posn-window posn))
- (if (numberp (posn-point posn))
- (goto-char (posn-point posn)))
- ;; If mark is highlighted, no need to bounce the cursor.
- ;; On X, we highlight while dragging, thus once again no need to bounce.
- (or transient-mark-mode
- (memq (framep (selected-frame)) '(x pc w32))
- (sit-for 1))
- (push-mark)
- (set-mark (point))
- (if (numberp (posn-point end))
- (goto-char (posn-point end)))
- ;; Don't set this-command to kill-region, so that a following
- ;; C-w will not double the text in the kill ring.
- ;; Ignore last-command so we don't append to a preceding kill.
- (let (this-command last-command)
- (copy-region-as-kill (mark) (point)))
- (mouse-set-region-1)))
-
-(defun mouse-set-region-1 ()
- (setq mouse-last-region-beg (region-beginning))
- (setq mouse-last-region-end (region-end))
- (setq mouse-last-region-tick (buffer-modified-tick)))
-
-(defvar mouse-scroll-delay 0.25
- "*The pause between scroll steps caused by mouse drags, in seconds.
-If you drag the mouse beyond the edge of a window, Emacs scrolls the
-window to bring the text beyond that edge into view, with a delay of
-this many seconds between scroll steps. Scrolling stops when you move
-the mouse back into the window, or release the button.
-This variable's value may be non-integral.
-Setting this to zero causes Emacs to scroll as fast as it can.")
-
-(defvar mouse-scroll-min-lines 1
- "*The minimum number of lines scrolled by dragging mouse out of window.
-Moving the mouse out the top or bottom edge of the window begins
-scrolling repeatedly. The number of lines scrolled per repetition
-is normally equal to the number of lines beyond the window edge that
-the mouse has moved. However, it always scrolls at least the number
-of lines specified by this variable.")
-
-(defun mouse-scroll-subr (window jump &optional overlay start)
- "Scroll the window WINDOW, JUMP lines at a time, until new input arrives.
-If OVERLAY is an overlay, let it stretch from START to the far edge of
-the newly visible text.
-Upon exit, point is at the far edge of the newly visible text."
- (cond
- ((and (> jump 0) (< jump mouse-scroll-min-lines))
- (setq jump mouse-scroll-min-lines))
- ((and (< jump 0) (< (- jump) mouse-scroll-min-lines))
- (setq jump (- mouse-scroll-min-lines))))
- (let ((opoint (point)))
- (while (progn
- (goto-char (window-start window))
- (if (not (zerop (vertical-motion jump window)))
- (progn
- (set-window-start window (point))
- (if (natnump jump)
- (progn
- (goto-char (window-end window))
- ;; window-end doesn't reflect the window's new
- ;; start position until the next redisplay. Hurrah.
- (vertical-motion (1- jump) window))
- (goto-char (window-start window)))
- (if overlay
- (move-overlay overlay start (point)))
- ;; Now that we have scrolled WINDOW properly,
- ;; put point back where it was for the redisplay
- ;; so that we don't mess up the selected window.
- (or (eq window (selected-window))
- (goto-char opoint))
- (sit-for mouse-scroll-delay)))))
- (or (eq window (selected-window))
- (goto-char opoint))))
-
-;; Create an overlay and immediately delete it, to get "overlay in no buffer".
-(defvar mouse-drag-overlay (make-overlay 1 1))
-(delete-overlay mouse-drag-overlay)
-(overlay-put mouse-drag-overlay 'face 'region)
-
-(defvar mouse-selection-click-count 0)
-
-(defvar mouse-selection-click-count-buffer nil)
-
-(defun mouse-drag-region (start-event)
- "Set the region to the text that the mouse is dragged over.
-Highlight the drag area as you move the mouse.
-This must be bound to a button-down mouse event.
-In Transient Mark mode, the highlighting remains as long as the mark
-remains active. Otherwise, it remains until the next input event."
- (interactive "e")
- (mouse-minibuffer-check start-event)
- (let* ((echo-keystrokes 0)
- (start-posn (event-start start-event))
- (start-point (posn-point start-posn))
- (start-window (posn-window start-posn))
- (start-frame (window-frame start-window))
- (bounds (window-edges start-window))
- (top (nth 1 bounds))
- (bottom (if (window-minibuffer-p start-window)
- (nth 3 bounds)
- ;; Don't count the mode line.
- (1- (nth 3 bounds))))
- (click-count (1- (event-click-count start-event))))
- (setq mouse-selection-click-count click-count)
- (setq mouse-selection-click-count-buffer (current-buffer))
- (mouse-set-point start-event)
- ;; In case the down click is in the middle of some intangible text,
- ;; use the end of that text, and put it in START-POINT.
- (if (< (point) start-point)
- (goto-char start-point))
- (setq start-point (point))
- (let ((range (mouse-start-end start-point start-point click-count)))
- (move-overlay mouse-drag-overlay (car range) (nth 1 range)
- (window-buffer start-window)))
- (deactivate-mark)
- ;; end-of-range is used only in the single-click case.
- ;; It is the place where the drag has reached so far
- ;; (but not outside the window where the drag started).
- (let (event end end-point last-end-point (end-of-range (point)))
- (track-mouse
- (while (progn
- (setq event (read-event))
- (or (mouse-movement-p event)
- (eq (car-safe event) 'switch-frame)))
- (if (eq (car-safe event) 'switch-frame)
- nil
- (setq end (event-end event)
- end-point (posn-point end))
- (if (numberp end-point)
- (setq last-end-point end-point))
-
- (cond
- ;; Are we moving within the original window?
- ((and (eq (posn-window end) start-window)
- (integer-or-marker-p end-point))
- ;; Go to START-POINT first, so that when we move to END-POINT,
- ;; if it's in the middle of intangible text,
- ;; point jumps in the direction away from START-POINT.
- (goto-char start-point)
- (goto-char end-point)
- (if (zerop (% click-count 3))
- (setq end-of-range (point)))
- (let ((range (mouse-start-end start-point (point) click-count)))
- (move-overlay mouse-drag-overlay (car range) (nth 1 range))))
-
- (t
- (let ((mouse-row (cdr (cdr (mouse-position)))))
- (cond
- ((null mouse-row))
- ((< mouse-row top)
- (mouse-scroll-subr start-window (- mouse-row top)
- mouse-drag-overlay start-point)
- ;; Without this, point tends to jump back to the starting
- ;; position where the mouse button was pressed down.
- (setq end-of-range (overlay-start mouse-drag-overlay)))
- ((>= mouse-row bottom)
- (mouse-scroll-subr start-window (1+ (- mouse-row bottom))
- mouse-drag-overlay start-point)
- (setq end-of-range (overlay-end mouse-drag-overlay))))))))))
- (if (consp event)
- (let ((fun (key-binding (vector (car event)))))
- ;; Run the binding of the terminating up-event, if possible.
- ;; In the case of a multiple click, it gives the wrong results,
- ;; because it would fail to set up a region.
- (if nil ;; (and (= (mod mouse-selection-click-count 3) 0) (fboundp fun))
- ;; In this case, we can just let the up-event execute normally.
- (let ((end (event-end event)))
- ;; Set the position in the event before we replay it,
- ;; because otherwise it may have a position in the wrong
- ;; buffer.
- (setcar (cdr end) end-of-range)
- ;; Delete the overlay before calling the function,
- ;; because delete-overlay increases buffer-modified-tick.
- (delete-overlay mouse-drag-overlay)
- (setq unread-command-events
- (cons event unread-command-events)))
- (if (not (= (overlay-start mouse-drag-overlay)
- (overlay-end mouse-drag-overlay)))
- (let* ((stop-point
- (if (numberp (posn-point (event-end event)))
- (posn-point (event-end event))
- last-end-point))
- ;; The end that comes from where we ended the drag.
- ;; Point goes here.
- (region-termination
- (if (and stop-point (< stop-point start-point))
- (overlay-start mouse-drag-overlay)
- (overlay-end mouse-drag-overlay)))
- ;; The end that comes from where we started the drag.
- ;; Mark goes there.
- (region-commencement
- (- (+ (overlay-end mouse-drag-overlay)
- (overlay-start mouse-drag-overlay))
- region-termination))
- last-command this-command)
- (push-mark region-commencement t t)
- (goto-char region-termination)
- (copy-region-as-kill (point) (mark t))
- (let ((buffer (current-buffer)))
- (mouse-show-mark)
- ;; mouse-show-mark can call read-event,
- ;; and that means the Emacs server could switch buffers
- ;; under us. If that happened,
- ;; avoid trying to use the region.
- (and (mark t) mark-active
- (eq buffer (current-buffer))
- (mouse-set-region-1))))
- (goto-char (overlay-end mouse-drag-overlay))
- (setq this-command 'mouse-set-point)
- (delete-overlay mouse-drag-overlay))))
- (delete-overlay mouse-drag-overlay)))))
-
-;; Commands to handle xterm-style multiple clicks.
-
-(defun mouse-skip-word (dir)
- "Skip over word, over whitespace, or over identical punctuation.
-If DIR is positive skip forward; if negative, skip backward."
- (let* ((char (following-char))
- (syntax (char-to-string (char-syntax char))))
- (cond ((or (string= syntax "w") (string= syntax " "))
- (if (< dir 0)
- (skip-syntax-backward syntax)
- (skip-syntax-forward syntax)))
- ((string= syntax "_")
- (if (< dir 0)
- (skip-syntax-backward "w_")
- (skip-syntax-forward "w_")))
- ((< dir 0)
- (while (and (not (bobp)) (= (preceding-char) char))
- (forward-char -1)))
- (t
- (while (and (not (eobp)) (= (following-char) char))
- (forward-char 1))))))
-
-;; Return a list of region bounds based on START and END according to MODE.
-;; If MODE is 0 then set point to (min START END), mark to (max START END).
-;; If MODE is 1 then set point to start of word at (min START END),
-;; mark to end of word at (max START END).
-;; If MODE is 2 then do the same for lines.
-(defun mouse-start-end (start end mode)
- (if (> start end)
- (let ((temp start))
- (setq start end
- end temp)))
- (setq mode (mod mode 3))
- (cond ((= mode 0)
- (list start end))
- ((and (= mode 1)
- (= start end)
- (char-after start)
- (= (char-syntax (char-after start)) ?\())
- (list start
- (save-excursion
- (goto-char start)
- (forward-sexp 1)
- (point))))
- ((and (= mode 1)
- (= start end)
- (char-after start)
- (= (char-syntax (char-after start)) ?\)))
- (list (save-excursion
- (goto-char (1+ start))
- (backward-sexp 1)
- (point))
- (1+ start)))
- ((and (= mode 1)
- (= start end)
- (char-after start)
- (= (char-syntax (char-after start)) ?\"))
- (let ((open (or (eq start (point-min))
- (save-excursion
- (goto-char (- start 1))
- (looking-at "\\s(\\|\\s \\|\\s>")))))
- (if open
- (list start
- (save-excursion
- (condition-case nil
- (progn
- (goto-char start)
- (forward-sexp 1)
- (point))
- (error end))))
- (list (save-excursion
- (condition-case nil
- (progn
- (goto-char (1+ start))
- (backward-sexp 1)
- (point))
- (error end)))
- (1+ start)))))
- ((= mode 1)
- (list (save-excursion
- (goto-char start)
- (mouse-skip-word -1)
- (point))
- (save-excursion
- (goto-char end)
- (mouse-skip-word 1)
- (point))))
- ((= mode 2)
- (list (save-excursion
- (goto-char start)
- (beginning-of-line 1)
- (point))
- (save-excursion
- (goto-char end)
- (forward-line 1)
- (point))))))
-
-;; Subroutine: set the mark where CLICK happened,
-;; but don't do anything else.
-(defun mouse-set-mark-fast (click)
- (mouse-minibuffer-check click)
- (let ((posn (event-start click)))
- (select-window (posn-window posn))
- (if (numberp (posn-point posn))
- (push-mark (posn-point posn) t t))))
-
-(defun mouse-undouble-last-event (events)
- (let* ((index (1- (length events)))
- (last (nthcdr index events))
- (event (car last))
- (basic (event-basic-type event))
- (modifiers (delq 'double (delq 'triple (copy-sequence (event-modifiers event)))))
- (new
- (if (consp event)
- (cons (event-convert-list (nreverse (cons basic modifiers)))
- (cdr event))
- event)))
- (setcar last new)
- (if (key-binding (apply 'vector events))
- t
- (setcar last event)
- nil)))
-
-;; Momentarily show where the mark is, if highlighting doesn't show it.
-
-(defvar mouse-region-delete-keys '([delete])
- "List of keys which shall cause the mouse region to be deleted.")
-
-(defun mouse-show-mark ()
- (if transient-mark-mode
- (if window-system
- (delete-overlay mouse-drag-overlay))
- (if window-system
- (let ((inhibit-quit t)
- (echo-keystrokes 0)
- event events key ignore
- x-lost-selection-hooks)
- (add-hook 'x-lost-selection-hooks
- '(lambda (seltype)
- (if (eq seltype 'PRIMARY)
- (progn (setq ignore t)
- (throw 'mouse-show-mark t)))))
- (move-overlay mouse-drag-overlay (point) (mark t))
- (catch 'mouse-show-mark
- (while (progn (setq event (read-event))
- (setq events (append events (list event)))
- (setq key (apply 'vector events))
- (and (memq 'down (event-modifiers event))
- (not (key-binding key))
- (not (member key mouse-region-delete-keys))
- (not (mouse-undouble-last-event events))))))
- ;; If we lost the selection, just turn off the highlighting.
- (if ignore
- nil
- ;; For certain special keys, delete the region.
- (if (member key mouse-region-delete-keys)
- (delete-region (overlay-start mouse-drag-overlay)
- (overlay-end mouse-drag-overlay))
- ;; Otherwise, unread the key so it gets executed normally.
- (setq unread-command-events
- (nconc events unread-command-events))))
- (setq quit-flag nil)
- (delete-overlay mouse-drag-overlay))
- (save-excursion
- (goto-char (mark t))
- (sit-for 1)))))
-
-(defun mouse-set-mark (click)
- "Set mark at the position clicked on with the mouse.
-Display cursor at that position for a second.
-This must be bound to a mouse click."
- (interactive "e")
- (mouse-minibuffer-check click)
- (select-window (posn-window (event-start click)))
- ;; We don't use save-excursion because that preserves the mark too.
- (let ((point-save (point)))
- (unwind-protect
- (progn (mouse-set-point click)
- (push-mark nil t t)
- (or transient-mark-mode
- (sit-for 1)))
- (goto-char point-save))))
-
-(defun mouse-kill (click)
- "Kill the region between point and the mouse click.
-The text is saved in the kill ring, as with \\[kill-region]."
- (interactive "e")
- (mouse-minibuffer-check click)
- (let* ((posn (event-start click))
- (click-posn (posn-point posn)))
- (select-window (posn-window posn))
- (if (numberp click-posn)
- (kill-region (min (point) click-posn)
- (max (point) click-posn)))))
-
-(defun mouse-yank-at-click (click arg)
- "Insert the last stretch of killed text at the position clicked on.
-Also move point to one end of the text thus inserted (normally the end).
-Prefix arguments are interpreted as with \\[yank].
-If `mouse-yank-at-point' is non-nil, insert at point
-regardless of where you click."
- (interactive "e\nP")
- ;; Give temporary modes such as isearch a chance to turn off.
- (run-hooks 'mouse-leave-buffer-hook)
- (or mouse-yank-at-point (mouse-set-point click))
- (setq this-command 'yank)
- (setq mouse-selection-click-count 0)
- (yank arg))
-
-(defun mouse-kill-ring-save (click)
- "Copy the region between point and the mouse click in the kill ring.
-This does not delete the region; it acts like \\[kill-ring-save]."
- (interactive "e")
- (mouse-set-mark-fast click)
- (let (this-command last-command)
- (kill-ring-save (point) (mark t)))
- (mouse-show-mark))
-
-;;; This function used to delete the text between point and the mouse
-;;; whenever it was equal to the front of the kill ring, but some
-;;; people found that confusing.
-
-;;; A list (TEXT START END), describing the text and position of the last
-;;; invocation of mouse-save-then-kill.
-(defvar mouse-save-then-kill-posn nil)
-
-(defun mouse-save-then-kill-delete-region (beg end)
- ;; We must make our own undo boundaries
- ;; because they happen automatically only for the current buffer.
- (undo-boundary)
- (if (or (= beg end) (eq buffer-undo-list t))
- ;; If we have no undo list in this buffer,
- ;; just delete.
- (delete-region beg end)
- ;; Delete, but make the undo-list entry share with the kill ring.
- ;; First, delete just one char, so in case buffer is being modified
- ;; for the first time, the undo list records that fact.
- (let (before-change-function after-change-function
- before-change-functions after-change-functions)
- (delete-region beg
- (+ beg (if (> end beg) 1 -1))))
- (let ((buffer-undo-list buffer-undo-list))
- ;; Undo that deletion--but don't change the undo list!
- (let (before-change-function after-change-function
- before-change-functions after-change-functions)
- (primitive-undo 1 buffer-undo-list))
- ;; Now delete the rest of the specified region,
- ;; but don't record it.
- (setq buffer-undo-list t)
- (if (/= (length (car kill-ring)) (- (max end beg) (min end beg)))
- (error "Lossage in mouse-save-then-kill-delete-region"))
- (delete-region beg end))
- (let ((tail buffer-undo-list))
- ;; Search back in buffer-undo-list for the string
- ;; that came from deleting one character.
- (while (and tail (not (stringp (car (car tail)))))
- (setq tail (cdr tail)))
- ;; Replace it with an entry for the entire deleted text.
- (and tail
- (setcar tail (cons (car kill-ring) (min beg end))))))
- (undo-boundary))
-
-(defun mouse-save-then-kill (click)
- "Save text to point in kill ring; the second time, kill the text.
-If the text between point and the mouse is the same as what's
-at the front of the kill ring, this deletes the text.
-Otherwise, it adds the text to the kill ring, like \\[kill-ring-save],
-which prepares for a second click to delete the text.
-
-If you have selected words or lines, this command extends the
-selection through the word or line clicked on. If you do this
-again in a different position, it extends the selection again.
-If you do this twice in the same position, the selection is killed."
- (interactive "e")
- (let ((before-scroll point-before-scroll))
- (mouse-minibuffer-check click)
- (let ((click-posn (posn-point (event-start click)))
- ;; Don't let a subsequent kill command append to this one:
- ;; prevent setting this-command to kill-region.
- (this-command this-command))
- (if (and (save-excursion
- (set-buffer (window-buffer (posn-window (event-start click))))
- (and (mark t) (> (mod mouse-selection-click-count 3) 0)
- ;; Don't be fooled by a recent click in some other buffer.
- (eq mouse-selection-click-count-buffer
- (current-buffer)))))
- (if (not (and (eq last-command 'mouse-save-then-kill)
- (equal click-posn
- (car (cdr-safe (cdr-safe mouse-save-then-kill-posn))))))
- ;; Find both ends of the object selected by this click.
- (let* ((range
- (mouse-start-end click-posn click-posn
- mouse-selection-click-count)))
- ;; Move whichever end is closer to the click.
- ;; That's what xterm does, and it seems reasonable.
- (if (< (abs (- click-posn (mark t)))
- (abs (- click-posn (point))))
- (set-mark (car range))
- (goto-char (nth 1 range)))
- ;; We have already put the old region in the kill ring.
- ;; Replace it with the extended region.
- ;; (It would be annoying to make a separate entry.)
- (kill-new (buffer-substring (point) (mark t)) t)
- (mouse-set-region-1)
- ;; Arrange for a repeated mouse-3 to kill this region.
- (setq mouse-save-then-kill-posn
- (list (car kill-ring) (point) click-posn))
- (mouse-show-mark))
- ;; If we click this button again without moving it,
- ;; that time kill.
- (mouse-save-then-kill-delete-region (mark) (point))
- (setq mouse-selection-click-count 0)
- (setq mouse-save-then-kill-posn nil))
- (if (and (eq last-command 'mouse-save-then-kill)
- mouse-save-then-kill-posn
- (eq (car mouse-save-then-kill-posn) (car kill-ring))
- (equal (cdr mouse-save-then-kill-posn) (list (point) click-posn)))
- ;; If this is the second time we've called
- ;; mouse-save-then-kill, delete the text from the buffer.
- (progn
- (mouse-save-then-kill-delete-region (point) (mark))
- ;; After we kill, another click counts as "the first time".
- (setq mouse-save-then-kill-posn nil))
- ;; This is not a repetition.
- ;; We are adjusting an old selection or creating a new one.
- (if (or (and (eq last-command 'mouse-save-then-kill)
- mouse-save-then-kill-posn)
- (and mark-active transient-mark-mode)
- (and (memq last-command
- '(mouse-drag-region mouse-set-region))
- (or mark-even-if-inactive
- (not transient-mark-mode))))
- ;; We have a selection or suitable region, so adjust it.
- (let* ((posn (event-start click))
- (new (posn-point posn)))
- (select-window (posn-window posn))
- (if (numberp new)
- (progn
- ;; Move whichever end of the region is closer to the click.
- ;; That is what xterm does, and it seems reasonable.
- (if (< (abs (- new (point))) (abs (- new (mark t))))
- (goto-char new)
- (set-mark new))
- (setq deactivate-mark nil)))
- (kill-new (buffer-substring (point) (mark t)) t)
- (mouse-show-mark))
- ;; Set the mark where point is, then move where clicked.
- (mouse-set-mark-fast click)
- (if before-scroll
- (goto-char before-scroll))
- (exchange-point-and-mark)
- (kill-new (buffer-substring (point) (mark t)))
- (if window-system
- (mouse-show-mark)))
- (mouse-set-region-1)
- (setq mouse-save-then-kill-posn
- (list (car kill-ring) (point) click-posn)))))))
-
-(global-set-key [M-mouse-1] 'mouse-start-secondary)
-(global-set-key [M-drag-mouse-1] 'mouse-set-secondary)
-(global-set-key [M-down-mouse-1] 'mouse-drag-secondary)
-(global-set-key [M-mouse-3] 'mouse-secondary-save-then-kill)
-(global-set-key [M-mouse-2] 'mouse-yank-secondary)
-
-;; An overlay which records the current secondary selection
-;; or else is deleted when there is no secondary selection.
-;; May be nil.
-(defvar mouse-secondary-overlay nil)
-
-(defvar mouse-secondary-click-count 0)
-
-;; A marker which records the specified first end for a secondary selection.
-;; May be nil.
-(defvar mouse-secondary-start nil)
-
-(defun mouse-start-secondary (click)
- "Set one end of the secondary selection to the position clicked on.
-Use \\[mouse-secondary-save-then-kill] to set the other end
-and complete the secondary selection."
- (interactive "e")
- (mouse-minibuffer-check click)
- (let ((posn (event-start click)))
- (save-excursion
- (set-buffer (window-buffer (posn-window posn)))
- ;; Cancel any preexisting secondary selection.
- (if mouse-secondary-overlay
- (delete-overlay mouse-secondary-overlay))
- (if (numberp (posn-point posn))
- (progn
- (or mouse-secondary-start
- (setq mouse-secondary-start (make-marker)))
- (move-marker mouse-secondary-start (posn-point posn)))))))
-
-(defun mouse-set-secondary (click)
- "Set the secondary selection to the text that the mouse is dragged over.
-This must be bound to a mouse drag event."
- (interactive "e")
- (mouse-minibuffer-check click)
- (let ((posn (event-start click))
- beg
- (end (event-end click)))
- (save-excursion
- (set-buffer (window-buffer (posn-window posn)))
- (if (numberp (posn-point posn))
- (setq beg (posn-point posn)))
- (if mouse-secondary-overlay
- (move-overlay mouse-secondary-overlay beg (posn-point end))
- (setq mouse-secondary-overlay (make-overlay beg (posn-point end))))
- (overlay-put mouse-secondary-overlay 'face 'secondary-selection))))
-
-(defun mouse-drag-secondary (start-event)
- "Set the secondary selection to the text that the mouse is dragged over.
-Highlight the drag area as you move the mouse.
-This must be bound to a button-down mouse event.
-The function returns a non-nil value if it creates a secondary selection."
- (interactive "e")
- (mouse-minibuffer-check start-event)
- (let* ((echo-keystrokes 0)
- (start-posn (event-start start-event))
- (start-point (posn-point start-posn))
- (start-window (posn-window start-posn))
- (start-frame (window-frame start-window))
- (bounds (window-edges start-window))
- (top (nth 1 bounds))
- (bottom (if (window-minibuffer-p start-window)
- (nth 3 bounds)
- ;; Don't count the mode line.
- (1- (nth 3 bounds))))
- (click-count (1- (event-click-count start-event))))
- (save-excursion
- (set-buffer (window-buffer start-window))
- (setq mouse-secondary-click-count click-count)
- (or mouse-secondary-overlay
- (setq mouse-secondary-overlay
- (make-overlay (point) (point))))
- (overlay-put mouse-secondary-overlay 'face 'secondary-selection)
- (if (> (mod click-count 3) 0)
- ;; Double or triple press: make an initial selection
- ;; of one word or line.
- (let ((range (mouse-start-end start-point start-point click-count)))
- (set-marker mouse-secondary-start nil)
- (move-overlay mouse-secondary-overlay 1 1
- (window-buffer start-window))
- (move-overlay mouse-secondary-overlay (car range) (nth 1 range)
- (window-buffer start-window)))
- ;; Single-press: cancel any preexisting secondary selection.
- (or mouse-secondary-start
- (setq mouse-secondary-start (make-marker)))
- (set-marker mouse-secondary-start start-point)
- (delete-overlay mouse-secondary-overlay))
- (let (event end end-point)
- (track-mouse
- (while (progn
- (setq event (read-event))
- (or (mouse-movement-p event)
- (eq (car-safe event) 'switch-frame)))
-
- (if (eq (car-safe event) 'switch-frame)
- nil
- (setq end (event-end event)
- end-point (posn-point end))
- (cond
- ;; Are we moving within the original window?
- ((and (eq (posn-window end) start-window)
- (integer-or-marker-p end-point))
- (let ((range (mouse-start-end start-point end-point
- click-count)))
- (if (or (/= start-point end-point)
- (null (marker-position mouse-secondary-start)))
- (progn
- (set-marker mouse-secondary-start nil)
- (move-overlay mouse-secondary-overlay
- (car range) (nth 1 range))))))
- (t
- (let ((mouse-row (cdr (cdr (mouse-position)))))
- (cond
- ((null mouse-row))
- ((< mouse-row top)
- (mouse-scroll-subr start-window (- mouse-row top)
- mouse-secondary-overlay start-point))
- ((>= mouse-row bottom)
- (mouse-scroll-subr start-window (1+ (- mouse-row bottom))
- mouse-secondary-overlay start-point)))))))))
-
- (if (consp event)
- (if (marker-position mouse-secondary-start)
- (save-window-excursion
- (delete-overlay mouse-secondary-overlay)
- (x-set-selection 'SECONDARY nil)
- (select-window start-window)
- (save-excursion
- (goto-char mouse-secondary-start)
- (sit-for 1)
- nil))
- (x-set-selection
- 'SECONDARY
- (buffer-substring (overlay-start mouse-secondary-overlay)
- (overlay-end mouse-secondary-overlay)))))))))
-
-(defun mouse-yank-secondary (click)
- "Insert the secondary selection at the position clicked on.
-Move point to the end of the inserted text.
-If `mouse-yank-at-point' is non-nil, insert at point
-regardless of where you click."
- (interactive "e")
- ;; Give temporary modes such as isearch a chance to turn off.
- (run-hooks 'mouse-leave-buffer-hook)
- (or mouse-yank-at-point (mouse-set-point click))
- (insert (x-get-selection 'SECONDARY)))
-
-(defun mouse-kill-secondary ()
- "Kill the text in the secondary selection.
-This is intended more as a keyboard command than as a mouse command
-but it can work as either one.
-
-The current buffer (in case of keyboard use), or the buffer clicked on,
-must be the one that the secondary selection is in. This requirement
-is to prevent accidents."
- (interactive)
- (let* ((keys (this-command-keys))
- (click (elt keys (1- (length keys)))))
- (or (eq (overlay-buffer mouse-secondary-overlay)
- (if (listp click)
- (window-buffer (posn-window (event-start click)))
- (current-buffer)))
- (error "Select or click on the buffer where the secondary selection is")))
- (let (this-command)
- (save-excursion
- (set-buffer (overlay-buffer mouse-secondary-overlay))
- (kill-region (overlay-start mouse-secondary-overlay)
- (overlay-end mouse-secondary-overlay))))
- (delete-overlay mouse-secondary-overlay)
-;;; (x-set-selection 'SECONDARY nil)
- (setq mouse-secondary-overlay nil))
-
-(defun mouse-secondary-save-then-kill (click)
- "Save text to point in kill ring; the second time, kill the text.
-You must use this in a buffer where you have recently done \\[mouse-start-secondary].
-If the text between where you did \\[mouse-start-secondary] and where
-you use this command matches the text at the front of the kill ring,
-this command deletes the text.
-Otherwise, it adds the text to the kill ring, like \\[kill-ring-save],
-which prepares for a second click with this command to delete the text.
-
-If you have already made a secondary selection in that buffer,
-this command extends or retracts the selection to where you click.
-If you do this again in a different position, it extends or retracts
-again. If you do this twice in the same position, it kills the selection."
- (interactive "e")
- (mouse-minibuffer-check click)
- (let ((posn (event-start click))
- (click-posn (posn-point (event-start click)))
- ;; Don't let a subsequent kill command append to this one:
- ;; prevent setting this-command to kill-region.
- (this-command this-command))
- (or (eq (window-buffer (posn-window posn))
- (or (and mouse-secondary-overlay
- (overlay-buffer mouse-secondary-overlay))
- (if mouse-secondary-start
- (marker-buffer mouse-secondary-start))))
- (error "Wrong buffer"))
- (save-excursion
- (set-buffer (window-buffer (posn-window posn)))
- (if (> (mod mouse-secondary-click-count 3) 0)
- (if (not (and (eq last-command 'mouse-secondary-save-then-kill)
- (equal click-posn
- (car (cdr-safe (cdr-safe mouse-save-then-kill-posn))))))
- ;; Find both ends of the object selected by this click.
- (let* ((range
- (mouse-start-end click-posn click-posn
- mouse-secondary-click-count)))
- ;; Move whichever end is closer to the click.
- ;; That's what xterm does, and it seems reasonable.
- (if (< (abs (- click-posn (overlay-start mouse-secondary-overlay)))
- (abs (- click-posn (overlay-end mouse-secondary-overlay))))
- (move-overlay mouse-secondary-overlay (car range)
- (overlay-end mouse-secondary-overlay))
- (move-overlay mouse-secondary-overlay
- (overlay-start mouse-secondary-overlay)
- (nth 1 range)))
- ;; We have already put the old region in the kill ring.
- ;; Replace it with the extended region.
- ;; (It would be annoying to make a separate entry.)
- (kill-new (buffer-substring
- (overlay-start mouse-secondary-overlay)
- (overlay-end mouse-secondary-overlay)) t)
- ;; Arrange for a repeated mouse-3 to kill this region.
- (setq mouse-save-then-kill-posn
- (list (car kill-ring) (point) click-posn)))
- ;; If we click this button again without moving it,
- ;; that time kill.
- (progn
- (mouse-save-then-kill-delete-region
- (overlay-start mouse-secondary-overlay)
- (overlay-end mouse-secondary-overlay))
- (setq mouse-save-then-kill-posn nil)
- (setq mouse-secondary-click-count 0)
- (delete-overlay mouse-secondary-overlay)))
- (if (and (eq last-command 'mouse-secondary-save-then-kill)
- mouse-save-then-kill-posn
- (eq (car mouse-save-then-kill-posn) (car kill-ring))
- (equal (cdr mouse-save-then-kill-posn) (list (point) click-posn)))
- ;; If this is the second time we've called
- ;; mouse-secondary-save-then-kill, delete the text from the buffer.
- (progn
- (mouse-save-then-kill-delete-region
- (overlay-start mouse-secondary-overlay)
- (overlay-end mouse-secondary-overlay))
- (setq mouse-save-then-kill-posn nil)
- (delete-overlay mouse-secondary-overlay))
- (if (overlay-start mouse-secondary-overlay)
- ;; We have a selection, so adjust it.
- (progn
- (if (numberp click-posn)
- (progn
- ;; Move whichever end of the region is closer to the click.
- ;; That is what xterm does, and it seems reasonable.
- (if (< (abs (- click-posn (overlay-start mouse-secondary-overlay)))
- (abs (- click-posn (overlay-end mouse-secondary-overlay))))
- (move-overlay mouse-secondary-overlay click-posn
- (overlay-end mouse-secondary-overlay))
- (move-overlay mouse-secondary-overlay
- (overlay-start mouse-secondary-overlay)
- click-posn))
- (setq deactivate-mark nil)))
- (if (eq last-command 'mouse-secondary-save-then-kill)
- ;; If the front of the kill ring comes from
- ;; an immediately previous use of this command,
- ;; replace it with the extended region.
- ;; (It would be annoying to make a separate entry.)
- (kill-new (buffer-substring
- (overlay-start mouse-secondary-overlay)
- (overlay-end mouse-secondary-overlay)) t)
- (copy-region-as-kill (overlay-start mouse-secondary-overlay)
- (overlay-end mouse-secondary-overlay))))
- (if mouse-secondary-start
- ;; All we have is one end of a selection,
- ;; so put the other end here.
- (let ((start (+ 0 mouse-secondary-start)))
- (kill-ring-save start click-posn)
- (if mouse-secondary-overlay
- (move-overlay mouse-secondary-overlay start click-posn)
- (setq mouse-secondary-overlay (make-overlay start click-posn)))
- (overlay-put mouse-secondary-overlay 'face 'secondary-selection))))
- (setq mouse-save-then-kill-posn
- (list (car kill-ring) (point) click-posn))))
- (if (overlay-buffer mouse-secondary-overlay)
- (x-set-selection 'SECONDARY
- (buffer-substring
- (overlay-start mouse-secondary-overlay)
- (overlay-end mouse-secondary-overlay)))))))
-
-(defvar mouse-menu-buffer-maxlen 20
- "*Number of buffers in one pane (submenu) of the buffer menu.
-If we have lots of buffers, divide them into groups of
-`mouse-menu-buffer-maxlen' and make a pane (or submenu) for each one.")
-
-(defun mouse-buffer-menu (event)
- "Pop up a menu of buffers for selection with the mouse.
-This switches buffers in the window that you clicked on,
-and selects that window."
- (interactive "e")
- (mouse-minibuffer-check event)
- (let* ((buffers
- ;; Make an alist of (MENU-ITEM . BUFFER).
- (let ((tail (buffer-list))
- (maxlen 0)
- head)
- (while tail
- (or (eq ?\ (aref (buffer-name (car tail)) 0))
- (setq maxlen
- (max maxlen
- (length (buffer-name (car tail))))))
- (setq tail (cdr tail)))
- (setq tail (buffer-list))
- (while tail
- (let ((elt (car tail)))
- (if (/= (aref (buffer-name elt) 0) ?\ )
- (setq head
- (cons
- (cons
- (format
- (format "%%%ds %%s%%s %%s" maxlen)
- (buffer-name elt)
- (if (buffer-modified-p elt) "*" " ")
- (save-excursion
- (set-buffer elt)
- (if buffer-read-only "%" " "))
- (or (buffer-file-name elt)
- (save-excursion
- (set-buffer elt)
- (if list-buffers-directory
- (expand-file-name
- list-buffers-directory)))
- ""))
- elt)
- head))))
- (setq tail (cdr tail)))
- ;; Compensate for the reversal that the above loop does.
- (nreverse head)))
- (menu
- ;; If we have lots of buffers, divide them into groups of 20
- ;; and make a pane (or submenu) for each one.
- (if (> (length buffers) (/ (* mouse-menu-buffer-maxlen 3) 2))
- (let ((buffers buffers) sublists next
- (i 1))
- (while buffers
- ;; Pull off the next mouse-menu-buffer-maxlen buffers
- ;; and make them the next element of sublist.
- (setq next (nthcdr mouse-menu-buffer-maxlen buffers))
- (if next
- (setcdr (nthcdr (1- mouse-menu-buffer-maxlen) buffers)
- nil))
- (setq sublists (cons (cons (format "Buffers %d" i) buffers)
- sublists))
- (setq i (1+ i))
- (setq buffers next))
- (cons "Buffer Menu" (nreverse sublists)))
- ;; Few buffers--put them all in one pane.
- (list "Buffer Menu" (cons "Select Buffer" buffers)))))
- (let ((buf (x-popup-menu event menu))
- (window (posn-window (event-start event))))
- (if buf
- (progn
- (or (framep window) (select-window window))
- (switch-to-buffer buf))))))
-
-;;; These need to be rewritten for the new scroll bar implementation.
-
-;;;!! ;; Commands for the scroll bar.
-;;;!!
-;;;!! (defun mouse-scroll-down (click)
-;;;!! (interactive "@e")
-;;;!! (scroll-down (1+ (cdr (mouse-coords click)))))
-;;;!!
-;;;!! (defun mouse-scroll-up (click)
-;;;!! (interactive "@e")
-;;;!! (scroll-up (1+ (cdr (mouse-coords click)))))
-;;;!!
-;;;!! (defun mouse-scroll-down-full ()
-;;;!! (interactive "@")
-;;;!! (scroll-down nil))
-;;;!!
-;;;!! (defun mouse-scroll-up-full ()
-;;;!! (interactive "@")
-;;;!! (scroll-up nil))
-;;;!!
-;;;!! (defun mouse-scroll-move-cursor (click)
-;;;!! (interactive "@e")
-;;;!! (move-to-window-line (1+ (cdr (mouse-coords click)))))
-;;;!!
-;;;!! (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 (click)
-;;;!! (interactive "@e")
-;;;!! (scroll-left (1+ (car (mouse-coords click)))))
-;;;!!
-;;;!! (defun mouse-scroll-right (click)
-;;;!! (interactive "@e")
-;;;!! (scroll-right (1+ (car (mouse-coords click)))))
-;;;!!
-;;;!! (defun mouse-scroll-left-full ()
-;;;!! (interactive "@")
-;;;!! (scroll-left nil))
-;;;!!
-;;;!! (defun mouse-scroll-right-full ()
-;;;!! (interactive "@")
-;;;!! (scroll-right nil))
-;;;!!
-;;;!! (defun mouse-scroll-move-cursor-horizontally (click)
-;;;!! (interactive "@e")
-;;;!! (move-to-column (1+ (car (mouse-coords click)))))
-;;;!!
-;;;!! (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)))
-;;;!!
-;;;!! (global-set-key [scroll-bar mouse-1] 'mouse-scroll-up)
-;;;!! (global-set-key [scroll-bar mouse-2] 'mouse-scroll-absolute)
-;;;!! (global-set-key [scroll-bar mouse-3] 'mouse-scroll-down)
-;;;!!
-;;;!! (global-set-key [vertical-slider mouse-1] 'mouse-scroll-move-cursor)
-;;;!! (global-set-key [vertical-slider mouse-2] 'mouse-scroll-move-cursor)
-;;;!! (global-set-key [vertical-slider mouse-3] 'mouse-scroll-move-cursor)
-;;;!!
-;;;!! (global-set-key [thumbup mouse-1] 'mouse-scroll-up-full)
-;;;!! (global-set-key [thumbup mouse-2] 'mouse-scroll-up-full)
-;;;!! (global-set-key [thumbup mouse-3] 'mouse-scroll-up-full)
-;;;!!
-;;;!! (global-set-key [thumbdown mouse-1] 'mouse-scroll-down-full)
-;;;!! (global-set-key [thumbdown mouse-2] 'mouse-scroll-down-full)
-;;;!! (global-set-key [thumbdown mouse-3] 'mouse-scroll-down-full)
-;;;!!
-;;;!! (global-set-key [horizontal-scroll-bar mouse-1] 'mouse-scroll-left)
-;;;!! (global-set-key [horizontal-scroll-bar mouse-2]
-;;;!! 'mouse-scroll-absolute-horizontally)
-;;;!! (global-set-key [horizontal-scroll-bar mouse-3] 'mouse-scroll-right)
-;;;!!
-;;;!! (global-set-key [horizontal-slider mouse-1]
-;;;!! 'mouse-scroll-move-cursor-horizontally)
-;;;!! (global-set-key [horizontal-slider mouse-2]
-;;;!! 'mouse-scroll-move-cursor-horizontally)
-;;;!! (global-set-key [horizontal-slider mouse-3]
-;;;!! 'mouse-scroll-move-cursor-horizontally)
-;;;!!
-;;;!! (global-set-key [thumbleft mouse-1] 'mouse-scroll-left-full)
-;;;!! (global-set-key [thumbleft mouse-2] 'mouse-scroll-left-full)
-;;;!! (global-set-key [thumbleft mouse-3] 'mouse-scroll-left-full)
-;;;!!
-;;;!! (global-set-key [thumbright mouse-1] 'mouse-scroll-right-full)
-;;;!! (global-set-key [thumbright mouse-2] 'mouse-scroll-right-full)
-;;;!! (global-set-key [thumbright mouse-3] 'mouse-scroll-right-full)
-;;;!!
-;;;!! (global-set-key [horizontal-scroll-bar S-mouse-2]
-;;;!! 'mouse-split-window-horizontally)
-;;;!! (global-set-key [mode-line S-mouse-2]
-;;;!! 'mouse-split-window-horizontally)
-;;;!! (global-set-key [vertical-scroll-bar S-mouse-2]
-;;;!! 'mouse-split-window)
-
-;;;!! ;;;;
-;;;!! ;;;; 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))
-;;;!! ;; (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 scroll bar.
-;;;!! ;;
-;;;!!
-;;;!! (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))))))
-
-;; Choose a completion with the mouse.
-
-(defun mouse-choose-completion (event)
- "Click on an alternative in the `*Completions*' buffer to choose it."
- (interactive "e")
- ;; Give temporary modes such as isearch a chance to turn off.
- (run-hooks 'mouse-leave-buffer-hook)
- (let ((buffer (window-buffer))
- choice
- base-size)
- (save-excursion
- (set-buffer (window-buffer (posn-window (event-start event))))
- (if completion-reference-buffer
- (setq buffer completion-reference-buffer))
- (setq base-size completion-base-size)
- (save-excursion
- (goto-char (posn-point (event-start event)))
- (let (beg end)
- (if (and (not (eobp)) (get-text-property (point) 'mouse-face))
- (setq end (point) beg (1+ (point))))
- (if (null beg)
- (error "No completion here"))
- (setq beg (previous-single-property-change beg 'mouse-face))
- (setq end (or (next-single-property-change end 'mouse-face)
- (point-max)))
- (setq choice (buffer-substring beg end)))))
- (let ((owindow (selected-window)))
- (select-window (posn-window (event-start event)))
- (if (and (one-window-p t 'selected-frame)
- (window-dedicated-p (selected-window)))
- ;; This is a special buffer's frame
- (iconify-frame (selected-frame))
- (or (window-dedicated-p (selected-window))
- (bury-buffer)))
- (select-window owindow))
- (choose-completion-string choice buffer base-size)))
-
-;; Font selection.
-
-(defun font-menu-add-default ()
- (let* ((default (cdr (assq 'font (frame-parameters (selected-frame)))))
- (font-alist x-fixed-font-alist)
- (elt (or (assoc "Misc" font-alist) (nth 1 font-alist))))
- (if (assoc "Default" elt)
- (delete (assoc "Default" elt) elt))
- (setcdr elt
- (cons (list "Default"
- (cdr (assq 'font (frame-parameters (selected-frame)))))
- (cdr elt)))))
-
-(defvar x-fixed-font-alist
- '("Font menu"
- ("Misc"
- ;; For these, we specify the pixel height and width.
- ("fixed" "fixed")
- ("6x10" "-misc-fixed-medium-r-normal--10-*-*-*-c-60-iso8859-1" "6x10")
- ("6x12"
- "-misc-fixed-medium-r-semicondensed--12-*-*-*-c-60-iso8859-1" "6x12")
- ("6x13"
- "-misc-fixed-medium-r-semicondensed--13-*-*-*-c-60-iso8859-1" "6x13")
- ("7x13" "-misc-fixed-medium-r-normal--13-*-*-*-c-70-iso8859-1" "7x13")
- ("7x14" "-misc-fixed-medium-r-normal--14-*-*-*-c-70-iso8859-1" "7x14")
- ("8x13" "-misc-fixed-medium-r-normal--13-*-*-*-c-80-iso8859-1" "8x13")
- ("9x15" "-misc-fixed-medium-r-normal--15-*-*-*-c-90-iso8859-1" "9x15")
- ("10x20" "-misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1" "10x20")
- ("11x18" "-misc-fixed-medium-r-normal--18-*-*-*-c-110-iso8859-1" "11x18")
- ("12x24" "-misc-fixed-medium-r-normal--24-*-*-*-c-120-iso8859-1" "12x24")
- ("")
- ("clean 5x8"
- "-schumacher-clean-medium-r-normal--8-*-*-*-c-50-iso8859-1")
- ("clean 6x8"
- "-schumacher-clean-medium-r-normal--8-*-*-*-c-60-iso8859-1")
- ("clean 8x8"
- "-schumacher-clean-medium-r-normal--8-*-*-*-c-80-iso8859-1")
- ("clean 8x10"
- "-schumacher-clean-medium-r-normal--10-*-*-*-c-80-iso8859-1")
- ("clean 8x14"
- "-schumacher-clean-medium-r-normal--14-*-*-*-c-80-iso8859-1")
- ("clean 8x16"
- "-schumacher-clean-medium-r-normal--16-*-*-*-c-80-iso8859-1")
- ("")
- ("sony 8x16" "-sony-fixed-medium-r-normal--16-*-*-*-c-80-iso8859-1"))
-;;; We don't seem to have these; who knows what they are.
-;;; ("fg-18" "fg-18")
-;;; ("fg-25" "fg-25")
-;;; ("lucidasanstypewriter-12" "lucidasanstypewriter-12")
-;;; ("lucidasanstypewriter-bold-14" "lucidasanstypewriter-bold-14")
-;;; ("lucidasanstypewriter-bold-24" "lucidasanstypewriter-bold-24")
-;;; ("lucidatypewriter-bold-r-24" "-b&h-lucidatypewriter-bold-r-normal-sans-24-240-75-75-m-140-iso8859-1")
-;;; ("fixed-medium-20" "-misc-fixed-medium-*-*-*-20-*-*-*-*-*-*-*")
- ("Courier"
- ;; For these, we specify the point height.
- ("8" "-adobe-courier-medium-r-normal--*-80-*-*-m-*-iso8859-1")
- ("10" "-adobe-courier-medium-r-normal--*-100-*-*-m-*-iso8859-1")
- ("12" "-adobe-courier-medium-r-normal--*-120-*-*-m-*-iso8859-1")
- ("14" "-adobe-courier-medium-r-normal--*-140-*-*-m-*-iso8859-1")
- ("18" "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1")
- ("24" "-adobe-courier-medium-r-normal--*-240-*-*-m-*-iso8859-1")
- ("8 bold" "-adobe-courier-bold-r-normal--*-80-*-*-m-*-iso8859-1")
- ("10 bold" "-adobe-courier-bold-r-normal--*-100-*-*-m-*-iso8859-1")
- ("12 bold" "-adobe-courier-bold-r-normal--*-120-*-*-m-*-iso8859-1")
- ("14 bold" "-adobe-courier-bold-r-normal--*-140-*-*-m-*-iso8859-1")
- ("18 bold" "-adobe-courier-bold-r-normal--*-180-*-*-m-*-iso8859-1")
- ("24 bold" "-adobe-courier-bold-r-normal--*-240-*-*-m-*-iso8859-1")
- ("8 slant" "-adobe-courier-medium-o-normal--*-80-*-*-m-*-iso8859-1")
- ("10 slant" "-adobe-courier-medium-o-normal--*-100-*-*-m-*-iso8859-1")
- ("12 slant" "-adobe-courier-medium-o-normal--*-120-*-*-m-*-iso8859-1")
- ("14 slant" "-adobe-courier-medium-o-normal--*-140-*-*-m-*-iso8859-1")
- ("18 slant" "-adobe-courier-medium-o-normal--*-180-*-*-m-*-iso8859-1")
- ("24 slant" "-adobe-courier-medium-o-normal--*-240-*-*-m-*-iso8859-1")
- ("8 bold slant" "-adobe-courier-bold-o-normal--*-80-*-*-m-*-iso8859-1")
- ("10 bold slant" "-adobe-courier-bold-o-normal--*-100-*-*-m-*-iso8859-1")
- ("12 bold slant" "-adobe-courier-bold-o-normal--*-120-*-*-m-*-iso8859-1")
- ("14 bold slant" "-adobe-courier-bold-o-normal--*-140-*-*-m-*-iso8859-1")
- ("18 bold slant" "-adobe-courier-bold-o-normal--*-180-*-*-m-*-iso8859-1")
- ("24 bold slant" "-adobe-courier-bold-o-normal--*-240-*-*-m-*-iso8859-1"))
- )
- "X fonts suitable for use in Emacs.")
-
-(defun mouse-set-font (&rest fonts)
- "Select an emacs font from a list of known good fonts"
- (interactive
- (x-popup-menu last-nonmenu-event x-fixed-font-alist))
- (if fonts
- (let (font)
- (while fonts
- (condition-case nil
- (progn
- (set-default-font (car fonts))
- (setq font (car fonts))
- (setq fonts nil))
- (error
- (setq fonts (cdr fonts)))))
- (if (null font)
- (error "Font not found")))))
-
-;;; Bindings for mouse commands.
-
-(define-key global-map [down-mouse-1] 'mouse-drag-region)
-(global-set-key [mouse-1] 'mouse-set-point)
-(global-set-key [drag-mouse-1] 'mouse-set-region)
-
-;; These are tested for in mouse-drag-region.
-(global-set-key [double-mouse-1] 'mouse-set-point)
-(global-set-key [triple-mouse-1] 'mouse-set-point)
-
-(global-set-key [mouse-2] 'mouse-yank-at-click)
-(global-set-key [mouse-3] 'mouse-save-then-kill)
-
-;; By binding these to down-going events, we let the user use the up-going
-;; event to make the selection, saving a click.
-(global-set-key [C-down-mouse-1] 'mouse-buffer-menu)
-(if (not (eq system-type 'ms-dos))
- (global-set-key [S-down-mouse-1] 'mouse-set-font))
-;; C-down-mouse-2 is bound in facemenu.el.
-(global-set-key [C-down-mouse-3] 'mouse-major-mode-menu)
-
-
-;; Replaced with dragging mouse-1
-;; (global-set-key [S-mouse-1] 'mouse-set-mark)
-
-(global-set-key [mode-line mouse-1] 'mouse-select-window)
-(global-set-key [mode-line drag-mouse-1] 'mouse-select-window)
-(global-set-key [mode-line down-mouse-1] 'mouse-drag-mode-line)
-(global-set-key [mode-line mouse-2] 'mouse-delete-other-windows)
-(global-set-key [mode-line mouse-3] 'mouse-delete-window)
-(global-set-key [mode-line C-mouse-2] 'mouse-split-window-horizontally)
-(global-set-key [vertical-scroll-bar C-mouse-2] 'mouse-split-window-vertically)
-(global-set-key [vertical-line C-mouse-2] 'mouse-split-window-vertically)
-(global-set-key [vertical-line down-mouse-1] 'mouse-drag-vertical-line)
-(global-set-key [vertical-line mouse-1] 'mouse-select-window)
-
-(provide 'mouse)
-
-;;; mouse.el ends here
diff --git a/lisp/msb.el b/lisp/msb.el
deleted file mode 100644
index 70361ea5fcd..00000000000
--- a/lisp/msb.el
+++ /dev/null
@@ -1,1002 +0,0 @@
-;;; msb.el --- Customizable buffer-selection with multiple menus.
-
-;; Copyright (C) 1993, 1994, 1995 Lars Lindberg <Lars.Lindberg@sypro.cap.se>
-
-;; Author: Lars Lindberg <Lars.Lindberg@sypro.cap.se>
-;; Created: 8 Oct 1993
-;; Lindberg's last update version: 3.31
-;; Keywords: mouse buffer menu
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Purpose of this package:
-;; 1. Offer a function for letting the user choose buffer,
-;; not necessarily for switching to it.
-;; 2. Make a better mouse-buffer-menu.
-;;
-;; Installation:
-
-;; 1. Byte compile msb first. It uses things in the cl package that
-;; are slow if not compiled, but blazingly fast when compiled. I
-;; have also had one report that said that msb malfunctioned when
-;; not compiled.
-;; 2. (require 'msb)
-;; Note! You now use msb instead of mouse-buffer-menu.
-;; 3. Now try the menu bar Buffers menu.
-;;
-;; Customization:
-;; Look at the variable `msb-menu-cond' for deciding what menus you
-;; want. It's not that hard to customize, despite my not-so-good
-;; doc-string. Feel free to send me a better doc-string.
-;; There are some constants for you to try here:
-;; msb--few-menus
-;; msb--very-many-menus (default)
-;;
-;; Look at the variable `msb-item-handling-function' for customization
-;; of the appearance of every menu item. Try for instance setting
-;; it to `msb-alon-item-handler'.
-;;
-;; Look at the variable `msb-item-sort-function' for customization
-;; of sorting the menus. Set it to t for instance, which means no
-;; sorting - you will get latest used buffer first.
-;;
-;; Also check out the variable `msb-display-invisible-buffers-p'.
-
-;; Known bugs:
-;; - Files-by-directory
-;; + No possibility to show client/changed buffers separately.
-;; + All file buffers only appear in in a file sub-menu, they will
-;; for instance not appear in the Mail sub-menu.
-
-;; Future enhancements:
-
-;;; Thanks goes to
-;; Mark Brader <msb@sq.com>
-;; Jim Berry <m1jhb00@FRB.GOV>
-;; Hans Chalupsky <hans@cs.Buffalo.EDU>
-;; Larry Rosenberg <ljr@ictv.com>
-;; Will Henney <will@astroscu.unam.mx>
-;; Jari Aalto <jaalto@tre.tele.nokia.fi>
-;; Michael Kifer <kifer@sbkifer.cs.sunysb.edu>
-;; Gael Marziou <gael@gnlab030.grenoble.hp.com>
-;; Dave Gillespie <daveg@thymus.synaptics.com>
-;; Alon Albert <alon@milcse.rtsg.mot.com>
-;; Kevin Broadey, <KevinB@bartley.demon.co.uk>
-;; Ake Stenhof <ake@cadpoint.se>
-;; Richard Stallman <rms@gnu.ai.mit.edu>
-;; Steve Fisk <fisk@medved.bowdoin.edu>
-
-;;; Code:
-
-(require 'cl)
-
-;;;
-;;; Some example constants to be used for `msb-menu-cond'. See that
-;;; variable for more information. Please note that if the condition
-;;; returns `multi', then the buffer can appear in several menus.
-;;;
-(defconst msb--few-menus
- '(((and (boundp 'server-buffer-clients)
- server-buffer-clients
- 'multi)
- 3030
- "Clients (%d)")
- ((and msb-display-invisible-buffers-p
- (msb-invisible-buffer-p)
- 'multi)
- 3090
- "Invisible buffers (%d)")
- ((eq major-mode 'dired-mode)
- 2010
- "Dired (%d)"
- msb-dired-item-handler
- msb-sort-by-directory)
- ((eq major-mode 'Man-mode)
- 4090
- "Manuals (%d)")
- ((eq major-mode 'w3-mode)
- 4020
- "WWW (%d)")
- ((or (memq major-mode '(rmail-mode rmail-edit-mode vm-summary-mode vm-mode mail-mode))
- (memq major-mode '(mh-letter-mode
- mh-show-mode
- mh-folder-mode))
- (memq major-mode '(gnus-summary-mode
- news-reply-mode
- gnus-group-mode
- gnus-article-mode
- gnus-kill-file-mode
- gnus-browse-killed-mode)))
- 4010
- "Mail (%d)")
- ((not buffer-file-name)
- 4099
- "Buffers (%d)")
- ('no-multi
- 1099
- "Files (%d)")))
-
-(defconst msb--very-many-menus
- '(((and (boundp 'server-buffer-clients)
- server-buffer-clients
- 'multi)
- 1010
- "Clients (%d)")
- ((and (boundp 'vc-mode) vc-mode 'multi)
- 1020
- "Version Control (%d)")
- ((and buffer-file-name
- (buffer-modified-p)
- 'multi)
- 1030
- "Changed files (%d)")
- ((and (get-buffer-process (current-buffer))
- 'multi)
- 1040
- "Processes (%d)")
- ((and msb-display-invisible-buffers-p
- (msb-invisible-buffer-p)
- 'multi)
- 1090
- "Invisible buffers (%d)")
- ((eq major-mode 'dired-mode)
- 2010
- "Dired (%d)"
- ;; Note this different menu-handler
- msb-dired-item-handler
- ;; Also note this item-sorter
- msb-sort-by-directory)
- ((eq major-mode 'Man-mode)
- 4030
- "Manuals (%d)")
- ((eq major-mode 'w3-mode)
- 4020
- "WWW (%d)")
- ((or (memq major-mode '(rmail-mode rmail-edit-mode vm-summary-mode vm-mode mail-mode))
- (memq major-mode '(mh-letter-mode
- mh-show-mode
- mh-folder-mode))
- (memq major-mode '(gnus-summary-mode
- news-reply-mode
- gnus-group-mode
- gnus-article-mode
- gnus-kill-file-mode
- gnus-browse-killed-mode)))
- 4010
- "Mail (%d)")
- ;; Catchup for all non-file buffers
- ((and (not buffer-file-name)
- 'no-multi)
- 4099
- "Other non-file buffers (%d)")
- ((and (string-match "/\\.[^/]*$" buffer-file-name)
- 'multi)
- 3090
- "Hidden Files (%d)")
- ((memq major-mode '(c-mode c++-mode))
- 3010
- "C/C++ Files (%d)")
- ((eq major-mode 'emacs-lisp-mode)
- 3020
- "Elisp Files (%d)")
- ((eq major-mode 'latex-mode)
- 3030
- "LaTex Files (%d)")
- ('no-multi
- 3099
- "Other files (%d)")))
-
-;; msb--many-menus is obsolete
-(defvar msb--many-menus msb--very-many-menus)
-
-;;;
-;;; Customizable variables
-;;;
-
-(defvar msb-separator-diff 100
- "*Non-nil means use separators.
-The separators will appear between all menus that have a sorting key that differs by this value or more.")
-
-(defvar msb-files-by-directory-sort-key 0
- "*The sort key for files sorted by directory")
-
-(defvar msb-max-menu-items 15
- "*The maximum number of items in a menu.
-If this variable is set to 15 for instance, then the submenu will be split up in minor parts, 15 items each.
-Nil means no limit.")
-
-(defvar msb-max-file-menu-items 10
- "*The maximum number of items from different directories.
-
-When the menu is of type `file by directory', this is the maximum
-number of buffers that are clumped together from different
-directories.
-
-Set this to 1 if you want one menu per directory instead of clumping
-them together.
-
-If the value is not a number, then the value 10 is used.")
-
-(defvar msb-most-recently-used-sort-key -1010
- "*Where should the menu with the most recently used buffers be placed?")
-
-(defvar msb-display-most-recently-used 15
- "*How many buffers should be in the most-recently-used menu.
- No buffers at all if less than 1 or nil (or any non-number).")
-
-(defvar msb-most-recently-used-title "Most recently used (%d)"
- "*The title for the most-recently-used menu.")
-
-(defvar msb-horizontal-shift-function '(lambda () 0)
- "*Function that specifies a number of pixels by which the top menu should
-be shifted leftwards.")
-
-(defvar msb-display-invisible-buffers-p nil
- "*Show invisible buffers or not.
-Non-nil means that the buffer menu should include buffers that have
-names that starts with a space character.")
-
-(defvar msb-item-handling-function 'msb-item-handler
- "*The appearance of a buffer menu.
-
-The default function to call for handling the appearance of a menu
-item. It should take to arguments, BUFFER and MAX-BUFFER-NAME-LENGTH,
-where the latter is the max length of all buffer names.
-
-The function should return the string to use in the menu.
-
-When the function is called, BUFFER is the current buffer.
-This function is called for items in the variable `msb-menu-cond' that
-have nil as ITEM-HANDLING-FUNCTION. See `msb-menu-cond' for more
-information.")
-
-(defvar msb-item-sort-function 'msb-sort-by-name
- "*The order of items in a buffer menu.
-The default function to call for handling the order of items in a menu
-item. This function is called like a sort function. The items
-look like (ITEM-NAME . BUFFER).
-ITEM-NAME is the name of the item that will appear in the menu.
-BUFFER is the buffer, this is not necessarily the current buffer.
-
-Set this to nil or t if you don't want any sorting (faster).")
-
-(defvar msb-files-by-directory nil
- "*Non-nil means that files should be sorted by directory instead of
-the groups in msb-menu-cond.")
-
-(defvar msb-menu-cond msb--very-many-menus
- "*List of criteria for splitting the mouse buffer menu.
-The elements in the list should be of this type:
- (CONDITION MENU-SORT-KEY MENU-TITLE ITEM-HANDLING-FN ITEM-SORT-FN).
-
-When making the split, the buffers are tested one by one against the
-CONDITION, just like a lisp cond: When hitting a true condition, the
-other criteria are *not* tested and the buffer name will appear in
-the menu with the menu-title corresponding to the true condition.
-
-If the condition returns the symbol `multi', then the buffer will be
-added to this menu *and* tested for other menus too. If it returns
-`no-multi', then the buffer will only be added if it hasn't been added
-to any other menu.
-
-During this test, the buffer in question is the current buffer, and
-the test is surrounded by calls to `save-excursion' and
-`save-match-data'.
-
-The categories are sorted by MENU-SORT-KEY. Smaller keys are on
-top. nil means don't display this menu.
-
-MENU-TITLE is really a format. If you add %d in it, the %d is replaced
-with the number of items in that menu.
-
-ITEM-HANDLING-FN, is optional. If it is supplied and is a
-function, than it is used for displaying the items in that particular
-buffer menu, otherwise the function pointed out by
-`msb-item-handling-function' is used.
-
-ITEM-SORT-FN, is also optional.
-If it is not supplied, the function pointed out by
-`msb-item-sort-function' is used.
-If it is nil, then no sort takes place and the buffers are presented
-in least-recently-used order.
-If it is t, then no sort takes place and the buffers are presented in
-most-recently-used order.
-If it is supplied and non-nil and not t than it is used for sorting
-the items in that particular buffer menu.
-
-Note1: There should always be a `catch-all' as last element,
-in this list. That is an element like (t TITLE ITEM-HANDLING-FUNCTION).
-Note2: A buffer menu appears only if it has at least one buffer in it.
-Note3: If you have a CONDITION that can't be evaluated you will get an
-error every time you do \\[msb].")
-
-(defvar msb-after-load-hooks nil
- "Hooks to be run after the msb package has been loaded.")
-
-;;;
-;;; Internal variables
-;;;
-
-;; The last calculated menu.
-(defvar msb--last-buffer-menu nil)
-
-;; If this is non-nil, then it is a string that describes the error.
-(defvar msb--error nil)
-
-;;;
-;;; Some example function to be used for `msb-item-handling-function'.
-;;;
-(defun msb-item-handler (buffer &optional maxbuf)
- "Create one string item, concerning BUFFER, for the buffer menu.
-The item looks like:
-*% <buffer-name>
-The `*' appears only if the buffer is marked as modified.
-The `%' appears only if the buffer is read-only.
-Optional second argument MAXBUF is completely ignored."
- (let ((name (buffer-name))
- (modified (if (buffer-modified-p) "*" " "))
- (read-only (if buffer-read-only "%" " ")))
- (format "%s%s %s" modified read-only name)))
-
-
-(eval-when-compile (require 'dired))
-
-;; `dired' can be called with a list of the form (directory file1 file2 ...)
-;; which causes `dired-directory' to be in the same form.
-(defun msb--dired-directory ()
- (cond ((stringp dired-directory)
- (abbreviate-file-name (expand-file-name dired-directory)))
- ((consp dired-directory)
- (abbreviate-file-name (expand-file-name (car dired-directory))))
- (t
- (error "Unknown type of `dired-directory' in buffer %s"
- (buffer-name)))))
-
-(defun msb-dired-item-handler (buffer &optional maxbuf)
- "Create one string item, concerning a dired BUFFER, for the buffer menu.
-The item looks like:
-*% <buffer-name>
-The `*' appears only if the buffer is marked as modified.
-The `%' appears only if the buffer is read-only.
-Optional second argument MAXBUF is completely ignored."
- (let ((name (msb--dired-directory))
- (modified (if (buffer-modified-p) "*" " "))
- (read-only (if buffer-read-only "%" " ")))
- (format "%s%s %s" modified read-only name)))
-
-(defun msb-alon-item-handler (buffer maxbuf)
- "Create one string item for the buffer menu.
-The item looks like:
-<buffer-name> *%# <file-name>
-The `*' appears only if the buffer is marked as modified.
-The `%' appears only if the buffer is read-only.
-The `#' appears only version control file (SCCS/RCS)."
- (format (format "%%%ds %%s%%s%%s %%s" maxbuf)
- (buffer-name buffer)
- (if (buffer-modified-p) "*" " ")
- (if buffer-read-only "%" " ")
- (if (and (boundp 'vc-mode) vc-mode) "#" " ")
- (or buffer-file-name "")))
-
-;;;
-;;; Some example function to be used for `msb-item-sort-function'.
-;;;
-(defun msb-sort-by-name (item1 item2)
- "Sorts the items depending on their buffer-name
-An item look like (NAME . BUFFER)."
- (string-lessp (buffer-name (cdr item1))
- (buffer-name (cdr item2))))
-
-
-(defun msb-sort-by-directory (item1 item2)
- "Sorts the items depending on their directory. Made for dired.
-An item look like (NAME . BUFFER)."
- (string-lessp (save-excursion (set-buffer (cdr item1)) (msb--dired-directory))
- (save-excursion (set-buffer (cdr item2)) (msb--dired-directory))))
-
-;;;
-;;; msb
-;;;
-;;; This function can be used instead of (mouse-buffer-menu EVENT)
-;;; function in "mouse.el".
-;;;
-(defun msb (event)
- "Pop up several menus of buffers for selection with the mouse.
-This command switches buffers in the window that you clicked on, and
-selects that window.
-
-See the function `mouse-select-buffer' and the variable
-`msb-menu-cond' for more information about how the menus are split."
- (interactive "e")
- (let ((old-window (selected-window))
- (window (posn-window (event-start event))))
- (unless (framep window) (select-window window))
- (let ((buffer (mouse-select-buffer event)))
- (if buffer
- (switch-to-buffer buffer)
- (select-window old-window))))
- nil)
-
-;;;
-;;; Some supportive functions
-;;;
-(defun msb-invisible-buffer-p (&optional buffer)
- "Return t if optional BUFFER is an \"invisible\" buffer.
-If the argument is left out or nil, then the current buffer is considered."
- (and (> (length (buffer-name buffer)) 0)
- (eq ?\ (aref (buffer-name buffer) 0))))
-
-;; Strip one hierarchy level from the end of PATH.
-(defun msb--strip-path (path)
- (save-match-data
- (if (string-match "\\(.+\\)/[^/]+$" path)
- (substring path (match-beginning 1) (match-end 1))
- "/")))
-
-;; Create an alist with all buffers from LIST that lies under the same
-;; directory will be in the same item as the directory string as
-;; ((PATH1 . (BUFFER-1 BUFFER-2 ...)) (PATH2 . (BUFFER-K BUFFER-K+1...)) ...)
-(defun msb--init-file-alist (list)
- (let ((buffer-alist
- (sort (mapcan
- (function
- (lambda (buffer)
- (let ((file-name (buffer-file-name buffer)))
- (when file-name
- (list (cons (msb--strip-path file-name) buffer))))))
- list)
- (function (lambda (item1 item2)
- (string< (car item1) (car item2)))))))
- ;; Make alist that looks like
- ;; ((PATH1 . (BUFFER-1 BUFFER-2 ...)) (PATH2 . (BUFFER-K)) ...)
- (let ((path nil)
- (buffers nil)
- (result nil))
- (append
- (mapcan (function
- (lambda (item)
- (cond
- ((and path
- (string= path (car item)))
- (push (cdr item) buffers)
- nil)
- (t
- (when path
- (setq result (cons path buffers)))
- (setq path (car item))
- (setq buffers (list (cdr item)))
- (and result (list result))))))
- buffer-alist)
- (list (cons path buffers))))))
-
-;; Choose file-menu with respect to directory for every buffer in LIST.
-(defun msb--choose-file-menu (list)
- (let ((buffer-alist (msb--init-file-alist list))
- (final-list nil)
- (max-clumped-together (if (numberp msb-max-file-menu-items)
- msb-max-file-menu-items
- 10))
- (top-found-p nil)
- (last-path nil)
- first rest path buffers)
- (setq first (car buffer-alist))
- (setq rest (cdr buffer-alist))
- (setq path (car first))
- (setq buffers (cdr first))
- (while rest
- (let ((found-p nil)
- (tmp-rest rest)
- new-path item)
- (setq item (car tmp-rest))
- (while (and tmp-rest
- (<= (length buffers) max-clumped-together)
- (>= (length (car item)) (length path))
- (string= path (substring (car item) 0 (length path))))
- (setq found-p t)
- (setq buffers (append buffers (cdr item)))
- (setq tmp-rest (cdr tmp-rest))
- (setq item (car tmp-rest)))
- (cond
- ((> (length buffers) max-clumped-together)
- (setq last-path (car first))
- (setq first
- (cons (format (if top-found-p
- "%s/... (%d)"
- "%s (%d)")
- (car first)
- (length (cdr first)))
- (cdr first)))
- (setq top-found-p nil)
- (push first final-list)
- (setq first (car rest)
- rest (cdr rest))
- (setq path (car first)
- buffers (cdr first)))
- (t
- (when found-p
- (setq top-found-p t)
- (setq first (cons path buffers)
- rest tmp-rest))
- (setq path (msb--strip-path path)
- buffers (cdr first))
- (when (and last-path
- (or (and (>= (length path) (length last-path))
- (string= last-path
- (substring path 0 (length last-path))))
- (and (< (length path) (length last-path))
- (string= path
- (substring last-path 0 (length path))))))
-
- (setq first
- (cons (format (if top-found-p
- "%s/... (%d)"
- "%s (%d)")
- (car first)
- (length (cdr first)))
- (cdr first)))
- (setq top-found-p nil)
- (push first final-list)
- (setq first (car rest)
- rest (cdr rest))
- (setq path (car first)
- buffers (cdr first)))))))
- (setq first
- (cons (format (if top-found-p
- "%s/... (%d)"
- "%s (%d)")
- (car first)
- (length (cdr first)))
- (cdr first)))
- (setq top-found-p nil)
- (push first final-list)
- (nreverse final-list)))
-
-;; Create a vector as:
-;; [BUFFER-LIST-VARIABLE CONDITION MENU-SORT-KEY MENU-TITLE ITEM-HANDLER SORTER)
-;; from an element in `msb-menu-cond'. See that variable for a
-;; description of its elements.
-(defun msb--create-function-info (menu-cond-elt)
- (let* ((list-symbol (make-symbol "-msb-buffer-list"))
- (tmp-ih (and (> (length menu-cond-elt) 3)
- (nth 3 menu-cond-elt)))
- (item-handler (if (and tmp-ih (fboundp tmp-ih))
- tmp-ih
- msb-item-handling-function))
- (tmp-s (if (> (length menu-cond-elt) 4)
- (nth 4 menu-cond-elt)
- msb-item-sort-function))
- (sorter (if (or (fboundp tmp-s)
- (null tmp-s)
- (eq tmp-s t))
- tmp-s
- msb-item-sort-function)))
- (when (< (length menu-cond-elt) 3)
- (error "Wrong format of msb-menu-cond."))
- (when (and (> (length menu-cond-elt) 3)
- (not (fboundp tmp-ih)))
- (signal 'invalid-function (list tmp-ih)))
- (when (and (> (length menu-cond-elt) 4)
- tmp-s
- (not (fboundp tmp-s))
- (not (eq tmp-s t)))
- (signal 'invalid-function (list tmp-s)))
- (set list-symbol ())
- (vector list-symbol ;BUFFER-LIST-VARIABLE
- (nth 0 menu-cond-elt) ;CONDITION
- (nth 1 menu-cond-elt) ;SORT-KEY
- (nth 2 menu-cond-elt) ;MENU-TITLE
- item-handler ;ITEM-HANDLER
- sorter) ;SORTER
- ))
-
-;; This defsubst is only used in `msb--choose-menu' below. It was
-;; pulled out merely to make the code somewhat clearer. The indention
-;; level was too big.
-(defsubst msb--collect (function-info-vector)
- (let ((result nil)
- (multi-flag nil)
- function-info-list)
- (setq function-info-list
- (loop for fi
- across function-info-vector
- if (and (setq result
- (eval (aref fi 1))) ;Test CONDITION
- (not (and (eq result 'no-multi)
- multi-flag))
- (progn (when (eq result 'multi)
- (setq multi-flag t))
- t))
- collect fi
- until (and result
- (not (eq result 'multi)))))
- (when (and (not function-info-list)
- (not result))
- (error "No catch-all in msb-menu-cond!"))
- function-info-list))
-
-;; Adds BUFFER to the menu depicted by FUNCTION-INFO
-;; All side-effects. Adds an element of form (BUFFER-TITLE . BUFFER)
-;; to the buffer-list variable in function-info.
-(defun msb--add-to-menu (buffer function-info max-buffer-name-length)
- (let ((list-symbol (aref function-info 0))) ;BUFFER-LIST-VARIABLE
- ;; Here comes the hairy side-effect!
- (set list-symbol
- (cons (cons (funcall (aref function-info 4) ;ITEM-HANDLER
- buffer
- max-buffer-name-length)
- buffer)
- (eval list-symbol)))))
-
-;; Selects the appropriate menu for BUFFER.
-;; This is all side-effects, folks!
-;; This should be optimized.
-(defsubst msb--choose-menu (buffer function-info-vector max-buffer-name-length)
- (unless (and (not msb-display-invisible-buffers-p)
- (msb-invisible-buffer-p buffer))
- (condition-case nil
- (save-excursion
- (set-buffer buffer)
- ;; Menu found. Add to this menu
- (mapc (function
- (lambda (function-info)
- (msb--add-to-menu buffer function-info max-buffer-name-length)))
- (msb--collect function-info-vector)))
- (error (unless msb--error
- (setq msb--error
- (format
- "In msb-menu-cond, error for buffer `%s'."
- (buffer-name buffer)))
- (error "%s" msb--error))))))
-
-;; Return (SORT-KEY TITLE . BUFFER-LIST) or nil if the
-;; buffer-list is empty.
-(defun msb--create-sort-item (function-info)
- (let ((buffer-list (eval (aref function-info 0))))
- (when buffer-list
- (let ((sorter (aref function-info 5)) ;SORTER
- (sort-key (aref function-info 2))) ;MENU-SORT-KEY
- (when sort-key
- (cons sort-key
- (cons (format (aref function-info 3) ;MENU-TITLE
- (length buffer-list))
- (cond
- ((null sorter)
- buffer-list)
- ((eq sorter t)
- (nreverse buffer-list))
- (t
- (sort buffer-list sorter))))))))))
-
-;; Returns a list on the form ((TITLE . BUFFER-LIST)) for
-;; the most recently used buffers.
-(defun msb--most-recently-used-menu (max-buffer-name-length)
- (when (and (numberp msb-display-most-recently-used)
- (> msb-display-most-recently-used 0))
- (let* ((buffers (cdr (buffer-list)))
- (most-recently-used
- (loop with n = 0
- for buffer in buffers
- if (save-excursion
- (set-buffer buffer)
- (and (not (msb-invisible-buffer-p))
- (not (eq major-mode 'dired-mode))))
- collect (save-excursion
- (set-buffer buffer)
- (cons (funcall msb-item-handling-function
- buffer
- max-buffer-name-length)
- buffer))
- and do (incf n)
- until (>= n msb-display-most-recently-used))))
- (cons (if (stringp msb-most-recently-used-title)
- (format msb-most-recently-used-title
- (length most-recently-used))
- (signal 'wrong-type-argument (list msb-most-recently-used-title)))
- most-recently-used))))
-
-(defun msb--create-buffer-menu-2 ()
- (let ((max-buffer-name-length 0)
- file-buffers
- function-info-vector)
- ;; Calculate the longest buffer name.
- (mapc
- (function
- (lambda (buffer)
- (if (or msb-display-invisible-buffers-p
- (not (msb-invisible-buffer-p)))
- (setq max-buffer-name-length
- (max max-buffer-name-length
- (length (buffer-name buffer)))))))
- (buffer-list))
- ;; Make a list with elements of type
- ;; (BUFFER-LIST-VARIABLE
- ;; CONDITION
- ;; MENU-SORT-KEY
- ;; MENU-TITLE
- ;; ITEM-HANDLER
- ;; SORTER)
- ;; Uses "function-global" variables:
- ;; function-info-vector
- (setq function-info-vector
- (apply (function vector)
- (mapcar (function msb--create-function-info)
- msb-menu-cond)))
- ;; Split the buffer-list into several lists; one list for each
- ;; criteria. This is the most critical part with respect to time.
- (mapc (function (lambda (buffer)
- (cond ((and msb-files-by-directory
- (buffer-file-name buffer))
- (push buffer file-buffers))
- (t
- (msb--choose-menu buffer
- function-info-vector
- max-buffer-name-length)))))
- (buffer-list))
- (when file-buffers
- (setq file-buffers
- (mapcar (function
- (lambda (buffer-list)
- (cons msb-files-by-directory-sort-key
- (cons (car buffer-list)
- (sort
- (mapcar (function
- (lambda (buffer)
- (cons (save-excursion
- (set-buffer buffer)
- (funcall msb-item-handling-function
- buffer
- max-buffer-name-length))
- buffer)))
- (cdr buffer-list))
- (function
- (lambda (item1 item2)
- (string< (car item1) (car item2)))))))))
- (msb--choose-file-menu file-buffers))))
- ;; Now make the menu - a list of (TITLE . BUFFER-LIST)
- (let* (menu
- (most-recently-used
- (msb--most-recently-used-menu max-buffer-name-length))
- (others (append file-buffers
- (loop for elt
- across function-info-vector
- for value = (msb--create-sort-item elt)
- if value collect value))))
- (setq menu
- (mapcar 'cdr ;Remove the SORT-KEY
- ;; Sort the menus - not the items.
- (msb--add-separators
- (sort
- ;; Get a list of (SORT-KEY TITLE . BUFFER-LIST)
- ;; Also sorts the items within the menus.
- (if (cdr most-recently-used)
- (cons
- ;; Add most recent used buffers
- (cons msb-most-recently-used-sort-key
- most-recently-used)
- others)
- others)
- (function (lambda (elt1 elt2)
- (< (car elt1) (car elt2))))))))
- ;; Now make it a keymap menu
- (append
- '(keymap "Select Buffer")
- (msb--make-keymap-menu menu)
- (when msb-separator-diff
- (list (list 'separator "---")))
- (list (cons 'toggle
- (cons
- (if msb-files-by-directory
- "*Files by type*"
- "*Files by directory*")
- 'msb--toggle-menu-type)))))))
-
-(defun msb--create-buffer-menu ()
- (save-match-data
- (save-excursion
- (msb--create-buffer-menu-2))))
-
-;;;
-;;; Multi purpose function for selecting a buffer with the mouse.
-;;;
-(defun msb--toggle-menu-type ()
- (interactive)
- (setq msb-files-by-directory (not msb-files-by-directory))
- (menu-bar-update-buffers t))
-
-(defun mouse-select-buffer (event)
- "Pop up several menus of buffers, for selection with the mouse.
-Returns the selected buffer or nil if no buffer is selected.
-
-The way the buffers are split is conveniently handled with the
-variable `msb-menu-cond'."
- ;; Popup the menu and return the selected buffer.
- (when (or msb--error
- (not msb--last-buffer-menu)
- (not (fboundp 'frame-or-buffer-changed-p))
- (frame-or-buffer-changed-p))
- (setq msb--error nil)
- (setq msb--last-buffer-menu (msb--create-buffer-menu)))
- (let ((position event)
- choice)
- (when (and (fboundp 'posn-x-y)
- (fboundp 'posn-window))
- (let ((posX (car (posn-x-y (event-start event))))
- (posY (cdr (posn-x-y (event-start event))))
- (posWind (posn-window (event-start event))))
- ;; adjust position
- (setq posX (- posX (funcall msb-horizontal-shift-function))
- position (list (list posX posY) posWind))))
- ;; This `sit-for' magically makes the menu stay up if the mouse
- ;; button is released within 0.1 second.
- (sit-for 0 100)
- ;; Popup the menu
- (setq choice (x-popup-menu position msb--last-buffer-menu))
- (cond
- ((eq (car choice) 'toggle)
- ;; Bring up the menu again with type toggled.
- (msb--toggle-menu-type)
- (mouse-select-buffer event))
- ((and (numberp (car choice))
- (null (cdr choice)))
- (let ((msb--last-buffer-menu (nthcdr 3 (assq (car choice) msb--last-buffer-menu))))
- (mouse-select-buffer event)))
- ((while (numberp (car choice))
- (setq choice (cdr choice))))
- ((and (stringp (car choice))
- (null (cdr choice)))
- (car choice))
- ((null choice)
- choice)
- (t
- (error "Unknown form for buffer: %s" choice)))))
-
-;; Add separators
-(defun msb--add-separators (sorted-list)
- (cond
- ((or (not msb-separator-diff)
- (not (numberp msb-separator-diff)))
- sorted-list)
- (t
- (let ((last-key nil))
- (mapcan
- (function
- (lambda (item)
- (cond
- ((and msb-separator-diff
- last-key
- (> (- (car item) last-key)
- msb-separator-diff))
- (setq last-key (car item))
- (list (cons last-key 'separator)
- item))
- (t
- (setq last-key (car item))
- (list item)))))
- sorted-list)))))
-
-(defun msb--split-menus-2 (list mcount result)
- (cond
- ((> (length list) msb-max-menu-items)
- (let ((count 0)
- sub-name
- (tmp-list nil))
- (while (< count msb-max-menu-items)
- (push (pop list) tmp-list)
- (incf count))
- (setq tmp-list (nreverse tmp-list))
- (setq sub-name (concat (car (car tmp-list)) "..."))
- (push (append (list mcount sub-name
- 'keymap sub-name)
- tmp-list)
- result))
- (msb--split-menus-2 list (1+ mcount) result))
- ((null result)
- list)
- (t
- (let (sub-name)
- (setq sub-name (concat (car (car list)) "..."))
- (push (append (list mcount sub-name
- 'keymap sub-name)
- list)
- result))
- (nreverse result))))
-
-(defun msb--split-menus (list)
- (msb--split-menus-2 list 0 nil))
-
-
-(defun msb--make-keymap-menu (raw-menu)
- (let ((end (cons '(nil) 'menu-bar-select-buffer))
- (mcount 0))
- (mapcar
- (function
- (lambda (sub-menu)
- (cond
- ((eq 'separator sub-menu)
- (list 'separator "---"))
- (t
- (let ((buffers (mapcar (function
- (lambda (item)
- (let ((string (car item))
- (buffer (cdr item)))
- (cons (buffer-name buffer)
- (cons string end)))))
- (cdr sub-menu))))
- (append (list (incf mcount) (car sub-menu)
- 'keymap (car sub-menu))
- (msb--split-menus buffers)))))))
- raw-menu)))
-
-(defun menu-bar-update-buffers (&optional arg)
- ;; If user discards the Buffers item, play along.
- (when (and (lookup-key (current-global-map) [menu-bar buffer])
- (or (not (fboundp 'frame-or-buffer-changed-p))
- (frame-or-buffer-changed-p)
- arg))
- (let ((frames (frame-list))
- buffers-menu frames-menu)
- ;; Make the menu of buffers proper.
- (setq msb--last-buffer-menu (msb--create-buffer-menu))
- (setq buffers-menu msb--last-buffer-menu)
- ;; Make a Frames menu if we have more than one frame.
- (when (cdr frames)
- (let* ((frame-length (length frames))
- (f-title (format "Frames (%d)" frame-length)))
- ;; List only the N most recently selected frames
- (when (and (integerp msb-max-menu-items)
- (> msb-max-menu-items 1)
- (> frame-length msb-max-menu-items))
- (setcdr (nthcdr msb-max-menu-items frames) nil))
- (setq frames-menu
- (nconc
- (list 'frame f-title '(nil) 'keymap f-title)
- (mapcar
- (function
- (lambda (frame)
- (nconc
- (list frame
- (cdr (assq 'name
- (frame-parameters frame)))
- (cons nil nil))
- 'menu-bar-select-frame)))
- frames)))))
- (define-key (current-global-map) [menu-bar buffer]
- (cons "Buffers"
- (if (and buffers-menu frames-menu)
- ;; Combine Frame and Buffers menus with separator between
- (nconc (list 'keymap "Buffers and Frames" frames-menu
- (and msb-separator-diff '(separator "---")))
- (cddr buffers-menu))
- (or buffers-menu 'undefined)))))))
-
-(unless (or (not (boundp 'menu-bar-update-hook))
- (memq 'menu-bar-update-buffers menu-bar-update-hook))
- (add-hook 'menu-bar-update-hook 'menu-bar-update-buffers))
-
-(and (fboundp 'mouse-buffer-menu)
- (substitute-key-definition 'mouse-buffer-menu 'msb (current-global-map)))
-
-(provide 'msb)
-(eval-after-load 'msb (run-hooks 'msb-after-load-hooks))
-
-;; Load the cl-extra library now, since we will certainly need it later.
-(mapc 'ignore nil)
-
-;;; msb.el ends here
diff --git a/lisp/nnbabyl.el b/lisp/nnbabyl.el
deleted file mode 100644
index 330fe905744..00000000000
--- a/lisp/nnbabyl.el
+++ /dev/null
@@ -1,625 +0,0 @@
-;;; nnbabyl.el --- rmail mbox access for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: news, mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; For an overview of what the interface functions do, please see the
-;; Gnus sources.
-
-;;; Code:
-
-(require 'nnheader)
-(require 'rmail)
-(require 'nnmail)
-(require 'nnoo)
-(eval-when-compile (require 'cl))
-
-(nnoo-declare nnbabyl)
-
-(defvoo nnbabyl-mbox-file (expand-file-name "~/RMAIL")
- "The name of the rmail box file in the users home directory.")
-
-(defvoo nnbabyl-active-file (expand-file-name "~/.rmail-active")
- "The name of the active file for the rmail box.")
-
-(defvoo nnbabyl-get-new-mail t
- "If non-nil, nnbabyl will check the incoming mail file and split the mail.")
-
-(defvoo nnbabyl-prepare-save-mail-hook nil
- "Hook run narrowed to an article before saving.")
-
-
-
-(defvar nnbabyl-mail-delimiter "\^_")
-
-(defconst nnbabyl-version "nnbabyl 1.0"
- "nnbabyl version.")
-
-(defvoo nnbabyl-mbox-buffer nil)
-(defvoo nnbabyl-current-group nil)
-(defvoo nnbabyl-status-string "")
-(defvoo nnbabyl-group-alist nil)
-(defvoo nnbabyl-active-timestamp nil)
-
-(defvoo nnbabyl-previous-buffer-mode nil)
-
-(eval-and-compile
- (autoload 'gnus-set-text-properties "gnus-ems"))
-
-
-
-;;; Interface functions
-
-(nnoo-define-basics nnbabyl)
-
-(deffoo nnbabyl-retrieve-headers (articles &optional group server fetch-old)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (let ((number (length articles))
- (count 0)
- (delim (concat "^" nnbabyl-mail-delimiter))
- article art-string start stop)
- (nnbabyl-possibly-change-newsgroup group server)
- (while (setq article (pop articles))
- (setq art-string (nnbabyl-article-string article))
- (set-buffer nnbabyl-mbox-buffer)
- (beginning-of-line)
- (when (or (search-forward art-string nil t)
- (search-backward art-string nil t))
- (re-search-backward delim nil t)
- (while (and (not (looking-at ".+:"))
- (zerop (forward-line 1))))
- (setq start (point))
- (search-forward "\n\n" nil t)
- (setq stop (1- (point)))
- (set-buffer nntp-server-buffer)
- (insert "221 ")
- (princ article (current-buffer))
- (insert " Article retrieved.\n")
- (insert-buffer-substring nnbabyl-mbox-buffer start stop)
- (goto-char (point-max))
- (insert ".\n"))
- (and (numberp nnmail-large-newsgroup)
- (> number nnmail-large-newsgroup)
- (zerop (% (incf count) 20))
- (nnheader-message 5 "nnbabyl: Receiving headers... %d%%"
- (/ (* count 100) number))))
-
- (and (numberp nnmail-large-newsgroup)
- (> number nnmail-large-newsgroup)
- (nnheader-message 5 "nnbabyl: Receiving headers...done"))
-
- (set-buffer nntp-server-buffer)
- (nnheader-fold-continuation-lines)
- 'headers)))
-
-(deffoo nnbabyl-open-server (server &optional defs)
- (nnoo-change-server 'nnbabyl server defs)
- (cond
- ((not (file-exists-p nnbabyl-mbox-file))
- (nnbabyl-close-server)
- (nnheader-report 'nnbabyl "No such file: %s" nnbabyl-mbox-file))
- ((file-directory-p nnbabyl-mbox-file)
- (nnbabyl-close-server)
- (nnheader-report 'nnbabyl "Not a regular file: %s" nnbabyl-mbox-file))
- (t
- (nnheader-report 'nnbabyl "Opened server %s using mbox %s" server
- nnbabyl-mbox-file)
- t)))
-
-(deffoo nnbabyl-close-server (&optional server)
- ;; Restore buffer mode.
- (when (and (nnbabyl-server-opened)
- nnbabyl-previous-buffer-mode)
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
- (narrow-to-region
- (caar nnbabyl-previous-buffer-mode)
- (cdar nnbabyl-previous-buffer-mode))
- (funcall (cdr nnbabyl-previous-buffer-mode))))
- (nnoo-close-server 'nnbabyl server)
- (setq nnbabyl-mbox-buffer nil)
- t)
-
-(deffoo nnbabyl-server-opened (&optional server)
- (and (nnoo-current-server-p 'nnbabyl server)
- nnbabyl-mbox-buffer
- (buffer-name nnbabyl-mbox-buffer)
- nntp-server-buffer
- (buffer-name nntp-server-buffer)))
-
-(deffoo nnbabyl-request-article (article &optional newsgroup server buffer)
- (nnbabyl-possibly-change-newsgroup newsgroup server)
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
- (goto-char (point-min))
- (when (search-forward (nnbabyl-article-string article) nil t)
- (let (start stop summary-line)
- (re-search-backward (concat "^" nnbabyl-mail-delimiter) nil t)
- (while (and (not (looking-at ".+:"))
- (zerop (forward-line 1))))
- (setq start (point))
- (or (and (re-search-forward
- (concat "^" nnbabyl-mail-delimiter) nil t)
- (forward-line -1))
- (goto-char (point-max)))
- (setq stop (point))
- (let ((nntp-server-buffer (or buffer nntp-server-buffer)))
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (insert-buffer-substring nnbabyl-mbox-buffer start stop)
- (goto-char (point-min))
- ;; If there is an EOOH header, then we have to remove some
- ;; duplicated headers.
- (setq summary-line (looking-at "Summary-line:"))
- (when (search-forward "\n*** EOOH ***" nil t)
- (if summary-line
- ;; The headers to be deleted are located before the
- ;; EOOH line...
- (delete-region (point-min) (progn (forward-line 1)
- (point)))
- ;; ...or after.
- (delete-region (progn (beginning-of-line) (point))
- (or (search-forward "\n\n" nil t)
- (point)))))
- (if (numberp article)
- (cons nnbabyl-current-group article)
- (nnbabyl-article-group-number)))))))
-
-(deffoo nnbabyl-request-group (group &optional server dont-check)
- (let ((active (cadr (assoc group nnbabyl-group-alist))))
- (save-excursion
- (cond
- ((or (null active)
- (null (nnbabyl-possibly-change-newsgroup group server)))
- (nnheader-report 'nnbabyl "No such group: %s" group))
- (dont-check
- (nnheader-report 'nnbabyl "Selected group %s" group)
- (nnheader-insert ""))
- (t
- (nnheader-report 'nnbabyl "Selected group %s" group)
- (nnheader-insert "211 %d %d %d %s\n"
- (1+ (- (cdr active) (car active)))
- (car active) (cdr active) group))))))
-
-(deffoo nnbabyl-request-scan (&optional group server)
- (nnbabyl-read-mbox)
- (nnmail-get-new-mail
- 'nnbabyl
- (lambda ()
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
- (save-buffer)))
- nnbabyl-mbox-file group
- (lambda ()
- (save-excursion
- (let ((in-buf (current-buffer)))
- (goto-char (point-min))
- (while (search-forward "\n\^_\n" nil t)
- (delete-char -1))
- (set-buffer nnbabyl-mbox-buffer)
- (goto-char (point-max))
- (search-backward "\n\^_" nil t)
- (goto-char (match-end 0))
- (insert-buffer-substring in-buf)))
- (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file))))
-
-(deffoo nnbabyl-close-group (group &optional server)
- t)
-
-(deffoo nnbabyl-request-create-group (group &optional server)
- (nnmail-activate 'nnbabyl)
- (unless (assoc group nnbabyl-group-alist)
- (setq nnbabyl-group-alist (cons (list group (cons 1 0))
- nnbabyl-group-alist))
- (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file))
- t)
-
-(deffoo nnbabyl-request-list (&optional server)
- (save-excursion
- (nnmail-find-file nnbabyl-active-file)
- (setq nnbabyl-group-alist (nnmail-get-active))))
-
-(deffoo nnbabyl-request-newgroups (date &optional server)
- (nnbabyl-request-list server))
-
-(deffoo nnbabyl-request-list-newsgroups (&optional server)
- (nnheader-report 'nnbabyl "nnbabyl: LIST NEWSGROUPS is not implemented."))
-
-(deffoo nnbabyl-request-expire-articles
- (articles newsgroup &optional server force)
- (nnbabyl-possibly-change-newsgroup newsgroup server)
- (let* ((is-old t)
- rest)
- (nnmail-activate 'nnbabyl)
-
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
- (gnus-set-text-properties (point-min) (point-max) nil)
- (while (and articles is-old)
- (goto-char (point-min))
- (if (search-forward (nnbabyl-article-string (car articles)) nil t)
- (if (setq is-old
- (nnmail-expired-article-p
- newsgroup
- (buffer-substring
- (point) (progn (end-of-line) (point))) force))
- (progn
- (nnheader-message 5 "Deleting article %d in %s..."
- (car articles) newsgroup)
- (nnbabyl-delete-mail))
- (setq rest (cons (car articles) rest))))
- (setq articles (cdr articles)))
- (save-buffer)
- ;; Find the lowest active article in this group.
- (let ((active (nth 1 (assoc newsgroup nnbabyl-group-alist))))
- (goto-char (point-min))
- (while (and (not (search-forward
- (nnbabyl-article-string (car active)) nil t))
- (<= (car active) (cdr active)))
- (setcar active (1+ (car active)))
- (goto-char (point-min))))
- (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file)
- (nconc rest articles))))
-
-(deffoo nnbabyl-request-move-article
- (article group server accept-form &optional last)
- (nnbabyl-possibly-change-newsgroup group server)
- (let ((buf (get-buffer-create " *nnbabyl move*"))
- result)
- (and
- (nnbabyl-request-article article group server)
- (save-excursion
- (set-buffer buf)
- (insert-buffer-substring nntp-server-buffer)
- (goto-char (point-min))
- (if (re-search-forward
- "^X-Gnus-Newsgroup:"
- (save-excursion (search-forward "\n\n" nil t) (point)) t)
- (delete-region (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point))))
- (setq result (eval accept-form))
- (kill-buffer (current-buffer))
- result)
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
- (goto-char (point-min))
- (if (search-forward (nnbabyl-article-string article) nil t)
- (nnbabyl-delete-mail))
- (and last (save-buffer))))
- result))
-
-(deffoo nnbabyl-request-accept-article (group &optional server last)
- (nnbabyl-possibly-change-newsgroup group server)
- (nnmail-check-syntax)
- (let ((buf (current-buffer))
- result beg)
- (and
- (nnmail-activate 'nnbabyl)
- (save-excursion
- (goto-char (point-min))
- (search-forward "\n\n" nil t)
- (forward-line -1)
- (save-excursion
- (while (re-search-backward "^X-Gnus-Newsgroup: " beg t)
- (delete-region (point) (progn (forward-line 1) (point)))))
- (let ((nnmail-split-methods
- (if (stringp group) (list (list group ""))
- nnmail-split-methods)))
- (setq result (car (nnbabyl-save-mail))))
- (set-buffer nnbabyl-mbox-buffer)
- (goto-char (point-max))
- (search-backward "\n\^_")
- (goto-char (match-end 0))
- (insert-buffer-substring buf)
- (when last
- (save-buffer)
- (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file))
- result))))
-
-(deffoo nnbabyl-request-replace-article (article group buffer)
- (nnbabyl-possibly-change-newsgroup group)
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
- (goto-char (point-min))
- (if (not (search-forward (nnbabyl-article-string article) nil t))
- nil
- (nnbabyl-delete-mail t t)
- (insert-buffer-substring buffer)
- (save-buffer)
- t)))
-
-(deffoo nnbabyl-request-delete-group (group &optional force server)
- (nnbabyl-possibly-change-newsgroup group server)
- ;; Delete all articles in GROUP.
- (if (not force)
- () ; Don't delete the articles.
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
- (goto-char (point-min))
- ;; Delete all articles in this group.
- (let ((ident (concat "\nX-Gnus-Newsgroup: " nnbabyl-current-group ":"))
- found)
- (while (search-forward ident nil t)
- (setq found t)
- (nnbabyl-delete-mail))
- (and found (save-buffer)))))
- ;; Remove the group from all structures.
- (setq nnbabyl-group-alist
- (delq (assoc group nnbabyl-group-alist) nnbabyl-group-alist)
- nnbabyl-current-group nil)
- ;; Save the active file.
- (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file)
- t)
-
-(deffoo nnbabyl-request-rename-group (group new-name &optional server)
- (nnbabyl-possibly-change-newsgroup group server)
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
- (goto-char (point-min))
- (let ((ident (concat "\nX-Gnus-Newsgroup: " nnbabyl-current-group ":"))
- (new-ident (concat "\nX-Gnus-Newsgroup: " new-name ":"))
- found)
- (while (search-forward ident nil t)
- (replace-match new-ident t t)
- (setq found t))
- (and found (save-buffer))))
- (let ((entry (assoc group nnbabyl-group-alist)))
- (and entry (setcar entry new-name))
- (setq nnbabyl-current-group nil)
- ;; Save the new group alist.
- (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file)
- t))
-
-
-;;; Internal functions.
-
-;; If FORCE, delete article no matter how many X-Gnus-Newsgroup
-;; headers there are. If LEAVE-DELIM, don't delete the Unix mbox
-;; delimiter line.
-(defun nnbabyl-delete-mail (&optional force leave-delim)
- ;; Delete the current X-Gnus-Newsgroup line.
- (or force
- (delete-region
- (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point))))
- ;; Beginning of the article.
- (save-excursion
- (save-restriction
- (widen)
- (narrow-to-region
- (save-excursion
- (re-search-backward (concat "^" nnbabyl-mail-delimiter) nil t)
- (if leave-delim (progn (forward-line 1) (point))
- (match-beginning 0)))
- (progn
- (forward-line 1)
- (or (and (re-search-forward (concat "^" nnbabyl-mail-delimiter)
- nil t)
- (if (and (not (bobp)) leave-delim)
- (progn (forward-line -2) (point))
- (match-beginning 0)))
- (point-max))))
- (goto-char (point-min))
- ;; Only delete the article if no other groups owns it as well.
- (if (or force (not (re-search-forward "^X-Gnus-Newsgroup: " nil t)))
- (delete-region (point-min) (point-max))))))
-
-(defun nnbabyl-possibly-change-newsgroup (newsgroup &optional server)
- (when (and server
- (not (nnbabyl-server-opened server)))
- (nnbabyl-open-server server))
- (if (or (not nnbabyl-mbox-buffer)
- (not (buffer-name nnbabyl-mbox-buffer)))
- (save-excursion (nnbabyl-read-mbox)))
- (or nnbabyl-group-alist
- (nnmail-activate 'nnbabyl))
- (if newsgroup
- (if (assoc newsgroup nnbabyl-group-alist)
- (setq nnbabyl-current-group newsgroup)
- (nnheader-report 'nnbabyl "No such group in file"))
- t))
-
-(defun nnbabyl-article-string (article)
- (if (numberp article)
- (concat "\nX-Gnus-Newsgroup: " nnbabyl-current-group ":"
- (int-to-string article) " ")
- (concat "\nMessage-ID: " article)))
-
-(defun nnbabyl-article-group-number ()
- (save-excursion
- (goto-char (point-min))
- (and (re-search-forward "^X-Gnus-Newsgroup: +\\([^:]+\\):\\([0-9]+\\) "
- nil t)
- (cons (buffer-substring (match-beginning 1) (match-end 1))
- (string-to-int
- (buffer-substring (match-beginning 2) (match-end 2)))))))
-
-(defun nnbabyl-insert-lines ()
- "Insert how many lines and chars there are in the body of the mail."
- (let (lines chars)
- (save-excursion
- (goto-char (point-min))
- (when (search-forward "\n\n" nil t)
- ;; There may be an EOOH line here...
- (when (looking-at "\\*\\*\\* EOOH \\*\\*\\*")
- (search-forward "\n\n" nil t))
- (setq chars (- (point-max) (point))
- lines (max (- (count-lines (point) (point-max)) 1) 0))
- ;; Move back to the end of the headers.
- (goto-char (point-min))
- (search-forward "\n\n" nil t)
- (forward-char -1)
- (save-excursion
- (when (re-search-backward "^Lines: " nil t)
- (delete-region (point) (progn (forward-line 1) (point)))))
- (insert (format "Lines: %d\n" lines))
- chars))))
-
-(defun nnbabyl-save-mail ()
- ;; Called narrowed to an article.
- (let ((group-art (nreverse (nnmail-article-group 'nnbabyl-active-number))))
- (nnbabyl-insert-lines)
- (nnmail-insert-xref group-art)
- (nnbabyl-insert-newsgroup-line group-art)
- (run-hooks 'nnbabyl-prepare-save-mail-hook)
- group-art))
-
-(defun nnbabyl-insert-newsgroup-line (group-art)
- (save-excursion
- (goto-char (point-min))
- (while (looking-at "From ")
- (replace-match "Mail-from: From " t t)
- (forward-line 1))
- ;; If there is a C-l at the beginning of the narrowed region, this
- ;; isn't really a "save", but rather a "scan".
- (goto-char (point-min))
- (or (looking-at "\^L")
- (save-excursion
- (insert "\^L\n0, unseen,,\n*** EOOH ***\n")
- (goto-char (point-max))
- (insert "\^_\n")))
- (if (search-forward "\n\n" nil t)
- (progn
- (forward-char -1)
- (while group-art
- (insert (format "X-Gnus-Newsgroup: %s:%d %s\n"
- (caar group-art) (cdar group-art)
- (current-time-string)))
- (setq group-art (cdr group-art)))))
- t))
-
-(defun nnbabyl-active-number (group)
- ;; Find the next article number in GROUP.
- (let ((active (cadr (assoc group nnbabyl-group-alist))))
- (if active
- (setcdr active (1+ (cdr active)))
- ;; This group is new, so we create a new entry for it.
- ;; This might be a bit naughty... creating groups on the drop of
- ;; a hat, but I don't know...
- (setq nnbabyl-group-alist (cons (list group (setq active (cons 1 1)))
- nnbabyl-group-alist)))
- (cdr active)))
-
-(defun nnbabyl-read-mbox ()
- (nnmail-activate 'nnbabyl)
- (unless (file-exists-p nnbabyl-mbox-file)
- ;; Create a new, empty RMAIL mbox file.
- (save-excursion
- (set-buffer (setq nnbabyl-mbox-buffer
- (create-file-buffer nnbabyl-mbox-file)))
- (setq buffer-file-name nnbabyl-mbox-file)
- (insert "BABYL OPTIONS:\n\n\^_")
- (write-region (point-min) (point-max) nnbabyl-mbox-file t 'nomesg)))
-
- (if (and nnbabyl-mbox-buffer
- (buffer-name nnbabyl-mbox-buffer)
- (save-excursion
- (set-buffer nnbabyl-mbox-buffer)
- (= (buffer-size) (nnheader-file-size nnbabyl-mbox-file))))
- () ; This buffer hasn't changed since we read it last. Possibly.
- (save-excursion
- (let ((delim (concat "^" nnbabyl-mail-delimiter))
- (alist nnbabyl-group-alist)
- start end number)
- (set-buffer (setq nnbabyl-mbox-buffer
- (nnheader-find-file-noselect
- nnbabyl-mbox-file nil 'raw)))
- ;; Save previous buffer mode.
- (setq nnbabyl-previous-buffer-mode
- (cons (cons (point-min) (point-max))
- major-mode))
-
- (buffer-disable-undo (current-buffer))
- (widen)
- (setq buffer-read-only nil)
- (fundamental-mode)
-
- ;; Go through the group alist and compare against
- ;; the rmail file.
- (while alist
- (goto-char (point-max))
- (when (and (re-search-backward
- (format "^X-Gnus-Newsgroup: %s:\\([0-9]+\\) "
- (caar alist)) nil t)
- (> (setq number
- (string-to-number
- (buffer-substring
- (match-beginning 1) (match-end 1))))
- (cdadar alist)))
- (setcdr (cadar alist) (1+ number)))
- (setq alist (cdr alist)))
-
- ;; We go through the mbox and make sure that each and
- ;; every mail belongs to some group or other.
- (goto-char (point-min))
- (re-search-forward delim nil t)
- (setq start (match-end 0))
- (while (re-search-forward delim nil t)
- (setq end (match-end 0))
- (unless (search-backward "\nX-Gnus-Newsgroup: " start t)
- (goto-char end)
- (save-excursion
- (save-restriction
- (narrow-to-region (goto-char start) end)
- (nnbabyl-save-mail)
- (setq end (point-max)))))
- (goto-char (setq start end)))
- (when (buffer-modified-p (current-buffer))
- (save-buffer))
- (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file)))))
-
-(defun nnbabyl-remove-incoming-delims ()
- (goto-char (point-min))
- (while (search-forward "\^_" nil t)
- (replace-match "?" t t)))
-
-(defun nnbabyl-check-mbox ()
- "Go through the nnbabyl mbox and make sure that no article numbers are reused."
- (interactive)
- (let ((idents (make-vector 1000 0))
- id)
- (save-excursion
- (when (or (not nnbabyl-mbox-buffer)
- (not (buffer-name nnbabyl-mbox-buffer)))
- (nnbabyl-read-mbox))
- (set-buffer nnbabyl-mbox-buffer)
- (goto-char (point-min))
- (while (re-search-forward "^X-Gnus-Newsgroup: \\([^ ]+\\) " nil t)
- (if (intern-soft (setq id (match-string 1)) idents)
- (progn
- (delete-region (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point)))
- (nnheader-message 7 "Moving %s..." id)
- (nnbabyl-save-mail))
- (intern id idents)))
- (when (buffer-modified-p (current-buffer))
- (save-buffer))
- (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file)
- (message ""))))
-
-(provide 'nnbabyl)
-
-;;; nnbabyl.el ends here
diff --git a/lisp/nndb.el b/lisp/nndb.el
deleted file mode 100644
index 15d82ec4f1c..00000000000
--- a/lisp/nndb.el
+++ /dev/null
@@ -1,229 +0,0 @@
-;;; nndb.el --- nndb access for Gnus
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Kai Grossjohann <grossjohann@ls6.informatik.uni-dortmund.de>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; I have shamelessly snarfed the code of nntp.el from sgnus.
-;; Kai
-
-
-;;-
-;; Register nndb with known select methods.
-
-(setq gnus-valid-select-methods
- (cons '("nndb" mail address respool prompt-address)
- gnus-valid-select-methods))
-
-
-;;; Code:
-
-(require 'nnheader)
-(require 'nntp)
-(eval-when-compile (require 'cl))
-
-(eval-and-compile
- (unless (fboundp 'open-network-stream)
- (require 'tcp)))
-
-(eval-when-compile (require 'cl))
-
-(eval-and-compile
- (autoload 'news-setup "rnewspost")
- (autoload 'news-reply-mode "rnewspost")
- (autoload 'cancel-timer "timer")
- (autoload 'telnet "telnet" nil t)
- (autoload 'telnet-send-input "telnet" nil t)
- (autoload 'timezone-parse-date "timezone"))
-
-;; Declare nndb as derived from nntp
-
-(nnoo-declare nndb nntp)
-
-;; Variables specific to nndb
-
-;;- currently not used but just in case...
-(defvoo nndb-deliver-program "nndel"
- "*The program used to put a message in an NNDB group.")
-
-;; Variables copied from nntp
-
-(defvoo nndb-server-opened-hook '(nntp-send-authinfo-from-file)
- "Like nntp-server-opened-hook."
- nntp-server-opened-hook)
-
-;(defvoo nndb-rlogin-parameters '("telnet" "${NNDBSERVER:=localhost}" "9000")
-; "*Parameters to nndb-open-login. Like nntp-rlogin-parameters."
-; nntp-rlogin-parameters)
-
-;(defvoo nndb-rlogin-user-name nil
-; "*User name for rlogin connect method."
-; nntp-rlogin-user-name)
-
-(defvoo nndb-address "localhost"
- "*The name of the NNDB server."
- nntp-address)
-
-(defvoo nndb-port-number 9000
- "*Port number to connect to."
- nntp-port-number)
-
-;(defvoo nndb-current-group ""
-; "Like nntp-current-group."
-; nntp-current-group)
-
-(defvoo nndb-status-string nil "" nntp-status-string)
-
-
-
-(defconst nndb-version "nndb 0.3"
- "Version numbers of this version of NNDB.")
-
-
-;;; Interface functions.
-
-(nnoo-define-basics nndb)
-
-;; Import other stuff from nntp as is.
-
-(nnoo-import nndb
- (nntp))
-
-;;- maybe this should be mail??
-;;-(defun nndb-request-type (group &optional article)
-;;- 'news)
-
-;;------------------------------------------------------------------
-;;- only new stuff below
-
-; nndb-request-update-info does not exist and is not needed
-
-; nndb-request-update-mark does not exist and is not needed
-
-; nndb-request-scan does not exist
-; get new mail from somewhere -- maybe this is not needed?
-; --> todo
-
-(deffoo nndb-request-create-group (group &optional server)
- "Creates a group if it doesn't exist yet."
- (nntp-send-command "^[23].*\n" "MKGROUP" group))
-
-; todo -- use some other time than the creation time of the article
-; best is time since article has been marked as expirable
-(deffoo nndb-request-expire-articles
- (articles &optional group server force)
- "Expires ARTICLES from GROUP on SERVER.
-If FORCE, delete regardless of exiration date, otherwise use normal
-expiry mechanism."
- (let (msg art)
- (nntp-possibly-change-server group server) ;;-
- (while articles
- (setq art (pop articles))
- (nntp-send-command "^\\([23]\\|^423\\).*\n" "DATE" art)
- (setq msg (nndb-status-message))
- ;; CCC we shouldn't be using the variable nndb-status-string?
- (if (string-match "^423" (nnheader-get-report 'nndb))
- ()
- (or (string-match "\\([0-9]+\\) \\([0-9]+\\)$" msg)
- (error "Not a valid response for DATE command: %s"
- msg))
- (if (nnmail-expired-article-p
- group
- (list (string-to-int
- (substring msg (match-beginning 1) (match-end 1)))
- (string-to-int
- (substring msg (match-beginning 2) (match-end 2))))
- force)
- (nnheader-message 5 "Deleting article %s in %s..."
- art group)
- (nntp-send-command "^[23].*\n" "DELETE" art))))))
-
-(deffoo nndb-request-move-article
- (article group server accept-form &optional last)
- "Move ARTICLE (a number) from GROUP on SERVER.
-Evals ACCEPT-FORM in current buffer, where the article is.
-Optional LAST is ignored."
- (let ((artbuf (get-buffer-create " *nndb move*"))
- result)
- (and
- (nndb-request-article article group server artbuf)
- (save-excursion
- (set-buffer artbuf)
- (setq result (eval accept-form))
- (kill-buffer (current-buffer))
- result)
- (nndb-request-expire-articles (list article)
- group
- server
- t))
- result))
-
-(deffoo nndb-request-accept-article (group server &optional last)
- "The article in the current buffer is put into GROUP."
- (nntp-possibly-change-server group server) ;;-
- (let (art statmsg)
- (when (nntp-send-command "^[23].*\r?\n" "ACCEPT" group)
- (nnheader-insert "")
- (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].*\n")
- (setq statmsg (nntp-status-message))
- (or (string-match "^\\([0-9]+\\)" statmsg)
- (error "nndb: %s" statmsg))
- (setq art (substring statmsg
- (match-beginning 1)
- (match-end 1)))
- (message "nndb: accepted %s" art)
- (list art))))
-
-(deffoo nndb-request-replace-article (article group buffer)
- "ARTICLE is the number of the article in GROUP to be replaced
-with the contents of the BUFFER."
- (set-buffer buffer)
- (let (art statmsg)
- (when (nntp-send-command "^[23].*\r?\n" "REPLACE" (int-to-string article))
- (nnheader-insert "")
- (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].*\n")
-; (setq statmsg (nntp-status-message))
-; (or (string-match "^\\([0-9]+\\)" statmsg)
-; (error "nndb: %s" statmsg))
-; (setq art (substring statmsg
-; (match-beginning 1)
-; (match-end 1)))
-; (message "nndb: replaced %s" art)
- (list (int-to-string article)))))
-
-; nndb-request-delete-group does not exist
-; todo -- maybe later
-
-; nndb-request-rename-group does not exist
-; todo -- maybe later
-
-(provide 'nndb)
-
-
diff --git a/lisp/nndir.el b/lisp/nndir.el
deleted file mode 100644
index dd7fa8ade8b..00000000000
--- a/lisp/nndir.el
+++ /dev/null
@@ -1,99 +0,0 @@
-;;; nndir.el --- single directory newsgroup access for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'nnheader)
-(require 'nnmh)
-(require 'nnml)
-(require 'nnoo)
-(eval-when-compile (require 'cl))
-
-(nnoo-declare nndir
- nnml nnmh)
-
-(defvoo nndir-directory nil
- "Where nndir will look for groups."
- nnml-current-directory nnmh-current-directory)
-
-(defvoo nndir-nov-is-evil nil
- "*Non-nil means that nndir will never retrieve NOV headers."
- nnml-nov-is-evil)
-
-
-
-(defvoo nndir-current-group "" nil nnml-current-group nnmh-current-group)
-(defvoo nndir-top-directory nil nil nnml-directory nnmh-directory)
-(defvoo nndir-get-new-mail nil nil nnml-get-new-mail nnmh-get-new-mail)
-
-(defvoo nndir-status-string "" nil nnmh-status-string)
-(defconst nndir-version "nndir 1.0")
-
-
-
-;;; Interface functions.
-
-(nnoo-define-basics nndir)
-
-(deffoo nndir-open-server (server &optional defs)
- (setq nndir-directory
- (or (cadr (assq 'nndir-directory defs))
- server))
- (unless (assq 'nndir-directory defs)
- (push `(nndir-directory ,server) defs))
- (push `(nndir-current-group
- ,(file-name-nondirectory (directory-file-name nndir-directory)))
- defs)
- (push `(nndir-top-directory
- ,(file-name-directory (directory-file-name nndir-directory)))
- defs)
- (nnoo-change-server 'nndir server defs)
- (let (err)
- (cond
- ((not (condition-case arg
- (file-exists-p nndir-directory)
- (ftp-error (setq err (format "%s" arg)))))
- (nndir-close-server)
- (nnheader-report
- 'nndir (or err "No such file or directory: %s" nndir-directory)))
- ((not (file-directory-p (file-truename nndir-directory)))
- (nndir-close-server)
- (nnheader-report 'nndir "Not a directory: %s" nndir-directory))
- (t
- (nnheader-report 'nndir "Opened server %s using directory %s"
- server nndir-directory)
- t))))
-
-(nnoo-map-functions nndir
- (nnml-retrieve-headers 0 nndir-current-group 0 0)
- (nnmh-request-article 0 nndir-current-group 0 0)
- (nnmh-request-group nndir-current-group 0 0)
- (nnmh-close-group nndir-current-group 0)
- (nnmh-request-list (nnoo-current-server 'nndir) nndir-directory)
- (nnmh-request-newsgroups (nnoo-current-server 'nndir) nndir-directory))
-
-(provide 'nndir)
-
-;;; nndir.el ends here
diff --git a/lisp/nndoc.el b/lisp/nndoc.el
deleted file mode 100644
index 72791d0c533..00000000000
--- a/lisp/nndoc.el
+++ /dev/null
@@ -1,482 +0,0 @@
-;;; nndoc.el --- single file access for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'nnheader)
-(require 'message)
-(require 'nnmail)
-(require 'nnoo)
-(eval-when-compile (require 'cl))
-
-(nnoo-declare nndoc)
-
-(defvoo nndoc-article-type 'guess
- "*Type of the file.
-One of `mbox', `babyl', `digest', `news', `rnews', `mmdf', `forward',
-`mime-digest', `standard-digest', `slack-digest', `clari-briefs' or
-`guess'.")
-
-(defvoo nndoc-post-type 'mail
- "*Whether the nndoc group is `mail' or `post'.")
-
-(defvar nndoc-type-alist
- `((mmdf
- (article-begin . "^\^A\^A\^A\^A\n")
- (body-end . "^\^A\^A\^A\^A\n"))
- (news
- (article-begin . "^Path:"))
- (rnews
- (article-begin . "^#! *rnews +\\([0-9]+\\) *\n")
- (body-end-function . nndoc-rnews-body-end))
- (mbox
- (article-begin . "^From \\([^ \n]*\\(\\|\".*\"[^ \n]*\\)\\) ?\\([^ \n]*\\) *\\([^ ]*\\) *\\([0-9]*\\) *\\([0-9:]*\\) *\\([A-Z]?[A-Z]?[A-Z][A-Z]\\( DST\\)?\\|[-+]?[0-9][0-9][0-9][0-9]\\|\\) * [0-9][0-9]\\([0-9]*\\) *\\([A-Z]?[A-Z]?[A-Z][A-Z]\\( DST\\)?\\|[-+]?[0-9][0-9][0-9][0-9]\\|\\) *\\(remote from .*\\)?\n")
- (article-begin-function . nndoc-mbox-article-begin)
- (body-end-function . nndoc-mbox-body-end))
- (babyl
- (article-begin . "\^_\^L *\n")
- (body-end . "\^_")
- (body-begin-function . nndoc-babyl-body-begin)
- (head-begin-function . nndoc-babyl-head-begin))
- (forward
- (article-begin . "^-+ Start of forwarded message -+\n+")
- (body-end . "^-+ End of forwarded message -+$")
- (prepare-body . nndoc-unquote-dashes))
- (clari-briefs
- (article-begin . "^ \\*")
- (body-end . "^\t------*[ \t]^*\n^ \\*")
- (body-begin . "^\t")
- (head-end . "^\t")
- (generate-head . nndoc-generate-clari-briefs-head)
- (article-transform . nndoc-transform-clari-briefs))
- (slack-digest
- (article-begin . "^------------------------------*[\n \t]+")
- (head-end . "^ ?$")
- (body-end-function . nndoc-digest-body-end)
- (body-begin . "^ ?$")
- (file-end . "^End of")
- (prepare-body . nndoc-unquote-dashes))
- (mime-digest
- (article-begin . "")
- (head-end . "^ ?$")
- (body-end . "")
- (file-end . ""))
- (standard-digest
- (first-article . ,(concat "^" (make-string 70 ?-) "\n\n+"))
- (article-begin . ,(concat "\n\n" (make-string 30 ?-) "\n\n+"))
- (prepare-body . nndoc-unquote-dashes)
- (body-end-function . nndoc-digest-body-end)
- (head-end . "^ ?$")
- (body-begin . "^ ?\n")
- (file-end . "^End of .*digest.*[0-9].*\n\\*\\*\\|^End of.*Digest *$"))
- (guess
- (guess . nndoc-guess-type))
- (digest
- (guess . nndoc-guess-digest-type))
- ))
-
-
-
-(defvoo nndoc-file-begin nil)
-(defvoo nndoc-first-article nil)
-(defvoo nndoc-article-end nil)
-(defvoo nndoc-article-begin nil)
-(defvoo nndoc-article-begin-function nil)
-(defvoo nndoc-head-begin nil)
-(defvoo nndoc-head-end nil)
-(defvoo nndoc-file-end nil)
-(defvoo nndoc-body-begin nil)
-(defvoo nndoc-body-end-function nil)
-(defvoo nndoc-body-begin-function nil)
-(defvoo nndoc-head-begin-function nil)
-(defvoo nndoc-body-end nil)
-(defvoo nndoc-dissection-alist nil)
-(defvoo nndoc-prepare-body nil)
-(defvoo nndoc-generate-head nil)
-(defvoo nndoc-article-transform nil)
-
-(defvoo nndoc-status-string "")
-(defvoo nndoc-group-alist nil)
-(defvoo nndoc-current-buffer nil
- "Current nndoc news buffer.")
-(defvoo nndoc-address nil)
-
-(defconst nndoc-version "nndoc 1.0"
- "nndoc version.")
-
-
-
-;;; Interface functions
-
-(nnoo-define-basics nndoc)
-
-(deffoo nndoc-retrieve-headers (articles &optional newsgroup server fetch-old)
- (when (nndoc-possibly-change-buffer newsgroup server)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (let (article entry)
- (if (stringp (car articles))
- 'headers
- (while articles
- (when (setq entry (cdr (assq (setq article (pop articles))
- nndoc-dissection-alist)))
- (insert (format "221 %d Article retrieved.\n" article))
- (if nndoc-generate-head
- (funcall nndoc-generate-head article)
- (insert-buffer-substring
- nndoc-current-buffer (car entry) (nth 1 entry)))
- (goto-char (point-max))
- (or (= (char-after (1- (point))) ?\n) (insert "\n"))
- (insert (format "Lines: %d\n" (nth 4 entry)))
- (insert ".\n")))
-
- (nnheader-fold-continuation-lines)
- 'headers)))))
-
-(deffoo nndoc-request-article (article &optional newsgroup server buffer)
- (nndoc-possibly-change-buffer newsgroup server)
- (save-excursion
- (let ((buffer (or buffer nntp-server-buffer))
- (entry (cdr (assq article nndoc-dissection-alist)))
- beg)
- (set-buffer buffer)
- (erase-buffer)
- (if (stringp article)
- nil
- (insert-buffer-substring
- nndoc-current-buffer (car entry) (nth 1 entry))
- (insert "\n")
- (setq beg (point))
- (insert-buffer-substring
- nndoc-current-buffer (nth 2 entry) (nth 3 entry))
- (goto-char beg)
- (when nndoc-prepare-body
- (funcall nndoc-prepare-body))
- (when nndoc-article-transform
- (funcall nndoc-article-transform article))
- t))))
-
-(deffoo nndoc-request-group (group &optional server dont-check)
- "Select news GROUP."
- (let (number)
- (cond
- ((not (nndoc-possibly-change-buffer group server))
- (nnheader-report 'nndoc "No such file or buffer: %s"
- nndoc-address))
- (dont-check
- (nnheader-report 'nndoc "Selected group %s" group)
- t)
- ((zerop (setq number (length nndoc-dissection-alist)))
- (nndoc-close-group group)
- (nnheader-report 'nndoc "No articles in group %s" group))
- (t
- (nnheader-insert "211 %d %d %d %s\n" number 1 number group)))))
-
-(deffoo nndoc-request-type (group &optional article)
- (cond ((not article) 'unknown)
- (nndoc-post-type nndoc-post-type)
- (t 'unknown)))
-
-(deffoo nndoc-close-group (group &optional server)
- (nndoc-possibly-change-buffer group server)
- (and nndoc-current-buffer
- (buffer-name nndoc-current-buffer)
- (kill-buffer nndoc-current-buffer))
- (setq nndoc-group-alist (delq (assoc group nndoc-group-alist)
- nndoc-group-alist))
- (setq nndoc-current-buffer nil)
- (nnoo-close-server 'nndoc server)
- (setq nndoc-dissection-alist nil)
- t)
-
-(deffoo nndoc-request-list (&optional server)
- nil)
-
-(deffoo nndoc-request-newgroups (date &optional server)
- nil)
-
-(deffoo nndoc-request-list-newsgroups (&optional server)
- nil)
-
-
-;;; Internal functions.
-
-(defun nndoc-possibly-change-buffer (group source)
- (let (buf)
- (cond
- ;; The current buffer is this group's buffer.
- ((and nndoc-current-buffer
- (buffer-name nndoc-current-buffer)
- (eq nndoc-current-buffer
- (setq buf (cdr (assoc group nndoc-group-alist))))))
- ;; We change buffers by taking an old from the group alist.
- ;; `source' is either a string (a file name) or a buffer object.
- (buf
- (setq nndoc-current-buffer buf))
- ;; It's a totally new group.
- ((or (and (bufferp nndoc-address)
- (buffer-name nndoc-address))
- (and (stringp nndoc-address)
- (file-exists-p nndoc-address)
- (not (file-directory-p nndoc-address))))
- (push (cons group (setq nndoc-current-buffer
- (get-buffer-create
- (concat " *nndoc " group "*"))))
- nndoc-group-alist)
- (setq nndoc-dissection-alist nil)
- (save-excursion
- (set-buffer nndoc-current-buffer)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (if (stringp nndoc-address)
- (insert-file-contents nndoc-address)
- (insert-buffer-substring nndoc-address)))))
- ;; Initialize the nndoc structures according to this new document.
- (when (and nndoc-current-buffer
- (not nndoc-dissection-alist))
- (save-excursion
- (set-buffer nndoc-current-buffer)
- (nndoc-set-delims)
- (nndoc-dissect-buffer)))
- (unless nndoc-current-buffer
- (nndoc-close-server))
- ;; Return whether we managed to select a file.
- nndoc-current-buffer))
-
-;; MIME (RFC 1341) digest hack by Ulrik Dickow <dickow@nbi.dk>.
-(defun nndoc-guess-digest-type ()
- "Guess what digest type the current document is."
- (let ((case-fold-search t) ; We match a bit too much, keep it simple.
- boundary-id b-delimiter entry)
- (goto-char (point-min))
- (cond
- ;; MIME digest.
- ((and
- (re-search-forward
- (concat "^Content-Type: *multipart/digest;[ \t\n]*[ \t]"
- "boundary=\"\\([^\"\n]*[^\" \t\n]\\)\"")
- nil t)
- (match-beginning 1))
- (setq boundary-id (match-string 1)
- b-delimiter (concat "\n--" boundary-id "[\n \t]+"))
- (setq entry (assq 'mime-digest nndoc-type-alist))
- (setcdr entry
- (list
- (cons 'head-end "^ ?$")
- (cons 'body-begin "^ ?\n")
- (cons 'article-begin b-delimiter)
- (cons 'body-end-function 'nndoc-digest-body-end)
-; (cons 'body-end
-; (concat "\n--" boundary-id "\\(--\\)?[\n \t]+"))
- (cons 'file-end (concat "\n--" boundary-id "--[ \t]*$"))))
- 'mime-digest)
- ;; Standard digest.
- ((and (re-search-forward (concat "^" (make-string 70 ?-) "\n\n") nil t)
- (re-search-forward
- (concat "\n\n" (make-string 30 ?-) "\n\n") nil t))
- 'standard-digest)
- ;; Stupid digest.
- (t
- 'slack-digest))))
-
-(defun nndoc-guess-type ()
- "Guess what document type is in the current buffer."
- (goto-char (point-min))
- (cond
- ((looking-at message-unix-mail-delimiter)
- 'mbox)
- ((looking-at "\^A\^A\^A\^A$")
- 'mmdf)
- ((looking-at "^Path:.*\n")
- 'news)
- ((looking-at "#! *rnews")
- 'rnews)
- ((re-search-forward "\^_\^L *\n" nil t)
- 'babyl)
- ((save-excursion
- (and (re-search-forward "^-+ Start of forwarded message -+\n+" nil t)
- (not (re-search-forward "^Subject:.*digest" nil t))))
- 'forward)
- ((let ((case-fold-search nil))
- (re-search-forward "^\t[^a-z]+ ([^a-z]+) --" nil t))
- 'clari-briefs)
- (t
- 'digest)))
-
-(defun nndoc-set-delims ()
- "Set the nndoc delimiter variables according to the type of the document."
- (let ((vars '(nndoc-file-begin
- nndoc-first-article
- nndoc-article-end nndoc-head-begin nndoc-head-end
- nndoc-file-end nndoc-article-begin
- nndoc-body-begin nndoc-body-end-function nndoc-body-end
- nndoc-prepare-body nndoc-article-transform
- nndoc-generate-head nndoc-body-begin-function
- nndoc-head-begin-function nndoc-article-begin-function)))
- (while vars
- (set (pop vars) nil)))
- (let* (defs guess)
- ;; Guess away until we find the real file type.
- (while (setq defs (cdr (assq nndoc-article-type nndoc-type-alist))
- guess (assq 'guess defs))
- (setq nndoc-article-type (funcall (cdr guess))))
- ;; Set the nndoc variables.
- (while defs
- (set (intern (format "nndoc-%s" (caar defs)))
- (cdr (pop defs))))))
-
-(defun nndoc-search (regexp)
- (prog1
- (re-search-forward regexp nil t)
- (beginning-of-line)))
-
-(defun nndoc-dissect-buffer ()
- "Go through the document and partition it into heads/bodies/articles."
- (let ((i 0)
- (first t)
- head-begin head-end body-begin body-end)
- (setq nndoc-dissection-alist nil)
- (save-excursion
- (set-buffer nndoc-current-buffer)
- (goto-char (point-min))
- ;; Find the beginning of the file.
- (when nndoc-file-begin
- (nndoc-search nndoc-file-begin))
- ;; Go through the file.
- (while (if (and first nndoc-first-article)
- (nndoc-search nndoc-first-article)
- (if nndoc-article-begin-function
- (funcall nndoc-article-begin-function)
- (nndoc-search nndoc-article-begin)))
- (setq first nil)
- (cond (nndoc-head-begin-function
- (funcall nndoc-head-begin-function))
- (nndoc-head-begin
- (nndoc-search nndoc-head-begin)))
- (if (and nndoc-file-end
- (looking-at nndoc-file-end))
- (goto-char (point-max))
- (setq head-begin (point))
- (nndoc-search (or nndoc-head-end "^$"))
- (setq head-end (point))
- (if nndoc-body-begin-function
- (funcall nndoc-body-begin-function)
- (nndoc-search (or nndoc-body-begin "^\n")))
- (setq body-begin (point))
- (or (and nndoc-body-end-function
- (funcall nndoc-body-end-function))
- (and nndoc-body-end
- (nndoc-search nndoc-body-end))
- (if nndoc-article-begin-function
- (funcall nndoc-article-begin-function)
- (nndoc-search nndoc-article-begin))
- (progn
- (goto-char (point-max))
- (when nndoc-file-end
- (and (re-search-backward nndoc-file-end nil t)
- (beginning-of-line)))))
- (setq body-end (point))
- (push (list (incf i) head-begin head-end body-begin body-end
- (count-lines body-begin body-end))
- nndoc-dissection-alist))))))
-
-(defun nndoc-unquote-dashes ()
- "Unquote quoted non-separators in digests."
- (while (re-search-forward "^- -"nil t)
- (replace-match "-" t t)))
-
-(defun nndoc-digest-body-end ()
- (and (re-search-forward nndoc-article-begin nil t)
- (goto-char (match-beginning 0))))
-
-(defun nndoc-mbox-article-begin ()
- (when (re-search-forward nndoc-article-begin nil t)
- (goto-char (match-beginning 0))))
-
-(defun nndoc-mbox-body-end ()
- (let ((beg (point))
- len end)
- (when
- (save-excursion
- (and (re-search-backward nndoc-article-begin nil t)
- (setq end (point))
- (search-forward "\n\n" beg t)
- (re-search-backward
- "^Content-Length:[ \t]*\\([0-9]+\\) *$" end t)
- (setq len (string-to-int (match-string 1)))
- (search-forward "\n\n" beg t)
- (or (= (setq len (+ (point) len)) (point-max))
- (and (< len (point-max))
- (goto-char len)
- (looking-at nndoc-article-begin)))))
- (goto-char len))))
-
-(defun nndoc-rnews-body-end ()
- (and (re-search-backward nndoc-article-begin nil t)
- (forward-line 1)
- (goto-char (+ (point) (string-to-int (match-string 1))))))
-
-(defun nndoc-transform-clari-briefs (article)
- (goto-char (point-min))
- (when (looking-at " *\\*\\(.*\\)\n")
- (replace-match "" t t))
- (nndoc-generate-clari-briefs-head article))
-
-(defun nndoc-generate-clari-briefs-head (article)
- (let ((entry (cdr (assq article nndoc-dissection-alist)))
- subject from)
- (save-excursion
- (set-buffer nndoc-current-buffer)
- (save-restriction
- (narrow-to-region (car entry) (nth 3 entry))
- (goto-char (point-min))
- (when (looking-at " *\\*\\(.*\\)$")
- (setq subject (match-string 1))
- (when (string-match "[ \t]+$" subject)
- (setq subject (substring subject 0 (match-beginning 0)))))
- (when
- (let ((case-fold-search nil))
- (re-search-forward
- "^\t\\([^a-z]+\\(,[^(]+\\)? ([^a-z]+)\\) --" nil t))
- (setq from (match-string 1)))))
- (insert "From: " "clari@clari.net (" (or from "unknown") ")"
- "\nSubject: " (or subject "(no subject)") "\n")))
-
-(defun nndoc-babyl-body-begin ()
- (re-search-forward "^\n" nil t)
- (when (looking-at "\*\*\* EOOH \*\*\*")
- (re-search-forward "^\n" nil t)))
-
-(defun nndoc-babyl-head-begin ()
- (when (re-search-forward "^[0-9].*\n" nil t)
- (when (looking-at "\*\*\* EOOH \*\*\*")
- (forward-line 1))
- t))
-
-(provide 'nndoc)
-
-;;; nndoc.el ends here
diff --git a/lisp/nneething.el b/lisp/nneething.el
deleted file mode 100644
index bcf013fdf8b..00000000000
--- a/lisp/nneething.el
+++ /dev/null
@@ -1,356 +0,0 @@
-;;; nneething.el --- random file access for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: news, mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Based on nnspool.el by Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>.
-;; For an overview of what the interface functions do, please see the
-;; Gnus sources.
-
-;;; Code:
-
-(require 'nnheader)
-(require 'nnmail)
-(require 'nnoo)
-(eval-when-compile (require 'cl))
-
-(nnoo-declare nneething)
-
-(defvoo nneething-map-file-directory "~/.nneething/"
- "*Where nneething stores the map files.")
-
-(defvoo nneething-map-file ".nneething"
- "*Name of the map files.")
-
-(defvoo nneething-exclude-files nil
- "*Regexp saying what files to exclude from the group.
-If this variable is nil, no files will be excluded.")
-
-
-
-;;; Internal variables.
-
-(defconst nneething-version "nneething 1.0"
- "nneething version.")
-
-(defvoo nneething-current-directory nil
- "Current news group directory.")
-
-(defvoo nneething-status-string "")
-(defvoo nneething-group-alist nil)
-
-(defvoo nneething-message-id-number 0)
-(defvoo nneething-work-buffer " *nneething work*")
-
-(defvoo nneething-directory nil)
-(defvoo nneething-group nil)
-(defvoo nneething-map nil)
-(defvoo nneething-read-only nil)
-(defvoo nneething-active nil)
-
-
-
-;;; Interface functions.
-
-(nnoo-define-basics nneething)
-
-(deffoo nneething-retrieve-headers (articles &optional group server fetch-old)
- (nneething-possibly-change-directory group)
-
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (let* ((number (length articles))
- (count 0)
- (large (and (numberp nnmail-large-newsgroup)
- (> number nnmail-large-newsgroup)))
- article file)
-
- (if (stringp (car articles))
- 'headers
-
- (while (setq article (pop articles))
- (setq file (nneething-file-name article))
-
- (when (and (file-exists-p file)
- (or (file-directory-p file)
- (not (zerop (nnheader-file-size file)))))
- (insert (format "221 %d Article retrieved.\n" article))
- (nneething-insert-head file)
- (insert ".\n"))
-
- (incf count)
-
- (and large
- (zerop (% count 20))
- (message "nneething: Receiving headers... %d%%"
- (/ (* count 100) number))))
-
- (when large
- (message "nneething: Receiving headers...done"))
-
- (nnheader-fold-continuation-lines)
- 'headers))))
-
-(deffoo nneething-request-article (id &optional group server buffer)
- (nneething-possibly-change-directory group)
- (let ((file (unless (stringp id) (nneething-file-name id)))
- (nntp-server-buffer (or buffer nntp-server-buffer)))
- (and (stringp file) ; We did not request by Message-ID.
- (file-exists-p file) ; The file exists.
- (not (file-directory-p file)) ; It's not a dir.
- (save-excursion
- (nnmail-find-file file) ; Insert the file in the nntp buf.
- (or (nnheader-article-p) ; Either it's a real article...
- (progn
- (goto-char (point-min))
- (nneething-make-head file (current-buffer)) ; ... or we fake some headers.
- (insert "\n")))
- t))))
-
-(deffoo nneething-request-group (group &optional dir dont-check)
- (nneething-possibly-change-directory group dir)
- (unless dont-check
- (nneething-create-mapping)
- (if (> (car nneething-active) (cdr nneething-active))
- (nnheader-insert "211 0 1 0 %s\n" group)
- (nnheader-insert
- "211 %d %d %d %s\n"
- (- (1+ (cdr nneething-active)) (car nneething-active))
- (car nneething-active) (cdr nneething-active)
- group)))
- t)
-
-(deffoo nneething-request-list (&optional server dir)
- (nnheader-report 'nneething "LIST is not implemented."))
-
-(deffoo nneething-request-newgroups (date &optional server)
- (nnheader-report 'nneething "NEWSGROUPS is not implemented."))
-
-(deffoo nneething-request-type (group &optional article)
- 'unknown)
-
-(deffoo nneething-close-group (group &optional server)
- (setq nneething-current-directory nil)
- t)
-
-
-;;; Internal functions.
-
-(defun nneething-possibly-change-directory (group &optional dir)
- (when group
- (if (and nneething-group
- (string= group nneething-group))
- t
- (let (entry)
- (if (setq entry (assoc group nneething-group-alist))
- (progn
- (setq nneething-group group)
- (setq nneething-directory (nth 1 entry))
- (setq nneething-map (nth 2 entry))
- (setq nneething-active (nth 3 entry)))
- (setq nneething-group group)
- (setq nneething-directory dir)
- (setq nneething-map nil)
- (setq nneething-active (cons 1 0))
- (nneething-create-mapping)
- (push (list group dir nneething-map nneething-active)
- nneething-group-alist))))))
-
-(defun nneething-map-file ()
- ;; We make sure that the .nneething directory exists.
- (unless (file-exists-p nneething-map-file-directory)
- (make-directory nneething-map-file-directory 'parents))
- ;; We store it in a special directory under the user's home dir.
- (concat (file-name-as-directory nneething-map-file-directory)
- nneething-group nneething-map-file))
-
-(defun nneething-create-mapping ()
- ;; Read nneething-active and nneething-map.
- (let ((map-file (nneething-map-file))
- (files (directory-files nneething-directory))
- touched map-files)
- (if (file-exists-p map-file)
- (condition-case nil
- (load map-file nil t t)
- (error nil)))
- (or nneething-active (setq nneething-active (cons 1 0)))
- ;; Old nneething had a different map format.
- (when (and (cdar nneething-map)
- (atom (cdar nneething-map)))
- (setq nneething-map
- (mapcar (lambda (n)
- (list (cdr n) (car n)
- (nth 5 (file-attributes
- (nneething-file-name (car n))))))
- nneething-map)))
- ;; Remove files matching the exclusion regexp.
- (when nneething-exclude-files
- (let ((f files)
- prev)
- (while f
- (if (string-match nneething-exclude-files (car f))
- (if prev (setcdr prev (cdr f))
- (setq files (cdr files)))
- (setq prev f))
- (setq f (cdr f)))))
- ;; Remove deleted files from the map.
- (let ((map nneething-map)
- prev)
- (while map
- (if (and (member (cadar map) files)
- ;; We also remove files that have changed mod times.
- (equal (nth 5 (file-attributes
- (nneething-file-name (cadar map))))
- (caddar map)))
- (progn
- (push (cadar map) map-files)
- (setq prev map))
- (setq touched t)
- (if prev
- (setcdr prev (cdr map))
- (setq nneething-map (cdr nneething-map))))
- (setq map (cdr map))))
- ;; Find all new files and enter them into the map.
- (while files
- (unless (member (car files) map-files)
- ;; This file is not in the map, so we enter it.
- (setq touched t)
- (setcdr nneething-active (1+ (cdr nneething-active)))
- (push (list (cdr nneething-active) (car files)
- (nth 5 (file-attributes
- (nneething-file-name (car files)))))
- nneething-map))
- (setq files (cdr files)))
- (when (and touched
- (not nneething-read-only))
- (save-excursion
- (nnheader-set-temp-buffer " *nneething map*")
- (insert "(setq nneething-map '" (prin1-to-string nneething-map) ")\n"
- "(setq nneething-active '" (prin1-to-string nneething-active)
- ")\n")
- (write-region (point-min) (point-max) map-file nil 'nomesg)
- (kill-buffer (current-buffer))))))
-
-(defun nneething-insert-head (file)
- "Insert the head of FILE."
- (when (nneething-get-head file)
- (insert-buffer-substring nneething-work-buffer)
- (goto-char (point-max))))
-
-(defun nneething-make-head (file &optional buffer)
- "Create a head by looking at the file attributes of FILE."
- (let ((atts (file-attributes file)))
- (insert
- "Subject: " (file-name-nondirectory file) "\n"
- "Message-ID: <nneething-"
- (int-to-string (incf nneething-message-id-number))
- "@" (system-name) ">\n"
- (if (equal '(0 0) (nth 5 atts)) ""
- (concat "Date: " (current-time-string (nth 5 atts)) "\n"))
- (or (if buffer
- (save-excursion
- (set-buffer buffer)
- (if (re-search-forward "<[a-zA-Z0-9_]@[-a-zA-Z0-9_]>" 1000 t)
- (concat "From: " (match-string 0) "\n"))))
- (nneething-from-line (nth 2 atts) file))
- (if (> (string-to-int (int-to-string (nth 7 atts))) 0)
- (concat "Chars: " (int-to-string (nth 7 atts)) "\n")
- "")
- (if buffer
- (save-excursion
- (set-buffer buffer)
- (concat "Lines: " (int-to-string
- (count-lines (point-min) (point-max))) "\n"))
- "")
- )))
-
-(defun nneething-from-line (uid &optional file)
- "Return a From header based of UID."
- (let* ((login (condition-case nil
- (user-login-name uid)
- (error
- (cond ((= uid (user-uid)) (user-login-name))
- ((zerop uid) "root")
- (t (int-to-string uid))))))
- (name (condition-case nil
- (user-full-name uid)
- (error
- (cond ((= uid (user-uid)) (user-full-name))
- ((zerop uid) "Ms. Root")))))
- (host (if (string-match "\\`/[^/@]*@\\([^:/]+\\):" file)
- (prog1
- (substring file
- (match-beginning 1)
- (match-end 1))
- (if (string-match "/\\(users\\|home\\)/\\([^/]+\\)/" file)
- (setq login (substring file
- (match-beginning 2)
- (match-end 2))
- name nil)))
- (system-name))))
- (concat "From: " login "@" host
- (if name (concat " (" name ")") "") "\n")))
-
-(defun nneething-get-head (file)
- "Either find the head in FILE or make a head for FILE."
- (save-excursion
- (set-buffer (get-buffer-create nneething-work-buffer))
- (setq case-fold-search nil)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (cond
- ((not (file-exists-p file))
- ;; The file do not exist.
- nil)
- ((or (file-directory-p file)
- (file-symlink-p file))
- ;; It's a dir, so we fudge a head.
- (nneething-make-head file) t)
- (t
- ;; We examine the file.
- (nnheader-insert-head file)
- (if (nnheader-article-p)
- (delete-region
- (progn
- (goto-char (point-min))
- (or (and (search-forward "\n\n" nil t)
- (1- (point)))
- (point-max)))
- (point-max))
- (goto-char (point-min))
- (nneething-make-head file (current-buffer))
- (delete-region (point) (point-max)))
- t))))
-
-(defun nneething-file-name (article)
- "Return the file name of ARTICLE."
- (concat (file-name-as-directory nneething-directory)
- (if (numberp article)
- (cadr (assq article nneething-map))
- article)))
-
-(provide 'nneething)
-
-;;; nneething.el ends here
diff --git a/lisp/nnfolder.el b/lisp/nnfolder.el
deleted file mode 100644
index 775273dbeca..00000000000
--- a/lisp/nnfolder.el
+++ /dev/null
@@ -1,784 +0,0 @@
-;;; nnfolder.el --- mail folder access for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Scott Byer <byer@mv.us.adobe.com>
-;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; For an overview of what the interface functions do, please see the
-;; Gnus sources.
-
-;; Various enhancements by byer@mv.us.adobe.com (Scott Byer).
-
-;;; Code:
-
-(require 'nnheader)
-(require 'message)
-(require 'nnmail)
-(require 'nnoo)
-(eval-when-compile (require 'cl))
-
-(nnoo-declare nnfolder)
-
-(defvoo nnfolder-directory (expand-file-name message-directory)
- "The name of the nnfolder directory.")
-
-(defvoo nnfolder-active-file
- (nnheader-concat nnfolder-directory "active")
- "The name of the active file.")
-
-;; I renamed this variable to something more in keeping with the general GNU
-;; style. -SLB
-
-(defvoo nnfolder-ignore-active-file nil
- "If non-nil, causes nnfolder to do some extra work in order to determine
-the true active ranges of an mbox file. Note that the active file is still
-saved, but its values are not used. This costs some extra time when
-scanning an mbox when opening it.")
-
-(defvoo nnfolder-distrust-mbox nil
- "If non-nil, causes nnfolder to not trust the user with respect to
-inserting unaccounted for mail in the middle of an mbox file. This can greatly
-slow down scans, which now must scan the entire file for unmarked messages.
-When nil, scans occur forward from the last marked message, a huge
-time saver for large mailboxes.")
-
-(defvoo nnfolder-newsgroups-file
- (concat (file-name-as-directory nnfolder-directory) "newsgroups")
- "Mail newsgroups description file.")
-
-(defvoo nnfolder-get-new-mail t
- "If non-nil, nnfolder will check the incoming mail file and split the mail.")
-
-(defvoo nnfolder-prepare-save-mail-hook nil
- "Hook run narrowed to an article before saving.")
-
-(defvoo nnfolder-save-buffer-hook nil
- "Hook run before saving the nnfolder mbox buffer.")
-
-(defvoo nnfolder-inhibit-expiry nil
- "If non-nil, inhibit expiry.")
-
-
-
-(defconst nnfolder-version "nnfolder 1.0"
- "nnfolder version.")
-
-(defconst nnfolder-article-marker "X-Gnus-Article-Number: "
- "String used to demarcate what the article number for a message is.")
-
-(defvoo nnfolder-current-group nil)
-(defvoo nnfolder-current-buffer nil)
-(defvoo nnfolder-status-string "")
-(defvoo nnfolder-group-alist nil)
-(defvoo nnfolder-buffer-alist nil)
-(defvoo nnfolder-scantime-alist nil)
-
-
-
-;;; Interface functions
-
-(nnoo-define-basics nnfolder)
-
-(deffoo nnfolder-retrieve-headers (articles &optional group server fetch-old)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (let ((delim-string (concat "^" message-unix-mail-delimiter))
- article art-string start stop)
- (nnfolder-possibly-change-group group server)
- (when nnfolder-current-buffer
- (set-buffer nnfolder-current-buffer)
- (goto-char (point-min))
- (if (stringp (car articles))
- 'headers
- (while articles
- (setq article (car articles))
- (setq art-string (nnfolder-article-string article))
- (set-buffer nnfolder-current-buffer)
- (if (or (search-forward art-string nil t)
- ;; Don't search the whole file twice! Also, articles
- ;; probably have some locality by number, so searching
- ;; backwards will be faster. Especially if we're at the
- ;; beginning of the buffer :-). -SLB
- (search-backward art-string nil t))
- (progn
- (setq start (or (re-search-backward delim-string nil t)
- (point)))
- (search-forward "\n\n" nil t)
- (setq stop (1- (point)))
- (set-buffer nntp-server-buffer)
- (insert (format "221 %d Article retrieved.\n" article))
- (insert-buffer-substring nnfolder-current-buffer start stop)
- (goto-char (point-max))
- (insert ".\n")))
- (setq articles (cdr articles)))
-
- (set-buffer nntp-server-buffer)
- (nnheader-fold-continuation-lines)
- 'headers)))))
-
-(deffoo nnfolder-open-server (server &optional defs)
- (nnoo-change-server 'nnfolder server defs)
- (when (not (file-exists-p nnfolder-directory))
- (condition-case ()
- (make-directory nnfolder-directory t)
- (error t)))
- (cond
- ((not (file-exists-p nnfolder-directory))
- (nnfolder-close-server)
- (nnheader-report 'nnfolder "Couldn't create directory: %s"
- nnfolder-directory))
- ((not (file-directory-p (file-truename nnfolder-directory)))
- (nnfolder-close-server)
- (nnheader-report 'nnfolder "Not a directory: %s" nnfolder-directory))
- (t
- (nnheader-report 'nnfolder "Opened server %s using directory %s"
- server nnfolder-directory)
- t)))
-
-(deffoo nnfolder-request-close ()
- (let ((alist nnfolder-buffer-alist))
- (while alist
- (nnfolder-close-group (caar alist) nil t)
- (setq alist (cdr alist))))
- (nnoo-close-server 'nnfolder)
- (setq nnfolder-buffer-alist nil
- nnfolder-group-alist nil))
-
-(deffoo nnfolder-request-article (article &optional group server buffer)
- (nnfolder-possibly-change-group group server)
- (save-excursion
- (set-buffer nnfolder-current-buffer)
- (goto-char (point-min))
- (if (search-forward (nnfolder-article-string article) nil t)
- (let (start stop)
- (re-search-backward (concat "^" message-unix-mail-delimiter) nil t)
- (setq start (point))
- (forward-line 1)
- (or (and (re-search-forward
- (concat "^" message-unix-mail-delimiter) nil t)
- (forward-line -1))
- (goto-char (point-max)))
- (setq stop (point))
- (let ((nntp-server-buffer (or buffer nntp-server-buffer)))
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (insert-buffer-substring nnfolder-current-buffer start stop)
- (goto-char (point-min))
- (while (looking-at "From ")
- (delete-char 5)
- (insert "X-From-Line: ")
- (forward-line 1))
- (if (numberp article)
- (cons nnfolder-current-group article)
- (goto-char (point-min))
- (search-forward (concat "\n" nnfolder-article-marker))
- (cons nnfolder-current-group
- (string-to-int
- (buffer-substring
- (point) (progn (end-of-line) (point)))))))))))
-
-(deffoo nnfolder-request-group (group &optional server dont-check)
- (save-excursion
- (nnmail-activate 'nnfolder)
- (if (not (assoc group nnfolder-group-alist))
- (nnheader-report 'nnfolder "No such group: %s" group)
- (nnfolder-possibly-change-group group server)
- (if dont-check
- (progn
- (nnheader-report 'nnfolder "Selected group %s" group)
- t)
- (let* ((active (assoc group nnfolder-group-alist))
- (group (car active))
- (range (cadr active)))
- (cond
- ((null active)
- (nnheader-report 'nnfolder "No such group: %s" group))
- ((null nnfolder-current-group)
- (nnheader-report 'nnfolder "Empty group: %s" group))
- (t
- (nnheader-report 'nnfolder "Selected group %s" group)
- (nnheader-insert "211 %d %d %d %s\n"
- (1+ (- (cdr range) (car range)))
- (car range) (cdr range) group))))))))
-
-(deffoo nnfolder-request-scan (&optional group server)
- (nnfolder-possibly-change-group group server t)
- (nnmail-get-new-mail
- 'nnfolder
- (lambda ()
- (let ((bufs nnfolder-buffer-alist))
- (save-excursion
- (while bufs
- (if (not (buffer-name (nth 1 (car bufs))))
- (setq nnfolder-buffer-alist
- (delq (car bufs) nnfolder-buffer-alist))
- (set-buffer (nth 1 (car bufs)))
- (nnfolder-save-buffer)
- (kill-buffer (current-buffer)))
- (setq bufs (cdr bufs))))))
- nnfolder-directory
- group))
-
-;; Don't close the buffer if we're not shutting down the server. This way,
-;; we can keep the buffer in the group buffer cache, and not have to grovel
-;; over the buffer again unless we add new mail to it or modify it in some
-;; way.
-
-(deffoo nnfolder-close-group (group &optional server force)
- ;; Make sure we _had_ the group open.
- (when (or (assoc group nnfolder-buffer-alist)
- (equal group nnfolder-current-group))
- (let ((inf (assoc group nnfolder-buffer-alist)))
- (when inf
- (when nnfolder-current-group
- (push (list nnfolder-current-group nnfolder-current-buffer)
- nnfolder-buffer-alist))
- (setq nnfolder-buffer-alist
- (delq inf nnfolder-buffer-alist))
- (setq nnfolder-current-buffer (cadr inf)
- nnfolder-current-group (car inf))))
- (when (and nnfolder-current-buffer
- (buffer-name nnfolder-current-buffer))
- (save-excursion
- (set-buffer nnfolder-current-buffer)
- ;; If the buffer was modified, write the file out now.
- (nnfolder-save-buffer)
- ;; If we're shutting the server down, we need to kill the
- ;; buffer and remove it from the open buffer list. Or, of
- ;; course, if we're trying to minimize our space impact.
- (kill-buffer (current-buffer))
- (setq nnfolder-buffer-alist (delq (assoc group nnfolder-buffer-alist)
- nnfolder-buffer-alist)))))
- (setq nnfolder-current-group nil
- nnfolder-current-buffer nil)
- t)
-
-(deffoo nnfolder-request-create-group (group &optional server)
- (nnfolder-possibly-change-group nil server)
- (nnmail-activate 'nnfolder)
- (when group
- (unless (assoc group nnfolder-group-alist)
- (push (list group (cons 1 0)) nnfolder-group-alist)
- (nnmail-save-active nnfolder-group-alist nnfolder-active-file)))
- t)
-
-(deffoo nnfolder-request-list (&optional server)
- (nnfolder-possibly-change-group nil server)
- (save-excursion
- (nnmail-find-file nnfolder-active-file)
- (setq nnfolder-group-alist (nnmail-get-active))))
-
-(deffoo nnfolder-request-newgroups (date &optional server)
- (nnfolder-possibly-change-group nil server)
- (nnfolder-request-list server))
-
-(deffoo nnfolder-request-list-newsgroups (&optional server)
- (nnfolder-possibly-change-group nil server)
- (save-excursion
- (nnmail-find-file nnfolder-newsgroups-file)))
-
-(deffoo nnfolder-request-expire-articles
- (articles newsgroup &optional server force)
- (nnfolder-possibly-change-group newsgroup server)
- (let* ((is-old t)
- rest)
- (nnmail-activate 'nnfolder)
-
- (save-excursion
- (set-buffer nnfolder-current-buffer)
- (while (and articles is-old)
- (goto-char (point-min))
- (if (search-forward (nnfolder-article-string (car articles)) nil t)
- (if (setq is-old
- (nnmail-expired-article-p
- newsgroup
- (buffer-substring
- (point) (progn (end-of-line) (point)))
- force nnfolder-inhibit-expiry))
- (progn
- (nnheader-message 5 "Deleting article %d..."
- (car articles) newsgroup)
- (nnfolder-delete-mail))
- (setq rest (cons (car articles) rest))))
- (setq articles (cdr articles)))
- (nnfolder-save-buffer)
- ;; Find the lowest active article in this group.
- (let* ((active (cadr (assoc newsgroup nnfolder-group-alist)))
- (marker (concat "\n" nnfolder-article-marker))
- (number "[0-9]+")
- (activemin (cdr active)))
- (goto-char (point-min))
- (while (and (search-forward marker nil t)
- (re-search-forward number nil t))
- (setq activemin (min activemin
- (string-to-number (buffer-substring
- (match-beginning 0)
- (match-end 0))))))
- (setcar active activemin))
- (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
- (nconc rest articles))))
-
-(deffoo nnfolder-request-move-article
- (article group server accept-form &optional last)
- (nnfolder-possibly-change-group group server)
- (let ((buf (get-buffer-create " *nnfolder move*"))
- result)
- (and
- (nnfolder-request-article article group server)
- (save-excursion
- (set-buffer buf)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert-buffer-substring nntp-server-buffer)
- (goto-char (point-min))
- (while (re-search-forward
- (concat "^" nnfolder-article-marker)
- (save-excursion (search-forward "\n\n" nil t) (point)) t)
- (delete-region (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point))))
- (setq result (eval accept-form))
- (kill-buffer buf)
- result)
- (save-excursion
- (nnfolder-possibly-change-group group server)
- (set-buffer nnfolder-current-buffer)
- (goto-char (point-min))
- (if (search-forward (nnfolder-article-string article) nil t)
- (nnfolder-delete-mail))
- (and last (nnfolder-save-buffer))))
- result))
-
-(deffoo nnfolder-request-accept-article (group &optional server last)
- (nnfolder-possibly-change-group group server)
- (nnmail-check-syntax)
- (and (stringp group) (nnfolder-possibly-change-group group))
- (let ((buf (current-buffer))
- result)
- (goto-char (point-min))
- (when (looking-at "X-From-Line: ")
- (replace-match "From "))
- (and
- (nnfolder-request-list)
- (save-excursion
- (set-buffer buf)
- (goto-char (point-min))
- (search-forward "\n\n" nil t)
- (forward-line -1)
- (while (re-search-backward (concat "^" nnfolder-article-marker) nil t)
- (delete-region (point) (progn (forward-line 1) (point))))
- (setq result (car (nnfolder-save-mail (and (stringp group) group)))))
- (save-excursion
- (set-buffer nnfolder-current-buffer)
- (and last (nnfolder-save-buffer))))
- (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
- (unless result
- (nnheader-report 'nnfolder "Couldn't store article"))
- result))
-
-(deffoo nnfolder-request-replace-article (article group buffer)
- (nnfolder-possibly-change-group group)
- (save-excursion
- (set-buffer nnfolder-current-buffer)
- (goto-char (point-min))
- (if (not (search-forward (nnfolder-article-string article) nil t))
- nil
- (nnfolder-delete-mail t t)
- (insert-buffer-substring buffer)
- (nnfolder-save-buffer)
- t)))
-
-(deffoo nnfolder-request-delete-group (group &optional force server)
- (nnfolder-close-group group server t)
- ;; Delete all articles in GROUP.
- (if (not force)
- () ; Don't delete the articles.
- ;; Delete the file that holds the group.
- (condition-case nil
- (delete-file (nnfolder-group-pathname group))
- (error nil)))
- ;; Remove the group from all structures.
- (setq nnfolder-group-alist
- (delq (assoc group nnfolder-group-alist) nnfolder-group-alist)
- nnfolder-current-group nil
- nnfolder-current-buffer nil)
- ;; Save the active file.
- (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
- t)
-
-(deffoo nnfolder-request-rename-group (group new-name &optional server)
- (nnfolder-possibly-change-group group server)
- (save-excursion
- (set-buffer nnfolder-current-buffer)
- (and (file-writable-p buffer-file-name)
- (condition-case ()
- (progn
- (rename-file
- buffer-file-name
- (nnfolder-group-pathname new-name))
- t)
- (error nil))
- ;; That went ok, so we change the internal structures.
- (let ((entry (assoc group nnfolder-group-alist)))
- (and entry (setcar entry new-name))
- (setq nnfolder-current-buffer nil
- nnfolder-current-group nil)
- ;; Save the new group alist.
- (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
- ;; We kill the buffer instead of renaming it and stuff.
- (kill-buffer (current-buffer))
- t))))
-
-
-;;; Internal functions.
-
-(defun nnfolder-article-string (article)
- (if (numberp article)
- (concat "\n" nnfolder-article-marker (int-to-string article) " ")
- (concat "\nMessage-ID: " article)))
-
-(defun nnfolder-delete-mail (&optional force leave-delim)
- "Delete the message that point is in."
- (save-excursion
- (delete-region
- (save-excursion
- (re-search-backward (concat "^" message-unix-mail-delimiter) nil t)
- (if leave-delim (progn (forward-line 1) (point))
- (match-beginning 0)))
- (progn
- (forward-line 1)
- (if (re-search-forward (concat "^" message-unix-mail-delimiter) nil t)
- (if (and (not (bobp)) leave-delim)
- (progn (forward-line -2) (point))
- (match-beginning 0))
- (point-max))))))
-
-;; When scanning, we're not looking t immediately switch into the group - if
-;; we know our information is up to date, don't even bother reading the file.
-(defun nnfolder-possibly-change-group (group &optional server scanning)
- (when (and server
- (not (nnfolder-server-opened server)))
- (nnfolder-open-server server))
- (when (and group (or nnfolder-current-buffer
- (not (equal group nnfolder-current-group))))
- (unless (file-exists-p nnfolder-directory)
- (make-directory (directory-file-name nnfolder-directory) t))
- (nnfolder-possibly-activate-groups nil)
- (or (assoc group nnfolder-group-alist)
- (not (file-exists-p
- (nnfolder-group-pathname group)))
- (progn
- (setq nnfolder-group-alist
- (cons (list group (cons 1 0)) nnfolder-group-alist))
- (nnmail-save-active nnfolder-group-alist nnfolder-active-file)))
- (let (inf file)
- (if (and (equal group nnfolder-current-group)
- nnfolder-current-buffer
- (buffer-name nnfolder-current-buffer))
- ()
- (setq nnfolder-current-group group)
-
- ;; If we have to change groups, see if we don't already have the mbox
- ;; in memory. If we do, verify the modtime and destroy the mbox if
- ;; needed so we can rescan it.
- (if (setq inf (assoc group nnfolder-buffer-alist))
- (setq nnfolder-current-buffer (nth 1 inf)))
-
- ;; If the buffer is not live, make sure it isn't in the alist. If it
- ;; is live, verify that nobody else has touched the file since last
- ;; time.
- (if (or (not (and nnfolder-current-buffer
- (buffer-name nnfolder-current-buffer)))
- (not (and (bufferp nnfolder-current-buffer)
- (verify-visited-file-modtime
- nnfolder-current-buffer))))
- (progn
- (if (and nnfolder-current-buffer
- (buffer-name nnfolder-current-buffer)
- (bufferp nnfolder-current-buffer))
- (kill-buffer nnfolder-current-buffer))
- (setq nnfolder-buffer-alist (delq inf nnfolder-buffer-alist))
- (setq inf nil)))
-
- (if inf
- ()
- (save-excursion
- (setq file (nnfolder-group-pathname group))
- (if (file-directory-p (file-truename file))
- ()
- (unless (file-exists-p file)
- (unless (file-exists-p (file-name-directory file))
- (make-directory (file-name-directory file) t))
- (write-region 1 1 file t 'nomesg))
- (setq nnfolder-current-buffer
- (nnfolder-read-folder file scanning))
- (if nnfolder-current-buffer
- (progn
- (set-buffer nnfolder-current-buffer)
- (setq nnfolder-buffer-alist
- (cons (list group nnfolder-current-buffer)
- nnfolder-buffer-alist)))))))))
- (setq nnfolder-current-group group)))
-
-(defun nnfolder-save-mail (&optional group)
- "Called narrowed to an article."
- (let* ((nnmail-split-methods
- (if group (list (list group "")) nnmail-split-methods))
- (group-art-list
- (nreverse (nnmail-article-group 'nnfolder-active-number)))
- (delim (concat "^" message-unix-mail-delimiter))
- save-list group-art)
- (goto-char (point-min))
- ;; This might come from somewhere else.
- (unless (looking-at delim)
- (insert "From nobody " (current-time-string) "\n")
- (goto-char (point-min)))
- ;; Quote all "From " lines in the article.
- (forward-line 1)
- (while (re-search-forward delim nil t)
- (beginning-of-line)
- (insert "> "))
- (setq save-list group-art-list)
- (nnmail-insert-lines)
- (nnmail-insert-xref group-art-list)
- (run-hooks 'nnmail-prepare-save-mail-hook)
- (run-hooks 'nnfolder-prepare-save-mail-hook)
-
- ;; Insert the mail into each of the destination groups.
- (while group-art-list
- (setq group-art (car group-art-list)
- group-art-list (cdr group-art-list))
-
- ;; Kill the previous newsgroup markers.
- (goto-char (point-min))
- (search-forward "\n\n" nil t)
- (forward-line -1)
- (while (search-backward (concat "\n" nnfolder-article-marker) nil t)
- (delete-region (1+ (point)) (progn (forward-line 2) (point))))
-
- (nnfolder-possibly-change-group (car group-art))
- ;; Insert the new newsgroup marker.
- (nnfolder-insert-newsgroup-line group-art)
- (unless nnfolder-current-buffer
- (nnfolder-close-group (car group-art))
- (nnfolder-request-create-group (car group-art))
- (nnfolder-possibly-change-group (car group-art)))
- (let ((beg (point-min))
- (end (point-max))
- (obuf (current-buffer)))
- (set-buffer nnfolder-current-buffer)
- (goto-char (point-max))
- (unless (eolp)
- (insert "\n"))
- (insert "\n")
- (insert-buffer-substring obuf beg end)
- (set-buffer obuf)))
-
- ;; Did we save it anywhere?
- save-list))
-
-(defun nnfolder-insert-newsgroup-line (group-art)
- (save-excursion
- (goto-char (point-min))
- (if (search-forward "\n\n" nil t)
- (progn
- (forward-char -1)
- (insert (format (concat nnfolder-article-marker "%d %s\n")
- (cdr group-art) (current-time-string)))))))
-
-(defun nnfolder-possibly-activate-groups (&optional group)
- (save-excursion
- ;; If we're looking for the activation of a specific group, find out
- ;; its real name and switch to it.
- (if group (nnfolder-possibly-change-group group))
- ;; If the group alist isn't active, activate it now.
- (nnmail-activate 'nnfolder)))
-
-(defun nnfolder-active-number (group)
- (when group
- (save-excursion
- ;; Find the next article number in GROUP.
- (prog1
- (let ((active (cadr (assoc group nnfolder-group-alist))))
- (if active
- (setcdr active (1+ (cdr active)))
- ;; This group is new, so we create a new entry for it.
- ;; This might be a bit naughty... creating groups on the drop of
- ;; a hat, but I don't know...
- (setq nnfolder-group-alist
- (cons (list group (setq active (cons 1 1)))
- nnfolder-group-alist)))
- (cdr active))
- (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
- (nnfolder-possibly-activate-groups group)))))
-
-
-;; This method has a problem if you've accidentally let the active list get
-;; out of sync with the files. This could happen, say, if you've
-;; accidentally gotten new mail with something other than Gnus (but why
-;; would _that_ ever happen? :-). In that case, we will be in the middle of
-;; processing the file, ready to add new X-Gnus article number markers, and
-;; we'll run across a message with no ID yet - the active list _may_not_ be
-;; ready for us yet.
-
-;; To handle this, I'm modifying this routine to maintain the maximum ID seen
-;; so far, and when we hit a message with no ID, we will _manually_ scan the
-;; rest of the message looking for any more, possibly higher IDs. We'll
-;; assume the maximum that we find is the highest active. Note that this
-;; shouldn't cost us much extra time at all, but will be a lot less
-;; vulnerable to glitches between the mbox and the active file.
-
-(defun nnfolder-read-folder (file &optional scanning)
- ;; This is an attempt at a serious shortcut - don't even read in the file
- ;; if we know we've seen it since the last time it was touched.
- (let ((scantime (cadr (assoc nnfolder-current-group
- nnfolder-scantime-alist)))
- (modtime (nth 5 (or (file-attributes file) '(nil nil nil nil nil)))))
- (if (and scanning scantime
- (eq (car scantime) (car modtime))
- (eq (cdr scantime) (cadr modtime)))
- nil
- (save-excursion
- (nnfolder-possibly-activate-groups nil)
- ;; Read in the file.
- (set-buffer (setq nnfolder-current-buffer
- (nnheader-find-file-noselect file nil 'raw)))
- (buffer-disable-undo (current-buffer))
- ;; If the file hasn't been touched since the last time we scanned it,
- ;; don't bother doing anything with it.
- (let ((delim (concat "^" message-unix-mail-delimiter))
- (marker (concat "\n" nnfolder-article-marker))
- (number "[0-9]+")
- (active (or (cadr (assoc nnfolder-current-group
- nnfolder-group-alist))
- (cons 1 0)))
- (scantime (assoc nnfolder-current-group nnfolder-scantime-alist))
- (minid (lsh -1 -1))
- maxid start end newscantime)
-
- (setq maxid (or (cdr active) 0))
- (goto-char (point-min))
-
- ;; Anytime the active number is 1 or 0, it is suspect. In that
- ;; case, search the file manually to find the active number. Or,
- ;; of course, if we're being paranoid. (This would also be the
- ;; place to build other lists from the header markers, such as
- ;; expunge lists, etc., if we ever desired to abandon the active
- ;; file entirely for mboxes.)
- (when (or nnfolder-ignore-active-file
- (< maxid 2))
- (while (and (search-forward marker nil t)
- (re-search-forward number nil t))
- (let ((newnum (string-to-number (match-string 0))))
- (setq maxid (max maxid newnum))
- (setq minid (min minid newnum))))
- (setcar active (max 1 (min minid maxid)))
- (setcdr active (max maxid (cdr active)))
- (goto-char (point-min)))
-
- ;; As long as we trust that the user will only insert unmarked mail
- ;; at the end, go to the end and search backwards for the last
- ;; marker. Find the start of that message, and begin to search for
- ;; unmarked messages from there.
- (if (not (or nnfolder-distrust-mbox
- (< maxid 2)))
- (progn
- (goto-char (point-max))
- (if (not (re-search-backward marker nil t))
- (goto-char (point-min))
- (if (not (re-search-backward delim nil t))
- (goto-char (point-min))))))
-
- ;; Keep track of the active number on our own, and insert it back
- ;; into the active list when we're done. Also, prime the pump to
- ;; cut down on the number of searches we do.
- (setq end (point-marker))
- (set-marker end (or (and (re-search-forward delim nil t)
- (match-beginning 0))
- (point-max)))
- (while (not (= end (point-max)))
- (setq start (marker-position end))
- (goto-char end)
- ;; There may be more than one "From " line, so we skip past
- ;; them.
- (while (looking-at delim)
- (forward-line 1))
- (set-marker end (or (and (re-search-forward delim nil t)
- (match-beginning 0))
- (point-max)))
- (goto-char start)
- (if (not (search-forward marker end t))
- (progn
- (narrow-to-region start end)
- (nnmail-insert-lines)
- (nnfolder-insert-newsgroup-line
- (cons nil (nnfolder-active-number nnfolder-current-group)))
- (widen))))
-
- ;; Make absolutely sure that the active list reflects reality!
- (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
- ;; Set the scantime for this group.
- (setq newscantime (visited-file-modtime))
- (if scantime
- (setcdr scantime (list newscantime))
- (push (list nnfolder-current-group newscantime)
- nnfolder-scantime-alist))
- (current-buffer))))))
-
-;;;###autoload
-(defun nnfolder-generate-active-file ()
- "Look for mbox folders in the nnfolder directory and make them into groups."
- (interactive)
- (nnmail-activate 'nnfolder)
- (let ((files (directory-files nnfolder-directory))
- file)
- (while (setq file (pop files))
- (when (and (not (backup-file-name-p file))
- (nnheader-mail-file-mbox-p file))
- (nnheader-message 5 "Adding group %s..." file)
- (push (list file (cons 1 0)) nnfolder-group-alist)
- (nnfolder-possibly-change-group file)
-;; (nnfolder-read-folder file)
- (nnfolder-close-group file))
- (message ""))))
-
-(defun nnfolder-group-pathname (group)
- "Make pathname for GROUP."
- (let ((dir (file-name-as-directory (expand-file-name nnfolder-directory))))
- ;; If this file exists, we use it directly.
- (if (or nnmail-use-long-file-names
- (file-exists-p (concat dir group)))
- (concat dir group)
- ;; If not, we translate dots into slashes.
- (concat dir (nnheader-replace-chars-in-string group ?. ?/)))))
-
-(defun nnfolder-save-buffer ()
- "Save the buffer."
- (when (buffer-modified-p)
- (run-hooks 'nnfolder-save-buffer-hook)
- (save-buffer)))
-
-(provide 'nnfolder)
-
-;;; nnfolder.el ends here
diff --git a/lisp/nnheader.el b/lisp/nnheader.el
deleted file mode 100644
index 1c93816dfb6..00000000000
--- a/lisp/nnheader.el
+++ /dev/null
@@ -1,620 +0,0 @@
-;;; nnheader.el --- header access macros for Gnus and its backends
-;; Copyright (C) 1987,88,89,90,93,94,95,96 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; These macros may look very much like the ones in GNUS 4.1. They
-;; are, in a way, but you should note that the indices they use have
-;; been changed from the internal GNUS format to the NOV format. The
-;; makes it possible to read headers from XOVER much faster.
-;;
-;; The format of a header is now:
-;; [number subject from date id references chars lines xref]
-;;
-;; (That last entry is defined as "misc" in the NOV format, but Gnus
-;; uses it for xrefs.)
-
-;;; Code:
-
-(require 'mail-utils)
-(eval-when-compile (require 'cl))
-
-(defvar nnheader-max-head-length 4096
- "*Max length of the head of articles.")
-
-(defvar nnheader-file-name-translation-alist nil
- "*Alist that says how to translate characters in file names.
-For instance, if \":\" is illegal as a file character in file names
-on your system, you could say something like:
-
-\(setq nnheader-file-name-translation-alist '((?: . ?_)))")
-
-;;; Header access macros.
-
-(defmacro mail-header-number (header)
- "Return article number in HEADER."
- `(aref ,header 0))
-
-(defmacro mail-header-set-number (header number)
- "Set article number of HEADER to NUMBER."
- `(aset ,header 0 ,number))
-
-(defmacro mail-header-subject (header)
- "Return subject string in HEADER."
- `(aref ,header 1))
-
-(defmacro mail-header-set-subject (header subject)
- "Set article subject of HEADER to SUBJECT."
- `(aset ,header 1 ,subject))
-
-(defmacro mail-header-from (header)
- "Return author string in HEADER."
- `(aref ,header 2))
-
-(defmacro mail-header-set-from (header from)
- "Set article author of HEADER to FROM."
- `(aset ,header 2 ,from))
-
-(defmacro mail-header-date (header)
- "Return date in HEADER."
- `(aref ,header 3))
-
-(defmacro mail-header-set-date (header date)
- "Set article date of HEADER to DATE."
- `(aset ,header 3 ,date))
-
-(defalias 'mail-header-message-id 'mail-header-id)
-(defmacro mail-header-id (header)
- "Return Id in HEADER."
- `(aref ,header 4))
-
-(defalias 'mail-header-set-message-id 'mail-header-set-id)
-(defmacro mail-header-set-id (header id)
- "Set article Id of HEADER to ID."
- `(aset ,header 4 ,id))
-
-(defmacro mail-header-references (header)
- "Return references in HEADER."
- `(aref ,header 5))
-
-(defmacro mail-header-set-references (header ref)
- "Set article references of HEADER to REF."
- `(aset ,header 5 ,ref))
-
-(defmacro mail-header-chars (header)
- "Return number of chars of article in HEADER."
- `(aref ,header 6))
-
-(defmacro mail-header-set-chars (header chars)
- "Set number of chars in article of HEADER to CHARS."
- `(aset ,header 6 ,chars))
-
-(defmacro mail-header-lines (header)
- "Return lines in HEADER."
- `(aref ,header 7))
-
-(defmacro mail-header-set-lines (header lines)
- "Set article lines of HEADER to LINES."
- `(aset ,header 7 ,lines))
-
-(defmacro mail-header-xref (header)
- "Return xref string in HEADER."
- `(aref ,header 8))
-
-(defmacro mail-header-set-xref (header xref)
- "Set article xref of HEADER to xref."
- `(aset ,header 8 ,xref))
-
-(defun make-mail-header (&optional init)
- "Create a new mail header structure initialized with INIT."
- (make-vector 9 init))
-
-;; Parsing headers and NOV lines.
-
-(defsubst nnheader-header-value ()
- (buffer-substring (match-end 0) (gnus-point-at-eol)))
-
-(defvar nnheader-newsgroup-none-id 1)
-
-(defun nnheader-parse-head (&optional naked)
- (let ((case-fold-search t)
- (cur (current-buffer))
- (buffer-read-only nil)
- end ref in-reply-to lines p)
- (goto-char (point-min))
- (when naked
- (insert "\n"))
- ;; Search to the beginning of the next header. Error messages
- ;; do not begin with 2 or 3.
- (prog1
- (when (or naked (re-search-forward "^[23][0-9]+ " nil t))
- ;; This implementation of this function, with nine
- ;; search-forwards instead of the one re-search-forward and
- ;; a case (which basically was the old function) is actually
- ;; about twice as fast, even though it looks messier. You
- ;; can't have everything, I guess. Speed and elegance
- ;; doesn't always go hand in hand.
- (vector
- ;; Number.
- (if naked
- (progn
- (setq p (point-min))
- 0)
- (prog1
- (read cur)
- (end-of-line)
- (setq p (point))
- (narrow-to-region (point)
- (or (and (search-forward "\n.\n" nil t)
- (- (point) 2))
- (point)))))
- ;; Subject.
- (progn
- (goto-char p)
- (if (search-forward "\nsubject: " nil t)
- (nnheader-header-value) "(none)"))
- ;; From.
- (progn
- (goto-char p)
- (if (search-forward "\nfrom: " nil t)
- (nnheader-header-value) "(nobody)"))
- ;; Date.
- (progn
- (goto-char p)
- (if (search-forward "\ndate: " nil t)
- (nnheader-header-value) ""))
- ;; Message-ID.
- (progn
- (goto-char p)
- (if (search-forward "\nmessage-id: " nil t)
- (nnheader-header-value)
- ;; If there was no message-id, we just fake one to make
- ;; subsequent routines simpler.
- (concat "none+"
- (int-to-string
- (incf nnheader-newsgroup-none-id)))))
- ;; References.
- (progn
- (goto-char p)
- (if (search-forward "\nreferences: " nil t)
- (nnheader-header-value)
- ;; Get the references from the in-reply-to header if there
- ;; were no references and the in-reply-to header looks
- ;; promising.
- (if (and (search-forward "\nin-reply-to: " nil t)
- (setq in-reply-to (nnheader-header-value))
- (string-match "<[^>]+>" in-reply-to))
- (substring in-reply-to (match-beginning 0)
- (match-end 0))
- "")))
- ;; Chars.
- 0
- ;; Lines.
- (progn
- (goto-char p)
- (if (search-forward "\nlines: " nil t)
- (if (numberp (setq lines (read cur)))
- lines 0)
- 0))
- ;; Xref.
- (progn
- (goto-char p)
- (and (search-forward "\nxref: " nil t)
- (nnheader-header-value)))))
- (when naked
- (goto-char (point-min))
- (delete-char 1)))))
-
-(defun nnheader-insert-nov (header)
- (princ (mail-header-number header) (current-buffer))
- (insert
- "\t"
- (or (mail-header-subject header) "(none)") "\t"
- (or (mail-header-from header) "(nobody)") "\t"
- (or (mail-header-date header) "") "\t"
- (or (mail-header-id header)
- (nnmail-message-id)) "\t"
- (or (mail-header-references header) "") "\t")
- (princ (or (mail-header-chars header) 0) (current-buffer))
- (insert "\t")
- (princ (or (mail-header-lines header) 0) (current-buffer))
- (insert "\t")
- (when (mail-header-xref header)
- (insert "Xref: " (mail-header-xref header) "\t"))
- (insert "\n"))
-
-(defun nnheader-insert-article-line (article)
- (goto-char (point-min))
- (insert "220 ")
- (princ article (current-buffer))
- (insert " Article retrieved.\n")
- (search-forward "\n\n" nil 'move)
- (delete-region (point) (point-max))
- (forward-char -1)
- (insert "."))
-
-;; Various cruft the backends and Gnus need to communicate.
-
-(defvar nntp-server-buffer nil)
-(defvar gnus-verbose-backends 7
- "*A number that says how talkative the Gnus backends should be.")
-(defvar gnus-nov-is-evil nil
- "If non-nil, Gnus backends will never output headers in the NOV format.")
-(defvar news-reply-yank-from nil)
-(defvar news-reply-yank-message-id nil)
-
-(defvar nnheader-callback-function nil)
-
-(defun nnheader-init-server-buffer ()
- "Initialize the Gnus-backend communication buffer."
- (save-excursion
- (setq nntp-server-buffer (get-buffer-create " *nntpd*"))
- (set-buffer nntp-server-buffer)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (kill-all-local-variables)
- (setq case-fold-search t) ;Should ignore case.
- t))
-
-
-;;; Various functions the backends use.
-
-(defun nnheader-file-error (file)
- "Return a string that says what is wrong with FILE."
- (format
- (cond
- ((not (file-exists-p file))
- "%s does not exist")
- ((file-directory-p file)
- "%s is a directory")
- ((not (file-readable-p file))
- "%s is not readable"))
- file))
-
-(defun nnheader-insert-head (file)
- "Insert the head of the article."
- (when (file-exists-p file)
- (if (eq nnheader-max-head-length t)
- ;; Just read the entire file.
- (nnheader-insert-file-contents-literally file)
- ;; Read 1K blocks until we find a separator.
- (let ((beg 0)
- format-alist
- (chop 1024))
- (while (and (eq chop (nth 1 (insert-file-contents
- file nil beg (incf beg chop))))
- (prog1 (not (search-forward "\n\n" nil t))
- (goto-char (point-max)))
- (or (null nnheader-max-head-length)
- (< beg nnheader-max-head-length))))))
- t))
-
-(defun nnheader-article-p ()
- "Say whether the current buffer looks like an article."
- (goto-char (point-min))
- (if (not (search-forward "\n\n" nil t))
- nil
- (narrow-to-region (point-min) (1- (point)))
- (goto-char (point-min))
- (while (looking-at "[A-Z][^ \t]+:.*\n\\([ \t].*\n\\)*\\|From .*\n")
- (goto-char (match-end 0)))
- (prog1
- (eobp)
- (widen))))
-
-(defun nnheader-insert-references (references message-id)
- "Insert a References header based on REFERENCES and MESSAGE-ID."
- (if (and (not references) (not message-id))
- () ; This is illegal, but not all articles have Message-IDs.
- (mail-position-on-field "References")
- (let ((begin (save-excursion (beginning-of-line) (point)))
- (fill-column 78)
- (fill-prefix "\t"))
- (if references (insert references))
- (if (and references message-id) (insert " "))
- (if message-id (insert message-id))
- ;; Fold long References lines to conform to RFC1036 (sort of).
- ;; The region must end with a newline to fill the region
- ;; without inserting extra newline.
- (fill-region-as-paragraph begin (1+ (point))))))
-
-(defun nnheader-replace-header (header new-value)
- "Remove HEADER and insert the NEW-VALUE."
- (save-excursion
- (save-restriction
- (nnheader-narrow-to-headers)
- (prog1
- (message-remove-header header)
- (goto-char (point-max))
- (insert header ": " new-value "\n")))))
-
-(defun nnheader-narrow-to-headers ()
- "Narrow to the head of an article."
- (widen)
- (narrow-to-region
- (goto-char (point-min))
- (if (search-forward "\n\n" nil t)
- (1- (point))
- (point-max)))
- (goto-char (point-min)))
-
-(defun nnheader-set-temp-buffer (name)
- "Set-buffer to an empty (possibly new) buffer called NAME with undo disabled."
- (set-buffer (get-buffer-create name))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (current-buffer))
-
-(defmacro nnheader-temp-write (file &rest forms)
- "Create a new buffer, evaluate FORM there, and write the buffer to FILE."
- `(save-excursion
- (let ((nnheader-temp-file ,file)
- (nnheader-temp-cur-buffer
- (nnheader-set-temp-buffer
- (generate-new-buffer-name " *nnheader temp*"))))
- (when (and nnheader-temp-file
- (not (file-directory-p (file-name-directory
- nnheader-temp-file))))
- (make-directory (file-name-directory nnheader-temp-file) t))
- (unwind-protect
- (prog1
- (progn
- ,@forms)
- (when nnheader-temp-file
- (set-buffer nnheader-temp-cur-buffer)
- (write-region (point-min) (point-max)
- nnheader-temp-file nil 'nomesg)))
- (when (buffer-name nnheader-temp-cur-buffer)
- (kill-buffer nnheader-temp-cur-buffer))))))
-
-(put 'nnheader-temp-write 'lisp-indent-function 1)
-(put 'nnheader-temp-write 'lisp-indent-hook 1)
-(put 'nnheader-temp-write 'edebug-form-spec '(form body))
-
-(defvar jka-compr-compression-info-list)
-(defvar nnheader-numerical-files
- (if (boundp 'jka-compr-compression-info-list)
- (concat "\\([0-9]+\\)\\("
- (mapconcat (lambda (i) (aref i 0))
- jka-compr-compression-info-list "\\|")
- "\\)?")
- "[0-9]+$")
- "Regexp that match numerical files.")
-
-(defvar nnheader-numerical-short-files (concat "^" nnheader-numerical-files)
- "Regexp that matches numerical file names.")
-
-(defvar nnheader-numerical-full-files (concat "/" nnheader-numerical-files)
- "Regexp that matches numerical full file paths.")
-
-(defsubst nnheader-file-to-number (file)
- "Take a file name and return the article number."
- (if (not (boundp 'jka-compr-compression-info-list))
- (string-to-int file)
- (string-match nnheader-numerical-short-files file)
- (string-to-int (match-string 0 file))))
-
-(defun nnheader-directory-files-safe (&rest args)
- ;; It has been reported numerous times that `directory-files'
- ;; fails with an alarming frequency on NFS mounted file systems.
- ;; This function executes that function twice and returns
- ;; the longest result.
- (let ((first (apply 'directory-files args))
- (second (apply 'directory-files args)))
- (if (> (length first) (length second))
- first
- second)))
-
-(defun nnheader-directory-articles (dir)
- "Return a list of all article files in a directory."
- (mapcar 'nnheader-file-to-number
- (nnheader-directory-files-safe
- dir nil nnheader-numerical-short-files t)))
-
-(defun nnheader-article-to-file-alist (dir)
- "Return an alist of article/file pairs in DIR."
- (mapcar (lambda (file) (cons (nnheader-file-to-number file) file))
- (nnheader-directory-files-safe
- dir nil nnheader-numerical-short-files t)))
-
-(defun nnheader-fold-continuation-lines ()
- "Fold continuation lines in the current buffer."
- (goto-char (point-min))
- (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
- (replace-match " " t t)))
-
-(defun nnheader-translate-file-chars (file)
- (if (null nnheader-file-name-translation-alist)
- ;; No translation is necessary.
- file
- ;; We translate -- but only the file name. We leave the directory
- ;; alone.
- (let* ((i 0)
- trans leaf path len)
- (if (string-match "/[^/]+\\'" file)
- ;; This is needed on NT's and stuff.
- (setq leaf (substring file (1+ (match-beginning 0)))
- path (substring file 0 (1+ (match-beginning 0))))
- ;; Fall back on this.
- (setq leaf (file-name-nondirectory file)
- path (file-name-directory file)))
- (setq len (length leaf))
- (while (< i len)
- (when (setq trans (cdr (assq (aref leaf i)
- nnheader-file-name-translation-alist)))
- (aset leaf i trans))
- (incf i))
- (concat path leaf))))
-
-(defun nnheader-report (backend &rest args)
- "Report an error from the BACKEND.
-The first string in ARGS can be a format string."
- (set (intern (format "%s-status-string" backend))
- (if (< (length args) 2)
- (car args)
- (apply 'format args)))
- nil)
-
-(defun nnheader-get-report (backend)
- (message "%s" (symbol-value (intern (format "%s-status-string" backend)))))
-
-(defun nnheader-insert (format &rest args)
- "Clear the communicaton buffer and insert FORMAT and ARGS into the buffer.
-If FORMAT isn't a format string, it and all ARGS will be inserted
-without formatting."
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (if (string-match "%" format)
- (insert (apply 'format format args))
- (apply 'insert format args))
- t))
-
-(defun nnheader-mail-file-mbox-p (file)
- "Say whether FILE looks like an Unix mbox file."
- (when (and (file-exists-p file)
- (file-readable-p file)
- (file-regular-p file))
- (save-excursion
- (nnheader-set-temp-buffer " *mail-file-mbox-p*")
- (nnheader-insert-file-contents-literally file)
- (goto-char (point-min))
- (prog1
- (looking-at message-unix-mail-delimiter)
- (kill-buffer (current-buffer))))))
-
-(defun nnheader-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 occurrences of FROM with TO.
- (while (< idx len)
- (if (= (aref string idx) from)
- (aset string idx to))
- (setq idx (1+ idx)))
- string))
-
-(defun nnheader-file-to-group (file &optional top)
- "Return a group name based on FILE and TOP."
- (nnheader-replace-chars-in-string
- (if (not top)
- file
- (condition-case ()
- (substring (expand-file-name file)
- (length
- (expand-file-name
- (file-name-as-directory top))))
- (error "")))
- ?/ ?.))
-
-(defun nnheader-message (level &rest args)
- "Message if the Gnus backends are talkative."
- (if (or (not (numberp gnus-verbose-backends))
- (<= level gnus-verbose-backends))
- (apply 'message args)
- (apply 'format args)))
-
-(defun nnheader-be-verbose (level)
- "Return whether the backends should be verbose on LEVEL."
- (or (not (numberp gnus-verbose-backends))
- (<= level gnus-verbose-backends)))
-
-(defun nnheader-group-pathname (group dir &optional file)
- "Make pathname for GROUP."
- (concat
- (let ((dir (file-name-as-directory (expand-file-name dir))))
- ;; If this directory exists, we use it directly.
- (if (file-directory-p (concat dir group))
- (concat dir group "/")
- ;; If not, we translate dots into slashes.
- (concat dir (nnheader-replace-chars-in-string group ?. ?/) "/")))
- (cond ((null file) "")
- ((numberp file) (int-to-string file))
- (t file))))
-
-(defun nnheader-functionp (form)
- "Return non-nil if FORM is funcallable."
- (or (and (symbolp form) (fboundp form))
- (and (listp form) (eq (car form) 'lambda))))
-
-(defun nnheader-concat (dir file)
- "Concat DIR as directory to FILE."
- (concat (file-name-as-directory dir) file))
-
-(defun nnheader-ms-strip-cr ()
- "Strip ^M from the end of all lines."
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward "\r$" nil t)
- (delete-backward-char 1))))
-
-(defun nnheader-file-size (file)
- "Return the file size of FILE or 0."
- (or (nth 7 (file-attributes file)) 0))
-
-(defun nnheader-find-etc-directory (package)
- "Go through the path and find the \".../etc/PACKAGE\" directory."
- (let ((path load-path)
- dir result)
- ;; We try to find the dir by looking at the load path,
- ;; stripping away the last component and adding "etc/".
- (while path
- (if (and (car path)
- (file-exists-p
- (setq dir (concat
- (file-name-directory
- (directory-file-name (car path)))
- "etc/" package "/")))
- (file-directory-p dir))
- (setq result dir
- path nil)
- (setq path (cdr path))))
- result))
-
-(defvar ange-ftp-path-format)
-(defvar efs-path-regexp)
-(defun nnheader-re-read-dir (path)
- "Re-read directory PATH if PATH is on a remote system."
- (if (boundp 'ange-ftp-path-format)
- (when (string-match (car ange-ftp-path-format) path)
- (ange-ftp-re-read-dir path))
- (if (boundp 'efs-path-regexp)
- (when (string-match efs-path-regexp path)
- (efs-re-read-dir path)))))
-
-(fset 'nnheader-run-at-time 'run-at-time)
-(fset 'nnheader-cancel-timer 'cancel-timer)
-(fset 'nnheader-find-file-noselect 'find-file-noselect)
-(fset 'nnheader-insert-file-contents-literally
- 'insert-file-contents-literally)
-
-(when (string-match "XEmacs\\|Lucid" emacs-version)
- (require 'nnheaderxm))
-
-(run-hooks 'nnheader-load-hook)
-
-(provide 'nnheader)
-
-;;; nnheader.el ends here
diff --git a/lisp/nnheaderems.el b/lisp/nnheaderems.el
deleted file mode 100644
index 14ce490bb17..00000000000
--- a/lisp/nnheaderems.el
+++ /dev/null
@@ -1,201 +0,0 @@
-;;; nnheaderems.el --- making Gnus backends work under different Emacsen
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(defun nnheader-xmas-run-at-time (time repeat function &rest args)
- (start-itimer
- "nnheader-run-at-time"
- `(lambda ()
- (,function ,@args))
- time repeat))
-
-(defun nnheader-xmas-cancel-timer (timer)
- (delete-itimer timer))
-
-;; Written by Erik Naggum <erik@naggum.no>.
-;; Saved by Steve Baur <steve@miranova.com>.
-(defun nnheader-xmas-insert-file-contents-literally (filename &optional visit beg end replace)
- "Like `insert-file-contents', q.v., but only reads in the file.
-A buffer may be modified in several ways after reading into the buffer due
-to advanced Emacs features, such as file-name-handlers, format decoding,
-find-file-hooks, etc.
- This function ensures that none of these modifications will take place."
- (let ( ; (file-name-handler-alist nil)
- (format-alist nil)
- (after-insert-file-functions nil)
- (find-buffer-file-type-function
- (if (fboundp 'find-buffer-file-type)
- (symbol-function 'find-buffer-file-type)
- nil)))
- (unwind-protect
- (progn
- (fset 'find-buffer-file-type (lambda (filename) t))
- (insert-file-contents filename visit beg end replace))
- (if find-buffer-file-type-function
- (fset 'find-buffer-file-type find-buffer-file-type-function)
- (fmakunbound 'find-buffer-file-type)))))
-
-(defun nnheader-xmas-find-file-noselect (filename &optional nowarn rawfile)
- "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
- (abbreviate-file-name
- (expand-file-name filename)))
- (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))
- (truename (abbreviate-file-name (file-truename filename)))
- (number (nthcdr 10 (file-attributes truename)))
- ;; Find any buffer for a file which has same truename.
- (other (and (not buf)
- (if (fboundp 'find-buffer-visiting)
- (find-buffer-visiting filename)
- (get-file-buffer filename))))
- error)
- ;; Let user know if there is a buffer with the same truename.
- (if other
- (progn
- (or nowarn
- (string-equal filename (buffer-file-name other))
- (message "%s and %s are the same file"
- filename (buffer-file-name other)))
- ;; Optionally also find that buffer.
- (if (or (and (boundp 'find-file-existing-other-name)
- find-file-existing-other-name)
- find-file-visit-truename)
- (setq buf other))))
- (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 (string= (file-name-nondirectory filename)
- (buffer-name buf))
- (format
- (if (buffer-modified-p buf)
- "File %s changed on disk. Discard your edits? "
- "File %s changed on disk. Reread from disk? ")
- (file-name-nondirectory filename))
- (format
- (if (buffer-modified-p buf)
- "File %s changed on disk. Discard your edits in %s? "
- "File %s changed on disk. Reread from disk into %s? ")
- (file-name-nondirectory filename)
- (buffer-name buf))))
- (save-excursion
- (set-buffer buf)
- (revert-buffer t t)))))
- (save-excursion
-;;; The truename stuff makes this obsolete.
-;;; (let* ((link-name (car (file-attributes filename)))
-;;; (linked-buf (and (stringp link-name)
-;;; (get-file-buffer link-name))))
-;;; (if (bufferp linked-buf)
-;;; (message "Symbolic link to file in buffer %s"
-;;; (buffer-name linked-buf))))
- (setq buf (create-file-buffer filename))
- ;; (set-buffer-major-mode buf)
- (set-buffer buf)
- (erase-buffer)
- (if rawfile
- (condition-case ()
- (nnheader-insert-file-contents-literally filename t)
- (file-error
- ;; Unconditionally set error
- (setq error t)))
- (condition-case ()
- (insert-file-contents filename t)
- (file-error
- ;; Run find-file-not-found-hooks until one returns non-nil.
- (or t ; (run-hook-with-args-until-success 'find-file-not-found-hooks)
- ;; If they fail too, set error.
- (setq error t)))))
- ;; Find the file's truename, and maybe use that as visited name.
- (setq buffer-file-truename truename)
- (setq buffer-file-number number)
- ;; On VMS, we may want to remember which directory in a search list
- ;; the file was found in.
- (and (eq system-type 'vax-vms)
- (let (logical)
- (if (string-match ":" (file-name-directory filename))
- (setq logical (substring (file-name-directory filename)
- 0 (match-beginning 0))))
- (not (member logical find-file-not-true-dirname-list)))
- (setq buffer-file-name buffer-file-truename))
- (if find-file-visit-truename
- (setq buffer-file-name
- (setq filename
- (expand-file-name buffer-file-truename))))
- ;; Set buffer's default directory to that of the file.
- (setq default-directory (file-name-directory filename))
- ;; Turn off backup files for certain file names. Since
- ;; this is a permanent local, the major mode won't eliminate it.
- (and (not (funcall backup-enable-predicate buffer-file-name))
- (progn
- (make-local-variable 'backup-inhibited)
- (setq backup-inhibited t)))
- (if rawfile
- nil
- (after-find-file error (not nowarn)))))
- buf)))
-
-(defun nnheader-ms-strip-cr ()
- "Strip ^M from the end of all lines."
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward "\r$" nil t)
- (delete-backward-char 1))))
-
-(eval-and-compile
- (cond
- ;; Do XEmacs function bindings.
- ((string-match "XEmacs\\|Lucid" emacs-version)
- (fset 'nnheader-run-at-time 'nnheader-xmas-run-at-time)
- (fset 'nnheader-cancel-timer 'nnheader-xmas-cancel-timer)
- (fset 'nnheader-find-file-noselect 'nnheader-xmas-find-file-noselect)
- (fset 'nnheader-insert-file-contents-literally
- (if (fboundp 'insert-file-contents-literally)
- 'insert-file-contents-literally
- 'nnheader-xmas-insert-file-contents-literally)))
- ;; Do Emacs function bindings.
- (t
- (fset 'nnheader-run-at-time 'run-at-time)
- (fset 'nnheader-cancel-timer 'cancel-timer)
- (fset 'nnheader-find-file-noselect 'find-file-noselect)
- (fset 'nnheader-insert-file-contents-literally
- 'insert-file-contents-literally)
- ))
- (when (memq system-type '(windows-nt))
- (add-hook 'nnmail-prepare-incoming-hook 'nnheader-ms-strip-cr)))
-
-(provide 'nnheaderems)
-
-;;; nnheaderems.el ends here.
diff --git a/lisp/nnkiboze.el b/lisp/nnkiboze.el
deleted file mode 100644
index b314d58d1a9..00000000000
--- a/lisp/nnkiboze.el
+++ /dev/null
@@ -1,388 +0,0 @@
-;;; nnkiboze.el --- select virtual news access for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The other access methods (nntp, nnspool, etc) are general news
-;; access methods. This module relies on Gnus and can not be used
-;; separately.
-
-;;; Code:
-
-(require 'nntp)
-(require 'nnheader)
-(require 'gnus)
-(require 'gnus-score)
-(require 'nnoo)
-(eval-when-compile (require 'cl))
-
-(nnoo-declare nnkiboze)
-(defvoo nnkiboze-directory gnus-directory
- "nnkiboze will put its files in this directory.")
-
-(defvoo nnkiboze-level 9
- "*The maximum level to be searched for articles.")
-
-(defvoo nnkiboze-remove-read-articles t
- "*If non-nil, nnkiboze will remove read articles from the kiboze group.")
-
-
-
-(defconst nnkiboze-version "nnkiboze 1.0"
- "Version numbers of this version of nnkiboze.")
-
-(defvoo nnkiboze-current-group nil)
-(defvoo nnkiboze-current-score-group "")
-(defvoo nnkiboze-status-string "")
-
-
-
-;;; Interface functions.
-
-(nnoo-define-basics nnkiboze)
-
-(deffoo nnkiboze-retrieve-headers (articles &optional group server fetch-old)
- (nnkiboze-possibly-change-newsgroups group)
- (if gnus-nov-is-evil
- nil
- (if (stringp (car articles))
- 'headers
- (let ((first (car articles))
- (last (progn (while (cdr articles) (setq articles (cdr articles)))
- (car articles)))
- (nov (nnkiboze-nov-file-name)))
- (if (file-exists-p nov)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (insert-file-contents nov)
- (goto-char (point-min))
- (while (and (not (eobp)) (< first (read (current-buffer))))
- (forward-line 1))
- (beginning-of-line)
- (if (not (eobp)) (delete-region 1 (point)))
- (while (and (not (eobp)) (>= last (read (current-buffer))))
- (forward-line 1))
- (beginning-of-line)
- (if (not (eobp)) (delete-region (point) (point-max)))
- 'nov))))))
-
-(deffoo nnkiboze-open-server (newsgroups &optional something)
- (gnus-make-directory nnkiboze-directory)
- (nnheader-init-server-buffer))
-
-(deffoo nnkiboze-server-opened (&optional server)
- (and nntp-server-buffer
- (get-buffer nntp-server-buffer)))
-
-(deffoo nnkiboze-request-article (article &optional newsgroup server buffer)
- (nnkiboze-possibly-change-newsgroups newsgroup)
- (if (not (numberp article))
- ;; This is a real kludge. It might not work at times, but it
- ;; does no harm I think. The only alternative is to offer no
- ;; article fetching by message-id at all.
- (nntp-request-article article newsgroup gnus-nntp-server buffer)
- (let* ((header (gnus-summary-article-header article))
- (xref (mail-header-xref header))
- igroup iarticle)
- (or xref (error "nnkiboze: No xref"))
- (or (string-match " \\([^ ]+\\):\\([0-9]+\\)" xref)
- (error "nnkiboze: Malformed xref"))
- (setq igroup (substring xref (match-beginning 1) (match-end 1)))
- (setq iarticle (string-to-int
- (substring xref (match-beginning 2) (match-end 2))))
- (and (gnus-request-group igroup t)
- (gnus-request-article iarticle igroup buffer)))))
-
-(deffoo nnkiboze-request-group (group &optional server dont-check)
- "Make GROUP the current newsgroup."
- (nnkiboze-possibly-change-newsgroups group)
- (if dont-check
- ()
- (let ((nov-file (nnkiboze-nov-file-name))
- beg end total)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (if (not (file-exists-p nov-file))
- (insert (format "211 0 0 0 %s\n" group))
- (insert-file-contents nov-file)
- (if (zerop (buffer-size))
- (insert (format "211 0 0 0 %s\n" group))
- (goto-char (point-min))
- (and (looking-at "[0-9]+") (setq beg (read (current-buffer))))
- (goto-char (point-max))
- (and (re-search-backward "^[0-9]" nil t)
- (setq end (read (current-buffer))))
- (setq total (count-lines (point-min) (point-max)))
- (erase-buffer)
- (insert (format "211 %d %d %d %s\n" total beg end group)))))))
- t)
-
-(deffoo nnkiboze-close-group (group &optional server)
- (nnkiboze-possibly-change-newsgroups group)
- ;; Remove NOV lines of articles that are marked as read.
- (when (and (file-exists-p (nnkiboze-nov-file-name))
- nnkiboze-remove-read-articles
- (eq major-mode 'gnus-summary-mode))
- (save-excursion
- (let ((unreads gnus-newsgroup-unreads)
- (unselected gnus-newsgroup-unselected)
- (version-control 'never))
- (set-buffer (get-buffer-create "*nnkiboze work*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (let ((cur (current-buffer))
- article)
- (insert-file-contents (nnkiboze-nov-file-name))
- (goto-char (point-min))
- (while (looking-at "[0-9]+")
- (if (or (memq (setq article (read cur)) unreads)
- (memq article unselected))
- (forward-line 1)
- (delete-region (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point)))))
- (write-file (nnkiboze-nov-file-name))
- (kill-buffer (current-buffer)))))
- (setq nnkiboze-current-group nil)))
-
-(deffoo nnkiboze-request-list (&optional server)
- (nnheader-report 'nnkiboze "LIST is not implemented."))
-
-(deffoo nnkiboze-request-newgroups (date &optional server)
- "List new groups."
- (nnheader-report 'nnkiboze "NEWGROUPS is not supported."))
-
-(deffoo nnkiboze-request-list-newsgroups (&optional server)
- (nnheader-report 'nnkiboze "LIST NEWSGROUPS is not implemented."))
-
-(deffoo nnkiboze-request-delete-group (group &optional force server)
- (nnkiboze-possibly-change-newsgroups group)
- (when force
- (let ((files (list (nnkiboze-nov-file-name)
- (concat nnkiboze-directory group ".newsrc")
- (nnkiboze-score-file group))))
- (while files
- (and (file-exists-p (car files))
- (file-writable-p (car files))
- (delete-file (car files)))
- (setq files (cdr files)))))
- (setq nnkiboze-current-group nil))
-
-
-;;; Internal functions.
-
-(defun nnkiboze-possibly-change-newsgroups (group)
- (setq nnkiboze-current-group group))
-
-(defun nnkiboze-prefixed-name (group)
- (gnus-group-prefixed-name group '(nnkiboze "")))
-
-;;;###autoload
-(defun nnkiboze-generate-groups ()
- "Usage: emacs -batch -l nnkiboze -f nnkiboze-generate-groups
-Finds out what articles are to be part of the nnkiboze groups."
- (interactive)
- (let ((nnmail-spool-file nil)
- (gnus-use-dribble-file nil)
- (gnus-read-active-file t)
- (gnus-expert-user t))
- (gnus))
- (let* ((gnus-newsrc-alist (gnus-copy-sequence gnus-newsrc-alist))
- (newsrc gnus-newsrc-alist)
- gnus-newsrc-hashtb)
- (gnus-make-hashtable-from-newsrc-alist)
- ;; We have copied all the newsrc alist info over to local copies
- ;; so that we can mess all we want with these lists.
- (while newsrc
- (if (string-match "nnkiboze" (caar newsrc))
- ;; For each kiboze group, we call this function to generate
- ;; it.
- (nnkiboze-generate-group (caar newsrc)))
- (setq newsrc (cdr newsrc)))))
-
-(defun nnkiboze-score-file (group)
- (list (expand-file-name
- (concat (file-name-as-directory gnus-kill-files-directory)
- (nnheader-translate-file-chars
- (concat nnkiboze-current-score-group
- "." gnus-score-file-suffix))))))
-
-(defun nnkiboze-generate-group (group)
- (let* ((info (nth 2 (gnus-gethash group gnus-newsrc-hashtb)))
- (newsrc-file (concat nnkiboze-directory group ".newsrc"))
- (nov-file (concat nnkiboze-directory group ".nov"))
- (regexp (nth 1 (nth 4 info)))
- (gnus-expert-user t)
- (gnus-large-newsgroup nil)
- (version-control 'never)
- (gnus-score-find-score-files-function 'nnkiboze-score-file)
- gnus-select-group-hook gnus-summary-prepare-hook
- gnus-thread-sort-functions gnus-show-threads
- gnus-visual
- method nnkiboze-newsrc nov-buffer gname newsrc active
- ginfo lowest glevel)
- (setq nnkiboze-current-score-group group)
- (or info (error "No such group: %s" group))
- ;; Load the kiboze newsrc file for this group.
- (and (file-exists-p newsrc-file) (load newsrc-file))
- ;; We also load the nov file for this group.
- (save-excursion
- (set-buffer (setq nov-buffer (find-file-noselect nov-file)))
- (buffer-disable-undo (current-buffer)))
- ;; Go through the active hashtb and add new all groups that match the
- ;; kiboze regexp.
- (mapatoms
- (lambda (group)
- (and (string-match regexp (setq gname (symbol-name group))) ; Match
- (not (assoc gname nnkiboze-newsrc)) ; It isn't registered
- (numberp (car (symbol-value group))) ; It is active
- (or (> nnkiboze-level 7)
- (and (setq glevel (nth 1 (nth 2 (gnus-gethash
- gname gnus-newsrc-hashtb))))
- (>= nnkiboze-level glevel)))
- (not (string-match "^nnkiboze:" gname)) ; Exclude kibozes
- (setq nnkiboze-newsrc
- (cons (cons gname (1- (car (symbol-value group))))
- nnkiboze-newsrc))))
- gnus-active-hashtb)
- ;; `newsrc' is set to the list of groups that possibly are
- ;; component groups to this kiboze group. This list has elements
- ;; on the form `(GROUP . NUMBER)', where NUMBER is the highest
- ;; number that has been kibozed in GROUP in this kiboze group.
- (setq newsrc nnkiboze-newsrc)
- (while newsrc
- (if (not (setq active (gnus-gethash
- (caar newsrc) gnus-active-hashtb)))
- ;; This group isn't active after all, so we remove it from
- ;; the list of component groups.
- (setq nnkiboze-newsrc (delq (car newsrc) nnkiboze-newsrc))
- (setq lowest (cdar newsrc))
- ;; Ok, we have a valid component group, so we jump to it.
- (switch-to-buffer gnus-group-buffer)
- (gnus-group-jump-to-group (caar newsrc))
- ;; We set all list of article marks to nil. Since we operate
- ;; on copies of the real lists, we can destroy anything we
- ;; want here.
- (and (setq ginfo (nth 2 (gnus-gethash (gnus-group-group-name)
- gnus-newsrc-hashtb)))
- (nth 3 ginfo)
- (setcar (nthcdr 3 ginfo) nil))
- ;; We set the list of read articles to be what we expect for
- ;; this kiboze group -- either nil or `(1 . LOWEST)'.
- (and ginfo (setcar (nthcdr 2 ginfo)
- (and (not (= lowest 1)) (cons 1 lowest))))
- (if (not (and (or (not ginfo)
- (> (length (gnus-list-of-unread-articles
- (car ginfo))) 0))
- (progn
- (gnus-group-select-group nil)
- (eq major-mode 'gnus-summary-mode))))
- () ; No unread articles, or we couldn't enter this group.
- ;; We are now in the group where we want to be.
- (setq method (gnus-find-method-for-group gnus-newsgroup-name))
- (and (eq method gnus-select-method) (setq method nil))
- ;; We go through the list of scored articles.
- (while gnus-newsgroup-scored
- (if (> (caar gnus-newsgroup-scored) lowest)
- ;; If it has a good score, then we enter this article
- ;; into the kiboze group.
- (nnkiboze-enter-nov
- nov-buffer
- (gnus-summary-article-header
- (caar gnus-newsgroup-scored))
- (if method
- (gnus-group-prefixed-name gnus-newsgroup-name method)
- gnus-newsgroup-name)))
- (setq gnus-newsgroup-scored (cdr gnus-newsgroup-scored)))
- ;; That's it. We exit this group.
- (gnus-summary-exit-no-update)))
- (setcdr (car newsrc) (car active))
- (setq newsrc (cdr newsrc)))
- ;; We save the nov file.
- (set-buffer nov-buffer)
- (save-buffer)
- (kill-buffer (current-buffer))
- ;; We save the kiboze newsrc for this group.
- (set-buffer (get-buffer-create "*nnkiboze work*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert "(setq nnkiboze-newsrc '" (prin1-to-string nnkiboze-newsrc)
- ")\n")
- (write-file newsrc-file)
- (kill-buffer (current-buffer))
- (switch-to-buffer gnus-group-buffer)
- (gnus-group-list-groups 5 nil)))
-
-(defun nnkiboze-enter-nov (buffer header group)
- (save-excursion
- (set-buffer buffer)
- (goto-char (point-max))
- (let ((xref (mail-header-xref header))
- (prefix (gnus-group-real-prefix group))
- (first t)
- article)
- (if (zerop (forward-line -1))
- (progn
- (setq article (1+ (read (current-buffer))))
- (forward-line 1))
- (setq article 1))
- (insert (int-to-string article) "\t"
- (or (mail-header-subject header) "") "\t"
- (or (mail-header-from header) "") "\t"
- (or (mail-header-date header) "") "\t"
- (or (mail-header-id header) "") "\t"
- (or (mail-header-references header) "") "\t"
- (int-to-string (or (mail-header-chars header) 0)) "\t"
- (int-to-string (or (mail-header-lines header) 0)) "\t")
- (if (or (not xref) (equal "" xref))
- (insert "Xref: " (system-name) " " group ":"
- (int-to-string (mail-header-number header))
- "\t\n")
- (insert (mail-header-xref header) "\t\n")
- (search-backward "\t" nil t)
- (search-backward "\t" nil t)
- (while (re-search-forward
- "[^ ]+:[0-9]+"
- (save-excursion (end-of-line) (point)) t)
- (if first
- ;; The first xref has to be the group this article
- ;; really came for - this is the article nnkiboze
- ;; will request when it is asked for the article.
- (save-excursion
- (goto-char (match-beginning 0))
- (insert prefix group ":"
- (int-to-string (mail-header-number header)) " ")
- (setq first nil)))
- (save-excursion
- (goto-char (match-beginning 0))
- (insert prefix)))))))
-
-(defun nnkiboze-nov-file-name ()
- (concat (file-name-as-directory nnkiboze-directory)
- (nnheader-translate-file-chars
- (concat (nnkiboze-prefixed-name nnkiboze-current-group) ".nov"))))
-
-(provide 'nnkiboze)
-
-;;; nnkiboze.el ends here
diff --git a/lisp/nnmail.el b/lisp/nnmail.el
deleted file mode 100644
index d108d590dad..00000000000
--- a/lisp/nnmail.el
+++ /dev/null
@@ -1,1201 +0,0 @@
-;;; nnmail.el --- mail support functions for the Gnus mail backends
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news, mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'nnheader)
-(require 'timezone)
-(require 'message)
-(eval-when-compile (require 'cl))
-
-(defvar nnmail-split-methods
- '(("mail.misc" ""))
- "*Incoming mail will be split according to this variable.
-
-If you'd like, for instance, one mail group for mail from the
-\"4ad-l\" mailing list, one group for junk mail and one for everything
-else, you could do something like this:
-
- (setq nnmail-split-methods
- '((\"mail.4ad\" \"From:.*4ad\")
- (\"mail.junk\" \"From:.*Lars\\\\|Subject:.*buy\")
- (\"mail.misc\" \"\")))
-
-As you can see, this variable is a list of lists, where the first
-element in each \"rule\" is the name of the group (which, by the way,
-does not have to be called anything beginning with \"mail\",
-\"yonka.zow\" is a fine, fine name), and the second is a regexp that
-nnmail will try to match on the header to find a fit.
-
-The second element can also be a function. In that case, it will be
-called narrowed to the headers with the first element of the rule as
-the argument. It should return a non-nil value if it thinks that the
-mail belongs in that group.
-
-The last element should always have \"\" as the regexp.
-
-This variable can also have a function as its value.")
-
-;; Suggested by Erik Selberg <speed@cs.washington.edu>.
-(defvar nnmail-crosspost t
- "*If non-nil, do crossposting if several split methods match the mail.
-If nil, the first match found will be used.")
-
-;; Added by gord@enci.ucalgary.ca (Gordon Matzigkeit).
-(defvar nnmail-keep-last-article nil
- "*If non-nil, nnmail will never delete the last expired article in a directory.
-You may need to set this variable if other programs are putting
-new mail into folder numbers that Gnus has marked as expired.")
-
-(defvar nnmail-use-long-file-names nil
- "*If non-nil the mail backends will use long file and directory names.
-If nil, groups like \"mail.misc\" will end up in directories like
-\"mail/misc/\".")
-
-(defvar nnmail-expiry-wait 7
- "*Expirable articles that are older than this will be expired.
-This variable can either be a number (which will be interpreted as a
-number of days) -- this doesn't have to be an integer. This variable
-can also be `immediate' and `never'.")
-
-(defvar nnmail-expiry-wait-function nil
- "*Variable that holds function to specify how old articles should be before they are expired.
- The function will be called with the name of the group that the
-expiry is to be performed in, and it should return an integer that
-says how many days an article can be stored before it is considered
-\"old\". It can also return the values `never' and `immediate'.
-
-Eg.:
-
-(setq nnmail-expiry-wait-function
- (lambda (newsgroup)
- (cond ((string-match \"private\" newsgroup) 31)
- ((string-match \"junk\" newsgroup) 1)
- ((string-match \"important\" newsgroup) 'never)
- (t 7))))")
-
-(defvar nnmail-spool-file
- (or (getenv "MAIL")
- (concat "/usr/spool/mail/" (user-login-name)))
- "Where the mail backends will look for incoming mail.
-This variable is \"/usr/spool/mail/$user\" by default.
-If this variable is nil, no mail backends will read incoming mail.
-If this variable is a list, all files mentioned in this list will be
-used as incoming mailboxes.")
-
-(defvar nnmail-crash-box "~/.gnus-crash-box"
- "*File where Gnus will store mail while processing it.")
-
-(defvar nnmail-use-procmail nil
- "*If non-nil, the mail backends will look in `nnmail-procmail-directory' for spool files.
-The file(s) in `nnmail-spool-file' will also be read.")
-
-(defvar nnmail-procmail-directory "~/incoming/"
- "*When using procmail (and the like), incoming mail is put in this directory.
-The Gnus mail backends will read the mail from this directory.")
-
-(defvar nnmail-procmail-suffix "\\.spool"
- "*Suffix of files created by procmail (and the like).
-This variable might be a suffix-regexp to match the suffixes of
-several files - eg. \".spool[0-9]*\".")
-
-(defvar nnmail-resplit-incoming nil
- "*If non-nil, re-split incoming procmail sorted mail.")
-
-(defvar nnmail-delete-file-function 'delete-file
- "Function called to delete files in some mail backends.")
-
-(defvar nnmail-crosspost-link-function 'add-name-to-file
- "Function called to create a copy of a file.
-This is `add-name-to-file' by default, which means that crossposts
-will use hard links. If your file system doesn't allow hard
-links, you could set this variable to `copy-file' instead.")
-
-(defvar nnmail-movemail-program "movemail"
- "*A command to be executed to move mail from the inbox.
-The default is \"movemail\".")
-
-(defvar nnmail-pop-password-required nil
- "*Non-nil if a password is required when reading mail using POP.")
-
-(defvar nnmail-read-incoming-hook nil
- "*Hook that will be run after the incoming mail has been transferred.
-The incoming mail is moved from `nnmail-spool-file' (which normally is
-something like \"/usr/spool/mail/$user\") to the user's home
-directory. This hook is called after the incoming mail box has been
-emptied, and can be used to call any mail box programs you have
-running (\"xwatch\", etc.)
-
-Eg.
-
-\(add-hook 'nnmail-read-incoming-hook
- (lambda ()
- (start-process \"mailsend\" nil
- \"/local/bin/mailsend\" \"read\" \"mbox\")))
-
-If you have xwatch running, this will alert it that mail has been
-read.
-
-If you use `display-time', you could use something like this:
-
-\(add-hook 'nnmail-read-incoming-hook
- (lambda ()
- ;; Update the displayed time, since that will clear out
- ;; the flag that says you have mail.
- (if (eq (process-status \"display-time\") 'run)
- (display-time-filter display-time-process \"\"))))")
-
-(when (eq system-type 'windows-nt)
- (add-hook 'nnmail-prepare-incoming-hook 'nnheader-ms-strip-cr))
-
-;; Suggested by Erik Selberg <speed@cs.washington.edu>.
-(defvar nnmail-prepare-incoming-hook nil
- "*Hook called before treating incoming mail.
-The hook is run in a buffer with all the new, incoming mail.")
-
-(defvar nnmail-pre-get-new-mail-hook nil
- "Hook called just before starting to handle new incoming mail.")
-
-(defvar nnmail-post-get-new-mail-hook nil
- "Hook called just after finishing handling new incoming mail.")
-
-;; Suggested by Mejia Pablo J <pjm9806@usl.edu>.
-(defvar nnmail-tmp-directory nil
- "*If non-nil, use this directory for temporary storage when reading incoming mail.")
-
-(defvar nnmail-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.")
-
-(defvar nnmail-split-fancy "mail.misc"
- "*Incoming mail can be split according to this fancy variable.
-To enable this, set `nnmail-split-methods' to `nnmail-split-fancy'.
-
-The format is this variable is SPLIT, where SPLIT can be one of
-the following:
-
-GROUP: Mail will be stored in GROUP (a string).
-
-\(FIELD VALUE SPLIT): If the message field FIELD (a regexp) contains
- VALUE (a regexp), store the messages as specified by SPLIT.
-
-\(| SPLIT...): Process each SPLIT expression until one of them matches.
- A SPLIT expression is said to match if it will cause the mail
- message to be stored in one or more groups.
-
-\(& SPLIT...): Process each SPLIT expression.
-
-FIELD must match a complete field name. VALUE must match a complete
-word according to the `nnmail-split-fancy-syntax-table' syntax table.
-You can use .* in the regexps to match partial field names or words.
-
-FIELD and VALUE can also be lisp symbols, in that case they are expanded
-as specified in `nnmail-split-abbrev-alist'.
-
-Example:
-
-\(setq nnmail-split-methods 'nnmail-split-fancy
- nnmail-split-fancy
- ;; Messages from the mailer deamon are not crossposted to any of
- ;; the ordinary groups. Warnings are put in a separate group
- ;; from real errors.
- '(| (\"from\" mail (| (\"subject\" \"warn.*\" \"mail.warning\")
- \"mail.misc\"))
- ;; Non-error messages are crossposted to all relevant
- ;; groups, but we don't crosspost between the group for the
- ;; (ding) list and the group for other (ding) related mail.
- (& (| (any \"ding@ifi\\\\.uio\\\\.no\" \"ding.list\")
- (\"subject\" \"ding\" \"ding.misc\"))
- ;; Other mailing lists...
- (any \"procmail@informatik\\\\.rwth-aachen\\\\.de\" \"procmail.list\")
- (any \"SmartList@informatik\\\\.rwth-aachen\\\\.de\" \"SmartList.list\")
- ;; People...
- (any \"larsi@ifi\\\\.uio\\\\.no\" \"people.Lars Magne Ingebrigtsen\"))
- ;; Unmatched mail goes to the catch all group.
- \"misc.misc\"))")
-
-(defvar nnmail-split-abbrev-alist
- '((any . "from\\|to\\|cc\\|sender\\|apparently-to")
- (mail . "mailer-daemon\\|postmaster"))
- "*Alist of abbreviations allowed in `nnmail-split-fancy'.")
-
-(defvar nnmail-delete-incoming t
- "*If non-nil, the mail backends will delete incoming files after splitting.")
-
-(defvar nnmail-message-id-cache-length 1000
- "*The approximate number of Message-IDs nnmail will keep in its cache.
-If this variable is nil, no checking on duplicate messages will be
-performed.")
-
-(defvar nnmail-message-id-cache-file "~/.nnmail-cache"
- "*The file name of the nnmail Message-ID cache.")
-
-(defvar nnmail-treat-duplicates 'warn
- "*If non-nil, nnmail keep a cache of Message-IDs to discover mail duplicates.
-Three values are legal: nil, which means that nnmail is not to keep a
-Message-ID cache; `warn', which means that nnmail should insert extra
-headers to warn the user about the duplication (this is the default);
-and `delete', which means that nnmail will delete duplicated mails.
-
-This variable can also be a function. It will be called from a buffer
-narrowed to the article in question with the Message-ID as a
-parameter. It should return nil, `warn' or `delete'.")
-
-;;; Internal variables.
-
-(defvar nnmail-pop-password nil
- "*Password to use when reading mail from a POP server, if required.")
-
-(defvar nnmail-split-fancy-syntax-table
- (copy-syntax-table (standard-syntax-table))
- "Syntax table used by `nnmail-split-fancy'.")
-
-(defvar nnmail-prepare-save-mail-hook nil
- "Hook called before saving mail.")
-
-(defvar nnmail-moved-inboxes nil
- "List of inboxes that have been moved.")
-
-(defvar nnmail-internal-password nil)
-
-
-
-(defconst nnmail-version "nnmail 1.0"
- "nnmail version.")
-
-
-
-(defun nnmail-request-post (&optional server)
- (mail-send-and-exit nil))
-
-(defun nnmail-find-file (file)
- "Insert FILE in server buffer safely."
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (let ((format-alist nil)
- (after-insert-file-functions nil))
- (condition-case ()
- (progn (insert-file-contents file) t)
- (file-error nil))))
-
-(defun nnmail-group-pathname (group dir &optional file)
- "Make pathname for GROUP."
- (concat
- (let ((dir (file-name-as-directory (expand-file-name dir))))
- ;; If this directory exists, we use it directly.
- (if (or nnmail-use-long-file-names
- (file-directory-p (concat dir group)))
- (concat dir group "/")
- ;; If not, we translate dots into slashes.
- (concat dir (nnheader-replace-chars-in-string group ?. ?/) "/")))
- (or file "")))
-
-(defun nnmail-date-to-time (date)
- "Convert DATE into time."
- (let* ((d1 (timezone-parse-date date))
- (t1 (timezone-parse-time (aref d1 3))))
- (apply 'encode-time
- (mapcar (lambda (el)
- (and el (string-to-number el)))
- (list
- (aref t1 2) (aref t1 1) (aref t1 0)
- (aref d1 2) (aref d1 1) (aref d1 0)
- (aref d1 4))))))
-
-(defun nnmail-time-less (t1 t2)
- "Say whether time T1 is less than time T2."
- (or (< (car t1) (car t2))
- (and (= (car t1) (car t2))
- (< (nth 1 t1) (nth 1 t2)))))
-
-(defun nnmail-days-to-time (days)
- "Convert DAYS into time."
- (let* ((seconds (* 1.0 days 60 60 24))
- (rest (expt 2 16))
- (ms (condition-case nil (round (/ seconds rest))
- (range-error (expt 2 16)))))
- (list ms (condition-case nil (round (- seconds (* ms rest)))
- (range-error (expt 2 16))))))
-
-(defun nnmail-time-since (time)
- "Return the time since TIME, which is either an internal time or a date."
- (when (stringp time)
- ;; Convert date strings to internal time.
- (setq time (nnmail-date-to-time time)))
- (let* ((current (current-time))
- (rest (if (< (nth 1 current) (nth 1 time)) (expt 2 16))))
- (list (- (+ (car current) (if rest -1 0)) (car time))
- (- (+ (or rest 0) (nth 1 current)) (nth 1 time)))))
-
-;; Function rewritten from rmail.el.
-(defun nnmail-move-inbox (inbox)
- "Move INBOX to `nnmail-crash-box'."
- (let ((inbox (file-truename
- (expand-file-name (substitute-in-file-name inbox))))
- (tofile (file-truename (expand-file-name
- (substitute-in-file-name nnmail-crash-box))))
- movemail popmail errors password)
- ;; If getting from mail spool directory,
- ;; use movemail to move rather than just renaming,
- ;; so as to interlock with the mailer.
- (unless (setq popmail (string-match "^po:" (file-name-nondirectory inbox)))
- (setq movemail t))
- (when popmail
- (setq inbox (file-name-nondirectory inbox)))
- (when (and movemail
- ;; On some systems, /usr/spool/mail/foo is a directory
- ;; and the actual inbox is /usr/spool/mail/foo/foo.
- (file-directory-p inbox))
- (setq inbox (expand-file-name (user-login-name) inbox)))
- (if (member inbox nnmail-moved-inboxes)
- nil
- (if popmail
- (progn
- (setq nnmail-internal-password nnmail-pop-password)
- (when (and nnmail-pop-password-required (not nnmail-pop-password))
- (setq nnmail-internal-password
- (nnmail-read-passwd
- (format "Password for %s: "
- (substring inbox (+ popmail 3))))))
- (message "Getting mail from post office ..."))
- (when (or (and (file-exists-p tofile)
- (/= 0 (nnheader-file-size tofile)))
- (and (file-exists-p inbox)
- (/= 0 (nnheader-file-size inbox))))
- (message "Getting mail from %s..." inbox)))
- ;; Set TOFILE if have not already done so, and
- ;; rename or copy the file INBOX to TOFILE if and as appropriate.
- (cond
- ((file-exists-p tofile)
- ;; The crash box exists already.
- t)
- ((and (not popmail)
- (not (file-exists-p inbox)))
- ;; There is no inbox.
- (setq tofile nil))
- ((and (not movemail) (not popmail))
- ;; Try copying. If that fails (perhaps no space),
- ;; rename instead.
- (condition-case nil
- (copy-file inbox tofile nil)
- (error
- ;; Third arg is t so we can replace existing file TOFILE.
- (rename-file inbox tofile t)))
- (push inbox nnmail-moved-inboxes)
- ;; 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) inbox)
- (file-error nil)))
- (t
- ;; Use movemail.
- (unwind-protect
- (save-excursion
- (setq errors (generate-new-buffer " *nnmail loss*"))
- (buffer-disable-undo errors)
- (let ((default-directory "/"))
- (apply
- 'call-process
- (append
- (list
- (expand-file-name nnmail-movemail-program exec-directory)
- nil errors nil inbox tofile)
- (when nnmail-internal-password
- (list nnmail-internal-password)))))
- (if (not (buffer-modified-p errors))
- ;; No output => movemail won
- (push inbox nnmail-moved-inboxes)
- (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)
- (setq tofile nil))))))
- (and errors
- (buffer-name errors)
- (kill-buffer errors))
- tofile)))
-
-(defun nnmail-get-active ()
- "Returns an assoc of group names and active ranges.
-nn*-request-list should have been called before calling this function."
- (let (group-assoc)
- ;; Go through all groups from the active list.
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (while (re-search-forward
- "^\\([^ \t]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\([0-9]+\\)" nil t)
- ;; We create an alist with `(GROUP (LOW . HIGH))' elements.
- (push (list (match-string 1)
- (cons (string-to-int (match-string 3))
- (string-to-int (match-string 2))))
- group-assoc)))
- group-assoc))
-
-(defun nnmail-save-active (group-assoc file-name)
- "Save GROUP-ASSOC in ACTIVE-FILE."
- (when file-name
- (let (group)
- (save-excursion
- (set-buffer (get-buffer-create " *nnmail active*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (while group-assoc
- (setq group (pop group-assoc))
- (insert (format "%s %d %d y\n" (car group) (cdadr group)
- (caadr group))))
- (unless (file-exists-p (file-name-directory file-name))
- (make-directory (file-name-directory file-name) t))
- (write-region 1 (point-max) (expand-file-name file-name) nil 'nomesg)
- (kill-buffer (current-buffer))))))
-
-(defun nnmail-get-split-group (file group)
- (if (or (eq nnmail-spool-file 'procmail)
- nnmail-use-procmail)
- (cond (group group)
- ((string-match (concat "^" (expand-file-name
- (file-name-as-directory
- nnmail-procmail-directory))
- "\\([^/]*\\)" nnmail-procmail-suffix "$")
- (expand-file-name file))
- (substring (expand-file-name file)
- (match-beginning 1) (match-end 1)))
- (t
- group))
- group))
-
-(defun nnmail-process-babyl-mail-format (func)
- (let ((case-fold-search t)
- start message-id content-length do-search end)
- (while (not (eobp))
- (goto-char (point-min))
- (re-search-forward
- " \n0, *unseen,+\n\\(\\*\\*\\* EOOH \\*\\*\\*\n\\)?" nil t)
- (goto-char (match-end 0))
- (delete-region (match-beginning 0) (match-end 0))
- (setq start (point))
- ;; Skip all the headers in case there are more "From "s...
- (or (search-forward "\n\n" nil t)
- (search-forward-regexp "^[^:]*\\( .*\\|\\)$" nil t)
- (search-forward " "))
- ;; Find the Message-ID header.
- (save-excursion
- (if (re-search-backward "^Message-ID:[ \t]*\\(<[^>]*>\\)" nil t)
- (setq message-id (buffer-substring (match-beginning 1)
- (match-end 1)))
- ;; There is no Message-ID here, so we create one.
- (save-excursion
- (when (re-search-backward "^Message-ID:" nil t)
- (beginning-of-line)
- (insert "Original-")))
- (forward-line -1)
- (insert "Message-ID: " (setq message-id (nnmail-message-id))
- "\n")))
- ;; Look for a Content-Length header.
- (if (not (save-excursion
- (and (re-search-backward
- "^Content-Length:[ \t]*\\([0-9]+\\)" start t)
- (setq content-length (string-to-int
- (buffer-substring
- (match-beginning 1)
- (match-end 1))))
- ;; We destroy the header, since none of
- ;; the backends ever use it, and we do not
- ;; want to confuse other mailers by having
- ;; a (possibly) faulty header.
- (progn (insert "X-") t))))
- (setq do-search t)
- (if (or (= (+ (point) content-length) (point-max))
- (save-excursion
- (goto-char (+ (point) content-length))
- (looking-at "")))
- (progn
- (goto-char (+ (point) content-length))
- (setq do-search nil))
- (setq do-search t)))
- ;; Go to the beginning of the next article - or to the end
- ;; of the buffer.
- (if do-search
- (if (re-search-forward "^" nil t)
- (goto-char (match-beginning 0))
- (goto-char (1- (point-max)))))
- (delete-char 1) ; delete ^_
- (save-excursion
- (save-restriction
- (narrow-to-region start (point))
- (goto-char (point-min))
- (nnmail-check-duplication message-id func)
- (setq end (point-max))))
- (goto-char end))))
-
-(defun nnmail-search-unix-mail-delim ()
- "Put point at the beginning of the next message."
- (let ((case-fold-search t)
- (delim (concat "^" message-unix-mail-delimiter))
- found)
- (while (not found)
- (if (re-search-forward delim nil t)
- (when (or (looking-at "[^\n :]+ *:")
- (looking-at delim)
- (looking-at (concat ">" message-unix-mail-delimiter)))
- (forward-line -1)
- (setq found 'yes))
- (setq found 'no)))
- (eq found 'yes)))
-
-(defun nnmail-process-unix-mail-format (func)
- (let ((case-fold-search t)
- (delim (concat "^" message-unix-mail-delimiter))
- start message-id content-length end skip head-end)
- (goto-char (point-min))
- (if (not (and (re-search-forward delim nil t)
- (goto-char (match-beginning 0))))
- ;; Possibly wrong format?
- (error "Error, unknown mail format! (Possibly corrupted.)")
- ;; Carry on until the bitter end.
- (while (not (eobp))
- (setq start (point)
- end nil)
- ;; Find the end of the head.
- (narrow-to-region
- start
- (if (search-forward "\n\n" nil t)
- (1- (point))
- ;; This will never happen, but just to be on the safe side --
- ;; if there is no head-body delimiter, we search a bit manually.
- (while (and (looking-at "From \\|[^ \t]+:")
- (not (eobp)))
- (forward-line 1)
- (point))))
- ;; Find the Message-ID header.
- (goto-char (point-min))
- (if (re-search-forward "^Message-ID:[ \t]*\\(<[^>]+>\\)" nil t)
- (setq message-id (match-string 1))
- (save-excursion
- (when (re-search-forward "^Message-ID:" nil t)
- (beginning-of-line)
- (insert "Original-")))
- ;; There is no Message-ID here, so we create one.
- (forward-line 1)
- (insert "Message-ID: " (setq message-id (nnmail-message-id)) "\n"))
- ;; Look for a Content-Length header.
- (goto-char (point-min))
- (if (not (re-search-forward
- "^Content-Length:[ \t]*\\([0-9]+\\)" nil t))
- (setq content-length nil)
- (setq content-length (string-to-int (match-string 1)))
- ;; We destroy the header, since none of the backends ever
- ;; use it, and we do not want to confuse other mailers by
- ;; having a (possibly) faulty header.
- (beginning-of-line)
- (insert "X-"))
- ;; Find the end of this article.
- (goto-char (point-max))
- (widen)
- (setq head-end (point))
- ;; We try the Content-Length value. The idea: skip over the header
- ;; separator, then check what happens content-length bytes into the
- ;; message body. This should be either the end ot the buffer, the
- ;; message separator or a blank line followed by the separator.
- ;; The blank line should probably be deleted. If neither of the
- ;; three is met, the content-length header is probably invalid.
- (when content-length
- (forward-line 1)
- (setq skip (+ (point) content-length))
- (goto-char skip)
- (cond ((or (= skip (point-max))
- (= (1+ skip) (point-max)))
- (setq end (point-max)))
- ((looking-at delim)
- (setq end skip))
- ((looking-at
- (concat "[ \t]*\n\\(" delim "\\)"))
- (setq end (match-beginning 1)))
- (t (setq end nil))))
- (if end
- (goto-char end)
- ;; No Content-Length, so we find the beginning of the next
- ;; article or the end of the buffer.
- (goto-char head-end)
- (or (nnmail-search-unix-mail-delim)
- (goto-char (point-max))))
- ;; Allow the backend to save the article.
- (save-excursion
- (save-restriction
- (narrow-to-region start (point))
- (goto-char (point-min))
- (nnmail-check-duplication message-id func)
- (setq end (point-max))))
- (goto-char end)))))
-
-(defun nnmail-process-mmdf-mail-format (func)
- (let ((delim "^\^A\^A\^A\^A$")
- (case-fold-search t)
- start message-id end)
- (goto-char (point-min))
- (if (not (and (re-search-forward delim nil t)
- (forward-line 1)))
- ;; Possibly wrong format?
- (error "Error, unknown mail format! (Possibly corrupted.)")
- ;; Carry on until the bitter end.
- (while (not (eobp))
- (setq start (point))
- ;; Find the end of the head.
- (narrow-to-region
- start
- (if (search-forward "\n\n" nil t)
- (1- (point))
- ;; This will never happen, but just to be on the safe side --
- ;; if there is no head-body delimiter, we search a bit manually.
- (while (and (looking-at "From \\|[^ \t]+:")
- (not (eobp)))
- (forward-line 1)
- (point))))
- ;; Find the Message-ID header.
- (goto-char (point-min))
- (if (re-search-forward "^Message-ID:[ \t]*\\(<[^>]+>\\)" nil t)
- (setq message-id (match-string 1))
- ;; There is no Message-ID here, so we create one.
- (save-excursion
- (when (re-search-backward "^Message-ID:" nil t)
- (beginning-of-line)
- (insert "Original-")))
- (forward-line 1)
- (insert "Message-ID: " (setq message-id (nnmail-message-id)) "\n"))
- ;; Find the end of this article.
- (goto-char (point-max))
- (widen)
- (if (re-search-forward delim nil t)
- (beginning-of-line)
- (goto-char (point-max)))
- ;; Allow the backend to save the article.
- (save-excursion
- (save-restriction
- (narrow-to-region start (point))
- (goto-char (point-min))
- (nnmail-check-duplication message-id func)
- (setq end (point-max))))
- (goto-char end)
- (forward-line 2)))))
-
-(defun nnmail-split-incoming (incoming func &optional exit-func group)
- "Go through the entire INCOMING file and pick out each individual mail.
-FUNC will be called with the buffer narrowed to each mail."
- (let (;; If this is a group-specific split, we bind the split
- ;; methods to just this group.
- (nnmail-split-methods (if (and group
- (or (eq nnmail-spool-file 'procmail)
- nnmail-use-procmail)
- (not nnmail-resplit-incoming))
- (list (list group ""))
- nnmail-split-methods)))
- (save-excursion
- ;; Insert the incoming file.
- (set-buffer (get-buffer-create " *nnmail incoming*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (nnheader-insert-file-contents-literally incoming)
- (unless (zerop (buffer-size))
- (goto-char (point-min))
- (save-excursion (run-hooks 'nnmail-prepare-incoming-hook))
- ;; Handle both babyl, MMDF and unix mail formats, since movemail will
- ;; use the former when fetching from a mailbox, the latter when
- ;; fetches from a file.
- (cond ((or (looking-at "\^L")
- (looking-at "BABYL OPTIONS:"))
- (nnmail-process-babyl-mail-format func))
- ((looking-at "\^A\^A\^A\^A")
- (nnmail-process-mmdf-mail-format func))
- (t
- (nnmail-process-unix-mail-format func))))
- (if exit-func (funcall exit-func))
- (kill-buffer (current-buffer)))))
-
-;; Mail crossposts suggested by Brian Edmonds <edmonds@cs.ubc.ca>.
-(defun nnmail-article-group (func)
- "Look at the headers and return an alist of groups that match.
-FUNC will be called with the group name to determine the article number."
- (let ((methods nnmail-split-methods)
- (obuf (current-buffer))
- (beg (point-min))
- end group-art method)
- (if (and (sequencep methods) (= (length methods) 1))
- ;; If there is only just one group to put everything in, we
- ;; just return a list with just this one method in.
- (setq group-art
- (list (cons (caar methods) (funcall func (caar methods)))))
- ;; We do actual comparison.
- (save-excursion
- ;; Find headers.
- (goto-char beg)
- (setq end (if (search-forward "\n\n" nil t) (point) (point-max)))
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- ;; Copy the headers into the work buffer.
- (insert-buffer-substring obuf beg end)
- ;; Fold continuation lines.
- (goto-char (point-min))
- (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
- (replace-match " " t t))
- (if (and (symbolp nnmail-split-methods)
- (fboundp nnmail-split-methods))
- ;; `nnmail-split-methods' is a function, so we just call
- ;; this function here and use the result.
- (setq group-art
- (mapcar
- (lambda (group) (cons group (funcall func group)))
- (condition-case nil
- (or (funcall nnmail-split-methods)
- '("bogus"))
- (error
- (message
- "Error in `nnmail-split-methods'; using `bogus' mail group")
- (sit-for 1)
- '("bogus")))))
- ;; Go through the split methods to find a match.
- (while (and methods (or nnmail-crosspost (not group-art)))
- (goto-char (point-max))
- (setq method (pop methods))
- (if (or methods
- (not (equal "" (nth 1 method))))
- (when (and
- (condition-case ()
- (if (stringp (nth 1 method))
- (re-search-backward (cadr method) nil t)
- ;; Function to say whether this is a match.
- (funcall (nth 1 method) (car method)))
- (error nil))
- ;; Don't enter the article into the same
- ;; group twice.
- (not (assoc (car method) group-art)))
- (push (cons (car method) (funcall func (car method)))
- group-art))
- ;; This is the final group, which is used as a
- ;; catch-all.
- (unless group-art
- (setq group-art
- (list (cons (car method)
- (funcall func (car method)))))))))
- group-art))))
-
-(defun nnmail-insert-lines ()
- "Insert how many lines there are in the body of the mail.
-Return the number of characters in the body."
- (let (lines chars)
- (save-excursion
- (goto-char (point-min))
- (when (search-forward "\n\n" nil t)
- (setq chars (- (point-max) (point)))
- (setq lines (count-lines (point) (point-max)))
- (forward-char -1)
- (save-excursion
- (when (re-search-backward "^Lines: " nil t)
- (delete-region (point) (progn (forward-line 1) (point)))))
- (beginning-of-line)
- (insert (format "Lines: %d\n" (max lines 0)))
- chars))))
-
-(defun nnmail-insert-xref (group-alist)
- "Insert an Xref line based on the (group . article) alist."
- (save-excursion
- (goto-char (point-min))
- (when (search-forward "\n\n" nil t)
- (forward-char -1)
- (when (re-search-backward "^Xref: " nil t)
- (delete-region (match-beginning 0)
- (progn (forward-line 1) (point))))
- (insert (format "Xref: %s" (system-name)))
- (while group-alist
- (insert (format " %s:%d" (caar group-alist) (cdar group-alist)))
- (setq group-alist (cdr group-alist)))
- (insert "\n"))))
-
-;; Written by byer@mv.us.adobe.com (Scott Byer).
-(defun nnmail-make-complex-temp-name (prefix)
- (let ((newname (make-temp-name prefix))
- (newprefix prefix))
- (while (file-exists-p newname)
- (setq newprefix (concat newprefix "x"))
- (setq newname (make-temp-name newprefix)))
- newname))
-
-;; Written by Per Abrahamsen <amanda@iesd.auc.dk>.
-
-(defun nnmail-split-fancy ()
- "Fancy splitting method.
-See the documentation for the variable `nnmail-split-fancy' for documentation."
- (let ((syntab (syntax-table)))
- (unwind-protect
- (progn
- (set-syntax-table nnmail-split-fancy-syntax-table)
- (nnmail-split-it nnmail-split-fancy))
- (set-syntax-table syntab))))
-
-(defvar nnmail-split-cache nil)
-;; Alist of split expressions their equivalent regexps.
-
-(defun nnmail-split-it (split)
- ;; Return a list of groups matching SPLIT.
- (cond ((stringp split)
- ;; A group.
- (list split))
- ((eq (car split) '&)
- (apply 'nconc (mapcar 'nnmail-split-it (cdr split))))
- ((eq (car split) '|)
- (let (done)
- (while (and (not done) (cdr split))
- (setq split (cdr split)
- done (nnmail-split-it (car split))))
- done))
- ((assq split nnmail-split-cache)
- ;; A compiled match expression.
- (goto-char (point-max))
- (if (re-search-backward (cdr (assq split nnmail-split-cache)) nil t)
- (nnmail-split-it (nth 2 split))))
- (t
- ;; An uncompiled match.
- (let* ((field (nth 0 split))
- (value (nth 1 split))
- (regexp (concat "^\\("
- (if (symbolp field)
- (cdr (assq field
- nnmail-split-abbrev-alist))
- field)
- "\\):.*\\<\\("
- (if (symbolp value)
- (cdr (assq value
- nnmail-split-abbrev-alist))
- value)
- "\\)\\>")))
- (setq nnmail-split-cache
- (cons (cons split regexp) nnmail-split-cache))
- (goto-char (point-max))
- (if (re-search-backward regexp nil t)
- (nnmail-split-it (nth 2 split)))))))
-
-;; Get a list of spool files to read.
-(defun nnmail-get-spool-files (&optional group)
- (if (null nnmail-spool-file)
- ;; No spool file whatsoever.
- nil
- (let* ((procmails
- ;; If procmail is used to get incoming mail, the files
- ;; are stored in this directory.
- (and (file-exists-p nnmail-procmail-directory)
- (or (eq nnmail-spool-file 'procmail)
- nnmail-use-procmail)
- (directory-files
- nnmail-procmail-directory
- t (concat (if group (concat "^" group) "")
- nnmail-procmail-suffix "$") t)))
- (p procmails)
- (crash (when (and (file-exists-p nnmail-crash-box)
- (> (nnheader-file-size
- (file-truename nnmail-crash-box)) 0))
- (list nnmail-crash-box))))
- ;; Remove any directories that inadvertantly match the procmail
- ;; suffix, which might happen if the suffix is "".
- (while p
- (when (file-directory-p (car p))
- (setq procmails (delete (car p) procmails)))
- (setq p (cdr p)))
- ;; Return the list of spools.
- (append
- crash
- (cond ((and group
- (or (eq nnmail-spool-file 'procmail)
- nnmail-use-procmail)
- procmails)
- procmails)
- ((and group
- (eq nnmail-spool-file 'procmail))
- nil)
- ((listp nnmail-spool-file)
- (append nnmail-spool-file procmails))
- ((stringp nnmail-spool-file)
- (cons nnmail-spool-file procmails))
- ((eq nnmail-spool-file 'pop)
- (cons (format "po:%s" (user-login-name)) procmails))
- (t
- procmails))))))
-
-;; Activate a backend only if it isn't already activated.
-;; If FORCE, re-read the active file even if the backend is
-;; already activated.
-(defun nnmail-activate (backend &optional force)
- (let (file timestamp file-time)
- (if (or (not (symbol-value (intern (format "%s-group-alist" backend))))
- force
- (and (setq file (condition-case ()
- (symbol-value (intern (format "%s-active-file"
- backend)))
- (error nil)))
- (setq file-time (nth 5 (file-attributes file)))
- (or (not
- (setq timestamp
- (condition-case ()
- (symbol-value (intern
- (format "%s-active-timestamp"
- backend)))
- (error 'none))))
- (not (consp timestamp))
- (equal timestamp '(0 0))
- (> (nth 0 file-time) (nth 0 timestamp))
- (and (= (nth 0 file-time) (nth 0 timestamp))
- (> (nth 1 file-time) (nth 1 timestamp))))))
- (save-excursion
- (or (eq timestamp 'none)
- (set (intern (format "%s-active-timestamp" backend))
- (current-time)))
- (funcall (intern (format "%s-request-list" backend)))
- (set (intern (format "%s-group-alist" backend))
- (nnmail-get-active))))
- t))
-
-(defun nnmail-message-id ()
- (concat "<" (message-unique-id) "@totally-fudged-out-message-id>"))
-
-;;;
-;;; nnmail duplicate handling
-;;;
-
-(defvar nnmail-cache-buffer nil)
-
-(defun nnmail-cache-open ()
- (if (or (not nnmail-treat-duplicates)
- (and nnmail-cache-buffer
- (buffer-name nnmail-cache-buffer)))
- () ; The buffer is open.
- (save-excursion
- (set-buffer
- (setq nnmail-cache-buffer
- (get-buffer-create " *nnmail message-id cache*")))
- (buffer-disable-undo (current-buffer))
- (and (file-exists-p nnmail-message-id-cache-file)
- (insert-file-contents nnmail-message-id-cache-file))
- (set-buffer-modified-p nil)
- (current-buffer))))
-
-(defun nnmail-cache-close ()
- (when (and nnmail-cache-buffer
- nnmail-treat-duplicates
- (buffer-name nnmail-cache-buffer)
- (buffer-modified-p nnmail-cache-buffer))
- (save-excursion
- (set-buffer nnmail-cache-buffer)
- ;; Weed out the excess number of Message-IDs.
- (goto-char (point-max))
- (and (search-backward "\n" nil t nnmail-message-id-cache-length)
- (progn
- (beginning-of-line)
- (delete-region (point-min) (point))))
- ;; Save the buffer.
- (or (file-exists-p (file-name-directory nnmail-message-id-cache-file))
- (make-directory (file-name-directory nnmail-message-id-cache-file)
- t))
- (write-region (point-min) (point-max)
- nnmail-message-id-cache-file nil 'silent)
- (set-buffer-modified-p nil)
- (setq nnmail-cache-buffer nil)
- ;;(kill-buffer (current-buffer))
- )))
-
-(defun nnmail-cache-insert (id)
- (when nnmail-treat-duplicates
- (save-excursion
- (set-buffer nnmail-cache-buffer)
- (goto-char (point-max))
- (insert id "\n"))))
-
-(defun nnmail-cache-id-exists-p (id)
- (when nnmail-treat-duplicates
- (save-excursion
- (set-buffer nnmail-cache-buffer)
- (goto-char (point-max))
- (search-backward id nil t))))
-
-(defun nnmail-check-duplication (message-id func)
- ;; If this is a duplicate message, then we do not save it.
- (let* ((duplication (nnmail-cache-id-exists-p message-id))
- (action (when duplication
- (cond
- ((memq nnmail-treat-duplicates '(warn delete))
- nnmail-treat-duplicates)
- ((nnheader-functionp nnmail-treat-duplicates)
- (funcall nnmail-treat-duplicates message-id))
- (t
- nnmail-treat-duplicates)))))
- (cond
- ((not duplication)
- (nnmail-cache-insert message-id)
- (funcall func))
- ((eq action 'delete)
- (delete-region (point-min) (point-max)))
- ((eq action 'warn)
- ;; We insert a warning.
- (let ((case-fold-search t)
- (newid (nnmail-message-id)))
- (goto-char (point-min))
- (when (re-search-forward "^message-id:" nil t)
- (beginning-of-line)
- (insert "Original-"))
- (beginning-of-line)
- (insert
- "Message-ID: " newid "\n"
- "Gnus-Warning: This is a duplicate of message " message-id "\n")
- (nnmail-cache-insert newid)
- (funcall func)))
- (t
- (funcall func)))))
-
-;;; Get new mail.
-
-(defun nnmail-get-value (&rest args)
- (let ((sym (intern (apply 'format args))))
- (when (boundp sym)
- (symbol-value sym))))
-
-(defun nnmail-get-new-mail (method exit-func temp
- &optional group spool-func)
- "Read new incoming mail."
- (let* ((spools (nnmail-get-spool-files group))
- (group-in group)
- incoming incomings spool)
- (when (and (nnmail-get-value "%s-get-new-mail" method)
- nnmail-spool-file)
- ;; We first activate all the groups.
- (nnmail-activate method)
- ;; Allow the user to hook.
- (run-hooks 'nnmail-pre-get-new-mail-hook)
- ;; Open the message-id cache.
- (nnmail-cache-open)
- ;; The we go through all the existing spool files and split the
- ;; mail from each.
- (while spools
- (setq spool (pop spools))
- ;; We read each spool file if either the spool is a POP-mail
- ;; spool, or the file exists. We can't check for the
- ;; existance of POPped mail.
- (when (or (string-match "^po:" spool)
- (and (file-exists-p spool)
- (> (nnheader-file-size (file-truename spool)) 0)))
- (nnheader-message 3 "%s: Reading incoming mail..." method)
- (when (and (nnmail-move-inbox spool)
- (file-exists-p nnmail-crash-box))
- ;; There is new mail. We first find out if all this mail
- ;; is supposed to go to some specific group.
- (setq group (nnmail-get-split-group spool group-in))
- ;; We split the mail
- (nnmail-split-incoming
- nnmail-crash-box (intern (format "%s-save-mail" method))
- spool-func group)
- ;; Check whether the inbox is to be moved to the special tmp dir.
- (setq incoming
- (nnmail-make-complex-temp-name
- (expand-file-name
- (if nnmail-tmp-directory
- (concat
- (file-name-as-directory nnmail-tmp-directory)
- (file-name-nondirectory (concat temp "Incoming")))
- (concat temp "Incoming")))))
- (rename-file nnmail-crash-box incoming t)
- (push incoming incomings))))
- ;; If we did indeed read any incoming spools, we save all info.
- (when incomings
- (nnmail-save-active
- (nnmail-get-value "%s-group-alist" method)
- (nnmail-get-value "%s-active-file" method))
- (when exit-func
- (funcall exit-func))
- (run-hooks 'nnmail-read-incoming-hook)
- (nnheader-message 3 "%s: Reading incoming mail...done" method))
- ;; Close the message-id cache.
- (nnmail-cache-close)
- ;; Allow the user to hook.
- (run-hooks 'nnmail-post-get-new-mail-hook)
- ;; Delete all the temporary files.
- (while incomings
- (setq incoming (pop incomings))
- (and nnmail-delete-incoming
- (file-exists-p incoming)
- (file-writable-p incoming)
- (delete-file incoming))))))
-
-(defun nnmail-expired-article-p (group time force &optional inhibit)
- "Say whether an article that is TIME old in GROUP should be expired."
- (if force
- t
- (let ((days (or (and nnmail-expiry-wait-function
- (funcall nnmail-expiry-wait-function group))
- nnmail-expiry-wait)))
- (cond ((or (eq days 'never)
- (and (not force)
- inhibit))
- ;; This isn't an expirable group.
- nil)
- ((eq days 'immediate)
- ;; We expire all articles on sight.
- t)
- ((equal time '(0 0))
- ;; This is an ange-ftp group, and we don't have any dates.
- nil)
- ((numberp days)
- (setq days (nnmail-days-to-time days))
- ;; Compare the time with the current time.
- (nnmail-time-less days (nnmail-time-since time)))))))
-
-(defvar nnmail-read-passwd nil)
-(defun nnmail-read-passwd (prompt)
- (unless nnmail-read-passwd
- (if (load "passwd" t)
- (setq nnmail-read-passwd 'read-passwd)
- (autoload 'ange-ftp-read-passwd "ange-ftp")
- (setq nnmail-read-passwd 'ange-ftp-read-passwd)))
- (funcall nnmail-read-passwd prompt))
-
-(defun nnmail-check-syntax ()
- "Check (and modify) the syntax of the message in the current buffer."
- (save-restriction
- (message-narrow-to-head)
- (let ((case-fold-search t))
- (unless (re-search-forward "^Message-Id:" nil t)
- (insert "Message-ID: " (nnmail-message-id) "\n")))))
-
-(run-hooks 'nnmail-load-hook)
-
-(provide 'nnmail)
-
-;;; nnmail.el ends here
diff --git a/lisp/nnmbox.el b/lisp/nnmbox.el
deleted file mode 100644
index 9b7957247d4..00000000000
--- a/lisp/nnmbox.el
+++ /dev/null
@@ -1,533 +0,0 @@
-;;; nnmbox.el --- mail mbox access for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: news, mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; For an overview of what the interface functions do, please see the
-;; Gnus sources.
-
-;;; Code:
-
-(require 'nnheader)
-(require 'message)
-(require 'nnmail)
-(require 'nnoo)
-(eval-when-compile (require 'cl))
-
-(nnoo-declare nnmbox)
-
-(defvoo nnmbox-mbox-file (expand-file-name "~/mbox")
- "The name of the mail box file in the user's home directory.")
-
-(defvoo nnmbox-active-file (expand-file-name "~/.mbox-active")
- "The name of the active file for the mail box.")
-
-(defvoo nnmbox-get-new-mail t
- "If non-nil, nnmbox will check the incoming mail file and split the mail.")
-
-(defvoo nnmbox-prepare-save-mail-hook nil
- "Hook run narrowed to an article before saving.")
-
-
-
-(defconst nnmbox-version "nnmbox 1.0"
- "nnmbox version.")
-
-(defvoo nnmbox-current-group nil
- "Current nnmbox news group directory.")
-
-(defconst nnmbox-mbox-buffer nil)
-
-(defvoo nnmbox-status-string "")
-
-(defvoo nnmbox-group-alist nil)
-(defvoo nnmbox-active-timestamp nil)
-
-
-
-;;; Interface functions
-
-(nnoo-define-basics nnmbox)
-
-(deffoo nnmbox-retrieve-headers (sequence &optional newsgroup server fetch-old)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (let ((number (length sequence))
- (count 0)
- article art-string start stop)
- (nnmbox-possibly-change-newsgroup newsgroup server)
- (while sequence
- (setq article (car sequence))
- (setq art-string (nnmbox-article-string article))
- (set-buffer nnmbox-mbox-buffer)
- (if (or (search-forward art-string nil t)
- (progn (goto-char (point-min))
- (search-forward art-string nil t)))
- (progn
- (setq start
- (save-excursion
- (re-search-backward
- (concat "^" message-unix-mail-delimiter) nil t)
- (point)))
- (search-forward "\n\n" nil t)
- (setq stop (1- (point)))
- (set-buffer nntp-server-buffer)
- (insert (format "221 %d Article retrieved.\n" article))
- (insert-buffer-substring nnmbox-mbox-buffer start stop)
- (goto-char (point-max))
- (insert ".\n")))
- (setq sequence (cdr sequence))
- (setq count (1+ count))
- (and (numberp nnmail-large-newsgroup)
- (> number nnmail-large-newsgroup)
- (zerop (% count 20))
- (nnheader-message 5 "nnmbox: Receiving headers... %d%%"
- (/ (* count 100) number))))
-
- (and (numberp nnmail-large-newsgroup)
- (> number nnmail-large-newsgroup)
- (nnheader-message 5 "nnmbox: Receiving headers...done"))
-
- (set-buffer nntp-server-buffer)
- (nnheader-fold-continuation-lines)
- 'headers)))
-
-(deffoo nnmbox-open-server (server &optional defs)
- (nnoo-change-server 'nnmbox server defs)
- (cond
- ((not (file-exists-p nnmbox-mbox-file))
- (nnmbox-close-server)
- (nnheader-report 'nnmbox "No such file: %s" nnmbox-mbox-file))
- ((file-directory-p nnmbox-mbox-file)
- (nnmbox-close-server)
- (nnheader-report 'nnmbox "Not a regular file: %s" nnmbox-mbox-file))
- (t
- (nnheader-report 'nnmbox "Opened server %s using mbox %s" server
- nnmbox-mbox-file)
- t)))
-
-(deffoo nnmbox-close-server (&optional server)
- (when (and nnmbox-mbox-buffer
- (buffer-name nnmbox-mbox-buffer))
- (kill-buffer nnmbox-mbox-buffer))
- (nnoo-close-server 'nnmbox server)
- t)
-
-(deffoo nnmbox-server-opened (&optional server)
- (and (nnoo-current-server-p 'nnmbox server)
- nnmbox-mbox-buffer
- (buffer-name nnmbox-mbox-buffer)
- nntp-server-buffer
- (buffer-name nntp-server-buffer)))
-
-(deffoo nnmbox-request-article (article &optional newsgroup server buffer)
- (nnmbox-possibly-change-newsgroup newsgroup server)
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
- (goto-char (point-min))
- (if (search-forward (nnmbox-article-string article) nil t)
- (let (start stop)
- (re-search-backward (concat "^" message-unix-mail-delimiter) nil t)
- (setq start (point))
- (forward-line 1)
- (or (and (re-search-forward
- (concat "^" message-unix-mail-delimiter) nil t)
- (forward-line -1))
- (goto-char (point-max)))
- (setq stop (point))
- (let ((nntp-server-buffer (or buffer nntp-server-buffer)))
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (insert-buffer-substring nnmbox-mbox-buffer start stop)
- (goto-char (point-min))
- (while (looking-at "From ")
- (delete-char 5)
- (insert "X-From-Line: ")
- (forward-line 1))
- (if (numberp article)
- (cons nnmbox-current-group article)
- (nnmbox-article-group-number)))))))
-
-(deffoo nnmbox-request-group (group &optional server dont-check)
- (let ((active (cadr (assoc group nnmbox-group-alist))))
- (cond
- ((or (null active)
- (null (nnmbox-possibly-change-newsgroup group server)))
- (nnheader-report 'nnmbox "No such group: %s" group))
- (dont-check
- (nnheader-report 'nnmbox "Selected group %s" group)
- (nnheader-insert ""))
- (t
- (nnheader-report 'nnmbox "Selected group %s" group)
- (nnheader-insert "211 %d %d %d %s\n"
- (1+ (- (cdr active) (car active)))
- (car active) (cdr active) group)))))
-
-(deffoo nnmbox-request-scan (&optional group server)
- (nnmbox-read-mbox)
- (nnmail-get-new-mail
- 'nnmbox
- (lambda ()
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
- (save-buffer)))
- nnmbox-mbox-file group
- (lambda ()
- (save-excursion
- (let ((in-buf (current-buffer)))
- (set-buffer nnmbox-mbox-buffer)
- (goto-char (point-max))
- (insert-buffer-substring in-buf)))
- (nnmail-save-active nnmbox-group-alist nnmbox-active-file))))
-
-(deffoo nnmbox-close-group (group &optional server)
- t)
-
-(deffoo nnmbox-request-list (&optional server)
- (save-excursion
- (nnmail-find-file nnmbox-active-file)
- (setq nnmbox-group-alist (nnmail-get-active))))
-
-(deffoo nnmbox-request-newgroups (date &optional server)
- (nnmbox-request-list server))
-
-(deffoo nnmbox-request-list-newsgroups (&optional server)
- (nnheader-report 'nnmbox "LIST NEWSGROUPS is not implemented."))
-
-(deffoo nnmbox-request-expire-articles
- (articles newsgroup &optional server force)
- (nnmbox-possibly-change-newsgroup newsgroup server)
- (let* ((is-old t)
- rest)
- (nnmail-activate 'nnmbox)
-
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
- (while (and articles is-old)
- (goto-char (point-min))
- (if (search-forward (nnmbox-article-string (car articles)) nil t)
- (if (setq is-old
- (nnmail-expired-article-p
- newsgroup
- (buffer-substring
- (point) (progn (end-of-line) (point))) force))
- (progn
- (nnheader-message 5 "Deleting article %d in %s..."
- (car articles) newsgroup)
- (nnmbox-delete-mail))
- (setq rest (cons (car articles) rest))))
- (setq articles (cdr articles)))
- (save-buffer)
- ;; Find the lowest active article in this group.
- (let ((active (nth 1 (assoc newsgroup nnmbox-group-alist))))
- (goto-char (point-min))
- (while (and (not (search-forward
- (nnmbox-article-string (car active)) nil t))
- (<= (car active) (cdr active)))
- (setcar active (1+ (car active)))
- (goto-char (point-min))))
- (nnmail-save-active nnmbox-group-alist nnmbox-active-file)
- (nconc rest articles))))
-
-(deffoo nnmbox-request-move-article
- (article group server accept-form &optional last)
- (nnmbox-possibly-change-newsgroup group server)
- (let ((buf (get-buffer-create " *nnmbox move*"))
- result)
- (and
- (nnmbox-request-article article group server)
- (save-excursion
- (set-buffer buf)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert-buffer-substring nntp-server-buffer)
- (goto-char (point-min))
- (while (re-search-forward
- "^X-Gnus-Newsgroup:"
- (save-excursion (search-forward "\n\n" nil t) (point)) t)
- (delete-region (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point))))
- (setq result (eval accept-form))
- (kill-buffer buf)
- result)
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
- (goto-char (point-min))
- (if (search-forward (nnmbox-article-string article) nil t)
- (nnmbox-delete-mail))
- (and last (save-buffer))))
- result))
-
-(deffoo nnmbox-request-accept-article (group &optional server last)
- (nnmbox-possibly-change-newsgroup group server)
- (nnmail-check-syntax)
- (let ((buf (current-buffer))
- result)
- (goto-char (point-min))
- (if (looking-at "X-From-Line: ")
- (replace-match "From ")
- (insert "From nobody " (current-time-string) "\n"))
- (and
- (nnmail-activate 'nnmbox)
- (progn
- (set-buffer buf)
- (goto-char (point-min))
- (search-forward "\n\n" nil t)
- (forward-line -1)
- (while (re-search-backward "^X-Gnus-Newsgroup: " nil t)
- (delete-region (point) (progn (forward-line 1) (point))))
- (setq result (nnmbox-save-mail (and (stringp group) group))))
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
- (goto-char (point-max))
- (insert-buffer-substring buf)
- (and last (save-buffer))
- result)
- (nnmail-save-active nnmbox-group-alist nnmbox-active-file))
- (car result)))
-
-(deffoo nnmbox-request-replace-article (article group buffer)
- (nnmbox-possibly-change-newsgroup group)
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
- (goto-char (point-min))
- (if (not (search-forward (nnmbox-article-string article) nil t))
- nil
- (nnmbox-delete-mail t t)
- (insert-buffer-substring buffer)
- (save-buffer)
- t)))
-
-(deffoo nnmbox-request-delete-group (group &optional force server)
- (nnmbox-possibly-change-newsgroup group server)
- ;; Delete all articles in GROUP.
- (if (not force)
- () ; Don't delete the articles.
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
- (goto-char (point-min))
- ;; Delete all articles in this group.
- (let ((ident (concat "\nX-Gnus-Newsgroup: " nnmbox-current-group ":"))
- found)
- (while (search-forward ident nil t)
- (setq found t)
- (nnmbox-delete-mail))
- (and found (save-buffer)))))
- ;; Remove the group from all structures.
- (setq nnmbox-group-alist
- (delq (assoc group nnmbox-group-alist) nnmbox-group-alist)
- nnmbox-current-group nil)
- ;; Save the active file.
- (nnmail-save-active nnmbox-group-alist nnmbox-active-file)
- t)
-
-(deffoo nnmbox-request-rename-group (group new-name &optional server)
- (nnmbox-possibly-change-newsgroup group server)
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
- (goto-char (point-min))
- (let ((ident (concat "\nX-Gnus-Newsgroup: " nnmbox-current-group ":"))
- (new-ident (concat "\nX-Gnus-Newsgroup: " new-name ":"))
- found)
- (while (search-forward ident nil t)
- (replace-match new-ident t t)
- (setq found t))
- (and found (save-buffer))))
- (let ((entry (assoc group nnmbox-group-alist)))
- (and entry (setcar entry new-name))
- (setq nnmbox-current-group nil)
- ;; Save the new group alist.
- (nnmail-save-active nnmbox-group-alist nnmbox-active-file)
- t))
-
-
-;;; Internal functions.
-
-;; If FORCE, delete article no matter how many X-Gnus-Newsgroup
-;; headers there are. If LEAVE-DELIM, don't delete the Unix mbox
-;; delimiter line.
-(defun nnmbox-delete-mail (&optional force leave-delim)
- ;; Delete the current X-Gnus-Newsgroup line.
- (or force
- (delete-region
- (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point))))
- ;; Beginning of the article.
- (save-excursion
- (save-restriction
- (narrow-to-region
- (save-excursion
- (re-search-backward (concat "^" message-unix-mail-delimiter) nil t)
- (if leave-delim (progn (forward-line 1) (point))
- (match-beginning 0)))
- (progn
- (forward-line 1)
- (or (and (re-search-forward (concat "^" message-unix-mail-delimiter)
- nil t)
- (if (and (not (bobp)) leave-delim)
- (progn (forward-line -2) (point))
- (match-beginning 0)))
- (point-max))))
- (goto-char (point-min))
- ;; Only delete the article if no other groups owns it as well.
- (if (or force (not (re-search-forward "^X-Gnus-Newsgroup: " nil t)))
- (delete-region (point-min) (point-max))))))
-
-(defun nnmbox-possibly-change-newsgroup (newsgroup &optional server)
- (when (and server
- (not (nnmbox-server-opened server)))
- (nnmbox-open-server server))
- (if (or (not nnmbox-mbox-buffer)
- (not (buffer-name nnmbox-mbox-buffer)))
- (save-excursion
- (set-buffer (setq nnmbox-mbox-buffer
- (nnheader-find-file-noselect
- nnmbox-mbox-file nil 'raw)))
- (buffer-disable-undo (current-buffer))))
- (if (not nnmbox-group-alist)
- (nnmail-activate 'nnmbox))
- (if newsgroup
- (if (assoc newsgroup nnmbox-group-alist)
- (setq nnmbox-current-group newsgroup))
- t))
-
-(defun nnmbox-article-string (article)
- (if (numberp article)
- (concat "\nX-Gnus-Newsgroup: " nnmbox-current-group ":"
- (int-to-string article) " ")
- (concat "\nMessage-ID: " article)))
-
-(defun nnmbox-article-group-number ()
- (save-excursion
- (goto-char (point-min))
- (and (re-search-forward "^X-Gnus-Newsgroup: +\\([^:]+\\):\\([0-9]+\\) "
- nil t)
- (cons (buffer-substring (match-beginning 1) (match-end 1))
- (string-to-int
- (buffer-substring (match-beginning 2) (match-end 2)))))))
-
-(defun nnmbox-save-mail (&optional group)
- "Called narrowed to an article."
- (let* ((nnmail-split-methods
- (if group (list (list group "")) nnmail-split-methods))
- (group-art (nreverse (nnmail-article-group 'nnmbox-active-number)))
- (delim (concat "^" message-unix-mail-delimiter)))
- (goto-char (point-min))
- ;; This might come from somewhere else.
- (unless (looking-at delim)
- (insert "From nobody " (current-time-string) "\n")
- (goto-char (point-min)))
- ;; Quote all "From " lines in the article.
- (forward-line 1)
- (while (re-search-forward delim nil t)
- (beginning-of-line)
- (insert "> "))
- (nnmail-insert-lines)
- (nnmail-insert-xref group-art)
- (nnmbox-insert-newsgroup-line group-art)
- (run-hooks 'nnmail-prepare-save-mail-hook)
- (run-hooks 'nnmbox-prepare-save-mail-hook)
- group-art))
-
-(defun nnmbox-insert-newsgroup-line (group-art)
- (save-excursion
- (goto-char (point-min))
- (if (search-forward "\n\n" nil t)
- (progn
- (forward-char -1)
- (while group-art
- (insert (format "X-Gnus-Newsgroup: %s:%d %s\n"
- (caar group-art) (cdar group-art)
- (current-time-string)))
- (setq group-art (cdr group-art)))))
- t))
-
-(defun nnmbox-active-number (group)
- ;; Find the next article number in GROUP.
- (let ((active (cadr (assoc group nnmbox-group-alist))))
- (if active
- (setcdr active (1+ (cdr active)))
- ;; This group is new, so we create a new entry for it.
- ;; This might be a bit naughty... creating groups on the drop of
- ;; a hat, but I don't know...
- (setq nnmbox-group-alist (cons (list group (setq active (cons 1 1)))
- nnmbox-group-alist)))
- (cdr active)))
-
-(defun nnmbox-read-mbox ()
- (nnmail-activate 'nnmbox)
- (if (not (file-exists-p nnmbox-mbox-file))
- (write-region 1 1 nnmbox-mbox-file t 'nomesg))
- (if (and nnmbox-mbox-buffer
- (buffer-name nnmbox-mbox-buffer)
- (save-excursion
- (set-buffer nnmbox-mbox-buffer)
- (= (buffer-size) (nnheader-file-size nnmbox-mbox-file))))
- ()
- (save-excursion
- (let ((delim (concat "^" message-unix-mail-delimiter))
- (alist nnmbox-group-alist)
- start end number)
- (set-buffer (setq nnmbox-mbox-buffer
- (nnheader-find-file-noselect
- nnmbox-mbox-file nil 'raw)))
- (buffer-disable-undo (current-buffer))
-
- ;; Go through the group alist and compare against
- ;; the mbox file.
- (while alist
- (goto-char (point-max))
- (when (and (re-search-backward
- (format "^X-Gnus-Newsgroup: %s:\\([0-9]+\\) "
- (caar alist)) nil t)
- (>= (setq number
- (string-to-number
- (buffer-substring
- (match-beginning 1) (match-end 1))))
- (cdadar alist)))
- (setcdr (cadar alist) (1+ number)))
- (setq alist (cdr alist)))
-
- (goto-char (point-min))
- (while (re-search-forward delim nil t)
- (setq start (match-beginning 0))
- (if (not (search-forward "\nX-Gnus-Newsgroup: "
- (save-excursion
- (setq end
- (or
- (and
- (re-search-forward delim nil t)
- (match-beginning 0))
- (point-max))))
- t))
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (nnmbox-save-mail))))
- (goto-char end))))))
-
-(provide 'nnmbox)
-
-;;; nnmbox.el ends here
diff --git a/lisp/nnmh.el b/lisp/nnmh.el
deleted file mode 100644
index cc9adab8996..00000000000
--- a/lisp/nnmh.el
+++ /dev/null
@@ -1,520 +0,0 @@
-;;; nnmh.el --- mhspool access for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: news, mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Based on nnspool.el by Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>.
-;; For an overview of what the interface functions do, please see the
-;; Gnus sources.
-
-;;; Code:
-
-(require 'nnheader)
-(require 'nnmail)
-(require 'gnus)
-(require 'nnoo)
-(eval-and-compile (require 'cl))
-
-(nnoo-declare nnmh)
-
-(defvoo nnmh-directory message-directory
- "*Mail spool directory.")
-
-(defvoo nnmh-get-new-mail t
- "*If non-nil, nnmh will check the incoming mail file and split the mail.")
-
-(defvoo nnmh-prepare-save-mail-hook nil
- "*Hook run narrowed to an article before saving.")
-
-(defvoo nnmh-be-safe nil
- "*If non-nil, nnmh will check all articles to make sure whether they are new or not.")
-
-
-
-(defconst nnmh-version "nnmh 1.0"
- "nnmh version.")
-
-(defvoo nnmh-current-directory nil
- "Current news group directory.")
-
-(defvoo nnmh-status-string "")
-(defvoo nnmh-group-alist nil)
-
-
-
-;;; Interface functions.
-
-(nnoo-define-basics nnmh)
-
-(deffoo nnmh-retrieve-headers (articles &optional newsgroup server fetch-old)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (let* ((file nil)
- (number (length articles))
- (large (and (numberp nnmail-large-newsgroup)
- (> number nnmail-large-newsgroup)))
- (count 0)
- beg article)
- (nnmh-possibly-change-directory newsgroup server)
- ;; We don't support fetching by Message-ID.
- (if (stringp (car articles))
- 'headers
- (while articles
- (when (and (file-exists-p
- (setq file (concat (file-name-as-directory
- nnmh-current-directory)
- (int-to-string
- (setq article (pop articles))))))
- (not (file-directory-p file)))
- (insert (format "221 %d Article retrieved.\n" article))
- (setq beg (point))
- (nnheader-insert-head file)
- (goto-char beg)
- (if (search-forward "\n\n" nil t)
- (forward-char -1)
- (goto-char (point-max))
- (insert "\n\n"))
- (insert ".\n")
- (delete-region (point) (point-max)))
- (setq count (1+ count))
-
- (and large
- (zerop (% count 20))
- (message "nnmh: Receiving headers... %d%%"
- (/ (* count 100) number))))
-
- (and large (message "nnmh: Receiving headers...done"))
-
- (nnheader-fold-continuation-lines)
- 'headers))))
-
-(deffoo nnmh-open-server (server &optional defs)
- (nnoo-change-server 'nnmh server defs)
- (when (not (file-exists-p nnmh-directory))
- (condition-case ()
- (make-directory nnmh-directory t)
- (error t)))
- (cond
- ((not (file-exists-p nnmh-directory))
- (nnmh-close-server)
- (nnheader-report 'nnmh "Couldn't create directory: %s" nnmh-directory))
- ((not (file-directory-p (file-truename nnmh-directory)))
- (nnmh-close-server)
- (nnheader-report 'nnmh "Not a directory: %s" nnmh-directory))
- (t
- (nnheader-report 'nnmh "Opened server %s using directory %s"
- server nnmh-directory)
- t)))
-
-(deffoo nnmh-request-article (id &optional newsgroup server buffer)
- (nnmh-possibly-change-directory newsgroup server)
- (let ((file (if (stringp id)
- nil
- (concat nnmh-current-directory (int-to-string id))))
- (nntp-server-buffer (or buffer nntp-server-buffer)))
- (and (stringp file)
- (file-exists-p file)
- (not (file-directory-p file))
- (save-excursion (nnmail-find-file file))
- (string-to-int (file-name-nondirectory file)))))
-
-(deffoo nnmh-request-group (group &optional server dont-check)
- (let ((pathname (nnmail-group-pathname group nnmh-directory))
- dir)
- (cond
- ((not (file-directory-p pathname))
- (nnheader-report
- 'nnmh "Can't select group (no such directory): %s" group))
- (t
- (setq nnmh-current-directory pathname)
- (and nnmh-get-new-mail
- nnmh-be-safe
- (nnmh-update-gnus-unreads group))
- (cond
- (dont-check
- (nnheader-report 'nnmh "Selected group %s" group)
- t)
- (t
- ;; Re-scan the directory if it's on a foreign system.
- (nnheader-re-read-dir pathname)
- (setq dir
- (sort
- (mapcar (lambda (name) (string-to-int name))
- (directory-files pathname nil "^[0-9]+$" t))
- '<))
- (cond
- (dir
- (nnheader-report 'nnmh "Selected group %s" group)
- (nnheader-insert
- "211 %d %d %d %s\n" (length dir) (car dir)
- (progn (while (cdr dir) (setq dir (cdr dir))) (car dir))
- group))
- (t
- (nnheader-report 'nnmh "Empty group %s" group)
- (nnheader-insert (format "211 0 1 0 %s\n" group))))))))))
-
-(deffoo nnmh-request-scan (&optional group server)
- (nnmail-get-new-mail 'nnmh nil nnmh-directory group))
-
-(deffoo nnmh-request-list (&optional server dir)
- (nnheader-insert "")
- (let ((nnmh-toplev
- (or dir (file-truename (file-name-as-directory nnmh-directory)))))
- (nnmh-request-list-1 nnmh-toplev))
- (setq nnmh-group-alist (nnmail-get-active))
- t)
-
-(defvar nnmh-toplev)
-(defun nnmh-request-list-1 (dir)
- (setq dir (expand-file-name dir))
- ;; Recurse down all directories.
- (let ((dirs (and (file-readable-p dir)
- (> (nth 1 (file-attributes (file-chase-links dir))) 2)
- (directory-files dir t nil t)))
- dir)
- ;; Recurse down directories.
- (while (setq dir (pop dirs))
- (when (and (not (member (file-name-nondirectory dir) '("." "..")))
- (file-directory-p dir)
- (file-readable-p dir))
- (nnmh-request-list-1 dir))))
- ;; For each directory, generate an active file line.
- (unless (string= (expand-file-name nnmh-toplev) dir)
- (let ((files (mapcar
- (lambda (name) (string-to-int name))
- (directory-files dir nil "^[0-9]+$" t))))
- (when files
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-max))
- (insert
- (format
- "%s %d %d y\n"
- (progn
- (string-match
- (regexp-quote
- (file-truename (file-name-as-directory
- (expand-file-name nnmh-toplev)))) dir)
- (nnheader-replace-chars-in-string
- (substring dir (match-end 0)) ?/ ?.))
- (apply 'max files)
- (apply 'min files)))))))
- t)
-
-(deffoo nnmh-request-newgroups (date &optional server)
- (nnmh-request-list server))
-
-(deffoo nnmh-request-expire-articles (articles newsgroup &optional server force)
- (nnmh-possibly-change-directory newsgroup server)
- (let* ((active-articles
- (mapcar
- (function
- (lambda (name)
- (string-to-int name)))
- (directory-files nnmh-current-directory nil "^[0-9]+$" t)))
- (is-old t)
- article rest mod-time)
- (nnmail-activate 'nnmh)
-
- (while (and articles is-old)
- (setq article (concat nnmh-current-directory
- (int-to-string (car articles))))
- (if (setq mod-time (nth 5 (file-attributes article)))
- (if (and (nnmh-deletable-article-p newsgroup (car articles))
- (setq is-old
- (nnmail-expired-article-p newsgroup mod-time force)))
- (progn
- (nnheader-message 5 "Deleting article %s in %s..."
- article newsgroup)
- (condition-case ()
- (funcall nnmail-delete-file-function article)
- (file-error
- (nnheader-message 1 "Couldn't delete article %s in %s"
- article newsgroup)
- (setq rest (cons (car articles) rest)))))
- (setq rest (cons (car articles) rest))))
- (setq articles (cdr articles)))
- (message "")
- (nconc rest articles)))
-
-(deffoo nnmh-close-group (group &optional server)
- t)
-
-(deffoo nnmh-request-move-article
- (article group server accept-form &optional last)
- (let ((buf (get-buffer-create " *nnmh move*"))
- result)
- (and
- (nnmh-deletable-article-p group article)
- (nnmh-request-article article group server)
- (save-excursion
- (set-buffer buf)
- (insert-buffer-substring nntp-server-buffer)
- (setq result (eval accept-form))
- (kill-buffer (current-buffer))
- result)
- (progn
- (nnmh-possibly-change-directory group server)
- (condition-case ()
- (funcall nnmail-delete-file-function
- (concat nnmh-current-directory (int-to-string article)))
- (file-error nil))))
- result))
-
-(deffoo nnmh-request-accept-article (group &optional server last noinsert)
- (nnmh-possibly-change-directory group server)
- (nnmail-check-syntax)
- (if (stringp group)
- (and
- (nnmail-activate 'nnmh)
- ;; We trick the choosing function into believing that only one
- ;; group is available.
- (let ((nnmail-split-methods (list (list group ""))))
- (car (nnmh-save-mail noinsert))))
- (and
- (nnmail-activate 'nnmh)
- (car (nnmh-save-mail noinsert)))))
-
-(deffoo nnmh-request-replace-article (article group buffer)
- (nnmh-possibly-change-directory group)
- (save-excursion
- (set-buffer buffer)
- (nnmh-possibly-create-directory group)
- (condition-case ()
- (progn
- (write-region
- (point-min) (point-max)
- (concat nnmh-current-directory (int-to-string article))
- nil (if (nnheader-be-verbose 5) nil 'nomesg))
- t)
- (error nil))))
-
-(deffoo nnmh-request-create-group (group &optional server)
- (nnmail-activate 'nnmh)
- (or (assoc group nnmh-group-alist)
- (let (active)
- (setq nnmh-group-alist (cons (list group (setq active (cons 1 0)))
- nnmh-group-alist))
- (nnmh-possibly-create-directory group)
- (nnmh-possibly-change-directory group server)
- (let ((articles (mapcar
- (lambda (file)
- (string-to-int file))
- (directory-files
- nnmh-current-directory nil "^[0-9]+$"))))
- (and articles
- (progn
- (setcar active (apply 'min articles))
- (setcdr active (apply 'max articles)))))))
- t)
-
-(deffoo nnmh-request-delete-group (group &optional force server)
- (nnmh-possibly-change-directory group server)
- ;; Delete all articles in GROUP.
- (if (not force)
- () ; Don't delete the articles.
- (let ((articles (directory-files nnmh-current-directory t "^[0-9]+$")))
- (while articles
- (and (file-writable-p (car articles))
- (progn
- (nnheader-message 5 "Deleting article %s in %s..."
- (car articles) group)
- (funcall nnmail-delete-file-function (car articles))))
- (setq articles (cdr articles))))
- ;; Try to delete the directory itself.
- (condition-case ()
- (delete-directory nnmh-current-directory)
- (error nil)))
- ;; Remove the group from all structures.
- (setq nnmh-group-alist
- (delq (assoc group nnmh-group-alist) nnmh-group-alist)
- nnmh-current-directory nil)
- t)
-
-(deffoo nnmh-request-rename-group (group new-name &optional server)
- (nnmh-possibly-change-directory group server)
- ;; Rename directory.
- (and (file-writable-p nnmh-current-directory)
- (condition-case ()
- (progn
- (rename-file
- (directory-file-name nnmh-current-directory)
- (directory-file-name
- (nnmail-group-pathname new-name nnmh-directory)))
- t)
- (error nil))
- ;; That went ok, so we change the internal structures.
- (let ((entry (assoc group nnmh-group-alist)))
- (and entry (setcar entry new-name))
- (setq nnmh-current-directory nil)
- t)))
-
-
-;;; Internal functions.
-
-(defun nnmh-possibly-change-directory (newsgroup &optional server)
- (when (and server
- (not (nnmh-server-opened server)))
- (nnmh-open-server server))
- (if newsgroup
- (let ((pathname (nnmail-group-pathname newsgroup nnmh-directory)))
- (if (file-directory-p pathname)
- (setq nnmh-current-directory pathname)
- (error "No such newsgroup: %s" newsgroup)))))
-
-(defun nnmh-possibly-create-directory (group)
- (let (dir dirs)
- (setq dir (nnmail-group-pathname group nnmh-directory))
- (while (not (file-directory-p dir))
- (setq dirs (cons dir dirs))
- (setq dir (file-name-directory (directory-file-name dir))))
- (while dirs
- (if (make-directory (directory-file-name (car dirs)))
- (error "Could not create directory %s" (car dirs)))
- (nnheader-message 5 "Creating mail directory %s" (car dirs))
- (setq dirs (cdr dirs)))))
-
-(defun nnmh-save-mail (&optional noinsert)
- "Called narrowed to an article."
- (let ((group-art (nreverse (nnmail-article-group 'nnmh-active-number))))
- (unless noinsert
- (nnmail-insert-lines)
- (nnmail-insert-xref group-art))
- (run-hooks 'nnmail-prepare-save-mail-hook)
- (run-hooks 'nnmh-prepare-save-mail-hook)
- (goto-char (point-min))
- (while (looking-at "From ")
- (replace-match "X-From-Line: ")
- (forward-line 1))
- ;; We save the article in all the newsgroups it belongs in.
- (let ((ga group-art)
- first)
- (while ga
- (nnmh-possibly-create-directory (caar ga))
- (let ((file (concat (nnmail-group-pathname
- (caar ga) nnmh-directory)
- (int-to-string (cdar ga)))))
- (if first
- ;; It was already saved, so we just make a hard link.
- (funcall nnmail-crosspost-link-function first file t)
- ;; Save the article.
- (write-region (point-min) (point-max) file nil nil)
- (setq first file)))
- (setq ga (cdr ga))))
- group-art))
-
-(defun nnmh-active-number (group)
- "Compute the next article number in GROUP."
- (let ((active (cadr (assoc group nnmh-group-alist))))
- ;; The group wasn't known to nnmh, so we just create an active
- ;; entry for it.
- (or active
- (progn
- (setq active (cons 1 0))
- (setq nnmh-group-alist (cons (list group active) nnmh-group-alist))))
- (setcdr active (1+ (cdr active)))
- (while (file-exists-p
- (concat (nnmail-group-pathname group nnmh-directory)
- (int-to-string (cdr active))))
- (setcdr active (1+ (cdr active))))
- (cdr active)))
-
-(defun nnmh-update-gnus-unreads (group)
- ;; Go through the .nnmh-articles file and compare with the actual
- ;; articles in this folder. The articles that are "new" will be
- ;; marked as unread by Gnus.
- (let* ((dir nnmh-current-directory)
- (files (sort (mapcar (function (lambda (name) (string-to-int name)))
- (directory-files nnmh-current-directory
- nil "^[0-9]+$" t)) '<))
- (nnmh-file (concat dir ".nnmh-articles"))
- new articles)
- ;; Load the .nnmh-articles file.
- (if (file-exists-p nnmh-file)
- (setq articles
- (let (nnmh-newsgroup-articles)
- (condition-case nil (load nnmh-file nil t t) (error nil))
- nnmh-newsgroup-articles)))
- ;; Add all new articles to the `new' list.
- (let ((art files))
- (while art
- (if (not (assq (car art) articles)) (setq new (cons (car art) new)))
- (setq art (cdr art))))
- ;; Remove all deleted articles.
- (let ((art articles))
- (while art
- (if (not (memq (caar art) files))
- (setq articles (delq (car art) articles)))
- (setq art (cdr art))))
- ;; Check whether the highest-numbered articles really are the ones
- ;; that Gnus thinks they are by looking at the time-stamps.
- (let ((art articles))
- (while (and art
- (not (equal
- (nth 5 (file-attributes
- (concat dir (int-to-string (caar art)))))
- (cdar art))))
- (setq articles (delq (car art) articles))
- (setq new (cons (caar art) new))
- (setq art (cdr art))))
- ;; Go through all the new articles and add them, and their
- ;; time-stamps to the list.
- (let ((n new))
- (while n
- (setq articles
- (cons (cons
- (car n)
- (nth 5 (file-attributes
- (concat dir (int-to-string (car n))))))
- articles))
- (setq n (cdr n))))
- ;; Make Gnus mark all new articles as unread.
- (or (zerop (length new))
- (gnus-make-articles-unread
- (gnus-group-prefixed-name group (list 'nnmh ""))
- (setq new (sort new '<))))
- ;; Sort the article list with highest numbers first.
- (setq articles (sort articles (lambda (art1 art2)
- (> (car art1) (car art2)))))
- ;; Finally write this list back to the .nnmh-articles file.
- (save-excursion
- (set-buffer (get-buffer-create "*nnmh out*"))
- (insert ";; Gnus article active file for " group "\n\n")
- (insert "(setq nnmh-newsgroup-articles '")
- (insert (prin1-to-string articles) ")\n")
- (write-region (point-min) (point-max) nnmh-file nil 'nomesg)
- (kill-buffer (current-buffer)))))
-
-(defun nnmh-deletable-article-p (group article)
- "Say whether ARTICLE in GROUP can be deleted."
- (let ((path (concat nnmh-current-directory (int-to-string article))))
- (and (file-writable-p path)
- (or (not nnmail-keep-last-article)
- (not (eq (cdr (nth 1 (assoc group nnmh-group-alist)))
- article))))))
-
-(provide 'nnmh)
-
-;;; nnmh.el ends here
diff --git a/lisp/nnml.el b/lisp/nnml.el
deleted file mode 100644
index 89c97ee9b95..00000000000
--- a/lisp/nnml.el
+++ /dev/null
@@ -1,764 +0,0 @@
-;;; nnml.el --- mail spool access for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: news, mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Based on nnspool.el by Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>.
-;; For an overview of what the interface functions do, please see the
-;; Gnus sources.
-
-;;; Code:
-
-(require 'nnheader)
-(require 'nnmail)
-(require 'nnoo)
-(require 'cl)
-
-(nnoo-declare nnml)
-
-(defvoo nnml-directory message-directory
- "Mail spool directory.")
-
-(defvoo nnml-active-file
- (concat (file-name-as-directory nnml-directory) "active")
- "Mail active file.")
-
-(defvoo nnml-newsgroups-file
- (concat (file-name-as-directory nnml-directory) "newsgroups")
- "Mail newsgroups description file.")
-
-(defvoo nnml-get-new-mail t
- "If non-nil, nnml will check the incoming mail file and split the mail.")
-
-(defvoo nnml-nov-is-evil nil
- "If non-nil, Gnus will never generate and use nov databases for mail groups.
-Using nov databases will speed up header fetching considerably.
-This variable shouldn't be flipped much. If you have, for some reason,
-set this to t, and want to set it to nil again, you should always run
-the `nnml-generate-nov-databases' command. The function will go
-through all nnml directories and generate nov databases for them
-all. This may very well take some time.")
-
-(defvoo nnml-prepare-save-mail-hook nil
- "Hook run narrowed to an article before saving.")
-
-(defvoo nnml-inhibit-expiry nil
- "If non-nil, inhibit expiry.")
-
-
-
-
-(defconst nnml-version "nnml 1.0"
- "nnml version.")
-
-(defvoo nnml-nov-file-name ".overview")
-
-(defvoo nnml-current-directory nil)
-(defvoo nnml-current-group nil)
-(defvoo nnml-status-string "")
-(defvoo nnml-nov-buffer-alist nil)
-(defvoo nnml-group-alist nil)
-(defvoo nnml-active-timestamp nil)
-(defvoo nnml-article-file-alist nil)
-
-(defvoo nnml-generate-active-function 'nnml-generate-active-info)
-
-
-
-;;; Interface functions.
-
-(nnoo-define-basics nnml)
-
-(deffoo nnml-retrieve-headers (sequence &optional newsgroup server fetch-old)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (let ((file nil)
- (number (length sequence))
- (count 0)
- beg article)
- (if (stringp (car sequence))
- 'headers
- (nnml-possibly-change-directory newsgroup server)
- (unless nnml-article-file-alist
- (setq nnml-article-file-alist
- (nnheader-article-to-file-alist nnml-current-directory)))
- (if (nnml-retrieve-headers-with-nov sequence fetch-old)
- 'nov
- (while sequence
- (setq article (car sequence))
- (setq file
- (concat nnml-current-directory
- (or (cdr (assq article nnml-article-file-alist))
- "")))
- (if (and (file-exists-p file)
- (not (file-directory-p file)))
- (progn
- (insert (format "221 %d Article retrieved.\n" article))
- (setq beg (point))
- (nnheader-insert-head file)
- (goto-char beg)
- (if (search-forward "\n\n" nil t)
- (forward-char -1)
- (goto-char (point-max))
- (insert "\n\n"))
- (insert ".\n")
- (delete-region (point) (point-max))))
- (setq sequence (cdr sequence))
- (setq count (1+ count))
- (and (numberp nnmail-large-newsgroup)
- (> number nnmail-large-newsgroup)
- (zerop (% count 20))
- (nnheader-message 6 "nnml: Receiving headers... %d%%"
- (/ (* count 100) number))))
-
- (and (numberp nnmail-large-newsgroup)
- (> number nnmail-large-newsgroup)
- (nnheader-message 6 "nnml: Receiving headers...done"))
-
- (nnheader-fold-continuation-lines)
- 'headers)))))
-
-(deffoo nnml-open-server (server &optional defs)
- (nnoo-change-server 'nnml server defs)
- (when (not (file-exists-p nnml-directory))
- (condition-case ()
- (make-directory nnml-directory t)
- (error t)))
- (cond
- ((not (file-exists-p nnml-directory))
- (nnml-close-server)
- (nnheader-report 'nnml "Couldn't create directory: %s" nnml-directory))
- ((not (file-directory-p (file-truename nnml-directory)))
- (nnml-close-server)
- (nnheader-report 'nnml "Not a directory: %s" nnml-directory))
- (t
- (nnheader-report 'nnml "Opened server %s using directory %s"
- server nnml-directory)
- t)))
-
-(deffoo nnml-request-article (id &optional newsgroup server buffer)
- (nnml-possibly-change-directory newsgroup server)
- (let* ((nntp-server-buffer (or buffer nntp-server-buffer))
- file path gpath group-num)
- (if (stringp id)
- (when (and (setq group-num (nnml-find-group-number id))
- (setq file (cdr
- (assq (cdr group-num)
- (nnheader-article-to-file-alist
- (setq gpath
- (nnmail-group-pathname
- (car group-num)
- nnml-directory)))))))
- (setq path (concat gpath (int-to-string (cdr group-num)))))
- (unless nnml-article-file-alist
- (setq nnml-article-file-alist
- (nnheader-article-to-file-alist nnml-current-directory)))
- (when (setq file (cdr (assq id nnml-article-file-alist)))
- (setq path (concat nnml-current-directory file))))
- (cond
- ((not path)
- (nnheader-report 'nnml "No such article: %s" id))
- ((not (file-exists-p path))
- (nnheader-report 'nnml "No such file: %s" path))
- ((file-directory-p path)
- (nnheader-report 'nnml "File is a directory: %s" path))
- ((not (save-excursion (nnmail-find-file path)))
- (nnheader-report 'nnml "Couldn't read file: %s" path))
- (t
- (nnheader-report 'nnml "Article %s retrieved" id)
- ;; We return the article number.
- (cons newsgroup (string-to-int (file-name-nondirectory path)))))))
-
-(deffoo nnml-request-group (group &optional server dont-check)
- (cond
- ((not (nnml-possibly-change-directory group server))
- (nnheader-report 'nnml "Invalid group (no such directory)"))
- ((not (file-directory-p nnml-current-directory))
- (nnheader-report 'nnml "%s is not a directory" nnml-current-directory))
- (dont-check
- (nnheader-report 'nnml "Group %s selected" group)
- t)
- (t
- (nnmail-activate 'nnml)
- (let ((active (nth 1 (assoc group nnml-group-alist))))
- (if (not active)
- (nnheader-report 'nnml "No such group: %s" group)
- (nnheader-report 'nnml "Selected group %s" group)
- (nnheader-insert "211 %d %d %d %s\n"
- (max (1+ (- (cdr active) (car active))) 0)
- (car active) (cdr active) group))))))
-
-(deffoo nnml-request-scan (&optional group server)
- (setq nnml-article-file-alist nil)
- (nnmail-get-new-mail 'nnml 'nnml-save-nov nnml-directory group))
-
-(deffoo nnml-close-group (group &optional server)
- (setq nnml-article-file-alist nil)
- t)
-
-(deffoo nnml-request-create-group (group &optional server)
- (nnmail-activate 'nnml)
- (or (assoc group nnml-group-alist)
- (let (active)
- (setq nnml-group-alist (cons (list group (setq active (cons 1 0)))
- nnml-group-alist))
- (nnml-possibly-create-directory group)
- (nnml-possibly-change-directory group server)
- (let ((articles
- (nnheader-directory-articles nnml-current-directory )))
- (and articles
- (progn
- (setcar active (apply 'min articles))
- (setcdr active (apply 'max articles)))))
- (nnmail-save-active nnml-group-alist nnml-active-file)))
- t)
-
-(deffoo nnml-request-list (&optional server)
- (save-excursion
- (nnmail-find-file nnml-active-file)
- (setq nnml-group-alist (nnmail-get-active))))
-
-(deffoo nnml-request-newgroups (date &optional server)
- (nnml-request-list server))
-
-(deffoo nnml-request-list-newsgroups (&optional server)
- (save-excursion
- (nnmail-find-file nnml-newsgroups-file)))
-
-(deffoo nnml-request-expire-articles (articles newsgroup &optional server force)
- (nnml-possibly-change-directory newsgroup server)
- (let* ((active-articles
- (nnheader-directory-articles nnml-current-directory))
- (is-old t)
- article rest mod-time number)
- (nnmail-activate 'nnml)
-
- (unless nnml-article-file-alist
- (setq nnml-article-file-alist
- (nnheader-article-to-file-alist nnml-current-directory)))
-
- (while (and articles is-old)
- (setq article (concat nnml-current-directory
- (int-to-string
- (setq number (pop articles)))))
- (when (setq mod-time (nth 5 (file-attributes article)))
- (if (and (nnml-deletable-article-p newsgroup number)
- (setq is-old
- (nnmail-expired-article-p newsgroup mod-time force
- nnml-inhibit-expiry)))
- (progn
- (nnheader-message 5 "Deleting article %s in %s..."
- article newsgroup)
- (condition-case ()
- (funcall nnmail-delete-file-function article)
- (file-error
- (push number rest)))
- (setq active-articles (delq number active-articles))
- (nnml-nov-delete-article newsgroup number))
- (push number rest))))
- (let ((active (nth 1 (assoc newsgroup nnml-group-alist))))
- (when active
- (setcar active (or (and active-articles
- (apply 'min active-articles))
- (1+ (cdr active)))))
- (nnmail-save-active nnml-group-alist nnml-active-file))
- (nnml-save-nov)
- (message "")
- (nconc rest articles)))
-
-(deffoo nnml-request-move-article
- (article group server accept-form &optional last)
- (let ((buf (get-buffer-create " *nnml move*"))
- result)
- (nnml-possibly-change-directory group server)
- (unless nnml-article-file-alist
- (setq nnml-article-file-alist
- (nnheader-article-to-file-alist nnml-current-directory)))
- (and
- (nnml-deletable-article-p group article)
- (nnml-request-article article group server)
- (save-excursion
- (set-buffer buf)
- (insert-buffer-substring nntp-server-buffer)
- (setq result (eval accept-form))
- (kill-buffer (current-buffer))
- result)
- (progn
- (nnml-possibly-change-directory group server)
- (condition-case ()
- (funcall nnmail-delete-file-function
- (concat nnml-current-directory
- (int-to-string article)))
- (file-error nil))
- (nnml-nov-delete-article group article)
- (and last (nnml-save-nov))))
- result))
-
-(deffoo nnml-request-accept-article (group &optional server last)
- (nnml-possibly-change-directory group server)
- (nnmail-check-syntax)
- (let (result)
- (if (stringp group)
- (and
- (nnmail-activate 'nnml)
- ;; We trick the choosing function into believing that only one
- ;; group is available.
- (let ((nnmail-split-methods (list (list group ""))))
- (setq result (car (nnml-save-mail))))
- (progn
- (nnmail-save-active nnml-group-alist nnml-active-file)
- (and last (nnml-save-nov))))
- (and
- (nnmail-activate 'nnml)
- (setq result (car (nnml-save-mail)))
- (progn
- (nnmail-save-active nnml-group-alist nnml-active-file)
- (and last (nnml-save-nov)))))
- result))
-
-(deffoo nnml-request-replace-article (article group buffer)
- (nnml-possibly-change-directory group)
- (save-excursion
- (set-buffer buffer)
- (nnml-possibly-create-directory group)
- (let ((chars (nnmail-insert-lines))
- (art (concat (int-to-string article) "\t"))
- headers)
- (when (condition-case ()
- (progn
- (write-region
- (point-min) (point-max)
- (concat nnml-current-directory (int-to-string article))
- nil (if (nnheader-be-verbose 5) nil 'nomesg))
- t)
- (error nil))
- (setq headers (nnml-parse-head chars article))
- ;; Replace the NOV line in the NOV file.
- (save-excursion
- (set-buffer (nnml-open-nov group))
- (goto-char (point-min))
- (if (or (looking-at art)
- (search-forward (concat "\n" art) nil t))
- ;; Delete the old NOV line.
- (delete-region (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point)))
- ;; The line isn't here, so we have to find out where
- ;; we should insert it. (This situation should never
- ;; occur, but one likes to make sure...)
- (while (and (looking-at "[0-9]+\t")
- (< (string-to-int
- (buffer-substring
- (match-beginning 0) (match-end 0)))
- article)
- (zerop (forward-line 1)))))
- (beginning-of-line)
- (nnheader-insert-nov headers)
- (nnml-save-nov)
- t)))))
-
-(deffoo nnml-request-delete-group (group &optional force server)
- (nnml-possibly-change-directory group server)
- (when force
- ;; Delete all articles in GROUP.
- (let ((articles
- (directory-files
- nnml-current-directory t
- (concat nnheader-numerical-short-files
- "\\|" (regexp-quote nnml-nov-file-name) "$")))
- article)
- (while articles
- (setq article (pop articles))
- (when (file-writable-p article)
- (nnheader-message 5 "Deleting article %s in %s..." article group)
- (funcall nnmail-delete-file-function article))))
- ;; Try to delete the directory itself.
- (condition-case ()
- (delete-directory nnml-current-directory)
- (error nil)))
- ;; Remove the group from all structures.
- (setq nnml-group-alist
- (delq (assoc group nnml-group-alist) nnml-group-alist)
- nnml-current-group nil
- nnml-current-directory nil)
- ;; Save the active file.
- (nnmail-save-active nnml-group-alist nnml-active-file)
- t)
-
-(deffoo nnml-request-rename-group (group new-name &optional server)
- (nnml-possibly-change-directory group server)
- ;; Rename directory.
- (and (file-writable-p nnml-current-directory)
- (condition-case ()
- (let ((parent
- (file-name-directory
- (directory-file-name
- (nnmail-group-pathname new-name nnml-directory)))))
- (unless (file-exists-p parent)
- (make-directory parent t))
- (rename-file
- (directory-file-name nnml-current-directory)
- (directory-file-name
- (nnmail-group-pathname new-name nnml-directory)))
- t)
- (error nil))
- ;; That went ok, so we change the internal structures.
- (let ((entry (assoc group nnml-group-alist)))
- (and entry (setcar entry new-name))
- (setq nnml-current-directory nil
- nnml-current-group nil)
- ;; Save the new group alist.
- (nnmail-save-active nnml-group-alist nnml-active-file)
- t)))
-
-
-;;; Internal functions.
-
-(defun nnml-deletable-article-p (group article)
- "Say whether ARTICLE in GROUP can be deleted."
- (let (file path)
- (when (setq file (cdr (assq article nnml-article-file-alist)))
- (setq path (concat nnml-current-directory file))
- (and (file-writable-p path)
- (or (not nnmail-keep-last-article)
- (not (eq (cdr (nth 1 (assoc group nnml-group-alist)))
- article)))))))
-
-;; Find an article number in the current group given the Message-ID.
-(defun nnml-find-group-number (id)
- (save-excursion
- (set-buffer (get-buffer-create " *nnml id*"))
- (buffer-disable-undo (current-buffer))
- (let ((alist nnml-group-alist)
- number)
- ;; We want to look through all .overview files, but we want to
- ;; start with the one in the current directory. It seems most
- ;; likely that the article we are looking for is in that group.
- (if (setq number (nnml-find-id nnml-current-group id))
- (cons nnml-current-group number)
- ;; It wasn't there, so we look through the other groups as well.
- (while (and (not number)
- alist)
- (or (string= (caar alist) nnml-current-group)
- (setq number (nnml-find-id (caar alist) id)))
- (or number
- (setq alist (cdr alist))))
- (and number
- (cons (caar alist) number))))))
-
-(defun nnml-find-id (group id)
- (erase-buffer)
- (let ((nov (concat (nnmail-group-pathname group nnml-directory)
- nnml-nov-file-name))
- number found)
- (when (file-exists-p nov)
- (insert-file-contents nov)
- (while (and (not found)
- (search-forward id nil t)) ; We find the ID.
- ;; And the id is in the fourth field.
- (if (search-backward
- "\t" (save-excursion (beginning-of-line) (point)) t 4)
- (progn
- (beginning-of-line)
- (setq found t)
- ;; We return the article number.
- (setq number
- (condition-case ()
- (read (current-buffer))
- (error nil))))))
- number)))
-
-(defun nnml-retrieve-headers-with-nov (articles &optional fetch-old)
- (if (or gnus-nov-is-evil nnml-nov-is-evil)
- nil
- (let ((first (car articles))
- (last (progn (while (cdr articles) (setq articles (cdr articles)))
- (car articles)))
- (nov (concat nnml-current-directory nnml-nov-file-name)))
- (when (file-exists-p nov)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (insert-file-contents nov)
- (if (and fetch-old
- (not (numberp fetch-old)))
- t ; Don't remove anything.
- (if fetch-old
- (setq first (max 1 (- first fetch-old))))
- (goto-char (point-min))
- (while (and (not (eobp)) (> first (read (current-buffer))))
- (forward-line 1))
- (beginning-of-line)
- (if (not (eobp)) (delete-region 1 (point)))
- (while (and (not (eobp)) (>= last (read (current-buffer))))
- (forward-line 1))
- (beginning-of-line)
- (if (not (eobp)) (delete-region (point) (point-max)))
- t))))))
-
-(defun nnml-possibly-change-directory (group &optional server)
- (when (and server
- (not (nnml-server-opened server)))
- (nnml-open-server server))
- (when group
- (let ((pathname (nnmail-group-pathname group nnml-directory)))
- (when (not (equal pathname nnml-current-directory))
- (setq nnml-current-directory pathname
- nnml-current-group group
- nnml-article-file-alist nil))))
- t)
-
-(defun nnml-possibly-create-directory (group)
- (let (dir dirs)
- (setq dir (nnmail-group-pathname group nnml-directory))
- (while (not (file-directory-p dir))
- (setq dirs (cons dir dirs))
- (setq dir (file-name-directory (directory-file-name dir))))
- (while dirs
- (make-directory (directory-file-name (car dirs)))
- (nnheader-message 5 "Creating mail directory %s" (car dirs))
- (setq dirs (cdr dirs)))))
-
-(defun nnml-save-mail ()
- "Called narrowed to an article."
- (let ((group-art (nreverse (nnmail-article-group 'nnml-active-number)))
- chars headers)
- (setq chars (nnmail-insert-lines))
- (nnmail-insert-xref group-art)
- (run-hooks 'nnmail-prepare-save-mail-hook)
- (run-hooks 'nnml-prepare-save-mail-hook)
- (goto-char (point-min))
- (while (looking-at "From ")
- (replace-match "X-From-Line: ")
- (forward-line 1))
- ;; We save the article in all the newsgroups it belongs in.
- (let ((ga group-art)
- first)
- (while ga
- (nnml-possibly-create-directory (caar ga))
- (let ((file (concat (nnmail-group-pathname
- (caar ga) nnml-directory)
- (int-to-string (cdar ga)))))
- (if first
- ;; It was already saved, so we just make a hard link.
- (funcall nnmail-crosspost-link-function first file t)
- ;; Save the article.
- (write-region (point-min) (point-max) file nil
- (if (nnheader-be-verbose 5) nil 'nomesg))
- (setq first file)))
- (setq ga (cdr ga))))
- ;; Generate a nov line for this article. We generate the nov
- ;; line after saving, because nov generation destroys the
- ;; header.
- (setq headers (nnml-parse-head chars))
- ;; Output the nov line to all nov databases that should have it.
- (let ((ga group-art))
- (while ga
- (nnml-add-nov (caar ga) (cdar ga) headers)
- (setq ga (cdr ga))))
- group-art))
-
-(defun nnml-active-number (group)
- "Compute the next article number in GROUP."
- (let ((active (cadr (assoc group nnml-group-alist))))
- ;; The group wasn't known to nnml, so we just create an active
- ;; entry for it.
- (unless active
- ;; Perhaps the active file was corrupt? See whether
- ;; there are any articles in this group.
- (nnml-possibly-create-directory group)
- (nnml-possibly-change-directory group)
- (unless nnml-article-file-alist
- (setq nnml-article-file-alist
- (sort
- (nnheader-article-to-file-alist nnml-current-directory)
- (lambda (a1 a2) (< (car a1) (car a2))))))
- (setq active
- (if nnml-article-file-alist
- (cons (caar nnml-article-file-alist)
- (caar (last nnml-article-file-alist)))
- (cons 1 0)))
- (setq nnml-group-alist (cons (list group active) nnml-group-alist)))
- (setcdr active (1+ (cdr active)))
- (while (file-exists-p
- (concat (nnmail-group-pathname group nnml-directory)
- (int-to-string (cdr active))))
- (setcdr active (1+ (cdr active))))
- (cdr active)))
-
-(defun nnml-add-nov (group article headers)
- "Add a nov line for the GROUP base."
- (save-excursion
- (set-buffer (nnml-open-nov group))
- (goto-char (point-max))
- (mail-header-set-number headers article)
- (nnheader-insert-nov headers)))
-
-(defsubst nnml-header-value ()
- (buffer-substring (match-end 0) (progn (end-of-line) (point))))
-
-(defun nnml-parse-head (chars &optional number)
- "Parse the head of the current buffer."
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (narrow-to-region
- (point)
- (1- (or (search-forward "\n\n" nil t) (point-max))))
- ;; Fold continuation lines.
- (goto-char (point-min))
- (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
- (replace-match " " t t))
- ;; Remove any tabs; they are too confusing.
- (subst-char-in-region (point-min) (point-max) ?\t ? )
- (let ((headers (nnheader-parse-head t)))
- (mail-header-set-chars headers chars)
- (mail-header-set-number headers number)
- headers))))
-
-(defun nnml-open-nov (group)
- (or (cdr (assoc group nnml-nov-buffer-alist))
- (let ((buffer (find-file-noselect
- (concat (nnmail-group-pathname group nnml-directory)
- nnml-nov-file-name))))
- (save-excursion
- (set-buffer buffer)
- (buffer-disable-undo (current-buffer)))
- (setq nnml-nov-buffer-alist
- (cons (cons group buffer) nnml-nov-buffer-alist))
- buffer)))
-
-(defun nnml-save-nov ()
- (save-excursion
- (while nnml-nov-buffer-alist
- (when (buffer-name (cdar nnml-nov-buffer-alist))
- (set-buffer (cdar nnml-nov-buffer-alist))
- (and (buffer-modified-p)
- (write-region
- 1 (point-max) (buffer-file-name) nil 'nomesg))
- (set-buffer-modified-p nil)
- (kill-buffer (current-buffer)))
- (setq nnml-nov-buffer-alist (cdr nnml-nov-buffer-alist)))))
-
-;;;###autoload
-(defun nnml-generate-nov-databases ()
- "Generate nov databases in all nnml directories."
- (interactive)
- ;; Read the active file to make sure we don't re-use articles
- ;; numbers in empty groups.
- (nnmail-activate 'nnml)
- (nnml-open-server (or (nnoo-current-server 'nnml) ""))
- (setq nnml-directory (expand-file-name nnml-directory))
- ;; Recurse down the directories.
- (nnml-generate-nov-databases-1 nnml-directory)
- ;; Save the active file.
- (nnmail-save-active nnml-group-alist nnml-active-file))
-
-(defun nnml-generate-nov-databases-1 (dir)
- (setq dir (file-name-as-directory dir))
- ;; We descend recursively
- (let ((dirs (directory-files dir t nil t))
- dir)
- (while dirs
- (setq dir (pop dirs))
- (when (and (not (member (file-name-nondirectory dir) '("." "..")))
- (file-directory-p dir))
- (nnml-generate-nov-databases-1 dir))))
- ;; Do this directory.
- (let ((files (sort
- (mapcar
- (lambda (name) (string-to-int name))
- (directory-files dir nil "^[0-9]+$" t))
- '<)))
- (when files
- (funcall nnml-generate-active-function dir)
- ;; Generate the nov file.
- (nnml-generate-nov-file dir files))))
-
-(defvar files)
-(defun nnml-generate-active-info (dir)
- ;; Update the active info for this group.
- (let ((group (nnheader-file-to-group
- (directory-file-name dir) nnml-directory)))
- (setq nnml-group-alist
- (delq (assoc group nnml-group-alist) nnml-group-alist))
- (push (list group
- (cons (car files)
- (let ((f files))
- (while (cdr f) (setq f (cdr f)))
- (car f))))
- nnml-group-alist)))
-
-(defun nnml-generate-nov-file (dir files)
- (let* ((dir (file-name-as-directory dir))
- (nov (concat dir nnml-nov-file-name))
- (nov-buffer (get-buffer-create " *nov*"))
- nov-line chars file headers)
- (save-excursion
- ;; Init the nov buffer.
- (set-buffer nov-buffer)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (set-buffer nntp-server-buffer)
- ;; Delete the old NOV file.
- (when (file-exists-p nov)
- (funcall nnmail-delete-file-function nov))
- (while files
- (unless (file-directory-p
- (setq file (concat dir (int-to-string (car files)))))
- (erase-buffer)
- (insert-file-contents file)
- (narrow-to-region
- (goto-char (point-min))
- (progn
- (search-forward "\n\n" nil t)
- (setq chars (- (point-max) (point)))
- (max 1 (1- (point)))))
- (when (and (not (= 0 chars)) ; none of them empty files...
- (not (= (point-min) (point-max))))
- (goto-char (point-min))
- (setq headers (nnml-parse-head chars (car files)))
- (save-excursion
- (set-buffer nov-buffer)
- (goto-char (point-max))
- (nnheader-insert-nov headers)))
- (widen))
- (setq files (cdr files)))
- (save-excursion
- (set-buffer nov-buffer)
- (write-region 1 (point-max) (expand-file-name nov) nil
- 'nomesg)
- (kill-buffer (current-buffer))))))
-
-(defun nnml-nov-delete-article (group article)
- (save-excursion
- (set-buffer (nnml-open-nov group))
- (goto-char (point-min))
- (if (re-search-forward (concat "^" (int-to-string article) "\t") nil t)
- (delete-region (match-beginning 0) (progn (forward-line 1) (point))))
- t))
-
-(provide 'nnml)
-
-;;; nnml.el ends here
diff --git a/lisp/nnoo.el b/lisp/nnoo.el
deleted file mode 100644
index cddba4ae564..00000000000
--- a/lisp/nnoo.el
+++ /dev/null
@@ -1,251 +0,0 @@
-;;; nnoo.el --- OO Gnus Backends
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(eval-when-compile (require 'cl))
-
-(defvar nnoo-definition-alist nil)
-(defvar nnoo-state-alist nil)
-
-(defmacro defvoo (var init &optional doc &rest map)
- "The same as `defvar', only takes list of variables to MAP to."
- `(prog1
- ,(if doc
- `(defvar ,var ,init ,doc)
- `(defvar ,var ,init))
- (nnoo-define ',var ',map)))
-(put 'defvoo 'lisp-indent-function 2)
-(put 'defvoo 'lisp-indent-hook 2)
-(put 'defvoo 'edebug-form-spec '(var init &optional doc &rest map))
-
-(defmacro deffoo (func args &rest forms)
- "The same as `defun', only register FUNC."
- `(prog1
- (defun ,func ,args ,@forms)
- (nnoo-register-function ',func)))
-(put 'deffoo 'lisp-indent-function 2)
-(put 'deffoo 'lisp-indent-hook 2)
-(put 'deffoo 'edebug-form-spec '(&define name lambda-list def-body))
-
-(defun nnoo-register-function (func)
- (let ((funcs (nthcdr 3 (assoc (nnoo-backend func)
- nnoo-definition-alist))))
- (unless funcs
- (error "%s belongs to a backend that hasn't been declared" func))
- (setcar funcs (cons func (car funcs)))))
-
-(defmacro nnoo-declare (backend &rest parents)
- `(eval-and-compile
- (push (list ',backend
- (mapcar (lambda (p) (list p)) ',parents)
- nil nil)
- nnoo-definition-alist)))
-(put 'nnoo-declare 'lisp-indent-function 1)
-(put 'nnoo-declare 'lisp-indent-hook 1)
-
-(defun nnoo-parents (backend)
- (nth 1 (assoc backend nnoo-definition-alist)))
-
-(defun nnoo-variables (backend)
- (nth 2 (assoc backend nnoo-definition-alist)))
-
-(defun nnoo-functions (backend)
- (nth 3 (assoc backend nnoo-definition-alist)))
-
-(defmacro nnoo-import (backend &rest imports)
- `(nnoo-import-1 ',backend ',imports))
-(put 'nnoo-import 'lisp-indent-function 1)
-(put 'nnoo-import 'lisp-indent-hook 1)
-
-(defun nnoo-import-1 (backend imports)
- (let ((call-function
- (if (symbolp (car imports)) (pop imports) 'nnoo-parent-function))
- imp functions function)
- (while (setq imp (pop imports))
- (setq functions
- (or (cdr imp)
- (nnoo-functions (car imp))))
- (while functions
- (unless (fboundp (setq function
- (nnoo-symbol backend (nnoo-rest-symbol
- (car functions)))))
- (eval `(deffoo ,function (&rest args)
- (,call-function ',backend ',(car functions) args))))
- (pop functions)))))
-
-(defun nnoo-parent-function (backend function args)
- (let* ((pbackend (nnoo-backend function)))
- (nnoo-change-server pbackend (nnoo-current-server backend)
- (cdr (assq pbackend (nnoo-parents backend))))
- (apply function args)))
-
-(defun nnoo-execute (backend function &rest args)
- "Execute FUNCTION on behalf of BACKEND."
- (let* ((pbackend (nnoo-backend function)))
- (nnoo-change-server pbackend (nnoo-current-server backend)
- (cdr (assq pbackend (nnoo-parents backend))))
- (apply function args)))
-
-(defmacro nnoo-map-functions (backend &rest maps)
- `(nnoo-map-functions-1 ',backend ',maps))
-(put 'nnoo-map-functions 'lisp-indent-function 1)
-(put 'nnoo-map-functions 'lisp-indent-hook 1)
-
-(defun nnoo-map-functions-1 (backend maps)
- (let (m margs i)
- (while (setq m (pop maps))
- (setq i 0
- margs nil)
- (while (< i (length (cdr m)))
- (if (numberp (nth i (cdr m)))
- (push `(nth ,i args) margs)
- (push (nth i (cdr m)) margs))
- (incf i))
- (eval `(deffoo ,(nnoo-symbol backend (nnoo-rest-symbol (car m)))
- (&rest args)
- (nnoo-parent-function ',backend ',(car m)
- ,(cons 'list (nreverse margs))))))))
-
-(defun nnoo-backend (symbol)
- (string-match "^[^-]+-" (symbol-name symbol))
- (intern (substring (symbol-name symbol) 0 (1- (match-end 0)))))
-
-(defun nnoo-rest-symbol (symbol)
- (string-match "^[^-]+-" (symbol-name symbol))
- (intern (substring (symbol-name symbol) (match-end 0))))
-
-(defun nnoo-symbol (backend symbol)
- (intern (format "%s-%s" backend symbol)))
-
-(defun nnoo-define (var map)
- (let* ((backend (nnoo-backend var))
- (def (assq backend nnoo-definition-alist))
- (parents (nth 1 def)))
- (unless def
- (error "%s belongs to a backend that hasn't been declared." var))
- (setcar (nthcdr 2 def)
- (delq (assq var (nth 2 def)) (nth 2 def)))
- (setcar (nthcdr 2 def)
- (cons (cons var (symbol-value var))
- (nth 2 def)))
- (while map
- (nconc (assq (nnoo-backend (car map)) parents)
- (list (list (pop map) var))))))
-
-(defun nnoo-change-server (backend server defs)
- (let* ((bstate (cdr (assq backend nnoo-state-alist)))
- (sdefs (assq backend nnoo-definition-alist))
- (current (car bstate))
- (parents (nnoo-parents backend))
- state)
- (unless bstate
- (push (setq bstate (list backend nil))
- nnoo-state-alist)
- (pop bstate))
- (if (equal server current)
- t
- (nnoo-push-server backend current)
- (setq state (or (cdr (assoc server (cddr bstate)))
- (nnoo-variables backend)))
- (while state
- (set (caar state) (cdar state))
- (pop state))
- (setcar bstate server)
- (unless (cdr (assoc server (cddr bstate)))
- (while defs
- (set (caar defs) (cadar defs))
- (pop defs)))
- (while parents
- (nnoo-change-server
- (caar parents) server
- (mapcar (lambda (def) (list (car def) (symbol-value (cadr def))))
- (cdar parents)))
- (pop parents))))
- t)
-
-(defun nnoo-push-server (backend current)
- (let ((bstate (assq backend nnoo-state-alist))
- (defs (nnoo-variables backend)))
- ;; Remove the old definition.
- (setcdr (cdr bstate) (delq (assoc current (cddr bstate)) (cddr bstate)))
- (let (state)
- (while defs
- (push (cons (caar defs) (symbol-value (caar defs)))
- state)
- (pop defs))
- (nconc bstate (list (cons current state))))))
-
-(defun nnoo-current-server-p (backend server)
- (equal (nnoo-current-server backend) server))
-
-(defun nnoo-current-server (backend)
- (nth 1 (assq backend nnoo-state-alist)))
-
-(defun nnoo-close-server (backend &optional server)
- (unless server
- (setq server (nnoo-current-server backend)))
- (when server
- (let* ((bstate (cdr (assq backend nnoo-state-alist)))
- (defs (assoc server (cdr bstate))))
- (when bstate
- (setcar bstate nil)
- (setcdr bstate (delq defs (cdr bstate)))
- (pop defs)
- (while defs
- (set (car (pop defs)) nil)))))
- t)
-
-(defun nnoo-close (backend)
- (setq nnoo-state-alist
- (delq (assq backend nnoo-state-alist)
- nnoo-state-alist))
- t)
-
-(defun nnoo-status-message (backend server)
- (nnheader-get-report backend))
-
-(defun nnoo-server-opened (backend server)
- (and (nnoo-current-server-p backend server)
- nntp-server-buffer
- (buffer-name nntp-server-buffer)))
-
-(defmacro nnoo-define-basics (backend)
- `(eval-and-compile
- (nnoo-define-basics-1 ',backend)))
-
-(defun nnoo-define-basics-1 (backend)
- (let ((functions '(close-server server-opened status-message)))
- (while functions
- (eval `(deffoo ,(nnoo-symbol backend (car functions))
- (&optional server)
- (,(nnoo-symbol 'nnoo (pop functions)) ',backend server)))))
- (eval `(deffoo ,(nnoo-symbol backend 'open-server)
- (server &optional defs)
- (nnoo-change-server ',backend server defs))))
-
-(provide 'nnoo)
-
-;;; nnoo.el ends here.
diff --git a/lisp/nnsoup.el b/lisp/nnsoup.el
deleted file mode 100644
index 03e80fef9ab..00000000000
--- a/lisp/nnsoup.el
+++ /dev/null
@@ -1,747 +0,0 @@
-;;; nnsoup.el --- SOUP access for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: news, mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'nnheader)
-(require 'nnmail)
-(require 'gnus-soup)
-(require 'gnus-msg)
-(require 'nnoo)
-(eval-when-compile (require 'cl))
-
-(nnoo-declare nnsoup)
-
-(defvoo nnsoup-directory "~/SOUP/"
- "*SOUP packet directory.")
-
-(defvoo nnsoup-tmp-directory "/tmp/"
- "*Where nnsoup will store temporary files.")
-
-(defvoo nnsoup-replies-directory (concat nnsoup-directory "replies/")
- "*Directory where outgoing packets will be composed.")
-
-(defvoo nnsoup-replies-format-type ?n
- "*Format of the replies packages.")
-
-(defvoo nnsoup-replies-index-type ?n
- "*Index type of the replies packages.")
-
-(defvoo nnsoup-active-file (concat nnsoup-directory "active")
- "Active file.")
-
-(defvoo nnsoup-packer "tar cf - %s | gzip > $HOME/Soupin%d.tgz"
- "Format string command for packing a SOUP packet.
-The SOUP files will be inserted where the %s is in the string.
-This string MUST contain both %s and %d. The file number will be
-inserted where %d appears.")
-
-(defvoo nnsoup-unpacker "gunzip -c %s | tar xvf -"
- "*Format string command for unpacking a SOUP packet.
-The SOUP packet file name will be inserted at the %s.")
-
-(defvoo nnsoup-packet-directory "~/"
- "*Where nnsoup will look for incoming packets.")
-
-(defvoo nnsoup-packet-regexp "Soupout"
- "*Regular expression matching SOUP packets in `nnsoup-packet-directory'.")
-
-
-
-(defconst nnsoup-version "nnsoup 0.0"
- "nnsoup version.")
-
-(defvoo nnsoup-status-string "")
-(defvoo nnsoup-group-alist nil)
-(defvoo nnsoup-current-prefix 0)
-(defvoo nnsoup-replies-list nil)
-(defvoo nnsoup-buffers nil)
-(defvoo nnsoup-current-group nil)
-(defvoo nnsoup-group-alist-touched nil)
-
-
-
-;;; Interface functions.
-
-(nnoo-define-basics nnsoup)
-
-(deffoo nnsoup-retrieve-headers (sequence &optional group server fetch-old)
- (nnsoup-possibly-change-group group)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (let ((areas (cddr (assoc nnsoup-current-group nnsoup-group-alist)))
- (articles sequence)
- (use-nov t)
- useful-areas this-area-seq msg-buf)
- (if (stringp (car sequence))
- ;; We don't support fetching by Message-ID.
- 'headers
- ;; We go through all the areas and find which files the
- ;; articles in SEQUENCE come from.
- (while (and areas sequence)
- ;; Peel off areas that are below sequence.
- (while (and areas (< (cdaar areas) (car sequence)))
- (setq areas (cdr areas)))
- (when areas
- ;; This is a useful area.
- (push (car areas) useful-areas)
- (setq this-area-seq nil)
- ;; We take note whether this MSG has a corresponding IDX
- ;; for later use.
- (when (or (= (gnus-soup-encoding-index
- (gnus-soup-area-encoding (nth 1 (car areas)))) ?n)
- (not (file-exists-p
- (nnsoup-file
- (gnus-soup-area-prefix (nth 1 (car areas)))))))
- (setq use-nov nil))
- ;; We assign the portion of `sequence' that is relevant to
- ;; this MSG packet to this packet.
- (while (and sequence (<= (car sequence) (cdaar areas)))
- (push (car sequence) this-area-seq)
- (setq sequence (cdr sequence)))
- (setcar useful-areas (cons (nreverse this-area-seq)
- (car useful-areas)))))
-
- ;; We now have a list of article numbers and corresponding
- ;; areas.
- (setq useful-areas (nreverse useful-areas))
-
- ;; Two different approaches depending on whether all the MSG
- ;; files have corresponding IDX files. If they all do, we
- ;; simply return the relevant IDX files and let Gnus sort out
- ;; what lines are relevant. If some of the IDX files are
- ;; missing, we must return HEADs for all the articles.
- (if use-nov
- ;; We have IDX files for all areas.
- (progn
- (while useful-areas
- (goto-char (point-max))
- (let ((b (point))
- (number (car (nth 1 (car useful-areas))))
- (index-buffer (nnsoup-index-buffer
- (gnus-soup-area-prefix
- (nth 2 (car useful-areas))))))
- (when index-buffer
- (insert-buffer-substring index-buffer)
- (goto-char b)
- ;; We have to remove the index number entires and
- ;; insert article numbers instead.
- (while (looking-at "[0-9]+")
- (replace-match (int-to-string number) t t)
- (incf number)
- (forward-line 1))))
- (setq useful-areas (cdr useful-areas)))
- 'nov)
- ;; We insert HEADs.
- (while useful-areas
- (setq articles (caar useful-areas)
- useful-areas (cdr useful-areas))
- (while articles
- (when (setq msg-buf
- (nnsoup-narrow-to-article
- (car articles) (cdar useful-areas) 'head))
- (goto-char (point-max))
- (insert (format "221 %d Article retrieved.\n" (car articles)))
- (insert-buffer-substring msg-buf)
- (goto-char (point-max))
- (insert ".\n"))
- (setq articles (cdr articles))))
-
- (nnheader-fold-continuation-lines)
- 'headers)))))
-
-(deffoo nnsoup-open-server (server &optional defs)
- (nnoo-change-server 'nnsoup server defs)
- (when (not (file-exists-p nnsoup-directory))
- (condition-case ()
- (make-directory nnsoup-directory t)
- (error t)))
- (cond
- ((not (file-exists-p nnsoup-directory))
- (nnsoup-close-server)
- (nnheader-report 'nnsoup "Couldn't create directory: %s" nnsoup-directory))
- ((not (file-directory-p (file-truename nnsoup-directory)))
- (nnsoup-close-server)
- (nnheader-report 'nnsoup "Not a directory: %s" nnsoup-directory))
- (t
- (nnsoup-read-active-file)
- (nnheader-report 'nnsoup "Opened server %s using directory %s"
- server nnsoup-directory)
- t)))
-
-(deffoo nnsoup-request-close ()
- (nnsoup-write-active-file)
- (nnsoup-write-replies)
- (gnus-soup-save-areas)
- ;; Kill all nnsoup buffers.
- (let (buffer)
- (while nnsoup-buffers
- (setq buffer (cdr (pop nnsoup-buffers)))
- (and buffer
- (buffer-name buffer)
- (kill-buffer buffer))))
- (setq nnsoup-group-alist nil
- nnsoup-group-alist-touched nil
- nnsoup-current-group nil
- nnsoup-replies-list nil)
- (nnoo-close-server 'nnoo)
- t)
-
-(deffoo nnsoup-request-article (id &optional newsgroup server buffer)
- (nnsoup-possibly-change-group newsgroup)
- (let (buf)
- (save-excursion
- (set-buffer (or buffer nntp-server-buffer))
- (erase-buffer)
- (when (and (not (stringp id))
- (setq buf (nnsoup-narrow-to-article id)))
- (insert-buffer-substring buf)
- t))))
-
-(deffoo nnsoup-request-group (group &optional server dont-check)
- (nnsoup-possibly-change-group group)
- (if dont-check
- t
- (let ((active (cadr (assoc group nnsoup-group-alist))))
- (if (not active)
- (nnheader-report 'nnsoup "No such group: %s" group)
- (nnheader-insert
- "211 %d %d %d %s\n"
- (max (1+ (- (cdr active) (car active))) 0)
- (car active) (cdr active) group)))))
-
-(deffoo nnsoup-request-type (group &optional article)
- (nnsoup-possibly-change-group group)
- (if (not article)
- 'unknown
- (let ((kind (gnus-soup-encoding-kind
- (gnus-soup-area-encoding
- (nth 1 (nnsoup-article-to-area
- article nnsoup-current-group))))))
- (cond ((= kind ?m) 'mail)
- ((= kind ?n) 'news)
- (t 'unknown)))))
-
-(deffoo nnsoup-close-group (group &optional server)
- ;; Kill all nnsoup buffers.
- (let ((buffers nnsoup-buffers)
- elem)
- (while buffers
- (when (equal (car (setq elem (pop buffers))) group)
- (setq nnsoup-buffers (delq elem nnsoup-buffers))
- (and (cdr elem) (buffer-name (cdr elem))
- (kill-buffer (cdr elem))))))
- t)
-
-(deffoo nnsoup-request-list (&optional server)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (unless nnsoup-group-alist
- (nnsoup-read-active-file))
- (let ((alist nnsoup-group-alist)
- (standard-output (current-buffer))
- entry)
- (while (setq entry (pop alist))
- (insert (car entry) " ")
- (princ (cdadr entry))
- (insert " ")
- (princ (caadr entry))
- (insert " y\n"))
- t)))
-
-(deffoo nnsoup-request-scan (group &optional server)
- (nnsoup-unpack-packets))
-
-(deffoo nnsoup-request-newgroups (date &optional server)
- (nnsoup-request-list))
-
-(deffoo nnsoup-request-list-newsgroups (&optional server)
- nil)
-
-(deffoo nnsoup-request-post (&optional server)
- (nnsoup-store-reply "news")
- t)
-
-(deffoo nnsoup-request-mail (&optional server)
- (nnsoup-store-reply "mail")
- t)
-
-(deffoo nnsoup-request-expire-articles (articles group &optional server force)
- (nnsoup-possibly-change-group group)
- (let* ((total-infolist (assoc group nnsoup-group-alist))
- (active (cadr total-infolist))
- (infolist (cddr total-infolist))
- info range-list mod-time prefix)
- (while infolist
- (setq info (pop infolist)
- range-list (gnus-uncompress-range (car info))
- prefix (gnus-soup-area-prefix (nth 1 info)))
- (when ;; All the articles in this file are marked for expiry.
- (and (or (setq mod-time (nth 5 (file-attributes
- (nnsoup-file prefix))))
- (setq mod-time (nth 5 (file-attributes
- (nnsoup-file prefix t)))))
- (gnus-sublist-p articles range-list)
- ;; This file is old enough.
- (nnmail-expired-article-p group mod-time force))
- ;; Ok, we delete this file.
- (when (condition-case nil
- (progn
- (nnheader-message
- 5 "Deleting %s in group %s..." (nnsoup-file prefix)
- group)
- (when (file-exists-p (nnsoup-file prefix))
- (delete-file (nnsoup-file prefix)))
- (nnheader-message
- 5 "Deleting %s in group %s..." (nnsoup-file prefix t)
- group)
- (when (file-exists-p (nnsoup-file prefix t))
- (delete-file (nnsoup-file prefix t)))
- t)
- (error nil))
- (setcdr (cdr total-infolist) (delq info (cddr total-infolist)))
- (setq articles (gnus-sorted-complement articles range-list))))
- (when (not mod-time)
- (setcdr (cdr total-infolist) (delq info (cddr total-infolist)))))
- (if (cddr total-infolist)
- (setcar active (caaadr (cdr total-infolist)))
- (setcar active (1+ (cdr active))))
- (nnsoup-write-active-file t)
- ;; Return the articles that weren't expired.
- articles))
-
-
-;;; Internal functions
-
-(defun nnsoup-possibly-change-group (group &optional force)
- (if group
- (setq nnsoup-current-group group)
- t))
-
-(defun nnsoup-read-active-file ()
- (setq nnsoup-group-alist nil)
- (when (file-exists-p nnsoup-active-file)
- (condition-case ()
- (load nnsoup-active-file t t t)
- (error nil))
- ;; Be backwards compatible.
- (when (and nnsoup-group-alist
- (not (atom (caadar nnsoup-group-alist))))
- (let ((alist nnsoup-group-alist)
- entry e min max)
- (while (setq e (cdr (setq entry (pop alist))))
- (setq min (caaar e))
- (while (cdr e)
- (setq e (cdr e)))
- (setq max (cdaar e))
- (setcdr entry (cons (cons min max) (cdr entry)))))
- (setq nnsoup-group-alist-touched t))
- nnsoup-group-alist))
-
-(defun nnsoup-write-active-file (&optional force)
- (when (and nnsoup-group-alist
- (or force
- nnsoup-group-alist-touched))
- (setq nnsoup-group-alist-touched nil)
- (nnheader-temp-write nnsoup-active-file
- (let ((standard-output (current-buffer)))
- (prin1 `(setq nnsoup-group-alist ',nnsoup-group-alist))
- (insert "\n")
- (prin1 `(setq nnsoup-current-prefix ,nnsoup-current-prefix))
- (insert "\n")))))
-
-(defun nnsoup-next-prefix ()
- "Return the next free prefix."
- (let (prefix)
- (while (or (file-exists-p
- (nnsoup-file (setq prefix (int-to-string
- nnsoup-current-prefix))))
- (file-exists-p (nnsoup-file prefix t)))
- (incf nnsoup-current-prefix))
- (incf nnsoup-current-prefix)
- prefix))
-
-(defun nnsoup-read-areas ()
- (save-excursion
- (set-buffer nntp-server-buffer)
- (let ((areas (gnus-soup-parse-areas (concat nnsoup-tmp-directory "AREAS")))
- entry number area lnum cur-prefix file)
- ;; Go through all areas in the new AREAS file.
- (while (setq area (pop areas))
- ;; Change the name to the permanent name and move the files.
- (setq cur-prefix (nnsoup-next-prefix))
- (message "Incorporating file %s..." cur-prefix)
- (when (file-exists-p
- (setq file (concat nnsoup-tmp-directory
- (gnus-soup-area-prefix area) ".IDX")))
- (rename-file file (nnsoup-file cur-prefix)))
- (when (file-exists-p
- (setq file (concat nnsoup-tmp-directory
- (gnus-soup-area-prefix area) ".MSG")))
- (rename-file file (nnsoup-file cur-prefix t))
- (gnus-soup-set-area-prefix area cur-prefix)
- ;; Find the number of new articles in this area.
- (setq number (nnsoup-number-of-articles area))
- (if (not (setq entry (assoc (gnus-soup-area-name area)
- nnsoup-group-alist)))
- ;; If this is a new area (group), we just add this info to
- ;; the group alist.
- (push (list (gnus-soup-area-name area)
- (cons 1 number)
- (list (cons 1 number) area))
- nnsoup-group-alist)
- ;; There are already articles in this group, so we add this
- ;; info to the end of the entry.
- (nconc entry (list (list (cons (1+ (setq lnum (cdadr entry)))
- (+ lnum number))
- area)))
- (setcdr (cadr entry) (+ lnum number))))))
- (nnsoup-write-active-file t)
- (delete-file (concat nnsoup-tmp-directory "AREAS"))))
-
-(defun nnsoup-number-of-articles (area)
- (save-excursion
- (cond
- ;; If the number is in the area info, we just return it.
- ((gnus-soup-area-number area)
- (gnus-soup-area-number area))
- ;; If there is an index file, we just count the lines.
- ((/= (gnus-soup-encoding-index (gnus-soup-area-encoding area)) ?n)
- (set-buffer (nnsoup-index-buffer (gnus-soup-area-prefix area)))
- (count-lines (point-min) (point-max)))
- ;; We do it the hard way - re-searching through the message
- ;; buffer.
- (t
- (set-buffer (nnsoup-message-buffer (gnus-soup-area-prefix area)))
- (goto-char (point-min))
- (let ((regexp (nnsoup-header (gnus-soup-encoding-format
- (gnus-soup-area-encoding area))))
- (num 0))
- (while (re-search-forward regexp nil t)
- (setq num (1+ num)))
- num)))))
-
-(defun nnsoup-index-buffer (prefix &optional message)
- (let* ((file (concat prefix (if message ".MSG" ".IDX")))
- (buffer-name (concat " *nnsoup " file "*")))
- (or (get-buffer buffer-name) ; File aready loaded.
- (when (file-exists-p (concat nnsoup-directory file))
- (save-excursion ; Load the file.
- (set-buffer (get-buffer-create buffer-name))
- (buffer-disable-undo (current-buffer))
- (push (cons nnsoup-current-group (current-buffer)) nnsoup-buffers)
- (insert-file-contents (concat nnsoup-directory file))
- (current-buffer))))))
-
-(defun nnsoup-file (prefix &optional message)
- (expand-file-name
- (concat nnsoup-directory prefix (if message ".MSG" ".IDX"))))
-
-(defun nnsoup-message-buffer (prefix)
- (nnsoup-index-buffer prefix 'msg))
-
-(defun nnsoup-unpack-packets ()
- "Unpack all packets in `nnsoup-packet-directory'."
- (let ((packets (directory-files
- nnsoup-packet-directory t nnsoup-packet-regexp))
- packet)
- (while (setq packet (pop packets))
- (message (format "nnsoup: unpacking %s..." packet))
- (if (not (gnus-soup-unpack-packet
- nnsoup-tmp-directory nnsoup-unpacker packet))
- (message "Couldn't unpack %s" packet)
- (delete-file packet)
- (nnsoup-read-areas)
- (message "Unpacking...done")))))
-
-(defun nnsoup-narrow-to-article (article &optional area head)
- (let* ((area (or area (nnsoup-article-to-area article nnsoup-current-group)))
- (prefix (and area (gnus-soup-area-prefix (nth 1 area))))
- (msg-buf (and prefix (nnsoup-index-buffer prefix 'msg)))
- beg end)
- (when area
- (save-excursion
- (cond
- ;; There is no MSG file.
- ((null msg-buf)
- nil)
-
- ;; We use the index file to find out where the article begins and ends.
- ((and (= (gnus-soup-encoding-index
- (gnus-soup-area-encoding (nth 1 area)))
- ?c)
- (file-exists-p (nnsoup-file prefix)))
- (set-buffer (nnsoup-index-buffer prefix))
- (widen)
- (goto-char (point-min))
- (forward-line (- article (caar area)))
- (setq beg (read (current-buffer)))
- (forward-line 1)
- (if (looking-at "[0-9]+")
- (progn
- (setq end (read (current-buffer)))
- (set-buffer msg-buf)
- (widen)
- (let ((format (gnus-soup-encoding-format
- (gnus-soup-area-encoding (nth 1 area)))))
- (goto-char end)
- (if (or (= format ?n) (= format ?m))
- (setq end (progn (forward-line -1) (point))))))
- (set-buffer msg-buf))
- (widen)
- (narrow-to-region beg (or end (point-max))))
- (t
- (set-buffer msg-buf)
- (widen)
- (goto-char (point-min))
- (let ((header (nnsoup-header
- (gnus-soup-encoding-format
- (gnus-soup-area-encoding (nth 1 area))))))
- (re-search-forward header nil t (- article (caar area)))
- (narrow-to-region
- (match-beginning 0)
- (if (re-search-forward header nil t)
- (match-beginning 0)
- (point-max))))))
- (goto-char (point-min))
- (if (not head)
- ()
- (narrow-to-region
- (point-min)
- (if (search-forward "\n\n" nil t)
- (1- (point))
- (point-max))))
- msg-buf))))
-
-(defun nnsoup-header (format)
- (cond
- ((= format ?n)
- "^#! *rnews +[0-9]+ *$")
- ((= format ?m)
- (concat "^" message-unix-mail-delimiter))
- ((= format ?M)
- "^\^A\^A\^A\^A\n")
- (t
- (error "Unknown format: %c" format))))
-
-;;;###autoload
-(defun nnsoup-pack-replies ()
- "Make an outbound package of SOUP replies."
- (interactive)
- ;; Write all data buffers.
- (gnus-soup-save-areas)
- ;; Write the active file.
- (nnsoup-write-active-file)
- ;; Write the REPLIES file.
- (nnsoup-write-replies)
- ;; Pack all these files into a SOUP packet.
- (gnus-soup-pack nnsoup-replies-directory nnsoup-packer))
-
-(defun nnsoup-write-replies ()
- "Write the REPLIES file."
- (when nnsoup-replies-list
- (gnus-soup-write-replies nnsoup-replies-directory nnsoup-replies-list)
- (setq nnsoup-replies-list nil)))
-
-(defun nnsoup-article-to-area (article group)
- "Return the area that ARTICLE in GROUP is located in."
- (let ((areas (cddr (assoc group nnsoup-group-alist))))
- (while (and areas (< (cdaar areas) article))
- (setq areas (cdr areas)))
- (and areas (car areas))))
-
-(defvar nnsoup-old-functions
- (list message-send-mail-function message-send-news-function))
-
-;;;###autoload
-(defun nnsoup-set-variables ()
- "Use the SOUP methods for posting news and mailing mail."
- (interactive)
- (setq message-send-news-function 'nnsoup-request-post)
- (setq message-send-mail-function 'nnsoup-request-mail))
-
-;;;###autoload
-(defun nnsoup-revert-variables ()
- "Revert posting and mailing methods to the standard Emacs methods."
- (interactive)
- (setq message-send-mail-function (car nnsoup-old-functions))
- (setq message-send-news-function (cadr nnsoup-old-functions)))
-
-(defun nnsoup-store-reply (kind)
- ;; Mostly stolen from `message.el'.
- (require 'mail-utils)
- (let ((tembuf (generate-new-buffer " message temp"))
- (case-fold-search nil)
- (news (message-news-p))
- (resend-to-addresses (mail-fetch-field "resent-to"))
- delimline
- (mailbuf (current-buffer)))
- (unwind-protect
- (save-excursion
- (save-restriction
- (message-narrow-to-headers)
- (if (equal kind "mail")
- (message-generate-headers message-required-mail-headers)
- (message-generate-headers message-required-news-headers)))
- (set-buffer tembuf)
- (erase-buffer)
- (insert-buffer-substring mailbuf)
- ;; Remove some headers.
- (save-restriction
- (message-narrow-to-headers)
- ;; Remove some headers.
- (message-remove-header message-ignored-mail-headers t))
- (goto-char (point-max))
- ;; require one newline at the end.
- (or (= (preceding-char) ?\n)
- (insert ?\n))
- (when (and news
- (equal kind "mail")
- (or (mail-fetch-field "cc")
- (mail-fetch-field "to")))
- (message-insert-courtesy-copy))
- (let ((case-fold-search t))
- ;; 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))
- ;; Insert an extra newline if we need it to work around
- ;; Sun's bug that swallows newlines.
- (goto-char (1+ delimline))
- (when (eval message-mailer-swallows-blank-line)
- (newline))
- (let ((msg-buf
- (gnus-soup-store
- nnsoup-replies-directory
- (nnsoup-kind-to-prefix kind) nil nnsoup-replies-format-type
- nnsoup-replies-index-type))
- (num 0))
- (when (and msg-buf (bufferp msg-buf))
- (save-excursion
- (set-buffer msg-buf)
- (goto-char (point-min))
- (while (re-search-forward "^#! *rnews" nil t)
- (incf num)))
- (message "Stored %d messages" num)))
- (nnsoup-write-replies)
- (kill-buffer tembuf))))))
-
-(defun nnsoup-kind-to-prefix (kind)
- (unless nnsoup-replies-list
- (setq nnsoup-replies-list
- (gnus-soup-parse-replies
- (concat nnsoup-replies-directory "REPLIES"))))
- (let ((replies nnsoup-replies-list))
- (while (and replies
- (not (string= kind (gnus-soup-reply-kind (car replies)))))
- (setq replies (cdr replies)))
- (if replies
- (gnus-soup-reply-prefix (car replies))
- (setq nnsoup-replies-list
- (cons (vector (gnus-soup-unique-prefix nnsoup-replies-directory)
- kind
- (format "%c%c%c"
- nnsoup-replies-format-type
- nnsoup-replies-index-type
- (if (string= kind "news")
- ?n ?m)))
- nnsoup-replies-list))
- (gnus-soup-reply-prefix (car nnsoup-replies-list)))))
-
-(defun nnsoup-make-active ()
- "(Re-)create the SOUP active file."
- (interactive)
- (let ((files (sort (directory-files nnsoup-directory t "IDX$")
- (lambda (f1 f2)
- (< (progn (string-match "/\\([0-9]+\\)\\." f1)
- (string-to-int (match-string 1 f1)))
- (progn (string-match "/\\([0-9]+\\)\\." f2)
- (string-to-int (match-string 1 f2)))))))
- active group lines ident elem min)
- (set-buffer (get-buffer-create " *nnsoup work*"))
- (buffer-disable-undo (current-buffer))
- (while files
- (message "Doing %s..." (car files))
- (erase-buffer)
- (insert-file-contents (car files))
- (goto-char (point-min))
- (if (not (re-search-forward "^[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t *\\(Xref: \\)? *[^ ]* \\([^ ]+\\):[0-9]" nil t))
- (setq group "unknown")
- (setq group (match-string 2)))
- (setq lines (count-lines (point-min) (point-max)))
- (setq ident (progn (string-match
- "/\\([0-9]+\\)\\." (car files))
- (substring
- (car files) (match-beginning 1)
- (match-end 1))))
- (if (not (setq elem (assoc group active)))
- (push (list group (cons 1 lines)
- (list (cons 1 lines)
- (vector ident group "ncm" "" lines)))
- active)
- (nconc elem
- (list
- (list (cons (1+ (setq min (cdadr elem)))
- (+ min lines))
- (vector ident group "ncm" "" lines))))
- (setcdr (cadr elem) (+ min lines)))
- (setq files (cdr files)))
- (message "")
- (setq nnsoup-group-alist active)
- (nnsoup-write-active-file t)))
-
-(defun nnsoup-delete-unreferenced-message-files ()
- "Delete any *.MSG and *.IDX files that aren't known by nnsoup."
- (interactive)
- (let* ((known (apply 'nconc (mapcar
- (lambda (ga)
- (mapcar
- (lambda (area)
- (gnus-soup-area-prefix (cadr area)))
- (cddr ga)))
- nnsoup-group-alist)))
- (regexp "\\.MSG$\\|\\.IDX$")
- (files (directory-files nnsoup-directory nil regexp))
- non-files file)
- ;; Find all files that aren't known by nnsoup.
- (while (setq file (pop files))
- (string-match regexp file)
- (unless (member (substring file 0 (match-beginning 0)) known)
- (push file non-files)))
- ;; Sort and delete the files.
- (setq non-files (sort non-files 'string<))
- (map-y-or-n-p "Delete file %s? "
- (lambda (file) (delete-file (concat nnsoup-directory file)))
- non-files)))
-
-(provide 'nnsoup)
-
-;;; nnsoup.el ends here
diff --git a/lisp/nnspool.el b/lisp/nnspool.el
deleted file mode 100644
index f80bf28b7cd..00000000000
--- a/lisp/nnspool.el
+++ /dev/null
@@ -1,511 +0,0 @@
-;;; nnspool.el --- spool access for GNU Emacs
-;; Copyright (C) 1988,89,90,93,94,95,96 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'nnheader)
-(require 'nntp)
-(require 'timezone)
-(require 'nnoo)
-(eval-when-compile (require 'cl))
-
-(nnoo-declare nnspool)
-
-(defvoo nnspool-inews-program news-inews-program
- "Program to post news.
-This is most commonly `inews' or `injnews'.")
-
-(defvoo nnspool-inews-switches '("-h" "-S")
- "Switches for nnspool-request-post to pass to `inews' for posting news.
-If you are using Cnews, you probably should set this variable to nil.")
-
-(defvoo nnspool-spool-directory (file-name-as-directory news-path)
- "Local news spool directory.")
-
-(defvoo nnspool-nov-directory (concat nnspool-spool-directory "over.view/")
- "Local news nov directory.")
-
-(defvoo nnspool-lib-dir "/usr/lib/news/"
- "Where the local news library files are stored.")
-
-(defvoo nnspool-active-file (concat nnspool-lib-dir "active")
- "Local news active file.")
-
-(defvoo nnspool-newsgroups-file (concat nnspool-lib-dir "newsgroups")
- "Local news newsgroups file.")
-
-(defvoo nnspool-distributions-file (concat nnspool-lib-dir "distribs.pat")
- "Local news distributions file.")
-
-(defvoo nnspool-history-file (concat nnspool-lib-dir "history")
- "Local news history file.")
-
-(defvoo nnspool-active-times-file (concat nnspool-lib-dir "active.times")
- "Local news active date file.")
-
-(defvoo nnspool-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.")
-
-(defvoo nnspool-nov-is-evil nil
- "Non-nil means that nnspool will never return NOV lines instead of headers.")
-
-(defconst nnspool-sift-nov-with-sed nil
- "If non-nil, use sed to get the relevant portion from the overview file.
-If nil, nnspool will load the entire file into a buffer and process it
-there.")
-
-(defvoo nnspool-rejected-article-hook nil
- "*A hook that will be run when an article has been rejected by the server.")
-
-
-
-(defconst nnspool-version "nnspool 2.0"
- "Version numbers of this version of NNSPOOL.")
-
-(defvoo nnspool-current-directory nil
- "Current news group directory.")
-
-(defvoo nnspool-current-group nil)
-(defvoo nnspool-status-string "")
-
-
-;;; Interface functions.
-
-(nnoo-define-basics nnspool)
-
-(deffoo nnspool-retrieve-headers (articles &optional group server fetch-old)
- "Retrieve the headers of ARTICLES."
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (when (nnspool-possibly-change-directory group)
- (let* ((number (length articles))
- (count 0)
- (default-directory nnspool-current-directory)
- (do-message (and (numberp nnspool-large-newsgroup)
- (> number nnspool-large-newsgroup)))
- file beg article ag)
- (if (and (numberp (car articles))
- (nnspool-retrieve-headers-with-nov articles fetch-old))
- ;; We successfully retrieved the NOV headers.
- 'nov
- ;; No NOV headers here, so we do it the hard way.
- (while (setq article (pop articles))
- (if (stringp article)
- ;; This is a Message-ID.
- (setq ag (nnspool-find-id article)
- file (and ag (nnspool-article-pathname
- (car ag) (cdr ag)))
- article (cdr ag))
- ;; This is an article in the current group.
- (setq file (int-to-string article)))
- ;; Insert the head of the article.
- (when (and file
- (file-exists-p file))
- (insert "221 ")
- (princ article (current-buffer))
- (insert " Article retrieved.\n")
- (setq beg (point))
- (inline (nnheader-insert-head file))
- (goto-char beg)
- (search-forward "\n\n" nil t)
- (forward-char -1)
- (insert ".\n")
- (delete-region (point) (point-max)))
-
- (and do-message
- (zerop (% (incf count) 20))
- (message "nnspool: Receiving headers... %d%%"
- (/ (* count 100) number))))
-
- (and do-message
- (message "nnspool: Receiving headers...done"))
-
- ;; Fold continuation lines.
- (nnheader-fold-continuation-lines)
- 'headers)))))
-
-(deffoo nnspool-open-server (server &optional defs)
- (nnoo-change-server 'nnspool server defs)
- (cond
- ((not (file-exists-p nnspool-spool-directory))
- (nnspool-close-server)
- (nnheader-report 'nnspool "Spool directory doesn't exist: %s"
- nnspool-spool-directory))
- ((not (file-directory-p
- (directory-file-name
- (file-truename nnspool-spool-directory))))
- (nnspool-close-server)
- (nnheader-report 'nnspool "Not a directory: %s" nnspool-spool-directory))
- ((not (file-exists-p nnspool-active-file))
- (nnheader-report 'nnspool "The active file doesn't exist: %s"
- nnspool-active-file))
- (t
- (nnheader-report 'nnspool "Opened server %s using directory %s"
- server nnspool-spool-directory)
- t)))
-
-(deffoo nnspool-request-article (id &optional group server buffer)
- "Select article by message ID (or number)."
- (nnspool-possibly-change-directory group)
- (let ((nntp-server-buffer (or buffer nntp-server-buffer))
- file ag)
- (if (stringp id)
- ;; This is a Message-ID.
- (when (setq ag (nnspool-find-id id))
- (setq file (nnspool-article-pathname (car ag) (cdr ag))))
- (setq file (nnspool-article-pathname nnspool-current-group id)))
- (and file
- (file-exists-p file)
- (not (file-directory-p file))
- (save-excursion (nnspool-find-file file))
- ;; We return the article number and group name.
- (if (numberp id)
- (cons nnspool-current-group id)
- ag))))
-
-(deffoo nnspool-request-body (id &optional group server)
- "Select article body by message ID (or number)."
- (nnspool-possibly-change-directory group)
- (let ((res (nnspool-request-article id)))
- (when res
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (when (search-forward "\n\n" nil t)
- (delete-region (point-min) (point)))
- res))))
-
-(deffoo nnspool-request-head (id &optional group server)
- "Select article head by message ID (or number)."
- (nnspool-possibly-change-directory group)
- (let ((res (nnspool-request-article id)))
- (when res
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (when (search-forward "\n\n" nil t)
- (delete-region (1- (point)) (point-max)))
- (nnheader-fold-continuation-lines)))
- res))
-
-(deffoo nnspool-request-group (group &optional server dont-check)
- "Select news GROUP."
- (let ((pathname (nnspool-article-pathname group))
- dir)
- (if (not (file-directory-p pathname))
- (nnheader-report
- 'nnspool "Invalid group name (no such directory): %s" group)
- (setq nnspool-current-directory pathname)
- (nnheader-report 'nnspool "Selected group %s" group)
- (if dont-check
- (progn
- (nnheader-report 'nnspool "Selected group %s" group)
- t)
- ;; Yes, completely empty spool directories *are* possible.
- ;; Fix by Sudish Joseph <joseph@cis.ohio-state.edu>
- (when (setq dir (directory-files pathname nil "^[0-9]+$" t))
- (setq dir
- (sort (mapcar (lambda (name) (string-to-int name)) dir) '<)))
- (if dir
- (nnheader-insert
- "211 %d %d %d %s\n" (length dir) (car dir)
- (progn (while (cdr dir) (setq dir (cdr dir))) (car dir))
- group)
- (nnheader-report 'nnspool "Empty group %s" group)
- (nnheader-insert "211 0 0 0 %s\n" group))))))
-
-(deffoo nnspool-request-type (group &optional article)
- 'news)
-
-(deffoo nnspool-close-group (group &optional server)
- t)
-
-(deffoo nnspool-request-list (&optional server)
- "List active newsgroups."
- (save-excursion
- (or (nnspool-find-file nnspool-active-file)
- (nnheader-report 'nnspool (nnheader-file-error nnspool-active-file)))))
-
-(deffoo nnspool-request-list-newsgroups (&optional server)
- "List newsgroups (defined in NNTP2)."
- (save-excursion
- (or (nnspool-find-file nnspool-newsgroups-file)
- (nnheader-report 'nnspool (nnheader-file-error
- nnspool-newsgroups-file)))))
-
-(deffoo nnspool-request-list-distributions (&optional server)
- "List distributions (defined in NNTP2)."
- (save-excursion
- (or (nnspool-find-file nnspool-distributions-file)
- (nnheader-report 'nnspool (nnheader-file-error
- nnspool-distributions-file)))))
-
-;; Suggested by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
-(deffoo nnspool-request-newgroups (date &optional server)
- "List groups created after DATE."
- (if (nnspool-find-file nnspool-active-times-file)
- (save-excursion
- ;; Find the last valid line.
- (goto-char (point-max))
- (while (and (not (looking-at
- "\\([^ ]+\\) +\\([0-9]+\\)[0-9][0-9][0-9] "))
- (zerop (forward-line -1))))
- (let ((seconds (nnspool-seconds-since-epoch date))
- groups)
- ;; Go through lines and add the latest groups to a list.
- (while (and (looking-at "\\([^ ]+\\) +[0-9]+ ")
- (progn
- ;; We insert a .0 to make the list reader
- ;; interpret the number as a float. It is far
- ;; too big to be stored in a lisp integer.
- (goto-char (1- (match-end 0)))
- (insert ".0")
- (> (progn
- (goto-char (match-end 1))
- (read (current-buffer)))
- seconds))
- (setq groups (cons (buffer-substring
- (match-beginning 1) (match-end 1))
- groups))
- (zerop (forward-line -1))))
- (erase-buffer)
- (while groups
- (insert (car groups) " 0 0 y\n")
- (setq groups (cdr groups))))
- t)
- nil))
-
-(deffoo nnspool-request-post (&optional server)
- "Post a new news in current buffer."
- (save-excursion
- (let* ((process-connection-type nil) ; t bugs out on Solaris
- (inews-buffer (generate-new-buffer " *nnspool post*"))
- (proc
- (condition-case err
- (apply 'start-process "*nnspool inews*" inews-buffer
- nnspool-inews-program nnspool-inews-switches)
- (error
- (nnheader-report 'nnspool "inews error: %S" err)))))
- (if (not proc)
- ;; The inews program failed.
- ()
- (nnheader-report 'nnspool "")
- (set-process-sentinel proc 'nnspool-inews-sentinel)
- (process-send-region proc (point-min) (point-max))
- ;; We slap a condition-case around this, because the process may
- ;; have exited already...
- (condition-case nil
- (process-send-eof proc)
- (error nil))
- t))))
-
-
-
-;;; Internal functions.
-
-(defun nnspool-inews-sentinel (proc status)
- (save-excursion
- (set-buffer (process-buffer proc))
- (goto-char (point-min))
- (if (or (zerop (buffer-size))
- (search-forward "spooled" nil t))
- (kill-buffer (current-buffer))
- ;; Make status message by folding lines.
- (while (re-search-forward "[ \t\n]+" nil t)
- (replace-match " " t t))
- (nnheader-report 'nnspool "%s" (buffer-string))
- (message "nnspool: %s" nnspool-status-string)
- (ding)
- (run-hooks 'nnspool-rejected-article-hook))))
-
-(defun nnspool-retrieve-headers-with-nov (articles &optional fetch-old)
- (if (or gnus-nov-is-evil nnspool-nov-is-evil)
- nil
- (let ((nov (nnheader-group-pathname
- nnspool-current-group nnspool-nov-directory ".overview"))
- (arts articles)
- last)
- (if (not (file-exists-p nov))
- ()
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (if nnspool-sift-nov-with-sed
- (nnspool-sift-nov-with-sed articles nov)
- (insert-file-contents nov)
- (if (and fetch-old
- (not (numberp fetch-old)))
- t ; We want all the headers.
- (condition-case ()
- (progn
- ;; First we find the first wanted line.
- (nnspool-find-nov-line
- (if fetch-old (max 1 (- (car articles) fetch-old))
- (car articles)))
- (delete-region (point-min) (point))
- ;; Then we find the last wanted line.
- (if (nnspool-find-nov-line
- (progn (while (cdr articles)
- (setq articles (cdr articles)))
- (car articles)))
- (forward-line 1))
- (delete-region (point) (point-max))
- ;; If the buffer is empty, this wasn't very successful.
- (unless (zerop (buffer-size))
- ;; We check what the last article number was.
- ;; The NOV file may be out of sync with the articles
- ;; in the group.
- (forward-line -1)
- (setq last (read (current-buffer)))
- (if (= last (car articles))
- ;; Yup, it's all there.
- t
- ;; Perhaps not. We try to find the missing articles.
- (while (and arts
- (<= last (car arts)))
- (pop arts))
- ;; The articles in `arts' are missing from the buffer.
- (while arts
- (nnspool-insert-nov-head (pop arts)))
- t)))
- ;; The NOV file was corrupted.
- (error nil)))))))))
-
-(defun nnspool-insert-nov-head (article)
- "Read the head of ARTICLE, convert to NOV headers, and insert."
- (save-excursion
- (let ((cur (current-buffer))
- buf)
- (setq buf (nnheader-set-temp-buffer " *nnspool head*"))
- (when (nnheader-insert-head
- (nnspool-article-pathname nnspool-current-group article))
- (nnheader-insert-article-line article)
- (let ((headers (nnheader-parse-head)))
- (set-buffer cur)
- (goto-char (point-max))
- (nnheader-insert-nov headers)))
- (kill-buffer buf))))
-
-(defun nnspool-find-nov-line (article)
- (let ((max (point-max))
- (min (goto-char (point-min)))
- (cur (current-buffer))
- (prev (point-min))
- num found)
- (while (not found)
- (goto-char (/ (+ max min) 2))
- (beginning-of-line)
- (if (or (= (point) prev)
- (eobp))
- (setq found t)
- (setq prev (point))
- (cond ((> (setq num (read cur)) article)
- (setq max (point)))
- ((< num article)
- (setq min (point)))
- (t
- (setq found 'yes)))))
- ;; Now we may have found the article we're looking for, or we
- ;; may be somewhere near it.
- (when (and (not (eq found 'yes))
- (not (eq num article)))
- (setq found (point))
- (while (and (< (point) max)
- (or (not (numberp num))
- (< num article)))
- (forward-line 1)
- (setq found (point))
- (or (eobp)
- (= (setq num (read cur)) article)))
- (unless (eq num article)
- (goto-char found)))
- (beginning-of-line)
- (eq num article)))
-
-(defun nnspool-sift-nov-with-sed (articles file)
- (let ((first (car articles))
- (last (progn (while (cdr articles) (setq articles (cdr articles)))
- (car articles))))
- (call-process "awk" nil t nil
- (format "BEGIN {firstmsg=%d; lastmsg=%d;}\n $1 >= firstmsg && $1 <= lastmsg {print;}"
- (1- first) (1+ last))
- file)))
-
-;; Fixed by fdc@cliwe.ping.de (Frank D. Cringle).
-;; Find out what group an article identified by a Message-ID is in.
-(defun nnspool-find-id (id)
- (save-excursion
- (set-buffer (get-buffer-create " *nnspool work*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (condition-case ()
- (call-process "grep" nil t nil (regexp-quote id) nnspool-history-file)
- (error nil))
- (goto-char (point-min))
- (prog1
- (if (looking-at "<[^>]+>[ \t]+[-0-9~]+[ \t]+\\([^ /\t\n]+\\)/\\([0-9]+\\)[ \t\n]")
- (cons (match-string 1) (string-to-int (match-string 2))))
- (kill-buffer (current-buffer)))))
-
-(defun nnspool-find-file (file)
- "Insert FILE in server buffer safely."
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (condition-case ()
- (progn (nnheader-insert-file-contents-literally file) t)
- (file-error nil)))
-
-(defun nnspool-possibly-change-directory (group)
- (if (not group)
- t
- (let ((pathname (nnspool-article-pathname group)))
- (if (file-directory-p pathname)
- (setq nnspool-current-directory pathname
- nnspool-current-group group)
- (nnheader-report 'nnspool "No such newsgroup: %s" group)))))
-
-(defun nnspool-article-pathname (group &optional article)
- "Find the path for GROUP."
- (nnheader-group-pathname group nnspool-spool-directory article))
-
-(defun nnspool-seconds-since-epoch (date)
- (let* ((tdate (mapcar (lambda (ti) (and ti (string-to-int ti)))
- (timezone-parse-date date)))
- (ttime (mapcar (lambda (ti) (and ti (string-to-int ti)))
- (timezone-parse-time
- (aref (timezone-parse-date date) 3))))
- (unix (encode-time (nth 2 ttime) (nth 1 ttime) (nth 0 ttime)
- (nth 2 tdate) (nth 1 tdate) (nth 0 tdate)
- (nth 4 tdate))))
- (+ (* (car unix) 65536.0)
- (cadr unix))))
-
-(provide 'nnspool)
-
-;;; nnspool.el ends here
diff --git a/lisp/nntp.el b/lisp/nntp.el
deleted file mode 100644
index 8b34460b108..00000000000
--- a/lisp/nntp.el
+++ /dev/null
@@ -1,1336 +0,0 @@
-;;; nntp.el --- nntp access for Gnus
-;; Copyright (C) 1987,88,89,90,92,93,94,95,96 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'nnheader)
-(require 'nnoo)
-(eval-when-compile (require 'cl))
-
-(nnoo-declare nntp)
-
-(eval-and-compile
- (unless (fboundp 'open-network-stream)
- (require 'tcp)))
-
-(eval-when-compile (require 'cl))
-
-(eval-and-compile
- (autoload 'cancel-timer "timer")
- (autoload 'telnet "telnet" nil t)
- (autoload 'telnet-send-input "telnet" nil t)
- (autoload 'timezone-parse-date "timezone"))
-
-(defvoo 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
- (function
- (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-address'.")
-
-(defvoo nntp-server-opened-hook '(nntp-send-mode-reader)
- "*Hook used for sending commands to the server at startup.
-The default value is `nntp-send-mode-reader', which makes an innd
-server spawn an nnrpd server. Another useful function to put in this
-hook might be `nntp-send-authinfo', which will prompt for a password
-to allow posting from the server. Note that this is only necessary to
-do on servers that use strict access control.")
-(add-hook 'nntp-server-opened-hook 'nntp-send-mode-reader)
-
-(defvoo nntp-server-action-alist
- '(("nntpd 1\\.5\\.11t"
- (remove-hook 'nntp-server-opened-hook 'nntp-send-mode-reader)))
- "Alist of regexps to match on server types and actions to be taken.
-For instance, if you want Gnus to beep every time you connect
-to innd, you could say something like:
-
-\(setq nntp-server-action-alist
- '((\"innd\" (ding))))
-
-You probably don't want to do that, though.")
-
-(defvoo nntp-open-server-function 'nntp-open-network-stream
- "*Function used for connecting to a remote system.
-It will be called with the address of the remote system.
-
-Two pre-made functions are `nntp-open-network-stream', which is the
-default, and simply connects to some port or other on the remote
-system (see nntp-port-number). The other is `nntp-open-rlogin', which
-does an rlogin on the remote system, and then does a telnet to the
-NNTP server available there (see nntp-rlogin-parameters).")
-
-(defvoo nntp-rlogin-parameters '("telnet" "${NNTPSERVER:=localhost}" "nntp")
- "*Parameters to `nntp-open-login'.
-That function may be used as `nntp-open-server-function'. In that
-case, this list will be used as the parameter list given to rsh.")
-
-(defvoo nntp-rlogin-user-name nil
- "*User name on remote system when using the rlogin connect method.")
-
-(defvoo nntp-address nil
- "*The name of the NNTP server.")
-
-(defvoo nntp-port-number "nntp"
- "*Port number to connect to.")
-
-(defvoo nntp-end-of-line "\r\n"
- "String to use on the end of lines when talking to the NNTP server.
-This is \"\\r\\n\" by default, but should be \"\\n\" when
-using rlogin to communicate with the server.")
-
-(defvoo 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.")
-
-(defvoo nntp-buggy-select (memq system-type '(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.")
-
-(defvoo 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.")
-
-(defvoo nntp-debug-read 10000
- "*Display '...' every 10Kbytes of a message being received if it is non-nil.
-If it is a number, dots are displayed per the number.")
-
-(defvoo nntp-nov-is-evil nil
- "*If non-nil, nntp will never attempt to use XOVER when talking to the server.")
-
-(defvoo nntp-xover-commands '("XOVER" "XOVERVIEW")
- "*List of strings that are used as commands to fetch NOV lines from a server.
-The strings are tried in turn until a positive response is gotten. If
-none of the commands are successful, nntp will just grab headers one
-by one.")
-
-(defvoo nntp-nov-gap 20
- "*Maximum allowed gap between two articles.
-If the gap between two consecutive articles is bigger than this
-variable, split the XOVER request into two requests.")
-
-(defvoo nntp-connection-timeout nil
- "*Number of seconds to wait before an nntp connection times out.
-If this variable is nil, which is the default, no timers are set.")
-
-(defvoo nntp-command-timeout nil
- "*Number of seconds to wait for a response when sending a command.
-If this variable is nil, which is the default, no timers are set.")
-
-(defvoo nntp-retry-on-break nil
- "*If non-nil, re-send the command when the user types `C-g'.")
-
-(defvoo nntp-news-default-headers nil
- "*If non-nil, override `mail-default-headers' when posting news.")
-
-(defvoo nntp-prepare-server-hook nil
- "*Hook run before a server is opened.
-If can be used to set up a server remotely, for instance. Say you
-have an account at the machine \"other.machine\". This machine has
-access to an NNTP server that you can't access locally. You could
-then use this hook to rsh to the remote machine and start a proxy NNTP
-server there that you can connect to.")
-
-(defvoo nntp-async-number 5
- "*How many articles should be prefetched when in asynchronous mode.")
-
-(defvoo nntp-warn-about-losing-connection t
- "*If non-nil, beep when a server closes connection.")
-
-
-
-(defconst nntp-version "nntp 4.0"
- "Version numbers of this version of NNTP.")
-
-(defvar nntp-server-buffer nil
- "Buffer associated with the NNTP server process.")
-
-(defvoo 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'.")
-
-(defvoo nntp-status-string nil
- "Save the server response message.")
-
-(defvar nntp-opened-connections nil
- "All (possibly) opened connections.")
-
-(defvoo nntp-server-xover 'try)
-(defvoo nntp-server-list-active-group 'try)
-(defvoo nntp-current-group "")
-(defvoo nntp-server-type nil)
-
-(defvoo nntp-async-process nil)
-(defvoo nntp-async-buffer nil)
-(defvoo nntp-async-articles nil)
-(defvoo nntp-async-fetched nil)
-(defvoo nntp-async-group-alist nil)
-
-
-;;; Interface functions.
-
-(nnoo-define-basics nntp)
-
-(deffoo nntp-retrieve-headers (articles &optional group server fetch-old)
- "Retrieve the headers of ARTICLES."
- (nntp-possibly-change-server group server)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (if (and (not gnus-nov-is-evil)
- (not nntp-nov-is-evil)
- (nntp-retrieve-headers-with-xover articles fetch-old))
- ;; We successfully retrieved the headers via XOVER.
- 'nov
- ;; XOVER didn't work, so we do it the hard, slow and inefficient
- ;; way.
- (let ((number (length articles))
- (count 0)
- (received 0)
- (message-log-max nil)
- (last-point (point-min)))
- ;; Send HEAD command.
- (while articles
- (nntp-send-strings-to-server
- "HEAD" (if (numberp (car articles))
- (int-to-string (car articles))
- ;; `articles' is either a list of article numbers
- ;; or a list of article IDs.
- (car articles)))
- (setq articles (cdr articles)
- count (1+ count))
- ;; Every 400 header requests we have to read the stream in
- ;; order to avoid deadlocks.
- (when (or (null articles) ;All requests have been sent.
- (zerop (% count nntp-maximum-request)))
- (nntp-accept-response)
- (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))
- (nnheader-message 7 "NNTP: Receiving headers... %d%%"
- (/ (* received 100) number)))
- (nntp-accept-response))))
- ;; Wait for text of last command.
- (goto-char (point-max))
- (re-search-backward "^[0-9]" nil t)
- (when (looking-at "^[23]")
- (while (progn
- (goto-char (- (point-max) 3))
- (not (looking-at "^\\.\r?\n")))
- (nntp-accept-response)))
- (and (numberp nntp-large-newsgroup)
- (> number nntp-large-newsgroup)
- (nnheader-message 7 "NNTP: Receiving headers...done"))
-
- ;; Now all of replies are received. Fold continuation lines.
- (nnheader-fold-continuation-lines)
- ;; Remove all "\r"'s.
- (goto-char (point-min))
- (while (search-forward "\r" nil t)
- (replace-match "" t t))
- 'headers))))
-
-
-(deffoo nntp-retrieve-groups (groups &optional server)
- "Retrieve group info on GROUPS."
- (nntp-possibly-change-server nil server)
- (save-excursion
- (set-buffer nntp-server-buffer)
- ;; The first time this is run, this variable is `try'. So we
- ;; try.
- (when (eq nntp-server-list-active-group 'try)
- (nntp-try-list-active (car groups)))
- (erase-buffer)
- (let ((count 0)
- (received 0)
- (last-point (point-min))
- (command (if nntp-server-list-active-group "LIST ACTIVE" "GROUP")))
- (while groups
- ;; Send the command to the server.
- (nntp-send-strings-to-server command (car groups))
- (setq groups (cdr groups))
- (setq count (1+ count))
- ;; Every 400 requests we have to read the stream in
- ;; order to avoid deadlocks.
- (when (or (null groups) ;All requests have been sent.
- (zerop (% count nntp-maximum-request)))
- (nntp-accept-response)
- (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))
- (nntp-accept-response))))
-
- ;; Wait for the reply from the final command.
- (when nntp-server-list-active-group
- (goto-char (point-max))
- (re-search-backward "^[0-9]" nil t)
- (when (looking-at "^[23]")
- (while (progn
- (goto-char (- (point-max) 3))
- (not (looking-at "^\\.\r?\n")))
- (nntp-accept-response))))
-
- ;; Now all replies are received. We remove CRs.
- (goto-char (point-min))
- (while (search-forward "\r" nil t)
- (replace-match "" t t))
-
- (if (not nntp-server-list-active-group)
- 'group
- ;; We have read active entries, so we just delete the
- ;; superfluos gunk.
- (goto-char (point-min))
- (while (re-search-forward "^[.2-5]" nil t)
- (delete-region (match-beginning 0)
- (progn (forward-line 1) (point))))
- 'active))))
-
-(deffoo nntp-open-server (server &optional defs connectionless)
- "Open the virtual server SERVER.
-If CONNECTIONLESS is non-nil, don't attempt to connect to any physical
-servers."
- ;; Called with just a port number as the defs.
- (when (or (stringp (car defs))
- (numberp (car defs)))
- (setq defs `((nntp-port-number ,(car defs)))))
- (unless (assq 'nntp-address defs)
- (setq defs (append defs `((nntp-address ,server)))))
- (nnoo-change-server 'nntp server defs)
- (if (nntp-server-opened server)
- t
- (or (nntp-server-opened server)
- connectionless
- (prog2
- (run-hooks 'nntp-prepare-server-hook)
- (nntp-open-server-semi-internal nntp-address nntp-port-number)
- (nnheader-insert "")))))
-
-(deffoo nntp-close-server (&optional server)
- "Close connection to SERVER."
- (nntp-possibly-change-server nil server t)
- (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.
- (when (nntp-server-opened server)
- (nntp-send-command nil "QUIT")
- ;; Give the QUIT time to arrive.
- (sleep-for 1)))
- (nntp-close-server-internal server)))
-
-(deffoo nntp-request-close ()
- "Close all server connections."
- (let (proc)
- (while nntp-opened-connections
- (when (setq proc (pop nntp-opened-connections))
- ;; Un-set default sentinel function before closing connection.
- (when (eq 'nntp-default-sentinel (process-sentinel proc))
- (set-process-sentinel proc nil))
- (condition-case ()
- (process-send-string proc (concat "QUIT" nntp-end-of-line))
- (error nil))
- ;; Give the QUIT time to reach the server before we close
- ;; down the process.
- (sleep-for 1)
- (delete-process proc)))
- (and nntp-async-buffer
- (buffer-name nntp-async-buffer)
- (kill-buffer nntp-async-buffer))
- (let ((alist (cddr (assq 'nntp nnoo-state-alist)))
- entry)
- (while (setq entry (pop alist))
- (and (setq proc (cdr (assq 'nntp-async-buffer entry)))
- (buffer-name proc)
- (kill-buffer proc))))
- (nnoo-close-server 'nntp)
- (setq nntp-async-group-alist nil
- nntp-async-articles nil)))
-
-(deffoo nntp-server-opened (&optional server)
- "Say whether a connection to SERVER has been opened."
- (and (nnoo-current-server-p 'nntp server)
- nntp-server-buffer
- (buffer-name nntp-server-buffer)
- nntp-server-process
- (memq (process-status nntp-server-process) '(open run))))
-
-(deffoo nntp-status-message (&optional server)
- "Return server status as a string."
- (if (and nntp-status-string
- ;; NNN MESSAGE
- (string-match "[0-9][0-9][0-9][ \t]+\\([^\r]*\\).*$"
- nntp-status-string))
- (substring nntp-status-string (match-beginning 1) (match-end 1))
- ;; Empty message if nothing.
- (or nntp-status-string "")))
-
-(deffoo nntp-request-article (id &optional group server buffer)
- "Request article ID (Message-ID or number)."
- (nntp-possibly-change-server group server)
-
- (let (found)
-
- ;; First we see whether we can get the article from the async buffer.
- (when (and (numberp id)
- nntp-async-articles
- (memq id nntp-async-fetched))
- (save-excursion
- (set-buffer nntp-async-buffer)
- (let ((opoint (point))
- (art (if (numberp id) (int-to-string id) id))
- beg end)
- (when (and (or (re-search-forward (concat "^2.. +" art) nil t)
- (progn
- (goto-char (point-min))
- (re-search-forward (concat "^2.. +" art) opoint t)))
- (progn
- (beginning-of-line)
- (setq beg (point)
- end (re-search-forward "^\\.\r?\n" nil t))))
- (setq found t)
- (save-excursion
- (set-buffer (or buffer nntp-server-buffer))
- (erase-buffer)
- (insert-buffer-substring nntp-async-buffer beg end)
- (let ((nntp-server-buffer (current-buffer)))
- (nntp-decode-text)))
- (delete-region beg end)
- (when nntp-async-articles
- (nntp-async-fetch-articles id))))))
-
- (if found
- id
- ;; The article was not in the async buffer, so we fetch it now.
- (unwind-protect
- (progn
- (if buffer (set-process-buffer nntp-server-process buffer))
- (let ((nntp-server-buffer (or buffer nntp-server-buffer))
- (art (or (and (numberp id) (int-to-string id)) id)))
- (prog1
- (and (nntp-send-command
- ;; A bit odd regexp to ensure working over rlogin.
- "^\\.\r?\n" "ARTICLE" art)
- (if (numberp id)
- (cons nntp-current-group id)
- ;; We find out what the article number was.
- (nntp-find-group-and-number)))
- (nntp-decode-text)
- (and nntp-async-articles (nntp-async-fetch-articles id)))))
- (when buffer
- (set-process-buffer nntp-server-process nntp-server-buffer))))))
-
-(deffoo nntp-request-body (id &optional group server)
- "Request body of article ID (Message-ID or number)."
- (nntp-possibly-change-server group server)
- (prog1
- ;; If NEmacs, end of message may look like: "\256\215" (".^M")
- (nntp-send-command
- "^\\.\r?\n" "BODY" (or (and (numberp id) (int-to-string id)) id))
- (nntp-decode-text)))
-
-(deffoo nntp-request-head (id &optional group server)
- "Request head of article ID (Message-ID or number)."
- (nntp-possibly-change-server group server)
- (prog1
- (when (nntp-send-command
- "^\\.\r?\n" "HEAD" (if (numberp id) (int-to-string id) id))
- (if (numberp id) id
- ;; We find out what the article number was.
- (nntp-find-group-and-number)))
- (nntp-decode-text)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (nnheader-fold-continuation-lines))))
-
-(deffoo nntp-request-stat (id &optional group server)
- "Request STAT of article ID (Message-ID or number)."
- (nntp-possibly-change-server group server)
- (nntp-send-command
- "^[23].*\r?\n" "STAT" (or (and (numberp id) (int-to-string id)) id)))
-
-(deffoo nntp-request-type (group &optional article)
- 'news)
-
-(deffoo nntp-request-group (group &optional server dont-check)
- "Select GROUP."
- (nntp-possibly-change-server nil server)
- (setq nntp-current-group
- (when (nntp-send-command "^2.*\r?\n" "GROUP" group)
- group)))
-
-(deffoo nntp-request-asynchronous (group &optional server articles)
- "Enable pre-fetch in GROUP."
- (when nntp-async-articles
- (nntp-async-request-group group))
- (when nntp-async-number
- (if (not (or (nntp-async-server-opened)
- (nntp-async-open-server)))
- ;; Couldn't open the second connection
- (progn
- (message "Can't open second connection to %s" nntp-address)
- (ding)
- (setq nntp-async-articles nil)
- (sit-for 2))
- ;; We opened the second connection (or it was opened already).
- (setq nntp-async-articles articles)
- (setq nntp-async-fetched nil)
- ;; Clear any old data.
- (save-excursion
- (set-buffer nntp-async-buffer)
- (erase-buffer))
- ;; Select the correct current group on this server.
- (nntp-async-send-strings "GROUP" group)
- t)))
-
-(deffoo nntp-list-active-group (group &optional server)
- "Return the active info on GROUP (which can be a regexp."
- (nntp-possibly-change-server group server)
- (nntp-send-command "^.*\r?\n" "LIST ACTIVE" group))
-
-(deffoo nntp-request-group-description (group &optional server)
- "Get the description of GROUP."
- (nntp-possibly-change-server nil server)
- (prog1
- (nntp-send-command "^.*\r?\n" "XGTITLE" group)
- (nntp-decode-text)))
-
-(deffoo nntp-close-group (group &optional server)
- "Close GROUP."
- (setq nntp-current-group nil)
- t)
-
-(deffoo nntp-request-list (&optional server)
- "List all active groups."
- (nntp-possibly-change-server nil server)
- (prog1
- (nntp-send-command "^\\.\r?\n" "LIST")
- (nntp-decode-text)))
-
-(deffoo nntp-request-list-newsgroups (&optional server)
- "Get descriptions on all groups on SERVER."
- (nntp-possibly-change-server nil server)
- (prog1
- (nntp-send-command "^\\.\r?\n" "LIST NEWSGROUPS")
- (nntp-decode-text)))
-
-(deffoo nntp-request-newgroups (date &optional server)
- "List groups that have arrived since DATE."
- (nntp-possibly-change-server nil server)
- (let* ((date (timezone-parse-date date))
- (time-string
- (format "%s%02d%02d %s%s%s"
- (substring (aref date 0) 2) (string-to-int (aref date 1))
- (string-to-int (aref date 2)) (substring (aref date 3) 0 2)
- (substring
- (aref date 3) 3 5) (substring (aref date 3) 6 8))))
- (prog1
- (nntp-send-command "^\\.\r?\n" "NEWGROUPS" time-string)
- (nntp-decode-text))))
-
-(deffoo nntp-request-list-distributions (&optional server)
- "List distributions."
- (nntp-possibly-change-server nil server)
- (prog1
- (nntp-send-command "^\\.\r?\n" "LIST DISTRIBUTIONS")
- (nntp-decode-text)))
-
-(deffoo nntp-request-last (&optional group server)
- "Decrease the current article pointer."
- (nntp-possibly-change-server group server)
- (nntp-send-command "^[23].*\r?\n" "LAST"))
-
-(deffoo nntp-request-next (&optional group server)
- "Advance the current article pointer."
- (nntp-possibly-change-server group server)
- (nntp-send-command "^[23].*\r?\n" "NEXT"))
-
-(deffoo nntp-request-post (&optional server)
- "Post the current buffer."
- (nntp-possibly-change-server nil server)
- (when (nntp-send-command "^[23].*\r?\n" "POST")
- (nnheader-insert "")
- (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].*\n")))
-
-;;; Internal functions.
-
-(defun nntp-send-mode-reader ()
- "Send the MODE READER command to the nntp server.
-This function is supposed to be called from `nntp-server-opened-hook'.
-It will make innd servers spawn an nnrpd process to allow actual article
-reading."
- (nntp-send-command "^.*\r?\n" "MODE READER"))
-
-(defun nntp-send-nosy-authinfo ()
- "Send the AUTHINFO to the nntp server.
-This function is supposed to be called from `nntp-server-opened-hook'.
-It will prompt for a password."
- (nntp-send-command "^.*\r?\n" "AUTHINFO USER"
- (read-string "NNTP user name: "))
- (nntp-send-command "^.*\r?\n" "AUTHINFO PASS"
- (read-string "NNTP password: ")))
-
-(defun nntp-send-authinfo ()
- "Send the AUTHINFO to the nntp server.
-This function is supposed to be called from `nntp-server-opened-hook'.
-It will prompt for a password."
- (nntp-send-command "^.*\r?\n" "AUTHINFO USER" (user-login-name))
- (nntp-send-command "^.*\r?\n" "AUTHINFO PASS"
- (read-string "NNTP password: ")))
-
-(defun nntp-send-authinfo-from-file ()
- "Send the AUTHINFO to the nntp server.
-This function is supposed to be called from `nntp-server-opened-hook'.
-It will prompt for a password."
- (when (file-exists-p "~/.nntp-authinfo")
- (save-excursion
- (set-buffer (get-buffer-create " *authinfo*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (insert-file-contents "~/.nntp-authinfo")
- (goto-char (point-min))
- (nntp-send-command "^.*\r?\n" "AUTHINFO USER" (user-login-name))
- (nntp-send-command
- "^.*\r?\n" "AUTHINFO PASS"
- (buffer-substring (point) (progn (end-of-line) (point))))
- (kill-buffer (current-buffer)))))
-
-(defun nntp-default-sentinel (proc status)
- "Default sentinel function for NNTP server process."
- (let ((servers (cddr (assq 'nntp nnoo-state-alist)))
- server)
- ;; Go through the alist of server names and find the name of the
- ;; server that the process that sent the signal is connected to.
- ;; If you get my drift.
- (if (equal proc nntp-server-process)
- (setq server nntp-address)
- (while (and servers
- (not (equal proc (cdr (assq 'nntp-server-process
- (car servers))))))
- (setq servers (cdr servers)))
- (setq server (caar servers)))
- (when (and server
- nntp-warn-about-losing-connection)
- (nnheader-message 3 "nntp: Connection closed to server %s" server)
- (setq nntp-current-group "")
- (ding))))
-
-(defun nntp-kill-connection (server)
- "Choke the connection to SERVER."
- (let ((proc (cdr (assq 'nntp-server-process
- (assoc server (cddr
- (assq 'nntp nnoo-state-alist)))))))
- (when proc
- (delete-process (process-name proc)))
- (nntp-close-server server)
- (nnheader-report
- 'nntp (message "Connection timed out to server %s" server))
- (ding)
- (sit-for 1)))
-
-;; 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))
- (or (bolp) (insert "\n"))
- ;; Delete status line.
- (delete-region (goto-char (point-min)) (progn (forward-line 1) (point)))
- ;; Delete `^M's.
- (while (search-forward "\r" nil t)
- (replace-match "" t t))
- ;; Delete `.' at end of the buffer (end of text mark).
- (goto-char (point-max))
- (forward-line -1)
- (when (looking-at "^\\.\n")
- (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
- ;; Replace `.' at beginning of line with `..'.
- (goto-char (point-min))
- (while (search-forward "\n." nil t)
- (insert "."))
- (goto-char (point-max))
- ;; Insert newline at end of buffer.
- (or (bolp) (insert "\n"))
- ;; Insert `.' at end of buffer (end of text mark).
- (insert "." nntp-end-of-line)))
-
-
-;;;
-;;; Synchronous Communication with NNTP servers.
-;;;
-
-(defvar nntp-retry-command)
-
-(defun nntp-send-command (response cmd &rest args)
- "Wait for server RESPONSE after sending CMD and optional ARGS to server."
- (let ((timer
- (and nntp-command-timeout
- (nnheader-run-at-time
- nntp-command-timeout nil 'nntp-kill-command
- (nnoo-current-server 'nntp))))
- (nntp-retry-command t)
- result)
- (unwind-protect
- (save-excursion
- (while nntp-retry-command
- (setq nntp-retry-command nil)
- ;; Clear communication buffer.
- (set-buffer nntp-server-buffer)
- (widen)
- (erase-buffer)
- (if nntp-retry-on-break
- (condition-case ()
- (progn
- (apply 'nntp-send-strings-to-server cmd args)
- (setq result
- (if response
- (nntp-wait-for-response response)
- t)))
- (quit (setq nntp-retry-command t)))
- (apply 'nntp-send-strings-to-server cmd args)
- (setq result
- (if response
- (nntp-wait-for-response response)
- t))))
- result)
- (when timer
- (nnheader-cancel-timer timer)))))
-
-(defun nntp-kill-command (server)
- "Kill and restart the connection to SERVER."
- (let ((proc (cdr (assq
- 'nntp-server-process
- (assoc server (cddr (assq 'nntp nnoo-state-alist)))))))
- (when proc
- (delete-process (process-name proc)))
- (nntp-close-server server)
- (nntp-open-server server)
- (when nntp-current-group
- (nntp-request-group nntp-current-group))
- (setq nntp-retry-command t)))
-
-(defun nntp-send-command-old (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 &optional slow)
- "Wait for server response which matches REGEXP."
- (save-excursion
- (let ((status t)
- (wait t)
- (dotnum 0) ;Number of "." being displayed.
- (dotsize ;How often "." displayed.
- (if (numberp nntp-debug-read) nntp-debug-read 10000)))
- (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))
- (if slow
- (progn
- (cond ((re-search-forward "^[23][0-9][0-9]" nil t)
- (setq wait nil))
- ((re-search-forward "^[45][0-9][0-9]" nil t)
- (setq status nil)
- (setq wait nil))
- (t (nntp-accept-response)))
- (if (not wait) (delete-region (point-min)
- (progn (beginning-of-line)
- (point)))))
- (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-string
- (nnheader-replace-chars-in-string
- (buffer-substring (point-min) (point)) ?\r ? ))
- (when status
- (setq wait t)
- (while wait
- (goto-char (point-max))
- (if (bolp) (forward-line -1) (beginning-of-line))
- (if (looking-at regexp)
- (setq wait nil)
- (when nntp-debug-read
- (let ((newnum (/ (buffer-size) dotsize))
- (message-log-max nil))
- (unless (= dotnum newnum)
- (setq dotnum newnum)
- (nnheader-message 7 "NNTP: Reading %s"
- (make-string dotnum ?.)))))
- (nntp-accept-response)))
- ;; Remove "...".
- (when (and nntp-debug-read (> dotnum 0))
- (message ""))
- ;; Successfully received server response.
- t))))
-
-
-
-;;;
-;;; Low-Level Interface to NNTP Server.
-;;;
-
-(defun nntp-find-group-and-number ()
- (save-excursion
- (save-restriction
- (set-buffer nntp-server-buffer)
- (narrow-to-region (goto-char (point-min))
- (or (search-forward "\n\n" nil t) (point-max)))
- (goto-char (point-min))
- ;; We first find the number by looking at the status line.
- (let ((number (and (looking-at "2[0-9][0-9] +\\([0-9]+\\) ")
- (string-to-int
- (buffer-substring (match-beginning 1)
- (match-end 1)))))
- group newsgroups xref)
- (and number (zerop number) (setq number nil))
- ;; Then we find the group name.
- (setq group
- (cond
- ;; If there is only one group in the Newsgroups header,
- ;; then it seems quite likely that this article comes
- ;; from that group, I'd say.
- ((and (setq newsgroups (mail-fetch-field "newsgroups"))
- (not (string-match "," newsgroups)))
- newsgroups)
- ;; If there is more than one group in the Newsgroups
- ;; header, then the Xref header should be filled out.
- ;; We hazard a guess that the group that has this
- ;; article number in the Xref header is the one we are
- ;; looking for. This might very well be wrong if this
- ;; article happens to have the same number in several
- ;; groups, but that's life.
- ((and (setq xref (mail-fetch-field "xref"))
- number
- (string-match (format "\\([^ :]+\\):%d" number) xref))
- (substring xref (match-beginning 1) (match-end 1)))
- (t "")))
- (when (string-match "\r" group)
- (setq group (substring group 0 (match-beginning 0))))
- (cons group number)))))
-
-(defun nntp-retrieve-headers-with-xover (articles &optional fetch-old)
- (erase-buffer)
- (cond
-
- ;; This server does not talk NOV.
- ((not nntp-server-xover)
- nil)
-
- ;; We don't care about gaps.
- ((or (not nntp-nov-gap)
- fetch-old)
- (nntp-send-xover-command
- (if fetch-old
- (if (numberp fetch-old)
- (max 1 (- (car articles) fetch-old))
- 1)
- (car articles))
- (nntp-last-element articles) 'wait)
-
- (goto-char (point-min))
- (when (looking-at "[1-5][0-9][0-9] ")
- (delete-region (point) (progn (forward-line 1) (point))))
- (while (search-forward "\r" nil t)
- (replace-match "" t t))
- (goto-char (point-max))
- (forward-line -1)
- (when (looking-at "\\.")
- (delete-region (point) (progn (forward-line 1) (point)))))
-
- ;; We do it the hard way. For each gap, an XOVER command is sent
- ;; to the server. We do not wait for a reply from the server, we
- ;; just send them off as fast as we can. That means that we have
- ;; to count the number of responses we get back to find out when we
- ;; have gotten all we asked for.
- ((numberp nntp-nov-gap)
- (let ((count 0)
- (received 0)
- (last-point (point-min))
- (buf (current-buffer))
- first)
- ;; We have to check `nntp-server-xover'. If it gets set to nil,
- ;; that means that the server does not understand XOVER, but we
- ;; won't know that until we try.
- (while (and nntp-server-xover articles)
- (setq first (car articles))
- ;; Search forward until we find a gap, or until we run out of
- ;; articles.
- (while (and (cdr articles)
- (< (- (nth 1 articles) (car articles)) nntp-nov-gap))
- (setq articles (cdr articles)))
-
- (when (nntp-send-xover-command first (car articles))
- (setq articles (cdr articles)
- count (1+ count))
-
- ;; Every 400 requests we have to read the stream in
- ;; order to avoid deadlocks.
- (when (or (null articles) ;All requests have been sent.
- (zerop (% count nntp-maximum-request)))
- (accept-process-output)
- ;; On some Emacs versions the preceding function has
- ;; a tendency to change the buffer. Perhaps. It's
- ;; quite difficult to reproduce, because it only
- ;; seems to happen once in a blue moon.
- (set-buffer buf)
- (while (progn
- (goto-char last-point)
- ;; Count replies.
- (while (re-search-forward "^[0-9][0-9][0-9] " nil t)
- (setq received (1+ received)))
- (setq last-point (point))
- (< received count))
- (accept-process-output)
- (set-buffer buf)))))
-
- (when nntp-server-xover
- ;; Wait for the reply from the final command.
- (goto-char (point-max))
- (re-search-backward "^[0-9][0-9][0-9] " nil t)
- (when (looking-at "^[23]")
- (while (progn
- (goto-char (point-max))
- (forward-line -1)
- (not (looking-at "^\\.\r?\n")))
- (nntp-accept-response)))
-
- ;; We remove any "." lines and status lines.
- (goto-char (point-min))
- (while (search-forward "\r" nil t)
- (delete-char -1))
- (goto-char (point-min))
- (delete-matching-lines "^\\.$\\|^[1-5][0-9][0-9] ")))))
-
- nntp-server-xover)
-
-(defun nntp-send-xover-command (beg end &optional wait-for-reply)
- "Send the XOVER command to the server."
- (let ((range (format "%d-%d" (or beg 1) (or end beg 1))))
- (if (stringp nntp-server-xover)
- ;; If `nntp-server-xover' is a string, then we just send this
- ;; command.
- (if wait-for-reply
- (nntp-send-command "^\\.\r?\n" nntp-server-xover range)
- ;; We do not wait for the reply.
- (nntp-send-strings-to-server nntp-server-xover range))
- (let ((commands nntp-xover-commands))
- ;; `nntp-xover-commands' is a list of possible XOVER commands.
- ;; We try them all until we get at positive response.
- (while (and commands (eq nntp-server-xover 'try))
- (nntp-send-command "^\\.\r?\n" (car commands) range)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (and (looking-at "[23]") ; No error message.
- ;; We also have to look at the lines. Some buggy
- ;; servers give back simple lines with just the
- ;; article number. How... helpful.
- (progn
- (forward-line 1)
- (looking-at "[0-9]+\t...")) ; More text after number.
- (setq nntp-server-xover (car commands))))
- (setq commands (cdr commands)))
- ;; If none of the commands worked, we disable XOVER.
- (when (eq nntp-server-xover 'try)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (setq nntp-server-xover nil)))
- nntp-server-xover))))
-
-(defun nntp-send-strings-to-server (&rest strings)
- "Send STRINGS to the server."
- (let ((cmd (concat (mapconcat 'identity strings " ") nntp-end-of-line)))
- ;; We open the nntp server if it is down.
- (or (nntp-server-opened (nnoo-current-server 'nntp))
- (nntp-open-server (nnoo-current-server 'nntp))
- (error (nntp-status-message)))
- ;; Send the strings.
- (process-send-string nntp-server-process cmd)
- t))
-
-(defun nntp-send-region-to-server (begin end)
- "Send the current buffer region (from BEGIN to END) to the server."
- (save-excursion
- (let ((cur (current-buffer)))
- ;; Copy the buffer over to the send buffer.
- (nnheader-set-temp-buffer " *nntp send*")
- (insert-buffer-substring cur begin end)
- (save-excursion
- (set-buffer cur)
- (erase-buffer))
- ;; `process-send-region' does not work if the text to be sent is very
- ;; large, so we send it piecemeal.
- (let ((last (point-min))
- (size 100)) ;Size of text sent at once.
- (while (and (/= last (point-max))
- (memq (process-status nntp-server-process) '(open run)))
- (process-send-region
- nntp-server-process
- last (setq last (min (+ last size) (point-max))))
- ;; Read any output from the server. May be unnecessary.
- (accept-process-output)))
- (kill-buffer (current-buffer)))))
-
-(defun nntp-open-server-semi-internal (server &optional service)
- "Open SERVER.
-If SERVER is nil, use value of environment variable `NNTPSERVER'.
-If SERVICE, this this as the port number."
- (nnheader-insert "")
- (let ((server (or server (getenv "NNTPSERVER")))
- (status nil)
- (timer
- (and nntp-connection-timeout
- (nnheader-run-at-time nntp-connection-timeout
- nil 'nntp-kill-connection server))))
- (save-excursion
- (set-buffer nntp-server-buffer)
- (setq nntp-status-string "")
- (nnheader-message 5 "nntp: Connecting to server on %s..." nntp-address)
- (cond ((and server (nntp-open-server-internal server service))
- (setq nntp-address server)
- (setq status
- (condition-case nil
- (nntp-wait-for-response "^[23].*\r?\n" 'slow)
- (error nil)
- (quit nil)))
- (unless status
- (nntp-close-server-internal server)
- (nnheader-report
- 'nntp "Couldn't open connection to %s"
- (if (and nntp-address
- (not (equal nntp-address "")))
- nntp-address server)))
- (when nntp-server-process
- (set-process-sentinel
- nntp-server-process 'nntp-default-sentinel)
- ;; You can send commands at startup like AUTHINFO here.
- ;; Added by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>
- (run-hooks 'nntp-server-opened-hook)))
- ((null server)
- (nnheader-report 'nntp "NNTP server is not specified."))
- (t ; We couldn't open the server.
- (nnheader-report
- 'nntp (buffer-substring (point-min) (point-max)))))
- (when timer
- (nnheader-cancel-timer timer))
- (message "")
- (unless status
- (nnoo-close-server 'nntp server)
- (setq nntp-async-number nil))
- status)))
-
-(defvar nntp-default-directories '("~" "/tmp" "/")
- "Directories to as current directory in the nntp server buffer.")
-
-(defun nntp-open-server-internal (server &optional service)
- "Open connection to news server on SERVER by SERVICE (default is nntp)."
- (let (proc)
- (save-excursion
- (set-buffer nntp-server-buffer)
- ;; Make sure we have a valid current directory for the
- ;; nntp server buffer.
- (unless (file-exists-p default-directory)
- (let ((dirs nntp-default-directories))
- (while dirs
- (when (file-exists-p (car dirs))
- (setq default-directory (car dirs)
- dirs nil))
- (setq dirs (cdr dirs)))))
- (cond
- ((and (setq proc
- (condition-case nil
- (funcall nntp-open-server-function server)
- (error nil)))
- (memq (process-status proc) '(open run)))
- (setq nntp-server-process proc)
- (setq nntp-address server)
- ;; Suggested by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
- (process-kill-without-query proc)
- (run-hooks 'nntp-server-hook)
- (push proc nntp-opened-connections)
- (condition-case ()
- (nntp-read-server-type)
- (error
- (nnheader-report 'nntp "Couldn't open server %s" server)
- (nntp-close-server)))
- nntp-server-process)
- (t
- (nnheader-report 'nntp "Couldn't open server %s" server))))))
-
-(defun nntp-read-server-type ()
- "Find out what the name of the server we have connected to is."
- ;; Wait for the status string to arrive.
- (nntp-wait-for-response "^.*\n" t)
- (setq nntp-server-type (buffer-string))
- (let ((alist nntp-server-action-alist)
- entry)
- ;; Run server-specific commmands.
- (while alist
- (setq entry (pop alist))
- (when (string-match (car entry) nntp-server-type)
- (if (and (listp (cadr entry))
- (not (eq 'lambda (caadr entry))))
- (eval (cadr entry))
- (funcall (cadr entry)))))))
-
-(defun nntp-open-network-stream (server)
- (open-network-stream
- "nntpd" nntp-server-buffer server nntp-port-number))
-
-(defun nntp-open-rlogin (server)
- (let ((proc (if nntp-rlogin-user-name
- (start-process
- "nntpd" nntp-server-buffer "rsh"
- "-l" nntp-rlogin-user-name server
- (mapconcat 'identity
- nntp-rlogin-parameters " "))
- (start-process
- "nntpd" nntp-server-buffer "rsh" server
- (mapconcat 'identity
- nntp-rlogin-parameters " ")))))
- proc))
-
-(defun nntp-telnet-to-machine ()
- (let (b)
- (telnet "localhost")
- (goto-char (point-min))
- (while (not (re-search-forward "^login: *" nil t))
- (sit-for 1)
- (goto-char (point-min)))
- (goto-char (point-max))
- (insert "larsi")
- (telnet-send-input)
- (setq b (point))
- (while (not (re-search-forward ">" nil t))
- (sit-for 1)
- (goto-char b))
- (goto-char (point-max))
- (insert "ls")
- (telnet-send-input)))
-
-(defun nntp-close-server-internal (&optional server)
- "Close connection to news server."
- (nntp-possibly-change-server nil server)
- (if nntp-server-process
- (delete-process nntp-server-process))
- (setq nntp-server-process nil)
- (setq nntp-address ""))
-
-(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'.
- (let ((buf (current-buffer)))
- (prog1
- (if (or (not nntp-server-process)
- (not (memq (process-status nntp-server-process) '(open run))))
- (error "nntp: Process connection closed; %s" (nntp-status-message))
- (if nntp-buggy-select
- (progn
- ;; We cannot use `accept-process-output'.
- ;; Fujitsu UTS requires messages during sleep-for.
- ;; I don't know why.
- (nnheader-message 5 "NNTP: Reading...")
- (sleep-for 1)
- (nnheader-message 5 ""))
- (condition-case errorcode
- (accept-process-output nntp-server-process 1)
- (error
- (cond ((string-equal "select error: Invalid argument"
- (nth 1 errorcode))
- ;; Ignore select error.
- nil)
- (t
- (signal (car errorcode) (cdr errorcode))))))))
- (set-buffer buf))))
-
-(defun nntp-last-element (list)
- "Return last element of LIST."
- (while (cdr list)
- (setq list (cdr list)))
- (car list))
-
-(defun nntp-possibly-change-server (newsgroup server &optional connectionless)
- "Check whether the virtual server needs changing."
- (when (and server
- (not (nntp-server-opened server)))
- ;; This virtual server isn't open, so we (re)open it here.
- (nntp-open-server server nil t))
- (when (and newsgroup
- (not (equal newsgroup nntp-current-group)))
- ;; Set the proper current group.
- (nntp-request-group newsgroup server)))
-
-(defun nntp-try-list-active (group)
- (nntp-list-active-group group)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (goto-char (point-min))
- (cond ((looking-at "5[0-9]+")
- (setq nntp-server-list-active-group nil))
- (t
- (setq nntp-server-list-active-group t)))))
-
-(defun nntp-async-server-opened ()
- (and nntp-async-process
- (memq (process-status nntp-async-process) '(open run))))
-
-(defun nntp-async-open-server ()
- (save-excursion
- (set-buffer (generate-new-buffer " *async-nntp*"))
- (setq nntp-async-buffer (current-buffer))
- (buffer-disable-undo (current-buffer)))
- (let ((nntp-server-process nil)
- (nntp-server-buffer nntp-async-buffer))
- (nntp-open-server-semi-internal nntp-address nntp-port-number)
- (if (not (setq nntp-async-process nntp-server-process))
- (progn
- (setq nntp-async-number nil))
- (set-process-buffer nntp-async-process nntp-async-buffer))))
-
-(defun nntp-async-fetch-articles (article)
- (if (stringp article)
- ()
- (let ((articles (cdr (memq (assq article nntp-async-articles)
- nntp-async-articles)))
- (max (cond ((numberp nntp-async-number)
- nntp-async-number)
- ((eq nntp-async-number t)
- (length nntp-async-articles))
- (t 0)))
- nart)
- (while (and (>= (setq max (1- max)) 0)
- articles)
- (or (memq (setq nart (caar articles)) nntp-async-fetched)
- (progn
- (nntp-async-send-strings "ARTICLE " (int-to-string nart))
- (setq nntp-async-fetched (cons nart nntp-async-fetched))))
- (setq articles (cdr articles))))))
-
-(defun nntp-async-send-strings (&rest strings)
- (let ((cmd (concat (mapconcat 'identity strings " ") nntp-end-of-line)))
- (or (nntp-async-server-opened)
- (nntp-async-open-server)
- (error (nntp-status-message)))
- (process-send-string nntp-async-process cmd)))
-
-(defun nntp-async-request-group (group)
- (if (equal group nntp-current-group)
- ()
- (let ((asyncs (assoc group nntp-async-group-alist)))
- ;; A new group has been selected, so we push the current state
- ;; of async articles on an alist, and pull the old state off.
- (setq nntp-async-group-alist
- (cons (list nntp-current-group
- nntp-async-articles nntp-async-fetched
- nntp-async-process)
- (delq asyncs nntp-async-group-alist)))
- (and asyncs
- (progn
- (setq nntp-async-articles (nth 1 asyncs))
- (setq nntp-async-fetched (nth 2 asyncs))
- (setq nntp-async-process (nth 3 asyncs)))))))
-
-(provide 'nntp)
-
-;;; nntp.el ends here
diff --git a/lisp/nnvirtual.el b/lisp/nnvirtual.el
deleted file mode 100644
index 47269c0de69..00000000000
--- a/lisp/nnvirtual.el
+++ /dev/null
@@ -1,409 +0,0 @@
-;;; nnvirtual.el --- virtual newsgroups access for Gnus
-;; Copyright (C) 1994,95,96 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The other access methods (nntp, nnspool, etc) are general news
-;; access methods. This module relies on Gnus and can not be used
-;; separately.
-
-;;; Code:
-
-(require 'nntp)
-(require 'nnheader)
-(require 'gnus)
-(require 'nnoo)
-(eval-when-compile (require 'cl))
-
-(nnoo-declare nnvirtual)
-
-(defvoo nnvirtual-always-rescan nil
- "*If non-nil, always scan groups for unread articles when entering a group.
-If this variable is nil (which is the default) and you read articles
-in a component group after the virtual group has been activated, the
-read articles from the component group will show up when you enter the
-virtual group.")
-
-(defvoo nnvirtual-component-regexp nil
- "*Regexp to match component groups.")
-
-
-
-(defconst nnvirtual-version "nnvirtual 1.0")
-
-(defvoo nnvirtual-current-group nil)
-(defvoo nnvirtual-component-groups nil)
-(defvoo nnvirtual-mapping nil)
-
-(defvoo nnvirtual-status-string "")
-
-(eval-and-compile
- (autoload 'gnus-cache-articles-in-group "gnus-cache"))
-
-
-
-;;; Interface functions.
-
-(nnoo-define-basics nnvirtual)
-
-(deffoo nnvirtual-retrieve-headers (articles &optional newsgroup
- server fetch-old)
- (when (nnvirtual-possibly-change-server server)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (if (stringp (car articles))
- 'headers
- (let ((vbuf (nnheader-set-temp-buffer
- (get-buffer-create " *virtual headers*")))
- (unfetched (mapcar (lambda (g) (list g))
- nnvirtual-component-groups))
- (system-name (system-name))
- cgroup article result prefix)
- (while articles
- (setq article (assq (pop articles) nnvirtual-mapping))
- (when (and (setq cgroup (cadr article))
- (gnus-check-server
- (gnus-find-method-for-group cgroup) t)
- (gnus-request-group cgroup t))
- (setq prefix (gnus-group-real-prefix cgroup))
- (when (setq result (gnus-retrieve-headers
- (list (caddr article)) cgroup nil))
- (set-buffer nntp-server-buffer)
- (if (zerop (buffer-size))
- (nconc (assq cgroup unfetched) (list (caddr article)))
- ;; If we got HEAD headers, we convert them into NOV
- ;; headers. This is slow, inefficient and, come to think
- ;; of it, downright evil. So sue me. I couldn't be
- ;; bothered to write a header parse routine that could
- ;; parse a mixed HEAD/NOV buffer.
- (when (eq result 'headers)
- (nnvirtual-convert-headers))
- (goto-char (point-min))
- (while (not (eobp))
- (delete-region
- (point) (progn (read nntp-server-buffer) (point)))
- (princ (car article) (current-buffer))
- (beginning-of-line)
- (looking-at
- "[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t")
- (goto-char (match-end 0))
- (or (search-forward
- "\t" (save-excursion (end-of-line) (point)) t)
- (end-of-line))
- (while (= (char-after (1- (point))) ? )
- (forward-char -1)
- (delete-char 1))
- (if (eolp)
- (progn
- (end-of-line)
- (or (= (char-after (1- (point))) ?\t)
- (insert ?\t))
- (insert "Xref: " system-name " " cgroup ":")
- (princ (caddr article) (current-buffer))
- (insert "\t"))
- (insert "Xref: " system-name " " cgroup ":")
- (princ (caddr article) (current-buffer))
- (insert " ")
- (if (not (string= "" prefix))
- (while (re-search-forward
- "[^ ]+:[0-9]+"
- (save-excursion (end-of-line) (point)) t)
- (save-excursion
- (goto-char (match-beginning 0))
- (insert prefix))))
- (end-of-line)
- (or (= (char-after (1- (point))) ?\t)
- (insert ?\t)))
- (forward-line 1))
- (set-buffer vbuf)
- (goto-char (point-max))
- (insert-buffer-substring nntp-server-buffer)))))
-
- ;; In case some of the articles have expired or been
- ;; cancelled, we have to mark them as read in the
- ;; component group.
- (while unfetched
- (when (cdar unfetched)
- (gnus-group-make-articles-read
- (caar unfetched) (sort (cdar unfetched) '<)))
- (setq unfetched (cdr unfetched)))
-
- ;; The headers are ready for reading, so they are inserted into
- ;; the nntp-server-buffer, which is where Gnus expects to find
- ;; them.
- (prog1
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (insert-buffer-substring vbuf)
- 'nov)
- (kill-buffer vbuf)))))))
-
-(deffoo nnvirtual-request-article (article &optional group server buffer)
- (when (and (nnvirtual-possibly-change-server server)
- (numberp article))
- (let* ((amap (assq article nnvirtual-mapping))
- (cgroup (cadr amap)))
- (cond
- ((not amap)
- (nnheader-report 'nnvirtual "No such article: %s" article))
- ((not (gnus-check-group cgroup))
- (nnheader-report
- 'nnvirtual "Can't open server where %s exists" cgroup))
- ((not (gnus-request-group cgroup t))
- (nnheader-report 'nnvirtual "Can't open component group %s" cgroup))
- (t
- (if buffer
- (save-excursion
- (set-buffer buffer)
- (gnus-request-article-this-buffer (caddr amap) cgroup))
- (gnus-request-article (caddr amap) cgroup)))))))
-
-(deffoo nnvirtual-open-server (server &optional defs)
- (unless (assq 'nnvirtual-component-regexp defs)
- (push `(nnvirtual-component-regexp ,server)
- defs))
- (nnoo-change-server 'nnvirtual server defs)
- (if nnvirtual-component-groups
- t
- (setq nnvirtual-mapping nil)
- ;; Go through the newsrc alist and find all component groups.
- (let ((newsrc (cdr gnus-newsrc-alist))
- group)
- (while (setq group (car (pop newsrc)))
- (when (string-match nnvirtual-component-regexp group) ; Match
- ;; Add this group to the list of component groups.
- (setq nnvirtual-component-groups
- (cons group (delete group nnvirtual-component-groups))))))
- (if (not nnvirtual-component-groups)
- (nnheader-report 'nnvirtual "No component groups: %s" server)
- t)))
-
-(deffoo nnvirtual-request-group (group &optional server dont-check)
- (nnvirtual-possibly-change-server server)
- (setq nnvirtual-component-groups
- (delete (nnvirtual-current-group) nnvirtual-component-groups))
- (cond
- ((null nnvirtual-component-groups)
- (setq nnvirtual-current-group nil)
- (nnheader-report 'nnvirtual "No component groups in %s" group))
- (t
- (unless dont-check
- (nnvirtual-create-mapping))
- (setq nnvirtual-current-group group)
- (let ((len (length nnvirtual-mapping)))
- (nnheader-insert "211 %d 1 %d %s\n" len len group)))))
-
-(deffoo nnvirtual-request-type (group &optional article)
- (if (not article)
- 'unknown
- (let ((mart (assq article nnvirtual-mapping)))
- (when mart
- (gnus-request-type (cadr mart) (car mart))))))
-
-(deffoo nnvirtual-request-update-mark (group article mark)
- (let* ((nart (assq article nnvirtual-mapping))
- (cgroup (cadr nart))
- ;; The component group might be a virtual group.
- (nmark (gnus-request-update-mark cgroup (caddr nart) mark)))
- (when (and nart
- (= mark nmark)
- (gnus-group-auto-expirable-p cgroup))
- (setq mark gnus-expirable-mark)))
- mark)
-
-(deffoo nnvirtual-close-group (group &optional server)
- (when (nnvirtual-possibly-change-server server)
- ;; Copy (un)read articles.
- (nnvirtual-update-reads)
- ;; We copy the marks from this group to the component
- ;; groups here.
- (nnvirtual-update-marked))
- t)
-
-(deffoo nnvirtual-request-list (&optional server)
- (nnheader-report 'nnvirtual "LIST is not implemented."))
-
-(deffoo nnvirtual-request-newgroups (date &optional server)
- (nnheader-report 'nnvirtual "NEWGROUPS is not supported."))
-
-(deffoo nnvirtual-request-list-newsgroups (&optional server)
- (nnheader-report 'nnvirtual "LIST NEWSGROUPS is not implemented."))
-
-(deffoo nnvirtual-request-update-info (group info &optional server)
- (when (nnvirtual-possibly-change-server server)
- (let ((map nnvirtual-mapping)
- (marks (mapcar (lambda (m) (list (cdr m))) gnus-article-mark-lists))
- reads mr m op)
- ;; Go through the mapping.
- (while map
- (unless (nth 3 (setq m (pop map)))
- ;; Read article.
- (push (car m) reads))
- ;; Copy marks.
- (when (setq mr (nth 4 m))
- (while mr
- (setcdr (setq op (assq (pop mr) marks)) (cons (car m) (cdr op))))))
- ;; Compress the marks and the reads.
- (setq mr marks)
- (while mr
- (setcdr (car mr) (gnus-compress-sequence (sort (cdr (pop mr)) '<))))
- (setcar (cddr info) (gnus-compress-sequence (nreverse reads)))
- ;; Remove empty marks lists.
- (while (and marks (not (cdar marks)))
- (setq marks (cdr marks)))
- (setq mr marks)
- (while (cdr mr)
- (if (cdadr mr)
- (setq mr (cdr mr))
- (setcdr mr (cddr mr))))
-
- ;; Enter these new marks into the info of the group.
- (if (nthcdr 3 info)
- (setcar (nthcdr 3 info) marks)
- ;; Add the marks lists to the end of the info.
- (when marks
- (setcdr (nthcdr 2 info) (list marks))))
- t)))
-
-(deffoo nnvirtual-catchup-group (group &optional server all)
- (nnvirtual-possibly-change-server server)
- (let ((gnus-group-marked (copy-sequence nnvirtual-component-groups))
- (gnus-expert-user t))
- ;; Make sure all groups are activated.
- (mapcar
- (lambda (g)
- (when (not (numberp (car (gnus-gethash g gnus-newsrc-hashtb))))
- (gnus-activate-group g)))
- nnvirtual-component-groups)
- (save-excursion
- (set-buffer gnus-group-buffer)
- (gnus-group-catchup-current nil all))))
-
-(deffoo nnvirtual-find-group-art (group article)
- "Return the real group and article for virtual GROUP and ARTICLE."
- (let ((mart (assq article nnvirtual-mapping)))
- (when mart
- (cons (cadr mart) (caddr mart)))))
-
-
-;;; Internal functions.
-
-(defun nnvirtual-convert-headers ()
- "Convert HEAD headers into NOV headers."
- (save-excursion
- (set-buffer nntp-server-buffer)
- (let* ((dependencies (make-vector 100 0))
- (headers (gnus-get-newsgroup-headers dependencies))
- header)
- (erase-buffer)
- (while (setq header (pop headers))
- (nnheader-insert-nov header)))))
-
-(defun nnvirtual-possibly-change-server (server)
- (or (not server)
- (nnoo-current-server-p 'nnvirtual server)
- (nnvirtual-open-server server)))
-
-(defun nnvirtual-update-marked ()
- "Copy marks from the virtual group to the component groups."
- (let ((mark-lists gnus-article-mark-lists)
- (marks (gnus-info-marks (gnus-get-info (nnvirtual-current-group))))
- type list mart cgroups)
- (while (setq type (cdr (pop mark-lists)))
- (setq list (gnus-uncompress-range (cdr (assq type marks))))
- (setq cgroups
- (mapcar (lambda (g) (list g)) nnvirtual-component-groups))
- (while list
- (nconc (assoc (cadr (setq mart (assq (pop list) nnvirtual-mapping)))
- cgroups)
- (list (caddr mart))))
- (while cgroups
- (gnus-add-marked-articles
- (caar cgroups) type (cdar cgroups) nil t)
- (gnus-group-update-group (car (pop cgroups)) t)))))
-
-(defun nnvirtual-update-reads ()
- "Copy (un)reads from the current group to the component groups."
- (let ((groups (mapcar (lambda (g) (list g)) nnvirtual-component-groups))
- (articles (gnus-list-of-unread-articles
- (nnvirtual-current-group)))
- m)
- (while articles
- (setq m (assq (pop articles) nnvirtual-mapping))
- (nconc (assoc (nth 1 m) groups) (list (nth 2 m))))
- (while groups
- (gnus-update-read-articles (caar groups) (cdr (pop groups))))))
-
-(defun nnvirtual-current-group ()
- "Return the prefixed name of the current nnvirtual group."
- (concat "nnvirtual:" nnvirtual-current-group))
-
-(defsubst nnvirtual-marks (article marks)
- "Return a list of mark types for ARTICLE."
- (let (out)
- (while marks
- (when (memq article (cdar marks))
- (push (caar marks) out))
- (setq marks (cdr marks)))
- out))
-
-(defun nnvirtual-create-mapping ()
- "Create an article mapping for the current group."
- (let* ((div nil)
- m marks list article unreads marks active
- (map (sort
- (apply
- 'nconc
- (mapcar
- (lambda (g)
- (when (and (setq active (gnus-activate-group g))
- (> (cdr active) (car active)))
- (setq unreads (gnus-list-of-unread-articles g)
- marks (gnus-uncompress-marks
- (gnus-info-marks (gnus-get-info g))))
- (when gnus-use-cache
- (push (cons 'cache (gnus-cache-articles-in-group g))
- marks))
- (setq div (/ (float (car active))
- (if (zerop (cdr active))
- 1 (cdr active))))
- (mapcar (lambda (n)
- (list (* div (- n (car active)))
- g n (and (memq n unreads) t)
- (inline (nnvirtual-marks n marks))))
- (gnus-uncompress-range active))))
- nnvirtual-component-groups))
- (lambda (m1 m2)
- (< (car m1) (car m2)))))
- (i 0))
- (setq nnvirtual-mapping map)
- ;; Set the virtual article numbers.
- (while (setq m (pop map))
- (setcar m (setq article (incf i))))))
-
-(provide 'nnvirtual)
-
-;;; nnvirtual.el ends here
diff --git a/lisp/novice.el b/lisp/novice.el
deleted file mode 100644
index 424ef693fd1..00000000000
--- a/lisp/novice.el
+++ /dev/null
@@ -1,145 +0,0 @@
-;;; novice.el --- handling of disabled commands ("novice mode") for Emacs.
-
-;; Copyright (C) 1985, 1986, 1987, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: internal, help
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This mode provides a hook which is, by default, attached to various
-;; putatively dangerous commands in a (probably futile) attempt to
-;; prevent lusers from shooting themselves in the feet.
-
-;;; Code:
-
-;; This function is called (by autoloading)
-;; to handle any disabled command.
-;; The command is found in this-command
-;; and the keys are returned by (this-command-keys).
-
-;;;###autoload
-(defvar disabled-command-hook 'disabled-command-hook
- "Function to call to handle disabled commands.
-If nil, the feature is disabled, i.e., all commands work normally.")
-
-;;;###autoload
-(defun disabled-command-hook (&rest ignore)
- (let (char)
- (save-window-excursion
- (with-output-to-temp-buffer "*Help*"
- (let ((keys (this-command-keys)))
- (if (or (eq (aref keys 0)
- (if (stringp keys)
- (aref "\M-x" 0)
- ?\M-x))
- (and (>= (length keys) 2)
- (eq (aref keys 0) meta-prefix-char)
- (eq (aref keys 1) ?x)))
- (princ "You have invoked the disabled command ")
- (princ "You have typed ")
- (princ (key-description keys))
- (princ ", invoking disabled command ")))
- (princ this-command)
- (princ ":\n")
- ;; Print any special message saying why the command is disabled.
- (if (stringp (get this-command 'disabled))
- (princ (get this-command 'disabled)))
- ;; Keep only the first paragraph of the documentation.
- (save-excursion
- (set-buffer "*Help*")
- (goto-char (point-max))
- (save-excursion
- (princ (or (condition-case ()
- (documentation this-command)
- (error nil))
- "<< not documented >>")))
- (if (search-forward "\n\n" nil t)
- (delete-region (1- (point)) (point-max))
- (goto-char (point-max))))
- (princ "\n\n")
- (princ "You can now type
-Space to try the command just this once, but leave it disabled,
-Y to try it and enable it (no questions if you use it again),
-! to try it and enable all commands in this session, or
-N to do nothing (command remains disabled).")
- (save-excursion
- (set-buffer standard-output)
- (help-mode)))
- (message "Type y, n, ! or Space: ")
- (let ((cursor-in-echo-area t))
- (while (not (memq (setq char (downcase (read-char)))
- '(?! ? ?y ?n)))
- (ding)
- (message "Please type y, n, ! or Space: "))))
- (if (= char ?!)
- (setq disabled-command-hook nil))
- (if (= char ?y)
- (if (and user-init-file
- (not (string= "" user-init-file))
- (y-or-n-p "Enable command for future editing sessions also? "))
- (enable-command this-command)
- (put this-command 'disabled nil)))
- (if (/= char ?n)
- (call-interactively this-command))))
-
-;;;###autoload
-(defun enable-command (command)
- "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."
- (interactive "CEnable command: ")
- (put command 'disabled nil)
- (save-excursion
- (set-buffer (find-file-noselect
- (substitute-in-file-name user-init-file)))
- (goto-char (point-min))
- (if (search-forward (concat "(put '" (symbol-name command) " ") nil t)
- (delete-region
- (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point))))
- ;; Explicitly enable, in case this command is disabled by default
- ;; or in case the code we deleted was actually a comment.
- (goto-char (point-max))
- (insert "\n(put '" (symbol-name command) " 'disabled nil)\n")
- (save-buffer)))
-
-;;;###autoload
-(defun disable-command (command)
- "Require special confirmation to execute COMMAND from now on.
-The user's .emacs file is altered so that this will apply
-to future sessions."
- (interactive "CDisable command: ")
- (if (not (commandp command))
- (error "Invalid command name `%s'" command))
- (put command 'disabled t)
- (save-excursion
- (set-buffer (find-file-noselect
- (substitute-in-file-name user-init-file)))
- (goto-char (point-min))
- (if (search-forward (concat "(put '" (symbol-name command) " ") nil t)
- (delete-region
- (progn (beginning-of-line) (point))
- (progn (forward-line 1) (point))))
- (goto-char (point-max))
- (insert "\n(put '" (symbol-name command) " 'disabled t)\n")
- (save-buffer)))
-
-;;; novice.el ends here
diff --git a/lisp/options.el b/lisp/options.el
deleted file mode 100644
index 614292ce6e0..00000000000
--- a/lisp/options.el
+++ /dev/null
@@ -1,142 +0,0 @@
-;;; options.el --- edit Options command for Emacs.
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This code provides functions to list and edit the values of all global
-;; option variables known to loaded Emacs Lisp code. There are two entry
-;; points, `list-options' and `edit' options'. The latter enters a major
-;; mode specifically for editing option values. Do `M-x describe-mode' in
-;; that context for more details.
-
-;;; Code:
-
-;;;###autoload
-(defun list-options ()
- "Display a list of Emacs user options, with values and documentation."
- (interactive)
- (save-excursion
- (set-buffer (get-buffer-create "*List Options*"))
- (Edit-options-mode))
- (with-output-to-temp-buffer "*List Options*"
- (let (vars)
- (mapatoms (function (lambda (sym)
- (if (user-variable-p sym)
- (setq vars (cons sym vars))))))
- (setq vars (sort vars 'string-lessp))
- (while vars
- (let ((sym (car vars)))
- (princ ";; ")
- (prin1 sym)
- (princ ":\n\t")
- (prin1 (symbol-value sym))
- (terpri)
- (princ (substitute-command-keys
- (documentation-property sym 'variable-documentation)))
- (princ "\n;;\n"))
- (setq vars (cdr vars)))))
- (save-excursion
- (set-buffer "*List Options*")
- (setq buffer-read-only t)))
-
-;;;###autoload
-(defun edit-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."
- (interactive)
- (list-options)
- (pop-to-buffer "*List Options*"))
-
-(defvar Edit-options-mode-map
- (let ((map (make-keymap)))
- (define-key map "s" 'Edit-options-set)
- (define-key map "x" 'Edit-options-toggle)
- (define-key map "1" 'Edit-options-t)
- (define-key map "0" 'Edit-options-nil)
- (define-key map "p" 'backward-paragraph)
- (define-key map " " 'forward-paragraph)
- (define-key map "n" 'forward-paragraph)
- map)
- "")
-
-;; Edit Options mode is suitable only for specially formatted data.
-(put 'Edit-options-mode 'mode-class 'special)
-
-(defun Edit-options-mode ()
- "\\<Edit-options-mode-map>\
-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.
-
-Each variable description is a paragraph.
-For convenience, the characters \\[backward-paragraph] and \\[forward-paragraph] 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)
- (make-local-variable 'paragraph-separate)
- (setq paragraph-separate "[^\^@-\^?]")
- (make-local-variable 'paragraph-start)
- (setq paragraph-start "\t")
- (setq truncate-lines t)
- (setq major-mode 'Edit-options-mode)
- (setq mode-name "Options")
- (run-hooks 'Edit-options-mode-hook))
-
-(defun Edit-options-set () (interactive)
- (Edit-options-modify
- '(lambda (var) (eval-minibuffer (concat "New " (symbol-name var) ": ")))))
-
-(defun Edit-options-toggle () (interactive)
- (Edit-options-modify '(lambda (var) (not (symbol-value var)))))
-
-(defun Edit-options-t () (interactive)
- (Edit-options-modify '(lambda (var) t)))
-
-(defun Edit-options-nil () (interactive)
- (Edit-options-modify '(lambda (var) nil)))
-
-(defun Edit-options-modify (modfun)
- (save-excursion
- (let ((buffer-read-only nil) var pos)
- (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))))
- (goto-char pos)
- (forward-line 1)
- (forward-char 1)
- (save-excursion
- (set var (funcall modfun var)))
- (kill-sexp 1)
- (prin1 (symbol-value var) (current-buffer)))))
-
-;;; options.el ends here
diff --git a/lisp/paren.el b/lisp/paren.el
deleted file mode 100644
index 66d27fbb6af..00000000000
--- a/lisp/paren.el
+++ /dev/null
@@ -1,181 +0,0 @@
-;;; paren.el --- highlight matching paren.
-
-;; Copyright (C) 1993, 1996 Free Software Foundation, Inc.
-
-;; Author: rms@gnu.ai.mit.edu
-;; Maintainer: FSF
-;; Keywords: languages, faces
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Load this and it will display highlighting on whatever
-;; paren matches the one before or after point.
-
-;;; Code:
-
-;; This is the overlay used to highlight the matching paren.
-(defvar show-paren-overlay nil)
-;; This is the overlay used to highlight the closeparen right before point.
-(defvar show-paren-overlay-1 nil)
-
-(defvar show-paren-mode nil)
-(defvar show-paren-idle-timer nil)
-
-(defvar show-paren-mismatch-face nil)
-
-(defvar show-paren-delay (if (featurep 'lisp-float-type) 0.125 1)
- "*Time in seconds to delay before showing the matching paren.")
-
-(defvar show-paren-face 'region
- "*Name of the face to use for showing the matching paren.")
-
-;;;###autoload
-(defun show-paren-mode (&optional arg)
- "Toggle Show Paren mode.
-With prefix ARG, turn Show Paren mode on if and only if ARG is positive.
-Returns the new status of Show Paren mode (non-nil means on).
-
-When Show Paren mode is enabled, any matching parenthesis is highlighted
-after `show-paren-delay' seconds of Emacs idle time."
- (interactive "P")
- (if window-system
- (let ((on-p (if arg
- (> (prefix-numeric-value arg) 0)
- (not show-paren-mode))))
- (setq blink-matching-paren-on-screen (not on-p))
- (and show-paren-idle-timer (cancel-timer show-paren-idle-timer))
- (if on-p
- (setq show-paren-idle-timer (run-with-idle-timer show-paren-delay t
- 'show-paren-function))
- (and show-paren-overlay (overlay-buffer show-paren-overlay)
- (delete-overlay show-paren-overlay))
- (and show-paren-overlay-1 (overlay-buffer show-paren-overlay-1)
- (delete-overlay show-paren-overlay-1)))
- (setq show-paren-mode on-p))))
-
-;; Find the place to show, if there is one,
-;; and show it until input arrives.
-(defun show-paren-function ()
- ;; Do nothing if no window system to display results with.
- ;; Do nothing if executing keyboard macro.
- ;; Do nothing if input is pending.
- (if window-system
- (let (pos dir mismatch (oldpos (point))
- (face show-paren-face))
- (cond ((eq (char-syntax (preceding-char)) ?\))
- (setq dir -1))
- ((eq (char-syntax (following-char)) ?\()
- (setq dir 1)))
- (if dir
- (save-excursion
- (save-restriction
- ;; Determine the range within which to look for a match.
- (if blink-matching-paren-distance
- (narrow-to-region (max (point-min)
- (- (point) blink-matching-paren-distance))
- (min (point-max)
- (+ (point) blink-matching-paren-distance))))
- ;; Scan across one sexp within that range.
- ;; Errors or nil mean there is a mismatch.
- (condition-case ()
- (setq pos (scan-sexps (point) dir))
- (error (setq pos t
- mismatch t)))
- ;; If found a "matching" paren, see if it is the right
- ;; kind of paren to match the one we started at.
- (if (integerp pos)
- (let ((beg (min pos oldpos)) (end (max pos oldpos)))
- (and (/= (char-syntax (char-after beg)) ?\$)
- (setq mismatch
- (not (eq (char-after (1- end))
- ;; This can give nil.
- (matching-paren (char-after beg))))))))
- ;; If they don't properly match, use a different face,
- ;; or print a message.
- (if mismatch
- (progn
- (and (null show-paren-mismatch-face)
- (x-display-color-p)
- (progn
- (add-to-list 'facemenu-unlisted-faces
- 'paren-mismatch)
- (make-face 'paren-mismatch)
- (or (face-nontrivial-p 'paren-mismatch t)
- (progn
- (set-face-background 'paren-mismatch
- "purple")
- (set-face-foreground 'paren-mismatch
- "white")))
- (setq show-paren-mismatch-face 'paren-mismatch)))
- (if show-paren-mismatch-face
- (setq face show-paren-mismatch-face)
- (message "Paren mismatch"))))
- )))
- (cond (pos
- (if (or (= dir -1)
- (not (integerp pos)))
- ;; If matching backwards, highlight the closeparen
- ;; before point as well as its matching open.
- ;; If matching forward, and the openparen is unbalanced,
- ;; highlight the paren at point to indicate misbalance.
- (let ((from (if (= dir 1)
- (point)
- (1- (point))))
- (to (if (= dir 1)
- (1+ (point))
- (point))))
- (if show-paren-overlay-1
- (move-overlay show-paren-overlay-1
- from to
- (current-buffer))
- (setq show-paren-overlay-1
- (make-overlay from to)))
- ;; Always set the overlay face, since it varies.
- (overlay-put show-paren-overlay-1 'face face))
- ;; Otherwise, turn off any such highlighting.
- (and show-paren-overlay-1
- (overlay-buffer show-paren-overlay-1)
- (delete-overlay show-paren-overlay-1)))
- ;; Turn on highlighting for the matching paren, if found.
- ;; If it's an unmatched paren, turn off any such highlighting.
- (or (and (not (integerp pos))
- (delete-overlay show-paren-overlay))
- (if show-paren-overlay
- (move-overlay show-paren-overlay (- pos dir) pos
- (current-buffer))
- (setq show-paren-overlay
- (make-overlay (- pos dir) pos))))
- ;; Always set the overlay face, since it varies.
- (overlay-put show-paren-overlay 'face face))
- (t
- ;; If not at a paren that has a match,
- ;; turn off any previous paren highlighting.
- (and show-paren-overlay (overlay-buffer show-paren-overlay)
- (delete-overlay show-paren-overlay))
- (and show-paren-overlay-1 (overlay-buffer show-paren-overlay-1)
- (delete-overlay show-paren-overlay-1)))))))
-
-;;; For back compatibility we turn ourselves on if we're dumped or loaded.
-(add-hook 'window-setup-hook '(lambda () (show-paren-mode t)))
-(show-paren-mode t)
-
-(provide 'paren)
-
-;;; paren.el ends here
diff --git a/lisp/patcomp.el b/lisp/patcomp.el
deleted file mode 100644
index 201c23c911e..00000000000
--- a/lisp/patcomp.el
+++ /dev/null
@@ -1,15 +0,0 @@
-
-;;; This function is used by the patch files to update Emacs releases.
-
-(defun batch-byte-recompile-emacs ()
- "Recompile the Emacs `lisp' directory.
-This is used after installing the patches for a new version."
- (let ((load-path (list (expand-file-name "lisp"))))
- (byte-recompile-directory "lisp")))
-
-(defun batch-byte-compile-emacs ()
- "Compile new files installed in the Emacs `lisp' directory.
-This is used after installing the patches for a new version.
-It uses the command line arguments to specify the files to compile."
- (let ((load-path (list (expand-file-name "lisp"))))
- (batch-byte-compile)))
diff --git a/lisp/paths.el b/lisp/paths.el
deleted file mode 100644
index 96536a1b4a1..00000000000
--- a/lisp/paths.el
+++ /dev/null
@@ -1,155 +0,0 @@
-;;; paths.el --- define pathnames for use by various Emacs commands.
-
-;; Copyright (C) 1986, 1988, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; These are default settings for names of certain files and directories
-;; that Emacs needs to refer to from time to time.
-
-;; If these settings are not right, override them with `setq'
-;; in site-init.el. Do not change this file.
-
-;;; Code:
-
-(defvar Info-default-directory-list
- (let ((start (list "/usr/local/lib/info/"
- ;; This comes second so that, if it is the same
- ;; as configure-info-directory (which is usually true)
- ;; and Emacs has been installed (also usually true)
- ;; then the list will end with two copies of this;
- ;; which means that the last dir file Info-insert-dir
- ;; finds will be the one in this directory.
- "/usr/local/info/"))
- (configdir (file-name-as-directory configure-info-directory)))
- (setq start (nconc start (list configdir)))
- start)
- "Default list of directories to search for Info documentation files.
-They are searched in the order they are given in the list.
-Therefore, the directory of Info files that come with Emacs
-normally should come last (so that local files override standard ones).
-
-Once Info is started, the list of directories to search
-comes from the variable `Info-directory-list'.
-This variable `Info-default-directory-list' is used as the default
-for initializing `Info-directory-list' when Info is started.")
-
-(defvar news-path
- (if (file-exists-p "/usr/spool/news/")
- "/usr/spool/news/"
- "/var/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")
- ((file-exists-p "/usr/local/bin/inews") "/usr/local/bin/inews")
- ((file-exists-p "/usr/contrib/lib/news/inews") "/usr/contrib/lib/news/inews")
- ((file-exists-p "/usr/lib/news/inews") "/usr/lib/news/inews")
- (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.
-The null string means use the local host as the server site.")
-
-(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-local-organization nil
- "*The name of your organization, as a string.
-The `ORGANIZATION' environment variable is used instead if defined.")
-
-(defvar gnus-startup-file "~/.newsrc"
- "The file listing groups to which user is subscribed.
-Will use `gnus-startup-file'-SERVER instead if exists.")
-
-(defvar rmail-file-name "~/RMAIL"
- "Name of user's primary mail file.")
-
-(defconst rmail-spool-directory
- (cond ((string-match "^[^-]+-[^-]+-sco3.2v4" system-configuration)
- "/usr/spool/mail/")
- ;; On The Bull DPX/2 /usr/spool/mail is used although
- ;; it is usg-unix-v.
- ((string-match "^m68k-bull-sysv3" system-configuration)
- "/usr/spool/mail/")
- ;; SVR4 and recent BSD are said to use this.
- ;; Rather than trying to know precisely which systems use it,
- ;; let's assume this dir is never used for anything else.
- ((file-exists-p "/var/mail")
- "/var/mail/")
- ;; Many GNU/Linux systems use this name.
- ((file-exists-p "/var/spool/mail")
- "/var/spool/mail/")
- ((memq system-type '(dgux hpux usg-unix-v unisoft-unix rtu irix))
- "/usr/mail/")
- (t "/usr/spool/mail/"))
- "Name of directory used by system mailer for delivering new mail.
-Its name should end with a slash.")
-
-(defconst sendmail-program
- (cond
- ((file-exists-p "/usr/lib/sendmail") "/usr/lib/sendmail")
- ((file-exists-p "/usr/sbin/sendmail") "/usr/sbin/sendmail")
- ((file-exists-p "/usr/ucblib/sendmail") "/usr/ucblib/sendmail")
- (t "fakemail")) ;In ../etc, to interface to /bin/mail.
- "Program used to send messages.")
-
-(defconst remote-shell-program
- (cond
- ;; Some systems use rsh for the remote shell; others use that name for the
- ;; restricted shell and use remsh for the remote shell. Let's try to guess
- ;; based on what we actually find out there. The restricted shell is
- ;; almost certainly in /bin or /usr/bin, so it's probably safe to assume
- ;; that an rsh found elsewhere is the remote shell program. The converse
- ;; is not true: /usr/bin/rsh could be either one, so check that last.
- ((file-exists-p "/usr/ucb/remsh") "/usr/ucb/remsh")
- ((file-exists-p "/usr/bsd/remsh") "/usr/bsd/remsh")
- ((file-exists-p "/bin/remsh") "/bin/remsh")
- ((file-exists-p "/usr/bin/remsh") "/usr/bin/remsh")
- ((file-exists-p "/usr/local/bin/remsh") "/usr/local/bin/remsh")
- ((file-exists-p "/usr/ucb/rsh") "/usr/ucb/rsh")
- ((file-exists-p "/usr/bsd/rsh") "/usr/bsd/rsh")
- ((file-exists-p "/usr/local/bin/rsh") "/usr/local/bin/rsh")
- ((file-exists-p "/usr/bin/rcmd") "/usr/bin/rcmd")
- ((file-exists-p "/bin/rcmd") "/bin/rcmd")
- ((file-exists-p "/bin/rsh") "/bin/rsh")
- ((file-exists-p "/usr/bin/rsh") "/usr/bin/rsh")
- (t "rsh")))
-
-(defconst term-file-prefix (if (eq system-type 'vax-vms) "[.term]" "term/")
- "If non-nil, Emacs startup does (load (concat term-file-prefix (getenv \"TERM\")))
-You may set this variable to nil in your `.emacs' file if you do not wish
-the terminal-initialization file to be loaded.")
-
-(defconst abbrev-file-name
- (if (eq system-type 'vax-vms)
- "~/abbrev.def"
- (convert-standard-filename "~/.abbrev_defs"))
- "*Default name of file to read abbrevs from.")
-
-;;; paths.el ends here
diff --git a/lisp/play/blackbox.el b/lisp/play/blackbox.el
deleted file mode 100644
index 8de46c2f025..00000000000
--- a/lisp/play/blackbox.el
+++ /dev/null
@@ -1,421 +0,0 @@
-;;; blackbox.el --- blackbox game in Emacs Lisp
-
-;; Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
-
-;; Author: F. Thomas May <uw-nsr!uw-warp!tom@beaver.cs.washington.edu>
-;; Adapted-By: ESR
-;; Keywords: games
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; by F. Thomas May <uw-nsr!uw-warp!tom@beaver.cs.washington.edu>
-;; doc comment by Root Boy Jim <rbj@dsys.icst.nbs.gov>, 27 Apr 89
-;; interface improvements by ESR, Dec 5 1991.
-
-;; The object of the game is to find four hidden balls by shooting rays
-;; into the black box. There are four possibilities: 1) the ray will
-;; pass thru the box undisturbed, 2) it will hit a ball and be absorbed,
-;; 3) it will be deflected and exit the box, or 4) be deflected immediately,
-;; not even being allowed entry into the box.
-;;
-;; The strange part is the method of deflection. It seems that rays will
-;; not pass next to a ball, and change direction at right angles to avoid it.
-;;
-;; R 3
-;; 1 - - - - - - - - 1
-;; - - - - - - - -
-;; - O - - - - - - 3
-;; 2 - - - - O - O -
-;; 4 - - - - - - - -
-;; 5 - - - - - - - - 5
-;; - - - - - - - - R
-;; H - - - - - - - O
-;; 2 H 4 H
-;;
-;; Rays which enter and exit are numbered. You can see that rays 1 & 5 pass
-;; thru the box undisturbed. Ray 2 is deflected by the northwesternmost
-;; ball. Likewise rays 3 and 4. Rays which hit balls and are absorbed are
-;; marked with H. The bottom of the left and the right of the bottom hit
-;; the southeastern ball directly. Rays may also hit balls after being
-;; reflected. Consider the H on the bottom next to the 4. It bounces off
-;; the NW-ern most ball and hits the central ball. A ray shot from above
-;; the right side 5 would hit the SE-ern most ball. The R beneath the 5
-;; is because the ball is returned instantly. It is not allowed into
-;; the box if it would reflect immediately. The R on the top is a more
-;; leisurely return. Both central balls would tend to deflect it east
-;; or west, but it cannot go either way, so it just retreats.
-;;
-;; At the end of the game, if you've placed guesses for as many balls as
-;; there are in the box, the true board position will be revealed. Each
-;; `x' is an incorrect guess of yours; `o' is the true location of a ball.
-
-;;; Code:
-
-(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 [right] 'bb-right)
- (define-key blackbox-mode-map "\C-b" 'bb-left)
- (define-key blackbox-mode-map [left] 'bb-left)
- (define-key blackbox-mode-map "\C-p" 'bb-up)
- (define-key blackbox-mode-map [up] 'bb-up)
- (define-key blackbox-mode-map "\C-n" 'bb-down)
- (define-key blackbox-mode-map [down] '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 [insert] 'bb-romp)
- (define-key blackbox-mode-map "\C-m" 'bb-done)
- (define-key blackbox-mode-map [kp-enter] '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. To learn how to play blackbox,
-see the documentation for function `blackbox'.
-
-The usual mnemonic keys move the cursor around the box.
-\\<blackbox-mode-map>\\[bb-bol] and \\[bb-eol] move to the beginning and end of line, respectively.
-
-\\[bb-romp] -- send in a ray from point, or toggle a ball at point
-\\[bb-done] -- end game and get score
-"
- (interactive)
- (kill-all-local-variables)
- (use-local-map blackbox-mode-map)
- (setq truncate-lines t)
- (setq major-mode 'blackbox-mode)
- (setq mode-name "Blackbox"))
-
-;;;###autoload
-(defun blackbox (num)
- "Play blackbox. Optional prefix argument is the number of balls;
-the default is 4.
-
-What is blackbox?
-
-Blackbox is a game of hide and seek played on an 8 by 8 grid (the
-Blackbox). Your opponent (Emacs, in this case) has hidden several
-balls (usually 4) within this box. By shooting rays into the box and
-observing where they emerge it is possible to deduce the positions of
-the hidden balls. The fewer rays you use to find the balls, the lower
-your score.
-
-Overview of play:
-
-\\<blackbox-mode-map>\
-To play blackbox, type \\[blackbox]. An optional prefix argument
-specifies the number of balls to be hidden in the box; the default is
-four.
-
-The cursor can be moved around the box with the standard cursor
-movement keys.
-
-To shoot a ray, move the cursor to the edge of the box and press SPC.
-The result will be determined and the playfield updated.
-
-You may place or remove balls in the box by moving the cursor into the
-box and pressing \\[bb-romp].
-
-When you think the configuration of balls you have placed is correct,
-press \\[bb-done]. You will be informed whether you are correct or
-not, and be given your score. Your score is the number of letters and
-numbers around the outside of the box plus five for each incorrectly
-placed ball. If you placed any balls incorrectly, they will be
-indicated with `x', and their actual positions indicated with `o'.
-
-Details:
-
-There are three possible outcomes for each ray you send into the box:
-
- Detour: the ray is deflected and emerges somewhere other than
- where you sent it in. On the playfield, detours are
- denoted by matching pairs of numbers -- one where the
- ray went in, and the other where it came out.
-
- Reflection: the ray is reflected and emerges in the same place
- it was sent in. On the playfield, reflections are
- denoted by the letter `R'.
-
- Hit: the ray strikes a ball directly and is absorbed. It does
- not emerge from the box. On the playfield, hits are
- denoted by the letter `H'.
-
-The rules for how balls deflect rays are simple and are best shown by
-example.
-
-As a ray approaches a ball it is deflected ninety degrees. Rays can
-be deflected multiple times. In the diagrams below, the dashes
-represent empty box locations and the letter `O' represents a ball.
-The entrance and exit points of each ray are marked with numbers as
-described under \"Detour\" above. Note that the entrance and exit
-points are always interchangeable. `*' denotes the path taken by the
-ray.
-
-Note carefully the relative positions of the ball and the ninety
-degree deflection it causes.
-
- 1
- - * - - - - - - - - - - - - - - - - - - - - - -
- - * - - - - - - - - - - - - - - - - - - - - - -
-1 * * - - - - - - - - - - - - - - - O - - - - O -
- - - O - - - - - - - O - - - - - - - * * * * - -
- - - - - - - - - - - - * * * * * 2 3 * * * - - * - -
- - - - - - - - - - - - * - - - - - - - O - * - -
- - - - - - - - - - - - * - - - - - - - - * * - -
- - - - - - - - - - - - * - - - - - - - - * - O -
- 2 3
-
-As mentioned above, a reflection occurs when a ray emerges from the same point
-it was sent in. This can happen in several ways:
-
-
- - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - O - - - - - O - O - - - - - - - - - - -
-R * * * * - - - - - - - * - - - - O - - - - - - -
- - - - - O - - - - - - * - - - - R - - - - - - - -
- - - - - - - - - - - - * - - - - - - - - - - - -
- - - - - - - - - - - - * - - - - - - - - - - - -
- - - - - - - - - R * * * * - - - - - - - - - - - -
- - - - - - - - - - - - - O - - - - - - - - - - -
-
-In the first example, the ray is deflected downwards by the upper
-ball, then left by the lower ball, and finally retraces its path to
-its point of origin. The second example is similar. The third
-example is a bit anomalous but can be rationalized by realizing the
-ray never gets a chance to get into the box. Alternatively, the ray
-can be thought of as being deflected downwards and immediately
-emerging from the box.
-
-A hit occurs when a ray runs straight into a ball:
-
- - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - O - - -
- - - - - - - - - - - - - O - - - H * * * * - - - -
- - - - - - - - - H * * * * O - - - - - - * - - - -
- - - - - - - - - - - - - O - - - - - - O - - - -
-H * * * O - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
-
-Be sure to compare the second example of a hit with the first example of
-a reflection."
- (interactive "P")
- (switch-to-buffer "*Blackbox*")
- (blackbox-mode)
- (setq buffer-read-only t)
- (buffer-disable-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 (random 8) (random 8)))
- (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")
- (insert (format "\nThere are %d balls in the box" (length bb-board)))
- ))
-
-(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 ()
- "Finish the game and report score."
- (interactive)
- (let (bogus-balls)
- (cond
- ((not (= (length bb-balls-placed) (length bb-board)))
- (message "There %s %d hidden ball%s; you have placed %d."
- (if (= (length bb-board) 1) "is" "are")
- (length bb-board)
- (if (= (length bb-board) 1) "" "s")
- (length bb-balls-placed)))
- (t
- (setq bogus-balls (bb-show-bogus-balls bb-balls-placed bb-board))
- (if (= bogus-balls 0)
- (message "Right! Your score is %d." bb-score)
- (message "Oops! You missed %d ball%s. Your score is %d."
- bogus-balls
- (if (= bogus-balls 1) "" "s")
- (+ bb-score (* 5 bogus-balls))))
- (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."
- (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))))))
-
-;;; blackbox.el ends here
diff --git a/lisp/play/cookie1.el b/lisp/play/cookie1.el
deleted file mode 100644
index 3f8087fa2fa..00000000000
--- a/lisp/play/cookie1.el
+++ /dev/null
@@ -1,165 +0,0 @@
-;;; cookie1.el --- retrieve random phrases from fortune cookie files
-
-;; Copyright (C) 1993 Free Software Foundation, Inc.
-
-;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
-;; Maintainer: FSF
-;; Keywords: games
-;; Created: Mon Mar 22 17:06:26 1993
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Support for random cookie fetches from phrase files, used for such
-;; critical applications as emulating Zippy the Pinhead and confounding
-;; the NSA Trunk Trawler.
-;;
-;; The two entry points are `cookie' and `cookie-insert'. The helper
-;; function `shuffle-vector' may be of interest to programmers.
-;;
-;; The code expects phrase files to be in one of two formats:
-;;
-;; * ITS-style LINS format (strings terminated by ASCII 0 characters,
-;; leading whitespace ignored).
-;;
-;; * UNIX fortune file format (quotes terminated by %% on a line by itself).
-;;
-;; Everything up to the first delimiter is treated as a comment. Other
-;; formats could be supported by adding alternates to the regexp
-;; `cookie-delimiter'.
-;;
-;; This code derives from Steve Strassman's 1987 spook.el package, but
-;; has been generalized so that it supports multiple simultaneous
-;; cookie databases and fortune files. It is intended to be called
-;; from other packages such as yow.el and spook.el.
-;;
-;; TO DO: teach cookie-snarf to auto-detect ITS PINS or UNIX fortune(6)
-;; format and do the right thing.
-
-;;; Code:
-
-; Randomize the seed in the random number generator.
-(random t)
-
-(defconst cookie-delimiter "\n%%\n\\|\0"
- "Delimiter used to separate cookie file entries.")
-
-(defvar cookie-cache (make-vector 511 0)
- "Cache of cookie files that have already been snarfed.")
-
-;;;###autoload
-(defun cookie (phrase-file startmsg endmsg)
- "Return a random phrase from PHRASE-FILE. When the phrase file
-is read in, display STARTMSG at beginning of load, ENDMSG at end."
- (let ((cookie-vector (cookie-snarf phrase-file startmsg endmsg)))
- (shuffle-vector cookie-vector)
- (aref cookie-vector 1)))
-
-;;;###autoload
-(defun cookie-insert (phrase-file &optional count startmsg endmsg)
- "Insert random phrases from PHRASE-FILE; COUNT of them. When the phrase file
-is read in, display STARTMSG at beginning of load, ENDMSG at end."
- (let ((cookie-vector (cookie-snarf phrase-file startmsg endmsg)))
- (shuffle-vector cookie-vector)
- (let ((start (point)))
- (insert ?\n)
- (cookie1 (min (- (length cookie-vector) 1) (or count 1)) cookie-vector)
- (insert ?\n)
- (fill-region-as-paragraph start (point) nil))))
-
-(defun cookie1 (arg cookie-vec)
- "Inserts a cookie phrase ARG times."
- (cond ((zerop arg) t)
- (t (insert (aref cookie-vec arg))
- (insert " ")
- (cookie1 (1- arg) cookie-vec))))
-
-;;;###autoload
-(defun cookie-snarf (phrase-file startmsg endmsg)
- "Reads in the PHRASE-FILE, returns it as a vector of strings.
-Emit STARTMSG and ENDMSG before and after. Caches the result; second
-and subsequent calls on the same file won't go to disk."
- (let ((sym (intern-soft phrase-file cookie-cache)))
- (and sym (not (equal (symbol-function sym)
- (nth 5 (file-attributes phrase-file))))
- (yes-or-no-p (concat phrase-file
- " has changed. Read new contents? "))
- (setq sym nil))
- (if sym
- (symbol-value sym)
- (setq sym (intern phrase-file cookie-cache))
- (message "%s" startmsg)
- (save-excursion
- (let ((buf (generate-new-buffer "*cookie*"))
- (result nil))
- (set-buffer buf)
- (fset sym (nth 5 (file-attributes phrase-file)))
- (insert-file-contents (expand-file-name phrase-file))
- (re-search-forward cookie-delimiter)
- (while (progn (skip-chars-forward " \t\n\r\f") (not (eobp)))
- (let ((beg (point)))
- (re-search-forward cookie-delimiter)
- (setq result (cons (buffer-substring beg (1- (point)))
- result))))
- (kill-buffer buf)
- (message "%s" endmsg)
- (set sym (apply 'vector result)))))))
-
-(defun read-cookie (prompt phrase-file startmsg endmsg &optional require-match)
- "Prompt with PROMPT and read with completion among cookies in PHRASE-FILE.
-STARTMSG and ENDMSG are passed along to `cookie-snarf'.
-Optional fifth arg REQUIRE-MATCH non-nil forces a matching cookie."
- ;; Make sure the cookies are in the cache.
- (or (intern-soft phrase-file cookie-cache)
- (cookie-snarf phrase-file startmsg endmsg))
- (completing-read prompt
- (let ((sym (intern phrase-file cookie-cache)))
- ;; We cache the alist form of the cookie in a property.
- (or (get sym 'completion-alist)
- (let* ((alist nil)
- (vec (cookie-snarf phrase-file
- startmsg endmsg))
- (i (length vec)))
- (while (> (setq i (1- i)) 0)
- (setq alist (cons (list (aref vec i)) alist)))
- (put sym 'completion-alist alist))))
- nil require-match nil nil))
-
-; Thanks to Ian G Batten <BattenIG@CS.BHAM.AC.UK>
-; [of the University of Birmingham Computer Science Department]
-; for the iterative version of this shuffle.
-;
-;;;###autoload
-(defun shuffle-vector (vector)
- "Randomly permute the elements of VECTOR (all permutations equally likely)"
- (let ((i 0)
- j
- temp
- (len (length vector)))
- (while (< i len)
- (setq j (+ i (random (- len i))))
- (setq temp (aref vector i))
- (aset vector i (aref vector j))
- (aset vector j temp)
- (setq i (1+ i))))
- vector)
-
-(provide 'cookie1)
-
-;;; cookie1.el ends here
diff --git a/lisp/play/decipher.el b/lisp/play/decipher.el
deleted file mode 100644
index 3e487ff3232..00000000000
--- a/lisp/play/decipher.el
+++ /dev/null
@@ -1,1057 +0,0 @@
-;;; decipher.el --- Cryptanalyze monoalphabetic substitution ciphers
-;;
-;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-;;
-;; Author: Christopher J. Madsen <ac608@yfn.ysu.edu>
-;; Keywords: games
-;;
-;; This file is part of GNU Emacs.
-;;
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-;;
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Quick Start:
-;;
-;; To decipher a message, type or load it into a buffer and type
-;; `M-x decipher'. This will format the buffer and place it into
-;; Decipher mode. You can save your work to a file with the normal
-;; Emacs save commands; when you reload the file it will automatically
-;; enter Decipher mode.
-;;
-;; I'm not going to discuss how to go about breaking a cipher; try
-;; your local library for a book on cryptanalysis. One book you might
-;; find is:
-;; Cryptanalysis: A study of ciphers and their solution
-;; Helen Fouche Gaines
-;; ISBN 0-486-20097-3
-
-;;; Commentary:
-;;
-;; This package is designed to help you crack simple substitution
-;; ciphers where one letter stands for another. It works for ciphers
-;; with or without word divisions. (You must set the variable
-;; decipher-ignore-spaces for ciphers without word divisions.)
-;;
-;; First, some quick definitions:
-;; ciphertext The encrypted message (what you start with)
-;; plaintext The decrypted message (what you are trying to get)
-;;
-;; Decipher mode displays ciphertext in uppercase and plaintext in
-;; lowercase. You must enter the plaintext in lowercase; uppercase
-;; letters are interpreted as commands. The ciphertext may be entered
-;; in mixed case; `M-x decipher' will convert it to uppercase.
-;;
-;; Decipher mode depends on special characters in the first column of
-;; each line. The command `M-x decipher' inserts these characters for
-;; you. The characters and their meanings are:
-;; ( The plaintext & ciphertext alphabets on the first line
-;; ) The ciphertext & plaintext alphabets on the second line
-;; : A line of ciphertext (with plaintext below)
-;; > A line of plaintext (with ciphertext above)
-;; % A comment
-;; Each line in the buffer MUST begin with one of these characters (or
-;; be left blank). In addition, comments beginning with `%!' are reserved
-;; for checkpoints; see decipher-make-checkpoint & decipher-restore-checkpoint
-;; for more information.
-;;
-;; While the cipher message may contain digits or punctuation, Decipher
-;; mode will ignore these characters.
-;;
-;; The buffer is made read-only so it can't be modified by normal
-;; Emacs commands.
-;;
-;; Decipher supports Font Lock mode. To use it, you can also add
-;; (add-hook 'decipher-mode-hook 'turn-on-font-lock)
-;; See the variable `decipher-font-lock-keywords' if you want to customize
-;; the faces used. I'd like to thank Simon Marshall for his help in making
-;; Decipher work well with Font Lock.
-
-;;; Things To Do:
-;;
-;; Email me if you have any suggestions or would like to help.
-;; But be aware that I work on Decipher only sporadically.
-;;
-;; 1. The consonant-line shortcut
-;; 2. More functions for analyzing ciphertext
-
-;;;===================================================================
-;;; Variables:
-;;;===================================================================
-
-(eval-when-compile
- (require 'cl))
-
-(defvar decipher-force-uppercase t
- "*Non-nil means to convert ciphertext to uppercase.
-Nil means the case of the ciphertext is preserved.
-This variable must be set before typing `\\[decipher]'.")
-
-(defvar decipher-ignore-spaces nil
- "*Non-nil means to ignore spaces and punctuation when counting digrams.
-You should set this to `nil' if the cipher message is divided into words,
-or `t' if it is not.
-This variable is buffer-local.")
-(make-variable-buffer-local 'decipher-ignore-spaces)
-
-(defvar decipher-undo-limit 5000
- "The maximum number of entries in the undo list.
-When the undo list exceeds this number, 100 entries are deleted from
-the tail of the list.")
-
-;; End of user modifiable variables
-;;--------------------------------------------------------------------
-
-(defvar decipher-font-lock-keywords
- '(("^:.*" . font-lock-keyword-face)
- ("^>.*" . font-lock-string-face)
- ("^%!.*" . font-lock-reference-face)
- ("^%.*" . font-lock-comment-face)
- ("\\`(\\([a-z]+\\) +\\([A-Z]+\\)"
- (1 font-lock-string-face)
- (2 font-lock-keyword-face))
- ("^)\\([A-Z ]+\\)\\([a-z ]+\\)"
- (1 font-lock-keyword-face)
- (2 font-lock-string-face)))
- "Expressions to fontify in Decipher mode.
-
-Ciphertext uses `font-lock-keyword-face', plaintext uses
-`font-lock-string-face', comments use `font-lock-comment-face', and
-checkpoints use `font-lock-reference-face'. You can customize the
-display by changing these variables. For best results, I recommend
-that all faces use the same background color.
-
-For example, to display ciphertext in the `bold' face, use
- (add-hook 'decipher-mode-hook
- (lambda () (set (make-local-variable 'font-lock-keyword-face)
- 'bold)))
-in your `.emacs' file.")
-
-(defvar decipher-mode-map nil
- "Keymap for Decipher mode.")
-(if (not decipher-mode-map)
- (progn
- (setq decipher-mode-map (make-keymap))
- (suppress-keymap decipher-mode-map)
- (define-key decipher-mode-map "A" 'decipher-show-alphabet)
- (define-key decipher-mode-map "C" 'decipher-complete-alphabet)
- (define-key decipher-mode-map "D" 'decipher-digram-list)
- (define-key decipher-mode-map "F" 'decipher-frequency-count)
- (define-key decipher-mode-map "M" 'decipher-make-checkpoint)
- (define-key decipher-mode-map "N" 'decipher-adjacency-list)
- (define-key decipher-mode-map "R" 'decipher-restore-checkpoint)
- (define-key decipher-mode-map "U" 'decipher-undo)
- (define-key decipher-mode-map " " 'decipher-keypress)
- (substitute-key-definition 'undo 'decipher-undo
- decipher-mode-map global-map)
- (substitute-key-definition 'advertised-undo 'decipher-undo
- decipher-mode-map global-map)
- (let ((key ?a))
- (while (<= key ?z)
- (define-key decipher-mode-map (vector key) 'decipher-keypress)
- (incf key)))))
-
-(defvar decipher-stats-mode-map nil
- "Keymap for Decipher-Stats mode.")
-(if (not decipher-stats-mode-map)
- (progn
- (setq decipher-stats-mode-map (make-keymap))
- (suppress-keymap decipher-stats-mode-map)
- (define-key decipher-stats-mode-map "D" 'decipher-digram-list)
- (define-key decipher-stats-mode-map "F" 'decipher-frequency-count)
- (define-key decipher-stats-mode-map "N" 'decipher-adjacency-list)
- ))
-
-(defvar decipher-mode-syntax-table nil
- "Decipher mode syntax table")
-
-(if decipher-mode-syntax-table
- ()
- (let ((table (make-syntax-table))
- (c ?0))
- (while (<= c ?9)
- (modify-syntax-entry c "_" table) ;Digits are not part of words
- (incf c))
- (setq decipher-mode-syntax-table table)))
-
-(defvar decipher-alphabet nil)
-;; This is an alist containing entries (PLAIN-CHAR . CIPHER-CHAR),
-;; where PLAIN-CHAR runs from ?a to ?z and CIPHER-CHAR is an uppercase
-;; letter or space (which means no mapping is known for that letter).
-;; This *must* contain entries for all lowercase characters.
-(make-variable-buffer-local 'decipher-alphabet)
-
-(defvar decipher-stats-buffer nil
- "The buffer which displays statistics for this ciphertext.
-Do not access this variable directly, use the function
-`decipher-stats-buffer' instead.")
-(make-variable-buffer-local 'decipher-stats-buffer)
-
-(defvar decipher-undo-list-size 0
- "The number of entries in the undo list.")
-(make-variable-buffer-local 'decipher-undo-list-size)
-
-(defvar decipher-undo-list nil
- "The undo list for this buffer.
-Each element is either a cons cell (PLAIN-CHAR . CIPHER-CHAR) or a
-list of such cons cells.")
-(make-variable-buffer-local 'decipher-undo-list)
-
-(defvar decipher-pending-undo-list nil)
-
-;; The following variables are used by the analysis functions
-;; and are defined here to avoid byte-compiler warnings.
-;; Don't mess with them unless you know what you're doing.
-(defvar decipher-char nil
- "See the functions decipher-loop-with-breaks and decipher-loop-no-breaks.")
-(defvar decipher--prev-char)
-(defvar decipher--digram)
-(defvar decipher--digram-list)
-(defvar decipher--before)
-(defvar decipher--after)
-(defvar decipher--freqs)
-
-;;;===================================================================
-;;; Code:
-;;;===================================================================
-;; Main entry points:
-;;--------------------------------------------------------------------
-
-;;;###autoload
-(defun decipher ()
- "Format a buffer of ciphertext for cryptanalysis and enter Decipher mode."
- (interactive)
- ;; Make sure the buffer ends in a newline:
- (goto-char (point-max))
- (or (bolp)
- (insert "\n"))
- ;; See if it's already in decipher format:
- (goto-char (point-min))
- (if (looking-at "^(abcdefghijklmnopqrstuvwxyz \
-ABCDEFGHIJKLMNOPQRSTUVWXYZ -\\*-decipher-\\*-\n)")
- (message "Buffer is already formatted, entering Decipher mode...")
- ;; Add the alphabet at the beginning of the file
- (insert "(abcdefghijklmnopqrstuvwxyz \
-ABCDEFGHIJKLMNOPQRSTUVWXYZ -*-decipher-*-\n)\n\n")
- ;; Add lines for the solution:
- (let (begin)
- (while (not (eobp))
- (if (looking-at "^%")
- (forward-line) ;Leave comments alone
- (delete-horizontal-space)
- (if (eolp)
- (forward-line) ;Just leave blank lines alone
- (insert ":") ;Mark ciphertext line
- (setq begin (point))
- (forward-line)
- (if decipher-force-uppercase
- (upcase-region begin (point))) ;Convert ciphertext to uppercase
- (insert ">\n"))))) ;Mark plaintext line
- (delete-blank-lines) ;Remove any blank lines
- (delete-blank-lines)) ; at end of buffer
- (goto-line 4)
- (decipher-mode))
-
-;;;###autoload
-(defun decipher-mode ()
- "Major mode for decrypting monoalphabetic substitution ciphers.
-Lower-case letters enter plaintext.
-Upper-case letters are commands.
-
-The buffer is made read-only so that normal Emacs commands cannot
-modify it.
-
-The most useful commands are:
-\\<decipher-mode-map>
-\\[decipher-digram-list] Display a list of all digrams & their frequency
-\\[decipher-frequency-count] Display the frequency of each ciphertext letter
-\\[decipher-adjacency-list]\
- Show adjacency list for current letter (lists letters appearing next to it)
-\\[decipher-make-checkpoint] Save the current cipher alphabet (checkpoint)
-\\[decipher-restore-checkpoint] Restore a saved cipher alphabet (checkpoint)"
- (interactive)
- (kill-all-local-variables)
- (setq buffer-undo-list t ;Disable undo
- indent-tabs-mode nil ;Do not use tab characters
- major-mode 'decipher-mode
- mode-name "Decipher")
- (if decipher-force-uppercase
- (setq case-fold-search nil)) ;Case is significant when searching
- (use-local-map decipher-mode-map)
- (set-syntax-table decipher-mode-syntax-table)
- (decipher-read-alphabet)
- (set (make-local-variable 'font-lock-defaults)
- '(decipher-font-lock-keywords t))
- ;; Make the buffer writable when we exit Decipher mode:
- (make-local-hook 'change-major-mode-hook)
- (add-hook 'change-major-mode-hook
- (lambda () (setq buffer-read-only nil
- buffer-undo-list nil))
- nil t)
- (run-hooks 'decipher-mode-hook)
- (setq buffer-read-only t))
-(put 'decipher-mode 'mode-class 'special)
-
-;;--------------------------------------------------------------------
-;; Normal key handling:
-;;--------------------------------------------------------------------
-
-(defmacro decipher-last-command-char ()
- ;; Return the char which ran this command (for compatibility with XEmacs)
- (if (fboundp 'event-to-character)
- '(event-to-character last-command-event)
- 'last-command-event))
-
-(defun decipher-keypress ()
- "Enter a plaintext or ciphertext character."
- (interactive)
- (let ((decipher-function 'decipher-set-map)
- buffer-read-only) ;Make buffer writable
- (save-excursion
- (or (save-excursion
- (beginning-of-line)
- (let ((first-char (following-char)))
- (cond
- ((= ?: first-char)
- t)
- ((= ?> first-char)
- nil)
- ((= ?\( first-char)
- (setq decipher-function 'decipher-alphabet-keypress)
- t)
- ((= ?\) first-char)
- (setq decipher-function 'decipher-alphabet-keypress)
- nil)
- (t
- (error "Bad location")))))
- (let (goal-column)
- (previous-line 1)))
- (let ((char-a (following-char))
- (char-b (decipher-last-command-char)))
- (or (and (not (= ?w (char-syntax char-a)))
- (= char-b ?\ )) ;Spacebar just advances on non-letters
- (funcall decipher-function char-a char-b)))))
- (forward-char))
-
-(defun decipher-alphabet-keypress (a b)
- ;; Handle keypresses in the alphabet lines.
- ;; A is the character in the alphabet row (which starts with '(')
- ;; B is the character pressed
- (cond ((and (>= a ?A) (<= a ?Z))
- ;; If A is uppercase, then it is in the ciphertext alphabet:
- (decipher-set-map a b))
- ((and (>= a ?a) (<= a ?z))
- ;; If A is lowercase, then it is in the plaintext alphabet:
- (if (= b ?\ )
- ;; We are clearing the association (if any):
- (if (/= ?\ (setq b (cdr (assoc a decipher-alphabet))))
- (decipher-set-map b ?\ ))
- ;; Associate the plaintext char with the char pressed:
- (decipher-set-map b a)))
- (t
- ;; If A is not a letter, that's a problem:
- (error "Bad character"))))
-
-;;--------------------------------------------------------------------
-;; Undo:
-;;--------------------------------------------------------------------
-
-(defun decipher-undo ()
- "Undo a change in Decipher mode."
- (interactive)
- ;; If we don't get all the way thru, make last-command indicate that
- ;; for the following command.
- (setq this-command t)
- (or (eq major-mode 'decipher-mode)
- (error "This buffer is not in Decipher mode"))
- (or (eq last-command 'decipher-undo)
- (setq decipher-pending-undo-list decipher-undo-list))
- (or decipher-pending-undo-list
- (error "No further undo information"))
- (let ((undo-rec (pop decipher-pending-undo-list))
- buffer-read-only ;Make buffer writable
- redo-map redo-rec undo-map)
- (or (consp (car undo-rec))
- (setq undo-rec (list undo-rec)))
- (while (setq undo-map (pop undo-rec))
- (setq redo-map (decipher-get-undo (cdr undo-map) (car undo-map)))
- (if redo-map
- (setq redo-rec
- (if (consp (car redo-map))
- (append redo-map redo-rec)
- (cons redo-map redo-rec))))
- (decipher-set-map (cdr undo-map) (car undo-map) t))
- (decipher-add-undo redo-rec))
- (setq this-command 'decipher-undo)
- (message "Undo!"))
-
-(defun decipher-add-undo (undo-rec)
- "Add UNDO-REC to the undo list."
- (if undo-rec
- (progn
- (push undo-rec decipher-undo-list)
- (incf decipher-undo-list-size)
- (if (> decipher-undo-list-size decipher-undo-limit)
- (let ((new-size (- decipher-undo-limit 100)))
- ;; Truncate undo list to NEW-SIZE elements:
- (setcdr (nthcdr (1- new-size) decipher-undo-list) nil)
- (setq decipher-undo-list-size new-size))))))
-
-(defun decipher-get-undo-copy (cons)
- (if cons
- (cons (car cons) (cdr cons))))
-
-(defun decipher-get-undo (cipher-char plain-char)
- ;; Return an undo record that will undo the result of
- ;; (decipher-set-map CIPHER-CHAR PLAIN-CHAR)
- ;; We must copy the cons cell because the original cons cells will be
- ;; modified using setcdr.
- (let ((cipher-map (decipher-get-undo-copy (rassoc cipher-char decipher-alphabet)))
- (plain-map (decipher-get-undo-copy (assoc plain-char decipher-alphabet))))
- (cond ((equal ?\ plain-char)
- cipher-map)
- ((equal cipher-char (cdr plain-map))
- nil) ;We aren't changing anything
- ((equal ?\ (cdr plain-map))
- (or cipher-map (cons ?\ cipher-char)))
- (cipher-map
- (list plain-map cipher-map))
- (t
- plain-map))))
-
-;;--------------------------------------------------------------------
-;; Mapping ciphertext and plaintext:
-;;--------------------------------------------------------------------
-
-(defun decipher-set-map (cipher-char plain-char &optional no-undo)
- ;; Associate a ciphertext letter with a plaintext letter
- ;; CIPHER-CHAR must be an uppercase or lowercase letter
- ;; PLAIN-CHAR must be a lowercase letter (or a space)
- ;; NO-UNDO if non-nil means do not record undo information
- ;; Any existing associations for CIPHER-CHAR or PLAIN-CHAR will be erased.
- (setq cipher-char (upcase cipher-char))
- (or (and (>= cipher-char ?A) (<= cipher-char ?Z))
- (error "Bad character")) ;Cipher char must be uppercase letter
- (or no-undo
- (decipher-add-undo (decipher-get-undo cipher-char plain-char)))
- (let ((cipher-string (char-to-string cipher-char))
- (plain-string (char-to-string plain-char))
- case-fold-search ;Case is significant
- mapping bound)
- (save-excursion
- (goto-char (point-min))
- (if (setq mapping (rassoc cipher-char decipher-alphabet))
- (progn
- (setcdr mapping ?\ )
- (search-forward-regexp (concat "^([a-z]*"
- (char-to-string (car mapping))))
- (decipher-insert ?\ )
- (beginning-of-line)))
- (if (setq mapping (assoc plain-char decipher-alphabet))
- (progn
- (if (/= ?\ (cdr mapping))
- (decipher-set-map (cdr mapping) ?\ t))
- (setcdr mapping cipher-char)
- (search-forward-regexp (concat "^([a-z]*" plain-string))
- (decipher-insert cipher-char)
- (beginning-of-line)))
- (search-forward-regexp (concat "^([a-z]+ [A-Z]*" cipher-string))
- (decipher-insert plain-char)
- (setq case-fold-search t ;Case is not significant
- cipher-string (downcase cipher-string))
- (let ((font-lock-fontify-region-function 'ignore))
- ;; insert-and-inherit will pick the right face automatically
- (while (search-forward-regexp "^:" nil t)
- (setq bound (save-excursion (end-of-line) (point)))
- (while (search-forward cipher-string bound 'end)
- (decipher-insert plain-char)))))))
-
-(defun decipher-insert (char)
- ;; Insert CHAR in the row below point. It replaces any existing
- ;; character in that position.
- (let ((col (1- (current-column))))
- (save-excursion
- (forward-line)
- (or (= ?\> (following-char))
- (= ?\) (following-char))
- (error "Bad location"))
- (move-to-column col t)
- (or (eolp)
- (delete-char 1))
- (insert-and-inherit char))))
-
-;;--------------------------------------------------------------------
-;; Checkpoints:
-;;--------------------------------------------------------------------
-;; A checkpoint is a comment of the form:
-;; %!ABCDEFGHIJKLMNOPQRSTUVWXYZ! Description
-;; Such comments are usually placed at the end of the buffer following
-;; this header (which is inserted by decipher-make-checkpoint):
-;; %---------------------------
-;; % Checkpoints:
-;; % abcdefghijklmnopqrstuvwxyz
-;; but this is not required; checkpoints can be placed anywhere.
-;;
-;; The description is optional; all that is required is the alphabet.
-
-(defun decipher-make-checkpoint (desc)
- "Checkpoint the current cipher alphabet.
-This records the current alphabet so you can return to it later.
-You may have any number of checkpoints.
-Type `\\[decipher-restore-checkpoint]' to restore a checkpoint."
- (interactive "sCheckpoint description: ")
- (or (stringp desc)
- (setq desc ""))
- (let (alphabet
- buffer-read-only ;Make buffer writable
- mapping)
- (goto-char (point-min))
- (re-search-forward "^)")
- (move-to-column 27 t)
- (setq alphabet (buffer-substring-no-properties (- (point) 26) (point)))
- (if (re-search-forward "^%![A-Z ]+!" nil 'end)
- nil ; Add new checkpoint with others
- (if (re-search-backward "^% *Local Variables:" nil t)
- ;; Add checkpoints before local variables list:
- (progn (forward-line -1)
- (or (looking-at "^ *$")
- (progn (forward-line) (insert ?\n) (forward-line -1)))))
- (insert "\n%" (make-string 69 ?\-)
- "\n% Checkpoints:\n% abcdefghijklmnopqrstuvwxyz\n"))
- (beginning-of-line)
- (insert "%!" alphabet "! " desc ?\n)))
-
-(defun decipher-restore-checkpoint ()
- "Restore the cipher alphabet from a checkpoint.
-If point is not on a checkpoint line, moves to the first checkpoint line.
-If point is on a checkpoint, restores that checkpoint.
-
-Type `\\[decipher-make-checkpoint]' to make a checkpoint."
- (interactive)
- (beginning-of-line)
- (if (looking-at "%!\\([A-Z ]+\\)!")
- ;; Restore this checkpoint:
- (let ((alphabet (match-string 1))
- buffer-read-only) ;Make buffer writable
- (goto-char (point-min))
- (re-search-forward "^)")
- (or (eolp)
- (delete-region (point) (progn (end-of-line) (point))))
- (insert alphabet)
- (decipher-resync))
- ;; Move to the first checkpoint:
- (goto-char (point-min))
- (if (re-search-forward "^%![A-Z ]+!" nil t)
- (message "Select the checkpoint to restore and type `%s'"
- (substitute-command-keys "\\[decipher-restore-checkpoint]"))
- (error "No checkpoints in this buffer"))))
-
-;;--------------------------------------------------------------------
-;; Miscellaneous commands:
-;;--------------------------------------------------------------------
-
-(defun decipher-complete-alphabet ()
- "Complete the cipher alphabet.
-This fills any blanks in the cipher alphabet with the unused letters
-in alphabetical order. Use this when you have a keyword cipher and
-you have determined the keyword."
- (interactive)
- (let ((cipher-char ?A)
- (ptr decipher-alphabet)
- buffer-read-only ;Make buffer writable
- plain-map undo-rec)
- (while (setq plain-map (pop ptr))
- (if (equal ?\ (cdr plain-map))
- (progn
- (while (rassoc cipher-char decipher-alphabet)
- ;; Find the next unused letter
- (incf cipher-char))
- (push (cons ?\ cipher-char) undo-rec)
- (decipher-set-map cipher-char (car plain-map) t))))
- (decipher-add-undo undo-rec)))
-
-(defun decipher-show-alphabet ()
- "Display the current cipher alphabet in the message line."
- (interactive)
- (message
- (mapconcat (lambda (a)
- (concat
- (char-to-string (car a))
- (char-to-string (cdr a))))
- decipher-alphabet
- "")))
-
-(defun decipher-resync ()
- "Reprocess the buffer using the alphabet from the top.
-This regenerates all deciphered plaintext and clears the undo list.
-You should use this if you edit the ciphertext."
- (interactive)
- (message "Reprocessing buffer...")
- (let (alphabet
- buffer-read-only ;Make buffer writable
- mapping)
- (save-excursion
- (decipher-read-alphabet)
- (setq alphabet decipher-alphabet)
- (goto-char (point-min))
- (and (re-search-forward "^).+" nil t)
- (replace-match ")" nil nil))
- (while (re-search-forward "^>.+" nil t)
- (replace-match ">" nil nil))
- (decipher-read-alphabet)
- (while (setq mapping (pop alphabet))
- (or (equal ?\ (cdr mapping))
- (decipher-set-map (cdr mapping) (car mapping))))))
- (setq decipher-undo-list nil
- decipher-undo-list-size 0)
- (message "Reprocessing buffer...done"))
-
-;;--------------------------------------------------------------------
-;; Miscellaneous functions:
-;;--------------------------------------------------------------------
-
-(defun decipher-read-alphabet ()
- "Build the decipher-alphabet from the alphabet line in the buffer."
- (save-excursion
- (goto-char (point-min))
- (search-forward-regexp "^)")
- (move-to-column 27 t)
- (setq decipher-alphabet nil)
- (let ((plain-char ?z))
- (while (>= plain-char ?a)
- (backward-char)
- (push (cons plain-char (following-char)) decipher-alphabet)
- (decf plain-char)))))
-
-;;;===================================================================
-;;; Analyzing ciphertext:
-;;;===================================================================
-
-(defun decipher-frequency-count ()
- "Display the frequency count in the statistics buffer."
- (interactive)
- (decipher-analyze)
- (decipher-display-regexp "^A" "^[A-Z][A-Z]"))
-
-(defun decipher-digram-list ()
- "Display the list of digrams in the statistics buffer."
- (interactive)
- (decipher-analyze)
- (decipher-display-regexp "[A-Z][A-Z] +[0-9]" "^$"))
-
-(defun decipher-adjacency-list (cipher-char)
- "Display the adjacency list for the letter at point.
-The adjacency list shows all letters which come next to CIPHER-CHAR.
-
-An adjacency list (for the letter X) looks like this:
- 1 1 1 1 1 3 2 1 3 8
-X: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z * 11 14 9%
- 1 1 1 2 1 1 2 5 7
-This says that X comes before D once, and after B once. X begins 5
-words, and ends 3 words (`*' represents a space). X comes before 8
-different letters, after 7 differerent letters, and is next to a total
-of 11 different letters. It occurs 14 times, making up 9% of the
-ciphertext."
- (interactive (list (upcase (following-char))))
- (decipher-analyze)
- (let (start end)
- (save-excursion
- (set-buffer (decipher-stats-buffer))
- (goto-char (point-min))
- (or (re-search-forward (format "^%c: " cipher-char) nil t)
- (error "Character `%c' is not used in ciphertext." cipher-char))
- (forward-line -1)
- (setq start (point))
- (forward-line 3)
- (setq end (point)))
- (decipher-display-range start end)))
-
-;;--------------------------------------------------------------------
-(defun decipher-analyze ()
- "Perform frequency analysis on the current buffer if necessary."
- (cond
- ;; If this is the statistics buffer, do nothing:
- ((eq major-mode 'decipher-stats-mode))
- ;; If this is the Decipher buffer, see if the stats buffer exists:
- ((eq major-mode 'decipher-mode)
- (or (and (bufferp decipher-stats-buffer)
- (buffer-name decipher-stats-buffer))
- (decipher-analyze-buffer)))
- ;; Otherwise:
- (t (error "This buffer is not in Decipher mode"))))
-
-;;--------------------------------------------------------------------
-(defun decipher-display-range (start end)
- "Display text between START and END in the statistics buffer.
-START and END are positions in the statistics buffer. Makes the
-statistics buffer visible and sizes the window to just fit the
-displayed text, but leaves the current window selected."
- (let ((stats-buffer (decipher-stats-buffer))
- (current-window (selected-window))
- (pop-up-windows t))
- (or (eq (current-buffer) stats-buffer)
- (pop-to-buffer stats-buffer))
- (goto-char start)
- (or (one-window-p t)
- (enlarge-window (- (1+ (count-lines start end)) (window-height))))
- (recenter 0)
- (select-window current-window)))
-
-(defun decipher-display-regexp (start-regexp end-regexp)
- "Display text between two regexps in the statistics buffer.
-
-START-REGEXP matches the first line to display.
-END-REGEXP matches the line after that which ends the display.
-The ending line is included in the display unless it is blank."
- (let (start end)
- (save-excursion
- (set-buffer (decipher-stats-buffer))
- (goto-char (point-min))
- (re-search-forward start-regexp)
- (beginning-of-line)
- (setq start (point))
- (re-search-forward end-regexp)
- (beginning-of-line)
- (or (looking-at "^ *$")
- (forward-line 1))
- (setq end (point)))
- (decipher-display-range start end)))
-
-;;--------------------------------------------------------------------
-(defun decipher-loop-with-breaks (func)
- "Loop through ciphertext, calling FUNC once for each letter & word division.
-
-FUNC is called with no arguments, and its return value is unimportant.
-It may examine `decipher-char' to see the current ciphertext
-character. `decipher-char' contains either an uppercase letter or a space.
-
-FUNC is called exactly once between words, with `decipher-char' set to
-a space.
-
-See `decipher-loop-no-breaks' if you do not care about word divisions."
- (let ((decipher-char ?\ )
- (decipher--loop-prev-char ?\ ))
- (save-excursion
- (goto-char (point-min))
- (funcall func) ;Space marks beginning of first word
- (while (search-forward-regexp "^:" nil t)
- (while (not (eolp))
- (setq decipher-char (upcase (following-char)))
- (or (and (>= decipher-char ?A) (<= decipher-char ?Z))
- (setq decipher-char ?\ ))
- (or (and (equal decipher-char ?\ )
- (equal decipher--loop-prev-char ?\ ))
- (funcall func))
- (setq decipher--loop-prev-char decipher-char)
- (forward-char))
- (or (equal decipher-char ?\ )
- (progn
- (setq decipher-char ?\ ;
- decipher--loop-prev-char ?\ )
- (funcall func)))))))
-
-(defun decipher-loop-no-breaks (func)
- "Loop through ciphertext, calling FUNC once for each letter.
-
-FUNC is called with no arguments, and its return value is unimportant.
-It may examine `decipher-char' to see the current ciphertext letter.
-`decipher-char' contains an uppercase letter.
-
-Punctuation and spacing in the ciphertext are ignored.
-See `decipher-loop-with-breaks' if you care about word divisions."
- (let (decipher-char)
- (save-excursion
- (goto-char (point-min))
- (while (search-forward-regexp "^:" nil t)
- (while (not (eolp))
- (setq decipher-char (upcase (following-char)))
- (and (>= decipher-char ?A)
- (<= decipher-char ?Z)
- (funcall func))
- (forward-char))))))
-
-;;--------------------------------------------------------------------
-;; Perform the analysis:
-;;--------------------------------------------------------------------
-
-(defun decipher-insert-frequency-counts (freq-list total)
- "Insert frequency counts in current buffer.
-Each element of FREQ-LIST is a list (LETTER FREQ ...).
-TOTAL is the total number of letters in the ciphertext."
- (let ((i 4) temp-list)
- (while (> i 0)
- (setq temp-list freq-list)
- (while temp-list
- (insert (caar temp-list)
- (format "%4d%3d%% "
- (cadar temp-list)
- (/ (* 100 (cadar temp-list)) total)))
- (setq temp-list (nthcdr 4 temp-list)))
- (insert ?\n)
- (setq freq-list (cdr freq-list)
- i (1- i)))))
-
-(defun decipher--analyze ()
- ;; Perform frequency analysis on ciphertext.
- ;;
- ;; This function is called repeatedly with decipher-char set to each
- ;; character of ciphertext. It uses decipher--prev-char to remember
- ;; the previous ciphertext character.
- ;;
- ;; It builds several data structures, which must be initialized
- ;; before the first call to decipher--analyze. The arrays are
- ;; indexed with A = 0, B = 1, ..., Z = 25, SPC = 26 (if used).
- ;; decipher--after: (initialize to zeros)
- ;; A vector of 26 vectors of 27 integers. The first vector
- ;; represents the number of times A follows each character, the
- ;; second vector represents B, and so on.
- ;; decipher--before: (initialize to zeros)
- ;; The same as decipher--after, but representing the number of
- ;; times the character precedes each other character.
- ;; decipher--digram-list: (initialize to nil)
- ;; An alist with an entry for each digram (2-character sequence)
- ;; encountered. Each element is a cons cell (DIGRAM . FREQ),
- ;; where DIGRAM is a 2 character string and FREQ is the number
- ;; of times it occurs.
- ;; decipher--freqs: (initialize to zeros)
- ;; A vector of 26 integers, counting the number of occurrences
- ;; of the corresponding characters.
- (setq decipher--digram (format "%c%c" decipher--prev-char decipher-char))
- (incf (cdr (or (assoc decipher--digram decipher--digram-list)
- (car (push (cons decipher--digram 0)
- decipher--digram-list)))))
- (and (>= decipher--prev-char ?A)
- (incf (aref (aref decipher--before (- decipher--prev-char ?A))
- (if (equal decipher-char ?\ )
- 26
- (- decipher-char ?A)))))
- (and (>= decipher-char ?A)
- (incf (aref decipher--freqs (- decipher-char ?A)))
- (incf (aref (aref decipher--after (- decipher-char ?A))
- (if (equal decipher--prev-char ?\ )
- 26
- (- decipher--prev-char ?A)))))
- (setq decipher--prev-char decipher-char))
-
-(defun decipher--digram-counts (counts)
- "Generate the counts for an adjacency list."
- (let ((total 0))
- (concat
- (mapconcat (lambda (x)
- (cond ((> x 99) (incf total) "XX")
- ((> x 0) (incf total) (format "%2d" x))
- (t " ")))
- counts
- "")
- (format "%4d" (if (> (aref counts 26) 0)
- (1- total) ;Don't count space
- total)))))
-
-(defun decipher--digram-total (before-count after-count)
- "Count the number of different letters a letter appears next to."
- ;; We do not include spaces (word divisions) in this count.
- (let ((total 0)
- (i 26))
- (while (>= (decf i) 0)
- (if (or (> (aref before-count i) 0)
- (> (aref after-count i) 0))
- (incf total)))
- total))
-
-(defun decipher-analyze-buffer ()
- "Perform frequency analysis and store results in statistics buffer.
-Creates the statistics buffer if it doesn't exist."
- (let ((decipher--prev-char (if decipher-ignore-spaces ?\ ?\*))
- (decipher--before (make-vector 26 nil))
- (decipher--after (make-vector 26 nil))
- (decipher--freqs (make-vector 26 0))
- (total-chars 0)
- decipher--digram decipher--digram-list freq-list)
- (message "Scanning buffer...")
- (let ((i 26))
- (while (>= (decf i) 0)
- (aset decipher--before i (make-vector 27 0))
- (aset decipher--after i (make-vector 27 0))))
- (if decipher-ignore-spaces
- (progn
- (decipher-loop-no-breaks 'decipher--analyze)
- ;; The first character of ciphertext was marked as following a space:
- (let ((i 26))
- (while (>= (decf i) 0)
- (aset (aref decipher--after i) 26 0))))
- (decipher-loop-with-breaks 'decipher--analyze))
- (message "Processing results...")
- (setcdr (last decipher--digram-list 2) nil) ;Delete the phony "* " digram
- ;; Sort the digram list by frequency and alphabetical order:
- (setq decipher--digram-list (sort (sort decipher--digram-list
- (lambda (a b) (string< (car a) (car b))))
- (lambda (a b) (> (cdr a) (cdr b)))))
- ;; Generate the frequency list:
- ;; Each element is a list of 3 elements (LETTER FREQ DIFFERENT),
- ;; where LETTER is the ciphertext character, FREQ is the number
- ;; of times it occurs, and DIFFERENT is the number of different
- ;; letters it appears next to.
- (let ((i 26))
- (while (>= (decf i) 0)
- (setq freq-list
- (cons (list (+ i ?A)
- (aref decipher--freqs i)
- (decipher--digram-total (aref decipher--before i)
- (aref decipher--after i)))
- freq-list)
- total-chars (+ total-chars (aref decipher--freqs i)))))
- (save-excursion
- ;; Switch to statistics buffer, creating it if necessary:
- (set-buffer (decipher-stats-buffer t))
- ;; This can't happen, but it never hurts to double-check:
- (or (eq major-mode 'decipher-stats-mode)
- (error "Buffer %s is not in Decipher-Stats mode" (buffer-name)))
- (setq buffer-read-only nil)
- (erase-buffer)
- ;; Display frequency counts for letters A-Z:
- (decipher-insert-frequency-counts freq-list total-chars)
- (insert ?\n)
- ;; Display frequency counts for letters in order of frequency:
- (setq freq-list (sort freq-list
- (lambda (a b) (> (second a) (second b)))))
- (decipher-insert-frequency-counts freq-list total-chars)
- ;; Display letters in order of frequency:
- (insert ?\n (mapconcat (lambda (a) (char-to-string (car a)))
- freq-list nil)
- "\n\n")
- ;; Display list of digrams in order of frequency:
- (let* ((rows (floor (+ (length decipher--digram-list) 9) 10))
- (i rows)
- temp-list)
- (while (> i 0)
- (setq temp-list decipher--digram-list)
- (while temp-list
- (insert (caar temp-list)
- (format "%3d "
- (cdar temp-list)))
- (setq temp-list (nthcdr rows temp-list)))
- (delete-horizontal-space)
- (insert ?\n)
- (setq decipher--digram-list (cdr decipher--digram-list)
- i (1- i))))
- ;; Display adjacency list for each letter, sorted in descending
- ;; order of the number of adjacent letters:
- (setq freq-list (sort freq-list
- (lambda (a b) (> (third a) (third b)))))
- (let ((temp-list freq-list)
- entry i)
- (while (setq entry (pop temp-list))
- (if (equal 0 (second entry))
- nil ;This letter was not used
- (setq i (- (car entry) ?A))
- (insert ?\n " "
- (decipher--digram-counts (aref decipher--before i)) ?\n
- (car entry)
- ": A B C D E F G H I J K L M N O P Q R S T U V W X Y Z *"
- (format "%4d %4d %3d%%\n "
- (third entry) (second entry)
- (/ (* 100 (second entry)) total-chars))
- (decipher--digram-counts (aref decipher--after i)) ?\n))))
- (setq buffer-read-only t)
- (set-buffer-modified-p nil)
- ))
- (message nil))
-
-;;====================================================================
-;; Statistics Buffer:
-;;====================================================================
-
-(defun decipher-stats-mode ()
- "Major mode for displaying ciphertext statistics."
- (interactive)
- (kill-all-local-variables)
- (setq buffer-read-only t
- buffer-undo-list t ;Disable undo
- case-fold-search nil ;Case is significant when searching
- indent-tabs-mode nil ;Do not use tab characters
- major-mode 'decipher-stats-mode
- mode-name "Decipher-Stats")
- (use-local-map decipher-stats-mode-map)
- (run-hooks 'decipher-stats-mode-hook))
-(put 'decipher-stats-mode 'mode-class 'special)
-
-;;--------------------------------------------------------------------
-
-(defun decipher-display-stats-buffer ()
- "Make the statistics buffer visible, but do not select it."
- (let ((stats-buffer (decipher-stats-buffer))
- (current-window (selected-window)))
- (or (eq (current-buffer) stats-buffer)
- (progn
- (pop-to-buffer stats-buffer)
- (select-window current-window)))))
-
-(defun decipher-stats-buffer (&optional create)
- "Return the buffer used for decipher statistics.
-If CREATE is non-nil, create the buffer if it doesn't exist.
-This is guaranteed to return a buffer in Decipher-Stats mode;
-if it can't, it signals an error."
- (cond
- ;; We may already be in the statistics buffer:
- ((eq major-mode 'decipher-stats-mode)
- (current-buffer))
- ;; See if decipher-stats-buffer exists:
- ((and (bufferp decipher-stats-buffer)
- (buffer-name decipher-stats-buffer))
- (or (save-excursion
- (set-buffer decipher-stats-buffer)
- (eq major-mode 'decipher-stats-mode))
- (error "Buffer %s is not in Decipher-Stats mode"
- (buffer-name decipher-stats-buffer)))
- decipher-stats-buffer)
- ;; Create a new buffer if requested:
- (create
- (let ((stats-name (concat "*" (buffer-name) "*")))
- (setq decipher-stats-buffer
- (if (eq 'decipher-stats-mode
- (cdr-safe (assoc 'major-mode
- (buffer-local-variables
- (get-buffer stats-name)))))
- ;; We just lost track of the statistics buffer:
- (get-buffer stats-name)
- (generate-new-buffer stats-name))))
- (save-excursion
- (set-buffer decipher-stats-buffer)
- (decipher-stats-mode))
- decipher-stats-buffer)
- ;; Give up:
- (t (error "No statistics buffer"))))
-
-;;====================================================================
-
-(provide 'decipher)
-
-;;;(defun decipher-show-undo-list ()
-;;; "Display the undo list (for debugging purposes)."
-;;; (interactive)
-;;; (with-output-to-temp-buffer "*Decipher Undo*"
-;;; (let ((undo-list decipher-undo-list)
-;;; undo-rec undo-map)
-;;; (save-excursion
-;;; (set-buffer "*Decipher Undo*")
-;;; (while (setq undo-rec (pop undo-list))
-;;; (or (consp (car undo-rec))
-;;; (setq undo-rec (list undo-rec)))
-;;; (insert ?\()
-;;; (while (setq undo-map (pop undo-rec))
-;;; (insert (cdr undo-map) (car undo-map) ?\ ))
-;;; (delete-backward-char 1)
-;;; (insert ")\n"))))))
-
-;;; decipher.el ends here
diff --git a/lisp/play/dissociate.el b/lisp/play/dissociate.el
deleted file mode 100644
index 93a9f9e79ab..00000000000
--- a/lisp/play/dissociate.el
+++ /dev/null
@@ -1,101 +0,0 @@
-;;; dissociate.el --- scramble text amusingly for Emacs.
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: games
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The single entry point, `dissociated-press', applies a travesty
-;; generator to the current buffer. The results can be quite amusing.
-
-;;; Code:
-
-;;;###autoload
-(defun dissociated-press (&optional arg)
- "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."
- (interactive "P")
- (setq arg (if arg (prefix-numeric-value arg) 2))
- (let* ((inbuf (current-buffer))
- (outbuf (get-buffer-create "*Dissociation*"))
- (move-function (if (> arg 0) 'forward-char 'forward-word))
- (move-amount (if (> arg 0) arg (- arg)))
- (search-function (if (> arg 0) 'search-forward 'word-search-forward))
- (last-query-point 0))
- (if (= (point-max) (point-min))
- (error "The buffer contains no text to start from"))
- (switch-to-buffer outbuf)
- (erase-buffer)
- (while
- (save-excursion
- (goto-char last-query-point)
- (vertical-motion (- (window-height) 4))
- (or (= (point) (point-max))
- (and (progn (goto-char (point-max))
- (y-or-n-p "Continue dissociation? "))
- (progn
- (message "")
- (recenter 1)
- (setq last-query-point (point-max))
- t))))
- (let (start end)
- (save-excursion
- (set-buffer inbuf)
- (setq start (point))
- (if (eq move-function 'forward-char)
- (progn
- (setq end (+ start (+ move-amount (random 16))))
- (if (> end (point-max))
- (setq end (+ 1 move-amount (random 16))))
- (goto-char end))
- (funcall move-function
- (+ move-amount (random 16))))
- (setq end (point)))
- (let ((opoint (point)))
- (insert-buffer-substring inbuf start end)
- (save-excursion
- (goto-char opoint)
- (end-of-line)
- (and (> (current-column) fill-column)
- (do-auto-fill)))))
- (save-excursion
- (set-buffer inbuf)
- (if (eobp)
- (goto-char (point-min))
- (let ((overlap
- (buffer-substring (prog1 (point)
- (funcall move-function
- (- move-amount)))
- (point))))
- (goto-char (1+ (random (1- (point-max)))))
- (or (funcall search-function overlap nil t)
- (let ((opoint (point)))
- (goto-char 1)
- (funcall search-function overlap opoint t))))))
- (sit-for 0))))
-
-;;; dissociate.el ends here
diff --git a/lisp/play/doctor.el b/lisp/play/doctor.el
deleted file mode 100644
index faba5e1cf26..00000000000
--- a/lisp/play/doctor.el
+++ /dev/null
@@ -1,1614 +0,0 @@
-;;; doctor.el --- psychological help for frustrated users.
-;;; (censored version--see below)
-
-;; Copyright (C) 1985, 1987, 1994, 1996 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: games
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The single entry point `doctor', simulates a Rogerian analyst using
-;; phrase-production techniques similar to the classic ELIZA demonstration
-;; of pseudo-AI.
-
-;; This file has been censored by the Communications Decency Act.
-;; Some of its features were removed. The law was promoted as a ban
-;; on pornography, but it bans far more than that. The doctor program
-;; did not contain pornography, but part of it was prohibited
-;; nonetheless.
-
-;; For information on US government censorship of the Internet, and
-;; what you can do to bring back freedom of the press, see the web
-;; site http://www.vtw.org/
-
-;;; Code:
-
-(defun doctor-cadr (x) (car (cdr x)))
-(defun doctor-caddr (x) (car (cdr (cdr x))))
-(defun doctor-cddr (x) (cdr (cdr x)))
-
-(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 \.
- for your protection, i have been censored according to
- the Communications Decency Act \.
- ($ please) ($ describe) your ($ problems) \.
- each time you are finished talking, type \R\E\T twice \.))
- (insert "\n"))
-
-(defun make-doctor-variables ()
- (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-about)
- (setq feelings-about
- '((feelings about)
- (apprehensions toward)
- (thoughts on)
- (emotions toward)))
- (make-local-variable 'random-adjective)
- (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 '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 obsession 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 '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 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 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 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 screw 'sexverb)
-(doctor-put-meaning screwing '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 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 athletics '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)
-
-;;;###autoload
-(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) \.)))
- ((member sent howareyoulst)
- (doctor-type '(i\'m ok \. ($ describe) yourself \.)))
- ((or (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 3))
- (doctor-type '(are you ($ afraidof) that \?)))
- ((zerop (random 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 manageably 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 verb 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 believed 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 expelled
- explain explained explains
- fart farts feel feels felt fight fights find finds finding
- forget forgets forgot fought found
- 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 transferred 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)
- (let ((xxstr (doctor-make-string xx)))
- (and (>= (length xxstr) 2)
- (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 ninth 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 grody gross 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)
- "Replace 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 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 in the global variables SUBJ, VERB and OBJECT."
- (let ((foo (doctor-subjsearch sent key type)))
- (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 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)))
- (and auto-fill-function
- (> (current-column) fill-column)
- (apply auto-fill-function 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 \.\.\.))
- )))
- (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.
-;; But he might have removed it. I put it back. --roland
-(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)))
-
-(defun doctor-strangelove ()
- (interactive)
- (insert "Mein fuehrer!!\n")
- (doctor-read-print))
-
-;;; doctor.el ends here
diff --git a/lisp/play/dunnet.el b/lisp/play/dunnet.el
deleted file mode 100644
index 2e6ee21b1c1..00000000000
--- a/lisp/play/dunnet.el
+++ /dev/null
@@ -1,3343 +0,0 @@
-;;; dunnet.el --- Text adventure for Emacs
-
-;; Copyright (C) 1992, 1993 Free Software Foundation, Inc.
-
-;; Author: Ron Schnell <ronnie@media.mit.edu>
-;; Created: 25 Jul 1992
-;; Version: 2.0
-;; Keywords: games
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This game can be run in batch mode. To do this, use:
-;; emacs -batch -l dunnet
-
-;;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-;;; The log file should be set for your system, and it must
-;;; be writable by all.
-
-
-(defvar dun-log-file "/usr/local/dunnet.score"
- "Name of file to store score information for dunnet.")
-
-(if nil
- (eval-and-compile (setq byte-compile-warnings nil)))
-
-(eval-when-compile
- (require 'cl))
-
-;;;; Mode definitions for interactive mode
-
-(defun dun-mode ()
- "Major mode for running dunnet."
- (interactive)
- (text-mode)
- (make-local-variable 'scroll-step)
- (setq scroll-step 2)
- (use-local-map dungeon-mode-map)
- (setq major-mode 'dungeon-mode)
- (setq mode-name "Dungeon"))
-
-(defun dun-parse (arg)
- "Function called when return is pressed in interactive mode to parse line."
- (interactive "*p")
- (beginning-of-line)
- (setq beg (+ (point) 1))
- (end-of-line)
- (if (and (not (= beg (point))) (not (< (point) beg))
- (string= ">" (buffer-substring (- beg 1) beg)))
- (progn
- (setq line (downcase (buffer-substring beg (point))))
- (princ line)
- (if (eq (dun-vparse dun-ignore dun-verblist line) -1)
- (dun-mprinc "I don't understand that.\n")))
- (goto-char (point-max))
- (dun-mprinc "\n"))
- (dun-messages))
-
-(defun dun-messages ()
- (if dun-dead
- (text-mode)
- (if (eq dungeon-mode 'dungeon)
- (progn
- (if (not (= room dun-current-room))
- (progn
- (dun-describe-room dun-current-room)
- (setq room dun-current-room)))
- (dun-fix-screen)
- (dun-mprinc ">")))))
-
-
-;;;###autoload
-(defun dunnet ()
- "Switch to *dungeon* buffer and start game."
- (interactive)
- (switch-to-buffer "*dungeon*")
- (insert "This version of Dunnet has been censored for your protection
-in accord with the Communications Decency Act.\n\n")
- (dun-mode)
- (setq dun-dead nil)
- (setq room 0)
- (dun-messages))
-
-;;;;
-;;;; This section contains all of the verbs and commands.
-;;;;
-
-;;; Give long description of room if haven't been there yet. Otherwise
-;;; short. Also give long if we were called with negative room number.
-
-(defun dun-describe-room (room)
- (if (and (not (member (abs room) dun-light-rooms))
- (not (member obj-lamp dun-inventory)))
- (dun-mprincl "It is pitch dark. You are likely to be eaten by a grue.")
- (dun-mprincl (cadr (nth (abs room) dun-rooms)))
- (if (and (and (or (member room dun-visited)
- (string= dun-mode "dun-superb")) (> room 0))
- (not (string= dun-mode "long")))
- nil
- (dun-mprinc (car (nth (abs room) dun-rooms)))
- (dun-mprinc "\n"))
- (if (not (string= dun-mode "long"))
- (if (not (member (abs room) dun-visited))
- (setq dun-visited (append (list (abs room)) dun-visited))))
- (dolist (xobjs (nth dun-current-room dun-room-objects))
- (if (= xobjs obj-special)
- (dun-special-object)
- (if (>= xobjs 0)
- (dun-mprincl (car (nth xobjs dun-objects)))
- (if (not (and (= xobjs obj-bus) dun-inbus))
- (progn
- (dun-mprincl (car (nth (abs xobjs) dun-perm-objects)))))))
- (if (and (= xobjs obj-jar) dun-jar)
- (progn
- (dun-mprincl "The jar contains:")
- (dolist (x dun-jar)
- (dun-mprinc " ")
- (dun-mprincl (car (nth x dun-objects)))))))
- (if (and (member obj-bus (nth dun-current-room dun-room-objects)) dun-inbus)
- (dun-mprincl "You are on the bus."))))
-
-;;; There is a special object in the room. This object's description,
-;;; or lack thereof, depends on certain conditions.
-
-(defun dun-special-object ()
- (if (= dun-current-room computer-room)
- (if dun-computer
- (dun-mprincl
-"The panel lights are flashing in a seemingly organized pattern.")
- (dun-mprincl "The panel lights are steady and motionless.")))
-
- (if (and (= dun-current-room red-room)
- (not (member obj-towel (nth red-room dun-room-objects))))
- (dun-mprincl "There is a hole in the floor here."))
-
- (if (and (= dun-current-room marine-life-area) dun-black)
- (dun-mprincl
-"The room is lit by a black light, causing the fish, and some of
-your objects, to give off an eerie glow."))
- (if (and (= dun-current-room fourth-vermont-intersection) dun-hole)
- (progn
- (if (not dun-inbus)
- (progn
- (dun-mprincl"You fall into a hole in the ground.")
- (setq dun-current-room vermont-station)
- (dun-describe-room vermont-station))
- (progn
- (dun-mprincl
-"The bus falls down a hole in the ground and explodes.")
- (dun-die "burning")))))
-
- (if (> dun-current-room endgame-computer-room)
- (progn
- (if (not dun-correct-answer)
- (dun-endgame-question)
- (dun-mprincl "Your question is:")
- (dun-mprincl dun-endgame-question))))
-
- (if (= dun-current-room sauna)
- (progn
- (dun-mprincl (nth dun-sauna-level '(
-"It is normal room temperature in here."
-"It is luke warm in here."
-"It is comfortably hot in here."
-"It is refreshingly hot in here."
-"You are dead now.")))
- (if (and (= dun-sauna-level 3)
- (or (member obj-rms dun-inventory)
- (member obj-rms (nth dun-current-room dun-room-objects))))
- (progn
- (dun-mprincl
-"You notice the wax on your statuette beginning to melt, until it completely
-melts off. You are left with a beautiful diamond!")
- (if (member obj-rms dun-inventory)
- (progn
- (dun-remove-obj-from-inven obj-rms)
- (setq dun-inventory (append dun-inventory
- (list obj-diamond))))
- (dun-remove-obj-from-room dun-current-room obj-rms)
- (dun-replace dun-room-objects dun-current-room
- (append (nth dun-current-room dun-room-objects)
- (list obj-diamond))))
- (if (member obj-floppy dun-inventory)
- (progn
- (dun-mprincl
-"You notice your floppy disk beginning to melt. As you grab for it, the
-disk bursts into flames, and disintegrates.")
- (dun-remove-obj-from-inven obj-floppy)
- (dun-remove-obj-from-room dun-current-room obj-floppy)))))
- )))
-
-(defun dun-die (murderer)
- (dun-mprinc "\n")
- (if murderer
- (dun-mprincl "You are dead."))
- (dun-do-logfile 'dun-die murderer)
- (dun-score nil)
- (setq dun-dead t))
-
-(defun dun-quit (args)
- (dun-die nil))
-
-;;; Print every object in player's inventory. Special case for the jar,
-;;; as we must also print what is in it.
-
-(defun dun-inven (args)
- (dun-mprinc "You currently have:")
- (dun-mprinc "\n")
- (dolist (curobj dun-inventory)
- (if curobj
- (progn
- (dun-mprincl (cadr (nth curobj dun-objects)))
- (if (and (= curobj obj-jar) dun-jar)
- (progn
- (dun-mprincl "The jar contains:")
- (dolist (x dun-jar)
- (dun-mprinc " ")
- (dun-mprincl (cadr (nth x dun-objects))))))))))
-
-(defun dun-shake (obj)
- (let (objnum)
- (when (setq objnum (dun-objnum-from-args-std obj))
- (if (member objnum dun-inventory)
- (progn
-;;; If shaking anything will do anything, put here.
- (dun-mprinc "Shaking ")
- (dun-mprinc (downcase (cadr (nth objnum dun-objects))))
- (dun-mprinc " seems to have no effect.")
- (dun-mprinc "\n")
- )
- (if (and (not (member objnum (nth dun-current-room dun-room-silents)))
- (not (member objnum (nth dun-current-room dun-room-objects))))
- (dun-mprincl "I don't see that here.")
-;;; Shaking trees can be deadly
- (if (= objnum obj-tree)
- (progn
- (dun-mprinc
- "You begin to shake a tree, and notice a coconut begin to fall from the air.
-As you try to get your hand up to block it, you feel the impact as it lands
-on your head.")
- (dun-die "a coconut"))
- (if (= objnum obj-bear)
- (progn
- (dun-mprinc
-"As you go up to the bear, it removes your head and places it on the ground.")
- (dun-die "a bear"))
- (if (< objnum 0)
- (dun-mprincl "You cannot shake that.")
- (dun-mprincl "You don't have that.")))))))))
-
-
-(defun dun-drop (obj)
- (if dun-inbus
- (dun-mprincl "You can't drop anything while on the bus.")
- (let (objnum ptr)
- (when (setq objnum (dun-objnum-from-args-std obj))
- (if (not (setq ptr (member objnum dun-inventory)))
- (dun-mprincl "You don't have that.")
- (progn
- (dun-remove-obj-from-inven objnum)
- (dun-replace dun-room-objects dun-current-room
- (append (nth dun-current-room dun-room-objects)
- (list objnum)))
- (dun-mprincl "Done.")
- (if (member objnum (list obj-food obj-weight obj-jar))
- (dun-drop-check objnum))))))))
-
-;;; Dropping certain things causes things to happen.
-
-(defun dun-drop-check (objnum)
- (if (and (= objnum obj-food) (= room bear-hangout)
- (member obj-bear (nth bear-hangout dun-room-objects)))
- (progn
- (dun-mprincl
-"The bear takes the food and runs away with it. He left something behind.")
- (dun-remove-obj-from-room dun-current-room obj-bear)
- (dun-remove-obj-from-room dun-current-room obj-food)
- (dun-replace dun-room-objects dun-current-room
- (append (nth dun-current-room dun-room-objects)
- (list obj-key)))))
-
- (if (and (= objnum obj-jar) (member obj-nitric dun-jar)
- (member obj-glycerine dun-jar))
- (progn
- (dun-mprincl
- "As the jar impacts the ground it explodes into many pieces.")
- (setq dun-jar nil)
- (dun-remove-obj-from-room dun-current-room obj-jar)
- (if (= dun-current-room fourth-vermont-intersection)
- (progn
- (setq dun-hole t)
- (setq dun-current-room vermont-station)
- (dun-mprincl
-"The explosion causes a hole to open up in the ground, which you fall
-through.")))))
-
- (if (and (= objnum obj-weight) (= dun-current-room maze-button-room))
- (dun-mprincl "A passageway opens.")))
-
-;;; Give long description of current room, or an object.
-
-(defun dun-examine (obj)
- (let (objnum)
- (setq objnum (dun-objnum-from-args obj))
- (if (eq objnum obj-special)
- (dun-describe-room (* dun-current-room -1))
- (if (and (eq objnum obj-computer)
- (member obj-pc (nth dun-current-room dun-room-silents)))
- (dun-examine '("pc"))
- (if (eq objnum nil)
- (dun-mprincl "I don't know what that is.")
- (if (and (not (member objnum
- (nth dun-current-room dun-room-objects)))
- (not (member objnum
- (nth dun-current-room dun-room-silents)))
- (not (member objnum dun-inventory)))
- (dun-mprincl "I don't see that here.")
- (if (>= objnum 0)
- (if (and (= objnum obj-bone)
- (= dun-current-room marine-life-area) dun-black)
- (dun-mprincl
-"In this light you can see some writing on the bone. It says:
-For an explosive time, go to Fourth St. and Vermont.")
- (if (nth objnum dun-physobj-desc)
- (dun-mprincl (nth objnum dun-physobj-desc))
- (dun-mprincl "I see nothing special about that.")))
- (if (nth (abs objnum) dun-permobj-desc)
- (progn
- (dun-mprincl (nth (abs objnum) dun-permobj-desc)))
- (dun-mprincl "I see nothing special about that.")))))))))
-
-(defun dun-take (obj)
- (if dun-inbus
- (dun-mprincl "You can't take anything while on the bus.")
- (setq obj (dun-firstword obj))
- (if (not obj)
- (dun-mprincl "You must supply an object.")
- (if (string= obj "all")
- (let (gotsome)
- (setq gotsome nil)
- (dolist (x (nth dun-current-room dun-room-objects))
- (if (and (>= x 0) (not (= x obj-special)))
- (progn
- (setq gotsome t)
- (dun-mprinc (cadr (nth x dun-objects)))
- (dun-mprinc ": ")
- (dun-take-object x))))
- (if (not gotsome)
- (dun-mprincl "Nothing to take.")))
- (let (objnum)
- (setq objnum (cdr (assq (intern obj) dun-objnames)))
- (if (eq objnum nil)
- (progn
- (dun-mprinc "I don't know what that is.")
- (dun-mprinc "\n"))
- (dun-take-object objnum)))))))
-
-(defun dun-take-object (objnum)
- (if (and (member objnum dun-jar) (member obj-jar dun-inventory))
- (let (newjar)
- (dun-mprincl "You remove it from the jar.")
- (setq newjar nil)
- (dolist (x dun-jar)
- (if (not (= x objnum))
- (setq newjar (append newjar (list x)))))
- (setq dun-jar newjar)
- (setq dun-inventory (append dun-inventory (list objnum))))
- (if (not (member objnum (nth dun-current-room dun-room-objects)))
- (if (not (member objnum (nth dun-current-room dun-room-silents)))
- (dun-mprinc "I do not see that here.")
- (dun-try-take objnum))
- (if (>= objnum 0)
- (progn
- (if (and (car dun-inventory)
- (> (+ (dun-inven-weight) (nth objnum dun-object-lbs)) 11))
- (dun-mprinc "Your load would be too heavy.")
- (setq dun-inventory (append dun-inventory (list objnum)))
- (dun-remove-obj-from-room dun-current-room objnum)
- (dun-mprinc "Taken. ")
- (if (and (= objnum obj-towel) (= dun-current-room red-room))
- (dun-mprinc
- "Taking the towel reveals a hole in the floor."))))
- (dun-try-take objnum)))
- (dun-mprinc "\n")))
-
-(defun dun-inven-weight ()
- (let (total)
- (setq total 0)
- (dolist (x dun-jar)
- (setq total (+ total (nth x dun-object-lbs))))
- (dolist (x dun-inventory)
- (setq total (+ total (nth x dun-object-lbs)))) total))
-
-;;; We try to take an object that is untakable. Print a message
-;;; depending on what it is.
-
-(defun dun-try-take (obj)
- (dun-mprinc "You cannot take that."))
-
-(defun dun-dig (args)
- (if dun-inbus
- (dun-mprincl "You can't dig while on the bus.")
- (if (not (member 0 dun-inventory))
- (dun-mprincl "You have nothing with which to dig.")
- (if (not (nth dun-current-room dun-diggables))
- (dun-mprincl "Digging here reveals nothing.")
- (dun-mprincl "I think you found something.")
- (dun-replace dun-room-objects dun-current-room
- (append (nth dun-current-room dun-room-objects)
- (nth dun-current-room dun-diggables)))
- (dun-replace dun-diggables dun-current-room nil)))))
-
-(defun dun-climb (obj)
- (let (objnum)
- (setq objnum (dun-objnum-from-args obj))
- (cond ((null objnum)
- (dun-mprincl "I don't know that name."))
- ((and (not (eq objnum obj-special))
- (not (member objnum (nth dun-current-room dun-room-objects)))
- (not (member objnum (nth dun-current-room dun-room-silents)))
- (not (member objnum dun-inventory)))
- (dun-mprincl "I don't see that here."))
- ((and (eq objnum obj-special)
- (not (member obj-tree (nth dun-current-room dun-room-silents))))
- (dun-mprincl "There is nothing here to climb."))
- ((and (not (eq objnum obj-tree)) (not (eq objnum obj-special)))
- (dun-mprincl "You can't climb that."))
- (t
- (dun-mprincl
- "You manage to get about two feet up the tree and fall back down. You
-notice that the tree is very unsteady.")))))
-
-(defun dun-eat (obj)
- (let (objnum)
- (when (setq objnum (dun-objnum-from-args-std obj))
- (if (not (member objnum dun-inventory))
- (dun-mprincl "You don't have that.")
- (if (not (= objnum obj-food))
- (progn
- (dun-mprinc "You forcefully shove ")
- (dun-mprinc (downcase (cadr (nth objnum dun-objects))))
- (dun-mprincl " down your throat, and start choking.")
- (dun-die "choking"))
- (dun-mprincl "That tasted horrible.")
- (dun-remove-obj-from-inven obj-food))))))
-
-(defun dun-put (args)
- (if dun-inbus
- (dun-mprincl "You can't do that while on the bus")
- (let (newargs objnum objnum2 obj)
- (setq newargs (dun-firstwordl args))
- (if (not newargs)
- (dun-mprincl "You must supply an object")
- (setq obj (intern (car newargs)))
- (setq objnum (cdr (assq obj dun-objnames)))
- (if (not objnum)
- (dun-mprincl "I don't know what that object is.")
- (if (not (member objnum dun-inventory))
- (dun-mprincl "You don't have that.")
- (setq newargs (dun-firstwordl (cdr newargs)))
- (setq newargs (dun-firstwordl (cdr newargs)))
- (if (not newargs)
- (dun-mprincl "You must supply an indirect object.")
- (setq objnum2 (cdr (assq (intern (car newargs)) dun-objnames)))
- (if (and (eq objnum2 obj-computer) (= dun-current-room pc-area))
- (setq objnum2 obj-pc))
- (if (not objnum2)
- (dun-mprincl "I don't know what that indirect object is.")
- (if (and (not (member objnum2
- (nth dun-current-room dun-room-objects)))
- (not (member objnum2
- (nth dun-current-room dun-room-silents)))
- (not (member objnum2 dun-inventory)))
- (dun-mprincl "That indirect object is not here.")
- (dun-put-objs objnum objnum2))))))))))
-
-(defun dun-put-objs (obj1 obj2)
- (if (and (= obj2 obj-drop) (not dun-nomail))
- (setq obj2 obj-chute))
-
- (if (= obj2 obj-disposal) (setq obj2 obj-chute))
-
- (if (and (= obj1 obj-cpu) (= obj2 obj-computer))
- (progn
- (dun-remove-obj-from-inven obj-cpu)
- (setq dun-computer t)
- (dun-mprincl
-"As you put the CPU board in the computer, it immediately springs to life.
-The lights start flashing, and the fans seem to startup."))
- (if (and (= obj1 obj-weight) (= obj2 obj-button))
- (dun-drop '("weight"))
- (if (= obj2 obj-jar) ;; Put something in jar
- (if (not (member obj1 (list obj-paper obj-diamond obj-emerald
- obj-license obj-coins obj-egg
- obj-nitric obj-glycerine)))
- (dun-mprincl "That will not fit in the jar.")
- (dun-remove-obj-from-inven obj1)
- (setq dun-jar (append dun-jar (list obj1)))
- (dun-mprincl "Done."))
- (if (= obj2 obj-chute) ;; Put something in chute
- (progn
- (dun-remove-obj-from-inven obj1)
- (dun-mprincl
-"You hear it slide down the chute and off into the distance.")
- (dun-put-objs-in-treas (list obj1)))
- (if (= obj2 obj-box) ;; Put key in key box
- (if (= obj1 obj-key)
- (progn
- (dun-mprincl
-"As you drop the key, the box begins to shake. Finally it explodes
-with a bang. The key seems to have vanished!")
- (dun-remove-obj-from-inven obj1)
- (dun-replace dun-room-objects computer-room (append
- (nth computer-room
- dun-room-objects)
- (list obj1)))
- (dun-remove-obj-from-room dun-current-room obj-box)
- (setq dun-key-level (1+ dun-key-level)))
- (dun-mprincl "You can't put that in the key box!"))
-
- (if (and (= obj1 obj-floppy) (= obj2 obj-pc))
- (progn
- (setq dun-floppy t)
- (dun-remove-obj-from-inven obj1)
- (dun-mprincl "Done."))
-
- (if (= obj2 obj-urinal) ;; Put object in urinal
- (progn
- (dun-remove-obj-from-inven obj1)
- (dun-replace dun-room-objects urinal (append
- (nth urinal dun-room-objects)
- (list obj1)))
- (dun-mprincl
- "You hear it plop down in some water below."))
- (if (= obj2 obj-mail)
- (dun-mprincl "The mail chute is locked.")
- (if (member obj1 dun-inventory)
- (dun-mprincl
-"I don't know how to combine those objects. Perhaps you should
-just try dropping it.")
- (dun-mprincl"You can't put that there.")))))))))))
-
-(defun dun-type (args)
- (if (not (= dun-current-room computer-room))
- (dun-mprincl "There is nothing here on which you could type.")
- (if (not dun-computer)
- (dun-mprincl
-"You type on the keyboard, but your characters do not even echo.")
- (dun-unix-interface))))
-
-;;; Various movement directions
-
-(defun dun-n (args)
- (dun-move north))
-
-(defun dun-s (args)
- (dun-move south))
-
-(defun dun-e (args)
- (dun-move east))
-
-(defun dun-w (args)
- (dun-move west))
-
-(defun dun-ne (args)
- (dun-move northeast))
-
-(defun dun-se (args)
- (dun-move southeast))
-
-(defun dun-nw (args)
- (dun-move northwest))
-
-(defun dun-sw (args)
- (dun-move southwest))
-
-(defun dun-up (args)
- (dun-move up))
-
-(defun dun-down (args)
- (dun-move down))
-
-(defun dun-in (args)
- (dun-move in))
-
-(defun dun-out (args)
- (dun-move out))
-
-(defun dun-go (args)
- (if (or (not (car args))
- (eq (dun-doverb dun-ignore dun-verblist (car args)
- (cdr (cdr args))) -1))
- (dun-mprinc "I don't understand where you want me to go.\n")))
-
-;;; Uses the dungeon-map to figure out where we are going. If the
-;;; requested direction yields 255, we know something special is
-;;; supposed to happen, or perhaps you can't go that way unless
-;;; certain conditions are met.
-
-(defun dun-move (dir)
- (if (and (not (member dun-current-room dun-light-rooms))
- (not (member obj-lamp dun-inventory)))
- (progn
- (dun-mprinc
-"You trip over a grue and fall into a pit and break every bone in your
-body.")
- (dun-die "a grue"))
- (let (newroom)
- (setq newroom (nth dir (nth dun-current-room dungeon-map)))
- (if (eq newroom -1)
- (dun-mprinc "You can't go that way.\n")
- (if (eq newroom 255)
- (dun-special-move dir)
- (setq room -1)
- (setq dun-lastdir dir)
- (if dun-inbus
- (progn
- (if (or (< newroom 58) (> newroom 83))
- (dun-mprincl "The bus cannot go this way.")
- (dun-mprincl
- "The bus lurches ahead and comes to a screeching halt.")
- (dun-remove-obj-from-room dun-current-room obj-bus)
- (setq dun-current-room newroom)
- (dun-replace dun-room-objects newroom
- (append (nth newroom dun-room-objects)
- (list obj-bus)))))
- (setq dun-current-room newroom)))))))
-
-;;; Movement in this direction causes something special to happen if the
-;;; right conditions exist. It may be that you can't go this way unless
-;;; you have a key, or a passage has been opened.
-
-;;; coding note: Each check of the current room is on the same 'if' level,
-;;; i.e. there aren't else's. If two rooms next to each other have
-;;; specials, and they are connected by specials, this could cause
-;;; a problem. Be careful when adding them to consider this, and
-;;; perhaps use else's.
-
-(defun dun-special-move (dir)
- (if (= dun-current-room building-front)
- (if (not (member obj-key dun-inventory))
- (dun-mprincl "You don't have a key that can open this door.")
- (setq dun-current-room old-building-hallway))
- (if (= dun-current-room north-end-of-cave-passage)
- (let (combo)
- (dun-mprincl
-"You must type a 3 digit combination code to enter this room.")
- (dun-mprinc "Enter it here: ")
- (setq combo (dun-read-line))
- (if (not dun-batch-mode)
- (dun-mprinc "\n"))
- (if (string= combo dun-combination)
- (setq dun-current-room gamma-computing-center)
- (dun-mprincl "Sorry, that combination is incorrect."))))
-
- (if (= dun-current-room bear-hangout)
- (if (member obj-bear (nth bear-hangout dun-room-objects))
- (progn
- (dun-mprinc
-"The bear is very annoyed that you would be so presumptuous as to try
-and walk right by it. He tells you so by tearing your head off.
-")
- (dun-die "a bear"))
- (dun-mprincl "You can't go that way.")))
-
- (if (= dun-current-room vermont-station)
- (progn
- (dun-mprincl
-"As you board the train it immediately leaves the station. It is a very
-bumpy ride. It is shaking from side to side, and up and down. You
-sit down in one of the chairs in order to be more comfortable.")
- (dun-mprincl
-"\nFinally the train comes to a sudden stop, and the doors open, and some
-force throws you out. The train speeds away.\n")
- (setq dun-current-room museum-station)))
-
- (if (= dun-current-room old-building-hallway)
- (if (and (member obj-key dun-inventory)
- (> dun-key-level 0))
- (setq dun-current-room meadow)
- (dun-mprincl "You don't have a key that can open this door.")))
-
- (if (and (= dun-current-room maze-button-room) (= dir northwest))
- (if (member obj-weight (nth maze-button-room dun-room-objects))
- (setq dun-current-room 18)
- (dun-mprincl "You can't go that way.")))
-
- (if (and (= dun-current-room maze-button-room) (= dir up))
- (if (member obj-weight (nth maze-button-room dun-room-objects))
- (dun-mprincl "You can't go that way.")
- (setq dun-current-room weight-room)))
-
- (if (= dun-current-room classroom)
- (dun-mprincl "The door is locked."))
-
- (if (or (= dun-current-room lakefront-north)
- (= dun-current-room lakefront-south))
- (dun-swim nil))
-
- (if (= dun-current-room reception-area)
- (if (not (= dun-sauna-level 3))
- (setq dun-current-room health-club-front)
- (dun-mprincl
-"As you exit the building, you notice some flames coming out of one of the
-windows. Suddenly, the building explodes in a huge ball of fire. The flames
-engulf you, and you burn to death.")
- (dun-die "burning")))
-
- (if (= dun-current-room red-room)
- (if (not (member obj-towel (nth red-room dun-room-objects)))
- (setq dun-current-room long-n-s-hallway)
- (dun-mprincl "You can't go that way.")))
-
- (if (and (> dir down) (> dun-current-room gamma-computing-center)
- (< dun-current-room museum-lobby))
- (if (not (member obj-bus (nth dun-current-room dun-room-objects)))
- (dun-mprincl "You can't go that way.")
- (if (= dir in)
- (if (member obj-license dun-inventory)
- (progn
- (dun-mprincl
- "You board the bus and get in the driver's seat.")
- (setq dun-nomail t)
- (setq dun-inbus t))
- (dun-mprincl "You are not licensed for this type of vehicle."))
- (dun-mprincl "You hop off the bus.")
- (setq dun-inbus nil)))
- (if (= dun-current-room fifth-oaktree-intersection)
- (if (not dun-inbus)
- (progn
- (dun-mprincl "You fall down the cliff and land on your head.")
- (dun-die "a cliff"))
- (dun-mprincl
-"The bus flies off the cliff, and plunges to the bottom, where it explodes.")
- (dun-die "a bus accident")))
- (if (= dun-current-room main-maple-intersection)
- (progn
- (if (not dun-inbus)
- (dun-mprincl "The gate will not open.")
- (dun-mprincl
-"As the bus approaches, the gate opens and you drive through.")
- (dun-remove-obj-from-room main-maple-intersection obj-bus)
- (dun-replace dun-room-objects museum-entrance
- (append (nth museum-entrance dun-room-objects)
- (list obj-bus)))
- (setq dun-current-room museum-entrance)))))
- (if (= dun-current-room cave-entrance)
- (progn
- (dun-mprincl
-"As you enter the room you hear a rumbling noise. You look back to see
-huge rocks sliding down from the ceiling, and blocking your way out.\n")
- (setq dun-current-room misty-room)))))
-
-(defun dun-long (args)
- (setq dun-mode "long"))
-
-(defun dun-turn (obj)
- (let (objnum direction)
- (when (setq objnum (dun-objnum-from-args-std obj))
- (if (not (or (member objnum (nth dun-current-room dun-room-objects))
- (member objnum (nth dun-current-room dun-room-silents))))
- (dun-mprincl "I don't see that here.")
- (if (not (= objnum obj-dial))
- (dun-mprincl "You can't turn that.")
- (setq direction (dun-firstword (cdr obj)))
- (if (or (not direction)
- (not (or (string= direction "clockwise")
- (string= direction "counterclockwise"))))
- (dun-mprincl "You must indicate clockwise or counterclockwise.")
- (if (string= direction "clockwise")
- (setq dun-sauna-level (+ dun-sauna-level 1))
- (setq dun-sauna-level (- dun-sauna-level 1)))
-
- (if (< dun-sauna-level 0)
- (progn
- (dun-mprincl
- "The dial will not turn further in that direction.")
- (setq dun-sauna-level 0))
- (dun-sauna-heat))))))))
-
-(defun dun-sauna-heat ()
- (if (= dun-sauna-level 0)
- (dun-mprincl
- "The temperature has returned to normal room temperature."))
- (if (= dun-sauna-level 1)
- (dun-mprincl "It is now luke warm in here. You begin to sweat."))
- (if (= dun-sauna-level 2)
- (dun-mprincl "It is pretty hot in here. It is still very comfortable."))
- (if (= dun-sauna-level 3)
- (progn
- (dun-mprincl
-"It is now very hot. There is something very refreshing about this.")
- (if (or (member obj-rms dun-inventory)
- (member obj-rms (nth dun-current-room dun-room-objects)))
- (progn
- (dun-mprincl
-"You notice the wax on your statuette beginning to melt, until it completely
-melts off. You are left with a beautiful diamond!")
- (if (member obj-rms dun-inventory)
- (progn
- (dun-remove-obj-from-inven obj-rms)
- (setq dun-inventory (append dun-inventory
- (list obj-diamond))))
- (dun-remove-obj-from-room dun-current-room obj-rms)
- (dun-replace dun-room-objects dun-current-room
- (append (nth dun-current-room dun-room-objects)
- (list obj-diamond))))))
- (if (or (member obj-floppy dun-inventory)
- (member obj-floppy (nth dun-current-room dun-room-objects)))
- (progn
- (dun-mprincl
-"You notice your floppy disk beginning to melt. As you grab for it, the
-disk bursts into flames, and disintegrates.")
- (if (member obj-floppy dun-inventory)
- (dun-remove-obj-from-inven obj-floppy)
- (dun-remove-obj-from-room dun-current-room obj-floppy))))))
-
- (if (= dun-sauna-level 4)
- (progn
- (dun-mprincl
-"As the dial clicks into place, you immediately burst into flames.")
- (dun-die "burning"))))
-
-(defun dun-press (obj)
- (let (objnum)
- (when (setq objnum (dun-objnum-from-args-std obj))
- (if (not (or (member objnum (nth dun-current-room dun-room-objects))
- (member objnum (nth dun-current-room dun-room-silents))))
- (dun-mprincl "I don't see that here.")
- (if (not (member objnum (list obj-button obj-switch)))
- (progn
- (dun-mprinc "You can't ")
- (dun-mprinc (car line-list))
- (dun-mprincl " that."))
- (if (= objnum obj-button)
- (dun-mprincl
-"As you press the button, you notice a passageway open up, but
-as you release it, the passageway closes."))
- (if (= objnum obj-switch)
- (if dun-black
- (progn
- (dun-mprincl "The button is now in the off position.")
- (setq dun-black nil))
- (dun-mprincl "The button is now in the on position.")
- (setq dun-black t))))))))
-
-(defun dun-swim (args)
- (if (not (member dun-current-room (list lakefront-north lakefront-south)))
- (dun-mprincl "I see no water!")
- (if (not (member obj-life dun-inventory))
- (progn
- (dun-mprincl
-"You dive in the water, and at first notice it is quite cold. You then
-start to get used to it as you realize that you never really learned how
-to swim.")
- (dun-die "drowning"))
- (if (= dun-current-room lakefront-north)
- (setq dun-current-room lakefront-south)
- (setq dun-current-room lakefront-north)))))
-
-
-(defun dun-score (args)
- (if (not dun-endgame)
- (let (total)
- (setq total (dun-reg-score))
- (dun-mprinc "You have scored ")
- (dun-mprinc total)
- (dun-mprincl " out of a possible 90 points.") total)
- (dun-mprinc "You have scored ")
- (dun-mprinc (dun-endgame-score))
- (dun-mprincl " endgame points out of a possible 110.")
- (if (= (dun-endgame-score) 110)
- (dun-mprincl
-"\n\nCongratulations. You have won. The wizard password is 'moby'"))))
-
-(defun dun-help (args)
- (dun-mprincl
-"Welcome to dunnet (2.0), by Ron Schnell (ronnie@media.mit.edu).
-Here is some useful information (read carefully because there are one
-or more clues in here):
-- If you have a key that can open a door, you do not need to explicitly
- open it. You may just use 'in' or walk in the direction of the door.
-
-- If you have a lamp, it is always lit.
-
-- You will not get any points until you manage to get treasures to a certain
- place. Simply finding the treasures is not good enough. There is more
- than one way to get a treasure to the special place. It is also
- important that the objects get to the special place *unharmed* and
- *untarnished*. You can tell if you have successfully transported the
- object by looking at your score, as it changes immediately. Note that
- an object can become harmed even after you have received points for it.
- If this happens, your score will decrease, and in many cases you can never
- get credit for it again.
-
-- You can save your game with the 'save' command, and use restore it
- with the 'restore' command.
-
-- There are no limits on lengths of object names.
-
-- Directions are: north,south,east,west,northeast,southeast,northwest,
- southwest,up,down,in,out.
-
-- These can be abbreviated: n,s,e,w,ne,se,nw,sw,u,d,in,out.
-
-- If you go down a hole in the floor without an aid such as a ladder,
- you probably won't be able to get back up the way you came, if at all.
-
-- To run this game in batch mode (no emacs window), use:
- emacs -batch -l dunnet
-
-If you have questions or comments, please contact ronnie@media.mit.edu."))
-
-(defun dun-flush (args)
- (if (not (= dun-current-room bathroom))
- (dun-mprincl "I see nothing to flush.")
- (dun-mprincl "Whoooosh!!")
- (dun-put-objs-in-treas (nth urinal dun-room-objects))
- (dun-replace dun-room-objects urinal nil)))
-
-(defun dun-urinate (args)
- (if (not (= dun-current-room bathroom))
- (dun-mprincl "You can't do that here, don't even bother trying.")
- (if (not dun-gottago)
- (dun-mprincl "I'm afraid you don't have to go now.")
- (dun-mprincl "That was refreshing.")
- (setq dun-gottago nil)
- (dun-replace dun-room-objects urinal (append
- (nth urinal dun-room-objects)
- (list obj-URINE))))))
-
-
-(defun dun-sleep (args)
- (if (not (= dun-current-room bedroom))
- (dun-mprincl
-"You try to go to sleep while standing up here, but can't seem to do it.")
- (setq dun-gottago t)
- (dun-mprincl
-"As soon as you start to doze off you begin dreaming. You see images of
-workers digging caves, slaving in the humid heat. Then you see yourself
-as one of these workers. While no one is looking, you leave the group
-and walk into a room. The room is bare except for a horseshoe
-shaped piece of stone in the center. You see yourself digging a hole in
-the ground, then putting some kind of treasure in it, and filling the hole
-with dirt again. After this, you immediately wake up.")))
-
-(defun dun-break (obj)
- (let (objnum)
- (if (not (member obj-axe dun-inventory))
- (dun-mprincl "You have nothing you can use to break things.")
- (when (setq objnum (dun-objnum-from-args-std obj))
- (if (member objnum dun-inventory)
- (progn
- (dun-mprincl
-"You take the object in your hands and swing the axe. Unfortunately, you miss
-the object and slice off your hand. You bleed to death.")
- (dun-die "an axe"))
- (if (not (or (member objnum (nth dun-current-room dun-room-objects))
- (member objnum
- (nth dun-current-room dun-room-silents))))
- (dun-mprincl "I don't see that here.")
- (if (= objnum obj-cable)
- (progn
- (dun-mprincl
-"As you break the ethernet cable, everything starts to blur. You collapse
-for a moment, then straighten yourself up.
-")
- (dun-replace dun-room-objects gamma-computing-center
- (append
- (nth gamma-computing-center dun-room-objects)
- dun-inventory))
- (if (member obj-key dun-inventory)
- (progn
- (setq dun-inventory (list obj-key))
- (dun-remove-obj-from-room
- gamma-computing-center obj-key))
- (setq dun-inventory nil))
- (setq dun-current-room computer-room)
- (setq dun-ethernet nil)
- (dun-mprincl "Connection closed.")
- (dun-unix-interface))
- (if (< objnum 0)
- (progn
- (dun-mprincl "Your axe shatters into a million pieces.")
- (dun-remove-obj-from-inven obj-axe))
- (dun-mprincl "Your axe breaks it into a million pieces.")
- (dun-remove-obj-from-room dun-current-room objnum)))))))))
-
-(defun dun-drive (args)
- (if (not dun-inbus)
- (dun-mprincl "You cannot drive when you aren't in a vehicle.")
- (dun-mprincl "To drive while you are in the bus, just give a direction.")))
-
-(defun dun-superb (args)
- (setq dun-mode 'dun-superb))
-
-(defun dun-reg-score ()
- (let (total)
- (setq total 0)
- (dolist (x (nth treasure-room dun-room-objects))
- (setq total (+ total (nth x dun-object-pts))))
- (if (member obj-URINE (nth treasure-room dun-room-objects))
- (setq total 0)) total))
-
-(defun dun-endgame-score ()
- (let (total)
- (setq total 0)
- (dolist (x (nth endgame-treasure-room dun-room-objects))
- (setq total (+ total (nth x dun-object-pts)))) total))
-
-(defun dun-answer (args)
- (if (not dun-correct-answer)
- (dun-mprincl "I don't believe anyone asked you anything.")
- (setq args (car args))
- (if (not args)
- (dun-mprincl "You must give the answer on the same line.")
- (if (dun-members args dun-correct-answer)
- (progn
- (dun-mprincl "Correct.")
- (if (= dun-lastdir 0)
- (setq dun-current-room (1+ dun-current-room))
- (setq dun-current-room (- dun-current-room 1)))
- (setq dun-correct-answer nil))
- (dun-mprincl "That answer is incorrect.")))))
-
-(defun dun-endgame-question ()
-(if (not dun-endgame-questions)
- (progn
- (dun-mprincl "Your question is:")
- (dun-mprincl "No more questions, just do 'answer foo'.")
- (setq dun-correct-answer '("foo")))
- (let (which i newques)
- (setq i 0)
- (setq newques nil)
- (setq which (random (length dun-endgame-questions)))
- (dun-mprincl "Your question is:")
- (dun-mprincl (setq dun-endgame-question (car
- (nth which
- dun-endgame-questions))))
- (setq dun-correct-answer (cdr (nth which dun-endgame-questions)))
- (while (< i which)
- (setq newques (append newques (list (nth i dun-endgame-questions))))
- (setq i (1+ i)))
- (setq i (1+ which))
- (while (< i (length dun-endgame-questions))
- (setq newques (append newques (list (nth i dun-endgame-questions))))
- (setq i (1+ i)))
- (setq dun-endgame-questions newques))))
-
-(defun dun-power (args)
- (if (not (= dun-current-room pc-area))
- (dun-mprincl "That operation is not applicable here.")
- (if (not dun-floppy)
- (dun-dos-no-disk)
- (dun-dos-interface))))
-
-(defun dun-feed (args)
- (let (objnum)
- (when (setq objnum (dun-objnum-from-args-std args))
- (if (and (= objnum obj-bear)
- (member obj-bear (nth dun-current-room dun-room-objects)))
- (progn
- (if (not (member obj-food dun-inventory))
- (dun-mprincl "You have nothing with which to feed it.")
- (dun-drop '("food"))))
- (if (not (or (member objnum (nth dun-current-room dun-room-objects))
- (member objnum dun-inventory)
- (member objnum (nth dun-current-room dun-room-silents))))
- (dun-mprincl "I don't see that here.")
- (dun-mprincl "You cannot feed that."))))))
-
-
-;;;;
-;;;; This section defines various utility functions used
-;;;; by dunnet.
-;;;;
-
-
-;;; Function which takes a verb and a list of other words. Calls proper
-;;; function associated with the verb, and passes along the other words.
-
-(defun dun-doverb (dun-ignore dun-verblist verb rest)
- (if (not verb)
- nil
- (if (member (intern verb) dun-ignore)
- (if (not (car rest)) -1
- (dun-doverb dun-ignore dun-verblist (car rest) (cdr rest)))
- (if (not (cdr (assq (intern verb) dun-verblist))) -1
- (setq dun-numcmds (1+ dun-numcmds))
- (eval (list (cdr (assq (intern verb) dun-verblist)) (quote rest)))))))
-
-
-;;; Function to take a string and change it into a list of lowercase words.
-
-(defun dun-listify-string (strin)
- (let (pos ret-list end-pos)
- (setq pos 0)
- (setq ret-list nil)
- (while (setq end-pos (string-match "[ ,:;]" (substring strin pos)))
- (setq end-pos (+ end-pos pos))
- (if (not (= end-pos pos))
- (setq ret-list (append ret-list (list
- (downcase
- (substring strin pos end-pos))))))
- (setq pos (+ end-pos 1))) ret-list))
-
-(defun dun-listify-string2 (strin)
- (let (pos ret-list end-pos)
- (setq pos 0)
- (setq ret-list nil)
- (while (setq end-pos (string-match " " (substring strin pos)))
- (setq end-pos (+ end-pos pos))
- (if (not (= end-pos pos))
- (setq ret-list (append ret-list (list
- (downcase
- (substring strin pos end-pos))))))
- (setq pos (+ end-pos 1))) ret-list))
-
-(defun dun-replace (list n number)
- (rplaca (nthcdr n list) number))
-
-
-;;; Get the first non-ignored word from a list.
-
-(defun dun-firstword (list)
- (if (not (car list))
- nil
- (while (and list (member (intern (car list)) dun-ignore))
- (setq list (cdr list)))
- (car list)))
-
-(defun dun-firstwordl (list)
- (if (not (car list))
- nil
- (while (and list (member (intern (car list)) dun-ignore))
- (setq list (cdr list)))
- list))
-
-;;; parse a line passed in as a string Call the proper verb with the
-;;; rest of the line passed in as a list.
-
-(defun dun-vparse (dun-ignore dun-verblist line)
- (dun-mprinc "\n")
- (setq line-list (dun-listify-string (concat line " ")))
- (dun-doverb dun-ignore dun-verblist (car line-list) (cdr line-list)))
-
-(defun dun-parse2 (dun-ignore dun-verblist line)
- (dun-mprinc "\n")
- (setq line-list (dun-listify-string2 (concat line " ")))
- (dun-doverb dun-ignore dun-verblist (car line-list) (cdr line-list)))
-
-;;; Read a line, in window mode
-
-(defun dun-read-line ()
- (let (line)
- (setq line (read-string ""))
- (dun-mprinc line) line))
-
-;;; Insert something into the window buffer
-
-(defun dun-minsert (string)
- (if (stringp string)
- (insert string)
- (insert (prin1-to-string string))))
-
-;;; Print something out, in window mode
-
-(defun dun-mprinc (string)
- (if (stringp string)
- (insert string)
- (insert (prin1-to-string string))))
-
-;;; In window mode, keep screen from jumping by keeping last line at
-;;; the bottom of the screen.
-
-(defun dun-fix-screen ()
- (interactive)
- (forward-line (- 0 (- (window-height) 2 )))
- (set-window-start (selected-window) (point))
- (end-of-buffer))
-
-;;; Insert something into the buffer, followed by newline.
-
-(defun dun-minsertl (string)
- (dun-minsert string)
- (dun-minsert "\n"))
-
-;;; Print something, followed by a newline.
-
-(defun dun-mprincl (string)
- (dun-mprinc string)
- (dun-mprinc "\n"))
-
-;;; Function which will get an object number given the list of
-;;; words in the command, except for the verb.
-
-(defun dun-objnum-from-args (obj)
- (let (objnum)
- (setq obj (dun-firstword obj))
- (if (not obj)
- obj-special
- (setq objnum (cdr (assq (intern obj) dun-objnames))))))
-
-(defun dun-objnum-from-args-std (obj)
- (let (result)
- (if (eq (setq result (dun-objnum-from-args obj)) obj-special)
- (dun-mprincl "You must supply an object."))
- (if (eq result nil)
- (dun-mprincl "I don't know what that is."))
- (if (eq result obj-special)
- nil
- result)))
-
-;;; Take a short room description, and change spaces and slashes to dashes.
-
-(defun dun-space-to-hyphen (string)
- (let (space)
- (if (setq space (string-match "[ /]" string))
- (progn
- (setq string (concat (substring string 0 space) "-"
- (substring string (1+ space))))
- (dun-space-to-hyphen string))
- string)))
-
-;;; Given a unix style pathname, build a list of path components (recursive)
-
-(defun dun-get-path (dirstring startlist)
- (let (slash pos)
- (if (= (length dirstring) 0)
- startlist
- (if (string= (substring dirstring 0 1) "/")
- (dun-get-path (substring dirstring 1) (append startlist (list "/")))
- (if (not (setq slash (string-match "/" dirstring)))
- (append startlist (list dirstring))
- (dun-get-path (substring dirstring (1+ slash))
- (append startlist
- (list (substring dirstring 0 slash)))))))))
-
-
-;;; Is a string a member of a string list?
-
-(defun dun-members (string string-list)
- (let (found)
- (setq found nil)
- (dolist (x string-list)
- (if (string= x string)
- (setq found t))) found))
-
-;;; Function to put objects in the treasure room. Also prints current
-;;; score to let user know he has scored.
-
-(defun dun-put-objs-in-treas (objlist)
- (let (oscore newscore)
- (setq oscore (dun-reg-score))
- (dun-replace dun-room-objects 0 (append (nth 0 dun-room-objects) objlist))
- (setq newscore (dun-reg-score))
- (if (not (= oscore newscore))
- (dun-score nil))))
-
-;;; Load an encrypted file, and eval it.
-
-(defun dun-load-d (filename)
- (let (old-buffer result)
- (setq result t)
- (setq old-buffer (current-buffer))
- (switch-to-buffer (get-buffer-create "*loadc*"))
- (erase-buffer)
- (condition-case nil
- (insert-file-contents filename)
- (error (setq result nil)))
- (unless (not result)
- (condition-case nil
- (dun-rot13)
- (error (yank)))
- (eval-current-buffer)
- (kill-buffer (current-buffer))
- (switch-to-buffer old-buffer))
- result))
-
-;;; Functions to remove an object either from a room, or from inventory.
-
-(defun dun-remove-obj-from-room (room objnum)
- (let (newroom)
- (setq newroom nil)
- (dolist (x (nth room dun-room-objects))
- (if (not (= x objnum))
- (setq newroom (append newroom (list x)))))
- (rplaca (nthcdr room dun-room-objects) newroom)))
-
-(defun dun-remove-obj-from-inven (objnum)
- (let (new-inven)
- (setq new-inven nil)
- (dolist (x dun-inventory)
- (if (not (= x objnum))
- (setq new-inven (append new-inven (list x)))))
- (setq dun-inventory new-inven)))
-
-
-(let ((i 0) (lower "abcdefghijklmnopqrstuvwxyz") upper)
- (setq dun-translate-table (make-vector 256 0))
- (while (< i 256)
- (aset dun-translate-table i i)
- (setq i (1+ i)))
- (setq lower (concat lower lower))
- (setq upper (upcase lower))
- (setq i 0)
- (while (< i 26)
- (aset dun-translate-table (+ ?a i) (aref lower (+ i 13)))
- (aset dun-translate-table (+ ?A i) (aref upper (+ i 13)))
- (setq i (1+ i))))
-
-(defun dun-rot13 ()
- (let (str len (i 0))
- (setq str (buffer-substring (point-min) (point-max)))
- (setq len (length str))
- (while (< i len)
- (aset str i (aref dun-translate-table (aref str i)))
- (setq i (1+ i)))
- (erase-buffer)
- (insert str)))
-
-;;;;
-;;;; This section defines the globals that are used in dunnet.
-;;;;
-;;;; IMPORTANT
-;;;; All globals which can change must be saved from 'save-game. Add
-;;;; all new globals to bottom of file.
-
-(setq dun-visited '(27))
-(setq dun-current-room 1)
-(setq dun-exitf nil)
-(setq dun-badcd nil)
-(defvar dungeon-mode-map nil)
-(setq dungeon-mode-map (make-sparse-keymap))
-(define-key dungeon-mode-map "\r" 'dun-parse)
-(defvar dungeon-batch-map (make-keymap))
-(if (string= (substring emacs-version 0 2) "18")
- (let (n)
- (setq n 32)
- (while (< 0 (setq n (- n 1)))
- (aset dungeon-batch-map n 'dungeon-nil)))
- (let (n)
- (setq n 32)
- (while (< 0 (setq n (- n 1)))
- (aset (car (cdr dungeon-batch-map)) n 'dungeon-nil))))
-(define-key dungeon-batch-map "\r" 'exit-minibuffer)
-(define-key dungeon-batch-map "\n" 'exit-minibuffer)
-(setq dun-computer nil)
-(setq dun-floppy nil)
-(setq dun-key-level 0)
-(setq dun-hole nil)
-(setq dun-correct-answer nil)
-(setq dun-lastdir 0)
-(setq dun-numsaves 0)
-(setq dun-jar nil)
-(setq dun-dead nil)
-(setq room 0)
-(setq dun-numcmds 0)
-(setq dun-wizard nil)
-(setq dun-endgame-question nil)
-(setq dun-logged-in nil)
-(setq dungeon-mode 'dungeon)
-(setq dun-unix-verbs '((ls . dun-ls) (ftp . dun-ftp) (echo . dun-echo)
- (exit . dun-uexit) (cd . dun-cd) (pwd . dun-pwd)
- (rlogin . dun-rlogin) (uncompress . dun-uncompress)
- (cat . dun-cat) (zippy . dun-zippy)))
-
-(setq dun-dos-verbs '((dir . dun-dos-dir) (type . dun-dos-type)
- (exit . dun-dos-exit) (command . dun-dos-spawn)
- (b: . dun-dos-invd) (c: . dun-dos-invd)
- (a: . dun-dos-nil)))
-
-
-(setq dun-batch-mode nil)
-
-(setq dun-cdpath "/usr/toukmond")
-(setq dun-cdroom -10)
-(setq dun-uncompressed nil)
-(setq dun-ethernet t)
-(setq dun-restricted
- '(dun-room-objects dungeon-map dun-rooms
- dun-room-silents dun-combination))
-(setq dun-ftptype 'ascii)
-(setq dun-endgame nil)
-(setq dun-gottago t)
-(setq dun-black nil)
-
-(setq dun-rooms '(
- (
-"You are in the treasure room. A door leads out to the north."
- "Treasure room"
- )
- (
-"You are at a dead end of a dirt road. The road goes to the east.
-In the distance you can see that it will eventually fork off. The
-trees here are very tall royal palms, and they are spaced equidistant
-from each other."
- "Dead end"
- )
- (
-"You are on the continuation of a dirt road. There are more trees on
-both sides of you. The road continues to the east and west."
- "E/W Dirt road"
- )
- (
-"You are at a fork of two passages, one to the northeast, and one to the
-southeast. The ground here seems very soft. You can also go back west."
- "Fork"
- )
- (
-"You are on a northeast/southwest road."
- "NE/SW road"
- )
- (
-"You are at the end of the road. There is a building in front of you
-to the northeast, and the road leads back to the southwest."
- "Building front"
- )
- (
-"You are on a southeast/northwest road."
- "SE/NW road"
- )
- (
-"You are standing at the end of a road. A passage leads back to the
-northwest."
- "Bear hangout"
- )
- (
-"You are in the hallway of an old building. There are rooms to the east
-and west, and doors leading out to the north and south."
- "Old Building hallway"
- )
- (
-"You are in a mailroom. There are many bins where the mail is usually
-kept. The exit is to the west."
- "Mailroom"
- )
- (
-"You are in a computer room. It seems like most of the equipment has
-been removed. There is a VAX 11/780 in front of you, however, with
-one of the cabinets wide open. A sign on the front of the machine
-says: This VAX is named 'pokey'. To type on the console, use the
-'type' command. The exit is to the east."
- "Computer room"
- )
- (
-"You are in a meadow in the back of an old building. A small path leads
-to the west, and a door leads to the south."
- "Meadow"
- )
- (
-"You are in a round, stone room with a door to the east. There
-is a sign on the wall that reads: 'receiving room'."
- "Receiving room"
- )
- (
-"You are at the south end of a hallway that leads to the north. There
-are rooms to the east and west."
- "Northbound Hallway"
- )
- (
-"You are in a sauna. There is nothing in the room except for a dial
-on the wall. A door leads out to west."
- "Sauna"
- )
- (
-"You are at the end of a north/south hallway. You can go back to the south,
-or off to a room to the east."
- "End of N/S Hallway"
- )
- (
-"You are in an old weight room. All of the equipment is either destroyed
-or completely broken. There is a door out to the west, and there is a ladder
-leading down a hole in the floor."
- "Weight room" ;16
- )
- (
-"You are in a maze of twisty little passages, all alike.
-There is a button on the ground here."
- "Maze button room"
- )
- (
-"You are in a maze of little twisty passages, all alike."
- "Maze"
- )
- (
-"You are in a maze of thirsty little passages, all alike."
- "Maze" ;19
- )
- (
-"You are in a maze of twenty little passages, all alike."
- "Maze"
- )
- (
-"You are in a daze of twisty little passages, all alike."
- "Maze" ;21
- )
- (
-"You are in a maze of twisty little cabbages, all alike."
- "Maze" ;22
- )
- (
-"You are in a reception area for a health and fitness center. The place
-appears to have been recently ransacked, and nothing is left. There is
-a door out to the south, and a crawlspace to the southeast."
- "Reception area"
- )
- (
-"You are outside a large building to the north which used to be a health
-and fitness center. A road leads to the south."
- "Health Club front"
- )
- (
-"You are at the north side of a lake. On the other side you can see
-a road which leads to a cave. The water appears very deep."
- "Lakefront North"
- )
- (
-"You are at the south side of a lake. A road goes to the south."
- "Lakefront South"
- )
- (
-"You are in a well-hidden area off to the side of a road. Back to the
-northeast through the brush you can see the bear hangout."
- "Hidden area"
- )
- (
-"The entrance to a cave is to the south. To the north, a road leads
-towards a deep lake. On the ground nearby there is a chute, with a sign
-that says 'put treasures here for points'."
- "Cave Entrance" ;28
- )
- (
-"You are in a misty, humid room carved into a mountain.
-To the north is the remains of a rockslide. To the east, a small
-passage leads away into the darkness." ;29
- "Misty Room"
- )
- (
-"You are in an east/west passageway. The walls here are made of
-multicolored rock and are quite beautiful."
- "Cave E/W passage" ;30
- )
- (
-"You are at the junction of two passages. One goes north/south, and
-the other goes west."
- "N/S/W Junction" ;31
- )
- (
-"You are at the north end of a north/south passageway. There are stairs
-leading down from here. There is also a door leading west."
- "North end of cave passage" ;32
- )
- (
-"You are at the south end of a north/south passageway. There is a hole
-in the floor here, into which you could probably fit."
- "South end of cave passage" ;33
- )
- (
-"You are in what appears to be a worker's bedroom. There is a queen-
-sized bed in the middle of the room, and a painting hanging on the
-wall. A door leads to another room to the south, and stairways
-lead up and down."
- "Bedroom" ;34
- )
- (
-"You are in a bathroom built for workers in the cave. There is a
-urinal hanging on the wall, and some exposed pipes on the opposite
-wall where a sink used to be. To the north is a bedroom."
- "Bathroom" ;35
- )
- (
-"This is a marker for the urinal. User will not see this, but it
-is a room that can contain objects."
- "Urinal" ;36
- )
- (
-"You are at the northeast end of a northeast/southwest passageway.
-Stairs lead up out of sight."
- "Ne end of ne/sw cave passage" ;37
- )
- (
-"You are at the junction of northeast/southwest and east/west passages."
- "Ne/sw-e/w junction" ;38
- )
- (
-"You are at the southwest end of a northeast/southwest passageway."
- "Sw end of ne/sw cave passage" ;39
- )
- (
-"You are at the east end of an e/w passage. There are stairs leading up
-to a room above."
- "East end of e/w cave passage" ;40
- )
- (
-"You are at the west end of an e/w passage. There is a hole on the ground
-which leads down out of sight."
- "West end of e/w cave passage" ;41
- )
- (
-"You are in a room which is bare, except for a horseshoe shaped boulder
-in the center. Stairs lead down from here." ;42
- "Horseshoe boulder room"
- )
- (
-"You are in a room which is completely empty. Doors lead out to the north
-and east."
- "Empty room" ;43
- )
- (
-"You are in an empty room. Interestingly enough, the stones in this
-room are painted blue. Doors lead out to the east and south." ;44
- "Blue room"
- )
- (
-"You are in an empty room. Interestingly enough, the stones in this
-room are painted yellow. Doors lead out to the south and west." ;45
- "Yellow room"
- )
- (
-"You are in an empty room. Interestingly enough, the stones in this room
-are painted red. Doors lead out to the west and north."
- "Red room" ;46
- )
- (
-"You are in the middle of a long north/south hallway." ;47
- "Long n/s hallway"
- )
- (
-"You are 3/4 of the way towards the north end of a long north/south hallway."
- "3/4 north" ;48
- )
- (
-"You are at the north end of a long north/south hallway. There are stairs
-leading upwards."
- "North end of long hallway" ;49
- )
- (
-"You are 3/4 of the way towards the south end of a long north/south hallway."
- "3/4 south" ;50
- )
- (
-"You are at the south end of a long north/south hallway. There is a hole
-to the south."
- "South end of long hallway" ;51
- )
- (
-"You are at a landing in a stairwell which continues up and down."
- "Stair landing" ;52
- )
- (
-"You are at the continuation of an up/down staircase."
- "Up/down staircase" ;53
- )
- (
-"You are at the top of a staircase leading down. A crawlway leads off
-to the northeast."
- "Top of staircase." ;54
- )
- (
-"You are in a crawlway that leads northeast or southwest."
- "Ne crawlway" ;55
- )
- (
-"You are in a small crawlspace. There is a hole in the ground here, and
-a small passage back to the southwest."
- "Small crawlspace" ;56
- )
- (
-"You are in the Gamma Computing Center. An IBM 3090/600s is whirring
-away in here. There is an ethernet cable coming out of one of the units,
-and going through the ceiling. There is no console here on which you
-could type."
- "Gamma computing center" ;57
- )
- (
-"You are near the remains of a post office. There is a mail drop on the
-face of the building, but you cannot see where it leads. A path leads
-back to the east, and a road leads to the north."
- "Post office" ;58
- )
- (
-"You are at the intersection of Main Street and Maple Ave. Main street
-runs north and south, and Maple Ave runs east off into the distance.
-If you look north and east you can see many intersections, but all of
-the buildings that used to stand here are gone. Nothing remains except
-street signs.
-There is a road to the northwest leading to a gate that guards a building."
- "Main-Maple intersection" ;59
- )
- (
-"You are at the intersection of Main Street and the west end of Oaktree Ave."
- "Main-Oaktree intersection" ;60
- )
- (
-"You are at the intersection of Main Street and the west end of Vermont Ave."
- "Main-Vermont intersection" ;61
- )
- (
-"You are at the north end of Main Street at the west end of Sycamore Ave." ;62
- "Main-Sycamore intersection"
- )
- (
-"You are at the south end of First Street at Maple Ave." ;63
- "First-Maple intersection"
- )
- (
-"You are at the intersection of First Street and Oaktree Ave." ;64
- "First-Oaktree intersection"
- )
- (
-"You are at the intersection of First Street and Vermont Ave." ;65
- "First-Vermont intersection"
- )
- (
-"You are at the north end of First Street at Sycamore Ave." ;66
- "First-Sycamore intersection"
- )
- (
-"You are at the south end of Second Street at Maple Ave." ;67
- "Second-Maple intersection"
- )
- (
-"You are at the intersection of Second Street and Oaktree Ave." ;68
- "Second-Oaktree intersection"
- )
- (
-"You are at the intersection of Second Street and Vermont Ave." ;69
- "Second-Vermont intersection"
- )
- (
-"You are at the north end of Second Street at Sycamore Ave." ;70
- "Second-Sycamore intersection"
- )
- (
-"You are at the south end of Third Street at Maple Ave." ;71
- "Third-Maple intersection"
- )
- (
-"You are at the intersection of Third Street and Oaktree Ave." ;72
- "Third-Oaktree intersection"
- )
- (
-"You are at the intersection of Third Street and Vermont Ave." ;73
- "Third-Vermont intersection"
- )
- (
-"You are at the north end of Third Street at Sycamore Ave." ;74
- "Third-Sycamore intersection"
- )
- (
-"You are at the south end of Fourth Street at Maple Ave." ;75
- "Fourth-Maple intersection"
- )
- (
-"You are at the intersection of Fourth Street and Oaktree Ave." ;76
- "Fourth-Oaktree intersection"
- )
- (
-"You are at the intersection of Fourth Street and Vermont Ave." ;77
- "Fourth-Vermont intersection"
- )
- (
-"You are at the north end of Fourth Street at Sycamore Ave." ;78
- "Fourth-Sycamore intersection"
- )
- (
-"You are at the south end of Fifth Street at the east end of Maple Ave." ;79
- "Fifth-Maple intersection"
- )
- (
-"You are at the intersection of Fifth Street and the east end of Oaktree Ave.
-There is a cliff off to the east."
- "Fifth-Oaktree intersection" ;80
- )
- (
-"You are at the intersection of Fifth Street and the east end of Vermont Ave."
- "Fifth-Vermont intersection" ;81
- )
- (
-"You are at the north end of Fifth Street and the east end of Sycamore Ave."
- "Fifth-Sycamore intersection" ;82
- )
- (
-"You are in front of the Museum of Natural History. A door leads into
-the building to the north, and a road leads to the southeast."
- "Museum entrance" ;83
- )
- (
-"You are in the main lobby for the Museum of Natural History. In the center
-of the room is the huge skeleton of a dinosaur. Doors lead out to the
-south and east."
- "Museum lobby" ;84
- )
- (
-"You are in the geological display. All of the objects that used to
-be on display are missing. There are rooms to the east, west, and
-north."
- "Geological display" ;85
- )
- (
-"You are in the marine life area. The room is filled with fish tanks,
-which are filled with dead fish that have apparently died due to
-starvation. Doors lead out to the south and east."
- "Marine life area" ;86
- )
- (
-"You are in some sort of maintenance room for the museum. There is a
-switch on the wall labeled 'BL'. There are doors to the west and north."
- "Maintenance room" ;87
- )
- (
-"You are in a classroom where school children were taught about natural
-history. On the blackboard is written, 'No children allowed downstairs.'
-There is a door to the east with an 'exit' sign on it. There is another
-door to the west."
- "Classroom" ;88
- )
- (
-"You are at the Vermont St. subway station. A train is sitting here waiting."
- "Vermont station" ;89
- )
- (
-"You are at the Museum subway stop. A passage leads off to the north."
- "Museum station" ;90
- )
- (
-"You are in a north/south tunnel."
- "N/S tunnel" ;91
- )
- (
-"You are at the north end of a north/south tunnel. Stairs lead up and
-down from here. There is a garbage disposal here."
- "North end of n/s tunnel" ;92
- )
- (
-"You are at the top of some stairs near the subway station. There is
-a door to the west."
- "Top of subway stairs" ;93
- )
- (
-"You are at the bottom of some stairs near the subway station. There is
-a room to the northeast."
- "Bottom of subway stairs" ;94
- )
- (
-"You are in another computer room. There is a computer in here larger
-than you have ever seen. It has no manufacturers name on it, but it
-does have a sign that says: This machine's name is 'endgame'. The
-exit is to the southwest. There is no console here on which you could
-type."
- "Endgame computer room" ;95
- )
- (
-"You are in a north/south hallway."
- "Endgame n/s hallway" ;96
- )
- (
-"You have reached a question room. You must answer a question correctly in
-order to get by. Use the 'answer' command to answer the question."
- "Question room 1" ;97
- )
- (
-"You are in a north/south hallway."
- "Endgame n/s hallway" ;98
- )
- (
-"You are in a second question room."
- "Question room 2" ;99
- )
- (
-"You are in a north/south hallway."
- "Endgame n/s hallway" ;100
- )
- (
-"You are in a third question room."
- "Question room 3" ;101
- )
- (
-"You are in the endgame treasure room. A door leads out to the north, and
-a hallway leads to the south."
- "Endgame treasure room" ;102
- )
- (
-"You are in the winner's room. A door leads back to the south."
- "Winner's room" ;103
- )
- (
-"You have reached a dead end. There is a PC on the floor here. Above
-it is a sign that reads:
- Type the 'reset' command to type on the PC.
-A hole leads north."
- "PC area" ;104
- )
-))
-
-(setq dun-light-rooms '(0 1 2 3 4 5 6 7 8 9 10 11 12 13 24 25 26 27 28 58 59
- 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
- 77 78 79 80 81 82 83))
-
-(setq dun-verblist '((die . dun-die) (ne . dun-ne) (north . dun-n)
- (south . dun-s) (east . dun-e) (west . dun-w)
- (u . dun-up) (d . dun-down) (i . dun-inven)
- (inventory . dun-inven) (look . dun-examine) (n . dun-n)
- (s . dun-s) (e . dun-e) (w . dun-w) (se . dun-se)
- (nw . dun-nw) (sw . dun-sw) (up . dun-up)
- (down . dun-down) (in . dun-in) (out . dun-out)
- (go . dun-go) (drop . dun-drop) (southeast . dun-se)
- (southwest . dun-sw) (northeast . dun-ne)
- (northwest . dun-nw) (save . dun-save-game)
- (restore . dun-restore) (long . dun-long) (dig . dun-dig)
- (shake . dun-shake) (wave . dun-shake)
- (examine . dun-examine) (describe . dun-examine)
- (climb . dun-climb) (eat . dun-eat) (put . dun-put)
- (type . dun-type) (insert . dun-put)
- (score . dun-score) (help . dun-help) (quit . dun-quit)
- (read . dun-examine) (verbose . dun-long)
- (urinate . dun-urinate)
- (flush . dun-flush) (sleep . dun-sleep) (lie . dun-sleep)
- (x . dun-examine) (break . dun-break) (drive . dun-drive)
- (board . dun-in) (enter . dun-in) (turn . dun-turn)
- (press . dun-press) (push . dun-press) (swim . dun-swim)
- (on . dun-in) (off . dun-out) (chop . dun-break)
- (switch . dun-press) (cut . dun-break) (exit . dun-out)
- (leave . dun-out) (reset . dun-power) (flick . dun-press)
- (superb . dun-superb) (answer . dun-answer)
- (throw . dun-drop) (l . dun-examine) (take . dun-take)
- (get . dun-take) (feed . dun-feed)))
-
-(setq dun-inbus nil)
-(setq dun-nomail nil)
-(setq dun-ignore '(the to at))
-(setq dun-mode 'moby)
-(setq dun-sauna-level 0)
-
-(defconst north 0)
-(defconst south 1)
-(defconst east 2)
-(defconst west 3)
-(defconst northeast 4)
-(defconst southeast 5)
-(defconst northwest 6)
-(defconst southwest 7)
-(defconst up 8)
-(defconst down 9)
-(defconst in 10)
-(defconst out 11)
-
-(setq dungeon-map '(
-; no so ea we ne se nw sw up do in ot
- ( 96 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;0
- ( -1 -1 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;1
- ( -1 -1 3 1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;2
- ( -1 -1 -1 2 4 6 -1 -1 -1 -1 -1 -1 ) ;3
- ( -1 -1 -1 -1 5 -1 -1 3 -1 -1 -1 -1 ) ;4
- ( -1 -1 -1 -1 255 -1 -1 4 -1 -1 255 -1 ) ;5
- ( -1 -1 -1 -1 -1 7 3 -1 -1 -1 -1 -1 ) ;6
- ( -1 -1 -1 -1 -1 255 6 27 -1 -1 -1 -1 ) ;7
- ( 255 5 9 10 -1 -1 -1 5 -1 -1 -1 5 ) ;8
- ( -1 -1 -1 8 -1 -1 -1 -1 -1 -1 -1 -1 ) ;9
- ( -1 -1 8 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;10
- ( -1 8 -1 58 -1 -1 -1 -1 -1 -1 -1 -1 ) ;11
- ( -1 -1 13 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;12
- ( 15 -1 14 12 -1 -1 -1 -1 -1 -1 -1 -1 ) ;13
- ( -1 -1 -1 13 -1 -1 -1 -1 -1 -1 -1 -1 ) ;14
- ( -1 13 16 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;15
- ( -1 -1 -1 15 -1 -1 -1 -1 -1 17 16 -1 ) ;16
- ( -1 -1 17 17 17 17 255 17 255 17 -1 -1 ) ;17
- ( 18 18 18 18 18 -1 18 18 19 18 -1 -1 ) ;18
- ( -1 18 18 19 19 20 19 19 -1 18 -1 -1 ) ;19
- ( -1 -1 -1 18 -1 -1 -1 -1 -1 21 -1 -1 ) ;20
- ( -1 -1 -1 -1 -1 20 22 -1 -1 -1 -1 -1 ) ;21
- ( 18 18 18 18 16 18 23 18 18 18 18 18 ) ;22
- ( -1 255 -1 -1 -1 19 -1 -1 -1 -1 -1 -1 ) ;23
- ( 23 25 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;24
- ( 24 255 -1 -1 -1 -1 -1 -1 -1 -1 255 -1 ) ;25
- (255 28 -1 -1 -1 -1 -1 -1 -1 -1 255 -1 ) ;26
- ( -1 -1 -1 -1 7 -1 -1 -1 -1 -1 -1 -1 ) ;27
- ( 26 255 -1 -1 -1 -1 -1 -1 -1 -1 255 -1 ) ;28
- ( -1 -1 30 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;29
- ( -1 -1 31 29 -1 -1 -1 -1 -1 -1 -1 -1 ) ;30
- ( 32 33 -1 30 -1 -1 -1 -1 -1 -1 -1 -1 ) ;31
- ( -1 31 -1 255 -1 -1 -1 -1 -1 34 -1 -1 ) ;32
- ( 31 -1 -1 -1 -1 -1 -1 -1 -1 35 -1 -1 ) ;33
- ( -1 35 -1 -1 -1 -1 -1 -1 32 37 -1 -1 ) ;34
- ( 34 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;35
- ( -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;36
- ( -1 -1 -1 -1 -1 -1 -1 38 34 -1 -1 -1 ) ;37
- ( -1 -1 40 41 37 -1 -1 39 -1 -1 -1 -1 ) ;38
- ( -1 -1 -1 -1 38 -1 -1 -1 -1 -1 -1 -1 ) ;39
- ( -1 -1 -1 38 -1 -1 -1 -1 42 -1 -1 -1 ) ;40
- ( -1 -1 38 -1 -1 -1 -1 -1 -1 43 -1 -1 ) ;41
- ( -1 -1 -1 -1 -1 -1 -1 -1 -1 40 -1 -1 ) ;42
- ( 44 -1 46 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;43
- ( -1 43 45 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;44
- ( -1 46 -1 44 -1 -1 -1 -1 -1 -1 -1 -1 ) ;45
- ( 45 -1 -1 43 -1 -1 -1 -1 -1 255 -1 -1 ) ;46
- ( 48 50 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;47
- ( 49 47 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;48
- ( -1 48 -1 -1 -1 -1 -1 -1 52 -1 -1 -1 ) ;49
- ( 47 51 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;50
- ( 50 104 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;51
- ( -1 -1 -1 -1 -1 -1 -1 -1 53 49 -1 -1 ) ;52
- ( -1 -1 -1 -1 -1 -1 -1 -1 54 52 -1 -1 ) ;53
- ( -1 -1 -1 -1 55 -1 -1 -1 -1 53 -1 -1 ) ;54
- ( -1 -1 -1 -1 56 -1 -1 54 -1 -1 -1 54 ) ;55
- ( -1 -1 -1 -1 -1 -1 -1 55 -1 31 -1 -1 ) ;56
- ( -1 -1 32 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;57
- ( 59 -1 11 -1 -1 -1 -1 -1 -1 -1 255 255) ;58
- ( 60 58 63 -1 -1 -1 255 -1 -1 -1 255 255) ;59
- ( 61 59 64 -1 -1 -1 -1 -1 -1 -1 255 255) ;60
- ( 62 60 65 -1 -1 -1 -1 -1 -1 -1 255 255) ;61
- ( -1 61 66 -1 -1 -1 -1 -1 -1 -1 255 255) ;62
- ( 64 -1 67 59 -1 -1 -1 -1 -1 -1 255 255) ;63
- ( 65 63 68 60 -1 -1 -1 -1 -1 -1 255 255) ;64
- ( 66 64 69 61 -1 -1 -1 -1 -1 -1 255 255) ;65
- ( -1 65 70 62 -1 -1 -1 -1 -1 -1 255 255) ;66
- ( 68 -1 71 63 -1 -1 -1 -1 -1 -1 255 255) ;67
- ( 69 67 72 64 -1 -1 -1 -1 -1 -1 255 255) ;68
- ( 70 68 73 65 -1 -1 -1 -1 -1 -1 255 255) ;69
- ( -1 69 74 66 -1 -1 -1 -1 -1 -1 255 255) ;70
- ( 72 -1 75 67 -1 -1 -1 -1 -1 -1 255 255) ;71
- ( 73 71 76 68 -1 -1 -1 -1 -1 -1 255 255) ;72
- ( 74 72 77 69 -1 -1 -1 -1 -1 -1 255 255) ;73
- ( -1 73 78 70 -1 -1 -1 -1 -1 -1 255 255) ;74
- ( 76 -1 79 71 -1 -1 -1 -1 -1 -1 255 255) ;75
- ( 77 75 80 72 -1 -1 -1 -1 -1 -1 255 255) ;76
- ( 78 76 81 73 -1 -1 -1 -1 -1 -1 255 255) ;77
- ( -1 77 82 74 -1 -1 -1 -1 -1 -1 255 255) ;78
- ( 80 -1 -1 75 -1 -1 -1 -1 -1 -1 255 255) ;79
- ( 81 79 255 76 -1 -1 -1 -1 -1 -1 255 255) ;80
- ( 82 80 -1 77 -1 -1 -1 -1 -1 -1 255 255) ;81
- ( -1 81 -1 78 -1 -1 -1 -1 -1 -1 255 255) ;82
- ( 84 -1 -1 -1 -1 59 -1 -1 -1 -1 255 255) ;83
- ( -1 83 85 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;84
- ( 86 -1 87 84 -1 -1 -1 -1 -1 -1 -1 -1 ) ;85
- ( -1 85 88 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;86
- ( 88 -1 -1 85 -1 -1 -1 -1 -1 -1 -1 -1 ) ;87
- ( -1 87 255 86 -1 -1 -1 -1 -1 -1 -1 -1 ) ;88
- ( -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 255 -1 ) ;89
- ( 91 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;90
- ( 92 90 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;91
- ( -1 91 -1 -1 -1 -1 -1 -1 93 94 -1 -1 ) ;92
- ( -1 -1 -1 88 -1 -1 -1 -1 -1 92 -1 -1 ) ;93
- ( -1 -1 -1 -1 95 -1 -1 -1 92 -1 -1 -1 ) ;94
- ( -1 -1 -1 -1 -1 -1 -1 94 -1 -1 -1 -1 ) ;95
- ( 97 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;96
- ( -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;97
- ( 99 97 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;98
- ( -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;99
- ( 101 99 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;100
- ( -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;101
- ( 103 101 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;102
- ( -1 102 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;103
- ( 51 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;104
- )
-; no so ea we ne se nw sw up do in ot
-)
-
-
-;;; How the user references *all* objects, permanent and regular.
-(setq dun-objnames '(
- (shovel . 0)
- (lamp . 1)
- (cpu . 2) (board . 2) (card . 2)
- (food . 3)
- (key . 4)
- (paper . 5)
- (rms . 6) (statue . 6) (statuette . 6) (stallman . 6)
- (diamond . 7)
- (weight . 8)
- (life . 9) (preserver . 9)
- (bracelet . 10) (emerald . 10)
- (gold . 11)
- (platinum . 12)
- (towel . 13) (beach . 13)
- (axe . 14)
- (silver . 15)
- (license . 16)
- (coins . 17)
- (egg . 18)
- (jar . 19)
- (bone . 20)
- (acid . 21) (nitric . 21)
- (glycerine . 22)
- (ruby . 23)
- (amethyst . 24)
- (mona . 25)
- (bill . 26)
- (floppy . 27) (disk . 27)
-
- (boulder . -1)
- (tree . -2) (trees . -2) (palm . -2)
- (bear . -3)
- (bin . -4) (bins . -4)
- (cabinet . -5) (computer . -5) (vax . -5) (ibm . -5)
- (protoplasm . -6)
- (dial . -7)
- (button . -8)
- (chute . -9)
- (painting . -10)
- (bed . -11)
- (urinal . -12)
- (URINE . -13)
- (pipes . -14) (pipe . -14)
- (box . -15) (slit . -15)
- (cable . -16) (ethernet . -16)
- (mail . -17) (drop . -17)
- (bus . -18)
- (gate . -19)
- (cliff . -20)
- (skeleton . -21) (dinosaur . -21)
- (fish . -22)
- (tanks . -23)
- (switch . -24)
- (blackboard . -25)
- (disposal . -26) (garbage . -26)
- (ladder . -27)
- (subway . -28) (train . -28)
- (pc . -29) (drive . -29)
-))
-
-(dolist (x dun-objnames)
- (let (name)
- (setq name (concat "obj-" (prin1-to-string (car x))))
- (eval (list 'defconst (intern name) (cdr x)))))
-
-(defconst obj-special 255)
-
-;;; The initial setup of what objects are in each room.
-;;; Regular objects have whole numbers lower than 255.
-;;; Objects that cannot be taken but might move and are
-;;; described during room description are negative.
-;;; Stuff that is described and might change are 255, and are
-;;; handled specially by 'dun-describe-room.
-
-(setq dun-room-objects (list nil
-
- (list obj-shovel) ;; treasure-room
- (list obj-boulder) ;; dead-end
- nil nil nil
- (list obj-food) ;; se-nw-road
- (list obj-bear) ;; bear-hangout
- nil nil
- (list obj-special) ;; computer-room
- (list obj-lamp obj-license obj-silver);; meadow
- nil nil
- (list obj-special) ;; sauna
- nil
- (list obj-weight obj-life) ;; weight-room
- nil nil
- (list obj-rms obj-floppy) ;; thirsty-maze
- nil nil nil nil nil nil nil
- (list obj-emerald) ;; hidden-area
- nil
- (list obj-gold) ;; misty-room
- nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
- (list obj-towel obj-special) ;; red-room
- nil nil nil nil nil
- (list obj-box) ;; stair-landing
- nil nil nil
- (list obj-axe) ;; smal-crawlspace
- nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
- nil nil nil nil nil
- (list obj-special) ;; fourth-vermont-intersection
- nil nil
- (list obj-coins) ;; fifth-oaktree-intersection
- nil
- (list obj-bus) ;; fifth-sycamore-intersection
- nil
- (list obj-bone) ;; museum-lobby
- nil
- (list obj-jar obj-special obj-ruby) ;; marine-life-area
- (list obj-nitric) ;; maintenance-room
- (list obj-glycerine) ;; classroom
- nil nil nil nil nil
- (list obj-amethyst) ;; bottom-of-subway-stairs
- nil nil
- (list obj-special) ;; question-room-1
- nil
- (list obj-special) ;; question-room-2
- nil
- (list obj-special) ;; question-room-three
- nil
- (list obj-mona) ;; winner's-room
-nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
-nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
-nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
-nil))
-
-;;; These are objects in a room that are only described in the
-;;; room description. They are permanent.
-
-(setq dun-room-silents (list nil
- (list obj-tree) ;; dead-end
- (list obj-tree) ;; e-w-dirt-road
- nil nil nil nil nil nil
- (list obj-bin) ;; mailroom
- (list obj-computer) ;; computer-room
- nil nil nil
- (list obj-dial) ;; sauna
- nil
- (list obj-ladder) ;; weight-room
- (list obj-button obj-ladder) ;; maze-button-room
- nil nil nil
- nil nil nil nil nil nil nil
- (list obj-chute) ;; cave-entrance
- nil nil nil nil nil
- (list obj-painting obj-bed) ;; bedroom
- (list obj-urinal obj-pipes) ;; bathroom
- nil nil nil nil nil nil
- (list obj-boulder) ;; horseshoe-boulder-room
- nil nil nil nil nil nil nil nil nil nil nil nil nil nil
- (list obj-computer obj-cable) ;; gamma-computing-center
- (list obj-mail) ;; post-office
- (list obj-gate) ;; main-maple-intersection
- nil nil nil nil nil nil nil nil nil nil nil nil nil
- nil nil nil nil nil nil nil
- (list obj-cliff) ;; fifth-oaktree-intersection
- nil nil nil
- (list obj-dinosaur) ;; museum-lobby
- nil
- (list obj-fish obj-tanks) ;; marine-life-area
- (list obj-switch) ;; maintenance-room
- (list obj-blackboard) ;; classroom
- (list obj-train) ;; vermont-station
- nil nil
- (list obj-disposal) ;; north-end-of-n-s-tunnel
- nil nil
- (list obj-computer) ;; endgame-computer-room
- nil nil nil nil nil nil nil nil
- (list obj-pc) ;; pc-area
- nil nil nil nil nil nil
-))
-(setq dun-inventory '(1))
-
-;;; Descriptions of objects, as they appear in the room description, and
-;;; the inventory.
-
-(setq dun-objects '(
- ("There is a shovel here." "A shovel") ;0
- ("There is a lamp nearby." "A lamp") ;1
- ("There is a CPU card here." "A computer board") ;2
- ("There is some food here." "Some food") ;3
- ("There is a shiny brass key here." "A brass key") ;4
- ("There is a slip of paper here." "A slip of paper") ;5
- ("There is a wax statuette of Richard Stallman here." ;6
- "An RMS statuette")
- ("There is a shimmering diamond here." "A diamond") ;7
- ("There is a 10 pound weight here." "A weight") ;8
- ("There is a life preserver here." "A life preserver");9
- ("There is an emerald bracelet here." "A bracelet") ;10
- ("There is a gold bar here." "A gold bar") ;11
- ("There is a platinum bar here." "A platinum bar") ;12
- ("There is a beach towel on the ground here." "A beach towel")
- ("There is an axe here." "An axe") ;14
- ("There is a silver bar here." "A silver bar") ;15
- ("There is a bus driver's license here." "A license") ;16
- ("There are some valuable coins here." "Some valuable coins")
- ("There is a jewel-encrusted egg here." "A valuable egg") ;18
- ("There is a glass jar here." "A glass jar") ;19
- ("There is a dinosaur bone here." "A bone") ;20
- ("There is a packet of nitric acid here." "Some nitric acid")
- ("There is a packet of glycerine here." "Some glycerine") ;22
- ("There is a valuable ruby here." "A ruby") ;23
- ("There is a valuable amethyst here." "An amethyst") ;24
- ("The Mona Lisa is here." "The Mona Lisa") ;25
- ("There is a 100 dollar bill here." "A $100 bill") ;26
- ("There is a floppy disk here." "A floppy disk") ;27
- )
-)
-
-;;; Weight of objects
-
-(setq dun-object-lbs
- '(2 1 1 1 1 0 2 2 10 3 1 1 1 0 1 1 0 1 1 1 1 0 0 2 2 1 0 0))
-(setq dun-object-pts
- '(0 0 0 0 0 0 0 10 0 0 10 10 10 0 0 10 0 10 10 0 0 0 0 10 10 10 10 0))
-
-
-;;; Unix representation of objects.
-(setq dun-objfiles '(
- "shovel.o" "lamp.o" "cpu.o" "food.o" "key.o" "paper.o"
- "rms.o" "diamond.o" "weight.o" "preserver.o" "bracelet.o"
- "gold.o" "platinum.o" "towel.o" "axe.o" "silver.o" "license.o"
- "coins.o" "egg.o" "jar.o" "bone.o" "nitric.o" "glycerine.o"
- "ruby.o" "amethyst.o"
- ))
-
-;;; These are the descriptions for the negative numbered objects from
-;;; dun-room-objects
-
-(setq dun-perm-objects '(
- nil
- ("There is a large boulder here.")
- nil
- ("There is a ferocious bear here!")
- nil
- nil
- ("There is a worthless pile of protoplasm here.")
- nil
- nil
- nil
- nil
- nil
- nil
- ("There is a strange smell in this room.")
- nil
- (
-"There is a box with a slit in it, bolted to the wall here."
- )
- nil
- nil
- ("There is a bus here.")
- nil
- nil
- nil
-))
-
-
-;;; These are the descriptions the user gets when regular objects are
-;;; examined.
-
-(setq dun-physobj-desc '(
-"It is a normal shovel with a price tag attached that says $19.99."
-"The lamp is hand-crafted by Geppetto."
-"The CPU board has a VAX chip on it. It seems to have
-2 Megabytes of RAM onboard."
-"It looks like some kind of meat. Smells pretty bad."
-nil
-"The paper says: Don't forget to type 'help' for help. Also, remember
-this word: 'worms'"
-"The statuette is of the likeness of Richard Stallman, the author of the
-famous EMACS editor. You notice that he is not wearing any shoes."
-nil
-"You observe that the weight is heavy."
-"It says S. S. Minnow."
-nil
-nil
-nil
-"It has a picture of snoopy on it."
-nil
-nil
-"It has your picture on it!"
-"They are old coins from the 19th century."
-"It is a valuable Fabrege egg."
-"It is a a plain glass jar."
-nil
-nil
-nil
-nil
-nil
- )
-)
-
-;;; These are the descriptions the user gets when non-regular objects
-;;; are examined.
-
-(setq dun-permobj-desc '(
- nil
-"It is just a boulder. It cannot be moved."
-"They are palm trees with a bountiful supply of coconuts in them."
-"It looks like a grizzly to me."
-"All of the bins are empty. Looking closely you can see that there
-are names written at the bottom of each bin, but most of them are
-faded away so that you cannot read them. You can only make out three
-names:
- Jeffrey Collier
- Robert Toukmond
- Thomas Stock
-"
- nil
-"It is just a garbled mess."
-"The dial points to a temperature scale which has long since faded away."
-nil
-nil
-"It is a velvet painting of Elvis Presly. It seems to be nailed to the
-wall, and you cannot move it."
-"It is a queen sized bed, with a very firm mattress."
-"The urinal is very clean compared with everything else in the cave. There
-isn't even any rust. Upon close examination you realize that the drain at the
-bottom is missing, and there is just a large hole leading down the
-pipes into nowhere. The hole is too small for a person to fit in. The
-flush handle is so clean that you can see your reflection in it."
-nil
-nil
-"The box has a slit in the top of it, and on it, in sloppy handwriting, is
-written: 'For key upgrade, put key in here.'"
-nil
-"It says 'express mail' on it."
-"It is a 35 passenger bus with the company name 'mobytours' on it."
-"It is a large metal gate that is too big to climb over."
-"It is a HIGH cliff."
-"Unfortunately you do not know enough about dinosaurs to tell very much about
-it. It is very big, though."
-"The fish look like they were once quite beautiful."
-nil
-nil
-nil
-nil
-"It is a normal ladder that is permanently attached to the hole."
-"It is a passenger train that is ready to go."
-"It is a personal computer that has only one floppy disk drive."
- )
-)
-
-(setq dun-diggables
- (list nil nil nil (list obj-cpu) nil nil nil nil nil nil nil
- nil nil nil nil nil nil nil nil nil nil ;11-20
- nil nil nil nil nil nil nil nil nil nil ;21-30
- nil nil nil nil nil nil nil nil nil nil ;31-40
- nil (list obj-platinum) nil nil nil nil nil nil nil nil))
-
-(setq dun-room-shorts nil)
-(dolist (x dun-rooms)
- (setq dun-room-shorts
- (append dun-room-shorts (list (downcase
- (dun-space-to-hyphen
- (cadr x)))))))
-
-(setq dun-endgame-questions '(
- (
-"What is your password on the machine called 'pokey'?" "robert")
- (
-"What password did you use during anonymous ftp to gamma?" "foo")
- (
-"Excluding the endgame, how many places are there where you can put
-treasures for points?" "4" "four")
- (
-"What is your login name on the 'endgame' machine?" "toukmond"
-)
- (
-"What is the nearest whole dollar to the price of the shovel?" "20" "twenty")
- (
-"What is the name of the bus company serving the town?" "mobytours")
- (
-"Give either of the two last names in the mailroom, other than your own."
-"collier" "stock")
- (
-"What cartoon character is on the towel?" "snoopy")
- (
-"What is the last name of the author of EMACS?" "stallman")
- (
-"How many megabytes of memory is on the CPU board for the Vax?" "2")
- (
-"Which street in town is named after a U.S. state?" "vermont")
- (
-"How many pounds did the weight weigh?" "ten" "10")
- (
-"Name the STREET which runs right over the subway stop." "fourth" "4" "4th")
- (
-"How many corners are there in town (excluding the one with the Post Office)?"
- "24" "twentyfour" "twenty-four")
- (
-"What type of bear was hiding your key?" "grizzly")
- (
-"Name either of the two objects you found by digging." "cpu" "card" "vax"
-"board" "platinum")
- (
-"What network protocol is used between pokey and gamma?" "tcp/ip" "ip" "tcp")
-))
-
-(let (a)
- (setq a 0)
- (dolist (x dun-room-shorts)
- (eval (list 'defconst (intern x) a))
- (setq a (+ a 1))))
-
-
-
-;;;;
-;;;; This section defines the UNIX emulation functions for dunnet.
-;;;;
-
-(defun dun-unix-parse (args)
- (interactive "*p")
- (beginning-of-line)
- (let (beg esign)
- (setq beg (+ (point) 2))
- (end-of-line)
- (if (and (not (= beg (point)))
- (string= "$" (buffer-substring (- beg 2) (- beg 1))))
- (progn
- (setq line (downcase (buffer-substring beg (point))))
- (princ line)
- (if (eq (dun-parse2 nil dun-unix-verbs line) -1)
- (progn
- (if (setq esign (string-match "=" line))
- (dun-doassign line esign)
- (dun-mprinc (car line-list))
- (dun-mprincl ": not found.")))))
- (goto-char (point-max))
- (dun-mprinc "\n"))
- (if (eq dungeon-mode 'unix)
- (progn
- (dun-fix-screen)
- (dun-mprinc "$ ")))))
-
-(defun dun-doassign (line esign)
- (if (not dun-wizard)
- (let (passwd)
- (dun-mprinc "Enter wizard password: ")
- (setq passwd (dun-read-line))
- (if (not dun-batch-mode)
- (dun-mprinc "\n"))
- (if (string= passwd "moby")
- (progn
- (setq dun-wizard t)
- (dun-doassign line esign))
- (dun-mprincl "Incorrect.")))
-
- (let (varname epoint afterq i value)
- (setq varname (substring line 0 esign))
- (if (not (setq epoint (string-match ")" line)))
- (if (string= (substring line (1+ esign) (+ esign 2))
- "\"")
- (progn
- (setq afterq (substring line (+ esign 2)))
- (setq epoint (+
- (string-match "\"" afterq)
- (+ esign 3))))
-
- (if (not (setq epoint (string-match " " line)))
- (setq epoint (length line))))
- (setq epoint (1+ epoint))
- (while (and
- (not (= epoint (length line)))
- (setq i (string-match ")" (substring line epoint))))
- (setq epoint (+ epoint i 1))))
- (setq value (substring line (1+ esign) epoint))
- (dun-eval varname value))))
-
-(defun dun-eval (varname value)
- (let (eval-error)
- (switch-to-buffer (get-buffer-create "*dungeon-eval*"))
- (erase-buffer)
- (insert "(setq ")
- (insert varname)
- (insert " ")
- (insert value)
- (insert ")")
- (setq eval-error nil)
- (condition-case nil
- (eval-current-buffer)
- (error (setq eval-error t)))
- (kill-buffer (current-buffer))
- (switch-to-buffer "*dungeon*")
- (if eval-error
- (dun-mprincl "Invalid syntax."))))
-
-
-(defun dun-unix-interface ()
- (dun-login)
- (if dun-logged-in
- (progn
- (setq dungeon-mode 'unix)
- (define-key dungeon-mode-map "\r" 'dun-unix-parse)
- (dun-mprinc "$ "))))
-
-(defun dun-login ()
- (let (tries username password)
- (setq tries 4)
- (while (and (not dun-logged-in) (> (setq tries (- tries 1)) 0))
- (dun-mprinc "\n\nUNIX System V, Release 2.2 (pokey)\n\nlogin: ")
- (setq username (dun-read-line))
- (if (not dun-batch-mode)
- (dun-mprinc "\n"))
- (dun-mprinc "password: ")
- (setq password (dun-read-line))
- (if (not dun-batch-mode)
- (dun-mprinc "\n"))
- (if (or (not (string= username "toukmond"))
- (not (string= password "robert")))
- (dun-mprincl "login incorrect")
- (setq dun-logged-in t)
- (dun-mprincl "
-Welcome to Unix\n
-Please clean up your directories. The filesystem is getting full.
-Our tcp/ip link to gamma is a little flaky, but seems to work.
-The current version of ftp can only send files from the current
-directory, and deletes them after they are sent! Be careful.
-
-Note: Restricted bourne shell in use.\n")))
- (setq dungeon-mode 'dungeon)))
-
-(defun dun-ls (args)
- (if (car args)
- (let (ocdpath ocdroom)
- (setq ocdpath dun-cdpath)
- (setq ocdroom dun-cdroom)
- (if (not (eq (dun-cd args) -2))
- (dun-ls nil))
- (setq dun-cdpath ocdpath)
- (setq dun-cdroom ocdroom))
- (if (= dun-cdroom -10)
- (dun-ls-inven))
- (if (= dun-cdroom -2)
- (dun-ls-rooms))
- (if (= dun-cdroom -3)
- (dun-ls-root))
- (if (= dun-cdroom -4)
- (dun-ls-usr))
- (if (> dun-cdroom 0)
- (dun-ls-room))))
-
-(defun dun-ls-root ()
- (dun-mprincl "total 4
-drwxr-xr-x 3 root staff 512 Jan 1 1970 .
-drwxr-xr-x 3 root staff 2048 Jan 1 1970 ..
-drwxr-xr-x 3 root staff 2048 Jan 1 1970 usr
-drwxr-xr-x 3 root staff 2048 Jan 1 1970 rooms"))
-
-(defun dun-ls-usr ()
- (dun-mprincl "total 4
-drwxr-xr-x 3 root staff 512 Jan 1 1970 .
-drwxr-xr-x 3 root staff 2048 Jan 1 1970 ..
-drwxr-xr-x 3 toukmond restricted 512 Jan 1 1970 toukmond"))
-
-(defun dun-ls-rooms ()
- (dun-mprincl "total 16
-drwxr-xr-x 3 root staff 512 Jan 1 1970 .
-drwxr-xr-x 3 root staff 2048 Jan 1 1970 ..")
- (dolist (x dun-visited)
- (dun-mprinc
-"drwxr-xr-x 3 root staff 512 Jan 1 1970 ")
- (dun-mprincl (nth x dun-room-shorts))))
-
-(defun dun-ls-room ()
- (dun-mprincl "total 4
-drwxr-xr-x 3 root staff 512 Jan 1 1970 .
-drwxr-xr-x 3 root staff 2048 Jan 1 1970 ..
--rwxr-xr-x 3 root staff 2048 Jan 1 1970 description")
- (dolist (x (nth dun-cdroom dun-room-objects))
- (if (and (>= x 0) (not (= x 255)))
- (progn
- (dun-mprinc "-rwxr-xr-x 1 toukmond restricted 0 Jan 1 1970 ")
- (dun-mprincl (nth x dun-objfiles))))))
-
-(defun dun-ls-inven ()
- (dun-mprinc "total 467
-drwxr-xr-x 3 toukmond restricted 512 Jan 1 1970 .
-drwxr-xr-x 3 root staff 2048 Jan 1 1970 ..")
- (dolist (x dun-unix-verbs)
- (if (not (eq (car x) 'IMPOSSIBLE))
- (progn
- (dun-mprinc"
--rwxr-xr-x 1 toukmond restricted 10423 Jan 1 1970 ")
- (dun-mprinc (car x)))))
- (dun-mprinc "\n")
- (if (not dun-uncompressed)
- (dun-mprincl
-"-rwxr-xr-x 1 toukmond restricted 0 Jan 1 1970 paper.o.Z"))
- (dolist (x dun-inventory)
- (dun-mprinc
-"-rwxr-xr-x 1 toukmond restricted 0 Jan 1 1970 ")
- (dun-mprincl (nth x dun-objfiles))))
-
-(defun dun-echo (args)
- (let (nomore var)
- (setq nomore nil)
- (dolist (x args)
- (if (not nomore)
- (progn
- (if (not (string= (substring x 0 1) "$"))
- (progn
- (dun-mprinc x)
- (dun-mprinc " "))
- (setq var (intern (substring x 1)))
- (if (not (boundp var))
- (dun-mprinc " ")
- (if (member var dun-restricted)
- (progn
- (dun-mprinc var)
- (dun-mprinc ": Permission denied")
- (setq nomore t))
- (eval (list 'dun-mprinc var))
- (dun-mprinc " ")))))))
- (dun-mprinc "\n")))
-
-
-(defun dun-ftp (args)
- (let (host username passwd ident newlist)
- (if (not (car args))
- (dun-mprincl "ftp: hostname required on command line.")
- (setq host (intern (car args)))
- (if (not (member host '(gamma dun-endgame)))
- (dun-mprincl "ftp: Unknown host.")
- (if (eq host 'dun-endgame)
- (dun-mprincl "ftp: connection to endgame not allowed")
- (if (not dun-ethernet)
- (dun-mprincl "ftp: host not responding.")
- (dun-mprincl "Connected to gamma. FTP ver 0.9 00:00:00 01/01/70")
- (dun-mprinc "Username: ")
- (setq username (dun-read-line))
- (if (string= username "toukmond")
- (if dun-batch-mode
- (dun-mprincl "toukmond ftp access not allowed.")
- (dun-mprincl "\ntoukmond ftp access not allowed."))
- (if (string= username "anonymous")
- (if dun-batch-mode
- (dun-mprincl
- "Guest login okay, send your user ident as password.")
- (dun-mprincl
- "\nGuest login okay, send your user ident as password."))
- (if dun-batch-mode
- (dun-mprinc "Password required for ")
- (dun-mprinc "\nPassword required for "))
- (dun-mprincl username))
- (dun-mprinc "Password: ")
- (setq ident (dun-read-line))
- (if (not (string= username "anonymous"))
- (if dun-batch-mode
- (dun-mprincl "Login failed.")
- (dun-mprincl "\nLogin failed."))
- (if dun-batch-mode
- (dun-mprincl
- "Guest login okay, user access restrictions apply.")
- (dun-mprincl
- "\nGuest login okay, user access restrictions apply."))
- (dun-ftp-commands)
- (setq newlist
-'("What password did you use during anonymous ftp to gamma?"))
- (setq newlist (append newlist (list ident)))
- (rplaca (nthcdr 1 dun-endgame-questions) newlist)))))))))
-
-(defun dun-ftp-commands ()
- (setq dun-exitf nil)
- (let (line)
- (while (not dun-exitf)
- (dun-mprinc "ftp> ")
- (setq line (dun-read-line))
- (if
- (eq
- (dun-parse2 nil
- '((type . dun-ftptype) (binary . dun-bin) (bin . dun-bin)
- (send . dun-send) (put . dun-send) (quit . dun-ftpquit)
- (help . dun-ftphelp)(ascii . dun-fascii)
- ) line)
- -1)
- (dun-mprincl "No such command. Try help.")))
- (setq dun-ftptype 'ascii)))
-
-(defun dun-ftptype (args)
- (if (not (car args))
- (dun-mprincl "Usage: type [binary | ascii]")
- (setq args (intern (car args)))
- (if (eq args 'binary)
- (dun-bin nil)
- (if (eq args 'ascii)
- (dun-fascii 'nil)
- (dun-mprincl "Unknown type.")))))
-
-(defun dun-bin (args)
- (dun-mprincl "Type set to binary.")
- (setq dun-ftptype 'binary))
-
-(defun dun-fascii (args)
- (dun-mprincl "Type set to ascii.")
- (setq dun-ftptype 'ascii))
-
-(defun dun-ftpquit (args)
- (setq dun-exitf t))
-
-(defun dun-send (args)
- (if (not (car args))
- (dun-mprincl "Usage: send <filename>")
- (setq args (car args))
- (let (counter foo)
- (setq foo nil)
- (setq counter 0)
-
-;;; User can send commands! Stupid user.
-
-
- (if (assq (intern args) dun-unix-verbs)
- (progn
- (rplaca (assq (intern args) dun-unix-verbs) 'IMPOSSIBLE)
- (dun-mprinc "Sending ")
- (dun-mprinc dun-ftptype)
- (dun-mprinc " file for ")
- (dun-mprincl args)
- (dun-mprincl "Transfer complete."))
-
- (dolist (x dun-objfiles)
- (if (string= args x)
- (progn
- (if (not (member counter dun-inventory))
- (progn
- (dun-mprincl "No such file.")
- (setq foo t))
- (dun-mprinc "Sending ")
- (dun-mprinc dun-ftptype)
- (dun-mprinc " file for ")
- (dun-mprinc (downcase (cadr (nth counter dun-objects))))
- (dun-mprincl ", (0 bytes)")
- (if (not (eq dun-ftptype 'binary))
- (progn
- (if (not (member obj-protoplasm
- (nth receiving-room
- dun-room-objects)))
- (dun-replace dun-room-objects receiving-room
- (append (nth receiving-room
- dun-room-objects)
- (list obj-protoplasm))))
- (dun-remove-obj-from-inven counter))
- (dun-remove-obj-from-inven counter)
- (dun-replace dun-room-objects receiving-room
- (append (nth receiving-room dun-room-objects)
- (list counter))))
- (setq foo t)
- (dun-mprincl "Transfer complete."))))
- (setq counter (+ 1 counter)))
- (if (not foo)
- (dun-mprincl "No such file."))))))
-
-(defun dun-ftphelp (args)
- (dun-mprincl
- "Possible commands are:\nsend quit type ascii binary help"))
-
-(defun dun-uexit (args)
- (setq dungeon-mode 'dungeon)
- (dun-mprincl "\nYou step back from the console.")
- (define-key dungeon-mode-map "\r" 'dun-parse)
- (if (not dun-batch-mode)
- (dun-messages)))
-
-(defun dun-pwd (args)
- (dun-mprincl dun-cdpath))
-
-(defun dun-uncompress (args)
- (if (not (car args))
- (dun-mprincl "Usage: uncompress <filename>")
- (setq args (car args))
- (if (or dun-uncompressed
- (and (not (string= args "paper.o"))
- (not (string= args "paper.o.z"))))
- (dun-mprincl "Uncompress command failed.")
- (setq dun-uncompressed t)
- (setq dun-inventory (append dun-inventory (list obj-paper))))))
-
-(defun dun-rlogin (args)
- (let (passwd)
- (if (not (car args))
- (dun-mprincl "Usage: rlogin <hostname>")
- (setq args (car args))
- (if (string= args "endgame")
- (dun-rlogin-endgame)
- (if (not (string= args "gamma"))
- (dun-mprincl "No such host.")
- (if (not dun-ethernet)
- (dun-mprincl "Host not responding.")
- (dun-mprinc "Password: ")
- (setq passwd (dun-read-line))
- (if (not (string= passwd "worms"))
- (dun-mprincl "\nlogin incorrect")
- (dun-mprinc
-"\nYou begin to feel strange for a moment, and you lose your items."
-)
- (dun-replace dun-room-objects computer-room
- (append (nth computer-room dun-room-objects)
- dun-inventory))
- (setq dun-inventory nil)
- (setq dun-current-room receiving-room)
- (dun-uexit nil))))))))
-
-(defun dun-cd (args)
- (let (tcdpath tcdroom path-elements room-check)
- (if (not (car args))
- (dun-mprincl "Usage: cd <path>")
- (setq tcdpath dun-cdpath)
- (setq tcdroom dun-cdroom)
- (setq dun-badcd nil)
- (condition-case nil
- (setq path-elements (dun-get-path (car args) nil))
- (error (dun-mprincl "Invalid path.")
- (setq dun-badcd t)))
- (dolist (pe path-elements)
- (unless dun-badcd
- (if (not (string= pe "."))
- (if (string= pe "..")
- (progn
- (if (> tcdroom 0) ;In a room
- (progn
- (setq tcdpath "/rooms")
- (setq tcdroom -2))
- ;In /rooms,/usr,root
- (if (or
- (= tcdroom -2) (= tcdroom -4)
- (= tcdroom -3))
- (progn
- (setq tcdpath "/")
- (setq tcdroom -3))
- (if (= tcdroom -10) ;In /usr/toukmond
- (progn
- (setq tcdpath "/usr")
- (setq tcdroom -4))))))
- (if (string= pe "/")
- (progn
- (setq tcdpath "/")
- (setq tcdroom -3))
- (if (= tcdroom -4)
- (if (string= pe "toukmond")
- (progn
- (setq tcdpath "/usr/toukmond")
- (setq tcdroom -10))
- (dun-nosuchdir))
- (if (= tcdroom -10)
- (dun-nosuchdir)
- (if (> tcdroom 0)
- (dun-nosuchdir)
- (if (= tcdroom -3)
- (progn
- (if (string= pe "rooms")
- (progn
- (setq tcdpath "/rooms")
- (setq tcdroom -2))
- (if (string= pe "usr")
- (progn
- (setq tcdpath "/usr")
- (setq tcdroom -4))
- (dun-nosuchdir))))
- (if (= tcdroom -2)
- (progn
- (dolist (x dun-visited)
- (setq room-check
- (nth x
- dun-room-shorts))
- (if (string= room-check pe)
- (progn
- (setq tcdpath
- (concat "/rooms/" room-check))
- (setq tcdroom x))))
- (if (= tcdroom -2)
- (dun-nosuchdir)))))))))))))
- (if (not dun-badcd)
- (progn
- (setq dun-cdpath tcdpath)
- (setq dun-cdroom tcdroom)
- 0)
- -2))))
-
-(defun dun-nosuchdir ()
- (dun-mprincl "No such directory.")
- (setq dun-badcd t))
-
-(defun dun-cat (args)
- (let (doto checklist)
- (if (not (setq args (car args)))
- (dun-mprincl "Usage: cat <ascii-file-name>")
- (if (string-match "/" args)
- (dun-mprincl "cat: only files in current directory allowed.")
- (if (and (> dun-cdroom 0) (string= args "description"))
- (dun-mprincl (car (nth dun-cdroom dun-rooms)))
- (if (setq doto (string-match "\\.o" args))
- (progn
- (if (= dun-cdroom -10)
- (setq checklist dun-inventory)
- (setq checklist (nth dun-cdroom dun-room-objects)))
- (if (not (member (cdr
- (assq (intern
- (substring args 0 doto))
- dun-objnames))
- checklist))
- (dun-mprincl "File not found.")
- (dun-mprincl "Ascii files only.")))
- (if (assq (intern args) dun-unix-verbs)
- (dun-mprincl "Ascii files only.")
- (dun-mprincl "File not found."))))))))
-
-(defun dun-zippy (args)
- (dun-mprincl (yow)))
-
-(defun dun-rlogin-endgame ()
- (if (not (= (dun-score nil) 90))
- (dun-mprincl
- "You have not achieved enough points to connect to endgame.")
- (dun-mprincl"\nWelcome to the endgame. You are a truly noble adventurer.")
- (setq dun-current-room treasure-room)
- (setq dun-endgame t)
- (dun-replace dun-room-objects endgame-treasure-room (list obj-bill))
- (dun-uexit nil)))
-
-
-(random t)
-(setq tloc (+ 60 (random 18)))
-(dun-replace dun-room-objects tloc
- (append (nth tloc dun-room-objects) (list 18)))
-
-(setq tcomb (+ 100 (random 899)))
-(setq dun-combination (prin1-to-string tcomb))
-
-;;;;
-;;;; This section defines the DOS emulation functions for dunnet
-;;;;
-
-(defun dun-dos-parse (args)
- (interactive "*p")
- (beginning-of-line)
- (let (beg)
- (setq beg (+ (point) 3))
- (end-of-line)
- (if (not (= beg (point)))
- (let (line)
- (setq line (downcase (buffer-substring beg (point))))
- (princ line)
- (if (eq (dun-parse2 nil dun-dos-verbs line) -1)
- (progn
- (sleep-for 1)
- (dun-mprincl "Bad command or file name"))))
- (goto-char (point-max))
- (dun-mprinc "\n"))
- (if (eq dungeon-mode 'dos)
- (progn
- (dun-fix-screen)
- (dun-dos-prompt)))))
-
-(defun dun-dos-interface ()
- (dun-dos-boot-msg)
- (setq dungeon-mode 'dos)
- (define-key dungeon-mode-map "\r" 'dun-dos-parse)
- (dun-dos-prompt))
-
-(defun dun-dos-type (args)
- (sleep-for 2)
- (if (setq args (car args))
- (if (string= args "foo.txt")
- (dun-dos-show-combination)
- (if (string= args "command.com")
- (dun-mprincl "Cannot type binary files")
- (dun-mprinc "File not found - ")
- (dun-mprincl (upcase args))))
- (dun-mprincl "Must supply file name")))
-
-(defun dun-dos-invd (args)
- (sleep-for 1)
- (dun-mprincl "Invalid drive specification"))
-
-(defun dun-dos-dir (args)
- (sleep-for 1)
- (if (or (not (setq args (car args))) (string= args "\\"))
- (dun-mprincl "
- Volume in drive A is FOO
- Volume Serial Number is 1A16-08C9
- Directory of A:\\
-
-COMMAND COM 47845 04-09-91 2:00a
-FOO TXT 40 01-20-93 1:01a
- 2 file(s) 47845 bytes
- 1065280 bytes free
-")
- (dun-mprincl "
- Volume in drive A is FOO
- Volume Serial Number is 1A16-08C9
- Directory of A:\\
-
-File not found")))
-
-
-(defun dun-dos-prompt ()
- (dun-mprinc "A> "))
-
-(defun dun-dos-boot-msg ()
- (sleep-for 3)
- (dun-mprinc "Current time is ")
- (dun-mprincl (substring (current-time-string) 12 20))
- (dun-mprinc "Enter new time: ")
- (dun-read-line)
- (if (not dun-batch-mode)
- (dun-mprinc "\n")))
-
-(defun dun-dos-spawn (args)
- (sleep-for 1)
- (dun-mprincl "Cannot spawn subshell"))
-
-(defun dun-dos-exit (args)
- (setq dungeon-mode 'dungeon)
- (dun-mprincl "\nYou power down the machine and step back.")
- (define-key dungeon-mode-map "\r" 'dun-parse)
- (if (not dun-batch-mode)
- (dun-messages)))
-
-(defun dun-dos-no-disk ()
- (sleep-for 3)
- (dun-mprincl "Boot sector not found"))
-
-
-(defun dun-dos-show-combination ()
- (sleep-for 2)
- (dun-mprinc "\nThe combination is ")
- (dun-mprinc dun-combination)
- (dun-mprinc ".\n"))
-
-(defun dun-dos-nil (args))
-
-
-;;;;
-;;;; This section defines the save and restore game functions for dunnet.
-;;;;
-
-(defun dun-save-game (filename)
- (if (not (setq filename (car filename)))
- (dun-mprincl "You must supply a filename for the save.")
- (if (file-exists-p filename)
- (delete-file filename))
- (setq dun-numsaves (1+ dun-numsaves))
- (dun-make-save-buffer)
- (dun-save-val "dun-current-room")
- (dun-save-val "dun-computer")
- (dun-save-val "dun-combination")
- (dun-save-val "dun-visited")
- (dun-save-val "dun-diggables")
- (dun-save-val "dun-key-level")
- (dun-save-val "dun-floppy")
- (dun-save-val "dun-numsaves")
- (dun-save-val "dun-numcmds")
- (dun-save-val "dun-logged-in")
- (dun-save-val "dungeon-mode")
- (dun-save-val "dun-jar")
- (dun-save-val "dun-lastdir")
- (dun-save-val "dun-black")
- (dun-save-val "dun-nomail")
- (dun-save-val "dun-unix-verbs")
- (dun-save-val "dun-hole")
- (dun-save-val "dun-uncompressed")
- (dun-save-val "dun-ethernet")
- (dun-save-val "dun-sauna-level")
- (dun-save-val "dun-room-objects")
- (dun-save-val "dun-room-silents")
- (dun-save-val "dun-inventory")
- (dun-save-val "dun-endgame-questions")
- (dun-save-val "dun-endgame")
- (dun-save-val "dun-cdroom")
- (dun-save-val "dun-cdpath")
- (dun-save-val "dun-correct-answer")
- (dun-save-val "dun-inbus")
- (if (dun-compile-save-out filename)
- (dun-mprincl "Error saving to file.")
- (dun-do-logfile 'save nil)
- (switch-to-buffer "*dungeon*")
- (princ "")
- (dun-mprincl "Done."))))
-
-(defun dun-make-save-buffer ()
- (switch-to-buffer (get-buffer-create "*save-dungeon*"))
- (erase-buffer))
-
-(defun dun-compile-save-out (filename)
- (let (ferror)
- (setq ferror nil)
- (condition-case nil
- (dun-rot13)
- (error (setq ferror t)))
- (if (not ferror)
- (progn
- (goto-char (point-min))))
- (condition-case nil
- (write-region 1 (point-max) filename nil 1)
- (error (setq ferror t)))
- (kill-buffer (current-buffer))
- ferror))
-
-
-(defun dun-save-val (varname)
- (let (value)
- (setq varname (intern varname))
- (setq value (eval varname))
- (dun-minsert "(setq ")
- (dun-minsert varname)
- (dun-minsert " ")
- (if (or (listp value)
- (symbolp value))
- (dun-minsert "'"))
- (if (stringp value)
- (dun-minsert "\""))
- (dun-minsert value)
- (if (stringp value)
- (dun-minsert "\""))
- (dun-minsertl ")")))
-
-
-(defun dun-restore (args)
- (let (file)
- (if (not (setq file (car args)))
- (dun-mprincl "You must supply a filename.")
- (if (not (dun-load-d file))
- (dun-mprincl "Could not load restore file.")
- (dun-mprincl "Done.")
- (setq room 0)))))
-
-
-(defun dun-do-logfile (type how)
- (let (ferror newscore)
- (setq ferror nil)
- (switch-to-buffer (get-buffer-create "*score*"))
- (erase-buffer)
- (condition-case nil
- (insert-file-contents dun-log-file)
- (error (setq ferror t)))
- (unless ferror
- (goto-char (point-max))
- (dun-minsert (current-time-string))
- (dun-minsert " ")
- (dun-minsert (user-login-name))
- (dun-minsert " ")
- (if (eq type 'save)
- (dun-minsert "saved ")
- (if (= (dun-endgame-score) 110)
- (dun-minsert "won ")
- (if (not how)
- (dun-minsert "quit ")
- (dun-minsert "killed by ")
- (dun-minsert how)
- (dun-minsert " "))))
- (dun-minsert "at ")
- (dun-minsert (cadr (nth (abs room) dun-rooms)))
- (dun-minsert ". score: ")
- (if (> (dun-endgame-score) 0)
- (dun-minsert (setq newscore (+ 90 (dun-endgame-score))))
- (dun-minsert (setq newscore (dun-reg-score))))
- (dun-minsert " saves: ")
- (dun-minsert dun-numsaves)
- (dun-minsert " commands: ")
- (dun-minsert dun-numcmds)
- (dun-minsert "\n")
- (write-region 1 (point-max) dun-log-file nil 1))
- (kill-buffer (current-buffer))))
-
-
-;;;;
-;;;; These are functions, and function re-definitions so that dungeon can
-;;;; be run in batch mode.
-
-
-(defun dun-batch-mprinc (arg)
- (if (stringp arg)
- (send-string-to-terminal arg)
- (send-string-to-terminal (prin1-to-string arg))))
-
-
-(defun dun-batch-mprincl (arg)
- (if (stringp arg)
- (progn
- (send-string-to-terminal arg)
- (send-string-to-terminal "\n"))
- (send-string-to-terminal (prin1-to-string arg))
- (send-string-to-terminal "\n")))
-
-(defun dun-batch-parse (dun-ignore dun-verblist line)
- (setq line-list (dun-listify-string (concat line " ")))
- (dun-doverb dun-ignore dun-verblist (car line-list) (cdr line-list)))
-
-(defun dun-batch-parse2 (dun-ignore dun-verblist line)
- (setq line-list (dun-listify-string2 (concat line " ")))
- (dun-doverb dun-ignore dun-verblist (car line-list) (cdr line-list)))
-
-(defun dun-batch-read-line ()
- (read-from-minibuffer "" nil dungeon-batch-map))
-
-
-(defun dun-batch-loop ()
- (setq dun-dead nil)
- (setq room 0)
- (while (not dun-dead)
- (if (eq dungeon-mode 'dungeon)
- (progn
- (if (not (= room dun-current-room))
- (progn
- (dun-describe-room dun-current-room)
- (setq room dun-current-room)))
- (dun-mprinc ">")
- (setq line (downcase (dun-read-line)))
- (if (eq (dun-vparse dun-ignore dun-verblist line) -1)
- (dun-mprinc "I don't understand that.\n"))))))
-
-(defun dun-batch-dos-interface ()
- (dun-dos-boot-msg)
- (setq dungeon-mode 'dos)
- (while (eq dungeon-mode 'dos)
- (dun-dos-prompt)
- (setq line (downcase (dun-read-line)))
- (if (eq (dun-parse2 nil dun-dos-verbs line) -1)
- (progn
- (sleep-for 1)
- (dun-mprincl "Bad command or file name"))))
- (goto-char (point-max))
- (dun-mprinc "\n"))
-
-(defun dun-batch-unix-interface ()
- (dun-login)
- (if dun-logged-in
- (progn
- (setq dungeon-mode 'unix)
- (while (eq dungeon-mode 'unix)
- (dun-mprinc "$ ")
- (setq line (downcase (dun-read-line)))
- (if (eq (dun-parse2 nil dun-unix-verbs line) -1)
- (let (esign)
- (if (setq esign (string-match "=" line))
- (dun-doassign line esign)
- (dun-mprinc (car line-list))
- (dun-mprincl ": not found.")))))
- (goto-char (point-max))
- (dun-mprinc "\n"))))
-
-(defun dungeon-nil (arg)
- "noop"
- (interactive "*p"))
-
-(defun dun-batch-dungeon ()
- (load "dun-batch")
- (setq dun-visited '(27))
- (dun-mprinc "\n")
- (dun-batch-loop))
-
-(unless (not noninteractive)
- (fset 'dun-mprinc 'dun-batch-mprinc)
- (fset 'dun-mprincl 'dun-batch-mprincl)
- (fset 'dun-vparse 'dun-batch-parse)
- (fset 'dun-parse2 'dun-batch-parse2)
- (fset 'dun-read-line 'dun-batch-read-line)
- (fset 'dun-dos-interface 'dun-batch-dos-interface)
- (fset 'dun-unix-interface 'dun-batch-unix-interface)
- (dun-mprinc "\n")
- (setq dun-batch-mode t)
- (dun-batch-loop))
-
-
diff --git a/lisp/play/gomoku.el b/lisp/play/gomoku.el
deleted file mode 100644
index 332d1cedd9c..00000000000
--- a/lisp/play/gomoku.el
+++ /dev/null
@@ -1,1182 +0,0 @@
-;;; gomoku.el --- Gomoku game between you and Emacs
-
-;; Copyright (C) 1988, 1994, 1996 Free Software Foundation, Inc.
-
-;; Author: Philippe Schnoebelen <phs@lifia.imag.fr>
-;; Adapted-By: ESR, Daniel.Pfeiffer@Informatik.START.dbp.de
-;; Keywords: games
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; 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 :-).
-
-
-;; 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:
-;;
-;; The command "M-x gomoku" displays 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.
-
-;;; Code:
-
-;;;
-;;; 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.
- (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" 'backward-char) ; h
- (define-key gomoku-mode-map "l" 'forward-char) ; 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 [kp-7] 'gomoku-move-nw)
- (define-key gomoku-mode-map [kp-9] 'gomoku-move-ne)
- (define-key gomoku-mode-map [kp-1] 'gomoku-move-sw)
- (define-key gomoku-mode-map [kp-3] 'gomoku-move-se)
- (define-key gomoku-mode-map [kp-4] 'backward-char)
- (define-key gomoku-mode-map [kp-6] 'forward-char)
- (define-key gomoku-mode-map [kp-2] 'gomoku-move-down)
- (define-key gomoku-mode-map [kp-8] 'gomoku-move-up)
-
- (define-key gomoku-mode-map "\C-n" 'gomoku-move-down) ; C-n
- (define-key gomoku-mode-map "\C-p" 'gomoku-move-up) ; C-p
-
- ;; Key bindings for entering Human moves.
- (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 " " 'gomoku-human-plays) ; SPC
- (define-key gomoku-mode-map "\C-m" 'gomoku-human-plays) ; RET
- (define-key gomoku-mode-map "\C-c\C-p" 'gomoku-human-plays) ; C-c C-p
- (define-key gomoku-mode-map "\C-c\C-b" 'gomoku-human-takes-back) ; C-c C-b
- (define-key gomoku-mode-map "\C-c\C-r" 'gomoku-human-resigns) ; C-c C-r
- (define-key gomoku-mode-map "\C-c\C-e" 'gomoku-emacs-plays) ; C-c C-e
-
- (define-key gomoku-mode-map [kp-enter] 'gomoku-human-plays)
- (define-key gomoku-mode-map [insert] 'gomoku-human-plays)
- (define-key gomoku-mode-map [down-mouse-1] 'gomoku-click)
- (define-key gomoku-mode-map [drag-mouse-1] 'gomoku-click)
- (define-key gomoku-mode-map [mouse-1] 'gomoku-click)
- (define-key gomoku-mode-map [down-mouse-2] 'gomoku-click)
- (define-key gomoku-mode-map [mouse-2] 'gomoku-mouse-play)
- (define-key gomoku-mode-map [drag-mouse-2] 'gomoku-mouse-play)
-
- (substitute-key-definition 'previous-line 'gomoku-move-up
- gomoku-mode-map (current-global-map))
- (substitute-key-definition 'next-line 'gomoku-move-down
- gomoku-mode-map (current-global-map))
- (substitute-key-definition 'beginning-of-line 'gomoku-beginning-of-line
- gomoku-mode-map (current-global-map))
- (substitute-key-definition 'end-of-line 'gomoku-end-of-line
- gomoku-mode-map (current-global-map))
- (substitute-key-definition 'undo 'gomoku-human-takes-back
- gomoku-mode-map (current-global-map))
- (substitute-key-definition 'advertised-undo 'gomoku-human-takes-back
- gomoku-mode-map (current-global-map)))
-
-(defvar gomoku-emacs-won ()
- "*For making font-lock use the winner's face for the line.")
-
-(defvar gomoku-font-lock-O-face
- (if window-system
- (list (facemenu-get-face 'fg:red) 'bold))
- "*Face to use for Emacs' O.")
-
-(defvar gomoku-font-lock-X-face
- (if window-system
- (list (facemenu-get-face 'fg:green) 'bold))
- "*Face to use for your X.")
-
-(defvar gomoku-font-lock-keywords
- '(("O" . gomoku-font-lock-O-face)
- ("X" . gomoku-font-lock-X-face)
- ("[-|/\\]" 0 (if gomoku-emacs-won
- gomoku-font-lock-O-face
- gomoku-font-lock-X-face)))
- "*Font lock rules for Gomoku.")
-
-(put 'gomoku-mode 'front-sticky
- (put 'gomoku-mode 'rear-nonsticky '(intangible)))
-(put 'gomoku-mode 'intangible 1)
-
-(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. One interesting value is `turn-on-font-lock'."
- (interactive)
- (setq major-mode 'gomoku-mode
- mode-name "Gomoku")
- (gomoku-display-statistics)
- (use-local-map gomoku-mode-map)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(gomoku-font-lock-keywords t))
- (toggle-read-only t)
- (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 chose values 0, 1 and 6 to denote empty, X and O squares, the
-;; contents of a qtuple are 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))
- ((zerop (random (setq count (1+ count))))
- (setq best-square square
- score-max score)))
- (setq square (1+ square))) ; try next square
- best-square))
-
-;;;
-;;; 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-emacs-won nil
- 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-emacs-wins 0
- "Number of games Emacs won in this session.")
-
-(defvar gomoku-number-of-human-wins 0
- "Number of games you won 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."
- (message
- (cond
- ((eq result 'emacs-won)
- (setq gomoku-number-of-emacs-wins (1+ gomoku-number-of-emacs-wins))
- (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-human-wins)
- (zerop gomoku-number-of-draws)
- (> gomoku-number-of-emacs-wins 1))
- "I'm becoming tired of winning...")
- ("I won.")))
- ((eq result 'human-won)
- (setq gomoku-number-of-human-wins (1+ gomoku-number-of-human-wins))
- (concat "OK, you won this one."
- (cond
- (gomoku-human-took-back
- " I, for one, never take my moves back...")
- (gomoku-emacs-played-first
- ".. so what ?")
- (" Now, let me play first just once."))))
- ((eq result 'human-resigned)
- (setq gomoku-number-of-emacs-wins (1+ gomoku-number-of-emacs-wins))
- "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))
- (concat "This is a draw. "
- (cond
- (gomoku-human-took-back
- "I, for one, never take my moves back...")
- (gomoku-emacs-played-first
- "Just chance, I guess.")
- ("Now, let me play first just once."))))
- ((eq result 'draw-agreed)
- (setq gomoku-number-of-draws (1+ gomoku-number-of-draws))
- (concat "Draw agreed. "
- (cond
- (gomoku-human-took-back
- "I, for one, never take my moves back...")
- (gomoku-emacs-played-first
- "You were lucky.")
- ("Now, let me play first just once."))))
- ((eq result 'crash-game)
- "Sorry, I have been interrupted and cannot resume that game...")))
- (gomoku-display-statistics)
- ;;(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.
-;;;
-
-;;;###autoload
-(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.
-If prefix arg is given for N, M is prompted for.
-
-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 (if current-prefix-arg
- (list (prefix-numeric-value current-prefix-arg)
- (eval (read-minibuffer "Height: ")))))
- (gomoku-switch-to-window)
- (cond
- (gomoku-emacs-is-computing
- (gomoku-crash-game))
- ((or (not gomoku-game-in-progress)
- (<= gomoku-number-of-moves 2))
- (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 (eq m gomoku-saved-board-height))
- ;; Use EQ 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)
- (setq gomoku-emacs-won t) ; for font-lock
- (gomoku-find-filled-qtuple square 6)
- (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)))))))))
-
-;; For small square dimensions this is approximate, since though measured in
-;; pixels, event's (X . Y) is a character's top-left corner.
-(defun gomoku-click (click)
- "Position at the square where you click."
- (interactive "e")
- (and (windowp (posn-window (setq click (event-end click))))
- (numberp (posn-point click))
- (select-window (posn-window click))
- (setq click (posn-col-row click))
- (gomoku-goto-xy
- (min (max (/ (+ (- (car click)
- gomoku-x-offset
- 1)
- (window-hscroll)
- gomoku-square-width
- (% gomoku-square-width 2)
- (/ gomoku-square-width 2))
- gomoku-square-width)
- 1)
- gomoku-board-width)
- (min (max (/ (+ (- (cdr click)
- gomoku-y-offset
- 1)
- (let ((inhibit-point-motion-hooks t))
- (count-lines 1 (window-start)))
- gomoku-square-height
- (% gomoku-square-height 2)
- (/ gomoku-square-height 2))
- gomoku-square-height)
- 1)
- gomoku-board-height))))
-
-(defun gomoku-mouse-play (click)
- "Play at the square where you click."
- (interactive "e")
- (if (gomoku-click click)
- (gomoku-human-plays)))
-
-(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-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 ")
- (not (setq gomoku-human-refused-draw t))))
-
-;;;
-;;; 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-y ()
- "Return the board row where point is."
- (let ((inhibit-point-motion-hooks t))
- (1+ (/ (- (count-lines 1 (point)) gomoku-y-offset (if (bolp) 0 1))
- gomoku-square-height))))
-
-(defun gomoku-point-square ()
- "Return the index of the square point is on."
- (let ((inhibit-point-motion-hooks t))
- (gomoku-xy-to-index (1+ (/ (- (current-column) gomoku-x-offset)
- gomoku-square-width))
- (gomoku-point-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."
- (let ((inhibit-point-motion-hooks t))
- (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."
- (or (= value 1)
- (gomoku-goto-square square))
- (let ((inhibit-read-only t)
- (inhibit-point-motion-hooks t))
- (insert-and-inherit (cond ((= value 1) ?X)
- ((= value 6) ?O)
- (?.)))
- (and window-system
- (zerop value)
- (put-text-property (1- (point)) (point) 'mouse-face 'highlight))
- (delete-char 1)
- (backward-char 1))
- (sit-for 0)) ; Display NOW
-
-(defun gomoku-init-display (n m)
- "Display an N by M Gomoku board."
- (buffer-disable-undo (current-buffer))
- (let ((inhibit-read-only t)
- (point 1) opoint
- (intangible t)
- (i m) j x)
- ;; Try to minimize number of chars (because of text properties)
- (setq tab-width
- (if (zerop (% gomoku-x-offset gomoku-square-width))
- gomoku-square-width
- (max (/ (+ (% gomoku-x-offset gomoku-square-width)
- gomoku-square-width 1) 2) 2)))
- (erase-buffer)
- (newline gomoku-y-offset)
- (while (progn
- (setq j n
- x (- gomoku-x-offset gomoku-square-width))
- (while (>= (setq j (1- j)) 0)
- (insert-char ?\t (/ (- (setq x (+ x gomoku-square-width))
- (current-column))
- tab-width))
- (insert-char ? (- x (current-column)))
- (if (setq intangible (not intangible))
- (put-text-property point (point) 'intangible 2))
- (and (zerop j)
- (= i (- m 2))
- (progn
- (while (>= i 3)
- (append-to-buffer (current-buffer) opoint (point))
- (setq i (- i 2)))
- (goto-char (point-max))))
- (setq point (point))
- (insert ?.)
- (if window-system
- (put-text-property point (point)
- 'mouse-face 'highlight)))
- (> (setq i (1- i)) 0))
- (if (= i (1- m))
- (setq opoint point))
- (insert-char ?\n gomoku-square-height))
- (or (eq (char-after 1) ?.)
- (put-text-property 1 2 'point-entered
- (lambda (x x) (if (bobp) (forward-char)))))
- (or intangible
- (put-text-property point (point) 'intangible 2))
- (put-text-property point (point) 'point-entered
- (lambda (x x) (if (eobp) (backward-char))))
- (put-text-property (point-min) (point) 'category 'gomoku-mode))
- (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
- (format ": Won %d, lost %d%s"
- gomoku-number-of-human-wins
- gomoku-number-of-emacs-wins
- (if (zerop gomoku-number-of-draws)
- ""
- (format ", drew %d" gomoku-number-of-draws))))
- (force-mode-line-update))
-
-(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.
-
-(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."
- (let ((a 0) (b 0)
- (left square) (right square)
- (depl (gomoku-xy-to-index dx dy)))
- (while (and (> a -4) ; stretch tuple left
- (= value (aref gomoku-board (setq left (- left depl)))))
- (setq a (1- a)))
- (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 ?
- (gomoku-cross-qtuple (+ square (* a depl)) (+ square (* b depl))
- dx dy)
- t))))
-
-(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))
- (inhibit-read-only t)
- (inhibit-point-motion-hooks t))
- ;; WARNING: this function assumes DEPL > 0 and SQUARE2 > SQUARE1
- (while (/= square1 square2)
- (gomoku-goto-square square1)
- (setq square1 (+ square1 depl))
- (cond
- ((= dy 0) ; Horizontal
- (forward-char 1)
- (insert-char ?- (1- gomoku-square-width) t)
- (delete-region (point) (progn
- (skip-chars-forward " \t")
- (point))))
- ((= dx 0) ; Vertical
- (let ((n 1)
- (column (current-column)))
- (while (< n gomoku-square-height)
- (setq n (1+ n))
- (forward-line 1)
- (indent-to column)
- (insert-and-inherit ?|))))
- ((= dx -1) ; 1st Diagonal
- (indent-to (prog1 (- (current-column) (/ gomoku-square-width 2))
- (forward-line (/ gomoku-square-height 2))))
- (insert-and-inherit ?/))
- (t ; 2nd Diagonal
- (indent-to (prog1 (+ (current-column) (/ gomoku-square-width 2))
- (forward-line (/ gomoku-square-height 2))))
- (insert-and-inherit ?\\))))))
- (sit-for 0)) ; Display NOW
-
-;;;
-;;; CURSOR MOTION.
-;;;
-;; previous-line and next-line don't work right with intangible newlines
-(defun gomoku-move-down ()
- "Move point down one row on the Gomoku board."
- (interactive)
- (if (< (gomoku-point-y) gomoku-board-height)
- (next-line gomoku-square-height)))
-
-(defun gomoku-move-up ()
- "Move point up one row on the Gomoku board."
- (interactive)
- (if (> (gomoku-point-y) 1)
- (previous-line gomoku-square-height)))
-
-(defun gomoku-move-ne ()
- "Move point North East on the Gomoku board."
- (interactive)
- (gomoku-move-up)
- (forward-char))
-
-(defun gomoku-move-se ()
- "Move point South East on the Gomoku board."
- (interactive)
- (gomoku-move-down)
- (forward-char))
-
-(defun gomoku-move-nw ()
- "Move point North West on the Gomoku board."
- (interactive)
- (gomoku-move-up)
- (backward-char))
-
-(defun gomoku-move-sw ()
- "Move point South West on the Gomoku board."
- (interactive)
- (gomoku-move-down)
- (backward-char))
-
-(defun gomoku-beginning-of-line ()
- "Move point to first square on the Gomoku board row."
- (interactive)
- (move-to-column gomoku-x-offset))
-
-(defun gomoku-end-of-line ()
- "Move point to last square on the Gomoku board row."
- (interactive)
- (move-to-column (+ gomoku-x-offset
- (* gomoku-square-width (1- gomoku-board-width)))))
-
-(provide 'gomoku)
-
-;;; gomoku.el ends here
diff --git a/lisp/play/handwrite.el b/lisp/play/handwrite.el
deleted file mode 100644
index 766ba6a02c6..00000000000
--- a/lisp/play/handwrite.el
+++ /dev/null
@@ -1,1376 +0,0 @@
-;;; handwrite.el --- turns your emacs buffer into a handwritten document.
-;;
-;; (C) Copyright 1996 Free Software Foundation, Inc.
-;;
-;; Author: Danny Roozendaal (danny@tvs.kun.nl)
-;; Created: October 21 1996
-;; Keywords: cursive writing
-;;
-;; This file is part of GNU Emacs.
-;;
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-;;
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-;;
-;;; Commentary:
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; The function handwrite creates PostScript output containing a
-;; handwritten version of the current buffer..
-;; Other functions that may be useful are
-;;
-;; handwrite-10pt: sets the font size to 10 and finds corresponding
-;; values for the line spacing and the number of lines
-;; on a page.
-;; handwrite-11pt: which is similar
-;; handwrite-12pt: which is also similar
-;; handwrite-13pt: which is similar, too
-;;
-;; handwrite-set-pagenumber: set and unset page numbering
-;;
-;;
-;; If you are not satisfied with the type page there are a number of
-;; variables you may want to set.
-;;
-;;
-;; Installation
-;;
-;; type at your prompt "emacs -l handwrite.el" or put this file on your
-;; Emacs-Lisp load path, add the following into your ~/.emacs startup file
-;;
-;; (require 'handwrite)
-;;
-;; "M-x handwrite" or "Write by hand" in the edit menu should work now.
-;;
-;;
-;; I tried to make it `iso_8859_1'-friendly, but there are some exotic
-;; characters missing.
-;;
-;;
-;; Known bugs: -Page feeds do not do their work, but are ignored instead.
-;; -Tabs are not always properly displayed.
-;; -Handwrite may create corrupt PostScript if it encounters
-;; unknown characters.
-;;
-;; Thanks to anyone who emailed me suggestions!
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-;;; Code:
-
-
-;; Variables
-
-(defvar handwrite-psindex 0
- "The index of the PostScript buffer")
-(defvar menu-bar-handwrite-map (make-sparse-keymap "Handwrite functions."))
-(fset 'menu-bar-handwrite-map (symbol-value 'menu-bar-handwrite-map))
-
-
-;; User definable variables
-
-(defvar handwrite-numlines 60
- "*The number of lines on a page of the PostScript output")
-(defvar handwrite-fontsize 11
- "*The size of the font for the PostScript output")
-(defvar handwrite-linespace 12
- "*The spacing for the PostScript output")
-(defvar handwrite-xstart 30
- "*Translation in the x-direction of the origin in the PostScript output")
-(defvar handwrite-ystart 810
- "*Translation in the y-direction of the origin in the PostScript output")
-(defvar handwrite-pagenumbering nil
- "*If t then number each page of the PostScript output")
-(defvar handwrite-10pt-numlines 65
- "*The number of lines on a page for the function handwrite-10pt")
-(defvar handwrite-11pt-numlines 60
- "*The number of lines on a page for the function handwrite-11pt")
-(defvar handwrite-12pt-numlines 55
- "*The number of lines on a page for the function handwrite-12pt")
-(defvar handwrite-13pt-numlines 50
- "*The number of lines on a page for the function handwrite-13pt")
-
-
-;; Interactive functions
-
-(defun handwrite ()
- "Turns the buffer into a handwritten document.
-Variables: handwrite-linespace (default 12)
- handwrite-fontsize (default 11)
- handwrite-numlines (default 60)
- handwrite-pagenumbering (default nil)"
- (interactive)
- (let
- ((pmin) ; thanks, Havard
- (lastp)
- (cur-buf (current-buffer))
- (tpoint (point))
- (ps-ypos 63)
- (lcount 0)
- (ipage 1)
- (nlan next-line-add-newlines) ;remember the old value
- (buf-name (buffer-name) )
- (textp)
- (ps-buf-name) ;name of the PostScript buffer
- )
- (goto-char (point-min)) ;start at beginning
- (setq handwrite-psindex (1+ handwrite-psindex))
- (setq ps-buf-name
- (format "*handwritten%d.ps*" handwrite-psindex))
- (setq next-line-add-newlines t)
- (switch-to-buffer ps-buf-name)
- (handwrite-insert-header buf-name)
- (insert "\n(\\nCreated by Gnu Emacs' handwrite version "
- emacs-version "\\n\\n)=print flush\n")
- (handwrite-insert-preamble)
- (handwrite-insert-info)
- (handwrite-insert-font)
- (setq textp (point))
- (insert "%%Page: 1 1\n")
- (insert "Hwjst\n")
- (insert "/Hwsave save def\n")
- (if handwrite-pagenumbering (insert "20 30 m\nxym(page 1)a\n"))
- (insert "44 63 m\n")
- (insert "xym( )a")
- (backward-char 3)
- (switch-to-buffer cur-buf)
- (goto-char (point-min)) ;start at beginning
- (save-excursion
- ;;as long as we see a newline the document is not ended.
- (while (re-search-forward "\n" nil t)
- (previous-line 1)
- (beginning-of-line)
- (setq pmin (point))
- (search-forward "\n" nil t)
- (backward-char 1)
- (copy-region-as-kill (point) pmin)
- (forward-char 1)
- (switch-to-buffer ps-buf-name)
- (yank)
- (message "write write write...")
- (search-forward ")a" nil t)
- (backward-char 2)
- (setq lastp (point))
- (beginning-of-line)
- (search-forward "(" nil t)
- (while (re-search-forward "[()\\]" lastp t)
- (save-excursion
- (setq lastp (+ lastp 1))
- (forward-char -1)
- (insert "\\")))
- (setq ps-ypos (+ ps-ypos handwrite-linespace))
- (end-of-line)
- (insert "\n")
- (setq lcount (+ lcount 1))
- (cond ( (eq lcount handwrite-numlines)
- (setq ipage (+ ipage 1))
- (insert "0 0 m\n")
- (insert "showpage exec Hwsave restore\n")
- (insert "%%Page: " (number-to-string ipage) " "
- (number-to-string ipage) "\n")
- (insert "Hwjst\n")
- (insert "/Hwsave save def\n")
- (if handwrite-pagenumbering
- (insert "20 30 m\nxym(page "
- (number-to-string ipage) ")a\n"))
- (setq ps-ypos 63)
- (setq lcount 0)
- ))
- (insert "44 "(number-to-string ps-ypos) " m\n")
- (insert "xym( )a")
- (backward-char 3)
- (switch-to-buffer cur-buf)
- ))
- (switch-to-buffer ps-buf-name)
- (next-line 1)
- (insert "showpage exec Hwsave restore\n\n")
- (insert "%%Pages " (number-to-string ipage) " 0\n")
- (insert "%%EOF\n")
- (goto-char textp) ;start where the inserted text begins
- (while (search-forward "ÿ" nil t)
- (replace-match "\\" nil t) (insert "264"))
- (goto-char textp)
- (while (search-forward "á" nil t)
- (replace-match "\\" nil t) (insert "207"))
- (goto-char textp)
- (while (search-forward "à" nil t)
- (replace-match "\\" nil t) (insert "210"))
- (goto-char textp)
- (while (search-forward "â" nil t)
- (replace-match "\\" nil t) (insert "211"))
- (goto-char textp)
- (while (search-forward "ä" nil t)
- (replace-match "\\" nil t) (insert "212"))
- (goto-char textp)
- (while (search-forward "ã" nil t)
- (replace-match "\\" nil t) (insert "213"))
- (goto-char textp)
- (while (search-forward "å" nil t)
- (replace-match "\\" nil t) (insert "214"))
- (goto-char textp)
- (while (search-forward "é" nil t)
- (replace-match "\\" nil t) (insert "216"))
- (goto-char textp)
- (while (search-forward "è" nil t)
- (replace-match "\\" nil t) (insert "217"))
- (goto-char textp)
- (while (search-forward "ê" nil t)
- (replace-match "\\" nil t) (insert "220"))
- (goto-char textp)
- (while (search-forward "ë" nil t)
- (replace-match "\\" nil t) (insert "221"))
- (goto-char textp)
- (while (search-forward "í" nil t)
- (replace-match "\\" nil t) (insert "222"))
- (goto-char textp)
- (while (search-forward "ì" nil t)
- (replace-match "\\" nil t) (insert "223"))
- (goto-char textp)
- (while (search-forward "î" nil t)
- (replace-match "\\" nil t) (insert "224"))
- (goto-char textp)
- (while (search-forward "ï" nil t)
- (replace-match "\\" nil t) (insert "225"))
- (goto-char textp)
- (while (search-forward "ó" nil t)
- (replace-match "\\" nil t) (insert "227"))
- (goto-char textp)
- (while (search-forward "ò" nil t)
- (replace-match "\\" nil t) (insert "230"))
- (goto-char textp)
- (while (search-forward "ô" nil t)
- (replace-match "\\" nil t) (insert "231"))
- (goto-char textp)
- (while (search-forward "ö" nil t)
- (replace-match "\\" nil t) (insert "232"))
- (goto-char textp)
- (while (search-forward "õ" nil t)
- (replace-match "\\" nil t) (insert "233"))
- (goto-char textp)
- (while (search-forward "ú" nil t)
- (replace-match "\\" nil t) (insert "234"))
- (goto-char textp)
- (while (search-forward "ù" nil t)
- (replace-match "\\" nil t) (insert "235"))
- (goto-char textp)
- (while (search-forward "û" nil t)
- (replace-match "\\" nil t) (insert "236"))
- (goto-char textp)
- (while (search-forward "ü" nil t)
- (replace-match "\\" nil t) (insert "237"))
- (goto-char textp)
- (while (search-forward "ß" nil t)
- (replace-match "\\" nil t) (insert "247"))
- (goto-char textp)
- (while (search-forward "°" nil t)
- (replace-match "\\" nil t) (insert "241"))
- (goto-char textp)
- (while (search-forward "®" nil t)
- (replace-match "\\" nil t) (insert "250"))
- (goto-char textp)
- (while (search-forward "©" nil t)
- (replace-match "\\" nil t) (insert "251"))
- (goto-char textp)
- (while (search-forward "ij" nil t)
- (replace-match "\\" nil t) (insert "264"))
- (goto-char textp)
- (while (search-forward "ç" nil t)
- (replace-match "\\" nil t) (insert "215"))
- (goto-char textp)
- (while (search-forward "§" nil t)
- (replace-match "\\" nil t) (insert "244"))
- (goto-char textp)
- (while (search-forward "ñ" nil t)
- (replace-match "\\" nil t) (insert "226"))
- (goto-char textp)
- (while (search-forward "£" nil t)
- (replace-match "\\" nil t) (insert "243"))
- ;;To avoid cumbersome code we simply ignore pagefeeds
- (goto-char textp)
- (while (search-forward "\f" nil t)
- (replace-match "" nil t) )
- (untabify textp (point-max)) ; this may result in strange tabs
- (if (y-or-n-p "Send this to the printer? ")
- (call-process-region (point-min)
- (point-max) lpr-command nil nil nil))
- (message "")
- (bury-buffer ())
- (switch-to-buffer cur-buf)
- (goto-char tpoint)
- (setq next-line-add-newlines nlan)
- ))
-
-
-(defun handwrite-set-pagenumber ()
- "Toggle the value of handwrite-pagenumbering"
- (interactive)
- (if handwrite-pagenumbering
- (handwrite-set-pagenumber-off)(handwrite-set-pagenumber-on)))
-
-(defun handwrite-10pt ()
- "Sets the variable `handwrite-fontsize' to 10 and finds correct
-values for `handwrite-linespace' and `handwrite-numlines'"
- (interactive)
- (setq handwrite-fontsize 10)
- (setq handwrite-linespace 11)
- (setq handwrite-numlines handwrite-10pt-numlines)
- (define-key menu-bar-handwrite-map [10pt]
- '("10 pt *" . handwrite-10pt))
- (define-key menu-bar-handwrite-map [11pt]
- '("11 pt" . handwrite-11pt))
- (define-key menu-bar-handwrite-map [12pt]
- '("12 pt" . handwrite-12pt))
- (define-key menu-bar-handwrite-map [13pt]
- '("13 pt" . handwrite-13pt))
- (message "Joepie set to 10 points"))
-
-
-(defun handwrite-11pt ()
- "Sets the variable `handwrite-fontsize' to 11 and finds correct
-values for `handwrite-linespace' and `handwrite-numlines'"
- (interactive)
- (setq handwrite-fontsize 11)
- (setq handwrite-linespace 12)
- (setq handwrite-numlines handwrite-11pt-numlines )
- (define-key menu-bar-handwrite-map [10pt]
- '("10 pt" . handwrite-10pt))
- (define-key menu-bar-handwrite-map [11pt]
- '("11 pt *" . handwrite-11pt))
- (define-key menu-bar-handwrite-map [12pt]
- '("12 pt" . handwrite-12pt))
- (define-key menu-bar-handwrite-map [13pt]
- '("13 pt" . handwrite-13pt))
- (message "Joepie set to 11 points"))
-
-(defun handwrite-12pt ()
- "Sets the variable `handwrite-fontsize' to 12 and finds correct
-values for `handwrite-linespace' and `handwrite-numlines'"
- (interactive)
- (setq handwrite-fontsize 12)
- (setq handwrite-linespace 13)
- (setq handwrite-numlines handwrite-12pt-numlines)
- (define-key menu-bar-handwrite-map [10pt]
- '("10 pt" . handwrite-10pt))
- (define-key menu-bar-handwrite-map [11pt]
- '("11 pt" . handwrite-11pt))
- (define-key menu-bar-handwrite-map [12pt]
- '("12 pt *" . handwrite-12pt))
- (define-key menu-bar-handwrite-map [13pt]
- '("13 pt" . handwrite-13pt))
- (message "Joepie set to 12 points"))
-
-(defun handwrite-13pt ()
- "Sets the variable `handwrite-fontsize' to 13 and finds correct
-values for `handwrite-linespace' and `handwrite-numlines'"
- (interactive)
- (setq handwrite-fontsize 13)
- (setq handwrite-linespace 14)
- (setq handwrite-numlines handwrite-13pt-numlines)
- (define-key menu-bar-handwrite-map [10pt]
- '("10 pt" . handwrite-10pt))
- (define-key menu-bar-handwrite-map [11pt]
- '("11 pt" . handwrite-11pt))
- (define-key menu-bar-handwrite-map [12pt]
- '("12 pt" . handwrite-12pt))
- (define-key menu-bar-handwrite-map [13pt]
- '("13 pt *" . handwrite-13pt))
- (message "Joepie set to 13 points"))
-
-
-;; Internal Functions
-
-;;The header for the PostScript output. The argument is the name of
-;;the original buffer
-(defun handwrite-insert-header (buf-name)
- (insert "%!PS-Adobe-2.0\n")
- (insert "%%Title: " buf-name "\n")
- (insert "%%CreationDate: " (current-time-string) "\n" )
- (insert "%%Pages: (atend)\n")
- (insert "%%For: " user-mail-address "\n")
- (insert "%%EndComments\n"))
-
-;;Some PostScript definitions for using our font.
-(defun handwrite-insert-preamble ()
- (insert "\n%%BeginPreamble
-/m {moveto} def
-/r {roll} def
-/e {exch} def
-/a {awidthshow} def
-/xym {0.52490 0. 32 0.05249 0.} def
-/HwJdict 80 dict def
-/Hwfdict 80 dict def
-/getsymb {Hwfdict /Jsymb get 3 1 r put} def
-/Chread{
- { e begin
- HwJdict begin %read in character specifications
- /jnum e def
- /jnum1 jnum 6 mul def
- save symbstr jnum1 6 getinterval{
- }forall
- /pixvol e def
- /pixwid e def
- /charwidth e def
- /trx e def
- /try e def
- /pixf e def
- .02666667 .02666667 scale
- /pixwid pixwid 1.042 mul def
- /pixwidn pixwid trx add def
- /pixvoln pixvol try add def
- charwidth 0 trx try pixwidn pixvoln setcachedevice
- newpath 0 0 m
- pixf 0 gt{
- pixf 3 bitshift
- trx try translate
- pixwid pixvol scale
- /pixvol1 {pixvol 4 add true} def
- /pixvol2 pixvol neg def
- /pixvol3 pixvol 2 add def
- pixvol1 pixwid 0 0 pixvol2 0 pixvol3 6 array astore
- Jsymb jnum get
- imagemask
- }if
- restore
- end
- end
- }def
-}def
-/Hwjst{
- /Joepie findfont [Hws 0 Hws pop 0 Hws neg 0 0] makefont setfont
-}def
-%%EndPreamble\n"))
-
-;;The the font size for the PostScript output.
-;;Also the x-y-translations of the PostScript stuff.
-(defun handwrite-insert-info ()
- (insert "\n%%BeginSizeTranslate\n")
- (insert "/Hws " (number-to-string handwrite-fontsize) " def")
- (insert " %The size of the font\n")
- (insert (number-to-string handwrite-xstart)" "
- (number-to-string handwrite-ystart))
- (insert " translate %Translate the origin to the current location\n")
- (insert "1 -1 scale %Flip the y coordinate\n")
- (insert "%%EndSizeTranslate\n\n"))
-
-
-;;Bitmap PostScript font for pseudo handwritten documents.
-;;Two years ago, I created the 36 points font for my
-;;Apple Macintosh Classic II resulting in unusual ascii numbers.
-(defun handwrite-insert-font ()
- (insert "\n%%BeginFont Joepie
-Hwfdict begin
- /Jsymb 256 array def
- /FontType 3 def
- /FontBBox [0 0 1 1] def
- /FontMatrix [1 0 0 1 0 0] def
- /Encoding 256 array def
-end
-<002809000000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000
-FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 002809080000
-FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 002809000000 FF28FFFF0000
-FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000
-FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000
-FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000
-FF28FFFF0000 FF28FFFF0000 002809080000 020A0E08031E 021C0B0E0A0A
-040C09161418 04050A121323 040D0F1C141B 040C141C0F19 021B0B08060D
-02080B0C091E 0208080C0B20 041A0B100F0C 040E09141314 02060B08060B
-0219090C0C03 020C0B080304 04090C120F1F 04080A121017 020C10120514
-040A09121216 040C09121216 02090B120D15 040C0B121015 040A0A12121B
-020209120D1D 040A09121018 04040A12101C 020C0D080412 020408080717
-040B0B141116 040C0B16140B 040B0B141018 020A0D120C1C 04090B1C191F
-040A091A1C1C 0408071A1E20 040A0B1A1A1E 040E0D201E1A 040C0916181C
-040E0916171A 04010B1C1C27 060A0C20201E 040E060E141A 0401070E1327
-040E0A1C1D1A 040C0916181C 060C07262B1C 060C0520261C 04080D1E1C20
-040A05161C1C 040A0B1E1E1E 040A091A1D1E 040C0914171C 040E07161A1A
-060E091E1F1A 040E071A1D1A 060A0B2C2C1E 040808181B20 040409161722
-040C08181A1C 020A080A0A1D 040A0610121E 0208090A0A1F 041C0714160A
-040505161903 021B0C0C060D 040C08141713 040C0916181C 040C08121412
-040D0916181B 040C09141615 0202090C0D26 04040814171B 040A0916181E
-020C090A0D1B 0202090A0C23 040A0814171E 020C080A0D1C 060C09222412
-040C08161910 040C08141611 04000816191C 04020914171B 040A090E1014
-040A09101213 040C090C0F1B 040C09161812 040A09121412 040C09181A10
-040C08121511 04020812151C 040C08101312 040A050A0F1E 020A1114031C
-0208070A0E20 04140A141409 FF28FFFF0000 040A071A1B1C 040A091A181C
-040A0B1A171E 020F0F160E16 040A0F201A1E 04080D1E1A20 040E0B1E1D1A
-040C0814171B 040D0714171B 040D0714171A 040D0814171A 040D0814171B
-040D0814171B 04000912141C 040C0914151C 040C0914161C 040C0914151C
-040C0914151B 020B070A0D1C 020B070A0D1C 020B080A0D1C 020B070A0D1A
-040C0616191A 040B0714171D 040B08141719 040B0814171A 040B08141718
-040B08141718 040B0716191B 040B0716191B 040B0716191C 040B08161919
-040A0912111C 02180C0E090C 04050712141F 040A0816151C 04080A121220
-020F0A120E10 040408181522 04040816191D 040A0D201A1E 040A09201C1C
-06190B24210E 021C0B0C0708 0221090E0D03 040809141415 040C121E1619
-04080F1E1920 04130F1A1309 040C0B141216 04090914141E 040A0914131B
-040209161823 04030A161519 020B0B120E19 0407091A1921 040A0B1E141E
-040C0914140F 0401090C0F25 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000
-FF28FFFF0000 040A0B14121A 04010910101B FF28FFFF0000 040A0614181C
-040A09141618 0407090E1221 040D0A141510 002800160000 04080A141119
-04080614151A 040A0B1E1804 FF28FFFF0000 040A071A1B1D 040A071A191D
-FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 041408141303 061409262404
-041A0B120F0B 021D0B120D0A 021E0E0A050A 021E0B0A060A FF28FFFF0000
-FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 040600060F1C FF28FFFF0000
-020C0A0C0B16 020D080C0C17 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000
-02140B0A0506 02040908060E FF28FFFF0000 0608092A291E FF28FFFF0000
-FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000
-FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000
-040A0B1C181B 060C071E221C FF28FFFF0000 FF28FFFF0000 FF28FFFF0000
-FF28FFFF0000 021D0C0E0C08 021E090E0C06 0421060E1105 FF28FFFF0000
-021F0A0A0506 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000 FF28FFFF0000
-041E09101107>
-Hwfdict begin /symbstr e def end
-255< 00000000 00000000 80018000 60030000 38060000 0E1C0000 03F00000
-01C00000 01800000 00000000 00000000>getsymb
-250< 0000 0000 6000 7800 7800 F800 F800 7000 0000 0000>getsymb
-248< 00000000 00000000 F8000000 3F800000 03F80000 007E0000 00038000
-00000000 00000000 >getsymb
-247< 0000 0000 0030 0060 38E0 7FC0 C300 8000 0000 0000 >getsymb
-246< 0000 0000 0C00 1E00 3F00 3380 60C0 4040 C020 0010 0000 0000
->getsymb
-241< 000000000000 000000000000 008000000000 00C000000000 03C000000000
-038000000000 000000000000 000000000000 000000000000 000000000000
-010000000000 010000000000 010007C00000 03001FE00000 070038700000
-070030300000 0F0060300000 1B00C0700000 3300C0600000 6300C0C0C000
-C300C3818000 030046030000 03007C020000 0300F0060000 0180F00C0000
-018198180000 01C30C300000 00CE06300000 00FC03E00000 007801C00000
-000000000000 000000000000 >getsymb
-240< 00000000 00000000 00004000 0003C000 00038000 000E0000 000C0000
-00080000 00180000 0E187C00 1F98FC00 3FDCFF00 3FFFFF00 7FFFFE00
-7FFFFC00 FFFFF800 FFFFF000 FFFFF000 FFFFF000 FFFFF000 FFFFF000
-FFFFFC00 7FFFFC00 7FFFFF00 3FFFFF00 1FFFFE00 0FFFFE00 07FFF800
-03F3F000 00000000 00000000 >getsymb
-228< 000000000000 000000000000 03C010000000 07C0F0000000 1C7330000000
-383F20000000 303040000000 2030C0000000 6030C0000000 C01080000000
-C01180000000 C03100000000 406300000000 604200000000 60C40E000080
-71843F01E080 3F0CE183B180 1E0880CE1F00 001180FA0600 003100460600
-0023004C0200 0047004C0300 004B004C0300 00B300CC0300 00E300CC0200
-01C1818C0200 03C1830C0600 0380830C0C00 0600FE061800 1C007C03F000
-180000000000 300000000000 000000000000 000000000000 >getsymb
-226< 0000 0000 2000 1800 1800 0C00 0C00 0C00 0C00 0C00 0C00 1800 1000
-3000 6000 8000 0000 0000 >getsymb
-225< 0000 0000 7000 E800 F800 F800 F000 F000 0000 0000 >getsymb
-221< 0000 0000 8000 E000 3000 1C00 0E00 0700 0380 01C0 01C0 00E0 0030
-0030 0030 0060 00C0 0180 0300 0200 0600 0C00 1800 3000 4000 0000 0000
->getsymb
-220< 0000 0000 0060 0040 00C0 0180 0300 0600 0C00 1C00 3000 7000 6000
-C000 4000 6000 3000 3000 1800 1C00 0E00 0600 0300 0100 0000 0000
->getsymb
-218< 00000000 00000000 00020000 00060000 000E0000 000C0000 000C0000
-00180000 00180000 00100000 00300000 00200000 00200000 00400000
-00C00000 00C00000 01800000 01800000 03000000 03000000 06000000
-06000000 0C000000 1C000000 18000000 38000000 30000000 70000000
-60000000 C0000000 00000000 00000000 >getsymb
-213< 0000 0000 2000 1800 0C00 0400 0400 0C00 1800 3000 6000 8000 0000
-0000 >getsymb
-212< 0000 0000 0800 3000 6000 C000 C000 C000 6000 3000 1000 0800 0000
-0000 >getsymb
-211< 0000 0000 0040 1020 0810 0C18 0C18 1818 3010 4030 8060 0040 0000
-0000 >getsymb
-210< 00000000 00000000 00060000 04180000 18300000 30600000 60C00000
-C0C00000 C0C00000 C0C00000 C0400000 40200000 20000000 00000000
-00000000 >getsymb
-209< 000000000000 000000000000 FFF000000000 0FFFC0000000 000FFFFE0000
-000007FFF000 000000000000 000000000000 >getsymb
-208< 00000000 00000000 FFC00000 7FFF8000 007FE000 00000000 00000000
->getsymb
-204< 00000000 00000000 00000200 00038C00 0007F800 001CF000 00380000
-00200000 00000000 00000000 00080000 00060000 00030000 00078000
-0007C000 000CE000 001CF000 00303000 00303E00 003FF800 00FF1800
-00400C00 00C00C00 01800600 01800600 03000300 06000300 1C000380
-30000380 60000380 E0000700 00000000 00000000 >getsymb
-203< 00000000 00000000 00300000 00180000 000E0000 00038000 0003C000
-0000E000 0000F000 00001800 00060800 00030000 00038000 00078000
-000EC000 000C6000 00182000 00302000 00703000 01FC3000 00FFF800
-01807F80 03800E00 07000200 06000200 0E000300 1C000100 38000180
-600000C0 C0000060 C0000060 00000000 00000000 >getsymb
-201< 00000000 00000000 80180600 E03C0700 E07C0700 703C0E00 00000000
-00000000 >getsymb
-200< 00000000 00000000 00100000 00180000 E00C0000 30060000 18060000
-0C070000 0E018000 0E01C000 0780C000 03806000 00E07000 00E03000
-00703800 00303800 00607000 00606000 01C0C000 0180C000 03018000
-06070000 0C060000 380C0000 30080000 00100000 00200000 00600000
-00000000 00000000 >getsymb
-199< 00000000 00000000 00010000 00620000 00C60000 018C0000 03180000
-06180000 0C300000 18600000 10600000 70C00000 60C00000 E1C00000
-61C00000 30E00000 38600000 18300000 1C100000 0E080000 070C0000
-03060000 01C30000 00C30000 00438000 00418000 00008000 00000000
-00000000 >getsymb
-197< 00000000 00000000 00003800 0000F000 0C038000 3F870000 70FE0000
-603C0000 C0000800 80001000 00003000 03802000 0FE06000 38F06000
-701CC000 600F8000 60078000 00030000 00000000 00000000 >getsymb
-196< 00000000 00000000 0001C000 001F8000 00380000 00600000 00600000
-00400000 00400000 00C00000 00C00000 00C00000 00C00000 00CC0000
-00980000 01F00000 0F800000 0D800000 01800000 01800000 01800000
-01800000 01800000 01800000 01800000 01800000 01800000 01800000
-01800000 01800000 03000000 02000000 06000000 8C000000 78000000
-00000000 00000000 >getsymb
-195< 00000000 00000000 00000400 00001800 0003F000 00078000 00060000
-00040000 000C0000 000C0000 600C0000 F00C0000 300C0000 18180000
-18180000 18180000 08100000 08300000 0C300000 0C600000 0C600000
-0C400000 0DC00000 07800000 07000000 02000000 00000000 00000000
->getsymb
-194< 00000000 00000000 03018000 0F07C000 188C6000 10C83000 20701800
-60300C00 40200600 C0200300 C0000300 C0000300 40000300 40000300
-60000300 60000600 20000C00 30000800 10001800 18003000 0C006000
-0C00C000 06018000 03070000 010C0000 00980000 00F00000 00600000
-00400000 00400000 00000000 00000000 >getsymb
-192< 00000000 00000000 00C00000 00E00000 00C00000 00000000 00000000
-00000000 00C00000 00C00000 00600000 00600000 00C00000 01800000
-03000000 06000000 1C000000 38000000 60000000 60040000 C0060000
-C0020000 C0010000 E0030000 70060000 380C0000 1C3C0000 0FF80000
-07E00000 00000000 00000000 >getsymb
-191< 00000000 00000000 06000000 1F000000 318C0000 609F0000 60B38000
-60E18000 40418000 C040C000 C000C000 C000C000 C000C000 C0018000
-40030000 60060000 600C0000 30180000 30100000 18300000 18600000
-08400000 0CC00000 0C800000 05800000 03000000 03000000 02000000
-00000000 00000000 >getsymb
-186< 00000000 00000000 00060000 001C0000 00F80000 01F00000 01800000
-03800000 03800000 07000000 07000000 07000000 07000000 07000000
-07000000 07000000 07000000 07000000 07000000 07000000 07000000
-0F000000 0F000000 0F000000 0F000000 0F000000 0F000000 0F000000
-0E000000 0E000000 0E000000 0E000000 0E000000 0E000000 0E000000
-8C000000 FC000000 F8000000 30000000 00000000 00000000 >getsymb
-185< 00000000 00000000 00004000 7C003000 FF003000 CF806000 CDC0C000
-0CFF0000 0C1F0000 0C030000 0C030000 0C030000 0C030000 0C010000
-0C018000 3800D000 30006000 00000000 00000000 >getsymb
-184< 00000000 00000000 1FC00000 7FFC0000 EE0F0000 83038000 0301C000
-0180C000 01806000 01802000 01803000 01803000 01803000 01803000
-01803000 01803000 01806000 0180E000 0181C000 018F8000 03FC0000
-0FE00000 03000000 03000000 03000000 03000000 06000000 06000000
-06000000 06000000 06000000 06000000 00000000 00000000 >getsymb
-183< 00000000 00000000 000FF800 003FFE00 00F00700 03C00180 0F000080
-07000000 03C00000 01E00000 00780000 001E0000 00070000 0001C000
-0000E000 00007000 0000F800 0001C000 00038000 00060000 000C0000
-00380000 00700000 00E00000 01C00000 03800080 0F000180 1C000180
-38000180 70000300 E0000300 FC000600 7FFC0C00 03FFF800 0003F000
-00000000 00000000 >getsymb
-182< 0000 0000 0F00 3F80 40E0 8070 0038 0018 000C 000C 000C 000C 038C
-0FEC 1C3C 301C 201C 600C 600C 600C 600C 6008 6018 6030 3060 1FC0 0F80
-0000 0000 >getsymb
-181< 00000000 00000000 0600C000 0600C000 0600C000 0600C000 06008000
-06018000 06018000 0E018000 0E018000 0E018000 0E038000 0E038000
-0E038800 1E079800 1B0DF000 19F8E000 10F04000 30000000 30000000
-30000000 30000000 60000000 60000000 40000000 80000000 00000000
-00000000 >getsymb
-180< 00000000 00000000 08000000 0C030000 0C038000 00000000 00000000
-00000000 00000000 04030000 0C030000 0C030000 18030000 38030000
-30030000 70060300 F0060600 301C0C00 301C0C00 303C1800 186C3000
-1C6C6000 0CCC6000 078CC000 030D8000 000F0000 000E0000 003C0000
-007C0000 00CC0000 018C0000 030C0000 030C0000 03180000 03300000
-01E00000 00C00000 00000000 00000000 >getsymb
-179< 00000000 00000000 38000000 0E000000 03800000 00C00000 00600000
-00300000 001C0000 00070000 0003C000 00018000 00030000 00060000
-001C0000 00780000 00C00000 01800000 07000000 0E000000 18000000
-00000000 000FE000 1FFF0000 7FE00000 00000000 00000000 3FFFC000
-FFFF8000 00000000 00000000 >getsymb
-178< 00000000 00000000 00018000 00070000 000C0000 00180000 00700000
-01C00000 07000000 0C000000 38000000 60000000 C0000000 E0000000
-30000000 18000000 0E000000 07000000 01C00000 00E00000 00380000
-001C0000 00070000 00000000 00000000 3FFFF000 0FFFE000 00000000
-00000000 0FE00000 07FF8000 001FE000 00000000 00000000 >getsymb
-177< 00000000 00000000 01000000 03000000 03000000 03000000 03000000
-03000000 03000000 03000000 FFF80000 FFFF0000 03000000 03000000
-03000000 01800000 01800000 01800000 01800000 01800000 00000000
-00000000 FFFFC000 0FFFC000 00000000 00000000 >getsymb
-176< 00000000 00000000 000F0000 003FC000 3C60E000 7EC06000 C1806000
-C180C000 61FF8000 7F1F0000 1E000000 00000000 00000000 >getsymb
-175< 00000000 00000000 00000300 00000600 00000400 001FEC00 00783800
-00E03C00 03806600 06006200 0E004300 0C00C300 0C018180 0C018180
-18030180 18020180 18060180 180C0180 18080180 18180180 18300300
-18700300 18E00200 09800600 0D000C00 0F000800 07003800 0780F000
-0DFFC000 0C7F0000 18000000 30000000 60000000 C0000000 00000000
-00000000 >getsymb
-174< 00000000 00000000 00FF0000 03C1C000 0700E000 1C003000 30001000
-70001800 60001800 60000C00 60000C00 C0000C00 C0000C00 C0000C00
-C0000C00 C0000C00 C0000C00 C0001800 C0001800 C0001000 40003000
-60006000 70004000 3801C000 1C078000 0FFE0000 03F80000 00000000
-00000000 >getsymb
-173< 00000000 00000000 00040000 000C0000 000C0000 000C0000 00180000
-001FF000 07FFC000 3FF80000 78300000 00600000 00600000 00C00000
-00FFE000 3FFFC000 FFC00000 01800000 01800000 03000000 03000000
-06000000 04000000 00000000 00000000 >getsymb
-172< 0000 0000 E038 6038 C030 0000 0000 >getsymb
-171< 0000 0000 0600 1C00 3000 6000 4000 C000 C000 8000 0000 0000
->getsymb
-170< 000000000000 000000000000 000F20000000 01F82C700000 FF803EF80000
-FF00638C0000 6300630C0000 330063040000 130063060000 1B0063060000
-0B00C3060000 0B00C3060000 0B00C3068000 0E0183028000 060101038000
-000000030000 000000000000 000000000000 >getsymb
-169< 00000000 00000000 0000F800 0003FC00 003F1E00 00F80700 03800180
-06000180 1C0000C0 300000C0 3007C0C0 601FF0E0 60301820 60200C30
-C0600430 C0C00030 C0C00030 C0C00030 C0C00030 C0C02030 C0402030
-C0606030 6030C020 603F8060 380E01C0 3C000300 03001E00 03C03C00
-00FFE000 00FF0000 00000000 00000000 >getsymb
-168< 00000000 00000000 00078000 000FC000 000CE000 000C7000 007E1800
-00FC0C00 07C00E00 0F800700 0C060300 1C9F8300 30B0C180 30C0C180
-70C1C180 E0C38080 C0FF00C0 C0FC00C0 C1C800C0 C1CC00C0 C30E01C0
-C3030180 E2038300 6201C300 30000700 30000E00 38003C00 1C007800
-0E00E000 0F03C000 07FF8000 01FC0000 00000000 00000000 >getsymb
-167< 00000000 00000000 00070000 003F8000 0C70C000 1EC04000 1E804000
-1700C000 37018000 36030000 360C0000 661F0000 66018180 C6008300
-0600C600 0600CC00 0600D800 0600F000 0600E000 0600C000 0E038000
-0E0E0000 0C180000 0C200000 0C000000 0C000000 08000000 08000000
-10000000 10000000 10000000 00000000 00000000 >getsymb
-166< 00000000 00000000 00060000 00038000 01F0C000 07AFE000 3FBDF000
-5F5C3000 4FFC3000 5FFC3000 BFFC1000 FFFC1000 7FFC1000 7FFC1800
-7FF81800 7FF81800 FFF81800 FFF80800 7FF80800 7FF80800 3FF80800
-00580800 00180800 00180800 00181800 00181800 00181800 00181000
-00183000 00182000 00186000 00186000 0018C000 001CC000 000F8000
-00078000 00000000 00000000 >getsymb
-165< 0000 0000 3000 4F00 9FC0 FFE0 FFF0 7FF8 FFF8 FFF8 FFF8 FFFC 9FE4
-AFE4 4FD8 7FF0 2700 1E00 0000 0000 >getsymb
-164< 00000000 00000000 00F00000 01FC0000 03060000 06020000 06000000
-07000000 03200000 01C00000 07F00000 1C1C0000 30060000 60030000
-C0018000 C0018000 C0018000 E0070000 700C0000 1E780000 07E00000
-03F00000 06380000 081C0000 000C0000 00060000 00030000 00018000
-0400C000 0400C000 06018000 03038000 01FE0000 00F00000 00000000
-00000000 >getsymb
-163< 00000000 00000000 00018000 0007C000 001C6000 00303000 00601800
-00600800 00400000 00C00000 00C00000 00C00000 00C00000 00C00000
-00C00000 00C00000 1FC00000 03FE0000 01FFC000 01C00000 01800000
-0180E000 03013000 07001800 06001800 0C001000 18002000 3FC0E000
-F07FC000 601F0000 00000000 00000000 >getsymb
-162< 00000000 00000000 00180000 00300000 00200000 00600000 00600000
-00600000 00600000 01F00000 07F80000 0CCC0000 08C40000 18C00000
-30C00000 70800000 F1801000 31803000 31806000 31804000 3180C000
-31818000 19818000 19830000 0D8E0000 07980000 01F00000 01800000
-01000000 01000000 03000000 03000000 02000000 00000000 00000000
->getsymb
-161< 0000 0000 3C00 6600 6300 4180 C180 C080 C080 E180 FF00 4C00 6000
-3000 0000 0000 >getsymb
-160< 00000000 00000000 00C00000 00C00000 00C00000 00C00000 00C00000
-00C00000 00C00000 00C00000 01C00000 E1C00000 FFE00000 07FC0000
-01CF8000 01800000 01800000 01800000 01800000 01800000 01800000
-01800000 01800000 01800000 01800000 01800000 01800000 01800000
-01800000 01000000 00000000 00000000 >getsymb
-159< 00000000 00000000 01000000 0300C000 0300C000 00006000 00000000
-00000000 00000000 00000000 00008000 04008000 0E018000 3B018000
-63010000 43010180 C3030300 02030600 06030400 06030C00 06030C00
-06070800 06059800 060D9800 06189000 03F0F000 01E06000 00000000
-00000000 >getsymb
-158< 00000000 00000000 00100000 00780000 01CE0000 03870000 06018000
-0400C000 08006000 00002000 00000000 00000000 00000000 00004000
-00004000 0C018000 1E018000 33030000 63030180 C3030300 03030600
-06030600 06030400 06070C00 06070C00 06051800 06091800 07191000
-03F1F000 01E0E000 00000000 00000000 >getsymb
-157< 00000000 00000000 01800000 00C00000 00F00000 00300000 00180000
-000C0000 00060000 00000000 00000000 00000000 00008000 00018000
-00018000 3C018000 7E018000 43018180 C3010300 03030600 06030600
-06030C00 06070C00 06070C00 06059800 060D9800 07089000 03F8F000
-01F06000 00000000 00000000 >getsymb
-156< 00000000 00000000 00007000 0001C000 00030000 000E0000 00380000
-00200000 00E00000 00000000 00000000 00004000 0E00C000 1E00C000
-13018000 33018000 63030000 43030180 C3030300 03030600 06030600
-06070C00 06070C00 060F0C00 06099800 06199800 07309000 03E0F000
-01C06000 00000000 00000000 >getsymb
-155< 00000000 00000000 00C0C000 01E38000 11370000 0E1E0000 04000000
-00000000 00000000 00F00000 03FC0000 071E0000 0E070000 38018000
-7801C600 D801EC00 1801B800 18018000 18018000 0C018000 0C018000
-06010000 06030000 03060000 01FC0000 00F00000 00000000 00000000
->getsymb
-154< 00000000 00000000 0C040000 0C0E0000 100E0000 00000000 00000000
-00000000 00000000 00F00000 03FC0000 079E0000 0F070000 3F038000
-7203C600 C6017C00 06013000 06018000 0E018000 0C018000 0C010000
-06030000 06060000 030C0000 01F80000 00F00000 00000000 00000000
->getsymb
-153< 00000000 00000000 00C00000 00600000 00F00000 01BC0000 030E0000
-06070000 18018000 1000E000 00000000 00F00000 03FC0000 079E0000
-1F070000 3C038000 7803C600 D8016C00 18013800 18018000 18018000
-0C018000 0C010000 06030000 06060000 030C0000 01F80000 00F00000
-00000000 00000000 >getsymb
-152< 00000000 00000000 06000000 07000000 01C00000 00780000 003C0000
-00070000 00000000 00000000 00F00000 03FC0000 071E0000 1C030000
-38038000 7801C600 D8016C00 18013800 18018000 18018000 08018000
-0C010000 0C030000 06060000 030C0000 01F80000 00F00000 00000000
-00000000 >getsymb
-151< 00000000 00000000 00010000 00020000 000C0000 00180000 00300000
-00E00000 03800000 00000000 00000000 00000000 00000000 00000000
-00F00000 03FC0000 079C0000 1C060000 38030000 7801C600 D8016C00
-18013800 18018000 18018000 1C018000 0C030000 0C020000 0C060000
-060C0000 07F80000 01F00000 00000000 00000000 >getsymb
-150< 00000000 00000000 00000600 00E00C00 01B83800 010E6000 0603C000
-0C000000 00000000 00000000 00000000 00000000 00000000 0F1C0000
-3FBF0000 31B38000 61E18000 C1C18180 81818180 01818300 01818300
-01818600 03018600 07018400 06018C00 0600CC00 06007800 06003000
-00000000 00000000 >getsymb
-149< 0000 0000 1800 3830 3878 0070 0000 0000 0000 0000 0C00 1800 1800
-3000 3000 7008 F018 B030 3060 3060 30C0 30C0 3180 3180 1B00 1E00 1C00
-0800 0000 0000 >getsymb
-148< 0000 0000 0300 0780 0D80 18C0 3040 2060 2030 4030 0018 0000 0C00
-1800 1800 3000 3000 7008 F018 B030 3060 3060 30C0 30C0 3180 3180 1B00
-1E00 1C00 0800 0000 0000 >getsymb
-147< 0000 0000 8000 E000 7000 1800 0C00 0700 0780 0000 0000 0000 0C00
-1800 1800 3000 3000 7008 F018 B030 3060 3060 30C0 30C0 3180 3180 1B00
-1E00 1C00 0800 0000 0000 >getsymb
-146< 0000 0000 0018 0030 0060 01C0 0300 0E00 1C00 0000 0000 0000 0C00
-1800 1800 3000 3000 7008 F018 B030 3060 3060 30C0 30C0 3180 3180 1B00
-1E00 1C00 0800 0000 0000 >getsymb
-145< 00000000 00000000 301C0000 380C0000 30000000 00000000 00000000
-00000000 00000000 03E00000 0FF00000 1C180000 30180000 60180000
-40300000 C0600000 C0C00000 C7800000 FE001800 F0001000 60003000
-30006000 3000C000 18018000 0C030000 0C060000 061C0000 03F80000
-00E00000 00000000 00000000 >getsymb
-144< 00000000 00000000 03E00000 0FF80000 300E0000 20030000 40010000
-C0000000 00000000 00000000 03E00000 07300000 0C180000 180C0000
-300C0000 200C0000 60380000 60E00000 67C00000 FE001800 60003000
-60006000 3000C000 30018000 10030000 18060000 0C0C0000 06380000
-03F00000 01C00000 00000000 00000000 >getsymb
-143< 00000000 00000000 38000000 0C000000 07000000 01800000 00C00000
-00400000 00000000 00000000 01C00000 07E00000 0C300000 18180000
-30080000 30380000 60E00000 C3800000 CE000000 F8000C00 F0001800
-60003000 30006000 3000C000 18018000 08030000 0C060000 060C0000
-03F80000 01E00000 00000000 00000000 >getsymb
-142< 00000000 00000000 001C0000 00780000 00C00000 00800000 03000000
-02000000 00000000 00000000 07800000 1FC00000 30600000 60300000
-60300000 40600000 C1C00000 C7800000 9E000000 F0000800 C0001800
-C0003000 60006000 2000C000 30018000 18030000 080E0000 0C180000
-07F00000 03C00000 00000000 00000000 >getsymb
-141< 00000000 00000000 03E00000 0FF00000 18180000 30080000 60000000
-60003000 40006000 C000C000 C0008000 C0018000 C0018000 C0030000
-40030000 60020000 30060000 1F0C0000 07F80000 00E00000 00C00000
-00400000 00780000 001C0000 00040000 04060000 06060000 03060000
-030C0000 01F80000 00000000 00000000 >getsymb
-140< 00000000 00000000 00F00000 01F80000 02880000 00880000 00D80000
-00700000 00000000 00000000 01E08000 03F98000 060D8000 0C070000
-18060000 10060000 30060000 70060000 E0060600 E00C0400 600C0C00
-600C1800 201C1000 30163000 30366000 18366000 18624000 0FC3C000
-07818000 00000000 00000000 >getsymb
-139< 00000000 00000000 00004000 00008000 0E030000 339E0000 40F00000
-00000000 00000000 00000000 01E08000 03F98000 060D8000 0C070000
-18060000 10060000 30060000 70060000 E0060600 E00C0400 600C0C00
-600C1800 201C1000 30163000 30366000 18366000 18624000 0FC3C000
-07818000 00000000 00000000 >getsymb
-138< 00000000 00000000 00080000 040C0000 1C0C0000 18000000 00000000
-00000000 00000000 01E08000 03F98000 060D8000 0C070000 18060000
-10060000 30060000 70060000 E0060600 E00C0400 600C0C00 600C1800
-201C1000 30163000 30366000 18366000 18624000 0FC3C000 07818000
-00000000 00000000 >getsymb
-137< 00000000 00000000 00F00000 031C0000 0E060000 18038000 00008000
-00000000 00000000 01E08000 03F98000 060D8000 0C070000 18060000
-10060000 30060000 70060000 E0060600 E00C0400 600C0C00 600C1800
-201C1000 30163000 30366000 18366000 18624000 0FC3C000 07818000
-00000000 00000000 >getsymb
-136< 00000000 00000000 10000000 0C000000 04000000 06000000 03000000
-01800000 00000000 00000000 01E08000 03F98000 060D8000 0C070000
-18060000 10060000 30060000 70060000 E0060600 E00C0400 600C0C00
-600C1800 201C1000 30163000 30366000 18366000 18624000 0FC3C000
-07818000 00000000 00000000 >getsymb
-135< 00000000 00000000 00030000 000E0000 00180000 00300000 00400000
-00000000 00000000 00000000 01E08000 03F98000 060D8000 0C070000
-18060000 10060000 30060000 70060000 E0060600 E00C0400 600C0C00
-600C1800 201C1000 30163000 30366000 18366000 18624000 0FC3C000
-07818000 00000000 00000000 >getsymb
-134< 00000000 00000000 38003800 38003800 30001800 00000000 00000000
-20000000 60001800 60001800 60001800 C0001800 C0001800 C0001800
-C0003000 C0003000 C0006000 C0006000 C000C000 C001C018 C001C030
-C003C060 6006C060 600C60C0 30186180 3C303300 0FE01E00 07C00C00
-00000000 00000000 >getsymb
-133< 00000000 00000000 0F878000 1FCFC000 307CF800 303C3C00 30300C00
-30300600 30300300 30300300 30300300 30300300 30300700 60300E00
-C031FC00 C073F800 C0FF0000 C0FF0000 C0C30000 C0C30000 C0C18000
-C0C0C000 C0C0E000 C0C07000 E0C03000 E0C03800 70C00E00 30C00E00
-30C00300 30C00300 38C00380 1CC00180 0F8000C0 0F000040 00000000
-00000000 >getsymb
-132< 00000000 00000000 0F000100 1F800100 30E00300 30700300 30700300
-30700300 20580300 204C0300 20CC0380 60CC01C0 E0CE00C0 E0C700C0
-C0C300C0 C0C300C0 C0C381C0 C0C1C380 C0C0C300 C0C0C300 C0C0C300
-C0C0C300 C0C06300 C0C06300 C0C03300 C0C03300 C0C03F00 C0C01F00
-C0C00F00 C1C00F00 FF800F00 3F000600 00000000 00000000 >getsymb
-131< 0000 0000 000C 0018 0030 00E0 0380 0000 1FC0 09FC 181C 1000 3000
-2000 7F00 6FE0 E000 C000 C000 8000 C000 F000 3E00 07F0 0000 0000
->getsymb
-130< 00000000 00000000 003FC000 00FFE000 07F03000 0FC03800 1F000C00
-3B000E00 33000000 73000000 63000000 63000000 C3000000 C3000000
-C3000000 C3000000 C3000000 C3000000 C3000000 C3000000 C3000000
-C3000000 C3000000 C3000000 C6000000 CC000200 7C000C00 3C001C00
-07003000 03807000 01FFE000 00FF8000 00000000 00000000 >getsymb
-129< 00000000 00000000 000F0000 001F8000 0030C000 0030C000 0010C000
-001F0000 00000000 00000000 000C0000 000E0000 000E0000 000F0000
-00338000 00338000 0040C000 00C0C000 00FFC000 00FFE000 0101E000
-03003000 04003800 0C003800 10000C00 30000C00 60000E00 60000E00
-C0000600 C0000700 00000000 00000000 >getsymb
-128< 00000000 00000000 00C00000 00E0E000 00E0E000 0070F000 00000000
-00000000 00000000 00000000 00030000 00030000 00038000 0003C000
-000CE000 000CF000 00383000 00303800 0037FC00 003FBC00 00C00C00
-00C00E00 03000700 03000300 0C000380 0C000180 3C0000C0 380000C0
-E0000060 C0000060 00000000 00000000 >getsymb
-126< 00000000 00000000 00001000 00003000 00004000 1C018000 3E030000
-63060000 819C0000 00F00000 00600000 00000000 00000000 >getsymb
-125< 0000 0000 0780 1FE0 3870 0030 0030 0030 0030 0030 0030 0070 0060
-0040 0060 0030 0018 001C 0070 0060 0040 00C0 00C0 00C0 00C0 00C0 00C0
-0060 0020 0030 C030 7060 1DE0 0F80 0000 0000 >getsymb
-124< 0000 0000 6000 6000 6000 6000 6000 6000 6000 6000 6000 6000 6000
-6000 6000 6000 6000 C000 C000 C000 C000 C000 C000 C000 C000 C000 C000
-C000 C000 4000 0000 0000 >getsymb
-123< 00000000 00000000 00F80000 03FC0000 07020000 06000000 0C000000
-0C000000 0C000000 0C000000 0C000000 0C000000 18000000 18000000
-70000000 E0000000 38000000 0C000000 0C000000 0C000000 0C000000
-0C000000 0C000000 0C000000 18000000 18000000 30000000 30000000
-30040000 183C0000 1CF00000 07800000 00000000 00000000 >getsymb
-122< 00000000 00000000 03020000 078E0000 0CFC0000 186C0000 30080000
-30180000 60300000 C0306000 0060C000 0040C000 00C18000 00818000
-01830000 01030000 03060000 078C0000 0CF80000 18300000 00000000
-00000000 >getsymb
-121< 00000000 00000000 0600C000 0600C000 0C00C000 1C00C000 3C018000
-38038000 78038000 D8031800 18031000 18073000 180F2000 181B6000
-1C334000 0E62C000 07C78000 00070000 00060000 000E0000 001E0000
-00360000 00660000 00C60000 01860000 01860000 01840000 018C0000
-00F80000 00700000 00000000 00000000 >getsymb
-120< 00000000 00000000 0C000000 1E030000 1B078000 330C8000 31180000
-61B00000 C1B01800 01A03000 01E02000 00C06000 00C04000 00C0C000
-01C08000 63418000 36670000 3C3E0000 18180000 00000000 00000000
->getsymb
-119< 00000000 00000000 18004000 38084000 6C186000 4C186000 CC186040
-08183980 18183F00 18183600 18183000 18383000 18683000 18682000
-0C4C2000 0ECC6000 0386C000 01838000 00000000 00000000 >getsymb
-118< 00000000 00000000 18180000 3C1C0000 6C0C0000 4E0E0000 C6073000
-0607E000 0606C000 0C020000 0C030000 0C030000 0C030000 0C030000
-0C060000 040C0000 06180000 06300000 03E00000 01800000 00000000
-00000000 >getsymb
-117< 00000000 00000000 00004000 0E00C000 1E00C000 13018000 33018000
-63030000 43030000 C3030300 03030600 06030600 06070C00 06070C00
-060F0C00 06099800 06199800 07309000 03E0F000 01C06000 00000000
-00000000 >getsymb
-116< 00000000 00000000 00100000 00300000 00300000 00700000 00F00000
-01B00000 01300000 03300000 06200000 06200000 0C600000 18600000
-18400000 30400000 60400000 C6460000 0F4C0000 11580000 10F00000
-1FC00000 0CC00000 00800000 00800000 00800000 00800000 00800000
-00800000 00000000 00000000 >getsymb
-115< 00000000 00000000 00C00000 01C00000 07600000 1C600000 30300000
-60304000 C010C000 00198000 00198000 001B0000 000F0000 000E0000
-000C0000 00180000 00300000 00600000 18C00000 0F800000 07000000
-00000000 00000000 >getsymb
-114< 00000000 00000000 0C100000 1E300000 33F00000 31900000 60300000
-60600000 C0410000 80C20000 01860000 030C0000 03180000 03180000
-03300000 06300000 06200000 06600000 06400000 06C00000 07800000
-03000000 00000000 00000000 >getsymb
-113< 00000000 00000000 00004000 00FCC000 03FEC000 0F06C000 3C03C200
-78018600 D8018400 10038C00 30078C00 30058800 300D9800 30099800
-30119800 38333000 18633000 0FC23000 07062000 00066000 00064000
-000CC000 000CC000 000D8000 000D0000 000D0000 000F0000 000E0000
-00060000 00000000 00000000 >getsymb
-112< 00000000 00000000 00380000 0C7C0000 1EC60000 36C20000 67830000
-67030180 C6010300 06018600 06018400 0E018C00 0C008800 0C00D800
-0C007000 0C002000 0C000000 0C000000 0C000000 18000000 18000000
-18000000 18000000 18000000 18000000 18000000 18000000 18000000
-10000000 10000000 00000000 00000000 >getsymb
-111< 00000000 00000000 00F00000 03FC0000 079E0000 1F070000 3C038000
-7803C000 D8016C00 18013800 18018000 18018000 0C018000 0C010000
-06030000 06060000 030C0000 01F80000 00F00000 00000000 00000000
->getsymb
-110< 00000000 00000000 0E0E0000 1F1F0000 33B30000 21A18000 61E18000
-C1C18180 81818180 01818300 03018300 03018600 07018600 06018400
-0E018C00 0C00CC00 0C007800 0C003000 00000000 00000000 >getsymb
-109< 000000000000 000000000000 000000E00000 060001F00000 0F1E01300000
-19BF03180000 31E382180000 31C0C6180000 6180C4180000 C180CC183000
-8180C8186000 0180D8186000 0180F018C000 0180E0198000 0380C0190000
-0300C01B0000 0601800E0000 0601800E0000 060180040000 060180000000
-000000000000 000000000000 >getsymb
-108< 0000 0000 0700 0F80 08C0 18C0 18C0 18C0 30C0 30C0 30C0 3080 3180
-3300 3600 3600 3C00 3800 3008 7018 F030 B020 3060 3040 30C0 30C0 3080
-1980 1F00 0E00 0000 0000 >getsymb
-107< 00000000 00000000 00300000 00F80000 018C0000 018C0000 030C0000
-030C0000 03180000 03300000 03600000 03C00000 03800000 03000000
-07000000 0F000000 1B1E0000 323F0000 66618000 C6C18600 86C30C00
-078E1800 07383000 07E03000 07806000 06C06000 0C60C000 0C20C000
-0C318000 18330000 181E0000 180C0000 00000000 00000000 >getsymb
-106< 0000 0000 0080 0300 0300 0000 0000 0600 0600 0600 0E00 1E00 1600
-3600 6610 C630 8660 06C0 0780 0700 0600 0E00 1E00 3600 6600 6600 C600
-C600 C600 C600 C600 C600 CC00 CC00 CC00 7800 3000 0000 0000 >getsymb
-105< 0000 0000 0600 0600 0200 0000 0000 0000 0000 0000 0000 0C00 1800
-1800 3000 3000 7008 F018 B030 3060 3060 30C0 30C0 3180 3180 1B00 1E00
-1C00 0800 0000 0000 >getsymb
-104< 00000000 00000000 01E00000 03300000 03180000 02180000 06180000
-06180000 06180000 06300000 06200000 06600000 06C00000 07800000
-07000000 0E000000 1E000000 36000000 66000000 C6000300 06380600
-067C0600 06C60C00 07830C00 07030C00 06031800 06031800 06031800
-0C033000 0C033000 1801E000 1800C000 00000000 00000000 >getsymb
-103< 00000000 00000000 00300000 00F88000 038D8000 06070000 0C030000
-18070000 38070000 780F0000 D81B0600 98330C00 18331800 18633000
-0CC36000 0783C000 03078000 000F0000 003B0000 00630000 00C30000
-01830000 03060000 06060000 06060000 060C0000 06180000 03F00000
-01E00000 00000000 00000000 >getsymb
-102< 0000 0000 0380 07C0 0CC0 08C0 18C0 18C0 1980 1980 1900 1B00 1A00
-1C00 1C00 1800 3800 3800 5800 D818 1C70 1FC0 1E00 1B00 1980 18C0 18C0
-1860 1860 1860 1860 1860 1860 1860 1860 18C0 18C0 0C80 0F80 0700 0000
-0000 >getsymb
-101< 00000000 00000000 03E00000 0FF80000 1C1C0000 300C0000 200C0000
-600C0000 60380000 40E00000 C7800000 DE000400 F0000C00 E0001800
-60003000 30006000 3000C000 18018000 08030000 0C060000 079C0000
-03F80000 00E00000 00000000 00000000 >getsymb
-100< 00000000 00000000 00004000 00004000 00004000 0000C000 0000C000
-0000C000 0000C000 00018000 00018000 00018000 01E18000 07F18000
-0C1B8000 181F0000 180F0000 30060000 70060000 F0020300 B0060600
-30060400 300E0C00 300B0C00 101B1800 18319800 0C61B000 07C1F000
-0380E000 00000000 00000000 >getsymb
-99< 00000000 00000000 01F00000 07380000 0E0C0000 0C040000 18000000
-30000000 70000000 F0001000 30003000 30006000 30004000 3000C000
-30018000 18018000 18030000 0E0E0000 07380000 01F00000 00000000
-00000000 >getsymb
-98< 00000000 00000000 00600000 00F00000 01980000 010C0000 030C0000
-030C0000 03180000 02100000 06300000 06600000 07C00000 07000000
-06000000 0E000000 1E000000 36000000 66008000 C600C300 0601FE00
-0601B800 02018000 03018000 03018000 01010000 01830000 00C60000
-007C0000 00380000 00000000 00000000 >getsymb
-97< 00000000 00000000 01E08000 03F98000 060D8000 0C070000 18060000
-10060000 30060000 70060000 E0060600 E00C0400 600C0C00 600C1800
-201C1000 30163000 30366000 18366000 18624000 0FC3C000 07818000
-00000000 00000000 >getsymb
-96< 0000 0000 1800 3000 3000 6000 6000 C000 C000 C000 C000 6000 3000
-1800 0400 0000 0000 >getsymb
-95< 00000000 00000000 FF800000 3FFFFF00 00FFFF80 00000000 00000000
->getsymb
-94< 00000000 00000000 00700000 01F80000 038C0000 06060000 1C030000
-3001C000 6000E000 C0003000 00001800 00000C00 00000000 00000000
->getsymb
-93< 0000 0000 3FC0 FFC0 00C0 00C0 00C0 00C0 00C0 00C0 00C0 00C0 00C0
-00C0 00C0 00C0 00C0 00C0 00C0 00C0 00C0 00C0 00C0 00C0 00C0 00C0 00C0
-00C0 00C0 0180 0180 3F80 7F00 0000 0000 >getsymb
-92< 00000000 00000000 E0000000 70000000 30000000 18000000 18000000
-0C000000 0C000000 0E000000 06000000 06000000 03000000 03000000
-01800000 01800000 00C00000 00C00000 00400000 00600000 00600000
-00200000 00300000 00180000 00180000 00180000 000C0000 000E0000
-00060000 00070000 00038000 0000C000 00000000 00000000 >getsymb
-91< 0000 0000 7800 7F00 63C0 6000 6000 6000 6000 6000 6000 6000 6000
-6000 6000 6000 6000 6000 6000 6000 C000 C000 C000 C000 C000 C000 C000
-C000 E000 7C00 7F00 0000 0000 >getsymb
-90< 00000000 00000000 0C01F000 3E07B000 630C2000 41F86000 8070C000
-00018000 00030000 00060000 00040000 000C0000 00180000 00180000
-00300000 07E00000 00FC0000 00C00000 00800000 01800040 030000C0
-03000180 06000180 06000300 0C780600 09F80600 1B0F0C00 1E039800
-3C00F000 70007000 00000000 00000000 >getsymb
-89< 00000000 00000000 00002000 00002000 20002000 70006000 C8006000
-CC006000 CC00C000 8C00C000 0C00C000 0C00C000 0C00C000 0C00C000
-0C01C000 0C01C000 0403C000 0602C000 0602C600 0604CC00 021CD800
-03F0F000 01C0E000 0001C000 0003C000 0006C000 000CC000 0018C000
-0030C000 00608000 00418000 00C30000 00860000 008C0000 00D80000
-00700000 00000000 00000000 >getsymb
-88< 00000000 00000000 1F000000 31C00C00 30601E00 30303300 30387100
-18186000 0C18C000 000CC000 000C8000 000D8000 000F8000 000F0000
-000F0000 00070000 00060000 00060000 00060000 00060000 00060060
-000600C0 00060080 000F0180 400F0180 C01F0180 C0198100 C0318300
-6030C300 20604200 30C06600 1C803C00 0F801800 03000000 00000000
-00000000 >getsymb
-87< 000000000000 000000000000 100000000000 780000000000 4C0000000000
-8C0000000000 0C0030000000 0C00300000C0 0C00600001A0 0C0060000100
-0C0060000300 0C0060000300 0C00C0000300 0C00C0000300 1800C0000300
-1800C0000300 1001C0000600 3001C0000600 3003C0000C00 3003C0000C30
-3006C0001860 300CC00030C0 3018C00020C0 3018C0006180 3030C000C380
-1830C0018700 1860C0019C00 0CC0C003F800 0F80600FE000 0600703E0000
-00003FF00000 00000FC00000 000000000000 000000000000 >getsymb
-86< 00000000 00000000 30000100 78000380 CC0003F0 8C000360 0C000300
-0C000300 0C000300 0C000300 0C000600 0C000600 0C000600 0C000600
-0C000C00 06000C00 06000C00 06000C00 06001800 06001818 06001070
-060011E0 06003F80 06007C00 0300F000 0187C000 01FF0000 00780000
-00000000 00000000 >getsymb
-85< 000000000000 000000000000 300003000000 780003000000 CC0003000000
-8C0003000000 0C0003000000 0C0003000000 180006000000 180006000000
-180006000000 300006000000 300006000000 300006000000 30000C000000
-30000C000000 300018000000 300018000000 300030000000 300070060000
-3000700C0000 3000F0180000 1801B0180000 180318300000 0C0618600000
-0F0C0CC00000 03F807800000 01F003000000 000000000000 000000000000
->getsymb
-84< 00000000 00000000 0F800100 3FC00200 607E0C00 803FF800 000CE000
-000C0000 000C0000 000C0000 00060000 00060000 00030000 00030000
-00030000 00030000 00030000 00030000 000300C0 00030180 02030300
-02030300 02030600 03030C00 01833800 01C7F000 00FF8000 003C0000
-00000000 00000000 >getsymb
-83< 00000000 00000000 00F00000 01FC0000 031E0000 02030000 06018000
-0600C000 06004000 06004000 06008000 03000000 03800000 00F00000
-003C0000 000F0000 00038000 00018000 0000C600 00006400 00006C00
-00003800 00003000 20007000 70006000 9C00C000 06038000 030F0000
-03FC0000 01F80000 00000000 00000000 >getsymb
-82< 00000000 00000000 020FE000 033FF800 03F80C00 03C00600 07000300
-0F000300 1B000300 3B000300 33000600 33000C00 63003800 6300E000
-43038000 C30F0000 C3FC0000 C3FE0000 C3070018 C6070030 CC038060
-4C01C0C0 7C00C080 7C006180 38006180 38006100 38003300 38003300
-38001E00 38001E00 30000C00 10000000 00000000 00000000 >getsymb
-81< 00000000 00000000 001FE000 007FF000 01C03800 03001C00 06000C00
-0C000C00 0C000C00 18000C00 18000600 10000600 30000300 30000300
-30000300 30000300 60000300 60000200 60000600 C0000600 C000060C
-C000060C C0000C18 C0000C18 C0001830 603C3020 304E7060 3083C040
-1C01E0C0 0E037180 03FE1F00 00FC0E00 00000000 00000000 >getsymb
-80< 00000000 00000000 03FC0000 0FFF0000 3C01C000 7C007000 4C003800
-8C001800 0C000C00 0C000C00 0C000C00 0C000C00 06000C00 06000800
-06001800 06003000 261FE000 1FFF8030 0F800060 060000C0 06000180
-06000300 06000E00 06003800 0600F000 0603C000 0C0F0000 0C3C0000
-0FF00000 1FC00000 00000000 00000000 >getsymb
-79< 00000000 00000000 00FE0000 01FF8000 0700C000 0E00C000 0C006000
-18003000 30003000 30003000 70003000 60001800 40001C00 C0000C00
-C0000C00 C0000C00 C0000600 C0000600 C0000700 C0000730 C00006E0
-C0000600 60000600 60000600 30000400 30000C00 30001800 18003000
-0C006000 0C00C000 06018000 060F0000 03FC0000 00F00000 00000000
-00000000 >getsymb
-78< 000000000000 000000000000 1E0380000000 3F07E0000000 631C38000000
-81B81C000000 00F00C000000 00E006000000 00C002000000 00C003000000
-00C003000000 01C003000000 018003000000 018003000000 030003000000
-030003000000 030003800000 030001800000 030001800400 030001800800
-030001801800 060001803000 060000806000 0C0000C0C000 0C0000C0C000
-0C0000C18000 0C0000C30000 0C0000C60000 0000007C0000 000000380000
-000000000000 000000000000 >getsymb
-77< 000000000000 000000000000 070180000000 1F83C0000000 7186600F0000
-E0C6703F8000 00C43030C000 00CC1860C000 00CC18606000 00C808C06000
-00F80CC02000 00F006803000 00F007803000 00E007803000 00E003803000
-00E003003000 00E003003000 00E003006000 00E003006000 00E003006060
-00E0030060C0 00E0030060C0 00E003006180 00E003006180 00E003006100
-00E003006300 00C001006200 00C001006600 00C001003C00 00C001001800
-000000000000 000000000000 >getsymb
-76< 00000000 00000000 00300000 00780000 004C0000 00CC0000 00CC0000
-00CC0000 00CC0000 00D80000 00F00000 00E00000 01C00000 03C00000
-0EC00000 38C00000 60C00000 C0C00000 00C00000 00C00300 00C00600
-00C00C00 00C00C00 00C01800 0FE01800 1FF03000 31B83000 331C6000
-1E07C000 0C038000 00000000 00000000 >getsymb
-75< 00000000 00000000 18300060 3C7800C0 664C0300 43CC0600 838C1C00
-010C3800 000C6000 000CC000 000F8000 000F0000 00098000 0018C000
-00186000 00186000 00183000 00183000 00183018 00301830 00301830
-00201860 00600C60 20C00CC0 218004C0 330006C0 1E000380 0C000300
-00000000 00000000 >getsymb
-74< 00000000 00000000 00040000 180E0000 3E1B0000 23198000 63318000
-C1B18000 C1E18000 80C18000 80018000 00030000 00030000 00060000
-00060000 00060000 00060000 00062000 00066000 0006C000 00078000
-00070000 00060000 000C0000 001C0000 003C0000 006C0000 00CC0000
-018C0000 030C0000 060C0000 0C0C0000 0C0C0000 0C0C0000 0C0C0000
-0C180000 0C180000 06180000 03980000 03F80000 00F00000 00000000
-00000000 >getsymb
-73< 00000000 00000000 000C0000 1C3C0000 36660000 63C60000 41860000
-80060000 80060000 00060000 00060000 000C0000 000C0000 000C0000
-000C0000 000C0000 000C0000 00180000 00183000 00186000 00186000
-0018C000 80198000 801F0000 C03C0000 60700000 3FC00000 1F800000
-00000000 00000000 >getsymb
-72< 000000000000 000000000000 000001800000 000007C00000 1C100C600000
-3E3808600000 67D818600000 439818600000 801818400000 801818C00000
-001818800000 001819800000 00181F000000 00181C000000 001878000000
-001BF0000000 007E30000000 00F830000000 019830000000 031860030000
-061860060000 0618600C0000 0C18600C0000 181860180000 181860180000
-181060300000 183030300000 186030600000 0FC018600000 070008C00000
-00000F800000 000007000000 000000000000 000000000000 >getsymb
-71< 00000000 00000000 00180000 00FF0000 03C78000 0600E000 0C003000
-18001000 30000000 30000000 60000000 E0000000 C0000000 C0000000
-C0000000 C0000000 C0000000 60008000 60018000 30038030 30078060
-180F80C0 081D8380 0C310700 07E31C00 03C37000 0003C000 001F8000
-007F0000 01E30000 03830000 07030000 06060000 0C060000 0C040000
-0C0C0000 0C180000 0C100000 06300000 03E00000 01C00000 00000000
-00000000 >getsymb
-70< 00000000 00000000 0801FC00 0C0FF800 3FFE0000 FFF00000 8C000000
-0C000000 0C000000 04000000 06000000 06000000 03000000 0303F000
-03FF8000 03FC0000 03000000 02000000 06000000 06000600 04000C00
-0C001800 0C003000 0C00E000 18078000 180F0000 1FF80000 3FE00000
-00000000 00000000 >getsymb
-69< 00000000 00000000 03FC0000 07FF0000 1C038000 3C01C000 3000C000
-30004000 30000000 38000000 1E000000 0E000000 03F00000 01F80000
-03800000 0E000000 18000000 30000000 60000000 60000300 C0000600
-C0000600 C0000C00 C0000C00 C0001800 70003000 3800E000 1E01C000
-07FF0000 01FC0000 00000000 00000000 >getsymb
-68< 00000000 00000000 07FE0000 1FFF8000 3060C000 30C06000 30C03000
-19801800 19800800 0D000C00 07000400 07000600 03000300 03800300
-06C00300 06600300 06300300 061C0300 0C06030C 0C038318 1C01C670
-18007FC0 30003F00 3E001800 3B803000 71F0E000 C03FC000 C01F8000
-00000000 00000000 >getsymb
-67< 00000000 00000000 007F8000 01FFE000 07007000 0C003000 18001800
-38001800 30001800 60003000 60006000 6011C000 C01F0000 C0060000
-C0000000 C0000000 C0000000 C0000000 C0000000 C0000000 C00000C0
-C0000180 C0000180 60000300 60000300 60000600 30000C00 38003800
-1E00E000 0F03C000 01FF0000 00FE0000 00000000 00000000 >getsymb
-66< 00000000 00000000 03FC0000 0FFF0000 1B818000 2300C000 0300C000
-0300C000 0300C000 06018000 06038000 060F0000 041C0000 04700000
-0CF00000 0C1C0000 0C0F0000 0C078000 0C00C000 0C00600C 0C003018
-0C003818 0C001C30 0C000C30 0C000CE0 0C000DC0 18001F00 18001E00
-30003800 30007000 F800C000 7F018000 47FF0000 00FE0000 00000000
-00000000 >getsymb
-65< 00000000 00000000 001E0400 007F0C00 01C1C800 0300E800 06003800
-0C003000 18003000 10003000 30003000 60006000 60006000 60006000
-C0006000 C0006000 C000C000 C000C030 C000C060 C000C0C0 4000C180
-6000C300 2001C300 3001C600 3803C600 1802CC00 0C06CC00 06046C00
-039C7800 00F83000 00000000 00000000 >getsymb
-64< 00000000 00000000 001F0000 00FFE000 07C0F000 0F001800 1C000C00
-18000C00 30000700 70000300 60000180 60000180 400E0180 401F8180
-C030C180 C070C180 C0C04180 C1C0C180 C180C180 8300C180 C301C180
-C3018100 43018300 61018300 2186EE00 30CE7C00 107C0000 18000000
-0C000000 06000000 0300E000 01FFC000 007E0000 00000000 00000000
->getsymb
-63< 0000 0000 1E00 3F00 6180 C0C0 8060 8020 C030 6030 1030 0020 0060
-00C0 0180 0300 0200 0400 0C00 0800 1800 1000 3000 3000 1800 0000 0000
-0000 1800 1C00 0000 0000 >getsymb
-62< 00000000 00000000 C0000000 60000000 30000000 18000000 0C000000
-06000000 03000000 01800000 00C00000 00600000 00380000 001C0000
-00060000 00030000 00070000 001C0000 00700000 01C00000 07000000
-0E000000 38000000 60000000 C0000000 80000000 00000000 00000000
->getsymb
-61< 00000000 00000000 FFE00000 FFFFF000 001FF000 00000000 00000000
-00000000 00000000 00000000 00000000 FFFFC000 FFFFC000 00000000
-00000000 >getsymb
-60< 00000000 00000000 00018000 000F0000 00380000 00E00000 03800000
-06000000 0C000000 10000000 30000000 E0000000 60000000 20000000
-30000000 18000000 0C000000 06000000 03000000 01800000 00E00000
-00380000 000E0000 00038000 00000000 00000000 >getsymb
-59< 0000 0000 1800 3800 3000 2000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0C00 0600 0600 0600 0600 1C00 3000 E000 8000 0000 0000
->getsymb
-58< 0000 0000 6000 F000 C000 C000 0000 0000 0000 0000 0000 0000 0000
-0000 0000 0000 0000 8000 F000 E000 0000 0000 >getsymb
-57< 00000000 00000000 03F00000 0FFC0000 180E0000 38060000 60020000
-C0030000 C0030000 C0030000 C0030000 C0030000 C0020000 40060000
-60060000 601E0000 30340000 18640000 0FEC0000 078C0000 00080000
-00080000 00180000 00180000 00100000 80300000 C0300000 70600000
-1FC00000 0F000000 00000000 00000000 >getsymb
-56< 00000000 00000000 007C0000 00C60000 01820000 03030000 03010000
-03010000 03010000 03030000 01030000 01030000 03860000 0F8E0000
-18F80000 30700000 60100000 60180000 60080000 C0080000 C0080000
-C0180000 40180000 60300000 3FE00000 0FC00000 00000000 00000000
->getsymb
-55< 0000 0000 0008 3078 78F8 CC98 8798 0710 0030 0030 0020 0060 0040
-00C0 0080 3980 0FE0 03F8 0300 0300 0600 0600 0600 0C00 0800 1800 3000
-6000 6000 4000 4000 0000 0000 >getsymb
-54< 00000000 00000000 00040000 001C0000 00300000 00E00000 01800000
-03000000 06000000 0C000000 08000000 18F00000 33F80000 360E0000
-6C070000 78010000 60018000 60018000 C000C000 C000C000 C000C000
-C0008000 C0018000 60010000 30030000 18060000 1C0C0000 0F180000
-03F00000 00000000 00000000 >getsymb
-53< 00000000 00000000 01FF0000 03FF0000 03000000 03000000 06000000
-06000000 06000000 06000000 06000000 03C00000 00F80000 001C0000
-000E0000 00030000 00030000 00030000 000E0000 E01C0000 70300000
-3FE00000 0F800000 00000000 00000000 >getsymb
-52< 0000 0000 8018 8018 C018 C018 C018 C018 C018 FF18 3FF8 01F8 0030
-0030 0070 0060 0060 0060 00E0 00C0 00C0 0080 0080 0000 0000 >getsymb
-51< 00000000 00000000 01E00000 07F00000 0E180000 0C0C0000 000C0000
-000C0000 00180000 00300000 00600000 00C00000 00780000 001E0000
-00070000 00018000 0001C000 0000C000 8000C000 C0018000 C0070000
-7C0E0000 3FF80000 03F00000 00000000 00000000 >getsymb
-50< 00000000 00000000 07800000 1FC00000 38600000 70300000 C0300000
-80100000 00100000 00100000 00300000 00300000 00200000 00600000
-00C00000 01800000 01000000 03000000 06000000 06000000 0F004000
-1DC08000 307F8000 303E0000 00000000 00000000 >getsymb
-49< 0000 0000 3000 7800 9800 1800 1800 1800 1800 1800 1800 1800 1800
-3000 3000 3000 3000 3000 3000 3000 3000 3000 0000 0000 >getsymb
-48< 00000000 00000000 00E00000 03F80000 0E180000 180C0000 30060000
-30060000 60020000 E0030000 C0030000 C0030000 C0030000 C0030000
-C0030000 C0030000 C0020000 60060000 60060000 20040000 300C0000
-18180000 0C180000 07F00000 01E00000 00000000 00000000 >getsymb
-47< 00000000 00000000 00040000 00060000 000C0000 000C0000 00180000
-00180000 00180000 00300000 00300000 00200000 00600000 00600000
-00C00000 00C00000 01800000 01800000 03000000 03000000 06000000
-06000000 0C000000 0C000000 18000000 18000000 38000000 30000000
-60000000 60000000 60000000 C0000000 80000000 00000000 00000000
->getsymb
-46< 0000 0000 8000 C000 E000 C000 0000 0000 >getsymb
-45< 0000 0000 F000 7FF0 07F0 0000 0000 >getsymb
-44< 0000 0000 1000 1800 0C00 0C00 0C00 0C00 0800 1800 3000 6000 8000
-0000 0000 >getsymb
-43< 00000000 00000000 00100000 00100000 00300000 00300000 00300000
-00300000 00300000 0033E000 3FFFC000 FFFC0000 00300000 00300000
-00300000 00300000 00300000 00300000 00600000 00600000 00400000
-00400000 00000000 00000000 >getsymb
-42< 00000000 00000000 30180000 18300000 0C600000 04C00000 0FFE0000
-3FF80000 EC600000 86200000 06300000 03180000 03000000 01000000
-00000000 00000000 >getsymb
-41< 0000 0000 6000 F000 1C00 0E00 0300 0180 0080 00C0 00C0 00C0 00C0
-00C0 0060 0060 0060 0060 0060 0060 0060 00C0 00C0 00C0 00C0 00C0 0080
-0180 0380 0300 0600 0C00 1800 7000 0000 0000 >getsymb
-40< 0000 0000 0700 0E00 1800 3000 2000 6000 6000 6000 6000 6000 C000
-C000 C000 C000 C000 C000 C000 C000 6000 6000 6000 6000 3000 3000 1800
-1800 0C00 0600 0700 0380 0000 0000 >getsymb
-39< 0000 0000 2000 3000 1800 1800 0C00 0C00 0C00 1800 3000 3000 6000
-4000 8000 0000 0000 >getsymb
-38< 00000000 00000000 0F000000 1F800000 30C00000 20600000 20300000
-30300000 18200000 18400000 0CC00000 05800000 0F000000 1F000000
-19820000 30C20000 60660000 602C0000 C0380000 C0300000 C0300000
-C0780000 60680000 61CC0000 3F0C0000 1E040000 00060000 00000000
-00000000 >getsymb
-37< 00000000 00000000 0E03C000 3FDF8000 61F30000 60C70000 C0C60000
-C0CC0000 618C0000 630C0000 3E180000 0C300000 00300000 00600000
-00600000 00C00000 01C00000 03800000 0307C000 060FE000 0C3C2000
-18F03000 31E03000 37603000 6CC03000 78C06000 E0F0C000 C07FC000
-000F0000 00000000 00000000 >getsymb
-36< 00000000 00000000 01040000 03040000 030C0000 030C0000 030C0000
-037C0000 03DE0000 0F0F0000 0E0D8000 1A0C8000 360C0000 260C0000
-260C0000 1E0C0000 1FCC0000 07FC0000 043C0000 040E0000 8C0F8000
-CC0FC000 7C0C4000 1C0C6000 0E0CE000 0FFFC000 0CFE0000 0C180000
-0C180000 0C180000 0C180000 0C180000 0C100000 08100000 08100000
-08100000 00100000 00000000 00000000 >getsymb
-35< 00000000 00000000 00430000 00430000 00C30000 00C30000 00C30000
-00C30000 00C3F000 00FFF000 1FFF0000 3F870000 018C0000 018C0000
-018C0000 018C0000 030C0000 030FC000 7FFFC000 FFF80000 06180000
-06180000 06180000 0C180000 0C180000 0C100000 00000000 00000000
->getsymb
-34< 0000 0000 8300 6180 30C0 10C0 10C0 10C0 3180 6300 C000 8000 0000
-0000 >getsymb
-33< 0000 0000 4000 6000 6000 6000 6000 6000 6000 6000 6000 6000 6000
-6000 6000 6000 6000 6000 E000 C000 C000 C000 C000 C000 C000 8000 0000
-0000 0000 C000 C000 4000 0000 0000 >getsymb
-Hwfdict begin
- /BuildChar
- Chread
-end
-/Joepie Hwfdict definefont
-%%EndFont Joepie\n\n"))
-
-;;Sets page numbering off
-(defun handwrite-set-pagenumber-off ()
- (setq handwrite-pagenumbering nil)
- (define-key menu-bar-handwrite-map
- [numbering]
- '("Page numbering Off" . handwrite-set-pagenumber))
- (message "page numbering off"))
-
-;;Sets page numbering on
-(defun handwrite-set-pagenumber-on ()
- (setq handwrite-pagenumbering t)
- (define-key menu-bar-handwrite-map
- [numbering]
- '("Page numbering On" . handwrite-set-pagenumber))
- (message "page numbering on" ))
-
-
-;; Key bindings
-
-
-(define-key-after
- (lookup-key global-map [menu-bar edit])
- [handwrite]
- '("Write by hand" . menu-bar-handwrite-map)
- 'spell)
-
-(define-key menu-bar-handwrite-map [numbering]
- '("Page numbering Off" . handwrite-set-pagenumber))
-
-(define-key menu-bar-handwrite-map [10pt]
- '("10 pt" . handwrite-10pt))
-
-(define-key menu-bar-handwrite-map [11pt]
- '("11 pt *" . handwrite-11pt))
-
-(define-key menu-bar-handwrite-map [12pt]
- '("12 pt" . handwrite-12pt))
-
-(define-key menu-bar-handwrite-map [13pt]
- '("13 pt" . handwrite-13pt))
-
-(define-key menu-bar-handwrite-map [handwrite]
- '("Write by hand" . handwrite))
-
-(define-key-after
- (lookup-key menu-bar-handwrite-map [ ])
- [handwrite-separator1]
- '("----" . nil)
- 'handwrite)
-
-(define-key-after
- (lookup-key menu-bar-handwrite-map [ ])
- [handwrite-separator2]
- '("----" . nil)
- '10pt)
-
-
-(provide 'handwrite)
-
-
-;;; handwrite.el ends here
diff --git a/lisp/play/hanoi.el b/lisp/play/hanoi.el
deleted file mode 100644
index ba74a2ba645..00000000000
--- a/lisp/play/hanoi.el
+++ /dev/null
@@ -1,227 +0,0 @@
-;;; hanoi.el --- towers of hanoi in GNUmacs
-
-;; Author: Damon Anton Permezel
-;; Maintainer: FSF
-;; Keywords: games
-
-; Author (a) 1985, Damon Anton Permezel
-; This is in the public domain
-; since he distributed it without copyright notice in 1985.
-
-;;; Commentary:
-
-;; Solves the Towers of Hanoi puzzle while-U-wait.
-;;
-;; The puzzle: Start with N rings, decreasing in sizes from bottom to
-;; top, stacked around a post. There are two other posts. Your mission,
-;; should you choose to accept it, is to shift the pile, stacked in its
-;; original order, to another post.
-;;
-;; The challenge is to do it in the fewest possible moves. Each move
-;; shifts one ring to a different post. But there's a rule; you can
-;; only stack a ring on top of a larger one.
-;;
-;; The simplest nontrivial version of this puzzle is N = 3. Solution
-;; time rises as 2**N, and programs to solve it have long been considered
-;; classic introductory exercises in the use of recursion.
-;;
-;; The puzzle is called `Towers of Hanoi' because an early popular
-;; presentation wove a fanciful legend around it. According to this
-;; myth (uttered long before the Vietnam War), there is a Buddhist
-;; monastery at Hanoi which contains a large room with three time-worn
-;; posts in it surrounded by 21 golden discs. Monks, acting out the
-;; command of an ancient prophecy, have been moving these disks, in
-;; accordance with the rules of the puzzle, once every day since the
-;; monastery was founded over a thousand years ago. They are said
-;; believe that when the last move of the puzzle is completed, the
-;; world will end in a clap of thunder. Fortunately, they are nowhere
-;; even close to being done...
-
-;;; Code:
-
-;;;
-;;; hanoi-topos - direct cursor addressing
-;;;
-(defun hanoi-topos (row col)
- (goto-line row)
- (beginning-of-line)
- (forward-char col))
-
-;;;
-;;; hanoi - user callable Towers of Hanoi
-;;;
-;;;###autoload
-(defun hanoi (nrings)
- "Towers of Hanoi diversion. Argument is number of rings."
- (interactive "p")
- (if (<= nrings 1) (setq nrings 7))
- (let* (floor-row
- fly-row
- (window-height (1- (window-height (selected-window))))
- (window-width (window-width (selected-window)))
-
- ;; This is half the spacing to use between poles.
- (pole-spacing (/ window-width 6)))
- (if (not (and (> window-height (1+ nrings))
- (> pole-spacing nrings)))
- (progn
- (delete-other-windows)
- (if (not (and (> (setq window-height
- (1- (window-height (selected-window))))
- (1+ nrings))
- (> (setq pole-spacing (/ window-width 6))
- nrings)))
- (error "Window is too small (need at least %dx%d)"
- (* 6 (1+ nrings)) (+ 2 nrings)))))
- (setq floor-row (if (> (- window-height 3) (1+ nrings))
- (- window-height 3) window-height))
- (let ((fly-row (- floor-row nrings 1))
- ;; pole: column . fill height
- (pole-1 (cons (1- pole-spacing) floor-row))
- (pole-2 (cons (1- (* 3 pole-spacing)) floor-row))
- (pole-3 (cons (1- (* 5 pole-spacing)) floor-row))
- (rings (make-vector nrings nil)))
- ;; construct the ring list
- (let ((i 0))
- (while (< i nrings)
- ;; ring: [pole-number string empty-string]
- (aset rings i (vector nil
- (make-string (+ i i 3) (+ ?0 (% i 10)))
- (make-string (+ i i 3) ?\ )))
- (setq i (1+ i))))
- ;;
- ;; init the screen
- ;;
- (switch-to-buffer "*Hanoi*")
- (setq buffer-read-only nil)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (let ((i 0))
- (while (< i floor-row)
- (setq i (1+ i))
- (insert-char ?\ (1- window-width))
- (insert ?\n)))
- (insert-char ?= (1- window-width))
-
- (let ((n 1))
- (while (< n 6)
- (hanoi-topos fly-row (1- (* n pole-spacing)))
- (setq n (+ n 2))
- (let ((i fly-row))
- (while (< i floor-row)
- (setq i (1+ i))
- (next-line 1)
- (insert ?\|)
- (delete-char 1)
- (backward-char 1)))))
- ;(sit-for 0)
- ;;
- ;; now draw the rings in their initial positions
- ;;
- (let ((i 0)
- ring)
- (while (< i nrings)
- (setq ring (aref rings (- nrings 1 i)))
- (aset ring 0 (- floor-row i))
- (hanoi-topos (cdr pole-1)
- (- (car pole-1) (- nrings i)))
- (hanoi-draw-ring ring t nil)
- (setcdr pole-1 (1- (cdr pole-1)))
- (setq i (1+ i))))
- (setq buffer-read-only t)
- (sit-for 0)
- ;; Disable display of line and column numbers, for speed.
- (let ((line-number-mode nil)
- (column-number-mode nil))
- ;; do it!
- (hanoi0 (1- nrings) pole-1 pole-2 pole-3))
- (goto-char (point-min))
- (message "Done")
- (setq buffer-read-only t)
- (force-mode-line-update)
- (sit-for 0))))
-
-;;;
-;;; hanoi0 - work horse of hanoi
-;;;
-(defun hanoi0 (n from to work)
- (cond ((input-pending-p)
- (signal 'quit (list "I can tell you've had enough")))
- ((< n 0))
- (t
- (hanoi0 (1- n) from work to)
- (hanoi-move-ring n from to)
- (hanoi0 (1- n) work to from))))
-
-;;;
-;;; hanoi-move-ring - move ring 'n' from 'from' to 'to'
-;;;
-;;;
-(defun hanoi-move-ring (n from to)
- (let ((ring (aref rings n)) ; ring <- ring: (ring# . row)
- (buffer-read-only nil))
- (let ((row (aref ring 0)) ; row <- row ring is on
- (col (- (car from) n 1)) ; col <- left edge of ring
- (dst-col (- (car to) n 1)) ; dst-col <- dest col for left edge
- (dst-row (cdr to))) ; dst-row <- dest row for ring
- (hanoi-topos row col)
- (while (> row fly-row) ; move up to the fly row
- (hanoi-draw-ring ring nil t) ; blank out ring
- (previous-line 1) ; move up a line
- (hanoi-draw-ring ring t nil) ; redraw
- (sit-for 0)
- (setq row (1- row)))
- (setcdr from (1+ (cdr from))) ; adjust top row
- ;;
- ;; fly the ring over to the right pole
- ;;
- (while (not (equal dst-col col))
- (cond ((> dst-col col) ; dst-col > col: right shift
- (end-of-line 1)
- (delete-backward-char 2)
- (beginning-of-line 1)
- (insert ?\ ?\ )
- (sit-for 0)
- (setq col (1+ (1+ col))))
- ((< dst-col col) ; dst-col < col: left shift
- (beginning-of-line 1)
- (delete-char 2)
- (end-of-line 1)
- (insert ?\ ?\ )
- (sit-for 0)
- (setq col (1- (1- col))))))
- ;;
- ;; let the ring float down
- ;;
- (hanoi-topos fly-row dst-col)
- (while (< row dst-row) ; move down to the dest row
- (hanoi-draw-ring ring nil (> row fly-row)) ; blank out ring
- (next-line 1) ; move down a line
- (hanoi-draw-ring ring t nil) ; redraw ring
- (sit-for 0)
- (setq row (1+ row)))
- (aset ring 0 dst-row)
- (setcdr to (1- (cdr to)))))) ; adjust top row
-
-;;;
-;;; draw-ring - draw the ring at point, leave point unchanged
-;;;
-;;; Input:
-;;; ring
-;;; f1 - flag: t -> draw, nil -> erase
-;;; f2 - flag: t -> erasing and need to draw ?\|
-;;;
-(defun hanoi-draw-ring (ring f1 f2)
- (save-excursion
- (let* ((string (if f1 (aref ring 1) (aref ring 2)))
- (len (length string)))
- (delete-char len)
- (insert string)
- (if f2
- (progn
- (backward-char (/ (+ len 1) 2))
- (delete-char 1) (insert ?\|))))))
-
-(provide 'hanoi)
-
-;;; hanoi.el ends here
diff --git a/lisp/play/life.el b/lisp/play/life.el
deleted file mode 100644
index 9645cb398df..00000000000
--- a/lisp/play/life.el
+++ /dev/null
@@ -1,283 +0,0 @@
-;;; life.el --- John Horton Conway's `Life' game for GNU Emacs
-
-;; Copyright (C) 1988 Free Software Foundation, Inc.
-
-;; Author: Kyle Jones <talos!kjones@uunet.uu.net>
-;; Keywords: games
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; A demonstrator for John Horton Conway's "Life" cellular automaton
-;; in Emacs Lisp. Picks a random one of a set of interesting Life
-;; patterns and evolves it according to the familiar rules.
-
-;;; Code:
-
-(defconst life-patterns
- [("@@@" " @@" "@@@")
- ("@@@ @@@" "@@ @@ " "@@@ @@@")
- ("@@@ @@@" "@@ @@" "@@@ @@@")
- ("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
- ("@@@@@@@@@@")
- (" @@@@@@@@@@ "
- " @@@@@@@@@@ "
- " @@@@@@@@@@ "
- "@@@@@@@@@@ "
- "@@@@@@@@@@ ")
- ("@" "@" "@" "@" "@" "@" "@" "@" "@" "@" "@" "@" "@" "@" "@")
- ("@ @" "@ @" "@ @"
- "@ @" "@ @" "@ @"
- "@ @" "@ @" "@ @"
- "@ @" "@ @" "@ @"
- "@ @" "@ @" "@ @")
- ("@@ " " @@ " " @@ "
- " @@ " " @@ " " @@ "
- " @@ " " @@ " " @@ "
- " @@ " " @@ " " @@ "
- " @@ " " @@ " " @@ "
- " @@")
- ("@@@@@@@@@" "@ @ @" "@ @@@@@ @" "@ @ @ @" "@@@ @@@"
- "@ @ @ @" "@ @@@@@ @" "@ @ @" "@@@@@@@@@")]
- "Vector of rectangles containing some Life startup patterns.")
-
-;; Macros are used macros for manifest constants instead of variables
-;; because the compiler will convert them to constants, which should
-;; eval faster than symbols.
-;;
-;; Don't change any of the life-* macro constants unless you thoroughly
-;; understand the `life-grim-reaper' function.
-
-(defmacro life-life-char () ?@)
-(defmacro life-death-char () (1+ (life-life-char)))
-(defmacro life-birth-char () 3)
-(defmacro life-void-char () ?\ )
-
-(defmacro life-life-string () (char-to-string (life-life-char)))
-(defmacro life-death-string () (char-to-string (life-death-char)))
-(defmacro life-birth-string () (char-to-string (life-birth-char)))
-(defmacro life-void-string () (char-to-string (life-void-char)))
-(defmacro life-not-void-regexp () (concat "[^" (life-void-string) "\n]"))
-
-(defmacro life-increment (variable) (list 'setq variable (list '1+ variable)))
-
-
-;; list of numbers that tell how many characters to move to get to
-;; each of a cell's eight neighbors.
-(defconst life-neighbor-deltas nil)
-
-;; window display always starts here. Easier to deal with than
-;; (scroll-up) and (scroll-down) when trying to center the display.
-(defconst life-window-start nil)
-
-;; For mode line
-(defconst life-current-generation nil)
-;; Sadly, mode-line-format won't display numbers.
-(defconst life-generation-string nil)
-
-(defvar life-initialized nil
- "Non-nil if `life' has been run at least once.")
-
-;;;###autoload
-(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
-generations (this defaults to 1)."
- (interactive "p")
- (or life-initialized
- (random t))
- (setq life-initialized t)
- (or sleeptime (setq sleeptime 1))
- (life-setup)
- (life-display-generation sleeptime)
- (catch 'life-exit
- (while t
- (let ((inhibit-quit t))
- (life-grim-reaper)
- (life-expand-plane-if-needed)
- (life-increment-generation)
- (life-display-generation sleeptime)))))
-
-(defalias 'life-mode 'life)
-(put 'life-mode 'mode-class 'special)
-
-(defun life-setup ()
- (let (n)
- (switch-to-buffer (get-buffer-create "*Life*") t)
- (erase-buffer)
- (kill-all-local-variables)
- (setq case-fold-search nil
- mode-name "Life"
- major-mode 'life-mode
- truncate-lines t
- life-current-generation 0
- life-generation-string "0"
- mode-line-buffer-identification '("Life: generation "
- life-generation-string)
- fill-column (1- (window-width))
- life-window-start 1)
- (buffer-disable-undo (current-buffer))
- ;; stuff in the random pattern
- (life-insert-random-pattern)
- ;; make sure (life-life-char) is used throughout
- (goto-char (point-min))
- (while (re-search-forward (life-not-void-regexp) nil t)
- (replace-match (life-life-string) t t))
- ;; center the pattern horizontally
- (goto-char (point-min))
- (setq n (/ (- fill-column (save-excursion (end-of-line) (point))) 2))
- (while (not (eobp))
- (indent-to n)
- (forward-line))
- ;; center the pattern vertically
- (setq n (/ (- (1- (window-height))
- (count-lines (point-min) (point-max)))
- 2))
- (goto-char (point-min))
- (newline n)
- (goto-char (point-max))
- (newline n)
- ;; pad lines out to fill-column
- (goto-char (point-min))
- (while (not (eobp))
- (end-of-line)
- (indent-to fill-column)
- (move-to-column fill-column)
- (delete-region (point) (progn (end-of-line) (point)))
- (forward-line))
- ;; expand tabs to spaces
- (untabify (point-min) (point-max))
- ;; before starting be sure the automaton has room to grow
- (life-expand-plane-if-needed)
- ;; compute initial neighbor deltas
- (life-compute-neighbor-deltas)))
-
-(defun life-compute-neighbor-deltas ()
- (setq life-neighbor-deltas
- (list -1 (- fill-column)
- (- (1+ fill-column)) (- (+ 2 fill-column))
- 1 fill-column (1+ fill-column)
- (+ 2 fill-column))))
-
-(defun life-insert-random-pattern ()
- (insert-rectangle
- (elt life-patterns (random (length life-patterns))))
- (insert ?\n))
-
-(defun life-increment-generation ()
- (life-increment life-current-generation)
- (setq life-generation-string (int-to-string life-current-generation)))
-
-(defun life-grim-reaper ()
- ;; Clear the match information. Later we check to see if it
- ;; is still clear, if so then all the cells have died.
- (store-match-data nil)
- (goto-char (point-min))
- ;; For speed declare all local variable outside the loop.
- (let (point char pivot living-neighbors list)
- (while (search-forward (life-life-string) nil t)
- (setq list life-neighbor-deltas
- living-neighbors 0
- pivot (1- (point)))
- (while list
- (setq point (+ pivot (car list))
- char (char-after point))
- (cond ((eq char (life-void-char))
- (subst-char-in-region point (1+ point)
- (life-void-char) 1 t))
- ((< char 3)
- (subst-char-in-region point (1+ point) char (1+ char) t))
- ((< char 9)
- (subst-char-in-region point (1+ point) char 9 t))
- ((>= char (life-life-char))
- (life-increment living-neighbors)))
- (setq list (cdr list)))
- (if (memq living-neighbors '(2 3))
- ()
- (subst-char-in-region pivot (1+ pivot)
- (life-life-char) (life-death-char) t))))
- (if (null (match-beginning 0))
- (life-extinct-quit))
- (subst-char-in-region 1 (point-max) 9 (life-void-char) t)
- (subst-char-in-region 1 (point-max) 1 (life-void-char) t)
- (subst-char-in-region 1 (point-max) 2 (life-void-char) t)
- (subst-char-in-region 1 (point-max) (life-birth-char) (life-life-char) t)
- (subst-char-in-region 1 (point-max) (life-death-char) (life-void-char) t))
-
-(defun life-expand-plane-if-needed ()
- (catch 'done
- (goto-char (point-min))
- (while (not (eobp))
- ;; check for life at beginning or end of line. If found at
- ;; either end, expand at both ends,
- (cond ((or (eq (following-char) (life-life-char))
- (eq (progn (end-of-line) (preceding-char)) (life-life-char)))
- (goto-char (point-min))
- (while (not (eobp))
- (insert (life-void-char))
- (end-of-line)
- (insert (life-void-char))
- (forward-char))
- (setq fill-column (+ 2 fill-column))
- (scroll-left 1)
- (life-compute-neighbor-deltas)
- (throw 'done t)))
- (forward-line)))
- (goto-char (point-min))
- ;; check for life within the first two lines of the buffer.
- ;; If present insert two lifeless lines at the beginning..
- (cond ((search-forward (life-life-string)
- (+ (point) fill-column fill-column 2) t)
- (goto-char (point-min))
- (insert-char (life-void-char) fill-column)
- (insert ?\n)
- (insert-char (life-void-char) fill-column)
- (insert ?\n)
- (setq life-window-start (+ life-window-start fill-column 1))))
- (goto-char (point-max))
- ;; check for life within the last two lines of the buffer.
- ;; If present insert two lifeless lines at the end.
- (cond ((search-backward (life-life-string)
- (- (point) fill-column fill-column 2) t)
- (goto-char (point-max))
- (insert-char (life-void-char) fill-column)
- (insert ?\n)
- (insert-char (life-void-char) fill-column)
- (insert ?\n)
- (setq life-window-start (+ life-window-start fill-column 1)))))
-
-(defun life-display-generation (sleeptime)
- (goto-char life-window-start)
- (recenter 0)
-
- ;; Redisplay; if the user has hit a key, exit the loop.
- (or (eq t (sit-for sleeptime))
- (throw 'life-exit nil)))
-
-(defun life-extinct-quit ()
- (life-display-generation 0)
- (signal 'life-extinct nil))
-
-(put 'life-extinct 'error-conditions '(life-extinct quit))
-(put 'life-extinct 'error-message "All life has perished")
-
-(provide 'life)
-
-;;; life.el ends here
diff --git a/lisp/play/meese.el b/lisp/play/meese.el
deleted file mode 100644
index 8a3ad922b8a..00000000000
--- a/lisp/play/meese.el
+++ /dev/null
@@ -1,27 +0,0 @@
-;;; meese.el --- protect the impressionable young minds of America
-
-;; This is in the public domain on account of being distributed since
-;; 1985 or 1986 without a copyright notice.
-
-;; Maintainer: FSF
-;; Keywords: games
-
-;;; Code:
-
-(defun protect-innocence-hook ()
- (let ((dir (file-name-directory buffer-file-name)))
- (if (and (equal buffer-file-name (expand-file-name "sex.6" dir))
- (file-exists-p buffer-file-name)
- (not (y-or-n-p "Are you over 18? ")))
- (progn
- (clear-visited-file-modtime)
- (setq buffer-file-name (expand-file-name "celibacy.1" dir))
- (let ((inhibit-read-only t)) ; otherwise (erase-buffer) may bomb.
- (erase-buffer)
- (insert-file-contents buffer-file-name t))
- (rename-buffer (file-name-nondirectory buffer-file-name))))))
-
-(add-hook 'find-file-hooks 'protect-innocence-hook)
-(provide 'meese)
-
-;;; meese.el ends here
diff --git a/lisp/play/morse.el b/lisp/play/morse.el
deleted file mode 100644
index 5ab461641e5..00000000000
--- a/lisp/play/morse.el
+++ /dev/null
@@ -1,121 +0,0 @@
-;;; morse.el --- Convert text to morse code and back.
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: Rick Farnbach <rick_farnbach@MENTORG.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(defvar morse-code '(("a" . ".-")
- ("b" . "-...")
- ("c" . "-.-.")
- ("d" . "-..")
- ("e" . ".")
- ("f" . "..-.")
- ("g" . "--.")
- ("h" . "....")
- ("i" . "..")
- ("j" . ".---")
- ("k" . "-.-")
- ("l" . ".-..")
- ("m" . "--")
- ("n" . "-.")
- ("o" . "---")
- ("p" . ".--.")
- ("q" . "--.-")
- ("r" . ".-.")
- ("s" . "...")
- ("t" . "-")
- ("u" . "..-")
- ("v" . "...-")
- ("w" . ".--")
- ("x" . "-..-")
- ("y" . "-.--")
- ("z" . "--..")
- ;; Punctuation
- ("=" . "-...-")
- ("?" . "..--..")
- ("/" . "-..-.")
- ("," . "--..--")
- ("." . ".-.-.-")
- (":" . "---...")
- ("'" . ".----.")
- ("-" . "-....-")
- ("(" . "-.--.-")
- (")" . "-.--.-")
- ;; Numbers
- ("0" . "-----")
- ("1" . ".----")
- ("2" . "..---")
- ("3" . "...--")
- ("4" . "....-")
- ("5" . ".....")
- ("6" . "-....")
- ("7" . "--...")
- ("8" . "---..")
- ("9" . "----."))
- "Morse code character set.")
-
-(defun morse-region (beg end)
- "Convert all text in a given region to morse code."
- (interactive "r")
- (if (integerp end)
- (setq end (copy-marker end)))
- (save-excursion
- (let ((sep "")
- str morse)
- (goto-char beg)
- (while (< (point) end)
- (setq str (downcase (buffer-substring (point) (1+ (point)))))
- (cond ((looking-at "\\s-+")
- (goto-char (match-end 0))
- (setq sep ""))
- ((setq morse (assoc str morse-code))
- (delete-char 1)
- (insert sep (cdr morse))
- (setq sep "/"))
- (t
- (forward-char 1)
- (setq sep "")))))))
-
-(defun unmorse-region (beg end)
- "Convert morse coded text in region to ordinary ASCII text."
- (interactive "r")
- (if (integerp end)
- (setq end (copy-marker end)))
- (save-excursion
- (let (str paren morse)
- (goto-char beg)
- (while (< (point) end)
- (if (null (looking-at "[-.]+"))
- (forward-char 1)
- (setq str (buffer-substring (match-beginning 0) (match-end 0)))
- (if (null (setq morse (rassoc str morse-code)))
- (goto-char (match-end 0))
- (replace-match
- (if (string-equal "(" (car morse))
- (if (setq paren (null paren)) "(" ")")
- (car morse)) t)
- (if (looking-at "/")
- (delete-char 1))))))))
-
-(provide 'morse)
-
-;;; morse.el ends here
diff --git a/lisp/play/mpuz.el b/lisp/play/mpuz.el
deleted file mode 100644
index a99182d1689..00000000000
--- a/lisp/play/mpuz.el
+++ /dev/null
@@ -1,443 +0,0 @@
-;;; mpuz.el --- multiplication puzzle for GNU Emacs
-
-;; Copyright (C) 1990 Free Software Foundation, Inc.
-
-;; Author: Philippe Schnoebelen <phs@lifia.imag.fr>
-;; Keywords: games
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; When this package is loaded, `M-x mpuz' generates a random multiplication
-;; puzzle. This is a multiplication example in which each digit has been
-;; consistently replaced with some letter. Your job is to reconstruct
-;; the original digits. Type `?' while the mode is active for detailed help.
-
-;;; Code:
-
-(random t) ; randomize
-
-(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.")
-
-(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))
-
-(defun mpuz-mode ()
- "Multiplication puzzle mode.
-
-You have to guess which letters stand for which digits in the
-multiplication displayed inside the `*Mult Puzzle*' buffer.
-
-You may enter a guess for a letter's value by typing first the letter,
-then the digit. Thus, to guess that A=3, type A 3.
-
-To leave the game to do other editing work, just switch buffers.
-Then you may resume the game with M-x mpuz.
-You may abort a game by typing \\<mpuz-mode-map>\\[mpuz-offer-abort]."
- (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 (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 multiplication.
-;; Every digit appears in the board, crypted or not.
-;;------------------------------------------------------
-(defvar mpuz-board (make-vector 10 nil)
- "The board associates to 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 (random 1000)
- B (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 respective 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 progress."
- (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.")))
-
-;;;###autoload
-(defun mpuz ()
- "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 (upcase last-command-char)
- 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 (message "%c = " letter-char)
- ;; <char> has been entered.
- ;; Print "<char> =" and
- ;; read <num> or = <num>
- (setq digit-char (read-char))
- (if (eq digit-char ?=)
- (setq digit-char (read-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)))
-
-;;; mpuz.el ends here
diff --git a/lisp/play/solitaire.el b/lisp/play/solitaire.el
deleted file mode 100644
index 4ce8b7d3ff0..00000000000
--- a/lisp/play/solitaire.el
+++ /dev/null
@@ -1,455 +0,0 @@
-;;; solitaire.el --- game of solitaire in Emacs Lisp
-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-
-;; Author: Jan Schormann <Jan.Schormann@informatik.uni-oldenburg.de>
-;; Created: Fri afternoon, Jun 3, 1994
-;; Keywords: games
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This mode is for playing a well-known game of solitaire
-;; in which you jump pegs across other pegs.
-
-;; The game itself is somehow self-explanatory. Read the help text to
-;; solitaire, and try it.
-
-;;; Code:
-
-(defvar solitaire-mode-map nil
- "Keymap for playing solitaire.")
-
-(if solitaire-mode-map
- ()
- (setq solitaire-mode-map (make-sparse-keymap))
- (suppress-keymap solitaire-mode-map t)
- (define-key solitaire-mode-map "\C-f" 'solitaire-right)
- (define-key solitaire-mode-map "\C-b" 'solitaire-left)
- (define-key solitaire-mode-map "\C-p" 'solitaire-up)
- (define-key solitaire-mode-map "\C-n" 'solitaire-down)
- (define-key solitaire-mode-map [return] 'solitaire-move)
- (substitute-key-definition 'undo 'solitaire-undo
- solitaire-mode-map global-map)
- (define-key solitaire-mode-map " " 'solitaire-do-check)
- (define-key solitaire-mode-map "q" 'solitaire-quit)
-
- (define-key solitaire-mode-map [right] 'solitaire-right)
- (define-key solitaire-mode-map [left] 'solitaire-left)
- (define-key solitaire-mode-map [up] 'solitaire-up)
- (define-key solitaire-mode-map [down] 'solitaire-down)
-
- (define-key solitaire-mode-map [S-right] 'solitaire-move-right)
- (define-key solitaire-mode-map [S-left] 'solitaire-move-left)
- (define-key solitaire-mode-map [S-up] 'solitaire-move-up)
- (define-key solitaire-mode-map [S-down] 'solitaire-move-down)
-
- (define-key solitaire-mode-map [kp-6] 'solitaire-right)
- (define-key solitaire-mode-map [kp-4] 'solitaire-left)
- (define-key solitaire-mode-map [kp-8] 'solitaire-up)
- (define-key solitaire-mode-map [kp-2] 'solitaire-down)
- (define-key solitaire-mode-map [kp-5] 'solitaire-center-point)
-
- (define-key solitaire-mode-map [S-kp-6] 'solitaire-move-right)
- (define-key solitaire-mode-map [S-kp-4] 'solitaire-move-left)
- (define-key solitaire-mode-map [S-kp-8] 'solitaire-move-up)
- (define-key solitaire-mode-map [S-kp-2] 'solitaire-move-down)
-
- (define-key solitaire-mode-map [kp-enter] 'solitaire-move)
- (define-key solitaire-mode-map [kp-0] 'solitaire-undo)
-
- ;; spoil it with s ;)
- (define-key solitaire-mode-map [?s] 'solitaire-solve)
-
- ;; (define-key solitaire-mode-map [kp-0] 'solitaire-hint) - Not yet provided ;)
- )
-
-;; Solitaire mode is suitable only for specially formatted data.
-(put 'solitaire-mode 'mode-class 'special)
-
-(defun solitaire-mode ()
- "Major mode for playing solitaire.
-To learn how to play solitaire, see the documentation for function
-`solitaire'.
-\\<solitaire-mode-map>
-The usual mnemonic keys move the cursor around the board; in addition,
-\\[solitaire-move] is a prefix character for actually moving a stone on the board."
- (interactive)
- (kill-all-local-variables)
- (use-local-map solitaire-mode-map)
- (setq truncate-lines t)
- (setq major-mode 'solitaire-mode)
- (setq mode-name "Solitaire")
- (run-hooks 'solitaire-mode-hook))
-
-(defvar solitaire-stones 0
- "Counter for the stones that are still there.")
-
-(defvar solitaire-center nil
- "Center of the board.")
-
-(defvar solitaire-start nil
- "Upper left corner of the board.")
-
-(defvar solitaire-start-x nil)
-(defvar solitaire-start-y nil)
-
-(defvar solitaire-end nil
- "Lower right corner of the board.")
-
-(defvar solitaire-end-x nil)
-(defvar solitaire-end-y nil)
-
-(defvar solitaire-auto-eval t
- "*Non-nil means check for possible moves after each major change.
-This takes a while, so switch this on if you like to be informed when
-the game is over, or off, if you are working on a slow machine.")
-
-(defconst solitaire-valid-directions
- '(solitaire-left solitaire-right solitaire-up solitaire-down))
-
-;;;###autoload
-(defun solitaire (arg)
- "Play Solitaire.
-
-To play Solitaire, type \\[solitaire].
-\\<solitaire-mode-map>
-Move around the board using the cursor keys.
-Move stones using \\[solitaire-move] followed by a direction key.
-Undo moves using \\[solitaire-undo].
-Check for possible moves using \\[solitaire-do-check].
-\(The variable solitaire-auto-eval controls whether to automatically
-check after each move or undo)
-
-What is Solitaire?
-
-I don't know who invented this game, but it seems to be rather old and
-its origin seems be northern Africa. Here's how to play:
-Initially, the board will look similar to this:
-
- Le Solitaire
- ============
-
- o o o
-
- o o o
-
- o o o o o o o
-
- o o o . o o o
-
- o o o o o o o
-
- o o o
-
- o o o
-
-Let's call the o's stones and the .'s holes. One stone fits into one
-hole. As you can see, all holes but one are occupied by stones. The
-aim of the game is to get rid of all but one stone, leaving that last
-one in the middle of the board if you're cool.
-
-A stone can be moved if there is another stone next to it, and a hole
-after that one. Thus there must be three fields in a row, either
-horizontally or vertically, up, down, left or right, which look like
-this: o o .
-
-Then the first stone is moved to the hole, jumping over the second,
-which therefore is taken away. The above thus `evaluates' to: . . o
-
-That's all. Here's the board after two moves:
-
- o o o
-
- . o o
-
- o o . o o o o
-
- o . o o o o o
-
- o o o o o o o
-
- o o o
-
- o o o
-
-Pick your favourite shortcuts:
-
-\\{solitaire-mode-map}"
-
- (interactive "P")
- (switch-to-buffer "*Solitaire*")
- (solitaire-mode)
- (setq buffer-read-only t)
- (setq solitaire-stones 32)
- (solitaire-insert-board)
- (solitaire-build-modeline)
- (goto-char (point-max))
- (setq solitaire-center (search-backward "."))
- (setq buffer-undo-list (list (point)))
- (set-buffer-modified-p nil))
-
-(defun solitaire-build-modeline ()
- (setq mode-line-format
- (list "" "---" 'mode-line-buffer-identification
- (if (< 1 solitaire-stones)
- (format "--> There are %d stones left <--" solitaire-stones)
- "------")
- 'global-mode-string " %[(" 'mode-name 'minor-mode-alist "%n"
- ")%]-%-"))
- (force-mode-line-update))
-
-(defun solitaire-insert-board ()
- (let* ((buffer-read-only nil)
- (w (window-width))
- (h (window-height))
- (hsep (cond ((> w 26) " ")
- ((> w 20) " ")
- (t "")))
- (vsep (cond ((> h 17) "\n\n")
- (t "\n")))
- (indent (make-string (/ (- w 7 (* 6 (length hsep))) 2) ?\ )))
- (erase-buffer)
- (insert (make-string (/ (- h 7 (if (> h 12) 3 0)
- (* 6 (1- (length vsep)))) 2) ?\n))
- (if (or (string= vsep "\n\n") (> h 12))
- (progn
- (insert (format "%sLe Solitaire\n" indent))
- (insert (format "%s============\n\n" indent))))
- (insert indent)
- (setq solitaire-start (point))
- (setq solitaire-start-x (current-column))
- (setq solitaire-start-y (solitaire-current-line))
- (insert (format " %s %so%so%so%s" hsep hsep hsep hsep vsep))
- (insert (format "%s %s %so%so%so%s" indent hsep hsep hsep hsep vsep))
- (insert (format "%so%so%so%so%so%so%so%s" indent hsep hsep hsep hsep hsep hsep vsep))
- (insert (format "%so%so%so%s" indent hsep hsep hsep))
- (setq solitaire-center (point))
- (insert (format ".%so%so%so%s" hsep hsep hsep vsep))
- (insert (format "%so%so%so%so%so%so%so%s" indent hsep hsep hsep hsep hsep hsep vsep))
- (insert (format "%s %s %so%so%so%s" indent hsep hsep hsep hsep vsep))
- (insert (format "%s %s %so%so%so%s %s " indent hsep hsep hsep hsep hsep hsep))
- (setq solitaire-end (point))
- (setq solitaire-end-x (current-column))
- (setq solitaire-end-y (solitaire-current-line))
- ))
-
-(defun solitaire-right ()
- (interactive)
- (let ((start (point)))
- (forward-char)
- (while (= ?\ (following-char))
- (forward-char))
- (if (or (= 0 (following-char))
- (= ?\ (following-char))
- (= ?\n (following-char)))
- (goto-char start))))
-
-(defun solitaire-left ()
- (interactive)
- (let ((start (point)))
- (backward-char)
- (while (= ?\ (following-char))
- (backward-char))
- (if (or (= 0 (preceding-char))
- (= ?\ (following-char))
- (= ?\n (following-char)))
- (goto-char start))))
-
-(defun solitaire-up ()
- (interactive)
- (let ((start (point))
- (c (current-column)))
- (forward-line -1)
- (move-to-column c)
- (while (and (= ?\n (following-char))
- (forward-line -1)
- (move-to-column c)
- (not (bolp))))
- (if (or (= 0 (preceding-char))
- (= ?\ (following-char))
- (= ?\= (following-char))
- (= ?\n (following-char)))
- (goto-char start)
- )))
-
-(defun solitaire-down ()
- (interactive)
- (let ((start (point))
- (c (current-column)))
- (forward-line 1)
- (move-to-column c)
- (while (and (= ?\n (following-char))
- (forward-line 1)
- (move-to-column c)
- (not (eolp))))
- (if (or (= 0 (following-char))
- (= ?\ (following-char))
- (= ?\n (following-char)))
- (goto-char start))))
-
-(defun solitaire-center-point ()
- (interactive)
- (goto-char solitaire-center))
-
-(defun solitaire-move-right () (interactive) (solitaire-move '[right]))
-(defun solitaire-move-left () (interactive) (solitaire-move '[left]))
-(defun solitaire-move-up () (interactive) (solitaire-move '[up]))
-(defun solitaire-move-down () (interactive) (solitaire-move '[down]))
-
-(defun solitaire-possible-move (movesymbol)
- "Check if a move is possible from current point in the specified direction.
-MOVESYMBOL specifies the direction.
-Returns either a string, indicating cause of contraindication, or a
-list containing three numbers: starting field, skipped field (from
-which a stone will be taken away) and target."
-
- (save-excursion
- (let (move)
- (fset 'move movesymbol)
- (if (memq movesymbol solitaire-valid-directions)
- (let ((start (point))
- (skip (progn (move) (point)))
- (target (progn (move) (point))))
- (if (= skip target)
- "Off Board!"
- (if (or (/= ?o (char-after start))
- (/= ?o (char-after skip))
- (/= ?. (char-after target)))
- "Wrong move!"
- (list start skip target))))
- "Not a valid direction"))))
-
-(defun solitaire-move (dir)
- "Pseudo-prefix command to move a stone in Solitaire."
- (interactive "kMove where? ")
- (let* ((class (solitaire-possible-move (lookup-key solitaire-mode-map dir)))
- (buffer-read-only nil))
- (if (stringp class)
- (error class)
- (let ((start (car class))
- (skip (car (cdr class)))
- (target (car (cdr (cdr class)))))
- (goto-char start)
- (delete-char 1)
- (insert ?.)
- (goto-char skip)
- (delete-char 1)
- (insert ?.)
- (goto-char target)
- (delete-char 1)
- (insert ?o)
- (goto-char target)
- (setq solitaire-stones (1- solitaire-stones))
- (solitaire-build-modeline)
- (if solitaire-auto-eval (solitaire-do-check))))))
-
-(defun solitaire-undo (arg)
- "Undo a move in Solitaire."
- (interactive "P")
- (let ((buffer-read-only nil))
- (undo arg))
- (save-excursion
- (setq solitaire-stones
- (let ((count 0))
- (goto-char solitaire-end)
- (while (search-backward "o" solitaire-start 'done)
- (and (>= (current-column) solitaire-start-x)
- (<= (current-column) solitaire-end-x)
- (>= (solitaire-current-line) solitaire-start-y)
- (<= (solitaire-current-line) solitaire-end-y)
- (setq count (1+ count))))
- count)))
- (solitaire-build-modeline)
- (if solitaire-auto-eval (solitaire-do-check)))
-
-(defun solitaire-check ()
- (save-excursion
- (if (= 1 solitaire-stones)
- 0
- (goto-char solitaire-end)
- (let ((count 0))
- (while (search-backward "o" solitaire-start 'done)
- (and (>= (current-column) solitaire-start-x)
- (<= (current-column) solitaire-end-x)
- (>= (solitaire-current-line) solitaire-start-y)
- (<= (solitaire-current-line) solitaire-end-y)
- (mapcar
- (lambda (movesymbol)
- (if (listp (solitaire-possible-move movesymbol))
- (setq count (1+ count))))
- solitaire-valid-directions)))
- count))))
-
-(defun solitaire-do-check (&optional arg)
- "Check for any possible moves in Solitaire."
- (interactive "P")
- (let ((moves (solitaire-check)))
- (cond ((= 1 solitaire-stones)
- (message "Yeah! You made it! Only the King is left!"))
- ((zerop moves)
- (message "Sorry, no more possible moves."))
- ((= 1 moves)
- (message "There is one possible move."))
- (t (message "There are %d possible moves." moves)))))
-
-(defun solitaire-current-line ()
- "Return the vertical position of point.
-Seen in info on text lines."
- (+ (count-lines (point-min) (point))
- (if (= (current-column) 0) 1 0)
- -1))
-
-(defun solitaire-quit ()
- "Quit playing Solitaire."
- (interactive)
- (kill-buffer "*Solitaire*"))
-
-;; And here's the spoiler:)
-(defun solitaire-solve ()
- "Spoil solitaire by solving the game for you - nearly ...
-... stops with five stones left ;)"
- (interactive)
- (let ((allmoves [up up S-down up left left S-right up up left S-down
- up up right right S-left down down down S-up up
- S-down down down down S-up left left down
- S-right left left up up S-down right right right
- S-left left S-right right right right S-left
- right down down S-up down down left left S-right
- up up up S-down down S-up up up up S-down up
- right right S-left down right right down S-up
- left left left S-right right S-left down down
- left S-right S-up S-left S-left S-down S-right
- up S-right left left])
- ;; down down S-up left S-right
- ;; right S-left
- (solitaire-auto-eval nil))
- (solitaire-center-point)
- (mapcar (lambda (op)
- (if (memq op '(S-left S-right S-up S-down))
- (sit-for 0.2))
- (execute-kbd-macro (vector op))
- (if (memq op '(S-left S-right S-up S-down))
- (sit-for 0.4)))
- allmoves))
- (solitaire-do-check))
-
-(provide 'solitaire)
-
-;;; solitaire.el ends here
diff --git a/lisp/play/spook.el b/lisp/play/spook.el
deleted file mode 100644
index cf6685af51b..00000000000
--- a/lisp/play/spook.el
+++ /dev/null
@@ -1,69 +0,0 @@
-;;; spook.el --- spook phrase utility for overloading the NSA line eater
-
-;; Copyright (C) 1988, 1993 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: games
-;; Created: May 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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Steve Strassmann <straz@media-lab.media.mit.edu> didn't write
-;; this, and even if he did, he really didn't mean for you to use it
-;; in an anarchistic way.
-;;
-;; To use this:
-;; Just before sending mail, do M-x spook.
-;; A number of phrases will be inserted into your buffer, to help
-;; give your message that extra bit of attractiveness for automated
-;; keyword scanners. Help defeat the NSA trunk trawler!
-
-;;; Code:
-
-(require 'cookie1)
-
-; Variables
-(defvar spook-phrases-file (concat data-directory "spook.lines")
- "Keep your favorite phrases here.")
-
-(defvar spook-phrase-default-count 15
- "Default number of phrases to insert")
-
-;;;###autoload
-(defun spook ()
- "Adds that special touch of class to your outgoing mail."
- (interactive)
- (cookie-insert spook-phrases-file
- spook-phrase-default-count
- "Checking authorization..."
- "Checking authorization...Approved"))
-
-;;;###autoload
-(defun snarf-spooks ()
- "Return a vector containing the lines from `spook-phrases-file'."
- (cookie-snarf spook-phrases-file
- "Checking authorization..."
- "Checking authorization...Approved"))
-
-;; Note: the implementation that used to take up most of this file has been
-;; cleaned up, generalized, gratuitously broken by esr, and now resides in
-;; cookie1.el.
-
-;;; spook.el ends here
diff --git a/lisp/play/studly.el b/lisp/play/studly.el
deleted file mode 100644
index b5aafcab09a..00000000000
--- a/lisp/play/studly.el
+++ /dev/null
@@ -1,63 +0,0 @@
-;;; studly.el --- StudlyCaps (tm)(r)(c)(xxx)
-
-;;; This is in the public domain, since it was distributed
-;;; by its author without a copyright notice in 1986.
-
-;; Keywords: games
-
-;;; Commentary:
-
-;; Functions to studlycapsify a region, word, or buffer. Possibly the
-;; esoteric significance of studlycapsification escapes you; that is,
-;; you suffer from autostudlycapsifibogotification. Too bad.
-
-;;; Code:
-
-(defun studlify-region (begin end)
- "Studlify-case the region"
- (interactive "*r")
- (save-excursion
- (goto-char begin)
- (setq begin (point))
- (while (and (<= (point) end)
- (not (looking-at "\\W*\\'")))
- (forward-word 1)
- (backward-word 1)
- (setq begin (max (point) begin))
- (forward-word 1)
- (let ((offset 0)
- (word-end (min (point) end))
- c)
- (goto-char begin)
- (while (< (point) word-end)
- (setq offset (+ offset (following-char)))
- (forward-char 1))
- (setq offset (+ offset (following-char)))
- (goto-char begin)
- (while (< (point) word-end)
- (setq c (following-char))
- (if (and (= (% (+ c offset) 4) 2)
- (let ((ch (following-char)))
- (or (and (>= ch ?a) (<= ch ?z))
- (and (>= ch ?A) (<= ch ?Z)))))
- (progn
- (delete-char 1)
- (insert (logxor c ? ))))
- (forward-char 1))
- (setq begin (point))))))
-
-(defun studlify-word (count)
- "Studlify-case the current word, or COUNT words if given an argument"
- (interactive "*p")
- (let ((begin (point)) end rb re)
- (forward-word count)
- (setq end (point))
- (setq rb (min begin end) re (max begin end))
- (studlify-region rb re)))
-
-(defun studlify-buffer ()
- "Studlify-case the current buffer"
- (interactive "*")
- (studlify-region (point-min) (point-max)))
-
-;;; studly.el ends here
diff --git a/lisp/play/yow.el b/lisp/play/yow.el
deleted file mode 100644
index 501758e94a4..00000000000
--- a/lisp/play/yow.el
+++ /dev/null
@@ -1,130 +0,0 @@
-;;; yow.el --- quote random zippyisms
-
-;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Author: Richard Mlynarik
-;; Keywords: games
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Important pinheadery for GNU Emacs.
-;;
-;; See cookie1.el for implementation. Note --- the `n' argument of yow
-;; from the 18.xx implementation is no longer; we only support *random*
-;; random access now.
-
-;;; Code:
-
-(require 'cookie1)
-
-(defvar yow-file (concat data-directory "yow.lines")
- "File containing pertinent pinhead phrases.")
-
-(defconst yow-load-message "Am I CONSING yet?...")
-(defconst yow-after-load-message "I have SEEN the CONSING!!")
-
-;;;###autoload
-(defun yow (&optional insert)
- "Return or display a random Zippy quotation. With prefix arg, insert it."
- (interactive "P")
- (let ((yow (cookie yow-file yow-load-message yow-after-load-message)))
- (cond (insert
- (insert yow))
- ((not (interactive-p))
- yow)
- ((not (string-match "\n" yow))
- (delete-windows-on (get-buffer-create "*Help*"))
- (message "%s" yow))
- (t
- (message "Yow!")
- (with-output-to-temp-buffer "*Help*"
- (princ yow)
- (save-excursion
- (set-buffer standard-output)
- (help-mode)))))))
-
-(defsubst read-zippyism (prompt &optional require-match)
- "Read a Zippyism from the minibuffer with completion, prompting with PROMPT.
-If optional second arg is non-nil, require input to match a completion."
- (read-cookie prompt yow-file yow-load-message yow-after-load-message
- require-match))
-
-;;;###autoload
-(defun insert-zippyism (&optional zippyism)
- "Prompt with completion for a known Zippy quotation, and insert it at point."
- (interactive (list (read-zippyism "Pinhead wisdom: " t)))
- (insert zippyism))
-
-;;;###autoload
-(defun apropos-zippy (regexp)
- "Return a list of all Zippy quotes matching REGEXP.
-If called interactively, display a list of matches."
- (interactive "sApropos Zippy (regexp): ")
- ;; Make sure yows are loaded
- (cookie yow-file yow-load-message yow-after-load-message)
- (let* ((case-fold-search t)
- (cookie-table-symbol (intern yow-file cookie-cache))
- (string-table (symbol-value cookie-table-symbol))
- (matches nil)
- (len (length string-table))
- (i 0))
- (save-match-data
- (while (< i len)
- (and (string-match regexp (aref string-table i))
- (setq matches (cons (aref string-table i) matches)))
- (setq i (1+ i))))
- (and matches
- (setq matches (sort matches 'string-lessp)))
- (and (interactive-p)
- (cond ((null matches)
- (message "No matches found."))
- (t
- (let ((l matches))
- (with-output-to-temp-buffer "*Zippy Apropos*"
- (while l
- (princ (car l))
- (setq l (cdr l))
- (and l (princ "\n\n"))))))))
- matches))
-
-
-;; Yowza!! Feed zippy quotes to the doctor. Watch results.
-;; fun, fun, fun. Entertainment for hours...
-;;
-;; written by Kayvan Aghaiepour
-
-;;;###autoload
-(defun psychoanalyze-pinhead ()
- "Zippy goes to the analyst."
- (interactive)
- (doctor) ; start the psychotherapy
- (message "")
- (switch-to-buffer "*doctor*")
- (sit-for 0)
- (while (not (input-pending-p))
- (insert-string (yow))
- (sit-for 0)
- (doctor-ret-or-read 1)
- (doctor-ret-or-read 1)))
-
-(provide 'yow)
-
-;;; yow.el ends here
diff --git a/lisp/progmodes/ada-mode.el b/lisp/progmodes/ada-mode.el
deleted file mode 100644
index cf74a914ea2..00000000000
--- a/lisp/progmodes/ada-mode.el
+++ /dev/null
@@ -1,3741 +0,0 @@
-;;; ada-mode.el --- An Emacs major-mode for editing Ada source.
-;;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
-
-;;; Authors: Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de>
-;;; Rolf Ebert <ebert@inf.enst.fr>
-
-;;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; This mode is a complete rewrite of a major mode for editing Ada 83
-;;; and Ada 95 source code under Emacs-19. It contains completely new
-;;; indenting code and support for code browsing (see ada-xref).
-
-
-;;; USAGE
-;;; =====
-;;; Emacs should enter ada-mode when you load an ada source (*.ad[abs]).
-;;;
-;;; When you have entered ada-mode, you may get more info by pressing
-;;; C-h m. You may also get online help describing various functions by:
-;;; C-h d <Name of function you want described>
-
-
-;;; HISTORY
-;;; =======
-;;; The first Ada mode for GNU Emacs was written by V. Broman in
-;;; 1985. He based his work on the already existing Modula-2 mode.
-;;; This was distributed as ada.el in versions of Emacs prior to 19.29.
-;;;
-;;; Lynn Slater wrote an extensive Ada mode in 1989. It consisted of
-;;; several files with support for dired commands and other nice
-;;; things. It is currently available from the PAL
-;;; (wuarchive.wustl.edu:/languages/ada) as ada-mode-1.06a.tar.Z.
-;;;
-;;; The probably very first Ada mode (called electric-ada.el) was
-;;; written by Steven D. Litvintchouk and Steven M. Rosen for the
-;;; Gosling Emacs. L. Slater based his development on ada.el and
-;;; electric-ada.el.
-;;;
-;;; The current Ada mode is a complete rewrite by M. Heritsch and
-;;; R. Ebert. Some ideas from the ada-mode mailing list have been
-;;; added. Some of the functionality of L. Slater's mode has not
-;;; (yet) been recoded in this new mode. Perhaps you prefer sticking
-;;; to his version.
-
-
-;;; KNOWN BUGS
-;;; ==========
-;;;
-;;; In the presence of comments and/or incorrect syntax
-;;; ada-format-paramlist produces weird results.
-;;; -------------------
-;;; Indenting of some tasking constructs is still buggy.
-;;; -------------------
-;;; package Test is
-;;; -- If I hit return on the "type" line it will indent the next line
-;;; -- in another 3 space instead of heading out to the "(". If I hit
-;;; -- tab or return it reindents the line correctly but does not initially.
-;;; type Wait_Return is (Read_Success, Read_Timeout, Wait_Timeout,
-;;; Nothing_To_Wait_For_In_Wait_List);
-;;; -------------------
-
-
-
-;;; CREDITS
-;;; =======
-;;;
-;;; Many thanks to
-;;; Philippe Waroquiers (PW) <philippe@cfmu.eurocontrol.be> in particular,
-;;; woodruff@stc.llnl.gov (John Woodruff)
-;;; jj@ddci.dk (Jesper Joergensen)
-;;; gse@ocsystems.com (Scott Evans)
-;;; comar@LANG8.CS.NYU.EDU (Cyrille Comar)
-;;; and others for their valuable hints.
-
-;;;--------------------
-;;; USER OPTIONS
-;;;--------------------
-
-;; ---- configure indentation
-
-(defvar ada-indent 3
- "*Defines the size of Ada indentation.")
-
-(defvar ada-broken-indent 2
- "*# of columns to indent the continuation of a broken line.")
-
-(defvar ada-label-indent -4
- "*# of columns to indent a label.")
-
-(defvar ada-stmt-end-indent 0
- "*# of columns to indent a statement end keyword in a separate line.
-Examples are 'is', 'loop', 'record', ...")
-
-(defvar ada-when-indent 3
- "*Defines the indentation for 'when' relative to 'exception' or 'case'.")
-
-(defvar ada-indent-record-rel-type 3
- "*Defines the indentation for 'record' relative to 'type' or 'use'.")
-
-(defvar ada-indent-comment-as-code t
- "*If non-nil, comment-lines get indented as Ada code.")
-
-(defvar ada-indent-is-separate t
- "*If non-nil, 'is separate' or 'is abstract' on a single line are indented.")
-
-(defvar ada-indent-to-open-paren t
- "*If non-nil, indent according to the innermost open parenthesis.")
-
-(defvar ada-search-paren-char-count-limit 3000
- "*Search that many characters for an open parenthesis.")
-
-
-;; ---- other user options
-
-(defvar ada-tab-policy 'indent-auto
- "*Control behaviour of the TAB key.
-Must be one of `indent-rigidly', `indent-auto', `gei', `indent-af'
-or `always-tab'.
-
-`indent-rigidly' : always adds ada-indent blanks at the beginning of the line.
-`indent-auto' : use indentation functions in this file.
-`gei' : use David Kågedal's Generic Indentation Engine.
-`indent-af' : use Gary E. Barnes' ada-format.el
-`always-tab' : do indent-relative.")
-
-(defvar ada-move-to-declaration nil
- "*If non-nil, `ada-move-to-start' moves point to the subprog declaration,
-not to 'begin'.")
-
-(defvar ada-spec-suffix ".ads"
- "*Suffix of Ada specification files.")
-
-(defvar ada-body-suffix ".adb"
- "*Suffix of Ada body files.")
-
-(defvar ada-language-version 'ada95
- "*Do we program in `ada83' or `ada95'?")
-
-(defvar ada-case-keyword 'downcase-word
- "*Function to call to adjust the case of Ada keywords.
-It may be `downcase-word', `upcase-word', `ada-loose-case-word' or
-`capitalize-word'.")
-
-(defvar ada-case-identifier 'ada-loose-case-word
- "*Function to call to adjust the case of an Ada identifier.
-It may be `downcase-word', `upcase-word', `ada-loose-case-word' or
-`capitalize-word'.")
-
-(defvar ada-case-attribute 'capitalize-word
- "*Function to call to adjust the case of Ada attributes.
-It may be `downcase-word', `upcase-word', `ada-loose-case-word' or
-`capitalize-word'.")
-
-(defvar ada-auto-case t
- "*Non-nil automatically changes case of preceding word while typing.
-Casing is done according to `ada-case-keyword', `ada-case-identifier'
-and `ada-cacse-attribute'.")
-
-(defvar ada-clean-buffer-before-saving nil
- "*If non-nil, `remove-trailing-spaces' and `untabify' buffer before saving.")
-
-(defvar ada-mode-hook nil
- "*List of functions to call when Ada Mode is invoked.
-This is a good place to add Ada environment specific bindings.")
-
-(defvar ada-external-pretty-print-program "aimap"
- "*External pretty printer to call from within Ada Mode.")
-
-(defvar ada-tmp-directory "/tmp/"
- "*Directory to store the temporary file for the Ada pretty printer.")
-
-(defvar ada-fill-comment-prefix "-- "
- "*This is inserted in the first columns when filling a comment paragraph.")
-
-(defvar ada-fill-comment-postfix " --"
- "*This is inserted at the end of each line when filling a comment paragraph.
-with `ada-fill-comment-paragraph-postfix'.")
-
-(defvar ada-krunch-args "0"
- "*Argument of gnatk8, a string containing the max number of characters.
-Set to 0, if you don't use crunched filenames.")
-
-;;; ---- end of user configurable variables
-
-
-(defvar ada-mode-abbrev-table nil
- "Abbrev table used in Ada mode.")
-(define-abbrev-table 'ada-mode-abbrev-table ())
-
-(defvar ada-mode-map ()
- "Local keymap used for Ada Mode.")
-
-(defvar ada-mode-syntax-table nil
- "Syntax table to be used for editing Ada source code.")
-
-(defvar ada-mode-symbol-syntax-table nil
- "Syntax table for Ada, where `_' is a word constituent.")
-
-(defconst ada-83-keywords
- "\\<\\(abort\\|abs\\|accept\\|access\\|all\\|and\\|array\\|\
-at\\|begin\\|body\\|case\\|constant\\|declare\\|delay\\|delta\\|\
-digits\\|do\\|else\\|elsif\\|end\\|entry\\|exception\\|exit\\|for\\|\
-function\\|generic\\|goto\\|if\\|in\\|is\\|limited\\|loop\\|mod\\|\
-new\\|not\\|null\\|of\\|or\\|others\\|out\\|package\\|pragma\\|\
-private\\|procedure\\|raise\\|range\\|record\\|rem\\|renames\\|\
-return\\|reverse\\|select\\|separate\\|subtype\\|task\\|terminate\\|\
-then\\|type\\|use\\|when\\|while\\|with\\|xor\\)\\>"
-; "\\<\\(a\\(b\\(ort\\|s\\)\\|cce\\(pt\\|ss\\)\\|ll\\|nd\\|rray\\|t\\)\\|\
-;b\\(egin\\|ody\\)\\|c\\(ase\\|onstant\\)\\|\
-;d\\(e\\(clare\\|l\\(ay\\|ta\\)\\)\\|igits\\|o\\)\\|\
-;e\\(ls\\(e\\|if\\)\\|n\\(d\\|try\\)\\|x\\(ception\\|it\\)\\)\\|\
-;f\\(or\\|unction\\)\\|g\\(eneric\\|oto\\)\\|i[fns]\\|l\\(imited\\|oop\\)\\|\
-;mod\\|n\\(ew\\|ot\\|ull\\)\\|o\\([fr]\\|thers\\|ut\\)\\|\
-;p\\(ackage\\|r\\(agma\\|ivate\\|ocedure\\)\\)\\|\
-;r\\(a\\(ise\\|nge\\)\\|e\\(cord\\|m\\|names\\|turn\\|verse\\)\\)\\|\
-;s\\(e\\(lect\\|parate\\)\\|ubtype\\)\\|use\\|
-;t\\(ask\\|erminate\\|hen\\|ype\\)\\|w\\(h\\(en\\|ile\\)\\|ith\\)\\|xor\\)\\>"
- "regular expression for looking at Ada83 keywords.")
-
-(defconst ada-95-keywords
- "\\<\\(abort\\|abs\\|abstract\\|accept\\|access\\|aliased\\|\
-all\\|and\\|array\\|at\\|begin\\|body\\|case\\|constant\\|declare\\|\
-delay\\|delta\\|digits\\|do\\|else\\|elsif\\|end\\|entry\\|\
-exception\\|exit\\|for\\|function\\|generic\\|goto\\|if\\|in\\|\
-is\\|limited\\|loop\\|mod\\|new\\|not\\|null\\|of\\|or\\|others\\|\
-out\\|package\\|pragma\\|private\\|procedure\\|protected\\|raise\\|\
-range\\|record\\|rem\\|renames\\|requeue\\|return\\|reverse\\|\
-select\\|separate\\|subtype\\|tagged\\|task\\|terminate\\|then\\|\
-type\\|until\\|use\\|when\\|while\\|with\\|xor\\)\\>"
- "regular expression for looking at Ada95 keywords.")
-
-(defvar ada-keywords ada-95-keywords
- "Regular expression for looking at Ada keywords.")
-
-(defvar ada-ret-binding nil
- "Variable to save key binding of RET when casing is activated.")
-
-(defvar ada-lfd-binding nil
- "Variable to save key binding of LFD when casing is activated.")
-
-;;; ---- Regexps to find procedures/functions/packages
-
-(defconst ada-ident-re
- "[a-zA-Z0-9_\\.]+"
- "Regexp matching Ada (qualified) identifiers.")
-
-(defvar ada-procedure-start-regexp
- "^[ \t]*\\(procedure\\|function\\|task\\)[ \t\n]+\\([a-zA-Z0-9_\\.]+\\)"
- "Regexp used to find Ada procedures/functions.")
-
-(defvar ada-package-start-regexp
- "^[ \t]*\\(package\\)"
- "Regexp used to find Ada packages")
-
-
-;;; ---- regexps for indentation functions
-
-(defvar ada-block-start-re
- "\\<\\(begin\\|select\\|declare\\|private\\|or\\|generic\\|\
-exception\\|loop\\|else\\|\
-\\(\\(limited\\|abstract\\|tagged\\)[ \t]+\\)*record\\)\\>"
- "Regexp for keywords starting Ada blocks.")
-
-(defvar ada-end-stmt-re
- "\\(;\\|=>\\|^[ \t]*separate[ \t]+([a-zA-Z0-9_\\.]+)\\|\
-\\<\\(begin\\|else\\|record\\|loop\\|select\\|do\\|\
-declare\\|generic\\|private\\)\\>\\|\
-^[ \t]*\\(package\\|procedure\\|function\\)[ \ta-zA-Z0-9_\\.]+is\\|\
-^[ \t]*exception\\>\\)"
- "Regexp of possible ends for a non-broken statement.
-A new statement starts after these.")
-
-(defvar ada-loop-start-re
- "\\<\\(for\\|while\\|loop\\)\\>"
- "Regexp for the start of a loop.")
-
-(defvar ada-subprog-start-re
- "\\<\\(procedure\\|protected\\|package\\|function\\|\
-task\\|accept\\|entry\\)\\>"
- "Regexp for the start of a subprogram.")
-
-
-;; Written by Christian Egli <Christian.Egli@hcsd.hac.com>
-;;
-(defvar ada-imenu-generic-expression
- '((nil "^\\s-*\\(procedure\\|function\\)\\s-+\\([A-Za-z0-9_]+\\)" 2)
- ("Type Defs" "^\\s-*\\(sub\\)?type\\s-+\\([A-Za-z0-9_]+\\)" 2))
-
- "Imenu generic expression for Ada mode. See `imenu-generic-expression'.")
-
-;;;-------------
-;;; functions
-;;;-------------
-
-(defun ada-xemacs ()
- (or (string-match "Lucid" emacs-version)
- (string-match "XEmacs" emacs-version)))
-
-(defun ada-create-syntax-table ()
- "Create the syntax table for Ada Mode."
- ;; There are two different syntax-tables. The standard one declares
- ;; `_' as a symbol constituent, in the second one, it is a word
- ;; constituent. For some search and replacing routines we
- ;; temporarily switch between the two.
- (setq ada-mode-syntax-table (make-syntax-table))
- (set-syntax-table ada-mode-syntax-table)
-
- ;; define string brackets (% is alternative string bracket)
- (modify-syntax-entry ?% "\"" ada-mode-syntax-table)
- (modify-syntax-entry ?\" "\"" ada-mode-syntax-table)
-
- (modify-syntax-entry ?\# "$" ada-mode-syntax-table)
-
- (modify-syntax-entry ?: "." ada-mode-syntax-table)
- (modify-syntax-entry ?\; "." ada-mode-syntax-table)
- (modify-syntax-entry ?& "." ada-mode-syntax-table)
- (modify-syntax-entry ?\| "." ada-mode-syntax-table)
- (modify-syntax-entry ?+ "." ada-mode-syntax-table)
- (modify-syntax-entry ?* "." ada-mode-syntax-table)
- (modify-syntax-entry ?/ "." ada-mode-syntax-table)
- (modify-syntax-entry ?= "." ada-mode-syntax-table)
- (modify-syntax-entry ?< "." ada-mode-syntax-table)
- (modify-syntax-entry ?> "." ada-mode-syntax-table)
- (modify-syntax-entry ?$ "." ada-mode-syntax-table)
- (modify-syntax-entry ?\[ "." ada-mode-syntax-table)
- (modify-syntax-entry ?\] "." ada-mode-syntax-table)
- (modify-syntax-entry ?\{ "." ada-mode-syntax-table)
- (modify-syntax-entry ?\} "." ada-mode-syntax-table)
- (modify-syntax-entry ?. "." ada-mode-syntax-table)
- (modify-syntax-entry ?\\ "." ada-mode-syntax-table)
- (modify-syntax-entry ?\' "." ada-mode-syntax-table)
-
- ;; a single hyphen is punctuation, but a double hyphen starts a comment
- (modify-syntax-entry ?- ". 12" ada-mode-syntax-table)
-
- ;; and \f and \n end a comment
- (modify-syntax-entry ?\f "> " ada-mode-syntax-table)
- (modify-syntax-entry ?\n "> " ada-mode-syntax-table)
-
- ;; define what belongs in ada symbols
- (modify-syntax-entry ?_ "_" ada-mode-syntax-table)
-
- ;; define parentheses to match
- (modify-syntax-entry ?\( "()" ada-mode-syntax-table)
- (modify-syntax-entry ?\) ")(" ada-mode-syntax-table)
-
- (setq ada-mode-symbol-syntax-table (copy-syntax-table ada-mode-syntax-table))
- (modify-syntax-entry ?_ "w" ada-mode-symbol-syntax-table)
- )
-
-
-;;;###autoload
-(defun ada-mode ()
- "Ada Mode is the major mode for editing Ada code.
-
-Bindings are as follows: (Note: 'LFD' is control-j.)
-
- Indent line '\\[ada-tab]'
- Indent line, insert newline and indent the new line. '\\[newline-and-indent]'
-
- Re-format the parameter-list point is in '\\[ada-format-paramlist]'
- Indent all lines in region '\\[ada-indent-region]'
- Call external pretty printer program '\\[ada-call-pretty-printer]'
-
- Adjust case of identifiers and keywords in region '\\[ada-adjust-case-region]'
- Adjust case of identifiers and keywords in buffer '\\[ada-adjust-case-buffer]'
-
- Call EXTERNAL pretty printer (if you have one) '\\[ada-call-pretty-printer]'
-
- Fill comment paragraph '\\[ada-fill-comment-paragraph]'
- Fill comment paragraph and justify each line '\\[ada-fill-comment-paragraph-justify]'
- Fill comment paragraph, justify and append postfix '\\[ada-fill-comment-paragraph-postfix]'
-
- Next func/proc/task '\\[ada-next-procedure]' Previous func/proc/task '\\[ada-previous-procedure]'
- Next package '\\[ada-next-package]' Previous package '\\[ada-previous-package]'
-
- Goto matching start of current 'end ...;' '\\[ada-move-to-start]'
- Goto end of current block '\\[ada-move-to-end]'
-
-Comments are handled using standard GNU Emacs conventions, including:
- Start a comment '\\[indent-for-comment]'
- Comment region '\\[comment-region]'
- Uncomment region '\\[ada-uncomment-region]'
- Continue comment on next line '\\[indent-new-comment-line]'
-
-If you use imenu.el:
- Display index-menu of functions & procedures '\\[imenu]'
-
-If you use find-file.el:
- Switch to other file (Body <-> Spec) '\\[ff-find-other-file]'
- or '\\[ff-mouse-find-other-file]
- Switch to other file in other window '\\[ada-ff-other-window]'
- or '\\[ff-mouse-find-other-file-other-window]
- If you use this function in a spec and no body is available, it gets created
- with body stubs.
-
-If you use ada-xref.el:
- Goto declaration: '\\[ada-point-and-xref]' on the identifier
- or '\\[ada-goto-declaration]' with point on the identifier
- Complete identifier: '\\[ada-complete-identifier]'
- Execute Gnatf: '\\[ada-gnatf-current]'"
-
- (interactive)
- (kill-all-local-variables)
-
- (make-local-variable 'require-final-newline)
- (setq require-final-newline t)
-
- (make-local-variable 'comment-start)
- (setq comment-start "-- ")
-
- ;; comment end must be set because it may hold a wrong value if
- ;; this buffer had been in another mode before. RE
- (make-local-variable 'comment-end)
- (setq comment-end "")
-
- (make-local-variable 'comment-start-skip) ;; used by autofill
- (setq comment-start-skip "--+[ \t]*")
-
- (make-local-variable 'indent-line-function)
- (setq indent-line-function 'ada-indent-current-function)
-
- (make-local-variable 'fill-column)
- (setq fill-column 75)
-
- (make-local-variable 'comment-column)
- (setq comment-column 40)
-
- (make-local-variable 'parse-sexp-ignore-comments)
- (setq parse-sexp-ignore-comments t)
-
- (make-local-variable 'case-fold-search)
- (setq case-fold-search t)
-
- (make-local-variable 'fill-paragraph-function)
- (setq fill-paragraph-function 'ada-fill-comment-paragraph)
-
- (make-local-variable 'imenu-generic-expression)
- (setq imenu-generic-expression ada-imenu-generic-expression)
-
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '((ada-font-lock-keywords
- ada-font-lock-keywords-1
- ada-font-lock-keywords-2)
- nil t
- ((?\_ . "w"))
- beginning-of-line))
-
- (setq major-mode 'ada-mode)
- (setq mode-name "Ada")
-
- (setq blink-matching-paren t)
-
- (use-local-map ada-mode-map)
-
- (if ada-mode-syntax-table
- (set-syntax-table ada-mode-syntax-table)
- (ada-create-syntax-table))
-
- (if ada-clean-buffer-before-saving
- (progn
- ;; remove all spaces at the end of lines in the whole buffer.
- (add-hook 'local-write-file-hooks 'ada-remove-trailing-spaces)
- ;; convert all tabs to the correct number of spaces.
- (add-hook 'local-write-file-hooks 'ada-untabify-buffer)))
-
-
- ;; add menu 'Ada' to the menu bar
- (ada-add-ada-menu)
-
- (run-hooks 'ada-mode-hook)
-
- ;; the following has to be done after running the ada-mode-hook
- ;; because users might want to set the values of these variable
- ;; inside the hook (MH)
-
- (cond ((eq ada-language-version 'ada83)
- (setq ada-keywords ada-83-keywords))
- ((eq ada-language-version 'ada95)
- (setq ada-keywords ada-95-keywords)))
-
- (if ada-auto-case
- (ada-activate-keys-for-case)))
-
-
-;;;--------------------------
-;;; Fill Comment Paragraph
-;;;--------------------------
-
-(defun ada-fill-comment-paragraph-justify ()
- "Fills current comment paragraph and justifies each line as well."
- (interactive)
- (ada-fill-comment-paragraph t))
-
-
-(defun ada-fill-comment-paragraph-postfix ()
- "Fills current comment paragraph and justifies each line as well.
-Prompts for a postfix to be appended to each line."
- (interactive)
- (ada-fill-comment-paragraph t t))
-
-
-(defun ada-fill-comment-paragraph (&optional justify postfix)
- "Fills the current comment paragraph.
-If JUSTIFY is non-nil, each line is justified as well.
-If POSTFIX and JUSTIFY are non-nil, `ada-fill-comment-postfix' is appended
-to each filled and justified line.
-If `ada-indent-comment-as-code' is non-nil, the paragraph is idented."
- (interactive "P")
- (let ((opos (point-marker))
- (begin nil)
- (end nil)
- (end-2 nil)
- (indent nil)
- (ada-fill-comment-old-postfix "")
- (fill-prefix nil))
-
- ;; check if inside comment
- (if (not (ada-in-comment-p))
- (error "not inside comment"))
-
- ;; prompt for postfix if wanted
- (if (and justify
- postfix)
- (setq ada-fill-comment-postfix
- (read-from-minibuffer "enter new postfix string: "
- ada-fill-comment-postfix)))
-
- ;; prompt for old postfix to remove if necessary
- (if (and justify
- postfix)
- (setq ada-fill-comment-old-postfix
- (read-from-minibuffer "enter already existing postfix string: "
- ada-fill-comment-postfix)))
-
- ;;
- ;; find limits of paragraph
- ;;
- (message "filling comment paragraph ...")
- (save-excursion
- (back-to-indentation)
- ;; find end of paragraph
- (while (and (looking-at "--.*$")
- (not (looking-at "--[ \t]*$")))
- (forward-line 1)
- (back-to-indentation))
- (beginning-of-line)
- (setq end (point-marker))
- (goto-char opos)
- ;; find begin of paragraph
- (back-to-indentation)
- (while (and (looking-at "--.*$")
- (not (looking-at "--[ \t]*$")))
- (forward-line -1)
- (back-to-indentation))
- (forward-line 1)
- ;; get indentation to calculate width for filling
- (ada-indent-current)
- (back-to-indentation)
- (setq indent (current-column))
- (setq begin (point-marker)))
-
- ;; delete old postfix if necessary
- (if (and justify
- postfix)
- (save-excursion
- (goto-char begin)
- (while (re-search-forward (concat ada-fill-comment-old-postfix
- "\n")
- end t)
- (replace-match "\n"))))
-
- ;; delete leading whitespace and uncomment
- (save-excursion
- (goto-char begin)
- (beginning-of-line)
- (while (re-search-forward "^[ \t]*--[ \t]*" end t)
- (replace-match "")))
-
- ;; calculate fill width
- (setq fill-column (- fill-column indent
- (length ada-fill-comment-prefix)
- (if postfix
- (length ada-fill-comment-postfix)
- 0)))
- ;; fill paragraph
- (fill-region begin (1- end) justify)
- (setq fill-column (+ fill-column indent
- (length ada-fill-comment-prefix)
- (if postfix
- (length ada-fill-comment-postfix)
- 0)))
- ;; find end of second last line
- (save-excursion
- (goto-char end)
- (forward-line -2)
- (end-of-line)
- (setq end-2 (point-marker)))
-
- ;; re-comment and re-indent region
- (save-excursion
- (goto-char begin)
- (indent-to indent)
- (insert ada-fill-comment-prefix)
- (while (re-search-forward "\n" (1- end-2) t)
- (replace-match (concat "\n" ada-fill-comment-prefix))
- (beginning-of-line)
- (indent-to indent)))
-
- ;; append postfix if wanted
- (if (and justify
- postfix
- ada-fill-comment-postfix)
- (progn
- ;; append postfix up to there
- (save-excursion
- (goto-char begin)
- (while (re-search-forward "\n" (1- end-2) t)
- (replace-match (concat ada-fill-comment-postfix "\n")))
-
- ;; fill last line and append postfix
- (end-of-line)
- (insert-char ?
- (- fill-column
- (current-column)
- (length ada-fill-comment-postfix)))
- (insert ada-fill-comment-postfix))))
-
- ;; delete the extra line that gets inserted somehow(??)
- (save-excursion
- (goto-char (1- end))
- (end-of-line)
- (delete-char 1))
-
- (message "filling comment paragraph ... done")
- (goto-char opos))
- t)
-
-
-;;;--------------------------------;;;
-;;; Call External Pretty Printer ;;;
-;;;--------------------------------;;;
-
-(defun ada-call-pretty-printer ()
- "Calls the external Pretty Printer.
-The name is specified in `ada-external-pretty-print-program'. Saves the
-current buffer in a directory specified by `ada-tmp-directory',
-starts the pretty printer as external process on that file and then
-reloads the beautified program in the buffer and cleans up
-`ada-tmp-directory'."
- (interactive)
- (let ((filename-with-path buffer-file-name)
- (curbuf (current-buffer))
- (orgpos (point))
- (mesgbuf nil) ;; for byte-compiling
- (file-path (file-name-directory buffer-file-name))
- (filename-without-path (file-name-nondirectory buffer-file-name))
- (tmp-file-with-directory
- (concat ada-tmp-directory
- (file-name-nondirectory buffer-file-name))))
- ;;
- ;; save buffer in temporary file
- ;;
- (message "saving current buffer to temporary file ...")
- (write-file tmp-file-with-directory)
- (auto-save-mode nil)
- (message "saving current buffer to temporary file ... done")
- ;;
- ;; call external pretty printer program
- ;;
-
- (message "running external pretty printer ...")
- ;; create a temporary buffer for messages of pretty printer
- (setq mesgbuf (get-buffer-create "Pretty Printer Messages"))
- ;; execute pretty printer on temporary file
- (call-process ada-external-pretty-print-program
- nil mesgbuf t
- tmp-file-with-directory)
- ;; display messages if there are some
- (if (buffer-modified-p mesgbuf)
- ;; show the message buffer
- (display-buffer mesgbuf t)
- ;; kill the message buffer
- (kill-buffer mesgbuf))
- (message "running external pretty printer ... done")
- ;;
- ;; kill current buffer and load pretty printer output
- ;; or restore old buffer
- ;;
- (if (y-or-n-p
- "Really replace current buffer with pretty printer output ? ")
- (progn
- (set-buffer-modified-p nil)
- (kill-buffer curbuf)
- (find-file tmp-file-with-directory))
- (message "old buffer contents restored"))
- ;;
- ;; delete temporary file and restore information of current buffer
- ;;
- (delete-file tmp-file-with-directory)
- (set-visited-file-name filename-with-path)
- (auto-save-mode t)
- (goto-char orgpos)))
-
-
-;;;---------------
-;;; auto-casing
-;;;---------------
-
-;; from Philippe Waroquiers <philippe@cfmu.eurocontrol.be>
-;; modifiedby RE and MH
-
-(defun ada-after-keyword-p ()
- ;; returns t if cursor is after a keyword.
- (save-excursion
- (forward-word -1)
- (and (save-excursion
- (or
- (= (point) (point-min))
- (backward-char 1))
- (not (looking-at "_"))) ; (MH)
- (looking-at (concat ada-keywords "[^_]")))))
-
-(defun ada-after-char-p ()
- ;; returns t if after ada character "'". This is interpreted as being
- ;; in a character constant.
- (save-excursion
- (if (> (point) 2)
- (progn
- (forward-char -2)
- (looking-at "'"))
- nil)))
-
-
-(defun ada-adjust-case (&optional force-identifier)
- "Adjust the case of the word before the just typed character.
-Respect options `ada-case-keyword', `ada-case-identifier', and
-`ada-case-attribute'.
-If FORCE-IDENTIFIER is non-nil then also adjust keyword as identifier." ; (MH)
- (forward-char -1)
- (if (and (> (point) 1) (not (or (ada-in-string-p)
- (ada-in-comment-p)
- (ada-after-char-p))))
- (if (eq (char-syntax (char-after (1- (point)))) ?w)
- (if (save-excursion
- (forward-word -1)
- (or (= (point) (point-min))
- (backward-char 1))
- (looking-at "'"))
- (funcall ada-case-attribute -1)
- (if (and
- (not force-identifier) ; (MH)
- (ada-after-keyword-p))
- (funcall ada-case-keyword -1)
- (funcall ada-case-identifier -1)))))
- (forward-char 1))
-
-
-(defun ada-adjust-case-interactive (arg)
- (interactive "P")
- (let ((lastk last-command-char))
- (cond ((or (eq lastk ?\n)
- (eq lastk ?\r))
- ;; horrible kludge
- (insert " ")
- (ada-adjust-case)
- ;; horrible dekludge
- (delete-backward-char 1)
- ;; some special keys and their bindings
- (cond
- ((eq lastk ?\n)
- (funcall ada-lfd-binding))
- ((eq lastk ?\r)
- (funcall ada-ret-binding))))
- ((eq lastk ?\C-i) (ada-tab))
- ((self-insert-command (prefix-numeric-value arg))))
- ;; if there is a keyword in front of the underscore
- ;; then it should be part of an identifier (MH)
- (if (eq lastk ?_)
- (ada-adjust-case t)
- (ada-adjust-case))))
-
-
-(defun ada-activate-keys-for-case ()
- ;; save original keybindings to allow swapping ret/lfd
- ;; when casing is activated
- ;; the 'or ...' is there to be sure that the value will not
- ;; be changed again when Ada Mode is called more than once (MH)
- (or ada-ret-binding
- (setq ada-ret-binding (key-binding "\C-M")))
- (or ada-lfd-binding
- (setq ada-lfd-binding (key-binding "\C-j")))
- ;; call case modifying function after certain keys.
- (mapcar (function (lambda(key) (define-key
- ada-mode-map
- (char-to-string key)
- 'ada-adjust-case-interactive)))
- '( ?` ?~ ?! ?@ ?# ?$ ?% ?^ ?& ?* ?( ?) ?- ?= ?+ ?[ ?{ ?] ?}
- ?_ ?\\ ?| ?\; ?: ?' ?\" ?< ?, ?. ?> ?? ?/ ?\n 32 ?\r )))
-;; deleted ?\t from above list
-
-;;
-;; added by MH
-;;
-(defun ada-loose-case-word (&optional arg)
- "Capitalizes the first letter and the letters following `_'.
-ARG is ignored, it's there to fit the standard casing functions' style."
- (let ((pos (point))
- (first t))
- (skip-chars-backward "a-zA-Z0-9_")
- (while (or first
- (search-forward "_" pos t))
- (and first
- (setq first nil))
- (insert-char (upcase (following-char)) 1)
- (delete-char 1))
- (goto-char pos)))
-
-
-;;
-;; added by MH
-;;
-(defun ada-adjust-case-region (from to)
- "Adjusts the case of all words in the region.
-Attention: This function might take very long for big regions !"
- (interactive "*r")
- (let ((begin nil)
- (end nil)
- (keywordp nil)
- (reldiff nil))
- (unwind-protect
- (save-excursion
- (set-syntax-table ada-mode-symbol-syntax-table)
- (goto-char to)
- ;;
- ;; loop: look for all identifiers and keywords
- ;;
- (while (re-search-backward
- "[^a-zA-Z0-9_]\\([a-zA-Z0-9_]+\\)[^a-zA-Z0-9_]"
- from
- t)
- ;;
- ;; print status message
- ;;
- (setq reldiff (- (point) from))
- (message "adjusting case ... %5d characters left"
- (- (point) from))
- (forward-char 1)
- (or
- ;; do nothing if it is a string or comment
- (ada-in-string-or-comment-p)
- (progn
- ;;
- ;; get the identifier or keyword
- ;;
- (setq begin (point))
- (setq keywordp (looking-at (concat ada-keywords "[^_]")))
- (skip-chars-forward "a-zA-Z0-9_")
- ;;
- ;; casing according to user-option
- ;;
- (if keywordp
- (funcall ada-case-keyword -1)
- (funcall ada-case-identifier -1))
- (goto-char begin))))
- (message "adjusting case ... done"))
- (set-syntax-table ada-mode-syntax-table))))
-
-
-;;
-;; added by MH
-;;
-(defun ada-adjust-case-buffer ()
- "Adjusts the case of all words in the whole buffer.
-ATTENTION: This function might take very long for big buffers !"
- (interactive "*")
- (ada-adjust-case-region (point-min) (point-max)))
-
-
-;;;------------------------;;;
-;;; Format Parameter Lists ;;;
-;;;------------------------;;;
-
-(defun ada-format-paramlist ()
- "Reformats a parameter list.
-ATTENTION: 1) Comments inside the list are killed !
- 2) If the syntax is not correct (especially, if there are
- semicolons missing), it can get totally confused !
-In such a case, use `undo', correct the syntax and try again."
-
- (interactive)
- (let ((begin nil)
- (end nil)
- (delend nil)
- (paramlist nil))
- (unwind-protect
- (progn
- (set-syntax-table ada-mode-symbol-syntax-table)
-
- ;; check if really inside parameter list
- (or (ada-in-paramlist-p)
- (error "not in parameter list"))
- ;;
- ;; find start of current parameter-list
- ;;
- (ada-search-ignore-string-comment
- (concat ada-subprog-start-re "\\|\\<body\\>" ) t nil)
- (ada-search-ignore-string-comment "(" nil nil t)
- (backward-char 1)
- (setq begin (point))
-
- ;;
- ;; find end of parameter-list
- ;;
- (forward-sexp 1)
- (setq delend (point))
- (delete-char -1)
-
- ;;
- ;; find end of last parameter-declaration
- ;;
- (ada-search-ignore-string-comment "[^ \t\n]" t nil t)
- (forward-char 1)
- (setq end (point))
-
- ;;
- ;; build a list of all elements of the parameter-list
- ;;
- (setq paramlist (ada-scan-paramlist (1+ begin) end))
-
- ;;
- ;; delete the original parameter-list
- ;;
- (delete-region begin (1- delend))
-
- ;;
- ;; insert the new parameter-list
- ;;
- (goto-char begin)
- (ada-insert-paramlist paramlist))
-
- ;;
- ;; restore syntax-table
- ;;
- (set-syntax-table ada-mode-syntax-table)
- )))
-
-
-(defun ada-scan-paramlist (begin end)
- ;; Scans a parameter-list between BEGIN and END and returns a list
- ;; of its contents.
- ;; The list has the following format:
- ;;
- ;; Name of Param in? out? access? Name of Type Default-Exp or nil
- ;;
- ;; ( ('Name_Param_1' t nil t Type_Param_1 ':= expression')
- ;; ('Name_Param_2' nil nil t Type_Param_2 nil) )
-
- (let ((paramlist (list))
- (param (list))
- (notend t)
- (apos nil)
- (epos nil)
- (semipos nil)
- (match-cons nil))
-
- (goto-char begin)
- ;;
- ;; loop until end of last parameter
- ;;
- (while notend
-
- ;;
- ;; find first character of parameter-declaration
- ;;
- (ada-goto-next-non-ws)
- (setq apos (point))
-
- ;;
- ;; find last character of parameter-declaration
- ;;
- (if (setq match-cons
- (ada-search-ignore-string-comment "[ \t\n]*;" nil end t))
- (progn
- (setq epos (car match-cons))
- (setq semipos (cdr match-cons)))
- (setq epos end))
-
- ;;
- ;; read name(s) of parameter(s)
- ;;
- (goto-char apos)
- (looking-at "\\([a-zA-Z0-9_, \t\n]*[a-zA-Z0-9_]\\)[ \t\n]*:[^=]")
-
- (setq param (list (buffer-substring (match-beginning 1)
- (match-end 1))))
- (ada-search-ignore-string-comment ":" nil epos t)
-
- ;;
- ;; look for 'in'
- ;;
- (setq apos (point))
- (setq param
- (append param
- (list
- (consp
- (ada-search-ignore-string-comment "\\<in\\>"
- nil
- epos
- t)))))
-
- ;;
- ;; look for 'out'
- ;;
- (goto-char apos)
- (setq param
- (append param
- (list
- (consp
- (ada-search-ignore-string-comment "\\<out\\>"
- nil
- epos
- t)))))
-
- ;;
- ;; look for 'access'
- ;;
- (goto-char apos)
- (setq param
- (append param
- (list
- (consp
- (ada-search-ignore-string-comment "\\<access\\>"
- nil
- epos
- t)))))
-
- ;;
- ;; skip 'in'/'out'/'access'
- ;;
- (goto-char apos)
- (ada-goto-next-non-ws)
- (while (looking-at "\\<\\(in\\|out\\|access\\)\\>")
- (forward-word 1)
- (ada-goto-next-non-ws))
-
- ;;
- ;; read type of parameter
- ;;
- (looking-at "\\<[a-zA-Z0-9_\\.]+\\>")
- (setq param
- (append param
- (list
- (buffer-substring (match-beginning 0)
- (match-end 0)))))
-
- ;;
- ;; read default-expression, if there is one
- ;;
- (goto-char (setq apos (match-end 0)))
- (setq param
- (append param
- (list
- (if (setq match-cons
- (ada-search-ignore-string-comment ":="
- nil
- epos
- t))
- (buffer-substring (car match-cons)
- epos)
- nil))))
- ;;
- ;; add this parameter-declaration to the list
- ;;
- (setq paramlist (append paramlist (list param)))
-
- ;;
- ;; check if it was the last parameter
- ;;
- (if (eq epos end)
- (setq notend nil)
- (goto-char semipos))
-
- ) ; end of loop
-
- (reverse paramlist)))
-
-
-(defun ada-insert-paramlist (paramlist)
- ;; Inserts a formatted PARAMLIST in the buffer.
- ;; See doc of `ada-scan-paramlist' for the format.
- (let ((i (length paramlist))
- (parlen 0)
- (typlen 0)
- (temp 0)
- (inp nil)
- (outp nil)
- (accessp nil)
- (column nil)
- (orgpoint 0)
- (firstcol nil))
-
- ;;
- ;; loop until last parameter
- ;;
- (while (not (zerop i))
- (setq i (1- i))
-
- ;;
- ;; get max length of parameter-name
- ;;
- (setq parlen
- (if (<= parlen (setq temp
- (length (nth 0 (nth i paramlist)))))
- temp
- parlen))
-
- ;;
- ;; get max length of type-name
- ;;
- (setq typlen
- (if (<= typlen (setq temp
- (length (nth 4 (nth i paramlist)))))
- temp
- typlen))
-
- ;;
- ;; is there any 'in' ?
- ;;
- (setq inp
- (or inp
- (nth 1 (nth i paramlist))))
-
- ;;
- ;; is there any 'out' ?
- ;;
- (setq outp
- (or outp
- (nth 2 (nth i paramlist))))
-
- ;;
- ;; is there any 'access' ?
- ;;
- (setq accessp
- (or accessp
- (nth 3 (nth i paramlist))))) ; end of loop
-
- ;;
- ;; does paramlist already start on a separate line ?
- ;;
- (if (save-excursion
- (re-search-backward "^.\\|[^ \t]" nil t)
- (looking-at "^."))
- ;; yes => re-indent it
- (ada-indent-current)
- ;;
- ;; no => insert newline and indent it
- ;;
- (progn
- (ada-indent-current)
- (newline)
- (delete-horizontal-space)
- (setq orgpoint (point))
- (setq column (save-excursion
- (funcall (ada-indent-function) orgpoint)))
- (indent-to column)
- ))
-
- (insert "(")
-
- (setq firstcol (current-column))
- (setq i (length paramlist))
-
- ;;
- ;; loop until last parameter
- ;;
- (while (not (zerop i))
- (setq i (1- i))
- (setq column firstcol)
-
- ;;
- ;; insert parameter-name, space and colon
- ;;
- (insert (nth 0 (nth i paramlist)))
- (indent-to (+ column parlen 1))
- (insert ": ")
- (setq column (current-column))
-
- ;;
- ;; insert 'in' or space
- ;;
- (if (nth 1 (nth i paramlist))
- (insert "in ")
- (if (and
- (or inp
- accessp)
- (not (nth 3 (nth i paramlist))))
- (insert " ")))
-
- ;;
- ;; insert 'out' or space
- ;;
- (if (nth 2 (nth i paramlist))
- (insert "out ")
- (if (and
- (or outp
- accessp)
- (not (nth 3 (nth i paramlist))))
- (insert " ")))
-
- ;;
- ;; insert 'access'
- ;;
- (if (nth 3 (nth i paramlist))
- (insert "access "))
-
- (setq column (current-column))
-
- ;;
- ;; insert type-name and, if necessary, space and default-expression
- ;;
- (insert (nth 4 (nth i paramlist)))
- (if (nth 5 (nth i paramlist))
- (progn
- (indent-to (+ column typlen 1))
- (insert (nth 5 (nth i paramlist)))))
-
- ;;
- ;; check if it was the last parameter
- ;;
- (if (not (zerop i))
- ;; no => insert ';' and newline and indent
- (progn
- (insert ";")
- (newline)
- (indent-to firstcol))
- ;; yes
- (insert ")"))
-
- ) ; end of loop
-
- ;;
- ;; if anything follows, except semicolon:
- ;; put it in a new line and indent it
- ;;
- (if (not (looking-at "[ \t]*[;\n]"))
- (ada-indent-newline-indent))
-
- ))
-
-
-;;;----------------------------;;;
-;;; Move To Matching Start/End ;;;
-;;;----------------------------;;;
-
-(defun ada-move-to-start ()
- "Moves point to the matching start of the current Ada structure."
- (interactive)
- (let ((pos (point)))
- (unwind-protect
- (progn
- (set-syntax-table ada-mode-symbol-syntax-table)
-
- (message "searching for block start ...")
- (save-excursion
- ;;
- ;; do nothing if in string or comment or not on 'end ...;'
- ;; or if an error occurs during processing
- ;;
- (or
- (ada-in-string-or-comment-p)
- (and (progn
- (or (looking-at "[ \t]*\\<end\\>")
- (backward-word 1))
- (or (looking-at "[ \t]*\\<end\\>")
- (backward-word 1))
- (or (looking-at "[ \t]*\\<end\\>")
- (error "not on end ...;")))
- (ada-goto-matching-start 1)
- (setq pos (point))
-
- ;;
- ;; on 'begin' => go on, according to user option
- ;;
- ada-move-to-declaration
- (looking-at "\\<begin\\>")
- (ada-goto-matching-decl-start)
- (setq pos (point))))
-
- ) ; end of save-excursion
-
- ;; now really move to the found position
- (goto-char pos)
- (message "searching for block start ... done"))
-
- ;;
- ;; restore syntax-table
- ;;
- (set-syntax-table ada-mode-syntax-table))))
-
-
-(defun ada-move-to-end ()
- "Moves point to the matching end of the current block around point.
-Moves to 'begin' if in a declarative part."
- (interactive)
- (let ((pos (point))
- (decstart nil)
- (packdecl nil))
- (unwind-protect
- (progn
- (set-syntax-table ada-mode-symbol-syntax-table)
-
- (message "searching for block end ...")
- (save-excursion
-
- (forward-char 1)
- (cond
- ;; directly on 'begin'
- ((save-excursion
- (ada-goto-previous-word)
- (looking-at "\\<begin\\>"))
- (ada-goto-matching-end 1))
- ;; on first line of defun declaration
- ((save-excursion
- (and (ada-goto-stmt-start)
- (looking-at "\\<function\\>\\|\\<procedure\\>" )))
- (ada-search-ignore-string-comment "\\<begin\\>"))
- ;; on first line of task declaration
- ((save-excursion
- (and (ada-goto-stmt-start)
- (looking-at "\\<task\\>" )
- (forward-word 1)
- (ada-search-ignore-string-comment "[^ \n\t]")
- (not (backward-char 1))
- (looking-at "\\<body\\>")))
- (ada-search-ignore-string-comment "\\<begin\\>"))
- ;; accept block start
- ((save-excursion
- (and (ada-goto-stmt-start)
- (looking-at "\\<accept\\>" )))
- (ada-goto-matching-end 0))
- ;; package start
- ((save-excursion
- (and (ada-goto-matching-decl-start t)
- (looking-at "\\<package\\>")))
- (ada-goto-matching-end 1))
- ;; inside a 'begin' ... 'end' block
- ((save-excursion
- (ada-goto-matching-decl-start t))
- (ada-search-ignore-string-comment "\\<begin\\>"))
- ;; (hopefully ;-) everything else
- (t
- (ada-goto-matching-end 1)))
- (setq pos (point))
-
- ) ; end of save-excursion
-
- ;; now really move to the found position
- (goto-char pos)
- (message "searching for block end ... done"))
-
- ;;
- ;; restore syntax-table
- ;;
- (set-syntax-table ada-mode-syntax-table))))
-
-
-;;;-----------------------------;;;
-;;; Functions For Indentation ;;;
-;;;-----------------------------;;;
-
-;; ---- main functions for indentation
-
-(defun ada-indent-region (beg end)
- "Indents the region using `ada-indent-current' on each line."
- (interactive "*r")
- (goto-char beg)
- (let ((block-done 0)
- (lines-remaining (count-lines beg end))
- (msg (format "indenting %4d lines %%4d lines remaining ..."
- (count-lines beg end)))
- (endmark (copy-marker end)))
- ;; catch errors while indenting
- (condition-case err
- (while (< (point) endmark)
- (if (> block-done 9)
- (progn (message msg lines-remaining)
- (setq block-done 0)))
- (if (looking-at "^$") nil
- (ada-indent-current))
- (forward-line 1)
- (setq block-done (1+ block-done))
- (setq lines-remaining (1- lines-remaining)))
- ;; show line number where the error occurred
- (error
- (error "line %d: %s" (1+ (count-lines (point-min) (point))) err)))
- (message "indenting ... done")))
-
-
-(defun ada-indent-newline-indent ()
- "Indents the current line, inserts a newline and then indents the new line."
- (interactive "*")
- (let ((column)
- (orgpoint))
-
- (ada-indent-current)
- (newline)
- (delete-horizontal-space)
- (setq orgpoint (point))
-
- (unwind-protect
- (progn
- (set-syntax-table ada-mode-symbol-syntax-table)
-
- (setq column (save-excursion
- (funcall (ada-indent-function) orgpoint))))
-
- ;;
- ;; restore syntax-table
- ;;
- (set-syntax-table ada-mode-syntax-table))
-
- (indent-to column)
-
- ;; The following is needed to ensure that indentation will still be
- ;; correct if something follows behind point when typing LFD
- ;; For example: Imagine point to be there (*) when LFD is typed:
- ;; while cond loop
- ;; null; *end loop;
- ;; Result without the following statement would be:
- ;; while cond loop
- ;; null;
- ;; *end loop;
- ;; You would then have to type TAB to correct it.
- ;; If that doesn't bother you, you can comment out the following
- ;; statement to speed up indentation a LITTLE bit.
-
- (if (not (looking-at "[ \t]*$"))
- (ada-indent-current))
- ))
-
-
-(defun ada-indent-current ()
- "Indents current line as Ada code.
-This works by two steps:
- 1) It moves point to the end of the previous code line.
- Then it calls the function to calculate the indentation for the
- following line as if a newline would be inserted there.
- The calculated column # is saved and the old position of point
- is restored.
- 2) Then another function is called to calculate the indentation for
- the current line, based on the previously calculated column #."
-
- (interactive)
-
- (unwind-protect
- (progn
- (set-syntax-table ada-mode-symbol-syntax-table)
-
- (let ((line-end)
- (orgpoint (point-marker))
- (cur-indent)
- (prev-indent)
- (prevline t))
-
- ;;
- ;; first step
- ;;
- (save-excursion
- (if (ada-goto-prev-nonblank-line t)
- ;;
- ;; we are not in the first accessible line in the buffer
- ;;
- (progn
- ;;(end-of-line)
- ;;(forward-char 1)
- ;; we are already at the BOL
- (forward-line 1)
- (setq line-end (point))
- (setq prev-indent
- (save-excursion
- (funcall (ada-indent-function) line-end))))
- (progn ; first line of buffer -> set indent
- (beginning-of-line) ; to 0
- (delete-horizontal-space)
- (setq prevline nil))))
-
- (if prevline
- ;;
- ;; we are not in the first accessible line in the buffer
- ;;
- (progn
- ;;
- ;; second step
- ;;
- (back-to-indentation)
- (setq cur-indent (ada-get-current-indent prev-indent))
- ;; only reindent if indentation is different then the current
- (if (= (current-column) cur-indent)
- nil
- (delete-horizontal-space)
- (indent-to cur-indent))
- ;;
- ;; restore position of point
- ;;
- (goto-char orgpoint)
- (if (< (current-column) (current-indentation))
- (back-to-indentation))))))
-
- ;;
- ;; restore syntax-table
- ;;
- (set-syntax-table ada-mode-syntax-table)))
-
-
-(defun ada-get-current-indent (prev-indent)
- ;; Returns the column # to indent the current line to.
- ;; PREV-INDENT is the indentation resulting from the previous lines.
- (let ((column nil)
- (pos nil)
- (match-cons nil))
-
- (cond
- ;;
- ;; in open parenthesis, but not in parameter-list
- ;;
- ((and
- ada-indent-to-open-paren
- (not (ada-in-paramlist-p))
- (setq column (ada-in-open-paren-p)))
- ;; check if we have something like this (Table_Component_Type =>
- ;; Source_File_Record,)
- (save-excursion
- (if (and (ada-search-ignore-string-comment "[^ \t]" t nil)
- (looking-at "\n")
- (ada-search-ignore-string-comment "[^ \t\n]" t nil)
- (looking-at ">"))
- (setq column (+ ada-broken-indent column))))
- column)
-
- ;;
- ;; end
- ;;
- ((looking-at "\\<end\\>")
- (save-excursion
- (ada-goto-matching-start 1)
-
- ;;
- ;; found 'loop' => skip back to 'while' or 'for'
- ;; if 'loop' is not on a separate line
- ;;
- (if (and
- (looking-at "\\<loop\\>")
- (save-excursion
- (back-to-indentation)
- (not (looking-at "\\<loop\\>"))))
- (if (save-excursion
- (and
- (setq match-cons
- (ada-search-ignore-string-comment
- ada-loop-start-re t nil))
- (not (looking-at "\\<loop\\>"))))
- (goto-char (car match-cons))))
-
- (current-indentation)))
- ;;
- ;; exception
- ;;
- ((looking-at "\\<exception\\>")
- (save-excursion
- (ada-goto-matching-start 1)
- (current-indentation)))
- ;;
- ;; when
- ;;
- ((looking-at "\\<when\\>")
- (save-excursion
- (ada-goto-matching-start 1)
- (+ (current-indentation) ada-when-indent)))
- ;;
- ;; else
- ;;
- ((looking-at "\\<else\\>")
- (if (save-excursion
- (ada-goto-previous-word)
- (looking-at "\\<or\\>"))
- prev-indent
- (save-excursion
- (ada-goto-matching-start 1 nil t)
- (current-indentation))))
- ;;
- ;; elsif
- ;;
- ((looking-at "\\<elsif\\>")
- (save-excursion
- (ada-goto-matching-start 1 nil t)
- (current-indentation)))
- ;;
- ;; then
- ;;
- ((looking-at "\\<then\\>")
- (if (save-excursion
- (ada-goto-previous-word)
- (looking-at "\\<and\\>"))
- prev-indent
- (save-excursion
- (ada-search-ignore-string-comment "\\<elsif\\>\\|\\<if\\>" t nil)
- (+ (current-indentation) ada-stmt-end-indent))))
- ;;
- ;; loop
- ;;
- ((looking-at "\\<loop\\>")
- (setq pos (point))
- (save-excursion
- (goto-char (match-end 0))
- (ada-goto-stmt-start)
- (if (looking-at "\\<loop\\>\\|\\<if\\>")
- prev-indent
- (progn
- (if (not (looking-at ada-loop-start-re))
- (ada-search-ignore-string-comment ada-loop-start-re
- nil pos))
- (if (looking-at "\\<loop\\>")
- prev-indent
- (+ (current-indentation) ada-stmt-end-indent))))))
- ;;
- ;; begin
- ;;
- ((looking-at "\\<begin\\>")
- (save-excursion
- (if (ada-goto-matching-decl-start t)
- (current-indentation)
- (progn
- (message "no matching declaration start")
- prev-indent))))
- ;;
- ;; is
- ;;
- ((looking-at "\\<is\\>")
- (if (and
- ada-indent-is-separate
- (save-excursion
- (goto-char (match-end 0))
- (ada-goto-next-non-ws (save-excursion
- (end-of-line)
- (point)))
- (looking-at "\\<abstract\\>\\|\\<separate\\>")))
- (save-excursion
- (ada-goto-stmt-start)
- (+ (current-indentation) ada-indent))
- (save-excursion
- (ada-goto-stmt-start)
- (+ (current-indentation) ada-stmt-end-indent))))
- ;;
- ;; record
- ;;
- ((looking-at "\\<record\\>")
- (save-excursion
- (ada-search-ignore-string-comment
- "\\<\\(type\\|use\\)\\>" t nil)
- (if (looking-at "\\<use\\>")
- (ada-search-ignore-string-comment "\\<for\\>" t nil))
- (+ (current-indentation) ada-indent-record-rel-type)))
- ;;
- ;; or as statement-start
- ;;
- ((ada-looking-at-semi-or)
- (save-excursion
- (ada-goto-matching-start 1)
- (current-indentation)))
- ;;
- ;; private as statement-start
- ;;
- ((ada-looking-at-semi-private)
- (save-excursion
- (ada-goto-matching-decl-start)
- (current-indentation)))
- ;;
- ;; new/abstract/separate
- ;;
- ((looking-at "\\<\\(new\\|abstract\\|separate\\)\\>")
- (- prev-indent ada-indent (- ada-broken-indent)))
- ;;
- ;; return
- ;;
- ((looking-at "\\<return\\>")
- (save-excursion
- (forward-sexp -1)
- (if (and (looking-at "(")
- (save-excursion
- (backward-sexp 2)
- (looking-at "\\<function\\>")))
- (1+ (current-column))
- prev-indent)))
- ;;
- ;; do
- ;;
- ((looking-at "\\<do\\>")
- (save-excursion
- (ada-goto-stmt-start)
- (+ (current-indentation) ada-stmt-end-indent)))
- ;;
- ;; package/function/procedure
- ;;
- ((and (looking-at "\\<\\(package\\|function\\|procedure\\)\\>")
- (save-excursion
- (forward-char 1)
- (ada-goto-stmt-start)
- (looking-at "\\<\\(package\\|function\\|procedure\\)\\>")))
- (save-excursion
- ;; look for 'generic'
- (if (and (ada-goto-matching-decl-start t)
- (looking-at "generic"))
- (current-column)
- prev-indent)))
- ;;
- ;; label
- ;;
- ((looking-at "\\<[a-zA-Z0-9_]+[ \t\n]*:[^=]")
- (if (ada-in-decl-p)
- prev-indent
- (+ prev-indent ada-label-indent)))
- ;;
- ;; identifier and other noindent-statements
- ;;
- ((looking-at "\\<[a-zA-Z0-9_]+[ \t\n]*")
- prev-indent)
- ;;
- ;; beginning of a parameter list
- ;;
- ((looking-at "(")
- prev-indent)
- ;;
- ;; end of a parameter list
- ;;
- ((looking-at ")")
- (save-excursion
- (forward-char 1)
- (backward-sexp 1)
- (current-column)))
- ;;
- ;; comment
- ;;
- ((looking-at "--")
- (if ada-indent-comment-as-code
- prev-indent
- (current-indentation)))
- ;;
- ;; unknown syntax - maybe this should signal an error ?
- ;;
- (t
- prev-indent))))
-
-
-(defun ada-indent-function (&optional nomove)
- ;; Returns the function to calculate the indentation for the current
- ;; line according to the previous statement, ignoring the contents
- ;; of the current line after point. Moves point to the beginning of
- ;; the current statement, if NOMOVE is nil.
-
- (let ((orgpoint (point))
- (func nil)
- (stmt-start nil))
- ;;
- ;; inside a parameter-list
- ;;
- (if (ada-in-paramlist-p)
- (setq func 'ada-get-indent-paramlist)
- (progn
- ;;
- ;; move to beginning of current statement
- ;;
- (if (not nomove)
- (setq stmt-start (ada-goto-stmt-start)))
- ;;
- ;; no beginning found => don't change indentation
- ;;
- (if (and
- (eq orgpoint (point))
- (not nomove))
- (setq func 'ada-get-indent-nochange)
-
- (cond
- ;;
- ((and
- ada-indent-to-open-paren
- (ada-in-open-paren-p))
- (setq func 'ada-get-indent-open-paren))
- ;;
- ((looking-at "\\<end\\>")
- (setq func 'ada-get-indent-end))
- ;;
- ((looking-at ada-loop-start-re)
- (setq func 'ada-get-indent-loop))
- ;;
- ((looking-at ada-subprog-start-re)
- (setq func 'ada-get-indent-subprog))
- ;;
- ((looking-at "\\<package\\>")
- (setq func 'ada-get-indent-subprog)) ; maybe it needs a
- ; special function
- ; sometimes ?
- ;;
- ((looking-at ada-block-start-re)
- (setq func 'ada-get-indent-block-start))
- ;;
- ((looking-at "\\<type\\>")
- (setq func 'ada-get-indent-type))
- ;;
- ((looking-at "\\<\\(els\\)?if\\>")
- (setq func 'ada-get-indent-if))
- ;;
- ((looking-at "\\<case\\>")
- (setq func 'ada-get-indent-case))
- ;;
- ((looking-at "\\<when\\>")
- (setq func 'ada-get-indent-when))
- ;;
- ((looking-at "--")
- (setq func 'ada-get-indent-comment))
- ;;
- ((looking-at "[a-zA-Z0-9_]+[ \t\n]*:[^=]")
- (setq func 'ada-get-indent-label))
- ;;
- ((looking-at "\\<separate\\>")
- (setq func 'ada-get-indent-nochange))
- (t
- (setq func 'ada-get-indent-noindent))))))
-
- func))
-
-
-;; ---- functions to return indentation for special cases
-
-(defun ada-get-indent-open-paren (orgpoint)
- ;; Returns the indentation (column #) for the new line after ORGPOINT.
- ;; Assumes point to be behind an open parenthesis not yet closed.
- (ada-in-open-paren-p))
-
-
-(defun ada-get-indent-nochange (orgpoint)
- ;; Returns the indentation (column #) of the current line.
- (save-excursion
- (forward-line -1)
- (current-indentation)))
-
-
-(defun ada-get-indent-paramlist (orgpoint)
- ;; Returns the indentation (column #) for the new line after ORGPOINT.
- ;; Assumes point to be inside a parameter-list.
- (save-excursion
- (ada-search-ignore-string-comment "[^ \t\n]" t nil t)
- (cond
- ;;
- ;; in front of the first parameter
- ;;
- ((looking-at "(")
- (goto-char (match-end 0))
- (current-column))
- ;;
- ;; in front of another parameter
- ;;
- ((looking-at ";")
- (goto-char (cdr (ada-search-ignore-string-comment "(\\|;" t nil t)))
- (ada-goto-next-non-ws)
- (current-column))
- ;;
- ;; inside a parameter declaration
- ;;
- (t
- (goto-char (cdr (ada-search-ignore-string-comment "(\\|;" t nil t)))
- (ada-goto-next-non-ws)
- (+ (current-column) ada-broken-indent)))))
-
-
-(defun ada-get-indent-end (orgpoint)
- ;; Returns the indentation (column #) for the new line after ORGPOINT.
- ;; Assumes point to be at the beginning of an end-statement.
- ;; Therefore it has to find the corresponding start. This can be a little
- ;; slow, if it has to search through big files with many nested blocks.
- ;; Signals an error if the corresponding block-start doesn't match.
- (let ((defun-name nil)
- (indent nil))
- ;;
- ;; is the line already terminated by ';' ?
- ;;
- (if (save-excursion
- (ada-search-ignore-string-comment ";" nil orgpoint))
- ;;
- ;; yes, look what's following 'end'
- ;;
- (progn
- (forward-word 1)
- (ada-goto-next-non-ws)
- (cond
- ;;
- ;; loop/select/if/case/record/select
- ;;
- ((looking-at "\\<\\(loop\\|select\\|if\\|case\\|record\\)\\>")
- (save-excursion
- (ada-check-matching-start
- (buffer-substring (match-beginning 0)
- (match-end 0)))
- (if (looking-at "\\<\\(loop\\|record\\)\\>")
- (progn
- (forward-word 1)
- (ada-goto-stmt-start)))
- ;; a label ? => skip it
- (if (looking-at "[a-zA-Z0-9_]+[ \n\t]+:")
- (progn
- (goto-char (match-end 0))
- (ada-goto-next-non-ws)))
- ;; really looking-at the right thing ?
- (or (looking-at (concat "\\<\\("
- "loop\\|select\\|if\\|case\\|"
- "record\\|while\\|type\\)\\>"))
- (progn
- (ada-search-ignore-string-comment
- (concat "\\<\\("
- "loop\\|select\\|if\\|case\\|"
- "record\\|while\\|type\\)\\>")))
- (backward-word 1))
- (current-indentation)))
- ;;
- ;; a named block end
- ;;
- ((looking-at ada-ident-re)
- (setq defun-name (buffer-substring (match-beginning 0)
- (match-end 0)))
- (save-excursion
- (ada-goto-matching-start 0)
- (ada-check-defun-name defun-name)
- (current-indentation)))
- ;;
- ;; a block-end without name
- ;;
- ((looking-at ";")
- (save-excursion
- (ada-goto-matching-start 0)
- (if (looking-at "\\<begin\\>")
- (progn
- (setq indent (current-column))
- (if (ada-goto-matching-decl-start t)
- (current-indentation)
- indent)))))
- ;;
- ;; anything else - should maybe signal an error ?
- ;;
- (t
- (+ (current-indentation) ada-broken-indent))))
-
- (+ (current-indentation) ada-broken-indent))))
-
-
-(defun ada-get-indent-case (orgpoint)
- ;; Returns the indentation (column #) for the new line after ORGPOINT.
- ;; Assumes point to be at the beginning of an case-statement.
- (let ((cur-indent (current-indentation))
- (match-cons nil)
- (opos (point)))
- (cond
- ;;
- ;; case..is..when..=>
- ;;
- ((save-excursion
- (setq match-cons (ada-search-ignore-string-comment
- "[ \t\n]+=>" nil orgpoint)))
- (save-excursion
- (goto-char (car match-cons))
- (if (not (ada-search-ignore-string-comment "\\<when\\>" t opos))
- (error "missing 'when' between 'case' and '=>'"))
- (+ (current-indentation) ada-indent)))
- ;;
- ;; case..is..when
- ;;
- ((save-excursion
- (setq match-cons (ada-search-ignore-string-comment
- "\\<when\\>" nil orgpoint)))
- (goto-char (cdr match-cons))
- (+ (current-indentation) ada-broken-indent))
- ;;
- ;; case..is
- ;;
- ((save-excursion
- (setq match-cons (ada-search-ignore-string-comment
- "\\<is\\>" nil orgpoint)))
- (+ (current-indentation) ada-when-indent))
- ;;
- ;; incomplete case
- ;;
- (t
- (+ (current-indentation) ada-broken-indent)))))
-
-
-(defun ada-get-indent-when (orgpoint)
- ;; Returns the indentation (column #) for the new line after ORGPOINT.
- ;; Assumes point to be at the beginning of an when-statement.
- (let ((cur-indent (current-indentation)))
- (if (ada-search-ignore-string-comment
- "[ \t\n]+=>" nil orgpoint)
- (+ cur-indent ada-indent)
- (+ cur-indent ada-broken-indent))))
-
-
-(defun ada-get-indent-if (orgpoint)
- ;; Returns the indentation (column #) for the new line after ORGPOINT.
- ;; Assumes point to be at the beginning of an if-statement.
- (let ((cur-indent (current-indentation))
- (match-cons nil))
- ;;
- ;; if..then ?
- ;;
- (if (ada-search-but-not
- "\\<then\\>" "\\<and\\>[ \t\n]+\\<then\\>" nil orgpoint)
-
- (progn
- ;;
- ;; 'then' first in separate line ?
- ;; => indent according to 'then'
- ;;
- (if (save-excursion
- (back-to-indentation)
- (looking-at "\\<then\\>"))
- (setq cur-indent (current-indentation)))
- (forward-word 1)
- ;;
- ;; something follows 'then' ?
- ;;
- (if (setq match-cons
- (ada-search-ignore-string-comment
- "[^ \t\n]" nil orgpoint))
- (progn
- (goto-char (car match-cons))
- (+ ada-indent
- (- cur-indent (current-indentation))
- (funcall (ada-indent-function t) orgpoint)))
-
- (+ cur-indent ada-indent)))
-
- (+ cur-indent ada-broken-indent))))
-
-
-(defun ada-get-indent-block-start (orgpoint)
- ;; Returns the indentation (column #) for the new line after
- ;; ORGPOINT. Assumes point to be at the beginning of a block start
- ;; keyword.
- (let ((cur-indent (current-indentation))
- (pos nil))
- (cond
- ((save-excursion
- (forward-word 1)
- (setq pos (car (ada-search-ignore-string-comment
- "[^ \t\n]" nil orgpoint))))
- (goto-char pos)
- (save-excursion
- (funcall (ada-indent-function t) orgpoint)))
- ;;
- ;; nothing follows the block-start
- ;;
- (t
- (+ (current-indentation) ada-indent)))))
-
-
-(defun ada-get-indent-subprog (orgpoint)
- ;; Returns the indentation (column #) for the new line after ORGPOINT.
- ;; Assumes point to be at the beginning of a subprog-/package-declaration.
- (let ((match-cons nil)
- (cur-indent (current-indentation))
- (foundis nil)
- (addind 0)
- (fstart (point)))
- ;;
- ;; is there an 'is' in front of point ?
- ;;
- (if (save-excursion
- (setq match-cons
- (ada-search-ignore-string-comment
- "\\<is\\>\\|\\<do\\>" nil orgpoint)))
- ;;
- ;; yes, then skip to its end
- ;;
- (progn
- (setq foundis t)
- (goto-char (cdr match-cons)))
- ;;
- ;; no, then goto next non-ws, if there is one in front of point
- ;;
- (progn
- (if (ada-search-ignore-string-comment "[^ \t\n]" nil orgpoint)
- (ada-goto-next-non-ws)
- (goto-char orgpoint))))
-
- (cond
- ;;
- ;; nothing follows 'is'
- ;;
- ((and
- foundis
- (save-excursion
- (not (ada-search-ignore-string-comment
- "[^ \t\n]" nil orgpoint t))))
- (+ cur-indent ada-indent))
- ;;
- ;; is abstract/separate/new ...
- ;;
- ((and
- foundis
- (save-excursion
- (setq match-cons
- (ada-search-ignore-string-comment
- "\\<\\(separate\\|new\\|abstract\\)\\>"
- nil orgpoint))))
- (goto-char (car match-cons))
- (ada-search-ignore-string-comment ada-subprog-start-re t)
- (ada-get-indent-noindent orgpoint))
- ;;
- ;; something follows 'is'
- ;;
- ((and
- foundis
- (save-excursion
- (ada-search-ignore-string-comment "[^ \t\n]" nil orgpoint))
- (ada-goto-next-non-ws)
- (funcall (ada-indent-function t) orgpoint)))
- ;;
- ;; no 'is' but ';'
- ;;
- ((save-excursion
- (ada-search-ignore-string-comment ";" nil orgpoint))
- cur-indent)
- ;;
- ;; no 'is' or ';'
- ;;
- (t
- (+ cur-indent ada-broken-indent)))))
-
-
-(defun ada-get-indent-noindent (orgpoint)
- ;; Returns the indentation (column #) for the new line after ORGPOINT.
- ;; Assumes point to be at the beginning of a 'noindent statement'.
- (if (save-excursion
- (ada-search-ignore-string-comment ";" nil orgpoint))
- (current-indentation)
- (+ (current-indentation) ada-broken-indent)))
-
-
-(defun ada-get-indent-label (orgpoint)
- ;; Returns the indentation (column #) for the new line after ORGPOINT.
- ;; Assumes point to be at the beginning of a label or variable declaration.
- ;; Checks the context to decide if it's a label or a variable declaration.
- ;; This check might be a bit slow.
- (let ((match-cons nil)
- (cur-indent (current-indentation)))
- (goto-char (cdr (ada-search-ignore-string-comment ":")))
- (cond
- ;;
- ;; loop label
- ;;
- ((save-excursion
- (setq match-cons (ada-search-ignore-string-comment
- ada-loop-start-re nil orgpoint)))
- (goto-char (car match-cons))
- (ada-get-indent-loop orgpoint))
- ;;
- ;; declare label
- ;;
- ((save-excursion
- (setq match-cons (ada-search-ignore-string-comment
- "\\<declare\\>" nil orgpoint)))
- (save-excursion
- (goto-char (car match-cons))
- (+ (current-indentation) ada-indent)))
- ;;
- ;; complete statement following colon
- ;;
- ((save-excursion
- (ada-search-ignore-string-comment ";" nil orgpoint))
- (if (ada-in-decl-p)
- cur-indent ; variable-declaration
- (- cur-indent ada-label-indent))) ; label
- ;;
- ;; broken statement
- ;;
- ((save-excursion
- (ada-search-ignore-string-comment "[^ \t\n]" nil orgpoint))
- (if (ada-in-decl-p)
- (+ cur-indent ada-broken-indent)
- (+ cur-indent ada-broken-indent (- ada-label-indent))))
- ;;
- ;; nothing follows colon
- ;;
- (t
- (if (ada-in-decl-p)
- (+ cur-indent ada-broken-indent) ; variable-declaration
- (- cur-indent ada-label-indent)))))) ; label
-
-
-(defun ada-get-indent-loop (orgpoint)
- ;; Returns the indentation (column #) for the new line after ORGPOINT.
- ;; Assumes point to be at the beginning of a loop statement
- ;; or (unfortunately) also a for ... use statement.
- (let ((match-cons nil)
- (pos (point)))
- (cond
-
- ;;
- ;; statement complete
- ;;
- ((save-excursion
- (ada-search-ignore-string-comment ";" nil orgpoint))
- (current-indentation))
- ;;
- ;; simple loop
- ;;
- ((looking-at "loop\\>")
- (ada-get-indent-block-start orgpoint))
-
- ;;
- ;; 'for'- loop (or also a for ... use statement)
- ;;
- ((looking-at "for\\>")
- (cond
- ;;
- ;; for ... use
- ;;
- ((save-excursion
- (and
- (goto-char (match-end 0))
- (ada-search-ignore-string-comment "[^ /n/t]" nil orgpoint)
- (not (backward-char 1))
- (not (zerop (skip-chars-forward "_a-zA-Z0-9'")))
- (ada-search-ignore-string-comment "[^ /n/t]" nil orgpoint)
- (not (backward-char 1))
- (looking-at "\\<use\\>")
- ;;
- ;; check if there is a 'record' before point
- ;;
- (progn
- (setq match-cons (ada-search-ignore-string-comment
- "\\<record\\>" nil orgpoint))
- t)))
- (if match-cons
- (goto-char (car match-cons)))
- (+ (current-indentation) ada-indent))
- ;;
- ;; for..loop
- ;;
- ((save-excursion
- (setq match-cons (ada-search-ignore-string-comment
- "\\<loop\\>" nil orgpoint)))
- (goto-char (car match-cons))
- ;;
- ;; indent according to 'loop', if it's first in the line;
- ;; otherwise to 'for'
- ;;
- (if (not (save-excursion
- (back-to-indentation)
- (looking-at "\\<loop\\>")))
- (goto-char pos))
- (+ (current-indentation) ada-indent))
- ;;
- ;; for-statement is broken
- ;;
- (t
- (+ (current-indentation) ada-broken-indent))))
-
- ;;
- ;; 'while'-loop
- ;;
- ((looking-at "while\\>")
- ;;
- ;; while..loop ?
- ;;
- (if (save-excursion
- (setq match-cons (ada-search-ignore-string-comment
- "\\<loop\\>" nil orgpoint)))
-
- (progn
- (goto-char (car match-cons))
- ;;
- ;; indent according to 'loop', if it's first in the line;
- ;; otherwise to 'while'.
- ;;
- (if (not (save-excursion
- (back-to-indentation)
- (looking-at "\\<loop\\>")))
- (goto-char pos))
- (+ (current-indentation) ada-indent))
-
- (+ (current-indentation) ada-broken-indent))))))
-
-
-(defun ada-get-indent-type (orgpoint)
- ;; Returns the indentation (column #) for the new line after ORGPOINT.
- ;; Assumes point to be at the beginning of a type statement.
- (let ((match-dat nil))
- (cond
- ;;
- ;; complete record declaration
- ;;
- ((save-excursion
- (and
- (setq match-dat (ada-search-ignore-string-comment "\\<end\\>"
- nil
- orgpoint))
- (ada-goto-next-non-ws)
- (looking-at "\\<record\\>")
- (forward-word 1)
- (ada-goto-next-non-ws)
- (looking-at ";")))
- (goto-char (car match-dat))
- (current-indentation))
- ;;
- ;; record type
- ;;
- ((save-excursion
- (setq match-dat (ada-search-ignore-string-comment "\\<record\\>"
- nil
- orgpoint)))
- (goto-char (car match-dat))
- (+ (current-indentation) ada-indent))
- ;;
- ;; complete type declaration
- ;;
- ((save-excursion
- (ada-search-ignore-string-comment ";" nil orgpoint))
- (current-indentation))
- ;;
- ;; "type ... is", but not "type ... is ...", which is broken
- ;;
- ((save-excursion
- (and
- (ada-search-ignore-string-comment "\\<is\\>" nil orgpoint)
- (not (ada-search-ignore-string-comment "[^ \t\n]" nil orgpoint))))
- (+ (current-indentation) ada-indent))
- ;;
- ;; broken statement
- ;;
- (t
- (+ (current-indentation) ada-broken-indent)))))
-
-
-;;; ---- support-functions for indentation
-
-;;; ---- searching and matching
-
-(defun ada-goto-stmt-start (&optional limit)
- ;; Moves point to the beginning of the statement that point is in or
- ;; after. Returns the new position of point. Beginnings are found
- ;; by searching for 'ada-end-stmt-re' and then moving to the
- ;; following non-ws that is not a comment. LIMIT is actually not
- ;; used by the indentation functions.
- (let ((match-dat nil)
- (orgpoint (point)))
-
- (setq match-dat (ada-search-prev-end-stmt limit))
- (if match-dat
- ;;
- ;; found a previous end-statement => check if anything follows
- ;;
- (progn
- (if (not
- (save-excursion
- (goto-char (cdr match-dat))
- (ada-search-ignore-string-comment
- "[^ \t\n]" nil orgpoint)))
- ;;
- ;; nothing follows => it's the end-statement directly in
- ;; front of point => search again
- ;;
- (setq match-dat (ada-search-prev-end-stmt limit)))
- ;;
- ;; if found the correct end-statement => goto next non-ws
- ;;
- (if match-dat
- (goto-char (cdr match-dat)))
- (ada-goto-next-non-ws))
-
- ;;
- ;; no previous end-statement => we are at the beginning of the
- ;; accessible part of the buffer
- ;;
- (progn
- (goto-char (point-min))
- ;;
- ;; skip to the very first statement, if there is one
- ;;
- (if (setq match-dat
- (ada-search-ignore-string-comment
- "[^ \t\n]" nil orgpoint))
- (goto-char (car match-dat))
- (goto-char orgpoint))))
-
-
- (point)))
-
-
-(defun ada-search-prev-end-stmt (&optional limit)
- ;; Moves point to previous end-statement. Returns a cons cell whose
- ;; car is the beginning and whose cdr the end of the match.
- ;; End-statements are defined by 'ada-end-stmt-re'. Checks for
- ;; certain keywords if they follow 'end', which means they are no
- ;; end-statement there.
- (interactive) ;; DEBUG
- (let ((match-dat nil)
- (pos nil)
- (found nil))
- ;;
- ;; search until found or beginning-of-buffer
- ;;
- (while
- (and
- (not found)
- (setq match-dat (ada-search-ignore-string-comment ada-end-stmt-re
- t
- limit)))
-
- (goto-char (car match-dat))
-
- (if (not (ada-in-open-paren-p))
- ;;
- ;; check if there is an 'end' in front of the match
- ;;
- (if (not (and
- (looking-at "\\<\\(record\\|loop\\|select\\)\\>")
- (save-excursion
- (ada-goto-previous-word)
- (looking-at "\\<end\\>"))))
- (setq found t)
-
- (forward-word -1)))) ; end of loop
-
- (if found
- match-dat
- nil)))
-
-
-(defun ada-goto-next-non-ws (&optional limit)
- ;; Skips whitespaces, newlines and comments to next non-ws
- ;; character. Signals an error if there is no more such character
- ;; and limit is nil.
- (let ((match-cons nil))
- (setq match-cons (ada-search-ignore-string-comment
- "[^ \t\n]" nil limit t))
- (if match-cons
- (goto-char (car match-cons))
- (if (not limit)
- (error "no more non-ws")
- nil))))
-
-
-(defun ada-goto-stmt-end (&optional limit)
- ;; Moves point to the end of the statement that point is in or
- ;; before. Returns the new position of point or nil if not found.
- (if (ada-search-ignore-string-comment ada-end-stmt-re nil limit)
- (point)
- nil))
-
-
-(defun ada-goto-previous-word ()
- ;; Moves point to the beginning of the previous word of Ada code.
- ;; Returns the new position of point or nil if not found.
- (let ((match-cons nil)
- (orgpoint (point)))
- (if (setq match-cons
- (ada-search-ignore-string-comment "[^ \t\n]" t nil t))
- ;;
- ;; move to the beginning of the word found
- ;;
- (progn
- (goto-char (cdr match-cons))
- (skip-chars-backward "_a-zA-Z0-9")
- (point))
- ;;
- ;; if not found, restore old position of point
- ;;
- (progn
- (goto-char orgpoint)
- 'nil))))
-
-
-(defun ada-check-matching-start (keyword)
- ;; Signals an error if matching block start is not KEYWORD.
- ;; Moves point to the matching block start.
- (ada-goto-matching-start 0)
- (if (not (looking-at (concat "\\<" keyword "\\>")))
- (error "matching start is not '%s'" keyword)))
-
-
-(defun ada-check-defun-name (defun-name)
- ;; Checks if the name of the matching defun really is DEFUN-NAME.
- ;; Assumes point to be already positioned by 'ada-goto-matching-start'.
- ;; Moves point to the beginning of the declaration.
-
- ;;
- ;; 'accept' or 'package' ?
- ;;
- (if (not (looking-at "\\<\\(accept\\|package\\|task\\|protected\\)\\>"))
- (ada-goto-matching-decl-start))
- ;;
- ;; 'begin' of 'procedure'/'function'/'task' or 'declare'
- ;;
- (save-excursion
- ;;
- ;; a named 'declare'-block ?
- ;;
- (if (looking-at "\\<declare\\>")
- (ada-goto-stmt-start)
- ;;
- ;; no, => 'procedure'/'function'/'task'/'protected'
- ;;
- (progn
- (forward-word 2)
- (backward-word 1)
- ;;
- ;; skip 'body' 'protected' 'type'
- ;;
- (if (looking-at "\\<\\(body\\|type\\)\\>")
- (forward-word 1))
- (forward-sexp 1)
- (backward-sexp 1)))
- ;;
- ;; should be looking-at the correct name
- ;;
- (if (not (looking-at (concat "\\<" defun-name "\\>")))
- (error "matching defun has different name: %s"
- (buffer-substring (point)
- (progn (forward-sexp 1) (point)))))))
-
-
-(defun ada-goto-matching-decl-start (&optional noerror nogeneric)
- ;; Moves point to the matching declaration start of the current 'begin'.
- ;; If NOERROR is non-nil, it only returns nil if no match was found.
- (interactive) ;; DEBUG
- (let ((nest-count 1)
- (pos nil)
- (first t)
- (flag nil))
- ;;
- ;; search backward for interesting keywords
- ;;
- (while (and
- (not (zerop nest-count))
- (ada-search-ignore-string-comment
- (concat "\\<\\("
- "is\\|separate\\|end\\|declare\\|new\\|begin\\|generic"
- "\\)\\>") t))
- ;;
- ;; calculate nest-depth
- ;;
- (cond
- ;;
- ((looking-at "end")
- (ada-goto-matching-start 1 noerror)
- (if (looking-at "begin")
- (setq nest-count (1+ nest-count))))
- ;;
- ((looking-at "declare\\|generic")
- (setq nest-count (1- nest-count))
- (setq first nil))
- ;;
- ((looking-at "is")
- ;; check if it is only a type definition, but not a protected
- ;; type definition, which should be handled like a procedure.
- (if (save-excursion
- (ada-goto-previous-word)
- (skip-chars-backward "a-zA-Z0-9_.'")
- (if (save-excursion
- (backward-char 1)
- (looking-at ")"))
- (progn
- (forward-char 1)
- (backward-sexp 1)
- (skip-chars-backward "a-zA-Z0-9_.'")
- ))
- (ada-goto-previous-word)
- (and
- (looking-at "\\<type\\>")
- (save-match-data
- (ada-goto-previous-word)
- (not (looking-at "\\<protected\\>"))))
- ); end of save-excursion
- (goto-char (match-beginning 0))
- (progn
- (setq nest-count (1- nest-count))
- (setq first nil))))
-
- ;;
- ((looking-at "new")
- (if (save-excursion
- (ada-goto-previous-word)
- (looking-at "is"))
- (goto-char (match-beginning 0))))
- ;;
- ((and first
- (looking-at "begin"))
- (setq nest-count 0)
- (setq flag t))
- ;;
- (t
- (setq nest-count (1+ nest-count))
- (setq first nil)))
-
- ) ;; end of loop
-
- ;; check if declaration-start is really found
- (if (not
- (and
- (zerop nest-count)
- (not flag)
- (progn
- (if (looking-at "is")
- (ada-search-ignore-string-comment
- ada-subprog-start-re t)
- (looking-at "declare\\|generic")))))
- (if noerror nil
- (error "no matching proc/func/task/declare/package/protected"))
- t)))
-
-
-(defun ada-goto-matching-start (&optional nest-level noerror gotothen)
- ;; Moves point to the beginning of a block-start. Which block
- ;; depends on the value of NEST-LEVEL, which defaults to zero. If
- ;; NOERROR is non-nil, it only returns nil if no matching start was
- ;; found. If GOTOTHEN is non-nil, point moves to the 'then'
- ;; following 'if'.
- (let ((nest-count (if nest-level nest-level 0))
- (found nil)
- (pos nil))
-
- ;;
- ;; search backward for interesting keywords
- ;;
- (while (and
- (not found)
- (ada-search-ignore-string-comment
- (concat "\\<\\("
- "end\\|loop\\|select\\|begin\\|case\\|do\\|"
- "if\\|task\\|package\\|record\\|protected\\)\\>")
- t))
-
- ;;
- ;; calculate nest-depth
- ;;
- (cond
- ;; found block end => increase nest depth
- ((looking-at "end")
- (setq nest-count (1+ nest-count)))
- ;; found loop/select/record/case/if => check if it starts or
- ;; ends a block
- ((looking-at "loop\\|select\\|record\\|case\\|if")
- (setq pos (point))
- (save-excursion
- ;;
- ;; check if keyword follows 'end'
- ;;
- (ada-goto-previous-word)
- (if (looking-at "\\<end\\>")
- ;; it ends a block => increase nest depth
- (progn
- (setq nest-count (1+ nest-count))
- (setq pos (point)))
- ;; it starts a block => decrease nest depth
- (setq nest-count (1- nest-count))))
- (goto-char pos))
- ;; found package start => check if it really is a block
- ((looking-at "package")
- (save-excursion
- (ada-search-ignore-string-comment "\\<is\\>")
- (ada-goto-next-non-ws)
- ;; ignore it if it is only a declaration with 'new'
- (if (not (looking-at "\\<new\\>"))
- (setq nest-count (1- nest-count)))))
- ;; found task start => check if it has a body
- ((looking-at "task")
- (save-excursion
- (forward-word 1)
- (ada-goto-next-non-ws)
- ;; ignore it if it has no body
- (if (not (looking-at "\\<body\\>"))
- (setq nest-count (1- nest-count)))))
- ;; all the other block starts
- (t
- (setq nest-count (1- nest-count)))) ; end of 'cond'
-
- ;; match is found, if nest-depth is zero
- ;;
- (setq found (zerop nest-count))) ; end of loop
-
- (if found
- ;;
- ;; match found => is there anything else to do ?
- ;;
- (progn
- (cond
- ;;
- ;; found 'if' => skip to 'then', if it's on a separate line
- ;; and GOTOTHEN is non-nil
- ;;
- ((and
- gotothen
- (looking-at "if")
- (save-excursion
- (ada-search-ignore-string-comment "\\<then\\>" nil nil)
- (back-to-indentation)
- (looking-at "\\<then\\>")))
- (goto-char (match-beginning 0)))
- ;;
- ;; found 'do' => skip back to 'accept'
- ;;
- ((looking-at "do")
- (if (not (ada-search-ignore-string-comment "\\<accept\\>" t nil))
- (error "missing 'accept' in front of 'do'"))))
- (point))
-
- (if noerror
- nil
- (error "no matching start")))))
-
-
-(defun ada-goto-matching-end (&optional nest-level noerror)
- ;; Moves point to the end of a block. Which block depends on the
- ;; value of NEST-LEVEL, which defaults to zero. If NOERROR is
- ;; non-nil, it only returns nil if found no matching start.
- (let ((nest-count (if nest-level nest-level 0))
- (found nil))
-
- ;;
- ;; search forward for interesting keywords
- ;;
- (while (and
- (not found)
- (ada-search-ignore-string-comment
- (concat "\\<\\(end\\|loop\\|select\\|begin\\|case\\|"
- "if\\|task\\|package\\|record\\|do\\)\\>")))
-
- ;;
- ;; calculate nest-depth
- ;;
- (backward-word 1)
- (cond
- ;; found block end => decrease nest depth
- ((looking-at "\\<end\\>")
- (setq nest-count (1- nest-count))
- ;; skip the following keyword
- (if (progn
- (skip-chars-forward "end")
- (ada-goto-next-non-ws)
- (looking-at "\\<\\(loop\\|select\\|record\\|case\\|if\\)\\>"))
- (forward-word 1)))
- ;; found package start => check if it really starts a block
- ((looking-at "\\<package\\>")
- (ada-search-ignore-string-comment "\\<is\\>")
- (ada-goto-next-non-ws)
- ;; ignore and skip it if it is only a 'new' package
- (if (not (looking-at "\\<new\\>"))
- (setq nest-count (1+ nest-count))
- (skip-chars-forward "new")))
- ;; all the other block starts
- (t
- (setq nest-count (1+ nest-count))
- (forward-word 1))) ; end of 'cond'
-
- ;; match is found, if nest-depth is zero
- ;;
- (setq found (zerop nest-count))) ; end of loop
-
- (if (not found)
- (if noerror
- nil
- (error "no matching end"))
- t)))
-
-
-(defun ada-forward-sexp-ignore-comment ()
- ;; Skips one sexp forward, ignoring comments.
- (while (looking-at "[ \t\n]*--")
- (skip-chars-forward "[ \t\n]")
- (end-of-line))
- (forward-sexp 1))
-
-
-(defun ada-search-ignore-string-comment
- (search-re &optional backward limit paramlists)
- ;; Regexp-Search for SEARCH-RE, ignoring comments, strings and
- ;; parameter lists, if PARAMLISTS is nil. Returns a cons cell of
- ;; begin and end of match data or nil, if not found.
- (let ((found nil)
- (begin nil)
- (end nil)
- (pos nil)
- (search-func
- (if backward 're-search-backward
- 're-search-forward)))
-
- ;;
- ;; search until found or end-of-buffer
- ;;
- (while (and (not found)
- (funcall search-func search-re limit 1))
- (setq begin (match-beginning 0))
- (setq end (match-end 0))
-
- (cond
- ;;
- ;; found in comment => skip it
- ;;
- ((ada-in-comment-p)
- (if backward
- (progn
- (re-search-backward "--" nil 1)
- (goto-char (match-beginning 0)))
- (progn
- (forward-line 1)
- (beginning-of-line))))
- ;;
- ;; found in string => skip it
- ;;
- ((ada-in-string-p)
- (if backward
- (progn
- (re-search-backward "\"" nil 1) ; "\"\\|#" don't treat #
- (goto-char (match-beginning 0))))
- (re-search-forward "\"" nil 1))
- ;;
- ;; found character constant => ignore it
- ;;
- ((save-excursion
- (setq pos (- (point) (if backward 1 2)))
- (and (char-after pos)
- (= (char-after pos) ?')
- (= (char-after (+ pos 2)) ?')))
- ())
- ;;
- ;; found a parameter-list but should ignore it => skip it
- ;;
- ((and (not paramlists)
- (ada-in-paramlist-p))
- (if backward
- (ada-search-ignore-string-comment "(" t nil t)))
- ;;
- ;; directly in front of a comment => skip it, if searching forward
- ;;
- ((save-excursion
- (goto-char begin)
- (looking-at "--"))
- (if (not backward)
- (progn
- (forward-line 1)
- (beginning-of-line))))
- ;;
- ;; found what we were looking for
- ;;
- (t
- (setq found t)))) ; end of loop
-
- (if found
- (cons begin end)
- nil)))
-
-
-(defun ada-search-but-not (search-re not-search-re &optional backward limit)
- ;; Searches SEARCH-RE, ignoring parts of NOT-SEARCH-RE, strings,
- ;; comments and parameter-lists.
- (let ((begin nil)
- (end nil)
- (begin-not nil)
- (begin-end nil)
- (end-not nil)
- (ret-cons nil)
- (found nil))
-
- ;;
- ;; search until found or end-of-buffer
- ;;
- (while (and
- (not found)
- (save-excursion
- (setq ret-cons
- (ada-search-ignore-string-comment search-re
- backward limit))
- (if (consp ret-cons)
- (progn
- (setq begin (car ret-cons))
- (setq end (cdr ret-cons))
- t)
- nil)))
-
- (if (or
- ;;
- ;; if no NO-SEARCH-RE was found
- ;;
- (not
- (save-excursion
- (setq ret-cons
- (ada-search-ignore-string-comment not-search-re
- backward nil))
- (if (consp ret-cons)
- (progn
- (setq begin-not (car ret-cons))
- (setq end-not (cdr ret-cons))
- t)
- nil)))
- ;;
- ;; or this NO-SEARCH-RE is not a part of the SEARCH-RE
- ;; found before.
- ;;
- (or
- (<= end-not begin)
- (>= begin-not end)))
-
- (setq found t)
-
- ;;
- ;; not found the correct match => skip this match
- ;;
- (goto-char (if backward
- begin
- end)))) ; end of loop
-
- (if found
- (progn
- (goto-char begin)
- (cons begin end))
- nil)))
-
-
-(defun ada-goto-prev-nonblank-line ( &optional ignore-comment)
- ;; Moves point to the beginning of previous non-blank line,
- ;; ignoring comments if IGNORE-COMMENT is non-nil.
- ;; It returns t if a matching line was found.
- (let ((notfound t)
- (newpoint nil))
-
- (save-excursion
- ;;
- ;; backward one line, if there is one
- ;;
- (if (zerop (forward-line -1))
- ;;
- ;; there is some kind of previous line
- ;;
- (progn
- (beginning-of-line)
- (setq newpoint (point))
-
- ;;
- ;; search until found or beginning-of-buffer
- ;;
- (while (and (setq notfound
- (or (looking-at "[ \t]*$")
- (and (looking-at "[ \t]*--")
- ignore-comment)))
- (not (ada-in-limit-line-p)))
- (forward-line -1)
- ;;(beginning-of-line)
- (setq newpoint (point))) ; end of loop
-
- )) ; end of if
-
- ) ; end of save-excursion
-
- (if notfound nil
- (progn
- (goto-char newpoint)
- t))))
-
-
-(defun ada-goto-next-nonblank-line ( &optional ignore-comment)
- ;; Moves point to next non-blank line,
- ;; ignoring comments if IGNORE-COMMENT is non-nil.
- ;; It returns t if a matching line was found.
- (let ((notfound t)
- (newpoint nil))
-
- (save-excursion
- ;;
- ;; forward one line
- ;;
- (if (zerop (forward-line 1))
- ;;
- ;; there is some kind of previous line
- ;;
- (progn
- (beginning-of-line)
- (setq newpoint (point))
-
- ;;
- ;; search until found or end-of-buffer
- ;;
- (while (and (setq notfound
- (or (looking-at "[ \t]*$")
- (and (looking-at "[ \t]*--")
- ignore-comment)))
- (not (ada-in-limit-line-p)))
- (forward-line 1)
- (beginning-of-line)
- (setq newpoint (point))) ; end of loop
-
- )) ; end of if
-
- ) ; end of save-excursion
-
- (if notfound nil
- (progn
- (goto-char newpoint)
- t))))
-
-
-;; ---- boolean functions for indentation
-
-(defun ada-in-decl-p ()
- ;; Returns t if point is inside a declarative part.
- ;; Assumes point to be at the end of a statement.
- (or
- (ada-in-paramlist-p)
- (save-excursion
- (ada-goto-matching-decl-start t))))
-
-
-(defun ada-looking-at-semi-or ()
- ;; Returns t if looking-at an 'or' following a semicolon.
- (save-excursion
- (and (looking-at "\\<or\\>")
- (progn
- (forward-word 1)
- (ada-goto-stmt-start)
- (looking-at "\\<or\\>")))))
-
-
-(defun ada-looking-at-semi-private ()
- ;; Returns t if looking-at an 'private' following a semicolon.
- (save-excursion
- (and (looking-at "\\<private\\>")
- (progn
- (forward-word 1)
- (ada-goto-stmt-start)
- (looking-at "\\<private\\>")))))
-
-
-;;; make a faster??? ada-in-limit-line-p not using count-lines
-(defun ada-in-limit-line-p ()
- ;; return t if point is in first or last accessible line.
- (or (save-excursion (beginning-of-line) (= (point-min) (point)))
- (save-excursion (end-of-line) (= (point-max) (point)))))
-
-
-(defun ada-in-comment-p ()
- ;; Returns t if inside a comment.
- ;; (save-excursion (and (re-search-backward "\\(--\\|\n\\)" nil 1)
- ;; (looking-at "-"))))
- (nth 4 (parse-partial-sexp
- (save-excursion (beginning-of-line) (point))
- (point))))
-
-
-
-(defun ada-in-string-p ()
- ;; Returns t if point is inside a string
- ;; (Taken from pascal-mode.el, modified by MH).
- (save-excursion
- (and
- (nth 3 (parse-partial-sexp
- (save-excursion
- (beginning-of-line)
- (point)) (point)))
- ;; check if 'string quote' is only a character constant
- (progn
- (re-search-backward "\"" nil t) ; # not a string delimiter anymore
- (not (= (char-after (1- (point))) ?'))))))
-
-
-(defun ada-in-string-or-comment-p ()
- ;; Returns t if point is inside a string or a comment.
- (or (ada-in-comment-p)
- (ada-in-string-p)))
-
-
-(defun ada-in-paramlist-p ()
- ;; Returns t if point is inside a parameter-list
- ;; following 'function'/'procedure'/'package'.
- (save-excursion
- (and
- (re-search-backward "(\\|)" nil t)
- ;; inside parentheses ?
- (looking-at "(")
- (backward-word 2)
- ;; right keyword before parenthesis ?
- (looking-at (concat "\\<\\("
- "procedure\\|function\\|body\\|package\\|"
- "task\\|entry\\|accept\\)\\>"))
- (re-search-forward ")\\|:" nil t)
- ;; at least one ':' inside the parentheses ?
- (not (backward-char 1))
- (looking-at ":"))))
-
-
-;; not really a boolean function ...
-(defun ada-in-open-paren-p ()
- ;; If point is somewhere behind an open parenthesis not yet closed,
- ;; it returns the column # of the first non-ws behind this open
- ;; parenthesis, otherwise nil."
-
- (let ((start (if (< (point) ada-search-paren-char-count-limit)
- 1
- (- (point) ada-search-paren-char-count-limit)))
- parse-result
- (col nil))
- (setq parse-result (parse-partial-sexp start (point)))
- (if (nth 1 parse-result)
- (save-excursion
- (goto-char (1+ (nth 1 parse-result)))
- (if (save-excursion
- (re-search-forward "[^ \t]" nil 1)
- (backward-char 1)
- (and
- (not (looking-at "\n"))
- (setq col (current-column))))
- col
- (current-column)))
- nil)))
-
-
-
-;;;----------------------;;;
-;;; Behaviour Of TAB Key ;;;
-;;;----------------------;;;
-
-(defun ada-tab ()
- "Do indenting or tabbing according to `ada-tab-policy'."
- (interactive)
- (cond ((eq ada-tab-policy 'indent-and-tab) (error "not implemented"))
- ;; ada-indent-and-tab
- ((eq ada-tab-policy 'indent-rigidly) (ada-tab-hard))
- ((eq ada-tab-policy 'indent-auto) (ada-indent-current))
- ((eq ada-tab-policy 'gei) (ada-tab-gei))
- ((eq ada-tab-policy 'indent-af) (af-indent-line)) ; GEB
- ((eq ada-tab-policy 'always-tab) (error "not implemented"))
- ))
-
-
-(defun ada-untab (arg)
- "Delete leading indenting according to `ada-tab-policy'."
- (interactive "P")
- (cond ((eq ada-tab-policy 'indent-rigidly) (ada-untab-hard))
- ((eq ada-tab-policy 'indent-af) (backward-delete-char-untabify ; GEB
- (prefix-numeric-value arg) ; GEB
- arg)) ; GEB
- ((eq ada-tab-policy 'indent-auto) (error "not implemented"))
- ((eq ada-tab-policy 'always-tab) (error "not implemented"))
- ))
-
-
-(defun ada-indent-current-function ()
- "Ada Mode version of the indent-line-function."
- (interactive "*")
- (let ((starting-point (point-marker)))
- (ada-beginning-of-line)
- (ada-tab)
- (if (< (point) starting-point)
- (goto-char starting-point))
- (set-marker starting-point nil)
- ))
-
-
-(defun ada-tab-hard ()
- "Indent current line to next tab stop."
- (interactive)
- (save-excursion
- (beginning-of-line)
- (insert-char ? ada-indent))
- (if (save-excursion (= (point) (progn (beginning-of-line) (point))))
- (forward-char ada-indent)))
-
-
-(defun ada-untab-hard ()
- "indent current line to previous tab stop."
- (interactive)
- (let ((bol (save-excursion (progn (beginning-of-line) (point))))
- (eol (save-excursion (progn (end-of-line) (point)))))
- (indent-rigidly bol eol (- 0 ada-indent))))
-
-
-
-;;;---------------;;;
-;;; Miscellaneous ;;;
-;;;---------------;;;
-
-(defun ada-remove-trailing-spaces ()
- "remove trailing spaces in the whole buffer."
- (interactive)
- (save-match-data
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (while (re-search-forward "[ \t]+$" (point-max) t)
- (replace-match "" nil nil))))))
-
-
-(defun ada-untabify-buffer ()
-;; change all tabs to spaces
- (save-excursion
- (untabify (point-min) (point-max))))
-
-
-(defun ada-uncomment-region (beg end)
- "delete `comment-start' at the beginning of a line in the region."
- (interactive "r")
- (comment-region beg end -1))
-
-
-;; define a function to support find-file.el if loaded
-(defun ada-ff-other-window ()
- "Find other file in other window using `ff-find-other-file'."
- (interactive)
- (and (fboundp 'ff-find-other-file)
- (ff-find-other-file t)))
-
-
-;;;-------------------------------;;;
-;;; Moving To Procedures/Packages ;;;
-;;;-------------------------------;;;
-
-(defun ada-next-procedure ()
- "Moves point to next procedure."
- (interactive)
- (end-of-line)
- (if (re-search-forward ada-procedure-start-regexp nil t)
- (goto-char (match-beginning 1))
- (error "No more functions/procedures/tasks")))
-
-(defun ada-previous-procedure ()
- "Moves point to previous procedure."
- (interactive)
- (beginning-of-line)
- (if (re-search-backward ada-procedure-start-regexp nil t)
- (goto-char (match-beginning 1))
- (error "No more functions/procedures/tasks")))
-
-(defun ada-next-package ()
- "Moves point to next package."
- (interactive)
- (end-of-line)
- (if (re-search-forward ada-package-start-regexp nil t)
- (goto-char (match-beginning 1))
- (error "No more packages")))
-
-(defun ada-previous-package ()
- "Moves point to previous package."
- (interactive)
- (beginning-of-line)
- (if (re-search-backward ada-package-start-regexp nil t)
- (goto-char (match-beginning 1))
- (error "No more packages")))
-
-
-;;;-----------------------
-;;; define keymap for Ada
-;;;-----------------------
-
-(if (not ada-mode-map)
- (progn
- (setq ada-mode-map (make-sparse-keymap))
-
- ;; Indentation and Formatting
- (define-key ada-mode-map "\C-j" 'ada-indent-newline-indent)
- (define-key ada-mode-map "\t" 'ada-tab)
- (define-key ada-mode-map "\C-c\C-l" 'ada-indent-region)
- (if (ada-xemacs)
- (define-key ada-mode-map '(shift tab) 'ada-untab)
- (define-key ada-mode-map [S-tab] 'ada-untab))
- (define-key ada-mode-map "\C-c\C-f" 'ada-format-paramlist)
- (define-key ada-mode-map "\C-c\C-p" 'ada-call-pretty-printer)
-;;; We don't want to make meta-characters case-specific.
-;;; (define-key ada-mode-map "\M-Q" 'ada-fill-comment-paragraph-justify)
- (define-key ada-mode-map "\M-\C-q" 'ada-fill-comment-paragraph-postfix)
-
- ;; Movement
-;;; It isn't good to redefine these. What should be done instead? -- rms.
-;;; (define-key ada-mode-map "\M-e" 'ada-next-package)
-;;; (define-key ada-mode-map "\M-a" 'ada-previous-package)
- (define-key ada-mode-map "\M-\C-e" 'ada-next-procedure)
- (define-key ada-mode-map "\M-\C-a" 'ada-previous-procedure)
- (define-key ada-mode-map "\C-c\C-a" 'ada-move-to-start)
- (define-key ada-mode-map "\C-c\C-e" 'ada-move-to-end)
-
- ;; Compilation
- (define-key ada-mode-map "\C-c\C-c" 'compile)
-
- ;; Casing
- (define-key ada-mode-map "\C-c\C-r" 'ada-adjust-case-region)
- (define-key ada-mode-map "\C-c\C-b" 'ada-adjust-case-buffer)
-
- (define-key ada-mode-map "\177" 'backward-delete-char-untabify)
-
- ;; Use predefined function of emacs19 for comments (RE)
- (define-key ada-mode-map "\C-c;" 'comment-region)
- (define-key ada-mode-map "\C-c:" 'ada-uncomment-region)
-
- ;; Change basic functionality
-
- ;; `substitute-key-definition' is not defined equally in GNU Emacs
- ;; and XEmacs, you cannot put in an optional 4th parameter in
- ;; XEmacs. I don't think it's necessary, so I leave it out for
- ;; GNU Emacs as well. If you encounter any problems with the
- ;; following three functions, please tell me. RE
- (mapcar (function (lambda (pair)
- (substitute-key-definition (car pair) (cdr pair)
- ada-mode-map)))
- '((beginning-of-line . ada-beginning-of-line)
- (end-of-line . ada-end-of-line)
- (forward-to-indentation . ada-forward-to-indentation)
- ))
- ;; else GNU Emacs
- ;;(mapcar (lambda (pair)
- ;; (substitute-key-definition (car pair) (cdr pair)
- ;; ada-mode-map global-map))
-
- ))
-
-
-;;;-------------------
-;;; define menu 'Ada'
-;;;-------------------
-
-(require 'easymenu)
-
-(defun ada-add-ada-menu ()
- "Adds the menu 'Ada' to the menu bar in Ada Mode."
- (easy-menu-define ada-mode-menu ada-mode-map "Menu keymap for Ada mode."
- '("Ada"
- ["Next Package" ada-next-package t]
- ["Previous Package" ada-previous-package t]
- ["Next Procedure" ada-next-procedure t]
- ["Previous Procedure" ada-previous-procedure t]
- ["Goto Start" ada-move-to-start t]
- ["Goto End" ada-move-to-end t]
- ["------------------" nil nil]
- ["Indent Current Line (TAB)"
- ada-indent-current-function t]
- ["Indent Lines in Region" ada-indent-region t]
- ["Format Parameter List" ada-format-paramlist t]
- ["Pretty Print Buffer" ada-call-pretty-printer t]
- ["------------" nil nil]
- ["Fill Comment Paragraph"
- ada-fill-comment-paragraph t]
- ["Justify Comment Paragraph"
- ada-fill-comment-paragraph-justify t]
- ["Postfix Comment Paragraph"
- ada-fill-comment-paragraph-postfix t]
- ["------------" nil nil]
- ["Adjust Case Region" ada-adjust-case-region t]
- ["Adjust Case Buffer" ada-adjust-case-buffer t]
- ["----------" nil nil]
- ["Comment Region" comment-region t]
- ["Uncomment Region" ada-uncomment-region t]
- ["----------------" nil nil]
- ["Compile" compile (fboundp 'compile)]
- ["Next Error" next-error (fboundp 'next-error)]
- ["---------------" nil nil]
- ["Index" imenu (fboundp 'imenu)]
- ["--------------" nil nil]
- ["Other File Other Window" ada-ff-other-window
- (fboundp 'ff-find-other-file)]
- ["Other File" ff-find-other-file
- (fboundp 'ff-find-other-file)]))
- (if (ada-xemacs) (progn
- (easy-menu-add ada-mode-menu)
- (setq mode-popup-menu (cons "Ada Mode" ada-mode-menu)))))
-
-
-
-;;;-------------------------------
-;;; Define Some Support Functions
-;;;-------------------------------
-
-(defun ada-beginning-of-line (&optional arg)
- (interactive "P")
- (cond
- ((eq ada-tab-policy 'indent-af) (af-beginning-of-line arg))
- (t (beginning-of-line arg))
- ))
-
-(defun ada-end-of-line (&optional arg)
- (interactive "P")
- (cond
- ((eq ada-tab-policy 'indent-af) (af-end-of-line arg))
- (t (end-of-line arg))
- ))
-
-(defun ada-current-column ()
- (cond
- ((eq ada-tab-policy 'indent-af) (af-current-column))
- (t (current-column))
- ))
-
-(defun ada-forward-to-indentation (&optional arg)
- (interactive "P")
- (cond
- ((eq ada-tab-policy 'indent-af) (af-forward-to-indentation arg))
- (t (forward-to-indentation arg))
- ))
-
-;;;---------------------------------------------------
-;;; support for find-file
-;;;---------------------------------------------------
-
-
-;;;###autoload
-(defun ada-make-filename-from-adaname (adaname)
- "Determine the filename of a package/procedure from its own Ada name."
- ;; this is done simply by calling gkrunch, when we work with GNAT. It
- ;; must be a more complex function in other compiler environments.
- (interactive "s")
-
- ;; things that should really be done by the external process
- ;; since gnat-2.0, gnatk8 can do these things. If you still use a
- ;; previous version, just uncomment the following lines.
- (let (krunch-buf)
- (setq krunch-buf (generate-new-buffer "*gkrunch*"))
- (save-excursion
- (set-buffer krunch-buf)
-; (insert (downcase adaname))
-; (goto-char (point-min))
-; (while (search-forward "." nil t)
-; (replace-match "-" nil t))
-; (setq adaname (buffer-substring (point-min)
-; (progn
-; (goto-char (point-min))
-; (end-of-line)
-; (point))))
-; ;; clean the buffer
-; (delete-region (point-min) (point-max))
- ;; send adaname to external process "gnatk8"
- (call-process "gnatk8" nil krunch-buf nil
- adaname ada-krunch-args)
- ;; fetch output of that process
- (setq adaname (buffer-substring
- (point-min)
- (progn
- (goto-char (point-min))
- (end-of-line)
- (point))))
- (kill-buffer krunch-buf)))
- (setq adaname adaname) ;; can I avoid this statement?
- )
-
-
-;;; functions for placing the cursor on the corresponding subprogram
-(defun ada-which-function-are-we-in ()
- "Determine whether we are on a function definition/declaration.
-If that is the case remember the name of that function."
-
- (setq ff-function-name nil)
-
- (save-excursion
- (if (re-search-backward ada-procedure-start-regexp nil t)
- (setq ff-function-name (buffer-substring (match-beginning 0)
- (match-end 0)))
- ; we didn't find a procedure start, perhaps there is a package
- (if (re-search-backward ada-package-start-regexp nil t)
- (setq ff-function-name (buffer-substring (match-beginning 0)
- (match-end 0)))
- ))))
-
-
-;;;---------------------------------------------------
-;;; support for imenu
-;;;---------------------------------------------------
-
-(defun imenu-create-ada-index (&optional regexp)
- "Create index alist for Ada files."
- (let ((index-alist '())
- prev-pos char)
- (goto-char (point-min))
- ;(imenu-progress-message prev-pos 0)
- ;; Search for functions/procedures
- (save-match-data
- (while (re-search-forward
- (or regexp ada-procedure-start-regexp)
- nil t)
- ;(imenu-progress-message prev-pos)
- ;; do not store forward definitions
- ;; right now we store them. We want to avoid them only in
- ;; package bodies, not in the specs!! ???RE???
- (save-match-data
-; (if (not (looking-at (concat
-; "[ \t\n]*" ; WS
-; "\([^)]+\)" ; parameterlist
-; "\\([ \n\t]+return[ \n\t]+"; potential return
-; "[a-zA-Z0-9_\\.]+\\)?"
-; "[ \t]*" ; WS
-; ";" ;; THIS is what we really look for
-; )))
-; ; (push (imenu-example--name-and-position) index-alist)
- (setq index-alist (cons (imenu-example--name-and-position)
- index-alist))
-; )
- )
- ;(imenu-progress-message 100)
- ))
- (nreverse index-alist)))
-
-;;;---------------------------------------------------
-;;; support for font-lock
-;;;---------------------------------------------------
-
-;; Strings are a real pain in Ada because both ' and " can appear in a
-;; non-string quote context (the former as an operator, the latter as
-;; a character string). We follow the least losing solution, in which
-;; only " is a string quote. Therefore a character string of the form
-;; '"' will throw fontification off on the wrong track.
-
-(defconst ada-font-lock-keywords-1
- (list
- ;;
- ;; accept, entry, function, package (body), protected (body|type),
- ;; pragma, procedure, task (body) plus name.
- (list (concat
- "\\<\\("
- "accept\\|"
- "entry\\|"
- "function\\|"
- "package[ \t]+body\\|"
- "package\\|"
- "pragma\\|"
- "procedure\\|"
- "protected[ \t]+body\\|"
- "protected[ \t]+type\\|"
- "protected\\|"
-;; "p\\(\\(ackage\\|rotected\\)\\(\\|[ \t]+\\(body\\|type\\)\\)\
-;;\\|r\\(agma\\|ocedure\\)\\)\\|"
- "task\\|"
- "task[ \t]+body\\|"
- "task[ \t]+type"
-;; "task\\(\\|[ \t]+body\\)"
- "\\)\\>[ \t]*"
- "\\(\\sw+\\(\\.\\sw*\\)*\\)?")
- '(1 font-lock-keyword-face) '(2 font-lock-function-name-face nil t)))
- "Subdued level highlighting for Ada mode.")
-
-(defconst ada-font-lock-keywords-2
- (append ada-font-lock-keywords-1
- (list
- ;;
- ;; Main keywords, except those treated specially below.
- (concat "\\<\\("
-; ("abort" "abs" "abstract" "accept" "access" "aliased" "all"
-; "and" "array" "at" "begin" "case" "declare" "delay" "delta"
-; "digits" "do" "else" "elsif" "entry" "exception" "exit" "for"
-; "generic" "if" "in" "is" "limited" "loop" "mod" "not"
-; "null" "or" "others" "private" "protected"
-; "range" "record" "rem" "renames" "requeue" "return" "reverse"
-; "select" "separate" "tagged" "task" "terminate" "then" "until"
-; "while" "xor")
- "a\\(b\\(ort\\|s\\(\\|tract\\)\\)\\|cce\\(pt\\|ss\\)\\|"
- "l\\(iased\\|l\\)\\|nd\\|rray\\|t\\)\\|begin\\|case\\|"
- "d\\(e\\(clare\\|l\\(ay\\|ta\\)\\)\\|igits\\|o\\)\\|"
- "e\\(ls\\(e\\|if\\)\\|ntry\\|x\\(ception\\|it\\)\\)\\|for\\|"
- "generic\\|i[fns]\\|l\\(imited\\|oop\\)\\|mod\\|n\\(ot\\|ull\\)\\|"
- "o\\(r\\|thers\\|ut\\)\\|pr\\(ivate\\|otected\\)\\|"
- "r\\(ange\\|e\\(cord\\|m\\|names\\|queue\\|turn\\|verse\\)\\)\\|"
- "se\\(lect\\|parate\\)\\|"
- "t\\(agged\\|erminate\\|hen\\)\\|until\\|" ; task removed
- "wh\\(ile\\|en\\)\\|xor" ; "when" added
- "\\)\\>")
- ;;
- ;; Anything following end and not already fontified is a body name.
- '("\\<\\(end\\)\\>[ \t]+\\([a-zA-Z0-9_\\.]+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))
- ;;
- ;; Variable name plus optional keywords followed by a type name. Slow.
-; (list (concat "\\<\\(\\sw+\\)\\>[ \t]*:?[ \t]*"
-; "\\(access\\|constant\\|in\\|in[ \t]+out\\|out\\)?[ \t]*"
-; "\\(\\sw+\\)?")
-; '(1 font-lock-variable-name-face)
-; '(2 font-lock-keyword-face nil t) '(3 font-lock-type-face nil t))
- ;;
- ;; Optional keywords followed by a type name.
- (list (concat ; ":[ \t]*"
- "\\<\\(access\\|constant\\|in\\|in[ \t]+out\\|out\\)\\>"
- "[ \t]*"
- "\\(\\sw+\\)?")
- '(1 font-lock-keyword-face nil t) '(2 font-lock-type-face nil t))
- ;;
- ;; Keywords followed by a type or function name.
- (list (concat "\\<\\("
- "new\\|of\\|subtype\\|type"
- "\\)\\>[ \t]*\\(\\sw+\\)?[ \t]*\\((\\)?")
- '(1 font-lock-keyword-face)
- '(2 (if (match-beginning 4)
- font-lock-function-name-face
- font-lock-type-face) nil t))
- ;;
- ;; Keywords followed by a (comma separated list of) reference.
- (list (concat "\\<\\(goto\\|raise\\|use\\|with\\)\\>" ; "when" removed
- ; "[ \t]*\\(\\sw+\\(\\.\\sw*\\)*\\)?") ; RE
- "[ \t]*\\([a-zA-Z0-9_\\.\\|, ]+\\)\\W")
- '(1 font-lock-keyword-face) '(2 font-lock-reference-face nil t))
- ;;
- ;; Goto tags.
- '("<<\\(\\sw+\\)>>" 1 font-lock-reference-face)
- ))
- "Gaudy level highlighting for Ada mode.")
-
-(defvar ada-font-lock-keywords ada-font-lock-keywords-2
- "Default Expressions to highlight in Ada mode.
-See the doc to `font-lock-maximum-decoration' for user configuration.")
-
-;;;
-;;; ????
-;;;
-(defun ada-gen-comment-until-proc ()
- ;; comment until spec of a procedure or a function.
- (forward-line 1)
- (set-mark-command (point))
- (if (re-search-forward ada-procedure-start-regexp nil t)
- (progn (goto-char (match-beginning 1))
- (comment-region (mark) (point)))
- (error "No more functions/procedures")))
-
-
-(defun ada-gen-treat-proc (match)
- ;; make dummy body of a procedure/function specification.
- ;; MATCH is a cons cell containing the start and end location of the
- ;; last search for ada-procedure-start-regexp.
- (goto-char (car match))
- (let (proc-found func-found procname functype)
- (cond
- ((or (setq proc-found (looking-at "^[ \t]*procedure"))
- (setq func-found (looking-at "^[ \t]*function")))
- ;; treat it as a proc/func
- (forward-word 2)
- (forward-word -1)
- (setq procname (buffer-substring (point) (cdr match))) ; store proc name
-
- ;; goto end of procname
- (goto-char (cdr match))
-
- ;; skip over parameterlist
- (forward-sexp)
- ;; if function, skip over 'return' and result type.
- (if func-found
- (progn
- (forward-word 1)
- (skip-chars-forward " \t\n")
- (setq functype (buffer-substring (point)
- (progn
- (skip-chars-forward
- "a-zA-Z0-9_\.")
- (point))))))
- ;; look for next non WS
- (cond
- ((looking-at "[ \t]*;")
- (delete-region (match-beginning 0) (match-end 0)) ;; delete the ';'
- (ada-indent-newline-indent)
- (insert " is")
- (ada-indent-newline-indent)
- (if func-found
- (progn
- (insert "Result : ")
- (insert functype)
- (insert ";")
- (ada-indent-newline-indent)))
- (insert "begin -- ")
- (insert procname)
- (ada-indent-newline-indent)
- (insert "null;")
- (ada-indent-newline-indent)
- (if func-found
- (progn
- (insert "return Result;")
- (ada-indent-newline-indent)))
- (insert "end ")
- (insert procname)
- (insert ";")
- (ada-indent-newline-indent)
- )
- ;; else
- ((looking-at "[ \t\n]*is")
- ;; do nothing
- )
- ((looking-at "[ \t\n]*rename")
- ;; do nothing
- )
- (t
- (message "unknown syntax")))
- ))))
-
-
-(defun ada-make-body ()
- "Create an Ada package body in the current buffer.
-The potential old buffer contents is deleted first, then we copy the
-spec buffer in here and modify it to make it a body.
-
-This function typically is to be hooked into `ff-file-created-hooks'."
- (interactive)
- (delete-region (point-min) (point-max))
- (insert-buffer (car (cdr (buffer-list))))
- (ada-mode)
-
- (let (found)
- (if (setq found
- (ada-search-ignore-string-comment ada-package-start-regexp))
- (progn (goto-char (cdr found))
- (insert " body")
- ;; (forward-line -1)
- ;;(comment-region (point-min) (point))
- )
- (error "No package"))
-
- ;; (comment-until-proc)
- ;; does not work correctly
- ;; must be done by hand
-
- (while (setq found
- (ada-search-ignore-string-comment ada-procedure-start-regexp))
- (ada-gen-treat-proc found))))
-
-
-;;; provide ourself
-
-(provide 'ada-mode)
-
-;;; ada-mode.el ends here
diff --git a/lisp/progmodes/asm-mode.el b/lisp/progmodes/asm-mode.el
deleted file mode 100644
index 3a0370bdaaf..00000000000
--- a/lisp/progmodes/asm-mode.el
+++ /dev/null
@@ -1,231 +0,0 @@
-;;; asm-mode.el --- mode for editing assembler code
-
-;; Copyright (C) 1991 Free Software Foundation, Inc.
-
-;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
-;; Maintainer: FSF
-;; Keywords: tools, languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This mode was written by Eric S. Raymond <esr@snark.thyrsus.com>,
-;; inspired by an earlier asm-mode by Martin Neitzel.
-
-;; This minor mode is based on text mode. It defines a private abbrev table
-;; that can be used to save abbrevs for assembler mnemonics. It binds just
-;; five keys:
-;;
-;; TAB tab to next tab stop
-;; : outdent preceding label, tab to tab stop
-;; comment char place or move comment
-;; asm-comment-char specifies which character this is;
-;; you can use a different character in different
-;; Asm mode buffers.
-;; C-j, C-m newline and tab to tab stop
-;;
-;; Code is indented to the first tab stop level.
-
-;; This mode runs two hooks:
-;; 1) An asm-mode-set-comment-hook before the part of the initialization
-;; depending on asm-comment-char, and
-;; 2) an asm-mode-hook at the end of initialization.
-
-;;; Code:
-
-(defvar asm-comment-char ?;
- "*The comment-start character assumed by Asm mode.")
-
-(defvar asm-mode-syntax-table nil
- "Syntax table used while in Asm mode.")
-
-(defvar asm-mode-abbrev-table nil
- "Abbrev table used while in Asm mode.")
-(define-abbrev-table 'asm-mode-abbrev-table ())
-
-(defvar asm-mode-map nil
- "Keymap for Asm mode.")
-
-(if asm-mode-map
- nil
- (setq asm-mode-map (make-sparse-keymap))
- ;; Note that the comment character isn't set up until asm-mode is called.
- (define-key asm-mode-map ":" 'asm-colon)
- (define-key asm-mode-map "\C-c;" 'comment-region)
- (define-key asm-mode-map "\C-i" 'tab-to-tab-stop)
- (define-key asm-mode-map "\C-j" 'asm-newline)
- (define-key asm-mode-map "\C-m" 'asm-newline)
- )
-
-(defconst asm-font-lock-keywords
- '(("^\\(\\(\\sw\\|\\s_\\)+\\)\\>:?[ \t]*\\(\\sw+\\)?"
- (1 font-lock-function-name-face) (3 font-lock-keyword-face nil t))
- ("^\\s +\\(\\(\\sw\\|\\s_\\)+\\)" 1 font-lock-keyword-face))
- "Additional expressions to highlight in Assembler mode.")
-
-(defvar asm-code-level-empty-comment-pattern nil)
-(defvar asm-flush-left-empty-comment-pattern nil)
-(defvar asm-inline-empty-comment-pattern nil)
-
-;;;###autoload
-(defun asm-mode ()
- "Major mode for editing typical assembler code.
-Features a private abbrev table and the following bindings:
-
-\\[asm-colon]\toutdent a preceding label, tab to next tab stop.
-\\[tab-to-tab-stop]\ttab to next tab stop.
-\\[asm-newline]\tnewline, then tab to next tab stop.
-\\[asm-comment]\tsmart placement of assembler comments.
-
-The character used for making comments is set by the variable
-`asm-comment-char' (which defaults to `?;').
-
-Alternatively, you may set this variable in `asm-mode-set-comment-hook',
-which is called near the beginning of mode initialization.
-
-Turning on Asm mode runs the hook `asm-mode-hook' at the end of initialization.
-
-Special commands:
-\\{asm-mode-map}
-"
- (interactive)
- (kill-all-local-variables)
- (setq mode-name "Assembler")
- (setq major-mode 'asm-mode)
- (setq local-abbrev-table asm-mode-abbrev-table)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(asm-font-lock-keywords))
- (make-local-variable 'asm-mode-syntax-table)
- (setq asm-mode-syntax-table (make-syntax-table))
- (set-syntax-table asm-mode-syntax-table)
-
- (run-hooks 'asm-mode-set-comment-hook)
- ;; Make our own local child of asm-mode-map
- ;; so we can define our own comment character.
- (use-local-map (nconc (make-sparse-keymap) asm-mode-map))
- (local-set-key (vector asm-comment-char) 'asm-comment)
-
- (modify-syntax-entry asm-comment-char
- "<" asm-mode-syntax-table)
- (modify-syntax-entry ?\n
- ">" asm-mode-syntax-table)
- (let ((cs (regexp-quote (char-to-string asm-comment-char))))
- (make-local-variable 'comment-start)
- (setq comment-start (concat cs " "))
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip (concat cs "+[ \t]*"))
- (setq asm-inline-empty-comment-pattern (concat "^.+" cs "+ *$"))
- (setq asm-code-level-empty-comment-pattern (concat "^[\t ]+" cs cs " *$"))
- (setq asm-flush-left-empty-comment-pattern (concat "^" cs cs cs " *$"))
- )
- (make-local-variable 'comment-end)
- (setq comment-end "")
- (make-local-variable 'comment-column)
- (setq comment-column 32)
- (setq fill-prefix "\t")
- (run-hooks 'asm-mode-hook))
-
-(defun asm-colon ()
- "Insert a colon; if it follows a label, delete the label's indentation."
- (interactive)
- (save-excursion
- (beginning-of-line)
- (if (looking-at "[ \t]+\\(\\sw\\|\\s_\\)+$")
- (delete-horizontal-space)))
- (insert ":")
- (tab-to-tab-stop)
- )
-
-(defun asm-newline ()
- "Insert LFD + fill-prefix, to bring us back to code-indent level."
- (interactive)
- (if (eolp) (delete-horizontal-space))
- (insert "\n")
- (tab-to-tab-stop)
- )
-
-(defun asm-line-matches (pattern &optional withcomment)
- (save-excursion
- (beginning-of-line)
- (looking-at pattern)))
-
-(defun asm-pop-comment-level ()
- ;; Delete an empty comment ending current line. Then set up for a new one,
- ;; on the current line if it was all comment, otherwise above it
- (end-of-line)
- (delete-horizontal-space)
- (while (= (preceding-char) asm-comment-char)
- (delete-backward-char 1))
- (delete-horizontal-space)
- (if (bolp)
- nil
- (beginning-of-line)
- (open-line 1))
- )
-
-
-(defun asm-comment ()
- "Convert an empty comment to a `larger' kind, or start a new one.
-These are the known comment classes:
-
- 1 -- comment to the right of the code (at the comment-column)
- 2 -- comment on its own line, indented like code
- 3 -- comment on its own line, beginning at the left-most column.
-
-Suggested usage: while writing your code, trigger asm-comment
-repeatedly until you are satisfied with the kind of comment."
- (interactive)
- (cond
-
- ;; Blank line? Then start comment at code indent level.
- ((asm-line-matches "^[ \t]*$")
- (delete-horizontal-space)
- (tab-to-tab-stop)
- (insert asm-comment-char comment-start))
-
- ;; Nonblank line with no comment chars in it?
- ;; Then start a comment at the current comment column
- ((asm-line-matches (format "^[^%c\n]+$" asm-comment-char))
- (indent-for-comment))
-
- ;; Flush-left comment present? Just insert character.
- ((asm-line-matches asm-flush-left-empty-comment-pattern)
- (insert asm-comment-char))
-
- ;; Empty code-level comment already present?
- ;; Then start flush-left comment, on line above if this one is nonempty.
- ((asm-line-matches asm-code-level-empty-comment-pattern)
- (asm-pop-comment-level)
- (insert asm-comment-char asm-comment-char comment-start))
-
- ;; Empty comment ends line?
- ;; Then make code-level comment, on line above if this one is nonempty.
- ((asm-line-matches asm-inline-empty-comment-pattern)
- (asm-pop-comment-level)
- (tab-to-tab-stop)
- (insert asm-comment-char comment-start))
-
- ;; If all else fails, insert character
- (t
- (insert asm-comment-char))
-
- )
- (end-of-line))
-
-;;; asm-mode.el ends here
diff --git a/lisp/progmodes/awk-mode.el b/lisp/progmodes/awk-mode.el
deleted file mode 100644
index 3ba782bac38..00000000000
--- a/lisp/progmodes/awk-mode.el
+++ /dev/null
@@ -1,153 +0,0 @@
-;;; awk-mode.el --- AWK code editing commands for Emacs
-
-;; Copyright (C) 1988, 1994, 1996 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: unix, languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Sets up C-mode with support for awk-style #-comments and a lightly
-;; hacked syntax table.
-
-;;; Code:
-
-(defvar awk-mode-syntax-table nil
- "Syntax table in use in Awk-mode buffers.")
-
-(if awk-mode-syntax-table
- ()
- (setq awk-mode-syntax-table (make-syntax-table))
- (modify-syntax-entry ?\\ "\\" awk-mode-syntax-table)
- (modify-syntax-entry ?\n "> " awk-mode-syntax-table)
- (modify-syntax-entry ?\f "> " awk-mode-syntax-table)
- (modify-syntax-entry ?\# "< " awk-mode-syntax-table)
- (modify-syntax-entry ?/ "." awk-mode-syntax-table)
- (modify-syntax-entry ?* "." awk-mode-syntax-table)
- (modify-syntax-entry ?+ "." awk-mode-syntax-table)
- (modify-syntax-entry ?- "." awk-mode-syntax-table)
- (modify-syntax-entry ?= "." awk-mode-syntax-table)
- (modify-syntax-entry ?% "." awk-mode-syntax-table)
- (modify-syntax-entry ?< "." awk-mode-syntax-table)
- (modify-syntax-entry ?> "." awk-mode-syntax-table)
- (modify-syntax-entry ?& "." awk-mode-syntax-table)
- (modify-syntax-entry ?| "." awk-mode-syntax-table)
- (modify-syntax-entry ?_ "_" awk-mode-syntax-table)
- (modify-syntax-entry ?\' "\"" awk-mode-syntax-table))
-
-(defvar awk-mode-abbrev-table nil
- "Abbrev table in use in Awk-mode buffers.")
-(define-abbrev-table 'awk-mode-abbrev-table ())
-
-;; Regexps written with help from Peter Galbraith <galbraith@mixing.qc.dfo.ca>.
-(defconst awk-font-lock-keywords
- (eval-when-compile
- (list
- ;;
- ;; Function names.
- '("^[ \t]*\\(function\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))
- ;;
- ;; Variable names.
- (cons (concat "\\<\\("
-; ("ARGC" "ARGIND" "ARGV" "CONVFMT" "ENVIRON" "ERRNO"
-; "FIELDWIDTHS" "FILENAME" "FNR" "FS" "IGNORECASE" "NF" "NR"
-; "OFMT" "OFS" "ORS" "RLENGTH" "RS" "RSTART" "SUBSEP")
- "ARG\\([CV]\\|IND\\)\\|CONVFMT\\|E\\(NVIRON\\|RRNO\\)\\|"
- "F\\(I\\(ELDWIDTHS\\|LENAME\\)\\|NR\\|S\\)\\|IGNORECASE\\|"
- "N[FR]\\|O\\(F\\(MT\\|S\\)\\|RS\\)\\|"
- "R\\(LENGTH\\|S\\(\\|TART\\)\\)\\|SUBSEP"
- "\\)\\>")
- 'font-lock-variable-name-face)
- ;;
- ;; Keywords.
- (concat "\\<\\("
-; ("BEGIN" "END" "break" "continue" "delete" "exit" "for"
-; "getline" "if" "next" "print" "printf" "return" "while")
- "BEGIN\\|END\\|break\\|continue\\|delete\\|exit\\|for\\|"
- "getline\\|if\\|next\\|printf?\\|return\\|while"
- "\\)\\>")
- ;;
- ;; Builtins.
- (list (concat "\\<\\("
-; ("atan2" "close" "cos" "ctime" "exp" "gsub" "index" "int"
-; "length" "log" "match" "rand" "sin" "split" "sprintf"
-; "sqrt" "srand" "sub" "substr" "system" "time"
-; "tolower" "toupper")
- "atan2\\|c\\(lose\\|os\\|time\\)\\|exp\\|gsub\\|"
- "in\\(dex\\|t\\)\\|l\\(ength\\|og\\)\\|match\\|rand\\|"
- "s\\(in\\|p\\(lit\\|rintf\\)\\|qrt\\|rand\\|"
- "ub\\(\\|str\\)\\|ystem\\)\\|"
- "t\\(ime\\|o\\(lower\\|upper\\)\\)"
- "\\)(")
- 1 'font-lock-builtin-face)
- ;;
- ;; Operators. Is this too much?
- (cons (mapconcat 'identity
- '("&&" "||" "<=" "<" ">=" ">" "==" "!=" "!~" "~")
- "\\|")
- 'font-lock-reference-face)
- ))
- "Default expressions to highlight in AWK mode.")
-
-;;;###autoload
-(defun awk-mode ()
- "Major mode for editing AWK code.
-This is much like C mode except for the syntax of comments. It uses
-the same keymap as C mode and has the same variables for customizing
-indentation. It has its own abbrev table and its own syntax table.
-
-Turning on AWK mode calls the value of the variable `awk-mode-hook'
-with no args, if that value is non-nil."
- (interactive)
- (kill-all-local-variables)
- (require 'cc-mode)
- (use-local-map c-mode-map)
- (setq major-mode 'awk-mode)
- (setq mode-name "AWK")
- (setq local-abbrev-table awk-mode-abbrev-table)
- (set-syntax-table awk-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-function)
- (setq comment-indent-function 'c-comment-indent)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(awk-font-lock-keywords nil nil ((?_ . "w"))))
- (run-hooks 'awk-mode-hook))
-
-(provide 'awk-mode)
-
-;;; awk-mode.el ends here
diff --git a/lisp/progmodes/c-mode.el b/lisp/progmodes/c-mode.el
deleted file mode 100644
index f3364457e18..00000000000
--- a/lisp/progmodes/c-mode.el
+++ /dev/null
@@ -1,1650 +0,0 @@
-;;; c-mode.el --- C code editing commands for Emacs
-
-;; Copyright (C) 1985, 86, 87, 92, 94, 95 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: c
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; A smart editing mode for C code. It knows a lot about C syntax and tries
-;; to position the cursor according to C layout conventions. You can
-;; change the details of the layout style with option variables. Load it
-;; and do M-x describe-mode for details.
-
-;;; Code:
-
-(defvar c-mode-abbrev-table nil
- "Abbrev table in use in C mode.")
-(define-abbrev-table 'c-mode-abbrev-table ())
-
-(defvar c-mode-map (make-sparse-keymap)
- "Keymap used in C mode.")
-
-(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-sharp-sign)
-(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 "\ea" 'c-beginning-of-statement)
-(define-key c-mode-map "\ee" 'c-end-of-statement)
-(define-key c-mode-map "\C-c\C-n" 'c-forward-conditional)
-(define-key c-mode-map "\C-c\C-p" 'c-backward-conditional)
-(define-key c-mode-map "\C-c\C-u" 'c-up-conditional)
-(define-key c-mode-map "\177" 'backward-delete-char-untabify)
-(define-key c-mode-map "\t" 'c-indent-command)
-
-(define-key c-mode-map [menu-bar] (make-sparse-keymap))
-
-;; "C-mode" is not strictly the right punctuation--it should be "C
-;; mode"--but that would look like two menu items. "C-mode" is the
-;; best alternative I can think of.
-(define-key c-mode-map [menu-bar c]
- (cons "C-mode" (make-sparse-keymap "C-mode")))
-
-(define-key c-mode-map [menu-bar c comment-region]
- '("Comment Out Region" . comment-region))
-(define-key c-mode-map [menu-bar c c-macro-expand]
- '("Macro Expand Region" . c-macro-expand))
-(define-key c-mode-map [menu-bar c c-backslash-region]
- '("Backslashify" . c-backslash-region))
-(define-key c-mode-map [menu-bar c indent-exp]
- '("Indent Expression" . indent-c-exp))
-(define-key c-mode-map [menu-bar c indent-line]
- '("Indent Line" . c-indent-command))
-(define-key c-mode-map [menu-bar c fill]
- '("Fill Comment Paragraph" . c-fill-paragraph))
-(define-key c-mode-map [menu-bar c cpp-highlight-buffer]
- '("Highlight Conditionals" . cpp-highlight-buffer))
-(define-key c-mode-map [menu-bar c up]
- '("Up Conditional" . c-up-conditional))
-(define-key c-mode-map [menu-bar c backward]
- '("Backward Conditional" . c-backward-conditional))
-(define-key c-mode-map [menu-bar c forward]
- '("Forward Conditional" . c-forward-conditional))
-(define-key c-mode-map [menu-bar c backward-stmt]
- '("Backward Statement" . c-beginning-of-statement))
-(define-key c-mode-map [menu-bar c forward-stmt]
- '("Forward Statement" . c-end-of-statement))
-
-(put 'comment-region 'menu-enable 'mark-active)
-(put 'c-macro-expand 'menu-enable 'mark-active)
-(put 'c-backslash-region 'menu-enable 'mark-active)
-
-(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-style-alist
- '(("GNU"
- (c-indent-level . 2)
- (c-argdecl-indent . 5)
- (c-brace-offset . 0)
- (c-continued-brace-offset . 0)
- (c-label-offset . -2)
- (c-continued-statement-offset . 2))
- ("K&R"
- (c-indent-level . 5)
- (c-argdecl-indent . 0)
- (c-brace-offset . 0)
- (c-continued-brace-offset . -5)
- (c-label-offset . -5)
- (c-continued-statement-offset . 5))
- ("BSD"
- (c-indent-level . 4)
- (c-argdecl-indent . 4)
- (c-brace-offset . 0)
- (c-continued-brace-offset . -4)
- (c-label-offset . -4)
- (c-continued-statement-offset . 4))
- ("C++"
- (c-indent-level . 4)
- (c-argdecl-indent . 0)
- (c-brace-offset . 0)
- (c-continued-brace-offset . -4)
- (c-label-offset . -4)
- (c-continued-statement-offset . 4)
- (c-auto-newline . t))
- ("Whitesmith"
- (c-indent-level . 4)
- (c-argdecl-indent . 4)
- (c-brace-offset . 0)
- (c-continued-brace-offset . 0)
- (c-label-offset . -4)
- (c-continued-statement-offset . 4))))
-
-(defconst c-auto-newline nil
- "*Non-nil means automatically newline before and after braces,
-and after colons and semicolons, inserted in C code.
-If you do not want a leading newline before braces then use:
- (define-key c-mode-map \"{\" 'electric-c-semi)")
-
-(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.")
-
-;;; Regular expression used internally to recognize labels in switch
-;;; statements.
-(defconst c-switch-label-regexp "case[ \t'/(]\\|default[ \t]*:")
-
-;; This is actually the expression for C++ mode, but it's used for C too.
-(defvar c-imenu-generic-expression
- (`
- ((nil
- (,
- (concat
- "^" ; beginning of line is required
- "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
- "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; type specs; there can be no
- "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; more than 3 tokens, right?
-
- "\\(" ; last type spec including */&
- "[a-zA-Z0-9_:]+"
- "\\([ \t]*[*&]+[ \t]*\\|[ \t]+\\)" ; either pointer/ref sign or whitespace
- "\\)?" ; if there is a last type spec
- "\\(" ; name; take that into the imenu entry
- "[a-zA-Z0-9_:~]+" ; member function, ctor or dtor...
- ; (may not contain * because then
- ; "a::operator char*" would become "char*"!)
- "\\|"
- "\\([a-zA-Z0-9_:~]*::\\)?operator"
- "[^a-zA-Z1-9_][^(]*" ; ...or operator
- " \\)"
- "[ \t]*([^)]*)[ \t\n]*[^ ;]" ; require something other than a ; after
- ; the (...) to avoid prototypes. Can't
- ; catch cases with () inside the parentheses
- ; surrounding the parameters
- ; (like "int foo(int a=bar()) {...}"
-
- )) 6)
- ("Class"
- (, (concat
- "^" ; beginning of line is required
- "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
- "class[ \t]+"
- "\\([a-zA-Z0-9_]+\\)" ; this is the string we want to get
- "[ \t]*[:{]"
- )) 2)
-;; Example of generic expression for finding prototypes, structs, unions, enums.
-;; Uncomment if you want to find these too. It will be a bit slower gathering
-;; the indexes.
-; ("Prototypes"
-; (,
-; (concat
-; "^" ; beginning of line is required
-; "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
-; "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; type specs; there can be no
-; "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; more than 3 tokens, right?
-
-; "\\(" ; last type spec including */&
-; "[a-zA-Z0-9_:]+"
-; "\\([ \t]*[*&]+[ \t]*\\|[ \t]+\\)" ; either pointer/ref sign or whitespace
-; "\\)?" ; if there is a last type spec
-; "\\(" ; name; take that into the imenu entry
-; "[a-zA-Z0-9_:~]+" ; member function, ctor or dtor...
-; ; (may not contain * because then
-; ; "a::operator char*" would become "char*"!)
-; "\\|"
-; "\\([a-zA-Z0-9_:~]*::\\)?operator"
-; "[^a-zA-Z1-9_][^(]*" ; ...or operator
-; " \\)"
-; "[ \t]*([^)]*)[ \t\n]*;" ; require ';' after
-; ; the (...) Can't
-; ; catch cases with () inside the parentheses
-; ; surrounding the parameters
-; ; (like "int foo(int a=bar());"
-; )) 6)
-; ("Struct"
-; (, (concat
-; "^" ; beginning of line is required
-; "\\(static[ \t]+\\)?" ; there may be static or const.
-; "\\(const[ \t]+\\)?"
-; "struct[ \t]+"
-; "\\([a-zA-Z0-9_]+\\)" ; this is the string we want to get
-; "[ \t]*[{]"
-; )) 3)
-; ("Enum"
-; (, (concat
-; "^" ; beginning of line is required
-; "\\(static[ \t]+\\)?" ; there may be static or const.
-; "\\(const[ \t]+\\)?"
-; "enum[ \t]+"
-; "\\([a-zA-Z0-9_]+\\)" ; this is the string we want to get
-; "[ \t]*[{]"
-; )) 3)
-; ("Union"
-; (, (concat
-; "^" ; beginning of line is required
-; "\\(static[ \t]+\\)?" ; there may be static or const.
-; "\\(const[ \t]+\\)?"
-; "union[ \t]+"
-; "\\([a-zA-Z0-9_]+\\)" ; this is the string we want to get
-; "[ \t]*[{]"
-; )) 3)
- ))
- "Imenu generic expression for C mode. See `imenu-generic-expression'.")
-
-(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 'fill-paragraph-function)
- (setq fill-paragraph-function 'c-fill-paragraph)
- (make-local-variable 'indent-line-function)
- (setq indent-line-function 'c-indent-line)
- (make-local-variable 'indent-region-function)
- (setq indent-region-function 'c-indent-region)
- (make-local-variable 'require-final-newline)
- (setq require-final-newline t)
- (make-local-variable 'outline-regexp)
- (setq outline-regexp "[^#\n\^M]")
- (make-local-variable 'outline-level)
- (setq outline-level 'c-outline-level)
- (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-function)
- (setq comment-indent-function 'c-comment-indent)
- (make-local-variable 'comment-multi-line)
- (setq comment-multi-line t)
- (make-local-variable 'parse-sexp-ignore-comments)
- (setq parse-sexp-ignore-comments t)
- (make-local-variable 'imenu-generic-expression)
- (setq imenu-generic-expression c-imenu-generic-expression)
- (run-hooks 'c-mode-hook))
-
-(defun c-outline-level ()
- (save-excursion
- (skip-chars-forward "\t ")
- (current-column)))
-
-;; 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.
- (let ((opoint (point)))
- (save-excursion
- (beginning-of-line)
- (cond ((looking-at "[ \t]*}[ \t]*\\($\\|/\\*\\)")
- ;; A comment following a solitary close-brace
- ;; should have only one space.
- (search-forward "}")
- (1+ (current-column)))
- ((or (looking-at "^#[ \t]*endif[ \t]*")
- (looking-at "^#[ \t]*else[ \t]*"))
- 7) ;2 spaces after #endif
- ((progn
- (goto-char opoint)
- (skip-chars-backward " \t")
- (and (= comment-column 0) (bolp)))
- ;; If comment-column is 0, and nothing but space
- ;; before the comment, align it at 0 rather than 1.
- 0)
- (t
- (max (1+ (current-column)) ;Else indent at comment column
- comment-column))))))) ; except leave at least one space.
-
-(defun c-fill-paragraph (&optional arg)
- "Like \\[fill-paragraph] but handle C comments.
-If any of the current line is a comment or within a comment,
-fill the comment or the paragraph of it that point is in,
-preserving the comment indentation or line-starting decorations."
- (interactive "P")
- (let* (comment-start-place
- (first-line
- ;; Check for obvious entry to comment.
- (save-excursion
- (beginning-of-line)
- (skip-chars-forward " \t\n")
- (and (looking-at comment-start-skip)
- (setq comment-start-place (point))))))
- (if (and (eq major-mode 'c++-mode)
- (save-excursion
- (beginning-of-line)
- (looking-at ".*//")))
- (let (fill-prefix
- (paragraph-start
- ;; Lines containing just a comment start or just an end
- ;; should not be filled into paragraphs they are next to.
- (concat
- paragraph-start
- "\\|[ \t]*/\\*[ \t]*$\\|[ \t]*\\*/[ \t]*$\\|[ \t/*]*$"))
- (paragraph-separate
- (concat
- paragraph-separate
- "\\|[ \t]*/\\*[ \t]*$\\|[ \t]*\\*/[ \t]*$\\|[ \t/*]*$")))
- (save-excursion
- (beginning-of-line)
- ;; Move up to first line of this comment.
- (while (and (not (bobp)) (looking-at "[ \t]*//"))
- (forward-line -1))
- (if (not (looking-at ".*//"))
- (forward-line 1))
- ;; Find the comment start in this line.
- (re-search-forward "[ \t]*//[ \t]*")
- ;; Set the fill-prefix to be what all lines except the first
- ;; should start with.
- (let ((endcol (current-column)))
- (skip-chars-backward " \t")
- (setq fill-prefix
- (concat (make-string (- (current-column) 2) ?\ )
- "//"
- (make-string (- endcol (current-column)) ?\ ))))
- (save-restriction
- ;; Narrow down to just the lines of this comment.
- (narrow-to-region (point)
- (save-excursion
- (forward-line 1)
- (while (looking-at "[ \t]*//")
- (forward-line 1))
- (point)))
- (insert fill-prefix)
- (fill-paragraph arg)
- (delete-region (point-min)
- (+ (point-min) (length fill-prefix))))))
- (if (or first-line
- ;; t if we enter a comment between start of function and this line.
- (eq (calculate-c-indent) t)
- ;; t if this line contains a comment starter.
- (setq first-line
- (save-excursion
- (beginning-of-line)
- (prog1
- (re-search-forward comment-start-skip
- (save-excursion (end-of-line)
- (point))
- t)
- (setq comment-start-place (point))))))
- ;; Inside a comment: fill one comment paragraph.
- (let ((fill-prefix
- ;; The prefix for each line of this paragraph
- ;; is the appropriate part of the start of this line,
- ;; up to the column at which text should be indented.
- (save-excursion
- (beginning-of-line)
- (if (looking-at "[ \t]*/\\*.*\\*/")
- (progn (re-search-forward comment-start-skip)
- (make-string (current-column) ?\ ))
- (if first-line (forward-line 1))
-
- (let ((line-width (progn (end-of-line) (current-column))))
- (beginning-of-line)
- (prog1
- (buffer-substring
- (point)
-
- ;; How shall we decide where the end of the
- ;; fill-prefix is?
- ;; calculate-c-indent-within-comment bases its value
- ;; on the indentation of previous lines; if they're
- ;; indented specially, it could return a column
- ;; that's well into the current line's text. So
- ;; we'll take at most that many space, tab, or *
- ;; characters, and use that as our fill prefix.
- (let ((max-prefix-end
- (progn
- (move-to-column
- (calculate-c-indent-within-comment t)
- t)
- (point))))
- (beginning-of-line)
- (skip-chars-forward " \t*" max-prefix-end)
- ;; Don't include part of comment terminator
- ;; in the fill-prefix.
- (and (eq (following-char) ?/)
- (eq (preceding-char) ?*)
- (backward-char 1))
- (point)))
-
- ;; If the comment is only one line followed by a blank
- ;; line, calling move-to-column above may have added
- ;; some spaces and tabs to the end of the line; the
- ;; fill-paragraph function will then delete it and the
- ;; newline following it, so we'll lose a blank line
- ;; when we shouldn't. So delete anything
- ;; move-to-column added to the end of the line. We
- ;; record the line width instead of the position of the
- ;; old line end because move-to-column might break a
- ;; tab into spaces, and the new characters introduced
- ;; there shouldn't be deleted.
-
- ;; If you can see a better way to do this, please make
- ;; the change. This seems very messy to me.
- (delete-region (progn (move-to-column line-width)
- (point))
- (progn (end-of-line) (point))))))))
-
- (paragraph-start
- ;; Lines containing just a comment start or just an end
- ;; should not be filled into paragraphs they are next to.
- (concat
- paragraph-start
- "\\|[ \t]*/\\*[ \t]*$\\|[ \t]*\\*/[ \t]*$\\|[ \t/*]*$"))
- (paragraph-separate
- (concat
- paragraph-separate
- "\\|[ \t]*/\\*[ \t]*$\\|[ \t]*\\*/[ \t]*$\\|[ \t/*]*$"))
- (chars-to-delete 0))
- (save-restriction
- ;; Don't fill the comment together with the code following it.
- ;; So temporarily exclude everything before the comment start,
- ;; and everything after the line where the comment ends.
- ;; If comment-start-place is non-nil, the comment starter is there.
- ;; Otherwise, point is inside the comment.
- (narrow-to-region (save-excursion
- (if comment-start-place
- (goto-char comment-start-place)
- (search-backward "/*"))
- ;; Protect text before the comment start
- ;; by excluding it. Add spaces to bring back
- ;; proper indentation of that point.
- (let ((column (current-column)))
- (prog1 (point)
- (setq chars-to-delete column)
- (insert-char ?\ column))))
- (save-excursion
- (if comment-start-place
- (goto-char (+ comment-start-place 2)))
- (search-forward "*/" nil 'move)
- (forward-line 1)
- (point)))
- (save-excursion
- (goto-char (point-max))
- (forward-line -1)
- ;; And comment terminator was on a separate line before,
- ;; keep it that way.
- ;; This also avoids another problem:
- ;; if the fill-prefix ends in a *, it could eat up
- ;; the * of the comment terminator.
- (if (looking-at "[ \t]*\\*/")
- (narrow-to-region (point-min) (point))))
- (fill-paragraph arg)
- (save-excursion
- ;; Delete the chars we inserted to avoid clobbering
- ;; the stuff before the comment start.
- (goto-char (point-min))
- (if (> chars-to-delete 0)
- (delete-region (point) (+ (point) chars-to-delete)))
- ;; Find the comment ender (should be on last line of buffer,
- ;; given the narrowing) and don't leave it on its own line.
- ;; Do this with a fill command, so as to preserve sentence
- ;; boundaries.
- (goto-char (point-max))
- (forward-line -1)
- (search-forward "*/" nil 'move)
- (beginning-of-line)
- (if (looking-at "[ \t]*\\*/")
- (let ((fill-column (+ fill-column 9999)))
- (forward-line -1)
- (fill-region-as-paragraph (point) (point-max)))))))
- ;; Outside of comments: do ordinary filling.
- (fill-paragraph arg)))
- t))
-
-(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-sharp-sign (arg)
- "Insert character and correct line's indentation."
- (interactive "P")
- (if (save-excursion
- (skip-chars-backward " \t")
- (bolp))
- (let ((c-auto-newline nil))
- (electric-c-terminator 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 c-switch-label-regexp))
- (save-excursion
- (skip-chars-forward "a-zA-Z0-9_$")
- (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)
- ;; (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 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))
- ;; Find beginning of following line.
- (save-excursion
- (forward-line 1) (setq beg (point)))
- ;; Find first beginning-of-sexp for sexp extending past this line.
- (while (< (point) beg)
- (forward-sexp 1)
- (setq end (point))
- (skip-chars-forward " \t\n")))
- (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 c-switch-label-regexp)
- (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))))
- ((and (looking-at "}[ \t]*else\\b")
- (not (looking-at "}[ \t]*else\\s_")))
- (setq indent (save-excursion
- (forward-char)
- (backward-sexp)
- (c-backward-to-start-of-if)
- (current-indentation))))
- ((and (looking-at "while\\b")
- (not (looking-at "while\\s_"))
- (save-excursion
- (c-backward-to-start-of-do)))
- ;; This is a `while' that ends a do-while.
- (setq indent (save-excursion
- (c-backward-to-start-of-do)
- (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 accordingly.
- (let ((basic-indent
- (save-excursion
- (re-search-backward "^[^ \^L\t\n#]" nil 'move)
- (let (comment lim)
- ;; Recognize the DEFUN macro in Emacs.
- (if (save-excursion
- ;; Move down to the (putative) argnames line.
- (while (and (not (eobp))
- (not (looking-at " *[({}#/]")))
- (forward-line 1))
- ;; Go back to the DEFUN, if it is one.
- (condition-case nil
- (backward-sexp 1)
- (error))
- (beginning-of-line)
- (looking-at "DEFUN\\b"))
- c-argdecl-indent
- (if (and (looking-at "\\sw\\|\\s_")
- ;; This is careful to stop at the first
- ;; paren if we have
- ;; int foo Proto ((int, int));
- (looking-at "[^\"\n=(]*(")
- (progn
- (goto-char (1- (match-end 0)))
- ;; Skip any number of paren-groups.
- ;; Consider typedef int (*fcn) (int);
- (while (= (following-char) ?\()
- (setq lim (point))
- (condition-case nil
- (forward-sexp 1)
- (error))
- (skip-chars-forward " \t\f"))
- ;; Have we reached something
- ;; that shows this isn't a function
- ;; definition?
- (and (< (point) indent-point)
- (not (memq (following-char)
- '(?\, ?\;)))))
- ;; Make sure the "function decl" we found
- ;; is not inside a comment.
- (progn
- ;; Move back to the `(' starting arglist
- (goto-char lim)
- (beginning-of-line)
- (while (and (not comment)
- (search-forward "/*" lim t))
- (setq comment
- (not (search-forward "*/" lim t))))
- (not comment)))
- c-argdecl-indent 0))))))
- basic-indent)))
-
-;; ;; Now add a little if this is a continuation line.
-;; (+ basic-indent (if (or (bobp)
-;; (memq (preceding-char) '(?\) ?\; ?\}))
-;; ;; Line with zero indentation
-;; ;; is probably the return-type
-;; ;; of a function definition,
-;; ;; so following line is function name.
-;; (= (current-indentation) 0))
-;; 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) ?\,)
- (progn (forward-char -1)
- (c-backward-to-start-of-continued-exp containing-sexp)))
- (beginning-of-line)
- (c-backward-to-noncomment containing-sexp))
- ;; Check for a preprocessor statement or its continuation lines.
- ;; Move back to end of previous non-preprocessor line,
- ;; or possibly beginning of buffer.
- (let ((found (point)) stop)
- (while (not stop)
- (beginning-of-line)
- (cond ((bobp)
- (setq found (point)
- stop t))
- ((save-excursion (forward-char -1)
- (= (preceding-char) ?\\))
- (forward-char -1))
- ;; This line is not preceded by a backslash.
- ;; So either it starts a preprocessor command
- ;; or any following continuation lines
- ;; should not be skipped.
- ((= (following-char) ?#)
- (forward-char -1)
- (setq found (point)))
- (t (setq stop t))))
- (goto-char found))
- ;; Now we get the answer.
- (if (and (not (memq (preceding-char) '(0 ?\, ?\; ?\} ?\{)))
- ;; But don't treat a line with a close-brace
- ;; as a continuation. It is probably the
- ;; end of an enum type declaration.
- (save-excursion
- (goto-char indent-point)
- (skip-chars-forward " \t")
- (not (= (following-char) ?}))))
- ;; 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 prev stmt starts with open-brace, that
- ;; open brace was offset by c-brace-offset.
- ;; Compensate to get the column where
- ;; an ordinary statement would start.
- (if (= (following-char) ?\{) c-brace-offset 0)))))
- ;; If no previous statement,
- ;; indent it relative to line brace is on.
- (calculate-c-indent-after-brace))))))))
-
-(defun calculate-c-indent-after-brace ()
- "Return the proper C indent for the first line after an open-brace.
-This function is called with point before the brace."
- ;; 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 (&optional after-star)
- "Return the indentation amount for line inside a block comment.
-Optional arg AFTER-STAR means, if lines in the comment have a leading star,
-return the indentation of the text that would follow this star."
- (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")
- (if after-star
- (and (looking-at "\\*")
- (re-search-forward "\\*[ \t]*")))
- (and (re-search-forward "/\\*[ \t]*" end t)
- star-start
- (not after-star)
- (goto-char (1+ (match-beginning 0))))
- (if (and (looking-at "[ \t]*$") (= (preceding-char) ?\*))
- (1+ (current-column))
- (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 (memq (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 (and (not (bobp)) (not (zerop if-level)))
- (backward-sexp 1)
- (cond ((and (looking-at "else\\b")
- (not (looking-at "else\\s_")))
- (setq if-level (1+ if-level)))
- ((and (looking-at "if\\b")
- (not (looking-at "if\\s_")))
- (setq if-level (1- if-level)))
- ((< (point) limit)
- (setq if-level 0)
- (goto-char limit))))))
-
-(defun c-backward-to-start-of-do (&optional limit)
- "If point follows a `do' statement, move to beginning of it and return t.
-Otherwise return nil and don't move point."
- (or limit (setq limit (save-excursion (beginning-of-defun) (point))))
- (let ((first t)
- (startpos (point))
- (done nil))
- (while (not done)
- (let ((next-start (point)))
- (condition-case nil
- ;; Move back one token or one brace or paren group.
- (backward-sexp 1)
- ;; If we find an open-brace, we lose.
- (error (setq done 'fail)))
- (if done
- nil
- ;; If we reached a `do', we win.
- (if (looking-at "do\\b")
- (setq done 'succeed)
- ;; Otherwise, if we skipped a semicolon, we lose.
- ;; (Exception: we can skip one semicolon before getting
- ;; to a the last token of the statement, unless that token
- ;; is a close brace.)
- (if (save-excursion
- (forward-sexp 1)
- (or (and (not first) (= (preceding-char) ?}))
- (search-forward ";" next-start t
- (if (and first
- (/= (preceding-char) ?}))
- 2 1))))
- (setq done 'fail)
- (setq first nil)
- ;; If we go too far back in the buffer, we lose.
- (if (< (point) limit)
- (setq done 'fail)))))))
- (if (eq done 'succeed)
- t
- (goto-char startpos)
- nil)))
-
-(defun c-beginning-of-statement (count)
- "Go to the beginning of the innermost C statement.
-With prefix arg, go back N - 1 statements. If already at the beginning of a
-statement then go to the beginning of the preceding one.
-If within a string or comment, or next to a comment (only whitespace between),
-move by sentences instead of statements."
- (interactive "p")
- (let ((here (point)) state)
- (save-excursion
- (beginning-of-defun)
- (setq state (parse-partial-sexp (point) here nil nil)))
- (if (or (nth 3 state) (nth 4 state)
- (looking-at (concat "[ \t]*" comment-start-skip))
- (save-excursion (skip-chars-backward " \t")
- (goto-char (- (point) 2))
- (looking-at "\\*/")))
- (forward-sentence (- count))
- (while (> count 0)
- (c-beginning-of-statement-1)
- (setq count (1- count)))
- (while (< count 0)
- (c-end-of-statement-1)
- (setq count (1+ count))))))
-
-(defun c-end-of-statement (count)
- "Go to the end of the innermost C statement.
-With prefix arg, go forward N - 1 statements.
-Move forward to end of the next statement if already at end.
-If within a string or comment, move by sentences instead of statements."
- (interactive "p")
- (c-beginning-of-statement (- count)))
-
-(defun c-beginning-of-statement-1 ()
- (let ((last-begin (point))
- (first t))
- (condition-case ()
- (progn
- (while (and (not (bobp))
- (progn
- (backward-sexp 1)
- (or first
- (not (re-search-forward "[;{}]" last-begin t)))))
- (setq last-begin (point) first nil))
- (goto-char last-begin))
- (error (if first (backward-up-list 1) (goto-char last-begin))))))
-
-(defun c-end-of-statement-1 ()
- (condition-case ()
- (progn
- (while (and (not (eobp))
- (let ((beg (point)))
- (forward-sexp 1)
- (let ((end (point)))
- (save-excursion
- (goto-char beg)
- (not (re-search-forward "[;{}]" end t)))))))
- (re-search-backward "[;}]")
- (forward-char 1))
- (error
- (let ((beg (point)))
- (backward-up-list -1)
- (let ((end (point)))
- (goto-char beg)
- (search-forward ";" end 'move))))))
-
-(defun mark-c-function ()
- "Put mark at end of C function, point at beginning."
- (interactive)
- (push-mark (point))
- (end-of-defun)
- (push-mark (point) nil t)
- (beginning-of-defun)
- (backward-paragraph))
-
-;; Idea of ENDPOS is, indent each line, stopping when
-;; ENDPOS is encountered. But it's too much of a pain to make that work.
-(defun indent-c-exp (&optional endpos)
- "Indent each line of the C grouping following point."
- (interactive)
- (let* ((indent-stack (list nil))
- (opoint (point)) ;; May be altered below.
- (contain-stack
- (list (if endpos
- (let (funbeg)
- ;; Find previous fcn-start.
- (save-excursion (forward-char 1)
- (beginning-of-defun)
- (setq funbeg (point)))
- (setq opoint funbeg)
- ;; Try to find containing open,
- ;; but don't scan past that fcn-start.
- (save-restriction
- (narrow-to-region funbeg (point))
- (condition-case nil
- (save-excursion
- (backward-up-list 1)
- (point))
- ;; We gave up: must be between fcns.
- ;; Set opoint to beg of prev fcn
- ;; since otherwise calculate-c-indent
- ;; will get wrong answers.
- (error (setq opoint funbeg)
- (point)))))
- (point))))
- (case-fold-search nil)
- restart outer-loop-done inner-loop-done state ostate
- this-indent last-sexp
- at-else at-brace at-while
- last-depth this-point
- (next-depth 0))
- ;; If the braces don't match, get an error right away.
- (save-excursion
- (forward-sexp 1))
- ;; Realign the comment on the first line, even though we don't reindent it.
- (save-excursion
- (let ((beg (point)))
- (and (re-search-forward
- comment-start-skip
- (save-excursion (end-of-line) (point)) t)
- ;; Make sure this isn't a comment alone on a line
- ;; (which should be indented like code instead).
- (save-excursion
- (goto-char (match-beginning 0))
- (skip-chars-backward " \t")
- (not (bolp)))
- ;; Make sure the comment starter we found
- ;; is not actually in a string or quoted.
- (let ((new-state
- (parse-partial-sexp beg (point)
- nil nil state)))
- (and (not (nth 3 new-state)) (not (nth 5 new-state))))
- (progn (indent-for-comment) (beginning-of-line)))))
- (save-excursion
- (setq outer-loop-done nil)
- (while (and (not (eobp))
- (if endpos (< (point) endpos)
- (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 this line started within a comment, indent it as such.
- (if (or (nth 4 ostate) (nth 7 ostate))
- (c-indent-line))
- ;; If it ends outside of comments or strings, exit the inner loop.
- ;; Otherwise move on to next line.
- (if (or (nth 3 state) (nth 4 state) (nth 7 state))
- (forward-line 1)
- (setq inner-loop-done t)))
- (and endpos
- (while (< next-depth 0)
- (setq indent-stack (append indent-stack (list nil)))
- (setq contain-stack (append contain-stack (list nil)))
- (setq next-depth (1+ next-depth))
- (setq last-depth (1+ last-depth))
- (setcar (nthcdr 6 state) (1+ (nth 6 state)))))
- (setq outer-loop-done (and (not endpos) (<= next-depth 0)))
- (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")
- ;; Don't really reindent if the line is just whitespace,
- ;; or if it is past the endpos.
- ;; (The exit test in the outer while
- ;; does not exit until we have passed the first line
- ;; past the region.)
- (if (or (eolp) (and endpos (>= (point) endpos)))
- nil
- ;; Is this line in a new nesting level?
- ;; In other words, is this the first line that
- ;; starts in the new level?
- (if (and (car indent-stack)
- (>= (car indent-stack) 0))
- nil
- ;; Yes.
- ;; Compute the standard indent for this level.
- (let (val)
- (if (= (char-after (car contain-stack)) ?{)
- (save-excursion
- (goto-char (car contain-stack))
- (setq val (calculate-c-indent-after-brace)))
- (setq val (calculate-c-indent
- (if (car indent-stack)
- (- (car indent-stack))
- opoint))))
- ;; t means we are in a block comment and should
- ;; calculate accordingly.
- (if (eq val t)
- (setq val (calculate-c-indent-within-comment)))
- (setcar indent-stack val)))
- ;; Adjust indent of this individual line
- ;; based on its predecessor.
- ;; Handle continuation lines, if, else, while, and so on.
- (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 this-point (point))
- (setq at-else (and (looking-at "else\\b")
- (not (looking-at "else\\s_"))))
- (setq at-brace (= (following-char) ?{))
- (setq at-while (and (looking-at "while\\b")
- (not (looking-at "while\\s_"))))
- (if (= (following-char) ?})
- (setq this-indent (car indent-stack))
- (c-backward-to-noncomment opoint)
- (if (not (memq (preceding-char) '(0 ?\, ?\; ?} ?: ?{)))
- ;; 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.
- (cond (at-else (progn (c-backward-to-start-of-if opoint)
- (setq this-indent
- (current-indentation))))
- ((and at-while (c-backward-to-start-of-do opoint))
- (setq this-indent (current-indentation)))
- ((eq (preceding-char) ?\,)
- (goto-char this-point)
- (setq this-indent (calculate-c-indent)))
- (t (setq this-indent (car indent-stack))))))))
- ;; Adjust line indentation according to its contents
- (if (or (looking-at c-switch-label-regexp)
- (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) ?{)
- ;; Don't move an open-brace in column 0.
- ;; This is good when constructs such as
- ;; `extern "C" {' surround a function definition
- ;; that should be indented as usual.
- ;; It is also good for nested functions.
- ;; It is bad when an open-brace is indented at column 0
- ;; and you want to fix that, but we can't win 'em all.
- (if (zerop (current-column))
- (setq this-indent 0)
- (setq this-indent (+ this-indent c-brace-offset))))
- ;; Don't leave indentation in empty lines.
- (if (eolp) (setq this-indent 0))
- ;; 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)
- (save-excursion
- (let ((beg (point)))
- (and (re-search-forward
- comment-start-skip
- (save-excursion (end-of-line) (point)) t)
- ;; Make sure the comment starter we found
- ;; is not actually in a string or quoted.
- (let ((new-state
- (parse-partial-sexp beg (point)
- nil nil state)))
- (and (not (nth 3 new-state)) (not (nth 5 new-state))))
- (indent-for-comment)))))))))))
-
-;; Look at all comment-start strings in the current line after point.
-;; Return t if one of them starts a real comment.
-;; This is not used yet, because indent-for-comment
-;; isn't smart enough to handle the cases this can find.
-(defun indent-c-find-real-comment ()
- (let (win)
- (while (and (not win)
- (re-search-forward comment-start-skip
- (save-excursion (end-of-line) (point))
- t))
- ;; Make sure the comment start is not quoted.
- (let ((state-1
- (parse-partial-sexp
- (save-excursion (beginning-of-line) (point))
- (point) nil nil state)))
- (setq win (and (null (nth 3 state-1)) (null (nth 5 state-1))))))
- win))
-
-;; Indent every line whose first char is between START and END inclusive.
-(defun c-indent-region (start end)
- (save-excursion
- (goto-char start)
- ;; Advance to first nonblank line.
- (skip-chars-forward " \t\n")
- (beginning-of-line)
- (let ((endmark (copy-marker end))
- (c-tab-always-indent t))
- (while (and (bolp) (not (eobp)) (< (point) endmark))
- ;; Indent one line as with TAB.
- (let ((shift-amt (c-indent-line))
- nextline sexpbeg sexpend)
- (if (save-excursion (beginning-of-line) (looking-at "[ \t]*#"))
- (forward-line 1)
- (save-excursion
- ;; Find beginning of following line.
- (save-excursion
- (forward-line 1) (setq nextline (point)))
- ;; Find first beginning-of-sexp for sexp extending past this line.
- (beginning-of-line)
- (while (< (point) nextline)
- (condition-case nil
- (progn
- (forward-sexp 1)
- (setq sexpend (point-marker)))
- (error (setq sexpend nil)
- (goto-char nextline)))
- (skip-chars-forward " \t\n"))
- (if sexpend
- (progn
- ;; Make sure the sexp we found really starts on the
- ;; current line and extends past it.
- (goto-char sexpend)
- (backward-sexp 1)
- (setq sexpbeg (point)))))
- ;; If that sexp ends within the region,
- ;; indent it all at once, fast.
- (if (and sexpend (> sexpend nextline) (<= sexpend endmark)
- (< sexpbeg nextline))
- (progn
- (indent-c-exp)
- (goto-char sexpend)))
- ;; Move to following line and try again.
- (and sexpend (set-marker sexpend nil))
- (forward-line 1))))
- (set-marker endmark nil))))
-
-(defun set-c-style (style &optional global)
- "Set C-mode variables to use one of several different indentation styles.
-The arguments are a string representing the desired style
-and a flag which, if non-nil, means to set the style globally.
-\(Interactively, the flag comes from the prefix argument.)
-Available styles are GNU, K&R, BSD and Whitesmith."
- (interactive (list (let ((completion-ignore-case t))
- (completing-read "Use which C indentation style? "
- c-style-alist nil t))
- current-prefix-arg))
- (let ((vars (cdr (assoc style c-style-alist))))
- (or vars
- (error "Invalid C indentation style `%s'" style))
- (while vars
- (or global
- (make-local-variable (car (car vars))))
- (set (car (car vars)) (cdr (car vars)))
- (setq vars (cdr vars)))))
-
-;;; This page handles insertion and removal of backslashes for C macros.
-
-(defvar c-backslash-column 48
- "*Minimum column for end-of-line backslashes of macro definitions.")
-
-(defun c-backslash-region (from to delete-flag)
- "Insert, align, or delete end-of-line backslashes on the lines in the region.
-With no argument, inserts backslashes and aligns existing backslashes.
-With an argument, deletes the backslashes.
-
-This function does not modify the last line of the region if the region ends
-right at the start of the following line; it does not modify blank lines
-at the start of the region. So you can put the region around an entire macro
-definition and conveniently use this command."
- (interactive "r\nP")
- (save-excursion
- (goto-char from)
- (let ((column c-backslash-column)
- (endmark (make-marker)))
- (move-marker endmark to)
- ;; Compute the smallest column number past the ends of all the lines.
- (if (not delete-flag)
- (while (< (point) to)
- (end-of-line)
- (if (= (preceding-char) ?\\)
- (progn (forward-char -1)
- (skip-chars-backward " \t")))
- (setq column (max column (1+ (current-column))))
- (forward-line 1)))
- ;; Adjust upward to a tab column, if that doesn't push past the margin.
- (if (> (% column tab-width) 0)
- (let ((adjusted (* (/ (+ column tab-width -1) tab-width) tab-width)))
- (if (< adjusted (window-width))
- (setq column adjusted))))
- ;; Don't modify blank lines at start of region.
- (goto-char from)
- (while (and (< (point) endmark) (eolp))
- (forward-line 1))
- ;; Add or remove backslashes on all the lines.
- (while (and (< (point) endmark)
- ;; Don't backslashify the last line
- ;; if the region ends right at the start of the next line.
- (save-excursion
- (forward-line 1)
- (< (point) endmark)))
- (if (not delete-flag)
- (c-append-backslash column)
- (c-delete-backslash))
- (forward-line 1))
- (move-marker endmark nil))))
-
-(defun c-append-backslash (column)
- (end-of-line)
- ;; Note that "\\\\" is needed to get one backslash.
- (if (= (preceding-char) ?\\)
- (progn (forward-char -1)
- (delete-horizontal-space)
- (indent-to column))
- (indent-to column)
- (insert "\\")))
-
-(defun c-delete-backslash ()
- (end-of-line)
- (or (bolp)
- (progn
- (forward-char -1)
- (if (looking-at "\\\\")
- (delete-region (1+ (point))
- (progn (skip-chars-backward " \t") (point)))))))
-
-(defun c-up-conditional (count)
- "Move back to the containing preprocessor conditional, leaving mark behind.
-A prefix argument acts as a repeat count. With a negative argument,
-move forward to the end of the containing preprocessor conditional.
-When going backwards, `#elif' is treated like `#else' followed by `#if'.
-When going forwards, `#elif' is ignored."
- (interactive "p")
- (c-forward-conditional (- count) t))
-
-(defun c-backward-conditional (count &optional up-flag)
- "Move back across a preprocessor conditional, leaving mark behind.
-A prefix argument acts as a repeat count. With a negative argument,
-move forward across a preprocessor conditional."
- (interactive "p")
- (c-forward-conditional (- count) up-flag))
-
-(defun c-forward-conditional (count &optional up-flag)
- "Move forward across a preprocessor conditional, leaving mark behind.
-A prefix argument acts as a repeat count. With a negative argument,
-move backward across a preprocessor conditional."
- (interactive "p")
- (let* ((forward (> count 0))
- (increment (if forward -1 1))
- (search-function (if forward 're-search-forward 're-search-backward))
- (opoint (point))
- (new))
- (save-excursion
- (while (/= count 0)
- (let ((depth (if up-flag 0 -1)) found)
- (save-excursion
- ;; Find the "next" significant line in the proper direction.
- (while (and (not found)
- ;; Rather than searching for a # sign that comes
- ;; at the beginning of a line aside from whitespace,
- ;; search first for a string starting with # sign.
- ;; Then verify what precedes it.
- ;; This is faster on account of the fastmap feature of
- ;; the regexp matcher.
- (funcall search-function
- "#[ \t]*\\(if\\|elif\\|endif\\)"
- nil t))
- (beginning-of-line)
- ;; Now verify it is really a preproc line.
- (if (looking-at "^[ \t]*#[ \t]*\\(if\\|elif\\|endif\\)")
- (let ((prev depth))
- ;; Update depth according to what we found.
- (beginning-of-line)
- (cond ((looking-at "[ \t]*#[ \t]*endif")
- (setq depth (+ depth increment)))
- ((looking-at "[ \t]*#[ \t]*elif")
- (if (and forward (= depth 0))
- (setq found (point))))
- (t (setq depth (- depth increment))))
- ;; If we are trying to move across, and we find
- ;; an end before we find a beginning, get an error.
- (if (and (< prev 0) (< depth prev))
- (error (if forward
- "No following conditional at this level"
- "No previous conditional at this level")))
- ;; When searching forward, start from next line
- ;; so that we don't find the same line again.
- (if forward (forward-line 1))
- ;; If this line exits a level of conditional, exit inner loop.
- (if (< depth 0)
- (setq found (point))))
- ;; If the line is not really a conditional, skip past it.
- (if forward (end-of-line)))))
- (or found
- (error "No containing preprocessor conditional"))
- (goto-char (setq new found)))
- (setq count (+ count increment))))
- (push-mark)
- (goto-char new)))
-
-(provide 'c-mode)
-
-;;; c-mode.el ends here
diff --git a/lisp/progmodes/cmacexp.el b/lisp/progmodes/cmacexp.el
deleted file mode 100644
index f030ade3f67..00000000000
--- a/lisp/progmodes/cmacexp.el
+++ /dev/null
@@ -1,371 +0,0 @@
-;;; cmacexp.el --- expand C macros in a region
-
-;; Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
-
-;; Author: Francesco Potorti` <pot@cnuce.cnr.it>
-;; Version: $Id: cmacexp.el,v 1.25 1996/05/21 15:42:13 kwzh Exp rms $
-;; Adapted-By: ESR
-;; Keywords: c
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; USAGE =============================================================
-
-;; In C mode C-C C-e is bound to c-macro-expand. The result of the
-;; expansion is put in a separate buffer. A user option allows the
-;; window displaying the buffer to be optimally sized.
-;;
-;; When called with a C-u prefix, c-macro-expand replaces the selected
-;; region with the expansion. Both the preprocessor name and the
-;; initial flag can be set by the user. If c-macro-prompt-flag is set
-;; to a non-nil value the user is offered to change the options to the
-;; preprocessor each time c-macro-expand is invoked. Preprocessor
-;; arguments default to the last ones entered. If c-macro-prompt-flag
-;; is nil, one must use M-x set-variable to set a different value for
-;; c-macro-cppflags.
-
-;; A c-macro-expansion function is provided for non-interactive use.
-
-;; INSTALLATION ======================================================
-
-;; Put the following in your ~/.emacs file.
-
-;; If you want the *Macroexpansion* window to be not higher than
-;; necessary:
-;;(setq c-macro-shrink-window-flag t)
-;;
-;; If you use a preprocessor other than /lib/cpp (be careful to set a
-;; -C option or equivalent in order to make the preprocessor not to
-;; strip the comments):
-;;(setq c-macro-preprocessor "gpp -C")
-;;
-;; If you often use a particular set of flags:
-;;(setq c-macro-cppflags "-I /usr/include/local -DDEBUG"
-;;
-;; If you want the "Preprocessor arguments: " prompt:
-;;(setq c-macro-prompt-flag t)
-
-;; BUG REPORTS =======================================================
-
-;; Please report bugs, suggestions, complaints and so on to
-;; pot@cnuce.cnr.it (Francesco Potorti`).
-
-;; IMPROVEMENTS OVER emacs 18.xx cmacexp.el ==========================
-
-;; - A lot of user and programmer visible changes. See above.
-;; - #line directives are inserted, so __LINE__ and __FILE__ are
-;; correctly expanded. Works even with START inside a string, a
-;; comment or a region #ifdef'd away by cpp. cpp is invoked with -C,
-;; making comments visible in the expansion.
-;; - All work is done in core memory, no need for temporary files.
-
-;; ACKNOWLEDGEMENTS ==================================================
-
-;; A lot of thanks to Don Maszle who did a great work of testing, bug
-;; reporting and suggestion of new features. This work has been
-;; partially inspired by Don Maszle and Jonathan Segal's.
-
-;; BUGS ==============================================================
-
-;; If the start point of the region is inside a macro definition the
-;; macro expansion is often inaccurate.
-
-
-(require 'cc-mode)
-
-(provide 'cmacexp)
-
-(defvar c-macro-shrink-window-flag nil
- "*Non-nil means shrink the *Macroexpansion* window to fit its contents.")
-
-(defvar c-macro-prompt-flag nil
- "*Non-nil makes `c-macro-expand' prompt for preprocessor arguments.")
-
-(defvar c-macro-preprocessor
- ;; Cannot rely on standard directory on MS-DOS to find CPP.
- (cond ((eq system-type 'ms-dos) "cpp -C")
- ;; Solaris has it in an unusual place.
- ((and (string-match "^[^-]*-[^-]*-\\(solaris\\|sunos5\\)"
- system-configuration)
- (file-exists-p "/opt/SUNWspro/SC3.0.1/bin/acomp"))
- "/opt/SUNWspro/SC3.0.1/bin/acomp -C -E")
- (t "/lib/cpp -C"))
- "The preprocessor used by the cmacexp package.
-
-If you change this, be sure to preserve the `-C' (don't strip comments)
-option, or to set an equivalent one.")
-
-(defvar c-macro-cppflags ""
- "*Preprocessor flags used by `c-macro-expand'.")
-
-(defconst c-macro-buffer-name "*Macroexpansion*")
-
-(defun c-macro-expand (start end subst)
- "Expand C macros in the region, using the C preprocessor.
-Normally display output in temp buffer, but
-prefix arg means replace the region with it.
-
-`c-macro-preprocessor' specifies the preprocessor to use.
-Prompt for arguments to the preprocessor \(e.g. `-DDEBUG -I ./include')
-if the user option `c-macro-prompt-flag' is non-nil.
-
-Noninteractive args are START, END, SUBST.
-For use inside Lisp programs, see also `c-macro-expansion'."
-
- (interactive "r\nP")
- (let ((inbuf (current-buffer))
- (displaybuf (if subst
- (get-buffer c-macro-buffer-name)
- (get-buffer-create c-macro-buffer-name)))
- (expansion ""))
- ;; Build the command string.
- (if c-macro-prompt-flag
- (setq c-macro-cppflags
- (read-string "Preprocessor arguments: "
- c-macro-cppflags)))
- ;; Decide where to display output.
- (if (and subst
- (and buffer-read-only (not inhibit-read-only))
- (not (eq inbuf displaybuf)))
- (progn
- (message
- "Buffer is read only: displaying expansion in alternate window")
- (sit-for 2)
- (setq subst nil)
- (or displaybuf
- (setq displaybuf (get-buffer-create c-macro-buffer-name)))))
- ;; Expand the macro and output it.
- (setq expansion (c-macro-expansion start end
- (concat c-macro-preprocessor " "
- c-macro-cppflags) t))
- (if subst
- (let ((exchange (= (point) start)))
- (delete-region start end)
- (insert expansion)
- (if exchange
- (exchange-point-and-mark)))
- (set-buffer displaybuf)
- (setq buffer-read-only nil)
- (buffer-disable-undo displaybuf)
- (erase-buffer)
- (insert expansion)
- (set-buffer-modified-p nil)
- (if (string= "" expansion)
- (message "Null expansion")
- (c-macro-display-buffer))
- (setq buffer-read-only t)
- (setq buffer-auto-save-file-name nil)
- (bury-buffer displaybuf))))
-
-
-;; Display the current buffer in a window which is either just large
-;; enough to contain the entire buffer, or half the size of the
-;; screen, whichever is smaller. Do not select the new
-;; window.
-;;
-;; Several factors influence window resizing so that the window is
-;; sized optimally if it is created anew, and so that it is messed
-;; with minimally if it has been created by the user. If the window
-;; chosen for display exists already but contains something else, the
-;; window is not re-sized. If the window already contains the current
-;; buffer, it is never shrunk, but possibly expanded. Finally, if the
-;; variable c-macro-shrink-window-flag is nil the window size is *never*
-;; changed.
-(defun c-macro-display-buffer ()
- (goto-char (point-min))
- (c-mode)
- (let ((oldwinheight (window-height))
- (alreadythere ;the window was already there
- (get-buffer-window (current-buffer)))
- (popped nil)) ;the window popped changing the layout
- (or alreadythere
- (progn
- (display-buffer (current-buffer) t)
- (setq popped (/= oldwinheight (window-height)))))
- (if (and c-macro-shrink-window-flag ;user wants fancy shrinking :\)
- (or alreadythere popped))
- ;; Enlarge up to half screen, or shrink properly.
- (let ((oldwin (selected-window))
- (minheight 0)
- (maxheight 0))
- (save-excursion
- (select-window (get-buffer-window (current-buffer)))
- (setq minheight (if alreadythere
- (window-height)
- window-min-height))
- (setq maxheight (/ (frame-height) 2))
- (enlarge-window (- (min maxheight
- (max minheight
- (+ 2 (vertical-motion (point-max)))))
- (window-height)))
- (goto-char (point-min))
- (select-window oldwin))))))
-
-
-(defun c-macro-expansion (start end cppcommand &optional display)
- "Run a preprocessor on region and return the output as a string.
-Expand the region between START and END in the current buffer using
-the shell command CPPCOMMAND (e.g. \"/lib/cpp -C -DDEBUG\").
-Be sure to use a -C (don't strip comments) or equivalent option.
-Optional arg DISPLAY non-nil means show messages in the echo area."
-
-;; Copy the current buffer's contents to a temporary hidden buffer.
-;; Delete from END to end of buffer. Insert a preprocessor #line
-;; directive at START and after each #endif following START that are
-;; not inside a comment or a string. Put all the strings thus
-;; inserted (without the "line" substring) in a list named linelist.
-;; If START is inside a comment, prepend "*/" and append "/*" to the
-;; #line directive. If inside a string, prepend and append "\"".
-;; Preprocess the buffer contents, then look for all the lines stored
-;; in linelist starting from end of buffer. The last line so found is
-;; where START was, so return the substring from point to end of
-;; buffer.
- (let ((inbuf (current-buffer))
- (outbuf (get-buffer-create " *C Macro Expansion*"))
- (filename (if (and buffer-file-name
- (string-match (regexp-quote default-directory)
- buffer-file-name))
- (substring buffer-file-name (match-end 0))
- (buffer-name)))
- (mymsg (format "Invoking %s%s%s on region..."
- c-macro-preprocessor
- (if (string= "" c-macro-cppflags) "" " ")
- c-macro-cppflags))
- (uniquestring "??? !!! ??? start of c-macro expansion ??? !!! ???")
- (startlinenum 0)
- (linenum 0)
- (startstat ())
- (startmarker "")
- (exit-status 0)
- (tempname (make-temp-name (concat
- (or (getenv "TMPDIR") (getenv "TEMP")
- (getenv "TMP") "/tmp")
- "/"))))
- (unwind-protect
- (save-excursion
- (save-restriction
- (widen)
- (let ((in-syntax-table (syntax-table)))
- (set-buffer outbuf)
- (setq buffer-read-only nil)
- (erase-buffer)
- (set-syntax-table in-syntax-table))
- (insert-buffer-substring inbuf 1 end))
-
- ;; We have copied inbuf to outbuf. Point is at end of
- ;; outbuf. Inset a newline at the end, so cpp can correctly
- ;; parse a token ending at END.
- (insert "\n")
-
- ;; Save sexp status and line number at START.
- (setq startstat (parse-partial-sexp 1 start))
- (setq startlinenum (+ (count-lines 1 (point))
- (if (bolp) 1 0)))
-
- ;; Now we insert the #line directives after all #endif or
- ;; #else following START going backward, so the lines we
- ;; insert don't change the line numbers.
- ;(switch-to-buffer outbuf) (debug) ;debugging instructions
- (goto-char (point-max))
- (while (re-search-backward "\n#\\(endif\\|else\\)\\>" start 'move)
- (if (equal (nthcdr 3 (parse-partial-sexp start (point)
- nil nil startstat))
- '(nil nil nil 0 nil)) ;neither in string nor in
- ;comment nor after quote
- (progn
- (goto-char (match-end 0))
- (setq linenum (+ startlinenum
- (count-lines start (point))))
- (insert (format "\n#line %d \"%s\"\n" linenum filename))
- (goto-char (match-beginning 0)))))
-
- ;; Now we are at START. Insert the first #line directive.
- ;; This must work even inside a string or comment, or after a
- ;; quote.
- (let* ((startinstring (nth 3 startstat))
- (startincomment (nth 4 startstat))
- (startafterquote (nth 5 startstat))
- (startinbcomment (nth 7 startstat)))
- (insert (if startafterquote " " "")
- (cond (startinstring
- (char-to-string startinstring))
- (startincomment "*/")
- (""))
- (setq startmarker
- (concat "\n" uniquestring
- (cond (startinstring
- (char-to-string startinstring))
- (startincomment "/*")
- (startinbcomment "//"))
- (if startafterquote "\\")))
- (format "\n#line %d \"%s\"\n" startlinenum filename)))
-
- ;; Call the preprocessor.
- (if display (message mymsg))
- (setq exit-status
- (call-process-region 1 (point-max)
- shell-file-name
- t (list t tempname) nil "-c"
- cppcommand))
- (if display (message (concat mymsg "done")))
- (if (= (buffer-size) 0)
- ;; Empty output is normal after a fatal error.
- (insert "\nPreprocessor produced no output\n")
- ;; Find and delete the mark of the start of the expansion.
- ;; Look for `# nn "file.c"' lines and delete them.
- (goto-char (point-min))
- (search-forward startmarker)
- (delete-region 1 (point)))
- (while (re-search-forward (concat "^# [0-9]+ \""
- (regexp-quote filename)
- "\"") nil t)
- (beginning-of-line)
- (let ((beg (point)))
- (forward-line 1)
- (delete-region beg (point))))
-
- ;; If CPP got errors, show them at the beginning.
- ;; MS-DOS shells don't return the exit code of their children.
- ;; Look at the size of the error message file instead, but
- ;; don't punish those MS-DOS users who have a shell that does
- ;; return an error code.
- (or (and (or (not (boundp 'msdos-shells))
- (not (member (file-name-nondirectory shell-file-name)
- msdos-shells)))
- (eq exit-status 0))
- (zerop (nth 7 (file-attributes (expand-file-name tempname))))
- (progn
- (goto-char (point-min))
- ;; Put the messages inside a comment, so they won't get in
- ;; the way of font-lock, highlighting etc.
- (insert
- (format "/* Preprocessor terminated with status %s\n\n Messages from `%s\':\n\n"
- exit-status cppcommand))
- (goto-char (+ (point)
- (nth 1 (insert-file-contents tempname))))
- (insert "\n\n*/\n")))
- (delete-file tempname)
-
- ;; Compute the return value, keeping in account the space
- ;; inserted at the end of the buffer.
- (buffer-substring 1 (max 1 (- (point-max) 1))))
-
- ;; Cleanup.
- (kill-buffer outbuf))))
-
-;;; cmacexp.el ends here
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
deleted file mode 100644
index 4c9b9c56e76..00000000000
--- a/lisp/progmodes/compile.el
+++ /dev/null
@@ -1,1583 +0,0 @@
-;;; compile.el --- run compiler as inferior of Emacs, parse error messages.
-
-;; Copyright (C) 1985, 86, 87, 93, 94, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Roland McGrath <roland@prep.ai.mit.edu>
-;; Maintainer: FSF
-;; Keywords: tools, processes
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides the compile and grep facilities documented in
-;; the Emacs user's manual.
-
-;;; Code:
-
-;;;###autoload
-(defvar compilation-mode-hook nil
- "*List of hook functions run by `compilation-mode' (see `run-hooks').")
-
-;;;###autoload
-(defvar compilation-window-height nil
- "*Number of lines in a compilation window. If nil, use Emacs default.")
-
-(defvar compile-auto-highlight nil
- "*Specify how many compiler errors to highlight (and parse) initially.
-\(Highlighting applies to ean error message when the mouse is over it.)
-If this is a number N, all compiler error messages in the first N lines
-are highlighted and parsed as soon as they arrive in Emacs.
-If t, highlight and parse the whole compilation output as soon as it arrives.
-If nil, don't highlight or parse any of the buffer until you try to
-move to the error messages.
-
-Those messages which are not parsed and highlighted initially
-will be parsed and highlighted as soon as you try to move to them.")
-
-(defvar compilation-error-list nil
- "List of error message descriptors for visiting erring functions.
-Each error descriptor is a cons (or nil). Its car is a marker pointing to
-an error message. If its cdr is a marker, it points to the text of the
-line the message is about. If its cdr is a cons, it is a list
-\(\(DIRECTORY . FILE\) LINE [COLUMN]\). Or its cdr may be nil if that
-error 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.
-
-Some other commands (like `diff') use this list to control the error
-message tracking facilities; if you change its structure, you should make
-sure you also change those packages. Perhaps it is better not to change
-it at all.")
-
-(defvar compilation-old-error-list nil
- "Value of `compilation-error-list' after errors were parsed.")
-
-(defvar compilation-parse-errors-function 'compilation-parse-errors
- "Function to call to parse error messages from a compilation.
-It takes args LIMIT-SEARCH and FIND-AT-LEAST.
-If LIMIT-SEARCH is non-nil, don't bother parsing past that location.
-If FIND-AT-LEAST is non-nil, don't bother parsing after finding that
-many new errors.
-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.")
-
-;;;###autoload
-(defvar compilation-buffer-name-function nil
- "Function to compute the name of a compilation buffer.
-The function receives one argument, the name of the major mode of the
-compilation buffer. It should return a string.
-nil means compute the name with `(concat \"*\" (downcase major-mode) \"*\")'.")
-
-;;;###autoload
-(defvar compilation-finish-function nil
- "*Function to call when a compilation process finishes.
-It is called with two arguments: the compilation buffer, and a string
-describing how the process finished.")
-
-;;;###autoload
-(defvar compilation-finish-functions nil
- "*Functions to call when a compilation process finishes.
-Each function is called with two arguments: the compilation buffer,
-and a string describing how the process finished.")
-
-(defvar compilation-last-buffer nil
- "The most recent compilation buffer.
-A buffer becomes most recent when its compilation is started
-or when it is used with \\[next-error] or \\[compile-goto-error].")
-
-(defvar compilation-in-progress nil
- "List of compilation processes now running.")
-(or (assq 'compilation-in-progress minor-mode-alist)
- (setq minor-mode-alist (cons '(compilation-in-progress " Compiling")
- minor-mode-alist)))
-
-(defvar compilation-parsing-end nil
- "Position of end of buffer when last error messages were parsed.")
-
-(defvar compilation-error-message "No more errors"
- "Message to print when no more matches are found.")
-
-(defvar compilation-num-errors-found)
-
-(defvar compilation-error-regexp-alist
- '(
- ;; NOTE! See also grep-regexp-alist, below.
-
- ;; 4.3BSD grep, cc, lint pass 1:
- ;; /usr/src/foo/foo.c(8): warning: w may be used before set
- ;; or GNU utilities:
- ;; foo.c:8: error message
- ;; or HP-UX 7.0 fc:
- ;; foo.f :16 some horrible error message
- ;; or GNU utilities with column (GNAT 1.82):
- ;; foo.adb:2:1: Unit name does not match file name
- ;;
- ;; We'll insist that the number be followed by a colon or closing
- ;; paren, because otherwise this matches just about anything
- ;; containing a number with spaces around it.
- ("\n\
-\\([a-zA-Z]?:?[^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\)\\([) \t]\\|\
-:\\([^0-9\n]\\|\\([0-9]+:\\)\\)\\)" 1 2 5)
-
- ;; Microsoft C/C++:
- ;; keyboard.c(537) : warning C4005: 'min' : macro redefinition
- ;; d:\tmp\test.c(23) : error C2143: syntax error : missing ';' before 'if'
- ("\n\\(\\([a-zA-Z]:\\)?[^:( \t\n-]+\\)[:(][ \t]*\\([0-9]+\\)[:) \t]" 1 3)
-
- ;; Borland C++:
- ;; Error ping.c 15: Unable to open include file 'sys/types.h'
- ;; Warning ping.c 68: Call to function 'func' with no prototype
- ("\n\\(Error\\|Warning\\) \\([a-zA-Z]?:?[^:( \t\n]+\\)\
- \\([0-9]+\\)\\([) \t]\\|:[^0-9\n]\\)" 2 3)
-
- ;; 4.3BSD lint pass 2
- ;; strcmp: variable # of args. llib-lc(359) :: /usr/src/foo/foo.c(8)
- ("[ \t:]\\([a-zA-Z]?:?[^:( \t\n]+\\)[:(](+[ \t]*\\([0-9]+\\))[:) \t]*$"
- 1 2)
-
- ;; 4.3BSD lint pass 3
- ;; bloofle defined( /users/wolfgang/foo.c(4) ), but never used
- ;; This used to be
- ;; ("[ \t(]+\\([a-zA-Z]?:?[^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]+" 1 2)
- ;; which is regexp Impressionism - it matches almost anything!
- ("([ \t]*\\([a-zA-Z]?:?[^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\))" 1 2)
-
- ;; MIPS lint pass<n>; looks good for SunPro lint also
- ;; TrimMask (255) in solomon.c may be indistinguishable from TrimMasks (93) in solomon.c due to truncation
- ("[^ ]+ (\\([0-9]+\\)) in \\([^ ]+\\)" 2 1)
- ;; name defined but never used: LinInt in cmap_calc.c(199)
- ("in \\([^(]+\\)(\\([0-9]+\\))$" 1 2)
-
- ;; Ultrix 3.0 f77:
- ;; fort: Severe: addstf.f, line 82: Missing operator or delimiter symbol
- ;; Some SGI cc version:
- ;; cfe: Warning 835: foo.c, line 2: something
- ("\n\\(cfe\\|fort\\): [^:\n]*: \\([^ \n]*\\), line \\([0-9]+\\):" 2 3)
- ;; Error on line 3 of t.f: Execution error unclassifiable statement
- ;; Unknown who does this:
- ;; Line 45 of "foo.c": bloofle undefined
- ;; Absoft FORTRAN 77 Compiler 3.1.3
- ;; error on line 19 of fplot.f: spelling error?
- ;; warning on line 17 of fplot.f: data type is undefined for variable d
- ("\\(\n\\|on \\)[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\
-of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2)
-
- ;; Apollo cc, 4.3BSD fc:
- ;; "foo.f", line 3: Error: syntax error near end of statement
- ;; IBM RS6000:
- ;; "vvouch.c", line 19.5: 1506-046 (S) Syntax error.
- ;; Unknown compiler:
- ;; File "foobar.ml", lines 5-8, characters 20-155: blah blah
- ;; Microtec mcc68k:
- ;; "foo.c", line 32 pos 1; (E) syntax error; unexpected symbol: "lossage"
- ;; GNAT (as of July 94):
- ;; "foo.adb", line 2(11): warning: file name does not match ...
- ;; IBM AIX xlc compiler:
- ;; "src/swapping.c", line 30.34: 1506-342 (W) "/*" detected in comment.
- ("\"\\([^,\" \n\t]+\\)\", lines? \
-\\([0-9]+\\)\\([\(.]\\([0-9]+\\)\)?\\)?[:., (-]" 1 2 4)
-
- ;; MIPS RISC CC - the one distributed with Ultrix:
- ;; ccom: Error: foo.c, line 2: syntax error
- ;; DEC AXP OSF/1 cc
- ;; /usr/lib/cmplrs/cc/cfe: Error: foo.c: 1: blah blah
- ("rror: \\([^,\" \n\t]+\\)[,:] \\(line \\)?\\([0-9]+\\):" 1 3)
-
- ;; IBM AIX PS/2 C version 1.1:
- ;; ****** Error number 140 in line 8 of file errors.c ******
- ("in line \\([0-9]+\\) of file \\([^ \n]+[^. \n]\\)\\.? " 2 1)
- ;; IBM AIX lint is too painful to do right this way. File name
- ;; prefixes entire sections rather than being on each line.
-
- ;; Lucid Compiler, lcc 3.x
- ;; E, file.cc(35,52) Illegal operation on pointers
- ("\n[EW], \\([^(\n]*\\)(\\([0-9]+\\),[ \t]*\\([0-9]+\\)" 1 2 3)
-
- ;; GNU messages with program name and optional column number.
- ("\n[a-zA-Z]?:?[^0-9 \n\t:]+:[ \t]*\\([^ \n\t:]+\\):\
-\\([0-9]+\\):\\(\\([0-9]+\\)[: \t]\\)?" 1 2 4)
-
- ;; Cray C compiler error messages
- ("\n\\(cc\\| cft\\)-[0-9]+ c\\(c\\|f77\\): ERROR \\([^,\n]+, \\)* File = \\([^,\n]+\\), Line = \\([0-9]+\\)" 4 5)
-
- ;; IBM C/C++ Tools 2.01:
- ;; foo.c(2:0) : informational EDC0804: Function foo is not referenced.
- ;; foo.c(3:8) : warning EDC0833: Implicit return statement encountered.
- ;; foo.c(5:5) : error EDC0350: Syntax error.
- ("\n\\([^( \n\t]+\\)(\\([0-9]+\\):\\([0-9]+\\)) : " 1 2 3)
-
- ;; Sun ada (VADS, Solaris):
- ;; /home3/xdhar/rcds_rc/main.a, line 361, char 6:syntax error: "," inserted
- ("\n\\([^, ]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., \(-]" 1 2 3)
- )
- "Alist that specifies how to match errors in compiler output.
-Each elt has the form (REGEXP FILE-IDX LINE-IDX [COLUMN-IDX FILE-FORMAT...])
-If REGEXP matches, the FILE-IDX'th subexpression gives the file name, and
-the LINE-IDX'th subexpression gives the line number. If COLUMN-IDX is
-given, the COLUMN-IDX'th subexpression gives the column number on that line.
-If any FILE-FORMAT is given, each is a format string to produce a file name to
-try; %s in the string is replaced by the text matching the FILE-IDX'th
-subexpression.")
-
-(defvar compilation-read-command t
- "If not nil, M-x compile reads the compilation command to use.
-Otherwise, M-x compile just uses the value of `compile-command'.")
-
-(defvar compilation-ask-about-save t
- "If not nil, M-x compile asks which buffers to save before compiling.
-Otherwise, it saves all modified buffers without asking.")
-
-(defvar grep-regexp-alist
- '(("^\\([a-zA-Z]?:?[^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 2))
- "Regexp used to match grep hits. See `compilation-error-regexp-alist'.")
-
-(defvar grep-command "grep -n "
- "Last grep command used in \\[grep]; default for next grep.")
-
-;;;###autoload
-(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.")
-
-(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-enter-directory-regexp
- ": Entering directory `\\(.*\\)'$"
- "Regular expression matching lines that indicate a new current directory.
-This must contain one \\(, \\) pair around the directory name.
-
-The default value matches lines printed by the `-w' option of GNU Make.")
-
-(defvar compilation-leave-directory-regexp
- ": Leaving directory `\\(.*\\)'$"
- "Regular expression matching lines that indicate restoring current directory.
-This may contain one \\(, \\) pair around the name of the directory
-being moved from. If it does not, the last directory entered \(by a
-line matching `compilation-enter-directory-regexp'\) is assumed.
-
-The default value matches lines printed by the `-w' option of GNU Make.")
-
-(defvar compilation-directory-stack nil
- "Stack of previous directories for `compilation-leave-directory-regexp'.
-The head element is the directory the compilation was started in.")
-
-(defvar compilation-exit-message-function nil "\
-If non-nil, called when a compilation process dies to return a status message.
-This should be a function of three arguments: process status, exit status,
-and exit message; it returns a cons (MESSAGE . MODELINE) of the strings to
-write into the compilation buffer, and to put in its mode line.")
-
-;; History of compile commands.
-(defvar compile-history nil)
-;; History of grep commands.
-(defvar grep-history nil)
-
-(defvar compilation-mode-font-lock-keywords
- ;; This regexp needs a bit of rewriting. What is the third grouping for?
- '(("^\\([a-zA-Z]?:?[^ \n:]*:\\([0-9]+:\\)+\\)\\(.*\\)$"
- 1 font-lock-function-name-face))
-;;; ("^\\([^\n:]*:\\([0-9]+:\\)+\\)\\(.*\\)$" 0 font-lock-keyword-face keep)
- "Additional expressions to highlight in Compilation mode.")
-
-;;;###autoload
-(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.
-
-Interactively, prompts for the command if `compilation-read-command' is
-non-nil; otherwise uses `compile-command'. With prefix arg, always prompts.
-
-To run more than one compilation at once, start one and rename the
-\`*compilation*' buffer to some other name with \\[rename-buffer].
-Then start the next one.
-
-The name used for the buffer is actually whatever is returned by
-the function in `compilation-buffer-name-function', so you can set that
-to a function that generates a unique name."
- (interactive
- (if (or compilation-read-command current-prefix-arg)
- (list (read-from-minibuffer "Compile command: "
- compile-command nil nil
- '(compile-history . 1)))
- (list compile-command)))
- (setq compile-command command)
- (save-some-buffers (not compilation-ask-about-save) nil)
- (compile-internal compile-command "No more errors"))
-
-;;; run compile with the default command line
-(defun recompile ()
- "Re-compile the program including the current buffer."
- (interactive)
- (save-some-buffers (not compilation-ask-about-save) nil)
- (compile-internal compile-command "No more errors"))
-
-;; The system null device. (Should reference NULL_DEVICE from C.)
-(defvar grep-null-device "/dev/null" "The system null device.")
-
-;;;###autoload
-(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.
-
-This command uses a special history list for its arguments, so you can
-easily repeat a grep command."
- (interactive
- (list (read-from-minibuffer "Run grep (like this): "
- grep-command nil nil 'grep-history)))
- (let ((buf (compile-internal (concat command-args " " grep-null-device)
- "No more grep hits" "grep"
- ;; Give it a simpler regexp to match.
- nil grep-regexp-alist)))
- (save-excursion
- (set-buffer buf)
- (set (make-local-variable 'compilation-exit-message-function)
- (lambda (status code msg)
- (if (eq status 'exit)
- (cond ((zerop code)
- '("finished (matches found)\n" . "matched"))
- ((= code 1)
- '("finished with no matches found\n" . "no match"))
- (t
- (cons msg code)))
- (cons msg code)))))))
-
-(defun compile-internal (command error-message
- &optional name-of-mode parser regexp-alist
- name-function)
- "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-ALIST is the error message regexp alist to use (nil means the
-default). Sixth arg NAME-FUNCTION is a function called to name the buffer (nil
-means the default). The defaults for these variables are the global values of
-\`compilation-parse-errors-function', `compilation-error-regexp-alist', and
-\`compilation-buffer-name-function', respectively.
-
-Returns the compilation buffer created."
- (let (outbuf)
- (save-excursion
- (or name-of-mode
- (setq name-of-mode "Compilation"))
- (setq outbuf
- (get-buffer-create
- (funcall (or name-function compilation-buffer-name-function
- (function (lambda (mode)
- (concat "*" (downcase mode) "*"))))
- name-of-mode)))
- (set-buffer outbuf)
- (let ((comp-proc (get-buffer-process (current-buffer))))
- (if comp-proc
- (if (or (not (eq (process-status comp-proc) 'run))
- (yes-or-no-p
- (format "A %s process is running; kill it? "
- name-of-mode)))
- (condition-case ()
- (progn
- (interrupt-process comp-proc)
- (sit-for 1)
- (delete-process comp-proc))
- (error nil))
- (error "Cannot have two processes in `%s' at once"
- (buffer-name))
- )))
- ;; In case the compilation buffer is current, make sure we get the global
- ;; values of compilation-error-regexp-alist, etc.
- (kill-all-local-variables))
- (let ((regexp-alist (or regexp-alist compilation-error-regexp-alist))
- (parser (or parser compilation-parse-errors-function))
- (thisdir default-directory)
- outwin)
- (save-excursion
- ;; Clear out the compilation buffer and make it writable.
- ;; Change its default-directory to the directory where the compilation
- ;; will happen, and insert a `cd' command to indicate this.
- (set-buffer outbuf)
- (setq buffer-read-only nil)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (buffer-enable-undo (current-buffer))
- (setq default-directory thisdir)
- (insert "cd " thisdir "\n" command "\n")
- (set-buffer-modified-p nil))
- ;; If we're already in the compilation buffer, go to the end
- ;; of the buffer, so point will track the compilation output.
- (if (eq outbuf (current-buffer))
- (goto-char (point-max)))
- ;; Pop up the compilation buffer.
- (setq outwin (display-buffer outbuf))
- (save-excursion
- (set-buffer outbuf)
- (compilation-mode)
- ;; (setq buffer-read-only t) ;;; Non-ergonomic.
- (set (make-local-variable 'compilation-parse-errors-function) parser)
- (set (make-local-variable 'compilation-error-message) error-message)
- (set (make-local-variable 'compilation-error-regexp-alist) regexp-alist)
- (setq default-directory thisdir
- compilation-directory-stack (list default-directory))
- (set-window-start outwin (point-min))
- (setq mode-name name-of-mode)
- (or (eq outwin (selected-window))
- (set-window-point outwin (point-min)))
- (compilation-set-window-height outwin)
- ;; Start the compilation.
- (if (fboundp 'start-process)
- (let* ((process-environment (cons "EMACS=t" process-environment))
- (proc (start-process-shell-command (downcase mode-name)
- outbuf
- command)))
- (set-process-sentinel proc 'compilation-sentinel)
- (set-process-filter proc 'compilation-filter)
- (set-marker (process-mark proc) (point) outbuf)
- (setq compilation-in-progress
- (cons proc compilation-in-progress)))
- ;; No asynchronous processes available.
- (message "Executing `%s'..." command)
- ;; Fake modeline display as if `start-process' were run.
- (setq mode-line-process ":run")
- (force-mode-line-update)
- (sit-for 0) ; Force redisplay
- (let ((status (call-process shell-file-name nil outbuf nil "-c"
- command)))
- (cond ((numberp status)
- (compilation-handle-exit 'exit status
- (if (zerop status)
- "finished\n"
- (format "\
-exited abnormally with code %d\n"
- status))))
- ((stringp status)
- (compilation-handle-exit 'signal status
- (concat status "\n")))
- (t
- (compilation-handle-exit 'bizarre status status))))
- (message "Executing `%s'...done" command))))
- ;; Make it so the next C-x ` will use this buffer.
- (setq compilation-last-buffer outbuf)))
-
-;; Set the height of WINDOW according to compilation-window-height.
-(defun compilation-set-window-height (window)
- (and compilation-window-height
- (= (window-width window) (frame-width (window-frame window)))
- ;; If window is alone in its frame, aside from a minibuffer,
- ;; don't change its height.
- (not (eq window (frame-root-window (window-frame window))))
- ;; This save-excursion prevents us from changing the current buffer,
- ;; which might not be the same as the selected window's buffer.
- (save-excursion
- (let ((w (selected-window)))
- (unwind-protect
- (progn
- (select-window window)
- (enlarge-window (- compilation-window-height
- (window-height))))
- (select-window w))))))
-
-(defvar compilation-minor-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map [mouse-2] 'compile-mouse-goto-error)
- (define-key map "\C-c\C-c" 'compile-goto-error)
- (define-key map "\C-m" 'compile-goto-error)
- (define-key map "\C-c\C-k" 'kill-compilation)
- (define-key map "\M-n" 'compilation-next-error)
- (define-key map "\M-p" 'compilation-previous-error)
- (define-key map "\M-{" 'compilation-previous-file)
- (define-key map "\M-}" 'compilation-next-file)
- map)
- "Keymap for `compilation-minor-mode'.")
-
-(defvar compilation-mode-map
- (let ((map (cons 'keymap compilation-minor-mode-map)))
- (define-key map " " 'scroll-up)
- (define-key map "\^?" 'scroll-down)
- ;; Set up the menu-bar
- (define-key map [menu-bar compilation-menu]
- (cons "Compile" (make-sparse-keymap "Compile")))
-
- (define-key map [menu-bar compilation-menu compilation-mode-kill-compilation]
- '("Stop Compilation" . kill-compilation))
- (define-key map [menu-bar compilation-menu compilation-mode-separator2]
- '("----" . nil))
- (define-key map [menu-bar compilation-menu compilation-mode-first-error]
- '("First Error" . first-error))
- (define-key map [menu-bar compilation-menu compilation-mode-previous-error]
- '("Previous Error" . previous-error))
- (define-key map [menu-bar compilation-menu compilation-mode-next-error]
- '("Next Error" . next-error))
- (define-key map [menu-bar compilation-menu compilation-separator2]
- '("----" . nil))
- (define-key map [menu-bar compilation-menu compilation-mode-grep]
- '("Grep" . grep))
- (define-key map [menu-bar compilation-menu compilation-mode-recompile]
- '("Recompile" . recompile))
- (define-key map [menu-bar compilation-menu compilation-mode-compile]
- '("Compile" . compile))
- map)
- "Keymap for compilation log buffers.
-`compilation-minor-mode-map' is a cdr of this.")
-
-;;;###autoload
-(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].
-To kill the compilation, type \\[kill-compilation].
-
-Runs `compilation-mode-hook' with `run-hooks' (which see)."
- (interactive)
- (kill-all-local-variables)
- (use-local-map compilation-mode-map)
- (setq major-mode 'compilation-mode
- mode-name "Compilation")
- (compilation-setup)
- (set (make-local-variable 'font-lock-defaults)
- '(compilation-mode-font-lock-keywords t))
- (run-hooks 'compilation-mode-hook))
-
-;; Prepare the buffer for the compilation parsing commands to work.
-(defun compilation-setup ()
- ;; Make the buffer's mode line show process state.
- (setq mode-line-process '(":%s"))
- (set (make-local-variable 'compilation-error-list) nil)
- (set (make-local-variable 'compilation-old-error-list) nil)
- (set (make-local-variable 'compilation-parsing-end) 1)
- (set (make-local-variable 'compilation-directory-stack) nil)
- (setq compilation-last-buffer (current-buffer)))
-
-(defvar compilation-minor-mode nil
- "Non-nil when in compilation-minor-mode.
-In this minor mode, all the error-parsing commands of the
-Compilation major mode are available.")
-(make-variable-buffer-local 'compilation-minor-mode)
-
-(or (assq 'compilation-minor-mode minor-mode-alist)
- (setq minor-mode-alist (cons '(compilation-minor-mode " Compilation")
- minor-mode-alist)))
-(or (assq 'compilation-minor-mode minor-mode-map-alist)
- (setq minor-mode-map-alist (cons (cons 'compilation-minor-mode
- compilation-minor-mode-map)
- minor-mode-map-alist)))
-
-;;;###autoload
-(defun compilation-minor-mode (&optional arg)
- "Toggle compilation minor mode.
-With arg, turn compilation mode on if and only if arg is positive.
-See `compilation-mode'.
-Turning the mode on runs the normal hook `compilation-minor-mode-hook'."
- (interactive "P")
- (if (setq compilation-minor-mode (if (null arg)
- (null compilation-minor-mode)
- (> (prefix-numeric-value arg) 0)))
- (progn
- (compilation-setup)
- (run-hooks 'compilation-minor-mode-hook))))
-
-;; Write msg in the current buffer and hack its mode-line-process.
-(defun compilation-handle-exit (process-status exit-status msg)
- (let ((buffer-read-only nil)
- (status (if compilation-exit-message-function
- (funcall compilation-exit-message-function
- process-status exit-status msg)
- (cons msg exit-status)))
- (omax (point-max))
- (opoint (point)))
- ;; Record where we put the message, so we can ignore it
- ;; later on.
- (goto-char omax)
- (insert ?\n mode-name " " (car status))
- (forward-char -1)
- (insert " at " (substring (current-time-string) 0 19))
- (forward-char 1)
- (setq mode-line-process (format ":%s [%s]" process-status (cdr status)))
- ;; Force mode line redisplay soon.
- (force-mode-line-update)
- (if (and opoint (< opoint omax))
- (goto-char opoint))
- ;; Automatically parse (and mouse-highlight) error messages:
- (cond ((eq compile-auto-highlight t)
- (compile-reinitialize-errors nil (point-max)))
- ((numberp compile-auto-highlight)
- (compile-reinitialize-errors nil
- (save-excursion
- (goto-line compile-auto-highlight)
- (point)))))
- (if compilation-finish-function
- (funcall compilation-finish-function (current-buffer) msg))
- (let ((functions compilation-finish-functions))
- (while functions
- (funcall (car functions) (current-buffer) msg)
- (setq functions (cdr functions))))))
-
-;; Called when compilation process changes state.
-(defun compilation-sentinel (proc msg)
- "Sentinel for compilation buffers."
- (let ((buffer (process-buffer proc)))
- (if (memq (process-status proc) '(signal exit))
- (progn
- (if (null (buffer-name buffer))
- ;; buffer killed
- (set-process-buffer proc nil)
- (let ((obuf (current-buffer)))
- ;; save-excursion isn't the right thing if
- ;; process-buffer is current-buffer
- (unwind-protect
- (progn
- ;; Write something in the compilation buffer
- ;; and hack its mode line.
- (set-buffer buffer)
- (compilation-handle-exit (process-status proc)
- (process-exit-status proc)
- msg)
- ;; Since the 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))
- (set-buffer obuf))))
- (setq compilation-in-progress (delq proc compilation-in-progress))
- ))))
-
-(defun compilation-filter (proc string)
- "Process filter for compilation buffers.
-Just inserts the text, but uses `insert-before-markers'."
- (if (buffer-name (process-buffer proc))
- (save-excursion
- (set-buffer (process-buffer proc))
- (let ((buffer-read-only nil))
- (save-excursion
- (goto-char (process-mark proc))
- (insert-before-markers string)
- (run-hooks 'compilation-filter-hook)
- (set-marker (process-mark proc) (point)))))))
-
-;; Return the cdr of compilation-old-error-list for the error containing point.
-(defun compile-error-at-point ()
- (compile-reinitialize-errors nil (point))
- (let ((errors compilation-old-error-list))
- (while (and errors
- (> (point) (car (car errors))))
- (setq errors (cdr errors)))
- errors))
-
-(defsubst compilation-buffer-p (buffer)
- (save-excursion
- (set-buffer buffer)
- (or compilation-minor-mode (eq major-mode 'compilation-mode))))
-
-(defun compilation-next-error (n)
- "Move point to the next error in the compilation buffer.
-Does NOT find the source line like \\[next-error]."
- (interactive "p")
- (or (compilation-buffer-p (current-buffer))
- (error "Not in a compilation buffer."))
- (setq compilation-last-buffer (current-buffer))
-
- (let ((errors (compile-error-at-point)))
-
- ;; Move to the error after the one containing point.
- (goto-char (car (if (< n 0)
- (let ((i 0)
- (e compilation-old-error-list))
- ;; See how many cdrs away ERRORS is from the start.
- (while (not (eq e errors))
- (setq i (1+ i)
- e (cdr e)))
- (if (> (- n) i)
- (error "Moved back past first error")
- (nth (+ i n) compilation-old-error-list)))
- (let ((compilation-error-list (cdr errors)))
- (compile-reinitialize-errors nil nil n)
- (if compilation-error-list
- (nth (1- n) compilation-error-list)
- (error "Moved past last error"))))))))
-
-(defun compilation-previous-error (n)
- "Move point to the previous error in the compilation buffer.
-Does NOT find the source line like \\[next-error]."
- (interactive "p")
- (compilation-next-error (- n)))
-
-
-;; Given an elt of `compilation-error-list', return an object representing
-;; the referenced file which is equal to (but not necessarily eq to) what
-;; this function would return for another error in the same file.
-(defsubst compilation-error-filedata (data)
- (setq data (cdr data))
- (if (markerp data)
- (marker-buffer data)
- (car data)))
-
-;; Return a string describing a value from compilation-error-filedata.
-;; This value is not necessarily useful as a file name, but should be
-;; indicative to the user of what file's errors are being referred to.
-(defsubst compilation-error-filedata-file-name (filedata)
- (if (bufferp filedata)
- (buffer-file-name filedata)
- (car filedata)))
-
-(defun compilation-next-file (n)
- "Move point to the next error for a different file than the current one."
- (interactive "p")
- (or (compilation-buffer-p (current-buffer))
- (error "Not in a compilation buffer."))
- (setq compilation-last-buffer (current-buffer))
-
- (let ((reversed (< n 0))
- errors filedata)
-
- (if (not reversed)
- (setq errors (or (compile-error-at-point)
- (error "Moved past last error")))
-
- ;; Get a reversed list of the errors up through the one containing point.
- (compile-reinitialize-errors nil (point))
- (setq errors (reverse compilation-old-error-list)
- n (- n))
-
- ;; Ignore errors after point. (car ERRORS) will be the error
- ;; containing point, (cadr ERRORS) the one before it.
- (while (and errors
- (< (point) (car (car errors))))
- (setq errors (cdr errors))))
-
- (while (> n 0)
- (setq filedata (compilation-error-filedata (car errors)))
-
- ;; Skip past the following errors for this file.
- (while (equal filedata
- (compilation-error-filedata
- (car (or errors
- (if reversed
- (error "%s the first erring file"
- (compilation-error-filedata-file-name
- filedata))
- (let ((compilation-error-list nil))
- ;; Parse some more.
- (compile-reinitialize-errors nil nil 2)
- (setq errors compilation-error-list)))
- (error "%s is the last erring file"
- (compilation-error-filedata-file-name
- filedata))))))
- (setq errors (cdr errors)))
-
- (setq n (1- n)))
-
- ;; Move to the following error.
- (goto-char (car (car (or errors
- (if reversed
- (error "This is the first erring file")
- (let ((compilation-error-list nil))
- ;; Parse the last one.
- (compile-reinitialize-errors nil nil 1)
- compilation-error-list))))))))
-
-(defun compilation-previous-file (n)
- "Move point to the previous error for a different file than the current one."
- (interactive "p")
- (compilation-next-file (- n)))
-
-
-(defun kill-compilation ()
- "Kill the process made by the \\[compile] command."
- (interactive)
- (let ((buffer (compilation-find-buffer)))
- (if (get-buffer-process buffer)
- (interrupt-process (get-buffer-process buffer))
- (error "The compilation process is not running."))))
-
-
-;; Parse any new errors in the compilation buffer,
-;; or reparse from the beginning if the user has asked for that.
-(defun compile-reinitialize-errors (reparse
- &optional limit-search find-at-least)
- (save-excursion
- (set-buffer compilation-last-buffer)
- ;; If we are out of errors, or if user says "reparse",
- ;; discard the info we have, to force reparsing.
- (if (or (eq compilation-error-list t)
- reparse)
- (compilation-forget-errors))
- (if (and compilation-error-list
- (or (not limit-search)
- (> compilation-parsing-end limit-search))
- (or (not find-at-least)
- (>= (length compilation-error-list) find-at-least)))
- ;; Since compilation-error-list is non-nil, it points to a specific
- ;; error the user wanted. So don't move it around.
- nil
- ;; This was here for a long time (before my rewrite); why? --roland
- ;;(switch-to-buffer compilation-last-buffer)
- (set-buffer-modified-p nil)
- (if (< compilation-parsing-end (point-max))
- ;; compilation-error-list might be non-nil if we have a non-nil
- ;; LIMIT-SEARCH or FIND-AT-LEAST arg. In that case its value
- ;; records the current position in the error list, and we must
- ;; preserve that after reparsing.
- (let ((error-list-pos compilation-error-list))
- (funcall compilation-parse-errors-function
- limit-search
- (and find-at-least
- ;; We only need enough new parsed errors to reach
- ;; FIND-AT-LEAST errors past the current
- ;; position.
- (- find-at-least (length compilation-error-list))))
- ;; Remember the entire list for compilation-forget-errors. If
- ;; this is an incremental parse, append to previous list. If
- ;; we are parsing anew, compilation-forget-errors cleared
- ;; compilation-old-error-list above.
- (setq compilation-old-error-list
- (nconc compilation-old-error-list compilation-error-list))
- (if error-list-pos
- ;; We started in the middle of an existing list of parsed
- ;; errors before parsing more; restore that position.
- (setq compilation-error-list error-list-pos))
- ;; Mouse-Highlight (the first line of) each error message when the
- ;; mouse pointer moves over it:
- (let ((inhibit-read-only t)
- (error-list compilation-error-list))
- (while error-list
- (save-excursion
- (put-text-property (goto-char (car (car error-list)))
- (progn (end-of-line) (point))
- 'mouse-face 'highlight))
- (setq error-list (cdr error-list))))
- )))))
-
-(defun compile-mouse-goto-error (event)
- (interactive "e")
- (save-excursion
- (set-buffer (window-buffer (posn-window (event-end event))))
- (goto-char (posn-point (event-end event)))
-
- (or (compilation-buffer-p (current-buffer))
- (error "Not in a compilation buffer."))
- (setq compilation-last-buffer (current-buffer))
- (compile-reinitialize-errors nil (point))
-
- ;; Move to bol; the marker for the error on this line will point there.
- (beginning-of-line)
-
- ;; Move compilation-error-list to the elt of compilation-old-error-list
- ;; we want.
- (setq compilation-error-list compilation-old-error-list)
- (while (and compilation-error-list
- (> (point) (car (car compilation-error-list))))
- (setq compilation-error-list (cdr compilation-error-list)))
- (or compilation-error-list
- (error "No error to go to")))
- (select-window (posn-window (event-end event)))
- ;; Move to another window, so that next-error's window changes
- ;; result in the desired setup.
- (or (one-window-p)
- (progn
- (other-window -1)
- ;; other-window changed the selected buffer,
- ;; but we didn't want to do that.
- (set-buffer compilation-last-buffer)))
-
- (push-mark)
- (next-error 1))
-
-(defun compile-goto-error (&optional argp)
- "Visit the source for the error message point is on.
-Use this command in a compilation log buffer. Sets the mark at point there.
-\\[universal-argument] as a prefix arg means to reparse the buffer's error messages first;
-other kinds of prefix arguments are ignored."
- (interactive "P")
- (or (compilation-buffer-p (current-buffer))
- (error "Not in a compilation buffer."))
- (setq compilation-last-buffer (current-buffer))
- (compile-reinitialize-errors (consp argp) (point))
-
- ;; Move to bol; the marker for the error on this line will point there.
- (beginning-of-line)
-
- ;; Move compilation-error-list to the elt of compilation-old-error-list
- ;; we want.
- (setq compilation-error-list compilation-old-error-list)
- (while (and compilation-error-list
- (> (point) (car (car compilation-error-list))))
- (setq compilation-error-list (cdr compilation-error-list)))
-
- ;; Move to another window, so that next-error's window changes
- ;; result in the desired setup.
- (or (one-window-p)
- (progn
- (other-window -1)
- ;; other-window changed the selected buffer,
- ;; but we didn't want to do that.
- (set-buffer compilation-last-buffer)))
-
- (push-mark)
- (next-error 1))
-
-;; Return a compilation buffer.
-;; If the current buffer is a compilation buffer, return it.
-;; If compilation-last-buffer is set to a live buffer, use that.
-;; Otherwise, look for a compilation buffer and signal an error
-;; if there are none.
-(defun compilation-find-buffer (&optional other-buffer)
- (if (and (not other-buffer)
- (compilation-buffer-p (current-buffer)))
- ;; The current buffer is a compilation buffer.
- (current-buffer)
- (if (and compilation-last-buffer (buffer-name compilation-last-buffer)
- (compilation-buffer-p compilation-last-buffer)
- (or (not other-buffer) (not (eq compilation-last-buffer
- (current-buffer)))))
- compilation-last-buffer
- (let ((buffers (buffer-list)))
- (while (and buffers (or (not (compilation-buffer-p (car buffers)))
- (and other-buffer
- (eq (car buffers) (current-buffer)))))
- (setq buffers (cdr buffers)))
- (if buffers
- (car buffers)
- (or (and other-buffer
- (compilation-buffer-p (current-buffer))
- ;; The current buffer is a compilation buffer.
- (progn
- (if other-buffer
- (message "This is the only compilation buffer."))
- (current-buffer)))
- (error "No compilation started!")))))))
-
-;;;###autoload
-(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-function' and
-\`compilation-error-regexp-alist' for customization ideas."
- (interactive "P")
- (setq compilation-last-buffer (compilation-find-buffer))
- (compilation-goto-locus (compilation-next-error-locus
- ;; We want to pass a number here only if
- ;; we got a numeric prefix arg, not just C-u.
- (and (not (consp argp))
- (prefix-numeric-value argp))
- (consp argp))))
-;;;###autoload (define-key ctl-x-map "`" 'next-error)
-
-(defun previous-error ()
- "Visit previous compilation error message and corresponding source code.
-This operates on the output from the \\[compile] command."
- (interactive)
- (next-error -1))
-
-(defun first-error ()
- "Reparse the error message buffer and start at the first error
-Visit corresponding source code.
-This operates on the output from the \\[compile] command."
- (interactive)
- (next-error '(4)))
-
-(defvar compilation-skip-to-next-location nil
- "*If non-nil, skip multiple error messages for the same source location.")
-
-(defun compilation-next-error-locus (&optional move reparse silent)
- "Visit next compilation error and return locus in 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.
-
-Returns a cons (ERROR . SOURCE) of two markers: ERROR is a marker at the
-location of the error message in the compilation buffer, and SOURCE is a
-marker at the location in the source code indicated by the error message.
-
-Optional first arg MOVE says how many error messages to move forwards (or
-backwards, if negative); default is 1. Optional second arg REPARSE, if
-non-nil, says to reparse the error message buffer and reset to the first
-error (plus MOVE - 1). If optional third argument SILENT is non-nil, return
-nil instead of raising an error if there are no more errors.
-
-The current buffer should be the desired compilation output buffer."
- (or move (setq move 1))
- (compile-reinitialize-errors reparse nil (and (not reparse)
- (if (< move 1) 0 (1- move))))
- (let (next-errors next-error)
- (catch 'no-next-error
- (save-excursion
- (set-buffer compilation-last-buffer)
- ;; compilation-error-list points to the "current" error.
- (setq next-errors
- (if (> move 0)
- (nthcdr (1- move)
- compilation-error-list)
- ;; Zero or negative arg; we need to move back in the list.
- (let ((n (1- move))
- (i 0)
- (e compilation-old-error-list))
- ;; See how many cdrs away the current error is from the start.
- (while (not (eq e compilation-error-list))
- (setq i (1+ i)
- e (cdr e)))
- (if (> (- n) i)
- (error "Moved back past first error")
- (nthcdr (+ i n) compilation-old-error-list))))
- next-error (car next-errors))
- (while
- (if (null next-error)
- (progn
- (and move (/= move 1)
- (error (if (> move 0)
- "Moved past last error")
- "Moved back past first error"))
- ;; Forget existing error messages if compilation has finished.
- (if (not (and (get-buffer-process (current-buffer))
- (eq (process-status
- (get-buffer-process
- (current-buffer)))
- 'run)))
- (compilation-forget-errors))
- (if silent
- (throw 'no-next-error nil)
- (error (concat compilation-error-message
- (and (get-buffer-process (current-buffer))
- (eq (process-status
- (get-buffer-process
- (current-buffer)))
- 'run)
- " yet")))))
- (setq compilation-error-list (cdr next-errors))
- (if (null (cdr next-error))
- ;; This error is boring. Go to the next.
- t
- (or (markerp (cdr next-error))
- ;; This error has a filename/lineno pair.
- ;; Find the file and turn it into a marker.
- (let* ((fileinfo (car (cdr next-error)))
- (buffer (apply 'compilation-find-file
- (car next-error) fileinfo)))
- (if (null buffer)
- ;; We can't find this error's file.
- ;; Remove all errors in the same file.
- (progn
- (setq next-errors compilation-old-error-list)
- (while next-errors
- (and (consp (cdr (car next-errors)))
- (equal (car (cdr (car next-errors)))
- fileinfo)
- (progn
- (set-marker (car (car next-errors)) nil)
- (setcdr (car next-errors) nil)))
- (setq next-errors (cdr next-errors)))
- ;; Look for the next error.
- t)
- ;; We found the file. Get a marker for this error.
- ;; compilation-old-error-list is a buffer-local
- ;; variable, so we must be careful to extract its value
- ;; before switching to the source file buffer.
- (let ((errors compilation-old-error-list)
- (last-line (nth 1 (cdr next-error)))
- (column (nth 2 (cdr next-error))))
- (set-buffer buffer)
- (save-excursion
- (save-restriction
- (widen)
- (goto-line last-line)
- (if (and column (> column 0))
- ;; Columns in error msgs are 1-origin.
- (move-to-column (1- column))
- (beginning-of-line))
- (setcdr next-error (point-marker))
- ;; Make all the other error messages referring
- ;; to the same file have markers into the buffer.
- (while errors
- (and (consp (cdr (car errors)))
- (equal (car (cdr (car errors))) fileinfo)
- (let* ((this (nth 1 (cdr (car errors))))
- (column (nth 2 (cdr (car errors))))
- (lines (- this last-line)))
- (if (eq selective-display t)
- ;; When selective-display is t,
- ;; each C-m is a line boundary,
- ;; as well as each newline.
- (if (< lines 0)
- (re-search-backward "[\n\C-m]"
- nil 'end
- (- lines))
- (re-search-forward "[\n\C-m]"
- nil 'end
- lines))
- (forward-line lines))
- (if (and column (> column 1))
- (move-to-column (1- column))
- (beginning-of-line))
- (setq last-line this)
- (setcdr (car errors) (point-marker))))
- (setq errors (cdr errors)))))))))
- ;; If we didn't get a marker for this error, or this
- ;; marker's buffer was killed, go on to the next one.
- (or (not (markerp (cdr next-error)))
- (not (marker-buffer (cdr next-error))))))
- (setq next-errors compilation-error-list
- next-error (car next-errors)))))
-
- (if compilation-skip-to-next-location
- ;; Skip over multiple error messages for the same source location,
- ;; so the next C-x ` won't go to an error in the same place.
- (while (and compilation-error-list
- (equal (cdr (car compilation-error-list)) (cdr next-error)))
- (setq compilation-error-list (cdr compilation-error-list))))
-
- ;; We now have a marker for the position of the error source code.
- ;; NEXT-ERROR is a cons (ERROR . SOURCE) of two markers.
- next-error))
-
-(defun compilation-goto-locus (next-error)
- "Jump to an error locus returned by `compilation-next-error-locus'.
-Takes one argument, a cons (ERROR . SOURCE) of two markers.
-Selects a window with point at SOURCE, with another window displaying ERROR."
- (if (and (window-dedicated-p (selected-window))
- (eq (selected-window) (frame-root-window)))
- (switch-to-buffer-other-frame (marker-buffer (cdr next-error)))
- (switch-to-buffer (marker-buffer (cdr next-error))))
- (goto-char (cdr next-error))
- ;; If narrowing got in the way of
- ;; going to the right place, widen.
- (or (= (point) (marker-position (cdr next-error)))
- (progn
- (widen)
- (goto-char (cdr next-error))))
-
- ;; Show compilation buffer in other window, scrolled to this error.
- (let* ((pop-up-windows t)
- ;; Use an existing window if it is in a visible frame.
- (w (or (get-buffer-window (marker-buffer (car next-error)) 'visible)
- ;; Pop up a window.
- (display-buffer (marker-buffer (car next-error))))))
- (set-window-point w (car next-error))
- (set-window-start w (car next-error))
- (compilation-set-window-height w)))
-
-;; Find a buffer for file FILENAME.
-;; Search the directories in compilation-search-path.
-;; A nil in compilation-search-path means to try the
-;; current directory, which is passed in DIR.
-;; If FILENAME is not found at all, ask the user where to find it.
-;; Pop up the buffer containing MARKER and scroll to MARKER if we ask the user.
-(defun compilation-find-file (marker filename dir &rest formats)
- (or formats (setq formats '("%s")))
- (let ((dirs compilation-search-path)
- buffer thisdir fmts name)
- (if (file-name-absolute-p filename)
- ;; The file name is absolute. Use its explicit directory as
- ;; the first in the search path, and strip it from FILENAME.
- (setq filename (abbreviate-file-name (expand-file-name filename))
- dirs (cons (file-name-directory filename) dirs)
- filename (file-name-nondirectory filename)))
- ;; Now search the path.
- (while (and dirs (null buffer))
- (setq thisdir (or (car dirs) dir)
- fmts formats)
- ;; For each directory, try each format string.
- (while (and fmts (null buffer))
- (setq name (expand-file-name (format (car fmts) filename) thisdir)
- buffer (and (file-exists-p name)
- (find-file-noselect name))
- fmts (cdr fmts)))
- (setq dirs (cdr dirs)))
- (or buffer
- ;; The file doesn't exist.
- ;; Ask the user where to find it.
- ;; If he hits C-g, then the next time he does
- ;; next-error, he'll skip past it.
- (let* ((pop-up-windows t)
- (w (display-buffer (marker-buffer marker))))
- (set-window-point w marker)
- (set-window-start w marker)
- (let ((name (expand-file-name
- (read-file-name
- (format "Find this error in: (default %s) "
- filename)
- dir filename t))))
- (if (file-directory-p name)
- (setq name (expand-file-name filename name)))
- (and (file-exists-p name)
- (find-file-noselect name)))))))
-
-;; 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 (markerp (cdr next-error))
- (set-marker (cdr next-error) nil)))
- (setq compilation-old-error-list (cdr compilation-old-error-list)))
- (setq compilation-error-list nil
- compilation-directory-stack nil
- compilation-parsing-end 1)
- ;; Remove the highlighting added by compile-reinitialize-errors:
- (let ((inhibit-read-only t))
- (remove-text-properties (point-min) (point-max) '(mouse-face highlight)))
- )
-
-
-(defun count-regexp-groupings (regexp)
- "Return the number of \\( ... \\) groupings in REGEXP (a string)."
- (let ((groupings 0)
- (len (length regexp))
- (i 0)
- c)
- (while (< i len)
- (setq c (aref regexp i)
- i (1+ i))
- (cond ((= c ?\[)
- ;; Find the end of this [...].
- (while (and (< i len)
- (not (= (aref regexp i) ?\])))
- (setq i (1+ i))))
- ((= c ?\\)
- (if (< i len)
- (progn
- (setq c (aref regexp i)
- i (1+ i))
- (if (= c ?\))
- ;; We found the end of a grouping,
- ;; so bump our counter.
- (setq groupings (1+ groupings))))))))
- groupings))
-
-(defun compilation-parse-errors (limit-search find-at-least)
- "Parse the current buffer as grep, cc or lint error messages.
-See variable `compilation-parse-errors-function' for the interface it uses."
- (setq compilation-error-list nil)
- (message "Parsing error messages...")
- (let (text-buffer orig orig-expanded parent-expanded
- regexp enter-group leave-group error-group
- alist subexpr error-regexp-groups
- (found-desired nil)
- (compilation-num-errors-found 0))
-
- ;; 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)
- (progn
- (forward-line 2)
- ;; Move back so point is before the newline.
- ;; This matters because some error regexps use \n instead of ^
- ;; to be faster.
- (forward-char -1)))
-
- ;; Compile all the regexps we want to search for into one.
- (setq regexp (concat "\\(" compilation-enter-directory-regexp "\\)\\|"
- "\\(" compilation-leave-directory-regexp "\\)\\|"
- "\\(" (mapconcat (function
- (lambda (elt)
- (concat "\\(" (car elt) "\\)")))
- compilation-error-regexp-alist
- "\\|") "\\)"))
-
- ;; Find out how many \(...\) groupings are in each of the regexps, and set
- ;; *-GROUP to the grouping containing each constituent regexp (whose
- ;; subgroups will come immediately thereafter) of the big regexp we have
- ;; just constructed.
- (setq enter-group 1
- leave-group (+ enter-group
- (count-regexp-groupings
- compilation-enter-directory-regexp)
- 1)
- error-group (+ leave-group
- (count-regexp-groupings
- compilation-leave-directory-regexp)
- 1))
-
- ;; Compile an alist (IDX FILE LINE [COL]), where IDX is the number of
- ;; the subexpression for an entire error-regexp, and FILE and LINE (and
- ;; possibly COL) are the numbers for the subexpressions giving the file
- ;; name and line number (and possibly column number).
- (setq alist (or compilation-error-regexp-alist
- (error "compilation-error-regexp-alist is empty!"))
- subexpr (1+ error-group))
- (while alist
- (setq error-regexp-groups
- (cons (list subexpr
- (+ subexpr (nth 1 (car alist)))
- (+ subexpr (nth 2 (car alist)))
- (and (nth 3 (car alist))
- (+ subexpr (nth 3 (car alist)))))
- error-regexp-groups))
- (setq subexpr (+ subexpr 1 (count-regexp-groupings (car (car alist)))))
- (setq alist (cdr alist)))
-
- ;; Set up now the expanded, abbreviated directory variables
- ;; that compile-abbreviate-directory will need, so we can
- ;; compute them just once here.
- (setq orig (abbreviate-file-name default-directory)
- orig-expanded (abbreviate-file-name
- (file-truename default-directory))
- parent-expanded (abbreviate-file-name
- (expand-file-name "../" orig-expanded)))
-
- (while (and (not found-desired)
- ;; We don't just pass LIMIT-SEARCH to re-search-forward
- ;; because we want to find matches containing LIMIT-SEARCH
- ;; but which extend past it.
- (re-search-forward regexp nil t))
-
- ;; Figure out which constituent regexp matched.
- (cond ((match-beginning enter-group)
- ;; The match was the enter-directory regexp.
- (let ((dir
- (file-name-as-directory
- (expand-file-name
- (buffer-substring (match-beginning (+ enter-group 1))
- (match-end (+ enter-group 1)))))))
- ;; The directory name in the "entering" message
- ;; is a truename. Try to convert it to a form
- ;; like what the user typed in.
- (setq dir
- (compile-abbreviate-directory dir orig orig-expanded
- parent-expanded))
- (setq compilation-directory-stack
- (cons dir compilation-directory-stack))
- (and (file-directory-p dir)
- (setq default-directory dir)))
-
- (and limit-search (>= (point) limit-search)
- ;; The user wanted a specific error, and we're past it.
- ;; We do this check here (and in the leave-group case)
- ;; rather than at the end of the loop because if the last
- ;; thing seen is an error message, we must carefully
- ;; discard the last error when it is the first in a new
- ;; file (see below in the error-group case).
- (setq found-desired t)))
-
- ((match-beginning leave-group)
- ;; The match was the leave-directory regexp.
- (let ((beg (match-beginning (+ leave-group 1)))
- (stack compilation-directory-stack))
- (if beg
- (let ((dir
- (file-name-as-directory
- (expand-file-name
- (buffer-substring beg
- (match-end (+ leave-group
- 1)))))))
- ;; The directory name in the "leaving" message
- ;; is a truename. Try to convert it to a form
- ;; like what the user typed in.
- (setq dir
- (compile-abbreviate-directory dir orig orig-expanded
- parent-expanded))
- (while (and stack
- (not (string-equal (car stack) dir)))
- (setq stack (cdr stack)))))
- (setq compilation-directory-stack (cdr stack))
- (setq stack (car compilation-directory-stack))
- (if stack
- (setq default-directory stack))
- )
-
- (and limit-search (>= (point) limit-search)
- ;; The user wanted a specific error, and we're past it.
- ;; We do this check here (and in the enter-group case)
- ;; rather than at the end of the loop because if the last
- ;; thing seen is an error message, we must carefully
- ;; discard the last error when it is the first in a new
- ;; file (see below in the error-group case).
- (setq found-desired t)))
-
- ((match-beginning error-group)
- ;; The match was the composite error regexp.
- ;; Find out which individual regexp matched.
- (setq alist error-regexp-groups)
- (while (and alist
- (null (match-beginning (car (car alist)))))
- (setq alist (cdr alist)))
- (if alist
- (setq alist (car alist))
- (error "compilation-parse-errors: impossible regexp match!"))
-
- ;; Extract the file name and line number from the error message.
- (let ((beginning-of-match (match-beginning 0)) ;looking-at nukes
- (filename (buffer-substring (match-beginning (nth 1 alist))
- (match-end (nth 1 alist))))
- (linenum (string-to-int
- (buffer-substring
- (match-beginning (nth 2 alist))
- (match-end (nth 2 alist)))))
- (column (and (nth 3 alist)
- (match-beginning (nth 3 alist))
- (string-to-int
- (buffer-substring
- (match-beginning (nth 3 alist))
- (match-end (nth 3 alist)))))))
-
- ;; Check for a comint-file-name-prefix and prepend it if
- ;; appropriate. (This is very useful for
- ;; compilation-minor-mode in an rlogin-mode buffer.)
- (and (boundp 'comint-file-name-prefix)
- ;; If the file name is relative, default-directory will
- ;; already contain the comint-file-name-prefix (done by
- ;; compile-abbreviate-directory).
- (file-name-absolute-p filename)
- (setq filename (concat comint-file-name-prefix filename)))
-
- ;; Some compilers (e.g. Sun's java compiler, reportedly)
- ;; produce bogus file names like "./bar//foo.c" for the file
- ;; "bar/foo.c"; expand-file-name will collapse these into
- ;; "/foo.c" and fail to find the appropriate file. So we look
- ;; for doubled slashes in the file name and fix them up in the
- ;; buffer.
- (setq filename (command-line-normalize-file-name filename))
- (setq filename (cons filename (cons default-directory
- (nthcdr 4 alist))))
-
-
- ;; Locate the erring file and line.
- ;; Cons a new elt onto compilation-error-list,
- ;; giving a marker for the current compilation buffer
- ;; location, and the file and line number of the error.
- (save-excursion
- ;; Save as the start of the error the beginning of the
- ;; line containing the match unless the match starts at a
- ;; newline, in which case the beginning of the next line.
- (goto-char beginning-of-match)
- (forward-line (if (eolp) 1 0))
- (let ((this (cons (point-marker)
- (list filename linenum column))))
- ;; Don't add the same source line more than once.
- (if (and compilation-skip-to-next-location
- (equal (cdr this)
- (cdr (car compilation-error-list))))
- nil
- (setq compilation-error-list
- (cons this
- compilation-error-list))
- (setq compilation-num-errors-found
- (1+ compilation-num-errors-found)))))
- (and (or (and find-at-least (> compilation-num-errors-found
- find-at-least))
- (and limit-search (>= (point) limit-search)))
- ;; We have found as many new errors as the user wants,
- ;; or past the buffer position he indicated. We
- ;; continue to parse until we have seen all the
- ;; consecutive errors in the same file, so the error
- ;; positions will be recorded as markers in this buffer
- ;; that might change.
- (cdr compilation-error-list) ; Must check at least two.
- (not (equal (car (cdr (nth 0 compilation-error-list)))
- (car (cdr (nth 1 compilation-error-list)))))
- (progn
- ;; Discard the error just parsed, so that the next
- ;; parsing run can get it and the following errors in
- ;; the same file all at once. If we didn't do this, we
- ;; would have the same problem we are trying to avoid
- ;; with the test above, just delayed until the next run!
- (setq compilation-error-list
- (cdr compilation-error-list))
- (goto-char beginning-of-match)
- (setq found-desired t)))
- )
- )
- (t
- (error "compilation-parse-errors: known groups didn't match!")))
-
- (message "Parsing error messages...%d (%.0f%% of buffer)"
- compilation-num-errors-found
- ;; Use floating-point because (* 100 (point)) frequently
- ;; exceeds the range of Emacs Lisp integers.
- (/ (* 100.0 (point)) (point-max)))
-
- (and limit-search (>= (point) limit-search)
- ;; The user wanted a specific error, and we're past it.
- (setq found-desired t)))
- (setq compilation-parsing-end (if found-desired
- (point)
- ;; We have searched the whole buffer.
- (point-max))))
- (setq compilation-error-list (nreverse compilation-error-list))
- (message "Parsing error messages...done"))
-
-;; If directory DIR is a subdir of ORIG or of ORIG's parent,
-;; return a relative name for it starting from ORIG or its parent.
-;; ORIG-EXPANDED is an expanded version of ORIG.
-;; PARENT-EXPANDED is an expanded version of ORIG's parent.
-;; Those two args could be computed here, but we run faster by
-;; having the caller compute them just once.
-(defun compile-abbreviate-directory (dir orig orig-expanded parent-expanded)
- ;; Apply canonical abbreviations to DIR first thing.
- ;; Those abbreviations are already done in the other arguments passed.
- (setq dir (abbreviate-file-name dir))
-
- ;; Check for a comint-file-name-prefix and prepend it if appropriate.
- ;; (This is very useful for compilation-minor-mode in an rlogin-mode
- ;; buffer.)
- (if (boundp 'comint-file-name-prefix)
- (setq dir (concat comint-file-name-prefix dir)))
-
- (if (and (> (length dir) (length orig-expanded))
- (string= orig-expanded
- (substring dir 0 (length orig-expanded))))
- (setq dir
- (concat orig
- (substring dir (length orig-expanded)))))
- (if (and (> (length dir) (length parent-expanded))
- (string= parent-expanded
- (substring dir 0 (length parent-expanded))))
- (setq dir
- (concat (file-name-directory
- (directory-file-name orig))
- (substring dir (length parent-expanded)))))
- dir)
-
-(provide 'compile)
-
-;;; compile.el ends here
diff --git a/lisp/progmodes/cplus-md.el b/lisp/progmodes/cplus-md.el
deleted file mode 100644
index 9848adcf40b..00000000000
--- a/lisp/progmodes/cplus-md.el
+++ /dev/null
@@ -1,1061 +0,0 @@
-;;; cplus-md.el --- C++ code editing commands for Emacs
-
-;; Copyright (C) 1985, 1992, 1994, 1995 Free Software Foundation, Inc.
-
-;; Maintainer: Dave Detlefs <dld@cs.cmu.edu>
-;; Keywords: c
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; 1987 Dave Detlefs <dld@cs.cmu.edu>
-;; and Stewart Clamen <clamen@cs.cmu.edu>.
-;; Done by fairly faithful modification of:
-
-;;; Change Log:
-
-;; Feb, 1990 (Dave Detlefs, dld@cs.cmu.edu)
-;; Fixed electric-c++-terminator to handle double colons, at the
-;; request of John Hagerman.
-;;
-;; Jan, 1990 (Doug Lea, dl@oswego.edu)
-;; Replaced c++-comment-region and c++-uncomment-region with
-;; versions from Igor Metz that avoid potential infinite loops.
-;;
-;; Oct, 1989 (Dave Detlefs, dld@cs.cmu.edu)
-;; Added contribution from Igor Metz <metz@iam.unibe.ch>:
-;; functions c++-comment-region and c++-uncomment-region and
-;; corresponding key-binding.
-;; Also fixed bug in indentation of second line after an empty
-;; arglist with empty-arglist non-null.
-;;
-;; Sept, 1989 (Glen Ditchfield, gjditchfield@violet.uwaterloo.ca):
-;; Textual changes to more closely imitate Emacs 18.55's c-mode.
-;; Fixed handling of "default:", where ":" was the last character in the
-;; buffer. Fixed indentation of comments starting in column 0, and when
-;; previous line contained more than one comment start string. Fixed
-;; handling of "friend".
-;;
-;; Aug 7, 1989; John Hagerman (hagerman@ece.cmu.edu):
-;; Changed calculate-c++-indent to handle member initializations
-;; more flexibly. Two new variables are used to control behavior:
-;; c++-member-init-indent and c++-continued-member-init-offset.
-;; Note the assumption that member initializations and argument
-;; declarations are not mixed in one function definition.
-;;
-;; June 1989 (Dave Detlefs, dld@cs.cmu.edu)
-;; Fixed calculate-c++-indent to handle continued lines ending in
-;; {'s. (I wasn't following C-mode closely enough, or C-mode
-;; changed.) Made ' a quote character, at the behest of someone
-;; whose mail I apparently deleted (if they send me mail I'll credit
-;; them here in a future revision.)
-;; Dan Weinreb (dlw@odi.com) pointed out that 'c++-mode successively
-;; bound c++-indent-exp and c++-indent-defun to ESC-^q. ESC-^q is
-;; now bound to c++-indent-exp, while, c++-indent-defun is invoked
-;; with ESC-^x.
-
-;; February 1989 (Dave Detlefs, dld@cs.cmu.edu)
-;; Fixed some errors in c++-indent-defun, as pointed out by Sam
-;; Haradhvala (odi!sam@talcott.harvard.edu).
-;; October 1988 (Dave Detlefs, dld@cs.cmu.edu)
-;; It turns out I had only *thought* I had made
-;; beginning(end)-of-defun work. It should work better now -- you
-;; can either attempt to match defun headers "strongly," using a
-;; very complicated regexp, or "weakly," using a simple one. This
-;; is settable by a variable; the default is the cheaper weak
-;; method. (Stewart Clamen was intimately involved in this, too.)
-;;
-;; I made "'" *not* be a string delimiter, because that was causing
-;; comments containing contractions to ("// don't") to mess up paren
-;; balancing.
-;;
-;; I also incorporated another slight indentation fix from Glen
-;; Ditchfield.
-;;
-;; We hope this is will make into version 19 of gnu-emacs.
-;;
-;; September 1988: incorporated changes from Fred Calm at Schlumberger.
-;; Also, made beginning(end)-of-defun, indent-defun work.
-;;
-;; August 1987: incorporated changes done by Glen Ditchfield of Waterloo.
-
-;;; Code:
-
-(defvar c++-mode-abbrev-table nil
- "Abbrev table used in C++ mode.")
-(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 "\C-j" 'reindent-then-newline-and-indent)
- (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 "\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)
-;; (define-key c++-mode-map "\C-c\C-i" 'c++-insert-header)
- (define-key c++-mode-map "\C-c\C-\\" 'c-backslash-region))
-;; (define-key c++-mode-map "\e\C-a" 'c++-beginning-of-defun)
-;; (define-key c++-mode-map "\e\C-e" 'c++-end-of-defun)
-;; (define-key c++-mode-map "\e\C-x" 'c++-indent-defun))
-
-(defvar c++-mode-syntax-table nil
- "Syntax table used in C++ mode.")
-
-(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)
- (modify-syntax-entry ?* ". 23b" c++-mode-syntax-table)
- (modify-syntax-entry ?/ ". 124" c++-mode-syntax-table)
- (modify-syntax-entry ?\n ">" c++-mode-syntax-table)
- (modify-syntax-entry ?\^m ">" c++-mode-syntax-table))
-
-(defvar c++-continued-member-init-offset nil
- "*Extra indent for continuation lines of member inits;
-nil means to align with previous initializations rather than
-with the colon on the first line.")
-(defvar c++-member-init-indent 0
- "*Indentation level of member initializations in function declarations.")
-(defvar c++-friend-offset -4
- "*Offset of C++ friend declarations relative to member declarations.")
-(defvar c++-electric-colon t
- "*If t, colon is an electric terminator.")
-(defvar c++-empty-arglist-indent nil
- "*Indicates how far to indent an line following an empty argument
-list. Nil indicates to just after the paren.")
-
-(defvar c++-imenu-generic-expression
- (`
- ((nil
- (,
- (concat
- "^" ; beginning of line is required
- "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
- "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; type specs; there can be no
- "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; more than 3 tokens, right?
-
- "\\(" ; last type spec including */&
- "[a-zA-Z0-9_:]+"
- "\\([ \t]*[*&]+[ \t]*\\|[ \t]+\\)" ; either pointer/ref sign or whitespace
- "\\)?" ; if there is a last type spec
- "\\(" ; name; take that into the imenu entry
- "[a-zA-Z0-9_:~]+" ; member function, ctor or dtor...
- ; (may not contain * because then
- ; "a::operator char*" would become "char*"!)
- "\\|"
- "\\([a-zA-Z0-9_:~]*::\\)?operator"
- "[^a-zA-Z1-9_][^(]*" ; ...or operator
- " \\)"
- "[ \t]*([^)]*)[ \t\n]*[^ ;]" ; require something other than a ; after
- ; the (...) to avoid prototypes. Can't
- ; catch cases with () inside the parentheses
- ; surrounding the parameters
- ; (like "int foo(int a=bar()) {...}"
-
- )) 6)
- ("Class"
- (, (concat
- "^" ; beginning of line is required
- "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
- "class[ \t]+"
- "\\([a-zA-Z0-9_]+\\)" ; this is the string we want to get
- "[ \t]*[:{]"
- )) 2)
-;; Example of generic expression for finding prototypes, structs, unions, enums.
-;; Uncomment if you want to find these too. It will be a bit slower gathering
-;; the indexes.
-; ("Prototypes"
-; (,
-; (concat
-; "^" ; beginning of line is required
-; "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
-; "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; type specs; there can be no
-; "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; more than 3 tokens, right?
-
-; "\\(" ; last type spec including */&
-; "[a-zA-Z0-9_:]+"
-; "\\([ \t]*[*&]+[ \t]*\\|[ \t]+\\)" ; either pointer/ref sign or whitespace
-; "\\)?" ; if there is a last type spec
-; "\\(" ; name; take that into the imenu entry
-; "[a-zA-Z0-9_:~]+" ; member function, ctor or dtor...
-; ; (may not contain * because then
-; ; "a::operator char*" would become "char*"!)
-; "\\|"
-; "\\([a-zA-Z0-9_:~]*::\\)?operator"
-; "[^a-zA-Z1-9_][^(]*" ; ...or operator
-; " \\)"
-; "[ \t]*([^)]*)[ \t\n]*;" ; require ';' after
-; ; the (...) Can't
-; ; catch cases with () inside the parentheses
-; ; surrounding the parameters
-; ; (like "int foo(int a=bar());"
-; )) 6)
-; ("Struct"
-; (, (concat
-; "^" ; beginning of line is required
-; "\\(static[ \t]+\\)?" ; there may be static or const.
-; "\\(const[ \t]+\\)?"
-; "struct[ \t]+"
-; "\\([a-zA-Z0-9_]+\\)" ; this is the string we want to get
-; "[ \t]*[{]"
-; )) 3)
-; ("Enum"
-; (, (concat
-; "^" ; beginning of line is required
-; "\\(static[ \t]+\\)?" ; there may be static or const.
-; "\\(const[ \t]+\\)?"
-; "enum[ \t]+"
-; "\\([a-zA-Z0-9_]+\\)" ; this is the string we want to get
-; "[ \t]*[{]"
-; )) 3)
-; ("Union"
-; (, (concat
-; "^" ; beginning of line is required
-; "\\(static[ \t]+\\)?" ; there may be static or const.
-; "\\(const[ \t]+\\)?"
-; "union[ \t]+"
-; "\\([a-zA-Z0-9_]+\\)" ; this is the string we want to get
-; "[ \t]*[{]"
-; )) 3)
- ))
- "Imenu generic expression for C++ mode. See `imenu-generic-expression'.")
-
-(defun c++-mode ()
- "Major mode for editing C++ code. Very much like editing C code.
-Expression and list commands understand all C++ brackets.
-Tab at left margin indents for C++ code
-Comments are delimited with /* ... */ {or with // ... <newline>}
-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.
- Default is t.
- 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:'', or
- ``public:'' or ``private:'', or ``protected:''.
- c++-electric-colon
- If non-nil at invocation of c++-mode (t is the default) colon electrically
- indents.
- c++-empty-arglist-indent
- If non-nil, a function declaration or invocation which ends a line with a
- left paren is indented this many extra spaces, instead of flush with the
- left paren.
- c++-friend-offset
- Offset of C++ friend declarations relative to member declarations.
- c++-member-init-indent
- Indentation level of member initializations in function declarations,
- if they are on a separate line beginning with a colon.
- c++-continued-member-init-offset
- Extra indentation for continuation lines of member initializations; NIL
- means to align with previous initializations rather than with the colon.
-
-Settings for K&R, BSD, and Stroustrup indentation styles are
- c-indent-level 5 8 4
- c-continued-statement-offset 5 8 4
- c-continued-brace-offset 0
- c-brace-offset -5 -8 0
- c-brace-imaginary-offset 0
- c-argdecl-indent 0 8 4
- c-label-offset -5 -8 -4
- c++-empty-arglist-indent 4
- c++-friend-offset 0
-
-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)
- ;; This code depends on the old C mode.
- (require 'c-mode)
- (use-local-map c++-mode-map)
- (set-syntax-table c++-mode-syntax-table)
- (setq major-mode 'c++-mode
- mode-name "C++"
- comment-column 32
- local-abbrev-table c++-mode-abbrev-table)
- (set (make-local-variable 'indent-line-function) 'c++-indent-line)
- (set (make-local-variable 'comment-start) "// ")
- (set (make-local-variable 'comment-end) "")
- (set (make-local-variable 'comment-start-skip) "/\\*+ *\\|// *")
- (set (make-local-variable 'comment-indent-function) 'c++-comment-indent)
- (set (make-local-variable 'paragraph-start) (concat "$\\|" page-delimiter))
- (set (make-local-variable 'paragraph-separate) paragraph-start)
- (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
- (set (make-local-variable 'require-final-newline) t)
- (set (make-local-variable 'parse-sexp-ignore-comments) t)
- (make-local-variable 'imenu-generic-expression)
- (setq imenu-generic-expression c++-imenu-generic-expression)
- (run-hooks 'c++-mode-hook)
- (if c++-electric-colon
- (define-key c++-mode-map ":" 'electric-c++-terminator)))
-
-;; 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
- ;; Leave at least one space on non-empty lines.
- (if (zerop (current-column)) 0 (1+ (current-column)))
- (let ((cur-pt (point)))
- (beginning-of-line 0)
- ;; If previous line had a comment, use its indentation.
- (if (re-search-forward comment-start-skip cur-pt t)
- (progn
- (goto-char (match-beginning 0))
- (current-column))
- comment-column)))))) ; otherwise indent at comment column.
-
-(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))))
- (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, or another colon.
- ;; So quickly rule out most other uses of colon
- ;; and do no indentation for them.
- (and (eq last-command-char ?:)
- (or (not (or (looking-at "case[ \t]")
- (save-excursion
- (forward-word 1)
- (skip-chars-forward " \t")
- (>= (point) end))))
- ;; Do re-indent double colons
- (save-excursion
- (end-of-line 1)
- (looking-at ":"))))
- (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
- ;; the new marker object, used to be just an integer
- (setq insertpos (make-marker))
- ;; changed setq to set-marker
- (set-marker insertpos (1- (point)))
- ;; do this before the newline, since in auto fill can break
- (newline)
- (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++-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 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 ((looking-at "\\(default\\|public\\|private\\|protected\\):")
- (setq indent (+ indent c-label-offset)))
- ((or (looking-at "case\\b")
- (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))))
- ((looking-at "friend\[ \t]")
- (setq indent (+ indent c++-friend-offset)))
- ((= (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 or member initialization.
- ;; Indent like the previous top level line unless
- ;; (1) the previous line ends in a closeparen without semicolon,
- ;; in which case this line is the first argument declaration or
- ;; member initialization, or
- ;; (2) the previous line begins with a colon,
- ;; in which case this is the second line of member inits.
- ;; It is assumed that arg decls and member inits are not mixed.
- (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)))
- (if (= (preceding-char) ?\))
- (progn ; first arg decl or member init
- (goto-char indent-point)
- (skip-chars-forward " \t")
- (if (= (following-char) ?:)
- c++-member-init-indent
- c-argdecl-indent))
- (if (= (preceding-char) ?\;)
- (backward-char 1))
- (if (= (preceding-char) ?})
- 0
- (if (= (preceding-char) ?\))
- (forward-list -1))
- (beginning-of-line) ; continued arg decls or member inits
- (skip-chars-forward " \t")
- (if (= (following-char) ?:)
- (if c++-continued-member-init-offset
- (+ (current-indentation)
- c++-continued-member-init-offset)
- (progn
- (forward-char 1)
- (skip-chars-forward " \t")
- (current-column)))
- (current-indentation)))
- )))
- ((/= (char-after containing-sexp) ?{)
- ;; line is expression, not statement:
- ;; indent to just after the surrounding open -- unless
- ;; empty arg list, in which case we do what
- ;; c++-empty-arglist-indent says to do.
- (if (and c++-empty-arglist-indent
- (or (null (nth 2 state)) ;; indicates empty arg
- ;; list.
- ;; Use a heuristic: if the first
- ;; non-whitespace following left paren on
- ;; same line is not a comment,
- ;; is not an empty arglist.
- (save-excursion
- (goto-char (1+ containing-sexp))
- (not
- (looking-at "\\( \\|\t\\)*[^/\n]")))))
- (progn
- (goto-char containing-sexp)
- (beginning-of-line)
- (skip-chars-forward " \t")
- (goto-char (min (+ (point) c++-empty-arglist-indent)
- (1+ containing-sexp)))
- (current-column))
- ;; In C-mode, we would always indent to one after the
- ;; left paren. Here, though, we may have an
- ;; empty-arglist, so we'll indent to the min of that
- ;; and the beginning of the first argument.
- (goto-char (1+ containing-sexp))
- (current-column)))
- (t
- ;; Statement. Find previous non-comment character.
- (goto-char indent-point)
- (c++-backward-to-noncomment containing-sexp)
- (if (and (not (memq (preceding-char) '(0 ?\, ?\; ?\} ?\{)))
- ;; But don't treat a line with a close-brace
- ;; as a continuation. It is probably the
- ;; end of an enum type declaration.
- (save-excursion
- (goto-char indent-point)
- (skip-chars-forward " \t")
- (not (= (following-char) ?}))))
- ;; 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
- (concat
- "#\\|/\\*\\|//"
- "\\|case[ \t]"
- "\\|[a-zA-Z0-9_$]*:[^:]"
- "\\|friend[ \t]")))
- ;; Skip over comments and labels following openbrace.
- (cond ((= (following-char) ?\#)
- (forward-line 1))
- ((looking-at "/\\*")
- (search-forward "*/" nil 'move))
- ((looking-at "//\\|friend[ \t]")
- (forward-line 1))
- (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 prev stmt starts with open-brace, that
- ;; open brace was offset by c-brace-offset.
- ;; Compensate to get the column where
- ;; an ordinary statement would start.
- (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-offset 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 c++-backward-to-noncomment (lim)
- (let (opoint stop)
- (while (not stop)
- (skip-chars-backward " \t\n\r\f" lim)
- (setq opoint (point))
- (cond ((and (>= (point) (+ 2 lim))
- (save-excursion
- (forward-char -2)
- (looking-at "\\*/")))
- (search-backward "/*" lim 'move))
- ((and
- (search-backward "//" (max (c++-point-bol) lim) 'move)
- (not (c++-within-string-p (point) opoint))))
- ;; No comment to be found.
- ;; If there's a # command on this line,
- ;; move back to it.
- (t (beginning-of-line)
- (skip-chars-forward " \t")
- ;; But don't get fooled if we are already before the #.
- (if (and (looking-at "#") (< (point) opoint))
- (setq stop (<= (point) lim))
- (setq stop t)
- (goto-char opoint)))))))
-
-(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 last-depth
- 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.
- nil
- ;; Just started a new nesting level.
- ;; Compute the standard indent for this level.
- (let (val)
- (if (= (char-after (car contain-stack)) ?{)
- (save-excursion
- (goto-char (car contain-stack))
- (setq val (calculate-c-indent-after-brace)))
- (setq val (calculate-c++-indent
- (if (car indent-stack)
- (- (car indent-stack))))))
- (setcar indent-stack val)))
- ;; Adjust line indentation according to its predecessor.
- (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))))))
- ;; Adjust line indentation according to its contents
- (if (looking-at "\\(public\\|private\\|protected\\):")
- (setq this-indent (- this-indent c-indent-level))
- (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 (looking-at "friend[ \t]")
- (setq this-indent (+ this-indent c++-friend-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))))))))))
-
-(defun fill-c++-comment ()
- "Fill a comment contained in consecutive lines containing point.
-The fill lines remain a comment."
- (interactive)
- (save-excursion
- (let ((save fill-prefix))
- (beginning-of-line 1)
- (save-excursion
- (re-search-forward comment-start-skip
- (save-excursion (end-of-line) (point))
- t)
- (goto-char (match-end 0))
- (set-fill-prefix))
- (while (looking-at fill-prefix)
- (previous-line 1))
- (next-line 1)
- (insert-string "\n")
- (fill-paragraph nil)
- (delete-char -1)
- (setq fill-prefix save))))
-
-(defun c++-point-bol ()
- "Returns the value of the point at the beginning of the current line."
- (save-excursion
- (beginning-of-line)
- (point)))
-
-;; (defun c++-insert-header ()
-;; "Insert header denoting C++ code at top of buffer."
-;; (interactive)
-;; (save-excursion
-;; (goto-char (point-min))
-;; (insert "// "
-;; "This may look like C code, but it is really "
-;; "-*- C++ -*-"
-;; "\n\n")))
-
-(defun c++-within-string-p (point1 point2)
- "Returns true if number of double quotes between two points is odd."
- (let ((s (buffer-substring point1 point2)))
- (not (zerop (% (c++-count-char-in-string ?\" s) 2)))))
-
-(defun c++-count-char-in-string (c s)
- (let ((count 0)
- (pos 0))
- (while (< pos (length s))
- (setq count (+ count (if (\= (aref s pos) c) 1 0)))
- (setq pos (1+ pos)))
- count))
-
-;; rms: This page is creeping featurism, and not worth having.
-
-;;; Below are two regular expressions that attempt to match defuns
-;;; "strongly" and "weakly." The strong one almost reconstructs the
-;;; grammar of C++; the weak one just figures anything id or curly on
-;;; the left begins a defun. The constant "c++-match-header-strongly"
-;;; determines which to use; the default is the weak one.
-
-;; (defvar c++-match-header-strongly nil
-;; "*If nil, use `c++-defun-header-weak' to identify beginning of definitions.
-;; If non-nil, use `c++-defun-header-strong'.")
-;;
-;; (defvar c++-defun-header-strong-struct-equivs "\\(class\\|struct\\|enum\\)"
-;; "Regexp to match names of structure declaration blocks in C++.")
-;;
-;; (defconst c++-defun-header-strong
-;; (let*
-;; (; valid identifiers
-;; ;; There's a real weirdness here -- if I switch the below
-;; (id "\\(\\w\\|_\\)+")
-;; ;; to be
-;; ;; (id "\\(_\\|\\w\\)+")
-;; ;; things no longer work right. Try it and see!
-;;
-;; ; overloadable operators
-;; (op-sym1
-;; "[-+*/%^&|~!=<>]\\|[-+*/%^&|<>=!]=\\|<<=?\\|>>=?")
-;; (op-sym2
-;; "&&\\|||\\|\\+\\+\\|--\\|()\\|\\[\\]")
-;; (op-sym (concat "\\(" op-sym1 "\\|" op-sym2 "\\)"))
-;; ; whitespace
-;; (middle "[^\\*]*\\(\\*+[^/\\*][^\\*]*\\)*")
-;; (c-comment (concat "/\\*" middle "\\*+/"))
-;; (wh (concat "\\(\\s \\|\n\\|//.*$\\|" c-comment "\\)"))
-;; (wh-opt (concat wh "*"))
-;; (wh-nec (concat wh "+"))
-;; (oper (concat "\\(" "operator" "\\("
-;; wh-opt op-sym "\\|" wh-nec id "\\)" "\\)"))
-;; (dcl-list "([^():]*)")
-;; (func-name (concat "\\(" oper "\\|" id "::" id "\\|" id "\\)"))
-;; (inits
-;; (concat "\\(:"
-;; "\\(" wh-opt id "(.*\\()" wh-opt "," "\\)\\)*"
-;; wh-opt id "(.*)" wh-opt "{"
-;; "\\|" wh-opt "{\\)"))
-;; (type-name (concat
-;; "\\(" c++-defun-header-strong-struct-equivs wh-nec "\\)?"
-;; id))
-;; (type (concat "\\(const" wh-nec "\\)?"
-;; "\\(" type-name "\\|" type-name wh-opt "\\*+" "\\|"
-;; type-name wh-opt "&" "\\)"))
-;; (modifier "\\(inline\\|virtual\\|overload\\|auto\\|static\\)")
-;; (modifiers (concat "\\(" modifier wh-nec "\\)*"))
-;; (func-header
-;; ;; type arg-dcl
-;; (concat modifiers type wh-nec func-name wh-opt dcl-list wh-opt inits))
-;; (inherit (concat "\\(:" wh-opt "\\(public\\|private\\)?"
-;; wh-nec id "\\)"))
-;; (cs-header (concat
-;; c++-defun-header-strong-struct-equivs
-;; wh-nec id wh-opt inherit "?" wh-opt "{")))
-;; (concat "^\\(" func-header "\\|" cs-header "\\)"))
-;; "Strongly-defined regexp to match beginning of structure or function def.")
-;;
-;;
-;; ;; This part has to do with recognizing defuns.
-;;
-;; ;; The weak convention we will use is that a defun begins any time
-;; ;; there is a left curly brace, or some identifier on the left margin,
-;; ;; followed by a left curly somewhere on the line. (This will also
-;; ;; incorrectly match some continued strings, but this is after all
-;; ;; just a weak heuristic.) Suggestions for improvement (short of the
-;; ;; strong scheme shown above) are welcomed.
-;;
-;; (defconst c++-defun-header-weak "^{\\|^[_a-zA-Z].*{"
-;; "Weakly-defined regexp to match beginning of structure or function def.")
-;;
-;; (defun c++-beginning-of-defun (arg)
-;; (interactive "p")
-;; (let ((c++-defun-header (if c++-match-header-strongly
-;; c++-defun-header-strong
-;; c++-defun-header-weak)))
-;; (cond ((or (= arg 0) (and (> arg 0) (bobp))) nil)
-;; ((and (not (looking-at c++-defun-header))
-;; (let ((curr-pos (point))
-;; (open-pos (if (search-forward "{" nil 'move)
-;; (point)))
-;; (beg-pos
-;; (if (re-search-backward c++-defun-header nil 'move)
-;; (match-beginning 0))))
-;; (if (and open-pos beg-pos
-;; (< beg-pos curr-pos)
-;; (> open-pos curr-pos))
-;; (progn
-;; (goto-char beg-pos)
-;; (if (= arg 1) t nil));; Are we done?
-;; (goto-char curr-pos)
-;; nil))))
-;; (t
-;; (if (and (looking-at c++-defun-header) (not (bobp)))
-;; (forward-char (if (< arg 0) 1 -1)))
-;; (and (re-search-backward c++-defun-header nil 'move (or arg 1))
-;; (goto-char (match-beginning 0)))))))
-;;
-;;
-;; (defun c++-end-of-defun (arg)
-;; (interactive "p")
-;; (let ((c++-defun-header (if c++-match-header-strongly
-;; c++-defun-header-strong
-;; c++-defun-header-weak)))
-;; (if (and (eobp) (> arg 0))
-;; nil
-;; (if (and (> arg 0) (looking-at c++-defun-header)) (forward-char 1))
-;; (let ((pos (point)))
-;; (c++-beginning-of-defun
-;; (if (< arg 0)
-;; (- (- arg (if (eobp) 0 1)))
-;; arg))
-;; (if (and (< arg 0) (bobp))
-;; t
-;; (if (re-search-forward c++-defun-header nil 'move)
-;; (progn (forward-char -1)
-;; (forward-sexp)
-;; (beginning-of-line 2)))
-;; (if (and (= pos (point))
-;; (re-search-forward c++-defun-header nil 'move))
-;; (c++-end-of-defun 1))))
-;; t)))
-;;
-;; (defun c++-indent-defun ()
-;; "Indents the current function definition, struct or class declaration."
-;; (interactive)
-;; (let ((restore (point)))
-;; (c++-end-of-defun 1)
-;; (beginning-of-line 1)
-;; (let ((end (point)))
-;; (c++-beginning-of-defun 1)
-;; (while (<= (point) end)
-;; (c++-indent-line)
-;; (next-line 1)
-;; (beginning-of-line 1)))
-;; (goto-char restore)))
-
-;;; cplus-md.el ends here
diff --git a/lisp/progmodes/cpp.el b/lisp/progmodes/cpp.el
deleted file mode 100644
index fa0ed911e2e..00000000000
--- a/lisp/progmodes/cpp.el
+++ /dev/null
@@ -1,782 +0,0 @@
-;;; cpp.el --- Highlight or hide text according to cpp conditionals.
-
-;; Copyright (C) 1994, 1995 Free Software Foundation
-
-;; Author: Per Abrahamsen <abraham@iesd.auc.dk>
-;; Keywords: c, faces, tools
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Parse a text for C preprocessor conditionals, and highlight or hide
-;; the text inside the conditionals as you wish.
-
-;; This package is inspired by Jim Coplien's delta editor for SCCS.
-
-;;; Todo:
-
-;; Should parse "#if" and "#elif" expressions and merge the faces
-;; somehow.
-
-;; Somehow it is sometimes possible to make changes near a read only
-;; area which you can't undo. Their are other strange effects in that
-;; area.
-
-;; The Edit buffer should -- optionally -- appear in its own frame.
-
-;; Conditionals seem to be rear-sticky. They shouldn't be.
-
-;; Restore window configurations when exiting CPP Edit buffer.
-
-;;; Code:
-
-;;; Customization:
-
-(defvar cpp-config-file (convert-standard-filename ".cpp.el")
- "*File name to save cpp configuration.")
-
-(defvar cpp-known-face 'invisible
- "*Face used for known cpp symbols.")
-
-(defvar cpp-unknown-face 'highlight
- "*Face used for unknown cpp symbols.")
-
-(defvar cpp-face-type 'light
- "*Indicate what background face type you prefer.
-Can be either light or dark for color screens, mono for monochrome
-screens, and none if you don't use a window system.")
-
-(defvar cpp-known-writable t
- "*Non-nil means you are allowed to modify the known conditionals.")
-
-(defvar cpp-unknown-writable t
- "*Non-nil means you are allowed to modify the unknown conditionals.")
-
-(defvar cpp-edit-list nil
- "Alist of cpp macros and information about how they should be displayed.
-Each entry is a list with the following elements:
-0. The name of the macro (a string).
-1. Face used for text that is `ifdef' the macro.
-2. Face used for text that is `ifndef' the macro.
-3. `t', `nil', or `both' depending on what text may be edited.")
-
-(defvar cpp-overlay-list nil)
-;; List of cpp overlays active in the current buffer.
-(make-variable-buffer-local 'cpp-overlay-list)
-
-(defvar cpp-callback-data)
-(defvar cpp-state-stack)
-
-(defconst cpp-face-type-list
- '(("light color background" . light)
- ("dark color background" . dark)
- ("monochrome" . mono)
- ("tty" . none))
- "Alist of strings and names of the defined face collections.")
-
-(defconst cpp-writable-list
- ;; Names used for the writable property.
- '(("writable" . t)
- ("read-only" . nil)))
-
-(defvar cpp-button-event nil)
-;; This will be t in the callback for `cpp-make-button'.
-
-(defvar cpp-edit-buffer nil)
-;; Real buffer whose cpp display information we are editing.
-(make-variable-buffer-local 'cpp-edit-buffer)
-
-(defconst cpp-branch-list
- ;; Alist of branches.
- '(("false" . nil)
- ("true" . t)
- ("both" . both)))
-
-(defvar cpp-face-default-list nil
- "List of faces you can choose from for cpp conditionals.")
-
-(defvar cpp-face-light-name-list
- '("light gray" "light blue" "light cyan" "light yellow" "light pink"
- "pale green" "beige" "orange" "magenta" "violet" "medium purple"
- "turquoise")
- "Background colours useful with dark foreground colors.")
-
-(defvar cpp-face-dark-name-list
- '("dim gray" "blue" "cyan" "yellow" "red"
- "dark green" "brown" "dark orange" "dark khaki" "dark violet" "purple"
- "dark turquoise")
- "Background colours useful with light foreground colors.")
-
-(defvar cpp-face-light-list nil
- "Alist of names and faces to be used for light backgrounds.")
-
-(defvar cpp-face-dark-list nil
- "Alist of names and faces to be used for dark backgrounds.")
-
-(defvar cpp-face-mono-list
- '(("bold" . 'bold)
- ("bold-italic" . 'bold-italic)
- ("italic" . 'italic)
- ("underline" . 'underline))
- "Alist of names and faces to be used for monochrome screens.")
-
-(defvar cpp-face-none-list
- '(("default" . default)
- ("invisible" . invisible))
- "Alist of names and faces available even if you don't use a window system.")
-
-(defvar cpp-face-all-list
- (append cpp-face-light-list
- cpp-face-dark-list
- cpp-face-mono-list
- cpp-face-none-list)
- "All faces used for highlighting text inside cpp conditionals.")
-
-;;; Parse Buffer:
-
-(defvar cpp-parse-symbols nil
- "List of cpp macros used in the local buffer.")
-(make-variable-buffer-local 'cpp-parse-symbols)
-
-(defconst cpp-parse-regexp
- ;; Regexp matching all tokens needed to find conditionals.
- (concat
- "'\\|\"\\|/\\*\\|//\\|"
- "\\(^[ \t]*#[ \t]*\\(ifdef\\|ifndef\\|if\\|"
- "elif\\|else\\|endif\\)\\b\\)"))
-
-;;;###autoload
-(defun cpp-highlight-buffer (arg)
- "Highlight C code according to preprocessor conditionals.
-This command pops up a buffer which you should edit to specify
-what kind of highlighting to use, and the criteria for highlighting.
-A prefix arg suppresses display of that buffer."
- (interactive "P")
- (setq cpp-parse-symbols nil)
- (cpp-parse-reset)
- (if (null cpp-edit-list)
- (cpp-edit-load))
- (let (cpp-state-stack)
- (save-excursion
- (goto-char (point-min))
- (cpp-progress-message "Parsing...")
- (while (re-search-forward cpp-parse-regexp nil t)
- (cpp-progress-message "Parsing...%d%%"
- (/ (* 100 (- (point) (point-min))) (buffer-size)))
- (let ((match (buffer-substring (match-beginning 0) (match-end 0))))
- (cond ((or (string-equal match "'")
- (string-equal match "\""))
- (goto-char (match-beginning 0))
- (condition-case nil
- (forward-sexp)
- (error (cpp-parse-error
- "Unterminated string or character"))))
- ((string-equal match "/*")
- (or (search-forward "*/" nil t)
- (error "Unterminated comment")))
- ((string-equal match "//")
- (skip-chars-forward "^\n\r"))
- (t
- (end-of-line 1)
- (let ((from (match-beginning 1))
- (to (1+ (point)))
- (type (buffer-substring (match-beginning 2)
- (match-end 2)))
- (expr (buffer-substring (match-end 1) (point))))
- (cond ((string-equal type "ifdef")
- (cpp-parse-open t expr from to))
- ((string-equal type "ifndef")
- (cpp-parse-open nil expr from to))
- ((string-equal type "if")
- (cpp-parse-open t expr from to))
- ((string-equal type "elif")
- (let (cpp-known-face cpp-unknown-face)
- (cpp-parse-close from to))
- (cpp-parse-open t expr from to))
- ((string-equal type "else")
- (or cpp-state-stack
- (cpp-parse-error "Top level #else"))
- (let ((entry (list (not (nth 0 (car cpp-state-stack)))
- (nth 1 (car cpp-state-stack))
- from to)))
- (cpp-parse-close from to)
- (setq cpp-state-stack (cons entry cpp-state-stack))))
- ((string-equal type "endif")
- (cpp-parse-close from to))
- (t
- (cpp-parse-error "Parser error"))))))))
- (message "Parsing...done"))
- (if cpp-state-stack
- (save-excursion
- (goto-char (nth 3 (car cpp-state-stack)))
- (cpp-parse-error "Unclosed conditional"))))
- (or arg
- (null cpp-parse-symbols)
- (cpp-parse-edit)))
-
-(defun cpp-parse-open (branch expr begin end)
- "Push information about conditional-beginning onto `cpp-state-stack'."
- ;; Discard comments within this line.
- (while (string-match "\\b[ \t]*/\\*.*\\*/[ \t]*\\b" expr)
- (setq expr (concat (substring expr 0 (match-beginning 0))
- (substring expr (match-end 0)))))
- ;; If a comment starts on this line and continues past, discard it.
- (if (string-match "\\b[ \t]*/\\*" expr)
- (setq expr (substring expr 0 (match-beginning 0))))
- ;; Delete any C++ comment from the line.
- (if (string-match "\\b[ \t]*\\(//.*\\)?$" expr)
- (setq expr (substring expr 0 (match-beginning 0))))
- (while (string-match "[ \t]+" expr)
- (setq expr (concat (substring expr 0 (match-beginning 0))
- (substring expr (match-end 0)))))
- (setq cpp-state-stack (cons (list branch expr begin end) cpp-state-stack))
- (or (member expr cpp-parse-symbols)
- (setq cpp-parse-symbols
- (cons expr cpp-parse-symbols)))
- (if (assoc expr cpp-edit-list)
- (cpp-make-known-overlay begin end)
- (cpp-make-unknown-overlay begin end)))
-
-(defun cpp-parse-close (from to)
- ;; Pop top of cpp-state-stack and create overlay.
- (let ((entry (assoc (nth 1 (car cpp-state-stack)) cpp-edit-list))
- (branch (nth 0 (car cpp-state-stack)))
- (begin (nth 2 (car cpp-state-stack)))
- (end (nth 3 (car cpp-state-stack))))
- (setq cpp-state-stack (cdr cpp-state-stack))
- (if entry
- (let ((face (nth (if branch 1 2) entry))
- (read-only (eq (not branch) (nth 3 entry)))
- (priority (length cpp-state-stack))
- (overlay (make-overlay end from)))
- (cpp-make-known-overlay from to)
- (setq cpp-overlay-list (cons overlay cpp-overlay-list))
- (if priority (overlay-put overlay 'priority priority))
- (cond ((eq face 'invisible)
- (cpp-make-overlay-hidden overlay))
- ((eq face 'default))
- (t
- (overlay-put overlay 'face face)))
- (if read-only
- (cpp-make-overlay-read-only overlay)
- (cpp-make-overlay-sticky overlay)))
- (cpp-make-unknown-overlay from to))))
-
-(defun cpp-parse-error (error)
- ;; Error message issued by the cpp parser.
- (error "%s at line %d" error (count-lines (point-min) (point))))
-
-(defun cpp-parse-reset ()
- "Reset display of cpp conditionals to normal."
- (interactive)
- (while cpp-overlay-list
- (delete-overlay (car cpp-overlay-list))
- (setq cpp-overlay-list (cdr cpp-overlay-list))))
-
-;;;###autoload
-(defun cpp-parse-edit ()
- "Edit display information for cpp conditionals."
- (interactive)
- (or cpp-parse-symbols
- (cpp-highlight-buffer t))
- (let ((buffer (current-buffer)))
- (pop-to-buffer "*CPP Edit*")
- (cpp-edit-mode)
- (setq cpp-edit-buffer buffer)
- (cpp-edit-reset)))
-
-;;; Overlays:
-
-(defun cpp-make-known-overlay (start end)
- ;; Create an overlay for a known cpp command from START to END.
- (let ((overlay (make-overlay start end)))
- (if (eq cpp-known-face 'invisible)
- (cpp-make-overlay-hidden overlay)
- (or (eq cpp-known-face 'default)
- (overlay-put overlay 'face cpp-known-face))
- (if cpp-known-writable
- ()
- (overlay-put overlay 'modification-hooks '(cpp-signal-read-only))
- (overlay-put overlay 'insert-in-front-hooks '(cpp-signal-read-only))))
- (setq cpp-overlay-list (cons overlay cpp-overlay-list))))
-
-(defun cpp-make-unknown-overlay (start end)
- ;; Create an overlay for an unknown cpp command from START to END.
- (let ((overlay (make-overlay start end)))
- (cond ((eq cpp-unknown-face 'invisible)
- (cpp-make-overlay-hidden overlay))
- ((eq cpp-unknown-face 'default))
- (t
- (overlay-put overlay 'face cpp-unknown-face)))
- (if cpp-unknown-writable
- ()
- (overlay-put overlay 'modification-hooks '(cpp-signal-read-only))
- (overlay-put overlay 'insert-in-front-hooks '(cpp-signal-read-only)))
- (setq cpp-overlay-list (cons overlay cpp-overlay-list))))
-
-(defun cpp-make-overlay-hidden (overlay)
- ;; Make overlay hidden and intangible.
- (overlay-put overlay 'invisible t)
- (overlay-put overlay 'intangible t)
- ;; Unfortunately `intangible' is not implemented for overlays yet,
- ;; so we make is read-only instead.
- (overlay-put overlay 'modification-hooks '(cpp-signal-read-only))
- (overlay-put overlay 'insert-in-front-hooks '(cpp-signal-read-only)))
-
-(defun cpp-make-overlay-read-only (overlay)
- ;; Make overlay read only.
- (overlay-put overlay 'modification-hooks '(cpp-signal-read-only))
- (overlay-put overlay 'insert-in-front-hooks '(cpp-signal-read-only))
- (overlay-put overlay 'insert-behind-hooks '(cpp-signal-read-only)))
-
-(defun cpp-make-overlay-sticky (overlay)
- ;; Make OVERLAY grow when you insert text at either end.
- (overlay-put overlay 'insert-in-front-hooks '(cpp-grow-overlay))
- (overlay-put overlay 'insert-behind-hooks '(cpp-grow-overlay)))
-
-(defun cpp-signal-read-only (overlay after start end &optional len)
- ;; Only allow deleting the whole overlay.
- ;; Trying to change a read-only overlay.
- (if (and (not after)
- (or (< (overlay-start overlay) start)
- (> (overlay-end overlay) end)))
- (error "This text is read only")))
-
-(defun cpp-grow-overlay (overlay after start end &optional len)
- ;; Make OVERLAY grow to contain range START to END.
- (if after
- (move-overlay overlay
- (min start (overlay-start overlay))
- (max end (overlay-end overlay)))))
-
-;;; Edit Buffer:
-
-(defvar cpp-edit-map nil)
-;; Keymap for `cpp-edit-mode'.
-
-(if cpp-edit-map
- ()
- (setq cpp-edit-map (make-keymap))
- (suppress-keymap cpp-edit-map)
- (define-key cpp-edit-map [ down-mouse-2 ] 'cpp-push-button)
- (define-key cpp-edit-map [ mouse-2 ] 'ignore)
- (define-key cpp-edit-map " " 'scroll-up)
- (define-key cpp-edit-map "\C-?" 'scroll-down)
- (define-key cpp-edit-map [ delete ] 'scroll-down)
- (define-key cpp-edit-map "\C-c\C-c" 'cpp-edit-apply)
- (define-key cpp-edit-map "a" 'cpp-edit-apply)
- (define-key cpp-edit-map "A" 'cpp-edit-apply)
- (define-key cpp-edit-map "r" 'cpp-edit-reset)
- (define-key cpp-edit-map "R" 'cpp-edit-reset)
- (define-key cpp-edit-map "s" 'cpp-edit-save)
- (define-key cpp-edit-map "S" 'cpp-edit-save)
- (define-key cpp-edit-map "l" 'cpp-edit-load)
- (define-key cpp-edit-map "L" 'cpp-edit-load)
- (define-key cpp-edit-map "h" 'cpp-edit-home)
- (define-key cpp-edit-map "H" 'cpp-edit-home)
- (define-key cpp-edit-map "b" 'cpp-edit-background)
- (define-key cpp-edit-map "B" 'cpp-edit-background)
- (define-key cpp-edit-map "k" 'cpp-edit-known)
- (define-key cpp-edit-map "K" 'cpp-edit-known)
- (define-key cpp-edit-map "u" 'cpp-edit-unknown)
- (define-key cpp-edit-map "u" 'cpp-edit-unknown)
- (define-key cpp-edit-map "t" 'cpp-edit-true)
- (define-key cpp-edit-map "T" 'cpp-edit-true)
- (define-key cpp-edit-map "f" 'cpp-edit-false)
- (define-key cpp-edit-map "F" 'cpp-edit-false)
- (define-key cpp-edit-map "w" 'cpp-edit-write)
- (define-key cpp-edit-map "W" 'cpp-edit-write)
- (define-key cpp-edit-map "X" 'cpp-edit-toggle-known)
- (define-key cpp-edit-map "x" 'cpp-edit-toggle-known)
- (define-key cpp-edit-map "Y" 'cpp-edit-toggle-unknown)
- (define-key cpp-edit-map "y" 'cpp-edit-toggle-unknown)
- (define-key cpp-edit-map "q" 'bury-buffer)
- (define-key cpp-edit-map "Q" 'bury-buffer))
-
-(defvar cpp-edit-symbols nil)
-;; Symbols defined in the edit buffer.
-(make-variable-buffer-local 'cpp-edit-symbols)
-
-(defun cpp-edit-mode ()
- "Major mode for editing the criteria for highlighting cpp conditionals.
-Click on objects to change them.
-You can also use the keyboard accelerators indicated like this: [K]ey."
- (kill-all-local-variables)
- (buffer-disable-undo)
- (auto-save-mode -1)
- (setq buffer-read-only t)
- (setq major-mode 'cpp-edit-mode)
- (setq mode-name "CPP Edit")
- (use-local-map cpp-edit-map))
-
-(defun cpp-edit-apply ()
- "Apply edited display information to original buffer."
- (interactive)
- (cpp-edit-home)
- (cpp-highlight-buffer t))
-
-(defun cpp-edit-reset ()
- "Reset display information from original buffer."
- (interactive)
- (let ((buffer (current-buffer))
- (buffer-read-only nil)
- (start (window-start))
- (pos (point))
- symbols)
- (set-buffer cpp-edit-buffer)
- (setq symbols cpp-parse-symbols)
- (set-buffer buffer)
- (setq cpp-edit-symbols symbols)
- (erase-buffer)
- (insert "CPP Display Information for `")
- (cpp-make-button (buffer-name cpp-edit-buffer) 'cpp-edit-home)
- (insert "\n\nClick mouse-2 on item you want to change or use\n"
- "or switch to this buffer and type the keyboard equivalents.\n"
- "Keyboard equivalents are indicated with brackets like [T]his.\n\n")
- (cpp-make-button "[H]ome (display the C file)" 'cpp-edit-home)
- (insert " ")
- (cpp-make-button "[A]pply new settings" 'cpp-edit-apply)
- (insert "\n")
- (cpp-make-button "[S]ave settings" 'cpp-edit-save)
- (insert " ")
- (cpp-make-button "[L]oad settings" 'cpp-edit-load)
- (insert "\n\n")
-
- (insert "[B]ackground: ")
- (cpp-make-button (car (rassq cpp-face-type cpp-face-type-list))
- 'cpp-edit-background)
- (insert "\n[K]nown conditionals: ")
- (cpp-make-button (cpp-face-name cpp-known-face)
- 'cpp-edit-known nil t)
- (insert " [X] ")
- (cpp-make-button (car (rassq cpp-known-writable cpp-writable-list))
- 'cpp-edit-toggle-known)
- (insert "\n[U]nknown conditionals: ")
- (cpp-make-button (cpp-face-name cpp-unknown-face)
- 'cpp-edit-unknown nil t)
- (insert " [Y] ")
- (cpp-make-button (car (rassq cpp-unknown-writable cpp-writable-list))
- 'cpp-edit-toggle-unknown)
- (insert (format "\n\n\n%39s: %14s %14s %7s\n\n" "Expression"
- "[T]rue Face" "[F]alse Face" "[W]rite"))
- (while symbols
- (let* ((symbol (car symbols))
- (entry (assoc symbol cpp-edit-list))
- (true (nth 1 entry))
- (false (nth 2 entry))
- (write (if entry (nth 3 entry) 'both)))
- (setq symbols (cdr symbols))
-
- (if (and entry ; Make default entries unknown.
- (or (null true) (eq true 'default))
- (or (null false) (eq false 'default))
- (eq write 'both))
- (setq cpp-edit-list (delq entry cpp-edit-list)
- entry nil))
-
- (if (> (length symbol) 39)
- (insert (substring symbol 0 39) ": ")
- (insert (format "%39s: " symbol)))
-
- (cpp-make-button (cpp-face-name true)
- 'cpp-edit-true symbol t 14)
- (insert " ")
- (cpp-make-button (cpp-face-name false)
- 'cpp-edit-false symbol t 14)
- (insert " ")
- (cpp-make-button (car (rassq write cpp-branch-list))
- 'cpp-edit-write symbol nil 6)
- (insert "\n")))
- (insert "\n\n")
- (set-window-start nil start)
- (goto-char pos)))
-
-(defun cpp-edit-load ()
- "Load cpp configuration."
- (interactive)
- (cond ((null init-file-user)
- ;; If -q was specified, don't load any init files.
- nil)
- ((file-readable-p cpp-config-file)
- (load-file cpp-config-file))
- ((file-readable-p (concat "~/" cpp-config-file))
- (load-file cpp-config-file)))
- (if (eq major-mode 'cpp-edit-mode)
- (cpp-edit-reset)))
-
-(defun cpp-edit-save ()
- "Save the current cpp configuration in a file."
- (interactive)
- (require 'pp)
- (save-excursion
- (set-buffer cpp-edit-buffer)
- (let ((buffer (find-file-noselect cpp-config-file)))
- (set-buffer buffer)
- (erase-buffer)
- (pp (list 'setq 'cpp-known-face
- (list 'quote cpp-known-face)) buffer)
- (pp (list 'setq 'cpp-unknown-face
- (list 'quote cpp-unknown-face)) buffer)
- (pp (list 'setq 'cpp-face-type
- (list 'quote cpp-face-type)) buffer)
- (pp (list 'setq 'cpp-known-writable
- (list 'quote cpp-known-writable)) buffer)
- (pp (list 'setq 'cpp-unknown-writable
- (list 'quote cpp-unknown-writable)) buffer)
- (pp (list 'setq 'cpp-edit-list
- (list 'quote cpp-edit-list)) buffer)
- (write-file cpp-config-file))))
-
-(defun cpp-edit-home ()
- "Switch back to original buffer."
- (interactive)
- (if cpp-button-event
- (read-event))
- (pop-to-buffer cpp-edit-buffer))
-
-(defun cpp-edit-background ()
- "Change default face collection."
- (interactive)
- (call-interactively 'cpp-choose-default-face)
- (cpp-edit-reset))
-
-(defun cpp-edit-known ()
- "Select default for known conditionals."
- (interactive)
- (setq cpp-known-face (cpp-choose-face "Known face" cpp-known-face))
- (cpp-edit-reset))
-
-(defun cpp-edit-unknown ()
- "Select default for unknown conditionals."
- (interactive)
- (setq cpp-unknown-face (cpp-choose-face "Unknown face" cpp-unknown-face))
- (cpp-edit-reset))
-
-(defun cpp-edit-toggle-known (arg)
- "Toggle writable status for known conditionals.
-With optional argument ARG, make them writable iff ARG is positive."
- (interactive "@P")
- (if (or (and (null arg) cpp-known-writable)
- (<= (prefix-numeric-value arg) 0))
- (setq cpp-known-writable nil)
- (setq cpp-known-writable t))
- (cpp-edit-reset))
-
-(defun cpp-edit-toggle-unknown (arg)
- "Toggle writable status for unknown conditionals.
-With optional argument ARG, make them writable iff ARG is positive."
- (interactive "@P")
- (if (or (and (null arg) cpp-unknown-writable)
- (<= (prefix-numeric-value arg) 0))
- (setq cpp-unknown-writable nil)
- (setq cpp-unknown-writable t))
- (cpp-edit-reset))
-
-(defun cpp-edit-true (symbol face)
- "Select SYMBOL's true FACE used for highlighting taken conditionals."
- (interactive
- (let ((symbol (cpp-choose-symbol)))
- (list symbol
- (cpp-choose-face "True face"
- (nth 1 (assoc symbol cpp-edit-list))))))
- (setcar (nthcdr 1 (cpp-edit-list-entry-get-or-create symbol)) face)
- (cpp-edit-reset))
-
-(defun cpp-edit-false (symbol face)
- "Select SYMBOL's false FACE used for highlighting untaken conditionals."
- (interactive
- (let ((symbol (cpp-choose-symbol)))
- (list symbol
- (cpp-choose-face "False face"
- (nth 2 (assoc symbol cpp-edit-list))))))
- (setcar (nthcdr 2 (cpp-edit-list-entry-get-or-create symbol)) face)
- (cpp-edit-reset))
-
-(defun cpp-edit-write (symbol branch)
- "Set which branches of SYMBOL should be writable to BRANCH.
-BRANCH should be either nil (false branch), t (true branch) or 'both."
- (interactive (list (cpp-choose-symbol) (cpp-choose-branch)))
- (setcar (nthcdr 3 (cpp-edit-list-entry-get-or-create symbol)) branch)
- (cpp-edit-reset))
-
-(defun cpp-edit-list-entry-get-or-create (symbol)
- ;; Return the entry for SYMBOL in `cpp-edit-list'.
- ;; If it does not exist, create it.
- (let ((entry (assoc symbol cpp-edit-list)))
- (or entry
- (setq entry (list symbol nil nil 'both nil)
- cpp-edit-list (cons entry cpp-edit-list)))
- entry))
-
-;;; Prompts:
-
-(defun cpp-choose-symbol ()
- ;; Choose a symbol if called from keyboard, otherwise use the one clicked on.
- (if cpp-button-event
- cpp-callback-data
- (completing-read "Symbol: " (mapcar 'list cpp-edit-symbols) nil t)))
-
-(defun cpp-choose-branch ()
- ;; Choose a branch, either nil, t, or both.
- (if cpp-button-event
- (x-popup-menu cpp-button-event
- (list "Branch" (cons "Branch" cpp-branch-list)))
- (cdr (assoc (completing-read "Branch: " cpp-branch-list nil t)
- cpp-branch-list))))
-
-(defun cpp-choose-face (prompt default)
- ;; Choose a face from cpp-face-defalt-list.
- ;; PROMPT is what to say to the user.
- ;; DEFAULT is the default face.
- (or (if cpp-button-event
- (x-popup-menu cpp-button-event
- (list prompt (cons prompt cpp-face-default-list)))
- (let ((name (car (rassq default cpp-face-default-list))))
- (cdr (assoc (completing-read (if name
- (concat prompt
- " (default " name "): ")
- (concat prompt ": "))
- cpp-face-default-list nil t)
- cpp-face-all-list))))
- default))
-
-(defun cpp-choose-default-face (type)
- ;; Choose default face list for screen of TYPE.
- ;; Type must be one of the types defined in `cpp-face-type-list'.
- (interactive (list (if cpp-button-event
- (x-popup-menu cpp-button-event
- (list "Screen type"
- (cons "Screen type"
- cpp-face-type-list)))
- (cdr (assoc (completing-read "Screen type: "
- cpp-face-type-list
- nil t)
- cpp-face-type-list)))))
- (cond ((null type))
- ((eq type 'light)
- (if cpp-face-light-list
- ()
- (setq cpp-face-light-list
- (mapcar 'cpp-create-bg-face cpp-face-light-name-list))
- (setq cpp-face-all-list
- (append cpp-face-all-list cpp-face-light-list)))
- (setq cpp-face-type 'light)
- (setq cpp-face-default-list
- (append cpp-face-light-list cpp-face-none-list)))
- ((eq type 'dark)
- (if cpp-face-dark-list
- ()
- (setq cpp-face-dark-list
- (mapcar 'cpp-create-bg-face cpp-face-dark-name-list))
- (setq cpp-face-all-list
- (append cpp-face-all-list cpp-face-dark-list)))
- (setq cpp-face-type 'dark)
- (setq cpp-face-default-list
- (append cpp-face-dark-list cpp-face-none-list)))
- ((eq type 'mono)
- (setq cpp-face-type 'mono)
- (setq cpp-face-default-list
- (append cpp-face-mono-list cpp-face-none-list)))
- (t
- (setq cpp-face-type 'none)
- (setq cpp-face-default-list cpp-face-none-list))))
-
-;;; Buttons:
-
-(defun cpp-make-button (name callback &optional data face padding)
- ;; Create a button at point.
- ;; NAME is the name of the button.
- ;; CALLBACK is the function to call when the button is pushed.
- ;; DATA will be made available to CALLBACK
- ;;in the free variable cpp-callback-data.
- ;; FACE means that NAME is the name of a face in `cpp-face-all-list'.
- ;; PADDING means NAME will be right justified at that length.
- (let ((name (format "%s" name))
- from to)
- (cond ((null padding)
- (setq from (point))
- (insert name))
- ((> (length name) padding)
- (setq from (point))
- (insert (substring name 0 padding)))
- (t
- (insert (make-string (- padding (length name)) ? ))
- (setq from (point))
- (insert name)))
- (setq to (point))
- (setq face
- (if face
- (let ((check (cdr (assoc name cpp-face-all-list))))
- (if (memq check '(default invisible))
- 'bold
- check))
- 'bold))
- (add-text-properties from to
- (append (list 'face face)
- '(mouse-face highlight)
- (list 'cpp-callback callback)
- (if data (list 'cpp-data data))))))
-
-(defun cpp-push-button (event)
- ;; Pushed a CPP button.
- (interactive "@e")
- (set-buffer (window-buffer (posn-window (event-start event))))
- (let ((pos (posn-point (event-start event))))
- (let ((cpp-callback-data (get-text-property pos 'cpp-data))
- (fun (get-text-property pos 'cpp-callback))
- (cpp-button-event event))
- (cond (fun
- (call-interactively (get-text-property pos 'cpp-callback)))
- ((lookup-key global-map [ down-mouse-2])
- (call-interactively (lookup-key global-map [ down-mouse-2])))))))
-
-;;; Faces:
-
-(defun cpp-create-bg-face (color)
- ;; Create entry for face with background COLOR.
- (let ((name (intern (concat "cpp " color))))
- (make-face name)
- (set-face-background name color)
- (cons color name)))
-
-(cpp-choose-default-face (if window-system cpp-face-type 'none))
-
-(defun cpp-face-name (face)
- ;; Return the name of FACE from `cpp-face-all-list'.
- (let ((entry (rassq (if face face 'default) cpp-face-all-list)))
- (if entry
- (car entry)
- (format "<%s>" face))))
-
-;;; Utilities:
-
-(defvar cpp-progress-time 0)
-;; Last time we issued a progress message.
-
-(defun cpp-progress-message (&rest args)
- ;; Report progress at most once a second. Take same ARGS as `message'.
- (let ((time (nth 1 (current-time))))
- (if (= time cpp-progress-time)
- ()
- (setq cpp-progress-time time)
- (apply 'message args))))
-
-(provide 'cpp)
-
-;;; cpp.el ends here
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
deleted file mode 100644
index 80d56df9329..00000000000
--- a/lisp/progmodes/etags.el
+++ /dev/null
@@ -1,1606 +0,0 @@
-;;; etags.el --- etags facility for Emacs
-
-;; Copyright (C) 1985, 1986, 1988, 1989, 1992, 1993, 1994, 1995
-;; Free Software Foundation, Inc.
-
-;; Author: Roland McGrath <roland@gnu.ai.mit.edu>
-;; Keywords: tools
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;;;###autoload
-(defvar tags-file-name nil
- "*File name of tags table.
-To switch to a new tags table, setting this variable is sufficient.
-If you set this variable, do not also set `tags-table-list'.
-Use the `etags' program to make a tags table file.")
-;; Make M-x set-variable tags-file-name like M-x visit-tags-table.
-;;;###autoload (put 'tags-file-name 'variable-interactive "fVisit tags table: ")
-
-;;;###autoload
-;; Use `visit-tags-table-buffer' to cycle through tags tables in this list.
-(defvar tags-table-list nil
- "*List of file names of tags tables to search.
-An element that is a directory means the file \"TAGS\" in that directory.
-To switch to a new list of tags tables, setting this variable is sufficient.
-If you set this variable, do not also set `tags-file-name'.
-Use the `etags' program to make a tags table file.")
-
-;;;###autoload
-(defvar tags-add-tables 'ask-user
- "*Control whether to add a new tags table to the current list.
-t means do; nil means don't (always start a new list).
-Any other value means ask the user whether to add a new tags table
-to the current list (as opposed to starting a new list).")
-
-(defvar tags-table-computed-list nil
- "List of tags tables to search, computed from `tags-table-list'.
-This includes tables implicitly included by other tables. The list is not
-always complete: the included tables of a table are not known until that
-table is read into core. An element that is `t' is a placeholder
-indicating that the preceding element is a table that has not been read
-into core and might contain included tables to search.
-See `tags-table-check-computed-list'.")
-
-(defvar tags-table-computed-list-for nil
- "Value of `tags-table-list' that `tags-table-computed-list' corresponds to.
-If `tags-table-list' changes, `tags-table-computed-list' is thrown away and
-recomputed; see `tags-table-check-computed-list'.")
-
-(defvar tags-table-list-pointer nil
- "Pointer into `tags-table-computed-list' for the current state of searching.
-Use `visit-tags-table-buffer' to cycle through tags tables in this list.")
-
-(defvar tags-table-list-started-at nil
- "Pointer into `tags-table-computed-list', where the current search started.")
-
-(defvar tags-table-set-list nil
- "List of sets of tags table which have been used together in the past.
-Each element is a list of strings which are file names.")
-
-;;;###autoload
-(defvar find-tag-hook nil
- "*Hook to be run by \\[find-tag] after finding a tag. See `run-hooks'.
-The value in the buffer in which \\[find-tag] is done is used,
-not the value in the buffer \\[find-tag] goes to.")
-
-;;;###autoload
-(defvar find-tag-default-function nil
- "*A function of no arguments used by \\[find-tag] to pick a default tag.
-If nil, and the symbol that is the value of `major-mode'
-has a `find-tag-default-function' property (see `put'), that is used.
-Otherwise, `find-tag-default' is used.")
-
-(defvar default-tags-table-function nil
- "If non-nil, a function to choose a default tags file for a buffer.
-This function receives no arguments and should return the default
-tags table file to use for the current buffer.")
-
-(defvar tags-location-stack nil
- "List of markers which are locations visited by \\[find-tag].
-Pop back to the last location with \\[negative-argument] \\[find-tag].")
-
-;; Tags table state.
-;; These variables are local in tags table buffers.
-
-(defvar tags-table-files nil
- "List of file names covered by current tags table.
-nil means it has not yet been computed; use `tags-table-files' to do so.")
-
-(defvar tags-completion-table nil
- "Alist of tag names defined in current tags table.")
-
-(defvar tags-included-tables nil
- "List of tags tables included by the current tags table.")
-
-(defvar next-file-list nil
- "List of files for \\[next-file] to process.")
-
-;; Hooks for file formats.
-
-(defvar tags-table-format-hooks '(etags-recognize-tags-table
- recognize-empty-tags-table)
- "List of functions to be called in a tags table buffer to identify
-the type of tags table. The functions are called in order, with no arguments,
-until one returns non-nil. The function should make buffer-local bindings
-of the format-parsing tags function variables if successful.")
-
-(defvar file-of-tag-function nil
- "Function to do the work of `file-of-tag' (which see).")
-(defvar tags-table-files-function nil
- "Function to do the work of `tags-table-files' (which see).")
-(defvar tags-completion-table-function nil
- "Function to build the tags-completion-table.")
-(defvar snarf-tag-function nil
- "Function to get info about a matched tag for `goto-tag-location-function'.")
-(defvar goto-tag-location-function nil
- "Function of to go to the location in the buffer specified by a tag.
-One argument, the tag info returned by `snarf-tag-function'.")
-(defvar find-tag-regexp-search-function nil
- "Search function passed to `find-tag-in-order' for finding a regexp tag.")
-(defvar find-tag-regexp-tag-order nil
- "Tag order passed to `find-tag-in-order' for finding a regexp tag.")
-(defvar find-tag-regexp-next-line-after-failure-p nil
- "Flag passed to `find-tag-in-order' for finding a regexp tag.")
-(defvar find-tag-search-function nil
- "Search function passed to `find-tag-in-order' for finding a tag.")
-(defvar find-tag-tag-order nil
- "Tag order passed to `find-tag-in-order' for finding a tag.")
-(defvar find-tag-next-line-after-failure-p nil
- "Flag passed to `find-tag-in-order' for finding a tag.")
-(defvar list-tags-function nil
- "Function to do the work of `list-tags' (which see).")
-(defvar tags-apropos-function nil
- "Function to do the work of `tags-apropos' (which see).")
-(defvar tags-included-tables-function nil
- "Function to do the work of `tags-included-tables' (which see).")
-(defvar verify-tags-table-function nil
- "Function to return t iff the current buffer contains a valid
-\(already initialized\) tags file.")
-
-;; Initialize the tags table in the current buffer.
-;; Returns non-nil iff it is a valid tags table. On
-;; non-nil return, the tags table state variable are
-;; made buffer-local and initialized to nil.
-(defun initialize-new-tags-table ()
- (set (make-local-variable 'tags-table-files) nil)
- (set (make-local-variable 'tags-completion-table) nil)
- (set (make-local-variable 'tags-included-tables) nil)
- ;; Value is t if we have found a valid tags table buffer.
- (let ((hooks tags-table-format-hooks))
- (while (and hooks
- (not (funcall (car hooks))))
- (setq hooks (cdr hooks)))
- hooks))
-
-;;;###autoload
-(defun visit-tags-table (file &optional local)
- "Tell tags commands to use tags 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.
-
-Normally \\[visit-tags-table] sets the global value of `tags-file-name'.
-With a prefix arg, set the buffer-local value instead.
-When you find a tag with \\[find-tag], the buffer it finds the tag
-in is given a local value of this variable which is the name of the tags
-file the tag was in."
- (interactive (list (read-file-name "Visit tags table: (default TAGS) "
- default-directory
- (expand-file-name "TAGS"
- default-directory)
- t)
- current-prefix-arg))
- (or (stringp file) (signal 'wrong-type-argument (list 'stringp file)))
- ;; Bind tags-file-name so we can control below whether the local or
- ;; global value gets set. Calling visit-tags-table-buffer will
- ;; initialize a buffer for the file and set tags-file-name to the
- ;; Calling visit-tags-table-buffer with tags-file-name set to FILE will
- ;; initialize a buffer for FILE and set tags-file-name to the
- ;; fully-expanded name.
- (let ((tags-file-name file))
- (save-excursion
- (or (visit-tags-table-buffer file)
- (signal 'file-error (list "Visiting tags table"
- "file does not exist"
- file)))
- ;; Set FILE to the expanded name.
- (setq file tags-file-name)))
- (if local
- ;; Set the local value of tags-file-name.
- (set (make-local-variable 'tags-file-name) file)
- ;; Set the global value of tags-file-name.
- (setq-default tags-file-name file)))
-
-(defun tags-table-check-computed-list ()
- "Compute `tags-table-computed-list' from `tags-table-list' if necessary."
- (let ((expanded-list (mapcar 'tags-expand-table-name tags-table-list)))
- (or (equal tags-table-computed-list-for expanded-list)
- ;; The list (or default-directory) has changed since last computed.
- (let* ((compute-for (mapcar 'copy-sequence expanded-list))
- (tables (copy-sequence compute-for)) ;Mutated in the loop.
- (computed nil)
- table-buffer)
-
- (while tables
- (setq computed (cons (car tables) computed)
- table-buffer (get-file-buffer (car tables)))
- (if (and table-buffer
- ;; There is a buffer visiting the file. Now make sure
- ;; it is initialized as a tag table buffer.
- (save-excursion
- (tags-verify-table (buffer-file-name table-buffer))))
- (save-excursion
- (set-buffer table-buffer)
- (if (tags-included-tables)
- ;; Insert the included tables into the list we
- ;; are processing.
- (setcdr tables (nconc (mapcar 'tags-expand-table-name
- (tags-included-tables))
- (cdr tables)))))
- ;; This table is not in core yet. Insert a placeholder
- ;; saying we must read it into core to check for included
- ;; tables before searching the next table in the list.
- (setq computed (cons t computed)))
- (setq tables (cdr tables)))
-
- ;; Record the tags-table-list value (and the context of the
- ;; current directory) we computed from.
- (setq tags-table-computed-list-for compute-for
- tags-table-computed-list (nreverse computed))))))
-
-;; Extend `tags-table-computed-list' to remove the first `t' placeholder.
-;; An element of the list that is `t' is a placeholder indicating that the
-;; preceding element is a table that has not been read into core and might
-;; contain included tables to search. On return, the first placeholder
-;; element will be gone and the element before it read into core and its
-;; included tables inserted into the list.
-(defun tags-table-extend-computed-list ()
- (let ((list tags-table-computed-list))
- (while (not (eq (nth 1 list) t))
- (setq list (cdr list)))
- (save-excursion
- (if (tags-verify-table (car list))
- ;; We are now in the buffer visiting (car LIST). Extract its
- ;; list of included tables and insert it into the computed list.
- (let ((tables (tags-included-tables))
- (computed nil)
- table-buffer)
- (while tables
- (setq computed (cons (car tables) computed)
- table-buffer (get-file-buffer (car tables)))
- (if table-buffer
- (save-excursion
- (set-buffer table-buffer)
- (if (tags-included-tables)
- ;; Insert the included tables into the list we
- ;; are processing.
- (setcdr tables (append (tags-included-tables)
- tables))))
- ;; This table is not in core yet. Insert a placeholder
- ;; saying we must read it into core to check for included
- ;; tables before searching the next table in the list.
- (setq computed (cons t computed)))
- (setq tables (cdr tables)))
- (setq computed (nreverse computed))
- ;; COMPUTED now contains the list of included tables (and
- ;; tables included by them, etc.). Now splice this into the
- ;; current list.
- (setcdr list (nconc computed (cdr (cdr list)))))
- ;; It was not a valid table, so just remove the following placeholder.
- (setcdr list (cdr (cdr list)))))))
-
-;; Expand tags table name FILE into a complete file name.
-(defun tags-expand-table-name (file)
- (setq file (expand-file-name file))
- (if (file-directory-p file)
- (expand-file-name "TAGS" file)
- file))
-
-;; Like member, but comparison is done after tags-expand-table-name on both
-;; sides and elements of LIST that are t are skipped.
-(defun tags-table-list-member (file list)
- (setq file (tags-expand-table-name file))
- (while (and list
- (or (eq (car list) t)
- (not (string= file (tags-expand-table-name (car list))))))
- (setq list (cdr list)))
- list)
-
-(defun tags-verify-table (file)
- "Read FILE into a buffer and verify that it is a valid tags table.
-Sets the current buffer to one visiting FILE (if it exists).
-Returns non-nil iff it is a valid table."
- (if (get-file-buffer file)
- ;; The file is already in a buffer. Check for the visited file
- ;; having changed since we last used it.
- (let (win)
- (set-buffer (get-file-buffer file))
- (setq win (or verify-tags-table-function (initialize-new-tags-table)))
- (if (or (verify-visited-file-modtime (current-buffer))
- (not (yes-or-no-p
- (format "Tags file %s has changed, read new contents? "
- file))))
- (and win (funcall verify-tags-table-function))
- (revert-buffer t t)
- (initialize-new-tags-table)))
- (and (file-exists-p file)
- (progn
- (set-buffer (find-file-noselect file))
- (or (string= file buffer-file-name)
- ;; find-file-noselect has changed the file name.
- ;; Propagate the change to tags-file-name and tags-table-list.
- (let ((tail (member file tags-table-list)))
- (if tail
- (setcar tail buffer-file-name))
- (if (eq file tags-file-name)
- (setq tags-file-name buffer-file-name))))
- (initialize-new-tags-table)))))
-
-;; Subroutine of visit-tags-table-buffer. Search the current tags tables
-;; for one that has tags for THIS-FILE (or that includes a table that
-;; does). Return the name of the first table table listing THIS-FILE; if
-;; the table is one included by another table, it is the master table that
-;; we return. If CORE-ONLY is non-nil, check only tags tables that are
-;; already in buffers--don't visit any new files.
-(defun tags-table-including (this-file core-only)
- (let ((tables tags-table-computed-list)
- (found nil))
- ;; Loop over the list, looking for a table containing tags for THIS-FILE.
- (while (and (not found)
- tables)
-
- (if core-only
- ;; Skip tables not in core.
- (while (eq (nth 1 tables) t)
- (setq tables (cdr (cdr tables))))
- (if (eq (nth 1 tables) t)
- ;; This table has not been read into core yet. Read it in now.
- (tags-table-extend-computed-list)))
-
- (if tables
- ;; Select the tags table buffer and get the file list up to date.
- (let ((tags-file-name (car tables)))
- (visit-tags-table-buffer 'same)
- (if (member this-file (mapcar 'expand-file-name
- (tags-table-files)))
- ;; Found it.
- (setq found tables))))
- (setq tables (cdr tables)))
- (if found
- ;; Now determine if the table we found was one included by another
- ;; table, not explicitly listed. We do this by checking each
- ;; element of the computed list to see if it appears in the user's
- ;; explicit list; the last element we will check is FOUND itself.
- ;; Then we return the last one which did in fact appear in
- ;; tags-table-list.
- (let ((could-be nil)
- (elt tags-table-computed-list))
- (while (not (eq elt (cdr found)))
- (if (tags-table-list-member (car elt) tags-table-list)
- ;; This table appears in the user's list, so it could be
- ;; the one which includes the table we found.
- (setq could-be (car elt)))
- (setq elt (cdr elt))
- (if (eq t (car elt))
- (setq elt (cdr elt))))
- ;; The last element we found in the computed list before FOUND
- ;; that appears in the user's list will be the table that
- ;; included the one we found.
- could-be))))
-
-;; Subroutine of visit-tags-table-buffer. Move tags-table-list-pointer
-;; along and set tags-file-name. Returns nil when out of tables.
-(defun tags-next-table ()
- ;; If there is a placeholder element next, compute the list to replace it.
- (while (eq (nth 1 tags-table-list-pointer) t)
- (tags-table-extend-computed-list))
-
- ;; Go to the next table in the list.
- (setq tags-table-list-pointer (cdr tags-table-list-pointer))
- (or tags-table-list-pointer
- ;; Wrap around.
- (setq tags-table-list-pointer tags-table-computed-list))
-
- (if (eq tags-table-list-pointer tags-table-list-started-at)
- ;; We have come full circle. No more tables.
- (setq tags-table-list-pointer nil)
- ;; Set tags-file-name to the name from the list. It is already expanded.
- (setq tags-file-name (car tags-table-list-pointer))))
-
-(defun visit-tags-table-buffer (&optional cont)
- "Select the buffer containing the current tags table.
-If optional arg is a string, visit that file as a tags table.
-If optional arg is t, visit the next table in `tags-table-list'.
-If optional arg is the atom `same', don't look for a new table;
- just select the buffer visiting `tags-file-name'.
-If arg is nil or absent, choose a first buffer from information in
- `tags-file-name', `tags-table-list', `tags-table-list-pointer'.
-Returns t if it visits a tags table, or nil if there are no more in the list."
-
- ;; Set tags-file-name to the tags table file we want to visit.
- (cond ((eq cont 'same)
- ;; Use the ambient value of tags-file-name.
- (or tags-file-name
- (error "%s"
- (substitute-command-keys
- (concat "No tags table in use! "
- "Use \\[visit-tags-table] to select one.")))))
-
- ((eq t cont)
- ;; Find the next table.
- (if (tags-next-table)
- ;; Skip over nonexistent files.
- (while (and (not (or (get-file-buffer tags-file-name)
- (file-exists-p tags-file-name)))
- (tags-next-table)))))
-
- (t
- ;; Pick a table out of our hat.
- (tags-table-check-computed-list) ;Get it up to date, we might use it.
- (setq tags-file-name
- (or
- ;; If passed a string, use that.
- (if (stringp cont)
- (prog1 cont
- (setq cont nil)))
- ;; First, try a local variable.
- (cdr (assq 'tags-file-name (buffer-local-variables)))
- ;; Second, try a user-specified function to guess.
- (and default-tags-table-function
- (funcall default-tags-table-function))
- ;; Third, look for a tags table that contains tags for the
- ;; current buffer's file. If one is found, the lists will
- ;; be frobnicated, and CONT will be set non-nil so we don't
- ;; do it below.
- (and buffer-file-name
- (or
- ;; First check only tables already in buffers.
- (tags-table-including buffer-file-name t)
- ;; Since that didn't find any, now do the
- ;; expensive version: reading new files.
- (tags-table-including buffer-file-name nil)))
- ;; Fourth, use the user variable tags-file-name, if it is
- ;; not already in the current list.
- (and tags-file-name
- (not (tags-table-list-member tags-file-name
- tags-table-computed-list))
- tags-file-name)
- ;; Fifth, use the user variable giving the table list.
- ;; Find the first element of the list that actually exists.
- (let ((list tags-table-list)
- file)
- (while (and list
- (setq file (tags-expand-table-name (car list)))
- (not (get-file-buffer file))
- (not (file-exists-p file)))
- (setq list (cdr list)))
- (car list))
- ;; Finally, prompt the user for a file name.
- (expand-file-name
- (read-file-name "Visit tags table: (default TAGS) "
- default-directory
- "TAGS"
- t))))))
-
- ;; Expand the table name into a full file name.
- (setq tags-file-name (tags-expand-table-name tags-file-name))
-
- (if (and (eq cont t)
- (null tags-table-list-pointer))
- ;; All out of tables.
- nil
-
- ;; Verify that tags-file-name names a valid tags table.
- ;; Bind another variable with the value of tags-file-name
- ;; before we switch buffers, in case tags-file-name is buffer-local.
- (let ((curbuf (current-buffer))
- (local-tags-file-name tags-file-name))
- (if (tags-verify-table local-tags-file-name)
-
- ;; We have a valid tags table.
- (progn
- ;; Bury the tags table buffer so it
- ;; doesn't get in the user's way.
- (bury-buffer (current-buffer))
-
- ;; If this was a new table selection (CONT is nil), make
- ;; sure tags-table-list includes the chosen table, and
- ;; update the list pointer variables.
- (or cont
- ;; Look in the list for the table we chose.
- (let ((found (tags-table-list-member
- local-tags-file-name
- tags-table-computed-list)))
- (if found
- ;; There it is. Just switch to it.
- (setq tags-table-list-pointer found
- tags-table-list-started-at found)
-
- ;; The table is not in the current set.
- ;; Try to find it in another previously used set.
- (let ((sets tags-table-set-list))
- (while (and sets
- (not (tags-table-list-member
- local-tags-file-name
- (car sets))))
- (setq sets (cdr sets)))
- (if sets
- ;; Found in some other set. Switch to that set.
- (progn
- (or (memq tags-table-list tags-table-set-list)
- ;; Save the current list.
- (setq tags-table-set-list
- (cons tags-table-list
- tags-table-set-list)))
- (setq tags-table-list (car sets)))
-
- ;; Not found in any existing set.
- (if (and tags-table-list
- (or (eq t tags-add-tables)
- (and tags-add-tables
- (y-or-n-p
- (concat "Keep current list of "
- "tags tables also? ")))))
- ;; Add it to the current list.
- (setq tags-table-list (cons local-tags-file-name
- tags-table-list))
-
- ;; Make a fresh list, and store the old one.
- (message "Starting a new list of tags tables")
- (or (null tags-table-list)
- (memq tags-table-list tags-table-set-list)
- (setq tags-table-set-list
- (cons tags-table-list
- tags-table-set-list)))
- (setq tags-table-list (list local-tags-file-name))))
-
- ;; Recompute tags-table-computed-list.
- (tags-table-check-computed-list)
- ;; Set the tags table list state variables to start
- ;; over from tags-table-computed-list.
- (setq tags-table-list-started-at tags-table-computed-list
- tags-table-list-pointer
- tags-table-computed-list)))))
-
- ;; Return of t says the tags table is valid.
- t)
-
- ;; The buffer was not valid. Don't use it again.
- (set-buffer curbuf)
- (kill-local-variable 'tags-file-name)
- (if (eq local-tags-file-name tags-file-name)
- (setq tags-file-name nil))
- (error "File %s is not a valid tags table" local-tags-file-name)))))
-
-(defun tags-reset-tags-tables ()
- "Reset tags state to cancel effect of any previous \\[visit-tags-table]
-or \\[find-tag]."
- (interactive)
- (setq tags-file-name nil
- tags-location-stack nil
- tags-table-list nil
- tags-table-computed-list nil
- tags-table-computed-list-for nil
- tags-table-list-pointer nil
- tags-table-list-started-at nil
- tags-table-set-list nil))
-
-(defun file-of-tag ()
- "Return the file name of the file whose tags point is within.
-Assumes the tags table is the current buffer.
-File name returned is relative to tags table file's directory."
- (funcall file-of-tag-function))
-
-;;;###autoload
-(defun tags-table-files ()
- "Return a list of files in the current tags table.
-Assumes the tags table is the current buffer. The file names are returned
-as they appeared in the `etags' command that created the table, usually
-without directory names."
- (or tags-table-files
- (setq tags-table-files
- (funcall tags-table-files-function))))
-
-(defun tags-included-tables ()
- "Return a list of tags tables included by the current table.
-Assumes the tags table is the current buffer."
- (or tags-included-tables
- (setq tags-included-tables (funcall tags-included-tables-function))))
-
-;; Build tags-completion-table on demand. The single current tags table
-;; and its included tags tables (and their included tables, etc.) have
-;; their tags included in the completion table.
-(defun tags-completion-table ()
- (or tags-completion-table
- (condition-case ()
- (prog2
- (message "Making tags completion table for %s..." buffer-file-name)
- (let ((included (tags-included-tables))
- (table (funcall tags-completion-table-function)))
- (save-excursion
- ;; Iterate over the list of included tables, and combine each
- ;; included table's completion obarray to the parent obarray.
- (while included
- ;; Visit the buffer.
- (let ((tags-file-name (car included)))
- (visit-tags-table-buffer 'same))
- ;; Recurse in that buffer to compute its completion table.
- (if (tags-completion-table)
- ;; Combine the tables.
- (mapatoms (function
- (lambda (sym)
- (intern (symbol-name sym) table)))
- tags-completion-table))
- (setq included (cdr included))))
- (setq tags-completion-table table))
- (message "Making tags completion table for %s...done"
- buffer-file-name))
- (quit (message "Tags completion table construction aborted.")
- (setq tags-completion-table nil)))))
-
-;; Completion function for tags. Does normal try-completion,
-;; but builds tags-completion-table on demand.
-(defun tags-complete-tag (string predicate what)
- (save-excursion
- ;; If we need to ask for the tag table, allow that.
- (let ((enable-recursive-minibuffers t))
- (visit-tags-table-buffer))
- (if (eq what t)
- (all-completions string (tags-completion-table) predicate)
- (try-completion string (tags-completion-table) predicate))))
-
-;; 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 (or (re-search-backward "\\sw\\|\\s_"
- (save-excursion (beginning-of-line) (point))
- t)
- (re-search-forward "\\(\\sw\\|\\s_\\)+"
- (save-excursion (end-of-line) (point))
- t))
- (progn (goto-char (match-end 0))
- (buffer-substring (point)
- (progn (forward-sexp -1)
- (while (looking-at "\\s'")
- (forward-char 1))
- (point))))
- nil)))
-
-;; Read a tag name from the minibuffer with defaulting and completion.
-(defun find-tag-tag (string)
- (let* ((default (funcall (or find-tag-default-function
- (get major-mode 'find-tag-default-function)
- 'find-tag-default)))
- (spec (completing-read (if default
- (format "%s(default %s) " string default)
- string)
- 'tags-complete-tag)))
- (if (equal spec "")
- (or default (error "There is no default tag"))
- spec)))
-
-(defvar last-tag nil
- "Last tag found by \\[find-tag].")
-
-;; Get interactive args for find-tag{-noselect,-other-window,-regexp}.
-(defun find-tag-interactive (prompt &optional no-default)
- (if current-prefix-arg
- (list nil (if (< (prefix-numeric-value current-prefix-arg) 0)
- '-
- t))
- (list (if no-default
- (read-string prompt)
- (find-tag-tag prompt)))))
-
-(defvar find-tag-history nil)
-
-;;;###autoload
-(defun find-tag-noselect (tagname &optional next-p regexp-p)
- "Find tag (in current tags table) whose name contains TAGNAME.
-Returns the buffer containing the tag's definition and moves its point there,
-but does not select the buffer.
-The default for TAGNAME is the expression in the buffer near point.
-
-If second arg NEXT-P is t (interactively, with prefix arg), search for
-another tag that matches the last tagname or regexp used. When there are
-multiple matches for a tag, more exact matches are found first. If NEXT-P
-is the atom `-' (interactively, with prefix arg that is a negative number
-or just \\[negative-argument]), pop back to the previous tag gone to.
-
-If third arg REGEXP-P is non-nil, treat TAGNAME as a regexp.
-
-See documentation of variable `tags-file-name'."
- (interactive (find-tag-interactive "Find tag: "))
-
- (setq find-tag-history (cons tagname find-tag-history))
- ;; Save the current buffer's value of `find-tag-hook' before selecting the
- ;; tags table buffer.
- (let ((local-find-tag-hook find-tag-hook))
- (if (eq '- next-p)
- ;; Pop back to a previous location.
- (if (null tags-location-stack)
- (error "No previous tag locations")
- (let ((marker (car tags-location-stack)))
- ;; Pop the stack.
- (setq tags-location-stack (cdr tags-location-stack))
- (prog1
- ;; Move to the saved location.
- (set-buffer (marker-buffer marker))
- (goto-char (marker-position marker))
- ;; Kill that marker so it doesn't slow down editing.
- (set-marker marker nil nil)
- ;; Run the user's hook. Do we really want to do this for pop?
- (run-hooks 'local-find-tag-hook))))
- (if next-p
- ;; Find the same table we last used.
- (visit-tags-table-buffer 'same)
- ;; Pick a table to use.
- (visit-tags-table-buffer)
- ;; Record TAGNAME for a future call with NEXT-P non-nil.
- (setq last-tag tagname))
- ;; Record the location so we can pop back to it later.
- (let ((marker (make-marker)))
- (save-excursion
- (set-buffer
- ;; find-tag-in-order does the real work.
- (find-tag-in-order
- (if next-p last-tag tagname)
- (if regexp-p
- find-tag-regexp-search-function
- find-tag-search-function)
- (if regexp-p
- find-tag-regexp-tag-order
- find-tag-tag-order)
- (if regexp-p
- find-tag-regexp-next-line-after-failure-p
- find-tag-next-line-after-failure-p)
- (if regexp-p "matching" "containing")
- (not next-p)))
- (set-marker marker (point))
- (run-hooks 'local-find-tag-hook)
- (setq tags-location-stack
- (cons marker tags-location-stack))
- (current-buffer))))))
-
-;;;###autoload
-(defun find-tag (tagname &optional next-p regexp-p)
- "Find tag (in current tags table) whose name contains TAGNAME.
-Select the buffer containing the tag's definition, and move point there.
-The default for TAGNAME is the expression in the buffer around or before point.
-
-If second arg NEXT-P is t (interactively, with prefix arg), search for
-another tag that matches the last tagname or regexp used. When there are
-multiple matches for a tag, more exact matches are found first. If NEXT-P
-is the atom `-' (interactively, with prefix arg that is a negative number
-or just \\[negative-argument]), pop back to the previous tag gone to.
-
-See documentation of variable `tags-file-name'."
- (interactive (find-tag-interactive "Find tag: "))
- (switch-to-buffer (find-tag-noselect tagname next-p regexp-p)))
-;;;###autoload (define-key esc-map "." 'find-tag)
-
-;;;###autoload
-(defun find-tag-other-window (tagname &optional next-p regexp-p)
- "Find tag (in current tags table) whose name contains TAGNAME.
-Select the buffer containing the tag's definition in another window, and
-move point there. The default for TAGNAME is the expression in the buffer
-around or before point.
-
-If second arg NEXT-P is t (interactively, with prefix arg), search for
-another tag that matches the last tagname or regexp used. When there are
-multiple matches for a tag, more exact matches are found first. If NEXT-P
-is negative (interactively, with prefix arg that is a negative number or
-just \\[negative-argument]), pop back to the previous tag gone to.
-
-See documentation of variable `tags-file-name'."
- (interactive (find-tag-interactive "Find tag other window: "))
-
- ;; This hair is to deal with the case where the tag is found in the
- ;; selected window's buffer; without the hair, point is moved in both
- ;; windows. To prevent this, we save the selected window's point before
- ;; doing find-tag-noselect, and restore it after.
- (let* ((window-point (window-point (selected-window)))
- (tagbuf (find-tag-noselect tagname next-p regexp-p))
- (tagpoint (progn (set-buffer tagbuf) (point))))
- (set-window-point (prog1
- (selected-window)
- (switch-to-buffer-other-window tagbuf)
- ;; We have to set this new window's point; it
- ;; might already have been displaying a
- ;; different portion of tagbuf, in which case
- ;; switch-to-buffer-other-window doesn't set
- ;; the window's point from the buffer.
- (set-window-point (selected-window) tagpoint))
- window-point)))
-;;;###autoload (define-key ctl-x-4-map "." 'find-tag-other-window)
-
-;;;###autoload
-(defun find-tag-other-frame (tagname &optional next-p)
- "Find tag (in current tags table) whose name contains TAGNAME.
-Select the buffer containing the tag's definition in another frame, and
-move point there. The default for TAGNAME is the expression in the buffer
-around or before point.
-
-If second arg NEXT-P is t (interactively, with prefix arg), search for
-another tag that matches the last tagname or regexp used. When there are
-multiple matches for a tag, more exact matches are found first. If NEXT-P
-is negative (interactively, with prefix arg that is a negative number or
-just \\[negative-argument]), pop back to the previous tag gone to.
-
-See documentation of variable `tags-file-name'."
- (interactive (find-tag-interactive "Find tag other frame: "))
- (let ((pop-up-frames t))
- (find-tag-other-window tagname next-p)))
-;;;###autoload (define-key ctl-x-5-map "." 'find-tag-other-frame)
-
-;;;###autoload
-(defun find-tag-regexp (regexp &optional next-p other-window)
- "Find tag (in current tags table) whose name matches REGEXP.
-Select the buffer containing the tag's definition and move point there.
-
-If second arg NEXT-P is t (interactively, with prefix arg), search for
-another tag that matches the last tagname or regexp used. When there are
-multiple matches for a tag, more exact matches are found first. If NEXT-P
-is negative (interactively, with prefix arg that is a negative number or
-just \\[negative-argument]), pop back to the previous tag gone to.
-
-If third arg OTHER-WINDOW is non-nil, select the buffer in another window.
-
-See documentation of variable `tags-file-name'."
- (interactive (find-tag-interactive "Find tag regexp: " t))
- ;; We go through find-tag-other-window to do all the display hair there.
- (funcall (if other-window 'find-tag-other-window 'find-tag)
- regexp next-p t))
-;;;###autoload (define-key esc-map [?\C-.] 'find-tag-regexp)
-
-;; Internal tag finding function.
-
-;; PATTERN is a string to pass to second arg SEARCH-FORWARD-FUNC, and to
-;; any member of the function list ORDER (third arg). If ORDER is nil,
-;; use saved state to continue a previous search.
-
-;; Fourth arg MATCHING is a string, an English '-ing' word, to be used in
-;; an error message.
-
-;; Fifth arg NEXT-LINE-AFTER-FAILURE-P is non-nil if after a failed match,
-;; point should be moved to the next line.
-
-;; Algorithm is as follows. For each qualifier-func in ORDER, go to
-;; beginning of tags file, and perform inner loop: for each naive match for
-;; PATTERN found using SEARCH-FORWARD-FUNC, qualify the naive match using
-;; qualifier-func. If it qualifies, go to the specified line in the
-;; specified source file and return. Qualified matches are remembered to
-;; avoid repetition. State is saved so that the loop can be continued.
-
-(defvar tag-lines-already-matched nil) ;matches remembered here between calls
-
-(defun find-tag-in-order (pattern
- search-forward-func
- order
- next-line-after-failure-p
- matching
- first-search)
- (let (file ;name of file containing tag
- tag-info ;where to find the tag in FILE
- (first-table t)
- (tag-order order)
- (match-marker (make-marker))
- goto-func
- )
- (save-excursion
-
- (if first-search
- ;; This is the start of a search for a fresh tag.
- ;; Clear the list of tags matched by the previous search.
- ;; find-tag-noselect has already put us in the first tags table
- ;; buffer before we got called.
- (setq tag-lines-already-matched nil)
- ;; Continuing to search for the tag specified last time.
- ;; tag-lines-already-matched lists locations matched in previous
- ;; calls so we don't visit the same tag twice if it matches twice
- ;; during two passes with different qualification predicates.
- ;; Switch to the current tags table buffer.
- (visit-tags-table-buffer 'same))
-
- ;; Get a qualified match.
- (catch 'qualified-match-found
-
- ;; Iterate over the list of tags tables.
- (while (or first-table
- (visit-tags-table-buffer t))
-
- (and first-search first-table
- ;; Start at beginning of tags file.
- (goto-char (point-min)))
-
- (setq first-table nil)
-
- ;; Iterate over the list of ordering predicates.
- (while order
- (while (funcall search-forward-func pattern nil t)
- ;; Naive match found. Qualify the match.
- (and (funcall (car order) pattern)
- ;; Make sure it is not a previous qualified match.
- (not (member (set-marker match-marker (save-excursion
- (beginning-of-line)
- (point)))
- tag-lines-already-matched))
- (throw 'qualified-match-found nil))
- (if next-line-after-failure-p
- (forward-line 1)))
- ;; Try the next flavor of match.
- (setq order (cdr order))
- (goto-char (point-min)))
- (setq order tag-order))
- ;; We throw out on match, so only get here if there were no matches.
- ;; Clear out the markers we use to avoid duplicate matches so they
- ;; don't slow down editting and are immediately available for GC.
- (while tag-lines-already-matched
- (set-marker (car tag-lines-already-matched) nil nil)
- (setq tag-lines-already-matched (cdr tag-lines-already-matched)))
- (set-marker match-marker nil nil)
- (error "No %stags %s %s" (if first-search "" "more ")
- matching pattern))
-
- ;; Found a tag; extract location info.
- (beginning-of-line)
- (setq tag-lines-already-matched (cons match-marker
- tag-lines-already-matched))
- ;; Expand the filename, using the tags table buffer's default-directory.
- (setq file (expand-file-name (file-of-tag))
- tag-info (funcall snarf-tag-function))
-
- ;; Get the local value in the tags table buffer before switching buffers.
- (setq goto-func goto-tag-location-function)
-
- ;; Find the right line in the specified file.
- (set-buffer (find-file-noselect file))
- (widen)
- (push-mark)
- (funcall goto-func tag-info)
-
- ;; Return the buffer where the tag was found.
- (current-buffer))))
-
-;; `etags' TAGS file format support.
-
-;; If the current buffer is a valid etags TAGS file, give it local values of
-;; the tags table format variables, and return non-nil.
-(defun etags-recognize-tags-table ()
- (and (etags-verify-tags-table)
- ;; It is annoying to flash messages on the screen briefly,
- ;; and this message is not useful. -- rms
- ;; (message "%s is an `etags' TAGS file" buffer-file-name)
- (mapcar (function (lambda (elt)
- (set (make-local-variable (car elt)) (cdr elt))))
- '((file-of-tag-function . etags-file-of-tag)
- (tags-table-files-function . etags-tags-table-files)
- (tags-completion-table-function . etags-tags-completion-table)
- (snarf-tag-function . etags-snarf-tag)
- (goto-tag-location-function . etags-goto-tag-location)
- (find-tag-regexp-search-function . re-search-forward)
- (find-tag-regexp-tag-order . (tag-re-match-p))
- (find-tag-regexp-next-line-after-failure-p . t)
- (find-tag-search-function . search-forward)
- (find-tag-tag-order . (tag-exact-file-name-match-p
- tag-exact-match-p
- tag-symbol-match-p
- tag-word-match-p
- tag-any-match-p))
- (find-tag-next-line-after-failure-p . nil)
- (list-tags-function . etags-list-tags)
- (tags-apropos-function . etags-tags-apropos)
- (tags-included-tables-function . etags-tags-included-tables)
- (verify-tags-table-function . etags-verify-tags-table)
- ))))
-
-;; Return non-nil iff the current buffer is a valid etags TAGS file.
-(defun etags-verify-tags-table ()
- ;; Use eq instead of = in case char-after returns nil.
- (eq (char-after 1) ?\f))
-
-(defun etags-file-of-tag ()
- (save-excursion
- (re-search-backward "\f\n\\([^\n]+\\),[0-9]*\n")
- (expand-file-name (buffer-substring (match-beginning 1) (match-end 1))
- (file-truename default-directory))))
-
-
-(defun etags-tags-completion-table ()
- (let ((table (make-vector 511 0)))
- (save-excursion
- (goto-char (point-min))
- ;; This monster regexp matches an etags tag line.
- ;; \1 is the string to match;
- ;; \2 is not interesting;
- ;; \3 is the guessed tag name; XXX guess should be better eg DEFUN
- ;; \4 is not interesting;
- ;; \5 is the explicitly-specified tag name.
- ;; \6 is the line to start searching at;
- ;; \7 is the char to start searching at.
- (while (re-search-forward
- "^\\(\\([^\177]+[^-a-zA-Z0-9_$\177]+\\)?\\([-a-zA-Z0-9_$?:]+\\)\
-\[^-a-zA-Z0-9_$?:\177]*\\)\177\\(\\([^\n\001]+\\)\001\\)?\
-\\([0-9]+\\)?,\\([0-9]+\\)?\n"
- nil t)
- (intern (if (match-beginning 5)
- ;; There is an explicit tag name.
- (buffer-substring (match-beginning 5) (match-end 5))
- ;; No explicit tag name. Best guess.
- (buffer-substring (match-beginning 3) (match-end 3)))
- table)))
- table))
-
-(defun etags-snarf-tag ()
- (let (tag-text line startpos)
- (if (save-excursion
- (forward-line -1)
- (looking-at "\f\n"))
- ;; The match was for a source file name, not any tag within a file.
- ;; Give text of t, meaning to go exactly to the location we specify,
- ;; the beginning of the file.
- (setq tag-text t
- line nil
- startpos 1)
-
- ;; Find the end of the tag and record the whole tag text.
- (search-forward "\177")
- (setq tag-text (buffer-substring (1- (point))
- (save-excursion (beginning-of-line)
- (point))))
- ;; Skip explicit tag name if present.
- (search-forward "\001" (save-excursion (forward-line 1) (point)) t)
- (if (looking-at "[0-9]")
- (setq line (string-to-int (buffer-substring
- (point)
- (progn (skip-chars-forward "0-9")
- (point))))))
- (search-forward ",")
- (if (looking-at "[0-9]")
- (setq startpos (string-to-int (buffer-substring
- (point)
- (progn (skip-chars-forward "0-9")
- (point)))))))
- ;; Leave point on the next line of the tags file.
- (forward-line 1)
- (cons tag-text (cons line startpos))))
-
-;; TAG-INFO is a cons (TEXT LINE . POSITION) where TEXT is the initial part
-;; of a line containing the tag and POSITION is the character position of
-;; TEXT within the file (starting from 1); LINE is the line number. If
-;; TEXT is t, it means the tag refers to exactly LINE or POSITION
-;; (whichever is present, LINE having preference, no searching. Either
-;; LINE or POSITION may be nil; POSITION is used if present. If the tag
-;; isn't exactly at the given position then look around that position using
-;; a search window which expands until it hits the start of file.
-(defun etags-goto-tag-location (tag-info)
- (let ((startpos (cdr (cdr tag-info)))
- (line (car (cdr tag-info)))
- offset found pat)
- (if (eq (car tag-info) t)
- ;; Direct file tag.
- (cond (line (goto-line line))
- (startpos (goto-char startpos))
- (t (error "etags.el BUG: bogus direct file tag")))
- ;; This constant is 1/2 the initial search window.
- ;; There is no sense in making it too small,
- ;; since just going around the loop once probably
- ;; costs about as much as searching 2000 chars.
- (setq offset 1000
- found nil
- pat (concat (if (eq selective-display t)
- "\\(^\\|\^m\\)" "^")
- (regexp-quote (car tag-info))))
- ;; The character position in the tags table is 0-origin.
- ;; Convert it to a 1-origin Emacs character position.
- (if startpos (setq startpos (1+ startpos)))
- ;; If no char pos was given, try the given line number.
- (or startpos
- (if line
- (setq startpos (progn (goto-line line)
- (point)))))
- (or startpos
- (setq startpos (point-min)))
- ;; First see if the tag is right at the specified location.
- (goto-char startpos)
- (setq found (looking-at pat))
- (while (and (not found)
- (progn
- (goto-char (- startpos offset))
- (not (bobp))))
- (setq found
- (re-search-forward pat (+ startpos offset) t)
- offset (* 3 offset))) ; expand search window
- (or found
- (re-search-forward pat nil t)
- (error "Rerun etags: `%s' not found in %s"
- pat buffer-file-name)))
- ;; Position point at the right place
- ;; if the search string matched an extra Ctrl-m at the beginning.
- (and (eq selective-display t)
- (looking-at "\^m")
- (forward-char 1))
- (beginning-of-line)))
-
-(defun etags-list-tags (file)
- (goto-char 1)
- (if (not (search-forward (concat "\f\n" file ",") nil t))
- nil
- (forward-line 1)
- (while (not (or (eobp) (looking-at "\f")))
- (let ((tag (buffer-substring (point)
- (progn (skip-chars-forward "^\177")
- (point)))))
- (princ (if (looking-at "[^\n]+\001")
- ;; There is an explicit tag name; use that.
- (buffer-substring (1+ (point)) ;skip \177
- (progn (skip-chars-forward "^\001")
- (point)))
- tag)))
- (terpri)
- (forward-line 1))
- t))
-
-(defun etags-tags-apropos (string)
- (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)))
-
-(defun etags-tags-table-files ()
- (let ((files nil)
- beg)
- (goto-char (point-min))
- (while (search-forward "\f\n" nil t)
- (setq beg (point))
- (end-of-line)
- (skip-chars-backward "^," beg)
- (or (looking-at "include$")
- (setq files (cons (buffer-substring beg (1- (point))) files))))
- (nreverse files)))
-
-(defun etags-tags-included-tables ()
- (let ((files nil)
- beg)
- (goto-char (point-min))
- (while (search-forward "\f\n" nil t)
- (setq beg (point))
- (end-of-line)
- (skip-chars-backward "^," beg)
- (if (looking-at "include$")
- ;; Expand in the default-directory of the tags table buffer.
- (setq files (cons (expand-file-name (buffer-substring beg (1- (point))))
- files))))
- (nreverse files)))
-
-;; Empty tags file support.
-
-;; Recognize an empty file and give it local values of the tags table format
-;; variables which do nothing.
-(defun recognize-empty-tags-table ()
- (and (zerop (buffer-size))
- (mapcar (function (lambda (sym)
- (set (make-local-variable sym) 'ignore)))
- '(tags-table-files-function
- tags-completion-table-function
- find-tag-regexp-search-function
- find-tag-search-function
- tags-apropos-function
- tags-included-tables-function))
- (set (make-local-variable 'verify-tags-table-function)
- (function (lambda ()
- (zerop (buffer-size)))))))
-
-;;; Match qualifier functions for tagnames.
-;;; XXX these functions assume etags file format.
-
-;; This might be a neat idea, but it's too hairy at the moment.
-;;(defmacro tags-with-syntax (&rest body)
-;; (` (let ((current (current-buffer))
-;; (otable (syntax-table))
-;; (buffer (find-file-noselect (file-of-tag)))
-;; table)
-;; (unwind-protect
-;; (progn
-;; (set-buffer buffer)
-;; (setq table (syntax-table))
-;; (set-buffer current)
-;; (set-syntax-table table)
-;; (,@ body))
-;; (set-syntax-table otable)))))
-;;(put 'tags-with-syntax 'edebug-form-spec '(&rest form))
-
-;; t if point is at a tag line that matches TAG exactly.
-;; point should be just after a string that matches TAG.
-(defun tag-exact-match-p (tag)
- ;; The match is really exact if there is an explicit tag name.
- (or (and (eq (char-after (point)) ?\001)
- (eq (char-after (- (point) (length tag) 1)) ?\177))
- ;; We are not on the explicit tag name, but perhaps it follows.
- (looking-at (concat "[^\177\n]*\177" (regexp-quote tag) "\001"))))
-
-;; t if point is at a tag line that matches TAG as a symbol.
-;; point should be just after a string that matches TAG.
-(defun tag-symbol-match-p (tag)
- (and (looking-at "\\Sw.*\177") (looking-at "\\S_.*\177")
- (save-excursion
- (backward-char (1+ (length tag)))
- (and (looking-at "\\Sw") (looking-at "\\S_")))))
-
-;; t if point is at a tag line that matches TAG as a word.
-;; point should be just after a string that matches TAG.
-(defun tag-word-match-p (tag)
- (and (looking-at "\\b.*\177")
- (save-excursion (backward-char (length tag))
- (looking-at "\\b"))))
-
-(defun tag-exact-file-name-match-p (tag)
- (and (looking-at ",")
- (save-excursion (backward-char (length tag))
- (looking-at "\f\n"))))
-
-;; t if point is in a tag line with a tag containing TAG as a substring.
-(defun tag-any-match-p (tag)
- (looking-at ".*\177"))
-
-;; t if point is at a tag line that matches RE as a regexp.
-(defun tag-re-match-p (re)
- (save-excursion
- (beginning-of-line)
- (let ((bol (point)))
- (and (search-forward "\177" (save-excursion (end-of-line) (point)) t)
- (re-search-backward re bol t)))))
-
-;;;###autoload
-(defun next-file (&optional initialize novisit)
- "Select next file among files in current tags table.
-
-A first argument of t (prefix arg, if interactive) initializes to the
-beginning of the list of files in the tags table. If the argument is
-neither nil nor t, it is evalled to initialize the list of files.
-
-Non-nil second argument NOVISIT means use a temporary buffer
- to save time and avoid uninteresting warnings.
-
-Value is nil if the file was already visited;
-if the file was newly read in, the value is the filename."
- ;; Make the interactive arg t if there was any prefix arg.
- (interactive (list (if current-prefix-arg t)))
- (cond ((not initialize)
- ;; Not the first run.
- )
- ((eq initialize t)
- ;; Initialize the list from the tags table.
- (save-excursion
- ;; Visit the tags table buffer to get its list of files.
- (visit-tags-table-buffer)
- ;; Copy the list so we can setcdr below, and expand the file
- ;; names while we are at it, in this buffer's default directory.
- (setq next-file-list (mapcar 'expand-file-name (tags-table-files)))
- ;; Iterate over all the tags table files, collecting
- ;; a complete list of referenced file names.
- (while (visit-tags-table-buffer t)
- ;; Find the tail of the working list and chain on the new
- ;; sublist for this tags table.
- (let ((tail next-file-list))
- (while (cdr tail)
- (setq tail (cdr tail)))
- ;; Use a copy so the next loop iteration will not modify the
- ;; list later returned by (tags-table-files).
- (if tail
- (setcdr tail (mapcar 'expand-file-name (tags-table-files)))
- (setq next-file-list (mapcar 'expand-file-name
- (tags-table-files))))))))
- (t
- ;; Initialize the list by evalling the argument.
- (setq next-file-list (eval initialize))))
- (if next-file-list
- ()
- (and novisit
- (get-buffer " *next-file*")
- (kill-buffer " *next-file*"))
- (error "All files processed."))
- (let* ((next (car next-file-list))
- (new (not (get-file-buffer next))))
- ;; Advance the list before trying to find the file.
- ;; If we get an error finding the file, don't get stuck on it.
- (setq next-file-list (cdr next-file-list))
- (if (not (and new novisit))
- (set-buffer (find-file-noselect next novisit))
- ;; Like find-file, but avoids random warning messages.
- (set-buffer (get-buffer-create " *next-file*"))
- (kill-all-local-variables)
- (erase-buffer)
- (setq new next)
- (insert-file-contents new nil))
- new))
-
-(defvar tags-loop-operate nil
- "Form for `tags-loop-continue' to eval to change one file.")
-
-(defvar tags-loop-scan
- '(error "%s"
- (substitute-command-keys
- "No \\[tags-search] or \\[tags-query-replace] in progress."))
- "Form for `tags-loop-continue' to eval to scan one file.
-If it returns non-nil, this file needs processing by evalling
-\`tags-loop-operate'. Otherwise, move on to the next file.")
-
-;;;###autoload
-(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 (the
-argument is passed to `next-file', which see).
-
-Two variables control the processing we do on each file: the value of
-`tags-loop-scan' is a form to be executed on each file to see if it is
-interesting (it returns non-nil if so) and `tags-loop-operate' is a form to
-evaluate to operate on an interesting file. If the latter evaluates to
-nil, we exit; otherwise we scan the next file."
- (interactive)
- (let (new
- (messaged nil))
- (while
- (progn
- ;; Scan files quickly for the first or next interesting one.
- (while (or first-time
- (save-restriction
- (widen)
- (not (eval tags-loop-scan))))
- (setq new (next-file first-time t))
- ;; If NEW is non-nil, we got a temp buffer,
- ;; and NEW is the file name.
- (if (or messaged
- (and (not first-time)
- (> baud-rate search-slow-speed)
- (setq messaged t)))
- (message "Scanning file %s..." (or new buffer-file-name)))
- (setq first-time nil)
- (goto-char (point-min)))
-
- ;; If we visited it in a temp buffer, visit it now for real.
- (if new
- (let ((pos (point)))
- (erase-buffer)
- (set-buffer (find-file-noselect new))
- (setq new nil) ;No longer in a temp buffer.
- (widen)
- (goto-char pos)))
-
- (switch-to-buffer (current-buffer))
-
- ;; Now operate on the file.
- ;; If value is non-nil, continue to scan the next file.
- (eval tags-loop-operate)))
- (and messaged
- (null tags-loop-operate)
- (message "Scanning file %s...found" buffer-file-name))))
-;;;###autoload (define-key esc-map "," 'tags-loop-continue)
-
-;;;###autoload
-(defun tags-search (regexp &optional file-list-form)
- "Search through all files listed in tags 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-scan) 're-search-forward)
- (null tags-loop-operate))
- ;; Continue last tags-search as if by M-,.
- (tags-loop-continue nil)
- (setq tags-loop-scan
- (list 're-search-forward (list 'quote regexp) nil t)
- tags-loop-operate nil)
- (tags-loop-continue (or file-list-form t))))
-
-;;;###autoload
-(defun tags-query-replace (from to &optional delimited file-list-form)
- "Query-replace-regexp FROM with TO through all files listed in tags table.
-Third arg DELIMITED (prefix arg) means replace only word-delimited matches.
-If you exit (\\[keyboard-quit] or ESC), you can resume the query-replace
-with the command \\[tags-loop-continue].
-
-See documentation of variable `tags-file-name'."
- (interactive (query-replace-read-args "Tags query replace (regexp)" t))
- (setq tags-loop-scan (list 'prog1
- (list 'if (list 're-search-forward
- (list 'quote from) nil t)
- ;; When we find a match, move back
- ;; to the beginning of it so perform-replace
- ;; will see it.
- '(goto-char (match-beginning 0))))
- tags-loop-operate (list 'perform-replace
- (list 'quote from) (list 'quote to)
- t t (list 'quote delimited)))
- (tags-loop-continue (or file-list-form t)))
-
-(defun tags-complete-tags-table-file (string predicate what)
- (save-excursion
- ;; If we need to ask for the tag table, allow that.
- (let ((enable-recursive-minibuffers t))
- (visit-tags-table-buffer))
- (if (eq what t)
- (all-completions string (mapcar 'list (tags-table-files))
- predicate)
- (try-completion string (mapcar 'list (tags-table-files))
- predicate))))
-
-;;;###autoload
-(defun list-tags (file &optional next-match)
- "Display list of tags in file FILE.
-This searches only the first table in the list, and no included tables.
-FILE should be as it appeared in the `etags' command, usually without a
-directory specification."
- (interactive (list (completing-read "List tags in file: "
- 'tags-complete-tags-table-file
- nil t nil)))
- (with-output-to-temp-buffer "*Tags List*"
- (princ "Tags in file ")
- (princ file)
- (terpri)
- (save-excursion
- (let ((first-time t)
- (gotany nil))
- (while (visit-tags-table-buffer (not first-time))
- (setq first-time nil)
- (if (funcall list-tags-function file)
- (setq gotany t)))
- (or gotany
- (error "File %s not in current tags tables" file))))))
-
-;;;###autoload
-(defun tags-apropos (regexp)
- "Display list of all tags in tags table REGEXP matches."
- (interactive "sTags apropos (regexp): ")
- (with-output-to-temp-buffer "*Tags List*"
- (princ "Tags matching regexp ")
- (prin1 regexp)
- (terpri)
- (save-excursion
- (let ((first-time t))
- (while (visit-tags-table-buffer (not first-time))
- (setq first-time nil)
- (funcall tags-apropos-function regexp))))))
-
-;;; XXX Kludge interface.
-
-;; XXX If a file is in multiple tables, selection may get the wrong one.
-;;;###autoload
-(defun select-tags-table ()
- "Select a tags table file from a menu of those you have already used.
-The list of tags tables to select from is stored in `tags-table-set-list';
-see the doc of that variable if you want to add names to the list."
- (interactive)
- (pop-to-buffer "*Tags Table List*")
- (setq buffer-read-only nil)
- (erase-buffer)
- (let ((set-list tags-table-set-list)
- (desired-point nil))
- (if tags-table-list
- (progn
- (setq desired-point (point-marker))
- (princ tags-table-list (current-buffer))
- (insert "\C-m")
- (prin1 (car tags-table-list) (current-buffer)) ;invisible
- (insert "\n")))
- (while set-list
- (if (eq (car set-list) tags-table-list)
- ;; Already printed it.
- ()
- (princ (car set-list) (current-buffer))
- (insert "\C-m")
- (prin1 (car (car set-list)) (current-buffer)) ;invisible
- (insert "\n"))
- (setq set-list (cdr set-list)))
- (if tags-file-name
- (progn
- (or desired-point
- (setq desired-point (point-marker)))
- (insert tags-file-name "\C-m")
- (prin1 tags-file-name (current-buffer)) ;invisible
- (insert "\n")))
- (setq set-list (delete tags-file-name
- (apply 'nconc (cons (copy-sequence tags-table-list)
- (mapcar 'copy-sequence
- tags-table-set-list)))))
- (while set-list
- (insert (car set-list) "\C-m")
- (prin1 (car set-list) (current-buffer)) ;invisible
- (insert "\n")
- (setq set-list (delete (car set-list) set-list)))
- (goto-char 1)
- (insert-before-markers
- "Type `t' to select a tags table or set of tags tables:\n\n")
- (if desired-point
- (goto-char desired-point))
- (set-window-start (selected-window) 1 t))
- (set-buffer-modified-p nil)
- (select-tags-table-mode))
-
-(defvar select-tags-table-mode-map)
-(let ((map (make-sparse-keymap)))
- (define-key map "t" 'select-tags-table-select)
- (define-key map " " 'next-line)
- (define-key map "\^?" 'previous-line)
- (define-key map "n" 'next-line)
- (define-key map "p" 'previous-line)
- (define-key map "q" 'select-tags-table-quit)
- (setq select-tags-table-mode-map map))
-
-(defun select-tags-table-mode ()
- "Major mode for choosing a current tags table among those already loaded.
-
-\\{select-tags-table-mode-map}"
- (interactive)
- (kill-all-local-variables)
- (setq buffer-read-only t
- major-mode 'select-tags-table-mode
- mode-name "Select Tags Table")
- (use-local-map select-tags-table-mode-map)
- (setq selective-display t
- selective-display-ellipses nil))
-
-(defun select-tags-table-select ()
- "Select the tags table named on this line."
- (interactive)
- (search-forward "\C-m")
- (let ((name (read (current-buffer))))
- (visit-tags-table name)
- (select-tags-table-quit)
- (message "Tags table now %s" name)))
-
-(defun select-tags-table-quit ()
- "Kill the buffer and delete the selected window."
- (interactive)
- (kill-buffer (current-buffer))
- (or (one-window-p)
- (delete-window)))
-
-;;; Note, there is another definition of this function in bindings.el.
-;;;###autoload
-(defun complete-tag ()
- "Perform tags completion on the text around point.
-Completes to the set of names listed in the current tags table.
-The string to complete is chosen in the same way as the default
-for \\[find-tag] (which see)."
- (interactive)
- (or tags-table-list
- tags-file-name
- (error "%s"
- (substitute-command-keys
- "No tags table loaded. Try \\[visit-tags-table].")))
- (let ((pattern (funcall (or find-tag-default-function
- (get major-mode 'find-tag-default-function)
- 'find-tag-default)))
- beg
- completion)
- (or pattern
- (error "Nothing to complete"))
- (search-backward pattern)
- (setq beg (point))
- (forward-char (length pattern))
- (setq completion (try-completion pattern 'tags-complete-tag nil))
- (cond ((eq completion t))
- ((null completion)
- (message "Can't find completion for \"%s\"" pattern)
- (ding))
- ((not (string= pattern completion))
- (delete-region beg (point))
- (insert completion))
- (t
- (message "Making completion list...")
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list
- (all-completions pattern 'tags-complete-tag nil)))
- (message "Making completion list...%s" "done")))))
-
-;;;###autoload (define-key esc-map "\t" 'complete-tag)
-
-(provide 'etags)
-
-;;; etags.el ends here
diff --git a/lisp/progmodes/executable.el b/lisp/progmodes/executable.el
deleted file mode 100644
index 62d6f59fbbb..00000000000
--- a/lisp/progmodes/executable.el
+++ /dev/null
@@ -1,235 +0,0 @@
-;;; executable.el --- base functionality for executable interpreter scripts
-
-;; Copyright (C) 1994, 1995, 1996 by Free Software Foundation, Inc.
-
-;; Author: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389
-;; Keywords: languages, unix
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; executable.el is used by certain major modes to insert a suitable
-;; #! line at the beginning of the file, if the file does not already
-;; have one.
-
-;; Unless it has a magic number, a Unix file with executable mode is passed to
-;; a new instance of the running shell (or to a Bourne shell if a csh is
-;; running and the file starts with `:'). Only a shell can start such a file,
-;; exec() cannot, which is why it is important to have a magic number in every
-;; executable script. Such a magic number is made up by the characters `#!'
-;; the filename of an interpreter (in COFF, ELF or somesuch format) and one
-;; optional argument.
-
-;; This library is for certain major modes like sh-, awk-, perl-, tcl- or
-;; makefile-mode to insert or update a suitable #! line at the beginning of
-;; the file, if the file does not already have one and the file is not a
-;; default file of that interpreter (like .profile or makefile). It also
-;; makes the file executable if it wasn't, as soon as it's saved.
-
-;; It also allows debugging scripts, with an adaptation of compile, as far
-;; as interpreters give out meaningful error messages.
-
-;; Modes that use this should nconc `executable-map' to the end of their own
-;; keymap and `executable-font-lock-keywords' to the end of their own font
-;; lock keywords. Their mode-setting commands should call
-;; `executable-set-magic'.
-
-;;; Code:
-
-(defvar executable-insert t
- "*Non-nil means offer to add a magic number to a file.
-This takes effect when you switch to certain major modes,
-including Shell-script mode (`sh-mode').
-When you type \\[executable-set-magic], it always offers to add or
-update the magic number.")
-
-(defvar executable-query 'function
- "*If non-nil, ask user before changing an existing magic number.
-When this is `function', only ask when called non-interactively.")
-
-
-(defvar executable-magicless-file-regexp "/[Mm]akefile$\\|/\\.\\(z?profile\\|bash_profile\\|z?login\\|bash_login\\|z?logout\\|bash_logout\\|.+shrc\\|esrc\\|rcrc\\|[kz]shenv\\)$"
- "*On files with this kind of name no magic is inserted or changed.")
-
-
-(defvar executable-prefix "#! "
- "*Interpreter magic number prefix inserted when there was no magic number.")
-
-
-
-(defvar executable-chmod 73
- "*After saving, if the file is not executable, set this mode.
-This mode passed to `set-file-modes' is taken absolutely when negative, or
-relative to the files existing modes. Do nothing if this is nil.
-Typical values are 73 (+x) or -493 (rwxr-xr-x).")
-
-
-(defvar executable-command nil)
-
-(defvar executable-self-display "tail"
- "*Command you use with argument `+2' to make text files self-display.
-Note that the like of `more' doesn't work too well under Emacs \\[shell].")
-
-
-(defvar executable-font-lock-keywords
- '(("\\`#!.*/\\([^ \t\n]+\\)" 1 font-lock-keyword-face t))
- "*Rules for highlighting executable scripts' magic number.
-This can be included in `font-lock-keywords' by modes that call `executable'.")
-
-
-(defvar executable-error-regexp-alist
- '(;; /bin/xyz: syntax error at line 14: `(' unexpected
- ;; /bin/xyz[5]: syntax error at line 8 : ``' unmatched
- ("^\\(.*[^[/]\\)\\(\\[[0-9]+\\]\\)?: .* error .* line \\([0-9]+\\)" 1 3)
- ;; /bin/xyz[27]: ehco: not found
- ("^\\(.*[^/]\\)\\[\\([0-9]+\\)\\]: .*: " 1 2)
- ;; /bin/xyz: syntax error near unexpected token `)'
- ;; /bin/xyz: /bin/xyz: line 2: `)'
- ("^\\(.*[^/]\\): [^0-9\n]+\n\\1: \\1: line \\([0-9]+\\):" 1 2)
- ;; /usr/bin/awk: syntax error at line 5 of file /bin/xyz
- (" error .* line \\([0-9]+\\) of file \\(.+\\)$" 2 1)
- ;; /usr/bin/awk: calling undefined function toto
- ;; input record number 3, file awktestdata
- ;; source line 4 of file /bin/xyz
- ("^[^ ].+\n\\( .+\n\\)* line \\([0-9]+\\) of file \\(.+\\)$" 3 2)
- ;; makefile:1: *** target pattern contains no `%'. Stop.
- ("^\\(.+\\):\\([0-9]+\\): " 1 2))
- "Alist of regexps used to match script errors.
-See `compilation-error-regexp-alist'.")
-
-;; The C function openp slightly modified would do the trick fine
-(defun executable-find (command)
- "Search for COMMAND in exec-path and return the absolute file name.
-Return nil if COMMAND is not found anywhere in `exec-path'."
- (let ((list exec-path)
- file)
- (while list
- (setq list (if (and (setq file (expand-file-name command (car list)))
- (file-executable-p file)
- (not (file-directory-p file)))
- nil
- (setq file nil)
- (cdr list))))
- file))
-
-
-(defun executable-chmod ()
- "This gets called after saving a file to assure that it be executable.
-You can set the absolute or relative mode in variable `executable-chmod' for
-non-executable files."
- (and executable-chmod
- buffer-file-name
- (or (file-executable-p buffer-file-name)
- (set-file-modes buffer-file-name
- (if (< executable-chmod 0)
- (- executable-chmod)
- (logior executable-chmod
- (file-modes buffer-file-name)))))))
-
-
-(defun executable-interpret (command)
- "Run script with user-specified args, and collect output in a buffer.
-While script runs asynchronously, you can use the \\[next-error] command
-to find the next error."
- (interactive (list (read-string "Run script: "
- (or executable-command
- buffer-file-name))))
- (require 'compile)
- (save-some-buffers (not compilation-ask-about-save))
- (make-local-variable 'executable-command)
- (compile-internal (setq executable-command command)
- "No more errors." "Interpretation"
- ;; Give it a simpler regexp to match.
- nil executable-error-regexp-alist))
-
-
-
-;;;###autoload
-(defun executable-set-magic (interpreter &optional argument
- no-query-flag insert-flag)
- "Set this buffer's interpreter to INTERPRETER with optional ARGUMENT.
-The variables `executable-magicless-file-regexp', `executable-prefix',
-`executable-insert', `executable-query' and `executable-chmod' control
-when and how magic numbers are inserted or replaced and scripts made
-executable."
- (interactive
- (let* ((name (read-string "Name or file name of interpreter: "))
- (arg (read-string (format "Argument for %s: " name))))
- (list name arg (eq executable-query 'function) t)))
- (setq interpreter (if (file-name-absolute-p interpreter)
- interpreter
- (or (executable-find interpreter)
- (error "Interpreter %s not recognized" interpreter)))
- argument (concat interpreter
- (and argument (string< "" argument) " ")
- argument))
- (or buffer-read-only
- (if buffer-file-name
- (string-match executable-magicless-file-regexp
- buffer-file-name))
- (not (or insert-flag executable-insert))
- (> (point-min) 1)
- (save-excursion
- (let ((point (point-marker))
- (buffer-modified-p (buffer-modified-p)))
- (goto-char (point-min))
- (make-local-hook 'after-save-hook)
- (add-hook 'after-save-hook 'executable-chmod nil t)
- (if (looking-at "#![ \t]*\\(.*\\)$")
- (and (goto-char (match-beginning 1))
- ;; If the line ends in a space,
- ;; don't offer to change it.
- (not (= (char-after (1- (match-end 1))) ?\ ))
- (not (string= argument
- (buffer-substring (point) (match-end 1))))
- (if (or (not executable-query) no-query-flag
- (save-window-excursion
- ;; Make buffer visible before question.
- (switch-to-buffer (current-buffer))
- (y-or-n-p (concat "Replace magic number by `"
- executable-prefix argument "'? "))))
- (progn
- (replace-match argument t t nil 1)
- (message "Magic number changed to `%s'"
- (concat executable-prefix argument)))))
- (insert executable-prefix argument ?\n)
- (message "Magic number changed to `%s'"
- (concat executable-prefix argument)))
-;;; (or insert-flag
-;;; (eq executable-insert t)
-;;; (set-buffer-modified-p buffer-modified-p))
- )))
- interpreter)
-
-
-
-;;;###autoload
-(defun executable-self-display ()
- "Turn a text file into a self-displaying Un*x command.
-The magic number of such a command displays all lines but itself."
- (interactive)
- (if (eq this-command 'executable-self-display)
- (setq this-command 'executable-set-magic))
- (executable-set-magic executable-self-display "+2"))
-
-
-
-(provide 'executable)
-
-;; executable.el ends here
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el
deleted file mode 100644
index ada277ffc05..00000000000
--- a/lisp/progmodes/f90.el
+++ /dev/null
@@ -1,1697 +0,0 @@
-;;; f90.el --- Fortran-90 mode (free format)
-
-;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Torbj\"orn Einarsson <T.Einarsson@clab.ericsson.se>
-;; Last Change: Oct. 14, 1996
-;; Keywords: fortran, f90, languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Smart mode for editing F90 programs in FREE FORMAT.
-;; Knows about continuation lines, named structured statements, and other
-;; new features in F90 including HPF (High Performance Fortran) structures.
-;; The basic feature is to provide an accurate indentation of F90 programs.
-;; In addition, there are many more features like automatic matching of all
-;; end statements, an auto-fill function to break long lines, a join-lines
-;; function which joins continued lines etc etc.
-;; To facilitate typing, a fairly complete list of abbreviations is provided.
-;; For example, `i is short-hand for integer (if abbrev-mode is on).
-
-;; There are two separate features for highlighting the code.
-;; 1) Upcasing or capitalizing of all keywords.
-;; 2) Colors/fonts using font-lock-mode. (only when using X-windows)
-;; Automatic upcase of downcase of keywords is controlled by the parameter
-;; f90-auto-keyword-case.
-
-;; The indentations of lines starting with ! is determined by the first of the
-;; following matches (the values in the left column are the default values):
-
-;; start-string/regexp indent variable holding start-string/regexp
-;; !!! 0
-;; !hpf\\$ (re) 0 f90-directive-comment-re
-;; !!$ 0 f90-comment-region
-;; ! (re) as code f90-indented-comment-re
-;; default comment-column
-
-;; Ex: Here is the result of 3 different settings of f90-indented-comment-re
-;; f90-indented-comment-re !-indentation !!-indentation
-;; ! as code as code
-;; !! comment-column as code
-;; ![^!] as code comment-column
-;; Trailing comments are indented to comment-column with indent-for-comment M-;
-;; f90-comment-region (C-c;) toggles insertion of f90-comment-region in region.
-
-;; One common convention for free vs. fixed format is that free-format files
-;; have the ending .f90 while the fixed format files have the ending .f.
-;; To make f90-mode work, put this file in, for example, your directory
-;; ~/lisp, and be sure that you have the following in your .emacs-file
-;; (setq load-path (append load-path '("~/lisp")))
-;; (autoload 'f90-mode "f90"
-;; "Major mode for editing Fortran 90 code in free format." t)
-;; (setq auto-mode-alist (append auto-mode-alist
-;; (list '("\\.f90$" . f90-mode))))
-;; Once you have entered f90-mode, you may get more info by using
-;; the command describe-mode (C-h m). For online help describing various
-;; functions use C-h f <Name of function you want described>
-
-;; To customize the f90-mode for your taste, use, for example:
-;; (you don't have to specify values for all the parameters below)
-;;(setq f90-mode-hook
-;; '(lambda () (setq f90-do-indent 3
-;; f90-if-indent 3
-;; f90-type-indent 3
-;; f90-program-indent 2
-;; f90-continuation-indent 5
-;; f90-comment-region "!!$"
-;; f90-directive-comment-re "!hpf\\$"
-;; f90-indented-comment-re "!"
-;; f90-break-delimiters "[-+\\*/,><=% \t]"
-;; f90-break-before-delimiters t
-;; f90-beginning-ampersand t
-;; f90-smart-end 'blink
-;; f90-auto-keyword-case nil
-;; f90-leave-line-no nil
-;; f90-startup-message t
-;; indent-tabs-mode nil
-;; f90-font-lock-keywords f90-font-lock-keywords-2
-;; )
-;; ;;The rest is not default.
-;; (abbrev-mode 1) ; turn on abbreviation mode
-;; (turn-on-font-lock) ; for highlighting
-;; (f90-add-imenu-menu) ; extra menu with functions etc.
-;; (if f90-auto-keyword-case ; change case of all keywords on startup
-;; (f90-change-keywords f90-auto-keyword-case))
-;; ))
-;; in your .emacs file (the shown values are the defaults). You can also
-;; change the values of the lists f90-keywords etc.
-;; The auto-fill and abbreviation minor modes are accessible from the menu,
-;; or by using M-x auto-fill-mode and M-x abbrev-mode, respectively.
-
-;; Remarks
-;; 1) Line numbers are by default left-justified. If f90-leave-line-no is
-;; non-nil, the line numbers are never touched.
-;; 2) Multi-; statements like > do i=1,20 ; j=j+i ; end do < are not handled
-;; correctly, but I imagine them to be rare.
-;; 3) Regexps for hilit19 are no longer supported.
-;; 4) For FIXED FORMAT code, use the ordinary fortran mode.
-;; 5) This mode does not work under emacs-18.x.
-;; 6) Preprocessor directives, i.e., lines starting with # are left-justified
-;; and are untouched by all case-changing commands. There is, at present, no
-;; mechanism for treating multi-line directives (continued by \ ).
-;; 7) f77 do-loops do 10 i=.. ; ; 10 continue are not correctly indented.
-;; You are urged to use f90-do loops (with labels if you wish).
-;; 8) The highlighting mode under XEmacs is not as complete as under Emacs.
-
-;; List of user commands
-;; f90-previous-statement f90-next-statement
-;; f90-beginning-of-subprogram f90-end-of-subprogram f90-mark-subprogram
-;; f90-comment-region
-;; f90-indent-line f90-indent-new-line
-;; f90-indent-region (can be called by calling indent-region)
-;; f90-indent-subprogram
-;; f90-break-line f90-join-lines
-;; f90-fill-region
-;; f90-insert-end
-;; f90-upcase-keywords f90-upcase-region-keywords
-;; f90-downcase-keywords f90-downcase-region-keywords
-;; f90-capitalize-keywords f90-capitalize-region-keywords
-;; f90-add-imenu-menu
-;; f90-font-lock-1, f90-font-lock-2, f90-font-lock-3, f90-font-lock-4
-
-;; Thanks to all the people who have tested the mode. Special thanks to Jens
-;; Bloch Helmers for encouraging me to write this code, for creative
-;; suggestions as well as for the lists of hpf-commands.
-;; Also thanks to the authors of the fortran and pascal modes, on which some
-;; of this code is built.
-
-;;; Code:
-
-(defconst bug-f90-mode "T.Einarsson@clab.ericsson.se"
- "Address of mailing list for F90 mode bugs.")
-
-;; User options
-(defvar f90-do-indent 3
- "*Extra indentation applied to DO blocks.")
-
-(defvar f90-if-indent 3
- "*Extra indentation applied to IF, SELECT CASE, WHERE and FORALL blocks.")
-
-(defvar f90-type-indent 3
- "*Extra indentation applied to TYPE, INTERFACE and BLOCK DATA blocks.")
-
-(defvar f90-program-indent 2
- "*Extra indentation applied to PROGRAM/MODULE/SUBROUTINE/FUNCTION blocks.")
-
-(defvar f90-continuation-indent 5
- "*Extra indentation applied to F90 continuation lines.")
-
-(defvar f90-comment-region "!!$"
- "*String inserted by \\[f90-comment-region]\
- at start of each line in region.")
-
-(defvar f90-indented-comment-re "!"
- "*Regexp saying which comments to be indented like code.")
-
-(defvar f90-directive-comment-re "!hpf\\$"
- "*Regexp of comment-like directive like \"!HPF\\\\$\", not to be indented.")
-
-(defvar f90-beginning-ampersand t
- "*t makes automatic insertion of \& at beginning of continuation line.")
-
-(defvar f90-smart-end 'blink
- "*From an END statement, check and fill the end using matching block start.
-Allowed values are 'blink, 'no-blink, and nil, which determine
-whether to blink the matching beginning.")
-
-(defvar f90-break-delimiters "[-+\\*/><=,% \t]"
- "*Regexp holding list of delimiters at which lines may be broken.")
-
-(defvar f90-break-before-delimiters t
- "*Non-nil causes `f90-do-auto-fill' to break lines before delimiters.")
-
-(defvar f90-auto-keyword-case nil
- "*Automatic case conversion of keywords.
- The options are 'downcase-word, 'upcase-word, 'capitalize-word and nil")
-
-(defvar f90-leave-line-no nil
- "*If nil, left-justify linenumbers.")
-
-(defvar f90-startup-message t
- "*Non-nil displays a startup message when F90 mode is first called.")
-
-(defconst f90-keywords-re
- ;;("allocate" "allocatable" "assign" "assignment" "backspace" "block"
- ;;"call" "case" "character" "close" "common" "complex" "contains"
- ;;"continue" "cycle" "data" "deallocate" "dimension" "do" "double" "else"
- ;;"elseif" "elsewhere" "end" "enddo" "endfile" "endif" "entry" "equivalence"
- ;;"exit" "external" "forall" "format" "function" "goto" "if" "implicit"
- ;;"include" "inquire" "integer" "intent" "interface" "intrinsic" "logical"
- ;;"module" "namelist" "none" "nullify" "only" "open" "operator" "optional" "parameter"
- ;;"pause" "pointer" "precision" "print" "private" "procedure" "program"
- ;;"public" "read" "real" "recursive" "result" "return" "rewind" "save" "select"
- ;;"sequence" "stop" "subroutine" "target" "then" "type" "use" "where"
- ;;"while" "write")
- (concat
- "\\<\\(a\\(llocat\\(able\\|e\\)\\|ssign\\(\\|ment\\)\\)\\|b\\(ackspace\\|"
- "lock\\)\\|c\\(a\\(ll\\|se\\)\\|haracter\\|lose\\|o\\(m\\(mon\\|plex\\)\\|"
- "nt\\(ains\\|inue\\)\\)\\|ycle\\)\\|d\\(ata\\|eallocate\\|imension\\|"
- "o\\(\\|uble\\)\\)\\|e\\(lse\\(\\|if\\|where\\)\\|n\\(d\\(\\|do\\|file\\|"
- "if\\)\\|try\\)\\|quivalence\\|x\\(it\\|ternal\\)\\)\\|f\\(or\\(all\\|"
- "mat\\)\\|unction\\)\\|goto\\|i\\(f\\|mplicit\\|n\\(clude\\|quire\\|t\\("
- "e\\(ger\\|nt\\|rface\\)\\|rinsic\\)\\)\\)\\|logical\\|module\\|n\\("
- "amelist\\|one\\|ullify\\)\\|o\\(nly\\|p\\(en\\|erator\\|tional\\)\\)\\|p\\(a\\("
- "rameter\\|use\\)\\|ointer\\|r\\(ecision\\|i\\(nt\\|vate\\)\\|o\\("
- "cedure\\|gram\\)\\)\\|ublic\\)\\|re\\(a[dl]\\|cursive\\|sult\\|turn\\|wind\\)\\|"
- "s\\(ave\\|e\\(lect\\|quence\\)\\|top\\|ubroutine\\)\\|t\\(arget\\|hen\\|"
- "ype\\)\\|use\\|w\\(h\\(ere\\|ile\\)\\|rite\\)\\)\\>")
- "Regexp for F90 keywords.")
-
-(defconst f90-keywords-level-3-re
- ;; ("allocate" "allocatable" "assign" "assignment" "backspace" "close"
- ;; "deallocate" "dimension" "endfile" "entry" "equivalence" "external"
- ;; "inquire" "intent" "intrinsic" "nullify" "only" "open" "operator"
- ;; "optional" "parameter" "pause" "pointer" "print" "private" "public"
- ;; "read" "recursive" "result" "rewind" "save" "select" "sequence"
- ;; "target" "write")
- (concat
- "\\<\\(a\\(llocat\\(able\\|e\\)\\|ssign\\(\\|ment\\)\\)\\|backspace\\|"
- "close\\|d\\(eallocate\\|imension\\)\\|e\\(n\\(dfile\\|try\\)\\|"
- "quivalence\\|xternal\\)\\|"
- "in\\(quire\\|t\\(ent\\|rinsic\\)\\)\\|nullify\\|"
- "o\\(nly\\|p\\(en\\|erator\\|tional\\)\\)\\|"
- "p\\(a\\(rameter\\|use\\)\\|ointer\\|ri\\(nt\\|vate\\)\\|ublic\\)\\|re\\("
- "ad\\|cursive\\|sult\\|wind\\)\\|s\\(ave\\|e\\(lect\\|quence\\)\\)\\|target\\|"
- "write\\)\\>")
-"Keyword-regexp for font-lock level >= 3.")
-
-
-(defconst f90-procedures-re
- ;; ("abs" "achar" "acos" "adjustl" "adjustr" "aimag" "aint" "all" "allocated"
- ;; "anint" "any" "asin" "associated" "atan" "atan2" "bit_size" "btest"
- ;; "ceiling" "char" "cmplx" "conjg" "cos" "cosh" "count" "cshift"
- ;; "date_and_time" "dble" "digits" "dim" "dot_product" "dprod" "eoshift"
- ;; "epsilon" "exp" "exponent" "floor" "fraction" "huge" "iachar" "iand"
- ;; "ibclr" "ibits" "ibset" "ichar" "ieor" "index" "int" "ior" "ishft"
- ;; "ishftc" "kind" "lbound" "len" "len_trim" "lge" "lgt" "lle" "llt" "log"
- ;; "logical" "log10" "matmul" "max" "maxexponent" "maxloc" "maxval" "merge"
- ;; "min" "minexponent" "minloc" "minval" "mod" "modulo" "mvbits" "nearest"
- ;; "nint" "not" "pack" "precision" "present" "product" "radix"
- ;; "random_number" "random_seed" "range" "real" "repeat" "reshape"
- ;; "rrspacing" "scale" "scan" "selected_int_kind" "selected_real_kind"
- ;; "set_exponent" "shape" "sign" "sin" "sinh" "size" "spacing" "spread"
- ;; "sqrt" "sum" "system_clock" "tan" "tanh" "tiny" "transfer" "transpose"
- ;; "trim" "ubound" "unpack" "verify")
- ;; A left parenthesis to avoid highlighting non-procedures.
- ;; Real is taken out here to avoid highlighting declarations.
- (concat
- "\\<\\(a\\(bs\\|c\\(har\\|os\\)\\|djust[lr]\\|i\\(mag\\|nt\\)\\|ll\\(\\|"
- "ocated\\)\\|n\\(int\\|y\\)\\|s\\(in\\|sociated\\)\\|tan2?\\)\\|b\\("
- "it_size\\|test\\)\\|c\\(eiling\\|har\\|mplx\\|o\\(njg\\|sh?\\|unt\\)\\|"
- "shift\\)\\|d\\(ate_and_time\\|ble\\|i\\(gits\\|m\\)\\|ot_product\\|prod"
- "\\)\\|e\\(oshift\\|psilon\\|xp\\(\\|onent\\)\\)\\|f\\(loor\\|"
- "raction\\)\\|huge\\|i\\(a\\(char\\|nd\\)\\|b\\(clr\\|its\\|set\\)\\|"
- "char\\|eor\\|n\\(dex\\|t\\)\\|or\\|shftc?\\)\\|kind\\|l\\(bound\\|"
- "en\\(\\|_trim\\)\\|g[et]\\|l[et]\\|og\\(\\|10\\|ical\\)\\)\\|m\\(a\\("
- "tmul\\|x\\(\\|exponent\\|loc\\|val\\)\\)\\|erge\\|in\\(\\|exponent\\|"
- "loc\\|val\\)\\|od\\(\\|ulo\\)\\|vbits\\)\\|n\\(earest\\|int\\|ot\\)\\|"
- "p\\(ack\\|r\\(e\\(cision\\|sent\\)\\|oduct\\)\\)\\|r\\(a\\(dix\\|n\\("
- "dom_\\(number\\|seed\\)\\|ge\\)\\)\\|e\\(peat\\|shape\\)\\|rspacing\\)\\|"
- "s\\(ca\\(le\\|n\\)\\|e\\(lected_\\(int_kind\\|real_kind\\)\\|"
- "t_exponent\\)\\|hape\\|i\\(gn\\|nh?\\|ze\\)\\|p\\(acing\\|read\\)\\|"
- "qrt\\|um\\|ystem_clock\\)\\|t\\(anh?\\|iny\\|r\\(ans\\(fer\\|pose\\)\\|"
- "im\\)\\)\\|u\\(bound\\|npack\\)\\|verify\\)[ \t]*(")
- "Regexp whose first part matches F90 intrinsic procedures.")
-
-(defconst f90-operators-re
-;; "and" "or" "not" "eqv" "neqv" "eq" "ne" "lt" "le" "gt" "ge" "true" "false"
- (concat
- "\\.\\(and\\|eqv?\\|false\\|g[et]\\|l[et]\\|n\\(e\\(\\|qv\\)\\|"
- "ot\\)\\|or\\|true\\)\\.")
- "Regexp matching intrinsic operators.")
-
-(defconst f90-hpf-keywords-re
- ;; Intrinsic procedures
- ;; ("all_prefix" "all_scatter" "all_suffix" "any_prefix" "any_scatter"
- ;; "any_suffix" "copy_prefix" "copy_scatter" "copy_suffix" "count_prefix"
- ;; "count_scatter" "count_suffix" "grade_down" "grade_up" "hpf_alignment"
- ;; "hpf_template" "hpf_distribution" "iall" "iall_prefix" "iall_scatter"
- ;; "iall_suffix" "iany" "iany_prefix" "iany_scatter" "iany_suffix" "iparity"
- ;; "iparity_prefix" "iparity_scatter" "iparity_suffix" "leadz"
- ;; "maxval_prefix" "maxval_scatter" "maxval_suffix" "minval_prefix"
- ;; "minval_scatter" "minval_suffix" "parity" "parity_prefix"
- ;; "parity_scatter" "parity_suffix" "popcnt" "poppar" "product_prefix"
- ;; "product_scatter" "product_suffix" "sum_prefix" "sum_scatter"
- ;; "sum_suffix" "ilen" "number_of_processors" "processors_shape")
- ;; Directives
- ;; ("align" "distribute" "dynamic" "inherit" "template" "processors"
- ;; "realign" "redistribute" "independent")
- ;; Keywords
- ;; ("pure" "extrinsic" "new" "with" "onto" "block" "cyclic")
- (concat
- "\\<\\(a\\(l\\(ign\\|l_\\(prefix\\|s\\(catter\\|uffix\\)\\)\\)\\|ny_\\("
- "prefix\\|s\\(catter\\|uffix\\)\\)\\)\\|block\\|c\\(o\\(py_\\(prefix\\|"
- "s\\(catter\\|uffix\\)\\)\\|unt_\\(prefix\\|s\\(catter\\|uffix\\)\\)\\)\\|"
- "yclic\\)\\|d\\(istribute\\|ynamic\\)\\|extrinsic\\|grade_\\(down\\|"
- "up\\)\\|hpf_\\(alignment\\|distribution\\|template\\)\\|i\\(a\\(ll\\(\\|"
- "_\\(prefix\\|s\\(catter\\|uffix\\)\\)\\)\\|ny\\(\\|_\\(prefix\\|s\\("
- "catter\\|uffix\\)\\)\\)\\)\\|len\\|n\\(dependent\\|herit\\)\\|parity\\(\\|"
- "_\\(prefix\\|s\\(catter\\|uffix\\)\\)\\)\\)\\|leadz\\|m\\(axval_\\("
- "prefix\\|s\\(catter\\|uffix\\)\\)\\|inval_\\(prefix\\|s\\(catter\\|"
- "uffix\\)\\)\\)\\|n\\(ew\\|umber_of_processors\\)\\|onto\\|p\\(arity\\(\\|"
- "_\\(prefix\\|s\\(catter\\|uffix\\)\\)\\)\\|op\\(cnt\\|par\\)\\|ro\\("
- "cessors\\(\\|_shape\\)\\|duct_\\(prefix\\|s\\(catter\\|uffix\\)\\)\\)\\|"
- "ure\\)\\|re\\(align\\|distribute\\)\\|sum_\\(prefix\\|s\\(catter\\|"
- "uffix\\)\\)\\|template\\|with\\)\\>")
- "Regexp for all HPF keywords, procedures and directives.")
-
-;; Highlighting patterns
-
-(defvar f90-font-lock-keywords-1
- (list ; Emacs
- '("\\<\\(end[ \t]*\\(program\\|module\\|function\\|subroutine\\|type\\)\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
- '("\\<\\(program\\|call\\|module\\|subroutine\\|function\\|use\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))
- ;; Special highlighting of "module procedure foo-list"
- '("\\<\\(module[ \t]*procedure\\)\\>" (1 font-lock-keyword-face t))
- ;; Highlight definition of new type
- '("\\<\\(type\\)[ \t]*\\(,.*::[ \t]*\\|[ \t]+\\)\\(\\sw+\\)"
- (1 font-lock-keyword-face) (3 font-lock-function-name-face))
- "\\<\\(\\(end[ \t]*\\)?\\(interface\\|block[ \t]*data\\)\\|contains\\)\\>")
- "This does fairly subdued highlighting of comments and function calls.")
-
-(defvar f90-font-lock-keywords-2
- (append f90-font-lock-keywords-1
- (list
- ;; Variable declarations (avoid the real function call)
- '("^[ \t0-9]*\\(real\\|integer\\|c\\(haracter\\|omplex\\)\\|logical\\|type[ \t]*(\\sw+)\\)\\(.*::\\|[ \t]*(.*)\\)?\\([^!\n]*\\)"
- (1 font-lock-type-face) (4 font-lock-variable-name-face))
- ;; do, if, select, where, and forall constructs
- '("\\<\\(end[ \t]*\\(do\\|if\\|select\\|forall\\|where\\)\\)\\>\\([ \t]+\\(\\sw+\\)\\)?"
- (1 font-lock-keyword-face) (3 font-lock-reference-face nil t))
- '("^[ \t0-9]*\\(\\(\\sw+\\)[ \t]*:[ \t]*\\)?\\(\\(if\\|do\\([ \t]*while\\)?\\|select[ \t]*case\\|where\\|forall\\)\\)\\>"
- (2 font-lock-reference-face nil t) (3 font-lock-keyword-face))
- ;; implicit declaration
- '("\\<\\(implicit\\)[ \t]*\\(real\\|integer\\|c\\(haracter\\|omplex\\)\\|logical\\|type[ \t]*(\\sw+)\\|none\\)\\>" (1 font-lock-keyword-face) (2 font-lock-type-face))
- '("\\<\\(namelist\\|common\\)[ \t]*\/\\(\\sw+\\)?\/" (1 font-lock-keyword-face) (2 font-lock-reference-face nil t))
- "\\<else\\([ \t]*if\\|where\\)?\\>"
- "\\<\\(then\\|continue\\|format\\|include\\|stop\\|return\\)\\>"
- '("\\<\\(exit\\|cycle\\)[ \t]*\\(\\sw+\\)?\\>"
- (1 font-lock-keyword-face) (2 font-lock-reference-face nil t))
- '("\\<\\(case\\)[ \t]*\\(default\\|(\\)" . 1)
- '("\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)"
- (1 font-lock-keyword-face) (2 font-lock-reference-face))
- ;; line numbers (lines whose first character after number is letter)
- '("^[ \t]*\\([0-9]+\\)[ \t]*[a-z]+" (1 font-lock-reference-face t))))
- "Highlights declarations, do-loops and other constructions")
-
-(defvar f90-font-lock-keywords-3
- (append f90-font-lock-keywords-2
- (list
- f90-keywords-level-3-re
- f90-operators-re
- (if (string-match "XEmacs" emacs-version)
- (append (list f90-procedures-re) '(1 font-lock-keyword-face t))
- (list f90-procedures-re '(1 font-lock-keyword-face t)))
- "\\<real\\>" ; Avoid overwriting real defs.
- ))
- "Highlights all F90 keywords and intrinsic procedures.")
-
-(defvar f90-font-lock-keywords-4
- (append f90-font-lock-keywords-3
- (list f90-hpf-keywords-re))
- "Highlights all F90 and HPF keywords.")
-
-(defvar f90-font-lock-keywords
- f90-font-lock-keywords-2
- "*Default expressions to highlight in F90 mode.")
-
-;; syntax table
-(defvar f90-mode-syntax-table nil
- "Syntax table in use in F90 mode buffers.")
-
-(if f90-mode-syntax-table
- ()
- (setq f90-mode-syntax-table (make-syntax-table))
- (modify-syntax-entry ?\! "<" f90-mode-syntax-table) ; beg. comment
- (modify-syntax-entry ?\n ">" f90-mode-syntax-table) ; end comment
- (modify-syntax-entry ?_ "w" f90-mode-syntax-table) ; underscore in names
- (modify-syntax-entry ?\' "\"" f90-mode-syntax-table) ; string quote
- (modify-syntax-entry ?\" "\"" f90-mode-syntax-table) ; string quote
- (modify-syntax-entry ?\` "w" f90-mode-syntax-table) ; for abbrevs
- (modify-syntax-entry ?\r " " f90-mode-syntax-table) ; return is whitespace
- (modify-syntax-entry ?+ "." f90-mode-syntax-table)
- (modify-syntax-entry ?- "." f90-mode-syntax-table)
- (modify-syntax-entry ?= "." f90-mode-syntax-table)
- (modify-syntax-entry ?* "." f90-mode-syntax-table)
- (modify-syntax-entry ?/ "." f90-mode-syntax-table)
- (modify-syntax-entry ?\\ "/" f90-mode-syntax-table)) ; escape chars
-
-;; keys
-(defvar f90-mode-map ()
- "Keymap used in F90 mode.")
-
-(if f90-mode-map
- ()
- (setq f90-mode-map (make-sparse-keymap))
- (define-key f90-mode-map "`" 'f90-abbrev-start)
- (define-key f90-mode-map "\C-c;" 'f90-comment-region)
- (define-key f90-mode-map "\C-\M-a" 'f90-beginning-of-subprogram)
- (define-key f90-mode-map "\C-\M-e" 'f90-end-of-subprogram)
- (define-key f90-mode-map "\C-\M-h" 'f90-mark-subprogram)
- (define-key f90-mode-map "\C-\M-q" 'f90-indent-subprogram)
- (define-key f90-mode-map "\C-j" 'f90-indent-new-line) ; LFD equals C-j
- (define-key f90-mode-map "\r" 'newline)
- (define-key f90-mode-map "\C-c\r" 'f90-break-line)
- ;; (define-key f90-mode-map [M-return] 'f90-break-line)
- (define-key f90-mode-map "\C-c\C-d" 'f90-join-lines)
- (define-key f90-mode-map "\C-c\C-f" 'f90-fill-region)
- (define-key f90-mode-map "\C-c\C-p" 'f90-previous-statement)
- (define-key f90-mode-map "\C-c\C-n" 'f90-next-statement)
- (define-key f90-mode-map "\C-c\C-w" 'f90-insert-end)
- (define-key f90-mode-map "\t" 'f90-indent-line)
- (define-key f90-mode-map "," 'f90-electric-insert)
- (define-key f90-mode-map "+" 'f90-electric-insert)
- (define-key f90-mode-map "-" 'f90-electric-insert)
- (define-key f90-mode-map "*" 'f90-electric-insert)
- (define-key f90-mode-map "/" 'f90-electric-insert))
-
-
-;; menus
-(if (string-match "XEmacs" emacs-version)
- (defvar f90-xemacs-menu
- '("F90"
- ["Indent Subprogram" f90-indent-subprogram t]
- ["Mark Subprogram" f90-mark-subprogram t]
- ["Beginning of Subprogram" f90-beginning-of-subprogram t]
- ["End of Subprogram" f90-end-of-subprogram t]
- "-----"
- ["(Un)Comment Region" f90-comment-region t]
- ["Indent Region" indent-region t]
- ["Fill Region" f90-fill-region t]
- "-----"
- ["Break Line at Point" f90-break-line t]
- ["Join with Next Line" f90-join-lines t]
- ["Insert Newline" newline t]
- ["Insert Block End" f90-insert-end t]
- "-----"
- ["Upcase Keywords (buffer)" f90-upcase-keywords t]
- ["Upcase Keywords (region)" f90-upcase-region-keywords
- t]
- ["Capitalize Keywords (buffer)" f90-capitalize-keywords t]
- ["Capitalize Keywords (region)"
- f90-capitalize-region-keywords t]
- ["Downcase Keywords (buffer)" f90-downcase-keywords t]
- ["Downcase Keywords (region)"
- f90-downcase-region-keywords t]
- "-----"
- ["Toggle abbrev-mode" abbrev-mode t]
- ["Toggle auto-fill" auto-fill-mode t])
- "XEmacs menu for F90 mode.")
- ;; Emacs
-
- (defvar f90-change-case-menu
- (let ((map (make-sparse-keymap "Change Keyword Case")))
-
- (define-key map [dkr] (cons "Downcase Keywords (region)"
- 'f90-downcase-region-keywords))
- (put 'f90-downcase-region-keywords 'menu-enable 'mark-active)
-
- (define-key map [ckr] (cons "Capitalize Keywords (region)"
- 'f90-capitalize-region-keywords))
- (put 'f90-capitalize-region-keywords 'menu-enable 'mark-active)
-
- (define-key map [ukr] (cons "Upcase Keywords (region)"
- 'f90-upcase-region-keywords))
- (put 'f90-upcase-region-keywords 'menu-enable 'mark-active)
-
- (define-key map [line] (list "-----------------"))
-
- (define-key map [dkb] (cons "Downcase Keywords (buffer)"
- 'f90-downcase-keywords))
-
- (define-key map [ckb] (cons "Capitalize Keywords (buffer)"
- 'f90-capitalize-keywords))
-
- (define-key map [ukb] (cons "Upcase Keywords (buffer)"
- 'f90-upcase-keywords))
- map)
- "Submenu for change of case.")
- (defalias 'f90-change-case-menu f90-change-case-menu)
-
- ;; font-lock-menu and function calls
- (defalias 'f90-font-lock-on 'font-lock-mode)
- (defalias 'f90-font-lock-off 'font-lock-mode)
- (put 'f90-font-lock-on 'menu-enable 'font-lock-mode)
- (put 'f90-font-lock-off 'menu-enable '(not font-lock-mode))
-
- (defun f90-font-lock-1 ()
- (interactive)
- "Set font-lock-keywords to f90-font-lock-keywords-1."
- (font-lock-mode 1)
- (setq font-lock-keywords f90-font-lock-keywords-1)
- (font-lock-fontify-buffer))
-
- (defun f90-font-lock-2 ()
- (interactive)
- "Set font-lock-keywords to f90-font-lock-keywords-2."
- (font-lock-mode 1)
- (setq font-lock-keywords f90-font-lock-keywords-2)
- (font-lock-fontify-buffer))
-
- (defun f90-font-lock-3 ()
- (interactive)
- "Set font-lock-keywords to f90-font-lock-keywords-3."
- (font-lock-mode 1)
- (setq font-lock-keywords f90-font-lock-keywords-3)
- (font-lock-fontify-buffer))
-
- (defun f90-font-lock-4 ()
- (interactive)
- "Set font-lock-keywords to f90-font-lock-keywords-4."
- (font-lock-mode 1)
- (setq font-lock-keywords f90-font-lock-keywords-4)
- (font-lock-fontify-buffer))
-
- (defvar f90-font-lock-menu
- (let ((map (make-sparse-keymap "f90-font-lock-menu")))
- (define-key map [h4] (cons "Maximum highlighting (level 4)"
- 'f90-font-lock-4))
- (define-key map [h3] (cons "Heavy highlighting (level 3)"
- 'f90-font-lock-3))
- (define-key map [h2] (cons "Default highlighting (level 2)"
- 'f90-font-lock-2))
- (define-key map [h1] (cons "Light highlighting (level 1)"
- 'f90-font-lock-1))
- (define-key map [line] (list "-----------------"))
- (define-key map [floff] (cons "Turn off font-lock-mode"
- 'f90-font-lock-on))
- (define-key map [flon] (cons "Turn on font-lock-mode"
- 'f90-font-lock-off))
- map)
- "Submenu for highlighting using font-lock-mode.")
- (defalias 'f90-font-lock-menu f90-font-lock-menu)
-
- (define-key f90-mode-map [menu-bar] (make-sparse-keymap))
- (define-key f90-mode-map [menu-bar f90]
- (cons "F90" (make-sparse-keymap "f90")))
-
- (define-key f90-mode-map [menu-bar f90 f90-imenu-menu]
- '("Add imenu Menu" . f90-add-imenu-menu))
- (define-key f90-mode-map [menu-bar f90 abbrev-mode]
- '("Toggle abbrev-mode" . abbrev-mode))
- (define-key f90-mode-map [menu-bar f90 auto-fill-mode]
- '("Toggle auto-fill" . auto-fill-mode))
- (define-key f90-mode-map [menu-bar f90 line1]
- '("----"))
- (define-key f90-mode-map [menu-bar f90 f90-change-case-menu]
- (cons "Change Keyword Case" 'f90-change-case-menu))
- (define-key f90-mode-map [menu-bar f90 f90-font-lock-menu]
- (cons "Highlighting" 'f90-font-lock-menu))
- (define-key f90-mode-map [menu-bar f90 line2]
- '("----"))
-
- (define-key f90-mode-map [menu-bar f90 f90-insert-end]
- '("Insert Block End" . f90-insert-end))
- (define-key f90-mode-map [menu-bar f90 f90-join-lines]
- '("Join with Next Line" . f90-join-lines))
- (define-key f90-mode-map [menu-bar f90 f90-break-line]
- '("Break Line at Point" . f90-break-line))
-
- (define-key f90-mode-map [menu-bar f90 line3]
- '("----"))
-
- (define-key f90-mode-map [menu-bar f90 f90-fill-region]
- '("Fill Region" . f90-fill-region))
- (put 'f90-fill-region 'menu-enable 'mark-active)
-
- (define-key f90-mode-map [menu-bar f90 indent-region]
- '("Indent Region" . indent-region))
-
- (define-key f90-mode-map [menu-bar f90 f90-comment-region]
- '("(Un)Comment Region" . f90-comment-region))
- (put 'f90-comment-region 'menu-enable 'mark-active)
-
- (define-key f90-mode-map [menu-bar f90 line4]
- '("----"))
-
- (define-key f90-mode-map [menu-bar f90 f90-end-of-subprogram]
- '("End of Subprogram" . f90-end-of-subprogram))
- (define-key f90-mode-map [menu-bar f90 f90-beginning-of-subprogram]
- '("Beginning of Subprogram" . f90-beginning-of-subprogram))
- (define-key f90-mode-map [menu-bar f90 f90-mark-subprogram]
- '("Mark Subprogram" . f90-mark-subprogram))
- (define-key f90-mode-map [menu-bar f90 f90-indent-subprogram]
- '("Indent Subprogram" . f90-indent-subprogram))
- )
-
-;; Regexps for finding program structures.
-(defconst f90-blocks-re
- "\\(block[ \t]*data\\|do\\|if\\|interface\\|function\\|module\\|\
-program\\|select\\|subroutine\\|type\\|where\\|forall\\)\\>")
-(defconst f90-program-block-re
- "\\(program\\|module\\|subroutine\\|function\\)")
-(defconst f90-else-like-re
- "\\(else\\([ \t]*if\\|where\\)?\\|case[ \t]*\\(default\\|(\\)\\)")
-(defconst f90-end-if-re
- "end[ \t]*\\(if\\|select\\|where\\|forall\\)\\>")
-(defconst f90-end-type-re
- "end[ \t]*\\(type\\|interface\\|block[ \t]*data\\)")
-(defconst f90-type-def-re
- "\\<\\(type\\)[ \t]*\\(,.*::[ \t]*\\|[ \t]+\\)\\(\\sw+\\)")
-(defconst f90-no-break-re "\\(\\*\\*\\|//\\|=>\\)")
-;; A temporary position to make region operators faster
-(defvar f90-cache-position nil)
-(make-variable-buffer-local 'f90-cache-position)
-;; A flag to tell whether f90-imenu is turned on.
-(defvar f90-imenu nil)
-(make-variable-buffer-local 'f90-imenu)
-
-
-;; Imenu support
-(defvar f90-imenu-generic-expression
- (let ((good-char "[^!\"\&\n \t]") (not-e "[^e!\n\"\& \t]")
- (not-n "[^n!\n\"\& \t]") (not-d "[^d!\n\"\& \t]"))
- (list
- '(nil "^[ \t0-9]*program[ \t]+\\(\\sw+\\)" 1)
- '("Modules" "^[ \t0-9]*module[ \t]+\\(\\sw+\\)[ \t]*\\(!\\|$\\)" 1)
- '("Types" "^[ \t0-9]*type[ \t]+\\(\\sw+\\)" 1)
- (list
- "Procedures"
- (concat
- "^[ \t0-9]*"
- "\\("
- ;; At least three non-space characters before function/subroutine
- ;; Check that the last three non-space characters don't spell E N D
- "[^!\"\&\n]*\\("
- not-e good-char good-char "\\|"
- good-char not-n good-char "\\|"
- good-char good-char not-d "\\)"
- "\\|"
- ;; Less than three non-space characters before function/subroutine
- good-char "?" good-char "?"
- "\\)"
- "[ \t]*\\(function\\|subroutine\\)[ \t]+\\(\\sw+\\)")
- 4)))
- "imenu generic expression for F90 mode.")
-
-(defun f90-add-imenu-menu ()
- (interactive)
- "Add an imenu menu to the menubar."
- (if (not f90-imenu)
- (progn
- (imenu-add-to-menubar "F90-imenu")
- (redraw-frame (selected-frame))
- (setq f90-imenu t))
- (message "%s" "F90-imenu already exists.")))
-(put 'f90-add-imenu-menu 'menu-enable '(not f90-imenu))
-
-
-;; When compiling under GNU Emacs, load imenu during compilation. If
-;; you have 19.22 or earlier, comment this out, or get imenu.
-(and (fboundp 'eval-when-compile)
- (eval-when-compile
- (if (not (string-match "XEmacs" emacs-version))
- (require 'imenu))
- ()))
-
-;; abbrevs have generally two letters, except standard types `c, `i, `r, `t
-(defvar f90-mode-abbrev-table nil)
-(if f90-mode-abbrev-table
- ()
- (let ((ac abbrevs-changed))
- (define-abbrev-table 'f90-mode-abbrev-table ())
- (define-abbrev f90-mode-abbrev-table "`al" "allocate" nil)
- (define-abbrev f90-mode-abbrev-table "`ab" "allocatable" nil)
- (define-abbrev f90-mode-abbrev-table "`as" "assignment" nil)
- (define-abbrev f90-mode-abbrev-table "`ba" "backspace" nil)
- (define-abbrev f90-mode-abbrev-table "`bd" "block data" nil)
- (define-abbrev f90-mode-abbrev-table "`c" "character" nil)
- (define-abbrev f90-mode-abbrev-table "`cl" "close" nil)
- (define-abbrev f90-mode-abbrev-table "`cm" "common" nil)
- (define-abbrev f90-mode-abbrev-table "`cx" "complex" nil)
- (define-abbrev f90-mode-abbrev-table "`cn" "contains" nil)
- (define-abbrev f90-mode-abbrev-table "`cy" "cycle" nil)
- (define-abbrev f90-mode-abbrev-table "`de" "deallocate" nil)
- (define-abbrev f90-mode-abbrev-table "`df" "define" nil)
- (define-abbrev f90-mode-abbrev-table "`di" "dimension" nil)
- (define-abbrev f90-mode-abbrev-table "`dw" "do while" nil)
- (define-abbrev f90-mode-abbrev-table "`el" "else" nil)
- (define-abbrev f90-mode-abbrev-table "`eli" "else if" nil)
- (define-abbrev f90-mode-abbrev-table "`elw" "elsewhere" nil)
- (define-abbrev f90-mode-abbrev-table "`eq" "equivalence" nil)
- (define-abbrev f90-mode-abbrev-table "`ex" "external" nil)
- (define-abbrev f90-mode-abbrev-table "`ey" "entry" nil)
- (define-abbrev f90-mode-abbrev-table "`fl" "forall" nil)
- (define-abbrev f90-mode-abbrev-table "`fo" "format" nil)
- (define-abbrev f90-mode-abbrev-table "`fu" "function" nil)
- (define-abbrev f90-mode-abbrev-table "`fa" ".false." nil)
- (define-abbrev f90-mode-abbrev-table "`im" "implicit none" nil)
- (define-abbrev f90-mode-abbrev-table "`in " "include" nil)
- (define-abbrev f90-mode-abbrev-table "`i" "integer" nil)
- (define-abbrev f90-mode-abbrev-table "`it" "intent" nil)
- (define-abbrev f90-mode-abbrev-table "`if" "interface" nil)
- (define-abbrev f90-mode-abbrev-table "`lo" "logical" nil)
- (define-abbrev f90-mode-abbrev-table "`mo" "module" nil)
- (define-abbrev f90-mode-abbrev-table "`na" "namelist" nil)
- (define-abbrev f90-mode-abbrev-table "`nu" "nullify" nil)
- (define-abbrev f90-mode-abbrev-table "`op" "optional" nil)
- (define-abbrev f90-mode-abbrev-table "`pa" "parameter" nil)
- (define-abbrev f90-mode-abbrev-table "`po" "pointer" nil)
- (define-abbrev f90-mode-abbrev-table "`pr" "print" nil)
- (define-abbrev f90-mode-abbrev-table "`pi" "private" nil)
- (define-abbrev f90-mode-abbrev-table "`pm" "program" nil)
- (define-abbrev f90-mode-abbrev-table "`pu" "public" nil)
- (define-abbrev f90-mode-abbrev-table "`r" "real" nil)
- (define-abbrev f90-mode-abbrev-table "`rc" "recursive" nil)
- (define-abbrev f90-mode-abbrev-table "`rt" "return" nil)
- (define-abbrev f90-mode-abbrev-table "`rw" "rewind" nil)
- (define-abbrev f90-mode-abbrev-table "`se" "select" nil)
- (define-abbrev f90-mode-abbrev-table "`sq" "sequence" nil)
- (define-abbrev f90-mode-abbrev-table "`su" "subroutine" nil)
- (define-abbrev f90-mode-abbrev-table "`ta" "target" nil)
- (define-abbrev f90-mode-abbrev-table "`tr" ".true." nil)
- (define-abbrev f90-mode-abbrev-table "`t" "type" nil)
- (define-abbrev f90-mode-abbrev-table "`wh" "where" nil)
- (define-abbrev f90-mode-abbrev-table "`wr" "write" nil)
- (setq abbrevs-changed ac)))
-
-;;;###autoload
-(defun f90-mode ()
- "Major mode for editing Fortran 90 code in free format.
-
-\\[f90-indent-new-line] corrects current indentation and creates new\
- indented line.
-\\[f90-indent-line] indents the current line correctly.
-\\[f90-indent-subprogram] indents the current subprogram.
-
-Type `? or `\\[help-command] to display a list of built-in\
- abbrevs for F90 keywords.
-
-Key definitions:
-\\{f90-mode-map}
-
-Variables controlling indentation style and extra features:
-
- f90-do-indent
- Extra indentation within do blocks. (default 3)
- f90-if-indent
- Extra indentation within if/select case/where/forall blocks. (default 3)
- f90-type-indent
- Extra indentation within type/interface/block-data blocks. (default 3)
- f90-program-indent
- Extra indentation within program/module/subroutine/function blocks.
- (default 2)
- f90-continuation-indent
- Extra indentation applied to continuation lines. (default 5)
- f90-comment-region
- String inserted by \\[f90-comment-region] at start of each line in
- region. (default \"!!!$\")
- f90-indented-comment-re
- Regexp determining the type of comment to be intended like code.
- (default \"!\")
- f90-directive-comment-re
- Regexp of comment-like directive like \"!HPF\\\\$\", not to be indented.
- (default \"!hpf\\\\$\")
- f90-break-delimiters
- Regexp holding list of delimiters at which lines may be broken.
- (default \"[-+*/><=,% \\t]\")
- f90-break-before-delimiters
- Non-nil causes `f90-do-auto-fill' to break lines before delimiters.
- (default t)
- f90-beginning-ampersand
- Automatic insertion of \& at beginning of continuation lines. (default t)
- f90-smart-end
- From an END statement, check and fill the end using matching block start.
- Allowed values are 'blink, 'no-blink, and nil, which determine
- whether to blink the matching beginning.) (default 'blink)
- f90-auto-keyword-case
- Automatic change of case of keywords. (default nil)
- The possibilities are 'downcase-word, 'upcase-word, 'capitalize-word.
- f90-leave-line-no
- Do not left-justify line numbers. (default nil)
- f90-startup-message
- Set to nil to inhibit message first time F90 mode is used. (default t)
- f90-keywords-re
- List of keywords used for highlighting/upcase-keywords etc.
-
-Turning on F90 mode calls the value of the variable `f90-mode-hook'
-with no args, if that value is non-nil."
- (interactive)
- (kill-all-local-variables)
- (setq major-mode 'f90-mode)
- (setq mode-name "F90")
- (setq local-abbrev-table f90-mode-abbrev-table)
- (set-syntax-table f90-mode-syntax-table)
- (use-local-map f90-mode-map)
- (make-local-variable 'indent-line-function)
- (setq indent-line-function 'f90-indent-line)
- (make-local-variable 'indent-region-function)
- (setq indent-region-function 'f90-indent-region)
- (make-local-variable 'require-final-newline)
- (setq require-final-newline t)
- (make-local-variable 'comment-start)
- (setq comment-start "!")
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip "!+ *")
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'f90-comment-indent)
- (make-local-variable 'abbrev-all-caps)
- (setq abbrev-all-caps t)
- (make-local-variable 'normal-auto-fill-function)
- (setq normal-auto-fill-function 'f90-do-auto-fill)
- (setq indent-tabs-mode nil)
- ;; Setting up things for font-lock
- (if (string-match "XEmacs" emacs-version)
- (progn
- (put 'f90-mode 'font-lock-keywords-case-fold-search t)
- (if (and current-menubar
- (not (assoc "F90" current-menubar)))
- (progn
- (set-buffer-menubar (copy-sequence current-menubar))
- (add-submenu nil f90-xemacs-menu)))
- (make-local-variable 'font-lock-keywords)
- (setq font-lock-keywords f90-font-lock-keywords))
- ;; Emacs
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(f90-font-lock-keywords nil t))
-
- ;; Tell imenu how to handle f90.
- (make-local-variable 'imenu-generic-expression)
- (setq imenu-generic-expression f90-imenu-generic-expression))
- (run-hooks 'f90-mode-hook)
- (if f90-startup-message
- (message "Emacs F90 mode; please report bugs to %s" bug-f90-mode))
- (setq f90-startup-message nil))
-
-;; inline-functions
-(defsubst f90-get-beg-of-line ()
- (save-excursion (beginning-of-line) (point)))
-
-(defsubst f90-get-end-of-line ()
- (save-excursion (end-of-line) (point)))
-
-(defsubst f90-in-string ()
- (let ((beg-pnt
- (if (and f90-cache-position (> (point) f90-cache-position))
- f90-cache-position
- (point-min))))
- (nth 3 (parse-partial-sexp beg-pnt (point)))))
-
-(defsubst f90-in-comment ()
- (let ((beg-pnt
- (if (and f90-cache-position (> (point) f90-cache-position))
- f90-cache-position
- (point-min))))
- (nth 4 (parse-partial-sexp beg-pnt (point)))))
-
-(defsubst f90-line-continued ()
- (save-excursion
- (let ((bol (f90-get-beg-of-line)))
- (end-of-line)
- (while (f90-in-comment)
- (search-backward "!" bol)
- (skip-chars-backward "!"))
- (skip-chars-backward " \t")
- (= (preceding-char) ?&))))
-
-(defsubst f90-current-indentation ()
- "Return indentation of current line.
-Line-numbers are considered whitespace characters."
- (save-excursion
- (beginning-of-line) (skip-chars-forward " \t0-9")
- (current-column)))
-
-(defsubst f90-indent-to (col &optional no-line-number)
- "Indent current line to column COL.
-If no-line-number nil, jump over a possible line-number."
- (beginning-of-line)
- (if (not no-line-number)
- (skip-chars-forward " \t0-9"))
- (delete-horizontal-space)
- (if (zerop (current-column))
- (indent-to col)
- (indent-to col 1)))
-
-(defsubst f90-match-piece (arg)
- (if (match-beginning arg)
- (buffer-substring (match-beginning arg) (match-end arg))))
-
-(defsubst f90-get-present-comment-type ()
- (save-excursion
- (let ((type nil) (eol (f90-get-end-of-line)))
- (if (f90-in-comment)
- (progn
- (beginning-of-line)
- (re-search-forward "[!]+" eol)
- (while (f90-in-string)
- (re-search-forward "[!]+" eol))
- (setq type (buffer-substring (match-beginning 0) (match-end 0)))))
- type)))
-
-(defsubst f90-equal-symbols (a b)
- "Compare strings neglecting case and allowing for nil value."
- (let ((a-local (if a (downcase a) nil))
- (b-local (if b (downcase b) nil)))
- (equal a-local b-local)))
-
-;; XEmacs 19.11 & 19.12 gives back a single char when matching an empty regular
-;; expression. Therefore, the next 2 functions are longer than necessary.
-
-(defsubst f90-looking-at-do ()
- "Return (\"do\" name) if a do statement starts after point.
-Name is nil if the statement has no label."
- (if (looking-at "\\(\\(\\sw+\\)[ \t]*\:\\)?[ \t]*\\(do\\)\\>")
- (let (label
- (struct (f90-match-piece 3)))
- (if (looking-at "\\(\\sw+\\)[ \t]*\:")
- (setq label (f90-match-piece 1)))
- (list struct label))))
-
-(defsubst f90-looking-at-select-case ()
- "Return (\"select\" name) if a select-case statement starts after point.
-Name is nil if the statement has no label."
- (if (looking-at "\\(\\(\\sw+\\)[ \t]*\:\\)?[ \t]*\\(select\\)[ \t]*case[ \t]*(")
- (let (label
- (struct (f90-match-piece 3)))
- (if (looking-at "\\(\\sw+\\)[ \t]*\:")
- (setq label (f90-match-piece 1)))
- (list struct label))))
-
-(defsubst f90-looking-at-if-then ()
- "Return (\"if\" name) if an if () then statement starts after point.
-Name is nil if the statement has no label."
- (save-excursion
- (let (struct (label nil))
- (if (looking-at "\\(\\(\\sw+\\)[ \t]*\:\\)?[ \t]*\\(if\\)\\>")
- (progn
- (setq struct (f90-match-piece 3))
- (if (looking-at "\\(\\sw+\\)[ \t]*\:")
- (setq label (f90-match-piece 1)))
- (goto-char (scan-lists (point) 1 0))
- (skip-chars-forward " \t")
- (if (or (looking-at "then\\>")
- (if (f90-line-continued)
- (progn
- (f90-next-statement)
- (skip-chars-forward " \t0-9&")
- (looking-at "then\\>"))))
- (list struct label)))))))
-
-(defsubst f90-looking-at-where-or-forall ()
- "Return (kind name) if a where or forall statement starts after point.
-Name is nil if the statement has no label."
- (if (looking-at "\\(\\(\\sw+\\)[ \t]*\:\\)?[ \t]*\\(where\\|forall\\)[ \t]*(")
- (let (label
- (struct (f90-match-piece 3)))
- (if (looking-at "\\(\\sw+\\)[ \t]*\:")
- (setq label (f90-match-piece 1)))
- (list struct label))))
-
-(defsubst f90-looking-at-type-like ()
- "Return (kind name) at the start of a type/interface/block-data block.
-Name is non-nil only for type."
- (cond
- ((looking-at f90-type-def-re)
- (list (f90-match-piece 1) (f90-match-piece 3)))
- ((looking-at "\\(interface\\|block[\t]*data\\)\\>")
- (list (f90-match-piece 1) nil))))
-
-(defsubst f90-looking-at-program-block-start ()
- "Return (kind name) if a program block with name name starts after point."
- (cond
- ((looking-at "\\(program\\)[ \t]+\\(\\sw+\\)\\>")
- (list (f90-match-piece 1) (f90-match-piece 2)))
- ((and (not (looking-at "module[ \t]*procedure\\>"))
- (looking-at "\\(module\\)[ \t]+\\(\\sw+\\)\\>"))
- (list (f90-match-piece 1) (f90-match-piece 2)))
- ((and (not (looking-at "end[ \t]*\\(function\\|subroutine\\)"))
- (looking-at "[^!\"\&\n]*\\(function\\|subroutine\\)[ \t]+\\(\\sw+\\)"))
- (list (f90-match-piece 1) (f90-match-piece 2)))))
-
-(defsubst f90-looking-at-program-block-end ()
- "Return list of type and name of end of block."
- (if (looking-at (concat "end[ \t]*" f90-blocks-re
- "?\\([ \t]+\\(\\sw+\\)\\)?\\>"))
- (list (f90-match-piece 1) (f90-match-piece 3))))
-
-(defsubst f90-comment-indent ()
- (cond ((looking-at "!!!") 0)
- ((and f90-directive-comment-re
- (looking-at f90-directive-comment-re)) 0)
- ((looking-at (regexp-quote f90-comment-region)) 0)
- ((looking-at f90-indented-comment-re)
- (f90-calculate-indent))
- (t (skip-chars-backward " \t")
- (max (if (bolp) 0 (1+ (current-column))) comment-column))))
-
-(defsubst f90-present-statement-cont ()
- "Return continuation properties of present statement."
- (let (pcont cont)
- (save-excursion
- (setq pcont (if (f90-previous-statement) (f90-line-continued) nil)))
- (setq cont (f90-line-continued))
- (cond ((and (not pcont) (not cont)) 'single)
- ((and (not pcont) cont) 'begin)
- ((and pcont (not cont)) 'end)
- ((and pcont cont) 'middle)
- (t (error)))))
-
-(defsubst f90-indent-line-no ()
- (if f90-leave-line-no
- ()
- (if (and (not (zerop (skip-chars-forward " \t")))
- (looking-at "[0-9]"))
- (delete-horizontal-space)))
- (skip-chars-forward " \t0-9"))
-
-(defsubst f90-no-block-limit ()
- (let ((eol (f90-get-end-of-line)))
- (save-excursion
- (not (or (looking-at "end")
- (looking-at "\\(do\\|if\\|else\\(if\\|where\\)?\
-\\|select[ \t]*case\\|case\\|where\\|forall\\)\\>")
- (looking-at "\\(program\\|module\\|interface\\|\
-block[ \t]*data\\)\\>")
- (looking-at "\\(contains\\|\\sw+[ \t]*:\\)")
- (looking-at f90-type-def-re)
- (re-search-forward "\\(function\\|subroutine\\)" eol t))))))
-
-(defsubst f90-update-line ()
- (let (bol eol)
- (if f90-auto-keyword-case
- (progn (setq bol (f90-get-beg-of-line)
- eol (f90-get-end-of-line))
- (if f90-auto-keyword-case
- (f90-change-keywords f90-auto-keyword-case bol eol))))))
-
-(defun f90-electric-insert ()
- (interactive)
- "Calls f90-do-auto-fill at each operator insertion."
- (self-insert-command 1)
- (f90-update-line)
- (if auto-fill-function (f90-do-auto-fill)))
-
-(defun f90-get-correct-indent ()
- "Get correct indent for a line starting with line number.
-Does not check type and subprogram indentation."
- (let ((epnt (f90-get-end-of-line)) icol cont)
- (save-excursion
- (while (and (f90-previous-statement)
- (or (progn
- (setq cont (f90-present-statement-cont))
- (or (eq cont 'end) (eq cont 'middle)))
- (looking-at "[ \t]*[0-9]"))))
- (setq icol (current-indentation))
- (beginning-of-line)
- (if (re-search-forward "\\(if\\|do\\|select\\|where\\|forall\\)"
- (f90-get-end-of-line) t)
- (progn
- (beginning-of-line) (skip-chars-forward " \t")
- (cond ((f90-looking-at-do)
- (setq icol (+ icol f90-do-indent)))
- ((or (f90-looking-at-if-then)
- (f90-looking-at-where-or-forall)
- (f90-looking-at-select-case))
- (setq icol (+ icol f90-if-indent))))
- (end-of-line)))
- (while (re-search-forward
- "\\(if\\|do\\|select\\|where\\|forall\\)" epnt t)
- (beginning-of-line) (skip-chars-forward " \t0-9")
- (cond ((f90-looking-at-do)
- (setq icol (+ icol f90-do-indent)))
- ((or (f90-looking-at-if-then)
- (f90-looking-at-where-or-forall)
- (f90-looking-at-select-case))
- (setq icol (+ icol f90-if-indent)))
- ((looking-at f90-end-if-re)
- (setq icol (- icol f90-if-indent)))
- ((looking-at "end[ \t]*do\\>")
- (setq icol (- icol f90-do-indent))))
- (end-of-line))
- icol)))
-
-
-(defun f90-calculate-indent ()
- "Calculate the indent column based on previous statements."
- (interactive)
- (let (icol cont (case-fold-search t) (pnt (point)))
- (save-excursion
- (if (not (f90-previous-statement))
- (setq icol 0)
- (setq cont (f90-present-statement-cont))
- (if (eq cont 'end)
- (while (not (eq 'begin (f90-present-statement-cont)))
- (f90-previous-statement)))
- (cond ((eq cont 'begin)
- (setq icol (+ (f90-current-indentation)
- f90-continuation-indent)))
- ((eq cont 'middle) (setq icol(current-indentation)))
- (t (setq icol (f90-current-indentation))
- (skip-chars-forward " \t")
- (if (looking-at "[0-9]")
- (setq icol (f90-get-correct-indent))
- (cond ((or (f90-looking-at-if-then)
- (f90-looking-at-where-or-forall)
- (f90-looking-at-select-case)
- (looking-at f90-else-like-re))
- (setq icol (+ icol f90-if-indent)))
- ((f90-looking-at-do)
- (setq icol (+ icol f90-do-indent)))
- ((f90-looking-at-type-like)
- (setq icol (+ icol f90-type-indent)))
- ((or (f90-looking-at-program-block-start)
- (looking-at "contains[ \t]*\\($\\|!\\)"))
- (setq icol (+ icol f90-program-indent)))))
- (goto-char pnt)
- (beginning-of-line)
- (cond ((looking-at "[ \t]*$"))
- ((looking-at "[ \t]*#") ; Check for cpp directive.
- (setq icol 0))
- (t
- (skip-chars-forward " \t0-9")
- (cond ((or (looking-at f90-else-like-re)
- (looking-at f90-end-if-re))
- (setq icol (- icol f90-if-indent)))
- ((looking-at "end[ \t]*do\\>")
- (setq icol (- icol f90-do-indent)))
- ((looking-at f90-end-type-re)
- (setq icol (- icol f90-type-indent)))
- ((or (looking-at "contains[ \t]*\\(!\\|$\\)")
- (f90-looking-at-program-block-end))
- (setq icol (- icol f90-program-indent))))))
- ))))
- icol))
-
-;; Statement = statement line, a line which is neither blank, nor a comment.
-(defun f90-previous-statement ()
- "Move point to beginning of the previous F90 statement.
-Return nil if no previous statement is found."
- (interactive)
- (let (not-first-statement)
- (beginning-of-line)
- (while (and (setq not-first-statement (zerop (forward-line -1)))
- (looking-at "[ \t0-9]*\\(!\\|$\\|#\\)")))
- not-first-statement))
-
-(defun f90-next-statement ()
- "Move point to beginning of the next F90 statement.
-Return nil if no later statement is found."
- (interactive)
- (let (not-last-statement)
- (beginning-of-line)
- (while (and (setq not-last-statement
- (and (zerop (forward-line 1))
- (not (eobp))))
- (looking-at "[ \t0-9]*\\(!\\|$\\)")))
- not-last-statement))
-
-(defun f90-beginning-of-subprogram ()
- "Move point to the beginning of subprogram.
-Return (type name) or nil if not found."
- (interactive)
- (let ((count 1) (case-fold-search t) matching-beg)
- (beginning-of-line) (skip-chars-forward " \t0-9")
- (if (setq matching-beg (f90-looking-at-program-block-start))
- (setq count (- count 1)))
- (while (and (not (zerop count))
- (re-search-backward f90-program-block-re nil 'move))
- (beginning-of-line) (skip-chars-forward " \t0-9")
- (cond
- ((setq matching-beg (f90-looking-at-program-block-start))
- (setq count (- count 1)))
- ((f90-looking-at-program-block-end)
- (setq count (+ count 1)))))
- (beginning-of-line)
- (if (zerop count)
- matching-beg
- (message "No beginning-found.")
- nil)))
-
-(defun f90-end-of-subprogram ()
- "Move point to the end of subprogram.
-Return (type name) or nil if not found."
- (interactive)
- (let ((count 1) (case-fold-search t) matching-end)
- (beginning-of-line) (skip-chars-forward " \t0-9")
- (if (setq matching-end (f90-looking-at-program-block-end))
- (setq count (1- count)))
- (end-of-line)
- (while (and (not (zerop count))
- (re-search-forward f90-program-block-re nil 'move))
- (beginning-of-line) (skip-chars-forward " \t0-9")
- (cond ((f90-looking-at-program-block-start)
- (setq count (+ count 1)))
- ((setq matching-end (f90-looking-at-program-block-end))
- (setq count (1- count ))))
- (end-of-line))
- (forward-line 1)
- (if (zerop count)
- matching-end
- (message "No end found.")
- nil)))
-
-(defun f90-mark-subprogram ()
- "Put mark at end of F90 subprogram, point at beginning.
-Marks are pushed and highlight (grey shadow) is turned on."
- (interactive)
- (let ((pos (point)) program)
- (f90-end-of-subprogram)
- (push-mark (point) t)
- (goto-char pos)
- (setq program (f90-beginning-of-subprogram))
- ;; The keywords in the preceding lists assume case-insensitivity.
- (if (string-match "XEmacs" emacs-version)
- (zmacs-activate-region)
- (setq mark-active t)
- (setq deactivate-mark nil))
- program))
-
-(defun f90-comment-region (beg-region end-region)
- "Comment/uncomment every line in the region.
-Insert f90-comment-region at the beginning of every line in the region
-or, if already present, remove it."
- (interactive "*r")
- (let ((end (make-marker)))
- (set-marker end end-region)
- (goto-char beg-region)
- (beginning-of-line)
- (if (looking-at (regexp-quote f90-comment-region))
- (delete-region (point) (match-end 0))
- (insert f90-comment-region))
- (while (and (zerop (forward-line 1))
- (< (point) (marker-position end)))
- (if (looking-at (regexp-quote f90-comment-region))
- (delete-region (point) (match-end 0))
- (insert f90-comment-region)))
- (set-marker end nil)))
-
-(defun f90-indent-line (&optional no-update)
- "Indent current line as F90 code."
- (interactive)
- (let (indent (no-line-number nil) (pos (make-marker)) (case-fold-search t))
- (set-marker pos (point))
- (beginning-of-line) ; Digits after & \n are not line-no
- (if (save-excursion (and (f90-previous-statement) (f90-line-continued)))
- (progn (setq no-line-number t) (skip-chars-forward " \t"))
- (f90-indent-line-no))
- (if (looking-at "!")
- (setq indent (f90-comment-indent))
- (if (and (looking-at "end") f90-smart-end)
- (f90-match-end))
- (setq indent (f90-calculate-indent)))
- (if (zerop (- indent (current-column)))
- nil
- (f90-indent-to indent no-line-number))
- ;; If initial point was within line's indentation,
- ;; position after the indentation. Else stay at same point in text.
- (if (< (point) (marker-position pos))
- (goto-char (marker-position pos)))
- (if (not no-update) (f90-update-line))
- (if auto-fill-function (f90-do-auto-fill))
- (set-marker pos nil)))
-
-(defun f90-indent-new-line ()
- "Reindent the current F90 line, insert a newline and indent the newline.
-An abbrev before point is expanded if `abbrev-mode' is non-nil.
-If run in the middle of a line, the line is not broken."
- (interactive)
- (let (string cont (case-fold-search t))
- (if abbrev-mode (expand-abbrev))
- (beginning-of-line) ; Reindent where likely to be needed.
- (f90-indent-line-no)
- (if (or (looking-at "\\(end\\|else\\|!\\)"))
- (f90-indent-line 'no-update))
- (end-of-line)
- (delete-horizontal-space) ;Destroy trailing whitespace
- (setq string (f90-in-string))
- (setq cont (f90-line-continued))
- (if (and string (not cont)) (insert "&"))
- (f90-update-line)
- (newline)
- (if (or string (and cont f90-beginning-ampersand)) (insert "&"))
- (f90-indent-line 'no-update)))
-
-
-(defun f90-indent-region (beg-region end-region)
- "Indent every line in region by forward parsing."
- (interactive "*r")
- (let ((end-region-mark (make-marker)) (save-point (point-marker))
- (block-list nil) ind-lev ind-curr ind-b cont
- struct beg-struct end-struct)
- (set-marker end-region-mark end-region)
- (goto-char beg-region)
- ;; first find a line which is not a continuation line or comment
- (beginning-of-line)
- (while (and (looking-at "[ \t]*[0-9]*\\(!\\|#\\|[ \t]*$\\)")
- (progn (f90-indent-line 'no-update)
- (zerop (forward-line 1)))
- (< (point) end-region-mark)))
- (setq cont (f90-present-statement-cont))
- (while (and (or (eq cont 'middle) (eq cont 'end))
- (f90-previous-statement))
- (setq cont (f90-present-statement-cont)))
- ;; process present line for beginning of block
- (setq f90-cache-position (point))
- (f90-indent-line 'no-update)
- (setq ind-lev (f90-current-indentation))
- (setq ind-curr ind-lev)
- (beginning-of-line) (skip-chars-forward " \t0-9")
- (setq struct nil)
- (setq ind-b (cond ((setq struct (f90-looking-at-do)) f90-do-indent)
- ((or (setq struct (f90-looking-at-if-then))
- (setq struct (f90-looking-at-select-case))
- (setq struct (f90-looking-at-where-or-forall))
- (looking-at f90-else-like-re))
- f90-if-indent)
- ((setq struct (f90-looking-at-type-like))
- f90-type-indent)
- ((or(setq struct (f90-looking-at-program-block-start))
- (looking-at "contains[ \t]*\\($\\|!\\)"))
- f90-program-indent)))
- (if ind-b (setq ind-lev (+ ind-lev ind-b)))
- (if struct (setq block-list (cons struct block-list)))
- (while (and (f90-line-continued) (zerop (forward-line 1))
- (< (point) end-region-mark))
- (if (not (zerop (- (current-indentation)
- (+ ind-curr f90-continuation-indent))))
- (f90-indent-to (+ ind-curr f90-continuation-indent) 'no-line-no)))
- ;; process all following lines
- (while (and (zerop (forward-line 1)) (< (point) end-region-mark))
- (beginning-of-line)
- (f90-indent-line-no)
- (setq f90-cache-position (point))
- (cond ((looking-at "[ \t]*$") (setq ind-curr 0))
- ((looking-at "[ \t]*#") (setq ind-curr 0))
- ((looking-at "!") (setq ind-curr (f90-comment-indent)))
- ((f90-no-block-limit) (setq ind-curr ind-lev))
- ((looking-at f90-else-like-re) (setq ind-curr
- (- ind-lev f90-if-indent)))
- ((looking-at "contains[ \t]*\\($\\|!\\)")
- (setq ind-curr (- ind-lev f90-program-indent)))
- ((setq ind-b
- (cond ((setq struct (f90-looking-at-do)) f90-do-indent)
- ((or (setq struct (f90-looking-at-if-then))
- (setq struct (f90-looking-at-select-case))
- (setq struct (f90-looking-at-where-or-forall)))
- f90-if-indent)
- ((setq struct (f90-looking-at-type-like))
- f90-type-indent)
- ((setq struct (f90-looking-at-program-block-start))
- f90-program-indent)))
- (setq ind-curr ind-lev)
- (if ind-b (setq ind-lev (+ ind-lev ind-b)))
- (setq block-list (cons struct block-list)))
- ((setq end-struct (f90-looking-at-program-block-end))
- (setq beg-struct (car block-list)
- block-list (cdr block-list))
- (if f90-smart-end
- (save-excursion
- (f90-block-match (car beg-struct)(car (cdr beg-struct))
- (car end-struct)(car (cdr end-struct)))))
- (setq ind-b
- (cond ((looking-at f90-end-if-re) f90-if-indent)
- ((looking-at "end[ \t]*do\\>") f90-do-indent)
- ((looking-at f90-end-type-re) f90-type-indent)
- ((f90-looking-at-program-block-end)
- f90-program-indent)))
- (if ind-b (setq ind-lev (- ind-lev ind-b)))
- (setq ind-curr ind-lev))
- (t (setq ind-curr ind-lev)))
- ;; do the indentation if necessary
- (if (not (zerop (- ind-curr (current-column))))
- (f90-indent-to ind-curr))
- (while (and (f90-line-continued) (zerop (forward-line 1))
- (< (point) end-region-mark))
- (if (not (zerop (- (current-indentation)
- (+ ind-curr f90-continuation-indent))))
- (f90-indent-to (+ ind-curr f90-continuation-indent) 'no-line-no))))
- ;; restore point etc
- (setq f90-cache-position nil)
- (goto-char save-point)
- (set-marker end-region-mark nil)
- (set-marker save-point nil)
- (if (string-match "XEmacs" emacs-version)
- (zmacs-deactivate-region)
- (deactivate-mark))))
-
-(defun f90-indent-subprogram ()
- "Properly indent the subprogram which contains point."
- (interactive)
- (save-excursion
- (let (program)
- (setq program (f90-mark-subprogram))
- (if program
- (progn
- (message "Indenting %s %s..."
- (car program) (car (cdr program)))
- (f90-indent-region (point) (mark))
- (message "Indenting %s %s...done"
- (car program) (car (cdr program))))
- (message "Indenting the whole file...")
- (f90-indent-region (point) (mark))
- (message "Indenting the whole file...done")))))
-
-;; autofill and break-line
-(defun f90-break-line (&optional no-update)
- "Break line at point, insert continuation marker(s) and indent."
- (interactive)
- (let (ctype)
- (cond ((f90-in-string)
- (insert "&") (newline) (insert "&"))
- ((f90-in-comment)
- (setq ctype (f90-get-present-comment-type))
- (newline)
- (insert ctype))
- (t (insert "&")
- (if (not no-update) (f90-update-line))
- (newline)
- (if f90-beginning-ampersand (insert "&")))))
- (f90-indent-line))
-
-(defun f90-find-breakpoint ()
- "From fill-column, search backward for break-delimiter."
- (let ((bol (f90-get-beg-of-line)))
- (re-search-backward f90-break-delimiters bol)
- (if f90-break-before-delimiters
- (progn (backward-char)
- (if (not (looking-at f90-no-break-re))
- (forward-char)))
- (if (looking-at f90-no-break-re)
- (forward-char 2)
- (forward-char)))))
-
-(defun f90-do-auto-fill ()
- "Break line if non-white characters beyond fill-column. Also, update line. "
- (interactive)
- ;; Break the line before or after the last delimiter (non-word char) if
- ;; position is beyond fill-column.
- ;; Will not break **, //, or => (specified by f90-no-break-re).
- (f90-update-line)
- (while (> (current-column) fill-column)
- (let ((pos-mark (point-marker)))
- (move-to-column fill-column)
- (if (not (f90-in-string))
- (f90-find-breakpoint))
- (f90-break-line)
- (goto-char pos-mark)
- (set-marker pos-mark nil))))
-
-
-(defun f90-join-lines ()
- "Join present line with next line, if this line ends with \&."
- (interactive)
- (let (pos (oldpos (point)))
- (end-of-line)
- (skip-chars-backward " \t")
- (cond ((= (preceding-char) ?&)
- (delete-char -1)
- (setq pos (point))
- (forward-line 1)
- (skip-chars-forward " \t")
- (if (looking-at "\&") (delete-char 1))
- (delete-region pos (point))
- (if (not (f90-in-string))
- (progn (delete-horizontal-space) (insert " ")))
- (if (and auto-fill-function
- (> (save-excursion (end-of-line)
- (current-column))
- fill-column))
- (f90-do-auto-fill))
- (goto-char oldpos)
- t))))
-
-(defun f90-fill-region (beg-region end-region)
- "Fill every line in region by forward parsing. Join lines if possible."
- (interactive "*r")
- (let ((end-region-mark (make-marker))
- (f90-smart-end nil) (f90-auto-keyword-case nil) (go-on t)
- (auto-fill-function nil))
- (set-marker end-region-mark end-region)
- (goto-char beg-region)
- (while go-on
- ;; join as much as possible
- (while (f90-join-lines))
- ;; chop the line if necessary
- (while (> (save-excursion (end-of-line) (current-column))
- fill-column)
- (move-to-column fill-column)
- (f90-find-breakpoint)
- (f90-break-line 'no-update))
- (setq go-on (and (< (point) (marker-position end-region-mark))
- (zerop (forward-line 1))))
- (setq f90-cache-position (point)))
- (setq f90-cache-position nil)
- (if (string-match "XEmacs" emacs-version)
- (zmacs-deactivate-region)
- (deactivate-mark))))
-
-(defun f90-block-match (beg-block beg-name end-block end-name)
- "Match end-struct with beg-struct and complete end-block if possible.
-Leave point at the end of line."
- (search-forward "end" (f90-get-end-of-line))
- (catch 'no-match
- (if (not (f90-equal-symbols beg-block end-block))
- (if end-block
- (progn
- (message "END %s does not match %s." end-block beg-block)
- (end-of-line)
- (throw 'no-match nil))
- (message "Inserting %s." beg-block)
- (insert (concat " " beg-block)))
- (search-forward end-block))
- (if (not (f90-equal-symbols beg-name end-name))
- (cond ((and beg-name (not end-name))
- (message "Inserting %s." beg-name)
- (insert (concat " " beg-name)))
- ((and beg-name end-name)
- (message "Replacing %s with %s." end-name beg-name)
- (search-forward end-name)
- (replace-match beg-name))
- ((and (not beg-name) end-name)
- (message "Deleting %s." end-name)
- (search-forward end-name)
- (replace-match "")))
- (if end-name (search-forward end-name)))
- (if (not (looking-at "[ \t]*!")) (delete-horizontal-space))))
-
-(defun f90-match-end ()
- "From an end foo statement, find the corresponding foo including name."
- (interactive)
- (let ((count 1) (top-of-window (window-start)) (matching-beg nil)
- (end-point (point)) (case-fold-search t)
- beg-name end-name beg-block end-block end-struct)
- (if (save-excursion (beginning-of-line) (skip-chars-forward " \t0-9")
- (setq end-struct (f90-looking-at-program-block-end)))
- (progn
- (setq end-block (car end-struct))
- (setq end-name (car (cdr end-struct)))
- (save-excursion
- (beginning-of-line)
- (while
- (and (not (zerop count))
- (let ((stop nil) notexist)
- (while (not stop)
- (setq notexist
- (not (re-search-backward
- (concat "\\(" f90-blocks-re "\\)") nil t)))
- (if notexist
- (setq stop t)
- (setq stop
- (not (or (f90-in-string)
- (f90-in-comment))))))
- (not notexist)))
- (beginning-of-line) (skip-chars-forward " \t0-9")
- (cond ((setq matching-beg
- (cond
- ((f90-looking-at-do))
- ((f90-looking-at-if-then))
- ((f90-looking-at-where-or-forall))
- ((f90-looking-at-select-case))
- ((f90-looking-at-type-like))
- ((f90-looking-at-program-block-start))))
- (setq count (- count 1)))
- ((looking-at (concat "end[ \t]*" f90-blocks-re "\\b"))
- (setq count (+ count 1)))))
- (if (not (zerop count))
- (message "No matching beginning.")
- (f90-update-line)
- (if (eq f90-smart-end 'blink)
- (if (< (point) top-of-window)
- (message "Matches %s: %s"
- (what-line)
- (buffer-substring
- (progn (beginning-of-line) (point))
- (progn (end-of-line) (point))))
- (sit-for 1)))
- (setq beg-block (car matching-beg))
- (setq beg-name (car (cdr matching-beg)))
- (goto-char end-point)
- (beginning-of-line)
- (f90-block-match beg-block beg-name end-block end-name)))))))
-
-(defun f90-insert-end ()
- "Inserts an complete end statement matching beginning of present block."
- (interactive)
- (let ((f90-smart-end (if f90-smart-end f90-smart-end 'blink)))
- (insert "end")
- (f90-indent-new-line)))
-
-;; abbrevs and keywords
-
-(defun f90-abbrev-start ()
- "Typing `\\[help-command] or `? lists all the F90 abbrevs.
-Any other key combination is executed normally."
- (interactive)
- (let (e c)
- (insert last-command-char)
- (if (string-match "XEmacs" emacs-version)
- (progn
- (setq e (next-command-event))
- (setq c (event-to-character e)))
- (setq c (read-event)))
- ;; insert char if not equal to `?'
- (if (or (= c ??) (eq c help-char))
- (f90-abbrev-help)
- (if (string-match "XEmacs" emacs-version)
- (setq unread-command-event e)
- (setq unread-command-events (list c))))))
-
-(defun f90-abbrev-help ()
- "List the currently defined abbrevs in F90 mode."
- (interactive)
- (message "Listing abbrev table...")
- (display-buffer (f90-prepare-abbrev-list-buffer))
- (message "Listing abbrev table...done"))
-
-(defun f90-prepare-abbrev-list-buffer ()
- (save-excursion
- (set-buffer (get-buffer-create "*Abbrevs*"))
- (erase-buffer)
- (insert-abbrev-table-description 'f90-mode-abbrev-table t)
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- (edit-abbrevs-mode))
- (get-buffer-create "*Abbrevs*"))
-
-(defun f90-upcase-keywords ()
- "Upcase all F90 keywords in the buffer."
- (interactive)
- (f90-change-keywords 'upcase-word))
-
-(defun f90-capitalize-keywords ()
- "Capitalize all F90 keywords in the buffer."
- (interactive)
- (f90-change-keywords 'capitalize-word))
-
-(defun f90-downcase-keywords ()
- "Downcase all F90 keywords in the buffer."
- (interactive)
- (f90-change-keywords 'downcase-word))
-
-(defun f90-upcase-region-keywords (beg end)
- "Upcase all F90 keywords in the region."
- (interactive "*r")
- (f90-change-keywords 'upcase-word beg end))
-
-(defun f90-capitalize-region-keywords (beg end)
- "Capitalize all F90 keywords in the region."
- (interactive "*r")
- (f90-change-keywords 'capitalize-word beg end))
-
-(defun f90-downcase-region-keywords (beg end)
- "Downcase all F90 keywords in the region."
- (interactive "*r")
- (f90-change-keywords 'downcase-word beg end))
-
-;; Change the keywords according to argument.
-(defun f90-change-keywords (change-word &optional beg end)
- (save-excursion
- (setq beg (if beg beg (point-min)))
- (setq end (if end end (point-max)))
- (let ((keyword-re
- (concat "\\("
- f90-keywords-re "\\|" f90-procedures-re "\\|"
- f90-hpf-keywords-re "\\|" f90-operators-re "\\)"))
- (ref-point (point-min)) state
- (modified (buffer-modified-p)) saveword back-point)
- (goto-char beg)
- (unwind-protect
- (while (re-search-forward keyword-re end t)
- (if (progn
- (setq state (parse-partial-sexp ref-point (point)))
- (or (nth 3 state) (nth 4 state)
- (save-excursion ; Check for cpp directive.
- (beginning-of-line)
- (skip-chars-forward " \t0-9")
- (looking-at "#"))))
- ()
- (setq ref-point (point)
- back-point (save-excursion (backward-word 1) (point)))
- (setq saveword (buffer-substring back-point ref-point))
- (funcall change-word -1)
- (or (string= saveword (buffer-substring back-point ref-point))
- (setq modified t))))
- (or modified (set-buffer-modified-p nil))))))
-
-(provide 'f90)
-
-;;; f90.el ends here
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el
deleted file mode 100644
index 1c255b12a8c..00000000000
--- a/lisp/progmodes/fortran.el
+++ /dev/null
@@ -1,1589 +0,0 @@
-;;; fortran.el --- Fortran mode for GNU Emacs
-
-;; Copyright (c) 1986, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Michael D. Prange <prange@erl.mit.edu>
-;; Maintainer: bug-fortran-mode@erl.mit.edu (Steve Gildea and others)
-;; Version 1.30.6 (July 27, 1995)
-;; Keywords: languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Fortran mode has been upgraded and is now maintained by Stephen A. Wood
-;; (saw@cebaf.gov). It now will use either fixed format continuation line
-;; markers (character in 6th column), or tab format continuation line style
-;; (digit after a TAB character.) A auto-fill mode has been added to
-;; automatically wrap fortran lines that get too long.
-
-;; We acknowledge many contributions and valuable suggestions by
-;; Lawrence R. Dodd, Ralf Fassel, Ralph Finch, Stephen Gildea,
-;; Dr. Anil Gokhale, Ulrich Mueller, Mark Neale, Eric Prestemon,
-;; Gary Sabot and Richard Stallman.
-
-;; This file may be used with GNU Emacs version 18.xx if the following
-;; variable and function substitutions are made.
-;; Replace:
-;; frame-width with screen-width
-;; auto-fill-function with auto-fill-hook
-;; comment-indent-function with comment-indent-hook
-;; (setq unread-command-events (list c)) with (setq unread-command-char c)
-
-;; Bugs to bug-fortran-mode@erl.mit.edu
-
-;;; Code:
-
-(defconst fortran-mode-version "version 1.30.6")
-
-;;;###autoload
-(defvar fortran-tab-mode-default nil
- "*Default tabbing/carriage control style for empty files in Fortran mode.
-A value of t specifies tab-digit style of continuation control.
-A value of nil specifies that continuation lines are marked
-with a character in column 6.")
-
-;; Buffer local, used to display mode line.
-(defvar fortran-tab-mode-string nil
- "String to appear in mode line when TAB format mode is on.")
-
-(defvar fortran-do-indent 3
- "*Extra indentation applied to DO blocks.")
-
-(defvar fortran-if-indent 3
- "*Extra indentation applied to IF blocks.")
-
-(defvar fortran-structure-indent 3
- "*Extra indentation applied to STRUCTURE, UNION, MAP and INTERFACE blocks.")
-
-(defvar fortran-continuation-indent 5
- "*Extra indentation applied to Fortran continuation lines.")
-
-(defvar fortran-comment-indent-style 'fixed
- "*nil forces comment lines not to be touched,
-'fixed makes fixed comment indentation to `fortran-comment-line-extra-indent'
-columns beyond `fortran-minimum-statement-indent-fixed' (for
-`indent-tabs-mode' of nil) or `fortran-minimum-statement-indent-tab' (for
-`indent-tabs-mode' of t), and 'relative indents to current
-Fortran indentation plus `fortran-comment-line-extra-indent'.")
-
-(defvar fortran-comment-line-extra-indent 0
- "*Amount of extra indentation for text within full-line comments.")
-
-(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-fixed 6
- "*Minimum statement indentation for fixed format continuation style.")
-
-(defvar fortran-minimum-statement-indent-tab (max tab-width 6)
- "*Minimum statement indentation for TAB format continuation style.")
-
-;; 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 " "
- "*Single-character string 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-blink-matching-if nil
- "*Non-nil causes \\[fortran-indent-line] on ENDIF statement to blink on matching IF.
-Also, from an ENDDO statement blink on matching DO [WHILE] statement.")
-
-(defvar fortran-continuation-string "$"
- "*Single-character string used for Fortran continuation lines.
-In fixed format continuation style, this character is inserted in
-column 6 by \\[fortran-split-line] to begin a continuation line.
-Also, if \\[fortran-indent-line] finds this at the beginning of a line, it will
-convert the line into a continuation line of the appropriate style.
-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-fixed
- "0 4 6 10 20 30 40 5\
-\0 60 70\n\
-\[ ]|{ | | | | | | | | \
-\| | | | |}\n"
- "*String displayed above current line by \\[fortran-column-ruler].
-This variable used in fixed format mode.")
-
-(defvar fortran-column-ruler-tab
- "0 810 20 30 40 5\
-\0 60 70\n\
-\[ ]| { | | | | | | | | \
-\| | | | |}\n"
- "*String displayed above current line by \\[fortran-column-ruler].
-This variable used in TAB format mode.")
-
-(defconst bug-fortran-mode "bug-fortran-mode@erl.mit.edu"
- "Address of mailing list for Fortran mode bugs.")
-
-(defvar fortran-mode-syntax-table nil
- "Syntax table in use in Fortran mode buffers.")
-
-(defvar fortran-analyze-depth 100
- "Number of lines to scan to determine whether to use fixed or TAB format\
- style.")
-
-(defvar fortran-break-before-delimiters t
- "*Non-nil causes `fortran-fill' to break lines before delimiters.")
-
-(if fortran-mode-syntax-table
- ()
- (setq fortran-mode-syntax-table (make-syntax-table))
- (modify-syntax-entry ?\; "w" fortran-mode-syntax-table)
- (modify-syntax-entry ?\r " " 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 ?\\ "/" fortran-mode-syntax-table)
- (modify-syntax-entry ?. "w" fortran-mode-syntax-table)
- (modify-syntax-entry ?_ "w" fortran-mode-syntax-table)
- (modify-syntax-entry ?\! "<" fortran-mode-syntax-table)
- (modify-syntax-entry ?\n ">" fortran-mode-syntax-table))
-
-;; Comments are real pain in Fortran because there is no way to represent the
-;; standard comment syntax in an Emacs syntax table (we can for VAX-style).
-;; Therefore an unmatched quote in a standard comment will throw fontification
-;; off on the wrong track. So we do syntactic fontification with regexps.
-
-;; Regexps done by simon@gnu with help from Ulrik Dickow <dickow@nbi.dk> and
-;; probably others Si's forgotten about (sorry).
-
-(defconst fortran-font-lock-keywords-1 nil
- "Subdued level highlighting for Fortran mode.")
-
-(defconst fortran-font-lock-keywords-2 nil
- "Medium level highlighting for Fortran mode.")
-
-(defconst fortran-font-lock-keywords-3 nil
- "Gaudy level highlighting for Fortran mode.")
-
-(let ((comment-chars "c!*")
- (fortran-type-types
-; (make-regexp
-; (let ((simple-types '("character" "byte" "integer" "logical"
-; "none" "real" "complex"
-; "double[ \t]*precision" "double[ \t]*complex"))
-; (structured-types '("structure" "union" "map"))
-; (other-types '("record" "dimension" "parameter" "common" "save"
-; "external" "intrinsic" "data" "equivalence")))
-; (append
-; (mapcar (lambda (x) (concat "implicit[ \t]*" x)) simple-types)
-; simple-types
-; (mapcar (lambda (x) (concat "end[ \t]*" x)) structured-types)
-; structured-types
-; other-types)))
- (concat "byte\\|c\\(haracter\\|om\\(mon\\|plex\\)\\)\\|"
- "d\\(ata\\|imension\\|ouble"
- "[ \t]*\\(complex\\|precision\\)\\)\\|"
- "e\\(nd[ \t]*\\(map\\|structure\\|union\\)\\|"
- "quivalence\\|xternal\\)\\|"
- "i\\(mplicit[ \t]*\\(byte\\|"
- "c\\(haracter\\|omplex\\)\\|"
- "double[ \t]*\\(complex\\|precision\\)\\|"
- "integer\\|logical\\|none\\|real\\)\\|"
- "nt\\(eger\\|rinsic\\)\\)\\|"
- "logical\\|map\\|none\\|parameter\\|re\\(al\\|cord\\)\\|"
- "s\\(ave\\|tructure\\)\\|union"))
- (fortran-keywords
-; ("continue" "format" "end" "enddo" "if" "then" "else" "endif"
-; "elseif" "while" "inquire" "stop" "return" "include" "open"
-; "close" "read" "write" "format" "print")
- (concat "c\\(lose\\|ontinue\\)\\|"
- "e\\(lse\\(\\|if\\)\\|nd\\(\\|do\\|if\\)\\)\\|format\\|"
- "i\\(f\\|n\\(clude\\|quire\\)\\)\\|open\\|print\\|"
- "re\\(ad\\|turn\\)\\|stop\\|then\\|w\\(hile\\|rite\\)"))
- (fortran-logicals
-; ("and" "or" "not" "lt" "le" "eq" "ge" "gt" "ne" "true" "false")
- "and\\|eq\\|false\\|g[et]\\|l[et]\\|n\\(e\\|ot\\)\\|or\\|true"))
-
- (setq fortran-font-lock-keywords-1
- (list
- ;;
- ;; Fontify syntactically (assuming strings cannot be quoted or span lines).
- (cons (concat "^[" comment-chars "].*") 'font-lock-comment-face)
- '(fortran-match-!-comment . font-lock-comment-face)
- (list (concat "^[^" comment-chars "\t\n]" (make-string 71 ?.) "\\(.*\\)")
- '(1 font-lock-comment-face))
- '("'[^'\n]*'?" . font-lock-string-face)
- ;;
- ;; Program, subroutine and function declarations, plus calls.
- (list (concat "\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|"
- "program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?")
- '(1 font-lock-keyword-face)
- '(2 font-lock-function-name-face nil t))))
-
- (setq fortran-font-lock-keywords-2
- (append fortran-font-lock-keywords-1
- (list
- ;;
- ;; Fontify all type specifiers (must be first; see below).
- (cons (concat "\\<\\(" fortran-type-types "\\)\\>") 'font-lock-type-face)
- ;;
- ;; Fontify all builtin keywords (except logical, do and goto; see below).
- (concat "\\<\\(" fortran-keywords "\\)\\>")
- ;;
- ;; Fontify all builtin operators.
- (concat "\\.\\(" fortran-logicals "\\)\\.")
- ;;
- ;; Fontify do/goto keywords and targets, and goto tags.
- (list "\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)?"
- '(1 font-lock-keyword-face)
- '(2 font-lock-reference-face nil t))
- (cons "^ *\\([0-9]+\\)" 'font-lock-reference-face))))
-
- (setq fortran-font-lock-keywords-3
- (append
- ;;
- ;; The list `fortran-font-lock-keywords-1'.
- fortran-font-lock-keywords-1
- ;;
- ;; Fontify all type specifiers plus their declared items.
- (list
- (list (concat "\\<\\(" fortran-type-types "\\)\\>[ \t(/]*\\(*\\)?")
- ;; Fontify the type specifier.
- '(1 font-lock-type-face)
- ;; Fontify each declaration item (or just the /.../ block name).
- '(font-lock-match-c-style-declaration-item-and-skip-to-next
- ;; Start after any *(...) expression.
- (and (match-beginning 15) (forward-sexp 1))
- ;; No need to clean up.
- nil
- ;; Fontify as a variable name, functions are fontified elsewhere.
- (1 font-lock-variable-name-face nil t))))
- ;;
- ;; Things extra to `fortran-font-lock-keywords-3' (must be done first).
- (list
- ;;
- ;; Fontify goto-like `err=label'/`end=label' in read/write statements.
- '(", *\\(e\\(nd\\|rr\\)\\)\\> *\\(= *\\([0-9]+\\)\\)?"
- (1 font-lock-keyword-face) (4 font-lock-reference-face nil t))
- ;;
- ;; Highlight standard continuation character and in a TAB-formatted line.
- '("^ \\([^ 0]\\)" 1 font-lock-string-face)
- '("^\t\\([1-9]\\)" 1 font-lock-string-face))
- ;;
- ;; The list `fortran-font-lock-keywords-2' less that for types (see above).
- (cdr (nthcdr (length fortran-font-lock-keywords-1)
- fortran-font-lock-keywords-2))))
- )
-
-(defvar fortran-font-lock-keywords fortran-font-lock-keywords-1
- "Default expressions to highlight in Fortran mode.")
-
-
-(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 "\n" 'fortran-indent-new-line)
- (define-key fortran-mode-map "\e\C-q" 'fortran-indent-subprogram)
- (define-key fortran-mode-map "\C-c\C-w" 'fortran-window-create-momentarily)
- (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
- ()
- (let ((ac abbrevs-changed))
- (define-abbrev-table 'fortran-mode-abbrev-table ())
- (define-abbrev fortran-mode-abbrev-table ";au" "automatic" nil)
- (define-abbrev fortran-mode-abbrev-table ";b" "byte" nil)
- (define-abbrev fortran-mode-abbrev-table ";bd" "block data" 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 ";df" "define" 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 ";ew" "endwhere" 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 ";fa" ".false." 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 ";n" "namelist" nil)
- (define-abbrev fortran-mode-abbrev-table ";o" "open" nil) ; was ;op
- (define-abbrev fortran-mode-abbrev-table ";pa" "parameter" nil)
- (define-abbrev fortran-mode-abbrev-table ";pr" "program" nil)
- (define-abbrev fortran-mode-abbrev-table ";ps" "pause" nil)
- (define-abbrev fortran-mode-abbrev-table ";p" "print" nil)
- (define-abbrev fortran-mode-abbrev-table ";rc" "record" 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 ";sa" "save" nil)
- (define-abbrev fortran-mode-abbrev-table ";st" "structure" nil)
- (define-abbrev fortran-mode-abbrev-table ";sc" "static" nil)
- (define-abbrev fortran-mode-abbrev-table ";su" "subroutine" nil)
- (define-abbrev fortran-mode-abbrev-table ";tr" ".true." nil)
- (define-abbrev fortran-mode-abbrev-table ";ty" "type" nil)
- (define-abbrev fortran-mode-abbrev-table ";vo" "volatile" nil)
- (define-abbrev fortran-mode-abbrev-table ";w" "write" nil)
- (define-abbrev fortran-mode-abbrev-table ";wh" "where" nil)
- (setq abbrevs-changed ac)))
-
-;;;###autoload
-(defun fortran-mode ()
- "Major mode for editing Fortran code.
-\\[fortran-indent-line] 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.
-
-Key definitions:
-\\{fortran-mode-map}
-
-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-structure-indent
- Extra indentation within structure, union, map and interface blocks.
- (default 3)
- fortran-continuation-indent
- Extra indentation applied to continuation statements. (default 5)
- fortran-comment-line-extra-indent
- Amount of extra indentation for text within full-line comments. (default 0)
- fortran-comment-indent-style
- nil means don't change indentation of text in full-line comments,
- fixed means indent that text at `fortran-comment-line-extra-indent' beyond
- the value of `fortran-minimum-statement-indent-fixed' (for fixed
- format continuation style) or `fortran-minimum-statement-indent-tab'
- (for TAB format continuation style).
- relative means indent at `fortran-comment-line-extra-indent' beyond the
- indentation for a line of code.
- (default 'fixed)
- fortran-comment-indent-char
- Single-character string to be inserted instead of space for
- full-line comment indentation. (default \" \")
- fortran-minimum-statement-indent-fixed
- Minimum indentation for Fortran statements in fixed format mode. (def.6)
- fortran-minimum-statement-indent-tab
- Minimum indentation for Fortran statements in TAB format mode. (default 9)
- 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-blink-matching-if
- Non-nil causes \\[fortran-indent-line] on an ENDIF statement to blink on
- matching IF. Also, from an ENDDO statement, blink on matching DO [WHILE]
- statement. (default nil)
- fortran-continuation-string
- Single-character string 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-break-before-delimiters
- Non-nil causes `fortran-fill' breaks lines before delimiters.
- (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."
- (interactive)
- (kill-all-local-variables)
- (if fortran-startup-message
- (message "Emacs Fortran mode %s. Bugs to %s"
- fortran-mode-version bug-fortran-mode))
- (setq fortran-startup-message nil)
- (setq local-abbrev-table fortran-mode-abbrev-table)
- (set-syntax-table fortran-mode-syntax-table)
- ;; Font Lock mode support.
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '((fortran-font-lock-keywords
- fortran-font-lock-keywords-1
- fortran-font-lock-keywords-2
- fortran-font-lock-keywords-3)
- t t ((?/ . "$/"))))
- (make-local-variable 'fortran-break-before-delimiters)
- (setq fortran-break-before-delimiters t)
- (make-local-variable 'indent-line-function)
- (setq indent-line-function 'fortran-indent-line)
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'fortran-comment-hook)
- (make-local-variable 'comment-line-start-skip)
- (setq comment-line-start-skip
- "^[Cc*]\\(\\([^ \t\n]\\)\\2\\2*\\)?[ \t]*\\|^#.*")
- (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)
-;;;(setq abbrev-mode t) ; ?? (abbrev-mode 1) instead??
- (setq fill-column 72) ; Already local?
- (use-local-map fortran-mode-map)
- (setq mode-name "Fortran")
- (setq major-mode 'fortran-mode)
-;;;(make-local-variable 'fortran-tab-mode)
- (make-local-variable 'fortran-comment-line-extra-indent)
- (make-local-variable 'fortran-minimum-statement-indent-fixed)
- (make-local-variable 'fortran-minimum-statement-indent-tab)
- (make-local-variable 'fortran-column-ruler-fixed)
- (make-local-variable 'fortran-column-ruler-tab)
- (make-local-variable 'fortran-tab-mode-string)
- (setq fortran-tab-mode-string " TAB-format")
- (setq indent-tabs-mode (fortran-analyze-file-format))
- (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))
- ((fortran-find-comment-start-skip) ; catches any inline comment and
- ; leaves point after comment-start-skip
- (if comment-start-skip
- (progn (goto-char (match-beginning 0))
- (if (not (= (current-column) (fortran-comment-hook)))
- (progn (delete-horizontal-space)
- (indent-to (fortran-comment-hook)))))
- (end-of-line))) ; otherwise goto end of line or sth else?
- ;; 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."
- (interactive)
- (let (c)
- (insert last-command-char)
- (if (or (eq (setq c (read-event)) ??) ;insert char if not equal to `?'
- (eq c help-char))
- (fortran-abbrev-help)
- (setq unread-command-events (list c)))))
-
-(defun fortran-abbrev-help ()
- "List the currently defined abbrevs in Fortran mode."
- (interactive)
- (message "Listing abbrev table...")
- (display-buffer (fortran-prepare-abbrev-list-buffer))
- (message "Listing abbrev table...done"))
-
-(defun fortran-prepare-abbrev-list-buffer ()
- (save-excursion
- (set-buffer (get-buffer-create "*Abbrevs*"))
- (erase-buffer)
- (insert-abbrev-table-description 'fortran-mode-abbrev-table t)
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- (edit-abbrevs-mode))
- (get-buffer-create "*Abbrevs*"))
-
-(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-fixed' when in fixed
-format mode, and `fortran-column-ruler-tab' when in TAB format mode.
-The key typed is executed unless it is SPC."
- (interactive)
- (momentary-string-display
- (if indent-tabs-mode
- fortran-column-ruler-tab
- fortran-column-ruler-fixed)
- (save-excursion
- (beginning-of-line)
- (if (eq (window-start (selected-window))
- (window-point (selected-window)))
- (progn (forward-line) (point))
- (point)))
- nil "Type SPC or any command to erase ruler."))
-
-(defun fortran-window-create ()
- "Makes the window 72 columns wide.
-See also `fortran-window-create-momentarily'."
- (interactive)
- (condition-case error
- (progn
- (let ((window-min-width 2))
- (if (< (window-width) (frame-width))
- (enlarge-window-horizontally (- (frame-width)
- (window-width) 1)))
- (split-window-horizontally 73)
- (other-window 1)
- (switch-to-buffer " fortran-window-extra" t)
- (select-window (previous-window))))
- (error (message "No room for Fortran window.")
- 'error)))
-
-(defun fortran-window-create-momentarily (&optional arg)
- "Momentarily makes the window 72 columns wide.
-Optional ARG non-nil and non-unity disables the momentary feature.
-See also `fortran-window-create'."
- (interactive "p")
- (if (or (not arg)
- (= arg 1))
- (save-window-excursion
- (if (not (equal (fortran-window-create) 'error))
- (progn (message "Type SPC to continue editing.")
- (let ((char (read-event)))
- (or (equal char (string-to-char " "))
- (setq unread-command-events (list char)))))))
- (fortran-window-create)))
-
-(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 " ")
- (if indent-tabs-mode
- (progn
- (insert "\n\t")
- (insert-char (fortran-numerical-continuation-char) 1))
- (insert "\n " fortran-continuation-string)));Space after \n important
- (fortran-indent-line)) ;when the cont string is C, c or *.
-
-(defun fortran-numerical-continuation-char ()
- "Return a digit for tab-digit style of continuation lines.
-If, previous line is a tab-digit continuation line, returns that digit
-plus one. Otherwise return 1. Zero not allowed."
- (save-excursion
- (forward-line -1)
- (if (looking-at "\t[1-9]")
- (+ ?1 (% (- (char-after (+ (point) 1)) ?0) 9))
- ?1)))
-
-(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))
- (if arg
- (self-insert-command (prefix-numeric-value arg))
- (self-insert-command 1))
- (if (or (and (= 5 (current-column))
- (save-excursion
- (beginning-of-line)
- (looking-at " ")));In col 5 with only spaces to left.
- (and (= (if indent-tabs-mode
- fortran-minimum-statement-indent-tab
- fortran-minimum-statement-indent-fixed) (current-column))
- (save-excursion
- (beginning-of-line)
- (looking-at "\t"));In col 8 with a single tab to the left.
- (not (or (eq last-command 'fortran-indent-line)
- (eq last-command
- 'fortran-indent-new-line))))
- (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
- )
- (self-insert-command (prefix-numeric-value arg))
- (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
- (and
- (not (looking-at comment-line-start-skip))
- (or (looking-at
- (concat "[ \t]*" (regexp-quote fortran-continuation-string)))
- (or (looking-at " [^ 0\n]")
- (looking-at "\t[1-9]")))))
- (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 "\t[1-9]")
- (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
- (and (= (forward-line 1) 0)
- (not (eobp))))
- (or (looking-at comment-line-start-skip)
- (looking-at "[ \t]*$")
- (looking-at " [^ 0\n]")
- (looking-at "\t[1-9]")
- (looking-at (concat "[ \t]*" comment-start-skip)))))
- (if (not not-last-statement)
- 'last-statement)))
-
-(defun fortran-blink-matching-if ()
- ;; From a Fortran ENDIF statement, blink the matching IF statement.
- (let ((top-of-window (window-start)) matching-if
- (endif-point (point)) message)
- (if (save-excursion (beginning-of-line)
- (skip-chars-forward " \t0-9")
- (looking-at "end[ \t]*if\\b"))
- (progn
- (if (not (setq matching-if (fortran-beginning-if)))
- (setq message "No matching if.")
- (if (< matching-if top-of-window)
- (save-excursion
- (goto-char matching-if)
- (beginning-of-line)
- (setq message
- (concat "Matches "
- (buffer-substring
- (point) (progn (end-of-line) (point))))))))
- (if message
- (message "%s" message)
- (goto-char matching-if)
- (sit-for 1)
- (goto-char endif-point))))))
-
-(defun fortran-blink-matching-do ()
- ;; From a Fortran ENDDO statement, blink on the matching DO or DO WHILE
- ;; statement. This is basically copied from fortran-blink-matching-if.
- (let ((top-of-window (window-start)) matching-do
- (enddo-point (point)) message)
- (if (save-excursion (beginning-of-line)
- (skip-chars-forward " \t0-9")
- (looking-at "end[ \t]*do\\b"))
- (progn
- (if (not (setq matching-do (fortran-beginning-do)))
- (setq message "No matching do.")
- (if (< matching-do top-of-window)
- (save-excursion
- (goto-char matching-do)
- (beginning-of-line)
- (setq message
- (concat "Matches "
- (buffer-substring
- (point) (progn (end-of-line) (point))))))))
- (if message
- (message "%s" message)
- (goto-char matching-do)
- (sit-for 1)
- (goto-char enddo-point))))))
-
-(defun fortran-mark-do ()
- "Put mark at end of Fortran DO [WHILE]-ENDDO construct, point at beginning.
-The marks are pushed."
- (interactive)
- (let (enddo-point do-point)
- (if (setq enddo-point (fortran-end-do))
- (if (not (setq do-point (fortran-beginning-do)))
- (message "No matching do.")
- ;; Set mark, move point.
- (goto-char enddo-point)
- (push-mark)
- (goto-char do-point)))))
-
-(defun fortran-end-do ()
- ;; Search forward for first unmatched ENDDO. Return point or nil.
- (if (save-excursion (beginning-of-line)
- (skip-chars-forward " \t0-9")
- (looking-at "end[ \t]*do\\b"))
- ;; Sitting on one.
- (match-beginning 0)
- ;; Search for one.
- (save-excursion
- (let ((count 1))
- (while (and (not (= count 0))
- (not (eq (fortran-next-statement) 'last-statement))
- ;; Keep local to subprogram
- (not (looking-at "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")))
-
- (skip-chars-forward " \t0-9")
- (cond ((looking-at "end[ \t]*do\\b")
- (setq count (- count 1)))
- ((looking-at "do[ \t]+[^0-9]")
- (setq count (+ count 1)))))
- (and (= count 0)
- ;; All pairs accounted for.
- (point))))))
-
-(defun fortran-beginning-do ()
- ;; Search backwards for first unmatched DO [WHILE]. Return point or nil.
- (if (save-excursion (beginning-of-line)
- (skip-chars-forward " \t0-9")
- (looking-at "do[ \t]+"))
- ;; Sitting on one.
- (match-beginning 0)
- ;; Search for one.
- (save-excursion
- (let ((count 1))
- (while (and (not (= count 0))
- (not (eq (fortran-previous-statement) 'first-statement))
- ;; Keep local to subprogram
- (not (looking-at "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")))
-
- (skip-chars-forward " \t0-9")
- (cond ((looking-at "do[ \t]+[^0-9]")
- (setq count (- count 1)))
- ((looking-at "end[ \t]*do\\b")
- (setq count (+ count 1)))))
-
- (and (= count 0)
- ;; All pairs accounted for.
- (point))))))
-
-(defun fortran-mark-if ()
- "Put mark at end of Fortran IF-ENDIF construct, point at beginning.
-The marks are pushed."
- (interactive)
- (let (endif-point if-point)
- (if (setq endif-point (fortran-end-if))
- (if (not (setq if-point (fortran-beginning-if)))
- (message "No matching if.")
- ;; Set mark, move point.
- (goto-char endif-point)
- (push-mark)
- (goto-char if-point)))))
-
-(defun fortran-end-if ()
- ;; Search forwards for first unmatched ENDIF. Return point or nil.
- (if (save-excursion (beginning-of-line)
- (skip-chars-forward " \t0-9")
- (looking-at "end[ \t]*if\\b"))
- ;; Sitting on one.
- (match-beginning 0)
- ;; Search for one. The point has been already been moved to first
- ;; letter on line but this should not cause troubles.
- (save-excursion
- (let ((count 1))
- (while (and (not (= count 0))
- (not (eq (fortran-next-statement) 'last-statement))
- ;; Keep local to subprogram.
- (not (looking-at
- "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")))
-
- (skip-chars-forward " \t0-9")
- (cond ((looking-at "end[ \t]*if\\b")
- (setq count (- count 1)))
-
- ((looking-at "if[ \t]*(")
- (save-excursion
- (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.
- (or (looking-at " [^ 0\n]")
- (looking-at "\t[1-9]"))
- (not
- (setq then-test
- (looking-at
- ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
- then-test))
- (setq count (+ count 1)))))))
-
- (and (= count 0)
- ;; All pairs accounted for.
- (point))))))
-
-(defun fortran-beginning-if ()
- ;; Search backwards for first unmatched IF-THEN. Return point or nil.
- (if (save-excursion
- ;; May be sitting on multi-line if-then statement, first move to
- ;; beginning of current statement. Note: `fortran-previous-statement'
- ;; moves to previous statement *unless* current statement is first
- ;; one. Only move forward if not first-statement.
- (if (not (eq (fortran-previous-statement) 'first-statement))
- (fortran-next-statement))
- (skip-chars-forward " \t0-9")
- (and
- (looking-at "if[ \t]*(")
- (save-match-data
- (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")
- ;; Multi-line if-then.
- (let (then-test)
- (while
- (and (= (forward-line 1) 0)
- ;; Search forward for then.
- (or (looking-at " [^ 0\n]")
- (looking-at "\t[1-9]"))
- (not
- (setq then-test
- (looking-at
- ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
- then-test)))))
- ;; Sitting on one.
- (match-beginning 0)
- ;; Search for one.
- (save-excursion
- (let ((count 1))
- (while (and (not (= count 0))
- (not (eq (fortran-previous-statement) 'first-statement))
- ;; Keep local to subprogram.
- (not (looking-at
- "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")))
-
- (skip-chars-forward " \t0-9")
- (cond ((looking-at "if[ \t]*(")
- (save-excursion
- (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.
- (or (looking-at " [^ 0\n]")
- (looking-at "\t[1-9]"))
- (not
- (setq then-test
- (looking-at
- ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
- then-test))
- (setq count (- count 1)))))
- ((looking-at "end[ \t]*if\\b")
- (setq count (+ count 1)))))
-
- (and (= count 0)
- ;; All pairs accounted for.
- (point))))))
-
-(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 (and (not (looking-at comment-line-start-skip))
- (fortran-find-comment-start-skip))
- (fortran-indent-comment))))
- ;; Never leave point in left margin.
- (if (< (current-column) cfi)
- (move-to-column cfi))
- (if (and auto-fill-function
- (> (save-excursion (end-of-line) (current-column)) fill-column))
- (save-excursion
- (end-of-line)
- (fortran-fill)))
- (if fortran-blink-matching-if
- (progn
- (fortran-blink-matching-if)
- (fortran-blink-matching-do)))))
-
-(defun fortran-indent-new-line ()
- "Reindent the current Fortran line, insert a newline and indent the newline.
-An abbrev before point is expanded if `abbrev-mode' is non-nil."
- (interactive)
- (if abbrev-mode (expand-abbrev))
- (save-excursion
- (beginning-of-line)
- (skip-chars-forward " \t")
- (if (or (looking-at "[0-9]") ;Reindent only where it is most
- (looking-at "end") ;likely to be necessary
- (looking-at "else")
- (looking-at (regexp-quote fortran-continuation-string)))
- (fortran-indent-line)))
- (newline)
- (fortran-indent-line))
-
-(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)
- (fortran-minimum-statement-indent
- (if indent-tabs-mode
- fortran-minimum-statement-indent-tab
- fortran-minimum-statement-indent-fixed)))
- (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
- (or (looking-at " [^ 0\n]")
- (looking-at "\t[1-9]"))
- (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 "select[ \t]*case[ \t](.*)\\b")
- (setq icol (+ icol fortran-if-indent)))
- ((looking-at "case[ \t]*(.*)[ \t]*\n")
- (setq icol (+ icol fortran-if-indent)))
- ((looking-at "case[ \t]*default\\b")
- (setq icol (+ icol fortran-if-indent)))
- ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b")
- (setq icol (+ icol fortran-if-indent)))
- ((looking-at "where[ \t]*(.*)[ \t]*\n")
- (setq icol (+ icol fortran-if-indent)))
- ((looking-at "do\\b")
- (setq icol (+ icol fortran-do-indent)))
- ((looking-at
- "\\(structure\\|union\\|map\\|interface\\)\\b[ \t]*[^ \t=(a-z]")
- (setq icol (+ icol fortran-structure-indent)))
- ((looking-at "end\\b[ \t]*[^ \t=(a-z]")
- ;; Previous END resets indent to minimum
- (setq icol fortran-minimum-statement-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-extra-indent)))
- ((eq fortran-comment-indent-style 'fixed)
- (setq icol (+ fortran-minimum-statement-indent
- fortran-comment-line-extra-indent))))
- (setq fortran-minimum-statement-indent 0))
- ((or (looking-at (concat "[ \t]*"
- (regexp-quote
- fortran-continuation-string)))
- (looking-at " [^ 0\n]")
- (looking-at "\t[1-9]"))
- (setq icol (+ icol fortran-continuation-indent)))
- ((looking-at "[ \t]*#") ; Check for cpp directive.
- (setq fortran-minimum-statement-indent 0 icol 0))
- (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)))
- ((looking-at "case[ \t]*(.*)[ \t]*\n")
- (setq icol (- icol fortran-if-indent)))
- ((looking-at "case[ \t]*default\\b")
- (setq icol (- icol fortran-if-indent)))
- ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b")
- (setq icol (- icol fortran-if-indent)))
- ((looking-at "end[ \t]*where\\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)))
- ((looking-at
- "end[ \t]*\
-\\(structure\\|union\\|map\\|interface\\)\\b[ \t]*[^ \t=(a-z]")
- (setq icol (- icol fortran-structure-indent)))
- ((looking-at
- "end[ \t]*select\\b[ \t]*[^ \t=(a-z]")
- (setq icol (- icol fortran-if-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/8 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))))
- ((or (looking-at " [^ 0\n]")
- (looking-at "\t[1-9]"))
- (goto-char (match-end 0)))
- (t
- ;; Move past line number.
- (skip-chars-forward "[ \t0-9]");From Uli
- ))
- ;; 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-string' 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.
- 4) A TAB followed by a digit indicates a continuation 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 "\t[1-9]")
- (if indent-tabs-mode
- (goto-char (match-end 0))
- (delete-char 2)
- (insert " ")
- (insert fortran-continuation-string))
- (if (looking-at " [^ 0\n]")
- (if indent-tabs-mode
- (progn (delete-char 6)
- (insert "\t")
- (insert-char (fortran-numerical-continuation-char) 1))
- (forward-char 6))
- (delete-horizontal-space)
- ;; Put line number in columns 0-4
- ;; or put continuation character in column 5.
- (cond ((eobp))
- ((looking-at (regexp-quote fortran-continuation-string))
- (if indent-tabs-mode
- (progn
- (indent-to
- (if indent-tabs-mode
- fortran-minimum-statement-indent-tab
- fortran-minimum-statement-indent-fixed))
- (delete-char 1)
- (insert-char (fortran-numerical-continuation-char) 1))
- (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 (and comment-start-skip
- (fortran-find-comment-start-skip))
- (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 indented.
-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.
-Otherwise return a nil."
- (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))))))))
-
-(defun fortran-find-comment-start-skip ()
- "Move to past `comment-start-skip' found on current line.
-Return t if `comment-start-skip' found, nil if not."
-;;; In order to move point only if comment-start-skip is found,
-;;; this one uses a lot of save-excursions. Note that re-search-forward
-;;; moves point even if comment-start-skip is inside a string-constant.
-;;; Some code expects certain values for match-beginning and end
- (interactive)
- (if (save-excursion
- (re-search-forward comment-start-skip
- (save-excursion (end-of-line) (point)) t))
- (let ((save-match-beginning (match-beginning 0))
- (save-match-end (match-end 0)))
- (if (fortran-is-in-string-p (match-beginning 0))
- (save-excursion
- (goto-char save-match-end)
- (fortran-find-comment-start-skip)) ; recurse for rest of line
- (goto-char save-match-beginning)
- (re-search-forward comment-start-skip
- (save-excursion (end-of-line) (point)) t)
- (goto-char (match-end 0))
- t))
- nil))
-
-;;;From: simon@gnu (Simon Marshall)
-;;; Find the next ! not in a string.
-(defun fortran-match-!-comment (limit)
- (let (found)
- (while (and (setq found (search-forward "!" limit t))
- (fortran-is-in-string-p (point))))
- (if (not found)
- nil
- ;; Cheaper than `looking-at' "!.*".
- (store-match-data
- (list (1- (point)) (progn (end-of-line) (min (point) limit))))
- t)))
-
-;; The above function is about 10% faster than the below...
-;;(defun fortran-match-!-comment (limit)
-;; (let (found)
-;; (while (and (setq found (re-search-forward "!.*" limit t))
-;; (fortran-is-in-string-p (match-beginning 0))))
-;; found))
-
-;;;From: ralf@up3aud1.gwdg.de (Ralf Fassel)
-;;; Test if TAB format continuation lines work.
-(defun fortran-is-in-string-p (where)
- "Return non-nil if POS (a buffer position) is inside a Fortran string,
-nil else."
- (save-excursion
- (goto-char where)
- (cond
- ((bolp) nil) ; bol is never inside a string
- ((save-excursion ; comment lines too
- (beginning-of-line)(looking-at comment-line-start-skip)) nil)
- (t (let (;; ok, serious now. Init some local vars:
- (parse-state '(0 nil nil nil nil nil 0))
- (quoted-comment-start (if comment-start
- (regexp-quote comment-start)))
- (not-done t)
- parse-limit
- end-of-line
- )
- ;; move to start of current statement
- (fortran-next-statement)
- (fortran-previous-statement)
- ;; now parse up to WHERE
- (while not-done
- (if (or ;; skip to next line if:
- ;; - comment line?
- (looking-at comment-line-start-skip)
- ;; - at end of line?
- (eolp)
- ;; - not in a string and after comment-start?
- (and (not (nth 3 parse-state))
- comment-start
- (equal comment-start
- (char-to-string (preceding-char)))))
- ;; get around a bug in forward-line in versions <= 18.57
- (if (or (> (forward-line 1) 0) (eobp))
- (setq not-done nil))
- ;; else:
- ;; if we are at beginning of code line, skip any
- ;; whitespace, labels and tab continuation markers.
- (if (bolp) (skip-chars-forward " \t0-9"))
- ;; if we are in column <= 5 now, check for continuation char
- (cond ((= 5 (current-column)) (forward-char 1))
- ((and (< (current-column) 5)
- (equal fortran-continuation-string
- (char-to-string (following-char)))
- (forward-char 1))))
- ;; find out parse-limit from here
- (setq end-of-line (save-excursion (end-of-line)(point)))
- (setq parse-limit (min where end-of-line))
- ;; parse max up to comment-start, if non-nil and in current line
- (if comment-start
- (save-excursion
- (if (re-search-forward quoted-comment-start end-of-line t)
- (setq parse-limit (min (point) parse-limit)))))
- ;; now parse if still in limits
- (if (< (point) where)
- (setq parse-state (parse-partial-sexp
- (point) parse-limit nil nil parse-state))
- (setq not-done nil))
- ))
- ;; result is
- (nth 3 parse-state))))))
-
-(defun fortran-auto-fill-mode (arg)
- "Toggle fortran-auto-fill mode.
-With ARG, turn `fortran-auto-fill' mode on iff ARG is positive.
-In `fortran-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-function
- (if (if (null arg)
- (not auto-fill-function)
- (> (prefix-numeric-value arg) 0))
- 'fortran-do-auto-fill
- nil))
- (force-mode-line-update)))
-
-(defun fortran-do-auto-fill ()
- (if (> (current-column) fill-column)
- (fortran-indent-line)))
-
-(defun fortran-fill ()
- (interactive)
- (let* ((opoint (point))
- (bol (save-excursion (beginning-of-line) (point)))
- (eol (save-excursion (end-of-line) (point)))
- (bos (min eol (+ bol (fortran-current-line-indentation))))
- (quote
- (save-excursion
- (goto-char bol)
- (if (looking-at comment-line-start-skip)
- nil ; OK to break quotes on comment lines.
- (move-to-column fill-column)
- (cond ((fortran-is-in-string-p (point))
- (save-excursion (re-search-backward "[^']'[^']" bol t)
- (if fortran-break-before-delimiters
- (point)
- (1+ (point)))))
- (t nil)))))
- ;;
- ;; decide where to split the line. If a position for a quoted
- ;; string was found above then use that, else break the line
- ;; before the last delimiter.
- ;; Delimiters are whitespace, commas, and operators.
- ;; Will break before a pair of *'s.
- ;;
- (fill-point
- (or quote
- (save-excursion
- (move-to-column (1+ fill-column))
- (skip-chars-backward "^ \t\n,'+-/*=)"
-;;; (if fortran-break-before-delimiters
-;;; "^ \t\n,'+-/*=" "^ \t\n,'+-/*=)")
- )
- (if (<= (point) (1+ bos))
- (progn
- (move-to-column (1+ fill-column))
-;;;what is this doing???
- (if (not (re-search-forward "[\t\n,'+-/*)=]" eol t))
- (goto-char bol))))
- (if (bolp)
- (re-search-forward "[ \t]" opoint t)
- (forward-char -1)
- (if (looking-at "'")
- (forward-char 1)
- (skip-chars-backward " \t\*")))
- (if fortran-break-before-delimiters
- (point)
- (1+ (point))))))
- )
- ;; if we are in an in-line comment, don't break unless the
- ;; line of code is longer than it should be. Otherwise
- ;; break the line at the column computed above.
- ;;
- ;; Need to use fortran-find-comment-start-skip to make sure that quoted !'s
- ;; don't prevent a break.
- (if (not (or (save-excursion
- (if (and (re-search-backward comment-start-skip bol t)
- (not (fortran-is-in-string-p (point))))
- (progn
- (skip-chars-backward " \t")
- (< (current-column) (1+ fill-column)))))
- (save-excursion
- (goto-char fill-point)
- (bolp))))
- (if (> (save-excursion
- (goto-char fill-point) (current-column))
- (1+ fill-column))
- (progn (goto-char fill-point)
- (fortran-break-line))
- (save-excursion
- (if (> (save-excursion
- (goto-char fill-point)
- (current-column))
- (+ (calculate-fortran-indent) fortran-continuation-indent))
- (progn
- (goto-char fill-point)
- (fortran-break-line))))))
- ))
-(defun fortran-break-line ()
- (let ((opoint (point))
- (bol (save-excursion (beginning-of-line) (point)))
- (eol (save-excursion (end-of-line) (point)))
- (comment-string nil))
-
- (save-excursion
- (if (and comment-start-skip (fortran-find-comment-start-skip))
- (progn
- (re-search-backward comment-start-skip bol t)
- (setq comment-string (buffer-substring (point) eol))
- (delete-region (point) eol))))
-;;; Forward line 1 really needs to go to next non white line
- (if (save-excursion (forward-line 1)
- (or (looking-at " [^ 0\n]")
- (looking-at "\t[1-9]")))
- (progn
- (end-of-line)
- (delete-region (point) (match-end 0))
- (delete-horizontal-space)
- (fortran-fill))
- (fortran-split-line))
- (if comment-string
- (save-excursion
- (goto-char bol)
- (end-of-line)
- (delete-horizontal-space)
- (indent-to (fortran-comment-hook))
- (insert comment-string)))))
-
-(defun fortran-analyze-file-format ()
- "Returns nil if fixed format is used, t if TAB formatting is used.
-Use `fortran-tab-mode-default' if no non-comment statements are found in the
-file before the end or the first `fortran-analyze-depth' lines."
- (let ((i 0))
- (save-excursion
- (goto-char (point-min))
- (setq i 0)
- (while (not (or
- (eobp)
- (looking-at "\t")
- (looking-at " ")
- (> i fortran-analyze-depth)))
- (forward-line)
- (setq i (1+ i)))
- (cond
- ((looking-at "\t") t)
- ((looking-at " ") nil)
- (fortran-tab-mode-default t)
- (t nil)))))
-
-(or (assq 'fortran-tab-mode-string minor-mode-alist)
- (setq minor-mode-alist (cons
- '(fortran-tab-mode-string
- (indent-tabs-mode fortran-tab-mode-string))
- minor-mode-alist)))
-
-(provide 'fortran)
-
-;;; fortran.el ends here
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el
deleted file mode 100644
index 5c97d41255e..00000000000
--- a/lisp/progmodes/hideif.el
+++ /dev/null
@@ -1,1048 +0,0 @@
-;;; hide-ifdef-mode.el --- hides selected code within ifdef.
-
-;; Copyright (C) 1988, 1994 Free Software Foundation, Inc.
-
-;; Author: Dan LaLiberte <liberte@a.cs.uiuc.edu>
-;; Maintainer: FSF
-;; Keywords: c, outlines
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; To initialize, toggle the hide-ifdef minor mode with
-;;
-;; M-x hide-ifdef-mode
-;;
-;; This will set up key bindings and call hide-ifdef-mode-hook if it
-;; has a value. To explicitly hide ifdefs using a buffer-local
-;; define list (default empty), type
-;;
-;; M-x hide-ifdefs or C-c @ h
-;;
-;; Hide-ifdef suppresses the display of code that the preprocessor wouldn't
-;; pass through. The support of constant expressions in #if lines is
-;; limited to identifiers, parens, and the operators: &&, ||, !, and
-;; "defined". Please extend this.
-;;
-;; The hidden code is marked by ellipses (...). Be
-;; cautious when editing near ellipses, since the hidden text is
-;; still in the buffer, and you can move the point into it and modify
-;; text unawares. If you don't want to see the ellipses, set
-;; selective-display-ellipses to nil. But this can be dangerous.
-;; You can make your buffer read-only while hide-ifdef-hiding by setting
-;; hide-ifdef-read-only to a non-nil value. You can toggle this
-;; variable with hide-ifdef-toggle-read-only (C-c @ C-q).
-;;
-;; You can undo the effect of hide-ifdefs by typing
-;;
-;; M-x show-ifdefs or C-c @ s
-;;
-;; Use M-x hide-ifdef-define (C-c @ d) to define a symbol.
-;; Use M-x hide-ifdef-undef (C-c @ u) to undefine a symbol.
-;;
-;; If you define or undefine a symbol while hide-ifdef-mode is in effect,
-;; the display will be updated. Only the define list for the current
-;; buffer will be affected. You can save changes to the local define
-;; list with hide-ifdef-set-define-alist. This adds entries
-;; to hide-ifdef-define-alist.
-;;
-;; If you have defined a hide-ifdef-mode-hook, you can set
-;; up a list of symbols that may be used by hide-ifdefs as in the
-;; following example:
-;;
-;; (setq hide-ifdef-mode-hook
-;; '(lambda ()
-;; (if (not hide-ifdef-define-alist)
-;; (setq hide-ifdef-define-alist
-;; '((list1 ONE TWO)
-;; (list2 TWO THREE)
-;; )))
-;; (hide-ifdef-use-define-alist 'list2) ; use list2 by default
-;; ))
-;;
-;; You can call hide-ifdef-use-define-alist (C-c @ u) at any time to specify
-;; another list to use.
-;;
-;; To cause ifdefs to be hidden as soon as hide-ifdef-mode is called,
-;; set hide-ifdef-initially to non-nil.
-;;
-;; If you set hide-ifdef-lines to t, hide-ifdefs hides all the #ifdef lines.
-;; In the absence of highlighting, that might be a bad idea. If you set
-;; hide-ifdef-lines to nil (the default), the surrounding preprocessor
-;; lines will be displayed. That can be confusing in its own
-;; right. Other variations on display are possible, but not much
-;; better.
-;;
-;; You can explicitly hide or show individual ifdef blocks irrespective
-;; of the define list by using hide-ifdef-block and show-ifdef-block.
-;;
-;; You can move the point between ifdefs with forward-ifdef, backward-ifdef,
-;; up-ifdef, down-ifdef, next-ifdef, and previous-ifdef.
-;;
-;; If you have minor-mode-alist in your mode line (the default) two labels
-;; may appear. "Ifdef" will appear when hide-ifdef-mode is active. "Hiding"
-;; will appear when text may be hidden ("hide-ifdef-hiding" is non-nil).
-;;
-;; Written by Brian Marick, at Gould, Computer Systems Division, Urbana IL.
-;; Extensively modified by Daniel LaLiberte (while at Gould).
-;;
-;; You may freely modify and distribute this, but keep a record
-;; of modifications and send comments to:
-;; liberte@a.cs.uiuc.edu or ihnp4!uiucdcs!liberte
-;; I will continue to upgrade hide-ifdef-mode
-;; with your contributions.
-
-;;; Code:
-
-(require 'cc-mode)
-
-(defvar hide-ifdef-mode-submap nil
- "Keymap used with Hide-Ifdef mode.")
-
-(defvar hide-ifdef-mode-map nil
- "Keymap used with Hide-Ifdef mode.")
-
-(defconst hide-ifdef-mode-prefix-key "\C-c@"
- "Prefix key for all Hide-Ifdef mode commands.")
-
-;; Set up the submap that goes after the prefix key.
-(if hide-ifdef-mode-submap
- () ; Don't redefine it.
- (setq hide-ifdef-mode-submap (make-sparse-keymap))
- (define-key hide-ifdef-mode-submap "d" 'hide-ifdef-define)
- (define-key hide-ifdef-mode-submap "u" 'hide-ifdef-undef)
- (define-key hide-ifdef-mode-submap "D" 'hide-ifdef-set-define-alist)
- (define-key hide-ifdef-mode-submap "U" 'hide-ifdef-use-define-alist)
-
- (define-key hide-ifdef-mode-submap "h" 'hide-ifdefs)
- (define-key hide-ifdef-mode-submap "s" 'show-ifdefs)
- (define-key hide-ifdef-mode-submap "\C-d" 'hide-ifdef-block)
- (define-key hide-ifdef-mode-submap "\C-s" 'show-ifdef-block)
-
- (define-key hide-ifdef-mode-submap "\C-q" 'hide-ifdef-toggle-read-only)
- (let ((where (where-is-internal 'toggle-read-only '(keymap) t)))
- (if where
- (define-key hide-ifdef-mode-submap
- where
- 'hide-ifdef-toggle-outside-read-only)))
- )
-
-;; Set up the mode's main map, which leads via the prefix key to the submap.
-(if hide-ifdef-mode-map
- ()
- (setq hide-ifdef-mode-map (make-sparse-keymap))
- (define-key hide-ifdef-mode-map hide-ifdef-mode-prefix-key
- hide-ifdef-mode-submap))
-
-(defvar hide-ifdef-mode nil
- "Non-nil when hide-ifdef-mode is activated.")
-
-(defvar hide-ifdef-hiding nil
- "Non-nil when text may be hidden.")
-
-;; Arrange to use the mode's map when the mode is enabled.
-(or (assq 'hide-ifdef-mode minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons (cons 'hide-ifdef-mode hide-ifdef-mode-map)
- minor-mode-map-alist)))
-
-(or (assq 'hide-ifdef-hiding minor-mode-alist)
- (setq minor-mode-alist
- (cons '(hide-ifdef-hiding " Hiding")
- minor-mode-alist)))
-
-(or (assq 'hide-ifdef-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(hide-ifdef-mode " Ifdef")
- minor-mode-alist)))
-
-;; fix c-mode syntax table so we can recognize whole symbols.
-(defvar hide-ifdef-syntax-table
- (copy-syntax-table c-mode-syntax-table)
- "Syntax table used for tokenizing #if expressions.")
-
-(modify-syntax-entry ?_ "w" hide-ifdef-syntax-table)
-(modify-syntax-entry ?& "." hide-ifdef-syntax-table)
-(modify-syntax-entry ?\| "." hide-ifdef-syntax-table)
-
-;;;###autoload
-(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 if arg is positive, off otherwise.
-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.
-
-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'.
-
-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
- 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.
-
-\\{hide-ifdef-mode-map}"
-
- (interactive "P")
- (make-local-variable 'hide-ifdef-mode)
- (setq hide-ifdef-mode
- (if (null arg)
- (not hide-ifdef-mode)
- (> (prefix-numeric-value arg) 0)))
-
- (force-mode-line-update)
-
- (if hide-ifdef-mode
- (progn
- ; inherit global values
- (make-local-variable 'hide-ifdef-env)
- (setq hide-ifdef-env (default-value 'hide-ifdef-env))
-
- (make-local-variable 'hide-ifdef-hiding)
- (setq hide-ifdef-hiding (default-value 'hide-ifdef-hiding))
-
- (make-local-variable 'hif-outside-read-only)
- (setq hif-outside-read-only buffer-read-only)
-
- (run-hooks 'hide-ifdef-mode-hook)
-
- (if hide-ifdef-initially
- (hide-ifdefs)
- (show-ifdefs))
- (message "Enter Hide-Ifdef mode")
- )
- ; else end hide-ifdef-mode
- (if hide-ifdef-hiding
- (show-ifdefs))
- (message "Exit Hide-Ifdef mode")
- ))
-
-
-;; from outline.el with docstring fixed.
-(defun hif-outline-flag-region (from to flag)
- "Hides or shows lines from FROM to TO, according to FLAG.
-If FLAG is \\n (newline character) then text is shown, while if FLAG is \\^M
-\(control-M) the text is hidden."
- (let ((modp (buffer-modified-p)))
- (unwind-protect (progn
- (subst-char-in-region from to
- (if (= flag ?\n) ?\^M ?\n)
- flag t) )
- (set-buffer-modified-p modp))
- ))
-
-(defun hif-show-all ()
- "Show all of the text in the current buffer."
- (interactive)
- (hif-outline-flag-region (point-min) (point-max) ?\n))
-
-;; By putting this on after-revert-hook, we arrange that it only
-;; does anything when revert-buffer avoids turning off the mode.
-;; (That can happen in VC.)
-(defun hif-before-revert-function ()
- (and hide-ifdef-mode hide-ifdef-hiding
- (hide-ifdefs t)))
-(add-hook 'after-revert-hook 'hif-before-revert-function)
-
-(defun hide-ifdef-region (start end)
- "START is the start of a #if or #else form. END is the ending part.
-Everything including these lines is made invisible."
- (hif-outline-flag-region start end ?\^M)
- )
-
-(defun hif-show-ifdef-region (start end)
- "Everything between START and END is made visible."
- (hif-outline-flag-region start end ?\n)
- )
-
-
-
-;===%%SF%% evaluation (Start) ===
-
-;; It is not useful to set this to anything but `eval'.
-;; In fact, the variable might as well be eliminated.
-(defvar hide-ifdef-evaluator 'eval
- "The function to use to evaluate a form.
-The evaluator is given a canonical form and returns t if text under
-that form should be displayed.")
-
-(defvar hif-undefined-symbol nil
- "...is by default considered to be false.")
-
-(defvar hide-ifdef-env nil
- "An alist of defined symbols and their values.")
-
-
-(defun hif-set-var (var value)
- "Prepend (var value) pair to hide-ifdef-env."
- (setq hide-ifdef-env (cons (cons var value) hide-ifdef-env)))
-
-
-(defun hif-lookup (var)
-; (message "hif-lookup %s" var)
- (let ((val (assoc var hide-ifdef-env)))
- (if val
- (cdr val)
- hif-undefined-symbol)))
-
-(defun hif-defined (var)
- (hif-lookup var)
- ; when #if expressions are fully supported, defined result should be 1
- ; (if (assoc var hide-ifdef-env)
- ; 1
- ; nil)
-)
-
-
-;===%%SF%% evaluation (End) ===
-
-
-
-;===%%SF%% parsing (Start) ===
-;;; The code that understands what ifs and ifdef in files look like.
-
-(defconst hif-cpp-prefix "\\(^\\|\r\\)[ \t]*#[ \t]*")
-(defconst hif-ifndef-regexp (concat hif-cpp-prefix "ifndef"))
-(defconst hif-ifx-regexp (concat hif-cpp-prefix "if\\(n?def\\)?[ \t]+"))
-(defconst hif-else-regexp (concat hif-cpp-prefix "else"))
-(defconst hif-endif-regexp (concat hif-cpp-prefix "endif"))
-(defconst hif-ifx-else-endif-regexp
- (concat hif-ifx-regexp "\\|" hif-else-regexp "\\|" hif-endif-regexp))
-
-
-(defun hif-infix-to-prefix (token-list)
- "Convert list of tokens in infix into prefix list"
-; (message "hif-infix-to-prefix: %s" token-list)
- (if (= 1 (length token-list))
- (` (hif-lookup (quote (, (car token-list)))))
- (hif-parse-if-exp token-list))
- )
-
-; pattern to match initial identifier, !, &&, ||, (, or ).
-; Added ==, + and -: garyo@avs.com 8/9/94
-(defconst hif-token-regexp "^\\(&&\\|||\\|[!=]=\\|!\\|[()+-]\\|\\w+\\)")
-(defconst hif-end-of-comment "\\*/")
-
-
-(defun hif-tokenize (expr-string)
- "Separate string into a list of tokens"
- (let ((token-list nil)
- (expr-start 0)
- (expr-length (length expr-string))
- (current-syntax-table (syntax-table)))
- (unwind-protect
- (progn
- (set-syntax-table hide-ifdef-syntax-table)
- (while (< expr-start expr-length)
-; (message "expr-start = %d" expr-start) (sit-for 1)
- (cond
- ((string-match "^[ \t]+" expr-string expr-start)
- ;; skip whitespace
- (setq expr-start (match-end 0))
- ;; stick newline in string so ^ matches on the next string-match
- (aset expr-string (1- expr-start) ?\n))
-
- ((string-match "^/\\*" expr-string expr-start)
- (setq expr-start (match-end 0))
- (aset expr-string (1- expr-start) ?\n)
- (or
- (string-match hif-end-of-comment
- expr-string expr-start) ; eat comment
- (string-match "$" expr-string expr-start)) ; multi-line comment
- (setq expr-start (match-end 0))
- (aset expr-string (1- expr-start) ?\n))
-
- ((string-match "^//" expr-string expr-start)
- (string-match "$" expr-string expr-start)
- (setq expr-start (match-end 0)))
-
- ((string-match hif-token-regexp expr-string expr-start)
- (let ((token (substring expr-string expr-start (match-end 0))))
- (setq expr-start (match-end 0))
- (aset expr-string (1- expr-start) ?\n)
-; (message "token: %s" token) (sit-for 1)
- (setq token-list
- (cons
- (cond
- ((string-equal token "||") 'or)
- ((string-equal token "&&") 'and)
- ((string-equal token "==") 'equal)
- ((string-equal token "!=") 'hif-notequal)
- ((string-equal token "!") 'not)
- ((string-equal token "defined") 'hif-defined)
- ((string-equal token "(") 'lparen)
- ((string-equal token ")") 'rparen)
- ((string-equal token "+") 'hif-plus)
- ((string-equal token "-") 'hif-minus)
- (t (intern token)))
- token-list))))
- (t (error "Bad #if expression: %s" expr-string)))))
- (set-syntax-table current-syntax-table))
- (nreverse token-list)))
-
-;;;-----------------------------------------------------------------
-;;; Translate C preprocessor #if expressions using recursive descent.
-;;; This parser is limited to the operators &&, ||, !, and "defined".
-;;; Added ==, !=, +, and -. Gary Oberbrunner, garyo@avs.com, 8/9/94
-
-(defun hif-parse-if-exp (token-list)
- "Parse the TOKEN-LIST. Return translated list in prefix form."
- (hif-nexttoken)
- (prog1
- (hif-expr)
- (if token ; is there still a 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)
-
-(defun hif-expr ()
- "Parse an expression as found in #if.
- expr : term | expr '||' term."
- (let ((result (hif-term)))
- (while (eq token 'or)
- (hif-nexttoken)
- (setq result (list 'or result (hif-term))))
- result))
-
-(defun hif-term ()
- "Parse a term : eq-expr | term '&&' eq-expr."
- (let ((result (hif-eq-expr)))
- (while (eq token 'and)
- (hif-nexttoken)
- (setq result (list 'and result (hif-eq-expr))))
- result))
-
-(defun hif-eq-expr ()
- "Parse an eq-expr : math | eq-expr '=='|'!=' math."
- (let ((result (hif-math))
- (eq-token nil))
- (while (or (eq token 'equal) (eq token 'hif-notequal))
- (setq eq-token token)
- (hif-nexttoken)
- (setq result (list eq-token result (hif-math))))
- result))
-
-(defun hif-math ()
- "Parse an expression with + or - and simpler things.
- math : factor | math '+|-' factor."
- (let ((result (hif-factor))
- (math-op nil))
- (while (or (eq token 'hif-plus) (eq token 'hif-minus))
- (setq math-op token)
- (hif-nexttoken)
- (setq result (list math-op result (hif-factor))))
- result))
-
-(defun hif-factor ()
- "Parse a factor: '!' factor | '(' expr ')' | 'defined(' id ')' | id."
- (cond
- ((eq token 'not)
- (hif-nexttoken)
- (list 'not (hif-factor)))
-
- ((eq token 'lparen)
- (hif-nexttoken)
- (let ((result (hif-expr)))
- (if (not (eq token 'rparen))
- (error "Bad token in parenthesized expression: %s" token)
- (hif-nexttoken)
- result)))
-
- ((eq token 'hif-defined)
- (hif-nexttoken)
- (if (not (eq token 'lparen))
- (error "Error: expected \"(\" after \"defined\""))
- (hif-nexttoken)
- (let ((ident token))
- (if (memq token '(or and not hif-defined lparen rparen))
- (error "Error: unexpected token: %s" token))
- (hif-nexttoken)
- (if (not (eq token 'rparen))
- (error "Error: expected \")\" after identifier"))
- (hif-nexttoken)
- (` (hif-defined (quote (, ident))))
- ))
-
- (t ; identifier
- (let ((ident token))
- (if (memq ident '(or and))
- (error "Error: missing identifier"))
- (hif-nexttoken)
- (` (hif-lookup (quote (, ident))))
- ))
- ))
-
-(defun hif-mathify (val)
- "Treat VAL as a number: if it's t or nil, use 1 or 0."
- (cond ((eq val t)
- 1)
- ((null val)
- 0)
- (t val)))
-
-(defun hif-plus (a b)
- "Like ordinary plus but treat t and nil as 1 and 0."
- (+ (hif-mathify a) (hif-mathify b)))
-(defun hif-minus (a b)
- "Like ordinary minus but treat t and nil as 1 and 0."
- (- (hif-mathify a) (hif-mathify b)))
-(defun hif-notequal (a b)
- "Like (not (equal A B)) but as one symbol."
- (not (equal a b)))
-
-;;;----------- end of parser -----------------------
-
-
-(defun hif-canonicalize ()
- "When at beginning of #ifX, returns a Lisp expression for its condition."
- (save-excursion
- (let ((negate (looking-at hif-ifndef-regexp)))
- (re-search-forward hif-ifx-regexp)
- (let* ((expr-string
- (buffer-substring (point)
- (progn (skip-chars-forward "^\n\r") (point))))
- (expr (hif-infix-to-prefix (hif-tokenize expr-string))))
-; (message "hif-canonicalized: %s" expr)
- (if negate
- (list 'not expr)
- expr)))))
-
-
-(defun hif-find-any-ifX ()
- "Move to next #if..., or #ifndef, at point or after."
-; (message "find ifX at %d" (point))
- (prog1
- (re-search-forward hif-ifx-regexp (point-max) t)
- (beginning-of-line)))
-
-
-(defun hif-find-next-relevant ()
- "Move to next #if..., #else, or #endif, after the current line."
-; (message "hif-find-next-relevant at %d" (point))
- (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)))
-
-(defun hif-find-previous-relevant ()
- "Move to previous #if..., #else, or #endif, before the current line."
-; (message "hif-find-previous-relevant at %d" (point))
- (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)))
-
-
-(defun hif-looking-at-ifX () ;; Should eventually see #if
- (looking-at hif-ifx-regexp))
-(defun hif-looking-at-endif ()
- (looking-at hif-endif-regexp))
-(defun hif-looking-at-else ()
- (looking-at hif-else-regexp))
-
-
-
-(defun hif-ifdef-to-endif ()
- "If positioned at #ifX or #else form, skip to corresponding #endif."
-; (message "hif-ifdef-to-endif at %d" (point)) (sit-for 1)
- (hif-find-next-relevant)
- (cond ((hif-looking-at-ifX)
- (hif-ifdef-to-endif) ; find endif of nested if
- (hif-ifdef-to-endif)) ; find outer endif or else
- ((hif-looking-at-else)
- (hif-ifdef-to-endif)) ; find endif following else
- ((hif-looking-at-endif)
- 'done)
- (t
- (error "Mismatched #ifdef #endif pair"))))
-
-
-(defun hif-endif-to-ifdef ()
- "If positioned at #endif form, skip backward to corresponding #ifX."
-; (message "hif-endif-to-ifdef at %d" (point))
- (let ((start (point)))
- (hif-find-previous-relevant)
- (if (= start (point))
- (error "Mismatched #ifdef #endif pair")))
- (cond ((hif-looking-at-endif)
- (hif-endif-to-ifdef) ; find beginning of nested if
- (hif-endif-to-ifdef)) ; find beginning of outer if or else
- ((hif-looking-at-else)
- (hif-endif-to-ifdef))
- ((hif-looking-at-ifX)
- 'done)
- (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."
- (interactive "p")
- (or arg (setq arg 1))
- (if (< arg 0)
- (backward-ifdef (- arg)))
- (while (< 0 arg)
- (setq arg (- arg))
- (let ((start (point)))
- (if (not (hif-looking-at-ifX))
- (hif-find-next-relevant))
- (if (hif-looking-at-ifX)
- (hif-ifdef-to-endif)
- (goto-char start)
- (error "No following #ifdef")
- ))))
-
-
-(defun backward-ifdef (&optional arg)
- "Move point to beginning of the previous ifdef-endif.
-With argument, do this that many times."
- (interactive "p")
- (or arg (setq arg 1))
- (if (< arg 0)
- (forward-ifdef (- arg)))
- (while (< 0 arg)
- (setq arg (1- arg))
- (beginning-of-line)
- (let ((start (point)))
- (if (not (hif-looking-at-endif))
- (hif-find-previous-relevant))
- (if (hif-looking-at-endif)
- (hif-endif-to-ifdef)
- (goto-char start)
- (error "No previous #ifdef")))))
-
-
-(defun down-ifdef ()
- "Move point to beginning of nested ifdef or else-part."
- (interactive)
- (let ((start (point)))
- (hif-find-next-relevant)
- (if (or (hif-looking-at-ifX) (hif-looking-at-else))
- ()
- (goto-char start)
- (error "No following #ifdef"))))
-
-
-(defun up-ifdef ()
- "Move point to beginning of enclosing ifdef or else-part."
- (interactive)
- (beginning-of-line)
- (let ((start (point)))
- (if (not (hif-looking-at-endif))
- (hif-find-previous-relevant))
- (if (hif-looking-at-endif)
- (hif-endif-to-ifdef))
- (if (= start (point))
- (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."
- (interactive "p")
- (or arg (setq arg 1))
- (if (< arg 0)
- (previous-ifdef (- arg)))
- (while (< 0 arg)
- (setq arg (1- arg))
- (hif-find-next-relevant)
- (if (eolp)
- (progn
- (beginning-of-line)
- (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."
- (interactive "p")
- (or arg (setq arg 1))
- (if (< arg 0)
- (next-ifdef (- arg)))
- (while (< 0 arg)
- (setq arg (1- arg))
- (let ((start (point)))
- (hif-find-previous-relevant)
- (if (= start (point))
- (error "No previous #ifdefs, #elses, or #endifs")
- ))))
-
-
-;===%%SF%% parsing (End) ===
-
-
-;===%%SF%% hide-ifdef-hiding (Start) ===
-
-
-;;; A range is a structure with four components:
-;;; ELSE-P True if there was an else clause for the ifdef.
-;;; START The start of the range. (beginning of line)
-;;; ELSE The else marker (beginning of line)
-;;; Only valid if ELSE-P is true.
-;;; END The end of the range. (beginning of line)
-
-(defun hif-make-range (else-p start end &optional else)
- (list else-p start else end))
-
-(defun hif-range-else-p (range) (elt range 0))
-(defun hif-range-start (range) (elt range 1))
-(defun hif-range-else (range) (elt range 2))
-(defun hif-range-end (range) (elt range 3))
-
-
-
-;;; Find-Range
-;;; The workhorse, it delimits the #if region. Reasonably simple:
-;;; Skip until an #else or #endif is found, remembering positions. If
-;;; an #else was found, skip some more, looking for the true #endif.
-
-(defun hif-find-range ()
- "Returns a Range structure describing the current #if region.
-Point is left unchanged."
-; (message "hif-find-range at %d" (point))
- (save-excursion
- (beginning-of-line)
- (let ((start (point))
- (else-p nil)
- (else nil)
- (end nil))
- ;; Part one. Look for either #endif or #else.
- ;; This loop-and-a-half dedicated to E. Dijkstra.
- (hif-find-next-relevant)
- (while (hif-looking-at-ifX) ; Skip nested ifdef
- (hif-ifdef-to-endif)
- (hif-find-next-relevant))
- ;; Found either a #else or an #endif.
- (cond ((hif-looking-at-else)
- (setq else-p t)
- (setq else (point)))
- (t
- (setq end (point)) ; (save-excursion (end-of-line) (point))
- ))
- ;; If found #else, look for #endif.
- (if else-p
- (progn
- (hif-find-next-relevant)
- (while (hif-looking-at-ifX) ; Skip nested ifdef
- (hif-ifdef-to-endif)
- (hif-find-next-relevant))
- (if (hif-looking-at-else)
- (error "Found two elses in a row? Broken!"))
- (setq end (point)) ; (save-excursion (end-of-line) (point))
- ))
- (hif-make-range else-p start end else))))
-
-
-;;; A bit slimy.
-;;; NOTE: If there's an #ifdef at the beginning of the file, we can't
-;;; hide it. There's no previous newline to replace. If we added
-;;; 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."
- (if hide-ifdef-lines
- (save-excursion
- (goto-char point)
- (let ((modp (buffer-modified-p)))
- (unwind-protect
- (progn
- (beginning-of-line)
- (if (not (= (point) 1))
- (hide-ifdef-region (1- (point)) (point))))
- (set-buffer-modified-p modp))
- ))
- ))
-
-
-;;; Hif-Possibly-Hide
-;;; There are four cases. The #ifX expression is "taken" if it
-;;; the hide-ifdef-evaluator returns T. Presumably, this means the code
-;;; inside the #ifdef would be included when the program was
-;;; compiled.
-;;;
-;;; Case 1: #ifX taken, and there's an #else.
-;;; The #else part must be hidden. The #if (then) part must be
-;;; processed for nested #ifX's.
-;;; Case 2: #ifX taken, and there's no #else.
-;;; The #if part must be processed for nested #ifX's.
-;;; Case 3: #ifX not taken, and there's an #else.
-;;; The #if part must be hidden. The #else part must be processed
-;;; for nested #ifs.
-;;; Case 4: #ifX not taken, and there's no #else.
-;;; The #ifX part must be hidden.
-;;;
-;;; Further processing is done by narrowing to the relevant region
-;;; and just recursively calling hide-ifdef-guts.
-;;;
-;;; When hif-possibly-hide returns, point is at the end of the
-;;; possibly-hidden range.
-
-(defun hif-recurse-on (start end)
- "Call `hide-ifdef-guts' after narrowing to end of START line and END line."
- (save-excursion
- (save-restriction
- (goto-char start)
- (end-of-line)
- (narrow-to-region (point) end)
- (hide-ifdef-guts))))
-
-(defun hif-possibly-hide ()
- "Called at #ifX expression, this hides those parts that should be hidden.
-It uses the judgement of `hide-ifdef-evaluator'."
-; (message "hif-possibly-hide") (sit-for 1)
- (let ((test (hif-canonicalize))
- (range (hif-find-range)))
-; (message "test = %s" test) (sit-for 1)
-
- (hif-hide-line (hif-range-end range))
- (if (funcall hide-ifdef-evaluator test)
- (cond ((hif-range-else-p range) ; case 1
- (hif-hide-line (hif-range-else range))
- (hide-ifdef-region (hif-range-else range)
- (1- (hif-range-end range)))
- (hif-recurse-on (hif-range-start range)
- (hif-range-else range)))
- (t ; case 2
- (hif-recurse-on (hif-range-start range)
- (hif-range-end range))))
- (cond ((hif-range-else-p range) ; case 3
- (hif-hide-line (hif-range-else range))
- (hide-ifdef-region (hif-range-start range)
- (1- (hif-range-else range)))
- (hif-recurse-on (hif-range-else range)
- (hif-range-end range)))
- (t ; case 4
- (hide-ifdef-region (point)
- (1- (hif-range-end range))))
- ))
- (hif-hide-line (hif-range-start range)) ; Always hide start.
- (goto-char (hif-range-end range))
- (end-of-line)
- ))
-
-
-
-(defun hide-ifdef-guts ()
- "Does most of the work of `hide-ifdefs'.
-It does not do the work that's pointless to redo on a recursive entry."
-; (message "hide-ifdef-guts")
- (save-excursion
- (goto-char (point-min))
- (while (hif-find-any-ifX)
- (hif-possibly-hide))))
-
-;===%%SF%% hide-ifdef-hiding (End) ===
-
-
-;===%%SF%% exports (Start) ===
-
-;;;###autoload
-(defvar hide-ifdef-initially nil
- "*Non-nil means call `hide-ifdefs' when Hide-Ifdef mode is first activated.")
-
-;;;###autoload
-(defvar hide-ifdef-read-only nil
- "*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.")
-
-;;;###autoload
-(defvar hide-ifdef-lines nil
- "*Non-nil means hide the #ifX, #else, and #endif lines.")
-
-(defun hide-ifdef-toggle-read-only ()
- "Toggle hide-ifdef-read-only."
- (interactive)
- (setq hide-ifdef-read-only (not hide-ifdef-read-only))
- (message "Hide-Read-Only %s"
- (if hide-ifdef-read-only "ON" "OFF"))
- (if hide-ifdef-hiding
- (setq buffer-read-only (or hide-ifdef-read-only hif-outside-read-only)))
- (force-mode-line-update))
-
-(defun hide-ifdef-toggle-outside-read-only ()
- "Replacement for `toggle-read-only' within Hide-Ifdef mode."
- (interactive)
- (setq hif-outside-read-only (not hif-outside-read-only))
- (message "Read only %s"
- (if hif-outside-read-only "ON" "OFF"))
- (setq buffer-read-only
- (or (and hide-ifdef-hiding hide-ifdef-read-only)
- hif-outside-read-only)
- )
- (force-mode-line-update))
-
-
-(defun hide-ifdef-define (var)
- "Define a VAR so that #ifdef VAR would be included."
- (interactive "SDefine what? ")
- (hif-set-var var 1)
- (if hide-ifdef-hiding (hide-ifdefs)))
-
-(defun hide-ifdef-undef (var)
- "Undefine a VAR so that #ifdef VAR would not be included."
- (interactive "SUndefine what? ")
- (hif-set-var var nil)
- (if hide-ifdef-hiding (hide-ifdefs)))
-
-
-(defun hide-ifdefs (&optional nomsg)
- "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 be included by the C
-preprocessor if it were given the file with those symbols defined.
-
-Turn off hiding by calling `show-ifdefs'."
-
- (interactive)
- (message "Hiding...")
- (setq hif-outside-read-only buffer-read-only)
- (if (not hide-ifdef-mode)
- (hide-ifdef-mode 1)) ; turn on hide-ifdef-mode
- (if hide-ifdef-hiding
- (show-ifdefs)) ; Otherwise, deep confusion.
- (let ((inhibit-read-only t))
- (setq selective-display t)
- (setq hide-ifdef-hiding t)
- (hide-ifdef-guts))
- (setq buffer-read-only (or hide-ifdef-read-only hif-outside-read-only))
- (or nomsg
- (message "Hiding done")))
-
-
-(defun show-ifdefs ()
- "Cancel the effects of `hide-ifdef': show the contents of all #ifdefs."
- (interactive)
- (setq buffer-read-only hif-outside-read-only)
- (setq selective-display nil) ; defaults
- (let ((inhibit-read-only t))
- (hif-show-all))
- (setq hide-ifdef-hiding nil))
-
-
-(defun hif-find-ifdef-block ()
- "Utility for hide and show `ifdef-block'.
-Set top and bottom of ifdef block."
- (let (max-bottom)
- (save-excursion
- (beginning-of-line)
- (if (not (or (hif-looking-at-else) (hif-looking-at-ifX)))
- (up-ifdef))
- (setq top (point))
- (hif-ifdef-to-endif)
- (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))))))
- )
-
-
-(defun hide-ifdef-block ()
- "Hide the ifdef block (true or false part) enclosing or before the cursor."
- (interactive)
- (if (not hide-ifdef-mode)
- (hide-ifdef-mode 1))
- (setq selective-display t)
- (let (top bottom (inhibit-read-only t))
- (hif-find-ifdef-block) ; set top and bottom - dynamic scoping
- (hide-ifdef-region top bottom)
- (if hide-ifdef-lines
- (progn
- (hif-hide-line top)
- (hif-hide-line (1+ bottom))))
- (setq hide-ifdef-hiding t))
- (setq buffer-read-only (or hide-ifdef-read-only hif-outside-read-only)))
-
-
-(defun show-ifdef-block ()
- "Show the ifdef block (true or false part) enclosing or before the cursor."
- (interactive)
- (let ((inhibit-read-only t))
- (if hide-ifdef-lines
- (save-excursion
- (beginning-of-line)
- (hif-show-ifdef-region (1- (point)) (progn (end-of-line) (point))))
-
- (let (top bottom)
- (hif-find-ifdef-block)
- (hif-show-ifdef-region (1- top) bottom)))))
-
-
-;;; definition alist support
-
-(defvar hide-ifdef-define-alist nil
- "A global assoc list of pre-defined symbol lists")
-
-(defun hif-compress-define-list (env)
- "Compress the define list ENV into a list of defined symbols only."
- (let ((defs (mapcar '(lambda (arg)
- (if (hif-lookup (car arg)) (car arg)))
- env))
- (new-defs nil))
- (while defs
- (if (car defs)
- (setq new-defs (cons (car defs) new-defs)))
- (setq defs (cdr 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)))
-
-(defun hide-ifdef-use-define-alist (name)
- "Set `hide-ifdef-env' to the define list specified by NAME."
- (interactive "SUse define list: ")
- (let ((define-list (assoc name hide-ifdef-define-alist)))
- (if define-list
- (setq hide-ifdef-env
- (mapcar '(lambda (arg) (cons arg t))
- (cdr define-list)))
- (error "No define list for %s" name))
- (if hide-ifdef-hiding (hide-ifdefs))))
-
-(provide 'hideif)
-
-;;; hideif.el ends here
-
diff --git a/lisp/progmodes/hideshow.el b/lisp/progmodes/hideshow.el
deleted file mode 100644
index c49c7ea4da3..00000000000
--- a/lisp/progmodes/hideshow.el
+++ /dev/null
@@ -1,492 +0,0 @@
-;;; hideshow.el --- minor mode cmds to selectively display blocks of code
-
-;; Copyright (C) 1994,1995,1996 Free Software Foundation
-
-;; Author: Thien-Thi Nguyen <ttn@netcom.com>
-;; Version: 3.4
-;; Keywords: C C++ lisp tools editing
-;; Time-of-Day-Author-Most-Likely-to-be-Recalcitrant: early morning
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; LCD Archive Entry:
-;; hideshow|Thien-Thi Nguyen|ttn@netcom.com|
-;; minor mode commands to selectively display blocks of code|
-;; 18-Oct-1994|3.4|~/modes/hideshow.el.Z|
-
-;;; Commentary:
-
-;; This file provides `hs-minor-mode'. When active, six commands:
-;; hs-{hide,show}-{all,block}, hs-show-region and hs-minor-mode
-;; are available. They implement block hiding and showing. Blocks are
-;; defined in mode-specific way. In c-mode or c++-mode, they are simply
-;; curly braces, while in lisp-ish modes they are parens. Multi-line
-;; comments (c-mode) can also be hidden. The command M-x hs-minor-mode
-;; toggles the minor mode or sets it (similar to outline minor mode).
-;; See documentation for each command for more info.
-;;
-;; The variable `hs-unbalance-handler-method' controls hideshow's behavior
-;; in the case of "unbalanced parentheses". See doc for more info.
-
-;; Suggested usage:
-
-;; (load-library "hideshow")
-;; (defun my-hs-setup () "enables hideshow and binds some commands"
-;; (hs-minor-mode 1)
-;; (define-key hs-minor-mode-map "\C-ch" 'hs-hide-block)
-;; (define-key hs-minor-mode-map "\C-cs" 'hs-show-block)
-;; (define-key hs-minro-mode-map "\C-cH" 'hs-hide-all)
-;; (define-key hs-minro-mode-map "\C-cS" 'hs-show-all)
-;; (define-key hs-minor-mode-map "\C-cR" 'hs-show-region))
-;; (add-hook 'X-mode-hook 'my-hs-setup t) ; other modes similarly
-;;
-;; where X = {emacs-lisp,c,c++,perl,...}. See the doc for the variable
-;; `hs-special-modes-alist' if you'd like to use hideshow w/ other modes.
-
-;; Etc:
-
-;; Bug reports and fixes welcome (comments, too). Thanks go to
-;; Dean Andrews <adahome@ix.netcom.com>
-;; Preston F. Crow <preston.f.crow@dartmouth.edu>
-;; Gael Marziou <gael@gnlab030.grenoble.hp.com>
-;; Keith Sheffield <sheff@edcsgw2.cr.usgs.gov>
-;; Jan Djarv <jan.djarv@sa.erisoft.se>
-;; Lars Lindberg <qhslali@aom.ericsson.se>
-;; Alf-Ivar Holm <alfh@ifi.uio.no>
-;; for valuable feedback, code and bug reports.
-
-;;; Code:
-
-
-;;;----------------------------------------------------------------------------
-;;; user-configurable variables
-
-(defvar hs-unbalance-handler-method 'top-level
- "*Symbol representing how \"unbalanced parentheses\" should be handled.
-This error is usually signaled by `hs-show-block'. One of four values:
-`top-level', `next-line', `signal' or `ignore'. Default is `top-level'.
-
-- `top-level' -- Show top-level block containing the currently troublesome
- block.
-- `next-line' -- Use the fact that, for an already hidden block, its end
- will be on the next line. Attempt to show this block.
-- `signal' -- Pass the error through, stopping execution.
-- `ignore' -- Ignore the error, continuing execution.
-
-Values other than these four will be interpreted as `signal'.")
-
-(defvar hs-special-modes-alist '((c-mode "{" "}")
- (c++-mode "{" "}"))
- "*Alist of the form (MODE START-RE END-RE FORWARD-SEXP-FUNC).
-If present, hideshow will use these values for the start and end regexps,
-respectively. Since Algol-ish languages do not have single-character
-block delimiters, the function `forward-sexp' which is used by hideshow
-doesn't work. In this case, if a similar function is provided, you can
-register it and have hideshow use it instead of `forward-sexp'. To add
-more values, use
-
-\t(pushnew '(new-mode st-re end-re function-name)
-\t hs-special-modes-alist :test 'equal)
-
-For example:
-
-\t(pushnew '(simula-mode \"begin\" \"end\" simula-next-statement)
-\t hs-special-modes-alist :test 'equal)
-
-Note that the regexps should not contain leading or trailing whitespace.")
-
-(defvar hs-hide-hook nil
- "*Hooks called at the end of `hs-hide-all' and `hs-hide-block'.")
-
-(defvar hs-show-hook nil
- "*Hooks called at the end of commands to show text.
-These commands include `hs-show-all', `hs-show-block' and `hs-show-region'.")
-
-(defvar hs-minor-mode-prefix "\C-c"
- "*Prefix key to use for hideshow commands in hideshow minor mode.")
-
-
-;;;----------------------------------------------------------------------------
-;;; internal variables
-
-(defvar hs-minor-mode nil
- "Non-nil if using hideshow mode as a minor mode of some other mode.
-Use the command `hs-minor-mode' to toggle this variable.")
-
-(defvar hs-minor-mode-map nil
- "Mode map for hideshow minor mode.")
-
-(defvar hs-menu-bar nil
- "Menu bar for hideshow minor mode (Xemacs only).")
-
-(defvar hs-c-start-regexp nil
- "Regexp for beginning of comments. Buffer-local.
-Differs from mode-specific comment regexps in that surrounding
-whitespace is stripped.")
-
-(defvar hs-c-end-regexp nil
- "Regexp for end of comments. Buffer-local.
-See `hs-c-start-regexp'.")
-
-(defvar hs-block-start-regexp nil
- "Regexp for beginning of block. Buffer-local.")
-
-(defvar hs-block-end-regexp nil
- "Regexp for end of block. Buffer-local.")
-
-(defvar hs-forward-sexp-func 'forward-sexp
- "Function used to do a forward-sexp. Should change for Algol-ish modes.
-For single-character block delimiters -- ie, the syntax table regexp for the
-character is either `(' or `)' -- `hs-forward-sexp-func' would just be
-`forward-sexp'. For other modes such as simula, a more specialized function
-is necessary.")
-
-(defvar hs-emacs-type 'fsf
- "Used to support both Emacs and XEmacs.")
-
-(eval-when-compile
- (if (string-match "xemacs\\|lucid" emacs-version)
- (progn
- (defvar current-menubar nil "")
- (defun set-buffer-menubar (arg1))
- (defun add-menu (arg1 arg2 arg3)))))
-
-
-;;;----------------------------------------------------------------------------
-;;; support funcs
-
-;; snarfed from outline.el, but added buffer-read-only
-(defun hs-flag-region (from to flag)
- "Hides or shows lines from FROM to TO, according to FLAG.
-If FLAG is `?\\n' (the newline character) then show the text;
-if FLAG is `?\\^M' \(control-M) then hide the text."
- (let ((modp (buffer-modified-p))
- buffer-read-only) ; nothing is immune
- (unwind-protect (progn
- (subst-char-in-region
- from to
- (if (= flag ?\n) ?\C-m ?\n)
- flag t))
- (set-buffer-modified-p modp))))
-
-(defun hs-hide-block-at-point (&optional end)
- "Hide block iff on block beginning, optional END means reposition at end."
- (if (looking-at hs-block-start-regexp)
- (let* ((p (point))
- (q (progn (funcall hs-forward-sexp-func 1) (point))))
- (forward-line -1) (end-of-line)
- (if (and (< p (point)) (> (count-lines p q) 1))
- (hs-flag-region p (point) ?\C-m))
- (goto-char (if end q p)))))
-
-(defun hs-show-block-at-point (&optional end)
- "Show block iff on block beginning. Optional END means reposition at end."
- (if (looking-at hs-block-start-regexp)
- (let* ((p (point))
- (q
- (condition-case error ; probably unbalanced paren
- (progn
- (funcall hs-forward-sexp-func 1)
- (point))
- (error
- (cond
- ((eq hs-unbalance-handler-method 'ignore)
- ;; just ignore this block
- (point))
- ((eq hs-unbalance-handler-method 'top-level)
- ;; try to get out of rat's nest and expose the whole func
- (if (/= (current-column) 0) (beginning-of-defun))
- (setq p (point))
- (re-search-forward (concat "^" hs-block-start-regexp)
- (point-max) t 2)
- (point))
- ((eq hs-unbalance-handler-method 'next-line)
- ;; assumption is that user knows what s/he's doing
- (beginning-of-line) (setq p (point))
- (end-of-line 2) (point))
- (t
- ;; pass error through -- this applies to `signal', too
- (signal (car error) (cdr error))))))))
- (hs-flag-region p q ?\n)
- (goto-char (if end (1+ (point)) p)))))
-
-(defun hs-safety-is-job-n ()
- "Warn if `selective-display' or `selective-display-ellipses' is nil."
- (let ((str ""))
- (or selective-display
- (setq str "selective-display nil "))
- (or selective-display-ellipses
- (setq str (concat str "selective-display-ellipses nil")))
- (if (= (length str) 0)
- nil
- (message "warning: %s" str)
- (sit-for 2))))
-
-(defun hs-inside-comment-p ()
- "Returns non-nil if point is inside a comment, otherwise nil.
-Actually, for multi-line-able comments, returns a list containing
-the buffer position of the start and the end of the comment."
- ;; is it single-line-only or multi-line-able?
- (save-excursion
- (let ((p (point))
- q)
- (if (string= comment-end "") ; single line
- (let (found)
- (beginning-of-line)
- (setq found (re-search-forward hs-c-start-regexp p t))
- (and found (not (search-forward "\"" p t))))
- (re-search-forward hs-c-end-regexp (point-max) 1)
- (setq q (point))
- (forward-comment -1)
- (re-search-forward hs-c-start-regexp (point-max) 1)
- (if (< (- (point) (length comment-start)) p)
- (list (match-beginning 0) q))))))
-
-(defun hs-grok-mode-type ()
- "Setup variables for new buffers where applicable."
- (if (and (boundp 'comment-start)
- (boundp 'comment-end))
- (progn
- (setq hs-c-start-regexp (regexp-quote comment-start))
- (if (string-match " +$" hs-c-start-regexp)
- (setq hs-c-start-regexp
- (substring hs-c-start-regexp 0 (1- (match-end 0)))))
- (setq hs-c-end-regexp (if (string= "" comment-end) "\n"
- (regexp-quote comment-end)))
- (if (string-match "^ +" hs-c-end-regexp)
- (setq hs-c-end-regexp
- (substring hs-c-end-regexp (match-end 0))))
- (let ((lookup (assoc major-mode hs-special-modes-alist)))
- (setq hs-block-start-regexp (or (nth 1 lookup) "\\s\(")
- hs-block-end-regexp (or (nth 2 lookup) "\\s\)")
- hs-forward-sexp-func (or (nth 3 lookup) 'forward-sexp))))))
-
-(defun hs-find-block-beginning ()
- "Repositions point at block-start. Return point, or nil if top-level."
- (let (done
- (here (point))
- (both-regexps (concat "\\(" hs-block-start-regexp "\\)\\|\\("
- hs-block-end-regexp "\\)")))
- (while (and (not done)
- (re-search-backward both-regexps (point-min) t))
- (if (match-beginning 1) ; start of start-regexp
- (setq done (match-beginning 1))
- (goto-char (match-end 2)) ; end of end-regexp
- (funcall hs-forward-sexp-func -1)))
- (goto-char (or done here))
- done))
-
-(defmacro hs-life-goes-on (&rest body)
- "Executes optional BODY iff variable `hs-minor-mode' is non-nil."
- (list 'if 'hs-minor-mode (cons 'progn body)))
-
-
-;;;----------------------------------------------------------------------------
-;;; commands
-
-;;;###autoload
-(defun hs-hide-all ()
- "Hides all top-level blocks, displaying only first and last lines.
-It moves point to the beginning of the line, and it runs the normal hook
-`hs-hide-hook'. See documentation for `run-hooks'."
- (interactive)
- (hs-life-goes-on
- (message "hiding all blocks ...")
- (save-excursion
- (hs-flag-region (point-min) (point-max) ?\n) ; eliminate weirdness
- (goto-char (point-min))
- (let ((count 0)
- (top-level-re (concat "^" hs-block-start-regexp)))
- (while (progn
- (forward-comment (buffer-size))
- (re-search-forward top-level-re (point-max) t))
- (goto-char (match-beginning 0))
- (hs-hide-block-at-point t)
- (message "hiding ... %d" (setq count (1+ count)))))
- (hs-safety-is-job-n))
- (beginning-of-line)
- (message "hiding all blocks ... done")
- (run-hooks 'hs-hide-hook)))
-
-(defun hs-show-all ()
- "Shows all top-level blocks.
-This does not change point; it runs the normal hook `hs-show-hook'.
-See documentation for `run-hooks'."
- (interactive)
- (hs-life-goes-on
- (message "showing all blocks ...")
- (hs-flag-region (point-min) (point-max) ?\n)
- (message "showing all blocks ... done")
- (run-hooks 'hs-show-hook)))
-
-;;;###autoload
-(defun hs-hide-block (&optional end)
- "Selects a block and hides it. With prefix arg, reposition at end.
-Block is defined as a sexp for lispish modes, mode-specific otherwise.
-Comments are blocks, too. Upon completion, point is at repositioned and
-the normal hook `hs-hide-hook' is run. See documentation for `run-hooks'."
- (interactive "P")
- (hs-life-goes-on
- (let ((c-reg (hs-inside-comment-p)))
- (if c-reg
- (cond ((string= comment-end "")
- (message "can't hide a single-line comment"))
- ((< (count-lines (car c-reg) (nth 1 c-reg)) 2)
- (message "not enough comment lines to hide"))
- (t
- (goto-char (nth 1 c-reg))
- (forward-line -1)
- (hs-flag-region (car c-reg) (point) ?\C-m)
- (goto-char (if end (nth 1 c-reg) (car c-reg)))
- (hs-safety-is-job-n)
- (run-hooks 'hs-hide-hook)))
- (if (or (looking-at hs-block-start-regexp)
- (hs-find-block-beginning))
- (progn
- (hs-hide-block-at-point end)
- (hs-safety-is-job-n)
- (run-hooks 'hs-hide-hook)))))))
-
-(defun hs-show-block (&optional end)
- "Selects a block and shows it. With prefix arg, reposition at end.
-Upon completion, point is repositioned and the normal hook
-`hs-show-hook' is run. See documentation for `hs-hide-block' and `run-hooks'."
- (interactive "P")
- (hs-life-goes-on
- (let ((c-reg (hs-inside-comment-p)))
- (if c-reg
- (cond ((string= comment-end "")
- (message "already looking at the entire comment"))
- (t
- (hs-flag-region (car c-reg) (nth 1 c-reg) ?\n)
- (goto-char (if end (nth 1 c-reg) (car c-reg)))))
- (if (or (looking-at hs-block-start-regexp)
- (hs-find-block-beginning))
- (progn
- (hs-show-block-at-point end)
- (hs-safety-is-job-n)
- (run-hooks 'hs-show-hook)))))))
-
-(defun hs-show-region (beg end)
- "Shows all lines from BEG to END, without doing any block analysis.
-Note:` hs-show-region' is intended for use when when `hs-show-block' signals
-`unbalanced parentheses' and so is an emergency measure only. You may
-become very confused if you use this command indiscriminately."
- (interactive "r")
- (hs-life-goes-on
- (hs-flag-region beg end ?\n)
- (hs-safety-is-job-n)
- (run-hooks 'hs-show-hook)))
-
-;;;###autoload
-(defun hs-minor-mode (&optional arg)
- "Toggle hideshow minor mode.
-With ARG, turn hideshow minor mode on if ARG is positive, off otherwise.
-When hideshow minor mode is on, the menu bar is augmented with hideshow
-commands and the hideshow commands are enabled. The variables
-`selective-display' and `selective-display-ellipses' are set to t.
-Last, the normal hook `hs-minor-mode-hook' is run; see the doc for `run-hooks'.
-
-Turning hideshow minor mode off reverts the menu bar and the
-variables to default values and disables the hideshow commands."
- (interactive "P")
- (setq hs-minor-mode
- (if (null arg)
- (not hs-minor-mode)
- (> (prefix-numeric-value arg) 0)))
- (if hs-minor-mode
- (progn
- (if (eq hs-emacs-type 'lucid)
- (progn
- (set-buffer-menubar (copy-sequence current-menubar))
- (add-menu nil (car hs-menu-bar) (cdr hs-menu-bar))))
- (setq selective-display t
- selective-display-ellipses t)
- (hs-grok-mode-type)
- (run-hooks 'hs-minor-mode-hook))
- (if (eq hs-emacs-type 'lucid)
- (set-buffer-menubar (delete hs-menu-bar current-menubar)))
- (kill-local-variable 'selective-display)
- (kill-local-variable 'selective-display-ellipses)))
-
-
-;;;----------------------------------------------------------------------------
-;;; load-time setup routines
-
-;; which emacs being used?
-(setq hs-emacs-type
- (if (string-match "xemacs\\|lucid" emacs-version)
- 'lucid
- 'fsf))
-
-;; keymaps and menus
-(if (not hs-minor-mode-map)
- (setq hs-minor-mode-map (make-sparse-keymap))
- (cond
- ((eq hs-emacs-type 'lucid)
- (setq hs-menu-bar ; build top down for lucid
- '("hideshow"
- ["Hide Block" hs-hide-block t]
- ["Show Block" hs-show-block t]
- ["Hide All" hs-hide-all t]
- ["Show All" hs-show-all t]
- ["Show Region" hs-show-region t])))
- (t ; build bottom up for others
- (define-key hs-minor-mode-map [menu-bar hideshow]
- (cons "hideshow" (make-sparse-keymap "hideshow")))
- (define-key hs-minor-mode-map [menu-bar hideshow hs-show-region]
- '("Show Region" . hs-show-region))
- (define-key hs-minor-mode-map [menu-bar hideshow hs-show-all]
- '("Show All" . hs-show-all))
- (define-key hs-minor-mode-map [menu-bar hideshow hs-hide-all]
- '("Hide All" . hs-hide-all))
- (define-key hs-minor-mode-map [menu-bar hideshow hs-show-block]
- '("Show Block" . hs-show-block))
- (define-key hs-minor-mode-map [menu-bar hideshow hs-hide-block]
- '("Hide Block" . hs-hide-block)))))
-
-;; some housekeeping
-(or (assq 'hs-minor-mode minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons (cons 'hs-minor-mode hs-minor-mode-map)
- minor-mode-map-alist)))
-(or (assq 'hs-minor-mode minor-mode-alist)
- (setq minor-mode-alist (append minor-mode-alist
- (list '(hs-minor-mode " hs")))))
-
-;; make some variables buffer-local
-(make-variable-buffer-local 'hs-minor-mode)
-(make-variable-buffer-local 'hs-c-start-regexp)
-(make-variable-buffer-local 'hs-c-end-regexp)
-(make-variable-buffer-local 'hs-block-start-regexp)
-(make-variable-buffer-local 'hs-block-end-regexp)
-(make-variable-buffer-local 'hs-forward-sexp-func)
-(put 'hs-minor-mode 'permanent-local t)
-(put 'hs-c-start-regexp 'permanent-local t)
-(put 'hs-c-end-regexp 'permanent-local t)
-(put 'hs-block-start-regexp 'permanent-local t)
-(put 'hs-block-end-regexp 'permanent-local t)
-(put 'hs-forward-sexp-func 'permanent-local t)
-
-
-;;;----------------------------------------------------------------------------
-;;; that's it
-
-(provide 'hideshow)
-
-;;; hideshow.el ends here
diff --git a/lisp/progmodes/icon.el b/lisp/progmodes/icon.el
deleted file mode 100644
index 85e30a77ade..00000000000
--- a/lisp/progmodes/icon.el
+++ /dev/null
@@ -1,556 +0,0 @@
-;;; icon.el --- mode for editing Icon code
-
-;; Copyright (C) 1989 Free Software Foundation, Inc.
-
-;; Author: Chris Smith <csmith@convex.com>
-;; Created: 15 Feb 89
-;; Keywords: languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; A major mode for editing the Icon programming language.
-
-;;; Code:
-
-(defvar icon-mode-abbrev-table nil
- "Abbrev table in use in Icon-mode buffers.")
-(define-abbrev-table 'icon-mode-abbrev-table ())
-
-(defvar icon-mode-map ()
- "Keymap used in Icon mode.")
-(if icon-mode-map
- ()
- (setq icon-mode-map (make-sparse-keymap))
- (define-key icon-mode-map "{" 'electric-icon-brace)
- (define-key icon-mode-map "}" 'electric-icon-brace)
- (define-key icon-mode-map "\e\C-h" 'mark-icon-function)
- (define-key icon-mode-map "\e\C-a" 'beginning-of-icon-defun)
- (define-key icon-mode-map "\e\C-e" 'end-of-icon-defun)
- (define-key icon-mode-map "\e\C-q" 'indent-icon-exp)
- (define-key icon-mode-map "\177" 'backward-delete-char-untabify)
- (define-key icon-mode-map "\t" 'icon-indent-command))
-
-(defvar icon-mode-syntax-table nil
- "Syntax table in use in Icon-mode buffers.")
-
-(if icon-mode-syntax-table
- ()
- (setq icon-mode-syntax-table (make-syntax-table))
- (modify-syntax-entry ?\\ "\\" icon-mode-syntax-table)
- (modify-syntax-entry ?# "<" icon-mode-syntax-table)
- (modify-syntax-entry ?\n ">" icon-mode-syntax-table)
- (modify-syntax-entry ?$ "." icon-mode-syntax-table)
- (modify-syntax-entry ?/ "." icon-mode-syntax-table)
- (modify-syntax-entry ?* "." icon-mode-syntax-table)
- (modify-syntax-entry ?+ "." icon-mode-syntax-table)
- (modify-syntax-entry ?- "." icon-mode-syntax-table)
- (modify-syntax-entry ?= "." icon-mode-syntax-table)
- (modify-syntax-entry ?% "." icon-mode-syntax-table)
- (modify-syntax-entry ?< "." icon-mode-syntax-table)
- (modify-syntax-entry ?> "." icon-mode-syntax-table)
- (modify-syntax-entry ?& "." icon-mode-syntax-table)
- (modify-syntax-entry ?| "." icon-mode-syntax-table)
- (modify-syntax-entry ?\' "\"" icon-mode-syntax-table))
-
-(defvar icon-indent-level 4
- "*Indentation of Icon statements with respect to containing block.")
-(defvar icon-brace-imaginary-offset 0
- "*Imagined indentation of a Icon open brace that actually follows a statement.")
-(defvar icon-brace-offset 0
- "*Extra indentation for braces, compared with other text in same context.")
-(defvar icon-continued-statement-offset 4
- "*Extra indent for lines not starting new statements.")
-(defvar icon-continued-brace-offset 0
- "*Extra indent for substatements that start with open-braces.
-This is in addition to icon-continued-statement-offset.")
-
-(defvar icon-auto-newline nil
- "*Non-nil means automatically newline before and after braces
-inserted in Icon code.")
-
-(defvar icon-tab-always-indent t
- "*Non-nil means TAB in Icon mode should always reindent the current line,
-regardless of where in the line point is when the TAB command is used.")
-
-;;;###autoload
-(defun icon-mode ()
- "Major mode for editing Icon code.
-Expression and list commands understand all Icon brackets.
-Tab indents for Icon code.
-Paragraphs are separated by blank lines only.
-Delete converts tabs to spaces as it moves back.
-\\{icon-mode-map}
-Variables controlling indentation style:
- icon-tab-always-indent
- Non-nil means TAB in Icon mode should always reindent the current line,
- regardless of where in the line point is when the TAB command is used.
- icon-auto-newline
- Non-nil means automatically newline before and after braces
- inserted in Icon code.
- icon-indent-level
- Indentation of Icon statements within surrounding block.
- The surrounding block's indentation is the indentation
- of the line on which the open-brace appears.
- icon-continued-statement-offset
- Extra indentation given to a substatement, such as the
- 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'.
- 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."
- (interactive)
- (kill-all-local-variables)
- (use-local-map icon-mode-map)
- (setq major-mode 'icon-mode)
- (setq mode-name "Icon")
- (setq local-abbrev-table icon-mode-abbrev-table)
- (set-syntax-table icon-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 'indent-line-function)
- (setq indent-line-function 'icon-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-function)
- (setq comment-indent-function '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.
-(defun icon-comment-indent ()
- (if (looking-at "^#")
- 0
- (save-excursion
- (skip-chars-backward " \t")
- (max (if (bolp) 0 (1+ (current-column)))
- comment-column))))
-
-(defun electric-icon-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 icon-auto-newline
- (progn (icon-indent-line) (newline) t)
- nil)))
- (progn
- (insert last-command-char)
- (icon-indent-line)
- (if icon-auto-newline
- (progn
- (newline)
- ;; (newline) may have done auto-fill
- (setq insertpos (- (point) 2))
- (icon-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 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
-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."
- (if whole-exp
- ;; If arg, always indent this line as Icon
- ;; and shift remaining lines of expression the same amount.
- (let ((shift-amt (icon-indent-line))
- beg end)
- (save-excursion
- (if icon-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 icon-tab-always-indent)
- (save-excursion
- (skip-chars-backward " \t")
- (not (bolp))))
- (insert-tab)
- (icon-indent-line))))
-
-(defun icon-indent-line ()
- "Indent current line as Icon code.
-Return the amount the indentation changed by."
- (let ((indent (calculate-icon-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-icon-indent-within-comment)))
- ((looking-at "[ \t]*#")
- (setq indent 0))
- (t
- (skip-chars-forward " \t")
- (if (listp indent) (setq indent (car indent)))
- (cond ((and (looking-at "else\\b")
- (not (looking-at "else\\s_")))
- (setq indent (save-excursion
- (icon-backward-to-start-of-if)
- (current-indentation))))
- ((or (= (following-char) ?})
- (looking-at "end\\b"))
- (setq indent (- indent icon-indent-level)))
- ((= (following-char) ?{)
- (setq indent (+ indent icon-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-icon-indent (&optional parse-start)
- "Return appropriate indentation for current line as Icon 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
- toplevel)
- (if parse-start
- (goto-char parse-start)
- (setq toplevel (beginning-of-icon-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))
- ((and containing-sexp
- (/= (char-after containing-sexp) ?{))
- ;; line is expression, not statement:
- ;; indent to just after the surrounding open.
- (goto-char (1+ containing-sexp))
- (current-column))
- (t
- (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)
- ;; This line is continuation of preceding line's statement;
- ;; indent icon-continued-statement-offset more than the
- ;; first line of the statement.
- (progn
- (icon-backward-to-start-of-continued-exp containing-sexp)
- (+ icon-continued-statement-offset (current-column)
- (if (save-excursion (goto-char indent-point)
- (skip-chars-forward " \t")
- (eq (following-char) ?{))
- icon-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
- (if (looking-at "procedure\\s ")
- (forward-sexp 3)
- (forward-char 1))
- (while (progn (skip-chars-forward " \t\n")
- (looking-at "#"))
- ;; Skip over comments following openbrace.
- (forward-line 1))
- ;; The first following code counts
- ;; if it is before the line we want to indent.
- (and (< (point) indent-point)
- (current-column)))
- ;; 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 icon-indent-level is zero,
- ;; 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-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.
- (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)
- (not (memq ch '(0 ?\; ?\} ?\{ ?\) ?\] ?\" ?\' ?\n))))))
-
-(defun icon-backward-to-noncomment (lim)
- (let (opoint stop)
- (while (not stop)
- (skip-chars-backward " \t\n\f" lim)
- (setq opoint (point))
- (beginning-of-line)
- (if (and (nth 5 (parse-partial-sexp (point) opoint))
- (< lim (point)))
- (search-backward "#")
- (setq stop t)))))
-
-(defun icon-backward-to-start-of-continued-exp (lim)
- (if (memq (preceding-char) '(?\) ?\]))
- (forward-sexp -1))
- (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))))
-
-(defun icon-is-continued-line ()
- (save-excursion
- (end-of-line 0)
- (icon-is-continuation-line)))
-
-(defun icon-backward-to-start-of-if (&optional limit)
- "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))
- (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-icon-function ()
- "Put mark at end of Icon function, point at beginning."
- (interactive)
- (push-mark (point))
- (end-of-icon-defun)
- (push-mark (point))
- (beginning-of-line 0)
- (beginning-of-icon-defun))
-
-(defun beginning-of-icon-defun ()
- "Go to the start of the enclosing procedure; return t if at top level."
- (interactive)
- (if (re-search-backward "^procedure\\s \\|^end[ \t\n]" (point-min) 'move)
- (looking-at "e")
- t))
-
-(defun end-of-icon-defun ()
- (interactive)
- (if (not (bobp)) (forward-char -1))
- (re-search-forward "\\(\\s \\|^\\)end\\(\\s \\|$\\)" (point-max) 'move)
- (forward-word -1)
- (forward-line 1))
-
-(defun indent-icon-exp ()
- "Indent each line of the Icon 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 at-do
- (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 innerloop-done nil)
- (while (and (not innerloop-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))
- (icon-indent-line))
- (if (or (nth 3 state))
- (forward-line 1)
- (setq innerloop-done t)))
- (if (<= next-depth 0)
- (setq outer-loop-done t))
- (if outer-loop-done
- nil
- (if (/= last-depth next-depth)
- (setq last-sexp nil))
- (while (> last-depth next-depth)
- (setq indent-stack (cdr indent-stack)
- contain-stack (cdr contain-stack)
- last-depth (1- last-depth)))
- (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) ?{))
- (icon-backward-to-noncomment opoint)
- (if (icon-is-continuation-line)
- ;; Preceding line did not end in comma or semi;
- ;; indent this line icon-continued-statement-offset
- ;; more than previous.
- (progn
- (icon-backward-to-start-of-continued-exp (car contain-stack))
- (setq this-indent
- (+ icon-continued-statement-offset (current-column)
- (if at-brace icon-continued-brace-offset 0))))
- ;; Preceding line ended in comma or semi;
- ;; use the standard indent for this level.
- (if at-else
- (progn (icon-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-icon-indent
- (if (car indent-stack)
- (- (car indent-stack))))))
- (setcar indent-stack
- (setq this-indent val))))
- ;; Adjust line indentation according to its contents
- (if (or (= (following-char) ?})
- (looking-at "end\\b"))
- (setq this-indent (- this-indent icon-indent-level)))
- (if (= (following-char) ?{)
- (setq this-indent (+ this-indent icon-brace-offset)))
- ;; Put chosen indentation into effect.
- (or (= (current-column) this-indent)
- (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))))))))))
-
-;;; icon.el ends here
diff --git a/lisp/progmodes/inf-lisp.el b/lisp/progmodes/inf-lisp.el
deleted file mode 100644
index 870d3f944b7..00000000000
--- a/lisp/progmodes/inf-lisp.el
+++ /dev/null
@@ -1,642 +0,0 @@
-;;; inf-lisp.el --- an inferior-lisp mode
-
-;; Copyright (C) 1988, 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Olin Shivers <shivers@cs.cmu.edu>
-;; Keywords: processes, lisp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Hacked from tea.el by Olin Shivers (shivers@cs.cmu.edu). 8/88
-
-;; This file defines a a lisp-in-a-buffer package (inferior-lisp
-;; mode) built on top of comint mode. This version is more
-;; featureful, robust, and uniform than the Emacs 18 version. The
-;; key bindings are also more compatible with the bindings of Hemlock
-;; and Zwei (the Lisp Machine emacs).
-
-;; 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.
-;; This makes these modes easier to use.
-
-;; For documentation on the functionality provided by comint mode, and
-;; the hooks available for customising it, see the file comint.el.
-;; For further information on inferior-lisp mode, see the comments below.
-
-;; Needs fixin:
-;; 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, ...).
-;;
-;; It would be nice if inferior-lisp (and inferior scheme, T, ...) modes
-;; had a verbose minor mode wherein sending or compiling defuns, etc.
-;; would be reflected in the transcript with suitable comments, e.g.
-;; ";;; redefining fact". Several ways to do this. Which is right?
-;;
-;; 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?
-
-;;; Code:
-
-(require 'comint)
-(require 'lisp-mode)
-
-
-;;;###autoload
-(defvar inferior-lisp-filter-regexp "\\`\\s *\\(:\\(\\w\\|\\s_\\)\\)?\\s *\\'"
- "*What not to save on inferior Lisp's input history.
-Input matching this regexp is not saved on the input history in Inferior Lisp
-mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword
-\(as in :a, :c, etc.)")
-
-(defvar inferior-lisp-mode-map nil)
-(cond ((not inferior-lisp-mode-map)
- (setq inferior-lisp-mode-map
- (copy-keymap comint-mode-map))
- (setq inferior-lisp-mode-map
- (nconc inferior-lisp-mode-map shared-lisp-mode-map))
- (define-key inferior-lisp-mode-map "\C-x\C-e" 'lisp-eval-last-sexp)
- (define-key inferior-lisp-mode-map "\C-c\C-l" 'lisp-load-file)
- (define-key inferior-lisp-mode-map "\C-c\C-k" 'lisp-compile-file)
- (define-key inferior-lisp-mode-map "\C-c\C-a" 'lisp-show-arglist)
- (define-key inferior-lisp-mode-map "\C-c\C-d" 'lisp-describe-sym)
- (define-key inferior-lisp-mode-map "\C-c\C-f"
- 'lisp-show-function-documentation)
- (define-key inferior-lisp-mode-map "\C-c\C-v"
- 'lisp-show-variable-documentation)))
-
-;;; These commands augment Lisp mode, so you can process Lisp code in
-;;; the source files.
-(define-key lisp-mode-map "\M-\C-x" 'lisp-eval-defun) ; Gnu convention
-(define-key lisp-mode-map "\C-x\C-e" 'lisp-eval-last-sexp) ; Gnu convention
-(define-key lisp-mode-map "\C-c\C-e" 'lisp-eval-defun)
-(define-key lisp-mode-map "\C-c\C-r" 'lisp-eval-region)
-(define-key lisp-mode-map "\C-c\C-c" 'lisp-compile-defun)
-(define-key lisp-mode-map "\C-c\C-z" 'switch-to-lisp)
-(define-key lisp-mode-map "\C-c\C-l" 'lisp-load-file)
-(define-key lisp-mode-map "\C-c\C-k" 'lisp-compile-file) ; "kompile" file
-(define-key lisp-mode-map "\C-c\C-a" 'lisp-show-arglist)
-(define-key lisp-mode-map "\C-c\C-d" 'lisp-describe-sym)
-(define-key lisp-mode-map "\C-c\C-f" 'lisp-show-function-documentation)
-(define-key lisp-mode-map "\C-c\C-v" 'lisp-show-variable-documentation)
-
-
-;;; This function exists for backwards compatibility.
-;;; Previous versions of this package bound commands to C-c <letter>
-;;; bindings, which is not allowed by the gnumacs standard.
-
-;;; "This function binds many inferior-lisp commands to C-c <letter> bindings,
-;;;where they are more accessible. C-c <letter> bindings are reserved for the
-;;;user, so these bindings are non-standard. If you want them, you should
-;;;have this function called by the inferior-lisp-load-hook:
-;;; (setq inferior-lisp-load-hook '(inferior-lisp-install-letter-bindings))
-;;;You can modify this function to install just the bindings you want."
-(defun inferior-lisp-install-letter-bindings ()
- (define-key lisp-mode-map "\C-ce" 'lisp-eval-defun-and-go)
- (define-key lisp-mode-map "\C-cr" 'lisp-eval-region-and-go)
- (define-key lisp-mode-map "\C-cc" 'lisp-compile-defun-and-go)
- (define-key lisp-mode-map "\C-cz" 'switch-to-lisp)
- (define-key lisp-mode-map "\C-cl" 'lisp-load-file)
- (define-key lisp-mode-map "\C-ck" 'lisp-compile-file)
- (define-key lisp-mode-map "\C-ca" 'lisp-show-arglist)
- (define-key lisp-mode-map "\C-cd" 'lisp-describe-sym)
- (define-key lisp-mode-map "\C-cf" 'lisp-show-function-documentation)
- (define-key lisp-mode-map "\C-cv" 'lisp-show-variable-documentation)
-
- (define-key inferior-lisp-mode-map "\C-cl" 'lisp-load-file)
- (define-key inferior-lisp-mode-map "\C-ck" 'lisp-compile-file)
- (define-key inferior-lisp-mode-map "\C-ca" 'lisp-show-arglist)
- (define-key inferior-lisp-mode-map "\C-cd" 'lisp-describe-sym)
- (define-key inferior-lisp-mode-map "\C-cf" 'lisp-show-function-documentation)
- (define-key inferior-lisp-mode-map "\C-cv"
- 'lisp-show-variable-documentation))
-
-
-;;;###autoload
-(defvar inferior-lisp-program "lisp"
- "*Program name for invoking an inferior Lisp with for Inferior Lisp mode.")
-
-;;;###autoload
-(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.")
-
-;;;###autoload
-(defvar inferior-lisp-prompt "^[^> \n]*>+:? *"
- "Regexp to recognise prompts in the Inferior Lisp mode.
-Defaults to \"^[^> \\n]*>+:? *\", which works pretty good for Lucid, kcl,
-and franz. This variable is used to initialize `comint-prompt-regexp' in the
-Inferior Lisp buffer.
-
-More precise choices:
-Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\"
-franz: \"^\\\\(->\\\\|<[0-9]*>:\\\\) *\"
-kcl: \"^>+ *\"
-
-This is a fine thing to set in your .emacs file.")
-
-(defvar inferior-lisp-buffer nil "*The current inferior-lisp process buffer.
-
-MULTIPLE PROCESS SUPPORT
-===========================================================================
-To run multiple Lisp processes, you start the first up
-with \\[inferior-lisp]. It will be in a buffer named `*inferior-lisp*'.
-Rename this buffer with \\[rename-buffer]. You may now start up a new
-process with another \\[inferior-lisp]. It will be in a new buffer,
-named `*inferior-lisp*'. You can switch between the different process
-buffers with \\[switch-to-buffer].
-
-Commands that send text from source buffers to Lisp processes --
-like `lisp-eval-defun' or `lisp-show-arglist' -- have to choose a process
-to send to, when you have more than one Lisp process around. This
-is determined by the global variable `inferior-lisp-buffer'. Suppose you
-have three inferior Lisps running:
- Buffer Process
- foo inferior-lisp
- bar inferior-lisp<2>
- *inferior-lisp* inferior-lisp<3>
-If you do a \\[lisp-eval-defun] command on some Lisp source code,
-what process do you send it to?
-
-- If you're in a process buffer (foo, bar, or *inferior-lisp*),
- you send it to that process.
-- If you're in some other buffer (e.g., a source file), you
- send it to the process attached to buffer `inferior-lisp-buffer'.
-This process selection is performed by function `inferior-lisp-proc'.
-
-Whenever \\[inferior-lisp] fires up a new process, it resets
-`inferior-lisp-buffer' to be the new process's buffer. If you only run
-one process, this does the right thing. If you run multiple
-processes, you can change `inferior-lisp-buffer' to another process
-buffer with \\[set-variable].")
-
-;;;###autoload
-(defvar inferior-lisp-mode-hook '()
- "*Hook for customising Inferior Lisp mode.")
-
-(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', `inferior-lisp-filter-regexp' and
-`inferior-lisp-load-command' can customize this mode for different Lisp
-interpreters.
-
-For information on running multiple processes in multiple buffers, see
-documentation for variable `inferior-lisp-buffer'.
-
-\\{inferior-lisp-mode-map}
-
-Customisation: Entry to this mode runs the hooks on `comint-mode-hook' and
-`inferior-lisp-mode-hook' (in that order).
-
-You can send text to the inferior Lisp process from other buffers containing
-Lisp source.
- switch-to-lisp switches the current buffer to the Lisp process buffer.
- lisp-eval-defun sends the current defun to the Lisp process.
- lisp-compile-defun compiles the current defun.
- lisp-eval-region sends the current region to the Lisp process.
- lisp-compile-region compiles the current region.
-
- Prefixing the lisp-eval/compile-defun/region commands with
- a \\[universal-argument] causes a switch to the Lisp process buffer after sending
- the text.
-
-Commands:
-Return after the end of the process' output sends the text from the
- end of process to point.
-Return before the end of the process' output copies the sexp ending at point
- to the end of the process' output, and sends it.
-Delete converts tabs to spaces as it moves back.
-Tab indents for Lisp; with argument, shifts rest
- of expression rigidly with the current line.
-C-M-q does Tab on each line starting within following expression.
-Paragraphs are separated only by blank lines. Semicolons start comments.
-If you accidentally suspend your process, use \\[comint-continue-subjob]
-to continue it."
- (interactive)
- (comint-mode)
- (setq comint-prompt-regexp inferior-lisp-prompt)
- (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) ;c-c c-k for "kompile" file
- (setq comint-get-old-input (function lisp-get-old-input))
- (setq comint-input-filter (function lisp-input-filter))
- (setq comint-input-sentinel 'ignore)
- (run-hooks 'inferior-lisp-mode-hook))
-
-(defun lisp-get-old-input ()
- "Return a string containing the sexp ending at point."
- (save-excursion
- (let ((end (point)))
- (backward-sexp)
- (buffer-substring (point) end))))
-
-(defun lisp-input-filter (str)
- "t if STR does not match `inferior-lisp-filter-regexp'."
- (not (string-match inferior-lisp-filter-regexp str)))
-
-;;;###autoload
-(defun inferior-lisp (cmd)
- "Run an inferior Lisp process, input and output via buffer `*inferior-lisp*'.
-If there is a process already running in `*inferior-lisp*', just switch
-to that buffer.
-With argument, allows you to edit the command line (default is value
-of `inferior-lisp-program'). Runs the hooks from
-`inferior-lisp-mode-hook' (after the `comint-mode-hook' is run).
-\(Type \\[describe-mode] in the process buffer for a list of commands.)"
- (interactive (list (if current-prefix-arg
- (read-string "Run lisp: " inferior-lisp-program)
- inferior-lisp-program)))
- (if (not (comint-check-proc "*inferior-lisp*"))
- (let ((cmdlist (inferior-lisp-args-to-list cmd)))
- (set-buffer (apply (function make-comint)
- "inferior-lisp" (car cmdlist) nil (cdr cmdlist)))
- (inferior-lisp-mode)))
- (setq inferior-lisp-buffer "*inferior-lisp*")
- (pop-to-buffer "*inferior-lisp*"))
-;;;###autoload (add-hook 'same-window-buffer-names "*inferior-lisp*")
-
-;;;###autoload
-(defalias 'run-lisp 'inferior-lisp)
-
-;;; Break a string up into a list of arguments.
-;;; This will break if you have an argument with whitespace, as in
-;;; string = "-ab +c -x 'you lose'".
-(defun inferior-lisp-args-to-list (string)
- (let ((where (string-match "[ \t]" string)))
- (cond ((null where) (list string))
- ((not (= where 0))
- (cons (substring string 0 where)
- (inferior-lisp-args-to-list (substring string (+ 1 where)
- (length string)))))
- (t (let ((pos (string-match "[^ \t]" string)))
- (if (null pos)
- nil
- (inferior-lisp-args-to-list (substring string pos
- (length string)))))))))
-
-(defun lisp-eval-region (start end &optional and-go)
- "Send the current region to the inferior Lisp process.
-Prefix argument means switch to the Lisp buffer afterwards."
- (interactive "r\nP")
- (comint-send-region (inferior-lisp-proc) start end)
- (comint-send-string (inferior-lisp-proc) "\n")
- (if and-go (switch-to-lisp t)))
-
-(defun lisp-eval-defun (&optional and-go)
- "Send the current defun to the inferior Lisp process.
-Prefix argument means switch to the Lisp buffer afterwards."
- (interactive "P")
- (save-excursion
- (end-of-defun)
- (skip-chars-backward " \t\n\r\f") ; Makes allegro happy
- (let ((end (point)))
- (beginning-of-defun)
- (lisp-eval-region (point) end)))
- (if and-go (switch-to-lisp t)))
-
-(defun lisp-eval-last-sexp (&optional and-go)
- "Send the previous sexp to the inferior Lisp process.
-Prefix argument means switch to the Lisp buffer afterwards."
- (interactive "P")
- (lisp-eval-region (save-excursion (backward-sexp) (point)) (point) and-go))
-
-;;; Common Lisp COMPILE sux.
-(defun lisp-compile-region (start end &optional and-go)
- "Compile the current region in the inferior Lisp process.
-Prefix argument means switch to the Lisp buffer afterwards."
- (interactive "r\nP")
- (comint-send-string
- (inferior-lisp-proc)
- (format "(funcall (compile nil `(lambda () (progn 'compile %s))))\n"
- (buffer-substring start end)))
- (if and-go (switch-to-lisp t)))
-
-(defun lisp-compile-defun (&optional and-go)
- "Compile the current defun in the inferior Lisp process.
-Prefix argument means switch to the Lisp buffer afterwards."
- (interactive "P")
- (save-excursion
- (end-of-defun)
- (skip-chars-backward " \t\n\r\f") ; Makes allegro happy
- (let ((e (point)))
- (beginning-of-defun)
- (lisp-compile-region (point) e)))
- (if and-go (switch-to-lisp t)))
-
-(defun switch-to-lisp (eob-p)
- "Switch to the inferior Lisp process buffer.
-With argument, positions cursor at end of buffer."
- (interactive "P")
- (if (get-buffer inferior-lisp-buffer)
- (let ((pop-up-frames
- ;; Be willing to use another frame
- ;; that already has the window in it.
- (or pop-up-frames
- (get-buffer-window inferior-lisp-buffer t))))
- (pop-to-buffer inferior-lisp-buffer))
- (error "No current inferior Lisp buffer"))
- (cond (eob-p
- (push-mark)
- (goto-char (point-max)))))
-
-
-;;; Now that lisp-compile/eval-defun/region takes an optional prefix arg,
-;;; these commands are redundant. But they are kept around for the user
-;;; to bind if he wishes, for backwards functionality, and because it's
-;;; easier to type C-c e than C-u C-c C-e.
-
-(defun lisp-eval-region-and-go (start end)
- "Send the current region to the inferior Lisp, and switch to its buffer."
- (interactive "r")
- (lisp-eval-region start end t))
-
-(defun lisp-eval-defun-and-go ()
- "Send the current defun to the inferior Lisp, and switch to its buffer."
- (interactive)
- (lisp-eval-defun t))
-
-(defun lisp-compile-region-and-go (start end)
- "Compile the current region in the inferior Lisp, and switch to its buffer."
- (interactive "r")
- (lisp-compile-region start end t))
-
-(defun lisp-compile-defun-and-go ()
- "Compile the current defun in the inferior Lisp, and switch to its buffer."
- (interactive)
- (lisp-compile-defun t))
-
-;;; A version of the form in H. Shevis' soar-mode.el package. Less robust.
-;;; (defun lisp-compile-sexp (start end)
-;;; "Compile the s-expression bounded by START and END in the inferior lisp.
-;;; If the sexp isn't a DEFUN form, it is evaluated instead."
-;;; (cond ((looking-at "(defun\\s +")
-;;; (goto-char (match-end 0))
-;;; (let ((name-start (point)))
-;;; (forward-sexp 1)
-;;; (process-send-string "inferior-lisp"
-;;; (format "(compile '%s #'(lambda "
-;;; (buffer-substring name-start
-;;; (point)))))
-;;; (let ((body-start (point)))
-;;; (goto-char start) (forward-sexp 1) ; Can't use end-of-defun.
-;;; (process-send-region "inferior-lisp"
-;;; (buffer-substring body-start (point))))
-;;; (process-send-string "inferior-lisp" ")\n"))
-;;; (t (lisp-eval-region start end)))))
-;;;
-;;; (defun lisp-compile-region (start end)
-;;; "Each s-expression in the current region is compiled (if a DEFUN)
-;;; or evaluated (if not) in the inferior lisp."
-;;; (interactive "r")
-;;; (save-excursion
-;;; (goto-char start) (end-of-defun) (beginning-of-defun) ; error check
-;;; (if (< (point) start) (error "region begins in middle of defun"))
-;;; (goto-char start)
-;;; (let ((s start))
-;;; (end-of-defun)
-;;; (while (<= (point) end) ; Zip through
-;;; (lisp-compile-sexp s (point)) ; compiling up defun-sized chunks.
-;;; (setq s (point))
-;;; (end-of-defun))
-;;; (if (< s end) (lisp-compile-sexp s end)))))
-;;;
-;;; End of HS-style code
-
-
-(defvar lisp-prev-l/c-dir/file nil
- "Record last directory and file used in loading or compiling.
-This holds a cons cell of the form `(DIRECTORY . FILE)'
-describing the last `lisp-load-file' or `lisp-compile-file' command.")
-
-(defvar lisp-source-modes '(lisp-mode)
- "*Used to determine if a buffer contains Lisp source code.
-If it's loaded into a buffer that is in one of these major modes, it's
-considered a Lisp source file by `lisp-load-file' and `lisp-compile-file'.
-Used by these commands to determine defaults.")
-
-(defun lisp-load-file (file-name)
- "Load a Lisp file into the inferior Lisp process."
- (interactive (comint-get-source "Load Lisp file: " lisp-prev-l/c-dir/file
- lisp-source-modes nil)) ; NIL because LOAD
- ; doesn't need an exact name
- (comint-check-source file-name) ; Check to see if buffer needs saved.
- (setq lisp-prev-l/c-dir/file (cons (file-name-directory file-name)
- (file-name-nondirectory file-name)))
- (comint-send-string (inferior-lisp-proc)
- (format inferior-lisp-load-command file-name))
- (switch-to-lisp t))
-
-
-(defun lisp-compile-file (file-name)
- "Compile a Lisp file in the inferior Lisp process."
- (interactive (comint-get-source "Compile Lisp file: " lisp-prev-l/c-dir/file
- lisp-source-modes nil)) ; NIL = don't need
- ; suffix .lisp
- (comint-check-source file-name) ; Check to see if buffer needs saved.
- (setq lisp-prev-l/c-dir/file (cons (file-name-directory file-name)
- (file-name-nondirectory file-name)))
- (comint-send-string (inferior-lisp-proc) (concat "(compile-file \""
- file-name
- "\"\)\n"))
- (switch-to-lisp t))
-
-
-
-;;; Documentation functions: function doc, var doc, arglist, and
-;;; describe symbol.
-;;; ===========================================================================
-
-;;; Command strings
-;;; ===============
-
-(defvar lisp-function-doc-command
- "(let ((fn '%s))
- (format t \"Documentation for ~a:~&~a\"
- fn (documentation fn 'function))
- (values))\n"
- "Command to query inferior Lisp for a function's documentation.")
-
-(defvar lisp-var-doc-command
- "(let ((v '%s))
- (format t \"Documentation for ~a:~&~a\"
- v (documentation v 'variable))
- (values))\n"
- "Command to query inferior Lisp for a variable's documentation.")
-
-(defvar lisp-arglist-command
- "(let ((fn '%s))
- (format t \"Arglist for ~a: ~a\" fn (arglist fn))
- (values))\n"
- "Command to query inferior Lisp for a function's arglist.")
-
-(defvar lisp-describe-sym-command
- "(describe '%s)\n"
- "Command to query inferior Lisp for a variable's documentation.")
-
-
-;;; Ancillary functions
-;;; ===================
-
-;;; Reads a string from the user.
-(defun lisp-symprompt (prompt default)
- (list (let* ((prompt (if default
- (format "%s (default %s): " prompt default)
- (concat prompt ": ")))
- (ans (read-string prompt)))
- (if (zerop (length ans)) default ans))))
-
-
-;;; Adapted from function-called-at-point in help.el.
-(defun lisp-fn-called-at-pt ()
- "Returns the name of the function called in the current call.
-The value is nil if it can't find one."
- (condition-case nil
- (save-excursion
- (save-restriction
- (narrow-to-region (max (point-min) (- (point) 1000)) (point-max))
- (backward-up-list 1)
- (forward-char 1)
- (let ((obj (read (current-buffer))))
- (and (symbolp obj) obj))))
- (error nil)))
-
-
-;;; Adapted from variable-at-point in help.el.
-(defun lisp-var-at-pt ()
- (condition-case ()
- (save-excursion
- (forward-sexp -1)
- (skip-chars-forward "'")
- (let ((obj (read (current-buffer))))
- (and (symbolp obj) obj)))
- (error nil)))
-
-
-;;; Documentation functions: fn and var doc, arglist, and symbol describe.
-;;; ======================================================================
-
-(defun lisp-show-function-documentation (fn)
- "Send a command to the inferior Lisp to give documentation for function FN.
-See variable `lisp-function-doc-command'."
- (interactive (lisp-symprompt "Function doc" (lisp-fn-called-at-pt)))
- (comint-proc-query (inferior-lisp-proc)
- (format lisp-function-doc-command fn)))
-
-(defun lisp-show-variable-documentation (var)
- "Send a command to the inferior Lisp to give documentation for function FN.
-See variable `lisp-var-doc-command'."
- (interactive (lisp-symprompt "Variable doc" (lisp-var-at-pt)))
- (comint-proc-query (inferior-lisp-proc) (format lisp-var-doc-command var)))
-
-(defun lisp-show-arglist (fn)
- "Send a query to the inferior Lisp for the arglist for function FN.
-See variable `lisp-arglist-command'."
- (interactive (lisp-symprompt "Arglist" (lisp-fn-called-at-pt)))
- (comint-proc-query (inferior-lisp-proc) (format lisp-arglist-command fn)))
-
-(defun lisp-describe-sym (sym)
- "Send a command to the inferior Lisp to describe symbol SYM.
-See variable `lisp-describe-sym-command'."
- (interactive (lisp-symprompt "Describe" (lisp-var-at-pt)))
- (comint-proc-query (inferior-lisp-proc)
- (format lisp-describe-sym-command sym)))
-
-
-;; "Returns the current inferior Lisp process.
-;; See variable `inferior-lisp-buffer'."
-(defun inferior-lisp-proc ()
- (let ((proc (get-buffer-process (if (eq major-mode 'inferior-lisp-mode)
- (current-buffer)
- inferior-lisp-buffer))))
- (or proc
- (error "No Lisp subprocess; see variable `inferior-lisp-buffer'"))))
-
-
-;;; Do the user's customisation...
-;;;===============================
-(defvar inferior-lisp-load-hook nil
- "This hook is run when the library `inf-lisp' is loaded.
-This is a good place to put keybindings.")
-
-(run-hooks 'inferior-lisp-load-hook)
-
-;;; CHANGE LOG
-;;; ===========================================================================
-;;; 7/21/92 Jim Blandy
-;;; - Changed all uses of the cmulisp name or prefix to inferior-lisp;
-;;; this is now the official inferior lisp package. Use the global
-;;; ChangeLog from now on.
-;;; 5/24/90 Olin
-;;; - Split cmulisp and cmushell modes into separate files.
-;;; Not only is this a good idea, it's apparently the way it'll be rel 19.
-;;; - Upgraded process sends to use comint-send-string instead of
-;;; process-send-string.
-;;; - Explicit references to process "cmulisp" have been replaced with
-;;; (cmulisp-proc). This allows better handling of multiple process bufs.
-;;; - Added process query and var/function/symbol documentation
-;;; commands. Based on code written by Douglas Roberts.
-;;; - Added lisp-eval-last-sexp, bound to C-x C-e.
-;;;
-;;; 9/20/90 Olin
-;;; Added a save-restriction to lisp-fn-called-at-pt. This bug and fix
-;;; reported by Lennart Staflin.
-;;;
-;;; 3/12/90 Olin
-;;; - lisp-load-file and lisp-compile-file no longer switch-to-lisp.
-;;; Tale suggested this.
-;;; - Reversed this decision 7/15/91. You need the visual feedback.
-;;;
-;;; 7/25/91 Olin
-;;; Changed all keybindings of the form C-c <letter>. These are
-;;; supposed to be reserved for the user to bind. This affected
-;;; mainly the compile/eval-defun/region[-and-go] commands.
-;;; This was painful, but necessary to adhere to the gnumacs standard.
-;;; For some backwards compatibility, see the
-;;; cmulisp-install-letter-bindings
-;;; function.
-;;;
-;;; 8/2/91 Olin
-;;; - The lisp-compile/eval-defun/region commands now take a prefix arg,
-;;; which means switch-to-lisp after sending the text to the Lisp process.
-;;; This obsoletes all the -and-go commands. The -and-go commands are
-;;; kept around for historical reasons, and because the user can bind
-;;; them to key sequences shorter than C-u C-c C-<letter>.
-;;; - If M-x cmulisp is invoked with a prefix arg, it allows you to
-;;; edit the command line.
-
-(provide 'inf-lisp)
-
-;;; inf-lisp.el ends here
diff --git a/lisp/progmodes/m4-mode.el b/lisp/progmodes/m4-mode.el
deleted file mode 100644
index a9177ea91e0..00000000000
--- a/lisp/progmodes/m4-mode.el
+++ /dev/null
@@ -1,152 +0,0 @@
-;;; m4-mode.el --- m4 code editing commands for Emacs
-
-;;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Andrew Csillag <drew@staff.prodigy.com>
-;; Maintainer: Andrew Csillag <drew@staff.prodigy.com>
-;; Keywords: languages, faces
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; A smart editing mode for m4 macro definitions. It seems to have most of the
-;; syntax right (sexp motion commands work, but function motion commands don't).
-;; It also sets the font-lock syntax stuff for colorization
-
-;; To Do's:
-
-;; * want to make m4-m4-(buffer|region) look sorta like M-x compile look&feel ?
-;; * sexp motion commands don't seem to work right
-
-;; to autoload m4 lisp code:
-;; (autoload 'm4-mode "m4-mode" nil t)
-;;
-;; or can use (load "m4-mode") or (require 'm4-mode) to just load it
-;;
-;; to try to "auto-detect" m4 files:
-;; (setq auto-mode-alist
-;; (cons '(".*\\.m4$" . m4-mode)
-;; auto-mode-alist))
-
-;;; Thanks:
-;;; to Akim Demaille and Terry Jones for the bug reports
-
-;;; Code:
-
-;;path to the m4 program
-(defvar m4-program "/usr/local/bin/m4")
-
-;;thank god for make-regexp.el!
-(defvar m4-font-lock-keywords
- `(
- ("^\\\#.*" . font-lock-comment-face)
- ("\\\$\\\*" . font-lock-variable-name-face)
- ("\\\$[0-9]" . font-lock-variable-name-face)
- ("\\\$\\\#" . font-lock-variable-name-face)
- ("\\\$\\\@" . font-lock-variable-name-face)
- ("\\\$\\\*" . font-lock-variable-name-face)
- ("\\b\\(builtin\\|change\\(com\\|quote\\|word\\)\\|d\\(e\\(bug\\(file\\|mode\\)\\|cr\\|f\\(ine\\|n\\)\\)\\|iv\\(ert\\|num\\)\\|nl\\|umpdef\\)\\|e\\(rrprint\\|syscmd\\|val\\)\\|f\\(ile\\|ormat\\)\\|gnu\\|i\\(f\\(def\\|else\\)\\|n\\(c\\(lude\\|r\\)\\|d\\(ex\\|ir\\)\\)\\)\\|l\\(en\\|ine\\)\\|m\\(4\\(exit\\|wrap\\)\\|aketemp\\)\\|p\\(atsubst\\|opdef\\|ushdef\\)\\|regexp\\|s\\(hift\\|include\\|ubstr\\|ys\\(cmd\\|val\\)\\)\\|tra\\(ceo\\(ff\\|n\\)\\|nslit\\)\\|un\\(d\\(efine\\|ivert\\)\\|ix\\)\\)\\b" . font-lock-keyword-face)
- ("\\b\\(m4_\\(builtin\\|change\\(com\\|quote\\|word\\)\\|d\\(e\\(bug\\(file\\|mode\\)\\|cr\\|f\\(ine\\|n\\)\\)\\|iv\\(ert\\|num\\)\\|nl\\|umpdef\\)\\|e\\(rrprint\\|syscmd\\|val\\)\\|f\\(ile\\|ormat\\)\\|i\\(f\\(def\\|else\\)\\|n\\(c\\(lude\\|r\\)\\|d\\(ex\\|ir\\)\\)\\)\\|l\\(en\\|ine\\)\\|m\\(4\\(_undefine\\|exit\\|wrap\\)\\|aketemp\\)\\|p\\(atsubst\\|opdef\\|ushdef\\)\\|regexp\\|s\\(hift\\|include\\|ubstr\\|ys\\(cmd\\|val\\)\\)\\|tra\\(ceo\\(ff\\|n\\)\\|nslit\\)\\|undivert\\)\\)\\b" . font-lock-keyword-face)
- "default font-lock-keywords")
-)
-
-;;this may still need some work
-(defvar m4-mode-syntax-table nil
- "syntax table used in m4 mode")
-(setq m4-mode-syntax-table (make-syntax-table))
-(modify-syntax-entry ?` "('" m4-mode-syntax-table)
-(modify-syntax-entry ?' ")`" m4-mode-syntax-table)
-(modify-syntax-entry ?# "<\n" m4-mode-syntax-table)
-(modify-syntax-entry ?\n ">#" m4-mode-syntax-table)
-(modify-syntax-entry ?{ "_" m4-mode-syntax-table)
-(modify-syntax-entry ?} "_" m4-mode-syntax-table)
-(modify-syntax-entry ?* "w" m4-mode-syntax-table)
-(modify-syntax-entry ?_ "w" m4-mode-syntax-table)
-(modify-syntax-entry ?\" "w" m4-mode-syntax-table)
-
-(defvar m4-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-c\C-b" 'm4-m4-buffer)
- (define-key map "\C-c\C-r" 'm4-m4-region)
- (define-key map "\C-c\C-c" 'comment-region)
- map))
-
-(defun m4-m4-buffer ()
- "send contents of the current buffer to m4"
- (interactive)
- (start-process "m4process" "*m4 output*" m4-program "-e")
- (process-send-region "m4process" (point-min) (point-max))
- (process-send-eof "m4process")
- (switch-to-buffer "*m4 output*")
-)
-
-(defun m4-m4-region ()
- "send contents of the current region to m4"
- (interactive)
- (start-process "m4process" "*m4 output*" m4-program "-e")
- (process-send-region "m4process" (point) (mark))
- (process-send-eof "m4process")
- (switch-to-buffer "*m4 output*")
-)
-
-(defun m4-mode ()
- "A major-mode to edit m4 macro files
-\\{m4-mode-map}
-"
- (interactive)
- (kill-all-local-variables)
- (use-local-map m4-mode-map)
-
- (make-local-variable 'comment-start)
- (setq comment-start "#")
- (make-local-variable 'parse-sexp-ignore-comments)
- (setq parse-sexp-ignore-comments t)
-
-
- (make-local-variable 'font-lock-defaults)
- (setq major-mode 'm4-mode
- mode-name "m4"
- font-lock-defaults `(m4-font-lock-keywords nil)
- )
- (set-syntax-table m4-mode-syntax-table)
- (run-hooks 'm4-mode-hook))
-
-(provide 'm4-mode)
-;;stuff to play with for debugging
-;(char-to-string (char-syntax ?`))
-
-;;;how I generate the nasty looking regexps at the top
-;;;(make-regexp '("builtin" "changecom" "changequote" "changeword" "debugfile"
-;;; "debugmode" "decr" "define" "defn" "divert" "divnum" "dnl"
-;;; "dumpdef" "errprint" "esyscmd" "eval" "file" "format" "gnu"
-;;; "ifdef" "ifelse" "include" "incr" "index" "indir" "len" "line"
-;;; "m4exit" "m4wrap" "maketemp" "patsubst" "popdef" "pushdef" "regexp"
-;;; "shift" "sinclude" "substr" "syscmd" "sysval" "traceoff" "traceon"
-;;; "translit" "undefine" "undivert" "unix"))
-;;;(make-regexp '("m4_builtin" "m4_changecom" "m4_changequote" "m4_changeword"
-;;; "m4_debugfile" "m4_debugmode" "m4_decr" "m4_define" "m4_defn"
-;;; "m4_divert" "m4_divnum" "m4_dnl" "m4_dumpdef" "m4_errprint"
-;;; "m4_esyscmd" "m4_eval" "m4_file" "m4_format" "m4_ifdef" "m4_ifelse"
-;;; "m4_include" "m4_incr" "m4_index" "m4_indir" "m4_len" "m4_line"
-;;; "m4_m4exit" "m4_m4wrap" "m4_maketemp" "m4_patsubst" "m4_popdef"
-;;; "m4_pushdef" "m4_regexp" "m4_shift" "m4_sinclude" "m4_substr"
-;;; "m4_syscmd" "m4_sysval" "m4_traceoff" "m4_traceon" "m4_translit"
-;;; "m4_m4_undefine" "m4_undivert"))
-
-;;; m4.el ends here
diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el
deleted file mode 100644
index 25aaf3b8cf7..00000000000
--- a/lisp/progmodes/make-mode.el
+++ /dev/null
@@ -1,1396 +0,0 @@
-;;; make-mode.el --- makefile editing commands for Emacs
-
-;; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
-
-;; Author: Thomas Neumann <tom@smart.bo.open.de>
-;; Eric S. Raymond <esr@snark.thyrsus.com>
-;; Adapted-By: ESR
-;; Keywords: unix, tools
-
-;; RMS:
-;; This needs work.
-;; Also, the doc strings need fixing: the first line doesn't stand alone,
-;; and other usage is not high quality. Symbol names don't have `...'.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; A major mode for editing makefiles. The mode knows about Makefile
-;; syntax and defines M-n and M-p to move to next and previous productions.
-;;
-;; The keys $, =, : and . are electric; they try to help you fill in a
-;; macro reference, macro definition, ordinary target name, or special
-;; target name, respectively. Such names are completed using a list of
-;; targets and macro names parsed out of the makefile. This list is
-;; automatically updated, if necessary, whenever you invoke one of
-;; these commands. You can force it to be updated with C-c C-p.
-;;
-;; The command C-c C-f adds certain filenames in the current directory
-;; as targets. You can filter out filenames by setting the variable
-;; makefile-ignored-files-in-pickup-regex.
-;;
-;; The command C-c C-u grinds for a bit, then pops up a report buffer
-;; showing which target names are up-to-date with respect to their
-;; prerequisites, which targets are out-of-date, and which have no
-;; prerequisites.
-;;
-;; The command C-c C-b pops up a browser window listing all target and
-;; macro names. You can mark or unmark items wit C-c SPC, and insert
-;; all marked items back in the Makefile with C-c TAB.
-;;
-;; The command C-c TAB in the makefile buffer inserts a GNU make builtin.
-;; You will be prompted for the builtin's args.
-;;
-;; There are numerous other customization variables.
-
-;;
-;; To Do:
-;;
-;; * makefile-backslash-region should be given better behavior.
-;; * Consider binding C-c C-c to comment-region (like cc-mode).
-;; * Eliminate electric stuff entirely.
-;; * It might be nice to highlight targets differently depending on
-;; whether they are up-to-date or not. Not sure how this would
-;; interact with font-lock.
-;; * Would be nice to edit the commands in ksh-mode and have
-;; indentation and slashification done automatically. Hard.
-;; * Consider removing browser mode. It seems useless.
-;; * ":" should notice when a new target is made and add it to the
-;; list (or at least set makefile-need-target-pickup).
-;; * Make browser into a major mode.
-;; * Clean up macro insertion stuff. It is a mess.
-;; * Browser entry and exit is weird. Normalize.
-;; * Browser needs to be rewritten. Right now it is kind of a crock.
-;; Should at least:
-;; * Act more like dired/buffer menu/whatever.
-;; * Highlight as mouse traverses.
-;; * B2 inserts.
-;; * Update documentation above.
-;; * Update texinfo manual.
-;; * Update files.el.
-
-
-
-;;; Code:
-
-(provide 'makefile)
-
-;; Sadly we need this for a macro.
-(eval-when-compile
- (require 'imenu))
-
-;;; ------------------------------------------------------------
-;;; Configurable stuff
-;;; ------------------------------------------------------------
-
-(defvar makefile-browser-buffer-name "*Macros and Targets*"
- "Name of the macro- and target browser buffer.")
-
-(defvar makefile-target-colon ":"
- "String to append to all target names inserted by `makefile-insert-target'.
-\":\" or \"::\" are common values.")
-
-(defvar makefile-macro-assign " = "
- "String to append to all macro names inserted by `makefile-insert-macro'.
-The normal value should be \" = \", since this is what
-standard make expects. However, newer makes such as dmake
-allow a larger variety of different macro assignments, so you
-might prefer to use \" += \" or \" := \" .")
-
-(defvar makefile-electric-keys nil
- "If non-nil, install electric keybindings.
-Default is nil.")
-
-(defvar makefile-use-curly-braces-for-macros-p nil
- "Controls the style of generated macro references.
-t (actually non-nil) means macro references should use curly braces,
-like `${this}'.
-nil means use parentheses, like `$(this)'.")
-
-(defvar makefile-tab-after-target-colon t
- "If non-nil, insert a TAB after a target colon.
-Otherwise, a space is inserted.
-The default is t.")
-
-(defvar makefile-browser-leftmost-column 10
- "Number of blanks to the left of the browser selection mark.")
-
-(defvar makefile-browser-cursor-column 10
- "Column in which the cursor is positioned when it moves
-up or down in the browser.")
-
-(defvar makefile-backslash-column 48
- "*Column in which `makefile-backslash-region' inserts backslashes.")
-
-(defvar makefile-browser-selected-mark "+ "
- "String used to mark selected entries in the browser.")
-
-(defvar makefile-browser-unselected-mark " "
- "String used to mark unselected entries in the browser.")
-
-(defvar makefile-browser-auto-advance-after-selection-p t
- "If non-nil, cursor will move after item is selected in browser.")
-
-(defvar makefile-pickup-everything-picks-up-filenames-p nil
- "If non-nil, `makefile-pickup-everything' picks up filenames as targets.
-\(i.e. it calls `makefile-find-filenames-as-targets').
-Otherwise filenames are omitted.")
-
-(defvar makefile-cleanup-continuations-p t
- "If non-nil, automatically clean up continuation lines when saving.
-A line is cleaned up by removing all whitespace following a trailing
-backslash. This is done silently.
-IMPORTANT: Please note that enabling this option causes makefile-mode
-to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \'it seems necessary\'.")
-
-(defvar makefile-browser-hook '())
-
-;;
-;; Special targets for DMake, Sun's make ...
-;;
-(defvar makefile-special-targets-list
- '(("DEFAULT") ("DONE") ("ERROR") ("EXPORT")
- ("FAILED") ("GROUPEPILOG") ("GROUPPROLOG") ("IGNORE")
- ("IMPORT") ("INCLUDE") ("INCLUDEDIRS") ("INIT")
- ("KEEP_STATE") ("MAKEFILES") ("MAKE_VERSION") ("NO_PARALLEL")
- ("PARALLEL") ("PHONY") ("PRECIOUS") ("REMOVE")
- ("SCCS_GET") ("SILENT") ("SOURCE") ("SUFFIXES")
- ("WAIT") ("c.o") ("C.o") ("m.o")
- ("el.elc") ("y.c") ("s.o"))
- "List of special targets.
-You will be offered to complete on one of those in the minibuffer whenever
-you enter a \".\" at the beginning of a line in makefile-mode.")
-
-(defvar makefile-runtime-macros-list
- '(("@") ("&") (">") ("<") ("*") ("^") ("+") ("?") ("%") ("$"))
- "List of macros that are resolved by make at runtime.
-If you insert a macro reference using makefile-insert-macro-ref, the name
-of the macro is checked against this list. If it can be found its name will
-not be enclosed in { } or ( ).")
-
-;; Note that the first big subexpression is used by font lock. Note
-;; that if you change this regexp you must fix the imenu index
-;; function defined at the end of the file.
-(defconst makefile-dependency-regex
- "^ *\\([^\n\t#:]+\\([ \t]+[^ \t\n#:]+\\)*\\)[ \t]*:\\([ \t]*$\\|\\([^=\n].*$\\)\\)"
- "Regex used to find dependency lines in a makefile.")
-
-;; Note that the first subexpression is used by font lock. Note that
-;; if you change this regexp you must fix the imenu index function
-;; defined at the end of the file.
-(defconst makefile-macroassign-regex
- "^ *\\([^\n\t][^:#= \t\n]*\\)[ \t]*[*:+]?:?="
- "Regex used to find macro assignment lines in a makefile.")
-
-(defconst makefile-ignored-files-in-pickup-regex
- "\\(^\\..*\\)\\|\\(.*~$\\)\\|\\(.*,v$\\)\\|\\(\\.[chy]\\)"
- "Regex for filenames that will NOT be included in the target list.")
-
-(if (fboundp 'facemenu-unlisted-faces)
- (add-to-list 'facemenu-unlisted-faces 'makefile-space-face))
-(defvar makefile-space-face 'makefile-space-face
- "Face to use for highlighting leading spaces in Font-Lock mode.")
-
-(defconst makefile-font-lock-keywords
- (list
- ;; Do macro assignments. These get the "variable-name" face rather
- ;; arbitrarily.
- (list makefile-macroassign-regex 1 'font-lock-variable-name-face)
- ;;
- ;; Do dependencies. These get the function name face.
- (list makefile-dependency-regex 1 'font-lock-function-name-face)
- ;;
- ;; Variable references even in targets/strings/comments:
- '("\\$[({]\\([-a-zA-Z0-9_.]+\\)[}):]" 1 font-lock-reference-face prepend)
-
- ;; Highlight lines that contain just whitespace.
- ;; They can cause trouble, especially if they start with a tab.
- '("^[ \t]+$" . makefile-space-face)
-
- ;; Highlight shell comments that Make treats as commands,
- ;; since these can fool people.
- '("^\t+#" 0 makefile-space-face t)
-
- ;; Highlight spaces that precede tabs.
- ;; They can make a tab fail to be effective.
- '("^\\( +\\)\t" 1 makefile-space-face)))
-
-;;; ------------------------------------------------------------
-;;; The following configurable variables are used in the
-;;; up-to-date overview .
-;;; The standard configuration assumes that your `make' program
-;;; can be run in question/query mode using the `-q' option, this
-;;; means that the command
-;;;
-;;; make -q foo
-;;;
-;;; should return an exit status of zero if the target `foo' is
-;;; up to date and a nonzero exit status otherwise.
-;;; Many makes can do this although the docs/manpages do not mention
-;;; it. Try it with your favourite one. GNU make, System V make, and
-;;; Dennis Vadura's DMake have no problems.
-;;; Set the variable `makefile-brave-make' to the name of the
-;;; make utility that does this on your system.
-;;; To understand what this is all about see the function definition
-;;; of `makefile-query-by-make-minus-q' .
-;;; ------------------------------------------------------------
-
-(defvar makefile-brave-make "make"
- "A make that can handle the `-q' option.")
-
-(defvar makefile-query-one-target-method 'makefile-query-by-make-minus-q
- "Function to call to determine whether a make target is up to date.
-The function must satisfy this calling convention:
-
-* As its first argument, it must accept the name of the target to
- be checked, as a string.
-
-* As its second argument, it may accept the name of a makefile
- as a string. Depending on what you're going to do you may
- not need this.
-
-* It must return the integer value 0 (zero) if the given target
- should be considered up-to-date in the context of the given
- makefile, any nonzero integer value otherwise.")
-
-(defvar makefile-up-to-date-buffer-name "*Makefile Up-to-date overview*"
- "Name of the Up-to-date overview buffer.")
-
-;;; --- end of up-to-date-overview configuration ------------------
-
-(defvar makefile-mode-map nil
- "The keymap that is used in Makefile mode.")
-
-(if makefile-mode-map
- ()
- (setq makefile-mode-map (make-sparse-keymap))
- ;; set up the keymap
- (define-key makefile-mode-map "\C-c:" 'makefile-insert-target-ref)
- (if makefile-electric-keys
- (progn
- (define-key makefile-mode-map "$" 'makefile-insert-macro-ref)
- (define-key makefile-mode-map ":" 'makefile-electric-colon)
- (define-key makefile-mode-map "=" 'makefile-electric-equal)
- (define-key makefile-mode-map "." 'makefile-electric-dot)))
- (define-key makefile-mode-map "\C-c\C-f" 'makefile-pickup-filenames-as-targets)
- (define-key makefile-mode-map "\C-c\C-b" 'makefile-switch-to-browser)
- (define-key makefile-mode-map "\C-c\C-p" 'makefile-pickup-everything)
- (define-key makefile-mode-map "\C-c\C-u" 'makefile-create-up-to-date-overview)
- (define-key makefile-mode-map "\C-c\C-i" 'makefile-insert-gmake-function)
- (define-key makefile-mode-map "\C-c\C-\\" 'makefile-backslash-region)
- (define-key makefile-mode-map "\M-p" 'makefile-previous-dependency)
- (define-key makefile-mode-map "\M-n" 'makefile-next-dependency)
- (define-key makefile-mode-map "\e\t" 'makefile-complete)
-
- ;; Make menus.
- (define-key makefile-mode-map [menu-bar makefile-mode]
- (cons "Makefile" (make-sparse-keymap "Makefile")))
-
- (define-key makefile-mode-map [menu-bar makefile-mode browse]
- '("Pop up Makefile Browser" . makefile-switch-to-browser))
- (define-key makefile-mode-map [menu-bar makefile-mode complete]
- '("Complete Target or Macro" . makefile-complete))
- (define-key makefile-mode-map [menu-bar makefile-mode pickup]
- '("Find Targets and Macros" . makefile-pickup-everything))
-
- (define-key makefile-mode-map [menu-bar makefile-mode prev]
- '("Move to Previous Dependency" . makefile-previous-dependency))
- (define-key makefile-mode-map [menu-bar makefile-mode next]
- '("Move to Next Dependency" . makefile-next-dependency)))
-
-(defvar makefile-browser-map nil
- "The keymap that is used in the macro- and target browser.")
-(if makefile-browser-map
- ()
- (setq makefile-browser-map (make-sparse-keymap))
- (define-key makefile-browser-map "n" 'makefile-browser-next-line)
- (define-key makefile-browser-map "\C-n" 'makefile-browser-next-line)
- (define-key makefile-browser-map "p" 'makefile-browser-previous-line)
- (define-key makefile-browser-map "\C-p" 'makefile-browser-previous-line)
- (define-key makefile-browser-map " " 'makefile-browser-toggle)
- (define-key makefile-browser-map "i" 'makefile-browser-insert-selection)
- (define-key makefile-browser-map "I" 'makefile-browser-insert-selection-and-quit)
- (define-key makefile-browser-map "\C-c\C-m" 'makefile-browser-insert-continuation)
- (define-key makefile-browser-map "q" 'makefile-browser-quit)
- ;; disable horizontal movement
- (define-key makefile-browser-map "\C-b" 'undefined)
- (define-key makefile-browser-map "\C-f" 'undefined))
-
-
-(defvar makefile-mode-syntax-table nil)
-(if makefile-mode-syntax-table
- ()
- (setq makefile-mode-syntax-table (make-syntax-table))
- (modify-syntax-entry ?\( "() " makefile-mode-syntax-table)
- (modify-syntax-entry ?\) ")( " makefile-mode-syntax-table)
- (modify-syntax-entry ?\[ "(] " makefile-mode-syntax-table)
- (modify-syntax-entry ?\] ")[ " makefile-mode-syntax-table)
- (modify-syntax-entry ?\{ "(} " makefile-mode-syntax-table)
- (modify-syntax-entry ?\} "){ " makefile-mode-syntax-table)
- (modify-syntax-entry ?\' "\" " makefile-mode-syntax-table)
- (modify-syntax-entry ?\` "\" " makefile-mode-syntax-table)
- (modify-syntax-entry ?# "< " makefile-mode-syntax-table)
- (modify-syntax-entry ?\n "> " makefile-mode-syntax-table))
-
-
-;;; ------------------------------------------------------------
-;;; Internal variables.
-;;; You don't need to configure below this line.
-;;; ------------------------------------------------------------
-
-(defvar makefile-target-table nil
- "Table of all target names known for this buffer.")
-
-(defvar makefile-macro-table nil
- "Table of all macro names known for this buffer.")
-
-(defvar makefile-browser-client
- "A buffer in Makefile mode that is currently using the browser.")
-
-(defvar makefile-browser-selection-vector nil)
-(defvar makefile-has-prereqs nil)
-(defvar makefile-need-target-pickup t)
-(defvar makefile-need-macro-pickup t)
-
-(defvar makefile-mode-hook '())
-
-;; Each element looks like '("GNU MAKE FUNCTION" "ARG" "ARG" ... )
-;; Each "ARG" is used as a prompt for a required argument.
-(defconst makefile-gnumake-functions-alist
- '(
- ;; Text functions
- ("subst" "From" "To" "In")
- ("patsubst" "Pattern" "Replacement" "In")
- ("strip" "Text")
- ("findstring" "Find what" "In")
- ("filter" "Pattern" "Text")
- ("filter-out" "Pattern" "Text")
- ("sort" "List")
- ;; Filename functions
- ("dir" "Names")
- ("notdir" "Names")
- ("suffix" "Names")
- ("basename" "Names")
- ("addprefix" "Prefix" "Names")
- ("addsuffix" "Suffix" "Names")
- ("join" "List 1" "List 2")
- ("word" "Index" "Text")
- ("words" "Text")
- ("firstword" "Text")
- ("wildcard" "Pattern")
- ;; Misc functions
- ("foreach" "Variable" "List" "Text")
- ("origin" "Variable")
- ("shell" "Command")))
-
-
-;;; ------------------------------------------------------------
-;;; The mode function itself.
-;;; ------------------------------------------------------------
-
-;;;###autoload
-(defun makefile-mode ()
- "Major mode for editing Makefiles.
-This function ends by invoking the function(s) `makefile-mode-hook'.
-
-\\{makefile-mode-map}
-
-In the browser, use the following keys:
-
-\\{makefile-browser-map}
-
-Makefile mode can be configured by modifying the following variables:
-
-makefile-browser-buffer-name:
- Name of the macro- and target browser buffer.
-
-makefile-target-colon:
- The string that gets appended to all target names
- inserted by `makefile-insert-target'.
- \":\" or \"::\" are quite common values.
-
-makefile-macro-assign:
- The string that gets appended to all macro names
- inserted by `makefile-insert-macro'.
- The normal value should be \" = \", since this is what
- standard make expects. However, newer makes such as dmake
- allow a larger variety of different macro assignments, so you
- might prefer to use \" += \" or \" := \" .
-
-makefile-tab-after-target-colon:
- If you want a TAB (instead of a space) to be appended after the
- target colon, then set this to a non-nil value.
-
-makefile-browser-leftmost-column:
- Number of blanks to the left of the browser selection mark.
-
-makefile-browser-cursor-column:
- Column in which the cursor is positioned when it moves
- up or down in the browser.
-
-makefile-browser-selected-mark:
- String used to mark selected entries in the browser.
-
-makefile-browser-unselected-mark:
- String used to mark unselected entries in the browser.
-
-makefile-browser-auto-advance-after-selection-p:
- If this variable is set to a non-nil value the cursor
- will automagically advance to the next line after an item
- has been selected in the browser.
-
-makefile-pickup-everything-picks-up-filenames-p:
- If this variable is set to a non-nil value then
- `makefile-pickup-everything' also picks up filenames as targets
- (i.e. it calls `makefile-find-filenames-as-targets'), otherwise
- filenames are omitted.
-
-makefile-cleanup-continuations-p:
- If this variable is set to a non-nil value then makefile-mode
- will assure that no line in the file ends with a backslash
- (the continuation character) followed by any whitespace.
- This is done by silently removing the trailing whitespace, leaving
- the backslash itself intact.
- IMPORTANT: Please note that enabling this option causes makefile-mode
- to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\".
-
-makefile-browser-hook:
- A function or list of functions to be called just before the
- browser is entered. This is executed in the makefile buffer.
-
-makefile-special-targets-list:
- List of special targets. You will be offered to complete
- on one of those in the minibuffer whenever you enter a `.'.
- at the beginning of a line in Makefile mode."
-
- (interactive)
- (kill-all-local-variables)
- (make-local-variable 'local-write-file-hooks)
- (setq local-write-file-hooks
- '(makefile-cleanup-continuations makefile-warn-suspicious-lines))
- (make-local-variable 'makefile-target-table)
- (make-local-variable 'makefile-macro-table)
- (make-local-variable 'makefile-has-prereqs)
- (make-local-variable 'makefile-need-target-pickup)
- (make-local-variable 'makefile-need-macro-pickup)
-
- ;; Font lock.
- (if (fboundp 'make-face)
- (makefile-define-space-face))
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(makefile-font-lock-keywords))
-
- ;; Add-log.
- (make-local-variable 'add-log-current-defun-function)
- (setq add-log-current-defun-function 'makefile-add-log-defun)
-
- ;; Imenu.
- (make-local-variable 'imenu-create-index-function)
- (setq imenu-create-index-function 'makefile-menu-index-function)
-
- ;; Dabbrev.
- (make-local-variable 'dabbrev-abbrev-skip-leading-regexp)
- (setq dabbrev-abbrev-skip-leading-regexp "\\$")
-
- ;; Comment stuff.
- (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 "#+[ \t]*")
-
- ;; become the current major mode
- (setq major-mode 'makefile-mode)
- (setq mode-name "Makefile")
-
- ;; Activate keymap and syntax table.
- (use-local-map makefile-mode-map)
- (set-syntax-table makefile-mode-syntax-table)
-
- ;; Real TABs are important in makefiles
- (setq indent-tabs-mode t)
- (run-hooks 'makefile-mode-hook))
-
-
-
-;;; Motion code.
-
-(defun makefile-next-dependency ()
- "Move point to the beginning of the next dependency line."
- (interactive)
- (let ((here (point)))
- (end-of-line)
- (if (re-search-forward makefile-dependency-regex (point-max) t)
- (progn (beginning-of-line) t) ; indicate success
- (goto-char here) nil)))
-
-(defun makefile-previous-dependency ()
- "Move point to the beginning of the previous dependency line."
- (interactive)
- (let ((here (point)))
- (beginning-of-line)
- (if (re-search-backward makefile-dependency-regex (point-min) t)
- (progn (beginning-of-line) t) ; indicate success
- (goto-char here) nil)))
-
-
-
-;;; Electric keys. Blech.
-
-(defun makefile-electric-dot (arg)
- "Prompt for the name of a special target to insert.
-Only does electric insertion at beginning of line.
-Anywhere else just self-inserts."
- (interactive "p")
- (if (bolp)
- (makefile-insert-special-target)
- (self-insert-command arg)))
-
-(defun makefile-insert-special-target ()
- "Prompt for and insert a special target name.
-Uses `makefile-special-targets' list."
- (interactive)
- (makefile-pickup-targets)
- (let ((special-target
- (completing-read "Special target: "
- makefile-special-targets-list nil nil nil)))
- (if (zerop (length special-target))
- ()
- (insert "." special-target ":")
- (makefile-forward-after-target-colon))))
-
-(defun makefile-electric-equal (arg)
- "Prompt for name of a macro to insert.
-Only does prompting if point is at beginning of line.
-Anywhere else just self-inserts."
- (interactive "p")
- (makefile-pickup-macros)
- (if (bolp)
- (call-interactively 'makefile-insert-macro)
- (self-insert-command arg)))
-
-(defun makefile-insert-macro (macro-name)
- "Prepare definition of a new macro."
- (interactive "sMacro Name: ")
- (makefile-pickup-macros)
- (if (not (zerop (length macro-name)))
- (progn
- (beginning-of-line)
- (insert macro-name makefile-macro-assign)
- (setq makefile-need-macro-pickup t)
- (makefile-remember-macro macro-name))))
-
-(defun makefile-insert-macro-ref (macro-name)
- "Complete on a list of known macros, then insert complete ref at point."
- (interactive
- (list
- (progn
- (makefile-pickup-macros)
- (completing-read "Refer to macro: " makefile-macro-table nil nil nil))))
- (makefile-do-macro-insertion macro-name))
-
-(defun makefile-insert-target (target-name)
- "Prepare definition of a new target (dependency line)."
- (interactive "sTarget: ")
- (if (not (zerop (length target-name)))
- (progn
- (beginning-of-line)
- (insert target-name makefile-target-colon)
- (makefile-forward-after-target-colon)
- (end-of-line)
- (setq makefile-need-target-pickup t)
- (makefile-remember-target target-name))))
-
-(defun makefile-insert-target-ref (target-name)
- "Complete on a list of known targets, then insert target-ref at point."
- (interactive
- (list
- (progn
- (makefile-pickup-targets)
- (completing-read "Refer to target: " makefile-target-table nil nil nil))))
- (if (not (zerop (length target-name)))
- (insert target-name " ")))
-
-(defun makefile-electric-colon (arg)
- "Prompt for name of new target.
-Prompting only happens at beginning of line.
-Anywhere else just self-inserts."
- (interactive "p")
- (if (bolp)
- (call-interactively 'makefile-insert-target)
- (self-insert-command arg)))
-
-
-
-;;; ------------------------------------------------------------
-;;; Extracting targets and macros from an existing makefile
-;;; ------------------------------------------------------------
-
-(defun makefile-pickup-targets ()
- "Notice names of all target definitions in Makefile."
- (interactive)
- (if (not makefile-need-target-pickup)
- nil
- (setq makefile-need-target-pickup nil)
- (setq makefile-target-table nil)
- (setq makefile-has-prereqs nil)
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward makefile-dependency-regex (point-max) t)
- (makefile-add-this-line-targets)))
- (message "Read targets OK.")))
-
-(defun makefile-add-this-line-targets ()
- (save-excursion
- (beginning-of-line)
- (let ((done-with-line nil)
- (line-number (1+ (count-lines (point-min) (point)))))
- (while (not done-with-line)
- (skip-chars-forward " \t")
- (if (not (setq done-with-line (or (eolp)
- (char-equal (char-after (point)) ?:))))
- (progn
- (let* ((start-of-target-name (point))
- (target-name
- (progn
- (skip-chars-forward "^ \t:#")
- (buffer-substring start-of-target-name (point))))
- (has-prereqs
- (not (looking-at ":[ \t]*$"))))
- (if (makefile-remember-target target-name has-prereqs)
- (message "Picked up target \"%s\" from line %d"
- target-name line-number)))))))))
-
-(defun makefile-pickup-macros ()
- "Notice names of all macro definitions in Makefile."
- (interactive)
- (if (not makefile-need-macro-pickup)
- nil
- (setq makefile-need-macro-pickup nil)
- (setq makefile-macro-table nil)
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward makefile-macroassign-regex (point-max) t)
- (makefile-add-this-line-macro)
- (forward-line 1)))
- (message "Read macros OK.")))
-
-(defun makefile-add-this-line-macro ()
- (save-excursion
- (beginning-of-line)
- (skip-chars-forward " \t")
- (if (not (eolp))
- (let* ((start-of-macro-name (point))
- (line-number (1+ (count-lines (point-min) (point))))
- (macro-name (progn
- (skip-chars-forward "^ \t:#=*")
- (buffer-substring start-of-macro-name (point)))))
- (if (makefile-remember-macro macro-name)
- (message "Picked up macro \"%s\" from line %d"
- macro-name line-number))))))
-
-(defun makefile-pickup-everything (arg)
- "Notice names of all macros and targets in Makefile.
-Prefix arg means force pickups to be redone."
- (interactive "P")
- (if arg
- (progn
- (setq makefile-need-target-pickup t)
- (setq makefile-need-macro-pickup t)))
- (makefile-pickup-macros)
- (makefile-pickup-targets)
- (if makefile-pickup-everything-picks-up-filenames-p
- (makefile-pickup-filenames-as-targets)))
-
-(defun makefile-pickup-filenames-as-targets ()
- "Scan the current directory for filenames to use as targets.
-Checks each filename against `makefile-ignored-files-in-pickup-regex'
-and adds all qualifying names to the list of known targets."
- (interactive)
- (let* ((dir (file-name-directory (buffer-file-name)))
- (raw-filename-list (if dir
- (file-name-all-completions "" dir)
- (file-name-all-completions "" ""))))
- (mapcar '(lambda (name)
- (if (and (not (file-directory-p name))
- (not (string-match makefile-ignored-files-in-pickup-regex
- name)))
- (if (makefile-remember-target name)
- (message "Picked up file \"%s\" as target" name))))
- raw-filename-list)))
-
-
-
-;;; Completion.
-
-(defun makefile-complete ()
- "Perform completion on Makefile construct preceding point.
-Can complete variable and target names.
-The context determines which are considered."
- (interactive)
- (let* ((beg (save-excursion
- (skip-chars-backward "^$(){}:#= \t\n")
- (point)))
- (try (buffer-substring beg (point)))
- (do-macros nil)
- (paren nil))
-
- (save-excursion
- (goto-char beg)
- (let ((pc (preceding-char)))
- (cond
- ;; Beginning of line means anything.
- ((bolp)
- ())
-
- ;; Preceding "$" means macros only.
- ((= pc ?$)
- (setq do-macros t))
-
- ;; Preceding "$(" or "${" means macros only.
- ((and (or (= pc ?{)
- (= pc ?\())
- (progn
- (setq paren pc)
- (backward-char)
- (and (not (bolp))
- (= (preceding-char) ?$))))
- (setq do-macros t)))))
-
- ;; Try completion.
- (let* ((table (append (if do-macros
- '()
- makefile-target-table)
- makefile-macro-table))
- (completion (try-completion try table)))
- (cond
- ;; Exact match, so insert closing paren or colon.
- ((eq completion t)
- (insert (if do-macros
- (if (eq paren ?{)
- ?}
- ?\))
- (if (save-excursion
- (goto-char beg)
- (bolp))
- ":"
- " "))))
-
- ;; No match.
- ((null completion)
- (message "Can't find completion for \"%s\"" try)
- (ding))
-
- ;; Partial completion.
- ((not (string= try completion))
- ;; FIXME it would be nice to supply the closing paren if an
- ;; exact, unambiguous match were found. That is not possible
- ;; right now. Ditto closing ":" for targets.
- (delete-region beg (point))
-
- ;; DO-MACROS means doing macros only. If not that, then check
- ;; to see if this completion is a macro. Special insertion
- ;; must be done for macros.
- (if (or do-macros
- (assoc completion makefile-macro-table))
- (let ((makefile-use-curly-braces-for-macros-p
- (or (eq paren ?{)
- makefile-use-curly-braces-for-macros-p)))
- (delete-backward-char 2)
- (makefile-do-macro-insertion completion)
- (delete-backward-char 1))
-
- ;; Just insert targets.
- (insert completion)))
-
- ;; Can't complete any more, so make completion list. FIXME
- ;; this doesn't do the right thing when the completion is
- ;; actually inserted. I don't think there is an easy way to do
- ;; that.
- (t
- (message "Making completion list...")
- (let ((list (all-completions try table)))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list list)))
- (message "Making completion list...done"))))))
-
-
-
-;; Backslashification. Stolen from cc-mode.el.
-
-(defun makefile-backslashify-current-line (doit)
- (end-of-line)
- (if doit
- (if (not (save-excursion
- (forward-char -1)
- (eq (char-after (point)) ?\\ )))
- (progn
- (if (>= (current-column) makefile-backslash-column)
- (insert " \\")
- (while (<= (current-column) makefile-backslash-column)
- (insert "\t")
- (end-of-line))
- (delete-char -1)
- (while (< (current-column) makefile-backslash-column)
- (insert " ")
- (end-of-line))
- (insert "\\"))))
- (if (not (bolp))
- (progn
- (forward-char -1)
- (if (eq (char-after (point)) ?\\ )
- (let ((saved (save-excursion
- (end-of-line)
- (point))))
- (skip-chars-backward " \t")
- (delete-region (point) saved)))))))
-
-(defun makefile-backslash-region (beg end arg)
- "Insert backslashes at end of every line in region.
-Useful for defining multi-line rules.
-If called with a prefix argument, trailing backslashes are removed."
- (interactive "r\nP")
- (save-excursion
- (let ((do-lastline-p (progn (goto-char end) (not (bolp)))))
- (save-restriction
- (narrow-to-region beg end)
- (goto-char (point-min))
- (while (not (save-excursion
- (forward-line 1)
- (eobp)))
- (makefile-backslashify-current-line (null arg))
- (forward-line 1)))
- (and do-lastline-p
- (progn (goto-char end)
- (makefile-backslashify-current-line (null arg)))))))
-
-
-
-;;; ------------------------------------------------------------
-;;; Browser mode.
-;;; ------------------------------------------------------------
-
-(defun makefile-browser-format-target-line (target selected)
- (format
- (concat (make-string makefile-browser-leftmost-column ?\ )
- (if selected
- makefile-browser-selected-mark
- makefile-browser-unselected-mark)
- "%s%s")
- target makefile-target-colon))
-
-(defun makefile-browser-format-macro-line (macro selected)
- (format
- (concat (make-string makefile-browser-leftmost-column ?\ )
- (if selected
- makefile-browser-selected-mark
- makefile-browser-unselected-mark)
- (makefile-format-macro-ref macro))))
-
-(defun makefile-browser-fill (targets macros)
- (let ((inhibit-read-only t))
- (goto-char (point-min))
- (erase-buffer)
- (mapconcat
- (function
- (lambda (item) (insert (makefile-browser-format-target-line (car item) nil) "\n")))
- targets
- "")
- (mapconcat
- (function
- (lambda (item) (insert (makefile-browser-format-macro-line (car item) nil) "\n")))
- macros
- "")
- (sort-lines nil (point-min) (point-max))
- (goto-char (1- (point-max)))
- (delete-char 1) ; remove unnecessary newline at eob
- (goto-char (point-min))
- (forward-char makefile-browser-cursor-column)))
-
-;;;
-;;; Moving up and down in the browser
-;;;
-
-(defun makefile-browser-next-line ()
- "Move the browser selection cursor to the next line."
- (interactive)
- (if (not (makefile-last-line-p))
- (progn
- (forward-line 1)
- (forward-char makefile-browser-cursor-column))))
-
-(defun makefile-browser-previous-line ()
- "Move the browser selection cursor to the previous line."
- (interactive)
- (if (not (makefile-first-line-p))
- (progn
- (forward-line -1)
- (forward-char makefile-browser-cursor-column))))
-
-;;;
-;;; Quitting the browser (returns to client buffer)
-;;;
-
-(defun makefile-browser-quit ()
- "Leave the browser and return to the makefile buffer."
- (interactive)
- (let ((my-client makefile-browser-client))
- (setq makefile-browser-client nil) ; we quitted, so NO client!
- (set-buffer-modified-p nil)
- (kill-buffer (current-buffer))
- (pop-to-buffer my-client)))
-
-;;;
-;;; Toggle state of a browser item
-;;;
-
-(defun makefile-browser-toggle ()
- "Toggle the selection state of the browser item at the cursor position."
- (interactive)
- (let ((this-line (count-lines (point-min) (point))))
- (setq this-line (max 1 this-line))
- (makefile-browser-toggle-state-for-line this-line)
- (goto-line this-line)
- (let ((inhibit-read-only t))
- (beginning-of-line)
- (if (makefile-browser-on-macro-line-p)
- (let ((macro-name (makefile-browser-this-line-macro-name)))
- (delete-region (point) (progn (end-of-line) (point)))
- (insert
- (makefile-browser-format-macro-line
- macro-name
- (makefile-browser-get-state-for-line this-line))))
- (let ((target-name (makefile-browser-this-line-target-name)))
- (delete-region (point) (progn (end-of-line) (point)))
- (insert
- (makefile-browser-format-target-line
- target-name
- (makefile-browser-get-state-for-line this-line))))))
- (beginning-of-line)
- (forward-char makefile-browser-cursor-column)
- (if makefile-browser-auto-advance-after-selection-p
- (makefile-browser-next-line))))
-
-;;;
-;;; Making insertions into the client buffer
-;;;
-
-(defun makefile-browser-insert-continuation ()
- "Insert a makefile continuation.
-In the makefile buffer, go to (end-of-line), insert a \'\\\'
-character, insert a new blank line, go to that line and indent by one TAB.
-This is most useful in the process of creating continued lines when copying
-large dependencies from the browser to the client buffer.
-\(point) advances accordingly in the client buffer."
- (interactive)
- (save-excursion
- (set-buffer makefile-browser-client)
- (end-of-line)
- (insert "\\\n\t")))
-
-(defun makefile-browser-insert-selection ()
- "Insert all selected targets and/or macros in the makefile buffer.
-Insertion takes place at point."
- (interactive)
- (save-excursion
- (goto-line 1)
- (let ((current-line 1))
- (while (not (eobp))
- (if (makefile-browser-get-state-for-line current-line)
- (makefile-browser-send-this-line-item))
- (forward-line 1)
- (setq current-line (1+ current-line))))))
-
-(defun makefile-browser-insert-selection-and-quit ()
- (interactive)
- (makefile-browser-insert-selection)
- (makefile-browser-quit))
-
-(defun makefile-browser-send-this-line-item ()
- (if (makefile-browser-on-macro-line-p)
- (save-excursion
- (let ((macro-name (makefile-browser-this-line-macro-name)))
- (set-buffer makefile-browser-client)
- (insert (makefile-format-macro-ref macro-name) " ")))
- (save-excursion
- (let ((target-name (makefile-browser-this-line-target-name)))
- (set-buffer makefile-browser-client)
- (insert target-name " ")))))
-
-(defun makefile-browser-start-interaction ()
- (use-local-map makefile-browser-map)
- (setq buffer-read-only t))
-
-(defun makefile-browse (targets macros)
- (interactive)
- (if (zerop (+ (length targets) (length macros)))
- (progn
- (beep)
- (message "No macros or targets to browse! Consider running 'makefile-pickup-everything\'"))
- (let ((browser-buffer (get-buffer-create makefile-browser-buffer-name)))
- (pop-to-buffer browser-buffer)
- (make-variable-buffer-local 'makefile-browser-selection-vector)
- (makefile-browser-fill targets macros)
- (shrink-window-if-larger-than-buffer)
- (setq makefile-browser-selection-vector
- (make-vector (+ (length targets) (length macros)) nil))
- (makefile-browser-start-interaction))))
-
-(defun makefile-switch-to-browser ()
- (interactive)
- (run-hooks 'makefile-browser-hook)
- (setq makefile-browser-client (current-buffer))
- (makefile-pickup-targets)
- (makefile-pickup-macros)
- (makefile-browse makefile-target-table makefile-macro-table))
-
-
-
-;;; ------------------------------------------------------------
-;;; Up-to-date overview buffer
-;;; ------------------------------------------------------------
-
-(defun makefile-create-up-to-date-overview ()
- "Create a buffer containing an overview of the state of all known targets.
-Known targets are targets that are explicitly defined in that makefile;
-in other words, all targets that appear on the left hand side of a
-dependency in the makefile."
- (interactive)
- (if (y-or-n-p "Are you sure that the makefile being edited is consistent? ")
- ;;
- ;; The rest of this function operates on a temporary makefile, created by
- ;; writing the current contents of the makefile buffer.
- ;;
- (let ((saved-target-table makefile-target-table)
- (this-buffer (current-buffer))
- (makefile-up-to-date-buffer
- (get-buffer-create makefile-up-to-date-buffer-name))
- (filename (makefile-save-temporary))
- ;;
- ;; Forget the target table because it may contain picked-up filenames
- ;; that are not really targets in the current makefile.
- ;; We don't want to query these, so get a new target-table with just the
- ;; targets that can be found in the makefile buffer.
- ;; The 'old' target table will be restored later.
- ;;
- (real-targets (progn
- (makefile-pickup-targets)
- makefile-target-table))
- (prereqs makefile-has-prereqs)
- )
-
- (set-buffer makefile-up-to-date-buffer)
- (setq buffer-read-only nil)
- (erase-buffer)
- (makefile-query-targets filename real-targets prereqs)
- (if (zerop (buffer-size)) ; if it did not get us anything
- (progn
- (kill-buffer (current-buffer))
- (message "No overview created!")))
- (set-buffer this-buffer)
- (setq makefile-target-table saved-target-table)
- (if (get-buffer makefile-up-to-date-buffer-name)
- (progn
- (pop-to-buffer (get-buffer makefile-up-to-date-buffer-name))
- (shrink-window-if-larger-than-buffer)
- (sort-lines nil (point-min) (point-max))
- (setq buffer-read-only t))))))
-
-(defun makefile-save-temporary ()
- "Create a temporary file from the current makefile buffer."
- (let ((filename (makefile-generate-temporary-filename)))
- (write-region (point-min) (point-max) filename nil 0)
- filename)) ; return the filename
-
-(defun makefile-generate-temporary-filename ()
- "Create a filename suitable for use in `makefile-save-temporary'.
-Be careful to allow brain-dead file systems (DOS, SYSV ...) to cope
-with the generated name!"
- (let ((my-name (user-login-name))
- (my-uid (int-to-string (user-uid))))
- (concat "mktmp"
- (if (> (length my-name) 3)
- (substring my-name 0 3)
- my-name)
- "."
- (if (> (length my-uid) 3)
- (substring my-uid 0 3)
- my-uid))))
-
-(defun makefile-query-targets (filename target-table prereq-list)
- "Fill the up-to-date overview buffer.
-Checks each target in TARGET-TABLE using `makefile-query-one-target-method'
-and generates the overview, one line per target name."
- (insert
- (mapconcat
- (function (lambda (item)
- (let* ((target-name (car item))
- (no-prereqs (not (member target-name prereq-list)))
- (needs-rebuild (or no-prereqs
- (funcall
- makefile-query-one-target-method
- target-name
- filename))))
- (format "\t%s%s"
- target-name
- (cond (no-prereqs " .. has no prerequisites")
- (needs-rebuild " .. NEEDS REBUILD")
- (t " .. is up to date"))))
- ))
- target-table "\n"))
- (goto-char (point-min))
- (delete-file filename)) ; remove the tmpfile
-
-(defun makefile-query-by-make-minus-q (target &optional filename)
- (not (zerop
- (call-process makefile-brave-make nil nil nil
- "-f" filename "-q" target))))
-
-
-
-;;; ------------------------------------------------------------
-;;; Continuation cleanup
-;;; ------------------------------------------------------------
-
-(defun makefile-cleanup-continuations ()
- (if (eq major-mode 'makefile-mode)
- (if (and makefile-cleanup-continuations-p
- (not buffer-read-only))
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward "\\\\[ \t]+$" (point-max) t)
- (replace-match "\\" t t))))))
-
-
-;;; ------------------------------------------------------------
-;;; Warn of suspicious lines
-;;; ------------------------------------------------------------
-
-(defun makefile-warn-suspicious-lines ()
- (let ((dont-save nil))
- (if (eq major-mode 'makefile-mode)
- (let ((suspicious
- (save-excursion
- (goto-char (point-min))
- (re-search-forward
- "\\(^[\t]+$\\)\\|\\(^[ ]+[\t]\\)" (point-max) t))))
- (if suspicious
- (let ((line-nr (count-lines (point-min) suspicious)))
- (setq dont-save
- (not (y-or-n-p
- (format "Suspicious line %d. Save anyway "
- line-nr))))))))
- dont-save))
-
-
-
-;;; ------------------------------------------------------------
-;;; GNU make function support
-;;; ------------------------------------------------------------
-
-(defun makefile-insert-gmake-function ()
- "Insert a GNU make function call.
-Asks for the name of the function to use (with completion).
-Then prompts for all required parameters."
- (interactive)
- (let* ((gm-function-name (completing-read
- "Function: "
- makefile-gnumake-functions-alist
- nil t nil))
- (gm-function-prompts
- (cdr (assoc gm-function-name makefile-gnumake-functions-alist))))
- (if (not (zerop (length gm-function-name)))
- (insert (makefile-format-macro-ref
- (concat gm-function-name " "
- (makefile-prompt-for-gmake-funargs
- gm-function-name gm-function-prompts)))
- " "))))
-
-(defun makefile-prompt-for-gmake-funargs (function-name prompt-list)
- (mapconcat
- (function (lambda (one-prompt)
- (read-string (format "[%s] %s: " function-name one-prompt)
- nil)))
- prompt-list
- ","))
-
-
-
-;;; ------------------------------------------------------------
-;;; Utility functions
-;;; ------------------------------------------------------------
-
-(defun makefile-do-macro-insertion (macro-name)
- "Insert a macro reference."
- (if (not (zerop (length macro-name)))
- (if (assoc macro-name makefile-runtime-macros-list)
- (insert "$" macro-name)
- (insert (makefile-format-macro-ref macro-name)))))
-
-(defun makefile-remember-target (target-name &optional has-prereqs)
- "Remember a given target if it is not already remembered for this buffer."
- (if (not (zerop (length target-name)))
- (progn
- (if (not (assoc target-name makefile-target-table))
- (setq makefile-target-table
- (cons (list target-name) makefile-target-table)))
- (if has-prereqs
- (setq makefile-has-prereqs
- (cons target-name makefile-has-prereqs))))))
-
-(defun makefile-remember-macro (macro-name)
- "Remember a given macro if it is not already remembered for this buffer."
- (if (not (zerop (length macro-name)))
- (if (not (assoc macro-name makefile-macro-table))
- (setq makefile-macro-table
- (cons (list macro-name) makefile-macro-table)))))
-
-(defun makefile-forward-after-target-colon ()
- "Move point forward after inserting the terminating colon of a target.
-This acts according to the value of `makefile-tab-after-target-colon'."
- (if makefile-tab-after-target-colon
- (insert "\t")
- (insert " ")))
-
-(defun makefile-browser-on-macro-line-p ()
- "Determine if point is on a macro line in the browser."
- (save-excursion
- (beginning-of-line)
- (re-search-forward "\\$[{(]" (makefile-end-of-line-point) t)))
-
-(defun makefile-browser-this-line-target-name ()
- "Extract the target name from a line in the browser."
- (save-excursion
- (end-of-line)
- (skip-chars-backward "^ \t")
- (buffer-substring (point) (1- (makefile-end-of-line-point)))))
-
-(defun makefile-browser-this-line-macro-name ()
- "Extract the macro name from a line in the browser."
- (save-excursion
- (beginning-of-line)
- (re-search-forward "\\$[{(]" (makefile-end-of-line-point) t)
- (let ((macro-start (point)))
- (skip-chars-forward "^})")
- (buffer-substring macro-start (point)))))
-
-(defun makefile-format-macro-ref (macro-name)
- "Format a macro reference.
-Uses `makefile-use-curly-braces-for-macros-p'."
- (if (or (char-equal ?\( (string-to-char macro-name))
- (char-equal ?\{ (string-to-char macro-name)))
- (format "$%s" macro-name)
- (if makefile-use-curly-braces-for-macros-p
- (format "${%s}" macro-name)
- (format "$(%s)" macro-name))))
-
-(defun makefile-browser-get-state-for-line (n)
- (aref makefile-browser-selection-vector (1- n)))
-
-(defun makefile-browser-set-state-for-line (n to-state)
- (aset makefile-browser-selection-vector (1- n) to-state))
-
-(defun makefile-browser-toggle-state-for-line (n)
- (makefile-browser-set-state-for-line n (not (makefile-browser-get-state-for-line n))))
-
-(defun makefile-beginning-of-line-point ()
- (save-excursion
- (beginning-of-line)
- (point)))
-
-(defun makefile-end-of-line-point ()
- (save-excursion
- (end-of-line)
- (point)))
-
-(defun makefile-last-line-p ()
- (= (makefile-end-of-line-point) (point-max)))
-
-(defun makefile-first-line-p ()
- (= (makefile-beginning-of-line-point) (point-min)))
-
-
-
-;;; Support for other packages, like add-log and imenu.
-
-(defun makefile-add-log-defun ()
- "Return name of target or variable assignment that point is in.
-If it isn't in one, return nil."
- (save-excursion
- (let (found)
- (beginning-of-line)
- ;; Scan back line by line, noticing when we come to a
- ;; variable or rule definition, and giving up when we see
- ;; a line that is not part of either of those.
- (while (not found)
- (cond
- ((looking-at makefile-macroassign-regex)
- (setq found (buffer-substring-no-properties (match-beginning 1)
- (match-end 1))))
- ((looking-at makefile-dependency-regex)
- (setq found (buffer-substring-no-properties (match-beginning 1)
- (match-end 1))))
- ;; Don't keep looking across a blank line or comment. Give up.
- ((looking-at "$\\|#")
- (setq found 'bobp))
- ((bobp)
- (setq found 'bobp)))
- (or found
- (forward-line -1)))
- (if (stringp found) found))))
-
-;; FIXME it might be nice to have them separated by macro vs target.
-(defun makefile-menu-index-function ()
- ;; "Generate alist of indices for imenu."
- (let (alist
- stupid
- (re (concat makefile-dependency-regex
- "\\|"
- makefile-macroassign-regex)))
- (imenu-progress-message stupid 0)
- (goto-char (point-min))
- (while (re-search-forward re nil t)
- (imenu-progress-message stupid)
- (let ((n (if (match-beginning 1) 1 5)))
- (setq alist (cons
- (cons (buffer-substring (match-beginning n)
- (match-end n))
- (match-beginning n))
- alist))))
- (imenu-progress-message stupid 100)
- (nreverse alist)))
-
-(defun makefile-define-space-face ()
- (make-face 'makefile-space-face)
- (or (not (eq window-system 'x))
- (face-differs-from-default-p 'makefile-space-face)
- (let* ((params (frame-parameters))
- (light-bg (cdr (assq 'background-mode params)))
- (bg-color (cond ((eq (cdr (assq 'display-type params)) 'mono)
- (if light-bg "black" "white"))
- ((eq (cdr (assq 'display-type params)) 'grayscale)
- (if light-bg "black" "white"))
- (light-bg ; Light color background.
- "hotpink")
- (t ; Dark color background.
- "hotpink"))))
- (set-face-background 'makefile-space-face bg-color))))
-
-;;; make-mode.el ends here
diff --git a/lisp/progmodes/modula2.el b/lisp/progmodes/modula2.el
deleted file mode 100644
index 12c6befae9d..00000000000
--- a/lisp/progmodes/modula2.el
+++ /dev/null
@@ -1,454 +0,0 @@
-;;; modula2.el --- Modula-2 editing support package
-
-;; Author: Michael Schmidt <michael@pbinfo.UUCP>
-;; Tom Perrine <Perrin@LOGICON.ARPA>
-;; Keywords: languages
-
-;; The authors distributed this without a copyright notice
-;; back in 1988, so it is in the public domain. The original included
-;; the following credit:
-
-;; Author Mick Jordan
-;; amended Peter Robinson
-
-;;; Commentary:
-
-;; A major mode for editing Modula-2 code. It provides convenient abbrevs
-;; for Modula-2 keywords, knows about the standard layout rules, and supports
-;; a native compile command.
-
-;;; Code:
-
-;;; Added by Tom Perrine (TEP)
-(defvar m2-mode-syntax-table nil
- "Syntax table in use in Modula-2 buffers.")
-
-(defvar m2-compile-command "m2c"
- "Command to compile Modula-2 programs")
-
-(defvar m2-link-command "m2l"
- "Command to link Modula-2 programs")
-
-(defvar m2-link-name nil
- "Name of the executable.")
-
-
-(if m2-mode-syntax-table
- ()
- (let ((table (make-syntax-table)))
- (modify-syntax-entry ?\\ "\\" table)
- (modify-syntax-entry ?\( ". 1" table)
- (modify-syntax-entry ?\) ". 4" table)
- (modify-syntax-entry ?* ". 23" 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)
- (setq m2-mode-syntax-table table)))
-
-;;; Added by TEP
-(defvar m2-mode-map nil
- "Keymap used in Modula-2 mode.")
-
-(if m2-mode-map ()
- (let ((map (make-sparse-keymap)))
- (define-key map "\^i" 'm2-tab)
- (define-key map "\C-cb" 'm2-begin)
- (define-key map "\C-cc" 'm2-case)
- (define-key map "\C-cd" 'm2-definition)
- (define-key map "\C-ce" 'm2-else)
- (define-key map "\C-cf" 'm2-for)
- (define-key map "\C-ch" 'm2-header)
- (define-key map "\C-ci" 'm2-if)
- (define-key map "\C-cm" 'm2-module)
- (define-key map "\C-cl" 'm2-loop)
- (define-key map "\C-co" 'm2-or)
- (define-key map "\C-cp" 'm2-procedure)
- (define-key map "\C-c\C-w" 'm2-with)
- (define-key map "\C-cr" 'm2-record)
- (define-key map "\C-cs" 'm2-stdio)
- (define-key map "\C-ct" 'm2-type)
- (define-key map "\C-cu" 'm2-until)
- (define-key map "\C-cv" 'm2-var)
- (define-key map "\C-cw" 'm2-while)
- (define-key map "\C-cx" 'm2-export)
- (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)
- (define-key map "\C-c\C-l" 'm2-link)
- (define-key map "\C-c\C-c" 'm2-compile)
- (setq m2-mode-map map)))
-
-(defvar m2-indent 5 "*This variable gives the indentation in Modula-2-Mode")
-
-;;;###autoload
-(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."
- (interactive)
- (kill-all-local-variables)
- (use-local-map m2-mode-map)
- (setq major-mode 'modula-2-mode)
- (setq mode-name "Modula-2")
- (make-local-variable 'comment-column)
- (setq comment-column 41)
- (make-local-variable 'end-comment-column)
- (setq end-comment-column 75)
- (set-syntax-table m2-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 41)
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip "/\\*+ *")
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'c-comment-indent)
- (make-local-variable 'parse-sexp-ignore-comments)
- (setq parse-sexp-ignore-comments t)
- (run-hooks 'm2-mode-hook))
-
-(defun m2-newline ()
- "Insert a newline and indent following line like previous line."
- (interactive)
- (let ((hpos (current-indentation)))
- (newline)
- (indent-to hpos)))
-
-(defun m2-tab ()
- "Indent to next tab stop."
- (interactive)
- (indent-to (* (1+ (/ (current-indentation) m2-indent)) m2-indent)))
-
-(defun m2-begin ()
- "Insert a BEGIN keyword and indent for the next line."
- (interactive)
- (insert "BEGIN")
- (m2-newline)
- (m2-tab))
-
-(defun m2-case ()
- "Build skeleton CASE statement, prompting for the <expression>."
- (interactive)
- (let ((name (read-string "Case-Expression: ")))
- (insert "CASE " name " OF")
- (m2-newline)
- (m2-newline)
- (insert "END (* case " name " *);"))
- (end-of-line 0)
- (m2-tab))
-
-(defun m2-definition ()
- "Build skeleton DEFINITION MODULE, prompting for the <module name>."
- (interactive)
- (insert "DEFINITION MODULE ")
- (let ((name (read-string "Name: ")))
- (insert name ";\n\n\n\nEND " name ".\n"))
- (previous-line 3))
-
-(defun m2-else ()
- "Insert ELSE keyword and indent for next line."
- (interactive)
- (m2-newline)
- (backward-delete-char-untabify m2-indent ())
- (insert "ELSE")
- (m2-newline)
- (m2-tab))
-
-(defun m2-for ()
- "Build skeleton FOR loop statement, 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: "))
- (if (not (string-equal by ""))
- (insert " BY " by))
- (insert " DO")
- (m2-newline)
- (m2-newline)
- (insert "END (* for " name " to " limit " *);"))
- (end-of-line 0)
- (m2-tab))
-
-(defun m2-header ()
- "Insert a comment block containing the module title, author, etc."
- (interactive)
- (insert "(*\n Title: \t")
- (insert (read-string "Title: "))
- (insert "\n Created:\t")
- (insert (current-time-string))
- (insert "\n Author: \t")
- (insert (user-full-name))
- (insert (concat "\n\t\t<" (user-login-name) "@" (system-name) ">\n"))
- (insert "*)\n\n"))
-
-(defun m2-if ()
- "Insert skeleton IF statement, prompting for <boolean-expression>."
- (interactive)
- (insert "IF ")
- (let ((thecondition (read-string "<boolean-expression>: ")))
- (insert thecondition " THEN")
- (m2-newline)
- (m2-newline)
- (insert "END (* if " thecondition " *);"))
- (end-of-line 0)
- (m2-tab))
-
-(defun m2-loop ()
- "Build skeleton LOOP (with END)."
- (interactive)
- (insert "LOOP")
- (m2-newline)
- (m2-newline)
- (insert "END (* loop *);")
- (end-of-line 0)
- (m2-tab))
-
-(defun m2-module ()
- "Build skeleton IMPLEMENTATION MODULE, prompting for <module-name>."
- (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))
-
-(defun m2-or ()
- (interactive)
- (m2-newline)
- (backward-delete-char-untabify m2-indent)
- (insert "|")
- (m2-newline)
- (m2-tab))
-
-(defun m2-procedure ()
- (interactive)
- (insert "PROCEDURE ")
- (let ((name (read-string "Name: " ))
- args)
- (insert name " (")
- (insert (read-string "Arguments: ") ")")
- (setq args (read-string "Result Type: "))
- (if (not (string-equal args ""))
- (insert " : " args))
- (insert ";")
- (m2-newline)
- (insert "BEGIN")
- (m2-newline)
- (m2-newline)
- (insert "END ")
- (insert name)
- (insert ";")
- (end-of-line 0)
- (m2-tab)))
-
-(defun m2-with ()
- (interactive)
- (insert "WITH ")
- (let ((name (read-string "Record-Type: ")))
- (insert name)
- (insert " DO")
- (m2-newline)
- (m2-newline)
- (insert "END (* with " name " *);"))
- (end-of-line 0)
- (m2-tab))
-
-(defun m2-record ()
- (interactive)
- (insert "RECORD")
- (m2-newline)
- (m2-newline)
- (insert "END (* record *);")
- (end-of-line 0)
- (m2-tab))
-
-(defun m2-stdio ()
- (interactive)
- (insert "
-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;
-
-"))
-
-(defun m2-type ()
- (interactive)
- (insert "TYPE")
- (m2-newline)
- (m2-tab))
-
-(defun m2-until ()
- (interactive)
- (insert "REPEAT")
- (m2-newline)
- (m2-newline)
- (insert "UNTIL ")
- (insert (read-string "<boolean-expression>: ") ";")
- (end-of-line 0)
- (m2-tab))
-
-(defun m2-var ()
- (interactive)
- (m2-newline)
- (insert "VAR")
- (m2-newline)
- (m2-tab))
-
-(defun m2-while ()
- (interactive)
- (insert "WHILE ")
- (let ((name (read-string "<boolean-expression>: ")))
- (insert name " DO" )
- (m2-newline)
- (m2-newline)
- (insert "END (* while " name " *);"))
- (end-of-line 0)
- (m2-tab))
-
-(defun m2-export ()
- (interactive)
- (insert "EXPORT QUALIFIED "))
-
-(defun m2-import ()
- (interactive)
- (insert "FROM ")
- (insert (read-string "Module: "))
- (insert " IMPORT "))
-
-(defun m2-begin-comment ()
- (interactive)
- (if (not (bolp))
- (indent-to comment-column 0))
- (insert "(* "))
-
-(defun m2-end-comment ()
- (interactive)
- (if (not (bolp))
- (indent-to end-comment-column))
- (insert "*)"))
-
-(defun m2-compile ()
- (interactive)
- (setq modulename (buffer-name))
- (compile (concat m2-compile-command " " modulename)))
-
-(defun m2-link ()
- (interactive)
- (setq modulename (buffer-name))
- (if m2-link-name
- (compile (concat m2-link-command " " m2-link-name))
- (compile (concat m2-link-command " "
- (setq m2-link-name (read-string "Name of executable: "
- modulename))))))
-
-(defun m2-execute-monitor-command (command)
- (let* ((shell shell-file-name)
- (csh (equal (file-name-nondirectory shell) "csh")))
- (call-process shell nil t t "-cf" (concat "exec " command))))
-
-(defun m2-visit ()
- (interactive)
- (let ((deffile nil)
- (modfile nil)
- modulename)
- (save-excursion
- (setq modulename
- (read-string "Module name: "))
- (switch-to-buffer "*Command Execution*")
- (m2-execute-monitor-command (concat "m2whereis " modulename))
- (goto-char (point-min))
- (condition-case ()
- (progn (re-search-forward "\\(.*\\.def\\) *$")
- (setq deffile (buffer-substring (match-beginning 1)
- (match-end 1))))
- (search-failed ()))
- (condition-case ()
- (progn (re-search-forward "\\(.*\\.mod\\) *$")
- (setq modfile (buffer-substring (match-beginning 1)
- (match-end 1))))
- (search-failed ()))
- (if (not (or deffile modfile))
- (error "I can find neither definition nor implementation of %s"
- modulename)))
- (cond (deffile
- (find-file deffile)
- (if modfile
- (save-excursion
- (find-file modfile))))
- (modfile
- (find-file modfile)))))
-
-(defun m2-toggle ()
- "Toggle between .mod and .def files for the module."
- (interactive)
- (cond ((string-equal (substring (buffer-name) -4) ".def")
- (find-file-other-window
- (concat (substring (buffer-name) 0 -4) ".mod")))
- ((string-equal (substring (buffer-name) -4) ".mod")
- (find-file-other-window
- (concat (substring (buffer-name) 0 -4) ".def")))
- ((string-equal (substring (buffer-name) -3) ".mi")
- (find-file-other-window
- (concat (substring (buffer-name) 0 -3) ".md")))
- ((string-equal (substring (buffer-name) -3) ".md")
- (find-file-other-window
- (concat (substring (buffer-name) 0 -3) ".mi")))))
-
-;;; modula2.el ends here
diff --git a/lisp/progmodes/pascal.el b/lisp/progmodes/pascal.el
deleted file mode 100644
index 1055e692689..00000000000
--- a/lisp/progmodes/pascal.el
+++ /dev/null
@@ -1,1560 +0,0 @@
-;;; pascal.el --- major mode for editing pascal source in Emacs
-
-;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Espen Skoglund (espensk@stud.cs.uit.no)
-;; Keywords: languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; USAGE
-;; =====
-
-;; Emacs should enter Pascal mode when you find a Pascal source file.
-;; When you have entered Pascal mode, you may get more info by pressing
-;; C-h m. You may also get online help describing various functions by:
-;; C-h f <Name of function you want described>
-
-;; If you want to customize Pascal mode to fit you better, you may add
-;; these lines (the values of the variables presented here are the defaults):
-;;
-;; ;; User customization for Pascal mode
-;; (setq pascal-indent-level 3
-;; pascal-case-indent 2
-;; pascal-auto-newline nil
-;; pascal-tab-always-indent t
-;; pascal-auto-endcomments t
-;; pascal-auto-lineup '(all)
-;; pascal-toggle-completions nil
-;; pascal-type-keywords '("array" "file" "packed" "char"
-;; "integer" "real" "string" "record")
-;; pascal-start-keywords '("begin" "end" "function" "procedure"
-;; "repeat" "until" "while" "read" "readln"
-;; "reset" "rewrite" "write" "writeln")
-;; pascal-separator-keywords '("downto" "else" "mod" "div" "then"))
-
-;; KNOWN BUGS / BUGREPORTS
-;; =======================
-;; As far as I know, there are no bugs in the current version of this
-;; package. This may not be true however, since I never use this mode
-;; myself and therefore would never notice them anyway. If you do
-;; find any bugs, you may submit them to: espensk@stud.cs.uit.no
-;; as well as to bug-gnu-emacs@prep.ai.mit.edu.
-
-;;; Code:
-
-(defvar pascal-mode-abbrev-table nil
- "Abbrev table in use in Pascal-mode buffers.")
-(define-abbrev-table 'pascal-mode-abbrev-table ())
-
-(defvar pascal-mode-map ()
- "Keymap used in Pascal mode.")
-(if pascal-mode-map
- ()
- (setq pascal-mode-map (make-sparse-keymap))
- (define-key pascal-mode-map ";" 'electric-pascal-semi-or-dot)
- (define-key pascal-mode-map "." 'electric-pascal-semi-or-dot)
- (define-key pascal-mode-map ":" 'electric-pascal-colon)
- (define-key pascal-mode-map "=" 'electric-pascal-equal)
- (define-key pascal-mode-map "#" 'electric-pascal-hash)
- (define-key pascal-mode-map "\r" 'electric-pascal-terminate-line)
- (define-key pascal-mode-map "\t" 'electric-pascal-tab)
- (define-key pascal-mode-map "\M-\t" 'pascal-complete-word)
- (define-key pascal-mode-map "\M-?" 'pascal-show-completions)
- (define-key pascal-mode-map "\177" 'backward-delete-char-untabify)
- (define-key pascal-mode-map "\M-\C-h" 'pascal-mark-defun)
- (define-key pascal-mode-map "\C-c\C-b" 'pascal-insert-block)
- (define-key pascal-mode-map "\M-*" 'pascal-star-comment)
- (define-key pascal-mode-map "\C-c\C-c" 'pascal-comment-area)
- (define-key pascal-mode-map "\C-c\C-u" 'pascal-uncomment-area)
- (define-key pascal-mode-map "\M-\C-a" 'pascal-beg-of-defun)
- (define-key pascal-mode-map "\M-\C-e" 'pascal-end-of-defun)
- (define-key pascal-mode-map "\C-c\C-d" 'pascal-goto-defun)
- (define-key pascal-mode-map "\C-c\C-o" 'pascal-outline)
-;;; A command to change the whole buffer won't be used terribly
-;;; often, so no need for a key binding.
-; (define-key pascal-mode-map "\C-cd" 'pascal-downcase-keywords)
-; (define-key pascal-mode-map "\C-cu" 'pascal-upcase-keywords)
-; (define-key pascal-mode-map "\C-cc" 'pascal-capitalize-keywords)
- )
-
-(defvar pascal-imenu-generic-expression
- '("^[ \t]*\\(function\\|procedure\\)[ \t\n]+\\([a-zA-Z0-9_.:]+\\)" . (2))
- "Imenu expression for Pascal-mode. See `imenu-generic-expression'.")
-
-(defvar pascal-keywords
- '("and" "array" "begin" "case" "const" "div" "do" "downto" "else" "end"
- "file" "for" "function" "goto" "if" "in" "label" "mod" "nil" "not" "of"
- "or" "packed" "procedure" "program" "record" "repeat" "set" "then" "to"
- "type" "until" "var" "while" "with"
- ;; The following are not standard in pascal, but widely used.
- "get" "put" "input" "output" "read" "readln" "reset" "rewrite" "write"
- "writeln"))
-
-;;;
-;;; Regular expressions used to calculate indent, etc.
-;;;
-(defconst pascal-symbol-re "\\<[a-zA-Z_][a-zA-Z_0-9.]*\\>")
-(defconst pascal-beg-block-re "\\<\\(begin\\|case\\|record\\|repeat\\)\\>")
-(defconst pascal-end-block-re "\\<\\(end\\|until\\)\\>")
-(defconst pascal-declaration-re "\\<\\(const\\|label\\|type\\|var\\)\\>")
-(defconst pascal-defun-re "\\<\\(function\\|procedure\\|program\\)\\>")
-(defconst pascal-sub-block-re "\\<\\(if\\|else\\|for\\|while\\|with\\)\\>")
-(defconst pascal-noindent-re "\\<\\(begin\\|end\\|until\\|else\\)\\>")
-(defconst pascal-nosemi-re "\\<\\(begin\\|repeat\\|then\\|do\\|else\\)\\>")
-(defconst pascal-autoindent-lines-re
- "\\<\\(label\\|var\\|type\\|const\\|until\\|end\\|begin\\|repeat\\|else\\)\\>")
-
-;;; Strings used to mark beginning and end of excluded text
-(defconst pascal-exclude-str-start "{-----\\/----- EXCLUDED -----\\/-----")
-(defconst pascal-exclude-str-end " -----/\\----- EXCLUDED -----/\\-----}")
-
-(defvar pascal-mode-syntax-table nil
- "Syntax table in use in Pascal-mode buffers.")
-
-(if pascal-mode-syntax-table
- ()
- (setq pascal-mode-syntax-table (make-syntax-table))
- (modify-syntax-entry ?\\ "." pascal-mode-syntax-table)
- (modify-syntax-entry ?( "()1" pascal-mode-syntax-table)
- (modify-syntax-entry ?) ")(4" pascal-mode-syntax-table)
- (modify-syntax-entry ?* ". 23" pascal-mode-syntax-table)
- (modify-syntax-entry ?{ "<" pascal-mode-syntax-table)
- (modify-syntax-entry ?} ">" pascal-mode-syntax-table)
- (modify-syntax-entry ?+ "." pascal-mode-syntax-table)
- (modify-syntax-entry ?- "." pascal-mode-syntax-table)
- (modify-syntax-entry ?= "." pascal-mode-syntax-table)
- (modify-syntax-entry ?% "." pascal-mode-syntax-table)
- (modify-syntax-entry ?< "." pascal-mode-syntax-table)
- (modify-syntax-entry ?> "." pascal-mode-syntax-table)
- (modify-syntax-entry ?& "." pascal-mode-syntax-table)
- (modify-syntax-entry ?| "." pascal-mode-syntax-table)
- (modify-syntax-entry ?_ "w" pascal-mode-syntax-table)
- (modify-syntax-entry ?\' "\"" pascal-mode-syntax-table))
-
-(defvar pascal-font-lock-keywords
- (list
- '("^[ \t]*\\(function\\|pro\\(cedure\\|gram\\)\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
-; ("type" "const" "real" "integer" "char" "boolean" "var"
-; "record" "array" "file")
- (cons (concat "\\<\\(array\\|boolean\\|c\\(har\\|onst\\)\\|file\\|"
- "integer\\|re\\(al\\|cord\\)\\|type\\|var\\)\\>")
- 'font-lock-type-face)
- '("\\<\\(label\\|external\\|forward\\)\\>" . font-lock-reference-face)
- '("\\<\\([0-9]+\\)[ \t]*:" 1 font-lock-reference-face)
-; ("of" "to" "for" "if" "then" "else" "case" "while"
-; "do" "until" "and" "or" "not" "in" "with" "repeat" "begin" "end")
- (concat "\\<\\("
- "and\\|begin\\|case\\|do\\|e\\(lse\\|nd\\)\\|for\\|i[fn]\\|"
- "not\\|o[fr]\\|repeat\\|t\\(hen\\|o\\)\\|until\\|w\\(hile\\|ith\\)"
- "\\)\\>")
- '("\\<\\(goto\\)\\>[ \t]*\\([0-9]+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-reference-face nil t)))
- "Additional expressions to highlight in Pascal mode.")
-
-(defvar pascal-indent-level 3
- "*Indentation of Pascal statements with respect to containing block.")
-
-(defvar pascal-case-indent 2
- "*Indentation for case statements.")
-
-(defvar pascal-auto-newline nil
- "*Non-nil means automatically newline after semicolons and the punctuation
-mark after an end.")
-
-(defvar pascal-tab-always-indent t
- "*Non-nil means TAB in Pascal mode should always reindent the current line,
-regardless of where in the line point is when the TAB command is used.")
-
-(defvar pascal-auto-endcomments t
- "*Non-nil means a comment { ... } is set after the ends which ends cases and
-functions. The name of the function or case will be set between the braces.")
-
-(defvar pascal-auto-lineup '(all)
- "*List of contexts where auto lineup of :'s or ='s should be done.
-Elements can be of type: 'paramlist', 'declaration' or 'case', which will
-do auto lineup in parameterlist, declarations or case-statements
-respectively. The word 'all' will do all lineups. '(case paramlist) for
-instance will do lineup in case-statements and parameterlist, while '(all)
-will do all lineups.")
-
-(defvar pascal-toggle-completions nil
- "*Non-nil means \\<pascal-mode-map>\\[pascal-complete-word] should try all possible completions one by one.
-Repeated use of \\[pascal-complete-word] will show you all of them.
-Normally, when there is more than one possible completion,
-it displays a list of all possible completions.")
-
-(defvar pascal-type-keywords
- '("array" "file" "packed" "char" "integer" "real" "string" "record")
- "*Keywords for types used when completing a word in a declaration or parmlist.
-\(eg. integer, real, char.) The types defined within the Pascal program
-will be completed runtime, and should not be added to this list.")
-
-(defvar pascal-start-keywords
- '("begin" "end" "function" "procedure" "repeat" "until" "while"
- "read" "readln" "reset" "rewrite" "write" "writeln")
- "*Keywords to complete when standing at the first word of a statement.
-\(eg. begin, repeat, until, readln.)
-The procedures and variables defined within the Pascal program
-will be completed runtime and should not be added to this list.")
-
-(defvar pascal-separator-keywords
- '("downto" "else" "mod" "div" "then")
- "*Keywords to complete when NOT standing at the first word of a statement.
-\(eg. downto, else, mod, then.)
-Variables and function names defined within the
-Pascal program are completed runtime and should not be added to this list.")
-
-;;;
-;;; Macros
-;;;
-
-(defsubst pascal-get-beg-of-line (&optional arg)
- (save-excursion
- (beginning-of-line arg)
- (point)))
-
-(defsubst pascal-get-end-of-line (&optional arg)
- (save-excursion
- (end-of-line arg)
- (point)))
-
-(defun pascal-declaration-end ()
- (let ((nest 1))
- (while (and (> nest 0)
- (re-search-forward
- "[:=]\\|\\(\\<record\\>\\)\\|\\(\\<end\\>\\)"
- (save-excursion (end-of-line 2) (point)) t))
- (cond ((match-beginning 1) (setq nest (1+ nest)))
- ((match-beginning 2) (setq nest (1- nest)))
- ((looking-at "[^(\n]+)") (setq nest 0))))))
-
-
-(defun pascal-declaration-beg ()
- (let ((nest 1))
- (while (and (> nest 0)
- (re-search-backward "[:=]\\|\\<\\(type\\|var\\|label\\|const\\)\\>\\|\\(\\<record\\>\\)\\|\\(\\<end\\>\\)" (pascal-get-beg-of-line 0) t))
- (cond ((match-beginning 1) (setq nest 0))
- ((match-beginning 2) (setq nest (1- nest)))
- ((match-beginning 3) (setq nest (1+ nest)))))
- (= nest 0)))
-
-
-(defsubst pascal-within-string ()
- (save-excursion
- (nth 3 (parse-partial-sexp (pascal-get-beg-of-line) (point)))))
-
-
-;;;###autoload
-(defun pascal-mode ()
- "Major mode for editing Pascal code. \\<pascal-mode-map>
-TAB indents for Pascal code. Delete converts tabs to spaces as it moves back.
-
-\\[pascal-complete-word] completes the word around current point with respect \
-to position in code
-\\[pascal-show-completions] shows all possible completions at this point.
-
-Other useful functions are:
-
-\\[pascal-mark-defun]\t- Mark function.
-\\[pascal-insert-block]\t- insert begin ... end;
-\\[pascal-star-comment]\t- insert (* ... *)
-\\[pascal-comment-area]\t- Put marked area in a comment, fixing nested comments.
-\\[pascal-uncomment-area]\t- Uncomment an area commented with \
-\\[pascal-comment-area].
-\\[pascal-beg-of-defun]\t- Move to beginning of current function.
-\\[pascal-end-of-defun]\t- Move to end of current function.
-\\[pascal-goto-defun]\t- Goto function prompted for in the minibuffer.
-\\[pascal-outline]\t- Enter pascal-outline-mode (see also pascal-outline).
-
-Variables controlling indentation/edit style:
-
- pascal-indent-level (default 3)
- Indentation of Pascal statements with respect to containing block.
- pascal-case-indent (default 2)
- Indentation for case statements.
- pascal-auto-newline (default nil)
- Non-nil means automatically newline after semicolons and the punctuation
- mark after an end.
- pascal-tab-always-indent (default t)
- Non-nil means TAB in Pascal mode should always reindent the current line,
- regardless of where in the line point is when the TAB command is used.
- pascal-auto-endcomments (default t)
- Non-nil means a comment { ... } is set after the ends which ends cases and
- functions. The name of the function or case will be set between the braces.
- pascal-auto-lineup (default t)
- List of contexts where auto lineup of :'s or ='s hould be done.
-
-See also the user variables pascal-type-keywords, pascal-start-keywords and
-pascal-separator-keywords.
-
-Turning on Pascal mode calls the value of the variable pascal-mode-hook with
-no args, if that value is non-nil."
- (interactive)
- (kill-all-local-variables)
- (use-local-map pascal-mode-map)
- (setq major-mode 'pascal-mode)
- (setq mode-name "Pascal")
- (setq local-abbrev-table pascal-mode-abbrev-table)
- (set-syntax-table pascal-mode-syntax-table)
- (make-local-variable 'indent-line-function)
- (setq indent-line-function 'pascal-indent-line)
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'pascal-indent-comment)
- (make-local-variable 'parse-sexp-ignore-comments)
- (setq parse-sexp-ignore-comments nil)
- (make-local-variable 'case-fold-search)
- (setq case-fold-search t)
- (make-local-variable 'comment-start)
- (setq comment-start "{")
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip "(\\*+ *\\|{ *")
- (make-local-variable 'comment-end)
- (setq comment-end "}")
- ;; Font lock support
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(pascal-font-lock-keywords nil t))
- ;; Imenu support
- (make-local-variable 'imenu-generic-expression)
- (setq imenu-generic-expression pascal-imenu-generic-expression)
- (run-hooks 'pascal-mode-hook))
-
-
-
-;;;
-;;; Electric functions
-;;;
-(defun electric-pascal-terminate-line ()
- "Terminate line and indent next line."
- (interactive)
- ;; First, check if current line should be indented
- (save-excursion
- (beginning-of-line)
- (skip-chars-forward " \t")
- (if (looking-at pascal-autoindent-lines-re)
- (pascal-indent-line)))
- (delete-horizontal-space) ; Removes trailing whitespaces
- (newline)
- ;; Indent next line
- (pascal-indent-line)
- ;; Maybe we should set some endcomments
- (if pascal-auto-endcomments
- (pascal-set-auto-comments))
- ;; Check if we shall indent inside comment
- (let ((setstar nil))
- (save-excursion
- (forward-line -1)
- (skip-chars-forward " \t")
- (cond ((looking-at "\\*[ \t]+)")
- ;; Delete region between `*' and `)' if there is only whitespaces.
- (forward-char 1)
- (delete-horizontal-space))
- ((and (looking-at "(\\*\\|\\*[^)]")
- (not (save-excursion
- (search-forward "*)" (pascal-get-end-of-line) t))))
- (setq setstar t))))
- ;; If last line was a star comment line then this one shall be too.
- (if (null setstar)
- (pascal-indent-line)
- (insert "* "))))
-
-
-(defun electric-pascal-semi-or-dot ()
- "Insert `;' or `.' character and reindent the line."
- (interactive)
- (insert last-command-char)
- (save-excursion
- (beginning-of-line)
- (pascal-indent-line))
- (if pascal-auto-newline
- (electric-pascal-terminate-line)))
-
-(defun electric-pascal-colon ()
- "Insert `:' and do all indentions except line indent on this line."
- (interactive)
- (insert last-command-char)
- ;; Do nothing if within string.
- (if (pascal-within-string)
- ()
- (save-excursion
- (beginning-of-line)
- (pascal-indent-line))
- (let ((pascal-tab-always-indent nil))
- (pascal-indent-command))))
-
-(defun electric-pascal-equal ()
- "Insert `=', and do indention if within type declaration."
- (interactive)
- (insert last-command-char)
- (if (eq (car (pascal-calculate-indent)) 'declaration)
- (let ((pascal-tab-always-indent nil))
- (pascal-indent-command))))
-
-(defun electric-pascal-hash ()
- "Insert `#', and indent to column 0 if this is a CPP directive."
- (interactive)
- (insert last-command-char)
- (if (save-excursion (beginning-of-line) (looking-at "^[ \t]*#"))
- (save-excursion (beginning-of-line)
- (delete-horizontal-space))))
-
-(defun electric-pascal-tab ()
- "Function called when TAB is pressed in Pascal mode."
- (interactive)
- ;; Do nothing if within a string or in a CPP directive.
- (if (or (pascal-within-string)
- (and (not (bolp))
- (save-excursion (beginning-of-line) (eq (following-char) ?#))))
- (insert "\t")
- ;; If pascal-tab-always-indent, indent the beginning of the line.
- (if pascal-tab-always-indent
- (save-excursion
- (beginning-of-line)
- (pascal-indent-line))
- (if (save-excursion
- (skip-chars-backward " \t")
- (bolp))
- (pascal-indent-line)
- (insert "\t")))
- (pascal-indent-command)))
-
-
-
-;;;
-;;; Interactive functions
-;;;
-(defun pascal-insert-block ()
- "Insert Pascal begin ... end; block in the code with right indentation."
- (interactive)
- (pascal-indent-line)
- (insert "begin")
- (electric-pascal-terminate-line)
- (save-excursion
- (electric-pascal-terminate-line)
- (insert "end;")
- (beginning-of-line)
- (pascal-indent-line)))
-
-(defun pascal-star-comment ()
- "Insert Pascal star comment at point."
- (interactive)
- (pascal-indent-line)
- (insert "(*")
- (electric-pascal-terminate-line)
- (save-excursion
- (electric-pascal-terminate-line)
- (delete-horizontal-space)
- (insert ")"))
- (insert " "))
-
-(defun pascal-mark-defun ()
- "Mark the current pascal function (or procedure).
-This puts the mark at the end, and point at the beginning."
- (interactive)
- (push-mark (point))
- (pascal-end-of-defun)
- (push-mark (point))
- (pascal-beg-of-defun)
- (if (fboundp 'zmacs-activate-region)
- (zmacs-activate-region)))
-
-(defun pascal-comment-area (start end)
- "Put the region into a Pascal comment.
-The comments that are in this area are \"deformed\":
-`*)' becomes `!(*' and `}' becomes `!{'.
-These deformed comments are returned to normal if you use
-\\[pascal-uncomment-area] to undo the commenting.
-
-The commented area starts with `pascal-exclude-str-start', and ends with
-`pascal-include-str-end'. But if you change these variables,
-\\[pascal-uncomment-area] won't recognize the comments."
- (interactive "r")
- (save-excursion
- ;; Insert start and endcomments
- (goto-char end)
- (if (and (save-excursion (skip-chars-forward " \t") (eolp))
- (not (save-excursion (skip-chars-backward " \t") (bolp))))
- (forward-line 1)
- (beginning-of-line))
- (insert pascal-exclude-str-end)
- (setq end (point))
- (newline)
- (goto-char start)
- (beginning-of-line)
- (insert pascal-exclude-str-start)
- (newline)
- ;; Replace end-comments within commented area
- (goto-char end)
- (save-excursion
- (while (re-search-backward "\\*)" start t)
- (replace-match "!(*" t t)))
- (save-excursion
- (while (re-search-backward "}" start t)
- (replace-match "!{" t t)))))
-
-(defun pascal-uncomment-area ()
- "Uncomment a commented area; change deformed comments back to normal.
-This command does nothing if the pointer is not in a commented
-area. See also `pascal-comment-area'."
- (interactive)
- (save-excursion
- (let ((start (point))
- (end (point)))
- ;; Find the boundaries of the comment
- (save-excursion
- (setq start (progn (search-backward pascal-exclude-str-start nil t)
- (point)))
- (setq end (progn (search-forward pascal-exclude-str-end nil t)
- (point))))
- ;; Check if we're really inside a comment
- (if (or (equal start (point)) (<= end (point)))
- (message "Not standing within commented area.")
- (progn
- ;; Remove endcomment
- (goto-char end)
- (beginning-of-line)
- (let ((pos (point)))
- (end-of-line)
- (delete-region pos (1+ (point))))
- ;; Change comments back to normal
- (save-excursion
- (while (re-search-backward "!{" start t)
- (replace-match "}" t t)))
- (save-excursion
- (while (re-search-backward "!(\\*" start t)
- (replace-match "*)" t t)))
- ;; Remove startcomment
- (goto-char start)
- (beginning-of-line)
- (let ((pos (point)))
- (end-of-line)
- (delete-region pos (1+ (point)))))))))
-
-(defun pascal-beg-of-defun ()
- "Move backward to the beginning of the current function or procedure."
- (interactive)
- (catch 'found
- (if (not (looking-at (concat "\\s \\|\\s)\\|" pascal-defun-re)))
- (forward-sexp 1))
- (let ((nest 0) (max -1) (func 0)
- (reg (concat pascal-beg-block-re "\\|"
- pascal-end-block-re "\\|"
- pascal-defun-re)))
- (while (re-search-backward reg nil 'move)
- (cond ((let ((state (save-excursion
- (parse-partial-sexp (point-min) (point)))))
- (or (nth 3 state) (nth 4 state))) ; Inside string or comment
- ())
- ((match-end 1) ; begin|case|record|repeat
- (if (and (looking-at "\\<record\\>") (>= max 0))
- (setq func (1- func)))
- (setq nest (1+ nest)
- max (max nest max)))
- ((match-end 2) ; end|until
- (if (and (= nest max) (>= max 0))
- (setq func (1+ func)))
- (setq nest (1- nest)))
- ((match-end 3) ; function|procedure
- (if (= 0 func)
- (throw 'found t)
- (setq func (1- func)))))))
- nil))
-
-(defun pascal-end-of-defun ()
- "Move forward to the end of the current function or procedure."
- (interactive)
- (if (looking-at "\\s ")
- (forward-sexp 1))
- (if (not (looking-at pascal-defun-re))
- (pascal-beg-of-defun))
- (forward-char 1)
- (let ((nest 0) (func 1)
- (reg (concat pascal-beg-block-re "\\|"
- pascal-end-block-re "\\|"
- pascal-defun-re)))
- (while (and (/= func 0)
- (re-search-forward reg nil 'move))
- (cond ((let ((state (save-excursion
- (parse-partial-sexp (point-min) (point)))))
- (or (nth 3 state) (nth 4 state))) ; Inside string or comment
- ())
- ((match-end 1)
- (setq nest (1+ nest))
- (if (save-excursion
- (goto-char (match-beginning 0))
- (looking-at "\\<record\\>"))
- (setq func (1+ func))))
- ((match-end 2)
- (setq nest (1- nest))
- (if (= nest 0)
- (setq func (1- func))))
- ((match-end 3)
- (setq func (1+ func))))))
- (forward-line 1))
-
-(defun pascal-end-of-statement ()
- "Move forward to end of current statement."
- (interactive)
- (let ((parse-sexp-ignore-comments t)
- (nest 0) pos
- (regexp (concat "\\(" pascal-beg-block-re "\\)\\|\\("
- pascal-end-block-re "\\)")))
- (if (not (looking-at "[ \t\n]")) (forward-sexp -1))
- (or (looking-at pascal-beg-block-re)
- ;; Skip to end of statement
- (setq pos (catch 'found
- (while t
- (forward-sexp 1)
- (cond ((looking-at "[ \t]*;")
- (skip-chars-forward "^;")
- (forward-char 1)
- (throw 'found (point)))
- ((save-excursion
- (forward-sexp -1)
- (looking-at pascal-beg-block-re))
- (goto-char (match-beginning 0))
- (throw 'found nil))
- ((eobp)
- (throw 'found (point))))))))
- (if (not pos)
- ;; Skip a whole block
- (catch 'found
- (while t
- (re-search-forward regexp nil 'move)
- (setq nest (if (match-end 1)
- (1+ nest)
- (1- nest)))
- (cond ((eobp)
- (throw 'found (point)))
- ((= 0 nest)
- (throw 'found (pascal-end-of-statement))))))
- pos)))
-
-(defun pascal-downcase-keywords ()
- "Downcase all Pascal keywords in the buffer."
- (interactive)
- (pascal-change-keywords 'downcase-word))
-
-(defun pascal-upcase-keywords ()
- "Upcase all Pascal keywords in the buffer."
- (interactive)
- (pascal-change-keywords 'upcase-word))
-
-(defun pascal-capitalize-keywords ()
- "Capitalize all Pascal keywords in the buffer."
- (interactive)
- (pascal-change-keywords 'capitalize-word))
-
-;; Change the keywords according to argument.
-(defun pascal-change-keywords (change-word)
- (save-excursion
- (let ((keyword-re (concat "\\<\\("
- (mapconcat 'identity pascal-keywords "\\|")
- "\\)\\>")))
- (goto-char (point-min))
- (while (re-search-forward keyword-re nil t)
- (funcall change-word -1)))))
-
-
-
-;;;
-;;; Other functions
-;;;
-(defun pascal-set-auto-comments ()
- "Insert `{ case }' or `{ NAME }' on this line if appropriate.
-Insert `{ case }' if there is an `end' on the line which
-ends a case block. Insert `{ NAME }' if there is an `end'
-on the line which ends a function or procedure named NAME."
- (save-excursion
- (forward-line -1)
- (skip-chars-forward " \t")
- (if (and (looking-at "\\<end;")
- (not (save-excursion
- (end-of-line)
- (search-backward "{" (pascal-get-beg-of-line) t))))
- (let ((type (car (pascal-calculate-indent))))
- (if (eq type 'declaration)
- ()
- (if (eq type 'case)
- ;; This is a case block
- (progn
- (end-of-line)
- (delete-horizontal-space)
- (insert " { case }"))
- (let ((nest 1))
- ;; Check if this is the end of a function
- (save-excursion
- (while (not (or (looking-at pascal-defun-re) (bobp)))
- (backward-sexp 1)
- (cond ((looking-at pascal-beg-block-re)
- (setq nest (1- nest)))
- ((looking-at pascal-end-block-re)
- (setq nest (1+ nest)))))
- (if (bobp)
- (setq nest 1)))
- (if (zerop nest)
- (progn
- (end-of-line)
- (delete-horizontal-space)
- (insert " { ")
- (let (b e)
- (save-excursion
- (setq b (progn (pascal-beg-of-defun)
- (skip-chars-forward "^ \t")
- (skip-chars-forward " \t")
- (point))
- e (progn (skip-chars-forward "a-zA-Z0-9_")
- (point))))
- (insert-buffer-substring (current-buffer) b e))
- (insert " }"))))))))))
-
-
-
-;;;
-;;; Indentation
-;;;
-(defconst pascal-indent-alist
- '((block . (+ ind pascal-indent-level))
- (case . (+ ind pascal-case-indent))
- (caseblock . ind) (cpp . 0)
- (declaration . (+ ind pascal-indent-level))
- (paramlist . (pascal-indent-paramlist t))
- (comment . (pascal-indent-comment t))
- (defun . ind) (contexp . ind)
- (unknown . 0) (string . 0)))
-
-(defun pascal-indent-command ()
- "Indent for special part of code."
- (let* ((indent-str (pascal-calculate-indent))
- (type (car indent-str))
- (ind (car (cdr indent-str))))
- (cond ((and (eq type 'paramlist)
- (or (memq 'all pascal-auto-lineup)
- (memq 'paramlist pascal-auto-lineup)))
- (pascal-indent-paramlist)
- (pascal-indent-paramlist))
- ((and (eq type 'declaration)
- (or (memq 'all pascal-auto-lineup)
- (memq 'declaration pascal-auto-lineup)))
- (pascal-indent-declaration))
- ((and (eq type 'case) (not (looking-at "^[ \t]*$"))
- (or (memq 'all pascal-auto-lineup)
- (memq 'case pascal-auto-lineup)))
- (pascal-indent-case)))
- (if (looking-at "[ \t]+$")
- (skip-chars-forward " \t"))))
-
-(defun pascal-indent-line ()
- "Indent current line as a Pascal statement."
- (let* ((indent-str (pascal-calculate-indent))
- (type (car indent-str))
- (ind (car (cdr indent-str))))
- (if (looking-at "^[0-9a-zA-Z]+[ \t]*:[^=]")
- (search-forward ":" nil t))
- (delete-horizontal-space)
- ;; Some things should not be indented
- (if (or (and (eq type 'declaration) (looking-at pascal-declaration-re))
- (eq type 'cpp)
- (looking-at pascal-defun-re))
- ()
- ;; Other things should have no extra indent
- (if (looking-at pascal-noindent-re)
- (indent-to ind)
- ;; But most lines are treated this way:
- (indent-to (eval (cdr (assoc type pascal-indent-alist))))
- ))))
-
-(defun pascal-calculate-indent ()
- "Calculate the indent of the current Pascal line.
-Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
- (save-excursion
- (let* ((parse-sexp-ignore-comments t)
- (oldpos (point))
- (state (save-excursion (parse-partial-sexp (point-min) (point))))
- (nest 0) (par 0) (complete (looking-at "[ \t]*end\\>"))
- (elsed (looking-at "[ \t]*else\\>"))
- (type (catch 'nesting
- ;; Check if inside a string, comment or parenthesis
- (cond ((nth 3 state) (throw 'nesting 'string))
- ((nth 4 state) (throw 'nesting 'comment))
- ((> (car state) 0)
- (goto-char (scan-lists (point) -1 (car state)))
- (setq par (1+ (current-column))))
- ((save-excursion (beginning-of-line)
- (eq (following-char) ?#))
- (throw 'nesting 'cpp)))
- ;; Loop until correct indent is found
- (while t
- (backward-sexp 1)
- (cond (;--Escape from case statements
- (and (looking-at "[A-Za-z0-9]+[ \t]*:[^=]")
- (not complete)
- (save-excursion (skip-chars-backward " \t")
- (bolp))
- (= (save-excursion
- (end-of-line) (backward-sexp) (point))
- (point))
- (> (save-excursion (goto-char oldpos)
- (beginning-of-line)
- (point))
- (point)))
- (throw 'nesting 'caseblock))
- (;--Nest block outwards
- (looking-at pascal-beg-block-re)
- (if (= nest 0)
- (cond ((looking-at "case\\>")
- (throw 'nesting 'case))
- ((looking-at "record\\>")
- (throw 'nesting 'declaration))
- (t (throw 'nesting 'block)))
- (setq nest (1- nest))))
- (;--Nest block inwards
- (looking-at pascal-end-block-re)
- (if (and (looking-at "end\\s ")
- elsed (not complete))
- (throw 'nesting 'block))
- (setq complete t
- nest (1+ nest)))
- (;--Defun (or parameter list)
- (looking-at pascal-defun-re)
- (if (= 0 par)
- (throw 'nesting 'defun)
- (setq par 0)
- (let ((n 0))
- (while (re-search-forward
- "\\(\\<record\\>\\)\\|\\<end\\>"
- oldpos t)
- (if (match-end 1)
- (setq n (1+ n)) (setq n (1- n))))
- (if (> n 0)
- (throw 'nesting 'declaration)
- (throw 'nesting 'paramlist)))))
- (;--Declaration part
- (looking-at pascal-declaration-re)
- (if (save-excursion
- (goto-char oldpos)
- (forward-line -1)
- (looking-at "^[ \t]*$"))
- (throw 'nesting 'unknown)
- (throw 'nesting 'declaration)))
- (;--If, else or while statement
- (and (not complete)
- (looking-at pascal-sub-block-re))
- (throw 'nesting 'block))
- (;--Found complete statement
- (save-excursion (forward-sexp 1)
- (= (following-char) ?\;))
- (setq complete t))
- (;--No known statements
- (bobp)
- (throw 'nesting 'unknown))
- )))))
-
- ;; Return type of block and indent level.
- (if (> par 0) ; Unclosed Parenthesis
- (list 'contexp par)
- (list type (pascal-indent-level))))))
-
-(defun pascal-indent-level ()
- "Return the indent-level the current statement has.
-Do not count labels, case-statements or records."
- (save-excursion
- (beginning-of-line)
- (if (looking-at "[ \t]*[0-9a-zA-Z]+[ \t]*:[^=]")
- (search-forward ":" nil t)
- (if (looking-at ".*=[ \t]*record\\>")
- (search-forward "=" nil t)))
- (skip-chars-forward " \t")
- (current-column)))
-
-(defun pascal-indent-comment (&optional arg)
- "Indent current line as comment.
-If optional arg is non-nil, just return the
-column number the line should be indented to."
- (let* ((stcol (save-excursion
- (re-search-backward "(\\*\\|{" nil t)
- (1+ (current-column)))))
- (if arg stcol
- (delete-horizontal-space)
- (indent-to stcol))))
-
-(defun pascal-indent-case ()
- "Indent within case statements."
- (let ((savepos (point-marker))
- (end (prog2
- (end-of-line)
- (point-marker)
- (re-search-backward "\\<case\\>" nil t)))
- (beg (point)) oldpos
- (ind 0))
- ;; Get right indent
- (while (< (point) (marker-position end))
- (if (re-search-forward
- "^[ \t]*[^ \t,:]+[ \t]*\\(,[ \t]*[^ \t,:]+[ \t]*\\)*:"
- (marker-position end) 'move)
- (forward-char -1))
- (if (< (point) (marker-position end))
- (progn
- (delete-horizontal-space)
- (if (> (current-column) ind)
- (setq ind (current-column)))
- (pascal-end-of-statement))))
- (goto-char beg)
- (setq oldpos (marker-position end))
- ;; Indent all case statements
- (while (< (point) (marker-position end))
- (if (re-search-forward
- "^[ \t]*[^][ \t,\\.:]+[ \t]*\\(,[ \t]*[^ \t,:]+[ \t]*\\)*:"
- (marker-position end) 'move)
- (forward-char -1))
- (indent-to (1+ ind))
- (if (/= (following-char) ?:)
- ()
- (forward-char 1)
- (delete-horizontal-space)
- (insert " "))
- (setq oldpos (point))
- (pascal-end-of-statement))
- (goto-char savepos)))
-
-(defun pascal-indent-paramlist (&optional arg)
- "Indent current line in parameterlist.
-If optional arg is non-nil, just return the
-indent of the current line in parameterlist."
- (save-excursion
- (let* ((oldpos (point))
- (stpos (progn (goto-char (scan-lists (point) -1 1)) (point)))
- (stcol (1+ (current-column)))
- (edpos (progn (pascal-declaration-end)
- (search-backward ")" (pascal-get-beg-of-line) t)
- (point)))
- (usevar (re-search-backward "\\<var\\>" stpos t)))
- (if arg (progn
- ;; If arg, just return indent
- (goto-char oldpos)
- (beginning-of-line)
- (if (or (not usevar) (looking-at "[ \t]*var\\>"))
- stcol (+ 4 stcol)))
- (goto-char stpos)
- (forward-char 1)
- (delete-horizontal-space)
- (if (and usevar (not (looking-at "var\\>")))
- (indent-to (+ 4 stcol)))
- (pascal-indent-declaration nil stpos edpos)))))
-
-(defun pascal-indent-declaration (&optional arg start end)
- "Indent current lines as declaration, lining up the `:'s or `='s."
- (let ((pos (point-marker)))
- (if (and (not (or arg start)) (not (pascal-declaration-beg)))
- ()
- (let ((lineup (if (or (looking-at "\\<var\\>\\|\\<record\\>") arg start)
- ":" "="))
- (stpos (if start start
- (forward-word 2) (backward-word 1) (point)))
- (edpos (set-marker (make-marker)
- (if end end
- (max (progn (pascal-declaration-end)
- (point))
- pos))))
- ind)
-
- (goto-char stpos)
- ;; Indent lines in record block
- (if arg
- (while (<= (point) (marker-position edpos))
- (beginning-of-line)
- (delete-horizontal-space)
- (if (looking-at "end\\>")
- (indent-to arg)
- (indent-to (+ arg pascal-indent-level)))
- (forward-line 1)))
-
- ;; Do lineup
- (setq ind (pascal-get-lineup-indent stpos edpos lineup))
- (goto-char stpos)
- (while (and (<= (point) (marker-position edpos))
- (not (eobp)))
- (if (search-forward lineup (pascal-get-end-of-line) 'move)
- (forward-char -1))
- (delete-horizontal-space)
- (indent-to ind)
- (if (not (looking-at lineup))
- (forward-line 1) ; No more indent if there is no : or =
- (forward-char 1)
- (delete-horizontal-space)
- (insert " ")
- ;; Indent record block
- (if (looking-at "record\\>")
- (pascal-indent-declaration (current-column)))
- (forward-line 1)))))
-
- ;; If arg - move point
- (if arg (forward-line -1)
- (goto-char (marker-position pos)))))
-
-; "Return the indent level that will line up several lines within the region
-;from b to e nicely. The lineup string is str."
-(defun pascal-get-lineup-indent (b e str)
- (save-excursion
- (let ((ind 0)
- (reg (concat str "\\|\\(\\<record\\>\\)"))
- nest)
- (goto-char b)
- ;; Get rightmost position
- (while (< (point) e)
- (setq nest 1)
- (if (re-search-forward reg (min e (pascal-get-end-of-line 2)) 'move)
- (progn
- ;; Skip record blocks
- (if (match-beginning 1)
- (pascal-declaration-end)
- (progn
- (goto-char (match-beginning 0))
- (skip-chars-backward " \t")
- (if (> (current-column) ind)
- (setq ind (current-column)))
- (goto-char (match-end 0)))))))
- ;; In case no lineup was found
- (if (> ind 0)
- (1+ ind)
- ;; No lineup-string found
- (goto-char b)
- (end-of-line)
- (skip-chars-backward " \t")
- (1+ (current-column))))))
-
-
-
-;;;
-;;; Completion
-;;;
-(defvar pascal-str nil)
-(defvar pascal-all nil)
-(defvar pascal-pred nil)
-(defvar pascal-buffer-to-use nil)
-(defvar pascal-flag nil)
-
-(defun pascal-string-diff (str1 str2)
- "Return index of first letter where STR1 and STR2 differs."
- (catch 'done
- (let ((diff 0))
- (while t
- (if (or (> (1+ diff) (length str1))
- (> (1+ diff) (length str2)))
- (throw 'done diff))
- (or (equal (aref str1 diff) (aref str2 diff))
- (throw 'done diff))
- (setq diff (1+ diff))))))
-
-;; Calculate all possible completions for functions if argument is `function',
-;; completions for procedures if argument is `procedure' or both functions and
-;; procedures otherwise.
-
-(defun pascal-func-completion (type)
- ;; Build regular expression for function/procedure names
- (if (string= pascal-str "")
- (setq pascal-str "[a-zA-Z_]"))
- (let ((pascal-str (concat (cond
- ((eq type 'procedure) "\\<\\(procedure\\)\\s +")
- ((eq type 'function) "\\<\\(function\\)\\s +")
- (t "\\<\\(function\\|procedure\\)\\s +"))
- "\\<\\(" pascal-str "[a-zA-Z0-9_.]*\\)\\>"))
- match)
-
- (if (not (looking-at "\\<\\(function\\|procedure\\)\\>"))
- (re-search-backward "\\<\\(function\\|procedure\\)\\>" nil t))
- (forward-char 1)
-
- ;; Search through all reachable functions
- (while (pascal-beg-of-defun)
- (if (re-search-forward pascal-str (pascal-get-end-of-line) t)
- (progn (setq match (buffer-substring (match-beginning 2)
- (match-end 2)))
- (if (or (null pascal-pred)
- (funcall pascal-pred match))
- (setq pascal-all (cons match pascal-all)))))
- (goto-char (match-beginning 0)))))
-
-(defun pascal-get-completion-decl ()
- ;; Macro for searching through current declaration (var, type or const)
- ;; for matches of `str' and adding the occurrence tp `all'
- (let ((end (save-excursion (pascal-declaration-end)
- (point)))
- match)
- ;; Traverse lines
- (while (< (point) end)
- (if (re-search-forward "[:=]" (pascal-get-end-of-line) t)
- ;; Traverse current line
- (while (and (re-search-backward
- (concat "\\((\\|\\<\\(var\\|type\\|const\\)\\>\\)\\|"
- pascal-symbol-re)
- (pascal-get-beg-of-line) t)
- (not (match-end 1)))
- (setq match (buffer-substring (match-beginning 0) (match-end 0)))
- (if (string-match (concat "\\<" pascal-str) match)
- (if (or (null pascal-pred)
- (funcall pascal-pred match))
- (setq pascal-all (cons match pascal-all))))))
- (if (re-search-forward "\\<record\\>" (pascal-get-end-of-line) t)
- (pascal-declaration-end)
- (forward-line 1)))))
-
-(defun pascal-type-completion ()
- "Calculate all possible completions for types."
- (let ((start (point))
- goon)
- ;; Search for all reachable type declarations
- (while (or (pascal-beg-of-defun)
- (setq goon (not goon)))
- (save-excursion
- (if (and (< start (prog1 (save-excursion (pascal-end-of-defun)
- (point))
- (forward-char 1)))
- (re-search-forward
- "\\<type\\>\\|\\<\\(begin\\|function\\|procedure\\)\\>"
- start t)
- (not (match-end 1)))
- ;; Check current type declaration
- (pascal-get-completion-decl))))))
-
-(defun pascal-var-completion ()
- "Calculate all possible completions for variables (or constants)."
- (let ((start (point))
- goon twice)
- ;; Search for all reachable var declarations
- (while (or (pascal-beg-of-defun)
- (setq goon (not goon)))
- (save-excursion
- (if (> start (prog1 (save-excursion (pascal-end-of-defun)
- (point))))
- () ; Declarations not reachable
- (if (search-forward "(" (pascal-get-end-of-line) t)
- ;; Check parameterlist
- (pascal-get-completion-decl))
- (setq twice 2)
- (while (>= (setq twice (1- twice)) 0)
- (cond ((and (re-search-forward
- (concat "\\<\\(var\\|const\\)\\>\\|"
- "\\<\\(begin\\|function\\|procedure\\)\\>")
- start t)
- (not (match-end 2)))
- ;; Check var/const declarations
- (pascal-get-completion-decl))
- ((match-end 2)
- (setq twice 0)))))))))
-
-
-(defun pascal-keyword-completion (keyword-list)
- "Give list of all possible completions of keywords in KEYWORD-LIST."
- (mapcar '(lambda (s)
- (if (string-match (concat "\\<" pascal-str) s)
- (if (or (null pascal-pred)
- (funcall pascal-pred s))
- (setq pascal-all (cons s pascal-all)))))
- keyword-list))
-
-;; Function passed to completing-read, try-completion or
-;; all-completions to get completion on STR. If predicate is non-nil,
-;; it must be a function to be called for every match to check if this
-;; should really be a match. If flag is t, the function returns a list
-;; of all possible completions. If it is nil it returns a string, the
-;; longest possible completion, or t if STR is an exact match. If flag
-;; is 'lambda, the function returns t if STR is an exact match, nil
-;; otherwise.
-
-(defun pascal-completion (pascal-str pascal-pred pascal-flag)
- (save-excursion
- (let ((pascal-all nil))
- ;; Set buffer to use for searching labels. This should be set
- ;; within functions which use pascal-completions
- (set-buffer pascal-buffer-to-use)
-
- ;; Determine what should be completed
- (let ((state (car (pascal-calculate-indent))))
- (cond (;--Within a declaration or parameterlist
- (or (eq state 'declaration) (eq state 'paramlist)
- (and (eq state 'defun)
- (save-excursion
- (re-search-backward ")[ \t]*:"
- (pascal-get-beg-of-line) t))))
- (if (or (eq state 'paramlist) (eq state 'defun))
- (pascal-beg-of-defun))
- (pascal-type-completion)
- (pascal-keyword-completion pascal-type-keywords))
- (;--Starting a new statement
- (and (not (eq state 'contexp))
- (save-excursion
- (skip-chars-backward "a-zA-Z0-9_.")
- (backward-sexp 1)
- (or (looking-at pascal-nosemi-re)
- (progn
- (forward-sexp 1)
- (looking-at "\\s *\\(;\\|:[^=]\\)")))))
- (save-excursion (pascal-var-completion))
- (pascal-func-completion 'procedure)
- (pascal-keyword-completion pascal-start-keywords))
- (t;--Anywhere else
- (save-excursion (pascal-var-completion))
- (pascal-func-completion 'function)
- (pascal-keyword-completion pascal-separator-keywords))))
-
- ;; Now we have built a list of all matches. Give response to caller
- (pascal-completion-response))))
-
-(defun pascal-completion-response ()
- (cond ((or (equal pascal-flag 'lambda) (null pascal-flag))
- ;; This was not called by all-completions
- (if (null pascal-all)
- ;; Return nil if there was no matching label
- nil
- ;; Get longest string common in the labels
- (let* ((elm (cdr pascal-all))
- (match (car pascal-all))
- (min (length match))
- exact tmp)
- (if (string= match pascal-str)
- ;; Return t if first match was an exact match
- (setq match t)
- (while (not (null elm))
- ;; Find longest common string
- (if (< (setq tmp (pascal-string-diff match (car elm))) min)
- (progn
- (setq min tmp)
- (setq match (substring match 0 min))))
- ;; Terminate with match=t if this is an exact match
- (if (string= (car elm) pascal-str)
- (progn
- (setq match t)
- (setq elm nil))
- (setq elm (cdr elm)))))
- ;; If this is a test just for exact match, return nil ot t
- (if (and (equal pascal-flag 'lambda) (not (equal match 't)))
- nil
- match))))
- ;; If flag is t, this was called by all-completions. Return
- ;; list of all possible completions
- (pascal-flag
- pascal-all)))
-
-(defvar pascal-last-word-numb 0)
-(defvar pascal-last-word-shown nil)
-(defvar pascal-last-completions nil)
-
-(defun pascal-complete-word ()
- "Complete word at current point.
-\(See also `pascal-toggle-completions', `pascal-type-keywords',
-`pascal-start-keywords' and `pascal-separator-keywords'.)"
- (interactive)
- (let* ((b (save-excursion (skip-chars-backward "a-zA-Z0-9_") (point)))
- (e (save-excursion (skip-chars-forward "a-zA-Z0-9_") (point)))
- (pascal-str (buffer-substring b e))
- ;; The following variable is used in pascal-completion
- (pascal-buffer-to-use (current-buffer))
- (allcomp (if (and pascal-toggle-completions
- (string= pascal-last-word-shown pascal-str))
- pascal-last-completions
- (all-completions pascal-str 'pascal-completion)))
- (match (if pascal-toggle-completions
- "" (try-completion
- pascal-str (mapcar '(lambda (elm)
- (cons elm 0)) allcomp)))))
- ;; Delete old string
- (delete-region b e)
-
- ;; Toggle-completions inserts whole labels
- (if pascal-toggle-completions
- (progn
- ;; Update entry number in list
- (setq pascal-last-completions allcomp
- pascal-last-word-numb
- (if (>= pascal-last-word-numb (1- (length allcomp)))
- 0
- (1+ pascal-last-word-numb)))
- (setq pascal-last-word-shown (elt allcomp pascal-last-word-numb))
- ;; Display next match or same string if no match was found
- (if (not (null allcomp))
- (insert "" pascal-last-word-shown)
- (insert "" pascal-str)
- (message "(No match)")))
- ;; The other form of completion does not necessarily do that.
-
- ;; Insert match if found, or the original string if no match
- (if (or (null match) (equal match 't))
- (progn (insert "" pascal-str)
- (message "(No match)"))
- (insert "" match))
- ;; Give message about current status of completion
- (cond ((equal match 't)
- (if (not (null (cdr allcomp)))
- (message "(Complete but not unique)")
- (message "(Sole completion)")))
- ;; Display buffer if the current completion didn't help
- ;; on completing the label.
- ((and (not (null (cdr allcomp))) (= (length pascal-str)
- (length match)))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list allcomp))
- ;; Wait for a keypress. Then delete *Completion* window
- (momentary-string-display "" (point))
- (delete-window (get-buffer-window (get-buffer "*Completions*")))
- )))))
-
-(defun pascal-show-completions ()
- "Show all possible completions at current point."
- (interactive)
- (let* ((b (save-excursion (skip-chars-backward "a-zA-Z0-9_") (point)))
- (e (save-excursion (skip-chars-forward "a-zA-Z0-9_") (point)))
- (pascal-str (buffer-substring b e))
- ;; The following variable is used in pascal-completion
- (pascal-buffer-to-use (current-buffer))
- (allcomp (if (and pascal-toggle-completions
- (string= pascal-last-word-shown pascal-str))
- pascal-last-completions
- (all-completions pascal-str 'pascal-completion))))
- ;; Show possible completions in a temporary buffer.
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list allcomp))
- ;; Wait for a keypress. Then delete *Completion* window
- (momentary-string-display "" (point))
- (delete-window (get-buffer-window (get-buffer "*Completions*")))))
-
-
-(defun pascal-get-default-symbol ()
- "Return symbol around current point as a string."
- (save-excursion
- (buffer-substring (progn
- (skip-chars-backward " \t")
- (skip-chars-backward "a-zA-Z0-9_")
- (point))
- (progn
- (skip-chars-forward "a-zA-Z0-9_")
- (point)))))
-
-(defun pascal-build-defun-re (str &optional arg)
- "Return function/procedure starting with STR as regular expression.
-With optional second arg non-nil, STR is the complete name of the instruction."
- (if arg
- (concat "^\\(function\\|procedure\\)[ \t]+\\(" str "\\)\\>")
- (concat "^\\(function\\|procedure\\)[ \t]+\\(" str "[a-zA-Z0-9_]*\\)\\>")))
-
-;; Function passed to completing-read, try-completion or
-;; all-completions to get completion on any function name. If
-;; predicate is non-nil, it must be a function to be called for every
-;; match to check if this should really be a match. If flag is t, the
-;; function returns a list of all possible completions. If it is nil
-;; it returns a string, the longest possible completion, or t if STR
-;; is an exact match. If flag is 'lambda, the function returns t if
-;; STR is an exact match, nil otherwise.
-
-(defun pascal-comp-defun (pascal-str pascal-pred pascal-flag)
- (save-excursion
- (let ((pascal-all nil)
- match)
-
- ;; Set buffer to use for searching labels. This should be set
- ;; within functions which use pascal-completions
- (set-buffer pascal-buffer-to-use)
-
- (let ((pascal-str pascal-str))
- ;; Build regular expression for functions
- (if (string= pascal-str "")
- (setq pascal-str (pascal-build-defun-re "[a-zA-Z_]"))
- (setq pascal-str (pascal-build-defun-re pascal-str)))
- (goto-char (point-min))
-
- ;; Build a list of all possible completions
- (while (re-search-forward pascal-str nil t)
- (setq match (buffer-substring (match-beginning 2) (match-end 2)))
- (if (or (null pascal-pred)
- (funcall pascal-pred match))
- (setq pascal-all (cons match pascal-all)))))
-
- ;; Now we have built a list of all matches. Give response to caller
- (pascal-completion-response))))
-
-(defun pascal-goto-defun ()
- "Move to specified Pascal function/procedure.
-The default is a name found in the buffer around point."
- (interactive)
- (let* ((default (pascal-get-default-symbol))
- ;; The following variable is used in pascal-comp-function
- (pascal-buffer-to-use (current-buffer))
- (default (if (pascal-comp-defun default nil 'lambda)
- default ""))
- (label (if (not (string= default ""))
- ;; Do completion with default
- (completing-read (concat "Label: (default " default ") ")
- 'pascal-comp-defun nil t "")
- ;; There is no default value. Complete without it
- (completing-read "Label: "
- 'pascal-comp-defun nil t ""))))
- ;; If there was no response on prompt, use default value
- (if (string= label "")
- (setq label default))
- ;; Goto right place in buffer if label is not an empty string
- (or (string= label "")
- (progn
- (goto-char (point-min))
- (re-search-forward (pascal-build-defun-re label t))
- (beginning-of-line)))))
-
-
-
-;;;
-;;; Pascal-outline-mode
-;;;
-(defvar pascal-outline-map nil "Keymap used in Pascal Outline mode.")
-
-(if pascal-outline-map
- nil
- (if (boundp 'set-keymap-name)
- (set-keymap-name pascal-outline-map 'pascal-outline-map))
- (if (not (boundp 'set-keymap-parent))
- (setq pascal-outline-map (copy-keymap pascal-mode-map))
- (setq pascal-outline-map (make-sparse-keymap))
- (set-keymap-parent pascal-outline-map pascal-mode-map))
- (define-key pascal-outline-map "\M-\C-a" 'pascal-outline-prev-defun)
- (define-key pascal-outline-map "\M-\C-e" 'pascal-outline-next-defun)
- (define-key pascal-outline-map "\C-c\C-d" 'pascal-outline-goto-defun)
- (define-key pascal-outline-map "\C-c\C-s" 'pascal-show-all)
- (define-key pascal-outline-map "\C-c\C-h" 'pascal-hide-other-defuns))
-
-(defvar pascal-outline-mode nil "Non-nil while using Pascal Outline mode.")
-(make-variable-buffer-local 'pascal-outline-mode)
-(set-default 'pascal-outline-mode nil)
-(if (not (assoc 'pascal-outline-mode minor-mode-alist))
- (setq minor-mode-alist (append minor-mode-alist
- (list '(pascal-outline-mode " Outl")))))
-
-(defun pascal-outline (&optional arg)
- "Outline-line minor mode for Pascal mode.
-When in Pascal Outline mode, portions
-of the text being edited may be made invisible. \\<pascal-outline-map>
-
-Pascal Outline mode provides some additional commands.
-
-\\[pascal-outline-prev-defun]\
-\t- Move to previous function/procedure, hiding everything else.
-\\[pascal-outline-next-defun]\
-\t- Move to next function/procedure, hiding everything else.
-\\[pascal-outline-goto-defun]\
-\t- Goto function/procedure prompted for in minibuffer,
-\t hide all other functions.
-\\[pascal-show-all]\t- Show the whole buffer.
-\\[pascal-hide-other-defuns]\
-\t- Hide everything but the current function (function under the cursor).
-\\[pascal-outline]\t- Leave pascal-outline-mode."
- (interactive "P")
- (setq pascal-outline-mode
- (if (null arg) (not pascal-outline-mode) t))
- (if (boundp 'redraw-mode-line)
- (redraw-mode-line))
- (if pascal-outline-mode
- (progn
- (setq selective-display t)
- (use-local-map pascal-outline-map))
- (progn
- (setq selective-display nil)
- (pascal-show-all)
- (use-local-map pascal-mode-map))))
-
-(defun pascal-outline-change (b e pascal-flag)
- (let ((modp (buffer-modified-p)))
- (unwind-protect
- (subst-char-in-region b e (if (= pascal-flag ?\n)
- ?\^M ?\n) pascal-flag)
- (set-buffer-modified-p modp))))
-
-(defun pascal-show-all ()
- "Show all of the text in the buffer."
- (interactive)
- (pascal-outline-change (point-min) (point-max) ?\n))
-
-(defun pascal-hide-other-defuns ()
- "Show only the current defun."
- (interactive)
- (save-excursion
- (let ((beg (progn (if (not (looking-at "\\(function\\|procedure\\)\\>"))
- (pascal-beg-of-defun))
- (point)))
- (end (progn (pascal-end-of-defun)
- (backward-sexp 1)
- (search-forward "\n\\|\^M" nil t)
- (point)))
- (opoint (point-min)))
- (goto-char (point-min))
-
- ;; Hide all functions before current function
- (while (re-search-forward "^\\(function\\|procedure\\)\\>" beg 'move)
- (pascal-outline-change opoint (1- (match-beginning 0)) ?\^M)
- (setq opoint (point))
- ;; Functions may be nested
- (if (> (progn (pascal-end-of-defun) (point)) beg)
- (goto-char opoint)))
- (if (> beg opoint)
- (pascal-outline-change opoint (1- beg) ?\^M))
-
- ;; Show current function
- (pascal-outline-change beg end ?\n)
- ;; Hide nested functions
- (forward-char 1)
- (while (re-search-forward "^\\(function\\|procedure\\)\\>" end 'move)
- (setq opoint (point))
- (pascal-end-of-defun)
- (pascal-outline-change opoint (point) ?\^M))
-
- (goto-char end)
- (setq opoint end)
-
- ;; Hide all function after current function
- (while (re-search-forward "^\\(function\\|procedure\\)\\>" nil 'move)
- (pascal-outline-change opoint (1- (match-beginning 0)) ?\^M)
- (setq opoint (point))
- (pascal-end-of-defun))
- (pascal-outline-change opoint (point-max) ?\^M)
-
- ;; Hide main program
- (if (< (progn (forward-line -1) (point)) end)
- (progn
- (goto-char beg)
- (pascal-end-of-defun)
- (backward-sexp 1)
- (pascal-outline-change (point) (point-max) ?\^M))))))
-
-(defun pascal-outline-next-defun ()
- "Move to next function/procedure, hiding all others."
- (interactive)
- (pascal-end-of-defun)
- (pascal-hide-other-defuns))
-
-(defun pascal-outline-prev-defun ()
- "Move to previous function/procedure, hiding all others."
- (interactive)
- (pascal-beg-of-defun)
- (pascal-hide-other-defuns))
-
-(defun pascal-outline-goto-defun ()
- "Move to specified function/procedure, hiding all others."
- (interactive)
- (pascal-goto-defun)
- (pascal-hide-other-defuns))
-
-;;; pascal.el ends here
diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el
deleted file mode 100644
index 67a439da655..00000000000
--- a/lisp/progmodes/perl-mode.el
+++ /dev/null
@@ -1,732 +0,0 @@
-;;; perl-mode.el --- Perl code editing commands for GNU Emacs
-
-;; Copyright (C) 1990, 1994 Free Software Foundation, Inc.
-
-;; Author: William F. Mann
-;; Maintainer: FSF
-;; Adapted-By: ESR
-;; Keywords: languages
-
-;; Adapted from C code editing commands 'c-mode.el', Copyright 1987 by the
-;; Free Software Foundation, under terms of its General Public License.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; To enter perl-mode automatically, add (autoload 'perl-mode "perl-mode")
-;; to your .emacs file and change the first line of your perl script to:
-;; #!/usr/bin/perl -- # -*-Perl-*-
-;; With arguments to perl:
-;; #!/usr/bin/perl -P- # -*-Perl-*-
-;; To handle files included with do 'filename.pl';, add something like
-;; (setq auto-mode-alist (append (list (cons "\\.pl\\'" 'perl-mode))
-;; auto-mode-alist))
-;; to your .emacs file; otherwise the .pl suffix defaults to prolog-mode.
-
-;; This code is based on the 18.53 version c-mode.el, with extensive
-;; rewriting. Most of the features of c-mode survived intact.
-
-;; I added a new feature which adds functionality to TAB; it is controlled
-;; by the variable perl-tab-to-comment. With it enabled, TAB does the
-;; first thing it can from the following list: change the indentation;
-;; move past leading white space; delete an empty comment; reindent a
-;; comment; move to end of line; create an empty comment; tell you that
-;; the line ends in a quoted string, or has a # which should be a \#.
-
-;; If your machine is slow, you may want to remove some of the bindings
-;; to electric-perl-terminator. I changed the indenting defaults to be
-;; what Larry Wall uses in perl/lib, but left in all the options.
-
-;; I also tuned a few things: comments and labels starting in column
-;; zero are left there by indent-perl-exp; perl-beginning-of-function
-;; goes back to the first open brace/paren in column zero, the open brace
-;; in 'sub ... {', or the equal sign in 'format ... ='; indent-perl-exp
-;; (meta-^q) indents from the current line through the close of the next
-;; brace/paren, so you don't need to start exactly at a brace or paren.
-
-;; It may be good style to put a set of redundant braces around your
-;; main program. This will let you reindent it with meta-^q.
-
-;; Known problems (these are all caused by limitations in the Emacs Lisp
-;; parsing routine (parse-partial-sexp), which was not designed for such
-;; a rich language; writing a more suitable parser would be a big job):
-;; 1) Regular expression delimiters do not act as quotes, so special
-;; characters such as `'"#:;[](){} may need to be backslashed
-;; in regular expressions and in both parts of s/// and tr///.
-;; 2) The globbing syntax <pattern> is not recognized, so special
-;; characters in the pattern string must be backslashed.
-;; 3) The q, qq, and << quoting operators are not recognized; see below.
-;; 4) \ (backslash) always quotes the next character, so '\' is
-;; treated as the start of a string. Use "\\" as a work-around.
-;; 5) To make variables such a $' and $#array work, perl-mode treats
-;; $ just like backslash, so '$' is the same as problem 5.
-;; 6) Unfortunately, treating $ like \ makes ${var} be treated as an
-;; unmatched }. See below.
-;; 7) When ' (quote) is used as a package name separator, perl-mode
-;; doesn't understand, and thinks it is seeing a quoted string.
-
-;; Here are some ugly tricks to bypass some of these problems: the perl
-;; expression /`/ (that's a back-tick) usually evaluates harmlessly,
-;; but will trick perl-mode into starting a quoted string, which
-;; can be ended with another /`/. Assuming you have no embedded
-;; back-ticks, this can used to help solve problem 3:
-;;
-;; /`/; $ugly = q?"'$?; /`/;
-;;
-;; To solve problem 6, add a /{/; before each use of ${var}:
-;; /{/; while (<${glob_me}>) ...
-;;
-;; Problem 7 is even worse, but this 'fix' does work :-(
-;; $DB'stop#'
-;; [$DB'line#'
-;; ] =~ s/;9$//;
-
-;;; Code:
-
-(defvar perl-mode-abbrev-table nil
- "Abbrev table in use in perl-mode buffers.")
-(define-abbrev-table 'perl-mode-abbrev-table ())
-
-(defvar perl-mode-map ()
- "Keymap used in Perl mode.")
-(if perl-mode-map
- ()
- (setq perl-mode-map (make-sparse-keymap))
- (define-key perl-mode-map "{" 'electric-perl-terminator)
- (define-key perl-mode-map "}" 'electric-perl-terminator)
- (define-key perl-mode-map ";" 'electric-perl-terminator)
- (define-key perl-mode-map ":" 'electric-perl-terminator)
- (define-key perl-mode-map "\e\C-a" 'perl-beginning-of-function)
- (define-key perl-mode-map "\e\C-e" 'perl-end-of-function)
- (define-key perl-mode-map "\e\C-h" 'mark-perl-function)
- (define-key perl-mode-map "\e\C-q" 'indent-perl-exp)
- (define-key perl-mode-map "\177" 'backward-delete-char-untabify)
- (define-key perl-mode-map "\t" 'perl-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 perl-mode-syntax-table nil
- "Syntax table in use in perl-mode buffers.")
-
-(if perl-mode-syntax-table
- ()
- (setq perl-mode-syntax-table (make-syntax-table (standard-syntax-table)))
- (modify-syntax-entry ?\n ">" perl-mode-syntax-table)
- (modify-syntax-entry ?# "<" perl-mode-syntax-table)
- (modify-syntax-entry ?$ "/" perl-mode-syntax-table)
- (modify-syntax-entry ?% "." perl-mode-syntax-table)
- (modify-syntax-entry ?& "." perl-mode-syntax-table)
- (modify-syntax-entry ?\' "\"" perl-mode-syntax-table)
- (modify-syntax-entry ?* "." perl-mode-syntax-table)
- (modify-syntax-entry ?+ "." perl-mode-syntax-table)
- (modify-syntax-entry ?- "." perl-mode-syntax-table)
- (modify-syntax-entry ?/ "." perl-mode-syntax-table)
- (modify-syntax-entry ?< "." perl-mode-syntax-table)
- (modify-syntax-entry ?= "." perl-mode-syntax-table)
- (modify-syntax-entry ?> "." perl-mode-syntax-table)
- (modify-syntax-entry ?\\ "\\" perl-mode-syntax-table)
- (modify-syntax-entry ?` "\"" perl-mode-syntax-table)
- (modify-syntax-entry ?| "." perl-mode-syntax-table)
-)
-
-(defvar perl-imenu-generic-expression
- '(
- ;; Functions
- (nil "^sub\\s-+\\([-A-Za-z0-9+_:]+\\)\\(\\s-\\|\n\\)*{" 1 )
- ;;Variables
- ("Variables" "^\\([$@%][-A-Za-z0-9+_:]+\\)\\s-*=" 1 )
- ("Packages" "^package\\s-+\\([-A-Za-z0-9+_:]+\\);" 1 )
- )
- "Imenu generic expression for Perl mode. See `imenu-generic-expression'.")
-
-;; Regexps updated with help from Tom Tromey <tromey@cambric.colorado.edu> and
-;; Jim Campbell <jec@murzim.ca.boeing.com>.
-
-(defconst perl-font-lock-keywords-1
- '(;; What is this for?
- ;;("\\(--- .* ---\\|=== .* ===\\)" . font-lock-string-face)
- ;;
- ;; Fontify preprocessor statements as we do in `c-font-lock-keywords'.
- ;; Ilya Zakharevich <ilya@math.ohio-state.edu> thinks this is a bad idea.
- ("^#[ \t]*include[ \t]+\\(<[^>\"\n]+>\\)" 1 font-lock-string-face)
- ("^#[ \t]*define[ \t]+\\(\\sw+\\)(" 1 font-lock-function-name-face)
- ("^#[ \t]*if\\>"
- ("\\<\\(defined\\)\\>[ \t]*(?\\(\\sw+\\)?" nil nil
- (1 font-lock-reference-face) (2 font-lock-variable-name-face nil t)))
- ("^#[ \t]*\\(\\sw+\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-reference-face) (2 font-lock-variable-name-face nil t))
- ;;
- ;; Fontify function and package names in declarations.
- ("\\<\\(package\\|sub\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))
- ("\\<\\(import\\|no\\|require\\|use\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-reference-face nil t)))
- "Subdued level highlighting for Perl mode.")
-
-(defconst perl-font-lock-keywords-2
- (append perl-font-lock-keywords-1
- (list
- ;;
- ;; Fontify keywords, except those fontified otherwise.
-; (make-regexp '("if" "until" "while" "elsif" "else" "unless" "do" "dump"
-; "for" "foreach" "exit" "die"
-; "BEGIN" "END" "return" "exec" "eval"))
- (concat "\\<\\("
- "BEGIN\\|END\\|d\\(ie\\|o\\|ump\\)\\|"
- "e\\(ls\\(e\\|if\\)\\|val\\|x\\(ec\\|it\\)\\)\\|"
- "for\\(\\|each\\)\\|if\\|return\\|un\\(less\\|til\\)\\|while"
- "\\)\\>")
- ;;
- ;; Fontify local and my keywords as types.
- '("\\<\\(local\\|my\\)\\>" . font-lock-type-face)
- ;;
- ;; Fontify function, variable and file name references.
- '("&\\(\\sw+\\)" 1 font-lock-function-name-face)
- ;; Additionally underline non-scalar variables. Maybe this is a bad idea.
- ;;'("[$@%*][#{]?\\(\\sw+\\)" 1 font-lock-variable-name-face)
- '("[$*]{?\\(\\sw+\\)" 1 font-lock-variable-name-face)
- '("\\([@%]\\|\\$#\\)\\(\\sw+\\)"
- (2 (cons font-lock-variable-name-face '(underline))))
- '("<\\(\\sw+\\)>" 1 font-lock-reference-face)
- ;;
- ;; Fontify keywords with/and labels as we do in `c++-font-lock-keywords'.
- '("\\<\\(continue\\|goto\\|last\\|next\\|redo\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-reference-face nil t))
- '("^[ \t]*\\(\\sw+\\)[ \t]*:[^:]" 1 font-lock-reference-face)))
- "Gaudy level highlighting for Perl mode.")
-
-(defvar perl-font-lock-keywords perl-font-lock-keywords-1
- "Default expressions to highlight in Perl mode.")
-
-
-(defvar perl-indent-level 4
- "*Indentation of Perl statements with respect to containing block.")
-(defvar perl-continued-statement-offset 4
- "*Extra indent for lines not starting new statements.")
-(defvar perl-continued-brace-offset -4
- "*Extra indent for substatements that start with open-braces.
-This is in addition to `perl-continued-statement-offset'.")
-(defvar perl-brace-offset 0
- "*Extra indentation for braces, compared with other text in same context.")
-(defvar perl-brace-imaginary-offset 0
- "*Imagined indentation of an open brace that actually follows a statement.")
-(defvar perl-label-offset -2
- "*Offset of Perl label lines relative to usual indentation.")
-
-(defvar perl-tab-always-indent t
- "*Non-nil means TAB in Perl mode always indents the current line.
-Otherwise it inserts a tab character if you type it past the first
-nonwhite character on the line.")
-
-;; I changed the default to nil for consistency with general Emacs
-;; conventions -- rms.
-(defvar perl-tab-to-comment nil
- "*Non-nil means TAB moves to eol or makes a comment in some cases.
-For lines which don't need indenting, TAB either indents an
-existing comment, moves to end-of-line, or if at end-of-line already,
-create a new comment.")
-
-(defvar perl-nochange ";?#\\|\f\\|\\s(\\|\\(\\w\\|\\s_\\)+:"
- "*Lines starting with this regular expression are not auto-indented.")
-
-;;;###autoload
-(defun perl-mode ()
- "Major mode for editing Perl code.
-Expression and list commands understand all Perl brackets.
-Tab indents for Perl code.
-Comments are delimited with # ... \\n.
-Paragraphs are separated by blank lines only.
-Delete converts tabs to spaces as it moves back.
-\\{perl-mode-map}
-Variables controlling indentation style:
- perl-tab-always-indent
- Non-nil means TAB in Perl mode should always indent the current line,
- regardless of where in the line point is when the TAB command is used.
- perl-tab-to-comment
- Non-nil means that for lines which don't need indenting, TAB will
- either delete an empty comment, indent an existing comment, move
- to end-of-line, or if at end-of-line already, create a new comment.
- perl-nochange
- Lines starting with this regular expression are not auto-indented.
- perl-indent-level
- Indentation of Perl statements within surrounding block.
- The surrounding block's indentation is the indentation
- of the line on which the open-brace appears.
- perl-continued-statement-offset
- Extra indentation given to a substatement, such as the
- then-clause of an if or body of a while.
- perl-continued-brace-offset
- Extra indentation given to a brace that starts a substatement.
- This is in addition to `perl-continued-statement-offset'.
- perl-brace-offset
- Extra indentation for line if it starts with an open brace.
- perl-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.
- perl-label-offset
- Extra indentation for line that is a label.
-
-Various indentation styles: K&R BSD BLK GNU LW
- perl-indent-level 5 8 0 2 4
- perl-continued-statement-offset 5 8 4 2 4
- perl-continued-brace-offset 0 0 0 0 -4
- perl-brace-offset -5 -8 0 0 0
- perl-brace-imaginary-offset 0 0 4 0 0
- perl-label-offset -5 -8 -2 -2 -2
-
-Turning on Perl mode runs the normal hook `perl-mode-hook'."
- (interactive)
- (kill-all-local-variables)
- (use-local-map perl-mode-map)
- (setq major-mode 'perl-mode)
- (setq mode-name "Perl")
- (setq local-abbrev-table perl-mode-abbrev-table)
- (set-syntax-table perl-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 'perl-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 "\\(^\\|\\s-\\);?#+ *")
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'perl-comment-indent)
- (make-local-variable 'parse-sexp-ignore-comments)
- (setq parse-sexp-ignore-comments t)
- ;; Tell font-lock.el how to handle Perl.
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '((perl-font-lock-keywords
- perl-font-lock-keywords-1
- perl-font-lock-keywords-2)
- nil nil ((?\_ . "w"))))
- ;; Tell imenu how to handle Perl.
- (make-local-variable 'imenu-generic-expression)
- (setq imenu-generic-expression perl-imenu-generic-expression)
- (run-hooks 'perl-mode-hook))
-
-;; This is used by indent-for-comment
-;; to decide how much to indent a comment in Perl code
-;; based on its context.
-(defun perl-comment-indent ()
- (if (and (bolp) (not (eolp)))
- 0 ;Existing comment at bol stays there.
- (save-excursion
- (skip-chars-backward " \t")
- (max (if (bolp) ;Else indent at comment column
- 0 ; except leave at least one space if
- (1+ (current-column))) ; not at beginning of line.
- comment-column))))
-
-(defun electric-perl-terminator (arg)
- "Insert character and adjust indentation.
-If at end-of-line, and not in a comment or a quote, correct the's indentation."
- (interactive "P")
- (let ((insertpos (point)))
- (and (not arg) ; decide whether to indent
- (eolp)
- (save-excursion
- (beginning-of-line)
- (and (not ; eliminate comments quickly
- (and comment-start-skip
- (re-search-forward comment-start-skip insertpos t)) )
- (or (/= last-command-char ?:)
- ;; Colon is special only after a label ....
- (looking-at "\\s-*\\(\\w\\|\\s_\\)+$"))
- (let ((pps (parse-partial-sexp
- (perl-beginning-of-function) insertpos)))
- (not (or (nth 3 pps) (nth 4 pps) (nth 5 pps))))))
- (progn ; must insert, indent, delete
- (insert-char last-command-char 1)
- (perl-indent-line)
- (delete-char -1))))
- (self-insert-command (prefix-numeric-value arg)))
-
-;; not used anymore, but may be useful someday:
-;;(defun perl-inside-parens-p ()
-;; (condition-case ()
-;; (save-excursion
-;; (save-restriction
-;; (narrow-to-region (point)
-;; (perl-beginning-of-function))
-;; (goto-char (point-max))
-;; (= (char-after (or (scan-lists (point) -1 1) (point-min))) ?\()))
-;; (error nil)))
-
-(defun perl-indent-command (&optional arg)
- "Indent current line as Perl code, or optionally, insert a tab character.
-
-With an argument, indent the current line, regardless of other options.
-
-If `perl-tab-always-indent' is nil and point is not in the indentation
-area at the beginning of the line, simply insert a tab.
-
-Otherwise, indent the current line. If point was within the indentation
-area it is moved to the end of the indentation area. If the line was
-already indented properly and point was not within the indentation area,
-and if `perl-tab-to-comment' is non-nil (the default), then do the first
-possible action from the following list:
-
- 1) delete an empty comment
- 2) move forward to start of comment, indenting if necessary
- 3) move forward to end of line
- 4) create an empty comment
- 5) move backward to start of comment, indenting if necessary."
- (interactive "P")
- (if arg ; If arg, just indent this line
- (perl-indent-line "\f")
- (if (and (not perl-tab-always-indent)
- (> (current-column) (current-indentation)))
- (insert-tab)
- (let (bof lsexp delta (oldpnt (point)))
- (beginning-of-line)
- (setq lsexp (point))
- (setq bof (perl-beginning-of-function))
- (goto-char oldpnt)
- (setq delta (perl-indent-line "\f\\|;?#" bof))
- (and perl-tab-to-comment
- (= oldpnt (point)) ; done if point moved
- (if (listp delta) ; if line starts in a quoted string
- (setq lsexp (or (nth 2 delta) bof))
- (= delta 0)) ; done if indenting occurred
- (let (eol state)
- (end-of-line)
- (setq eol (point))
- (if (= (char-after bof) ?=)
- (if (= oldpnt eol)
- (message "In a format statement"))
- (setq state (parse-partial-sexp lsexp eol))
- (if (nth 3 state)
- (if (= oldpnt eol) ; already at eol in a string
- (message "In a string which starts with a %c."
- (nth 3 state)))
- (if (not (nth 4 state))
- (if (= oldpnt eol) ; no comment, create one?
- (indent-for-comment))
- (beginning-of-line)
- (if (and comment-start-skip
- (re-search-forward comment-start-skip eol 'move))
- (if (eolp)
- (progn ; kill existing comment
- (goto-char (match-beginning 0))
- (skip-chars-backward " \t")
- (kill-region (point) eol))
- (if (or (< oldpnt (point)) (= oldpnt eol))
- (indent-for-comment) ; indent existing comment
- (end-of-line)))
- (if (/= oldpnt eol)
- (end-of-line)
- (message "Use backslash to quote # characters.")
- (ding t))))))))))))
-
-(defun perl-indent-line (&optional nochange parse-start)
- "Indent current line as Perl code.
-Return the amount the indentation
-changed by, or (parse-state) if line starts in a quoted string."
- (let ((case-fold-search nil)
- (pos (- (point-max) (point)))
- (bof (or parse-start (save-excursion (perl-beginning-of-function))))
- beg indent shift-amt)
- (beginning-of-line)
- (setq beg (point))
- (setq shift-amt
- (cond ((= (char-after bof) ?=) 0)
- ((listp (setq indent (calculate-perl-indent bof))) indent)
- ((looking-at (or nochange perl-nochange)) 0)
- (t
- (skip-chars-forward " \t\f")
- (cond ((looking-at "\\(\\w\\|\\s_\\)+:")
- (setq indent (max 1 (+ indent perl-label-offset))))
- ((= (following-char) ?})
- (setq indent (- indent perl-indent-level)))
- ((= (following-char) ?{)
- (setq indent (+ indent perl-brace-offset))))
- (- indent (current-column)))))
- (skip-chars-forward " \t\f")
- (if (and (numberp shift-amt) (/= 0 shift-amt))
- (progn (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-perl-indent (&optional parse-start)
- "Return appropriate indentation for current line as Perl code.
-In usual case returns an integer: the column to indent to.
-Returns (parse-state) if line starts inside a string."
- (save-excursion
- (beginning-of-line)
- (let ((indent-point (point))
- (case-fold-search nil)
- (colon-line-end 0)
- state containing-sexp)
- (if parse-start ;used to avoid searching
- (goto-char parse-start)
- (perl-beginning-of-function))
- (while (< (point) indent-point) ;repeat until right sexp
- (setq parse-start (point))
- (setq state (parse-partial-sexp (point) indent-point 0))
-; state = (depth_in_parens innermost_containing_list last_complete_sexp
-; string_terminator_or_nil inside_commentp following_quotep
-; minimum_paren-depth_this_scan)
-; Parsing stops if depth in parentheses becomes equal to third arg.
- (setq containing-sexp (nth 1 state)))
- (cond ((nth 3 state) state) ; In a quoted string?
- ((null containing-sexp) ; Line is at top level.
- (skip-chars-forward " \t\f")
- (if (= (following-char) ?{)
- 0 ; move to beginning of line if it starts a function body
- ;; indent a little if this is a continuation line
- (perl-backward-to-noncomment)
- (if (or (bobp)
- (memq (preceding-char) '(?\; ?\})))
- 0 perl-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.
- (perl-backward-to-noncomment)
- ;; 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) ?:)
- (memq (char-syntax (char-after (- (point) 2)))
- '(?w ?_))))
- (if (eq (preceding-char) ?\,)
- (perl-backward-to-start-of-continued-exp containing-sexp)
- (beginning-of-line))
- (perl-backward-to-noncomment))
- ;; Now we get the answer.
- (if (not (memq (preceding-char) '(?\; ?\} ?\{)))
- ;; This line is continuation of preceding line's statement;
- ;; indent perl-continued-statement-offset more than the
- ;; previous line of the statement.
- (progn
- (perl-backward-to-start-of-continued-exp containing-sexp)
- (+ perl-continued-statement-offset (current-column)
- (if (save-excursion (goto-char indent-point)
- (looking-at "[ \t]*{"))
- perl-continued-brace-offset 0)))
- ;; This line starts a new statement.
- ;; Position at last unclosed open.
- (goto-char containing-sexp)
- (or
- ;; If open paren is in col 0, close brace is special
- (and (bolp)
- (save-excursion (goto-char indent-point)
- (looking-at "[ \t]*}"))
- perl-indent-level)
- ;; Is line first statement after an open-brace?
- ;; If no, find that first statement and indent like it.
- (save-excursion
- (forward-char 1)
- ;; Skip over comments and labels following openbrace.
- (while (progn
- (skip-chars-forward " \t\f\n")
- (cond ((looking-at ";?#")
- (forward-line 1) t)
- ((looking-at "\\(\\w\\|\\s_\\)+:")
- (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) perl-label-offset)
- (current-column))))
- ;; If no previous statement,
- ;; indent it relative to line brace is on.
- ;; For open paren in column zero, don't let statement
- ;; start there too. If perl-indent-level is zero,
- ;; use perl-brace-offset + perl-continued-statement-offset
- ;; For open-braces not the first thing in a line,
- ;; add in perl-brace-imaginary-offset.
- (+ (if (and (bolp) (zerop perl-indent-level))
- (+ perl-brace-offset perl-continued-statement-offset)
- perl-indent-level)
- ;; Move back over whitespace before the openbrace.
- ;; If openbrace is not first nonwhite thing on the line,
- ;; add the perl-brace-imaginary-offset.
- (progn (skip-chars-backward " \t")
- (if (bolp) 0 perl-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 perl-backward-to-noncomment ()
- "Move point backward to after the first non-white-space, skipping comments."
- (interactive)
- (let (opoint stop)
- (while (not stop)
- (setq opoint (point))
- (beginning-of-line)
- (if (and comment-start-skip
- (re-search-forward comment-start-skip opoint 'move 1))
- (progn (goto-char (match-end 1))
- (skip-chars-forward ";")))
- (skip-chars-backward " \t\f")
- (setq stop (or (bobp)
- (not (bolp))
- (forward-char -1))))))
-
-(defun perl-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\f"))
-
-;; note: this may be slower than the c-mode version, but I can understand it.
-(defun indent-perl-exp ()
- "Indent each line of the Perl grouping following point."
- (interactive)
- (let* ((case-fold-search nil)
- (oldpnt (point-marker))
- (bof-mark (save-excursion
- (end-of-line 2)
- (perl-beginning-of-function)
- (point-marker)))
- eol last-mark lsexp-mark delta)
- (if (= (char-after (marker-position bof-mark)) ?=)
- (message "Can't indent a format statement")
- (message "Indenting Perl expression...")
- (save-excursion (end-of-line) (setq eol (point)))
- (save-excursion ; locate matching close paren
- (while (and (not (eobp)) (<= (point) eol))
- (parse-partial-sexp (point) (point-max) 0))
- (setq last-mark (point-marker)))
- (setq lsexp-mark bof-mark)
- (beginning-of-line)
- (while (< (point) (marker-position last-mark))
- (setq delta (perl-indent-line nil (marker-position bof-mark)))
- (if (numberp delta) ; unquoted start-of-line?
- (progn
- (if (eolp)
- (delete-horizontal-space))
- (setq lsexp-mark (point-marker))))
- (end-of-line)
- (setq eol (point))
- (if (nth 4 (parse-partial-sexp (marker-position lsexp-mark) eol))
- (progn ; line ends in a comment
- (beginning-of-line)
- (if (or (not (looking-at "\\s-*;?#"))
- (listp delta)
- (and (/= 0 delta)
- (= (- (current-indentation) delta) comment-column)))
- (if (and comment-start-skip
- (re-search-forward comment-start-skip eol t))
- (indent-for-comment))))) ; indent existing comment
- (forward-line 1))
- (goto-char (marker-position oldpnt))
- (message "Indenting Perl expression...done"))))
-
-(defun perl-beginning-of-function (&optional arg)
- "Move backward to next beginning-of-function, or as far as possible.
-With argument, repeat that many times; negative args move forward.
-Returns new value of point in all cases."
- (interactive "p")
- (or arg (setq arg 1))
- (if (< arg 0) (forward-char 1))
- (and (/= arg 0)
- (re-search-backward "^\\s(\\|^\\s-*sub\\b[^{]+{\\|^\\s-*format\\b[^=]*=\\|^\\."
- nil 'move arg)
- (goto-char (1- (match-end 0))))
- (point))
-
-;; note: this routine is adapted directly from emacs lisp.el, end-of-defun;
-;; no bugs have been removed :-)
-(defun perl-end-of-function (&optional arg)
- "Move forward to next end-of-function.
-The end of a function is found by moving forward from the beginning of one.
-With argument, repeat that many times; negative args move backward."
- (interactive "p")
- (or arg (setq arg 1))
- (let ((first t))
- (while (and (> arg 0) (< (point) (point-max)))
- (let ((pos (point)) npos)
- (while (progn
- (if (and first
- (progn
- (forward-char 1)
- (perl-beginning-of-function 1)
- (not (bobp))))
- nil
- (or (bobp) (forward-char -1))
- (perl-beginning-of-function -1))
- (setq first nil)
- (forward-list 1)
- (skip-chars-forward " \t")
- (if (looking-at "[#\n]")
- (forward-line 1))
- (<= (point) pos))))
- (setq arg (1- arg)))
- (while (< arg 0)
- (let ((pos (point)))
- (perl-beginning-of-function 1)
- (forward-sexp 1)
- (forward-line 1)
- (if (>= (point) pos)
- (if (progn (perl-beginning-of-function 2) (not (bobp)))
- (progn
- (forward-list 1)
- (skip-chars-forward " \t")
- (if (looking-at "[#\n]")
- (forward-line 1)))
- (goto-char (point-min)))))
- (setq arg (1+ arg)))))
-
-(defun mark-perl-function ()
- "Put mark at end of Perl function, point at beginning."
- (interactive)
- (push-mark (point))
- (perl-end-of-function)
- (push-mark (point))
- (perl-beginning-of-function)
- (backward-paragraph))
-
-(provide 'perl-mode)
-
-;;; perl-mode.el ends here
diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el
deleted file mode 100644
index 05a3c7ed5ac..00000000000
--- a/lisp/progmodes/prolog.el
+++ /dev/null
@@ -1,273 +0,0 @@
-;;; prolog.el --- major mode for editing and running Prolog under Emacs
-
-;; Copyright (C) 1986, 1987 Free Software Foundation, Inc.
-
-;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides a major mode for editing Prolog. It knows
-;; about Prolog syntax and comments, and can send regions to an inferior
-;; Prolog interpreter process.
-
-;;; Code:
-
-(defvar prolog-mode-syntax-table nil)
-(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). ")
-
-(defvar prolog-compile-string "compile(user).\n"
- "*Compile mode (for Quintus Prolog).")
-
-(defvar prolog-eof-string "end_of_file.\n"
- "*String that represents end of file for prolog.
-nil means send actual operating system end of file.")
-
-(defvar prolog-indent-width 4)
-
-(if prolog-mode-syntax-table
- ()
- (let ((table (make-syntax-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 ?\n ">" table)
- (modify-syntax-entry ?< "." table)
- (modify-syntax-entry ?> "." table)
- (modify-syntax-entry ?\' "\"" table)
- (setq prolog-mode-syntax-table table)))
-
-(define-abbrev-table 'prolog-mode-abbrev-table ())
-
-(defun prolog-mode-variables ()
- (set-syntax-table prolog-mode-syntax-table)
- (setq local-abbrev-table prolog-mode-abbrev-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 'prolog-indent-line)
- (make-local-variable 'comment-start)
- (setq comment-start "%")
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip "%+ *")
- (make-local-variable 'comment-column)
- (setq comment-column 48)
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'prolog-comment-indent))
-
-(defun prolog-mode-commands (map)
- (define-key map "\t" 'prolog-indent-line)
- (define-key map "\e\C-x" 'prolog-consult-region))
-
-(if prolog-mode-map
- nil
- (setq prolog-mode-map (make-sparse-keymap))
- (prolog-mode-commands prolog-mode-map))
-
-;;;###autoload
-(defun prolog-mode ()
- "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."
- (interactive)
- (kill-all-local-variables)
- (use-local-map prolog-mode-map)
- (setq major-mode 'prolog-mode)
- (setq mode-name "Prolog")
- (prolog-mode-variables)
- (run-hooks 'prolog-mode-hook))
-
-(defun prolog-indent-line (&optional whole-exp)
- "Indent current line as Prolog code.
-With argument, indent any additional lines of the same clause
-rigidly along with this one (not yet)."
- (interactive "p")
- (let ((indent (prolog-indent-level))
- (pos (- (point-max) (point))) beg)
- (beginning-of-line)
- (setq beg (point))
- (skip-chars-forward " \t")
- (if (zerop (- indent (current-column)))
- nil
- (delete-region beg (point))
- (indent-to indent))
- (if (> (- (point-max) pos) (point))
- (goto-char (- (point-max) pos)))
- ))
-
-(defun prolog-indent-level ()
- "Compute prolog indentation level."
- (save-excursion
- (beginning-of-line)
- (skip-chars-forward " \t")
- (cond
- ((looking-at "%%%") 0) ;Large comment starts
- ((looking-at "%[^%]") comment-column) ;Small comment starts
- ((bobp) 0) ;Beginning of buffer
- (t
- (let ((empty t) ind more less)
- (if (looking-at ")")
- (setq less t) ;Find close
- (setq less nil))
- ;; See previous indentation
- (while empty
- (forward-line -1)
- (beginning-of-line)
- (if (bobp)
- (setq empty nil)
- (skip-chars-forward " \t")
- (if (not (or (looking-at "%[^%]") (looking-at "\n")))
- (setq empty nil))))
- (if (bobp)
- (setq ind 0) ;Beginning of buffer
- (setq ind (current-column))) ;Beginning of clause
- ;; See its beginning
- (if (looking-at "%%[^%]")
- ind
- ;; Real prolog code
- (if (looking-at "(")
- (setq more t) ;Find open
- (setq more nil))
- ;; See its tail
- (end-of-prolog-clause)
- (or (bobp) (forward-char -1))
- (cond ((looking-at "[,(;>]")
- (if (and more (looking-at "[^,]"))
- (+ ind prolog-indent-width) ;More indentation
- (max tab-width ind))) ;Same indentation
- ((looking-at "-") tab-width) ;TAB
- ((or less (looking-at "[^.]"))
- (max (- ind prolog-indent-width) 0)) ;Less indentation
- (t 0)) ;No indentation
- )))
- )))
-
-(defun end-of-prolog-clause ()
- "Go to end of clause in this line."
- (beginning-of-line 1)
- (let* ((eolpos (save-excursion (end-of-line) (point))))
- (if (re-search-forward comment-start-skip eolpos 'move)
- (goto-char (match-beginning 0)))
- (skip-chars-backward " \t")))
-
-(defun prolog-comment-indent ()
- "Compute prolog comment indentation."
- (cond ((looking-at "%%%") 0)
- ((looking-at "%%") (prolog-indent-level))
- (t
- (save-excursion
- (skip-chars-backward " \t")
- ;; Insert one space at least, except at left margin.
- (max (+ (current-column) (if (bolp) 0 1))
- comment-column)))
- ))
-
-
-;;;
-;;; Inferior prolog mode
-;;;
-(defvar inferior-prolog-mode-map nil)
-
-(defun inferior-prolog-mode ()
- "Major mode for interacting with an inferior Prolog process.
-
-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'.
-
-You can send text to the inferior Prolog from other buffers
-using the commands `send-region', `send-string' and \\[prolog-consult-region].
-
-Commands:
-Tab indents for Prolog; with argument, shifts rest
- of expression rigidly with the current line.
-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."
- (interactive)
- (require 'comint)
- (comint-mode)
- (setq major-mode 'inferior-prolog-mode
- mode-name "Inferior Prolog"
- comint-prompt-regexp "^| [ ?][- ] *")
- (prolog-mode-variables)
- (if inferior-prolog-mode-map nil
- (setq inferior-prolog-mode-map (copy-keymap comint-mode-map))
- (prolog-mode-commands inferior-prolog-mode-map))
- (use-local-map inferior-prolog-mode-map)
- (run-hooks 'prolog-mode-hook))
-
-;;;###autoload
-(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))
- (inferior-prolog-mode))
-
-(defun prolog-consult-region (compile beg end)
- "Send the region to the Prolog process made by \"M-x run-prolog\".
-If COMPILE (prefix arg) is not nil, use compile mode rather than consult mode."
- (interactive "P\nr")
- (save-excursion
- (if compile
- (send-string "prolog" prolog-compile-string)
- (send-string "prolog" prolog-consult-string))
- (send-region "prolog" beg end)
- (send-string "prolog" "\n") ;May be unnecessary
- (if prolog-eof-string
- (send-string "prolog" prolog-eof-string)
- (process-send-eof "prolog")))) ;Send eof to prolog process.
-
-(defun prolog-consult-region-and-go (compile beg end)
- "Send the region to the inferior Prolog, and switch to *prolog* buffer.
-If COMPILE (prefix arg) is not nil, use compile mode rather than consult mode."
- (interactive "P\nr")
- (prolog-consult-region compile beg end)
- (switch-to-buffer "*prolog*"))
-
-;;; prolog.el ends here
diff --git a/lisp/progmodes/scheme.el b/lisp/progmodes/scheme.el
deleted file mode 100644
index a4393df8ee7..00000000000
--- a/lisp/progmodes/scheme.el
+++ /dev/null
@@ -1,515 +0,0 @@
-;;; scheme.el --- Scheme mode, and its idiosyncratic commands.
-
-;; Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
-
-;; Author: Bill Rozas <jinz@prep.ai.mit.edu>
-;; Keywords: languages, lisp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Adapted from Lisp mode by Bill Rozas, jinx@prep.
-;; Initially a query replace of Lisp mode, except for the indentation
-;; of special forms. Probably the code should be merged at some point
-;; so that there is sharing between both libraries.
-
-;;; Code:
-
-(defvar scheme-mode-syntax-table nil "")
-(if (not scheme-mode-syntax-table)
- (let ((i 0))
- (setq scheme-mode-syntax-table (make-syntax-table))
- (set-syntax-table scheme-mode-syntax-table)
-
- ;; Default is atom-constituent.
- (while (< i 256)
- (modify-syntax-entry i "_ ")
- (setq i (1+ i)))
-
- ;; Word components.
- (setq i ?0)
- (while (<= i ?9)
- (modify-syntax-entry i "w ")
- (setq i (1+ i)))
- (setq i ?A)
- (while (<= i ?Z)
- (modify-syntax-entry i "w ")
- (setq i (1+ i)))
- (setq i ?a)
- (while (<= i ?z)
- (modify-syntax-entry i "w ")
- (setq i (1+ i)))
-
- ;; Whitespace
- (modify-syntax-entry ?\t " ")
- (modify-syntax-entry ?\n "> ")
- (modify-syntax-entry ?\f " ")
- (modify-syntax-entry ?\r " ")
- (modify-syntax-entry ? " ")
-
- ;; These characters are delimiters but otherwise undefined.
- ;; Brackets and braces balance for editing convenience.
- (modify-syntax-entry ?[ "(] ")
- (modify-syntax-entry ?] ")[ ")
- (modify-syntax-entry ?{ "(} ")
- (modify-syntax-entry ?} "){ ")
- (modify-syntax-entry ?\| " 23")
-
- ;; Other atom delimiters
- (modify-syntax-entry ?\( "() ")
- (modify-syntax-entry ?\) ")( ")
- (modify-syntax-entry ?\; "< ")
- (modify-syntax-entry ?\" "\" ")
- (modify-syntax-entry ?' " p")
- (modify-syntax-entry ?` " p")
-
- ;; Special characters
- (modify-syntax-entry ?, "_ p")
- (modify-syntax-entry ?@ "_ p")
- (modify-syntax-entry ?# "_ p14")
- (modify-syntax-entry ?\\ "\\ ")))
-
-(defvar scheme-mode-abbrev-table nil "")
-(define-abbrev-table 'scheme-mode-abbrev-table ())
-
-(defun scheme-mode-variables ()
- (set-syntax-table scheme-mode-syntax-table)
- (setq local-abbrev-table scheme-mode-abbrev-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 'scheme-indent-line)
- (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)
- ;; Look within the line for a ; following an even number of backslashes
- ;; after either a non-backslash or the line beginning.
- (setq comment-start-skip "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\);+[ \t]*")
- (make-local-variable 'comment-column)
- (setq comment-column 40)
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'scheme-comment-indent)
- (make-local-variable 'parse-sexp-ignore-comments)
- (setq parse-sexp-ignore-comments t)
- (setq mode-line-process '("" scheme-mode-line-process)))
-
-(defvar scheme-mode-line-process "")
-
-(defun scheme-mode-commands (map)
- (define-key map "\t" 'scheme-indent-line)
- (define-key map "\177" 'backward-delete-char-untabify)
- (define-key map "\e\C-q" 'scheme-indent-sexp))
-
-(defvar scheme-mode-map nil)
-(if (not scheme-mode-map)
- (progn
- (setq scheme-mode-map (make-sparse-keymap))
- (scheme-mode-commands scheme-mode-map)))
-
-;;;###autoload
-(defun scheme-mode ()
- "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."
- (interactive)
- (kill-all-local-variables)
- (scheme-mode-initialize)
- (scheme-mode-variables)
- (run-hooks 'scheme-mode-hook))
-
-(defun scheme-mode-initialize ()
- (use-local-map scheme-mode-map)
- (setq major-mode 'scheme-mode)
- (setq mode-name "Scheme"))
-
-(defvar scheme-mit-dialect t
- "If non-nil, scheme mode is specialized for MIT Scheme.
-Set this to nil if you normally use another dialect.")
-
-(defun scheme-comment-indent (&optional pos)
- (save-excursion
- (if pos (goto-char pos))
- (cond ((looking-at ";;;") (current-column))
- ((looking-at ";;")
- (let ((tem (calculate-scheme-indent)))
- (if (listp tem) (car tem) tem)))
- (t
- (skip-chars-backward " \t")
- (max (if (bolp) 0 (1+ (current-column)))
- comment-column)))))
-
-(defvar scheme-indent-offset nil "")
-(defvar scheme-indent-function 'scheme-indent-function "")
-
-(defun scheme-indent-line (&optional whole-exp)
- "Indent current line as Scheme code.
-With argument, indent any additional lines of the same expression
-rigidly along with this one."
- (interactive "P")
- (let ((indent (calculate-scheme-indent)) shift-amt beg end
- (pos (- (point-max) (point))))
- (beginning-of-line)
- (setq beg (point))
- (skip-chars-forward " \t")
- (if (looking-at "[ \t]*;;;")
- ;; Don't alter indentation of a ;;; comment line.
- nil
- (if (listp indent) (setq indent (car indent)))
- (setq shift-amt (- indent (current-column)))
- (if (zerop shift-amt)
- nil
- (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)))
- ;; If desired, shift remaining lines of expression the same amount.
- (and whole-exp (not (zerop shift-amt))
- (save-excursion
- (goto-char beg)
- (forward-sexp 1)
- (setq end (point))
- (goto-char beg)
- (forward-line 1)
- (setq beg (point))
- (> end beg))
- (indent-code-rigidly beg end shift-amt)))))
-
-(defun calculate-scheme-indent (&optional parse-start)
- "Return appropriate indentation for current line as scheme code.
-In usual case returns an integer: the column to indent to.
-Can instead return a list, whose car is the column to indent to.
-This means that following lines at the same level of indentation
-should not necessarily be indented the same way.
-The second element of the list is the buffer position
-of the start of the containing expression."
- (save-excursion
- (beginning-of-line)
- (let ((indent-point (point)) state paren-depth desired-indent (retry t)
- last-sexp containing-sexp first-sexp-list-p)
- (if parse-start
- (goto-char parse-start)
- (beginning-of-defun))
- ;; Find outermost containing sexp
- (while (< (point) indent-point)
- (setq state (parse-partial-sexp (point) indent-point 0)))
- ;; Find innermost containing sexp
- (while (and retry (setq paren-depth (car state)) (> paren-depth 0))
- (setq retry nil)
- (setq last-sexp (nth 2 state))
- (setq containing-sexp (car (cdr state)))
- ;; Position following last unclosed open.
- (goto-char (1+ containing-sexp))
- ;; Is there a complete sexp since then?
- (if (and last-sexp (> last-sexp (point)))
- ;; Yes, but is there a containing sexp after that?
- (let ((peek (parse-partial-sexp last-sexp indent-point 0)))
- (if (setq retry (car (cdr peek))) (setq state peek))))
- (if (not retry)
- ;; Innermost containing sexp found
- (progn
- (goto-char (1+ containing-sexp))
- (if (not last-sexp)
- ;; indent-point immediately follows open paren.
- ;; Don't call hook.
- (setq desired-indent (current-column))
- ;; Move to first sexp after containing open paren
- (parse-partial-sexp (point) last-sexp 0 t)
- (setq first-sexp-list-p (looking-at "\\s("))
- (cond
- ((> (save-excursion (forward-line 1) (point))
- last-sexp)
- ;; Last sexp is on same line as containing sexp.
- ;; It's almost certainly a function call.
- (parse-partial-sexp (point) last-sexp 0 t)
- (if (/= (point) last-sexp)
- ;; Indent beneath first argument or, if only one sexp
- ;; on line, indent beneath that.
- (progn (forward-sexp 1)
- (parse-partial-sexp (point) last-sexp 0 t)))
- (backward-prefix-chars))
- (t
- ;; Indent beneath first sexp on same line as last-sexp.
- ;; Again, it's almost certainly a function call.
- (goto-char last-sexp)
- (beginning-of-line)
- (parse-partial-sexp (point) last-sexp 0 t)
- (backward-prefix-chars)))))))
- ;; If looking at a list, don't call hook.
- (if first-sexp-list-p
- (setq desired-indent (current-column)))
- ;; Point is at the point to indent under unless we are inside a string.
- ;; Call indentation hook except when overridden by scheme-indent-offset
- ;; or if the desired indentation has already been computed.
- (cond ((car (nthcdr 3 state))
- ;; Inside a string, don't change indentation.
- (goto-char indent-point)
- (skip-chars-forward " \t")
- (setq desired-indent (current-column)))
- ((and (integerp scheme-indent-offset) containing-sexp)
- ;; Indent by constant offset
- (goto-char containing-sexp)
- (setq desired-indent (+ scheme-indent-offset (current-column))))
- ((not (or desired-indent
- (and (boundp 'scheme-indent-function)
- scheme-indent-function
- (not retry)
- (setq desired-indent
- (funcall scheme-indent-function
- indent-point state)))))
- ;; Use default indentation if not computed yet
- (setq desired-indent (current-column))))
- desired-indent)))
-
-(defun scheme-indent-function (indent-point state)
- (let ((normal-indent (current-column)))
- (save-excursion
- (goto-char (1+ (car (cdr state))))
- (re-search-forward "\\sw\\|\\s_")
- (if (/= (point) (car (cdr state)))
- (let ((function (buffer-substring (progn (forward-char -1) (point))
- (progn (forward-sexp 1) (point))))
- method)
- ;; Who cares about this, really?
- ;(if (not (string-match "\\\\\\||" function)))
- (setq function (downcase function))
- (setq method (get (intern-soft function) 'scheme-indent-function))
- (cond ((integerp method)
- (scheme-indent-specform method state indent-point))
- (method
- (funcall method state indent-point))
- ((and (> (length function) 3)
- (string-equal (substring function 0 3) "def"))
- (scheme-indent-defform state indent-point))))))))
-
-(defvar scheme-body-indent 2 "")
-
-(defun scheme-indent-specform (count state indent-point)
- (let ((containing-form-start (car (cdr state))) (i count)
- 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
- ;; least one word or symbol character following open paren of containing
- ;; form.
- (goto-char containing-form-start)
- (setq containing-form-column (current-column))
- (setq body-indent (+ scheme-body-indent containing-form-column))
- (forward-char 1)
- (forward-sexp 1)
- ;; Now find the start of the last form.
- (parse-partial-sexp (point) indent-point 1 t)
- (while (and (< (point) indent-point)
- (condition-case nil
- (progn
- (setq count (1- count))
- (forward-sexp 1)
- (parse-partial-sexp (point) indent-point 1 t))
- (error nil))))
- ;; Point is sitting on first character of last (or count) sexp.
- (cond ((> count 0)
- ;; A distinguished form. Use double scheme-body-indent.
- (list (+ containing-form-column (* 2 scheme-body-indent))
- containing-form-start))
- ;; A non-distinguished form. Use body-indent if there are no
- ;; distinguished forms and this is the first undistinguished
- ;; form, or if this is the first undistinguished form and
- ;; the preceding distinguished form has indentation at least
- ;; as great as body-indent.
- ((and (= count 0)
- (or (= i 0)
- (<= body-indent normal-indent)))
- body-indent)
- (t
- normal-indent))))
-
-(defun scheme-indent-defform (state indent-point)
- (goto-char (car (cdr state)))
- (forward-line 1)
- (if (> (point) (car (cdr (cdr state))))
- (progn
- (goto-char (car (cdr state)))
- (+ scheme-body-indent (current-column)))))
-
-;;; Let is different in Scheme
-
-(defun would-be-symbol (string)
- (not (string-equal (substring string 0 1) "(")))
-
-(defun next-sexp-as-string ()
- ;; Assumes that protected by a save-excursion
- (forward-sexp 1)
- (let ((the-end (point)))
- (backward-sexp 1)
- (buffer-substring (point) the-end)))
-
-;; This is correct but too slow.
-;; The one below works almost always.
-;;(defun scheme-let-indent (state indent-point)
-;; (if (would-be-symbol (next-sexp-as-string))
-;; (scheme-indent-specform 2 state indent-point)
-;; (scheme-indent-specform 1 state indent-point)))
-
-(defun scheme-let-indent (state indent-point)
- (skip-chars-forward " \t")
- (if (looking-at "[-a-zA-Z0-9+*/?!@$%^&_:~]")
- (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
-;; 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)
-
-;;;; 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)))
-
-(defun scheme-indent-sexp ()
- "Indent each line of the list starting just after point."
- (interactive)
- (let ((indent-stack (list nil)) (next-depth 0) bol
- outer-loop-done inner-loop-done state this-indent)
- (save-excursion (forward-sexp 1))
- (save-excursion
- (setq outer-loop-done nil)
- (while (not outer-loop-done)
- (setq last-depth next-depth
- innerloop-done nil)
- (while (and (not innerloop-done)
- (not (setq outer-loop-done (eobp))))
- (setq state (parse-partial-sexp (point) (progn (end-of-line) (point))
- nil nil state))
- (setq next-depth (car state))
- (if (car (nthcdr 4 state))
- (progn (indent-for-comment)
- (end-of-line)
- (setcar (nthcdr 4 state) nil)))
- (if (car (nthcdr 3 state))
- (progn
- (forward-line 1)
- (setcar (nthcdr 5 state) nil))
- (setq innerloop-done t)))
- (if (setq outer-loop-done (<= next-depth 0))
- nil
- (while (> last-depth next-depth)
- (setq indent-stack (cdr indent-stack)
- last-depth (1- last-depth)))
- (while (< last-depth next-depth)
- (setq indent-stack (cons nil indent-stack)
- last-depth (1+ last-depth)))
- (forward-line 1)
- (setq bol (point))
- (skip-chars-forward " \t")
- (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-scheme-indent
- (if (car indent-stack) (- (car indent-stack))))))
- (if (integerp val)
- (setcar indent-stack
- (setq this-indent val))
- (if (cdr val)
- (setcar indent-stack (- (car (cdr val)))))
- (setq this-indent (car val)))))
- (if (/= (current-column) this-indent)
- (progn (delete-region bol (point))
- (indent-to this-indent)))))))))
-
-(provide 'scheme)
-
-;;; scheme.el ends here
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
deleted file mode 100644
index 6ba2856938f..00000000000
--- a/lisp/progmodes/sh-script.el
+++ /dev/null
@@ -1,1388 +0,0 @@
-;;; sh-script.el --- shell-script editing commands for Emacs
-
-;; Copyright (C) 1993, 1994, 1995, 1996 by Free Software Foundation, Inc.
-
-;; Author: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389
-;; Version: 2.0e
-;; Maintainer: FSF
-;; Keywords: languages, unix
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Major mode for editing shell scripts. Bourne, C and rc shells as well
-;; as various derivatives are supported and easily derived from. Structured
-;; statements can be inserted with one command or abbrev. Completion is
-;; available for filenames, variables known from the script, the shell and
-;; the environment as well as commands.
-
-;;; Known Bugs:
-
-;; - In Bourne the keyword `in' is not anchored to case, for, select ...
-;; - Variables in `"' strings aren't fontified because there's no way of
-;; syntactically distinguishing those from `'' strings.
-
-;;; Code:
-
-;; page 1: variables and settings
-;; page 2: mode-command and utility functions
-;; page 3: statement syntax-commands for various shells
-;; page 4: various other commands
-
-(require 'executable)
-
-(defvar sh-ancestor-alist
- '((ash . sh)
- (bash . jsh)
- (dtksh . ksh)
- (es . rc)
- (itcsh . tcsh)
- (jcsh . csh)
- (jsh . sh)
- (ksh . ksh88)
- (ksh88 . jsh)
- (oash . sh)
- (pdksh . ksh88)
- (posix . sh)
- (tcsh . csh)
- (wksh . ksh88)
- (wsh . sh)
- (zsh . ksh88))
- "*Alist showing the direct ancestor of various shells.
-This is the basis for `sh-feature'. See also `sh-alias-alist'.
-By default we have the following three hierarchies:
-
-csh C Shell
- jcsh C Shell with Job Control
- tcsh Toronto C Shell
- itcsh ? Toronto C Shell
-rc Plan 9 Shell
- es Extensible Shell
-sh Bourne Shell
- ash ? Shell
- jsh Bourne Shell with Job Control
- bash GNU Bourne Again Shell
- ksh88 Korn Shell '88
- ksh Korn Shell '93
- dtksh CDE Desktop Korn Shell
- pdksh Public Domain Korn Shell
- wksh Window Korn Shell
- zsh Z Shell
- oash SCO OA (curses) Shell
- posix IEEE 1003.2 Shell Standard
- wsh ? Shell")
-
-
-(defvar sh-alias-alist
- (nconc (if (eq system-type 'gnu/linux)
- '((csh . tcsh)
- (ksh . pdksh)))
- ;; for the time being
- '((ksh . ksh88)
- (sh5 . sh)))
- "*Alist for transforming shell names to what they really are.
-Use this where the name of the executable doesn't correspond to the type of
-shell it really is.")
-
-
-(defvar sh-shell-file
- (or
- ;; On MSDOS and Windows, collapse $SHELL to lower-case and remove
- ;; the executable extension, so comparisons with the list of
- ;; known shells work.
- (and (memq system-type '(ms-dos windows-nt))
- (file-name-sans-extension (downcase (getenv "SHELL"))))
- (getenv "SHELL")
- "/bin/sh")
- "*The executable file name for the shell being programmed.")
-
-
-(defvar sh-shell-arg
- ;; bash does not need any options when run in a shell script,
- '((bash)
- (csh . "-f")
- (pdksh)
- ;; Bill_Mann@praxisint.com says -p with ksh can do harm.
- (ksh88)
- ;; -p means don't initialize functions from the environment.
- (rc . "-p")
- ;; Someone proposed -motif, but we don't want to encourage
- ;; use of a non-free widget set.
- (wksh)
- ;; -f means don't run .zshrc.
- (zsh . "-f"))
- "*Single argument string for the magic number. See `sh-feature'.")
-
-(defvar sh-shell-variables nil
- "Alist of shell variable names that should be included in completion.
-These are used for completion in addition to all the variables named
-in `process-environment'. Each element looks like (VAR . VAR), where
-the car and cdr are the same symbol.")
-
-(defvar sh-shell-variables-initialized nil
- "Non-nil if `sh-shell-variables' is initialized.")
-
-(defun sh-canonicalize-shell (shell)
- "Convert a shell name SHELL to the one we should handle it as."
- (or (symbolp shell)
- (setq shell (intern shell)))
- (or (cdr (assq shell sh-alias-alist))
- shell))
-
-(defvar sh-shell (sh-canonicalize-shell (file-name-nondirectory sh-shell-file))
- "The shell being programmed. This is set by \\[sh-set-shell].")
-
-;;; I turned off this feature because it doesn't permit typing commands
-;;; in the usual way without help.
-;;;(defvar sh-abbrevs
-;;; '((csh eval sh-abbrevs shell
-;;; "switch" 'sh-case
-;;; "getopts" 'sh-while-getopts)
-
-;;; (es eval sh-abbrevs shell
-;;; "function" 'sh-function)
-
-;;; (ksh88 eval sh-abbrevs sh
-;;; "select" 'sh-select)
-
-;;; (rc eval sh-abbrevs shell
-;;; "case" 'sh-case
-;;; "function" 'sh-function)
-
-;;; (sh eval sh-abbrevs shell
-;;; "case" 'sh-case
-;;; "function" 'sh-function
-;;; "until" 'sh-until
-;;; "getopts" 'sh-while-getopts)
-
-;;; ;; The next entry is only used for defining the others
-;;; (shell "for" sh-for
-;;; "loop" sh-indexed-loop
-;;; "if" sh-if
-;;; "tmpfile" sh-tmp-file
-;;; "while" sh-while)
-
-;;; (zsh eval sh-abbrevs ksh88
-;;; "repeat" 'sh-repeat))
-;;; "Abbrev-table used in Shell-Script mode. See `sh-feature'.
-;;;Due to the internal workings of abbrev tables, the shell name symbol is
-;;;actually defined as the table for the like of \\[edit-abbrevs].")
-
-
-
-(defvar sh-mode-syntax-table
- '((sh eval sh-mode-syntax-table ()
- ?\# "<"
- ?\^l ">#"
- ?\n ">#"
- ?\" "\"\""
- ?\' "\"'"
- ?\` "\"`"
- ?$ "\\" ; `escape' so $# doesn't start a comment
- ?! "_"
- ?% "_"
- ?: "_"
- ?. "_"
- ?^ "_"
- ?~ "_")
- (csh eval identity sh)
- (rc eval identity sh))
- "Syntax-table used in Shell-Script mode. See `sh-feature'.")
-
-
-
-(defvar sh-mode-map
- (let ((map (make-sparse-keymap))
- (menu-map (make-sparse-keymap "Insert")))
- (define-key map "\C-c(" 'sh-function)
- (define-key map "\C-c\C-w" 'sh-while)
- (define-key map "\C-c\C-u" 'sh-until)
- (define-key map "\C-c\C-t" 'sh-tmp-file)
- (define-key map "\C-c\C-s" 'sh-select)
- (define-key map "\C-c\C-r" 'sh-repeat)
- (define-key map "\C-c\C-o" 'sh-while-getopts)
- (define-key map "\C-c\C-l" 'sh-indexed-loop)
- (define-key map "\C-c\C-i" 'sh-if)
- (define-key map "\C-c\C-f" 'sh-for)
- (define-key map "\C-c\C-c" 'sh-case)
-
- (define-key map "=" 'sh-assignment)
- (define-key map "\C-c+" 'sh-add)
- (define-key map "\C-\M-x" 'sh-execute-region)
- (define-key map "\C-c\C-x" 'executable-interpret)
- (define-key map "<" 'sh-maybe-here-document)
- (define-key map "(" 'skeleton-pair-insert-maybe)
- (define-key map "{" 'skeleton-pair-insert-maybe)
- (define-key map "[" 'skeleton-pair-insert-maybe)
- (define-key map "'" 'skeleton-pair-insert-maybe)
- (define-key map "`" 'skeleton-pair-insert-maybe)
- (define-key map "\"" 'skeleton-pair-insert-maybe)
-
- (define-key map "\t" 'sh-indent-line)
- (substitute-key-definition 'complete-tag 'comint-dynamic-complete
- map (current-global-map))
- (substitute-key-definition 'newline-and-indent 'sh-newline-and-indent
- map (current-global-map))
- (substitute-key-definition 'delete-backward-char
- 'backward-delete-char-untabify
- map (current-global-map))
- (define-key map "\C-c:" 'sh-set-shell)
- (substitute-key-definition 'beginning-of-defun
- 'sh-beginning-of-compound-command
- map (current-global-map))
- (substitute-key-definition 'backward-sentence 'sh-beginning-of-command
- map (current-global-map))
- (substitute-key-definition 'forward-sentence 'sh-end-of-command
- map (current-global-map))
- (define-key map [menu-bar insert] (cons "Insert" menu-map))
- (define-key menu-map [sh-while] '("While Loop" . sh-while))
- (define-key menu-map [sh-until] '("Until Loop" . sh-until))
- (define-key menu-map [sh-tmp-file] '("Temporary File" . sh-tmp-file))
- (define-key menu-map [sh-select] '("Select Statement" . sh-select))
- (define-key menu-map [sh-repeat] '("Repeat Loop" . sh-repeat))
- (define-key menu-map [sh-while-getopts]
- '("Options Loop" . sh-while-getopts))
- (define-key menu-map [sh-indexed-loop]
- '("Indexed Loop" . sh-indexed-loop))
- (define-key menu-map [sh-if] '("If Statement" . sh-if))
- (define-key menu-map [sh-for] '("For Loop" . sh-for))
- (define-key menu-map [sh-case] '("Case Statement" . sh-case))
- map)
- "Keymap used in Shell-Script mode.")
-
-
-
-(defvar sh-dynamic-complete-functions
- '(shell-dynamic-complete-environment-variable
- shell-dynamic-complete-command
- comint-dynamic-complete-filename)
- "*Functions for doing TAB dynamic completion.")
-
-
-(defvar sh-require-final-newline
- '((csh . t)
- (pdksh . t)
- (rc eval . require-final-newline)
- (sh eval . require-final-newline))
- "*Value of `require-final-newline' in Shell-Script mode buffers.
-See `sh-feature'.")
-
-
-(defvar sh-assignment-regexp
- '((csh . "\\<\\([a-zA-Z0-9_]+\\)\\(\\[.+\\]\\)?[ \t]*[-+*/%^]?=")
- ;; actually spaces are only supported in let/(( ... ))
- (ksh88 . "\\<\\([a-zA-Z0-9_]+\\)\\(\\[.+\\]\\)?[ \t]*\\([-+*/%&|~^]\\|<<\\|>>\\)?=")
- (rc . "\\<\\([a-zA-Z0-9_*]+\\)[ \t]*=")
- (sh . "\\<\\([a-zA-Z0-9_]+\\)="))
- "*Regexp for the variable name and what may follow in an assignment.
-First grouping matches the variable name. This is upto and including the `='
-sign. See `sh-feature'.")
-
-
-(defvar sh-indentation 4
- "The width for further indentation in Shell-Script mode.")
-
-
-(defvar sh-remember-variable-min 3
- "*Don't remember variables less than this length for completing reads.")
-
-
-(defvar sh-header-marker nil
- "When non-`nil' is the end of header for prepending by \\[sh-execute-region].
-That command is also used for setting this variable.")
-
-
-(defvar sh-beginning-of-command
- "\\([;({`|&]\\|\\`\\|[^\\]\n\\)[ \t]*\\([/~a-zA-Z0-9:]\\)"
- "*Regexp to determine the beginning of a shell command.
-The actual command starts at the beginning of the second \\(grouping\\).")
-
-
-(defvar sh-end-of-command
- "\\([/~a-zA-Z0-9:]\\)[ \t]*\\([;#)}`|&]\\|$\\)"
- "*Regexp to determine the end of a shell command.
-The actual command ends at the end of the first \\(grouping\\).")
-
-
-
-(defvar sh-here-document-word "EOF"
- "Word to delimit here documents.")
-
-(defvar sh-test
- '((sh "[ ]" . 3)
- (ksh88 "[[ ]]" . 4))
- "Initial input in Bourne if, while and until skeletons. See `sh-feature'.")
-
-
-(defvar sh-builtins
- '((bash eval sh-append posix
- "alias" "bg" "bind" "builtin" "declare" "dirs" "enable" "fc" "fg"
- "help" "history" "jobs" "kill" "let" "local" "popd" "pushd" "source"
- "suspend" "typeset" "unalias")
-
- ;; The next entry is only used for defining the others
- (bourne eval sh-append shell
- "eval" "export" "getopts" "newgrp" "pwd" "read" "readonly"
- "times" "ulimit")
-
- (csh eval sh-append shell
- "alias" "chdir" "glob" "history" "limit" "nice" "nohup" "rehash"
- "setenv" "source" "time" "unalias" "unhash")
-
- (dtksh eval identity wksh)
-
- (es "access" "apids" "cd" "echo" "eval" "false" "let" "limit" "local"
- "newpgrp" "result" "time" "umask" "var" "vars" "wait" "whatis")
-
- (jsh eval sh-append sh
- "bg" "fg" "jobs" "kill" "stop" "suspend")
-
- (jcsh eval sh-append csh
- "bg" "fg" "jobs" "kill" "notify" "stop" "suspend")
-
- (ksh88 eval sh-append bourne
- "alias" "bg" "false" "fc" "fg" "jobs" "kill" "let" "print" "time"
- "typeset" "unalias" "whence")
-
- (oash eval sh-append sh
- "checkwin" "dateline" "error" "form" "menu" "newwin" "oadeinit"
- "oaed" "oahelp" "oainit" "pp" "ppfile" "scan" "scrollok" "wattr"
- "wclear" "werase" "win" "wmclose" "wmmessage" "wmopen" "wmove"
- "wmtitle" "wrefresh")
-
- (pdksh eval sh-append ksh88
- "bind")
-
- (posix eval sh-append sh
- "command")
-
- (rc "builtin" "cd" "echo" "eval" "limit" "newpgrp" "shift" "umask" "wait"
- "whatis")
-
- (sh eval sh-append bourne
- "hash" "test" "type")
-
- ;; The next entry is only used for defining the others
- (shell "cd" "echo" "eval" "set" "shift" "umask" "unset" "wait")
-
- (wksh eval sh-append ksh88
- "Xt[A-Z][A-Za-z]*")
-
- (zsh eval sh-append ksh88
- "autoload" "bindkey" "builtin" "chdir" "compctl" "declare" "dirs"
- "disable" "disown" "echotc" "enable" "functions" "getln" "hash"
- "history" "integer" "limit" "local" "log" "popd" "pushd" "r"
- "readonly" "rehash" "sched" "setopt" "source" "suspend" "true"
- "ttyctl" "type" "unfunction" "unhash" "unlimit" "unsetopt" "vared"
- "which"))
- "*List of all shell builtins for completing read and fontification.
-Note that on some systems not all builtins are available or some are
-implemented as aliases. See `sh-feature'.")
-
-
-
-(defvar sh-leading-keywords
- '((csh "else")
-
- (es "true" "unwind-protect" "whatis")
-
- (rc "else")
-
- (sh "do" "elif" "else" "if" "then" "trap" "type" "until" "while"))
- "*List of keywords that may be immediately followed by a builtin or keyword.
-Given some confusion between keywords and builtins depending on shell and
-system, the distinction here has been based on whether they influence the
-flow of control or syntax. See `sh-feature'.")
-
-
-(defvar sh-other-keywords
- '((bash eval sh-append bourne
- "bye" "logout")
-
- ;; The next entry is only used for defining the others
- (bourne eval sh-append sh
- "function")
-
- (csh eval sh-append shell
- "breaksw" "default" "end" "endif" "endsw" "foreach" "goto"
- "if" "logout" "onintr" "repeat" "switch" "then" "while")
-
- (es "break" "catch" "exec" "exit" "fn" "for" "forever" "fork" "if"
- "return" "throw" "while")
-
- (ksh88 eval sh-append bourne
- "select")
-
- (rc "break" "case" "exec" "exit" "fn" "for" "if" "in" "return" "switch"
- "while")
-
- (sh eval sh-append shell
- "done" "esac" "fi" "for" "in" "return")
-
- ;; The next entry is only used for defining the others
- (shell "break" "case" "continue" "exec" "exit")
-
- (zsh eval sh-append bash
- "select"))
- "*List of keywords not in `sh-leading-keywords'.
-See `sh-feature'.")
-
-
-
-(defvar sh-variables
- '((bash eval sh-append sh
- "allow_null_glob_expansion" "auto_resume" "BASH" "BASH_VERSION"
- "cdable_vars" "ENV" "EUID" "FCEDIT" "FIGNORE" "glob_dot_filenames"
- "histchars" "HISTFILE" "HISTFILESIZE" "history_control" "HISTSIZE"
- "hostname_completion_file" "HOSTTYPE" "IGNOREEOF" "ignoreeof"
- "LINENO" "MAIL_WARNING" "noclobber" "nolinks" "notify"
- "no_exit_on_failed_exec" "NO_PROMPT_VARS" "OLDPWD" "OPTERR" "PPID"
- "PROMPT_COMMAND" "PS4" "pushd_silent" "PWD" "RANDOM" "REPLY"
- "SECONDS" "SHLVL" "TMOUT" "UID")
-
- (csh eval sh-append shell
- "argv" "cdpath" "child" "echo" "histchars" "history" "home"
- "ignoreeof" "mail" "noclobber" "noglob" "nonomatch" "path" "prompt"
- "shell" "status" "time" "verbose")
-
- (es eval sh-append shell
- "apid" "cdpath" "CDPATH" "history" "home" "ifs" "noexport" "path"
- "pid" "prompt" "signals")
-
- (jcsh eval sh-append csh
- "notify")
-
- (ksh88 eval sh-append sh
- "ENV" "ERRNO" "FCEDIT" "FPATH" "HISTFILE" "HISTSIZE" "LINENO"
- "OLDPWD" "PPID" "PS3" "PS4" "PWD" "RANDOM" "REPLY" "SECONDS"
- "TMOUT")
-
- (oash eval sh-append sh
- "FIELD" "FIELD_MAX" "LAST_KEY" "OALIB" "PP_ITEM" "PP_NUM")
-
- (rc eval sh-append shell
- "apid" "apids" "cdpath" "CDPATH" "history" "home" "ifs" "path" "pid"
- "prompt" "status")
-
- (sh eval sh-append shell
- "CDPATH" "IFS" "OPTARG" "OPTIND" "PS1" "PS2")
-
- ;; The next entry is only used for defining the others
- (shell "COLUMNS" "EDITOR" "HOME" "HUSHLOGIN" "LANG" "LC_COLLATE"
- "LC_CTYPE" "LC_MESSAGES" "LC_MONETARY" "LC_NUMERIC" "LC_TIME"
- "LINES" "LOGNAME" "MAIL" "MAILCHECK" "MAILPATH" "PAGER" "PATH"
- "SHELL" "TERM" "TERMCAP" "TERMINFO" "VISUAL")
-
- (tcsh eval sh-append csh
- "addsuffix" "ampm" "autocorrect" "autoexpand" "autolist"
- "autologout" "chase_symlinks" "correct" "dextract" "edit" "el"
- "fignore" "gid" "histlit" "HOST" "HOSTTYPE" "HPATH"
- "ignore_symlinks" "listjobs" "listlinks" "listmax" "matchbeep"
- "nobeep" "NOREBIND" "oid" "printexitvalue" "prompt2" "prompt3"
- "pushdsilent" "pushdtohome" "recexact" "recognize_only_executables"
- "rmstar" "savehist" "SHLVL" "showdots" "sl" "SYSTYPE" "tcsh" "term"
- "tperiod" "tty" "uid" "version" "visiblebell" "watch" "who"
- "wordchars")
-
- (zsh eval sh-append ksh88
- "BAUD" "bindcmds" "cdpath" "DIRSTACKSIZE" "fignore" "FIGNORE" "fpath"
- "HISTCHARS" "hostcmds" "hosts" "HOSTS" "LISTMAX" "LITHISTSIZE"
- "LOGCHECK" "mailpath" "manpath" "NULLCMD" "optcmds" "path" "POSTEDIT"
- "prompt" "PROMPT" "PROMPT2" "PROMPT3" "PROMPT4" "psvar" "PSVAR"
- "READNULLCMD" "REPORTTIME" "RPROMPT" "RPS1" "SAVEHIST" "SPROMPT"
- "STTY" "TIMEFMT" "TMOUT" "TMPPREFIX" "varcmds" "watch" "WATCH"
- "WATCHFMT" "WORDCHARS" "ZDOTDIR"))
- "List of all shell variables available for completing read.
-See `sh-feature'.")
-
-
-
-(defvar sh-font-lock-keywords
- '((csh eval sh-append shell
- '("\\${?[#?]?\\([A-Za-z_][A-Za-z0-9_]*\\|0\\)" 1
- font-lock-variable-name-face))
-
- (es eval sh-append executable-font-lock-keywords
- '("\\$#?\\([A-Za-z_][A-Za-z0-9_]*\\|[0-9]+\\)" 1
- font-lock-variable-name-face))
-
- (rc eval identity es)
-
- (sh eval sh-append shell
- '("\\$\\({#?\\)?\\([A-Za-z_][A-Za-z0-9_]*\\|[-#?@!]\\)" 2
- font-lock-variable-name-face))
-
- ;; The next entry is only used for defining the others
- (shell eval sh-append executable-font-lock-keywords
- '("\\\\[^A-Za-z0-9]" 0 font-lock-string-face)
- '("\\${?\\([A-Za-z_][A-Za-z0-9_]*\\|[0-9]+\\|[$*_]\\)" 1
- font-lock-variable-name-face)))
- "*Rules for highlighting shell scripts. See `sh-feature'.")
-
-(defvar sh-font-lock-keywords-1
- '((sh "[ \t]in\\>"))
- "*Additional rules for highlighting shell scripts. See `sh-feature'.")
-
-(defvar sh-font-lock-keywords-2 ()
- "*Yet more rules for highlighting shell scripts. See `sh-feature'.")
-
-
-;; mode-command and utility functions
-
-;;;###autoload
-(put 'sh-mode 'mode-class 'special)
-
-;;;###autoload
-(defun sh-mode ()
- "Major mode for editing shell scripts.
-This mode works for many shells, since they all have roughly the same syntax,
-as far as commands, arguments, variables, pipes, comments etc. are concerned.
-Unless the file's magic number indicates the shell, your usual shell is
-assumed. Since filenames rarely give a clue, they are not further analyzed.
-
-This mode adapts to the variations between shells (see `sh-set-shell') by
-means of an inheritance based feature lookup (see `sh-feature'). This
-mechanism applies to all variables (including skeletons) that pertain to
-shell-specific features.
-
-The default style of this mode is that of Rosenblatt's Korn shell book.
-The syntax of the statements varies with the shell being used. The
-following commands are available, based on the current shell's syntax:
-
-\\[sh-case] case statement
-\\[sh-for] for loop
-\\[sh-function] function definition
-\\[sh-if] if statement
-\\[sh-indexed-loop] indexed loop from 1 to n
-\\[sh-while-getopts] while getopts loop
-\\[sh-repeat] repeat loop
-\\[sh-select] select loop
-\\[sh-until] until loop
-\\[sh-while] while loop
-
-\\[backward-delete-char-untabify] Delete backward one position, even if it was a tab.
-\\[sh-newline-and-indent] Delete unquoted space and indent new line same as this one.
-\\[sh-end-of-command] Go to end of successive commands.
-\\[sh-beginning-of-command] Go to beginning of successive commands.
-\\[sh-set-shell] Set this buffer's shell, and maybe its magic number.
-\\[sh-execute-region] Have optional header and region be executed in a subshell.
-
-\\[sh-maybe-here-document] Without prefix, following an unquoted < inserts here document.
-{, (, [, ', \", `
- Unless quoted with \\, insert the pairs {}, (), [], or '', \"\", ``.
-
-If you generally program a shell different from your login shell you can
-set `sh-shell-file' accordingly. If your shell's file name doesn't correctly
-indicate what shell it is use `sh-alias-alist' to translate.
-
-If your shell gives error messages with line numbers, you can use \\[executable-interpret]
-with your script for an edit-interpret-debug cycle."
- (interactive)
- (kill-all-local-variables)
- (use-local-map sh-mode-map)
- (make-local-variable 'indent-line-function)
- (make-local-variable 'indent-region-function)
- (make-local-variable 'skeleton-end-hook)
- (make-local-variable 'paragraph-start)
- (make-local-variable 'paragraph-separate)
- (make-local-variable 'comment-start)
- (make-local-variable 'comment-start-skip)
- (make-local-variable 'require-final-newline)
- (make-local-variable 'sh-header-marker)
- (make-local-variable 'sh-shell-file)
- (make-local-variable 'sh-shell)
- (make-local-variable 'skeleton-pair-alist)
- (make-local-variable 'skeleton-pair-filter)
- (make-local-variable 'comint-dynamic-complete-functions)
- (make-local-variable 'comint-prompt-regexp)
- (make-local-variable 'font-lock-defaults)
- (make-local-variable 'skeleton-filter)
- (make-local-variable 'skeleton-newline-indent-rigidly)
- (make-local-variable 'sh-shell-variables)
- (make-local-variable 'sh-shell-variables-initialized)
- (setq major-mode 'sh-mode
- mode-name "Shell-script"
- indent-line-function 'sh-indent-line
- ;; not very clever, but enables wrapping skeletons around regions
- indent-region-function (lambda (b e)
- (save-excursion
- (goto-char b)
- (skip-syntax-backward "-")
- (setq b (point))
- (goto-char e)
- (skip-syntax-backward "-")
- (indent-rigidly b (point) sh-indentation)))
- skeleton-end-hook (lambda ()
- (or (eolp) (newline) (indent-relative)))
- paragraph-start (concat page-delimiter "\\|$")
- paragraph-separate paragraph-start
- comment-start "# "
- comint-dynamic-complete-functions sh-dynamic-complete-functions
- ;; we can't look if previous line ended with `\'
- comint-prompt-regexp "^[ \t]*"
- font-lock-defaults
- `((sh-font-lock-keywords
- sh-font-lock-keywords-1
- sh-font-lock-keywords-2)
- nil nil
- ((?/ . "w") (?~ . "w") (?. . "w") (?- . "w") (?_ . "w")))
- skeleton-pair-alist '((?` _ ?`))
- skeleton-pair-filter 'sh-quoted-p
- skeleton-further-elements '((< '(- (min sh-indentation
- (current-column)))))
- skeleton-filter 'sh-feature
- skeleton-newline-indent-rigidly t)
- ;; Parse or insert magic number for exec, and set all variables depending
- ;; on the shell thus determined.
- (let ((interpreter
- (save-excursion
- (goto-char (point-min))
- (if (looking-at "#![ \t]?\\([^ \t\n]*/bin/env[ \t]\\)?\\([^ \t\n]+\\)")
- (buffer-substring (match-beginning 2)
- (match-end 2))))))
- (if interpreter
- (sh-set-shell interpreter nil nil)))
- (run-hooks 'sh-mode-hook))
-;;;###autoload
-(defalias 'shell-script-mode 'sh-mode)
-
-
-(defun sh-font-lock-keywords (&optional keywords)
- "Function to get simple fontification based on `sh-font-lock-keywords'.
-This adds rules for comments and assignments."
- (sh-feature sh-font-lock-keywords
- (lambda (list)
- `((,(sh-feature sh-assignment-regexp)
- 1 font-lock-variable-name-face)
- ,@keywords
- ,@list))))
-
-(defun sh-font-lock-keywords-1 (&optional builtins)
- "Function to get better fontification including keywords."
- (let ((keywords (concat "\\([;(){}`|&]\\|^\\)[ \t]*\\(\\(\\("
- (mapconcat 'identity
- (sh-feature sh-leading-keywords)
- "\\|")
- "\\)[ \t]+\\)?\\("
- (mapconcat 'identity
- (append (sh-feature sh-leading-keywords)
- (sh-feature sh-other-keywords))
- "\\|")
- "\\)")))
- (sh-font-lock-keywords
- `(,@(if builtins
- `((,(concat keywords "[ \t]+\\)?\\("
- (mapconcat 'identity (sh-feature sh-builtins) "\\|")
- "\\)\\>")
- (2 font-lock-keyword-face nil t)
- (6 font-lock-builtin-face))
- ,@(sh-feature sh-font-lock-keywords-2)))
- (,(concat keywords "\\)\\>")
- 2 font-lock-keyword-face)
- ,@(sh-feature sh-font-lock-keywords-1)))))
-
-(defun sh-font-lock-keywords-2 ()
- "Function to get better fontification including keywords and builtins."
- (sh-font-lock-keywords-1 t))
-
-
-(defun sh-set-shell (shell &optional no-query-flag insert-flag)
- "Set this buffer's shell to SHELL (a string).
-Makes this script executable via `executable-set-magic', and sets up the
-proper starting #!-line, if INSERT-FLAG is non-nil.
-Calls the value of `sh-set-shell-hook' if set."
- (interactive (list (completing-read "Name or path of shell: "
- interpreter-mode-alist
- (lambda (x) (eq (cdr x) 'sh-mode)))
- (eq executable-query 'function)
- t))
- (setq sh-shell (intern (file-name-nondirectory shell))
- sh-shell (or (cdr (assq sh-shell sh-alias-alist))
- sh-shell))
- (if insert-flag
- (setq sh-shell-file
- (executable-set-magic shell (sh-feature sh-shell-arg)
- no-query-flag insert-flag)))
- (setq require-final-newline (sh-feature sh-require-final-newline)
-;;; local-abbrev-table (sh-feature sh-abbrevs)
- font-lock-keywords nil ; force resetting
- font-lock-syntax-table nil
- comment-start-skip "#+[\t ]*"
- mode-line-process (format "[%s]" sh-shell)
- sh-shell-variables nil
- sh-shell-variables-initialized nil
- shell (sh-feature sh-variables))
- (set-syntax-table (sh-feature sh-mode-syntax-table))
- (while shell
- (sh-remember-variable (car shell))
- (setq shell (cdr shell)))
- (and (boundp 'font-lock-mode)
- font-lock-mode
- (font-lock-mode (font-lock-mode 0)))
- (run-hooks 'sh-set-shell-hook))
-
-
-
-(defun sh-feature (list &optional function)
- "Index ALIST by the current shell.
-If ALIST isn't a list where every element is a cons, it is returned as is.
-Else indexing follows an inheritance logic which works in two ways:
-
- - Fall back on successive ancestors (see `sh-ancestor-alist') as long as
- the alist contains no value for the current shell.
-
- - If the value thus looked up is a list starting with `eval' its `cdr' is
- first evaluated. If that is also a list and the first argument is a
- symbol in ALIST it is not evaluated, but rather recursively looked up in
- ALIST to allow the function called to define the value for one shell to be
- derived from another shell. While calling the function, is the car of the
- alist element is the current shell.
- The value thus determined is physically replaced into the alist.
-
-Optional FUNCTION is applied to the determined value and the result is cached
-in ALIST."
- (or (if (consp list)
- (let ((l list))
- (while (and l (consp (car l)))
- (setq l (cdr l)))
- (if l list)))
- (if function
- (cdr (assoc (setq function (cons sh-shell function)) list)))
- (let ((sh-shell sh-shell)
- elt val)
- (while (and sh-shell
- (not (setq elt (assq sh-shell list))))
- (setq sh-shell (cdr (assq sh-shell sh-ancestor-alist))))
- (if (and (consp (setq val (cdr elt)))
- (eq (car val) 'eval))
- (setcdr elt
- (setq val
- (eval (if (consp (setq val (cdr val)))
- (let ((sh-shell (car (cdr val)))
- function)
- (if (assq sh-shell list)
- (setcar (cdr val)
- (list 'quote
- (sh-feature list))))
- val)
- val)))))
- (if function
- (nconc list
- (list (cons function
- (setq sh-shell (car function)
- val (funcall (cdr function) val))))))
- val)))
-
-
-
-;;; I commented this out because nobody calls it -- rms.
-;;;(defun sh-abbrevs (ancestor &rest list)
-;;; "Iff it isn't, define the current shell as abbrev table and fill that.
-;;;Abbrev table will inherit all abbrevs from ANCESTOR, which is either an abbrev
-;;;table or a list of (NAME1 EXPANSION1 ...). In addition it will define abbrevs
-;;;according to the remaining arguments NAMEi EXPANSIONi ...
-;;;EXPANSION may be either a string or a skeleton command."
-;;; (or (if (boundp sh-shell)
-;;; (symbol-value sh-shell))
-;;; (progn
-;;; (if (listp ancestor)
-;;; (nconc list ancestor))
-;;; (define-abbrev-table sh-shell ())
-;;; (if (vectorp ancestor)
-;;; (mapatoms (lambda (atom)
-;;; (or (eq atom 0)
-;;; (define-abbrev (symbol-value sh-shell)
-;;; (symbol-name atom)
-;;; (symbol-value atom)
-;;; (symbol-function atom))))
-;;; ancestor))
-;;; (while list
-;;; (define-abbrev (symbol-value sh-shell)
-;;; (car list)
-;;; (if (stringp (car (cdr list)))
-;;; (car (cdr list))
-;;; "")
-;;; (if (symbolp (car (cdr list)))
-;;; (car (cdr list))))
-;;; (setq list (cdr (cdr list)))))
-;;; (symbol-value sh-shell)))
-
-
-(defun sh-mode-syntax-table (table &rest list)
- "Copy TABLE and set syntax for successive CHARs according to strings S."
- (setq table (copy-syntax-table table))
- (while list
- (modify-syntax-entry (car list) (car (cdr list)) table)
- (setq list (cdr (cdr list))))
- table)
-
-
-(defun sh-append (ancestor &rest list)
- "Return list composed of first argument (a list) physically appended to rest."
- (nconc list ancestor))
-
-
-(defun sh-modify (skeleton &rest list)
- "Modify a copy of SKELETON by replacing I1 with REPL1, I2 with REPL2 ..."
- (setq skeleton (copy-sequence skeleton))
- (while list
- (setcar (or (nthcdr (car list) skeleton)
- (error "Index %d out of bounds" (car list)))
- (car (cdr list)))
- (setq list (nthcdr 2 list)))
- skeleton)
-
-
-(defun sh-indent-line ()
- "Indent as far as preceding non-empty line, then by steps of `sh-indentation'.
-Lines containing only comments are considered empty."
- (interactive)
- (let ((previous (save-excursion
- (while (and (not (bobp))
- (progn
- (forward-line -1)
- (back-to-indentation)
- (or (eolp)
- (eq (following-char) ?#)))))
- (current-column)))
- current)
- (save-excursion
- (indent-to (if (eq this-command 'newline-and-indent)
- previous
- (if (< (current-column)
- (setq current (progn (back-to-indentation)
- (current-column))))
- (if (eolp) previous 0)
- (delete-region (point)
- (progn (beginning-of-line) (point)))
- (if (eolp)
- (max previous (* (1+ (/ current sh-indentation))
- sh-indentation))
- (* (1+ (/ current sh-indentation)) sh-indentation))))))
- (if (< (current-column) (current-indentation))
- (skip-chars-forward " \t"))))
-
-
-(defun sh-execute-region (start end &optional flag)
- "Pass optional header and region to a subshell for noninteractive execution.
-The working directory is that of the buffer, and only environment variables
-are already set which is why you can mark a header within the script.
-
-With a positive prefix ARG, instead of sending region, define header from
-beginning of buffer to point. With a negative prefix ARG, instead of sending
-region, clear header."
- (interactive "r\nP")
- (if flag
- (setq sh-header-marker (if (> (prefix-numeric-value flag) 0)
- (point-marker)))
- (if sh-header-marker
- (save-excursion
- (let (buffer-undo-list)
- (goto-char sh-header-marker)
- (append-to-buffer (current-buffer) start end)
- (shell-command-on-region (point-min)
- (setq end (+ sh-header-marker
- (- end start)))
- sh-shell-file)
- (delete-region sh-header-marker end)))
- (shell-command-on-region start end (concat sh-shell-file " -")))))
-
-
-(defun sh-remember-variable (var)
- "Make VARIABLE available for future completing reads in this buffer."
- (or (< (length var) sh-remember-variable-min)
- (getenv var)
- (assoc var sh-shell-variables)
- (setq sh-shell-variables (cons (cons var var) sh-shell-variables)))
- var)
-
-
-
-(defun sh-quoted-p ()
- "Is point preceded by an odd number of backslashes?"
- (eq -1 (% (save-excursion (skip-chars-backward "\\\\")) 2)))
-
-;; statement syntax-commands for various shells
-
-;; You are welcome to add the syntax or even completely new statements as
-;; appropriate for your favorite shell.
-
-(define-skeleton sh-case
- "Insert a case/switch statement. See `sh-feature'."
- (csh "expression: "
- "switch( " str " )" \n
- > "case " (read-string "pattern: ") ?: \n
- > _ \n
- "breaksw" \n
- ( "other pattern, %s: "
- < "case " str ?: \n
- > _ \n
- "breaksw" \n)
- < "default:" \n
- > _ \n
- resume:
- < < "endsw")
- (es)
- (rc "expression: "
- "switch( " str " ) {" \n
- > "case " (read-string "pattern: ") \n
- > _ \n
- ( "other pattern, %s: "
- < "case " str \n
- > _ \n)
- < "case *" \n
- > _ \n
- resume:
- < < ?})
- (sh "expression: "
- "case " str " in" \n
- > (read-string "pattern: ") ?\) \n
- > _ \n
- ";;" \n
- ( "other pattern, %s: "
- < str ?\) \n
- > _ \n
- ";;" \n)
- < "*)" \n
- > _ \n
- resume:
- < < "esac"))
-(put 'sh-case 'menu-enable '(sh-feature sh-case))
-
-
-
-(define-skeleton sh-for
- "Insert a for loop. See `sh-feature'."
- (csh eval sh-modify sh
- 1 "foreach "
- 3 " ( "
- 5 " )"
- 15 "end")
- (es eval sh-modify rc
- 3 " = ")
- (rc eval sh-modify sh
- 1 "for( "
- 5 " ) {"
- 15 ?})
- (sh "Index variable: "
- "for " str " in " _ "; do" \n
- > _ | ?$ & (sh-remember-variable str) \n
- < "done"))
-
-
-
-(define-skeleton sh-indexed-loop
- "Insert an indexed loop from 1 to n. See `sh-feature'."
- (bash eval identity posix)
- (csh "Index variable: "
- "@ " str " = 1" \n
- "while( $" str " <= " (read-string "upper limit: ") " )" \n
- > _ ?$ str \n
- "@ " str "++" \n
- < "end")
- (es eval sh-modify rc
- 3 " =")
- (ksh88 "Index variable: "
- "integer " str "=0" \n
- "while (( ( " str " += 1 ) <= "
- (read-string "upper limit: ")
- " )); do" \n
- > _ ?$ (sh-remember-variable str) \n
- < "done")
- (posix "Index variable: "
- str "=1" \n
- "while [ $" str " -le "
- (read-string "upper limit: ")
- " ]; do" \n
- > _ ?$ str \n
- str ?= (sh-add (sh-remember-variable str) 1) \n
- < "done")
- (rc "Index variable: "
- "for( " str " in" " `{awk 'BEGIN { for( i=1; i<="
- (read-string "upper limit: ")
- "; i++ ) print i }'}) {" \n
- > _ ?$ (sh-remember-variable str) \n
- < ?})
- (sh "Index variable: "
- "for " str " in `awk 'BEGIN { for( i=1; i<="
- (read-string "upper limit: ")
- "; i++ ) print i }'`; do" \n
- > _ ?$ (sh-remember-variable str) \n
- < "done"))
-
-
-(defun sh-shell-initialize-variables ()
- "Scan the buffer for variable assignments.
-Add these variables to `sh-shell-variables'."
- (message "Scanning buffer `%s' for variable assignments..." (buffer-name))
- (save-excursion
- (goto-char (point-min))
- (setq sh-shell-variables-initialized t)
- (while (search-forward "=" nil t)
- (sh-assignment 0)))
- (message "Scanning buffer `%s' for variable assignments...done"
- (buffer-name)))
-
-(defvar sh-add-buffer)
-
-(defun sh-add-completer (string predicate code)
- "Do completion using `sh-shell-variables', but initialize it first.
-This function is designed for use as the \"completion table\",
-so it takes three arguments:
- STRING, the current buffer contents;
- PREDICATE, the predicate for filtering possible matches;
- CODE, which says what kind of things to do.
-CODE can be nil, t or `lambda'.
-nil means to return the best completion of STRING, or nil if there is none.
-t means to return a list of all possible completions of STRING.
-`lambda' means to return t if STRING is a valid completion as it stands."
- (let ((sh-shell-variables
- (save-excursion
- (set-buffer sh-add-buffer)
- (or sh-shell-variables-initialized
- (sh-shell-initialize-variables))
- (nconc (mapcar (lambda (var)
- (let ((name
- (substring var 0 (string-match "=" var))))
- (cons name name)))
- process-environment)
- sh-shell-variables))))
- (cond ((null code)
- (try-completion string sh-shell-variables predicate))
- ((eq code t)
- (all-completions string sh-shell-variables predicate))
- ((eq code 'lambda)
- (assoc string sh-shell-variables)))))
-
-(defun sh-add (var delta)
- "Insert an addition of VAR and prefix DELTA for Bourne (type) shell."
- (interactive
- (let ((sh-add-buffer (current-buffer)))
- (list (completing-read "Variable: " 'sh-add-completer)
- (prefix-numeric-value current-prefix-arg))))
- (insert (sh-feature '((bash . "$[ ")
- (ksh88 . "$(( ")
- (posix . "$(( ")
- (rc . "`{expr $")
- (sh . "`expr $")
- (zsh . "$[ ")))
- (sh-remember-variable var)
- (if (< delta 0) " - " " + ")
- (number-to-string (abs delta))
- (sh-feature '((bash . " ]")
- (ksh88 . " ))")
- (posix . " ))")
- (rc . "}")
- (sh . "`")
- (zsh . " ]")))))
-
-
-
-(define-skeleton sh-function
- "Insert a function definition. See `sh-feature'."
- (bash eval sh-modify ksh88
- 3 "() {")
- (ksh88 "name: "
- "function " str " {" \n
- > _ \n
- < "}")
- (rc eval sh-modify ksh88
- 1 "fn ")
- (sh ()
- "() {" \n
- > _ \n
- < "}"))
-
-
-
-(define-skeleton sh-if
- "Insert an if statement. See `sh-feature'."
- (csh "condition: "
- "if( " str " ) then" \n
- > _ \n
- ( "other condition, %s: "
- < "else if( " str " ) then" \n
- > _ \n)
- < "else" \n
- > _ \n
- resume:
- < "endif")
- (es "condition: "
- "if { " str " } {" \n
- > _ \n
- ( "other condition, %s: "
- < "} { " str " } {" \n
- > _ \n)
- < "} {" \n
- > _ \n
- resume:
- < ?})
- (rc eval sh-modify csh
- 3 " ) {"
- 8 '( "other condition, %s: "
- < "} else if( " str " ) {" \n
- > _ \n)
- 10 "} else {"
- 17 ?})
- (sh "condition: "
- '(setq input (sh-feature sh-test))
- "if " str "; then" \n
- > _ \n
- ( "other condition, %s: "
- < "elif " str "; then" \n
- > _ \n)
- < "else" \n
- > _ \n
- resume:
- < "fi"))
-
-
-
-(define-skeleton sh-repeat
- "Insert a repeat loop definition. See `sh-feature'."
- (es nil
- "forever {" \n
- > _ \n
- < ?})
- (zsh "factor: "
- "repeat " str "; do"\n
- > _ \n
- < "done"))
-(put 'sh-repeat 'menu-enable '(sh-feature sh-repeat))
-
-
-
-(define-skeleton sh-select
- "Insert a select statement. See `sh-feature'."
- (ksh88 "Index variable: "
- "select " str " in " _ "; do" \n
- > ?$ str \n
- < "done"))
-(put 'sh-select 'menu-enable '(sh-feature sh-select))
-
-
-
-(define-skeleton sh-tmp-file
- "Insert code to setup temporary file handling. See `sh-feature'."
- (bash eval identity ksh88)
- (csh (file-name-nondirectory (buffer-file-name))
- "set tmp = /tmp/" str ".$$" \n
- "onintr exit" \n _
- (and (goto-char (point-max))
- (not (bolp))
- ?\n)
- "exit:\n"
- "rm $tmp* >&/dev/null" >)
- (es (file-name-nondirectory (buffer-file-name))
- "local( signals = $signals sighup sigint; tmp = /tmp/" str ".$pid ) {" \n
- > "catch @ e {" \n
- > "rm $tmp^* >[2]/dev/null" \n
- "throw $e" \n
- < "} {" \n
- > _ \n
- < ?} \n
- < ?})
- (ksh88 eval sh-modify sh
- 6 "EXIT")
- (rc (file-name-nondirectory (buffer-file-name))
- "tmp = /tmp/" str ".$pid" \n
- "fn sigexit { rm $tmp^* >[2]/dev/null }")
- (sh (file-name-nondirectory (buffer-file-name))
- "TMP=/tmp/" str ".$$" \n
- "trap \"rm $TMP* 2>/dev/null\" " ?0))
-
-
-
-(define-skeleton sh-until
- "Insert an until loop. See `sh-feature'."
- (sh "condition: "
- '(setq input (sh-feature sh-test))
- "until " str "; do" \n
- > _ \n
- < "done"))
-(put 'sh-until 'menu-enable '(sh-feature sh-until))
-
-
-
-(define-skeleton sh-while
- "Insert a while loop. See `sh-feature'."
- (csh eval sh-modify sh
- 2 "while( "
- 4 " )"
- 10 "end")
- (es eval sh-modify rc
- 2 "while { "
- 4 " } {")
- (rc eval sh-modify csh
- 4 " ) {"
- 10 ?})
- (sh "condition: "
- '(setq input (sh-feature sh-test))
- "while " str "; do" \n
- > _ \n
- < "done"))
-
-
-
-(define-skeleton sh-while-getopts
- "Insert a while getopts loop. See `sh-feature'.
-Prompts for an options string which consists of letters for each recognized
-option followed by a colon `:' if the option accepts an argument."
- (bash eval sh-modify sh
- 18 "${0##*/}")
- (csh nil
- "while( 1 )" \n
- > "switch( \"$1\" )" \n
- '(setq input '("- x" . 2))
- > >
- ( "option, %s: "
- < "case " '(eval str)
- '(if (string-match " +" str)
- (setq v1 (substring str (match-end 0))
- str (substring str 0 (match-beginning 0)))
- (setq v1 nil))
- str ?: \n
- > "set " v1 & " = $2" | -4 & _ \n
- (if v1 "shift") & \n
- "breaksw" \n)
- < "case --:" \n
- > "shift" \n
- < "default:" \n
- > "break" \n
- resume:
- < < "endsw" \n
- "shift" \n
- < "end")
- (ksh88 eval sh-modify sh
- 16 "print"
- 18 "${0##*/}"
- 36 "OPTIND-1")
- (posix eval sh-modify sh
- 18 "$(basename $0)")
- (sh "optstring: "
- "while getopts :" str " OPT; do" \n
- > "case $OPT in" \n
- > >
- '(setq v1 (append (vconcat str) nil))
- ( (prog1 (if v1 (char-to-string (car v1)))
- (if (eq (nth 1 v1) ?:)
- (setq v1 (nthcdr 2 v1)
- v2 "\"$OPTARG\"")
- (setq v1 (cdr v1)
- v2 nil)))
- < str "|+" str ?\) \n
- > _ v2 \n
- ";;" \n)
- < "*)" \n
- > "echo" " \"usage: " "`basename $0`"
- " [+-" '(setq v1 (point)) str
- '(save-excursion
- (while (search-backward ":" v1 t)
- (replace-match " ARG] [+-" t t)))
- (if (eq (preceding-char) ?-) -5)
- "] [--] ARGS...\"" \n
- "exit 2" \n
- < < "esac" \n
- < "done" \n
- "shift " (sh-add "OPTIND" -1)))
-(put 'sh-while-getopts 'menu-enable '(sh-feature sh-while-getopts))
-
-
-
-(defun sh-assignment (arg)
- "Remember preceding identifier for future completion and do self-insert."
- (interactive "p")
- (self-insert-command arg)
- (if (<= arg 1)
- (sh-remember-variable
- (save-excursion
- (if (re-search-forward (sh-feature sh-assignment-regexp)
- (prog1 (point)
- (beginning-of-line 1))
- t)
- (match-string 1))))))
-
-
-
-(defun sh-maybe-here-document (arg)
- "Inserts self. Without prefix, following unquoted `<' inserts here document.
-The document is bounded by `sh-here-document-word'."
- (interactive "*P")
- (self-insert-command (prefix-numeric-value arg))
- (or arg
- (not (eq (char-after (- (point) 2)) last-command-char))
- (save-excursion
- (backward-char 2)
- (sh-quoted-p))
- (progn
- (insert sh-here-document-word)
- (or (eolp) (looking-at "[ \t]") (insert ? ))
- (end-of-line 1)
- (while
- (sh-quoted-p)
- (end-of-line 2))
- (newline)
- (save-excursion (insert ?\n sh-here-document-word)))))
-
-
-;; various other commands
-
-(autoload 'comint-dynamic-complete "comint"
- "Dynamically perform completion at point." t)
-
-(autoload 'shell-dynamic-complete-command "shell"
- "Dynamically complete the command at point." t)
-
-(autoload 'comint-dynamic-complete-filename "comint"
- "Dynamically complete the filename at point." t)
-
-(autoload 'shell-dynamic-complete-environment-variable "shell"
- "Dynamically complete the environment variable at point." t)
-
-
-
-(defun sh-newline-and-indent ()
- "Strip unquoted whitespace, insert newline, and indent like current line."
- (interactive "*")
- (indent-to (prog1 (current-indentation)
- (delete-region (point)
- (progn
- (or (zerop (skip-chars-backward " \t"))
- (if (sh-quoted-p)
- (forward-char)))
- (point)))
- (newline))))
-
-
-
-(defun sh-beginning-of-command ()
- "Move point to successive beginnings of commands."
- (interactive)
- (if (re-search-backward sh-beginning-of-command nil t)
- (goto-char (match-beginning 2))))
-
-
-(defun sh-end-of-command ()
- "Move point to successive ends of commands."
- (interactive)
- (if (re-search-forward sh-end-of-command nil t)
- (goto-char (match-end 1))))
-
-(provide 'sh-script)
-;; sh-script.el ends here
diff --git a/lisp/progmodes/simula.el b/lisp/progmodes/simula.el
deleted file mode 100644
index c4de80bfd61..00000000000
--- a/lisp/progmodes/simula.el
+++ /dev/null
@@ -1,1773 +0,0 @@
-;;; simula.el --- SIMULA 87 code editing commands for Emacs
-
-;; Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
-
-;; Author: Hans Henrik Eriksen <hhe@ifi.uio.no>
-;; Maintainer: simula-mode@ifi.uio.no
-;; Adapted-By: ESR
-;; Keywords: languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; A major mode for editing the Simula language. It knows about Simula
-;; syntax and standard indentation commands. It also provides convenient
-;; abbrevs for Simula keywords.
-;;
-;; Hans Henrik Eriksen (the author) may be reached at:
-;; Institutt for informatikk,
-;; Universitetet i Oslo
-
-;;; Code:
-
-
-(defconst simula-tab-always-indent-default nil
- "Non-nil means TAB in SIMULA mode should always reindent the current line.
-Otherwise TAB indents only when point is within
-the run of whitespace at the beginning of the line.")
-
-(defvar simula-tab-always-indent simula-tab-always-indent-default
- "*Non-nil means TAB in SIMULA mode should always reindent the current line.
-Otherwise TAB indents only when point is within
-the run of whitespace at the beginning of the line.")
-
-(defconst simula-indent-level-default 3
- "Indentation of SIMULA statements with respect to containing block.")
-
-(defvar simula-indent-level simula-indent-level-default
- "*Indentation of SIMULA statements with respect to containing block.")
-
-(defconst simula-substatement-offset-default 3
- "Extra indentation after DO, THEN, ELSE, WHEN and OTHERWISE.")
-
-(defvar simula-substatement-offset simula-substatement-offset-default
- "*Extra indentation after DO, THEN, ELSE, WHEN and OTHERWISE.")
-
-(defconst simula-continued-statement-offset-default 3
- "Extra indentation for lines not starting a statement or substatement.
-If value is a list, each line in a multipleline continued statement
-will have the car of the list extra indentation with respect to
-the previous line of the statement.")
-
-(defvar simula-continued-statement-offset simula-continued-statement-offset-default
- "*Extra indentation for lines not starting a statement or substatement.
-If value is a list, each line in a multipleline continued statement
-will have the car of the list extra indentation with respect to
-the previous line of the statement.")
-
-(defconst simula-label-offset-default -4711
- "Offset of SIMULA label lines relative to usual indentation.")
-
-(defvar simula-label-offset simula-label-offset-default
- "*Offset of SIMULA label lines relative to usual indentation.")
-
-(defconst simula-if-indent-default '(0 . 0)
- "Extra indentation of THEN and ELSE with respect to the starting IF.
-Value is a cons cell, the car is extra THEN indentation and the cdr
-extra ELSE indentation. IF after ELSE is indented as the starting IF.")
-
-(defvar simula-if-indent simula-if-indent-default
- "*Extra indentation of THEN and ELSE with respect to the starting IF.
-Value is a cons cell, the car is extra THEN indentation and the cdr
-extra ELSE indentation. IF after ELSE is indented as the starting IF.")
-
-(defconst simula-inspect-indent-default '(0 . 0)
- "Extra indentation of WHEN and OTHERWISE with respect to the INSPECT.
-Value is a cons cell, the car is extra WHEN indentation
-and the cdr extra OTHERWISE indentation.")
-
-(defvar simula-inspect-indent simula-inspect-indent-default
- "*Extra indentation of WHEN and OTHERWISE with respect to the INSPECT.
-Value is a cons cell, the car is extra WHEN indentation
-and the cdr extra OTHERWISE indentation.")
-
-(defconst simula-electric-indent-default nil
- "Non-nil means `simula-indent-line' function may reindent previous line.")
-
-(defvar simula-electric-indent simula-electric-indent-default
- "*Non-nil means `simula-indent-line' function may reindent previous line.")
-
-(defconst simula-abbrev-keyword-default 'upcase
- "Specify how to convert case for SIMULA keywords.
-Value is one of the symbols `upcase', `downcase', `capitalize',
-(as in) `abbrev-table' or nil if they should not be changed.")
-
-(defvar simula-abbrev-keyword simula-abbrev-keyword-default
- "*Specify how to convert case for SIMULA keywords.
-Value is one of the symbols `upcase', `downcase', `capitalize',
-(as in) `abbrev-table' or nil if they should not be changed.")
-
-(defconst simula-abbrev-stdproc-default 'abbrev-table
- "Specify how to convert case for standard SIMULA procedure and class names.
-Value is one of the symbols `upcase', `downcase', `capitalize',
-(as in) `abbrev-table', or nil if they should not be changed.")
-
-(defvar simula-abbrev-stdproc simula-abbrev-stdproc-default
- "*Specify how to convert case for standard SIMULA procedure and class names.
-Value is one of the symbols `upcase', `downcase', `capitalize',
-(as in) `abbrev-table', or nil if they should not be changed.")
-
-(defvar simula-abbrev-file nil
- "*File with extra abbrev definitions for use in SIMULA mode.
-These are used together with the standard abbrev definitions for SIMULA.
-Please note that the standard definitions are required
-for SIMULA mode to function correctly.")
-
-(defvar simula-mode-syntax-table nil
- "Syntax table in SIMULA mode buffers.")
-
-;; Regexps written with help from Alf-Ivar Holm <alfh@ifi.uio.no>.
-(defconst simula-font-lock-keywords-1
- (list
- ;;
- ;; Comments and strings.
- '(simula-match-string-or-comment 0
- (if (match-beginning 1) font-lock-string-face font-lock-comment-face))
- ;;
- ;; Compiler directives.
- '("^%\\([^ \t\n].*\\)" 1 font-lock-reference-face)
- ;;
- ;; Class and procedure names.
- '("\\<\\(class\\|procedure\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))
- )
- "Subdued level highlighting for Simula mode.")
-
-(defconst simula-font-lock-keywords-2
- (append simula-font-lock-keywords-1
- (list
- ;;
- ;; Constants as references.
- '("\\<\\(false\\|none\\|notext\\|true\\)\\>" . font-lock-reference-face)
- ;;
- ;; Keywords.
- (concat "\\<\\("
-; (make-regexp
-; '("activate" "after" "and" "at" "before" "begin" "delay" "do"
-; "else" "end" "eq" "eqv" "external" "for" "ge" "go" "goto" "gt"
-; "hidden" "if" "imp" "in" "inner" "inspect" "is" "label" "le"
-; "lt" "ne" "new" "not" "or" "otherwise" "prior" "protected"
-; "qua" "reactivate" "step" "switch" "then" "this" "to" "until"
-; "virtual" "when" "while"))
- "a\\(ctivate\\|fter\\|nd\\|t\\)\\|be\\(fore\\|gin\\)\\|"
- "d\\(elay\\|o\\)\\|e\\(lse\\|nd\\|qv?\\|xternal\\)\\|for\\|"
- "g\\([eot]\\|oto\\)\\|hidden\\|i\\([fns]\\|mp\\|n\\(ner\\|"
- "spect\\)\\)\\|l\\([et]\\|abel\\)\\|n\\(ew?\\|ot\\)\\|"
- "o\\(r\\|therwise\\)\\|pr\\(ior\\|otected\\)\\|qua\\|"
- "reactivate\\|s\\(tep\\|witch\\)\\|t\\(h\\(en\\|is\\)\\|o\\)\\|"
- "until\\|virtual\\|wh\\(en\\|ile\\)"
- "\\)\\>")
- ;;
- ;; Types.
- (cons (concat "\\<\\(array\\|boolean\\|character\\|integer\\|"
- "long\\|name\\|real\\|short\\|text\\|value\\|ref\\)\\>")
- 'font-lock-type-face)
- ))
- "Medium level highlighting for Simula mode.")
-
-(defconst simula-font-lock-keywords-3
- (append simula-font-lock-keywords-2
- (list
- ;;
- ;; Super-class names and super-slow.
- '("\\<\\(\\sw+\\)[ \t]+class\\>" 1 font-lock-function-name-face)
- ;;
- ;; Types and their declarations.
- (list (concat "\\<\\(array\\|boolean\\|character\\|integer\\|"
- "long\\|name\\|real\\|short\\|text\\|value\\)\\>"
- "\\([ \t]+\\sw+\\>\\)*")
- '(font-lock-match-c-style-declaration-item-and-skip-to-next
- ;; Start with point after all type specifiers.
- (goto-char (or (match-beginning 2) (match-end 1)))
- ;; Finish with point after first type specifier.
- (goto-char (match-end 1))
- ;; Fontify as a variable name.
- (1 font-lock-variable-name-face)))
- ;;
- ;; Object references and their declarations.
- '("\\<\\(ref\\)\\>[ \t]*\\((\\(\\sw+\\))\\)?"
- (3 font-lock-function-name-face nil t)
- (font-lock-match-c-style-declaration-item-and-skip-to-next nil nil
- (1 font-lock-variable-name-face)))
- ))
- "Gaudy level highlighting for Simula mode.")
-
-(defvar simula-font-lock-keywords simula-font-lock-keywords-1
- "Default expressions to highlight in Simula mode.")
-
-; The following function is taken from cc-mode.el,
-; it determines the flavor of the Emacs running
-(defconst simula-emacs-features
- (let ((major (and (boundp 'emacs-major-version)
- emacs-major-version))
- (minor (and (boundp 'emacs-minor-version)
- emacs-minor-version))
- flavor comments)
- ;; figure out version numbers if not already discovered
- (and (or (not major) (not minor))
- (string-match "\\([0-9]+\\).\\([0-9]+\\)" emacs-version)
- (setq major (string-to-int (substring emacs-version
- (match-beginning 1)
- (match-end 1)))
- minor (string-to-int (substring emacs-version
- (match-beginning 2)
- (match-end 2)))))
- (if (not (and major minor))
- (error "Cannot figure out the major and minor version numbers."))
- ;; calculate the major version
- (cond
- ((= major 18) (setq major 'v18)) ;Emacs 18
- ((= major 4) (setq major 'v18)) ;Epoch 4
- ((= major 19) (setq major 'v19 ;Emacs 19
- flavor (if (string-match "Lucid" emacs-version)
- 'Lucid 'FSF)))
- ;; I don't know
- (t (error "Cannot recognize major version number: %s" major)))
- (list major flavor comments))
- "A list of features extant in the Emacs you are using.
-There are many flavors of Emacs out there, each with different
-features supporting those needed by simula-mode. Here's the current
-supported list, along with the values for this variable:
-
- Emacs 19: (v19 FSF 1-bit)
- Vanilla Emacs 18/Epoch 4: (v18 no-dual-comments)
- Emacs 18/Epoch 4 (patch2): (v18 8-bit)
- Lucid Emacs 19: (v19 Lucid 8-bit).")
-
-(defvar simula-mode-menu
- '(["Report Bug" simula-submit-bug-report t]
- ["Indent Line" simula-indent-line t]
- ["Backward Statement" simula-previous-statement t]
- ["Forward Statement" simula-next-statement t]
- ["Backward Up Level" simula-backward-up-level t]
- ["Forward Down Statement" simula-forward-down-level t]
- )
- "Lucid Emacs menu for SIMULA mode.")
-
-(if simula-mode-syntax-table
- ()
- (setq simula-mode-syntax-table (copy-syntax-table (standard-syntax-table)))
- (modify-syntax-entry ?! "<" simula-mode-syntax-table)
- (modify-syntax-entry ?$ "." simula-mode-syntax-table)
- (modify-syntax-entry ?% "." simula-mode-syntax-table)
- (modify-syntax-entry ?' "\"" simula-mode-syntax-table)
- (modify-syntax-entry ?\( "()" simula-mode-syntax-table)
- (modify-syntax-entry ?\) ")(" simula-mode-syntax-table)
- (modify-syntax-entry ?\; ">" simula-mode-syntax-table)
- (modify-syntax-entry ?\[ "." simula-mode-syntax-table)
- (modify-syntax-entry ?\\ "." simula-mode-syntax-table)
- (modify-syntax-entry ?\] "." simula-mode-syntax-table)
- (modify-syntax-entry ?_ "_" simula-mode-syntax-table)
- (modify-syntax-entry ?\| "." simula-mode-syntax-table)
- (modify-syntax-entry ?\{ "." simula-mode-syntax-table)
- (modify-syntax-entry ?\} "." simula-mode-syntax-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 "\C-c\C-u" 'simula-backward-up-level)
- (define-key simula-mode-map "\C-c\C-p" 'simula-previous-statement)
- (define-key simula-mode-map "\C-c\C-d" 'simula-forward-down-level)
- (define-key simula-mode-map "\C-c\C-n" 'simula-next-statement)
- ;(define-key simula-mode-map "\C-c\C-g" 'simula-goto-definition)
- ;(define-key simula-mode-map "\C-c\C-h" 'simula-standard-help)
- (define-key simula-mode-map "\177" 'backward-delete-char-untabify)
- (define-key simula-mode-map ":" 'simula-electric-label)
- (define-key simula-mode-map "\e\C-q" 'simula-indent-exp)
- (define-key simula-mode-map "\t" 'simula-indent-command)
- ;; Emacs 19 defines menus in the mode map
- (if (memq 'FSF simula-emacs-features)
- (progn
- (define-key simula-mode-map [menu-bar] (make-sparse-keymap))
-
- (define-key simula-mode-map [menu-bar simula]
- (cons "SIMULA" (make-sparse-keymap "SIMULA")))
- (define-key simula-mode-map [menu-bar simula bug-report]
- '("Submit Bug Report" . simula-submit-bug-report))
- (define-key simula-mode-map [menu-bar simula separator-indent]
- '("--"))
- (define-key simula-mode-map [menu-bar simula indent-exp]
- '("Indent Expression" . simula-indent-exp))
- (define-key simula-mode-map [menu-bar simula indent-line]
- '("Indent Line" . simula-indent-command))
- (define-key simula-mode-map [menu-bar simula separator-navigate]
- '("--"))
- (define-key simula-mode-map [menu-bar simula backward-stmt]
- '("Previous Statement" . simula-previous-statement))
- (define-key simula-mode-map [menu-bar simula forward-stmt]
- '("Next Statement" . simula-next-statement))
- (define-key simula-mode-map [menu-bar simula backward-up]
- '("Backward Up Level" . simula-backward-up-level))
- (define-key simula-mode-map [menu-bar simula forward-down]
- '("Forward Down Statement" . simula-forward-down-level))
-
- (put 'simula-next-statement 'menu-enable '(not (eobp)))
- (put 'simula-previous-statement 'menu-enable '(not (bobp)))
- (put 'simula-forward-down-level 'menu-enable '(not (eobp)))
- (put 'simula-backward-up-level 'menu-enable '(not (bobp)))
- (put 'simula-indent-command 'menu-enable '(not buffer-read-only))
- (put 'simula-indent-exp 'menu-enable '(not buffer-read-only))))
-
- ;; RMS: mouse-3 should not select this menu. mouse-3's global
- ;; definition is useful in SIMULA mode and we should not interfere
- ;; with that. The menu is mainly for beginners, and for them,
- ;; the menubar requires less memory than a special click.
- ;; in Lucid Emacs, we want the menu to popup when the 3rd button is
- ;; hit. In 19.10 and beyond this is done automatically if we put
- ;; the menu on mode-popup-menu variable, see c-common-init [cc-mode.el]
- (if (memq 'Lucid simula-emacs-features)
- (if (not (boundp 'mode-popup-menu))
- (define-key simula-mode-map 'button3 'simula-popup-menu))))
-
-;; menus for Lucid
-(defun simula-popup-menu (e)
- "Pops up the SIMULA menu."
- (interactive "@e")
- (popup-menu (cons (concat mode-name " Mode Commands") simula-mode-menu))
- (simula-keep-region-active))
-
-;; active regions, and auto-newline/hungry delete key
-(defun simula-keep-region-active ()
- ;; do whatever is necessary to keep the region active in
- ;; Lucid. ignore byte-compiler warnings you might see
- (and (boundp 'zmacs-region-stays)
- (setq zmacs-region-stays t)))
-
-(defvar simula-mode-abbrev-table nil
- "Abbrev table in SIMULA mode buffers")
-
-
-;;;###autoload
-(defun simula-mode ()
- "Major mode for editing SIMULA code.
-\\{simula-mode-map}
-Variables controlling indentation style:
- simula-tab-always-indent
- Non-nil means TAB in SIMULA mode should always reindent the current line,
- regardless of where in the line point is when the TAB command is used.
- simula-indent-level
- Indentation of SIMULA statements with respect to containing block.
- simula-substatement-offset
- Extra indentation after DO, THEN, ELSE, WHEN and OTHERWISE.
- simula-continued-statement-offset 3
- Extra indentation for lines not starting a statement or substatement,
- e.g. a nested FOR-loop. If value is a list, each line in a multiple-
- line continued statement will have the car of the list extra indentation
- with respect to the previous line of the statement.
- simula-label-offset -4711
- Offset of SIMULA label lines relative to usual indentation.
- simula-if-indent '(0 . 0)
- Extra indentation of THEN and ELSE with respect to the starting IF.
- Value is a cons cell, the car is extra THEN indentation and the cdr
- extra ELSE indentation. IF after ELSE is indented as the starting IF.
- simula-inspect-indent '(0 . 0)
- Extra indentation of WHEN and OTHERWISE with respect to the
- corresponding INSPECT. Value is a cons cell, the car is
- extra WHEN indentation and the cdr extra OTHERWISE indentation.
- simula-electric-indent nil
- If this variable is non-nil, `simula-indent-line'
- will check the previous line to see if it has to be reindented.
- simula-abbrev-keyword 'upcase
- Determine how SIMULA keywords will be expanded. Value is one of
- the symbols `upcase', `downcase', `capitalize', (as in) `abbrev-table',
- or nil if they should not be changed.
- simula-abbrev-stdproc 'abbrev-table
- Determine how standard SIMULA procedure and class names will be
- expanded. Value is one of the symbols `upcase', `downcase', `capitalize',
- (as in) `abbrev-table', or nil if they should not be changed.
-
-Turning on SIMULA mode calls the value of the variable simula-mode-hook
-with no arguments, if that value is non-nil
-
-Warning: simula-mode-hook should not read in an abbrev file without calling
-the function simula-install-standard-abbrevs afterwards, preferably not
-at all."
- (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-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-start-skip)
- (setq comment-start-skip "!+ *")
- (make-local-variable 'parse-sexp-ignore-comments)
- (setq parse-sexp-ignore-comments nil)
- (make-local-variable 'comment-multi-line)
- (setq comment-multi-line t)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults
- '((simula-font-lock-keywords simula-font-lock-keywords-1
- simula-font-lock-keywords-2 simula-font-lock-keywords-3)
- t t ((?_ . "w"))))
- (if simula-mode-abbrev-table
- ()
- (if simula-abbrev-file
- (read-abbrev-file simula-abbrev-file)
- (define-abbrev-table 'simula-mode-abbrev-table ()))
- (let (abbrevs-changed)
- (simula-install-standard-abbrevs)))
- (setq local-abbrev-table simula-mode-abbrev-table)
- (abbrev-mode 1)
- (run-hooks 'simula-mode-hook))
-
-
-(defun simula-indent-exp ()
- "Indent SIMULA expression following point."
- (interactive)
- (let ((here (point))
- (simula-electric-indent nil)
- end)
- (simula-skip-comment-forward)
- (if (eobp)
- (goto-char here)
- (unwind-protect
- (progn
- (simula-next-statement 1)
- (setq end (point-marker))
- (simula-previous-statement 1)
- (beginning-of-line)
- (while (< (point) end)
- (if (not (looking-at "[ \t]*$"))
- (simula-indent-line))
- (forward-line 1)))
- (and end (set-marker end nil))))))
-
-
-(defun simula-indent-line ()
- "Indent this line as SIMULA code.
-If `simula-electric-indent' is non-nil, indent previous line if necessary."
- (let ((origin (- (point-max) (point)))
- (indent (simula-calculate-indent))
- (case-fold-search t))
- (unwind-protect
- (if simula-electric-indent
- (progn
- ;;
- ;; manually expand abbrev on last line, if any
- ;;
- (end-of-line 0)
- (expand-abbrev)
- ;; now maybe we should reindent that line
- (beginning-of-line)
- (skip-chars-forward " \t\f")
- (if (and
- (looking-at
- "\\(end\\|if\\|then\\|else\\|when\\|otherwise\\)\\>")
- (not (simula-context)))
- ;; yes - reindent
- (let ((post-indent (simula-calculate-indent)))
- (if (eq (current-indentation) post-indent)
- ()
- (delete-horizontal-space)
- (indent-to post-indent))))))
- (goto-char (- (point-max) origin))
- (if (eq (current-indentation) indent)
- (back-to-indentation)
- (delete-horizontal-space)
- (indent-to indent)))))
-
-
-(defun simula-indent-command (&optional whole-exp)
- "Indent current line as SIMULA code, or insert TAB character.
-If `simula-tab-always-indent' is non-nil, always indent current line.
-Otherwise, indent only if point is before any non-whitespace
-character on the line.
-
-A numeric argument, regardless of its value, means indent rigidly
-all the lines of the SIMULA statement after point so that this line
-becomes properly indented.
-The relative indentation among the lines of the statement are preserved."
- (interactive "P")
- (let ((case-fold-search t))
- (if (or whole-exp simula-tab-always-indent
- (save-excursion
- (skip-chars-backward " \t\f")
- (bolp)))
- ;; reindent current line
- (let ((indent (save-excursion
- (beginning-of-line)
- (simula-calculate-indent)))
- (current (current-indentation))
- (origin (- (point-max) (point)))
- (bol (save-excursion
- (skip-chars-backward " \t\f")
- (bolp)))
- beg end)
- (unwind-protect
- (if (eq current indent)
- (if (save-excursion
- (skip-chars-backward " \t\f")
- (bolp))
- (back-to-indentation))
- (beginning-of-line)
- (delete-horizontal-space)
- (indent-to indent))
- (if (not bol)
- (goto-char (- (point-max) origin))))
- (setq origin (point))
- (if whole-exp
- (save-excursion
- (beginning-of-line 2)
- (setq beg (point))
- (goto-char origin)
- (simula-next-statement 1)
- (setq end (point))
- (if (and (> end beg) (not (eq indent current)))
- (indent-code-rigidly beg end (- indent current) "%")))))
- (insert-tab))))
-
-
-(defun simula-context ()
- "Returns value according to syntactic SIMULA context of point.
- 0 point inside COMMENT comment
- 1 point on SIMULA-compiler directive line
- 2 point inside END comment
- 3 point inside string
- 4 point inside character constant
- nil otherwise."
- ;; first, find out if this is a compiler directive line
- (if (save-excursion
- (beginning-of-line)
- (eq (following-char) ?%))
- ;; YES - return 1
- 1
- (save-excursion
- ;; The current line is NOT a compiler directive line.
- ;; Now, the strategy is to search backward to find a semicolon
- ;; that is NOT inside a string. The point after semicolon MUST be
- ;; outside a comment, since semicolons are comment-ending and
- ;; comments are non-recursive. We take advantage of the fact
- ;; that strings MUST end on the same line as they started, so
- ;; that we can easily decide whether we are inside a string or not.
- (let (return-value (origin (point)))
- (skip-chars-backward "^;" (point-min))
- ;; found semicolon or beginning of buffer
- (let (loopvalue (saved-point origin))
- (while (and (not (bobp))
- (if (progn
- (beginning-of-line)
- ;; compiler directive line? If so, cont searching..
- (eq (following-char) ?%))
- t
- (while (< (point) saved-point)
- (skip-chars-forward "^;\"'")
- (forward-char 1)
- (cond
- ((eq (preceding-char) ?\;)
- (setq saved-point (point)))
- ((eq (preceding-char) ?\")
- (skip-chars-forward "^\";")
- (if (eq (following-char) ?\;)
- (setq saved-point (point) loopvalue t)
- (forward-char 1)))
- (t
- (if (eq (following-char) ?')
- (forward-char 1))
- (skip-chars-forward "^';")
- (if (eq (following-char) ?\;)
- (setq saved-point (point) loopvalue t)
- (forward-char 1)))))
- loopvalue))
- (backward-char 1)
- (skip-chars-backward "^;")
- (setq saved-point (point) loopvalue nil)))
- ;; Now we are CERTAIN that we are outside comments and strings.
- ;; The job now is to search forward again towards the origin
- ;; skipping directives, comments and strings correctly,
- ;; so that we know what context we are in when we find the origin.
- (while (and
- (< (point) origin)
- (re-search-forward
- "\\<end\\>\\|!\\|\"\\|'\\|^%\\|\\<comment\\>" origin 'move))
- (cond
- ((memq (preceding-char) '(?d ?D))
- (setq return-value 2)
- (while (and (re-search-forward
- ";\\|\\<end\\>\\|\\<else\\>\\|\\<otherwise\\>\\|\\<when\\>\\|^%"
- origin 'move)
- ;; found another END?
- (or (memq (preceding-char) '(?d ?D))
- ;; if directive, skip line
- (and (eq (preceding-char) ?%)
- (beginning-of-line 2))
- ;; found other keyword, out of END comment
- (setq return-value nil))))
- (if (and (eq (char-syntax (preceding-char)) ?w)
- (eq (char-syntax (following-char)) ?w))
- (save-excursion
- (backward-word 1)
- (if (looking-at "end\\>\\|else\\>\\|otherwise\\>\\|when\\>")
- (setq return-value nil)))))
- ((memq (preceding-char) '(?! ?t ?T))
- ; skip comment
- (setq return-value 0)
- (skip-chars-forward "^%;" origin)
- (while (and return-value (< (point) origin))
- (if (eq (following-char) ?\;)
- (setq return-value nil)
- (if (bolp)
- (beginning-of-line 2) ; skip directive inside comment
- (forward-char 1)) ; or single '%'
- (skip-chars-forward "^%;" origin))))
- ((eq (preceding-char) ?\")
- (if (not (search-forward "\"" origin 'move))
- (setq return-value 3)))
- ((eq (preceding-char) ?\')
- (if (or (eq (point) origin) (eobp))
- (setq return-value 4)
- (forward-char 1)
- (if (not (search-forward "'" origin 'move))
- (setq return-value 4))))
- ;; compiler directive line - skip
- (t (beginning-of-line 2))))
- return-value)
- )))
-
-
-(defun simula-electric-label ()
- "If this is a label that starts the line, reindent the line."
- (interactive)
- (expand-abbrev)
- (insert ?:)
- (let ((origin (- (point-max) (point)))
- (case-fold-search t)
- ;; don't mix a label with an assignment operator := :-
- ;; therefore take a peek at next typed character...
- (next-char (read-event)))
- (unwind-protect
- (setq unread-command-events (append unread-command-events
- (list next-char)))
- ;; Problem: find out if character just read is a command char
- ;; that would insert something after ':' making it a label.
- ;; At least \n, \r (and maybe \t) falls into this category.
- ;; This is a real crock, it depends on traditional keymap
- ;; bindings, that is, printing characters doing self-insert,
- ;; and no other command sequence inserting '-' or '='.
- ;; simula-electric-label can be easily fooled...
- (if (and (not (memq next-char '(?= ?-)))
- (or (memq next-char '(?\n ?\r))
- (and (eq next-char ?\t)
- simula-tab-always-indent)
- (not (memq (following-char) '(?= ?-))))
- (not (simula-context))
- ;; label?
- (progn
- (backward-char 1)
- (skip-chars-backward " \t\f")
- (skip-chars-backward "a-zA-Z0-9_")
- (if (looking-at "virtual\\>")
- nil
- (skip-chars-backward " \t\f")
- (bolp))))
- (let ((amount (simula-calculate-indent)))
- (delete-horizontal-space)
- (indent-to amount)))
- (goto-char (- (point-max) origin)))))
-
-
-(defun simula-backward-up-level (count)
- "Move backward up COUNT block levels.
-If COUNT is negative, move forward up block level instead."
- (interactive "p")
- (let ((origin (point))
- (case-fold-search t))
- (condition-case ()
- (if (> count 0)
- (while (> count 0)
- (re-search-backward "\\<begin\\>\\|\\<end\\>")
- (if (not (simula-context))
- (setq count (if (memq (following-char) '(?b ?B))
- (1- count)
- (1+ count)))))
- (while (< count 0)
- (re-search-forward "\\<begin\\>\\|\\<end\\>")
- (backward-word 1)
- (if (not (simula-context))
- (setq count (if (memq (following-char) '(?e ?E))
- (1+ count)
- (1- count))))
- (backward-word -1)))
- ;; If block level not found, jump back to origin and signal an error
- (error (progn
- (goto-char origin)
- (error "No higher block level")))
- (quit (progn
- (goto-char origin)
- (signal 'quit nil))))))
-
-
-(defun simula-forward-down-level (count)
- "Move forward down COUNT block levels.
-If COUNT is negative, move backward down block level instead."
- (interactive "p")
- ;; When we search for a deeper block level, we must never
- ;; get out of the block where we started -> count >= start-count
- (let ((start-count count)
- (origin (point))
- (case-fold-search t))
- (condition-case ()
- (if (< count 0)
- (while (< count 0)
- (re-search-backward "\\<begin\\>\\|\\<end\\>")
- (if (not (simula-context))
- (setq count (if (memq (following-char) '(?e ?E))
- (1+ count)
- (1- count))))
- (if (< count start-count) (signal 'error nil)))
- (while (> count 0)
- (re-search-forward "\\<begin\\>\\|\\<end\\>")
- (backward-word 1)
- (if (not (simula-context))
- (setq count (if (memq (following-char) '(?b ?B))
- (1- count)
- (1+ count))))
- (backward-word -1)
- ;; deeper level has to be found within starting block
- (if (> count start-count) (signal 'error nil))))
- ;; If block level not found, jump back to origin and signal an error
- (error (progn
- (goto-char origin)
- (error "No containing block level")))
- (quit (progn
- (goto-char origin)
- (signal 'quit nil))))))
-
-
-(defun simula-previous-statement (count)
- "Move backward COUNT statements.
-If COUNT is negative, move forward instead."
- (interactive "p")
- (if (< count 0)
- (simula-next-statement (- count))
- (let (status
- (case-fold-search t)
- (origin (point)))
- (condition-case ()
- ;;
- (progn
- (simula-skip-comment-backward)
- (if (memq (preceding-char) '(?n ?N))
- (progn
- (backward-word 1)
- (if (not (looking-at "\\<begin\\>"))
- (backward-word -1)))
- (if (eq (preceding-char) ?\;)
- (backward-char 1))
- )
- (while (and (natnump (setq count (1- count)))
- (setq status (simula-search-backward
- ";\\|\\<begin\\>" nil 'move))))
- (if status
- (progn
- (if (eq (following-char) ?\;)
- (forward-char 1)
- (backward-word -1))))
- (simula-skip-comment-forward))
- (error (progn (goto-char origin)
- (error "Incomplete statement (too many ENDs)")))
- (quit (progn (goto-char origin) (signal 'quit nil)))))))
-
-
-(defun simula-next-statement (count)
- "Move forward COUNT statements.
-If COUNT is negative, move backward instead."
- (interactive "p")
- (if (< count 0)
- (simula-previous-statement (- count))
- (let (status
- (case-fold-search t)
- (origin (point)))
- (condition-case ()
- (progn
- (simula-skip-comment-forward)
- (if (looking-at "\\<end\\>") (forward-word 1))
- (while (and (natnump (setq count (1- count)))
- (setq status (simula-search-forward
- ";\\|\\<end\\>" (point-max) 'move))))
- (if (and status (/= (preceding-char) ?\;))
- (progn
- (backward-word 1)
- (simula-skip-comment-backward))))
- (error (progn (goto-char origin)
- (error "Incomplete statement (too few ENDs)")))
- (quit (progn (goto-char origin) (signal 'quit nil)))))))
-
-
-(defun simula-skip-comment-backward (&optional stop-at-end)
- "Search towards bob to find first char that is outside a comment."
- (interactive)
- (catch 'simula-out
- (let (context)
- (while t
- (skip-chars-backward " \t\n\f")
- (if (eq (preceding-char) ?\;)
- (save-excursion
- (backward-char 1)
- (setq context (simula-context))
- (if (and stop-at-end (eq context 2))
- (setq context nil)))
- (setq context (simula-context)))
- (cond
- ((memq context '(nil 3 4))
- ;; check to see if we found a label
- (if (and (eq (preceding-char) ?:)
- (not (memq (following-char) '(?- ?=)))
- (save-excursion
- (skip-chars-backward ": \t\fa-zA-Z0-9_")
- (not (looking-at "virtual\\>"))))
- (skip-chars-backward ": \t\fa-zA-Z0-9_")
- (throw 'simula-out nil)))
- ((eq context 0)
- ;; since we are inside a comment, it must start somewhere!
- (while (and (re-search-backward "!\\|\\<comment\\>")
- (memq (simula-context) '(0 1)))))
- ((eq context 1)
- (beginning-of-line)
- (if (bobp)
- (throw 'simula-out nil)
- (backward-char)))
- ((eq context 2)
- ;; an END-comment must belong to an END
- (re-search-backward "\\<end\\>")
- (forward-word 1)
- (throw 'simula-out nil))
- ;; should be impossible to get here..
- )))))
-
-
-(defun simula-skip-comment-forward ()
- "Search towards eob to find first char that is outside a comment."
- ;; this function assumes we start with point .outside a comment
- (interactive)
- (catch 'simula-out
- (while t
- (skip-chars-forward " \t\n\f")
- ;; BUG: the following (0 2) branches don't take into account intermixing
- ;; directive lines
- (cond
- ((looking-at "!\\|\\<comment\\>")
- (search-forward ";" nil 'move))
- ((and (bolp) (eq (following-char) ?%))
- (beginning-of-line 2))
- ((and (looking-at "[a-z0-9_]*[ \t\f]*:[^-=]")
- (not (looking-at "virtual\\>")))
- (skip-chars-forward "a-zA-Z0-9_ \t\f:"))
- (t
- (throw 'simula-out t))))))
-
-
-(defun simula-forward-up-level ()
- (let ((continue-loop t)
- (origin (point))
- (case-fold-search t)
- return-value
- temp)
- (while continue-loop
- (if (re-search-backward "\\<begin\\>\\|\\<end\\>" (point-min) 'move)
- (setq temp (simula-context)
- return-value (and (memq (preceding-char) '(?d ?D))
- (memq temp '(nil 2)))
- continue-loop (and (not return-value)
- (simula-forward-up-level)))
- (setq continue-loop nil)))
- (if return-value
- t
- (goto-char origin)
- nil)))
-
-
-(defun simula-calculate-indent ()
- (save-excursion
- (let ((where (simula-context))
- (origin (point))
- (indent 0)
- continued
- start-line
- temp
- found-end
- prev-cont)
- (cond
- ((eq where 0)
- ;;
- ;; Comment.
- ;; If comment started on previous non-blank line, indent to the
- ;; column where the comment started, else indent as that line.
- ;;
- (skip-chars-backward " \t\n\f")
- (while (and (not (bolp)) (eq (simula-context) 0))
- (re-search-backward "^\\|!\\|\\<comment\\>"))
- (skip-chars-forward " \t\n\f")
- (prog1
- (current-column)
- (goto-char origin)))
- ((eq where 1)
- ;;
- ;; Directive. Always 0.
- ;;
- 0)
- ;;
- ;; Detect missing string delimiters
- ;;
- ((eq where 3)
- (error "Inside string"))
- ((eq where 4)
- (error "Inside character constant"))
- ;;
- ;; check to see if inside ()'s
- ;;
- ((setq temp (simula-inside-parens))
- temp)
- ;;
- ;; Calculate non-comment indentation
- (t
- ;; first, find out if this line starts with something that needs
- ;; special indentation (END/IF/THEN/ELSE/WHEN/OTHERWISE or label)
- ;;
- (skip-chars-forward " \t\f")
- (cond
- ;;
- ;; END
- ;;
- ((looking-at "end\\>")
- (setq indent (- simula-indent-level)
- found-end t))
- ;;
- ;; IF/THEN/ELSE
- ;;
- ((looking-at "if\\>\\|then\\>\\|else\\>")
- ;; search for the *starting* IF
- (cond
- ((memq (following-char) '(?T ?t))
- (setq indent (car simula-if-indent)))
- ((memq (following-char) '(?E ?e))
- (setq indent (cdr simula-if-indent)))
- (t
- (forward-word 1)
- (setq indent 0)))
- (simula-find-if))
- ;;
- ;; WHEN/OTHERWISE
- ;;
- ((looking-at "when\\>\\|otherwise\\>")
- ;; search for corresponding INSPECT
- (if (memq (following-char) '(?W ?w))
- (setq indent (car simula-inspect-indent))
- (setq indent (cdr simula-inspect-indent)))
- (simula-find-inspect))
- ;;
- ;; label:
- ;;
- ((and (not (looking-at "virtual\\>"))
- (looking-at "[a-z0-9_]*[ \t\f]*:[^-=]"))
- (setq indent simula-label-offset)))
- ;; find line with non-comment text
- (simula-skip-comment-backward 'dont-skip-end)
- (if (and found-end
- (not (eq (preceding-char) ?\;))
- (if (memq (preceding-char) '(?N ?n))
- (save-excursion
- (backward-word 1)
- (not (looking-at "begin\\>")))
- t))
- (progn
- (simula-previous-statement 1)
- (simula-skip-comment-backward)))
- (setq start-line
- (save-excursion (beginning-of-line) (point))
- ;; - perhaps this is a continued statement
- continued
- (save-excursion
- (and (not (bobp))
- ;; (not found-end)
- (if (eq (char-syntax (preceding-char)) ?w)
- (progn
- (backward-word 1)
- (not (looking-at
- "begin\\|then\\|else\\|when\\|otherwise\\|do"
- )))
- (not (memq (preceding-char) '(?: ?\;)))))))
- ;;
- ;; MAIN calculation loop - count BEGIN/DO etc.
- ;;
- (while (not (bolp))
- (if (re-search-backward
- ";\\|\\<\\(begin\\|end\\|if\\|else\\|then\\|when\\|otherwise\\|do\\)\\>"
- start-line 'move)
- (if (simula-context)
- ();; found something in a comment/string - ignore
- (setq temp (following-char))
- (cond
- ((eq temp ?\;)
- (simula-previous-statement 1))
- ((looking-at "begin\\>")
- (setq indent (+ indent simula-indent-level)))
- ((looking-at "end\\>")
- (forward-word 1)
- (simula-previous-statement 1))
- ((looking-at "do\\>")
- (setq indent (+ indent simula-substatement-offset))
- (simula-find-do-match))
- ((looking-at "\\(if\\|then\\|else\\)\\>")
- (if (memq temp '(?I ?i))
- (forward-word 1)
- (setq indent (+ indent
- simula-substatement-offset
- (if (memq temp '(?T ?t))
- (car simula-if-indent)
- (cdr simula-if-indent)))))
- (simula-find-if))
- ((looking-at "\\<when\\>\\|\\<otherwise\\>")
- (setq indent (+ indent
- simula-substatement-offset
- (if (memq temp '(?W ?w))
- (car simula-if-indent)
- (cdr simula-if-indent))))
- (simula-find-inspect)))
- ;; found the start of a [sub]statement
- ;; add indentation for continued statement
- (if continued
- (setq indent
- (+ indent
- (if (listp simula-continued-statement-offset)
- (car simula-continued-statement-offset)
- simula-continued-statement-offset))))
- (setq start-line
- (save-excursion (beginning-of-line) (point))
- continued nil))
- ;; search failed .. point is at beginning of line
- ;; determine if we should continue searching
- ;; (at or before comment or label)
- ;; temp = t means finished
- (setq temp
- (and (not (simula-context))
- (save-excursion
- (skip-chars-forward " \t\f")
- (or (looking-at "virtual")
- (not
- (looking-at
- "!\\|comment\\>\\|[a-z0-9_]*[ \t\f]*:[^-=]")))))
- prev-cont continued)
- ;; if we are finished, find current line's indentation
- (if temp
- (setq indent (+ indent (current-indentation))))
- ;; find next line with non-comment SIMULA text
- ;; maybe indent extra if statement continues
- (simula-skip-comment-backward)
- (setq continued
- (and (not (bobp))
- (if (eq (char-syntax (preceding-char)) ?w)
- (save-excursion
- (backward-word 1)
- (not (looking-at
- "begin\\|then\\|else\\|when\\|otherwise\\|do")))
- (not (memq (preceding-char) '(?: ?\;))))))
- ;; if we the state of the continued-variable
- ;; changed, add indentation for continued statement
- (if (or (and prev-cont (not continued))
- (and continued
- (listp simula-continued-statement-offset)))
- (setq indent
- (+ indent
- (if (listp simula-continued-statement-offset)
- (car simula-continued-statement-offset)
- simula-continued-statement-offset))))
- ;; while ends if point is at beginning of line at loop test
- (if (not temp)
- (setq start-line (save-excursion (beginning-of-line) (point)))
- (beginning-of-line))))
- ;;
- ;; return indentation
- ;;
- indent)))))
-
-
-(defun simula-find-if ()
- "Find starting IF of a IF-THEN[-ELSE[-IF-THEN...]] statement."
- (catch 'simula-out
- (while t
- (if (and (simula-search-backward "\\<if\\>\\|;\\|\\<begin\\>"nil t)
- (memq (following-char) '(?I ?i)))
- (save-excursion
- ;;
- ;; find out if this IF was really the start of the IF statement
- ;;
- (simula-skip-comment-backward)
- (if (and (eq (char-syntax (preceding-char)) ?w)
- (progn
- (backward-word 1)
- (looking-at "else\\>")))
- ()
- (throw 'simula-out t)))
- (if (not (looking-at "\\<if\\>"))
- (error "Missing IF or misplaced BEGIN or ';' (can't find IF)")
- ;;
- ;; we were at the starting IF in the first place..
- ;;
- (throw 'simula-out t))))))
-
-
-(defun simula-find-inspect ()
- "Find INSPECT matching WHEN or OTHERWISE."
- (catch 'simula-out
- (let ((level 0))
- ;;
- ;; INSPECTs can be nested, have to find the corresponding one
- ;;
- (while t
- (if (and (simula-search-backward "\\<inspect\\>\\|\\<otherwise\\>\\|;"
- nil t)
- (/= (following-char) ?\;))
- (if (memq (following-char) '(?O ?o))
- (setq level (1+ level))
- (if (zerop level)
- (throw 'simula-out t)
- (setq level (1- level))))
- (error "Missing INSPECT or misplaced ';' (can't find INSPECT)"))))))
-
-
-(defun simula-find-do-match ()
- "Find keyword matching DO: FOR, WHILE, INSPECT or WHEN"
- (while (and (re-search-backward
- "\\<\\(do\\|for\\|while\\|inspect\\|when\\|end\\|begin\\)\\>\\|;"
- nil 'move)
- (simula-context)))
- (if (and (looking-at "\\<\\(for\\|while\\|inspect\\|when\\)\\>")
- (not (simula-context)))
- () ;; found match
- (error "No matching FOR, WHILE or INSPECT for DO, or misplaced ';'")))
-
-
-(defun simula-inside-parens ()
- "Return position after `(' on line if inside parentheses, nil otherwise."
- (save-excursion
- (let ((parlevel 0))
- (catch 'simula-out
- (while t
- (if (re-search-backward "(\\|)\\|;" nil t)
- (if (eq (simula-context) nil)
- ;; found something - check it out
- (cond
- ((eq (following-char) ?\;)
- (if (zerop parlevel)
- (throw 'simula-out nil)
- (error "Parenthesis mismatch or misplaced ';'")))
- ((eq (following-char) ?\()
- (if (zerop parlevel)
- (throw 'simula-out (1+ (current-column)))
- (setq parlevel (1- parlevel))))
- (t (setq parlevel (1+ parlevel))))
- );; nothing - inside comment or string
- ;; search failed
- (throw 'simula-out nil)))))))
-
-
-(defun simula-goto-definition ()
- "Goto point of definition of variable, procedure or class."
- (interactive))
-
-
-(defun simula-expand-stdproc ()
- (if (or (not simula-abbrev-stdproc) (simula-context))
- (unexpand-abbrev)
- (cond
- ((eq simula-abbrev-stdproc 'upcase) (upcase-word -1))
- ((eq simula-abbrev-stdproc 'downcase) (downcase-word -1))
- ((eq simula-abbrev-stdproc 'capitalize) (capitalize-word -1))
- ((eq simula-abbrev-stdproc 'abbrev-table)
- ;; If not in lowercase, expansions are always capitalized.
- ;; We then want to replace with the exact expansion.
- (if (equal (symbol-name last-abbrev) last-abbrev-text)
- ()
- (downcase-word -1)
- (expand-abbrev))))))
-
-
-(defun simula-expand-keyword ()
- (if (or (not simula-abbrev-keyword) (simula-context))
- (unexpand-abbrev)
- (cond
- ((eq simula-abbrev-keyword 'upcase) (upcase-word -1))
- ((eq simula-abbrev-keyword 'downcase) (downcase-word -1))
- ((eq simula-abbrev-keyword 'capitalize) (capitalize-word -1))
- ((eq simula-abbrev-stdproc 'abbrev-table)
- (if (equal (symbol-name last-abbrev) last-abbrev-text)
- ()
- (downcase-word -1)
- (expand-abbrev))))))
-
-
-(defun simula-electric-keyword ()
- "Expand SIMULA keyword. If it starts the line, reindent."
- ;; redisplay
- (let ((show-char (eq this-command 'self-insert-command)))
- ;; If the abbrev expansion results in reindentation, the user may have
- ;; to wait some time before the character he typed is displayed
- ;; (the char causing the expansion is inserted AFTER the hook function
- ;; is called). This is annoying in case of normal characters.
- ;; However, if the user pressed a key bound to newline, it is better
- ;; to have the line inserted after the begin-end match.
- (if show-char
- (progn
- (insert-char last-command-char 1)
- (sit-for 0)
- (backward-char 1)))
- (if (let ((where (simula-context))
- (case-fold-search t))
- (if where
- (if (and (eq where 2) (eq (char-syntax (preceding-char)) ?w))
- (save-excursion
- (backward-word 1)
- (not (looking-at "end\\>"))))))
- (unexpand-abbrev)
- (cond
- ((not simula-abbrev-keyword) (unexpand-abbrev))
- ((eq simula-abbrev-keyword 'upcase) (upcase-word -1))
- ((eq simula-abbrev-keyword 'downcase) (downcase-word -1))
- ((eq simula-abbrev-keyword 'capitalize) (capitalize-word -1)))
- (let ((pos (- (point-max) (point)))
- (case-fold-search t)
- null)
- (condition-case null
- (progn
- ;; check if the expanded word is on the beginning of the line.
- (if (and (eq (char-syntax (preceding-char)) ?w)
- (progn
- (backward-word 1)
- (if (looking-at "end\\>")
- (save-excursion
- (simula-backward-up-level 1)
- (if (pos-visible-in-window-p)
- (sit-for 1)
- (message "Matches %s"
- (buffer-substring
- (point)
- (+ (point) (window-width)))))))
- (skip-chars-backward " \t\f")
- (bolp)))
- (let ((indent (simula-calculate-indent)))
- (if (eq indent (current-indentation))
- ()
- (delete-horizontal-space)
- (indent-to indent)))
- (skip-chars-forward " \t\f"))
- ;; check for END - blow whistles and ring bells
-
- (goto-char (- (point-max) pos))
- (if show-char
- (delete-char 1)))
- (quit (goto-char (- (point-max) pos))))))))
-
-
-(defun simula-search-backward (regexp &optional bound noerror)
- "Search backward from point for regular expression REGEXP, ignoring matches
-found inside SIMULA comments, string literals, and BEGIN..END blocks.
-Set point to the end of the occurrence found, and return point.
-An optional second argument BOUND bounds the search, it is a buffer position.
-The match found must not extend after that position. Optional third argument
-NOERROR, if t, means if fail just return nil (no error).
-If not nil and not t, move to limit of search and return nil."
- (let (begin end context (comb-regexp (concat regexp "\\|\\<end\\>"))
- match (start-point (point)))
- (catch 'simula-backward
- (while (re-search-backward comb-regexp bound 1)
- ;; We have a match, check SIMULA context at match-beginning
- ;; to see if we are outside comments etc.
- ;; Set MATCH to t if we found a true match,
- ;; set MATCH to 'BLOCK if we found a BEGIN..END block,
- ;; else set MATCH to nil.
- (save-match-data
- (setq context (simula-context))
- (cond
- ((eq context nil)
- (setq match (if (looking-at regexp) t 'BLOCK)))
-;;; A comment-ending semicolon is part of the comment, and shouldn't match.
-;;; ((eq context 0)
-;;; (setq match (if (eq (following-char) ?\;) t nil)))
- ((eq context 2)
- (setq match (if (and (looking-at regexp)
- (looking-at ";\\|\\<end\\>\\|\\<else\\>\\|\\<otherwise\\>\\|\\<when\\>"))
- t
- (if (looking-at "\\<end\\>") 'BLOCK nil))))
- (t (setq match nil))))
- ;; Exit if true match
- (if (eq match t) (throw 'simula-backward (point)))
- (if (eq match 'BLOCK)
- ;; We found the END of a block
- (let ((level 0))
- (while (natnump level)
- (if (re-search-backward "\\<begin\\>\\|\\<end\\>" bound 1)
- (let ((context (simula-context)))
- ;; We found a BEGIN -> decrease level count
- (cond ((and (eq context nil)
- (memq (following-char) '(?b ?B)))
- (setq level (1- level)))
- ;; END -> increase level count
- ((and (memq context '(nil 2))
- (memq (following-char) '(?e ?E)))
- (setq level (1+ level)))))
- ;; Block search failed. Action depends on noerror.
- (if (or (not noerror) (eq noerror t))
- (goto-char start-point))
- (if (not noerror)
- (signal 'search-failed (list regexp)))
- (throw 'simula-backward nil))))))
- ;; Search failed. Action depends on noerror.
- (if (or (not noerror) (eq noerror t))
- (goto-char start-point))
- (if noerror
- nil
- (signal 'search-failed (list regexp))))))
-
-
-(defun simula-search-forward (regexp &optional bound noerror)
- "Search forward from point for regular expression REGEXP, ignoring matches
-found inside SIMULA comments, string literals, and BEGIN..END blocks.
-Set point to the end of the occurrence found, and return point.
-An optional second argument BOUND bounds the search, it is a buffer position.
-The match found must not extend after that position. Optional third argument
-NOERROR, if t, means if fail just return nil (no error).
-If not nil and not t, move to limit of search and return nil."
- (let (begin end context (comb-regexp (concat regexp "\\|\\<begin\\>"))
- match (start-point (point)))
- (catch 'simula-forward
- (while (re-search-forward comb-regexp bound 1)
- ;; We have a match, check SIMULA context at match-beginning
- ;; to see if we are outside comments.
- ;; Set MATCH to t if we found a true match,
- ;; set MATCH to 'BLOCK if we found a BEGIN..END block,
- ;; else set MATCH to nil.
- (save-match-data
- (save-excursion
- (goto-char (match-beginning 0))
- (setq context (simula-context))
- (cond
- ((not context)
- (setq match (if (looking-at regexp) t 'BLOCK)))
-;;; A comment-ending semicolon is part of the comment, and shouldn't match.
-;;; ((eq context 0)
-;;; (setq match (if (eq (following-char) ?\;) t nil)))
- ((eq context 2)
- (setq match (if (and (looking-at regexp)
- (looking-at ";\\|\\<end\\>\\|\\<else\\>\\|\\<otherwise\\>\\|\\<when\\>")) t nil)))
- (t (setq match nil)))))
- ;; Exit if true match
- (if (eq match t) (throw 'simula-forward (point)))
- (if (eq match 'BLOCK)
- ;; We found the BEGINning of a block
- (let ((level 0))
- (while (natnump level)
- (if (re-search-forward "\\<begin\\>\\|\\<end\\>" bound 1)
- (let ((context (simula-context)))
- ;; We found a BEGIN -> increase level count
- (cond ((eq context nil) (setq level (1+ level)))
- ;; END -> decrease level count
- ((and (eq context 2)
- ;; Don't match BEGIN inside END comment
- (memq (preceding-char) '(?d ?D)))
- (setq level (1- level)))))
- ;; Block search failed. Action depends on noerror.
- (if (or (not noerror) (eq noerror t))
- (goto-char start-point))
- (if (not noerror)
- (signal 'search-failed (list regexp)))
- (throw 'simula-forward nil))))))
- ;; Search failed. Action depends on noerror.
- (if (or (not noerror) (eq noerror t))
- (goto-char start-point))
- (if noerror
- nil
- (signal 'search-failed (list regexp))))))
-
-
-(defun simula-install-standard-abbrevs ()
- "Define Simula keywords, procedures and classes in local abbrev table."
- ;; procedure and class names are as of the SIMULA 87 standard.
- (interactive)
- (mapcar (function (lambda (args)
- (apply 'define-abbrev simula-mode-abbrev-table args)))
- '(("abs" "Abs" simula-expand-stdproc)
- ("accum" "Accum" simula-expand-stdproc)
- ("activate" "ACTIVATE" simula-expand-keyword)
- ("addepsilon" "AddEpsilon" simula-expand-stdproc)
- ("after" "AFTER" simula-expand-keyword)
- ("and" "AND" simula-expand-keyword)
- ("arccos" "ArcCos" simula-expand-stdproc)
- ("arcsin" "ArcSin" simula-expand-stdproc)
- ("arctan" "ArcTan" simula-expand-stdproc)
- ("arctan2" "ArcTan2" simula-expand-stdproc)
- ("array" "ARRAY" simula-expand-keyword)
- ("at" "AT" simula-expand-keyword)
- ("before" "BEFORE" simula-expand-keyword)
- ("begin" "BEGIN" simula-expand-keyword)
- ("blanks" "Blanks" simula-expand-stdproc)
- ("boolean" "BOOLEAN" simula-expand-keyword)
- ("breakoutimage" "BreakOutImage" simula-expand-stdproc)
- ("bytefile" "ByteFile" simula-expand-stdproc)
- ("call" "Call" simula-expand-stdproc)
- ("cancel" "Cancel" simula-expand-stdproc)
- ("cardinal" "Cardinal" simula-expand-stdproc)
- ("char" "Char" simula-expand-stdproc)
- ("character" "CHARACTER" simula-expand-keyword)
- ("checkpoint" "CheckPoint" simula-expand-stdproc)
- ("class" "CLASS" simula-expand-keyword)
- ("clear" "Clear" simula-expand-stdproc)
- ("clocktime" "ClockTime" simula-expand-stdproc)
- ("close" "Close" simula-expand-stdproc)
- ("comment" "COMMENT" simula-expand-keyword)
- ("constant" "Constant" simula-expand-stdproc)
- ("copy" "Copy" simula-expand-stdproc)
- ("cos" "Cos" simula-expand-stdproc)
- ("cosh" "CosH" simula-expand-stdproc)
- ("cotan" "CoTan" simula-expand-stdproc)
- ("cputime" "CpuTime" simula-expand-stdproc)
- ("current" "Current" simula-expand-stdproc)
- ("datetime" "DateTime" simula-expand-stdproc)
- ("decimalmark" "DecimalMark" simula-expand-stdproc)
- ("delay" "DELAY" simula-expand-keyword)
- ("deleteimage" "DeleteImage" simula-expand-stdproc)
- ("detach" "Detach" simula-expand-stdproc)
- ("digit" "Digit" simula-expand-stdproc)
- ("directbytefile" "DirectByteFile" simula-expand-stdproc)
- ("directfile" "DirectFile" simula-expand-stdproc)
- ("discrete" "Discrete" simula-expand-stdproc)
- ("do" "DO" simula-expand-keyword)
- ("downcase" "Downcase" simula-expand-stdproc)
- ("draw" "Draw" simula-expand-stdproc)
- ("eject" "Eject" simula-expand-stdproc)
- ("else" "ELSE" simula-electric-keyword)
- ("empty" "Empty" simula-expand-stdproc)
- ("end" "END" simula-electric-keyword)
- ("endfile" "Endfile" simula-expand-stdproc)
- ("entier" "Entier" simula-expand-stdproc)
- ("eq" "EQ" simula-expand-keyword)
- ("eqv" "EQV" simula-expand-keyword)
- ("erlang" "Erlang" simula-expand-stdproc)
- ("error" "Error" simula-expand-stdproc)
- ("evtime" "EvTime" simula-expand-stdproc)
- ("exp" "Exp" simula-expand-stdproc)
- ("external" "EXTERNAL" simula-expand-keyword)
- ("false" "FALSE" simula-expand-keyword)
- ("field" "Field" simula-expand-stdproc)
- ("file" "File" simula-expand-stdproc)
- ("first" "First" simula-expand-stdproc)
- ("follow" "Follow" simula-expand-stdproc)
- ("for" "FOR" simula-expand-keyword)
- ("ge" "GE" simula-expand-keyword)
- ("getchar" "GetChar" simula-expand-stdproc)
- ("getfrac" "GetFrac" simula-expand-stdproc)
- ("getint" "GetInt" simula-expand-stdproc)
- ("getreal" "GetReal" simula-expand-stdproc)
- ("go" "GO" simula-expand-keyword)
- ("goto" "GOTO" simula-expand-keyword)
- ("gt" "GT" simula-expand-keyword)
- ("head" "Head" simula-expand-stdproc)
- ("hidden" "HIDDEN" simula-expand-keyword)
- ("histd" "HistD" simula-expand-stdproc)
- ("histo" "Histo" simula-expand-stdproc)
- ("hold" "Hold" simula-expand-stdproc)
- ("idle" "Idle" simula-expand-stdproc)
- ("if" "IF" simula-expand-keyword)
- ("image" "Image" simula-expand-stdproc)
- ("imagefile" "ImageFile" simula-expand-stdproc)
- ("imp" "IMP" simula-expand-keyword)
- ("in" "IN" simula-expand-keyword)
- ("inbyte" "InByte" simula-expand-stdproc)
- ("inbytefile" "InByteFile" simula-expand-stdproc)
- ("inchar" "InChar" simula-expand-stdproc)
- ("infile" "InFile" simula-expand-stdproc)
- ("infrac" "InFrac" simula-expand-stdproc)
- ("inimage" "InImage" simula-expand-stdproc)
- ("inint" "InInt" simula-expand-stdproc)
- ("inner" "INNER" simula-expand-keyword)
- ("inreal" "InReal" simula-expand-stdproc)
- ("inrecord" "InRecord" simula-expand-stdproc)
- ("inspect" "INSPECT" simula-expand-keyword)
- ("integer" "INTEGER" simula-expand-keyword)
- ("intext" "InText" simula-expand-stdproc)
- ("into" "Into" simula-expand-stdproc)
- ("is" "IS" simula-expand-keyword)
- ("isochar" "ISOChar" simula-expand-stdproc)
- ("isopen" "IsOpen" simula-expand-stdproc)
- ("isorank" "ISORank" simula-expand-stdproc)
- ("label" "LABEL" simula-expand-keyword)
- ("last" "Last" simula-expand-stdproc)
- ("lastitem" "LastItem" simula-expand-stdproc)
- ("lastloc" "LastLoc" simula-expand-stdproc)
- ("le" "LE" simula-expand-keyword)
- ("length" "Length" simula-expand-stdproc)
- ("letter" "Letter" simula-expand-stdproc)
- ("line" "Line" simula-expand-stdproc)
- ("linear" "Linear" simula-expand-stdproc)
- ("linesperpage" "LinesPerPage" simula-expand-stdproc)
- ("link" "Link" simula-expand-stdproc)
- ("linkage" "Linkage" simula-expand-stdproc)
- ("ln" "Ln" simula-expand-stdproc)
- ("locate" "Locate" simula-expand-stdproc)
- ("location" "Location" simula-expand-stdproc)
- ("lock" "Lock" simula-expand-stdproc)
- ("locked" "Locked" simula-expand-stdproc)
- ("log10" "Log10" simula-expand-stdproc)
- ("long" "LONG" simula-expand-keyword)
- ("lowcase" "LowCase" simula-expand-stdproc)
- ("lowerbound" "LowerBound" simula-expand-stdproc)
- ("lowten" "LowTen" simula-expand-stdproc)
- ("lt" "LT" simula-expand-keyword)
- ("main" "Main" simula-expand-stdproc)
- ("max" "Max" simula-expand-stdproc)
- ("maxint" "MaxInt" simula-expand-stdproc)
- ("maxlongreal" "MaxLongReal" simula-expand-stdproc)
- ("maxloc" "MaxLoc" simula-expand-stdproc)
- ("maxrank" "MaxRank" simula-expand-stdproc)
- ("maxreal" "MaxReal" simula-expand-stdproc)
- ("min" "Min" simula-expand-stdproc)
- ("minint" "MinInt" simula-expand-stdproc)
- ("minlongreal" "MinLongReal" simula-expand-stdproc)
- ("minrank" "MinRank" simula-expand-stdproc)
- ("minreal" "MinReal" simula-expand-stdproc)
- ("mod" "Mod" simula-expand-stdproc)
- ("more" "More" simula-expand-stdproc)
- ("name" "NAME" simula-expand-keyword)
- ("ne" "NE" simula-expand-keyword)
- ("negexp" "NegExp" simula-expand-stdproc)
- ("new" "NEW" simula-expand-keyword)
- ("nextev" "NextEv" simula-expand-stdproc)
- ("none" "NONE" simula-expand-keyword)
- ("normal" "Normal" simula-expand-stdproc)
- ("not" "NOT" simula-expand-keyword)
- ("notext" "NOTEXT" simula-expand-keyword)
- ("open" "Open" simula-expand-stdproc)
- ("or" "OR" simula-expand-keyword)
- ("otherwise" "OTHERWISE" simula-electric-keyword)
- ("out" "Out" simula-expand-stdproc)
- ("outbyte" "OutByte" simula-expand-stdproc)
- ("outbytefile" "OutByteFile" simula-expand-stdproc)
- ("outchar" "OutChar" simula-expand-stdproc)
- ("outfile" "OutFile" simula-expand-stdproc)
- ("outfix" "OutFix" simula-expand-stdproc)
- ("outfrac" "OutFrac" simula-expand-stdproc)
- ("outimage" "OutImage" simula-expand-stdproc)
- ("outint" "OutInt" simula-expand-stdproc)
- ("outreal" "OutReal" simula-expand-stdproc)
- ("outrecord" "OutRecord" simula-expand-stdproc)
- ("outtext" "OutText" simula-expand-stdproc)
- ("page" "Page" simula-expand-stdproc)
- ("passivate" "Passivate" simula-expand-stdproc)
- ("poisson" "Poisson" simula-expand-stdproc)
- ("pos" "Pos" simula-expand-stdproc)
- ("precede" "Precede" simula-expand-stdproc)
- ("pred" "Pred" simula-expand-stdproc)
- ("prev" "Prev" simula-expand-stdproc)
- ("printfile" "PrintFile" simula-expand-stdproc)
- ("prior" "PRIOR" simula-expand-keyword)
- ("procedure" "PROCEDURE" simula-expand-keyword)
- ("process" "Process" simula-expand-stdproc)
- ("protected" "PROTECTED" simula-expand-keyword)
- ("putchar" "PutChar" simula-expand-stdproc)
- ("putfix" "PutFix" simula-expand-stdproc)
- ("putfrac" "PutFrac" simula-expand-stdproc)
- ("putint" "PutInt" simula-expand-stdproc)
- ("putreal" "PutReal" simula-expand-stdproc)
- ("qua" "QUA" simula-expand-keyword)
- ("randint" "RandInt" simula-expand-stdproc)
- ("rank" "Rank" simula-expand-stdproc)
- ("reactivate" "REACTIVATE" simula-expand-keyword)
- ("real" "REAL" simula-expand-keyword)
- ("ref" "REF" simula-expand-keyword)
- ("resume" "Resume" simula-expand-stdproc)
- ("setaccess" "SetAccess" simula-expand-stdproc)
- ("setpos" "SetPos" simula-expand-stdproc)
- ("short" "SHORT" simula-expand-keyword)
- ("sign" "Sign" simula-expand-stdproc)
- ("simset" "SimSet" simula-expand-stdproc)
- ("simulaid" "SimulaId" simula-expand-stdproc)
- ("simulation" "Simulation" simula-expand-stdproc)
- ("sin" "Sin" simula-expand-stdproc)
- ("sinh" "SinH" simula-expand-stdproc)
- ("sourceline" "SourceLine" simula-expand-stdproc)
- ("spacing" "Spacing" simula-expand-stdproc)
- ("sqrt" "Sqrt" simula-expand-stdproc)
- ("start" "Start" simula-expand-stdproc)
- ("step" "STEP" simula-expand-keyword)
- ("strip" "Strip" simula-expand-stdproc)
- ("sub" "Sub" simula-expand-stdproc)
- ("subepsilon" "SubEpsilon" simula-expand-stdproc)
- ("suc" "Suc" simula-expand-stdproc)
- ("switch" "SWITCH" simula-expand-keyword)
- ("sysin" "SysIn" simula-expand-stdproc)
- ("sysout" "SysOut" simula-expand-stdproc)
- ("tan" "Tan" simula-expand-stdproc)
- ("tanh" "TanH" simula-expand-stdproc)
- ("terminate_program" "Terminate_Program" simula-expand-stdproc)
- ("terminated" "Terminated" simula-expand-stdproc)
- ("text" "TEXT" simula-expand-keyword)
- ("then" "THEN" simula-electric-keyword)
- ("this" "THIS" simula-expand-keyword)
- ("time" "Time" simula-expand-stdproc)
- ("to" "TO" simula-expand-keyword)
- ("true" "TRUE" simula-expand-keyword)
- ("uniform" "Uniform" simula-expand-stdproc)
- ("unlock" "Unlock" simula-expand-stdproc)
- ("until" "UNTIL" simula-expand-keyword)
- ("upcase" "Upcase" simula-expand-stdproc)
- ("upperbound" "UpperBound" simula-expand-stdproc)
- ("value" "VALUE" simula-expand-keyword)
- ("virtual" "VIRTUAL" simula-expand-keyword)
- ("wait" "Wait" simula-expand-stdproc)
- ("when" "WHEN" simula-electric-keyword)
- ("while" "WHILE" simula-expand-keyword))))
-
-;;; Font Lock mode support.
-(eval-when-compile
- (require 'cl))
-
-;; SIMULA comments and strings are a mess. If we rely on the syntax table,
-;; then %-comments may be shown incorrectly (and prematurely) ended by a
-;; semicolon, !-comments by a newline and '-strings may screw up the rest of
-;; the buffer. And of course we can't do comment- or end-comments using the
-;; syntax table. We can do everything except end-comments in one fast regexp,
-;; but we aught to do end-comments too, so we need a function. simon@gnu.
-(defun simula-match-string-or-comment (limit)
- ;; Return t if there is a string or comment before LIMIT.
- ;; Matches buffer text so that if (match-string 1) is non-nil, it is the
- ;; string. Otherwise, (match-string 0) is non-nil, and is the comment.
- (when (re-search-forward
- (eval-when-compile
- (concat "\\(\"[^\"\n]*\"\\|'\\(.\\|![0-9]+!\\)'\\)\\|"
- "\\(\\<end[ \t\n]+\\)\\|"
- "^%[ \t].*\\|\\(!\\|\\<comment\\>\\)[^;]*;?"))
- limit t)
- (when (match-beginning 3)
- ;; We've matched an end-comment. Yuck. Find the extent of it.
- (store-match-data
- (list (point)
- (if (re-search-forward "\\<\\(end\\|else\\|when\\|otherwise\\)\\>\\|;"
- limit 'move)
- (match-beginning 0)
- (point)))))
- t))
-
-;;; Hilit mode support.
-(if (and (fboundp 'hilit-set-mode-patterns)
- (boundp 'hilit-patterns-alist)
- (not (assoc 'simula-mode hilit-patterns-alist)))
- (hilit-set-mode-patterns
- 'simula-mode
- '(
- ("^%\\([ \t\f].*\\)?$" nil comment)
- ("^%include\\>" nil include)
- ("\"[^\"\n]*\"\\|'.'\\|'![0-9]+!'" nil string)
- ("\\<\\(ACTIVATE\\|AFTER\\|AND\\|ARRAY\\|AT\\|BEFORE\\|BEGIN\\|BOOLEAN\\|CHARACTER\\|CLASS\\|DELAY\\|DO\\|ELSE\\|END\\|EQ\\|EQV\\|EXTERNAL\\|FALSE\\|FOR\\|GE\\|GO\\|GOTO\\|GT\\|HIDDEN\\|IF\\|IMP\\|IN\\|INNER\\|INSPECT\\|INTEGER\\|IS\\|LABEL\\|LE\\|LONG\\|LT\\|NAME\\|NE\\|NEW\\|NONE\\|NOT\\|NOTEXT\\|OR\\|OTHERWISE\\|PRIOR\\|PROCEDURE\\|PROTECTED\\|QUA\\|REACTIVATE\\|REAL\\|REF\\|SHORT\\|STEP\\|SWITCH\\|TEXT\\|THEN\\|THIS\\|TO\\|TRUE\\|UNTIL\\|VALUE\\|VIRTUAL\\|WHEN\\|WHILE\\)\\>" nil keyword)
- ("!\\|\\<COMMENT\\>" ";" comment))
- nil 'case-insensitive))
-
-;; None of this seems to be used by anything, including hilit19.el. simon@gnu.
-;(setq simula-find-comment-point -1
-; simula-find-comment-context nil)
-;
-;;; function used by hilit19
-;(defun simula-find-next-comment-region (param)
-; "Return region (start end) cons of comment after point, or NIL"
-; (let (start end)
-; ;; This function is called repeatedly, check if point is
-; ;; where we left it in the last call
-; (if (not (eq simula-find-comment-point (point)))
-; (setq simula-find-comment-point (point)
-; simula-find-comment-context (simula-context)))
-; ;; loop as long as we haven't found the end of a comment
-; (if (memq simula-find-comment-context '(0 1 2))
-; (setq start (point))
-; (if (re-search-forward "\\<end\\>\\|!\\|\"\\|'\\|^%\\|\\<comment\\>"
-; nil 'move)
-; (let ((previous-char (preceding-char)))
-; (cond
-; ((memq previous-char '(?d ?D))
-; (setq start (point)
-; simula-find-comment-context 2))
-; ((memq previous-char '(?t ?T ?\!))
-; (setq start (point)
-; simula-find-comment-context 0))
-; ((eq previous-char ?%)
-; (setq start (point)
-; simula-find-comment-context 0))))))
-; ;; BUG: the following (0 2) branches don't take into account intermixing
-; ;; directive lines
-; (cond
-; ((eq simula-find-comment-context 0)
-; (search-forward ";" nil 'move))
-; ((eq simula-find-comment-context 1)
-; (beginning-of-line 2))
-; ((eq simula-find-comment-context 2)
-; (re-search-forward ";\\|\\<end\\>\\|\\<else\\>\\|\\<otherwise\\>\\|\\<when\\>\\" (point-max) 'move)))
-; (if start
-; (setq end (point)))
-; ;; save point for later calls to this function
-; (setq simula-find-comment-point (if end (point) -1))
-; (and end (cons start end))))
-
-;; defuns for submitting bug reports
-
-(defconst simula-mode-help-address "simula-mode@ifi.uio.no"
- "Address accepting submission of simula-mode bug reports.")
-
-(defun simula-submit-bug-report ()
- "Submit via mail a bug report on simula-mode."
- (interactive)
- (and
- (y-or-n-p "Do you want to submit a report on simula-mode? ")
- (reporter-submit-bug-report
- simula-mode-help-address
- (concat "simula-mode from Emacs " emacs-version)
- (list
- ;; report only the vars that affect indentation
- 'simula-emacs-features
- 'simula-indent-level
- 'simula-substatement-offset
- 'simula-continued-statement-offset
- 'simula-label-offset
- 'simula-if-indent
- 'simula-inspect-indent
- 'simula-electric-indent
- 'simula-abbrev-keyword
- 'simula-abbrev-stdproc
- 'simula-abbrev-file
- 'simula-tab-always-indent
- ))))
-
-(provide 'simula-mode)
-
-;;; simula.el ends here
diff --git a/lisp/progmodes/tcl.el b/lisp/progmodes/tcl.el
deleted file mode 100644
index ef8e27b68df..00000000000
--- a/lisp/progmodes/tcl.el
+++ /dev/null
@@ -1,2227 +0,0 @@
-;; tcl.el --- Tcl code editing commands for Emacs
-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-
-;; Maintainer: Tom Tromey <tromey@busco.lanl.gov>
-;; Author: Tom Tromey <tromey@busco.lanl.gov>
-;; Chris Lindblad <cjl@lcs.mit.edu>
-;; Keywords: languages tcl modes
-;; Version: $Revision: 1.50 $
-
-;; 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 TO INSTALL:
-;; Put the following forms in your .emacs to enable autoloading of Tcl
-;; mode, and auto-recognition of ".tcl" files.
-;;
-;; (autoload 'tcl-mode "tcl" "Tcl mode." t)
-;; (autoload 'inferior-tcl "tcl" "Run inferior Tcl process." t)
-;; (setq auto-mode-alist (append '(("\\.tcl$" . tcl-mode)) auto-mode-alist))
-;;
-;; If you plan to use the interface to the TclX help files, you must
-;; set the variable tcl-help-directory-list to point to the topmost
-;; directories containing the TclX help files. Eg:
-;;
-;; (setq tcl-help-directory-list '("/usr/local/lib/tclx/help"))
-;;
-;; Also you will want to add the following to your .emacs:
-;;
-;; (autoload 'tcl-help-on-word "tcl" "Help on Tcl commands" t)
-;;
-;; FYI a *very* useful thing to do is nroff all the Tk man pages and
-;; put them in a subdir of the help system.
-;;
-
-;;; Commentary:
-
-;; LCD Archive Entry:
-;; tcl|Tom Tromey|tromey@busco.lanl.gov|
-;; Major mode for editing Tcl|
-;; $Date: 1996/03/23 05:14:50 $|$Revision: 1.50 $|~/modes/tcl.el.Z|
-
-;; CUSTOMIZATION NOTES:
-;; * tcl-proc-list can be used to customize a list of things that
-;; "define" other things. Eg in my project I put "defvar" in this
-;; list.
-;; * tcl-typeword-list is similar, but uses font-lock-type-face.
-;; * tcl-keyword-list is a list of keywords. I've generally used this
-;; for flow-control words. Eg I add "unwind_protect" to this list.
-;; * tcl-type-alist can be used to minimally customize indentation
-;; according to context.
-
-;; Change log:
-;; $Log: tcl.el,v $
-;; Revision 1.50 1996/03/23 05:14:50 tromey
-;; (tcl-using-emacs-19): Work with XEmacs 20.0. From Ben Wing.
-;;
-;; Revision 1.49 1995/12/07 18:27:47 tromey
-;; (add-log-tcl-defun): Don't use tcl-beginning-of-defun; just go to end
-;; of line before searching.
-;;
-;; Revision 1.48 1995/12/07 18:18:21 tromey
-;; (add-log-tcl-defun): Now uses tcl-beginning-of-defun.
-;;
-;; Revision 1.47 1995/08/22 17:49:45 tromey
-;; (tcl-hilit): New function from "Chris Alfeld" <calfeld@math.utah.edu>
-;; (tcl-mode): Call it
-;;
-;; Revision 1.46 1995/08/07 16:02:01 tromey
-;; (tcl-do-auto-fill): Only fill past fill-column; for 19.29.
-;; (tcl-auto-fill-mode): Use force-mode-line-update.
-;;
-;; Revision 1.45 1995/07/23 23:51:25 tromey
-;; (tcl-word-no-props): New function.
-;; (tcl-figure-type): Use it.
-;; (tcl-current-word): Ditto.
-;;
-;; Revision 1.44 1995/07/23 20:26:47 tromey
-;; Doc fixes.
-;;
-;; Revision 1.43 1995/07/17 19:59:49 tromey
-;; (inferior-tcl-mode): Use modeline-process if it exists.
-;;
-;; Revision 1.42 1995/07/17 19:55:25 tromey
-;; XEmacs currently must use tcl-internal-end-of-defun
-;;
-;; Revision 1.41 1995/07/14 21:54:56 tromey
-;; Changes to make menus work in XEmacs.
-;; From Mike Scheidler <c23mts@kocrsv01.delcoelect.com>
-;;
-;; Revision 1.40 1995/07/11 03:13:15 tromey
-;; (tcl-mode): Customize for new dabbrev.
-;;
-;; Revision 1.39 1995/07/09 21:58:03 tromey
-;; (tcl-do-fill-paragraph): New function.
-;; (tcl-mode): Set up for paragraph filling.
-;;
-;; Revision 1.38 1995/07/09 21:30:32 tromey
-;; (tcl-mode): Fixes to 19.29 paragraph variables.
-;;
-;; Revision 1.37 1995/07/09 18:52:16 tromey
-;; (tcl-do-auto-fill): Set fill-prefix.
-;;
-;; Revision 1.36 1995/07/09 01:07:57 tromey
-;; (tcl-imenu-create-index-function): Work with imenu from Emacs 19.29
-;;
-;; Revision 1.35 1995/06/27 20:12:00 tromey
-;; (tcl-type-alist): More itcl changes.
-;;
-;; Revision 1.34 1995/06/27 20:06:05 tromey
-;; More changes for itcl.
-;; Bug fixes for Emacs 19.29.
-;;
-;; Revision 1.33 1995/06/27 20:01:29 tromey
-;; (tcl-set-proc-regexp): Allow leading spaces.
-;; (tcl-proc-list): Changes for itcl.
-;; (tcl-typeword-list): Ditto.
-;; (tcl-keyword-list): Ditto.
-;;
-;; Revision 1.32 1995/05/11 22:12:49 tromey
-;; (tcl-type-alist): Include entry for "proc".
-;;
-;; Revision 1.31 1995/05/10 23:38:12 tromey
-;; (tcl-add-fsf-menu): Use make-lucid-menu-keymap, not
-;; "make-xemacs-menu-keymap".
-;;
-;; Revision 1.30 1995/05/10 18:22:21 tromey
-;; Bug fix in menu code for XEmacs.
-;;
-;; Revision 1.29 1995/05/09 21:36:53 tromey
-;; Changed "Lucid Emacs" to "XEmacs".
-;; Tcl's popup menu now added to existing one, courtesy
-;; dfarmer@evolving.com (Doug Farmer)
-;;
-;; Revision 1.28 1995/04/08 19:52:50 tromey
-;; (tcl-outline-level): New function
-;; (tcl-mode): Added outline-handling stuff.
-;; From Jesper Pedersen <blackie@imada.ou.dk>
-;;
-;; Revision 1.27 1994/10/11 02:01:27 tromey
-;; (tcl-mode): imenu-create-index-function made buffer local.
-;;
-;; Revision 1.26 1994/09/01 18:06:24 tromey
-;; Added filename completion in inferior tcl mode
-;;
-;; Revision 1.25 1994/08/22 15:56:24 tromey
-;; tcl-load-file default to current buffer.
-;;
-;; Revision 1.24 1994/08/21 20:33:05 tromey
-;; Fixed bug in tcl-guess-application.
-;;
-;; Revision 1.23 1994/08/21 03:54:45 tromey
-;; Keybindings don't overshadown comint bindings.
-;;
-;; Revision 1.22 1994/07/26 00:46:07 tromey
-;; Emacs 18 changes from Carl Witty.
-;;
-;; Revision 1.21 1994/07/14 22:49:21 tromey
-;; Added ";;;###autoload" comments where appropriate.
-;;
-; Revision 1.20 1994/06/05 16:57:22 tromey
-; tcl-current-word does the right thing in inferior-tcl-mode.
-;
-; Revision 1.19 1994/06/03 21:09:19 tromey
-; Another menu fix.
-;
-; Revision 1.18 1994/06/03 20:39:14 tromey
-; Fixed menu bug.
-;
-; Revision 1.17 1994/06/03 00:47:15 tromey
-; Fixed bug in bug-reporting code.
-;
-; Revision 1.16 1994/05/26 05:06:14 tromey
-; Menu items now sensitive as appropriate.
-;
-; Revision 1.15 1994/05/22 20:38:11 tromey
-; Added bug-report keybindings and menu entries.
-;
-; Revision 1.14 1994/05/22 20:18:28 tromey
-; Even more compile stuff.
-;
-; Revision 1.13 1994/05/22 20:17:15 tromey
-; Moved emacs version checking code to very beginning.
-;
-; Revision 1.12 1994/05/22 20:14:59 tromey
-; Compile fixes.
-;
-; Revision 1.11 1994/05/22 20:12:44 tromey
-; Fixed mark-defun for 19.23.
-; More menu fixes.
-;
-; Revision 1.10 1994/05/22 20:02:03 tromey
-; Fixed bug with M-;.
-; Wrote bug-reporting code.
-;
-; Revision 1.9 1994/05/22 05:26:51 tromey
-; Fixes for imenu.
-;
-; Revision 1.8 1994/05/22 03:38:07 tromey
-; Fixed menu support.
-;
-; Revision 1.7 1994/05/03 01:23:42 tromey
-; *** empty log message ***
-;
-; Revision 1.6 1994/04/23 16:23:36 tromey
-; Wrote tcl-indent-for-comment
-;
-;;
-;; 18-Mar-1994 Tom Tromey Fourth beta release.
-;; Added {un,}comment-region to menu. Idea from
-;; Mike Scheidler <c23mts@kocrsv01.delcoelect.com>
-;; 17-Mar-1994 Tom Tromey
-;; Fixed tcl-restart-with-file. Bug fix attempt in
-;; tcl-internal-end-of-defun.
-;; 16-Mar-1994 Tom Tromey Third beta release
-;; Added support code for menu (from Tcl mode written by
-;; schmid@fb3-s7.math.TU-Berlin.DE (Gregor Schmid)).
-;; 12-Mar-1994 Tom Tromey
-;; Better documentation for inferior-tcl-buffer. Wrote
-;; tcl-restart-with-file. Wrote Lucid Emacs menu (but no
-;; code to install it).
-;; 12-Mar-1994 Tom Tromey
-;; Wrote tcl-guess-application. Another stab at making
-;; tcl-omit-ws-regexp work.
-;; 10-Mar-1994 Tom Tromey Second beta release
-;; Last Modified: Thu Mar 10 01:24:25 1994 (Tom Tromey)
-;; Wrote perl-mode style line indentation command.
-;; Wrote more documentation. Added tcl-continued-indent-level.
-;; Integrated help code.
-;; 8-Mar-1994 Tom Tromey
-;; Last Modified: Tue Mar 8 11:58:44 1994 (Tom Tromey)
-;; Bug fixes.
-;; 6-Mar-1994 Tom Tromey
-;; Last Modified: Sun Mar 6 18:55:41 1994 (Tom Tromey)
-;; Updated auto-newline support.
-;; 6-Mar-1994 Tom Tromey Beta release
-;; Last Modified: Sat Mar 5 17:24:32 1994 (Tom Tromey)
-;; Wrote tcl-hashify-buffer. Other minor bug fixes.
-;; 5-Mar-1994 Tom Tromey
-;; Last Modified: Sat Mar 5 16:11:20 1994 (Tom Tromey)
-;; Wrote electric-hash code.
-;; 3-Mar-1994 Tom Tromey
-;; Last Modified: Thu Mar 3 02:53:40 1994 (Tom Tromey)
-;; Added code to handle auto-fill in comments.
-;; Added imenu support code.
-;; Cleaned up code.
-;; Better font-lock support.
-;; 28-Feb-1994 Tom Tromey
-;; Last Modified: Mon Feb 28 14:08:05 1994 (Tom Tromey)
-;; Made tcl-figure-type more easily configurable.
-;; 28-Feb-1994 Tom Tromey
-;; Last Modified: Mon Feb 28 01:02:58 1994 (Tom Tromey)
-;; Wrote inferior-tcl mode.
-;; 16-Feb-1994 Tom Tromey
-;; Last Modified: Wed Feb 16 17:05:19 1994 (Tom Tromey)
-;; Added support for font-lock-mode.
-;; 29-Oct-1993 Tom Tromey
-;; Last Modified: Sun Oct 24 17:39:14 1993 (Tom Tromey)
-;; Patches from Guido Bosch to make things work with Lucid Emacs.
-;; 22-Oct-1993 Tom Tromey
-;; Last Modified: Fri Oct 22 15:26:46 1993 (Tom Tromey)
-;; Made many characters have "_" syntax class; suggested by Guido
-;; Bosch <Guido.Bosch@loria.fr>. Note that this includes the "$"
-;; character, which might be a change you'd notice.
-;; 21-Oct-1993 Tom Tromey
-;; Last Modified: Thu Oct 21 20:28:40 1993 (Tom Tromey)
-;; More fixes for tcl-omit-ws-regexp.
-;; 20-Oct-1993 Tom Tromey
-;; Started keeping history. Fixed tcl-{beginning,end}-of-defun.
-;; Added some code to make things work with Emacs 18.
-
-;; THANKS TO:
-;; Guido Bosch <Guido.Bosch@loria.fr>
-;; pgs1002@esc.cam.ac.uk (Dr P.G. Sjoerdsma)
-;; Mike Scheidler <c23mts@kocrsv01.delcoelect.com>
-;; Matt Newman <men@charney.colorado.edu>
-;; rwhitby@research.canon.oz.au (Rod Whitby)
-;; h9118101@hkuxa.hku.hk (Yip Chi Lap [Beta])
-;; Pertti Tapio Kasanen <ptk@delta.hut.fi>
-;; schmid@fb3-s7.math.TU-Berlin.DE (Gregor Schmid)
-;; warsaw@nlm.nih.gov (Barry A. Warsaw)
-;; Carl Witty <cwitty@ai.mit.edu>
-;; T. V. Raman <raman@crl.dec.com>
-;; Jesper Pedersen <blackie@imada.ou.dk>
-;; dfarmer@evolving.com (Doug Farmer)
-;; "Chris Alfeld" <calfeld@math.utah.edu>
-;; Ben Wing <wing@666.com>
-
-;; KNOWN BUGS:
-;; * indent-region should skip blank lines. (It does in v19, so I'm
-;; not motivated to fix it here).
-;; * In Tcl "#" is not always a comment character. This can confuse
-;; tcl.el in certain circumstances. For now the only workaround is
-;; to enclose offending hash characters in quotes or precede it with
-;; a backslash. Note that using braces won't work -- quotes change
-;; the syntax class of characters between them, while braces do not.
-;; The electric-# mode helps alleviate this problem somewhat.
-;; * indent-tcl-exp is untested.
-;; * Doesn't work under Emacs 18 yet.
-;; * There's been a report that font-lock does strange things under
-;; Lucid Emacs 19.6. For instance in "proc foobar", the space
-;; before "foobar" is highlighted.
-
-;; TODO:
-;; * make add-log-tcl-defun smarter. should notice if we are in the
-;; middle of a defun, or between defuns. should notice if point is
-;; on first line of defun (or maybe even in comments before defun).
-;; * Allow continuation lines to be indented under the first argument
-;; of the preceeding line, like this:
-;; [list something \
-;; something-else]
-;; * There is a request that indentation work like this:
-;; button .fred -label Fred \
-;; -command {puts fred}
-;; * Should have tcl-complete-symbol that queries the inferior process.
-;; * Should have describe-symbol that works by sending the magic
-;; command to a tclX process.
-;; * Need C-x C-e binding (tcl-eval-last-exp).
-;; * Write indent-region function that is faster than indenting each
-;; line individually.
-;; * tcl-figure-type should stop at "beginning of line" (only ws
-;; before point, and no "\" on previous line). (see tcl-real-command-p).
-;; * overrides some comint keybindings; fix.
-;; * Trailing \ will eat blank lines. Should deal with this.
-;; (this would help catch some potential bugs).
-;; * Inferior should display in half the screen, not the whole screen.
-;; * Indentation should deal with "switch".
-;; * Consider writing code to find help files automatically (for
-;; common cases).
-;; * `#' shouldn't insert `\#' when point is in string.
-
-
-
-;;; Code:
-
-;; I sure wish Emacs had a package that made it easy to extract this
-;; sort of information. Strange definition works with XEmacs 20.0.
-(defconst tcl-using-emacs-19 (not (string-match "18\\." emacs-version))
- "Nil unless using Emacs 19 (XEmacs or FSF).")
-
-;; FIXME this will break on Emacs 19.100.
-(defconst tcl-using-emacs-19-23
- (string-match "19\\.\\(2[3-9]\\|[3-9][0-9]\\)" emacs-version)
- "Nil unless using Emacs 19-23 or later.")
-
-(defconst tcl-using-xemacs-19 (string-match "XEmacs" emacs-version)
- "Nil unless using XEmacs).")
-
-(require 'comint)
-
-;; When compiling under GNU Emacs, load imenu during compilation. If
-;; you have 19.22 or earlier, comment this out, or get imenu.
-(and (fboundp 'eval-when-compile)
- (eval-when-compile
- (if (and (string-match "19\\." emacs-version)
- (not (string-match "XEmacs" emacs-version)))
- (require 'imenu))
- ()))
-
-(defconst tcl-version "$Revision: 1.50 $")
-(defconst tcl-maintainer "Tom Tromey <tromey@drip.colorado.edu>")
-
-;;
-;; User variables.
-;;
-
-(defvar tcl-indent-level 4
- "*Indentation of Tcl statements with respect to containing block.")
-
-(defvar tcl-continued-indent-level 4
- "*Indentation of continuation line relative to first line of command.")
-
-(defvar tcl-auto-newline nil
- "*Non-nil means automatically newline before and after braces
-inserted in Tcl code.")
-
-(defvar tcl-tab-always-indent t
- "*Control effect of TAB key.
-If t (the default), always indent current line.
-If nil and point is not in the indentation area at the beginning of
-the line, a TAB is inserted.
-Other values cause the first possible action from the following list
-to take place:
-
- 1. Move from beginning of line to correct indentation.
- 2. Delete an empty comment.
- 3. Move forward to start of comment, indenting if necessary.
- 4. Move forward to end of line, indenting if necessary.
- 5. Create an empty comment.
- 6. Move backward to start of comment, indenting if necessary.")
-
-(defvar tcl-use-hairy-comment-detector t
- "*If not `nil', the the more complicated, but slower, comment
-detecting function is used. This variable is only used in GNU Emacs
-19 (the fast function is always used elsewhere).")
-
-(defvar tcl-electric-hash-style 'smart
- "*Style of electric hash insertion to use.
-Possible values are 'backslash, meaning that `\\' quoting should be
-done; 'quote, meaning that `\"' quoting should be done; 'smart,
-meaning that the choice between 'backslash and 'quote should be
-made depending on the number of hashes inserted; or nil, meaning that
-no quoting should be done. Any other value for this variable is
-taken to mean 'smart. The default is 'smart.")
-
-(defvar tcl-help-directory-list nil
- "*List of topmost directories containing TclX help files")
-
-(defvar tcl-use-smart-word-finder t
- "*If not nil, use a better way of finding the current word when
-looking up help on a Tcl command.")
-
-(defvar tcl-application "wish"
- "*Name of Tcl application to run in inferior Tcl mode.")
-
-(defvar tcl-command-switches nil
- "*Switches to supply to `tcl-application'.")
-
-(defvar tcl-prompt-regexp "^\\(% \\|\\)"
- "*If not nil, a regexp that will match the prompt in the inferior process.
-If nil, the prompt is the name of the application with \">\" appended.
-
-The default is \"^\\(% \\|\\)\", which will match the default primary
-and secondary prompts for tclsh and wish.")
-
-(defvar inferior-tcl-source-command "source %s\n"
- "*Format-string for building a Tcl command to load a file.
-This format string should use `%s' to substitute a file name
-and should result in a Tcl expression that will command the
-inferior Tcl to load that file. The filename will be appropriately
-quoted for Tcl.")
-
-;;
-;; Keymaps, abbrevs, syntax tables.
-;;
-
-(defvar tcl-mode-abbrev-table nil
- "Abbrev table in use in Tcl-mode buffers.")
-(if tcl-mode-abbrev-table
- ()
- (define-abbrev-table 'tcl-mode-abbrev-table ()))
-
-(defvar tcl-mode-map ()
- "Keymap used in Tcl mode.")
-
-(defvar tcl-mode-syntax-table nil
- "Syntax table in use in Tcl-mode buffers.")
-(if tcl-mode-syntax-table
- ()
- (setq tcl-mode-syntax-table (make-syntax-table))
- (modify-syntax-entry ?% "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?@ "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?& "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?* "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?+ "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?- "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?. "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?: "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?! "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?$ "_" tcl-mode-syntax-table) ; FIXME use "'"?
- (modify-syntax-entry ?/ "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?~ "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?< "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?= "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?> "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?| "_" tcl-mode-syntax-table)
- (modify-syntax-entry ?\( "()" tcl-mode-syntax-table)
- (modify-syntax-entry ?\) ")(" tcl-mode-syntax-table)
- (modify-syntax-entry ?\; "." tcl-mode-syntax-table)
- (modify-syntax-entry ?\n "> " tcl-mode-syntax-table)
- (modify-syntax-entry ?\f "> " tcl-mode-syntax-table)
- (modify-syntax-entry ?# "< " tcl-mode-syntax-table))
-
-(defvar inferior-tcl-mode-map nil
- "Keymap used in Inferior Tcl mode.")
-
-;; XEmacs menu.
-(defvar tcl-xemacs-menu
- '(["Beginning of function" tcl-beginning-of-defun t]
- ["End of function" tcl-end-of-defun t]
- ["Mark function" tcl-mark-defun t]
- ["Indent region" indent-region (tcl-mark)]
- ["Comment region" comment-region (tcl-mark)]
- ["Uncomment region" tcl-uncomment-region (tcl-mark)]
- "----"
- ["Show Tcl process buffer" inferior-tcl t]
- ["Send function to Tcl process" tcl-eval-defun
- (and inferior-tcl-buffer (get-buffer inferior-tcl-buffer))]
- ["Send region to Tcl process" tcl-eval-region
- (and inferior-tcl-buffer (get-buffer inferior-tcl-buffer))]
- ["Send file to Tcl process" tcl-load-file
- (and inferior-tcl-buffer (get-buffer inferior-tcl-buffer))]
- ["Restart Tcl process with file" tcl-restart-with-file t]
- "----"
- ["Tcl help" tcl-help-on-word tcl-help-directory-list]
- ["Send bug report" tcl-submit-bug-report t])
- "XEmacs menu for Tcl mode.")
-
-;; GNU Emacs does menus via keymaps. Do it in a function in case we
-;; later decide to add it to inferior Tcl mode as well.
-(defun tcl-add-fsf-menu (map)
- (define-key map [menu-bar] (make-sparse-keymap))
- ;; This fails in Emacs 19.22 and earlier.
- (require 'lmenu)
- (let ((menu (make-lucid-menu-keymap "Tcl" tcl-xemacs-menu)))
- (define-key map [menu-bar tcl] (cons "Tcl" menu))
- ;; The following is intended to compute the key sequence
- ;; information for the menu. It doesn't work.
- (x-popup-menu nil menu)))
-
-(defun tcl-fill-mode-map ()
- (define-key tcl-mode-map "{" 'tcl-electric-char)
- (define-key tcl-mode-map "}" 'tcl-electric-brace)
- (define-key tcl-mode-map "[" 'tcl-electric-char)
- (define-key tcl-mode-map "]" 'tcl-electric-char)
- (define-key tcl-mode-map ";" 'tcl-electric-char)
- (define-key tcl-mode-map "#" 'tcl-electric-hash)
- ;; FIXME.
- (define-key tcl-mode-map "\e\C-a" 'tcl-beginning-of-defun)
- ;; FIXME.
- (define-key tcl-mode-map "\e\C-e" 'tcl-end-of-defun)
- ;; FIXME.
- (define-key tcl-mode-map "\e\C-h" 'tcl-mark-defun)
- (define-key tcl-mode-map "\e\C-q" 'indent-tcl-exp)
- (define-key tcl-mode-map "\177" 'backward-delete-char-untabify)
- (define-key tcl-mode-map "\t" 'tcl-indent-command)
- (define-key tcl-mode-map "\M-;" 'tcl-indent-for-comment)
- (define-key tcl-mode-map "\M-\C-x" 'tcl-eval-defun)
- (define-key tcl-mode-map "\C-c\C-b" 'tcl-submit-bug-report)
- (and (fboundp 'comment-region)
- (define-key tcl-mode-map "\C-c\C-c" 'comment-region))
- (define-key tcl-mode-map "\C-c\C-i" 'tcl-help-on-word)
- (define-key tcl-mode-map "\C-c\C-v" 'tcl-eval-defun)
- (define-key tcl-mode-map "\C-c\C-f" 'tcl-load-file)
- (define-key tcl-mode-map "\C-c\C-t" 'inferior-tcl)
- (define-key tcl-mode-map "\C-c\C-x" 'tcl-eval-region)
- (define-key tcl-mode-map "\C-c\C-s" 'switch-to-tcl)
-
- ;; Make menus.
- (if (and tcl-using-emacs-19 (not tcl-using-xemacs-19))
- (progn
- (tcl-add-fsf-menu tcl-mode-map))))
-
-(defun tcl-fill-inferior-map ()
- (define-key inferior-tcl-mode-map "\t" 'comint-dynamic-complete)
- (define-key inferior-tcl-mode-map "\M-?"
- 'comint-dynamic-list-filename-completions)
- (define-key inferior-tcl-mode-map "\e\C-a" 'tcl-beginning-of-defun)
- (define-key inferior-tcl-mode-map "\e\C-e" 'tcl-end-of-defun)
- (define-key inferior-tcl-mode-map "\177" 'backward-delete-char-untabify)
- (define-key inferior-tcl-mode-map "\M-\C-x" 'tcl-eval-defun)
- (define-key inferior-tcl-mode-map "\C-c\C-b" 'tcl-submit-bug-report)
- (define-key inferior-tcl-mode-map "\C-c\C-i" 'tcl-help-on-word)
- (define-key inferior-tcl-mode-map "\C-c\C-v" 'tcl-eval-defun)
- (define-key inferior-tcl-mode-map "\C-c\C-f" 'tcl-load-file)
- (define-key inferior-tcl-mode-map "\C-c\C-t" 'inferior-tcl)
- (define-key inferior-tcl-mode-map "\C-c\C-x" 'tcl-eval-region)
- (define-key inferior-tcl-mode-map "\C-c\C-s" 'switch-to-tcl))
-
-(if tcl-mode-map
- ()
- (setq tcl-mode-map (make-sparse-keymap))
- (tcl-fill-mode-map))
-
-(if inferior-tcl-mode-map
- ()
- ;; FIXME Use keymap inheritance here? FIXME we override comint
- ;; keybindings here. Maybe someone has a better set?
- (setq inferior-tcl-mode-map (copy-keymap comint-mode-map))
- (tcl-fill-inferior-map))
-
-
-(defvar inferior-tcl-buffer nil
- "*The current inferior-tcl process buffer.
-
-MULTIPLE PROCESS SUPPORT
-===========================================================================
-To run multiple Tcl processes, you start the first up with
-\\[inferior-tcl]. It will be in a buffer named `*inferior-tcl*'.
-Rename this buffer with \\[rename-buffer]. You may now start up a new
-process with another \\[inferior-tcl]. It will be in a new buffer,
-named `*inferior-tcl*'. You can switch between the different process
-buffers with \\[switch-to-buffer].
-
-Commands that send text from source buffers to Tcl processes -- like
-`tcl-eval-defun' or `tcl-load-file' -- have to choose a process to
-send to, when you have more than one Tcl process around. This is
-determined by the global variable `inferior-tcl-buffer'. Suppose you
-have three inferior Lisps running:
- Buffer Process
- foo inferior-tcl
- bar inferior-tcl<2>
- *inferior-tcl* inferior-tcl<3>
-If you do a \\[tcl-eval-defun] command on some Lisp source code, what
-process do you send it to?
-
-- If you're in a process buffer (foo, bar, or *inferior-tcl*),
- you send it to that process.
-- If you're in some other buffer (e.g., a source file), you
- send it to the process attached to buffer `inferior-tcl-buffer'.
-This process selection is performed by function `inferior-tcl-proc'.
-
-Whenever \\[inferior-tcl] fires up a new process, it resets
-`inferior-tcl-buffer' to be the new process's buffer. If you only run
-one process, this does the right thing. If you run multiple
-processes, you can change `inferior-tcl-buffer' to another process
-buffer with \\[set-variable].")
-
-;;
-;; Hooks and other customization.
-;;
-
-(defvar tcl-mode-hook nil
- "Hook run on entry to Tcl mode.
-
-Several functions exist which are useful to run from your
-`tcl-mode-hook' (see each function's documentation for more
-information):
-
- tcl-guess-application
- Guesses a default setting for `tcl-application' based on any
- \"#!\" line at the top of the file.
- tcl-hashify-buffer
- Quotes all \"#\" characters that don't correspond to actual
- Tcl comments. (Useful when editing code not originally created
- with this mode).
- tcl-auto-fill-mode
- Auto-filling of Tcl comments.
-
-Emacs 19 users can add functions to the hook with `add-hook':
-
- (add-hook 'tcl-mode-hook 'tcl-guess-application)
-
-Emacs 18 users must use `setq':
-
- (setq tcl-mode-hook (cons 'tcl-guess-application tcl-mode-hook))")
-
-
-(defvar inferior-tcl-mode-hook nil
- "Hook for customizing Inferior Tcl mode.")
-
-(defvar tcl-proc-list
- '("proc" "method" "itcl_class")
- "List of commands whose first argument defines something.
-This exists because some people (eg, me) use \"defvar\" et al.
-Call `tcl-set-proc-regexp' and `tcl-set-font-lock-keywords'
-after changing this list.")
-
-(defvar tcl-proc-regexp nil
- "Regexp to use when matching proc headers.")
-
-(defvar tcl-typeword-list
- '("global" "upvar" "inherit" "public" "protected" "common")
- "List of Tcl keywords denoting \"type\". Used only for highlighting.
-Call `tcl-set-font-lock-keywords' after changing this list.")
-
-;; Generally I've picked control operators to be keywords.
-(defvar tcl-keyword-list
- '("if" "then" "else" "elseif" "for" "foreach" "break" "continue" "while"
- "eval" "case" "in" "switch" "default" "exit" "error" "proc" "return"
- "uplevel" "constructor" "destructor" "itcl_class" "loop" "for_array_keys"
- "for_recursive_glob" "for_file")
- "List of Tcl keywords. Used only for highlighting.
-Default list includes some TclX keywords.
-Call `tcl-set-font-lock-keywords' after changing this list.")
-
-(defvar tcl-font-lock-keywords nil
- "Keywords to highlight for Tcl. See variable `font-lock-keywords'.
-This variable is generally set from `tcl-proc-regexp',
-`tcl-typeword-list', and `tcl-keyword-list' by the function
-`tcl-set-font-lock-keywords'.")
-
-;; FIXME need some way to recognize variables because array refs look
-;; like 2 sexps.
-(defvar tcl-type-alist
- '(
- ("proc" nil tcl-expr tcl-commands)
- ("method" nil tcl-expr tcl-commands)
- ("destructor" tcl-commands)
- ("constructor" tcl-commands)
- ("expr" tcl-expr)
- ("catch" tcl-commands)
- ("if" tcl-expr "then" tcl-commands)
- ("elseif" tcl-expr "then" tcl-commands)
- ("elseif" tcl-expr tcl-commands)
- ("if" tcl-expr tcl-commands)
- ("while" tcl-expr tcl-commands)
- ("for" tcl-commands tcl-expr tcl-commands tcl-commands)
- ("foreach" nil nil tcl-commands)
- ("for_file" nil nil tcl-commands)
- ("for_array_keys" nil nil tcl-commands)
- ("for_recursive_glob" nil nil nil tcl-commands)
- ;; Loop handling is not perfect, because the third argument can be
- ;; either a command or an expr, and there is no real way to look
- ;; forward.
- ("loop" nil tcl-expr tcl-expr tcl-commands)
- ("loop" nil tcl-expr tcl-commands)
- )
- "Alist that controls indentation.
-\(Actually, this really only controls what happens on continuation lines).
-Each entry looks like `(KEYWORD TYPE ...)'.
-Each type entry describes a sexp after the keyword, and can be one of:
-* nil, meaning that this sexp has no particular type.
-* tcl-expr, meaning that this sexp is an arithmetic expression.
-* tcl-commands, meaning that this sexp holds Tcl commands.
-* a string, which must exactly match the string at the corresponding
- position for a match to be made.
-
-For example, the entry for the \"loop\" command is:
-
- (\"loop\" nil tcl-expr tcl-commands)
-
-This means that the \"loop\" command has three arguments. The first
-argument is ignored (for indentation purposes). The second argument
-is a Tcl expression, and the last argument is Tcl commands.")
-
-(defvar tcl-explain-indentation nil
- "If not `nil', debugging message will be printed during indentation.")
-
-
-
-;;
-;; Work around differences between various versions of Emacs.
-;;
-
-;; We use this because Lemacs 19.9 has what we need.
-(defconst tcl-pps-has-arg-6
- (or tcl-using-emacs-19
- (and tcl-using-xemacs-19
- (condition-case nil
- (progn
- (parse-partial-sexp (point) (point) nil nil nil t)
- t)
- (error nil))))
- "t if using an emacs which supports sixth (\"commentstop\") argument
-to parse-partial-sexp.")
-
-;; Its pretty bogus to have to do this, but there is no easier way to
-;; say "match not syntax-1 and not syntax-2". Too bad you can't put
-;; \s in [...]. This sickness is used in Emacs 19 to match a defun
-;; starter. (It is used for this in v18 as well).
-;;(defconst tcl-omit-ws-regexp
-;; (concat "^\\(\\s"
-;; (mapconcat 'char-to-string "w_.()\"\\$'/" "\\|\\s")
-;; "\\)\\S(*")
-;; "Regular expression that matches everything except space, comment
-;;starter, and comment ender syntax codes.")
-
-;; FIXME? Instead of using the hairy regexp above, we just use a
-;; simple one.
-;;(defconst tcl-omit-ws-regexp "^[^] \t\n#}]\\S(*"
-;; "Regular expression used in locating function definitions.")
-
-;; Here's another stab. I think this one actually works. Now the
-;; problem seems to be that there is a bug in Emacs 19.22 where
-;; end-of-defun doesn't really use the brace matching the one that
-;; trails defun-prompt-regexp.
-(defconst tcl-omit-ws-regexp "^[^ \t\n#}][^\n}]+}*[ \t]+")
-
-(defun tcl-internal-beginning-of-defun (&optional arg)
- "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")
- (if (or (null arg) (= arg 0))
- (setq arg 1))
- (let (success)
- (while (progn
- (setq arg (1- arg))
- (and (>= arg 0)
- (setq success
- (re-search-backward tcl-omit-ws-regexp nil 'move 1))))
- (while (and (looking-at "[]#}]")
- (setq success
- (re-search-backward tcl-omit-ws-regexp nil 'move 1)))))
- (beginning-of-line)
- (not (null success))))
-
-(defun tcl-internal-end-of-defun (&optional arg)
- "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 ((start (point)))
- ;; Was forward-char. I think this works a little better.
- (forward-line)
- (tcl-beginning-of-defun)
- (while (> arg 0)
- (while (and (re-search-forward tcl-omit-ws-regexp nil 'move 1)
- (progn (beginning-of-line) t)
- (looking-at "[]#}]")
- (progn (forward-line) t)))
- (let ((next-line (save-excursion
- (forward-line)
- (point))))
- (while (< (point) next-line)
- (forward-sexp)))
- (forward-line)
- (if (> (point) start) (setq arg (1- arg))))))
-
-;; In Emacs 19, we can use begining-of-defun as long as we set up a
-;; certain regexp. In Emacs 18, we need our own function.
-(fset 'tcl-beginning-of-defun
- (if tcl-using-emacs-19
- 'beginning-of-defun
- 'tcl-internal-beginning-of-defun))
-
-;; Ditto end-of-defun.
-(fset 'tcl-end-of-defun
- (if (and tcl-using-emacs-19 (not tcl-using-xemacs-19))
- 'end-of-defun
- 'tcl-internal-end-of-defun))
-
-;; Internal mark-defun that is used for losing Emacsen.
-(defun tcl-internal-mark-defun ()
- "Put mark at end of Tcl function, point at beginning."
- (interactive)
- (push-mark (point))
- (tcl-end-of-defun)
- (if tcl-using-emacs-19
- (push-mark (point) nil t)
- (push-mark (point)))
- (tcl-beginning-of-defun)
- (backward-paragraph))
-
-;; In GNU Emacs 19-23 and later, mark-defun works as advertised. I
-;; don't know about XEmacs, so for now it and Emacs 18 just lose.
-(fset 'tcl-mark-defun
- (if tcl-using-emacs-19-23
- 'mark-defun
- 'tcl-internal-mark-defun))
-
-;; In GNU Emacs 19, mark takes an additional "force" argument. I
-;; don't know about XEmacs, so I'm just assuming it is the same.
-;; Emacs 18 doesn't have this argument.
-(defun tcl-mark ()
- "Return mark, or nil if none."
- (if tcl-using-emacs-19
- (mark t)
- (mark)))
-
-
-
-;;
-;; Some helper functions.
-;;
-
-(defun tcl-set-proc-regexp ()
- "Set `tcl-proc-regexp' from variable `tcl-proc-list'."
- (setq tcl-proc-regexp (concat "^\\s-*\\("
- (mapconcat 'identity tcl-proc-list "\\|")
- "\\)[ \t]+")))
-
-(defun tcl-set-font-lock-keywords ()
- "Set `tcl-font-lock-keywords'.
-Uses variables `tcl-proc-regexp' and `tcl-keyword-list'."
- (setq tcl-font-lock-keywords
- (list
- ;; Names of functions (and other "defining things").
- (list (concat tcl-proc-regexp "\\([^ \t\n]+\\)")
- 2 'font-lock-function-name-face)
-
- ;; Names of type-defining things.
- (list (concat "\\(\\s-\\|^\\)\\("
- ;; FIXME Use 'regexp-quote?
- (mapconcat 'identity tcl-typeword-list "\\|")
- "\\)\\(\\s-\\|$\\)")
- 2 'font-lock-type-face)
-
- ;; Keywords. Only recognized if surrounded by whitespace.
- ;; FIXME consider using "not word or symbol", not
- ;; "whitespace".
- (cons (concat "\\(\\s-\\|^\\)\\("
- ;; FIXME Use regexp-quote?
- (mapconcat 'identity tcl-keyword-list "\\|")
- "\\)\\(\\s-\\|$\\)")
- 2)
- )))
-
-(if tcl-proc-regexp
- ()
- (tcl-set-proc-regexp))
-
-(if tcl-font-lock-keywords
- ()
- (tcl-set-font-lock-keywords))
-
-
-
-;;
-;; The mode itself.
-;;
-
-;;;###autoload
-(defun tcl-mode ()
- "Major mode for editing Tcl code.
-Expression and list commands understand all Tcl brackets.
-Tab indents for Tcl code.
-Paragraphs are separated by blank lines only.
-Delete converts tabs to spaces as it moves back.
-
-Variables controlling indentation style:
- tcl-indent-level
- Indentation of Tcl statements within surrounding block.
- tcl-continued-indent-level
- Indentation of continuation line relative to first line of command.
-
-Variables controlling user interaction with mode (see variable
-documentation for details):
- tcl-tab-always-indent
- Controls action of TAB key.
- tcl-auto-newline
- Non-nil means automatically newline before and after braces, brackets,
- and semicolons inserted in Tcl code.
- tcl-electric-hash-style
- Controls action of `#' key.
- tcl-use-hairy-comment-detector
- If t, use more complicated, but slower, comment detector.
- This variable is only used in GNU Emacs 19.
- tcl-use-smart-word-finder
- If not nil, use a smarter, Tcl-specific way to find the current
- word when looking up help on a Tcl command.
-
-Turning on Tcl mode calls the value of the variable `tcl-mode-hook'
-with no args, if that value is non-nil. Read the documentation for
-`tcl-mode-hook' to see what kinds of interesting hook functions
-already exist.
-
-Commands:
-\\{tcl-mode-map}"
- (interactive)
- (kill-all-local-variables)
- (use-local-map tcl-mode-map)
- (setq major-mode 'tcl-mode)
- (setq mode-name "Tcl")
- (setq local-abbrev-table tcl-mode-abbrev-table)
- (set-syntax-table tcl-mode-syntax-table)
-
- (make-local-variable 'paragraph-start)
- (make-local-variable 'paragraph-separate)
- (if (and tcl-using-emacs-19-23
- (>= emacs-minor-version 29))
- (progn
- ;; In Emacs 19.29, you aren't supposed to start these with a
- ;; ^.
- (setq paragraph-start "$\\| ")
- (setq paragraph-separate paragraph-start))
- (setq paragraph-start (concat "^$\\|" page-delimiter))
- (setq paragraph-separate paragraph-start))
- (make-local-variable 'paragraph-ignore-fill-prefix)
- (setq paragraph-ignore-fill-prefix t)
- (make-local-variable 'fill-paragraph-function)
- (setq fill-paragraph-function 'tcl-do-fill-paragraph)
-
- (make-local-variable 'indent-line-function)
- (setq indent-line-function 'tcl-indent-line)
- ;; Tcl doesn't require a final newline.
- ;; (make-local-variable 'require-final-newline)
- ;; (setq require-final-newline t)
-
- (make-local-variable 'comment-start)
- (setq comment-start "# ")
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip "#+ *")
- (make-local-variable 'comment-column)
- (setq comment-column 40)
- (make-local-variable 'comment-end)
- (setq comment-end "")
-
- (make-local-variable 'outline-regexp)
- (setq outline-regexp "[^\n\^M]")
- (make-local-variable 'outline-level)
- (setq outline-level 'tcl-outline-level)
-
- (make-local-variable 'font-lock-keywords)
- (setq font-lock-keywords tcl-font-lock-keywords)
-
- ;; The following only really makes sense under GNU Emacs 19.
- (make-local-variable 'imenu-create-index-function)
- (setq imenu-create-index-function 'tcl-imenu-create-index-function)
- (make-local-variable 'parse-sexp-ignore-comments)
-
- ;; Settings for new dabbrev code.
- (make-local-variable 'dabbrev-case-fold-search)
- (setq dabbrev-case-fold-search nil)
- (make-local-variable 'dabbrev-case-replace)
- (setq dabbrev-case-replace nil)
- (make-local-variable 'dabbrev-abbrev-skip-leading-regexp)
- (setq dabbrev-abbrev-skip-leading-regexp "[$!]")
- (make-local-variable 'dabbrev-abbrev-char-regexp)
- (setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_")
-
- (if tcl-using-emacs-19
- (progn
- ;; This can only be set to t in Emacs 19 and XEmacs.
- ;; Emacs 18 and Epoch lose.
- (setq parse-sexp-ignore-comments t)
- ;; XEmacs has defun-prompt-regexp, but I don't believe
- ;; that it works for end-of-defun -- only for
- ;; beginning-of-defun.
- (make-local-variable 'defun-prompt-regexp)
- (setq defun-prompt-regexp tcl-omit-ws-regexp)
- ;; The following doesn't work in Lucid Emacs 19.6, but maybe
- ;; it will appear in later versions.
- (make-local-variable 'add-log-current-defun-function)
- (setq add-log-current-defun-function 'add-log-tcl-defun))
- (setq parse-sexp-ignore-comments nil))
-
- ;; Put Tcl menu into menubar for XEmacs. This happens
- ;; automatically for GNU Emacs.
- (if (and tcl-using-xemacs-19
- current-menubar
- (not (assoc "Tcl" current-menubar)))
- (progn
- (set-buffer-menubar (copy-sequence current-menubar))
- (add-menu nil "Tcl" tcl-xemacs-menu)))
- ;; Append Tcl menu to popup menu for XEmacs.
- (if (and tcl-using-xemacs-19 (boundp 'mode-popup-menu))
- (setq mode-popup-menu
- (cons (concat mode-name " Mode Commands") tcl-xemacs-menu)))
-
- ;; If hilit19 is loaded, add our stuff.
- (if (featurep 'hilit19)
- (tcl-hilit))
-
- (run-hooks 'tcl-mode-hook))
-
-
-
-;; This is used for braces, brackets, and semi (except for closing
-;; braces, which are handled specially).
-(defun tcl-electric-char (arg)
- "Insert character and correct line's indentation."
- (interactive "p")
- ;; Indent line first; this looks better if parens blink.
- (tcl-indent-line)
- (self-insert-command arg)
- (if (and tcl-auto-newline (= last-command-char ?\;))
- (progn
- (newline)
- (tcl-indent-line))))
-
-;; This is used for closing braces. If tcl-auto-newline is set, can
-;; insert a newline both before and after the brace, depending on
-;; context. FIXME should this be configurable? Does anyone use this?
-(defun tcl-electric-brace (arg)
- "Insert character and correct line's indentation."
- (interactive "p")
- ;; If auto-newlining and there is stuff on the same line, insert a
- ;; newline first.
- (if tcl-auto-newline
- (progn
- (if (save-excursion
- (skip-chars-backward " \t")
- (bolp))
- ()
- (tcl-indent-line)
- (newline))
- ;; In auto-newline case, must insert a newline after each
- ;; brace. So an explicit loop is needed.
- (while (> arg 0)
- (insert last-command-char)
- (tcl-indent-line)
- (newline)
- (setq arg (1- arg))))
- (self-insert-command arg))
- (tcl-indent-line))
-
-
-
-(defun tcl-indent-command (&optional arg)
- "Indent current line as Tcl code, or in some cases insert a tab character.
-If tcl-tab-always-indent is t (the default), always indent current line.
-If tcl-tab-always-indent is nil and point is not in the indentation
-area at the beginning of the line, a TAB is inserted.
-Other values of tcl-tab-always-indent cause the first possible action
-from the following list to take place:
-
- 1. Move from beginning of line to correct indentation.
- 2. Delete an empty comment.
- 3. Move forward to start of comment, indenting if necessary.
- 4. Move forward to end of line, indenting if necessary.
- 5. Create an empty comment.
- 6. Move backward to start of comment, indenting if necessary."
- (interactive "p")
- (cond
- ((not tcl-tab-always-indent)
- ;; Indent if in indentation area, otherwise insert TAB.
- (if (<= (current-column) (current-indentation))
- (tcl-indent-line)
- (insert-tab arg)))
- ((eq tcl-tab-always-indent t)
- ;; Always indent.
- (tcl-indent-line))
- (t
- ;; "Perl-mode" style TAB command.
- (let* ((ipoint (point))
- (eolpoint (progn
- (end-of-line)
- (point)))
- (comment-p (tcl-in-comment)))
- (cond
- ((= ipoint (save-excursion
- (beginning-of-line)
- (point)))
- (beginning-of-line)
- (tcl-indent-line)
- ;; If indenting didn't leave us in column 0, go to the
- ;; indentation. Otherwise leave point at end of line. This
- ;; is a hack.
- (if (= (point) (save-excursion
- (beginning-of-line)
- (point)))
- (end-of-line)
- (back-to-indentation)))
- ((and comment-p (looking-at "[ \t]*$"))
- ;; Empty comment, so delete it. We also delete any ";"
- ;; characters at the end of the line. I think this is
- ;; friendlier, but I don't know how other people will feel.
- (backward-char)
- (skip-chars-backward " \t;")
- (delete-region (point) eolpoint))
- ((and comment-p (< ipoint (point)))
- ;; Before comment, so skip to it.
- (tcl-indent-line)
- (indent-for-comment))
- ((/= ipoint eolpoint)
- ;; Go to end of line (since we're not there yet).
- (goto-char eolpoint)
- (tcl-indent-line))
- ((not comment-p)
- (tcl-indent-line)
- (tcl-indent-for-comment))
- (t
- ;; Go to start of comment. We don't leave point where it is
- ;; because we want to skip comment-start-skip.
- (tcl-indent-line)
- (indent-for-comment)))))))
-
-(defun tcl-indent-line ()
- "Indent current line as Tcl code.
-Return the amount the indentation changed by."
- (let ((indent (calculate-tcl-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)))
- (t
- (skip-chars-forward " \t")
- (if (listp indent) (setq indent (car indent)))
- (cond ((= (following-char) ?})
- (setq indent (- indent tcl-indent-level)))
- ((= (following-char) ?\])
- (setq indent (- indent 1))))))
- (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 tcl-figure-type ()
- "Determine type of sexp at point.
-This is either 'tcl-expr, 'tcl-commands, or nil. Puts point at start
-of sexp that indicates types.
-
-See documentation for variable `tcl-type-alist' for more information."
- (let ((count 0)
- result
- word-stack)
- (while (and (< count 5)
- (not result))
- (condition-case nil
- (progn
- ;; FIXME should use "tcl-backward-sexp", which would skip
- ;; over entire variables, etc.
- (backward-sexp)
- (if (looking-at "[a-zA-Z_]+")
- (let ((list tcl-type-alist)
- entry)
- (setq word-stack (cons (tcl-word-no-props) word-stack))
- (while (and list (not result))
- (setq entry (car list))
- (setq list (cdr list))
- (let ((index 0))
- (while (and entry (<= index count))
- ;; Abort loop if string does not match word on
- ;; stack.
- (and (stringp (car entry))
- (not (string= (car entry)
- (nth index word-stack)))
- (setq entry nil))
- (setq entry (cdr entry))
- (setq index (1+ index)))
- (and (> index count)
- (not (stringp (car entry)))
- (setq result (car entry)))
- )))
- (setq word-stack (cons nil word-stack))))
- (error nil))
- (setq count (1+ count)))
- (and tcl-explain-indentation
- (message "Indentation type %s" result))
- result))
-
-(defun calculate-tcl-indent (&optional parse-start)
- "Return appropriate indentation for current line as Tcl 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)
- (continued-line
- (save-excursion
- (if (bobp)
- nil
- (backward-char)
- (= ?\\ (preceding-char)))))
- (continued-indent-value (if continued-line
- tcl-continued-indent-level
- 0))
- state
- containing-sexp
- found-next-line)
- (if parse-start
- (goto-char parse-start)
- (tcl-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))
- ;; Inside comment or string. Return nil or t if should
- ;; not change this line
- (nth 4 state))
- ((null containing-sexp)
- ;; Line is at top level.
- continued-indent-value)
- (t
- ;; Set expr-p if we are looking at the expression part of
- ;; an "if", "expr", etc statement. Set commands-p if we
- ;; are looking at the body part of an if, while, etc
- ;; statement. FIXME Should check for "for" loops here.
- (goto-char containing-sexp)
- (let* ((sexpr-type (tcl-figure-type))
- (expr-p (eq sexpr-type 'tcl-expr))
- (commands-p (eq sexpr-type 'tcl-commands))
- (expr-start (point)))
- ;; Find the first statement in the block and indent
- ;; like it. The first statement in the block might be
- ;; on the same line, so what we do is skip all
- ;; "virtually blank" lines, looking for a non-blank
- ;; one. A line is virtually blank if it only contains
- ;; a comment and whitespace. FIXME continued comments
- ;; aren't supported. They are a wart on Tcl anyway.
- ;; We do it this funky way because we want to know if
- ;; we've found a statement on some line _after_ the
- ;; line holding the sexp opener.
- (goto-char containing-sexp)
- (forward-char)
- (if (and (< (point) indent-point)
- (looking-at "[ \t]*\\(#.*\\)?$"))
- (progn
- (forward-line)
- (while (and (< (point) indent-point)
- (looking-at "[ \t]*\\(#.*\\)?$"))
- (setq found-next-line t)
- (forward-line))))
- (if (or continued-line
- (/= (char-after containing-sexp) ?{)
- expr-p)
- (progn
- ;; Line is continuation line, or the sexp opener
- ;; is not a curly brace, or we are are looking at
- ;; an `expr' expression (which must be split
- ;; specially). So indentation is column of first
- ;; good spot after sexp opener (with some added
- ;; in the continued-line case). If there is no
- ;; nonempty line before the indentation point, we
- ;; use the column of the character after the sexp
- ;; opener.
- (if (>= (point) indent-point)
- (progn
- (goto-char containing-sexp)
- (forward-char))
- (skip-chars-forward " \t"))
- (+ (current-column) continued-indent-value))
- ;; After a curly brace, and not a continuation line.
- ;; So take indentation from first good line after
- ;; start of block, unless that line is on the same
- ;; line as the opening brace. In this case use the
- ;; indentation of the opening brace's line, plus
- ;; another indent step. If we are in the body part
- ;; of an "if" or "while" then the indentation is
- ;; taken from the line holding the start of the
- ;; statement.
- (if (and (< (point) indent-point)
- found-next-line)
- (current-indentation)
- (if commands-p
- (goto-char expr-start)
- (goto-char containing-sexp))
- (+ (current-indentation) tcl-indent-level)))))))))
-
-
-
-(defun indent-tcl-exp ()
- "Indent each line of the Tcl grouping following point."
- (interactive)
- (let ((indent-stack (list nil))
- (contain-stack (list (point)))
- (case-fold-search nil)
- outer-loop-done inner-loop-done state ostate
- this-indent last-sexp continued-line
- (next-depth 0)
- last-depth)
- (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))
- (tcl-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)
- (setq continued-line
- (save-excursion
- (backward-char)
- (= (preceding-char) ?\\)))
- (skip-chars-forward " \t")
- (if (eolp)
- nil
- (if (and (car indent-stack)
- (>= (car indent-stack) 0))
- ;; Line is on an existing nesting level.
- (setq this-indent (car indent-stack))
- ;; Just started a new nesting level.
- ;; Compute the standard indent for this level.
- (let ((val (calculate-tcl-indent
- (if (car indent-stack)
- (- (car indent-stack))))))
- (setcar indent-stack
- (setq this-indent val))
- (setq continued-line nil)))
- (cond ((not (numberp this-indent)))
- ((= (following-char) ?})
- (setq this-indent (- this-indent tcl-indent-level)))
- ((= (following-char) ?\])
- (setq this-indent (- this-indent 1))))
- ;; Put chosen indentation into effect.
- (or (null this-indent)
- (= (current-column)
- (if continued-line
- (+ this-indent tcl-indent-level)
- this-indent))
- (progn
- (delete-region (point) (progn (beginning-of-line) (point)))
- (indent-to
- (if continued-line
- (+ this-indent tcl-indent-level)
- this-indent)))))))))
- )
-
-
-
-;;
-;; Interfaces to other packages.
-;;
-
-(defun tcl-imenu-create-index-function ()
- "Generate alist of indices for imenu."
- (let ((re (concat tcl-proc-regexp "\\([^ \t\n{]+\\)"))
- alist prev-pos)
- (goto-char (point-min))
- (imenu-progress-message prev-pos 0)
- (save-match-data
- (while (re-search-forward re nil t)
- (imenu-progress-message prev-pos)
- ;; Position on start of proc name, not beginning of line.
- (setq alist (cons
- (cons (buffer-substring (match-beginning 2) (match-end 2))
- (match-beginning 2))
- alist))))
- (imenu-progress-message prev-pos 100)
- (nreverse alist)))
-
-;; FIXME Definition of function is very ad-hoc. Should use
-;; tcl-beginning-of-defun. Also has incestuous knowledge about the
-;; format of tcl-proc-regexp.
-(defun add-log-tcl-defun ()
- "Return name of Tcl function point is in, or nil."
- (save-excursion
- (end-of-line)
- (if (re-search-backward (concat tcl-proc-regexp "\\([^ \t\n{]+\\)") nil t)
- (buffer-substring (match-beginning 2)
- (match-end 2)))))
-
-(defun tcl-outline-level ()
- (save-excursion
- (skip-chars-forward " \t")
- (current-column)))
-
-
-
-;;
-;; Helper functions for inferior Tcl mode.
-;;
-
-;; This exists to let us delete the prompt when commands are sent
-;; directly to the inferior Tcl. See gud.el for an explanation of how
-;; it all works (I took it from there). This stuff doesn't really
-;; work as well as I'd like it to. But I don't believe there is
-;; anything useful that can be done.
-(defvar inferior-tcl-delete-prompt-marker nil)
-
-(defun tcl-filter (proc string)
- (let ((inhibit-quit t))
- (save-excursion
- (set-buffer (process-buffer proc))
- (goto-char (process-mark proc))
- ;; Delete prompt if requested.
- (if (marker-buffer inferior-tcl-delete-prompt-marker)
- (progn
- (delete-region (point) inferior-tcl-delete-prompt-marker)
- (set-marker inferior-tcl-delete-prompt-marker nil)))))
- (if tcl-using-emacs-19
- (comint-output-filter proc string)
- (funcall comint-output-filter string)))
-
-(defun tcl-send-string (proc string)
- (save-excursion
- (set-buffer (process-buffer proc))
- (goto-char (process-mark proc))
- (beginning-of-line)
- (if (looking-at comint-prompt-regexp)
- (set-marker inferior-tcl-delete-prompt-marker (point))))
- (comint-send-string proc string))
-
-(defun tcl-send-region (proc start end)
- (save-excursion
- (set-buffer (process-buffer proc))
- (goto-char (process-mark proc))
- (beginning-of-line)
- (if (looking-at comint-prompt-regexp)
- (set-marker inferior-tcl-delete-prompt-marker (point))))
- (comint-send-region proc start end))
-
-(defun switch-to-tcl (eob-p)
- "Switch to inferior Tcl process buffer.
-With argument, positions cursor at end of buffer."
- (interactive "P")
- (if (get-buffer inferior-tcl-buffer)
- (pop-to-buffer inferior-tcl-buffer)
- (error "No current inferior Tcl buffer"))
- (cond (eob-p
- (push-mark)
- (goto-char (point-max)))))
-
-(defun inferior-tcl-proc ()
- "Return current inferior Tcl process.
-See variable `inferior-tcl-buffer'."
- (let ((proc (get-buffer-process (if (eq major-mode 'inferior-tcl-mode)
- (current-buffer)
- inferior-tcl-buffer))))
- (or proc
- (error "No Tcl process; see variable `inferior-tcl-buffer'"))))
-
-(defun tcl-eval-region (start end &optional and-go)
- "Send the current region to the inferior Tcl process.
-Prefix argument means switch to the Tcl buffer afterwards."
- (interactive "r\nP")
- (let ((proc (inferior-tcl-proc)))
- (tcl-send-region proc start end)
- (tcl-send-string proc "\n")
- (if and-go (switch-to-tcl t))))
-
-(defun tcl-eval-defun (&optional and-go)
- "Send the current defun to the inferior Tcl process.
-Prefix argument means switch to the Tcl buffer afterwards."
- (interactive "P")
- (save-excursion
- (tcl-end-of-defun)
- (let ((end (point)))
- (tcl-beginning-of-defun)
- (tcl-eval-region (point) end)))
- (if and-go (switch-to-tcl t)))
-
-
-
-;;
-;; Inferior Tcl mode itself.
-;;
-
-(defun inferior-tcl-mode ()
- "Major mode for interacting with Tcl interpreter.
-
-A Tcl process can be started with M-x inferior-tcl.
-
-Entry to this mode runs the hooks comint-mode-hook and
-inferior-tcl-mode-hook, in that order.
-
-You can send text to the inferior Tcl process from other buffers
-containing Tcl source.
-
-Variables controlling Inferior Tcl mode:
- tcl-application
- Name of program to run.
- tcl-command-switches
- Command line arguments to `tcl-application'.
- tcl-prompt-regexp
- Matches prompt.
- inferior-tcl-source-command
- Command to use to read Tcl file in running application.
- inferior-tcl-buffer
- The current inferior Tcl process buffer. See variable
- documentation for details on multiple-process support.
-
-The following commands are available:
-\\{inferior-tcl-mode-map}"
- (interactive)
- (comint-mode)
- (setq comint-prompt-regexp (or tcl-prompt-regexp
- (concat "^"
- (regexp-quote tcl-application)
- ">")))
- (setq major-mode 'inferior-tcl-mode)
- (setq mode-name "Inferior Tcl")
- (if (boundp 'modeline-process)
- (setq modeline-process '(": %s")) ; For XEmacs.
- (setq mode-line-process '(": %s")))
- (use-local-map inferior-tcl-mode-map)
- (setq local-abbrev-table tcl-mode-abbrev-table)
- (set-syntax-table tcl-mode-syntax-table)
- (if tcl-using-emacs-19
- (progn
- (make-local-variable 'defun-prompt-regexp)
- (setq defun-prompt-regexp tcl-omit-ws-regexp)))
- (make-local-variable 'inferior-tcl-delete-prompt-marker)
- (setq inferior-tcl-delete-prompt-marker (make-marker))
- (set-process-filter (get-buffer-process (current-buffer)) 'tcl-filter)
- (run-hooks 'inferior-tcl-mode-hook))
-
-;;;###autoload
-(defun inferior-tcl (cmd)
- "Run inferior Tcl process.
-Prefix arg means enter program name interactively.
-See documentation for function `inferior-tcl-mode' for more information."
- (interactive
- (list (if current-prefix-arg
- (read-string "Run Tcl: " tcl-application)
- tcl-application)))
- (if (not (comint-check-proc "*inferior-tcl*"))
- (progn
- (set-buffer (apply (function make-comint) "inferior-tcl" cmd nil
- tcl-command-switches))
- (inferior-tcl-mode)))
- (make-local-variable 'tcl-application)
- (setq tcl-application cmd)
- (setq inferior-tcl-buffer "*inferior-tcl*")
- (switch-to-buffer "*inferior-tcl*"))
-
-(and (fboundp 'defalias)
- (defalias 'run-tcl 'inferior-tcl))
-
-
-
-;;
-;; Auto-fill support.
-;;
-
-(defun tcl-real-command-p ()
- "Return nil if point is not at the beginning of a command.
-A command is the first word on an otherwise empty line, or the
-first word following a semicolon, opening brace, or opening bracket."
- (save-excursion
- (skip-chars-backward " \t")
- (cond
- ((bobp) t)
- ((bolp)
- (backward-char)
- ;; Note -- continued comments are not supported here. I
- ;; consider those to be a wart on the language.
- (not (eq ?\\ (preceding-char))))
- (t
- (memq (preceding-char) '(?\; ?{ ?\[))))))
-
-;; FIXME doesn't actually return t. See last case.
-(defun tcl-real-comment-p ()
- "Return t if point is just after the `#' beginning a real comment.
-Does not check to see if previous char is actually `#'.
-A real comment is either at the beginning of the buffer,
-preceeded only by whitespace on the line, or has a preceeding
-semicolon, opening brace, or opening bracket on the same line."
- (save-excursion
- (backward-char)
- (tcl-real-command-p)))
-
-(defun tcl-hairy-scan-for-comment (state end always-stop)
- "Determine if point is in a comment.
-Returns a list of the form `(FLAG . STATE)'. STATE can be used
-as input to future invocations. FLAG is nil if not in comment,
-t otherwise. If in comment, leaves point at beginning of comment.
-Only works in Emacs 19. See also `tcl-simple-scan-for-comment', a
-simpler version that is often right, and works in Emacs 18."
- (let ((bol (save-excursion
- (goto-char end)
- (beginning-of-line)
- (point)))
- real-comment
- last-cstart)
- (while (and (not last-cstart) (< (point) end))
- (setq real-comment nil) ;In case we've looped around and it is
- ;set.
- (setq state (parse-partial-sexp (point) end nil nil state t))
- (if (nth 4 state)
- (progn
- ;; If ALWAYS-STOP is set, stop even if we don't have a
- ;; real comment, or if the comment isn't on the same line
- ;; as the end.
- (if always-stop (setq last-cstart (point)))
- ;; If we have a real comment, then set the comment
- ;; starting point if we are on the same line as the ending
- ;; location.
- (setq real-comment (tcl-real-comment-p))
- (if real-comment
- (progn
- (and (> (point) bol) (setq last-cstart (point)))
- ;; NOTE Emacs 19 has a misfeature whereby calling
- ;; parse-partial-sexp with COMMENTSTOP set and with
- ;; an initial list that says point is in a comment
- ;; will cause an immediate return. So we must skip
- ;; over the comment ourselves.
- (beginning-of-line 2)))
- ;; Frob the state to make it look like we aren't in a
- ;; comment.
- (setcar (nthcdr 4 state) nil))))
- (and last-cstart
- (goto-char last-cstart))
- (cons real-comment state)))
-
-(defun tcl-hairy-in-comment ()
- "Return t if point is in a comment, and leave point at beginning
-of comment."
- (let ((save (point)))
- (tcl-beginning-of-defun)
- (car (tcl-hairy-scan-for-comment nil save nil))))
-
-(defun tcl-simple-in-comment ()
- "Return t if point is in comment, and leave point at beginning
-of comment. This is faster that `tcl-hairy-in-comment', but is
-correct less often."
- (let ((save (point))
- comment)
- (beginning-of-line)
- (while (and (< (point) save) (not comment))
- (search-forward "#" save 'move)
- (setq comment (tcl-real-comment-p)))
- comment))
-
-(defun tcl-in-comment ()
- "Return t if point is in comment, and leave point at beginning
-of comment."
- (if (and tcl-pps-has-arg-6
- tcl-use-hairy-comment-detector)
- (tcl-hairy-in-comment)
- (tcl-simple-in-comment)))
-
-(defun tcl-do-fill-paragraph (ignore)
- "fill-paragraph function for Tcl mode. Only fills in a comment."
- (let (in-comment col where)
- (save-excursion
- (end-of-line)
- (setq in-comment (tcl-in-comment))
- (if in-comment
- (progn
- (setq where (1+ (point)))
- (setq col (1- (current-column))))))
- (and in-comment
- (save-excursion
- (back-to-indentation)
- (= col (current-column)))
- ;; In a comment. Set the fill prefix, and find the paragraph
- ;; boundaries by searching for lines that look like
- ;; comment-only lines.
- (let ((fill-prefix (buffer-substring (progn
- (beginning-of-line)
- (point))
- where))
- p-start p-end)
- ;; Search backwards.
- (save-excursion
- (while (looking-at "^[ \t]*#")
- (forward-line -1))
- (forward-line)
- (setq p-start (point)))
-
- ;; Search forwards.
- (save-excursion
- (while (looking-at "^[ \t]*#")
- (forward-line))
- (setq p-end (point)))
-
- ;; Narrow and do the fill.
- (save-restriction
- (narrow-to-region p-start p-end)
- (fill-paragraph ignore)))))
- t)
-
-(defun tcl-do-auto-fill ()
- "Auto-fill function for Tcl mode. Only auto-fills in a comment."
- (if (> (current-column) fill-column)
- (let ((fill-prefix "# ")
- in-comment col)
- (save-excursion
- (setq in-comment (tcl-in-comment))
- (if in-comment
- (setq col (1- (current-column)))))
- (if in-comment
- (progn
- (do-auto-fill)
- (save-excursion
- (back-to-indentation)
- (delete-region (point) (save-excursion
- (beginning-of-line)
- (point)))
- (indent-to-column col)))))))
-
-
-
-;;
-;; Help-related code.
-;;
-
-(defvar tcl-help-saved-dirs nil
- "Saved help directories.
-If `tcl-help-directory-list' changes, this allows `tcl-help-on-word'
-to update the alist.")
-
-(defvar tcl-help-alist nil
- "Alist with command names as keys and filenames as values.")
-
-(defun tcl-help-snarf-commands (dirlist)
- "Build alist of commands and filenames."
- (while dirlist
- (let ((files (directory-files (car dirlist) t)))
- (while files
- (if (and (file-directory-p (car files))
- (not
- (let ((fpart (file-name-nondirectory (car files))))
- (or (equal fpart ".")
- (equal fpart "..")))))
- (let ((matches (directory-files (car files) t)))
- (while matches
- (or (file-directory-p (car matches))
- (setq tcl-help-alist
- (cons
- (cons (file-name-nondirectory (car matches))
- (car matches))
- tcl-help-alist)))
- (setq matches (cdr matches)))))
- (setq files (cdr files))))
- (setq dirlist (cdr dirlist))))
-
-(defun tcl-reread-help-files ()
- "Set up to re-read files, and then do it."
- (interactive)
- (message "Building Tcl help file index...")
- (setq tcl-help-saved-dirs tcl-help-directory-list)
- (setq tcl-help-alist nil)
- (tcl-help-snarf-commands tcl-help-directory-list)
- (message "Building Tcl help file index...done"))
-
-(defun tcl-word-no-props ()
- "Like current-word, but strips properties."
- (let ((word (current-word)))
- (and (fboundp 'set-text-properties)
- (set-text-properties 0 (length word) nil word))
- word))
-
-(defun tcl-current-word (flag)
- "Return current command word, or nil.
-If FLAG is nil, just uses `current-word'.
-Otherwise scans backward for most likely Tcl command word."
- (if (and flag
- (memq major-mode '(tcl-mode inferior-tcl-mode)))
- (condition-case nil
- (save-excursion
- ;; Look backward for first word actually in alist.
- (if (bobp)
- ()
- (while (and (not (bobp))
- (not (tcl-real-command-p)))
- (backward-sexp)))
- (if (assoc (tcl-word-no-props) tcl-help-alist)
- (tcl-word-no-props)))
- (error nil))
- (tcl-word-no-props)))
-
-;;;###autoload
-(defun tcl-help-on-word (command &optional arg)
- "Get help on Tcl command. Default is word at point.
-Prefix argument means invert sense of `tcl-use-smart-word-finder'."
- (interactive
- (list
- (progn
- (if (not (equal tcl-help-directory-list tcl-help-saved-dirs))
- (tcl-reread-help-files))
- (let ((word (tcl-current-word
- (if current-prefix-arg
- (not tcl-use-smart-word-finder)
- tcl-use-smart-word-finder))))
- (completing-read
- (if (or (null word) (string= word ""))
- "Help on Tcl command: "
- (format "Help on Tcl command (default %s): " word))
- tcl-help-alist nil t)))
- current-prefix-arg))
- (if (not (equal tcl-help-directory-list tcl-help-saved-dirs))
- (tcl-reread-help-files))
- (if (string= command "")
- (setq command (tcl-current-word
- (if arg
- (not tcl-use-smart-word-finder)
- tcl-use-smart-word-finder))))
- (let* ((help (get-buffer-create "*Tcl help*"))
- (cell (assoc command tcl-help-alist))
- (file (and cell (cdr cell))))
- (set-buffer help)
- (delete-region (point-min) (point-max))
- (if file
- (progn
- (insert "*** " command "\n\n")
- (insert-file-contents file))
- (if (string= command "")
- (insert "Magical Pig!")
- (insert "Tcl command " command " not in help\n")))
- (set-buffer-modified-p nil)
- (goto-char (point-min))
- (display-buffer help)))
-
-
-
-;;
-;; Other interactive stuff.
-;;
-
-(defvar tcl-previous-dir/file nil
- "Record last directory and file used in loading.
-This holds a cons cell of the form `(DIRECTORY . FILE)'
-describing the last `tcl-load-file' command.")
-
-(defun tcl-load-file (file &optional and-go)
- "Load a Tcl file into the inferior Tcl process.
-Prefix argument means switch to the Tcl buffer afterwards."
- (interactive
- (list
- ;; car because comint-get-source returns a list holding the
- ;; filename.
- (car (comint-get-source "Load Tcl file: "
- (or (and
- (eq major-mode 'tcl-mode)
- (buffer-file-name))
- tcl-previous-dir/file)
- '(tcl-mode) t))
- current-prefix-arg))
- (comint-check-source file)
- (setq tcl-previous-dir/file (cons (file-name-directory file)
- (file-name-nondirectory file)))
- (tcl-send-string (inferior-tcl-proc)
- (format inferior-tcl-source-command (tcl-quote file)))
- (if and-go (switch-to-tcl t)))
-
-(defun tcl-restart-with-file (file &optional and-go)
- "Restart inferior Tcl with file.
-If an inferior Tcl process exists, it is killed first.
-Prefix argument means switch to the Tcl buffer afterwards."
- (interactive
- (list
- (car (comint-get-source "Restart with Tcl file: "
- (or (and
- (eq major-mode 'tcl-mode)
- (buffer-file-name))
- tcl-previous-dir/file)
- '(tcl-mode) t))
- current-prefix-arg))
- (let* ((buf (if (eq major-mode 'inferior-tcl-mode)
- (current-buffer)
- inferior-tcl-buffer))
- (proc (and buf (get-process buf))))
- (cond
- ((not (and buf (get-buffer buf)))
- ;; I think this will be ok.
- (inferior-tcl tcl-application)
- (tcl-load-file file and-go))
- ((or
- (not (comint-check-proc buf))
- (yes-or-no-p
- "A Tcl process is running, are you sure you want to reset it? "))
- (save-excursion
- (comint-check-source file)
- (setq tcl-previous-dir/file (cons (file-name-directory file)
- (file-name-nondirectory file)))
- (comint-exec (get-buffer-create buf)
- (if proc
- (process-name proc)
- "inferior-tcl")
- tcl-application file tcl-command-switches)
- (if and-go (switch-to-tcl t)))))))
-
-;; FIXME I imagine you can do this under Emacs 18. I just don't know
-;; how.
-(defun tcl-auto-fill-mode (&optional arg)
- "Like `auto-fill-mode', but controls filling of Tcl comments."
- (interactive "P")
- (and (not tcl-using-emacs-19)
- (error "You must use Emacs 19 to get this feature."))
- ;; Following code taken from "auto-fill-mode" (simple.el).
- (prog1
- (setq auto-fill-function
- (if (if (null arg)
- (not auto-fill-function)
- (> (prefix-numeric-value arg) 0))
- 'tcl-do-auto-fill
- nil))
- (force-mode-line-update)))
-
-;; hilit19 support from "Chris Alfeld" <calfeld@math.utah.edu>
-(defun tcl-hilit ()
- (hilit-set-mode-patterns
- '(tcl-mode)
- '(
- ("\\(^ *\\|\; *\\)#.*$" nil comment)
- ("[^\\]\\(\\$[A-Za-z0-9\\-\\_./\\(\\)]+\\)" 1 label)
- ("[^_]\\<\\(append\\|array\\|auto_execok\\|auto_load\\|auto_mkindex\\|auto_reset\\|break\\|case\\|catch\\|cd\\|close\\|concat\\|continue\\|eof\\|error\\|eval\\|exec\\|exit\\|expr\\|file\\|flush\\|for\\|foreach\\|format\\|gets\\|glob\\|global\\|history\\|if\\|incr\\|info\\|join\\|lappend\\|lindex\\|linsert\\|list\\|llength\\|lrange\\|lreplace\\|lsearch\\|lsort\\|open\\|pid\\|proc\\|puts\\|pwd\\|read\\|regexp\\|regsub\\|rename\\|return\\|scan\\|seek\\|set\\|source\\|split\\|string\\|switch\\|tell\\|time\\|trace\\|unknown\\|unset\\|uplevel\\|upvar\\|while\\)\\>[^_]" 1 keyword) ; tcl keywords
- ("[^_]\\<\\(after\\|bell\\|bind\\|bindtags\\|clipboard\\|destroy\\|fileevent\\|focus\\|grab\\|image\\|lower\\|option\\|pack\\|place\\|raise\\|scale\\|selection\\|send\\|subst\\|tk\\|tk_popup\\|tkwait\\|update\\|winfo\\|wm\\)\\>[^_]" 1 define) ; tk keywords
- ("[^_]\\<\\(button\\|canvas\\|checkbutton\\|entry\\|frame\\|label\\|listbox\\|menu\\|menubutton\\|message\\|radiobutton\\|scrollbar\\|text\\|toplevel\\)\\>[^_]" 1 decl) ; tk widgets
- ("[^_]\\<\\(tix\\((ButtonBox\\|Baloon\\|Control\\|DirList\\|ExFileSelectBox\\|ExFileSelectDialog\\|FileEntry\\|HList\\|LabelEntry\\|LabelFrame\\|NoteBook\\|OptionMenu\\|PanedWindow\\|PopupMenu\\|ScrolledHList\\|ScrolledText\\|ScrolledWindow\\|Select\\|StdButtonBox\\)\\)\\>[^_]" 1 defun) ; tix widgets
- ("[{}\\\"\\(\\)]" nil include) ; misc punctuation
- )))
-
-(defun tcl-electric-hash (&optional count)
- "Insert a `#' and quote if it does not start a real comment.
-Prefix arg is number of `#'s to insert.
-See variable `tcl-electric-hash-style' for description of quoting
-styles."
- (interactive "p")
- (or count (setq count 1))
- (if (> count 0)
- (let ((type
- (if (eq tcl-electric-hash-style 'smart)
- (if (> count 3) ; FIXME what is "smart"?
- 'quote
- 'backslash)
- tcl-electric-hash-style))
- comment)
- (if type
- (progn
- (save-excursion
- (insert "#")
- (setq comment (tcl-in-comment)))
- (delete-char 1)
- (and tcl-explain-indentation (message "comment: %s" comment))
- (cond
- ((eq type 'quote)
- (if (not comment)
- (insert "\"")))
- ((eq type 'backslash)
- ;; The following will set count to 0, so the
- ;; insert-char can still be run.
- (if (not comment)
- (while (> count 0)
- (insert "\\#")
- (setq count (1- count)))))
- (t nil))))
- (insert-char ?# count))))
-
-(defun tcl-hashify-buffer ()
- "Quote all `#'s in current buffer that aren't Tcl comments."
- (interactive)
- (save-excursion
- (goto-char (point-min))
- (if (and tcl-pps-has-arg-6 tcl-use-hairy-comment-detector)
- (let (state
- result)
- (while (< (point) (point-max))
- (setq result (tcl-hairy-scan-for-comment state (point-max) t))
- (if (car result)
- (beginning-of-line 2)
- (backward-char)
- (if (eq ?# (following-char))
- (insert "\\"))
- (forward-char))
- (setq state (cdr result))))
- (while (and (< (point) (point-max))
- (search-forward "#" nil 'move))
- (if (tcl-real-comment-p)
- (beginning-of-line 2)
- ;; There's really no good way for the simple converter to
- ;; work. So we just quote # if it isn't already quoted.
- ;; Bogus, but it works.
- (backward-char)
- (if (not (eq ?\\ (preceding-char)))
- (insert "\\"))
- (forward-char))))))
-
-(defun tcl-indent-for-comment ()
- "Indent this line's comment to comment column, or insert an empty comment.
-Is smart about syntax of Tcl comments.
-Parts of this were taken from indent-for-comment (simple.el)."
- (interactive "*")
- (end-of-line)
- (or (tcl-in-comment)
- (progn
- ;; Not in a comment, so we have to insert one. Create an
- ;; empty comment (since there isn't one on this line). If
- ;; line is not blank, make sure we insert a ";" first.
- (skip-chars-backward " \t")
- (let ((eolpoint (point)))
- (beginning-of-line)
- (if (/= (point) eolpoint)
- (progn
- (goto-char eolpoint)
- (insert
- (if (tcl-real-command-p) "" ";")
- "# ")
- (backward-char))))))
- ;; Point is just after the "#" starting a comment. Move it as
- ;; appropriate.
- (let* ((indent (if comment-indent-hook
- (funcall comment-indent-hook)
- (funcall comment-indent-function)))
- (begpos (progn
- (backward-char)
- (point))))
- (if (/= begpos indent)
- (progn
- (skip-chars-backward " \t" (save-excursion
- (beginning-of-line)
- (point)))
- (delete-region (point) begpos)
- (indent-to indent)))
- (looking-at comment-start-skip) ; Always true.
- (goto-char (match-end 0))
- ;; I don't like the effect of the next two.
- ;;(skip-chars-backward " \t" (match-beginning 0))
- ;;(skip-chars-backward "^ \t" (match-beginning 0))
- ))
-
-;; The following was inspired by the Tcl editing mode written by
-;; Gregor Schmid <schmid@fb3-s7.math.TU-Berlin.DE>. His version also
-;; attempts to snarf the command line options from the command line,
-;; but I didn't think that would really be that helpful (doesn't seem
-;; like it owould be right enough. His version also looks for the
-;; "#!/bin/csh ... exec" hack, but that seemed even less useful.
-;; FIXME should make sure that the application mentioned actually
-;; exists.
-(defun tcl-guess-application ()
- "Attempt to guess Tcl application by looking at first line.
-The first line is assumed to look like \"#!.../program ...\"."
- (save-excursion
- (goto-char (point-min))
- (if (looking-at "#![^ \t]*/\\([^ \t\n/]+\\)\\([ \t]\\|$\\)")
- (progn
- (make-local-variable 'tcl-application)
- (setq tcl-application (buffer-substring (match-beginning 1)
- (match-end 1)))))))
-
-;; This only exists to put on the menubar. I couldn't figure out any
-;; other way to do it. FIXME should take "number of #-marks"
-;; argument.
-(defun tcl-uncomment-region (beg end)
- "Uncomment region."
- (interactive "r")
- (comment-region beg end -1))
-
-
-
-;;
-;; XEmacs menu support.
-;; Taken from schmid@fb3-s7.math.TU-Berlin.DE (Gregor Schmid),
-;; who wrote a different Tcl mode.
-;; We also have support for menus in FSF. We do this by
-;; loading the XEmacs menu emulation code.
-;;
-
-(defun tcl-popup-menu (e)
- (interactive "@e")
- (and tcl-using-emacs-19
- (not tcl-using-xemacs-19)
- (if tcl-using-emacs-19-23
- (require 'lmenu)
- ;; CAVEATS:
- ;; * lmenu.el provides 'menubar, which is bogus.
- ;; * lmenu.el causes menubars to be turned on everywhere.
- ;; Doubly bogus!
- ;; Both of these problems are fixed in Emacs 19.23. People
- ;; using an Emacs before that just suffer.
- (require 'menubar "lmenu"))) ;; This is annoying
- ;; IMHO popup-menu should be autoloaded in FSF Emacs. Oh well.
- (popup-menu tcl-xemacs-menu))
-
-
-
-;;
-;; Quoting and unquoting functions.
-;;
-
-;; This quoting is sufficient to protect eg a filename from any sort
-;; of expansion or splitting. Tcl quoting sure sucks.
-(defun tcl-quote (string)
- "Quote STRING according to Tcl rules."
- (mapconcat (function (lambda (char)
- (if (memq char '(?[ ?] ?{ ?} ?\\ ?\" ?$ ? ?\;))
- (concat "\\" (char-to-string char))
- (char-to-string char))))
- string ""))
-
-
-
-;;
-;; Bug reporting.
-;;
-
-(and (fboundp 'eval-when-compile)
- (eval-when-compile
- (require 'reporter)))
-
-(defun tcl-submit-bug-report ()
- "Submit via mail a bug report on Tcl mode."
- (interactive)
- (require 'reporter)
- (and
- (y-or-n-p "Do you really want to submit a bug report on Tcl mode? ")
- (reporter-submit-bug-report
- tcl-maintainer
- (concat "Tcl mode " tcl-version)
- '(tcl-indent-level
- tcl-continued-indent-level
- tcl-auto-newline
- tcl-tab-always-indent
- tcl-use-hairy-comment-detector
- tcl-electric-hash-style
- tcl-help-directory-list
- tcl-use-smart-word-finder
- tcl-application
- tcl-command-switches
- tcl-prompt-regexp
- inferior-tcl-source-command
- tcl-using-emacs-19
- tcl-using-emacs-19-23
- tcl-using-xemacs-19
- tcl-proc-list
- tcl-proc-regexp
- tcl-typeword-list
- tcl-keyword-list
- tcl-font-lock-keywords
- tcl-pps-has-arg-6))))
-
-
-
-(provide 'tcl)
-
-;;; tcl.el ends here
diff --git a/lisp/ps-print.el b/lisp/ps-print.el
deleted file mode 100644
index 57e9b378fe3..00000000000
--- a/lisp/ps-print.el
+++ /dev/null
@@ -1,2931 +0,0 @@
-;;; ps-print.el --- Jim's Pretty-Good PostScript Generator for Emacs 19.
-
-;; Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Jim Thompson <thompson@wg2.waii.com>
-;; Maintainer: duthen@cegelec-red.fr (Jacques Duthen Prestataire)
-;; Keywords: print, PostScript
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; LCD Archive Entry:
-;; ps-print|James C. Thompson|thompson@wg2.waii.com|
-;; Jim's Pretty-Good PostScript Generator for Emacs 19 (ps-print)|
-;; 26-Feb-1994|2.8|~/packages/ps-print.el|
-
-;; 3.03 [jack] Sept 27, 1996 Jacques Duthen <duthen@cegelec-red.fr>
-;; Merge 31 diffs between 19.29 and 19.34
-
-;; 3.02 [jack] June 26, 1996 Jacques Duthen <duthen@cegelec-red.fr>
-;; Add new page dimensions to `ps-page-dimensions-database' for `paper-type'
-;; Improve landscape mode `ps-landscape-mode' and multiple columns
-;; printing `ps-number-of-columns':
-;; The text and the margins are no more scaled.
-;; Simplify the semantics of `ps-inter-column' (space between columns).
-;; Add error checking for negative `ps-print-width' and `ps-print-height'.
-;; Change the semantics of `ps-top-margin' which is now the TOP MARGIN,
-;; and add `ps-header-offset' instead of having `ps-top-margin' split in 2.
-;; Add `ps-header-font-family', `ps-header-font-size' and
-;; `ps-header-title-font-size' to control the header.
-;; Add `ps-header-line-pad'.
-;; Change the semantics of `ps-font-info-database' to have symbolic
-;; font families.
-;; Add new fonts to `ps-font-info-database': `Courier' `Helvetica'
-;; `Times' `Palatino' `Helvetica-Narrow' `NewCenturySchlbk'
-;; Make public `ps-font-family' and `ps-font-size' so that the user
-;; can directly control the text font and size without loading ps-print.
-;; Add error checking for unknown font families and a message giving
-;; the exhaustive list of available font families.
-;; Document how to install a new font family.
-;; Add `/ReportAllFontInfo' to get all the font families of the printer.
-;; Add the possibility to make `mixed' font families.
-;; Add `ps-setup' to get the current setup.
-;; Add tools `ps-line-lengths' `ps-nb-pages-buffer' `ps-nb-pages-region'
-;; to help choose the font size.
-;; Split `ps-print-prologue' in two to insert info from header fonts
-;; Replace indexes by macro `ps-page-dimensions-get-width'
-;; to get access to the dimensions list.
-;; Add `ps-select-font' inside `ps-get-page-dimensions'.
-;; Fix the "clumsy" `ps-page-height' management.
-;; Move `ps-get-page-dimensions' to the beginning of `ps-begin-file'
-;; to get early error checking.
-;; Add sample setup `ps-jack-setup'.
-;;
-;; Rewrite a lot of postscript code and add comments inside it
-;; (maybe they should not (or optionally) be included in the generated
-;; Postscript).
-;; Translate the origin to (lm, bm) to simplify the other moves.
-;; Fix bug in `/HeaderOffset' with `/PrintStartY'.
-;; Fix bug in `/SetHeaderLines'.
-;; Change `/ReportFontInfo' for use by `/ReportAllFontInfo'.
-;;
-
-;; 3.01 [jack] June 4, 1996 Jacques Duthen <duthen@cegelec-red.fr>
-;; Manage float value for every variable representing a size.
-;; Add `ps-font-info-database' `ps-inter-column'
-
-;; 3.00 [jack] May 17, 1996 Jacques Duthen <duthen@cegelec-red.fr>
-;; based on 2.8 Jim's Pretty-Good version:
-;; Add `ps-landscape-mode' and `ps-number-of-columns'
-;; for dumb multi-column landscape mode.
-
-;; Baseline-version: 2.8. (Jim's last change version -- this
-;; file may have been edited as part of Emacs without changes to the
-;; version number. When reporting bugs, please also report the
-;; version of Emacs, if any, that ps-print was distributed with.)
-
-;;; Commentary:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; About ps-print
-;; --------------
-;;
-;; This package provides printing of Emacs buffers on PostScript
-;; printers; the buffer's bold and italic text attributes are
-;; preserved in the printer output. Ps-print is intended for use with
-;; Emacs 19 or Lucid Emacs, together with a fontifying package such as
-;; font-lock or hilit.
-;;
-;;
-;; Using ps-print
-;; --------------
-;;
-;; The Commands
-;;
-;; Ps-print provides eight commands for generating PostScript images
-;; of Emacs buffers:
-;;
-;; ps-print-buffer
-;; ps-print-buffer-with-faces
-;; ps-print-region
-;; ps-print-region-with-faces
-;; ps-spool-buffer
-;; ps-spool-buffer-with-faces
-;; ps-spool-region
-;; ps-spool-region-with-faces
-;;
-;; These commands all perform essentially the same function: they
-;; generate PostScript images suitable for printing on a PostScript
-;; printer or displaying with GhostScript. These commands are
-;; collectively referred to as "ps-print- commands".
-;;
-;; The word "print" or "spool" in the command name determines when the
-;; PostScript image is sent to the printer:
-;;
-;; print - The PostScript image is immediately sent to the
-;; printer;
-;;
-;; spool - The PostScript image is saved temporarily in an
-;; Emacs buffer. Many images may be spooled locally
-;; before printing them. To send the spooled images
-;; to the printer, use the command `ps-despool'.
-;;
-;; The spooling mechanism was designed for printing lots of small
-;; files (mail messages or netnews articles) to save paper that would
-;; otherwise be wasted on banner pages, and to make it easier to find
-;; your output at the printer (it's easier to pick up one 50-page
-;; printout than to find 50 single-page printouts).
-;;
-;; Ps-print has a hook in the `kill-emacs-hooks' so that you won't
-;; accidentally quit from Emacs while you have unprinted PostScript
-;; waiting in the spool buffer. If you do attempt to exit with
-;; spooled PostScript, you'll be asked if you want to print it, and if
-;; you decline, you'll be asked to confirm the exit; this is modeled
-;; on the confirmation that Emacs uses for modified buffers.
-;;
-;; The word "buffer" or "region" in the command name determines how
-;; much of the buffer is printed:
-;;
-;; buffer - Print the entire buffer.
-;;
-;; region - Print just the current region.
-;;
-;; The -with-faces suffix on the command name means that the command
-;; will include font, color, and underline information in the
-;; PostScript image, so the printed image can look as pretty as the
-;; buffer. The ps-print- commands without the -with-faces suffix
-;; don't include font, color, or underline information; images printed
-;; with these commands aren't as pretty, but are faster to generate.
-;;
-;; Two ps-print- command examples:
-;;
-;; ps-print-buffer - print the entire buffer,
-;; without font, color, or
-;; underline information, and
-;; send it immediately to the
-;; printer.
-;;
-;; ps-spool-region-with-faces - print just the current region;
-;; include font, color, and
-;; underline information, and
-;; spool the image in Emacs to
-;; send to the printer later.
-;;
-;;
-;; Invoking Ps-Print
-;; -----------------
-;;
-;; To print your buffer, type
-;;
-;; M-x ps-print-buffer
-;;
-;; or substitute one of the other seven ps-print- commands. The
-;; command will generate the PostScript image and print or spool it as
-;; specified. By giving the command a prefix argument
-;;
-;; C-u M-x ps-print-buffer
-;;
-;; it will save the PostScript image to a file instead of sending it
-;; to the printer; you will be prompted for the name of the file to
-;; save the image to. The prefix argument is ignored by the commands
-;; that spool their images, but you may save the spooled images to a
-;; file by giving a prefix argument to `ps-despool':
-;;
-;; C-u M-x ps-despool
-;;
-;; When invoked this way, `ps-despool' will prompt you for the name of
-;; the file to save to.
-;;
-;; Any of the `ps-print-' commands can be bound to keys; I recommend
-;; binding `ps-spool-buffer-with-faces', `ps-spool-region-with-faces',
-;; and `ps-despool'. Here are the bindings I use on my Sun 4 keyboard:
-;;
-;; (global-set-key 'f22 'ps-spool-buffer-with-faces) ;f22 is prsc
-;; (global-set-key '(shift f22) 'ps-spool-region-with-faces)
-;; (global-set-key '(control f22) 'ps-despool)
-;;
-;;
-;; The Printer Interface
-;; ---------------------
-;;
-;; The variables `ps-lpr-command' and `ps-lpr-switches' determine what
-;; command is used to send the PostScript images to the printer, and
-;; what arguments to give the command. These are analogous to
-;; `lpr-command' and `lpr-switches'.
-;; Make sure that they contain appropriate values for your system;
-;; see the usage notes below and the documentation of these variables.
-;;
-;; NOTE: `ps-lpr-command' and `ps-lpr-switches' take their initial values
-;; from the variables `lpr-command' and `lpr-switches'. If you have
-;; `lpr-command' set to invoke a pretty-printer such as `enscript',
-;; then ps-print won't work properly. `ps-lpr-command' must name
-;; a program that does not format the files it prints.
-;;
-;;
-;; The Page Layout
-;; ---------------
-;;
-;; All dimensions are floats in PostScript points.
-;; 1 inch == 2.54 cm == 72 points
-;; 1 cm == (/ 1 2.54) inch == (/ 72 2.54) points
-;;
-;; The variable `ps-paper-type' determines the size of paper ps-print
-;; formats for; it should contain one of the symbols:
-;; `a4' `a3' `letter' `legal' `letter-small' `tabloid'
-;; `ledger' `statement' `executive' `a4small' `b4' `b5'
-;;
-;; The variable `ps-landscape-mode' determines the orientation
-;; of the printing on the page:
-;; nil means `portrait' mode, non-nil means `landscape' mode.
-;; There is no oblique mode yet, though this is easy to do in ps.
-
-;; In landscape mode, the text is NOT scaled: you may print 70 lines
-;; in portrait mode and only 50 lignes in landscape mode.
-;; The margins represent margins in the printed paper:
-;; the top margin is the margin between the top of the page
-;; and the printed header, whatever the orientation is.
-;;
-;; The variable `ps-number-of-columns' determines the number of columns
-;; both in landscape and portrait mode.
-;; You can use:
-;; - (the standard) one column portrait mode
-;; - (my favorite) two columns landscape mode (which spares trees)
-;; but also
-;; - one column landscape mode for files with very long lines.
-;; - multi-column portrait or landscape mode
-;;
-;;
-;; Horizontal layout
-;; -----------------
-;;
-;; The horizontal layout is determined by the variables
-;; `ps-left-margin' `ps-inter-column' `ps-right-margin'
-;; as follows:
-;;
-;; ------------------------------------------
-;; | | | | | | | |
-;; | lm | text | ic | text | ic | text | rm |
-;; | | | | | | | |
-;; ------------------------------------------
-;;
-;; If `ps-number-of-columns' is 1, `ps-inter-column' is not relevant.
-;; Usually, lm = rm > 0 and ic = lm
-;; If (ic < 0), the text of adjacent columns can overlap.
-;;
-;;
-;; Vertical layout
-;; ---------------
-;;
-;; The vertical layout is determined by the variables
-;; `ps-bottom-margin' `ps-top-margin' `ps-header-offset'
-;; as follows:
-;;
-;; |--------| |--------|
-;; | tm | | tm |
-;; |--------| |--------|
-;; | header | | |
-;; |--------| | |
-;; | ho | | |
-;; |--------| or | text |
-;; | | | |
-;; | text | | |
-;; | | | |
-;; |--------| |--------|
-;; | bm | | bm |
-;; |--------| |--------|
-;;
-;; If `ps-print-header' is nil, `ps-header-offset' is not relevant.
-;; The margins represent margins in the printed paper:
-;; the top margin is the margin between the top of the page
-;; and the printed header, whatever the orientation is.
-;;
-;;
-;; Headers
-;; -------
-;;
-;; Ps-print can print headers at the top of each column; the default
-;; headers contain the following four items: on the left, the name of
-;; the buffer and, if the buffer is visiting a file, the file's
-;; directory; on the right, the page number and date of printing.
-;; The default headers look something like this:
-;;
-;; ps-print.el 1/21
-;; /home/jct/emacs-lisp/ps/new 94/12/31
-;;
-;; When printing on duplex printers, left and right are reversed so
-;; that the page numbers are toward the outside (cf. `ps-spool-duplex').
-;;
-;; Headers are configurable:
-;; To turn them off completely, set `ps-print-header' to nil.
-;; To turn off the header's gaudy framing box,
-;; set `ps-print-header-frame' to nil.
-;;
-;; The font family and size of text in the header are determined
-;; by the variables `ps-header-font-family', `ps-header-font-size' and
-;; `ps-header-title-font-size' (see below).
-;;
-;; The variable `ps-header-line-pad' determines the portion of a header
-;; title line height to insert between the header frame and the text
-;; it contains, both in the vertical and horizontal directions:
-;; .5 means half a line.
-
-;; Page numbers are printed in `n/m' format, indicating page n of m pages;
-;; to omit the total page count and just print the page number,
-;; set `ps-show-n-of-n' to nil.
-;;
-;; The amount of information in the header can be changed by changing
-;; the number of lines. To show less, set `ps-header-lines' to 1, and
-;; the header will show only the buffer name and page number. To show
-;; more, set `ps-header-lines' to 3, and the header will show the time of
-;; printing below the date.
-;;
-;; To change the content of the headers, change the variables
-;; `ps-left-header' and `ps-right-header'.
-;; These variables are lists, specifying top-to-bottom the text
-;; to display on the left or right side of the header.
-;; Each element of the list should be a string or a symbol.
-;; Strings are inserted directly into the PostScript arrays,
-;; and should contain the PostScript string delimiters '(' and ')'.
-;;
-;; Symbols in the header format lists can either represent functions
-;; or variables. Functions are called, and should return a string to
-;; show in the header. Variables should contain strings to display in
-;; the header. In either case, function or variable, the PostScript
-;; string delimiters are added by ps-print, and should not be part of
-;; the returned value.
-;;
-;; Here's an example: say we want the left header to display the text
-;;
-;; Moe
-;; Larry
-;; Curly
-;;
-;; where we have a function to return "Moe"
-;;
-;; (defun moe-func ()
-;; "Moe")
-;;
-;; a variable specifying "Larry"
-;;
-;; (setq larry-var "Larry")
-;;
-;; and a literal for "Curly". Here's how `ps-left-header' should be
-;; set:
-;;
-;; (setq ps-left-header (list 'moe-func 'larry-var "(Curly)"))
-;;
-;; Note that Curly has the PostScript string delimiters inside his
-;; quotes -- those aren't misplaced lisp delimiters!
-;; Without them, PostScript would attempt to call the undefined
-;; function Curly, which would result in a PostScript error.
-;; Since most printers don't report PostScript errors except by
-;; aborting the print job, this kind of error can be hard to track down.
-;; Consider yourself warned!
-;;
-;;
-;; Duplex Printers
-;; ---------------
-;;
-;; If you have a duplex-capable printer (one that prints both sides of
-;; the paper), set `ps-spool-duplex' to t.
-;; Ps-print will insert blank pages to make sure each buffer starts
-;; on the correct side of the paper.
-;; Don't forget to set `ps-lpr-switches' to select duplex printing
-;; for your printer.
-;;
-;;
-;; Font managing
-;; -------------
-;;
-;; Ps-print now knows rather precisely some fonts:
-;; the variable `ps-font-info-database' contains information
-;; for a list of font families (currently mainly `Courier' `Helvetica'
-;; `Times' `Palatino' `Helvetica-Narrow' `NewCenturySchlbk').
-;; Each font family contains the font names for standard, bold, italic
-;; and bold-italic characters, a reference size (usually 10) and the
-;; corresponding line height, width of a space and average character width.
-;;
-;; The variable `ps-font-family' determines which font family
-;; is to be used for ordinary text.
-;; If its value does not correspond to a known font family,
-;; an error message is printed into the `*Messages*' buffer,
-;; which lists the currently available font families.
-;;
-;; The variable `ps-font-size' determines the size (in points)
-;; of the font for ordinary text, when generating Postscript.
-;; Its value is a float.
-;;
-;; Similarly, the variable `ps-header-font-family' determines
-;; which font family is to be used for text in the header.
-;; The variable `ps-header-font-size' determines the font size,
-;; in points, for text in the header.
-;; The variable `ps-header-title-font-size' determines the font size,
-;; in points, for the top line of text in the header.
-;;
-;;
-;; Adding a new font family
-;; ------------------------
-;;
-;; To use a new font family, you MUST first teach ps-print
-;; this font, ie add its information to `ps-font-info-database',
-;; otherwise ps-print cannot correctly place line and page breaks.
-;;
-;; For example, assuming `Helvetica' is unkown,
-;; you first need to do the following ONLY ONCE:
-;;
-;; - create a new buffer
-;; - generate the PostScript image to a file (C-u M-x ps-print-buffer)
-;; - open this file and find the line:
-;; `% 3 cm 20 cm moveto 10 /Courier ReportFontInfo showpage'
-;; - delete the leading `%' (which is the Postscript comment character)
-;; - replace in this line `Courier' by the new font (say `Helvetica')
-;; to get the line:
-;; `3 cm 20 cm moveto 10 /Helvetica ReportFontInfo showpage'
-;; - send this file to the printer (or to ghostscript).
-;; You should read the following on the output page:
-;;
-;; For Helvetica 10 point, the line height is 11.56, the space width is 2.78
-;; and a crude estimate of average character width is 5.09243
-;;
-;; - Add these values to the `ps-font-info-database':
-;; (setq ps-font-info-database
-;; (append
-;; '((Helvetica ; the family name
-;; "Helvetica" "Helvetica-Bold" "Helvetica-Oblique" "Helvetica-BoldOblique"
-;; 10.0 11.56 2.78 5.09243))
-;; ps-font-info-database))
-;; - Now you can use this font family with any size:
-;; (setq ps-font-family 'Helvetica)
-;; - if you want to use this family in another emacs session, you must
-;; put into your `~/.emacs':
-;; (require 'ps-print)
-;; (setq ps-font-info-database (append ...)))
-;; if you don't want to load ps-print, you have to copy the whole value:
-;; (setq ps-font-info-database '(<your stuff> <the standard stuff>))
-;; or, if you can wait until the `ps-print-hook' is implemented, do:
-;; (add-hook 'ps-print-hook '(setq ps-font-info-database (append ...)))
-;; This does not work yet, since there is no `ps-print-hook' yet.
-;;
-;; You can create new `mixed' font families like:
-;; (my-mixed-family
-;; "Courier-Bold" "Helvetica"
-;; "Zapf-Chancery-MediumItalic" "NewCenturySchlbk-BoldItalic"
-;; 10.0 10.55 6.0 6.0)
-;; Now you can use your new font family with any size:
-;; (setq ps-font-family 'my-mixed-family)
-;;
-;; You can get information on all the fonts resident in YOUR printer
-;; by uncommenting the line:
-;; % 3 cm 20 cm moveto ReportAllFontInfo showpage
-;;
-;; The postscript file should be sent to YOUR postscript printer.
-;; If you send it to ghostscript or to another postscript printer,
-;; you may get slightly different results.
-;; Anyway, as ghostscript fonts are autoload, you won't get
-;; much font info.
-;;
-;;
-;; How Ps-Print Deals With Faces
-;; -----------------------------
-;;
-;; The ps-print-*-with-faces commands attempt to determine which faces
-;; should be printed in bold or italic, but their guesses aren't
-;; always right. For example, you might want to map colors into faces
-;; so that blue faces print in bold, and red faces in italic.
-;;
-;; It is possible to force ps-print to consider specific faces bold or
-;; italic, no matter what font they are displayed in, by setting the
-;; variables `ps-bold-faces' and `ps-italic-faces'. These variables
-;; contain lists of faces that ps-print should consider bold or
-;; italic; to set them, put code like the following into your .emacs
-;; file:
-;;
-;; (setq ps-bold-faces '(my-blue-face))
-;; (setq ps-italic-faces '(my-red-face))
-;;
-;; Faces like bold-italic that are both bold and italic should go in
-;; *both* lists.
-;;
-;; Ps-print keeps internal lists of which fonts are bold and which are
-;; italic; these lists are built the first time you invoke ps-print.
-;; For the sake of efficiency, the lists are built only once; the same
-;; lists are referred in later invocations of ps-print.
-;;
-;; Because these lists are built only once, it's possible for them to
-;; get out of sync, if a face changes, or if new faces are added. To
-;; get the lists back in sync, you can set the variable
-;; `ps-build-face-reference' to t, and the lists will be rebuilt the
-;; next time ps-print is invoked.
-;;
-;;
-;; How Ps-Print Deals With Color
-;; -----------------------------
-;;
-;; Ps-print detects faces with foreground and background colors
-;; defined and embeds color information in the PostScript image.
-;; The default foreground and background colors are defined by the
-;; variables `ps-default-fg' and `ps-default-bg'.
-;; On black-and-white printers, colors are displayed in grayscale.
-;; To turn off color output, set `ps-print-color-p' to nil.
-;;
-;;
-;; Utilities
-;; ---------
-;;
-;; Some tools are provided to help you customize your font setup.
-;;
-;; `ps-setup' returns (some part of) the current setup.
-;;
-;; To avoid wrapping too many lines, you may want to adjust the
-;; left and right margins and the font size. On UN*X systems, do:
-;; pr -t file | awk '{printf "%3d %s\n", length($0), $0}' | sort -r | head
-;; to determine the longest lines of your file.
-;; Then, the command `ps-line-lengths' will give you the correspondance
-;; between a line length (number of characters) and the maximum font
-;; size which doesn't wrap such a line with the current ps-print setup.
-;;
-;; The commands `ps-nb-pages-buffer' and `ps-nb-pages-region' display
-;; the correspondance between a number of pages and the maximum font
-;; size which allow the number of lines of the current buffer or of
-;; its current region to fit in this number of pages.
-;; Note: line folding is not taken into account in this process
-;; and could change the results.
-;;
-;;
-;; New since version 1.5
-;; ---------------------
-;;
-;; Color output capability.
-;; Automatic detection of font attributes (bold, italic).
-;; Configurable headers with page numbers.
-;; Slightly faster.
-;; Support for different paper sizes.
-;; Better conformance to PostScript Document Structure Conventions.
-;;
-;;
-;; New since version 2.8
-;; ---------------------
-;;
-;; [jack] 960517 Jacques Duthen <duthen@cegelec-red.fr>
-;;
-;; Font familiy and float size for text and header.
-;; Landscape mode.
-;; Multiple columns.
-;; Tools for page setup.
-;;
-;;
-;; Known bugs and limitations of ps-print:
-;; --------------------------------------
-;;
-;; Although color printing will work in XEmacs 19.12, it doesn't work
-;; well; in particular, bold or italic fonts don't print in the right
-;; background color.
-;;
-;; Invisible properties aren't correctly ignored in XEmacs 19.12.
-;;
-;; Automatic font-attribute detection doesn't work well, especially
-;; with hilit19 and older versions of get-create-face. Users having
-;; problems with auto-font detection should use the lists
-;; `ps-italic-faces' and `ps-bold-faces' and/or turn off automatic
-;; detection by setting `ps-auto-font-detect' to nil.
-;;
-;; Automatic font-attribute detection doesn't work with XEmacs 19.12
-;; in tty mode; use the lists `ps-italic-faces' and `ps-bold-faces'
-;; instead.
-;;
-;; Still too slow; could use some hand-optimization.
-;;
-;; ASCII Control characters other than tab, linefeed and pagefeed are
-;; not handled.
-;;
-;; Default background color isn't working.
-;;
-;; Faces are always treated as opaque.
-;;
-;; Epoch and Emacs 18 not supported. At all.
-;;
-;; Fixed-pitch fonts work better for line folding, but are not required.
-;;
-;; `ps-nb-pages-buffer' and `ps-nb-pages-region' don't take care
-;; of folding lines.
-;;
-;;
-;; Things to change:
-;; ----------------
-;;
-;; Add `ps-print-hook' (I don't know how to do that (yet!)).
-;; Add 4-up capability (really needed?).
-;; Add line numbers (should not be too hard).
-;; Add `ps-non-bold-faces' and `ps-non-italic-faces' (should be easy).
-;; Put one header per page over the columns (easy but needed?).
-;; Improve the memory management for big files (hard?).
-;; `ps-nb-pages-buffer' and `ps-nb-pages-region' should take care
-;; of folding lines.
-;;
-;;
-;; Acknowledgements
-;; ----------------
-;; Thanks to Jim Thompson <?@?> for the 2.8 version I started from.
-;; [jack]
-;;
-;; Thanks to Kevin Rodgers <kevinr@ihs.com> for adding support for
-;; color and the invisible property.
-;;
-;; Thanks to Avishai Yacobi, avishaiy@mcil.comm.mot.com, for writing
-;; the initial port to Emacs 19. His code is no longer part of
-;; ps-print, but his work is still appreciated.
-;;
-;; Thanks to Remi Houdaille and Michel Train, michel@metasoft.fdn.org,
-;; for adding underline support. Their code also is no longer part of
-;; ps-print, but their efforts are not forgotten.
-;;
-;; Thanks also to all of you who mailed code to add features to
-;; ps-print; although I didn't use your code, I still appreciate your
-;; sharing it with me.
-;;
-;; Thanks to all who mailed comments, encouragement, and criticism.
-;; Thanks also to all who responded to my survey; I had too many
-;; responses to reply to them all, but I greatly appreciate your
-;; interest.
-;;
-;; Jim
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;; Code:
-
-(defconst ps-print-version "3.01"
- "ps-print.el,v 3.01 1996/06/13 18:12 jack
-
-Jack's last change version -- this file may have been edited as part of
-Emacs without changes to the version number. When reporting bugs,
-please also report the version of Emacs, if any, that ps-print was
-distributed with.
-
-Please send all bug fixes and enhancements to
- Jacques Duthen <duthen@cegelec-red.fr>.
-")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; User Variables:
-
-;;; Interface to the command system
-
-(defvar ps-lpr-command lpr-command
- "*The shell command for printing a PostScript file.")
-
-(defvar ps-lpr-switches lpr-switches
- "*A list of extra switches to pass to `ps-lpr-command'.")
-
-;;; Page layout
-
-;; All page dimensions are in PostScript points.
-;; 1 inch == 2.54 cm == 72 points
-;; 1 cm == (/ 1 2.54) inch == (/ 72 2.54) points
-
-;; Letter 8.5 inch x 11.0 inch
-;; Legal 8.5 inch x 14.0 inch
-;; A4 8.26 inch x 11.69 inch = 21.0 cm x 29.7 cm
-
-;; LetterSmall 7.68 inch x 10.16 inch
-;; Tabloid 11.0 inch x 17.0 inch
-;; Ledger 17.0 inch x 11.0 inch
-;; Statement 5.5 inch x 8.5 inch
-;; Executive 7.5 inch x 10.0 inch
-;; A3 11.69 inch x 16.5 inch = 29.7 cm x 42.0 cm
-;; A4Small 7.47 inch x 10.85 inch
-;; B4 10.125 inch x 14.33 inch
-;; B5 7.16 inch x 10.125 inch
-
-(defvar ps-page-dimensions-database
- (list (list 'a4 (/ (* 72 21.0) 2.54) (/ (* 72 29.7) 2.54))
- (list 'a3 (/ (* 72 29.7) 2.54) (/ (* 72 42.0) 2.54))
- (list 'letter (* 72 8.5) (* 72 11.0))
- (list 'legal (* 72 8.5) (* 72 14.0))
- (list 'letter-small (* 72 7.68) (* 72 10.16))
- (list 'tabloid (* 72 11.0) (* 72 17.0))
- (list 'ledger (* 72 17.0) (* 72 11.0))
- (list 'statement (* 72 5.5) (* 72 8.5))
- (list 'executive (* 72 7.5) (* 72 10.0))
- (list 'a4small (* 72 7.47) (* 72 10.85))
- (list 'b4 (* 72 10.125) (* 72 14.33))
- (list 'b5 (* 72 7.16) (* 72 10.125)))
- "*List associating a symbolic paper type to its width and height.
-see `ps-paper-type'.")
-
-(defvar ps-paper-type 'letter
- "*Specifies the size of paper to format for.
-Should be one of the paper types defined in `ps-page-dimensions-database':
-`letter', `legal', `a4'...")
-
-(defvar ps-landscape-mode 'nil
- "*Non-nil means print in landscape mode.")
-
-(defvar ps-number-of-columns 1
- "*Specifies the number of columns")
-
-;;; Horizontal layout
-
-;; ------------------------------------------
-;; | | | | | | | |
-;; | lm | text | ic | text | ic | text | rm |
-;; | | | | | | | |
-;; ------------------------------------------
-
-(defvar ps-left-margin (/ (* 72 2.0) 2.54) ; 2 cm
- "*Left margin in points (1/72 inch).")
-
-(defvar ps-right-margin (/ (* 72 2.0) 2.54) ; 2 cm
- "*Right margin in points (1/72 inch).")
-
-(defvar ps-inter-column (/ (* 72 2.0) 2.54) ; 2 cm
- "*Horizontal space between columns in points (1/72 inch).")
-
-;;; Vertical layout
-
-;; |--------|
-;; | tm |
-;; |--------|
-;; | header |
-;; |--------|
-;; | ho |
-;; |--------|
-;; | text |
-;; |--------|
-;; | bm |
-;; |--------|
-
-(defvar ps-bottom-margin (/ (* 72 1.5) 2.54) ; 1.5 cm
- "*Bottom margin in points (1/72 inch).")
-
-(defvar ps-top-margin (/ (* 72 1.5) 2.54) ; 1.5 cm
- "*Top margin in points (1/72 inch).")
-
-(defvar ps-header-offset (/ (* 72 1.0) 2.54) ; 1.0 cm
- "*Vertical space in points (1/72 inch) between the main text and the header.")
-
-(defvar ps-header-line-pad 0.15
- "*Portion of a header title line height to insert between the header frame
-and the text it contains, both in the vertical and horizontal directions.")
-
-;;; Header setup
-
-(defvar ps-print-header t
- "*Non-nil means print a header at the top of each page.
-By default, the header displays the buffer name, page number, and, if
-the buffer is visiting a file, the file's directory. Headers are
-customizable by changing variables `ps-header-left' and
-`ps-header-right'.")
-
-(defvar ps-print-header-frame t
- "*Non-nil means draw a gaudy frame around the header.")
-
-(defvar ps-header-lines 2
- "*Number of lines to display in page header, when generating Postscript.")
-(make-variable-buffer-local 'ps-header-lines)
-
-(defvar ps-show-n-of-n t
- "*Non-nil means show page numbers as N/M, meaning page N of M.
-Note: page numbers are displayed as part of headers, see variable
-`ps-print-headers'.")
-
-(defvar ps-spool-duplex nil ; Not many people have duplex
- ; printers, so default to nil.
- "*Non-nil indicates spooling is for a two-sided printer.
-For a duplex printer, the `ps-spool-*' commands will insert blank pages
-as needed between print jobs so that the next buffer printed will
-start on the right page. Also, if headers are turned on, the headers
-will be reversed on duplex printers so that the page numbers fall to
-the left on even-numbered pages.")
-
-;;; Fonts
-
-(defvar ps-font-info-database
- '((Courier ; the family key
- "Courier" "Courier-Bold" "Courier-Oblique" "Courier-BoldOblique"
- 10.0 10.55 6.0 6.0)
- (Helvetica ; the family key
- "Helvetica" "Helvetica-Bold" "Helvetica-Oblique" "Helvetica-BoldOblique"
- 10.0 11.56 2.78 5.09243)
- (Times
- "Times-Roman" "Times-Bold" "Times-Italic" "Times-BoldItalic"
- 10.0 11.0 2.5 4.71432)
- (Palatino
- "Palatino-Roman" "Palatino-Bold" "Palatino-Italic" "Palatino-BoldItalic"
- 10.0 12.1 2.5 5.08676)
- (Helvetica-Narrow
- "Helvetica-Narrow" "Helvetica-Narrow-Bold"
- "Helvetica-Narrow-Oblique" "Helvetica-Narrow-BoldOblique"
- 10.0 11.56 2.2796 4.17579)
- (NewCenturySchlbk
- "NewCenturySchlbk-Roman" "NewCenturySchlbk-Bold"
- "NewCenturySchlbk-Italic" "NewCenturySchlbk-BoldItalic"
- 10.0 12.15 2.78 5.31162)
- ;; got no bold for the next ones
- (AvantGarde-Book
- "AvantGarde-Book" "AvantGarde-Book"
- "AvantGarde-BookOblique" "AvantGarde-BookOblique"
- 10.0 11.77 2.77 5.45189)
- (AvantGarde-Demi
- "AvantGarde-Demi" "AvantGarde-Demi"
- "AvantGarde-DemiOblique" "AvantGarde-DemiOblique"
- 10.0 12.72 2.8 5.51351)
- (Bookman-Demi
- "Bookman-Demi" "Bookman-Demi"
- "Bookman-DemiItalic" "Bookman-DemiItalic"
- 10.0 11.77 3.4 6.05946)
- (Bookman-Light
- "Bookman-Light" "Bookman-Light"
- "Bookman-LightItalic" "Bookman-LightItalic"
- 10.0 11.79 3.2 5.67027)
- ;; got no bold and no italic for the next ones
- (Symbol
- "Symbol" "Symbol" "Symbol" "Symbol"
- 10.0 13.03 2.5 3.24324)
- (Zapf-Dingbats
- "Zapf-Dingbats" "Zapf-Dingbats" "Zapf-Dingbats" "Zapf-Dingbats"
- 10.0 9.63 2.78 2.78)
- (Zapf-Chancery-MediumItalic
- "Zapf-Chancery-MediumItalic" "Zapf-Chancery-MediumItalic"
- "Zapf-Chancery-MediumItalic" "Zapf-Chancery-MediumItalic"
- 10.0 11.45 2.2 4.10811)
-)
- "*Font info database: font family (the key), name, bold, italic, bold-italic,
-reference size, line height, space width, average character width.
-To get the info for another specific font (say Helvetica), do the following:
-- create a new buffer
-- generate the PostScript image to a file (C-u M-x ps-print-buffer)
-- open this file and delete the leading `%' (which is the Postscript
- comment character) from the line
- `% 3 cm 20 cm moveto 10 /Courier ReportFontInfo showpage'
- to get the line
- `3 cm 20 cm moveto 10 /Helvetica ReportFontInfo showpage'
-- add the values to `ps-font-info-database'.
-You can get all the fonts of YOUR printer using `ReportAllFontInfo'.")
-
-(defvar ps-font-family 'Courier
- "Font family name for ordinary text, when generating Postscript.")
-
-(defvar ps-font-size 8.5
- "Font size, in points, for ordinary text, when generating Postscript.")
-
-(defvar ps-header-font-family 'Helvetica
- "Font family name for text in the header, when generating Postscript.")
-
-(defvar ps-header-font-size 12
- "Font size, in points, for text in the header, when generating Postscript.")
-
-(defvar ps-header-title-font-size 14
- "Font size, in points, for the top line of text in the header,
-when generating Postscript.")
-
-;;; Colors
-
-(defvar ps-print-color-p (or (fboundp 'x-color-values) ; Emacs
- (fboundp 'pixel-components)) ; XEmacs
-; Printing color requires x-color-values.
- "*If non-nil, print the buffer's text in color.")
-
-(defvar ps-default-fg '(0.0 0.0 0.0)
- "*RGB values of the default foreground color. Defaults to black.")
-
-(defvar ps-default-bg '(1.0 1.0 1.0)
- "*RGB values of the default background color. Defaults to white.")
-
-(defvar ps-auto-font-detect t
- "*Non-nil means automatically detect bold/italic face attributes.
-nil means rely solely on the lists `ps-bold-faces', `ps-italic-faces',
-and `ps-underlined-faces'.")
-
-(defvar ps-bold-faces '()
- "*A list of the \(non-bold\) faces that should be printed in bold font.
-This applies to generating Postscript.")
-
-(defvar ps-italic-faces '()
- "*A list of the \(non-italic\) faces that should be printed in italic font.
-This applies to generating Postscript.")
-
-(defvar ps-underlined-faces '()
- "*A list of the \(non-underlined\) faces that should be printed underlined.
-This applies to generating Postscript.")
-
-(defvar ps-left-header
- (list 'ps-get-buffer-name 'ps-header-dirpart)
- "*The items to display (each on a line) on the left part of the page header.
-This applies to generating Postscript.
-
-The value should be a list of strings and symbols, each representing an
-entry in the PostScript array HeaderLinesLeft.
-
-Strings are inserted unchanged into the array; those representing
-PostScript string literals should be delimited with PostScript string
-delimiters '(' and ')'.
-
-For symbols with bound functions, the function is called and should
-return a string to be inserted into the array. For symbols with bound
-values, the value should be a string to be inserted into the array.
-In either case, function or variable, the string value has PostScript
-string delimiters added to it.")
-(make-variable-buffer-local 'ps-left-header)
-
-(defvar ps-right-header
- (list "/pagenumberstring load" 'time-stamp-yy/mm/dd 'time-stamp-hh:mm:ss)
- "*The items to display (each on a line) on the right part of the page header.
-This applies to generating Postscript.
-
-See the variable `ps-left-header' for a description of the format of
-this variable.")
-(make-variable-buffer-local 'ps-right-header)
-
-(defvar ps-razzle-dazzle t
- "*Non-nil means report progress while formatting buffer.")
-
-(defvar ps-adobe-tag "%!PS-Adobe-1.0\n"
- "*Contains the header line identifying the output as PostScript.
-By default, `ps-adobe-tag' contains the standard identifier. Some
-printers require slightly different versions of this line.")
-
-(defvar ps-build-face-reference t
- "*Non-nil means build the reference face lists.
-
-Ps-print sets this value to nil after it builds its internal reference
-lists of bold and italic faces. By settings its value back to t, you
-can force ps-print to rebuild the lists the next time you invoke one
-of the ...-with-faces commands.
-
-You should set this value back to t after you change the attributes of
-any face, or create new faces. Most users shouldn't have to worry
-about its setting, though.")
-
-(defvar ps-always-build-face-reference nil
- "*Non-nil means always rebuild the reference face lists.
-
-If this variable is non-nil, ps-print will rebuild its internal
-reference lists of bold and italic faces *every* time one of the
--with-faces commands is called. Most users shouldn't need to set this
-variable.")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; User commands
-
-;;;###autoload
-(defun ps-print-buffer (&optional filename)
- "Generate and print a PostScript image of the buffer.
-
-When called with a numeric prefix argument (C-u), prompts the user for
-the name of a file to save the PostScript image in, instead of sending
-it to the printer.
-
-More specifically, the FILENAME argument is treated as follows: if it
-is nil, send the image to the printer. If FILENAME is a string, save
-the PostScript image in a file with that name. If FILENAME is a
-number, prompt the user for the name of the file to save in."
-
- (interactive (list (ps-print-preprint current-prefix-arg)))
- (ps-generate (current-buffer) (point-min) (point-max)
- 'ps-generate-postscript)
- (ps-do-despool filename))
-
-
-;;;###autoload
-(defun ps-print-buffer-with-faces (&optional filename)
- "Generate and print a PostScript image of the buffer.
-Like `ps-print-buffer', but includes font, color, and underline
-information in the generated image. This command works only if you
-are using a window system, so it has a way to determine color values."
- (interactive (list (ps-print-preprint current-prefix-arg)))
- (ps-generate (current-buffer) (point-min) (point-max)
- 'ps-generate-postscript-with-faces)
- (ps-do-despool filename))
-
-
-;;;###autoload
-(defun ps-print-region (from to &optional filename)
- "Generate and print a PostScript image of the region.
-Like `ps-print-buffer', but prints just the current region."
-
- (interactive (list (point) (mark) (ps-print-preprint current-prefix-arg)))
- (ps-generate (current-buffer) from to
- 'ps-generate-postscript)
- (ps-do-despool filename))
-
-
-;;;###autoload
-(defun ps-print-region-with-faces (from to &optional filename)
- "Generate and print a PostScript image of the region.
-Like `ps-print-region', but includes font, color, and underline
-information in the generated image. This command works only if you
-are using a window system, so it has a way to determine color values."
-
- (interactive (list (point) (mark) (ps-print-preprint current-prefix-arg)))
- (ps-generate (current-buffer) from to
- 'ps-generate-postscript-with-faces)
- (ps-do-despool filename))
-
-
-;;;###autoload
-(defun ps-spool-buffer ()
- "Generate and spool a PostScript image of the buffer.
-Like `ps-print-buffer' except that the PostScript image is saved in a
-local buffer to be sent to the printer later.
-
-Use the command `ps-despool' to send the spooled images to the printer."
- (interactive)
- (ps-generate (current-buffer) (point-min) (point-max)
- 'ps-generate-postscript))
-
-
-;;;###autoload
-(defun ps-spool-buffer-with-faces ()
- "Generate and spool a PostScript image of the buffer.
-Like `ps-spool-buffer', but includes font, color, and underline
-information in the generated image. This command works only if you
-are using a window system, so it has a way to determine color values.
-
-Use the command `ps-despool' to send the spooled images to the printer."
-
- (interactive)
- (ps-generate (current-buffer) (point-min) (point-max)
- 'ps-generate-postscript-with-faces))
-
-
-;;;###autoload
-(defun ps-spool-region (from to)
- "Generate a PostScript image of the region and spool locally.
-Like `ps-spool-buffer', but spools just the current region.
-
-Use the command `ps-despool' to send the spooled images to the printer."
- (interactive "r")
- (ps-generate (current-buffer) from to
- 'ps-generate-postscript))
-
-
-;;;###autoload
-(defun ps-spool-region-with-faces (from to)
- "Generate a PostScript image of the region and spool locally.
-Like `ps-spool-region', but includes font, color, and underline
-information in the generated image. This command works only if you
-are using a window system, so it has a way to determine color values.
-
-Use the command `ps-despool' to send the spooled images to the printer."
- (interactive "r")
- (ps-generate (current-buffer) from to
- 'ps-generate-postscript-with-faces))
-
-;;;###autoload
-(defun ps-despool (&optional filename)
- "Send the spooled PostScript to the printer.
-
-When called with a numeric prefix argument (C-u), prompt the user for
-the name of a file to save the spooled PostScript in, instead of sending
-it to the printer.
-
-More specifically, the FILENAME argument is treated as follows: if it
-is nil, send the image to the printer. If FILENAME is a string, save
-the PostScript image in a file with that name. If FILENAME is a
-number, prompt the user for the name of the file to save in."
- (interactive (list (ps-print-preprint current-prefix-arg)))
- (ps-do-despool filename))
-
-;;;###autoload
-(defun ps-line-lengths ()
- "*Display the correspondance between a line length and a font size,
-using the current ps-print setup.
-Try: pr -t file | awk '{printf \"%3d %s\n\", length($0), $0}' | sort -r | head"
- (interactive)
- (ps-line-lengths-internal))
-
-;;;###autoload
-(defun ps-nb-pages-buffer (nb-lines)
- "*Display an approximate correspondance between a font size and the number
-of pages the current buffer would require to print
-using the current ps-print setup."
- (interactive (list (count-lines (point-min) (point-max))))
- (ps-nb-pages nb-lines))
-
-;;;###autoload
-(defun ps-nb-pages-region (nb-lines)
- "*Display an approximate correspondance between a font size and the number
-of pages the current region would require to print
-using the current ps-print setup."
- (interactive (list (count-lines (mark) (point))))
- (ps-nb-pages nb-lines))
-
-;;;###autoload
-(defun ps-setup ()
- "*Return the current setup"
- (format "
- (setq ps-print-color-p %s
- ps-lpr-command \"%s\"
- ps-lpr-switches %s
-
- ps-paper-type '%s
- ps-landscape-mode %s
- ps-number-of-columns %s
-
- ps-left-margin %s
- ps-right-margin %s
- ps-inter-column %s
- ps-bottom-margin %s
- ps-top-margin %s
- ps-header-offset %s
- ps-header-line-pad %s
- ps-print-header %s
- ps-print-header-frame %s
- ps-header-lines %s
- ps-show-n-of-n %s
- ps-spool-duplex %s
-
- ps-font-family '%s
- ps-font-size %s
- ps-header-font-family '%s
- ps-header-font-size %s
- ps-header-title-font-size %s)
-"
- ps-print-color-p
- ps-lpr-command
- ps-lpr-switches
- ps-paper-type
- ps-landscape-mode
- ps-number-of-columns
- ps-left-margin
- ps-right-margin
- ps-inter-column
- ps-bottom-margin
- ps-top-margin
- ps-header-offset
- ps-header-line-pad
- ps-print-header
- ps-print-header-frame
- ps-header-lines
- ps-show-n-of-n
- ps-spool-duplex
- ps-font-family
- ps-font-size
- ps-header-font-family
- ps-header-font-size
- ps-header-title-font-size))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Utility functions and variables:
-
-(defvar ps-print-emacs-type
- (cond ((string-match "XEmacs" emacs-version) 'xemacs)
- ((string-match "Lucid" emacs-version) 'lucid)
- ((string-match "Epoch" emacs-version) 'epoch)
- (t 'emacs)))
-
-(if (or (eq ps-print-emacs-type 'lucid)
- (eq ps-print-emacs-type 'xemacs))
- (if (< emacs-minor-version 12)
- (setq ps-print-color-p nil))
- (require 'faces)) ; face-font, face-underline-p,
- ; x-font-regexp
-
-(require 'time-stamp)
-
-(defvar ps-font nil
- "Font family name for ordinary text, when generating Postscript.")
-
-(defvar ps-font-bold nil
- "Font family name for bold text, when generating Postscript.")
-
-(defvar ps-font-italic nil
- "Font family name for italic text, when generating Postscript.")
-
-(defvar ps-font-bold-italic nil
- "Font family name for bold italic text, when generating Postscript.")
-
-(defvar ps-avg-char-width nil
- "The average width, in points, of a character, for generating Postscript.
-This is the value that ps-print uses to determine the length,
-x-dimension, of the text it has printed, and thus affects the point at
-which long lines wrap around.")
-
-(defvar ps-space-width nil
- "The width of a space character, for generating Postscript.
-This value is used in expanding tab characters.")
-
-(defvar ps-line-height nil
- "The height of a line, for generating Postscript.
-This is the value that ps-print uses to determine the height,
-y-dimension, of the lines of text it has printed, and thus affects the
-point at which page-breaks are placed.
-The line-height is *not* the same as the point size of the font.")
-
-(defvar ps-print-prologue-1
- "% ISOLatin1Encoding stolen from ps_init.ps in GhostScript 2.6.1.4:
-/ISOLatin1Encoding where { pop } {
-% -- The ISO Latin-1 encoding vector isn't known, so define it.
-% -- The first half is the same as the standard encoding,
-% -- except for minus instead of hyphen at code 055.
-/ISOLatin1Encoding
-StandardEncoding 0 45 getinterval aload pop
- /minus
-StandardEncoding 46 82 getinterval aload pop
-%*** NOTE: the following are missing in the Adobe documentation,
-%*** but appear in the displayed table:
-%*** macron at 0225, dieresis at 0230, cedilla at 0233, space at 0240.
-% 0200 (128)
- /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
- /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
- /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent
- /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron
-% 0240 (160)
- /space /exclamdown /cent /sterling
- /currency /yen /brokenbar /section
- /dieresis /copyright /ordfeminine /guillemotleft
- /logicalnot /hyphen /registered /macron
- /degree /plusminus /twosuperior /threesuperior
- /acute /mu /paragraph /periodcentered
- /cedilla /onesuperior /ordmasculine /guillemotright
- /onequarter /onehalf /threequarters /questiondown
-% 0300 (192)
- /Agrave /Aacute /Acircumflex /Atilde
- /Adieresis /Aring /AE /Ccedilla
- /Egrave /Eacute /Ecircumflex /Edieresis
- /Igrave /Iacute /Icircumflex /Idieresis
- /Eth /Ntilde /Ograve /Oacute
- /Ocircumflex /Otilde /Odieresis /multiply
- /Oslash /Ugrave /Uacute /Ucircumflex
- /Udieresis /Yacute /Thorn /germandbls
-% 0340 (224)
- /agrave /aacute /acircumflex /atilde
- /adieresis /aring /ae /ccedilla
- /egrave /eacute /ecircumflex /edieresis
- /igrave /iacute /icircumflex /idieresis
- /eth /ntilde /ograve /oacute
- /ocircumflex /otilde /odieresis /divide
- /oslash /ugrave /uacute /ucircumflex
- /udieresis /yacute /thorn /ydieresis
-256 packedarray def
-} ifelse
-
-/reencodeFontISO { %def
- dup
- length 5 add dict % Make a new font (a new dict the same size
- % as the old one) with room for our new symbols.
-
- begin % Make the new font the current dictionary.
-
-
- { 1 index /FID ne
- { def } { pop pop } ifelse
- } forall % Copy each of the symbols from the old dictionary
- % to the new one except for the font ID.
-
- /Encoding ISOLatin1Encoding def % Override the encoding with
- % the ISOLatin1 encoding.
-
- % Use the font's bounding box to determine the ascent, descent,
- % and overall height; don't forget that these values have to be
- % transformed using the font's matrix.
-
-% ^ (x2 y2)
-% | |
-% | v
-% | +----+ - -
-% | | | ^
-% | | | | Ascent (usually > 0)
-% | | | |
-% (0 0) -> +--+----+-------->
-% | | |
-% | | v Descent (usually < 0)
-% (x1 y1) --> +----+ - -
-
- FontBBox % -- x1 y1 x2 y2
- FontMatrix transform /Ascent exch def pop
- FontMatrix transform /Descent exch def pop
- /FontHeight Ascent Descent sub def % use `sub' because descent < 0
-
- % Define these in case they're not in the FontInfo
- % (also, here they're easier to get to.
- /UnderlinePosition 1 def
- /UnderlineThickness 1 def
-
- % Get the underline position and thickness if they're defined.
- currentdict /FontInfo known {
- FontInfo
-
- dup /UnderlinePosition known {
- dup /UnderlinePosition get
- 0 exch FontMatrix transform exch pop
- /UnderlinePosition exch def
- } if
-
- dup /UnderlineThickness known {
- /UnderlineThickness get
- 0 exch FontMatrix transform exch pop
- /UnderlineThickness exch def
- } if
-
- } if
-
- currentdict % Leave the new font on the stack
- end % Stop using the font as the current dictionary.
- definefont % Put the font into the font dictionary
- pop % Discard the returned font.
-} bind def
-
-/DefFont { % Font definition
- findfont exch scalefont reencodeFontISO
-} def
-
-/F { % Font selection
- findfont
- dup /Ascent get /Ascent exch def
- dup /Descent get /Descent exch def
- dup /FontHeight get /FontHeight exch def
- dup /UnderlinePosition get /UnderlinePosition exch def
- dup /UnderlineThickness get /UnderlineThickness exch def
- setfont
-} def
-
-/FG /setrgbcolor load def
-
-/bg false def
-/BG {
- dup /bg exch def
- { mark 4 1 roll ] /bgcolor exch def } if
-} def
-
-% B width C
-% +-----------+
-% | Ascent (usually > 0)
-% A + +
-% | Descent (usually < 0)
-% +-----------+
-% E width D
-
-/dobackground { % width --
- currentpoint % -- width x y
- gsave
- newpath
- moveto % A (x y)
- 0 Ascent rmoveto % B
- dup 0 rlineto % C
- 0 Descent Ascent sub rlineto % D
- neg 0 rlineto % E
- closepath
- bgcolor aload pop setrgbcolor
- fill
- grestore
-} def
-
-/dobackgroundstring { % string --
- stringwidth pop
- dobackground
-} def
-
-/dounderline { % fromx fromy --
- currentpoint
- gsave
- UnderlineThickness setlinewidth
- 4 2 roll
- UnderlinePosition add moveto
- UnderlinePosition add lineto
- stroke
- grestore
-} def
-
-/eolbg { % dobackground until right margin
- PrintWidth % -- x-eol
- currentpoint pop % -- cur-x
- sub % -- width until eol
- dobackground
-} def
-
-/eolul { % idem for underline
- PrintWidth % -- x-eol
- currentpoint exch pop % -- x-eol cur-y
- dounderline
-} def
-
-/SL { % Soft Linefeed
- bg { eolbg } if
- ul { eolul } if
- 0 currentpoint exch pop LineHeight sub moveto
-} def
-
-/HL /SL load def % Hard Linefeed
-
-/sp1 { currentpoint 3 -1 roll } def
-
-% Some debug
-/dcp { currentpoint exch 40 string cvs print (, ) print = } def
-/dp { print 2 copy
- exch 40 string cvs print (, ) print = } def
-
-/S {
- bg { dup dobackgroundstring } if
- ul { sp1 } if
- show
- ul { dounderline } if
-} def
-
-/W {
- ul { sp1 } if
- ( ) stringwidth % Get the width of a space in the current font.
- pop % Discard the Y component.
- mul % Multiply the width of a space
- % by the number of spaces to plot
- bg { dup dobackground } if
- 0 rmoveto
- ul { dounderline } if
-} def
-
-/BeginDoc {
- % ---- save the state of the document (useful for ghostscript!)
- /docState save def
- % ---- [jack] Kludge: my ghostscript window is 21x27.7 instead of 21x29.7
- /JackGhostscript where {
- pop 1 27.7 29.7 div scale
- } if
- LandscapeMode {
- % ---- translate to bottom-right corner of Portrait page
- LandscapePageHeight 0 translate
- 90 rotate
- } if
- /ColumnWidth PrintWidth InterColumn add def
- % ---- translate to lower left corner of TEXT
- LeftMargin BottomMargin translate
- % ---- define where printing will start
- /f0 F % this installs Ascent
- /PrintStartY PrintHeight Ascent sub def
- /ColumnIndex 1 def
-} def
-
-/EndDoc {
- % ---- on last page but not last column, spit out the page
- ColumnIndex 1 eq not { showpage } if
- % ---- restore the state of the document (useful for ghostscript!)
- docState restore
-} def
-
-/BeginDSCPage {
- % ---- when 1st column, save the state of the page
- ColumnIndex 1 eq { /pageState save def } if
- % ---- save the state of the column
- /columnState save def
-} def
-
-/BeginPage {
- PrintHeader {
- PrintHeaderFrame { HeaderFrame } if
- HeaderText
- } if
- 0 PrintStartY moveto % move to where printing will start
-} def
-
-/EndPage {
- bg { eolbg } if
- ul { eolul } if
-} def
-
-/EndDSCPage {
- ColumnIndex NumberOfColumns eq {
- % ---- on last column, spit out the page
- showpage
- % ---- restore the state of the page
- pageState restore
- /ColumnIndex 1 def
- } { % else
- % ---- restore the state of the current column
- columnState restore
- % ---- and translate to the next column
- ColumnWidth 0 translate
- /ColumnIndex ColumnIndex 1 add def
- } ifelse
-} def
-
-/ul false def
-
-/UL { /ul exch def } def
-
-/SetHeaderLines { % nb-lines --
- /HeaderLines exch def
- % ---- bottom up
- HeaderPad
- HeaderLines 1 sub HeaderLineHeight mul add
- HeaderTitleLineHeight add
- HeaderPad add
- /HeaderHeight exch def
-} def
-
-% |---------|
-% | tm |
-% |---------|
-% | header |
-% |-+-------| <-- (x y)
-% | ho |
-% |---------|
-% | text |
-% |-+-------| <-- (0 0)
-% | bm |
-% |---------|
-
-/HeaderFrameStart { % -- x y
- 0 PrintHeight HeaderOffset add
-} def
-
-/HeaderFramePath {
- PrintWidth 0 rlineto
- 0 HeaderHeight rlineto
- PrintWidth neg 0 rlineto
- 0 HeaderHeight neg rlineto
-} def
-
-/HeaderFrame {
- gsave
- 0.4 setlinewidth
- % ---- fill a black rectangle (the shadow of the next one)
- HeaderFrameStart moveto
- 1 -1 rmoveto
- HeaderFramePath
- 0 setgray fill
- % ---- do the next rectangle ...
- HeaderFrameStart moveto
- HeaderFramePath
- gsave 0.9 setgray fill grestore % filled with grey
- gsave 0 setgray stroke grestore % drawn with black
- grestore
-} def
-
-/HeaderStart {
- HeaderFrameStart
- exch HeaderPad add exch % horizontal pad
- % ---- bottom up
- HeaderPad add % vertical pad
- HeaderDescent sub
- HeaderLineHeight HeaderLines 1 sub mul add
-} def
-
-/strcat {
- dup length 3 -1 roll dup length dup 4 -1 roll add string dup
- 0 5 -1 roll putinterval
- dup 4 2 roll exch putinterval
-} def
-
-/pagenumberstring {
- PageNumber 32 string cvs
- ShowNofN {
- (/) strcat
- PageCount 32 string cvs strcat
- } if
-} def
-
-/HeaderText {
- HeaderStart moveto
-
- HeaderLinesRight HeaderLinesLeft % -- rightLines leftLines
-
- % ---- hack: `PN 1 and' == `PN 2 modulo'
-
- % ---- if duplex and even page number, then exchange left and right
- Duplex PageNumber 1 and 0 eq and { exch } if
-
- { % ---- process the left lines
- aload pop
- exch F
- gsave
- dup xcheck { exec } if
- show
- grestore
- 0 HeaderLineHeight neg rmoveto
- } forall
-
- HeaderStart moveto
-
- { % ---- process the right lines
- aload pop
- exch F
- gsave
- dup xcheck { exec } if
- dup stringwidth pop
- PrintWidth exch sub HeaderPad 2 mul sub 0 rmoveto
- show
- grestore
- 0 HeaderLineHeight neg rmoveto
- } forall
-} def
-
-/ReportFontInfo {
- 2 copy
- /t0 3 1 roll DefFont
- /t0 F
- /lh FontHeight def
- /sw ( ) stringwidth pop def
- /aw (01234567890abcdefghijklmnopqrstuvwxyz) dup length exch
- stringwidth pop exch div def
- /t1 12 /Helvetica-Oblique DefFont
- /t1 F
- gsave
- (For ) show
- 128 string cvs show
- ( ) show
- 32 string cvs show
- ( point, the line height is ) show
- lh 32 string cvs show
- (, the space width is ) show
- sw 32 string cvs show
- (,) show
- grestore
- 0 FontHeight neg rmoveto
- gsave
- (and a crude estimate of average character width is ) show
- aw 32 string cvs show
- (.) show
- grestore
- 0 FontHeight neg rmoveto
-} def
-
-/cm { % cm to point
- 72 mul 2.54 div
-} def
-
-/ReportAllFontInfo {
- FontDirectory
- { % key = font name value = font dictionary
- pop 10 exch ReportFontInfo
- } forall
-} def
-
-% 3 cm 20 cm moveto 10 /Courier ReportFontInfo showpage
-% 3 cm 20 cm moveto ReportAllFontInfo showpage
-
-")
-
-(defvar ps-print-prologue-2
- "
-% ---- These lines must be kept together because...
-
-/h0 F
-/HeaderTitleLineHeight FontHeight def
-
-/h1 F
-/HeaderLineHeight FontHeight def
-/HeaderDescent Descent def
-
-% ---- ...because `F' has a side-effect on `FontHeight' and `Descent'
-
-")
-
-;; Start Editing Here:
-
-(defvar ps-source-buffer nil)
-(defvar ps-spool-buffer-name "*PostScript*")
-(defvar ps-spool-buffer nil)
-
-(defvar ps-output-head nil)
-(defvar ps-output-tail nil)
-
-(defvar ps-page-count 0)
-(defvar ps-showpage-count 0)
-
-(defvar ps-current-font 0)
-(defvar ps-current-underline-p nil)
-(defvar ps-default-color (if ps-print-color-p ps-default-fg)) ; black
-(defvar ps-current-color ps-default-color)
-(defvar ps-current-bg nil)
-
-(defvar ps-razchunk 0)
-
-(defvar ps-color-format
- (if (eq ps-print-emacs-type 'emacs)
-
- ;;Emacs understands the %f format; we'll
- ;;use it to limit color RGB values to
- ;;three decimals to cut down some on the
- ;;size of the PostScript output.
- "%0.3f %0.3f %0.3f"
-
- ;; Lucid emacsen will have to make do with
- ;; %s (princ) for floats.
- "%s %s %s"))
-
-;; These values determine how much print-height to deduct when headers
-;; are turned on. This is a pretty clumsy way of handling it, but
-;; it'll do for now.
-
-(defvar ps-header-font)
-(defvar ps-header-title-font)
-
-(defvar ps-header-line-height)
-(defvar ps-header-title-line-height)
-(defvar ps-header-pad 0
- "Vertical and horizontal space in points (1/72 inch) between the header frame
-and the text it contains.")
-
-;; Define accessors to the dimensions list.
-
-(defmacro ps-page-dimensions-get-width (dims) `(nth 0 ,dims))
-(defmacro ps-page-dimensions-get-height (dims) `(nth 1 ,dims))
-
-(defvar ps-landscape-page-height)
-
-(defvar ps-print-width nil)
-(defvar ps-print-height nil)
-
-(defvar ps-height-remaining)
-(defvar ps-width-remaining)
-
-(defvar ps-ref-bold-faces nil)
-(defvar ps-ref-italic-faces nil)
-(defvar ps-ref-underlined-faces nil)
-
-(defvar ps-print-color-scale nil)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Internal functions
-
-(defun ps-line-lengths-internal ()
- "Display the correspondance between a line length and a font size,
-using the current ps-print setup.
-Try: pr -t file | awk '{printf \"%3d %s\n\", length($0), $0}' | sort -r | head"
- (let ((buf (get-buffer-create "*Line-lengths*"))
- (ifs ps-font-size) ; initial font size
- (icw ps-avg-char-width) ; initial character width
- (print-width (progn (ps-get-page-dimensions)
- ps-print-width))
- (ps-setup (ps-setup)) ; setup for the current buffer
- (fs-min 5) ; minimum font size
- cw-min ; minimum character width
- nb-cpl-max ; maximum nb of characters per line
- (fs-max 14) ; maximum font size
- cw-max ; maximum character width
- nb-cpl-min ; minimum nb of characters per line
- fs ; current font size
- cw ; current character width
- nb-cpl ; current nb of characters per line
- )
- (setq cw-min (/ (* icw fs-min) ifs)
- nb-cpl-max (floor (/ print-width cw-min))
- cw-max (/ (* icw fs-max) ifs)
- nb-cpl-min (floor (/ print-width cw-max)))
- (setq nb-cpl nb-cpl-min)
- (set-buffer buf)
- (goto-char (point-max))
- (if (not (bolp)) (insert "\n"))
- (insert ps-setup)
- (insert "nb char per line / font size\n")
- (while (<= nb-cpl nb-cpl-max)
- (setq cw (/ print-width (float nb-cpl))
- fs (/ (* ifs cw) icw))
- (insert (format "%3s %s\n" nb-cpl fs))
- (setq nb-cpl (1+ nb-cpl)))
- (insert "\n")
- (display-buffer buf 'not-this-window)))
-
-(defun ps-nb-pages (nb-lines)
- "Display an approximate correspondance between a font size and the number
-of pages the number of lines would require to print
-using the current ps-print setup."
- (let ((buf (get-buffer-create "*Nb-Pages*"))
- (ifs ps-font-size) ; initial font size
- (ilh ps-line-height) ; initial line height
- (page-height (progn (ps-get-page-dimensions)
- ps-print-height))
- (ps-setup (ps-setup)) ; setup for the current buffer
- (fs-min 4) ; minimum font size
- lh-min ; minimum line height
- nb-lpp-max ; maximum nb of lines per page
- nb-page-min ; minimum nb of pages
- (fs-max 14) ; maximum font size
- lh-max ; maximum line height
- nb-lpp-min ; minimum nb of lines per page
- nb-page-max ; maximum nb of pages
- fs ; current font size
- lh ; current line height
- nb-lpp ; current nb of lines per page
- nb-page ; current nb of pages
- )
- (setq lh-min (/ (* ilh fs-min) ifs)
- nb-lpp-max (floor (/ page-height lh-min))
- nb-page-min (ceiling (/ (float nb-lines) nb-lpp-max))
- lh-max (/ (* ilh fs-max) ifs)
- nb-lpp-min (floor (/ page-height lh-max))
- nb-page-max (ceiling (/ (float nb-lines) nb-lpp-min)))
- (setq nb-page nb-page-min)
- (set-buffer buf)
- (goto-char (point-max))
- (if (not (bolp)) (insert "\n"))
- (insert ps-setup)
- (insert (format "%d lines\n" nb-lines))
- (insert "nb page / font size\n")
- (while (<= nb-page nb-page-max)
- (setq nb-lpp (ceiling (/ nb-lines (float nb-page)))
- lh (/ page-height nb-lpp)
- fs (/ (* ifs lh) ilh))
- (insert (format "%s %s\n" nb-page fs))
- (setq nb-page (1+ nb-page)))
- (insert "\n")
- (display-buffer buf 'not-this-window)))
-
-(defun ps-select-font ()
- "Choose the font name and size (scaling data)."
- (let ((assoc (assq ps-font-family ps-font-info-database))
- l fn fb fi bi sz lh sw aw)
- (if (null assoc)
- (error "Don't have data to scale font %s. Known fonts families are %s"
- ps-font-family
- (mapcar 'car ps-font-info-database)))
- (setq l (cdr assoc)
- fn (prog1 (car l) (setq l (cdr l))) ; need `pop'
- fb (prog1 (car l) (setq l (cdr l)))
- fi (prog1 (car l) (setq l (cdr l)))
- bi (prog1 (car l) (setq l (cdr l)))
- sz (prog1 (car l) (setq l (cdr l)))
- lh (prog1 (car l) (setq l (cdr l)))
- sw (prog1 (car l) (setq l (cdr l)))
- aw (prog1 (car l) (setq l (cdr l))))
-
- (setq ps-font fn)
- (setq ps-font-bold fb)
- (setq ps-font-italic fi)
- (setq ps-font-bold-italic bi)
- ;; These data just need to be rescaled:
- (setq ps-line-height (/ (* lh ps-font-size) sz))
- (setq ps-space-width (/ (* sw ps-font-size) sz))
- (setq ps-avg-char-width (/ (* aw ps-font-size) sz))
- ps-font-family))
-
-(defun ps-select-header-font ()
- "Choose the font name and size (scaling data) for the header."
- (let ((assoc (assq ps-header-font-family ps-font-info-database))
- l fn fb fi bi sz lh sw aw)
- (if (null assoc)
- (error "Don't have data to scale font %s. Known fonts families are %s"
- ps-font-family
- (mapcar 'car ps-font-info-database)))
- (setq l (cdr assoc)
- fn (prog1 (car l) (setq l (cdr l))) ; need `pop'
- fb (prog1 (car l) (setq l (cdr l)))
- fi (prog1 (car l) (setq l (cdr l)))
- bi (prog1 (car l) (setq l (cdr l)))
- sz (prog1 (car l) (setq l (cdr l)))
- lh (prog1 (car l) (setq l (cdr l)))
- sw (prog1 (car l) (setq l (cdr l)))
- aw (prog1 (car l) (setq l (cdr l))))
-
- ;; Font name
- (setq ps-header-font fn)
- (setq ps-header-title-font fb)
- ;; Line height: These data just need to be rescaled:
- (setq ps-header-title-line-height (/ (* lh ps-header-title-font-size) sz))
- (setq ps-header-line-height (/ (* lh ps-header-font-size) sz))
- ps-header-font-family))
-
-(defun ps-get-page-dimensions ()
- (let ((page-dimensions (cdr (assq ps-paper-type ps-page-dimensions-database)))
- page-width page-height)
- (cond
- ((null page-dimensions)
- (error "`ps-paper-type' must be one of:\n%s"
- (mapcar 'car ps-page-dimensions-database)))
- ((< ps-number-of-columns 1)
- (error "The number of columns %d should not be negative")))
-
- (ps-select-font)
- (ps-select-header-font)
-
- (setq page-width (ps-page-dimensions-get-width page-dimensions)
- page-height (ps-page-dimensions-get-height page-dimensions))
-
- ;; Landscape mode
- (if ps-landscape-mode
- ;; exchange width and height
- (setq page-width (prog1 page-height (setq page-height page-width))))
-
- ;; It is used to get the lower right corner (only in landscape mode)
- (setq ps-landscape-page-height page-height)
-
- ;; | lm | text | ic | text | ic | text | rm |
- ;; page-width == lm + n * pw + (n - 1) * ic + rm
- ;; => pw == (page-width - lm -rm - (n - 1) * ic) / n
- (setq ps-print-width
- (/ (- page-width
- ps-left-margin ps-right-margin
- (* (1- ps-number-of-columns) ps-inter-column))
- ps-number-of-columns))
- (if (<= ps-print-width 0)
- (error "Bad horizontal layout:
-page-width == %s
-ps-left-margin == %s
-ps-right-margin == %s
-ps-inter-column == %s
-ps-number-of-columns == %s
-| lm | text | ic | text | ic | text | rm |
-page-width == lm + n * print-width + (n - 1) * ic + rm
-=> print-width == %d !"
- page-width
- ps-left-margin
- ps-right-margin
- ps-inter-column
- ps-number-of-columns
- ps-print-width))
-
- (setq ps-print-height
- (- page-height ps-bottom-margin ps-top-margin))
- (if (<= ps-print-height 0)
- (error "Bad vertical layout:
-ps-top-margin == %s
-ps-bottom-margin == %s
-page-height == bm + print-height + tm
-=> print-height == %d !"
- ps-top-margin
- ps-bottom-margin
- ps-print-height))
- ;; If headers are turned on, deduct the height of the header from
- ;; the print height.
- (cond
- (ps-print-header
- (setq ps-header-pad
- (* ps-header-line-pad ps-header-title-line-height))
- (setq ps-print-height
- (- ps-print-height
- ps-header-offset
- ps-header-pad
- ps-header-title-line-height
- (* ps-header-line-height (- ps-header-lines 1))
- ps-header-pad))))
- (if (<= ps-print-height 0)
- (error "Bad vertical layout:
-ps-top-margin == %s
-ps-bottom-margin == %s
-ps-header-offset == %s
-ps-header-pad == %s
-header-height == %s
-page-height == bm + print-height + tm - ho - hh
-=> print-height == %d !"
- ps-top-margin
- ps-bottom-margin
- ps-header-offset
- ps-header-pad
- (+ ps-header-pad
- ps-header-title-line-height
- (* ps-header-line-height (- ps-header-lines 1))
- ps-header-pad)
- ps-print-height))))
-
-(defun ps-print-preprint (&optional filename)
- (if (and filename
- (or (numberp filename)
- (listp filename)))
- (let* ((name (concat (buffer-name) ".ps"))
- (prompt (format "Save PostScript to file: (default %s) "
- name))
- (res (read-file-name prompt default-directory name nil)))
- (if (file-directory-p res)
- (expand-file-name name (file-name-as-directory res))
- res))))
-
-;; The following functions implement a simple list-buffering scheme so
-;; that ps-print doesn't have to repeatedly switch between buffers
-;; while spooling. The functions ps-output and ps-output-string build
-;; up the lists; the function ps-flush-output takes the lists and
-;; insert its contents into the spool buffer (*PostScript*).
-
-(defun ps-output-string-prim (string)
- (insert "(") ;insert start-string delimiter
- (save-excursion ;insert string
- (insert string))
-
- ;; Find and quote special characters as necessary for PS
- (while (re-search-forward "[()\\]" nil t)
- (save-excursion
- (forward-char -1)
- (insert "\\")))
-
- (goto-char (point-max))
- (insert ")")) ;insert end-string delimiter
-
-(defun ps-init-output-queue ()
- (setq ps-output-head (list ""))
- (setq ps-output-tail ps-output-head))
-
-(defun ps-output (&rest args)
- (setcdr ps-output-tail args)
- (while (cdr ps-output-tail)
- (setq ps-output-tail (cdr ps-output-tail))))
-
-(defun ps-output-string (string)
- (ps-output t string))
-
-(defun ps-flush-output ()
- (save-excursion
- (set-buffer ps-spool-buffer)
- (goto-char (point-max))
- (while ps-output-head
- (let ((it (car ps-output-head)))
- (if (not (eq t it))
- (insert it)
- (setq ps-output-head (cdr ps-output-head))
- (ps-output-string-prim (car ps-output-head))))
- (setq ps-output-head (cdr ps-output-head))))
- (ps-init-output-queue))
-
-(defun ps-insert-file (fname)
- (ps-flush-output)
-
- ;; Check to see that the file exists and is readable; if not, throw
- ;; and error.
- (if (not (file-readable-p fname))
- (error "Could not read file `%s'" fname))
-
- (save-excursion
- (set-buffer ps-spool-buffer)
- (goto-char (point-max))
- (insert-file fname)))
-
-;; These functions insert the arrays that define the contents of the
-;; headers.
-
-(defun ps-generate-header-line (fonttag &optional content)
- (ps-output " [ " fonttag " ")
- (cond
- ;; Literal strings should be output as is -- the string must
- ;; contain its own PS string delimiters, '(' and ')', if necessary.
- ((stringp content)
- (ps-output content))
-
- ;; Functions are called -- they should return strings; they will be
- ;; inserted as strings and the PS string delimiters added.
- ((and (symbolp content) (fboundp content))
- (ps-output-string (funcall content)))
-
- ;; Variables will have their contents inserted. They should
- ;; contain strings, and will be inserted as strings.
- ((and (symbolp content) (boundp content))
- (ps-output-string (symbol-value content)))
-
- ;; Anything else will get turned into an empty string.
- (t
- (ps-output-string "")))
- (ps-output " ]\n"))
-
-(defun ps-generate-header (name contents)
- (ps-output "/" name " [\n")
- (if (> ps-header-lines 0)
- (let ((count 1))
- (ps-generate-header-line "/h0" (car contents))
- (while (and (< count ps-header-lines)
- (setq contents (cdr contents)))
- (ps-generate-header-line "/h1" (car contents))
- (setq count (+ count 1)))
- (ps-output "] def\n"))))
-
-(defun ps-output-boolean (name bool)
- (ps-output (format "/%s %s def\n" name (if bool "true" "false"))))
-
-(defun ps-begin-file ()
- (ps-get-page-dimensions)
- (setq ps-showpage-count 0)
-
- (ps-output ps-adobe-tag)
- (ps-output "%%Title: " (buffer-name) "\n") ;Take job name from name of
- ;first buffer printed
- (ps-output "%%Creator: " (user-full-name) "\n")
- (ps-output "%%CreationDate: "
- (time-stamp-hh:mm:ss) " " (time-stamp-mon-dd-yyyy) "\n")
- (ps-output "%% DocumentFonts: "
- ps-font " " ps-font-bold " " ps-font-italic " "
- ps-font-bold-italic " "
- ps-header-font " " ps-header-title-font "\n")
- (ps-output "%%Pages: (atend)\n")
- (ps-output "%%EndComments\n\n")
-
- (ps-output-boolean "LandscapeMode" ps-landscape-mode)
- (ps-output (format "/NumberOfColumns %d def\n" ps-number-of-columns))
-
- (ps-output (format "/LandscapePageHeight %s def\n" ps-landscape-page-height))
- (ps-output (format "/PrintWidth %s def\n" ps-print-width))
- (ps-output (format "/PrintHeight %s def\n" ps-print-height))
-
- (ps-output (format "/LeftMargin %s def\n" ps-left-margin))
- (ps-output (format "/RightMargin %s def\n" ps-right-margin)) ; not used
- (ps-output (format "/InterColumn %s def\n" ps-inter-column))
-
- (ps-output (format "/BottomMargin %s def\n" ps-bottom-margin))
- (ps-output (format "/TopMargin %s def\n" ps-top-margin)) ; not used
- (ps-output (format "/HeaderOffset %s def\n" ps-header-offset))
- (ps-output (format "/HeaderPad %s def\n" ps-header-pad))
-
- (ps-output-boolean "PrintHeader" ps-print-header)
- (ps-output-boolean "PrintHeaderFrame" ps-print-header-frame)
- (ps-output-boolean "ShowNofN" ps-show-n-of-n)
- (ps-output-boolean "Duplex" ps-spool-duplex)
-
- (ps-output (format "/LineHeight %s def\n" ps-line-height))
-
- (ps-output ps-print-prologue-1)
-
- ;; Header fonts
- (ps-output ; /h0 14 /Helvetica-Bold Font
- (format "/h0 %s /%s DefFont\n" ps-header-title-font-size ps-header-title-font))
- (ps-output ; /h1 12 /Helvetica Font
- (format "/h1 %s /%s DefFont\n" ps-header-font-size ps-header-font))
-
- (ps-output ps-print-prologue-2)
-
- ;; Text fonts
- (ps-output (format "/f0 %s /%s DefFont\n" ps-font-size ps-font))
- (ps-output (format "/f1 %s /%s DefFont\n" ps-font-size ps-font-bold))
- (ps-output (format "/f2 %s /%s DefFont\n" ps-font-size ps-font-italic))
- (ps-output (format "/f3 %s /%s DefFont\n" ps-font-size ps-font-bold-italic))
-
- (ps-output "\nBeginDoc\n\n")
- (ps-output "%%EndPrologue\n"))
-
-(defun ps-header-dirpart ()
- (let ((fname (buffer-file-name)))
- (if fname
- (if (string-equal (buffer-name) (file-name-nondirectory fname))
- (file-name-directory fname)
- fname)
- "")))
-
-(defun ps-get-buffer-name ()
- (cond
- ;; Indulge Jim this little easter egg:
- ((string= (buffer-name) "ps-print.el")
- "Hey, Cool! It's ps-print.el!!!")
- ;; Indulge Jack this other little easter egg:
- ((string= (buffer-name) "sokoban.el")
- "Super! C'est sokoban.el!")
- (t (buffer-name))))
-
-(defun ps-begin-job ()
- (setq ps-page-count 0))
-
-(defun ps-end-file ()
- (ps-output "\nEndDoc\n\n")
- (ps-output "%%Trailer\n")
- (ps-output "%%Pages: " (format "%d\n" ps-showpage-count)))
-
-(defun ps-next-page ()
- (ps-end-page)
- (ps-flush-output)
- (ps-begin-page))
-
-(defun ps-begin-page (&optional dummypage)
- (ps-get-page-dimensions)
- (setq ps-width-remaining ps-print-width)
- (setq ps-height-remaining ps-print-height)
-
- (setq ps-page-count (+ ps-page-count 1))
-
- (ps-output "\n%%Page: "
- (format "%d %d\n" ps-page-count (+ 1 ps-showpage-count)))
- (ps-output "BeginDSCPage\n")
- (ps-output (format "/PageNumber %d def\n" ps-page-count))
- (ps-output "/PageCount 0 def\n")
-
- (if ps-print-header
- (progn
- (ps-generate-header "HeaderLinesLeft" ps-left-header)
- (ps-generate-header "HeaderLinesRight" ps-right-header)
- (ps-output (format "%d SetHeaderLines\n" ps-header-lines))))
-
- (ps-output "BeginPage\n")
- (ps-set-font ps-current-font)
- (ps-set-bg ps-current-bg)
- (ps-set-color ps-current-color)
- (ps-set-underline ps-current-underline-p))
-
-(defun ps-end-page ()
- (setq ps-showpage-count (+ 1 ps-showpage-count))
- (ps-output "EndPage\n")
- (ps-output "EndDSCPage\n"))
-
-(defun ps-dummy-page ()
- (setq ps-showpage-count (+ 1 ps-showpage-count))
- (ps-output "%%Page: " (format "- %d\n" ps-showpage-count)
- "BeginDSCPage
-/PrintHeader false def
-BeginPage
-EndPage
-EndDSCPage\n"))
-
-(defun ps-next-line ()
- (if (< ps-height-remaining ps-line-height)
- (ps-next-page)
- (setq ps-width-remaining ps-print-width)
- (setq ps-height-remaining (- ps-height-remaining ps-line-height))
- (ps-hard-lf)))
-
-(defun ps-continue-line ()
- (if (< ps-height-remaining ps-line-height)
- (ps-next-page)
- (setq ps-width-remaining ps-print-width)
- (setq ps-height-remaining (- ps-height-remaining ps-line-height))
- (ps-soft-lf)))
-
-;; [jack] Why hard and soft ?
-
-(defun ps-hard-lf ()
- (ps-output "HL\n"))
-
-(defun ps-soft-lf ()
- (ps-output "SL\n"))
-
-(defun ps-find-wrappoint (from to char-width)
- (let ((avail (truncate (/ ps-width-remaining char-width)))
- (todo (- to from)))
- (if (< todo avail)
- (cons to (* todo char-width))
- (cons (+ from avail) ps-width-remaining))))
-
-(defun ps-basic-plot-string (from to &optional bg-color)
- (let* ((wrappoint (ps-find-wrappoint from to ps-avg-char-width))
- (to (car wrappoint))
- (string (buffer-substring from to)))
- (ps-output-string string)
- (ps-output " S\n")
- wrappoint))
-
-(defun ps-basic-plot-whitespace (from to &optional bg-color)
- (let* ((wrappoint (ps-find-wrappoint from to ps-space-width))
- (to (car wrappoint)))
-
- (ps-output (format "%d W\n" (- to from)))
- wrappoint))
-
-(defun ps-plot (plotfunc from to &optional bg-color)
- (while (< from to)
- (let* ((wrappoint (funcall plotfunc from to bg-color))
- (plotted-to (car wrappoint))
- (plotted-width (cdr wrappoint)))
- (setq from plotted-to)
- (setq ps-width-remaining (- ps-width-remaining plotted-width))
- (if (< from to)
- (ps-continue-line))))
- (if ps-razzle-dazzle
- (let* ((q-todo (- (point-max) (point-min)))
- (q-done (- (point) (point-min)))
- (chunkfrac (/ q-todo 8))
- (chunksize (if (> chunkfrac 1000) 1000 chunkfrac)))
- (if (> (- q-done ps-razchunk) chunksize)
- (let (foo)
- (setq ps-razchunk q-done)
- (setq foo
- (if (< q-todo 100)
- (/ (* 100 q-done) q-todo)
- (/ q-done (/ q-todo 100))))
- (message "Formatting...%d%%" foo))))))
-
-(defun ps-set-font (font)
- (setq ps-current-font font)
- (ps-output (format "/f%d F\n" ps-current-font)))
-
-(defun ps-set-bg (color)
- (if (setq ps-current-bg color)
- (ps-output (format ps-color-format (nth 0 color) (nth 1 color)
- (nth 2 color))
- " true BG\n")
- (ps-output "false BG\n")))
-
-(defun ps-set-color (color)
- (if (setq ps-current-color color)
- nil
- (setq ps-current-color ps-default-fg))
- (ps-output (format ps-color-format (nth 0 ps-current-color)
- (nth 1 ps-current-color) (nth 2 ps-current-color))
- " FG\n"))
-
-(defun ps-set-underline (underline-p)
- (ps-output (if underline-p "true" "false") " UL\n")
- (setq ps-current-underline-p underline-p))
-
-(defun ps-plot-region (from to font fg-color &optional bg-color underline-p)
-
- (if (not (equal font ps-current-font))
- (ps-set-font font))
-
- ;; Specify a foreground color only if one's specified and it's
- ;; different than the current.
- (if (not (equal fg-color ps-current-color))
- (ps-set-color fg-color))
-
- (if (not (equal bg-color ps-current-bg))
- (ps-set-bg bg-color))
-
- ;; Toggle underlining if different.
- (if (not (equal underline-p ps-current-underline-p))
- (ps-set-underline underline-p))
-
- ;; Starting at the beginning of the specified region...
- (save-excursion
- (goto-char from)
-
- ;; ...break the region up into chunks separated by tabs, linefeeds,
- ;; and pagefeeds, and plot each chunk.
- (while (< from to)
- (if (re-search-forward "[\t\n\f]" to t)
- (let ((match (char-after (match-beginning 0))))
- (cond
- ((= match ?\t)
- (let ((linestart
- (save-excursion (beginning-of-line) (point))))
- (ps-plot 'ps-basic-plot-string from (- (point) 1)
- bg-color)
- (forward-char -1)
- (setq from (+ linestart (current-column)))
- (if (re-search-forward "[ \t]+" to t)
- (ps-plot 'ps-basic-plot-whitespace
- from (+ linestart (current-column))
- bg-color))))
-
- ((= match ?\n)
- (ps-plot 'ps-basic-plot-string from (- (point) 1)
- bg-color)
- (ps-next-line)
- )
-
- ((= match ?\f)
- (ps-plot 'ps-basic-plot-string from (- (point) 1)
- bg-color)
- (ps-next-page)))
- (setq from (point)))
- (ps-plot 'ps-basic-plot-string from to bg-color)
- (setq from to)))))
-
-(defun ps-color-value (x-color-value)
- ;; Scale 16-bit X-COLOR-VALUE to PostScript color value in [0, 1] interval.
- (/ x-color-value ps-print-color-scale))
-
-(defun ps-color-values (x-color)
- (cond ((fboundp 'x-color-values)
- (x-color-values x-color))
- ((fboundp 'pixel-components)
- (pixel-components x-color))
- (t (error "No available function to determine X color values."))))
-
-(defun ps-face-attributes (face)
- (let ((differs (face-differs-from-default-p face)))
- (list (memq face ps-ref-bold-faces)
- (memq face ps-ref-italic-faces)
- (memq face ps-ref-underlined-faces)
- (and differs (face-foreground face))
- (and differs (face-background face)))))
-
-(defun ps-face-attribute-list (face-or-list)
- (if (listp face-or-list)
- (let (bold-p italic-p underline-p foreground background face-attr face)
- (while face-or-list
- (setq face (car face-or-list))
- (setq face-attr (ps-face-attributes face))
- (setq bold-p (or bold-p (nth 0 face-attr)))
- (setq italic-p (or italic-p (nth 1 face-attr)))
- (setq underline-p (or underline-p (nth 2 face-attr)))
- (if foreground
- nil
- (setq foreground (nth 3 face-attr)))
- (if background
- nil
- (setq background (nth 4 face-attr)))
- (setq face-or-list (cdr face-or-list)))
- (list bold-p italic-p underline-p foreground background))
-
- (ps-face-attributes face-or-list)))
-
-(defun ps-plot-with-face (from to face)
- (if face
- (let* ((face-attr (ps-face-attribute-list face))
- (bold-p (nth 0 face-attr))
- (italic-p (nth 1 face-attr))
- (underline-p (nth 2 face-attr))
- (foreground (nth 3 face-attr))
- (background (nth 4 face-attr))
- (fg-color (if (and ps-print-color-p foreground)
- (mapcar 'ps-color-value
- (ps-color-values foreground))
- ps-default-color))
- (bg-color (if (and ps-print-color-p background)
- (mapcar 'ps-color-value
- (ps-color-values background)))))
- (ps-plot-region from to
- (cond ((and bold-p italic-p) 3)
- (italic-p 2)
- (bold-p 1)
- (t 0))
-; (or fg-color '(0.0 0.0 0.0))
- fg-color
- bg-color underline-p))
- (goto-char to)))
-
-
-(defun ps-emacs-face-kind-p (face kind kind-regex kind-list)
- (let ((frame-font (face-font face))
- (face-defaults (face-font face t)))
- (or
- ;; Check FACE defaults:
- (and (listp face-defaults)
- (memq kind face-defaults))
-
- ;; Check the user's preferences
- (memq face kind-list))))
-
-(defun ps-xemacs-face-kind-p (face kind kind-regex kind-list)
- (let* ((frame-font (or (face-font face) (face-font 'default)))
- (kind-cons (assq kind (x-font-properties frame-font)))
- (kind-spec (cdr-safe kind-cons))
- (case-fold-search t))
-
- (or (and kind-spec (string-match kind-regex kind-spec))
- ;; Kludge-compatible:
- (memq face kind-list))))
-
-(defun ps-face-bold-p (face)
- (if (eq ps-print-emacs-type 'emacs)
- (ps-emacs-face-kind-p face 'bold "-\\(bold\\|demibold\\)-"
- ps-bold-faces)
- (ps-xemacs-face-kind-p face 'WEIGHT_NAME "bold\\|demibold"
- ps-bold-faces)))
-
-(defun ps-face-italic-p (face)
- (if (eq ps-print-emacs-type 'emacs)
- (ps-emacs-face-kind-p face 'italic "-[io]-" ps-italic-faces)
- (or
- (ps-xemacs-face-kind-p face 'ANGLE_NAME "i\\|o" ps-italic-faces)
- (ps-xemacs-face-kind-p face 'SLANT "i\\|o" ps-italic-faces))))
-
-(defun ps-face-underlined-p (face)
- (or (face-underline-p face)
- (memq face ps-underlined-faces)))
-
-;; Ensure that face-list is fbound.
-(or (fboundp 'face-list) (defalias 'face-list 'list-faces))
-
-(defun ps-build-reference-face-lists ()
- (if ps-auto-font-detect
- (let ((faces (face-list))
- the-face)
- (setq ps-ref-bold-faces nil
- ps-ref-italic-faces nil
- ps-ref-underlined-faces nil)
- (while faces
- (setq the-face (car faces))
- (if (ps-face-italic-p the-face)
- (setq ps-ref-italic-faces
- (cons the-face ps-ref-italic-faces)))
- (if (ps-face-bold-p the-face)
- (setq ps-ref-bold-faces
- (cons the-face ps-ref-bold-faces)))
- (if (ps-face-underlined-p the-face)
- (setq ps-ref-underlined-faces
- (cons the-face ps-ref-underlined-faces)))
- (setq faces (cdr faces))))
- (setq ps-ref-bold-faces ps-bold-faces)
- (setq ps-ref-italic-faces ps-italic-faces)
- (setq ps-ref-underlined-faces ps-underlined-faces))
- (setq ps-build-face-reference nil))
-
-(defun ps-mapper (extent list)
- (nconc list (list (list (extent-start-position extent) 'push extent)
- (list (extent-end-position extent) 'pull extent)))
- nil)
-
-(defun ps-sorter (a b)
- (< (car a) (car b)))
-
-(defun ps-extent-sorter (a b)
- (< (extent-priority a) (extent-priority b)))
-
-(defun ps-print-ensure-fontified (start end)
- (if (and (boundp 'lazy-lock-mode) lazy-lock-mode)
- (if (fboundp 'lazy-lock-fontify-region)
- (lazy-lock-fontify-region start end) ; the new
- (lazy-lock-fontify-buffer)))) ; the old
-
-(defun ps-generate-postscript-with-faces (from to)
- ;; Build the reference lists of faces if necessary.
- (if (or ps-always-build-face-reference
- ps-build-face-reference)
- (progn
- (message "Collecting face information...")
- (ps-build-reference-face-lists)))
- ;; Set the color scale. We do it here instead of in the defvar so
- ;; that ps-print can be dumped into emacs. This expression can't be
- ;; evaluated at dump-time because X isn't initialized.
- (setq ps-print-color-scale
- (if ps-print-color-p
- (float (car (ps-color-values "white")))
- 1.0))
- ;; Generate some PostScript.
- (save-restriction
- (narrow-to-region from to)
- (let ((face 'default)
- (position to))
- (ps-print-ensure-fontified from to)
- (cond ((or (eq ps-print-emacs-type 'lucid)
- (eq ps-print-emacs-type 'xemacs))
- ;; Build the list of extents...
- (let ((a (cons 'dummy nil))
- record type extent extent-list)
- (map-extents 'ps-mapper nil from to a)
- (setq a (cdr a))
- (setq a (sort a 'ps-sorter))
-
- (setq extent-list nil)
-
- ;; Loop through the extents...
- (while a
- (setq record (car a))
-
- (setq position (car record))
- (setq record (cdr record))
-
- (setq type (car record))
- (setq record (cdr record))
-
- (setq extent (car record))
-
- ;; Plot up to this record.
- ;; XEmacs 19.12: for some reason, we're getting into a
- ;; situation in which some of the records have
- ;; positions less than 'from'. Since we've narrowed
- ;; the buffer, this'll generate errors. This is a
- ;; hack, but don't call ps-plot-with-face unless from >
- ;; point-min.
- (if (and (>= from (point-min))
- (<= position (point-max)))
- (ps-plot-with-face from position face))
-
- (cond
- ((eq type 'push)
- (if (extent-face extent)
- (setq extent-list (sort (cons extent extent-list)
- 'ps-extent-sorter))))
-
- ((eq type 'pull)
- (setq extent-list (sort (delq extent extent-list)
- 'ps-extent-sorter))))
-
- (setq face
- (if extent-list
- (extent-face (car extent-list))
- 'default))
-
- (setq from position)
- (setq a (cdr a)))))
-
- ((eq ps-print-emacs-type 'emacs)
- (let ((property-change from)
- (overlay-change from))
- (while (< from to)
- (if (< property-change to) ; Don't search for property change
- ; unless previous search succeeded.
- (setq property-change
- (next-property-change from nil to)))
- (if (< overlay-change to) ; Don't search for overlay change
- ; unless previous search succeeded.
- (setq overlay-change
- (min (next-overlay-change from) to)))
- (setq position
- (min property-change overlay-change))
- ;; The code below is not quite correct,
- ;; because a non-nil overlay invisible property
- ;; which is inactive according to the current value
- ;; of buffer-invisibility-spec nonetheless overrides
- ;; a face text property.
- (setq face
- (cond ((let ((prop (get-text-property from 'invisible)))
- ;; Decide whether this invisible property
- ;; really makes the text invisible.
- (if (eq buffer-invisibility-spec t)
- (not (null prop))
- (or (memq prop buffer-invisibility-spec)
- (assq prop buffer-invisibility-spec))))
- nil)
- ((get-text-property from 'face))
- (t 'default)))
- (let ((overlays (overlays-at from))
- (face-priority -1)) ; text-property
- (while overlays
- (let* ((overlay (car overlays))
- (overlay-face (overlay-get overlay 'face))
- (overlay-invisible (overlay-get overlay 'invisible))
- (overlay-priority (or (overlay-get overlay
- 'priority)
- 0)))
- (if (and (or overlay-invisible overlay-face)
- (> overlay-priority face-priority))
- (setq face (cond ((if (eq buffer-invisibility-spec t)
- (not (null overlay-invisible))
- (or (memq overlay-invisible buffer-invisibility-spec)
- (assq overlay-invisible buffer-invisibility-spec)))
- nil)
- ((and face overlay-face)))
- face-priority overlay-priority)))
- (setq overlays (cdr overlays))))
- ;; Plot up to this record.
- (ps-plot-with-face from position face)
- (setq from position)))))
- (ps-plot-with-face from to face))))
-
-(defun ps-generate-postscript (from to)
- (ps-plot-region from to 0 nil))
-
-(defun ps-generate (buffer from to genfunc)
- (let ((from (min to from))
- (to (max to from))
- ;; This avoids trouble if chars with read-only properties
- ;; are copied into ps-spool-buffer.
- (inhibit-read-only t))
- (save-restriction
- (narrow-to-region from to)
- (if ps-razzle-dazzle
- (message "Formatting...%d%%" (setq ps-razchunk 0)))
- (set-buffer buffer)
- (setq ps-source-buffer buffer)
- (setq ps-spool-buffer (get-buffer-create ps-spool-buffer-name))
- (ps-init-output-queue)
- (let (safe-marker completed-safely needs-begin-file)
- (unwind-protect
- (progn
- (set-buffer ps-spool-buffer)
-
- ;; Get a marker and make it point to the current end of the
- ;; buffer, If an error occurs, we'll delete everything from
- ;; the end of this marker onwards.
- (setq safe-marker (make-marker))
- (set-marker safe-marker (point-max))
-
- (goto-char (point-min))
- (if (looking-at (regexp-quote "%!PS-Adobe-1.0"))
- nil
- (setq needs-begin-file t))
- (save-excursion
- (set-buffer ps-source-buffer)
- (if needs-begin-file (ps-begin-file))
- (ps-begin-job)
- (ps-begin-page))
- (set-buffer ps-source-buffer)
- (funcall genfunc from to)
- (ps-end-page)
-
- (if (and ps-spool-duplex
- (= (mod ps-page-count 2) 1))
- (ps-dummy-page))
- (ps-flush-output)
-
- ;; Back to the PS output buffer to set the page count
- (set-buffer ps-spool-buffer)
- (goto-char (point-max))
- (while (re-search-backward "^/PageCount 0 def$" nil t)
- (replace-match (format "/PageCount %d def" ps-page-count) t))
-
- ;; Setting this variable tells the unwind form that the
- ;; the postscript was generated without error.
- (setq completed-safely t))
-
- ;; Unwind form: If some bad mojo occurred while generating
- ;; postscript, delete all the postscript that was generated.
- ;; This protects the previously spooled files from getting
- ;; corrupted.
- (if (and (markerp safe-marker) (not completed-safely))
- (progn
- (set-buffer ps-spool-buffer)
- (delete-region (marker-position safe-marker) (point-max))))))
-
- (if ps-razzle-dazzle
- (message "Formatting...done")))))
-
-(defun ps-do-despool (filename)
- (if (or (not (boundp 'ps-spool-buffer))
- (not (symbol-value 'ps-spool-buffer)))
- (message "No spooled PostScript to print")
- (ps-end-file)
- (ps-flush-output)
- (if filename
- (save-excursion
- (if ps-razzle-dazzle
- (message "Saving..."))
- (set-buffer ps-spool-buffer)
- (setq filename (expand-file-name filename))
- (write-region (point-min) (point-max) filename)
- (if ps-razzle-dazzle
- (message "Wrote %s" filename)))
- ;; Else, spool to the printer
- (if ps-razzle-dazzle
- (message "Printing..."))
- (save-excursion
- (set-buffer ps-spool-buffer)
- (if (and (eq system-type 'ms-dos) (stringp dos-ps-printer))
- (write-region (point-min) (point-max) dos-ps-printer t 0)
- (let ((binary-process-input t)) ; for MS-DOS
- (apply 'call-process-region
- (point-min) (point-max) ps-lpr-command nil
- (if (fboundp 'start-process) 0 nil)
- nil
- ps-lpr-switches))))
- (if ps-razzle-dazzle
- (message "Printing...done")))
- (kill-buffer ps-spool-buffer)))
-
-(defun ps-kill-emacs-check ()
- (let (ps-buffer)
- (if (and (setq ps-buffer (get-buffer ps-spool-buffer-name))
- (buffer-modified-p ps-buffer))
- (if (y-or-n-p "Unprinted PostScript waiting; print now? ")
- (ps-despool)))
- (if (and (setq ps-buffer (get-buffer ps-spool-buffer-name))
- (buffer-modified-p ps-buffer))
- (if (yes-or-no-p "Unprinted PostScript waiting; exit anyway? ")
- nil
- (error "Unprinted PostScript")))))
-
-(if (fboundp 'add-hook)
- (funcall 'add-hook 'kill-emacs-hook 'ps-kill-emacs-check)
- (if kill-emacs-hook
- (message "Won't override existing kill-emacs-hook")
- (setq kill-emacs-hook 'ps-kill-emacs-check)))
-
-;;; Sample Setup Code:
-
-;; This stuff is for anybody that's brave enough to look this far,
-;; and able to figure out how to use it. It isn't really part of ps-
-;; print, but I'll leave it here in hopes it might be useful:
-
-;; WARNING!!! The following code is *sample* code only. Don't use it
-;; unless you understand what it does!
-
-(defmacro ps-prsc () (list 'if (list 'eq 'ps-print-emacs-type ''emacs)
- [f22] ''f22))
-(defmacro ps-c-prsc () (list 'if (list 'eq 'ps-print-emacs-type ''emacs)
- [C-f22]
- ''(control f22)))
-(defmacro ps-s-prsc () (list 'if (list 'eq 'ps-print-emacs-type ''emacs)
- [S-f22]
- ''(shift f22)))
-
-;; Look in an article or mail message for the Subject: line. To be
-;; placed in ps-left-headers.
-(defun ps-article-subject ()
- (save-excursion
- (goto-char (point-min))
- (if (re-search-forward "^Subject:[ \t]+\\(.*\\)$" nil t)
- (buffer-substring (match-beginning 1) (match-end 1))
- "Subject ???")))
-
-;; Look in an article or mail message for the From: line. Sorta-kinda
-;; understands RFC-822 addresses and can pull the real name out where
-;; it's provided. To be placed in ps-left-headers.
-(defun ps-article-author ()
- (save-excursion
- (goto-char (point-min))
- (if (re-search-forward "^From:[ \t]+\\(.*\\)$" nil t)
- (let ((fromstring (buffer-substring (match-beginning 1) (match-end 1))))
- (cond
-
- ;; Try first to match addresses that look like
- ;; thompson@wg2.waii.com (Jim Thompson)
- ((string-match ".*[ \t]+(\\(.*\\))" fromstring)
- (substring fromstring (match-beginning 1) (match-end 1)))
-
- ;; Next try to match addresses that look like
- ;; Jim Thompson <thompson@wg2.waii.com>
- ((string-match "\\(.*\\)[ \t]+<.*>" fromstring)
- (substring fromstring (match-beginning 1) (match-end 1)))
-
- ;; Couldn't find a real name -- show the address instead.
- (t fromstring)))
- "From ???")))
-
-;; A hook to bind to gnus-Article-prepare-hook. This will set the ps-
-;; left-headers specially for gnus articles. Unfortunately, gnus-
-;; article-mode-hook is called only once, the first time the *Article*
-;; buffer enters that mode, so it would only work for the first time
-;; we ran gnus. The second time, this hook wouldn't get set up. The
-;; only alternative is gnus-article-prepare-hook.
-(defun ps-gnus-article-prepare-hook ()
- (setq ps-header-lines 3)
- (setq ps-left-header
- ;; The left headers will display the article's subject, its
- ;; author, and the newsgroup it was in.
- (list 'ps-article-subject 'ps-article-author 'gnus-newsgroup-name)))
-
-;; A hook to bind to vm-mode-hook to locally bind prsc and set the ps-
-;; left-headers specially for mail messages. This header setup would
-;; also work, I think, for RMAIL.
-(defun ps-vm-mode-hook ()
- (local-set-key (ps-prsc) 'ps-vm-print-message-from-summary)
- (setq ps-header-lines 3)
- (setq ps-left-header
- ;; The left headers will display the message's subject, its
- ;; author, and the name of the folder it was in.
- (list 'ps-article-subject 'ps-article-author 'buffer-name)))
-
-;; Every now and then I forget to switch from the *Summary* buffer to
-;; the *Article* before hitting prsc, and a nicely formatted list of
-;; article subjects shows up at the printer. This function, bound to
-;; prsc for the gnus *Summary* buffer means I don't have to switch
-;; buffers first.
-(defun ps-gnus-print-article-from-summary ()
- (interactive)
- (if (get-buffer "*Article*")
- (save-excursion
- (set-buffer "*Article*")
- (ps-spool-buffer-with-faces))))
-
-;; See ps-gnus-print-article-from-summary. This function does the
-;; same thing for vm.
-(defun ps-vm-print-message-from-summary ()
- (interactive)
- (if (and (boundp 'vm-mail-buffer) (symbol-value 'vm-mail-buffer))
- (save-excursion
- (set-buffer (symbol-value 'vm-mail-buffer))
- (ps-spool-buffer-with-faces))))
-
-;; A hook to bind to bind to gnus-summary-setup-buffer to locally bind
-;; prsc.
-(defun ps-gnus-summary-setup ()
- (local-set-key (ps-prsc) 'ps-gnus-print-article-from-summary))
-
-;; Look in an article or mail message for the Subject: line. To be
-;; placed in ps-left-headers.
-(defun ps-info-file ()
- (save-excursion
- (goto-char (point-min))
- (if (re-search-forward "File:[ \t]+\\([^, \t\n]*\\)" nil t)
- (buffer-substring (match-beginning 1) (match-end 1))
- "File ???")))
-
-;; Look in an article or mail message for the Subject: line. To be
-;; placed in ps-left-headers.
-(defun ps-info-node ()
- (save-excursion
- (goto-char (point-min))
- (if (re-search-forward "Node:[ \t]+\\([^,\t\n]*\\)" nil t)
- (buffer-substring (match-beginning 1) (match-end 1))
- "Node ???")))
-
-(defun ps-info-mode-hook ()
- (setq ps-left-header
- ;; The left headers will display the node name and file name.
- (list 'ps-info-node 'ps-info-file)))
-
-;; WARNING! The following function is a *sample* only, and is *not*
-;; meant to be used as a whole unless you understand what the effects
-;; will be! (In fact, this is a copy of Jim's setup for ps-print -- I'd
-;; be very surprised if it was useful to *anybody*, without
-;; modification.)
-
-(defun ps-jts-ps-setup ()
- (global-set-key (ps-prsc) 'ps-spool-buffer-with-faces) ;f22 is prsc
- (global-set-key (ps-s-prsc) 'ps-spool-region-with-faces)
- (global-set-key (ps-c-prsc) 'ps-despool)
- (add-hook 'gnus-article-prepare-hook 'ps-gnus-article-prepare-hook)
- (add-hook 'gnus-summary-mode-hook 'ps-gnus-summary-setup)
- (add-hook 'vm-mode-hook 'ps-vm-mode-hook)
- (add-hook 'vm-mode-hooks 'ps-vm-mode-hook)
- (add-hook 'Info-mode-hook 'ps-info-mode-hook)
- (setq ps-spool-duplex t)
- (setq ps-print-color-p nil)
- (setq ps-lpr-command "lpr")
- (setq ps-lpr-switches '("-Jjct,duplex_long"))
- 'ps-jts-ps-setup)
-
-;; WARNING! The following function is a *sample* only, and is *not*
-;; meant to be used as a whole unless it corresponds to your needs.
-;; (In fact, this is a copy of Jack's setup for ps-print --
-;; I would not be that surprised if it was useful to *anybody*,
-;; without modification.)
-
-(defun ps-jack-setup ()
- (setq ps-print-color-p 'nil
- ps-lpr-command "lpr"
- ps-lpr-switches (list)
-
- ps-paper-type 'a4
- ps-landscape-mode 't
- ps-number-of-columns 2
-
- ps-left-margin (/ (* 72 1.0) 2.54) ; 1.0 cm
- ps-right-margin (/ (* 72 1.0) 2.54) ; 1.0 cm
- ps-inter-column (/ (* 72 1.0) 2.54) ; 1.0 cm
- ps-bottom-margin (/ (* 72 1.5) 2.54) ; 1.5 cm
- ps-top-margin (/ (* 72 1.5) 2.54) ; 1.5 cm
- ps-header-offset (/ (* 72 1.0) 2.54) ; 1.0 cm
- ps-header-line-pad .15
- ps-print-header t
- ps-print-header-frame t
- ps-header-lines 2
- ps-show-n-of-n t
- ps-spool-duplex nil
-
- ps-font-family 'Courier
- ps-font-size 5.5
- ps-header-font-family 'Helvetica
- ps-header-font-size 6
- ps-header-title-font-size 8)
- 'ps-jack-setup)
-
-(provide 'ps-print)
-
-;;; ps-print.el ends here
diff --git a/lisp/rcompile.el b/lisp/rcompile.el
deleted file mode 100644
index c2d5b3f62de..00000000000
--- a/lisp/rcompile.el
+++ /dev/null
@@ -1,163 +0,0 @@
-;;; rcompile.el --- run a compilation on a remote machine
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Albert <alon@milcse.rtsg.mot.com>
-;; Maintainer: FSF
-;; Created: 1993 Oct 6
-;; Version: 1.1
-;; Keywords: tools, processes
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package is for running a remote compilation and using emacs to parse
-;; the error messages. It works by rsh'ing the compilation to a remote host
-;; and parsing the output. If the file visited at the time remote-compile was
-;; called was loaded remotely (ange-ftp), the host and user name are obtained
-;; by the calling ange-ftp-ftp-name on the current directory. In this case the
-;; next-error command will also ange-ftp the files over. This is achieved
-;; automatically because the compilation-parse-errors function uses
-;; default-directory to build its file names. If however the file visited was
-;; loaded locally, remote-compile prompts for a host and user and assumes the
-;; files mounted locally (otherwise, how was the visited file loaded).
-
-;; See the user defined variables section for more info.
-
-;; I was contemplating redefining "compile" to "remote-compile" automatically
-;; if the file visited was ange-ftp'ed but decided against it for now. If you
-;; feel this is a good idea, let me know and I'll consider it again.
-
-;; Installation:
-
-;; To use rcompile, you also need to give yourself permission to connect to
-;; the remote host. You do this by putting lines like:
-
-;; monopoly alon
-;; vme33
-;;
-;; in a file named .rhosts in the home directory (of the remote machine).
-;; Be careful what you put in this file. A line like:
-;;
-;; +
-;;
-;; Will allow anyone access to your account without a password. I suggest you
-;; read the rhosts(5) manual page before you edit this file (if you are not
-;; familiar with it already)
-
-;;; Code:
-
-(provide 'rcompile)
-(require 'compile)
-;;; The following should not be needed.
-;;; (eval-when-compile (require 'ange-ftp))
-
-;;;; user defined variables
-
-(defvar remote-compile-host nil
- "*Host for remote compilations.")
-
-(defvar remote-compile-user nil
- "User for remote compilations.
-nil means use the value returned by \\[user-login-name].")
-
-(defvar remote-compile-run-before nil
- "*Command to run before compilation.
-This can be used for setting up environment variables,
-since rsh does not invoke the shell as a login shell and files like .login
-\(tcsh\) and .bash_profile \(bash\) are not run.
-nil means run no commands.")
-
-(defvar remote-compile-prompt-for-host nil
- "*Non-nil means prompt for host if not available from filename.")
-
-(defvar remote-compile-prompt-for-user nil
- "*Non-nil means prompt for user if not available from filename.")
-
-;;;; internal variables
-
-;; History of remote compile hosts and users
-(defvar remote-compile-host-history nil)
-(defvar remote-compile-user-history nil)
-
-
-;;;; entry point
-
-;;;###autoload
-(defun remote-compile (host user command)
- "Compile the the current buffer's directory on HOST. Log in as USER.
-See \\[compile]."
- (interactive
- (let ((parsed (or (and (featurep 'ange-ftp)
- (ange-ftp-ftp-name default-directory))))
- host user command prompt)
- (if parsed
- (setq host (nth 0 parsed)
- user (nth 1 parsed))
- (setq prompt (if (stringp remote-compile-host)
- (format "Compile on host (default %s): "
- remote-compile-host)
- "Compile on host: ")
- host (if (or remote-compile-prompt-for-host
- (null remote-compile-host))
- (read-from-minibuffer prompt
- "" nil nil
- 'remote-compile-host-history)
- remote-compile-host)
- user (if remote-compile-prompt-for-user
- (read-from-minibuffer (format
- "Compile by user (default %s)"
- (or remote-compile-user
- (user-login-name)))
- "" nil nil
- 'remote-compile-user-history)
- remote-compile-user)))
- (setq command (read-from-minibuffer "Compile command: "
- compile-command nil nil
- '(compile-history . 1)))
- (list (if (string= host "") remote-compile-host host)
- (if (string= user "") remote-compile-user user)
- command)))
- (setq compile-command command)
- (cond (user
- (setq remote-compile-user user))
- ((null remote-compile-user)
- (setq remote-compile-user (user-login-name))))
- (let* ((parsed (and (featurep 'ange-ftp)
- (ange-ftp-ftp-name default-directory)))
- (compile-command
- (format "%s %s -l %s \"(%scd %s; %s)\""
- remote-shell-program
- host
- remote-compile-user
- (if remote-compile-run-before
- (concat remote-compile-run-before "; ")
- "")
- (if parsed (nth 2 parsed) default-directory)
- compile-command)))
- (setq remote-compile-host host)
- (save-some-buffers nil nil)
- (compile-internal compile-command "No more errors")
- ;; Set comint-file-name-prefix in the compilation buffer so
- ;; compilation-parse-errors will find referenced files by ange-ftp.
- (save-excursion
- (set-buffer compilation-last-buffer)
- (setq comint-file-name-prefix (concat "/" host ":")))))
-
-;;; rcompile.el ends here
diff --git a/lisp/rect.el b/lisp/rect.el
deleted file mode 100644
index d8e742ce6a1..00000000000
--- a/lisp/rect.el
+++ /dev/null
@@ -1,246 +0,0 @@
-;;; rect.el --- rectangle functions for GNU Emacs.
-
-;; Copyright (C) 1985, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides the operations on rectangles that are ocumented
-;; in the Emacs manual.
-
-;;; Code:
-
-(defun operate-on-rectangle (function start end coerce-tabs)
- "Call FUNCTION for each line of rectangle with corners at START, END.
-If COERCE-TABS is non-nil, convert multi-column characters
-that span the starting or ending columns on any line
-to multiple spaces before calling FUNCTION.
-FUNCTION is called with three arguments:
- position of start of segment of this line within the rectangle,
- number of columns that belong to rectangle but are before that position,
- number of columns that belong to rectangle but are after point.
-Point is at the end of the segment of this line within the rectangle."
- (let (startcol startlinepos endcol endlinepos)
- (save-excursion
- (goto-char start)
- (setq startcol (current-column))
- (beginning-of-line)
- (setq startlinepos (point)))
- (save-excursion
- (goto-char end)
- (setq endcol (current-column))
- (forward-line 1)
- (setq endlinepos (point-marker)))
- (if (< endcol startcol)
- (setq startcol (prog1 endcol (setq endcol startcol))))
- (save-excursion
- (goto-char startlinepos)
- (while (< (point) endlinepos)
- (let (startpos begextra endextra)
- (move-to-column startcol coerce-tabs)
- (setq begextra (- (current-column) startcol))
- (setq startpos (point))
- (move-to-column endcol coerce-tabs)
- (setq endextra (- endcol (current-column)))
- (if (< begextra 0)
- (setq endextra (+ endextra begextra)
- begextra 0))
- (funcall function startpos begextra endextra))
- (forward-line 1)))
- (- endcol startcol)))
-
-(defun delete-rectangle-line (startdelpos ignore ignore)
- (delete-region startdelpos (point)))
-
-(defun delete-extract-rectangle-line (startdelpos begextra endextra)
- (save-excursion
- (extract-rectangle-line startdelpos begextra endextra))
- (delete-region startdelpos (point)))
-
-(defun extract-rectangle-line (startdelpos begextra endextra)
- (let ((line (buffer-substring startdelpos (point)))
- (end (point)))
- (goto-char startdelpos)
- (while (search-forward "\t" end t)
- (let ((width (- (current-column)
- (save-excursion (forward-char -1)
- (current-column)))))
- (setq line (concat (substring line 0 (- (point) end 1))
- (spaces-string width)
- (substring line (+ (length line) (- (point) end)))))))
- (if (or (> begextra 0) (> endextra 0))
- (setq line (concat (spaces-string begextra)
- line
- (spaces-string endextra))))
- (setq lines (cons line lines))))
-
-(defconst spaces-strings
- '["" " " " " " " " " " " " " " " " "])
-
-(defun spaces-string (n)
- (if (<= n 8) (aref spaces-strings n)
- (let ((val ""))
- (while (> n 8)
- (setq val (concat " " val)
- n (- n 8)))
- (concat val (aref spaces-strings n)))))
-
-;;;###autoload
-(defun delete-rectangle (start end)
- "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."
- (interactive "r")
- (operate-on-rectangle 'delete-rectangle-line start end t))
-
-;;;###autoload
-(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."
- (let (lines)
- (operate-on-rectangle 'delete-extract-rectangle-line
- start end t)
- (nreverse lines)))
-
-;;;###autoload
-(defun extract-rectangle (start end)
- "Return 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 'extract-rectangle-line start end nil)
- (nreverse lines)))
-
-(defvar killed-rectangle nil
- "Rectangle for yank-rectangle to insert.")
-
-;;;###autoload
-(defun kill-rectangle (start end)
- "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'."
- (interactive "r")
- (if buffer-read-only
- (progn
- (setq killed-rectangle (extract-rectangle start end))
- (barf-if-buffer-read-only)))
- (setq killed-rectangle (delete-extract-rectangle start end)))
-
-;;;###autoload
-(defun yank-rectangle ()
- "Yank the last killed rectangle with upper left corner at point."
- (interactive)
- (insert-rectangle killed-rectangle))
-
-;;;###autoload
-(defun insert-rectangle (rectangle)
- "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.
-After this command, the mark is at the upper left corner
-and point is at the lower right corner."
- (let ((lines rectangle)
- (insertcolumn (current-column))
- (first t))
- (push-mark)
- (while lines
- (or first
- (progn
- (forward-line 1)
- (or (bolp) (insert ?\n))
- (move-to-column insertcolumn t)))
- (setq first nil)
- (insert (car lines))
- (setq lines (cdr lines)))))
-
-;;;###autoload
-(defun open-rectangle (start end)
- "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 instead winds up to the right of the rectangle."
- (interactive "r")
- (operate-on-rectangle 'open-rectangle-line start end nil)
- (goto-char start))
-
-(defun open-rectangle-line (startpos begextra endextra)
- ;; Column where rectangle ends.
- (let ((endcol (+ (current-column) endextra))
- whitewidth)
- (goto-char startpos)
- ;; Column where rectangle begins.
- (let ((begcol (- (current-column) begextra)))
- (skip-chars-forward " \t")
- ;; Width of whitespace to be deleted and recreated.
- (setq whitewidth (- (current-column) begcol)))
- ;; Delete the whitespace following the start column.
- (delete-region startpos (point))
- ;; Open the desired width, plus same amount of whitespace we just deleted.
- (indent-to (+ endcol whitewidth))))
-
-;;;###autoload
-(defun string-rectangle (start end string)
- "Insert STRING on each line of the region-rectangle, shifting text right.
-The left edge of the rectangle specifies the column for insertion.
-This command does not delete or overwrite any existing text.
-
-Called from a program, takes three args; START, END and STRING."
- (interactive "r\nsString rectangle: ")
- (operate-on-rectangle 'string-rectangle-line start end t))
-
-(defun string-rectangle-line (startpos begextra endextra)
- (let (whitespace)
- (goto-char startpos)
- ;; Compute horizontal width of following whitespace.
- (let ((ocol (current-column)))
- (skip-chars-forward " \t")
- (setq whitespace (- (current-column) ocol)))
- ;; Delete the following whitespace.
- (delete-region startpos (point))
- ;; Insert the desired string.
- (insert string)
- ;; Insert the same width of whitespace that we had before.
- (indent-to (+ (current-column) whitespace))))
-
-;;;###autoload
-(defun clear-rectangle (start end)
- "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."
- (interactive "r")
- (operate-on-rectangle 'clear-rectangle-line start end t))
-
-(defun clear-rectangle-line (startpos begextra endextra)
- ;; Find end of whitespace after the rectangle.
- (skip-chars-forward " \t")
- (let ((column (+ (current-column) endextra)))
- ;; Delete the text in the rectangle, and following whitespace.
- (delete-region (point)
- (progn (goto-char startpos)
- (skip-chars-backward " \t")
- (point)))
- ;; Reindent out to same column that we were at.
- (indent-to column)))
-
-(provide 'rect)
-
-;;; rect.el ends here
diff --git a/lisp/regi.el b/lisp/regi.el
deleted file mode 100644
index 81674d19988..00000000000
--- a/lisp/regi.el
+++ /dev/null
@@ -1,255 +0,0 @@
-;;; regi.el --- REGular expression Interpreting engine
-
-;; Copyright (C) 1993 Free Software Foundation, Inc.
-
-;; Author: 1993 Barry A. Warsaw, Century Computing, Inc. <bwarsaw@cen.com>
-;; Maintainer: bwarsaw@cen.com
-;; Created: 24-Feb-1993
-;; Version: 1.8
-;; Last Modified: 1993/06/01 21:33:00
-;; Keywords: extensions, matching
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-
-(defun regi-pos (&optional position col-p)
- "Return the character position at various buffer positions.
-Optional POSITION can be one of the following symbols:
-
-`bol' == beginning of line
-`boi' == beginning of indentation
-`eol' == end of line [default]
-`bonl' == beginning of next line
-`bopl' == beginning of previous line
-
-Optional COL-P non-nil returns `current-column' instead of character position."
- (save-excursion
- (cond
- ((eq position 'bol) (beginning-of-line))
- ((eq position 'boi) (back-to-indentation))
- ((eq position 'bonl) (forward-line 1))
- ((eq position 'bopl) (forward-line -1))
- (t (end-of-line)))
- (if col-p (current-column) (point))))
-
-(defun regi-mapcar (predlist func &optional negate-p case-fold-search-p)
- "Build a regi frame where each element of PREDLIST appears exactly once.
-The frame contains elements where each member of PREDLIST is
-associated with FUNC, and optionally NEGATE-P and CASE-FOLD-SEARCH-P."
- (let (frame tail)
- (if (or negate-p case-fold-search-p)
- (setq tail (list negate-p)))
- (if case-fold-search-p
- (setq tail (append tail (list case-fold-search-p))))
- (while predlist
- (let ((element (list (car predlist) func)))
- (if tail
- (setq element (append element tail)))
- (setq frame (append frame (list element))
- predlist (cdr predlist))
- ))
- frame))
-
-
-(defun regi-interpret (frame &optional start end)
- "Interpret the regi frame FRAME.
-If optional START and END are supplied, they indicate the region of
-interest, and the buffer is narrowed to the beginning of the line
-containing START, and beginning of the line after the line containing
-END. Otherwise, point and mark are not set and processing continues
-until your FUNC returns the `abort' symbol (see below). Beware! Not
-supplying a START or END could put you in an infinite loop.
-
-A regi frame is a list of entries of the form:
-
- (PRED FUNC [NEGATE-P [CASE-FOLD-SEARCH]])
-
-PRED is a predicate against which each line in the region is tested,
-and if a match occurs, FUNC is `eval'd. Point is then moved to the
-beginning of the next line, the frame is reset and checking continues.
-If a match doesn't occur, the next entry is checked against the
-current line until all entries in the frame are checked. At this
-point, if no match occurred, the frame is reset and point is moved to
-the next line. Checking continues until every line in the region is
-checked. Optional NEGATE-P inverts the result of PRED before FUNC is
-called and `case-fold-search' is bound to the optional value of
-CASE-FOLD-SEARCH for the PRED check.
-
-PRED can be a string, variable, function or one of the following
-symbols: t, nil, `begin', `end', and `every'. If PRED is a string, or
-a variable or list that evaluates to a string, it is interpreted as a
-regular expression and is matched against the current line (from the
-beginning) using `looking-at'. If PRED does not evaluate to a string,
-it is interpreted as a binary value (nil or non-nil).
-
-PRED can also be one of the following symbols:
-
-t -- always produces a true outcome
-`begin' -- always executes before anything else
-`end' -- always executes after everything else
-`every' -- execute after frame is matched on a line
-
-Note that NEGATE-P and CASE-FOLD-SEARCH are meaningless if PRED is one
-of these special symbols. Only the first occurrence of each symbol in
-a frame entry is used, the rest are ignored.
-
-Your FUNC can return values which control regi processing. If a list
-is returned from your function, it can contain any combination of the
-following elements:
-
-the symbol `continue'
- Tells regi to continue processing frame-entries after a match,
- instead of resetting to the first entry and advancing to the next
- line, as is the default behavior. When returning this symbol,
- you must take care not to enter an infinite loop.
-
-the symbol `abort'
- Tells regi to terminate processing this frame. any end
- frame-entry is still processed.
-
-the list `(frame . NEWFRAME)'
- Tells regi to use NEWFRAME as its current frame. In other words,
- your FUNC can modify the executing regi frame on the fly.
-
-the list `(step . STEP)'
- Tells regi to move STEP number of lines forward during normal
- processing. By default, regi moves forward 1 line. STEP can be
- negative, but be careful of infinite loops.
-
-You should usually take care to explicitly return nil from your
-function if no action is to take place. Your FUNC will always be
-`eval'ed. The following variables will be temporarily bound to some
-useful information:
-
-`curline'
- the current line in the buffer, as a string
-
-`curframe'
- the full, current frame being executed
-
-`curentry'
- the current frame entry being executed."
-
- (save-excursion
- (save-restriction
- (let (begin-tag end-tag every-tag current-frame working-frame donep)
-
- ;; set up the narrowed region
- (and start
- end
- (let* ((tstart start)
- (start (min start end))
- (end (max start end)))
- (narrow-to-region
- (progn (goto-char end) (regi-pos 'bonl))
- (progn (goto-char start) (regi-pos 'bol)))))
-
- ;; lets find the special tags and remove them from the working
- ;; frame. note that only the last special tag is used.
- (mapcar
- (function
- (lambda (entry)
- (let ((pred (car entry))
- (func (car (cdr entry))))
- (cond
- ((eq pred 'begin) (setq begin-tag func))
- ((eq pred 'end) (setq end-tag func))
- ((eq pred 'every) (setq every-tag func))
- (t
- (setq working-frame (append working-frame (list entry))))
- ) ; end-cond
- )))
- frame) ; end-mapcar
-
- ;; execute the begin entry
- (eval begin-tag)
-
- ;; now process the frame
- (setq current-frame working-frame)
- (while (not (or donep (eobp)))
- (let* ((entry (car current-frame))
- (pred (nth 0 entry))
- (func (nth 1 entry))
- (negate-p (nth 2 entry))
- (case-fold-search (nth 3 entry))
- match-p)
- (catch 'regi-throw-top
- (cond
- ;; we are finished processing the frame for this line
- ((not current-frame)
- (setq current-frame working-frame) ;reset frame
- (forward-line 1)
- (throw 'regi-throw-top t))
- ;; see if predicate evaluates to a string
- ((stringp (setq match-p (eval pred)))
- (setq match-p (looking-at match-p)))
- ) ; end-cond
-
- ;; now that we've done the initial matching, check for
- ;; negation of match
- (and negate-p
- (setq match-p (not match-p)))
-
- ;; if the line matched, package up the argument list and
- ;; funcall the FUNC
- (if match-p
- (let* ((curline (buffer-substring
- (regi-pos 'bol)
- (regi-pos 'eol)))
- (curframe current-frame)
- (curentry entry)
- (result (eval func))
- (step (or (cdr (assq 'step result)) 1))
- )
- ;; changing frame on the fly?
- (if (assq 'frame result)
- (setq working-frame (cdr (assq 'frame result))))
-
- ;; continue processing current frame?
- (if (memq 'continue result)
- (setq current-frame (cdr current-frame))
- (forward-line step)
- (setq current-frame working-frame))
-
- ;; abort current frame?
- (if (memq 'abort result)
- (progn
- (setq donep t)
- (throw 'regi-throw-top t)))
- ) ; end-let
-
- ;; else if no match occurred, then process the next
- ;; frame-entry on the current line
- (setq current-frame (cdr current-frame))
-
- ) ; end-if match-p
- ) ; end catch
- ) ; end let
-
- ;; after every cycle, evaluate every-tag
- (eval every-tag)
- ) ; end-while
-
- ;; now process the end entry
- (eval end-tag)))))
-
-
-(provide 'regi)
-;;; regi.el ends here
diff --git a/lisp/register.el b/lisp/register.el
deleted file mode 100644
index 32cd981bdca..00000000000
--- a/lisp/register.el
+++ /dev/null
@@ -1,272 +0,0 @@
-;;; register.el --- register commands for Emacs.
-
-;; Copyright (C) 1985, 1993, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package of functions emulates and somewhat extends the venerable
-;; TECO's `register' feature, which permits you to save various useful
-;; pieces of buffer state to named variables. The entry points are
-;; documented in the Emacs user's manual.
-
-;;; Code:
-
-(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,
-frame configuration, mark or list.
-A list of strings represents a rectangle.
-A list of the form (file . NAME) represents the file named NAME.
-A list of the form (file-query NAME POSITION) represents position POSITION
- in the file named NAME, but query before visiting it.")
-
-(defun get-register (reg)
- "Return contents of Emacs register named REG, or nil if none."
- (cdr (assq reg register-alist)))
-
-(defun set-register (register value)
- "Set contents of Emacs register named REGISTER to VALUE. Returns VALUE.
-See the documentation of the variable `register-alist' for possible VALUE."
- (let ((aelt (assq register register-alist)))
- (if aelt
- (setcdr aelt value)
- (setq aelt (cons register value))
- (setq register-alist (cons aelt register-alist)))
- value))
-
-(defun point-to-register (register &optional arg)
- "Store current location of point in register REGISTER.
-With prefix argument, store current frame configuration.
-Use \\[jump-to-register] to go to that location or restore that configuration.
-Argument is a character, naming the register."
- (interactive "cPoint to register: \nP")
- (set-register register
- (if arg (current-frame-configuration) (point-marker))))
-
-(defun window-configuration-to-register (register &optional arg)
- "Store the window configuration of the selected frame in register REGISTER.
-Use \\[jump-to-register] to restore the configuration.
-Argument is a character, naming the register."
- (interactive "cWindow configuration to register: \nP")
- (set-register register (current-window-configuration)))
-
-(defun frame-configuration-to-register (register &optional arg)
- "Store the window configuration of all frames in register REGISTER.
-Use \\[jump-to-register] to restore the configuration.
-Argument is a character, naming the register."
- (interactive "cFrame configuration to register: \nP")
- (set-register register (current-frame-configuration)))
-
-(defalias 'register-to-point 'jump-to-register)
-(defun jump-to-register (register &optional delete)
- "Move point to location stored in a register.
-If the register contains a file name, find that file.
- \(To put a file name in a register, you must use `set-register'.)
-If the register contains a window configuration (one frame) or a frame
-configuration (all frames), restore that frame or all frames accordingly.
-First argument is a character, naming the register.
-Optional second arg non-nil (interactively, prefix argument) says to
-delete any existing frames that the frame configuration doesn't mention.
-\(Otherwise, these frames are iconified.)"
- (interactive "cJump to register: \nP")
- (let ((val (get-register register)))
- (cond
- ((and (fboundp 'frame-configuration-p)
- (frame-configuration-p val))
- (set-frame-configuration val (not delete)))
- ((window-configuration-p val)
- (set-window-configuration val))
- ((markerp val)
- (or (marker-buffer val)
- (error "That register's buffer no longer exists"))
- (switch-to-buffer (marker-buffer val))
- (goto-char val))
- ((and (consp val) (eq (car val) 'file))
- (find-file (cdr val)))
- ((and (consp val) (eq (car val) 'file-query))
- (or (find-buffer-visiting (nth 1 val))
- (y-or-n-p (format "Visit file %s again? " (nth 1 val)))
- (error "Register access aborted"))
- (find-file (nth 1 val))
- (goto-char (nth 2 val)))
- (t
- (error "Register doesn't contain a buffer position or configuration")))))
-
-;; Turn markers into file-query references when a buffer is killed.
-(defun register-swap-out ()
- (and buffer-file-name
- (let ((tail register-alist))
- (while tail
- (and (markerp (cdr (car tail)))
- (eq (marker-buffer (cdr (car tail))) (current-buffer))
- (setcdr (car tail)
- (list 'file-query
- buffer-file-name
- (marker-position (cdr (car tail))))))
- (setq tail (cdr tail))))))
-
-(add-hook 'kill-buffer-hook 'register-swap-out)
-
-;(defun number-to-register (arg char)
-; "Store a number in a register.
-;Two args, NUMBER and REGISTER (a character, naming the register).
-;If NUMBER is nil, digits in the buffer following point are read
-;to get the number to store.
-;Interactively, NUMBER is the prefix arg (none means nil)."
-; (interactive "P\ncNumber to register: ")
-; (set-register char
-; (if arg
-; (prefix-numeric-value arg)
-; (if (looking-at "[0-9][0-9]*")
-; (save-excursion
-; (save-restriction
-; (narrow-to-region (point)
-; (progn (skip-chars-forward "0-9")
-; (point)))
-; (goto-char (point-min))
-; (read (current-buffer))))
-; 0))))
-
-;(defun increment-register (arg char)
-; "Add NUMBER to the contents of register REGISTER.
-;Interactively, NUMBER is the prefix arg (none means nil)."
-; (interactive "p\ncNumber to register: ")
-; (or (integerp (get-register char))
-; (error "Register does not contain a number"))
-; (set-register char (+ arg (get-register char))))
-
-(defun view-register (register)
- "Display what is contained in register named REGISTER.
-The Lisp value REGISTER is a character."
- (interactive "cView register: ")
- (let ((val (get-register register)))
- (if (null val)
- (message "Register %s is empty" (single-key-description register))
- (with-output-to-temp-buffer "*Output*"
- (princ "Register ")
- (princ (single-key-description register))
- (princ " contains ")
- (cond
- ((integerp val)
- (princ val))
-
- ((markerp val)
- (let ((buf (marker-buffer val)))
- (if (null buf)
- (princ "a marker in no buffer")
- (princ "a buffer position:\nbuffer ")
- (princ (buffer-name buf))
- (princ ", position ")
- (princ (marker-position val)))))
-
- ((window-configuration-p val)
- (princ "a window configuration."))
-
- ((frame-configuration-p val)
- (princ "a frame configuration."))
-
- ((and (consp val) (eq (car val) 'file))
- (princ "the file ")
- (prin1 (cdr val))
- (princ "."))
-
- ((consp val)
- (princ "the rectangle:\n")
- (while val
- (princ (car val))
- (terpri)
- (setq val (cdr val))))
-
- ((stringp val)
- (princ "the text:\n")
- (princ val))
-
- (t
- (princ "Garbage:\n")
- (prin1 val)))))))
-
-(defun insert-register (register &optional arg)
- "Insert contents of register REGISTER. (REGISTER is a character.)
-Normally puts point before and mark after the inserted text.
-If optional second arg is non-nil, puts mark before and point after.
-Interactively, second arg is non-nil if prefix arg is supplied."
- (interactive "*cInsert register: \nP")
- (push-mark)
- (let ((val (get-register register)))
- (cond
- ((consp val)
- (insert-rectangle val))
- ((stringp val)
- (insert val))
- ((integerp val)
- (princ val (current-buffer)))
- ((and (markerp val) (marker-position val))
- (princ (marker-position val) (current-buffer)))
- (t
- (error "Register does not contain text"))))
- (if (not arg) (exchange-point-and-mark)))
-
-(defun copy-to-register (register start end &optional delete-flag)
- "Copy region into register REGISTER. With prefix arg, delete as well.
-Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
-START and END are buffer positions indicating what to copy."
- (interactive "cCopy to register: \nr\nP")
- (set-register register (buffer-substring start end))
- (if delete-flag (delete-region start end)))
-
-(defun append-to-register (register start end &optional delete-flag)
- "Append region to text in register REGISTER.
-With prefix arg, delete as well.
-Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
-START and END are buffer positions indicating what to append."
- (interactive "cAppend to register: \nr\nP")
- (or (stringp (get-register register))
- (error "Register does not contain text"))
- (set-register register (concat (get-register register)
- (buffer-substring start end)))
- (if delete-flag (delete-region start end)))
-
-(defun prepend-to-register (register start end &optional delete-flag)
- "Prepend region to text in register REGISTER.
-With prefix arg, delete as well.
-Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
-START and END are buffer positions indicating what to prepend."
- (interactive "cPrepend to register: \nr\nP")
- (or (stringp (get-register register))
- (error "Register does not contain text"))
- (set-register register (concat (buffer-substring start end)
- (get-register register)))
- (if delete-flag (delete-region start end)))
-
-(defun copy-rectangle-to-register (register start end &optional delete-flag)
- "Copy rectangular region into register REGISTER.
-With prefix arg, delete as well.
-Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
-START and END are buffer positions giving two corners of rectangle."
- (interactive "cCopy rectangle to register: \nr\nP")
- (set-register register
- (if delete-flag
- (delete-extract-rectangle start end)
- (extract-rectangle start end))))
-
-;;; register.el ends here
diff --git a/lisp/replace.el b/lisp/replace.el
deleted file mode 100644
index 95b791aec39..00000000000
--- a/lisp/replace.el
+++ /dev/null
@@ -1,741 +0,0 @@
-;;; replace.el --- replace commands for Emacs.
-
-;; Copyright (C) 1985, 1986, 1987, 1992, 1994, 1996 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package supplies the string and regular-expression replace functions
-;; documented in the Emacs user's manual.
-
-;;; Code:
-
-(defvar case-replace t "\
-*Non-nil means query-replace should preserve case in replacements.")
-
-(defvar query-replace-history nil)
-
-(defvar query-replace-interactive nil
- "Non-nil means `query-replace' uses the last search string.
-That becomes the \"string to replace\".")
-
-(defun query-replace-read-args (string regexp-flag)
- (let (from to)
- (if query-replace-interactive
- (setq from (car (if regexp-flag regexp-search-ring search-ring)))
- (setq from (read-from-minibuffer (format "%s: " string)
- nil nil nil
- 'query-replace-history)))
- (setq to (read-from-minibuffer (format "%s %s with: " string from)
- nil nil nil
- 'query-replace-history))
- (list from to current-prefix-arg)))
-
-(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.
-
-If `query-replace-interactive' is non-nil, the last incremental search
-string is used as FROM-STRING--you don't have to specify it with the
-minibuffer.
-
-Preserves case in each replacement if `case-replace' and `case-fold-search'
-are non-nil and FROM-STRING has no uppercase letters.
-\(Preserving case means that if the string matched is all caps, or capitalized,
-then its replacement is upcased or capitalized.)
-
-Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace
-only matches surrounded by word boundaries.
-
-To customize possible responses, change the \"bindings\" in `query-replace-map'."
- (interactive (query-replace-read-args "Query replace" nil))
- (perform-replace from-string to-string t nil arg))
-(define-key esc-map "%" 'query-replace)
-
-(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.
-
-If `query-replace-interactive' is non-nil, the last incremental search
-regexp is used as REGEXP--you don't have to specify it with the
-minibuffer.
-
-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), if non-nil, means replace
-only matches surrounded by word boundaries.
-In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP,
-and `\\=\\N' (where N is a digit) stands for
- whatever what matched the Nth `\\(...\\)' in REGEXP."
- (interactive (query-replace-read-args "Query replace regexp" t))
- (perform-replace regexp to-string t t arg))
-
-(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.
-
-If `query-replace-interactive' is non-nil, the last incremental search
-regexp is used as REGEXP--you don't have to specify it with the minibuffer.
-
-A prefix argument N says to use each replacement string N times
-before rotating to the next."
- (interactive
- (let (from to)
- (setq from (if query-replace-interactive
- (car regexp-search-ring)
- (read-from-minibuffer "Map query replace (regexp): "
- nil nil nil
- 'query-replace-history)))
- (setq to (read-from-minibuffer
- (format "Query replace %s with (space-separated strings): "
- from)
- nil nil nil
- 'query-replace-history))
- (list from to current-prefix-arg)))
- (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)))
-
-(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.
-\(Preserving case means that if the string matched is all caps, or capitalized,
-then its replacement is upcased or capitalized.)
-
-Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace
-only matches surrounded by word boundaries.
-
-If `query-replace-interactive' is non-nil, the last incremental search
-string is used as FROM-STRING--you don't have to specify it with the
-minibuffer.
-
-This function is usually the wrong thing to use in a Lisp program.
-What you probably want is a loop like this:
- (while (search-forward FROM-STRING nil t)
- (replace-match TO-STRING nil t))
-which will run faster and will not set the mark or print anything."
- (interactive (query-replace-read-args "Replace string" nil))
- (perform-replace from-string to-string nil nil delimited))
-
-(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), if non-nil, means replace
-only matches surrounded by word boundaries.
-In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP,
-and `\\=\\N' (where N is a digit) stands for
- whatever what matched the Nth `\\(...\\)' in REGEXP.
-
-If `query-replace-interactive' is non-nil, the last incremental search
-regexp is used as REGEXP--you don't have to specify it with the minibuffer.
-
-This function is usually the wrong thing to use in a Lisp program.
-What you probably want is a loop like this:
- (while (re-search-forward REGEXP nil t)
- (replace-match TO-STRING nil nil))
-which will run faster and will not set the mark or print anything."
- (interactive (query-replace-read-args "Replace regexp" t))
- (perform-replace regexp to-string nil t delimited))
-
-(defvar regexp-history nil
- "History list for some commands that read regular expressions.")
-
-(defalias 'delete-non-matching-lines 'keep-lines)
-(defun keep-lines (regexp)
- "Delete all lines except those containing matches for REGEXP.
-A match split across lines preserves all the lines it lies in.
-Applies to all lines after point."
- (interactive (list (read-from-minibuffer
- "Keep lines (containing match for regexp): "
- nil nil nil 'regexp-history)))
- (save-excursion
- (or (bolp) (forward-line 1))
- (let ((start (point)))
- (while (not (eobp))
- ;; Start is first char not preserved by previous match.
- (if (not (re-search-forward regexp nil 'move))
- (delete-region start (point-max))
- (let ((end (save-excursion (goto-char (match-beginning 0))
- (beginning-of-line)
- (point))))
- ;; Now end is first char preserved by the new match.
- (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))))))
-
-(defalias 'delete-matching-lines 'flush-lines)
-(defun flush-lines (regexp)
- "Delete lines containing matches for REGEXP.
-If a match is split across lines, all the lines it lies in are deleted.
-Applies to lines after point."
- (interactive (list (read-from-minibuffer
- "Flush lines (containing match for regexp): "
- nil nil nil 'regexp-history)))
- (save-excursion
- (while (and (not (eobp))
- (re-search-forward regexp nil t))
- (delete-region (save-excursion (goto-char (match-beginning 0))
- (beginning-of-line)
- (point))
- (progn (forward-line 1) (point))))))
-
-(defalias 'count-matches 'how-many)
-(defun how-many (regexp)
- "Print number of matches for REGEXP following point."
- (interactive (list (read-from-minibuffer
- "How many matches for (regexp): "
- nil nil nil 'regexp-history)))
- (let ((count 0) opoint)
- (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))))
- (message "%d occurrences" count))))
-
-(defvar occur-mode-map ())
-(if occur-mode-map
- ()
- (setq occur-mode-map (make-sparse-keymap))
- (define-key occur-mode-map [mouse-2] 'occur-mode-mouse-goto)
- (define-key occur-mode-map "\C-c\C-c" 'occur-mode-goto-occurrence)
- (define-key occur-mode-map "\C-m" 'occur-mode-goto-occurrence))
-
-(defvar occur-buffer nil)
-(defvar occur-nlines nil)
-(defvar occur-pos-list nil)
-
-(defun occur-mode ()
- "Major mode for output from \\[occur].
-\\<occur-mode-map>Move point to one of the items in this buffer, then use
-\\[occur-mode-goto-occurrence] to go to the occurrence that the item refers to.
-Alternatively, click \\[occur-mode-mouse-goto] on an item to go to it.
-
-\\{occur-mode-map}"
- (kill-all-local-variables)
- (use-local-map occur-mode-map)
- (setq major-mode 'occur-mode)
- (setq mode-name "Occur")
- (make-local-variable 'occur-buffer)
- (make-local-variable 'occur-nlines)
- (make-local-variable 'occur-pos-list)
- (run-hooks 'occur-mode-hook))
-
-(defun occur-mode-mouse-goto (event)
- "In Occur mode, go to the occurrence whose line you click on."
- (interactive "e")
- (let (buffer pos)
- (save-excursion
- (set-buffer (window-buffer (posn-window (event-end event))))
- (save-excursion
- (goto-char (posn-point (event-end event)))
- (setq pos (occur-mode-find-occurrence))
- (setq buffer occur-buffer)))
- (pop-to-buffer buffer)
- (goto-char (marker-position pos))))
-
-(defun occur-mode-find-occurrence ()
- (if (or (null occur-buffer)
- (null (buffer-name occur-buffer)))
- (progn
- (setq occur-buffer nil
- occur-pos-list nil)
- (error "Buffer in which occurrences were found is deleted")))
- (let* ((line-count
- (count-lines (point-min)
- (save-excursion
- (beginning-of-line)
- (point))))
- (occur-number (save-excursion
- (beginning-of-line)
- (/ (1- line-count)
- (cond ((< occur-nlines 0)
- (- 2 occur-nlines))
- ((> occur-nlines 0)
- (+ 2 (* 2 occur-nlines)))
- (t 1)))))
- (pos (nth occur-number occur-pos-list)))
- (if (< line-count 1)
- (error "No occurrence on this line"))
- (or pos
- (error "No occurrence on this line"))
- pos))
-
-(defun occur-mode-goto-occurrence ()
- "Go to the occurrence the current line describes."
- (interactive)
- (let ((pos (occur-mode-find-occurrence)))
- (pop-to-buffer occur-buffer)
- (goto-char (marker-position pos))))
-
-(defvar list-matching-lines-default-context-lines 0
- "*Default number of context lines to include around a `list-matching-lines'
-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.")
-
-(defalias 'list-matching-lines 'occur)
-
-(defvar list-matching-lines-face 'bold
- "*Face used by M-x list-matching-lines to show the text that matches.
-If the value is nil, don't highlight the matching portions specially.")
-
-(defun occur (regexp &optional nlines)
- "Show all lines in the current buffer containing a match for REGEXP.
-
-If a match spreads across multiple lines, all those lines are shown.
-
-Each line is displayed 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 (let* ((default (car regexp-history))
- (input
- (read-from-minibuffer
- (if default
- (format "List lines matching regexp (default `%s'): "
- default)
- "List lines matching regexp: ")
- nil nil nil 'regexp-history)))
- (if (string-equal input "")
- default
- (set-text-properties 0 (length input) nil input)
- input))
- current-prefix-arg))
- (let ((nlines (if nlines
- (prefix-numeric-value nlines)
- list-matching-lines-default-context-lines))
- (first t)
- (buffer (current-buffer))
- (dir default-directory)
- (linenum 1)
- (prevpos (point-min))
- (final-context-start (make-marker)))
-;;; (save-excursion
-;;; (beginning-of-line)
-;;; (setq linenum (1+ (count-lines (point-min) (point))))
-;;; (setq prevpos (point)))
- (save-excursion
- (goto-char (point-min))
- ;; Check first whether there are any matches at all.
- (if (not (re-search-forward regexp nil t))
- (message "No matches for `%s'" regexp)
- ;; Back up, so the search loop below will find the first match.
- (goto-char (match-beginning 0))
- (with-output-to-temp-buffer "*Occur*"
- (save-excursion
- (set-buffer standard-output)
- (setq default-directory dir)
- ;; We will insert the number of lines, and "lines", later.
- (insert " matching ")
- (let ((print-escape-newlines t))
- (prin1 regexp))
- (insert " in buffer " (buffer-name buffer) ?. ?\n)
- (occur-mode)
- (setq occur-buffer buffer)
- (setq occur-nlines nlines)
- (setq occur-pos-list ()))
- (if (eq buffer standard-output)
- (goto-char (point-max)))
- (save-excursion
- ;; 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))
- (goto-char (match-beginning 0))
- (beginning-of-line)
- (save-match-data
- (setq linenum (+ linenum (count-lines prevpos (point)))))
- (setq prevpos (point))
- (goto-char (match-end 0))
- (let* ((start (save-excursion
- (goto-char (match-beginning 0))
- (forward-line (if (< nlines 0) nlines (- nlines)))
- (point)))
- (end (save-excursion
- (goto-char (match-end 0))
- (if (> nlines 0)
- (forward-line (1+ nlines))
- (forward-line 1))
- (point)))
- ;; Record where the actual match
- (match-offset
- (save-excursion
- (goto-char (match-beginning 0))
- (beginning-of-line)
- ;; +6 to skip over line number
- (+ 6 (- (match-beginning 0) (point)))))
- (match-len (- (match-end 0) (match-beginning 0)))
- (tag (format "%5d" linenum))
- (empty (make-string (length tag) ?\ ))
- tem)
- (save-excursion
- (setq tem (make-marker))
- (set-marker tem (point))
- (set-buffer standard-output)
- (setq occur-pos-list (cons tem occur-pos-list))
- (or first (zerop nlines)
- (insert "--------\n"))
- (setq first nil)
- (insert-buffer-substring buffer start end)
- (set-marker final-context-start
- (- (point) (- end (match-end 0))))
- (backward-char (- end start))
- (setq tem nlines)
- (while (> tem 0)
- (insert empty ?:)
- (forward-line 1)
- (setq tem (1- tem)))
- (let ((this-linenum linenum)
- line-start)
- (while (< (point) final-context-start)
- (if (null tag)
- (setq tag (format "%5d" this-linenum)))
- (insert tag ?:)
- (setq line-start
- (save-excursion
- (beginning-of-line)
- (point)))
- (put-text-property line-start
- (save-excursion
- (end-of-line)
- (point))
- 'mouse-face 'highlight)
- (if list-matching-lines-face
- (put-text-property
- (+ line-start match-offset)
- (+ line-start match-offset match-len)
- 'face list-matching-lines-face))
- (forward-line 1)
- (setq tag nil)
- (setq this-linenum (1+ this-linenum)))
- (while (<= (point) final-context-start)
- (insert empty ?:)
- (forward-line 1)
- (setq this-linenum (1+ this-linenum))))
- (while (< tem nlines)
- (insert empty ?:)
- (forward-line 1)
- (setq tem (1+ tem)))
- (goto-char (point-max)))
- (forward-line 1)))
- (set-buffer standard-output)
- ;; Put positions in increasing order to go with buffer.
- (setq occur-pos-list (nreverse occur-pos-list))
- (goto-char (point-min))
- (let ((message-string
- (if (= (length occur-pos-list) 1)
- "1 line"
- (format "%d lines" (length occur-pos-list)))))
- (insert message-string)
- (if (interactive-p)
- (message "%s matched" message-string)))))))))
-
-;; It would be nice to use \\[...], but there is no reasonable way
-;; to make that display both SPC and Y.
-(defconst query-replace-help
- "Type Space or `y' to replace one match, Delete or `n' to skip to next,
-RET or `q' to exit, Period to replace one match and exit,
-Comma to replace but not move point immediately,
-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."
- "Help message while in query-replace")
-
-(defvar query-replace-map (make-sparse-keymap)
- "Keymap that defines the responses to questions in `query-replace'.
-The \"bindings\" in this map are not commands; they are answers.
-The valid answers include `act', `skip', `act-and-show',
-`exit', `act-and-exit', `edit', `delete-and-edit', `recenter',
-`automatic', `backup', `exit-prefix', and `help'.")
-
-(define-key query-replace-map " " 'act)
-(define-key query-replace-map "\d" 'skip)
-(define-key query-replace-map [delete] 'skip)
-(define-key query-replace-map [backspace] 'skip)
-(define-key query-replace-map "y" 'act)
-(define-key query-replace-map "n" 'skip)
-(define-key query-replace-map "Y" 'act)
-(define-key query-replace-map "N" 'skip)
-(define-key query-replace-map "," 'act-and-show)
-(define-key query-replace-map "q" 'exit)
-(define-key query-replace-map "\r" 'exit)
-(define-key query-replace-map [return] 'exit)
-(define-key query-replace-map "." 'act-and-exit)
-(define-key query-replace-map "\C-r" 'edit)
-(define-key query-replace-map "\C-w" 'delete-and-edit)
-(define-key query-replace-map "\C-l" 'recenter)
-(define-key query-replace-map "!" 'automatic)
-(define-key query-replace-map "^" 'backup)
-(define-key query-replace-map "\C-h" 'help)
-(define-key query-replace-map [f1] 'help)
-(define-key query-replace-map [help] 'help)
-(define-key query-replace-map "?" 'help)
-(define-key query-replace-map "\C-g" 'quit)
-(define-key query-replace-map "\C-]" 'quit)
-(define-key query-replace-map "\e" 'exit-prefix)
-(define-key query-replace-map [escape] 'exit-prefix)
-
-(defun perform-replace (from-string replacements
- query-flag regexp-flag delimited-flag
- &optional repeat-count map)
- "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 probably do exactly what you want."
- (or map (setq map query-replace-map))
- (and query-flag minibuffer-auto-raise
- (raise-frame (window-frame (minibuffer-window))))
- (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)
- (real-match-data nil) ; the match data for the current match
- (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.
- (match-again t)
- (message
- (if query-flag
- (substitute-command-keys
- "Query replacing %s with %s: (\\<query-replace-map>\\[help] for help) "))))
- (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"
- (if regexp-flag from-string
- (regexp-quote from-string))
- "\\b")))
- (push-mark)
- (undo-boundary)
- (unwind-protect
- ;; Loop finding occurrences that perhaps should be replaced.
- (while (and keep-going
- (not (eobp))
- (funcall search-function search-string nil t)
- ;; If the search string matches immediately after
- ;; the previous match, but it did not match there
- ;; before the replacement was done, ignore the match.
- (if (or (eq lastrepl (point))
- (and regexp-flag
- (eq lastrepl (match-beginning 0))
- (not match-again)))
- (if (eobp)
- nil
- ;; Don't replace the null string
- ;; right after end of previous replacement.
- (forward-char 1)
- (funcall search-function search-string nil t))
- t))
-
- ;; Save the data associated with the real match.
- ;; For speed, use only integers and reuse the list used last time.
- (setq real-match-data (match-data t real-match-data))
-
- ;; Before we make the replacement, decide whether the search string
- ;; can match again just after this match.
- (if regexp-flag
- (setq match-again (looking-at search-string)))
- ;; 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
- (store-match-data real-match-data)
- (replace-match next-replacement nocasify literal)
- (setq replace-count (1+ replace-count)))
- (undo-boundary)
- (let (done replaced key def)
- ;; Loop reading commands until one of them sets done,
- ;; which means it has finished handling this occurrence.
- (while (not done)
- (store-match-data real-match-data)
- (replace-highlight (match-beginning 0) (match-end 0))
- ;; Bind message-log-max so we don't fill up the message log
- ;; with a bunch of identical messages.
- (let ((message-log-max nil))
- (message message from-string next-replacement))
- (setq key (read-event))
- (setq key (vector key))
- (setq def (lookup-key map key))
- ;; Restore the match data while we process the command.
- (cond ((eq def 'help)
- (with-output-to-temp-buffer "*Help*"
- (princ
- (concat "Query replacing "
- (if regexp-flag "regexp " "")
- from-string " with "
- next-replacement ".\n\n"
- (substitute-command-keys
- query-replace-help)))
- (save-excursion
- (set-buffer standard-output)
- (help-mode))))
- ((eq def 'exit)
- (setq keep-going nil)
- (setq done t))
- ((eq def 'backup)
- (if stack
- (let ((elt (car stack)))
- (goto-char (car elt))
- (setq replaced (eq t (cdr elt)))
- (or replaced
- (store-match-data (cdr elt)))
- (setq stack (cdr stack)))
- (message "No previous match")
- (ding 'no-terminate)
- (sit-for 1)))
- ((eq def 'act)
- (or replaced
- (progn
- (replace-match next-replacement nocasify literal)
- (setq replace-count (1+ replace-count))))
- (setq done t replaced t))
- ((eq def 'act-and-exit)
- (or replaced
- (progn
- (replace-match next-replacement nocasify literal)
- (setq replace-count (1+ replace-count))))
- (setq keep-going nil)
- (setq done t replaced t))
- ((eq def 'act-and-show)
- (if (not replaced)
- (progn
- (replace-match next-replacement nocasify literal)
- (setq replace-count (1+ replace-count))
- (setq replaced t))))
- ((eq def 'automatic)
- (or replaced
- (progn
- (replace-match next-replacement nocasify literal)
- (setq replace-count (1+ replace-count))))
- (setq done t query-flag nil replaced t))
- ((eq def 'skip)
- (setq done t))
- ((eq def 'recenter)
- (recenter nil))
- ((eq def 'edit)
- (store-match-data
- (prog1 (match-data)
- (save-excursion (recursive-edit))))
- ;; Before we make the replacement,
- ;; decide whether the search string
- ;; can match again just after this match.
- (if regexp-flag
- (setq match-again (looking-at search-string))))
- ((eq def 'delete-and-edit)
- (delete-region (match-beginning 0) (match-end 0))
- (store-match-data
- (prog1 (match-data)
- (save-excursion (recursive-edit))))
- (setq replaced t))
- ;; Note: we do not need to treat `exit-prefix'
- ;; specially here, since we reread
- ;; any unrecognized character.
- (t
- (setq this-command 'mode-exited)
- (setq keep-going nil)
- (setq unread-command-events
- (append (listify-key-sequence key)
- unread-command-events))
- (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 (match-data t)))
- stack))))
- (setq lastrepl (point)))
- (replace-dehighlight))
- (or unread-command-events
- (message "Replaced %d occurrence%s"
- replace-count
- (if (= replace-count 1) "" "s")))
- (and keep-going stack)))
-
-(defvar query-replace-highlight nil
- "*Non-nil means to highlight words during query replacement.")
-
-(defvar replace-overlay nil)
-
-(defun replace-dehighlight ()
- (and replace-overlay
- (progn
- (delete-overlay replace-overlay)
- (setq replace-overlay nil))))
-
-(defun replace-highlight (start end)
- (and query-replace-highlight
- (progn
- (or replace-overlay
- (progn
- (setq replace-overlay (make-overlay start end))
- (overlay-put replace-overlay 'face
- (if (internal-find-face 'query-replace)
- 'query-replace 'region))))
- (move-overlay replace-overlay start end (current-buffer)))))
-
-;;; replace.el ends here
diff --git a/lisp/reposition.el b/lisp/reposition.el
deleted file mode 100644
index cfb6079b93e..00000000000
--- a/lisp/reposition.el
+++ /dev/null
@@ -1,198 +0,0 @@
-;;; reposition.el --- center a Lisp function or comment on the screen
-
-;; Copyright (C) 1991, 1994 Free Software Foundation, Inc.
-
-;; Author: Michael D. Ernst <mernst@theory.lcs.mit.edu>
-;; Created: Jan 1991
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; 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.
-
-;;; Code:
-
-;;;###autoload
-(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
- (if (not (eobp)) (forward-char 1))
- (end-of-defun -1)
- ;; Skip whitespace, newlines, and form feeds.
- (if (re-search-forward "[^ \t\n\f]" nil t)
- (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")
- ))))
-
-;;;###autoload (define-key esc-map "\C-l" 'reposition-window)
-
-;;; 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)))
-
-;;; reposition.el ends here
diff --git a/lisp/resume.el b/lisp/resume.el
deleted file mode 100644
index 5e14679974d..00000000000
--- a/lisp/resume.el
+++ /dev/null
@@ -1,128 +0,0 @@
-;;; resume.el --- process command line args from within a suspended Emacs job
-
-;; Copyright (C) 1992 Free Software Foundation, Inc.
-
-;; Author: Joe Wells <jbw@bucsf.bu.edu>
-;; Adapted-By: ESR
-;; Keywords: processes
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The purpose of this library is to handle command line arguments
-;; when you resume an existing Emacs job.
-
-;; In order to use it, you must put this code in your .emacs file.
-
-;; (add-hook 'suspend-hook 'resume-suspend-hook)
-;; (add-hook 'suspend-resume-hook 'resume-process-args)
-
-;; You can't get the benefit of this library by using the `emacs' command,
-;; since that always starts a new Emacs job. Instead you must use a
-;; command called `edit' which knows how to resume an existing Emacs job
-;; if you have one, or start a new Emacs job if you don't have one.
-
-;; To define the `edit' command, run the script etc/emacs.csh (if you use CSH),
-;; or etc/emacs.bash if you use BASH. You would normally do this in your
-;; login script.
-
-;; Stephan Gildea suggested bug fix (gildea@bbn.com).
-;; Ideas from Michael DeCorte and other people.
-
-;;; Code:
-
-(defvar resume-emacs-args-file (expand-file-name "~/.emacs_args")
- "*This file is where arguments are placed for a suspended emacs job.")
-
-(defvar resume-emacs-args-buffer " *Command Line Args*"
- "Buffer that is used by resume-process-args.")
-
-(defun resume-process-args ()
- "Handler for command line args given when Emacs is resumed."
- (let ((start-buffer (current-buffer))
- (args-buffer (get-buffer-create resume-emacs-args-buffer))
- length args
- (command-line-default-directory default-directory))
- (unwind-protect
- (progn
- (set-buffer args-buffer)
- (erase-buffer)
- ;; get the contents of resume-emacs-args-file
- (condition-case ()
- (let ((result (insert-file-contents resume-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))
- (resume-write-buffer-to-file (current-buffer) resume-emacs-args-file)
- ;; if nothing was in buffer, args will be null
- (or (null args)
- (setq command-line-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)))))
-
-;;;###autoload
-(defun resume-suspend-hook ()
- "Clear out the file used for transmitting args when Emacs resumes."
- (save-excursion
- (set-buffer (get-buffer-create resume-emacs-args-buffer))
- (erase-buffer)
- (resume-write-buffer-to-file (current-buffer) resume-emacs-args-file)))
-
-(defun resume-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)))
-
-(provide 'resume)
-
-;;; resume.el ends here
diff --git a/lisp/rlogin.el b/lisp/rlogin.el
deleted file mode 100644
index a197133d63b..00000000000
--- a/lisp/rlogin.el
+++ /dev/null
@@ -1,335 +0,0 @@
-;;; rlogin.el --- remote login interface
-
-;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Noah Friedman
-;; Maintainer: Noah Friedman <friedman@prep.ai.mit.edu>
-;; Keywords: unix, comm
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; $Id: rlogin.el,v 1.34 1996/06/20 17:30:41 friedman Exp friedman $
-
-;;; Commentary:
-
-;; Support for remote logins using `rlogin'.
-;; This program is layered on top of shell.el; the code here only accounts
-;; for the variations needed to handle a remote process, e.g. directory
-;; tracking and the sending of some special characters.
-
-;; If you wish for rlogin mode to prompt you in the minibuffer for
-;; passwords when a password prompt appears, just enter m-x send-invisible
-;; and type in your line, or add `comint-watch-for-password-prompt' to
-;; `comint-output-filter-functions'.
-
-;;; Code:
-
-(require 'comint)
-(require 'shell)
-
-(defvar rlogin-program "rlogin"
- "*Name of program to invoke rlogin")
-
-(defvar rlogin-explicit-args nil
- "*List of arguments to pass to rlogin on the command line.")
-
-(defvar rlogin-mode-hook nil
- "*Hooks to run after setting current buffer to rlogin-mode.")
-
-(defvar rlogin-process-connection-type nil
- "*If non-`nil', use a pty for the local rlogin process.
-If `nil', use a pipe (if pipes are supported on the local system).
-
-Generally it is better not to waste ptys on systems which have a static
-number of them. On the other hand, some implementations of `rlogin' assume
-a pty is being used, and errors will result from using a pipe instead.")
-
-(defvar rlogin-directory-tracking-mode 'local
- "*Control whether and how to do directory tracking in an rlogin buffer.
-
-nil means don't do directory tracking.
-
-t means do so using an ftp remote file name.
-
-Any other value means do directory tracking using local file names.
-This works only if the remote machine and the local one
-share the same directories (through NFS). This is the default.
-
-This variable becomes local to a buffer when set in any fashion for it.
-
-It is better to use the function of the same name to change the behavior of
-directory tracking in an rlogin session once it has begun, rather than
-simply setting this variable, since the function does the necessary
-re-synching of directories.")
-
-(make-variable-buffer-local 'rlogin-directory-tracking-mode)
-
-(defvar rlogin-host nil
- "*The name of the remote host. This variable is buffer-local.")
-
-(defvar rlogin-remote-user nil
- "*The username used on the remote host.
-This variable is buffer-local and defaults to your local user name.
-If rlogin is invoked with the `-l' option to specify the remote username,
-this variable is set from that.")
-
-;; Initialize rlogin mode map.
-(defvar rlogin-mode-map '())
-(cond
- ((null rlogin-mode-map)
- (setq rlogin-mode-map (if (consp shell-mode-map)
- (cons 'keymap shell-mode-map)
- (copy-keymap shell-mode-map)))
- (define-key rlogin-mode-map "\C-c\C-c" 'rlogin-send-Ctrl-C)
- (define-key rlogin-mode-map "\C-c\C-d" 'rlogin-send-Ctrl-D)
- (define-key rlogin-mode-map "\C-c\C-z" 'rlogin-send-Ctrl-Z)
- (define-key rlogin-mode-map "\C-c\C-\\" 'rlogin-send-Ctrl-backslash)
- (define-key rlogin-mode-map "\C-d" 'rlogin-delchar-or-send-Ctrl-D)
- (define-key rlogin-mode-map "\C-i" 'rlogin-tab-or-complete)))
-
-
-;;;###autoload (add-hook 'same-window-regexps "^\\*rlogin-.*\\*\\(\\|<[0-9]+>\\)")
-
-(defvar rlogin-history nil)
-
-;;;###autoload
-(defun rlogin (input-args &optional buffer)
- "Open a network login connection via `rlogin' with args INPUT-ARGS.
-INPUT-ARGS should start with a host name; it may also contain
-other arguments for `rlogin'.
-
-Input is sent line-at-a-time to the remote connection.
-
-Communication with the remote host is recorded in a buffer `*rlogin-HOST*'
-\(or `*rlogin-USER@HOST*' if the remote username differs\).
-If a prefix argument is given and the buffer `*rlogin-HOST*' already exists,
-a new buffer with a different connection will be made.
-
-When called from a program, if the optional second argument BUFFER is
-a string or buffer, it specifies the buffer to use.
-
-The variable `rlogin-program' contains the name of the actual program to
-run. It can be a relative or absolute path.
-
-The variable `rlogin-explicit-args' is a list of arguments to give to
-the rlogin when starting. They are added after any arguments given in
-INPUT-ARGS.
-
-If the default value of `rlogin-directory-tracking-mode' is t, then the
-default directory in that buffer is set to a remote (FTP) file name to
-access your home directory on the remote machine. Occasionally this causes
-an error, if you cannot access the home directory on that machine. This
-error is harmless as long as you don't try to use that default directory.
-
-If `rlogin-directory-tracking-mode' is neither t nor nil, then the default
-directory is initially set up to your (local) home directory.
-This is useful if the remote machine and your local machine
-share the same files via NFS. This is the default.
-
-If you wish to change directory tracking styles during a session, use the
-function `rlogin-directory-tracking-mode' rather than simply setting the
-variable."
- (interactive (list
- (read-from-minibuffer "rlogin arguments (hostname first): "
- nil nil nil 'rlogin-history)
- current-prefix-arg))
-
- (let* ((process-connection-type rlogin-process-connection-type)
- (args (if rlogin-explicit-args
- (append (rlogin-parse-words input-args)
- rlogin-explicit-args)
- (rlogin-parse-words input-args)))
- (host (car args))
- (user (or (car (cdr (member "-l" args)))
- (user-login-name)))
- (buffer-name (if (string= user (user-login-name))
- (format "*rlogin-%s*" host)
- (format "*rlogin-%s@%s*" user host)))
- proc)
-
- (cond ((null buffer))
- ((stringp buffer)
- (setq buffer-name buffer))
- ((bufferp buffer)
- (setq buffer-name (buffer-name buffer)))
- ((numberp buffer)
- (setq buffer-name (format "%s<%d>" buffer-name buffer)))
- (t
- (setq buffer-name (generate-new-buffer-name buffer-name))))
-
- (setq buffer (get-buffer-create buffer-name))
- (pop-to-buffer buffer-name)
-
- (cond
- ((comint-check-proc buffer-name))
- (t
- (comint-exec buffer buffer-name rlogin-program nil args)
- (setq proc (get-buffer-process buffer))
- ;; Set process-mark to point-max in case there is text in the
- ;; buffer from a previous exited process.
- (set-marker (process-mark proc) (point-max))
-
- ;; comint-output-filter-functions is just like a hook, except that the
- ;; functions in that list are passed arguments. add-hook serves well
- ;; enough for modifying it.
- ;; comint-output-filter-functions should already have a
- ;; permanent-local property, at least in emacs 19.27 or later.
- (if (fboundp 'make-local-hook)
- (make-local-hook 'comint-output-filter-functions)
- (make-local-variable 'comint-output-filter-functions))
- (add-hook 'comint-output-filter-functions 'rlogin-carriage-filter)
-
- (rlogin-mode)
-
- (make-local-variable 'rlogin-host)
- (setq rlogin-host host)
- (make-local-variable 'rlogin-remote-user)
- (setq rlogin-remote-user user)
-
- (condition-case ()
- (cond ((eq rlogin-directory-tracking-mode t)
- ;; Do this here, rather than calling the tracking mode
- ;; function, to avoid a gratuitous resync check; the default
- ;; should be the user's home directory, be it local or remote.
- (setq comint-file-name-prefix
- (concat "/" rlogin-remote-user "@" rlogin-host ":"))
- (cd-absolute comint-file-name-prefix))
- ((null rlogin-directory-tracking-mode))
- (t
- (cd-absolute (concat comint-file-name-prefix "~/"))))
- (error nil))))))
-
-(defun rlogin-mode ()
- "Set major-mode for rlogin sessions.
-If `rlogin-mode-hook' is set, run it."
- (interactive)
- (kill-all-local-variables)
- (shell-mode)
- (setq major-mode 'rlogin-mode)
- (setq mode-name "rlogin")
- (use-local-map rlogin-mode-map)
- (setq shell-dirtrackp rlogin-directory-tracking-mode)
- (make-local-variable 'comint-file-name-prefix)
- (run-hooks 'rlogin-mode-hook))
-
-(defun rlogin-directory-tracking-mode (&optional prefix)
- "Do remote or local directory tracking, or disable entirely.
-
-If called with no prefix argument or a unspecified prefix argument (just
-``\\[universal-argument]'' with no number) do remote directory tracking via
-ange-ftp. If called as a function, give it no argument.
-
-If called with a negative prefix argument, disable directory tracking
-entirely.
-
-If called with a positive, numeric prefix argument, e.g.
-``\\[universal-argument] 1 M-x rlogin-directory-tracking-mode\'',
-then do directory tracking but assume the remote filesystem is the same as
-the local system. This only works in general if the remote machine and the
-local one share the same directories (through NFS)."
- (interactive "P")
- (cond
- ((or (null prefix)
- (consp prefix))
- (setq rlogin-directory-tracking-mode t)
- (setq shell-dirtrackp t)
- (setq comint-file-name-prefix
- (concat "/" rlogin-remote-user "@" rlogin-host ":")))
- ((< prefix 0)
- (setq rlogin-directory-tracking-mode nil)
- (setq shell-dirtrackp nil))
- (t
- (setq rlogin-directory-tracking-mode 'local)
- (setq comint-file-name-prefix "")
- (setq shell-dirtrackp t)))
- (cond
- (shell-dirtrackp
- (let* ((proc (get-buffer-process (current-buffer)))
- (proc-mark (process-mark proc))
- (current-input (buffer-substring proc-mark (point-max)))
- (orig-point (point))
- (offset (and (>= orig-point proc-mark)
- (- (point-max) orig-point))))
- (unwind-protect
- (progn
- (delete-region proc-mark (point-max))
- (goto-char (point-max))
- (shell-resync-dirs))
- (goto-char proc-mark)
- (insert current-input)
- (if offset
- (goto-char (- (point-max) offset))
- (goto-char orig-point)))))))
-
-
-;; Parse a line into its constituent parts (words separated by
-;; whitespace). Return a list of the words.
-(defun rlogin-parse-words (line)
- (let ((list nil)
- (posn 0)
- (match-data (match-data)))
- (while (string-match "[^ \t\n]+" line posn)
- (setq list (cons (substring line (match-beginning 0) (match-end 0))
- list))
- (setq posn (match-end 0)))
- (store-match-data (match-data))
- (nreverse list)))
-
-(defun rlogin-carriage-filter (string)
- (let* ((point-marker (point-marker))
- (end (process-mark (get-buffer-process (current-buffer))))
- (beg (or (and (boundp 'comint-last-output-start)
- comint-last-output-start)
- (- end (length string)))))
- (goto-char beg)
- (while (search-forward "\C-m" end t)
- (delete-char -1))
- (goto-char point-marker)))
-
-(defun rlogin-send-Ctrl-C ()
- (interactive)
- (send-string nil "\C-c"))
-
-(defun rlogin-send-Ctrl-D ()
- (interactive)
- (send-string nil "\C-d"))
-
-(defun rlogin-send-Ctrl-Z ()
- (interactive)
- (send-string nil "\C-z"))
-
-(defun rlogin-send-Ctrl-backslash ()
- (interactive)
- (send-string nil "\C-\\"))
-
-(defun rlogin-delchar-or-send-Ctrl-D (arg)
- "\
-Delete ARG characters forward, or send a C-d to process if at end of buffer."
- (interactive "p")
- (if (eobp)
- (rlogin-send-Ctrl-D)
- (delete-char arg)))
-
-(defun rlogin-tab-or-complete ()
- "Complete file name if doing directory tracking, or just insert TAB."
- (interactive)
- (if rlogin-directory-tracking-mode
- (comint-dynamic-complete)
- (insert "\C-i")))
-
-;;; rlogin.el ends here
diff --git a/lisp/rot13.el b/lisp/rot13.el
deleted file mode 100644
index e346c97a5f7..00000000000
--- a/lisp/rot13.el
+++ /dev/null
@@ -1,67 +0,0 @@
-;;; rot13.el --- display a buffer in rot13.
-
-;; Copyright (C) 1988 Free Software Foundation, Inc.
-
-;; Author: Howard Gayle:
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The single entry point, `rot13-other-window', performs a Caesar cipher
-;; encrypt/decrypt on the current buffer and displays the result in another
-;; window. Rot13 encryption is sometimes used on USENET as a read-at-your-
-;; own-risk wrapper for material some might consider offensive, such as
-;; ethnic humor.
-;;
-;; Written by Howard Gayle.
-;; This hack is mainly to show off the char table stuff.
-
-;;; Code:
-
-(defvar rot13-display-table
- (let ((table (make-display-table))
- (i 0))
- (while (< i 26)
- (aset table (+ i ?a) (vector (+ (% (+ i 13) 26) ?a)))
- (aset table (+ i ?A) (vector (+ (% (+ i 13) 26) ?A)))
- (setq i (1+ i)))
- table)
- "Char table for rot 13 display.")
-
-;;;###autoload
-(defun rot13-other-window ()
- "Display current buffer in rot 13 in another window.
-To terminate the rot13 display, delete that window."
- (interactive)
- (let ((w (display-buffer (current-buffer) t)))
- (set-window-display-table w rot13-display-table)))
-
-;;;###autoload
-(defun toggle-rot13-mode ()
- "Toggle the use of rot 13 encoding for the current window."
- (interactive)
- (if (eq (window-display-table (selected-window)) rot13-display-table)
- (set-window-display-table (selected-window) nil)
- (if (null (window-display-table (selected-window)))
- (set-window-display-table (selected-window) rot13-display-table))))
-
-(provide 'rot13)
-
-;;; rot13.el ends here
diff --git a/lisp/rsz-mini.el b/lisp/rsz-mini.el
deleted file mode 100644
index da5f4b478ba..00000000000
--- a/lisp/rsz-mini.el
+++ /dev/null
@@ -1,254 +0,0 @@
-;;; rsz-mini.el --- dynamically resize minibuffer to display entire contents
-
-;; Copyright (C) 1990, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Noah Friedman <friedman@prep.ai.mit.edu>
-;; Roland McGrath <roland@prep.ai.mit.edu>
-;; Maintainer: friedman@prep.ai.mit.edu
-;; Keywords: minibuffer, window, frame, display
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package allows the entire contents (or as much as possible) of the
-;; minibuffer to be visible at once when typing. As the end of a line is
-;; reached, the minibuffer will resize itself. When the user is done
-;; typing, the minibuffer will return to its original size.
-
-;; In window systems where it is possible to have a frame in which the
-;; minibuffer is the only window, the frame itself can be resized. In
-;; Emacs 19.22 and earlier, the frame may not be properly returned to
-;; its original size after it ceases to be active because
-;; `minibuffer-exit-hook' didn't exist until version 19.23.
-;;
-;; Prior to Emacs 19.26, minibuffer-exit-hook wasn't called after exiting
-;; from the minibuffer by hitting the quit char. That meant that the
-;; frame size restoration function wasn't being called in that case. In
-;; 19.26 or later, minibuffer-exit-hook should be called anyway.
-
-;; Note that the minibuffer and echo area are not the same! They simply
-;; happen to occupy roughly the same place on the frame. Messages put in
-;; the echo area will not cause any resizing by this package.
-
-;; This package is considered a minor mode but it doesn't put anything in
-;; minor-mode-alist because this mode is specific to the minibuffer, which
-;; has no mode line.
-
-;; To enable or disable this mode, use M-x resize-minibuffer-mode.
-
-;;; Code:
-
-
-;;;###autoload
-(defvar resize-minibuffer-mode nil
- "*If non-`nil', resize the minibuffer so its entire contents are visible.")
-
-;;;###autoload
-(defvar resize-minibuffer-window-max-height nil
- "*Maximum size the minibuffer window is allowed to become.
-If less than 1 or not a number, the limit is the height of the frame in
-which the active minibuffer window resides.")
-
-;;;###autoload
-(defvar resize-minibuffer-window-exactly t
- "*Allow making minibuffer exactly the size to display all its contents.
-If `nil', the minibuffer window can temporarily increase in size but
-never get smaller while it is active. Any other value allows exact
-resizing.")
-
-;;;###autoload
-(defvar resize-minibuffer-frame nil
- "*Allow changing the frame height of minibuffer frames.
-If non-`nil' and the active minibuffer is the sole window in its frame,
-allow changing the frame height.")
-
-;;;###autoload
-(defvar resize-minibuffer-frame-max-height nil
- "*Maximum size the minibuffer frame is allowed to become.
-If less than 1 or not a number, there is no limit.")
-
-;;;###autoload
-(defvar resize-minibuffer-frame-exactly t
- "*Allow making minibuffer frame exactly the size to display all its contents.
-If `nil', the minibuffer frame can temporarily increase in size but
-never get smaller while it is active. Any other value allows exact
-resizing.")
-
-;; Variable used to store the height of the minibuffer frame
-;; on entry, so it can be restored on exit. It is made local before it is
-;; modified. Do not use it yourself.
-(defvar resize-minibuffer-frame-original-height nil)
-
-
-;;;###autoload
-(defun resize-minibuffer-mode (&optional prefix)
- "Enable or disable resize-minibuffer mode.
-A negative prefix argument disables this mode. A positive argument or
-argument of 0 enables it.
-
-When this minor mode is enabled, the minibuffer is dynamically resized to
-contain the entire region of text put in it as you type.
-
-The variable `resize-minibuffer-mode' is set to t or nil depending on
-whether this mode is active or not.
-
-The maximum height to which the minibuffer can grow is controlled by the
-variable `resize-minibuffer-window-max-height'.
-
-The variable `resize-minibuffer-window-exactly' determines whether the
-minibuffer window should ever be shrunk to make it no larger than needed to
-display its contents.
-
-When using a window system, it is possible for a minibuffer to be the sole
-window in a frame. Since that window is already its maximum size, the only
-way to make more text visible at once is to increase the size of the frame.
-The variable `resize-minibuffer-frame' controls whether this should be
-done. The variables `resize-minibuffer-frame-max-height' and
-`resize-minibuffer-frame-exactly' are analogous to their window
-counterparts."
- (interactive "p")
- (or prefix (setq prefix 0))
- (cond
- ((>= prefix 0)
- (setq resize-minibuffer-mode t))
- (t
- (setq resize-minibuffer-mode nil))))
-
-(defun resize-minibuffer-setup ()
- (cond
- (resize-minibuffer-mode
- (cond
- ((and window-system
- (eq 'only (cdr (assq 'minibuffer (frame-parameters)))))
- ;; Checking for resize-minibuffer-frame is done outside the cond
- ;; predicate because that should always be t if this is a minibuffer
- ;; frame; it just shouldn't do anything if this flag is nil.
- (and resize-minibuffer-frame
- (progn
- ;; Can't trust the height stored in minibuffer-frame-alist
- ;; since the frame can be resized by the window manager and
- ;; that variable isn't updated.
- (make-local-variable 'resize-minibuffer-frame-original-height)
- (setq resize-minibuffer-frame-original-height (frame-height))
-
- (make-local-hook 'post-command-hook)
- (add-hook 'post-command-hook 'resize-minibuffer-frame 'append t)
-
- (make-local-hook 'minibuffer-exit-hook)
- (add-hook 'minibuffer-exit-hook 'resize-minibuffer-frame-restore
- nil t)
-
- (resize-minibuffer-frame))))
- (t
- (make-local-variable 'post-command-hook)
- ;; Copy this because add-hook modifies the list structure.
- (setq post-command-hook (copy-sequence post-command-hook))
- (add-hook 'post-command-hook 'resize-minibuffer-window 'append)
-
- (make-local-variable 'minibuffer-exit-hook)
- (add-hook 'minibuffer-exit-hook 'resize-minibuffer-window-restore)
-
- (resize-minibuffer-window))))))
-
-(defun resize-minibuffer-count-window-lines (&optional start end)
- "Return number of window lines occupied by text in region.
-The number of window lines may be greater than the number of actual lines
-in the buffer if any wrap on the display due to their length.
-
-Optional arguments START and END default to point-min and point-max,
-respectively."
- (or start (setq start (point-min)))
- (or end (setq end (point-max)))
- (if (= start end)
- 0
- (save-excursion
- (save-restriction
- (widen)
- (narrow-to-region start end)
- (goto-char start)
- (vertical-motion (buffer-size))))))
-
-
-;; Resize the minibuffer window to contain the minibuffer's contents.
-(defun resize-minibuffer-window ()
- (and (eq (selected-window) (minibuffer-window))
- (let ((height (window-height))
- (lines (1+ (resize-minibuffer-count-window-lines))))
- (and (numberp resize-minibuffer-window-max-height)
- (> resize-minibuffer-window-max-height 0)
- (setq lines (min lines resize-minibuffer-window-max-height)))
- (or (if resize-minibuffer-window-exactly
- (= lines height)
- (<= lines height))
- (enlarge-window (- lines height))))))
-
-;; This resizes the minibuffer back to one line as soon as it is exited
-;; (e.g. when the user hits RET). This way, subsequent messages put in the
-;; echo area aren't cluttered with leftover minibuffer text.
-;; It should be called by minibuffer-exit-hook.
-;;
-;; Note that because it calls sit-for to force a screen update, strange
-;; things may happen in the minibuffer, such as unexpanded partial
-;; completions by complete.el showing their completion.
-;; If this bothers you, just redefine this function to do nothing, in, say,
-;; your after-load-alist. Perhaps there should be an option variable,
-;; but I don't know if there's really any demand for it.
-;; (Clobbering this definition is harmless because eventually emacs restores
-;; its idea of the minibuffer window size when the minibuffer isn't in use
-;; anyway; this is just a kludge because of the timing for that update).
-(defun resize-minibuffer-window-restore ()
- (cond
- ((not (eq (minibuffer-window) (selected-window))))
- ((> (window-height) 1)
- (enlarge-window (- 1 (window-height)))
- (sit-for 0))))
-
-
-;; Resize the minibuffer frame to contain the minibuffer's contents.
-;; The minibuffer frame must be the current frame.
-(defun resize-minibuffer-frame ()
- (let ((height (frame-height))
- (lines (1+ (resize-minibuffer-count-window-lines))))
- (and (numberp resize-minibuffer-frame-max-height)
- (> resize-minibuffer-frame-max-height 0)
- (setq lines (min lines resize-minibuffer-frame-max-height)))
- (cond
- ((> lines height)
- (set-frame-size (window-frame (minibuffer-window)) (frame-width) lines))
- ((and resize-minibuffer-frame-exactly
- (> height resize-minibuffer-frame-original-height)
- (< lines height))
- (set-frame-size (window-frame (minibuffer-window))
- (frame-width) lines)))))
-
-;; Restore the original height of the frame.
-;; resize-minibuffer-frame-original-height is set in
-;; resize-minibuffer-setup.
-(defun resize-minibuffer-frame-restore ()
- (set-frame-size (window-frame (minibuffer-window))
- (frame-width)
- resize-minibuffer-frame-original-height))
-
-
-(provide 'rsz-mini)
-
-(add-hook 'minibuffer-setup-hook 'resize-minibuffer-setup)
-(resize-minibuffer-mode)
-
-;; rsz-mini.el ends here
diff --git a/lisp/s-region.el b/lisp/s-region.el
deleted file mode 100644
index 81cc0470026..00000000000
--- a/lisp/s-region.el
+++ /dev/null
@@ -1,124 +0,0 @@
-;;; s-region.el --- set region using shift key.
-
-;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Morten Welinder (terra@diku.dk)
-;; Keywords: terminals
-;; Favourite-brand-of-beer: None, I hate beer.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Having loaded this code you can set the region by holding down the
-;; shift key and move the cursor to the other end of the region. The
-;; functionality provided by this code is similar to that provided by
-;; the editors of Borland International's compilers for ms-dos.
-
-;; Currently, s-region-move may be bound only to events that are vectors
-;; of length one and whose last element is a symbol. Also, the functions
-;; that are given this kind of overlay should be (interactive "p")
-;; functions.
-
-;; If the following keys are not already bound then...
-;; C-insert is bound to copy-region-as-kill
-;; S-delete is bound to kill-region
-;; S-insert is bound to yank
-
-;;; Code:
-
-(defvar s-region-overlay (make-overlay 1 1))
-(overlay-put s-region-overlay 'face 'region)
-(overlay-put s-region-overlay 'priority 1000000) ; for hilit19
-
-(defun s-region-unshift (key)
- "Remove shift modifier from last keypress KEY and return that as a key."
- (if (vectorp key)
- (let ((last (aref key (1- (length key)))))
- (if (symbolp last)
- (let* ((keyname (symbol-name last))
- (pos (string-match "S-" keyname)))
- (if pos
- ;; We skip all initial parts of the event assuming that
- ;; those are setting up the prefix argument to the command.
- (vector (intern (concat (substring keyname 0 pos)
- (substring keyname (+ 2 pos)))))
- (error "Non-shifted key: %S" key)))
- (error "Key does not end in a symbol: %S" key)))
- (error "Non-vector key: %S" key)))
-
-(defun s-region-move-p1 (&rest arg)
- "This is an overlay function to point-moving keys that are interactive \"p\""
- (interactive "p")
- (apply (function s-region-move) arg))
-
-(defun s-region-move-p2 (&rest arg)
- "This is an overlay function to point-moving keys that are interactive \"P\""
- (interactive "P")
- (apply (function s-region-move) arg))
-
-(defun s-region-move (&rest arg)
- (if (if mark-active (not (equal last-command 's-region-move)) t)
- (set-mark-command nil)
- (message "")) ; delete the "Mark set" message
- (setq this-command 's-region-move)
- (apply (key-binding (s-region-unshift (this-command-keys))) arg)
- (move-overlay s-region-overlay (mark) (point) (current-buffer))
- (sit-for 1)
- (delete-overlay s-region-overlay))
-
-(defun s-region-bind (keylist &optional map)
- "Bind shifted keys in KEYLIST to s-region-move-p1 or s-region-move-p2.
-Each key in KEYLIST is shifted and bound to one of the s-region-move
-functions provided it is already bound to some command or other.
-Optional third argument MAP specifies keymap to add binding to, defaulting
-to global keymap."
- (let ((p2 (list 'scroll-up 'scroll-down
- 'beginning-of-buffer 'end-of-buffer)))
- (or map (setq map global-map))
- (while keylist
- (let* ((key (car keylist))
- (binding (key-binding key)))
- (if (commandp binding)
- (define-key
- map
- (vector (intern (concat "S-" (symbol-name (aref key 0)))))
- (cond ((memq binding p2)
- 's-region-move-p2)
- (t 's-region-move-p1)))))
- (setq keylist (cdr keylist)))))
-
-;; Single keys (plus modifiers) only!
-(s-region-bind
- (list [right] [left] [up] [down]
- [C-left] [C-right] [C-up] [C-down]
- [M-left] [M-right] [M-up] [M-down]
- [next] [previous] [home] [end]
- [C-next] [C-previous] [C-home] [C-end]
- [M-next] [M-previous] [M-home] [M-end]))
-
-(or (global-key-binding [C-insert])
- (global-set-key [C-insert] 'copy-region-as-kill))
-(or (global-key-binding [S-delete])
- (global-set-key [S-delete] 'kill-region))
-(or (global-key-binding [S-insert])
- (global-set-key [S-insert] 'yank))
-
-(provide 's-region)
-
-;; s-region.el ends here.
diff --git a/lisp/saveplace.el b/lisp/saveplace.el
deleted file mode 100644
index 364e766dcb0..00000000000
--- a/lisp/saveplace.el
+++ /dev/null
@@ -1,229 +0,0 @@
-;;; saveplace.el --- automatically save place in files.
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Karl Fogel <kfogel@cs.oberlin.edu>
-;; Maintainer: FSF
-;; Created: July, 1993
-;; Keywords: bookmarks, placeholders
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Automatically save place in files, so that visiting them later
-;; (even during a different Emacs session) automatically moves point
-;; to the saved position, when the file is first found. Uses the
-;; value of buffer-local variable save-place to determine whether to
-;; save position or not.
-;;
-;; Thanks to Stefan Schoef, who sent a patch with the
-;; `save-place-version-control' stuff in it.
-
-;;; Code:
-
-;; this is what I was using during testing:
-;; (define-key ctl-x-map "p" 'toggle-save-place)
-
-(defvar save-place-alist nil
- "Alist of saved places to go back to when revisiting files.
-Each element looks like (FILENAME . POSITION);
-visiting file FILENAME goes automatically to position POSITION
-rather than the beginning of the buffer.
-This alist is saved between Emacs sessions.")
-
-(defvar save-place nil
- "*Non-nil means automatically save place in each file.
-This means when you visit a file, point goes to the last place
-where it was when you previously visited the same file.
-This variable is automatically buffer-local.
-
-If you wish your place in any file to always be automatically saved,
-simply put this in your `~/.emacs' file:
-
-\(setq-default save-place t\)")
-
-(make-variable-buffer-local 'save-place)
-
-(defvar save-place-file (convert-standard-filename "~/.emacs-places")
- "*Name of the file that records `save-place-alist' value.")
-
-(defvar save-place-version-control 'nospecial
- "*Controls whether to make numbered backups of master save-place file.
-It can have four values: t, nil, `never', and `nospecial'. The first
-three have the same meaning that they do for the variable
-`version-control', and the final value `nospecial' means just use the
-value of `version-control'.")
-
-(defvar save-place-loaded nil
- "Non-nil means that the `save-place-file' has been loaded.")
-
-(defvar save-place-limit nil
- "Maximum number of entries to retain in the list; nil means no limit.")
-
-(defun toggle-save-place (&optional parg)
- "Toggle whether to save your place in this file between sessions.
-If this mode is enabled, point is recorded when you kill the buffer
-or exit Emacs. Visiting this file again will go to that position,
-even in a later Emacs session.
-
-If called with a prefix arg, the mode is enabled if and only if
-the argument is positive.
-
-To save places automatically in all files, put this in your `.emacs' file:
-
-\(setq-default save-place t\)"
- (interactive "P")
- (if (not buffer-file-name)
- (message "Buffer `%s' not visiting a file" (buffer-name))
- (if (and save-place (or (not parg) (<= parg 0)))
- (progn
- (message "No place will be saved in this file")
- (setq save-place nil))
- (message "Place will be saved")
- (setq save-place t))))
-
-(defun save-place-to-alist ()
- ;; put filename and point in a cons box and then cons that onto the
- ;; front of the save-place-alist, if save-place is non-nil.
- ;; Otherwise, just delete that file from the alist.
- ;; first check to make sure alist has been loaded in from the master
- ;; file. If not, do so, then feel free to modify the alist. It
- ;; will be saved again when Emacs is killed.
- (or save-place-loaded (load-save-place-alist-from-file))
- (if buffer-file-name
- (progn
- (let ((cell (assoc buffer-file-name save-place-alist)))
- (if cell
- (setq save-place-alist (delq cell save-place-alist))))
- (if save-place
- (setq save-place-alist
- (cons (cons buffer-file-name
- (if (not (eq major-mode 'hexl-mode))
- (point)
- (1+ (hexl-current-address))))
- save-place-alist))))))
-
-(defun save-place-alist-to-file ()
- (let ((file (expand-file-name save-place-file)))
- (save-excursion
- (message "Saving places to %s..." file)
- (set-buffer (get-buffer-create " *Saved Places*"))
- (delete-region (point-min) (point-max))
- (if (file-readable-p file)
- (insert-file-contents file))
- (delete-region (point-min) (point-max))
- (goto-char (point-min))
- (print save-place-alist (current-buffer))
- (let ((version-control
- (cond
- ((null save-place-version-control) nil)
- ((eq 'never save-place-version-control) 'never)
- ((eq 'nospecial save-place-version-control) version-control)
- (t
- t))))
- (write-file file)
- (kill-buffer (current-buffer))
- (message "Saving places to %s...done" file)))))
-
-(defun load-save-place-alist-from-file ()
- (if (not save-place-loaded)
- (progn
- (setq save-place-loaded t)
- (let ((file (expand-file-name save-place-file)))
- ;; make sure that the alist does not get overwritten, and then
- ;; load it if it exists:
- (if (file-readable-p file)
- (save-excursion
- (message "Loading places from %s..." save-place-file)
- ;; don't want to use find-file because we have been
- ;; adding hooks to it.
- (set-buffer (get-buffer-create " *Saved Places*"))
- (delete-region (point-min) (point-max))
- (insert-file-contents file)
- (goto-char (point-min))
- (setq save-place-alist
- (car (read-from-string
- (buffer-substring (point-min) (point-max)))))
-
- ;; If there is a limit, and we're over it, then we'll
- ;; have to truncate the end of the list:
- (if save-place-limit
- (if (<= save-place-limit 0)
- ;; Zero gets special cased. I'm not thrilled
- ;; with this, but the loop for >= 1 is tight.
- (setq save-place-alist nil)
- ;; Else the limit is >= 1, so enforce it by
- ;; counting and then `setcdr'ing.
- (let ((s save-place-alist)
- (count 1))
- (while s
- (if (>= count save-place-limit)
- (setcdr s nil)
- (setq count (1+ count)))
- (setq s (cdr s))))))
-
- (kill-buffer (current-buffer))
- (message "Loading places from %s...done" file)
- t)
- t)
- nil))))
-
-(defun save-places-to-alist ()
- ;; go through buffer-list, saving places to alist if save-place is
- ;; non-nil, deleting them from alist if it is nil.
- (let ((buf-list (buffer-list)))
- (while buf-list
- ;; put this into a save-excursion in case someone is counting on
- ;; another function in kill-emacs-hook to act on the last buffer
- ;; they were in:
- (save-excursion
- (set-buffer (car buf-list))
- ;; save-place checks buffer-file-name too, but we can avoid
- ;; overhead of function call by checking here too.
- (and buffer-file-name (save-place-to-alist))
- (setq buf-list (cdr buf-list))))))
-
-(defun save-place-find-file-hook ()
- (or save-place-loaded (load-save-place-alist-from-file))
- (let ((cell (assoc buffer-file-name save-place-alist)))
- (if cell
- (progn
- (or after-find-file-from-revert-buffer
- (goto-char (cdr cell)))
- ;; and make sure it will be saved again for later
- (setq save-place t)))))
-
-(defun save-place-kill-emacs-hook ()
- ;; First update the alist. This loads the old save-place-file if nec.
- (save-places-to-alist)
- ;; Now save the alist in the file, if we have ever loaded the file
- ;; (including just now).
- (if save-place-loaded
- (save-place-alist-to-file)))
-
-(add-hook 'find-file-hooks 'save-place-find-file-hook t)
-
-(add-hook 'kill-emacs-hook 'save-place-kill-emacs-hook)
-
-(add-hook 'kill-buffer-hook 'save-place-to-alist)
-
-(provide 'saveplace) ; why not...
-
-;;; saveplace.el ends here
-
diff --git a/lisp/score-mode.el b/lisp/score-mode.el
deleted file mode 100644
index 8505a93185b..00000000000
--- a/lisp/score-mode.el
+++ /dev/null
@@ -1,110 +0,0 @@
-;;; score-mode.el --- mode for editing Gnus score files
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news, mail
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'easymenu)
-(require 'timezone)
-(eval-when-compile (require 'cl))
-
-(defvar gnus-score-mode-hook nil
- "*Hook run in score mode buffers.")
-
-(defvar gnus-score-menu-hook nil
- "*Hook run after creating the score mode menu.")
-
-(defvar gnus-score-edit-exit-function nil
- "Function run on exit from the score buffer.")
-
-(defvar gnus-score-mode-map nil)
-(unless gnus-score-mode-map
- (setq gnus-score-mode-map (copy-keymap emacs-lisp-mode-map))
- (define-key gnus-score-mode-map "\C-c\C-c" 'gnus-score-edit-exit)
- (define-key gnus-score-mode-map "\C-c\C-d" 'gnus-score-edit-insert-date)
- (define-key gnus-score-mode-map "\C-c\C-p" 'gnus-score-pretty-print))
-
-;;;###autoload
-(defun gnus-score-mode ()
- "Mode for editing Gnus score files.
-This mode is an extended emacs-lisp mode.
-
-\\{gnus-score-mode-map}"
- (interactive)
- (kill-all-local-variables)
- (use-local-map gnus-score-mode-map)
- (when menu-bar-mode
- (gnus-score-make-menu-bar))
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (setq major-mode 'gnus-score-mode)
- (setq mode-name "Score")
- (lisp-mode-variables nil)
- (make-local-variable 'gnus-score-edit-exit-function)
- (run-hooks 'emacs-lisp-mode-hook 'gnus-score-mode-hook))
-
-(defun gnus-score-make-menu-bar ()
- (unless (boundp 'gnus-score-menu)
- (easy-menu-define
- gnus-score-menu gnus-score-mode-map ""
- '("Score"
- ["Exit" gnus-score-edit-exit t]
- ["Insert date" gnus-score-edit-insert-date t]
- ["Format" gnus-score-pretty-print t]))
- (run-hooks 'gnus-score-menu-hook)))
-
-(defun gnus-score-edit-insert-date ()
- "Insert date in numerical format."
- (interactive)
- (princ (gnus-score-day-number (current-time)) (current-buffer)))
-
-(defun gnus-score-pretty-print ()
- "Format the current score file."
- (interactive)
- (goto-char (point-min))
- (let ((form (read (current-buffer))))
- (erase-buffer)
- (pp form (current-buffer)))
- (goto-char (point-min)))
-
-(defun gnus-score-edit-exit ()
- "Stop editing the score file."
- (interactive)
- (unless (file-exists-p (file-name-directory (buffer-file-name)))
- (make-directory (file-name-directory (buffer-file-name)) t))
- (save-buffer)
- (bury-buffer (current-buffer))
- (let ((buf (current-buffer)))
- (when gnus-score-edit-exit-function
- (funcall gnus-score-edit-exit-function))
- (when (eq buf (current-buffer))
- (switch-to-buffer (other-buffer (current-buffer))))))
-
-(defun gnus-score-day-number (time)
- (let ((dat (decode-time time)))
- (timezone-absolute-from-gregorian
- (nth 4 dat) (nth 3 dat) (nth 5 dat))))
-
-(provide 'score-mode)
-
-;;; score-mode.el ends here
diff --git a/lisp/scroll-bar.el b/lisp/scroll-bar.el
deleted file mode 100644
index ec0f7164943..00000000000
--- a/lisp/scroll-bar.el
+++ /dev/null
@@ -1,241 +0,0 @@
-;;; scroll-bar.el --- window system-independent scroll bar support.
-
-;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: hardware
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Window-system-independent bindings of mouse clicks on the scroll bar.
-;; Presently emulates the scroll-bar behavior of xterm.
-
-;;; Code:
-
-(require 'mouse)
-
-
-;;;; Utilities.
-
-(defun scroll-bar-event-ratio (event)
- "Given a scroll bar event EVENT, return the scroll bar position as a ratio.
-The value is a cons cell (PORTION . WHOLE) containing two integers
-whose ratio gives the event's vertical position in the scroll bar, with 0
-referring to the top and 1 to the bottom."
- (nth 2 event))
-
-(defun scroll-bar-scale (num-denom whole)
- "Given a pair (NUM . DENOM) and WHOLE, return (/ (* NUM WHOLE) DENOM).
-This is handy for scaling a position on a scroll bar into real units,
-like buffer positions. If SCROLL-BAR-POS is the (PORTION . WHOLE) pair
-from a scroll bar event, then (scroll-bar-scale SCROLL-BAR-POS
-\(buffer-size)) is the position in the current buffer corresponding to
-that scroll bar position."
- ;; We multiply before we divide to maintain precision.
- ;; We use floating point because the product of a large buffer size
- ;; with a large scroll bar portion can easily overflow a lisp int.
- (truncate (/ (* (float (car num-denom)) whole) (cdr num-denom))))
-
-
-;;;; Helpful functions for enabling and disabling scroll bars.
-
-(defun scroll-bar-mode (flag)
- "Toggle display of vertical scroll bars on each frame.
-This command applies to all frames that exist and frames to be
-created in the future.
-With a numeric argument, if the argument is negative,
-turn off scroll bars; otherwise, turn on scroll bars."
- (interactive "P")
- (if flag (setq flag (prefix-numeric-value flag)))
-
- ;; Obtain the current setting by looking at default-frame-alist.
- (let ((scroll-bar-mode
- (let ((assq (assq 'vertical-scroll-bars default-frame-alist)))
- (if assq (cdr assq) t))))
-
- ;; Tweedle it according to the argument.
- (setq scroll-bar-mode (if (null flag) (not scroll-bar-mode)
- (or (not (numberp flag)) (>= flag 0))))
-
- ;; Apply it to default-frame-alist.
- (mapcar
- (function
- (lambda (param-name)
- (let ((parameter (assq param-name default-frame-alist)))
- (if (consp parameter)
- (setcdr parameter scroll-bar-mode)
- (setq default-frame-alist
- (cons (cons param-name scroll-bar-mode)
- default-frame-alist))))))
- '(vertical-scroll-bars horizontal-scroll-bars))
-
- ;; Apply it to existing frames.
- (let ((frames (frame-list)))
- (while frames
- (modify-frame-parameters
- (car frames)
- (list (cons 'vertical-scroll-bars scroll-bar-mode)
- (cons 'horizontal-scroll-bars scroll-bar-mode)))
- (setq frames (cdr frames))))))
-
-;;;; Buffer navigation using the scroll bar.
-
-;;; This was used for up-events on button 2, but no longer.
-(defun scroll-bar-set-window-start (event)
- "Set the window start according to where the scroll bar is dragged.
-EVENT should be a scroll bar click or drag event."
- (interactive "e")
- (let* ((end-position (event-end event))
- (window (nth 0 end-position))
- (portion-whole (nth 2 end-position)))
- (save-excursion
- (set-buffer (window-buffer window))
- (save-excursion
- (goto-char (+ (point-min)
- (scroll-bar-scale portion-whole
- (- (point-max) (point-min)))))
- (beginning-of-line)
- (set-window-start window (point))))))
-
-(defun scroll-bar-drag-position (portion-whole)
- "Calculate new window start for drag event."
- (save-excursion
- (goto-char (+ (point-min)
- (scroll-bar-scale portion-whole
- (- (point-max) (point-min)))))
- (beginning-of-line)
- (point)))
-
-(defun scroll-bar-maybe-set-window-start (event)
- "Set the window start according to where the scroll bar is dragged.
-Only change window start if the new start is substantially different.
-EVENT should be a scroll bar click or drag event."
- (interactive "e")
- (let* ((end-position (event-end event))
- (window (nth 0 end-position))
- (portion-whole (nth 2 end-position))
- (next-portion-whole (cons (1+ (car portion-whole))
- (cdr portion-whole)))
- portion-start
- next-portion-start
- (current-start (window-start window)))
- (save-excursion
- (set-buffer (window-buffer window))
- (setq portion-start (scroll-bar-drag-position portion-whole))
- (setq next-portion-start (max
- (scroll-bar-drag-position next-portion-whole)
- (1+ portion-start)))
- (if (or (> current-start next-portion-start)
- (< current-start portion-start))
- (set-window-start window portion-start)
- ;; Always set window start, to ensure scroll bar position is updated.
- (set-window-start window current-start)))))
-
-;; Scroll the window to the proper position for EVENT.
-(defun scroll-bar-drag-1 (event)
- (let* ((start-position (event-start event))
- (window (nth 0 start-position))
- (portion-whole (nth 2 start-position)))
- (save-excursion
- (set-buffer (window-buffer window))
- ;; Calculate position relative to the accessible part of the buffer.
- (goto-char (+ (point-min)
- (scroll-bar-scale portion-whole
- (- (point-max) (point-min)))))
- (beginning-of-line)
- (set-window-start window (point)))))
-
-(defun scroll-bar-drag (event)
- "Scroll the window by dragging the scroll bar slider.
-If you click outside the slider, the window scrolls to bring the slider there."
- (interactive "e")
- (let* (done
- (echo-keystrokes 0))
- (or point-before-scroll
- (setq point-before-scroll (point)))
- ;; Our scrolling can move point; don't let that clear point-before-scroll.
- (let (point-before-scroll)
- (scroll-bar-drag-1 event)
- (track-mouse
- (while (not done)
- (setq event (read-event))
- (if (eq (car-safe event) 'mouse-movement)
- (setq event (read-event)))
- (cond ((eq (car-safe event) 'scroll-bar-movement)
- (scroll-bar-drag-1 event))
- (t
- ;; Exit when we get the drag event; ignore that event.
- (setq done t)))))
- (sit-for 0))))
-
-(defun scroll-bar-scroll-down (event)
- "Scroll the window's top line down to the location of the scroll bar click.
-EVENT should be a scroll bar click."
- (interactive "e")
- (let ((old-selected-window (selected-window)))
- (unwind-protect
- (progn
- (let* ((end-position (event-end event))
- (window (nth 0 end-position))
- (portion-whole (nth 2 end-position)))
- (let (point-before-scroll)
- (select-window window))
- (or point-before-scroll
- (setq point-before-scroll (point)))
- (let (point-before-scroll)
- (scroll-down
- (scroll-bar-scale portion-whole (1- (window-height)))))))
- (select-window old-selected-window))))
-
-(defun scroll-bar-scroll-up (event)
- "Scroll the line next to the scroll bar click to the top of the window.
-EVENT should be a scroll bar click."
- (interactive "e")
- (let ((old-selected-window (selected-window)))
- (unwind-protect
- (progn
- (let* ((end-position (event-end event))
- (window (nth 0 end-position))
- (portion-whole (nth 2 end-position)))
- (let (point-before-scroll)
- (select-window window))
- (or point-before-scroll
- (setq point-before-scroll (point)))
- (let (point-before-scroll)
- (scroll-up
- (scroll-bar-scale portion-whole (1- (window-height)))))))
- (select-window old-selected-window))))
-
-
-;;;; Bindings.
-
-;;; For now, we'll set things up to work like xterm.
-(global-set-key [vertical-scroll-bar mouse-1] 'scroll-bar-scroll-up)
-(global-set-key [vertical-scroll-bar drag-mouse-1] 'scroll-bar-scroll-up)
-
-(global-set-key [vertical-scroll-bar down-mouse-2] 'scroll-bar-drag)
-
-(global-set-key [vertical-scroll-bar mouse-3] 'scroll-bar-scroll-down)
-(global-set-key [vertical-scroll-bar drag-mouse-3] 'scroll-bar-scroll-down)
-
-
-(provide 'scroll-bar)
-
-;;; scroll-bar.el ends here
diff --git a/lisp/select.el b/lisp/select.el
deleted file mode 100644
index 8fb51428272..00000000000
--- a/lisp/select.el
+++ /dev/null
@@ -1,310 +0,0 @@
-;;; select.el --- lisp portion of standard selection support.
-
-;; Keywords: internal
-
-;; Copyright (c) 1993, 1994 Free Software Foundation, Inc.
-;; Based partially on earlier release by Lucid.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;; This is for temporary compatibility with pre-release Emacs 19.
-(defalias 'x-selection 'x-get-selection)
-(defun x-get-selection (&optional type data-type)
- "Return the value of an X Windows selection.
-The argument TYPE (default `PRIMARY') says which selection,
-and the argument DATA-TYPE (default `STRING') says how to convert the data."
- (x-get-selection-internal (or type 'PRIMARY) (or data-type 'STRING)))
-
-(defun x-get-clipboard ()
- "Return text pasted to the clipboard."
- (x-get-selection-internal 'CLIPBOARD 'STRING))
-
-(defun x-set-selection (type data)
- "Make an X Windows selection of type TYPE and value DATA.
-The argument TYPE (default `PRIMARY') says which selection,
-and DATA specifies the contents. DATA may be a string,
-a symbol, an integer (or a cons of two integers or list of two integers).
-
-The selection may also be a cons of two markers pointing to the same buffer,
-or an overlay. In these cases, the selection is considered to be the text
-between the markers *at whatever time the selection is examined*.
-Thus, editing done in the buffer after you specify the selection
-can alter the effective value of the selection.
-
-The data may also be a vector of valid non-vector selection values.
-
-Interactively, the text of the region is used as the selection value."
- (interactive (if (not current-prefix-arg)
- (list 'PRIMARY (read-string "Set text for pasting: "))
- (list 'PRIMARY (substring (region-beginning) (region-end)))))
- ;; This is for temporary compatibility with pre-release Emacs 19.
- (if (stringp type)
- (setq type (intern type)))
- (or (x-valid-simple-selection-p data)
- (and (vectorp data)
- (let ((valid t)
- (i (1- (length data))))
- (while (>= i 0)
- (or (x-valid-simple-selection-p (aref data i))
- (setq valid nil))
- (setq i (1- i)))
- valid))
- (signal 'error (list "invalid selection" data)))
- (or type (setq type 'PRIMARY))
- (if data
- (x-own-selection-internal type data)
- (x-disown-selection-internal type))
- data)
-
-(defun x-valid-simple-selection-p (data)
- (or (stringp data)
- (symbolp data)
- (integerp data)
- (and (consp data)
- (integerp (car data))
- (or (integerp (cdr data))
- (and (consp (cdr data))
- (integerp (car (cdr data))))))
- (overlayp data)
- (and (consp data)
- (markerp (car data))
- (markerp (cdr data))
- (marker-buffer (car data))
- (marker-buffer (cdr data))
- (eq (marker-buffer (car data))
- (marker-buffer (cdr data)))
- (buffer-name (marker-buffer (car data)))
- (buffer-name (marker-buffer (cdr data))))))
-
-;;; Cut Buffer support
-
-(defun x-get-cut-buffer (&optional which-one)
- "Returns the value of one of the 8 X server cut-buffers. Optional arg
-WHICH-ONE should be a number from 0 to 7, defaulting to 0.
-Cut buffers are considered obsolete; you should use selections instead."
- (x-get-cut-buffer-internal
- (if which-one
- (aref [CUT_BUFFER0 CUT_BUFFER1 CUT_BUFFER2 CUT_BUFFER3
- CUT_BUFFER4 CUT_BUFFER5 CUT_BUFFER6 CUT_BUFFER7]
- which-one)
- 'CUT_BUFFER0)))
-
-(defun x-set-cut-buffer (string &optional push)
- "Store STRING into the X server's primary cut buffer.
-If PUSH is non-nil, also rotate the cut buffers:
-this means the previous value of the primary cut buffer moves the second
-cut buffer, and the second to the third, and so on (there are 8 buffers.)
-Cut buffers are considered obsolete; you should use selections instead."
- ;; Check the data type of STRING.
- (substring string 0 0)
- (if push
- (x-rotate-cut-buffers-internal 1))
- (x-store-cut-buffer-internal 'CUT_BUFFER0 string))
-
-
-;;; Functions to convert the selection into various other selection types.
-;;; Every selection type that Emacs handles is implemented this way, except
-;;; for TIMESTAMP, which is a special case.
-
-(defun xselect-convert-to-string (selection type value)
- (cond ((stringp value)
- value)
- ((overlayp value)
- (save-excursion
- (or (buffer-name (overlay-buffer value))
- (error "selection is in a killed buffer"))
- (set-buffer (overlay-buffer value))
- (buffer-substring (overlay-start value)
- (overlay-end value))))
- ((and (consp value)
- (markerp (car value))
- (markerp (cdr value)))
- (or (eq (marker-buffer (car value)) (marker-buffer (cdr value)))
- (signal 'error
- (list "markers must be in the same buffer"
- (car value) (cdr value))))
- (save-excursion
- (set-buffer (or (marker-buffer (car value))
- (error "selection is in a killed buffer")))
- (buffer-substring (car value) (cdr value))))
- (t nil)))
-
-(defun xselect-convert-to-length (selection type value)
- (let ((value
- (cond ((stringp value)
- (length value))
- ((overlayp value)
- (abs (- (overlay-end value) (overlay-start value))))
- ((and (consp value)
- (markerp (car value))
- (markerp (cdr value)))
- (or (eq (marker-buffer (car value))
- (marker-buffer (cdr value)))
- (signal 'error
- (list "markers must be in the same buffer"
- (car value) (cdr value))))
- (abs (- (car value) (cdr value)))))))
- (if value ; force it to be in 32-bit format.
- (cons (ash value -16) (logand value 65535))
- nil)))
-
-(defun xselect-convert-to-targets (selection type value)
- ;; return a vector of atoms, but remove duplicates first.
- (let* ((all (cons 'TIMESTAMP (mapcar 'car selection-converter-alist)))
- (rest all))
- (while rest
- (cond ((memq (car rest) (cdr rest))
- (setcdr rest (delq (car rest) (cdr rest))))
- ((eq (car (cdr rest)) '_EMACS_INTERNAL) ; shh, it's a secret
- (setcdr rest (cdr (cdr rest))))
- (t
- (setq rest (cdr rest)))))
- (apply 'vector all)))
-
-(defun xselect-convert-to-delete (selection type value)
- (x-disown-selection-internal selection)
- ;; A return value of nil means that we do not know how to do this conversion,
- ;; and replies with an "error". A return value of NULL means that we have
- ;; done the conversion (and any side-effects) but have no value to return.
- 'NULL)
-
-(defun xselect-convert-to-filename (selection type value)
- (cond ((overlayp value)
- (buffer-file-name (or (overlay-buffer value)
- (error "selection is in a killed buffer"))))
- ((and (consp value)
- (markerp (car value))
- (markerp (cdr value)))
- (buffer-file-name (or (marker-buffer (car value))
- (error "selection is in a killed buffer"))))
- (t nil)))
-
-(defun xselect-convert-to-charpos (selection type value)
- (let (a b tmp)
- (cond ((cond ((overlayp value)
- (setq a (overlay-start value)
- b (overlay-end value)))
- ((and (consp value)
- (markerp (car value))
- (markerp (cdr value)))
- (setq a (car value)
- b (cdr value))))
- (setq a (1- a) b (1- b)) ; zero-based
- (if (< b a) (setq tmp a a b b tmp))
- (cons 'SPAN
- (vector (cons (ash a -16) (logand a 65535))
- (cons (ash b -16) (logand b 65535))))))))
-
-(defun xselect-convert-to-lineno (selection type value)
- (let (a b buf tmp)
- (cond ((cond ((and (consp value)
- (markerp (car value))
- (markerp (cdr value)))
- (setq a (marker-position (car value))
- b (marker-position (cdr value))
- buf (marker-buffer (car value))))
- ((overlayp value)
- (setq buf (overlay-buffer value)
- a (overlay-start value)
- b (overlay-end value)))
- )
- (save-excursion
- (set-buffer buf)
- (setq a (count-lines 1 a)
- b (count-lines 1 b)))
- (if (< b a) (setq tmp a a b b tmp))
- (cons 'SPAN
- (vector (cons (ash a -16) (logand a 65535))
- (cons (ash b -16) (logand b 65535))))))))
-
-(defun xselect-convert-to-colno (selection type value)
- (let (a b buf tmp)
- (cond ((cond ((and (consp value)
- (markerp (car value))
- (markerp (cdr value)))
- (setq a (car value)
- b (cdr value)
- buf (marker-buffer a)))
- ((overlayp value)
- (setq buf (overlay-buffer value)
- a (overlay-start value)
- b (overlay-end value)))
- )
- (save-excursion
- (set-buffer buf)
- (goto-char a)
- (setq a (current-column))
- (goto-char b)
- (setq b (current-column)))
- (if (< b a) (setq tmp a a b b tmp))
- (cons 'SPAN
- (vector (cons (ash a -16) (logand a 65535))
- (cons (ash b -16) (logand b 65535))))))))
-
-(defun xselect-convert-to-os (selection type size)
- (symbol-name system-type))
-
-(defun xselect-convert-to-host (selection type size)
- (system-name))
-
-(defun xselect-convert-to-user (selection type size)
- (user-full-name))
-
-(defun xselect-convert-to-class (selection type size)
- "Emacs")
-
-;; We do not try to determine the name Emacs was invoked with,
-;; because it is not clean for a program's behavior to depend on that.
-(defun xselect-convert-to-name (selection type size)
- "emacs")
-
-(defun xselect-convert-to-integer (selection type value)
- (and (integerp value)
- (cons (ash value -16) (logand value 65535))))
-
-(defun xselect-convert-to-atom (selection type value)
- (and (symbolp value) value))
-
-(defun xselect-convert-to-identity (selection type value) ; used internally
- (vector value))
-
-(setq selection-converter-alist
- '((TEXT . xselect-convert-to-string)
- (STRING . xselect-convert-to-string)
- (TARGETS . xselect-convert-to-targets)
- (LENGTH . xselect-convert-to-length)
- (DELETE . xselect-convert-to-delete)
- (FILE_NAME . xselect-convert-to-filename)
- (CHARACTER_POSITION . xselect-convert-to-charpos)
- (LINE_NUMBER . xselect-convert-to-lineno)
- (COLUMN_NUMBER . xselect-convert-to-colno)
- (OWNER_OS . xselect-convert-to-os)
- (HOST_NAME . xselect-convert-to-host)
- (USER . xselect-convert-to-user)
- (CLASS . xselect-convert-to-class)
- (NAME . xselect-convert-to-name)
- (ATOM . xselect-convert-to-atom)
- (INTEGER . xselect-convert-to-integer)
- (_EMACS_INTERNAL . xselect-convert-to-identity)
- ))
-
-(provide 'select)
-
-;;; select.el ends here.
diff --git a/lisp/server.el b/lisp/server.el
deleted file mode 100644
index 78f10f422df..00000000000
--- a/lisp/server.el
+++ /dev/null
@@ -1,445 +0,0 @@
-;;; server.el --- Lisp code for GNU Emacs running as server process.
-
-;; Copyright (C) 1986, 1987, 1992, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: William Sommerfeld <wesommer@athena.mit.edu>
-;; Keywords: processes
-
-;; Changes by peck@sun.com and by rms.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This Lisp code is run in Emacs when it is to operate as
-;; a server for other processes.
-
-;; Load this library and do M-x server-edit to enable Emacs as a server.
-;; Emacs runs the program ../arch-lib/emacsserver as a subprocess
-;; for communication with clients. If there are no client buffers to edit,
-;; server-edit acts like (switch-to-buffer (other-buffer))
-
-;; When some other program runs "the editor" to edit a file,
-;; "the editor" can be the Emacs client program ../lib-src/emacsclient.
-;; This program transmits the file names to Emacs through
-;; the server subprocess, and Emacs visits them and lets you edit them.
-
-;; Note that any number of clients may dispatch files to emacs to be edited.
-
-;; When you finish editing a Server buffer, again call server-edit
-;; to mark that buffer as done for the client and switch to the next
-;; Server buffer. When all the buffers for a client have been edited
-;; and exited with server-edit, the client "editor" will return
-;; to the program that invoked it.
-
-;; 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:
-
-;; 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
-;; 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.
-
-;;; Code:
-
-(defvar server-program (expand-file-name "emacsserver" exec-directory)
- "*The program to use as the edit server.")
-
-(defvar server-visit-hook nil
- "*List of hooks to call when visiting a file for the Emacs server.")
-
-(defvar server-switch-hook nil
- "*List of hooks to call when switching to a buffer for the Emacs server.")
-
-(defvar server-done-hook nil
- "*List of hooks to call when done editing a buffer for the Emacs server.")
-
-(defvar server-process nil
- "the current server process")
-
-(defvar server-previous-string "")
-
-(defvar server-clients nil
- "List of current server clients.
-Each element is (CLIENTID BUFFERS...) where CLIENTID is a string
-that can be given to the server process to identify a client.
-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.")
-(make-variable-buffer-local 'server-buffer-clients)
-;; Changing major modes should not erase this local.
-(put 'server-buffer-clients 'permanent-local t)
-
-(defvar server-window nil
- "*The window to use for selecting Emacs server buffers.
-If nil, use the selected window.
-If it is a frame, use the frame's selected window.")
-
-(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.")
-
-(or (assq 'server-buffer-clients minor-mode-alist)
- (setq minor-mode-alist (cons '(server-buffer-clients " Server") minor-mode-alist)))
-
-;; If a *server* buffer exists,
-;; write STRING to it for logging purposes.
-(defun server-log (string)
- (if (get-buffer "*server*")
- (save-excursion
- (set-buffer "*server*")
- (goto-char (point-max))
- (insert (current-time-string) " " string)
- (or (bolp) (newline)))))
-
-(defun server-sentinel (proc msg)
- (cond ((eq (process-status proc) 'exit)
- (server-log (message "Server subprocess exited")))
- ((eq (process-status proc) 'signal)
- (server-log (message "Server subprocess killed")))))
-
-;;;###autoload
-(defun server-start (&optional leave-dead)
- "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 `emacsclient' in the
-Emacs distribution as your standard \"editor\".
-
-Prefix arg means just kill any existing server communications subprocess."
- (interactive "P")
- ;; kill it dead!
- (if server-process
- (progn
- (set-process-sentinel server-process nil)
- (condition-case () (delete-process server-process) (error nil))))
- ;; Delete the socket files made by previous server invocations.
- (let* ((sysname (system-name))
- (dot-index (string-match "\\." sysname)))
- (condition-case ()
- (delete-file (format "~/.emacs-server-%s" sysname))
- (error nil))
- (condition-case ()
- (delete-file (format "/tmp/esrv%d-%s" (user-uid) sysname))
- (error nil))
- ;; In case the server file name was made with a domainless hostname,
- ;; try deleting that name too.
- (if dot-index
- (let ((shortname (substring sysname 0 dot-index)))
- (condition-case ()
- (delete-file (format "~/.emacs-server-%s" shortname))
- (error nil))
- (condition-case ()
- (delete-file (format "/tmp/esrv%d-%s" (user-uid) shortname))
- (error nil)))))
- ;; If this Emacs already had a server, clear out associated status.
- (while server-clients
- (let ((buffer (nth 1 (car server-clients))))
- (server-buffer-done buffer)))
- (if leave-dead
- nil
- (if server-process
- (server-log (message "Restarting server")))
- ;; Using a pty is wasteful, and the separate session causes
- ;; annoyance sometimes (some systems kill idle sessions).
- (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)))
-
-;Process a request from the server to edit some files.
-;Format of STRING is "Client: CLIENTID PATH PATH PATH... \n"
-(defun server-process-filter (proc string)
- (server-log string)
- (setq string (concat server-previous-string string))
- ;; If the input is multiple lines,
- ;; process each line individually.
- (while (string-match "\n" string)
- (let ((request (substring string 0 (match-beginning 0)))
- client nowait
- (files nil)
- (lineno 1))
- ;; Remove this line from STRING.
- (setq string (substring string (match-end 0)))
- (if (string-match "^Error: " request)
- (message "Server error: %s" (substring request (match-end 0)))
- (if (string-match "^Client: " request)
- (progn
- (setq request (substring request (match-end 0)))
- (setq client (list (substring request 0 (string-match " " request))))
- (setq request (substring request (match-end 0)))
- (while (string-match "[^ ]+ " request)
- (let ((arg
- (substring request (match-beginning 0) (1- (match-end 0))))
- (pos 0))
- (setq request (substring request (match-end 0)))
- (if (string-match "\\`-nowait" arg)
- (setq nowait t)
- (if (string-match "\\`\\+[0-9]+\\'" arg)
- ;; ARG is a line number option.
- (setq lineno (read (substring arg 1)))
- ;; ARG is a file name.
- ;; Collapse multiple slashes to single slashes.
- (setq arg (command-line-normalize-file-name arg))
- ;; Undo the quoting that emacsclient does
- ;; for certain special characters.
- (while (string-match "&." arg pos)
- (setq pos (1+ (match-beginning 0)))
- (let ((nextchar (aref arg pos)))
- (cond ((= nextchar ?&)
- (setq arg (replace-match "&" t t arg)))
- ((= nextchar ?-)
- (setq arg (replace-match "-" t t arg)))
- (t
- (setq arg (replace-match " " t t arg))))))
- (setq files
- (cons (list arg lineno)
- files))
- (setq lineno 1)))))
- (server-visit-files files client nowait)
- ;; CLIENT is now a list (CLIENTNUM BUFFERS...)
- (or nowait
- (setq server-clients (cons client server-clients)))
- (server-switch-buffer (nth 1 client))
- (run-hooks 'server-switch-hook)
- (message (substitute-command-keys
- "When done with a buffer, type \\[server-edit]")))))))
- ;; Save for later any partial line that remains.
- (setq server-previous-string string))
-
-(defun server-visit-files (files client &optional nowait)
- "Finds FILES and returns the list CLIENT with the buffers nconc'd.
-FILES is an alist whose elements are (FILENAME LINENUMBER).
-NOWAIT non-nil means this client is not waiting for the results,
-so don't mark these buffers specially, just visit them normally."
- ;; Bind last-nonmenu-event to force use of keyboard, not mouse, for queries.
- (let (client-record (last-nonmenu-event t) (obuf (current-buffer)))
- ;; Restore the current buffer afterward, but not using save-excursion,
- ;; because we don't want to save point in this buffer
- ;; if it happens to be one of those specified by the server.
- (unwind-protect
- (while files
- ;; If there is an existing buffer modified or the file is modified,
- ;; revert it.
- ;; If there is an existing buffer with deleted file, offer to write it.
- (let* ((filen (car (car files)))
- (obuf (get-file-buffer filen)))
- (if (and obuf (set-buffer obuf))
- (if (file-exists-p filen)
- (if (or (not (verify-visited-file-modtime obuf))
- (buffer-modified-p obuf))
- (revert-buffer t nil))
- (if (y-or-n-p
- (concat "File no longer exists: "
- filen
- ", write buffer to file? "))
- (write-file filen)))
- (set-buffer (find-file-noselect filen))
- (run-hooks 'server-visit-hook)))
- (goto-line (nth 1 (car files)))
- (if (not nowait)
- (setq server-buffer-clients
- (cons (car client) server-buffer-clients)))
- (setq client-record (cons (current-buffer) client-record))
- (setq files (cdr files)))
- (set-buffer obuf))
- (nconc client client-record)))
-
-(defun server-buffer-done (buffer)
- "Mark BUFFER as \"done\" for its client(s).
-This buries the buffer, then returns a list of the form (NEXT-BUFFER KILLED).
-NEXT-BUFFER is another server buffer, as a suggestion for what to select next,
-or nil. KILLED is t if we killed BUFFER (because it was a temp file)."
- (let ((running (eq (process-status server-process) 'run))
- (next-buffer nil)
- (killed nil)
- (first t)
- (old-clients server-clients))
- (while old-clients
- (let ((client (car old-clients)))
- (or next-buffer
- (setq next-buffer (nth 1 (memq buffer client))))
- (delq buffer client)
- ;; Delete all dead buffers from CLIENT.
- (let ((tail client))
- (while tail
- (and (bufferp (car tail))
- (null (buffer-name (car tail)))
- (delq (car tail) client))
- (setq tail (cdr tail))))
- ;; If client now has no pending buffers,
- ;; tell it that it is done, and forget it entirely.
- (if (cdr client) nil
- (if running
- (progn
- ;; Don't send emacsserver two commands in close succession.
- ;; It cannot handle that.
- (or first (sit-for 1))
- (setq first nil)
- (send-string server-process
- (format "Close: %s Done\n" (car client)))
- (server-log (format "Close: %s Done\n" (car client)))))
- (setq server-clients (delq client server-clients))))
- (setq old-clients (cdr old-clients)))
- (if (and (bufferp buffer) (buffer-name buffer))
- (progn
- (save-excursion
- (set-buffer buffer)
- (setq server-buffer-clients nil)
- (run-hooks 'server-done-hook))
- (if (server-temp-file-p buffer)
- (progn (kill-buffer buffer)
- (setq killed t))
- (bury-buffer buffer))))
- (list next-buffer killed)))
-
-(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 server-done ()
- "Offer to save current buffer, mark it as \"done\" for clients.
-This buries the buffer, then returns a list of the form (NEXT-BUFFER KILLED).
-NEXT-BUFFER is another server buffer, as a suggestion for what to select next,
-or nil. KILLED is t if we killed the BUFFER (because it was a temp file)."
- (let ((buffer (current-buffer)))
- (if server-buffer-clients
- (progn
- (if (server-temp-file-p buffer)
- ;; For a temp file, save, and do make a non-numeric backup
- ;; (unless make-backup-files is nil).
- (let ((version-control nil)
- (buffer-backed-up nil))
- (save-buffer))
- (if (and (buffer-modified-p)
- (y-or-n-p (concat "Save file " buffer-file-name "? ")))
- (save-buffer buffer)))
- (server-buffer-done buffer)))))
-
-;; Ask before killing a server buffer.
-;; It was suggested to release its client instead,
-;; but I think that is dangerous--the client would proceed
-;; using whatever is on disk in that file. -- rms.
-(defun server-kill-buffer-query-function ()
- (or (not server-buffer-clients)
- (yes-or-no-p (format "Buffer `%s' still has clients; kill it? "
- (buffer-name (current-buffer))))))
-
-(add-hook 'kill-buffer-query-functions
- 'server-kill-buffer-query-function)
-
-(defun server-kill-emacs-query-function ()
- (let (live-client
- (tail server-clients))
- ;; See if any clients have any buffers that are still alive.
- (while tail
- (if (memq t (mapcar 'stringp (mapcar 'buffer-name (cdr (car tail)))))
- (setq live-client t))
- (setq tail (cdr tail)))
- (or (not live-client)
- (yes-or-no-p "Server buffers still have clients; exit anyway? "))))
-
-(add-hook 'kill-emacs-query-functions 'server-kill-emacs-query-function)
-
-(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.
-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 `make-backup-files', if nil, still
-inhibits a backup; you can set it locally in a particular buffer to
-prevent a backup for it.) 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)
- (memq (process-status server-process) '(signal exit)))
- (server-start nil)
- (apply 'server-switch-buffer (server-done))))
-
-(defun server-switch-buffer (&optional next-buffer killed-one)
- "Switch to another buffer, preferably one that has a client.
-Arg NEXT-BUFFER is a suggestion; if it is a live buffer, use it."
- ;; KILLED-ONE is t in a recursive call
- ;; if we have already killed one temp-file server buffer.
- ;; This means we should avoid the final "switch to some other buffer"
- ;; since we've already effectively done that.
- (cond ((and (windowp server-window)
- (window-live-p server-window))
- (select-window server-window))
- ((framep server-window)
- (if (not (frame-live-p server-window))
- (setq server-window (make-frame)))
- (select-window (frame-selected-window server-window))))
- (if (window-minibuffer-p (selected-window))
- (select-window (next-window nil 'nomini 0)))
- ;; Move to a non-dedicated window, if we have one.
- (let ((last-window (previous-window nil 'nomini 0)))
- (while (and (window-dedicated-p (selected-window))
- (not (eq last-window (selected-window))))
- (select-window (next-window nil 'nomini 0))))
- (set-window-dedicated-p (selected-window) nil)
- (if next-buffer
- (if (and (bufferp next-buffer)
- (buffer-name next-buffer))
- (switch-to-buffer next-buffer)
- ;; If NEXT-BUFFER is a dead buffer,
- ;; remove the server records for it
- ;; and try the next surviving server buffer.
- (apply 'server-switch-buffer
- (server-buffer-done next-buffer)))
- (if server-clients
- (server-switch-buffer (nth 1 (car server-clients)) killed-one)
- (if (not killed-one)
- (switch-to-buffer (other-buffer))))))
-
-(global-set-key "\C-x#" 'server-edit)
-
-(provide 'server)
-
-;;; server.el ends here
diff --git a/lisp/shadowfile.el b/lisp/shadowfile.el
deleted file mode 100644
index 13abf4026f0..00000000000
--- a/lisp/shadowfile.el
+++ /dev/null
@@ -1,843 +0,0 @@
-;;; shadowfile.el --- automatic file copying for Emacs 19
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Boris Goldowsky <boris@gnu.ai.mit.edu>
-;; Keywords: comm
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; LCD Archive Entry:
-;; shadowfile|Boris Goldowsky|boris@gnu.ai.mit.edu|
-;; Helps you keep identical copies of files in multiple places.|
-;; $Date: 1996/01/14 07:34:30 $ |$Revision: 1.7 $|~/misc/shadowfile.el.Z|
-
-;; Commentary:
-
-;; This package helps you to keep identical copies of files in more than one
-;; place - possibly on different machines. When you save a file, it checks
-;; whether it is on the list of files with "shadows", and if so, it tries to
-;; copy it when you exit emacs (or use the shadow-copy-files command).
-
-;; Installation & Use:
-
-;; Put (require 'shadowfile) in your .emacs; add clusters (if necessary)
-;; and file groups with shadow-define-cluster,
-;; shadow-define-literal-group, and shadow-define-regexp-group (see the
-;; documentation for these functions for information on how and when to
-;; use them). After doing this once, everything should be automatic.
-
-;; The lists of clusters and shadows are saved in a file called .shadows,
-;; so that they can be remembered from one emacs session to another, even
-;; (as much as possible) if the emacs session terminates abnormally. The
-;; files needing to be copied are stored in .shadow_todo; if a file cannot
-;; be copied for any reason, it will stay on the list to be tried again
-;; next time. The .shadows file should itself have shadows on all your
-;; accounts so that the information in it is consistent everywhere, but
-;; .shadow_todo is local information and should have no shadows.
-
-;; If you do not want to copy a particular file, you can answer "no" and
-;; be asked again next time you hit C-x 4 s or exit emacs. If you do not
-;; want to be asked again, use shadow-cancel, and you will not be asked
-;; until you change the file and save it again. If you do not want to
-;; shadow that file ever again, you can edit it out of the .shadows
-;; buffer. Anytime you edit the .shadows buffer, you must type M-x
-;; shadow-read-files to load in the new information, or your changes will
-;; be overwritten!
-
-;; Bugs & Warnings:
-;;
-;; - It is bad to have two emacses both running shadowfile at the same
-;; time. It tries to detect this condition, but is not always successful.
-;;
-;; - You have to be careful not to edit a file in two locations
-;; before shadowfile has had a chance to copy it; otherwise
-;; "updating shadows" will overwrite one of the changed versions.
-;;
-;; - It ought to check modification times of both files to make sure
-;; it is doing the right thing. This will have to wait until
-;; file-newer-than-file-p works between machines.
-;;
-;; - It will not make directories for you, it just fails to copy files
-;; that belong in non-existent directories.
-;;
-;; Please report any bugs to me (boris@gnu.ai.mit.edu). Also let me know
-;; if you have suggestions or would like to be informed of updates.
-
-;;; Code:
-
-(provide 'shadowfile)
-(require 'ange-ftp)
-
-(setq find-file-visit-truename t) ; makes life easier with symbolic links
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Variables
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defvar shadow-noquery nil
- "*If t, always copy shadow files without asking.
-If nil \(the default), always ask. If not nil and not t, ask only if there
-is no buffer currently visiting the file.")
-
-(defvar shadow-inhibit-message nil
- "*If nonnil, do not display a message when a file needs copying.")
-
-(defvar shadow-inhibit-overload nil
- "If nonnil, shadowfile won't redefine C-x C-c.
-Normally it overloads the function `save-buffers-kill-emacs' to check
-for files have been changed and need to be copied to other systems.")
-
-(defvar shadow-info-file nil
- "File to keep shadow information in.
-The shadow-info-file should be shadowed to all your accounts to
-ensure consistency. Default: ~/.shadows")
-
-(defvar shadow-todo-file nil
- "File to store the list of uncopied shadows in.
-This means that if a remote system is down, or for any reason you cannot or
-decide not to copy your shadow files at the end of one emacs session, it will
-remember and ask you again in your next emacs session.
-This file must NOT be shadowed to any other system, it is host-specific.
-Default: ~/.shadow_todo")
-
-;;; The following two variables should in most cases initialize themselves
-;;; correctly. They are provided as variables in case the defaults are wrong
-;;; on your machine \(and for efficiency).
-
-(defvar shadow-system-name (system-name)
- "The complete hostname of this machine.")
-
-(defvar shadow-homedir nil
- "Your home directory on this machine.")
-
-;;;
-;;; Internal variables whose values are stored in the info and todo files:
-;;;
-
-(defvar shadow-clusters nil
- "List of host clusters \(see shadow-define-cluster).")
-
-(defvar shadow-literal-groups nil
- "List of files that are shared between hosts.
-This list contains shadow structures with literal filenames, created by
-shadow-define-group.")
-
-(defvar shadow-regexp-groups nil
- "List of file types that are shared between hosts.
-This list contains shadow structures with regexps matching filenames,
-created by shadow-define-regexp-group.")
-
-;;;
-;;; Other internal variables:
-;;;
-
-(defvar shadow-files-to-copy nil) ; List of files that need to
- ; be copied to remote hosts.
-
-(defvar shadow-hashtable nil) ; for speed
-
-(defvar shadow-info-buffer nil) ; buf visiting shadow-info-file
-(defvar shadow-todo-buffer nil) ; buf visiting shadow-todo-file
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Syntactic sugar; General list and string manipulation
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defmacro shadow-when (condition &rest body)
- ;; From cl.el
- "(shadow-when CONDITION . BODY) => evaluate BODY if CONDITION is true."
- (` (if (not (, condition)) () (,@ body))))
-
-(defun shadow-union (a b)
- "Add members of list A to list B
-if they are not equal to items already in B."
- (if (null a)
- b
- (if (member (car a) b)
- (shadow-union (cdr a) b)
- (shadow-union (cdr a) (cons (car a) b)))))
-
-(defun shadow-find (func list)
- "If FUNC applied to some element of LIST is nonnil,
-return the first such element."
- (while (and list (not (funcall func (car list))))
- (setq list (cdr list)))
- (car list))
-
-(defun shadow-remove-if (func list)
- "Remove elements satisfying FUNC from LIST.
-Nondestructive; actually returns a copy of the list with the elements removed."
- (if list
- (if (funcall func (car list))
- (shadow-remove-if func (cdr list))
- (cons (car list) (shadow-remove-if func (cdr list))))
- nil))
-
-(defun shadow-join (strings sep)
- "Concatenate elements of the list of STRINGS with SEP between each."
- (cond ((null strings) "")
- ((null (cdr strings)) (car strings))
- ((concat (car strings) " " (shadow-join (cdr strings) sep)))))
-
-(defun shadow-regexp-superquote (string)
- "Like regexp-quote, but includes the ^ and $
-to make sure regexp matches nothing but STRING."
- (concat "^" (regexp-quote string) "$"))
-
-(defun shadow-suffix (prefix string)
- "If PREFIX begins STRING, return the rest.
-Return value is nonnil if PREFIX and STRING are string= up to the length of
-PREFIX."
- (let ((lp (length prefix))
- (ls (length string)))
- (if (and (>= ls lp)
- (string= prefix (substring string 0 lp)))
- (substring string lp))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Clusters and sites
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;; I use the term `site' to refer to a string which may be the name of a
-;;; cluster or a literal hostname. All user-level commands should accept
-;;; either.
-
-(defun shadow-make-cluster (name primary regexp)
- "Creates a shadow cluster
-called NAME, using the PRIMARY hostname, REGEXP matching all hosts in the
-cluster. The variable shadow-clusters associates the names of clusters to
-these structures.
- This function is for program use: to create clusters interactively, use
-shadow-define-cluster instead."
- (list name primary regexp))
-
-(defmacro shadow-cluster-name (cluster)
- "Return the name of the CLUSTER."
- (list 'elt cluster 0))
-
-(defmacro shadow-cluster-primary (cluster)
- "Return the primary hostname of a CLUSTER."
- (list 'elt cluster 1))
-
-(defmacro shadow-cluster-regexp (cluster)
- "Return the regexp matching hosts in a CLUSTER."
- (list 'elt cluster 2))
-
-(defun shadow-set-cluster (name primary regexp)
- "Put cluster NAME on the list of clusters,
-replacing old definition if any. PRIMARY and REGEXP are the
-information defining the cluster. For interactive use, call
-shadow-define-cluster instead."
- (let ((rest (shadow-remove-if
- (function (lambda (x) (equal name (car x))))
- shadow-clusters)))
- (setq shadow-clusters
- (cons (shadow-make-cluster name primary regexp)
- rest))))
-
-(defmacro shadow-get-cluster (name)
- "Return cluster named NAME, or nil."
- (list 'assoc name 'shadow-clusters))
-
-(defun shadow-site-primary (site)
- "If SITE is a cluster, return primary host, otherwise return SITE."
- (let ((c (shadow-get-cluster site)))
- (if c
- (shadow-cluster-primary c)
- site)))
-
-;;; SITES
-
-(defun shadow-site-cluster (site)
- "Given a SITE \(hostname or cluster name), return the cluster
-that it is in, or nil."
- (or (assoc site shadow-clusters)
- (shadow-find
- (function (lambda (x)
- (string-match (shadow-cluster-regexp x)
- site)))
- shadow-clusters)))
-
-(defun shadow-read-site ()
- "Read a cluster name or hostname from the minibuffer."
- (let ((ans (completing-read "Host or cluster name [RET when done]: "
- shadow-clusters)))
- (if (equal "" ans)
- nil
- ans)))
-
-(defun shadow-site-match (site1 site2)
- "Nonnil iff SITE1 is or includes SITE2.
-Each may be a host or cluster name; if they are clusters, regexp of site1 will
-be matched against the primary of site2."
- (or (string-equal site1 site2) ; quick check
- (let* ((cluster1 (shadow-get-cluster site1))
- (primary2 (shadow-site-primary site2)))
- (if cluster1
- (string-match (shadow-cluster-regexp cluster1) primary2)
- (string-equal site1 primary2)))))
-
-(defun shadow-get-user (site)
- "Returns the default username for a site."
- (ange-ftp-get-user (shadow-site-primary site)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Filename manipulation
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun shadow-parse-fullpath (fullpath)
- "Parse PATH into \(site user path) list,
-or leave it alone if it already is one. Returns nil if the argument is not a
-full ange-ftp pathname."
- (if (listp fullpath)
- fullpath
- (ange-ftp-ftp-name fullpath)))
-
-(defun shadow-parse-path (path)
- "Parse any PATH into \(site user path) list.
-Argument can be a simple path, full ange-ftp path, or already a hup list."
- (or (shadow-parse-fullpath path)
- (list shadow-system-name
- (user-login-name)
- path)))
-
-(defsubst shadow-make-fullpath (host user path)
- "Make an ange-ftp style fullpath out of HOST, USER (optional), and PATH.
-This is probably not as general as it ought to be."
- (concat "/"
- (if user (concat user "@"))
- host ":"
- path))
-
-(defun shadow-replace-path-component (fullpath newpath)
- "Return FULLPATH with the pathname component changed to NEWPATH."
- (let ((hup (shadow-parse-fullpath fullpath)))
- (shadow-make-fullpath (nth 0 hup) (nth 1 hup) newpath)))
-
-(defun shadow-local-file (file)
- "If FILENAME is at this site,
-remove /user@host part. If refers to a different system or a different user on
-this system, return nil."
- (let ((hup (shadow-parse-fullpath file)))
- (cond ((null hup) file)
- ((and (shadow-site-match (nth 0 hup) shadow-system-name)
- (string-equal (nth 1 hup) (user-login-name)))
- (nth 2 hup))
- (t nil))))
-
-(defun shadow-expand-cluster-in-file-name (file)
- "If hostname part of FILE is a cluster, expand it
-into the cluster's primary hostname. Will return the pathname bare if it is
-a local file."
- (let ((hup (shadow-parse-path file))
- cluster)
- (cond ((null hup) file)
- ((shadow-local-file hup))
- ((shadow-make-fullpath (shadow-site-primary (nth 0 hup))
- (nth 1 hup)
- (nth 2 hup))))))
-
-(defun shadow-expand-file-name (file &optional default)
- "Expand file name and get file's true name."
- (file-truename (expand-file-name file default)))
-
-(defun shadow-contract-file-name (file)
- "Simplify FILENAME
-by replacing (when possible) home directory with ~, and hostname with cluster
-name that includes it. Filename should be absolute and true."
- (let* ((hup (shadow-parse-path file))
- (homedir (if (shadow-local-file hup)
- shadow-homedir
- (file-name-as-directory
- (nth 2 (shadow-parse-fullpath
- (expand-file-name
- (shadow-make-fullpath
- (nth 0 hup) (nth 1 hup) "~")))))))
- (suffix (shadow-suffix homedir (nth 2 hup)))
- (cluster (shadow-site-cluster (nth 0 hup))))
- (shadow-make-fullpath
- (if cluster
- (shadow-cluster-name cluster)
- (nth 0 hup))
- (nth 1 hup)
- (if suffix
- (concat "~/" suffix)
- (nth 2 hup)))))
-
-(defun shadow-same-site (pattern file)
- "True if the site of PATTERN and of FILE are on the same site.
-If usernames are supplied, they must also match exactly. PATTERN and FILE may
-be lists of host, user, path, or ange-ftp pathnames. FILE may also be just a
-local filename."
- (let ((pattern-sup (shadow-parse-fullpath pattern))
- (file-sup (shadow-parse-path file)))
- (and
- (shadow-site-match (nth 0 pattern-sup) (nth 0 file-sup))
- (or (null (nth 1 pattern-sup))
- (string-equal (nth 1 pattern-sup) (nth 1 file-sup))))))
-
-(defun shadow-file-match (pattern file &optional regexp)
- "Returns t if PATTERN matches FILE.
-If REGEXP is supplied and nonnil, the pathname part of the pattern is a regular
-expression, otherwise it must match exactly. The sites and usernames must
-match---see shadow-same-site. The pattern must be in full ange-ftp format, but
-the file can be any valid filename. This function does not do any filename
-expansion or contraction, you must do that yourself first."
- (let* ((pattern-sup (shadow-parse-fullpath pattern))
- (file-sup (shadow-parse-path file)))
- (and (shadow-same-site pattern-sup file-sup)
- (if regexp
- (string-match (nth 2 pattern-sup) (nth 2 file-sup))
- (string-equal (nth 2 pattern-sup) (nth 2 file-sup))))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; User-level Commands
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun shadow-define-cluster (name)
- "Edit \(or create) the definition of a cluster.
-This is a group of hosts that share directories, so that copying to or from
-one of them is sufficient to update the file on all of them. Clusters are
-defined by a name, the network address of a primary host \(the one we copy
-files to), and a regular expression that matches the hostnames of all the sites
-in the cluster."
- (interactive (list (completing-read "Cluster name: " shadow-clusters () ())))
- (let* ((old (shadow-get-cluster name))
- (primary (read-string "Primary host: "
- (if old (shadow-cluster-primary old)
- name)))
- (regexp (let (try-regexp)
- (while (not
- (string-match
- (setq try-regexp
- (read-string
- "Regexp matching all host names: "
- (if old (shadow-cluster-regexp old)
- (shadow-regexp-superquote primary))))
- primary))
- (message "Regexp doesn't include the primary host!")
- (sit-for 2))
- try-regexp))
-; (username (read-no-blanks-input
-; (format "Username [default: %s]: "
-; (shadow-get-user primary))
-; (if old (or (shadow-cluster-username old) "")
-; (user-login-name))))
- )
-; (if (string-equal "" username) (setq username nil))
- (shadow-set-cluster name primary regexp)))
-
-(defun shadow-define-literal-group ()
- "Declare a single file to be shared between sites.
-It may have different filenames on each site. When this file is edited, the
-new version will be copied to each of the other locations. Sites can be
-specific hostnames, or names of clusters \(see shadow-define-cluster)."
- (interactive)
- (let* ((hup (shadow-parse-fullpath
- (shadow-contract-file-name (buffer-file-name))))
- (path (nth 2 hup))
- user site group)
- (while (setq site (shadow-read-site))
- (setq user (read-string (format "Username [default %s]: "
- (shadow-get-user site)))
- path (read-string "Filename: " path))
- (setq group (cons (shadow-make-fullpath site
- (if (string-equal "" user)
- (shadow-get-user site)
- user)
- path)
- group)))
- (setq shadow-literal-groups (cons group shadow-literal-groups)))
- (shadow-write-info-file))
-
-(defun shadow-define-regexp-group ()
- "Make each of a group of files be shared between hosts.
-Prompts for regular expression; files matching this are shared between a list
-of sites, which are also prompted for. The filenames must be identical on all
-hosts \(if they aren't, use shadow-define-group instead of this function).
-Each site can be either a hostname or the name of a cluster \(see
-shadow-define-cluster)."
- (interactive)
- (let ((regexp (read-string
- "Filename regexp: "
- (if (buffer-file-name)
- (shadow-regexp-superquote
- (nth 2
- (shadow-parse-path
- (shadow-contract-file-name
- (buffer-file-name))))))))
- site sites usernames)
- (while (setq site (shadow-read-site))
- (setq sites (cons site sites))
- (setq usernames
- (cons (read-string (format "Username for %s: " site)
- (shadow-get-user site))
- usernames)))
- (setq shadow-regexp-groups
- (cons (shadow-make-group regexp sites usernames)
- shadow-regexp-groups))
- (shadow-write-info-file)))
-
-(defun shadow-shadows ()
- ;; Mostly for debugging.
- "Interactive function to display shadows of a buffer."
- (interactive)
- (let ((msg (shadow-join (mapcar (function cdr)
- (shadow-shadows-of (buffer-file-name)))
- " ")))
- (message "%s"
- (if (zerop (length msg))
- "No shadows."
- msg))))
-
-(defun shadow-copy-files (&optional arg)
- "Copy all pending shadow files.
-With prefix argument, copy all pending files without query.
-Pending copies are stored in variable shadow-files-to-copy, and in
-shadow-todo-file if necessary. This function is invoked by
-shadow-save-buffers-kill-emacs, so it is not usually necessary to
-call it manually."
- (interactive "P")
- (if (and (not shadow-files-to-copy) (interactive-p))
- (message "No files need to be shadowed.")
- (save-excursion
- (map-y-or-n-p (function
- (lambda (pair)
- (or arg shadow-noquery
- (format "Copy shadow file %s? " (cdr pair)))))
- (function shadow-copy-file)
- shadow-files-to-copy
- '("shadow" "shadows" "copy"))
- (shadow-write-todo-file t))))
-
-(defun shadow-cancel ()
- "Cancel the instruction to copy some files.
-Prompts for which copy operations to cancel. You will not be asked to copy
-them again, unless you make more changes to the files. To cancel a shadow
-permanently, remove the group from shadow-literal-groups or
-shadow-regexp-groups."
- (interactive)
- (map-y-or-n-p (function (lambda (pair)
- (format "Cancel copying %s to %s? "
- (car pair) (cdr pair))))
- (function (lambda (pair)
- (shadow-remove-from-todo pair)))
- shadow-files-to-copy
- '("shadow" "shadows" "cancel copy"))
- (message "There are %d shadows to be updated."
- (length shadow-files-to-copy))
- (shadow-write-todo-file))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Internal functions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun shadow-make-group (regexp sites usernames)
- "Makes a description of a file group---
-actually a list of regexp ange-ftp file names---from REGEXP \(name of file to
-be shadowed), list of SITES, and corresponding list of USERNAMES for each
-site."
- (if sites
- (cons (shadow-make-fullpath (car sites) (car usernames) regexp)
- (shadow-make-group regexp (cdr sites) (cdr usernames)))
- nil))
-
-(defun shadow-copy-file (s)
- "Copy one shadow file."
- (let* ((buffer
- (cond ((get-file-buffer
- (abbreviate-file-name (shadow-expand-file-name (car s)))))
- ((not (file-readable-p (car s)))
- (if (y-or-n-p
- (format "Cannot find file %s--cancel copy request?"
- (car s)))
- (shadow-remove-from-todo s))
- nil)
- ((or (eq t shadow-noquery)
- (y-or-n-p
- (format "No buffer for %s -- update shadow anyway?"
- (car s))))
- (find-file-noselect (car s)))))
- (to (shadow-expand-cluster-in-file-name (cdr s))))
- (shadow-when buffer
- (set-buffer buffer)
- (save-restriction
- (widen)
- (condition-case i
- (progn
- (write-region (point-min) (point-max) to)
- (shadow-remove-from-todo s))
- (error (message "Shadow %s not updated!" (cdr s))))))))
-
-(defun shadow-shadows-of (file)
- "Returns copy operations needed to update FILE.
-Filename should have clusters expanded, but otherwise can have any format.
-Return value is a list of dotted pairs like \(from . to), where from
-and to are absolute file names."
- (or (symbol-value (intern-soft file shadow-hashtable))
- (let* ((absolute-file (shadow-expand-file-name
- (or (shadow-local-file file) file)
- shadow-homedir))
- (canonical-file (shadow-contract-file-name absolute-file))
- (shadows
- (mapcar (function (lambda (shadow)
- (cons absolute-file shadow)))
- (append
- (shadow-shadows-of-1
- canonical-file shadow-literal-groups nil)
- (shadow-shadows-of-1
- canonical-file shadow-regexp-groups t)))))
- (set (intern file shadow-hashtable) shadows))))
-
-(defun shadow-shadows-of-1 (file groups regexp)
- "Return list of FILE's shadows in GROUPS,
-which are considered as regular expressions if third arg REGEXP is true."
- (if groups
- (let ((nonmatching
- (shadow-remove-if
- (function (lambda (x) (shadow-file-match x file regexp)))
- (car groups))))
- (append (cond ((equal nonmatching (car groups)) nil)
- (regexp
- (let ((realpath (nth 2 (shadow-parse-fullpath file))))
- (mapcar
- (function
- (lambda (x)
- (shadow-replace-path-component x realpath)))
- nonmatching)))
- (t nonmatching))
- (shadow-shadows-of-1 file (cdr groups) regexp)))))
-
-(defun shadow-add-to-todo ()
- "If current buffer has shadows, add them to the list
-of files needing to be copied."
- (let ((shadows (shadow-shadows-of
- (shadow-expand-file-name
- (buffer-file-name (current-buffer))))))
- (shadow-when shadows
- (setq shadow-files-to-copy
- (shadow-union shadows shadow-files-to-copy))
- (shadow-when (not shadow-inhibit-message)
- (message "%s" (substitute-command-keys
- "Use \\[shadow-copy-files] to update shadows."))
- (sit-for 1))
- (shadow-write-todo-file)))
- nil) ; Return nil for write-file-hooks
-
-(defun shadow-remove-from-todo (pair)
- "Remove PAIR from shadow-files-to-copy.
-PAIR must be (eq to) one of the elements of that list."
- (setq shadow-files-to-copy
- (shadow-remove-if (function (lambda (s) (eq s pair)))
- shadow-files-to-copy)))
-
-(defun shadow-read-files ()
- "Visits and loads shadow-info-file and shadow-todo-file,
-thus restoring shadowfile's state from your last emacs session.
-Returns t unless files were locked; then returns nil."
- (interactive)
- (if (and (fboundp 'file-locked-p)
- (or (stringp (file-locked-p shadow-info-file))
- (stringp (file-locked-p shadow-todo-file))))
- (progn
- (message "Shadowfile is running in another emacs; can't have two.")
- (beep)
- (sit-for 3)
- nil)
- (save-excursion
- (shadow-when shadow-info-file
- (set-buffer (setq shadow-info-buffer
- (find-file-noselect shadow-info-file)))
- (shadow-when (and (not (buffer-modified-p))
- (file-newer-than-file-p (make-auto-save-file-name)
- shadow-info-file))
- (erase-buffer)
- (message "Data recovered from %s."
- (car (insert-file-contents (make-auto-save-file-name))))
- (sit-for 1))
- (eval-current-buffer))
- (shadow-when shadow-todo-file
- (set-buffer (setq shadow-todo-buffer
- (find-file-noselect shadow-todo-file)))
- (shadow-when (and (not (buffer-modified-p))
- (file-newer-than-file-p (make-auto-save-file-name)
- shadow-todo-file))
- (erase-buffer)
- (message "Data recovered from %s."
- (car (insert-file-contents (make-auto-save-file-name))))
- (sit-for 1))
- (eval-current-buffer nil))
- (shadow-invalidate-hashtable))
- t))
-
-(defun shadow-write-info-file ()
- "Write out information to shadow-info-file.
-Also clears shadow-hashtable, since when there are new shadows defined, the old
-hashtable info is invalid."
- (shadow-invalidate-hashtable)
- (if shadow-info-file
- (save-excursion
- (if (not shadow-info-buffer)
- (setq shadow-info-buffer (find-file-noselect shadow-info-file)))
- (set-buffer shadow-info-buffer)
- (delete-region (point-min) (point-max))
- (shadow-insert-var 'shadow-clusters)
- (shadow-insert-var 'shadow-literal-groups)
- (shadow-insert-var 'shadow-regexp-groups))))
-
-(defun shadow-write-todo-file (&optional save)
- "Write out information to shadow-todo-file.
-With nonnil argument also saves the buffer."
- (save-excursion
- (if (not shadow-todo-buffer)
- (setq shadow-todo-buffer (find-file-noselect shadow-todo-file)))
- (set-buffer shadow-todo-buffer)
- (delete-region (point-min) (point-max))
- (shadow-insert-var 'shadow-files-to-copy)
- (if save (shadow-save-todo-file))))
-
-(defun shadow-save-todo-file ()
- (if (and shadow-todo-buffer (buffer-modified-p shadow-todo-buffer))
- (save-excursion
- (set-buffer shadow-todo-buffer)
- (condition-case nil ; have to continue even in case of
- (basic-save-buffer) ; error, otherwise kill-emacs might
- (error ; not work!
- (message "WARNING: Can't save shadow todo file; it is locked!")
- (sit-for 1))))))
-
-(defun shadow-invalidate-hashtable ()
- (setq shadow-hashtable (make-vector 37 0)))
-
-(defun shadow-insert-var (variable)
- "Prettily insert a setq command for VARIABLE.
-which, when later evaluated, will restore it to its current setting.
-SYMBOL must be the name of a variable whose value is a list."
- (let ((standard-output (current-buffer)))
- (insert (format "(setq %s" variable))
- (cond ((consp (eval variable))
- (insert "\n '(")
- (prin1 (car (eval variable)))
- (let ((rest (cdr (eval variable))))
- (while rest
- (insert "\n ")
- (prin1 (car rest))
- (setq rest (cdr rest)))
- (insert "))\n\n")))
- (t (insert " ")
- (prin1 (eval variable))
- (insert ")\n\n")))))
-
-(defun shadow-save-buffers-kill-emacs (&optional arg)
- "Offer to save each buffer and copy shadows, then kill this Emacs process.
-With prefix arg, silently save all file-visiting buffers, then kill.
-
-Extended by shadowfile to automatically save `shadow-todo-file' and
-look for files that have been changed and need to be copied to other systems."
- ;; This function is necessary because we need to get control and save
- ;; the todo file /after/ saving other files, but /before/ the warning
- ;; message about unsaved buffers (because it can get modified by the
- ;; action of saving other buffers). `kill-emacs-hook' is no good
- ;; because it is not called at the correct time, and also because it is
- ;; called when the terminal is disconnected and we cannot ask whether
- ;; to copy files.
- (interactive "P")
- (shadow-save-todo-file)
- (save-some-buffers arg t)
- (shadow-copy-files)
- (shadow-save-todo-file)
- (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)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Lucid Emacs compatibility
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; This is on hold until someone tells me about a working version of
-;; map-ynp for Lucid Emacs.
-
-;(shadow-when (string-match "Lucid" emacs-version)
-; (require 'symlink-fix)
-; (require 'ange-ftp)
-; (require 'map-ynp)
-; (if (not (fboundp 'file-truename))
-; (fset 'shadow-expand-file-name
-; (symbol-function 'symlink-expand-file-name)))
-; (if (not (fboundp 'ange-ftp-ftp-name))
-; (fset 'ange-ftp-ftp-name
-; (symbol-function 'ange-ftp-ftp-path))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Hook us up
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;; File shadowing is activated at load time, unless this this file is
-;;; being preloaded, in which case it is added to after-init-hook.
-;;; Thanks to Richard Caley for this scheme.
-
-(defun shadow-initialize ()
- (if (null shadow-homedir)
- (setq shadow-homedir
- (file-name-as-directory (shadow-expand-file-name "~"))))
- (if (null shadow-info-file)
- (setq shadow-info-file
- (shadow-expand-file-name "~/.shadows")))
- (if (null shadow-todo-file)
- (setq shadow-todo-file
- (shadow-expand-file-name "~/.shadow_todo")))
- (if (not (shadow-read-files))
- (progn
- (message "Shadowfile information files not found - aborting")
- (beep)
- (sit-for 3))
- (shadow-when (and (not shadow-inhibit-overload)
- (not (fboundp 'shadow-orig-save-buffers-kill-emacs)))
- (fset 'shadow-orig-save-buffers-kill-emacs
- (symbol-function 'save-buffers-kill-emacs))
- (fset 'save-buffers-kill-emacs
- (symbol-function 'shadow-save-buffers-kill-emacs)))
- (add-hook 'write-file-hooks 'shadow-add-to-todo)
- (define-key ctl-x-4-map "s" 'shadow-copy-files)))
-
-(if noninteractive
- (add-hook 'after-init-hook 'shadow-initialize)
- (shadow-initialize))
-
-;;;Local Variables:
-;;;eval:(put 'shadow-when 'lisp-indent-hook 1)
-;;;End:
-
-;;; shadowfile.el ends here
diff --git a/lisp/shell.el b/lisp/shell.el
deleted file mode 100644
index 1d4dfcef3c1..00000000000
--- a/lisp/shell.el
+++ /dev/null
@@ -1,853 +0,0 @@
-;;; shell.el --- specialized comint.el for running the shell.
-
-;; Copyright (C) 1988, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Olin Shivers <shivers@cs.cmu.edu>
-;; Maintainer: Simon Marshall <simon@gnu.ai.mit.edu>
-;; Keywords: processes
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Please send me bug reports, bug fixes, and extensions, so that I can
-;; merge them into the master source.
-;; - Olin Shivers (shivers@cs.cmu.edu)
-;; - Simon Marshall (simon@gnu.ai.mit.edu)
-
-;; This file defines a a shell-in-a-buffer package (shell mode) built
-;; on top of comint mode. This is actually cmushell with things
-;; renamed to replace its counterpart in Emacs 18. cmushell is more
-;; featureful, robust, and uniform than the Emacs 18 version.
-
-;; 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.
-;; This makes these modes easier to use.
-
-;; For documentation on the functionality provided by comint mode, and
-;; the hooks available for customising it, see the file comint.el.
-;; For further information on shell mode, see the comments below.
-
-;; 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?
-
-;; YOUR .EMACS FILE
-;;=============================================================================
-;; Some suggestions for your .emacs file.
-;;
-;; ;; Define M-# to run some strange command:
-;; (eval-after-load "shell"
-;; '(define-key shell-mode-map "\M-#" 'shells-dynamic-spell))
-
-;; Brief Command Documentation:
-;;============================================================================
-;; Comint Mode Commands: (common to shell and all comint-derived modes)
-;;
-;; m-p comint-previous-input Cycle backwards in input history
-;; m-n comint-next-input Cycle forwards
-;; m-r comint-previous-matching-input Previous input matching a regexp
-;; m-s comint-next-matching-input Next input that matches
-;; m-c-l comint-show-output Show last batch of process output
-;; return comint-send-input
-;; c-d comint-delchar-or-maybe-eof Delete char unless at end of buff.
-;; c-c c-a comint-bol Beginning of line; skip prompt
-;; c-c c-u comint-kill-input ^u
-;; c-c c-w backward-kill-word ^w
-;; c-c c-c comint-interrupt-subjob ^c
-;; c-c c-z comint-stop-subjob ^z
-;; c-c c-\ comint-quit-subjob ^\
-;; c-c c-o comint-kill-output Delete last batch of process output
-;; c-c c-r comint-show-output Show last batch of process output
-;; c-c c-h comint-dynamic-list-input-ring List input history
-;; send-invisible Read line w/o echo & send to proc
-;; comint-continue-subjob Useful if you accidentally suspend
-;; top-level job
-;; comint-mode-hook is the comint mode hook.
-
-;; Shell Mode Commands:
-;; shell Fires up the shell process
-;; tab comint-dynamic-complete Complete filename/command/history
-;; m-? comint-dynamic-list-filename-completions
-;; List completions in help buffer
-;; m-c-f shell-forward-command Forward a shell command
-;; m-c-b shell-backward-command Backward a shell command
-;; dirs Resync the buffer's dir stack
-;; dirtrack-toggle Turn dir tracking on/off
-;; comint-strip-ctrl-m Remove trailing ^Ms from output
-;;
-;; The shell mode hook is shell-mode-hook
-;; comint-prompt-regexp is initialised to shell-prompt-pattern, for backwards
-;; compatibility.
-
-;; Read the rest of this file for more information.
-
-;;; Code:
-
-(require 'comint)
-
-;;; Customization and Buffer Variables
-
-;;;###autoload
-(defvar shell-prompt-pattern "^[^#$%>\n]*[#$%>] *"
- "Regexp to match prompts in the inferior shell.
-Defaults to \"^[^#$%>\\n]*[#$%>] *\", which works pretty well.
-This variable is used to initialise `comint-prompt-regexp' in the
-shell buffer.
-
-The pattern should probably not match more than one line. If it does,
-Shell mode may become confused trying to distinguish prompt from input
-on lines which don't start with a prompt.
-
-This is a fine thing to set in your `.emacs' file.")
-
-(defvar shell-completion-fignore nil
- "*List of suffixes to be disregarded during file/command completion.
-This variable is used to initialize `comint-completion-fignore' in the shell
-buffer. The default is nil, for compatibility with most shells.
-Some people like (\"~\" \"#\" \"%\").
-
-This is a fine thing to set in your `.emacs' file.")
-
-(defvar shell-delimiter-argument-list '(?\| ?& ?< ?> ?\( ?\) ?\;)
- "List of characters to recognise as separate arguments.
-This variable is used to initialize `comint-delimiter-argument-list' in the
-shell buffer. The value may depend on the operating system or shell.
-
-This is a fine thing to set in your `.emacs' file.")
-
-(defvar shell-file-name-chars
- (if (memq system-type '(ms-dos windows-nt))
- "~/A-Za-z0-9_^$!#%&{}@`'.()-"
- "~/A-Za-z0-9+@:_.$#%,={}-")
- "String of characters valid in a file name.
-This variable is used to initialize `comint-file-name-chars' in the
-shell buffer. The value may depend on the operating system or shell.
-
-This is a fine thing to set in your `.emacs' file.")
-
-(defvar shell-file-name-quote-list
- (if (memq system-type '(ms-dos windows-nt))
- nil
- (append shell-delimiter-argument-list '(?\ ?\* ?\! ?\" ?\' ?\`)))
- "List of characters to quote when in a file name.
-This variable is used to initialize `comint-file-name-quote-list' in the
-shell buffer. The value may depend on the operating system or shell.
-
-This is a fine thing to set in your `.emacs' file.")
-
-(defvar shell-dynamic-complete-functions
- '(comint-replace-by-expanded-history
- shell-dynamic-complete-environment-variable
- shell-dynamic-complete-command
- shell-replace-by-expanded-directory
- comint-dynamic-complete-filename)
- "List of functions called to perform completion.
-This variable is used to initialise `comint-dynamic-complete-functions' in the
-shell buffer.
-
-This is a fine thing to set in your `.emacs' file.")
-
-(defvar shell-command-regexp "[^;&|\n]+"
- "*Regexp to match a single command within a pipeline.
-This is used for directory tracking and does not do a perfect job.")
-
-(defvar shell-completion-execonly t
- "*If non-nil, use executable files only for completion candidates.
-This mirrors the optional behavior of tcsh.
-
-Detecting executability of files may slow command completion considerably.")
-
-(defvar shell-popd-regexp "popd"
- "*Regexp to match subshell commands equivalent to popd.")
-
-(defvar shell-pushd-regexp "pushd"
- "*Regexp to match subshell commands equivalent to pushd.")
-
-(defvar shell-pushd-tohome nil
- "*If non-nil, make pushd with no arg behave as \"pushd ~\" (like cd).
-This mirrors the optional behavior of tcsh.")
-
-(defvar shell-pushd-dextract nil
- "*If non-nil, make \"pushd +n\" pop the nth dir to the stack top.
-This mirrors the optional behavior of tcsh.")
-
-(defvar shell-pushd-dunique nil
- "*If non-nil, make pushd only add unique directories to the stack.
-This mirrors the optional behavior of tcsh.")
-
-(defvar shell-cd-regexp "cd"
- "*Regexp to match subshell commands equivalent to cd.")
-
-(defvar shell-chdrive-regexp
- (if (memq system-type '(ms-dos windows-nt))
- ; NetWare allows the five chars between upper and lower alphabetics.
- "[]a-zA-Z^_`\\[\\\\]:"
- nil)
- "*If non-nil, is regexp used to track drive changes.")
-
-(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-input-autoexpand 'history
- "*If non-nil, expand input command history references on completion.
-This mirrors the optional behavior of tcsh (its autoexpand and histlit).
-
-If the value is `input', then the expansion is seen on input.
-If the value is `history', then the expansion is only when inserting
-into the buffer's input ring. See also `comint-magic-space' and
-`comint-dynamic-complete'.
-
-This variable supplies a default for `comint-input-autoexpand',
-for Shell mode only.")
-
-(defvar shell-dirstack nil
- "List of directories saved by pushd in this buffer's shell.
-Thus, this does not include the shell's current directory.")
-
-(defvar shell-dirtrackp t
- "Non-nil in a shell buffer means directory tracking is enabled.")
-
-(defvar shell-last-dir nil
- "Keep track of last directory for ksh `cd -' command.")
-
-(defvar shell-dirstack-query nil
- "Command used by `shell-resync-dir' to query the shell.")
-
-(defvar shell-mode-map nil)
-(cond ((not shell-mode-map)
- (setq shell-mode-map (nconc (make-sparse-keymap) comint-mode-map))
- (define-key shell-mode-map "\C-c\C-f" 'shell-forward-command)
- (define-key shell-mode-map "\C-c\C-b" 'shell-backward-command)
- (define-key shell-mode-map "\t" 'comint-dynamic-complete)
- (define-key shell-mode-map "\M-?"
- 'comint-dynamic-list-filename-completions)
- (define-key shell-mode-map [menu-bar completion]
- (copy-keymap (lookup-key comint-mode-map [menu-bar completion])))
- (define-key-after (lookup-key shell-mode-map [menu-bar completion])
- [complete-env-variable] '("Complete Env. Variable Name" .
- shell-dynamic-complete-environment-variable)
- 'complete-file)
- (define-key-after (lookup-key shell-mode-map [menu-bar completion])
- [expand-directory] '("Expand Directory Reference" .
- shell-replace-by-expanded-directory)
- 'complete-expand)))
-
-(defvar shell-mode-hook '()
- "*Hook for customising Shell mode.")
-
-(defvar shell-font-lock-keywords
- (list (cons shell-prompt-pattern 'font-lock-keyword-face)
- '("[ \t]\\([+-][^ \t\n]+\\)" 1 font-lock-comment-face)
- '("^[^ \t\n]+:.*" . font-lock-string-face)
- '("^\\[[1-9][0-9]*\\]" . font-lock-string-face))
- "Additional expressions to highlight in Shell mode.")
-
-;;; Basic Procedures
-
-(defun shell-mode ()
- "Major mode for interacting with an inferior shell.
-\\[comint-send-input] after the end of the process' output sends the text from
- the end of process to the end of the current line.
-\\[comint-send-input] before end of process output copies the current line minus the prompt to
- the end of the buffer and sends it (\\[comint-copy-old-input] just copies the current line).
-\\[send-invisible] reads a line of text without echoing it, and sends it to
- the shell. This is useful for entering passwords. Or, add the function
- `comint-watch-for-password-prompt' to `comint-output-filter-functions'.
-
-If you want to make multiple shell buffers, rename the `*shell*' buffer
-using \\[rename-buffer] or \\[rename-uniquely] and start a new shell.
-
-If you want to make shell buffers limited in length, add the function
-`comint-truncate-buffer' to `comint-output-filter-functions'.
-
-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.
-While directory tracking is enabled, the shell's working directory is displayed
-by \\[list-buffers] or \\[mouse-buffer-menu] in the `File' field.
-\\[dirs] queries the shell and resyncs Emacs' idea of what the current
- directory stack is.
-\\[dirtrack-toggle] turns directory tracking on and off.
-
-\\{shell-mode-map}
-Customization: Entry to this mode runs the hooks on `comint-mode-hook' and
-`shell-mode-hook' (in that order). Before each input, the hooks on
-`comint-input-filter-functions' are run. After each shell output, the hooks
-on `comint-output-filter-functions' are run.
-
-Variables `shell-cd-regexp', `shell-chdrive-regexp', `shell-pushd-regexp'
-and `shell-popd-regexp' are used to match their respective commands,
-while `shell-pushd-tohome', `shell-pushd-dextract' and `shell-pushd-dunique'
-control the behavior of the relevant command.
-
-Variables `comint-completion-autolist', `comint-completion-addsuffix',
-`comint-completion-recexact' and `comint-completion-fignore' control the
-behavior of file name, command name and variable name completion. Variable
-`shell-completion-execonly' controls the behavior of command name completion.
-Variable `shell-completion-fignore' is used to initialise the value of
-`comint-completion-fignore'.
-
-Variables `comint-input-ring-file-name' and `comint-input-autoexpand' control
-the initialisation of the input ring history, and history expansion.
-
-Variables `comint-output-filter-functions', a hook, and
-`comint-scroll-to-bottom-on-input' and `comint-scroll-to-bottom-on-output'
-control whether input and output cause the window to scroll to the end of the
-buffer."
- (interactive)
- (comint-mode)
- (setq major-mode 'shell-mode)
- (setq mode-name "Shell")
- (use-local-map shell-mode-map)
- (setq comint-prompt-regexp shell-prompt-pattern)
- (setq comint-completion-fignore shell-completion-fignore)
- (setq comint-delimiter-argument-list shell-delimiter-argument-list)
- (setq comint-file-name-chars shell-file-name-chars)
- (setq comint-file-name-quote-list shell-file-name-quote-list)
- (setq comint-dynamic-complete-functions shell-dynamic-complete-functions)
- (make-local-variable 'paragraph-start)
- (setq paragraph-start comint-prompt-regexp)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(shell-font-lock-keywords t))
- (make-local-variable 'shell-dirstack)
- (setq shell-dirstack nil)
- (setq shell-last-dir nil)
- (make-local-variable 'shell-dirtrackp)
- (setq shell-dirtrackp t)
- (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t)
- (setq comint-input-autoexpand shell-input-autoexpand)
- (make-local-variable 'list-buffers-directory)
- (setq list-buffers-directory (expand-file-name default-directory))
- ;; shell-dependent assignments.
- (let ((shell (file-name-nondirectory (car
- (process-command (get-buffer-process (current-buffer)))))))
- (setq comint-input-ring-file-name
- (or (getenv "HISTFILE")
- (cond ((string-equal shell "bash") "~/.bash_history")
- ((string-equal shell "ksh") "~/.sh_history")
- (t "~/.history"))))
- (if (or (equal comint-input-ring-file-name "")
- (equal (file-truename comint-input-ring-file-name)
- (file-truename "/dev/null")))
- (setq comint-input-ring-file-name nil))
- (setq shell-dirstack-query
- (cond ((string-equal shell "sh") "pwd")
- ((string-equal shell "ksh") "echo $PWD ~-")
- (t "dirs"))))
- (run-hooks 'shell-mode-hook)
- (comint-read-input-ring t))
-
-;;;###autoload
-(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*'.
-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 the variable `shell-prompt-pattern'.
-
-The shell file name (sans directories) is used to make a symbol name
-such as `explicit-csh-args'. 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.)"
- (interactive)
- (if (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")))
- shell-buffer)
- (save-excursion
- (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"))))
- (setq shell-buffer (current-buffer))
- (shell-mode))
- (pop-to-buffer shell-buffer))
- (pop-to-buffer "*shell*")))
-
-;;; Don't do this when shell.el is loaded, only while dumping.
-;;;###autoload (add-hook 'same-window-buffer-names "*shell*")
-
-;;; 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 version in Emacs 18's shell.el. It has the following failings:
-;;; 1. It doesn't know about the cdpath shell variable.
-;;; 2. It cannot infallibly deal with command sequences, though it does well
-;;; with these and with ignoring commands forked in another shell with ()s.
-;;; 3. More generally, any complex command 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* affect 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.
-
-(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-chdrive-regexp', `shell-pushd-regexp',
-and `shell-popd-regexp', while `shell-pushd-tohome', `shell-pushd-dextract',
-and `shell-pushd-dunique' control the behavior of the relevant command.
-
-Environment variables are expanded, see function `substitute-in-file-name'."
- (if shell-dirtrackp
- ;; We fail gracefully if we think the command will fail in the shell.
- (condition-case chdir-failure
- (let ((start (progn (string-match "^[; \t]*" str) ; skip whitespace
- (match-end 0)))
- end cmd arg1)
- (while (string-match shell-command-regexp str start)
- (setq end (match-end 0)
- cmd (comint-arguments (substring str start end) 0 0)
- arg1 (comint-arguments (substring str start end) 1 1))
- (cond ((string-match (concat "\\`\\(" shell-popd-regexp
- "\\)\\($\\|[ \t]\\)")
- cmd)
- (shell-process-popd (comint-substitute-in-file-name arg1)))
- ((string-match (concat "\\`\\(" shell-pushd-regexp
- "\\)\\($\\|[ \t]\\)")
- cmd)
- (shell-process-pushd (comint-substitute-in-file-name arg1)))
- ((string-match (concat "\\`\\(" shell-cd-regexp
- "\\)\\($\\|[ \t]\\)")
- cmd)
- (shell-process-cd (comint-substitute-in-file-name arg1)))
- ((and shell-chdrive-regexp
- (string-match (concat "\\`\\(" shell-chdrive-regexp
- "\\)\\($\\|[ \t]\\)")
- cmd))
- (shell-process-cd (comint-substitute-in-file-name cmd))))
- (setq start (progn (string-match "[; \t]*" str end) ; skip again
- (match-end 0)))))
- (error "Couldn't cd"))))
-
-;;; popd [+n]
-(defun shell-process-popd (arg)
- (let ((num (or (shell-extract-num arg) 0)))
- (cond ((and num (= num 0) shell-dirstack)
- (shell-cd (car shell-dirstack))
- (setq shell-dirstack (cdr shell-dirstack))
- (shell-dirstack-message))
- ((and num (> num 0) (<= num (length shell-dirstack)))
- (let* ((ds (cons nil shell-dirstack))
- (cell (nthcdr (1- num) ds)))
- (rplacd cell (cdr (cdr cell)))
- (setq shell-dirstack (cdr ds))
- (shell-dirstack-message)))
- (t
- (error "Couldn't popd")))))
-
-;; Return DIR prefixed with comint-file-name-prefix as appropriate.
-(defun shell-prefixed-directory-name (dir)
- (if (= (length comint-file-name-prefix) 0)
- dir
- (if (file-name-absolute-p dir)
- ;; The name is absolute, so prepend the prefix.
- (concat comint-file-name-prefix dir)
- ;; For relative name we assume default-directory already has the prefix.
- (expand-file-name dir))))
-
-;;; cd [dir]
-(defun shell-process-cd (arg)
- (let ((new-dir (cond ((zerop (length arg)) (concat comint-file-name-prefix
- "~"))
- ((string-equal "-" arg) shell-last-dir)
- (t (shell-prefixed-directory-name arg)))))
- (setq shell-last-dir default-directory)
- (shell-cd new-dir)
- (shell-dirstack-message)))
-
-;;; pushd [+n | dir]
-(defun shell-process-pushd (arg)
- (let ((num (shell-extract-num arg)))
- (cond ((zerop (length arg))
- ;; no arg -- swap pwd and car of stack unless shell-pushd-tohome
- (cond (shell-pushd-tohome
- (shell-process-pushd (concat comint-file-name-prefix "~")))
- (shell-dirstack
- (let ((old default-directory))
- (shell-cd (car shell-dirstack))
- (setq shell-dirstack (cons old (cdr shell-dirstack)))
- (shell-dirstack-message)))
- (t
- (message "Directory stack empty."))))
- ((numberp num)
- ;; pushd +n
- (cond ((> num (length shell-dirstack))
- (message "Directory stack not that deep."))
- ((= num 0)
- (error (message "Couldn't cd.")))
- (shell-pushd-dextract
- (let ((dir (nth (1- num) shell-dirstack)))
- (shell-process-popd arg)
- (shell-process-pushd default-directory)
- (shell-cd dir)
- (shell-dirstack-message)))
- (t
- (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)))
- (shell-cd (car new-ds))
- (setq shell-dirstack (cdr new-ds))
- (shell-dirstack-message)))))
- (t
- ;; pushd <dir>
- (let ((old-wd default-directory))
- (shell-cd (shell-prefixed-directory-name arg))
- (if (or (null shell-pushd-dunique)
- (not (member old-wd shell-dirstack)))
- (setq shell-dirstack (cons old-wd shell-dirstack)))
- (shell-dirstack-message))))))
-
-;; 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."
- (interactive)
- (if (setq shell-dirtrackp (not shell-dirtrackp))
- (setq list-buffers-directory default-directory)
- (setq list-buffers-directory nil))
- (message "Directory tracking %s" (if shell-dirtrackp "ON" "OFF")))
-
-;;; For your typing convenience:
-(defalias 'dirtrack-toggle 'shell-dirtrack-toggle)
-
-(defun shell-cd (dir)
- "Do normal `cd' to DIR, and set `list-buffers-directory'."
- (if shell-dirtrackp
- (setq list-buffers-directory (file-name-as-directory
- (expand-file-name dir))))
- (cd dir))
-
-(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."
- (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) (1- (match-end 0))))
- (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 (concat comint-file-name-prefix
- (substring dl (match-beginning 1)
- (match-end 1)))
- ds))
- (setq i (match-end 0)))
- (let ((ds (nreverse ds)))
- (condition-case nil
- (progn (shell-cd (car ds))
- (setq shell-dirstack (cdr ds)
- shell-last-dir (car shell-dirstack))
- (shell-dirstack-message))
- (error (message "Couldn't cd.")))))))
-
-;;; For your typing convenience:
-(defalias '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))
- (home (expand-file-name (concat comint-file-name-prefix "~/")))
- (homelen (length home)))
- (while ds
- (let ((dir (car ds)))
- (and (>= (length dir) homelen) (string= home (substring dir 0 homelen))
- (setq dir (concat "~/" (substring dir homelen))))
- ;; Strip off comint-file-name-prefix if present.
- (and comint-file-name-prefix
- (>= (length dir) (length comint-file-name-prefix))
- (string= comint-file-name-prefix
- (substring dir 0 (length comint-file-name-prefix)))
- (setq dir (substring dir (length comint-file-name-prefix)))
- (setcar ds dir))
- (setq msg (concat msg (directory-file-name dir) " "))
- (setq ds (cdr ds))))
- (message "%s" msg)))
-
-(defun shell-forward-command (&optional arg)
- "Move forward across ARG shell command(s). Does not cross lines.
-See `shell-command-regexp'."
- (interactive "p")
- (let ((limit (save-excursion (end-of-line nil) (point))))
- (if (re-search-forward (concat shell-command-regexp "\\([;&|][\t ]*\\)+")
- limit 'move arg)
- (skip-syntax-backward " "))))
-
-
-(defun shell-backward-command (&optional arg)
- "Move backward across ARG shell command(s). Does not cross lines.
-See `shell-command-regexp'."
- (interactive "p")
- (let ((limit (save-excursion (comint-bol nil) (point))))
- (if (> limit (point))
- (save-excursion (beginning-of-line) (setq limit (point))))
- (skip-syntax-backward " " limit)
- (if (re-search-backward
- (format "[;&|]+[\t ]*\\(%s\\)" shell-command-regexp) limit 'move arg)
- (progn (goto-char (match-beginning 1))
- (skip-chars-forward ";&|")))))
-
-
-(defun shell-dynamic-complete-command ()
- "Dynamically complete the command at point.
-This function is similar to `comint-dynamic-complete-filename', except that it
-searches `exec-path' (minus the trailing emacs library path) for completion
-candidates. Note that this may not be the same as the shell's idea of the
-path.
-
-Completion is dependent on the value of `shell-completion-execonly', plus
-those that effect file completion. See `shell-dynamic-complete-as-command'.
-
-Returns t if successful."
- (interactive)
- (let ((filename (comint-match-partial-filename)))
- (if (and filename
- (save-match-data (not (string-match "[~/]" filename)))
- (eq (match-beginning 0)
- (save-excursion (shell-backward-command 1) (point))))
- (prog2 (message "Completing command name...")
- (shell-dynamic-complete-as-command)))))
-
-
-(defun shell-dynamic-complete-as-command ()
- "Dynamically complete at point as a command.
-See `shell-dynamic-complete-filename'. Returns t if successful."
- (let* ((filename (or (comint-match-partial-filename) ""))
- (pathnondir (file-name-nondirectory filename))
- (paths (cdr (reverse exec-path)))
- (cwd (file-name-as-directory (expand-file-name default-directory)))
- (ignored-extensions
- (and comint-completion-fignore
- (mapconcat (function (lambda (x) (concat (regexp-quote x) "$")))
- comint-completion-fignore "\\|")))
- (path "") (comps-in-path ()) (file "") (filepath "") (completions ()))
- ;; Go thru each path in the search path, finding completions.
- (while paths
- (setq path (file-name-as-directory (comint-directory (or (car paths) ".")))
- comps-in-path (and (file-accessible-directory-p path)
- (file-name-all-completions pathnondir path)))
- ;; Go thru each completion found, to see whether it should be used.
- (while comps-in-path
- (setq file (car comps-in-path)
- filepath (concat path file))
- (if (and (not (member file completions))
- (not (and ignored-extensions
- (string-match ignored-extensions file)))
- (or (string-equal path cwd)
- (not (file-directory-p filepath)))
- (or (null shell-completion-execonly)
- (file-executable-p filepath)))
- (setq completions (cons file completions)))
- (setq comps-in-path (cdr comps-in-path)))
- (setq paths (cdr paths)))
- ;; OK, we've got a list of completions.
- (let ((success (let ((comint-completion-addsuffix nil))
- (comint-dynamic-simple-complete pathnondir completions))))
- (if (and (memq success '(sole shortest)) comint-completion-addsuffix
- (not (file-directory-p (comint-match-partial-filename))))
- (insert " "))
- success)))
-
-
-(defun shell-match-partial-variable ()
- "Return the shell variable at point, or nil if none is found."
- (save-excursion
- (let ((limit (point)))
- (if (re-search-backward "[^A-Za-z0-9_{}]" nil 'move)
- (or (looking-at "\\$") (forward-char 1)))
- ;; Anchor the search forwards.
- (if (or (eolp) (looking-at "[^A-Za-z0-9_{}$]"))
- nil
- (re-search-forward "\\$?{?[A-Za-z0-9_]*}?" limit)
- (buffer-substring (match-beginning 0) (match-end 0))))))
-
-
-(defun shell-dynamic-complete-environment-variable ()
- "Dynamically complete the environment variable at point.
-Completes if after a variable, i.e., if it starts with a \"$\".
-See `shell-dynamic-complete-as-environment-variable'.
-
-This function is similar to `comint-dynamic-complete-filename', except that it
-searches `process-environment' for completion candidates. Note that this may
-not be the same as the interpreter's idea of variable names. The main problem
-with this type of completion is that `process-environment' is the environment
-which Emacs started with. Emacs does not track changes to the environment made
-by the interpreter. Perhaps it would be more accurate if this function was
-called `shell-dynamic-complete-process-environment-variable'.
-
-Returns non-nil if successful."
- (interactive)
- (let ((variable (shell-match-partial-variable)))
- (if (and variable (string-match "^\\$" variable))
- (prog2 (message "Completing variable name...")
- (shell-dynamic-complete-as-environment-variable)))))
-
-
-(defun shell-dynamic-complete-as-environment-variable ()
- "Dynamically complete at point as an environment variable.
-Used by `shell-dynamic-complete-environment-variable'.
-Uses `comint-dynamic-simple-complete'."
- (let* ((var (or (shell-match-partial-variable) ""))
- (variable (substring var (or (string-match "[^$({]\\|$" var) 0)))
- (variables (mapcar (function (lambda (x)
- (substring x 0 (string-match "=" x))))
- process-environment))
- (addsuffix comint-completion-addsuffix)
- (comint-completion-addsuffix nil)
- (success (comint-dynamic-simple-complete variable variables)))
- (if (memq success '(sole shortest))
- (let* ((var (shell-match-partial-variable))
- (variable (substring var (string-match "[^$({]" var)))
- (protection (cond ((string-match "{" var) "}")
- ((string-match "(" var) ")")
- (t "")))
- (suffix (cond ((null addsuffix) "")
- ((file-directory-p
- (comint-directory (getenv variable))) "/")
- (t " "))))
- (insert protection suffix)))
- success))
-
-
-(defun shell-replace-by-expanded-directory ()
- "Expand directory stack reference before point.
-Directory stack references are of the form \"=digit\" or \"=-\".
-See `default-directory' and `shell-dirstack'.
-
-Returns t if successful."
- (interactive)
- (if (comint-match-partial-filename)
- (save-excursion
- (goto-char (match-beginning 0))
- (let ((stack (cons default-directory shell-dirstack))
- (index (cond ((looking-at "=-/?")
- (length shell-dirstack))
- ((looking-at "=\\([0-9]+\\)")
- (string-to-number
- (buffer-substring
- (match-beginning 1) (match-end 1)))))))
- (cond ((null index)
- nil)
- ((>= index (length stack))
- (error "Directory stack not that deep."))
- (t
- (replace-match (file-name-as-directory (nth index stack)) t t)
- (message "Directory item: %d" index)
- t))))))
-
-(provide 'shell)
-
-;;; shell.el ends here
diff --git a/lisp/simple.el b/lisp/simple.el
deleted file mode 100644
index 5fe8f638d62..00000000000
--- a/lisp/simple.el
+++ /dev/null
@@ -1,3269 +0,0 @@
-;;; simple.el --- basic editing commands for Emacs
-
-;; Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; A grab-bag of basic Emacs commands not specifically related to some
-;; major mode or to file-handling.
-
-;;; Code:
-
-(defun newline (&optional arg)
- "Insert a newline, and move to left margin of the new line if it's blank.
-The newline is marked with the text-property `hard'.
-With arg, insert that many newlines.
-In Auto Fill mode, if no numeric arg, break the preceding line if it's long."
- (interactive "*P")
- (barf-if-buffer-read-only)
- ;; Inserting a newline at the end of a line produces better redisplay in
- ;; try_window_id than inserting at the beginning of a line, and the textual
- ;; result is the same. So, if we're at beginning of line, pretend to be at
- ;; the end of the previous line.
- (let ((flag (and (not (bobp))
- (bolp)
- ;; Make sure there are no markers here.
- (not (buffer-has-markers-at (1- (point))))
- ;; Make sure the newline before point isn't intangible.
- (not (get-char-property (1- (point)) 'intangible))
- ;; Make sure the newline before point isn't read-only.
- (not (get-char-property (1- (point)) 'read-only))
- ;; Make sure the newline before point isn't invisible.
- (not (get-char-property (1- (point)) 'invisible))
- ;; Make sure the newline before point has the same
- ;; properties as the char before it (if any).
- (< (or (previous-property-change (point)) -2)
- (- (point) 2))))
- (was-page-start (and (bolp)
- (looking-at page-delimiter)))
- (beforepos (point)))
- (if flag (backward-char 1))
- ;; Call self-insert so that auto-fill, abbrev expansion etc. happens.
- ;; Set last-command-char to tell self-insert what to insert.
- (let ((last-command-char ?\n)
- ;; Don't auto-fill if we have a numeric argument.
- ;; Also not if flag is true (it would fill wrong line);
- ;; there is no need to since we're at BOL.
- (auto-fill-function (if (or arg flag) nil auto-fill-function)))
- (unwind-protect
- (self-insert-command (prefix-numeric-value arg))
- ;; If we get an error in self-insert-command, put point at right place.
- (if flag (forward-char 1))))
- ;; If we did *not* get an error, cancel that forward-char.
- (if flag (backward-char 1))
- ;; Mark the newline(s) `hard'.
- (if use-hard-newlines
- (set-hard-newline-properties
- (- (point) (if arg (prefix-numeric-value arg) 1)) (point)))
- ;; If the newline leaves the previous line blank,
- ;; and we have a left margin, delete that from the blank line.
- (or flag
- (save-excursion
- (goto-char beforepos)
- (beginning-of-line)
- (and (looking-at "[ \t]$")
- (> (current-left-margin) 0)
- (delete-region (point) (progn (end-of-line) (point))))))
- (if flag (forward-char 1))
- ;; Indent the line after the newline, except in one case:
- ;; when we added the newline at the beginning of a line
- ;; which starts a page.
- (or was-page-start
- (move-to-left-margin nil t)))
- nil)
-
-(defun set-hard-newline-properties (from to)
- (let ((sticky (get-text-property from 'rear-nonsticky)))
- (put-text-property from to 'hard 't)
- ;; If rear-nonsticky is not "t", add 'hard to rear-nonsticky list
- (if (and (listp sticky) (not (memq 'hard sticky)))
- (put-text-property from (point) 'rear-nonsticky
- (cons 'hard sticky)))))
-
-(defun open-line (arg)
- "Insert a newline and leave point before it.
-If there is a fill prefix and/or a left-margin, insert them on the new line
-if the line would have been blank.
-With arg N, insert N newlines."
- (interactive "*p")
- (let* ((do-fill-prefix (and fill-prefix (bolp)))
- (do-left-margin (and (bolp) (> (current-left-margin) 0)))
- (loc (point)))
- (newline arg)
- (goto-char loc)
- (while (> arg 0)
- (cond ((bolp)
- (if do-left-margin (indent-to (current-left-margin)))
- (if do-fill-prefix (insert-and-inherit fill-prefix))))
- (forward-line 1)
- (setq arg (1- arg)))
- (goto-char loc)
- (end-of-line)))
-
-(defun split-line ()
- "Split current line, moving portion beyond point vertically down."
- (interactive "*")
- (skip-chars-forward " \t")
- (let ((col (current-column))
- (pos (point)))
- (newline 1)
- (indent-to col 0)
- (goto-char pos)))
-
-(defun quoted-insert (arg)
- "Read next input character and insert it.
-This is useful for inserting control characters.
-You may also type up to 3 octal digits, to insert a character with that code.
-
-In overwrite mode, this function inserts the character anyway, and
-does not handle octal digits specially. This means that if you use
-overwrite as your normal editing mode, you can use this function to
-insert characters when necessary.
-
-In binary overwrite mode, this function does overwrite, and octal
-digits are interpreted as a character code. This is supposed to make
-this function useful in editing binary files."
- (interactive "*p")
- (let ((char (if (or (not overwrite-mode)
- (eq overwrite-mode 'overwrite-mode-binary))
- (read-quoted-char)
- (read-char))))
- (if (> arg 0)
- (if (eq overwrite-mode 'overwrite-mode-binary)
- (delete-char arg)))
- (while (> arg 0)
- (insert-and-inherit char)
- (setq arg (1- arg)))))
-
-(defun delete-indentation (&optional arg)
- "Join this line to previous and fix up whitespace at join.
-If there is a fill prefix, delete it from the beginning of this line.
-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)))
- ;; If the second line started with the fill prefix,
- ;; delete the prefix.
- (if (and fill-prefix
- (<= (+ (point) (length fill-prefix)) (point-max))
- (string= fill-prefix
- (buffer-substring (point)
- (+ (point) (length fill-prefix)))))
- (delete-region (point) (+ (point) (length fill-prefix))))
- (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 any immediately following blank lines."
- (interactive "*")
- (let (thisblank singleblank)
- (save-excursion
- (beginning-of-line)
- (setq thisblank (looking-at "[ \t]*$"))
- ;; Set singleblank if there is just one blank line here.
- (setq singleblank
- (and thisblank
- (not (looking-at "[ \t]*\n[ \t]*$"))
- (or (bobp)
- (progn (forward-line -1)
- (not (looking-at "[ \t]*$")))))))
- ;; Delete preceding blank lines, and this one too if it's the only one.
- (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)))))
- ;; Delete following blank lines, unless the current line is blank
- ;; and there are no following blank lines.
- (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)))))
- ;; Handle the special case where point is followed by newline and eob.
- ;; Delete the line, leaving point at eob.
- (if (looking-at "^[ \t]*\n\\'")
- (delete-region (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 value of `indent-line-function'.
-In programming language modes, this is the same as TAB.
-In some text modes, where TAB inserts a tab, this command indents to the
-column specified by the function `current-left-margin'."
- (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 calling the current value of `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
-column specified by the function `current-left-margin'."
- (interactive "*")
- (save-excursion
- (delete-region (point) (progn (skip-chars-backward " \t") (point)))
- (indent-according-to-mode))
- (newline)
- (indent-according-to-mode))
-
-;; Internal subroutine of delete-char
-(defun kill-forward-chars (arg)
- (if (listp arg) (setq arg (car arg)))
- (if (eq arg '-) (setq arg -1))
- (kill-region (point) (+ (point) arg)))
-
-;; Internal subroutine of backward-delete-char
-(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 a prefix arg 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 and including ARG'th occurrence of CHAR.
-Goes backward if ARG is negative; error if CHAR not found."
- (interactive "p\ncZap to char: ")
- (kill-region (point) (progn
- (search-forward (char-to-string char) nil nil arg)
-; (goto-char (if (> arg 0) (1- (point)) (1+ (point))))
- (point))))
-
-(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 beginning.
-
-If the buffer is narrowed, this command uses the beginning and size
-of the accessible part of the buffer.
-
-Don't use this command in Lisp programs!
-\(goto-char (point-min)) is faster and avoids clobbering the mark."
- (interactive "P")
- (push-mark)
- (let ((size (- (point-max) (point-min))))
- (goto-char (if arg
- (+ (point-min)
- (if (> size 10000)
- ;; Avoid overflow for large buffer sizes!
- (* (prefix-numeric-value arg)
- (/ size 10))
- (/ (+ 10 (* 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 end.
-
-If the buffer is narrowed, this command uses the beginning and size
-of the accessible part of the buffer.
-
-Don't use this command in Lisp programs!
-\(goto-char (point-max)) is faster and avoids clobbering the mark."
- (interactive "P")
- (push-mark)
- (let ((size (- (point-max) (point-min))))
- (goto-char (if arg
- (- (point-max)
- (if (> size 10000)
- ;; Avoid overflow for large buffer sizes!
- (* (prefix-numeric-value arg)
- (/ size 10))
- (/ (* size (prefix-numeric-value arg)) 10)))
- (point-max))))
- ;; If we went to a place in the middle of the buffer,
- ;; adjust it to the beginning of a line.
- (if arg (forward-line 1)
- ;; If the end of the buffer is not already on the screen,
- ;; then scroll specially to put it near, but not at, the bottom.
- (if (let ((old-point (point)))
- (save-excursion
- (goto-char (window-start))
- (vertical-motion (window-height))
- (< (point) old-point)))
- (progn
- (overlay-recenter (point))
- (recenter -3)))))
-
-(defun mark-whole-buffer ()
- "Put point at beginning and mark at end of buffer.
-You probably should not use this function in Lisp programs;
-it is usually a mistake for a Lisp function to use any subroutine
-that uses or sets the mark."
- (interactive)
- (push-mark (point))
- (push-mark (point-max) nil t)
- (goto-char (point-min)))
-
-(defun count-lines-region (start end)
- "Print number of lines and characters in the region."
- (interactive "r")
- (message "Region has %d lines, %d characters"
- (count-lines start end) (- end start)))
-
-(defun what-line ()
- "Print the current buffer line number and narrowed line number of point."
- (interactive)
- (let ((opoint (point)) start)
- (save-excursion
- (save-restriction
- (goto-char (point-min))
- (widen)
- (beginning-of-line)
- (setq start (point))
- (goto-char opoint)
- (beginning-of-line)
- (if (/= start 1)
- (message "line %d (narrowed line %d)"
- (1+ (count-lines 1 (point)))
- (1+ (count-lines start (point))))
- (message "Line %d" (1+ (count-lines 1 (point)))))))))
-
-
-(defun count-lines (start end)
- "Return number of lines between START and END.
-This is usually the number of newlines between them,
-but can be one more if START is not equal to END
-and the greater of them is not at the start of a line."
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (goto-char (point-min))
- (if (eq selective-display t)
- (save-match-data
- (let ((done 0))
- (while (re-search-forward "[\n\C-m]" nil t 40)
- (setq done (+ 40 done)))
- (while (re-search-forward "[\n\C-m]" nil t 1)
- (setq done (+ 1 done)))
- (goto-char (point-max))
- (if (and (/= start end)
- (not (bolp)))
- (1+ done)
- done)))
- (- (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, %d, 0x%x) point=%d of %d(%d%%) <%d - %d> column %d %s"
- (single-key-description char) char char char pos total percent beg end col hscroll)
- (message "Char: %s (0%o, %d, 0x%x) point=%d of %d(%d%%) column %d %s"
- (single-key-description char) char 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))
-
-(defvar read-expression-map (cons 'keymap minibuffer-local-map)
- "Minibuffer keymap used for reading Lisp expressions.")
-(define-key read-expression-map "\M-\t" 'lisp-complete-symbol)
-
-(put 'eval-expression 'disabled t)
-
-(defvar read-expression-history nil)
-
-;; 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 the variable `values'."
- (interactive
- (list (read-from-minibuffer "Eval: "
- nil read-expression-map t
- 'read-expression-history)))
- (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."
- (let ((command (read-from-minibuffer prompt
- (prin1-to-string command)
- read-expression-map t
- '(command-history . 1))))
- ;; If command was added to command-history as a string,
- ;; get rid of that. We want only evaluable expressions there.
- (if (stringp (car command-history))
- (setq command-history (cdr command-history)))
-
- ;; If command to be redone does not match front of history,
- ;; add it to the history.
- (or (equal command (car command-history))
- (setq command-history (cons command command-history)))
- (eval command)))
-
-(defun 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.
-You can use the minibuffer history commands \\<minibuffer-local-map>\\[next-history-element] and \\[previous-history-element]
-to get different commands to edit and resubmit."
- (interactive "p")
- (let ((elt (nth (1- arg) command-history))
- newcmd)
- (if elt
- (progn
- (setq newcmd
- (let ((print-level nil)
- (minibuffer-history-position arg)
- (minibuffer-history-sexp-flag t))
- (read-from-minibuffer
- "Redo: " (prin1-to-string elt) read-expression-map t
- (cons 'command-history arg))))
-
- ;; If command was added to command-history as a string,
- ;; get rid of that. We want only evaluable expressions there.
- (if (stringp (car command-history))
- (setq command-history (cdr command-history)))
-
- ;; 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))))
-
-(defvar minibuffer-history nil
- "Default minibuffer history list.
-This is used for all minibuffer input
-except when an alternate history list is specified.")
-(defvar minibuffer-history-sexp-flag nil
- "Non-nil when doing history operations on `command-history'.
-More generally, indicates that the history list being acted on
-contains expressions rather than strings.")
-(setq minibuffer-history-variable 'minibuffer-history)
-(setq minibuffer-history-position nil)
-(defvar minibuffer-history-search-history nil)
-
-(mapcar
- (lambda (key-and-command)
- (mapcar
- (lambda (keymap-and-completionp)
- ;; Arg is (KEYMAP-SYMBOL . COMPLETION-MAP-P).
- ;; If the cdr of KEY-AND-COMMAND (the command) is a cons,
- ;; its car is used if COMPLETION-MAP-P is nil, its cdr if it is t.
- (define-key (symbol-value (car keymap-and-completionp))
- (car key-and-command)
- (let ((command (cdr key-and-command)))
- (if (consp command)
- ;; (and ... nil) => ... turns back on the completion-oriented
- ;; history commands which rms turned off since they seem to
- ;; do things he doesn't like.
- (if (and (cdr keymap-and-completionp) nil) ;XXX turned off
- (progn (error "EMACS BUG!") (cdr command))
- (car command))
- command))))
- '((minibuffer-local-map . nil)
- (minibuffer-local-ns-map . nil)
- (minibuffer-local-completion-map . t)
- (minibuffer-local-must-match-map . t)
- (read-expression-map . nil))))
- '(("\en" . (next-history-element . next-complete-history-element))
- ([next] . (next-history-element . next-complete-history-element))
- ("\ep" . (previous-history-element . previous-complete-history-element))
- ([prior] . (previous-history-element . previous-complete-history-element))
- ("\er" . previous-matching-history-element)
- ("\es" . next-matching-history-element)))
-
-(defun previous-matching-history-element (regexp n)
- "Find the previous history element that matches REGEXP.
-\(Previous history elements refer to earlier actions.)
-With prefix argument N, search for Nth previous match.
-If N is negative, find the next or Nth next match."
- (interactive
- (let* ((enable-recursive-minibuffers t)
- (minibuffer-history-sexp-flag nil)
- (regexp (read-from-minibuffer "Previous element matching (regexp): "
- nil
- minibuffer-local-map
- nil
- 'minibuffer-history-search-history)))
- ;; Use the last regexp specified, by default, if input is empty.
- (list (if (string= regexp "")
- (if minibuffer-history-search-history
- (car minibuffer-history-search-history)
- (error "No previous history search regexp"))
- regexp)
- (prefix-numeric-value current-prefix-arg))))
- (let ((history (symbol-value minibuffer-history-variable))
- prevpos
- (pos minibuffer-history-position))
- (while (/= n 0)
- (setq prevpos pos)
- (setq pos (min (max 1 (+ pos (if (< n 0) -1 1))) (length history)))
- (if (= pos prevpos)
- (error (if (= pos 1)
- "No later matching history item"
- "No earlier matching history item")))
- (if (string-match regexp
- (if minibuffer-history-sexp-flag
- (let ((print-level nil))
- (prin1-to-string (nth (1- pos) history)))
- (nth (1- pos) history)))
- (setq n (+ n (if (< n 0) 1 -1)))))
- (setq minibuffer-history-position pos)
- (erase-buffer)
- (let ((elt (nth (1- pos) history)))
- (insert (if minibuffer-history-sexp-flag
- (let ((print-level nil))
- (prin1-to-string elt))
- elt)))
- (goto-char (point-min)))
- (if (or (eq (car (car command-history)) 'previous-matching-history-element)
- (eq (car (car command-history)) 'next-matching-history-element))
- (setq command-history (cdr command-history))))
-
-(defun next-matching-history-element (regexp n)
- "Find the next history element that matches REGEXP.
-\(The next history element refers to a more recent action.)
-With prefix argument N, search for Nth next match.
-If N is negative, find the previous or Nth previous match."
- (interactive
- (let* ((enable-recursive-minibuffers t)
- (minibuffer-history-sexp-flag nil)
- (regexp (read-from-minibuffer "Next element matching (regexp): "
- nil
- minibuffer-local-map
- nil
- 'minibuffer-history-search-history)))
- ;; Use the last regexp specified, by default, if input is empty.
- (list (if (string= regexp "")
- (setcar minibuffer-history-search-history
- (nth 1 minibuffer-history-search-history))
- regexp)
- (prefix-numeric-value current-prefix-arg))))
- (previous-matching-history-element regexp (- n)))
-
-(defun next-history-element (n)
- "Insert the next element of the minibuffer history into the minibuffer."
- (interactive "p")
- (or (zerop n)
- (let ((narg (min (max 1 (- minibuffer-history-position n))
- (length (symbol-value minibuffer-history-variable)))))
- (if (or (zerop narg)
- (= minibuffer-history-position narg))
- (error (if (if (zerop narg)
- (> n 0)
- (= minibuffer-history-position 1))
- "End of history; no next item"
- "Beginning of history; no preceding item"))
- (erase-buffer)
- (setq minibuffer-history-position narg)
- (let ((elt (nth (1- minibuffer-history-position)
- (symbol-value minibuffer-history-variable))))
- (insert
- (if minibuffer-history-sexp-flag
- (let ((print-level nil))
- (prin1-to-string elt))
- elt)))
- (goto-char (point-min))))))
-
-(defun previous-history-element (n)
- "Inserts the previous element of the minibuffer history into the minibuffer."
- (interactive "p")
- (next-history-element (- n)))
-
-(defun next-complete-history-element (n)
- "Get next element of history which is a completion of minibuffer contents."
- (interactive "p")
- (let ((point-at-start (point)))
- (next-matching-history-element
- (concat "^" (regexp-quote (buffer-substring (point-min) (point)))) n)
- ;; next-matching-history-element always puts us at (point-min).
- ;; Move to the position we were at before changing the buffer contents.
- ;; This is still sensical, because the text before point has not changed.
- (goto-char point-at-start)))
-
-(defun previous-complete-history-element (n)
- "\
-Get previous element of history which is a completion of minibuffer contents."
- (interactive "p")
- (next-complete-history-element (- n)))
-
-(defun goto-line (arg)
- "Goto line ARG, counting from line 1 at beginning of buffer."
- (interactive "NGoto line: ")
- (setq arg (prefix-numeric-value arg))
- (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
-(defalias '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")
- ;; If we don't get all the way thru, make last-command indicate that
- ;; for the following command.
- (setq this-command t)
- (let ((modified (buffer-modified-p))
- (recent-save (recent-auto-save-p)))
- (or (eq (selected-window) (minibuffer-window))
- (message "Undo!"))
- (or (eq last-command 'undo)
- (progn (undo-start)
- (undo-more 1)))
- (undo-more (or arg 1))
- ;; Don't specify a position in the undo record for the undo command.
- ;; Instead, undoing this should move point to where the change is.
- (let ((tail buffer-undo-list)
- done)
- (while (and tail (not done) (not (null (car tail))))
- (if (integerp (car tail))
- (progn
- (setq done t)
- (setq buffer-undo-list (delq (car tail) buffer-undo-list))))
- (setq tail (cdr tail))))
- (and modified (not (buffer-modified-p))
- (delete-auto-save-file-if-necessary recent-save)))
- ;; If we do get all the way thru, make this-command indicate that.
- (setq this-command 'undo))
-
-(defvar pending-undo-list nil
- "Within a run of consecutive undo commands, list remaining to be undone.")
-
-(defun undo-start ()
- "Set `pending-undo-list' to the front of the undo list.
-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)))
-
-(defvar shell-command-history nil
- "History list for some commands that read shell commands.")
-
-(defvar shell-command-switch "-c"
- "Switch used to have the shell execute its command line argument.")
-
-(defun shell-command (command &optional output-buffer)
- "Execute string COMMAND in inferior shell; display output, if any.
-
-If COMMAND ends in ampersand, execute it asynchronously.
-The output appears in the buffer `*Async Shell Command*'.
-That buffer is in shell mode.
-
-Otherwise, COMMAND is executed synchronously. The output appears in the
-buffer `*Shell Command Output*'.
-If the output is one line, it is displayed in the echo area *as well*,
-but it is nonetheless available in buffer `*Shell Command Output*',
-even though that buffer is not automatically displayed.
-If there is no output, or if output is inserted in the current buffer,
-then `*Shell Command Output*' is deleted.
-
-The optional second argument OUTPUT-BUFFER, if non-nil,
-says to put the output in some other buffer.
-If OUTPUT-BUFFER is a buffer or buffer name, put the output there.
-If OUTPUT-BUFFER is not a buffer and not nil,
-insert output in current buffer. (This cannot be done asynchronously.)
-In either case, the output is inserted after point (leaving mark after it)."
- (interactive (list (read-from-minibuffer "Shell command: "
- nil nil nil 'shell-command-history)
- current-prefix-arg))
- ;; Look for a handler in case default-directory is a remote file name.
- (let ((handler
- (find-file-name-handler (directory-file-name default-directory)
- 'shell-command)))
- (if handler
- (funcall handler 'shell-command command output-buffer)
- (if (and output-buffer
- (not (or (bufferp output-buffer) (stringp output-buffer))))
- (progn (barf-if-buffer-read-only)
- (push-mark)
- ;; We do not use -f for csh; we will not support broken use of
- ;; .cshrcs. Even the BSD csh manual says to use
- ;; "if ($?prompt) exit" before things which are not useful
- ;; non-interactively. Besides, if someone wants their other
- ;; aliases for shell commands then they can still have them.
- (call-process shell-file-name nil t nil
- shell-command-switch command)
- ;; This is like exchange-point-and-mark, but doesn't
- ;; activate the mark. It is cleaner to avoid activation,
- ;; even though the command loop would deactivate the mark
- ;; because we inserted text.
- (goto-char (prog1 (mark t)
- (set-marker (mark-marker) (point)
- (current-buffer)))))
- ;; Preserve the match data in case called from a program.
- (save-match-data
- (if (string-match "[ \t]*&[ \t]*$" command)
- ;; Command ending with ampersand means asynchronous.
- (let ((buffer (get-buffer-create
- (or output-buffer "*Async Shell Command*")))
- (directory default-directory)
- proc)
- ;; Remove the ampersand.
- (setq command (substring command 0 (match-beginning 0)))
- ;; If will kill a process, query first.
- (setq proc (get-buffer-process buffer))
- (if proc
- (if (yes-or-no-p "A command is running. Kill it? ")
- (kill-process proc)
- (error "Shell command in progress")))
- (save-excursion
- (set-buffer buffer)
- (setq buffer-read-only nil)
- (erase-buffer)
- (display-buffer buffer)
- (setq default-directory directory)
- (setq proc (start-process "Shell" buffer shell-file-name
- shell-command-switch command))
- (setq mode-line-process '(":%s"))
- (require 'shell) (shell-mode)
- (set-process-sentinel proc 'shell-command-sentinel)
- ))
- (shell-command-on-region (point) (point) command output-buffer)
- ))))))
-
-;; We have a sentinel to prevent insertion of a termination message
-;; in the buffer itself.
-(defun shell-command-sentinel (process signal)
- (if (memq (process-status process) '(exit signal))
- (message "%s: %s."
- (car (cdr (cdr (process-command process))))
- (substring signal 0 -1))))
-
-(defun shell-command-on-region (start end command
- &optional output-buffer replace)
- "Execute string COMMAND in inferior shell with region as input.
-Normally display output (if any) in temp buffer `*Shell Command Output*';
-Prefix arg means replace the region with it.
-
-The noninteractive arguments are START, END, COMMAND, OUTPUT-BUFFER, REPLACE.
-If REPLACE is non-nil, that means insert the output
-in place of text from START to END, putting point and mark around it.
-
-If the output is one line, it is displayed in the echo area,
-but it is nonetheless available in buffer `*Shell Command Output*'
-even though that buffer is not automatically displayed.
-If there is no output, or if output is inserted in the current buffer,
-then `*Shell Command Output*' is deleted.
-
-If the optional fourth argument OUTPUT-BUFFER is non-nil,
-that says to put the output in some other buffer.
-If OUTPUT-BUFFER is a buffer or buffer name, put the output there.
-If OUTPUT-BUFFER is not a buffer and not nil,
-insert output in the current buffer.
-In either case, the output is inserted after point (leaving mark after it)."
- (interactive (let ((string
- ;; Do this before calling region-beginning
- ;; and region-end, in case subprocess output
- ;; relocates them while we are in the minibuffer.
- (read-from-minibuffer "Shell command on region: "
- nil nil nil
- 'shell-command-history)))
- ;; call-interactively recognizes region-beginning and
- ;; region-end specially, leaving them in the history.
- (list (region-beginning) (region-end)
- string
- current-prefix-arg
- current-prefix-arg)))
- (if (or replace
- (and output-buffer
- (not (or (bufferp output-buffer) (stringp output-buffer))))
- (equal (buffer-name (current-buffer)) "*Shell Command Output*"))
- ;; Replace specified region with output from command.
- (let ((swap (and replace (< start end))))
- ;; Don't muck with mark unless REPLACE says we should.
- (goto-char start)
- (and replace (push-mark))
- (call-process-region start end shell-file-name t t nil
- shell-command-switch command)
- (let ((shell-buffer (get-buffer "*Shell Command Output*")))
- (and shell-buffer (not (eq shell-buffer (current-buffer)))
- (kill-buffer shell-buffer)))
- ;; Don't muck with mark unless REPLACE says we should.
- (and replace swap (exchange-point-and-mark)))
- ;; No prefix argument: put the output in a temp buffer,
- ;; replacing its entire contents.
- (let ((buffer (get-buffer-create
- (or output-buffer "*Shell Command Output*")))
- (success nil))
- (unwind-protect
- (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 (setq buffer-read-only nil)
- (delete-region (max start end) (point-max))
- (delete-region (point-min) (min start end))
- (call-process-region (point-min) (point-max)
- shell-file-name t t nil
- shell-command-switch command)
- (setq success t))
- ;; Clear the output buffer, then run the command with output there.
- (save-excursion
- (set-buffer buffer)
- (setq buffer-read-only nil)
- (erase-buffer))
- (call-process-region start end shell-file-name
- nil buffer nil
- shell-command-switch command)
- (setq success t))
- ;; Report the amount of output.
- (let ((lines (save-excursion
- (set-buffer buffer)
- (if (= (buffer-size) 0)
- 0
- (count-lines (point-min) (point-max))))))
- (cond ((= lines 0)
- (if success
- (message "(Shell command completed with no output)"))
- (kill-buffer buffer))
- ((and success (= lines 1))
- (message "%s"
- (save-excursion
- (set-buffer buffer)
- (goto-char (point-min))
- (buffer-substring (point)
- (progn (end-of-line) (point))))))
- (t
- (save-excursion
- (set-buffer buffer)
- (goto-char (point-min)))
- (display-buffer buffer))))))))
-
-(defun shell-command-to-string (command)
- "Execute shell command COMMAND and return its output as a string."
- (with-output-to-string
- (with-current-buffer
- standard-output
- (call-process shell-file-name nil t nil shell-command-switch command))))
-
-(defvar universal-argument-map
- (let ((map (make-sparse-keymap)))
- (define-key map [t] 'universal-argument-other-key)
- (define-key map (vector meta-prefix-char t) 'universal-argument-other-key)
- (define-key map [switch-frame] nil)
- (define-key map [?\C-u] 'universal-argument-more)
- (define-key map [?-] 'universal-argument-minus)
- (define-key map [?0] 'digit-argument)
- (define-key map [?1] 'digit-argument)
- (define-key map [?2] 'digit-argument)
- (define-key map [?3] 'digit-argument)
- (define-key map [?4] 'digit-argument)
- (define-key map [?5] 'digit-argument)
- (define-key map [?6] 'digit-argument)
- (define-key map [?7] 'digit-argument)
- (define-key map [?8] 'digit-argument)
- (define-key map [?9] 'digit-argument)
- map)
- "Keymap used while processing \\[universal-argument].")
-
-(defvar universal-argument-num-events nil
- "Number of argument-specifying events read by `universal-argument'.
-`universal-argument-other-key' uses this to discard those events
-from (this-command-keys), and reread only the final command.")
-
-(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.
-For some commands, just \\[universal-argument] by itself serves as a flag
-which is different in effect from any particular numeric argument.
-These commands include \\[set-mark-command] and \\[start-kbd-macro]."
- (interactive)
- (setq prefix-arg (list 4))
- (setq universal-argument-num-events (length (this-command-keys)))
- (setq overriding-terminal-local-map universal-argument-map))
-
-;; A subsequent C-u means to multiply the factor by 4 if we've typed
-;; nothing but C-u's; otherwise it means to terminate the prefix arg.
-(defun universal-argument-more (arg)
- (interactive "P")
- (if (consp arg)
- (setq prefix-arg (list (* 4 (car arg))))
- (setq prefix-arg arg)
- (setq overriding-terminal-local-map nil))
- (setq universal-argument-num-events (length (this-command-keys))))
-
-(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")
- (cond ((integerp arg)
- (setq prefix-arg (- arg)))
- ((eq arg '-)
- (setq prefix-arg nil))
- (t
- (setq prefix-arg '-)))
- (setq universal-argument-num-events (length (this-command-keys)))
- (setq overriding-terminal-local-map universal-argument-map))
-
-(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")
- (let ((digit (- (logand last-command-char ?\177) ?0)))
- (cond ((integerp arg)
- (setq prefix-arg (+ (* arg 10)
- (if (< arg 0) (- digit) digit))))
- ((eq arg '-)
- ;; Treat -0 as just -, so that -01 will work.
- (setq prefix-arg (if (zerop digit) '- (- digit))))
- (t
- (setq prefix-arg digit))))
- (setq universal-argument-num-events (length (this-command-keys)))
- (setq overriding-terminal-local-map universal-argument-map))
-
-;; For backward compatibility, minus with no modifiers is an ordinary
-;; command if digits have already been entered.
-(defun universal-argument-minus (arg)
- (interactive "P")
- (if (integerp arg)
- (universal-argument-other-key arg)
- (negative-argument arg)))
-
-;; Anything else terminates the argument and is left in the queue to be
-;; executed as a command.
-(defun universal-argument-other-key (arg)
- (interactive "P")
- (setq prefix-arg arg)
- (let* ((key (this-command-keys))
- (keylist (listify-key-sequence key)))
- (setq unread-command-events
- (append (nthcdr universal-argument-num-events keylist)
- unread-command-events)))
- (reset-this-command-lengths)
- (setq overriding-terminal-local-map nil))
-
-(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"))
-
-(defvar kill-whole-line nil
- "*If non-nil, `kill-line' with no arg at beg of line kills the whole line.")
-
-(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.
-
-If `kill-whole-line' is non-nil, then kill the whole line
-when given no argument at the beginning of a line."
- (interactive "P")
- (kill-region (point)
- ;; It is better to move point to the other end of the kill
- ;; before killing. That way, in a read-only buffer, point
- ;; moves across the text that is copied to the kill ring.
- ;; The choice has no effect on undo now that undo records
- ;; the value of point from before the command was run.
- (progn
- (if arg
- (forward-line (prefix-numeric-value arg))
- (if (eobp)
- (signal 'end-of-buffer nil))
- (if (or (looking-at "[ \t]*$") (and kill-whole-line (bolp)))
- (forward-line 1)
- (end-of-line)))
- (point))))
-
-;;;; Window system cut and paste hooks.
-
-(defvar interprogram-cut-function nil
- "Function to call to make a killed region available to other programs.
-
-Most window systems provide some sort of facility for cutting and
-pasting text between the windows of different programs.
-This variable holds a function that Emacs calls whenever text
-is put in the kill ring, to make the new kill available to other
-programs.
-
-The function takes one or two arguments.
-The first argument, TEXT, is a string containing
-the text which should be made available.
-The second, PUSH, if non-nil means this is a \"new\" kill;
-nil means appending to an \"old\" kill.")
-
-(defvar interprogram-paste-function nil
- "Function to call to get text cut from other programs.
-
-Most window systems provide some sort of facility for cutting and
-pasting text between the windows of different programs.
-This variable holds a function that Emacs calls to obtain
-text that other programs have provided for pasting.
-
-The function should be called with no arguments. If the function
-returns nil, then no other program has provided such text, and the top
-of the Emacs kill ring should be used. If the function returns a
-string, that string should be put in the kill ring as the latest kill.
-
-Note that the function should return a string only if a program other
-than Emacs has provided a string for pasting; if Emacs provided the
-most recent string, the function should return nil. If it is
-difficult to tell whether Emacs or some other program provided the
-current string, it is probably good enough to return nil if the string
-is equal (according to `string=') to the last text Emacs provided.")
-
-
-
-;;;; The kill ring data structure.
-
-(defvar kill-ring nil
- "List of killed text sequences.
-Since the kill ring is supposed to interact nicely with cut-and-paste
-facilities offered by window systems, use of this variable should
-interact nicely with `interprogram-cut-function' and
-`interprogram-paste-function'. The functions `kill-new',
-`kill-append', and `current-kill' are supposed to implement this
-interaction; you may want to use them instead of manipulating the kill
-ring directly.")
-
-(defvar 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-new (string &optional replace)
- "Make STRING the latest kill in the kill ring.
-Set the kill-ring-yank pointer to point to it.
-If `interprogram-cut-function' is non-nil, apply it to STRING.
-Optional second argument REPLACE non-nil means that STRING will replace
-the front of the kill ring, rather than being added to the list."
- (and (fboundp 'menu-bar-update-yank-menu)
- (menu-bar-update-yank-menu string (and replace (car kill-ring))))
- (if replace
- (setcar kill-ring string)
- (setq kill-ring (cons string kill-ring))
- (if (> (length kill-ring) kill-ring-max)
- (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil)))
- (setq kill-ring-yank-pointer kill-ring)
- (if interprogram-cut-function
- (funcall interprogram-cut-function string (not replace))))
-
-(defun kill-append (string before-p)
- "Append STRING to the end of the latest kill in the kill ring.
-If BEFORE-P is non-nil, prepend STRING to the kill.
-If `interprogram-cut-function' is set, pass the resulting kill to
-it."
- (kill-new (if before-p
- (concat string (car kill-ring))
- (concat (car kill-ring) string)) t))
-
-(defun current-kill (n &optional do-not-move)
- "Rotate the yanking point by N places, and then return that kill.
-If N is zero, `interprogram-paste-function' is set, and calling it
-returns a string, then that string is added to the front of the
-kill ring and returned as the latest kill.
-If optional arg DO-NOT-MOVE is non-nil, then don't actually move the
-yanking point; just return the Nth kill forward."
- (let ((interprogram-paste (and (= n 0)
- interprogram-paste-function
- (funcall interprogram-paste-function))))
- (if interprogram-paste
- (progn
- ;; Disable the interprogram cut function when we add the new
- ;; text to the kill ring, so Emacs doesn't try to own the
- ;; selection, with identical text.
- (let ((interprogram-cut-function nil))
- (kill-new interprogram-paste))
- interprogram-paste)
- (or kill-ring (error "Kill ring is empty"))
- (let ((ARGth-kill-element
- (nthcdr (mod (- n (length kill-ring-yank-pointer))
- (length kill-ring))
- kill-ring)))
- (or do-not-move
- (setq kill-ring-yank-pointer ARGth-kill-element))
- (car ARGth-kill-element)))))
-
-
-
-;;;; Commands for manipulating the kill ring.
-
-(defvar kill-read-only-ok nil
- "*Non-nil means don't signal an error for killing read-only text.")
-
-(put 'text-read-only 'error-conditions
- '(text-read-only buffer-read-only error))
-(put 'text-read-only 'error-message "Text is read-only")
-
-(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].)
-If the buffer is read-only, Emacs will beep and refrain from deleting
-the text, but put the text in the kill ring anyway. This means that
-you can use the killing commands to copy text from a read-only buffer.
-
-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")
- (cond
-
- ;; If the buffer is read-only, we should beep, in case the person
- ;; just isn't aware of this. However, there's no harm in putting
- ;; the region's text in the kill ring, anyway.
- ((and (not inhibit-read-only)
- (or buffer-read-only
- (text-property-not-all beg end 'read-only nil)))
- (copy-region-as-kill beg end)
- ;; This should always barf, and give us the correct error.
- (if kill-read-only-ok
- (message "Read only text copied to kill ring")
- (setq this-command 'kill-region)
- ;; Signal an error if the buffer is read-only.
- (barf-if-buffer-read-only)
- ;; If the buffer isn't read-only, the text is.
- (signal 'text-read-only (list (current-buffer)))))
-
- ;; In certain cases, we can arrange for the undo list and the kill
- ;; ring to share the same string object. This code does that.
- ((not (or (eq buffer-undo-list t)
- (eq last-command 'kill-region)
- ;; Use = since positions may be numbers or markers.
- (= beg end)))
- ;; Don't let the undo list be truncated before we can even access it.
- (let ((undo-strong-limit (+ (- (max beg end) (min beg end)) 100))
- (old-list buffer-undo-list)
- tail)
- (delete-region beg end)
- ;; Search back in buffer-undo-list for this string,
- ;; in case a change hook made property changes.
- (setq tail buffer-undo-list)
- (while (not (stringp (car (car tail))))
- (setq tail (cdr tail)))
- ;; Take the same string recorded for undo
- ;; and put it in the kill-ring.
- (kill-new (car (car tail)))))
-
- (t
- (copy-region-as-kill beg end)
- (delete-region beg end)))
- (setq this-command 'kill-region))
-
-;; copy-region-as-kill no longer sets this-command, because it's confusing
-;; to get two copies of the text when the user accidentally types M-w and
-;; then corrects it with the intended C-w.
-(defun copy-region-as-kill (beg end)
- "Save the region as if killed, but don't kill it.
-If `interprogram-cut-function' is non-nil, also save the text for a window
-system cut and paste."
- (interactive "r")
- (if (eq last-command 'kill-region)
- (kill-append (buffer-substring beg end) (< end beg))
- (kill-new (buffer-substring beg end)))
- nil)
-
-(defun kill-ring-save (beg end)
- "Save the region as if killed, but don't kill it.
-This command is similar to `copy-region-as-kill', except that it gives
-visual feedback indicating the extent of the region being copied.
-If `interprogram-cut-function' is non-nil, also save the text for a window
-system cut and paste."
- (interactive "r")
- (copy-region-as-kill beg end)
- (if (interactive-p)
- (let ((other-end (if (= (point) beg) end beg))
- (opoint (point))
- ;; Inhibit quitting so we can make a quit here
- ;; look like a C-g typed as a command.
- (inhibit-quit t))
- (if (pos-visible-in-window-p other-end (selected-window))
- (progn
- ;; Swap point and mark.
- (set-marker (mark-marker) (point) (current-buffer))
- (goto-char other-end)
- (sit-for 1)
- ;; Swap back.
- (set-marker (mark-marker) other-end (current-buffer))
- (goto-char opoint)
- ;; If user quit, deactivate the mark
- ;; as C-g would as a command.
- (and quit-flag mark-active
- (deactivate-mark)))
- (let* ((killed-text (current-kill 0))
- (message-len (min (length killed-text) 40)))
- (if (= (point) beg)
- ;; Don't say "killed"; that is misleading.
- (message "Saved text until \"%s\""
- (substring killed-text (- message-len)))
- (message "Saved text from \"%s\""
- (substring killed-text 0 message-len))))))))
-
-(defun append-next-kill ()
- "Cause following command, if it kills, to append to previous kill."
- (interactive)
- (if (interactive-p)
- (progn
- (setq this-command 'kill-region)
- (message "If the next command is a kill, it will append"))
- (setq last-command 'kill-region)))
-
-(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, insert the Nth previous kill.
-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 ((inhibit-read-only t)
- (before (< (point) (mark t))))
- (delete-region (point) (mark t))
- (set-marker (mark-marker) (point) (current-buffer))
- (insert (current-kill arg))
- (if before
- ;; This is like exchange-point-and-mark, but doesn't activate the mark.
- ;; It is cleaner to avoid activation, even though the command
- ;; loop would deactivate the mark because we inserted text.
- (goto-char (prog1 (mark t)
- (set-marker (mark-marker) (point) (current-buffer))))))
- nil)
-
-(defun yank (&optional arg)
- "Reinsert the last stretch of killed text.
-More precisely, reinsert the stretch of killed text most recently
-killed OR yanked. Put point at end, and set mark at beginning.
-With just C-u as argument, same but put point at beginning (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")
- ;; If we don't get all the way thru, make last-command indicate that
- ;; for the following command.
- (setq this-command t)
- (push-mark (point))
- (insert (current-kill (cond
- ((listp arg) 0)
- ((eq arg '-) -1)
- (t (1- arg)))))
- (if (consp arg)
- ;; This is like exchange-point-and-mark, but doesn't activate the mark.
- ;; It is cleaner to avoid activation, even though the command
- ;; loop would deactivate the mark because we inserted text.
- (goto-char (prog1 (mark t)
- (set-marker (mark-marker) (point) (current-buffer)))))
- ;; If we do get all the way thru, make this-command indicate that.
- (setq this-command 'yank)
- nil)
-
-(defun rotate-yank-pointer (arg)
- "Rotate the yanking point in the kill ring.
-With argument, rotate that many kills forward (or backward, if negative)."
- (interactive "p")
- (current-kill arg))
-
-
-(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
- (list
- (progn
- (barf-if-buffer-read-only)
- (read-buffer "Insert buffer: "
- (if (eq (selected-window) (next-window (selected-window)))
- (other-buffer (current-buffer))
- (window-buffer (next-window (selected-window))))
- t))))
- (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))
- nil)
-
-(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:
-BUFFER (or buffer name), START and END.
-START and END specify the portion of the current buffer to be copied."
- (interactive
- (list (read-buffer "Append to buffer: " (other-buffer (current-buffer) t))
- (region-beginning) (region-end)))
- (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:
-BUFFER (or buffer name), START and END.
-START and END specify 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:
-BUFFER (or buffer name), START and END.
-START and END specify 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)))))
-
-(put 'mark-inactive 'error-conditions '(mark-inactive error))
-(put 'mark-inactive 'error-message "The mark is not active now")
-
-(defun mark (&optional force)
- "Return this buffer's mark value as integer; error if mark inactive.
-If optional argument FORCE is non-nil, access the mark value
-even if the mark is not currently active, and return nil
-if there is no mark at all.
-
-If you are using this in an editing command, you are most likely making
-a mistake; see the documentation of `set-mark'."
- (if (or force (not transient-mark-mode) mark-active mark-even-if-inactive)
- (marker-position (mark-marker))
- (signal 'mark-inactive nil)))
-
-;; Many places set mark-active directly, and several of them failed to also
-;; run deactivate-mark-hook. This shorthand should simplify.
-(defsubst deactivate-mark ()
- "Deactivate the mark by setting `mark-active' to nil.
-\(That makes a difference only in Transient Mark mode.)
-Also runs the hook `deactivate-mark-hook'."
- (if transient-mark-mode
- (progn
- (setq mark-active nil)
- (run-hooks 'deactivate-mark-hook))))
-
-(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)))."
-
- (if pos
- (progn
- (setq mark-active t)
- (run-hooks 'activate-mark-hook)
- (set-marker (mark-marker) pos (current-buffer)))
- ;; Normally we never clear mark-active except in Transient Mark mode.
- ;; But when we actually clear out the mark value too,
- ;; we must clear mark-active in any mode.
- (setq mark-active nil)
- (run-hooks 'deactivate-mark-hook)
- (set-marker (mark-marker) nil)))
-
-(defvar mark-ring nil
- "The list of former marks of the current buffer, most recent first.")
-(make-variable-buffer-local 'mark-ring)
-(put 'mark-ring 'permanent-local t)
-
-(defvar mark-ring-max 16
- "*Maximum size of mark ring. Start discarding off end if gets this big.")
-
-(defvar global-mark-ring nil
- "The list of saved global marks, most recent first.")
-
-(defvar global-mark-ring-max 16
- "*Maximum size of global 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, push old mark position on local mark
-ring, and push mark on global mark ring.
-With argument, jump to mark, and pop a new position for mark off the ring
-\(does not affect global 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)
- (progn
- (push-mark nil nil t))
- (if (null (mark t))
- (error "No mark set in this buffer")
- (goto-char (mark t))
- (pop-mark))))
-
-(defun push-mark (&optional location nomsg activate)
- "Set mark at LOCATION (point, by default) and push old mark on mark ring.
-If the last global mark pushed was not in the current buffer,
-also push LOCATION on the global mark ring.
-Display `Mark set' unless the optional second arg NOMSG is non-nil.
-In Transient Mark mode, activate mark if optional third arg ACTIVATE 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.
-
-In Transient Mark mode, this does not activate the mark."
- (if (null (mark t))
- 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-marker (mark-marker) (or location (point)) (current-buffer))
- ;; Now push the mark on the global mark ring.
- (if (and global-mark-ring
- (eq (marker-buffer (car global-mark-ring)) (current-buffer)))
- ;; The last global mark pushed was in this same buffer.
- ;; Don't push another one.
- nil
- (setq global-mark-ring (cons (copy-marker (mark-marker)) global-mark-ring))
- (if (> (length global-mark-ring) global-mark-ring-max)
- (progn
- (move-marker (car (nthcdr global-mark-ring-max global-mark-ring))
- nil)
- (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil))))
- (or nomsg executing-kbd-macro (> (minibuffer-depth) 0)
- (message "Mark set"))
- (if (or activate (not transient-mark-mode))
- (set-mark (mark t)))
- nil)
-
-(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-marker (mark-marker) (+ 0 (car mark-ring)) (current-buffer))
- (deactivate-mark)
- (move-marker (car mark-ring) nil)
- (if (null (mark t)) (ding))
- (setq mark-ring (cdr mark-ring)))))
-
-(defalias '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.
-This command works even when the mark is not active,
-and it reactivates the mark."
- (interactive nil)
- (let ((omark (mark t)))
- (if (null omark)
- (error "No mark set in this buffer"))
- (set-mark (point))
- (goto-char omark)
- nil))
-
-(defun transient-mark-mode (arg)
- "Toggle Transient Mark mode.
-With arg, turn Transient Mark mode on if arg is positive, off otherwise.
-
-In Transient Mark mode, when the mark is active, the region is highlighted.
-Changing the buffer \"deactivates\" the mark.
-So do certain other operations that set the mark
-but whose main purpose is something else--for example,
-incremental search, \\[beginning-of-buffer], and \\[end-of-buffer]."
- (interactive "P")
- (setq transient-mark-mode
- (if (null arg)
- (not transient-mark-mode)
- (> (prefix-numeric-value arg) 0))))
-
-(defun pop-global-mark ()
- "Pop off global mark ring and jump to the top location."
- (interactive)
- ;; Pop entries which refer to non-existent buffers.
- (while (and global-mark-ring (not (marker-buffer (car global-mark-ring))))
- (setq global-mark-ring (cdr global-mark-ring)))
- (or global-mark-ring
- (error "No global mark set"))
- (let* ((marker (car global-mark-ring))
- (buffer (marker-buffer marker))
- (position (marker-position marker)))
- (setq global-mark-ring (nconc (cdr global-mark-ring)
- (list (car global-mark-ring))))
- (set-buffer buffer)
- (or (and (>= position (point-min))
- (<= position (point-max)))
- (widen))
- (goto-char position)
- (switch-to-buffer buffer)))
-
-(defvar next-line-add-newlines t
- "*If non-nil, `next-line' inserts newline to avoid `end of buffer' error.")
-
-(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, behavior depends on the
-value of `next-line-add-newlines'. If non-nil, it inserts a newline character
-to create a line, and moves the cursor to that line. Otherwise it moves the
-cursor to the end of the buffer.
-
-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. This goal column is stored
-in `goal-column', which is nil when there is none.
-
-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 (and next-line-add-newlines (= arg 1))
- (let ((opoint (point)))
- (end-of-line)
- (if (eobp)
- (newline 1)
- (goto-char opoint)
- (line-move arg)))
- (if (interactive-p)
- (condition-case nil
- (line-move arg)
- ((beginning-of-buffer end-of-buffer) (ding)))
- (line-move 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 a negative argument instead. It is usually easier
-to use and more reliable (no dependence on goal column, etc.)."
- (interactive "p")
- (if (interactive-p)
- (condition-case nil
- (line-move (- arg))
- ((beginning-of-buffer end-of-buffer) (ding)))
- (line-move (- arg)))
- nil)
-
-(defvar track-eol nil
- "*Non-nil means vertical motion starting at end of line keeps to ends of lines.
-This means moving to the end of each line moved onto.
-The beginning of a blank line does not count as the end of a line.")
-
-(defvar goal-column nil
- "*Semipermanent goal column for vertical motion, as set by \\[set-goal-column], or nil.")
-(make-variable-buffer-local 'goal-column)
-
-(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.
-When the `track-eol' feature is doing its job, the value is 9999.")
-
-(defvar line-move-ignore-invisible nil
- "*Non-nil means \\[next-line] and \\[previous-line] ignore invisible lines.
-Outline mode sets this.")
-
-;; This is the guts of next-line and previous-line.
-;; Arg says how many lines to move.
-(defun line-move (arg)
- ;; Don't run any point-motion hooks, and disregard intangibility,
- ;; for intermediate positions.
- (let ((inhibit-point-motion-hooks t)
- (opoint (point))
- new)
- (unwind-protect
- (progn
- (if (not (or (eq last-command 'next-line)
- (eq last-command 'previous-line)))
- (setq temporary-goal-column
- (if (and track-eol (eolp)
- ;; Don't count beg of empty line as end of line
- ;; unless we just did explicit end-of-line.
- (or (not (bolp)) (eq last-command 'end-of-line)))
- 9999
- (current-column))))
- (if (and (not (integerp selective-display))
- (not line-move-ignore-invisible))
- ;; Use just newline characters.
- (or (if (> arg 0)
- (progn (if (> arg 1) (forward-line (1- arg)))
- ;; This way of moving forward ARG lines
- ;; verifies that we have a newline after the last one.
- ;; It doesn't get confused by intangible text.
- (end-of-line)
- (zerop (forward-line 1)))
- (and (zerop (forward-line arg))
- (bolp)))
- (signal (if (< arg 0)
- 'beginning-of-buffer
- 'end-of-buffer)
- nil))
- ;; Move by arg lines, but ignore invisible ones.
- (while (> arg 0)
- (end-of-line)
- (and (zerop (vertical-motion 1))
- (signal 'end-of-buffer nil))
- ;; If the following character is currently invisible,
- ;; skip all characters with that same `invisible' property value.
- (while (and (not (eobp))
- (let ((prop
- (get-char-property (point) 'invisible)))
- (if (eq buffer-invisibility-spec t)
- prop
- (or (memq prop buffer-invisibility-spec)
- (assq prop buffer-invisibility-spec)))))
- (if (get-text-property (point) 'invisible)
- (goto-char (next-single-property-change (point) 'invisible))
- (goto-char (next-overlay-change (point)))))
- (setq arg (1- arg)))
- (while (< arg 0)
- (beginning-of-line)
- (and (zerop (vertical-motion -1))
- (signal 'beginning-of-buffer nil))
- (while (and (not (bobp))
- (let ((prop
- (get-char-property (1- (point)) 'invisible)))
- (if (eq buffer-invisibility-spec t)
- prop
- (or (memq prop buffer-invisibility-spec)
- (assq prop buffer-invisibility-spec)))))
- (if (get-text-property (1- (point)) 'invisible)
- (goto-char (previous-single-property-change (point) 'invisible))
- (goto-char (previous-overlay-change (point)))))
- (setq arg (1+ arg))))
- (let ((buffer-invisibility-spec nil))
- (move-to-column (or goal-column temporary-goal-column))))
- ;; Remember where we moved to, go back home,
- ;; then do the motion over again
- ;; in just one step, with intangibility and point-motion hooks
- ;; enabled this time.
- (setq new (point))
- (goto-char opoint)
- (setq inhibit-point-motion-hooks nil)
- (goto-char new)))
- nil)
-
-;;; Many people have said they rarely use this feature, and often type
-;;; it by accident. Maybe it shouldn't even be on a key.
-(put 'set-goal-column 'disabled t)
-
-(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.
-The goal column is stored in the variable `goal-column'."
- (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)
-
-;;; Partial support for horizontal autoscrolling. Someday, this feature
-;;; will be built into the C level and all the (hscroll-point-visible) calls
-;;; will go away.
-
-(defvar hscroll-step 0
- "*The number of columns to try scrolling a window by when point moves out.
-If that fails to bring point back on frame, point is centered instead.
-If this is zero, point is always centered after it moves off frame.")
-
-(defun hscroll-point-visible ()
- "Scrolls the selected window horizontally to make point visible."
- (save-excursion
- (set-buffer (window-buffer))
- (if (not (or truncate-lines
- (> (window-hscroll) 0)
- (and truncate-partial-width-windows
- (< (window-width) (frame-width)))))
- ;; Point is always visible when lines are wrapped.
- ()
- ;; If point is on the invisible part of the line before window-start,
- ;; then hscrolling can't bring it back, so reset window-start first.
- (and (< (point) (window-start))
- (let ((ws-bol (save-excursion
- (goto-char (window-start))
- (beginning-of-line)
- (point))))
- (and (>= (point) ws-bol)
- (set-window-start nil ws-bol))))
- (let* ((here (hscroll-window-column))
- (left (min (window-hscroll) 1))
- (right (1- (window-width))))
- ;; Allow for the truncation glyph, if we're not exactly at eol.
- (if (not (and (= here right)
- (= (following-char) ?\n)))
- (setq right (1- right)))
- (cond
- ;; If too far away, just recenter. But don't show too much
- ;; white space off the end of the line.
- ((or (< here (- left hscroll-step))
- (> here (+ right hscroll-step)))
- (let ((eol (save-excursion (end-of-line) (hscroll-window-column))))
- (scroll-left (min (- here (/ (window-width) 2))
- (- eol (window-width) -5)))))
- ;; Within range. Scroll by one step (or maybe not at all).
- ((< here left)
- (scroll-right hscroll-step))
- ((> here right)
- (scroll-left hscroll-step)))))))
-
-;; This function returns the window's idea of the display column of point,
-;; assuming that the window is already known to be truncated rather than
-;; wrapped, and that we've already handled the case where point is on the
-;; part of the line before window-start. We ignore window-width; if point
-;; is beyond the right margin, we want to know how far. The return value
-;; includes the effects of window-hscroll, window-start, and the prompt
-;; string in the minibuffer. It may be negative due to hscroll.
-(defun hscroll-window-column ()
- (let* ((hscroll (window-hscroll))
- (startpos (save-excursion
- (beginning-of-line)
- (if (= (point) (save-excursion
- (goto-char (window-start))
- (beginning-of-line)
- (point)))
- (goto-char (window-start)))
- (point)))
- (hpos (+ (if (and (eq (selected-window) (minibuffer-window))
- (= 1 (window-start))
- (= startpos (point-min)))
- (minibuffer-prompt-width)
- 0)
- (min 0 (- 1 hscroll))))
- val)
- (car (cdr (compute-motion startpos (cons hpos 0)
- (point) (cons 0 1)
- 1000000 (cons hscroll 0) nil)))))
-
-
-;; rms: (1) The definitions of arrow keys should not simply restate
-;; what keys they are. The arrow keys should run the ordinary commands.
-;; (2) The arrow keys are just one of many common ways of moving point
-;; within a line. Real horizontal autoscrolling would be a good feature,
-;; but supporting it only for arrow keys is too incomplete to be desirable.
-
-;;;;; Make arrow keys do the right thing for improved terminal support
-;;;;; When we implement true horizontal autoscrolling, right-arrow and
-;;;;; left-arrow can lose the (if truncate-lines ...) clause and become
-;;;;; aliases. These functions are bound to the corresponding keyboard
-;;;;; events in loaddefs.el.
-
-;;(defun right-arrow (arg)
-;; "Move right one character on the screen (with prefix ARG, that many chars).
-;;Scroll right if needed to keep point horizontally onscreen."
-;; (interactive "P")
-;; (forward-char arg)
-;; (hscroll-point-visible))
-
-;;(defun left-arrow (arg)
-;; "Move left one character on the screen (with prefix ARG, that many chars).
-;;Scroll left if needed to keep point horizontally onscreen."
-;; (interactive "P")
-;; (backward-char arg)
-;; (hscroll-point-visible))
-
-(defun scroll-other-window-down (lines)
- "Scroll the \"other window\" down.
-For more details, see the documentation for `scroll-other-window'."
- (interactive "P")
- (scroll-other-window
- ;; Just invert the argument's meaning.
- ;; We can do that without knowing which window it will be.
- (if (eq lines '-) nil
- (if (null lines) '-
- (- (prefix-numeric-value lines))))))
-(define-key esc-map [?\C-\S-v] 'scroll-other-window-down)
-
-(defun beginning-of-buffer-other-window (arg)
- "Move point to the beginning of the buffer in the other window.
-Leave mark at previous position.
-With arg N, put point N/10 of the way from the true beginning."
- (interactive "P")
- (let ((orig-window (selected-window))
- (window (other-window-for-scrolling)))
- ;; We use unwind-protect rather than save-window-excursion
- ;; because the latter would preserve the things we want to change.
- (unwind-protect
- (progn
- (select-window window)
- ;; Set point and mark in that window's buffer.
- (beginning-of-buffer arg)
- ;; Set point accordingly.
- (recenter '(t)))
- (select-window orig-window))))
-
-(defun end-of-buffer-other-window (arg)
- "Move point to the end of the buffer in the other window.
-Leave mark at previous position.
-With arg N, put point N/10 of the way from the true end."
- (interactive "P")
- ;; See beginning-of-buffer-other-window for comments.
- (let ((orig-window (selected-window))
- (window (other-window-for-scrolling)))
- (unwind-protect
- (progn
- (select-window window)
- (end-of-buffer arg)
- (recenter '(t)))
- (select-window orig-window))))
-
-(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)))
-
-(defvar comment-column 32
- "*Column to indent right-margin comments to.
-Setting this variable automatically makes it local to the current buffer.
-Each mode establishes a different default value for this variable; you
-can set the value for a particular mode using that mode's hook.")
-(make-variable-buffer-local 'comment-column)
-
-(defvar comment-start nil
- "*String to insert to start a new comment, or nil if no comment syntax.")
-
-(defvar 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.")
-
-(defvar comment-end ""
- "*String to insert to end a new comment.
-Should be an empty string if comments are terminated by end-of-line.")
-
-(defvar comment-indent-hook nil
- "Obsolete variable for function to compute desired indentation for a comment.
-This function is called with no args with point at the beginning of
-the comment's starting delimiter.")
-
-(defvar comment-indent-function
- '(lambda () comment-column)
- "Function to compute desired indentation for a comment.
-This function is called with no args with point at the beginning of
-the comment's starting delimiter.")
-
-(defvar block-comment-start nil
- "*String to insert to start a new comment on a line by itself.
-If nil, use `comment-start' instead.
-Note that the regular expression `comment-start-skip' should skip this string
-as well as the `comment-start' string.")
-
-(defvar block-comment-end nil
- "*String to insert to end a new comment on a line by itself.
-Should be an empty string if comments are terminated by end-of-line.
-If nil, use `comment-end' instead.")
-
-(defun indent-for-comment ()
- "Indent this line's comment to comment column, or insert an empty comment."
- (interactive "*")
- (let* ((empty (save-excursion (beginning-of-line)
- (looking-at "[ \t]*$")))
- (starter (or (and empty block-comment-start) comment-start))
- (ender (or (and empty block-comment-end) comment-end)))
- (if (null starter)
- (error "No comment syntax defined")
- (let* ((eolpos (save-excursion (end-of-line) (point)))
- cpos indent begpos)
- (beginning-of-line)
- (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-syntax-backward " " (match-beginning 0))
- (skip-syntax-backward "^ " (match-beginning 0)))))
- (setq begpos (point))
- ;; Compute desired indent.
- (if (= (current-column)
- (setq indent (if comment-indent-hook
- (funcall comment-indent-hook)
- (funcall comment-indent-function))))
- (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 starter)
- (save-excursion
- (insert ender)))))))
-
-(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."
- ;; this function loses in a lot of situations. it incorrectly recognises
- ;; comment delimiters sometimes (ergo, inside a string), doesn't work
- ;; with multi-line comments, can kill extra whitespace if comment wasn't
- ;; through end-of-line, et cetera.
- (interactive "P")
- (or comment-start-skip (error "No comment syntax defined"))
- (let ((count (prefix-numeric-value arg)) endc)
- (while (> count 0)
- (save-excursion
- (end-of-line)
- (setq endc (point))
- (beginning-of-line)
- (and (string< "" comment-end)
- (setq endc
- (progn
- (re-search-forward (regexp-quote comment-end) endc 'move)
- (skip-chars-forward " \t")
- (point))))
- (beginning-of-line)
- (if (re-search-forward comment-start-skip endc t)
- (progn
- (goto-char (match-beginning 0))
- (skip-chars-backward " \t")
- (kill-region (point) endc)
- ;; to catch comments a line beginnings
- (indent-according-to-mode))))
- (if arg (forward-line 1))
- (setq count (1- count)))))
-
-(defun comment-region (beg end &optional arg)
- "Comment or uncomment each line in the region.
-With just C-u prefix arg, uncomment each line in region.
-Numeric prefix arg ARG means use ARG comment characters.
-If ARG is negative, delete that many comment characters instead.
-Comments are terminated on each line, even for syntax in which newline does
-not end the comment. Blank lines do not get comments."
- ;; if someone wants it to only put a comment-start at the beginning and
- ;; comment-end at the end then typing it, C-x C-x, closing it, C-x C-x
- ;; is easy enough. No option is made here for other than commenting
- ;; every line.
- (interactive "r\nP")
- (or comment-start (error "No comment syntax is defined"))
- (if (> beg end) (let (mid) (setq mid beg beg end end mid)))
- (save-excursion
- (save-restriction
- (let ((cs comment-start) (ce comment-end)
- numarg)
- (if (consp arg) (setq numarg t)
- (setq numarg (prefix-numeric-value arg))
- ;; For positive arg > 1, replicate the comment delims now,
- ;; then insert the replicated strings just once.
- (while (> numarg 1)
- (setq cs (concat cs comment-start)
- ce (concat ce comment-end))
- (setq numarg (1- numarg))))
- ;; Loop over all lines from BEG to END.
- (narrow-to-region beg end)
- (goto-char beg)
- (while (not (eobp))
- (if (or (eq numarg t) (< numarg 0))
- (progn
- ;; Delete comment start from beginning of line.
- (if (eq numarg t)
- (while (looking-at (regexp-quote cs))
- (delete-char (length cs)))
- (let ((count numarg))
- (while (and (> 1 (setq count (1+ count)))
- (looking-at (regexp-quote cs)))
- (delete-char (length cs)))))
- ;; Delete comment end from end of line.
- (if (string= "" ce)
- nil
- (if (eq numarg t)
- (progn
- (end-of-line)
- ;; This is questionable if comment-end ends in
- ;; whitespace. That is pretty brain-damaged,
- ;; though.
- (while (progn (skip-chars-backward " \t")
- (and (>= (- (point) (point-min)) (length ce))
- (save-excursion
- (backward-char (length ce))
- (looking-at (regexp-quote ce)))))
- (delete-char (- (length ce)))))
- (let ((count numarg))
- (while (> 1 (setq count (1+ count)))
- (end-of-line)
- ;; this is questionable if comment-end ends in whitespace
- ;; that is pretty brain-damaged though
- (skip-chars-backward " \t")
- (save-excursion
- (backward-char (length ce))
- (if (looking-at (regexp-quote ce))
- (delete-char (length ce))))))))
- (forward-line 1))
- ;; Insert at beginning and at end.
- (if (looking-at "[ \t]*$") ()
- (insert cs)
- (if (string= "" ce) ()
- (end-of-line)
- (insert ce)))
- (search-forward "\n" nil 'move)))))))
-
-(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))
- nil t))
-
-(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)))
-
-(defun current-word (&optional strict)
- "Return the word point is on (or a nearby word) as a string.
-If optional arg STRICT is non-nil, return nil unless point is within
-or adjacent to a word."
- (save-excursion
- (let ((oldpoint (point)) (start (point)) (end (point)))
- (skip-syntax-backward "w_") (setq start (point))
- (goto-char oldpoint)
- (skip-syntax-forward "w_") (setq end (point))
- (if (and (eq start oldpoint) (eq end oldpoint))
- ;; Point is neither within nor adjacent to a word.
- (and (not strict)
- (progn
- ;; Look for preceding word in same line.
- (skip-syntax-backward "^w_"
- (save-excursion (beginning-of-line)
- (point)))
- (if (bolp)
- ;; No preceding word in same line.
- ;; Look for following word in same line.
- (progn
- (skip-syntax-forward "^w_"
- (save-excursion (end-of-line)
- (point)))
- (setq start (point))
- (skip-syntax-forward "w_")
- (setq end (point)))
- (setq end (point))
- (skip-syntax-backward "w_")
- (setq start (point)))
- (buffer-substring start end)))
- (buffer-substring start end)))))
-
-(defvar 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)
-
-(defvar auto-fill-inhibit-regexp nil
- "*Regexp to match lines which should not be auto-filled.")
-
-;; This function is the auto-fill-function of a buffer
-;; when Auto-Fill mode is enabled.
-;; It returns t if it really did any work.
-(defun do-auto-fill ()
- (let (fc justify bol give-up
- (fill-prefix fill-prefix))
- (if (or (not (setq justify (current-justification)))
- (null (setq fc (current-fill-column)))
- (and (eq justify 'left)
- (<= (current-column) fc))
- (save-excursion (beginning-of-line)
- (setq bol (point))
- (and auto-fill-inhibit-regexp
- (looking-at auto-fill-inhibit-regexp))))
- nil ;; Auto-filling not required
- (if (memq justify '(full center right))
- (save-excursion (unjustify-current-line)))
-
- ;; Choose a fill-prefix automatically.
- (if (and adaptive-fill-mode
- (or (null fill-prefix) (string= fill-prefix "")))
- (let ((prefix
- (fill-context-prefix
- (save-excursion (backward-paragraph 1) (point))
- (save-excursion (forward-paragraph 1) (point))
- ;; Don't accept a non-whitespace fill prefix
- ;; from the first line of a paragraph.
- "^[ \t]*$")))
- (and prefix (not (equal prefix ""))
- (setq fill-prefix prefix))))
-
- (while (and (not give-up) (> (current-column) fc))
- ;; Determine where to split the line.
- (let ((fill-point
- (let ((opoint (point))
- bounce
- (first t)
- after-prefix)
- (save-excursion
- (beginning-of-line)
- (setq after-prefix (point))
- (and fill-prefix
- (looking-at (regexp-quote fill-prefix))
- (setq after-prefix (match-end 0)))
- (move-to-column (1+ fc))
- ;; Move back to a word boundary.
- (while (or first
- ;; If this is after period and a single space,
- ;; move back once more--we don't want to break
- ;; the line there and make it look like a
- ;; sentence end.
- (and (not (bobp))
- (not bounce)
- sentence-end-double-space
- (save-excursion (forward-char -1)
- (and (looking-at "\\. ")
- (not (looking-at "\\. "))))))
- (setq first nil)
- (skip-chars-backward "^ \t\n")
- ;; If we find nowhere on the line to break it,
- ;; break after one word. Set bounce to t
- ;; so we will not keep going in this while loop.
- (if (<= (point) after-prefix)
- (progn
- (re-search-forward "[ \t]" opoint t)
- (setq bounce t)))
- (skip-chars-backward " \t"))
- ;; Let fill-point be set to the place where we end up.
- (point)))))
- ;; If that place is not the beginning of the line,
- ;; break the line there.
- (if (save-excursion
- (goto-char fill-point)
- (not (bolp)))
- (let ((prev-column (current-column)))
- ;; 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 t)
- (save-excursion
- (goto-char fill-point)
- (indent-new-comment-line t)))
- ;; Now do justification, if required
- (if (not (eq justify 'left))
- (save-excursion
- (end-of-line 0)
- (justify-current-line justify nil t)))
- ;; If making the new line didn't reduce the hpos of
- ;; the end of the line, then give up now;
- ;; trying again will not help.
- (if (>= (current-column) prev-column)
- (setq give-up t)))
- ;; No place to break => stop trying.
- (setq give-up t))))
- ;; Justify last line.
- (justify-current-line justify t t)
- t)))
-
-(defvar normal-auto-fill-function 'do-auto-fill
- "The function to use for `auto-fill-function' if Auto Fill mode is turned on.
-Some major modes set this.")
-
-(defun auto-fill-mode (&optional arg)
- "Toggle Auto Fill mode.
-With arg, turn Auto Fill mode on if and only if arg is positive.
-In Auto Fill mode, inserting a space at a column beyond `current-fill-column'
-automatically breaks the line at a previous space.
-
-The value of `normal-auto-fill-function' specifies the function to use
-for `auto-fill-function' when turning Auto Fill mode on."
- (interactive "P")
- (prog1 (setq auto-fill-function
- (if (if (null arg)
- (not auto-fill-function)
- (> (prefix-numeric-value arg) 0))
- normal-auto-fill-function
- nil))
- (force-mode-line-update)))
-
-;; This holds a document string used to document auto-fill-mode.
-(defun auto-fill-function ()
- "Automatically break line at a previous space, in insertion of text."
- nil)
-
-(defun turn-on-auto-fill ()
- "Unconditionally turn on Auto Fill mode."
- (auto-fill-mode 1))
-
-(defun set-fill-column (arg)
- "Set `fill-column' to specified argument.
-Just \\[universal-argument] as argument means to use the current column."
- (interactive "P")
- (cond ((integerp arg)
- (setq fill-column arg))
- ((consp arg)
- (setq fill-column (current-column)))
- ;; Disallow missing argument; it's probably a typo for C-x C-f.
- (t
- (error "set-fill-column requires an explicit argument")))
- (message "fill-column set to %d" fill-column))
-
-(defvar comment-multi-line nil
- "*Non-nil means \\[indent-new-comment-line] should continue same comment
-on new line, with no new terminator or starter.
-This is obsolete because you might as well use \\[newline-and-indent].")
-
-(defun indent-new-comment-line (&optional soft)
- "Break line at point and indent, continuing comment if within one.
-This indents the body of the continued comment
-under the previous comment line.
-
-This command is intended for styles where you write a comment per line,
-starting a new comment (and terminating it if necessary) on each line.
-If you want to continue one comment across several lines, use \\[newline-and-indent].
-
-If a fill column is specified, it overrides the use of the comment column
-or comment indentation.
-
-The inserted newline is marked hard if `use-hard-newlines' is true,
-unless optional argument SOFT is non-nil."
- (interactive)
- (let (comcol comstart)
- (skip-chars-backward " \t")
- (delete-region (point)
- (progn (skip-chars-forward " \t")
- (point)))
- (if soft (insert-and-inherit ?\n) (newline 1))
- (if fill-prefix
- (progn
- (indent-to-left-margin)
- (insert-and-inherit fill-prefix))
- (if (not comment-multi-line)
- (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.
-
- ;; If comment-start-skip contains a \(...\) pair,
- ;; the real comment delimiter starts at the end of that pair.
- (let ((win (or (match-end 1) (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 (or (match-end 1) (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-and-inherit ?\n)
- (forward-char -1)
- (indent-for-comment)
- (save-excursion
- ;; Make sure we delete the newline inserted above.
- (end-of-line)
- (delete-char 1)))
- (indent-according-to-mode)))))
-
-(defun set-selective-display (arg)
- "Set `selective-display' to ARG; clear it if no arg.
-When the value of `selective-display' is a number > 0,
-lines whose indentation is >= that value are not displayed.
-The variable `selective-display' has a separate value for each buffer."
- (interactive "P")
- (if (eq selective-display t)
- (error "selective-display already in use for marked lines"))
- (let ((current-vpos
- (save-restriction
- (narrow-to-region (point-min) (point))
- (goto-char (window-start))
- (vertical-motion (window-height)))))
- (setq selective-display
- (and arg (prefix-numeric-value arg)))
- (recenter current-vpos))
- (set-window-start (selected-window) (window-start (selected-window)))
- (princ "selective-display set to " t)
- (prin1 selective-display t)
- (princ "." t))
-
-(defconst overwrite-mode-textual " Ovwrt"
- "The string displayed in the mode line when in overwrite mode.")
-(defconst overwrite-mode-binary " Bin Ovwrt"
- "The string displayed in the mode line when in binary overwrite mode.")
-
-(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. At the
-end of a line, such characters extend the line. Before a tab,
-such characters insert until the tab is filled in.
-\\[quoted-insert] still inserts characters in overwrite mode; this
-is supposed to make it easier to insert characters when necessary."
- (interactive "P")
- (setq overwrite-mode
- (if (if (null arg) (not overwrite-mode)
- (> (prefix-numeric-value arg) 0))
- 'overwrite-mode-textual))
- (force-mode-line-update))
-
-(defun binary-overwrite-mode (arg)
- "Toggle binary overwrite mode.
-With arg, turn binary overwrite mode on iff arg is positive.
-In binary overwrite mode, printing characters typed in replace
-existing text. Newlines are not treated specially, so typing at the
-end of a line joins the line to the next, with the typed character
-between them. Typing before a tab character simply replaces the tab
-with the character typed.
-\\[quoted-insert] replaces the text at the cursor, just as ordinary
-typing characters do.
-
-Note that binary overwrite mode is not its own minor mode; it is a
-specialization of overwrite-mode, entered by setting the
-`overwrite-mode' variable to `overwrite-mode-binary'."
- (interactive "P")
- (setq overwrite-mode
- (if (if (null arg)
- (not (eq overwrite-mode 'overwrite-mode-binary))
- (> (prefix-numeric-value arg) 0))
- 'overwrite-mode-binary))
- (force-mode-line-update))
-
-(defvar line-number-mode t
- "*Non-nil means display line number in mode line.")
-
-(defun line-number-mode (arg)
- "Toggle Line Number mode.
-With arg, turn Line Number mode on iff arg is positive.
-When Line Number mode is enabled, the line number appears
-in the mode line."
- (interactive "P")
- (setq line-number-mode
- (if (null arg) (not line-number-mode)
- (> (prefix-numeric-value arg) 0)))
- (force-mode-line-update))
-
-(defvar column-number-mode nil
- "*Non-nil means display column number in mode line.")
-
-(defun column-number-mode (arg)
- "Toggle Column Number mode.
-With arg, turn Column Number mode on iff arg is positive.
-When Column Number mode is enabled, the column number appears
-in the mode line."
- (interactive "P")
- (setq column-number-mode
- (if (null arg) (not column-number-mode)
- (> (prefix-numeric-value arg) 0)))
- (force-mode-line-update))
-
-(defvar blink-matching-paren t
- "*Non-nil means show matching open-paren when close-paren is inserted.")
-
-(defvar blink-matching-paren-on-screen t
- "*Non-nil means show matching open-paren when it is on screen.
-nil means don't show it (but the open-paren can still be shown
-when it is off screen.")
-
-(defvar blink-matching-paren-distance 12000
- "*If non-nil, is maximum distance to search for matching open-paren.")
-
-(defvar blink-matching-delay 1
- "*The number of seconds that `blink-matching-open' will delay at a match.")
-
-(defvar blink-matching-paren-dont-ignore-comments nil
- "*Non-nil means `blink-matching-paren' should not ignore comments.")
-
-(defun blink-matching-open ()
- "Move cursor momentarily to the beginning of the sexp before point."
- (interactive)
- (and (> (point) (1+ (point-min)))
- blink-matching-paren
- ;; Verify an even number of quoting characters precede the close.
- (= 1 (logand 1 (- (point)
- (save-excursion
- (forward-char -1)
- (skip-syntax-backward "/\\")
- (point)))))
- (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 ()
- (let ((parse-sexp-ignore-comments
- (and parse-sexp-ignore-comments
- (not blink-matching-paren-dont-ignore-comments))))
- (setq blinkpos (scan-sexps oldpos -1)))
- (error nil)))
- (and blinkpos
- (/= (char-syntax (char-after blinkpos))
- ?\$)
- (setq mismatch
- (or (null (matching-paren (char-after blinkpos)))
- (/= (char-after (1- oldpos))
- (matching-paren (char-after blinkpos))))))
- (if mismatch (setq blinkpos nil))
- (if blinkpos
- (progn
- (goto-char blinkpos)
- (if (pos-visible-in-window-p)
- (and blink-matching-paren-on-screen
- (sit-for blink-matching-delay))
- (goto-char blinkpos)
- (message
- "Matches %s"
- ;; Show what precedes the open in its line, if anything.
- (if (save-excursion
- (skip-chars-backward " \t")
- (not (bolp)))
- (buffer-substring (progn (beginning-of-line) (point))
- (1+ blinkpos))
- ;; Show what follows the open in its line, if anything.
- (if (save-excursion
- (forward-char 1)
- (skip-chars-forward " \t")
- (not (eolp)))
- (buffer-substring blinkpos
- (progn (end-of-line) (point)))
- ;; Otherwise show the previous nonblank line,
- ;; if there is one.
- (if (save-excursion
- (skip-chars-backward "\n \t")
- (not (bobp)))
- (concat
- (buffer-substring (progn
- (skip-chars-backward "\n \t")
- (beginning-of-line)
- (point))
- (progn (end-of-line)
- (skip-chars-backward " \t")
- (point)))
- ;; Replace the newline and other whitespace with `...'.
- "..."
- (buffer-substring blinkpos (1+ blinkpos)))
- ;; There is nothing to show except the char itself.
- (buffer-substring blinkpos (1+ blinkpos))))))))
- (cond (mismatch
- (message "Mismatched parentheses"))
- ((not blink-matching-paren-distance)
- (message "Unmatched parenthesis"))))))))
-
-;Turned off because it makes dbx bomb out.
-(setq blink-paren-function 'blink-matching-open)
-
-;; This executes C-g typed while Emacs is waiting for a command.
-;; Quitting out of a program does not go through here;
-;; that happens in the QUIT macro at the C code level.
-(defun keyboard-quit ()
- "Signal a quit condition.
-During execution of Lisp code, this character causes a quit directly.
-At top-level, as an editor command, this simply beeps."
- (interactive)
- (deactivate-mark)
- (signal 'quit nil))
-
-(define-key global-map "\C-g" 'keyboard-quit)
-
-(defvar buffer-quit-function nil
- "Function to call to \"quit\" the current buffer, or nil if none.
-\\[keyboard-escape-quit] calls this function when its more local actions
-\(such as cancelling a prefix argument, minibuffer or region) do not apply.")
-
-(defun keyboard-escape-quit ()
- "Exit the current \"mode\" (in a generalized sense of the word).
-This command can exit an interactive command such as `query-replace',
-can clear out a prefix argument or a region,
-can get out of the minibuffer or other recursive edit,
-cancel the use of the current buffer (for special-purpose buffers),
-or go back to just one window (by deleting all but the selected window)."
- (interactive)
- (cond ((eq last-command 'mode-exited) nil)
- ((> (minibuffer-depth) 0)
- (abort-recursive-edit))
- (current-prefix-arg
- nil)
- ((and transient-mark-mode
- mark-active)
- (deactivate-mark))
- (buffer-quit-function
- (funcall buffer-quit-function))
- ((not (one-window-p t))
- (delete-other-windows))))
-
-(define-key global-map "\e\e\e" 'keyboard-escape-quit)
-
-(defvar mail-user-agent 'sendmail-user-agent
- "*Your preference for a mail composition package.
-Various Emacs Lisp packages (e.g. reporter) require you to compose an
-outgoing email message. This variable lets you specify which
-mail-sending package you prefer.
-
-Valid values include:
-
- sendmail-user-agent -- use the default Emacs Mail package
- mh-e-user-agent -- use the Emacs interface to the MH mail system
- message-user-agent -- use the GNUS mail sending package
-
-Additional valid symbols may be available; check with the author of
-your package for details.")
-
-(defun define-mail-user-agent (symbol composefunc sendfunc
- &optional abortfunc hookvar)
- "Define a symbol to identify a mail-sending package for `mail-user-agent'.
-
-SYMBOL can be any Lisp symbol. Its function definition and/or
-value as a variable do not matter for this usage; we use only certain
-properties on its property list, to encode the rest of the arguments.
-
-COMPOSEFUNC is program callable function that composes an outgoing
-mail message buffer. This function should set up the basics of the
-buffer without requiring user interaction. It should populate the
-standard mail headers, leaving the `to:' and `subject:' headers blank
-by default.
-
-COMPOSEFUNC should accept several optional arguments--the same
-arguments that `compose-mail' takes. See that function's documentation.
-
-SENDFUNC is the command a user would run to send the message.
-
-Optional ABORTFUNC is the command a user would run to abort the
-message. For mail packages that don't have a separate abort function,
-this can be `kill-buffer' (the equivalent of omitting this argument).
-
-Optional HOOKVAR is a hook variable that gets run before the message
-is actually sent. Callers that use the `mail-user-agent' may
-install a hook function temporarily on this hook variable.
-If HOOKVAR is nil, `mail-send-hook' is used.
-
-The properties used on SYMBOL are `composefunc', `sendfunc',
-`abortfunc', and `hookvar'."
- (put symbol 'composefunc composefunc)
- (put symbol 'sendfunc sendfunc)
- (put symbol 'abortfunc (or abortfunc 'kill-buffer))
- (put symbol 'hookvar (or hookvar 'mail-send-hook)))
-
-(defun assoc-ignore-case (key alist)
- "Like `assoc', but assumes KEY is a string and ignores case when comparing."
- (let (element)
- (while (and alist (not element))
- (if (equal key (downcase (car (car alist))))
- (setq element (car alist)))
- (setq alist (cdr alist)))
- element))
-
-(define-mail-user-agent 'sendmail-user-agent
- '(lambda (&optional to subject other-headers continue
- switch-function yank-action send-actions)
- (if switch-function
- (let ((special-display-buffer-names nil)
- (special-display-regexps nil)
- (same-window-buffer-names nil)
- (same-window-regexps nil))
- (funcall switch-function "*mail*")))
- (let ((cc (cdr (assoc-ignore-case "cc" other-headers)))
- (in-reply-to (cdr (assoc-ignore-case "in-reply-to" other-headers))))
- (or (mail continue to subject in-reply-to cc yank-action send-actions)
- continue
- (error "Message aborted"))))
- 'mail-send-and-exit)
-
-(define-mail-user-agent 'mh-e-user-agent
- 'mh-smail-batch 'mh-send-letter 'mh-fully-kill-draft
- 'mh-before-send-letter-hook)
-
-(defun compose-mail (&optional to subject other-headers continue
- switch-function yank-action send-actions)
- "Start composing a mail message to send.
-This uses the user's chosen mail composition package
-as selected with the variable `mail-user-agent'.
-The optional arguments TO and SUBJECT specify recipients
-and the initial Subject field, respectively.
-
-OTHER-HEADERS is an alist specifying additional
-header fields. Elements look like (HEADER . VALUE) where both
-HEADER and VALUE are strings.
-
-CONTINUE, if non-nil, says to continue editing a message already
-being composed.
-
-SWITCH-FUNCTION, if non-nil, is a function to use to
-switch to and display the buffer used for mail composition.
-
-YANK-ACTION, if non-nil, is an action to perform, if and when necessary,
-to insert the raw text of the message being replied to.
-It has the form (FUNCTION . ARGS). The user agent will apply
-FUNCTION to ARGS, to insert the raw text of the original message.
-\(The user agent will also run `mail-citation-hook', *after* the
-original text has been inserted in this way.)
-
-SEND-ACTIONS is a list of actions to call when the message is sent.
-Each action has the form (FUNCTION . ARGS)."
- (interactive)
- (let ((function (get mail-user-agent 'composefunc)))
- (funcall function to subject other-headers continue
- switch-function yank-action send-actions)))
-
-(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.
-
-If VARIABLE has a `variable-interactive' property, that is used as if
-it were the arg to `interactive' (which see) to interactively read the value."
- (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))))
- (save-excursion
- (set-buffer standard-output)
- (help-mode))
- nil)))))
- (list var
- (let ((prop (get var 'variable-interactive)))
- (if prop
- ;; Use VAR's `variable-interactive' property
- ;; as an interactive spec for prompting.
- (call-interactively (list 'lambda '(arg)
- (list 'interactive prop)
- 'arg))
- (eval-minibuffer (format "Set %s to value: " var)))))))
- (set var val))
-
-;; Define the major mode for lists of completions.
-
-(defvar completion-list-mode-map nil
- "Local map for completion list buffers.")
-(or completion-list-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map [mouse-2] 'mouse-choose-completion)
- (define-key map [down-mouse-2] nil)
- (define-key map "\C-m" 'choose-completion)
- (define-key map "\e\e\e" 'delete-completion-window)
- (define-key map [left] 'previous-completion)
- (define-key map [right] 'next-completion)
- (setq completion-list-mode-map map)))
-
-;; Completion mode is suitable only for specially formatted data.
-(put 'completion-list-mode 'mode-class 'special)
-
-(defvar completion-reference-buffer nil
- "Record the buffer that was current when the completion list was requested.
-This is a local variable in the completion list buffer.
-Initial value is nil to avoid some compiler warnings.")
-
-(defvar completion-base-size nil
- "Number of chars at beginning of minibuffer not involved in completion.
-This is a local variable in the completion list buffer
-but it talks about the buffer in `completion-reference-buffer'.
-If this is nil, it means to compare text to determine which part
-of the tail end of the buffer's text is involved in completion.")
-
-(defun delete-completion-window ()
- "Delete the completion list window.
-Go to the window from which completion was requested."
- (interactive)
- (let ((buf completion-reference-buffer))
- (delete-window (selected-window))
- (if (get-buffer-window buf)
- (select-window (get-buffer-window buf)))))
-
-(defun previous-completion (n)
- "Move to the previous item in the completion list."
- (interactive "p")
- (next-completion (- n)))
-
-(defun next-completion (n)
- "Move to the next item in the completion list.
-With prefix argument N, move N items (negative N means move backward)."
- (interactive "p")
- (while (and (> n 0) (not (eobp)))
- (let ((prop (get-text-property (point) 'mouse-face))
- (end (point-max)))
- ;; If in a completion, move to the end of it.
- (if prop
- (goto-char (next-single-property-change (point) 'mouse-face nil end)))
- ;; Move to start of next one.
- (goto-char (next-single-property-change (point) 'mouse-face nil end)))
- (setq n (1- n)))
- (while (and (< n 0) (not (bobp)))
- (let ((prop (get-text-property (1- (point)) 'mouse-face))
- (end (point-min)))
- ;; If in a completion, move to the start of it.
- (if prop
- (goto-char (previous-single-property-change
- (point) 'mouse-face nil end)))
- ;; Move to end of the previous completion.
- (goto-char (previous-single-property-change (point) 'mouse-face nil end))
- ;; Move to the start of that one.
- (goto-char (previous-single-property-change (point) 'mouse-face nil end)))
- (setq n (1+ n))))
-
-(defun choose-completion ()
- "Choose the completion that point is in or next to."
- (interactive)
- (let (beg end completion (buffer completion-reference-buffer)
- (base-size completion-base-size))
- (if (and (not (eobp)) (get-text-property (point) 'mouse-face))
- (setq end (point) beg (1+ (point))))
- (if (and (not (bobp)) (get-text-property (1- (point)) 'mouse-face))
- (setq end (1- (point)) beg (point)))
- (if (null beg)
- (error "No completion here"))
- (setq beg (previous-single-property-change beg 'mouse-face))
- (setq end (or (next-single-property-change end 'mouse-face) (point-max)))
- (setq completion (buffer-substring beg end))
- (let ((owindow (selected-window)))
- (if (and (one-window-p t 'selected-frame)
- (window-dedicated-p (selected-window)))
- ;; This is a special buffer's frame
- (iconify-frame (selected-frame))
- (or (window-dedicated-p (selected-window))
- (bury-buffer)))
- (select-window owindow))
- (choose-completion-string completion buffer base-size)))
-
-;; Delete the longest partial match for STRING
-;; that can be found before POINT.
-(defun choose-completion-delete-max-match (string)
- (let ((opoint (point))
- (len (min (length string)
- (- (point) (point-min)))))
- (goto-char (- (point) (length string)))
- (if completion-ignore-case
- (setq string (downcase string)))
- (while (and (> len 0)
- (let ((tail (buffer-substring (point)
- (+ (point) len))))
- (if completion-ignore-case
- (setq tail (downcase tail)))
- (not (string= tail (substring string 0 len)))))
- (setq len (1- len))
- (forward-char 1))
- (delete-char len)))
-
-;; Switch to BUFFER and insert the completion choice CHOICE.
-;; BASE-SIZE, if non-nil, says how many characters of BUFFER's text
-;; to keep. If it is nil, use choose-completion-delete-max-match instead.
-
-;; If BUFFER is the minibuffer, exit the minibuffer
-;; unless it is reading a file name and CHOICE is a directory.
-(defun choose-completion-string (choice &optional buffer base-size)
- (let ((buffer (or buffer completion-reference-buffer)))
- ;; If BUFFER is a minibuffer, barf unless it's the currently
- ;; active minibuffer.
- (if (and (string-match "\\` \\*Minibuf-[0-9]+\\*\\'" (buffer-name buffer))
- (or (not (active-minibuffer-window))
- (not (equal buffer
- (window-buffer (active-minibuffer-window))))))
- (error "Minibuffer is not active for completion")
- ;; Insert the completion into the buffer where completion was requested.
- (set-buffer buffer)
- (if base-size
- (delete-region (+ base-size (point-min)) (point))
- (choose-completion-delete-max-match choice))
- (insert choice)
- (remove-text-properties (- (point) (length choice)) (point)
- '(mouse-face nil))
- ;; Update point in the window that BUFFER is showing in.
- (let ((window (get-buffer-window buffer t)))
- (set-window-point window (point)))
- ;; If completing for the minibuffer, exit it with this choice.
- (and (equal buffer (window-buffer (minibuffer-window)))
- minibuffer-completion-table
- ;; If this is reading a file name, and the file name chosen
- ;; is a directory, don't exit the minibuffer.
- (if (and (eq minibuffer-completion-table 'read-file-name-internal)
- (file-directory-p (buffer-string)))
- (select-window (active-minibuffer-window))
- (exit-minibuffer))))))
-
-(defun completion-list-mode ()
- "Major mode for buffers showing lists of possible completions.
-Type \\<completion-list-mode-map>\\[choose-completion] in the completion list\
- to select the completion near point.
-Use \\<completion-list-mode-map>\\[mouse-choose-completion] to select one\
- with the mouse."
- (interactive)
- (kill-all-local-variables)
- (use-local-map completion-list-mode-map)
- (setq mode-name "Completion List")
- (setq major-mode 'completion-list-mode)
- (make-local-variable 'completion-base-size)
- (setq completion-base-size nil)
- (run-hooks 'completion-list-mode-hook))
-
-(defvar completion-fixup-function nil
- "A function to customize how completions are identified in completion lists.
-`completion-setup-function' calls this function with no arguments
-each time it has found what it thinks is one completion.
-Point is at the end of the completion in the completion list buffer.
-If this function moves point, it can alter the end of that completion.")
-
-;; This function goes in completion-setup-hook, so that it is called
-;; after the text of the completion list buffer is written.
-
-(defun completion-setup-function ()
- (save-excursion
- (let ((mainbuf (current-buffer)))
- (set-buffer standard-output)
- (completion-list-mode)
- (make-local-variable 'completion-reference-buffer)
- (setq completion-reference-buffer mainbuf)
-;;; The value 0 is right in most cases, but not for file name completion.
-;;; so this has to be turned off.
-;;; (setq completion-base-size 0)
- (goto-char (point-min))
- (if window-system
- (insert (substitute-command-keys
- "Click \\[mouse-choose-completion] on a completion to select it.\n")))
- (insert (substitute-command-keys
- "In this buffer, type \\[choose-completion] to \
-select the completion near point.\n\n"))
- (forward-line 1)
- (while (re-search-forward "[^ \t\n]+\\( [^ \t\n]+\\)*" nil t)
- (let ((beg (match-beginning 0))
- (end (point)))
- (if completion-fixup-function
- (funcall completion-fixup-function))
- (put-text-property beg (point) 'mouse-face 'highlight)
- (goto-char end))))))
-
-(add-hook 'completion-setup-hook 'completion-setup-function)
-
-(define-key minibuffer-local-completion-map [prior]
- 'switch-to-completions)
-(define-key minibuffer-local-must-match-map [prior]
- 'switch-to-completions)
-(define-key minibuffer-local-completion-map "\M-v"
- 'switch-to-completions)
-(define-key minibuffer-local-must-match-map "\M-v"
- 'switch-to-completions)
-
-(defun switch-to-completions ()
- "Select the completion list window."
- (interactive)
- ;; Make sure we have a completions window.
- (or (get-buffer-window "*Completions*")
- (minibuffer-completion-help))
- (select-window (get-buffer-window "*Completions*"))
- (goto-char (point-min))
- (search-forward "\n\n")
- (forward-line 1))
-
-;; Support keyboard commands to turn on various modifiers.
-
-;; These functions -- which are not commands -- each add one modifier
-;; to the following event.
-
-(defun event-apply-alt-modifier (ignore-prompt)
- (vector (event-apply-modifier (read-event) 'alt 22 "A-")))
-(defun event-apply-super-modifier (ignore-prompt)
- (vector (event-apply-modifier (read-event) 'super 23 "s-")))
-(defun event-apply-hyper-modifier (ignore-prompt)
- (vector (event-apply-modifier (read-event) 'hyper 24 "H-")))
-(defun event-apply-shift-modifier (ignore-prompt)
- (vector (event-apply-modifier (read-event) 'shift 25 "S-")))
-(defun event-apply-control-modifier (ignore-prompt)
- (vector (event-apply-modifier (read-event) 'control 26 "C-")))
-(defun event-apply-meta-modifier (ignore-prompt)
- (vector (event-apply-modifier (read-event) 'meta 27 "M-")))
-
-(defun event-apply-modifier (event symbol lshiftby prefix)
- "Apply a modifier flag to event EVENT.
-SYMBOL is the name of this modifier, as a symbol.
-LSHIFTBY is the numeric value of this modifier, in keyboard events.
-PREFIX is the string that represents this modifier in an event type symbol."
- (if (numberp event)
- (cond ((eq symbol 'control)
- (if (and (<= (downcase event) ?z)
- (>= (downcase event) ?a))
- (- (downcase event) ?a -1)
- (if (and (<= (downcase event) ?Z)
- (>= (downcase event) ?A))
- (- (downcase event) ?A -1)
- (logior (lsh 1 lshiftby) event))))
- ((eq symbol 'shift)
- (if (and (<= (downcase event) ?z)
- (>= (downcase event) ?a))
- (upcase event)
- (logior (lsh 1 lshiftby) event)))
- (t
- (logior (lsh 1 lshiftby) event)))
- (if (memq symbol (event-modifiers event))
- event
- (let ((event-type (if (symbolp event) event (car event))))
- (setq event-type (intern (concat prefix (symbol-name event-type))))
- (if (symbolp event)
- event-type
- (cons event-type (cdr event)))))))
-
-(define-key function-key-map [?\C-x ?@ ?h] 'event-apply-hyper-modifier)
-(define-key function-key-map [?\C-x ?@ ?s] 'event-apply-super-modifier)
-(define-key function-key-map [?\C-x ?@ ?m] 'event-apply-meta-modifier)
-(define-key function-key-map [?\C-x ?@ ?a] 'event-apply-alt-modifier)
-(define-key function-key-map [?\C-x ?@ ?S] 'event-apply-shift-modifier)
-(define-key function-key-map [?\C-x ?@ ?c] 'event-apply-control-modifier)
-
-;;;; Keypad support.
-
-;;; Make the keypad keys act like ordinary typing keys. If people add
-;;; bindings for the function key symbols, then those bindings will
-;;; override these, so this shouldn't interfere with any existing
-;;; bindings.
-
-;; Also tell read-char how to handle these keys.
-(mapcar
- (lambda (keypad-normal)
- (let ((keypad (nth 0 keypad-normal))
- (normal (nth 1 keypad-normal)))
- (put keypad 'ascii-character normal)
- (define-key function-key-map (vector keypad) (vector normal))))
- '((kp-0 ?0) (kp-1 ?1) (kp-2 ?2) (kp-3 ?3) (kp-4 ?4)
- (kp-5 ?5) (kp-6 ?6) (kp-7 ?7) (kp-8 ?8) (kp-9 ?9)
- (kp-space ?\ )
- (kp-tab ?\t)
- (kp-enter ?\r)
- (kp-multiply ?*)
- (kp-add ?+)
- (kp-separator ?,)
- (kp-subtract ?-)
- (kp-decimal ?.)
- (kp-divide ?/)
- (kp-equal ?=)))
-
-;;; simple.el ends here
diff --git a/lisp/skeleton.el b/lisp/skeleton.el
deleted file mode 100644
index a5bacfeb1b0..00000000000
--- a/lisp/skeleton.el
+++ /dev/null
@@ -1,592 +0,0 @@
-;;; skeleton.el --- Lisp language extension for writing statement skeletons
-
-;; Copyright (C) 1993, 1994, 1995, 1996 by Free Software Foundation, Inc.
-
-;; Author: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389
-;; Maintainer: FSF
-;; Keywords: extensions, abbrev, languages, tools
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; A very concise language extension for writing structured statement
-;; skeleton insertion commands for programming language modes. This
-;; originated in shell-script mode and was applied to ada-mode's
-;; commands which shrunk to one third. And these commands are now
-;; user configurable.
-
-;;; Code:
-
-;; page 1: statement skeleton language definition & interpreter
-;; page 2: paired insertion
-;; page 3: mirror-mode, an example for setting up paired insertion
-
-
-(defvar skeleton-transformation nil
- "*If non-nil, function applied to literal strings before they are inserted.
-It should take strings and characters and return them transformed, or nil
-which means no transformation.
-Typical examples might be `upcase' or `capitalize'.")
-
-; this should be a fourth argument to defvar
-(put 'skeleton-transformation 'variable-interactive
- "aTransformation function: ")
-
-
-(defvar skeleton-autowrap t
- "Controls wrapping behaviour of functions created with `define-skeleton'.
-When the region is visible (due to `transient-mark-mode' or marking a region
-with the mouse) and this is non-`nil' and the function was called without an
-explicit ARG, then the ARG defaults to -1, i.e. wrapping around the visible
-region.
-
-We will probably delete this variable in a future Emacs version
-unless we get a substantial number of complaints about the auto-wrap
-feature.")
-
-(defvar skeleton-end-hook
- (lambda ()
- (or (eolp) (newline-and-indent)))
- "Hook called at end of skeleton but before going to point of interest.
-By default this moves out anything following to next line.
-The variables `v1' and `v2' are still set when calling this.")
-
-
-;;;###autoload
-(defvar skeleton-filter 'identity
- "Function for transforming a skeleton proxy's aliases' variable value.")
-
-(defvar skeleton-untabify t
- "When non-`nil' untabifies when deleting backwards with element -ARG.")
-
-(defvar skeleton-newline-indent-rigidly nil
- "When non-`nil', indent rigidly under current line for element `\\n'.
-Else use mode's `indent-line-function'.")
-
-(defvar skeleton-further-elements ()
- "A buffer-local varlist (see `let') of mode specific skeleton elements.
-These variables are bound while interpreting a skeleton. Their value may
-in turn be any valid skeleton element if they are themselves to be used as
-skeleton elements.")
-(make-variable-buffer-local 'skeleton-further-elements)
-
-
-(defvar skeleton-subprompt
- (substitute-command-keys
- "RET, \\<minibuffer-local-map>\\[abort-recursive-edit] or \\[help-command]")
- "*Replacement for %s in prompts of recursive subskeletons.")
-
-
-(defvar skeleton-abbrev-cleanup nil
- "Variable used to delete the character that led to abbrev expansion.")
-
-
-(defvar skeleton-debug nil
- "*If non-nil `define-skeleton' will override previous definition.")
-
-(defvar skeleton-positions nil
- "List of positions marked with @, after skeleton insertion.
-The list describes the most recent skeleton insertion, and its elements
-are integer buffer positions in the reverse order of the insertion order.")
-
-;; reduce the number of compiler warnings
-(defvar skeleton)
-(defvar skeleton-modified)
-(defvar skeleton-point)
-(defvar skeleton-regions)
-
-;;;###autoload
-(defmacro define-skeleton (command documentation &rest skeleton)
- "Define a user-configurable COMMAND that enters a statement skeleton.
-DOCUMENTATION is that of the command, while the variable of the same name,
-which contains the skeleton, has a documentation to that effect.
-INTERACTOR and ELEMENT ... are as defined under `skeleton-insert'."
- (if skeleton-debug
- (set command skeleton))
- `(progn
- (defun ,command (&optional str arg)
- ,(concat documentation
- (if (string-match "\n\\>" documentation)
- "" "\n")
- "\n"
- "This is a skeleton command (see `skeleton-insert').
-Normally the skeleton text is inserted at point, with nothing \"inside\".
-If there is a highlighted region, the skeleton text is wrapped
-around the region text.
-
-A prefix argument ARG says to wrap the skeleton around the next ARG words.
-A prefix argument of zero says to wrap around zero words---that is, nothing.
-This is a way of overiding the use of a highlighted region.")
- (interactive "*P\nP")
- (skeleton-proxy-new ',skeleton str arg))))
-
-;;;###autoload
-(defun skeleton-proxy-new (skeleton &optional str arg)
- "Insert skeleton defined by variable of same name (see `skeleton-insert').
-Prefix ARG allows wrapping around words or regions (see `skeleton-insert').
-If no ARG was given, but the region is visible, ARG defaults to -1 depending
-on `skeleton-autowrap'. An ARG of M-0 will prevent this just for once.
-This command can also be an abbrev expansion (3rd and 4th columns in
-\\[edit-abbrevs] buffer: \"\" command-name).
-
-When called as a function, optional first argument STR may also be a string
-which will be the value of `str' whereas the skeleton's interactor is then
-ignored."
- (interactive "*P\nP")
- (setq skeleton (funcall skeleton-filter skeleton))
- (if (not skeleton)
- (if (memq this-command '(self-insert-command
- skeleton-pair-insert-maybe
- expand-abbrev))
- (setq buffer-undo-list (primitive-undo 1 buffer-undo-list)))
- (skeleton-insert skeleton
- (if (setq skeleton-abbrev-cleanup
- (or (eq this-command 'self-insert-command)
- (eq this-command
- 'skeleton-pair-insert-maybe)))
- ()
- ;; Pretend C-x a e passed its prefix arg to us
- (if (or arg current-prefix-arg)
- (prefix-numeric-value (or arg
- current-prefix-arg))
- (and skeleton-autowrap
- (or (eq last-command 'mouse-drag-region)
- (and transient-mark-mode mark-active))
- -1)))
- (if (stringp str)
- str))
- (and skeleton-abbrev-cleanup
- (setq skeleton-abbrev-cleanup (point))
- (add-hook 'post-command-hook 'skeleton-abbrev-cleanup nil t))))
-
-;; This command isn't meant to be called, only its aliases with meaningful
-;; names are.
-;;;###autoload
-(defun skeleton-proxy (&optional str arg)
- "Insert skeleton defined by variable of same name (see `skeleton-insert').
-Prefix ARG allows wrapping around words or regions (see `skeleton-insert').
-If no ARG was given, but the region is visible, ARG defaults to -1 depending
-on `skeleton-autowrap'. An ARG of M-0 will prevent this just for once.
-This command can also be an abbrev expansion (3rd and 4th columns in
-\\[edit-abbrevs] buffer: \"\" command-name).
-
-When called as a function, optional first argument STR may also be a string
-which will be the value of `str' whereas the skeleton's interactor is then
-ignored."
- (interactive "*P\nP")
- (let ((function (nth 1 (backtrace-frame 1))))
- (if (eq function 'nth) ; uncompiled Lisp function
- (setq function (nth 1 (backtrace-frame 5)))
- (if (eq function 'byte-code) ; tracing byte-compiled function
- (setq function (nth 1 (backtrace-frame 2)))))
- (if (not (setq function (funcall skeleton-filter (symbol-value function))))
- (if (memq this-command '(self-insert-command
- skeleton-pair-insert-maybe
- expand-abbrev))
- (setq buffer-undo-list (primitive-undo 1 buffer-undo-list)))
- (skeleton-insert function
- (if (setq skeleton-abbrev-cleanup
- (or (eq this-command 'self-insert-command)
- (eq this-command
- 'skeleton-pair-insert-maybe)))
- ()
- ;; Pretend C-x a e passed its prefix arg to us
- (if (or arg current-prefix-arg)
- (prefix-numeric-value (or arg
- current-prefix-arg))
- (and skeleton-autowrap
- (or (eq last-command 'mouse-drag-region)
- (and transient-mark-mode mark-active))
- -1)))
- (if (stringp str)
- str))
- (and skeleton-abbrev-cleanup
- (setq skeleton-abbrev-cleanup (point))
- (add-hook 'post-command-hook 'skeleton-abbrev-cleanup nil t)))))
-
-
-(defun skeleton-abbrev-cleanup (&rest list)
- "Value for `post-command-hook' to remove char that expanded abbrev."
- (if (integerp skeleton-abbrev-cleanup)
- (progn
- (delete-region skeleton-abbrev-cleanup (point))
- (setq skeleton-abbrev-cleanup)
- (remove-hook 'post-command-hook 'skeleton-abbrev-cleanup t))))
-
-
-;;;###autoload
-(defun skeleton-insert (skeleton &optional skeleton-regions str)
- "Insert the complex statement skeleton SKELETON describes very concisely.
-
-With optional third REGIONS wrap first interesting point (`_') in skeleton
-around next REGIONS words, if REGIONS is positive. If REGIONS is negative,
-wrap REGIONS preceding interregions into first REGIONS interesting positions
-\(successive `_'s) in skeleton. An interregion is the stretch of text between
-two contiguous marked points. If you marked A B C [] (where [] is the cursor)
-in alphabetical order, the 3 interregions are simply the last 3 regions. But
-if you marked B A [] C, the interregions are B-A, A-[], []-C.
-
-Optional fourth STR is the value for the variable `str' within the skeleton.
-When this is non-`nil' the interactor gets ignored, and this should be a valid
-skeleton element.
-
-SKELETON is made up as (INTERACTOR ELEMENT ...). INTERACTOR may be nil if
-not needed, a prompt-string or an expression for complex read functions.
-
-If ELEMENT is a string or a character it gets inserted (see also
-`skeleton-transformation'). Other possibilities are:
-
- \\n go to next line and indent according to mode
- _ interesting point, interregion here, point after termination
- > indent line (or interregion if > _) according to major mode
- @ add position to `skeleton-positions'
- & do next ELEMENT if previous moved point
- | do next ELEMENT if previous didn't move point
- -num delete num preceding characters (see `skeleton-untabify')
- resume: skipped, continue here if quit is signaled
- nil skipped
-
-Further elements can be defined via `skeleton-further-elements'. ELEMENT may
-itself be a SKELETON with an INTERACTOR. The user is prompted repeatedly for
-different inputs. The SKELETON is processed as often as the user enters a
-non-empty string. \\[keyboard-quit] terminates skeleton insertion, but
-continues after `resume:' and positions at `_' if any. If INTERACTOR in such
-a subskeleton is a prompt-string which contains a \".. %s ..\" it is
-formatted with `skeleton-subprompt'. Such an INTERACTOR may also a list of
-strings with the subskeleton being repeated once for each string.
-
-Quoted Lisp expressions are evaluated evaluated for their side-effect.
-Other Lisp expressions are evaluated and the value treated as above.
-Note that expressions may not return `t' since this implies an
-endless loop. Modes can define other symbols by locally setting them
-to any valid skeleton element. The following local variables are
-available:
-
- str first time: read a string according to INTERACTOR
- then: insert previously read string once more
- help help-form during interaction with the user or `nil'
- input initial input (string or cons with index) while reading str
- v1, v2 local variables for memorizing anything you want
-
-When done with skeleton, but before going back to `_'-point call
-`skeleton-end-hook' if that is non-`nil'."
- (and skeleton-regions
- (setq skeleton-regions
- (if (> skeleton-regions 0)
- (list (point-marker)
- (save-excursion (forward-word skeleton-regions)
- (point-marker)))
- (setq skeleton-regions (- skeleton-regions))
- ;; copy skeleton-regions - 1 elements from `mark-ring'
- (let ((l1 (cons (mark-marker) mark-ring))
- (l2 (list (point-marker))))
- (while (and l1 (> skeleton-regions 0))
- (setq l2 (cons (car l1) l2)
- skeleton-regions (1- skeleton-regions)
- l1 (cdr l1)))
- (sort l2 '<))))
- (goto-char (car skeleton-regions))
- (setq skeleton-regions (cdr skeleton-regions)))
- (let ((beg (point))
- skeleton-modified skeleton-point resume: help input v1 v2)
- (setq skeleton-positions nil)
- (unwind-protect
- (eval `(let ,skeleton-further-elements
- (skeleton-internal-list skeleton str)))
- (run-hooks 'skeleton-end-hook)
- (sit-for 0)
- (or (pos-visible-in-window-p beg)
- (progn
- (goto-char beg)
- (recenter 0)))
- (if skeleton-point
- (goto-char skeleton-point)))))
-
-(defun skeleton-read (str &optional initial-input recursive)
- "Function for reading a string from the minibuffer within skeletons.
-PROMPT may contain a `%s' which will be replaced by `skeleton-subprompt'.
-If non-`nil' second arg INITIAL-INPUT or variable `input' is a string or
-cons with index to insert before reading. If third arg RECURSIVE is non-`nil'
-i.e. we are handling the iterator of a subskeleton, returns empty string if
-user didn't modify input.
-While reading, the value of `minibuffer-help-form' is variable `help' if that
-is non-`nil' or a default string."
- (let ((minibuffer-help-form (or (if (boundp 'help) (symbol-value 'help))
- (if recursive "\
-As long as you provide input you will insert another subskeleton.
-
-If you enter the empty string, the loop inserting subskeletons is
-left, and the current one is removed as far as it has been entered.
-
-If you quit, the current subskeleton is removed as far as it has been
-entered. No more of the skeleton will be inserted, except maybe for a
-syntactically necessary termination."
- "\
-You are inserting a skeleton. Standard text gets inserted into the buffer
-automatically, and you are prompted to fill in the variable parts.")))
- (eolp (eolp)))
- ;; since Emacs doesn't show main window's cursor, do something noticeable
- (or eolp
- (open-line 1))
- (unwind-protect
- (setq str (if (stringp str)
- (read-string (format str skeleton-subprompt)
- (setq initial-input
- (or initial-input
- (symbol-value 'input))))
- (eval str)))
- (or eolp
- (delete-char 1))))
- (if (and recursive
- (or (null str)
- (string= str "")
- (equal str initial-input)
- (equal str (car-safe initial-input))))
- (signal 'quit t)
- str))
-
-(defun skeleton-internal-list (skeleton &optional str recursive)
- (let* ((start (save-excursion (beginning-of-line) (point)))
- (column (current-column))
- (line (buffer-substring start
- (save-excursion (end-of-line) (point))))
- opoint)
- (or str
- (setq str `(setq str (skeleton-read ',(car skeleton) nil ,recursive))))
- (while (setq skeleton-modified (eq opoint (point))
- opoint (point)
- skeleton (cdr skeleton))
- (condition-case quit
- (skeleton-internal-1 (car skeleton))
- (quit
- (if (eq (cdr quit) 'recursive)
- (setq recursive 'quit
- skeleton (memq 'resume: skeleton))
- ;; remove the subskeleton as far as it has been shown
- ;; the subskeleton shouldn't have deleted outside current line
- (end-of-line)
- (delete-region start (point))
- (insert line)
- (move-to-column column)
- (if (cdr quit)
- (setq skeleton ()
- recursive nil)
- (signal 'quit 'recursive)))))))
- ;; maybe continue loop or go on to next outer resume: section
- (if (eq recursive 'quit)
- (signal 'quit 'recursive)
- recursive))
-
-
-(defun skeleton-internal-1 (element &optional literal)
- (cond ((char-or-string-p element)
- (if (and (integerp element) ; -num
- (< element 0))
- (if skeleton-untabify
- (backward-delete-char-untabify (- element))
- (delete-backward-char (- element)))
- (insert-before-markers (if (and skeleton-transformation
- (not literal))
- (funcall skeleton-transformation element)
- element))))
- ((eq element '\n) ; actually (eq '\n 'n)
- (if (and skeleton-regions
- (eq (nth 1 skeleton) '_))
- (progn
- (or (eolp)
- (newline))
- (indent-region (point) (car skeleton-regions) nil))
- (if skeleton-newline-indent-rigidly
- (indent-to (prog1 (current-indentation)
- (newline)))
- (newline)
- (indent-according-to-mode))))
- ((eq element '>)
- (if (and skeleton-regions
- (eq (nth 1 skeleton) '_))
- (indent-region (point) (car skeleton-regions) nil)
- (indent-according-to-mode)))
- ((eq element '_)
- (if skeleton-regions
- (progn
- (goto-char (car skeleton-regions))
- (setq skeleton-regions (cdr skeleton-regions))
- (and (<= (current-column) (current-indentation))
- (eq (nth 1 skeleton) '\n)
- (end-of-line 0)))
- (or skeleton-point
- (setq skeleton-point (point)))))
- ((eq element '&)
- (if skeleton-modified
- (setq skeleton (cdr skeleton))))
- ((eq element '|)
- (or skeleton-modified
- (setq skeleton (cdr skeleton))))
- ((eq element '@)
- (setq skeleton-positions (cons (point) skeleton-positions)))
- ((eq 'quote (car-safe element))
- (eval (nth 1 element)))
- ((or (stringp (car-safe element))
- (consp (car-safe element)))
- (if (symbolp (car-safe (car element)))
- (while (skeleton-internal-list element nil t))
- (setq literal (car element))
- (while literal
- (skeleton-internal-list element (car literal))
- (setq literal (cdr literal)))))
- ((null element))
- ((skeleton-internal-1 (eval element) t))))
-
-
-;; Maybe belongs into simple.el or elsewhere
-;; ;###autoload
-;;; (define-skeleton local-variables-section
-;; "Insert a local variables section. Use current comment syntax if any."
-;; (completing-read "Mode: " obarray
-;; (lambda (symbol)
-;; (if (commandp symbol)
-;; (string-match "-mode$" (symbol-name symbol))))
-;; t)
-;; '(save-excursion
-;; (if (re-search-forward page-delimiter nil t)
-;; (error "Not on last page.")))
-;; comment-start "Local Variables:" comment-end \n
-;; comment-start "mode: " str
-;; & -5 | '(kill-line 0) & -1 | comment-end \n
-;; ( (completing-read (format "Variable, %s: " skeleton-subprompt)
-;; obarray
-;; (lambda (symbol)
-;; (or (eq symbol 'eval)
-;; (user-variable-p symbol)))
-;; t)
-;; comment-start str ": "
-;; (read-from-minibuffer "Expression: " nil read-expression-map nil
-;; 'read-expression-history) | _
-;; comment-end \n)
-;; resume:
-;; comment-start "End:" comment-end \n)
-
-;; Variables and command for automatically inserting pairs like () or "".
-
-(defvar skeleton-pair nil
- "*If this is nil pairing is turned off, no matter what else is set.
-Otherwise modes with `skeleton-pair-insert-maybe' on some keys
-will attempt to insert pairs of matching characters.")
-
-
-(defvar skeleton-pair-on-word nil
- "*If this is nil, paired insertion is inhibited before or inside a word.")
-
-
-(defvar skeleton-pair-filter (lambda ())
- "Attempt paired insertion if this function returns nil, before inserting.
-This allows for context-sensitive checking whether pairing is appropriate.")
-
-
-(defvar skeleton-pair-alist ()
- "An override alist of pairing partners matched against `last-command-char'.
-Each alist element, which looks like (ELEMENT ...), is passed to
-`skeleton-insert' with no interactor. Variable `str' does nothing.
-
-Elements might be (?` ?` _ \"''\"), (?\\( ? _ \" )\") or (?{ \\n > _ \\n ?} >).")
-
-
-;;;###autoload
-(defun skeleton-pair-insert-maybe (arg)
- "Insert the character you type ARG times.
-
-With no ARG, if `skeleton-pair' is non-nil, pairing can occur. If the region
-is visible the pair is wrapped around it depending on `skeleton-autowrap'.
-Else, if `skeleton-pair-on-word' is non-nil or we are not before or inside a
-word, and if `skeleton-pair-filter' returns nil, pairing is performed.
-
-If a match is found in `skeleton-pair-alist', that is inserted, else
-the defaults are used. These are (), [], {}, <> and `' for the
-symmetrical ones, and the same character twice for the others."
- (interactive "*P")
- (let ((mark (and skeleton-autowrap
- (or (eq last-command 'mouse-drag-region)
- (and transient-mark-mode mark-active))))
- (skeleton-end-hook))
- (if (or arg
- (not skeleton-pair)
- (and (not mark)
- (or overwrite-mode
- (if (not skeleton-pair-on-word) (looking-at "\\w"))
- (funcall skeleton-pair-filter))))
- (self-insert-command (prefix-numeric-value arg))
- (setq last-command-char (logand last-command-char 255))
- (or skeleton-abbrev-cleanup
- (skeleton-insert
- (cons nil (or (assq last-command-char skeleton-pair-alist)
- (assq last-command-char '((?( _ ?))
- (?[ _ ?])
- (?{ _ ?})
- (?< _ ?>)
- (?` _ ?')))
- `(,last-command-char _ ,last-command-char)))
- (if mark -1))))))
-
-
-;; A more serious example can be found in sh-script.el
-;;; (defun mirror-mode ()
-;; "This major mode is an amusing little example of paired insertion.
-;;All printable characters do a paired self insert, while the other commands
-;;work normally."
-;; (interactive)
-;; (kill-all-local-variables)
-;; (make-local-variable 'skeleton-pair)
-;; (make-local-variable 'skeleton-pair-on-word)
-;; (make-local-variable 'skeleton-pair-filter)
-;; (make-local-variable 'skeleton-pair-alist)
-;; (setq major-mode 'mirror-mode
-;; mode-name "Mirror"
-;; skeleton-pair-on-word t
-;; ;; in the middle column insert one or none if odd window-width
-;; skeleton-pair-filter (lambda ()
-;; (if (>= (current-column)
-;; (/ (window-width) 2))
-;; ;; insert both on next line
-;; (next-line 1)
-;; ;; insert one or both?
-;; (= (* 2 (1+ (current-column)))
-;; (window-width))))
-;; ;; mirror these the other way round as well
-;; skeleton-pair-alist '((?) _ ?()
-;; (?] _ ?[)
-;; (?} _ ?{)
-;; (?> _ ?<)
-;; (?/ _ ?\\)
-;; (?\\ _ ?/)
-;; (?` ?` _ "''")
-;; (?' ?' _ "``"))
-;; ;; in this mode we exceptionally ignore the user, else it's no fun
-;; skeleton-pair t)
-;; (let ((map (make-vector 256 'skeleton-pair-insert-maybe))
-;; (i 0))
-;; (use-local-map `(keymap ,map))
-;; (while (< i ? )
-;; (aset map i nil)
-;; (aset map (+ i 128) nil)
-;; (setq i (1+ i))))
-;; (run-hooks 'mirror-mode-hook))
-
-(provide 'skeleton)
-
-;; skeleton.el ends here
diff --git a/lisp/sort.el b/lisp/sort.el
deleted file mode 100644
index fcd8906b1f0..00000000000
--- a/lisp/sort.el
+++ /dev/null
@@ -1,523 +0,0 @@
-;;; sort.el --- commands to sort text in an Emacs buffer.
-
-;; Copyright (C) 1986, 1987, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Howie Kaye
-;; Maintainer: FSF
-;; Keywords: unix
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides the sorting facilities documented in the Emacs
-;; user's manual.
-
-;;; Code:
-
-(defvar sort-fold-case nil
- "*Non-nil if the buffer sort functions should ignore case.")
-
-;;;###autoload
-(defun sort-subr (reverse nextrecfun endrecfun &optional startkeyfun endkeyfun)
- "General text sorting routine to divide buffer into records and sort them.
-Arguments are REVERSE NEXTRECFUN ENDRECFUN &optional STARTKEYFUN ENDKEYFUN.
-
-We divide the accessible portion of the buffer into disjoint pieces
-called sort records. A portion of each sort record (perhaps all of
-it) is designated as the sort key. The records are rearranged in the
-buffer in order by their sort keys. The records may or may not be
-contiguous.
-
-Usually the records are rearranged in order of ascending sort key.
-If REVERSE is non-nil, they are rearranged in order of descending sort key.
-The variable `sort-fold-case' determines whether alphabetic case affects
-the sort order.
-
-The next four arguments are functions to be called to move point
-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.
-
-ENDRECFUN is called with point within the record.
-It should move point to the end of the record.
-
-STARTKEYFUN moves from the start of the record to the start of the key.
-It may return either a non-nil value to be used as the key, or
-else the key is the substring between the values of point after
-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
-same as ENDRECFUN."
- ;; Heuristically try to avoid messages if sorting a small amt of text.
- (let ((messages (> (- (point-max) (point-min)) 50000)))
- (save-excursion
- (if messages (message "Finding sort keys..."))
- (let* ((sort-lists (sort-build-lists nextrecfun endrecfun
- startkeyfun endkeyfun))
- (old (reverse sort-lists))
- (case-fold-search sort-fold-case))
- (if (null sort-lists)
- ()
- (or reverse (setq sort-lists (nreverse sort-lists)))
- (if messages (message "Sorting records..."))
- (setq sort-lists
- (if (fboundp 'sortcar)
- (sortcar sort-lists
- (cond ((numberp (car (car sort-lists)))
- ;; This handles both ints and floats.
- '<)
- ((consp (car (car sort-lists)))
- (function
- (lambda (a b)
- (> 0 (compare-buffer-substrings
- nil (car a) (cdr a)
- nil (car b) (cdr b))))))
- (t
- 'string<)))
- (sort sort-lists
- (cond ((numberp (car (car sort-lists)))
- 'car-less-than-car)
- ((consp (car (car sort-lists)))
- (function
- (lambda (a b)
- (> 0 (compare-buffer-substrings
- nil (car (car a)) (cdr (car a))
- nil (car (car b)) (cdr (car b)))))))
- (t
- (function
- (lambda (a b)
- (string< (car a) (car b)))))))))
- (if reverse (setq sort-lists (nreverse sort-lists)))
- (if messages (message "Reordering buffer..."))
- (sort-reorder-buffer sort-lists old)))
- (if messages (message "Reordering buffer... Done"))))
- nil)
-
-;; Parse buffer into records using the arguments as Lisp expressions;
-;; 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.
-
-;; The records appear in the list lastmost first!
-
-(defun sort-build-lists (nextrecfun endrecfun startkeyfun endkeyfun)
- (let ((sort-lists ())
- (start-rec nil)
- done key)
- ;; Loop over sort records.
- ;(goto-char (point-min)) -- it is the caller's responsibility to
- ;arrange this if necessary
- (while (not (eobp))
- (setq start-rec (point)) ;save record start
- (setq done nil)
- ;; Get key value, or move to start of key.
- (setq key (catch 'key
- (or (and startkeyfun (funcall startkeyfun))
- ;; If key was not returned as value,
- ;; move to end of key and get key from the buffer.
- (let ((start (point)))
- (funcall (or endkeyfun
- (prog1 endrecfun (setq done t))))
- (cons start (point))))))
- ;; Move to end of this record (start of next one, or end of buffer).
- (cond ((prog1 done (setq done nil)))
- (endrecfun (funcall endrecfun))
- (nextrecfun (funcall nextrecfun) (setq done t)))
- (if key (setq sort-lists (cons
- ;; consing optimization in case in which key
- ;; is same as record.
- (if (and (consp key)
- (equal (car key) start-rec)
- (equal (cdr key) (point)))
- (cons key key)
- (cons key (cons start-rec (point))))
- sort-lists)))
- (and (not done) nextrecfun (funcall nextrecfun)))
- sort-lists))
-
-(defun sort-reorder-buffer (sort-lists old)
- (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)
- last
- (nth 1 (car old)))
- (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)))
- 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)))))
-
-;;;###autoload
-(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).
-The variable `sort-fold-case' determines whether alphabetic case affects
-the sort order."
- (interactive "P\nr")
- (save-excursion
- (save-restriction
- (narrow-to-region beg end)
- (goto-char (point-min))
- (sort-subr reverse 'forward-line 'end-of-line))))
-
-;;;###autoload
-(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).
-The variable `sort-fold-case' determines whether alphabetic case affects
-the sort order."
- (interactive "P\nr")
- (save-excursion
- (save-restriction
- (narrow-to-region beg end)
- (goto-char (point-min))
- (sort-subr reverse
- (function
- (lambda ()
- (while (and (not (eobp)) (looking-at paragraph-separate))
- (forward-line 1))))
- 'forward-paragraph))))
-
-;;;###autoload
-(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).
-The variable `sort-fold-case' determines whether alphabetic case affects
-the sort order."
- (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))))
-
-(defvar sort-fields-syntax-table nil)
-(if sort-fields-syntax-table nil
- (let ((table (make-syntax-table))
- (i 0))
- (while (< i 256)
- (modify-syntax-entry i "w" table)
- (setq i (1+ i)))
- (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)))
-
-;;;###autoload
-(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.
-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 field)
- (string-to-number
- (buffer-substring
- (point)
- (save-excursion
- ;; This is just wrong! Even without floats...
- ;; (skip-chars-forward "[0-9]")
- (forward-sexp 1)
- (point))))))
- nil))
-
-;;;;;###autoload
-;;(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 field)
-;; (string-to-number
-;; (buffer-substring
-;; (point)
-;; (save-excursion
-;; (re-search-forward
-;; "[+-]?[0-9]*\.?[0-9]*\\([eE][+-]?[0-9]+\\)?")
-;; (point))))))
-;; nil))
-
-;;;###autoload
-(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.
-Called from a program, there are three arguments:
-FIELD, BEG and END. BEG and END specify region to sort.
-The variable `sort-fold-case' determines whether alphabetic case affects
-the sort order."
- (interactive "p\nr")
- (sort-fields-1 field beg end
- (function (lambda ()
- (sort-skip-fields field)
- nil))
- (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))
- (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)))
- (set-syntax-table tbl))))
-
-;; Position at the beginning of field N on the current line,
-;; assuming point is initially at the beginning of the line.
-(defun sort-skip-fields (n)
- (if (> n 0)
- ;; Skip across N - 1 fields.
- (let ((i (1- n)))
- (while (> i 0)
- (skip-chars-forward " \t")
- (skip-chars-forward "^ \t\n")
- (setq i (1- i)))
- (skip-chars-forward " \t")
- (if (eolp)
- (error "Line has too few fields: %s"
- (buffer-substring
- (save-excursion (beginning-of-line) (point))
- (save-excursion (end-of-line) (point))))))
- (end-of-line)
- ;; Skip back across - N - 1 fields.
- (let ((i (1- (- n))))
- (while (> i 0)
- (skip-chars-backward " \t")
- (skip-chars-backward "^ \t\n")
- (setq i (1- i)))
- (skip-chars-backward " \t"))
- (if (bolp)
- (error "Line has too few fields: %s"
- (buffer-substring
- (save-excursion (beginning-of-line) (point))
- (save-excursion (end-of-line) (point)))))
- ;; Position at the front of the field
- ;; even if moving backwards.
- (skip-chars-backward "^ \t\n")))
-
-(defvar sort-regexp-fields-regexp)
-(defvar sort-regexp-record-end)
-
-;; Move to the beginning of the next match for record-regexp,
-;; and set sort-regexp-record-end to the end of that match.
-;; If the next match is empty and does not advance point,
-;; skip one character and try again.
-(defun sort-regexp-fields-next-record ()
- (let ((oldpos (point)))
- (and (re-search-forward sort-regexp-fields-regexp nil 'move)
- (setq sort-regexp-record-end (match-end 0))
- (if (= sort-regexp-record-end oldpos)
- (progn
- (forward-char 1)
- (re-search-forward sort-regexp-fields-regexp nil 'move)
- (setq sort-regexp-record-end (match-end 0)))
- t)
- (goto-char (match-beginning 0)))))
-
-;;;###autoload
-(defun sort-regexp-fields (reverse record-regexp key-regexp beg end)
- "Sort the region lexicographically as specified 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.
-
-The variable `sort-fold-case' determines whether alphabetic case affects
-the sort 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.
- (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
- (sort-regexp-fields-regexp record-regexp))
- (re-search-forward sort-regexp-fields-regexp)
- (setq sort-regexp-record-end (point))
- (goto-char (match-beginning 0))
- (sort-subr reverse
- 'sort-regexp-fields-next-record
- (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 ()
- (cons (match-beginning n)
- (match-end n))
- ;; if there was no such register
- (error (throw 'key nil)))))))))))
-
-
-(defvar sort-columns-subprocess t)
-
-;;;###autoload
-(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
-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.
-The variable `sort-fold-case' determines whether alphabetic case affects
-the sort 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."
- (interactive "P\nr")
- (save-excursion
- (let (beg1 end1 col-beg1 col-end1 col-start col-end)
- (goto-char (min beg end))
- (setq col-beg1 (current-column))
- (beginning-of-line)
- (setq beg1 (point))
- (goto-char (max beg end))
- (setq col-end1 (current-column))
- (forward-line)
- (setq end1 (point))
- (setq col-start (min col-beg1 col-end1))
- (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 (or (eq system-type 'vax-vms)
- (text-properties-at beg1)
- (< (next-property-change beg1 nil end1) end1)))
- ;; Use the sort utility if we can; it is 4 times as fast.
- ;; Do not use it if there are any properties in the region,
- ;; since the sort utility would lose the properties.
- (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)))))))))
-
-;;;###autoload
-(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)))))
-
-(provide 'sort)
-
-;;; sort.el ends here
diff --git a/lisp/soundex.el b/lisp/soundex.el
deleted file mode 100644
index 5f703228df2..00000000000
--- a/lisp/soundex.el
+++ /dev/null
@@ -1,74 +0,0 @@
-;;; soundex.el --- implement Soundex algorithm
-
-;; Copyright (C) 1993 Free Software Foundation, Inc.
-
-;; Author: Christian Plaunt <chris@bliss.berkeley.edu>
-;; Maintainer: FSF
-;; Keywords: matching
-;; Created: Sat May 15 14:48:18 1993
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The Soundex algorithm maps English words into representations of
-;; how they sound. Words with vaguely similar sound map to the same string.
-
-;;; Code:
-
-(defvar soundex-alist
- '((?B . "1") (?F . "1") (?P . "1") (?V . "1")
- (?C . "2") (?G . "2") (?J . "2") (?K . "2") (?Q . "2") (?S . "2")
- (?X . "2") (?Z . "2") (?D . "3") (?T . "3") (?L . "4") (?M . "5")
- (?N . "5") (?R . "6"))
- "Alist of chars-to-key-code for building Soundex keys.")
-
-(defun soundex (word)
- "Return a Soundex key for WORD.
-Implemented as described in:
-Knuth, Donald E. \"The Art of Computer Programming, Vol. 3: Sorting
-and Searching\", Addison-Wesley (1973), pp. 391-392."
- (let* ((word (upcase word)) (length (length word))
- (code (cdr (assq (aref word 0) soundex-alist)))
- (key (substring word 0 1)) (index 1) (prev-code code))
- ;; once we have a four char key, we're done
- (while (and (> 4 (length key)) (< index length))
- ;; look up the code for each letter in word at index
- (setq code (cdr (assq (aref word index) soundex-alist))
- index (1+ index)
- ;; append code to key unless the same codes belong to
- ;; adjacent letters in the original string
- key (concat key (if (or (null code) (string= code prev-code))
- ()
- code))
- prev-code code))
- ;; return a key that is 4 chars long and padded by "0"s if needed
- (if (> 4 (length key))
- (substring (concat key "000") 0 4)
- key)))
-
-;(defvar soundex-test
-; '("Euler" "Gauss" "Hilbert" "Knuth" "Lloyd" "Lukasiewicz"
-; "Ellery" "Ghosh" "Heilbronn" "Kant" "Ladd" "Lissajous")
-; "\n Knuth's names to demonstrate the Soundex algorithm.")
-;
-;(mapcar 'soundex soundex-test)
-;("E460" "G200" "H416" "K530" "L300" "L222"
-; "E460" "G200" "H416" "K530" "L300" "L222")
-
-;; soundex.el ends here
diff --git a/lisp/startup.el b/lisp/startup.el
deleted file mode 100644
index 68f857cde74..00000000000
--- a/lisp/startup.el
+++ /dev/null
@@ -1,968 +0,0 @@
-;;; startup.el --- process Emacs shell arguments
-
-;; Copyright (C) 1985, 86, 92, 94, 95, 1996 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This file parses the command line and gets Emacs running. Options on
-;; the command line are handled in precedence order. The order is the
-;; one in the list below; first described means first handled. Options
-;; within each category (delimited by a bar) are handled in the order
-;; encountered on the command line.
-
-;; -------------------------
-;; -version Print Emacs version to stderr, then exit
-;; --version successfully right away.
-;; This option is handled by emacs.c
-;; -------------------------
-;; -help Print a short usage description and exit
-;; --help successfully right away.
-;; This option is handled by emacs.c
-;; -------------------------
-;; -nl Do not use shared memory (for systems that
-;; -no-shared-memory support this) for the dumped Emacs data.
-;; This option is handled by emacs.c
-;;
-;; -map For VMS.
-;; --map-data This option is handled by emacs.c
-;; -------------------------
-;; -t FILE Use FILE as the name of the terminal.
-;; --terminal FILE Using this implies "-nw" also.
-;; This option is handled by emacs.c
-;; -------------------------
-;; -d DISPNAME Use DISPNAME as the name of the X-windows
-;; -display DISPNAME display for the initial frame.
-;; --display DISPNAME This option is handled by emacs.c
-;; -------------------------
-;; -nw Do not use a windows system (but use the
-;; --no-windows terminal instead.)
-;; This option is handled by emacs.c
-;; -------------------------
-;; -batch Execute noninteractively (messages go to stdout,
-;; --batch variable noninteractive set to t)
-;; This option is handled by emacs.c
-;; -------------------------
-;; -q Do not load user's init file and do not load
-;; -no-init-file "default.el". Regardless of this switch,
-;; --no-init-file "site-start" is still loaded.
-;; -------------------------
-;; -no-site-file Do not load "site-start.el". (This is the ONLY
-;; --no-site-file way to prevent loading that file.)
-;; -------------------------
-;; -u USER Load USER's init file instead of the init
-;; -user USER file belonging to the user starting Emacs.
-;; --user USER
-;; -------------------------
-;; -debug-init Don't catch errors in init files; let the
-;; --debug-init debugger run.
-;; -------------------------
-;; -i ICONTYPE Set type of icon using when Emacs is
-;; -itype ICONTYPE iconified under X-windows.
-;; --icon-type ICONTYPE This option is passed on to term/x-win.el
-;;
-;; -iconic Start Emacs iconified under X-windows.
-;; --iconic This option is passed on to term/x-win.el
-;; -------------------------
-;; Various X-windows options for colors/fonts/geometry/title etc.
-;; These options are passed on to term/x-win.el which see. Certain
-;; of these are also found in term/pc-win.el
-;; -------------------------
-;; FILE Visit FILE.
-;;
-;; -L DIRNAME Add DIRNAME to load-path
-;; -directory DIRNAME
-;; --directory DIRNAME
-;;
-;; -l FILE Load and execute the Emacs lisp code
-;; -load FILE in FILE.
-;; --load FILE
-;;
-;; -f FUNC Execute Emacs lisp function FUNC with
-;; -funcall FUNC no arguments. The "-e" form is outdated
-;; --funcall FUNC and should not be used. (It's a typo
-;; -e FUNC promoted to a feature.)
-;;
-;; -eval FORM Execute Emacs lisp form FORM.
-;; --eval FORM
-;;
-;; -insert FILE Insert the contents of FILE into buffer.
-;; --insert FILE
-;; -------------------------
-;; -kill Kill (exit) Emacs right away.
-;; --kill
-;; -------------------------
-
-;;; Code:
-
-(setq top-level '(normal-top-level))
-
-(defvar command-line-processed nil "t once command line has been processed")
-
-(defvar inhibit-startup-message nil
- "*Non-nil inhibits the initial startup message.
-This is for use in your personal init file, once you are familiar
-with the contents of the startup message.")
-
-(defvar inhibit-startup-echo-area-message nil
- "*Non-nil inhibits the initial startup echo area message.
-Inhibition takes effect only if your `.emacs' file contains
-a line of this form:
- (setq inhibit-startup-echo-area-message \"YOUR-USER-NAME\")
-If your `.emacs' file is byte-compiled, use the following form instead:
- (eval '(setq inhibit-startup-echo-area-message \"YOUR-USER-NAME\"))
-Thus, someone else using a copy of your `.emacs' file will see
-the startup message unless he personally acts to inhibit it.")
-
-(defvar inhibit-default-init nil
- "*Non-nil inhibits loading the `default' library.")
-
-(defvar 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 command-line-args-left nil
- "List of command-line args not yet processed.")
-
-(defvar command-line-functions nil ;; lrs 7/31/89
- "List of functions to process unrecognized command-line arguments.
-Each function should access the dynamically bound variables
-`argi' (the current argument) and `command-line-args-left' (the remaining
-arguments). The function should return non-nil only if it recognizes and
-processes `argi'. If it does so, it may consume successive arguments by
-altering `command-line-args-left' to remove them.")
-
-(defvar command-line-default-directory nil
- "Default directory to use for command line arguments.
-This is normally copied from `default-directory' when Emacs starts.")
-
-;;; This is here, rather than in x-win.el, so that we can ignore these
-;;; options when we are not using X.
-(defvar command-line-x-option-alist
- '(("-bw" 1 x-handle-numeric-switch border-width)
- ("-d" 1 x-handle-display)
- ("-display" 1 x-handle-display)
- ("-name" 1 x-handle-name-switch)
- ("-title" 1 x-handle-switch title)
- ("-T" 1 x-handle-switch title)
- ("-r" 0 x-handle-switch reverse t)
- ("-rv" 0 x-handle-switch reverse t)
- ("-reverse" 0 x-handle-switch reverse t)
- ("-reverse-video" 0 x-handle-switch reverse t)
- ("-fn" 1 x-handle-switch font)
- ("-font" 1 x-handle-switch font)
- ("-ib" 1 x-handle-numeric-switch internal-border-width)
- ("-g" 1 x-handle-geometry)
- ("-geometry" 1 x-handle-geometry)
- ("-fg" 1 x-handle-switch foreground-color)
- ("-foreground" 1 x-handle-switch foreground-color)
- ("-bg" 1 x-handle-switch background-color)
- ("-background" 1 x-handle-switch background-color)
- ("-ms" 1 x-handle-switch mouse-color)
- ("-itype" 0 x-handle-switch icon-type t)
- ("-i" 0 x-handle-switch icon-type t)
- ("-iconic" 0 x-handle-iconic)
- ("-xrm" 1 x-handle-xrm-switch)
- ("-cr" 1 x-handle-switch cursor-color)
- ("-vb" 0 x-handle-switch vertical-scroll-bars t)
- ("-hb" 0 x-handle-switch horizontal-scroll-bars t)
- ("-bd" 1 x-handle-switch)
- ("--border-width" 1 x-handle-numeric-switch border-width)
- ("--display" 1 x-handle-display)
- ("--name" 1 x-handle-name-switch)
- ("--title" 1 x-handle-switch title)
- ("--reverse-video" 0 x-handle-switch reverse t)
- ("--font" 1 x-handle-switch font)
- ("--internal-border" 1 x-handle-numeric-switch internal-border-width)
- ("--geometry" 1 x-handle-geometry)
- ("--foreground-color" 1 x-handle-switch foreground-color)
- ("--background-color" 1 x-handle-switch background-color)
- ("--mouse-color" 1 x-handle-switch mouse-color)
- ("--icon-type" 0 x-handle-switch icon-type t)
- ("--iconic" 0 x-handle-iconic)
- ("--xrm" 1 x-handle-xrm-switch)
- ("--cursor-color" 1 x-handle-switch cursor-color)
- ("--vertical-scroll-bars" 0 x-handle-switch vertical-scroll-bars t)
- ("--border-color" 1 x-handle-switch border-width))
- "Alist of X Windows options.
-Each element has the form
- (NAME NUMARGS HANDLER FRAME-PARAM VALUE)
-where NAME is the option name string, NUMARGS is the number of arguments
-that the option accepts, HANDLER is a function to call to handle the option.
-FRAME-PARAM (optional) is the frame parameter this option specifies,
-and VALUE is the value which is given to that frame parameter
-\(most options use the argument for this, so VALUE is not present).")
-
-(defvar before-init-hook nil
- "Normal hook run after handling urgent options but before loading init files.")
-
-(defvar after-init-hook nil
- "Normal hook run after loading the init files, `~/.emacs' and `default.el'.
-There is no `condition-case' around the running of these functions;
-therefore, if you set `debug-on-error' non-nil in `.emacs',
-an error in one of these functions will invoke the debugger.")
-
-(defvar emacs-startup-hook nil
- "Normal hook run after loading init files and handling the command line.")
-
-(defvar term-setup-hook nil
- "Normal hook run after loading terminal-specific Lisp code.
-It also follows `emacs-startup-hook'. This hook exists for users to set,
-so as to override the definitions made by the terminal-specific file.
-Emacs never sets this variable itself.")
-
-(defvar keyboard-type nil
- "The brand of keyboard you are using.
-This variable is used to define
-the proper function and keypad keys for use under X. It is used in a
-fashion analogous to the environment value TERM.")
-
-(defvar window-setup-hook nil
- "Normal hook run to initialize window system display.
-Emacs runs this hook after processing the command line arguments and loading
-the user's init file.")
-
-(defvar initial-major-mode 'lisp-interaction-mode
- "Major mode command symbol to use for the initial *scratch* buffer.")
-
-(defvar init-file-user nil
- "Identity of user whose `.emacs' file is or was read.
-The value is nil if `-q' or `--no-init-file' was specified,
-meaning do not load any init file.
-
-Otherwise, the value may be the null string, meaning use the init file
-for the user that originally logged in, or it may be a
-string containing a user's name meaning use that person's init file.
-
-In either of the latter cases, `(concat \"~\" init-file-user \"/\")'
-evaluates to the name of the directory where the `.emacs' file was
-looked for.
-
-Setting `init-file-user' does not prevent Emacs from loading
-`site-start.el'. The only way to do that is to use `--no-site-file'.")
-
-(defvar site-run-file "site-start"
- "File containing site-wide run-time initializations.
-This file is loaded at run-time before `~/.emacs'. It contains inits
-that need to be in place for the entire site, but which, due to their
-higher incidence of change, don't make sense to load into emacs'
-dumped image. Thus, the run-time load order is: 1. file described in
-this variable, if non-nil; 2. `~/.emacs'; 3. `default.el'.
-
-Don't use the `site-start.el' file for things some users may not like.
-Put them in `default.el' instead, so that users can more easily
-override them. Users can prevent loading `default.el' with the `-q'
-option or by setting `inhibit-default-init' in their own init files,
-but inhibiting `site-start.el' requires `--no-site-file', which
-is less convenient.")
-
-(defconst iso-8859-1-locale-regexp "8859[-_]?1"
- "Regexp that specifies when to enable the ISO 8859-1 character set.
-We do that if this regexp matches the locale name
-specified by the LC_ALL, LC_CTYPE and LANG environment variables.")
-
-(defvar mail-host-address nil
- "*Name of this machine, for purposes of naming users.")
-
-(defvar user-mail-address nil
- "*Full mailing address of this user.
-This is initialized based on `mail-host-address',
-after your init file is read, in case it sets `mail-host-address'.")
-
-(defvar auto-save-list-file-prefix
- (if (eq system-type 'ms-dos)
- "~/_s" ; MS-DOS cannot have initial dot, and allows only 8.3 names
- "~/.saves-")
- "Prefix for generating `auto-save-list-file-name'.
-This is used after reading your `.emacs' file to initialize
-`auto-save-list-file-name', by appending Emacs's pid and the system name,
-if you have not already set `auto-save-list-file-name' yourself.
-Set this to nil if you want to prevent `auto-save-list-file-name'
-from being initialized.")
-
-(defvar init-file-debug nil)
-
-(defvar init-file-had-error nil)
-
-;; This function is called from the subdirs.el file.
-(defun normal-top-level-add-to-load-path (dirs)
- (let ((tail (member (directory-file-name default-directory) load-path)))
- (setcdr tail (append (mapcar 'expand-file-name dirs) (cdr tail)))))
-
-(defun normal-top-level ()
- (if command-line-processed
- (message "Back to top level.")
- (setq command-line-processed t)
- ;; Give *Messages* the same default-directory as *scratch*,
- ;; just to keep things predictable.
- (let ((dir default-directory))
- (save-excursion
- (set-buffer (get-buffer "*Messages*"))
- (setq default-directory dir)))
- ;; Look in each dir in load-path for a subdirs.el file.
- ;; If we find one, load it, which will add the appropriate subdirs
- ;; of that dir into load-path,
- (let ((tail load-path)
- new)
- (while tail
- (setq new (cons (car tail) new))
- (let ((default-directory (car tail)))
- (load (expand-file-name "subdirs.el" (car tail)) t t t))
- (setq tail (cdr tail))))
- (if (not (eq system-type 'vax-vms))
- (progn
- ;; If the PWD environment variable isn't accurate, delete it.
- (let ((pwd (getenv "PWD")))
- (and (stringp pwd)
- ;; Use FOO/., so that if FOO is a symlink, file-attributes
- ;; describes the directory linked to, not FOO itself.
- (or (equal (file-attributes
- (concat (file-name-as-directory pwd) "."))
- (file-attributes
- (concat (file-name-as-directory default-directory)
- ".")))
- (setq process-environment
- (delete (concat "PWD=" pwd)
- process-environment)))))))
- (setq default-directory (abbreviate-file-name default-directory))
- (let ((menubar-bindings-done nil))
- (unwind-protect
- (command-line)
- ;; Do this again, in case .emacs defined more abbreviations.
- (setq default-directory (abbreviate-file-name default-directory))
- ;; Specify the file for recording all the auto save files of this session.
- ;; This is used by recover-session.
- (or auto-save-list-file-name
- (and auto-save-list-file-prefix
- (setq auto-save-list-file-name
- ;; Under MS-DOS our PID is almost always reused between
- ;; Emacs invocations. We need something more unique.
- (if (eq system-type 'ms-dos)
- (concat
- (make-temp-name
- (expand-file-name auto-save-list-file-prefix))
- "~")
-
- (expand-file-name (format "%s%d-%s~"
- auto-save-list-file-prefix
- (emacs-pid)
- (system-name)))))))
- (run-hooks 'emacs-startup-hook)
- (and term-setup-hook
- (run-hooks 'term-setup-hook))
- ;; Modify the initial frame based on what .emacs puts into
- ;; ...-frame-alist.
- (if (fboundp 'frame-notice-user-settings)
- (frame-notice-user-settings))
- ;; Now we know the user's default font, so add it to the menu.
- (if (fboundp 'font-menu-add-default)
- (font-menu-add-default))
- (and window-setup-hook
- (run-hooks 'window-setup-hook))
- (or menubar-bindings-done
- (if (memq window-system '(x w32))
- (precompute-menubar-bindings)))))))
-
-;; Precompute the keyboard equivalents in the menu bar items.
-(defun precompute-menubar-bindings ()
- (let ((submap (lookup-key global-map [menu-bar])))
- (while submap
- (and (consp (car submap))
- (symbolp (car (car submap)))
- (stringp (car-safe (cdr (car submap))))
- (keymapp (cdr (cdr (car submap))))
- (progn
- (x-popup-menu nil (cdr (cdr (car submap))))
- (if purify-flag
- (garbage-collect))))
- (setq submap (cdr submap))))
- (setq define-key-rebound-commands t))
-
-(defun command-line ()
- (setq command-line-default-directory default-directory)
-
- ;; See if we should import version-control from the environment variable.
- (let ((vc (getenv "VERSION_CONTROL")))
- (cond ((eq vc nil)) ;don't do anything if not set
- ((or (string= vc "t")
- (string= vc "numbered"))
- (setq version-control t))
- ((or (string= vc "nil")
- (string= vc "existing"))
- (setq version-control nil))
- ((or (string= vc "never")
- (string= vc "simple"))
- (setq version-control 'never))))
-
- (if (let ((ctype
- ;; Use the first of these three envvars that has a nonempty value.
- (or (let ((string (getenv "LC_ALL")))
- (and (not (equal string "")) string))
- (let ((string (getenv "LC_CTYPE")))
- (and (not (equal string "")) string))
- (let ((string (getenv "LANG")))
- (and (not (equal string "")) string)))))
- (and ctype
- (string-match iso-8859-1-locale-regexp ctype)))
- (progn
- (require 'disp-table)
- (standard-display-european t)
- (require 'iso-syntax)))
-
- ;;! This has been commented out; I currently find the behavior when
- ;;! split-window-keep-point is nil disturbing, but if I can get used
- ;;! to it, then it would be better to eliminate the option.
- ;;! ;; Choose a good default value for split-window-keep-point.
- ;;! (setq split-window-keep-point (> baud-rate 2400))
-
- ;; Read window system's init file if using a window system.
- (condition-case error
- (if (and window-system (not noninteractive))
- (load (concat term-file-prefix
- (symbol-name window-system)
- "-win")
- ;; Every window system should have a startup file;
- ;; barf if we can't find it.
- nil t))
- ;; If we can't read it, print the error message and exit.
- (error
- (princ
- (if (eq (car error) 'error)
- (apply 'concat (cdr error))
- (if (memq 'file-error (get (car error) 'error-conditions))
- (format "%s: %s"
- (nth 1 error)
- (mapconcat '(lambda (obj) (prin1-to-string obj t))
- (cdr (cdr error)) ", "))
- (format "%s: %s"
- (get (car error) 'error-message)
- (mapconcat '(lambda (obj) (prin1-to-string obj t))
- (cdr error) ", "))))
- 'external-debugging-output)
- (setq window-system nil)
- (kill-emacs)))
-
- (let ((done nil)
- (args (cdr command-line-args)))
-
- ;; Figure out which user's init file to load,
- ;; either from the environment or from the options.
- (setq init-file-user (if noninteractive nil (user-login-name)))
- ;; If user has not done su, use current $HOME to find .emacs.
- (and init-file-user (string= init-file-user (user-real-login-name))
- (setq init-file-user ""))
-
- ;; Process the command-line args, and delete the arguments
- ;; processed. This is consistent with the way main in emacs.c
- ;; does things.
- (while (and (not done) args)
- (let ((longopts '(("--no-init-file") ("--no-site-file") ("--user")
- ("--debug-init") ("--iconic") ("--icon-type")))
- (argi (car args))
- (argval nil))
- ;; Handle --OPTION=VALUE format.
- (if (and (string-match "\\`--" argi)
- (string-match "=" argi))
- (setq argval (substring argi (match-end 0))
- argi (substring argi 0 (match-beginning 0))))
- (or (equal argi "--")
- (let ((completion (try-completion argi longopts)))
- (if (eq completion t)
- (setq argi (substring argi 1))
- (if (stringp completion)
- (let ((elt (assoc completion longopts)))
- (or elt
- (error "Option `%s' is ambiguous" argi))
- (setq argi (substring (car elt) 1)))
- (setq argval nil)))))
- (cond
- ((or (string-equal argi "-q")
- (string-equal argi "-no-init-file"))
- (setq init-file-user nil
- args (cdr args)))
- ((or (string-equal argi "-u")
- (string-equal argi "-user"))
- (or argval
- (setq args (cdr args)
- argval (car args)))
- (setq init-file-user argval
- argval nil
- args (cdr args)))
- ((string-equal argi "-no-site-file")
- (setq site-run-file nil
- args (cdr args)))
- ((string-equal argi "-debug-init")
- (setq init-file-debug t
- args (cdr args)))
- ((string-equal argi "-iconic")
- (setq initial-frame-alist
- (cons '(visibility . icon) initial-frame-alist))
- (setq args (cdr args)))
- ((or (string-equal argi "-icon-type")
- (string-equal argi "-i")
- (string-equal argi "-itype"))
- (setq default-frame-alist
- (cons '(icon-type . t) default-frame-alist))
- (setq args (cdr args)))
- (t (setq done t)))
- ;; Was argval set but not used?
- (and argval
- (error "Option `%s' doesn't allow an argument" argi))))
-
- ;; Re-attach the program name to the front of the arg list.
- (and command-line-args (setcdr command-line-args args)))
-
- ;; Under X Windows, this creates the X frame and deletes the terminal frame.
- (if (fboundp 'face-initialize)
- (face-initialize))
- (if (fboundp 'frame-initialize)
- (frame-initialize))
- ;; If frame was created with a menu bar, set menu-bar-mode on.
- (if (or (not (memq window-system '(x w32)))
- (> (cdr (assq 'menu-bar-lines (frame-parameters))) 0))
- (menu-bar-mode t))
-
- (run-hooks 'before-init-hook)
-
- ;; Run the site-start library if it exists. The point of this file is
- ;; that it is run before .emacs. There is no point in doing this after
- ;; .emacs; that is useless.
- (if site-run-file
- (load site-run-file t t))
-
- ;; Sites should not disable this. Only individuals should disable
- ;; the startup message.
- (setq inhibit-startup-message nil)
-
- ;; Load that user's init file, or the default one, or none.
- (let (debug-on-error-from-init-file
- debug-on-error-should-be-set
- (debug-on-error-initial
- (if (eq init-file-debug t) 'startup init-file-debug)))
- (let ((debug-on-error debug-on-error-initial)
- ;; This function actually reads the init files.
- (inner
- (function
- (lambda ()
- (if init-file-user
- (progn
- (setq user-init-file
- (cond
- ((eq system-type 'ms-dos)
- (concat "~" init-file-user "/_emacs"))
- ((eq system-type 'windows-nt)
- (if (file-exists-p "~/.emacs")
- "~/.emacs"
- "~/_emacs"))
- ((eq system-type 'vax-vms)
- "sys$login:.emacs")
- (t
- (concat "~" init-file-user "/.emacs"))))
- (load user-init-file 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)))))))))
- (if init-file-debug
- ;; Do this without a condition-case if the user wants to debug.
- (funcall inner)
- (condition-case error
- (progn
- (funcall inner)
- (setq init-file-had-error nil))
- (error (message "Error in init file: %s%s%s"
- (get (car error) 'error-message)
- (if (cdr error) ": " "")
- (mapconcat 'prin1-to-string (cdr error) ", "))
- (setq init-file-had-error t))))
- ;; If we can tell that the init file altered debug-on-error,
- ;; arrange to preserve the value that it set up.
- (or (eq debug-on-error debug-on-error-initial)
- (setq debug-on-error-should-be-set t
- debug-on-error-from-init-file debug-on-error)))
- (if debug-on-error-should-be-set
- (setq debug-on-error debug-on-error-from-init-file)))
-
- ;; Do this here in case the init file sets mail-host-address.
- (or user-mail-address
- (setq user-mail-address (concat (user-login-name) "@"
- (or mail-host-address
- (system-name)))))
-
- (run-hooks 'after-init-hook)
-
- ;; If *scratch* exists and init file didn't change its mode, initialize it.
- (if (get-buffer "*scratch*")
- (save-excursion
- (set-buffer "*scratch*")
- (if (eq major-mode 'fundamental-mode)
- (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) (not window-system)
- (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)))))
-
- ;; Process the remaining args.
- (command-line-1 (cdr command-line-args))
-
- ;; If -batch, terminate after processing the command options.
- (if noninteractive (kill-emacs t)))
-
-(defun command-line-1 (command-line-args-left)
- (or noninteractive (input-pending-p) init-file-had-error
- (and inhibit-startup-echo-area-message
- (let ((buffer (get-buffer-create " *temp*")))
- (prog1
- (condition-case nil
- (save-excursion
- (set-buffer buffer)
- (insert-file-contents user-init-file)
- (re-search-forward
- (concat
- "([ \t\n]*setq[ \t\n]+"
- "inhibit-startup-echo-area-message[ \t\n]+"
- (regexp-quote
- (prin1-to-string
- (if (string= init-file-user "")
- (user-login-name)
- init-file-user)))
- "[ \t\n]*)")
- nil t))
- (error nil))
- (kill-buffer buffer))))
- (message (if (eq (key-binding "\C-h\C-p") 'describe-project)
- "For information about the GNU Project and its goals, type C-h C-p."
- (substitute-command-keys
- "For information about the GNU Project and its goals, type \\[describe-project]."))))
- (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 process, 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
- (run-hooks 'term-setup-hook))
- ;; Don't let the hook be run twice.
- (setq term-setup-hook nil)
-
- ;; It's important to notice the user settings before we
- ;; display the startup message; otherwise, the settings
- ;; won't take effect until the user gives the first
- ;; keystroke, and that's distracting.
- (if (fboundp 'frame-notice-user-settings)
- (frame-notice-user-settings))
-
- (and window-setup-hook
- (run-hooks 'window-setup-hook))
- (setq window-setup-hook nil)
- ;; Do this now to avoid an annoying delay if the user
- ;; clicks the menu bar during the sit-for.
- (if (memq window-system '(x w32))
- (precompute-menubar-bindings))
- (setq menubar-bindings-done t)
- (unwind-protect
- (progn
- ;; The convention for this piece of code is that
- ;; each piece of output starts with one or two newlines
- ;; and does not end with any newlines.
- (insert "Welcome to GNU Emacs")
- (if (eq system-type 'gnu/linux)
- (insert ", one component of a Linux-based GNU system."))
- (insert "\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-x\C-c") 'save-buffers-kill-emacs)
- (eq (key-binding "\C-ht") 'help-with-tutorial)
- (eq (key-binding "\C-hi") 'info)
- (eq (key-binding "\C-h\C-n") 'view-emacs-news))
- (insert "
-Get help C-h (Hold down CTRL and press h)
-Undo changes C-x u Exit Emacs C-x C-c
-Get a tutorial C-h t Use Info to read docs C-h i")
- (insert (substitute-command-keys
- (format "\n
-Get help %s
-Undo changes \\[advertised-undo]
-Exit Emacs \\[save-buffers-kill-emacs]
-Get a tutorial \\[help-with-tutorial]
-Use Info to read docs \\[info]"
- (let ((where (where-is-internal
- 'help-command nil t)))
- (if where
- (key-description where)
- "M-x help"))))))
- ;; Say how to use the menu bar
- ;; if that is not with the mouse.
- (if (not (assq 'display (frame-parameters)))
- (if (and (eq (key-binding "\M-`") 'tmm-menubar)
- (eq (key-binding [f10]) 'tmm-menubar))
- (insert "
-Activate menubar F10 or ESC ` or M-`")
- (insert (substitute-command-keys "
-Activate menubar \\[tmm-menubar]"))))
-
- ;; Windows and MSDOS (currently) do not count as
- ;; window systems, but do have mouse support.
- (if window-system
- (insert "
-Mode-specific menu C-mouse-3 (third button, with CTRL)"))
- ;; Many users seem to have problems with these.
- (insert "
-\(`C-' means use the CTRL key. `M-' means use the Meta (or Alt) key.
-If you have no Meta key, you may instead type ESC followed by the character.)")
- (and auto-save-list-file-prefix
- (directory-files
- (file-name-directory auto-save-list-file-prefix)
- nil
- (concat "\\`"
- (regexp-quote (file-name-nondirectory
- auto-save-list-file-prefix)))
- t)
- (insert "\n\nIf an Emacs session crashed recently, "
- "type M-x recover-session RET\nto recover"
- " the files you were editing."))
-
- (insert "\n\n" (emacs-version)
- "
-Copyright (C) 1996 Free Software Foundation, Inc.")
- (if (and (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))
- (insert
- "\n
-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.")
- (insert (substitute-command-keys
- "\n
-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.")))
- (goto-char (point-min))
-
- (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)))))
- ;; Delay 2 seconds after the init file error message
- ;; was displayed, so user can read it.
- (if init-file-had-error
- (sit-for 2))
- (let ((dir command-line-default-directory)
- (file-count 0)
- first-file-buffer
- tem
- just-files ;; t if this follows the magic -- option.
- ;; This includes our standard options' long versions
- ;; and long versions of what's on command-switch-alist.
- (longopts
- (append '(("--funcall") ("--load") ("--insert") ("--kill")
- ("--directory") ("--eval") ("--find-file") ("--visit"))
- (mapcar '(lambda (elt)
- (list (concat "-" (car elt))))
- command-switch-alist)))
- (line 0))
-
- ;; Add the long X options to longopts.
- (setq tem command-line-x-option-alist)
- (while tem
- (if (string-match "^--" (car (car tem)))
- (setq longopts (cons (list (car (car tem))) longopts)))
- (setq tem (cdr tem)))
-
- ;; Loop, processing options.
- (while (and command-line-args-left)
- (let* ((argi (car command-line-args-left))
- (orig-argi argi)
- argval completion
- ;; List of directories specified in -L/--directory,
- ;; in reverse of the order specified.
- extra-load-path
- (initial-load-path load-path))
- (setq command-line-args-left (cdr command-line-args-left))
-
- ;; Do preliminary decoding of the option.
- (if just-files
- ;; After --, don't look for options; treat all args as files.
- (setq argi "")
- ;; Convert long options to ordinary options
- ;; and separate out an attached option argument into argval.
- (if (string-match "^--[^=]*=" argi)
- (setq argval (substring argi (match-end 0))
- argi (substring argi 0 (1- (match-end 0)))))
- (if (equal argi "--")
- (setq completion nil)
- (setq completion (try-completion argi longopts)))
- (if (eq completion t)
- (setq argi (substring argi 1))
- (if (stringp completion)
- (let ((elt (assoc completion longopts)))
- (or elt
- (error "Option `%s' is ambiguous" argi))
- (setq argi (substring (car elt) 1)))
- (setq argval nil argi orig-argi))))
-
- ;; Execute the option.
- (cond ((setq tem (assoc argi command-switch-alist))
- (if argval
- (let ((command-line-args-left
- (cons argval command-line-args-left)))
- (funcall (cdr tem) argi))
- (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
- (if argval
- (setq tem (intern argval))
- (setq tem (intern (car command-line-args-left)))
- (setq command-line-args-left (cdr command-line-args-left)))
- (if (arrayp (symbol-function tem))
- (command-execute tem)
- (funcall tem)))
- ((string-equal argi "-eval")
- (if argval
- (setq tem argval)
- (setq tem (car command-line-args-left))
- (setq command-line-args-left (cdr command-line-args-left)))
- (eval (read tem)))
- ;; Set the default directory as specified in -L.
- ((or (string-equal argi "-L")
- (string-equal argi "-directory"))
- (if argval
- (setq tem argval)
- (setq tem (car command-line-args-left)
- command-line-args-left (cdr command-line-args-left)))
- (setq tem (command-line-normalize-file-name tem))
- (setq extra-load-path
- (cons (expand-file-name tem) extra-load-path))
- (setq load-path (append (nreverse extra-load-path)
- initial-load-path)))
- ((or (string-equal argi "-l")
- (string-equal argi "-load"))
- (if argval
- (setq tem argval)
- (setq tem (car command-line-args-left)
- command-line-args-left (cdr command-line-args-left)))
- (let ((file (command-line-normalize-file-name tem)))
- ;; 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)))
- ((string-equal argi "-insert")
- (if argval
- (setq tem argval)
- (setq tem (car command-line-args-left)
- command-line-args-left (cdr command-line-args-left)))
- (or (stringp tem)
- (error "File name omitted from `-insert' option"))
- (insert-file-contents (command-line-normalize-file-name tem)))
- ((string-equal argi "-kill")
- (kill-emacs t))
- ((string-match "^\\+[0-9]+\\'" argi)
- (setq line (string-to-int argi)))
- ((setq tem (assoc argi command-line-x-option-alist))
- ;; Ignore X-windows options and their args if not using X.
- (setq command-line-args-left
- (nthcdr (nth 1 tem) command-line-args-left)))
- ((or (string-equal argi "-find-file")
- (string-equal argi "-visit"))
- ;; An explicit option to specify visiting a file.
- (setq file-count (1+ file-count))
- (let ((file
- (expand-file-name
- (command-line-normalize-file-name orig-argi)
- dir)))
- (if (= file-count 1)
- (setq first-file-buffer (find-file file))
- (find-file-other-window file)))
- (or (zerop line)
- (goto-line line))
- (setq line 0))
- ((equal argi "--")
- (setq just-files t))
- (t
- ;; We have almost exhausted our options. See if the
- ;; user has made any other command-line options available
- (let ((hooks command-line-functions);; lrs 7/31/89
- (did-hook nil))
- (while (and hooks
- (not (setq did-hook (funcall (car hooks)))))
- (setq hooks (cdr hooks)))
- (if (not did-hook)
- ;; Ok, presume that the argument is a file name
- (progn
- (if (string-match "\\`-" argi)
- (error "Unknown option `%s'" argi))
- (setq file-count (1+ file-count))
- (let ((file
- (expand-file-name
- (command-line-normalize-file-name orig-argi)
- dir)))
- (if (= file-count 1)
- (setq first-file-buffer (find-file file))
- (find-file-other-window file)))
- (or (zerop line)
- (goto-line line))
- (setq line 0))))))))
- ;; If 3 or more files visited, and not all visible,
- ;; show user what they all are.
- (and (> file-count 2)
- (not noninteractive)
- (or (get-buffer-window first-file-buffer)
- (progn (other-window 1)
- (buffer-menu)))))))
-
-(defun command-line-normalize-file-name (file)
- "Collapse multiple slashes to one, to handle non-Emacs file names."
- (save-match-data
- ;; Use arg 1 so that we don't collapse // at the start of the file name.
- ;; That is significant on some systems.
- ;; However, /// at the beginning is supposed to mean just /, not //.
- (if (string-match "^///+" file)
- (setq file (replace-match "/" t t file)))
- (while (string-match "//+" file 1)
- (setq file (replace-match "/" t t file)))
- file))
-
-;;; startup.el ends here
diff --git a/lisp/subr.el b/lisp/subr.el
deleted file mode 100644
index 22056046416..00000000000
--- a/lisp/subr.el
+++ /dev/null
@@ -1,975 +0,0 @@
-;;; subr.el --- basic lisp subroutines for Emacs
-
-;; Copyright (C) 1985, 1986, 1992, 1994, 1995 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-
-;;;; Lisp language features.
-
-(defmacro lambda (&rest cdr)
- "Return a lambda expression.
-A call of the form (lambda ARGS DOCSTRING INTERACTIVE BODY) is
-self-quoting; the result of evaluating the lambda expression is the
-expression itself. The lambda expression may then be treated as a
-function, i.e., stored as the function value of a symbol, passed to
-funcall or mapcar, etc.
-
-ARGS should take the same form as an argument list for a `defun'.
-DOCSTRING is an optional documentation string.
- If present, it should describe how to call the function.
- But documentation strings are usually not useful in nameless functions.
-INTERACTIVE should be a call to the function `interactive', which see.
-It may also be omitted.
-BODY should be a list of lisp expressions."
- ;; Note that this definition should not use backquotes; subr.el should not
- ;; depend on backquote.el.
- (list 'function (cons 'lambda cdr)))
-
-;;(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))))
-
-
-;;;; Keymap support.
-
-(defun undefined ()
- (interactive)
- (ding))
-
-;Prevent the \{...} documentation construct
-;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."
- (substitute-key-definition 'self-insert-command 'undefined map global-map)
- (or nodigits
- (let (loop)
- (define-key map "-" 'negative-argument)
- ;; Make plain numbers do numeric args.
- (setq loop ?0)
- (while (<= loop ?9)
- (define-key map (char-to-string loop) 'digit-argument)
- (setq loop (1+ loop))))))
-
-;Moved to keymap.c
-;(defun copy-keymap (keymap)
-; "Return a copy of KEYMAP"
-; (while (not (keymapp keymap))
-; (setq keymap (signal 'wrong-type-argument (list 'keymapp keymap))))
-; (if (vectorp keymap)
-; (copy-sequence keymap)
-; (copy-alist keymap)))
-
-(defvar key-substitution-in-progress nil
- "Used internally by substitute-key-definition.")
-
-(defun substitute-key-definition (olddef newdef keymap &optional oldmap prefix)
- "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.
-If optional fourth argument OLDMAP is specified, we redefine
-in KEYMAP as NEWDEF those chars which are defined as OLDDEF in OLDMAP."
- (or prefix (setq prefix ""))
- (let* ((scan (or oldmap keymap))
- (vec1 (vector nil))
- (prefix1 (vconcat prefix vec1))
- (key-substitution-in-progress
- (cons scan key-substitution-in-progress)))
- ;; Scan OLDMAP, finding each char or event-symbol that
- ;; has any definition, and act on it with hack-key.
- (while (consp scan)
- (if (consp (car scan))
- (let ((char (car (car scan)))
- (defn (cdr (car scan))))
- ;; The inside of this let duplicates exactly
- ;; the inside of the following let that handles array elements.
- (aset vec1 0 char)
- (aset prefix1 (length prefix) char)
- (let (inner-def skipped)
- ;; Skip past menu-prompt.
- (while (stringp (car-safe defn))
- (setq skipped (cons (car defn) skipped))
- (setq defn (cdr defn)))
- ;; Skip past cached key-equivalence data for menu items.
- (and (consp defn) (consp (car defn))
- (setq defn (cdr defn)))
- (setq inner-def defn)
- ;; Look past a symbol that names a keymap.
- (while (and (symbolp inner-def)
- (fboundp inner-def))
- (setq inner-def (symbol-function inner-def)))
- (if (eq defn olddef)
- (define-key keymap prefix1 (nconc (nreverse skipped) newdef))
- (if (and (keymapp defn)
- ;; Avoid recursively scanning
- ;; where KEYMAP does not have a submap.
- (let ((elt (lookup-key keymap prefix1)))
- (or (null elt)
- (keymapp elt)))
- ;; Avoid recursively rescanning keymap being scanned.
- (not (memq inner-def
- key-substitution-in-progress)))
- ;; If this one isn't being scanned already,
- ;; scan it now.
- (substitute-key-definition olddef newdef keymap
- inner-def
- prefix1)))))
- (if (arrayp (car scan))
- (let* ((array (car scan))
- (len (length array))
- (i 0))
- (while (< i len)
- (let ((char i) (defn (aref array i)))
- ;; The inside of this let duplicates exactly
- ;; the inside of the previous let.
- (aset vec1 0 char)
- (aset prefix1 (length prefix) char)
- (let (inner-def skipped)
- ;; Skip past menu-prompt.
- (while (stringp (car-safe defn))
- (setq skipped (cons (car defn) skipped))
- (setq defn (cdr defn)))
- (and (consp defn) (consp (car defn))
- (setq defn (cdr defn)))
- (setq inner-def defn)
- (while (and (symbolp inner-def)
- (fboundp inner-def))
- (setq inner-def (symbol-function inner-def)))
- (if (eq defn olddef)
- (define-key keymap prefix1
- (nconc (nreverse skipped) newdef))
- (if (and (keymapp defn)
- (let ((elt (lookup-key keymap prefix1)))
- (or (null elt)
- (keymapp elt)))
- (not (memq inner-def
- key-substitution-in-progress)))
- (substitute-key-definition olddef newdef keymap
- inner-def
- prefix1)))))
- (setq i (1+ i))))))
- (setq scan (cdr scan)))))
-
-(defun define-key-after (keymap key definition after)
- "Add binding in KEYMAP for KEY => DEFINITION, right after AFTER's binding.
-This is like `define-key' except that the binding for KEY is placed
-just after the binding for the event AFTER, instead of at the beginning
-of the map. Note that AFTER must be an event type (like KEY), NOT a command
-\(like DEFINITION).
-
-If AFTER is t, the new binding goes at the end of the keymap.
-
-KEY must contain just one event type--that is to say, it must be
-a string or vector of length 1.
-
-The order of bindings in a keymap matters when it is used as a menu."
-
- (or (keymapp keymap)
- (signal 'wrong-type-argument (list 'keymapp keymap)))
- (if (> (length key) 1)
- (error "multi-event key specified in `define-key-after'"))
- (let ((tail keymap) done inserted
- (first (aref key 0)))
- (while (and (not done) tail)
- ;; Delete any earlier bindings for the same key.
- (if (eq (car-safe (car (cdr tail))) first)
- (setcdr tail (cdr (cdr tail))))
- ;; When we reach AFTER's binding, insert the new binding after.
- ;; If we reach an inherited keymap, insert just before that.
- ;; If we reach the end of this keymap, insert at the end.
- (if (or (and (eq (car-safe (car tail)) after)
- (not (eq after t)))
- (eq (car (cdr tail)) 'keymap)
- (null (cdr tail)))
- (progn
- ;; Stop the scan only if we find a parent keymap.
- ;; Keep going past the inserted element
- ;; so we can delete any duplications that come later.
- (if (eq (car (cdr tail)) 'keymap)
- (setq done t))
- ;; Don't insert more than once.
- (or inserted
- (setcdr tail (cons (cons (aref key 0) definition) (cdr tail))))
- (setq inserted t)))
- (setq tail (cdr tail)))))
-
-(put 'keyboard-translate-table 'char-table-extra-slots 0)
-
-(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 (char-table-p keyboard-translate-table)
- (setq keyboard-translate-table
- (make-char-table 'keyboard-translate-table nil)))
- (aset keyboard-translate-table from to))
-
-
-;;;; The global keymap tree.
-
-;;; global-map, esc-map, and ctl-x-map have their values set up in
-;;; keymap.c; we just give them docstrings here.
-
-(defvar global-map nil
- "Default global keymap mapping Emacs keyboard input into commands.
-The value is a keymap which is usually (but not necessarily) Emacs's
-global map.")
-
-(defvar esc-map nil
- "Default keymap for ESC (meta) commands.
-The normal global definition of the character ESC indirects to this keymap.")
-
-(defvar ctl-x-map nil
- "Default keymap for C-x commands.
-The normal global definition of the character C-x indirects to this keymap.")
-
-(defvar ctl-x-4-map (make-sparse-keymap)
- "Keymap for subcommands of C-x 4")
-(defalias 'ctl-x-4-prefix ctl-x-4-map)
-(define-key ctl-x-map "4" 'ctl-x-4-prefix)
-
-(defvar ctl-x-5-map (make-sparse-keymap)
- "Keymap for frame commands.")
-(defalias 'ctl-x-5-prefix ctl-x-5-map)
-(define-key ctl-x-map "5" 'ctl-x-5-prefix)
-
-
-;;;; Event manipulation functions.
-
-;; The call to `read' is to ensure that the value is computed at load time
-;; and not compiled into the .elc file. The value is negative on most
-;; machines, but not on all!
-(defconst listify-key-sequence-1 (logior 128 (read "?\\M-\\^@")))
-
-(defun listify-key-sequence (key)
- "Convert a key sequence to a list of events."
- (if (vectorp key)
- (append key nil)
- (mapcar (function (lambda (c)
- (if (> c 127)
- (logxor c listify-key-sequence-1)
- c)))
- (append key nil))))
-
-(defsubst eventp (obj)
- "True if the argument is an event object."
- (or (integerp obj)
- (and (symbolp obj)
- (get obj 'event-symbol-elements))
- (and (consp obj)
- (symbolp (car obj))
- (get (car obj) 'event-symbol-elements))))
-
-(defun event-modifiers (event)
- "Returns a list of symbols representing the modifier keys in event EVENT.
-The elements of the list may include `meta', `control',
-`shift', `hyper', `super', `alt', `click', `double', `triple', `drag',
-and `down'."
- (let ((type event))
- (if (listp type)
- (setq type (car type)))
- (if (symbolp type)
- (cdr (get type 'event-symbol-elements))
- (let ((list nil))
- (or (zerop (logand type ?\M-\^@))
- (setq list (cons 'meta list)))
- (or (and (zerop (logand type ?\C-\^@))
- (>= (logand type 127) 32))
- (setq list (cons 'control list)))
- (or (and (zerop (logand type ?\S-\^@))
- (= (logand type 255) (downcase (logand type 255))))
- (setq list (cons 'shift list)))
- (or (zerop (logand type ?\H-\^@))
- (setq list (cons 'hyper list)))
- (or (zerop (logand type ?\s-\^@))
- (setq list (cons 'super list)))
- (or (zerop (logand type ?\A-\^@))
- (setq list (cons 'alt list)))
- list))))
-
-(defun event-basic-type (event)
- "Returns the basic type of the given event (all modifiers removed).
-The value is an ASCII printing character (not upper case) or a symbol."
- (if (consp event)
- (setq event (car event)))
- (if (symbolp event)
- (car (get event 'event-symbol-elements))
- (let ((base (logand event (1- (lsh 1 18)))))
- (downcase (if (< base 32) (logior base 64) base)))))
-
-(defsubst mouse-movement-p (object)
- "Return non-nil if OBJECT is a mouse movement event."
- (and (consp object)
- (eq (car object) 'mouse-movement)))
-
-(defsubst event-start (event)
- "Return the starting position of EVENT.
-If EVENT is a mouse press or a mouse click, this returns the location
-of the event.
-If EVENT is a drag, this returns the drag's starting position.
-The return value is of the form
- (WINDOW BUFFER-POSITION (X . Y) TIMESTAMP)
-The `posn-' functions access elements of such lists."
- (nth 1 event))
-
-(defsubst event-end (event)
- "Return the ending location of EVENT. EVENT should be a click or drag event.
-If EVENT is a click event, this function is the same as `event-start'.
-The return value is of the form
- (WINDOW BUFFER-POSITION (X . Y) TIMESTAMP)
-The `posn-' functions access elements of such lists."
- (nth (if (consp (nth 2 event)) 2 1) event))
-
-(defsubst event-click-count (event)
- "Return the multi-click count of EVENT, a click or drag event.
-The return value is a positive integer."
- (if (integerp (nth 2 event)) (nth 2 event) 1))
-
-(defsubst posn-window (position)
- "Return the window in POSITION.
-POSITION should be a list of the form
- (WINDOW BUFFER-POSITION (X . Y) TIMESTAMP)
-as returned by the `event-start' and `event-end' functions."
- (nth 0 position))
-
-(defsubst posn-point (position)
- "Return the buffer location in POSITION.
-POSITION should be a list of the form
- (WINDOW BUFFER-POSITION (X . Y) TIMESTAMP)
-as returned by the `event-start' and `event-end' functions."
- (if (consp (nth 1 position))
- (car (nth 1 position))
- (nth 1 position)))
-
-(defsubst posn-x-y (position)
- "Return the x and y coordinates in POSITION.
-POSITION should be a list of the form
- (WINDOW BUFFER-POSITION (X . Y) TIMESTAMP)
-as returned by the `event-start' and `event-end' functions."
- (nth 2 position))
-
-(defun posn-col-row (position)
- "Return the column and row in POSITION, measured in characters.
-POSITION should be a list of the form
- (WINDOW BUFFER-POSITION (X . Y) TIMESTAMP)
-as returned by the `event-start' and `event-end' functions.
-For a scroll-bar event, the result column is 0, and the row
-corresponds to the vertical position of the click in the scroll bar."
- (let ((pair (nth 2 position))
- (window (posn-window position)))
- (if (eq (if (consp (nth 1 position))
- (car (nth 1 position))
- (nth 1 position))
- 'vertical-scroll-bar)
- (cons 0 (scroll-bar-scale pair (1- (window-height window))))
- (if (eq (if (consp (nth 1 position))
- (car (nth 1 position))
- (nth 1 position))
- 'horizontal-scroll-bar)
- (cons (scroll-bar-scale pair (window-width window)) 0)
- (let* ((frame (if (framep window) window (window-frame window)))
- (x (/ (car pair) (frame-char-width frame)))
- (y (/ (cdr pair) (frame-char-height frame))))
- (cons x y))))))
-
-(defsubst posn-timestamp (position)
- "Return the timestamp of POSITION.
-POSITION should be a list of the form
- (WINDOW BUFFER-POSITION (X . Y) TIMESTAMP)
-as returned by the `event-start' and `event-end' functions."
- (nth 3 position))
-
-
-;;;; Obsolescent names for functions.
-
-(defalias 'dot 'point)
-(defalias 'dot-marker 'point-marker)
-(defalias 'dot-min 'point-min)
-(defalias 'dot-max 'point-max)
-(defalias 'window-dot 'window-point)
-(defalias 'set-window-dot 'set-window-point)
-(defalias 'read-input 'read-string)
-(defalias 'send-string 'process-send-string)
-(defalias 'send-region 'process-send-region)
-(defalias 'show-buffer 'set-window-buffer)
-(defalias 'buffer-flush-undo 'buffer-disable-undo)
-(defalias 'eval-current-buffer 'eval-buffer)
-(defalias 'compiled-function-p 'byte-code-function-p)
-(defalias 'define-function 'defalias)
-
-;; Some programs still use this as a function.
-(defun baud-rate ()
- "Obsolete function returning the value of the `baud-rate' variable.
-Please convert your programs to use the variable `baud-rate' directly."
- baud-rate)
-
-(defalias 'focus-frame 'ignore)
-(defalias 'unfocus-frame 'ignore)
-
-;;;; Alternate names for functions - these are not being phased out.
-
-(defalias 'string= 'string-equal)
-(defalias 'string< 'string-lessp)
-(defalias 'move-marker 'set-marker)
-(defalias 'not 'null)
-(defalias 'rplaca 'setcar)
-(defalias 'rplacd 'setcdr)
-(defalias 'beep 'ding) ;preserve lingual purity
-(defalias 'indent-to-column 'indent-to)
-(defalias 'backward-delete-char 'delete-backward-char)
-(defalias 'search-forward-regexp (symbol-function 're-search-forward))
-(defalias 'search-backward-regexp (symbol-function 're-search-backward))
-(defalias 'int-to-string 'number-to-string)
-(defalias 'set-match-data 'store-match-data)
-
-;;; Should this be an obsolete name? If you decide it should, you get
-;;; to go through all the sources and change them.
-(defalias 'string-to-int 'string-to-number)
-
-;;;; Hook manipulation functions.
-
-(defun make-local-hook (hook)
- "Make the hook HOOK local to the current buffer.
-When a hook is local, its local and global values
-work in concert: running the hook actually runs all the hook
-functions listed in *either* the local value *or* the global value
-of the hook variable.
-
-This function works by making `t' a member of the buffer-local value,
-which acts as a flag to run the hook functions in the default value as
-well. This works for all normal hooks, but does not work for most
-non-normal hooks yet. We will be changing the callers of non-normal
-hooks so that they can handle localness; this has to be done one by
-one.
-
-This function does nothing if HOOK is already local in the current
-buffer.
-
-Do not use `make-local-variable' to make a hook variable buffer-local."
- (if (local-variable-p hook)
- nil
- (or (boundp hook) (set hook nil))
- (make-local-variable hook)
- (set hook (list t))))
-
-(defun add-hook (hook function &optional append local)
- "Add to the value of HOOK the function FUNCTION.
-FUNCTION is not added if already present.
-FUNCTION is added (if necessary) at the beginning of the hook list
-unless the optional argument APPEND is non-nil, in which case
-FUNCTION is added at the end.
-
-The optional fourth argument, LOCAL, if non-nil, says to modify
-the hook's buffer-local value rather than its default value.
-This makes no difference if the hook is not buffer-local.
-To make a hook variable buffer-local, always use
-`make-local-hook', not `make-local-variable'.
-
-HOOK should be a symbol, and FUNCTION may be any valid function. If
-HOOK is void, it is first set to nil. If HOOK's value is a single
-function, it is changed to a list of functions."
- (or (boundp hook) (set hook nil))
- (or (default-boundp hook) (set-default hook nil))
- ;; If the hook value is a single function, turn it into a list.
- (let ((old (symbol-value hook)))
- (if (or (not (listp old)) (eq (car old) 'lambda))
- (set hook (list old))))
- (if (or local
- ;; Detect the case where make-local-variable was used on a hook
- ;; and do what we used to do.
- (and (local-variable-if-set-p hook)
- (not (memq t (symbol-value hook)))))
- ;; Alter the local value only.
- (or (if (consp function)
- (member function (symbol-value hook))
- (memq function (symbol-value hook)))
- (set hook
- (if append
- (append (symbol-value hook) (list function))
- (cons function (symbol-value hook)))))
- ;; Alter the global value (which is also the only value,
- ;; if the hook doesn't have a local value).
- (or (if (consp function)
- (member function (default-value hook))
- (memq function (default-value hook)))
- (set-default hook
- (if append
- (append (default-value hook) (list function))
- (cons function (default-value hook)))))))
-
-(defun remove-hook (hook function &optional local)
- "Remove from the value of HOOK the function FUNCTION.
-HOOK should be a symbol, and FUNCTION may be any valid function. If
-FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the
-list of hooks to run in HOOK, then nothing is done. See `add-hook'.
-
-The optional third argument, LOCAL, if non-nil, says to modify
-the hook's buffer-local value rather than its default value.
-This makes no difference if the hook is not buffer-local.
-To make a hook variable buffer-local, always use
-`make-local-hook', not `make-local-variable'."
- (if (or (not (boundp hook)) ;unbound symbol, or
- (not (default-boundp 'hook))
- (null (symbol-value hook)) ;value is nil, or
- (null function)) ;function is nil, then
- nil ;Do nothing.
- (if (or local
- ;; Detect the case where make-local-variable was used on a hook
- ;; and do what we used to do.
- (and (local-variable-p hook)
- (not (memq t (symbol-value hook)))))
- (let ((hook-value (symbol-value hook)))
- (if (consp hook-value)
- (if (member function hook-value)
- (setq hook-value (delete function (copy-sequence hook-value))))
- (if (equal hook-value function)
- (setq hook-value nil)))
- (set hook hook-value))
- (let ((hook-value (default-value hook)))
- (if (consp hook-value)
- (if (member function hook-value)
- (setq hook-value (delete function (copy-sequence hook-value))))
- (if (equal hook-value function)
- (setq hook-value nil)))
- (set-default hook hook-value)))))
-
-(defun add-to-list (list-var element)
- "Add to the value of LIST-VAR the element ELEMENT if it isn't there yet.
-The test for presence of ELEMENT is done with `equal'.
-If you want to use `add-to-list' on a variable that is not defined
-until a certain package is loaded, you should put the call to `add-to-list'
-into a hook function that will be run only after loading the package.
-`eval-after-load' provides one way to do this. In some cases
-other hooks, such as major mode hooks, can do the job."
- (or (member element (symbol-value list-var))
- (set list-var (cons element (symbol-value list-var)))))
-
-;;;; Specifying things to do after certain files are loaded.
-
-(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'.
-If FILE is already loaded, evaluate FORM right now.
-It does nothing if FORM is already on the list for FILE.
-FILE should be the name of a library, with no directory name."
- ;; Make sure there is an element for FILE.
- (or (assoc file after-load-alist)
- (setq after-load-alist (cons (list file) after-load-alist)))
- ;; Add FORM to the element if it isn't there.
- (let ((elt (assoc file after-load-alist)))
- (or (member form (cdr elt))
- (progn
- (nconc elt (list form))
- ;; If the file has been loaded already, run FORM right away.
- (and (assoc file load-history)
- (eval 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)))
-
-
-;;;; Input and display facilities.
-
-(defun read-quoted-char (&optional prompt)
- "Like `read-char', except that if the first character read is an octal
-digit, we read up to two more octal digits and return the character
-represented by the octal number consisting of those digits.
-Optional argument PROMPT specifies a string to use to prompt the user."
- (let ((message-log-max nil) (count 0) (code 0) char)
- (while (< count 3)
- (let ((inhibit-quit (zerop count))
- ;; Don't let C-h get the help message--only help function keys.
- (help-char nil)
- (help-form
- "Type the special character you want to use,
-or three octal digits representing its character code."))
- (and prompt (message "%s-" prompt))
- (setq char (read-char))
- (if inhibit-quit (setq quit-flag nil)))
- (cond ((null char))
- ((and (<= ?0 char) (<= char ?7))
- (setq code (+ (* code 8) (- char ?0))
- count (1+ count))
- (and prompt (setq prompt (message "%s %c" prompt char))))
- ((> count 0)
- (setq unread-command-events (list char) count 259))
- (t (setq code char count 259))))
- ;; Turn a meta-character into a character with the 0200 bit set.
- (logior (if (/= (logand code ?\M-\^@) 0) 128 0)
- (logand 255 code))))
-
-(defun force-mode-line-update (&optional all)
- "Force the mode-line of the current buffer to be redisplayed.
-With optional non-nil ALL, force redisplay of all mode-lines."
- (if all (save-excursion (set-buffer (other-buffer))))
- (set-buffer-modified-p (buffer-modified-p)))
-
-(defun momentary-string-display (string pos &optional exit-char message)
- "Momentarily display STRING in the buffer at POS.
-Display remains until next character is typed.
-If the char is EXIT-CHAR (optional third arg, default is SPC) it is swallowed;
-otherwise it is then available as input (as a command if nothing else).
-Display MESSAGE (optional fourth arg) in the echo area.
-If MESSAGE is nil, instructions to type EXIT-CHAR are displayed there."
- (or exit-char (setq exit-char ?\ ))
- (let ((buffer-read-only nil)
- ;; Don't modify the undo list at all.
- (buffer-undo-list t)
- (modified (buffer-modified-p))
- (name buffer-file-name)
- insert-end)
- (unwind-protect
- (progn
- (save-excursion
- (goto-char pos)
- ;; defeat file locking... don't try this at home, kids!
- (setq buffer-file-name nil)
- (insert-before-markers string)
- (setq insert-end (point))
- ;; If the message end is off screen, recenter now.
- (if (> (window-end) insert-end)
- (recenter (/ (window-height) 2)))
- ;; If that pushed message start off the screen,
- ;; scroll to start it at the top of the screen.
- (move-to-window-line 0)
- (if (> (point) pos)
- (progn
- (goto-char pos)
- (recenter 0))))
- (message (or message "Type %s to continue editing.")
- (single-key-description exit-char))
- (let ((char (read-event)))
- (or (eq char exit-char)
- (setq unread-command-events (list char)))))
- (if insert-end
- (save-excursion
- (delete-region pos insert-end)))
- (setq buffer-file-name name)
- (set-buffer-modified-p modified))))
-
-
-;;;; Miscellanea.
-
-;; A number of major modes set this locally.
-;; Give it a global value to avoid compiler warnings.
-(defvar font-lock-defaults nil)
-
-;; Avoid compiler warnings about this variable,
-;; which has a special meaning on certain system types.
-(defvar buffer-file-type nil
- "Non-nil if the visited file is a binary file.
-This variable is meaningful on MS-DOG and Windows NT.
-On those systems, it is automatically local in every buffer.
-On other systems, this variable is normally always nil.")
-
-;; This should probably be written in C (i.e., without using `walk-windows').
-(defun get-buffer-window-list (buffer &optional minibuf frame)
- "Return windows currently displaying BUFFER, or nil if none.
-See `walk-windows' for the meaning of MINIBUF and FRAME."
- (let ((buffer (if (bufferp buffer) buffer (get-buffer buffer))) windows)
- (walk-windows (function (lambda (window)
- (if (eq (window-buffer window) buffer)
- (setq windows (cons window windows)))))
- minibuf frame)
- windows))
-
-(defun ignore (&rest ignore)
- "Do nothing and return nil.
-This function accepts any number of arguments, but ignores them."
- (interactive)
- nil)
-
-(defun error (&rest args)
- "Signal an error, making error message by passing all args to `format'.
-In Emacs, the convention is that error messages start with a capital
-letter but *do not* end with a period. Please follow this convention
-for the sake of consistency."
- (while t
- (signal 'error (list (apply 'format args)))))
-
-(defalias 'user-original-login-name 'user-login-name)
-
-(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 handled as usual in the shell."
- (cond
- ((eq system-type 'vax-vms)
- (apply 'start-process name buffer args))
- ;; We used to use `exec' to replace the shell with the command,
- ;; but that failed to handle (...) and semicolon, etc.
- (t
- (start-process name buffer shell-file-name shell-command-switch
- (mapconcat 'identity args " ")))))
-
-(defmacro with-current-buffer (buffer &rest body)
- "Execute the forms in BODY with BUFFER as the current buffer.
-The value returned is the value of the last form in BODY.
-See also `with-temp-buffer'."
- `(save-current-buffer
- (set-buffer ,buffer)
- ,@body))
-
-(defmacro with-temp-file (file &rest forms)
- "Create a new buffer, evaluate FORMS there, and write the buffer to FILE.
-The value of the last form in FORMS is returned, like `progn'.
-See also `with-temp-buffer'."
- (let ((temp-file (make-symbol "temp-file"))
- (temp-buffer (make-symbol "temp-buffer")))
- `(let ((,temp-file ,file)
- (,temp-buffer
- (get-buffer-create (generate-new-buffer-name " *temp file*"))))
- (unwind-protect
- (prog1
- (with-current-buffer ,temp-buffer
- ,@forms)
- (with-current-buffer ,temp-buffer
- (widen)
- (write-region (point-min) (point-max) ,temp-file nil 0)))
- (and (buffer-name ,temp-buffer)
- (kill-buffer ,temp-buffer))))))
-
-(defmacro with-temp-buffer (&rest forms)
- "Create a temporary buffer, and evaluate FORMS there like `progn'.
-See also `with-temp-file' and `with-output-to-string'."
- (let ((temp-buffer (make-symbol "temp-buffer")))
- `(let ((,temp-buffer
- (get-buffer-create (generate-new-buffer-name " *temp*"))))
- (unwind-protect
- (with-current-buffer ,temp-buffer
- ,@forms)
- (and (buffer-name ,temp-buffer)
- (kill-buffer ,temp-buffer))))))
-
-(defmacro with-output-to-string (&rest body)
- "Execute BODY, return the text it sent to `standard-output', as a string."
- `(let ((standard-output
- (get-buffer-create (generate-new-buffer-name " *string-output*"))))
- (let ((standard-output standard-output))
- ,@body)
- (with-current-buffer standard-output
- (prog1
- (buffer-string)
- (kill-buffer nil)))))
-
-(defmacro combine-after-change-calls (&rest body)
- "Execute BODY, but don't call the after-change functions till the end.
-If BODY makes changes in the buffer, they are recorded
-and the functions on `after-change-functions' are called several times
-when BODY is finished.
-The return value is rthe value of the last form in BODY.
-
-If `before-change-functions' is non-nil, then calls to the after-change
-functions can't be deferred, so in that case this macro has no effect.
-
-Do not alter `after-change-functions' or `before-change-functions'
-in BODY."
- `(unwind-protect
- (let ((combine-after-change-calls t))
- . ,body)
- (combine-after-change-execute)))
-
-
-(defvar save-match-data-internal)
-
-;; We use save-match-data-internal as the local variable because
-;; that works ok in practice (people should not use that variable elsewhere).
-;; We used to use an uninterned symbol; the compiler handles that properly
-;; now, but it generates slower code.
-(defmacro save-match-data (&rest body)
- "Execute the BODY forms, restoring the global value of the match data."
- `(let ((save-match-data-internal (match-data)))
- (unwind-protect
- (progn ,@body)
- (store-match-data save-match-data-internal))))
-
-(defun match-string (num &optional string)
- "Return string of text matched by last search.
-NUM specifies which parenthesized expression in the last regexp.
- Value is nil if NUMth pair didn't match, or there were less than NUM pairs.
-Zero means the entire text matched by the whole regexp or whole string.
-STRING should be given if the last search was by `string-match' on STRING."
- (if (match-beginning num)
- (if string
- (substring string (match-beginning num) (match-end num))
- (buffer-substring (match-beginning num) (match-end num)))))
-
-(defun split-string (string &optional separators)
- "Splits STRING into substrings where there are matches for SEPARATORS.
-Each match for SEPARATORS is a splitting point.
-The substrings between the splitting points are made into a list
-which is returned.
-If SEPARATORS is absent, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
- (let ((rexp (or separators "[ \f\t\n\r\v]+"))
- (start 0)
- (list nil))
- (while (string-match rexp string start)
- (or (eq (match-beginning 0) 0)
- (setq list
- (cons (substring string start (match-beginning 0))
- list)))
- (setq start (match-end 0)))
- (or (eq start (length string))
- (setq list
- (cons (substring string start)
- list)))
- (nreverse list)))
-
-(defun shell-quote-argument (argument)
- "Quote an argument for passing as argument to an inferior shell."
- (if (eq system-type 'ms-dos)
- ;; MS-DOS shells don't have quoting, so don't do any.
- argument
- (if (eq system-type 'windows-nt)
- (concat "\"" argument "\"")
- ;; Quote everything except POSIX filename characters.
- ;; This should be safe enough even for really weird shells.
- (let ((result "") (start 0) end)
- (while (string-match "[^-0-9a-zA-Z_./]" argument start)
- (setq end (match-beginning 0)
- result (concat result (substring argument start end)
- "\\" (substring argument end (1+ end)))
- start (1+ end)))
- (concat result (substring argument start))))))
-
-(defun make-syntax-table (&optional oldtable)
- "Return a new syntax table.
-It inherits all letters and control characters from the standard
-syntax table; other characters are copied from the standard syntax table."
- (if oldtable
- (copy-syntax-table oldtable)
- (let ((table (copy-syntax-table))
- i)
- (setq i 0)
- (while (<= i 31)
- (aset table i nil)
- (setq i (1+ i)))
- (setq i ?A)
- (while (<= i ?Z)
- (aset table i nil)
- (setq i (1+ i)))
- (setq i ?a)
- (while (<= i ?z)
- (aset table i nil)
- (setq i (1+ i)))
- (setq i 128)
- (while (<= i 255)
- (aset table i nil)
- (setq i (1+ i)))
- table)))
-
-(defun global-set-key (key command)
- "Give KEY a global binding as COMMAND.
-COMMAND is a symbol naming an interactively-callable function.
-KEY is a key sequence (a string or vector of characters or event types).
-Non-ASCII characters with codes above 127 (such as ISO Latin-1)
-can be included if you use a vector.
-Note that if KEY has a local binding in the current buffer
-that local binding will continue to shadow any global binding."
- (interactive "KSet key globally: \nCSet key %s to command: ")
- (or (vectorp key) (stringp key)
- (signal 'wrong-type-argument (list 'arrayp key)))
- (define-key (current-global-map) key command)
- nil)
-
-(defun local-set-key (key command)
- "Give KEY a local binding as COMMAND.
-COMMAND is a symbol naming an interactively-callable function.
-KEY is a key sequence (a string or vector of characters or event types).
-Non-ASCII characters with codes above 127 (such as ISO Latin-1)
-can be included if you use a vector.
-The binding goes in the current buffer's local map,
-which in most cases is shared with all other buffers in the same major mode."
- (interactive "KSet key locally: \nCSet key %s locally to command: ")
- (let ((map (current-local-map)))
- (or map
- (use-local-map (setq map (make-sparse-keymap))))
- (or (vectorp key) (stringp key)
- (signal 'wrong-type-argument (list 'arrayp key)))
- (define-key map key command))
- nil)
-
-(defun global-unset-key (key)
- "Remove global binding of KEY.
-KEY is a string representing a sequence of keystrokes."
- (interactive "kUnset key globally: ")
- (global-set-key key nil))
-
-(defun local-unset-key (key)
- "Remove local binding of KEY.
-KEY is a string representing a sequence of keystrokes."
- (interactive "kUnset key locally: ")
- (if (current-local-map)
- (local-set-key key nil))
- nil)
-
-;; We put this here instead of in frame.el so that it's defined even on
-;; systems where frame.el isn't loaded.
-(defun frame-configuration-p (object)
- "Return non-nil if OBJECT seems to be a frame configuration.
-Any list whose car is `frame-configuration' is assumed to be a frame
-configuration."
- (and (consp object)
- (eq (car object) 'frame-configuration)))
-
-;; now in fns.c
-;(defun nth (n list)
-; "Returns the Nth element of LIST.
-;N counts from zero. If LIST is not that long, nil is returned."
-; (car (nthcdr n list)))
-;
-;(defun copy-alist (alist)
-; "Return a copy of ALIST.
-;This is a new alist which represents the same mapping
-;from objects to objects, but does not share the alist structure with ALIST.
-;The objects mapped (cars and cdrs of elements of the alist)
-;are shared, however."
-; (setq alist (copy-sequence alist))
-; (let ((tail alist))
-; (while tail
-; (if (consp (car tail))
-; (setcar tail (cons (car (car tail)) (cdr (car tail)))))
-; (setq tail (cdr tail))))
-; alist)
-
-;;; subr.el ends here
-
diff --git a/lisp/sun-curs.el b/lisp/sun-curs.el
deleted file mode 100644
index 4118bd74c7b..00000000000
--- a/lisp/sun-curs.el
+++ /dev/null
@@ -1,217 +0,0 @@
-;;; sun-curs.el --- cursor definitions for Sun windows
-
-;; Copyright (C) 1987 Free Software Foundation, Inc.
-
-;; Author: Jeff Peck <peck@sun.com>
-;; Keywords: hardware
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;;;
-;;; Added some more cursors and moved the hot spots
-;;; Cursor defined by 16 pairs of 16-bit numbers
-;;;
-;;; 9-dec-86 Jeff Peck, Sun Microsystems Inc. <peck@sun.com>
-
-(require 'cl)
-
-(defvar sc::cursors nil "List of known cursors")
-
-(defmacro defcursor (name x y string)
- (if (not (memq name sc::cursors))
- (setq sc::cursors (cons name sc::cursors)))
- (list 'defconst name (list 'vector x y string)))
-
-;;; push should be defined in common lisp, but if not use this:
-;(defmacro push (v l)
-; "The ITEM is evaluated and consed onto LIST, a list-valued atom"
-; (list 'setq l (list 'cons v l)))
-
-;;;
-;;; The standard default cursor
-;;;
-(defcursor sc:right-arrow 15 0
- (concat '(0 1 0 3 0 7 0 15 0 31 0 63 0 127 0 15
- 0 27 0 25 0 48 0 48 0 96 0 96 0 192 0 192)))
-
-;;(sc:set-cursor sc:right-arrow)
-
-(defcursor sc:fat-left-arrow 0 8
- (concat '(1 0 3 0 7 0 15 0 31 0 63 255 127 255 255 255
- 255 255 127 255 63 255 31 0 15 0 7 0 3 0 1 0)))
-
-(defcursor sc:box 8 8
- (concat '(15 252 8 4 8 4 8 4 8 4 8 4 8 4 8 4
- 8 132 8 4 8 4 8 4 8 4 8 4 8 4 15 252)))
-
-(defcursor sc:hourglass 8 8
- (concat "\177\376\100\002\040\014\032\070"
- "\017\360\007\340\003\300\001\200"
- "\001\200\002\100\005\040\010\020"
- "\021\210\043\304\107\342\177\376"))
-
-(defun sc:set-cursor (icon)
- "Change the Sun mouse cursor to ICON.
-If ICON is nil, switch to the system default cursor,
-Otherwise, ICON should be a vector or the name of a vector of [x y 32-chars]"
- (interactive "XIcon Name: ")
- (if (symbolp icon) (setq icon (symbol-value icon)))
- (sun-change-cursor-icon icon))
-
-(make-local-variable '*edit-icon*)
-(make-variable-buffer-local 'icon-edit)
-(setq-default icon-edit nil)
-(or (assq 'icon-edit minor-mode-alist)
- (push '(icon-edit " IconEdit") minor-mode-alist))
-
-(defun sc:edit-cursor (icon)
- "convert icon to rectangle, edit, and repack"
- (interactive "XIcon Name: ")
- (if (not icon) (setq icon (sc::menu-choose-cursor (selected-window) 1 1)))
- (if (symbolp icon) (setq icon (symbol-value icon)))
- (if (get-buffer "icon-edit") (kill-buffer "icon-edit"))
- (switch-to-buffer "icon-edit")
- (local-set-mouse '(text right) 'sc::menu-function)
- (local-set-mouse '(text left) '(sc::pic-ins-at-mouse 32))
- (local-set-mouse '(text middle) '(sc::pic-ins-at-mouse 64))
- (local-set-mouse '(text left middle) 'sc::hotspot)
- (sc::display-icon icon)
- (picture-mode)
- (setq icon-edit t) ; for mode line display
-)
-
-(defun sc::pic-ins-at-mouse (char)
- "Picture insert char at mouse location"
- (mouse-move-point *mouse-window* (min 15 *mouse-x*) (min 15 *mouse-y*))
- (move-to-column (1+ (min 15 (current-column))) t)
- (delete-char -1)
- (insert char)
- (sc::goto-hotspot))
-
-(defun sc::menu-function (window x y)
- (sun-menu-evaluate window (1+ x) y sc::menu))
-
-(defmenu sc::menu
- ("Cursor Menu")
- ("Pack & Use" sc::pack-buffer-to-cursor)
- ("Pack to Icon" sc::pack-buffer-to-icon
- (sc::menu-choose-cursor *menu-window* *menu-x* *menu-y*))
- ("New Icon" call-interactively 'sc::make-cursor)
- ("Edit Icon" sc:edit-cursor
- (sc::menu-choose-cursor *menu-window* *menu-x* *menu-y*))
- ("Set Cursor" sc:set-cursor
- (sc::menu-choose-cursor *menu-window* *menu-x* *menu-y*))
- ("Reset Cursor" sc:set-cursor nil)
- ("Help" sc::edit-icon-help-menu)
- ("Quit" sc::quit-edit)
- )
-
-(defun sc::quit-edit ()
- (interactive)
- (bury-buffer (current-buffer))
- (switch-to-buffer (other-buffer) 'no-record))
-
-(defun sc::make-cursor (symbol)
- (interactive "SIcon Name: ")
- (eval (list 'defcursor symbol 0 0 ""))
- (sc::pack-buffer-to-icon (symbol-value symbol)))
-
-(defmenu sc::edit-icon-help-menu
- ("Simple Icon Editor")
- ("Left => CLEAR")
- ("Middle => SET")
- ("L & M => HOTSPOT")
- ("Right => MENU"))
-
-(defun sc::edit-icon-help ()
- (message "Left=> CLEAR Middle=> SET Left+Middle=> HOTSPOT Right=> MENU"))
-
-(defun sc::pack-buffer-to-cursor ()
- (sc::pack-buffer-to-icon *edit-icon*)
- (sc:set-cursor *edit-icon*))
-
-(defun sc::menu-choose-cursor (window x y)
- "Presents a menu of cursor names, and returns one or nil"
- (let ((curs sc::cursors)
- (items))
- (while curs
- (push (sc::menu-item-for-cursor (car curs)) items)
- (setq curs (cdr curs)))
- (push (list "Choose Cursor") items)
- (setq menu (menu-create items))
- (sun-menu-evaluate window x y menu)))
-
-(defun sc::menu-item-for-cursor (cursor)
- "apply function to selected cursor"
- (list (symbol-name cursor) 'quote cursor))
-
-(defun sc::hotspot (window x y)
- (aset *edit-icon* 0 x)
- (aset *edit-icon* 1 y)
- (sc::goto-hotspot))
-
-(defun sc::goto-hotspot ()
- (goto-line (1+ (aref *edit-icon* 1)))
- (move-to-column (aref *edit-icon* 0)))
-
-(defun sc::display-icon (icon)
- (setq *edit-icon* (copy-sequence icon))
- (let ((string (aref *edit-icon* 2))
- (index 0))
- (while (< index 32)
- (let ((char (aref string index))
- (bit 128))
- (while (> bit 0)
- (insert (sc::char-at-bit char bit))
- (setq bit (lsh bit -1))))
- (if (eq 1 (% index 2)) (newline))
- (setq index (1+ index))))
- (sc::goto-hotspot))
-
-(defun sc::char-at-bit (char bit)
- (if (> (logand char bit) 0) "@" " "))
-
-(defun sc::pack-buffer-to-icon (icon)
- "Pack 16 x 16 field into icon string"
- (goto-char (point-min))
- (aset icon 0 (aref *edit-icon* 0))
- (aset icon 1 (aref *edit-icon* 1))
- (aset icon 2 (mapconcat 'sc::pack-one-line "1234567890123456" ""))
- (sc::goto-hotspot)
- )
-
-(defun sc::pack-one-line (dummy)
- (let* (char chr1 chr2)
- (setq char 0 chr1 (mapconcat 'sc::pack-one-char "12345678" "") chr1 char)
- (setq char 0 chr2 (mapconcat 'sc::pack-one-char "12345678" "") chr2 char)
- (forward-line 1)
- (concat (char-to-string chr1) (char-to-string chr2))
- ))
-
-(defun sc::pack-one-char (dummy)
- "pack following char into char, unless eolp"
- (if (or (eolp) (char-equal (following-char) 32))
- (setq char (lsh char 1))
- (setq char (1+ (lsh char 1))))
- (if (not (eolp))(forward-char)))
-
-(provide 'sm-cursors)
-
-;;; sun-curs.el ends here
diff --git a/lisp/sun-fns.el b/lisp/sun-fns.el
deleted file mode 100644
index 0dce106b845..00000000000
--- a/lisp/sun-fns.el
+++ /dev/null
@@ -1,642 +0,0 @@
-;;; sun-fns.el --- subroutines of Mouse handling for Sun windows
-
-;; Copyright (C) 1987 Free Software Foundation, Inc.
-
-;; Author: Jeff Peck <peck@sun.com>
-;; Keywords: hardware
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Submitted Mar. 1987, Jeff Peck
-;; Sun Microsystems Inc. <peck@sun.com>
-;; Conceived Nov. 1986, Stan Jefferson,
-;; Computer Science Lab, SRI International.
-;; GoodIdeas Feb. 1987, Steve Greenbaum
-;; & UpClicks Reasoning Systems, Inc.
-;;
-;;
-;; Functions for manipulating via the mouse and mouse-map definitions
-;; for accessing them. Also definitions of mouse menus.
-;; This file you should freely modify to reflect you personal tastes.
-;;
-;; First half of file defines functions to implement mouse commands,
-;; Don't delete any of those, just add what ever else you need.
-;; Second half of file defines mouse bindings, do whatever you want there.
-
-;;
-;; Mouse Functions.
-;;
-;; These functions follow the sun-mouse-handler convention of being called
-;; with three arguments: (window x-pos y-pos)
-;; This makes it easy for a mouse executed command to know where the mouse is.
-;; Use the macro "eval-in-window" to execute a function
-;; in a temporarily selected window.
-;;
-;; If you have a function that must be called with other arguments
-;; bind the mouse button to an s-exp that contains the necessary parameters.
-;; See "minibuffer" bindings for examples.
-;;
-
-;;; Code:
-
-(require 'sun-mouse)
-
-(defconst cursor-pause-milliseconds 300
- "*Number of milliseconds to display alternate cursor (usually the mark)")
-
-(defun indicate-region (&optional pause)
- "Bounce cursor to mark for cursor-pause-milliseconds and back again"
- (or pause (setq pause cursor-pause-milliseconds))
- (let ((point (point)))
- (goto-char (mark))
- (sit-for-millisecs pause)
- ;(update-display)
- ;(sleep-for-millisecs pause)
- (goto-char point)))
-
-
-;;;
-;;; Text buffer operations
-;;;
-(defun mouse-move-point (window x y)
- "Move point to mouse cursor."
- (select-window window)
- (move-to-loc x y)
- (if (memq last-command ; support the mouse-copy/delete/yank
- '(mouse-copy mouse-delete mouse-yank-move))
- (setq this-command 'mouse-yank-move))
- )
-
-(defun mouse-set-mark (window x y)
- "Set mark at mouse cursor."
- (eval-in-window window ;; use this to get the unwind protect
- (let ((point (point)))
- (move-to-loc x y)
- (set-mark (point))
- (goto-char point)
- (indicate-region)))
- )
-
-(defun mouse-set-mark-and-select (window x y)
- "Set mark at mouse cursor, and select that window."
- (select-window window)
- (mouse-set-mark window x y)
- )
-
-(defun mouse-set-mark-and-stuff (w x y)
- "Set mark at mouse cursor, and put region in stuff buffer."
- (mouse-set-mark-and-select w x y)
- (sun-select-region (region-beginning) (region-end)))
-
-;;;
-;;; Simple mouse dragging stuff: marking with button up
-;;;
-
-(defvar *mouse-drag-window* nil)
-(defvar *mouse-drag-x* -1)
-(defvar *mouse-drag-y* -1)
-
-(defun mouse-drag-move-point (window x y)
- "Move point to mouse cursor, and allow dragging."
- (mouse-move-point window x y)
- (setq *mouse-drag-window* window
- *mouse-drag-x* x
- *mouse-drag-y* y))
-
-(defun mouse-drag-set-mark-stuff (window x y)
- "The up click handler that goes with mouse-drag-move-point.
-If mouse is in same WINDOW but at different X or Y than when
-mouse-drag-move-point was last executed, set the mark at mouse
-and put the region in the stuff buffer."
- (if (and (eq *mouse-drag-window* window)
- (not (and (equal *mouse-drag-x* x)
- (equal *mouse-drag-y* y))))
- (mouse-set-mark-and-stuff window x y)
- (setq this-command last-command)) ; this was just an upclick no-op.
- )
-
-(defun mouse-select-or-drag-move-point (window x y)
- "Select window if not selected, otherwise do mouse-drag-move-point."
- (if (eq (selected-window) window)
- (mouse-drag-move-point window x y)
- (mouse-select-window window x y)))
-
-;;;
-;;; esoterica:
-;;;
-(defun mouse-exch-pt-and-mark (window x y)
- "Exchange point and mark."
- (select-window window)
- (exchange-point-and-mark)
- )
-
-(defun mouse-call-kbd-macro (window x y)
- "Invokes last keyboard macro at mouse cursor."
- (mouse-move-point window x y)
- (call-last-kbd-macro)
- )
-
-(defun mouse-mark-thing (window x y)
- "Set point and mark to text object using syntax table.
-The resulting region is put in the sun-window stuff buffer.
-Left or right Paren syntax marks an s-expression.
-Clicking at the end of a line marks the line including a trailing newline.
-If it doesn't recognize one of these it marks the character at point."
- (mouse-move-point window x y)
- (if (eobp) (open-line 1))
- (let* ((char (char-after (point)))
- (syntax (char-syntax char)))
- (cond
- ((eq syntax ?w) ; word.
- (forward-word 1)
- (set-mark (point))
- (forward-word -1))
- ;; try to include a single following whitespace (is this a good idea?)
- ;; No, not a good idea since inconsistent.
- ;;(if (eq (char-syntax (char-after (mark))) ?\ )
- ;; (set-mark (1+ (mark))))
- ((eq syntax ?\( ) ; open paren.
- (mark-sexp 1))
- ((eq syntax ?\) ) ; close paren.
- (forward-char 1)
- (mark-sexp -1)
- (exchange-point-and-mark))
- ((eolp) ; mark line if at end.
- (set-mark (1+ (point)))
- (beginning-of-line 1))
- (t ; mark character
- (set-mark (1+ (point)))))
- (indicate-region)) ; display region boundary.
- (sun-select-region (region-beginning) (region-end))
- )
-
-(defun mouse-kill-thing (window x y)
- "Kill thing at mouse, and put point there."
- (mouse-mark-thing window x y)
- (kill-region-and-unmark (region-beginning) (region-end))
- )
-
-(defun mouse-kill-thing-there (window x y)
- "Kill thing at mouse, leave point where it was.
-See mouse-mark-thing for a description of the objects recognized."
- (eval-in-window window
- (save-excursion
- (mouse-mark-thing window x y)
- (kill-region (region-beginning) (region-end))))
- )
-
-(defun mouse-save-thing (window x y &optional quiet)
- "Put thing at mouse in kill ring.
-See mouse-mark-thing for a description of the objects recognized."
- (mouse-mark-thing window x y)
- (copy-region-as-kill (region-beginning) (region-end))
- (if (not quiet) (message "Thing saved"))
- )
-
-(defun mouse-save-thing-there (window x y &optional quiet)
- "Put thing at mouse in kill ring, leave point as is.
-See mouse-mark-thing for a description of the objects recognized."
- (eval-in-window window
- (save-excursion
- (mouse-save-thing window x y quiet))))
-
-;;;
-;;; Mouse yanking...
-;;;
-(defun mouse-copy-thing (window x y)
- "Put thing at mouse in kill ring, yank to point.
-See mouse-mark-thing for a description of the objects recognized."
- (setq last-command 'not-kill) ;Avoids appending to previous kills.
- (mouse-save-thing-there window x y t)
- (yank)
- (setq this-command 'yank))
-
-(defun mouse-move-thing (window x y)
- "Kill thing at mouse, yank it to point.
-See mouse-mark-thing for a description of the objects recognized."
- (setq last-command 'not-kill) ;Avoids appending to previous kills.
- (mouse-kill-thing-there window x y)
- (yank)
- (setq this-command 'yank))
-
-(defun mouse-yank-at-point (&optional window x y)
- "Yank from kill-ring at point; then cycle thru kill ring."
- (if (eq last-command 'yank)
- (let ((before (< (point) (mark))))
- (delete-region (point) (mark))
- (insert (current-kill 1))
- (if before (exchange-point-and-mark)))
- (yank))
- (setq this-command 'yank))
-
-(defun mouse-yank-at-mouse (window x y)
- "Yank from kill-ring at mouse; then cycle thru kill ring."
- (mouse-move-point window x y)
- (mouse-yank-at-point window x y))
-
-(defun mouse-save/delete/yank (&optional window x y)
- "Context sensitive save/delete/yank.
-Consecutive clicks perform as follows:
- * first click saves region to kill ring,
- * second click kills region,
- * third click yanks from kill ring,
- * subsequent clicks cycle thru kill ring.
-If mouse-move-point is performed after the first or second click,
-the next click will do a yank, etc. Except for a possible mouse-move-point,
-this command is insensitive to mouse location."
- (cond
- ((memq last-command '(mouse-delete yank mouse-yank-move)) ; third+ click
- (mouse-yank-at-point))
- ((eq last-command 'mouse-copy) ; second click
- (kill-region (region-beginning) (region-end))
- (setq this-command 'mouse-delete))
- (t ; first click
- (copy-region-as-kill (region-beginning) (region-end))
- (message "Region saved")
- (setq this-command 'mouse-copy))
- ))
-
-
-(defun mouse-split-horizontally (window x y)
- "Splits the window horizontally at mouse cursor."
- (eval-in-window window (split-window-horizontally (1+ x))))
-
-(defun mouse-split-vertically (window x y)
- "Split the window vertically at the mouse cursor."
- (eval-in-window window (split-window-vertically (1+ y))))
-
-(defun mouse-select-window (window x y)
- "Selects the window, restoring point."
- (select-window window))
-
-(defun mouse-delete-other-windows (window x y)
- "Deletes all windows except the one mouse is in."
- (delete-other-windows window))
-
-(defun mouse-delete-window (window x y)
- "Deletes the window mouse is in."
- (delete-window window))
-
-(defun mouse-undo (window x y)
- "Invokes undo in the window mouse is in."
- (eval-in-window window (undo)))
-
-;;;
-;;; Scroll operations
-;;;
-
-;;; The move-to-window-line is used below because otherwise
-;;; scrolling a non-selected process window with the mouse, after
-;;; the process has written text past the bottom of the window,
-;;; gives an "End of buffer" error, and then scrolls. The
-;;; move-to-window-line seems to force recomputing where things are.
-(defun mouse-scroll-up (window x y)
- "Scrolls the window upward."
- (eval-in-window window (move-to-window-line 1) (scroll-up nil)))
-
-(defun mouse-scroll-down (window x y)
- "Scrolls the window downward."
- (eval-in-window window (scroll-down nil)))
-
-(defun mouse-scroll-proportional (window x y)
- "Scrolls the window proportionally corresponding to window
-relative X divided by window width."
- (eval-in-window window
- (if (>= x (1- (window-width)))
- ;; When x is maximum (equal to or 1 less than window width),
- ;; goto end of buffer. We check for this special case
- ;; because the calculated goto-char often goes short of the
- ;; end due to roundoff error, and we often really want to go
- ;; to the end.
- (goto-char (point-max))
- (progn
- (goto-char (+ (point-min) ; For narrowed regions.
- (* x (/ (- (point-max) (point-min))
- (1- (window-width))))))
- (beginning-of-line))
- )
- (what-cursor-position) ; Report position.
- ))
-
-(defun mouse-line-to-top (window x y)
- "Scrolls the line at the mouse cursor up to the top."
- (eval-in-window window (scroll-up y)))
-
-(defun mouse-top-to-line (window x y)
- "Scrolls the top line down to the mouse cursor."
- (eval-in-window window (scroll-down y)))
-
-(defun mouse-line-to-bottom (window x y)
- "Scrolls the line at the mouse cursor to the bottom."
- (eval-in-window window (scroll-up (+ y (- 2 (window-height))))))
-
-(defun mouse-bottom-to-line (window x y)
- "Scrolls the bottom line up to the mouse cursor."
- (eval-in-window window (scroll-down (+ y (- 2 (window-height))))))
-
-(defun mouse-line-to-middle (window x y)
- "Scrolls the line at the mouse cursor to the middle."
- (eval-in-window window (scroll-up (- y -1 (/ (window-height) 2)))))
-
-(defun mouse-middle-to-line (window x y)
- "Scrolls the line at the middle to the mouse cursor."
- (eval-in-window window (scroll-up (- (/ (window-height) 2) y 1))))
-
-
-;;;
-;;; main emacs menu.
-;;;
-(defmenu expand-menu
- ("Vertically" mouse-expand-vertically *menu-window*)
- ("Horizontally" mouse-expand-horizontally *menu-window*))
-
-(defmenu delete-window-menu
- ("This One" delete-window *menu-window*)
- ("All Others" delete-other-windows *menu-window*))
-
-(defmenu mouse-help-menu
- ("Text Region"
- mouse-help-region *menu-window* *menu-x* *menu-y* 'text)
- ("Scrollbar"
- mouse-help-region *menu-window* *menu-x* *menu-y* 'scrollbar)
- ("Modeline"
- mouse-help-region *menu-window* *menu-x* *menu-y* 'modeline)
- ("Minibuffer"
- mouse-help-region *menu-window* *menu-x* *menu-y* 'minibuffer)
- )
-
-(defmenu emacs-quit-menu
- ("Suspend" suspend-emacstool)
- ("Quit" save-buffers-kill-emacs))
-
-(defmenu emacs-menu
- ("Emacs Menu")
- ("Stuff Selection" sun-yank-selection)
- ("Expand" . expand-menu)
- ("Delete Window" . delete-window-menu)
- ("Previous Buffer" mouse-select-previous-buffer *menu-window*)
- ("Save Buffers" save-some-buffers)
- ("List Directory" list-directory nil)
- ("Dired" dired nil)
- ("Mouse Help" . mouse-help-menu)
- ("Quit" . emacs-quit-menu))
-
-(defun emacs-menu-eval (window x y)
- "Pop-up menu of editor commands."
- (sun-menu-evaluate window (1+ x) (1- y) 'emacs-menu))
-
-(defun mouse-expand-horizontally (window)
- (eval-in-window window
- (enlarge-window 4 t)
- (update-display) ; Try to redisplay, since can get confused.
- ))
-
-(defun mouse-expand-vertically (window)
- (eval-in-window window (enlarge-window 4)))
-
-(defun mouse-select-previous-buffer (window)
- "Switch buffer in mouse window to most recently selected buffer."
- (eval-in-window window (switch-to-buffer (other-buffer))))
-
-;;;
-;;; minibuffer menu
-;;;
-(defmenu minibuffer-menu
- ("Minibuffer" message "Just some miscellaneous minibuffer commands")
- ("Stuff" sun-yank-selection)
- ("Do-It" exit-minibuffer)
- ("Abort" abort-recursive-edit)
- ("Suspend" suspend-emacs))
-
-(defun minibuffer-menu-eval (window x y)
- "Pop-up menu of commands."
- (sun-menu-evaluate window x (1- y) 'minibuffer-menu))
-
-(defun mini-move-point (window x y)
- ;; -6 is good for most common cases
- (mouse-move-point window (- x 6) 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))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Buffer-mode Mouse commands
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(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))
- )
-
-(defun mouse-buffer-select (w x y)
- "Put the indicated buffer in selected window."
- (switch-to-buffer (Buffer-at-mouse w x y))
- (list-buffers)
- )
-
-(defun mouse-buffer-delete (w x y)
- "mark indicated buffer for delete"
- (save-window-excursion
- (mouse-move-point w x y)
- (Buffer-menu-delete)
- ))
-
-(defun mouse-buffer-execute (w x y)
- "execute buffer-menu selections"
- (save-window-excursion
- (mouse-move-point w x y)
- (Buffer-menu-execute)
- ))
-
-(defun enable-mouse-in-buffer-list ()
- "Call this to enable mouse selections in *Buffer List*
- LEFT puts the indicated buffer in the selected window.
- MIDDLE buries the indicated buffer.
- 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)
- )
- )
-
-
-;;;*******************************************************************
-;;;
-;;; Global Mouse Bindings.
-;;;
-;;; There is some sense to this mouse binding madness:
-;;; LEFT and RIGHT scrolls are inverses.
-;;; SHIFT makes an opposite meaning in the scroll bar.
-;;; SHIFT is an alternative to DOUBLE (but double chords do not exist).
-;;; META makes the scrollbar functions work in the text region.
-;;; MIDDLE operates the mark
-;;; LEFT operates at point
-
-;;; META commands are generally non-destructive,
-;;; SHIFT is a little more dangerous.
-;;; CONTROL is for the really complicated ones.
-
-;;; CONTROL-META-SHIFT-RIGHT gives help on that region.
-
-;;;
-;;; Text Region mousemap
-;;;
-;; The basics: Point, Mark, Menu, Sun-Select:
-(global-set-mouse '(text left) 'mouse-drag-move-point)
-(global-set-mouse '(text up left) 'mouse-drag-set-mark-stuff)
-(global-set-mouse '(text shift left) 'mouse-exch-pt-and-mark)
-(global-set-mouse '(text double left) 'mouse-exch-pt-and-mark)
-
-(global-set-mouse '(text middle) 'mouse-set-mark-and-stuff)
-
-(global-set-mouse '(text right) 'emacs-menu-eval)
-(global-set-mouse '(text shift right) '(sun-yank-selection))
-(global-set-mouse '(text double right) '(sun-yank-selection))
-
-;; The Slymoblics multi-command for Save, Kill, Copy, Move:
-(global-set-mouse '(text shift middle) 'mouse-save/delete/yank)
-(global-set-mouse '(text double middle) 'mouse-save/delete/yank)
-
-;; Save, Kill, Copy, Move Things:
-;; control-left composes with control middle/right to produce copy/move
-(global-set-mouse '(text control middle ) 'mouse-save-thing-there)
-(global-set-mouse '(text control right ) 'mouse-kill-thing-there)
-(global-set-mouse '(text control left) 'mouse-yank-at-point)
-(global-set-mouse '(text control middle left) 'mouse-copy-thing)
-(global-set-mouse '(text control right left) 'mouse-move-thing)
-(global-set-mouse '(text control right middle) 'mouse-mark-thing)
-
-;; The Universal mouse help command (press all buttons):
-(global-set-mouse '(text shift control meta right) 'mouse-help-region)
-(global-set-mouse '(text double control meta right) 'mouse-help-region)
-
-;;; Meta in Text Region is like meta version in scrollbar:
-(global-set-mouse '(text meta left) 'mouse-line-to-top)
-(global-set-mouse '(text meta shift left) 'mouse-line-to-bottom)
-(global-set-mouse '(text meta double left) 'mouse-line-to-bottom)
-(global-set-mouse '(text meta middle) 'mouse-line-to-middle)
-(global-set-mouse '(text meta shift middle) 'mouse-middle-to-line)
-(global-set-mouse '(text meta double middle) 'mouse-middle-to-line)
-(global-set-mouse '(text meta control middle) 'mouse-split-vertically)
-(global-set-mouse '(text meta right) 'mouse-top-to-line)
-(global-set-mouse '(text meta shift right) 'mouse-bottom-to-line)
-(global-set-mouse '(text meta double right) 'mouse-bottom-to-line)
-
-;; Miscellaneous:
-(global-set-mouse '(text meta control left) 'mouse-call-kbd-macro)
-(global-set-mouse '(text meta control right) 'mouse-undo)
-
-;;;
-;;; Scrollbar mousemap.
-;;; Are available in the Scrollbar Region, or with Meta Text (or Meta Scrollbar)
-;;;
-(global-set-mouse '(scrollbar left) 'mouse-line-to-top)
-(global-set-mouse '(scrollbar shift left) 'mouse-line-to-bottom)
-(global-set-mouse '(scrollbar double left) 'mouse-line-to-bottom)
-
-(global-set-mouse '(scrollbar middle) 'mouse-line-to-middle)
-(global-set-mouse '(scrollbar shift middle) 'mouse-middle-to-line)
-(global-set-mouse '(scrollbar double middle) 'mouse-middle-to-line)
-(global-set-mouse '(scrollbar control middle) 'mouse-split-vertically)
-
-(global-set-mouse '(scrollbar right) 'mouse-top-to-line)
-(global-set-mouse '(scrollbar shift right) 'mouse-bottom-to-line)
-(global-set-mouse '(scrollbar double right) 'mouse-bottom-to-line)
-
-(global-set-mouse '(scrollbar meta left) 'mouse-line-to-top)
-(global-set-mouse '(scrollbar meta shift left) 'mouse-line-to-bottom)
-(global-set-mouse '(scrollbar meta double left) 'mouse-line-to-bottom)
-(global-set-mouse '(scrollbar meta middle) 'mouse-line-to-middle)
-(global-set-mouse '(scrollbar meta shift middle) 'mouse-middle-to-line)
-(global-set-mouse '(scrollbar meta double middle) 'mouse-middle-to-line)
-(global-set-mouse '(scrollbar meta control middle) 'mouse-split-vertically)
-(global-set-mouse '(scrollbar meta right) 'mouse-top-to-line)
-(global-set-mouse '(scrollbar meta shift right) 'mouse-bottom-to-line)
-(global-set-mouse '(scrollbar meta double right) 'mouse-bottom-to-line)
-
-;; And the help menu:
-(global-set-mouse '(scrollbar shift control meta right) 'mouse-help-region)
-(global-set-mouse '(scrollbar double control meta right) 'mouse-help-region)
-
-;;;
-;;; Modeline mousemap.
-;;;
-;;; 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 middle) 'mouse-scroll-proportional)
-(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)
-
-;;; control-left selects this window, control-right deletes it.
-(global-set-mouse '(modeline control left) 'mouse-delete-other-windows)
-(global-set-mouse '(modeline control right) 'mouse-delete-window)
-
-;; in case of confusion, just select it:
-(global-set-mouse '(modeline control left right)'mouse-select-window)
-
-;; even without confusion (and without the keyboard) select it:
-(global-set-mouse '(modeline left right) 'mouse-select-window)
-
-;; And the help menu:
-(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:
-;;;
-(global-set-mouse '(minibuffer left) 'mini-move-point)
-
-(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 control middle) '(next-complex-command 1))
-(global-set-mouse '(minibuffer meta middle) '(previous-complex-command 1))
-
-(global-set-mouse '(minibuffer right) 'minibuffer-menu-eval)
-
-(global-set-mouse '(minibuffer shift control meta right) 'mouse-help-region)
-(global-set-mouse '(minibuffer double control meta right) 'mouse-help-region)
-
-(provide 'sun-fns)
-
-;;; sun-fns.el ends here
diff --git a/lisp/tabify.el b/lisp/tabify.el
deleted file mode 100644
index c5d76fcc211..00000000000
--- a/lisp/tabify.el
+++ /dev/null
@@ -1,75 +0,0 @@
-;;; tabify.el --- tab conversion commands for Emacs
-
-;; Copyright (C) 1985, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Commands to optimize spaces to tabs or expand tabs to spaces in a region
-;; (`tabify' and `untabify'). The variable tab-width does the obvious.
-
-;;; Code:
-
-;;;###autoload
-(defun untabify (start end)
- "Convert all tabs in region to multiple spaces, preserving columns.
-Called non-interactively, the region is specified by arguments
-START and END, rather than by the position of point and mark.
-The variable `tab-width' controls the spacing of tab stops."
- (interactive "r")
- (save-excursion
- (save-restriction
- (narrow-to-region (point-min) end)
- (goto-char start)
- (while (search-forward "\t" nil t) ; faster than re-search
- (let ((tab-beg (point))
- (column (current-column))
- (indent-tabs-mode nil))
- (skip-chars-backward "\t" start)
- (delete-region tab-beg (point))
- (indent-to column))))))
-
-;;;###autoload
-(defun tabify (start end)
- "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.
-Called non-interactively, the region is specified by arguments
-START and END, rather than by the position of point and mark.
-The variable `tab-width' controls the spacing of tab stops."
- (interactive "r")
- (save-excursion
- (save-restriction
- ;; Include the beginning of the line in the narrowing
- ;; since otherwise it will throw off current-column.
- (goto-char start)
- (beginning-of-line)
- (narrow-to-region (point) end)
- (goto-char start)
- (while (re-search-forward "[ \t][ \t][ \t]*" nil t)
- (let ((column (current-column))
- (indent-tabs-mode t))
- (delete-region (match-beginning 0) (point))
- (indent-to column))))))
-
-(provide 'tabify)
-
-;;; tabify.el ends here
diff --git a/lisp/talk.el b/lisp/talk.el
deleted file mode 100644
index 0baedeb301e..00000000000
--- a/lisp/talk.el
+++ /dev/null
@@ -1,101 +0,0 @@
-;;; talk.el --- Allow several users to talk to each other through Emacs.
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Keywords: comm, frames
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This is a multi-user talk package that runs in Emacs.
-;; Use talk-connect to bring a new person into the conversation.
-
-;;; Code:
-
-(defvar talk-display-alist nil
- "Alist of displays on which Emacs talk is now running.
-Each element has the form (DISPLAY FRAME BUFFER).")
-
-;;;###autoload
-(defun talk-connect (display)
- "Connect to display DISPLAY for the Emacs talk group."
- (interactive "sTalk to display: ")
- ;; Make sure we have an entry for the current display.
- (let ((mydisp (cdr (assq 'display (frame-parameters (selected-frame))))))
- (talk-add-display mydisp))
- ;; Make sure we have an entry for the specified display.
- (talk-add-display display)
- ;; Add the new buffers to all talk frames.
- (talk-update-buffers))
-
-(defun talk-add-display (display)
- (let* ((elt (assoc display talk-display-alist))
- (name (concat "*talk-" display "*"))
- buffer frame)
- (if (not (and elt (frame-live-p (setq frame (nth 1 elt)))))
- (setq frame (make-frame-on-display display (list (cons 'name name)))))
- (if (not (and elt (buffer-name (get-buffer (setq buffer (nth 2 elt))))))
- (setq buffer (get-buffer-create name)))
- (setq talk-display-alist
- (cons (list display frame buffer) (delq elt talk-display-alist)))))
-
-(defun talk-disconnect ()
- "Disconnect this display from the Emacs talk group."
- (interactive)
- (let* ((mydisp (cdr (assq 'display (frame-parameters (selected-frame)))))
- (elt (assoc mydisp talk-display-alist)))
- (delete-frame (nth 1 elt))
- (kill-buffer (nth 2 elt))
- (setq talk-display-alist (delq elt talk-display-alist))
- (talk-update-buffers)))
-
-(defun talk-update-buffers ()
- "Update all the talk frames so that each shows all the talk buffers."
- (let ((tail talk-display-alist))
- (while tail
- (let ((frame (nth 1 (car tail)))
- (this-buffer (nth 2 (car tail)))
- (buffers
- (mapcar (function (lambda (elt) (nth 2 elt)))
- talk-display-alist)))
- ;; Put this display's own talk buffer
- ;; at the front of the list.
- (setq buffers (cons this-buffer (delq this-buffer buffers)))
- (talk-split-up-frame frame buffers))
- (setq tail (cdr tail)))))
-
-(defun talk-split-up-frame (frame buffers)
- "Split FRAME into equal-sized windows displaying the buffers in BUFFERS.
-Select the first of these windows, displaying the first of the buffers."
- (let ((lines-per-buffer (/ (frame-height frame) (length buffers)))
- (old-frame (selected-frame)))
- (unwind-protect
- (progn
- (select-frame frame)
- (select-window (frame-first-window frame))
- (delete-other-windows)
- (while (progn
- (switch-to-buffer (car buffers))
- (setq buffers (cdr buffers)))
- (split-window-vertically lines-per-buffer)
- (other-window 1))
- (select-window (frame-first-window frame)))
- (select-frame old-frame))))
-
-;;; talk.el ends here
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
deleted file mode 100644
index 5776680d6cb..00000000000
--- a/lisp/tar-mode.el
+++ /dev/null
@@ -1,1207 +0,0 @@
-;;; tar-mode.el --- simple editing of tar files from GNU emacs
-
-;; Copyright (C) 1990, 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Jamie Zawinski <jwz@lucid.com>
-;; Created: 04 Apr 1990
-;; Keywords: unix
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; 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.
-
-;; 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 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.
-
-;; Rationale:
-
-;; Why does tar-mode edit the file itself instead of using tar?
-
-;; That means that you can edit tar files which you don't have room for
-;; on your local disk.
-
-;; I don't know about recent features in gnu tar, but old versions of tar
-;; can't replace a file in the middle of a tar file with a new version.
-;; Tar-mode can. I don't think tar can do things like chmod the subfiles.
-;; An implementation which involved unpacking and repacking the file into
-;; some scratch directory would be very wasteful, and wouldn't be able to
-;; preserve the file owners.
-
-;;; Code:
-
-(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
- "*Non-nil means 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.")
-
-(defvar tar-mode-show-date nil
- "*Non-nil means Tar mode should show the date/time of each subfile.
-This information is useful, but it takes screen space away from file names.")
-
-(defvar tar-parse-info nil)
-(defvar tar-header-offset nil)
-(defvar tar-superior-buffer nil)
-(defvar tar-superior-descriptor nil)
-(defvar tar-subfile-mode nil)
-
-(put 'tar-parse-info 'permanent-local t)
-(put 'tar-header-offset 'permanent-local t)
-(put 'tar-superior-buffer 'permanent-local t)
-(put 'tar-superior-descriptor 'permanent-local t)
-
-;;; 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 tar-header-block-tokenize (string)
- "Return a `tar-header' structure.
-This is 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-long-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)
- (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) ?0)))
- start (1+ start)))
- n)))
-
-(defun tar-parse-octal-long-integer (string &optional start end)
- (if (null start) (setq start 0))
- (if (null end) (setq end (length string)))
- (if (= (aref string start) 0)
- (list 0 0)
- (let ((lo 0)
- (hi 0))
- (while (< start end)
- (if (>= (aref string start) ?0)
- (setq lo (+ (* lo 8) (- (aref string start) ?0))
- hi (+ (* hi 8) (ash lo -16))
- lo (logand lo 65535)))
- (setq start (1+ start)))
- (list hi lo))))
-
-(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 tar-header-block-checksum (string)
- "Compute and return 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 tar-header-block-check-checksum (hblock desired-checksum file-name)
- "Beep and print a warning if the checksum doesn't match."
- (if (not (= desired-checksum (tar-header-block-checksum hblock)))
- (progn (beep) (message "Invalid checksum for file %s!" file-name))))
-
-(defun tar-header-block-recompute-checksum (hblock)
- "Modifies the given string to have a valid checksum field."
- (let* ((chk (tar-header-block-checksum 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-clip-time-string (time)
- (let ((str (current-time-string time)))
- (concat (substring str 4 16) (substring str 19 24))))
-
-(defun tar-grind-file-mode (mode string start)
- "Store `-rw--r--r--' indicating MODE into STRING beginning at START.
-MODE should be an integer which is a file mode value."
- (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 tar-header-block-summarize (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 (if tar-mode-show-date 18 0))
- (slash (1- (+ left namew)))
- (lastdigit (+ slash groupw sizew))
- (datestart (+ lastdigit 2))
- (namestart (+ datestart 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))
- (setq time (tar-clip-time-string time))
- (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))))
- (if tar-mode-show-date
- (tar-dotimes (i (length time)) (aset string (+ datestart i) (aref time i))))
- (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)))))
- (put-text-property namestart (length string)
- 'mouse-face 'highlight string)
- string)))
-
-
-(defun tar-summarize-buffer ()
- "Parse the contents of the tar file in the current buffer.
-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)
- (while (and (<= (+ pos 512) (point-max))
- (not (eq 'empty-tar-block
- (setq tokens
- (tar-header-block-tokenize
- (buffer-substring pos (+ pos 512)))))))
- (setq pos (+ pos 512))
- (message "Parsing tar file...%d%%"
- ;(/ (* pos 100) bs) ; this gets round-off lossage
- (/ pos bs100) ; this doesn't
- )
- (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....
- ;(tar-header-block-check-checksum
- ; hblock (tar-header-block-checksum hblock)
- ; (tar-header-name tokens))
-
- (setq result (cons (make-tar-desc pos tokens) result))
-
- (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))
- ;; A tar file should end with a block or two of nulls,
- ;; but let's not get a fatal error if it doesn't.
- (if (eq tokens 'empty-tar-block)
- (message "Parsing tar file...done")
- (message "Warning: premature EOF parsing tar file")))
- (save-excursion
- (goto-char (point-min))
- (let ((buffer-read-only nil)
- (summaries nil))
- ;; Collect summary lines and insert them all at once since tar files
- ;; can be pretty big.
- (tar-dolist (tar-desc (reverse tar-parse-info))
- (setq summaries
- (cons (tar-header-block-summarize (tar-desc-tokens tar-desc))
- (cons "\n"
- summaries))))
- (insert (apply 'concat summaries))
- (make-local-variable 'tar-header-offset)
- (setq tar-header-offset (point))
- (narrow-to-region 1 tar-header-offset)
- (set-buffer-modified-p nil))))
-
-(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 "\C-m" 'tar-extract)
- (define-key tar-mode-map [mouse-2] 'tar-mouse-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 [down] 'tar-next-line)
- (define-key tar-mode-map "o" 'tar-extract-other-window)
- (define-key tar-mode-map "p" 'tar-previous-line)
- (define-key tar-mode-map "\^P" 'tar-previous-line)
- (define-key tar-mode-map [up] '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)
- )
-
-;; Make menu bar items.
-
-;; Get rid of the Edit menu bar item to save space.
-(define-key tar-mode-map [menu-bar edit] 'undefined)
-
-(define-key tar-mode-map [menu-bar immediate]
- (cons "Immediate" (make-sparse-keymap "Immediate")))
-
-(define-key tar-mode-map [menu-bar immediate view]
- '("View This File" . tar-view))
-(define-key tar-mode-map [menu-bar immediate display]
- '("Display in Other Window" . tar-display-other-file))
-(define-key tar-mode-map [menu-bar immediate find-file-other-window]
- '("Find in Other Window" . tar-extract-other-window))
-(define-key tar-mode-map [menu-bar immediate find-file]
- '("Find This File" . tar-extract))
-
-(define-key tar-mode-map [menu-bar mark]
- (cons "Mark" (make-sparse-keymap "Mark")))
-
-(define-key tar-mode-map [menu-bar mark unmark-all]
- '("Unmark All" . tar-clear-modification-flags))
-(define-key tar-mode-map [menu-bar mark deletion]
- '("Flag" . tar-flag-deleted))
-(define-key tar-mode-map [menu-bar mark unmark]
- '("Unflag" . tar-unflag))
-
-(define-key tar-mode-map [menu-bar operate]
- (cons "Operate" (make-sparse-keymap "Operate")))
-
-(define-key tar-mode-map [menu-bar operate chown]
- '("Change Owner..." . tar-chown-entry))
-(define-key tar-mode-map [menu-bar operate chgrp]
- '("Change Group..." . tar-chgrp-entry))
-(define-key tar-mode-map [menu-bar operate chmod]
- '("Change Mode..." . tar-chmod-entry))
-(define-key tar-mode-map [menu-bar operate rename]
- '("Rename to..." . tar-rename-entry))
-(define-key tar-mode-map [menu-bar operate copy]
- '("Copy to..." . tar-copy))
-(define-key tar-mode-map [menu-bar operate expunge]
- '("Expunge Marked Files" . tar-expunge))
-
-;; tar mode is suitable only for specially formatted data.
-(put 'tar-mode 'mode-class 'special)
-(put 'tar-subfile-mode 'mode-class 'special)
-
-;;;###autoload
-(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;
-or click mouse-2 on the file's line in the Tar mode 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.
- ;; rms: with permanent locals, it should now be possible to make this work
- ;; interactively in some reasonable fashion.
- (kill-all-local-variables)
- (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)
- (make-local-variable 'enable-local-variables)
- (setq enable-local-variables nil)
- (make-local-variable 'next-line-add-newlines)
- (setq next-line-add-newlines nil)
- (setq major-mode 'tar-mode)
- (setq mode-name "Tar")
- (use-local-map tar-mode-map)
- (auto-save-mode 0)
- (make-local-variable 'write-contents-hooks)
- (setq write-contents-hooks '(tar-mode-write-file))
- (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 arranges for \"saving\" this buffer to write the data
-into the tar-file buffer that it came from. The changes will actually
-appear on disk when you save the tar-file's buffer."
- (interactive "P")
- (or (and (boundp 'tar-superior-buffer) tar-superior-buffer)
- (error "This buffer is not an element of a tar file"))
-;;; Don't do this, because it is redundant and wastes mode line space.
-;;; (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
- (make-local-variable 'local-write-file-hooks)
- (setq local-write-file-hooks '(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
- (kill-local-variable 'local-write-file-hooks))))
-
-
-;; Revert the buffer and recompute the dired-like listing.
-(defun tar-mode-revert (&optional no-autosave no-confirm)
- (let ((revert-buffer-function nil)
- (old-offset tar-header-offset)
- success)
- (setq tar-header-offset nil)
- (unwind-protect
- (and (revert-buffer t no-confirm)
- (progn (widen)
- (setq success t)
- (tar-mode)))
- ;; If the revert was canceled,
- ;; put back the old value of tar-header-offset.
- (or success
- (setq tar-header-offset old-offset)))))
-
-
-(defun tar-next-line (p)
- (interactive "p")
- (forward-line p)
- (if (eobp) nil (forward-char (if tar-mode-show-date 54 36))))
-
-(defun tar-previous-line (p)
- (interactive "p")
- (tar-next-line (- p)))
-
-(defun tar-current-descriptor (&optional noerror)
- "Return 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-get-descriptor ()
- (let* ((descriptor (tar-current-descriptor))
- (tokens (tar-desc-tokens descriptor))
- (size (tar-header-size tokens))
- (link-p (tar-header-link-type tokens)))
- (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"))
- descriptor))
-
-(defun tar-mouse-extract (event)
- "Extract a file whose tar directory line you click on."
- (interactive "e")
- (save-excursion
- (set-buffer (window-buffer (posn-window (event-end event))))
- (save-excursion
- (goto-char (posn-point (event-end event)))
- ;; Just make sure this doesn't get an error.
- (tar-get-descriptor)))
- (select-window (posn-window (event-end event)))
- (goto-char (posn-point (event-end event)))
- (tar-extract))
-
-(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-get-descriptor))
- (tokens (tar-desc-tokens descriptor))
- (name (tar-header-name tokens))
- (size (tar-header-size tokens))
- (start (+ (tar-desc-data-start descriptor) tar-header-offset -1))
- (end (+ start size)))
- (let* ((tar-buffer (current-buffer))
- (tarname (file-name-nondirectory (buffer-file-name)))
- (bufname (concat (file-name-nondirectory name)
- " ("
- tarname
- ")"))
- (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)
- (setq buffer-file-name
- (expand-file-name (concat tarname ":" name)))
- (setq buffer-file-truename
- (abbreviate-file-name buffer-file-name))
- ;; Set the default-directory to the dir of the
- ;; superior buffer.
- (setq default-directory
- (save-excursion
- (set-buffer tar-buffer)
- default-directory))
- (normal-mode) ; pick a mode.
- (rename-buffer bufname)
- (make-local-variable 'tar-superior-buffer)
- (make-local-variable 'tar-superior-descriptor)
- (setq tar-superior-buffer tar-buffer)
- (setq tar-superior-descriptor descriptor)
- (setq buffer-read-only read-only-p)
- (set-buffer-modified-p nil)
- (tar-subfile-mode 1))
- (set-buffer tar-buffer))
- (narrow-to-region 1 tar-header-offset)))
- (if view-p
- (progn
- (view-buffer buffer)
- (and just-created
- ;; This will be created by view.el
- (setq view-exit-action 'kill-buffer)))
- (if (eq other-window-p 'display)
- (display-buffer buffer)
- (if other-window-p
- (switch-to-buffer-other-window buffer)
- (switch-to-buffer buffer)))))))
-
-
-(defun tar-extract-other-window ()
- "*In Tar mode, find this entry of the tar file in another window."
- (interactive)
- (tar-extract t))
-
-(defun tar-display-other-window ()
- "*In Tar mode, display this entry of the tar file in another window."
- (interactive)
- (tar-extract 'display))
-
-(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)
- "Read a file name with this line's entry as the default."
- (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-get-descriptor))
- (tokens (tar-desc-tokens descriptor))
- (name (tar-header-name tokens))
- (size (tar-header-size tokens))
- (start (+ (tar-desc-data-start descriptor) tar-header-offset -1))
- (end (+ start size))
- (inhibit-file-name-handlers inhibit-file-name-handlers)
- (inhibit-file-name-operation inhibit-file-name-operation))
- (save-restriction
- (widen)
- ;; Inhibit compressing a subfile again if *both* name and
- ;; to-file are handled by jka-compr
- (if (and (eq (find-file-name-handler name 'write-region) 'jka-compr-handler)
- (eq (find-file-name-handler to-file 'write-region) 'jka-compr-handler))
- (setq inhibit-file-name-handlers
- (cons 'jka-compr-handler
- (and (eq inhibit-file-name-operation 'write-region)
- inhibit-file-name-handlers))
- inhibit-file-name-operation 'write-region))
- (write-region start end to-file))
- (message "Copied tar entry %s to %s" name to-file)))
-
-(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 sync...
- (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 files expunged. Be sure to save this buffer." n)))))
-
-
-(defun tar-clear-modification-flags ()
- "Remove the stars at the beginning of each line."
- (interactive)
- (save-excursion
- (goto-char 1)
- (while (< (point) tar-header-offset)
- (if (not (eq (following-char) ?\ ))
- (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 (tar-header-block-summarize 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 (tar-header-block-checksum
- (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.
- (tar-header-block-check-checksum
- (buffer-substring start (+ start 512))
- chk (tar-header-name tokens))
- )))
- (narrow-to-region 1 tar-header-offset))))
-
-
-(defun tar-octal-time (timeval)
- ;; Format a timestamp as 11 octal digits. Ghod, I hope this works...
- (let ((hibits (car timeval)) (lobits (car (cdr timeval))))
- (insert (format "%05o%01o%05o"
- (lsh hibits -2)
- (logior (lsh (logand 3 hibits) 1) (> (logand lobits 32768) 0))
- (logand 32767 lobits)
- ))))
-
-(defun tar-subfile-save-buffer ()
- "In tar subfile mode, save this buffer 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 'tar-superior-buffer) tar-superior-buffer))
- (error "This buffer has no superior tar file buffer"))
- (if (not (and (boundp 'tar-superior-descriptor) tar-superior-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 tar-superior-descriptor))
- (set-buffer tar-superior-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 (tar-octal-time (current-time)))
- (insert ? ))
- ;;
- ;; compute a new checksum and insert it.
- (let ((chk (tar-header-block-checksum
- (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))
- after
- (m (set-marker (make-marker) tar-header-offset)))
- (forward-line 1)
- (setq after (point))
- ;; Insert the new text after the old, before deleting,
- ;; to preserve the window start.
- (insert-before-markers (tar-header-block-summarize tokens t) "\n")
- (delete-region p after)
- (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'. Be sure to save that buffer!"
- (buffer-name tar-superior-buffer))
- ;; Prevent ordinary saving from happening.
- t)))
-
-
-(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))))
- (inhibit-read-only t) ; ##
- )
- ;; 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)))
- )))
-
-
-;; Used in write-file-hook to write tar-files out correctly.
-(defun tar-mode-write-file ()
- (unwind-protect
- (save-excursion
- (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 (point-max) buffer-file-name nil t)
- (tar-clear-modification-flags)
- (set-buffer-modified-p nil))
- (narrow-to-region 1 tar-header-offset))
- ;; return T because we've written the file.
- t)
-
-(provide 'tar-mode)
-
-;;; tar-mode.el ends here
diff --git a/lisp/tcp.el b/lisp/tcp.el
deleted file mode 100644
index 2f5b756ab82..00000000000
--- a/lisp/tcp.el
+++ /dev/null
@@ -1,75 +0,0 @@
-;;; tcp.el --- TCP/IP stream emulation for GNU Emacs
-
-;; Copyright (C) 1988, 1989, 1993 Free Software Foundation, Inc.
-
-;; Author: Masanobu Umeda
-;; Maintainer: umerin@mse.kyutech.ac.jp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Notes on TCP package:
-;;
-;; This package provides a TCP/IP stream emulation for GNU Emacs. If
-;; the function `open-network-stream' is not defined in Emacs, but
-;; your operating system has a capability of network stream
-;; connection, this tcp package can be used for communicating with
-;; NNTP server.
-;;
-;; The tcp package runs inferior process which actually does the role
-;; of `open-network-stream'. The program `tcp' provided with this
-;; package can be used for such purpose. Before loading the package,
-;; compile `tcp.c' and install it as `tcp' in a directory in the emacs
-;; search path. If you modify `tcp.c', please send diffs to the author
-;; of GNUS. I'll include some of them in the next releases.
-
-;;; Code:
-
-(provide 'tcp)
-
-(defvar tcp-program-name "tcp"
- "*The name of the program emulating open-network-stream function.")
-
-(defun open-network-stream (name buffer host service)
- "Open a TCP connection for a service to a host.
-Returns a subprocess-object to represent the connection.
-Input and output work as for subprocesses; `delete-process' closes it.
-Args are NAME BUFFER HOST SERVICE.
-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 name of the host to connect to.
-Fourth arg SERVICE is name of the service desired, or an integer
- specifying a port number to connect to."
- (let ((proc (start-process name buffer
- tcp-program-name
- host
- (if (stringp service)
- service
- (int-to-string service))
- )))
- (process-kill-without-query proc)
- ;; Return process
- proc
- ))
-
-;;; tcp.el ends here
diff --git a/lisp/telnet.el b/lisp/telnet.el
deleted file mode 100644
index f5e61fc1dca..00000000000
--- a/lisp/telnet.el
+++ /dev/null
@@ -1,237 +0,0 @@
-;;; telnet.el --- run a telnet session from within an Emacs buffer
-
-;; Copyright (C) 1985, 1988, 1992, 1994 Free Software Foundation, Inc.
-
-;; Author: William F. Schelter
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This mode is intended to be used for telnet or rsh to a remode host;
-;; `telnet' and `rsh' are the two entry points. Multiple telnet or rsh
-;; sessions are supported.
-;;
-;; Normally, input is sent to the remote telnet/rsh line-by-line, as you
-;; type RET or LFD. C-c C-c sends a C-c to the remote immediately;
-;; C-c C-z sends C-z immediately. C-c C-q followed by any character
-;; sends that character immediately.
-;;
-;; All RET characters are filtered out of the output coming back from the
-;; remote system. The mode tries to do other useful translations based
-;; on what it sees coming back from the other system before the password
-;; query. It knows about UNIX, ITS, TOPS-20 and Explorer systems.
-
-;;; Code:
-
-;; 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)
-
-(defvar telnet-new-line "\r")
-(defvar telnet-mode-map nil)
-(defvar telnet-prompt-pattern "^[^#$%>\n]*[#$%>] *")
-(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 from telnet process while looking for password.")
-(make-variable-buffer-local 'telnet-count)
-
-(defvar telnet-program "telnet"
- "Program to run to open a telnet connection.")
-
-(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 again for a username and password.")
-
-(defun telnet-interrupt-subjob ()
- (interactive)
- "Interrupt the program running through telnet on the remote host."
- (send-string nil telnet-interrupt-string))
-
-(defun telnet-c-z ()
- (interactive)
- (send-string nil "\C-z"))
-
-(defun send-process-next-char ()
- (interactive)
- (send-string nil
- (char-to-string
- (let ((inhibit-quit t))
- (prog1 (read-char)
- (setq quit-flag nil))))))
-
-; initialization on first load.
-(if telnet-mode-map
- nil
- (setq telnet-mode-map (nconc (make-sparse-keymap) comint-mode-map))
- (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-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))
-
-;;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)
- (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 "^[^*>\n]*[*>] *"))
- ((string-match "explorer" string) ;;explorer telnet needs work
- (setq telnet-replace-c-g ?\n))))
- (setq comint-prompt-regexp telnet-prompt-pattern))
-
-(defun telnet-initial-filter (proc string)
- ;For reading up to and including password; also will get machine type.
- (cond ((string-match "No such host" string)
- (kill-buffer (process-buffer proc))
- (error "No such host."))
- ((string-match "passw" string)
- (telnet-filter proc string)
- (setq telnet-count 0)
- (send-string proc (concat (comint-read-noecho "Password: " t)
- telnet-new-line)))
- (t (telnet-check-software-type-initialize string)
- (telnet-filter proc string)
- (cond ((> telnet-count telnet-maximum-count)
- (set-process-filter proc 'telnet-filter))
- (t (setq telnet-count (1+ telnet-count)))))))
-
-;; Identical to comint-simple-send, except that it sends telnet-new-line
-;; instead of "\n".
-(defun telnet-simple-send (proc string)
- (comint-send-string proc string)
- (comint-send-string proc telnet-new-line))
-
-(defun telnet-filter (proc string)
- (save-excursion
- (set-buffer (process-buffer proc))
- (let* ((last-insertion (marker-position (process-mark proc)))
- (delta (- (point) last-insertion))
- (ie (and comint-last-input-end
- (marker-position comint-last-input-end)))
- (w (get-buffer-window (current-buffer)))
- (ws (and w (window-start w))))
- (goto-char last-insertion)
- (insert-before-markers string)
- (set-marker (process-mark proc) (point))
- (if ws (set-window-start w ws t))
- (if ie (set-marker comint-last-input-end ie))
- (while (progn (skip-chars-backward "^\C-m" last-insertion)
- (> (point) last-insertion))
- (delete-region (1- (point)) (point)))
- (goto-char (process-mark proc))
- (and telnet-replace-c-g
- (subst-char-in-region last-insertion (point) ?\C-g
- telnet-replace-c-g t))
- ;; If point is after the insertion place, move it
- ;; along with the text.
- (if (> delta 0)
- (goto-char (+ (process-mark proc) delta))))))
-
-(defun telnet-send-input ()
- (interactive)
-; (comint-send-input telnet-new-line telnet-remote-echoes)
- (comint-send-input)
- (if telnet-remote-echoes
- (delete-region comint-last-input-start
- comint-last-input-end)))
-
-;;;###autoload (add-hook 'same-window-regexps "\\*telnet-.*\\*\\(\\|<[0-9]+>\\)")
-
-;;;###autoload
-(defun telnet (host)
- "Open a network login connection to host named HOST (a string).
-Communication with HOST is recorded in a buffer `*telnet-HOST*'.
-Normally input is edited in Emacs and sent a line at a time."
- (interactive "sOpen telnet connection to host: ")
- (let* ((comint-delimiter-argument-list '(?\ ?\t))
- (name (concat "telnet-" (comint-arguments host 0 nil) ))
- (buffer (get-buffer (concat "*" name "*")))
- process)
- (if (and buffer (get-buffer-process buffer))
- (pop-to-buffer (concat "*" name "*"))
- (pop-to-buffer (make-comint name telnet-program))
- (setq process (get-buffer-process (current-buffer)))
- (set-process-filter process 'telnet-initial-filter)
- ;; Don't send the `open' cmd till telnet is ready for it.
- (accept-process-output process)
- (erase-buffer)
- (send-string process (concat "open " host "\n"))
- (telnet-mode)
- (setq comint-input-sender 'telnet-simple-send)
- (setq telnet-count telnet-initial-count))))
-
-(defun telnet-mode ()
- "This mode is for using telnet (or rsh) 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
-sent to try to stop execution of a job on the remote host.
-Data is sent to the remote host when RET is typed.
-
-\\{telnet-mode-map}
-"
- (interactive)
- (comint-mode)
- (setq major-mode 'telnet-mode
- mode-name "Telnet"
- comint-prompt-regexp telnet-prompt-pattern)
- (use-local-map telnet-mode-map)
- (run-hooks 'telnet-mode-hook))
-
-;;;###autoload (add-hook 'same-window-regexps "\\*rsh-[^-]*\\*\\(\\|<[0-9]*>\\)")
-
-;;;###autoload
-(defun rsh (host)
- "Open a network login connection to host named HOST (a string).
-Communication with HOST is recorded in a buffer `*rsh-HOST*'.
-Normally input is edited in Emacs and sent a line at a time."
- (interactive "sOpen rsh connection to host: ")
- (require 'shell)
- (let ((name (concat "rsh-" host )))
- (pop-to-buffer (make-comint name remote-shell-program nil host))
- (set-process-filter (get-process name) 'telnet-initial-filter)
- (telnet-mode)
- (setq telnet-count -16)))
-
-(provide 'telnet)
-
-;;; telnet.el ends here
diff --git a/lisp/tempo.el b/lisp/tempo.el
deleted file mode 100644
index 6ee10096afc..00000000000
--- a/lisp/tempo.el
+++ /dev/null
@@ -1,764 +0,0 @@
-;;; tempo.el --- Flexible template insertion
-
-;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: David K}gedal <davidk@lysator.liu.se >
-;; Created: 16 Feb 1994
-;; K}gedal's last version number: 1.2.4
-;; Keywords: extensions, languages, tools
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This file provides a simple way to define powerful templates, or
-;; macros, if you wish. It is mainly intended for, but not limited to,
-;; other programmers to be used for creating shortcuts for editing
-;; certain kind of documents. It was originally written to be used by
-;; a HTML editing mode written by Nelson Minar <nelson@santafe.edu>,
-;; and his html-helper-mode.el is probably the best example of how to
-;; use this program.
-
-;; A template is defined as a list of items to be inserted in the
-;; current buffer at point. Some of the items can be simple strings,
-;; while other can control formatting or define special points of
-;; interest in the inserted text.
-
-;; If a template defines a "point of interest" that point is inserted
-;; in a buffer-local list of "points of interest" that the user can
-;; jump between with the commands `tempo-backward-mark' and
-;; `tempo-forward-mark'. If the template definer provides a prompt for
-;; the point, and the variable `tempo-interactive' is non-nil, the
-;; user will be prompted for a string to be inserted in the buffer,
-;; using the minibuffer.
-
-;; The template can also define one point to be replaced with the
-;; current region if the template command is called with a prefix (or
-;; a non-nil argument).
-
-;; More flexible templates can be created by including lisp symbols,
-;; which will be evaluated as variables, or lists, which will will be
-;; evaluated as lisp expressions.
-
-;; See the documentation for tempo-define-template for the different
-;; items that can be used to define a tempo template.
-
-;; One of the more powerful features of tempo templates are automatic
-;; completion. With every template can be assigned a special tag that
-;; should be recognized by `tempo-complete-tag' and expanded to the
-;; complete template. By default the tags are added to a global list
-;; of template tags, and are matched against the last word before
-;; point. But if you assign your tags to a specific list, you can also
-;; specify another method for matching text in the buffer against the
-;; tags. In the HTML mode, for instance, the tags are matched against
-;; the text between the last `<' and point.
-
-;; When defining a template named `foo', a symbol named
-;; `tempo-template-foo' will be created whose value as a variable will
-;; be the template definition, and its function value will be an
-;; interactive function that inserts the template at the point.
-
-;; The latest tempo.el distribution can be fetched from
-;; ftp.lysator.liu.se in the directory /pub/emacs
-
-;; There is also a WWW page at
-;; http://www.lysator.liu.se/~davidk/elisp/ which has some information
-
-;;; Known bugs:
-
-;; If the 'o is the first element in a template, strange things can
-;; happen when the template is inserted at the beginning of a
-;; line. This is due to strange behaviour in open-line. But it should
-;; be easily avoided.
-
-;; The 'o tag is also a problem when including the region. This will
-;; be looked into.
-
-;; Clicking mouse-2 in the completion buffer gives strange results.
-
-;; There is a bug in some emacs versions that prevents completion from
-;; working. If it doesn't work for you, send me a note indicating your
-;; emacs version and your problems.
-
-;;; Contributors:
-
-;; These people have given me important feedback and new ideas for
-;; tempo.el. Thanks.
-
-;; Nelson Minar <nelson@santafe.edu>
-;; Richard Stallman <rms@gnu.ai.mit.edu>
-;; Lars Lindberg <Lars.Lindberg@sypro.cap.se>
-;; Glen Whitney <Glen.Whitney@math.lsa.umich.edu>
-
-;;; Code:
-
-;; (provide 'tempo)
-
-;;; User options
-
-(defvar tempo-interactive nil
- "*Prompt user for strings in templates.
-If this variable is non-nil, `tempo-insert' prompts the
-user for text to insert in the templates")
-
-(defvar tempo-insert-region nil
- "*Automatically insert current region when there is a `r' in the template
-If this variable is NIL, `r' elements will be treated just like `p'
-elements, unless the template function is given a prefix (or a non-nil
-argument). If this variable is non-NIL, the behaviour is reversed.
-
-In Transient Mark mode, this option is unused.")
-
-(defvar tempo-show-completion-buffer t
- "*If non-NIL, show a buffer with possible completions, when only
-a partial completion can be found")
-
-(defvar tempo-leave-completion-buffer nil
- "*If NIL, a completion buffer generated by \\[tempo-complete-tag]
-disappears at the next keypress; otherwise, it remains forever.")
-
-;;; Internal variables
-
-(defvar tempo-insert-string-functions nil
- "List of functions to run when inserting a string.
-Each function is called with a single arg, STRING and should return
-another string. This could be used for making all strings upcase by
-setting it to '(upcase), for example.")
-
-(defvar tempo-tags nil
- "An association list with tags and corresponding templates")
-
-(defvar tempo-local-tags '((tempo-tags . nil))
- "A list of locally installed tag completion lists.
-It is a association list where the car of every element is a symbol
-whose variable value is a template list. The cdr part, if non-nil, is a
-function or a regexp that defines the string to match. See the
-documentation for the function `tempo-complete-tag' for more info.
-
-`tempo-tags' is always in the last position in this list.")
-
-(defvar tempo-collection nil
- "A collection of all the tags defined for the current buffer.")
-
-(defvar tempo-dirty-collection t
- "Indicates if the tag collection needs to be rebuilt.")
-
-(defvar tempo-marks nil
- "A list of marks to jump to with `\\[tempo-forward-mark]' and `\\[tempo-backward-mark]'.")
-
-(defvar tempo-match-finder "\\b\\([^\\b]+\\)\\="
- "The regexp or function used to find the string to match against tags.
-
-If `tempo-match-finder is a string, it should contain a regular
-expression with at least one \\( \\) pair. When searching for tags,
-`tempo-complete-tag' calls `re-search-backward' with this string, and
-the string between the first \\( and \\) is used for matching against
-each string in the tag list. If one is found, the whole text between
-the first \\( and the point is replaced with the inserted template.
-
-You will probably want to include \\ \= at the end of the regexp to
-make sure that the string is matched only against text adjacent to the
-point.
-
-If `tempo-match-finder' is a symbol, it should be a function that
-returns a pair of the form (STRING . POS), where STRING is the string
-used for matching and POS is the buffer position after which text
-should be replaced with a template.")
-
-(defvar tempo-user-elements nil
- "Element handlers for user-defined elements.
-A list of symbols which are bound to functions that take one argument.
-This function should return something to be sent to `tempo-insert' if
-it recognizes the argument, and NIL otherwise")
-
-(defvar tempo-named-insertions nil
- "Temporary storage for named insertions")
-
-(defvar tempo-region-start (make-marker)
- "Region start when inserting around the region")
-
-(defvar tempo-region-stop (make-marker)
- "Region stop when inserting around the region")
-
-;; Make some variables local to every buffer
-
-(make-variable-buffer-local 'tempo-marks)
-(make-variable-buffer-local 'tempo-local-tags)
-(make-variable-buffer-local 'tempo-match-finder)
-(make-variable-buffer-local 'tempo-collection)
-(make-variable-buffer-local 'tempo-dirty-collection)
-
-;;; Functions
-
-;;; First some useful functions and macros
-
-(defun tempo-mapc (fun lst)
- (if (null lst) nil
- (funcall fun (car lst))
- (tempo-mapc fun (cdr lst))))
-
-(defmacro tempo-dolist (il &rest forms)
- (let ((i (car il))
- (l (car (cdr il))))
- (list 'tempo-mapc
- (list 'function (append (list 'lambda
- (list i))
- forms))
- l)))
-(put 'tempo-dolist 'lisp-indent-function 1)
-
-;;
-;; tempo-define-template
-
-(defun tempo-define-template (name elements &optional tag documentation taglist)
- "Define a template.
-This function creates a template variable `tempo-template-NAME' and an
-interactive function `tempo-template-NAME' that inserts the template
-at the point. The created function is returned.
-
-NAME is a string that contains the name of the template, ELEMENTS is a
-list of elements in the template, TAG is the tag used for completion,
-DOCUMENTATION is the documentation string for the insertion command
-created, and TAGLIST (a symbol) is the tag list that TAG (if provided)
-should be added to). If TAGLIST is nil and TAG is non-nil, TAG is
-added to `tempo-tags'
-
-The elements in ELEMENTS can be of several types:
-
- - A string. It is sent to the hooks in `tempo-insert-string-functions',
- and the result is inserted.
- - The symbol 'p. This position is saved in `tempo-marks'.
- - The symbol 'r. If `tempo-insert' is called with ON-REGION non-nil
- the current region is placed here. Otherwise it works like 'p.
- - (p PROMPT <NAME> <NOINSERT>) If `tempo-interactive' is non-nil, the
- user is prompted in the minbuffer with PROMPT for a string to be
- inserted. If the optional parameter NAME is non-nil, the text is
- saved for later insertion with the `s' tag. If there already is
- something saved under NAME that value is used instead and no
- prompting is made. If NOINSERT is provided and non-nil, nothing is
- inserted, but text is still saved when a NAME is provided. For
- clarity, the symbol 'noinsert should be used as argument.
- - (P PROMPT <NAME> <NOINSERT>) Works just like the previous tag, but
- forces tempo-interactive to be true.
- - (r PROMPT <NAME> <NOINSERT>) like the previous, but if
- `tempo-interactive' is nil and `tempo-insert' is called with
- ON-REGION non-nil, the current region is placed here. This usually
- happens when you call the template function with a prefix argument.
- - (s NAME) Inserts text previously read with the (p ..) construct.
- Finds the insertion saved under NAME and inserts it. Acts like 'p
- if tempo-interactive is nil.
- - '& If there is only whitespace between the line start and point,
- nothing happens. Otherwise a newline is inserted.
- - '% If there is only whitespace between point and end-of-line
- nothing happens. Otherwise a newline is inserted.
- - 'n inserts a newline.
- - '> The line is indented using `indent-according-to-mode'. Note that
- you often should place this item after the text you want on the
- line.
- - 'r> Like r, but it also indents the region.
- - 'n> Inserts a newline and indents line.
- - 'o Like '% but leaves the point before the newline.
- - nil. It is ignored.
- - Anything else. It is evaluated and the result is treated as an
- element to be inserted. One additional tag is useful for these
- cases. If an expression returns a list '(l foo bar), the elements
- after 'l will be inserted according to the usual rules. This makes
- it possible to return several elements from one expression."
-
- (let* ((template-name (intern (concat "tempo-template-"
- name)))
- (command-name template-name))
- (set template-name elements)
- (fset command-name (list 'lambda (list '&optional 'arg)
- (or documentation
- (concat "Insert a " name "."))
- (list 'interactive "*P")
- (list 'tempo-insert-template (list 'quote
- template-name)
- (list 'if 'tempo-insert-region
- (list 'not 'arg) 'arg))))
- (and tag
- (tempo-add-tag tag template-name taglist))
- command-name))
-
-;;;
-;;; tempo-insert-template
-
-(defun tempo-insert-template (template on-region)
- "Insert a template.
-TEMPLATE is the template to be inserted. If ON-REGION is non-nil the
-`r' elements are replaced with the current region. In Transient Mark
-mode, ON-REGION is ignored and assumed true if the region is active."
- (unwind-protect
- (progn
- (if (or (and (boundp 'transient-mark-mode) ; For Emacs
- transient-mark-mode
- mark-active)
- (and (boundp 'zmacs-regions) ; For XEmacs
- zmacs-regions (mark)))
- (setq on-region t))
- (and on-region
- (set-marker tempo-region-start (min (mark) (point)))
- (set-marker tempo-region-stop (max (mark) (point))))
- (if on-region
- (goto-char tempo-region-start))
- (save-excursion
- (tempo-insert-mark (point-marker))
- (mapcar (function (lambda (elt)
- (tempo-insert elt on-region)))
- (symbol-value template))
- (tempo-insert-mark (point-marker)))
- (tempo-forward-mark))
- (tempo-forget-insertions)
- ;; Should I check for zmacs here too???
- (and (boundp 'transient-mark-mode)
- transient-mark-mode
- (deactivate-mark))))
-
-;;;
-;;; tempo-insert
-
-(defun tempo-insert (element on-region)
- "Insert a template element.
-Insert one element from a template. If ON-REGION is non-nil the `r'
-elements are replaced with the current region.
-
-See documentation for `tempo-define-template' for the kind of elements
-possible."
- (cond ((stringp element) (tempo-process-and-insert-string element))
- ((and (consp element)
- (eq (car element) 'p)) (tempo-insert-prompt-compat
- (cdr element)))
- ((and (consp element)
- (eq (car element) 'P)) (let ((tempo-interactive t))
- (tempo-insert-prompt-compat
- (cdr element))))
-;;; ((and (consp element)
-;;; (eq (car element) 'v)) (tempo-save-named
-;;; (nth 1 element)
-;;; nil
-;;; (nth 2 element)))
- ((and (consp element)
- (eq (car element) 'r)) (if on-region
- (goto-char tempo-region-stop)
- (tempo-insert-prompt-compat
- (cdr element))))
- ((and (consp element)
- (eq (car element) 's)) (tempo-insert-named (car (cdr element))))
- ((and (consp element)
- (eq (car element) 'l)) (mapcar (function
- (lambda (elt)
- (tempo-insert elt on-region)))
- (cdr element)))
- ((eq element 'p) (tempo-insert-mark (point-marker)))
- ((eq element 'r) (if on-region
- (goto-char tempo-region-stop)
- (tempo-insert-mark (point-marker))))
- ((eq element 'r>) (if on-region
- (progn
- (goto-char tempo-region-stop)
- (indent-region (mark) (point) nil))
- (tempo-insert-mark (point-marker))))
- ((eq element '>) (indent-according-to-mode))
- ((eq element '&) (if (not (or (= (current-column) 0)
- (save-excursion
- (re-search-backward
- "^\\s-*\\=" nil t))))
- (insert "\n")))
- ((eq element '%) (if (not (or (eolp)
- (save-excursion
- (re-search-forward
- "\\=\\s-*$" nil t))))
- (insert "\n")))
- ((eq element 'n) (insert "\n"))
- ((eq element 'n>) (insert "\n") (indent-according-to-mode))
- ;; Bug: If the 'o is the first element in a template, strange
- ;; things can happen when the template is inserted at the
- ;; beginning of a line.
- ((eq element 'o) (if (not (or on-region
- (eolp)
- (save-excursion
- (re-search-forward
- "\\=\\s-*$" nil t))))
- (open-line 1)))
- ((null element))
- (t (tempo-insert (or (tempo-is-user-element element)
- (eval element))
- on-region))))
-
-;;;
-;;; tempo-insert-prompt
-
-(defun tempo-insert-prompt-compat (prompt)
- "Compatibility hack for tempo-insert-prompt.
-PROMPT can be either a prompt string, or a list of arguments to
-tempo-insert-prompt, or nil."
- (if (consp prompt) ; not NIL either
- (apply 'tempo-insert-prompt prompt)
- (tempo-insert-prompt prompt)))
-
-(defun tempo-insert-prompt (prompt &optional save-name no-insert)
- "Prompt for a text string and insert it in the current buffer.
-If the variable `tempo-interactive' is non-nil the user is prompted
-for a string in the minibuffer, which is then inserted in the current
-buffer. If `tempo-interactive' is nil, the current point is placed on
-`tempo-mark'.
-
-PROMPT is the prompt string, SAVE-NAME is a name to save the inserted
-text under. If the optional argument NO-INSERT is non-nil, no text i
-inserted. This can be useful when there is a SAVE-NAME.
-
-If there already is a value for SAVE-NAME, it is used and the user is
-never prompted."
- (let (insertion
- (previous (and save-name
- (tempo-lookup-named save-name))))
- (cond
- ;; Insert previous value, unless no-insert is non-nil
- ((and previous
- (not no-insert))
- (tempo-insert-named save-name)) ; A double lookup here, but who
- ; cares
- ;; If no-insert is non-nil, don't insert the previous value. Just
- ;; keep it
- (previous
- nil)
- ;; No previous value. Prompt or insert mark
- (tempo-interactive
- (if (not (stringp prompt))
- (error "tempo: The prompt (%s) is not a string" prompt))
- (setq insertion (read-string prompt))
- (or no-insert
- (insert insertion))
- (if save-name
- (tempo-save-named save-name insertion)))
- (t
- (tempo-insert-mark (point-marker))))))
-
-;;;
-;;; tempo-is-user-element
-
-(defun tempo-is-user-element (element)
- "Tries all the user-defined element handlers in
-`tempo-user-elements'"
- ;; Sigh... I need (some list)
- (catch 'found
- (mapcar (function (lambda (handler)
- (let ((result (funcall handler element)))
- (if result (throw 'found result)))))
- tempo-user-elements)
- (throw 'found nil)))
-
-;;;
-;;; tempo-forget-insertions
-
-(defun tempo-forget-insertions ()
- "Forget all the saved named insertions."
- (setq tempo-named-insertions nil))
-
-;;;
-;;; tempo-save-named
-
-(defun tempo-save-named (name data) ; Had an optional prompt for 'v
- "Save some data for later insertion
-The contents of DATA is saved under the name NAME.
-
-The data can later be retrieved with `tempo-lookup-named'.
-
-This function returns nil, so it can be used in a template without
-inserting anything."
- (setq tempo-named-insertions
- (cons (cons name data)
- tempo-named-insertions))
- nil)
-
-;;;
-;;; tempo-lookup-named
-
-(defun tempo-lookup-named (name)
- "Lookup some saved data under the name NAME.
-Returns the data if NAME was found, and nil otherwise."
- (cdr (assq name tempo-named-insertions)))
-
-;;;
-;;; tempo-insert-named
-
-(defun tempo-insert-named (name)
- "Insert the previous insertion saved under a named specified in NAME.
-If there is no such name saved, a tempo mark is inserted.
-
-Note that if the data is a string, it will not be run through the string
-processor."
- (let* ((insertion (tempo-lookup-named name)))
- (cond ((null insertion)
- (tempo-insert-mark (point-marker)))
- ((stringp insertion)
- (insert insertion))
- (t
- (tempo-insert insertion nil)))))
-
-
-;;;
-;;; tempo-process-and-insert-string
-
-(defun tempo-process-and-insert-string (string)
- "Insert a string from a template.
-Run a string through the preprocessors in `tempo-insert-string-functions'
-and insert the results."
- (cond ((null tempo-insert-string-functions)
- nil)
- ((symbolp tempo-insert-string-functions)
- (setq string
- (funcall tempo-insert-string-functions string)))
- ((listp tempo-insert-string-functions)
- (tempo-dolist (fn tempo-insert-string-functions)
- (setq string (funcall fn string))))
- (t
- (error "Bogus value in tempo-insert-string-functions: %s"
- tempo-insert-string-functions)))
- (insert string))
-
-;;;
-;;; tempo-insert-mark
-
-(defun tempo-insert-mark (mark)
- "Insert a mark `tempo-marks' while keeping it sorted"
- (cond ((null tempo-marks) (setq tempo-marks (list mark)))
- ((< mark (car tempo-marks)) (setq tempo-marks (cons mark tempo-marks)))
- (t (let ((lp tempo-marks))
- (while (and (cdr lp)
- (<= (car (cdr lp)) mark))
- (setq lp (cdr lp)))
- (if (not (= mark (car lp)))
- (setcdr lp (cons mark (cdr lp))))))))
-
-;;;
-;;; tempo-forward-mark
-
-(defun tempo-forward-mark ()
- "Jump to the next mark in `tempo-forward-mark-list'."
- (interactive)
- (let ((next-mark (catch 'found
- (mapcar
- (function
- (lambda (mark)
- (if (< (point) mark)
- (throw 'found mark))))
- tempo-marks)
- ;; return nil if not found
- nil)))
- (if next-mark
- (goto-char next-mark))))
-
-;;;
-;;; tempo-backward-mark
-
-(defun tempo-backward-mark ()
- "Jump to the previous mark in `tempo-back-mark-list'."
- (interactive)
- (let ((prev-mark (catch 'found
- (let (last)
- (mapcar
- (function
- (lambda (mark)
- (if (<= (point) mark)
- (throw 'found last))
- (setq last mark)))
- tempo-marks)
- last))))
- (if prev-mark
- (goto-char prev-mark))))
-
-;;;
-;;; tempo-add-tag
-
-(defun tempo-add-tag (tag template &optional tag-list)
- "Add a template tag.
-Add the TAG, that should complete to TEMPLATE to the list in TAG-LIST,
-or to `tempo-tags' if TAG-LIST is nil."
-
- (interactive "sTag: \nCTemplate: ")
- (if (null tag-list)
- (setq tag-list 'tempo-tags))
- (if (not (assoc tag (symbol-value tag-list)))
- (set tag-list (cons (cons tag template) (symbol-value tag-list))))
- (tempo-invalidate-collection))
-
-;;;
-;;; tempo-use-tag-list
-
-(defun tempo-use-tag-list (tag-list &optional completion-function)
- "Install TAG-LIST to be used for template completion in the current buffer.
-TAG-LIST is a symbol whose variable value is a tag list created with
-`tempo-add-tag'.
-
-COMPLETION-FUNCTION is an obsolete option for specifying an optional
-function or string that is used by `\\[tempo-complete-tag]' to find a
-string to match the tag against. It has the same definition as the
-variable `tempo-match-finder'. In this version, supplying a
-COMPLETION-FUNCTION just sets `tempo-match-finder' locally."
- (let ((old (assq tag-list tempo-local-tags)))
- (if old
- (setcdr old completion-function)
- (setq tempo-local-tags (cons (cons tag-list completion-function)
- tempo-local-tags))))
- (if completion-function
- (setq tempo-match-finder completion-function))
- (tempo-invalidate-collection))
-
-;;;
-;;; tempo-invalidate-collection
-
-(defun tempo-invalidate-collection ()
- "Marks the tag collection as obsolete.
-Whenever it is needed again it will be rebuilt."
- (setq tempo-dirty-collection t))
-
-;;;
-;;; tempo-build-collection
-
-(defun tempo-build-collection ()
- "Build a collection of all the tags and return it.
-If `tempo-dirty-collection' is NIL, the old collection is reused."
- (prog1
- (or (and (not tempo-dirty-collection)
- tempo-collection)
- (setq tempo-collection
- (apply (function append)
- (mapcar (function (lambda (tag-list)
- ; If the format for
- ; tempo-local-tags changes,
- ; change this
- (eval (car tag-list))))
- tempo-local-tags))))
- (setq tempo-dirty-collection nil)))
-
-;;;
-;;; tempo-find-match-string
-
-(defun tempo-find-match-string (finder)
- "Find a string to be matched against a tag list.
-FINDER is a function or a string. Returns (STRING . POS), or nil
-if no reasonable string is found."
- (cond ((stringp finder)
- (let (successful)
- (save-excursion
- (or (setq successful (re-search-backward finder nil t))
- 0))
- (if successful
- (cons (buffer-substring (match-beginning 1)
- (match-end 1)) ; This seems to be a
- ; bug in emacs
- (match-beginning 1))
- nil)))
- (t
- (funcall finder))))
-
-;;;
-;;; tempo-complete-tag
-
-(defun tempo-complete-tag (&optional silent)
- "Look for a tag and expand it.
-All the tags in the tag lists in `tempo-local-tags'
-\(this includes `tempo-tags') are searched for a match for the text
-before the point. The way the string to match for is determined can
-be altered with the variable `tempo-match-finder'. If
-`tempo-match-finder' returns nil, then the results are the same as
-no match at all.
-
-If a single match is found, the corresponding template is expanded in
-place of the matching string.
-
-If a partial completion or no match at all is found, and SILENT is
-non-NIL, the function will give a signal.
-
-If a partial completion is found and `tempo-show-completion-buffer' is
-non-NIL, a buffer containing possible completions is displayed."
-
- ;; This function may look like a hack, but this is how I want it to
- ;; work.
- (interactive "*")
- (let* ((collection (tempo-build-collection))
- (match-info (tempo-find-match-string tempo-match-finder))
- (match-string (car match-info))
- (match-start (cdr match-info))
- (exact (assoc match-string collection))
- (compl (or (car exact)
- (and match-info (try-completion match-string collection)))))
- (if compl (delete-region match-start (point)))
- (cond ((null match-info) (or silent (ding)))
- ((null compl) (or silent (ding)))
- ((eq compl t) (tempo-insert-template
- (cdr (assoc match-string
- collection))
- nil))
- (t (if (setq exact (assoc compl collection))
- (tempo-insert-template (cdr exact) nil)
- (insert compl)
- (or silent (ding))
- (if tempo-show-completion-buffer
- (tempo-display-completions match-string
- collection)))))))
-
-
-;;;
-;;; tempo-display-completions
-
-(defun tempo-display-completions (string tag-list)
- "Show a buffer containing possible completions for STRING."
- (if tempo-leave-completion-buffer
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list
- (all-completions string tag-list)))
- (save-window-excursion
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list
- (all-completions string tag-list)))
- (sit-for 32767))))
-
-;;;
-;;; tempo-expand-if-complete
-
-(defun tempo-expand-if-complete ()
- "Expand the tag before point if it is complete.
-Returns non-nil if an expansion was made and nil otherwise.
-
-This could as an example be used in a command that is bound to the
-space bar, and looks something like this:
-
-(defun tempo-space ()
- (interactive \"*\")
- (or (tempo-expand-if-complete)
- (insert \" \")))"
-
- (interactive "*")
- (let* ((collection (tempo-build-collection))
- (match-info (tempo-find-match-string tempo-match-finder))
- (match-string (car match-info))
- (match-start (cdr match-info))
- (exact (assoc match-string collection)))
- (if exact
- (progn
- (delete-region match-start (point))
- (tempo-insert-template (cdr exact) nil)
- t)
- nil)))
-
-(provide 'tempo)
-
-;;; tempo.el ends here
diff --git a/lisp/term.el b/lisp/term.el
deleted file mode 100644
index 8e266c0e78a..00000000000
--- a/lisp/term.el
+++ /dev/null
@@ -1,3261 +0,0 @@
-;;; term.el --- general command interpreter in a window stuff
-
-;; Copyright (C) 1988, 1990, 1992, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Per Bothner <bothner@cygnus.com>
-;; Based on comint mode written by: Olin Shivers <shivers@cs.cmu.edu>
-;; Keyword: processes
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The changelog is at the end of this file.
-
-;; Please send me bug reports, bug fixes, and extensions, so that I can
-;; merge them into the master source.
-;; - Per Bothner (bothner@cygnus.com)
-
-;; This file defines a general command-interpreter-in-a-buffer package
-;; (term mode). The idea is that you can build specific process-in-a-buffer
-;; modes on top of term 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 hints on converting existing process modes (e.g., tex-mode,
-;; background, dbx, gdb, kermit, prolog, telnet) to use term-mode
-;; instead of shell-mode, see the notes at the end of this file.
-
-
-;; Brief Command Documentation:
-;;============================================================================
-;; Term Mode Commands: (common to all derived modes, like cmushell & cmulisp
-;; mode)
-;;
-;; m-p term-previous-input Cycle backwards in input history
-;; m-n term-next-input Cycle forwards
-;; m-r term-previous-matching-input Previous input matching a regexp
-;; m-s comint-next-matching-input Next input that matches
-;; return term-send-input
-;; c-c c-a term-bol Beginning of line; skip prompt.
-;; c-d term-delchar-or-maybe-eof Delete char unless at end of buff.
-;; c-c c-u term-kill-input ^u
-;; c-c c-w backward-kill-word ^w
-;; c-c c-c term-interrupt-subjob ^c
-;; c-c c-z term-stop-subjob ^z
-;; c-c c-\ term-quit-subjob ^\
-;; c-c c-o term-kill-output Delete last batch of process output
-;; c-c c-r term-show-output Show last batch of process output
-;; c-c c-h term-dynamic-list-input-ring List input history
-;;
-;; Not bound by default in term-mode
-;; term-send-invisible Read a line w/o echo, and send to proc
-;; (These are bound in shell-mode)
-;; term-dynamic-complete Complete filename at point.
-;; term-dynamic-list-completions List completions in help buffer.
-;; term-replace-by-expanded-filename Expand and complete filename at point;
-;; replace with expanded/completed name.
-;; term-kill-subjob No mercy.
-;; term-show-maximum-output Show as much output as possible.
-;; term-continue-subjob Send CONT signal to buffer's process
-;; group. Useful if you accidentally
-;; suspend your process (with C-c C-z).
-
-;; term-mode-hook is the term mode hook. Basically for your keybindings.
-;; term-load-hook is run after loading in this package.
-
-;; Code:
-
-;; This is passed to the inferior in the EMACS environment variable,
-;; so it is important to increase it if there are protocol-relevant changes.
-(defconst term-protocol-version "0.95")
-
-(require 'ring)
-(require 'ehelp)
-
-;;; Buffer Local Variables:
-;;;============================================================================
-;;; Term mode buffer local variables:
-;;; term-prompt-regexp - string term-bol uses to match prompt.
-;;; term-delimiter-argument-list - list For delimiters and arguments
-;;; term-last-input-start - marker Handy if inferior always echoes
-;;; term-last-input-end - marker For term-kill-output command
-;; For the input history mechanism:
-(defvar term-input-ring-size 32 "Size of input history ring.")
-;;; term-input-ring-size - integer
-;;; term-input-ring - ring
-;;; term-input-ring-index - number ...
-;;; term-input-autoexpand - symbol ...
-;;; term-input-ignoredups - boolean ...
-;;; term-last-input-match - string ...
-;;; term-dynamic-complete-functions - hook For the completion mechanism
-;;; term-completion-fignore - list ...
-;;; term-get-old-input - function Hooks for specific
-;;; term-input-filter-functions - hook process-in-a-buffer
-;;; term-input-filter - function modes.
-;;; term-input-send - function
-;;; term-scroll-to-bottom-on-output - symbol ...
-;;; term-scroll-show-maximum-output - boolean...
-(defvar term-height) ;; Number of lines in window.
-(defvar term-width) ;; Number of columns in window.
-(defvar term-home-marker) ;; Marks the "home" position for cursor addressing.
-(defvar term-saved-home-marker nil) ;; When using alternate sub-buffer,
-;; contains saved term-home-marker from original sub-buffer .
-(defvar term-start-line-column 0) ;; (current-column) at start of screen line,
-;; or nil if unknown.
-(defvar term-current-column 0) ;; If non-nil, is cache for (current-column).
-(defvar term-current-row 0) ;; Current vertical row (relative to home-marker)
-;; or nil if unknown.
-(defvar term-insert-mode nil)
-(defvar term-vertical-motion)
-(defvar term-terminal-state 0) ;; State of the terminal emulator:
-;; state 0: Normal state
-;; state 1: Last character was a graphic in the last column.
-;; If next char is graphic, first move one column right
-;; (and line warp) before displaying it.
-;; This emulates (more or less) the behavior of xterm.
-;; state 2: seen ESC
-;; state 3: seen ESC [ (or ESC [ ?)
-;; state 4: term-terminal-parameter contains pending output.
-(defvar term-kill-echo-list nil) ;; A queue of strings whose echo
-;; we want suppressed.
-(defvar term-terminal-parameter)
-(defvar term-terminal-previous-parameter)
-(defvar term-current-face 'default)
-(defvar term-scroll-start 0) ;; Top-most line (inclusive) of scrolling region.
-(defvar term-scroll-end) ;; Number of line (zero-based) after scrolling region.
-(defvar term-pager-count nil) ;; If nil, paging is disabled.
-;; Otherwise, number of lines before we need to page.
-(defvar term-saved-cursor nil)
-(defvar term-command-hook)
-(defvar term-log-buffer nil)
-(defvar term-scroll-with-delete nil) ;; term-scroll-with-delete is t if
-;; forward scrolling should be implemented by delete to
-;; top-most line(s); and nil if scrolling should be implemented
-;; by moving term-home-marker. It is set to t iff there is a
-;; (non-default) scroll-region OR the alternate buffer is used.
-(defvar term-pending-delete-marker) ;; New user input in line mode needs to
-;; be deleted, because it gets echoed by the inferior.
-;; To reduce flicker, we defer the delete until the next output.
-(defvar term-old-mode-map nil) ;; Saves the old keymap when in char mode.
-(defvar term-old-mode-line-format) ;; Saves old mode-line-format while paging.
-(defvar term-pager-old-local-map nil) ;; Saves old keymap while paging.
-(defvar term-pager-old-filter) ;; Saved process-filter while paging.
-
-(defvar explicit-shell-file-name nil
- "*If non-nil, is file name to use for explicitly requested inferior shell.")
-
-(defvar term-prompt-regexp "^"
- "Regexp to recognise prompts in the inferior process.
-Defaults to \"^\", the null string at BOL.
-
-Good choices:
- Canonical Lisp: \"^[^> \\n]*>+:? *\" (Lucid, franz, kcl, T, cscheme, oaklisp)
- Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\"
- franz: \"^\\\\(->\\\\|<[0-9]*>:\\\\) *\"
- kcl: \"^>+ *\"
- shell: \"^[^#$%>\\n]*[#$%>] *\"
- T: \"^>+ *\"
-
-This is a good thing to set in mode hooks.")
-
-(defvar term-delimiter-argument-list ()
- "List of characters to recognise as separate arguments in input.
-Strings comprising a character in this list will separate the arguments
-surrounding them, and also be regarded as arguments in their own right (unlike
-whitespace). See `term-arguments'.
-Defaults to the empty list.
-
-For shells, a good value is (?\\| ?& ?< ?> ?\\( ?\\) ?;).
-
-This is a good thing to set in mode hooks.")
-
-(defvar term-input-autoexpand nil
- "*If non-nil, expand input command history references on completion.
-This mirrors the optional behavior of tcsh (its autoexpand and histlit).
-
-If the value is `input', then the expansion is seen on input.
-If the value is `history', then the expansion is only when inserting
-into the buffer's input ring. See also `term-magic-space' and
-`term-dynamic-complete'.
-
-This variable is buffer-local.")
-
-(defvar term-input-ignoredups nil
- "*If non-nil, don't add input matching the last on the input ring.
-This mirrors the optional behavior of bash.
-
-This variable is buffer-local.")
-
-(defvar term-input-ring-file-name nil
- "*If non-nil, name of the file to read/write input history.
-See also `term-read-input-ring' and `term-write-input-ring'.
-
-This variable is buffer-local, and is a good thing to set in mode hooks.")
-
-(defvar term-scroll-to-bottom-on-output nil
- "*Controls whether interpreter output causes window to scroll.
-If nil, then do not scroll. If t or `all', scroll all windows showing buffer.
-If `this', scroll only the selected window.
-If `others', scroll only those that are not the selected window.
-
-The default is nil.
-
-See variable `term-scroll-show-maximum-output'.
-This variable is buffer-local.")
-
-(defvar term-scroll-show-maximum-output nil
- "*Controls how interpreter output causes window to scroll.
-If non-nil, then show the maximum output when the window is scrolled.
-
-See variable `term-scroll-to-bottom-on-output'.
-This variable is buffer-local.")
-
-;; Where gud-display-frame should put the debugging arrow. This is
-;; set by the marker-filter, which scans the debugger's output for
-;; indications of the current pc.
-(defvar term-pending-frame nil)
-
-;;; Here are the per-interpreter hooks.
-(defvar term-get-old-input (function term-get-old-input-default)
- "Function that submits old text in term 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
-term-get-old-input-default, which grabs the current line, and strips off
-leading text matching term-prompt-regexp")
-
-(defvar term-dynamic-complete-functions
- '(term-replace-by-expanded-history term-dynamic-complete-filename)
- "List of functions called to perform completion.
-Functions should return non-nil if completion was performed.
-See also `term-dynamic-complete'.
-
-This is a good thing to set in mode hooks.")
-
-(defvar term-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 term-input-filter-functions '()
- "Functions to call before input is sent to the process.
-These functions get one argument, a string containing the text to send.
-
-This variable is buffer-local.")
-
-(defvar term-input-sender (function term-simple-send)
- "Function to actually send to PROCESS the STRING submitted by user.
-Usually this is just 'term-simple-send, but if your mode needs to
-massage the input string, this is your hook. This is called from
-the user command term-send-input. term-simple-send just sends
-the string plus a newline.")
-
-(defvar term-eol-on-send t
- "*Non-nil means go to the end of the line before sending input.
-See `term-send-input'.")
-
-(defvar term-mode-hook '()
- "Called upon entry into term-mode
-This is run before the process is cranked up.")
-
-(defvar term-exec-hook '()
- "Called each time a process is exec'd by term-exec.
-This is called after the process is cranked up. It is useful for things that
-must be done each time a process is executed in a term-mode buffer (e.g.,
-\(process-kill-without-query)). In contrast, the term-mode-hook is only
-executed once when the buffer is created.")
-
-(defvar term-mode-map nil)
-(defvar term-raw-map nil
- "Keyboard map for sending characters directly to the inferior process.")
-(defvar term-escape-char nil
- "Escape character for char-sub-mode of term mode.
-Do not change it directly; use term-set-escape-char instead.")
-(defvar term-raw-escape-map nil)
-
-(defvar term-pager-break-map nil)
-
-(defvar term-ptyp t
- "True if communications via pty; false if by pipe. Buffer local.
-This is to work around a bug in emacs process signaling.")
-
-(defvar term-last-input-match ""
- "Last string searched for by term input history search, for defaulting.
-Buffer local variable.")
-
-(defvar term-input-ring nil)
-(defvar term-last-input-start)
-(defvar term-last-input-end)
-(defvar term-input-ring-index nil
- "Index of last matched history element.")
-(defvar term-matching-input-from-input-string ""
- "Input previously used to match input history.")
-; This argument to set-process-filter disables reading from the process,
-; assuming this is emacs-19.20 or newer.
-(defvar term-pager-filter t)
-
-(put 'term-replace-by-expanded-history 'menu-enable 'term-input-autoexpand)
-(put 'term-input-ring 'permanent-local t)
-(put 'term-input-ring-index 'permanent-local t)
-(put 'term-input-autoexpand 'permanent-local t)
-(put 'term-input-filter-functions 'permanent-local t)
-(put 'term-scroll-to-bottom-on-output 'permanent-local t)
-(put 'term-scroll-show-maximum-output 'permanent-local t)
-(put 'term-ptyp 'permanent-local t)
-
-;; Do FORMS if running under Emacs-19.
-(defmacro term-if-emacs19 (&rest forms)
- (if (string-match "^19" emacs-version) (cons 'progn forms)))
-;; True if running under XEmacs (previously Lucid emacs).
-(defmacro term-is-xemacs () '(string-match "Lucid" emacs-version))
-;; Do FORM if running under XEmacs (previously Lucid emacs).
-(defmacro term-if-xemacs (&rest forms)
- (if (term-is-xemacs) (cons 'progn forms)))
-;; Do FORM if NOT running under XEmacs (previously Lucid emacs).
-(defmacro term-ifnot-xemacs (&rest forms)
- (if (not (term-is-xemacs)) (cons 'progn forms)))
-
-(defmacro term-in-char-mode () '(eq (current-local-map) term-raw-map))
-(defmacro term-in-line-mode () '(not (term-in-char-mode)))
-;; True if currently doing PAGER handling.
-(defmacro term-pager-enabled () 'term-pager-count)
-(defmacro term-handling-pager () 'term-pager-old-local-map)
-(defmacro term-using-alternate-sub-buffer () 'term-saved-home-marker)
-
-(defvar term-signals-menu)
-(defvar term-terminal-menu)
-
-(term-if-xemacs
- (defvar term-terminal-menu
- '("Terminal"
- [ "Character mode" term-char-mode (term-in-line-mode)]
- [ "Line mode" term-line-mode (term-in-char-mode)]
- [ "Enable paging" term-pager-toggle (not term-pager-count)]
- [ "Disable paging" term-pager-toggle term-pager-count])))
-
-(defun term-mode ()
- "Major mode for interacting with an inferior interpreter.
-Interpreter name is same as buffer name, sans the asterisks.
-In line sub-mode, return at end of buffer sends line as input,
-while return not at end copies rest of line to end and sends it.
-In char sub-mode, each character (except `term-escape-char`) is
-set immediately.
-
-This mode is typically customised to create inferior-lisp-mode,
-shell-mode, etc.. This can be done by setting the hooks
-term-input-filter-functions, term-input-filter, term-input-sender and
-term-get-old-input to appropriate functions, and the variable
-term-prompt-regexp to the appropriate regular expression.
-
-An input history is maintained of size `term-input-ring-size', and
-can be accessed with the commands \\[term-next-input], \\[term-previous-input], and \\[term-dynamic-list-input-ring].
-Input ring history expansion can be achieved with the commands
-\\[term-replace-by-expanded-history] or \\[term-magic-space].
-Input ring expansion is controlled by the variable `term-input-autoexpand',
-and addition is controlled by the variable `term-input-ignoredups'.
-
-Input to, and output from, the subprocess can cause the window to scroll to
-the end of the buffer. See variables `term-scroll-to-bottom-on-input',
-and `term-scroll-to-bottom-on-output'.
-
-If you accidentally suspend your process, use \\[term-continue-subjob]
-to continue it.
-
-\\{term-mode-map}
-
-Entry to this mode runs the hooks on term-mode-hook"
- (interactive)
- ;; Do not remove this. All major modes must do this.
- (kill-all-local-variables)
- (setq major-mode 'term-mode)
- (setq mode-name "Term")
- (use-local-map term-mode-map)
- (make-local-variable 'term-home-marker)
- (setq term-home-marker (copy-marker 0))
- (make-local-variable 'term-saved-home-marker)
- (make-local-variable 'term-height)
- (make-local-variable 'term-width)
- (setq term-width (1- (window-width)))
- (setq term-height (1- (window-height)))
- (make-local-variable 'term-terminal-parameter)
- (make-local-variable 'term-saved-cursor)
- (make-local-variable 'term-last-input-start)
- (setq term-last-input-start (make-marker))
- (make-local-variable 'term-last-input-end)
- (setq term-last-input-end (make-marker))
- (make-local-variable 'term-last-input-match)
- (setq term-last-input-match "")
- (make-local-variable 'term-prompt-regexp) ; Don't set; default
- (make-local-variable 'term-input-ring-size) ; ...to global val.
- (make-local-variable 'term-input-ring)
- (make-local-variable 'term-input-ring-file-name)
- (or (and (boundp 'term-input-ring) term-input-ring)
- (setq term-input-ring (make-ring term-input-ring-size)))
- (make-local-variable 'term-input-ring-index)
- (or (and (boundp 'term-input-ring-index) term-input-ring-index)
- (setq term-input-ring-index nil))
-
- (make-local-variable 'term-command-hook)
- (setq term-command-hook (symbol-function 'term-command-hook))
-
- (make-local-variable 'term-terminal-state)
- (make-local-variable 'term-kill-echo-list)
- (make-local-variable 'term-start-line-column)
- (make-local-variable 'term-current-column)
- (make-local-variable 'term-current-row)
- (make-local-variable 'term-log-buffer)
- (make-local-variable 'term-scroll-start)
- (make-local-variable 'term-scroll-end)
- (setq term-scroll-end term-height)
- (make-local-variable 'term-scroll-with-delete)
- (make-local-variable 'term-pager-count)
- (make-local-variable 'term-pager-old-local-map)
- (make-local-variable 'term-old-mode-map)
- (make-local-variable 'term-insert-mode)
- (make-local-variable 'term-dynamic-complete-functions)
- (make-local-variable 'term-completion-fignore)
- (make-local-variable 'term-get-old-input)
- (make-local-variable 'term-matching-input-from-input-string)
- (make-local-variable 'term-input-autoexpand)
- (make-local-variable 'term-input-ignoredups)
- (make-local-variable 'term-delimiter-argument-list)
- (make-local-variable 'term-input-filter-functions)
- (make-local-variable 'term-input-filter)
- (make-local-variable 'term-input-sender)
- (make-local-variable 'term-eol-on-send)
- (make-local-variable 'term-scroll-to-bottom-on-output)
- (make-local-variable 'term-scroll-show-maximum-output)
- (make-local-variable 'term-ptyp)
- (make-local-variable 'term-exec-hook)
- (make-local-variable 'term-vertical-motion)
- (make-local-variable 'term-pending-delete-marker)
- (setq term-pending-delete-marker (make-marker))
- (make-local-variable 'term-current-face)
- (make-local-variable 'term-pending-frame)
- (setq term-pending-frame nil)
- (run-hooks 'term-mode-hook)
- (term-if-xemacs
- (set-buffer-menubar
- (append current-menubar (list term-terminal-menu))))
- (or term-input-ring
- (setq term-input-ring (make-ring term-input-ring-size)))
- (term-update-mode-line))
-
-(if term-mode-map
- nil
- (setq term-mode-map (make-sparse-keymap))
- (define-key term-mode-map "\ep" 'term-previous-input)
- (define-key term-mode-map "\en" 'term-next-input)
- (define-key term-mode-map "\er" 'term-previous-matching-input)
- (define-key term-mode-map "\es" 'term-next-matching-input)
- (term-ifnot-xemacs
- (define-key term-mode-map [?\A-\M-r] 'term-previous-matching-input-from-input)
- (define-key term-mode-map [?\A-\M-s] 'term-next-matching-input-from-input))
- (define-key term-mode-map "\e\C-l" 'term-show-output)
- (define-key term-mode-map "\C-m" 'term-send-input)
- (define-key term-mode-map "\C-d" 'term-delchar-or-maybe-eof)
- (define-key term-mode-map "\C-c\C-a" 'term-bol)
- (define-key term-mode-map "\C-c\C-u" 'term-kill-input)
- (define-key term-mode-map "\C-c\C-w" 'backward-kill-word)
- (define-key term-mode-map "\C-c\C-c" 'term-interrupt-subjob)
- (define-key term-mode-map "\C-c\C-z" 'term-stop-subjob)
- (define-key term-mode-map "\C-c\C-\\" 'term-quit-subjob)
- (define-key term-mode-map "\C-c\C-m" 'term-copy-old-input)
- (define-key term-mode-map "\C-c\C-o" 'term-kill-output)
- (define-key term-mode-map "\C-c\C-r" 'term-show-output)
- (define-key term-mode-map "\C-c\C-e" 'term-show-maximum-output)
- (define-key term-mode-map "\C-c\C-l" 'term-dynamic-list-input-ring)
- (define-key term-mode-map "\C-c\C-n" 'term-next-prompt)
- (define-key term-mode-map "\C-c\C-p" 'term-previous-prompt)
- (define-key term-mode-map "\C-c\C-d" 'term-send-eof)
- (define-key term-mode-map "\C-c\C-k" 'term-char-mode)
- (define-key term-mode-map "\C-c\C-j" 'term-line-mode)
- (define-key term-mode-map "\C-c\C-q" 'term-pager-toggle)
-
- (copy-face 'default 'term-underline-face)
- (set-face-underline-p 'term-underline-face t)
-
-; ;; completion:
-; (define-key term-mode-map [menu-bar completion]
-; (cons "Complete" (make-sparse-keymap "Complete")))
-; (define-key term-mode-map [menu-bar completion complete-expand]
-; '("Expand File Name" . term-replace-by-expanded-filename))
-; (define-key term-mode-map [menu-bar completion complete-listing]
-; '("File Completion Listing" . term-dynamic-list-filename-completions))
-; (define-key term-mode-map [menu-bar completion complete-file]
-; '("Complete File Name" . term-dynamic-complete-filename))
-; (define-key term-mode-map [menu-bar completion complete]
-; '("Complete Before Point" . term-dynamic-complete))
-; ;; Put them in the menu bar:
-; (setq menu-bar-final-items (append '(terminal completion inout signals)
-; menu-bar-final-items))
- )
-
-;; Menu bars:
-(term-ifnot-xemacs
- (term-if-emacs19
-
- ;; terminal:
- (let (newmap)
- (setq newmap (make-sparse-keymap "Terminal"))
- (define-key newmap [terminal-pager-enable]
- '("Enable paging" . term-fake-pager-enable))
- (define-key newmap [terminal-pager-disable]
- '("Disable paging" . term-fake-pager-disable))
- (define-key newmap [terminal-char-mode]
- '("Character mode" . term-char-mode))
- (define-key newmap [terminal-line-mode]
- '("Line mode" . term-line-mode))
- (setq term-terminal-menu (cons "Terminal" newmap))
-
- ;; completion: (line mode only)
- (defvar term-completion-menu (make-sparse-keymap "Complete"))
- (define-key term-mode-map [menu-bar completion]
- (cons "Complete" term-completion-menu))
- (define-key term-completion-menu [complete-expand]
- '("Expand File Name" . term-replace-by-expanded-filename))
- (define-key term-completion-menu [complete-listing]
- '("File Completion Listing" . term-dynamic-list-filename-completions))
- (define-key term-completion-menu [menu-bar completion complete-file]
- '("Complete File Name" . term-dynamic-complete-filename))
- (define-key term-completion-menu [menu-bar completion complete]
- '("Complete Before Point" . term-dynamic-complete))
-
- ;; Input history: (line mode only)
- (defvar term-inout-menu (make-sparse-keymap "In/Out"))
- (define-key term-mode-map [menu-bar inout]
- (cons "In/Out" term-inout-menu))
- (define-key term-inout-menu [kill-output]
- '("Kill Current Output Group" . term-kill-output))
- (define-key term-inout-menu [next-prompt]
- '("Forward Output Group" . term-next-prompt))
- (define-key term-inout-menu [previous-prompt]
- '("Backward Output Group" . term-previous-prompt))
- (define-key term-inout-menu [show-maximum-output]
- '("Show Maximum Output" . term-show-maximum-output))
- (define-key term-inout-menu [show-output]
- '("Show Current Output Group" . term-show-output))
- (define-key term-inout-menu [kill-input]
- '("Kill Current Input" . term-kill-input))
- (define-key term-inout-menu [copy-input]
- '("Copy Old Input" . term-copy-old-input))
- (define-key term-inout-menu [forward-matching-history]
- '("Forward Matching Input..." . term-forward-matching-input))
- (define-key term-inout-menu [backward-matching-history]
- '("Backward Matching Input..." . term-backward-matching-input))
- (define-key term-inout-menu [next-matching-history]
- '("Next Matching Input..." . term-next-matching-input))
- (define-key term-inout-menu [previous-matching-history]
- '("Previous Matching Input..." . term-previous-matching-input))
- (define-key term-inout-menu [next-matching-history-from-input]
- '("Next Matching Current Input" . term-next-matching-input-from-input))
- (define-key term-inout-menu [previous-matching-history-from-input]
- '("Previous Matching Current Input" . term-previous-matching-input-from-input))
- (define-key term-inout-menu [next-history]
- '("Next Input" . term-next-input))
- (define-key term-inout-menu [previous-history]
- '("Previous Input" . term-previous-input))
- (define-key term-inout-menu [list-history]
- '("List Input History" . term-dynamic-list-input-ring))
- (define-key term-inout-menu [expand-history]
- '("Expand History Before Point" . term-replace-by-expanded-history))
-
- ;; Signals
- (setq newmap (make-sparse-keymap "Signals"))
- (define-key newmap [eof] '("EOF" . term-send-eof))
- (define-key newmap [kill] '("KILL" . term-kill-subjob))
- (define-key newmap [quit] '("QUIT" . term-quit-subjob))
- (define-key newmap [cont] '("CONT" . term-continue-subjob))
- (define-key newmap [stop] '("STOP" . term-stop-subjob))
- (define-key newmap [] '("BREAK" . term-interrupt-subjob))
- (define-key term-mode-map [menu-bar signals]
- (setq term-signals-menu (cons "Signals" newmap)))
- )))
-
-(defun term-reset-size (height width)
- (setq term-height height)
- (setq term-width width)
- (setq term-start-line-column nil)
- (setq term-current-row nil)
- (setq term-current-column nil)
- (term-scroll-region 0 height))
-
-;; Recursive routine used to check if any string in term-kill-echo-list
-;; matches part of the buffer before point.
-;; If so, delete that matched part of the buffer - this suppresses echo.
-;; Also, remove that string from the term-kill-echo-list.
-;; We *also* remove any older string on the list, as a sanity measure,
-;; in case something gets out of sync. (Except for type-ahead, there
-;; should only be one element in the list.)
-
-(defun term-check-kill-echo-list ()
- (let ((cur term-kill-echo-list) (found nil) (save-point (point)))
- (unwind-protect
- (progn
- (end-of-line)
- (while cur
- (let* ((str (car cur)) (len (length str)) (start (- (point) len)))
- (if (and (>= start (point-min))
- (string= str (buffer-substring start (point))))
- (progn (delete-backward-char len)
- (setq term-kill-echo-list (cdr cur))
- (setq term-current-column nil)
- (setq term-current-row nil)
- (setq term-start-line-column nil)
- (setq cur nil found t))
- (setq cur (cdr cur))))))
- (if (not found)
- (goto-char save-point)))
- found))
-
-(defun term-check-size (process)
- (if (or (/= term-height (1- (window-height)))
- (/= term-width (1- (window-width))))
- (progn
- (term-reset-size (1- (window-height)) (1- (window-width)))
- (set-process-window-size process term-height term-width))))
-
-(defun term-send-raw-string (chars)
- (let ((proc (get-buffer-process (current-buffer))))
- (if (not proc)
- (error "Current buffer has no process")
- ;; Note that (term-current-row) must be called *after*
- ;; (point) has been updated to (process-mark proc).
- (goto-char (process-mark proc))
- (if (term-pager-enabled)
- (setq term-pager-count (term-current-row)))
- (process-send-string proc chars))))
-
-(defun term-send-raw ()
- "Send the last character typed through the terminal-emulator
-without any interpretation."
- (interactive)
- ;; Convert `return' to C-m, etc.
- (if (and (symbolp last-input-char)
- (get last-input-char 'ascii-character))
- (setq last-input-char (get last-input-char 'ascii-character)))
- (term-send-raw-string (make-string 1 last-input-char)))
-
-(defun term-send-raw-meta ()
- (interactive)
- (if (symbolp last-input-char)
- ;; Convert `return' to C-m, etc.
- (let ((tmp (get last-input-char 'event-symbol-elements)))
- (if tmp
- (setq last-input-char (car tmp)))
- (if (symbolp last-input-char)
- (progn
- (setq tmp (get last-input-char 'ascii-character))
- (if tmp (setq last-input-char tmp))))))
- (term-send-raw-string (if (and (numberp last-input-char)
- (> last-input-char 127)
- (< last-input-char 256))
- (make-string 1 last-input-char)
- (format "\e%c" last-input-char))))
-
-(defun term-mouse-paste (click arg)
- "Insert the last stretch of killed text at the position clicked on."
- (interactive "e\nP")
- (term-if-xemacs
- (term-send-raw-string (or (condition-case () (x-get-selection) (error ()))
- (x-get-cutbuffer)
- (error "No selection or cut buffer available"))))
- (term-ifnot-xemacs
- ;; Give temporary modes such as isearch a chance to turn off.
- (run-hooks 'mouse-leave-buffer-hook)
- (setq this-command 'yank)
- (term-send-raw-string (current-kill (cond
- ((listp arg) 0)
- ((eq arg '-) -1)
- (t (1- arg)))))))
-
-;; Which would be better: "\e[A" or "\eOA"? readline accepts either.
-(defun term-send-up () (interactive) (term-send-raw-string "\e[A"))
-(defun term-send-down () (interactive) (term-send-raw-string "\e[B"))
-(defun term-send-right () (interactive) (term-send-raw-string "\e[C"))
-(defun term-send-left () (interactive) (term-send-raw-string "\e[D"))
-
-(defun term-set-escape-char (c)
- "Change term-escape-char and keymaps that depend on it."
- (if term-escape-char
- (define-key term-raw-map term-escape-char 'term-send-raw))
- (setq c (make-string 1 c))
- (define-key term-raw-map c term-raw-escape-map)
- ;; Define standard bindings in term-raw-escape-map
- (define-key term-raw-escape-map "\C-x"
- (lookup-key (current-global-map) "\C-x"))
- (define-key term-raw-escape-map "\C-v"
- (lookup-key (current-global-map) "\C-v"))
- (define-key term-raw-escape-map "\C-u"
- (lookup-key (current-global-map) "\C-u"))
- (define-key term-raw-escape-map c 'term-send-raw)
- (define-key term-raw-escape-map "\C-q" 'term-pager-toggle)
- ;; The keybinding for term-char-mode is needed by the menubar code.
- (define-key term-raw-escape-map "\C-k" 'term-char-mode)
- (define-key term-raw-escape-map "\C-j" 'term-line-mode))
-
-(defun term-char-mode ()
- "Switch to char (\"raw\") sub-mode of term mode.
-Each character you type is sent directly to the inferior without
-intervention from emacs, except for the escape character (usually C-c)."
- (interactive)
- (if (not term-raw-map)
- (let* ((map (make-keymap))
- (esc-map (make-keymap))
- (i 0))
- (while (< i 128)
- (define-key map (make-string 1 i) 'term-send-raw)
- (define-key esc-map (make-string 1 i) 'term-send-raw-meta)
- (setq i (1+ i)))
- (define-key map "\e" esc-map)
- (setq term-raw-map map)
- (setq term-raw-escape-map
- (copy-keymap (lookup-key (current-global-map) "\C-x")))
- (term-if-emacs19
- (term-if-xemacs
- (define-key term-raw-map [button2] 'term-mouse-paste))
- (term-ifnot-xemacs
- (define-key term-raw-map [mouse-2] 'term-mouse-paste)
- (define-key term-raw-map [menu-bar terminal] term-terminal-menu)
- (define-key term-raw-map [menu-bar signals] term-signals-menu))
- (define-key term-raw-map [up] 'term-send-up)
- (define-key term-raw-map [down] 'term-send-down)
- (define-key term-raw-map [right] 'term-send-right)
- (define-key term-raw-map [left] 'term-send-left))
- (term-set-escape-char ?\C-c)))
- ;; FIXME: Emit message? Cfr ilisp-raw-message
- (if (term-in-line-mode)
- (progn
- (setq term-old-mode-map (current-local-map))
- (use-local-map term-raw-map)
-
- ;; Send existing partial line to inferior (without newline).
- (let ((pmark (process-mark (get-buffer-process (current-buffer))))
- (save-input-sender term-input-sender))
- (if (> (point) pmark)
- (unwind-protect
- (progn
- (setq term-input-sender
- (symbol-function 'term-send-string))
- (end-of-line)
- (term-send-input))
- (setq term-input-sender save-input-sender))))
- (term-update-mode-line))))
-
-(defun term-line-mode ()
- "Switch to line (\"cooked\") sub-mode of term mode.
-This means that emacs editing commands work as normally, until
-you type \\[term-send-input] which sends the current line to the inferior."
- (interactive)
- (if (term-in-char-mode)
- (progn
- (use-local-map term-old-mode-map)
- (term-update-mode-line))))
-
-(defun term-update-mode-line ()
- (setq mode-line-process
- (if (term-in-char-mode)
- (if (term-pager-enabled) '(": char page %s") '(": char %s"))
- (if (term-pager-enabled) '(": line page %s") '(": line %s"))))
- (force-mode-line-update))
-
-(defun term-check-proc (buffer)
- "True if there is a process associated w/buffer BUFFER, and
-it is alive (status RUN or STOP). BUFFER can be either a buffer or the
-name of one"
- (let ((proc (get-buffer-process buffer)))
- (and proc (memq (process-status proc) '(run stop)))))
-
-;;; Note that this guy, unlike shell.el's make-shell, barfs if you pass it ()
-;;; for the second argument (program).
-;;;###autoload
-(defun make-term (name program &optional startfile &rest switches)
-"Make a term process NAME in a buffer, running PROGRAM.
-The name of the buffer is made by surrounding NAME with `*'s.
-If there is already a running process in that buffer, it is not restarted.
-Optional third arg STARTFILE is the name of a file to send the contents of to
-the process. Any more args are arguments to PROGRAM."
- (let ((buffer (get-buffer-create (concat "*" name "*"))))
- ;; If no process, or nuked process, crank up a new one and put buffer in
- ;; term mode. Otherwise, leave buffer and existing process alone.
- (cond ((not (term-check-proc buffer))
- (save-excursion
- (set-buffer buffer)
- (term-mode)) ; Install local vars, mode, keymap, ...
- (term-exec buffer name program startfile switches)))
- buffer))
-
-;;;###autoload
-(defun term (program)
- "Start a terminal-emulator in a new buffer."
- (interactive (list (read-from-minibuffer "Run program: "
- (or explicit-shell-file-name
- (getenv "ESHELL")
- (getenv "SHELL")
- "/bin/sh"))))
- (set-buffer (make-term "terminal" program))
- (term-mode)
- (term-char-mode)
- (switch-to-buffer "*terminal*"))
-
-(defun term-exec (buffer name command startfile switches)
- "Start up a process in buffer for term 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 term
-buffer. The hook term-exec-hook is run after each exec."
- (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 (term-exec-1 name buffer command switches)))
- (make-local-variable 'term-ptyp)
- (setq term-ptyp process-connection-type) ; T if pty, NIL if pipe.
- ;; Jump to the end, and set the process mark.
- (goto-char (point-max))
- (set-marker (process-mark proc) (point))
- (set-process-filter proc 'term-emulate-terminal)
- ;; Feed it the startfile.
- (cond (startfile
- ;;This is guaranteed to wait long enough
- ;;but has bad results if the term 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))
- (term-send-string proc startfile)))
- (run-hooks 'term-exec-hook)
- buffer)))
-
-;;; Name to use for TERM.
-;;; Using "emacs" loses, because bash disables editing if TERM == emacs.
-(defvar term-term-name "eterm")
-; Format string, usage: (format term-termcap-string emacs-term-name "TERMCAP=" 24 80)
-(defvar term-termcap-format
- "%s%s:li#%d:co#%d:cl=\\E[H\\E[J:cd=\\E[J:bs:am:xn:cm=\\E[%%i%%d;%%dH\
-:nd=\\E[C:up=\\E[A:ce=\\E[K:ho=\\E[H:pt\
-:al=\\E[L:dl=\\E[M:DL=\\E[%%dM:AL=\\E[%%dL:cs=\\E[%%i%%d;%%dr:sf=\\n\
-:te=\\E[2J\\E[?47l\\E8:ti=\\E7\\E[?47h\
-:dc=\\E[P:DC=\\E[%%dP:IC=\\E[%%d@:im=\\E[4h:ei=\\E[4l:mi:\
-:so=\\E[7m:se=\\E[m:us=\\E[4m:ue=\\E[m:md=\\E[1m:mr=\\E[7m:me=\\E[m\
-:UP=\\E[%%dA:DO=\\E[%%dB:LE=\\E[%%dD:RI=\\E[%%dC"
-;;; : -undefine ic
- "termcap capabilities supported")
-
-;;; This auxiliary function cranks up the process for term-exec in
-;;; the appropriate environment.
-
-(defun term-exec-1 (name buffer command switches)
- ;; We need to do an extra (fork-less) exec to run stty.
- ;; (This would not be needed if we had suitable emacs primitives.)
- ;; The 'if ...; then shift; fi' hack is because Bourne shell
- ;; loses one arg when called with -c, and newer shells (bash, ksh) don't.
- ;; Thus we add an extra dummy argument "..", and then remove it.
- (let ((process-environment
- (nconc
- (list
- (format "TERM=%s" term-term-name)
- (if (and (boundp 'system-uses-terminfo) system-uses-terminfo)
- (format "TERMINFO=%s" data-directory)
- (format term-termcap-format "TERMCAP="
- term-term-name term-height term-width))
- (format "EMACS=%s (term:%s)" emacs-version term-protocol-version)
- (format "LINES=%d" term-height)
- (format "COLUMNS=%d" term-width))
- process-environment))
- (process-connection-type t))
- (apply 'start-process name buffer
- "/bin/sh" "-c"
- (format "stty -nl echo rows %d columns %d sane 2>/dev/null;\
-if [ $1 = .. ]; then shift; fi; exec \"$@\""
- term-height term-width)
- ".."
- command switches)))
-
-;;; This should be in emacs, but it isn't.
-(defun term-mem (item list &optional elt=)
- "Test to see if ITEM is equal to an item in LIST.
-Option comparison function ELT= defaults to equal."
- (let ((elt= (or elt= (function equal)))
- (done nil))
- (while (and list (not done))
- (if (funcall elt= item (car list))
- (setq done list)
- (setq list (cdr list))))
- done))
-
-
-;;; Input history processing in a buffer
-;;; ===========================================================================
-;;; Useful input history functions, courtesy of the Ergo group.
-
-;;; Eleven commands:
-;;; term-dynamic-list-input-ring List history in help buffer.
-;;; term-previous-input Previous input...
-;;; term-previous-matching-input ...matching a string.
-;;; term-previous-matching-input-from-input ... matching the current input.
-;;; term-next-input Next input...
-;;; term-next-matching-input ...matching a string.
-;;; term-next-matching-input-from-input ... matching the current input.
-;;; term-backward-matching-input Backwards input...
-;;; term-forward-matching-input ...matching a string.
-;;; term-replace-by-expanded-history Expand history at point;
-;;; replace with expanded history.
-;;; term-magic-space Expand history and insert space.
-;;;
-;;; Three functions:
-;;; term-read-input-ring Read into term-input-ring...
-;;; term-write-input-ring Write to term-input-ring-file-name.
-;;; term-replace-by-expanded-history-before-point Workhorse function.
-
-(defun term-read-input-ring (&optional silent)
- "Sets the buffer's `term-input-ring' from a history file.
-The name of the file is given by the variable `term-input-ring-file-name'.
-The history ring is of size `term-input-ring-size', regardless of file size.
-If `term-input-ring-file-name' is nil this function does nothing.
-
-If the optional argument SILENT is non-nil, we say nothing about a
-failure to read the history file.
-
-This function is useful for major mode commands and mode hooks.
-
-The structure of the history file should be one input command per line,
-with the most recent command last.
-See also `term-input-ignoredups' and `term-write-input-ring'."
- (cond ((or (null term-input-ring-file-name)
- (equal term-input-ring-file-name ""))
- nil)
- ((not (file-readable-p term-input-ring-file-name))
- (or silent
- (message "Cannot read history file %s"
- term-input-ring-file-name)))
- (t
- (let ((history-buf (get-buffer-create " *temp*"))
- (file term-input-ring-file-name)
- (count 0)
- (ring (make-ring term-input-ring-size)))
- (unwind-protect
- (save-excursion
- (set-buffer history-buf)
- (widen)
- (erase-buffer)
- (insert-file-contents file)
- ;; Save restriction in case file is already visited...
- ;; Watch for those date stamps in history files!
- (goto-char (point-max))
- (while (and (< count term-input-ring-size)
- (re-search-backward "^[ \t]*\\([^#\n].*\\)[ \t]*$"
- nil t))
- (let ((history (buffer-substring (match-beginning 1)
- (match-end 1))))
- (if (or (null term-input-ignoredups)
- (ring-empty-p ring)
- (not (string-equal (ring-ref ring 0) history)))
- (ring-insert-at-beginning ring history)))
- (setq count (1+ count))))
- (kill-buffer history-buf))
- (setq term-input-ring ring
- term-input-ring-index nil)))))
-
-(defun term-write-input-ring ()
- "Writes the buffer's `term-input-ring' to a history file.
-The name of the file is given by the variable `term-input-ring-file-name'.
-The original contents of the file are lost if `term-input-ring' is not empty.
-If `term-input-ring-file-name' is nil this function does nothing.
-
-Useful within process sentinels.
-
-See also `term-read-input-ring'."
- (cond ((or (null term-input-ring-file-name)
- (equal term-input-ring-file-name "")
- (null term-input-ring) (ring-empty-p term-input-ring))
- nil)
- ((not (file-writable-p term-input-ring-file-name))
- (message "Cannot write history file %s" term-input-ring-file-name))
- (t
- (let* ((history-buf (get-buffer-create " *Temp Input History*"))
- (ring term-input-ring)
- (file term-input-ring-file-name)
- (index (ring-length ring)))
- ;; Write it all out into a buffer first. Much faster, but messier,
- ;; than writing it one line at a time.
- (save-excursion
- (set-buffer history-buf)
- (erase-buffer)
- (while (> index 0)
- (setq index (1- index))
- (insert (ring-ref ring index) ?\n))
- (write-region (buffer-string) nil file nil 'no-message)
- (kill-buffer nil))))))
-
-
-(defun term-dynamic-list-input-ring ()
- "List in help buffer the buffer's input history."
- (interactive)
- (if (or (not (ring-p term-input-ring))
- (ring-empty-p term-input-ring))
- (message "No history")
- (let ((history nil)
- (history-buffer " *Input History*")
- (index (1- (ring-length term-input-ring)))
- (conf (current-window-configuration)))
- ;; We have to build up a list ourselves from the ring vector.
- (while (>= index 0)
- (setq history (cons (ring-ref term-input-ring index) history)
- index (1- index)))
- ;; Change "completion" to "history reference"
- ;; to make the display accurate.
- (with-output-to-temp-buffer history-buffer
- (display-completion-list history)
- (set-buffer history-buffer)
- (forward-line 3)
- (while (search-backward "completion" nil 'move)
- (replace-match "history reference")))
- (sit-for 0)
- (message "Hit space to flush")
- (let ((ch (read-event)))
- (if (eq ch ?\ )
- (set-window-configuration conf)
- (setq unread-command-events (list ch)))))))
-
-
-(defun term-regexp-arg (prompt)
- ;; Return list of regexp and prefix arg using PROMPT.
- (let* ((minibuffer-history-sexp-flag nil)
- ;; Don't clobber this.
- (last-command last-command)
- (regexp (read-from-minibuffer prompt nil nil nil
- 'minibuffer-history-search-history)))
- (list (if (string-equal regexp "")
- (setcar minibuffer-history-search-history
- (nth 1 minibuffer-history-search-history))
- regexp)
- (prefix-numeric-value current-prefix-arg))))
-
-(defun term-search-arg (arg)
- ;; First make sure there is a ring and that we are after the process mark
- (cond ((not (term-after-pmark-p))
- (error "Not at command line"))
- ((or (null term-input-ring)
- (ring-empty-p term-input-ring))
- (error "Empty input ring"))
- ((zerop arg)
- ;; arg of zero resets search from beginning, and uses arg of 1
- (setq term-input-ring-index nil)
- 1)
- (t
- arg)))
-
-(defun term-search-start (arg)
- ;; Index to start a directional search, starting at term-input-ring-index
- (if term-input-ring-index
- ;; If a search is running, offset by 1 in direction of arg
- (mod (+ term-input-ring-index (if (> arg 0) 1 -1))
- (ring-length term-input-ring))
- ;; For a new search, start from beginning or end, as appropriate
- (if (>= arg 0)
- 0 ; First elt for forward search
- (1- (ring-length term-input-ring))))) ; Last elt for backward search
-
-(defun term-previous-input-string (arg)
- "Return the string ARG places along the input ring.
-Moves relative to `term-input-ring-index'."
- (ring-ref term-input-ring (if term-input-ring-index
- (mod (+ arg term-input-ring-index)
- (ring-length term-input-ring))
- arg)))
-
-(defun term-previous-input (arg)
- "Cycle backwards through input history."
- (interactive "*p")
- (term-previous-matching-input "." arg))
-
-(defun term-next-input (arg)
- "Cycle forwards through input history."
- (interactive "*p")
- (term-previous-input (- arg)))
-
-(defun term-previous-matching-input-string (regexp arg)
- "Return the string matching REGEXP ARG places along the input ring.
-Moves relative to `term-input-ring-index'."
- (let* ((pos (term-previous-matching-input-string-position regexp arg)))
- (if pos (ring-ref term-input-ring pos))))
-
-(defun term-previous-matching-input-string-position (regexp arg &optional start)
- "Return the index matching REGEXP ARG places along the input ring.
-Moves relative to START, or `term-input-ring-index'."
- (if (or (not (ring-p term-input-ring))
- (ring-empty-p term-input-ring))
- (error "No history"))
- (let* ((len (ring-length term-input-ring))
- (motion (if (> arg 0) 1 -1))
- (n (mod (- (or start (term-search-start arg)) motion) len))
- (tried-each-ring-item nil)
- (prev nil))
- ;; Do the whole search as many times as the argument says.
- (while (and (/= arg 0) (not tried-each-ring-item))
- ;; Step once.
- (setq prev n
- n (mod (+ n motion) len))
- ;; If we haven't reached a match, step some more.
- (while (and (< n len) (not tried-each-ring-item)
- (not (string-match regexp (ring-ref term-input-ring n))))
- (setq n (mod (+ n motion) len)
- ;; If we have gone all the way around in this search.
- tried-each-ring-item (= n prev)))
- (setq arg (if (> arg 0) (1- arg) (1+ arg))))
- ;; Now that we know which ring element to use, if we found it, return that.
- (if (string-match regexp (ring-ref term-input-ring n))
- n)))
-
-(defun term-previous-matching-input (regexp arg)
- "Search backwards through input history for match for REGEXP.
-\(Previous history elements are earlier commands.)
-With prefix argument N, search for Nth previous match.
-If N is negative, find the next or Nth next match."
- (interactive (term-regexp-arg "Previous input matching (regexp): "))
- (setq arg (term-search-arg arg))
- (let ((pos (term-previous-matching-input-string-position regexp arg)))
- ;; Has a match been found?
- (if (null pos)
- (error "Not found")
- (setq term-input-ring-index pos)
- (message "History item: %d" (1+ pos))
- (delete-region
- ;; Can't use kill-region as it sets this-command
- (process-mark (get-buffer-process (current-buffer))) (point))
- (insert (ring-ref term-input-ring pos)))))
-
-(defun term-next-matching-input (regexp arg)
- "Search forwards through input history for match for REGEXP.
-\(Later history elements are more recent commands.)
-With prefix argument N, search for Nth following match.
-If N is negative, find the previous or Nth previous match."
- (interactive (term-regexp-arg "Next input matching (regexp): "))
- (term-previous-matching-input regexp (- arg)))
-
-(defun term-previous-matching-input-from-input (arg)
- "Search backwards through input history for match for current input.
-\(Previous history elements are earlier commands.)
-With prefix argument N, search for Nth previous match.
-If N is negative, search forwards for the -Nth following match."
- (interactive "p")
- (if (not (memq last-command '(term-previous-matching-input-from-input
- term-next-matching-input-from-input)))
- ;; Starting a new search
- (setq term-matching-input-from-input-string
- (buffer-substring
- (process-mark (get-buffer-process (current-buffer)))
- (point))
- term-input-ring-index nil))
- (term-previous-matching-input
- (concat "^" (regexp-quote term-matching-input-from-input-string))
- arg))
-
-(defun term-next-matching-input-from-input (arg)
- "Search forwards through input history for match for current input.
-\(Following history elements are more recent commands.)
-With prefix argument N, search for Nth following match.
-If N is negative, search backwards for the -Nth previous match."
- (interactive "p")
- (term-previous-matching-input-from-input (- arg)))
-
-
-(defun term-replace-by-expanded-history (&optional silent)
- "Expand input command history references before point.
-Expansion is dependent on the value of `term-input-autoexpand'.
-
-This function depends on the buffer's idea of the input history, which may not
-match the command interpreter's idea, assuming it has one.
-
-Assumes history syntax is like typical Un*x shells'. However, since emacs
-cannot know the interpreter's idea of input line numbers, assuming it has one,
-it cannot expand absolute input line number references.
-
-If the optional argument SILENT is non-nil, never complain
-even if history reference seems erroneous.
-
-See `term-magic-space' and `term-replace-by-expanded-history-before-point'.
-
-Returns t if successful."
- (interactive)
- (if (and term-input-autoexpand
- (string-match "[!^]" (funcall term-get-old-input))
- (save-excursion (beginning-of-line)
- (looking-at term-prompt-regexp)))
- ;; Looks like there might be history references in the command.
- (let ((previous-modified-tick (buffer-modified-tick)))
- (message "Expanding history references...")
- (term-replace-by-expanded-history-before-point silent)
- (/= previous-modified-tick (buffer-modified-tick)))))
-
-
-(defun term-replace-by-expanded-history-before-point (silent)
- "Expand directory stack reference before point.
-See `term-replace-by-expanded-history'. Returns t if successful."
- (save-excursion
- (let ((toend (- (save-excursion (end-of-line nil) (point)) (point)))
- (start (progn (term-bol nil) (point))))
- (while (progn
- (skip-chars-forward "^!^"
- (save-excursion
- (end-of-line nil) (- (point) toend)))
- (< (point)
- (save-excursion
- (end-of-line nil) (- (point) toend))))
- ;; This seems a bit complex. We look for references such as !!, !-num,
- ;; !foo, !?foo, !{bar}, !?{bar}, ^oh, ^my^, ^god^it, ^never^ends^.
- ;; If that wasn't enough, the plings can be suffixed with argument
- ;; range specifiers.
- ;; Argument ranges are complex too, so we hive off the input line,
- ;; referenced with plings, with the range string to `term-args'.
- (setq term-input-ring-index nil)
- (cond ((or (= (preceding-char) ?\\)
- (term-within-quotes start (point)))
- ;; The history is quoted, or we're in quotes.
- (goto-char (1+ (point))))
- ((looking-at "![0-9]+\\($\\|[^-]\\)")
- ;; We cannot know the interpreter's idea of input line numbers.
- (goto-char (match-end 0))
- (message "Absolute reference cannot be expanded"))
- ((looking-at "!-\\([0-9]+\\)\\(:?[0-9^$*-]+\\)?")
- ;; Just a number of args from `number' lines backward.
- (let ((number (1- (string-to-number
- (buffer-substring (match-beginning 1)
- (match-end 1))))))
- (if (<= number (ring-length term-input-ring))
- (progn
- (replace-match
- (term-args (term-previous-input-string number)
- (match-beginning 2) (match-end 2))
- t t)
- (setq term-input-ring-index number)
- (message "History item: %d" (1+ number)))
- (goto-char (match-end 0))
- (message "Relative reference exceeds input history size"))))
- ((or (looking-at "!!?:?\\([0-9^$*-]+\\)") (looking-at "!!"))
- ;; Just a number of args from the previous input line.
- (replace-match
- (term-args (term-previous-input-string 0)
- (match-beginning 1) (match-end 1))
- t t)
- (message "History item: previous"))
- ((looking-at
- "!\\??\\({\\(.+\\)}\\|\\(\\sw+\\)\\)\\(:?[0-9^$*-]+\\)?")
- ;; Most recent input starting with or containing (possibly
- ;; protected) string, maybe just a number of args. Phew.
- (let* ((mb1 (match-beginning 1)) (me1 (match-end 1))
- (mb2 (match-beginning 2)) (me2 (match-end 2))
- (exp (buffer-substring (or mb2 mb1) (or me2 me1)))
- (pref (if (save-match-data (looking-at "!\\?")) "" "^"))
- (pos (save-match-data
- (term-previous-matching-input-string-position
- (concat pref (regexp-quote exp)) 1))))
- (if (null pos)
- (progn
- (goto-char (match-end 0))
- (or silent
- (progn (message "Not found")
- (ding))))
- (setq term-input-ring-index pos)
- (replace-match
- (term-args (ring-ref term-input-ring pos)
- (match-beginning 4) (match-end 4))
- t t)
- (message "History item: %d" (1+ pos)))))
- ((looking-at "\\^\\([^^]+\\)\\^?\\([^^]*\\)\\^?")
- ;; Quick substitution on the previous input line.
- (let ((old (buffer-substring (match-beginning 1) (match-end 1)))
- (new (buffer-substring (match-beginning 2) (match-end 2)))
- (pos nil))
- (replace-match (term-previous-input-string 0) t t)
- (setq pos (point))
- (goto-char (match-beginning 0))
- (if (not (search-forward old pos t))
- (or silent
- (error "Not found"))
- (replace-match new t t)
- (message "History item: substituted"))))
- (t
- (goto-char (match-end 0))))))))
-
-
-(defun term-magic-space (arg)
- "Expand input history references before point and insert ARG spaces.
-A useful command to bind to SPC. See `term-replace-by-expanded-history'."
- (interactive "p")
- (term-replace-by-expanded-history)
- (self-insert-command arg))
-
-(defun term-within-quotes (beg end)
- "Return t if the number of quotes between BEG and END is odd.
-Quotes are single and double."
- (let ((countsq (term-how-many-region "\\(^\\|[^\\\\]\\)\'" beg end))
- (countdq (term-how-many-region "\\(^\\|[^\\\\]\\)\"" beg end)))
- (or (= (mod countsq 2) 1) (= (mod countdq 2) 1))))
-
-(defun term-how-many-region (regexp beg end)
- "Return number of matches for REGEXP from BEG to END."
- (let ((count 0))
- (save-excursion
- (save-match-data
- (goto-char beg)
- (while (re-search-forward regexp end t)
- (setq count (1+ count)))))
- count))
-
-(defun term-args (string begin end)
- ;; From STRING, return the args depending on the range specified in the text
- ;; from BEGIN to END. If BEGIN is nil, assume all args. Ignore leading `:'.
- ;; Range can be x-y, x-, -y, where x/y can be [0-9], *, ^, $.
- (save-match-data
- (if (null begin)
- (term-arguments string 0 nil)
- (let* ((range (buffer-substring
- (if (eq (char-after begin) ?:) (1+ begin) begin) end))
- (nth (cond ((string-match "^[*^]" range) 1)
- ((string-match "^-" range) 0)
- ((string-equal range "$") nil)
- (t (string-to-number range))))
- (mth (cond ((string-match "[-*$]$" range) nil)
- ((string-match "-" range)
- (string-to-number (substring range (match-end 0))))
- (t nth))))
- (term-arguments string nth mth)))))
-
-;; Return a list of arguments from ARG. Break it up at the
-;; delimiters in term-delimiter-argument-list. Returned list is backwards.
-(defun term-delim-arg (arg)
- (if (null term-delimiter-argument-list)
- (list arg)
- (let ((args nil)
- (pos 0)
- (len (length arg)))
- (while (< pos len)
- (let ((char (aref arg pos))
- (start pos))
- (if (memq char term-delimiter-argument-list)
- (while (and (< pos len) (eq (aref arg pos) char))
- (setq pos (1+ pos)))
- (while (and (< pos len)
- (not (memq (aref arg pos)
- term-delimiter-argument-list)))
- (setq pos (1+ pos))))
- (setq args (cons (substring arg start pos) args))))
- args)))
-
-(defun term-arguments (string nth mth)
- "Return from STRING the NTH to MTH arguments.
-NTH and/or MTH can be nil, which means the last argument.
-Returned arguments are separated by single spaces.
-We assume whitespace separates arguments, except within quotes.
-Also, a run of one or more of a single character
-in `term-delimiter-argument-list' is a separate argument.
-Argument 0 is the command name."
- (let ((argpart "[^ \n\t\"'`]+\\|\\(\"[^\"]*\"\\|'[^']*'\\|`[^`]*`\\)")
- (args ()) (pos 0)
- (count 0)
- beg str quotes)
- ;; Build a list of all the args until we have as many as we want.
- (while (and (or (null mth) (<= count mth))
- (string-match argpart string pos))
- (if (and beg (= pos (match-beginning 0)))
- ;; It's contiguous, part of the same arg.
- (setq pos (match-end 0)
- quotes (or quotes (match-beginning 1)))
- ;; It's a new separate arg.
- (if beg
- ;; Put the previous arg, if there was one, onto ARGS.
- (setq str (substring string beg pos)
- args (if quotes (cons str args)
- (nconc (term-delim-arg str) args))
- count (1+ count)))
- (setq quotes (match-beginning 1))
- (setq beg (match-beginning 0))
- (setq pos (match-end 0))))
- (if beg
- (setq str (substring string beg pos)
- args (if quotes (cons str args)
- (nconc (term-delim-arg str) args))
- count (1+ count)))
- (let ((n (or nth (1- count)))
- (m (if mth (1- (- count mth)) 0)))
- (mapconcat
- (function (lambda (a) a)) (nthcdr n (nreverse (nthcdr m args))) " "))))
-
-;;;
-;;; Input processing stuff [line mode]
-;;;
-
-(defun term-send-input ()
- "Send input to process.
-After the process output mark, sends all text from the process mark to
-point as input to the process. Before the process output mark, calls value
-of variable term-get-old-input to retrieve old input, copies it to the
-process mark, and sends it. A terminal newline is also inserted into the
-buffer and sent to the process. The list of function names contained in the
-value of `term-input-filter-functions' is called on the input before sending
-it. The input is entered into the input history ring, if the value of variable
-term-input-filter returns non-nil when called on the input.
-
-Any history reference may be expanded depending on the value of the variable
-`term-input-autoexpand'. The list of function names contained in the value
-of `term-input-filter-functions' is called on the input before sending it.
-The input is entered into the input history ring, if the value of variable
-`term-input-filter' returns non-nil when called on the input.
-
-If variable `term-eol-on-send' is non-nil, then point is moved to the
-end of line before sending the input.
-
-The values of `term-get-old-input', `term-input-filter-functions', and
-`term-input-filter' are chosen according to the command interpreter running
-in the buffer. E.g.,
-
-If the interpreter is the csh,
- term-get-old-input is the default: take the current line, discard any
- initial string matching regexp term-prompt-regexp.
- term-input-filter-functions monitors input for \"cd\", \"pushd\", and
- \"popd\" commands. When it sees one, it cd's the buffer.
- term-input-filter is the default: returns T if the input isn't all white
- space.
-
-If the term is Lucid Common Lisp,
- term-get-old-input snarfs the sexp ending at point.
- term-input-filter-functions does nothing.
- term-input-filter returns NIL if the input matches input-filter-regexp,
- which matches (1) all whitespace (2) :a, :c, etc.
-
-Similarly for Soar, Scheme, etc."
- (interactive)
- ;; Note that the input string does not include its terminal newline.
- (let ((proc (get-buffer-process (current-buffer))))
- (if (not proc) (error "Current buffer has no process")
- (let* ((pmark (process-mark proc))
- (pmark-val (marker-position pmark))
- (input-is-new (>= (point) pmark-val))
- (intxt (if input-is-new
- (progn (if term-eol-on-send (end-of-line))
- (buffer-substring pmark (point)))
- (funcall term-get-old-input)))
- (input (if (not (eq term-input-autoexpand 'input))
- ;; Just whatever's already there
- intxt
- ;; Expand and leave it visible in buffer
- (term-replace-by-expanded-history t)
- (buffer-substring pmark (point))))
- (history (if (not (eq term-input-autoexpand 'history))
- input
- ;; This is messy 'cos ultimately the original
- ;; functions used do insertion, rather than return
- ;; strings. We have to expand, then insert back.
- (term-replace-by-expanded-history t)
- (let ((copy (buffer-substring pmark (point))))
- (delete-region pmark (point))
- (insert input)
- copy))))
- (if (term-pager-enabled)
- (save-excursion
- (goto-char (process-mark proc))
- (setq term-pager-count (term-current-row))))
- (if (and (funcall term-input-filter history)
- (or (null term-input-ignoredups)
- (not (ring-p term-input-ring))
- (ring-empty-p term-input-ring)
- (not (string-equal (ring-ref term-input-ring 0)
- history))))
- (ring-insert term-input-ring history))
- (let ((functions term-input-filter-functions))
- (while functions
- (funcall (car functions) (concat input "\n"))
- (setq functions (cdr functions))))
- (setq term-input-ring-index nil)
-
- ;; Update the markers before we send the input
- ;; in case we get output amidst sending the input.
- (set-marker term-last-input-start pmark)
- (set-marker term-last-input-end (point))
- (if input-is-new
- (progn
- ;; Set up to delete, because inferior should echo.
- (if (marker-buffer term-pending-delete-marker)
- (delete-region term-pending-delete-marker pmark))
- (set-marker term-pending-delete-marker pmark-val)
- (set-marker (process-mark proc) (point))))
- (goto-char pmark)
- (funcall term-input-sender proc input)))))
-
-(defun term-get-old-input-default ()
- "Default for term-get-old-input.
-Take the current line, and discard any initial text matching
-term-prompt-regexp."
- (save-excursion
- (beginning-of-line)
- (term-skip-prompt)
- (let ((beg (point)))
- (end-of-line)
- (buffer-substring beg (point)))))
-
-(defun term-copy-old-input ()
- "Insert after prompt old input at point as new input to be edited.
-Calls `term-get-old-input' to get old input."
- (interactive)
- (let ((input (funcall term-get-old-input))
- (process (get-buffer-process (current-buffer))))
- (if (not process)
- (error "Current buffer has no process")
- (goto-char (process-mark process))
- (insert input))))
-
-(defun term-skip-prompt ()
- "Skip past the text matching regexp term-prompt-regexp.
-If this takes us past the end of the current line, don't skip at all."
- (let ((eol (save-excursion (end-of-line) (point))))
- (if (and (looking-at term-prompt-regexp)
- (<= (match-end 0) eol))
- (goto-char (match-end 0)))))
-
-
-(defun term-after-pmark-p ()
- "Is point after the process output marker?"
- ;; Since output could come into the buffer after we looked at the point
- ;; but before we looked at the process marker's value, we explicitly
- ;; serialise. This is just because I don't know whether or not emacs
- ;; services input during execution of lisp commands.
- (let ((proc-pos (marker-position
- (process-mark (get-buffer-process (current-buffer))))))
- (<= proc-pos (point))))
-
-(defun term-simple-send (proc string)
- "Default function for sending to PROC input STRING.
-This just sends STRING plus a newline. To override this,
-set the hook TERM-INPUT-SENDER."
- (term-send-string proc string)
- (term-send-string proc "\n"))
-
-(defun term-bol (arg)
- "Goes to the beginning of line, then skips past the prompt, if any.
-If a prefix argument is given (\\[universal-argument]), then no prompt skip
--- go straight to column 0.
-
-The prompt skip is done by skipping text matching the regular expression
-term-prompt-regexp, a buffer local variable."
- (interactive "P")
- (beginning-of-line)
- (if (null arg) (term-skip-prompt)))
-
-;;; 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 term-send-invisible and type in your line.
-
-(defun term-read-noecho (prompt &optional stars)
- "Read a single line of text from user without echoing, and return it.
-Prompt with argument PROMPT, a string. Optional argument STARS causes
-input to be echoed with '*' characters on the prompt line. Input ends with
-RET, LFD, or ESC. DEL or C-h rubs out. C-u kills line. C-g aborts (if
-`inhibit-quit' is set because e.g. this function was called from a process
-filter and C-g is pressed, this function returns nil rather than a string).
-
-Note that the keystrokes comprising the text can still be recovered
-\(temporarily) with \\[view-lossage]. This may be a security bug for some
-applications."
- (let ((ans "")
- (c 0)
- (echo-keystrokes 0)
- (cursor-in-echo-area t)
- (done nil))
- (while (not done)
- (if stars
- (message "%s%s" prompt (make-string (length ans) ?*))
- (message "%s" prompt))
- (setq c (read-char))
- (cond ((= c ?\C-g)
- ;; This function may get called from a process filter, where
- ;; inhibit-quit is set. In later versions of emacs read-char
- ;; may clear quit-flag itself and return C-g. That would make
- ;; it impossible to quit this loop in a simple way, so
- ;; re-enable it here (for backward-compatibility the check for
- ;; quit-flag below would still be necessary, so this seems
- ;; like the simplest way to do things).
- (setq quit-flag t
- done t))
- ((or (= c ?\r) (= c ?\n) (= c ?\e))
- (setq done t))
- ((= c ?\C-u)
- (setq ans ""))
- ((and (/= c ?\b) (/= c ?\177))
- (setq ans (concat ans (char-to-string c))))
- ((> (length ans) 0)
- (setq ans (substring ans 0 -1)))))
- (if quit-flag
- ;; Emulate a true quit, except that we have to return a value.
- (prog1
- (setq quit-flag nil)
- (message "Quit")
- (beep t))
- (message "")
- ans)))
-
-(defun term-send-invisible (str &optional proc)
- "Read a string without echoing.
-Then send it to the process running in the current buffer. A new-line
-is additionally sent. String is not saved on term input history list.
-Security bug: your string can still be temporarily recovered with
-\\[view-lossage]."
- (interactive "P") ; Defeat snooping via C-x esc
- (if (not (stringp str))
- (setq str (term-read-noecho "Non-echoed text: " t)))
- (if (not proc)
- (setq proc (get-buffer-process (current-buffer))))
- (if (not proc) (error "Current buffer has no process")
- (setq term-kill-echo-list (nconc term-kill-echo-list
- (cons str nil)))
- (term-send-string proc str)
- (term-send-string proc "\n")))
-
-
-;;; Low-level process communication
-
-(defvar term-input-chunk-size 512
- "*Long inputs send to term processes are broken up into chunks of this size.
-If your process is choking on big inputs, try lowering the value.")
-
-(defun term-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 term-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 term-input-chunk-size)))
- (process-send-string proc (substring str 0 i))
- (while (< i len)
- (let ((next-i (+ i term-input-chunk-size)))
- (accept-process-output)
- (process-send-string proc (substring str i (min len next-i)))
- (setq i next-i)))))
-
-(defun term-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 term-send-string."
- (term-send-string proc (buffer-substring start end)))
-
-
-;;; Random input hackage
-
-(defun term-kill-output ()
- "Kill all output from interpreter since last input."
- (interactive)
- (let ((pmark (process-mark (get-buffer-process (current-buffer)))))
- (kill-region term-last-input-end pmark)
- (goto-char pmark)
- (insert "*** output flushed ***\n")
- (set-marker pmark (point))))
-
-(defun term-show-output ()
- "Display start of this batch of interpreter output at top of window.
-Sets mark to the value of point when this command is run."
- (interactive)
- (goto-char term-last-input-end)
- (backward-char)
- (beginning-of-line)
- (set-window-start (selected-window) (point))
- (end-of-line))
-
-(defun term-interrupt-subjob ()
- "Interrupt the current subjob."
- (interactive)
- (interrupt-process nil term-ptyp))
-
-(defun term-kill-subjob ()
- "Send kill signal to the current subjob."
- (interactive)
- (kill-process nil term-ptyp))
-
-(defun term-quit-subjob ()
- "Send quit signal to the current subjob."
- (interactive)
- (quit-process nil term-ptyp))
-
-(defun term-stop-subjob ()
- "Stop the current subjob.
-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 \\[term-continue-subjob] to resume the process. (This
-is not a problem with most shells, since they ignore this signal.)"
- (interactive)
- (stop-process nil term-ptyp))
-
-(defun term-continue-subjob ()
- "Send CONT signal to process buffer's process group.
-Useful if you accidentally suspend the top-level process."
- (interactive)
- (continue-process nil term-ptyp))
-
-(defun term-kill-input ()
- "Kill all text from last stuff output by interpreter to point."
- (interactive)
- (let* ((pmark (process-mark (get-buffer-process (current-buffer))))
- (p-pos (marker-position pmark)))
- (if (> (point) p-pos)
- (kill-region pmark (point)))))
-
-(defun term-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)))
-
-(defun term-send-eof ()
- "Send an EOF to the current buffer's process."
- (interactive)
- (process-send-eof))
-
-(defun term-backward-matching-input (regexp arg)
- "Search backward through buffer for match for REGEXP.
-Matches are searched for on lines that match `term-prompt-regexp'.
-With prefix argument N, search for Nth previous match.
-If N is negative, find the next or Nth next match."
- (interactive (term-regexp-arg "Backward input matching (regexp): "))
- (let* ((re (concat term-prompt-regexp ".*" regexp))
- (pos (save-excursion (end-of-line (if (> arg 0) 0 1))
- (if (re-search-backward re nil t arg)
- (point)))))
- (if (null pos)
- (progn (message "Not found")
- (ding))
- (goto-char pos)
- (term-bol nil))))
-
-(defun term-forward-matching-input (regexp arg)
- "Search forward through buffer for match for REGEXP.
-Matches are searched for on lines that match `term-prompt-regexp'.
-With prefix argument N, search for Nth following match.
-If N is negative, find the previous or Nth previous match."
- (interactive (term-regexp-arg "Forward input matching (regexp): "))
- (term-backward-matching-input regexp (- arg)))
-
-
-(defun term-next-prompt (n)
- "Move to end of Nth next prompt in the buffer.
-See `term-prompt-regexp'."
- (interactive "p")
- (let ((paragraph-start term-prompt-regexp))
- (end-of-line (if (> n 0) 1 0))
- (forward-paragraph n)
- (term-skip-prompt)))
-
-(defun term-previous-prompt (n)
- "Move to end of Nth previous prompt in the buffer.
-See `term-prompt-regexp'."
- (interactive "p")
- (term-next-prompt (- n)))
-
-;;; 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, ...).
-
-
-;;; TERM-SOURCE-DEFAULT -- determines defaults for source-file processing
-;;; commands.
-;;;
-;;; TERM-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.
-;;;
-;;; TERM-GET-SOURCE -- used by the source-file processing commands to prompt
-;;; for the file to process.
-
-;;; (TERM-SOURCE-DEFAULT previous-dir/file source-modes)
-;;;============================================================================
-;;; This function computes the defaults for the load-file and compile-file
-;;; commands for tea, soar, cmulisp, and cmuscheme 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 term-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))))
-
-
-;;; (TERM-CHECK-SOURCE fname)
-;;;============================================================================
-;;; Prior to loading or compiling (or otherwise processing) a file (in the CMU
-;;; 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 term-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)))))
-
-
-;;; (TERM-GET-SOURCE prompt prev-dir/file source-modes mustmatch-p)
-;;;============================================================================
-;;; TERM-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 TERM-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 (term-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 term-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 term-get-source (prompt prev-dir/file source-modes mustmatch-p)
- (let* ((def (term-source-default prev-dir/file source-modes))
- (stringfile (term-extract-string))
- (sfile-p (and stringfile
- (condition-case ()
- (file-exists-p stringfile)
- (error nil))
- (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)))))
-
-;;; I am somewhat divided on this string-default feature. It seems
-;;; to violate the principle-of-least-astonishment, in that it makes
-;;; the default harder to predict, so you actually have to look and see
-;;; what the default really is before choosing it. This can trip you up.
-;;; On the other hand, it can be useful, I guess. I would appreciate feedback
-;;; on this.
-;;; -Olin
-
-
-;;; 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 term-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)))
- (term-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)))))))
-
-;;; Returns the current column in the current screen line.
-;;; Note: (current-column) yields column in buffer line.
-
-(defun term-horizontal-column ()
- (- (term-current-column) (term-start-line-column)))
-
-;; Calls either vertical-motion or buffer-vertical-motion
-(defmacro term-vertical-motion (count)
- (list 'funcall 'term-vertical-motion count))
-
-;; An emulation of vertical-motion that is independent of having a window.
-;; Instead, it uses the term-width variable as the logical window width.
-
-(defun buffer-vertical-motion (count)
- (cond ((= count 0)
- (move-to-column (* term-width (/ (current-column) term-width)))
- 0)
- ((> count 0)
- (let ((H)
- (todo (+ count (/ (current-column) term-width))))
- (end-of-line)
- ;; The loop iterates over buffer lines;
- ;; H is the number of screen lines in the current line, i.e.
- ;; the ceiling of dividing the buffer line width by term-width.
- (while (and (<= (setq H (max (/ (+ (current-column) term-width -1)
- term-width)
- 1))
- todo)
- (not (eobp)))
- (setq todo (- todo H))
- (forward-char) ;; Move past the ?\n
- (end-of-line)) ;; and on to the end of the next line.
- (if (and (>= todo H) (> todo 0))
- (+ (- count todo) H -1) ;; Hit end of buffer.
- (move-to-column (* todo term-width))
- count)))
- (t ;; (< count 0) ;; Similar algorithm, but for upward motion.
- (let ((H)
- (todo (- count)))
- (while (and (<= (setq H (max (/ (+ (current-column) term-width -1)
- term-width)
- 1))
- todo)
- (progn (beginning-of-line)
- (not (bobp))))
- (setq todo (- todo H))
- (backward-char)) ;; Move to end of previous line.
- (if (and (>= todo H) (> todo 0))
- (+ count todo (- 1 H)) ;; Hit beginning of buffer.
- (move-to-column (* (- H todo 1) term-width))
- count)))))
-
-;;; The term-start-line-column variable is used as a cache.
-(defun term-start-line-column ()
- (cond (term-start-line-column)
- ((let ((save-pos (point)))
- (term-vertical-motion 0)
- (setq term-start-line-column (current-column))
- (goto-char save-pos)
- term-start-line-column))))
-
-;;; Same as (current-column), but uses term-current-column as a cache.
-(defun term-current-column ()
- (cond (term-current-column)
- ((setq term-current-column (current-column)))))
-
-;;; Move DELTA column right (or left if delta < 0).
-
-(defun term-move-columns (delta)
- (setq term-current-column (+ (term-current-column) delta))
- (move-to-column term-current-column t))
-
-;; Insert COUNT copies of CHAR in the default face.
-(defun term-insert-char (char count)
- (let ((old-point (point)))
- (insert-char char count)
- (put-text-property old-point (point) 'face 'default)))
-
-(defun term-current-row ()
- (cond (term-current-row)
- ((setq term-current-row
- (save-restriction
- (save-excursion
- (narrow-to-region term-home-marker (point-max))
- (- (term-vertical-motion -9999))))))))
-
-(defun term-adjust-current-row-cache (delta)
- (if term-current-row
- (setq term-current-row (+ term-current-row delta))))
-
-(defun term-terminal-pos ()
- (save-excursion ; save-restriction
- (let ((save-col (term-current-column))
- x y)
- (term-vertical-motion 0)
- (setq x (- save-col (current-column)))
- (setq y (term-vertical-motion term-height))
- (cons x y))))
-
-;;; Terminal emulation
-;;; This is the standard process filter for term buffers.
-;;; It emulates (most of the features of) a VT100/ANSI-style terminal.
-
-(defun term-emulate-terminal (proc str)
- (let* ((previous-buffer (current-buffer))
- (i 0) char funny count save-point save-marker old-point temp win
- (selected (selected-window))
- (str-length (length str)))
- (unwind-protect
- (progn
- (set-buffer (process-buffer proc))
-
- (if (marker-buffer term-pending-delete-marker)
- (progn
- ;; Delete text following term-pending-delete-marker.
- (delete-region term-pending-delete-marker (process-mark proc))
- (set-marker term-pending-delete-marker nil)))
-
- (if (eq (window-buffer) (current-buffer))
- (progn
- (setq term-vertical-motion (symbol-function 'vertical-motion))
- (term-check-size proc))
- (setq term-vertical-motion
- (symbol-function 'buffer-vertical-motion)))
-
- (setq save-marker (copy-marker (process-mark proc)))
-
- (if (/= (point) (process-mark proc))
- (progn (setq save-point (point-marker))
- (goto-char (process-mark proc))))
-
- (save-restriction
- ;; If the buffer is in line mode, and there is a partial
- ;; input line, save the line (by narrowing to leave it
- ;; outside the restriction ) until we're done with output.
- (if (and (> (point-max) (process-mark proc))
- (term-in-line-mode))
- (narrow-to-region (point-min) (process-mark proc)))
-
- (if term-log-buffer
- (princ str term-log-buffer))
- (cond ((eq term-terminal-state 4) ;; Have saved pending output.
- (setq str (concat term-terminal-parameter str))
- (setq term-terminal-parameter nil)
- (setq str-length (length str))
- (setq term-terminal-state 0)))
-
- (while (< i str-length)
- (setq char (aref str i))
- (cond ((< term-terminal-state 2)
- ;; Look for prefix of regular chars
- (setq funny
- (string-match "[\r\n\000\007\033\t\b\032\016\017]"
- str i))
- (if (not funny) (setq funny str-length))
- (cond ((> funny i)
- (cond ((eq term-terminal-state 1)
- (term-move-columns 1)
- (setq term-terminal-state 0)))
- (setq count (- funny i))
- (setq temp (- (+ (term-horizontal-column) count)
- term-width))
- (cond ((<= temp 0)) ;; All count chars fit in line.
- ((> count temp) ;; Some chars fit.
- ;; This iteration, handle only what fits.
- (setq count (- count temp))
- (setq funny (+ count i)))
- ((or (not (or term-pager-count
- term-scroll-with-delete))
- (> (term-handle-scroll 1) 0))
- (term-adjust-current-row-cache 1)
- (setq count (min count term-width))
- (setq funny (+ count i))
- (setq term-start-line-column
- term-current-column))
- (t ;; Doing PAGER processing.
- (setq count 0 funny i)
- (setq term-current-column nil)
- (setq term-start-line-column nil)))
- (setq old-point (point))
- ;; In the common case that we're at the end of
- ;; the buffer, we can save a little work.
- (cond ((/= (point) (point-max))
- (if term-insert-mode
- ;; Inserting spaces, then deleting them,
- ;; then inserting the actual text is
- ;; inefficient, but it is simple, and
- ;; the actual overhead is miniscule.
- (term-insert-spaces count))
- (term-move-columns count)
- (delete-region old-point (point)))
- (t (setq term-current-column (+ (term-current-column) count))))
- (insert (substring str i funny))
- (put-text-property old-point (point)
- 'face term-current-face)
- ;; If the last char was written in last column,
- ;; back up one column, but remember we did so.
- ;; Thus we emulate xterm/vt100-style line-wrapping.
- (cond ((eq temp 0)
- (term-move-columns -1)
- (setq term-terminal-state 1)))
- (setq i (1- funny)))
- ((and (setq term-terminal-state 0)
- (eq char ?\^I)) ; TAB
- ;; FIXME: Does not handle line wrap!
- (setq count (term-current-column))
- (setq count (+ count 8 (- (mod count 8))))
- (if (< (move-to-column count nil) count)
- (term-insert-char char 1))
- (setq term-current-column count))
- ((eq char ?\r)
- ;; Optimize CRLF at end of buffer:
- (cond ((and (< (setq temp (1+ i)) str-length)
- (eq (aref str temp) ?\n)
- (= (point) (point-max))
- (not (or term-pager-count
- term-kill-echo-list
- term-scroll-with-delete)))
- (insert ?\n)
- (term-adjust-current-row-cache 1)
- (setq term-start-line-column 0)
- (setq term-current-column 0)
- (setq i temp))
- (t ;; Not followed by LF or can't optimize:
- (term-vertical-motion 0)
- (setq term-current-column term-start-line-column))))
- ((eq char ?\n)
- (if (not (and term-kill-echo-list
- (term-check-kill-echo-list)))
- (term-down 1 t)))
- ((eq char ?\b)
- (term-move-columns -1))
- ((eq char ?\033) ; Escape
- (setq term-terminal-state 2))
- ((eq char 0)) ; NUL: Do nothing
- ((eq char ?\016)) ; Shift Out - ignored
- ((eq char ?\017)) ; Shift In - ignored
- ((eq char ?\^G)
- (beep t)) ; Bell
- ((eq char ?\032)
- (let ((end (string-match "\n" str i)))
- (if end
- (progn (funcall term-command-hook
- (substring str (1+ i) (1- end)))
- (setq i end))
- (setq term-terminal-parameter
- (substring str i))
- (setq term-terminal-state 4)
- (setq i str-length))))
- (t ; insert char FIXME: Should never happen
- (term-move-columns 1)
- (backward-delete-char 1)
- (insert char))))
- ((eq term-terminal-state 2) ; Seen Esc
- (cond ((eq char ?\133) ;; ?\133 = ?[
- (make-local-variable 'term-terminal-parameter)
- (make-local-variable 'term-terminal-previous-parameter)
- (setq term-terminal-parameter 0)
- (setq term-terminal-previous-parameter 0)
- (setq term-terminal-state 3))
- ((eq char ?D) ;; scroll forward
- (term-handle-deferred-scroll)
- (term-down 1 t)
- (setq term-terminal-state 0))
- ((eq char ?M) ;; scroll reversed
- (term-insert-lines 1)
- (setq term-terminal-state 0))
- ((eq char ?7) ;; Save cursor
- (term-handle-deferred-scroll)
- (setq term-saved-cursor
- (cons (term-current-row)
- (term-horizontal-column)))
- (setq term-terminal-state 0))
- ((eq char ?8) ;; Restore cursor
- (if term-saved-cursor
- (term-goto (car term-saved-cursor)
- (cdr term-saved-cursor)))
- (setq term-terminal-state 0))
- ((setq term-terminal-state 0))))
- ((eq term-terminal-state 3) ; Seen Esc [
- (cond ((and (>= char ?0) (<= char ?9))
- (setq term-terminal-parameter
- (+ (* 10 term-terminal-parameter) (- char ?0))))
- ((eq char ?\073 ) ; ?;
- (setq term-terminal-previous-parameter
- term-terminal-parameter)
- (setq term-terminal-parameter 0))
- ((eq char ??)) ; Ignore ?
- (t
- (term-handle-ansi-escape proc char)
- (setq term-terminal-state 0)))))
- (if (term-handling-pager)
- ;; Finish stuff to get ready to handle PAGER.
- (progn
- (if (> (% (current-column) term-width) 0)
- (setq term-terminal-parameter
- (substring str i))
- ;; We're at column 0. Goto end of buffer; to compensate,
- ;; prepend a ?\r for later. This looks more consistent.
- (if (zerop i)
- (setq term-terminal-parameter
- (concat "\r" (substring str i)))
- (setq term-terminal-parameter (substring str (1- i)))
- (aset term-terminal-parameter 0 ?\r))
- (goto-char (point-max)))
- (setq term-terminal-state 4)
- (make-local-variable 'term-pager-old-filter)
- (setq term-pager-old-filter (process-filter proc))
- (set-process-filter proc term-pager-filter)
- (setq i str-length)))
- (setq i (1+ i))))
-
- (if (>= (term-current-row) term-height)
- (term-handle-deferred-scroll))
-
- (set-marker (process-mark proc) (point))
- (if save-point
- (progn (goto-char save-point)
- (set-marker save-point nil)))
-
- ;; Check for a pending filename-and-line number to display.
- ;; We do this before scrolling, because we might create a new window.
- (if (and term-pending-frame
- (eq (window-buffer selected) (current-buffer)))
- (progn (term-display-line (car term-pending-frame)
- (cdr term-pending-frame))
- (setq term-pending-frame nil)
- ;; We have created a new window, so check the window size.
- (term-check-size proc)))
-
- ;; Scroll each window displaying the buffer but (by default)
- ;; only if the point matches the process-mark we started with.
- (setq win selected)
- (while (progn
- (setq win (next-window win nil t))
- (if (eq (window-buffer win) (process-buffer proc))
- (let ((scroll term-scroll-to-bottom-on-output))
- (select-window win)
- (if (or (= (point) save-marker)
- (eq scroll t) (eq scroll 'all)
- ;; Maybe user wants point to jump to the end.
- (and (eq selected win)
- (or (eq scroll 'this) (not save-point)))
- (and (eq scroll 'others)
- (not (eq selected win))))
- (progn
- (goto-char term-home-marker)
- (recenter 0)
- (goto-char (process-mark proc))
- (if (not (pos-visible-in-window-p (point) win))
- (recenter -1))))
- ;; Optionally scroll so that the text
- ;; ends at the bottom of the window.
- (if (and term-scroll-show-maximum-output
- (>= (point) (process-mark proc)))
- (save-excursion
- (goto-char (point-max))
- (recenter -1)))))
- (not (eq win selected))))
-
- (set-marker save-marker nil))
- ;; unwind-protect cleanup-forms follow:
- (set-buffer previous-buffer)
- (select-window selected))))
-
-(defun term-handle-deferred-scroll ()
- (let ((count (- (term-current-row) term-height)))
- (if (>= count 0)
- (save-excursion
- (goto-char term-home-marker)
- (term-vertical-motion (1+ count))
- (set-marker term-home-marker (point))
- (setq term-current-row (1- term-height))))))
-
-;;; Handle a character assuming (eq terminal-state 2) -
-;;; i.e. we have previously seen Escape followed by ?[.
-
-(defun term-handle-ansi-escape (proc char)
- (cond
- ((eq char ?H) ; cursor motion
- (if (<= term-terminal-parameter 0)
- (setq term-terminal-parameter 1))
- (if (<= term-terminal-previous-parameter 0)
- (setq term-terminal-previous-parameter 1))
- (if (> term-terminal-previous-parameter term-height)
- (setq term-terminal-previous-parameter term-height))
- (if (> term-terminal-parameter term-width)
- (setq term-terminal-parameter term-width))
- (term-goto
- (1- term-terminal-previous-parameter)
- (1- term-terminal-parameter)))
- ;; \E[A - cursor up
- ((eq char ?A)
- (term-handle-deferred-scroll)
- (term-down (- (max 1 term-terminal-parameter)) t))
- ;; \E[B - cursor down
- ((eq char ?B)
- (term-down (max 1 term-terminal-parameter) t))
- ;; \E[C - cursor right
- ((eq char ?C)
- (term-move-columns (max 1 term-terminal-parameter)))
- ;; \E[D - cursor left
- ((eq char ?D)
- (term-move-columns (- (max 1 term-terminal-parameter))))
- ;; \E[J - clear to end of screen
- ((eq char ?J)
- (term-erase-in-display term-terminal-parameter))
- ;; \E[K - clear to end of line
- ((eq char ?K)
- (term-erase-in-line term-terminal-parameter))
- ;; \E[L - insert lines
- ((eq char ?L)
- (term-insert-lines (max 1 term-terminal-parameter)))
- ;; \E[M - delete lines
- ((eq char ?M)
- (term-delete-lines (max 1 term-terminal-parameter)))
- ;; \E[P - delete chars
- ((eq char ?P)
- (term-delete-chars (max 1 term-terminal-parameter)))
- ;; \E[@ - insert spaces
- ((eq char ?@)
- (term-insert-spaces (max 1 term-terminal-parameter)))
- ;; \E[?h - DEC Private Mode Set
- ((eq char ?h)
- (cond ((eq term-terminal-parameter 4)
- (setq term-insert-mode t))
- ((eq term-terminal-parameter 47)
- (term-switch-to-alternate-sub-buffer t))))
- ;; \E[?l - DEC Private Mode Reset
- ((eq char ?l)
- (cond ((eq term-terminal-parameter 4)
- (setq term-insert-mode nil))
- ((eq term-terminal-parameter 47)
- (term-switch-to-alternate-sub-buffer nil))))
- ;; \E[m - Set/reset standard mode
- ((eq char ?m)
- (cond ((eq term-terminal-parameter 7)
- (setq term-current-face 'highlight))
- ((eq term-terminal-parameter 4)
- (setq term-current-face 'term-underline-face))
- ((eq term-terminal-parameter 1)
- (setq term-current-face 'bold))
- (t (setq term-current-face 'default))))
- ;; \E[6n - Report cursor position
- ((eq char ?n)
- (term-handle-deferred-scroll)
- (process-send-string proc
- (format "\e[%s;%sR"
- (1+ (term-current-row))
- (1+ (term-horizontal-column)))))
- ;; \E[r - Set scrolling region
- ((eq char ?r)
- (term-scroll-region
- (1- term-terminal-previous-parameter)
- term-terminal-parameter))
- (t)))
-
-(defun term-scroll-region (top bottom)
- "Set scrolling region.
-TOP is the top-most line (inclusive) of the new scrolling region,
-while BOTTOM is the line following the new scrolling region (e.g. exclusive).
-The top-most line is line 0."
- (setq term-scroll-start
- (if (or (< top 0) (>= top term-height))
- 0
- top))
- (setq term-scroll-end
- (if (or (<= bottom term-scroll-start) (> bottom term-height))
- term-height
- bottom))
- (setq term-scroll-with-delete
- (or (term-using-alternate-sub-buffer)
- (not (and (= term-scroll-start 0)
- (= term-scroll-end term-height))))))
-
-(defun term-switch-to-alternate-sub-buffer (set)
- ;; If asked to switch to (from) the alternate sub-buffer, and already (not)
- ;; using it, do nothing. This test is needed for some programs (including
- ;; emacs) that emit the ti termcap string twice, for unknown reason.
- (term-handle-deferred-scroll)
- (if (eq set (not (term-using-alternate-sub-buffer)))
- (let ((row (term-current-row))
- (col (term-horizontal-column)))
- (cond (set
- (goto-char (point-max))
- (if (not (eq (preceding-char) ?\n))
- (term-insert-char ?\n 1))
- (setq term-scroll-with-delete t)
- (setq term-saved-home-marker (copy-marker term-home-marker))
- (set-marker term-home-marker (point)))
- (t
- (setq term-scroll-with-delete
- (not (and (= term-scroll-start 0)
- (= term-scroll-end term-height))))
- (set-marker term-home-marker term-saved-home-marker)
- (set-marker term-saved-home-marker nil)
- (setq term-saved-home-marker nil)
- (goto-char term-home-marker)))
- (setq term-current-column nil)
- (setq term-current-row 0)
- (term-goto row col))))
-
-;; Default value for the symbol term-command-hook.
-
-(defun term-command-hook (string)
- (cond ((= (aref string 0) ?\032)
- ;; gdb (when invoked with -fullname) prints:
- ;; \032\032FULLFILENAME:LINENUMBER:CHARPOS:BEG_OR_MIDDLE:PC\n
- (let* ((first-colon (string-match ":" string 1))
- (second-colon
- (string-match ":" string (1+ first-colon)))
- (filename (substring string 1 first-colon))
- (fileline (string-to-int
- (substring string (1+ first-colon) second-colon))))
- (setq term-pending-frame (cons filename fileline))))
- ((= (aref string 0) ?/)
- (cd (substring string 1)))
- ;; Allowing the inferior to call functions in emacs is
- ;; probably too big a security hole.
- ;; ((= (aref string 0) ?!)
- ;; (eval (car (read-from-string string 1))))
- (t)));; Otherwise ignore it
-
-;; 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.
-;; This is mainly used by gdb.
-
-(defun term-display-line (true-file line)
- (term-display-buffer-line (find-file-noselect true-file) line))
-
-(defun term-display-buffer-line (buffer line)
- (let* ((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)))
-
-;;; The buffer-local marker term-home-marker defines the "home position"
-;;; (in terms of cursor motion). However, we move the term-home-marker
-;;; "down" as needed so that is no more that a window-full above (point-max).
-
-(defun term-goto-home ()
- (term-handle-deferred-scroll)
- (goto-char term-home-marker)
- (setq term-current-row 0)
- (setq term-current-column (current-column))
- (setq term-start-line-column term-current-column))
-
-(defun term-goto (row col)
- (term-handle-deferred-scroll)
- (cond ((and term-current-row (>= row term-current-row))
- ;; I assume this is a worthwhile optimization.
- (term-vertical-motion 0)
- (setq term-current-column term-start-line-column)
- (setq row (- row term-current-row)))
- (t
- (term-goto-home)))
- (term-down row)
- (term-move-columns col))
-
-; The page is full, so enter "pager" mode, and wait for input.
-
-(defun term-process-pager ()
- (if (not term-pager-break-map)
- (let* ((map (make-keymap))
- (i 0) tmp)
-; (while (< i 128)
-; (define-key map (make-string 1 i) 'term-send-raw)
-; (setq i (1+ i)))
- (define-key map "\e"
- (lookup-key (current-global-map) "\e"))
- (define-key map "\C-x"
- (lookup-key (current-global-map) "\C-x"))
- (define-key map "\C-u"
- (lookup-key (current-global-map) "\C-u"))
- (define-key map " " 'term-pager-page)
- (define-key map "\r" 'term-pager-line)
- (define-key map "?" 'term-pager-help)
- (define-key map "h" 'term-pager-help)
- (define-key map "b" 'term-pager-back-page)
- (define-key map "\177" 'term-pager-back-line)
- (define-key map "q" 'term-pager-discard)
- (define-key map "D" 'term-pager-disable)
- (define-key map "<" 'term-pager-bob)
- (define-key map ">" 'term-pager-eob)
-
- ;; Add menu bar.
- (term-if-emacs19
- (term-ifnot-xemacs
- (define-key map [menu-bar terminal] term-terminal-menu)
- (define-key map [menu-bar signals] term-signals-menu)
- (setq tmp (make-sparse-keymap "More pages?"))
- (define-key tmp [help] '("Help" . term-pager-help))
- (define-key tmp [disable]
- '("Disable paging" . term-fake-pager-disable))
- (define-key tmp [discard]
- '("Discard remaining output" . term-pager-discard))
- (define-key tmp [eob] '("Goto to end" . term-pager-eob))
- (define-key tmp [bob] '("Goto to beginning" . term-pager-bob))
- (define-key tmp [line] '("1 line forwards" . term-pager-line))
- (define-key tmp [bline] '("1 line backwards" . term-pager-back-line))
- (define-key tmp [back] '("1 page backwards" . term-pager-back-page))
- (define-key tmp [page] '("1 page forwards" . term-pager-page))
- (define-key map [menu-bar page] (cons "More pages?" tmp))
- ))
-
- (setq term-pager-break-map map)))
-; (let ((process (get-buffer-process (current-buffer))))
-; (stop-process process))
- (setq term-pager-old-local-map (current-local-map))
- (use-local-map term-pager-break-map)
- (make-local-variable 'term-old-mode-line-format)
- (setq term-old-mode-line-format mode-line-format)
- (setq mode-line-format
- (list "-- **MORE** "
- mode-line-buffer-identification
- " [Type ? for help] "
- "%-"))
- (force-mode-line-update))
-
-(defun term-pager-line (lines)
- (interactive "p")
- (let* ((moved (vertical-motion (1+ lines)))
- (deficit (- lines moved)))
- (if (> moved lines)
- (backward-char))
- (cond ((<= deficit 0) ;; OK, had enough in the buffer for request.
- (recenter (1- term-height)))
- ((term-pager-continue deficit)))))
-
-(defun term-pager-page (arg)
- "Proceed past the **MORE** break, allowing the next page of output to appear"
- (interactive "p")
- (term-pager-line (* arg term-height)))
-
-; Pager mode command to go to beginning of buffer
-(defun term-pager-bob ()
- (interactive)
- (goto-char (point-min))
- (if (= (vertical-motion term-height) term-height)
- (backward-char))
- (recenter (1- term-height)))
-
-; pager mode command to go to end of buffer
-(defun term-pager-eob ()
- (interactive)
- (goto-char term-home-marker)
- (recenter 0)
- (goto-char (process-mark (get-buffer-process (current-buffer)))))
-
-(defun term-pager-back-line (lines)
- (interactive "p")
- (vertical-motion (- 1 lines))
- (if (not (bobp))
- (backward-char)
- (beep)
- ;; Move cursor to end of window.
- (vertical-motion term-height)
- (backward-char))
- (recenter (1- term-height)))
-
-(defun term-pager-back-page (arg)
- (interactive "p")
- (term-pager-back-line (* arg term-height)))
-
-(defun term-pager-discard ()
- (interactive)
- (setq term-terminal-parameter "")
- (interrupt-process nil t)
- (term-pager-continue term-height))
-
-; Disable pager processing.
-; Only callable while in pager mode. (Contrast term-disable-pager.)
-(defun term-pager-disable ()
- (interactive)
- (if (term-handling-pager)
- (term-pager-continue nil)
- (setq term-pager-count nil))
- (term-update-mode-line))
-
-; Enable pager processing.
-(defun term-pager-enable ()
- (interactive)
- (or (term-pager-enabled)
- (setq term-pager-count 0)) ;; Or maybe set to (term-current-row) ??
- (term-update-mode-line))
-
-(defun term-pager-toggle ()
- (interactive)
- (if (term-pager-enabled) (term-pager-disable) (term-pager-enable)))
-
-(term-ifnot-xemacs
- (defalias 'term-fake-pager-enable 'term-pager-toggle)
- (defalias 'term-fake-pager-disable 'term-pager-toggle)
- (put 'term-char-mode 'menu-enable '(term-in-line-mode))
- (put 'term-line-mode 'menu-enable '(term-in-char-mode))
- (put 'term-fake-pager-enable 'menu-enable '(not term-pager-count))
- (put 'term-fake-pager-disable 'menu-enable 'term-pager-count))
-
-(defun term-pager-help ()
- "Provide help on commands available in a terminal-emulator **MORE** break"
- (interactive)
- (message "Terminal-emulator pager break help...")
- (sit-for 0)
- (with-electric-help
- (function (lambda ()
- (princ (substitute-command-keys
-"\\<term-pager-break-map>\
-Terminal-emulator MORE break.\n\
-Type one of the following keys:\n\n\
-\\[term-pager-page]\t\tMove forward one page.\n\
-\\[term-pager-line]\t\tMove forward one line.\n\
-\\[universal-argument] N \\[term-pager-page]\tMove N pages forward.\n\
-\\[universal-argument] N \\[term-pager-line]\tMove N lines forward.\n\
-\\[universal-argument] N \\[term-pager-back-line]\tMove N lines back.\n\
-\\[universal-argument] N \\[term-pager-back-page]\t\tMove N pages back.\n\
-\\[term-pager-bob]\t\tMove to the beginning of the buffer.\n\
-\\[term-pager-eob]\t\tMove to the end of the buffer.\n\
-\\[term-pager-discard]\t\tKill pending output and kill process.\n\
-\\[term-pager-disable]\t\tDisable PAGER handling.\n\n\
-\\{term-pager-break-map}\n\
-Any other key is passed through to the program
-running under the terminal emulator and disables pager processing until
-all pending output has been dealt with."))
- nil))))
-
-(defun term-pager-continue (new-count)
- (let ((process (get-buffer-process (current-buffer))))
- (use-local-map term-pager-old-local-map)
- (setq term-pager-old-local-map nil)
- (setq mode-line-format term-old-mode-line-format)
- (force-mode-line-update)
- (setq term-pager-count new-count)
- (set-process-filter process term-pager-old-filter)
- (funcall term-pager-old-filter process "")
- (continue-process process)))
-
-;; Make sure there are DOWN blank lines below the current one.
-;; Return 0 if we're unable (because of PAGER handling), else return DOWN.
-
-(defun term-handle-scroll (down)
- (let ((scroll-needed
- (- (+ (term-current-row) down 1) term-scroll-end)))
- (if (> scroll-needed 0)
- (let ((save-point (copy-marker (point))) (save-top))
- (goto-char term-home-marker)
- (cond (term-scroll-with-delete
- ;; delete scroll-needed lines at term-scroll-start
- (term-vertical-motion term-scroll-start)
- (setq save-top (point))
- (term-vertical-motion scroll-needed)
- (delete-region save-top (point))
- (goto-char save-point)
- (term-vertical-motion down)
- (term-adjust-current-row-cache (- scroll-needed))
- (setq term-current-column nil)
- (term-insert-char ?\n scroll-needed))
- ((and (numberp term-pager-count)
- (< (setq term-pager-count (- term-pager-count down))
- 0))
- (setq down 0)
- (term-process-pager))
- (t
- (term-adjust-current-row-cache (- scroll-needed))
- (term-vertical-motion scroll-needed)
- (set-marker term-home-marker (point))))
- (goto-char save-point)
- (set-marker save-point nil))))
- down)
-
-(defun term-down (down &optional check-for-scroll)
- "Move down DOWN screen lines vertically."
- (let ((start-column (term-horizontal-column)))
- (if (and check-for-scroll (or term-scroll-with-delete term-pager-count))
- (setq down (term-handle-scroll down)))
- (term-adjust-current-row-cache down)
- (if (/= (point) (point-max))
- (setq down (- down (term-vertical-motion down))))
- ;; Extend buffer with extra blank lines if needed.
- (cond ((> down 0)
- (term-insert-char ?\n down)
- (setq term-current-column 0)
- (setq term-start-line-column 0))
- (t
- (setq term-current-column nil)
- (setq term-start-line-column (current-column))))
- (if start-column
- (term-move-columns start-column))))
-
-;; Assuming point is at the beginning of a screen line,
-;; if the line above point wraps around, add a ?\n to undo the wrapping.
-;; FIXME: Probably should be called more than it is.
-(defun term-unwrap-line ()
- (if (not (bolp)) (insert-before-markers ?\n)))
-
-(defun term-erase-in-line (kind)
- (if (> kind 1) ;; erase left of point
- (let ((cols (term-horizontal-column)) (saved-point (point)))
- (term-vertical-motion 0)
- (delete-region (point) saved-point)
- (term-insert-char ?\n cols)))
- (if (not (eq kind 1)) ;; erase right of point
- (let ((saved-point (point))
- (wrapped (and (zerop (term-horizontal-column))
- (not (zerop (term-current-column))))))
- (term-vertical-motion 1)
- (delete-region saved-point (point))
- ;; wrapped is true if we're at the beginning of screen line,
- ;; but not a buffer line. If we delete the current screen line
- ;; that will make the previous line no longer wrap, and (because
- ;; of the way emacs display works) point will be at the end of
- ;; the previous screen line rather then the beginning of the
- ;; current one. To avoid that, we make sure that current line
- ;; contain a space, to force the previous line to continue to wrap.
- ;; We could do this always, but it seems preferable to not add the
- ;; extra space when wrapped is false.
- (if wrapped
- (insert ? ))
- (insert ?\n)
- (put-text-property saved-point (point) 'face 'default)
- (goto-char saved-point))))
-
-(defun term-erase-in-display (kind)
- "Erases (that is blanks out) part of the window.
-If KIND is 0, erase from (point) to (point-max);
-if KIND is 1, erase from home to point; else erase from home to point-max.
-Should only be called when point is at the start of a screen line."
- (term-handle-deferred-scroll)
- (cond ((eq term-terminal-parameter 0)
- (delete-region (point) (point-max))
- (term-unwrap-line))
- ((let ((row (term-current-row))
- (col (term-horizontal-column))
- (start-region term-home-marker)
- (end-region (if (eq kind 1) (point) (point-max))))
- (delete-region start-region end-region)
- (term-unwrap-line)
- (if (eq kind 1)
- (term-insert-char ?\n row))
- (setq term-current-column nil)
- (setq term-current-row nil)
- (term-goto row col)))))
-
-(defun term-delete-chars (count)
- (let ((save-point (point)))
- (term-vertical-motion 1)
- (term-unwrap-line)
- (goto-char save-point)
- (move-to-column (+ (term-current-column) count) t)
- (delete-region save-point (point))))
-
-;;; Insert COUNT spaces after point, but do not change any of
-;;; following screen lines. Hence we may have to delete characters
-;;; at teh end of this screen line to make room.
-
-(defun term-insert-spaces (count)
- (let ((save-point (point)) (save-eol))
- (term-vertical-motion 1)
- (if (bolp)
- (backward-char))
- (setq save-eol (point))
- (move-to-column (+ (term-start-line-column) (- term-width count)) t)
- (if (> save-eol (point))
- (delete-region (point) save-eol))
- (goto-char save-point)
- (term-insert-char ? count)
- (goto-char save-point)))
-
-(defun term-delete-lines (lines)
- (let ((start (point))
- (save-current-column term-current-column)
- (save-start-line-column term-start-line-column)
- (save-current-row (term-current-row)))
- (term-down lines)
- (delete-region start (point))
- (term-down (- term-scroll-end save-current-row lines))
- (term-insert-char ?\n lines)
- (setq term-current-column save-current-column)
- (setq term-start-line-column save-start-line-column)
- (setq term-current-row save-current-row)
- (goto-char start)))
-
-(defun term-insert-lines (lines)
- (let ((start (point))
- (start-deleted)
- (save-current-column term-current-column)
- (save-start-line-column term-start-line-column)
- (save-current-row (term-current-row)))
- (term-down (- term-scroll-end save-current-row lines))
- (setq start-deleted (point))
- (term-down lines)
- (delete-region start-deleted (point))
- (goto-char start)
- (setq term-current-column save-current-column)
- (setq term-start-line-column save-start-line-column)
- (setq term-current-row save-current-row)
- (term-insert-char ?\n lines)
- (goto-char start)))
-
-(defun term-set-output-log (name)
- "Record raw inferior process output in a buffer."
- (interactive (list (if term-log-buffer
- nil
- (read-buffer "Record output in buffer: "
- (format "%s output-log"
- (buffer-name (current-buffer)))
- nil))))
- (if (or (null name) (equal name ""))
- (progn (setq term-log-buffer nil)
- (message "Output logging off."))
- (if (get-buffer name)
- nil
- (save-excursion
- (set-buffer (get-buffer-create name))
- (fundamental-mode)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)))
- (setq term-log-buffer (get-buffer name))
- (message "Recording terminal emulator output into buffer \"%s\""
- (buffer-name term-log-buffer))))
-
-(defun term-stop-photo ()
- "Discontinue raw inferior process logging."
- (interactive)
- (term-set-output-log nil))
-
-(defun term-show-maximum-output ()
- "Put the end of the buffer at the bottom of the window."
- (interactive)
- (goto-char (point-max))
- (recenter -1))
-
-;;; Do the user's customisation...
-
-(defvar term-load-hook nil
- "This hook is run when term is loaded in.
-This is a good place to put keybindings.")
-
-(run-hooks 'term-load-hook)
-
-
-;;; Filename/command/history completion in a buffer
-;;; ===========================================================================
-;;; Useful completion functions, courtesy of the Ergo group.
-
-;;; Six commands:
-;;; term-dynamic-complete Complete or expand command, filename,
-;;; history at point.
-;;; term-dynamic-complete-filename Complete filename at point.
-;;; term-dynamic-list-filename-completions List completions in help buffer.
-;;; term-replace-by-expanded-filename Expand and complete filename at point;
-;;; replace with expanded/completed name.
-;;; term-dynamic-simple-complete Complete stub given candidates.
-
-;;; These are not installed in the term-mode keymap. But they are
-;;; available for people who want them. Shell-mode installs them:
-;;; (define-key shell-mode-map "\t" 'term-dynamic-complete)
-;;; (define-key shell-mode-map "\M-?"
-;;; 'term-dynamic-list-filename-completions)))
-;;;
-;;; Commands like this are fine things to put in load hooks if you
-;;; want them present in specific modes.
-
-(defvar term-completion-autolist nil
- "*If non-nil, automatically list possibilities on partial completion.
-This mirrors the optional behavior of tcsh.")
-
-(defvar term-completion-addsuffix t
- "*If non-nil, add a `/' to completed directories, ` ' to file names.
-This mirrors the optional behavior of tcsh.")
-
-(defvar term-completion-recexact nil
- "*If non-nil, use shortest completion if characters cannot be added.
-This mirrors the optional behavior of tcsh.
-
-A non-nil value is useful if `term-completion-autolist' is non-nil too.")
-
-(defvar term-completion-fignore nil
- "*List of suffixes to be disregarded during file completion.
-This mirrors the optional behavior of bash and tcsh.
-
-Note that this applies to `term-dynamic-complete-filename' only.")
-
-(defvar term-file-name-prefix ""
- "Prefix prepended to absolute file names taken from process input.
-This is used by term's and shell's completion functions, and by shell's
-directory tracking functions.")
-
-
-(defun term-directory (directory)
- ;; Return expanded DIRECTORY, with `term-file-name-prefix' if absolute.
- (expand-file-name (if (file-name-absolute-p directory)
- (concat term-file-name-prefix directory)
- directory)))
-
-
-(defun term-word (word-chars)
- "Return the word of WORD-CHARS at point, or nil if non is found.
-Word constituents are considered to be those in WORD-CHARS, which is like the
-inside of a \"[...]\" (see `skip-chars-forward')."
- (save-excursion
- (let ((limit (point))
- (word (concat "[" word-chars "]"))
- (non-word (concat "[^" word-chars "]")))
- (if (re-search-backward non-word nil 'move)
- (forward-char 1))
- ;; Anchor the search forwards.
- (if (or (eolp) (looking-at non-word))
- nil
- (re-search-forward (concat word "+") limit)
- (buffer-substring (match-beginning 0) (match-end 0))))))
-
-
-(defun term-match-partial-filename ()
- "Return the filename at point, or nil if non is found.
-Environment variables are substituted. See `term-word'."
- (let ((filename (term-word "~/A-Za-z0-9+@:_.$#,={}-")))
- (and filename (substitute-in-file-name filename))))
-
-
-(defun term-dynamic-complete ()
- "Dynamically perform completion at point.
-Calls the functions in `term-dynamic-complete-functions' to perform
-completion until a function returns non-nil, at which point completion is
-assumed to have occurred."
- (interactive)
- (let ((functions term-dynamic-complete-functions))
- (while (and functions (null (funcall (car functions))))
- (setq functions (cdr functions)))))
-
-
-(defun term-dynamic-complete-filename ()
- "Dynamically complete the filename at point.
-Completes if after a filename. See `term-match-partial-filename' and
-`term-dynamic-complete-as-filename'.
-This function is similar to `term-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. A completions listing
-may be shown in a help buffer if completion is ambiguous.
-
-Completion is dependent on the value of `term-completion-addsuffix',
-`term-completion-recexact' and `term-completion-fignore', and the timing of
-completions listing is dependent on the value of `term-completion-autolist'.
-
-Returns t if successful."
- (interactive)
- (if (term-match-partial-filename)
- (prog2 (or (eq (selected-window) (minibuffer-window))
- (message "Completing file name..."))
- (term-dynamic-complete-as-filename))))
-
-(defun term-dynamic-complete-as-filename ()
- "Dynamically complete at point as a filename.
-See `term-dynamic-complete-filename'. Returns t if successful."
- (let* ((completion-ignore-case nil)
- (completion-ignored-extensions term-completion-fignore)
- (success t)
- (filename (or (term-match-partial-filename) ""))
- (pathdir (file-name-directory filename))
- (pathnondir (file-name-nondirectory filename))
- (directory (if pathdir (term-directory pathdir) default-directory))
- (completion (file-name-completion pathnondir directory))
- (mini-flag (eq (selected-window) (minibuffer-window))))
- (cond ((null completion)
- (message "No completions of %s" filename)
- (setq success nil))
- ((eq completion t) ; Means already completed "file".
- (if term-completion-addsuffix (insert " "))
- (or mini-flag (message "Sole completion")))
- ((string-equal completion "") ; Means completion on "directory/".
- (term-dynamic-list-filename-completions))
- (t ; Completion string returned.
- (let ((file (concat (file-name-as-directory directory) completion)))
- (insert (substring (directory-file-name completion)
- (length pathnondir)))
- (cond ((symbolp (file-name-completion completion directory))
- ;; We inserted a unique completion.
- (if term-completion-addsuffix
- (insert (if (file-directory-p file) "/" " ")))
- (or mini-flag (message "Completed")))
- ((and term-completion-recexact term-completion-addsuffix
- (string-equal pathnondir completion)
- (file-exists-p file))
- ;; It's not unique, but user wants shortest match.
- (insert (if (file-directory-p file) "/" " "))
- (or mini-flag (message "Completed shortest")))
- ((or term-completion-autolist
- (string-equal pathnondir completion))
- ;; It's not unique, list possible completions.
- (term-dynamic-list-filename-completions))
- (t
- (or mini-flag (message "Partially completed")))))))
- success))
-
-
-(defun term-replace-by-expanded-filename ()
- "Dynamically expand and complete the filename at point.
-Replace the filename with an expanded, canonicalised and completed replacement.
-\"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. For expansion
-see `expand-file-name' and `substitute-in-file-name'. For completion see
-`term-dynamic-complete-filename'."
- (interactive)
- (replace-match (expand-file-name (term-match-partial-filename)) t t)
- (term-dynamic-complete-filename))
-
-
-(defun term-dynamic-simple-complete (stub candidates)
- "Dynamically complete STUB from CANDIDATES list.
-This function inserts completion characters at point by completing STUB from
-the strings in CANDIDATES. A completions listing may be shown in a help buffer
-if completion is ambiguous.
-
-Returns nil if no completion was inserted.
-Returns `sole' if completed with the only completion match.
-Returns `shortest' if completed with the shortest of the completion matches.
-Returns `partial' if completed as far as possible with the completion matches.
-Returns `listed' if a completion listing was shown.
-
-See also `term-dynamic-complete-filename'."
- (let* ((completion-ignore-case nil)
- (candidates (mapcar (function (lambda (x) (list x))) candidates))
- (completions (all-completions stub candidates)))
- (cond ((null completions)
- (message "No completions of %s" stub)
- nil)
- ((= 1 (length completions)) ; Gotcha!
- (let ((completion (car completions)))
- (if (string-equal completion stub)
- (message "Sole completion")
- (insert (substring completion (length stub)))
- (message "Completed"))
- (if term-completion-addsuffix (insert " "))
- 'sole))
- (t ; There's no unique completion.
- (let ((completion (try-completion stub candidates)))
- ;; Insert the longest substring.
- (insert (substring completion (length stub)))
- (cond ((and term-completion-recexact term-completion-addsuffix
- (string-equal stub completion)
- (member completion completions))
- ;; It's not unique, but user wants shortest match.
- (insert " ")
- (message "Completed shortest")
- 'shortest)
- ((or term-completion-autolist
- (string-equal stub completion))
- ;; It's not unique, list possible completions.
- (term-dynamic-list-completions completions)
- 'listed)
- (t
- (message "Partially completed")
- 'partial)))))))
-
-
-(defun term-dynamic-list-filename-completions ()
- "List in help buffer possible completions of the filename at point."
- (interactive)
- (let* ((completion-ignore-case nil)
- (filename (or (term-match-partial-filename) ""))
- (pathdir (file-name-directory filename))
- (pathnondir (file-name-nondirectory filename))
- (directory (if pathdir (term-directory pathdir) default-directory))
- (completions (file-name-all-completions pathnondir directory)))
- (if completions
- (term-dynamic-list-completions completions)
- (message "No completions of %s" filename))))
-
-
-(defun term-dynamic-list-completions (completions)
- "List in help buffer sorted COMPLETIONS.
-Typing SPC flushes the help buffer."
- (let ((conf (current-window-configuration)))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list (sort completions 'string-lessp)))
- (message "Hit space to flush")
- (let (key first)
- (if (save-excursion
- (set-buffer (get-buffer "*Completions*"))
- (setq key (read-key-sequence nil)
- first (aref key 0))
- (and (consp first)
- (eq (window-buffer (posn-window (event-start first)))
- (get-buffer "*Completions*"))
- (eq (key-binding key) 'mouse-choose-completion)))
- ;; If the user does mouse-choose-completion with the mouse,
- ;; execute the command, then delete the completion window.
- (progn
- (mouse-choose-completion first)
- (set-window-configuration conf))
- (if (eq first ?\ )
- (set-window-configuration conf)
- (setq unread-command-events (listify-key-sequence key)))))))
-
-;;; Converting process modes to use term mode
-;;; ===========================================================================
-;;; Renaming variables
-;;; Most of the work is renaming variables and functions. These are the common
-;;; ones:
-;;; Local variables:
-;;; last-input-start term-last-input-start
-;;; last-input-end term-last-input-end
-;;; shell-prompt-pattern term-prompt-regexp
-;;; shell-set-directory-error-hook <no equivalent>
-;;; Miscellaneous:
-;;; shell-set-directory <unnecessary>
-;;; shell-mode-map term-mode-map
-;;; Commands:
-;;; shell-send-input term-send-input
-;;; shell-send-eof term-delchar-or-maybe-eof
-;;; kill-shell-input term-kill-input
-;;; interrupt-shell-subjob term-interrupt-subjob
-;;; stop-shell-subjob term-stop-subjob
-;;; quit-shell-subjob term-quit-subjob
-;;; kill-shell-subjob term-kill-subjob
-;;; kill-output-from-shell term-kill-output
-;;; show-output-from-shell term-show-output
-;;; copy-last-shell-input Use term-previous-input/term-next-input
-;;;
-;;; SHELL-SET-DIRECTORY is gone, its functionality taken over by
-;;; SHELL-DIRECTORY-TRACKER, the shell mode's term-input-filter-functions.
-;;; Term mode does not provide functionality equivalent to
-;;; shell-set-directory-error-hook; it is gone.
-;;;
-;;; term-last-input-start is provided for modes which want to munge
-;;; the buffer after input is sent, perhaps because the inferior
-;;; insists on echoing the input. The LAST-INPUT-START variable in
-;;; the old shell package was used to implement a history mechanism,
-;;; but you should think twice before using term-last-input-start
-;;; for this; the input history ring often does the job better.
-;;;
-;;; If you are implementing some process-in-a-buffer mode, called foo-mode, do
-;;; *not* create the term-mode local variables in your foo-mode function.
-;;; This is not modular. Instead, call term-mode, and let *it* create the
-;;; necessary term-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 term-mode hooks
-;;; (term-{prompt-regexp, input-filter, input-filter-functions,
-;;; get-old-input) that need to be different from the defaults. Call
-;;; foo-mode-hook, and you're done. Don't run the term-mode hook yourself;
-;;; term-mode will take care of it. The following example, from shell.el,
-;;; is typical:
-;;;
-;;; (defvar shell-mode-map '())
-;;; (cond ((not shell-mode-map)
-;;; (setq shell-mode-map (copy-keymap term-mode-map))
-;;; (define-key shell-mode-map "\C-c\C-f" 'shell-forward-command)
-;;; (define-key shell-mode-map "\C-c\C-b" 'shell-backward-command)
-;;; (define-key shell-mode-map "\t" 'term-dynamic-complete)
-;;; (define-key shell-mode-map "\M-?"
-;;; 'term-dynamic-list-filename-completions)))
-;;;
-;;; (defun shell-mode ()
-;;; (interactive)
-;;; (term-mode)
-;;; (setq term-prompt-regexp shell-prompt-pattern)
-;;; (setq major-mode 'shell-mode)
-;;; (setq mode-name "Shell")
-;;; (use-local-map shell-mode-map)
-;;; (make-local-variable 'shell-directory-stack)
-;;; (setq shell-directory-stack nil)
-;;; (add-hook 'term-input-filter-functions 'shell-directory-tracker)
-;;; (run-hooks 'shell-mode-hook))
-;;;
-;;;
-;;; Note that make-term 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-term a program argument
-;;; of NIL, it barfs. Adjust your code accordingly...
-;;;
-;;; Completion for term-mode users
-;;;
-;;; For modes that use term-mode, term-dynamic-complete-functions is the
-;;; hook to add completion functions to. Functions on this list should return
-;;; non-nil if completion occurs (i.e., further completion should not occur).
-;;; You could use term-dynamic-simple-complete to do the bulk of the
-;;; completion job.
-
-(provide 'term)
-
-;;; term.el ends here
diff --git a/lisp/term/README b/lisp/term/README
deleted file mode 100644
index e672b15dcf7..00000000000
--- a/lisp/term/README
+++ /dev/null
@@ -1,214 +0,0 @@
- This directory contains files of elisp that customize Emacs for certain
-terminal types.
-
- When Emacs starts, it checks the TERM environment variable to see what type
-of terminal the user is running on, checks for an elisp file named
-"term/${TERM}.el", and if one exists, loads it. 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'.
-
- When writing terminal packages, there are some things it is good to keep in
-mind.
-
- First, about keycap names. Your terminal package can create any keycap
-cookies it likes, but there are good reasons to stick to the set recognized by
-the X-windows code whenever possible. The key symbols recognized by Emacs
-are listed in src/term.c; look for the string `keys' in that file.
-
- For one thing, it means that you'll have the same Emacs key bindings on in
-terminal mode as on an X console. If there are differences, you can bet
-they'll frustrate you after you've forgotten about them.
-
- For another, the X keysms provide a standard set of names that Emacs knows
-about. It tries to bind many of them to useful things at startup, before your
-.emacs is read (so you can override them). In some ways, the X keysym standard
-is a admittedly poor one; it's incomplete, and not well matched to the set of
-`virtual keys' that UNIX terminfo(3) provides. But, trust us, the alternatives
-were worse.
-
- This doesn't mean that if your terminal has a "Cokebottle" key you shouldn't
-define a [cokebottle] keycap. But if you must define cookies that aren't in
-that set, try to pattern them on the standard terminfo variable names for
-clarity; also, for a fighting chance that your binding may be useful to someone
-else someday.
-
- For example, if your terminal has a `find' key, observe that terminfo
-supports a key_find capability and call your cookie [key-find].
-
-Here is a complete list, with corresponding X keysyms.
-
------------------------------------------------------------------------------
-Variable name cap X Keysym Description
--------------- --- ------------ -------------------------------------
-key_down kd down Sent by terminal down arrow key
-key_up ku up Sent by terminal up arrow key
-key_left kl left Sent by terminal left arrow key
-key_right kr right Sent by terminal right arrow key
-key_home kh home Sent by home key.
-key_backspace kb Sent by backspace key
-key_dl kd deleteline Sent by delete line key.
-key_il kA insertline Sent by insert line.
-key_dc kD Sent by delete character key.
-key_ic kI insertchar (1) Sent by ins char/enter ins mode key.
-key_eic KM Sent by rmir or smir in insert mode.
-key_clear kC Sent by clear screen or erase key.
-key_eos kS Sent by clear-to-end-of-screen key.
-key_eol kE Sent by clear-to-end-of-line key.
-key_sf kF Sent by scroll-forward/down key
-key_sr kR Sent by scroll-backward/up key
-key_npage kN next (2) Sent by next-page key
-key_ppage kP prior (2) Sent by previous-page key
-key_stab kT Sent by set-tab key
-key_ctab kt Sent by clear-tab key
-key_catab ka Sent by clear-all-tabs key.
-key_enter @8 kp-enter Enter/send (unreliable)
-key_print %9 print print or copy
-key_ll kH Sent by home-down key
-key_a1 K1 kp-1 Upper left of keypad
-key_a3 K3 kp-3 Upper right of keypad
-key_b2 K2 kp-5 Center of keypad
-key_c1 K4 kp-7 Lower left of keypad
-key_c3 K5 kp-9 Lower right of keypad
-key_btab kB backtab Back tab key
-key_beg @1 begin beg(inning) key
-key_cancel @2 cancel cancel key
-key_close @3 close key
-key_command @4 execute (3) cmd (command) key
-key_copy @5 copy key
-key_create @6 create key
-key_end @7 end end key
-key_exit @9 exit key
-key_find @0 find key
-key_help %1 help key
-key_mark %2 mark key
-key_message %3 message key
-key_move %4 move key
-key_next %5 next (2) next object key
-key_open %6 open key
-key_options %7 menu (3) options key
-key_previous %8 previous (2) previous object key
-key_redo %0 redo redo key
-key_reference &1 ref(erence) key
-key_refresh &2 refresh key
-key_replace &3 replace key
-key_restart &4 reset (3) restart key
-key_resume &5 resume key
-key_save &6 save key
-key_sbeg &9 shifted beginning key
-key_select *6 select select key
-key_suspend &7 suspend key
-key_undo &8 undo undo key
-
-key_scancel &0 shifted cancel key
-key_scommand *1 shifted command key
-key_scopy *2 shifted copy key
-key_screate *3 shifted create key
-key_sdc *4 shifted delete char key
-key_sdl *5 shifted delete line key
-key_send *7 shifted end key
-key_seol *8 shifted clear line key
-key_sexit *9 shifted exit key
-key_sf kF shifted find key
-key_shelp #1 shifted help key
-key_shome #2 shifted home key
-key_sic #3 shifted input key
-key_sleft #4 shifted left arrow key
-key_smessage %a shifted message key
-key_smove %b shifted move key
-key_snext %c shifted next key
-key_soptions %d shifted options key
-key_sprevious %e shifted prev key
-key_sprint %f shifted print key
-key_sredo %g shifted redo key
-key_sreplace %h shifted replace key
-key_sright %i shifted right arrow
-key_sresume %j shifted resume key
-key_ssave !1 shifted save key
-key_suspend !2 shifted suspend key
-key_sundo !3 shifted undo key
-
-key_f0 k0 f0 (4) function key 0
-key_f1 k1 f1 function key 1
-key_f2 k2 f2 function key 2
-key_f3 k3 f3 function key 3
-key_f4 k4 f4 function key 4
-key_f5 k5 f5 function key 5
-key_f6 k6 f6 function key 6
-key_f7 k7 f7 function key 7
-key_f8 k8 f8 function key 8
-key_f9 k9 f9 function key 9
-key_f10 k; f10 (4) function key 10
-key_f11 F1 f11 function key 11
- : : : :
-key_f35 FP f35 function key 35
-key_f36 FQ function key 36
- : : : :
-key_f64 k1 function key 64
-
-(1) The terminfo documentation says this may be the 'insert character' or
- `enter insert mode' key. Accordingly, key_ic is mapped to the `insertchar'
- keysym if there is also a key_dc key; otherwise it's mapped to `insert'.
- The presumption is that keyboards with `insert character' keys usually
- have `delete character' keys paired with them.
-
-(2) If there is no key_next key but there is a key_npage key, key_npage
- will be bound to the `next' keysym. If there is no key_previous key but
- there is a key_ppage key, key_ppage will be bound to the `previous' keysym.
-
-(3) Sorry, these are not exact but they're the best we can do.
-
-(4) The uses of the "k0" capability are inconsistent; sometimes it
- describes F10, whereas othertimes it describes F0 and "k;" describes F10.
- Emacs attempts to politely accommodate both systems by testing for
- "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
------------------------------------------------------------------------------
-
- The following X keysyms do *not* have terminfo equivalents. These are
-the cookies your terminal package will have to set up itself, if you want them:
-
- break
- system
- user
- kp-backtab
- kp-space
- kp-tab
- kp-f1
- kp-f2
- kp-f3
- kp-f4
- kp-multiply
- kp-add
- kp-separator
- kp-subtract
- kp-decimal
- kp-divide
- kp-0
- kp-2
- kp-4
- kp-6
- kp-8
- kp-equal
-
- In general, you should not bind any of the standard keysym names to
-functions in a terminal package. There's code in loaddefs.el that does that;
-the less people make exceptions to that, the more consistent an interface Emacs
-will have across different keyboards. Those exceptions should go in your
-.emacs file.
-
- Finally, if you're using a USL UNIX or a Sun box or anything else with the
-USL version of curses(3) on it, bear in mind that the original curses(3) had
-(and still has) a very much smaller set of keycaps. In fact, the reliable
-ones were just the arrow keys and the first ten function keys. If you care
-about making your package portable to older Berkeley machines, don't count on
-the setup code to bind anything else.
-
- If your terminal's arrow key sequences are so funky that they conflict with
-normal Emacs key bindings, the package should set up a function called
-(enable-foo-arrow-keys), where `foo' becomes the terminal name, and leave
-it up to the user's .emacs file whether to call it.
-
- Before writing a terminal-support package, it's a good idea to read the
-existing ones and learn the common conventions.
diff --git a/lisp/term/apollo.el b/lisp/term/apollo.el
deleted file mode 100644
index ffe8e6bb1a6..00000000000
--- a/lisp/term/apollo.el
+++ /dev/null
@@ -1 +0,0 @@
-(load "term/vt100" nil t)
diff --git a/lisp/term/bg-mouse.el b/lisp/term/bg-mouse.el
deleted file mode 100644
index dfd81d3fba9..00000000000
--- a/lisp/term/bg-mouse.el
+++ /dev/null
@@ -1,313 +0,0 @@
-;;; bg-mouse.el --- GNU Emacs code for BBN Bitgraph mouse.
-
-;; Copyright (C) Free Software Foundation, Inc. Oct 1985.
-
-;; Author: John Robinson <jr@bbn-unix.arpa>
-;; Stephen Gildea <gildea@bbn.com>
-;; Maintainer: FSF
-;; Keywords: hardware
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;;; Original version by John Robinson (jr@bbn-unix.arpa, bbncca!jr), Oct 1985
-;;; Modularized and enhanced by gildea@bbn.com Nov 1987
-;;; Time stamp <89/03/21 14:27:08 gildea>
-
-;;; User customization option:
-
-(defvar bg-mouse-fast-select-window nil
- "*Non-nil for mouse hits to select new window, then execute; else just select.")
-
-;;; These numbers are summed to make the index into the mouse-map.
-;;; The low three bits correspond to what the mouse actually sends.
-(defconst bg-button-r 1)
-(defconst bg-button-m 2)
-(defconst bg-button-c 2)
-(defconst bg-button-l 4)
-(defconst bg-in-modeline 8)
-(defconst bg-in-scrollbar 16)
-(defconst bg-in-minibuf 24)
-
-;;; semicolon screws up indenting, so use this instead
-(defconst semicolon ?\;)
-
-;;; Defuns:
-
-(defun bg-mouse-report (prefix-arg)
- "Read, parse, and execute a BBN BitGraph mouse click.
-
-L-- move point | These apply for mouse click in a window.
---R set mark | If bg-mouse-fast-select-window is nil,
-L-R kill region | these commands on a nonselected window
--C- move point and yank | just select that window.
-LC- yank-pop |
--CR or LCR undo | \"Scroll bar\" is right-hand window column.
-
-on modeline: on \"scroll bar\": in minibuffer:
-L-- scroll-up line to top execute-extended-command
---R scroll-down line to bottom eval-expression
--C- proportional goto-char line to middle suspend-emacs
-
-To reinitialize the mouse if the terminal is reset, type ESC : RET"
- (interactive "P")
- (bg-get-tty-num semicolon)
- (let*
- ((screen-mouse-x (min (1- (frame-width)) ;don't hit column 86!
- (/ (bg-get-tty-num semicolon) 9)))
- (screen-mouse-y (- (1- (frame-height)) ;assume default font size.
- (/ (bg-get-tty-num semicolon) 16)))
- (bg-mouse-buttons (% (bg-get-tty-num ?c) 8))
- (bg-mouse-window (bg-window-from-x-y screen-mouse-x screen-mouse-y))
- (bg-cursor-window (selected-window))
- (edges (window-edges bg-mouse-window))
- (minibuf-p (= screen-mouse-y (1- (screen-height))))
- (in-modeline-p (and (not minibuf-p)
- (= screen-mouse-y (1- (nth 3 edges)))))
- (in-scrollbar-p (and (not minibuf-p) (not in-modeline-p)
- (>= screen-mouse-x (1- (nth 2 edges)))))
- (same-window-p (eq bg-mouse-window bg-cursor-window))
- (in-minibuf-p (and minibuf-p
- (not bg-mouse-window))) ;minibuf must be inactive
- (bg-mode-bits (+ (if in-minibuf-p bg-in-minibuf 0)
- (if in-modeline-p bg-in-modeline 0)
- (if in-scrollbar-p bg-in-scrollbar 0)))
- (bg-command
- (lookup-key mouse-map
- (char-to-string (+ bg-mode-bits bg-mouse-buttons))))
- (bg-mouse-x (- screen-mouse-x (nth 0 edges)))
- (bg-mouse-y (- screen-mouse-y (nth 1 edges))))
- (cond ((or in-modeline-p in-scrollbar-p)
- (select-window bg-mouse-window)
- (bg-command-execute bg-command)
- (select-window bg-cursor-window))
- ((or same-window-p in-minibuf-p)
- (bg-command-execute bg-command))
- (t ;in another window
- (select-window bg-mouse-window)
- (if bg-mouse-fast-select-window
- (bg-command-execute bg-command)))
- )))
-
-
-;;; Library of commands:
-
-(defun bg-set-point ()
- "Move point to location of BitGraph mouse."
- (interactive)
- (bg-move-point-to-x-y bg-mouse-x bg-mouse-y)
- (setq this-command 'next-line) ;make subsequent line moves work
- (setq temporary-goal-column bg-mouse-x))
-
-(defun bg-set-mark ()
- "Set mark at location of BitGraph mouse."
- (interactive)
- (push-mark)
- (bg-move-point-to-x-y bg-mouse-x bg-mouse-y)
- (exchange-point-and-mark))
-
-(defun bg-yank ()
- "Move point to location of BitGraph mouse and yank."
- (interactive "*")
- (bg-move-point-to-x-y bg-mouse-x bg-mouse-y)
- (setq this-command 'yank)
- (yank))
-
-(defun yank-pop-1 ()
- (interactive "*")
- (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."
- (interactive "*")
- (if (eql last-command 'yank)
- (yank-pop 1)
- (bg-yank)))
-
-;;; In 18.51, Emacs Lisp doesn't provide most-positive-fixnum
-(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."
- (interactive)
- ;; check carefully for overflow in intermediate calculations
- (goto-char
- (cond ((zerop bg-mouse-x)
- 0)
- ((< (buffer-size) (/ bg-most-positive-fixnum bg-mouse-x))
- ;; no danger of overflow: compute it exactly
- (/ (* bg-mouse-x (buffer-size))
- (1- (window-width))))
- (t
- ;; overflow possible: approximate
- (* (/ (buffer-size) (1- (window-width)))
- bg-mouse-x))))
- (beginning-of-line)
- (what-cursor-position))
-
-(defun bg-mouse-line-to-top ()
- "Scroll the line pointed to by the BitGraph mouse to the top of the window."
- (interactive)
- (scroll-up bg-mouse-y))
-
-(defun bg-mouse-line-to-center ()
- "Scroll the line pointed to by the BitGraph mouse to the center
-of the window"
- (interactive)
- (scroll-up (/ (+ 2 bg-mouse-y bg-mouse-y (- (window-height))) 2)))
-
-(defun bg-mouse-line-to-bottom ()
- "Scroll the line pointed to by the mouse to the bottom of the window."
- (interactive)
- (scroll-up (+ bg-mouse-y (- 2 (window-height)))))
-
-(defun bg-kill-region ()
- (interactive "*")
- (kill-region (region-beginning) (region-end)))
-
-(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)."
- (interactive)
- (let ((moused-text
- (save-excursion
- (bg-move-point-to-x-y bg-mouse-x bg-mouse-y)
- (if (looking-at "\\s)")
- (forward-char 1)
- (forward-sexp 1))
- (buffer-substring (save-excursion (backward-sexp 1) (point))
- (point)))))
- (select-window bg-cursor-window)
- (delete-horizontal-space)
- (cond
- ((bolp)
- (indent-according-to-mode))
- ;; In Lisp assume double-quote is closing; in Text assume opening.
- ;; Why? Because it does the right thing most often.
- ((save-excursion (forward-char -1)
- (and (not (looking-at "\\s\""))
- (looking-at "[`'\"\\]\\|\\s(")))
- nil)
- (t
- (insert-string " ")))
- (insert-string moused-text)
- (or (eolp)
- (looking-at "\\s.\\|\\s)")
- (and (looking-at "'") (looking-at "\\sw")) ;hack for text mode
- (save-excursion (insert-string " ")))))
-
-;;; Utility functions:
-
-(defun bg-get-tty-num (term-char)
- "Read from terminal until TERM-CHAR is read, and return intervening number.
-If non-numeric not matching TERM-CHAR, reprogram the mouse and signal an error."
- (let
- ((num 0)
- (char (- (read-char) 48)))
- (while (and (>= char 0)
- (<= char 9))
- (setq num (+ (* num 10) char))
- (setq char (- (read-char) 48)))
- (or (eq term-char (+ char 48))
- (progn
- (bg-program-mouse)
- (error
- "Invalid data format in bg-mouse command: mouse reinitialized.")))
- num))
-
-;;; Note that this fails in the minibuf because move-to-column doesn't
-;;; allow for the width of the prompt.
-(defun bg-move-point-to-x-y (x y)
- "Position cursor in window coordinates.
-X and Y are 0-based character positions in the window."
- (move-to-window-line y)
- ;; if not on a wrapped line, zero-column will be 0
- (let ((zero-column (current-column))
- (scroll-offset (window-hscroll)))
- ;; scrolling takes up column 0 to display the $
- (if (> scroll-offset 0)
- (setq scroll-offset (1- scroll-offset)))
- (move-to-column (+ zero-column scroll-offset x))
- ))
-
-;;; Returns the window that screen position (x, y) is in or nil if none,
-;;; meaning we are in the echo area with a non-active minibuffer.
-;;; If coordinates-in-window-p were not in an X-windows-specific file
-;;; we could use that. In Emacs 19 can even use locate-window-from-coordinates
-(defun bg-window-from-x-y (x y)
- "Find window corresponding to screen coordinates.
-X and Y are 0-based character positions on the screen."
- (let ((edges (window-edges))
- (window nil))
- (while (and (not (eq window (selected-window)))
- (or (< y (nth 1 edges))
- (>= y (nth 3 edges))
- (< x (nth 0 edges))
- (>= x (nth 2 edges))))
- (setq window (next-window window))
- (setq edges (window-edges window)))
- (cond ((eq window (selected-window))
- nil) ;we've looped: not found
- ((not window)
- (selected-window)) ;just starting: current window
- (t
- window))
- ))
-
-(defun bg-command-execute (bg-command)
- (if (commandp bg-command)
- (command-execute bg-command)
- (ding)))
-
-(defun bg-program-mouse ()
- (send-string-to-terminal "\e:0;7;;;360;512;9;16;9;16c"))
-
-;;; Note that the doc string for mouse-map (as defined in subr.el)
-;;; says it is for the X-window mouse. This is wrong; that keymap
-;;; should be used for your mouse no matter what terminal you have.
-
-(or (keymapp mouse-map)
- (setq mouse-map (make-keymap)))
-
-(defun bind-bg-mouse-click (click-code function)
- "Bind bg-mouse CLICK-CODE to run FUNCTION."
- (define-key mouse-map (char-to-string click-code) function))
-
-(bind-bg-mouse-click bg-button-l 'bg-set-point)
-(bind-bg-mouse-click bg-button-m 'bg-yank)
-(bind-bg-mouse-click bg-button-r 'bg-set-mark)
-(bind-bg-mouse-click (+ bg-button-l bg-button-m) 'yank-pop-1)
-(bind-bg-mouse-click (+ bg-button-l bg-button-r) 'bg-kill-region)
-(bind-bg-mouse-click (+ bg-button-m bg-button-r) 'undo)
-(bind-bg-mouse-click (+ bg-button-l bg-button-m bg-button-r) 'undo)
-(bind-bg-mouse-click (+ bg-in-modeline bg-button-l) 'scroll-up)
-(bind-bg-mouse-click (+ bg-in-modeline bg-button-m) 'bg-move-by-percentage)
-(bind-bg-mouse-click (+ bg-in-modeline bg-button-r) 'scroll-down)
-(bind-bg-mouse-click (+ bg-in-scrollbar bg-button-l) 'bg-mouse-line-to-top)
-(bind-bg-mouse-click (+ bg-in-scrollbar bg-button-m) 'bg-mouse-line-to-center)
-(bind-bg-mouse-click (+ bg-in-scrollbar bg-button-r) 'bg-mouse-line-to-bottom)
-(bind-bg-mouse-click (+ bg-in-minibuf bg-button-l) 'execute-extended-command)
-(bind-bg-mouse-click (+ bg-in-minibuf bg-button-m) 'suspend-emacs)
-(bind-bg-mouse-click (+ bg-in-minibuf bg-button-r) 'eval-expression)
-
-(provide 'bg-mouse)
-
-;;; bg-mouse.el ends here
diff --git a/lisp/term/bobcat.el b/lisp/term/bobcat.el
deleted file mode 100644
index f106b8b75c2..00000000000
--- a/lisp/term/bobcat.el
+++ /dev/null
@@ -1,2 +0,0 @@
-;;; HP terminals usually encourage using ^H as the rubout character
-(load "term/keyswap" nil t)
diff --git a/lisp/term/internal.el b/lisp/term/internal.el
deleted file mode 100644
index e9e6c02336d..00000000000
--- a/lisp/term/internal.el
+++ /dev/null
@@ -1,91 +0,0 @@
-;; internal.el -- setup support for PC keyboards and screens, internal terminal
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Morten Welinder <terra@diku.dk>
-;; Version: 1.02
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;; ---------------------------------------------------------------------------
-;; screen setup -- that's easy!
-(standard-display-8bit 127 254)
-;; ---------------------------------------------------------------------------
-;; keyboard setup -- that's simple!
-(set-input-mode nil nil 0)
-(define-key function-key-map [backspace] "\177") ; Normal behaviour for BS
-(define-key function-key-map [delete] "\C-d") ; ... and Delete
-(define-key function-key-map [tab] [?\t])
-(define-key function-key-map [linefeed] [?\n])
-(define-key function-key-map [clear] [11])
-(define-key function-key-map [return] [13])
-(define-key function-key-map [escape] [?\e])
-(define-key function-key-map [M-backspace] [?\M-\d])
-(define-key function-key-map [M-delete] [?\M-\d])
-(define-key function-key-map [M-tab] [?\M-\t])
-(define-key function-key-map [M-linefeed] [?\M-\n])
-(define-key function-key-map [M-clear] [?\M-\013])
-(define-key function-key-map [M-return] [?\M-\015])
-(define-key function-key-map [M-escape] [?\M-\e])
-(put 'backspace 'ascii-character 127)
-(put 'delete 'ascii-character 127)
-(put 'tab 'ascii-character ?\t)
-(put 'linefeed 'ascii-character ?\n)
-(put 'clear 'ascii-character 12)
-(put 'return 'ascii-character 13)
-(put 'escape 'ascii-character ?\e)
-;; ---------------------------------------------------------------------------
-;; We want to do this when Emacs is started because it depends on the
-;; country code.
-(let* ((i 128)
- (modify (function
- (lambda (ch sy)
- (modify-syntax-entry ch sy text-mode-syntax-table)
- (if (boundp 'tex-mode-syntax-table)
- (modify-syntax-entry ch sy tex-mode-syntax-table))
- (modify-syntax-entry ch sy (standard-syntax-table))
- )))
- (table (standard-case-table))
- ;; The following are strings of letters, first lower then upper case.
- ;; This will look funny on terminals which display other code pages.
- (chars
- (cond
- ((= dos-codepage 850)
- "‡€š‚ƒ¶„Ž…·†ÆÇ µˆÒ‰ÓŠÔ‹ØŒ×Þ¡Ö‘’“â”™•ã¢à›–ê£é—ë˜Yìí¡I£é¤¥ÐÑçè")
- ((= dos-codepage 865)
- "‡€š‚ƒA„Ž…A†ˆE‰EŠE‹IŒII‘’“O”™•O–U£U˜Y› A¡I¢O£U¤¥")
- ;; default is 437
- (t "‡€š‚ƒA„Ž…A†ˆE‰EŠE‹IŒII‘’“O”™•O–U£U˜Y A¡I¢O£U¤¥"))))
-
- (while (< i 256)
- (funcall modify i "_")
- (setq i (1+ i)))
-
- (setq i 0)
- (while (< i (length chars))
- (let ((ch1 (aref chars i))
- (ch2 (aref chars (1+ i))))
- (if (> ch2 127)
- (set-case-syntax-pair ch2 ch1 table))
- (setq i (+ i 2))))
- (save-excursion
- (mapcar (lambda (b) (set-buffer b) (set-case-table table))
- (buffer-list)))
- (set-standard-case-table table))
diff --git a/lisp/term/keyswap.el b/lisp/term/keyswap.el
deleted file mode 100644
index 55ef13fd9b1..00000000000
--- a/lisp/term/keyswap.el
+++ /dev/null
@@ -1,41 +0,0 @@
-;; keyswap.el --- swap BS and DEL keys
-
-;; Copyright (C) 1992 Free Software Foundation, Inc.
-
-;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
-;; Keywords: terminals
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package is meant to be called by other terminal packages.
-
-;;; Code:
-
-(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))
-
-;;; keyswap.el ends here
diff --git a/lisp/term/lk201.el b/lisp/term/lk201.el
deleted file mode 100644
index aedf221b4f1..00000000000
--- a/lisp/term/lk201.el
+++ /dev/null
@@ -1,68 +0,0 @@
-;; Define function key sequences for DEC terminals.
-
-;; Termcap or terminfo should set these.
-;; (define-key function-key-map "\e[A" [up])
-;; (define-key function-key-map "\e[B" [down])
-;; (define-key function-key-map "\e[C" [right])
-;; (define-key function-key-map "\e[D" [left])
-
-(define-key function-key-map "\e[1~" [find])
-(define-key function-key-map "\e[2~" [insert])
-(define-key function-key-map "\e[3~" [delete])
-(define-key function-key-map "\e[4~" [select])
-(define-key function-key-map "\e[5~" [prior])
-(define-key function-key-map "\e[6~" [next])
-(define-key function-key-map "\e[11~" [f1])
-(define-key function-key-map "\e[12~" [f2])
-(define-key function-key-map "\e[13~" [f3])
-(define-key function-key-map "\e[14~" [f4])
-(define-key function-key-map "\e[15~" [f5])
-(define-key function-key-map "\e[17~" [f6])
-(define-key function-key-map "\e[18~" [f7])
-(define-key function-key-map "\e[19~" [f8])
-(define-key function-key-map "\e[20~" [f9])
-(define-key function-key-map "\e[21~" [f10])
-;; Customarily F11 is used as the ESC key.
-;; The file that includes this one, takes care of that.
-(define-key function-key-map "\e[23~" [f11])
-(define-key function-key-map "\e[24~" [f12])
-(define-key function-key-map "\e[25~" [f13])
-(define-key function-key-map "\e[26~" [f14])
-(define-key function-key-map "\e[28~" [help])
-(define-key function-key-map "\e[29~" [menu])
-(define-key function-key-map "\e[31~" [f17])
-(define-key function-key-map "\e[32~" [f18])
-(define-key function-key-map "\e[33~" [f19])
-(define-key function-key-map "\e[34~" [f20])
-
-;; Termcap or terminfo should set these.
-;; (define-key function-key-map "\eOA" [up])
-;; (define-key function-key-map "\eOB" [down])
-;; (define-key function-key-map "\eOC" [right])
-;; (define-key function-key-map "\eOD" [left])
-
-;; Termcap or terminfo should set these, but doesn't properly.
-;; Termcap sets these to k1-k4, which get mapped to f1-f4 in term.c
-(define-key function-key-map "\eOP" [kp-f1])
-(define-key function-key-map "\eOQ" [kp-f2])
-(define-key function-key-map "\eOR" [kp-f3])
-(define-key function-key-map "\eOS" [kp-f4])
-
-(define-key function-key-map "\eOI" [kp-tab])
-(define-key function-key-map "\eOj" [kp-multiply])
-(define-key function-key-map "\eOk" [kp-add])
-(define-key function-key-map "\eOl" [kp-separator])
-(define-key function-key-map "\eOM" [kp-enter])
-(define-key function-key-map "\eOm" [kp-subtract])
-(define-key function-key-map "\eOn" [kp-decimal])
-(define-key function-key-map "\eOo" [kp-divide])
-(define-key function-key-map "\eOp" [kp-0])
-(define-key function-key-map "\eOq" [kp-1])
-(define-key function-key-map "\eOr" [kp-2])
-(define-key function-key-map "\eOs" [kp-3])
-(define-key function-key-map "\eOt" [kp-4])
-(define-key function-key-map "\eOu" [kp-5])
-(define-key function-key-map "\eOv" [kp-6])
-(define-key function-key-map "\eOw" [kp-7])
-(define-key function-key-map "\eOx" [kp-8])
-(define-key function-key-map "\eOy" [kp-9])
diff --git a/lisp/term/news.el b/lisp/term/news.el
deleted file mode 100644
index d0939db95ea..00000000000
--- a/lisp/term/news.el
+++ /dev/null
@@ -1,73 +0,0 @@
-;; news.el --- keypad and function key bindings for the Sony NEWS keyboard
-
-;; Copyright (C) 1989, 1993 Free Software Foundation, Inc.
-
-;; Author: FSF
-;; Keywords: terminals
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Uses the Emacs 19 terminal initialization features --- won't work with 18.
-
-;;; Code:
-
-(if (boundp 'news-fkey-prefix)
- nil
- ;; The terminal initialization should already have set up some keys
- (setq news-fkey-prefix (lookup-key function-key-map "\eO"))
- (if (not (keymapp news-fkey-prefix))
- (error "What? Your news termcap/terminfo has no keycaps in it."))
-
- ;; Termcap or terminfo will set these
- ;; (define-key news-fkey-prefix "P" [f1])
- ;; (define-key news-fkey-prefix "Q" [f2])
- ;; (define-key news-fkey-prefix "R" [f3])
- ;; (define-key news-fkey-prefix "S" [f4])
- ;; (define-key news-fkey-prefix "T" [f5])
- ;; (define-key news-fkey-prefix "U" [f6])
- ;; (define-key news-fkey-prefix "V" [f7])
- ;; (define-key news-fkey-prefix "W" [f8])
- ;; (define-key news-fkey-prefix "X" [f9])
- ;; (define-key news-fkey-prefix "Y" [f10])
-
- ;; Terminfo will set these
- (define-key news-fkey-prefix "a" [execute])
- (define-key news-fkey-prefix "b" [select])
- (define-key news-fkey-prefix "c" [cancel])
- (define-key news-fkey-prefix "M" [kp-enter])
- (define-key news-fkey-prefix "q" [kp-1])
- (define-key news-fkey-prefix "s" [kp-3])
- (define-key news-fkey-prefix "u" [kp-5])
- (define-key news-fkey-prefix "w" [kp-7])
- (define-key news-fkey-prefix "y" [kp-9])
-
- ;; These aren't in either termcap or terminfo's repertoire
- (define-key news-fkey-prefix "m" [kp-subtract])
- (define-key news-fkey-prefix "k" [kp-add])
- (define-key news-fkey-prefix "l" [kp-separator])
- (define-key news-fkey-prefix "n" [kp-decimal])
- (define-key news-fkey-prefix "p" [kp-0])
- (define-key news-fkey-prefix "r" [kp-2])
- (define-key news-fkey-prefix "t" [kp-4])
- (define-key news-fkey-prefix "v" [kp-6])
- (define-key news-fkey-prefix "x" [kp-8])
- )
-
-;;; news.el ends here
diff --git a/lisp/term/pc-win.el b/lisp/term/pc-win.el
deleted file mode 100644
index 50d101f9ef5..00000000000
--- a/lisp/term/pc-win.el
+++ /dev/null
@@ -1,329 +0,0 @@
-;; pc-win.el -- setup support for `PC windows' (whatever that is).
-
-;; Copyright (C) 1994, 1996 Free Software Foundation, Inc.
-
-;; Author: Morten Welinder <terra@diku.dk>
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(load "term/internal" nil t)
-
-;; Color translation -- doesn't really need to be fast.
-;; Colors listed here do not include the "light-",
-;; "medium-" and "dark-" prefixes that are accounted for
-;; by `msdos-color-translate', which see below).
-
-(defvar msdos-color-aliases
- '(("snow" . "white")
- ("ghost white" . "white")
- ("ghostwhite" . "white")
- ("white smoke" . "white")
- ("whitesmoke" . "white")
- ("gainsboro" . "white")
- ("floral white" . "white")
- ("floralwhite" . "white")
- ("old lace" . "white")
- ("oldlace" . "white")
- ("linen" . "white")
- ("antique white" . "white")
- ("antiquewhite" . "white")
- ("papaya whip" . "white")
- ("papayawhip" . "white")
- ("blanched almond" . "white")
- ("blanchedalmond" . "white")
- ("bisque" . "white")
- ("peach puff" . "lightred")
- ("peachpuff" . "lightred")
- ("navajo white" . "lightred")
- ("navajowhite" . "lightred")
- ("moccasin" . "lightred")
- ("cornsilk" . "white")
- ("ivory" . "white")
- ("lemon chiffon" . "yellow")
- ("lemonchiffon" . "yellow")
- ("seashell" . "white")
- ("honeydew" . "white")
- ("mint cream" . "white")
- ("mintcream" . "white")
- ("azure" . "lightcyan")
- ("alice blue" . "lightcyan")
- ("aliceblue" . "lightcyan")
- ("lavender" . "lightcyan")
- ("lavender blush" . "lightcyan")
- ("lavenderblush" . "lightcyan")
- ("misty rose" . "lightred")
- ("mistyrose" . "lightred")
- ("aquamarine" . "blue")
- ("cadet blue" . "blue")
- ("cadetblue" . "blue")
- ("cornflower blue" . "lightblue")
- ("cornflowerblue" . "lightblue")
- ("midnight blue" . "blue")
- ("midnightblue" . "blue")
- ("navy blue" . "cyan")
- ("navyblue" . "cyan")
- ("navy" . "cyan")
- ("sky blue" . "lightblue")
- ("skyblue" . "lightblue")
- ("dodger blue" . "blue")
- ("dodgerblue" . "blue")
- ("powder blue" . "lightblue")
- ("powderblue" . "lightblue")
- ("slate blue" . "cyan")
- ("slateblue" . "cyan")
- ("steel blue" . "blue")
- ("steelblue" . "blue")
- ("coral" . "lightred")
- ("firebrick" . "red")
- ("gold" . "yellow")
- ("goldenrod" . "yellow")
- ("pale goldenrod" . "yellow")
- ("palegoldenrod" . "yellow")
- ("olive green" . "lightgreen")
- ("olivegreen" . "lightgreen")
- ("olive drab" . "green")
- ("olivedrab" . "green")
- ("forest green" . "green")
- ("forestgreen" . "green")
- ("lime green" . "lightgreen")
- ("limegreen" . "lightgreen")
- ("sea green" . "lightcyan")
- ("seagreen" . "lightcyan")
- ("spring green" . "green")
- ("springgreen" . "green")
- ("pale green" . "lightgreen")
- ("palegreen" . "lightgreen")
- ("lawn green" . "lightgreen")
- ("lawngreen" . "lightgreen")
- ("chartreuse" . "yellow")
- ("yellow green" . "lightgreen")
- ("yellowgreen" . "lightgreen")
- ("green yellow" . "lightgreen")
- ("greenyellow" . "lightgreen")
- ("slate grey" . "lightgray")
- ("slategrey" . "lightgray")
- ("slate gray" . "lightgray")
- ("slategray" . "lightgray")
- ("dim grey" . "darkgray")
- ("dimgrey" . "darkgray")
- ("dim gray" . "darkgray")
- ("dimgray" . "darkgray")
- ("light grey" . "lightgray")
- ("lightgrey" . "lightgray")
- ("light gray" . "lightgray")
- ("gray" . "darkgray")
- ("grey" . "darkgray")
- ("gray80" . "darkgray")
- ("gray50" . "black")
- ("gray90" . "darkgray")
- ("khaki" . "green")
- ("maroon" . "red")
- ("orange" . "brown")
- ("orchid" . "brown")
- ("saddle brown" . "red")
- ("saddlebrown" . "red")
- ("sienna" . "red")
- ("peru" . "red")
- ("pink" . "lightred")
- ("plum" . "magenta")
- ("indian red" . "red")
- ("indianred" . "red")
- ("violet red" . "magenta")
- ("violetred" . "magenta")
- ("orange red" . "red")
- ("orangered" . "red")
- ("salmon" . "lightred")
- ("sienna" . "lightred")
- ("tan" . "lightred")
- ("thistle" . "magenta")
- ("turquoise" . "lightgreen")
- ("pale turquoise" . "cyan")
- ("paleturquoise" . "cyan")
- ("violet" . "magenta")
- ("blue violet" . "lightmagenta")
- ("blueviolet" . "lightmagenta")
- ("wheat" . "white")
- ("green yellow" . "yellow")
- ("greenyellow" . "yellow")
- ("purple" . "magenta")
- ("royalblue" . "blue")
- ("grey40" . "darkgray")
- ("rosybrown" . "brown")
- ("rosy brown" . "brown")
- ("beige" . "brown"))
- "List of alternate names for colors.")
-
-(defun msdos-color-translate (name)
- (setq name (downcase name))
- (let* ((len (length name))
- (val (- (length x-colors)
- (length (member name x-colors))))
- (try))
- (if (or (< val 0) (>= val (length x-colors))) (setq val nil))
- (or val
- (and (setq try (cdr (assoc name msdos-color-aliases)))
- (msdos-color-translate try))
- (and (> len 5)
- (string= "light" (substring name 0 5))
- (setq try (msdos-color-translate (substring name 5)))
- (logior try 8))
- (and (> len 6)
- (string= "light " (substring name 0 6))
- (setq try (msdos-color-translate (substring name 6)))
- (logior try 8))
- (and (> len 6)
- (string= "medium" (substring name 0 6))
- (msdos-color-translate (substring name 6)))
- (and (> len 7)
- (string= "medium " (substring name 0 7))
- (msdos-color-translate (substring name 7)))
- (and (> len 4)
- (string= "dark" (substring name 0 4))
- (msdos-color-translate (substring name 4)))
- (and (> len 5)
- (string= "dark " (substring name 0 5))
- (msdos-color-translate (substring name 5))))))
-;; ---------------------------------------------------------------------------
-;; We want to delay setting frame parameters until the faces are setup
-(defvar default-frame-alist nil)
-(modify-frame-parameters terminal-frame default-frame-alist)
-
-(defun msdos-face-setup ()
- (modify-frame-parameters terminal-frame default-frame-alist)
-
- (set-face-foreground 'bold "yellow" terminal-frame)
- (set-face-foreground 'italic "red" terminal-frame)
- (set-face-foreground 'bold-italic "lightred" terminal-frame)
- (set-face-foreground 'underline "white" terminal-frame)
- (set-face-background 'region "green" terminal-frame)
-
- (make-face 'msdos-menu-active-face)
- (make-face 'msdos-menu-passive-face)
- (make-face 'msdos-menu-select-face)
- (set-face-foreground 'msdos-menu-active-face "white" terminal-frame)
- (set-face-foreground 'msdos-menu-passive-face "lightgray" terminal-frame)
- (set-face-background 'msdos-menu-active-face "blue" terminal-frame)
- (set-face-background 'msdos-menu-passive-face "blue" terminal-frame)
- (set-face-background 'msdos-menu-select-face "red" terminal-frame))
-
-;; We have only one font, so...
-(add-hook 'before-init-hook 'msdos-face-setup)
-
-;; We create frames as if we were a terminal, but with a twist.
-(defun make-msdos-frame (&optional parameters)
- (let ((parms
- (append initial-frame-alist default-frame-alist parameters nil)))
- (make-terminal-frame parms)))
-
-(setq frame-creation-function 'make-msdos-frame)
-
-;; ---------------------------------------------------------------------------
-;; More or less useful imitations of certain X-functions. A lot of the
-;; values returned are questionable, but usually only the form of the
-;; returned value matters. Also, by the way, recall that `ignore' is
-;; a useful function for returning 'nil regardless of argument.
-
-;; From src/xfns.c
-(defun x-display-color-p (&optional display) 't)
-(defun x-list-fonts (pattern &optional face frame) (list "default"))
-(defun x-color-defined-p (color) (numberp (msdos-color-translate color)))
-(defun x-display-pixel-width (&optional frame) (frame-width frame))
-(defun x-display-pixel-height (&optional frame) (frame-height frame))
-(defun x-display-planes (&optional frame) 4) ; 3 for background, actually
-(defun x-display-color-cells (&optional frame) 16) ; ???
-(defun x-server-max-request-size (&optional frame) 1000000) ; ???
-(defun x-server-vendor (&optional frame) t "GNU")
-(defun x-server-version (&optional frame) '(1 0 0))
-(defun x-display-screens (&optional frame) 1)
-(defun x-display-mm-height (&optional frame) 200) ; Guess the size of my
-(defun x-display-mm-width (&optional frame) 253) ; monitor, MW...
-(defun x-display-backing-store (&optional frame) 'not-useful)
-(defun x-display-visual-class (&optional frame) 'static-color)
-(fset 'x-display-save-under 'ignore)
-(fset 'x-get-resource 'ignore)
-
-;; From lisp/term/x-win.el
-(setq x-display-name "pc")
-(setq split-window-keep-point t)
-(defvar x-colors '("black"
- "blue"
- "green"
- "cyan"
- "red"
- "magenta"
- "brown"
- "lightgray"
- "darkgray"
- "lightblue"
- "lightgreen"
- "lightcyan"
- "lightred"
- "lightmagenta"
- "yellow"
- "white")
- "The list of colors available on a PC display under MS-DOS.")
-(defun x-defined-colors (&optional frame)
- "Return a list of colors supported for a particular frame.
-The argument FRAME specifies which frame to try.
-The value may be different for frames on different X displays."
- x-colors)
-;
-;; From lisp/select.el
-(defun x-get-selection (&rest rest) "")
-(fset 'x-set-selection 'ignore)
-
-;; From lisp/faces.el: we only have one font, so always return
-;; it, no matter which variety they've asked for.
-(defun x-frob-font-slant (font which)
- font)
-
-;; From lisp/term/x-win.el: make iconify-or-deiconify-frame a no-op.
-(fset 'iconify-or-deiconify-frame 'ignore)
-
-;; From lisp/frame.el
-(fset 'set-default-font 'ignore)
-(fset 'set-mouse-color 'ignore) ; We cannot, I think.
-(fset 'set-cursor-color 'ignore) ; Hardware determined by char under.
-(fset 'set-border-color 'ignore) ; Not useful.
-;; ---------------------------------------------------------------------------
-;; Handle the X-like command line parameters "-fg" and "-bg"
-(defun msdos-handle-args (args)
- (let ((rest nil))
- (while args
- (let ((this (car args)))
- (setq args (cdr args))
- (cond ((or (string= this "-fg") (string= this "-foreground"))
- (if args
- (setq default-frame-alist
- (cons (cons 'foreground-color (car args))
- default-frame-alist)
- args (cdr args))))
- ((or (string= this "-bg") (string= this "-background"))
- (if args
- (setq default-frame-alist
- (cons (cons 'background-color (car args))
- default-frame-alist)
- args (cdr args))))
- (t (setq rest (cons this rest))))))
- (nreverse rest)))
-
-(setq command-line-args (msdos-handle-args command-line-args))
-;; ---------------------------------------------------------------------------
diff --git a/lisp/term/sun-mouse.el b/lisp/term/sun-mouse.el
deleted file mode 100644
index 7287b59c191..00000000000
--- a/lisp/term/sun-mouse.el
+++ /dev/null
@@ -1,681 +0,0 @@
-;;; sun-mouse.el --- mouse handling for Sun windows
-
-;; Copyright (C) 1987 Free Software Foundation, Inc.
-
-;; Author: Jeff Peck
-;; Maintainer: FSF
-;; Keywords: hardware
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Jeff Peck, Sun Microsystems, Jan 1987.
-;; Original idea by Stan Jefferson
-
-;; Modeled after the GNUEMACS keymap interface.
-;;
-;; User Functions:
-;; make-mousemap, copy-mousemap,
-;; define-mouse, global-set-mouse, local-set-mouse,
-;; use-global-mousemap, use-local-mousemap,
-;; mouse-lookup, describe-mouse-bindings
-;;
-;; Options:
-;; extra-click-wait, scrollbar-width
-
-;;; Code:
-
-(defvar extra-click-wait 150
- "*Number of milliseconds to wait for an extra click.
-Set this to zero if you don't want chords or double clicks.")
-
-(defvar scrollbar-width 5
- "*The character width of the scrollbar.
-The cursor is deemed to be in the right edge scrollbar if it is this near the
-right edge, and more than two chars past the end of the indicated line.
-Setting to nil limits the scrollbar to the edge or vertical dividing bar.")
-
-;;;
-;;; Mousemaps
-;;;
-(defun make-mousemap ()
- "Returns a new mousemap."
- (cons 'mousemap nil))
-
-(defun copy-mousemap (mousemap)
- "Return a copy of mousemap."
- (copy-alist mousemap))
-
-(defun define-mouse (mousemap mouse-list def)
- "Args MOUSEMAP, MOUSE-LIST, DEF. Define MOUSE-LIST in MOUSEMAP as DEF.
-MOUSE-LIST is a list of atoms specifying a mouse hit according to these rules:
- * One of these atoms specifies the active region of the definition.
- text, scrollbar, modeline, minibuffer
- * One or two or these atoms specify the button or button combination.
- left, middle, right, double
- * Any combination of these atoms specify the active shift keys.
- control, shift, meta
- * With a single unshifted button, you can add
- up
- to indicate an up-click.
-The atom `double' is used with a button designator to denote a double click.
-Two button chords are denoted by listing the two buttons.
-See sun-mouse-handler for the treatment of the form DEF."
- (mousemap-set (mouse-list-to-mouse-code mouse-list) mousemap def))
-
-(defun global-set-mouse (mouse-list def)
- "Give MOUSE-EVENT-LIST a local definition of DEF.
-See define-mouse for a description of MOUSE-EVENT-LIST and DEF.
-Note that if MOUSE-EVENT-LIST has a local definition in the current buffer,
-that local definition will continue to shadow any global definition."
- (interactive "xMouse event: \nxDefinition: ")
- (define-mouse current-global-mousemap mouse-list def))
-
-(defun local-set-mouse (mouse-list def)
- "Give MOUSE-EVENT-LIST a local definition of DEF.
-See define-mouse for a description of the arguments.
-The definition goes in the current buffer's local mousemap.
-Normally buffers in the same major mode share a local mousemap."
- (interactive "xMouse event: \nxDefinition: ")
- (if (null current-local-mousemap)
- (setq current-local-mousemap (make-mousemap)))
- (define-mouse current-local-mousemap mouse-list def))
-
-(defun use-global-mousemap (mousemap)
- "Selects MOUSEMAP as the global mousemap."
- (setq current-global-mousemap mousemap))
-
-(defun use-local-mousemap (mousemap)
- "Selects MOUSEMAP as the local mousemap.
-nil for MOUSEMAP means no local mousemap."
- (setq current-local-mousemap mousemap))
-
-
-;;;
-;;; Interface to the Mouse encoding defined in Emacstool.c
-;;;
-;;; Called when mouse-prefix is sent to emacs, additional
-;;; information is read in as a list (button x y time-delta)
-;;;
-;;; First, some generally useful functions:
-;;;
-
-(defun logtest (x y)
- "True if any bits set in X are also set in Y.
-Just like the Common Lisp function of the same name."
- (not (zerop (logand x y))))
-
-
-;;;
-;;; Hit accessors.
-;;;
-
-(defconst sm::ButtonBits 7) ; Lowest 3 bits.
-(defconst sm::ShiftmaskBits 56) ; Second lowest 3 bits (56 = 63 - 7).
-(defconst sm::DoubleBits 64) ; Bit 7.
-(defconst sm::UpBits 128) ; Bit 8.
-
-;;; All the useful code bits
-(defmacro sm::hit-code (hit)
- (` (nth 0 (, hit))))
-;;; The button, or buttons if a chord.
-(defmacro sm::hit-button (hit)
- (` (logand sm::ButtonBits (nth 0 (, hit)))))
-;;; The shift, control, and meta flags.
-(defmacro sm::hit-shiftmask (hit)
- (` (logand sm::ShiftmaskBits (nth 0 (, hit)))))
-;;; Set if a double click (but not a chord).
-(defmacro sm::hit-double (hit)
- (` (logand sm::DoubleBits (nth 0 (, hit)))))
-;;; Set on button release (as opposed to button press).
-(defmacro sm::hit-up (hit)
- (` (logand sm::UpBits (nth 0 (, hit)))))
-;;; Screen x position.
-(defmacro sm::hit-x (hit) (list 'nth 1 hit))
-;;; Screen y position.
-(defmacro sm::hit-y (hit) (list 'nth 2 hit))
-;;; Milliseconds since last hit.
-(defmacro sm::hit-delta (hit) (list 'nth 3 hit))
-
-(defmacro sm::hit-up-p (hit) ; A predicate.
- (` (not (zerop (sm::hit-up (, hit))))))
-
-;;;
-;;; Loc accessors. for sm::window-xy
-;;;
-(defmacro sm::loc-w (loc) (list 'nth 0 loc))
-(defmacro sm::loc-x (loc) (list 'nth 1 loc))
-(defmacro sm::loc-y (loc) (list 'nth 2 loc))
-
-(defmacro eval-in-buffer (buffer &rest forms)
- "Macro to switches to BUFFER, evaluates FORMS, returns to original buffer."
- ;; When you don't need the complete window context of eval-in-window
- (` (let ((StartBuffer (current-buffer)))
- (unwind-protect
- (progn
- (set-buffer (, buffer))
- (,@ forms))
- (set-buffer StartBuffer)))))
-
-(put 'eval-in-buffer 'lisp-indent-function 1)
-
-;;; this is used extensively by sun-fns.el
-;;;
-(defmacro eval-in-window (window &rest forms)
- "Switch to WINDOW, evaluate FORMS, return to original window."
- (` (let ((OriginallySelectedWindow (selected-window)))
- (unwind-protect
- (progn
- (select-window (, window))
- (,@ forms))
- (select-window OriginallySelectedWindow)))))
-(put 'eval-in-window 'lisp-indent-function 1)
-
-;;;
-;;; handy utility, generalizes window_loop
-;;;
-
-;;; It's a macro (and does not evaluate its arguments).
-(defmacro eval-in-windows (form &optional yesmini)
- "Switches to each window and evaluates FORM. Optional argument
-YESMINI says to include the minibuffer as a window.
-This is a macro, and does not evaluate its arguments."
- (` (let ((OriginallySelectedWindow (selected-window)))
- (unwind-protect
- (while (progn
- (, form)
- (not (eq OriginallySelectedWindow
- (select-window
- (next-window nil (, yesmini)))))))
- (select-window OriginallySelectedWindow)))))
-(put 'eval-in-window 'lisp-indent-function 0)
-
-(defun move-to-loc (x y)
- "Move cursor to window location X, Y.
-Handles wrapped and horizontally scrolled lines correctly."
- (move-to-window-line y)
- ;; window-line-end expects this to return the window column it moved to.
- (let ((cc (current-column))
- (nc (move-to-column
- (if (zerop (window-hscroll))
- (+ (current-column)
- (min (- (window-width) 2) ; To stay on the line.
- x))
- (+ (window-hscroll) -1
- (min (1- (window-width)) ; To stay on the line.
- x))))))
- (- nc cc)))
-
-
-(defun minibuffer-window-p (window)
- "True iff this WINDOW is minibuffer."
- (= (frame-height)
- (nth 3 (window-edges window)) ; The bottom edge.
- ))
-
-
-(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).
-A form bound to button by define-mouse is found by mouse-lookup.
-The variables: *mouse-window*, *mouse-x*, *mouse-y* are bound.
-If the form is a symbol (symbolp), it is funcall'ed with *mouse-window*,
-*mouse-x*, and *mouse-y* as arguments; if the form is a list (listp),
-the form is eval'ed; if the form is neither of these, it is an error.
-Returns nil."
- (interactive)
- (if (null hit) (setq hit (sm::combined-hits)))
- (let ((loc (sm::window-xy (sm::hit-x hit) (sm::hit-y hit))))
- (let ((*mouse-window* (sm::loc-w loc))
- (*mouse-x* (sm::loc-x loc))
- (*mouse-y* (sm::loc-y loc))
- (mouse-code (mouse-event-code hit loc)))
- (let ((form (eval-in-buffer (window-buffer *mouse-window*)
- (mouse-lookup mouse-code))))
- (cond ((null form)
- (if (not (sm::hit-up-p hit)) ; undefined up hits are ok.
- (error "Undefined mouse event: %s"
- (prin1-to-string
- (mouse-code-to-mouse-list mouse-code)))))
- ((symbolp form)
- (setq this-command form)
- (funcall form *mouse-window* *mouse-x* *mouse-y*))
- ((listp form)
- (setq this-command (car form))
- (eval form))
- (t
- (error "Mouse action must be symbol or list, but was: %s"
- form))))))
- ;; Don't let 'sun-mouse-handler get on last-command,
- ;; since this function should be transparent.
- (if (eq this-command 'sun-mouse-handler)
- (setq this-command last-command))
- ;; (message (prin1-to-string this-command)) ; to see what your buttons did
- nil)
-
-(defun sm::combined-hits ()
- "Read and return next mouse-hit, include possible double click"
- (let ((hit1 (mouse-hit-read)))
- (if (not (sm::hit-up-p hit1)) ; Up hits don't start doubles or chords.
- (let ((hit2 (mouse-second-hit extra-click-wait)))
- (if hit2 ; we cons'd it, we can smash it.
- ; (setf (sm::hit-code hit1) (logior (sm::hit-code hit1) ...))
- (setcar hit1 (logior (sm::hit-code hit1)
- (sm::hit-code hit2)
- (if (= (sm::hit-button hit1)
- (sm::hit-button hit2))
- sm::DoubleBits 0))))))
- hit1))
-
-(defun mouse-hit-read ()
- "Read mouse-hit list from keyboard. Like (read 'read-char),
-but that uses minibuffer, and mucks up last-command."
- (let ((char-list nil) (char nil))
- (while (not (equal 13 ; Carriage return.
- (prog1 (setq char (read-char))
- (setq char-list (cons char char-list))))))
- (read (mapconcat 'char-to-string (nreverse char-list) ""))
- ))
-
-;;; Second Click Hackery....
-;;; if prefix is not mouse-prefix, need a way to unread the char...
-;;; or else have mouse flush input queue, or else need a peek at next char.
-
-;;; There is no peek, but since one character can be unread, we only
-;;; have to flush the queue when the command after a mouse click
-;;; starts with mouse-prefix1 (see below).
-;;; Something to do later: We could buffer the read commands and
-;;; execute them ourselves after doing the mouse command (using
-;;; lookup-key ??).
-
-(defvar mouse-prefix1 24 ; C-x
- "First char of mouse-prefix. Used to detect double clicks and chords.")
-
-(defvar mouse-prefix2 0 ; C-@
- "Second char of mouse-prefix. Used to detect double clicks and chords.")
-
-
-(defun mouse-second-hit (hit-wait)
- "Returns the next mouse hit occurring within HIT-WAIT milliseconds."
- (if (sit-for-millisecs hit-wait) nil ; No input within hit-wait millisecs.
- (let ((pc1 (read-char)))
- (if (or (not (equal pc1 mouse-prefix1))
- (sit-for-millisecs 3)) ; a mouse prefix will have second char
- ;; Can get away with one unread.
- (progn (setq unread-command-events (list pc1))
- nil) ; Next input not mouse event.
- (let ((pc2 (read-char)))
- (if (not (equal pc2 mouse-prefix2))
- (progn (setq unread-command-events (list pc1)) ; put back the ^X
-;;; Too bad can't do two: (setq unread-command-event (list pc1 pc2))
-;;; Well, now we can, but I don't understand this code well enough to fix it...
- (ding) ; user will have to retype that pc2.
- nil) ; This input is not a mouse event.
- ;; Next input has mouse prefix and is within time limit.
- (let ((new-hit (mouse-hit-read))) ; Read the new hit.
- (if (sm::hit-up-p new-hit) ; Ignore up events when timing.
- (mouse-second-hit (- hit-wait (sm::hit-delta new-hit)))
- new-hit ; New down hit within limit, return it.
- ))))))))
-
-(defun sm::window-xy (x y)
- "Find window containing screen coordinates X and Y.
-Returns list (window x y) where x and y are relative to window."
- (or
- (catch 'found
- (eval-in-windows
- (let ((we (window-edges (selected-window))))
- (let ((le (nth 0 we))
- (te (nth 1 we))
- (re (nth 2 we))
- (be (nth 3 we)))
- (if (= re (frame-width))
- ;; include the continuation column with this window
- (setq re (1+ re)))
- (if (= be (frame-height))
- ;; include partial line at bottom of frame with this window
- ;; id est, if window is not multiple of char size.
- (setq be (1+ be)))
-
- (if (and (>= x le) (< x re)
- (>= y te) (< y be))
- (throw 'found
- (list (selected-window) (- x le) (- y te))))))
- t)) ; include minibuffer in eval-in-windows
- ;;If x,y from a real mouse click, we shouldn't get here.
- (list nil x y)
- ))
-
-(defun sm::window-region (loc)
- "Parse LOC into a region symbol.
-Returns one of (text scrollbar modeline minibuffer)"
- (let ((w (sm::loc-w loc))
- (x (sm::loc-x loc))
- (y (sm::loc-y loc)))
- (let ((right (1- (window-width w)))
- (bottom (1- (window-height w))))
- (cond ((minibuffer-window-p w) 'minibuffer)
- ((>= y bottom) 'modeline)
- ((>= x right) 'scrollbar)
- ;; far right column (window separator) is always a scrollbar
- ((and scrollbar-width
- ;; mouse within scrollbar-width of edge.
- (>= x (- right scrollbar-width))
- ;; mouse a few chars past the end of line.
- (>= x (+ 2 (window-line-end w x y))))
- 'scrollbar)
- (t 'text)))))
-
-(defun window-line-end (w x y)
- "Return WINDOW column (ignore X) containing end of line Y"
- (eval-in-window w (save-excursion (move-to-loc (frame-width) y))))
-
-;;;
-;;; The encoding of mouse events into a mousemap.
-;;; These values must agree with coding in emacstool:
-;;;
-(defconst sm::keyword-alist
- '((left . 1) (middle . 2) (right . 4)
- (shift . 8) (control . 16) (meta . 32) (double . 64) (up . 128)
- (text . 256) (scrollbar . 512) (modeline . 1024) (minibuffer . 2048)
- ))
-
-(defun mouse-event-code (hit loc)
- "Maps MOUSE-HIT and LOC into a mouse-code."
-;;;Region is a code for one of text, modeline, scrollbar, or minibuffer.
- (logior (sm::hit-code hit)
- (mouse-region-to-code (sm::window-region loc))))
-
-(defun mouse-region-to-code (region)
- "Returns partial mouse-code for specified REGION."
- (cdr (assq region sm::keyword-alist)))
-
-(defun mouse-list-to-mouse-code (mouse-list)
- "Map a MOUSE-LIST to a mouse-code."
- (apply 'logior
- (mapcar (function (lambda (x)
- (cdr (assq x sm::keyword-alist))))
- mouse-list)))
-
-(defun mouse-code-to-mouse-list (mouse-code)
- "Map a MOUSE-CODE to a mouse-list."
- (apply 'nconc (mapcar
- (function (lambda (x)
- (if (logtest mouse-code (cdr x))
- (list (car x)))))
- sm::keyword-alist)))
-
-(defun mousemap-set (code mousemap value)
- (let* ((alist (cdr mousemap))
- (assq-result (assq code alist)))
- (if assq-result
- (setcdr assq-result value)
- (setcdr mousemap (cons (cons code value) alist)))))
-
-(defun mousemap-get (code mousemap)
- (cdr (assq code (cdr mousemap))))
-
-(defun mouse-lookup (mouse-code)
- "Look up MOUSE-EVENT and return the definition. nil means undefined."
- (or (mousemap-get mouse-code current-local-mousemap)
- (mousemap-get mouse-code current-global-mousemap)))
-
-;;;
-;;; I (jpeck) don't understand the utility of the next four functions
-;;; ask Steven Greenbaum <froud@kestrel>
-;;;
-(defun mouse-mask-lookup (mask list)
- "Args MASK (a bit mask) and LIST (a list of (code . form) pairs).
-Returns a list of elements of LIST whose code or'ed with MASK is non-zero."
- (let ((result nil))
- (while list
- (if (logtest mask (car (car list)))
- (setq result (cons (car list) result)))
- (setq list (cdr list)))
- result))
-
-(defun mouse-union (l l-unique)
- "Return the union of list of mouse (code . form) pairs L and L-UNIQUE,
-where L-UNIQUE is considered to be union'ized already."
- (let ((result l-unique))
- (while l
- (let ((code-form-pair (car l)))
- (if (not (assq (car code-form-pair) result))
- (setq result (cons code-form-pair result))))
- (setq l (cdr l)))
- result))
-
-(defun mouse-union-first-preferred (l1 l2)
- "Return the union of lists of mouse (code . form) pairs L1 and L2,
-based on the code's, with preference going to elements in L1."
- (mouse-union l2 (mouse-union l1 nil)))
-
-(defun mouse-code-function-pairs-of-region (region)
- "Return a list of (code . function) pairs, where each code is
-currently set in the REGION."
- (let ((mask (mouse-region-to-code region)))
- (mouse-union-first-preferred
- (mouse-mask-lookup mask (cdr current-local-mousemap))
- (mouse-mask-lookup mask (cdr current-global-mousemap))
- )))
-
-;;;
-;;; Functions for DESCRIBE-MOUSE-BINDINGS
-;;; And other mouse documentation functions
-;;; Still need a good procedure to print out a help sheet in readable format.
-;;;
-
-(defun one-line-doc-string (function)
- "Returns first line of documentation string for FUNCTION.
-If there is no documentation string, then the string
-\"No documentation\" is returned."
- (while (consp function) (setq function (car function)))
- (let ((doc (documentation function)))
- (if (null doc)
- "No documentation."
- (string-match "^.*$" doc)
- (substring doc 0 (match-end 0)))))
-
-(defun print-mouse-format (binding)
- (princ (car binding))
- (princ ": ")
- (mapcar (function
- (lambda (mouse-list)
- (princ mouse-list)
- (princ " ")))
- (cdr binding))
- (terpri)
- (princ " ")
- (princ (one-line-doc-string (car binding)))
- (terpri)
- )
-
-(defun print-mouse-bindings (region)
- "Prints mouse-event bindings for REGION."
- (mapcar 'print-mouse-format (sm::event-bindings region)))
-
-(defun sm::event-bindings (region)
- "Returns an alist of (function . (mouse-list1 ... mouse-listN)) for REGION,
-where each mouse-list is bound to the function in REGION."
- (let ((mouse-bindings (mouse-code-function-pairs-of-region region))
- (result nil))
- (while mouse-bindings
- (let* ((code-function-pair (car mouse-bindings))
- (current-entry (assoc (cdr code-function-pair) result)))
- (if current-entry
- (setcdr current-entry
- (cons (mouse-code-to-mouse-list (car code-function-pair))
- (cdr current-entry)))
- (setq result (cons (cons (cdr code-function-pair)
- (list (mouse-code-to-mouse-list
- (car code-function-pair))))
- result))))
- (setq mouse-bindings (cdr mouse-bindings))
- )
- result))
-
-(defun describe-mouse-bindings ()
- "Lists all current mouse-event bindings."
- (interactive)
- (with-output-to-temp-buffer "*Help*"
- (princ "Text Region") (terpri)
- (princ "---- ------") (terpri)
- (print-mouse-bindings 'text) (terpri)
- (princ "Modeline Region") (terpri)
- (princ "-------- ------") (terpri)
- (print-mouse-bindings 'modeline) (terpri)
- (princ "Scrollbar Region") (terpri)
- (princ "--------- ------") (terpri)
- (print-mouse-bindings 'scrollbar)))
-
-(defun describe-mouse-briefly (mouse-list)
- "Print a short description of the function bound to MOUSE-LIST."
- (interactive "xDescribe mouse list briefly: ")
- (let ((function (mouse-lookup (mouse-list-to-mouse-code mouse-list))))
- (if function
- (message "%s runs the command %s" mouse-list function)
- (message "%s is undefined" mouse-list))))
-
-(defun mouse-help-menu (function-and-binding)
- (cons (prin1-to-string (car function-and-binding))
- (menu-create ; Two sub-menu items of form ("String" . nil)
- (list (list (one-line-doc-string (car function-and-binding)))
- (list (prin1-to-string (cdr function-and-binding)))))))
-
-(defun mouse-help-region (w x y &optional region)
- "Displays a menu of mouse functions callable in this region."
- (let* ((region (or region (sm::window-region (list w x y))))
- (mlist (mapcar (function mouse-help-menu)
- (sm::event-bindings region)))
- (menu (menu-create (cons (list (symbol-name region)) mlist)))
- (item (sun-menu-evaluate w 0 y menu))
- )))
-
-;;;
-;;; Menu interface functions
-;;;
-;;; use defmenu, because this interface is subject to change
-;;; really need a menu-p, but we use vectorp and the context...
-;;;
-(defun menu-create (items)
- "Functional form for defmenu, given a list of ITEMS returns a menu.
-Each ITEM is a (STRING . VALUE) pair."
- (apply 'vector items)
- )
-
-(defmacro defmenu (menu &rest itemlist)
- "Defines MENU to be a menu, the ITEMS are (STRING . VALUE) pairs.
-See sun-menu-evaluate for interpretation of ITEMS."
- (list 'defconst menu (funcall 'menu-create itemlist))
- )
-
-(defun sun-menu-evaluate (*menu-window* *menu-x* *menu-y* menu)
- "Display a pop-up menu in WINDOW at X Y and evaluate selected item
-of MENU. MENU (or its symbol-value) should be a menu defined by defmenu.
- A menu ITEM is a (STRING . FORM) pair;
-the FORM associated with the selected STRING is evaluated,
-and the resulting value is returned. Generally these FORMs are
-evaluated for their side-effects rather than their values.
- If the selected form is a menu or a symbol whose value is a menu,
-then it is displayed and evaluated as a pullright menu item.
- If the the FORM of the first ITEM is nil, the STRING of the item
-is used as a label for the menu, i.e. it's inverted and not selectable."
-
- (if (symbolp menu) (setq menu (symbol-value menu)))
- (eval (sun-menu-internal *menu-window* *menu-x* *menu-y* 4 menu)))
-
-(defun sun-get-frame-data (code)
- "Sends the tty-sub-window escape sequence CODE to terminal,
-and returns a cons of the two numbers in returned escape sequence.
-That is it returns (cons <car> <cdr>) from \"\\E[n;<car>;<cdr>t\".
-CODE values: 13 = Tool-Position, 14 = Size-in-Pixels, 18 = Size-in-Chars."
- (send-string-to-terminal (concat "\033[" (int-to-string code) "t"))
- (let (char str x y)
- (while (not (equal 116 (setq char (read-char)))) ; #\t = 116
- (setq str (cons char str)))
- (setq str (mapconcat 'char-to-string (nreverse str) ""))
- (string-match ";[0-9]*" str)
- (setq y (substring str (1+ (match-beginning 0)) (match-end 0)))
- (setq str (substring str (match-end 0)))
- (string-match ";[0-9]*" str)
- (setq x (substring str (1+ (match-beginning 0)) (match-end 0)))
- (cons (string-to-int y) (string-to-int x))))
-
-(defun sm::font-size ()
- "Returns font size in pixels: (cons Ysize Xsize)"
- (let ((pix (sun-get-frame-data 14)) ; returns size in pixels
- (chr (sun-get-frame-data 18))) ; returns size in chars
- (cons (/ (car pix) (car chr)) (/ (cdr pix) (cdr chr)))))
-
-(defvar sm::menu-kludge-x nil
- "Cached frame-to-window X-Offset for sm::menu-kludge")
-(defvar sm::menu-kludge-y nil
- "Cached frame-to-window Y-Offset for sm::menu-kludge")
-
-(defun sm::menu-kludge ()
- "If sunfns.c uses <Menu_Base_Kludge> this function must be here!"
- (or sm::menu-kludge-y
- (let ((fs (sm::font-size)))
- (setq sm::menu-kludge-y (+ 8 (car fs)) ; a title line and borders
- sm::menu-kludge-x 4))) ; best values depend on .defaults/Menu
- (let ((wl (sun-get-frame-data 13))) ; returns frame location
- (cons (+ (car wl) sm::menu-kludge-y)
- (+ (cdr wl) sm::menu-kludge-x))))
-
-;;;
-;;; Function interface to selection/region
-;;; primitive functions are defined in sunfns.c
-;;;
-(defun sun-yank-selection ()
- "Set mark and yank the contents of the current sunwindows selection.
-Insert contents into the current buffer at point."
- (interactive "*")
- (set-mark-command nil)
- (insert-string (sun-get-selection)))
-
-(defun sun-select-region (beg end)
- "Set the sunwindows selection to the region in the current buffer."
- (interactive "r")
- (sun-set-selection (buffer-substring beg end)))
-
-;;;
-;;; Support for emacstool
-;;; This closes the window instead of stopping emacs.
-;;;
-(defun suspend-emacstool (&optional stuffstring)
- "Suspend emacstool.
-If running under as a detached process emacstool,
-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 stuffstring (send-string-to-terminal stuffstring))
- (send-string-to-terminal "\033[2t") ; To close EmacsTool window.
- (run-hooks 'suspend-resume-hook))
-;;;
-;;; initialize mouse maps
-;;;
-
-(make-variable-buffer-local 'current-local-mousemap)
-(setq-default current-local-mousemap nil)
-(defvar current-global-mousemap (make-mousemap))
-
-(provide 'sun-mouse)
-
-;;; sun-mouse.el ends here
diff --git a/lisp/term/sun.el b/lisp/term/sun.el
deleted file mode 100644
index 4d75e524f4e..00000000000
--- a/lisp/term/sun.el
+++ /dev/null
@@ -1,280 +0,0 @@
-;; sun.el --- keybinding for standard default sunterm keys
-
-;; Copyright (C) 1987 Free Software Foundation, Inc.
-
-;; Author: Jeff Peck <peck@sun.com>
-;; Keywords: terminals
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The function key sequences for the console have been converted for
-;; use with function-key-map, but the *tool stuff hasn't been touched.
-
-;;; Code:
-
-(defun ignore-key ()
- "interactive version of ignore"
- (interactive)
- (ignore))
-
-(defun scroll-down-in-place (n)
- (interactive "p")
- (previous-line n)
- (scroll-down n))
-
-(defun scroll-up-in-place (n)
- (interactive "p")
- (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 select-previous-complex-command ()
- "Select Previous-complex-command"
- (interactive)
- (if (zerop (minibuffer-depth))
- (repeat-complex-command 1)
- (previous-complex-command 1)))
-
-(defun rerun-prev-command ()
- "Repeat Previous-complex-command."
- (interactive)
- (eval (nth 0 command-history)))
-
-(defvar grep-arg nil "Default arg for RE-search")
-(defun grep-arg ()
- (if (memq last-command '(research-forward research-backward)) grep-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)))
- )
- (if (and search-command (stringp search-arg)) (setq grep-arg search-arg)
- (setq search-command this-command
- grep-arg (read-string "REsearch: " grep-arg)
- this-command search-command)
- grep-arg))))
-
-(defun research-forward ()
- "Repeat RE search forward."
- (interactive)
- (re-search-forward (grep-arg)))
-
-(defun research-backward ()
- "Repeat RE search backward."
- (interactive)
- (re-search-backward (grep-arg)))
-
-;;;
-;;; 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
-;;;
-
-(defvar sun-esc-bracket nil
- "*If non-nil, rebind ESC [ as prefix for Sun function keys.")
-
-(defvar sun-raw-prefix (make-sparse-keymap))
-(define-key function-key-map "\e[" sun-raw-prefix)
-
-(define-key sun-raw-prefix "210z" [r3])
-(define-key sun-raw-prefix "213z" [r6])
-(define-key sun-raw-prefix "214z" [r7])
-(define-key sun-raw-prefix "216z" [r9])
-(define-key sun-raw-prefix "218z" [r11])
-(define-key sun-raw-prefix "220z" [r13])
-(define-key sun-raw-prefix "222z" [r15])
-(define-key sun-raw-prefix "193z" [redo])
-(define-key sun-raw-prefix "194z" [props])
-(define-key sun-raw-prefix "195z" [undo])
-; (define-key sun-raw-prefix "196z" 'ignore-key) ; Expose-down
-; (define-key sun-raw-prefix "197z" [put])
-; (define-key sun-raw-prefix "198z" 'ignore-key) ; Open-down
-; (define-key sun-raw-prefix "199z" [get])
-(define-key sun-raw-prefix "200z" [find])
-; (define-key sun-raw-prefix "201z" 'kill-region-and-unmark) ; Delete
-(define-key sun-raw-prefix "226z" [t3])
-(define-key sun-raw-prefix "227z" [t4])
-(define-key sun-raw-prefix "229z" [t6])
-(define-key sun-raw-prefix "230z" [t7])
-(define-key sun-raw-prefix "A" [up]) ; R8
-(define-key sun-raw-prefix "B" [down]) ; R14
-(define-key sun-raw-prefix "C" [right]) ; R12
-(define-key sun-raw-prefix "D" [left]) ; R10
-
-(global-set-key [r3] 'backward-page)
-(global-set-key [r6] 'forward-page)
-(global-set-key [r7] 'beginning-of-buffer)
-(global-set-key [r9] 'scroll-down)
-(global-set-key [r11] 'recenter)
-(global-set-key [r13] 'end-of-buffer)
-(global-set-key [r15] 'scroll-up)
-(global-set-key [redo] 'redraw-display)
-(global-set-key [props] 'list-buffers)
-(global-set-key [undo] 'undo)
-(global-set-key [put] 'sun-select-region)
-(global-set-key [get] 'sun-yank-selection)
-(global-set-key [find] 'exchange-point-and-mark)
-(global-set-key [t3] 'scroll-down-in-place)
-(global-set-key [t4] 'scroll-up-in-place)
-(global-set-key [t6] 'shrink-window)
-(global-set-key [t7] 'enlarge-window)
-
-
-(if sun-esc-bracket (global-unset-key "\e["))
-
-;;; Since .emacs gets loaded before this file, a hook is supplied
-;;; for you to put your own bindings in.
-
-(defvar sun-raw-prefix-hooks nil
- "List of forms to evaluate after setting sun-raw-prefix.")
-
-(let ((hooks sun-raw-prefix-hooks))
- (while hooks
- (eval (car hooks))
- (setq hooks (cdr hooks))
- ))
-
-
-;;; This section adds definitions 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!
-;;;
-;;; Important to define SHIFTed sequence before matching unshifted sequence.
-;;; (talk about bletcherous old uppercase terminal conventions!*$#@&%*&#$%)
-;;; this is worse than C-S/C-Q flow control anyday!
-;;; Do *YOU* run in capslock mode?
-;;;
-
-;;; Note: al, el and gl 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 "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" 'prev-complex-command) ; M-Again
-(define-key suntool-map "bl" 'redraw-display) ; Again
-(define-key suntool-map "cl" 'list-buffers) ; Props
-(define-key suntool-map "dl" 'undo) ; Undo
-(define-key suntool-map "el" 'ignore-key) ; Expose-Open
-(define-key suntool-map "fl" 'sun-select-region) ; Put
-(define-key suntool-map "f," 'copy-region-as-kill) ; C-Put
-(define-key suntool-map "gl" 'ignore-key) ; Open-Open
-(define-key suntool-map "hl" 'sun-yank-selection) ; Get
-(define-key suntool-map "h," 'yank) ; C-Get
-(define-key suntool-map "il" 'research-forward) ; Find
-(define-key suntool-map "i," 're-search-forward) ; C-Find
-(define-key suntool-map "i\M-l" 'research-backward) ; M-Find
-(define-key suntool-map "i\M-," 're-search-backward) ; C-M-Find
-
-(define-key suntool-map "jL" 'yank) ; DELETE
-(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 "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 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 ctl-x-map "*" suntool-map)
-
-;;; Since .emacs gets loaded before this file, a hook is supplied
-;;; for you to put your own bindings in.
-
-(defvar suntool-map-hooks nil
- "List of forms to evaluate after setting suntool-map.")
-
-(let ((hooks suntool-map-hooks))
- (while hooks
- (eval (car hooks))
- (setq hooks (cdr 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 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 (< (sun-window-init) 0)
- (message "Not a Sun 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\\"))
- ))
-
-(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.
- )
-(define-key ctl-x-map "\C-@" 'sun-mouse-once)
-
-;;; sun.el ends here
diff --git a/lisp/term/sup-mouse.el b/lisp/term/sup-mouse.el
deleted file mode 100644
index 0075b302526..00000000000
--- a/lisp/term/sup-mouse.el
+++ /dev/null
@@ -1,208 +0,0 @@
-;;; sup-mouse.el --- supdup mouse support for lisp machines
-
-;; Copyright (C) Free Software Foundation 1985, 1986
-
-;; Author: Wolfgang Rupprecht
-;; Maintainer: FSF
-;; Created: 21 Nov 1986
-;; Keywords: hardware
-
-;; (from code originally written by John Robinson@bbn for the bitgraph)
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;;; User customization option:
-
-(defvar sup-mouse-fast-select-window nil
- "*Non-nil for mouse hits to select new window, then execute; else just select.")
-
-(defconst mouse-left 0)
-(defconst mouse-center 1)
-(defconst mouse-right 2)
-
-(defconst mouse-2left 4)
-(defconst mouse-2center 5)
-(defconst mouse-2right 6)
-
-(defconst mouse-3left 8)
-(defconst mouse-3center 9)
-(defconst mouse-3right 10)
-
-;;; Defuns:
-
-(defun sup-mouse-report ()
- "This function is called directly by the mouse, it parses and
-executes the mouse commands.
-
- L move point * |---- These apply for mouse click in a window.
-2L delete word |
-3L copy word | If sup-mouse-fast-select-window is nil,
- C move point and yank * | just selects that window.
-2C yank pop |
- R set mark * |
-2R delete region |
-3R copy region |
-
-on modeline on \"scroll bar\" in minibuffer
- L scroll-up line to top execute-extended-command
- C proportional goto-char line to middle mouse-help
- R scroll-down line to bottom eval-expression"
-
- (interactive)
- (let*
-;; expect a string of <esc>:<buttons>;<x-pos>;<y-pos>c
- ((buttons (sup-get-tty-num ?\;))
- (x (sup-get-tty-num ?\;))
- (y (sup-get-tty-num ?c))
- (window (sup-pos-to-window x y))
- (edges (window-edges window))
- (old-window (selected-window))
- (in-minibuf-p (eq y (1- (frame-height))))
- (same-window-p (and (not in-minibuf-p) (eq window old-window)))
- (in-modeline-p (eq y (1- (nth 3 edges))))
- (in-scrollbar-p (>= x (1- (nth 2 edges)))))
- (setq x (- x (nth 0 edges)))
- (setq y (- y (nth 1 edges)))
-
-; (error "mouse-hit %d %d %d" buttons x y) ;;;; debug
-
- (cond (in-modeline-p
- (select-window window)
- (cond ((= buttons mouse-left)
- (scroll-up))
- ((= buttons mouse-right)
- (scroll-down))
- ((= buttons mouse-center)
- (goto-char (/ (* x
- (- (point-max) (point-min)))
- (1- (window-width))))
- (beginning-of-line)
- (what-cursor-position)))
- (select-window old-window))
- (in-scrollbar-p
- (select-window window)
- (scroll-up
- (cond ((= buttons mouse-left)
- y)
- ((= buttons mouse-right)
- (+ y (- 2 (window-height))))
- ((= buttons mouse-center)
- (/ (+ 2 y y (- (window-height))) 2))
- (t
- 0)))
- (select-window old-window))
- (same-window-p
- (cond ((= buttons mouse-left)
- (sup-move-point-to-x-y x y))
- ((= buttons mouse-2left)
- (sup-move-point-to-x-y x y)
- (kill-word 1))
- ((= buttons mouse-3left)
- (sup-move-point-to-x-y x y)
- (save-excursion
- (copy-region-as-kill
- (point) (progn (forward-word 1) (point))))
- (setq this-command 'yank)
- )
- ((= buttons mouse-right)
- (push-mark)
- (sup-move-point-to-x-y x y)
- (exchange-point-and-mark))
- ((= buttons mouse-2right)
- (push-mark)
- (sup-move-point-to-x-y x y)
- (kill-region (mark) (point)))
- ((= buttons mouse-3right)
- (push-mark)
- (sup-move-point-to-x-y x y)
- (copy-region-as-kill (mark) (point))
- (setq this-command 'yank))
- ((= buttons mouse-center)
- (sup-move-point-to-x-y x y)
- (setq this-command 'yank)
- (yank))
- ((= buttons mouse-2center)
- (yank-pop 1))
- )
- )
- (in-minibuf-p
- (cond ((= buttons mouse-right)
- (call-interactively 'eval-expression))
- ((= buttons mouse-left)
- (call-interactively 'execute-extended-command))
- ((= buttons mouse-center)
- (describe-function 'sup-mouse-report)); silly self help
- ))
- (t ;in another window
- (select-window window)
- (cond ((not sup-mouse-fast-select-window))
- ((= buttons mouse-left)
- (sup-move-point-to-x-y x y))
- ((= buttons mouse-right)
- (push-mark)
- (sup-move-point-to-x-y x y)
- (exchange-point-and-mark))
- ((= buttons mouse-center)
- (sup-move-point-to-x-y x y)
- (setq this-command 'yank)
- (yank))
- ))
- )))
-
-
-(defun sup-get-tty-num (term-char)
- "Read from terminal until TERM-CHAR is read, and return intervening number.
-Upon non-numeric not matching TERM-CHAR signal an error."
- (let
- ((num 0)
- (char (read-char)))
- (while (and (>= char ?0)
- (<= char ?9))
- (setq num (+ (* num 10) (- char ?0)))
- (setq char (read-char)))
- (or (eq term-char char)
- (error "Invalid data format in mouse command"))
- num))
-
-(defun sup-move-point-to-x-y (x y)
- "Position cursor in window coordinates.
-X and Y are 0-based character positions in the window."
- (move-to-window-line y)
- (move-to-column x)
- )
-
-(defun sup-pos-to-window (x y)
- "Find window corresponding to frame coordinates.
-X and Y are 0-based character positions on the frame."
- (let ((edges (window-edges))
- (window nil))
- (while (and (not (eq window (selected-window)))
- (or (< y (nth 1 edges))
- (>= y (nth 3 edges))
- (< x (nth 0 edges))
- (>= x (nth 2 edges))))
- (setq window (next-window window))
- (setq edges (window-edges window))
- )
- (or window (selected-window))
- )
- )
-
-;;; sup-mouse.el ends here
diff --git a/lisp/term/tvi970.el b/lisp/term/tvi970.el
deleted file mode 100644
index 200ba315534..00000000000
--- a/lisp/term/tvi970.el
+++ /dev/null
@@ -1,126 +0,0 @@
-;;; tvi970.el --- terminal support for the Televideo 970
-
-;; Author: Jim Blandy <jimb@occs.cs.oberlin.edu>, January 1992
-;; Keywords: terminals
-
-;; 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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Uses the Emacs 19 terminal initialization features --- won't work with 18.
-
-;;; Code:
-
-(or (lookup-key function-key-map "\e[")
- (define-key function-key-map "\e[" (make-keymap)))
-;; (or (lookup-key function-key-map "\eO")
-;; (define-key function-key-map "\eO" (make-keymap)))
-
-;; Miscellaneous keys
-(mapcar (function (lambda (key-binding)
- (define-key function-key-map
- (car key-binding) (nth 1 key-binding))))
- '(
- ;; These are set up by termcap or terminfo
- ;; ("\eOP" [kp-f1])
- ;; ("\eOQ" [kp-f2])
- ;; ("\eOR" [kp-f3])
- ;; ("\eOS" [kp-f4])
-
- ;; These might br set by terminfo
- ("\e[H" [home])
- ("\e[Z" [backtab])
- ("\e[i" [print])
- ("\e[@" [insert])
- ("\e[L" [insertline])
- ("\e[M" [deleteline])
- ("\e[U" [next]) ;; actually the `page' key
-
- ;; These won't be set up by either
- ("\eOm" [kp-subtract])
- ("\eOl" [kp-separator])
- ("\eOn" [kp-decimal])
- ("\eOM" [kp-enter])
-
- ;; These won't be set up by either either
- ("\e[K" [key_eol]) ;; Not an X keysym
- ("\e[J" [key_eos]) ;; Not an X keysym
- ("\e[2J" [key_clear]) ;; Not an X keysym
- ("\e[P" [key_dc]) ;; Not an X keysym
- ("\e[g" [S-tab]) ;; Not an X keysym
- ("\e[2N" [clearentry]) ;; Not an X keysym
- ("\e[2K" [S-clearentry]) ;; Not an X keysym
- ("\e[E" [?\C-j]) ;; Not an X keysym
- ("\e[g" [S-backtab]) ;; Not an X keysym
- ("\e[?1i" [key_sprint]) ;; Not an X keysym
- ("\e[4h" [key_sic]) ;; Not an X keysym
- ("\e[4l" [S-delete]) ;; Not an X keysym
- ("\e[Q" [S-insertline]) ;; Not an X keysym
- ("\e[1Q" [key_sdl]) ;; Not an X keysym
- ("\e[19l" [key_seol]) ;; Not an X keysym
- ("\e[19h" [S-erasepage]) ;; Not an X keysym
- ("\e[V" [S-page]) ;; Not an X keysym
- ("\eS" [send]) ;; Not an X keysym
- ("\e5" [S-send]) ;; Not an X keysym
- ))
-
-;; The numeric keypad keys.
-(let ((i 0))
- (while (< i 10)
- (define-key function-key-map
- (format "\eO%c" (+ i ?p))
- (vector (intern (format "kp-%d" i))))
- (setq i (1+ i))))
-;; The numbered function keys.
-(let ((i 0))
- (while (< i 16)
- (define-key function-key-map
- (format "\e?%c" (+ i ?a))
- (vector (intern (format "f%d" (1+ i)))))
- (define-key function-key-map
- (format "\e?%c" (+ i ?A))
- (vector (intern (format "S-f%d" (1+ i)))))
- (setq i (1+ i))))
-
-
-;;; Should keypad numbers send ordinary digits or distinct escape sequences?
-(defvar tvi970-keypad-numeric nil
- "The terminal should be in numeric keypad mode iff this variable is non-nil.
-Do not set this variable! Call the function ``tvi970-set-keypad-mode''.")
-
-(defun tvi970-set-keypad-mode (&optional arg)
- "Set the current mode of the TVI 970 numeric keypad.
-In ``numeric keypad mode'', the number keys on the keypad act as
-ordinary digits. In ``alternate keypad mode'', the keys send distinct
-escape sequences, meaning that they can have their own bindings,
-independent of the normal number keys.
-With no argument, toggle between the two possible modes.
-With a positive argument, select alternate keypad mode.
-With a negative argument, select numeric keypad mode."
- (interactive "P")
- (setq tvi970-keypad-numeric
- (if (null arg)
- (not tvi970-keypad-numeric)
- (> (prefix-numeric-value arg) 0)))
- (send-string-to-terminal (if tvi970-keypad-numeric "\e=" "\e>")))
-
-(tvi970-set-keypad-mode 1)
-
-;;; tv970 ends here
diff --git a/lisp/term/vt100.el b/lisp/term/vt100.el
deleted file mode 100644
index 83fcc42d6e1..00000000000
--- a/lisp/term/vt100.el
+++ /dev/null
@@ -1,56 +0,0 @@
-;;; vt100.el --- define VT100 function key sequences in function-key-map
-
-;; Copyright (C) 1989, 1993 Free Software Foundation, Inc.
-
-;; Author: FSF
-;; Keywords: terminals
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Uses the Emacs 19 terminal initialization features --- won't work with 18.
-
-;; Handles all VT100 clones, including the Apollo terminal. Also handles
-;; the VT200 --- its PF- and arrow- keys are different, but all those
-;; are really set up by the terminal initialization code, which mines them
-;; out of termcap. This package is here to define the keypad comma, dash
-;; and period (which aren't in termcap's repertoire) and the function for
-;; changing from 80 to 132 columns & vv.
-
-;;; Code:
-
-;; Set up function-key-map entries that termcap and terminfo don't know.
-(load "term/lk201" nil t)
-
-;;; Controlling the screen width.
-(defconst vt100-wide-mode (= (frame-width) 132)
- "t if vt100 is in 132-column mode.")
-
-(defun vt100-wide-mode (&optional arg)
- "Toggle 132/80 column mode for vt100s.
-With positive argument, switch to 132-column mode.
-With negative argument, switch to 80-column mode."
- (interactive "P")
- (setq vt100-wide-mode
- (if (null arg) (not vt100-wide-mode)
- (> (prefix-numeric-value arg) 0)))
- (send-string-to-terminal (if vt100-wide-mode "\e[?3h" "\e[?3l"))
- (set-frame-width terminal-frame (if vt100-wide-mode 132 80)))
-
-;;; vt100.el ends here
diff --git a/lisp/term/vt200.el b/lisp/term/vt200.el
deleted file mode 100644
index 31f64a0f8b2..00000000000
--- a/lisp/term/vt200.el
+++ /dev/null
@@ -1,6 +0,0 @@
-;; For our purposes we can treat the vt200 and vt100 almost alike.
-;; Most differences are handled by the termcap entry.
-(load "term/vt100" nil t)
-
-;; Make F11 an escape key.
-(define-key function-key-map "\e[23~" [?\e])
diff --git a/lisp/term/vt201.el b/lisp/term/vt201.el
deleted file mode 100644
index c9cb12521dc..00000000000
--- a/lisp/term/vt201.el
+++ /dev/null
@@ -1,7 +0,0 @@
-;; For our purposes we can treat the vt200 and vt100 almost alike.
-;; Most differences are handled by the termcap entry.
-(load "term/vt100" nil t)
-
-;; Make F11 an escape key.
-(define-key function-key-map "\e[23~" [?\e])
-
diff --git a/lisp/term/vt220.el b/lisp/term/vt220.el
deleted file mode 100644
index c9cb12521dc..00000000000
--- a/lisp/term/vt220.el
+++ /dev/null
@@ -1,7 +0,0 @@
-;; For our purposes we can treat the vt200 and vt100 almost alike.
-;; Most differences are handled by the termcap entry.
-(load "term/vt100" nil t)
-
-;; Make F11 an escape key.
-(define-key function-key-map "\e[23~" [?\e])
-
diff --git a/lisp/term/vt240.el b/lisp/term/vt240.el
deleted file mode 100644
index 31f64a0f8b2..00000000000
--- a/lisp/term/vt240.el
+++ /dev/null
@@ -1,6 +0,0 @@
-;; For our purposes we can treat the vt200 and vt100 almost alike.
-;; Most differences are handled by the termcap entry.
-(load "term/vt100" nil t)
-
-;; Make F11 an escape key.
-(define-key function-key-map "\e[23~" [?\e])
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el
deleted file mode 100644
index c295cc39617..00000000000
--- a/lisp/term/w32-win.el
+++ /dev/null
@@ -1,669 +0,0 @@
-;;; win32-win.el --- parse switches controlling interface with win32
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Kevin Gallo
-;; Keywords: terminals
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; win32-win.el: this file is loaded from ../lisp/startup.el when it recognizes
-;; that win32 windows are to be used. Command line switches are parsed and those
-;; pertaining to win32 are processed and removed from the command line. The
-;; win32 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).
-
-;;; Code:
-
-
-;; 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
-;; -i .iconType
-;; -itype .iconType
-;; -iconic .iconic
-;; -name .name
-;; -reverse *reverseVideo
-;; -rv *reverseVideo
-;; -selectionTimeout .selectionTimeout
-;; -synchronous *synchronous
-;; -xrm
-
-;; An alist of X options and the function which handles them. See
-;; ../startup.el.
-
-(if (not (eq window-system 'win32))
- (error "%s: Loading win32-win.el but not compiled for win32" (invocation-name)))
-
-(require 'frame)
-(require 'mouse)
-(require 'scroll-bar)
-(require 'faces)
-(require 'select)
-(require 'menu-bar)
-
-;; Because Windows scrollbars look and act quite differently compared
-;; with the standard X scroll-bars, we don't try to use the normal
-;; scroll bar routines.
-
-(defun w32-handle-scroll-bar-event (event)
- "Handle Win32 scroll bar events to do normal Window style scrolling."
- (interactive "e")
- (let ((old-window (selected-window)))
- (unwind-protect
- (let* ((position (event-start event))
- (window (nth 0 position))
- (portion-whole (nth 2 position))
- (bar-part (nth 4 position)))
- (save-excursion
- (select-window window)
- (cond
- ((eq bar-part 'up)
- (scroll-down 1))
- ((eq bar-part 'above-handle)
- (scroll-down))
- ((eq bar-part 'handle)
- (scroll-bar-maybe-set-window-start event))
- ((eq bar-part 'below-handle)
- (scroll-up))
- ((eq bar-part 'down)
- (scroll-up 1))
- )))
- (select-window old-window))))
-
-;; The following definition is used for debugging.
-;(defun w32-handle-scroll-bar-event (event) (interactive "e") (princ event))
-
-(global-set-key [vertical-scroll-bar mouse-1] 'w32-handle-scroll-bar-event)
-
-;; (scroll-bar-mode nil)
-
-(defvar x-invocation-args)
-
-(defvar x-command-line-resources nil)
-
-(defconst x-option-alist
- '(("-bw" . x-handle-numeric-switch)
- ("-d" . x-handle-display)
- ("-display" . x-handle-display)
- ("-name" . x-handle-name-rn-switch)
- ("-rn" . x-handle-name-rn-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-numeric-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)
- ("-itype" . x-handle-switch)
- ("-i" . x-handle-switch)
- ("-iconic" . x-handle-iconic)
- ("-xrm" . x-handle-xrm-switch)
- ("-cr" . x-handle-switch)
- ("-vb" . x-handle-switch)
- ("-hb" . x-handle-switch)
- ("-bd" . x-handle-switch)))
-
-(defconst x-long-option-alist
- '(("--border-width" . "-bw")
- ("--display" . "-d")
- ("--name" . "-name")
- ("--title" . "-T")
- ("--reverse-video" . "-reverse")
- ("--font" . "-font")
- ("--internal-border" . "-ib")
- ("--geometry" . "-geometry")
- ("--foreground-color" . "-fg")
- ("--background-color" . "-bg")
- ("--mouse-color" . "-ms")
- ("--icon-type" . "-itype")
- ("--iconic" . "-iconic")
- ("--xrm" . "-xrm")
- ("--cursor-color" . "-cr")
- ("--vertical-scroll-bars" . "-vb")
- ("--border-color" . "-bd")))
-
-(defconst x-switch-definitions
- '(("-name" name)
- ("-T" name)
- ("-r" reverse t)
- ("-rv" reverse t)
- ("-reverse" reverse t)
- ("-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)
- ("-itype" icon-type t)
- ("-i" icon-type t)
- ("-vb" vertical-scroll-bars t)
- ("-hb" horizontal-scroll-bars t)
- ("-bd" border-color)
- ("-bw" border-width)))
-
-;; Handler for switches of the form "-switch value" or "-switch".
-(defun x-handle-switch (switch)
- (let ((aelt (assoc switch x-switch-definitions)))
- (if aelt
- (if (nth 2 aelt)
- (setq default-frame-alist
- (cons (cons (nth 1 aelt) (nth 2 aelt))
- default-frame-alist))
- (setq default-frame-alist
- (cons (cons (nth 1 aelt)
- (car x-invocation-args))
- default-frame-alist)
- x-invocation-args (cdr x-invocation-args))))))
-
-;; Make -iconic apply only to the initial frame!
-(defun x-handle-iconic (switch)
- (setq initial-frame-alist
- (cons '(visibility . icon) initial-frame-alist)))
-
-;; Handler for switches of the form "-switch n"
-(defun x-handle-numeric-switch (switch)
- (let ((aelt (assoc switch x-switch-definitions)))
- (if aelt
- (setq default-frame-alist
- (cons (cons (nth 1 aelt)
- (string-to-int (car x-invocation-args)))
- default-frame-alist)
- x-invocation-args
- (cdr x-invocation-args)))))
-
-;; Handle the -xrm option.
-(defun x-handle-xrm-switch (switch)
- (or (consp x-invocation-args)
- (error "%s: missing argument to `%s' option" (invocation-name) switch))
- (setq x-command-line-resources (car x-invocation-args))
- (setq x-invocation-args (cdr x-invocation-args)))
-
-;; Handle the geometry option
-(defun x-handle-geometry (switch)
- (let ((geo (x-parse-geometry (car x-invocation-args))))
- (setq initial-frame-alist
- (append initial-frame-alist
- (if (or (assq 'left geo) (assq 'top geo))
- '((user-position . t)))
- (if (or (assq 'height geo) (assq 'width geo))
- '((user-size . t)))
- geo)
- x-invocation-args (cdr x-invocation-args))))
-
-;; Handle the -name and -rn options. Set the variable x-resource-name
-;; to the option's operand; if the switch was `-name', set the name of
-;; the initial frame, too.
-(defun x-handle-name-rn-switch (switch)
- (or (consp x-invocation-args)
- (error "%s: missing argument to `%s' option" (invocation-name) switch))
- (setq x-resource-name (car x-invocation-args)
- x-invocation-args (cdr x-invocation-args))
- (if (string= switch "-name")
- (setq initial-frame-alist (cons (cons 'name x-resource-name)
- initial-frame-alist))))
-
-(defvar x-display-name nil
- "The display name specifying server and frame.")
-
-(defun x-handle-display (switch)
- (setq x-display-name (car x-invocation-args)
- x-invocation-args (cdr x-invocation-args)))
-
-(defvar x-invocation-args nil)
-
-(defun x-handle-args (args)
- "Process the X-related command line options in ARGS.
-This is done before the user's startup file is loaded. 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).
-This returns ARGS with the arguments that have been processed removed."
- (message "%s" args)
- (setq x-invocation-args args
- args nil)
- (while x-invocation-args
- (let* ((this-switch (car x-invocation-args))
- (orig-this-switch this-switch)
- completion argval aelt)
- (setq x-invocation-args (cdr x-invocation-args))
- ;; Check for long options with attached arguments
- ;; and separate out the attached option argument into argval.
- (if (string-match "^--[^=]*=" this-switch)
- (setq argval (substring this-switch (match-end 0))
- this-switch (substring this-switch 0 (1- (match-end 0)))))
- (setq completion (try-completion this-switch x-long-option-alist))
- (if (eq completion t)
- ;; Exact match for long option.
- (setq this-switch (cdr (assoc this-switch x-long-option-alist)))
- (if (stringp completion)
- (let ((elt (assoc completion x-long-option-alist)))
- ;; Check for abbreviated long option.
- (or elt
- (error "Option `%s' is ambiguous" this-switch))
- (setq this-switch (cdr elt)))
- ;; Check for a short option.
- (setq argval nil this-switch orig-this-switch)))
- (setq aelt (assoc this-switch x-option-alist))
- (if aelt
- (if argval
- (let ((x-invocation-args
- (cons argval x-invocation-args)))
- (funcall (cdr aelt) this-switch))
- (funcall (cdr aelt) this-switch))
- (setq args (cons this-switch args)))))
- (setq args (nreverse args)))
-
-
-
-;;
-;; 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"
- "green"
- "Green"
- "dark green"
- "DarkGreen"
- "dark olive green"
- "DarkOliveGreen"
- "forest green"
- "ForestGreen"
- "lime green"
- "LimeGreen"
- "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 (&optional frame)
- "Return a list of colors supported for a particular frame.
-The argument FRAME specifies which frame to try.
-The value may be different for frames on different X displays."
- (or frame (setq frame (selected-frame)))
- (let* ((color-map-colors (mapcar (lambda (clr) (car clr)) w32-color-map))
- (all-colors (or color-map-colors x-colors))
- (this-color nil)
- (defined-colors nil))
- (message "Defining colors...")
- (while all-colors
- (setq this-color (car all-colors)
- all-colors (cdr all-colors))
- (and (face-color-supported-p frame this-color t)
- (setq defined-colors (cons this-color defined-colors))))
- defined-colors))
-
-;;;; Function keys
-
-(defun iconify-or-deiconify-frame ()
- "Iconify the selected frame, or deiconify if it's currently an icon."
- (interactive)
- (if (eq (cdr (assq 'visibility (frame-parameters))) t)
- (iconify-frame)
- (make-frame-visible)))
-
-(substitute-key-definition 'suspend-emacs 'iconify-or-deiconify-frame
- global-map)
-
-;; Map certain keypad keys into ASCII characters
-;; that people usually expect.
-(define-key function-key-map [tab] [?\t])
-(define-key function-key-map [linefeed] [?\n])
-(define-key function-key-map [clear] [11])
-(define-key function-key-map [return] [13])
-(define-key function-key-map [escape] [?\e])
-(define-key function-key-map [M-tab] [?\M-\t])
-(define-key function-key-map [M-linefeed] [?\M-\n])
-(define-key function-key-map [M-clear] [?\M-\013])
-(define-key function-key-map [M-return] [?\M-\015])
-(define-key function-key-map [M-escape] [?\M-\e])
-
-;; These don't do the right thing (voelker)
-;(define-key function-key-map [backspace] [127])
-;(define-key function-key-map [delete] [127])
-;(define-key function-key-map [M-backspace] [?\M-\d])
-;(define-key function-key-map [M-delete] [?\M-\d])
-
-;; These tell read-char how to convert
-;; these special chars to ASCII.
-(put 'tab 'ascii-character ?\t)
-(put 'linefeed 'ascii-character ?\n)
-(put 'clear 'ascii-character 12)
-(put 'return 'ascii-character 13)
-(put 'escape 'ascii-character ?\e)
-;; These don't seem to be necessary (voelker)
-;(put 'backspace 'ascii-character 127)
-;(put 'delete 'ascii-character 127)
-
-
-;;;; Selections and cut buffers
-
-;;; We keep track of the last text selected here, so we can check the
-;;; current selection against it, and avoid passing back our own text
-;;; from x-cut-buffer-or-selection-value.
-(defvar x-last-selected-text nil)
-
-;;; It is said that overlarge strings are slow to put into the cut buffer.
-;;; Note this value is overridden below.
-(defvar x-cut-buffer-max 20000
- "Max number of characters to put in the cut buffer.")
-
-(defvar x-select-enable-clipboard t
- "Non-nil means cutting and pasting uses the clipboard.
-This is in addition to the primary selection.")
-
-(defun x-select-text (text &optional push)
- (if x-select-enable-clipboard
- (w32-set-clipboard-data text))
- (setq x-last-selected-text text))
-
-;;; Return the value of the current selection.
-;;; Consult the selection, then the cut buffer. Treat empty strings
-;;; as if they were unset.
-(defun x-get-selection-value ()
- (if x-select-enable-clipboard
- (let (text)
- ;; Don't die if x-get-selection signals an error.
- (condition-case c
- (setq text (w32-get-clipboard-data))
- (error (message "w32-get-clipboard-data:%s" c)))
- (if (string= text "") (setq text nil))
- (cond
- ((not text) nil)
- ((eq text x-last-selected-text) nil)
- ((string= text x-last-selected-text)
- ;; Record the newer string, so subsequent calls can use the 'eq' test.
- (setq x-last-selected-text text)
- nil)
- (t
- (setq x-last-selected-text text))))))
-
-;;; Do the actual Windows setup here; the above code just defines
-;;; functions and variables that we use now.
-
-(setq command-line-args (x-handle-args command-line-args))
-
-;;; Make sure we have a valid resource name.
-(or (stringp x-resource-name)
- (let (i)
- (setq x-resource-name (invocation-name))
-
- ;; Change any . or * characters in x-resource-name to hyphens,
- ;; so as not to choke when we use it in X resource queries.
- (while (setq i (string-match "[.*]" x-resource-name))
- (aset x-resource-name i ?-))))
-
-;; For the benefit of older Emacses (19.27 and earlier) that are sharing
-;; the same lisp directory, don't pass the third argument unless we seem
-;; to have the multi-display support.
-(if (fboundp 'x-close-connection)
- (x-open-connection ""
- x-command-line-resources
- ;; Exit Emacs with fatal error if this fails.
- t)
- (x-open-connection ""
- x-command-line-resources))
-
-(setq frame-creation-function 'x-create-frame-with-faces)
-
-(setq x-cut-buffer-max (min (- (/ (x-server-max-request-size) 2) 100)
- x-cut-buffer-max))
-
-;; W32 expects the menu bar cut and paste commands to use the clipboard.
-;; This has ,? to match both on Sunos and on Solaris.
-(menu-bar-enable-clipboard)
-
-;; Apply a geometry resource to the initial frame. Put it at the end
-;; of the alist, so that anything specified on the command line takes
-;; precedence.
-(let* ((res-geometry (x-get-resource "geometry" "Geometry"))
- parsed)
- (if res-geometry
- (progn
- (setq parsed (x-parse-geometry res-geometry))
- ;; If the resource specifies a position,
- ;; call the position and size "user-specified".
- (if (or (assq 'top parsed) (assq 'left parsed))
- (setq parsed (cons '(user-position . t)
- (cons '(user-size . t) parsed))))
- ;; All geometry parms apply to the initial frame.
- (setq initial-frame-alist (append initial-frame-alist parsed))
- ;; The size parms apply to all frames.
- (if (assq 'height parsed)
- (setq default-frame-alist
- (cons (cons 'height (cdr (assq 'height parsed)))
- default-frame-alist)))
- (if (assq 'width parsed)
- (setq default-frame-alist
- (cons (cons 'width (cdr (assq 'width parsed)))
- default-frame-alist))))))
-
-;; Check the reverseVideo resource.
-(let ((case-fold-search t))
- (let ((rv (x-get-resource "reverseVideo" "ReverseVideo")))
- (if (and rv
- (string-match "^\\(true\\|yes\\|on\\)$" rv))
- (setq default-frame-alist
- (cons '(reverse . t) default-frame-alist)))))
-
-;; Set x-selection-timeout, measured in milliseconds.
-(let ((res-selection-timeout
- (x-get-resource "selectionTimeout" "SelectionTimeout")))
- (setq x-selection-timeout 20000)
- (if res-selection-timeout
- (setq x-selection-timeout (string-to-number res-selection-timeout))))
-
-(defun x-win-suspend-error ()
- (error "Suspending an emacs running under Win32 makes no sense"))
-(add-hook 'suspend-hook 'x-win-suspend-error)
-
-;;; Arrange for the kill and yank functions to set and check the clipboard.
-(setq interprogram-cut-function 'x-select-text)
-(setq interprogram-paste-function 'x-get-selection-value)
-
-;;; Turn off window-splitting optimization; w32 is usually fast enough
-;;; that this is only annoying.
-(setq split-window-keep-point t)
-
-;; Don't show the frame name; that's redundant.
-(setq-default mode-line-buffer-identification '("Emacs: %12b"))
-
-;;; Set to a system sound if you want a fancy bell.
-(set-message-beep 'ok)
-
-;; Remap some functions to call w32 common dialogs
-
-(defun internal-face-interactive (what &optional bool)
- (let* ((fn (intern (concat "face-" what)))
- (prompt (concat "Set " what " of face"))
- (face (read-face-name (concat prompt ": ")))
- (default (if (fboundp fn)
- (or (funcall fn face (selected-frame))
- (funcall fn 'default (selected-frame)))))
- (fn-win (intern (concat (symbol-name window-system) "-select-" what)))
- (value
- (if (fboundp fn-win)
- (funcall fn-win)
- (if bool
- (y-or-n-p (concat "Should face " (symbol-name face)
- " be " bool "? "))
- (read-string (concat prompt " " (symbol-name face) " to: ")
- default)))))
- (list face (if (equal value "") nil value))))
-
-;; Redefine the font selection to use the standard Win32 dialog
-
-(defun mouse-set-font (&rest fonts)
- (interactive)
- (set-default-font (w32-select-font)))
-
-;;; win32-win.el ends here
diff --git a/lisp/term/wyse50.el b/lisp/term/wyse50.el
deleted file mode 100644
index 3cb1307bb89..00000000000
--- a/lisp/term/wyse50.el
+++ /dev/null
@@ -1,151 +0,0 @@
-;;; wyse50.el --- terminal support code for Wyse 50
-
-;; Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Daniel Pfieffer <pfieffer@cix.cict.fr> January 1991
-;; Jim Blandy <jimb@occs.cs.oberlin.edu>
-;; Keywords: terminals
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Uses the Emacs 19 terminal initialization features --- won't work with 18.
-;; Rewritten for Emacs 19 by jimb, January 1992
-;; Cleaned up for new terminal package conventions by esr, March 1993
-;; Should work well for Televideo TVI 925 although it's overkill.
-;;
-;; The Wyse50 is ergonomically wonderful, but its escape-sequence design sucks
-;; rocks. The left-arrow key emits a backspace (!) and the down-arrow a line
-;; feed (!!). Thus, you have to unbind some commonly-used Emacs keys to
-;; enable the arrows.
-
-;;; Code:
-
-(define-key function-key-map "\C-a" (make-keymap))
-(mapcar (function (lambda (key-definition)
- (define-key function-key-map
- (car key-definition) (nth 1 key-definition))))
- '(
- ;; These might be set up by termcap and terminfo
- ("\C-k" [up])
- ("\C-j" [down])
- ("\C-l" [right])
- ("\C-h" [left])
- ("\^a@\^m" [f1])
- ("\^aA\^m" [f2])
- ("\^aB\^m" [f3])
- ("\^aC\^m" [f4])
- ("\^aD\^m" [f5])
- ("\^aE\^m" [f6])
- ("\^aF\^m" [f7])
- ("\^aG\^m" [f8])
- ("\^aH\^m" [f9])
-
- ;; These might be set up by terminfo
- ("\eK" [next])
- ("\eT" [clearline])
- ("\^^" [home])
- ("\e\^^" [end])
- ("\eQ" [insert])
- ("\eE" [insertline])
- ("\eR" [deleteline])
- ("\eP" [print])
- ("\er" [replace])
- ("\^aI\^m" [f10])
- ("\^aJ\^m" [f11])
- ("\^aK\^m" [f12])
- ("\^aL\^m" [f13])
- ("\^aM\^m" [f14])
- ("\^aN\^m" [f15])
- ("\^aO\^m" [f16])
- ("\^a`\^m" [f17])
- ("\^aa\^m" [f18])
- ("\^ab\^m" [f19])
- ("\^ac\^m" [f20])
- ("\^ad\^m" [f21])
- ("\^ae\^m" [f22])
- ("\^af\^m" [f23])
- ("\^ag\^m" [f24])
- ("\^ah\^m" [f25])
- ("\^ai\^m" [f26])
- ("\^aj\^m" [f27])
- ("\^ak\^m" [f28])
- ("\^al\^m" [f29])
- ("\^am\^m" [f30])
- ("\^an\^m" [f31])
- ("\^ao\^m" [f32])
-
- ;; Terminfo may know about these, but X won't
- ("\eI" [key-stab]) ;; Not an X keysym
- ("\eJ" [key-snext]) ;; Not an X keysym
- ("\eY" [key-clear]) ;; Not an X keysym
-
- ;; These are totally strange :-)
- ("\eW" [?\C-?]) ;; Not an X keysym
- ("\^a\^k\^m" [funct-up]) ;; Not an X keysym
- ("\^a\^j\^m" [funct-down]) ;; Not an X keysym
- ("\^a\^l\^m" [funct-right]) ;; Not an X keysym
- ("\^a\^h\^m" [funct-left]) ;; Not an X keysym
- ("\^a\^m\^m" [funct-return]) ;; Not an X keysym
- ("\^a\^i\^m" [funct-tab]) ;; Not an X keysym
-))
-
-(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-h M-?
-LFD Funct Return, some modes override down-arrow via LFD
-C-k CLR Line
-C-l Scrn CLR
-M-r M-x move-to-window-line, Funct up-arrow or down-arrow are similar
-"
- (interactive)
- (mapcar (function (lambda (key-definition)
- (global-set-key (car key-definition)
- (nth 1 key-definition))))
- ;; By unsetting C-a and then binding it to a prefix, we
- ;; allow the rest of the function keys which start with C-a
- ;; to be recognized.
- '(("\C-a" nil)
- ("\C-k" nil)
- ("\C-j" nil)
- ("\C-l" nil)
- ("\C-h" nil)
- ("\er" nil)))
- (fset 'enable-arrow-keys nil))
-
-
-;;; Miscellaneous hacks
-
-;;; 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!
-(add-hook 'kill-emacs-hook
- (function (lambda () (interactive)
- (send-string-to-terminal
- (concat "\ea23R" (1+ (frame-width)) "C\eG0")))))
-
-;;; wyse50.el ends here
diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el
deleted file mode 100644
index 12a1ec48163..00000000000
--- a/lisp/term/x-win.el
+++ /dev/null
@@ -1,711 +0,0 @@
-;;; x-win.el --- parse switches controlling interface with X window system
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: FSF
-;; Keywords: terminals
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; 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).
-
-;;; Code:
-
-;; 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
-;; -i .iconType
-;; -itype .iconType
-;; -iconic .iconic
-;; -name .name
-;; -reverse *reverseVideo
-;; -rv *reverseVideo
-;; -selectionTimeout .selectionTimeout
-;; -synchronous *synchronous
-;; -xrm
-
-;; An alist of X options and the function which handles them. See
-;; ../startup.el.
-
-(if (not (eq window-system 'x))
- (error "%s: Loading x-win.el but not compiled for X" (invocation-name)))
-
-(require 'frame)
-(require 'mouse)
-(require 'scroll-bar)
-(require 'faces)
-(require 'select)
-(require 'menu-bar)
-
-(defvar x-invocation-args)
-
-(defvar x-command-line-resources nil)
-
-;; Handler for switches of the form "-switch value" or "-switch".
-(defun x-handle-switch (switch)
- (let ((aelt (assoc switch command-line-x-option-alist)))
- (if aelt
- (let ((param (nth 3 aelt))
- (value (nth 4 aelt)))
- (if value
- (setq default-frame-alist
- (cons (cons param value)
- default-frame-alist))
- (setq default-frame-alist
- (cons (cons param
- (car x-invocation-args))
- default-frame-alist)
- 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 command-line-x-option-alist)))
- (if aelt
- (let ((param (nth 3 aelt)))
- (setq default-frame-alist
- (cons (cons param
- (string-to-int (car x-invocation-args)))
- default-frame-alist)
- x-invocation-args
- (cdr x-invocation-args))))))
-
-;; Make -iconic apply only to the initial frame!
-(defun x-handle-iconic (switch)
- (setq initial-frame-alist
- (cons '(visibility . icon) initial-frame-alist)))
-
-;; Handle the -xrm option.
-(defun x-handle-xrm-switch (switch)
- (or (consp x-invocation-args)
- (error "%s: missing argument to `%s' option" (invocation-name) switch))
- (setq x-command-line-resources (car x-invocation-args))
- (setq x-invocation-args (cdr x-invocation-args)))
-
-;; Handle the geometry option
-(defun x-handle-geometry (switch)
- (let ((geo (x-parse-geometry (car x-invocation-args))))
- (setq initial-frame-alist
- (append initial-frame-alist
- (if (or (assq 'left geo) (assq 'top geo))
- '((user-position . t)))
- (if (or (assq 'height geo) (assq 'width geo))
- '((user-size . t)))
- geo)
- x-invocation-args (cdr x-invocation-args))))
-
-;; Handle the -name option. Set the variable x-resource-name
-;; to the option's operand; set the name of
-;; the initial frame, too.
-(defun x-handle-name-switch (switch)
- (or (consp x-invocation-args)
- (error "%s: missing argument to `%s' option" (invocation-name) switch))
- (setq x-resource-name (car x-invocation-args)
- x-invocation-args (cdr x-invocation-args))
- (setq initial-frame-alist (cons (cons 'name x-resource-name)
- initial-frame-alist)))
-
-(defvar x-display-name nil
- "The X display name specifying server and X frame.")
-
-(defun x-handle-display (switch)
- (setq x-display-name (car x-invocation-args)
- x-invocation-args (cdr x-invocation-args))
- ;; Make subshell programs see the same DISPLAY value Emacs really uses.
- ;; Note that this isn't completely correct, since Emacs can use
- ;; multiple displays. However, there is no way to tell an already
- ;; running subshell which display the user is currently typing on.
- (setenv "DISPLAY" x-display-name))
-
-(defun x-handle-args (args)
- "Process the X-related command line options in ARGS.
-This is done before the user's startup file is loaded. 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).
-This function returns ARGS minus the arguments that have been processed."
- ;; We use ARGS to accumulate the args that we don't handle here, to return.
- (setq x-invocation-args args
- args nil)
- (while (and x-invocation-args
- (not (equal (car x-invocation-args) "--")))
- (let* ((this-switch (car x-invocation-args))
- (orig-this-switch this-switch)
- completion argval aelt handler)
- (setq x-invocation-args (cdr x-invocation-args))
- ;; Check for long options with attached arguments
- ;; and separate out the attached option argument into argval.
- (if (string-match "^--[^=]*=" this-switch)
- (setq argval (substring this-switch (match-end 0))
- this-switch (substring this-switch 0 (1- (match-end 0)))))
- ;; Complete names of long options.
- (if (string-match "^--" this-switch)
- (progn
- (setq completion (try-completion this-switch command-line-x-option-alist))
- (if (eq completion t)
- ;; Exact match for long option.
- nil
- (if (stringp completion)
- (let ((elt (assoc completion command-line-x-option-alist)))
- ;; Check for abbreviated long option.
- (or elt
- (error "Option `%s' is ambiguous" this-switch))
- (setq this-switch completion))))))
- (setq aelt (assoc this-switch command-line-x-option-alist))
- (if aelt (setq handler (nth 2 aelt)))
- (if handler
- (if argval
- (let ((x-invocation-args
- (cons argval x-invocation-args)))
- (funcall handler this-switch))
- (funcall handler this-switch))
- (setq args (cons orig-this-switch args)))))
- (nconc (nreverse args) x-invocation-args))
-
-;;
-;; 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"
- "green"
- "Green"
- "dark green"
- "DarkGreen"
- "dark olive green"
- "DarkOliveGreen"
- "forest green"
- "ForestGreen"
- "lime green"
- "LimeGreen"
- "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 list of X colors from the `rgb.txt' file.")
-
-(defun x-defined-colors (&optional frame)
- "Return a list of colors supported for a particular frame.
-The argument FRAME specifies which frame to try.
-The value may be different for frames on different X displays."
- (or frame (setq frame (selected-frame)))
- (let ((all-colors x-colors)
- (this-color nil)
- (defined-colors nil))
- (while all-colors
- (setq this-color (car all-colors)
- all-colors (cdr all-colors))
- (and (face-color-supported-p frame this-color t)
- (setq defined-colors (cons this-color defined-colors))))
- defined-colors))
-
-;;;; Function keys
-
-(defun iconify-or-deiconify-frame ()
- "Iconify the selected frame, or deiconify if it's currently an icon."
- (interactive)
- (if (eq (cdr (assq 'visibility (frame-parameters))) t)
- (iconify-frame)
- (make-frame-visible)))
-
-(substitute-key-definition 'suspend-emacs 'iconify-or-deiconify-frame
- global-map)
-
-;; Map certain keypad keys into ASCII characters
-;; that people usually expect.
-(define-key function-key-map [backspace] [127])
-(define-key function-key-map [delete] [127])
-(define-key function-key-map [tab] [?\t])
-(define-key function-key-map [linefeed] [?\n])
-(define-key function-key-map [clear] [?\C-l])
-(define-key function-key-map [return] [?\C-m])
-(define-key function-key-map [escape] [?\e])
-(define-key function-key-map [M-backspace] [?\M-\d])
-(define-key function-key-map [M-delete] [?\M-\d])
-(define-key function-key-map [M-tab] [?\M-\t])
-(define-key function-key-map [M-linefeed] [?\M-\n])
-(define-key function-key-map [M-clear] [?\M-\C-l])
-(define-key function-key-map [M-return] [?\M-\C-m])
-(define-key function-key-map [M-escape] [?\M-\e])
-
-;; These tell read-char how to convert
-;; these special chars to ASCII.
-(put 'backspace 'ascii-character 127)
-(put 'delete 'ascii-character 127)
-(put 'tab 'ascii-character ?\t)
-(put 'linefeed 'ascii-character ?\n)
-(put 'clear 'ascii-character 12)
-(put 'return 'ascii-character 13)
-(put 'escape 'ascii-character ?\e)
-
-(defun vendor-specific-keysyms (vendor)
- "Return the appropriate value of system-key-alist for VENDOR.
-VENDOR is a string containing the name of the X Server's vendor,
-as returned by (x-server-vendor)."
- (cond ((string-equal vendor "Apollo Computer Inc.")
- '((65280 . linedel)
- (65281 . chardel)
- (65282 . copy)
- (65283 . cut)
- (65284 . paste)
- (65285 . move)
- (65286 . grow)
- (65287 . cmd)
- (65288 . shell)
- (65289 . leftbar)
- (65290 . rightbar)
- (65291 . leftbox)
- (65292 . rightbox)
- (65293 . upbox)
- (65294 . downbox)
- (65295 . pop)
- (65296 . read)
- (65297 . edit)
- (65298 . save)
- (65299 . exit)
- (65300 . repeat)))
- ((or (string-equal vendor "Hewlett-Packard Incorporated")
- (string-equal vendor "Hewlett-Packard Company"))
- '(( 168 . mute-acute)
- ( 169 . mute-grave)
- ( 170 . mute-asciicircum)
- ( 171 . mute-diaeresis)
- ( 172 . mute-asciitilde)
- ( 175 . lira)
- ( 190 . guilder)
- ( 252 . block)
- ( 256 . longminus)
- (65388 . reset)
- (65389 . system)
- (65390 . user)
- (65391 . clearline)
- (65392 . insertline)
- (65393 . deleteline)
- (65394 . insertchar)
- (65395 . deletechar)
- (65396 . backtab)
- (65397 . kp-backtab)))
- ((or (string-equal vendor "X11/NeWS - Sun Microsystems Inc.")
- (string-equal vendor "X Consortium"))
- '((392976 . f36)
- (392977 . f37)
- (393056 . req)
- ;; These are for Sun under X11R6
- (393072 . props)
- (393073 . front)
- (393074 . copy)
- (393075 . open)
- (393076 . paste)
- (393077 . cut)))
- (t
- ;; This is used by DEC's X server.
- '((65280 . remove)))))
-
-
-;;;; Selections and cut buffers
-
-;;; We keep track of the last text selected here, so we can check the
-;;; current selection against it, and avoid passing back our own text
-;;; from x-cut-buffer-or-selection-value.
-(defvar x-last-selected-text nil)
-
-;;; It is said that overlarge strings are slow to put into the cut buffer.
-;;; Note this value is overridden below.
-(defvar x-cut-buffer-max 20000
- "Max number of characters to put in the cut buffer.")
-
-(defvar x-select-enable-clipboard nil
- "Non-nil means cutting and pasting uses the clipboard.
-This is in addition to the primary selection.")
-
-;;; Make TEXT, a string, the primary X selection.
-;;; Also, set the value of X cut buffer 0, for backward compatibility
-;;; with older X applications.
-;;; gildea@lcs.mit.edu says it's not desirable to put kills
-;;; in the clipboard.
-(defun x-select-text (text &optional push)
- ;; Don't send the cut buffer too much text.
- ;; It becomes slow, and if really big it causes errors.
- (if (< (length text) x-cut-buffer-max)
- (x-set-cut-buffer text push)
- (x-set-cut-buffer "" push))
- (x-set-selection 'PRIMARY text)
- (if x-select-enable-clipboard
- (x-set-selection 'CLIPBOARD text))
- (setq x-last-selected-text text))
-
-;;; Return the value of the current X selection.
-;;; Consult the selection, then the cut buffer. Treat empty strings
-;;; as if they were unset.
-(defun x-cut-buffer-or-selection-value ()
- (let (text)
-
- ;; Don't die if x-get-selection signals an error.
- (condition-case c
- (setq text (x-get-selection 'PRIMARY))
- (error nil))
- (if (string= text "") (setq text nil))
-
- (if x-select-enable-clipboard
- (condition-case c
- (setq text (x-get-selection 'CLIPBOARD))
- (error nil)))
- (if (string= text "") (setq text nil))
- (or text (setq text (x-get-cut-buffer 0)))
- (if (string= text "") (setq text nil))
-
- (cond
- ((not text) nil)
- ((eq text x-last-selected-text) nil)
- ((string= text x-last-selected-text)
- ;; Record the newer string, so subsequent calls can use the `eq' test.
- (setq x-last-selected-text text)
- nil)
- (t
- (setq x-last-selected-text text)))))
-
-
-;;; Do the actual X Windows setup here; the above code just defines
-;;; functions and variables that we use now.
-
-(setq command-line-args (x-handle-args command-line-args))
-
-;;; Make sure we have a valid resource name.
-(or (stringp x-resource-name)
- (let (i)
- (setq x-resource-name (invocation-name))
-
- ;; Change any . or * characters in x-resource-name to hyphens,
- ;; so as not to choke when we use it in X resource queries.
- (while (setq i (string-match "[.*]" x-resource-name))
- (aset x-resource-name i ?-))))
-
-;; For the benefit of older Emacses (19.27 and earlier) that are sharing
-;; the same lisp directory, don't pass the third argument unless we seem
-;; to have the multi-display support.
-(if (fboundp 'x-close-connection)
- (x-open-connection (or x-display-name
- (setq x-display-name (getenv "DISPLAY")))
- x-command-line-resources
- ;; Exit Emacs with fatal error if this fails.
- t)
- (x-open-connection (or x-display-name
- (setq x-display-name (getenv "DISPLAY")))
- x-command-line-resources))
-
-(setq frame-creation-function 'x-create-frame-with-faces)
-
-(setq x-cut-buffer-max (min (- (/ (x-server-max-request-size) 2) 100)
- x-cut-buffer-max))
-
-;; Sun expects the menu bar cut and paste commands to use the clipboard.
-;; This has ,? to match both on Sunos and on Solaris.
-(if (string-match "Sun Microsystems,? Inc\\."
- (x-server-vendor))
- (menu-bar-enable-clipboard))
-
-;; Apply a geometry resource to the initial frame. Put it at the end
-;; of the alist, so that anything specified on the command line takes
-;; precedence.
-(let* ((res-geometry (x-get-resource "geometry" "Geometry"))
- parsed)
- (if res-geometry
- (progn
- (setq parsed (x-parse-geometry res-geometry))
- ;; If the resource specifies a position,
- ;; call the position and size "user-specified".
- (if (or (assq 'top parsed) (assq 'left parsed))
- (setq parsed (cons '(user-position . t)
- (cons '(user-size . t) parsed))))
- ;; All geometry parms apply to the initial frame.
- (setq initial-frame-alist (append initial-frame-alist parsed))
- ;; The size parms apply to all frames.
- (if (assq 'height parsed)
- (setq default-frame-alist
- (cons (cons 'height (cdr (assq 'height parsed)))
- default-frame-alist)))
- (if (assq 'width parsed)
- (setq default-frame-alist
- (cons (cons 'width (cdr (assq 'width parsed)))
- default-frame-alist))))))
-
-;; Check the reverseVideo resource.
-(let ((case-fold-search t))
- (let ((rv (x-get-resource "reverseVideo" "ReverseVideo")))
- (if (and rv
- (string-match "^\\(true\\|yes\\|on\\)$" rv))
- (setq default-frame-alist
- (cons '(reverse . t) default-frame-alist)))))
-
-;; Set x-selection-timeout, measured in milliseconds.
-(let ((res-selection-timeout
- (x-get-resource "selectionTimeout" "SelectionTimeout")))
- (setq x-selection-timeout 20000)
- (if res-selection-timeout
- (setq x-selection-timeout (string-to-number res-selection-timeout))))
-
-(defun x-win-suspend-error ()
- (error "Suspending an emacs running under X makes no sense"))
-(add-hook 'suspend-hook 'x-win-suspend-error)
-
-;;; Arrange for the kill and yank functions to set and check the clipboard.
-(setq interprogram-cut-function 'x-select-text)
-(setq interprogram-paste-function 'x-cut-buffer-or-selection-value)
-
-;;; Turn off window-splitting optimization; X is usually fast enough
-;;; that this is only annoying.
-(setq split-window-keep-point t)
-
-;; Don't show the frame name; that's redundant with X.
-(setq-default mode-line-buffer-identification '("Emacs: %12b"))
-
-;;; Motif direct handling of f10 wasn't working right,
-;;; So temporarily we've turned it off in lwlib-Xm.c
-;;; and turned the Emacs f10 back on.
-;;; ;; Motif normally handles f10 itself, so don't try to handle it a second time.
-;;; (if (featurep 'motif)
-;;; (global-set-key [f10] 'ignore))
-
-;;; x-win.el ends here
diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el
deleted file mode 100644
index 05b5b7ba0fd..00000000000
--- a/lisp/term/xterm.el
+++ /dev/null
@@ -1,47 +0,0 @@
-;;; xterm.el --- define function key sequences for xterm
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; Author: FSF
-;; Keywords: terminals
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;;; Code:
-
-(define-key function-key-map "\e[A" [up])
-(define-key function-key-map "\e[B" [down])
-(define-key function-key-map "\e[C" [right])
-(define-key function-key-map "\e[D" [left])
-(define-key function-key-map "\e[2~" [insert])
-(define-key function-key-map "\e[4~" [select])
-(define-key function-key-map "\e[5~" [prior])
-(define-key function-key-map "\e[6~" [next])
-(define-key function-key-map "\e[11~" [f1])
-(define-key function-key-map "\e[12~" [f2])
-(define-key function-key-map "\e[13~" [f3])
-(define-key function-key-map "\e[14~" [f4])
-(define-key function-key-map "\e[15~" [f5])
-(define-key function-key-map "\e[17~" [f6])
-(define-key function-key-map "\e[18~" [f7])
-(define-key function-key-map "\e[19~" [f8])
-(define-key function-key-map "\e[20~" [f9])
-(define-key function-key-map "\e[21~" [f10])
-(define-key function-key-map "\e[23~" [f11])
-(define-key function-key-map "\e[24~" [f12])
-(define-key function-key-map "\e[29~" [print])
diff --git a/lisp/terminal.el b/lisp/terminal.el
deleted file mode 100644
index 8f8da8a14f6..00000000000
--- a/lisp/terminal.el
+++ /dev/null
@@ -1,1320 +0,0 @@
-;;; terminal.el --- terminal emulator for GNU Emacs.
-
-;; Copyright (C) 1986,87,88,89,93,94 Free Software Foundation, Inc.
-
-;; Author: Richard Mlynarik <mly@eddie.mit.edu>
-;; Maintainer: FSF
-;; Keywords: comm, terminals
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; This file has been censored by the Communications Decency Act.
-;;; That law was passed under the guise of a ban on pornography, but
-;;; it bans far more than that. This file did not contain pornography,
-;;; but it was censored nonetheless.
-
-;;; For information on US government censorship of the Internet, and
-;;; what you can do to bring back freedom of the press, see the web
-;;; site http://www.vtw.org/
-
-;;; Code:
-
-;;>>TODO
-;;>> ** Nothing can be done about emacs' meta-lossage **
-;;>> (without redoing keymaps `sanely' -- ask Mly for details)
-
-;;>> One probably wants to do setenv MORE -c when running with
-;;>> more-processing enabled.
-
-(require 'ehelp)
-
-(defvar terminal-escape-char ?\C-^
- "*All characters except for this are passed verbatim through the
-terminal-emulator. This character acts as a prefix for commands
-to the emulator program itself. Type this character twice to send
-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
-of the screen.
-This variable is local to each terminal-emulator buffer.")
-
-(defvar terminal-more-processing t
- "*If non-nil, do more-processing.
-This variable is local to each terminal-emulator buffer.")
-
-;; If you are the sort of loser who uses scrolling without more breaks
-;; and expects to actually see anything, you should probably set this to
-;; around 400
-(defvar terminal-redisplay-interval 5000
- "*Maximum number of characters which will be processed by the
-terminal-emulator before a screen redisplay is forced.
-Set this to a large value for greater throughput,
-set it smaller for more frequent updates but overall slower
-performance.")
-
-(defvar terminal-more-break-insertion
- "*** More break -- Press space to continue ***")
-
-(defvar terminal-meta-map nil)
-(if terminal-meta-map
- nil
- (let ((map (make-sparse-keymap)))
- (define-key map [t] 'te-pass-through)
- (setq terminal-meta-map map)))
-
-(defvar terminal-map nil)
-(if terminal-map
- nil
- (let ((map (make-sparse-keymap)))
- (define-key map [t] 'te-pass-through)
- (define-key map [switch-frame] 'handle-switch-frame)
- (define-key map "\e" terminal-meta-map)
- ;(define-key map "\C-l"
- ; '(lambda () (interactive) (te-pass-through) (redraw-display)))
- (setq terminal-map map)))
-
-(defvar terminal-escape-map nil)
-(if terminal-escape-map
- nil
- (let ((map (make-sparse-keymap)))
- (define-key map [t] 'undefined)
- (let ((s "0"))
- (while (<= (aref s 0) ?9)
- (define-key map s 'digit-argument)
- (aset s 0 (1+ (aref s 0)))))
- (define-key map "b" 'switch-to-buffer)
- (define-key map "o" 'other-window)
- (define-key map "e" 'te-set-escape-char)
- (define-key map "\C-l" 'redraw-display)
- (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)))
-
-(defvar te-escape-command-alist nil)
-(if te-escape-command-alist
- 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)
- ("Tofu" . te-tofu) ;; confuse the uninitiated
- ("Stuff Input" . te-stuff-string)
- ("Flush Pending Output" . te-flush-pending-output)
- ("Enable More Processing" . te-enable-more-processing)
- ("Disable More Processing" . te-disable-more-processing)
- ("Scroll at end of page" . te-do-scrolling)
- ("Wrap at end of page" . te-do-wrapping)
- ("Switch To Buffer" . switch-to-buffer)
- ("Other Window" . other-window)
- ("Kill Buffer" . kill-buffer)
- ("Help" . te-escape-help)
- ("Set Redisplay Interval" . te-set-redisplay-interval)
- )))
-
-(defvar terminal-more-break-map nil)
-(if terminal-more-break-map
- nil
- (let ((map (make-sparse-keymap)))
- (define-key map [t] 'te-more-break-unread)
- (define-key map (char-to-string help-char) 'te-more-break-help)
- (define-key map " " 'te-more-break-resume)
- (define-key map "\C-l" 'redraw-display)
- (define-key map "\C-o" 'te-more-break-flush-pending-output)
- ;;>>> this isn't right
- ;(define-key map "\^?" 'te-more-break-flush-pending-output) ;DEL
- (define-key map "\r" 'te-more-break-advance-one-line)
-
- (setq terminal-more-break-map map)))
-
-
-;;; Pacify the byte compiler
-(defvar te-process nil)
-(defvar te-log-buffer nil)
-(defvar te-height nil)
-(defvar te-width nil)
-(defvar te-more-count nil)
-(defvar te-redisplay-count nil)
-(defvar te-pending-output nil)
-(defvar te-saved-point)
-(defvar te-more-old-point nil)
-(defvar te-more-old-local-map nil)
-(defvar te-more-old-filter nil)
-(defvar te-more-old-mode-line-format nil)
-(defvar te-pending-output-info nil)
-
-;; Required to support terminfo systems
-(defconst te-terminal-name-prefix "emacs-em"
- "Prefix used for terminal type names for Terminfo.")
-(defconst te-terminfo-directory "/tmp/emacs-terminfo/"
- "Directory used for run-time terminal definition files for Terminfo.")
-(defvar te-terminal-name nil)
-
-;;;; escape map
-
-(defun te-escape ()
- (interactive)
- (let (s
- (local (current-local-map))
- (global (current-global-map)))
- (unwind-protect
- (progn
- (use-global-map terminal-escape-map)
- (use-local-map terminal-escape-map)
- (setq s (read-key-sequence
- (if current-prefix-arg
- (format "Emacs Terminal escape> %d "
- (prefix-numeric-value current-prefix-arg))
- "Emacs Terminal escape> "))))
- (use-global-map global)
- (use-local-map local))
-
- (message "")
-
- (cond
- ;; Certain keys give vector notation, like [escape] when
- ;; you hit esc key...
- ((and (stringp s)
- (string= s (make-string 1 terminal-escape-char)))
- (setq last-command-char terminal-escape-char)
- (let ((terminal-escape-char -259))
- (te-pass-through)))
-
- ((setq s (lookup-key terminal-escape-map s))
- (call-interactively s)))
-
- ))
-
-
-(defun te-escape-help ()
- "Provide help on commands available after terminal-escape-char is typed."
- (interactive)
- (message "Terminal emulator escape help...")
- (let ((char (single-key-description terminal-escape-char)))
- (with-electric-help
- (function (lambda ()
- (princ (format "Terminal-emulator escape, invoked by \"%s\"
-Type \"%s\" twice to send a single \"%s\" through.
-
-Other chars following \"%s\" are interpreted as follows:\n"
- char char char char))
-
- (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 t)
- 'te-escape-extended-command))
- (let ((l (if (fboundp 'sortcar)
- (sortcar (copy-sequence te-escape-command-alist)
- 'string<)
- (sort (copy-sequence te-escape-command-alist)
- (function (lambda (a b)
- (string< (car a) (car b))))))))
- (while l
- (let ((doc (or (documentation (cdr (car l)))
- "Not documented")))
- (if (string-match "\n" doc)
- ;; just use first line of documentation
- (setq doc (substring doc 0 (match-beginning 0))))
- (princ " \"")
- (princ (car (car l)))
- (princ "\":\n ")
- (princ doc)
- (write-char ?\n))
- (setq l (cdr l))))
- nil)))))
-
-
-
-(defun te-escape-extended-command ()
- (interactive)
- (let ((c (let ((completion-ignore-case t))
- (completing-read "terminal command: "
- te-escape-command-alist
- nil t))))
- (if c
- (catch 'foo
- (setq c (downcase c))
- (let ((l te-escape-command-alist))
- (while l
- (if (string= c (downcase (car (car l))))
- (throw 'foo (call-interactively (cdr (car l))))
- (setq l (cdr l)))))))))
-
-;; not used.
-(defun te-escape-extended-command-unread ()
- (interactive)
- (setq unread-command-events (listify-key-sequence (this-command-keys)))
- (te-escape-extended-command))
-
-(defun te-set-escape-char (c)
- "Change the terminal-emulator escape character."
- (interactive "cSet escape character to: ")
- (let ((o terminal-escape-char))
- (message (if (= o c)
- "\"%s\" is the escape char"
- "\"%s\" is now the escape; \"%s\" passes through")
- (single-key-description c)
- (single-key-description o))
- (setq terminal-escape-char c)))
-
-
-(defun te-stuff-string (string)
- "Read a string to send to through the terminal emulator
-as though that string had been typed on the keyboard.
-
-Very poor man's file transfer protocol."
- (interactive "sStuff string: ")
- (process-send-string te-process string))
-
-(defun te-set-output-log (name)
- "Record output from the terminal emulator in a buffer."
- (interactive (list (if te-log-buffer
- nil
- (read-buffer "Record output in buffer: "
- (format "%s output-log"
- (buffer-name (current-buffer)))
- nil))))
- (if (or (null name) (equal name ""))
- (progn (setq te-log-buffer nil)
- (message "Output logging off."))
- (if (get-buffer name)
- nil
- (save-excursion
- (set-buffer (get-buffer-create name))
- (fundamental-mode)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)))
- (setq te-log-buffer (get-buffer name))
- (message "Recording terminal emulator output into buffer \"%s\""
- (buffer-name te-log-buffer))))
-
-(defun te-tofu ()
- "Discontinue output log."
- (interactive)
- (te-set-output-log nil))
-
-
-(defun te-toggle (sym arg)
- (set sym (cond ((not (numberp arg)) arg)
- ((= arg 1) (not (symbol-value sym)))
- ((< arg 0) nil)
- (t t))))
-
-(defun te-toggle-more-processing (arg)
- (interactive "p")
- (message (if (te-toggle 'terminal-more-processing arg)
- "More processing on" "More processing off"))
- (if terminal-more-processing (setq te-more-count -1)))
-
-(defun te-toggle-scrolling (arg)
- (interactive "p")
- (message (if (te-toggle 'terminal-scrolling arg)
- "Scroll at end of page" "Wrap at end of page")))
-
-(defun te-enable-more-processing ()
- "Enable ** MORE ** processing"
- (interactive)
- (te-toggle-more-processing t))
-
-(defun te-disable-more-processing ()
- "Disable ** MORE ** processing"
- (interactive)
- (te-toggle-more-processing nil))
-
-(defun te-do-scrolling ()
- "Scroll at end of page (yuck)"
- (interactive)
- (te-toggle-scrolling t))
-
-(defun te-do-wrapping ()
- "Wrap to top of window at end of page"
- (interactive)
- (te-toggle-scrolling nil))
-
-
-(defun te-set-redisplay-interval (arg)
- "Set the maximum interval (in output characters) between screen updates.
-Set this number to large value for greater throughput,
-set it smaller for more frequent updates (but overall slower performance."
- (interactive "NMax number of output chars between redisplay updates: ")
- (setq arg (max arg 1))
- (setq terminal-redisplay-interval arg
- te-redisplay-count 0))
-
-;;;; more map
-
-;; every command -must- call te-more-break-unwind
-;; or grave lossage will result
-
-(put 'te-more-break-unread 'suppress-keymap t)
-(defun te-more-break-unread ()
- (interactive)
- (if (eq last-input-char terminal-escape-char)
- (call-interactively 'te-escape)
- (message "Continuing from more break (\"%s\" typed, %d chars output pending...)"
- (single-key-description last-input-char)
- (te-pending-output-length))
- (setq te-more-count 259259)
- (te-more-break-unwind)
- (let ((terminal-more-processing nil))
- (te-pass-through))))
-
-(defun te-more-break-resume ()
- "Proceed past the **MORE** break,
-allowing the next page of output to appear"
- (interactive)
- (message "Continuing from more break")
- (te-more-break-unwind))
-
-(defun te-more-break-help ()
- "Provide help on commands available in a terminal-emulator **MORE** break"
- (interactive)
- (message "Terminal-emulator more break help...")
- (sit-for 0)
- (with-electric-help
- (function (lambda ()
- (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 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
-running under the terminal emulator and disables more processing until
-all pending output has been dealt with.")
- nil))))
-
-
-(defun te-more-break-advance-one-line ()
- "Allow one more line of text to be output before doing another more break."
- (interactive)
- (setq te-more-count 1)
- (te-more-break-unwind))
-
-(defun te-more-break-flush-pending-output ()
- "Discard any output which has been received by the terminal emulator but
-not yet processed and then proceed from the more break."
- (interactive)
- (te-more-break-unwind)
- (te-flush-pending-output))
-
-(defun te-flush-pending-output ()
- "Discard any as-yet-unprocessed output which has been received by
-the terminal emulator."
- (interactive)
- ;; this could conceivably be confusing in the presence of
- ;; escape-sequences spanning process-output chunks
- (if (null (cdr te-pending-output))
- (message "(There is no output pending)")
- (let ((length (te-pending-output-length)))
- (message "Flushing %d chars of pending output" length)
- (setq te-pending-output
- (list 0 (format "\n*** %d chars of pending output flushed ***\n"
- length)))
- (te-update-pending-output-display)
- (te-process-output nil)
- (sit-for 0))))
-
-
-(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."
- (interactive)
- (cond ((eq last-input-char terminal-escape-char)
- (call-interactively 'te-escape))
- (t
- ;; Convert `return' to C-m, etc.
- (if (and (symbolp last-input-char)
- (get last-input-char 'ascii-character))
- (setq last-input-char (get last-input-char 'ascii-character)))
- ;; Convert meta characters to 8-bit form for transmission.
- (if (and (integerp last-input-char)
- (not (zerop (logand last-input-char ?\M-\^@))))
- (setq last-input-char (+ 128 (logand last-input-char 127))))
- ;; Now ignore all but actual characters.
- ;; (It ought to be possible to send through function
- ;; keys as character sequences if we add a description
- ;; to our termcap entry of what they should look like.)
- (if (integerp last-input-char)
- (progn
- (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))
- (message "Function key `%s' ignored"
- (single-key-description last-input-char))))))
-
-
-(defun te-set-window-start ()
- (let* ((w (get-buffer-window (current-buffer)))
- (h (if w (window-height w))))
- (cond ((not w)) ; buffer not displayed
- ((>= h (/ (- (point) (point-min)) (1+ te-width)))
- ;; this is the normal case
- (set-window-start w (point-min)))
- ;; this happens if some vandal shrinks our window.
- ((>= h (/ (- (point-max) (point)) (1+ te-width)))
- (set-window-start w (- (point-max) (* h (1+ te-width)) -1)))
- ;; I give up.
- (t nil))))
-
-(defun te-pending-output-length ()
- (let ((length (car te-pending-output))
- (tem (cdr te-pending-output)))
- (while tem
- (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-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)
- (force-mode-line-update)
- ;; 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 "%s"
- (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))
- (use-local-map terminal-map)
- (setq major-mode 'terminal-mode)
- (setq mode-name "terminal")
- (setq mode-line-process '(":%s")))
-
-;;;; more break hair
-
-(defun te-more-break ()
- (te-set-more-count t)
- (make-local-variable 'te-more-old-point)
- (setq te-more-old-point (point))
- (make-local-variable 'te-more-old-local-map)
- (setq te-more-old-local-map (current-local-map))
- (use-local-map terminal-more-break-map)
- (make-local-variable 'te-more-old-filter)
- (setq te-more-old-filter (process-filter te-process))
- (make-local-variable 'te-more-old-mode-line-format)
- (setq te-more-old-mode-line-format mode-line-format
- mode-line-format (list "-- **MORE** "
- mode-line-buffer-identification
- "%-"))
- (set-process-filter te-process
- (function (lambda (process string)
- (save-excursion
- (set-buffer (process-buffer process))
- (setq te-pending-output (nconc te-pending-output
- (list string))))
- (te-update-pending-output-display))))
- (te-update-pending-output-display)
- (if (eq (window-buffer (selected-window)) (current-buffer))
- (message "More break "))
- (or (eobp)
- (null terminal-more-break-insertion)
- (save-excursion
- (forward-char 1)
- (delete-region (point) (+ (point) te-width))
- (insert terminal-more-break-insertion)))
- (run-hooks 'terminal-more-break-hook)
- (sit-for 0) ;get display to update
- (throw 'te-process-output t))
-
-(defun te-more-break-unwind ()
- (use-local-map te-more-old-local-map)
- (set-process-filter te-process te-more-old-filter)
- (goto-char te-more-old-point)
- (setq mode-line-format te-more-old-mode-line-format)
- (force-mode-line-update)
- (let ((buffer-read-only nil))
- (cond ((eobp))
- (terminal-more-break-insertion
- (forward-char 1)
- (delete-region (point)
- (+ (point) (length terminal-more-break-insertion)))
- (insert-char ?\ te-width)
- (goto-char te-more-old-point)))
- (setq te-more-old-point nil)
- (let ((te-more-count 259259))
- (te-newline)))
- ;(sit-for 0)
- (te-process-output t))
-
-(defun te-set-more-count (newline)
- (let ((line (/ (- (point) (point-min)) (1+ te-width))))
- (if newline (setq line (1+ line)))
- (cond ((= line te-height)
- (setq te-more-count te-height))
- ;>>>> something is strange. Investigate this!
- ((= line (1- te-height))
- (setq te-more-count te-height))
- ((or (< line (/ te-height 2))
- (> (- te-height line) 10))
- ;; break at end of this page
- (setq te-more-count (- te-height line)))
- (t
- ;; migrate back towards top (ie bottom) of screen.
- (setq te-more-count (- te-height
- (if (> te-height 10) 2 1)))))))
-
-
-;;;; More or less straight-forward terminal escapes
-
-;; ^j, meaning `newline' to non-display programs.
-;; (Who would think of ever writing a system which doesn't understand
-;; display terminals natively? Un*x: The Operating System of the Future.)
-(defun te-newline ()
- "Move down a line, optionally do more processing, perhaps wrap/scroll,
-move to start of new line, clear to end of line."
- (end-of-line)
- (cond ((not terminal-more-processing))
- ((< (setq te-more-count (1- te-more-count)) 0)
- (te-set-more-count t))
- ((eql te-more-count 0)
- ;; this doesn't return
- (te-more-break)))
- (if (eobp)
- (progn
- (delete-region (point-min) (+ (point-min) te-width))
- (goto-char (point-min))
- (if terminal-scrolling
- (progn (delete-char 1)
- (goto-char (point-max))
- (insert ?\n))))
- (forward-char 1)
- (delete-region (point) (+ (point) te-width)))
- (insert-char ?\ te-width)
- (beginning-of-line)
- (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
- (let ((y (- (te-get-char) 32))
- (x (- (te-get-char) 32)))
- (if (or (> x te-width)
- (> y te-height))
- ()
- (goto-char (+ (point-min) x (* y (1+ te-width))))
- ;(te-set-window-start?)
- ))
- (setq te-more-count -1))
-
-
-
-;; ^p c
-(defun te-clear-rest-of-line ()
- (save-excursion
- (let ((n (- (point) (progn (end-of-line) (point)))))
- (delete-region (point) (+ (point) n))
- (insert-char ?\ (- n)))))
-
-
-;; ^p C
-(defun te-clear-rest-of-screen ()
- (save-excursion
- (te-clear-rest-of-line)
- (while (progn (end-of-line) (not (eobp)))
- (forward-char 1) (end-of-line)
- (delete-region (- (point) te-width) (point))
- (insert-char ?\ te-width))))
-
-
-;; ^p ^l
-(defun te-clear-screen ()
- ;; regenerate buffer to compensate for (nonexistent!!) bugs.
- (erase-buffer)
- (let ((i 0))
- (while (< i te-height)
- (setq i (1+ i))
- (insert-char ?\ te-width)
- (insert ?\n)))
- (delete-region (1- (point-max)) (point-max))
- (goto-char (point-min))
- (setq te-more-count -1))
-
-
-;; ^p ^o count+32
-(defun te-insert-lines ()
- (if (not (bolp))
- ();(error "fooI")
- (save-excursion
- (let* ((line (- te-height (/ (- (point) (point-min)) (1+ te-width)) -1))
- (n (min (- (te-get-char) ?\ ) line))
- (i 0))
- (delete-region (- (point-max) (* n (1+ te-width))) (point-max))
- (if (eql (point) (point-max)) (insert ?\n))
- (while (< i n)
- (setq i (1+ i))
- (insert-char ?\ te-width)
- (or (eql i line) (insert ?\n))))))
- (setq te-more-count -1))
-
-
-;; ^p ^k count+32
-(defun te-delete-lines ()
- (if (not (bolp))
- ();(error "fooD")
- (let* ((line (- te-height (/ (- (point) (point-min)) (1+ te-width)) -1))
- (n (min (- (te-get-char) ?\ ) line))
- (i 0))
- (delete-region (point)
- (min (+ (point) (* n (1+ te-width))) (point-max)))
- (save-excursion
- (goto-char (point-max))
- (while (< i n)
- (setq i (1+ i))
- (insert-char ?\ te-width)
- (or (eql i line) (insert ?\n))))))
- (setq te-more-count -1))
-
-;; ^p ^a
-(defun te-beginning-of-line ()
- (beginning-of-line))
-
-;; ^p ^b
-(defun te-backward-char ()
- (if (not (bolp))
- (backward-char 1)))
-
-;; ^p ^f
-(defun te-forward-char ()
- (if (not (eolp))
- (forward-char 1)))
-
-
-;; 0177
-(defun te-delete ()
- (if (bolp)
- ()
- (delete-region (1- (point)) (point))
- (insert ?\ )
- (forward-char -1)))
-
-;; ^p ^g
-(defun te-beep ()
- (beep))
-
-
-;; ^p _ count+32
-(defun te-insert-spaces ()
- (let* ((p (point))
- (n (min (- (te-get-char) 32)
- (- (progn (end-of-line) (point)) p))))
- (if (<= n 0)
- nil
- (delete-char (- n))
- (goto-char p)
- (insert-char ?\ n))
- (goto-char p)))
-
-;; ^p d count+32 (should be ^p ^d but cretinous un*x won't send ^d chars!!!)
-(defun te-delete-char ()
- (let* ((p (point))
- (n (min (- (te-get-char) 32)
- (- (progn (end-of-line) (point)) p))))
- (if (<= n 0)
- nil
- (insert-char ?\ n)
- (goto-char p)
- (delete-char n))
- (goto-char p)))
-
-
-
-;; disgusting unix-required excrement
-;; Are we living twenty years in the past yet?
-
-(defun te-losing-unix ()
- nil)
-
-;; ^i
-(defun te-output-tab ()
- (let* ((p (point))
- (x (- p (progn (beginning-of-line) (point))))
- (l (min (- 8 (logand x 7))
- (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)
-;; ^h => te-backward-char (for which it should use ^p ^b)
-
-
-
-(defun te-filter (process string)
- (let* ((obuf (current-buffer)))
- ;; can't use save-excursion, as that preserves point, which we don't want
- (unwind-protect
- (progn
- (set-buffer (process-buffer process))
- (goto-char te-saved-point)
- (and (bufferp te-log-buffer)
- (if (null (buffer-name te-log-buffer))
- ;; killed
- (setq te-log-buffer nil)
- (set-buffer te-log-buffer)
- (goto-char (point-max))
- (insert-before-markers string)
- (set-buffer (process-buffer process))))
- (setq te-pending-output (nconc te-pending-output (list string)))
- (te-update-pending-output-display)
- (te-process-output (eq (current-buffer)
- (window-buffer (selected-window))))
- (set-buffer (process-buffer process))
- (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...
-(defun te-process-output (preemptible)
- ;;>> There seems no good reason to ever disallow preemption
- (setq preemptible t)
- (catch 'te-process-output
- (let ((buffer-read-only nil)
- (string nil) ostring start char (matchpos nil))
- (while (cdr te-pending-output)
- (setq ostring string
- start (car te-pending-output)
- string (car (cdr te-pending-output))
- char (aref string start))
- (if (eql (setq start (1+ start)) (length string))
- (progn (setq te-pending-output
- (cons 0 (cdr (cdr te-pending-output)))
- start 0
- string (car (cdr te-pending-output)))
- (te-update-pending-output-display))
- (setcar te-pending-output start))
- (if (and (> char ?\037) (< char ?\377))
- (cond ((eolp)
- ;; unread char
- (if (eql start 0)
- (setq te-pending-output
- (cons 0 (cons (make-string 1 char)
- (cdr te-pending-output))))
- (setcar te-pending-output (1- start)))
- (te-newline))
- ((null string)
- (delete-char 1) (insert char)
- (te-redisplay-if-necessary 1))
- (t
- (let ((end (or (and (eq ostring string) matchpos)
- (setq matchpos (string-match
- "[\000-\037\177-\377]"
- string start))
- (length string))))
- (delete-char 1) (insert char)
- (setq char (point)) (end-of-line)
- (setq end (min end (+ start (- (point) char))))
- (goto-char char)
- (if (eql end matchpos) (setq matchpos nil))
- (delete-region (point) (+ (point) (- end start)))
- (insert (if (and (eql start 0)
- (eql end (length string)))
- string
- (substring string start end)))
- (if (eql end (length string))
- (setq te-pending-output
- (cons 0 (cdr (cdr te-pending-output))))
- (setcar te-pending-output end))
- (te-redisplay-if-necessary (1+ (- end start))))))
- ;; I suppose if I split the guts of this out into a separate
- ;; function we could trivially emulate different terminals
- ;; Who cares in any case? (Apart from stupid losers using rlogin)
- (funcall
- (if (eql char ?\^p)
- (or (cdr (assq (te-get-char)
- '((?= . te-move-to-position)
- (?c . te-clear-rest-of-line)
- (?C . te-clear-rest-of-screen)
- (?\C-o . te-insert-lines)
- (?\C-k . te-delete-lines)
- ;; not necessary, but help sometimes.
- (?\C-a . te-beginning-of-line)
- (?\C-b . te-backward-char)
- ;; should be C-d, but un*x
- ;; pty's won't send \004 through!
- ;; Can you believe this?
- (?d . te-delete-char)
- (?_ . te-insert-spaces)
- ;; random
- (?\C-f . te-forward-char)
- (?\C-g . te-beep)
- (?\C-j . te-down-vertically-or-scroll)
- (?\C-l . te-clear-screen)
- )))
- 'te-losing-unix)
- (or (cdr (assq char
- '((?\C-j . te-newline)
- (?\177 . te-delete)
- ;; Did I ask to be sent these characters?
- ;; 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)))
- (te-redisplay-if-necessary 1))
- (and preemptible
- (input-pending-p)
- ;; preemptible output! Oh my!!
- (throw 'te-process-output t)))))
- ;; We must update window-point in every window displaying our buffer
- (let* ((s (selected-window))
- (w s))
- (while (not (eq s (setq w (next-window w))))
- (if (eq (window-buffer w) (current-buffer))
- (set-window-point w (point))))))
-
-(defun te-get-char ()
- (if (cdr te-pending-output)
- (let ((start (car te-pending-output))
- (string (car (cdr te-pending-output))))
- (prog1 (aref string start)
- (if (eql (setq start (1+ start)) (length string))
- (setq te-pending-output (cons 0 (cdr (cdr te-pending-output))))
- (setcar te-pending-output start))))
- (catch 'char
- (let ((filter (process-filter te-process)))
- (unwind-protect
- (progn
- (set-process-filter te-process
- (function (lambda (p s)
- (or (eql (length s) 1)
- (setq te-pending-output (list 1 s)))
- (throw 'char (aref s 0)))))
- (accept-process-output te-process))
- (set-process-filter te-process filter))))))
-
-
-(defun te-redisplay-if-necessary (length)
- (and (<= (setq te-redisplay-count (- te-redisplay-count length)) 0)
- (eq (current-buffer) (window-buffer (selected-window)))
- (waiting-for-user-input-p)
- (progn (te-update-pending-output-display)
- (sit-for 0)
- (setq te-redisplay-count terminal-redisplay-interval))))
-
-(defun te-update-pending-output-display ()
- (if (null (cdr te-pending-output))
- (setq te-pending-output-info "")
- (let ((length (te-pending-output-length)))
- (if (< length 1500)
- (setq te-pending-output-info "")
- (setq te-pending-output-info (format "(%dK chars output pending) "
- (/ (+ length 512) 1024))))))
- (force-mode-line-update))
-
-
-(defun te-sentinel (process message)
- (cond ((eq (process-status process) 'run))
- ((null (buffer-name (process-buffer process)))) ;deleted
- (t (let ((b (current-buffer)))
- (save-excursion
- (set-buffer (process-buffer process))
- (setq buffer-read-only nil)
- (fundamental-mode)
- (goto-char (point-max))
- (delete-blank-lines)
- (delete-horizontal-space)
- (insert "\n*******\n" message "*******\n"))
- (if (and (eq b (process-buffer process))
- (waiting-for-user-input-p))
- (progn (goto-char (point-max))
- (recenter -1)))))))
-
-(defvar te-stty-string "stty -nl erase '^?' kill '^u' intr '^c' echo pass8"
- "Shell command to set terminal modes for terminal emulator.")
-;; This used to have `new' in it, but that loses outside BSD
-;; and it's apparently not needed in BSD.
-
-(defvar explicit-shell-file-name nil
- "*If non-nil, is file name to use for explicitly requested inferior shell.")
-
-;;;###autoload
-(defun terminal-emulator (buffer program args &optional width height)
- "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."
- (interactive
- (cons (save-excursion
- (set-buffer (get-buffer-create "*terminal*"))
- (buffer-name (if (or (not (boundp 'te-process))
- (null te-process)
- (not (eq (process-status te-process)
- 'run)))
- (current-buffer)
- (generate-new-buffer "*terminal*"))))
- (append
- (let* ((default-s
- ;; Default shell is same thing M-x shell uses.
- (or explicit-shell-file-name
- (getenv "ESHELL")
- (getenv "SHELL")
- "/bin/sh"))
- (s (read-string
- (format "Run program in emulator: (default %s) "
- default-s))))
- (if (equal s "")
- (list default-s '())
- (te-parse-program-and-args s))))))
- (switch-to-buffer buffer)
- (if (null width) (setq width (- (window-width (selected-window)) 1)))
- (if (null height) (setq height (- (window-height (selected-window)) 1)))
- (terminal-mode)
- (setq te-width width te-height height)
- (setq te-terminal-name (concat te-terminal-name-prefix te-width
- te-height))
- (setq mode-line-buffer-identification
- (list (format "Emacs terminal %dx%d: %%b " te-width te-height)
- 'te-pending-output-info))
- (let ((buffer-read-only nil))
- (te-clear-screen))
- (let (process)
- (while (setq process (get-buffer-process (current-buffer)))
- (if (y-or-n-p (format "Kill process %s? " (process-name process)))
- (delete-process process)
- (error "Process %s not killed" (process-name process)))))
- (condition-case err
- (let ((process-environment
- (cons (concat "TERM=" te-terminal-name)
- (cons (concat "TERMCAP=" (te-create-termcap))
- (cons (concat "TERMINFO=" (te-create-terminfo))
- process-environment)))))
- (setq te-process
- (start-process "terminal-emulator" (current-buffer)
- "/bin/sh" "-c"
- ;; Yuck!!! Start a shell to set some terminal
- ;; control characteristics. Then start the
- ;; "env" program to setup the terminal type
- ;; Then finally start the program we wanted.
- (format "%s; exec %s"
- te-stty-string
- (mapconcat 'te-quote-arg-for-sh
- (cons program args) " "))))
- (set-process-filter te-process 'te-filter)
- (set-process-sentinel te-process 'te-sentinel))
- (error (fundamental-mode)
- (signal (car err) (cdr err))))
- (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 t)
- " ")))
-
-
-(defun te-parse-program-and-args (s)
- (cond ((string-match "\\`\\([-a-zA-Z0-9+=_.@/:]+[ \t]*\\)+\\'" s)
- (let ((l ()) (p 0))
- (while p
- (setq l (cons (if (string-match
- "\\([-a-zA-Z0-9+=_.@/:]+\\)\\([ \t]+\\)*"
- s p)
- (prog1 (substring s p (match-end 1))
- (setq p (match-end 0))
- (if (eql p (length s)) (setq p nil)))
- (prog1 (substring s p)
- (setq p nil)))
- l)))
- (setq l (nreverse l))
- (list (car l) (cdr l))))
- ((and (string-match "[ \t]" s) (not (file-exists-p s)))
- (list shell-file-name (list "-c" (concat "exec " s))))
- (t (list s ()))))
-
-(put 'terminal-mode 'mode-class 'special)
-;; This is only separated out from function terminal-emulator
-;; to keep the latter a little more manageable.
-(defun terminal-mode ()
- "Set up variables for use with the terminal-emulator.
-One should not call this -- it is an internal function
-of the terminal-emulator"
- (kill-all-local-variables)
- (buffer-disable-undo (current-buffer))
- (setq major-mode 'terminal-mode)
- (setq mode-name "terminal")
-; (make-local-variable 'Helper-return-blurb)
-; (setq Helper-return-blurb "return to terminal simulator")
- (setq mode-line-process '(":%s"))
- (setq buffer-read-only t)
- (setq truncate-lines t)
- (make-local-variable 'terminal-escape-char)
- (setq terminal-escape-char (default-value 'terminal-escape-char))
- (make-local-variable 'terminal-scrolling)
- (setq terminal-scrolling (default-value 'terminal-scrolling))
- (make-local-variable 'terminal-more-processing)
- (setq terminal-more-processing (default-value 'terminal-more-processing))
- (make-local-variable 'terminal-redisplay-interval)
- (setq terminal-redisplay-interval (default-value 'terminal-redisplay-interval))
- (make-local-variable 'te-width)
- (make-local-variable 'te-height)
- (make-local-variable 'te-process)
- (make-local-variable 'te-pending-output)
- (setq te-pending-output (list 0))
- (make-local-variable 'te-saved-point)
- (setq te-saved-point (point-min))
- (make-local-variable 'te-pending-output-info) ;for the mode line
- (setq te-pending-output-info "")
- (make-local-variable 'inhibit-quit)
- ;(setq inhibit-quit t)
- (make-local-variable 'te-log-buffer)
- (setq te-log-buffer nil)
- (make-local-variable 'te-more-count)
- (setq te-more-count -1)
- (make-local-variable 'te-redisplay-count)
- (setq te-redisplay-count terminal-redisplay-interval)
- ;(use-local-map terminal-mode-map)
- ;; terminal-mode-hook is called above in function terminal-emulator
- )
-
-;;;; what a complete loss
-
-(defun te-quote-arg-for-sh (string)
- (cond ((string-match "\\`[-a-zA-Z0-9+=_.@/:]+\\'"
- string)
- string)
- ((not (string-match "[$]" string))
- ;; "[\"\\]" are special to sh and the lisp reader in the same way
- (prin1-to-string string))
- (t
- (let ((harder "")
- (start 0)
- (end 0))
- (while (cond ((>= start (length string))
- nil)
- ;; this is the set of chars magic with "..." in `sh'
- ((setq end (string-match "[\"\\$]"
- string start))
- t)
- (t (setq harder (concat harder
- (substring string start)))
- nil))
- (setq harder (concat harder (substring string start end)
- ;; Can't use ?\\ since `concat'
- ;; unfortunately does prin1-to-string
- ;; on fixna. Amazing.
- "\\"
- (substring string
- end
- (1+ end)))
- start (1+ end)))
- (concat "\"" harder "\"")))))
-
-(defun te-create-terminfo ()
- "Create and compile a terminfo entry for the virtual terminal. This is kept
-in the directory specified by `te-terminfo-directory'."
- (if (and system-uses-terminfo
- (not (file-exists-p (concat te-terminfo-directory
- (substring te-terminal-name-prefix 0 1)
- "/" te-terminal-name))))
- (let ( (terminfo
- (concat
- ;; The first newline avoids trouble with ncurses.
- (format "%s,\n\tmir, xon,cols#%d, lines#%d,"
- te-terminal-name te-width te-height)
- "bel=^P^G, clear=^P\\f, cr=^P^A, cub1=^P^B, cud1=^P\\n,"
- "cuf1=^P^F, cup=^P=%p1%'\\s'%+%c%p2%'\\s'%+%c,"
- "dch=^Pd%p1%'\\s'%+%c, dch1=^Pd!, dl=^P^K%p1%'\\s'%+%c,"
- "dl1=^P^K!, ed=^PC, el=^Pc, home=^P=\\s\\s,"
- "ich=^P_%p1%'\\s'%+%c, ich1=^P_!, il=^P^O%p1%'\\s'%+%c,"
- "il1=^P^O!, ind=^P\\n, nel=\\n,\n"))
- ;; The last newline avoids trouble with ncurses.
- (file-name (concat te-terminfo-directory te-terminal-name ".tif")) )
- (make-directory te-terminfo-directory t)
- (save-excursion
- (set-buffer (create-file-buffer file-name))
- (insert terminfo)
- (write-file file-name)
- (kill-buffer nil)
- )
- (let ( (process-environment
- (cons (concat "TERMINFO="
- (directory-file-name te-terminfo-directory))
- process-environment)) )
- (set-process-sentinel (start-process "tic" nil "tic" file-name)
- 'te-tic-sentinel))))
- (directory-file-name te-terminfo-directory)
-)
-
-(defun te-create-termcap ()
- "Create a termcap entry for the virtual terminal"
- ;; Because of Unix Brain Death(tm), we can't change
- ;; the terminal type of a running process, and so
- ;; terminal size and scrollability are wired-down
- ;; at this point. ("Detach? What's that?")
- (concat (format "%s:co#%d:li#%d:%s"
- ;; Sigh. These can't be dynamically changed.
- te-terminal-name te-width te-height (if terminal-scrolling
- "" "ns:"))
- ;;-- Basic things
- ;; cursor-motion, bol, forward/backward char
- "cm=^p=%+ %+ :cr=^p^a:le=^p^b:nd=^p^f:"
- ;; newline, clear eof/eof, audible bell
- "nw=^j:ce=^pc:cd=^pC:cl=^p^l:bl=^p^g:"
- ;; insert/delete char/line
- "IC=^p_%+ :DC=^pd%+ :AL=^p^o%+ :DL=^p^k%+ :"
- ;;-- Not-widely-known (ie nonstandard) flags, which mean
- ;; o writing in the last column of the last line
- ;; doesn't cause idiotic scrolling, and
- ;; o don't use idiotische c-s/c-q sogenannte
- ;; ``flow control'' auf keinen Fall.
- "LP:NF:"
- ;;-- For stupid or obsolete programs
- "ic=^p_!:dc=^pd!:al=^p^o!:dl=^p^k!:ho=^p= :"
- ;;-- For disgusting programs.
- ;; (VI? What losers need these, I wonder?)
- "im=:ei=:dm=:ed=:mi:do=^p^j:nl=^p^j:bs:")
-)
-
-(defun te-tic-sentinel (proc state-change)
- "If tic has finished, delete the .tif file"
- (if (equal state-change "finished
-")
- (delete-file (concat te-terminfo-directory te-terminal-name ".tif"))))
-
-(provide 'terminal)
-
-;;; terminal.el ends here
diff --git a/lisp/textmodes/=ispell4.el b/lisp/textmodes/=ispell4.el
deleted file mode 100644
index 1bca6748052..00000000000
--- a/lisp/textmodes/=ispell4.el
+++ /dev/null
@@ -1,1091 +0,0 @@
-;;; ispell4.el --- this is the GNU EMACS interface to GNU ISPELL version 4.
-
-;; Copyright (C) 1990, 1991, 1993 Free Software Foundation, Inc.
-
-;; Keywords: wp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides a graceful interface to ispell, the GNU
-;; spelling checker.
-
-;;; Code:
-
-(defvar ispell-have-new-look t
- "Non-nil means use the `-r' option when running `look'.")
-
-(defvar ispell-enable-tex-parser nil
- "Non-nil enables experimental TeX parser in Ispell for TeX-mode buffers.")
-
-(defvar ispell-process nil "The process running Ispell")
-(defvar ispell-next-message nil
- "An integer: where in `*ispell*' buffer to find next message from Ispell.")
-
-(defvar ispell-command "ispell"
- "Command for running Ispell.")
-(defvar ispell-command-options nil
- "*String (or list of strings) to pass to Ispell as command arguments.
-You can specify your private dictionary via the -p <filename> option.
-The -S option is always passed to Ispell as the last parameter,
-and need not be mentioned here.")
-
-(defvar ispell-look-command "look"
- "*Command for running look.")
-
-;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 reflecting 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)
-
-;; Non-nil means we have started showing an alternatives window.
-;; This is the window config from before then.
-(defvar ispell-window-configuration 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 in your private dictionary
-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*")
-
-;; Start an ispell subprocess; check the version; and display the greeting.
-
-(defun start-ispell ()
- (message "Starting ispell ...")
- (let ((buf (get-buffer "*ispell*")))
- (if buf
- (kill-buffer buf)))
- (condition-case err
- (setq ispell-process
- (apply 'start-process "ispell" "*ispell*" ispell-command
- (append (if (listp ispell-command-options)
- ispell-command-options
- (list ispell-command-options))
- '("-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 "%s" (car (cdr greeting))))
- (delete-region (point-min) last-char))))
-
-;; Make sure ispell is ready for a command.
-;; Leaves buffer set to *ispell*, point at '='.
-
-(defun ispell-sync (intr)
- (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)))
-
-;; Send a command to ispell. Choices are:
-;;
-;; WORD Check spelling of WORD. 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 dictionary
-;;
-;; :accept WORD don't complain about word any more this session
-;;
-;; :dump write out the current private dictionary, if necessary.
-;;
-;; :reload reread private dictionary (default: `~/ispell.words')
-;;
-;; :tex
-;; :troff
-;; :generic set type of parser to use when scanning whole files
-
-(defun ispell-cmd (&rest strings)
- (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))))
-
-;; Return the next message sent by the Ispell subprocess.
-
-(defun ispell-next-message ()
- (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 slitex-mode)))
-
-(defvar ispell-menu-map (make-sparse-keymap "Spell"))
-(defalias 'ispell-menu-map ispell-menu-map)
-
-(define-key ispell-menu-map [ispell-complete-word-interior-frag]
- '("Complete Interior Fragment" . ispell-complete-word-interior-frag))
-
-(define-key ispell-menu-map [ispell-complete-word]
- '("Complete Word" . ispell-complete-word))
-
-(define-key ispell-menu-map [reload-ispell]
- '("Reload Dictionary" . reload-ispell))
-
-(define-key ispell-menu-map [ispell-next]
- '("Continue Check" . ispell-next))
-
-(define-key ispell-menu-map [ispell-message]
- '("Check Message" . ispell-message))
-
-(define-key ispell-menu-map [ispell-word]
- '("Check Word" . ispell-word))
-
-(define-key ispell-menu-map [ispell-region]
- '("Check Region" . ispell-region))
-
-(define-key ispell-menu-map [ispell-buffer]
- '("Check Buffer" . ispell))
-
-;;;autoload
-(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 dictionary (by default,
- `$HOME/ispell.words').
-a Accept. Accept this word for the rest of this editing session,
- but don't put it in your private dictionary.
-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"))
- ;; Deactivate the mark, because we'll do it anyway if we change something,
- ;; and a region highlight while in the Ispell loop is distracting.
- (deactivate-mark)
- (save-excursion
- (set-buffer buf)
- (let ((filename buffer-file-name)
- (delete-temp nil))
- (unwind-protect
- (progn
- (cond ((or (null filename)
- (find-file-name-handler buffer-file-name nil))
- (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)
- (t
- (message "Ispell parsing done.")
- (ispell-next))))
-
-;;;autoload
-(defalias 'ispell-buffer 'ispell)
-
-(defun ispell-next ()
- "Resume command loop for most recent Ispell command.
-Return value is t unless exit is due to typing `q'."
- (interactive)
- (setq ispell-window-configuration nil)
- (prog1
- (unwind-protect
- (catch 'ispell-quit
- ;; There used to be a save-excursion here,
- ;; but that was annoying: it's better if point doesn't move
- ;; when you type q.
- (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)))
- t)
- (ispell-dehighlight)
- (if ispell-window-configuration
- (set-window-configuration ispell-window-configuration))
- (cond ((null ispell-bad-words)
- (error "Ispell has not yet been run"))
- ((markerp (car ispell-bad-words))
- (message "%s"
- (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)))
-
-;;;autoload
-(defun ispell-word (&optional resume)
- "Check the spelling of the word under the cursor.
-See the command `ispell' for more information.
-With a prefix argument, resume handling of the previous Ispell command."
- (interactive "P")
- (if resume
- (ispell-next)
- (condition-case err
- (unwind-protect
- (catch 'ispell-quit
- (save-window-excursion
- (ispell-point (point) "at point."))
- (ispell-dump))
- (ispell-dehighlight))
- (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)))))))
-
-;;;autoload (define-key esc-map "$" 'ispell-word)
-
-;;;autoload
-(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)
- ;; There used to be a save-excursion here,
- ;; but that was annoying: it's better if point doesn't move
- ;; when you type q.
- (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))
- ;; Do nothing if we don't find a word.
- (if (< start end)
- (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)
-;;; This just causes confusion. -- rms.
-;;; (goto-char start)
-;;; (sit-for 0)
- (message "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 frame, 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)
- (or ispell-window-configuration
- (setq ispell-window-configuration (current-window-configuration)))
- (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 "'")))
- (ispell-highlight start end)
- (while flag
- (ispell-show-choices word message first-line)
- (message "Ispell command: ")
- (undo-boundary)
- (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 'ispell-quit nil))
- ((= c (nth 3 (current-input-mode)))
- (keyboard-quit))
- ((= 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 ispell-look-command nil buf nil "-r" regex)
- (call-process ispell-look-command 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"))
-
-(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"))
-
-(defvar ispell-highlight t
- "*Non-nil means to highlight ispell words.")
-
-(defvar ispell-overlay nil)
-
-(defun ispell-dehighlight ()
- (and ispell-overlay
- (progn
- (delete-overlay ispell-overlay)
- (setq ispell-overlay nil))))
-
-(defun ispell-highlight (start end)
- (and ispell-highlight
- window-system
- (progn
- (or ispell-overlay
- (progn
- (setq ispell-overlay (make-overlay start end))
- (overlay-put ispell-overlay 'face
- (if (internal-find-face 'ispell)
- 'ispell 'region))))
- (move-overlay ispell-overlay start end (current-buffer)))))
-
-;;;; ispell-complete-word
-
-;;; Brief Description:
-;;; Complete word fragment at point using dictionary and replace with full
-;;; word. Expansion done in current buffer like lisp-complete-symbol.
-;;; Completion of interior word fragments possible with prefix argument.
-
-;;; Known Problem:
-;;; Does not use private dictionary because GNU `look' does not use it. It
-;;; would be nice if GNU `look' took standard input; this would allow gzip'ed
-;;; dictionaries to be used. GNU `look' also has a bug, see
-;;; `ispell-gnu-look-still-broken-p'.
-
-;;; Motivation:
-;;; The `l', "regular expression look up", keymap option of ispell-word
-;;; (ispell-do-look) can only be run after finding a misspelled word. So
-;;; ispell-do-look can not be used to look for words starting with `cat' to
-;;; find `catechetical' since `cat' is a correctly spelled word. Furthermore,
-;;; ispell-do-look does not return the entire list returned by `look'.
-;;;
-;;; ispell-complete-word allows you to get a completion list from the system
-;;; dictionary and expand a word fragment at the current position in a buffer.
-;;; These examples assume ispell-complete-word is bound to M-TAB as it is in
-;;; text-mode; the `Complete Word' and `Complete Interior Fragment' entries of
-;;; the "Spell" submenu under the "Edit" menu may also be used instead of
-;;; M-TAB and C-u M-TAB, respectively.
-;;;
-;;; EXAMPLE 1: The word `Saskatchewan' needs to be spelled. The user may
-;;; type `Sas' and hit M-TAB and a completion list will be built using the
-;;; shell command `look' and displayed in the *Completions* buffer:
-;;;
-;;; Possible completions are:
-;;; sash sashay
-;;; sashayed sashed
-;;; sashes sashimi
-;;; Saskatchewan Saskatoon
-;;; sass sassafras
-;;; sassier sassing
-;;; sasswood sassy
-;;;
-;;; By viewing this list the user will hopefully be motivated to insert the
-;;; letter `k' after the `sas'. When M-TAB is hit again the word `Saskat'
-;;; will be inserted in place of `sas' (note case) since this is a unique
-;;; substring completion. The narrowed completion list can be viewed with
-;;; another M-TAB
-;;;
-;;; Possible completions are:
-;;; Saskatchewan Saskatoon
-;;;
-;;; Inserting the letter `c' and hitting M-TAB will narrow the completion
-;;; possibilities to just `Saskatchewan' and this will be inserted in the
-;;; buffer. At any point the user may click the mouse on a completion to
-;;; select it.
-;;;
-;;; EXAMPLE 2: The user has typed `Sasaquane' and M-$ (ispell-word) gives no
-;;; "near-misses" in which case you back up to `Sas' and hit M-TAB and find
-;;; the correct word as above. The `Sas' will be replaced by `Saskatchewan'
-;;; and the remaining word fragment `aquane' can be deleted.
-;;;
-;;; EXAMPLE 3: If a version of `look' is used that supports regular
-;;; expressions, then `ispell-have-new-look' should be t (its default) and
-;;; interior word fragments may also be used for the search. The word
-;;; `pneumonia' needs to be spelled. The user can only remember the
-;;; interior fragment `mon' in which case `C-u M-TAB' on `mon' gives a list
-;;; of all words containing the interior word fragment `mon'. Typing `p'
-;;; and M-TAB will narrow this list to all the words starting with `p' and
-;;; containing `mon' from which `pneumonia' can be found as above.
-
-;;; The user-defined variables are:
-;;;
-;;; ispell-look-command
-;;; ispell-look-dictionary
-;;; ispell-gnu-look-still-broken-p
-
-;;; Algorithm (some similarity to lisp-complete-symbol):
-;;;
-;;; * call-process on command ispell-look-command (default: "look") to find
-;;; words in ispell-look-dictionary matching `string' (or `regexp' if
-;;; ispell-have-new-look is t). Parse output and store results in
-;;; ispell-lookup-completions-alist.
-;;;
-;;; * Build completion list using try-completion and `string'
-;;;
-;;; * Replace `string' in buffer with matched common substring completion.
-;;;
-;;; * Display completion list only if there is no matched common substring.
-;;;
-;;; * Rebuild ispell-lookup-completions-alist, on a next call, only when
-;;; beginning of word fragment has changed.
-;;;
-;;; * Interior fragments searches are performed similarly with the exception
-;;; that the entire fragment at point is initially removed from the buffer,
-;;; the STRING passed to try-completion and all-completions is just "" and
-;;; not the interior fragment; this allows all completions containing the
-;;; interior fragment to be shown. The location in the buffer is stored to
-;;; decide whether future completion narrowing of the current list should be
-;;; done or if a new list should be built. See interior fragment example
-;;; above.
-;;;
-;;; * Robust searches are done using a `look' with -r (regular expression)
-;;; switch if ispell-have-new-look is t.
-
-;;;; User-defined variables.
-
-(defvar ispell-look-dictionary nil
- "*If non-nil then spelling dictionary as string for `ispell-complete-word'.
-Overrides default dictionary file such as \"/usr/dict/words\" or GNU look's
-\"${prefix}/lib/ispell/ispell.words\"")
-
-(defvar ispell-gnu-look-still-broken-p nil
- "*t if GNU look -r can give different results with and without trailing `.*'.
-Example: `look -dfr \"^ya\" foo' returns nothing, while `look -dfr \"^ya.*\" foo'
-returns `yacc', where `foo' is a dictionary file containing the three lines
-
- y
- y's
- yacc
-
-Both commands should return `yacc'. If `ispell-complete-word' erroneously
-states that no completions exist for a string, then setting this variable to t
-will help find those completions.")
-
-;;;; Internal variables.
-
-;;; Possible completions for last word fragment.
-(defvar ispell-lookup-completions-alist nil)
-
-;;; Last word fragment processed by `ispell-complete-word'.
-(defvar ispell-lookup-last-word nil)
-
-;;; Buffer local variables.
-
-;;; Value of interior-frag in last call to `ispell-complete-word'.
-(defvar ispell-lookup-last-interior-p nil)
-(make-variable-buffer-local 'ispell-lookup-last-interior-p)
-(put 'ispell-lookup-last-interior-p 'permanent-local t)
-
-;;; Buffer position in last call to `ispell-complete-word'.
-(defvar ispell-lookup-last-bow nil)
-(make-variable-buffer-local 'ispell-lookup-last-bow)
-(put 'ispell-lookup-last-bow 'permanent-local t)
-
-;;;; Interactive functions.
-;;;autoload
-(defun ispell-complete-word (&optional interior-frag)
- "Complete word using letters at point to word beginning using `look'.
-With optional argument INTERIOR-FRAG, word fragment at point is assumed to be
-an interior word fragment in which case `ispell-have-new-look' should be t.
-See also `ispell-look-dictionary' and `ispell-gnu-look-still-broken-p'."
-
- (interactive "P")
-
- ;; `look' must support regexp expressions in order to perform an interior
- ;; fragment search.
- (if (and interior-frag (not ispell-have-new-look))
- (error (concat "Sorry, `ispell-have-new-look' is nil. "
- "You also will need GNU Ispell's `look'.")))
-
- (let* ((completion-ignore-case t)
-
- ;; Get location of beginning of word fragment.
- (bow (save-excursion (skip-chars-backward "a-zA-Z'") (point)))
-
- ;; Get the string to look up.
- (string (buffer-substring bow (point)))
-
- ;; Get regexp for which we search and, if necessary, an interior word
- ;; fragment.
- (regexp (if interior-frag
- (concat "^.*" string ".*")
- ;; If possible use fast binary search: no trailing `.*'.
- (concat "^" string
- (if ispell-gnu-look-still-broken-p ".*"))))
-
- ;; We want all completions for case of interior fragments so set
- ;; prefix to an empty string.
- (prefix (if interior-frag "" string))
-
- ;; Are we continuing from a previous interior fragment search?
- ;; Check last value of interior-word and if the point has moved.
- (continuing-an-interior-frag-p
- (and ispell-lookup-last-interior-p
- (equal ispell-lookup-last-bow bow)))
-
- ;; Are we starting a unique word fragment search? Always t for
- ;; interior word fragment search.
- (new-unique-string-p
- (or interior-frag (null ispell-lookup-last-word)
- (let ((case-fold-search t))
- ;; Can we locate last word fragment as a substring of current
- ;; word fragment? If the last word fragment is larger than
- ;; the current string then we will have to rebuild the list
- ;; later.
- (not (string-match
- (concat "^" ispell-lookup-last-word) string)))))
-
- completion)
-
- ;; Check for perfect completion already. That is, maybe the user has hit
- ;; M-x ispell-complete-word one too many times?
- (if (string-equal string "")
- (if (string-equal (concat ispell-lookup-last-word " ")
- (buffer-substring
- (save-excursion (forward-word -1) (point)) (point)))
- (error "Perfect match already")
- (error "No word fragment at point")))
-
- ;; Create list of words from system dictionary starting with `string' if
- ;; new string and not continuing from a previous interior fragment search.
- (if (and (not continuing-an-interior-frag-p) new-unique-string-p)
- (setq ispell-lookup-completions-alist
- (ispell-lookup-build-list string regexp)))
-
- ;; Check for a completion of `string' in the list and store `string' and
- ;; other variables for the next call.
- (setq completion (try-completion prefix ispell-lookup-completions-alist)
- ispell-lookup-last-word string
- ispell-lookup-last-interior-p interior-frag
- ispell-lookup-last-bow bow)
-
- ;; Test the completion status.
- (cond
-
- ;; * Guess is a perfect match.
- ((eq completion t)
- (insert " ")
- (message "Perfect match."))
-
- ;; * No possibilities.
- ((null completion)
- (message "Can't find completion for \"%s\"" string)
- (beep))
-
- ;; * Replace string fragment with matched common substring completion.
- ((and (not (string-equal completion ""))
- ;; Fold case so a completion list is built when `string' and common
- ;; substring differ only in case.
- (let ((case-fold-search t))
- (not (string-match (concat "^" completion "$") string))))
- (search-backward string bow)
- (replace-match completion nil t) ; FIXEDCASE doesn't work? or LITERAL?
- (message "Proposed unique substring. Repeat for completions list."))
-
- ;; * String is a common substring completion already. Make list.
- (t
- (message "Making completion list...")
- (if (string-equal completion "") (delete-region bow (point)))
- (let ((list (all-completions prefix ispell-lookup-completions-alist)))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list list)))
- (message "Making completion list...done")))))
-
-;;;autoload
-(defun ispell-complete-word-interior-frag ()
- "Runs `ispell-complete-word' with a non-nil INTERIOR-FRAG.
-A completion list is built for word fragment at point which is assumed to be
-an interior word fragment. `ispell-have-new-look' should be t."
- (interactive)
- (ispell-complete-word t))
-
-;;;; Internal Function.
-
-;;; Build list of words using ispell-look-command from dictionary
-;;; ispell-look-dictionary (if this is a non-nil string). Look for words
-;;; starting with STRING if ispell-have-new-look is nil or look for REGEXP if
-;;; ispell-have-new-look is t. Returns result as an alist suitable for use by
-;;; try-completion, all-completions, and completing-read.
-(defun ispell-lookup-build-list (string regexp)
- (save-excursion
- (message "Building list...")
- (set-buffer (get-buffer-create " *ispell look*"))
- (erase-buffer)
-
- (if (stringp ispell-look-dictionary)
- (if ispell-have-new-look
- (call-process ispell-look-command nil t nil "-fr" regexp
- ispell-look-dictionary)
- (call-process ispell-look-command nil t nil "-f" string
- ispell-look-dictionary))
- (if ispell-have-new-look
- (call-process ispell-look-command nil t nil "-fr" regexp)
- (call-process ispell-look-command nil t nil "-f" string)))
-
- ;; Build list for try-completion and all-completions by storing each line
- ;; of output starting from bottom of buffer and deleting upwards.
- (let (list)
- (goto-char (point-min))
- (while (not (= (point-min) (point-max)))
- (end-of-line)
- (setq list (cons (buffer-substring (point-min) (point)) list))
- (forward-line)
- (delete-region (point-min) (point)))
-
- ;; Clean.
- (erase-buffer)
- (message "Building list...done")
-
- ;; Make the list into an alist and return.
- (mapcar 'list (nreverse list)))))
-
-;; Return regexp-quote of STRING if STRING is non-empty.
-;; Otherwise return an unmatchable regexp.
-(defun ispell-non-empty-string (string)
- (if (or (not string) (string-equal string ""))
- "\\'\\`" ; An unmatchable string if string is null.
- (regexp-quote string)))
-
-(defvar ispell-message-cite-regexp "^ \\|^\t"
- "*Regular expression to match lines cited from one message into another.")
-
-(defvar ispell-message-text-end
- (concat "^\\(" (mapconcat (function identity)
- '(
- ;; Matches postscript files.
- "%!PS-Adobe-2.0"
- ;; Matches uuencoded text
- "begin [0-9][0-9][0-9] .*\nM.*\nM.*\nM"
- ;; Matches shell files (esp. auto-decoding)
- "#! /bin/sh"
- ;; Matches difference listing
- "diff -c .*\n\\*\\*\\* .*\n--- "
- ;; Matches "--------------------- cut here"
- "[-=]+\\s cut here")
- "\\|")
- "\\)")
- "*End of text which will be checked in ispell-message.
-If it is a string, limit at first occurrence of that regular expression.
-Otherwise, it must be a function which is called to get the limit.")
-
-(defvar ispell-message-limit (* 100 80)
- "*Ispell-message will check no more than this number of characters.")
-
-;;;autoload
-(defun ispell-message ()
- "Check the spelling of a mail message or news post.
-Don't check spelling of message headers (except subject) or included messages.
-
-To spell-check whenever a message is sent, include this line in .emacs:
- (setq news-inews-hook (setq mail-send-hook 'ispell-message))
-
-Or you can bind the function to C-c i in gnus or mail with:
- (setq mail-mode-hook (setq news-reply-mode-hook
- (function (lambda () (local-set-key \"\\C-ci\" 'ispell-message)))))"
- (interactive)
- (save-excursion
- (let (non-internal-message
- (old-case-fold-search case-fold-search)
- (case-fold-search nil))
- (goto-char (point-min))
- ;; Don't spell-check the headers.
- (if (search-forward mail-header-separator nil t)
- ;; Move to first body line.
- (forward-line 1)
- (while (and (looking-at "[a-zA-Z-]+:\\|\t\\| ")
- (not (eobp)))
- (forward-line 1))
- (setq non-internal-message t)
- )
- (let* ((cite-regexp ;Prefix of inserted text
- (cond
- ((featurep 'supercite) ; sc 3.0
- (concat "\\(" (sc-cite-regexp) "\\)" "\\|"
- (ispell-non-empty-string sc-reference-tag-string)))
- ((featurep 'sc) ; sc 2.3
- (concat "\\(" sc-cite-regexp "\\)" "\\|"
- (ispell-non-empty-string sc-reference-tag-string)))
- (non-internal-message ; Assume nn sent us this message.
- (concat "In [a-zA-Z.]+ you write:" "\\|"
- "In <[^,;&+=]+> [^,;&+=]+ writes:" "\\|"
- " *> *"))
- ((equal major-mode 'news-reply-mode) ;Gnus
- (concat "In article <" "\\|"
- (if mail-yank-prefix
- (ispell-non-empty-string mail-yank-prefix)
- ispell-message-cite-regexp)))
- ((boundp 'vm-included-text-prefix) ; VM mail message
- (concat "[^,;&+=]+ writes:" "\\|"
- (ispell-non-empty-string vm-included-text-prefix)
- ))
- ((boundp 'mh-ins-buf-prefix) ; mh mail message
- (ispell-non-empty-string mh-ins-buf-prefix))
- (mail-yank-prefix ; vanilla mail message.
- (ispell-non-empty-string mail-yank-prefix))
- (t ispell-message-cite-regexp)))
- (continue t)
- (limit
- (min
- (+ (point-min) ispell-message-limit)
- (point-max)
- (save-excursion
- (cond
- ((not ispell-message-text-end) (point-max))
- ((char-or-string-p ispell-message-text-end)
- (if (re-search-forward ispell-message-text-end nil 'end)
- (match-beginning 0)
- (point-max)))
- (t (funcall ispell-message-text-end))))))
- (search-limit ; Search limit which won't stop in middle of citation
- (+ limit (length cite-regexp)))
- )
- ;; Check the subject
- (save-excursion
- (let ((case-fold-search t)
- (message-begin (point)))
- (goto-char (point-min))
- ;; "\\s *" matches newline if subject is empty
- (if (and (re-search-forward "^Subject:[\t ]*" message-begin t)
- (not (looking-at "re\\>")))
- (setq continue
- (ispell-region (- (point) 1)
- (progn
- (end-of-line)
- (while (looking-at "\n[ \t]")
- (end-of-line 2))
- (point))))
- )))
-
- ;; Check the body.
- (while (and (< (point) limit) continue)
- ;; Skip across text cited from other messages.
- (while (and (looking-at (concat "^[ \t]*$\\|" cite-regexp))
- (< (point) limit))
- (forward-line 1))
- (if (< (point) limit)
- ;; Check the next batch of lines that *aren't* cited.
- (let ((start (point)))
- (if (re-search-forward
- (concat "^\\(" cite-regexp "\\)") search-limit 'end)
- (beginning-of-line))
- (if (> (point) limit) (goto-char limit))
- (let ((case-fold-search old-case-fold-search))
- (save-excursion
- (setq continue (ispell-region (- start 1) (point))))))))))))
-
-(provide 'ispell)
-
-;;; ispell.el ends here
diff --git a/lisp/textmodes/bib-mode.el b/lisp/textmodes/bib-mode.el
deleted file mode 100644
index 42de7459ee0..00000000000
--- a/lisp/textmodes/bib-mode.el
+++ /dev/null
@@ -1,241 +0,0 @@
-;;; bib-mode.el --- bib-mode, major mode for editing bib files.
-
-;; Copyright (C) 1989 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: bib
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; 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.
-
-;;; Code:
-
-(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
- (bib-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 bib-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 capitalized in a title (unless the first word).")
-
-(defvar bib-capitalize-title-stop-regexp
- (concat "\\(" bib-capitalize-title-stop-words "\\)\\(\\b\\|'\\)"))
-
-(defun bib-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 bib-capitalize-title-stop-regexp))
- (downcase-word 1)
- (capitalize-word 1)))
- ))
- (set-syntax-table orig-syntax-table))))
-
-
-(defun bib-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)
- (bib-capitalize-title-region (point-min) (point-max))
- (buffer-string)))
-
-(provide 'bib-mode)
-
-;;; bib-mode.el ends here
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el
deleted file mode 100644
index f41f48951fe..00000000000
--- a/lisp/textmodes/bibtex.el
+++ /dev/null
@@ -1,2450 +0,0 @@
-;;; bibtex.el --- BibTeX mode for GNU Emacs
-
-;; Copyright (C) 1992, 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Stefan Schoef <schoef@offis.uni-oldenburg.de>
-;; Bengt Martensson <bengt@mathematik.uni-Bremen.de>
-;; Mark Shapiro <shapiro@corto.inria.fr>
-;; Mike Newton <newton@gumby.cs.caltech.edu>
-;; Aaron Larson <alarson@src.honeywell.com>
-;; Maintainer: Stefan Schoef <schoef@offis.uni-oldenburg.de>
-;; Keywords: BibTeX, LaTeX, TeX
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Major mode for editing and validating BibTeX files.
-
-;; Usage:
-;; See documentation for function bibtex-mode (or type "\M-x describe-mode"
-;; when you are in bibtex-mode).
-
-;; Todo:
-;; Distribute texinfo file.
-
-;; Known Bugs:
-;; 1. using regular expressions to match the entire BibTeX entry dies
-;; on long entries (e.g. those containing abstracts) since
-;; the length of regular expression matches is fairly limited.
-;; 2. Calling bibtex-find-text in a string entry results in the
-;; error message "Can't find enclosing Bibtex field" instead of
-;; moving to the empty string. [reported by gernot@cs.unsw.oz.au]
-
-;; (current keeper: schoef@offis.uni-oldenburg.de
-;; previous: alarson@src.honeywell.com)
-
-;;; Code:
-
-;; User Options:
-
-(defvar bibtex-field-left-delimiter "{"
- "*Set this to { or \" according to your personal preferences.
-This variable is buffer local.")
-(make-variable-buffer-local 'bibtex-field-left-delimiter)
-
-(defvar bibtex-field-right-delimiter "}"
- "*Set this to } or \" according to your personal preferences.
-This variable is buffer local.")
-(make-variable-buffer-local 'bibtex-field-right-delimiter)
-
-(defvar bibtex-include-OPTcrossref '("InProceedings" "InCollection")
- "*All entries listed here will have an OPTcrossref field.")
-
-(defvar bibtex-include-OPTkey t
- "*If non-nil, all entries will have an OPTkey field.")
-
-(defvar bibtex-include-OPTannote t
- "*If non-nil, all entries will have an OPTannote field.")
-
-(defvar bibtex-mode-user-optional-fields nil
- "*List of optional fields the user wants to have always present.
-Entries should be lists of strings with two elements (first element =
-name of the field, second element = comment to appear in the echo area).")
-
-(defvar bibtex-clean-entry-zap-empty-opts t
- "*If non-nil, bibtex-clean-entry will delete all empty optional fields.")
-
-(defvar bibtex-sort-ignore-string-entries t
- "*If non-nil, BibTeX @STRING entries are not sort-significant.
-That means they are ignored when determining ordering of the buffer
-(e.g. sorting, locating alphabetical position for new entries, etc.).
-This variable is buffer local.")
-(make-variable-buffer-local 'bibtex-sort-ignore-string-entries)
-
-(defvar bibtex-maintain-sorted-entries nil
- "*If non-nil, bibtex-mode maintains all BibTeX entries in sorted order.
-Setting this variable to nil will strip off some comfort (e.g. TAB
-completion for reference keys in minibuffer, automatic detection of
-duplicates) from bibtex-mode. See also bibtex-sort-ignore-string-entries.
-This variable is buffer local.")
-(make-variable-buffer-local 'bibtex-maintain-sorted-entries)
-
-(defvar bibtex-parse-keys-timeout auto-save-timeout
- "*Specifies interval for parsing buffer for keys.
-The buffer is checked every bibtex-parse-keys-timeout seconds if it is
-modified since last parsing and is parsed if necessary. This is needed
-only if buffer is maintained sorted (bibtex-maintain-sorted-entries
-non-nil).")
-
-(defvar bibtex-entry-field-alist
- '(
- ("Article" . (((("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the article (BibTeX converts it to lowercase)")
- ("journal" "Name of the journal (use string, remove braces)")
- ("year" "Year of publication"))
- (("volume" "Volume of the journal")
- ("number" "Number of the journal")
- ("month" "Month of the publication as a string (remove braces)")
- ("pages" "Pages in the journal")
- ("note" "Remarks to be put at the end of the \\bibitem")))
- ((("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the article (BibTeX converts it to lowercase)"))
- (("journal" "Name of the journal (use string, remove braces)")
- ("year" "Year of publication")
- ("volume" "Volume of the journal")
- ("number" "Number of the journal")
- ("month" "Month of the publication as a string (remove braces)")
- ("pages" "Pages in the journal")
- ("note" "Remarks to be put at the end of the \\bibitem")))))
- ("Book" . (((("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the book")
- ("publisher" "Publishing company")
- ("year" "Year of publication"))
- (("editor" "Editor1 [and Editor2 ...] [and others]")
- ("volume" "Volume of the book in the series")
- ("number" "Number of the book in a small series (overwritten by volume)")
- ("series" "Series in which the book appeared")
- ("address" "Address of the publisher")
- ("edition" "Edition of the book as a capitalized English word")
- ("month" "Month of the publication as a string (remove braces)")
- ("note" "Remarks to be put at the end of the \\bibitem")))))
- ("Booklet" . (((("title" "Title of the booklet (BibTeX converts it to lowercase)"))
- (("author" "Author1 [and Author2 ...] [and others]")
- ("howpublished" "The way in which the booklet was published")
- ("address" "Address of the publisher")
- ("year" "Year of publication")
- ("month" "Month of the publication as a string (remove braces)")
- ("note" "Remarks to be put at the end of the \\bibitem")))))
- ("InBook" . (((("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the book")
- ("chapter" "Chapter in the book")
- ("publisher" "Publishing company")
- ("year" "Year of publication"))
- (("editor" "Editor1 [and Editor2 ...] [and others]")
- ("volume" "Volume of the book in the series")
- ("number" "Number of the book in a small series (overwritten by volume)")
- ("series" "Series in which the book appeared")
- ("address" "Address of the publisher")
- ("edition" "Edition of the book as a capitalized English word")
- ("month" "Month of the publication as a string (remove braces)")
- ("pages" "Pages in the book")
- ("type" "Word to use instead of \"chapter\"")
- ("note" "Remarks to be put at the end of the \\bibitem")))
- ((("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the book")
- ("chapter" "Chapter in the book"))
- (("publisher" "Publishing company")
- ("year" "Year of publication")
- ("editor" "Editor1 [and Editor2 ...] [and others]")
- ("volume" "Volume of the book in the series")
- ("number" "Number of the book in a small series (overwritten by volume)")
- ("series" "Series in which the book appeared")
- ("address" "Address of the publisher")
- ("edition" "Edition of the book as a capitalized English word")
- ("month" "Month of the publication as a string (remove braces)")
- ("pages" "Pages in the book")
- ("type" "Word to use instead of \"chapter\"")
- ("note" "Remarks to be put at the end of the \\bibitem")))))
- ("InCollection" . (((("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the article in book (BibTeX converts it to lowercase)")
- ("booktitle" "Name of the book")
- ("publisher" "Publishing company")
- ("year" "Year of publication"))
- (("editor" "Editor1 [and Editor2 ...] [and others]")
- ("volume" "Volume of the book in the series")
- ("number" "Number of the book in a small series (overwritten by volume)")
- ("series" "Series in which the book appeared")
- ("chapter" "Chapter in the book")
- ("type" "Word to use instead of \"chapter\"")
- ("address" "Address of the publisher")
- ("edition" "Edition of the book as a capitalized English word")
- ("month" "Month of the publication as a string (remove braces)")
- ("pages" "Pages in the book")
- ("note" "Remarks to be put at the end of the \\bibitem")))
- ((("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the article in book (BibTeX converts it to lowercase)")
- ("booktitle" "Name of the book"))
- (("publisher" "Publishing company")
- ("year" "Year of publication")
- ("editor" "Editor1 [and Editor2 ...] [and others]")
- ("volume" "Volume of the book in the series")
- ("number" "Number of the book in a small series (overwritten by volume)")
- ("series" "Series in which the book appeared")
- ("chapter" "Chapter in the book")
- ("type" "Word to use instead of \"chapter\"")
- ("address" "Address of the publisher")
- ("edition" "Edition of the book as a capitalized English word")
- ("month" "Month of the publication as a string (remove braces)")
- ("pages" "Pages in the book")
- ("note" "Remarks to be put at the end of the \\bibitem")))))
- ("InProceedings" . (((("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the article in proceedings (BibTeX converts it to lowercase)")
- ("booktitle" "Name of the conference proceedings")
- ("year" "Year of publication"))
- (("editor" "Editor1 [and Editor2 ...] [and others]")
- ("volume" "Volume of the conference proceedings in the series")
- ("number" "Number of the conference proceedings in a small series (overwritten by volume)")
- ("series" "Series in which the conference proceedings appeared")
- ("organization" "Sponsoring organization of the conference")
- ("publisher" "Publishing company, its location")
- ("address" "Location of the Proceedings")
- ("month" "Month of the publication as a string (remove braces)")
- ("pages" "Pages in the conference proceedings")
- ("note" "Remarks to be put at the end of the \\bibitem")))
- ((("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the article in proceedings (BibTeX converts it to lowercase)")
- ("booktitle" "Name of the conference proceedings"))
- (("editor" "Editor1 [and Editor2 ...] [and others]")
- ("volume" "Volume of the conference proceedings in the series")
- ("number" "Number of the conference proceedings in a small series (overwritten by volume)")
- ("series" "Series in which the conference proceedings appeared")
- ("year" "Year of publication")
- ("organization" "Sponsoring organization of the conference")
- ("publisher" "Publishing company, its location")
- ("address" "Location of the Proceedings")
- ("month" "Month of the publication as a string (remove braces)")
- ("pages" "Pages in the conference proceedings")
- ("note" "Remarks to be put at the end of the \\bibitem")))))
- ("Manual" . (((("title" "Title of the manual"))
- (("author" "Author1 [and Author2 ...] [and others]")
- ("organization" "Publishing organization of the manual")
- ("address" "Address of the organization")
- ("edition" "Edition of the manual as a capitalized English word")
- ("year" "Year of publication")
- ("month" "Month of the publication as a string (remove braces)")
- ("note" "Remarks to be put at the end of the \\bibitem")))))
-
- ("MastersThesis" . (((("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the master\'s thesis (BibTeX converts it to lowercase)")
- ("school" "School where the master\'s thesis was written")
- ("year" "Year of publication"))
- (("address" "Address of the school (if not part of field \"school\") or country")
- ("type" "Type of the master\'s thesis")
- ("month" "Month of the publication as a string (remove braces)")
- ("note" "Remarks to be put at the end of the \\bibitem")))))
- ("Misc" . ((()
- (("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the reference (BibTeX converts it to lowercase)")
- ("howpublished" "The way in which the reference was published")
- ("year" "Year of publication")
- ("month" "Month of the publication as a string (remove braces)")
- ("note" "Remarks to be put at the end of the \\bibitem")))))
- ("PhdThesis" . (((("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the PhD. thesis")
- ("school" "School where the PhD. thesis was written")
- ("year" "Year of publication"))
- (("address" "Address of the school (if not part of field \"school\") or country")
- ("type" "Type of the PhD. thesis")
- ("month" "Month of the publication as a string (remove braces)")
- ("note" "Remarks to be put at the end of the \\bibitem")))))
- ("Proceedings" . (((("title" "Title of the conference proceedings")
- ("year" "Year of publication"))
- (("editor" "Editor1 [and Editor2 ...] [and others]")
- ("volume" "Volume of the conference proceedings in the series")
- ("number" "Number of the conference proceedings in a small series (overwritten by volume)")
- ("series" "Series in which the conference proceedings appeared")
- ("publisher" "Publishing company, its location")
- ("organization" "Sponsoring organization of the conference")
- ("address" "Location of the Proceedings")
- ("month" "Month of the publication as a string (remove braces)")
- ("note" "Remarks to be put at the end of the \\bibitem")))))
- ("TechReport" . (((("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the technical report (BibTeX converts it to lowercase)")
- ("institution" "Sponsoring institution of the report")
- ("year" "Year of publication"))
- (("type" "Type of the report (if other than \"technical report\")")
- ("number" "Number of the technical report")
- ("address" "Address of the institution (if not part of field \"institution\") or country")
- ("month" "Month of the publication as a string (remove braces)")
- ("note" "Remarks to be put at the end of the \\bibitem")))))
- ("Unpublished" . (((("author" "Author1 [and Author2 ...] [and others]")
- ("title" "Title of the unpublished reference (BibTeX converts it to lowercase)")
- ("note" "Remarks to be put at the end of the \\bibitem"))
- (("year" "Year of publication")
- ("month" "Month of the publication as a string (remove braces)")))))
- )
-
- "Defines reference types and their associated fields.
-List of
-(entry-name (required optional) (crossref-required crossref-optional))
-triples.
-If the third element is nil, the first pair is always to be used.
-If not, the second pair is to be used in the case of presence of a
-crossref field and the third in the case of absence.
-Required , optional, crossref-required and crossref-optional are lists.
-Each element of these lists is a list of strings with two elements
-(first element = name of the field,
- second element = comment to appear in the echo area).")
-
-(defvar bibtex-predefined-strings
- '(
- ("jan") ("feb") ("mar") ("apr") ("may") ("jun") ("jul") ("aug")
- ("sep") ("oct") ("nov") ("dec")
- ("acmcs") ("acta") ("cacm") ("ibmjrd") ("ibmsj") ("ieeese")
- ("ieeetc") ("ieeetcad") ("ipl") ("jacm") ("jcss") ("scp")
- ("sicomp") ("tcs") ("tocs") ("tods") ("tog") ("toms") ("toois")
- ("toplas")
- )
- "Alist of string definitions.
-Should contain the strings defined in the BibTeX style files. Each
-element is a list with just one element: the string.")
-
-(defvar bibtex-string-files nil
- "*List of BibTeX files containing string definitions.
-Those files must be specified using pathnames relative to the
-directories specified in $BIBINPUTS. This variable is only evaluated
-when bibtex-mode is entered (i. e. when loading the BibTeX file).")
-
-(defvar bibtex-help-message t
- "*If not nil print help messages in the echo area on entering a new field.")
-
-(defvar bibtex-autokey-names 1
- "*Number of names to use for the automatically generated reference key.
-If this is set to anything but a number, all names are used.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-name-change-strings
- '(("\\\\\\\"a" "ae") ("\\\\\\\"o" "oe") ("\\\\\\\"u" "ue")
- ("\\\\\\\"s" "ss")
- ("\\\\\\\"A" "Ae") ("\\\\\\\"O" "Oe") ("\\\\\\\"U" "Ue")
- ("\\\"a" "ae") ("\\\"o" "oe") ("\\\"u" "ue") ("\\\"s" "ss")
- ("\\\"A" "Ae") ("\\\"O" "Oe") ("\\\"U" "Ue")
- ("{" "") ("}" ""))
- "Alist of (old-regexp new-string) pairs.
-Any part of name matching a old-regexp is replaced by new-string.
-Case of the old-regexp is significant. All regexps are tried in the
-order in which they appear in the list, so be sure to avoid recursion here.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-name-length 'infty
- "*Number of characters from name to incorporate into key.
-If this is set to anything but a number, all characters are used.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-name-separator ""
- "*String that comes between any two names in the key.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-year-length 2
- "*Number of rightmost digits from the year field yo incorporate into key.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-titlewords 5
- "*Number of title words to use for the automatically generated reference key.
-If this is set to anything but a number, all title words are used.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-title-terminators
- '("\\." "!" "\\?" ":" ";" "---")
- "*Regexp list defining the termination of the main part of the title.
-Case of the regexps is ignored.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-titlewords-stretch 2
- "*Number of words that can additionally be used from the title.
-These words are used only, if a sentence from the title can be ended then.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-titleword-first-ignore
- '("a" "an" "on" "the" "eine?" "der" "die" "das")
- "*Determines words that may begin a title but are not to be used in the key.
-Each item of the list is a regexp. If the first word of the title matchs a
-regexp from that list, it is not included in the title, even if it is
-capitalized. Regexps in the list must be entered using lowercase letters.")
-
-(defvar bibtex-autokey-titleword-abbrevs nil
- "*Determines exceptions to the usual abbreviation mechanism.
-A list of (old-regexp new-string) pairs.
-Use all lowercase letters for old-regexp.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-titleword-change-strings
- '(("\\\\\\\"a" "ae") ("\\\\\\\"o" "oe") ("\\\\\\\"u" "ue")
- ("\\\\\\\"s" "ss")
- ("\\\\\\\"A" "Ae") ("\\\\\\\"O" "Oe") ("\\\\\\\"U" "Ue")
- ("\\\"a" "ae") ("\\\"o" "oe") ("\\\"u" "ue") ("\\\"s" "ss")
- ("\\\"A" "Ae") ("\\\"O" "Oe") ("\\\"U" "Ue")
- ("{" "") ("}" ""))
- "Alist of (old-regexp new-string) pairs.
-Any part of title word matching a old-regexp is replaced by new-string.
-Case of the old-regexp is significant.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-titleword-length 5
- "*Number of characters from title words to incorporate into key.
-If this is set to anything but a number, all characters are used.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-titleword-separator "_"
- "*String to be put between the title words.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-name-year-separator ""
- "*String to be put between name part and year part of key.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-year-title-separator ":_"
- "*String to be put between name part and year part of key.
-See the documentation of function bibtex-generate-autokey for further detail.")
-
-(defvar bibtex-autokey-edit-before-use t
- "*If non-nil, user is allowed to edit the generated key before it is used.")
-
-;; bibtex-font-lock-keywords is a user option as well, but since the
-;; patterns used to define this variable are defined in a later
-;; section of this file, its definition comes later.
-
-
-;; Syntax Table, Keybindings and BibTeX Entry List
-(defvar bibtex-mode-syntax-table
- (let ((st (make-syntax-table)))
- (modify-syntax-entry ?\" "w" st)
- ;; this was formerly "\"". Does this cause any problems?
- (modify-syntax-entry ?$ "$$ " st)
- (modify-syntax-entry ?% "< " st)
- (modify-syntax-entry ?' "w " st)
- (modify-syntax-entry ?@ "w " st)
- (modify-syntax-entry ?\\ "\\" st)
- (modify-syntax-entry ?\f "> " st)
- (modify-syntax-entry ?\n "> " st)
- (modify-syntax-entry ?~ " " st)
- st))
-
-(defvar bibtex-mode-map
- (let ((km (make-sparse-keymap)))
-
- (define-key km "\t" 'bibtex-find-text)
- (define-key km "\n" 'bibtex-next-field)
- (define-key km "\M-\t" 'bibtex-complete-string)
- (define-key km "\C-c\"" 'bibtex-remove-double-quotes-or-braces)
- (define-key km "\C-c{" 'bibtex-remove-double-quotes-or-braces)
- (define-key km "\C-c}" 'bibtex-remove-double-quotes-or-braces)
- (define-key km "\C-c\C-c" 'bibtex-clean-entry)
- (define-key km "\C-c?" 'bibtex-print-help-message)
- (define-key km "\C-c\C-p" 'bibtex-pop-previous)
- (define-key km "\C-c\C-n" 'bibtex-pop-next)
- (define-key km "\C-c\C-k" 'bibtex-kill-optional-field)
- (define-key km "\C-c\C-d" 'bibtex-empty-field)
- (define-key km "\C-c$" 'bibtex-ispell-entry)
- (define-key km "\M-\C-a" 'bibtex-beginning-of-entry)
- (define-key km "\M-\C-e" 'bibtex-end-of-entry)
- (define-key km "\C-c\C-b" 'bibtex-entry)
- (define-key km "\C-c\C-q" 'bibtex-hide-entry-bodies)
- (define-key km "\C-c\C-rn" 'bibtex-narrow-to-entry)
- (define-key km "\C-c\C-rw" 'widen)
- (define-key km "\C-c\C-o" 'bibtex-remove-OPT)
-
- (define-key km "\C-c\C-e\C-i" 'bibtex-InProceedings)
- (define-key km "\C-c\C-ei" 'bibtex-InCollection)
- (define-key km "\C-c\C-eI" 'bibtex-InBook)
- (define-key km "\C-c\C-e\C-a" 'bibtex-Article)
- (define-key km "\C-c\C-e\C-b" 'bibtex-InBook)
- (define-key km "\C-c\C-eb" 'bibtex-Book)
- (define-key km "\C-c\C-eB" 'bibtex-Booklet)
- (define-key km "\C-c\C-e\C-c" 'bibtex-InCollection)
- (define-key km "\C-c\C-e\C-m" 'bibtex-Manual)
- (define-key km "\C-c\C-em" 'bibtex-MastersThesis)
- (define-key km "\C-c\C-eM" 'bibtex-Misc)
- (define-key km "\C-c\C-e\C-p" 'bibtex-InProceedings)
- (define-key km "\C-c\C-ep" 'bibtex-Proceedings)
- (define-key km "\C-c\C-eP" 'bibtex-PhdThesis)
- (define-key km "\C-c\C-e\M-p" 'bibtex-preamble)
- (define-key km "\C-c\C-e\C-s" 'bibtex-string)
- (define-key km "\C-c\C-e\C-t" 'bibtex-TechReport)
- (define-key km "\C-c\C-e\C-u" 'bibtex-Unpublished)
- km))
-
-(define-key bibtex-mode-map [menu-bar bibtex-edit]
- (cons "BibTeX-Edit" (make-sparse-keymap "BibTeX-Edit")))
-(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-print-help-message]
- '("Help about Current Field" . bibtex-print-help-message))
-(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-complete-string]
- '("String Complete" . bibtex-complete-string))
-(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-next-field]
- '("Next Field" . bibtex-next-field))
-(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-find-text]
- '("End of Field" . bibtex-find-text))
-(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-pop-previous]
- '("Snatch from Similar Preceding Field" . bibtex-pop-previous))
-(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-pop-next]
- '("Snatch from Similar Following Field" . bibtex-pop-next))
-(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-remove-OPT]
- '("Remove OPT" . bibtex-remove-OPT))
-(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-remove-double-quotes-or-braces]
- '("Remove Quotes or Braces" . bibtex-remove-double-quotes-or-braces))
-(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-clean-entry]
- '("Clean Up Entry" . bibtex-clean-entry))
-(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-sort-entries]
- '("Sort Entries" . bibtex-sort-entries))
-(define-key bibtex-mode-map
- [menu-bar bibtex-edit bibtex-validate-buffer-from-point]
- '("Validate Entries Starting at Point" .
- (lambda ()
- (interactive)
- (bibtex-validate-buffer t))))
-(define-key bibtex-mode-map [menu-bar bibtex-edit bibtex-validate-buffer]
- '("Validate Entries" . bibtex-validate-buffer))
-
-(define-key bibtex-mode-map [menu-bar entry-types]
- (cons "Entry-Types" (make-sparse-keymap "Entry-Types")))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-preamble]
- '("Preamble" . bibtex-preamble))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-string]
- '("String" . bibtex-string))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-Misc]
- '("Miscellaneous" . bibtex-Misc))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-Unpublished]
- '("Unpublished" . bibtex-Unpublished))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-Manual]
- '("Technical Manual" . bibtex-Manual))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-TechReport]
- '("Technical Report" . bibtex-TechReport))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-MastersThesis]
- '("Master's Thesis" . bibtex-MastersThesis))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-PhdThesis]
- '("PhD. Thesis" . bibtex-PhdThesis))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-Booklet]
- '("Booklet (Bound, but no Publisher/Institution)" . bibtex-Booklet))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-Book]
- '("Book" . bibtex-Book))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-Proceedings]
- '("Conference Proceedings" . bibtex-Proceedings))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-InBook]
- '("Chapter or Pages in a Book" . bibtex-InBook))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-InCollection]
- '("Article in a Collection" . bibtex-InCollection))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-InProceedings]
- '("Article in Conference Proceedings" . bibtex-InProceedings))
-(define-key bibtex-mode-map [menu-bar entry-types bibtex-Article]
- '("Article in Journal" . bibtex-Article))
-
-
-;; Bug Reporting
-
-(defconst
- bibtex-maintainer-address "Stefan Schoef <schoef@offis.uni-oldenburg.de>")
-;; current maintainer
-
-
-;; Internal Variables
-
-(defvar bibtex-pop-previous-search-point nil)
-;; Next point where bibtex-pop-previous starts looking for a similar
-;; entry.
-
-(defvar bibtex-pop-next-search-point nil)
-;; Next point where bibtex-pop-next starts looking for a similar entry.
-
-(defvar bibtex-completion-candidates nil)
-;; Candidates for bibtex-complete-string. Initialized from
-;; bibtex-predefined-strings and bibtex-string-files. This variable is
-;; buffer-local.
-(make-variable-buffer-local 'bibtex-completion-candidates)
-
-(defvar bibtex-keys nil)
-;; Candidates for TAB completion when entering a reference key using
-;; the minibuffer. Initialized in bibtex-mode and updated for each
-;; new entry. This variable is buffer-local.
-(make-variable-buffer-local 'bibtex-keys)
-
-(defvar bibtex-buffer-last-parsed-for-keys-tick nil)
-;; Remembers the value returned by buffer-modified-tick when buffer
-;; was parsed for keys the last time.
-(make-variable-buffer-local 'bibtex-keys)
-
-
-;; Functions to Parse the BibTeX Entries
-
-(defun bibtex-cfield (name text)
- ;; Create a regexp for a BibTeX field of name NAME and text TEXT.
- (concat ",[ \t\n]*\\("
- name
- "\\)[ \t\n]*=[ \t\n]*\\("
- text
- "\\)"))
-(defconst bibtex-name-in-cfield 1)
-;; The regexp subexpression number of the name part in bibtex-cfield.
-
-(defconst bibtex-text-in-cfield 2)
-;; The regexp subexpression number of the text part in bibtex-cfield.
-
-(defconst bibtex-field-name "[^\"#%'(),={} \t\n0-9][^\"#%'(),={} \t\n]*")
-;; Regexp defining the name part of a BibTeX field.
-
-(defconst bibtex-field-const "[][A-Za-z0-9.:;?!`'()/*@_+=|<>-]+")
-;; Format of a bibtex field constant (same as bibtex-reference-key (see below))
-
-(defconst bibtex-field-string-part-not-braced
- "[^{}]")
-;; Match field string part without braces
-
-(defconst bibtex-field-string-part-no-inner-braces
- (concat
- "{"
- "\\(" bibtex-field-string-part-not-braced "\\)*"
- "}"))
-;; Match field string part with no inner braces
-
-(defconst bibtex-field-string-part-1-inner-brace
- (concat
- "{"
- "\\("
- "\\(" bibtex-field-string-part-not-braced "\\)"
- "\\|"
- "\\(" bibtex-field-string-part-no-inner-braces "\\)"
- "\\)*"
- "}"))
-;; Match field string part with at most 1 inner brace
-
-(defconst bibtex-field-string-part-2-inner-braces
- (concat
- "{"
- "\\("
- "\\(" bibtex-field-string-part-not-braced "\\)"
- "\\|"
- "\\(" bibtex-field-string-part-no-inner-braces "\\)"
- "\\|"
- "\\(" bibtex-field-string-part-1-inner-brace "\\)"
- "\\)*"
- "}"))
-;; Match field string part with at most 2 inner braces
-
-(defconst bibtex-field-string-part-3-inner-braces
- (concat
- "{"
- "\\("
- "\\(" bibtex-field-string-part-not-braced "\\)"
- "\\|"
- "\\(" bibtex-field-string-part-no-inner-braces "\\)"
- "\\|"
- "\\(" bibtex-field-string-part-1-inner-brace "\\)"
- "\\|"
- "\\(" bibtex-field-string-part-2-inner-braces "\\)"
- "\\)*"
- "}"))
-;; Match field string part with at most 3 inner braces
-
-(defconst bibtex-field-string-braced
- bibtex-field-string-part-3-inner-braces)
-;; Match braced field string with inner nesting level of braces at most 3
-
-(defconst bibtex-field-string-quoted
- (concat
- "\""
- "\\("
- "\\(" "[^\"\\]" "\\)" ;; every character except quote or backslash
- "\\|"
-;; "\\(" "\"[A-Za-z-]" "\\)" ;; a quote followed by a letter or dash
-;; "\\|"
-;; last two lines commented out until lines like
-;; author = "Stefan Sch"of"
-;; are supported by BibTeX
- "\\(" "\\\\.\\|\n" "\\)" ;; a backslash followed by any character
- "\\)*"
- "\""))
-;; Match quoted field string
-
-(defconst bibtex-field-string
- (concat
- "\\(" bibtex-field-string-braced "\\)"
- "\\|"
- "\\(" bibtex-field-string-quoted "\\)"))
-;; Match a braced or quoted string
-
-(defconst bibtex-field-string-or-const
- (concat bibtex-field-const "\\|" bibtex-field-string))
-;; Match either bibtex-field-string or bibtex-field-const.
-
-(defconst bibtex-field-text
- (concat
- "\\(" bibtex-field-string-or-const "\\)"
- "\\([ \t\n]+#[ \t\n]+\\(" bibtex-field-string-or-const "\\)\\)*"))
-;; Regexp defining the text part of a BibTeX field: either a string,
-;; or an empty string, or a constant followed by one or more # /
-;; constant pairs.
-
-(defconst bibtex-field
- (bibtex-cfield bibtex-field-name bibtex-field-text))
-;; Regexp defining the format of a BibTeX field.
-
-(defconst bibtex-name-in-field bibtex-name-in-cfield)
-;; The regexp subexpression number of the name part in BibTeX-field.
-
-(defconst bibtex-text-in-field bibtex-text-in-cfield)
-;; The regexp subexpression number of the text part in BibTeX-field.
-
-(defconst bibtex-reference-type "@[A-Za-z]+")
-;; Regexp defining the type part of a BibTeX reference entry.
-
-(defconst bibtex-reference-key "[][A-Za-z0-9.:;?!`'()/*@_+=|<>-]+")
-;; Regexp defining the label part of a BibTeX reference entry (same as
-;; bibtex-field-const (see above))
-
-(defconst bibtex-reference-head
- (concat "^[ \t]*\\("
- bibtex-reference-type
- "\\)[ \t]*[({][ \t]*\\("
- bibtex-reference-key
- "\\)"))
-;; Regexp defining format of the header line of a BibTeX reference
-;; entry.
-
-(defconst bibtex-reference-maybe-empty-head
- (concat bibtex-reference-head "?"))
-;; Regexp defining format of the header line of a maybe empty
-;; BibTeX reference entry (without reference key).
-
-(defconst bibtex-type-in-head 1)
-;; The regexp subexpression number of the type part in
-;; bibtex-reference-head.
-
-(defconst bibtex-key-in-head 2)
-;; The regexp subexpression number of the key part in
-;; bibtex-reference-head.
-
-(defconst bibtex-reference
- (concat bibtex-reference-head
- "\\([ \t\n]*" bibtex-field "\\)*"
- "[ \t\n]*,?[ \t\n]*[})]"))
-;; Regexp defining the format of a BibTeX reference entry.
-
-(defconst bibtex-type-in-reference bibtex-type-in-head)
-;; The regexp subexpression number of the type part in
-;; bibtex-reference.
-
-(defconst bibtex-key-in-reference bibtex-key-in-head)
-;; The regexp subexpression number of the key part in
-;; bibtex-reference.
-
-(defconst bibtex-string
- (concat "^[ \t]*@[sS][tT][rR][iI][nN][gG][ \t\n]*[({][ \t\n]*\\("
- bibtex-reference-key
- "\\)[ \t\n]*=[ \t\n]*\\("
- bibtex-field-text
- "\\)[ \t\n]*[})]"))
-;; Regexp defining the format of a BibTeX string entry.
-
-(defconst bibtex-key-in-string 1)
-;; The regexp subexpression of the name part in bibtex-string.
-
-(defconst bibtex-text-in-string 2)
-;; The regexp subexpression of the text part in bibtex-string.
-
-(defvar bibtex-font-lock-keywords
- (list
- (list bibtex-reference-maybe-empty-head
- (list bibtex-type-in-head 'font-lock-function-name-face)
- (list bibtex-key-in-head 'font-lock-reference-face nil t))
- ;; reference type and reference label
- (list (concat "^[ \t]*\\(OPT" bibtex-field-name "\\)[ \t]*=")
- 1 'font-lock-comment-face)
- ;; optional field names (treated as comments)
- (list (concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=")
- 1 'font-lock-variable-name-face)
- ;; field names
- "*Default expressions to highlight in BibTeX mode."))
-;; now all needed patterns are defined
-
-(defconst bibtex-name-alignment 2)
-;; Alignment for the name part in BibTeX fields. Chosen on aesthetic
-;; grounds only.
-
-(defconst bibtex-text-alignment (length " organization = "))
-;; Alignment for the text part in BibTeX fields. Equal to the space
-;; needed for the longest name part.
-
-
-;; Helper Functions
-
-(defun assoc-ignore-case (string alist)
- ;; Return non-nil if STRING is `equal' to the car of an element of
- ;; LIST. Comparison is done with case ignored. The value is actually
- ;; the element of LIST whose car is `equal' to STRING.
- (or (assoc string alist)
- (while (and alist
- (not (string-equal
- (downcase string)
- (downcase (car (car alist))))))
- (setq alist (cdr alist)))
- (car alist)))
-
-(defun member-of-regexp (string list)
- ;; Return non-nil if STRING is exactly matched by an element of
- ;; LIST. This function is influenced by the actual value of
- ;; `case-fold-search'. The value is actually the tail of LIST whose
- ;; car matches STRING.
- (while
- (and
- list
- (not
- (string-match
- (concat "^" (car list) "$")
- string)))
- (setq list (cdr list)))
- list)
-
-(defun assoc-of-regexp (string alist)
- ;; Return non-nil if STRING is exactly matched by the car of an
- ;; element of LIST. This function is influenced by the actual value
- ;; of `case-fold-search'. The value is actually the element of LIST
- ;; whose car matches STRING.
- (while
- (and
- alist
- (not
- (string-match
- (concat "^" (car (car alist)) "$")
- string)))
- (setq alist (cdr alist)))
- (car alist))
-
-(defun skip-whitespace-and-comments ()
- (let ((md (match-data)))
- (unwind-protect
- (while (cond ((looking-at "\\s>+\\|\\s +")
- ;; was whitespace
- ;; NOTE: also checked end-comment. In latex and
- ;; lisp modes, newline is an end comment, but it
- ;; should also be a whitespace char.
- (goto-char (match-end 0)))
- ;; If looking at beginning of comment, skip to end.
- ((looking-at "\\s<")
- (re-search-forward "\\s>"))))
- (store-match-data md))))
-
-(defun map-bibtex-entries (fun)
- ;; Call FUN for each BibTeX entry starting with the current. Do this
- ;; to the end of the file. FUN is called with one argument, the key
- ;; of the entry, and with point inside the entry. If
- ;; bibtex-sort-ignore-string-entries is non-nil, FUN will not be called
- ;; for @string entries.
- (bibtex-beginning-of-entry)
- (while (re-search-forward bibtex-reference-head nil t)
- (if (and bibtex-sort-ignore-string-entries
- (string-equal "@string"
- (downcase (buffer-substring-no-properties
- (match-beginning bibtex-type-in-head)
- (match-end bibtex-type-in-head)))))
- nil
- (funcall fun (buffer-substring-no-properties
- (match-beginning bibtex-key-in-head)
- (match-end bibtex-key-in-head))))))
-
-(defun bibtex-flash-head ()
- ;; Flash at BibTeX reference head before point, if exists.
- (let ((flash))
- (cond ((re-search-backward bibtex-reference-head (point-min) t)
- (goto-char (match-beginning bibtex-type-in-head))
- (setq flash (match-end bibtex-key-in-reference)))
- (t
- (end-of-line)
- (skip-chars-backward " \t")
- (setq flash (point))
- (beginning-of-line)
- (skip-chars-forward " \t")))
- (if (pos-visible-in-window-p (point))
- (sit-for 1)
- (message "From: %s"
- (buffer-substring (point) flash)))))
-
-(defun bibtex-move-outside-of-entry ()
- ;; Make sure we are outside of a BibTeX entry.
- (cond ((or
- (= (point) (point-max))
- (= (point) (point-min))
- (looking-at "[ \n]*@")
- )
- t)
- (t
- (backward-paragraph)
- (forward-paragraph)))
- (re-search-forward "[ \t\n]*" (point-max) t))
-
-(defun beginning-of-first-bibtex-entry ()
- ;; Go to the beginning of the first BibTeX entry in buffer.
- (goto-char (point-min))
- (cond
- ((re-search-forward "^@" nil 'move)
- (beginning-of-line))
- ((and (bobp) (eobp))
- nil)
- (t
- (message "Warning: No BibTeX entries found!"))))
-
-(defun bibtex-inside-field ()
- ;; Try to avoid point being at end of a BibTeX field.
- (end-of-line)
- (skip-chars-backward " \t")
- (cond ((= (preceding-char) ?,)
- (forward-char -2)))
- (cond ((or
- (= (preceding-char) ?})
- (= (preceding-char) ?\"))
- (forward-char -1))))
-
-(defun bibtex-enclosing-field ()
- ;; Search for BibTeX field enclosing point. Point moves to end of
- ;; field; also, use match-beginning and match-end to parse the field.
- ;; sct@dcs.edinburgh.ac.uk
- (let ((old-point (point)))
- (condition-case errname
- (bibtex-enclosing-regexp bibtex-field)
- (search-failed
- (goto-char old-point)
- (error "Can't find enclosing BibTeX field.")))))
-
-(defun bibtex-enclosing-reference ()
- ;; Search for BibTeX reference enclosing point. Point moves to
- ;; beginning of reference. Beginning/end of reference is given by
- ;; (match-beginning/match-end 0).
- (let ((old-point (point)))
- (if (not
- (re-search-backward bibtex-reference-head (point-min) t))
- (progn
- (error "Can't find enclosing BibTeX reference.")
- (goto-char old-point)))
- (goto-char (match-beginning bibtex-type-in-head))
- (let ((pnt (point)))
- (if (not
- (re-search-forward bibtex-reference (point-max) t))
- (progn
- (error "Can't find enclosing BibTeX reference.")
- (goto-char old-point))
- (goto-char pnt)))))
-
-(defun bibtex-enclosing-reference-maybe-empty-head ()
- ;; Search for BibTeX reference enclosing point. Point moves to
- ;; beginning of reference. Beginning/end of reference is given by
- ;; (match-beginning/match-end 0).
- (let ((old-point (point)))
- (if (not
- (re-search-backward
- bibtex-reference-maybe-empty-head (point-min) t))
- (progn
- (error "Can't find enclosing BibTeX reference.")
- (goto-char old-point)))
- (goto-char (match-beginning bibtex-type-in-head))
- (let ((pnt (point)))
- (if (not
- (re-search-forward
- (concat
- bibtex-reference-maybe-empty-head
- "\\([ \t\n]*" bibtex-field "\\)*"
- "[ \t\n]*,?[ \t\n]*[})]")
- (point-max) t))
- (progn
- (error "Can't find enclosing BibTeX reference.")
- (goto-char old-point))
- (goto-char pnt)))))
-
-(defun bibtex-enclosing-regexp (regexp)
- ;; Search for REGEXP enclosing point. Point moves to end of
- ;; REGEXP. See also match-beginning and match-end. If an enclosing
- ;; REGEXP is not found, signals search-failed; point is left in an
- ;; undefined location.
- ;; Doesn't something like this exist already?
- ;; compute reasonable limits for the loop
- (let* ((initial (point))
- (right (if (re-search-forward regexp (point-max) t)
- (match-end 0)
- (point-max)))
- (left
- (progn
- (goto-char initial)
- (if (re-search-backward regexp (point-min) t)
- (match-beginning 0)
- (point-min)))))
- ; within the prescribed limits, loop until a match is found
- (goto-char left)
- (re-search-forward regexp right nil 1)
- (if (> (match-beginning 0) initial)
- (signal 'search-failed (list regexp)))
- (while (<= (match-end 0) initial)
- (re-search-forward regexp right nil 1)
- (if (> (match-beginning 0) initial)
- (signal 'search-failed (list regexp))))
- ))
-
-(defun bibtex-autokey-change (string change-list)
- ;; Returns a string where some regexps are changed according to
- ;; change-list. Every item of change-list is an (old-regexp
- ;; new-string) pair.
- (let ((return-string string)
- case-fold-search
- (index 0)
- (len (length change-list))
- change-item)
- (while (< index len)
- (setq change-item (elt change-list index))
- (while (string-match (car change-item) return-string)
- (setq
- return-string
- (concat (substring return-string 0 (match-beginning 0))
- (elt change-item 1)
- (substring return-string (match-end 0)))))
- (setq index (1+ index)))
- return-string))
-
-(defun bibtex-autokey-abbrev (string len)
- ;; Returns an abbreviation of string with at least len
- ;; characters. String is aborted only after a consonant or at the
- ;; word end. If len is not a number, string is returned unchanged.
- (let* ((string-length (length string))
- (len (if (numberp len)
- (min len string-length)
- len))
- (return-string (if (numberp len)
- (substring string 0 len)))
- (index len)
- (vowels '(?a ?e ?i ?o ?u ?A ?E ?I ?O ?U)))
- (if (numberp len)
- (progn
- (while (and
- (< index string-length)
- (member (elt return-string
- (1- (length return-string)))
- vowels))
- (setq return-string (concat return-string
- (substring
- string index (1+ index)))
- index (1+ index)))
- return-string)
- string)))
-
-(defun bibtex-generate-autokey ()
- "Generates automatically a key from the author/editor and the title field.
-The generation algorithm works as follows:
- 1. If there is a non-empty author (preferred) or editor field,
- use it for the name part of the key.
- 2. Change any substring found in `bibtex-autokey-name-change-strings'
- to the corresponding new one (see documentation of this variable
- for further detail).
- 3. For every of the first `bibtex-autokey-names' names in the
- \"name\" field, determine the last name.
- 4. From every last name, take at least `bibtex-autokey-name-length'
- characters (abort only after a consonant or at a word end).
- 5. Build the name part of the key by concatenating all abbreviated last
- names with the string `bibtex-autokey-name-separator' between
- any two.
- 6. Build the year part of the key by truncating the contents of the
- \"year\" field to the rightmost `bibtex-autokey-year-length'
- digits (useful values are 2 and 4).
- 7. For the title part of the key change the contents of the \"title\"
- field of the reference according to
- `bibtex-autokey-titleword-change-strings' to the corresponding
- new one (see documentation of this variable for further detail).
- 8. Abbreviate the result to the string up to (but not including) the
- first occurrence of a regexp matched by the items of
- `bibtex-autokey-title-terminators' and delete the first
- word if it appears in `bibtex-autokey-titleword-first-ignore'.
- Build the title part of the key by using at least the first
- `bibtex-autokey-titlewords' capitalized words from this
- abbreviated title. If the abbreviated title ends after maximal
- `bibtex-autokey-titlewords' + `bibtex-autokey-titlewords-stretch'
- capitalized words, all capitalized words from the abbreviated title
- are used.
- 9. For every used title word that appears in
- `bibtex-autokey-titleword-abbrevs' use the corresponding abbreviation
- (see documentation of this variable for further detail).
- 10. From every title word not generated by an abbreviation, take at
- least `bibtex-autokey-titleword-length' characters (abort only after
- a consonant or at a word end).
- 11. Build the title part of the key by concatenating all abbreviated
- title words with the string `bibtex-autokey-titleword-separator'
- between any two.
- 12. At least, to get the key, concatenate the name part, the year part
- and the title part with `bibtex-autokey-name-year-separator'
- between the name and the year if both are non-empty and
- `bibtex-autokey-year-title-separator' between the year and
- the title if both are non-empty."
-
- (let* ((pnt (point))
- (min
- (progn
- (bibtex-beginning-of-entry)
- (point)))
- (max
- (progn
- (bibtex-end-of-entry)
- (point)))
- (namefield
- (progn
- (goto-char min)
- (if (or
- (re-search-forward "^[ \t]*author[ \t]*=" max t)
- (re-search-forward "^[ \t]*editor[ \t]*=" max t))
- (let* (bibtex-help-message
- (start (progn
- (bibtex-find-text t)
- (point)))
- (end (progn
- (bibtex-find-text nil)
- (point))))
- (bibtex-autokey-change
- (buffer-substring-no-properties start end)
- bibtex-autokey-name-change-strings))
- "")))
- (namelist
- (mapcar
- (function
- (lambda (fullname)
- (bibtex-autokey-abbrev
- (if (string-match "," fullname)
- (substring fullname 0 (match-beginning 0))
- (progn
- (if (string-match " [^ ]*$" fullname)
- (substring
- fullname (1+ (match-beginning 0)))
- fullname)))
- bibtex-autokey-name-length)))
- ;; Gather all names into a list
- (let (names
- (counter 0))
- (while (and
- (not (equal namefield ""))
- (or
- (not (numberp bibtex-autokey-names))
- (< counter bibtex-autokey-names)))
- (if (string-match " and " namefield)
- (progn
- (setq
- names
- (append names
- (list
- (downcase
- (substring
- namefield 0 (match-beginning 0)))))
- namefield
- (substring namefield (match-end 0))))
- (setq names
- (append names (list (downcase namefield)))
- namefield ""))
- (setq counter (1+ counter)))
- names)))
- (namepart (mapconcat (function (lambda (name) name))
- namelist
- bibtex-autokey-name-separator))
- (yearfield
- (progn
- (goto-char min)
- (if (re-search-forward
- "^[ \t]*year[ \t]*=[ \t]*\\([0-9]*\\)" max t)
- (buffer-substring-no-properties
- (match-beginning 1) (match-end 1))
- "")))
- (yearpart
- (if (equal yearfield "")
- ""
- (substring yearfield
- (- (length yearfield)
- bibtex-autokey-year-length))))
- (titlestring
- (let ((case-fold-search t)
- (titlefield
- (progn
- (goto-char min)
- (if (re-search-forward
- "^[ \t]*title[ \t]*=" max t)
- (let* (bibtex-help-message
- (start (progn
- (bibtex-find-text t)
- (point)))
- (end (progn
- (bibtex-find-text nil)
- (point))))
- (bibtex-autokey-change
- (buffer-substring-no-properties start end)
- bibtex-autokey-titleword-change-strings))
- "")))
- case-fold-search
- (index 0)
- (numberofitems
- (length bibtex-autokey-title-terminators)))
- (while (< index numberofitems)
- (if (string-match
- (elt bibtex-autokey-title-terminators index)
- titlefield)
- (setq titlefield
- (substring titlefield 0 (match-beginning 0))))
- (setq index (1+ index)))
- titlefield))
- (titlelist
- (mapcar
- (function
- (lambda (titleword)
- (let ((abbrev
- (assoc-of-regexp
- titleword bibtex-autokey-titleword-abbrevs)))
- (if abbrev
- (elt abbrev 1)
- (bibtex-autokey-abbrev
- titleword
- bibtex-autokey-titleword-length)))))
- ;; Gather all titlewords into a list
- (let (titlewords
- titlewords-extra
- case-fold-search
- (counter 0)
- (first t))
- (while (and
- (not (equal titlestring ""))
- (or
- (not (numberp bibtex-autokey-titlewords))
- (< counter (+
- bibtex-autokey-titlewords
- bibtex-autokey-titlewords-stretch))))
- (if (string-match "\\b[A-Z][A-Za-z0-9]*" titlestring)
- (let* ((end-match (match-end 0))
- (titleword
- (downcase (substring titlestring
- (match-beginning 0)
- end-match))))
- (if (or
- (not (numberp bibtex-autokey-titlewords))
- (< counter bibtex-autokey-titlewords))
- (if (and
- first
- (member-of-regexp
- titleword
- bibtex-autokey-titleword-first-ignore))
- (setq counter -1)
- (setq titlewords
- (append titlewords (list titleword))))
- (setq
- titlewords-extra
- (append titlewords-extra (list titleword))))
- (setq titlestring
- (substring titlestring end-match)))
- (setq titlestring ""))
- (setq first nil
- counter (1+ counter)))
- (if (string-match "\\b[A-Z][^ ]*\\b" titlestring)
- titlewords
- (append titlewords titlewords-extra)))))
- (titlepart (mapconcat (function (lambda (name) name))
- titlelist
- bibtex-autokey-titleword-separator))
- (autokey
- (concat
- namepart
- (if (not
- (or
- (equal namepart "")
- (equal yearpart "")))
- bibtex-autokey-name-year-separator)
- yearpart
- (if (not
- (or
- (and
- (equal namepart "")
- (equal yearpart ""))
- (equal titlepart "")))
- bibtex-autokey-year-title-separator)
- titlepart)))
- (goto-char pnt)
- autokey))
-
-(defun bibtex-parse-keys (add &optional abortable)
- ;; Sets bibtex-keys to the keys used in the whole (possibly
- ;; restricted) buffer (either as entry keys or as crossref entries).
- ;; If ADD is non-nil adds the new keys to bibtex-keys instead of
- ;; simply resetting it. If ABORTABLE is non-nil abort on user input.
- (if bibtex-maintain-sorted-entries
- (let ((labels (if add
- bibtex-keys))
- label
- (case-fold-search t))
- (save-excursion
- (goto-char (point-min))
- (if (not add)
- (message "Parsing reference keys..."))
-
- (if (not
- (catch 'userkey
- (while
- (re-search-forward
- (concat
- "\\(" bibtex-reference-head "\\)"
- "\\|"
- "\\("
- "^[ \t]*crossref[ \t\n]*=[ \t\n]*"
- "\\("
- "\\({"
- bibtex-reference-key
- ;; every valid crossref entry must have the
- ;; form of a reference key, so we need no
- ;; nesting of brace etc. here
- "}\\)"
- "\\|"
- "\\(\""
- bibtex-reference-key
- "\"\\)"
- "\\)"
- ",?$"
- "\\)")
- nil t)
- (if (and
- abortable
- (input-pending-p))
- (throw 'userkey t))
- (if (match-beginning (1+ bibtex-key-in-head))
- (setq
- label
- (buffer-substring-no-properties
- (match-beginning (1+ bibtex-key-in-head))
- (match-end (1+ bibtex-key-in-head))))
- (setq
- label
- (buffer-substring-no-properties
- (1+ (match-beginning (+ 3 bibtex-key-in-head)))
- (1- (match-end (+ 3 bibtex-key-in-head))))))
- (if (not (assoc label labels))
- (setq labels
- (cons (list label) labels))))))
- (progn
- (setq
- bibtex-buffer-last-parsed-for-keys-tick
- (buffer-modified-tick))
- (if (not add)
- (message "Parsing reference keys... done"))
- (setq bibtex-keys labels)))))))
-
-(defun bibtex-auto-fill-function ()
- (let ((fill-prefix (make-string (+ bibtex-text-alignment 1) ? )))
- (do-auto-fill)))
-
-
-;; Interactive Functions:
-
-;;;###autoload
-(defun bibtex-mode ()
- "Major mode for editing BibTeX files.
-To submit a problem report, enter `\\[bibtex-submit-bug-report]' from a
-bibtex-mode buffer. This automatically sets up a mail buffer with
-version information already added. You just need to add a description
-of the problem, including a reproducable test case and send the
-message.
-
-\\{bibtex-mode-map}
-
-A command such as \\[bibtex-Book] will outline the fields for a BibTeX book entry.
-
-The optional fields start with the string OPT, and thus ignored by BibTeX.
-The OPT string may be removed from a field with \\[bibtex-remove-OPT].
-\\[bibtex-kill-optional-field] kills the current optional field entirely.
-\\[bibtex-remove-double-quotes-or-braces] removes the double-quotes or
-braces around the text of the current field. \\[bibtex-empty-field]
-replaces the text of the current field with the default \"\" or {}.
-
-The command \\[bibtex-clean-entry] cleans the current entry, i.e. (i) removes
-double-quotes or braces from entirely numerical fields, (ii) removes
-OPT from all non-empty optional fields, (iii) removes all empty
-optional fields, and (iv) checks that no non-optional fields are empty.
-
-Use \\[bibtex-find-text] to position the cursor at the end of the current field.
-Use \\[bibtex-next-field] to move to end of the next field.
-
-The following may be of interest as well:
-
- Functions:
- bibtex-entry
- bibtex-print-help-message
- bibtex-beginning-of-entry
- bibtex-end-of-entry
- bibtex-ispell-abstract
- bibtex-narrow-to-entry
- bibtex-hide-entry-bodies
- bibtex-sort-entries
- bibtex-validate-buffer
- bibtex-pop-previous
- bibtex-pop-next
- bibtex-complete-string
-
- Variables:
- bibtex-field-left-delimiter
- bibtex-field-right-delimiter
- bibtex-include-OPTcrossref
- bibtex-include-OPTkey
- bibtex-include-OPTannote
- bibtex-mode-user-optional-fields
- bibtex-clean-entry-zap-empty-opts
- bibtex-sort-ignore-string-entries
- bibtex-maintain-sorted-entries
- bibtex-entry-field-alist
- bibtex-predefined-strings
- bibtex-string-files
-
----------------------------------------------------------
-Entry to this mode calls the value of bibtex-mode-hook if that value is
-non-nil."
- (interactive)
- (kill-all-local-variables)
- (use-local-map bibtex-mode-map)
- (setq major-mode 'bibtex-mode)
- (setq mode-name "BibTeX")
- (set-syntax-table bibtex-mode-syntax-table)
- (setq bibtex-completion-candidates bibtex-predefined-strings)
- (mapcar
- (function
- (lambda (filename)
- ;; collect pathnames
- (let* ((bib (getenv "BIBINPUTS"))
- (path (if bib
- bib
- "."))
- (dirs
- (mapcar
- (function
- (lambda (dirname) ;; strips off trailing slashes
- (let ((len (length dirname)))
- (if (equal (elt dirname (1- len)) "/")
- (substring dirname 0 (1- (1- len)))
- dirname))))
- (let (actdirs)
- (while (string-match ":" path)
- (setq actdirs
- (append actdirs
- (list (substring
- path 0
- (1- (match-end 0)))))
- path (substring path (match-end 0))))
- (append actdirs (list path)))))
- (filename (if (string-match "\.bib$" filename)
- filename
- (concat filename ".bib")))
- fullfilename
- (item 0)
- (size (length dirs)))
- ;; test filenames
- (while (and
- (< item size)
- (not (file-readable-p
- (setq fullfilename
- (concat (elt dirs item) "/" filename)))))
- (setq item (1+ item)))
- (if (< item size)
- ;; file was found
- (let ((curbuf (current-buffer))
- (bufname (make-temp-name ""))
- (compl bibtex-completion-candidates))
- (create-file-buffer bufname)
- (set-buffer bufname)
- (insert-file-contents fullfilename)
- (goto-char (point-min))
- (while (re-search-forward bibtex-string nil t)
- (setq
- compl
- (append
- compl
- (list
- (list (buffer-substring-no-properties
- (match-beginning bibtex-key-in-string)
- (match-end bibtex-key-in-string)))))))
- (kill-buffer bufname)
- (set-buffer curbuf)
- (setq bibtex-completion-candidates compl))
- (error "File %s not in $BIBINPUTS paths" filename)))))
- bibtex-string-files)
- (run-with-idle-timer
- bibtex-parse-keys-timeout bibtex-parse-keys-timeout
- (function
- (lambda ()
- (if (and
- bibtex-maintain-sorted-entries
- (eq major-mode 'bibtex-mode)
- (not
- (eq (buffer-modified-tick)
- bibtex-buffer-last-parsed-for-keys-tick)))
- (bibtex-parse-keys nil t)))))
- (bibtex-parse-keys nil)
- (make-local-variable 'paragraph-start)
- (setq paragraph-start "[ \f\n\t]*$")
- (make-local-variable 'comment-start)
- (setq comment-start "%")
- (make-local-variable 'normal-auto-fill-function)
- (setq normal-auto-fill-function 'bibtex-auto-fill-function)
- (set (make-local-variable 'font-lock-defaults)
- '(bibtex-font-lock-keywords
- nil t ((?$ . "\"")
- ;; Mathematical expressions should be fontified as strings
- (?\" . ".")
- ;; Quotes are field delimiters and quote-delimited
- ;; entries should be fontified in the same way as
- ;; brace-delimited ones
- )))
- (run-hooks 'bibtex-mode-hook))
-
-(defun bibtex-submit-bug-report ()
- "Submit via mail a bug report on bibtex.el."
- (interactive)
- (if (y-or-n-p "Do you want to submit a bug report on BibTeX mode? ")
- (progn
- (require 'reporter)
- (let ((reporter-prompt-for-summary-p t))
- (reporter-submit-bug-report
- bibtex-maintainer-address
- "bibtex.el"
- (list
- 'system-configuration
- 'system-configuration-options
- 'bibtex-sort-ignore-string-entries
- 'bibtex-maintain-sorted-entries
- 'bibtex-field-left-delimiter
- 'bibtex-field-right-delimiter
- ;; Possible sorting and parsing bugs
- 'bibtex-mode-user-optional-fields
- ;; Possible format error
- 'bibtex-predefined-strings
- 'bibtex-string-files
- ;; Possible format error
- 'bibtex-font-lock-keywords
- ;; Possible bugs regarding fontlocking
- 'bibtex-autokey-names
- 'bibtex-autokey-name-change-strings
- 'bibtex-autokey-name-length
- 'bibtex-autokey-name-separator
- 'bibtex-autokey-year-length
- 'bibtex-autokey-titlewords
- 'bibtex-autokey-title-terminators
- 'bibtex-autokey-titlewords-stretch
- 'bibtex-autokey-titleword-first-ignore
- 'bibtex-autokey-titleword-abbrevs
- 'bibtex-autokey-titleword-change-strings
- 'bibtex-autokey-titleword-length
- 'bibtex-autokey-titleword-separator
- 'bibtex-autokey-name-year-separator
- 'bibtex-autokey-year-title-separator
- 'bibtex-autokey-edit-before-use
- ;; Possible bugs regarding automatic labels
- 'bibtex-entry-field-alist
- ;; Possible format error
- 'bibtex-help-message
- 'bibtex-include-OPTcrossref
- 'bibtex-include-OPTkey
- 'bibtex-include-OPTannote
- 'bibtex-clean-entry-zap-empty-opts
- ;; User variables which shouldn't cause any errors
- )
- nil nil
- (concat "Hi Stefan,
-
-I want to report a bug on Emacs BibTeX mode.
-I've read the `Bugs' section in the `Emacs' info page, so I know how
-to make a clear and unambiguous report. I have started a fresh Emacs
-via `"invocation-name " --no-init-file --no-site-file', thereafter (in
-case I'm reporting on a version of `bibtex.el' which is not part of
-the standard emacs distribution) I loaded the questionable version
-of `bibtex.el' with `M-x load-file', and then, to produce the buggy
-behaviour, I did the following:")))
- (message nil))))
-
-(defun bibtex-entry (entry-type &optional required optional)
- "Inserts a new BibTeX entry.
-Calls the value of bibtex-add-entry-hook if that value is non-nil."
- (interactive (let* ((completion-ignore-case t)
- (e-t (completing-read
- "Entry Type: "
- bibtex-entry-field-alist
- nil t)))
- (list e-t)))
- (if (and (null required) (null optional))
- (let* ((e (assoc-ignore-case entry-type bibtex-entry-field-alist))
- (r-n-o (elt e 1))
- (c-ref (elt e 2)))
- (if (null e)
- (error "Bibtex entry type %s not defined!" entry-type))
- (if (and
- (member entry-type bibtex-include-OPTcrossref)
- c-ref)
- (setq required (elt c-ref 0)
- optional (elt c-ref 1))
- (setq required (elt r-n-o 0)
- optional (elt r-n-o 1)))))
- (let ((key
- (if bibtex-maintain-sorted-entries
- (completing-read
- (format "%s key: " entry-type)
- bibtex-keys))))
- (if bibtex-maintain-sorted-entries
- (bibtex-find-entry-location key)
- (bibtex-move-outside-of-entry))
- (insert "@" entry-type "{")
- (if key
- (insert key))
- (save-excursion
- (mapcar 'bibtex-make-field required)
- (if (member entry-type bibtex-include-OPTcrossref)
- (bibtex-make-optional-field '("crossref")))
- (if bibtex-include-OPTkey
- (bibtex-make-optional-field '("key")))
- (mapcar 'bibtex-make-optional-field optional)
- (mapcar 'bibtex-make-optional-field
- bibtex-mode-user-optional-fields)
- (if bibtex-include-OPTannote
- (bibtex-make-optional-field '("annote")))
- (insert "\n}\n\n"))
- (bibtex-next-field t)
- (run-hooks 'bibtex-add-entry-hook)))
-
-(defun bibtex-print-help-message ()
- "Prints helpful information about current field in current BibTeX entry."
- (interactive)
- (let* ((pnt (point))
- (field-name
- (progn
- (beginning-of-line)
- (condition-case errname
- (bibtex-enclosing-regexp bibtex-field)
- (search-failed
- (goto-char pnt)
- (error "Not on BibTeX field")))
- (let ((mb (match-beginning bibtex-name-in-field))
- (me (match-end bibtex-name-in-field)))
- (goto-char mb)
- (buffer-substring-no-properties
- (if (looking-at "OPT")
- (+ 3 mb)
- mb)
- me))))
- (reference-type
- (progn
- (re-search-backward
- bibtex-reference-maybe-empty-head nil t)
- (buffer-substring-no-properties
- (1+ (match-beginning bibtex-type-in-head))
- (match-end bibtex-type-in-head))))
- (entry-list
- (assoc-ignore-case reference-type
- bibtex-entry-field-alist))
- (c-r-list (elt entry-list 2))
- (req-opt-list
- (if (and
- (member reference-type bibtex-include-OPTcrossref)
- c-r-list)
- c-r-list
- (elt entry-list 1)))
- (list-of-entries (append
- (elt req-opt-list 0)
- (elt req-opt-list 1)
- bibtex-mode-user-optional-fields
- (if (member
- reference-type
- bibtex-include-OPTcrossref)
- '(("crossref"
- "Label of the crossreferenced entry")))
- (if bibtex-include-OPTannote
- '(("annote"
- "Personal annotation (ignored)")))
- (if bibtex-include-OPTkey
- '(("key"
- "Key used for label creation if author and editor fields are missing"))))))
- (goto-char pnt)
- (let ((comment (assoc-ignore-case field-name list-of-entries)))
- (if comment
- (message (elt comment 1))
- (message "NO COMMENT AVAILABLE")))))
-
-(defun bibtex-make-field (e-t)
- "Makes a field named E-T in current BibTeX entry."
- (interactive "sBibTeX field name: ")
- (let ((name (if (consp e-t)
- (elt e-t 0)
- e-t)))
- (if (interactive-p)
- (progn
- (bibtex-find-text nil)
- (if (looking-at "[}\"]")
- (forward-char 1))))
- (insert ",\n")
- (indent-to-column bibtex-name-alignment)
- (insert name " = ")
- (indent-to-column bibtex-text-alignment)
- (insert bibtex-field-left-delimiter bibtex-field-right-delimiter)
- (if (interactive-p)
- (forward-char -1))))
-
-(defun bibtex-make-optional-field (e-t)
- "Makes an optional field named E-T in current BibTeX entry."
- (if (consp e-t)
- (setq e-t (cons (concat "OPT" (car e-t)) (cdr e-t)))
- (setq e-t (concat "OPT" e-t)))
- (bibtex-make-field e-t))
-
-(defun bibtex-beginning-of-entry ()
- "Move to beginning of BibTeX entry.
-If inside an entry, move to the beginning of it, otherwise move to the
-beginning of the previous entry."
- (interactive)
- (if (looking-at "^@")
- (forward-char))
- (re-search-backward "^@" nil 'move))
-
-(defun bibtex-end-of-entry ()
- "Move to end of BibTeX entry.
-If inside an entry, move to the end of it, otherwise move to the end
-of the previous entry."
- (interactive)
- (bibtex-beginning-of-entry)
- (let ((parse-sexp-ignore-comments t))
- (forward-sexp 2) ;; skip entry type and body
- ))
-
-(defun bibtex-ispell-entry ()
- "Spell whole BibTeX entry."
- (interactive)
- (ispell-region (progn (bibtex-beginning-of-entry) (point))
- (progn (bibtex-end-of-entry) (point))))
-
-(defun bibtex-ispell-abstract ()
- "Spell abstract of BibTeX entry."
- (interactive)
- (let ((pnt (bibtex-end-of-entry)))
- (bibtex-beginning-of-entry)
- (if (null
- (re-search-forward "^[ \t]*[OPT]*abstract[ \t]*=" pnt))
- (error "No abstract in entry.")))
- (ispell-region (point)
- (save-excursion (forward-sexp) (point))))
-
-(defun bibtex-narrow-to-entry ()
- "Narrow buffer to current BibTeX entry."
- (interactive)
- (save-excursion
- (narrow-to-region (progn (bibtex-beginning-of-entry) (point))
- (progn (bibtex-end-of-entry) (point)))))
-
-(defun bibtex-hide-entry-bodies (&optional arg)
- "Hide all lines between first and last BibTeX entries not beginning with @.
-With argument, show all text."
- (interactive "P")
- (save-excursion
- (beginning-of-first-bibtex-entry)
- ;; subst-char-in-region modifies the buffer, despite what the
- ;; documentation says...
- (let ((modifiedp (buffer-modified-p))
- (buffer-read-only nil))
- (if arg
- (subst-char-in-region (point) (point-max) ?\r ?\n t)
- (while (save-excursion (re-search-forward "\n[^@]" (point-max) t))
- ;; (save-excursion (replace-regexp "\n\\([^@]\\)" "\r\\1"))
- (save-excursion
- (while (re-search-forward "\n\\([^@]\\)" nil t)
- (replace-match "\r\\1" nil nil)))))
- (setq selective-display (not arg))
- (set-buffer-modified-p modifiedp))))
-
-(defun bibtex-sort-entries ()
- "Sort BibTeX entries alphabetically by key.
-Text outside of BibTeX entries is not affected. If
-bibtex-sort-ignore-string-entries is non-nil, @string entries will be
-ignored."
- (interactive)
- (save-restriction
- (beginning-of-first-bibtex-entry)
- (narrow-to-region
- (point)
- (save-excursion
- (goto-char (point-max))
- (bibtex-end-of-entry)
- (point)))
- (if bibtex-sort-ignore-string-entries
- (if (re-search-forward bibtex-reference nil 'move)
- (goto-char (match-beginning 0))))
- (sort-subr
- nil
- ;; NEXTREC function
- (function
- (lambda ()
- (if bibtex-sort-ignore-string-entries
- (if (re-search-forward bibtex-reference nil 'move)
- (goto-char (match-beginning 0)))
- (if (re-search-forward bibtex-reference-head nil 'move)
- (goto-char (match-beginning 0))))))
- ;; ENDREC function
- 'bibtex-end-of-entry
- ;; STARTKEY function
- (function
- (lambda ()
- (if bibtex-sort-ignore-string-entries
- (progn
- (re-search-forward bibtex-reference)
- (buffer-substring-no-properties
- (match-beginning bibtex-key-in-reference)
- (match-end bibtex-key-in-reference)))
- (re-search-forward bibtex-reference-head)
- (buffer-substring-no-properties
- (match-beginning bibtex-key-in-head)
- (match-end bibtex-key-in-head)))))
- ;; ENDKEY function
- nil)))
-
-(defun bibtex-find-entry-location (entry-name &optional ignore-dups)
- "Looking for place to put the BibTeX entry named ENTRY-NAME.
-Performs a binary search (therefore, buffer is assumed to be in sorted
-order, without duplicates (see \\[bibtex-validate-buffer]), if it is
-not, bibtex-find-entry-location will fail). If entry-name is already
-used as a reference key, an error is signaled. However, if optional
-variable IGNORE-DUPS is non-nil, no error messages about duplicate
-entries are signaled, but the error handling is assumed to be made in
-the calling function. Nil is returned, if an duplicate entry error
-occurred, and t in all other cases."
- (let* ((left
- (progn
- (beginning-of-first-bibtex-entry)
- (if bibtex-sort-ignore-string-entries
- (re-search-forward bibtex-reference nil `move)
- (bibtex-end-of-entry))
- (point)))
- (right
- (progn
- (goto-char (point-max))
- (if bibtex-sort-ignore-string-entries
- (re-search-backward bibtex-reference nil `move)
- (bibtex-beginning-of-entry))
- (point)))
- actual-point
- actual-key
- (done (>= left right))
- new
- dup)
- (while (not done)
- (setq actual-point (/ (+ left right) 2))
- (goto-char actual-point)
- (bibtex-beginning-of-entry)
- (setq actual-key
- (if bibtex-sort-ignore-string-entries
- (progn
- (re-search-forward bibtex-reference)
- (buffer-substring-no-properties
- (match-beginning bibtex-key-in-reference)
- (match-end bibtex-key-in-reference)))
- (re-search-forward bibtex-reference-head)
- (buffer-substring-no-properties
- (match-beginning bibtex-key-in-head)
- (match-end bibtex-key-in-head))))
- (cond
- ((string-lessp entry-name actual-key)
- (setq new (match-beginning 0))
- (if (equal right new)
- (setq done t)
- (setq right new)))
- ((string-lessp actual-key entry-name)
- (setq new (match-end 0))
- (if (equal left new)
- (setq done t)
- (setq left new)))
- ((string-equal actual-key entry-name)
- (setq dup t
- done t)
- (if (not ignore-dups)
- (error "Entry with key `%s' already exists!" entry-name)))))
- (if dup
- nil
- (goto-char right)
- (if (re-search-forward bibtex-reference nil t)
- (progn
- (setq actual-key
- (buffer-substring-no-properties
- (match-beginning bibtex-key-in-reference)
- (match-end bibtex-key-in-reference)))
- (if (string-lessp actual-key entry-name)
- ;; even greater than last entry --> we must append
- (progn
- (goto-char (match-end 0))
- (newline (forward-line 2))
- (beginning-of-line))
- (goto-char right))))
- t)))
-
-(defun bibtex-validate-buffer (&optional from-point)
- "Validate if the current BibTeX buffer is syntactically correct.
-Any garbage (e.g. comments) before the first \"@\" is not tested (so
-you can put comments here).
-With non-nil FROM-POINT it starts with entry enclosing point."
- (interactive "P")
- (let ((pnt (point))
- (starting-point
- (progn
- (if from-point
- (bibtex-beginning-of-entry)
- (beginning-of-first-bibtex-entry))
- (point))))
- ;; looking if entries fit syntactical structure
- (goto-char starting-point)
- (while (re-search-forward "^@" nil t)
- (forward-char -1)
- (let ((p (point)))
- (if (or
- (looking-at "@string")
- (looking-at "@preamble"))
- (forward-char)
- (if (not (and
- (re-search-forward bibtex-reference nil t)
- (equal p (match-beginning 0))))
- (progn
- (goto-char p)
- (error "Bad entry begins here"))))))
- ;; looking if entries are balanced (a single non-escaped quote
- ;; inside braces is not detected by the former check, but
- ;; bibtex-sort-entries stumbles about it
- (goto-char starting-point)
- (map-bibtex-entries
- (function
- (lambda (current)
- (bibtex-beginning-of-entry)
- (forward-sexp 2))))
- ;; looking for correct sort order and duplicates
- (if bibtex-maintain-sorted-entries
- (let (previous
- point)
- (goto-char starting-point)
- (map-bibtex-entries
- (function
- (lambda (current)
- (cond ((or (null previous)
- (string< previous current))
- (setq previous current
- point (point)))
- ((string-equal previous current)
- (error "Duplicate here with previous!"))
- (t
- (error "Entries out of order here!"))))))))
- (goto-char pnt)
- (if from-point
- (message "Part of BibTeX buffer starting at point is syntactically correct")
- (message "BibTeX buffer is syntactically correct"))))
-
-(defun bibtex-next-field (arg)
- "Finds end of text of next BibTeX field; with arg, to its beginning."
- (interactive "P")
- (bibtex-inside-field)
- (let ((start (point)))
- (condition-case ()
- (progn
- (bibtex-enclosing-field)
- (goto-char (match-end 0))
- (forward-char 2))
- (error
- (goto-char start)
- (end-of-line)
- (forward-char 1))))
- (bibtex-find-text arg))
-
-(defun bibtex-find-text (arg)
- "Go to end of text of current field; with arg, go to beginning."
- (interactive "P")
- (bibtex-inside-field)
- (bibtex-enclosing-field)
- (if arg
- (progn
- (goto-char (match-beginning bibtex-text-in-field))
- (if (looking-at "[{\"]")
- (forward-char 1)))
- (goto-char (match-end bibtex-text-in-field))
- (if (or
- (= (preceding-char) ?})
- (= (preceding-char) ?\"))
- (forward-char -1)))
- (if bibtex-help-message
- (bibtex-print-help-message)))
-
-(defun bibtex-remove-OPT ()
- "Removes the 'OPT' starting optional arguments and goes to end of text."
- (interactive)
- (bibtex-inside-field)
- (bibtex-enclosing-field)
- (save-excursion
- (goto-char (match-beginning bibtex-name-in-field))
- (if (looking-at "OPT")
- ;; sct@dcs.edinburgh.ac.uk
- (progn
- (delete-char (length "OPT"))
- (search-forward "=")
- (delete-horizontal-space)
- (indent-to-column bibtex-text-alignment))))
- (bibtex-inside-field))
-
-(defun bibtex-remove-double-quotes-or-braces ()
- "Removes \"\" or {} around string."
- (interactive)
- (save-excursion
- (bibtex-inside-field)
- (bibtex-enclosing-field)
- (let ((start (match-beginning bibtex-text-in-field))
- (stop (match-end bibtex-text-in-field)))
- (goto-char start)
- (while (re-search-forward bibtex-field-string stop t)
- (let ((beg (match-beginning 0))
- (end (match-end 0)))
- (goto-char end)
- (forward-char -1)
- (if (looking-at "[}\"]")
- (delete-char 1))
- (goto-char beg)
- (if (looking-at "[{\"]")
- (delete-char 1)))))))
-
-(defun bibtex-kill-optional-field ()
- "Kill the entire enclosing optional BibTeX field."
- (interactive)
- (bibtex-inside-field)
- (bibtex-enclosing-field)
- (goto-char (match-beginning bibtex-name-in-field))
- (let ((the-end (match-end 0))
- (the-beginning (match-beginning 0)))
- (if (looking-at "OPT")
- (progn
- (goto-char the-end)
- (skip-chars-forward " \t\n,")
- (kill-region the-beginning the-end))
- (error "Mandatory fields can't be killed"))))
-
-(defun bibtex-empty-field ()
- "Delete the text part of the current field, replace with empty text."
- (interactive)
- (bibtex-inside-field)
- (bibtex-enclosing-field)
- (goto-char (match-beginning bibtex-text-in-field))
- (kill-region (point) (match-end bibtex-text-in-field))
- (insert (concat bibtex-field-left-delimiter
- bibtex-field-right-delimiter))
- (bibtex-find-text t))
-
-(defun bibtex-pop (arg direction)
- ;; generic function to be used by bibtex-pop-previous and bibtex-pop-next
- (let (bibtex-help-message)
- (bibtex-find-text nil))
- (save-excursion
- ;; parse current field
- (bibtex-inside-field)
- (bibtex-enclosing-field)
- (let ((start-old-text (match-beginning bibtex-text-in-field))
- (stop-old-text (match-end bibtex-text-in-field))
- (start-name (match-beginning bibtex-name-in-field))
- (stop-name (match-end bibtex-name-in-field))
- (new-text))
- (goto-char start-name)
- ;; construct regexp for field with same name as this one,
- ;; ignoring possible OPT's
- (let ((matching-entry
- (bibtex-cfield
- (buffer-substring-no-properties (if (looking-at "OPT")
- (+ (point) (length "OPT"))
- (point))
- stop-name)
- bibtex-field-text)))
- ;; if executed several times in a row, start each search where
- ;; the last one was finished
- (cond ((eq last-command 'bibtex-pop)
- t
- )
- (t
- (bibtex-enclosing-reference-maybe-empty-head)
- (setq bibtex-pop-previous-search-point (point))
- (setq bibtex-pop-next-search-point (match-end 0))))
- (if (eq direction 'previous)
- (goto-char bibtex-pop-previous-search-point)
- (goto-char bibtex-pop-next-search-point))
- ;; Now search for arg'th previous/next similar field
- (cond
- ((if (eq direction 'previous)
- (re-search-backward matching-entry (point-min) t arg)
- (re-search-forward matching-entry (point-max) t arg))
- ;; Found a matching field. Remember boundaries.
- (setq bibtex-pop-previous-search-point (match-beginning 0))
- (setq bibtex-pop-next-search-point (match-end 0))
- (setq new-text
- (buffer-substring-no-properties
- (match-beginning bibtex-text-in-field)
- (match-end bibtex-text-in-field)))
- ;; change delimiters, if any changes needed
- (let ((start 0)
- old-open
- new-open
- old-close
- new-close)
- (if (equal bibtex-field-left-delimiter "{")
- (setq old-open ?\"
- new-open ?\{
- old-close ?\"
- new-close ?\})
- (setq old-open ?\{
- new-open ?\"
- old-close ?\}
- new-close ?\"))
- (while (string-match bibtex-field-string new-text start)
- (let ((beg (match-beginning 0))
- (end (1- (match-end 0))))
- (if (and
- (eq (aref new-text beg) old-open)
- (eq (aref new-text end) old-close))
- (progn
- (aset new-text beg new-open)
- (aset new-text end new-close))))
- (setq start (match-end 0))))
- (bibtex-flash-head)
- ;; Go back to where we started, delete old text, and pop new.
- (goto-char stop-old-text)
- (delete-region start-old-text stop-old-text)
- (insert new-text))
- (t
- ;; search failed
- (error (concat "No "
- (if (eq direction 'previous)
- "previous"
- "next")
- " matching BibTeX field.")))))))
- (let (bibtex-help-message)
- (bibtex-find-text nil))
- (setq this-command 'bibtex-pop))
-
-(defun bibtex-pop-previous (arg)
- "Replace text of current field with the text of similar field in previous entry.
-With arg, goes up ARG entries. Repeated, goes up so many times. May be
-intermixed with \\[bibtex-pop-next] (bibtex-pop-next)."
- (interactive "p")
- (bibtex-pop arg 'previous))
-
-(defun bibtex-pop-next (arg)
- "Replace text of current field with the text of similar field in next entry.
-With arg, goes down ARG entries. Repeated, goes down so many times. May be
-intermixed with \\[bibtex-pop-previous] (bibtex-pop-previous)."
- (interactive "p")
- (bibtex-pop arg 'next))
-
-(defun bibtex-clean-entry (&optional arg)
- "Finish editing the current BibTeX entry and clean it up.
-For all optional fields of current BibTeX entry: if empty, kill the
-whole field; otherwise, remove the \"OPT\" string in the name; if text
-numerical, remove double-quotes. For all mandatory fields: if empty,
-signal error. If label of entry is empty or a prefix argument was
-given, calculate a new entry label."
- (interactive "P")
- (bibtex-beginning-of-entry)
- (let ((start (point))
- crossref-there)
- (save-restriction
- (narrow-to-region start (save-excursion (bibtex-end-of-entry) (point)))
- (while (and
- (re-search-forward bibtex-field (point-max) t 1)
- (not crossref-there))
- ;; determine if reference has crossref entry
- (let ((begin-name (match-beginning bibtex-name-in-field))
- (begin-text (match-beginning bibtex-text-in-field)))
- (goto-char begin-name)
- (if (looking-at "\\(OPTcrossref\\)\\|\\(crossref\\)")
- (progn
- (goto-char begin-text)
- (if (not (looking-at "\\(\"\"\\)\\|\\({}\\)"))
- (setq crossref-there t))))))
- (bibtex-enclosing-reference-maybe-empty-head)
- (re-search-forward bibtex-reference-type)
- (let ((begin-type (1+ (match-beginning 0)))
- (end-type (match-end 0)))
- (goto-char start)
- (while (re-search-forward bibtex-field (point-max) t 1)
- (let ((begin-field (match-beginning 0))
- (end-field (match-end 0))
- (begin-name (match-beginning bibtex-name-in-field))
- (end-name (match-end bibtex-name-in-field))
- (begin-text (match-beginning bibtex-text-in-field))
- (end-text (match-end bibtex-text-in-field))
- )
- (goto-char begin-name)
- (cond ((and
- (looking-at "OPT")
- bibtex-clean-entry-zap-empty-opts)
- (goto-char begin-text)
- (if (looking-at "\\(\"\"\\)\\|\\({}\\)")
- ;; empty: delete whole field if really optional
- ;; (missing crossref handled) or complain
- (if (and
- (not crossref-there)
- (assoc
- (downcase
- (buffer-substring-no-properties
- (+ (length "OPT") begin-name) end-name))
- (car (car (cdr
- (assoc-ignore-case
- (buffer-substring-no-properties
- begin-type end-type)
- bibtex-entry-field-alist))))))
- ;; field is not really optional
- (progn
- (goto-char begin-name)
- (delete-char (length "OPT"))
- ;; make field non-OPT
- (search-forward "=")
- (delete-horizontal-space)
- (indent-to-column bibtex-text-alignment)
- (forward-char)
- ;; and loop to go through next test
- (error "Mandatory field ``%s'' is empty"
- (buffer-substring-no-properties
- begin-name
- end-name)))
- ;; field is optional
- (delete-region begin-field end-field))
- ;; otherwise: not empty, delete "OPT"
- (goto-char begin-name)
- (delete-char (length "OPT"))
- (progn
- ;; fixup alignment. [alarson:19920309.2047CST]
- (search-forward "=")
- (delete-horizontal-space)
- (indent-to-column bibtex-text-alignment))
- (goto-char begin-field)
- ;; and loop to go through next test
- ))
- (t
- (goto-char begin-text)
- (cond ((looking-at "\\(\"[0-9]+\"\\)\\|\\({[0-9]+}\\)")
- ;; if numerical,
- (goto-char end-text)
- (delete-char -1)
- (goto-char begin-text)
- (delete-char 1)
- ;; delete enclosing delimiters
- (goto-char end-field)
- ;; go to end for next search
- (forward-char -2)
- ;; to compensate for the 2 delimiters deleted
- )
- ((looking-at "\\(\"\"\\)\\|\\({}\\)")
- ;; if empty field, complain
- (forward-char 1)
- (if (not (or (equal (buffer-substring-no-properties
- begin-name
- (+ begin-name 3))
- "OPT")
- (equal (buffer-substring-no-properties
- begin-name
- (+ begin-name 3))
- "opt")))
- (error "Mandatory field ``%s'' is empty"
- (buffer-substring-no-properties
- begin-name end-name))))
- (t
- (goto-char end-field)))))))))
- (goto-char start)
- (bibtex-end-of-entry))
- (let* ((eob (progn
- (bibtex-end-of-entry)
- (point)))
- (key (progn
- (bibtex-beginning-of-entry)
- (if (re-search-forward
- bibtex-reference-head eob t)
- (buffer-substring-no-properties
- (match-beginning bibtex-key-in-head)
- (match-end bibtex-key-in-head))))))
- (if (or
- arg
- (not key))
- (progn
- (let ((autokey
- (if bibtex-autokey-edit-before-use
- (read-from-minibuffer "Key to use: "
- (bibtex-generate-autokey))
- (bibtex-generate-autokey))))
- (bibtex-beginning-of-entry)
- (re-search-forward bibtex-reference-maybe-empty-head)
- (if (match-beginning bibtex-key-in-head)
- (delete-region (match-beginning bibtex-key-in-head)
- (match-end bibtex-key-in-head)))
- (insert autokey)
- (let ((start (progn
- (bibtex-beginning-of-entry)
- (point)))
- (end (progn
- (bibtex-end-of-entry)
- (re-search-forward "^@" nil 'move)
- (beginning-of-line)
- (point)))
- last-command)
- (kill-region start end)
- (let ((success
- (or
- (not bibtex-maintain-sorted-entries)
- (bibtex-find-entry-location autokey t))))
- (yank)
- (setq kill-ring (cdr kill-ring))
- (forward-char -1)
- (bibtex-beginning-of-entry)
- (re-search-forward bibtex-reference-head)
- (if (not success)
- (error
- "New inserted reference may be a duplicate."))))))))
- (save-excursion
- (let ((start (progn (bibtex-beginning-of-entry) (point)))
- (end (progn (bibtex-end-of-entry) (point))))
- (save-restriction
- (narrow-to-region start end)
- (bibtex-parse-keys t)))))
-
-(defun bibtex-complete-string ()
- "Complete word fragment before point to longest prefix of a defined string.
-If point is not after the part of a word, all strings are listed."
- (interactive "*")
- (let* ((end (point))
- (beg (save-excursion
- (re-search-backward "[ \t{\"]")
- (forward-char 1)
- (point)))
- (part-of-word (buffer-substring-no-properties beg end))
- (string-list (copy-sequence bibtex-completion-candidates))
- (case-fold-search t)
- (completion (save-excursion
- (while (re-search-backward
- bibtex-string (point-min) t)
- (setq string-list
- (cons
- (list
- (buffer-substring-no-properties
- (match-beginning bibtex-key-in-string)
- (match-end bibtex-key-in-string)))
- string-list)))
- (setq string-list
- (sort string-list
- (lambda(x y)
- (string-lessp
- (car x)
- (car y)))))
- (try-completion part-of-word string-list))))
- (cond ((eq completion t)
- ;; remove double-quotes or braces if field is no concatenation
- (save-excursion
- (bibtex-inside-field)
- (bibtex-enclosing-field)
- (let ((end (match-end bibtex-text-in-field)))
- (goto-char (match-beginning bibtex-text-in-field))
- (if (and
- (looking-at bibtex-field-string)
- (equal (match-end 0) end))
- (bibtex-remove-double-quotes-or-braces)))))
- ((null completion)
- (error "Can't find completion for \"%s\"" part-of-word))
- ((not (string= part-of-word completion))
- (delete-region beg end)
- (insert completion)
- (if (assoc completion string-list)
- ;; remove double-quotes or braces if field is no concatenation
- (save-excursion
- (bibtex-inside-field)
- (bibtex-enclosing-field)
- (let ((end (match-end bibtex-text-in-field)))
- (goto-char (match-beginning bibtex-text-in-field))
- (if (and
- (looking-at bibtex-field-string)
- (equal (match-end 0) end))
- (bibtex-remove-double-quotes-or-braces))))))
- (t
- (message "Making completion list...")
- (let ((list (all-completions part-of-word string-list)))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list list)))
- (message "Making completion list...done")))))
-
-(defun bibtex-Article ()
- (interactive)
- (bibtex-entry "Article"))
-
-(defun bibtex-Book ()
- (interactive)
- (bibtex-entry "Book"))
-
-(defun bibtex-Booklet ()
- (interactive)
- (bibtex-entry "Booklet"))
-
-(defun bibtex-InBook ()
- (interactive)
- (bibtex-entry "InBook"))
-
-(defun bibtex-InCollection ()
- (interactive)
- (bibtex-entry "InCollection"))
-
-(defun bibtex-InProceedings ()
- (interactive)
- (bibtex-entry "InProceedings"))
-
-(defun bibtex-Manual ()
- (interactive)
- (bibtex-entry "Manual"))
-
-(defun bibtex-MastersThesis ()
- (interactive)
- (bibtex-entry "MastersThesis"))
-
-(defun bibtex-Misc ()
- (interactive)
- (bibtex-entry "Misc"))
-
-(defun bibtex-PhdThesis ()
- (interactive)
- (bibtex-entry "PhdThesis"))
-
-(defun bibtex-Proceedings ()
- (interactive)
- (bibtex-entry "Proceedings"))
-
-(defun bibtex-TechReport ()
- (interactive)
- (bibtex-entry "TechReport"))
-
-(defun bibtex-Unpublished ()
- (interactive)
- (bibtex-entry "Unpublished"))
-
-(defun bibtex-string ()
- (interactive)
- (bibtex-move-outside-of-entry)
- (insert
- (concat
- "@string{ = "
- bibtex-field-left-delimiter
- bibtex-field-right-delimiter
- "}\n"))
- (forward-line -1)
- (forward-char 8))
-
-(defun bibtex-preamble ()
- (interactive)
- (bibtex-move-outside-of-entry)
- (insert "@Preamble{}\n")
- (forward-line -1)
- (forward-char 10))
-
-
-;; Make BibTeX a Feature
-
-(provide 'bibtex)
-
-;;; bibtex.el ends here
diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el
deleted file mode 100644
index 17237a4a235..00000000000
--- a/lisp/textmodes/fill.el
+++ /dev/null
@@ -1,858 +0,0 @@
-;;; fill.el --- fill commands for Emacs
-
-;; Copyright (C) 1985, 86, 92, 94, 95, 1996 Free Software Foundation, Inc.
-
-;; Keywords: wp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; All the commands for filling text. These are documented in the Emacs
-;; manual.
-
-;;; Code:
-
-(defvar 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.
-A value of nil means that any change in indentation starts a new paragraph.")
-
-(defvar sentence-end-double-space t
- "*Non-nil means a single space does not end a sentence.")
-
-(defvar colon-double-space nil
- "*Non-nil means put two spaces after a colon when filling.")
-
-(defvar fill-paragraph-function nil
- "Mode-specific function to fill a paragraph, or nil if there is none.
-If the function returns nil, then `fill-paragraph' does its normal work.")
-
-(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 (move-to-left-margin) (point))
- (point)))
- (if (equal fill-prefix "")
- (setq fill-prefix nil))
- (if fill-prefix
- (message "fill-prefix: \"%s\"" fill-prefix)
- (message "fill-prefix cancelled")))
-
-(defvar adaptive-fill-mode t
- "*Non-nil means determine a paragraph's fill prefix from its text.")
-
-(defvar 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. If the paragraph has just one line, the indentation
-is taken from that line.")
-
-(defvar adaptive-fill-function nil
- "*Function to call to choose a fill prefix for a paragraph.
-This function is used when `adaptive-fill-regexp' does not match.")
-
-(defun current-fill-column ()
- "Return the fill-column to use for this line.
-The fill-column to use for a buffer is stored in the variable `fill-column',
-but can be locally modified by the `right-margin' text property, which is
-subtracted from `fill-column'.
-
-The fill column to use for a line is the first column at which the column
-number equals or exceeds the local fill-column - right-margin difference."
- (save-excursion
- (if fill-column
- (let* ((here (progn (beginning-of-line) (point)))
- (here-col 0)
- (eol (progn (end-of-line) (point)))
- margin fill-col change col)
- ;; Look separately at each region of line with a different right-margin.
- (while (and (setq margin (get-text-property here 'right-margin)
- fill-col (- fill-column (or margin 0))
- change (text-property-not-all
- here eol 'right-margin margin))
- (progn (goto-char (1- change))
- (setq col (current-column))
- (< col fill-col)))
- (setq here change
- here-col col))
- (max here-col fill-col)))))
-
-(defun canonically-space-region (beg end)
- "Remove extra spaces between words in region.
-Leave one space between words, two at end of sentences or after colons
-(depending on values of `sentence-end-double-space' and `colon-double-space').
-Remove indentation from each line."
- (interactive "r")
- (save-excursion
- (goto-char beg)
- ;; Nuke tabs; they get screwed up in a fill.
- ;; This is quick, but loses when a tab follows the end of a sentence.
- ;; Actually, it is difficult to tell that from "Mr.\tSmith".
- ;; Blame the typist.
- (subst-char-in-region beg end ?\t ?\ )
- (while (and (< (point) end)
- (re-search-forward " *" end t))
- (delete-region
- (+ (match-beginning 0)
- ;; Determine number of spaces to leave:
- (save-excursion
- (skip-chars-backward " ]})\"'")
- (cond ((and sentence-end-double-space
- (memq (preceding-char) '(?. ?? ?!))) 2)
- ((and colon-double-space
- (= (preceding-char) ?:)) 2)
- ((char-equal (preceding-char) ?\n) 0)
- (t 1))))
- (match-end 0)))
- ;; Make sure sentences ending at end of line get an extra space.
- ;; loses on split abbrevs ("Mr.\nSmith")
- (goto-char beg)
- (while (and (< (point) end)
- (re-search-forward "[.?!][])}\"']*$" end t))
- ;; We insert before markers in case a caller such as
- ;; do-auto-fill has done a save-excursion with point at the end
- ;; of the line and wants it to stay at the end of the line.
- (insert-before-markers-and-inherit ? ))))
-
-(defun fill-context-prefix (from to &optional first-line-regexp)
- "Compute a fill prefix from the text between FROM and TO.
-This uses the variables `adaptive-fill-prefix' and `adaptive-fill-function'.
-If FIRST-LINE-REGEXP is non-nil, then when taking a prefix from the
-first line, insist it must match FIRST-LINE-REGEXP."
- (save-excursion
- (goto-char from)
- (if (eolp) (forward-line 1))
- ;; Move to the second line unless there is just one.
- (let ((firstline (point))
- ;; Non-nil if we are on the second line.
- at-second
- result)
- (forward-line 1)
- (if (>= (point) to)
- (goto-char firstline)
- (setq at-second t))
- (move-to-left-margin)
- (let ((start (point)))
- (setq result
- (if (not (looking-at paragraph-start))
- (cond ((and adaptive-fill-regexp (looking-at adaptive-fill-regexp))
- (buffer-substring-no-properties start (match-end 0)))
- (adaptive-fill-function (funcall adaptive-fill-function)))))
- (and result
- (or at-second
- (null first-line-regexp)
- (string-match first-line-regexp result))
- result)))))
-
-(defun fill-region-as-paragraph (from to &optional justify
- nosqueeze squeeze-after)
- "Fill the region as one paragraph.
-It removes any paragraph breaks in the region and extra newlines at the end,
-indents and fills lines between the margins given by the
-`current-left-margin' and `current-fill-column' functions.
-It leaves point at the beginning of the line following the paragraph.
-
-Normally performs justification according to the `current-justification'
-function, but with a prefix arg, does full justification instead.
-
-From a program, optional third arg JUSTIFY can specify any type of
-justification. Fourth arg NOSQUEEZE non-nil means not to make spaces
-between words canonical before filling. Fifth arg SQUEEZE-AFTER, if non-nil,
-means don't canonicalize spaces before that position.
-
-If `sentence-end-double-space' is non-nil, then period followed by one
-space does not end a sentence, so don't break a line there."
- (interactive (list (region-beginning) (region-end)
- (if current-prefix-arg 'full)))
- ;; Arrange for undoing the fill to restore point.
- (if (and buffer-undo-list (not (eq buffer-undo-list t)))
- (setq buffer-undo-list (cons (point) buffer-undo-list)))
-
- ;; Make sure "to" is the endpoint.
- (goto-char (min from to))
- (setq to (max from to))
- ;; Ignore blank lines at beginning of region.
- (skip-chars-forward " \t\n")
-
- (let ((from-plus-indent (point))
- (oneleft nil))
-
- (beginning-of-line)
- (setq from (point))
-
- ;; Delete all but one soft newline at end of region.
- ;; And leave TO before that one.
- (goto-char to)
- (while (and (> (point) from) (eq ?\n (char-after (1- (point)))))
- (if (and oneleft
- (not (and use-hard-newlines
- (get-text-property (1- (point)) 'hard))))
- (delete-backward-char 1)
- (backward-char 1)
- (setq oneleft t)))
- (setq to (point))
-
- ;; If there was no newline, and there is text in the paragraph, then
- ;; create a newline.
- (if (and (not oneleft) (> to from-plus-indent))
- (newline))
- (goto-char from-plus-indent))
-
- (if (not (> to (point)))
- nil ; There is no paragraph, only whitespace: exit now.
-
- (or justify (setq justify (current-justification)))
-
- ;; 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 (and adaptive-fill-mode
- (or (null fill-prefix) (string= fill-prefix "")))
- (setq fill-prefix (fill-context-prefix from to)))
-
- (save-restriction
- (goto-char from)
- (beginning-of-line)
- (narrow-to-region (point) to)
-
- (if (not justify) ; filling disabled: just check indentation
- (progn
- (goto-char from)
- (while (not (eobp))
- (if (and (not (eolp))
- (< (current-indentation) (current-left-margin)))
- (indent-to-left-margin))
- (forward-line 1)))
-
- (if use-hard-newlines
- (remove-text-properties from (point-max) '(hard nil)))
- ;; Make sure first line is indented (at least) to left margin...
- (if (or (memq justify '(right center))
- (< (current-indentation) (current-left-margin)))
- (indent-to-left-margin))
- ;; Delete the fill prefix from every line except the first.
- ;; The first line may not even have a fill prefix.
- (goto-char from)
- (let ((fpre (and fill-prefix (not (equal fill-prefix ""))
- (concat "[ \t]*"
- (regexp-quote fill-prefix)
- "[ \t]*"))))
- (and fpre
- (progn
- (if (>= (+ (current-left-margin) (length fill-prefix))
- (current-fill-column))
- (error "fill-prefix too long for specified width"))
- (goto-char from)
- (forward-line 1)
- (while (not (eobp))
- (if (looking-at fpre)
- (delete-region (point) (match-end 0)))
- (forward-line 1))
- (goto-char from)
- (if (looking-at fpre)
- (goto-char (match-end 0)))
- (setq from (point)))))
- ;; Remove indentation from lines other than the first.
- (beginning-of-line 2)
- (indent-region (point) (point-max) 0)
- (goto-char from)
-
- ;; FROM, and point, are 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")
- (while (re-search-forward "[.?!][])}\"']*$" nil t)
- (or (eobp) (insert-and-inherit ?\ )))
- (goto-char from)
- (skip-chars-forward " \t")
- ;; Then change all newlines to spaces.
- (subst-char-in-region from (point-max) ?\n ?\ )
- (if (and nosqueeze (not (eq justify 'full)))
- nil
- (canonically-space-region (or squeeze-after (point)) (point-max))
- (goto-char (point-max))
- (delete-horizontal-space)
- (insert-and-inherit " "))
- (goto-char (point-min))
-
- ;; This is the actual filling loop.
- (let ((prefixcol 0) linebeg)
- (while (not (eobp))
- (setq linebeg (point))
- (move-to-column (1+ (current-fill-column)))
- (if (eobp)
- (or nosqueeze (delete-horizontal-space))
- ;; Move back to start of word.
- (skip-chars-backward "^ \n" linebeg)
- ;; Don't break after a period followed by just one space.
- ;; Move back to the previous place to break.
- ;; The reason is that if a period ends up at the end of a line,
- ;; further fills will assume it ends a sentence.
- ;; If we now know it does not end a sentence,
- ;; avoid putting it at the end of the line.
- (if sentence-end-double-space
- (while (and (> (point) (+ linebeg 2))
- (eq (preceding-char) ?\ )
- (not (eq (following-char) ?\ ))
- (eq (char-after (- (point) 2)) ?\.))
- (forward-char -2)
- (skip-chars-backward "^ \n" linebeg)))
- ;; If the left margin and fill prefix by themselves
- ;; pass the fill-column. or if they are zero
- ;; but we have no room for even one word,
- ;; keep at least one word anyway.
- ;; This handles ALL BUT the first line of the paragraph.
- (if (if (zerop prefixcol)
- (save-excursion
- (skip-chars-backward " \t" linebeg)
- (bolp))
- (>= prefixcol (current-column)))
- ;; Ok, skip at least one word.
- ;; Meanwhile, don't stop at a period followed by one space.
- (let ((first t))
- (move-to-column prefixcol)
- (while (and (not (eobp))
- (or first
- (and (not (bobp))
- sentence-end-double-space
- (save-excursion (forward-char -1)
- (and (looking-at "\\. ")
- (not (looking-at "\\. ")))))))
- (skip-chars-forward " \t")
- (skip-chars-forward "^ \n\t")
- (setq first nil)))
- ;; Normally, move back over the single space between the words.
- (forward-char -1))
- ;; If the left margin and fill prefix by themselves
- ;; pass the fill-column, keep at least one word.
- ;; This handles the first line of the paragraph.
- (if (and (zerop prefixcol)
- (let ((fill-point (point)) nchars)
- (save-excursion
- (move-to-left-margin)
- (setq nchars (- fill-point (point)))
- (or (< nchars 0)
- (and fill-prefix
- (< nchars (length fill-prefix))
- (string= (buffer-substring (point) fill-point)
- (substring fill-prefix 0 nchars)))))))
- ;; Ok, skip at least one word. But
- ;; don't stop at a period followed by just one space.
- (let ((first t))
- (while (and (not (eobp))
- (or first
- (and (not (bobp))
- sentence-end-double-space
- (save-excursion (forward-char -1)
- (and (looking-at "\\. ")
- (not (looking-at "\\. ")))))))
- (skip-chars-forward " \t")
- (skip-chars-forward "^ \t\n")
- (setq first nil))))
- ;; Check again to see if we got to the end of the paragraph.
- (if (save-excursion (skip-chars-forward " \t") (eobp))
- (or nosqueeze (delete-horizontal-space))
- ;; Replace whitespace here with one newline, then indent to left
- ;; margin.
- (skip-chars-backward " \t")
- (insert ?\n)
- ;; Give newline the properties of the space(s) it replaces
- (set-text-properties (1- (point)) (point)
- (text-properties-at (point)))
- (indent-to-left-margin)
- ;; Insert the fill prefix after indentation.
- ;; Set prefixcol so whitespace in the prefix won't get lost.
- (and fill-prefix (not (equal fill-prefix ""))
- (progn
- (insert-and-inherit fill-prefix)
- (setq prefixcol (current-column))))))
- ;; Justify the line just ended, if desired.
- (if justify
- (if (eobp)
- (justify-current-line justify t t)
- (forward-line -1)
- (justify-current-line justify nil t)
- (forward-line 1))))))
- ;; Leave point after final newline.
- (goto-char (point-max)))
- (forward-char 1))))
-
-(defun fill-paragraph (arg)
- "Fill paragraph at or after point. Prefix arg means justify as well.
-If `sentence-end-double-space' is non-nil, then period followed by one
-space does not end a sentence, so don't break a line there.
-
-If `fill-paragraph-function' is non-nil, we call it (passing our
-argument to it), and if it returns non-nil, we simply return its value."
- (interactive (list (if current-prefix-arg 'full)))
- (or (and fill-paragraph-function
- (let ((function fill-paragraph-function)
- fill-paragraph-function)
- (funcall function arg)))
- (let ((before (point)))
- (save-excursion
- (forward-paragraph)
- (or (bolp) (newline 1))
- (let ((end (point))
- (beg (progn (backward-paragraph) (point))))
- (goto-char before)
- (if use-hard-newlines
- ;; Can't use fill-region-as-paragraph, since this paragraph may
- ;; still contain hard newlines. See fill-region.
- (fill-region beg end arg)
- (fill-region-as-paragraph beg end arg)))))))
-
-(defun fill-region (from to &optional justify nosqueeze to-eop)
- "Fill each of the paragraphs in the region.
-Prefix arg (non-nil third arg, if called from program) means justify as well.
-
-Noninteractively, fourth arg NOSQUEEZE non-nil means to leave
-whitespace other than line breaks untouched, and fifth arg TO-EOP
-non-nil means to keep filling to the end of the paragraph (or next
-hard newline, if `use-hard-newlines' is on).
-
-If `sentence-end-double-space' is non-nil, then period followed by one
-space does not end a sentence, so don't break a line there."
- (interactive (list (region-beginning) (region-end)
- (if current-prefix-arg 'full)))
- (let (end beg)
- (save-restriction
- (goto-char (max from to))
- (if to-eop
- (progn (skip-chars-backward "\n")
- (forward-paragraph)))
- (setq end (point))
- (goto-char (setq beg (min from to)))
- (beginning-of-line)
- (narrow-to-region (point) end)
- (while (not (eobp))
- (let ((initial (point))
- end)
- ;; If using hard newlines, break at every one for filling
- ;; purposes rather than using paragraph breaks.
- (if use-hard-newlines
- (progn
- (while (and (setq end (text-property-any (point) (point-max)
- 'hard t))
- (not (= ?\n (char-after end)))
- (not (= end (point-max))))
- (goto-char (1+ end)))
- (setq end (if end (min (point-max) (1+ end)) (point-max)))
- (goto-char initial))
- (forward-paragraph 1)
- (setq end (point))
- (forward-paragraph -1))
- (if (< (point) beg)
- (goto-char beg))
- (if (>= (point) initial)
- (fill-region-as-paragraph (point) end justify nosqueeze)
- (goto-char end)))))))
-
-
-(defvar default-justification 'left
- "*Method of justifying text not otherwise specified.
-Possible values are `left', `right', `full', `center', or `none'.
-The requested kind of justification is done whenever lines are filled.
-The `justification' text-property can locally override this variable.
-This variable automatically becomes buffer-local when set in any fashion.")
-(make-variable-buffer-local 'default-justification)
-
-(defun current-justification ()
- "How should we justify this line?
-This returns the value of the text-property `justification',
-or the variable `default-justification' if there is no text-property.
-However, it returns nil rather than `none' to mean \"don't justify\"."
- (let ((j (or (get-text-property
- ;; Make sure we're looking at paragraph body.
- (save-excursion (skip-chars-forward " \t")
- (if (and (eobp) (not (bobp)))
- (1- (point)) (point)))
- 'justification)
- default-justification)))
- (if (eq 'none j)
- nil
- j)))
-
-(defun set-justification (begin end value &optional whole-par)
- "Set the region's justification style.
-The kind of justification to use is prompted for.
-If the mark is not active, this command operates on the current paragraph.
-If the mark is active, the region is used. However, if the beginning and end
-of the region are not at paragraph breaks, they are moved to the beginning and
-end of the paragraphs they are in.
-If `use-hard-newlines' is true, all hard newlines are taken to be paragraph
-breaks.
-
-When calling from a program, operates just on region between BEGIN and END,
-unless optional fourth arg WHOLE-PAR is non-nil. In that case bounds are
-extended to include entire paragraphs as in the interactive command."
- (interactive (list (if mark-active (region-beginning) (point))
- (if mark-active (region-end) (point))
- (let ((s (completing-read
- "Set justification to: "
- '(("left") ("right") ("full")
- ("center") ("none"))
- nil t)))
- (if (equal s "") (error ""))
- (intern s))
- t))
- (save-excursion
- (save-restriction
- (if whole-par
- (let ((paragraph-start (if use-hard-newlines "." paragraph-start))
- (paragraph-ignore-fill-prefix (if use-hard-newlines t
- paragraph-ignore-fill-prefix)))
- (goto-char begin)
- (while (and (bolp) (not (eobp))) (forward-char 1))
- (backward-paragraph)
- (setq begin (point))
- (goto-char end)
- (skip-chars-backward " \t\n" begin)
- (forward-paragraph)
- (setq end (point))))
-
- (narrow-to-region (point-min) end)
- (unjustify-region begin (point-max))
- (put-text-property begin (point-max) 'justification value)
- (fill-region begin (point-max) nil t))))
-
-(defun set-justification-none (b e)
- "Disable automatic filling for paragraphs in the region.
-If the mark is not active, this applies to the current paragraph."
- (interactive (list (if mark-active (region-beginning) (point))
- (if mark-active (region-end) (point))))
- (set-justification b e 'none t))
-
-(defun set-justification-left (b e)
- "Make paragraphs in the region left-justified.
-This is usually the default, but see the variable `default-justification'.
-If the mark is not active, this applies to the current paragraph."
- (interactive (list (if mark-active (region-beginning) (point))
- (if mark-active (region-end) (point))))
- (set-justification b e 'left t))
-
-(defun set-justification-right (b e)
- "Make paragraphs in the region right-justified:
-Flush at the right margin and ragged on the left.
-If the mark is not active, this applies to the current paragraph."
- (interactive (list (if mark-active (region-beginning) (point))
- (if mark-active (region-end) (point))))
- (set-justification b e 'right t))
-
-(defun set-justification-full (b e)
- "Make paragraphs in the region fully justified:
-This makes lines flush on both margins by inserting spaces between words.
-If the mark is not active, this applies to the current paragraph."
- (interactive (list (if mark-active (region-beginning) (point))
- (if mark-active (region-end) (point))))
- (set-justification b e 'full t))
-
-(defun set-justification-center (b e)
- "Make paragraphs in the region centered.
-If the mark is not active, this applies to the current paragraph."
- (interactive (list (if mark-active (region-beginning) (point))
- (if mark-active (region-end) (point))))
- (set-justification b e 'center t))
-
-;; A line has up to six parts:
-;;
-;; >>> hello.
-;; [Indent-1][FP][ Indent-2 ][text][trailing whitespace][newline]
-;;
-;; "Indent-1" is the left-margin indentation; normally it ends at column
-;; given by the `current-left-margin' function.
-;; "FP" is the fill-prefix. It can be any string, including whitespace.
-;; "Indent-2" is added to justify a line if the `current-justification' is
-;; `center' or `right'. In `left' and `full' justification regions, any
-;; whitespace there is part of the line's text, and should not be changed.
-;; Trailing whitespace is not counted as part of the line length when
-;; center- or right-justifying.
-;;
-;; All parts of the line are optional, although the final newline can
-;; only be missing on the last line of the buffer.
-
-(defun justify-current-line (&optional how eop nosqueeze)
- "Do some kind of justification on this line.
-Normally does full justification: adds spaces to the line to make it end at
-the column given by `current-fill-column'.
-Optional first argument HOW specifies alternate type of justification:
-it can be `left', `right', `full', `center', or `none'.
-If HOW is t, will justify however the `current-justification' function says to.
-If HOW is nil or missing, full justification is done by default.
-Second arg EOP non-nil means that this is the last line of the paragraph, so
-it will not be stretched by full justification.
-Third arg NOSQUEEZE non-nil means to leave interior whitespace unchanged,
-otherwise it is made canonical."
- (interactive)
- (if (eq t how) (setq how (or (current-justification) 'none))
- (if (null how) (setq how 'full)
- (or (memq how '(none left right center))
- (setq how 'full))))
- (or (memq how '(none left)) ; No action required for these.
- (let ((fc (current-fill-column))
- (pos (point-marker))
- fp-end ; point at end of fill prefix
- beg ; point at beginning of line's text
- end ; point at end of line's text
- indent ; column of `beg'
- endcol ; column of `end'
- ncols) ; new indent point or offset
- (end-of-line)
- ;; Check if this is the last line of the paragraph.
- (if (and use-hard-newlines (null eop)
- (get-text-property (point) 'hard))
- (setq eop t))
- (skip-chars-backward " \t")
- ;; Quick exit if it appears to be properly justified already
- ;; or there is no text.
- (if (or (bolp)
- (and (memq how '(full right))
- (= (current-column) fc)))
- nil
- (setq end (point))
- (beginning-of-line)
- (skip-chars-forward " \t")
- ;; Skip over fill-prefix.
- (if (and fill-prefix
- (not (string-equal fill-prefix ""))
- (equal fill-prefix
- (buffer-substring
- (point) (min (point-max) (+ (length fill-prefix)
- (point))))))
- (forward-char (length fill-prefix))
- (if (and adaptive-fill-mode
- (looking-at adaptive-fill-regexp))
- (goto-char (match-end 0))))
- (setq fp-end (point))
- (skip-chars-forward " \t")
- ;; This is beginning of the line's text.
- (setq indent (current-column))
- (setq beg (point))
- (goto-char end)
- (setq endcol (current-column))
-
- ;; HOW can't be null or left--we would have exited already
- (cond ((eq 'right how)
- (setq ncols (- fc endcol))
- (if (< ncols 0)
- ;; Need to remove some indentation
- (delete-region
- (progn (goto-char fp-end)
- (if (< (current-column) (+ indent ncols))
- (move-to-column (+ indent ncols) t))
- (point))
- (progn (move-to-column indent) (point)))
- ;; Need to add some
- (goto-char beg)
- (indent-to (+ indent ncols))
- ;; If point was at beginning of text, keep it there.
- (if (= beg pos)
- (move-marker pos (point)))))
-
- ((eq 'center how)
- ;; Figure out how much indentation is needed
- (setq ncols (+ (current-left-margin)
- (/ (- fc (current-left-margin) ;avail. space
- (- endcol indent)) ;text width
- 2)))
- (if (< ncols indent)
- ;; Have too much indentation - remove some
- (delete-region
- (progn (goto-char fp-end)
- (if (< (current-column) ncols)
- (move-to-column ncols t))
- (point))
- (progn (move-to-column indent) (point)))
- ;; Have too little - add some
- (goto-char beg)
- (indent-to ncols)
- ;; If point was at beginning of text, keep it there.
- (if (= beg pos)
- (move-marker pos (point)))))
-
- ((eq 'full how)
- ;; Insert extra spaces between words to justify line
- (save-restriction
- (narrow-to-region beg end)
- (or nosqueeze
- (canonically-space-region beg end))
- (goto-char (point-max))
- (setq ncols (- fc endcol))
- ;; Ncols is number of additional spaces needed
- (if (> ncols 0)
- (if (and (not eop)
- (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-and-inherit " ")
- (skip-chars-backward " ")
- (setq ncols (1- ncols)))))))
- (t (error "Unknown justification value"))))
- (goto-char pos)
- (move-marker pos nil)))
- nil)
-
-(defun unjustify-current-line ()
- "Remove justification whitespace from current line.
-If the line is centered or right-justified, this function removes any
-indentation past the left margin. If the line is full-justified, it removes
-extra spaces between words. It does nothing in other justification modes."
- (let ((justify (current-justification)))
- (cond ((eq 'left justify) nil)
- ((eq nil justify) nil)
- ((eq 'full justify) ; full justify: remove extra spaces
- (beginning-of-line-text)
- (canonically-space-region
- (point) (save-excursion (end-of-line) (point))))
- ((memq justify '(center right))
- (save-excursion
- (move-to-left-margin nil t)
- ;; Position ourselves after any fill-prefix.
- (if (and fill-prefix
- (not (string-equal fill-prefix ""))
- (equal fill-prefix
- (buffer-substring
- (point) (min (point-max) (+ (length fill-prefix)
- (point))))))
- (forward-char (length fill-prefix)))
- (delete-region (point) (progn (skip-chars-forward " \t")
- (point))))))))
-
-(defun unjustify-region (&optional begin end)
- "Remove justification whitespace from region.
-For centered or right-justified regions, this function removes any indentation
-past the left margin from each line. For full-justified lines, it removes
-extra spaces between words. It does nothing in other justification modes.
-Arguments BEGIN and END are optional; default is the whole buffer."
- (save-excursion
- (save-restriction
- (if end (narrow-to-region (point-min) end))
- (goto-char (or begin (point-min)))
- (while (not (eobp))
- (unjustify-current-line)
- (forward-line 1)))))
-
-
-(defun fill-nonuniform-paragraphs (min max &optional justifyp mailp)
- "Fill paragraphs within the region, allowing varying indentation within each.
-This command divides the region into \"paragraphs\",
-only at paragraph-separator lines, then fills each paragraph
-using as the fill prefix the smallest indentation of any line
-in the paragraph.
-
-When calling from a program, pass range to fill as first two arguments.
-
-Optional third and fourth arguments JUSTIFY and MAIL-FLAG:
-JUSTIFY to justify paragraphs (prefix arg),
-MAIL-FLAG for a mail message, i. e. don't fill header lines."
- (interactive (list (region-beginning) (region-end)
- (if current-prefix-arg 'full)))
- (let ((fill-individual-varying-indent t))
- (fill-individual-paragraphs min max justifyp mailp)))
-
-(defun fill-individual-paragraphs (min max &optional justify mailp)
- "Fill paragraphs of uniform indentation within the region.
-This command divides the region into \"paragraphs\",
-treating every change in indentation level as a paragraph boundary,
-then fills each paragraph using its indentation level as the fill prefix.
-
-When calling from a program, pass range to fill as first two arguments.
-
-Optional third and fourth arguments JUSTIFY and MAIL-FLAG:
-JUSTIFY to justify paragraphs (prefix arg),
-MAIL-FLAG for a mail message, i. e. don't fill header lines."
- (interactive (list (region-beginning) (region-end)
- (if current-prefix-arg 'full)))
- (save-restriction
- (save-excursion
- (goto-char min)
- (beginning-of-line)
- (narrow-to-region (point) max)
- (if mailp
- (while (and (not (eobp))
- (or (looking-at "[ \t]*[^ \t\n]+:")
- (looking-at "[ \t]*$")))
- (if (looking-at "[ \t]*[^ \t\n]+:")
- (search-forward "\n\n" nil 'move)
- (forward-line 1))))
- (narrow-to-region (point) max)
- ;; Loop over paragraphs.
- (while (progn (skip-chars-forward " \t\n") (not (eobp)))
- (move-to-left-margin)
- (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
- (if (and adaptive-fill-mode adaptive-fill-regexp
- (looking-at adaptive-fill-regexp))
- (match-string 0)
- (buffer-substring
- (point)
- (save-excursion (skip-chars-forward " \t")
- (point))))
- fill-prefix-regexp (regexp-quote fill-prefix)))
- (forward-line 1)
- (if (bolp)
- ;; If forward-line went past a newline,
- ;; move further to the left margin.
- (move-to-left-margin))
- ;; Now stop the loop if end of paragraph.
- (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) justify)
- (or had-newline (delete-char -1))))))))
-
-;;; fill.el ends here
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
deleted file mode 100644
index dd553fa90e7..00000000000
--- a/lisp/textmodes/ispell.el
+++ /dev/null
@@ -1,2412 +0,0 @@
-;;; ispell.el --- spell checking using Ispell
-
-;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
-
-;; Authors : Ken Stevens <k.stevens@ieee.org>
-;; Last Modified On: Tue Jun 13 12:05:28 EDT 1995
-;; Update Revision : 2.37
-;; Syntax : emacs-lisp
-;; Status : Release with 3.1.12+ ispell.
-;; Version : International Ispell Version 3.1 by Geoff Kuenning.
-;; Bug Reports : ispell-el-bugs@itcorp.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;; Note: version numbers and time stamp are not updated
-;; when this file is edited for release with GNU Emacs.
-
-;;; Commentary:
-
-;; INSTRUCTIONS
-;;
-;; This code contains a section of user-settable variables that you should
-;; inspect prior to installation. Look past the end of the history list.
-;; Set them up for your locale and the preferences of the majority of the
-;; users. Otherwise the users may need to set a number of variables
-;; themselves.
-;; You particularly may want to change the default dictionary for your
-;; country and language.
-;;
-;;
-;; To fully install this, add this file to your Emacs Lisp directory and
-;; compile it with M-X byte-compile-file. Then add the following to the
-;; appropriate init file:
-;;
-;; (autoload 'ispell-word "ispell"
-;; "Check the spelling of word in buffer." t)
-;; (global-set-key "\e$" 'ispell-word)
-;; (autoload 'ispell-region "ispell"
-;; "Check the spelling of region." t)
-;; (autoload 'ispell-buffer "ispell"
-;; "Check the spelling of buffer." t)
-;; (autoload 'ispell-complete-word "ispell"
-;; "Look up current word in dictionary and try to complete it." t)
-;; (autoload 'ispell-change-dictionary "ispell"
-;; "Change ispell dictionary." t)
-;; (autoload 'ispell-message "ispell"
-;; "Check spelling of mail message or news post.")
-;;
-;; Depending on the mail system you use, you may want to include these:
-;;
-;; (add-hook 'news-inews-hook 'ispell-message)
-;; (add-hook 'mail-send-hook 'ispell-message)
-;; (add-hook 'mh-before-send-letter-hook 'ispell-message)
-;;
-;;
-;; Ispell has a TeX parser and a nroff parser (the default).
-;; The parsing is controlled by the variable ispell-parser. Currently
-;; it is just a "toggle" between TeX and nroff, but if more parsers are
-;; added it will be updated. See the variable description for more info.
-;;
-;;
-;; TABLE OF CONTENTS
-;;
-;; ispell-word
-;; ispell-region
-;; ispell-buffer
-;; ispell-message
-;; ispell-continue
-;; ispell-complete-word
-;; ispell-complete-word-interior-frag
-;; ispell-change-dictionary
-;; ispell-kill-ispell
-;; ispell-pdict-save
-;;
-;;
-;; Commands in ispell-region:
-;; Character replacement: Replace word with choice. May query-replace.
-;; ' ': Accept word this time.
-;; 'i': Accept word and insert into private dictionary.
-;; 'a': Accept word for this session.
-;; 'A': Accept word and place in buffer-local dictionary.
-;; 'r': Replace word with typed-in value. Rechecked.
-;; 'R': Replace word with typed-in value. Query-replaced in buffer. Rechecked.
-;; '?': Show these commands
-;; 'x': Exit spelling buffer. Move cursor to original point.
-;; 'X': Exit spelling buffer. Leave cursor at the current point.
-;; 'q': Quit spelling session (Kills ispell process).
-;; 'l': Look up typed-in replacement in alternate dictionary. Wildcards okay.
-;; 'u': Like 'i', but the word is lower-cased first.
-;; 'm': Like 'i', but allows one to include dictionary completion info.
-;; 'C-l': redraws screen
-;; 'C-r': recursive edit
-;; 'C-z': suspend emacs or iconify frame
-;;
-;; Buffer-Local features:
-;; There are a number of buffer-local features that can be used to customize
-;; ispell for the current buffer. This includes language dictionaries,
-;; personal dictionaries, parsing, and local word spellings. Each of these
-;; local customizations are done either through local variables, or by
-;; including the keyword and argument(s) at the end of the buffer (usually
-;; prefixed by the comment characters). See the end of this file for
-;; examples. The local keywords and variables are:
-;;
-;; ispell-dictionary-keyword language-dictionary
-;; uses local variable ispell-local-dictionary
-;; ispell-pdict-keyword personal-dictionary
-;; uses local variable ispell-local-pdict
-;; ispell-parsing-keyword mode-arg extended-char-arg
-;; ispell-words-keyword any number of local word spellings
-;;
-;;
-;; BUGS:
-;; Highlighting in version 19 still doesn't work on tty's.
-;; On some versions of emacs, growing the minibuffer fails.
-;;
-;; HISTORY
-;;
-;; Revision 2.38 1996/5/30 ethanb@phys.washington.edu
-;; Update ispell-message for gnus 5 (news-inews-hook => message-send-hook;
-;; different header for quoted message).
-;;
-;; Revision 2.37 1995/6/13 12:05:28 stevens
-;; Removed autoload from ispell-dictionary-alist. *choices* mode-line shows
-;; misspelled word. Block skip for pgp & forwarded messages added.
-;; RMS: the autoload changes had problems and I removed them.
-;;
-;; Revision 2.36 1995/2/6 17:39:38 stevens
-;; Properly adjust screen with different ispell-choices-win-default-height
-;; settings. Skips SGML entity references.
-;;
-;; Revision 2.35 1995/1/13 14:16:46 stevens
-;; Skips SGML tags, ispell-change-dictionary fix for add-hook, assure personal
-;; dictionary is saved when called from the menu
-;;
-;; Revision 2.34 1994/12/08 13:17:41 stevens
-;; Interaction corrected to function with all 3.1 ispell versions.
-;;
-;; Revision 2.33 1994/11/24 02:31:20 stevens
-;; Repaired bug introduced in 2.32 that corrupts buffers when correcting.
-;; Improved buffer scrolling. Nondestructive buffer selections allowed.
-;;
-;; Revision 2.32 1994/10/31 21:10:08 geoff
-;; Many revisions accepted from RMS/FSF. I think (though I don't know) that
-;; this represents an 'official' version.
-;;
-;; Revision 2.31 1994/5/31 10:18:17 stevens
-;; Repaired comments. buffer-local commands executed in `ispell-word' now.
-;; German dictionary described for extended character mode. Dict messages.
-;;
-;; Revision 2.30 1994/5/20 22:18:36 stevens
-;; Continue ispell from ispell-word, C-z functionality fixed.
-;;
-;; Revision 2.29 1994/5/12 09:44:33 stevens
-;; Restored ispell-use-ptys-p, ispell-message aborts sends with interrupt.
-;; defined fn ispell
-;;
-;; Revision 2.28 1994/4/28 16:24:40 stevens
-;; Window checking when ispell-message put on gnus-inews-article-hook jwz.
-;; prefixed ispell- to highlight functions and horiz-scroll fn.
-;; Try and respect case of word in ispell-complete-word.
-;; Ignore non-char events. Ispell-use-ptys-p commented out. Lucid menu.
-;; Better interrupt handling. ispell-message improvements from Ethan.
-;;
-;; Revision 2.27
-;; version 18 explicit C-g handling disabled as it didn't work. Added
-;; ispell-extra-args for ispell customization (jwz)
-;;
-;; Revision 2.26 1994/2/15 16:11:14 stevens
-;; name changes for copyright assignment. Added word-frags in complete-word.
-;; Horizontal scroll (John Conover). Query-replace matches words now. bugs.
-;;
-;; Revision 2.25
-;; minor mods, upgraded ispell-message
-;;
-;; Revision 2.24
-;; query-replace more robust, messages, defaults, ispell-change-dict.
-;;
-;; Revision 2.23 1993/11/22 23:47:03 stevens
-;; ispell-message, Fixed highlighting, added menu-bar, fixed ispell-help, ...
-;;
-;; Revision 2.22
-;; Added 'u' command. Fixed default in ispell-local-dictionary.
-;; fixed affix rules display. Tib skipping more robust. Contributions by
-;; Per Abraham (parser selection), Denis Howe, and Eberhard Mattes.
-;;
-;; Revision 2.21 1993/06/30 14:09:04 stevens
-;; minor bugs. (nroff word skipping fixed)
-;;
-;; Revision 2.20 1993/06/30 14:09:04 stevens
-;;
-;; Debugging and contributions by: Boris Aronov, Rik Faith, Chris Moore,
-;; Kevin Rodgers, Malcolm Davis.
-;; Particular thanks to Michael Lipp, Jamie Zawinski, Phil Queinnec
-;; and John Heidemann for suggestions and code.
-;; Major update including many tweaks.
-;; Many changes were integrations of suggestions.
-;; lookup-words rehacked to use call-process (Jamie).
-;; ispell-complete-word rehacked to be compatible with the rest of the
-;; system for word searching and to include multiple wildcards,
-;; and its own dictionary.
-;; query-replace capability added. New options 'X', 'R', and 'A'.
-;; buffer-local modes for dictionary, word-spelling, and formatter-parsing.
-;; Many random bugs, like commented comments being skipped, fix to
-;; keep-choices-win, fix for math mode, added pipe mode choice,
-;; fixed 'q' command, ispell-word checks previous word and leave cursor
-;; in same location. Fixed tib code which could drop spelling regions.
-;; Cleaned up setq calls for efficiency. Gave more context on window overlays.
-;; Assure context on ispell-command-loop. Window lossage in look cmd fixed.
-;; Due to pervasive opinion, common-lisp package syntax removed. Display
-;; problem when not highlighting.
-;;
-;; Revision 2.19 1992/01/10 10:54:08 geoff
-;; Make another attempt at fixing the "Bogus, dude" problem. This one is
-;; less elegant, but has the advantage of working.
-;;
-;; Revision 2.18 1992/01/07 10:04:52 geoff
-;; Fix the "Bogus, Dude" problem in ispell-word.
-;;
-;; Revision 2.17 1991/09/12 00:01:42 geoff
-;; Add some changes to make ispell-complete-word work better, though
-;; still not perfectly.
-;;
-;; Revision 2.16 91/09/04 18:00:52 geoff
-;; More updates from Sebastian, to make the multiple-dictionary support
-;; more flexible.
-;;
-;; Revision 2.15 91/09/04 17:30:02 geoff
-;; Sebastian Kremer's tib support
-;;
-;; Revision 2.14 91/09/04 16:19:37 geoff
-;; Don't do set-window-start if the move-to-window-line moved us
-;; downward, rather than upward. This prevents getting the buffer all
-;; confused. Also, don't use the "not-modified" function to clear the
-;; modification flag; instead use set-buffer-modified-p. This prevents
-;; extra messages from flashing.
-;;
-;; Revision 2.13 91/09/04 14:35:41 geoff
-;; Fix a spelling error in a comment. Add code to handshake with the
-;; ispell process before sending anything to it.
-;;
-;; Revision 2.12 91/09/03 20:14:21 geoff
-;; Add Sebastian Kremer's multiple-language support.
-;;
-;;
-;; Walt Buehring
-;; Texas Instruments - Computer Science Center
-;; ARPA: Buehring%TI-CSL@CSNet-Relay
-;; UUCP: {smu, texsun, im4u, rice} ! ti-csl ! buehring
-;;
-;; ispell-region and associated routines added by
-;; Perry Smith
-;; pedz@bobkat
-;; Tue Jan 13 20:18:02 CST 1987
-;;
-;; extensively modified by Mark Davies and Andrew Vignaux
-;; {mark,andrew}@vuwcomp
-;; Sun May 10 11:45:04 NZST 1987
-;;
-;; Ken Stevens ARPA: k.stevens@ieee.org
-;; Tue Jan 3 16:59:07 PST 1989
-;; This file has overgone a major overhaul to be compatible with ispell
-;; version 2.1. Most of the functions have been totally rewritten, and
-;; many user-accessible variables have been added. The syntax table has
-;; been removed since it didn't work properly anyway, and a filter is
-;; used rather than a buffer. Regular expressions are used based on
-;; ispell's internal definition of characters (see ispell(4)).
-;; Some new updates:
-;; - Updated to version 3.0 to include terse processing.
-;; - Added a variable for the look command.
-;; - Fixed a bug in ispell-word when cursor is far away from the word
-;; that is to be checked.
-;; - Ispell places the incorrect word or guess in the minibuffer now.
-;; - fixed a bug with 'l' option when multiple windows are on the screen.
-;; - lookup-words just didn't work with the process filter. Fixed.
-;; - Rewrote the process filter to make it cleaner and more robust
-;; in the event of a continued line not being completed.
-;; - Made ispell-init-process more robust in handling errors.
-;; - Fixed bug in continuation location after a region has been modified by
-;; correcting a misspelling.
-;; Mon 17 Sept 1990
-;;
-;; Sebastian Kremer <sk@thp.uni-koeln.de>
-;; Wed Aug 7 14:02:17 MET DST 1991
-;; - Ported ispell-complete-word from Ispell 2 to Ispell 3.
-;; - Added ispell-kill-ispell command.
-;; - Added ispell-dictionary and ispell-dictionary-alist variables to
-;; support other than default language. See their docstrings and
-;; command ispell-change-dictionary.
-;; - (ispelled it :-)
-;; - Added ispell-skip-tib variable to support the tib bibliography
-;; program.
-
-
-;; **********************************************************************
-;; The following variables should be set according to personal preference
-;; and location of binaries:
-;; **********************************************************************
-
-;; ******* THIS FILE IS WRITTEN FOR ISPELL VERSION 3.1
-
-;;; Code:
-
-(defvar ispell-highlight-p t
- "*Highlight spelling errors when non-nil.")
-
-(defvar ispell-highlight-face 'highlight
- "*The face used for Ispell highlighting. For Emacses with overlays.
-Possible values are `highlight', `modeline', `secondary-selection',
-`region', and `underline'.
-This variable can be set by the user to whatever face they desire.
-It's most convenient if the cursor color and highlight color are
-slightly different.")
-
-(defvar ispell-check-comments t
- "*If nil, don't check spelling of comments.")
-
-(defvar ispell-query-replace-choices nil
- "*Corrections made throughout region when non-nil.
-Uses `query-replace' (\\[query-replace]) for corrections.")
-
-(defvar ispell-skip-tib nil
- "*Does not spell check `tib' bibliography references when non-nil.
-Skips any text between strings matching regular expressions
-`ispell-tib-ref-beginning' and `ispell-tib-ref-end'.
-
-TeX users beware: Any field starting with [. will skip until a .] -- even
-your whole buffer -- unless you set `ispell-skip-tib' to nil. That includes
-a [.5mm] type of number....")
-
-(defvar ispell-tib-ref-beginning "[[<]\\."
- "Regexp matching the beginning of a Tib reference.")
-
-(defvar ispell-tib-ref-end "\\.[]>]"
- "Regexp matching the end of a Tib reference.")
-
-(defvar ispell-keep-choices-win t
- "*When not nil, the `*Choices*' window remains for spelling session.
-This minimizes redisplay thrashing.")
-
-(defvar ispell-choices-win-default-height 2
- "*The default size of the `*Choices*' window, including status line.
-Must be greater than 1.")
-
-(defvar ispell-program-name "ispell"
- "Program invoked by \\[ispell-word] and \\[ispell-region] commands.")
-
-(defvar ispell-alternate-dictionary
- (cond ((file-exists-p "/usr/dict/web2") "/usr/dict/web2")
- ((file-exists-p "/usr/share/dict/web2") "/usr/share/dict/web2")
- ((file-exists-p "/usr/dict/words") "/usr/dict/words")
- ((file-exists-p "/usr/lib/dict/words") "/usr/lib/dict/words")
- ((file-exists-p "/usr/share/dict/words") "/usr/share/dict/words")
- ((file-exists-p "/sys/dict") "/sys/dict")
- (t "/usr/dict/words"))
- "*Alternate dictionary for spelling help.")
-
-(defvar ispell-complete-word-dict ispell-alternate-dictionary
- "*Dictionary used for word completion.")
-
-(defvar ispell-grep-command "egrep"
- "Name of the grep command for search processes.")
-
-(defvar ispell-grep-options "-i"
- "String of options to use when running the program in `ispell-grep-command'.
-Should probably be \"-i\" or \"-e\".
-Some machines (like the NeXT) don't support \"-i\"")
-
-(defvar ispell-look-command "look"
- "Name of the look command for search processes.
-This must be an absolute file name.")
-
-(defvar ispell-look-p (file-exists-p ispell-look-command)
- "*Non-nil means use `look' rather than `grep'.
-Default is based on whether `look' seems to be available.")
-
-(defvar ispell-have-new-look nil
- "*Non-nil means use the `-r' option (regexp) when running `look'.")
-
-(defvar ispell-look-options (if ispell-have-new-look "-dfr" "-df")
- "String of command options for `ispell-look-command'.")
-
-(defvar ispell-use-ptys-p nil
- "When non-nil, Emacs uses ptys to communicate with Ispell.
-When nil, Emacs uses pipes.")
-
-(defvar ispell-following-word nil
- "*Non-nil means `ispell-word' checks the word around or after point.
-Otherwise `ispell-word' checks the preceding word.")
-
-(defvar ispell-help-in-bufferp nil
- "*Non-nil means display interactive keymap help in a buffer.
-Otherwise use the minibuffer.")
-
-(defvar ispell-quietly nil
- "*Non-nil means suppress messages in `ispell-word'.")
-
-(defvar ispell-format-word (function upcase)
- "*Formatting function for displaying word being spell checked.
-The function must take one string argument and return a string.")
-
-;;;###autoload
-(defvar ispell-personal-dictionary nil
- "*File name of your personal spelling dictionary, or nil.
-If nil, the default personal dictionary, \"~/.ispell_DICTNAME\" is used,
-where DICTNAME is the name of your default dictionary.")
-
-(defvar ispell-silently-savep nil
- "*When non-nil, save the personal dictionary without confirmation.")
-
-;;; This variable contains the current dictionary being used if the ispell
-;;; process is running. Otherwise it contains the global default.
-(defvar ispell-dictionary nil
- "If non-nil, a dictionary to use instead of the default one.
-This is passed to the ispell process using the `-d' switch and is
-used as key in `ispell-dictionary-alist' (which see).
-
-You should set this variable before your first use of Emacs spell-checking
-commands in the Emacs session, or else use the \\[ispell-change-dictionary]
-command to change it. Otherwise, this variable only takes effect in a newly
-started Ispell process.")
-
-(defvar ispell-extra-args nil
- "*If non-nil, a list of extra switches to pass to the Ispell program.
-For example, '(\"-W\" \"3\") to cause it to accept all 1-3 character
-words as correct. See also `ispell-dictionary-alist', which may be used
-for language-specific arguments.")
-
-;;; The preparation of the menu bar menu must be autoloaded
-;;; because otherwise this file gets autoloaded every time Emacs starts
-;;; so that it can set up the menus and determine keyboard equivalents.
-
-;;;###autoload
-(defvar ispell-dictionary-alist-1 ; sk 9-Aug-1991 18:28
- '((nil ; default (english.aff)
- "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil)
- ("english" ; make English explicitly selectable
- "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil)
- ("british" ; British version
- "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B" "-d" "british") nil)
- ("american" ; American version
- "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B" "-d" "american") nil)
- ("deutsch" ; deutsch.aff
- "[a-zA-Z\"]" "[^a-zA-Z\"]" "[']" t ("-C") "~tex")
- ("deutsch8"
- "[a-zA-Z\304\326\334\344\366\337\374]"
- "[^a-zA-Z\304\326\334\344\366\337\374]"
- "[']" t ("-C" "-d" "deutsch") "~latin1")
- ("nederlands" ; nederlands.aff
- "[A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
- "[^A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
- "[']" t ("-C") nil)
- ("nederlands8" ; dutch8.aff
- "[A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
- "[^A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
- "[']" t ("-C") nil)))
-
-;;;###autoload
-(defvar ispell-dictionary-alist-2
- '(("svenska" ;7 bit swedish mode
- "[A-Za-z}{|\\133\\135\\\\]" "[^A-Za-z}{|\\133\\135\\\\]"
- "[']" nil ("-C") nil)
- ("svenska8" ;8 bit swedish mode
- "[A-Za-z\345\344\366\305\304\366]" "[^A-Za-z\345\344\366\305\304\366]"
- "[']" nil ("-C" "-d" "svenska") "~list") ; Add `"-T" "list"' instead?
- ("francais7"
- "[A-Za-z]" "[^A-Za-z]" "[`'^---]" t nil nil)
- ("francais" ; francais.aff
- "[A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374]"
- "[^A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374]"
- "[---']" t nil "~list")
- ("francais-tex" ; francais.aff
- "[A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374\\]"
- "[^A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374\\]"
- "[---'^`\"]" t nil "~tex")
- ("dansk" ; dansk.aff
- "[A-Z\306\330\305a-z\346\370\345]" "[^A-Z\306\330\305a-z\346\370\345]"
- "" nil ("-C") nil)
- ))
-
-
-;;; ispell-dictionary-alist is set up from two subvariables above
-;;; to avoid having very long lines in loaddefs.el.
-;;;###autoload
-(defvar ispell-dictionary-alist
- (append ispell-dictionary-alist-1 ispell-dictionary-alist-2)
- "An alist of dictionaries and their associated parameters.
-
-Each element of this list is also a list:
-
-\(DICTIONARY-NAME CASECHARS NOT-CASECHARS OTHERCHARS MANY-OTHERCHARS-P
- ISPELL-ARGS EXTENDED-CHARACTER-MODE\)
-
-DICTIONARY-NAME is a possible value of variable `ispell-dictionary', nil
-means the default dictionary.
-
-CASECHARS is a regular expression of valid characters that comprise a
-word.
-
-NOT-CASECHARS is the opposite regexp of CASECHARS.
-
-OTHERCHARS is a regular expression of other characters that are valid
-in word constructs. Otherchars cannot be adjacent to each other in a
-word, nor can they begin or end a word. This implies we can't check
-\"Stevens'\" as a correct possessive and other correct formations.
-
-Hint: regexp syntax requires the hyphen to be declared first here.
-
-MANY-OTHERCHARS-P is non-nil if many otherchars are to be allowed in a
-word instead of only one.
-
-ISPELL-ARGS is a list of additional arguments passed to the ispell
-subprocess.
-
-EXTENDED-CHARACTER-MODE should be used when dictionaries are used which
-have been configured in an Ispell affix file. (For example, umlauts
-can be encoded as \\\"a, a\\\", \"a, ...) Defaults are ~tex and ~nroff
-in English. This has the same effect as the command-line `-T' option.
-The buffer Major Mode controls Ispell's parsing in tex or nroff mode,
-but the dictionary can control the extended character mode.
-Both defaults can be overruled in a buffer-local fashion. See
-`ispell-parsing-keyword' for details on this.
-
-Note that the CASECHARS and OTHERCHARS slots of the alist should
-contain the same character set as casechars and otherchars in the
-language.aff file \(e.g., english.aff\).")
-
-;;;###autoload
-(defvar ispell-menu-map nil "Key map for ispell menu")
-
-;;;###autoload
-(defvar ispell-menu-lucid nil "Spelling menu for Lucid Emacs.")
-
-;;; Break out lucid menu and split into several calls to avoid having
-;;; long lines in loaddefs.el. Detect need off following constant.
-
-;;;###autoload
-(defconst ispell-menu-map-needed ; make sure this is not Lucid Emacs
- (and (not ispell-menu-map)
-;;; This is commented out because it fails in Emacs.
-;;; due to the fact that menu-bar is loaded much later than loaddefs.
-;;; ;; make sure this isn't Lucid Emacs
-;;; (featurep 'menu-bar)
- (not (string-match "Lucid" emacs-version))))
-
-;;; Set up dictionary
-;;;###autoload
-(if ispell-menu-map-needed
- (let ((dicts (reverse (cons (cons "default" nil) ispell-dictionary-alist)))
- name)
- (setq ispell-menu-map (make-sparse-keymap "Spell"))
- ;; add the dictionaries to the bottom of the list.
- (while dicts
- (setq name (car (car dicts))
- dicts (cdr dicts))
- (if (stringp name)
- (define-key ispell-menu-map (vector (intern name))
- (cons (concat "Select " (capitalize name))
- (list 'lambda () '(interactive)
- (list 'ispell-change-dictionary name))))))))
-
-;;; define commands in menu in opposite order you want them to appear.
-;;;###autoload
-(if ispell-menu-map-needed
- (progn
- (define-key ispell-menu-map [ispell-change-dictionary]
- '("Change Dictionary" . ispell-change-dictionary))
- (define-key ispell-menu-map [ispell-kill-ispell]
- '("Kill Process" . ispell-kill-ispell))
- (define-key ispell-menu-map [ispell-pdict-save]
- '("Save Dictionary" . (lambda () (interactive) (ispell-pdict-save t t))))
- (define-key ispell-menu-map [ispell-complete-word]
- '("Complete Word" . ispell-complete-word))
- (define-key ispell-menu-map [ispell-complete-word-interior-frag]
- '("Complete Word Frag" . ispell-complete-word-interior-frag))))
-
-;;;###autoload
-(if ispell-menu-map-needed
- (progn
- (define-key ispell-menu-map [ispell-continue]
- '("Continue Check" . ispell-continue))
- (define-key ispell-menu-map [ispell-word]
- '("Check Word" . ispell-word))
- (define-key ispell-menu-map [ispell-region]
- '("Check Region" . ispell-region))
- (define-key ispell-menu-map [ispell-buffer]
- '("Check Buffer" . ispell-buffer))))
-
-;;;###autoload
-(if ispell-menu-map-needed
- (progn
- (define-key ispell-menu-map [ispell-message]
- '("Check Message" . ispell-message))
- (define-key ispell-menu-map [ispell-help]
- ;; use (x-popup-menu last-nonmenu-event(list "" ispell-help-list)) ?
- '("Help" . (lambda () (interactive) (describe-function 'ispell-help))))
- (put 'ispell-region 'menu-enable 'mark-active)
- (fset 'ispell-menu-map (symbol-value 'ispell-menu-map))))
-
-;;; Xemacs version 19
-(if (and (string-lessp "19" emacs-version)
- (string-match "Lucid" emacs-version))
- (let ((dicts (cons (cons "default" nil) ispell-dictionary-alist))
- (current-menubar (or current-menubar default-menubar))
- (menu
- '(["Help" (describe-function 'ispell-help) t]
- ;;["Help" (popup-menu ispell-help-list) t]
- ["Check Message" ispell-message t]
- ["Check Buffer" ispell-buffer t]
- ["Check Word" ispell-word t]
- ["Check Region" ispell-region (or (not zmacs-regions) (mark))]
- ["Continue Check" ispell-continue t]
- ["Complete Word Frag"ispell-complete-word-interior-frag t]
- ["Complete Word" ispell-complete-word t]
- ["Kill Process" ispell-kill-ispell t]
- "-"
- ["Save Dictionary" (ispell-pdict-save t t) t]
- ["Change Dictionary" ispell-change-dictionary t]))
- name)
- (while dicts
- (setq name (car (car dicts))
- dicts (cdr dicts))
- (if (stringp name)
- (setq menu (append menu
- (list
- (vector (concat "Select " (capitalize name))
- (list 'ispell-change-dictionary name)
- t))))))
- (setq ispell-menu-lucid menu)
- (if current-menubar
- (progn
- (delete-menu-item '("Edit" "Spell")) ; in case already defined
- (add-menu '("Edit") "Spell" ispell-menu-lucid)))))
-
-
-;;; **********************************************************************
-;;; The following are used by ispell, and should not be changed.
-;;; **********************************************************************
-
-
-;;; The version must be 3.1 or greater for this version of ispell.el
-;;; There is an incompatibility between version 3.1.12 and lower versions.
-(defconst ispell-required-version '("3.1." 12)
- "Ispell versions with which this version of ispell.el is known to work.")
-(defvar ispell-offset 1
- "Offset that maps protocol differences between ispell 3.1 versions.")
-
-(defun ispell-get-casechars ()
- (nth 1 (assoc ispell-dictionary ispell-dictionary-alist)))
-(defun ispell-get-not-casechars ()
- (nth 2 (assoc ispell-dictionary ispell-dictionary-alist)))
-(defun ispell-get-otherchars ()
- (nth 3 (assoc ispell-dictionary ispell-dictionary-alist)))
-(defun ispell-get-many-otherchars-p ()
- (nth 4 (assoc ispell-dictionary ispell-dictionary-alist)))
-(defun ispell-get-ispell-args ()
- (nth 5 (assoc ispell-dictionary ispell-dictionary-alist)))
-(defun ispell-get-extended-character-mode ()
- (nth 6 (assoc ispell-dictionary ispell-dictionary-alist)))
-
-(defvar ispell-process nil
- "The process object for Ispell.")
-
-(defvar ispell-pdict-modified-p nil
- "Non-nil means personal dictionary has modifications to be saved.")
-
-;;; If you want to save the dictionary when quitting, must do so explicitly.
-;;; When non-nil, the spell session is terminated.
-;;; When numeric, contains cursor location in buffer, and cursor remains there.
-(defvar ispell-quit nil)
-
-(defvar ispell-filter nil
- "Output filter from piped calls to Ispell.")
-
-(defvar ispell-filter-continue nil
- "Control variable for Ispell filter function.")
-
-(defvar ispell-process-directory nil
- "The directory where `ispell-process' was started.")
-
-(defvar ispell-query-replace-marker (make-marker)
- "Marker for `query-replace' processing.")
-
-(defvar ispell-checking-message nil
- "Non-nil when we're checking a mail message")
-
-(defconst ispell-choices-buffer "*Choices*")
-
-(defvar ispell-overlay nil "Overlay variable for Ispell highlighting.")
-
-;;; *** Buffer Local Definitions ***
-
-;;; This is the local dictionary to use. When nil the default dictionary will
-;;; be used. Do not redefine default value or it will override the global!
-(defvar ispell-local-dictionary nil
- "If non-nil, a dictionary to use for Ispell commands in this buffer.
-The value must be a string dictionary name in `ispell-dictionary-alist'.
-This variable becomes buffer-local when set in any fashion.
-
-Setting ispell-local-dictionary to a value has the same effect as
-calling \\[ispell-change-dictionary] with that value. This variable
-is automatically set when defined in the file with either
-`ispell-dictionary-keyword' or the Local Variable syntax.")
-
-(make-variable-buffer-local 'ispell-local-dictionary)
-
-;; Use default directory, unless locally set.
-(set-default 'ispell-local-dictionary nil)
-
-(defconst ispell-words-keyword "LocalWords: "
- "The keyword for local oddly-spelled words to accept.
-The keyword will be followed by any number of local word spellings.
-There can be multiple of these keywords in the file.")
-
-(defconst ispell-dictionary-keyword "Local IspellDict: "
- "The keyword for local dictionary definitions.
-There should be only one dictionary keyword definition per file, and it
-should be followed by a correct dictionary name in `ispell-dictionary-alist'.")
-
-(defconst ispell-parsing-keyword "Local IspellParsing: "
- "The keyword for overriding default Ispell parsing.
-Determined by the buffer's major mode and extended-character mode as well as
-the default dictionary.
-
-The above keyword string should be followed by `latex-mode' or
-`nroff-mode' to put the current buffer into the desired parsing mode.
-
-Extended character mode can be changed for this buffer by placing
-a `~' followed by an extended-character mode -- such as `~.tex'.")
-
-(defvar ispell-skip-sgml nil
- "Skips spell checking of SGML tags and entity references when non-nil.
-This variable is set when major-mode is sgml-mode or html-mode.")
-
-(defvar ispell-local-pdict ispell-personal-dictionary
- "A buffer local variable containing the current personal dictionary.
-If non-nil, the value must be a string, which is a file name.
-
-If you specify a personal dictionary for the current buffer which is
-different from the current personal dictionary, the effect is similar
-to calling \\[ispell-change-dictionary]. This variable is automatically
-set when defined in the file with either `ispell-pdict-keyword' or the
-local variable syntax.")
-
-(make-variable-buffer-local 'ispell-local-pdict)
-
-(defconst ispell-pdict-keyword "Local IspellPersDict: "
- "The keyword for defining buffer local dictionaries.")
-
-(defvar ispell-buffer-local-name nil
- "Contains the buffer name if local word definitions were used.
-Ispell is then restarted because the local words could conflict.")
-
-(defvar ispell-parser 'use-mode-name
- "*Indicates whether ispell should parse the current buffer as TeX Code.
-Special value `use-mode-name' tries to guess using the name of major-mode.
-Default parser is 'nroff.
-Currently the only other valid parser is 'tex.
-
-You can set this variable in hooks in your init file -- eg:
-
-(add-hook 'tex-mode-hook (function (lambda () (setq ispell-parser 'tex))))")
-
-(defvar ispell-region-end (make-marker)
- "Marker that allows spelling continuations.")
-
-(defvar ispell-check-only nil
- "If non-nil, `ispell-word' does not try to correct the word.")
-
-
-;;; **********************************************************************
-;;; **********************************************************************
-
-
-(and (string-lessp "19" emacs-version)
- (not (boundp 'epoch::version))
- (defalias 'ispell 'ispell-buffer))
-
-;;;###autoload
-(define-key global-map "\M-$" 'ispell-word)
-
-;;;###autoload
-(defun ispell-word (&optional following quietly continue)
- "Check spelling of word under or before the cursor.
-If the word is not found in dictionary, display possible corrections
-in a window allowing you to choose one.
-
-With a prefix argument (or if CONTINUE is non-nil),
-resume interrupted spell-checking of a buffer or region.
-
-If optional argument FOLLOWING is non-nil or if `ispell-following-word'
-is non-nil when called interactively, then the following word
-\(rather than preceding\) is checked when the cursor is not over a word.
-When the optional argument QUIETLY is non-nil or `ispell-quietly' is non-nil
-when called interactively, non-corrective messages are suppressed.
-
-Word syntax described by `ispell-dictionary-alist' (which see).
-
-This will check or reload the dictionary. Use \\[ispell-change-dictionary]
-or \\[ispell-region] to update the Ispell process."
- (interactive (list nil nil current-prefix-arg))
- (if continue
- (ispell-continue)
- (if (interactive-p)
- (setq following ispell-following-word
- quietly ispell-quietly))
- (ispell-accept-buffer-local-defs) ; use the correct dictionary
- (let ((cursor-location (point)) ; retain cursor location
- (word (ispell-get-word following))
- start end poss replace)
- ;; destructure return word info list.
- (setq start (car (cdr word))
- end (car (cdr (cdr word)))
- word (car word))
-
- ;; now check spelling of word.
- (or quietly
- (message "Checking spelling of %s..."
- (funcall ispell-format-word word)))
- (process-send-string ispell-process "%\n") ;put in verbose mode
- (process-send-string ispell-process (concat "^" word "\n"))
- ;; wait until ispell has processed word
- (while (progn
- (accept-process-output ispell-process)
- (not (string= "" (car ispell-filter)))))
- ;;(process-send-string ispell-process "!\n") ;back to terse mode.
- (setq ispell-filter (cdr ispell-filter))
- (if (listp ispell-filter)
- (setq poss (ispell-parse-output (car ispell-filter))))
- (cond ((eq poss t)
- (or quietly
- (message "%s is correct" (funcall ispell-format-word word))))
- ((stringp poss)
- (or quietly
- (message "%s is correct because of root %s"
- (funcall ispell-format-word word)
- (funcall ispell-format-word poss))))
- ((null poss) (message "Error in ispell process"))
- (ispell-check-only ; called from ispell minor mode.
- (beep))
- (t ; prompt for correct word.
- (save-window-excursion
- (setq replace (ispell-command-loop
- (car (cdr (cdr poss)))
- (car (cdr (cdr (cdr poss))))
- (car poss) start end)))
- (cond ((equal 0 replace)
- (ispell-add-per-file-word-list (car poss)))
- (replace
- (setq word (if (atom replace) replace (car replace))
- cursor-location (+ (- (length word) (- end start))
- cursor-location))
- (if (not (equal word (car poss)))
- (progn
- (delete-region start end)
- (insert word)))
- (if (not (atom replace)) ; recheck spelling of replacement
- (progn
- (goto-char cursor-location)
- (ispell-word following quietly)))))
- (if (get-buffer ispell-choices-buffer)
- (kill-buffer ispell-choices-buffer))))
- (goto-char cursor-location) ; return to original location
- (ispell-pdict-save ispell-silently-savep)
- (if ispell-quit (setq ispell-quit nil)))))
-
-
-(defun ispell-get-word (following &optional extra-otherchars)
- "Return the word for spell-checking according to ispell syntax.
-If optional argument FOLLOWING is non-nil or if `ispell-following-word'
-is non-nil when called interactively, then the following word
-\(rather than preceding\) is checked when the cursor is not over a word.
-Optional second argument contains otherchars that can be included in word
-many times.
-
-Word syntax described by `ispell-dictionary-alist' (which see)."
- (let* ((ispell-casechars (ispell-get-casechars))
- (ispell-not-casechars (ispell-get-not-casechars))
- (ispell-otherchars (ispell-get-otherchars))
- (ispell-many-otherchars-p (ispell-get-many-otherchars-p))
- (word-regexp (concat ispell-casechars
- "+\\("
- ispell-otherchars
- "?"
- (if extra-otherchars
- (concat extra-otherchars "?"))
- ispell-casechars
- "+\\)"
- (if (or ispell-many-otherchars-p
- extra-otherchars)
- "*" "?")))
- did-it-once
- start end word)
- ;; find the word
- (if (not (looking-at ispell-casechars))
- (if following
- (re-search-forward ispell-casechars (point-max) t)
- (re-search-backward ispell-casechars (point-min) t)))
- ;; move to front of word
- (re-search-backward ispell-not-casechars (point-min) 'start)
- (while (and (or (looking-at ispell-otherchars)
- (and extra-otherchars (looking-at extra-otherchars)))
- (not (bobp))
- (or (not did-it-once)
- ispell-many-otherchars-p))
- (if (and extra-otherchars (looking-at extra-otherchars))
- (progn
- (backward-char 1)
- (if (looking-at ispell-casechars)
- (re-search-backward ispell-not-casechars (point-min) 'move)))
- (setq did-it-once t)
- (backward-char 1)
- (if (looking-at ispell-casechars)
- (re-search-backward ispell-not-casechars (point-min) 'move)
- (backward-char -1))))
- ;; Now mark the word and save to string.
- (or (re-search-forward word-regexp (point-max) t)
- (error "No word found to check!"))
- (setq start (match-beginning 0)
- end (point)
- word (buffer-substring start end))
- (list word start end)))
-
-
-;;; Global ispell-pdict-modified-p is set by ispell-command-loop and
-;;; tracks changes in the dictionary. The global may either be
-;;; a value or a list, whose value is the state of whether the
-;;; dictionary needs to be saved.
-
-(defun ispell-pdict-save (&optional no-query force-save)
- "Check to see if the personal dictionary has been modified.
-If so, ask if it needs to be saved."
- (interactive (list ispell-silently-savep t))
- (if (and ispell-pdict-modified-p (listp ispell-pdict-modified-p))
- (setq ispell-pdict-modified-p (car ispell-pdict-modified-p)))
- (if (or ispell-pdict-modified-p force-save)
- (if (or no-query (y-or-n-p "Personal dictionary modified. Save? "))
- (progn
- (process-send-string ispell-process "#\n")
- (message "Personal dictionary saved."))))
- ;; unassert variable, even if not saved to avoid questioning.
- (setq ispell-pdict-modified-p nil))
-
-
-(defun ispell-command-loop (miss guess word start end)
- "Display possible corrections from list MISS.
-GUESS lists possibly valid affix construction of WORD.
-Returns nil to keep word.
-Returns 0 to insert locally into buffer-local dictionary.
-Returns string for new chosen word.
-Returns list for new replacement word (will be rechecked).
-Highlights the word, which is assumed to run from START to END.
-Global `ispell-pdict-modified-p' becomes a list where the only value
-indicates whether the dictionary has been modified when option `a' or `i' is
-used."
- (let ((textbuf (current-buffer))
- (count ?0)
- (line 2)
- (max-lines (- (window-height) 4)) ; assure 4 context lines.
- (choices miss)
- (window-min-height (min window-min-height
- ispell-choices-win-default-height))
- (command-characters '( ? ?i ?a ?A ?r ?R ?? ?x ?X ?q ?l ?u ?m ))
- (skipped 0)
- char num result textwin highlighted)
-
- ;; setup the *Choices* buffer with valid data.
- (save-excursion
- (set-buffer (get-buffer-create ispell-choices-buffer))
- (setq mode-line-format (concat "-- %b -- word: " word))
- (erase-buffer)
- (if guess
- (progn
- (insert "Affix rules generate and capitalize "
- "this word as shown below:\n\t")
- (while guess
- (if (> (+ 4 (current-column) (length (car guess)))
- (window-width))
- (progn
- (insert "\n\t")
- (setq line (1+ line))))
- (insert (car guess) " ")
- (setq guess (cdr guess)))
- (insert "\nUse option `i' if this is a correct composition"
- " from the derivative root.\n")
- (setq line (+ line (if choices 3 2)))))
- (while (and choices
- (< (if (> (+ 7 (current-column) (length (car choices))
- (if (> count ?~) 3 0))
- (window-width))
- (progn
- (insert "\n")
- (setq line (1+ line)))
- line)
- max-lines))
- ;; not so good if there are over 20 or 30 options, but then, if
- ;; there are that many you don't want to scan them all anyway...
- (while (memq count command-characters) ; skip command characters.
- (setq count (1+ count)
- skipped (1+ skipped)))
- (insert "(" count ") " (car choices) " ")
- (setq choices (cdr choices)
- count (1+ count)))
- (setq count (- count ?0 skipped)))
-
- ;; Assure word is visible
- (if (not (pos-visible-in-window-p end))
- (sit-for 0))
- ;; Display choices for misspelled word.
- (let ((choices-window (get-buffer-window ispell-choices-buffer)))
- (if choices-window
- (if (= line (window-height choices-window))
- (select-window choices-window)
- ;; *Choices* window changed size. Adjust the choices window
- ;; without scrolling the spelled window when possible
- (let ((window-line (- line (window-height choices-window)))
- (visible (progn (forward-line -1) (point))))
- (if (< line ispell-choices-win-default-height)
- (setq window-line (+ window-line
- (- ispell-choices-win-default-height
- line))))
- (move-to-window-line 0)
- (forward-line window-line)
- (set-window-start (selected-window)
- (if (> (point) visible) visible (point)))
- (goto-char end)
- (select-window (previous-window)) ; *Choices* window
- (enlarge-window window-line)))
- ;; Overlay *Choices* window when it isn't showing
- (ispell-overlay-window (max line ispell-choices-win-default-height)))
- (switch-to-buffer ispell-choices-buffer)
- (goto-char (point-min)))
-
- (select-window (setq textwin (next-window)))
-
- ;; highlight word, protecting current buffer status
- (unwind-protect
- (progn
- (if ispell-highlight-p
- (ispell-highlight-spelling-error start end t))
- ;; Loop until a valid choice is made.
- (while
- (eq
- t
- (setq
- result
- (progn
- (undo-boundary)
- (message (concat "C-h or ? for more options; SPC to leave "
- "unchanged, Character to replace word"))
- (let ((inhibit-quit t))
- (setq char (if (fboundp 'read-char-exclusive)
- (read-char-exclusive)
- (read-char))
- skipped 0)
- (if (or quit-flag (= char ?\C-g)) ; C-g is like typing X
- (setq char ?X
- quit-flag nil)))
- ;; Adjust num to array offset skipping command characters.
- (let ((com-chars command-characters))
- (while com-chars
- (if (and (> (car com-chars) ?0) (< (car com-chars) char))
- (setq skipped (1+ skipped)))
- (setq com-chars (cdr com-chars)))
- (setq num (- char ?0 skipped)))
-
- (cond
- ((= char ? ) nil) ; accept word this time only
- ((= char ?i) ; accept and insert word into pers dict
- (process-send-string ispell-process (concat "*" word "\n"))
- (setq ispell-pdict-modified-p '(t)) ; dictionary modified!
- nil)
- ((or (= char ?a) (= char ?A)) ; accept word without insert
- (process-send-string ispell-process (concat "@" word "\n"))
- (if (null ispell-pdict-modified-p)
- (setq ispell-pdict-modified-p
- (list ispell-pdict-modified-p)))
- (if (= char ?A) 0)) ; return 0 for ispell-add buffer-local
- ((or (= char ?r) (= char ?R)) ; type in replacement
- (if (or (= char ?R) ispell-query-replace-choices)
- (list (read-string "Query-replacement for: " word) t)
- (cons (read-string "Replacement for: " word) nil)))
- ((or (= char ??) (= char help-char) (= char ?\C-h))
- (ispell-help)
- t)
- ;; Quit and move point back.
- ((= char ?x)
- (ispell-pdict-save ispell-silently-savep)
- (message "Exited spell-checking")
- (setq ispell-quit t)
- nil)
- ;; Quit and preserve point.
- ((= char ?X)
- (ispell-pdict-save ispell-silently-savep)
- (message "%s"
- (substitute-command-keys
- (concat "Spell-checking suspended;"
- " use C-u \\[ispell-word] to resume")))
- (setq ispell-quit (max (point-min)
- (- (point) (length word))))
- nil)
- ((= char ?q)
- (if (y-or-n-p "Really kill Ispell process? ")
- (progn
- (ispell-kill-ispell t) ; terminate process.
- (setq ispell-quit (or (not ispell-checking-message)
- (point))
- ispell-pdict-modified-p nil))
- t)) ; continue if they don't quit.
- ((= char ?l)
- (let ((new-word (read-string
- "Lookup string (`*' is wildcard): "
- word))
- (new-line 2))
- (if new-word
- (progn
- (save-excursion
- (set-buffer (get-buffer-create
- ispell-choices-buffer))
- (erase-buffer)
- (setq count ?0
- skipped 0
- mode-line-format (concat
- "-- %b -- word: "
- new-word)
- miss (lookup-words new-word)
- choices miss)
- (while (and choices ; adjust choices window.
- (< (if (> (+ 7 (current-column)
- (length (car choices))
- (if (> count ?~) 3 0))
- (window-width))
- (progn
- (insert "\n")
- (setq new-line
- (1+ new-line)))
- new-line)
- max-lines))
- (while (memq count command-characters)
- (setq count (1+ count)
- skipped (1+ skipped)))
- (insert "(" count ") " (car choices) " ")
- (setq choices (cdr choices)
- count (1+ count)))
- (setq count (- count ?0 skipped)))
- (select-window (previous-window))
- (if (and (/= new-line line)
- (> (max line new-line)
- ispell-choices-win-default-height))
- (let* ((minh ispell-choices-win-default-height)
- (gr-bl (if (< line minh) ; blanks
- (- minh line)
- 0))
- (shr-bl (if (< new-line minh) ; blanks
- (- minh new-line)
- 0)))
- (if (> new-line line)
- (enlarge-window (- new-line line gr-bl))
- (shrink-window (- line new-line shr-bl)))
- (setq line new-line)))
- (select-window (next-window)))))
- t) ; reselect from new choices
- ((= char ?u)
- (process-send-string ispell-process
- (concat "*" (downcase word) "\n"))
- (setq ispell-pdict-modified-p '(t)) ; dictionary modified!
- nil)
- ((= char ?m) ; type in what to insert
- (process-send-string
- ispell-process (concat "*" (read-string "Insert: " word)
- "\n"))
- (setq ispell-pdict-modified-p '(t))
- (cons word nil))
- ((and (>= num 0) (< num count))
- (if ispell-query-replace-choices ; Query replace flag
- (list (nth num miss) 'query-replace)
- (nth num miss)))
- ((= char ?\C-l)
- (redraw-display) t)
- ((= char ?\C-r)
- (save-window-excursion (recursive-edit)) t)
- ((= char ?\C-z)
- (funcall (key-binding "\C-z"))
- t)
- (t (ding) t))))))
- result)
- ;; protected
- (if ispell-highlight-p ; unhighlight
- (save-window-excursion
- (select-window textwin)
- (ispell-highlight-spelling-error start end))))))
-
-
-;;;###autoload
-(defun ispell-help ()
- "Display a list of the options available when a misspelling is encountered.
-
-Selections are:
-
-DIGIT: Replace the word with a digit offered in the *Choices* buffer.
-SPC: Accept word this time.
-`i': Accept word and insert into private dictionary.
-`a': Accept word for this session.
-`A': Accept word and place in `buffer-local dictionary'.
-`r': Replace word with typed-in value. Rechecked.
-`R': Replace word with typed-in value. Query-replaced in buffer. Rechecked.
-`?': Show these commands.
-`x': Exit spelling buffer. Move cursor to original point.
-`X': Exit spelling buffer. Leaves cursor at the current point, and permits
- the aborted check to be completed later.
-`q': Quit spelling session (Kills ispell process).
-`l': Look up typed-in replacement in alternate dictionary. Wildcards okay.
-`u': Like `i', but the word is lower-cased first.
-`m': Like `i', but allows one to include dictionary completion information.
-`C-l': redraws screen
-`C-r': recursive edit
-`C-z': suspend emacs or iconify frame"
-
- (let ((help-1 (concat "[r/R]eplace word; [a/A]ccept for this session; "
- "[i]nsert into private dictionary"))
- (help-2 (concat "[l]ook a word up in alternate dictionary; "
- "e[x/X]it; [q]uit session"))
- (help-3 (concat "[u]ncapitalized insert into dictionary. "
- "Type 'C-h d ispell-help' for more help")))
- (save-window-excursion
- (if ispell-help-in-bufferp
- (progn
- (ispell-overlay-window 4)
- (switch-to-buffer (get-buffer-create "*Ispell Help*"))
- (insert (concat help-1 "\n" help-2 "\n" help-3))
- (sit-for 5)
- (kill-buffer "*Ispell Help*"))
- (select-window (minibuffer-window))
- ;;(enlarge-window 2)
- (erase-buffer)
- (cond ((string-match "Lucid" emacs-version)
- (message help-3)
- (enlarge-window 1)
- (message help-2)
- (enlarge-window 1)
- (message help-1)
- (goto-char (point-min)))
- (t
- (if (string-lessp "19" emacs-version)
- (message nil))
- (enlarge-window 2)
- ;; Make sure we display the minibuffer
- ;; in this window, not some other.
- (set-minibuffer-window (selected-window))
- (insert (concat help-1 "\n" help-2 "\n" help-3))))
- (sit-for 5)
- (erase-buffer)))))
-
-
-(defun lookup-words (word &optional lookup-dict)
- "Look up word in word-list dictionary.
-A `*' serves as a wild card. If no wild cards, `look' is used if it exists.
-Otherwise the variable `ispell-grep-command' contains the command used to
-search for the words (usually egrep).
-
-Optional second argument contains the dictionary to use; the default is
-`ispell-alternate-dictionary'."
- ;; We don't use the filter for this function, rather the result is written
- ;; into a buffer. Hence there is no need to save the filter values.
- (if (null lookup-dict)
- (setq lookup-dict ispell-alternate-dictionary))
-
- (let* ((process-connection-type ispell-use-ptys-p)
- (wild-p (string-match "\\*" word))
- (look-p (and ispell-look-p ; Only use look for an exact match.
- (or ispell-have-new-look (not wild-p))))
- (ispell-grep-buffer (get-buffer-create "*Ispell-Temp*")) ; result buf
- (prog (if look-p ispell-look-command ispell-grep-command))
- (args (if look-p ispell-look-options ispell-grep-options))
- status results loc)
- (unwind-protect
- (save-window-excursion
- (message "Starting \"%s\" process..." (file-name-nondirectory prog))
- (set-buffer ispell-grep-buffer)
- (if look-p
- nil
- ;; convert * to .*
- (insert "^" word "$")
- (while (search-backward "*" nil t) (insert "."))
- (setq word (buffer-string))
- (erase-buffer))
- (setq status (call-process prog nil t nil args word lookup-dict))
- ;; grep returns status 1 and no output when word not found, which
- ;; is a perfectly normal thing.
- (if (stringp status)
- (setq results (cons (format "error: %s exited with signal %s"
- (file-name-nondirectory prog) status)
- results))
- ;; else collect words into `results' in FIFO order
- (goto-char (point-max))
- ;; assure we've ended with \n
- (or (bobp) (= (preceding-char) ?\n) (insert ?\n))
- (while (not (bobp))
- (setq loc (point))
- (forward-line -1)
- (setq results (cons (buffer-substring (point) (1- loc))
- results)))))
- ;; protected
- (kill-buffer ispell-grep-buffer)
- (if (and results (string-match ".+: " (car results)))
- (error "%s error: %s" ispell-grep-command (car results))))
- results))
-
-
-;;; "ispell-filter" is a list of output lines from the generating function.
-;;; Each full line (ending with \n) is a separate item on the list.
-;;; "output" can contain multiple lines, part of a line, or both.
-;;; "start" and "end" are used to keep bounds on lines when "output" contains
-;;; multiple lines.
-;;; "ispell-filter-continue" is true when we have received only part of a
-;;; line as output from a generating function ("output" did not end with \n)
-;;; THIS FUNCTION WILL FAIL IF THE PROCESS OUTPUT DOESN'T END WITH \n!
-;;; This is the case when a process dies or fails. The default behavior
-;;; in this case treats the next input received as fresh input.
-
-(defun ispell-filter (process output)
- "Output filter function for ispell, grep, and look."
- (let ((start 0)
- (continue t)
- end)
- (while continue
- (setq end (string-match "\n" output start)) ; get text up to the newline.
- ;; If we get out of sync and ispell-filter-continue is asserted when we
- ;; are not continuing, treat the next item as a separate list. When
- ;; ispell-filter-continue is asserted, ispell-filter *should* always be a
- ;; list!
-
- ;; Continue with same line (item)?
- (if (and ispell-filter-continue ispell-filter (listp ispell-filter))
- ;; Yes. Add it to the prev item
- (setcar ispell-filter
- (concat (car ispell-filter) (substring output start end)))
- ;; No. This is a new line and item.
- (setq ispell-filter
- (cons (substring output start end) ispell-filter)))
- (if (null end)
- ;; We've completed reading the output, but didn't finish the line.
- (setq ispell-filter-continue t continue nil)
- ;; skip over newline, this line complete.
- (setq ispell-filter-continue nil end (1+ end))
- (if (= end (length output)) ; No more lines in output
- (setq continue nil) ; so we can exit the filter.
- (setq start end)))))) ; else move start to next line of input
-
-
-;;; This function destroys the mark location if it is in the word being
-;;; highlighted.
-(defun ispell-highlight-spelling-error-generic (start end &optional highlight)
- "Highlight the word from START to END with a kludge using `inverse-video'.
-When the optional third arg HIGHLIGHT is set, the word is highlighted;
-otherwise it is displayed normally."
- (let ((modified (buffer-modified-p)) ; don't allow this fn to modify buffer
- (buffer-read-only nil) ; Allow highlighting read-only buffers.
- (text (buffer-substring start end)) ; Save highlight region
- (inhibit-quit t) ; inhibit interrupt processing here.
- (buffer-undo-list t)) ; don't clutter the undo list.
- (delete-region start end)
- (insert-char ? (- end start)) ; minimize amount of redisplay
- (sit-for 0) ; update display
- (if highlight (setq inverse-video (not inverse-video))) ; toggle video
- (delete-region start end) ; delete whitespace
- (insert text) ; insert text in inverse video.
- (sit-for 0) ; update display showing inverse video.
- (if highlight (setq inverse-video (not inverse-video))) ; toggle video
- (set-buffer-modified-p modified))) ; don't modify if flag not set.
-
-
-(defun ispell-highlight-spelling-error-lucid (start end &optional highlight)
- "Highlight the word from START to END using `isearch-highlight'.
-When the optional third arg HIGHLIGHT is set, the word is highlighted,
-otherwise it is displayed normally."
- (if highlight
- (isearch-highlight start end)
- (isearch-dehighlight t))
- ;;(sit-for 0)
- )
-
-
-(defun ispell-highlight-spelling-error-overlay (start end &optional highlight)
- "Highlight the word from START to END using overlays.
-When the optional third arg HIGHLIGHT is set, the word is highlighted
-otherwise it is displayed normally.
-
-The variable `ispell-highlight-face' selects the face to use for highlighting."
- (if highlight
- (progn
- (setq ispell-overlay (make-overlay start end))
- (overlay-put ispell-overlay 'face ispell-highlight-face))
- (delete-overlay ispell-overlay)))
-
-
-(defun ispell-highlight-spelling-error (start end &optional highlight)
- (cond
- ((string-match "Lucid" emacs-version)
- (ispell-highlight-spelling-error-lucid start end highlight))
- ((and (string-lessp "19" emacs-version)
- (featurep 'faces) window-system)
- (ispell-highlight-spelling-error-overlay start end highlight))
- (t (ispell-highlight-spelling-error-generic start end highlight))))
-
-
-(defun ispell-overlay-window (height)
- "Create a window covering the top HEIGHT lines of the current window.
-Ensure that the line above point is still visible but otherwise avoid
-scrolling the current window. Leave the new window selected."
- (save-excursion
- (let ((oldot (save-excursion (forward-line -1) (point)))
- (top (save-excursion (move-to-window-line height) (point))))
- ;; If line above old point (line starting at olddot) would be
- ;; hidden by new window, scroll it to just below new win
- ;; otherwise set top line of other win so it doesn't scroll.
- (if (< oldot top) (setq top oldot))
- ;; NB: Lemacs 19.9 bug: If a window of size N (N includes the mode
- ;; line) is demanded, the last line is not visible.
- ;; At least this happens on AIX 3.2, lemacs w/ Motif, font 9x15.
- ;; So we increment the height for this case.
- (if (string-match "19\.9.*Lucid" (emacs-version))
- (setq height (1+ height)))
- (split-window nil height)
- (set-window-start (next-window) top))))
-
-
-;;; Should we add a compound word match return value?
-(defun ispell-parse-output (output)
- "Parse the OUTPUT string from Ispell and return:
-1: t for an exact match.
-2: A string containing the root word for a match via suffix removal.
-3: A list of possible correct spellings of the format:
- '(\"ORIGINAL-WORD\" OFFSET MISS-LIST GUESS-LIST)
- ORIGINAL-WORD is a string of the possibly misspelled word.
- OFFSET is an integer giving the line offset of the word.
- MISS-LIST and GUESS-LIST are possibly null lists of guesses and misses."
- (cond
- ((string= output "") t) ; for startup with pipes...
- ((string= output "*") t) ; exact match
- ((string= output "-") t) ; compound word match
- ((string= (substring output 0 1) "+") ; found cuz of root word
- (substring output 2)) ; return root word
- (t ; need to process &, ?, and #'s
- (let ((type (substring output 0 1)) ; &, ?, or #
- (original-word (substring output 2 (string-match " " output 2)))
- (cur-count 0) ; contains number of misses + guesses
- count miss-list guess-list offset)
- (setq output (substring output (match-end 0))) ; skip over misspelling
- (if (string= type "#")
- (setq count 0) ; no misses for type #
- (setq count (string-to-int output) ; get number of misses.
- output (substring output (1+ (string-match " " output 1)))))
- (setq offset (string-to-int output))
- (if (string= type "#") ; No miss or guess list.
- (setq output nil)
- (setq output (substring output (1+ (string-match " " output 1)))))
- (while output
- (let ((end (string-match ", \\|\\($\\)" output))) ; end of miss/guess.
- (setq cur-count (1+ cur-count))
- (if (> cur-count count)
- (setq guess-list (cons (substring output 0 end) guess-list))
- (setq miss-list (cons (substring output 0 end) miss-list)))
- (if (match-end 1) ; True only when at end of line.
- (setq output nil) ; no more misses or guesses
- (setq output (substring output (+ end 2))))))
- (list original-word offset miss-list guess-list)))))
-
-
-(defun check-ispell-version ()
- ;; This is a little wasteful as we actually launch ispell twice: once
- ;; to make sure it's the right version, and once for real. But people
- ;; get confused by version mismatches *all* the time (and I've got the
- ;; email to prove it) so I think this is worthwhile. And the -v[ersion]
- ;; option is the only way I can think of to do this that works with
- ;; all versions, since versions earlier than 3.0.09 didn't identify
- ;; themselves on startup.
- (save-excursion
- (let ((case-fold-search t)
- ;; avoid bugs when syntax of `.' changes in various default modes
- (default-major-mode 'fundamental-mode)
- status)
- (set-buffer (get-buffer-create " *ispell-tmp*"))
- (erase-buffer)
- (setq status (call-process ispell-program-name nil t nil "-v"))
- (goto-char (point-min))
- (if (not (memq status '(0 nil)))
- (error "%s exited with %s %s" ispell-program-name
- (if (stringp status) "signal" "code") status))
- (if (not (re-search-forward
- (concat "\\b\\("
- (regexp-quote (car ispell-required-version))
- "\\)\\([0-9]*\\)\\b")
- nil t))
- (error
- "%s version %s* is required: try renaming ispell4.el to ispell.el"
- ispell-program-name (car ispell-required-version))
- ;; check that it is the correct version.
- (if (< (car (read-from-string (buffer-substring
- (match-beginning 2) (match-end 2))))
- (car (cdr ispell-required-version)))
- (setq ispell-offset 0)))
- (kill-buffer (current-buffer)))))
-
-
-(defun ispell-init-process ()
- "Check status of Ispell process and start if necessary."
- (if (and ispell-process
- (eq (process-status ispell-process) 'run)
- ;; If we're using a personal dictionary, assure
- ;; we're in the same default directory!
- (or (not ispell-personal-dictionary)
- (equal ispell-process-directory default-directory)))
- (setq ispell-filter nil ispell-filter-continue nil)
- ;; may need to restart to select new personal dictionary.
- (ispell-kill-ispell t)
- (message "Starting new Ispell process...")
- (sit-for 0)
- (check-ispell-version)
- (setq ispell-process
- (let ((process-connection-type ispell-use-ptys-p))
- (apply 'start-process
- "ispell" nil ispell-program-name
- "-a" ; accept single input lines
- "-m" ; make root/affix combos not in dict
- (let (args)
- ;; Local dictionary becomes the global dictionary in use.
- (if ispell-local-dictionary
- (setq ispell-dictionary ispell-local-dictionary))
- (setq args (ispell-get-ispell-args))
- (if ispell-dictionary ; use specified dictionary
- (setq args
- (append (list "-d" ispell-dictionary) args)))
- (if ispell-personal-dictionary ; use specified pers dict
- (setq args
- (append args
- (list "-p"
- (expand-file-name
- ispell-personal-dictionary)))))
- (setq args (append args ispell-extra-args))
- args)))
- ispell-filter nil
- ispell-filter-continue nil
- ispell-process-directory default-directory)
- (set-process-filter ispell-process 'ispell-filter)
- (accept-process-output ispell-process) ; Get version ID line
- (cond ((null ispell-filter)
- (error "%s did not output version line" ispell-program-name))
- ((and
- (stringp (car ispell-filter))
- (if (string-match "warning: " (car ispell-filter))
- (progn
- (accept-process-output ispell-process 5) ; 1st was warn msg.
- (stringp (car ispell-filter)))
- (null (cdr ispell-filter)))
- (string-match "^@(#) " (car ispell-filter)))
- ;; got the version line as expected (we already know it's the right
- ;; version, so don't bother checking again.)
- nil)
- (t
- ;; Otherwise, it must be an error message. Show the user.
- ;; But first wait to see if some more output is going to arrive.
- ;; Otherwise we get cool errors like "Can't open ".
- (sleep-for 1)
- (accept-process-output)
- (error "%s" (mapconcat 'identity ispell-filter "\n"))))
- (setq ispell-filter nil) ; Discard version ID line
- (let ((extended-char-mode (ispell-get-extended-character-mode)))
- (if extended-char-mode
- (process-send-string ispell-process
- (concat extended-char-mode "\n"))))
- (process-kill-without-query ispell-process)))
-
-;;;###autoload
-(defun ispell-kill-ispell (&optional no-error)
- "Kill current Ispell process (so that you may start a fresh one).
-With NO-ERROR, just return non-nil if there was no Ispell running."
- (interactive)
- (if (not (and ispell-process
- (eq (process-status ispell-process) 'run)))
- (or no-error
- (error "There is no ispell process running!"))
- (kill-process ispell-process)
- (setq ispell-process nil)
- (message "Ispell process killed")
- nil))
-
-
-;;; ispell-change-dictionary is set in some people's hooks. Maybe this should
-;;; call ispell-init-process rather than wait for a spell checking command?
-
-;;;###autoload
-(defun ispell-change-dictionary (dict &optional arg)
- "Change `ispell-dictionary' (q.v.) and kill old Ispell process.
-A new one will be started as soon as necessary.
-
-By just answering RET you can find out what the current dictionary is.
-
-With prefix argument, set the default directory."
- (interactive
- (list (completing-read
- "Use new dictionary (RET for current, SPC to complete): "
- (cons (cons "default" nil) ispell-dictionary-alist) nil t)
- current-prefix-arg))
- (if (equal dict "default") (setq dict nil))
- ;; This relies on completing-read's bug of returning "" for no match
- (cond ((equal dict "")
- (message "Using %s dictionary"
- (or ispell-local-dictionary ispell-dictionary "default")))
- ((and (equal dict ispell-dictionary)
- (or (null ispell-local-dictionary)
- (equal dict ispell-local-dictionary)))
- ;; Specified dictionary is the default already. No-op
- (and (interactive-p)
- (message "No change, using %s dictionary" (or dict "default"))))
- (t ; reset dictionary!
- (if (assoc dict ispell-dictionary-alist)
- (progn
- (if (or arg (null dict)) ; set default dictionary
- (setq ispell-dictionary dict))
- (if (null arg) ; set local dictionary
- (setq ispell-local-dictionary dict)))
- (error "Illegal dictionary: %s" dict))
- (ispell-kill-ispell t)
- (message "(Next %sIspell command will use %s dictionary)"
- (cond ((equal ispell-local-dictionary ispell-dictionary)
- "")
- (arg "global ")
- (t "local "))
- (or (if (or (equal ispell-local-dictionary ispell-dictionary)
- (null arg))
- ispell-local-dictionary
- ispell-dictionary)
- "default")))))
-
-
-;;; Spelling of comments are checked when ispell-check-comments is non-nil.
-
-;;;###autoload
-(defun ispell-region (reg-start reg-end)
- "Interactively check a region for spelling errors."
- (interactive "r") ; Don't flag errors on read-only bufs.
- (ispell-accept-buffer-local-defs) ; set up dictionary, local words, etc.
- (unwind-protect
- (save-excursion
- (message "Spell checking %s using %s dictionary..."
- (if (and (= reg-start (point-min)) (= reg-end (point-max)))
- (buffer-name) "region")
- (or ispell-dictionary "default"))
- ;; Returns cursor to original location.
- (save-window-excursion
- (goto-char reg-start)
- (let ((transient-mark-mode nil)
- ref-type)
- (while (and (not ispell-quit) (< (point) reg-end))
- (let ((start (point))
- (offset-change 0)
- (end (save-excursion (end-of-line) (min (point) reg-end)))
- (ispell-casechars (ispell-get-casechars))
- string)
- (cond ; LOOK AT THIS LINE AND SKIP OR PROCESS
- ((eolp) ; END OF LINE, just go to next line.
- (forward-char 1))
- ((and (null ispell-check-comments) ; SKIPPING COMMENTS
- comment-start ; skip comments that start on the line.
- (search-forward comment-start end t)) ; or found here.
- (if (= (- (point) start) (length comment-start))
- ;; comment starts the line. Skip entire line or region
- (if (string= "" comment-end) ; skip to next line
- (beginning-of-line 2) ; or jump to comment end.
- (search-forward comment-end reg-end 'limit))
- ;; Comment later in line. Check spelling before comment.
- (let ((limit (- (point) (length comment-start))))
- (goto-char (1- limit))
- (if (looking-at "\\\\") ; "quoted" comment, don't skip
- ;; quoted comment. Skip over comment-start
- (if (= start (1- limit))
- (setq limit (+ limit (length comment-start)))
- (setq limit (1- limit))))
- (goto-char start)
- ;; Only check when "casechars" or math before comment
- (if (or (re-search-forward ispell-casechars limit t)
- (re-search-forward "[][()$]" limit t))
- (setq string
- (concat "^" (buffer-substring start limit)
- "\n")
- offset-change (- offset-change ispell-offset)))
- (goto-char limit))))
- ((looking-at "[---#@*+!%~^]") ; SKIP SPECIAL ISPELL CHARACTERS
- (forward-char 1))
- ((or (and ispell-skip-tib ; SKIP TIB REFERENCES OR SGML MARKUP
- (re-search-forward ispell-tib-ref-beginning end t)
- (setq ref-type 'tib))
- (and ispell-skip-sgml
- (re-search-forward "[<&]" end t)
- (setq ref-type 'sgml)))
- (if (or (and (eq 'tib ref-type) ; tib tag is 2 chars.
- (= (- (point) 2) start))
- (and (eq 'sgml ref-type) ; sgml skips 1 char.
- (= (- (point) 1) start)))
- ;; Skip to end of reference, not necessarily on this line
- ;; Return an error if tib/sgml reference not found
- (if (or
- (and
- (eq 'tib ref-type)
- (not
- (re-search-forward ispell-tib-ref-end reg-end t)))
- (and (eq 'sgml ref-type)
- (not (re-search-forward "[>;]" reg-end t))))
- (progn
- (ispell-pdict-save ispell-silently-savep)
- (ding)
- (message
- (concat
- "Open tib or SGML command. Fix buffer or set "
- (if (eq 'tib ref-type)
- "ispell-skip-tib"
- "ispell-skip-sgml")
- " to nil"))
- ;; keep cursor at error location
- (setq ispell-quit (- (point) 2))))
- ;; Check spelling between reference and start of the line.
- (let ((limit (- (point) (if (eq 'tib ref-type) 2 1))))
- (goto-char start)
- (if (or (re-search-forward ispell-casechars limit t)
- (re-search-forward "[][()$]" limit t))
- (setq string
- (concat "^" (buffer-substring start limit)
- "\n")
- offset-change (- offset-change ispell-offset)))
- (goto-char limit))))
- ((or (re-search-forward ispell-casechars end t) ; TEXT EXISTS
- (re-search-forward "[][()$]" end t)) ; or MATH COMMANDS
- (setq string (concat "^" (buffer-substring start end) "\n")
- offset-change (- offset-change ispell-offset))
- (goto-char end))
- (t (beginning-of-line 2))) ; EMPTY LINE, skip it.
-
- (setq end (point)) ; "end" tracks end of region to check.
-
- (if string ; there is something to spell!
- (let (poss)
- ;; send string to spell process and get input.
- (process-send-string ispell-process string)
- (while (progn
- (accept-process-output ispell-process)
- ;; Last item of output contains a blank line.
- (not (string= "" (car ispell-filter)))))
- ;; parse all inputs from the stream one word at a time.
- ;; Place in FIFO order and remove the blank item.
- (setq ispell-filter (nreverse (cdr ispell-filter)))
- (while (and (not ispell-quit) ispell-filter)
- (setq poss (ispell-parse-output (car ispell-filter)))
- (if (listp poss) ; spelling error occurred.
- (let* ((word-start (+ start offset-change
- (car (cdr poss))))
- (word-end (+ word-start
- (length (car poss))))
- replace)
- (goto-char word-start)
- ;; Adjust the horizontal scroll & point
- (ispell-horiz-scroll)
- (goto-char word-end)
- (ispell-horiz-scroll)
- (goto-char word-start)
- (ispell-horiz-scroll)
- (if (/= word-end
- (progn
- (search-forward (car poss) word-end t)
- (point)))
- ;; This occurs due to filter pipe problems
- (error
- (concat "Ispell misalignment: word "
- "`%s' point %d; please retry")
- (car poss) word-start))
- (if (not (pos-visible-in-window-p))
- (sit-for 0))
- (if ispell-keep-choices-win
- (setq replace
- (ispell-command-loop
- (car (cdr (cdr poss)))
- (car (cdr (cdr (cdr poss))))
- (car poss) word-start word-end))
- (save-window-excursion
- (setq replace
- (ispell-command-loop
- (car (cdr (cdr poss)))
- (car (cdr (cdr (cdr poss))))
- (car poss) word-start word-end))))
- (cond
- ((and replace (listp replace))
- ;; REPLACEMENT WORD entered. Recheck line
- ;; starting with the replacement word.
- (setq ispell-filter nil
- string (buffer-substring word-start
- word-end))
- (let ((change (- (length (car replace))
- (length (car poss)))))
- ;; adjust regions
- (setq reg-end (+ reg-end change)
- offset-change (+ offset-change
- change)))
- (if (not (equal (car replace) (car poss)))
- (progn
- (delete-region word-start word-end)
- (insert (car replace))))
- ;; I only need to recheck typed-in replacements
- (if (not (eq 'query-replace
- (car (cdr replace))))
- (backward-char (length (car replace))))
- (setq end (point)) ; reposition for recheck
- ;; when second arg exists, query-replace, saving regions
- (if (car (cdr replace))
- (unwind-protect
- (save-window-excursion
- (set-marker
- ispell-query-replace-marker reg-end)
- ;; Assume case-replace &
- ;; case-fold-search correct?
- (query-replace string (car replace)
- t))
- (setq reg-end
- (marker-position
- ispell-query-replace-marker))
- (set-marker ispell-query-replace-marker
- nil))))
- ((or (null replace)
- (equal 0 replace)) ; ACCEPT/INSERT
- (if (equal 0 replace) ; BUFFER-LOCAL DICT ADD
- (setq reg-end
- (ispell-add-per-file-word-list
- (car poss) reg-end)))
- ;; This avoids pointing out the word that was
- ;; just accepted (via 'i' or 'a') if it follows
- ;; on the same line.
- ;; Redo check following the accepted word.
- (if (and ispell-pdict-modified-p
- (listp ispell-pdict-modified-p))
- ;; Word accepted. Recheck line.
- (setq ispell-pdict-modified-p ; update flag
- (car ispell-pdict-modified-p)
- ispell-filter nil ; discontinue check
- end word-start))) ; reposition loc.
- (replace ; STRING REPLACEMENT for this word.
- (delete-region word-start word-end)
- (insert replace)
- (let ((change (- (length replace)
- (length (car poss)))))
- (setq reg-end (+ reg-end change)
- offset-change (+ offset-change change)
- end (+ end change)))))
- (if (not ispell-quit)
- (message "Continuing spelling check using %s dictionary..."
- (or ispell-dictionary "default")))
- (sit-for 0)))
- ;; finished with line!
- (setq ispell-filter (cdr ispell-filter)))))
- (goto-char end)))))
- (not ispell-quit))
- ;; protected
- (if (get-buffer ispell-choices-buffer)
- (kill-buffer ispell-choices-buffer))
- (if ispell-quit
- (progn
- ;; preserve or clear the region for ispell-continue.
- (if (not (numberp ispell-quit))
- (set-marker ispell-region-end nil)
- ;; Enable ispell-continue.
- (set-marker ispell-region-end reg-end)
- (goto-char ispell-quit))
- ;; Check for aborting
- (if (and ispell-checking-message (numberp ispell-quit))
- (progn
- (setq ispell-quit nil)
- (error "Message send aborted.")))
- (setq ispell-quit nil))
- (set-marker ispell-region-end nil)
- ;; Only save if successful exit.
- (ispell-pdict-save ispell-silently-savep)
- (message "Spell-checking done"))))
-
-
-
-;;;###autoload
-(defun ispell-buffer ()
- "Check the current buffer for spelling errors interactively."
- (interactive)
- (ispell-region (point-min) (point-max)))
-
-
-;;;###autoload
-(defun ispell-continue ()
- (interactive)
- "Continue a spelling session after making some changes."
- (if (not (marker-position ispell-region-end))
- (message "No session to continue. Use 'X' command when checking!")
- (if (not (equal (marker-buffer ispell-region-end) (current-buffer)))
- (message "Must continue ispell from buffer %s"
- (buffer-name (marker-buffer ispell-region-end)))
- (ispell-region (point) (marker-position ispell-region-end)))))
-
-
-;;; Horizontal scrolling
-(defun ispell-horiz-scroll ()
- "Places point within the horizontal visibility of its window area."
- (if truncate-lines ; display truncating lines?
- ;; See if display needs to be scrolled.
- (let ((column (- (current-column) (max (window-hscroll) 1))))
- (if (and (< column 0) (> (window-hscroll) 0))
- (scroll-right (max (- column) 10))
- (if (>= column (- (window-width) 2))
- (scroll-left (max (- column (window-width) -3) 10)))))))
-
-
-;;; Interactive word completion.
-;;; Forces "previous-word" processing. Do we want to make this selectable?
-
-;;;###autoload
-(defun ispell-complete-word (&optional interior-frag)
- "Look up word before or under point in dictionary (see lookup-words command)
-and try to complete it. If optional INTERIOR-FRAG is non-nil then the word
-may be a character sequence inside of a word.
-
-Standard ispell choices are then available."
- (interactive "P")
- (let ((cursor-location (point))
- case-fold-search
- (word (ispell-get-word nil "\\*")) ; force "previous-word" processing.
- start end possibilities replacement)
- (setq start (car (cdr word))
- end (car (cdr (cdr word)))
- word (car word)
- possibilities
- (or (string= word "") ; Will give you every word
- (lookup-words (concat (if interior-frag "*") word "*")
- ispell-complete-word-dict)))
- (cond ((eq possibilities t)
- (message "No word to complete"))
- ((null possibilities)
- (message "No match for \"%s\"" word))
- (t ; There is a modification...
- (cond ; Try and respect case of word.
- ((string-match "^[^A-Z]+$" word)
- (setq possibilities (mapcar 'downcase possibilities)))
- ((string-match "^[^a-z]+$" word)
- (setq possibilities (mapcar 'upcase possibilities)))
- ((string-match "^[A-Z]" word)
- (setq possibilities (mapcar 'capitalize possibilities))))
- (save-window-excursion
- (setq replacement
- (ispell-command-loop possibilities nil word start end)))
- (cond
- ((equal 0 replacement) ; BUFFER-LOCAL ADDITION
- (ispell-add-per-file-word-list word))
- (replacement ; REPLACEMENT WORD
- (delete-region start end)
- (setq word (if (atom replacement) replacement (car replacement))
- cursor-location (+ (- (length word) (- end start))
- cursor-location))
- (insert word)
- (if (not (atom replacement)) ; recheck spelling of replacement.
- (progn
- (goto-char cursor-location)
- (ispell-word nil t)))))
- (if (get-buffer ispell-choices-buffer)
- (kill-buffer ispell-choices-buffer))))
- (ispell-pdict-save ispell-silently-savep)
- (goto-char cursor-location)))
-
-
-;;;###autoload
-(defun ispell-complete-word-interior-frag ()
- "Completes word matching character sequence inside a word."
- (interactive)
- (ispell-complete-word t))
-
-
-;;; **********************************************************************
-;;; Ispell Minor Mode
-;;; **********************************************************************
-
-(defvar ispell-minor-mode nil
- "Non-nil if Ispell minor mode is enabled.")
-;; Variable indicating that ispell minor mode is active.
-(make-variable-buffer-local 'ispell-minor-mode)
-
-(or (assq 'ispell-minor-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(ispell-minor-mode " Spell") minor-mode-alist)))
-
-(defvar ispell-minor-keymap
- (let ((map (make-sparse-keymap)))
- (define-key map " " 'ispell-minor-check)
- (define-key map "\r" 'ispell-minor-check)
- map)
- "Keymap used for Ispell minor mode.")
-
-(or (not (boundp 'minor-mode-map-alist))
- (assoc 'ispell-minor-mode minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons (cons 'ispell-minor-mode ispell-minor-keymap)
- minor-mode-map-alist)))
-
-;;;###autoload
-(defun ispell-minor-mode (&optional arg)
- "Toggle Ispell minor mode.
-With prefix arg, turn Ispell minor mode on iff arg is positive.
-
-In Ispell minor mode, pressing SPC or RET
-warns you if the previous word is incorrectly spelled."
- (interactive "P")
- (setq ispell-minor-mode
- (not (or (and (null arg) ispell-minor-mode)
- (<= (prefix-numeric-value arg) 0))))
- (force-mode-line-update))
-
-(defun ispell-minor-check ()
- ;; Check previous word then continue with the normal binding of this key.
- (interactive "*")
- (let ((ispell-minor-mode nil)
- (ispell-check-only t))
- (save-restriction
- (narrow-to-region (point-min) (point))
- (ispell-word nil t))
- (call-interactively (key-binding (this-command-keys)))))
-
-
-;;; **********************************************************************
-;;; Ispell Message
-;;; **********************************************************************
-;;; Original from D. Quinlan, E. Bradford, A. Albert, and M. Ernst
-
-
-(defvar ispell-message-text-end
- (mapconcat (function identity)
- '(
- ;; Matches postscript files.
- "^%!PS-Adobe-[123].0"
- ;; Matches uuencoded text
- "^begin [0-9][0-9][0-9] .*\nM.*\nM.*\nM"
- ;; Matches shell files (esp. auto-decoding)
- "^#! /bin/[ck]?sh"
- ;; Matches context difference listing
- "\\(diff -c .*\\)?\n\\*\\*\\* .*\n--- .*\n\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*"
- ;; Matches reporter.el bug report
- "^current state:\n==============\n"
- ;; Matches "----------------- cut here"
- ;; and "------- Start of forwarded message",
- ;; or either one with "- " in front.
- "^\\(- \\)?[-=_]+\\s ?\\(cut here\\|\\(Start of \\)?forwarded message\\)")
- "\\|")
- "*End of text which will be checked in ispell-message.
-If it is a string, limit at first occurrence of that regular expression.
-Otherwise, it must be a function which is called to get the limit.")
-
-
-(defvar ispell-message-start-skip
- (mapconcat (function identity)
- '(
- ;; Matches forwarded messages
- "^---* Forwarded Message"
- ;; Matches PGP Public Key block
- "^---*BEGIN PGP [A-Z ]*--*"
- )
- "\\|")
- "Spelling is skipped inside these start/end groups by ispell-message.
-Assumed that blocks are not mutually inclusive.")
-
-
-(defvar ispell-message-end-skip
- (mapconcat (function identity)
- '(
- ;; Matches forwarded messages
- "^--- End of Forwarded Message"
- ;; Matches PGP Public Key block
- "^---*END PGP [A-Z ]*--*"
- )
- "\\|")
- "Spelling is skipped inside these start/end groups by ispell-message.
-Assumed that blocks are not mutually inclusive.")
-
-
-;;;###autoload
-(defun ispell-message ()
- "Check the spelling of a mail message or news post.
-Don't check spelling of message headers except the Subject field.
-Don't check included messages.
-
-To abort spell checking of a message region and send the message anyway,
-use the `x' command. (Any subsequent regions will be checked.)
-The `X' command aborts the message send so that you can edit the buffer.
-
-To spell-check whenever a message is sent, include the appropriate lines
-in your .emacs file:
- (add-hook 'message-send-hook 'ispell-message)
- (add-hook 'mail-send-hook 'ispell-message)
- (add-hook 'mh-before-send-letter-hook 'ispell-message)
-
-You can bind this to the key C-c i in GNUS or mail by adding to
-`news-reply-mode-hook' or `mail-mode-hook' the following lambda expression:
- (function (lambda () (local-set-key \"\\C-ci\" 'ispell-message)))"
- (interactive)
- (save-excursion
- (goto-char (point-min))
- (let* ((internal-messagep (save-excursion
- (re-search-forward
- (concat "^"
- (regexp-quote mail-header-separator)
- "$")
- nil t)))
- (limit (copy-marker
- (cond
- ((not ispell-message-text-end) (point-max))
- ((char-or-string-p ispell-message-text-end)
- (if (re-search-forward ispell-message-text-end nil t)
- (match-beginning 0)
- (point-max)))
- (t (min (point-max) (funcall ispell-message-text-end))))))
- (cite-regexp ;Prefix of inserted text
- (cond
- ((featurep 'supercite) ; sc 3.0
- (concat "\\(" (sc-cite-regexp) "\\)" "\\|"
- (ispell-non-empty-string sc-reference-tag-string)))
- ((featurep 'sc) ; sc 2.3
- (concat "\\(" sc-cite-regexp "\\)" "\\|"
- (ispell-non-empty-string sc-reference-tag-string)))
- ((equal major-mode 'news-reply-mode) ;GNUS 4 & below
- (concat "In article <" "\\|"
- (if mail-yank-prefix
- (ispell-non-empty-string mail-yank-prefix)
- "^ \\|^\t")))
- ((equal major-mode 'message-mode) ;GNUS 5
- (concat ".*@.* writes:$" "\\|"
- (if mail-yank-prefix
- (ispell-non-empty-string mail-yank-prefix)
- "^ \\|^\t")))
- ((equal major-mode 'mh-letter-mode) ; mh mail message
- (ispell-non-empty-string mh-ins-buf-prefix))
- ((not internal-messagep) ; Assume n sent us this message.
- (concat "In [a-zA-Z.]+ you write:" "\\|"
- "In <[^,;&+=]+> [^,;&+=]+ writes:" "\\|"
- " *> *"))
- ((boundp 'vm-included-text-prefix) ; VM mail message
- (concat "[^,;&+=]+ writes:" "\\|"
- (ispell-non-empty-string vm-included-text-prefix)))
- (mail-yank-prefix ; vanilla mail message.
- (ispell-non-empty-string mail-yank-prefix))
- (t "^ \\|^\t")))
- (cite-regexp-start (concat "^[ \t]*$\\|" cite-regexp))
- (cite-regexp-end (concat "^\\(" cite-regexp "\\)"))
- (old-case-fold-search case-fold-search)
- (case-fold-search t)
- (ispell-checking-message t))
- (goto-char (point-min))
- ;; Skip header fields except Subject: without Re:'s
- ;;(search-forward mail-header-separator nil t)
- (while (if internal-messagep
- (< (point) internal-messagep)
- (and (looking-at "[a-zA-Z---]+:\\|\t\\| ")
- (not (eobp))))
- (if (looking-at "Subject: *") ; Spell check new subject fields
- (progn
- (goto-char (match-end 0))
- (if (and (not (looking-at ".*Re\\>"))
- (not (looking-at "\\[")))
- (let ((case-fold-search old-case-fold-search))
- (ispell-region (point)
- (progn
- (end-of-line)
- (while (looking-at "\n[ \t]")
- (end-of-line 2))
- (point)))))))
- (forward-line 1))
- (setq case-fold-search nil)
- ;; Skip mail header, particularly for non-english languages.
- (if (looking-at (concat (regexp-quote mail-header-separator) "$"))
- (forward-line 1))
- (while (< (point) limit)
- ;; Skip across text cited from other messages.
- (while (and (looking-at cite-regexp-start)
- (< (point) limit)
- (zerop (forward-line 1))))
-
- (if (< (point) limit)
- (let* ((start (point))
- ;; Check the next batch of lines that *aren't* cited.
- (end-c (and (re-search-forward cite-regexp-end limit 'end)
- (match-beginning 0)))
- ;; Skip a block of included text.
- (end-fwd (and (goto-char start)
- (re-search-forward ispell-message-start-skip
- limit 'end)
- (progn (beginning-of-line)
- (point))))
- (end (or (and end-c end-fwd (min end-c end-fwd))
- end-c end-fwd
- ;; default to limit of text.
- (marker-position limit))))
- (goto-char start)
- (ispell-region start end)
- (if (and end-fwd (= end end-fwd))
- (progn
- (goto-char end)
- (re-search-forward ispell-message-end-skip limit 'end))
- (goto-char end)))))
- (set-marker limit nil))))
-
-
-(defun ispell-non-empty-string (string)
- (if (or (not string) (string-equal string ""))
- "\\'\\`" ; An unmatchable string if string is null.
- (regexp-quote string)))
-
-
-;;; **********************************************************************
-;;; Buffer Local Functions
-;;; **********************************************************************
-
-
-(defun ispell-accept-buffer-local-defs ()
- "Load all buffer-local information, restarting ispell when necessary."
- (ispell-buffer-local-dict) ; May kill ispell-process.
- (ispell-buffer-local-words) ; Will initialize ispell-process.
- (ispell-buffer-local-parsing))
-
-
-(defun ispell-buffer-local-parsing ()
- "Place Ispell into parsing mode for this buffer.
-Overrides the default parsing mode.
-Includes latex/nroff modes and extended character mode."
- ;; (ispell-init-process) must already be called.
- (process-send-string ispell-process "!\n") ; Put process in terse mode.
- ;; We assume all major modes with "tex-mode" in them should use latex parsing
- (if (or (and (eq ispell-parser 'use-mode-name)
- (string-match "[Tt][Ee][Xx]-mode" (symbol-name major-mode)))
- (eq ispell-parser 'tex))
- (process-send-string ispell-process "+\n") ; set ispell mode to tex
- (process-send-string ispell-process "-\n")) ; set mode to normal (nroff)
- ;; Hard-wire test for SGML & HTML mode.
- (setq ispell-skip-sgml (memq major-mode '(sgml-mode html-mode)))
- ;; Set default extended character mode for given buffer, if any.
- (let ((extended-char-mode (ispell-get-extended-character-mode)))
- (if extended-char-mode
- (process-send-string ispell-process (concat extended-char-mode "\n"))))
- ;; Set buffer-local parsing mode and extended character mode, if specified.
- (save-excursion
- (goto-char (point-min))
- ;; Uses last valid definition
- (while (search-forward ispell-parsing-keyword nil t)
- (let ((end (save-excursion (end-of-line) (point)))
- (case-fold-search t)
- string)
- (while (re-search-forward " *\\([^ \"]+\\)" end t)
- ;; space separated definitions.
- (setq string (buffer-substring (match-beginning 1) (match-end 1)))
- (cond ((string-match "latex-mode" string)
- (process-send-string ispell-process "+\n~tex\n"))
- ((string-match "nroff-mode" string)
- (process-send-string ispell-process "-\n~nroff"))
- ((string-match "~" string) ; Set extended character mode.
- (process-send-string ispell-process (concat string "\n")))
- (t (message "Illegal Ispell Parsing argument!")
- (sit-for 2))))))))
-
-
-;;; Can kill the current ispell process
-
-(defun ispell-buffer-local-dict ()
- "Initializes local dictionary.
-When a dictionary is defined in the buffer (see variable
-`ispell-dictionary-keyword'), it will override the local setting
-from \\[ispell-change-dictionary].
-Both should not be used to define a buffer-local dictionary."
- (save-excursion
- (goto-char (point-min))
- (let (end)
- ;; Override the local variable definition.
- ;; Uses last valid definition.
- (while (search-forward ispell-dictionary-keyword nil t)
- (setq end (save-excursion (end-of-line) (point)))
- (if (re-search-forward " *\\([^ \"]+\\)" end t)
- (setq ispell-local-dictionary
- (buffer-substring (match-beginning 1) (match-end 1)))))
- (goto-char (point-min))
- (while (search-forward ispell-pdict-keyword nil t)
- (setq end (save-excursion (end-of-line) (point)))
- (if (re-search-forward " *\\([^ \"]+\\)" end t)
- (setq ispell-local-pdict
- (buffer-substring (match-beginning 1) (match-end 1)))))))
- ;; Reload if new personal dictionary defined.
- (if (and ispell-local-pdict
- (not (equal ispell-local-pdict ispell-personal-dictionary)))
- (progn
- (ispell-kill-ispell t)
- (setq ispell-personal-dictionary ispell-local-pdict)))
- ;; Reload if new dictionary defined.
- (if (and ispell-local-dictionary
- (not (equal ispell-local-dictionary ispell-dictionary)))
- (ispell-change-dictionary ispell-local-dictionary)))
-
-
-(defun ispell-buffer-local-words ()
- "Loads the buffer-local dictionary in the current buffer."
- (if (and ispell-buffer-local-name
- (not (equal ispell-buffer-local-name (buffer-name))))
- (progn
- (ispell-kill-ispell t)
- (setq ispell-buffer-local-name nil)))
- (ispell-init-process)
- (save-excursion
- (goto-char (point-min))
- (while (search-forward ispell-words-keyword nil t)
- (or ispell-buffer-local-name
- (setq ispell-buffer-local-name (buffer-name)))
- (let ((end (save-excursion (end-of-line) (point)))
- string)
- ;; buffer-local words separated by a space, and can contain
- ;; any character other than a space.
- (while (re-search-forward " *\\([^ ]+\\)" end t)
- (setq string (buffer-substring (match-beginning 1) (match-end 1)))
- (process-send-string ispell-process (concat "@" string "\n")))))))
-
-
-;;; returns optionally adjusted region-end-point.
-
-(defun ispell-add-per-file-word-list (word &optional reg-end)
- "Adds new word to the per-file word list."
- (or ispell-buffer-local-name
- (setq ispell-buffer-local-name (buffer-name)))
- (if (null reg-end)
- (setq reg-end 0))
- (save-excursion
- (goto-char (point-min))
- (let (case-fold-search line-okay search done string)
- (while (not done)
- (setq search (search-forward ispell-words-keyword nil 'move)
- line-okay (< (+ (length word) 1 ; 1 for space after word..
- (progn (end-of-line) (current-column)))
- 80))
- (if (or (and search line-okay)
- (null search))
- (progn
- (setq done t)
- (if (null search)
- (progn
- (open-line 1)
- (setq string (concat comment-start " "
- ispell-words-keyword))
- ;; in case the keyword is in the middle of the file....
- (if (> reg-end (point))
- (setq reg-end (+ reg-end (length string))))
- (insert string)
- (if (and comment-end (not (equal "" comment-end)))
- (save-excursion
- (open-line 1)
- (forward-line 1)
- (insert comment-end)))))
- (if (> reg-end (point))
- (setq reg-end (+ 1 reg-end (length word))))
- (insert (concat " " word)))))))
- reg-end)
-
-
-(defconst ispell-version "2.37 -- Tue Jun 13 12:05:28 EDT 1995")
-
-(provide 'ispell)
-
-
-;;; LOCAL VARIABLES AND BUFFER-LOCAL VALUE EXAMPLES.
-
-;;; Local Variable options:
-;;; mode: name(-mode)
-;;; eval: expression
-;;; local-variable: value
-
-;;; The following sets the buffer local dictionary to english!
-
-;;; Local Variables:
-;;; mode: emacs-lisp
-;;; comment-column: 40
-;;; ispell-local-dictionary: "american"
-;;; End:
-
-
-;;; MORE EXAMPLES OF ISPELL BUFFER-LOCAL VALUES
-
-;;; The following places this file in nroff parsing and extended char modes.
-;;; Local IspellParsing: nroff-mode ~nroff
-;;; Change IspellDict to IspellDict: to enable the following line.
-;;; Local IspellDict english
-;;; Change IspellPersDict to IspellPersDict: to enable the following line.
-;;; Local IspellPersDict ~/.ispell_lisp
-;;; The following were automatically generated by ispell using the 'A' command:
-; LocalWords: ispell ispell-highlight-p ispell-check-comments query-replace
-; LocalWords: ispell-query-replace-choices ispell-skip-tib non-nil tib
-; LocalWords: regexps ispell-tib-ref-beginning ispell-tib-ref-end
-
-;; ispell.el ends here
diff --git a/lisp/textmodes/makeinfo.el b/lisp/textmodes/makeinfo.el
deleted file mode 100644
index a649d522156..00000000000
--- a/lisp/textmodes/makeinfo.el
+++ /dev/null
@@ -1,247 +0,0 @@
-;;; makeinfo.el --- run makeinfo conveniently
-
-;; Copyright (C) 1991, 1993 Free Software Foundation, Inc.
-
-;; Author: Robert J. Chassell
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; The Texinfo mode `makeinfo' related commands are:
-
-;; makeinfo-region to run makeinfo on the current region.
-;; makeinfo-buffer to run makeinfo on the current buffer, or
-;; with optional prefix arg, on current region
-;; kill-compilation to kill currently running makeinfo job
-;; makeinfo-recenter-makeinfo-buffer to redisplay *compilation* buffer
-
-;;; Keybindings (defined in `texinfo.el')
-
-;; makeinfo bindings
-; (define-key texinfo-mode-map "\C-c\C-m\C-r" 'makeinfo-region)
-; (define-key texinfo-mode-map "\C-c\C-m\C-b" 'makeinfo-buffer)
-; (define-key texinfo-mode-map "\C-c\C-m\C-k" 'kill-compilation)
-; (define-key texinfo-mode-map "\C-c\C-m\C-l"
-; 'makeinfo-recenter-compilation-buffer)
-
-;;; Code:
-
-;;; Variables used by `makeinfo'
-
-(require 'compile)
-
-(defvar makeinfo-run-command "makeinfo"
- "*Command used to run `makeinfo' subjob.
-The name of the file is appended to this string, separated by a space.")
-
-(defvar makeinfo-options "--fill-column=70"
- "*String containing options for running `makeinfo'.
-Do not include `--footnote-style' or `--paragraph-indent';
-the proper way to specify those is with the Texinfo commands
-`@footnotestyle` and `@paragraphindent'.")
-
-(require 'texinfo)
-
-(defvar makeinfo-compilation-process nil
- "Process that runs `makeinfo'. Should start out nil.")
-
-(defvar makeinfo-temp-file nil
- "Temporary file name used for text being sent as input to `makeinfo'.")
-
-(defvar makeinfo-output-file-name nil
- "Info file name used for text output by `makeinfo'.")
-
-
-;;; The `makeinfo' function definitions
-
-(defun makeinfo-region (region-beginning region-end)
- "Make Info file from region of current Texinfo file, and switch to it.
-
-This command does not offer the `next-error' feature since it would
-apply to a temporary file, not the original; use the `makeinfo-buffer'
-command to gain use of `next-error'."
-
- (interactive "r")
- (let (filename-or-header
- filename-or-header-beginning
- filename-or-header-end)
- ;; Cannot use `let' for makeinfo-temp-file or
- ;; makeinfo-output-file-name since `makeinfo-compilation-sentinel'
- ;; needs them.
-
- (setq makeinfo-temp-file
- (concat
- (make-temp-name
- (substring (buffer-file-name)
- 0
- (or (string-match "\\.tex" (buffer-file-name))
- (length (buffer-file-name)))))
- ".texinfo"))
-
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (let ((search-end (save-excursion (forward-line 100) (point))))
- ;; Find and record the Info filename,
- ;; or else explain that a filename is needed.
- (if (re-search-forward
- "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*"
- search-end t)
- (setq makeinfo-output-file-name
- (buffer-substring (match-beginning 1) (match-end 1)))
- (error
- "The texinfo file needs a line saying: @setfilename <name>"))
-
- ;; Find header and specify its beginning and end.
- (goto-char (point-min))
- (if (and
- (prog1
- (search-forward tex-start-of-header search-end t)
- (beginning-of-line)
- ;; Mark beginning of header.
- (setq filename-or-header-beginning (point)))
- (prog1
- (search-forward tex-end-of-header nil t)
- (beginning-of-line)
- ;; Mark end of header
- (setq filename-or-header-end (point))))
-
- ;; Insert the header into the temporary file.
- (write-region
- (min filename-or-header-beginning region-beginning)
- filename-or-header-end
- makeinfo-temp-file nil nil)
-
- ;; Else no header; insert @filename line into temporary file.
- (goto-char (point-min))
- (search-forward "@setfilename" search-end t)
- (beginning-of-line)
- (setq filename-or-header-beginning (point))
- (forward-line 1)
- (setq filename-or-header-end (point))
- (write-region
- (min filename-or-header-beginning region-beginning)
- filename-or-header-end
- makeinfo-temp-file nil nil))
-
- ;; Insert the region into the file.
- (write-region
- (max region-beginning filename-or-header-end)
- region-end
- makeinfo-temp-file t nil)
-
- ;; Run the `makeinfo-compile' command in the *compilation* buffer
- (save-excursion
- (makeinfo-compile
- (concat makeinfo-run-command
- " "
- makeinfo-options
- " "
- makeinfo-temp-file)
- "Use `makeinfo-buffer' to gain use of the `next-error' command"
- nil)))))))
-
-;;; Actually run makeinfo. COMMAND is the command to run.
-;;; ERROR-MESSAGE is what to say when next-error can't find another error.
-;;; If PARSE-ERRORS is non-nil, do try to parse error messages.
-(defun makeinfo-compile (command error-message parse-errors)
- (let ((buffer
- (compile-internal command error-message nil
- (and (not parse-errors)
- ;; If we do want to parse errors, pass nil.
- ;; Otherwise, use this function, which won't
- ;; ever find any errors.
- '(lambda (&rest ignore)
- (setq compilation-error-list nil))))))
- (set-process-sentinel (get-buffer-process buffer)
- 'makeinfo-compilation-sentinel)))
-
-;; Delete makeinfo-temp-file after processing is finished,
-;; and visit Info file.
-;; This function is called when the compilation process changes state.
-;; Based on `compilation-sentinel' in compile.el
-(defun makeinfo-compilation-sentinel (proc msg)
- (compilation-sentinel proc msg)
- (if (and makeinfo-temp-file (file-exists-p makeinfo-temp-file))
- (delete-file makeinfo-temp-file))
- ;; Always use the version on disk.
- (if (get-file-buffer makeinfo-output-file-name)
- (progn (set-buffer makeinfo-output-file-name)
- (revert-buffer t t))
- (find-file makeinfo-output-file-name))
- (goto-char (point-min)))
-
-(defun makeinfo-buffer ()
- "Make Info file from current buffer.
-
-Use the \\[next-error] command to move to the next error
-\(if there are errors\)."
-
- (interactive)
- (cond ((null buffer-file-name)
- (error "Buffer not visiting any file"))
- ((buffer-modified-p)
- (if (y-or-n-p "Buffer modified; do you want to save it? ")
- (save-buffer))))
-
- ;; Find and record the Info filename,
- ;; or else explain that a filename is needed.
- (save-excursion
- (goto-char (point-min))
- (let ((search-end (save-excursion (forward-line 100) (point))))
- (if (re-search-forward
- "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*"
- search-end t)
- (setq makeinfo-output-file-name
- (buffer-substring (match-beginning 1) (match-end 1)))
- (error
- "The texinfo file needs a line saying: @setfilename <name>"))))
-
- (save-excursion
- (makeinfo-compile
- (concat makeinfo-run-command " " makeinfo-options
- " " buffer-file-name)
- "No more errors."
- t)))
-
-(defun makeinfo-recenter-compilation-buffer (linenum)
- "Redisplay `*compilation*' buffer so 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 ((makeinfo-buffer (get-buffer "*compilation*"))
- (old-buffer (current-buffer)))
- (if (null makeinfo-buffer)
- (message "No *compilation* buffer")
- (pop-to-buffer makeinfo-buffer)
- (bury-buffer makeinfo-buffer)
- (goto-char (point-max))
- (recenter (if linenum
- (prefix-numeric-value linenum)
- (/ (window-height) 2)))
- (pop-to-buffer old-buffer)
- )))
-
-;;; Place `provide' at end of file.
-(provide 'makeinfo)
-
-;;; makeinfo.el ends here
-
diff --git a/lisp/textmodes/nroff-mode.el b/lisp/textmodes/nroff-mode.el
deleted file mode 100644
index 71ef6c2643e..00000000000
--- a/lisp/textmodes/nroff-mode.el
+++ /dev/null
@@ -1,270 +0,0 @@
-;;; nroff-mode.el --- GNU Emacs major mode for editing nroff source
-
-;; Copyright (C) 1985, 1986, 1994, 1995 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: wp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package is a major mode for editing nroff source code. It knows
-;; about various nroff constructs, ms, mm, and me macros, and will fill
-;; and indent paragraphs properly in their presence. It also includes
-;; a command to count text lines (excluding nroff constructs), a command
-;; to center a line, and movement commands that know how to skip macros.
-
-;; Paragraph filling and line-counting currently don't respect comments,
-;; as they should.
-
-;;; Code:
-
-(defvar nroff-mode-abbrev-table nil
- "Abbrev table used while in nroff mode.")
-(define-abbrev-table 'nroff-mode-abbrev-table ())
-
-(defvar nroff-mode-map nil
- "Major mode keymap for nroff mode.")
-(if (not nroff-mode-map)
- (progn
- (setq nroff-mode-map (make-sparse-keymap))
- (define-key nroff-mode-map "\t" 'tab-to-tab-stop)
- (define-key nroff-mode-map "\es" 'center-line)
- (define-key nroff-mode-map "\e?" 'count-text-lines)
- (define-key nroff-mode-map "\n" 'electric-nroff-newline)
- (define-key nroff-mode-map "\en" 'forward-text-line)
- (define-key nroff-mode-map "\ep" 'backward-text-line)))
-
-(defvar nroff-mode-syntax-table nil
- "Syntax table used while in nroff mode.")
-
-(defvar nroff-font-lock-keywords
- (list
- ;; Directives are . or ' at start of line, followed by
- ;; optional whitespace, then command (which my be longer than
- ;; 2 characters in groff). Perhaps the arguments should be
- ;; fontified as well.
- "^[.']\\s-*\\sw+"
- ;; There are numerous groff escapes; the following get things
- ;; like \-, \(em (standard troff) and \f[bar] (groff
- ;; variants). This won't currently do groff's \A'foo' and
- ;; the like properly. One might expect it to highlight an escape's
- ;; arguments in common cases, like \f.
- (concat "\\\\" ; backslash
- "\\(" ; followed by various possibilities
- (mapconcat 'identity
- '("[f*n]*\\[.+]" ; some groff extensions
- "(.." ; two chars after (
- "[^(\"]" ; single char escape
- ) "\\|")
- "\\)")
- )
- "Font-lock highlighting control in nroff-mode.")
-
-;;;###autoload
-(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
-closing requests for requests that are used in matched pairs."
- (interactive)
- (kill-all-local-variables)
- (use-local-map nroff-mode-map)
- (setq mode-name "Nroff")
- (setq major-mode 'nroff-mode)
- (if nroff-mode-syntax-table
- ()
- (setq nroff-mode-syntax-table (copy-syntax-table text-mode-syntax-table))
- ;; " isn't given string quote syntax in text-mode but it
- ;; (arguably) should be for use round nroff arguments (with ` and
- ;; ' used otherwise).
- (modify-syntax-entry ?\" "\" 2" nroff-mode-syntax-table)
- ;; Comments are delimited by \" and newline.
- (modify-syntax-entry ?\\ "\\ 1" nroff-mode-syntax-table)
- (modify-syntax-entry ?\n "> 1" nroff-mode-syntax-table))
- (set-syntax-table nroff-mode-syntax-table)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(nroff-font-lock-keywords nil t))
- (setq local-abbrev-table nroff-mode-abbrev-table)
- (make-local-variable 'nroff-electric-mode)
- (setq nroff-electric-mode nil)
- (make-local-variable 'outline-regexp)
- (setq outline-regexp "\\.H[ ]+[1-7]+ ")
- (make-local-variable 'outline-level)
- (setq outline-level 'nroff-outline-level)
- ;; now define a bunch of variables for use by commands in this mode
- (make-local-variable 'page-delimiter)
- (setq page-delimiter "^\\.\\(bp\\|SK\\|OP\\)")
- (make-local-variable 'paragraph-start)
- (setq paragraph-start (concat "[.']\\|" paragraph-start))
- (make-local-variable 'paragraph-separate)
- (setq paragraph-separate (concat "[.']\\|" paragraph-separate))
- ;; comment syntax added by mit-erl!gildea 18 Apr 86
- (make-local-variable 'comment-start)
- (setq comment-start "\\\" ")
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip "\\\\\"[ \t]*")
- (make-local-variable 'comment-column)
- (setq comment-column 24)
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'nroff-comment-indent)
- (run-hooks 'text-mode-hook 'nroff-mode-hook))
-
-(defun nroff-outline-level ()
- (save-excursion
- (looking-at outline-regexp)
- (skip-chars-forward ".H ")
- (string-to-int (buffer-substring (point) (+ 1 (point))))))
-
-;;; Compute how much to indent a comment in nroff/troff source.
-;;; By mit-erl!gildea April 86
-(defun nroff-comment-indent ()
- "Compute indent for an nroff/troff comment.
-Puts a full-stop before comments on a line by themselves."
- (let ((pt (point)))
- (unwind-protect
- (progn
- (skip-chars-backward " \t")
- (if (bolp)
- (progn
- (setq pt (1+ pt))
- (insert ?.)
- 1)
- (if (save-excursion
- (backward-char 1)
- (looking-at "^[.']"))
- 1
- (max comment-column
- (* 8 (/ (+ (current-column)
- 9) 8)))))) ; add 9 to ensure at least two blanks
- (goto-char pt))))
-
-(defun count-text-lines (start end &optional print)
- "Count lines in region, except for nroff request lines.
-All lines not starting with a period are counted up.
-Interactively, print result in echo area.
-Noninteractively, return number of non-request lines from START to END."
- (interactive "r\np")
- (if print
- (message "Region has %d text lines" (count-text-lines start end))
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (goto-char (point-min))
- (- (buffer-size) (forward-text-line (buffer-size)))))))
-
-(defun forward-text-line (&optional cnt)
- "Go forward one nroff text line, skipping lines of nroff requests.
-An argument is a repeat count; if negative, move backward."
- (interactive "p")
- (if (not cnt) (setq cnt 1))
- (while (and (> cnt 0) (not (eobp)))
- (forward-line 1)
- (while (and (not (eobp)) (looking-at "[.']."))
- (forward-line 1))
- (setq cnt (- cnt 1)))
- (while (and (< cnt 0) (not (bobp)))
- (forward-line -1)
- (while (and (not (bobp))
- (looking-at "[.']."))
- (forward-line -1))
- (setq cnt (+ cnt 1)))
- cnt)
-
-(defun backward-text-line (&optional cnt)
- "Go backward one nroff text line, skipping lines of nroff requests.
-An argument is a repeat count; negative means move forward."
- (interactive "p")
- (forward-text-line (- cnt)))
-
-(defconst nroff-brace-table
- '((".(b" . ".)b")
- (".(l" . ".)l")
- (".(q" . ".)q")
- (".(c" . ".)c")
- (".(x" . ".)x")
- (".(z" . ".)z")
- (".(d" . ".)d")
- (".(f" . ".)f")
- (".LG" . ".NL")
- (".SM" . ".NL")
- (".LD" . ".DE")
- (".CD" . ".DE")
- (".BD" . ".DE")
- (".DS" . ".DE")
- (".DF" . ".DE")
- (".FS" . ".FE")
- (".KS" . ".KE")
- (".KF" . ".KE")
- (".LB" . ".LE")
- (".AL" . ".LE")
- (".BL" . ".LE")
- (".DL" . ".LE")
- (".ML" . ".LE")
- (".RL" . ".LE")
- (".VL" . ".LE")
- (".RS" . ".RE")
- (".TS" . ".TE")
- (".EQ" . ".EN")
- (".PS" . ".PE")
- (".BS" . ".BE")
- (".G1" . ".G2") ; grap
- (".na" . ".ad b")
- (".nf" . ".fi")
- (".de" . "..")))
-
-(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,
-automatically inserts the matching closing request after point."
- (interactive "P")
- (let ((completion (save-excursion
- (beginning-of-line)
- (and (null arg)
- nroff-electric-mode
- (<= (point) (- (point-max) 3))
- (cdr (assoc (buffer-substring (point)
- (+ 3 (point)))
- nroff-brace-table)))))
- (needs-nl (not (looking-at "[ \t]*$"))))
- (if (null completion)
- (newline (prefix-numeric-value arg))
- (save-excursion
- (insert "\n\n" completion)
- (if needs-nl (insert "\n")))
- (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."
- (interactive "P")
- (or (eq major-mode 'nroff-mode) (error "Must be in nroff mode"))
- (or (assq 'nroff-electric-mode minor-mode-alist)
- (setq minor-mode-alist (append minor-mode-alist
- (list '(nroff-electric-mode
- " Electric")))))
- (setq nroff-electric-mode
- (cond ((null arg) (null nroff-electric-mode))
- (t (> (prefix-numeric-value arg) 0)))))
-
-;;; nroff-mode.el ends here
diff --git a/lisp/textmodes/ooutline.el b/lisp/textmodes/ooutline.el
deleted file mode 100644
index af053cc3245..00000000000
--- a/lisp/textmodes/ooutline.el
+++ /dev/null
@@ -1,573 +0,0 @@
-;;; outline.el --- outline mode commands for Emacs
-
-;; Copyright (C) 1986, 1993, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: outlines
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package is a major mode for editing outline-format documents.
-;; An outline can be `abstracted' to show headers at any given level,
-;; with all stuff below hidden. See the Emacs manual for details.
-
-;;; Code:
-
-;; Jan '86, Some new features added by Peter Desnoyers and rewritten by RMS.
-
-(defvar outline-regexp nil
- "*Regular expression to match the beginning of a heading.
-Any line whose beginning matches this regexp is considered to start 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.")
-
-;; Can't initialize this in the defvar above -- some major modes have
-;; already assigned a local value to it.
-(or (default-value 'outline-regexp)
- (setq-default outline-regexp "[*\^L]+"))
-
-(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-prefix-map nil)
-
-(if outline-mode-prefix-map
- nil
- (setq outline-mode-prefix-map (make-sparse-keymap))
- (define-key outline-mode-prefix-map "\C-n" 'outline-next-visible-heading)
- (define-key outline-mode-prefix-map "\C-p" 'outline-previous-visible-heading)
- (define-key outline-mode-prefix-map "\C-i" 'show-children)
- (define-key outline-mode-prefix-map "\C-s" 'show-subtree)
- (define-key outline-mode-prefix-map "\C-d" 'hide-subtree)
- (define-key outline-mode-prefix-map "\C-u" 'outline-up-heading)
- (define-key outline-mode-prefix-map "\C-f" 'outline-forward-same-level)
- (define-key outline-mode-prefix-map "\C-b" 'outline-backward-same-level)
- (define-key outline-mode-prefix-map "\C-t" 'hide-body)
- (define-key outline-mode-prefix-map "\C-a" 'show-all)
- (define-key outline-mode-prefix-map "\C-c" 'hide-entry)
- (define-key outline-mode-prefix-map "\C-e" 'show-entry)
- (define-key outline-mode-prefix-map "\C-l" 'hide-leaves)
- (define-key outline-mode-prefix-map "\C-k" 'show-branches)
- (define-key outline-mode-prefix-map "\C-q" 'hide-sublevels)
- (define-key outline-mode-prefix-map "\C-o" 'hide-other))
-
-(defvar outline-mode-menu-bar-map nil)
-(if outline-mode-menu-bar-map
- nil
- (setq outline-mode-menu-bar-map (make-sparse-keymap))
-
- (define-key outline-mode-menu-bar-map [hide]
- (cons "Hide" (make-sparse-keymap "Hide")))
-
- (define-key outline-mode-menu-bar-map [hide hide-other]
- '("Hide Other" . hide-other))
- (define-key outline-mode-menu-bar-map [hide hide-sublevels]
- '("Hide Sublevels" . hide-sublevels))
- (define-key outline-mode-menu-bar-map [hide hide-subtree]
- '("Hide Subtree" . hide-subtree))
- (define-key outline-mode-menu-bar-map [hide hide-entry]
- '("Hide Entry" . hide-entry))
- (define-key outline-mode-menu-bar-map [hide hide-body]
- '("Hide Body" . hide-body))
- (define-key outline-mode-menu-bar-map [hide hide-leaves]
- '("Hide Leaves" . hide-leaves))
-
- (define-key outline-mode-menu-bar-map [show]
- (cons "Show" (make-sparse-keymap "Show")))
-
- (define-key outline-mode-menu-bar-map [show show-subtree]
- '("Show Subtree" . show-subtree))
- (define-key outline-mode-menu-bar-map [show show-children]
- '("Show Children" . show-children))
- (define-key outline-mode-menu-bar-map [show show-branches]
- '("Show Branches" . show-branches))
- (define-key outline-mode-menu-bar-map [show show-entry]
- '("Show Entry" . show-entry))
- (define-key outline-mode-menu-bar-map [show show-all]
- '("Show All" . show-all))
-
- (define-key outline-mode-menu-bar-map [headings]
- (cons "Headings" (make-sparse-keymap "Headings")))
-
- (define-key outline-mode-menu-bar-map [headings outline-backward-same-level]
- '("Previous Same Level" . outline-backward-same-level))
- (define-key outline-mode-menu-bar-map [headings outline-forward-same-level]
- '("Next Same Level" . outline-forward-same-level))
- (define-key outline-mode-menu-bar-map [headings outline-previous-visible-heading]
- '("Previous" . outline-previous-visible-heading))
- (define-key outline-mode-menu-bar-map [headings outline-next-visible-heading]
- '("Next" . outline-next-visible-heading))
- (define-key outline-mode-menu-bar-map [headings outline-up-heading]
- '("Up" . outline-up-heading)))
-
-(defvar outline-mode-map nil "")
-
-(if outline-mode-map
- nil
- (setq outline-mode-map (nconc (make-sparse-keymap) text-mode-map))
- (define-key outline-mode-map "\C-c" outline-mode-prefix-map)
- (define-key outline-mode-map [menu-bar] outline-mode-menu-bar-map))
-
-(defvar outline-minor-mode nil
- "Non-nil if using Outline mode as a minor mode of some other mode.")
-(make-variable-buffer-local 'outline-minor-mode)
-(put 'outline-minor-mode 'permanent-local t)
-(or (assq 'outline-minor-mode minor-mode-alist)
- (setq minor-mode-alist (append minor-mode-alist
- (list '(outline-minor-mode " Outl")))))
-
-(defvar outline-font-lock-keywords
- '(;; Highlight headings according to the level.
- ("^\\([*]+\\)[ \t]*\\([^\n\r]+\\)?[ \t]*[\n\r]"
- (1 font-lock-string-face)
- (2 (let ((len (- (match-end 1) (match-beginning 1))))
- (or (cdr (assq len '((1 . font-lock-function-name-face)
- (2 . font-lock-keyword-face)
- (3 . font-lock-comment-face))))
- font-lock-variable-name-face))
- nil t))
- ;; Highlight citations of the form [1] and [Mar94].
- ("\\[\\([A-Z][A-Za-z]+\\)*[0-9]+\\]" . font-lock-type-face))
- "Additional expressions to highlight in Outline mode.")
-
-;;;###autoload
-(defun outline-mode ()
- "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:\\<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
-
-\\[hide-body] make all text invisible (not headings).
-\\[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.
- No effect on body, or subheadings 2 or more levels down.
- With arg N, affects subheadings N levels down.
-\\[hide-entry] make immediately following body invisible.
-\\[show-entry] make it visible.
-\\[hide-leaves] make body under heading and under its subheadings invisible.
- The subheadings remain visible.
-\\[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."
- (interactive)
- (kill-all-local-variables)
- (setq selective-display t)
- (use-local-map outline-mode-map)
- (setq mode-name "Outline")
- (setq major-mode 'outline-mode)
- (define-abbrev-table 'text-mode-abbrev-table ())
- (setq local-abbrev-table text-mode-abbrev-table)
- (set-syntax-table text-mode-syntax-table)
- (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 "\\)"))
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(outline-font-lock-keywords t))
- (make-local-variable 'change-major-mode-hook)
- (add-hook 'change-major-mode-hook 'show-all)
- (run-hooks 'text-mode-hook 'outline-mode-hook))
-
-(defvar outline-minor-mode-prefix "\C-c@"
- "*Prefix key to use for Outline commands in Outline minor mode.
-The value of this variable is checked as part of loading Outline mode.
-After that, changing the prefix key requires manipulating keymaps.")
-
-(defvar outline-minor-mode-map nil)
-(if outline-minor-mode-map
- nil
- (setq outline-minor-mode-map (make-sparse-keymap))
- (define-key outline-minor-mode-map [menu-bar]
- outline-mode-menu-bar-map)
- (define-key outline-minor-mode-map outline-minor-mode-prefix
- outline-mode-prefix-map))
-
-(or (assq 'outline-minor-mode minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons (cons 'outline-minor-mode outline-minor-mode-map)
- minor-mode-map-alist)))
-
-;;;###autoload
-(defun outline-minor-mode (&optional arg)
- "Toggle Outline minor mode.
-With arg, turn Outline minor mode on if arg is positive, off otherwise.
-See the command `outline-mode' for more information on this mode."
- (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)
- (run-hooks 'outline-minor-mode-hook))
- (setq selective-display nil))
- ;; When turning off outline mode, get rid of any ^M's.
- (or outline-minor-mode
- (outline-flag-region (point-min) (point-max) ?\n))
- (force-mode-line-update))
-
-(defvar outline-level 'outline-level
- "Function of no args to compute a header's nesting level in an outline.
-It can assume point is at the beginning of a header line.")
-
-;; This used to count columns rather than characters, but that made ^L
-;; appear to be at level 2 instead of 1. Columns would be better for
-;; tab handling, but the default regexp doesn't use tabs, and anyone
-;; who changes the regexp can also redefine the outline-level variable
-;; as appropriate.
-(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 number of characters that `outline-regexp' matches."
- (save-excursion
- (looking-at outline-regexp)
- (- (match-end 0) (match-beginning 0))))
-
-(defun outline-next-preface ()
- "Skip forward to just before the next heading line.
-If there's no following heading line, stop before the newline
-at the end of the buffer."
- (if (re-search-forward (concat "[\n\^M]\\(" outline-regexp "\\)")
- nil 'move)
- (goto-char (match-beginning 0)))
- (if (memq (preceding-char) '(?\n ?\^M))
- (forward-char -1)))
-
-(defun outline-next-heading ()
- "Move to the next (possibly invisible) heading line."
- (interactive)
- (if (re-search-forward (concat "[\n\^M]\\(" outline-regexp "\\)")
- nil 'move)
- (goto-char (1+ (match-beginning 0)))))
-
-(defun outline-back-to-heading ()
- "Move to previous heading line, or beg of this line if it's a heading.
-Only visible heading lines are considered."
- (beginning-of-line)
- (or (outline-on-heading-p)
- (re-search-backward (concat "^\\(" outline-regexp "\\)") nil t)
- (error "before first heading")))
-
-(defun outline-on-heading-p ()
- "Return t if point is on a (visible) heading line."
- (save-excursion
- (beginning-of-line)
- (and (bolp)
- (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)."
- (interactive "p")
- (if (< arg 0)
- (beginning-of-line)
- (end-of-line))
- (or (re-search-forward (concat "^\\(" outline-regexp "\\)") nil t arg)
- (error ""))
- (beginning-of-line))
-
-(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)."
- (interactive "p")
- (outline-next-visible-heading (- arg)))
-
-(defun outline-flag-region (from to flag)
- "Hides or shows lines from FROM to TO, according to FLAG.
-If FLAG is `\\n' (newline character) then text is shown,
-while if FLAG is `\\^M' (control-M) the text is hidden."
- (let (buffer-read-only)
- (subst-char-in-region from to
- (if (= flag ?\n) ?\^M ?\n)
- flag t)))
-
-(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)))
-
-(defun show-entry ()
- "Show the body directly following this heading."
- (interactive)
- (save-excursion
- (outline-flag-region (point) (progn (outline-next-preface) (point)) ?\n)))
-
-(defun hide-body ()
- "Hide all of buffer except headings."
- (interactive)
- (hide-region-body (point-min) (point-max)))
-
-(defun hide-region-body (start end)
- "Hide all body lines in the region, but not headings."
- (save-excursion
- (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)
- (if (not (eobp))
- (progn
- (forward-char
- (if (looking-at "[\n\^M][\n\^M]")
- 2 1))
- (outline-end-of-heading)))))))
-
-(defun show-all ()
- "Show all of the text in the buffer."
- (interactive)
- (outline-flag-region (point-min) (point-max) ?\n))
-
-(defun hide-subtree ()
- "Hide everything after this heading at deeper levels."
- (interactive)
- (outline-flag-subtree ?\^M))
-
-(defun hide-leaves ()
- "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 ()
- "Show everything after this heading at deeper levels."
- (interactive)
- (outline-flag-subtree ?\n))
-
-(defun hide-sublevels (levels)
- "Hide everything but the top LEVELS levels of headers, in whole buffer."
- (interactive "p")
- (if (< levels 1)
- (error "Must keep at least one level of headers"))
- (setq levels (1- levels))
- (save-excursion
- (goto-char (point-min))
- ;; Keep advancing to the next top-level heading.
- (while (or (and (bobp) (outline-on-heading-p))
- (outline-next-heading))
- (let ((end (save-excursion (outline-end-of-subtree) (point))))
- ;; Hide everything under that.
- (outline-flag-region (point) end ?\^M)
- ;; Show the first LEVELS levels under that.
- (if (> levels 0)
- (show-children levels))
- ;; Move to the next, since we already found it.
- (goto-char end)))))
-
-(defun hide-other ()
- "Hide everything except for the current body and the parent headings."
- (interactive)
- (hide-sublevels 1)
- (let ((last (point))
- (pos (point)))
- (while (save-excursion
- (and (re-search-backward "[\n\r]" nil t)
- (eq (following-char) ?\r)))
- (save-excursion
- (beginning-of-line)
- (if (eq last (point))
- (progn
- (outline-next-heading)
- (outline-flag-region last (point) ?\n))
- (show-children)
- (setq last (point)))))))
-
-(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)
- (let ((opoint (point))
- (first t)
- (level (funcall outline-level)))
- (while (and (not (eobp))
- (or first (> (funcall outline-level) level)))
- (setq first nil)
- (outline-next-heading))
- (if (memq (preceding-char) '(?\n ?\^M))
- (progn
- ;; Go to end of line before heading
- (forward-char -1)
- (if (memq (preceding-char) '(?\n ?\^M))
- ;; leave blank line before heading
- (forward-char -1))))))
-
-(defun show-branches ()
- "Show all subheadings of this heading, but not their bodies."
- (interactive)
- (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
- (outline-back-to-heading)
- (let ((start-level (funcall outline-level)))
- (outline-next-heading)
- (if (eobp)
- 1
- (max 1 (- (funcall outline-level) start-level)))))))
- (save-excursion
- (save-restriction
- (outline-back-to-heading)
- (setq level (+ level (funcall outline-level)))
- (narrow-to-region (point)
- (progn (outline-end-of-subtree)
- (if (eobp) (point-max) (1+ (point)))))
- (goto-char (point-min))
- (while (and (not (eobp))
- (progn
- (outline-next-heading)
- (not (eobp))))
- (if (<= (funcall 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)))))))
-
-(defun outline-up-heading (arg)
- "Move to the heading line of which the present line is a subheading.
-With argument, move up ARG levels."
- (interactive "p")
- (outline-back-to-heading)
- (if (eq (funcall outline-level) 1)
- (error ""))
- (while (and (> (funcall outline-level) 1)
- (> arg 0)
- (not (bobp)))
- (let ((present-level (funcall outline-level)))
- (while (not (< (funcall outline-level) present-level))
- (outline-previous-visible-heading 1))
- (setq arg (- arg 1)))))
-
-(defun outline-forward-same-level (arg)
- "Move forward to the ARG'th subheading at same level as this one.
-Stop at the first and last subheadings of a superior heading."
- (interactive "p")
- (outline-back-to-heading)
- (while (> arg 0)
- (let ((point-to-move-to (save-excursion
- (outline-get-next-sibling))))
- (if point-to-move-to
- (progn
- (goto-char point-to-move-to)
- (setq arg (1- arg)))
- (progn
- (setq arg 0)
- (error ""))))))
-
-(defun outline-get-next-sibling ()
- "Move to next heading of the same level, and return point or nil if none."
- (let ((level (funcall outline-level)))
- (outline-next-visible-heading 1)
- (while (and (> (funcall outline-level) level)
- (not (eobp)))
- (outline-next-visible-heading 1))
- (if (< (funcall outline-level) level)
- nil
- (point))))
-
-(defun outline-backward-same-level (arg)
- "Move backward to the ARG'th subheading at same level as this one.
-Stop at the first and last subheadings of a superior heading."
- (interactive "p")
- (outline-back-to-heading)
- (while (> arg 0)
- (let ((point-to-move-to (save-excursion
- (outline-get-last-sibling))))
- (if point-to-move-to
- (progn
- (goto-char point-to-move-to)
- (setq arg (1- arg)))
- (progn
- (setq arg 0)
- (error ""))))))
-
-(defun outline-get-last-sibling ()
- "Move to next heading of the same level, and return point or nil if none."
- (let ((level (funcall outline-level)))
- (outline-previous-visible-heading 1)
- (while (and (> (funcall outline-level) level)
- (not (bobp)))
- (outline-previous-visible-heading 1))
- (if (< (funcall outline-level) level)
- nil
- (point))))
-
-(provide 'outline)
-
-;;; outline.el ends here
diff --git a/lisp/textmodes/outline.el b/lisp/textmodes/outline.el
deleted file mode 100644
index 6116c8116da..00000000000
--- a/lisp/textmodes/outline.el
+++ /dev/null
@@ -1,651 +0,0 @@
-;;; outline.el --- outline mode commands for Emacs
-
-;; Copyright (C) 1986, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: outlines
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package is a major mode for editing outline-format documents.
-;; An outline can be `abstracted' to show headers at any given level,
-;; with all stuff below hidden. See the Emacs manual for details.
-
-;;; Code:
-
-;; Jan '86, Some new features added by Peter Desnoyers and rewritten by RMS.
-
-(defvar outline-regexp nil
- "*Regular expression to match the beginning of a heading.
-Any line whose beginning matches this regexp is considered to start 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.")
-
-;; Can't initialize this in the defvar above -- some major modes have
-;; already assigned a local value to it.
-(or (default-value 'outline-regexp)
- (setq-default outline-regexp "[*\^L]+"))
-
-(defvar outline-heading-end-regexp "\n"
- "*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-prefix-map nil)
-
-(if outline-mode-prefix-map
- nil
- (setq outline-mode-prefix-map (make-sparse-keymap))
- (define-key outline-mode-prefix-map "\C-n" 'outline-next-visible-heading)
- (define-key outline-mode-prefix-map "\C-p" 'outline-previous-visible-heading)
- (define-key outline-mode-prefix-map "\C-i" 'show-children)
- (define-key outline-mode-prefix-map "\C-s" 'show-subtree)
- (define-key outline-mode-prefix-map "\C-d" 'hide-subtree)
- (define-key outline-mode-prefix-map "\C-u" 'outline-up-heading)
- (define-key outline-mode-prefix-map "\C-f" 'outline-forward-same-level)
- (define-key outline-mode-prefix-map "\C-b" 'outline-backward-same-level)
- (define-key outline-mode-prefix-map "\C-t" 'hide-body)
- (define-key outline-mode-prefix-map "\C-a" 'show-all)
- (define-key outline-mode-prefix-map "\C-c" 'hide-entry)
- (define-key outline-mode-prefix-map "\C-e" 'show-entry)
- (define-key outline-mode-prefix-map "\C-l" 'hide-leaves)
- (define-key outline-mode-prefix-map "\C-k" 'show-branches)
- (define-key outline-mode-prefix-map "\C-q" 'hide-sublevels)
- (define-key outline-mode-prefix-map "\C-o" 'hide-other))
-
-(defvar outline-mode-menu-bar-map nil)
-(if outline-mode-menu-bar-map
- nil
- (setq outline-mode-menu-bar-map (make-sparse-keymap))
-
- (define-key outline-mode-menu-bar-map [hide]
- (cons "Hide" (make-sparse-keymap "Hide")))
-
- (define-key outline-mode-menu-bar-map [hide hide-other]
- '("Hide Other" . hide-other))
- (define-key outline-mode-menu-bar-map [hide hide-sublevels]
- '("Hide Sublevels" . hide-sublevels))
- (define-key outline-mode-menu-bar-map [hide hide-subtree]
- '("Hide Subtree" . hide-subtree))
- (define-key outline-mode-menu-bar-map [hide hide-entry]
- '("Hide Entry" . hide-entry))
- (define-key outline-mode-menu-bar-map [hide hide-body]
- '("Hide Body" . hide-body))
- (define-key outline-mode-menu-bar-map [hide hide-leaves]
- '("Hide Leaves" . hide-leaves))
-
- (define-key outline-mode-menu-bar-map [show]
- (cons "Show" (make-sparse-keymap "Show")))
-
- (define-key outline-mode-menu-bar-map [show show-subtree]
- '("Show Subtree" . show-subtree))
- (define-key outline-mode-menu-bar-map [show show-children]
- '("Show Children" . show-children))
- (define-key outline-mode-menu-bar-map [show show-branches]
- '("Show Branches" . show-branches))
- (define-key outline-mode-menu-bar-map [show show-entry]
- '("Show Entry" . show-entry))
- (define-key outline-mode-menu-bar-map [show show-all]
- '("Show All" . show-all))
-
- (define-key outline-mode-menu-bar-map [headings]
- (cons "Headings" (make-sparse-keymap "Headings")))
-
- (define-key outline-mode-menu-bar-map [headings outline-backward-same-level]
- '("Previous Same Level" . outline-backward-same-level))
- (define-key outline-mode-menu-bar-map [headings outline-forward-same-level]
- '("Next Same Level" . outline-forward-same-level))
- (define-key outline-mode-menu-bar-map [headings outline-previous-visible-heading]
- '("Previous" . outline-previous-visible-heading))
- (define-key outline-mode-menu-bar-map [headings outline-next-visible-heading]
- '("Next" . outline-next-visible-heading))
- (define-key outline-mode-menu-bar-map [headings outline-up-heading]
- '("Up" . outline-up-heading)))
-
-(defvar outline-mode-map nil "")
-
-(if outline-mode-map
- nil
- (setq outline-mode-map (nconc (make-sparse-keymap) text-mode-map))
- (define-key outline-mode-map "\C-c" outline-mode-prefix-map)
- (define-key outline-mode-map [menu-bar] outline-mode-menu-bar-map))
-
-(defvar outline-minor-mode nil
- "Non-nil if using Outline mode as a minor mode of some other mode.")
-(make-variable-buffer-local 'outline-minor-mode)
-(or (assq 'outline-minor-mode minor-mode-alist)
- (setq minor-mode-alist (append minor-mode-alist
- (list '(outline-minor-mode " Outl")))))
-
-(defvar outline-font-lock-keywords
- '(;; Highlight headings according to the level.
- ("^\\(\\*+\\)[ \t]*\\(.+\\)?[ \t]*$"
- (1 font-lock-string-face)
- (2 (let ((len (- (match-end 1) (match-beginning 1))))
- (or (cdr (assq len '((1 . font-lock-function-name-face)
- (2 . font-lock-keyword-face)
- (3 . font-lock-comment-face))))
- font-lock-variable-name-face))
- nil t))
- ;; Highlight citations of the form [1] and [Mar94].
- ("\\[\\([A-Z][A-Za-z]+\\)*[0-9]+\\]" . font-lock-type-face))
- "Additional expressions to highlight in Outline mode.")
-
-(defvar outline-view-change-hook nil
- "Normal hook to be run after outline visibility changes.")
-
-;;;autoload
-(defun outline-mode ()
- "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:\\<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
-
-\\[hide-body] make all text invisible (not headings).
-\\[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.
- No effect on body, or subheadings 2 or more levels down.
- With arg N, affects subheadings N levels down.
-\\[hide-entry] make immediately following body invisible.
-\\[show-entry] make it visible.
-\\[hide-leaves] make body under heading and under its subheadings invisible.
- The subheadings remain visible.
-\\[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."
- (interactive)
- (kill-all-local-variables)
- (use-local-map outline-mode-map)
- (setq mode-name "Outline")
- (setq major-mode 'outline-mode)
- (define-abbrev-table 'text-mode-abbrev-table ())
- (setq local-abbrev-table text-mode-abbrev-table)
- (set-syntax-table text-mode-syntax-table)
- (make-local-variable 'line-move-ignore-invisible)
- (setq line-move-ignore-invisible t)
- ;; Cause use of ellipses for invisible text.
- (setq buffer-invisibility-spec '((t . t)))
- (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 "\\)"))
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(outline-font-lock-keywords t))
- (make-local-variable 'change-major-mode-hook)
- (add-hook 'change-major-mode-hook 'show-all)
- (run-hooks 'text-mode-hook 'outline-mode-hook))
-
-(defvar outline-minor-mode-prefix "\C-c@"
- "*Prefix key to use for Outline commands in Outline minor mode.
-The value of this variable is checked as part of loading Outline mode.
-After that, changing the prefix key requires manipulating keymaps.")
-
-(defvar outline-minor-mode-map nil)
-(if outline-minor-mode-map
- nil
- (setq outline-minor-mode-map (make-sparse-keymap))
- (define-key outline-minor-mode-map [menu-bar]
- outline-mode-menu-bar-map)
- (define-key outline-minor-mode-map outline-minor-mode-prefix
- outline-mode-prefix-map))
-
-(or (assq 'outline-minor-mode minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons (cons 'outline-minor-mode outline-minor-mode-map)
- minor-mode-map-alist)))
-
-;;;autoload
-(defun outline-minor-mode (&optional arg)
- "Toggle Outline minor mode.
-With arg, turn Outline minor mode on if arg is positive, off otherwise.
-See the command `outline-mode' for more information on this mode."
- (interactive "P")
- (setq outline-minor-mode
- (if (null arg) (not outline-minor-mode)
- (> (prefix-numeric-value arg) 0)))
- (if outline-minor-mode
- (progn
- (make-local-hook 'change-major-mode-hook)
- ;; Turn off this mode if we change major modes.
- (add-hook 'change-major-mode-hook
- '(lambda () (outline-minor-mode -1))
- nil t)
- (make-local-variable 'line-move-ignore-invisible)
- (setq line-move-ignore-invisible t)
- ;; Cause use of ellipses for invisible text.
- (setq buffer-invisibility-spec '((t . t)))
- (run-hooks 'outline-minor-mode-hook))
- (setq line-move-ignore-invisible nil)
- ;; Cause use of ellipses for invisible text.
- (setq buffer-invisibility-spec t))
- ;; When turning off outline mode, get rid of any outline hiding.
- (or outline-minor-mode
- (show-all))
- (force-mode-line-update))
-
-(defvar outline-level 'outline-level
- "Function of no args to compute a header's nesting level in an outline.
-It can assume point is at the beginning of a header line.")
-
-;; This used to count columns rather than characters, but that made ^L
-;; appear to be at level 2 instead of 1. Columns would be better for
-;; tab handling, but the default regexp doesn't use tabs, and anyone
-;; who changes the regexp can also redefine the outline-level variable
-;; as appropriate.
-(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 number of characters that `outline-regexp' matches."
- (save-excursion
- (looking-at outline-regexp)
- (- (match-end 0) (match-beginning 0))))
-
-(defun outline-next-preface ()
- "Skip forward to just before the next heading line.
-If there's no following heading line, stop before the newline
-at the end of the buffer."
- (if (re-search-forward (concat "\n\\(" outline-regexp "\\)")
- nil 'move)
- (goto-char (match-beginning 0)))
- (if (bolp)
- (forward-char -1)))
-
-(defun outline-next-heading ()
- "Move to the next (possibly invisible) heading line."
- (interactive)
- (if (re-search-forward (concat "\n\\(" outline-regexp "\\)")
- nil 'move)
- (goto-char (1+ (match-beginning 0)))))
-
-(defsubst outline-visible ()
- "Non-nil if the character after point is visible."
- (not (get-char-property (point) 'invisible)))
-
-(defun outline-back-to-heading ()
- "Move to previous heading line, or beg of this line if it's a heading.
-Only visible heading lines are considered."
- (beginning-of-line)
- (or (outline-on-heading-p)
- (let (found)
- (save-excursion
- (while (not found)
- (or (re-search-backward (concat "^\\(" outline-regexp "\\)")
- nil t)
- (error "before first heading"))
- (setq found (and (outline-visible) (point)))))
- (goto-char found)
- found)))
-
-(defun outline-on-heading-p ()
- "Return t if point is on a (visible) heading line."
- (save-excursion
- (beginning-of-line)
- (and (bolp) (outline-visible)
- (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)."
- (interactive "p")
- (if (< arg 0)
- (beginning-of-line)
- (end-of-line))
- (while (and (not (bobp)) (< arg 0))
- (while (and (not (bobp))
- (re-search-backward (concat "^\\(" outline-regexp "\\)")
- nil 'move)
- (not (outline-visible))))
- (setq arg (1+ arg)))
- (while (and (not (eobp)) (> arg 0))
- (while (and (not (eobp))
- (re-search-forward (concat "^\\(" outline-regexp "\\)")
- nil 'move)
- (not (outline-visible))))
- (setq arg (1- arg)))
- (beginning-of-line))
-
-(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)."
- (interactive "p")
- (outline-next-visible-heading (- arg)))
-
-(defun outline-flag-region (from to flag)
- "Hides or shows lines from FROM to TO, according to FLAG.
-If FLAG is nil then text is shown, while if FLAG is t the text is hidden."
- (let ((inhibit-read-only t))
- (save-excursion
- (goto-char from)
- (end-of-line)
- (outline-discard-overlays (point) to 'outline)
- (if flag
- (let ((o (make-overlay (point) to)))
- (overlay-put o 'invisible flag)
- (overlay-put o 'outline t)))))
- (run-hooks 'outline-view-change-hook))
-
-;; Exclude from the region BEG ... END all overlays
-;; with a non-nil PROP property.
-;; Exclude them by shrinking them to exclude BEG ... END,
-;; or even by splitting them if necessary.
-;; Overlays without a non-nil PROP property are not touched.
-(defun outline-discard-overlays (beg end prop)
- (if (< end beg)
- (setq beg (prog1 end (setq end beg))))
- (save-excursion
- (let ((overlays (overlays-in beg end)))
- (while overlays
- (let ((o (car overlays)))
- (if (overlay-get o prop)
- ;; Either push this overlay outside beg...end
- ;; or split it to exclude beg...end
- ;; or delete it entirely (if it is contained in beg...end).
- (if (< (overlay-start o) beg)
- (if (> (overlay-end o) end)
- (let ((o1 (outline-copy-overlay o)))
- (move-overlay o1 (overlay-start o1) beg)
- (move-overlay o (overlay-start o) beg)))
- (if (> (overlay-end o) end)
- (move-overlay o end (overlay-end o))
- (delete-overlay o)))))
- (setq overlays (cdr overlays))))))
-
-;; Make a copy of overlay O, with the same beginning, end and properties.
-(defun outline-copy-overlay (o)
- (let ((o1 (make-overlay (overlay-start o) (overlay-end o)
- (overlay-buffer o)))
- (props (overlay-properties o)))
- (while props
- (overlay-put o1 (car props) (nth 1 props))
- (setq props (cdr (cdr props))))
- o1))
-
-(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)) t)))
-
-(defun show-entry ()
- "Show the body directly following this heading."
- (interactive)
- (save-excursion
- (outline-flag-region (point) (progn (outline-next-preface) (point)) nil)))
-
-(defun hide-body ()
- "Hide all of buffer except headings."
- (interactive)
- (hide-region-body (point-min) (point-max)))
-
-(defun hide-region-body (start end)
- "Hide all body lines in the region, but not headings."
- (save-excursion
- (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)) t)
- (if (not (eobp))
- (progn
- (forward-char
- (if (looking-at "\n\n")
- 2 1))
- (outline-end-of-heading)))))))
-
-(defun show-all ()
- "Show all of the text in the buffer."
- (interactive)
- (outline-flag-region (point-min) (point-max) nil))
-
-(defun hide-subtree ()
- "Hide everything after this heading at deeper levels."
- (interactive)
- (outline-flag-subtree t))
-
-(defun hide-leaves ()
- "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 ()
- "Show everything after this heading at deeper levels."
- (interactive)
- (outline-flag-subtree nil))
-
-(defun hide-sublevels (levels)
- "Hide everything but the top LEVELS levels of headers, in whole buffer."
- (interactive "p")
- (if (< levels 1)
- (error "Must keep at least one level of headers"))
- (setq levels (1- levels))
- (save-excursion
- (goto-char (point-min))
- ;; Keep advancing to the next top-level heading.
- (while (or (and (bobp) (outline-on-heading-p))
- (outline-next-heading))
- (let ((end (save-excursion (outline-end-of-subtree) (point))))
- ;; Hide everything under that.
- (outline-flag-region (point) end t)
- ;; Show the first LEVELS levels under that.
- (if (> levels 0)
- (show-children levels))
- ;; Move to the next, since we already found it.
- (goto-char end)))))
-
-(defun hide-other ()
- "Hide everything except for the current body and the parent headings."
- (interactive)
- (hide-sublevels 1)
- (let ((last (point))
- (pos (point)))
- (while (save-excursion
- (and (end-of-line 0)
- (not (outline-visible))))
- (save-excursion
- (beginning-of-line)
- (if (eq last (point))
- (progn
- (outline-next-heading)
- (outline-flag-region last (point) nil))
- (show-children)
- (setq last (point)))))))
-
-(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)
- (let ((opoint (point))
- (first t)
- (level (funcall outline-level)))
- (while (and (not (eobp))
- (or first (> (funcall outline-level) level)))
- (setq first nil)
- (outline-next-heading))
- (if (bolp)
- (progn
- ;; Go to end of line before heading
- (forward-char -1)
- (if (bolp)
- ;; leave blank line before heading
- (forward-char -1))))))
-
-(defun show-branches ()
- "Show all subheadings of this heading, but not their bodies."
- (interactive)
- (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
- (outline-back-to-heading)
- (let ((start-level (funcall outline-level)))
- (outline-next-heading)
- (if (eobp)
- 1
- (max 1 (- (funcall outline-level) start-level)))))))
- (save-excursion
- (save-restriction
- (outline-back-to-heading)
- (setq level (+ level (funcall outline-level)))
- (narrow-to-region (point)
- (progn (outline-end-of-subtree)
- (if (eobp) (point-max) (1+ (point)))))
- (goto-char (point-min))
- (while (and (not (eobp))
- (progn
- (outline-next-heading)
- (not (eobp))))
- (if (<= (funcall outline-level) level)
- (save-excursion
- (outline-flag-region (save-excursion
- (forward-char -1)
- (if (bolp)
- (forward-char -1))
- (point))
- (progn (outline-end-of-heading) (point))
- nil)))))))
-
-(defun outline-up-heading (arg)
- "Move to the heading line of which the present line is a subheading.
-With argument, move up ARG levels."
- (interactive "p")
- (outline-back-to-heading)
- (if (eq (funcall outline-level) 1)
- (error "Already at top level of the outline"))
- (while (and (> (funcall outline-level) 1)
- (> arg 0)
- (not (bobp)))
- (let ((present-level (funcall outline-level)))
- (while (not (< (funcall outline-level) present-level))
- (outline-previous-visible-heading 1))
- (setq arg (- arg 1)))))
-
-(defun outline-forward-same-level (arg)
- "Move forward to the ARG'th subheading at same level as this one.
-Stop at the first and last subheadings of a superior heading."
- (interactive "p")
- (outline-back-to-heading)
- (while (> arg 0)
- (let ((point-to-move-to (save-excursion
- (outline-get-next-sibling))))
- (if point-to-move-to
- (progn
- (goto-char point-to-move-to)
- (setq arg (1- arg)))
- (progn
- (setq arg 0)
- (error "No following same-level heading"))))))
-
-(defun outline-get-next-sibling ()
- "Move to next heading of the same level, and return point or nil if none."
- (let ((level (funcall outline-level)))
- (outline-next-visible-heading 1)
- (while (and (> (funcall outline-level) level)
- (not (eobp)))
- (outline-next-visible-heading 1))
- (if (< (funcall outline-level) level)
- nil
- (point))))
-
-(defun outline-backward-same-level (arg)
- "Move backward to the ARG'th subheading at same level as this one.
-Stop at the first and last subheadings of a superior heading."
- (interactive "p")
- (outline-back-to-heading)
- (while (> arg 0)
- (let ((point-to-move-to (save-excursion
- (outline-get-last-sibling))))
- (if point-to-move-to
- (progn
- (goto-char point-to-move-to)
- (setq arg (1- arg)))
- (progn
- (setq arg 0)
- (error "No previous same-level heading"))))))
-
-(defun outline-get-last-sibling ()
- "Move to next heading of the same level, and return point or nil if none."
- (let ((level (funcall outline-level)))
- (outline-previous-visible-heading 1)
- (while (and (> (funcall outline-level) level)
- (not (bobp)))
- (outline-previous-visible-heading 1))
- (if (< (funcall outline-level) level)
- nil
- (point))))
-
-(provide 'outline)
-(provide 'noutline)
-
-;;; outline.el ends here
diff --git a/lisp/textmodes/page-ext.el b/lisp/textmodes/page-ext.el
deleted file mode 100644
index bc5e971b141..00000000000
--- a/lisp/textmodes/page-ext.el
+++ /dev/null
@@ -1,772 +0,0 @@
-;;; page-ext.el --- extended page handling commands
-
-;; Copyright (C) 1990, 1991, 1993, 1994 Free Software Foundation
-
-;; Maintainer: Robert J. Chassell <bob@gnu.ai.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; You may use these commands to handle an address list or other
-;; small data base.
-
-
-;;; 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
-;; pages-directory-goto 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.
-
-;; You may set several user options:
-;;
-;; The `pages-directory-buffer-narrowing-p' variable causes the
-;; `pages-directory-goto' command to narrow to the destination page.
-;;
-;; The `pages-directory-for-adding-page-narrowing-p' variable, causes the
-;; `add-new-page' command to narrow to the new entry.
-;;
-;; The `pages-directory-for-adding-new-page-before-current-page-p' variable
-;; causes the `add-new-page' command to insert a new page before current
-;; page.
-;;
-;; These variables are true by default.
-;;
-;; Additional, addresses-related user options are described in the next page
-;; of this file.
-
-
-;;; 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
-;; 59 Temple Place - Suite 330
-;; Boston, MA 02111-1307 USA.
-;; (617) 542-5942
-;; 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 restrictions 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
-;; display 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' (pages-directory-goto) to go to the entry to
-;; which it refers in the pages buffer.
-
-;; You can type `C-c C-p C-a' (add-new-page) to add a new entry in the
-;; pages buffer or address file. This is the same command you use to
-;; add a new entry when you are in the pages buffer or address file.
-
-;; 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.
-
-;; You may customize the addresses commands:
-
-;; The `pages-addresses-file-name' variable determines the name of
-;; the addresses file; by default it is "~/addresses".
-
-;; The `pages-directory-for-addresses-goto-narrowing-p' variable
-;; determines whether `pages-directory-goto' narrows the addresses
-;; buffer to the entry, which it does by default.
-
-;; The `pages-directory-for-addresses-buffer-keep-windows-p' variable
-;; determines whether `pages-directory-for-addresses' deletes other
-;; windows to show as many lines as possible on the screen or works
-;; in the usual Emacs manner and keeps other windows. Default is to
-;; keep other windows.
-
-;; The `pages-directory-for-adding-addresses-narrowing-p' variable
-;; determines whether `pages-directory-for-addresses' narrows the
-;; addresses buffer to a new entry when you are adding that entry.
-;; Default is to narrow to new entry, which means you see a blank
-;; screen before you write the new entry.
-
-;; `pages-directory' in detail
-
-;; Call the `pages-directory' command 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.
-
-;;; Code:
-
-
-;;; Customarily customizable variable definitions
-
-(defvar pages-directory-buffer-narrowing-p t
- "*If non-nil, `pages-directory-goto' narrows pages buffer to entry.")
-
-(defvar pages-directory-for-adding-page-narrowing-p t
- "*If non-nil, `add-new-page' narrows page buffer to new entry.")
-
-(defvar pages-directory-for-adding-new-page-before-current-page-p t
- "*If non-nil, `add-new-page' inserts new page before current page.")
-
-
-;;; Addresses related variables
-
-(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-goto-narrowing-p t
- "*If non-nil, `pages-directory-goto' narrows addresses buffer to entry.")
-
-(defvar pages-directory-for-addresses-buffer-keep-windows-p t
- "*If nil, `pages-directory-for-addresses' deletes other windows.")
-
-(defvar pages-directory-for-adding-addresses-narrowing-p t
- "*If non-nil, `add-new-page' narrows addresses buffer to new entry.")
-
-
-;;; 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)))
- ;; If COUNT is negative, we want to go back -COUNT + 1 page boundaries.
- ;; The first page boundary we reach is the top of the current page,
- ;; which doesn't count.
- (while (and (< count 1) (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. Prompt for header line.
-
-If point is in the pages directory buffer, insert the new page in the
-buffer associated with the directory.
-
-Insert the new page just before current page if
- pages-directory-for-adding-new-page-before-current-page-p variable
-is non-nil. Else insert at exact location of point.
-
-Narrow to new page if
- pages-directory-for-adding-page-narrowing-p variable
-is non-nil.
-
-Page begins with a `^L' as the default page-delimiter.
-Use \\[set-page-delimiter] to change the page-delimiter.
-Point is left in the body of page."
- (interactive "sHeader line: ")
- (widen)
- ;; If in pages directory buffer
- (if (eq major-mode 'pages-directory-mode)
- (progn
- ;; Add new page before or after current page?
- (if pages-directory-for-adding-new-page-before-current-page-p
- (pages-directory-goto)
- (pages-directory-goto)
- (forward-page)
- (or (eobp) (forward-line -1)))))
- (widen)
- ;; Move point before current delimiter if desired.
- (and pages-directory-for-adding-new-page-before-current-page-p
- (if (re-search-backward page-delimiter nil t)
- (goto-char (match-beginning 0))
- ;; If going to beginning of file, insert a page-delimiter
- ;; before current first page.
- (goto-char (point-min))
- (insert
- (format "%s\n"
- ;; Remove leading `^' from page-delimiter string
- (if (eq '^ (car (read-from-string page-delimiter)))
- (substring page-delimiter 1))))
- (goto-char (point-min))))
- ;; Insert page delimiter at beginning of line.
- (if (not (looking-at "^.")) (forward-line 1))
- (insert (format "%s\n%s\n\n\n"
- (if (eq '^ (car (read-from-string page-delimiter)))
- (substring page-delimiter 1))
- header-line))
- (forward-line -1)
- (and pages-directory-for-adding-page-narrowing-p (narrow-to-page)))
-
-(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-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)
- (define-key pages-directory-map "\C-c\C-p\C-a" 'add-new-page))
-
-(defvar original-page-delimiter "^\f"
- "Default page delimiter.")
-
-(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 "^\f")
- (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 ((target-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 target-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 target-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 target-buffer start end))
-
- (if count-lines-p
- (save-excursion
- (beginning-of-line)
- (insert (format "%3d: " line-count))))
-
- (terpri))
- (end-of-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
-
-(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 \\[pages-directory-goto] to go to the same line
-in the addresses buffer.
-
-If pages-directory-for-addresses-goto-narrowing-p is non-nil,
-`pages-directory-goto' narrows addresses buffer to entry.
-
-If pages-directory-for-addresses-buffer-keep-windows-p is nil,
-this command deletes other windows when it displays the addresses
-directory."
-
- (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-goto-narrowing-p)
- (or pages-directory-for-addresses-buffer-keep-windows-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 \\[pages-directory-goto] 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))
-
-
-;;; Place `provide' at end of file.
-(provide 'page-ext)
-
-;;;;;;;;;;;;;;;; end of page-ext.el ;;;;;;;;;;;;;;;;
-
diff --git a/lisp/textmodes/page.el b/lisp/textmodes/page.el
deleted file mode 100644
index 2cc0533535d..00000000000
--- a/lisp/textmodes/page.el
+++ /dev/null
@@ -1,161 +0,0 @@
-;;; page.el --- page motion commands for emacs.
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This code provides the page-oriented movement and selection commands
-;; documented in the Emacs manual.
-
-;;; Code:
-
-(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'."
- (interactive "p")
- (or count (setq count 1))
- (while (and (> count 0) (not (eobp)))
- ;; In case the page-delimiter matches the null string,
- ;; don't find a match without moving.
- (if (bolp) (forward-char 1))
- (if (re-search-forward page-delimiter nil t)
- nil
- (goto-char (point-max)))
- (setq count (1- count)))
- (while (and (< count 0) (not (bobp)))
- ;; In case the page-delimiter matches the null string,
- ;; don't find a match without moving.
- (and (save-excursion (re-search-backward page-delimiter nil t))
- (= (match-end 0) (point))
- (goto-char (match-beginning 0)))
- (forward-char -1)
- (if (re-search-backward page-delimiter nil t)
- ;; We found one--move to the end of it.
- (goto-char (match-end 0))
- ;; We found nothing--go to beg of buffer.
- (goto-char (point-min)))
- (setq count (1+ count))))
-
-(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'."
- (interactive "p")
- (or count (setq count 1))
- (forward-page (- count)))
-
-(defun mark-page (&optional arg)
- "Put mark at end of page, point at beginning.
-A numeric arg specifies to move forward or backward by that many pages,
-thus marking a page other than the one point was originally in."
- (interactive "P")
- (setq arg (if arg (prefix-numeric-value arg) 0))
- (if (> arg 0)
- (forward-page arg)
- (if (< arg 0)
- (forward-page (1- arg))))
- (forward-page)
- (push-mark nil t t)
- (forward-page -1))
-
-(defun narrow-to-page (&optional arg)
- "Make text outside current page invisible.
-A numeric arg specifies to move forward or backward by that many pages,
-thus showing a page other than the one point was originally in."
- (interactive "P")
- (setq arg (if arg (prefix-numeric-value arg) 0))
- (save-excursion
- (widen)
- (if (> arg 0)
- (forward-page arg)
- (if (< arg 0)
- (let ((adjust 0)
- (opoint (point)))
- ;; If we are not now at the beginning of a page,
- ;; move back one extra time, to get to the start of this page.
- (save-excursion
- (beginning-of-line)
- (or (and (looking-at page-delimiter)
- (eq (match-end 0) opoint))
- (setq adjust 1)))
- (forward-page (- arg adjust)))))
- ;; Find the end of the page.
- (forward-page)
- ;; If we stopped due to end of buffer, stay there.
- ;; If we stopped after a page delimiter, put end of restriction
- ;; at the beginning of that line.
- (if (save-excursion
- (goto-char (match-beginning 0)) ; was (beginning-of-line)
- (looking-at page-delimiter))
- (beginning-of-line))
- (narrow-to-region (point)
- (progn
- ;; Find the top of the page.
- (forward-page -1)
- ;; If we found beginning of buffer, stay there.
- ;; If extra text follows page delimiter on same line,
- ;; include it.
- ;; Otherwise, show text starting with following line.
- (if (and (eolp) (not (bobp)))
- (forward-line 1))
- (point)))))
-(put 'narrow-to-page 'disabled t)
-
-(defun count-lines-page ()
- "Report number of lines on current page, and how many are before or after point."
- (interactive)
- (save-excursion
- (let ((opoint (point)) beg end
- total before after)
- (forward-page)
- (beginning-of-line)
- (or (looking-at page-delimiter)
- (end-of-line))
- (setq end (point))
- (backward-page)
- (setq beg (point))
- (setq total (count-lines beg end)
- before (count-lines beg opoint)
- after (count-lines opoint end))
- (message "Page has %d lines (%d + %d)" total before after))))
-
-(defun what-page ()
- "Print page and line number of point."
- (interactive)
- (save-restriction
- (widen)
- (save-excursion
- (beginning-of-line)
- (let ((count 1)
- (opoint (point)))
- (goto-char 1)
- (while (re-search-forward page-delimiter opoint t)
- (setq count (1+ count)))
- (message "Page %d, line %d"
- count
- (1+ (count-lines (point) opoint)))))))
-
-;;; Place `provide' at end of file.
-(provide 'page)
-
-;;; page.el ends here
diff --git a/lisp/textmodes/paragraphs.el b/lisp/textmodes/paragraphs.el
deleted file mode 100644
index cb876d55031..00000000000
--- a/lisp/textmodes/paragraphs.el
+++ /dev/null
@@ -1,389 +0,0 @@
-;;; paragraphs.el --- paragraph and sentence parsing.
-
-;; Copyright (C) 1985, 86, 87, 91, 94, 95, 96 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: wp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides the paragraph-oriented commands documented in the
-;; Emacs manual.
-
-;;; Code:
-
-(defvar use-hard-newlines nil
- "Non-nil means to distinguish hard and soft newlines.
-See documentation for the `use-hard-newlines' function.")
-(make-variable-buffer-local 'use-hard-newlines)
-
-(defun use-hard-newlines (&optional arg insert)
- "Minor mode to distinguish hard and soft newlines.
-When active, the functions `newline' and `open-line' add the
-text-property `hard' to newlines that they insert, and a line is
-only considered as a candidate to match `paragraph-start' or
-`paragraph-separate' if it follows a hard newline.
-
-Prefix argument says to turn mode on if positive, off if negative.
-When the mode is turned on, if there are newlines in the buffer but no hard
-newlines, ask the user whether to mark as hard any newlines preceeding a
-`paragraph-start' line. From a program, second arg INSERT specifies whether
-to do this; it can be `never' to change nothing, t or `always' to force
-marking, `guess' to try to do the right thing with no questions, nil
-or anything else to ask the user.
-
-Newlines not marked hard are called \"soft\", and are always internal
-to paragraphs. The fill functions insert and delete only soft newlines."
- (interactive (list current-prefix-arg nil))
- (if (or (<= (prefix-numeric-value arg) 0)
- (and use-hard-newlines (null arg)))
- ;; Turn mode off
- (setq use-hard-newlines nil)
- ;; Turn mode on
- ;; Intuit hard newlines --
- ;; mark as hard any newlines preceding a paragraph-start line.
- (if (or (eq insert t) (eq insert 'always)
- (and (not (eq 'never insert))
- (not use-hard-newlines)
- (not (text-property-any (point-min) (point-max) 'hard t))
- (save-excursion
- (goto-char (point-min))
- (search-forward "\n" nil t))
- (or (eq insert 'guess)
- (y-or-n-p "Make newlines between paragraphs hard? "))))
- (save-excursion
- (goto-char (point-min))
- (while (search-forward "\n" nil t)
- (let ((pos (point)))
- (move-to-left-margin)
- (if (looking-at paragraph-start)
- (progn
- (set-hard-newline-properties (1- pos) pos)
- ;; If paragraph-separate, newline after it is hard too.
- (if (looking-at paragraph-separate)
- (progn
- (end-of-line)
- (if (not (eobp))
- (set-hard-newline-properties
- (point) (1+ (point))))))))))))
- (setq use-hard-newlines t)))
-
-(defvar paragraph-start "[ \t\n\f]" "\
-*Regexp for beginning of a line that starts OR separates paragraphs.
-This regexp should match lines that separate paragraphs
-and should also match lines that start a paragraph
-\(and are part of that paragraph).
-
-This is matched against the text at the left margin, which is not necessarily
-the beginning of the line, so it should never use \"^\" as an anchor. This
-ensures that the paragraph functions will work equally well within a region
-of text indented by a margin setting.
-
-The variable `paragraph-separate' specifies how to distinguish
-lines that start paragraphs from lines that separate them.
-
-If the variable `use-hard-newlines' is nonnil, then only lines following a
-hard newline are considered to match.")
-
-;; paragraph-start requires a hard newline, but paragraph-separate does not:
-;; It is assumed that paragraph-separate is distinctive enough to be believed
-;; whenever it occurs, while it is reasonable to set paragraph-start to
-;; something very minimal, even including "." (which makes every hard newline
-;; start a new paragraph).
-
-(defvar 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.
-
-This is matched against the text at the left margin, which is not necessarily
-the beginning of the line, so it should not use \"^\" as an anchor. This
-ensures that the paragraph functions will work equally within a region of
-text indented by a margin setting.")
-
-(defvar sentence-end (purecopy "[.?!][]\"')}]*\\($\\| $\\|\t\\| \\)[ \t\n]*") "\
-*Regexp describing the end of a sentence.
-All paragraph boundaries also end sentences, regardless.
-
-In order to be recognized as the end of a sentence, the ending period,
-question mark, or exclamation point must be followed by two spaces,
-unless it's inside some sort of quotes or parenthesis.")
-
-(defvar page-delimiter "^\014" "\
-*Regexp describing line-beginnings that separate pages.")
-
-(defvar paragraph-ignore-fill-prefix nil "\
-Non-nil means the paragraph commands are not affected by `fill-prefix'.
-This is desirable in modes where blank lines are the paragraph delimiters.")
-
-(defun forward-paragraph (&optional arg)
- "Move forward to end of paragraph.
-With argument ARG, do it ARG times;
-a negative argument ARG = -N means move backward N paragraphs.
-
-A line which `paragraph-start' matches either separates paragraphs
-\(if `paragraph-separate' matches it also) or is the first line of a paragraph.
-A paragraph end is the beginning of a line which is not part of the paragraph
-to which the end of the previous line belongs, or the end of the buffer."
- (interactive "p")
- (or arg (setq arg 1))
- (let* ((fill-prefix-regexp
- (and fill-prefix (not (equal fill-prefix ""))
- (not paragraph-ignore-fill-prefix)
- (regexp-quote fill-prefix)))
- ;; Remove ^ from paragraph-start and paragraph-sep if they are there.
- ;; These regexps shouldn't be anchored, because we look for them
- ;; starting at the left-margin. This allows paragraph commands to
- ;; work normally with indented text.
- ;; This hack will not find problem cases like "whatever\\|^something".
- (paragraph-start (if (and (not (equal "" paragraph-start))
- (equal ?^ (aref paragraph-start 0)))
- (substring paragraph-start 1)
- paragraph-start))
- (paragraph-separate (if (and (not (equal "" paragraph-start))
- (equal ?^ (aref paragraph-separate 0)))
- (substring paragraph-separate 1)
- paragraph-separate))
- (paragraph-separate
- (if fill-prefix-regexp
- (concat paragraph-separate "\\|"
- fill-prefix-regexp "[ \t]*$")
- paragraph-separate))
- ;; This is used for searching.
- (sp-paragraph-start (concat "^[ \t]*\\(" paragraph-start "\\)"))
- start)
- (while (and (< arg 0) (not (bobp)))
- (if (and (not (looking-at paragraph-separate))
- (re-search-backward "^\n" (max (1- (point)) (point-min)) t)
- (looking-at paragraph-separate))
- nil
- (setq start (point))
- ;; Move back over paragraph-separating lines.
- (forward-char -1) (beginning-of-line)
- (while (and (not (bobp))
- (progn (move-to-left-margin)
- (looking-at paragraph-separate)))
- (forward-line -1))
- (if (bobp)
- nil
- ;; Go to end of the previous (non-separating) line.
- (end-of-line)
- ;; Search back for line that starts or separates paragraphs.
- (if (if fill-prefix-regexp
- ;; There is a fill prefix; it overrides paragraph-start.
- (let (multiple-lines)
- (while (and (progn (beginning-of-line) (not (bobp)))
- (progn (move-to-left-margin)
- (not (looking-at paragraph-separate)))
- (looking-at fill-prefix-regexp))
- (if (not (= (point) start))
- (setq multiple-lines t))
- (forward-line -1))
- (move-to-left-margin)
-;;; This deleted code caused a long hanging-indent line
-;;; not to be filled together with the following lines.
-;;; ;; Don't move back over a line before the paragraph
-;;; ;; which doesn't start with fill-prefix
-;;; ;; unless that is the only line we've moved over.
-;;; (and (not (looking-at fill-prefix-regexp))
-;;; multiple-lines
-;;; (forward-line 1))
- (not (bobp)))
- (while (and (re-search-backward sp-paragraph-start nil 1)
- ;; Found a candidate, but need to check if it is a
- ;; REAL paragraph-start.
- (not (bobp))
- (progn (setq start (point))
- (move-to-left-margin)
- (not (looking-at paragraph-separate)))
- (or (not (looking-at paragraph-start))
- (and use-hard-newlines
- (not (get-text-property (1- start)
- 'hard)))))
- (goto-char start))
- (> (point) (point-min)))
- ;; Found one.
- (progn
- ;; Move forward over paragraph separators.
- ;; We know this cannot reach the place we started
- ;; because we know we moved back over a non-separator.
- (while (and (not (eobp))
- (progn (move-to-left-margin)
- (looking-at paragraph-separate)))
- (forward-line 1))
- ;; If line before paragraph is just margin, back up to there.
- (end-of-line 0)
- (if (> (current-column) (current-left-margin))
- (forward-char 1)
- (skip-chars-backward " \t")
- (if (not (bolp))
- (forward-line 1))))
- ;; No starter or separator line => use buffer beg.
- (goto-char (point-min)))))
- (setq arg (1+ arg)))
- (while (and (> arg 0) (not (eobp)))
- ;; Move forward over separator lines, and one more line.
- (while (prog1 (and (not (eobp))
- (progn (move-to-left-margin) (not (eobp)))
- (looking-at paragraph-separate))
- (forward-line 1)))
- (if fill-prefix-regexp
- ;; There is a fill prefix; it overrides paragraph-start.
- (while (and (not (eobp))
- (progn (move-to-left-margin) (not (eobp)))
- (not (looking-at paragraph-separate))
- (looking-at fill-prefix-regexp))
- (forward-line 1))
- (while (and (re-search-forward sp-paragraph-start nil 1)
- (progn (setq start (match-beginning 0))
- (goto-char start)
- (not (eobp)))
- (progn (move-to-left-margin)
- (not (looking-at paragraph-separate)))
- (or (not (looking-at paragraph-start))
- (and use-hard-newlines
- (not (get-text-property (1- start) 'hard)))))
- (forward-char 1))
- (if (< (point) (point-max))
- (goto-char start)))
- (setq arg (1- arg)))))
-
-(defun backward-paragraph (&optional arg)
- "Move backward to start of paragraph.
-With argument ARG, do it ARG times;
-a negative argument ARG = -N means move forward N paragraphs.
-
-A paragraph start is the beginning of a line which is a
-`first-line-of-paragraph' or which is ordinary text and follows a
-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."
- (interactive)
- (forward-paragraph 1)
- (push-mark nil t 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-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-region (point) (progn (backward-paragraph arg) (point))))
-
-(defun transpose-paragraphs (arg)
- "Interchange this (or next) paragraph with previous one."
- (interactive "*p")
- (transpose-subr 'forward-paragraph arg))
-
-(defun start-of-paragraph-text ()
- (let ((opoint (point)) npoint)
- (forward-paragraph -1)
- (setq npoint (point))
- (skip-chars-forward " \t\n")
- ;; If the range of blank lines found spans the original start point,
- ;; try again from the beginning of it.
- ;; Must be careful to avoid infinite loop
- ;; when following a single return at start of buffer.
- (if (and (>= (point) opoint) (< npoint opoint))
- (progn
- (goto-char npoint)
- (if (> npoint (point-min))
- (start-of-paragraph-text))))))
-
-(defun end-of-paragraph-text ()
- (let ((opoint (point)))
- (forward-paragraph 1)
- (if (eq (preceding-char) ?\n) (forward-char -1))
- (if (<= (point) opoint)
- (progn
- (forward-char 1)
- (if (< (point) (point-max))
- (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."
- (interactive "p")
- (or arg (setq arg 1))
- (while (< arg 0)
- (let ((par-beg (save-excursion (start-of-paragraph-text) (point))))
- (if (re-search-backward (concat sentence-end "[^ \t\n]") par-beg t)
- (goto-char (1- (match-end 0)))
- (goto-char par-beg)))
- (setq arg (1+ arg)))
- (while (> arg 0)
- (let ((par-end (save-excursion (end-of-paragraph-text) (point))))
- (if (re-search-forward sentence-end par-end t)
- (skip-chars-backward " \t\n")
- (goto-char par-end)))
- (setq arg (1- arg))))
-
-(defun backward-sentence (&optional arg)
- "Move backward to start of sentence. With arg, do it arg times.
-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."
- (interactive "p")
- (kill-region (point) (progn (forward-sentence arg) (point))))
-
-(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."
- (interactive "p")
- (kill-region (point) (progn (backward-sentence arg) (point))))
-
-(defun mark-end-of-sentence (arg)
- "Put mark at end of sentence. Arg works as in `forward-sentence'."
- (interactive "p")
- (push-mark
- (save-excursion
- (forward-sentence arg)
- (point))
- nil t))
-
-(defun transpose-sentences (arg)
- "Interchange this (next) and previous sentence."
- (interactive "*p")
- (transpose-subr 'forward-sentence arg))
-
-;;; paragraphs.el ends here
diff --git a/lisp/textmodes/picture.el b/lisp/textmodes/picture.el
deleted file mode 100644
index e2cd1897d0a..00000000000
--- a/lisp/textmodes/picture.el
+++ /dev/null
@@ -1,646 +0,0 @@
-;;; picture.el --- "Picture mode" -- editing using quarter-plane screen model.
-
-;; Copyright (C) 1985, 1994 Free Software Foundation, Inc.
-
-;; Author: K. Shane Hartman
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This code provides the picture-mode commands documented in the Emacs
-;; manual. The screen is treated as a semi-infinite quarter-plane with
-;; support for rectangle operations and `etch-a-sketch' character
-;; insertion in any of eight directions.
-
-;;; Code:
-
-(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
-if necessary to attain exactly the specified column."
- (or (natnump column) (setq column 0))
- (move-to-column column)
- (let ((col (current-column)))
- (if (< col column)
- (indent-to column)
- (if (and (/= col column)
- (= (preceding-char) ?\t))
- (let (indent-tabs-mode)
- (delete-char -1)
- (indent-to col)
- (move-to-column column))))
- ;; This call will go away when Emacs gets real horizontal autoscrolling
- (hscroll-point-visible)))
-
-
-;; Picture Movement Commands
-
-(defun picture-beginning-of-line (&optional arg)
- "Position point at the beginning of the line.
-With ARG not nil, move forward ARG - 1 lines first.
-If scan reaches end of buffer, stop there without error."
- (interactive "P")
- (if arg (forward-line (1- (prefix-numeric-value arg))))
- (beginning-of-line)
- ;; This call will go away when Emacs gets real horizontal autoscrolling
- (hscroll-point-visible))
-
-(defun picture-end-of-line (&optional arg)
- "Position point after last non-blank character on current line.
-With ARG not nil, move forward ARG - 1 lines first.
-If scan reaches end of buffer, stop there without error."
- (interactive "P")
- (if arg (forward-line (1- (prefix-numeric-value arg))))
- (beginning-of-line)
- (skip-chars-backward " \t" (prog1 (point) (end-of-line)))
- ;; This call will go away when Emacs gets real horizontal autoscrolling
- (hscroll-point-visible))
-
-(defun picture-forward-column (arg)
- "Move cursor right, making whitespace if necessary.
-With argument, move that many columns."
- (interactive "p")
- (let ((target-column (+ (current-column) arg)))
- (move-to-column-force target-column)
- ;; Picture mode isn't really suited to multi-column characters,
- ;; but we might as well let the user move across them.
- (and (< arg 0)
- (> (current-column) target-column)
- (forward-char -1))))
-
-(defun picture-backward-column (arg)
- "Move cursor left, making whitespace if necessary.
-With argument, move that many columns."
- (interactive "p")
- (picture-forward-column (- arg)))
-
-(defun picture-move-down (arg)
- "Move vertically down, making whitespace if necessary.
-With argument, move that many lines."
- (interactive "p")
- (let ((col (current-column)))
- (picture-newline arg)
- (move-to-column-force col)))
-
-(defconst picture-vertical-step 0
- "Amount to move vertically after text character in Picture mode.")
-
-(defconst picture-horizontal-step 1
- "Amount to move horizontally after text character in Picture mode.")
-
-(defun picture-move-up (arg)
- "Move vertically up, making whitespace if necessary.
-With argument, move that many lines."
- (interactive "p")
- (picture-move-down (- arg)))
-
-(defun picture-movement-right ()
- "Move right after self-inserting character in Picture mode."
- (interactive)
- (picture-set-motion 0 1))
-
-(defun picture-movement-left ()
- "Move left after self-inserting character in Picture mode."
- (interactive)
- (picture-set-motion 0 -1))
-
-(defun picture-movement-up ()
- "Move up after self-inserting character in Picture mode."
- (interactive)
- (picture-set-motion -1 0))
-
-(defun picture-movement-down ()
- "Move down after self-inserting character in Picture mode."
- (interactive)
- (picture-set-motion 1 0))
-
-(defun picture-movement-nw ()
- "Move up and left after self-inserting character in Picture mode."
- (interactive)
- (picture-set-motion -1 -1))
-
-(defun picture-movement-ne ()
- "Move up and right after self-inserting character in Picture mode."
- (interactive)
- (picture-set-motion -1 1))
-
-(defun picture-movement-sw ()
- "Move down and left after self-inserting character in Picture mode."
- (interactive)
- (picture-set-motion 1 -1))
-
-(defun picture-movement-se ()
- "Move down and right after self-inserting character in Picture mode."
- (interactive)
- (picture-set-motion 1 1))
-
-(defun picture-set-motion (vert horiz)
- "Set VERTICAL and HORIZONTAL increments for movement in Picture mode.
-The mode line is updated to reflect the current direction."
- (setq picture-vertical-step vert
- picture-horizontal-step horiz)
- (setq mode-name
- (format "Picture:%s"
- (car (nthcdr (+ 1 (% horiz 2) (* 3 (1+ (% vert 2))))
- '(nw up ne left none right sw down se)))))
- (force-mode-line-update)
- (message ""))
-
-(defun picture-move ()
- "Move in direction of `picture-vertical-step' and `picture-horizontal-step'."
- (picture-move-down picture-vertical-step)
- (picture-forward-column picture-horizontal-step))
-
-(defun picture-motion (arg)
- "Move point in direction 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."
- (interactive "p")
- (picture-move-down (* arg picture-vertical-step))
- (picture-forward-column (* arg picture-horizontal-step)))
-
-(defun picture-motion-reverse (arg)
- "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."
- (interactive "p")
- (picture-motion (- arg)))
-
-
-;; Picture insertion and deletion.
-
-(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."
- (interactive "p")
- (while (> arg 0)
- (setq arg (1- arg))
- (move-to-column-force (1+ (current-column)))
- (delete-char -1)
- (insert last-command-event) ; Always a character in this case.
- (forward-char -1)
- (picture-move)))
-
-(defun picture-clear-column (arg)
- "Clear out ARG columns after point without moving."
- (interactive "p")
- (let* ((opoint (point))
- (original-col (current-column))
- (target-col (+ original-col arg)))
- (move-to-column-force target-col)
- (delete-region opoint (point))
- (save-excursion
- (indent-to (max target-col original-col)))))
-
-(defun picture-backward-clear-column (arg)
- "Clear out ARG columns before point, moving back over them."
- (interactive "p")
- (picture-clear-column (- arg)))
-
-(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."
- (interactive "P")
- (if arg
- (progn
- (setq arg (prefix-numeric-value arg))
- (kill-line arg)
- (newline (if (> arg 0) arg (- arg))))
- (if (looking-at "[ \t]*$")
- (kill-ring-save (point) (progn (forward-line 1) (point)))
- (kill-region (point) (progn (end-of-line) (point))))))
-
-(defun picture-newline (arg)
- "Move to the beginning of the following line.
-With argument, moves that many lines (up, if negative argument);
-always moves to the beginning of a line."
- (interactive "p")
- (if (< arg 0)
- (forward-line arg)
- (while (> arg 0)
- (end-of-line)
- (if (eobp) (newline) (forward-char 1))
- (setq arg (1- arg))))
- ;; This call will go away when Emacs gets real horizontal autoscrolling
- (hscroll-point-visible))
-
-(defun picture-open-line (arg)
- "Insert an empty line after the current line.
-With positive argument insert that many lines."
- (interactive "p")
- (save-excursion
- (end-of-line)
- (open-line arg))
- ;; This call will go away when Emacs gets real horizontal autoscrolling
- (hscroll-point-visible))
-
-(defun picture-duplicate-line ()
- "Insert a duplicate of the current line, below it."
- (interactive)
- (save-excursion
- (let ((contents
- (buffer-substring
- (progn (beginning-of-line) (point))
- (progn (picture-newline 1) (point)))))
- (forward-line -1)
- (insert contents))))
-
-;; Like replace-match, but overwrites.
-(defun picture-replace-match (newtext fixedcase literal)
- (let (ocolumn change pos)
- (goto-char (setq pos (match-end 0)))
- (setq ocolumn (current-column))
- ;; Make the replacement and undo it, to see how it changes the length.
- (let ((buffer-undo-list nil)
- list1)
- (replace-match newtext fixedcase literal)
- (setq change (- (current-column) ocolumn))
- (setq list1 buffer-undo-list)
- (while list1
- (setq list1 (primitive-undo 1 list1))))
- (goto-char pos)
- (if (> change 0)
- (delete-region (point)
- (progn
- (move-to-column-force (+ change (current-column)))
- (point))))
- (replace-match newtext fixedcase literal)
- (if (< change 0)
- (insert-char ?\ (- change)))))
-
-;; Picture Tabs
-
-(defvar picture-tab-chars "!-~"
- "*A character set which controls behavior of commands
-\\[picture-set-tab-stops] and \\[picture-tab-search]. It is NOT a
-regular expression, any regexp special characters will be quoted.
-It defines a set of \"interesting characters\" to look for when setting
-\(or searching for) tab stops, initially \"!-~\" (all printing characters).
-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
-\\[picture-set-tab-stops] on either of the previous lines would result
-in the following tab stops
- : : : :
-Another example - \"A-Za-z0-9\" would produce the tab stops
- : : : :
-
-Note that if you want the character `-' to be in the set, it must be
-included in a range or else appear in a context where it cannot be
-taken for indicating a range (e.g. \"-A-Z\" declares the set to be the
-letters `A' through `Z' and the character `-'). If you want the
-character `\\' in the set it must be preceded by itself: \"\\\\\".
-
-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."
- (interactive "P")
- (save-excursion
- (let (tabs)
- (if arg
- (setq tabs (default-value 'tab-stop-list))
- (let ((regexp (concat "[ \t]+[" (regexp-quote picture-tab-chars) "]")))
- (beginning-of-line)
- (let ((bol (point)))
- (end-of-line)
- (while (re-search-backward regexp bol t)
- (skip-chars-forward " \t")
- (setq tabs (cons (current-column) tabs)))
- (if (null tabs)
- (error "No characters in set %s on this line."
- (regexp-quote picture-tab-chars))))))
- (setq tab-stop-list tabs)
- (let ((blurb (make-string (1+ (nth (1- (length tabs)) tabs)) ?\ )))
- (while tabs
- (aset blurb (car tabs) ?:)
- (setq tabs (cdr tabs)))
- (message blurb)))))
-
-(defun picture-tab-search (&optional arg)
- "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'.
-If no such character is found, move to beginning of line."
- (interactive "P")
- (let ((target (current-column)))
- (save-excursion
- (if (and (not arg)
- (progn
- (beginning-of-line)
- (skip-chars-backward
- (concat "^" (regexp-quote picture-tab-chars))
- (point-min))
- (not (bobp))))
- (move-to-column target))
- (if (re-search-forward
- (concat "[ \t]+[" (regexp-quote picture-tab-chars) "]")
- (save-excursion (end-of-line) (point))
- 'move)
- (setq target (1- (current-column)))
- (setq target nil)))
- (if target
- (move-to-column-force target)
- (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
-list can be changed by \\[picture-set-tab-stops] and \\[edit-tab-stops].
-See also documentation for variable `picture-tab-chars'."
- (interactive "P")
- (let* ((opoint (point)))
- (move-to-tab-stop)
- (if arg
- (let (indent-tabs-mode
- (column (current-column)))
- (delete-region opoint (point))
- (indent-to column)))))
-
-;; Picture Rectangles
-
-(defconst picture-killed-rectangle nil
- "Rectangle killed or copied by \\[picture-clear-rectangle] in Picture mode.
-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."
- (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."
- (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))
- (prog1 (save-excursion
- (if killp
- (delete-extract-rectangle start end)
- (prog1 (extract-rectangle start end)
- (clear-rectangle start end))))
- (move-to-column-force column))))
-
-(defun picture-yank-rectangle (&optional insertp)
- "Overlay rectangle saved by \\[picture-clear-rectangle]
-The rectangle is positioned with upper left corner at point, overwriting
-existing text. With prefix argument, the rectangle is inserted instead,
-shifting existing text. Leaves mark at one corner of rectangle and
-point at the other (diagonally opposed) corner."
- (interactive "P")
- (if (not (consp picture-killed-rectangle))
- (error "No rectangle saved.")
- (picture-insert-rectangle picture-killed-rectangle insertp)))
-
-(defun picture-yank-at-click (click arg)
- "Insert the last killed rectangle at the position clicked on.
-Also move point to one end of the text thus inserted (normally the end).
-Prefix arguments are interpreted as with \\[yank].
-If `mouse-yank-at-point' is non-nil, insert at point
-regardless of where you click."
- (interactive "e\nP")
- (or mouse-yank-at-point (mouse-set-point click))
- (picture-yank-rectangle arg))
-
-(defun picture-yank-rectangle-from-register (register &optional insertp)
- "Overlay rectangle saved in REGISTER.
-The rectangle is positioned with upper left corner at point, overwriting
-existing text. With prefix argument, the rectangle is
-inserted instead, shifting existing text. Leaves mark at one corner
-of rectangle and point at the other (diagonally opposed) corner."
- (interactive "cRectangle from register: \nP")
- (let ((rectangle (get-register register)))
- (if (not (consp rectangle))
- (error "Register %c does not contain a rectangle." register)
- (picture-insert-rectangle rectangle insertp))))
-
-(defun picture-insert-rectangle (rectangle &optional insertp)
- "Overlay RECTANGLE with upper left corner at point.
-Optional argument INSERTP, if non-nil causes RECTANGLE to be inserted.
-Leaves the region surrounding the rectangle."
- (let ((indent-tabs-mode nil))
- (if (not insertp)
- (save-excursion
- (delete-rectangle (point)
- (progn
- (picture-forward-column (length (car rectangle)))
- (picture-move-down (1- (length rectangle)))
- (point)))))
- (push-mark)
- (insert-rectangle rectangle)))
-
-
-;; Picture Keymap, entry and exit points.
-
-(defconst picture-mode-map nil)
-
-(defun picture-substitute (oldfun newfun)
- (substitute-key-definition oldfun newfun picture-mode-map global-map))
-
-(if (not picture-mode-map)
- (progn
- (setq picture-mode-map (list 'keymap (make-vector 256 nil)))
- (picture-substitute 'self-insert-command 'picture-self-insert)
- (picture-substitute 'completion-separator-self-insert-command
- 'picture-self-insert)
- (picture-substitute 'completion-separator-self-insert-autofilling
- 'picture-self-insert)
- (picture-substitute 'forward-char 'picture-forward-column)
- (picture-substitute 'backward-char 'picture-backward-column)
- (picture-substitute 'delete-char 'picture-clear-column)
- ;; There are two possibilities for what is normally on DEL.
- (picture-substitute 'backward-delete-char-untabify 'picture-backward-clear-column)
- (picture-substitute 'delete-backward-char 'picture-backward-clear-column)
- (picture-substitute 'kill-line 'picture-clear-line)
- (picture-substitute 'open-line 'picture-open-line)
- (picture-substitute 'newline 'picture-newline)
- (picture-substitute 'newline-and-indent 'picture-duplicate-line)
- (picture-substitute 'next-line 'picture-move-down)
- (picture-substitute 'previous-line 'picture-move-up)
- (picture-substitute 'beginning-of-line 'picture-beginning-of-line)
- (picture-substitute 'end-of-line 'picture-end-of-line)
-
- (define-key picture-mode-map "\C-c\C-d" 'delete-char)
- (define-key picture-mode-map "\e\t" 'picture-toggle-tab-state)
- (define-key picture-mode-map "\t" 'picture-tab)
- (define-key picture-mode-map "\e\t" 'picture-tab-search)
- (define-key picture-mode-map "\C-c\t" 'picture-set-tab-stops)
- (define-key picture-mode-map "\C-c\C-k" 'picture-clear-rectangle)
- (define-key picture-mode-map "\C-c\C-w" 'picture-clear-rectangle-to-register)
- (define-key picture-mode-map "\C-c\C-y" 'picture-yank-rectangle)
- (define-key picture-mode-map "\C-c\C-x" 'picture-yank-rectangle-from-register)
- (define-key picture-mode-map "\C-c\C-c" 'picture-mode-exit)
- (define-key picture-mode-map "\C-c\C-f" 'picture-motion)
- (define-key picture-mode-map "\C-c\C-b" 'picture-motion-reverse)
- (define-key picture-mode-map "\C-c<" 'picture-movement-left)
- (define-key picture-mode-map "\C-c>" 'picture-movement-right)
- (define-key picture-mode-map "\C-c^" 'picture-movement-up)
- (define-key picture-mode-map "\C-c." 'picture-movement-down)
- (define-key picture-mode-map "\C-c`" 'picture-movement-nw)
- (define-key picture-mode-map "\C-c'" 'picture-movement-ne)
- (define-key picture-mode-map "\C-c/" 'picture-movement-sw)
- (define-key picture-mode-map "\C-c\\" 'picture-movement-se)))
-
-(defvar picture-mode-hook nil
- "If non-nil, its value is called on entry to Picture mode.
-Picture mode is invoked by the command \\[picture-mode].")
-
-(defvar picture-mode-old-local-map)
-(defvar picture-mode-old-mode-name)
-(defvar picture-mode-old-major-mode)
-(defvar picture-mode-old-truncate-lines)
-
-;;;###autoload
-(defun picture-mode ()
- "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:
- \\[picture-move-down] Move vertically to SAME column in previous line.
- \\[picture-move-up] Move vertically to SAME column in next line.
- \\[picture-end-of-line] Move to column following last non-whitespace character.
- \\[picture-forward-column] Move right inserting spaces if required.
- \\[picture-backward-column] 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 character.
- `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.
- \\[picture-backward-clear-column] Clear (replace) ARG columns before point, moving back over them.
- \\[picture-clear-line] Clear ARG lines, advancing over them. The cleared
- text is saved in the kill ring.
- \\[picture-open-line] 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 picture-mode-hook if non-nil.
-
-Note that Picture mode commands will work outside of Picture mode, but
-they are not defaultly assigned to keys."
- (interactive)
- (if (eq major-mode 'picture-mode)
- (error "You are already editing a picture.")
- (make-local-variable 'picture-mode-old-local-map)
- (setq picture-mode-old-local-map (current-local-map))
- (use-local-map picture-mode-map)
- (make-local-variable 'picture-mode-old-mode-name)
- (setq picture-mode-old-mode-name mode-name)
- (make-local-variable 'picture-mode-old-major-mode)
- (setq picture-mode-old-major-mode major-mode)
- (setq major-mode 'picture-mode)
- (make-local-variable 'picture-killed-rectangle)
- (setq picture-killed-rectangle nil)
- (make-local-variable 'tab-stop-list)
- (setq tab-stop-list (default-value 'tab-stop-list))
- (make-local-variable 'picture-tab-chars)
- (setq picture-tab-chars (default-value 'picture-tab-chars))
- (make-local-variable 'picture-vertical-step)
- (make-local-variable 'picture-horizontal-step)
- (make-local-variable 'picture-mode-old-truncate-lines)
- (setq picture-mode-old-truncate-lines truncate-lines)
- (setq truncate-lines t)
- (picture-set-motion 0 1)
-
- ;; edit-picture-hook is what we used to run, picture-mode-hook is in doc.
- (run-hooks 'edit-picture-hook 'picture-mode-hook)
- (message "Type %s in this buffer to return it to %s mode."
- (substitute-command-keys "\\[picture-mode-exit]")
- picture-mode-old-mode-name)))
-
-;;;###autoload
-(defalias 'edit-picture 'picture-mode)
-
-(defun picture-mode-exit (&optional nostrip)
- "Undo picture-mode and return to previous major mode.
-With no argument strips whitespace from end of every line in Picture buffer
- otherwise just return to previous mode."
- (interactive "P")
- (if (not (eq major-mode 'picture-mode))
- (error "You aren't editing a Picture.")
- (if (not nostrip) (picture-clean))
- (setq mode-name picture-mode-old-mode-name)
- (use-local-map picture-mode-old-local-map)
- (setq major-mode picture-mode-old-major-mode)
- (kill-local-variable 'tab-stop-list)
- (setq truncate-lines picture-mode-old-truncate-lines)
- (force-mode-line-update)))
-
-(defun picture-clean ()
- "Eliminate whitespace at ends of lines."
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward "[ \t][ \t]*$" nil t)
- (delete-region (match-beginning 0) (point)))))
-
-(provide 'picture)
-
-;;; picture.el ends here
diff --git a/lisp/textmodes/refbib.el b/lisp/textmodes/refbib.el
deleted file mode 100644
index ec3039e578d..00000000000
--- a/lisp/textmodes/refbib.el
+++ /dev/null
@@ -1,730 +0,0 @@
-;;; refbib.el --- convert refer-style references to ones usable by Latex bib
-
-;; Copyright (C) 1989 Free Software Foundation, Inc.
-
-;; Author: Henry Kautz <kautz@research.att.com>
-;; Keywords: bib, tex
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; 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*.
-
-;;; Change Log:
-
-;; HISTORY
-;; 9/88, created H.Kautz
-;; 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 capitalize-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
-
-;;; Code:
-
-;**********************************************************
-; 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 its 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 not to be used to build the citation key.
-This is in addition to the `r2b-capitalize-title-stop-words'.")
-
-(defvar r2b-delimit-with-quote
- t
- "*If true, then use \" to delimit fields, otherwise use braces")
-
-;**********************************************************
-; Utility Functions
-
-(defvar r2b-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 capitalized in a title (unless the first word).")
-
-(defvar r2b-capitalize-title-stop-regexp
- (concat "\\(" r2b-capitalize-title-stop-words "\\)\\(\\b\\|'\\)"))
-
-(defun r2b-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 r2b-capitalize-title-stop-regexp))
- (downcase-word 1)
- (capitalize-word 1)))
- ))
- (set-syntax-table orig-syntax-table))))
-
-
-(defun r2b-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)
- (r2b-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 'r2b-capitalize-title-stop-words)
- (makunbound 'r2b-capitalize-title-stop-regexp)
- (makunbound 'r2b-additional-stop-words)
- (makunbound 'r2b-stop-regexp))
-
-(defvar r2b-stop-regexp
- (concat "\\`\\(\\("
- r2b-additional-stop-words "\\|" r2b-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 (r2b-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 its 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
-Please send bug reports and suggestions to
- Henry Kautz
- kautz@research.att.com
- allegra!kautz")
-
-
-(defun r2b-help ()
- "Print help message."
- (interactive)
- (with-output-to-temp-buffer "*Help*"
- (princ r2b-help-message)
- (save-excursion
- (set-buffer standard-output)
- (help-mode))))
-
-(if (not r2b-load-quietly)
- (r2b-help))
-
-(message "r2b loaded")
-
-(provide 'refer-to-bibtex)
-
-;;; refbib.el ends here
diff --git a/lisp/textmodes/refer.el b/lisp/textmodes/refer.el
deleted file mode 100644
index 3234acf2d02..00000000000
--- a/lisp/textmodes/refer.el
+++ /dev/null
@@ -1,387 +0,0 @@
-;;; refer.el --- look up references in bibliography files.
-
-;; Copyright (C) 1992, 1996 Free Software Foundation, Inc.
-
-;; Author: Ashwin Ram <ashwin@cc.gatech.edu>
-;; Maintainer: Gernot Heiser <gernot@jungfrau.disy.cse.unsw.EDU.AU>
-;; Adapted-By: ESR
-;; Keywords: bib
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Functions to look up references in bibliography files given lists of
-;; keywords, similar to refer(1). I don't use tags since tags on .bib files
-;; only picks up the cite key, where as refer-find-entry looks for occurrences
-;; of keywords anywhere in the bibliography entry.
-;;
-;; To use:
-;; (autoload 'refer-find-entry "refer" nil t)
-;; or (require 'refer)
-;;
-;; To look for an article by Knuth about semaphores:
-;; Invoke refer-find-entry, then in response to the Keywords: prompt,
-;; say: Knuth semaphores (a blank-separated list of keywords to be used
-;; as search strings).
-;;
-;; To continue the previous search, i.e., to search for the next occurrence
-;; of the keywords, use refer-find-next-entry, or invoke refer-find-entry
-;; with a prefix argument.
-;;
-;; Once you've found the entry you want to reference, invoke
-;; refer-yank-key to insert it at point in the current buffer
-;; (typically as the argument of a \cite{} command).
-;;
-;; I use (define-key tex-mode-map "\C-c\C-y" 'refer-yank-key)
-;; to bind this often-used function to a key in (la)tex-mode.
-;;
-;; If the list of bibliography files changes, reinitialize the variable
-;; refer-bib-files.
-;;
-;; To customize:
-;; See variables refer-bib-files, refer-cache-bib-files and
-;; refer-bib-files-regexp. By default, these are set up so that refer
-;; looks for the keywords you specify in all the .bib files in the current
-;; directory.
-;;
-;; The only assumption I make about bib files is that they contain a bunch
-;; of entries, one to a paragraph. refer-find-entry searches paragraph by
-;; paragraph, looking for a paragraph containing all the keywords
-;; specified. So you should be able to use pretty much any bib file with
-;; this code. If your bib file does not use paragraphs to separate
-;; entries, try setting the paragraph-start/separate variables, or changing
-;; the (forward-paragraph 1) call in refer-find-entry-in-file.
-
-;;; Code:
-
-(provide 'refer)
-
-(defvar refer-bib-directory nil
- "Directory, or list of directories, to search for \\.bib files. Can
-be set to 'bibinputs or 'texinputs, in which case the environment
-variable BIBINPUTS or TEXINPUTS, respectively, is used to obtain a
-list of directories. Useful only if refer-bib-files is set to 'dir or
-a list of file names (without directory). A value of nil indicates the
-current working directory.
-
-If refer-bib-directory is 'bibinputs or 'texinputs, it is setq'd to
-the appropriate list of directories when it is first used.
-
-Note that an empty directory is interpreted by BibTeX as indicating
-the default search path. Since Refer does not know that default path,
-it cannot search it. Include that path explicitly in your BIBINPUTS
-environment if you really want it searched (which is not likely to
-happen anyway).")
-
-(defvar refer-bib-files 'dir
- "*List of \\.bib files to search for references,
-or one of the following special values:
-nil = prompt for \\.bib file (if visiting a \\.bib file, use it as default)
-auto = read \\.bib file names from appropriate command in buffer (see
- refer-bib-files-regexp) unless the buffer's mode is bibtex-mode,
- in which case only the buffer is searched
-dir = use all \\.bib files in directories referenced by refer-bib-directory.
-
-If a specified file doesn't exist and has no extension, a \\.bib extension
-is automatically tried.
-
-If refer-bib-files is nil, auto or dir, it is setq'd to the appropriate
-list of files when it is first used if refer-cache-bib-files is t. If
-refer-cache-bib-files is nil, the list of \\.bib files to use is re-read
-each time it is needed.")
-
-(defvar refer-cache-bib-files t
- "*Variable determining whether the value of refer-bib-files should be cached.
-If t, initialize the value of refer-bib-files the first time it is used. If
-nil, re-read the list of \\.bib files depending on the value of refer-bib-files
-each time it is needed.")
-
-(defvar refer-bib-files-regexp "\\\\bibliography"
- "*Regexp matching a bibliography file declaration.
-The current buffer is expected to contain a line such as
-\\bibliography{file1,file2,file3}
-which is read to set up refer-bib-files. The regexp must specify the command
-(such as \\bibliography) that is used to specify the list of bib files. The
-command is expected to specify a file name, or a list of comma-separated file
-names, within curly braces.
-If a specified file doesn't exist and has no extension, a \\.bib extension
-is automatically tried.")
-
-(make-variable-buffer-local 'refer-bib-files)
-(make-variable-buffer-local 'refer-cache-bib-files)
-(make-variable-buffer-local 'refer-bib-directory)
-
-;;; Internal variables
-(defvar refer-saved-state nil)
-(defvar refer-previous-keywords nil)
-(defvar refer-saved-pos nil)
-(defvar refer-same-file nil)
-
-(defun refer-find-entry (keywords &optional continue)
- "Find entry in refer-bib-files containing KEYWORDS.
-If KEYWORDS is nil, prompt user for blank-separated list of keywords.
-If CONTINUE is t, or if called interactively with a prefix arg, look for next
-entry by continuing search from previous point."
- (interactive (list nil current-prefix-arg))
- (or keywords (setq keywords (if continue
- refer-previous-keywords
- (read-string "Keywords: "))))
- (setq refer-previous-keywords keywords)
- (refer-find-entry-internal keywords continue))
-
-(defun refer-find-next-entry ()
- "Find next occurrence of entry in refer-bib-files. See refer-find-entry."
- (interactive)
- (refer-find-entry-internal refer-previous-keywords t))
-
-(defun refer-yank-key ()
- "Inserts at point in current buffer the \"key\" field of the entry
-found on the last refer-find-entry or refer-find-next-entry."
- (interactive)
- (let ((old-point (point)))
- (insert
- (save-window-excursion
- (save-excursion
- (find-file (car refer-saved-state))
- (if (looking-at
- "[ \t\n]*@\\s-*[a-zA-Z][a-zA-Z0-9]*\\s-*{\\s-*\\([^ \t\n,]+\\)\\s-*,")
- (buffer-substring (match-beginning 1) (match-end 1))
- (error "Cannot find key for entry in file %s."
- (car refer-saved-state))))))
- (if (not (= (point) old-point))
- (set-mark old-point))))
-
-(defun refer-find-entry-internal (keywords continue)
- (let ((keywords-list (refer-convert-string-to-list-of-strings keywords))
- (old-buffer (current-buffer))
- (old-window (selected-window))
- (new-window (selected-window))
- (files (if continue
- refer-saved-state
- (setq refer-saved-pos nil)
- (refer-get-bib-files)))
- (n 0)
- (found nil)
- (file nil))
- ;; find window in which to display bibliography file.
- ;; if a bibliography file is already displayed in a window, use
- ;; that one, otherwise use any window other than the current one
- (while (not found)
- (while (and (not (null (setq file (nth n files))))
- (setq n (1+ n))
- (not (string-equal file
- (buffer-file-name
- (window-buffer new-window))))))
- (setq found
- (if (null file)
- (eq (setq new-window (next-window new-window 'nomini))
- old-window)
- 't)))
- (if (null file) ; didn't find bib file in any window:
- (progn (if (one-window-p 'nomini)
- (setq old-window (split-window)))
- (setq new-window (next-window old-window 'nomini))))
- (select-window (if refer-same-file
- old-window
- new-window)) ; the window in which to show the bib file
- (catch 'found
- (while files
- (let ((file (cond ((file-exists-p (car files)) (car files))
- ((file-exists-p (concat (car files) ".bib"))
- (concat (car files) ".bib")))))
- (setq refer-saved-state files)
- (if file
- (if (refer-find-entry-in-file keywords-list file refer-saved-pos)
- (progn
- (setq refer-saved-pos (point))
- (recenter 0)
- (throw 'found (find-file file)))
- (setq refer-saved-pos nil
- files (cdr files)))
- (progn (message "Scanning %s... No such file" (car files) (ding))
- (sit-for 1)
- (setq files (cdr files))))))
- (message "Keywords \"%s\" not found in any \.bib file" keywords (ding)))
- (select-window old-window)))
-
-(defun refer-find-entry-in-file (keywords-list file &optional old-pos)
- (message "Scanning %s..." file)
- (expand-file-name file)
- (set-buffer (find-file-noselect file))
- (find-file file)
- (if (not old-pos)
- (goto-char (point-min))
- (goto-char old-pos)
- (forward-paragraph 1))
- (let ((begin (point))
- (end 0)
- (found nil))
- (while (and (not found)
- (not (eobp)))
- (forward-paragraph 1)
- (setq end (point))
- (setq found
- (refer-every (function (lambda (keyword)
- (goto-char begin)
- (re-search-forward keyword end t)))
- keywords-list))
- (if (not found)
- (progn
- (setq begin end)
- (goto-char begin))))
- (if found
- (progn (goto-char begin)
- (re-search-forward "\\W" nil t)
- (message "Scanning %s... found" file))
- (progn (message "Scanning %s... not found" file)
- nil))))
-
-(defun refer-every (pred l)
- (cond ((null l) nil)
- ((funcall pred (car l))
- (or (null (cdr l))
- (refer-every pred (cdr l))))))
-
-(defun refer-convert-string-to-list-of-strings (s)
- (let ((current (current-buffer))
- (temp-buffer (get-buffer-create "*refer-temp*")))
- (set-buffer temp-buffer)
- (erase-buffer)
- (insert (regexp-quote s))
- (goto-char (point-min))
- (insert "(\"")
- (while (re-search-forward "[ \t]+" nil t)
- (replace-match "\" \"" t t))
- (goto-char (point-max))
- (insert "\")")
- (goto-char (point-min))
- (prog1 (read temp-buffer)
- (set-buffer current))))
-
-(defun refer-expand-files (file-list dir-list)
- (let (file files dir dirs)
- (while (setq file (car file-list))
- (setq dirs (copy-alist dir-list))
- (while (setq dir (car dirs))
- (if (file-exists-p (expand-file-name file dir))
- (setq files (append files (list (expand-file-name file dir)))
- dirs nil)
- (if (file-exists-p (expand-file-name (concat file ".bib") dir))
- (setq files (append files (list (expand-file-name (concat file ".bib")
- dir)))
- dirs nil)
- (setq dirs (cdr dirs)))))
- (setq file-list (cdr file-list)))
- files))
-
-(defun refer-get-bib-files ()
- (let* ((dir-list
- (cond
- ((null refer-bib-directory)
- '("."))
- ((or (eq refer-bib-directory 'texinputs)
- (eq refer-bib-directory 'bibinputs))
- (let ((envvar (getenv (if (eq refer-bib-directory 'texinputs)
- "TEXINPUTS"
- "BIBINPUTS")))
- (dirs nil))
- (if (null envvar)
- (setq envvar "."))
- (while (string-match ":" envvar)
- (let ((dir (substring envvar 0 (match-beginning 0))))
- (if (and (not (string-equal "" dir))
- (file-directory-p dir))
- (setq dirs (append (list (expand-file-name dir nil))
- dirs))))
- (setq envvar (substring envvar (match-end 0))))
- (if (and (not (string-equal "" envvar))
- (file-directory-p envvar))
- (setq dirs (append (list envvar) dirs)))
- (setq dirs (nreverse dirs))))
- ((listp refer-bib-directory)
- refer-bib-directory)
- (t
- (list refer-bib-directory))))
- (files
- (cond
- ((null refer-bib-files)
- (list (expand-file-name
- (if (eq major-mode 'bibtex-mode)
- (read-file-name
- (format ".bib file: (default %s) "
- (file-name-nondirectory
- (buffer-file-name)))
- (file-name-directory (buffer-file-name))
- (file-name-nondirectory (buffer-file-name))
- t)
- (read-file-name ".bib file: " nil nil t)))))
- ((eq refer-bib-files 'auto)
- (let ((files
- (save-excursion
- (if (setq refer-same-file (eq major-mode 'bibtex-mode))
- (list buffer-file-name)
- (if (progn
- (goto-char (point-min))
- (re-search-forward (concat refer-bib-files-regexp
- "\\s-*\{") nil t))
- (let ((files (list (buffer-substring
- (point)
- (progn
- (re-search-forward "[,\}]"
- nil t)
- (backward-char 1)
- (point))))))
- (while (not (looking-at "\}"))
- (setq files (append files
- (list (buffer-substring
- (progn (forward-char 1)
- (point))
- (progn (re-search-forward
- "[,\}]" nil t)
- (backward-char 1)
- (point)))))))
- files)
- (error (concat "No \\\\bibliography command in this "
- "buffer, can't read refer-bib-files")))))))
- (refer-expand-files files dir-list)))
- ((eq refer-bib-files 'dir)
- (let ((dirs (nreverse dir-list))
- dir files)
- (while (setq dir (car dirs))
- (setq files
- (append (directory-files dir t "\\.bib$")
- files))
- (setq dirs (cdr dirs)))
- files))
- ((and (listp refer-bib-files)
- (or (eq refer-bib-directory 'texinputs)
- (eq refer-bib-directory 'bibinputs)))
- (refer-expand-files refer-bib-files dir-list))
- ((listp refer-bib-files) refer-bib-files)
- (t (error "Illegal value for refer-bib-files: %s"
- refer-bib-files)))))
- (if (or (eq refer-bib-directory 'texinputs)
- (eq refer-bib-directory 'bibinputs))
- (setq refer-bib-directory dir-list))
- (if refer-cache-bib-files
- (setq refer-bib-files files))
- files))
-
-;;; refer.el ends here
-
diff --git a/lisp/textmodes/scribe.el b/lisp/textmodes/scribe.el
deleted file mode 100644
index 2ec4899585a..00000000000
--- a/lisp/textmodes/scribe.el
+++ /dev/null
@@ -1,325 +0,0 @@
-;;; scribe.el --- scribe mode, and its idiosyncratic commands.
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: wp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; A major mode for editing source in written for the Scribe text formatter.
-;; Knows about Scribe syntax and standard layout rules. The command to
-;; run Scribe on a buffer is bogus; someone interested should fix it.
-
-;;; Code:
-
-(defvar scribe-mode-syntax-table nil
- "Syntax table used while in scribe mode.")
-
-(defvar scribe-mode-abbrev-table nil
- "Abbrev table used while in scribe mode.")
-
-(defvar scribe-fancy-paragraphs nil
- "*Non-NIL makes Scribe mode use a different style of paragraph separation.")
-
-(defvar scribe-electric-quote nil
- "*Non-NIL makes insert of double quote use `` or '' depending on context.")
-
-(defvar scribe-electric-parenthesis nil
- "*Non-NIL makes parenthesis char ( (]}> ) automatically insert its close
-if typed after an @Command form.")
-
-(defconst scribe-open-parentheses "[({<"
- "Open parenthesis characters for Scribe.")
-
-(defconst scribe-close-parentheses "])}>"
- "Close parenthesis characters for Scribe.
-These should match up with `scribe-open-parenthesis'.")
-
-(if (null scribe-mode-syntax-table)
- (let ((st (syntax-table)))
- (unwind-protect
- (progn
- (setq scribe-mode-syntax-table (copy-syntax-table
- text-mode-syntax-table))
- (set-syntax-table scribe-mode-syntax-table)
- (modify-syntax-entry ?\" " ")
- (modify-syntax-entry ?\\ " ")
- (modify-syntax-entry ?@ "w ")
- (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 st))))
-
-(defvar scribe-mode-map nil)
-
-(if scribe-mode-map
- nil
- (setq scribe-mode-map (make-sparse-keymap))
- (define-key scribe-mode-map "\t" 'scribe-tab)
- (define-key scribe-mode-map "\e\t" 'tab-to-tab-stop)
- (define-key scribe-mode-map "\es" 'center-line)
- (define-key scribe-mode-map "\e}" 'up-list)
- (define-key scribe-mode-map "\eS" 'center-paragraph)
- (define-key scribe-mode-map "\"" 'scribe-insert-quote)
- (define-key scribe-mode-map "(" 'scribe-parenthesis)
- (define-key scribe-mode-map "[" 'scribe-parenthesis)
- (define-key scribe-mode-map "{" 'scribe-parenthesis)
- (define-key scribe-mode-map "<" 'scribe-parenthesis)
- (define-key scribe-mode-map "\C-c\C-c" 'scribe-chapter)
- (define-key scribe-mode-map "\C-c\C-t" 'scribe-section)
- (define-key scribe-mode-map "\C-c\C-s" 'scribe-subsection)
- (define-key scribe-mode-map "\C-c\C-v" 'scribe-insert-environment)
- (define-key scribe-mode-map "\C-c\C-e" 'scribe-bracket-region-be)
- (define-key scribe-mode-map "\C-c[" 'scribe-begin)
- (define-key scribe-mode-map "\C-c]" 'scribe-end)
- (define-key scribe-mode-map "\C-c\C-i" 'scribe-italicize-word)
- (define-key scribe-mode-map "\C-c\C-b" 'scribe-bold-word)
- (define-key scribe-mode-map "\C-c\C-u" 'scribe-underline-word))
-
-;;;###autoload
-(defun scribe-mode ()
- "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."
- (interactive)
- (kill-all-local-variables)
- (use-local-map scribe-mode-map)
- (setq mode-name "Scribe")
- (setq major-mode 'scribe-mode)
- (define-abbrev-table 'scribe-mode-abbrev-table ())
- (setq local-abbrev-table scribe-mode-abbrev-table)
- (make-local-variable 'comment-start)
- (setq comment-start "@Comment[")
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip (concat "@Comment[" scribe-open-parentheses "]"))
- (make-local-variable 'comment-column)
- (setq comment-column 0)
- (make-local-variable 'comment-end)
- (setq comment-end "]")
- (make-local-variable 'paragraph-start)
- (setq paragraph-start (concat "\\([\n\f]\\)\\|\\(@\\w+["
- scribe-open-parentheses
- "].*["
- scribe-close-parentheses
- "]$\\)"))
- (make-local-variable 'paragraph-separate)
- (setq paragraph-separate (if scribe-fancy-paragraphs
- paragraph-start "$"))
- (make-local-variable 'sentence-end)
- (setq sentence-end "\\([.?!]\\|@:\\)[]\"')}]*\\($\\| $\\|\t\\| \\)[ \t\n]*")
- (make-local-variable 'compile-command)
- (setq compile-command (concat "scribe " (buffer-file-name)))
- (set-syntax-table scribe-mode-syntax-table)
- (run-hooks 'text-mode-hook 'scribe-mode-hook))
-
-(defun scribe-tab ()
- (interactive)
- (insert "@\\"))
-
-;; This algorithm could probably be improved somewhat.
-;; Right now, it loses seriously...
-
-(defun scribe ()
- "Run Scribe on the current buffer."
- (interactive)
- (call-interactively 'compile))
-
-(defun scribe-envelop-word (string count)
- "Surround current word with Scribe construct @STRING[...].
-COUNT specifies how many words to surround. A negative count means
-to skip backward."
- (let ((spos (point)) (epos (point)) (ccoun 0) noparens)
- (if (not (zerop count))
- (progn (if (= (char-syntax (preceding-char)) ?w)
- (forward-sexp (min -1 count)))
- (setq spos (point))
- (if (looking-at (concat "@\\w[" scribe-open-parentheses "]"))
- (forward-char 2)
- (goto-char epos)
- (skip-chars-backward "\\W")
- (forward-char -1))
- (forward-sexp (max count 1))
- (setq epos (point))))
- (goto-char spos)
- (while (and (< ccoun (length scribe-open-parentheses))
- (save-excursion
- (or (search-forward (char-to-string
- (aref scribe-open-parentheses ccoun))
- epos t)
- (search-forward (char-to-string
- (aref scribe-close-parentheses ccoun))
- epos t)))
- (setq ccoun (1+ ccoun))))
- (if (>= ccoun (length scribe-open-parentheses))
- (progn (goto-char epos)
- (insert "@end(" string ")")
- (goto-char spos)
- (insert "@begin(" string ")"))
- (goto-char epos)
- (insert (aref scribe-close-parentheses ccoun))
- (goto-char spos)
- (insert "@" string (aref scribe-open-parentheses ccoun))
- (goto-char epos)
- (forward-char 3)
- (skip-chars-forward scribe-close-parentheses))))
-
-(defun scribe-underline-word (count)
- "Underline COUNT words around point by means of Scribe constructs."
- (interactive "p")
- (scribe-envelop-word "u" count))
-
-(defun scribe-bold-word (count)
- "Boldface COUNT words around point by means of Scribe constructs."
- (interactive "p")
- (scribe-envelop-word "b" count))
-
-(defun scribe-italicize-word (count)
- "Italicize COUNT words around point by means of Scribe constructs."
- (interactive "p")
- (scribe-envelop-word "i" count))
-
-(defun scribe-begin ()
- (interactive)
- (insert "\n")
- (forward-char -1)
- (scribe-envelop-word "Begin" 0)
- (re-search-forward (concat "[" scribe-open-parentheses "]")))
-
-(defun scribe-end ()
- (interactive)
- (insert "\n")
- (forward-char -1)
- (scribe-envelop-word "End" 0)
- (re-search-forward (concat "[" scribe-open-parentheses "]")))
-
-(defun scribe-chapter ()
- (interactive)
- (insert "\n")
- (forward-char -1)
- (scribe-envelop-word "Chapter" 0)
- (re-search-forward (concat "[" scribe-open-parentheses "]")))
-
-(defun scribe-section ()
- (interactive)
- (insert "\n")
- (forward-char -1)
- (scribe-envelop-word "Section" 0)
- (re-search-forward (concat "[" scribe-open-parentheses "]")))
-
-(defun scribe-subsection ()
- (interactive)
- (insert "\n")
- (forward-char -1)
- (scribe-envelop-word "SubSection" 0)
- (re-search-forward (concat "[" scribe-open-parentheses "]")))
-
-(defun scribe-bracket-region-be (env min max)
- (interactive "sEnvironment: \nr")
- (save-excursion
- (goto-char max)
- (insert "@end(" env ")\n")
- (goto-char min)
- (insert "@begin(" env ")\n")))
-
-(defun scribe-insert-environment (env)
- (interactive "sEnvironment: ")
- (scribe-bracket-region-be env (point) (point))
- (forward-line 1)
- (insert ?\n)
- (forward-char -1))
-
-(defun scribe-insert-quote (count)
- "Insert ``, '' or \" according to preceding character.
-If `scribe-electric-quote' is non-NIL, insert ``, '' or \" according
-to preceding character. With numeric arg N, always insert N \" characters.
-Else just insert \"."
- (interactive "P")
- (if (or count (not scribe-electric-quote))
- (self-insert-command (prefix-numeric-value count))
- (let (lastfore lastback lastquote)
- (insert
- (cond
- ((= (preceding-char) ?\\) ?\")
- ((bobp) "``")
- (t
- (setq lastfore (save-excursion (and (search-backward
- "``" (- (point) 1000) t)
- (point)))
- lastback (save-excursion (and (search-backward
- "''" (- (point) 1000) t)
- (point)))
- lastquote (save-excursion (and (search-backward
- "\"" (- (point) 100) t)
- (point))))
- (if (not lastquote)
- (cond ((not lastfore) "``")
- ((not lastback) "''")
- ((> lastfore lastback) "''")
- (t "``"))
- (cond ((and (not lastback) (not lastfore)) "\"")
- ((and lastback (not lastfore) (> lastquote lastback)) "\"")
- ((and lastback (not lastfore) (> lastback lastquote)) "``")
- ((and lastfore (not lastback) (> lastquote lastfore)) "\"")
- ((and lastfore (not lastback) (> lastfore lastquote)) "''")
- ((and (> lastquote lastfore) (> lastquote lastback)) "\"")
- ((> lastfore lastback) "''")
- (t "``")))))))))
-
-(defun scribe-parenthesis (count)
- "If scribe-electric-parenthesis is non-NIL, insertion of an open-parenthesis
-character inserts the following close parenthesis character if the
-preceding text is of the form @Command."
- (interactive "P")
- (self-insert-command (prefix-numeric-value count))
- (let (at-command paren-char point-save)
- (if (or count (not scribe-electric-parenthesis))
- nil
- (save-excursion
- (forward-char -1)
- (setq point-save (point))
- (skip-chars-backward (concat "^ \n\t\f" scribe-open-parentheses))
- (setq at-command (and (equal (following-char) ?@)
- (/= (point) (1- point-save)))))
- (if (and at-command
- (setq paren-char
- (string-match (regexp-quote
- (char-to-string (preceding-char)))
- scribe-open-parentheses)))
- (save-excursion
- (insert (aref scribe-close-parentheses paren-char)))))))
-
-;;; scribe.el ends here
diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el
deleted file mode 100644
index 234d8c2fba7..00000000000
--- a/lisp/textmodes/sgml-mode.el
+++ /dev/null
@@ -1,1262 +0,0 @@
-;;; sgml-mode.el --- SGML- and HTML-editing modes
-
-;; Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: James Clark <jjc@clark.com>
-;; Adapted-By: ESR; Daniel.Pfeiffer@Informatik.START.dbp.de
-;; Keywords: wp, hypermedia, comm, languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Configurable major mode for editing document in the SGML standard general
-;; markup language. As an example contains a mode for editing the derived
-;; HTML hypertext markup language.
-
-;;; Code:
-
-;; As long as Emacs' syntax can't be complemented with predicates to context
-;; sensitively confirm the syntax of characters, we have to live with this
-;; kludgy kind of tradeoff.
-(defvar sgml-specials '(?\")
- "List of characters that have a special meaning for sgml-mode.
-This list is used when first loading the sgml-mode library.
-The supported characters and potential disadvantages are:
-
- ?\\\" Makes \" in text start a string.
- ?' Makes ' in text start a string.
- ?- Makes -- in text start a comment.
-
-When only one of ?\\\" or ?' are included, \"'\" or '\"' as it can be found in
-DTDs, start a string. To partially avoid this problem this also makes these
-self insert as named entities depending on `sgml-quick-keys'.
-
-Including ?- has the problem of affecting dashes that have nothing to do
-with comments, so we normally turn it off.")
-
-(defvar sgml-quick-keys nil
- "Use <, >, &, SPC and `sgml-specials' keys ``electrically'' when non-nil.
-This takes effect when first loading the library.")
-
-
-(defvar sgml-mode-map
- (let ((map (list 'keymap (make-vector 256 nil)))
- (menu-map (make-sparse-keymap "SGML")))
- (define-key map "\t" 'indent-relative-maybe)
- (define-key map "\C-c\C-i" 'sgml-tags-invisible)
- (define-key map "/" 'sgml-slash)
- (define-key map "\C-c\C-n" 'sgml-name-char)
- (define-key map "\C-c\C-t" 'sgml-tag)
- (define-key map "\C-c\C-a" 'sgml-attributes)
- (define-key map "\C-c\C-b" 'sgml-skip-tag-backward)
- (define-key map [?\C-c left] 'sgml-skip-tag-backward)
- (define-key map "\C-c\C-f" 'sgml-skip-tag-forward)
- (define-key map [?\C-c right] 'sgml-skip-tag-forward)
- (define-key map "\C-c\C-d" 'sgml-delete-tag)
- (define-key map "\C-c\^?" 'sgml-delete-tag)
- (define-key map "\C-c?" 'sgml-tag-help)
- (define-key map "\C-c8" 'sgml-name-8bit-mode)
- (define-key map "\C-c\C-v" 'sgml-validate)
- (if sgml-quick-keys
- (progn
- (define-key map "&" 'sgml-name-char)
- (define-key map "<" 'sgml-tag)
- (define-key map " " 'sgml-auto-attributes)
- (define-key map ">" 'sgml-maybe-end-tag)
- (if (memq ?\" sgml-specials)
- (define-key map "\"" 'sgml-name-self))
- (if (memq ?' sgml-specials)
- (define-key map "'" 'sgml-name-self))))
- (let ((c 127)
- (map (nth 1 map)))
- (while (< (setq c (1+ c)) 256)
- (aset map c 'sgml-maybe-name-self)))
- (define-key map [menu-bar sgml] (cons "SGML" menu-map))
- (define-key menu-map [sgml-validate] '("Validate" . sgml-validate))
- (define-key menu-map [sgml-name-8bit-mode]
- '("Toggle 8 Bit Insertion" . sgml-name-8bit-mode))
- (define-key menu-map [sgml-tags-invisible]
- '("Toggle Tag Visibility" . sgml-tags-invisible))
- (define-key menu-map [sgml-tag-help]
- '("Describe Tag" . sgml-tag-help))
- (define-key menu-map [sgml-delete-tag]
- '("Delete Tag" . sgml-delete-tag))
- (define-key menu-map [sgml-skip-tag-forward]
- '("Forward Tag" . sgml-skip-tag-forward))
- (define-key menu-map [sgml-skip-tag-backward]
- '("Backward Tag" . sgml-skip-tag-backward))
- (define-key menu-map [sgml-attributes]
- '("Insert Attributes" . sgml-attributes))
- (define-key menu-map [sgml-tag] '("Insert Tag" . sgml-tag))
- map)
- "Keymap for SGML mode. See also `sgml-specials'.")
-
-
-(defvar sgml-mode-syntax-table
- (let ((table (copy-syntax-table text-mode-syntax-table)))
- (modify-syntax-entry ?< "(>" table)
- (modify-syntax-entry ?> ")<" table)
- (if (memq ?- sgml-specials)
- (modify-syntax-entry ?- "_ 1234" table))
- (if (memq ?\" sgml-specials)
- (modify-syntax-entry ?\" "\"\"" table))
- (if (memq ?' sgml-specials)
- (modify-syntax-entry ?\' "\"'" table))
- table)
- "Syntax table used in SGML mode. See also `sgml-specials'.")
-
-
-(defvar sgml-name-8bit-mode nil
- "*When non-`nil' insert 8 bit characters with their names.")
-
-(defvar sgml-char-names
- [nil nil nil nil nil nil nil nil
- nil nil nil nil nil nil nil nil
- nil nil nil nil nil nil nil nil
- nil nil nil nil nil nil nil nil
- "ensp" "excl" "quot" "num" "dollar" "percnt" "amp" "apos"
- "lpar" "rpar" "ast" "plus" "comma" "hyphen" "period" "sol"
- nil nil nil nil nil nil nil nil
- nil nil "colon" "semi" "lt" "eq" "gt" "quest"
- "commat" nil nil nil nil nil nil nil
- nil nil nil nil nil nil nil nil
- nil nil nil nil nil nil nil nil
- nil nil nil "lsqb" nil "rsqb" "uarr" "lowbar"
- "lsquo" nil nil nil nil nil nil nil
- nil nil nil nil nil nil nil nil
- nil nil nil nil nil nil nil nil
- nil nil nil "lcub" "verbar" "rcub" "tilde" nil
- nil nil nil nil nil nil nil nil
- nil nil nil nil nil nil nil nil
- nil nil nil nil nil nil nil nil
- nil nil nil nil nil nil nil nil
- "nbsp" "iexcl" "cent" "pound" "curren" "yen" "brvbar" "sect"
- "uml" "copy" "ordf" "laquo" "not" "shy" "reg" "macr"
- "ring" "plusmn" "sup2" "sup3" "acute" "micro" "para" "middot"
- "cedil" "sup1" "ordm" "raquo" "frac14" "half" "frac34" "iquest"
- "Agrave" "Aacute" "Acirc" "Atilde" "Auml" "Aring" "AElig" "Ccedil"
- "Egrave" "Eacute" "Ecirc" "Euml" "Igrave" "Iacute" "Icirc" "Iuml"
- "ETH" "Ntilde" "Ograve" "Oacute" "Ocirc" "Otilde" "Ouml" nil
- "Oslash" "Ugrave" "Uacute" "Ucirc" "Uuml" "Yacute" "THORN" "szlig"
- "agrave" "aacute" "acirc" "atilde" "auml" "aring" "aelig" "ccedil"
- "egrave" "eacute" "ecirc" "euml" "igrave" "iacute" "icirc" "iuml"
- "eth" "ntilde" "ograve" "oacute" "ocirc" "otilde" "ouml" "divide"
- "oslash" "ugrave" "uacute" "ucirc" "uuml" "yacute" "thorn" "yuml"]
- "Vector of symbolic character names without `&' and `;'.")
-
-
-;; sgmls is a free SGML parser available from
-;; ftp.uu.net:pub/text-processing/sgml
-;; Its error messages can be parsed by next-error.
-;; The -s option suppresses output.
-
-(defvar sgml-validate-command "sgmls -s"
- "*The command to validate an SGML document.
-The file name of current buffer file name will be appended to this,
-separated by a space.")
-
-(defvar sgml-saved-validate-command nil
- "The command last used to validate in this buffer.")
-
-
-;;; I doubt that null end tags are used much for large elements,
-;;; so use a small distance here.
-(defconst sgml-slash-distance 1000
- "*If non-nil, is the maximum distance to search for matching /.")
-
-(defconst sgml-start-tag-regex
- "<[A-Za-z]\\([-.A-Za-z0-9= \n\t]\\|\"[^\"]*\"\\|'[^']*'\\)*"
- "Regular expression that matches a non-empty start tag.
-Any terminating > or / is not matched.")
-
-
-(defvar sgml-font-lock-keywords
- '(("<\\([!?][a-z0-9]+\\)" 1 font-lock-keyword-face)
- ("<\\(/?[a-z0-9]+\\)" 1 font-lock-function-name-face)
- ("[&%][-.A-Za-z0-9]+;?" . font-lock-variable-name-face)
- ("<!--[^<>]*-->" . font-lock-comment-face))
- "*Rules for highlighting SGML code. See also `sgml-tag-face-alist'.")
-
-;; internal
-(defvar sgml-font-lock-keywords-1 ())
-
-(defvar sgml-face-tag-alist ()
- "Alist of face and tag name for facemenu.")
-
-(defvar sgml-tag-face-alist ()
- "Tag names and face or list of faces to fontify with when invisible.
-When `font-lock-maximum-decoration' is 1 this is always used for fontifying.
-When more these are fontified together with `sgml-font-lock-keywords'.")
-
-
-(defvar sgml-display-text ()
- "Tag names as lowercase symbols, and display string when invisible.")
-
-;; internal
-(defvar sgml-tags-invisible nil)
-
-
-(defvar sgml-tag-alist
- '(("![" ("ignore" t) ("include" t))
- ("!attlist")
- ("!doctype")
- ("!element")
- ("!entity"))
- "*Alist of tag names for completing read and insertion rules.
-This alist is made up as
-
- ((\"tag\" . TAGRULE)
- ...)
-
-TAGRULE is a list of optionally `t' (no endtag) or `\\n' (separate endtag by
-newlines) or a skeleton with `nil', `t' or `\\n' in place of the interactor
-followed by an ATTRIBUTERULE (for an always present attribute) or an
-attribute alist.
-
-The attribute alist is made up as
-
- ((\"attribute\" . ATTRIBUTERULE)
- ...)
-
-ATTRIBUTERULE is a list of optionally `t' (no value when no input) followed by
-an optional alist of possible values.")
-
-(defvar sgml-tag-help
- '(("!" . "Empty declaration for comment")
- ("![" . "Embed declarations with parser directive")
- ("!attlist" . "Tag attributes declaration")
- ("!doctype" . "Document type (DTD) declaration")
- ("!element" . "Tag declaration")
- ("!entity" . "Entity (macro) declaration"))
- "*Alist of tag name and short description.")
-
-
-;; put read-only last to enable setting this even when read-only enabled
-(or (get 'sgml-tag 'invisible)
- (setplist 'sgml-tag
- (append '(invisible t
- rear-nonsticky t
- point-entered sgml-point-entered
- read-only t)
- (symbol-plist 'sgml-tag))))
-
-
-
-(defun sgml-mode-common (sgml-tag-face-alist sgml-display-text)
- "Common code for setting up `sgml-mode' and derived modes.
-SGML-TAG-FACE-ALIST is used for calculating `sgml-font-lock-keywords-1'.
-SGML-DISPLAY-TEXT sets up alternate text for when tags are invisible (see
-varables of same name)."
- (kill-all-local-variables)
- (setq local-abbrev-table text-mode-abbrev-table)
- (set-syntax-table sgml-mode-syntax-table)
- (make-local-variable 'indent-line-function)
- (make-local-variable 'paragraph-start)
- (make-local-variable 'paragraph-separate)
- (make-local-variable 'sgml-saved-validate-command)
- (make-local-variable 'comment-start)
- (make-local-variable 'comment-end)
- (make-local-variable 'comment-indent-function)
- (make-local-variable 'comment-start-skip)
- (make-local-variable 'comment-indent-function)
- (make-local-variable 'sgml-tags-invisible)
- (make-local-variable 'skeleton-transformation)
- (make-local-variable 'skeleton-further-elements)
- (make-local-variable 'skeleton-end-hook)
- (make-local-variable 'font-lock-defaults)
- (make-local-variable 'sgml-font-lock-keywords-1)
- (make-local-variable 'facemenu-add-face-function)
- (make-local-variable 'facemenu-end-add-face)
- ;;(make-local-variable 'facemenu-remove-face-function)
- (and sgml-tag-face-alist
- (not (assq 1 sgml-tag-face-alist))
- (nconc sgml-tag-face-alist
- `((1 (,(concat "<\\("
- (mapconcat 'car sgml-tag-face-alist "\\|")
- "\\)\\([ \t].+\\)?>\\(.+\\)</\\1>")
- 3 (cdr (assoc (match-string 1) ',sgml-tag-face-alist)))))))
- (setq indent-line-function 'indent-relative-maybe
- ;; A start or end tag by itself on a line separates a paragraph.
- ;; This is desirable because SGML discards a newline that appears
- ;; immediately after a start tag or immediately before an end tag.
- paragraph-start "^[ \t\n]\\|\
-\\(</?\\([A-Za-z]\\([-.A-Za-z0-9= \t\n]\\|\"[^\"]*\"\\|'[^']*'\\)*\\)?>$\\)"
- paragraph-separate "^[ \t\n]*$\\|\
-^</?\\([A-Za-z]\\([-.A-Za-z0-9= \t\n]\\|\"[^\"]*\"\\|'[^']*'\\)*\\)?>$"
- comment-start "<!-- "
- comment-end " -->"
- comment-indent-function 'sgml-comment-indent
- ;; This will allow existing comments within declarations to be
- ;; recognized.
- comment-start-skip "--[ \t]*"
- skeleton-transformation 'identity
- skeleton-further-elements '((completion-ignore-case t))
- skeleton-end-hook (lambda ()
- (or (eolp)
- (not (or (eq v2 '\n)
- (eq (car-safe v2) '\n)))
- (newline-and-indent)))
- sgml-font-lock-keywords-1 (cdr (assq 1 sgml-tag-face-alist))
- font-lock-defaults '((sgml-font-lock-keywords
- sgml-font-lock-keywords-1)
- nil
- t)
- facemenu-add-face-function
- (lambda (face end)
- (if (setq face (cdr (assq face sgml-face-tag-alist)))
- (progn
- (setq facemenu-end-add-face (concat "</" face ">"))
- (concat "<" face ">"))
- (error "Face not configured for %s mode." mode-name))))
- (while sgml-display-text
- (put (car (car sgml-display-text)) 'before-string
- (cdr (car sgml-display-text)))
- (setq sgml-display-text (cdr sgml-display-text)))
- (run-hooks 'text-mode-hook 'sgml-mode-hook))
-
-
-;;;###autoload
-(defun sgml-mode (&optional function)
- "Major mode for editing SGML documents.
-Makes > match <. Makes / blink matching /.
-Keys <, &, SPC within <>, \" and ' can be electric depending on
-`sgml-quick-keys'.
-
-Do \\[describe-variable] sgml- SPC to see available variables.
-
-Use \\[sgml-validate] to validate your document with an SGML parser.
-\\{sgml-mode-map}"
- (interactive)
- (sgml-mode-common sgml-tag-face-alist sgml-display-text)
- (use-local-map sgml-mode-map)
- (setq mode-name "SGML"
- major-mode 'sgml-mode))
-
-
-
-(defun sgml-comment-indent ()
- (if (and (looking-at "--")
- (not (and (eq (preceding-char) ?!)
- (eq (char-after (- (point) 2)) ?<))))
- (progn
- (skip-chars-backward " \t")
- (max comment-column (1+ (current-column))))
- 0))
-
-
-
-(defun sgml-slash (arg)
- "Insert / and display any previous matching /.
-Two /s are treated as matching if the first / ends a net-enabling
-start tag, and the second / is the corresponding null end tag."
- (interactive "p")
- (insert-char ?/ arg)
- (if (> arg 0)
- (let ((oldpos (point))
- (blinkpos)
- (level 0))
- (save-excursion
- (save-restriction
- (if sgml-slash-distance
- (narrow-to-region (max (point-min)
- (- (point) sgml-slash-distance))
- oldpos))
- (if (and (re-search-backward sgml-start-tag-regex (point-min) t)
- (eq (match-end 0) (1- oldpos)))
- ()
- (goto-char (1- oldpos))
- (while (and (not blinkpos)
- (search-backward "/" (point-min) t))
- (let ((tagend (save-excursion
- (if (re-search-backward sgml-start-tag-regex
- (point-min) t)
- (match-end 0)
- nil))))
- (if (eq tagend (point))
- (if (eq level 0)
- (setq blinkpos (point))
- (setq level (1- level)))
- (setq level (1+ level)))))))
- (if blinkpos
- (progn
- (goto-char blinkpos)
- (if (pos-visible-in-window-p)
- (sit-for 1)
- (message "Matches %s"
- (buffer-substring (progn
- (beginning-of-line)
- (point))
- (1+ blinkpos))))))))))
-
-
-(defun sgml-name-char (&optional char)
- "Insert a symbolic character name according to `sgml-char-names'.
-8 bit chars may be inserted with the meta key as in M-SPC for no break space,
-or M-- for a soft hyphen."
- (interactive "*")
- (insert ?&)
- (or char
- (setq char (read-quoted-char)))
- (delete-backward-char 1)
- (insert char)
- (undo-boundary)
- (delete-backward-char 1)
- (insert ?&
- (or (aref sgml-char-names char)
- (format "#%d" char))
- ?\;))
-
-
-(defun sgml-name-self ()
- "Insert a symbolic character name according to `sgml-char-names'."
- (interactive "*")
- (sgml-name-char last-command-char))
-
-
-(defun sgml-maybe-name-self ()
- "Insert a symbolic character name according to `sgml-char-names'."
- (interactive "*")
- (if sgml-name-8bit-mode
- (sgml-name-char last-command-char)
- (self-insert-command 1)))
-
-
-(defun sgml-name-8bit-mode ()
- "Toggle insertion of 8 bit characters."
- (interactive)
- (setq sgml-name-8bit-mode (not sgml-name-8bit-mode)))
-
-
-
-(define-skeleton sgml-tag
- "Insert a tag you are prompted for, optionally with attributes.
-Completion and configuration is according to `sgml-tag-alist'.
-If you like tags and attributes in uppercase set `skeleton-transformation'
-to `upcase'."
- (funcall skeleton-transformation
- (completing-read "Tag: " sgml-tag-alist))
- ?< (setq v1 (eval str)) |
- (("") -1 '(undo-boundary) "&lt;") |
- (("") '(setq v2 (sgml-attributes v1 t)) ?>
- (if (string= "![" v1)
- (prog1 '(("") " [ " _ " ]]")
- (backward-char))
- (if (or (eq v2 t)
- (string-match "^[/!?]" v1))
- ()
- (if (symbolp v2)
- '(("") v2 _ v2 "</" v1 ?>)
- (if (eq (car v2) t)
- (cons '("") (cdr v2))
- (append '(("") (car v2))
- (cdr v2)
- '(resume: (car v2) _ "</" v1 ?>))))))))
-
-(autoload 'skeleton-read "skeleton")
-
-(defun sgml-attributes (alist &optional quiet)
- "When at toplevel of a tag, interactively insert attributes."
- (interactive (list (save-excursion (sgml-beginning-of-tag t))))
- (or (stringp alist) (error "Wrong context for adding attribute"))
- (if alist
- (let ((completion-ignore-case t)
- car attribute i)
- (setq alist (cdr (assoc (downcase alist) sgml-tag-alist)))
- (if (or (symbolp (car alist))
- (symbolp (car (car alist))))
- (setq car (car alist)
- alist (cdr alist)))
- (or quiet
- (message "No attributes configured."))
- (if (stringp (car alist))
- (progn
- (insert (if (eq (preceding-char) ? ) "" ? ) (car alist))
- (sgml-value alist))
- (setq i (length alist))
- (while (> i 0)
- (insert ? )
- (insert (funcall skeleton-transformation
- (setq attribute
- (skeleton-read '(completing-read
- "[Attribute]: "
- alist)))))
- (if (string= "" attribute)
- (setq i 0)
- (sgml-value (assoc attribute alist))
- (setq i (1- i))))
- (if (eq (preceding-char) ? )
- (delete-backward-char 1)))
- car)))
-
-(defun sgml-auto-attributes (arg)
- "Self insert, except, when at top level of tag, prompt for attributes.
-With prefix ARG only self insert."
- (interactive "*P")
- (let ((point (point))
- tag)
- (if (or arg
- (not sgml-tag-alist) ; no message when nothing configured
- (symbolp (setq tag (save-excursion (sgml-beginning-of-tag t))))
- (eq (aref tag 0) ?/))
- (self-insert-command (prefix-numeric-value arg))
- (sgml-attributes tag)
- (setq last-command-char ? )
- (or (> (point) point)
- (self-insert-command 1)))))
-
-
-(defun sgml-tag-help (&optional tag)
- "Display description of optional TAG or tag at point."
- (interactive)
- (or tag
- (save-excursion
- (if (eq (following-char) ?<)
- (forward-char))
- (setq tag (sgml-beginning-of-tag))))
- (or (stringp tag)
- (error "No tag selected"))
- (setq tag (downcase tag))
- (message "%s"
- (or (cdr (assoc tag sgml-tag-help))
- (and (eq (aref tag 0) ?/)
- (cdr (assoc (substring tag 1) sgml-tag-help)))
- "No description available")))
-
-
-(defun sgml-maybe-end-tag ()
- "Name self unless in position to end a tag."
- (interactive)
- (or (condition-case nil
- (save-excursion (up-list -1))
- (error
- (sgml-name-self)
- t))
- (condition-case nil
- (progn
- (save-excursion (up-list 1))
- (sgml-name-self))
- (error (self-insert-command 1)))))
-
-
-(defun sgml-skip-tag-backward (arg)
- "Skip to beginning of tag or matching opening tag if present.
-With prefix ARG, repeat that many times."
- (interactive "p")
- (while (>= arg 1)
- (search-backward "<" nil t)
- (if (looking-at "</\\([^ \n\t>]+\\)")
- ;; end tag, skip any nested pairs
- (let ((case-fold-search t)
- (re (concat "</?" (regexp-quote (match-string 1)))))
- (while (and (re-search-backward re nil t)
- (eq (char-after (1+ (point))) ?/))
- (forward-char 1)
- (sgml-skip-tag-backward 1))))
- (setq arg (1- arg))))
-
-(defun sgml-skip-tag-forward (arg &optional return)
- "Skip to end of tag or matching closing tag if present.
-With prefix ARG, repeat that many times.
-Return t iff after a closing tag."
- (interactive "p")
- (setq return t)
- (while (>= arg 1)
- (skip-chars-forward "^<>")
- (if (eq (following-char) ?>)
- (up-list -1))
- (if (looking-at "<\\([^/ \n\t>]+\\)")
- ;; start tag, skip any nested same pairs _and_ closing tag
- (let ((case-fold-search t)
- (re (concat "</?" (regexp-quote (match-string 1))))
- point close)
- (forward-list 1)
- (setq point (point))
- (while (and (re-search-forward re nil t)
- (not (setq close
- (eq (char-after (1+ (match-beginning 0))) ?/)))
- (not (up-list -1))
- (sgml-skip-tag-forward 1))
- (setq close nil))
- (if close
- (up-list 1)
- (goto-char point)
- (setq return)))
- (forward-list 1))
- (setq arg (1- arg)))
- return)
-
-(defun sgml-delete-tag (arg)
- "Delete tag on or after cursor, and matching closing or opening tag.
-With prefix ARG, repeat that many times."
- (interactive "p")
- (while (>= arg 1)
- (save-excursion
- (let* (close open)
- (if (looking-at "[ \t\n]*<")
- ;; just before tag
- (if (eq (char-after (match-end 0)) ?/)
- ;; closing tag
- (progn
- (setq close (point))
- (goto-char (match-end 0))))
- ;; on tag?
- (or (save-excursion (setq close (sgml-beginning-of-tag)
- close (and (stringp close)
- (eq (aref close 0) ?/)
- (point))))
- ;; not on closing tag
- (let ((point (point)))
- (sgml-skip-tag-backward 1)
- (if (or (not (eq (following-char) ?<))
- (save-excursion
- (forward-list 1)
- (<= (point) point)))
- (error "Not on or before tag")))))
- (if close
- (progn
- (sgml-skip-tag-backward 1)
- (setq open (point))
- (goto-char close)
- (kill-sexp 1))
- (setq open (point))
- (sgml-skip-tag-forward 1)
- (backward-list)
- (forward-char)
- (if (eq (aref (sgml-beginning-of-tag) 0) ?/)
- (kill-sexp 1)))
- (goto-char open)
- (kill-sexp 1)))
- (setq arg (1- arg))))
-
-
-
-(defun sgml-tags-invisible (arg)
- "Toggle visibility of existing tags."
- (interactive "P")
- (let ((modified (buffer-modified-p))
- (inhibit-read-only t)
- (point (point-min))
- symbol)
- (save-excursion
- (goto-char point)
- (if (setq sgml-tags-invisible
- (if arg
- (>= (prefix-numeric-value arg) 0)
- (not sgml-tags-invisible)))
- (while (re-search-forward "<\\([!/?A-Za-z][-A-Za-z0-9]*\\)"
- nil t)
- (setq symbol (intern-soft (downcase (match-string 1))))
- (goto-char (match-beginning 0))
- (and (get symbol 'before-string)
- (not (overlays-at (point)))
- (overlay-put (make-overlay (point)
- (match-beginning 1))
- 'category symbol))
- (put-text-property (setq point (point)) (forward-list)
- 'intangible (point))
- (put-text-property point (point)
- 'category 'sgml-tag))
- (while (< (setq point (next-overlay-change point)) (point-max))
- (delete-overlay (car (overlays-at point))))
- (remove-text-properties (point-min) (point-max)
- '(category sgml-tag intangible t))))
- (set-buffer-modified-p modified)
- (run-hooks 'sgml-tags-invisible-hook)
- (message "")))
-
-(defun sgml-point-entered (x y)
- ;; Show preceding or following hidden tag, depending of cursor direction.
- (let ((inhibit-point-motion-hooks t))
- (save-excursion
- (message "Invisible tag: %s"
- (buffer-substring
- (point)
- (if (or (and (> x y)
- (not (eq (following-char) ?<)))
- (and (< x y)
- (eq (preceding-char) ?>)))
- (backward-list)
- (forward-list)))))))
-
-
-(autoload 'compile-internal "compile")
-
-(defun sgml-validate (command)
- "Validate an SGML document.
-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 line in the SGML document that caused it."
- (interactive
- (list (read-string "Validate command: "
- (or sgml-saved-validate-command
- (concat sgml-validate-command
- " "
- (let ((name (buffer-file-name)))
- (and name
- (file-name-nondirectory name))))))))
- (setq sgml-saved-validate-command command)
- (compile-internal command "No more errors"))
-
-
-(defun sgml-beginning-of-tag (&optional top-level)
- "Skip to beginning of tag and return its name.
-Else `t'."
- (or (if top-level
- (condition-case nil
- (up-list -1)
- (error t))
- (>= (point)
- (if (search-backward "<" nil t)
- (save-excursion
- (forward-list)
- (point))
- 0)))
- (if (looking-at "<[!?/]?[[A-Za-z][A-Za-z0-9]*")
- (buffer-substring-no-properties
- (1+ (point))
- (match-end 0))
- t)))
-
-(defun sgml-value (alist)
- (setq alist (cdr alist))
- (if (stringp (car alist))
- (insert "=\"" (car alist) ?\")
- (if (eq (car alist) t)
- (if (cdr alist)
- (progn
- (insert "=\"")
- (setq alist (skeleton-read '(completing-read
- "[Value]: " (cdr alist))))
- (if (string< "" alist)
- (insert (funcall skeleton-transformation alist) ?\")
- (delete-backward-char 2))))
- (insert "=\"")
- (if alist
- (insert (funcall skeleton-transformation
- (skeleton-read '(completing-read "Value: " alist)))))
- (insert ?\"))))
-
-(provide 'sgml-mode)
-
-(defvar html-quick-keys sgml-quick-keys
- "Use C-c X combinations for quick insertion of frequent tags when non-nil.
-This defaults to `sgml-quick-keys'.
-This takes effect when first loading the library.")
-
-(defvar html-mode-map
- (let ((map (nconc (make-sparse-keymap) sgml-mode-map))
- (menu-map (make-sparse-keymap "HTML")))
- (define-key map "\C-c6" 'html-headline-6)
- (define-key map "\C-c5" 'html-headline-5)
- (define-key map "\C-c4" 'html-headline-4)
- (define-key map "\C-c3" 'html-headline-3)
- (define-key map "\C-c2" 'html-headline-2)
- (define-key map "\C-c1" 'html-headline-1)
- (define-key map "\C-c\r" 'html-paragraph)
- (define-key map "\C-c\n" 'html-line)
- (define-key map "\C-c\C-c-" 'html-horizontal-rule)
- (define-key map "\C-c\C-co" 'html-ordered-list)
- (define-key map "\C-c\C-cu" 'html-unordered-list)
- (define-key map "\C-c\C-cr" 'html-radio-buttons)
- (define-key map "\C-c\C-cc" 'html-checkboxes)
- (define-key map "\C-c\C-cl" 'html-list-item)
- (define-key map "\C-c\C-ch" 'html-href-anchor)
- (define-key map "\C-c\C-cn" 'html-name-anchor)
- (define-key map "\C-c\C-ci" 'html-image)
- (if html-quick-keys
- (progn
- (define-key map "\C-c-" 'html-horizontal-rule)
- (define-key map "\C-co" 'html-ordered-list)
- (define-key map "\C-cu" 'html-unordered-list)
- (define-key map "\C-cr" 'html-radio-buttons)
- (define-key map "\C-cc" 'html-checkboxes)
- (define-key map "\C-cl" 'html-list-item)
- (define-key map "\C-ch" 'html-href-anchor)
- (define-key map "\C-cn" 'html-name-anchor)
- (define-key map "\C-ci" 'html-image)))
- (define-key map "\C-c\C-s" 'html-autoview-mode)
- (define-key map "\C-c\C-v" 'browse-url-of-buffer)
- (define-key map [menu-bar html] (cons "HTML" menu-map))
- (define-key menu-map [html-autoview-mode]
- '("Toggle Autoviewing" . html-autoview-mode))
- (define-key menu-map [browse-url-of-buffer]
- '("View Buffer Contents" . browse-url-of-buffer))
- (define-key menu-map [nil] '("--"))
- ;;(define-key menu-map "6" '("Heading 6" . html-headline-6))
- ;;(define-key menu-map "5" '("Heading 5" . html-headline-5))
- ;;(define-key menu-map "4" '("Heading 4" . html-headline-4))
- (define-key menu-map "3" '("Heading 3" . html-headline-3))
- (define-key menu-map "2" '("Heading 2" . html-headline-2))
- (define-key menu-map "1" '("Heading 1" . html-headline-1))
- (define-key menu-map "l" '("Radio Buttons" . html-radio-buttons))
- (define-key menu-map "c" '("Checkboxes" . html-checkboxes))
- (define-key menu-map "l" '("List Item" . html-list-item))
- (define-key menu-map "u" '("Unordered List" . html-unordered-list))
- (define-key menu-map "o" '("Ordered List" . html-ordered-list))
- (define-key menu-map "-" '("Horizontal Rule" . html-horizontal-rule))
- (define-key menu-map "\n" '("Line Break" . html-line))
- (define-key menu-map "\r" '("Paragraph" . html-paragraph))
- (define-key menu-map "i" '("Image" . html-image))
- (define-key menu-map "h" '("Href Anchor" . html-href-anchor))
- (define-key menu-map "n" '("Name Anchor" . html-name-anchor))
- map)
- "Keymap for commands for use in HTML mode.")
-
-
-(defvar html-face-tag-alist
- '((bold . "b")
- (italic . "i")
- (underline . "u")
- (modeline . "rev"))
- "Value of `sgml-face-tag-alist' for HTML mode.")
-
-(defvar html-tag-face-alist
- '(("b" . bold)
- ("big" . bold)
- ("blink" . highlight)
- ("cite" . italic)
- ("em" . italic)
- ("h1" bold underline)
- ("h2" bold-italic underline)
- ("h3" italic underline)
- ("h4" . underline)
- ("h5" . underline)
- ("h6" . underline)
- ("i" . italic)
- ("rev" . modeline)
- ("s" . underline)
- ("small" . default)
- ("strong" . bold)
- ("title" bold underline)
- ("tt" . default)
- ("u" . underline)
- ("var" . italic))
- "Value of `sgml-tag-face-alist' for HTML mode.")
-
-
-(defvar html-display-text
- '((img . "[/]")
- (hr . "----------")
- (li . "o "))
- "Value of `sgml-display-text' for HTML mode.")
-
-
-; should code exactly HTML 3 here when that is finished
-(defvar html-tag-alist
- (let* ((1-9 '(("8") ("9")
- ("1") ("2") ("3") ("4") ("5") ("6") ("7")))
- (align '(("align" ("left") ("center") ("right"))))
- (valign '(("top") ("middle") ("bottom") ("baseline")))
- (rel '(("next") ("previous") ("parent") ("subdocument") ("made")))
- (href '("href" ("ftp:") ("file:") ("finger:") ("gopher:") ("http:")
- ("mailto:") ("news:") ("rlogin:") ("telnet:") ("tn3270:")
- ("wais:") ("/cgi-bin/")))
- (name '("name"))
- (link `(,href
- ("rel" ,@rel)
- ("rev" ,@rel)
- ("title")))
- (list '((nil \n
- ( "List item: "
- "<li>" str \n))
- ("type" ("A") ("a") ("I") ("i") ("1"))))
- (cell `(t
- ,align
- ("valign" ,@valign)
- ("colspan" ,@1-9)
- ("rowspan" ,@1-9)
- ("nowrap" t))))
- ;; put ,-expressions first, else byte-compile chokes (as of V19.29)
- ;; and like this it's more efficient anyway
- `(("a" ,name ,@link)
- ("base" t ,@href)
- ("dir" ,@list)
- ("font" ("size" ("-1") ("+1") ("-2") ("+2") ,@(cdr (cdr 1-9))))
- ("form" (\n _ \n "<input type=\"submit\" value=\"\">")
- ("action" ,@(cdr href)) ("method" ("get") ("post")))
- ("h1" ,@align)
- ("h2" ,@align)
- ("h3" ,@align)
- ("h4" ,@align)
- ("h5" ,@align)
- ("h6" ,@align)
- ("hr" t ("size" ,@1-9) ("width") ("noshade" t) ,@align)
- ("img" t ("align" ,@valign ("texttop") ("absmiddle") ("absbottom"))
- ("src") ("alt") ("width" "1") ("height" "1")
- ("border" "1") ("vspace" "1") ("hspace" "1") ("ismap" t))
- ("input" t ("size" ,@1-9) ("maxlength" ,@1-9) ("checked" t) ,name
- ("type" ("text") ("password") ("checkbox") ("radio")
- ("submit") ("reset"))
- ("value"))
- ("link" t ,@link)
- ("menu" ,@list)
- ("ol" ,@list)
- ("p" t ,@align)
- ("select" (nil \n
- ("Text: "
- "<option>" str \n))
- ,name ("size" ,@1-9) ("multiple" t))
- ("table" (nil \n
- ((completing-read "Cell kind: " '(("td") ("th"))
- nil t "t")
- "<tr><" str ?> _ \n))
- ("border" t ,@1-9) ("width" "10") ("cellpadding"))
- ("td" ,@cell)
- ("textarea" ,name ("rows" ,@1-9) ("cols" ,@1-9))
- ("th" ,@cell)
- ("ul" ,@list)
-
- ,@sgml-tag-alist
-
- ("abbrev")
- ("acronym")
- ("address")
- ("array" (nil \n
- ("Item: " "<item>" str \n))
- "align")
- ("au")
- ("b")
- ("big")
- ("blink")
- ("blockquote" \n)
- ("body" \n ("background" ".gif") ("bgcolor" "#") ("text" "#")
- ("link" "#") ("alink" "#") ("vlink" "#"))
- ("box" (nil _ "<over>" _))
- ("br" t ("clear" ("left") ("right")))
- ("caption" ("valign" ("top") ("bottom")))
- ("center" \n)
- ("cite")
- ("code" \n)
- ("dd" t)
- ("del")
- ("dfn")
- ("dl" (nil \n
- ( "Term: "
- "<dt>" str "<dd>" _ \n)))
- ("dt" (t _ "<dd>"))
- ("em")
- ("fn" "id" "fn")
- ("head" \n)
- ("html" (\n
- "<head>\n"
- "<title>" (setq str (read-input "Title: ")) "</title>\n"
- "<body>\n<h1>" str "</h1>\n" _
- "\n<address>\n<a href=\"mailto:"
- user-mail-address
- "\">" (user-full-name) "</a>\n</address>"))
- ("i")
- ("ins")
- ("isindex" t ("action") ("prompt"))
- ("kbd")
- ("lang")
- ("li" t)
- ("math" \n)
- ("nobr")
- ("option" t ("value") ("label") ("selected" t))
- ("over" t)
- ("person")
- ("pre" \n)
- ("q")
- ("rev")
- ("s")
- ("samp")
- ("small")
- ("strong")
- ("sub")
- ("sup")
- ("title")
- ("tr" t)
- ("tt")
- ("u")
- ("var")
- ("wbr" t)))
- "*Value of `sgml-tag-alist' for HTML mode.")
-
-(defvar html-tag-help
- `(,@sgml-tag-help
- ("a" . "Anchor of point or link elsewhere")
- ("abbrev" . "?")
- ("acronym" . "?")
- ("address" . "Formatted mail address")
- ("array" . "Math array")
- ("au" . "?")
- ("b" . "Bold face")
- ("base" . "Base address for URLs")
- ("big" . "Font size")
- ("blink" . "Blinking text")
- ("blockquote" . "Indented quotation")
- ("body" . "Document body")
- ("box" . "Math fraction")
- ("br" . "Line break")
- ("caption" . "Table caption")
- ("center" . "Centered text")
- ("changed" . "Change bars")
- ("cite" . "Citation of a document")
- ("code" . "Formatted source code")
- ("dd" . "Definition of term")
- ("del" . "?")
- ("dfn" . "?")
- ("dir" . "Directory list (obsolete)")
- ("dl" . "Definition list")
- ("dt" . "Term to be definined")
- ("em" . "Emphasised")
- ("embed" . "Embedded data in foreign format")
- ("fig" . "Figure")
- ("figa" . "Figure anchor")
- ("figd" . "Figure description")
- ("figt" . "Figure text")
- ("fn" . "?")
- ("font" . "Font size")
- ("form" . "Form with input fields")
- ("group" . "Document grouping")
- ("h1" . "Most important section headline")
- ("h2" . "Important section headline")
- ("h3" . "Section headline")
- ("h4" . "Minor section headline")
- ("h5" . "Unimportant section headline")
- ("h6" . "Least important section headline")
- ("head" . "Document header")
- ("hr" . "Horizontal rule")
- ("html" . "HTML Document")
- ("i" . "Italic face")
- ("img" . "Graphic image")
- ("input" . "Form input field")
- ("ins" . "?")
- ("isindex" . "Input field for index search")
- ("kbd" . "Keybard example face")
- ("lang" . "Natural language")
- ("li" . "List item")
- ("link" . "Link relationship")
- ("math" . "Math formula")
- ("menu" . "Menu list (obsolete)")
- ("mh" . "Form mail header")
- ("nextid" . "Allocate new id")
- ("nobr" . "Text without line break")
- ("ol" . "Ordered list")
- ("option" . "Selection list item")
- ("over" . "Math fraction rule")
- ("p" . "Paragraph start")
- ("panel" . "Floating panel")
- ("person" . "?")
- ("pre" . "Preformatted fixed width text")
- ("q" . "?")
- ("rev" . "Reverse video")
- ("s" . "?")
- ("samp" . "Sample text")
- ("select" . "Selection list")
- ("small" . "Font size")
- ("sp" . "Nobreak space")
- ("strong" . "Standout text")
- ("sub" . "Subscript")
- ("sup" . "Superscript")
- ("table" . "Table with rows and columns")
- ("tb" . "Table vertical break")
- ("td" . "Table data cell")
- ("textarea" . "Form multiline edit area")
- ("th" . "Table header cell")
- ("title" . "Document title")
- ("tr" . "Table row separator")
- ("tt" . "Typewriter face")
- ("u" . "Underlined text")
- ("ul" . "Unordered list")
- ("var" . "Math variable face")
- ("wbr" . "Enable <br> within <nobr>"))
-"*Value of `sgml-tag-help' for HTML mode.")
-
-
-
-;;;###autoload
-(defun html-mode ()
- "Major mode based on SGML mode for editing HTML documents.
-This allows inserting skeleton costructs used in hypertext documents with
-completion. See below for an introduction to HTML. Use
-\\[browse-url-of-buffer] to see how this comes out. See also `sgml-mode' on
-which this is based.
-
-Do \\[describe-variable] html- SPC and \\[describe-variable] sgml- SPC to see available variables.
-
-To write fairly well formatted pages you only need to know few things. Most
-browsers have a function to read the source code of the page being seen, so
-you can imitate various tricks. Here's a very short HTML primer which you
-can also view with a browser to see what happens:
-
-<title>A Title Describing Contents</title> should be on every page. Pages can
-have <h1>Very Major Headlines</h1> through <h6>Very Minor Headlines</h6>
-<hr> Parts can be separated with horizontal rules.
-
-<p>Paragraphs only need an opening tag. Line breaks and multiple spaces are
-ignored unless the text is <pre>preformatted.</pre> Text can be marked as
-<b>bold</b>, <i>italic</i> or <u>underlined</u> using the normal M-g or
-Edit/Text Properties/Face commands.
-
-Pages can have <a name=\"SOMENAME\">named points</a> and can link other points
-to them with <a href=\"#SOMENAME\">see also somename</a>. In the same way <a
-href=\"URL\">see also URL</a> where URL is a filename relative to current
-directory or something like http://www.cs.indiana.edu/elisp/w3/docs.html.
-
-Images in many formats can be inlined with <img src=\"URL\">.
-
-If you mainly create your own documents, `sgml-specials' might be interesting.
-But note that some HTML 2 browsers can't handle &apos;. To work around that
-do:
-
-\(eval-after-load \"sgml-mode\" '(aset sgml-char-names ?' nil))
-\\{html-mode-map}"
- (interactive)
- (sgml-mode-common html-tag-face-alist html-display-text)
- (use-local-map html-mode-map)
- (make-local-variable 'sgml-tag-alist)
- (make-local-variable 'sgml-face-tag-alist)
- (make-local-variable 'sgml-tag-help)
- (make-local-variable 'outline-regexp)
- (make-local-variable 'outline-heading-end-regexp)
- (make-local-variable 'outline-level)
- (setq mode-name "HTML"
- major-mode 'html-mode
- sgml-tag-alist html-tag-alist
- sgml-face-tag-alist html-face-tag-alist
- sgml-tag-help html-tag-help
- outline-regexp "^.*<[Hh][1-6]\\>"
- outline-heading-end-regexp "</[Hh][1-6]>"
- outline-level (lambda ()
- (char-after (1- (match-end 0)))))
- (run-hooks 'html-mode-hook))
-
-
-(define-skeleton html-href-anchor
- "HTML anchor tag with href attribute."
- nil
- "<a href=\"http:" _ "\"></a>")
-
-(define-skeleton html-name-anchor
- "HTML anchor tag with name attribute."
- nil
- "<a name=\"" _ "\"></a>")
-
-(define-skeleton html-headline-1
- "HTML level 1 headline tags."
- nil
- "<h1>" _ "</h1>")
-
-(define-skeleton html-headline-2
- "HTML level 2 headline tags."
- nil
- "<h2>" _ "</h2>")
-
-(define-skeleton html-headline-3
- "HTML level 3 headline tags."
- nil
- "<h3>" _ "</h3>")
-
-(define-skeleton html-headline-4
- "HTML level 4 headline tags."
- nil
- "<h4>" _ "</h4>")
-
-(define-skeleton html-headline-5
- "HTML level 5 headline tags."
- nil
- "<h5>" _ "</h5>")
-
-(define-skeleton html-headline-6
- "HTML level 6 headline tags."
- nil
- "<h6>" _ "</h6>")
-
-(define-skeleton html-horizontal-rule
- "HTML horizontal rule tag."
- nil
- "<hr>" \n)
-
-(define-skeleton html-image
- "HTML image tag."
- nil
- "<img src=\"http:" _ "\">")
-
-(define-skeleton html-line
- "HTML line break tag."
- nil
- "<br>" \n)
-
-(define-skeleton html-ordered-list
- "HTML ordered list tags."
- nil
- ?< "ol>" \n
- "<li>" _ \n
- "</ol>")
-
-(define-skeleton html-unordered-list
- "HTML unordered list tags."
- nil
- ?< "ul>" \n
- "<li>" _ \n
- "</ul>")
-
-(define-skeleton html-list-item
- "HTML list item tag."
- nil
- (if (bolp) nil '\n)
- "<li>")
-
-(define-skeleton html-paragraph
- "HTML paragraph tag."
- nil
- (if (bolp) nil ?\n)
- \n "<p>")
-
-(define-skeleton html-checkboxes
- "Group of connected checkbox inputs."
- nil
- '(setq v1 (eval str)) ; allow passing name as argument
- ("Value & Text: "
- "<input type=\"checkbox\" name=\""
- (or v1 (setq v1 (skeleton-read "Name: ")))
- "\" value=\"" str ?\"
- (if v2 "" " checked") ?> str
- (or v2 (setq v2 (if (y-or-n-p "Newline? ") "<br>" ""))) \n))
-
-(define-skeleton html-radio-buttons
- "Group of connected radio button inputs."
- nil
- '(setq v1 (eval str)) ; allow passing name as argument
- ("Value & Text: "
- "<input type=\"radio\" name=\""
- (or v1 (setq v1 (skeleton-read "Name: ")))
- "\" value=\"" str ?\"
- (if v2 "" " checked") ?> str
- (or v2 (setq v2 (if (y-or-n-p "Newline? ") "<br>" ""))) \n))
-
-
-(defun html-autoview-mode (&optional arg)
- "Toggle automatic viewing via `html-viewer' upon saving buffer.
-With positive prefix ARG always turns viewing on, with negative ARG always off.
-Can be used as a value for `html-mode-hook'."
- (interactive "P")
- (if (setq arg (if arg
- (< (prefix-numeric-value arg) 0)
- (and (boundp 'after-save-hook)
- (memq 'browse-url-of-buffer after-save-hook))))
- (setq after-save-hook (delq 'browse-url-of-buffer after-save-hook))
- (make-local-hook 'after-save-hook)
- (add-hook 'after-save-hook 'browse-url-of-buffer nil t))
- (message "Autoviewing turned %s."
- (if arg "off" "on")))
-
-;;; sgml-mode.el ends here
diff --git a/lisp/textmodes/spell.el b/lisp/textmodes/spell.el
deleted file mode 100644
index 65dde5383c7..00000000000
--- a/lisp/textmodes/spell.el
+++ /dev/null
@@ -1,154 +0,0 @@
-;;; spell.el --- spelling correction interface for Emacs.
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: wp, unix
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This mode provides an Emacs interface to the UNIX spell(1) program.
-;; Entry points are `spell-buffer', `spell-word', `spell-region' and
-;; `spell-string'. These facilities are documented in the Emacs user's
-;; manual.
-
-;;; Code:
-
-(defvar spell-command "spell"
- "*Command to run the spell program.")
-
-(defvar spell-filter nil
- "*Filter function to process text before passing it to spell program.
-This function might remove text-processor commands.
-nil means don't alter the text before checking it.")
-
-;;;###autoload
-(put 'spell-filter 'risky-local-variable t)
-
-;;;###autoload
-(defun spell-buffer ()
- "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."
- (interactive)
- (spell-region (point-min) (point-max) "buffer"))
-
-;;;###autoload
-(defun spell-word ()
- "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."
- (interactive)
- (let (beg end spell-filter)
- (save-excursion
- (if (not (looking-at "\\<"))
- (forward-word -1))
- (setq beg (point))
- (forward-word 1)
- (setq end (point)))
- (spell-region beg end (buffer-substring beg end))))
-
-;;;###autoload
-(defun spell-region (start end &optional description)
- "Like `spell-buffer' but applies only to region.
-Used in a program, applies from START to END.
-DESCRIPTION is an optional string naming the unit being checked:
-for example, \"word\"."
- (interactive "r")
- (let ((filter spell-filter)
- (buf (get-buffer-create " *temp*")))
- (save-excursion
- (set-buffer buf)
- (widen)
- (erase-buffer))
- (message "Checking spelling of %s..." (or description "region"))
- (if (and (null filter) (= ?\n (char-after (1- end))))
- (if (string= "spell" spell-command)
- (call-process-region start end "spell" nil buf)
- (call-process-region start end shell-file-name
- nil buf nil "-c" spell-command))
- (let ((oldbuf (current-buffer)))
- (save-excursion
- (set-buffer buf)
- (insert-buffer-substring oldbuf start end)
- (or (bolp) (insert ?\n))
- (if filter (funcall filter))
- (if (string= "spell" spell-command)
- (call-process-region (point-min) (point-max) "spell" t buf)
- (call-process-region (point-min) (point-max) shell-file-name
- t buf nil "-c" spell-command)))))
- (message "Checking spelling of %s...%s"
- (or description "region")
- (if (save-excursion
- (set-buffer buf)
- (> (buffer-size) 0))
- "not correct"
- "correct"))
- (let (word newword
- (case-fold-search t)
- (case-replace t))
- (while (save-excursion
- (set-buffer buf)
- (> (buffer-size) 0))
- (save-excursion
- (set-buffer buf)
- (goto-char (point-min))
- (setq word (downcase
- (buffer-substring (point)
- (progn (end-of-line) (point)))))
- (forward-char 1)
- (delete-region (point-min) (point))
- (setq newword
- (read-input (concat "`" word
- "' not recognized; edit a replacement: ")
- word))
- (flush-lines (concat "^" (regexp-quote word) "$")))
- (if (not (equal word newword))
- (progn
- (goto-char (point-min))
- (query-replace-regexp (concat "\\b" (regexp-quote word) "\\b")
- newword)))))))
-
-
-;;;###autoload
-(defun spell-string (string)
- "Check spelling of string supplied as argument."
- (interactive "sSpell string: ")
- (let ((buf (get-buffer-create " *temp*")))
- (save-excursion
- (set-buffer buf)
- (widen)
- (erase-buffer)
- (insert string "\n")
- (if (string= "spell" spell-command)
- (call-process-region (point-min) (point-max) "spell"
- t t)
- (call-process-region (point-min) (point-max) shell-file-name
- t t nil "-c" spell-command))
- (if (= 0 (buffer-size))
- (message "%s is correct" string)
- (goto-char (point-min))
- (while (search-forward "\n" nil t)
- (replace-match " "))
- (message "%sincorrect" (buffer-substring 1 (point-max)))))))
-
-;;; spell.el ends here
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
deleted file mode 100644
index f12047153e4..00000000000
--- a/lisp/textmodes/tex-mode.el
+++ /dev/null
@@ -1,1239 +0,0 @@
-;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands.
-
-;; Copyright (C) 1985, 86, 89, 92, 94, 95, 96 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: tex
-
-;; Contributions over the years by William F. Schelter, Dick King,
-;; Stephen Gildea, Michael Prange, Jacob Gore, and Edward M. Reingold.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(require 'shell)
-(require 'compile)
-
-;;;###autoload
-(defvar tex-shell-file-name nil
- "*If non-nil, the shell file name to run in the subshell used to run TeX.")
-
-;;;###autoload
-(defvar tex-directory "."
- "*Directory in which temporary files are written.
-You can make this `/tmp' if your TEXINPUTS has no relative directories in it
-and you don't try to apply \\[tex-region] or \\[tex-buffer] when there are
-`\\input' commands with relative directories.")
-
-;;;###autoload
-(defvar tex-first-line-header-regexp nil
- "Regexp for matching a first line which `tex-region' should include.
-If this is non-nil, it should be a regular expression string;
-if it matches the first line of the file,
-`tex-region' always includes the first line in the TeX run.")
-
-;;;###autoload
-(defvar tex-main-file nil
- "*The main TeX source file which includes this buffer's file.
-The command `tex-buffer' runs TeX on `tex-main-file'if that is non-nil.")
-
-;;;###autoload
-(defvar tex-offer-save t
- "*If non-nil, ask about saving modified buffers before \\[tex-file] is run.")
-
-;;;###autoload
-(defvar tex-run-command "tex"
- "*Command used to run TeX subjob.
-If this string contains an asterisk (`*'), that is replaced by the file name;
-otherwise, the file name, preceded by blank, is added at the end.")
-
-;;;###autoload
-(defvar latex-run-command "latex"
- "*Command used to run LaTeX subjob.
-If this string contains an asterisk (`*'), that is replaced by the file name;
-otherwise, the file name, preceded by blank, is added at the end.")
-
-(defvar standard-latex-block-names
- '("abstract" "array" "center" "description"
- "displaymath" "document" "enumerate" "eqnarray"
- "eqnarray*" "equation" "figure" "figure*"
- "flushleft" "flushright" "itemize" "letter"
- "list" "minipage" "picture" "quotation"
- "quote" "slide" "sloppypar" "tabbing"
- "table" "table*" "tabular" "tabular*"
- "thebibliography" "theindex*" "titlepage" "trivlist"
- "verbatim" "verbatim*" "verse")
- "Standard LaTeX block names.")
-
-;;;###autoload
-(defvar latex-block-names nil
- "*User defined LaTeX block names.
-Combined with `standard-latex-block-names' for minibuffer completion.")
-
-;;;###autoload
-(defvar slitex-run-command "slitex"
- "*Command used to run SliTeX subjob.
-If this string contains an asterisk (`*'), that is replaced by the file name;
-otherwise, the file name, preceded by blank, is added at the end.")
-
-;;;###autoload
-(defvar tex-bibtex-command "bibtex"
- "*Command used by `tex-bibtex-file' to gather bibliographic data.
-If this string contains an asterisk (`*'), that is replaced by the file name;
-otherwise, the file name, preceded by blank, is added at the end.")
-
-;;;###autoload
-(defvar tex-dvi-print-command "lpr -d"
- "*Command used by \\[tex-print] to print a .dvi file.
-If this string contains an asterisk (`*'), that is replaced by the file name;
-otherwise, the file name, preceded by blank, is added at the end.")
-
-;;;###autoload
-(defvar tex-alt-dvi-print-command "lpr -d"
- "*Command used by \\[tex-print] with a prefix arg to print a .dvi file.
-If this string contains an asterisk (`*'), that is replaced by the file name;
-otherwise, the file name, preceded by blank, is added at the end.
-
-If two printers are not enough of a choice, you can set the variable
-`tex-alt-dvi-print-command' to an expression that asks what you want;
-for example,
-
- (setq tex-alt-dvi-print-command
- '(format \"lpr -P%s\" (read-string \"Use printer: \")))
-
-would tell \\[tex-print] with a prefix argument to ask you which printer to
-use.")
-
-;;;###autoload
-(defvar tex-dvi-view-command nil
- "*Command used by \\[tex-view] to display a `.dvi' file.
-If this string contains an asterisk (`*'), that is replaced by the file name;
-otherwise, the file name, preceded by blank, is added at the end.
-
-This can be set conditionally so that the previewer used is suitable for the
-window system being used. For example,
-
- (setq tex-dvi-view-command
- (if (eq window-system 'x) \"xdvi\" \"dvi2tty * | cat -s\"))
-
-would tell \\[tex-view] to use xdvi under X windows and to use dvi2tty
-otherwise.")
-
-;;;###autoload
-(defvar tex-show-queue-command "lpq"
- "*Command used by \\[tex-show-print-queue] to show the print queue.
-Should show the queue(s) that \\[tex-print] puts jobs on.")
-
-;;;###autoload
-(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'.")
-
-;;;###autoload
-(defvar tex-open-quote "``"
- "*String inserted by typing \\[tex-insert-quote] to open a quotation.")
-
-;;;###autoload
-(defvar tex-close-quote "''"
- "*String inserted by typing \\[tex-insert-quote] to close a quotation.")
-
-(defvar tex-last-temp-file nil
- "Latest temporary file generated by \\[tex-region] and \\[tex-buffer].
-Deleted when the \\[tex-region] or \\[tex-buffer] is next run, or when the
-tex shell terminates.")
-
-(defvar tex-command nil
- "Command to run TeX.
-The name of the file, preceded by a blank, will be added to this string.")
-
-(defvar tex-trailer nil
- "String appended after the end of a region sent to TeX by \\[tex-region].")
-
-(defvar tex-start-of-header nil
- "Regular expression used by \\[tex-region] to find start of file's header.")
-
-(defvar tex-end-of-header nil
- "Regular expression used by \\[tex-region] to find end of file's header.")
-
-(defvar tex-shell-cd-command "cd"
- "Command to give to shell running TeX to change directory.
-The value of `tex-directory' is 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 latex-imenu-create-index ()
- "Generates an alist for imenu from a LaTeX buffer."
- (let (result temp)
- (goto-char (point-max))
- (while (re-search-backward "\\\\\\(part\\|chapter\\|\
-\\(sub\\)?\\(\\(sub\\)?section\\|paragraph\\)\\)\\*?[ \t\n]*{\\([^}]*\\)}" nil t)
- (setq temp
- (assoc (buffer-substring-no-properties (match-beginning 1)
- (match-end 1))
- '(("part" . "") ("chapter" . " ")
- ("section" . " ") ("subsection" . " ")
- ("subsubsection" . " ")
- ("paragraph" . " ") ("subparagraph" . " "))))
- (setq result (cons (cons (concat (cdr temp) (match-string 5))
- (match-beginning 0))
- result)))
- result))
-
-(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)
-
- (define-key keymap [menu-bar tex] (cons "TeX" (make-sparse-keymap "TeX")))
-
- (define-key keymap [menu-bar tex tex-kill-job] '("Tex Kill" . tex-kill-job))
- (define-key keymap [menu-bar tex tex-recenter-output-buffer]
- '("Tex Recenter" . tex-recenter-output-buffer))
- (define-key keymap [menu-bar tex tex-show-print-queue]
- '("Show Print Queue" . tex-show-print-queue))
- (define-key keymap [menu-bar tex tex-alt-print]
- '("Tex Print (alt printer)" . tex-alt-print))
- (define-key keymap [menu-bar tex tex-print] '("Tex Print" . tex-print))
- (define-key keymap [menu-bar tex tex-view] '("Tex View" . 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)
- (define-key tex-mode-map "\C-c\C-u" 'tex-goto-last-unclosed-latex-block)
- (define-key tex-mode-map [menu-bar tex tex-bibtex-file]
- '("BibTeX File" . tex-bibtex-file))
- (define-key tex-mode-map [menu-bar tex tex-validate-region]
- '("Validate Region" . tex-validate-region))
- (define-key tex-mode-map [menu-bar tex validate-tex-buffer]
- '("Validate Buffer" . validate-tex-buffer))
- (define-key tex-mode-map [menu-bar tex tex-region]
- '("TeX Region" . tex-region))
- (define-key tex-mode-map [menu-bar tex tex-buffer]
- '("TeX Buffer" . tex-buffer))
- (define-key tex-mode-map [menu-bar tex tex-file] '("TeX File" . tex-file)))
-
-(put 'tex-region 'menu-enable 'mark-active)
-(put 'tex-validate-region 'menu-enable 'mark-active)
-(put 'tex-print 'menu-enable '(stringp tex-print-file))
-(put 'tex-alt-print 'menu-enable '(stringp tex-print-file))
-(put 'tex-view 'menu-enable '(stringp tex-print-file))
-(put 'tex-recenter-output-buffer 'menu-enable '(get-buffer "*tex-shell*"))
-(put 'tex-kill-job 'menu-enable '(tex-shell-running))
-
-
-(defvar tex-shell-map nil
- "Keymap for the TeX shell.
-Inherits `shell-mode-map' with a few additions.")
-
-(defvar tex-face-alist
- '((bold . "{\\bf ")
- (italic . "{\\it ")
- (bold-italic . "{\\bi ") ; hypothetical
- (underline . "\\underline{")
- (default . "{\\rm "))
- "Alist of face and TeX font name for facemenu.")
-
-(defvar tex-latex-face-alist
- `((italic . "{\\em ")
- ,@tex-face-alist)
- "Alist of face and LaTeX font name for facemenu.")
-
-
-(defvar compare-windows-whitespace) ; Pacify the byte-compiler
-
-;;; This would be a lot simpler if we just used a regexp search,
-;;; but then it would be too slow.
-;;;###autoload
-(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'
-says which mode to use."
- (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\\|documentclass\\|begin\\b\\|NeedsTeXFormat{LaTeX")
- (if (looking-at
- "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}")
- 'slitex-mode
- 'latex-mode)
- 'plain-tex-mode))))
- (if mode (funcall mode)
- (funcall tex-default-mode))))
-
-;;;###autoload
-(defalias 'TeX-mode 'tex-mode)
-;;;###autoload
-(defalias 'LaTeX-mode 'latex-mode)
-
-;;;###autoload
-(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-alt-dvi-print-command
- Alternative command string used by \\[tex-print] (when given a prefix
- argument) 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 runs the hook `text-mode-hook', then the hook
-`tex-mode-hook', and finally the hook `plain-tex-mode-hook'. When the
-special subshell is initiated, the hook `tex-shell-hook' is run."
-
- (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))
-;;;###autoload
-(defalias 'plain-TeX-mode 'plain-tex-mode)
-
-;;;###autoload
-(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-alt-dvi-print-command
- Alternative command string used by \\[tex-print] (when given a prefix
- argument) 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 runs the hook `text-mode-hook', then
-`tex-mode-hook', and finally `latex-mode-hook'. When the special
-subshell is initiated, `tex-shell-hook' is run."
- (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\\|\\\\documentclass")
- (setq tex-end-of-header "\\\\begin{document}")
- (setq tex-trailer "\\end{document}\n")
- ;; A line containing just $$ is treated as a paragraph separator.
- ;; A line starting with $$ starts a paragraph,
- ;; but does not separate paragraphs if it has more stuff on it.
- (setq paragraph-start "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$\\|\
-\\\\begin\\>\\|\\\\label\\>\\|\\\\end\\>\\|\\\\\\[\\|\\\\\\]\\|\
-\\\\chapter\\>\\|\\\\section\\>\\|\
-\\\\subsection\\>\\|\\\\subsubsection\\>\\|\
-\\\\paragraph\\>\\|\\\\subparagraph\\>\\|\
-\\\\item\\>\\|\\\\bibitem\\>\\|\\\\newline\\>\\|\\\\noindent\\>\\|\
-\\\\[a-z]*space\\>\\|\\\\[a-z]*skip\\>\\|\
-\\\\newpage\\>\\|\\\\[a-z]*page\\|\\\\footnote\\>\\|\
-\\\\marginpar\\>\\|\\\\parbox\\>\\|\\\\caption\\>")
- (setq paragraph-separate "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$[ \t]*$\\|\
-\\\\begin\\>\\|\\\\label\\>\\|\\\\end\\>\\|\\\\\\[\\|\\\\\\]\\|\
-\\\\chapter\\>\\|\\\\section\\>\\|\
-\\\\subsection\\>\\|\\\\subsubsection\\>\\|\
-\\\\paragraph\\>\\|\\\\subparagraph\\>\\|\
-\\(\\\\item\\|\\\\bibitem\\|\\\\newline\\|\\\\noindent\\|\
-\\\\[a-z]*space\\|\\\\[a-z]*skip\\|\
-\\\\newpage\\|\\\\[a-z]*page[a-z]*\\|\\\\footnote\\|\
-\\\\marginpar\\|\\\\parbox\\|\\\\caption\\)[ \t]*\\($\\|%\\)")
- (make-local-variable 'imenu-create-index-function)
- (setq imenu-create-index-function 'latex-imenu-create-index)
- (make-local-variable 'tex-face-alist)
- (setq tex-face-alist tex-latex-face-alist)
- (run-hooks 'text-mode-hook 'tex-mode-hook 'latex-mode-hook))
-
-;;;###autoload
-(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-alt-dvi-print-command
- Alternative command string used by \\[tex-print] (when given a prefix
- argument) 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 runs the hook `text-mode-hook', then the hook
-`tex-mode-hook', then the hook `latex-mode-hook', and finally the hook
-`slitex-mode-hook'. When the special subshell is initiated, the hook
-`tex-shell-hook' is run."
- (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}\\|\\\\documentclass{slides}")
- (setq tex-end-of-header "\\\\begin{document}")
- (setq tex-trailer "\\end{document}\n")
- ;; A line containing just $$ is treated as a paragraph separator.
- ;; A line starting with $$ starts a paragraph,
- ;; but does not separate paragraphs if it has more stuff on it.
- (setq paragraph-start "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$\\|\
-\\\\begin\\>\\|\\\\label\\>\\|\\\\end\\>\\|\\\\\\[\\|\\\\\\]\\|\
-\\\\chapter\\>\\|\\\\section\\>\\|\
-\\\\subsection\\>\\|\\\\subsubsection\\>\\|\
-\\\\paragraph\\>\\|\\\\subparagraph\\>\\|\
-\\\\item\\>\\|\\\\bibitem\\>\\|\\\\newline\\>\\|\\\\noindent\\>\\|\
-\\\\[a-z]*space\\>\\|\\\\[a-z]*skip\\>\\|\
-\\\\newpage\\>\\|\\\\[a-z]*page\\|\\\\footnote\\>\\|\
-\\\\marginpar\\>\\|\\\\parbox\\>\\|\\\\caption\\>")
- (setq paragraph-separate "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$[ \t]*$\\|\
-\\\\begin\\>\\|\\\\label\\>\\|\\\\end\\>\\|\\\\\\[\\|\\\\\\]\\|\
-\\\\chapter\\>\\|\\\\section\\>\\|\
-\\\\subsection\\>\\|\\\\subsubsection\\>\\|\
-\\\\paragraph\\>\\|\\\\subparagraph\\>\\|\
-\\\\item[ \t]*$\\|\\\\bibitem[ \t]*$\\|\\\\newline[ \t]*$\\|\\\\noindent[ \t]*$\\|\
-\\\\[a-z]*space[ \t]*$\\|\\\\[a-z]*skip[ \t]*$\\|\
-\\\\newpage[ \t]*$\\|\\\\[a-z]*page[a-z]*[ \t]*$\\|\\\\footnote[ \t]*$\\|\
-\\\\marginpar[ \t]*$\\|\\\\parbox[ \t]*$\\|\\\\caption[ \t]*$")
- (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)
- ;; A line containing just $$ is treated as a paragraph separator.
- (setq paragraph-start "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$")
- (make-local-variable 'paragraph-separate)
- ;; A line starting with $$ starts a paragraph,
- ;; but does not separate paragraphs if it has more stuff on it.
- (setq paragraph-separate "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$[ \t]*$")
- (make-local-variable 'comment-start)
- (setq comment-start "%")
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip "\\(\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)")
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'tex-comment-indent)
- (make-local-variable 'parse-sexp-ignore-comments)
- (setq parse-sexp-ignore-comments t)
- (make-local-variable 'compare-windows-whitespace)
- (setq compare-windows-whitespace 'tex-categorize-whitespace)
- (make-local-variable 'skeleton-further-elements)
- (setq skeleton-further-elements
- '((indent-line-function 'indent-relative-maybe)))
- (make-local-variable 'facemenu-add-face-function)
- (make-local-variable 'facemenu-end-add-face)
- (make-local-variable 'facemenu-remove-face-function)
- (setq facemenu-add-face-function
- (lambda (face end)
- (let ((face-text (cdr (assq face tex-face-alist))))
- (if face-text
- face-text
- (error "Face %s not configured for %s mode" face mode-name))))
- facemenu-end-add-face "}"
- facemenu-remove-face-function t)
- (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.
-Their positions are recorded in the buffer `*Occur*'.
-To find a particular invalidity from `*Occur*',
-switch to to that buffer and type C-c C-c on the line
-for the invalidity you want to see."
- (interactive)
- (let ((buffer (current-buffer))
- (prevpos (point-min))
- (linenum nil))
- (with-output-to-temp-buffer "*Occur*"
- (princ "Mismatches:\n")
- (save-excursion
- (set-buffer standard-output)
- (occur-mode)
- (setq occur-buffer buffer)
- (setq occur-nlines 0)
- (setq occur-pos-list nil))
- (save-excursion
- (goto-char (point-max))
- (while (and (not (input-pending-p)) (not (bobp)))
- (let ((end (point))
- prev-end)
- ;; Scan the previous paragraph for invalidities.
- (if (search-backward "\n\n" nil t)
- (progn
- (setq prev-end (point))
- (forward-char 2))
- (goto-char (setq prev-end (point-min))))
- (or (tex-validate-region (point) end)
- (let* ((oend end)
- (end (save-excursion (forward-line 1) (point)))
- start tem)
- (beginning-of-line)
- (setq start (point))
- ;; Keep track of line number as we scan,
- ;; in a cumulative fashion.
- (if linenum
- (setq linenum (- linenum (count-lines prevpos (point))))
- (setq linenum (1+ (count-lines 1 start))))
- (setq prevpos (point))
- ;; Mention this mismatch in *Occur*.
- ;; Since we scan from end of buffer to beginning,
- ;; add each mismatch at the beginning of *Occur*
- ;; and at the beginning of occur-pos-list.
- (save-excursion
- (setq tem (point-marker))
- (set-buffer standard-output)
- (goto-char (point-min))
- ;; Skip "Mismatches:" header line.
- (forward-line 1)
- (setq occur-pos-list (cons tem occur-pos-list))
- (insert-buffer-substring buffer start end)
- (forward-char (- start end))
- (insert (format "%3d: " linenum)))))
- (goto-char prev-end))))
- (save-excursion
- (set-buffer standard-output)
- (if (null occur-pos-list)
- (insert "None!\n"))
- (if (interactive-p)
- (message "%d mismatches found" (length occur-pos-list)))))))
-
-(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
- (skip-syntax-forward " .>")
- (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 or $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.
-(define-skeleton tex-latex-block
- "Create a matching pair of lines \\begin[OPT]{NAME} and \\end{NAME} at point.
-Puts point on a blank line between them."
- (completing-read "LaTeX block name: "
- (mapcar 'list
- (append standard-latex-block-names
- latex-block-names)))
- "\\begin["
- (skeleton-read "[options]: ") & ?\] | -1
- ?\{
- str
- ?\} \n
- _ \n
- "\\end{" str ?\})
-
-(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-goto-last-unclosed-latex-block ()
- "Move point to the last unclosed \\begin{...}.
-Mark is left at original location."
- (interactive)
- (let ((spot))
- (save-excursion
- (condition-case nil
- (tex-last-unended-begin)
- (error (error "Couldn't find unended \\begin")))
- (setq spot (point)))
- (push-mark)
- (goto-char spot)))
-
-(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 nil
- (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))))
-
-(defun tex-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.
-
-This function works on TeX compilations only. It is necessary for
-that purpose, since TeX does not put file names on the same line as
-line numbers for the errors."
- (setq compilation-error-list nil)
- (message "Parsing error messages...")
- (modify-syntax-entry ?\{ "_")
- (modify-syntax-entry ?\} "_")
- (modify-syntax-entry ?\[ "_")
- (modify-syntax-entry ?\] "_")
- (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 "^l\.[0-9]+ " nil t)
- (let (linenum filename
- error-marker text-marker)
- ;; Extract file name and line number from error message.
- ;; Line number is 2 away from beginning of line: "l.23"
- (beginning-of-line)
- (goto-char (+ (point) 2))
- (setq linenum (read (current-buffer)))
- ;; The file is the one that was opened last and is still open.
- ;; We need to find the last open parenthesis.
- (insert ?\))
- (backward-sexp)
- (forward-char)
- (setq filename (current-word))
- ;; Locate the erring file and line.
- (if (and (equal filename last-filename)
- (= linenum last-linenum))
- nil
- (skip-chars-backward "^(")
- (backward-char)
- (forward-sexp)
- (backward-delete-char 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)))
- (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)))
-
-;;; 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:
-
-;;;###autoload
-(defun tex-start-shell ()
- (save-excursion
- (set-buffer
- (make-comint
- "tex-shell"
- (or tex-shell-file-name (getenv "ESHELL") (getenv "SHELL") "/bin/sh")
- nil))
- (let ((proc (get-process "tex-shell")))
- (set-process-sentinel proc 'tex-shell-sentinel)
- (process-kill-without-query proc)
- (setq comint-prompt-regexp shell-prompt-pattern)
- (setq tex-shell-map (nconc (make-sparse-keymap) shell-mode-map))
- (tex-define-common-keys tex-shell-map)
- (use-local-map tex-shell-map)
- (run-hooks 'tex-shell-hook)
- (while (zerop (buffer-size))
- (sleep-for 1)))))
-
-(defun tex-display-shell ()
- "Make the TeX shell buffer visible in a window."
- (display-buffer (process-buffer (get-process "tex-shell")))
- (tex-recenter-output-buffer nil))
-
-(defun tex-shell-sentinel (proc msg)
- (cond ((null (buffer-name (process-buffer proc)))
- ;; buffer killed
- (set-process-buffer proc nil)
- (tex-delete-last-temp-files))
- ((memq (process-status proc) '(signal exit))
- (tex-delete-last-temp-files))))
-
-(defun tex-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))))
-
-(defvar tex-send-command-modified-tick 0)
-(make-variable-buffer-local 'tex-send-command-modified-tick)
-
-(defun tex-send-command (command &optional file background)
- "Send COMMAND to TeX shell process, substituting optional FILE for *.
-Do this in background if optional BACKGROUND is t. If COMMAND has no *,
-FILE will be appended, preceded by a blank, to COMMAND. If FILE is nil, no
-substitution will be made in COMMAND. COMMAND can be any expression that
-evaluates to a command string."
- (save-excursion
- (let* ((cmd (eval command))
- (proc (or (get-process "tex-shell") (error "No TeX subprocess")))
- (buf (process-buffer proc))
- (star (string-match "\\*" cmd))
- (string
- (concat
- (if file
- (if star (concat (substring cmd 0 star)
- file (substring cmd (1+ star)))
- (concat cmd " " file))
- cmd)
- (if background "&" ""))))
- ;; Switch to buffer before checking for subproc output in it.
- (set-buffer buf)
- ;; If text is unchanged since previous tex-send-command,
- ;; we haven't got any output. So wait for output now.
- (if (= (buffer-modified-tick buf) tex-send-command-modified-tick)
- (accept-process-output proc))
- (goto-char (process-mark proc))
- (insert string)
- (comint-send-input)
- (setq tex-send-command-modified-tick (buffer-modified-tick buf)))))
-
-(defun tex-delete-last-temp-files (&optional not-all)
- "Delete any junk files from last temp file.
-If NOT-ALL is non-nil, save the `.dvi' file."
- (if tex-last-temp-file
- (let* ((dir (file-name-directory tex-last-temp-file))
- (list (and (file-directory-p dir)
- (file-name-all-completions
- (file-name-nondirectory tex-last-temp-file) dir))))
- (while list
- (if not-all
- (and
- ;; If arg is non-nil, don't delete the .dvi file.
- (not (string-match "\\.dvi$" (car list)))
- (delete-file (concat dir (car list))))
- (delete-file (concat dir (car list))))
- (setq list (cdr list))))))
-
-(add-hook 'kill-emacs-hook 'tex-delete-last-temp-files)
-
-;;; The commands:
-
-(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)))
- ;; Temp file will be written and TeX will be run in zap-directory.
- ;; If the TEXINPUTS file has relative directories or if the region has
- ;; \input of files, this must be the same directory as the file for
- ;; TeX to access the correct inputs. That's why it's safest if
- ;; tex-directory is ".".
- (let* ((zap-directory
- (file-name-as-directory (expand-file-name tex-directory)))
- (tex-out-file (concat zap-directory tex-zap-file ".tex")))
- ;; Don't delete temp files if we do the same buffer twice in a row.
- (or (eq (current-buffer) tex-last-buffer-texed)
- (tex-delete-last-temp-files t))
- ;; Write the new temp file.
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (forward-line 100)
- (let ((search-end (point))
- (default-directory zap-directory)
- (already-output 0))
- (goto-char (point-min))
-
- ;; Maybe copy first line, such as `\input texinfo', to temp file.
- (and tex-first-line-header-regexp
- (looking-at tex-first-line-header-regexp)
- (write-region (point)
- (progn (forward-line 1)
- (setq already-output (point)))
- tex-out-file nil nil))
-
- ;; Write out the header, if there is one,
- ;; and any of the specified region which extends before it.
- ;; But don't repeat anything already written.
- (if (re-search-forward tex-start-of-header search-end t)
- (let (hbeg)
- (beginning-of-line)
- (setq hbeg (point)) ;mark beginning of header
- (if (re-search-forward tex-end-of-header nil t)
- (let (hend)
- (forward-line 1)
- (setq hend (point)) ;mark end of header
- (write-region (max (min hbeg beg) already-output)
- hend
- tex-out-file
- (not (zerop already-output)) nil)
- (setq already-output hend)))))
-
- ;; Write out the specified region
- ;; (but don't repeat anything already written).
- (write-region (max beg already-output) end
- tex-out-file
- (not (zerop already-output)) nil))
- ;; Write the trailer, if any.
- ;; Precede it with a newline to make sure it
- ;; is not hidden in a comment.
- (if tex-trailer
- (write-region (concat "\n" tex-trailer) nil
- tex-out-file t nil))))
- ;; Record the file name to be deleted afterward.
- (setq tex-last-temp-file tex-out-file)
- (tex-send-command tex-shell-cd-command zap-directory)
- (tex-send-command tex-command tex-out-file)
- (tex-display-shell)
- (setq tex-print-file tex-out-file)
- (setq tex-last-buffer-texed (current-buffer))))
-
-(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 ((source-file
- (or tex-main-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))))
- (if tex-offer-save
- (save-some-buffers))
- (if (tex-shell-running)
- (tex-kill-job)
- (tex-start-shell))
- (tex-send-command tex-shell-cd-command file-dir)
- (tex-send-command tex-command source-file)
- (tex-display-shell)
- (setq tex-last-buffer-texed (current-buffer))
- (setq tex-print-file source-file)))
-
-(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)
- (quit-process (get-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))
- (window))
- (if (null tex-shell)
- (message "No TeX output buffer")
- (setq window (display-buffer tex-shell))
- (save-selected-window
- (select-window window)
- (bury-buffer tex-shell)
- (goto-char (point-max))
- (recenter (if linenum
- (prefix-numeric-value linenum)
- (/ (window-height) 2)))))))
-
-(defun tex-print (&optional alt)
- "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file].
-Runs the shell command defined by `tex-dvi-print-command'. If prefix argument
-is provided, use the alternative command, `tex-alt-dvi-print-command'."
- (interactive "P")
- (let ((print-file-name-dvi (tex-append tex-print-file ".dvi"))
- test-name)
- (if (and (not (equal (current-buffer) tex-last-buffer-texed))
- (buffer-file-name)
- ;; Check that this buffer's printed file is up to date.
- (file-newer-than-file-p
- (setq test-name (tex-append (buffer-file-name) ".dvi"))
- (buffer-file-name)))
- (setq print-file-name-dvi test-name))
- (if (not (file-exists-p print-file-name-dvi))
- (error "No appropriate `.dvi' file could be found")
- (tex-send-command
- (if alt tex-alt-dvi-print-command tex-dvi-print-command)
- print-file-name-dvi t))))
-
-(defun tex-alt-print ()
- "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file].
-Runs the shell command defined by `tex-alt-dvi-print-command'."
- (interactive)
- (tex-print t))
-
-(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.
-You must set that variable yourself before using this command,
-because there is no standard value that would generally work."
- (interactive)
- (or tex-dvi-view-command
- (error "You must set `tex-dvi-view-command'"))
- (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.
-Pascal-based TeX scans for the first period, C TeX uses the last.
-No period is retained immediately before SUFFIX,
-so normally SUFFIX starts with one."
- (if (stringp file-name)
- (let ((file (file-name-nondirectory file-name))
- trial-name)
- ;; Try splitting on last period.
- ;; The first-period split can get fooled when two files
- ;; named a.tex and a.b.tex are both tex'd;
- ;; the last-period split must be right if it matches at all.
- (setq trial-name
- (concat (file-name-directory file-name)
- (substring file 0
- (string-match "\\.[^.]*$" file))
- suffix))
- (if (or (file-exists-p trial-name)
- (file-exists-p (concat trial-name ".aux"))) ;for BibTeX files
- trial-name
- ;; Not found, so split on first period.
- (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))
- (tex-send-command tex-show-queue-command)
- (tex-display-shell))
-
-(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))))
- (tex-send-command tex-shell-cd-command file-dir)
- (tex-send-command tex-bibtex-command tex-out-file))
- (tex-display-shell))
-
-(run-hooks 'tex-mode-load-hook)
-
-(provide 'tex-mode)
-
-;;; tex-mode.el ends here
-
diff --git a/lisp/textmodes/texinfmt.el b/lisp/textmodes/texinfmt.el
deleted file mode 100644
index 7e6dcd57c25..00000000000
--- a/lisp/textmodes/texinfmt.el
+++ /dev/null
@@ -1,3058 +0,0 @@
-;;; texinfmt.el --- format Texinfo files into Info files.
-
-;; Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993 Free Software
-;; Foundation, Inc.
-
-;; Maintainer: Robert J. Chassell <bug-texinfo@prep.ai.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;;; Emacs lisp functions to convert Texinfo files to Info files.
-
-(defvar texinfmt-version "2.32 of 19 November 1993")
-
-;;; Variable definitions
-
-(require 'texinfo) ; So `texinfo-footnote-style' is defined.
-(require 'texnfo-upd) ; So `texinfo-section-types-regexp' is defined.
-
-(defvar texinfo-format-syntax-table nil)
-
-(defvar texinfo-vindex)
-(defvar texinfo-findex)
-(defvar texinfo-cindex)
-(defvar texinfo-pindex)
-(defvar texinfo-tindex)
-(defvar texinfo-kindex)
-(defvar texinfo-last-node)
-(defvar texinfo-node-names)
-(defvar texinfo-enclosure-list)
-(defvar texinfo-alias-list)
-
-(defvar texinfo-command-start)
-(defvar texinfo-command-end)
-(defvar texinfo-command-name)
-(defvar texinfo-defun-type)
-(defvar texinfo-last-node-pos)
-(defvar texinfo-stack)
-(defvar texinfo-short-index-cmds-alist)
-(defvar texinfo-short-index-format-cmds-alist)
-(defvar texinfo-format-filename)
-(defvar texinfo-footnote-number)
-(defvar texinfo-start-of-header)
-(defvar texinfo-end-of-header)
-(defvar texinfo-raisesections-alist)
-(defvar texinfo-lowersections-alist)
-
-;;; Syntax table
-
-(if texinfo-format-syntax-table
- nil
- (setq texinfo-format-syntax-table (make-syntax-table))
- (modify-syntax-entry ?\" " " texinfo-format-syntax-table)
- (modify-syntax-entry ?\\ " " texinfo-format-syntax-table)
- (modify-syntax-entry ?@ "\\" texinfo-format-syntax-table)
- (modify-syntax-entry ?\^q "\\" texinfo-format-syntax-table)
- (modify-syntax-entry ?\[ "." texinfo-format-syntax-table)
- (modify-syntax-entry ?\] "." texinfo-format-syntax-table)
- (modify-syntax-entry ?\( "." texinfo-format-syntax-table)
- (modify-syntax-entry ?\) "." texinfo-format-syntax-table)
- (modify-syntax-entry ?{ "(}" texinfo-format-syntax-table)
- (modify-syntax-entry ?} "){" texinfo-format-syntax-table)
- (modify-syntax-entry ?\' "." texinfo-format-syntax-table))
-
-
-;;; Top level buffer and region formatting functions
-
-;;;###autoload
-(defun texinfo-format-buffer (&optional notagify)
- "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."
- (interactive "P")
- (let ((lastmessage "Formatting Info file..."))
- (message lastmessage)
- (texinfo-format-buffer-1)
- (if notagify
- nil
- (if (> (buffer-size) 30000)
- (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))))
- (message (concat lastmessage
- (if (interactive-p) "done. Now save it." "done.")))))
-
-(defvar texinfo-region-buffer-name "*Info Region*"
- "*Name of the temporary buffer used by \\[texinfo-format-region].")
-
-;;;###autoload
-(defun texinfo-format-region (region-beginning region-end)
- "Convert 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-pos
- texinfo-last-node
- texinfo-node-names
- (texinfo-footnote-number 0)
- last-input-buffer
- (fill-column-for-info fill-column)
- (input-buffer (current-buffer))
- (input-directory default-directory)
- (header-text "")
- (header-beginning 1)
- (header-end 1))
-
-;;; Copy lines between beginning and end of header lines,
-;;; if any, or else copy the `@setfilename' line, if any.
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (let ((search-end (save-excursion (forward-line 100) (point))))
- (if (or
- ;; Either copy header text.
- (and
- (prog1
- (search-forward tex-start-of-header search-end t)
- (forward-line 1)
- ;; Mark beginning of header.
- (setq header-beginning (point)))
- (prog1
- (search-forward tex-end-of-header nil t)
- (beginning-of-line)
- ;; Mark end of header
- (setq header-end (point))))
- ;; Or copy @filename line.
- (prog2
- (goto-char (point-min))
- (search-forward "@setfilename" search-end t)
- (beginning-of-line)
- (setq header-beginning (point))
- (forward-line 1)
- (setq header-end (point))))
-
- ;; Copy header
- (setq header-text
- (buffer-substring
- (min header-beginning region-beginning)
- header-end))))))
-
-;;; Find a buffer to use.
- (switch-to-buffer (get-buffer-create texinfo-region-buffer-name))
- (erase-buffer)
- ;; Insert the header into the buffer.
- (insert header-text)
- ;; Insert the region into the buffer.
- (insert-buffer-substring
- input-buffer
- (max region-beginning header-end)
- region-end)
- ;; Make sure region ends in a newline.
- (or (= (preceding-char) ?\n)
- (insert "\n"))
-
- (goto-char (point-min))
- (texinfo-mode)
- (message "Converting region to Info format...")
- (setq fill-column fill-column-for-info)
- ;; Install a syntax table useful for scanning command operands.
- (set-syntax-table texinfo-format-syntax-table)
-
- ;; Insert @include files so `texinfo-raise-lower-sections' can
- ;; work on them without losing track of multiple
- ;; @raise/@lowersections commands.
- (while (re-search-forward "^@include" nil t)
- (setq texinfo-command-end (point))
- (let ((filename (concat input-directory
- (texinfo-parse-line-arg))))
- (re-search-backward "^@include")
- (delete-region (point) (save-excursion (forward-line 1) (point)))
- (message "Reading included file: %s" filename)
- (save-excursion
- (save-restriction
- (narrow-to-region
- (point)
- (+ (point) (car (cdr (insert-file-contents filename)))))
- (goto-char (point-min))
- ;; Remove `@setfilename' line from included file, if any,
- ;; so @setfilename command not duplicated.
- (if (re-search-forward
- "^@setfilename" (save-excursion (forward-line 100) (point)) t)
- (progn
- (beginning-of-line)
- (delete-region
- (point) (save-excursion (forward-line 1) (point)))))))))
-
- ;; Raise or lower level of each section, if necessary.
- (goto-char (point-min))
- (texinfo-raise-lower-sections)
- ;; Append @refill to appropriate paragraphs for filling.
- (goto-char (point-min))
- (texinfo-append-refill)
- ;; If the region includes the effective end of the data,
- ;; discard everything after that.
- (goto-char (point-max))
- (if (re-search-backward "^@bye" nil t)
- (delete-region (point) (point-max)))
- ;; Make sure buffer ends in a newline.
- (or (= (preceding-char) ?\n)
- (insert "\n"))
- ;; Don't use a previous value of texinfo-enclosure-list.
- (setq texinfo-enclosure-list nil)
- (setq texinfo-alias-list nil)
-
- (goto-char (point-min))
- (if (looking-at "\\\\input[ \t]+texinfo")
- (delete-region (point) (save-excursion (forward-line 1) (point))))
-
- ;; Insert Info region title text.
- (goto-char (point-min))
- (if (search-forward
- "@setfilename" (save-excursion (forward-line 100) (point)) t)
- (progn
- (setq texinfo-command-end (point))
- (beginning-of-line)
- (setq texinfo-command-start (point))
- (let ((arg (texinfo-parse-arg-discard)))
- (insert " "
- texinfo-region-buffer-name
- " buffer for: `")
- (insert (file-name-nondirectory (expand-file-name arg)))
- (insert "', -*-Text-*-\n")))
- ;; Else no `@setfilename' line
- (insert " "
- texinfo-region-buffer-name
- " buffer -*-Text-*-\n"))
- (insert "produced by `texinfo-format-region'\n"
- "from a region in: "
- (if (buffer-file-name input-buffer)
- (concat "`"
- (file-name-sans-versions
- (file-name-nondirectory
- (buffer-file-name input-buffer)))
- "'")
- (concat "buffer `" (buffer-name input-buffer) "'"))
- "\nusing `texinfmt.el' version "
- texinfmt-version
- ".\n\n")
-
- ;; Now convert for real.
- (goto-char (point-min))
- (texinfo-format-scan)
- (goto-char (point-min))
-
- (message "Done.")))
-
-
-;;; Primary internal formatting function for the whole buffer.
-
-(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-last-node-pos
- 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-for-info fill-column)
- (input-buffer (current-buffer))
- (input-directory default-directory))
- (setq texinfo-enclosure-list nil)
- (setq texinfo-alias-list nil)
- (save-excursion
- (goto-char (point-min))
- (or (search-forward "@setfilename" nil t)
- (error "Texinfo file needs an `@setfilename FILENAME' line."))
- (setq texinfo-command-end (point))
- (setq outfile (texinfo-parse-line-arg)))
- (find-file outfile)
- (texinfo-mode)
- (setq fill-column fill-column-for-info)
- (set-syntax-table texinfo-format-syntax-table)
- (erase-buffer)
- (insert-buffer-substring input-buffer)
- (message "Converting %s to Info format..." (buffer-name input-buffer))
-
- ;; Insert @include files so `texinfo-raise-lower-sections' can
- ;; work on them without losing track of multiple
- ;; @raise/@lowersections commands.
- (goto-char (point-min))
- (while (re-search-forward "^@include" nil t)
- (setq texinfo-command-end (point))
- (let ((filename (concat input-directory
- (texinfo-parse-line-arg))))
- (re-search-backward "^@include")
- (delete-region (point) (save-excursion (forward-line 1) (point)))
- (message "Reading included file: %s" filename)
- (save-excursion
- (save-restriction
- (narrow-to-region
- (point)
- (+ (point) (car (cdr (insert-file-contents filename)))))
- (goto-char (point-min))
- ;; Remove `@setfilename' line from included file, if any,
- ;; so @setfilename command not duplicated.
- (if (re-search-forward
- "^@setfilename"
- (save-excursion (forward-line 100) (point)) t)
- (progn
- (beginning-of-line)
- (delete-region
- (point) (save-excursion (forward-line 1) (point)))))))))
- ;; Raise or lower level of each section, if necessary.
- (goto-char (point-min))
- (texinfo-raise-lower-sections)
- ;; Append @refill to appropriate paragraphs
- (goto-char (point-min))
- (texinfo-append-refill)
- (goto-char (point-min))
- (search-forward "@setfilename")
- (beginning-of-line)
- (delete-region (point-min) (point))
- ;; 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)))
- ;; Make sure buffer ends in a newline.
- (or (= (preceding-char) ?\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)))
-
-
-;;; Perform non-@-command file conversions: quotes and hyphens
-
-(defun texinfo-format-convert (min max)
- ;; Convert left and right quotes to typewriter font quotes.
- (goto-char min)
- (while (search-forward "``" max t)
- (replace-match "\""))
- (goto-char min)
- (while (search-forward "''" max t)
- (replace-match "\""))
- ;; Convert three hyphens in a row to two.
- (goto-char min)
- (while (re-search-forward "\\( \\|\\w\\)\\(---\\)\\( \\|\\w\\)" max t)
- (delete-region (1+ (match-beginning 2)) (+ 2 (match-beginning
- 2)))))
-
-
-;;; Handle paragraph filling
-
-(defvar texinfo-no-refill-regexp
- "^@\\(example\\|smallexample\\|lisp\\|smalllisp\\|display\\|format\\|flushleft\\|flushright\\|menu\\|titlepage\\|iftex\\|ifhtml\\|tex\\|html\\)"
- "Regexp specifying environments in which paragraphs are not filled.")
-
-(defvar texinfo-part-of-para-regexp
- "^@\\(b{\\|bullet{\\|cite{\\|code{\\|emph{\\|equiv{\\|error{\\|expansion{\\|file{\\|i{\\|inforef{\\|kbd{\\|key{\\|lisp{\\|minus{\\|point{\\|print{\\|pxref{\\|r{\\|ref{\\|result{\\|samp{\\|sc{\\|t{\\|TeX{\\|today{\\|var{\\|w{\\|xref{\\)"
- "Regexp specifying @-commands found within paragraphs.")
-
-(defun texinfo-append-refill ()
- "Append @refill at end of each paragraph that should be filled.
-Do not append @refill to paragraphs within @example and similar environments.
-Do not append @refill to paragraphs containing @w{TEXT} or @*."
-
- ;; It is necessary to append @refill before other processing because
- ;; the other processing removes information that tells Texinfo
- ;; whether the text should or should not be filled.
-
- (while (< (point) (point-max))
- (let ((refill-blank-lines "^[ \t\n]*$")
- (case-fold-search nil)) ; Don't confuse @TeX and @tex....
- (beginning-of-line)
- ;; 1. Skip over blank lines;
- ;; skip over lines beginning with @-commands,
- ;; but do not skip over lines
- ;; that are no-refill environments such as @example or
- ;; that begin with within-paragraph @-commands such as @code.
- (while (and (looking-at (concat "^@\\|^\\\\\\|" refill-blank-lines))
- (not (looking-at
- (concat
- "\\("
- texinfo-no-refill-regexp
- "\\|"
- texinfo-part-of-para-regexp
- "\\)")))
- (< (point) (point-max)))
- (forward-line 1))
- ;; 2. Skip over @example and similar no-refill environments.
- (if (looking-at texinfo-no-refill-regexp)
- (let ((environment
- (buffer-substring (match-beginning 1) (match-end 1))))
- (progn (re-search-forward (concat "^@end " environment) nil t)
- (forward-line 1)))
- ;; 3. Do not refill a paragraph containing @w or @*
- (if (or
- (>= (point) (point-max))
- (re-search-forward
- "@w{\\|@\\*" (save-excursion (forward-paragraph) (point)) t))
- ;; Go to end of paragraph and do nothing.
- (forward-paragraph)
- ;; 4. Else go to end of paragraph and insert @refill
- (forward-paragraph)
- (forward-line -1)
- (end-of-line)
- (delete-region
- (point)
- (save-excursion (skip-chars-backward " \t") (point)))
- ;; `looking-at-backward' not available in v. 18.57
- ;; (if (not (looking-at-backward "@refill\\|@bye")) ;)
- (if (not (re-search-backward
- "@refill\\|@bye"
- (save-excursion (beginning-of-line) (point))
- t))
- (insert "@refill"))
- (forward-line 1))))))
-
-
-;;; Handle `@raisesections' and `@lowersections' commands
-
-;; These commands change the hierarchical level of chapter structuring
-;; commands.
-;;
-;; @raisesections changes @subsection to @section,
-;; @section to @chapter,
-;; etc.
-;;
-;; @lowersections changes @chapter to @section
-;; @subsection to @subsubsection,
-;; etc.
-;;
-;; An @raisesections/@lowersections command changes only those
-;; structuring commands that follow the @raisesections/@lowersections
-;; command.
-;;
-;; Repeated @raisesections/@lowersections continue to raise or lower
-;; the heading level.
-;;
-;; An @lowersections command cancels an @raisesections command, and
-;; vice versa.
-;;
-;; You cannot raise or lower "beyond" chapters or subsubsections, but
-;; trying to do so does not elicit an error---you just get more
-;; headings that mean the same thing as you keep raising or lowering
-;; (for example, after a single @raisesections, both @chapter and
-;; @section produce chapter headings).
-
-(defun texinfo-raise-lower-sections ()
- "Raise or lower the hierarchical level of chapters, sections, etc.
-
-This function acts according to `@raisesections' and `@lowersections'
-commands in the Texinfo file.
-
-For example, an `@lowersections' command is useful if you wish to
-include what is written as an outer or standalone Texinfo file in
-another Texinfo file as an inner, included file. The `@lowersections'
-command changes chapters to sections, sections to subsections and so
-on.
-
-@raisesections changes @subsection to @section,
- @section to @chapter,
- @heading to @chapheading,
- etc.
-
-@lowersections changes @chapter to @section,
- @subsection to @subsubsection,
- @heading to @subheading,
- etc.
-
-An `@raisesections' or `@lowersections' command changes only those
-structuring commands that follow the `@raisesections' or
-`@lowersections' command.
-
-An `@lowersections' command cancels an `@raisesections' command, and
-vice versa.
-
-Repeated use of the commands continue to raise or lower the hierarchical
-level a step at a time.
-
-An attempt to raise above `chapters' reproduces chapter commands; an
-attempt to lower below subsubsections reproduces subsubsection
-commands."
-
- ;; `texinfo-section-types-regexp' is defined in `texnfo-upd.el';
- ;; it is a regexp matching chapter, section, other headings
- ;; (but not the top node).
-
- (let (type (level 0))
- (while
- (re-search-forward
- (concat
- "\\(\\(^@\\(raise\\|lower\\)sections\\)\\|\\("
- texinfo-section-types-regexp
- "\\)\\)")
- nil t)
- (beginning-of-line)
- (save-excursion (setq type (read (current-buffer))))
- (cond
-
- ;; 1. Increment level
- ((eq type '@raisesections)
- (setq level (1+ level))
- (delete-region
- (point) (save-excursion (forward-line 1) (point))))
-
- ;; 2. Decrement level
- ((eq type '@lowersections)
- (setq level (1- level))
- (delete-region
- (point) (save-excursion (forward-line 1) (point))))
-
- ;; Now handle structuring commands
- ((cond
-
- ;; 3. Raise level when positive
- ((> level 0)
- (let ((count level)
- (new-level type))
- (while (> count 0)
- (setq new-level
- (cdr (assq new-level texinfo-raisesections-alist)))
- (setq count (1- count)))
- (kill-word 1)
- (insert (symbol-name new-level))))
-
- ;; 4. Do nothing except move point when level is zero
- ((= level 0) (forward-line 1))
-
- ;; 5. Lower level when positive
- ((< level 0)
- (let ((count level)
- (new-level type))
- (while (< count 0)
- (setq new-level
- (cdr (assq new-level texinfo-lowersections-alist)))
- (setq count (1+ count)))
- (kill-word 1)
- (insert (symbol-name new-level))))))))))
-
-(defvar texinfo-raisesections-alist
- '((@chapter . @chapter) ; Cannot go higher
- (@unnumbered . @unnumbered)
-
- (@majorheading . @majorheading)
- (@chapheading . @chapheading)
- (@appendix . @appendix)
-
- (@section . @chapter)
- (@unnumberedsec . @unnumbered)
- (@heading . @chapheading)
- (@appendixsec . @appendix)
-
- (@subsection . @section)
- (@unnumberedsubsec . @unnumberedsec)
- (@subheading . @heading)
- (@appendixsubsec . @appendixsec)
-
- (@subsubsection . @subsection)
- (@unnumberedsubsubsec . @unnumberedsubsec)
- (@subsubheading . @subheading)
- (@appendixsubsubsec . @appendixsubsec))
- "*An alist of next higher levels for chapters, sections. etc.
-For example, section to chapter, subsection to section.
-Used by `texinfo-raise-lower-sections'.
-The keys specify types of section; the values correspond to the next
-higher types.")
-
-(defvar texinfo-lowersections-alist
- '((@chapter . @section)
- (@unnumbered . @unnumberedsec)
- (@majorheading . @heading)
- (@chapheading . @heading)
- (@appendix . @appendixsec)
-
- (@section . @subsection)
- (@unnumberedsec . @unnumberedsubsec)
- (@heading . @subheading)
- (@appendixsec . @appendixsubsec)
-
- (@subsection . @subsubsection)
- (@unnumberedsubsec . @unnumberedsubsubsec)
- (@subheading . @subsubheading)
- (@appendixsubsec . @appendixsubsubsec)
-
- (@subsubsection . @subsubsection) ; Cannot go lower.
- (@unnumberedsubsubsec . @unnumberedsubsubsec)
- (@subsubheading . @subsubheading)
- (@appendixsubsubsec . @appendixsubsubsec))
- "*An alist of next lower levels for chapters, sections. etc.
-For example, chapter to section, section to subsection.
-Used by `texinfo-raise-lower-sections'.
-The keys specify types of section; the values correspond to the next
-lower types.")
-
-
-;;; Perform those texinfo-to-info conversions that apply to the whole input
-;;; uniformly.
-
-(defun texinfo-format-scan ()
- (texinfo-format-convert (point-min) (point-max))
- ;; 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))
- ;; Handle let aliasing
- (setq texinfo-command-name
- (let (trial
- (cmdname
- (buffer-substring
- (1+ texinfo-command-start) texinfo-command-end)))
- (while (setq trial (assoc cmdname texinfo-alias-list))
- (setq cmdname (cdr trial)))
- (intern cmdname)))
- ;; Call the handler for this command.
- (let ((enclosure-type
- (assoc
- (symbol-name texinfo-command-name)
- texinfo-enclosure-list)))
- (if enclosure-type
- (progn
- (insert
- (car (car (cdr enclosure-type)))
- (texinfo-parse-arg-discard)
- (car (cdr (car (cdr enclosure-type)))))
- (goto-char texinfo-command-start))
- (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 ()
- (texinfo-format-begin-end 'texinfo-format))
-
-(put 'end 'texinfo-format 'texinfo-format-end)
-(defun texinfo-format-end ()
- (texinfo-format-begin-end 'texinfo-end))
-
-(defun texinfo-format-begin-end (prop)
- (setq texinfo-command-name (intern (texinfo-parse-line-arg)))
- (let ((cmd (get texinfo-command-name prop)))
- (if cmd (funcall cmd)
- (texinfo-unsupported))))
-
-;;; Parsing functions
-
-(defun texinfo-parse-line-arg ()
- (goto-char texinfo-command-end)
- (let ((start (point)))
- (cond ((looking-at " ")
- (skip-chars-forward " ")
- (setq start (point))
- (end-of-line)
- (skip-chars-backward " ")
- (delete-region (point) (progn (end-of-line) (point)))
- (setq texinfo-command-end (1+ (point))))
- ((looking-at "{")
- (setq start (1+ (point)))
- (forward-list 1)
- (setq texinfo-command-end (point))
- (forward-char -1))
- (t
- (error "Invalid texinfo command arg format")))
- (prog1 (buffer-substring start (point))
- (if (eolp) (forward-char 1)))))
-
-(defun texinfo-parse-expanded-arg ()
- (goto-char texinfo-command-end)
- (let ((start (point))
- marker)
- (cond ((looking-at " ")
- (skip-chars-forward " ")
- (setq start (point))
- (end-of-line)
- (setq texinfo-command-end (1+ (point))))
- ((looking-at "{")
- (setq start (1+ (point)))
- (forward-list 1)
- (setq texinfo-command-end (point))
- (forward-char -1))
- (t
- (error "Invalid texinfo command arg format")))
- (setq marker (move-marker (make-marker) texinfo-command-end))
- (texinfo-format-expand-region start (point))
- (setq texinfo-command-end (marker-position marker))
- (move-marker marker nil)
- (prog1 (buffer-substring start (point))
- (if (eolp) (forward-char 1)))))
-
-(defun texinfo-format-expand-region (start end)
- (save-restriction
- (narrow-to-region start end)
- (let (texinfo-command-start
- texinfo-command-end
- texinfo-command-name
- texinfo-stack)
- (texinfo-format-scan))
- (goto-char (point-max))))
-
-(defun texinfo-parse-arg-discard ()
- (prog1 (texinfo-parse-line-arg)
- (texinfo-discard-command)))
-
-(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
- args)
- (skip-chars-forward " ")
- (while (not (eolp))
- (setq beg (point))
- (re-search-forward "[\n,]")
- (setq next (point))
- (if (bolp) (setq next (1- next)))
- (forward-char -1)
- (skip-chars-backward " ")
- (setq end (point))
- (setq args (cons (if (> end beg) (buffer-substring beg end))
- args))
- (goto-char next)
- (skip-chars-forward " "))
- (if (eolp) (forward-char 1))
- (setq texinfo-command-end (point))
- (nreverse args)))
-
-(defun texinfo-format-parse-args ()
- (let ((start (1- (point)))
- next beg end
- args)
- (search-forward "{")
- (save-excursion
- (texinfo-format-expand-region
- (point)
- (save-excursion (up-list 1) (1- (point)))))
- ;; The following does not handle cross references of the form:
- ;; `@xref{bullet, , @code{@@bullet}@{@}}.' because the
- ;; re-search-forward finds the first right brace after the second
- ;; comma.
- (while (/= (preceding-char) ?\})
- (skip-chars-forward " \t\n")
- (setq beg (point))
- (re-search-forward "[},]")
- (setq next (point))
- (forward-char -1)
- (skip-chars-backward " \t\n")
- (setq end (point))
- (cond ((< beg end)
- (goto-char beg)
- (while (search-forward "\n" end t)
- (replace-match " "))))
- (setq args (cons (if (> end beg) (buffer-substring beg end))
- args))
- (goto-char next))
- (if (eolp) (forward-char 1))
- (setq texinfo-command-end (point))
- (nreverse args)))
-
-(defun texinfo-format-parse-defun-args ()
- (goto-char texinfo-command-end)
- (let ((start (point)))
- (end-of-line)
- (setq texinfo-command-end (1+ (point)))
- (let ((marker (move-marker (make-marker) texinfo-command-end)))
- (texinfo-format-expand-region start (point))
- (setq texinfo-command-end (marker-position marker))
- (move-marker marker nil))
- (goto-char start)
- (let ((args '())
- beg end)
- (skip-chars-forward " ")
- (while (not (eolp))
- (cond ((looking-at "{")
- (setq beg (1+ (point)))
- (forward-list 1)
- (setq end (1- (point))))
- (t
- (setq beg (point))
- (re-search-forward "[\n ]")
- (forward-char -1)
- (setq end (point))))
- (setq args (cons (buffer-substring beg end) args))
- (skip-chars-forward " "))
- (forward-char 1)
- (nreverse args))))
-
-(defun texinfo-discard-line ()
- (goto-char texinfo-command-end)
- (skip-chars-forward " \t")
- (or (eolp)
- (error "Extraneous text at end of command line."))
- (goto-char texinfo-command-start)
- (or (bolp)
- (error "Extraneous text at beginning of command line."))
- (delete-region (point) (progn (forward-line 1) (point))))
-
-(defun texinfo-discard-line-with-args ()
- (goto-char texinfo-command-start)
- (delete-region (point) (progn (forward-line 1) (point))))
-
-
-;;; @setfilename
-
-;; Only `texinfo-format-buffer' handles @setfilename with this
-;; definition; `texinfo-format-region' handles @setfilename, if any,
-;; specially.
-(put 'setfilename 'texinfo-format 'texinfo-format-setfilename)
-(defun texinfo-format-setfilename ()
- (let ((arg (texinfo-parse-arg-discard)))
- (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'\n"
- "from file"
- (if (buffer-file-name input-buffer)
- (concat " `"
- (file-name-sans-versions
- (file-name-nondirectory
- (buffer-file-name input-buffer)))
- "'")
- (concat "buffer `" (buffer-name input-buffer) "'"))
- "\nusing `texinfmt.el' version "
- texinfmt-version
- ".\n\n")))
-
-;;; @node, @menu
-
-(put 'node 'texinfo-format 'texinfo-format-node)
-(put 'nwnode 'texinfo-format 'texinfo-format-node)
-(defun texinfo-format-node ()
- (let* ((args (texinfo-format-parse-line-args))
- (name (nth 0 args))
- (next (nth 1 args))
- (prev (nth 2 args))
- (up (nth 3 args)))
- (texinfo-discard-command)
- (setq texinfo-last-node name)
- (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)
- ;; insert "\n\^_" unconditionally since this is what info is looking for
- (insert "\n\^_\nFile: " texinfo-format-filename
- ", Node: " name)
- (if next
- (insert ", Next: " next))
- (if prev
- (insert ", Prev: " prev))
- (if up
- (insert ", Up: " up))
- (insert ?\n)
- (setq texinfo-last-node-pos (point))))
-
-(put 'menu 'texinfo-format 'texinfo-format-menu)
-(defun texinfo-format-menu ()
- (texinfo-discard-line)
- (insert "* Menu:\n\n"))
-
-(put 'menu 'texinfo-end 'texinfo-discard-command)
-
-
-;;; Cross references
-
-; @xref {NODE, FNAME, NAME, FILE, DOCUMENT}
-; -> *Note FNAME: (FILE)NODE
-; If FILE is missing,
-; *Note FNAME: NODE
-; If FNAME is empty and NAME is present
-; *Note NAME: Node
-; If both NAME and FNAME are missing
-; *Note NODE::
-; texinfo ignores the DOCUMENT argument.
-; -> See section <xref to NODE> [NAME, else NODE], page <xref to NODE>
-; If FILE is specified, (FILE)NODE is used for xrefs.
-; 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)))
- (texinfo-discard-command)
- (insert "*Note ")
- (let ((fname (or (nth 1 args) (nth 2 args))))
- (if (null (or fname (nth 3 args)))
- (insert (car args) "::")
- (insert (or fname (car args)) ": ")
- (if (nth 3 args)
- (insert "(" (nth 3 args) ")"))
- (insert (car args))))))
-
-(put 'pxref 'texinfo-format 'texinfo-format-pxref)
-(defun texinfo-format-pxref ()
- (texinfo-format-xref)
- (or (save-excursion
- (forward-char -2)
- (looking-at "::"))
- (insert ".")))
-
-;@inforef{NODE, FNAME, FILE}
-;Like @xref{NODE, FNAME,,FILE} in texinfo.
-;In Tex, generates "See Info file FILE, node NODE"
-(put 'inforef 'texinfo-format 'texinfo-format-inforef)
-(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) "::"))))
-
-
-;;; Section headings
-
-(put 'majorheading 'texinfo-format 'texinfo-format-chapter)
-(put 'chapheading 'texinfo-format 'texinfo-format-chapter)
-(put 'ichapter 'texinfo-format 'texinfo-format-chapter)
-(put 'chapter 'texinfo-format 'texinfo-format-chapter)
-(put 'iappendix 'texinfo-format 'texinfo-format-chapter)
-(put 'appendix 'texinfo-format 'texinfo-format-chapter)
-(put 'iunnumbered 'texinfo-format 'texinfo-format-chapter)
-(put 'top 'texinfo-format 'texinfo-format-chapter)
-(put 'unnumbered 'texinfo-format 'texinfo-format-chapter)
-(defun texinfo-format-chapter ()
- (texinfo-format-chapter-1 ?*))
-
-(put 'heading 'texinfo-format 'texinfo-format-section)
-(put 'isection 'texinfo-format 'texinfo-format-section)
-(put 'section 'texinfo-format 'texinfo-format-section)
-(put 'iappendixsection 'texinfo-format 'texinfo-format-section)
-(put 'appendixsection 'texinfo-format 'texinfo-format-section)
-(put 'iappendixsec 'texinfo-format 'texinfo-format-section)
-(put 'appendixsec 'texinfo-format 'texinfo-format-section)
-(put 'iunnumberedsec 'texinfo-format 'texinfo-format-section)
-(put 'unnumberedsec 'texinfo-format 'texinfo-format-section)
-(defun texinfo-format-section ()
- (texinfo-format-chapter-1 ?=))
-
-(put 'subheading 'texinfo-format 'texinfo-format-subsection)
-(put 'isubsection 'texinfo-format 'texinfo-format-subsection)
-(put 'subsection 'texinfo-format 'texinfo-format-subsection)
-(put 'iappendixsubsec 'texinfo-format 'texinfo-format-subsection)
-(put 'appendixsubsec 'texinfo-format 'texinfo-format-subsection)
-(put 'iunnumberedsubsec 'texinfo-format 'texinfo-format-subsection)
-(put 'unnumberedsubsec 'texinfo-format 'texinfo-format-subsection)
-(defun texinfo-format-subsection ()
- (texinfo-format-chapter-1 ?-))
-
-(put 'subsubheading 'texinfo-format 'texinfo-format-subsubsection)
-(put 'isubsubsection 'texinfo-format 'texinfo-format-subsubsection)
-(put 'subsubsection 'texinfo-format 'texinfo-format-subsubsection)
-(put 'iappendixsubsubsec 'texinfo-format 'texinfo-format-subsubsection)
-(put 'appendixsubsubsec 'texinfo-format 'texinfo-format-subsubsection)
-(put 'iunnumberedsubsubsec 'texinfo-format 'texinfo-format-subsubsection)
-(put 'unnumberedsubsubsec 'texinfo-format 'texinfo-format-subsubsection)
-(defun texinfo-format-subsubsection ()
- (texinfo-format-chapter-1 ?.))
-
-(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)))
-
-(put 'SectionPAD 'texinfo-format 'texinfo-format-sectionpad)
-(defun texinfo-format-sectionpad ()
- (let ((str (texinfo-parse-arg-discard)))
- (forward-char -1)
- (let ((column (current-column)))
- (forward-char 1)
- (while (> column 0)
- (insert str)
- (setq column (1- column))))
- (insert ?\n)))
-
-
-;;; Space controlling commands: @. and @:, and the soft hyphen.
-
-(put '\. 'texinfo-format 'texinfo-format-\.)
-(defun texinfo-format-\. ()
- (texinfo-discard-command)
- (insert "."))
-
-(put '\: 'texinfo-format 'texinfo-format-\:)
-(defun texinfo-format-\: ()
- (texinfo-discard-command))
-
-(put '\- 'texinfo-format 'texinfo-format-soft-hyphen)
-(defun texinfo-format-soft-hyphen ()
- (texinfo-discard-command))
-
-
-;;; @center, @sp, and @br
-
-(put 'center 'texinfo-format 'texinfo-format-center)
-(defun texinfo-format-center ()
- (let ((arg (texinfo-parse-expanded-arg)))
- (texinfo-discard-command)
- (insert arg)
- (insert ?\n)
- (save-restriction
- (goto-char (1- (point)))
- (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 and @footnotestyle
-
-; 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:
-;
-; * In the End of 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.
-;
-; * In the Separate node style, all the footnotes for a single node
-; are placed in an automatically constructed node of their own.
-
-; Footnote style is specified by the @footnotestyle command, either
-; @footnotestyle separate
-; or
-; @footnotestyle end
-;
-; The default is separate
-
-(defvar texinfo-footnote-style "separate"
- "Footnote style, either separate or end.")
-
-(put 'footnotestyle 'texinfo-format 'texinfo-footnotestyle)
-(defun texinfo-footnotestyle ()
- "Specify whether footnotes are at end of node or in separate nodes.
-Argument is either end or separate."
- (setq texinfo-footnote-style (texinfo-parse-arg-discard)))
-
-(defvar texinfo-footnote-number)
-
-(put 'footnote 'texinfo-format 'texinfo-format-footnote)
-(defun texinfo-format-footnote ()
- "Format a footnote in either end of node or separate node style.
-The texinfo-footnote-style variable controls which style is used."
- (setq texinfo-footnote-number (1+ texinfo-footnote-number))
- (cond ((string= texinfo-footnote-style "end")
- (texinfo-format-end-node))
- ((string= texinfo-footnote-style "separate")
- (texinfo-format-separate-node))))
-
-(defun texinfo-format-separate-node ()
- "Format footnote in Separate node style, with notes in own node.
-The node is constructed automatically."
- (let* (start
- (arg (texinfo-parse-line-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) ; remove or insert whitespace, as needed
- (delete-region (save-excursion (skip-chars-backward " \t\n") (point))
- (point))
- (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 the End of node style, with notes at end of node."
- (let (start
- (arg (texinfo-parse-line-arg)))
- (texinfo-discard-command) ; remove or insert whitespace, as needed
- (delete-region (save-excursion (skip-chars-backward " \t\n") (point))
- (point))
- (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))))))
-
-
-;;; @itemize, @enumerate, and similar commands
-
-;; @itemize pushes (itemize "COMMANDS" STARTPOS) on texinfo-stack.
-;; @enumerate pushes (enumerate 0 STARTPOS).
-;; @item dispatches to the texinfo-item prop of the first elt of the list.
-;; For itemize, this puts in and rescans the COMMANDS.
-;; For enumerate, this increments the number and puts it in.
-;; In either case, it puts a Backspace at the front of the line
-;; which marks it not to be indented later.
-;; All other lines get indented by 5 when the @end is reached.
-
-(defvar texinfo-stack-depth 0
- "Count of number of unpopped texinfo-push-stack calls.
-Used by @refill indenting command to avoid indenting within lists, etc.")
-
-(defun texinfo-push-stack (check arg)
- (setq texinfo-stack-depth (1+ texinfo-stack-depth))
- (setq texinfo-stack
- (cons (list check arg texinfo-command-start)
- texinfo-stack)))
-
-(defun texinfo-pop-stack (check)
- (setq texinfo-stack-depth (1- texinfo-stack-depth))
- (if (null texinfo-stack)
- (error "Unmatched @end %s" check))
- (if (not (eq (car (car texinfo-stack)) check))
- (error "@end %s matches @%s"
- check (car (car texinfo-stack))))
- (prog1 (cdr (car texinfo-stack))
- (setq texinfo-stack (cdr texinfo-stack))))
-
-(put 'itemize 'texinfo-format 'texinfo-itemize)
-(defun texinfo-itemize ()
- (texinfo-push-stack
- 'itemize
- (progn (skip-chars-forward " \t")
- (if (eolp)
- "@bullet"
- (texinfo-parse-line-arg))))
- (texinfo-discard-line-with-args)
- (setq fill-column (- fill-column 5)))
-
-(put 'itemize 'texinfo-end 'texinfo-end-itemize)
-(defun texinfo-end-itemize ()
- (setq fill-column (+ fill-column 5))
- (texinfo-discard-command)
- (let ((stacktop
- (texinfo-pop-stack 'itemize)))
- (texinfo-do-itemize (nth 1 stacktop))))
-
-(put 'enumerate 'texinfo-format 'texinfo-enumerate)
-(defun texinfo-enumerate ()
- (texinfo-push-stack
- 'enumerate
- (progn (skip-chars-forward " \t")
- (if (eolp)
- 1
- (read (current-buffer)))))
- (if (and (symbolp (car (cdr (car texinfo-stack))))
- (> 1 (length (symbol-name (car (cdr (car texinfo-stack)))))))
- (error
- "@enumerate: Use a number or letter, eg: 1, A, a, 3, B, or d." ))
- (texinfo-discard-line-with-args)
- (setq fill-column (- fill-column 5)))
-
-(put 'enumerate 'texinfo-end 'texinfo-end-enumerate)
-(defun texinfo-end-enumerate ()
- (setq fill-column (+ fill-column 5))
- (texinfo-discard-command)
- (let ((stacktop
- (texinfo-pop-stack 'enumerate)))
- (texinfo-do-itemize (nth 1 stacktop))))
-
-;; @alphaenumerate never became a standard part of Texinfo
-(put 'alphaenumerate 'texinfo-format 'texinfo-alphaenumerate)
-(defun texinfo-alphaenumerate ()
- (texinfo-push-stack 'alphaenumerate (1- ?a))
- (setq fill-column (- fill-column 5))
- (texinfo-discard-line))
-
-(put 'alphaenumerate 'texinfo-end 'texinfo-end-alphaenumerate)
-(defun texinfo-end-alphaenumerate ()
- (setq fill-column (+ fill-column 5))
- (texinfo-discard-command)
- (let ((stacktop
- (texinfo-pop-stack 'alphaenumerate)))
- (texinfo-do-itemize (nth 1 stacktop))))
-
-;; @capsenumerate never became a standard part of Texinfo
-(put 'capsenumerate 'texinfo-format 'texinfo-capsenumerate)
-(defun texinfo-capsenumerate ()
- (texinfo-push-stack 'capsenumerate (1- ?A))
- (setq fill-column (- fill-column 5))
- (texinfo-discard-line))
-
-(put 'capsenumerate 'texinfo-end 'texinfo-end-capsenumerate)
-(defun texinfo-end-capsenumerate ()
- (setq fill-column (+ fill-column 5))
- (texinfo-discard-command)
- (let ((stacktop
- (texinfo-pop-stack 'capsenumerate)))
- (texinfo-do-itemize (nth 1 stacktop))))
-
-;; At the @end, indent all the lines within the construct
-;; except those marked with backspace. FROM says where
-;; construct started.
-(defun texinfo-do-itemize (from)
- (save-excursion
- (while (progn (forward-line -1)
- (>= (point) from))
- (if (= (following-char) ?\b)
- (save-excursion
- (delete-char 1)
- (end-of-line)
- (delete-char 6))
- (if (not (looking-at "[ \t]*$"))
- (save-excursion (insert " ")))))))
-
-(put 'item 'texinfo-format 'texinfo-item)
-(put 'itemx 'texinfo-format 'texinfo-item)
-(defun texinfo-item ()
- (funcall (get (car (car texinfo-stack)) 'texinfo-item)))
-
-(put 'itemize 'texinfo-item 'texinfo-itemize-item)
-(defun texinfo-itemize-item ()
- ;; (texinfo-discard-line) ; Did not handle text on same line as @item.
- (delete-region (1+ (point)) (save-excursion (beginning-of-line) (point)))
- (if (looking-at "[ \t]*[^ \t\n]+")
- ;; Text on same line as @item command.
- (insert "\b " (nth 1 (car texinfo-stack)) " \n")
- ;; Else text on next line.
- (insert "\b " (nth 1 (car texinfo-stack)) " "))
- (forward-line -1))
-
-(put 'enumerate 'texinfo-item 'texinfo-enumerate-item)
-(defun texinfo-enumerate-item ()
- (texinfo-discard-line)
- (let (enumerating-symbol)
- (cond ((integerp (car (cdr (car texinfo-stack))))
- (setq enumerating-symbol (car (cdr (car texinfo-stack))))
- (insert ?\b (format "%3d. " enumerating-symbol) ?\n)
- (setcar (cdr (car texinfo-stack)) (1+ enumerating-symbol)))
- ((symbolp (car (cdr (car texinfo-stack))))
- (setq enumerating-symbol
- (symbol-name (car (cdr (car texinfo-stack)))))
- (if (or (equal ?\[ (string-to-char enumerating-symbol))
- (equal ?\{ (string-to-char enumerating-symbol)))
- (error
- "Too many items in enumerated list; alphabet ends at Z."))
- (insert ?\b (format "%3s. " enumerating-symbol) ?\n)
- (setcar (cdr (car texinfo-stack))
- (make-symbol
- (char-to-string
- (1+
- (string-to-char enumerating-symbol))))))
- (t
- (error
- "@enumerate: Use a number or letter, eg: 1, A, a, 3, B or d." )))
- (forward-line -1)))
-
-(put 'alphaenumerate 'texinfo-item 'texinfo-alphaenumerate-item)
-(defun texinfo-alphaenumerate-item ()
- (texinfo-discard-line)
- (let ((next (1+ (car (cdr (car texinfo-stack))))))
- (if (> next ?z)
- (error "More than 26 items in @alphaenumerate; get a bigger alphabet."))
- (setcar (cdr (car texinfo-stack)) next)
- (insert "\b " next ". \n"))
- (forward-line -1))
-
-(put 'capsenumerate 'texinfo-item 'texinfo-capsenumerate-item)
-(defun texinfo-capsenumerate-item ()
- (texinfo-discard-line)
- (let ((next (1+ (car (cdr (car texinfo-stack))))))
- (if (> next ?Z)
- (error "More than 26 items in @capsenumerate; get a bigger alphabet."))
- (setcar (cdr (car texinfo-stack)) next)
- (insert "\b " next ". \n"))
- (forward-line -1))
-
-
-;;; @table
-
-; The `@table' command produces two-column tables.
-
-(put 'table 'texinfo-format 'texinfo-table)
-(defun texinfo-table ()
- (texinfo-push-stack
- 'table
- (progn (skip-chars-forward " \t")
- (if (eolp)
- "@asis"
- (texinfo-parse-line-arg))))
- (texinfo-discard-line-with-args)
- (setq fill-column (- fill-column 5)))
-
-(put 'table 'texinfo-item 'texinfo-table-item)
-(defun texinfo-table-item ()
- (let ((arg (texinfo-parse-arg-discard))
- (itemfont (car (cdr (car texinfo-stack)))))
- (insert ?\b itemfont ?\{ arg "}\n \n"))
- (forward-line -2))
-
-(put 'table 'texinfo-end 'texinfo-end-table)
-(defun texinfo-end-table ()
- (setq fill-column (+ fill-column 5))
- (texinfo-discard-command)
- (let ((stacktop
- (texinfo-pop-stack 'table)))
- (texinfo-do-itemize (nth 1 stacktop))))
-
-;; @description appears to be an undocumented variant on @table that
-;; does not require an arg. It fails in texinfo.tex 2.58 and is not
-;; part of makeinfo.c The command appears to be a relic of the past.
-(put 'description 'texinfo-end 'texinfo-end-table)
-(put 'description 'texinfo-format 'texinfo-description)
-(defun texinfo-description ()
- (texinfo-push-stack 'table "@asis")
- (setq fill-column (- fill-column 5))
- (texinfo-discard-line))
-
-
-;;; @ftable, @vtable
-
-; The `@ftable' and `@vtable' commands are like the `@table' command
-; but they also insert each entry in the first column of the table
-; into the function or variable index.
-
-;; Handle the @ftable and @vtable commands:
-
-(put 'ftable 'texinfo-format 'texinfo-ftable)
-(put 'vtable 'texinfo-format 'texinfo-vtable)
-
-(defun texinfo-ftable () (texinfo-indextable 'ftable))
-(defun texinfo-vtable () (texinfo-indextable 'vtable))
-
-(defun texinfo-indextable (table-type)
- (texinfo-push-stack table-type (texinfo-parse-arg-discard))
- (setq fill-column (- fill-column 5)))
-
-;; Handle the @item commands within ftable and vtable:
-
-(put 'ftable 'texinfo-item 'texinfo-ftable-item)
-(put 'vtable 'texinfo-item 'texinfo-vtable-item)
-
-(defun texinfo-ftable-item () (texinfo-indextable-item 'texinfo-findex))
-(defun texinfo-vtable-item () (texinfo-indextable-item 'texinfo-vindex))
-
-(defun texinfo-indextable-item (index-type)
- (let ((item (texinfo-parse-arg-discard))
- (itemfont (car (cdr (car texinfo-stack))))
- (indexvar index-type))
- (insert ?\b itemfont ?\{ item "}\n \n")
- (set indexvar
- (cons
- (list item texinfo-last-node)
- (symbol-value indexvar)))
- (forward-line -2)))
-
-;; Handle @end ftable, @end vtable
-
-(put 'ftable 'texinfo-end 'texinfo-end-ftable)
-(put 'vtable 'texinfo-end 'texinfo-end-vtable)
-
-(defun texinfo-end-ftable () (texinfo-end-indextable 'ftable))
-(defun texinfo-end-vtable () (texinfo-end-indextable 'vtable))
-
-(defun texinfo-end-indextable (table-type)
- (setq fill-column (+ fill-column 5))
- (texinfo-discard-command)
- (let ((stacktop
- (texinfo-pop-stack table-type)))
- (texinfo-do-itemize (nth 1 stacktop))))
-
-
-;;; @ifinfo, @iftex, @tex, @ifhtml, @html
-
-(put 'ifinfo 'texinfo-format 'texinfo-discard-line)
-(put 'ifinfo 'texinfo-end 'texinfo-discard-command)
-
-(put 'iftex 'texinfo-format 'texinfo-format-iftex)
-(defun texinfo-format-iftex ()
- (delete-region texinfo-command-start
- (progn (re-search-forward "@end iftex[ \t]*\n")
- (point))))
-
-(put 'ifhtml 'texinfo-format 'texinfo-format-ifhtml)
-(defun texinfo-format-ifhtml ()
- (delete-region texinfo-command-start
- (progn (re-search-forward "@end ifhtml[ \t]*\n")
- (point))))
-
-(put 'tex 'texinfo-format 'texinfo-format-tex)
-(defun texinfo-format-tex ()
- (delete-region texinfo-command-start
- (progn (re-search-forward "@end tex[ \t]*\n")
- (point))))
-
-(put 'html 'texinfo-format 'texinfo-format-html)
-(defun texinfo-format-html ()
- (delete-region texinfo-command-start
- (progn (re-search-forward "@end html[ \t]*\n")
- (point))))
-
-
-;;; @titlepage
-
-(put 'titlepage 'texinfo-format 'texinfo-format-titlepage)
-(defun texinfo-format-titlepage ()
- (delete-region texinfo-command-start
- (progn (re-search-forward "@end titlepage[ \t]*\n")
- (point))))
-
-(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 (re-search-forward "@end titlespec[ \t]*\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-time-string "%e %b %Y")))
-
-
-;;; @ignore
-
-(put 'ignore 'texinfo-format 'texinfo-format-ignore)
-(defun texinfo-format-ignore ()
- (delete-region texinfo-command-start
- (progn (re-search-forward "@end ignore[ \t]*\n")
- (point))))
-
-(put 'endignore 'texinfo-format 'texinfo-discard-line)
-
-
-;;; Define the Info enclosure command: @definfoenclose
-
-; A `@definfoenclose' command may be used to define a highlighting
-; command for Info, but not for TeX. A command defined using
-; `@definfoenclose' marks text by enclosing it in strings that precede
-; and follow the text.
-;
-; Presumably, if you define a command with `@definfoenclose` for Info,
-; you will also define the same command in the TeX definitions file,
-; `texinfo.tex' in a manner appropriate for typesetting.
-;
-; Write a `@definfoenclose' command on a line and follow it with three
-; arguments separated by commas (commas are used as separators in an
-; `@node' line in the same way). The first argument to
-; `@definfoenclose' is the @-command name \(without the `@'\); the
-; second argument is the Info start delimiter string; and the third
-; argument is the Info end delimiter string. The latter two arguments
-; enclose the highlighted text in the Info file. A delimiter string
-; may contain spaces. Neither the start nor end delimiter is
-; required. However, if you do not provide a start delimiter, you
-; must follow the command name with two commas in a row; otherwise,
-; the Info formatting commands will misinterpret the end delimiter
-; string as a start delimiter string.
-;
-; If you do a @definfoenclose{} on the name of a pre-defined macro (such
-; as @emph{}, @strong{}, @tt{}, or @i{}) the enclosure definition will
-; override the built-in definition.
-;
-; An enclosure command defined this way takes one argument in braces.
-;
-; For example, you can write:
-;
-; @ifinfo
-; @definfoenclose phoo, //, \\
-; @end ifinfo
-;
-; near the beginning of a Texinfo file at the beginning of the lines
-; to define `@phoo' as an Info formatting command that inserts `//'
-; before and `\\' after the argument to `@phoo'. You can then write
-; `@phoo{bar}' wherever you want `//bar\\' highlighted in Info.
-;
-; Also, for TeX formatting, you could write
-;
-; @iftex
-; @global@let@phoo=@i
-; @end iftex
-;
-; to define `@phoo' as a command that causes TeX to typeset
-; the argument to `@phoo' in italics.
-;
-; Note that each definition applies to its own formatter: one for TeX,
-; the other for texinfo-format-buffer or texinfo-format-region.
-;
-; Here is another example: write
-;
-; @definfoenclose headword, , :
-;
-; near the beginning of the file, to define `@headword' as an Info
-; formatting command that inserts nothing before and a colon after the
-; argument to `@headword'.
-
-(put 'definfoenclose 'texinfo-format 'texinfo-define-info-enclosure)
-(defun texinfo-define-info-enclosure ()
- (let* ((args (texinfo-format-parse-line-args))
- (command-name (nth 0 args))
- (beginning-delimiter (or (nth 1 args) ""))
- (end-delimiter (or (nth 2 args) "")))
- (texinfo-discard-command)
- (setq texinfo-enclosure-list
- (cons
- (list command-name
- (list
- beginning-delimiter
- end-delimiter))
- texinfo-enclosure-list))))
-
-
-;;; @var, @code and the like
-
-(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 'b 'texinfo-format 'texinfo-format-noop)
-(put 'i 'texinfo-format 'texinfo-format-noop)
-(put 'r 'texinfo-format 'texinfo-format-noop)
-(put 't 'texinfo-format 'texinfo-format-noop)
-(put 'w 'texinfo-format 'texinfo-format-noop)
-(put 'asis 'texinfo-format 'texinfo-format-noop)
-(put 'dmn 'texinfo-format 'texinfo-format-noop)
-(put 'key 'texinfo-format 'texinfo-format-noop)
-(put 'math 'texinfo-format 'texinfo-format-noop)
-(put 'titlefont 'texinfo-format 'texinfo-format-noop)
-(defun texinfo-format-noop ()
- (insert (texinfo-parse-arg-discard))
- (goto-char texinfo-command-start))
-
-(put 'cite 'texinfo-format 'texinfo-format-code)
-(put 'code 'texinfo-format 'texinfo-format-code)
-(put 'file 'texinfo-format 'texinfo-format-code)
-(put 'kbd 'texinfo-format 'texinfo-format-code)
-(put 'samp 'texinfo-format 'texinfo-format-code)
-(defun texinfo-format-code ()
- (insert "`" (texinfo-parse-arg-discard) "'")
- (goto-char texinfo-command-start))
-
-(put 'emph 'texinfo-format 'texinfo-format-emph)
-(put 'strong 'texinfo-format 'texinfo-format-emph)
-(defun texinfo-format-emph ()
- (insert "*" (texinfo-parse-arg-discard) "*")
- (goto-char texinfo-command-start))
-
-(put 'dfn 'texinfo-format 'texinfo-format-defn)
-(put 'defn 'texinfo-format 'texinfo-format-defn)
-(defun texinfo-format-defn ()
- (insert "\"" (texinfo-parse-arg-discard) "\"")
- (goto-char texinfo-command-start))
-
-(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)
- (insert "*"))
-
-
-;;; @example, @lisp, @quotation, @display, @smalllisp, @smallexample
-
-(put 'display 'texinfo-format 'texinfo-format-example)
-(put 'example 'texinfo-format 'texinfo-format-example)
-(put 'lisp 'texinfo-format 'texinfo-format-example)
-(put 'quotation 'texinfo-format 'texinfo-format-example)
-(put 'smallexample 'texinfo-format 'texinfo-format-example)
-(put 'smalllisp 'texinfo-format 'texinfo-format-example)
-(defun texinfo-format-example ()
- (texinfo-push-stack 'example nil)
- (setq fill-column (- fill-column 5))
- (texinfo-discard-line))
-
-(put 'example 'texinfo-end 'texinfo-end-example)
-(put 'display 'texinfo-end 'texinfo-end-example)
-(put 'lisp 'texinfo-end 'texinfo-end-example)
-(put 'quotation 'texinfo-end 'texinfo-end-example)
-(put 'smallexample 'texinfo-end 'texinfo-end-example)
-(put 'smalllisp 'texinfo-end 'texinfo-end-example)
-(defun texinfo-end-example ()
- (setq fill-column (+ fill-column 5))
- (texinfo-discard-command)
- (let ((stacktop
- (texinfo-pop-stack 'example)))
- (texinfo-do-itemize (nth 1 stacktop))))
-
-(put 'exdent 'texinfo-format 'texinfo-format-exdent)
-(defun texinfo-format-exdent ()
- (texinfo-discard-command)
- (delete-region (point)
- (progn
- (skip-chars-forward " ")
- (point)))
- (insert ?\b)
- ;; Cancel out the deletion that texinfo-do-itemize
- ;; is going to do at the end of this line.
- (save-excursion
- (end-of-line)
- (insert "\n ")))
-
-
-;;; @cartouche
-
-; The @cartouche command is a noop in Info; in a printed manual,
-; it makes a box with rounded corners.
-
-(put 'cartouche 'texinfo-format 'texinfo-discard-line)
-(put 'cartouche 'texinfo-end 'texinfo-discard-command)
-
-
-;;; @flushleft and @format
-
-; The @flushleft command left justifies every line but leaves the
-; right end ragged. As far as Info is concerned, @flushleft is a
-; `do-nothing' command
-
-; The @format command is similar to @example except that it does not
-; indent; this means that in Info, @format is similar to @flushleft.
-
-(put 'format 'texinfo-format 'texinfo-format-flushleft)
-(put 'flushleft 'texinfo-format 'texinfo-format-flushleft)
-(defun texinfo-format-flushleft ()
- (texinfo-discard-line))
-
-(put 'format 'texinfo-end 'texinfo-end-flushleft)
-(put 'flushleft 'texinfo-end 'texinfo-end-flushleft)
-(defun texinfo-end-flushleft ()
- (texinfo-discard-command))
-
-
-;;; @flushright
-
-; The @flushright command right justifies every line but leaves the
-; left end ragged. Spaces and tabs at the right ends of lines are
-; removed so that visible text lines up on the right side.
-
-(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)
- (skip-chars-backward " \t")
- (delete-region (point) (progn (end-of-line) (point)))
- (current-column)))
- ? )))))
-
-
-;;; @ctrl, @TeX, @copyright, @minus, @dots
-
-(put 'ctrl 'texinfo-format 'texinfo-format-ctrl)
-(defun texinfo-format-ctrl ()
- (let ((str (texinfo-parse-arg-discard)))
- (insert (logand 31 (aref str 0)))))
-
-(put 'TeX 'texinfo-format 'texinfo-format-TeX)
-(defun texinfo-format-TeX ()
- (texinfo-parse-arg-discard)
- (insert "TeX"))
-
-(put 'copyright 'texinfo-format 'texinfo-format-copyright)
-(defun texinfo-format-copyright ()
- (texinfo-parse-arg-discard)
- (insert "(C)"))
-
-(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)
- (insert "-"))
-
-(put 'dots 'texinfo-format 'texinfo-format-dots)
-(defun texinfo-format-dots ()
- (texinfo-parse-arg-discard)
- (insert "..."))
-
-(put 'enddots 'texinfo-format 'texinfo-format-enddots)
-(defun texinfo-format-enddots ()
- (texinfo-parse-arg-discard)
- (insert "...."))
-
-
-;;; Refilling and indenting: @refill, @paragraphindent, @noindent
-
-;;; Indent only those paragraphs that are refilled as a result of an
-;;; @refill command.
-
-; * If the value is `asis', do not change the existing indentation at
-; the starts of paragraphs.
-
-; * If the value zero, delete any existing indentation.
-
-; * If the value is greater than zero, indent each paragraph by that
-; number of spaces.
-
-;;; But do not refill paragraphs with an @refill command that are
-;;; preceded by @noindent or are part of a table, list, or deffn.
-
-(defvar texinfo-paragraph-indent "asis"
- "Number of spaces for @refill to indent a paragraph; else to leave as is.")
-
-(put 'paragraphindent 'texinfo-format 'texinfo-paragraphindent)
-
-(defun texinfo-paragraphindent ()
- "Specify the number of spaces for @refill to indent a paragraph.
-Default is to leave the number of spaces as is."
- (let ((arg (texinfo-parse-arg-discard)))
- (if (string= "asis" arg)
- (setq texinfo-paragraph-indent "asis")
- (setq texinfo-paragraph-indent (string-to-int arg)))))
-
-(put 'refill 'texinfo-format 'texinfo-format-refill)
-(defun texinfo-format-refill ()
- "Refill paragraph. Also, indent first line as set by @paragraphindent.
-Default is to leave paragraph indentation as is."
- (texinfo-discard-command)
- (forward-paragraph -1)
- (if (looking-at "[ \t\n]*$") (forward-line 1))
- ;; Do not indent if an entry in a list, table, or deffn,
- ;; or if paragraph is preceded by @noindent.
- ;; Otherwise, indent
- (cond
- ;; delete a @noindent line and do not indent paragraph
- ((save-excursion (forward-line -1)
- (looking-at "^@noindent"))
- (forward-line -1)
- (delete-region (point) (progn (forward-line 1) (point))))
- ;; do nothing if "asis"
- ((equal texinfo-paragraph-indent "asis"))
- ;; do no indenting in list, etc.
- ((> texinfo-stack-depth 0))
- ;; otherwise delete existing whitespace and indent
- (t
- (delete-region (point) (progn (skip-chars-forward " \t") (point)))
- (insert (make-string texinfo-paragraph-indent ? ))))
- (forward-paragraph 1)
- (forward-line -1)
- (end-of-line)
- ;; Do not fill a section title line with asterisks, hyphens, etc. that
- ;; are used to underline it. This could occur if the line following
- ;; the underlining is not an index entry and has text within it.
- (let* ((previous-paragraph-separate paragraph-separate)
- (paragraph-separate (concat paragraph-separate "\\|[-=*.]+"))
- (previous-paragraph-start paragraph-start)
- (paragraph-start (concat paragraph-start "\\|[-=*.]+")))
- (unwind-protect
- (fill-paragraph nil)
- (setq paragraph-separate previous-paragraph-separate)
- (setq paragraph-start previous-paragraph-start))))
-
-(put 'noindent 'texinfo-format 'texinfo-noindent)
-(defun texinfo-noindent ()
- (save-excursion
- (forward-paragraph 1)
- (if (search-backward "@refill"
- (save-excursion (forward-line -1) (point)) t)
- () ; leave @noindent command so @refill command knows not to indent
- ;; else
- (texinfo-discard-line))))
-
-
-;;; Index generation
-
-(put 'vindex 'texinfo-format 'texinfo-format-vindex)
-(defun texinfo-format-vindex ()
- (texinfo-index 'texinfo-vindex))
-
-(put 'cindex 'texinfo-format 'texinfo-format-cindex)
-(defun texinfo-format-cindex ()
- (texinfo-index 'texinfo-cindex))
-
-(put 'findex 'texinfo-format 'texinfo-format-findex)
-(defun texinfo-format-findex ()
- (texinfo-index 'texinfo-findex))
-
-(put 'pindex 'texinfo-format 'texinfo-format-pindex)
-(defun texinfo-format-pindex ()
- (texinfo-index 'texinfo-pindex))
-
-(put 'tindex 'texinfo-format 'texinfo-format-tindex)
-(defun texinfo-format-tindex ()
- (texinfo-index 'texinfo-tindex))
-
-(put 'kindex 'texinfo-format 'texinfo-format-kindex)
-(defun texinfo-format-kindex ()
- (texinfo-index 'texinfo-kindex))
-
-(defun texinfo-index (indexvar)
- (let ((arg (texinfo-parse-expanded-arg)))
- (texinfo-discard-command)
- (set indexvar
- (cons (list arg
- texinfo-last-node
- ;; Region formatting may not provide last node position.
- (if texinfo-last-node-pos
- (1+ (count-lines texinfo-last-node-pos (point)))
- 1))
- (symbol-value indexvar)))))
-
-(defconst texinfo-indexvar-alist
- '(("cp" . texinfo-cindex)
- ("fn" . texinfo-findex)
- ("vr" . texinfo-vindex)
- ("tp" . texinfo-tindex)
- ("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)))
-
-
-;;; Sort and index (for VMS)
-
-;; Sort an index which is in the current buffer between START and END.
-;; Used on VMS, where the `sort' utility is not available.
-(defun texinfo-sort-region (start end)
- (require 'sort)
- (save-restriction
- (narrow-to-region start end)
- (sort-subr nil 'forward-line 'end-of-line 'texinfo-sort-startkeyfun)))
-
-;; Subroutine for sorting an index.
-;; At start of a line, return a string to sort the line under.
-(defun texinfo-sort-startkeyfun ()
- (let ((line
- (buffer-substring (point) (save-excursion (end-of-line) (point)))))
- ;; Canonicalize whitespace and eliminate funny chars.
- (while (string-match "[ \t][ \t]+\\|[^a-z0-9 ]+" line)
- (setq line (concat (substring line 0 (match-beginning 0))
- " "
- (substring line (match-end 0) (length line)))))
- line))
-
-
-;;; @printindex
-
-(put 'printindex 'texinfo-format 'texinfo-format-printindex)
-
-(defun texinfo-format-printindex ()
- (let ((indexelts (symbol-value
- (cdr (assoc (texinfo-parse-arg-discard)
- texinfo-indexvar-alist))))
- opoint)
- (insert "\n* Menu:\n\n")
- (setq opoint (point))
- (texinfo-print-index nil indexelts)
-
- (if (memq system-type '(vax-vms windows-nt ms-dos))
- (texinfo-sort-region opoint (point))
- (shell-command-on-region opoint (point) "sort -fd" 1))))
-
-(defun texinfo-print-index (file indexelts)
- (while indexelts
- (if (stringp (car (car indexelts)))
- (progn
- (insert "* " (car (car indexelts)) ": " )
- (indent-to 32)
- (insert
- (if file (concat "(" file ")") "")
- (nth 1 (car indexelts)) ".")
- (indent-to 54)
- (insert
- (if (nth 2 (car indexelts))
- (format " %d." (nth 2 (car indexelts)))
- "")
- "\n"))
- ;; index entries from @include'd file
- (texinfo-print-index (nth 1 (car indexelts))
- (nth 2 (car indexelts))))
- (setq indexelts (cdr indexelts))))
-
-
-;;; Glyphs: @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 "=>"))
-
-
-;;; Definition formatting: @deffn, @defun, etc
-
-;; What definition formatting produces:
-;;
-;; @deffn category name args...
-;; In Info, `Category: name ARGS'
-;; In index: name: node. line#.
-;;
-;; @defvr category name
-;; In Info, `Category: name'
-;; In index: name: node. line#.
-;;
-;; @deftp category name attributes...
-;; `category name attributes...' Note: @deftp args in lower case.
-;; In index: name: node. line#.
-;;
-;; Specialized function-like or variable-like entity:
-;;
-;; @defun, @defmac, @defspec, @defvar, @defopt
-;;
-;; @defun name args In Info, `Function: name ARGS'
-;; @defmac name args In Info, `Macro: name ARGS'
-;; @defvar name In Info, `Variable: name'
-;; etc.
-;; In index: name: node. line#.
-;;
-;; Generalized typed-function-like or typed-variable-like entity:
-;; @deftypefn category data-type name args...
-;; In Info, `Category: data-type name args...'
-;; @deftypevr category data-type name
-;; In Info, `Category: data-type name'
-;; In index: name: node. line#.
-;;
-;; Specialized typed-function-like or typed-variable-like entity:
-;; @deftypefun data-type name args...
-;; In Info, `Function: data-type name ARGS'
-;; In index: name: node. line#.
-;;
-;; @deftypevar data-type name
-;; In Info, `Variable: data-type name'
-;; In index: name: node. line#. but include args after name!?
-;;
-;; Generalized object oriented entity:
-;; @defop category class name args...
-;; In Info, `Category on class: name ARG'
-;; In index: name on class: node. line#.
-;;
-;; @defcv category class name
-;; In Info, `Category of class: name'
-;; In index: name of class: node. line#.
-;;
-;; Specialized object oriented entity:
-;; @defmethod class name args...
-;; In Info, `Method on class: name ARGS'
-;; In index: name on class: node. line#.
-;;
-;; @defivar class name
-;; In Info, `Instance variable of class: name'
-;; In index: name of class: node. line#.
-
-
-;;; The definition formatting functions
-
-(defun texinfo-format-defun ()
- (texinfo-push-stack 'defun nil)
- (setq fill-column (- fill-column 5))
- (texinfo-format-defun-1 t))
-
-(defun texinfo-end-defun ()
- (setq fill-column (+ fill-column 5))
- (texinfo-discard-command)
- (let ((start (nth 1 (texinfo-pop-stack 'defun))))
- (texinfo-do-itemize start)
- ;; Delete extra newline inserted after header.
- (save-excursion
- (goto-char start)
- (delete-char -1))))
-
-(defun texinfo-format-defunx ()
- (texinfo-format-defun-1 nil))
-
-(defun texinfo-format-defun-1 (first-p)
- (let ((parse-args (texinfo-format-parse-defun-args))
- (texinfo-defun-type (get texinfo-command-name 'texinfo-defun-type)))
- (texinfo-discard-command)
- ;; Delete extra newline inserted after previous header line.
- (if (not first-p)
- (delete-char -1))
- (funcall
- (get texinfo-command-name 'texinfo-deffn-formatting-property) parse-args)
- ;; Insert extra newline so that paragraph filling does not mess
- ;; with header line.
- (insert "\n\n")
- (rplaca (cdr (cdr (car texinfo-stack))) (point))
- (funcall
- (get texinfo-command-name 'texinfo-defun-indexing-property) parse-args)))
-
-;;; Formatting the first line of a definition
-
-;; @deffn, @defvr, @deftp
-(put 'deffn 'texinfo-deffn-formatting-property 'texinfo-format-deffn)
-(put 'deffnx 'texinfo-deffn-formatting-property 'texinfo-format-deffn)
-(put 'defvr 'texinfo-deffn-formatting-property 'texinfo-format-deffn)
-(put 'defvrx 'texinfo-deffn-formatting-property 'texinfo-format-deffn)
-(put 'deftp 'texinfo-deffn-formatting-property 'texinfo-format-deffn)
-(put 'deftpx 'texinfo-deffn-formatting-property 'texinfo-format-deffn)
-(defun texinfo-format-deffn (parsed-args)
- ;; Generalized function-like, variable-like, or generic data-type entity:
- ;; @deffn category name args...
- ;; In Info, `Category: name ARGS'
- ;; @deftp category name attributes...
- ;; `category name attributes...' Note: @deftp args in lower case.
- (let ((category (car parsed-args))
- (name (car (cdr parsed-args)))
- (args (cdr (cdr parsed-args))))
- (insert " -- " category ": " name)
- (while args
- (insert " "
- (if (or (= ?& (aref (car args) 0))
- (eq (eval (car texinfo-defun-type)) 'deftp-type))
- (car args)
- (upcase (car args))))
- (setq args (cdr args)))))
-
-;; @defun, @defmac, @defspec, @defvar, @defopt: Specialized, simple
-(put 'defun 'texinfo-deffn-formatting-property
- 'texinfo-format-specialized-defun)
-(put 'defunx 'texinfo-deffn-formatting-property
- 'texinfo-format-specialized-defun)
-(put 'defmac 'texinfo-deffn-formatting-property
- 'texinfo-format-specialized-defun)
-(put 'defmacx 'texinfo-deffn-formatting-property
- 'texinfo-format-specialized-defun)
-(put 'defspec 'texinfo-deffn-formatting-property
- 'texinfo-format-specialized-defun)
-(put 'defspecx 'texinfo-deffn-formatting-property
- 'texinfo-format-specialized-defun)
-(put 'defvar 'texinfo-deffn-formatting-property
- 'texinfo-format-specialized-defun)
-(put 'defvarx 'texinfo-deffn-formatting-property
- 'texinfo-format-specialized-defun)
-(put 'defopt 'texinfo-deffn-formatting-property
- 'texinfo-format-specialized-defun)
-(put 'defoptx 'texinfo-deffn-formatting-property
- 'texinfo-format-specialized-defun)
-(defun texinfo-format-specialized-defun (parsed-args)
- ;; Specialized function-like or variable-like entity:
- ;; @defun name args In Info, `Function: Name ARGS'
- ;; @defmac name args In Info, `Macro: Name ARGS'
- ;; @defvar name In Info, `Variable: Name'
- ;; Use cdr of texinfo-defun-type to determine category:
- (let ((category (car (cdr texinfo-defun-type)))
- (name (car parsed-args))
- (args (cdr parsed-args)))
- (insert " -- " category ": " name)
- (while args
- (insert " "
- (if (= ?& (aref (car args) 0))
- (car args)
- (upcase (car args))))
- (setq args (cdr args)))))
-
-;; @deftypefn, @deftypevr: Generalized typed
-(put 'deftypefn 'texinfo-deffn-formatting-property 'texinfo-format-deftypefn)
-(put 'deftypefnx 'texinfo-deffn-formatting-property 'texinfo-format-deftypefn)
-(put 'deftypevr 'texinfo-deffn-formatting-property 'texinfo-format-deftypefn)
-(put 'deftypevrx 'texinfo-deffn-formatting-property 'texinfo-format-deftypefn)
-(defun texinfo-format-deftypefn (parsed-args)
- ;; Generalized typed-function-like or typed-variable-like entity:
- ;; @deftypefn category data-type name args...
- ;; In Info, `Category: data-type name args...'
- ;; @deftypevr category data-type name
- ;; In Info, `Category: data-type name'
- ;; Note: args in lower case, unless modified in command line.
- (let ((category (car parsed-args))
- (data-type (car (cdr parsed-args)))
- (name (car (cdr (cdr parsed-args))))
- (args (cdr (cdr (cdr parsed-args)))))
- (insert " -- " category ": " data-type " " name)
- (while args
- (insert " " (car args))
- (setq args (cdr args)))))
-
-;; @deftypefun, @deftypevar: Specialized typed
-(put 'deftypefun 'texinfo-deffn-formatting-property 'texinfo-format-deftypefun)
-(put 'deftypefunx 'texinfo-deffn-formatting-property
- 'texinfo-format-deftypefun)
-(put 'deftypevar 'texinfo-deffn-formatting-property 'texinfo-format-deftypefun)
-(put 'deftypevarx 'texinfo-deffn-formatting-property
- 'texinfo-format-deftypefun)
-(defun texinfo-format-deftypefun (parsed-args)
- ;; Specialized typed-function-like or typed-variable-like entity:
- ;; @deftypefun data-type name args...
- ;; In Info, `Function: data-type name ARGS'
- ;; @deftypevar data-type name
- ;; In Info, `Variable: data-type name'
- ;; Note: args in lower case, unless modified in command line.
- ;; Use cdr of texinfo-defun-type to determine category:
- (let ((category (car (cdr texinfo-defun-type)))
- (data-type (car parsed-args))
- (name (car (cdr parsed-args)))
- (args (cdr (cdr parsed-args))))
- (insert " -- " category ": " data-type " " name)
- (while args
- (insert " " (car args))
- (setq args (cdr args)))))
-
-;; @defop: Generalized object-oriented
-(put 'defop 'texinfo-deffn-formatting-property 'texinfo-format-defop)
-(put 'defopx 'texinfo-deffn-formatting-property 'texinfo-format-defop)
-(defun texinfo-format-defop (parsed-args)
- ;; Generalized object oriented entity:
- ;; @defop category class name args...
- ;; In Info, `Category on class: name ARG'
- ;; Note: args in upper case; use of `on'
- (let ((category (car parsed-args))
- (class (car (cdr parsed-args)))
- (name (car (cdr (cdr parsed-args))))
- (args (cdr (cdr (cdr parsed-args)))))
- (insert " -- " category " on " class ": " name)
- (while args
- (insert " " (upcase (car args)))
- (setq args (cdr args)))))
-
-;; @defcv: Generalized object-oriented
-(put 'defcv 'texinfo-deffn-formatting-property 'texinfo-format-defcv)
-(put 'defcvx 'texinfo-deffn-formatting-property 'texinfo-format-defcv)
-(defun texinfo-format-defcv (parsed-args)
- ;; Generalized object oriented entity:
- ;; @defcv category class name
- ;; In Info, `Category of class: name'
- ;; Note: args in upper case; use of `of'
- (let ((category (car parsed-args))
- (class (car (cdr parsed-args)))
- (name (car (cdr (cdr parsed-args))))
- (args (cdr (cdr (cdr parsed-args)))))
- (insert " -- " category " of " class ": " name)
- (while args
- (insert " " (upcase (car args)))
- (setq args (cdr args)))))
-
-;; @defmethod: Specialized object-oriented
-(put 'defmethod 'texinfo-deffn-formatting-property 'texinfo-format-defmethod)
-(put 'defmethodx 'texinfo-deffn-formatting-property 'texinfo-format-defmethod)
-(defun texinfo-format-defmethod (parsed-args)
- ;; Specialized object oriented entity:
- ;; @defmethod class name args...
- ;; In Info, `Method on class: name ARGS'
- ;; Note: args in upper case; use of `on'
- ;; Use cdr of texinfo-defun-type to determine category:
- (let ((category (car (cdr texinfo-defun-type)))
- (class (car parsed-args))
- (name (car (cdr parsed-args)))
- (args (cdr (cdr parsed-args))))
- (insert " -- " category " on " class ": " name)
- (while args
- (insert " " (upcase (car args)))
- (setq args (cdr args)))))
-
-;; @defivar: Specialized object-oriented
-(put 'defivar 'texinfo-deffn-formatting-property 'texinfo-format-defivar)
-(put 'defivarx 'texinfo-deffn-formatting-property 'texinfo-format-defivar)
-(defun texinfo-format-defivar (parsed-args)
- ;; Specialized object oriented entity:
- ;; @defivar class name
- ;; In Info, `Instance variable of class: name'
- ;; Note: args in upper case; use of `of'
- ;; Use cdr of texinfo-defun-type to determine category:
- (let ((category (car (cdr texinfo-defun-type)))
- (class (car parsed-args))
- (name (car (cdr parsed-args)))
- (args (cdr (cdr parsed-args))))
- (insert " -- " category " of " class ": " name)
- (while args
- (insert " " (upcase (car args)))
- (setq args (cdr args)))))
-
-
-;;; Indexing for definitions
-
-;; An index entry has three parts: the `entry proper', the node name, and the
-;; line number. Depending on the which command is used, the entry is
-;; formatted differently:
-;;
-;; @defun,
-;; @defmac,
-;; @defspec,
-;; @defvar,
-;; @defopt all use their 1st argument as the entry-proper
-;;
-;; @deffn,
-;; @defvr,
-;; @deftp
-;; @deftypefun
-;; @deftypevar all use their 2nd argument as the entry-proper
-;;
-;; @deftypefn,
-;; @deftypevr both use their 3rd argument as the entry-proper
-;;
-;; @defmethod uses its 2nd and 1st arguments as an entry-proper
-;; formatted: NAME on CLASS
-
-;; @defop uses its 3rd and 2nd arguments as an entry-proper
-;; formatted: NAME on CLASS
-;;
-;; @defivar uses its 2nd and 1st arguments as an entry-proper
-;; formatted: NAME of CLASS
-;;
-;; @defcv uses its 3rd and 2nd argument as an entry-proper
-;; formatted: NAME of CLASS
-
-(put 'defun 'texinfo-defun-indexing-property 'texinfo-index-defun)
-(put 'defunx 'texinfo-defun-indexing-property 'texinfo-index-defun)
-(put 'defmac 'texinfo-defun-indexing-property 'texinfo-index-defun)
-(put 'defmacx 'texinfo-defun-indexing-property 'texinfo-index-defun)
-(put 'defspec 'texinfo-defun-indexing-property 'texinfo-index-defun)
-(put 'defspecx 'texinfo-defun-indexing-property 'texinfo-index-defun)
-(put 'defvar 'texinfo-defun-indexing-property 'texinfo-index-defun)
-(put 'defvarx 'texinfo-defun-indexing-property 'texinfo-index-defun)
-(put 'defopt 'texinfo-defun-indexing-property 'texinfo-index-defun)
-(put 'defoptx 'texinfo-defun-indexing-property 'texinfo-index-defun)
-(defun texinfo-index-defun (parsed-args)
- ;; use 1st parsed-arg as entry-proper
- ;; `index-list' will be texinfo-findex or the like
- (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
- (set index-list
- (cons
- ;; Three elements: entry-proper, node-name, line-number
- (list
- (car parsed-args)
- texinfo-last-node
- ;; Region formatting may not provide last node position.
- (if texinfo-last-node-pos
- (1+ (count-lines texinfo-last-node-pos (point)))
- 1))
- (symbol-value index-list)))))
-
-(put 'deffn 'texinfo-defun-indexing-property 'texinfo-index-deffn)
-(put 'deffnx 'texinfo-defun-indexing-property 'texinfo-index-deffn)
-(put 'defvr 'texinfo-defun-indexing-property 'texinfo-index-deffn)
-(put 'defvrx 'texinfo-defun-indexing-property 'texinfo-index-deffn)
-(put 'deftp 'texinfo-defun-indexing-property 'texinfo-index-deffn)
-(put 'deftpx 'texinfo-defun-indexing-property 'texinfo-index-deffn)
-(put 'deftypefun 'texinfo-defun-indexing-property 'texinfo-index-deffn)
-(put 'deftypefunx 'texinfo-defun-indexing-property 'texinfo-index-deffn)
-(put 'deftypevar 'texinfo-defun-indexing-property 'texinfo-index-deffn)
-(put 'deftypevarx 'texinfo-defun-indexing-property 'texinfo-index-deffn)
-(defun texinfo-index-deffn (parsed-args)
- ;; use 2nd parsed-arg as entry-proper
- ;; `index-list' will be texinfo-findex or the like
- (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
- (set index-list
- (cons
- ;; Three elements: entry-proper, node-name, line-number
- (list
- (car (cdr parsed-args))
- texinfo-last-node
- ;; Region formatting may not provide last node position.
- (if texinfo-last-node-pos
- (1+ (count-lines texinfo-last-node-pos (point)))
- 1))
- (symbol-value index-list)))))
-
-(put 'deftypefn 'texinfo-defun-indexing-property 'texinfo-index-deftypefn)
-(put 'deftypefnx 'texinfo-defun-indexing-property 'texinfo-index-deftypefn)
-(put 'deftypevr 'texinfo-defun-indexing-property 'texinfo-index-deftypefn)
-(put 'deftypevrx 'texinfo-defun-indexing-property 'texinfo-index-deftypefn)
-(defun texinfo-index-deftypefn (parsed-args)
- ;; use 3rd parsed-arg as entry-proper
- ;; `index-list' will be texinfo-findex or the like
- (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
- (set index-list
- (cons
- ;; Three elements: entry-proper, node-name, line-number
- (list
- (car (cdr (cdr parsed-args)))
- texinfo-last-node
- ;; Region formatting may not provide last node position.
- (if texinfo-last-node-pos
- (1+ (count-lines texinfo-last-node-pos (point)))
- 1))
- (symbol-value index-list)))))
-
-(put 'defmethod 'texinfo-defun-indexing-property 'texinfo-index-defmethod)
-(put 'defmethodx 'texinfo-defun-indexing-property 'texinfo-index-defmethod)
-(defun texinfo-index-defmethod (parsed-args)
- ;; use 2nd on 1st parsed-arg as entry-proper
- ;; `index-list' will be texinfo-findex or the like
- (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
- (set index-list
- (cons
- ;; Three elements: entry-proper, node-name, line-number
- (list
- (format "%s on %s"
- (car (cdr parsed-args))
- (car parsed-args))
- texinfo-last-node
- ;; Region formatting may not provide last node position.
- (if texinfo-last-node-pos
- (1+ (count-lines texinfo-last-node-pos (point)))
- 1))
- (symbol-value index-list)))))
-
-(put 'defop 'texinfo-defun-indexing-property 'texinfo-index-defop)
-(put 'defopx 'texinfo-defun-indexing-property 'texinfo-index-defop)
-(defun texinfo-index-defop (parsed-args)
- ;; use 3rd on 2nd parsed-arg as entry-proper
- ;; `index-list' will be texinfo-findex or the like
- (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
- (set index-list
- (cons
- ;; Three elements: entry-proper, node-name, line-number
- (list
- (format "%s on %s"
- (car (cdr (cdr parsed-args)))
- (car (cdr parsed-args)))
- texinfo-last-node
- ;; Region formatting may not provide last node position.
- (if texinfo-last-node-pos
- (1+ (count-lines texinfo-last-node-pos (point)))
- 1))
- (symbol-value index-list)))))
-
-(put 'defivar 'texinfo-defun-indexing-property 'texinfo-index-defivar)
-(put 'defivarx 'texinfo-defun-indexing-property 'texinfo-index-defivar)
-(defun texinfo-index-defivar (parsed-args)
- ;; use 2nd of 1st parsed-arg as entry-proper
- ;; `index-list' will be texinfo-findex or the like
- (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
- (set index-list
- (cons
- ;; Three elements: entry-proper, node-name, line-number
- (list
- (format "%s of %s"
- (car (cdr parsed-args))
- (car parsed-args))
- texinfo-last-node
- ;; Region formatting may not provide last node position.
- (if texinfo-last-node-pos
- (1+ (count-lines texinfo-last-node-pos (point)))
- 1))
- (symbol-value index-list)))))
-
-(put 'defcv 'texinfo-defun-indexing-property 'texinfo-index-defcv)
-(put 'defcvx 'texinfo-defun-indexing-property 'texinfo-index-defcv)
-(defun texinfo-index-defcv (parsed-args)
- ;; use 3rd of 2nd parsed-arg as entry-proper
- ;; `index-list' will be texinfo-findex or the like
- (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
- (set index-list
- (cons
- ;; Three elements: entry-proper, node-name, line-number
- (list
- (format "%s of %s"
- (car (cdr (cdr parsed-args)))
- (car (cdr parsed-args)))
- texinfo-last-node
- ;; Region formatting may not provide last node position.
- (if texinfo-last-node-pos
- (1+ (count-lines texinfo-last-node-pos (point)))
- 1))
- (symbol-value index-list)))))
-
-
-;;; Properties for definitions
-
-;; Each definition command has six properties:
-;;
-;; 1. texinfo-deffn-formatting-property to format definition line
-;; 2. texinfo-defun-indexing-property to create index entry
-;; 3. texinfo-format formatting command
-;; 4. texinfo-end end formatting command
-;; 5. texinfo-defun-type type of deffn to format
-;; 6. texinfo-defun-index type of index to use
-;;
-;; The `x' forms of each definition command are used for the second
-;; and subsequent header lines.
-
-;; The texinfo-deffn-formatting-property and texinfo-defun-indexing-property
-;; are listed just before the appropriate formatting and indexing commands.
-
-(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-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-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-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-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-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-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-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-index 'texinfo-tindex)
-(put 'deftpx 'texinfo-defun-index 'texinfo-tindex)
-
-;;; Object-oriented stuff is a little hairier.
-
-(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-index 'texinfo-findex)
-(put 'defopx 'texinfo-defun-index 'texinfo-findex)
-
-(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 "Method"))
-(put 'defmethodx 'texinfo-defun-type '('defmethod-type "Method"))
-(put 'defmethod 'texinfo-defun-index 'texinfo-findex)
-(put 'defmethodx 'texinfo-defun-index 'texinfo-findex)
-
-(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-index 'texinfo-vindex)
-(put 'defcvx 'texinfo-defun-index 'texinfo-vindex)
-
-(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-index 'texinfo-vindex)
-(put 'defivarx 'texinfo-defun-index 'texinfo-vindex)
-
-;;; Typed functions and variables
-
-(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-index 'texinfo-findex)
-(put 'deftypefnx 'texinfo-defun-index 'texinfo-findex)
-
-(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-index 'texinfo-findex)
-(put 'deftypefunx 'texinfo-defun-index 'texinfo-findex)
-
-(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-index 'texinfo-vindex)
-(put 'deftypevrx 'texinfo-defun-index 'texinfo-vindex)
-
-(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-index 'texinfo-vindex)
-(put 'deftypevarx 'texinfo-defun-index 'texinfo-vindex)
-
-
-;;; @set, @clear, @ifset, @ifclear
-
-;; If a flag is set with @set FLAG, then text between @ifset and @end
-;; ifset is formatted normally, but if the flag is is cleared with
-;; @clear FLAG, then the text is not formatted; it is ignored.
-
-;; If a flag is cleared with @clear FLAG, then text between @ifclear
-;; and @end ifclear is formatted normally, but if the flag is is set with
-;; @set FLAG, then the text is not formatted; it is ignored. @ifclear
-;; is the opposite of @ifset.
-
-;; If a flag is set to a string with @set FLAG,
-;; replace @value{FLAG} with the string.
-;; If a flag with a value is cleared,
-;; @value{FLAG} is invalid,
-;; as if there had never been any @set FLAG previously.
-
-(put 'clear 'texinfo-format 'texinfo-clear)
-(defun texinfo-clear ()
- "Clear the value of the flag."
- (let* ((arg (texinfo-parse-arg-discard))
- (flag (car (read-from-string arg)))
- (value (substring arg (cdr (read-from-string arg)))))
- (put flag 'texinfo-whether-setp 'flag-cleared)
- (put flag 'texinfo-set-value "")))
-
-(put 'set 'texinfo-format 'texinfo-set)
-(defun texinfo-set ()
- "Set the value of the flag, optionally to a string.
-The command `@set foo This is a string.'
-sets flag foo to the value: `This is a string.'
-The command `@value{foo}' expands to the value."
- (let* ((arg (texinfo-parse-arg-discard))
- (flag (car (read-from-string arg)))
- (value (substring arg (cdr (read-from-string arg)))))
- (put flag 'texinfo-whether-setp 'flag-set)
- (put flag 'texinfo-set-value value)))
-
-(put 'value 'texinfo-format 'texinfo-value)
-(defun texinfo-value ()
- "Insert the string to which the flag is set.
-The command `@set foo This is a string.'
-sets flag foo to the value: `This is a string.'
-The command `@value{foo}' expands to the value."
- (let ((arg (texinfo-parse-arg-discard)))
- (cond ((and
- (eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
- 'flag-set)
- (get (car (read-from-string arg)) 'texinfo-set-value))
- (insert (get (car (read-from-string arg)) 'texinfo-set-value)))
- ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
- 'flag-cleared)
- (insert (format "{No value for \"%s\"}" arg)))
- ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp) nil)
- (insert (format "{No value for \"%s\"}" arg))))))
-
-(put 'ifset 'texinfo-end 'texinfo-discard-command)
-(put 'ifset 'texinfo-format 'texinfo-if-set)
-(defun texinfo-if-set ()
- "If set, continue formatting; else do not format region up to @end ifset"
- (let ((arg (texinfo-parse-arg-discard)))
- (cond
- ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
- 'flag-set)
- ;; Format the text (i.e., do not remove it); do nothing here.
- ())
- ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
- 'flag-cleared)
- ;; Clear region (i.e., cause the text to be ignored).
- (delete-region texinfo-command-start
- (progn (re-search-forward "@end ifset[ \t]*\n")
- (point))))
- ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
- nil)
- ;; In this case flag is neither set nor cleared.
- ;; Act as if set, i.e. do nothing.
- ()))))
-
-(put 'ifclear 'texinfo-end 'texinfo-discard-command)
-(put 'ifclear 'texinfo-format 'texinfo-if-clear)
-(defun texinfo-if-clear ()
- "If clear, continue formatting; if set, do not format up to @end ifset"
- (let ((arg (texinfo-parse-arg-discard)))
- (cond
- ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
- 'flag-set)
- ;; Clear region (i.e., cause the text to be ignored).
- (delete-region texinfo-command-start
- (progn (re-search-forward "@end ifclear[ \t]*\n")
- (point))))
- ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
- 'flag-cleared)
- ;; Format the text (i.e., do not remove it); do nothing here.
- ())
- ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
- nil)
- ;; In this case flag is neither set nor cleared.
- ;; Act as if clear, i.e. do nothing.
- ()))))
-
-
-;;; 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 referring 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' line.
-
-;; Updated 24 March 1993
-;; In order for @raisesections and @lowersections to work, included
-;; files must be inserted into the buffer holding the outer file
-;; before other Info formatting takes place. So @include is no longer
-;; is treated like other @-commands.
-(put 'include 'texinfo-format 'texinfo-format-noop)
-
-; 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))))
-;
-;(defun texinfo-subindex (indexvar file content)
-; (set indexvar (cons (list 'recurse file content)
-; (symbol-value indexvar))))
-
-; Second definition:
-; (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
-; (save-restriction
-; (narrow-to-region
-; (point)
-; (+ (point) (car (cdr (insert-file-contents filename)))))
-; (goto-char (point-min))
-; (texinfo-append-refill)
-; (texinfo-format-convert (point-min) (point-max))))
-; (setq last-input-buffer input-buffer) ; to bypass setfilename
-; ))
-
-
-;;; Numerous commands do nothing in Texinfo
-
-;; These commands are defined in texinfo.tex for printed output.
-
-(put 'bye 'texinfo-format 'texinfo-discard-line)
-(put 'c 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'comment 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'contents 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'finalout 'texinfo-format 'texinfo-discard-line)
-(put 'group 'texinfo-end 'texinfo-discard-line-with-args)
-(put 'group 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'headings 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'hsize 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'itemindent 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'lispnarrowing 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'need 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'nopara 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'page 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'parindent 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'setchapternewpage '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 'setx 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'shortcontents 'texinfo-format 'texinfo-discard-line-with-args)
-(put 'smallbook 'texinfo-format 'texinfo-discard-line)
-(put 'summarycontents 'texinfo-format 'texinfo-discard-line-with-args)
-
-
-;;; Some commands cannot be handled
-
-(defun texinfo-unsupported ()
- (error "%s is not handled by texinfo"
- (buffer-substring texinfo-command-start texinfo-command-end)))
-
-;;; Batch formatting
-
-(defun batch-texinfo-format ()
- "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\"."
- (if (not noninteractive)
- (error "batch-texinfo-format 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))
- (condition-case err
- (progn
- (if buffer-file-name (kill-buffer (current-buffer)))
- (find-file file)
- (buffer-disable-undo (current-buffer))
- (set-buffer-modified-p nil)
- (texinfo-mode)
- (message "texinfo formatting %s..." file)
- (texinfo-format-buffer nil)
- (if (buffer-modified-p)
- (progn (message "Saving modified %s" (buffer-file-name))
- (save-buffer))))
- (error
- (message ">> Error: %s" (prin1-to-string err))
- (message ">> point at")
- (let ((s (buffer-substring (point)
- (min (+ (point) 100)
- (point-max))))
- (tem 0))
- (while (setq tem (string-match "\n+" s tem))
- (setq s (concat (substring s 0 (match-beginning 0))
- "\n>> "
- (substring s (match-end 0)))
- tem (1+ tem)))
- (message ">> %s" s))
- (setq error 1))))
- (kill-emacs error))))
-
-
-;;; Place `provide' at end of file.
-(provide 'texinfmt)
-
-;;; texinfmt.el ends here.
diff --git a/lisp/textmodes/texinfo.el b/lisp/textmodes/texinfo.el
deleted file mode 100644
index ea16b03a4ae..00000000000
--- a/lisp/textmodes/texinfo.el
+++ /dev/null
@@ -1,752 +0,0 @@
-;;; texinfo.el --- major mode for editing Texinfo files
-
-;; Copyright (C) 1985, 1988, 1989, 1990, 1991, 1992, 1993 Free Software
-;; Foundation, Inc.
-
-;; Author: Robert J. Chassell
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-
-;;; Autoloads:
-
-(autoload 'makeinfo-region
- "makeinfo"
- "Make Info file from region of current Texinfo file, and switch to it.
-
-This command does not offer the `next-error' feature since it would
-apply to a temporary file, not the original; use the `makeinfo-buffer'
-command to gain use of `next-error'."
- t nil)
-
-(autoload 'makeinfo-buffer
- "makeinfo"
- "Make Info file from current buffer.
-
-Use the \\[next-error] command to move to the next error
-\(if there are errors\)."
- t nil)
-
-(autoload 'kill-compilation
- "compile"
- "Kill the process made by the \\[compile] command."
- t nil)
-
-(autoload 'makeinfo-recenter-compilation-buffer
- "makeinfo"
- "Redisplay `*compilation*' buffer so 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."
- t nil)
-
-(autoload 'texinfo-make-menu
- "texnfo-upd"
- "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."
- t nil)
-
-(autoload 'texinfo-all-menus-update
- "texnfo-upd"
- "Update every regular menu in a Texinfo file.
-Remove pre-existing master menu, if there is one.
-
-If called with a non-nil argument, this function first updates all the
-nodes in the buffer before updating the menus."
- t nil)
-
-(autoload 'texinfo-master-menu
- "texnfo-upd"
- "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-existing 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."
- t nil)
-
-(autoload 'texinfo-indent-menu-description
- "texnfo-upd"
- "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."
- t nil)
-
-(autoload 'texinfo-insert-node-lines
- "texnfo-upd"
- "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."
- t nil)
-
-(autoload 'texinfo-start-menu-description
- "texnfo-upd"
- "In this menu entry, insert the node's section title as a description.
-Position point at beginning of description ready for editing.
-Do not insert a title if the line contains an existing description.
-
-You will need to edit the inserted text since a useful description
-complements the node name rather than repeats it as a title does."
- t nil)
-
-(autoload 'texinfo-multiple-files-update
- "texnfo-upd"
- "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."
- t nil)
-
-
-;;; Code:
-
-;;; Don't you dare insert any `require' calls at top level in this file--rms.
-
-;;; Syntax table
-
-(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))
-
-;; Written by Wolfgang Bangerth <zcg51122@rpool1.rus.uni-stuttgart.de>
-;; To override this example, set either `imenu-generic-expression'
-;; or `imenu-create-index-function'.
-(defvar texinfo-imenu-generic-expression
- '((nil "^@node[ \t]+\\([^,\n]*\\)" 1)
- ("Chapters" "^@chapter[ \t]+\\(.*\\)$" 1))
-
- "Imenu generic expression for TexInfo mode. See `imenu-generic-expression'.")
-
-(defvar texinfo-font-lock-keywords
- '(;; All but the first 2 had an OVERRIDE of t.
- ;; It didn't seem to be any better, and it's slower--simon.
- ("^\\(@c\\|@comment\\)\\>.*" . font-lock-comment-face) ;comments
- ;; Robert J. Chassell <bob@gnu.ai.mit.edu> says remove this line.
- ;("\\$\\([^$]*\\)\\$" 1 font-lock-string-face t)
- ("@\\([a-zA-Z]+\\|[^ \t\n]\\)" 1 font-lock-keyword-face) ;commands
- ("^\\*\\(.*\\)[\t ]*$" 1 font-lock-function-name-face t) ;menu items
- ("@\\(emph\\|strong\\|b\\|i\\){\\([^}]+\\)" 2 font-lock-comment-face)
- ("@\\(file\\|kbd\\|key\\|url\\|email\\){\\([^}]+\\)" 2 font-lock-string-face)
- ("@\\(samp\\|code\\|var\\|math\\){\\([^}]+\\)"
- 2 font-lock-variable-name-face)
- ("@\\(cite\\|xref\\|pxref\\){\\([^}]+\\)" 2 font-lock-reference-face)
- ("@\\(end\\|itemx?\\) +\\(.+\\)" 2 font-lock-function-name-face keep)
- )
- "Additional expressions to highlight in TeXinfo mode.")
-
-(defvar texinfo-section-list
- '(("top" 1)
- ("majorheading" 1)
- ("chapter" 2)
- ("unnumbered" 2)
- ("appendix" 2)
- ("chapheading" 2)
- ("section" 3)
- ("unnumberedsec" 3)
- ("appendixsec" 3)
- ("heading" 3)
- ("subsection" 4)
- ("unnumberedsubsec" 4)
- ("appendixsubsec" 4)
- ("subheading" 4)
- ("subsubsection" 5)
- ("unnumberedsubsubsec" 5)
- ("appendixsubsubsec" 5)
- ("subsubheading" 5))
- "Alist of sectioning commands and their relative level.")
-
-(defun texinfo-outline-level ()
- ;; Calculate level of current texinfo outline heading.
- (save-excursion
- (if (bobp)
- 0
- (forward-char 1)
- (let* ((word (buffer-substring-no-properties
- (point) (progn (forward-word 1) (point))))
- (entry (assoc word texinfo-section-list)))
- (if entry
- (nth 1 entry)
- 5)))))
-
-;;; Keybindings
-(defvar texinfo-mode-map nil)
-
-;;; Keys common both to Texinfo mode and to TeX shell.
-
-(defun texinfo-define-common-keys (keymap)
- "Define the keys both in Texinfo mode and in the texinfo-tex-shell."
- (define-key keymap "\C-c\C-t\C-k" 'tex-kill-job)
- (define-key keymap "\C-c\C-t\C-x" 'texinfo-quit-job)
- (define-key keymap "\C-c\C-t\C-l" 'tex-recenter-output-buffer)
- (define-key keymap "\C-c\C-t\C-d" 'texinfo-delete-from-print-queue)
- (define-key keymap "\C-c\C-t\C-q" 'tex-show-print-queue)
- (define-key keymap "\C-c\C-t\C-p" 'texinfo-tex-print)
- (define-key keymap "\C-c\C-t\C-v" 'texinfo-tex-view)
- (define-key keymap "\C-c\C-t\C-i" 'texinfo-texindex)
-
- (define-key keymap "\C-c\C-t\C-r" 'texinfo-tex-region)
- (define-key keymap "\C-c\C-t\C-b" 'texinfo-tex-buffer))
-
-;; 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))
-
- ;; bindings for `texnfo-tex.el'
- (texinfo-define-common-keys texinfo-mode-map)
-
- ;; bindings for `makeinfo.el'
- (define-key texinfo-mode-map "\C-c\C-m\C-k" 'kill-compilation)
- (define-key texinfo-mode-map "\C-c\C-m\C-l"
- 'makeinfo-recenter-compilation-buffer)
- (define-key texinfo-mode-map "\C-c\C-m\C-r" 'makeinfo-region)
- (define-key texinfo-mode-map "\C-c\C-m\C-b" 'makeinfo-buffer)
-
- ; Bindings for texinfmt.el.
- (define-key texinfo-mode-map "\C-c\C-e\C-r" 'texinfo-format-region)
- (define-key texinfo-mode-map "\C-c\C-e\C-b" 'texinfo-format-buffer)
-
- ;; bindings for updating nodes and menus
-
- (define-key texinfo-mode-map "\C-c\C-um" 'texinfo-master-menu)
-
- (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 "\C-c}" 'up-list)
- (define-key texinfo-mode-map "\C-c{" 'texinfo-insert-braces)
-
- ;; bindings for inserting strings
-
- (define-key texinfo-mode-map "\C-c\C-c\C-d" 'texinfo-start-menu-description)
-
- (define-key texinfo-mode-map "\C-c\C-cv" 'texinfo-insert-@var)
- (define-key texinfo-mode-map "\C-c\C-ct" 'texinfo-insert-@table)
- (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-cf" 'texinfo-insert-@file)
- (define-key texinfo-mode-map "\C-c\C-cx" 'texinfo-insert-@example)
- (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))
-
-
-;;; Texinfo mode
-
-(defvar texinfo-chapter-level-regexp
- "chapter\\|unnumbered \\|appendix \\|majorheading\\|chapheading"
- "Regular expression matching Texinfo chapter-level headings.
-This does not match `@node' and does not match the `@top' command.")
-
-;;;###autoload
-(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 with \\[makeinfo-buffer] or
-the `makeinfo' program. 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 \\[makeinfo-region], which runs `makeinfo' on the current region.
-
- 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 'page-delimiter)
- (setq page-delimiter
- (concat
- "^@node [ \t]*[Tt]op\\|^@\\("
- texinfo-chapter-level-regexp
- "\\)"))
- (make-local-variable 'require-final-newline)
- (setq require-final-newline t)
- (make-local-variable 'indent-tabs-mode)
- (setq indent-tabs-mode nil)
- (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 'imenu-generic-expression)
- (setq imenu-generic-expression texinfo-imenu-generic-expression)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(texinfo-font-lock-keywords t))
- (make-local-variable 'outline-regexp)
- (setq outline-regexp
- (concat "@\\("
- (mapconcat 'car texinfo-section-list "\\>\\|")
- "\\>\\)"))
- (make-local-variable 'outline-level)
- (setq outline-level 'texinfo-outline-level)
- (make-local-variable 'tex-start-of-header)
- (setq tex-start-of-header "%\\*\\*start")
- (make-local-variable 'tex-end-of-header)
- (setq tex-end-of-header "%\\*\\*end")
- (make-local-variable 'tex-first-line-header-regexp)
- (setq tex-first-line-header-regexp "^\\\\input")
- (make-local-variable 'tex-trailer)
- (setq tex-trailer "@bye\n")
- (run-hooks 'text-mode-hook 'texinfo-mode-hook))
-
-
-;;; Insert string commands
-
-(defconst texinfo-environment-regexp
- "^[ \t]*@\\(f?table\\|enumerate\\|itemize\
-\\|ifhtml\\|ifinfo\\|iftex\\|ifset\\|ifclear\
-\\|example\\|quotation\\|lisp\\|smallexample\\|smalllisp\\|display\\|format\
-\\|flushleft\\|flushright\\|ignore\\|group\\|tex\\|html\\|cartouche\\|menu\
-\\|titlepage\\|end\\|def[a-z]*[a-wyz]\\>\\)"
- "Regexp for environment-like Texinfo list commands.
-Subexpression 1 is what goes into the corresponding `@end' statement.")
-
-(defun texinfo-insert-@end ()
- "Insert the matching `@end' for the last Texinfo command that needs one."
- (interactive)
- (let ((depth 1) string)
- (save-excursion
- (while (and (> depth 0)
- (re-search-backward texinfo-environment-regexp nil t)
- (if (looking-at "@end")
- (setq depth (1+ depth))
- (setq depth (1- depth)))))
- (looking-at texinfo-environment-regexp)
- (if (zerop depth)
- (setq string
- (buffer-substring (match-beginning 1)
- (match-end 1)))))
- (insert "@end ")
- (if string (insert string "\n"))))
-
-;; The following insert commands accept a prefix arg N, which is the
-;; number of words (actually s-exprs) that should be surrounded by
-;; braces. Thus you can first paste a variable name into a .texinfo
-;; buffer, then say C-u 1 C-c C-c v at the beginning of the just
-;; pasted variable name to put @var{...} *around* the variable name.
-;; Operate on previous word or words with negative arg.
-
-;; These commands use texinfo-insert-@-with-arg
-(defun texinfo-insert-@-with-arg (string &optional arg)
- (if arg
- (progn
- (setq arg (prefix-numeric-value arg))
- (if (< arg 0)
- (progn
- (skip-chars-backward " \t\n\r\f")
- (save-excursion
- (forward-sexp arg)
- (insert "@" string "{"))
- (insert "}"))
- (skip-chars-forward " \t\n\r\f")
- (insert "@" string "{")
- (forward-sexp arg)
- (insert "}")))
- (insert "@" string "{}")
- (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-insert-@code (&optional arg)
- "Insert a `@code{...}' command in a Texinfo buffer.
-A numeric argument says how many words the braces should surround.
-The default is not to surround any existing words with the braces."
- (interactive "P")
- (texinfo-insert-@-with-arg "code" arg))
-
-(defun texinfo-insert-@dfn (&optional arg)
- "Insert a `@dfn{...}' command in a Texinfo buffer.
-A numeric argument says how many words the braces should surround.
-The default is not to surround any existing words with the braces."
- (interactive "P")
- (texinfo-insert-@-with-arg "dfn" arg))
-
-(defun texinfo-insert-@example ()
- "Insert the string `@example' in a Texinfo buffer."
- (interactive)
- (insert "@example\n"))
-
-(defun texinfo-insert-@file (&optional arg)
- "Insert a `@file{...}' command in a Texinfo buffer.
-A numeric argument says how many words the braces should surround.
-The default is not to surround any existing words with the braces."
- (interactive "P")
- (texinfo-insert-@-with-arg "file" arg))
-
-(defun texinfo-insert-@item ()
- "Insert the string `@item' in a Texinfo buffer."
- (interactive)
- (insert "@item")
- (newline))
-
-(defun texinfo-insert-@kbd (&optional arg)
- "Insert a `@kbd{...}' command in a Texinfo buffer.
-A numeric argument says how many words the braces should surround.
-The default is not to surround any existing words with the braces."
- (interactive "P")
- (texinfo-insert-@-with-arg "kbd" arg))
-
-(defun texinfo-insert-@node ()
- "Insert the string `@node' in a Texinfo buffer.
-This also inserts on the following line a comment indicating
-the order of arguments to @node."
- (interactive)
- (insert "@node \n@comment node-name, next, previous, up")
- (forward-line -1)
- (forward-char 6))
-
-(defun texinfo-insert-@noindent ()
- "Insert the string `@noindent' in a Texinfo buffer."
- (interactive)
- (insert "@noindent\n"))
-
-(defun texinfo-insert-@samp (&optional arg)
- "Insert a `@samp{...}' command in a Texinfo buffer.
-A numeric argument says how many words the braces should surround.
-The default is not to surround any existing words with the braces."
- (interactive "P")
- (texinfo-insert-@-with-arg "samp" arg))
-
-(defun texinfo-insert-@table (&optional arg)
- "Insert the string `@table' in a Texinfo buffer."
- (interactive "P")
- (insert "@table "))
-
-(defun texinfo-insert-@var (&optional arg)
- "Insert a `@var{}' command in a Texinfo buffer.
-A numeric argument says how many words the braces should surround.
-The default is not to surround any existing words with the braces."
- (interactive "P")
- (texinfo-insert-@-with-arg "var" arg))
-
-;;; Texinfo file structure
-
-;; These are defined in tenfo-upd.el.
-(defvar texinfo-section-types-regexp)
-(defvar texinfo-section-level-regexp)
-(defvar texinfo-subsection-level-regexp)
-(defvar texinfo-subsubsection-level-regexp)
-
-(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 buffer named `*Occur*'. In that buffer, you can move point to
-one of those lines and then use \\<occur-mode-map>\\[occur-mode-goto-occurrence],
-to jump to the corresponding spot in the Texinfo source file."
-
- (interactive "P")
- (require 'texnfo-upd)
- (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 "-----")
- ;; Now format the "*Occur*" buffer to show the structure.
- ;; Thanks to ceder@signum.se (Per Cederqvist)
- (goto-char (point-max))
- (let ((margin 5))
- (while (re-search-backward "^ *[0-9]*:" nil 0)
- (re-search-forward ":")
- (setq margin
- (cond
- ((looking-at
- (concat "@\\(" texinfo-chapter-level-regexp "\\)")) 5)
- ;; ((looking-at "@chapter ") 5)
- ;; ((looking-at "@unnumbered ") 5)
- ;; ((looking-at "@appendix ") 5)
- ;; ((looking-at "@majorheading ") 5)
- ;; ((looking-at "@chapheading ") 5)
-
- ((looking-at
- (concat "@\\(" texinfo-section-level-regexp "\\)")) 9)
- ;; ((looking-at "@section ") 9)
- ;; ((looking-at "@unnumberedsec ") 9)
- ;; ((looking-at "@appendixsec ") 9)
- ;; ((looking-at "@heading ") 9)
-
- ((looking-at
- (concat "@\\(" texinfo-subsection-level-regexp "\\)")) 13)
- ;; ((looking-at "@subsection ") 13)
- ;; ((looking-at "@unnumberedsubsec ") 13)
- ;; ((looking-at "@appendixsubsec ") 13)
- ;; ((looking-at "@subheading ") 13)
-
- ((looking-at
- (concat "@\\(" texinfo-subsubsection-level-regexp "\\)")) 17)
- ;; ((looking-at "@subsubsection ") 17)
- ;; ((looking-at "@unnumberedsubsubsec ") 17)
- ;; ((looking-at "@appendixsubsubsec ") 17)
- ;; ((looking-at "@subsubheading ") 17)
- (t margin)))
- (indent-to-column margin)
- (beginning-of-line))))
-
-;;; The tex and print function definitions:
-
-(defvar texinfo-texi2dvi-command "texi2dvi"
- "*Command used by `texinfo-tex-buffer' to run TeX and texindex on a buffer.")
-
-(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.")
-
-(defvar texinfo-delete-from-print-queue-command "lprm"
- "*Command string used to delete a job from the line printer queue.
-Command is used by \\[texinfo-delete-from-print-queue] based on
-number provided by a previous \\[tex-show-print-queue]
-command.")
-
-(defvar texinfo-tex-trailer "@bye"
- "String appended after a region sent to TeX by `texinfo-tex-region'.")
-
-(defun texinfo-tex-region (beg end)
- "Run TeX on the current region.
-This works by writing a temporary file (`tex-zap-file') in the directory
-that is the value of `tex-directory', then running TeX on that file.
-
-The first line of the buffer 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 `texinfo-tex-trailer' is appended to the temporary file after the region."
- (interactive "r")
- (require 'tex-mode)
- (let ((tex-command texinfo-tex-command)
- (tex-trailer "@bye\n"))
- (tex-region beg end)))
-
-(defun texinfo-tex-buffer ()
- "Run TeX on visited file, once or twice, to make a correct `.dvi' file."
- (interactive)
- (require 'tex-mode)
- (let ((tex-command texinfo-texi2dvi-command))
- (tex-buffer)))
-
-(defun texinfo-texindex ()
- "Run `texindex' on unsorted index files.
-The index files are made by \\[texinfo-tex-region] or \\[texinfo-tex-buffer].
-This runs the shell command defined by `texinfo-texindex-command'."
- (interactive)
- (require 'tex-mode)
- (tex-send-command texinfo-texindex-command (concat tex-zap-file ".??"))
- (tex-recenter-output-buffer nil))
-
-(defun texinfo-tex-print ()
- "Print `.dvi' file made by \\[texinfo-tex-region] or \\[texinfo-tex-buffer].
-This runs the shell command defined by `tex-dvi-print-command'."
- (interactive)
- (require 'tex-mode)
- (tex-print))
-
-(defun texinfo-tex-view ()
- "View `.dvi' file made by \\[texinfo-tex-region] or \\[texinfo-tex-buffer].
-This runs the shell command defined by `tex-dvi-view-command'."
- (interactive)
- (require 'tex-mode)
- (tex-view))
-
-(defun texinfo-quit-job ()
- "Quit currently running TeX job, by sending an `x' to it."
- (interactive)
- (if (not (get-process "tex-shell"))
- (error "No TeX shell running"))
- (tex-send-command "x"))
-
-(defun texinfo-delete-from-print-queue (job-number)
- "Delete job from the line printer spooling queue.
-You are prompted for the job number (use a number shown by a previous
-\\[texinfo-show-print-queue] command)."
- (interactive "nPrinter job number for deletion: ")
- (require 'tex-mode)
- (if (tex-shell-running)
- (tex-kill-job)
- (tex-start-shell))
- (tex-send-command texinfo-delete-from-print-queue-command job-number)
- (tex-recenter-output-buffer nil))
-
-(provide 'texinfo)
-
-;;; texinfo.el ends here
diff --git a/lisp/textmodes/texnfo-upd.el b/lisp/textmodes/texnfo-upd.el
deleted file mode 100644
index e44ef6ba8db..00000000000
--- a/lisp/textmodes/texnfo-upd.el
+++ /dev/null
@@ -1,2049 +0,0 @@
-;;; texnfo-upd.el --- utilities for updating nodes and menus in Texinfo files
-
-;; Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
-
-;; Author: Robert J. Chassell
-;; Maintainer: bug-texinfo@prep.ai.mit.edu
-;; Keywords: maint, tex, docs
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Known bug: update commands fail to ignore @ignore.
-
-;; Summary: how to use the updating commands
-
-;; 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.
-;;
-;; 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 update node functions described 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-sequential-node-update' 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 menu making functions described in detail
-
-;; 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.
-
-
-;;; Code:
-
-;;; The 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 in %s... " (buffer-name))
- (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)
- (beginning-of-line)
- (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-incorporate-menu-entry-names 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.
-Update pre-existing master menu, if there is one.
-
-If called with a non-nil argument, this function first updates all the
-nodes in the buffer before updating the menus."
- (interactive "P")
- (let ((case-fold-search t)
- master-menu-p)
- (save-excursion
- (push-mark (point-max) t)
- (goto-char (point-min))
- (message "Checking for a master menu in %s ... "(buffer-name))
- (save-excursion
- (if (re-search-forward texinfo-master-menu-header nil t)
- ;; Remove detailed master menu listing
- (progn
- (setq master-menu-p t)
- (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-p
- (progn
- (message "Updating all nodes in %s ... " (buffer-name))
- (sleep-for 2)
- (push-mark (point-max) t)
- (goto-char (point-min))
- ;; Using the mark to pass bounds this way
- ;; is kludgy, but it's not worth fixing. -- rms.
- (let ((mark-active t))
- (texinfo-update-node t))))
-
- (message "Updating all menus in %s ... " (buffer-name))
- (sleep-for 2)
- (push-mark (point-max) t)
- (goto-char (point-min))
- ;; Using the mark to pass bounds this way
- ;; is kludgy, but it's not worth fixing. -- rms.
- (let ((mark-active t))
- (texinfo-make-menu t))
-
- (if master-menu-p
- (progn
- (message "Updating the master menu in %s... " (buffer-name))
- (sleep-for 2)
- (texinfo-master-menu nil))))
-
- (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."
- (let ((case-fold-search t))
- (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."
- (let ((case-fold-search t))
- (cond
- ((or (string-equal "top" level) (string-equal "chapter" level))
- (if (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" region-end t)
- (progn (beginning-of-line) t)))
- (t
- (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))))
- region-end t)
- (progn (beginning-of-line) t))))))
-
-
-;;; 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)
- (prog1 "" (forward-line 1)))
- ;; Use following to insert section titles automatically.
- ;; (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 position
-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."
- (let ((case-fold-search t))
- (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 is found in the old menu, insert the
-old description into the new entry.
-
-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 (re-search-forward
- ;; Existing nodes can have the form
- ;; * NODE NAME:: DESCRIPTION
- ;; or
- ;; * MENU ITEM: NODE NAME. DESCRIPTION.
- ;;
- ;; Recognize both when looking for the description.
- (concat "\\* \\(" ; so only menu entries are found
- (car (car new-menu-list)) "::"
- "\\|"
- ".*: " (car (car new-menu-list)) "[.,\t\n]"
- "\\)"
- ) ; 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-incorporate-menu-entry-names (new-menu-list)
- "Copy any old menu entry names 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, do nothing.
-
-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 is the description (or nil).
-
-If we find an existing menu entry name, we change the first element of
-the pair to be another dotted pair in which the car is the menu entry
-name and the cdr is the node name.
-
-NEW-MENU-LIST 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 (re-search-forward
- ;; Existing nodes can have the form
- ;; * NODE NAME:: DESCRIPTION
- ;; or
- ;; * MENU ITEM: NODE NAME. DESCRIPTION.
- ;;
- ;; We're interested in the second case.
- (concat "\\* " ; so only menu entries are found
- "\\(.*\\): " (car (car new-menu-list)) "[.,\t\n]")
- end-of-menu
- t)
- (setcar
- (car new-menu-list) ; replace the node name
- (cons (buffer-substring (match-beginning 1) (match-end 1))
- (car (car new-menu-list)))))
- (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 `@'!
- ;; !! Known bug: does not copy descriptions starting with ^|\{?* etc.
- (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-name2\" . \"description\"\) ... \)
-
-However, the description field might be nil.
-
-Also, the node-name field might itself be a dotted pair (call it P) of
-strings instead of just a string. In that case, the car of P
-is the menu entry name, and the cdr of P is the node name."
-
- (insert "@menu\n")
- (while menu-list
- ;; Every menu entry starts with a star and a space.
- (insert "* ")
-
- ;; Insert the node name (and menu entry name, if present).
- (let ((node-part (car (car menu-list))))
- (if (stringp node-part)
- ;; "Double colon" entry line; menu entry and node name are the same,
- (insert (format "%s::" node-part))
- ;; "Single colon" entry line; menu entry and node name are different.
- (insert (format "%s: %s." (car node-part) (cdr node-part)))))
-
- ;; Insert the description, if present.
- (if (cdr (car menu-list))
- (progn
- ;; Move to right place.
- (indent-to texinfo-column-for-description 2)
- ;; Insert description.
- (insert (format "%s" (cdr (car menu-list))))))
-
- (insert "\n") ; end this menu entry
- (setq menu-list (cdr menu-list)))
- (insert "@end menu")
- (message
- "Updated \"%s\" level menu following node: %s ... " level node-name))
-
-
-;;; Starting menu descriptions by inserting titles
-
-(defun texinfo-start-menu-description ()
- "In this menu entry, insert the node's section title as a description.
-Position point at beginning of description ready for editing.
-Do not insert a title if the line contains an existing description.
-
-You will need to edit the inserted text since a useful description
-complements the node name rather than repeats it as a title does."
-
- (interactive)
- (let (beginning end node-name title)
- (save-excursion
- (beginning-of-line)
- (if (search-forward "* " (save-excursion (end-of-line) (point)) t)
- (progn (skip-chars-forward " \t")
- (setq beginning (point)))
- (error "This is not a line in a menu!"))
-
- (cond
- ;; "Double colon" entry line; menu entry and node name are the same,
- ((search-forward "::" (save-excursion (end-of-line) (point)) t)
- (if (looking-at "[ \t]*[^ \t\n]+")
- (error "Descriptive text already exists."))
- (skip-chars-backward ": \t")
- (setq node-name (buffer-substring beginning (point))))
-
- ;; "Single colon" entry line; menu entry and node name are different.
- ((search-forward ":" (save-excursion (end-of-line) (point)) t)
- (skip-chars-forward " \t")
- (setq beginning (point))
- ;; Menu entry line ends in a period, comma, or tab.
- (if (re-search-forward "[.,\t]"
- (save-excursion (forward-line 1) (point)) t)
- (progn
- (if (looking-at "[ \t]*[^ \t\n]+")
- (error "Descriptive text already exists."))
- (skip-chars-backward "., \t")
- (setq node-name (buffer-substring beginning (point))))
- ;; Menu entry line ends in a return.
- (re-search-forward ".*\n"
- (save-excursion (forward-line 1) (point)) t)
- (skip-chars-backward " \t\n")
- (setq node-name (buffer-substring beginning (point)))
- (if (= 0 (length node-name))
- (error "No node name on this line.")
- (insert "."))))
- (t (error "No node name on this line.")))
- ;; Search for node that matches node name, and copy the section title.
- (if (re-search-forward
- (concat
- "^@node[ \t]+"
- node-name
- ".*\n" ; match node line
- "\\("
- "\\(\\(^@c \\|^@comment\\).*\n\\)" ; match comment line, if any
- "\\|" ; or
- "\\(^@ifinfo[ ]*\n\\)" ; ifinfo line, if any
- "\\)?")
- nil t)
- (progn
- (setq title
- (buffer-substring
- ;; skip over section type
- (progn (forward-word 1)
- ;; and over spaces
- (skip-chars-forward " \t")
- (point))
- (progn (end-of-line)
- (skip-chars-backward " \t")
- (point)))))
- (error "Cannot find node to match node name in menu entry.")))
- ;; Return point to the menu and insert the title.
- (end-of-line)
- (delete-region
- (point)
- (save-excursion (skip-chars-backward " \t") (point)))
- (indent-to texinfo-column-for-description 2)
- (save-excursion (insert title))))
-
-
-;;; 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 (re-search-forward "\\* \\(.*::\\|.*: [^.,\t\n]+[.,\t]\\)"
- (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-existing 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")
- (let ((case-fold-search t))
- (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
- (or (re-search-forward "^@node" nil t)
- (error "Too few nodes for a master menu!"))
- (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 in %s ...first updating all nodes... "
- (buffer-name))
- (sleep-for 2)
- (push-mark (point-max) t)
- (goto-char (point-min))
- (texinfo-update-node t)
-
- (message "Updating all menus in %s ... " (buffer-name))
- (sleep-for 2)
- (push-mark (point-max) t)
- (goto-char (point-min))
- (texinfo-make-menu t)))
-
- (message "Now making the master menu in %s... " (buffer-name))
- (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))
-
- (if (re-search-forward texinfo-master-menu-header nil t)
- (progn
- (goto-char (match-beginning 0))
- (insert "\n")
- (delete-blank-lines)
- (goto-char (point-min))))
-
- (re-search-forward "^@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))
- ;; Insert a master menu only after `Top' node and before next node
- ;; \(or include file if there is no next node\).
- (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\\|^@include") (point))))
- (if (not (re-search-forward "^@menu" first-chapter t))
- (error
- "Buffer lacks ordinary `Top' menu in which to insert master.")))
- (beginning-of-line)
- (delete-region ; buffer must have ordinary top menu
- (point)
- (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))
-
- ;; Only insert detailed master menu if there is one....
- (if (car (car 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."
- (let ((case-fold-search t))
- (save-excursion
- (if (re-search-backward
- (concat
- "\\(^@top"
- "\\|" ; or
- texinfo-section-types-regexp ; all other section types
- "\\)")
- nil
- t)
- (progn
- (beginning-of-line)
- (forward-word 1) ; skip over section type
- (skip-chars-forward " \t") ; and over spaces
- (buffer-substring
- (point)
- (progn (end-of-line) (point))))
- ""))))
-
-(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)
- ;; handle multi-line description
- (if (not (re-search-backward "^\\* " nil t))
- (error "No entries in menu."))
- (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."
- (let ((case-fold-search t))
- (save-excursion
- (cond
- ((re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
-;;; Following search limit by cph but causes a bug
-;;; (save-excursion
-;;; (end-of-line)
-;;; (point))
- nil
- t)
- "top")
- ((re-search-forward texinfo-section-types-regexp nil t)
- (buffer-substring-no-properties
- (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."
- (let ((case-fold-search t))
- (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."
- (let ((case-fold-search t))
- ;; !! Known bug: if section immediately follows top node, this
- ;; returns the beginning of the buffer as the beginning of the
- ;; higher level 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."
- (let ((case-fold-search t))
- (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
- ;; Never finds end of level above chapter so goes to end.
- (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.")
-
-;; We used to look for just sub, but that found @subtitle.
-(defvar texinfo-section-types-regexp
- "^@\\(chapter \\|sect\\|subs\\|subh\\|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
-
-;;;###autoload
-(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 32."
-
- (interactive "P")
- (if (not region-p)
- ;; update a single node
- (let ((auto-fill-function nil) (auto-fill-hook nil))
- (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-function nil)
- (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 (point) t)
- (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.")))))
-
-;;;###autoload
-(defun texinfo-every-node-update ()
- "Update every node in a Texinfo file."
- (interactive)
- (save-excursion
- (push-mark (point-max) t)
- (goto-char (point-min))
- ;; Using the mark to pass bounds this way
- ;; is kludgy, but it's not worth fixing. -- rms.
- (let ((mark-active t))
- (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
- (let ((initial (texinfo-copy-next-section-title)))
- ;; This is not clean. Use `interactive' to read the arg.
- (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 (use no @, commas, colons, or apostrophes): "
- initial)))
- (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."
- (let ((eol-point (save-excursion (end-of-line) (point))))
- (if (search-forward "," eol-point t)
- (delete-region (1- (point)) eol-point)))
- (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."
- (let ((case-fold-search t))
- (cond ((eq direction 'next)
- (forward-line 3) ; skip over current node
- ;; Search for section commands accompanied by node lines;
- ;; ignore section commands in the middle of nodes.
- (if (re-search-forward
- ;; A `Top' node is never a next pointer, so won't find it.
- (concat
- ;; Match node line.
- "\\(^@node\\).*\n"
- ;; Match comment or ifinfo line, if any
- "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
- (eval
- (cdr (assoc level texinfo-update-menu-same-level-regexps))))
- end
- t)
- 'normal
- 'no-pointer))
- ((eq direction 'previous)
- (if (re-search-backward
- (concat
- "\\("
- ;; Match node line.
- "\\(^@node\\).*\n"
- ;; Match comment or ifinfo line, if any
- "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
- (eval
- (cdr (assoc level texinfo-update-menu-same-level-regexps)))
- "\\|"
- ;; Match node line.
- "\\(^@node\\).*\n"
- ;; Match comment or ifinfo line, if any
- "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
- (eval
- (cdr (assoc level texinfo-update-menu-higher-regexps)))
- "\\|"
- ;; Handle `Top' node specially.
- "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
- "\\)")
- beginning
- t)
- 'normal
- 'no-pointer))
- ((eq direction 'up)
- (if (re-search-backward
- (concat
- "\\("
- ;; Match node line.
- "\\(^@node\\).*\n"
- ;; Match comment or ifinfo line, if any
- "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
- (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
- "\\|"
- ;; Handle `Top' node specially.
- "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
- "\\)")
- (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.)
-
-;;;###autoload
-(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)
- ;; update a single node
- (let ((auto-fill-function nil) (auto-fill-hook nil))
- (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-function nil)
- (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 (point) t)
- (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."
- (let ((case-fold-search t))
- (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 (beginning end &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 "r\nP")
-
- ;; Use marker; after inserting node lines, leave point at end of
- ;; region and mark at beginning.
-
- (let (beginning-marker end-marker title last-section-position)
-
- ;; Save current position on mark ring and set mark to end.
- (push-mark end t)
- (setq end-marker (mark-marker))
-
- (goto-char beginning)
- (while (re-search-forward
- texinfo-section-types-regexp
- end-marker
- 'end)
- ;; Copy title if desired.
- (if title-p
- (progn
- (beginning-of-line)
- (forward-word 1)
- (skip-chars-forward " \t")
- (setq title (buffer-substring
- (point)
- (save-excursion (end-of-line) (point))))))
- ;; Insert node line if necessary.
- (if (re-search-backward
- "^@node"
- ;; Avoid finding previous node line if node lines are close.
- (or last-section-position
- (save-excursion (forward-line -2) (point))) t)
- ;; @node is present, and point at beginning of that line
- (forward-word 1) ; Leave point just after @node.
- ;; Else @node missing; insert one.
- (beginning-of-line) ; Beginning of `@section' line.
- (insert "@node\n")
- (backward-char 1)) ; Leave point just after `@node'.
- ;; Insert title if desired.
- (if title-p
- (progn
- (skip-chars-forward " \t")
- ;; Use regexp based on what info looks for
- ;; (alternatively, use "[a-zA-Z]+");
- ;; this means we only insert a title if none exists.
- (if (not (looking-at "[^,\t\n ]+"))
- (progn
- (beginning-of-line)
- (forward-word 1)
- (insert " " title)
- (message "Inserted title %s ... " title)))))
- ;; Go forward beyond current section title.
- (re-search-forward texinfo-section-types-regexp
- (save-excursion (forward-line 3) (point)) t)
- (setq last-section-position (point))
- (forward-line 1))
-
- ;; Leave point at end of region, mark at beginning.
- (set-mark beginning)
-
- (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 ((node-end (or
- (save-excursion
- (if (re-search-forward "\\(^@node\\)" nil t)
- (match-beginning 0)))
- (point-max))))
- (if (re-search-forward texinfo-section-types-regexp node-end t)
- (progn
- (beginning-of-line)
- ;; 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.
-
-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 and this function
-; does not fill it; however a comment tells you how to do so.
-; You would use the title field if you wanted to insert titles in the
-; description slot of a menu as a description.
-
- (let ((case-fold-search t)
- 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
- (prog1 "" (forward-line 1)))
- ;; Use following to insert section titles automatically.
- ;; (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
- (prog1 "" (forward-line 1)))
- ;; Use following to insert section titles automatically.
- ;; (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)
-
- ;; Update other menus and nodes if requested.
- (if update-everything (texinfo-all-menus-update t))
-
- (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))
-
- (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
- ;; Every menu entry starts with a star and a space.
- (insert "* ")
-
- ;; Insert the node name (and menu entry name, if present).
- (let ((node-part (car (car menu-list))))
- (if (stringp node-part)
- ;; "Double colon" entry line; menu entry and node name are the same,
- (insert (format "%s::" node-part))
- ;; "Single colon" entry line; menu entry and node name are different.
- (insert (format "%s: %s." (car node-part) (cdr node-part)))))
-
- ;; Insert the description, if present.
- (if (cdr (car menu-list))
- (progn
- ;; Move to right place.
- (indent-to texinfo-column-for-description 2)
- ;; Insert description.
- (insert (format "%s" (cdr (car menu-list))))))
-
- (insert "\n") ; end this menu 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 the `Top' level node pointers and the 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 in addition to creating or updating
-pointers in the first @node line in each included file and creating or
-updating the `Top' level node pointers of the outer file. This does
-not create or update other menus and 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. Also, update 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 (cons
- (read-string
- "Name of outer `include' file: "
- (buffer-file-name))
- (cond ((not current-prefix-arg)
- '(nil nil))
- ((listp current-prefix-arg)
- '(t nil)) ; make-master-menu
- ((numberp current-prefix-arg)
- '(t t)) ; update-everything
- )))
-
- (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)))))
-
- ;; Remove unwanted extra lines.
- (save-excursion
- (goto-char (point-min))
-
- (re-search-forward "^@menu")
- (forward-line -1)
- (insert "\n") ; Ensure at least one blank line.
- (delete-blank-lines)
-
- (re-search-forward "^@end menu")
- (forward-line 1)
- (insert "\n") ; Ensure at least one blank line.
- (delete-blank-lines))
-
- (message "Multiple files updated."))
-
-
-;;; Place `provide' at end of file.
-(provide 'texnfo-upd)
-
-;;; texnfo-upd.el ends here
diff --git a/lisp/textmodes/text-mode.el b/lisp/textmodes/text-mode.el
deleted file mode 100644
index ab8895e9872..00000000000
--- a/lisp/textmodes/text-mode.el
+++ /dev/null
@@ -1,172 +0,0 @@
-;;; text-mode.el --- text mode, and its idiosyncratic commands.
-
-;; Copyright (C) 1985, 1992, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides the fundamental text mode documented in the
-;; Emacs user's manual.
-
-;;; Code:
-
-(defvar text-mode-syntax-table nil
- "Syntax table used while in text mode.")
-
-(defvar text-mode-abbrev-table nil
- "Abbrev table used while in text mode.")
-(define-abbrev-table 'text-mode-abbrev-table ())
-
-(if text-mode-syntax-table
- ()
- (setq text-mode-syntax-table (make-syntax-table))
- (modify-syntax-entry ?\" ". " text-mode-syntax-table)
- (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.")
-
-(if text-mode-map
- ()
- (setq text-mode-map (make-sparse-keymap))
- (define-key text-mode-map "\e\t" 'ispell-complete-word)
- (define-key text-mode-map "\t" 'tab-to-tab-stop)
- (define-key text-mode-map "\es" 'center-line)
- (define-key text-mode-map "\eS" 'center-paragraph))
-
-
-;(defun non-saved-text-mode ()
-; "Like text-mode, but delete auto save file when file is saved for real."
-; (text-mode)
-; (make-local-variable 'delete-auto-save-files)
-; (setq delete-auto-save-files t))
-
-(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',
-if that value is non-nil."
- (interactive)
- (kill-all-local-variables)
- (use-local-map text-mode-map)
- (setq mode-name "Text")
- (setq major-mode 'text-mode)
- (setq local-abbrev-table text-mode-abbrev-table)
- (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.")
-
-(if indented-text-mode-map
- ()
- ;; Make different definition for TAB before the one in text-mode-map, but
- ;; share the rest.
- (let ((newmap (make-sparse-keymap)))
- (define-key newmap "\t" 'indent-relative)
- (setq indented-text-mode-map (nconc newmap text-mode-map))))
-
-(defun indented-text-mode ()
- "Major mode for editing text with indented paragraphs.
-In this mode, paragraphs are delimited only by blank lines.
-You can thus get the benefit of adaptive filling
- (see the variable `adaptive-fill-mode').
-\\{indented-text-mode-map}
-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)
- (use-local-map text-mode-map)
- (define-abbrev-table 'text-mode-abbrev-table ())
- (setq local-abbrev-table text-mode-abbrev-table)
- (set-syntax-table text-mode-syntax-table)
- (make-local-variable 'indent-line-function)
- (setq indent-line-function 'indent-relative-maybe)
- (make-local-variable 'paragraph-start)
- (setq paragraph-start (concat "$\\|" page-delimiter))
- (make-local-variable 'paragraph-separate)
- (setq paragraph-separate paragraph-start)
- (use-local-map indented-text-mode-map)
- (setq mode-name "Indented Text")
- (setq major-mode 'indented-text-mode)
- (run-hooks 'text-mode-hook 'indented-text-mode-hook))
-
-(defun center-paragraph ()
- "Center each nonblank line in the paragraph at or after point.
-See `center-line' for more info."
- (interactive)
- (save-excursion
- (forward-paragraph)
- (or (bolp) (newline 1))
- (let ((end (point)))
- (backward-paragraph)
- (center-region (point) end))))
-
-(defun center-region (from to)
- "Center each nonblank line starting in the region.
-See `center-line' for more info."
- (interactive "r")
- (if (> from to)
- (let ((tem to))
- (setq to from from tem)))
- (save-excursion
- (save-restriction
- (narrow-to-region from to)
- (goto-char from)
- (while (not (eobp))
- (or (save-excursion (skip-chars-forward " \t") (eolp))
- (center-line))
- (forward-line 1)))))
-
-(defun center-line (&optional nlines)
- "Center the line point is on, within the width specified by `fill-column'.
-This means adjusting the indentation so that it equals
-the distance between the end of the text and `fill-column'.
-The argument NLINES says how many lines to center."
- (interactive "P")
- (if nlines (setq nlines (prefix-numeric-value nlines)))
- (while (not (eq nlines 0))
- (save-excursion
- (let ((lm (current-left-margin))
- line-length)
- (beginning-of-line)
- (delete-horizontal-space)
- (end-of-line)
- (delete-horizontal-space)
- (setq line-length (current-column))
- (if (> (- fill-column lm line-length) 0)
- (indent-line-to
- (+ lm (/ (- fill-column lm line-length) 2))))))
- (cond ((null nlines)
- (setq nlines 0))
- ((> nlines 0)
- (setq nlines (1- nlines))
- (forward-line 1))
- ((< nlines 0)
- (setq nlines (1+ nlines))
- (forward-line -1)))))
-
-;;; text-mode.el ends here
diff --git a/lisp/textmodes/two-column.el b/lisp/textmodes/two-column.el
deleted file mode 100644
index 1fa8474c9b9..00000000000
--- a/lisp/textmodes/two-column.el
+++ /dev/null
@@ -1,624 +0,0 @@
-;;; two-column.el --- minor mode for editing of two-column text
-
-;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389
-;; Adapted-By: ESR, Daniel Pfeiffer
-
-;; Esperanto: English:
-
-;; ^Ci dosiero estas ero de GNU Emacs. This file is part of GNU Emacs.
-
-;; GNU Emacs estas libera programaro; GNU Emacs is free software; you can
-;; vi povas disdoni ^gin kaj/a^u modifi redistribute it and/or modify it
-;; ^gin sub la kondi^coj de la GNU under the terms of the GNU General
-;; ^Generala Publika Licenco kiel pub- Public License as published by the
-;; likigita far la Liberprogramara Fon- Free Software Foundation; either
-;; da^jo; a^u eldono 2a, a^u (la^u via version 2, or (at your option) any
-;; elekto) ajna posta eldono. later version.
-
-;; GNU Emacs estas disdonata en la GNU Emacs is distributed in the hope
-;; espero ke ^gi estos utila, sed SEN that it will be useful, but WITHOUT
-;; IA GARANTIO; sen e^c la implicita ANY WARRANTY; without even the
-;; garantio de VENDEBLECO a^u PRETECO implied warranty of MERCHANTABILITY
-;; POR DETERMINITA CELO. Vidu la GNU or FITNESS FOR A PARTICULAR PURPOSE.
-;; ^Generala Publika Licenco por plenaj See the GNU General Public License
-;; detaloj. for more details.
-
-;; Vi devus ricevinti kopion de la GNU You should have received a copy of
-;; ^Generala Publika Licenco kune kun the GNU General Public License along
-;; GNU Emacs; vidu la dosieron COPYING. with GNU Emacs; see the file
-;; Alikaze skribu al la COPYING. If not, write to the
-
-;; Free Software Foundation, 59 Temple Place - Suite 330
-;; Boston, MA 02111-1307, USA.
-
-
-;;; Komentario: Commentary:
-
-;; Tiu programaro ebligas vin redakti This package gives you the ability
-;; dukolumnan tekston. to edit text in a two-column format.
-
-
-;; Vi havas tri eblecojn por eki tiun You have three ways to start up this
-;; mal^cefan modalon. ^Ciu donas al vi minor mode. Each gives you a
-;; horizontale disigatan fenestron, si- horizontally split window similar to
-;; milan al fina apareco de via teksto: the final outcome of your text:
-
-
-;; f2 2 asocias novan bufron nomatan associates a new buffer called
-;; C-x 6 2 same, sed kun 2C/ anta^u. the same, but with 2C/
-;; prepended.
-
-;; f2 b asocias alian bufron. Vi povas associates another buffer.
-;; C-x 6 b anka^u asocii dataron, se vi This can be used to associate a
-;; ^jus anta^ue faris C-x C-f. file if you just did C-x C-f.
-
-;; f2 s disigas jam dukolumnan tekston splits a two-column text into
-;; C-x 6 s en du bufroj ekde la nuna two buffers from the current
-;; linio, kaj je la nuna kolumno. line and at the current column.
-;; La anta^uaj signoj (ofte The preceding characters (often
-;; tabeligilo a^u |) estas la tab or |) are the column
-;; kolumna disiganto. Linioj kiuj separator. Lines that don't
-;; ne enhavas ilin ne estas have them won't be separated.
-;; disigitaj. Kiel la kvara kaj Like the fourth and fifth line
-;; la kvina linio se vi disigas if you split this file from
-;; ^ci dataron ekde la unua angla the first english word.
-;; vorto.
-
-;; Se vi volas meti longajn liniojn If you include long lines, i.e which
-;; (ekz. programerojn) en la kunigotan will span both columns (eg. source
-;; tekston, ili devas esti en la code), they should be in what will
-;; estonte unua kolumno. La alia devas be the first column, with the
-;; havi vakajn linion apud ili. associated buffer having empty lines
-;; next to them.
-
-;; Averto: en Emacs kiam vi ^san^gas la Attention: in Emacs when you change
-;; ^cefan modalon, la mal^cefaj modaloj the major mode, the minor modes are
-;; estas anka^u elmemorigitaj. Tiu- also purged from memory. In that
-;; okaze vi devas religi la du bufrojn case you must reassociate the two
-;; per iu C-x 6-ordono, ekz. C-x 6 b. buffers with any C-x 6-command, e.g.
-;; C-x 6 b.
-
-;; Kiam vi estos kontenta de la When you have edited both buffers to
-;; rezulto, vi kunmetos la du kolumnojn your content, you merge them with
-;; per C-x 6 1. Se vi poste vidas C-x 6 1. If you then see a problem,
-;; problemon, vi neniigu la kunmeton you undo the merge with C-x u and
-;; per C-x u kaj plue modifu la du continue to edit the two buffers.
-;; bufrojn. Kiam vi ne plu volas tajpi When you no longer want to edit in
-;; dukolumne, vi eliru el la mal^cefa two columns, you turn off the minor
-;; modalo per C-x 6 d. mode with C-x 6 d.
-
-
-;; Aldone al dukolumna redaktado, ek- In addition to two-column editing of
-;; zemple por skribi dulingvan tekston text, for example for writing a
-;; flank-al-flanke kiel ^ci tiu, aliaj bilingual text side-by-side as shown
-;; interesaj uzoj trovitas por tiu mal- here, other interesting uses have
-;; ^cefa modalo: been found for this minor mode:
-
-;; Vi povas disigi la kolumnojn per {+} You can separate the columns with
-;; ajna pla^ca ^ceno starigante {+} any string that pleases you, by
-;; `2C-separator'. Ekzemple "{+} " {+} setting `2C-separator'. For example
-;; por amuzi^gi. f2 s a^u C-x 6 s {+} "{+} " if you'd like to have fun.
-;; traktas tiujn kun prefiksa {+} f2 s or C-x 6 s handles these with a
-;; argumento kiu signifas la longon {+} prefix argument that means the
-;; de tia ^ceno. {+} desired length of such a string.
-
-
-;; Programistoj eble ^satus la eblecon Programmers might like the ability
-;; forspliti la komentarian kolumnon de to split off the comment column of a
-;; dosiero kiel la sekvanta. Vi povas file that looks like the following.
-;; rearan^gigi la paragrafon. La pro- You can fill-paragraph the comment.
-;; blemo estas ke koda^jo tuj lar- The problem is, code quickly gets
-;; ^gi^gas, tiel ke vi bezonas pli rather wide, so you need to use a
-;; mallar^gan komentarian kolumnon. narrower comment column. Code lines
-;; Koda^jaj linioj tra `comment-column' that reach beyond `comment-column'
-;; ne problemas, krom ke vi ne vidos are no problem, except that you
-;; iliajn finojn dum redaktado. won't see their end during editing.
-
-
-;; BEGIN -- This is just some meaningless
-;; FOR i IN 1..10 LOOP -- code in Ada, that runs foobar
-;; foobar( i ); -- once for each argument from one
-;; END LOOP; -- to ten, and then we're already
-;; END; -- through with it.
-
-;; Pli bone ankora^u, vi povas pozici- Better yet, you can put the point
-;; i^gi anta^u "This", tajpi M-3 f2 s before "This", type M-3 f2 s
-;; kiu igas "-- " la separigilon inter which makes "-- " the separator
-;; senkomentaria Ada bufro kaj nur- between a no-comments Ada buffer,
-;; teksta komentaria bufro. Kiam vi and a plain text comment buffer.
-;; denove kuni^gos ilin, ^ciu nevaka When you put them back together,
-;; linio de l' dua kolumno denove every non-empty line of the 2nd
-;; anta^uhavos "-- ". column will again be preceded by
-;; "-- ".
-
-
-;;; Code:
-
-
-;; Lucid patch
-(or (fboundp 'frame-width)
- (fset 'frame-width 'screen-width))
-
-
-;;;;; Set up keymap ;;;;;
-
-(defvar 2C-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "2" '2C-two-columns)
- (define-key map [f2] '2C-two-columns)
- (define-key map "b" '2C-associate-buffer)
- (define-key map "s" '2C-split)
- map)
- "Keymap for commands for setting up two-column mode.")
-
-
-
-;;;###autoload (autoload '2C-command "two-column" () t 'keymap)
-(fset '2C-command 2C-mode-map)
-
-;;;###autoload
-;; This one is for historical reasons and simple keyboards, it is not
-;; at all mnemonic. All usual sequences containing 2 were used, and
-;; f2 could not be set up in a standard way under Emacs 18.
-(global-set-key "\C-x6" '2C-command)
-
-
-;;;###autoload
-(global-set-key [f2] '2C-command)
-
-
-(defvar 2C-minor-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "1" '2C-merge)
- (define-key map "d" '2C-dissociate)
- (define-key map "o" '2C-associated-buffer)
- (define-key map "\^m" '2C-newline)
- (define-key map "|" '2C-toggle-autoscroll)
- (define-key map "{" '2C-shrink-window-horizontally)
- (define-key map "}" '2C-enlarge-window-horizontally)
- map)
- "Keymap for commands for use in two-column mode.")
-
-
-(setq minor-mode-map-alist
- (cons (cons '2C-mode
- (let ((map (make-sparse-keymap)))
- (substitute-key-definition '2C-command 2C-minor-mode-map
- map (current-global-map))
- (substitute-key-definition 'enlarge-window-horizontally
- '2C-enlarge-window-horizontally
- map (current-global-map))
- (substitute-key-definition 'shrink-window-horizontally
- '2C-shrink-window-horizontally
- map (current-global-map))
- map))
- minor-mode-map-alist))
-
-;;;;; variable declarations ;;;;;
-
-;; Markers seem to be the only buffer-id not affected by renaming a buffer.
-;; This nevertheless loses when a buffer is killed. The variable-name is
-;; required by `describe-mode'.
-(defvar 2C-mode nil
- "Marker to the associated buffer, if non-nil.")
-(make-variable-buffer-local '2C-mode)
-(put '2C-mode 'permanent-local t)
-
-
-
-(setq minor-mode-alist (cons '(2C-mode " 2C") minor-mode-alist))
-
-
-
-;; rearranged, so that the pertinent info will show in 40 columns
-(defvar 2C-mode-line-format
- '("-%*- %15b --" (-3 . "%p") "--%[(" mode-name
- minor-mode-alist "%n" mode-line-process ")%]%-")
- "*Value of mode-line-format for a buffer in two-column minor mode.")
-
-
-(defvar 2C-other-buffer-hook 'text-mode
- "*Hook run in new buffer when it is associated with current one.")
-
-
-(defvar 2C-separator ""
- "*A string inserted between the two columns when merging.
-This gets set locally by \\[2C-split].")
-(put '2C-separator 'permanent-local t)
-
-
-
-(defvar 2C-window-width 40
- "*The width of the first column. (Must be at least `window-min-width')
-This value is local for every buffer that sets it.")
-(make-variable-buffer-local '2C-window-width)
-(put '2C-window-width 'permanent-local t)
-
-
-
-(defvar 2C-beyond-fill-column 4
- "*Base for calculating `fill-column' for a buffer in two-column minor mode.
-The value of `fill-column' becomes `2C-window-width' for this buffer
-minus this value.")
-
-
-
-(defvar 2C-autoscroll t
- "If non-nil, Emacs attempts to keep the two column's buffers aligned.")
-
-
-
-(defvar 2C-autoscroll-start nil)
-(make-variable-buffer-local '2C-autoscroll-start)
-
-;;;;; base functions ;;;;;
-
-;; The access method for the other buffer. This tries to remedy against
-;; lost local variables and lost buffers.
-(defun 2C-other (&optional req)
- (or (if 2C-mode
- (or (prog1
- (marker-buffer 2C-mode)
- (setq mode-line-format 2C-mode-line-format))
- ;; The associated buffer somehow got killed.
- (progn
- ;; The other variables may later be useful if the user
- ;; reestablishes the association.
- (kill-local-variable '2C-mode)
- (kill-local-variable 'mode-line-format)
- nil)))
- (if req (error "You must first set two-column minor mode."))))
-
-
-
-;; function for setting up two-column minor mode in a buffer associated
-;; with the buffer pointed to by the marker other.
-(defun 2C-mode (other)
- "Minor mode for independently editing two columns.
-This is set up for two associated buffers by the three commands bound
-to \\[2C-two-columns] , \\[2C-associate-buffer] and \\[2C-split].
-Turning on two-column mode calls the value of the variable `2C-mode-hook',
-if that value is non-nil.
-
-These buffers can be edited separately, for example with `fill-paragraph'.
-If you want to disable parallel scrolling temporarily, use \\[2C-toggle-autoscroll] .
-
-If you include long lines, i.e which will span both columns (eg.
-source code), they should be in what will be the first column, with
-the associated buffer having empty lines next to them.
-
-Potential uses are writing bilingual texts, or editing the comments of a
-source code. See the file lisp/two-column.el for detailed examples.
-
-You have the following commands at your disposal:
-
-\\[2C-two-columns] Rearrange screen with current buffer first
-\\[2C-associate-buffer] Reassociate buffer after changing major mode
-\\[shrink-window-horizontally], \\[enlarge-window-horizontally] Shrink, enlarge current column
-\\[2C-associated-buffer] Switch to associated buffer at same point
-\\[2C-newline] Insert newline(s) in both buffers at same point
-\\[2C-merge] Merge both buffers
-\\[2C-dissociate] Dissociate the two buffers
-
-These keybindings can be customized in your ~/.emacs by `2C-mode-map',
-`2C-minor-mode-map' and by binding `2C-command' to some prefix.
-
-The appearance of the screen can be customized by the variables
-`2C-window-width', `2C-beyond-fill-column', `2C-mode-line-format' and
-`truncate-partial-width-windows'."
- (make-local-hook 'post-command-hook)
- (add-hook 'post-command-hook '2C-autoscroll nil t)
- (setq fill-column (- 2C-window-width
- 2C-beyond-fill-column)
- mode-line-format 2C-mode-line-format
- 2C-mode other)
- (run-hooks '2C-mode-hook))
-
-
-
-;;;###autoload
-(defun 2C-two-columns (&optional buffer)
- "Split current window vertically for two-column editing.
-When called the first time, associates a buffer with the current
-buffer in two-column minor mode (see \\[describe-mode] ).
-Runs `2C-other-buffer-hook' in the new buffer.
-When called again, restores the screen layout with the current buffer
-first and the associated buffer to its right."
- (interactive "P")
- ;; first go to full width, so that we can certainly split into two windows
- (if (< (window-width) (frame-width))
- (enlarge-window 99999 t))
- (split-window-horizontally
- (max window-min-width (min 2C-window-width
- (- (frame-width) window-min-width))))
- (if (2C-other)
- (progn
- (other-window 1)
- (switch-to-buffer (2C-other))
- (other-window -1)
- (if 2C-autoscroll
- (2C-toggle-autoscroll t)))
-
- (2C-mode (prog1 (point-marker)
- (other-window 1)
- (switch-to-buffer
- (or buffer
- (generate-new-buffer (concat "2C/" (buffer-name)))))
- (or buffer
- (run-hooks '2C-other-buffer-hook))))
-
- (2C-mode (prog1 (point-marker)
- (other-window -1)))))
-
-
-
-;;;###autoload
-(defun 2C-associate-buffer ()
- "Associate another buffer with this one in two-column minor mode.
-Can also be used to associate a just previously visited file, by
-accepting the proposed default buffer.
-
-\(See \\[describe-mode] .)"
- (interactive)
- (let ((b1 (current-buffer))
- (b2 (or (2C-other)
- (read-buffer "Associate buffer: " (other-buffer)))))
- (save-excursion
- (setq 2C-mode nil)
- (set-buffer b2)
- (and (2C-other)
- (not (eq b1 (2C-other)))
- (error "Buffer already associated with buffer `%s'."
- (buffer-name (2C-other))))
- (setq b1 (and (assq '2C-window-width (buffer-local-variables))
- 2C-window-width)))
- ; if other buffer has a local width, adjust here too
- (if b1 (setq 2C-window-width (- (frame-width) b1)))
- (2C-two-columns b2)))
-
-
-
-;;;###autoload
-(defun 2C-split (arg)
- "Split a two-column text at point, into two buffers in two-column minor mode.
-Point becomes the local value of `2C-window-width'. Only lines that
-have the ARG same preceding characters at that column get split. The
-ARG preceding characters without any leading whitespace become the local
-value for `2C-separator'. This way lines that continue across both
-columns remain untouched in the first buffer.
-
-This function can be used with a prototype line, to set up things. You
-write the first line of each column and then split that line. E.g.:
-
-First column's text sSs Second column's text
- \\___/\\
- / \\
- 5 character Separator You type M-5 \\[2C-split] with the point here.
-
-\(See \\[describe-mode] .)"
- (interactive "*p")
- (and (2C-other)
- (if (y-or-n-p (concat "Overwrite associated buffer `"
- (buffer-name (2C-other))
- "'? "))
- (save-excursion
- (set-buffer (2C-other))
- (erase-buffer))
- (signal 'quit nil)))
- (let ((point (point))
- ; make next-line always come back to same column
- (goal-column (current-column))
- ; a counter for empty lines in other buffer
- (n (1- (count-lines (point-min) (point))))
- chars other)
- (save-excursion
- (backward-char arg)
- (setq chars (buffer-substring (point) point))
- (skip-chars-forward " \t" point)
- (make-local-variable '2C-separator)
- (setq 2C-separator (buffer-substring (point) point)
- 2C-window-width (current-column)))
- (2C-two-columns)
- (setq other (2C-other))
- ; now we're ready to actually split
- (save-excursion
- (while (not (eobp))
- (if (not (and (= (current-column) goal-column)
- (string= chars
- (buffer-substring (point)
- (save-excursion
- (backward-char arg)
- (point))))))
- (setq n (1+ n))
- (setq point (point))
- (backward-char arg)
- (skip-chars-backward " \t")
- (delete-region point (point))
- (setq point (point))
- (insert-char ?\n n)
- (append-to-buffer other point (progn (end-of-line)
- (if (eobp)
- (point)
- (1+ (point)))))
- (delete-region point (point))
- (setq n 0))
- (next-line 1)))))
-
-
-
-
-(defun 2C-dissociate ()
- "Turn off two-column minor mode in current and associated buffer.
-If the associated buffer is unmodified and empty, it is killed."
- (interactive)
- (let ((buffer (current-buffer)))
- (save-excursion
- (and (2C-other)
- (set-buffer (2C-other))
- (or (not (2C-other))
- (eq buffer (2C-other)))
- (if (and (not (buffer-modified-p))
- (eobp) (bobp))
- (kill-buffer nil)
- (kill-local-variable '2C-mode)
- (kill-local-variable '2C-window-width)
- (kill-local-variable '2C-separator)
- (kill-local-variable 'mode-line-format)
- (kill-local-variable 'fill-column))))
- (kill-local-variable '2C-mode)
- (kill-local-variable '2C-window-width)
- (kill-local-variable '2C-separator)
- (kill-local-variable 'mode-line-format)
- (kill-local-variable 'fill-column)))
-
-
-
-;; this doesn't use yank-rectangle, so that the first column can
-;; contain long lines
-(defun 2C-merge ()
- "Merges the associated buffer with the current buffer.
-They get merged at the column, which is the value of `2C-window-width',
-i.e. usually at the vertical window separator. This separator gets
-replaced with white space. Beyond that the value of `2C-separator' gets
-inserted on merged lines. The two columns are thus pasted side by side,
-in a single text. If the other buffer is not displayed to the left of
-this one, then this one becomes the left column.
-
-If you want `2C-separator' on empty lines in the second column,
-you should put just one space in them. In the final result, you can strip
-off trailing spaces with \\[beginning-of-buffer] \\[replace-regexp] [ SPC TAB ] + $ RET RET"
- (interactive)
- (and (> (car (window-edges)) 0) ; not touching left edge of screen
- (eq (window-buffer (previous-window))
- (2C-other t))
- (other-window -1))
- (save-excursion
- (let ((b1 (current-buffer))
- (b2 (2C-other t))
- string)
- (goto-char (point-min))
- (set-buffer b2)
- (goto-char (point-min))
- (while (not (eobp))
- (setq string (buffer-substring (point)
- (progn (end-of-line) (point))))
- (or (eobp)
- (forward-char)) ; next line
- (set-buffer b1)
- (if (string= string "")
- ()
- (end-of-line)
- (indent-to-column 2C-window-width)
- (insert 2C-separator string))
- (next-line 1) ; add one if necessary
- (set-buffer b2))))
- (if (< (window-width) (frame-width))
- (enlarge-window 99999 t)))
-
-;;;;; utility functions ;;;;;
-
-(defun 2C-associated-buffer ()
- "Switch to associated buffer."
- (interactive)
- (let ((line (+ (count-lines (point-min) (point))
- (if (bolp) 1 0)))
- (col (if (eolp) (if (bolp) 0) (current-column))))
- (if (get-buffer-window (2C-other t))
- (select-window (get-buffer-window (2C-other)))
- (switch-to-buffer (2C-other)))
- (newline (goto-line line))
- (if col
- (move-to-column col)
- (end-of-line 1))))
-
-(defun 2C-newline (arg)
- "Insert ARG newlines in both buffers."
- (interactive "P")
- (save-window-excursion
- (2C-associated-buffer)
- (newline arg))
- (newline arg))
-
-(defun 2C-toggle-autoscroll (arg)
- "Toggle autoscrolling, or set it iff prefix ARG is non-nil and positive.
-When autoscrolling is turned on, this also realigns the two buffers."
- (interactive "P")
- ;(sit-for 0)
- (setq 2C-autoscroll-start (window-start))
- (if (setq 2C-autoscroll (if arg
- (>= (prefix-numeric-value arg) 0)
- (not 2C-autoscroll)))
- (select-window
- (prog1 (selected-window)
- (message "Autoscrolling is on.")
- (setq arg (count-lines (point-min) (window-start)))
- (if (get-buffer-window (2C-other t))
- (progn
- (select-window (get-buffer-window (2C-other)))
- (setq arg (- arg (count-lines (point-min) (window-start))))
- ;; make sure that other buffer has enough lines
- (save-excursion
- (insert-char ?\n
- (- arg (count-lines (window-start)
- (goto-char (point-max)))
- -1)))
- (scroll-up arg)))))
- (message "Autoscrolling is off.")))
-
-
-
-(defun 2C-autoscroll ()
- (if 2C-autoscroll
- ;; catch a mouse scroll on non-selected scrollbar
- (select-window
- (prog1 (selected-window)
- (and (consp last-command-char)
- (not (eq (selected-window)
- (car (car (cdr last-command-char)))))
- (select-window (car (car (cdr last-command-char)))))
- ;; In some cases scrolling causes an error, but post-command-hook
- ;; shouldn't, and should always stay in the original window
- (condition-case ()
- (and (or 2C-autoscroll-start (2C-toggle-autoscroll t) nil)
- (/= (window-start) 2C-autoscroll-start)
- (2C-other)
- (get-buffer-window (2C-other))
- (let ((lines (count-lines (window-start)
- 2C-autoscroll-start)))
- (if (< (window-start) 2C-autoscroll-start)
- (setq lines (- lines)))
- (setq 2C-autoscroll-start (window-start))
- (select-window (get-buffer-window (2C-other)))
- ;; make sure that other buffer has enough lines
- (save-excursion
- (insert-char
- ?\n (- lines (count-lines (window-start)
- (goto-char (point-max)))
- -1)))
- (scroll-up lines)
- (setq 2C-autoscroll-start (window-start))))
- (error))))))
-
-
-
-(defun 2C-enlarge-window-horizontally (arg)
- "Make current window ARG columns wider."
- (interactive "p")
- (enlarge-window arg t)
- (and (2C-other)
- (setq 2C-window-width (+ 2C-window-width arg))
- (set-buffer (2C-other))
- (setq 2C-window-width (- 2C-window-width arg))))
-
-(defun 2C-shrink-window-horizontally (arg)
- "Make current window ARG columns narrower."
- (interactive "p")
- (2C-enlarge-window-horizontally (- arg)))
-
-
-
-(provide 'two-column)
-
-;;; two-column.el ends here
diff --git a/lisp/textmodes/underline.el b/lisp/textmodes/underline.el
deleted file mode 100644
index 91dc0b2c2f8..00000000000
--- a/lisp/textmodes/underline.el
+++ /dev/null
@@ -1,63 +0,0 @@
-;;; underline.el --- insert/remove underlining (done by overstriking) in Emacs.
-
-;; Copyright (C) 1985 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: wp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package deals with the primitive form of underlining
-;; consisting of prefixing each character with "_\^h". The entry
-;; point `underline-region' performs such underlining on a region.
-;; The entry point `ununderline-region' removes it.
-
-;;; Code:
-
-;;;###autoload
-(defun underline-region (start end)
- "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."
- (interactive "r")
- (save-excursion
- (let ((end1 (make-marker)))
- (move-marker end1 (max start end))
- (goto-char (min start end))
- (while (< (point) end1)
- (or (looking-at "[_\^@- ]")
- (insert "_\b"))
- (forward-char 1)))))
-
-;;;###autoload
-(defun ununderline-region (start end)
- "Remove all underlining (overstruck underscores) in the region.
-Called from program, takes two arguments START and END
-which specify the range to operate on."
- (interactive "r")
- (save-excursion
- (let ((end1 (make-marker)))
- (move-marker end1 (max start end))
- (goto-char (min start end))
- (while (re-search-forward "_\b\\|\b_" end1 t)
- (delete-char -2)))))
-
-;;; underline.el ends here
diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el
deleted file mode 100644
index fda31632aa1..00000000000
--- a/lisp/thingatpt.el
+++ /dev/null
@@ -1,256 +0,0 @@
-;;; thingatpt.el --- Get the `thing' at point
-
-;; Copyright (C) 1991,92,93,94,95,1996 Free Software Foundation, Inc.
-
-;; Author: Mike Williams <mikew@gopher.dosli.govt.nz>
-;; Keywords: extensions, matching, mouse
-;; Created: Thu Mar 28 13:48:23 1991
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;;; Commentary:
-
-;; This file provides routines for getting the "thing" at the location of
-;; point, whatever that "thing" happens to be. The "thing" is defined by
-;; its beginning and end positions in the buffer.
-;;
-;; The function bounds-of-thing-at-point finds the beginning and end
-;; positions by moving first forward to the end of the "thing", and then
-;; backwards to the beginning. By default, it uses the corresponding
-;; forward-"thing" operator (eg. forward-word, forward-line).
-;;
-;; Special cases are allowed for using properties associated with the named
-;; "thing":
-;;
-;; forward-op Function to call to skip forward over a "thing" (or
-;; with a negative argument, backward).
-;;
-;; beginning-op Function to call to skip to the beginning of a "thing".
-;; end-op Function to call to skip to the end of a "thing".
-;;
-;; Reliance on existing operators means that many `things' can be accessed
-;; without further code: eg.
-;; (thing-at-point 'line)
-;; (thing-at-point 'page)
-
-;;; Code:
-
-(provide 'thingatpt)
-
-;; Basic movement
-
-;;;###autoload
-(defun forward-thing (thing &optional n)
- "Move forward to the end of the next THING."
- (let ((forward-op (or (get thing 'forward-op)
- (intern-soft (format "forward-%s" thing)))))
- (if (fboundp forward-op)
- (funcall forward-op (or n 1))
- (error "Can't determine how to move over a %s" thing))))
-
-;; General routines
-
-;;;###autoload
-(defun bounds-of-thing-at-point (thing)
- "Determine the start and end buffer locations for the THING at point.
-THING is a symbol which specifies the kind of syntactic entity you want.
-Possibilities include `symbol', `list', `sexp', `defun', `filename', `url',
-`word', `sentence', `whitespace', `line', `page' and others.
-
-See the file `thingatpt.el' for documentation on how to define
-a symbol as a valid THING.
-
-The value is a cons cell (START . END) giving the start and end positions
-of the textual entity that was found."
- (let ((orig (point)))
- (condition-case nil
- (save-excursion
- (let ((end (progn
- (funcall
- (or (get thing 'end-op)
- (function (lambda () (forward-thing thing 1)))))
- (point)))
- (beg (progn
- (funcall
- (or (get thing 'beginning-op)
- (function (lambda () (forward-thing thing -1)))))
- (point))))
- (if (and beg end (<= beg orig) (<= orig end))
- (cons beg end)
- ;; Try a second time, moving backward first and forward after,
- ;; so that we can find a thing that ends at ORIG.
- (let ((beg (progn
- (funcall
- (or (get thing 'beginning-op)
- (function (lambda () (forward-thing thing -1)))))
- (point)))
- (end (progn
- (funcall
- (or (get thing 'end-op)
- (function (lambda () (forward-thing thing 1)))))
- (point))))
- (if (and beg end (<= beg orig) (<= orig end))
- (cons beg end))))))
- (error nil))))
-
-;;;###autoload
-(defun thing-at-point (thing)
- "Return the THING at point.
-THING is a symbol which specifies the kind of syntactic entity you want.
-Possibilities include `symbol', `list', `sexp', `defun', `filename', `url',
-`word', `sentence', `whitespace', `line', `page' and others.
-
-See the file `thingatpt.el' for documentation on how to define
-a symbol as a valid THING."
- (let ((bounds (bounds-of-thing-at-point thing)))
- (if bounds
- (buffer-substring (car bounds) (cdr bounds)))))
-
-;; Go to beginning/end
-
-(defun beginning-of-thing (thing)
- (let ((bounds (bounds-of-thing-at-point thing)))
- (or bounds (error "No %s here" thing))
- (goto-char (car bounds))))
-
-(defun end-of-thing (thing)
- (let ((bounds (bounds-of-thing-at-point thing)))
- (or bounds (error "No %s here" thing))
- (goto-char (cdr bounds))))
-
-;; Special cases
-
-;; Lines
-
-;; bolp will be false when you click on the last line in the buffer
-;; and it has no final newline.
-
-(put 'line 'beginning-op
- (function (lambda () (if (bolp) (forward-line -1) (beginning-of-line)))))
-
-;; Sexps
-
-(defun in-string-p ()
- (let ((orig (point)))
- (save-excursion
- (beginning-of-defun)
- (nth 3 (parse-partial-sexp (point) orig)))))
-
-(defun end-of-sexp ()
- (let ((char-syntax (char-syntax (char-after (point)))))
- (if (or (eq char-syntax ?\))
- (and (eq char-syntax ?\") (in-string-p)))
- (forward-char 1)
- (forward-sexp 1))))
-
-(put 'sexp 'end-op 'end-of-sexp)
-
-;; Lists
-
-(put 'list 'end-op (function (lambda () (up-list 1))))
-(put 'list 'beginning-op 'backward-sexp)
-
-;; Filenames and URLs
-
-(defvar thing-at-point-file-name-chars "~/A-Za-z0-9---_.${}#%,:"
- "Characters allowable in filenames.")
-
-(put 'filename 'end-op
- '(lambda () (skip-chars-forward thing-at-point-file-name-chars)))
-(put 'filename 'beginning-op
- '(lambda () (skip-chars-backward thing-at-point-file-name-chars)))
-
-(defvar thing-at-point-url-chars "~/A-Za-z0-9---_@$%&=.,"
- "Characters allowable in a URL.")
-
-(put 'url 'end-op
- '(lambda () (skip-chars-forward (concat ":" thing-at-point-url-chars))
- (skip-chars-backward ".,:")))
-(put 'url 'beginning-op
- '(lambda ()
- (skip-chars-backward thing-at-point-url-chars)
- (or (= (preceding-char) ?:)
- (error "No URL here"))
- (forward-char -1)
- (skip-chars-backward "a-zA-Z")))
-
-;; Whitespace
-
-(defun forward-whitespace (arg)
- (interactive "p")
- (if (natnump arg)
- (re-search-forward "[ \t]+\\|\n" nil nil arg)
- (while (< arg 0)
- (if (re-search-backward "[ \t]+\\|\n" nil nil)
- (or (eq (char-after (match-beginning 0)) 10)
- (skip-chars-backward " \t")))
- (setq arg (1+ arg)))))
-
-;; Buffer
-
-(put 'buffer 'end-op 'end-of-buffer)
-(put 'buffer 'beginning-op 'beginning-of-buffer)
-
-;; Symbols
-
-(defun forward-symbol (arg)
- (interactive "p")
- (if (natnump arg)
- (re-search-forward "\\(\\sw\\|\\s_\\)+" nil nil arg)
- (while (< arg 0)
- (if (re-search-backward "\\(\\sw\\|\\s_\\)+" nil nil)
- (skip-syntax-backward "w_"))
- (setq arg (1+ arg)))))
-
-;; Syntax blocks
-
-(defun forward-same-syntax (&optional arg)
- (interactive "p")
- (while (< arg 0)
- (skip-syntax-backward
- (char-to-string (char-syntax (char-after (1- (point))))))
- (setq arg (1+ arg)))
- (while (> arg 0)
- (skip-syntax-forward (char-to-string (char-syntax (char-after (point)))))
- (setq arg (1- arg))))
-
-;; Aliases
-
-(defun word-at-point () (thing-at-point 'word))
-(defun sentence-at-point () (thing-at-point 'sentence))
-
-(defun read-from-whole-string (str)
- "Read a lisp expression from STR.
-Signal an error if the entire string was not used."
- (let* ((read-data (read-from-string str))
- (more-left
- (condition-case nil
- (progn (read-from-string (substring str (cdr read-data)))
- t)
- (end-of-file nil))))
- (if more-left
- (error "Can't read whole string")
- (car read-data))))
-
-(defun form-at-point (&optional thing pred)
- (let ((sexp (condition-case nil
- (read-from-whole-string (thing-at-point (or thing 'sexp)))
- (error nil))))
- (if (or (not pred) (funcall pred sexp)) sexp)))
-
-(defun sexp-at-point () (form-at-point 'sexp))
-(defun symbol-at-point () (form-at-point 'sexp 'symbolp))
-(defun number-at-point () (form-at-point 'sexp 'numberp))
-(defun list-at-point () (form-at-point 'list 'listp))
-
-;; thingatpt.el ends here.
diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el
deleted file mode 100644
index 85351d741f8..00000000000
--- a/lisp/time-stamp.el
+++ /dev/null
@@ -1,346 +0,0 @@
-;;; time-stamp.el --- Maintain last change time stamps in files edited by Emacs
-
-;; Copyright 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-;; Maintainer's Time-stamp: <1996-08-13 14:03:17 gildea>
-;; Maintainer: Stephen Gildea <gildea@lcs.mit.edu>
-;; Keywords: tools
-
-;; This 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 2, or (at your option)
-;; any later version.
-
-;; This 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 GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; A template in a file can be updated with a new time stamp when
-;; you save the file. For example:
-;; static char *ts = "sdmain.c Time-stamp: <1996-08-13 10:20:51 gildea>";
-;; See the top of `time-stamp.el' for another example.
-
-;; To use time-stamping, add this line to your .emacs file:
-;; (add-hook 'write-file-hooks 'time-stamp)
-;; Now any time-stamp templates in your files will be updated automatically.
-
-;; See the documentation for the functions `time-stamp'
-;; and `time-stamp-toggle-active' for details.
-
-;;; Change Log:
-
-;; Originally based on the 19 Dec 88 version of
-;; date.el by John Sturdy <mcvax!harlqn.co.uk!jcgs@uunet.uu.net>
-;; Version 2, January 1995: replaced functions with %-escapes
-;; $Id: time-stamp.el,v 1.23 1996/12/17 00:19:01 rms Exp rms $
-
-;;; Code:
-
-(defvar time-stamp-active t
- "*Non-nil to enable time-stamping of buffers by \\[time-stamp].
-Can be toggled by \\[time-stamp-toggle-active].
-See also the variable `time-stamp-warn-inactive'.")
-
-(defvar time-stamp-warn-inactive t
- "Non-nil to have \\[time-stamp] warn if a buffer did not get time-stamped.
-A warning is printed if `time-stamp-active' is nil and the buffer contains
-a time stamp template that would otherwise have been updated.")
-
-(defvar time-stamp-old-format-warn 'ask
- "Action to take if `time-stamp-format' is an old-style list.
-If `error', the format is not used. If `ask', the user is queried about
-using the time-stamp-format. If `warn', a warning is displayed.
-If nil, no notification is given.")
-
-(defvar time-stamp-format "%Y-%m-%d %H:%M:%S %u"
- "*Format of the string inserted by \\[time-stamp].
-The value may be a string or a list. Lists are supported only for
-backward compatibility; see variable `time-stamp-old-format-warn'.
-
-A string is used with `format-time-string'.
-For example, to get the format used by the `date' command,
-use \"%3a %3b %2d %H:%M:%S %Z %y\".
-
-In addition to the features of `format-time-string',
-you can use the following %-constructs:
-
-%f file name without directory
-%F full file name
-%h mail host name
-%s system name
-%u user's login name")
-
-;;; Do not change time-stamp-line-limit, time-stamp-start, or
-;;; time-stamp-end in your .emacs or you will be incompatible
-;;; with other people's files! If you must change them,
-;;; do so only in the local variables section of the file itself.
-
-
-(defvar time-stamp-line-limit 8 ;Do not change!
- "Lines of a file searched; positive counts from start, negative from end.
-The patterns `time-stamp-start' and `time-stamp-end' must be found on one
-of the first (last) `time-stamp-line-limit' lines of the file for the
-file to be time-stamped by \\[time-stamp].
-
-Do not change `time-stamp-line-limit', `time-stamp-start', or
-`time-stamp-end' for yourself or you will be incompatible
-with other people's files! If you must change them for some application,
-do so in the local variables section of the time-stamped file itself.")
-
-
-(defvar time-stamp-start "Time-stamp:[ \t]+\\\\?[\"<]+" ;Do not change!
- "Regexp after which the time stamp is written by \\[time-stamp].
-See also the variables `time-stamp-end' and `time-stamp-line-limit'.
-
-Do not change `time-stamp-line-limit', `time-stamp-start', or
-`time-stamp-end' for yourself or you will be incompatible
-with other people's files! If you must change them for some application,
-do so in the local variables section of the time-stamped file itself.")
-
-
-(defvar time-stamp-end "\\\\?[\">]" ;Do not change!
- "Regexp marking the text after the time stamp.
-\\[time-stamp] deletes the text between the first match of `time-stamp-start'
-and the following match of `time-stamp-end' on the same line,
-then writes the time stamp specified by `time-stamp-format' between them.
-
-Do not change `time-stamp-line-limit', `time-stamp-start', or
-`time-stamp-end' for yourself or you will be incompatible
-with other people's files! If you must change them for some application,
-do so in the local variables section of the time-stamped file itself.")
-
-
-
-;;;###autoload
-(defun time-stamp ()
- "Update the time stamp string in the buffer.
-A template in a file can be automatically updated with a new time stamp
-every time you save the file. Add this line to your .emacs file:
- (add-hook 'write-file-hooks 'time-stamp)
-Normally the template must appear in the first 8 lines of a file and
-look like one of the following:
- Time-stamp: <>
- Time-stamp: \" \"
-The time stamp is written between the brackets or quotes:
- Time-stamp: <1996-07-18 10:20:51 gildea>
-Only updates the time stamp if the variable `time-stamp-active' is non-nil.
-The format of the time stamp is set by the variable `time-stamp-format'.
-The variables `time-stamp-line-limit', `time-stamp-start',
-and `time-stamp-end' control finding the template."
- (interactive)
- (let ((case-fold-search nil)
- (start nil)
- (end nil)
- search-limit)
- (save-excursion
- (save-restriction
- (widen)
- (cond ((> time-stamp-line-limit 0)
- (goto-char (setq start (point-min)))
- (forward-line time-stamp-line-limit)
- (setq search-limit (point)))
- (t
- (goto-char (setq search-limit (point-max)))
- (forward-line time-stamp-line-limit)
- (setq start (point))))
- (goto-char start)
- (while (and (< (point) search-limit)
- (not end)
- (re-search-forward time-stamp-start search-limit 'move))
- (setq start (point))
- (end-of-line)
- (let ((line-end (point)))
- (goto-char start)
- (if (re-search-forward time-stamp-end line-end 'move)
- (setq end (match-beginning 0)))))))
- (if end
- (progn
- ;; do all warnings outside save-excursion
- (cond
- ((not time-stamp-active)
- (if time-stamp-warn-inactive
- ;; don't signal an error in a write-file-hook
- (progn
- (message "Warning: time-stamp-active is off; did not time-stamp buffer.")
- (sit-for 1))))
- ((not (and (stringp time-stamp-start)
- (stringp time-stamp-end)))
- (message "time-stamp-start or time-stamp-end is not a string")
- (sit-for 1))
- (t
- (let ((new-time-stamp (time-stamp-string)))
- (if (stringp new-time-stamp)
- (save-excursion
- (save-restriction
- (widen)
- (delete-region start end)
- (goto-char start)
- (insert new-time-stamp)
- (setq end (point))
- ;; remove any tabs used to format time stamp
- (goto-char start)
- (if (search-forward "\t" end t)
- (untabify start end)))))))))))
- ;; be sure to return nil so can be used on write-file-hooks
- nil)
-
-;;;###autoload
-(defun time-stamp-toggle-active (&optional arg)
- "Toggle `time-stamp-active', setting whether \\[time-stamp] updates a buffer.
-With arg, turn time stamping on if and only if arg is positive."
- (interactive "P")
- (setq time-stamp-active
- (if (null arg)
- (not time-stamp-active)
- (> (prefix-numeric-value arg) 0)))
- (message "time-stamp is now %s." (if time-stamp-active "active" "off")))
-
-(defconst time-stamp-no-file "(no file)"
- "String to use when the buffer is not associated with a file.")
-
-(defun time-stamp-string-preprocess (format)
- "Process occurrences in FORMAT of %f, %F, %h, %s and %u.
-These are replaced with the file name (nondirectory part),
-full file name, host name for mail, system name, and user name.
-Do not alter other %-combinations, and do detect %%."
- (let ((result "") (pos 0) (case-fold-search nil)
- (file (or buffer-file-name "(no file)")))
- (while (string-match "%[%uhfFs]" format pos)
- (setq result (concat result (substring format pos (match-beginning 0))))
- (let ((char (aref format (1+ (match-beginning 0)))))
- (cond ((= char ?%)
- (setq result (concat result "%%")))
- ((= char ?u)
- (setq result (concat result (user-login-name))))
- ((= char ?f)
- (setq result (concat result (file-name-nondirectory file))))
- ((= char ?f)
- (setq result (concat result file)))
- ((= char ?s)
- (setq result (concat result (system-name))))
- ((= char ?h)
- (setq result (concat result (time-stamp-mail-host-name))))))
- (setq pos (match-end 0)))
- (concat result (substring format pos))))
-
-(defun time-stamp-string ()
- "Generate the new string to be inserted by \\[time-stamp]."
- (if (stringp time-stamp-format)
- (format-time-string (time-stamp-string-preprocess time-stamp-format)
- (current-time))
- ;; handle version 1 compatibility
- (cond ((or (eq time-stamp-old-format-warn 'error)
- (and (eq time-stamp-old-format-warn 'ask)
- (not (y-or-n-p "Use non-string time-stamp-format? "))))
- (message "Warning: no time-stamp: time-stamp-format not a string")
- (sit-for 1)
- nil)
- (t
- (cond ((eq time-stamp-old-format-warn 'warn)
- (message "Obsolescent time-stamp-format type; should be string")
- (sit-for 1)))
- (time-stamp-fconcat time-stamp-format " ")))))
-
-(defconst time-stamp-no-file "(no file)"
- "String to use when the buffer is not associated with a file.")
-
-(defun time-stamp-mail-host-name ()
- "Return the name of the host where the user receives mail.
-This is the value of `mail-host-address' if bound and a string,
-otherwise the value of the function system-name."
- (or (and (boundp 'mail-host-address)
- (stringp mail-host-address)
- mail-host-address)
- (system-name)))
-
-;;; the rest of this file is for version 1 compatibility
-
-(defun time-stamp-fconcat (list sep)
- "Similar to (mapconcat 'funcall LIST SEP) but LIST allows literals.
-If an element of LIST is a symbol, it is funcalled to get the string to use;
-the separator SEP is used between two strings obtained by funcalling a
-symbol. Otherwise the element itself is inserted; no separator is used
-around literals."
- (let ((return-string "")
- (insert-sep-p nil))
- (while list
- (cond ((symbolp (car list))
- (if insert-sep-p
- (setq return-string (concat return-string sep)))
- (setq return-string (concat return-string (funcall (car list))))
- (setq insert-sep-p t))
- (t
- (setq return-string (concat return-string (car list)))
- (setq insert-sep-p nil)))
- (setq list (cdr list)))
- return-string))
-
-;;; Some functions used in time-stamp-format
-
-;;; Could generate most of a message-id with
-;;; '(time-stamp-yymmdd "" time-stamp-hhmm "@" time-stamp-mail-host-name)
-
-;;; pretty form, suitable for a title page
-
-(defun time-stamp-month-dd-yyyy ()
- "Return the current date as a string in \"Month DD, YYYY\" form."
- (format-time-string "%B %e, %Y"))
-
-(defun time-stamp-dd/mm/yyyy ()
- "Return the current date as a string in \"DD/MM/YYYY\" form."
- (format-time-string "%d/%m/%Y"))
-
-;;; same as __DATE__ in ANSI C
-
-(defun time-stamp-mon-dd-yyyy ()
- "Return the current date as a string in \"Mon DD YYYY\" form.
-The first character of DD is space if the value is less than 10."
- (format-time-string "%b %d %Y"))
-
-;;; RFC 822 date
-
-(defun time-stamp-dd-mon-yy ()
- "Return the current date as a string in \"DD Mon YY\" form."
- (format-time-string "%d %b %y"))
-
-;;; RCS 3 date
-
-(defun time-stamp-yy/mm/dd ()
- "Return the current date as a string in \"YY/MM/DD\" form."
- (format-time-string "%y/%m/%d"))
-
-;;; RCS 5 date
-
-(defun time-stamp-yyyy/mm/dd ()
- "Return the current date as a string in \"YYYY/MM/DD\" form."
- (format-time-string "%Y/%m/%d"))
-
-;;; ISO 8601 date
-
-(defun time-stamp-yyyy-mm-dd ()
- "Return the current date as a string in \"YYYY-MM-DD\" form."
- (format-time-string "%Y-%m-%d"))
-
-(defun time-stamp-yymmdd ()
- "Return the current date as a string in \"YYMMDD\" form."
- (format-time-string "%y%m%d"))
-
-(defun time-stamp-hh:mm:ss ()
- "Return the current time as a string in \"HH:MM:SS\" form."
- (format-time-string "%T"))
-
-(defun time-stamp-hhmm ()
- "Return the current time as a string in \"HHMM\" form."
- (format-time-string "%H%M"))
-
-(provide 'time-stamp)
-
-;;; time-stamp.el ends here
diff --git a/lisp/time.el b/lisp/time.el
deleted file mode 100644
index 8f798fa08a2..00000000000
--- a/lisp/time.el
+++ /dev/null
@@ -1,220 +0,0 @@
-;;; time.el --- display time and load in mode line of Emacs.
-
-;; Copyright (C) 1985, 86, 87, 93, 94, 1996 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Facilities to display current time/date and a new-mail indicator
-;; in the Emacs mode line. The single entry point is `display-time'.
-
-;;; Code:
-
-(defvar display-time-mail-file nil
- "*File name of mail inbox file, for indicating existence of new mail.
-Non-nil and not a string means don't check for mail. nil means use
-default, which is system-dependent, and is the same as used by Rmail.")
-
-;;;###autoload
-(defvar display-time-day-and-date nil "\
-*Non-nil means \\[display-time] should display day and date as well as time.")
-
-(defvar display-time-timer nil)
-
-(defvar display-time-interval 60
- "*Seconds between updates of time in the mode line.")
-
-(defvar display-time-24hr-format nil
- "*Non-nil indicates time should be displayed as hh:mm, 0 <= hh <= 23.
-Nil means 1 <= hh <= 12, and an AM/PM suffix is used.")
-
-(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.")
-
-(defvar display-time-server-down-time nil
- "Time when mail file's file system was recorded to be down.
-If that file system seems to be up, the value is nil.")
-
-;;;###autoload
-(defun display-time ()
- "Enable display of time, load level, and mail flag in mode lines.
-This display updates automatically every minute.
-If `display-time-day-and-date' is non-nil, the current day and date
-are displayed as well.
-This runs the normal hook `display-time-hook' after each update."
- (interactive)
- (display-time-mode 1))
-
-;;;###autoload
-(defun display-time-mode (arg)
- "Toggle display of time, load level, and mail flag in mode lines.
-With a numeric arg, enable this display if arg is positive.
-
-When this display is enabled, it updates automatically every minute.
-If `display-time-day-and-date' is non-nil, the current day and date
-are displayed as well.
-This runs the normal hook `display-time-hook' after each update."
- (interactive "P")
- (let ((on (if (null arg)
- (not display-time-timer)
- (> (prefix-numeric-value arg) 0))))
- (and display-time-timer (cancel-timer display-time-timer))
- (setq display-time-timer nil)
- (setq display-time-string "")
- (or global-mode-string (setq global-mode-string '("")))
- (if on
- (progn
- (or (memq 'display-time-string global-mode-string)
- (setq global-mode-string
- (append global-mode-string '(display-time-string))))
- ;; Set up the time timer.
- (setq display-time-timer
- (run-at-time t display-time-interval
- 'display-time-event-handler))
- ;; Make the time appear right away.
- (display-time-update)
- ;; When you get new mail, clear "Mail" from the mode line.
- (add-hook 'rmail-after-get-new-mail-hook
- 'display-time-event-handler))
- (remove-hook 'rmail-after-get-new-mail-hook
- 'display-time-event-handler))))
-
-
-(defvar display-time-format
- (concat
- (if display-time-day-and-date
- "%a %b %e" "")
- (if display-time-24hr-format "%H:%m" "%-I:%M%p"))
- "*A string specifying the format for displaying the time in the mode line.
-See the function `format-time-string' for an explanation of
-how to write this string.")
-
-(defvar display-time-string-forms
- '((format-time-string display-time-format now)
- load
- (if mail " Mail" ""))
- "*A list of expressions governing display of the time in the mode line.
-For most purposes, you can control the time format using `display-time-format'
-which is a more standard interface.
-
-This expression is a list of expressions that can involve the keywords
-`load', `day', `month', and `year', `12-hours', `24-hours', `minutes',
-`seconds', all numbers in string form, and `monthname', `dayname', `am-pm',
-and `time-zone' all alphabetic strings, and `mail' a true/nil value.
-
-For example, the form
-
- '((substring year -2) \"/\" month \"/\" day
- \" \" 24-hours \":\" minutes \":\" seconds
- (if time-zone \" (\") time-zone (if time-zone \")\")
- (if mail \" Mail\" \"\"))
-
-would give mode line times like `94/12/30 21:07:48 (UTC)'.")
-
-(defun display-time-event-handler ()
- (display-time-update)
- ;; Do redisplay right now, if no input pending.
- (sit-for 0)
- (let* ((current (current-time))
- (timer display-time-timer)
- ;; Compute the time when this timer will run again, next.
- (next-time (timer-relative-time
- (list (aref timer 1) (aref timer 2) (aref timer 3))
- (* 5 (aref timer 4)) 0)))
- ;; If the activation time is far in the past,
- ;; skip executions until we reach a time in the future.
- ;; This avoids a long pause if Emacs has been suspended for hours.
- (or (> (nth 0 next-time) (nth 0 current))
- (and (= (nth 0 next-time) (nth 0 current))
- (> (nth 1 next-time) (nth 1 current)))
- (and (= (nth 0 next-time) (nth 0 current))
- (= (nth 1 next-time) (nth 1 current))
- (> (nth 2 next-time) (nth 2 current)))
- (progn
- (timer-set-time timer (timer-next-integral-multiple-of-time
- current display-time-interval)
- display-time-interval)
- (timer-activate timer)))))
-
-;; Update the display-time info for the mode line
-;; but don't redisplay right now. This is used for
-;; things like Rmail `g' that want to force an update
-;; which can wait for the next redisplay.
-(defun display-time-update ()
- (let* ((now (current-time))
- (time (current-time-string now))
- (load (condition-case ()
- (if (zerop (car (load-average))) ""
- (let ((str (format " %03d" (car (load-average)))))
- (concat (substring str 0 -2) "." (substring str -2))))
- (error "")))
- (mail-spool-file (or display-time-mail-file
- (getenv "MAIL")
- (concat rmail-spool-directory
- (user-login-name))))
- (mail (and (stringp mail-spool-file)
- (or (null display-time-server-down-time)
- ;; If have been down for 20 min, try again.
- (> (- (nth 1 (current-time))
- display-time-server-down-time)
- 1200))
- (let ((start-time (current-time)))
- (prog1
- (display-time-file-nonempty-p mail-spool-file)
- (if (> (- (nth 1 (current-time)) (nth 1 start-time))
- 20)
- ;; Record that mail file is not accessible.
- (setq display-time-server-down-time
- (nth 1 (current-time)))
- ;; Record that mail file is accessible.
- (setq display-time-server-down-time nil))))))
- (24-hours (substring time 11 13))
- (hour (string-to-int 24-hours))
- (12-hours (int-to-string (1+ (% (+ hour 11) 12))))
- (am-pm (if (>= hour 12) "pm" "am"))
- (minutes (substring time 14 16))
- (seconds (substring time 17 19))
- (time-zone (car (cdr (current-time-zone now))))
- (day (substring time 8 10))
- (year (substring time 20 24))
- (monthname (substring time 4 7))
- (month
- (cdr
- (assoc
- monthname
- '(("Jan" . "1") ("Feb" . "2") ("Mar" . "3") ("Apr" . "4")
- ("May" . "5") ("Jun" . "6") ("Jul" . "7") ("Aug" . "8")
- ("Sep" . "9") ("Oct" . "10") ("Nov" . "11") ("Dec" . "12")))))
- (dayname (substring time 0 3)))
- (setq display-time-string
- (mapconcat 'eval display-time-string-forms ""))
- ;; This is inside the let binding, but we are not going to document
- ;; what variables are available.
- (run-hooks 'display-time-hook))
- (force-mode-line-update))
-
-(defun display-time-file-nonempty-p (file)
- (and (file-exists-p file)
- (< 0 (nth 7 (file-attributes (file-chase-links file))))))
-
-;;; time.el ends here
diff --git a/lisp/timer.el b/lisp/timer.el
deleted file mode 100644
index 1a343755661..00000000000
--- a/lisp/timer.el
+++ /dev/null
@@ -1,453 +0,0 @@
-;;; timer.el --- run a function with args at some time in future.
-
-;; Copyright (C) 1996 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package gives you the capability to run Emacs Lisp commands at
-;; specified times in the future, either as one-shots or periodically.
-
-;;; Code:
-
-;; Layout of a timer vector:
-;; [triggered-p high-seconds low-seconds usecs repeat-delay
-;; function args idle-delay]
-
-(defun timer-create ()
- "Create a timer object."
- (let ((timer (make-vector 8 nil)))
- (aset timer 0 t)
- timer))
-
-(defun timerp (object)
- "Return t if OBJECT is a timer."
- (and (vectorp object) (= (length object) 8)))
-
-(defun timer-set-time (timer time &optional delta)
- "Set the trigger time of TIMER to TIME.
-TIME must be in the internal format returned by, e.g., `current-time'.
-If optional third argument DELTA is a non-zero integer, make the timer
-fire repeatedly that many seconds apart."
- (or (timerp timer)
- (error "Invalid timer"))
- (aset timer 1 (car time))
- (aset timer 2 (if (consp (cdr time)) (car (cdr time)) (cdr time)))
- (aset timer 3 (or (and (consp (cdr time)) (consp (cdr (cdr time)))
- (nth 2 time))
- 0))
- (aset timer 4 (and (numberp delta) (> delta 0) delta))
- timer)
-
-(defun timer-set-idle-time (timer secs &optional repeat)
- "Set the trigger idle time of TIMER to SECS.
-If optional third argument REPEAT is non-nil, make the timer
-fire each time Emacs is idle for that many seconds."
- (or (timerp timer)
- (error "Invalid timer"))
- (aset timer 1 0)
- (aset timer 2 0)
- (aset timer 3 0)
- (timer-inc-time timer secs)
- (aset timer 4 repeat)
- timer)
-
-(defun timer-next-integral-multiple-of-time (time secs)
- "Yield the next value after TIME that is an integral multiple of SECS.
-More precisely, the next value, after TIME, that is an integral multiple
-of SECS seconds since the epoch. SECS may be a fraction."
- (let ((time-base (ash 1 16)))
- (if (fboundp 'atan)
- ;; Use floating point, taking care to not lose precision.
- (let* ((float-time-base (float time-base))
- (million 1000000.0)
- (time-usec (+ (* million
- (+ (* float-time-base (nth 0 time))
- (nth 1 time)))
- (nth 2 time)))
- (secs-usec (* million secs))
- (mod-usec (mod time-usec secs-usec))
- (next-usec (+ (- time-usec mod-usec) secs-usec))
- (time-base-million (* float-time-base million)))
- (list (floor next-usec time-base-million)
- (floor (mod next-usec time-base-million) million)
- (floor (mod next-usec million))))
- ;; Floating point is not supported.
- ;; Use integer arithmetic, avoiding overflow if possible.
- (let* ((mod-sec (mod (+ (* (mod time-base secs)
- (mod (nth 0 time) secs))
- (nth 1 time))
- secs))
- (next-1-sec (+ (- (nth 1 time) mod-sec) secs)))
- (list (+ (nth 0 time) (floor next-1-sec time-base))
- (mod next-1-sec time-base)
- 0)))))
-
-(defun timer-relative-time (time secs &optional usecs)
- "Advance TIME by SECS seconds and optionally USECS microseconds.
-SECS may be a fraction."
- (let ((high (car time))
- (low (if (consp (cdr time)) (nth 1 time) (cdr time)))
- (micro (if (numberp (car-safe (cdr-safe (cdr time))))
- (nth 2 time)
- 0)))
- ;; Add
- (if usecs (setq micro (+ micro usecs)))
- (if (floatp secs)
- (setq micro (+ micro (floor (* 1000000 (- secs (floor secs)))))))
- (setq low (+ low (floor secs)))
-
- ;; Normalize
- (setq low (+ low (/ micro 1000000)))
- (setq micro (mod micro 1000000))
- (setq high (+ high (/ low 65536)))
- (setq low (logand low 65535))
-
- (list high low (and (/= micro 0) micro))))
-
-(defun timer-inc-time (timer secs &optional usecs)
- "Increment the time set in TIMER by SECS seconds and USECS microseconds.
-SECS may be a fraction."
- (let ((time (timer-relative-time
- (list (aref timer 1) (aref timer 2) (aref timer 3))
- secs
- usecs)))
- (aset timer 1 (nth 0 time))
- (aset timer 2 (nth 1 time))
- (aset timer 3 (or (nth 2 time) 0))))
-
-(defun timer-set-time-with-usecs (timer time usecs &optional delta)
- "Set the trigger time of TIMER to TIME.
-TIME must be in the internal format returned by, e.g., `current-time'.
-If optional third argument DELTA is a non-zero integer, make the timer
-fire repeatedly that many seconds apart."
- (or (timerp timer)
- (error "Invalid timer"))
- (aset timer 1 (car time))
- (aset timer 2 (if (consp (cdr time)) (car (cdr time)) (cdr time)))
- (aset timer 3 usecs)
- (aset timer 4 (and (numberp delta) (> delta 0) delta))
- timer)
-
-(defun timer-set-function (timer function &optional args)
- "Make TIMER call FUNCTION with optional ARGS when triggering."
- (or (timerp timer)
- (error "Invalid timer"))
- (aset timer 5 function)
- (aset timer 6 args)
- timer)
-
-(defun timer-activate (timer)
- "Put TIMER on the list of active timers."
- (if (and (timerp timer)
- (integerp (aref timer 1))
- (integerp (aref timer 2))
- (integerp (aref timer 3))
- (aref timer 5))
- (let ((timers timer-list)
- last)
- ;; Skip all timers to trigger before the new one.
- (while (and timers
- (or (> (aref timer 1) (aref (car timers) 1))
- (and (= (aref timer 1) (aref (car timers) 1))
- (> (aref timer 2) (aref (car timers) 2)))
- (and (= (aref timer 1) (aref (car timers) 1))
- (= (aref timer 2) (aref (car timers) 2))
- (> (aref timer 3) (aref (car timers) 3)))))
- (setq last timers
- timers (cdr timers)))
- ;; Insert new timer after last which possibly means in front of queue.
- (if last
- (setcdr last (cons timer timers))
- (setq timer-list (cons timer timers)))
- (aset timer 0 nil)
- (aset timer 7 nil)
- nil)
- (error "Invalid or uninitialized timer")))
-
-(defun timer-activate-when-idle (timer)
- "Arrange to activate TIMER whenever Emacs is next idle."
- (if (and (timerp timer)
- (integerp (aref timer 1))
- (integerp (aref timer 2))
- (integerp (aref timer 3))
- (aref timer 5))
- (let ((timers timer-idle-list)
- last)
- ;; Skip all timers to trigger before the new one.
- (while (and timers
- (or (> (aref timer 1) (aref (car timers) 1))
- (and (= (aref timer 1) (aref (car timers) 1))
- (> (aref timer 2) (aref (car timers) 2)))
- (and (= (aref timer 1) (aref (car timers) 1))
- (= (aref timer 2) (aref (car timers) 2))
- (> (aref timer 3) (aref (car timers) 3)))))
- (setq last timers
- timers (cdr timers)))
- ;; Insert new timer after last which possibly means in front of queue.
- (if last
- (setcdr last (cons timer timers))
- (setq timer-idle-list (cons timer timers)))
- (aset timer 0 t)
- (aset timer 7 t)
- nil)
- (error "Invalid or uninitialized timer")))
-
-;;;###autoload
-(defalias 'disable-timeout 'cancel-timer)
-;;;###autoload
-(defun cancel-timer (timer)
- "Remove TIMER from the list of active timers."
- (or (timerp timer)
- (error "Invalid timer"))
- (setq timer-list (delq timer timer-list))
- (setq timer-idle-list (delq timer timer-idle-list))
- nil)
-
-;;;###autoload
-(defun cancel-function-timers (function)
- "Cancel all timers scheduled by `run-at-time' which would run FUNCTION."
- (interactive "aCancel timers of function: ")
- (let ((tail timer-list))
- (while tail
- (if (eq (aref (car tail) 5) function)
- (setq timer-list (delq (car tail) timer-list)))
- (setq tail (cdr tail))))
- (let ((tail timer-idle-list))
- (while tail
- (if (eq (aref (car tail) 5) function)
- (setq timer-idle-list (delq (car tail) timer-idle-list)))
- (setq tail (cdr tail)))))
-
-;; Set up the common handler for all timer events. Since the event has
-;; the timer as parameter we can still distinguish. Note that using
-;; special-event-map ensures that event timer events that arrive in the
-;; middle of a key sequence being entered are still handled correctly.
-(define-key special-event-map [timer-event] 'timer-event-handler)
-
-;; Record the last few events, for debugging.
-(defvar timer-event-last-2 nil)
-(defvar timer-event-last-1 nil)
-(defvar timer-event-last nil)
-
-(defun timer-event-handler (event)
- "Call the handler for the timer in the event EVENT."
- (interactive "e")
- (setq timer-event-last-2 timer-event-last-1)
- (setq timer-event-last-1 timer-event-last)
- (setq timer-event-last (cons event (copy-sequence event)))
- (let ((inhibit-quit t)
- (timer (car-safe (cdr-safe event))))
- (if (timerp timer)
- (progn
- ;; Delete from queue.
- (cancel-timer timer)
- ;; Run handler
- (condition-case nil
- (apply (aref timer 5) (aref timer 6))
- (error nil))
- ;; Re-schedule if requested.
- (if (aref timer 4)
- (if (aref timer 7)
- (timer-activate-when-idle timer)
- (timer-inc-time timer (aref timer 4) 0)
- (timer-activate timer))))
- (error "Bogus timer event"))))
-
-;; This function is incompatible with the one in levents.el.
-(defun timeout-event-p (event)
- "Non-nil if EVENT is a timeout event."
- (and (listp event) (eq (car event) 'timer-event)))
-
-;;;###autoload
-(defun run-at-time (time repeat function &rest args)
- "Perform an action at time TIME.
-Repeat the action every REPEAT seconds, if REPEAT is non-nil.
-TIME should be a string like \"11:23pm\", nil meaning now, a number of seconds
-from now, a value from `current-time', or t (with non-nil REPEAT)
-meaning the next integral multiple of REPEAT.
-REPEAT may be an integer or floating point number.
-The action is to call FUNCTION with arguments ARGS.
-
-This function returns a timer object which you can use in `cancel-timer'."
- (interactive "sRun at time: \nNRepeat interval: \naFunction: ")
-
- (or (null repeat)
- (and (numberp repeat) (< 0 repeat))
- (error "Invalid repetition interval"))
-
- ;; Special case: nil means "now" and is useful when repeating.
- (if (null time)
- (setq time (current-time)))
-
- ;; Special case: t means the next integral multiple of REPEAT.
- (if (and (eq time t) repeat)
- (setq time (timer-next-integral-multiple-of-time (current-time) repeat)))
-
- ;; Handle numbers as relative times in seconds.
- (if (numberp time)
- (setq time (timer-relative-time (current-time) time)))
-
- ;; Handle relative times like "2 hours and 35 minutes"
- (if (stringp time)
- (let ((secs (timer-duration time)))
- (if secs
- (setq time (timer-relative-time (current-time) secs)))))
-
- ;; Handle "11:23pm" and the like. Interpret it as meaning today
- ;; which admittedly is rather stupid if we have passed that time
- ;; already. (Though only Emacs hackers hack Emacs at that time.)
- (if (stringp time)
- (progn
- (require 'diary-lib)
- (let ((hhmm (diary-entry-time time))
- (now (decode-time)))
- (if (>= hhmm 0)
- (setq time
- (encode-time 0 (% hhmm 100) (/ hhmm 100) (nth 3 now)
- (nth 4 now) (nth 5 now) (nth 8 now)))))))
-
- (or (consp time)
- (error "Invalid time format"))
-
- (let ((timer (timer-create)))
- (timer-set-time timer time repeat)
- (timer-set-function timer function args)
- (timer-activate timer)
- timer))
-
-;;;###autoload
-(defun run-with-timer (secs repeat function &rest args)
- "Perform an action after a delay of SECS seconds.
-Repeat the action every REPEAT seconds, if REPEAT is non-nil.
-SECS and REPEAT may be integers or floating point numbers.
-The action is to call FUNCTION with arguments ARGS.
-
-This function returns a timer object which you can use in `cancel-timer'."
- (interactive "sRun after delay (seconds): \nNRepeat interval: \naFunction: ")
- (apply 'run-at-time secs repeat function args))
-
-;;;###autoload
-(defun add-timeout (secs function object &optional repeat)
- "Add a timer to run SECS seconds from now, to call FUNCTION on OBJECT.
-If REPEAT is non-nil, repeat the timer every REPEAT seconds.
-This function is for compatibility; see also `run-with-timer'."
- (run-with-timer secs repeat function object))
-
-;;;###autoload
-(defun run-with-idle-timer (secs repeat function &rest args)
- "Perform an action the next time Emacs is idle for SECS seconds.
-If REPEAT is non-nil, do this each time Emacs is idle for SECS seconds.
-SECS may be an integer or a floating point number.
-The action is to call FUNCTION with arguments ARGS.
-
-This function returns a timer object which you can use in `cancel-timer'."
- (interactive
- (list (read-from-minibuffer "Run after idle (seconds): " nil nil t)
- (y-or-n-p "Repeat each time Emacs is idle? ")
- (intern (completing-read "Function: " obarray 'fboundp t))))
- (let ((timer (timer-create)))
- (timer-set-function timer function args)
- (timer-set-idle-time timer secs repeat)
- (timer-activate-when-idle timer)
- timer))
-
-(defun with-timeout-handler (tag)
- (throw tag 'timeout))
-
-;;;###autoload (put 'with-timeout 'lisp-indent-function 1)
-
-;;;###autoload
-(defmacro with-timeout (list &rest body)
- "Run BODY, but if it doesn't finish in SECONDS seconds, give up.
-If we give up, we run the TIMEOUT-FORMS and return the value of the last one.
-The call should look like:
- (with-timeout (SECONDS TIMEOUT-FORMS...) BODY...)
-The timeout is checked whenever Emacs waits for some kind of external
-event \(such as keyboard input, input from subprocesses, or a certain time);
-if the program loops without waiting in any way, the timeout will not
-be detected."
- (let ((seconds (car list))
- (timeout-forms (cdr list)))
- `(let ((with-timeout-tag (cons nil nil))
- with-timeout-value with-timeout-timer)
- (if (catch with-timeout-tag
- (progn
- (setq with-timeout-timer
- (run-with-timer ,seconds nil
- 'with-timeout-handler
- with-timeout-tag))
- (setq with-timeout-value (progn . ,body))
- nil))
- (progn . ,timeout-forms)
- (cancel-timer with-timeout-timer)
- with-timeout-value))))
-
-(defun y-or-n-p-with-timeout (prompt seconds default-value)
- "Like (y-or-n-p PROMPT), with a timeout.
-If the user does not answer after SECONDS seconds, return DEFAULT-VALUE."
- (with-timeout (seconds default-value)
- (y-or-n-p prompt)))
-
-(defvar timer-duration-words
- (list (cons "microsec" 0.000001)
- (cons "microsecond" 0.000001)
- (cons "millisec" 0.001)
- (cons "millisecond" 0.001)
- (cons "sec" 1)
- (cons "second" 1)
- (cons "min" 60)
- (cons "minute" 60)
- (cons "hour" (* 60 60))
- (cons "day" (* 24 60 60))
- (cons "week" (* 7 24 60 60))
- (cons "fortnight" (* 14 24 60 60))
- (cons "month" (* 30 24 60 60)) ; Approximation
- (cons "year" (* 365.25 24 60 60)) ; Approximation
- )
- "Alist mapping temporal words to durations in seconds")
-
-(defun timer-duration (string)
- "Return number of seconds specified by STRING, or nil if parsing fails."
- (let ((secs 0)
- (start 0)
- (case-fold-search t))
- (while (string-match
- "[ \t]*\\([0-9.]+\\)?[ \t]*\\([a-z]+[a-rt-z]\\)s?[ \t]*"
- string start)
- (let ((count (if (match-beginning 1)
- (string-to-number (match-string 1 string))
- 1))
- (itemsize (cdr (assoc (match-string 2 string)
- timer-duration-words))))
- (if itemsize
- (setq start (match-end 0)
- secs (+ secs (* count itemsize)))
- (setq secs nil
- start (length string)))))
- (if (= start (length string))
- secs
- (if (string-match "\\`[0-9.]+\\'" string)
- (string-to-number string)))))
-
-(provide 'timer)
-
-;;; timer.el ends here
diff --git a/lisp/timezone.el b/lisp/timezone.el
deleted file mode 100644
index b4619488960..00000000000
--- a/lisp/timezone.el
+++ /dev/null
@@ -1,397 +0,0 @@
-;;; timezone.el --- time zone package for GNU Emacs
-
-;; Copyright (C) 1990, 1991, 1992, 1993, 1996 Free Software Foundation, Inc.
-
-;; Author: Masanobu Umeda
-;; Maintainer: umerin@mse.kyutech.ac.jp
-;; Keywords: news
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(provide 'timezone)
-
-(defvar timezone-world-timezones
- '(("PST" . -800)
- ("PDT" . -700)
- ("MST" . -700)
- ("MDT" . -600)
- ("CST" . -600)
- ("CDT" . -500)
- ("EST" . -500)
- ("EDT" . -400)
- ("AST" . -400) ;by <clamen@CS.CMU.EDU>
- ("NST" . -330) ;by <clamen@CS.CMU.EDU>
- ("UT" . +000)
- ("GMT" . +000)
- ("BST" . +100)
- ("MET" . +100)
- ("EET" . +200)
- ("JST" . +900)
- ("GMT+1" . +100) ("GMT+2" . +200) ("GMT+3" . +300)
- ("GMT+4" . +400) ("GMT+5" . +500) ("GMT+6" . +600)
- ("GMT+7" . +700) ("GMT+8" . +800) ("GMT+9" . +900)
- ("GMT+10" . +1000) ("GMT+11" . +1100) ("GMT+12" . +1200) ("GMT+13" . +1300)
- ("GMT-1" . -100) ("GMT-2" . -200) ("GMT-3" . -300)
- ("GMT-4" . -400) ("GMT-5" . -500) ("GMT-6" . -600)
- ("GMT-7" . -700) ("GMT-8" . -800) ("GMT-9" . -900)
- ("GMT-10" . -1000) ("GMT-11" . -1100) ("GMT-12" . -1200))
- "*Time differentials of timezone from GMT in +-HHMM form.
-This list is obsolescent, and is present only for backwards compatibility,
-because time zone names are ambiguous in practice.
-Use `current-time-zone' instead.")
-
-(defvar timezone-months-assoc
- '(("JAN" . 1)("FEB" . 2)("MAR" . 3)
- ("APR" . 4)("MAY" . 5)("JUN" . 6)
- ("JUL" . 7)("AUG" . 8)("SEP" . 9)
- ("OCT" . 10)("NOV" . 11)("DEC" . 12))
- "Alist of first three letters of a month and its numerical representation.")
-
-(defun timezone-make-date-arpa-standard (date &optional local timezone)
- "Convert DATE to an arpanet standard date.
-Optional 1st argument LOCAL specifies the default local timezone of the DATE;
-if nil, GMT is assumed.
-Optional 2nd argument TIMEZONE specifies a time zone to be represented in;
-if nil, the local time zone is assumed."
- (let ((new (timezone-fix-time date local timezone)))
- (timezone-make-arpa-date (aref new 0) (aref new 1) (aref new 2)
- (timezone-make-time-string
- (aref new 3) (aref new 4) (aref new 5))
- (aref new 6))
- ))
-
-(defun timezone-make-date-sortable (date &optional local timezone)
- "Convert DATE to a sortable date string.
-Optional 1st argument LOCAL specifies the default local timezone of the DATE;
-if nil, GMT is assumed.
-Optional 2nd argument TIMEZONE specifies a timezone to be represented in;
-if nil, the local time zone is assumed."
- (let ((new (timezone-fix-time date local timezone)))
- (timezone-make-sortable-date (aref new 0) (aref new 1) (aref new 2)
- (timezone-make-time-string
- (aref new 3) (aref new 4) (aref new 5)))
- ))
-
-
-;;
-;; Parsers and Constructors of Date and Time
-;;
-
-(defun timezone-make-arpa-date (year month day time &optional timezone)
- "Make arpanet standard date string from YEAR, MONTH, DAY, and TIME.
-Optional argument TIMEZONE specifies a time zone."
- (let ((zone
- (if (listp timezone)
- (let* ((m (timezone-zone-to-minute timezone))
- (absm (if (< m 0) (- m) m)))
- (format "%c%02d%02d"
- (if (< m 0) ?- ?+) (/ absm 60) (% absm 60)))
- timezone)))
- (format "%02d %s %04d %s %s"
- day
- (capitalize (car (rassq month timezone-months-assoc)))
- year
- time
- zone)))
-
-(defun timezone-make-sortable-date (year month day time)
- "Make sortable date string from YEAR, MONTH, DAY, and TIME."
- (format "%4d%02d%02d%s"
- year month day time))
-
-(defun timezone-make-time-string (hour minute second)
- "Make time string from HOUR, MINUTE, and SECOND."
- (format "%02d:%02d:%02d" hour minute second))
-
-(defun timezone-parse-date (date)
- "Parse DATE and return a vector [YEAR MONTH DAY TIME TIMEZONE].
-19 is prepended to year if necessary. Timezone may be nil if nothing.
-Understands the following styles:
- (1) 14 Apr 89 03:20[:12] [GMT]
- (2) Fri, 17 Mar 89 4:01[:33] [GMT]
- (3) Mon Jan 16 16:12[:37] [GMT] 1989
- (4) 6 May 1992 1641-JST (Wednesday)
- (5) 22-AUG-1993 10:59:12.82
- (6) Thu, 11 Apr 16:17:12 91 [MET]
- (7) Mon, 6 Jul 16:47:20 T 1992 [MET]
- (8) 1996-06-24 21:13:12 [GMT]"
- ;; Get rid of any text properties.
- (and (stringp date)
- (or (text-properties-at 0 date)
- (next-property-change 0 date))
- (setq date (copy-sequence date))
- (set-text-properties 0 (length date) nil date))
- (let ((date (or date ""))
- (year nil)
- (month nil)
- (day nil)
- (time nil)
- (zone nil)) ;This may be nil.
- (cond ((string-match
- "\\([^ \t,]+\\),[ \t]+\\([0-9]+\\)[ \t]+\\([^ \t,]+\\)[ \t]+\\([0-9]+:[0-9:]+\\)[ \t]+\\(T[ \t]+\\|\\)\\([0-9]+\\)[ \t]*\\'" date)
- ;; Styles: (6) and (7) without timezone
- (setq year 6 month 3 day 2 time 4 zone nil))
- ((string-match
- "\\([^ \t,]+\\),[ \t]+\\([0-9]+\\)[ \t]+\\([^ \t,]+\\)[ \t]+\\([0-9]+:[0-9:]+\\)[ \t]+\\(T[ \t]+\\|\\)\\([0-9]+\\)[ \t]*\\([-+a-zA-Z0-9]+\\)" date)
- ;; Styles: (6) and (7) with timezone and buggy timezone
- (setq year 6 month 3 day 2 time 4 zone 7))
- ((string-match
- "\\([0-9]+\\)[ \t]+\\([^ \t,]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\([0-9]+:[0-9:]+\\)[ \t]*\\'" date)
- ;; Styles: (1) and (2) without timezone
- (setq year 3 month 2 day 1 time 4 zone nil))
- ((string-match
- "\\([0-9]+\\)[ \t]+\\([^ \t,]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\([0-9]+:[0-9:]+\\)[ \t]*\\([-+a-zA-Z0-9]+\\)" date)
- ;; Styles: (1) and (2) with timezone and buggy timezone
- (setq year 3 month 2 day 1 time 4 zone 5))
- ((string-match
- "\\([^ \t,]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\([0-9]+:[0-9:]+\\)[ \t]+\\([0-9]+\\)" date)
- ;; Styles: (3) without timezone
- (setq year 4 month 1 day 2 time 3 zone nil))
- ((string-match
- "\\([^ \t,]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\([0-9]+:[0-9:]+\\)[ \t]+\\([-+a-zA-Z0-9]+\\)[ \t]+\\([0-9]+\\)" date)
- ;; Styles: (3) with timezone
- (setq year 5 month 1 day 2 time 3 zone 4))
- ((string-match
- "\\([0-9]+\\)[ \t]+\\([^ \t,]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\([0-9]+\\)[ \t]*\\([-+a-zA-Z0-9]+\\)" date)
- ;; Styles: (4) with timezone
- (setq year 3 month 2 day 1 time 4 zone 5))
- ((string-match
- "\\([0-9]+\\)-\\([A-Za-z]+\\)-\\([0-9]+\\)[ \t]+\\([0-9]+:[0-9]+:[0-9]+\\)\\.[0-9]+" date)
- ;; Styles: (5) without timezone.
- (setq year 3 month 2 day 1 time 4 zone nil))
- ((string-match
- "\\([0-9]+\\)-\\([0-9]+\\)-\\([0-9]+\\)[ \t]+\\([0-9]+:[0-9]+:[0-9]+\\)[ \t]*\\([-+a-zA-Z0-9]+\\)" date)
- ;; Styles: (8) with timezone.
- (setq year 1 month 2 day 3 time 4 zone 5))
- ((string-match
- "\\([0-9]+\\)-\\([0-9]+\\)-\\([0-9]+\\)[ \t]+\\([0-9]+:[0-9]+:[0-9]+\\)" date)
- ;; Styles: (8) without timezone.
- (setq year 1 month 2 day 3 time 4 zone nil))
- )
- (if year
- (progn
- (setq year
- (substring date (match-beginning year) (match-end year)))
- ;; It is now Dec 1992. 8 years before the end of the World.
- (if (< (length year) 4)
- (setq year (concat "19" (substring year -2 nil))))
- (setq month
- (if (= (aref date (+ (match-beginning month) 2)) ?-)
- ;; Handle numeric months, spanning exactly two digits.
- (substring date
- (match-beginning month)
- (+ (match-beginning month) 2))
- (let ((string (substring date
- (match-beginning month)
- (+ (match-beginning month) 3))))
- (int-to-string
- (cdr (assoc (upcase string) timezone-months-assoc))))))
- (setq day
- (substring date (match-beginning day) (match-end day)))
- (setq time
- (substring date (match-beginning time) (match-end time)))))
- (if zone
- (setq zone
- (substring date (match-beginning zone) (match-end zone))))
- ;; Return a vector.
- (if year
- (vector year month day time zone)
- (vector "0" "0" "0" "0" nil))
- ))
-
-(defun timezone-parse-time (time)
- "Parse TIME (HH:MM:SS) and return a vector [hour minute second].
-Recognize HH:MM:SS, HH:MM, HHMMSS, HHMM."
- (let ((time (or time ""))
- (hour nil)
- (minute nil)
- (second nil))
- (cond ((string-match "\\`\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)\\'" time)
- ;; HH:MM:SS
- (setq hour 1 minute 2 second 3))
- ((string-match "\\`\\([0-9]+\\):\\([0-9]+\\)\\'" time)
- ;; HH:MM
- (setq hour 1 minute 2 second nil))
- ((string-match "\\`\\([0-9][0-9]\\)\\([0-9][0-9]\\)\\([0-9][0-9]\\)\\'" time)
- ;; HHMMSS
- (setq hour 1 minute 2 second 3))
- ((string-match "\\`\\([0-9][0-9]\\)\\([0-9][0-9]\\)\\'" time)
- ;; HHMM
- (setq hour 1 minute 2 second nil))
- )
- ;; Return [hour minute second]
- (vector
- (if hour
- (substring time (match-beginning hour) (match-end hour)) "0")
- (if minute
- (substring time (match-beginning minute) (match-end minute)) "0")
- (if second
- (substring time (match-beginning second) (match-end second)) "0"))
- ))
-
-
-;; Miscellaneous
-
-(defun timezone-zone-to-minute (timezone)
- "Translate TIMEZONE to an integer minute offset from GMT.
-TIMEZONE can be a cons cell containing the output of current-time-zone,
-or an integer of the form +-HHMM, or a time zone name."
- (cond
- ((consp timezone)
- (/ (car timezone) 60))
- (timezone
- (progn
- (setq timezone
- (or (cdr (assoc (upcase timezone) timezone-world-timezones))
- ;; +900
- timezone))
- (if (stringp timezone)
- (setq timezone (string-to-int timezone)))
- ;; Taking account of minute in timezone.
- ;; HHMM -> MM
- (let* ((abszone (abs timezone))
- (minutes (+ (* 60 (/ abszone 100)) (% abszone 100))))
- (if (< timezone 0) (- minutes) minutes))))
- (t 0)))
-
-(defun timezone-time-from-absolute (date seconds)
- "Compute the UTC time equivalent to DATE at time SECONDS after midnight.
-Return a list suitable as an argument to current-time-zone,
-or nil if the date cannot be thus represented.
-DATE is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
- (let* ((current-time-origin 719163)
- ;; (timezone-absolute-from-gregorian 1 1 1970)
- (days (- date current-time-origin))
- (seconds-per-day (float 86400))
- (seconds (+ seconds (* days seconds-per-day)))
- (current-time-arithmetic-base (float 65536))
- (hi (floor (/ seconds current-time-arithmetic-base)))
- (hibase (* hi current-time-arithmetic-base))
- (lo (floor (- seconds hibase))))
- (and (< (abs (- seconds (+ hibase lo))) 2) ;; Check for integer overflow.
- (cons hi lo))))
-
-(defun timezone-time-zone-from-absolute (date seconds)
- "Compute the local time zone for DATE at time SECONDS after midnight.
-Return a list in the same format as current-time-zone's result,
-or nil if the local time zone could not be computed.
-DATE is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
- (and (fboundp 'current-time-zone)
- (let ((utc-time (timezone-time-from-absolute date seconds)))
- (and utc-time
- (let ((zone (current-time-zone utc-time)))
- (and (car zone) zone))))))
-
-(defun timezone-fix-time (date local timezone)
- "Convert DATE (default timezone LOCAL) to YYYY-MM-DD-HH-MM-SS-ZONE vector.
-If LOCAL is nil, it is assumed to be GMT.
-If TIMEZONE is nil, use the local time zone."
- (let* ((date (timezone-parse-date date))
- (year (string-to-int (aref date 0)))
- (year (cond ((< year 50)
- (+ year 2000))
- ((< year 100)
- (+ year 1900))
- (t year)))
- (month (string-to-int (aref date 1)))
- (day (string-to-int (aref date 2)))
- (time (timezone-parse-time (aref date 3)))
- (hour (string-to-int (aref time 0)))
- (minute (string-to-int (aref time 1)))
- (second (string-to-int (aref time 2)))
- (local (or (aref date 4) local)) ;Use original if defined
- (timezone
- (or timezone
- (timezone-time-zone-from-absolute
- (timezone-absolute-from-gregorian month day year)
- (+ second (* 60 (+ minute (* 60 hour)))))))
- (diff (- (timezone-zone-to-minute timezone)
- (timezone-zone-to-minute local)))
- (minute (+ minute diff))
- (hour-fix (floor minute 60)))
- (setq hour (+ hour hour-fix))
- (setq minute (- minute (* 60 hour-fix)))
- ;; HOUR may be larger than 24 or smaller than 0.
- (cond ((<= 24 hour) ;24 -> 00
- (setq hour (- hour 24))
- (setq day (1+ day))
- (if (< (timezone-last-day-of-month month year) day)
- (progn
- (setq month (1+ month))
- (setq day 1)
- (if (< 12 month)
- (progn
- (setq month 1)
- (setq year (1+ year))
- ))
- )))
- ((> 0 hour)
- (setq hour (+ hour 24))
- (setq day (1- day))
- (if (> 1 day)
- (progn
- (setq month (1- month))
- (if (> 1 month)
- (progn
- (setq month 12)
- (setq year (1- year))
- ))
- (setq day (timezone-last-day-of-month month year))
- )))
- )
- (vector year month day hour minute second timezone)))
-
-;; Partly copied from Calendar program by Edward M. Reingold.
-;; Thanks a lot.
-
-(defun timezone-last-day-of-month (month year)
- "The last day in MONTH during YEAR."
- (if (and (= month 2) (timezone-leap-year-p year))
- 29
- (aref [31 28 31 30 31 30 31 31 30 31 30 31] (1- month))))
-
-(defun timezone-leap-year-p (year)
- "Returns t if YEAR is a Gregorian leap year."
- (or (and (zerop (% year 4))
- (not (zerop (% year 100))))
- (zerop (% year 400))))
-
-(defun timezone-day-number (month day year)
- "Return the day number within the year of the date month/day/year."
- (let ((day-of-year (+ day (* 31 (1- month)))))
- (if (> month 2)
- (progn
- (setq day-of-year (- day-of-year (/ (+ 23 (* 4 month)) 10)))
- (if (timezone-leap-year-p year)
- (setq day-of-year (1+ day-of-year)))))
- day-of-year))
-
-(defun timezone-absolute-from-gregorian (month day year)
- "The number of days between the Gregorian date 12/31/1 BC and month/day/year.
-The Gregorian date Sunday, December 31, 1 BC is imaginary."
- (+ (timezone-day-number month day year);; Days this year
- (* 365 (1- year));; + Days in prior years
- (/ (1- year) 4);; + Julian leap years
- (- (/ (1- year) 100));; - century years
- (/ (1- year) 400)));; + Gregorian leap years
-
-;;; timezone.el ends here
diff --git a/lisp/tmm.el b/lisp/tmm.el
deleted file mode 100644
index b016e8231bf..00000000000
--- a/lisp/tmm.el
+++ /dev/null
@@ -1,471 +0,0 @@
-;;; tmm.el --- text mode access to menu-bar
-
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Ilya Zakharevich <ilya@math.mps.ohio-state.edu>
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; To use this package add
-
-;; (autoload 'tmm-menubar 'tmm "Text mode substitute for menubar" t)
-;; (global-set-key [f10] 'tmm-menubar)
-;; to your .emacs file. You can also add your own access to different
-;; menus available in Window System Emacs modeling definition after
-;; tmm-menubar.
-
-;;; Code:
-
-(require 'electric)
-
-;;; The following will be localized, added only to pacify the compiler.
-(defvar tmm-short-cuts)
-(defvar tmm-old-mb-map nil)
-(defvar tmm-old-comp-map)
-(defvar tmm-c-prompt)
-(defvar tmm-km-list)
-(defvar tmm-next-shortcut-digit)
-(defvar tmm-table-undef)
-
-;;;###autoload (define-key global-map "\M-`" 'tmm-menubar)
-;;;###autoload (define-key global-map [f10] 'tmm-menubar)
-;;;###autoload (define-key global-map [menu-bar mouse-1] 'tmm-menubar-mouse)
-
-;;;###autoload
-(defun tmm-menubar (&optional x-position)
- "Text-mode emulation of looking and choosing from a menubar.
-See the documentation for `tmm-prompt'.
-X-POSITION, if non-nil, specifies a horizontal position within the menu bar;
-we make that menu bar item (the one at that position) the default choice."
- (interactive)
- (run-hooks 'menu-bar-update-hook)
- ;; Obey menu-bar-final-items; put those items last.
- (let ((menu-bar (tmm-get-keybind [menu-bar]))
- menu-bar-item)
- (let ((list menu-bar-final-items))
- (while list
- (let ((item (car list)))
- ;; ITEM is the name of an item that we want to put last.
- ;; Find it in MENU-BAR and move it to the end.
- (let ((this-one (assq item menu-bar)))
- (setq menu-bar (append (delq this-one menu-bar)
- (list this-one)))))
- (setq list (cdr list))))
- (if x-position
- (let ((tail menu-bar)
- this-one
- (column 0))
- (while (and tail (< column x-position))
- (setq this-one (car tail))
- (if (and (consp (car tail))
- (consp (cdr (car tail)))
- (stringp (nth 1 (car tail))))
- (setq column (+ column
- (length (nth 1 (car tail)))
- 1)))
- (setq tail (cdr tail)))
- (setq menu-bar-item (car this-one))))
- (tmm-prompt menu-bar nil menu-bar-item)))
-
-;;;###autoload
-(defun tmm-menubar-mouse (event)
- "Text-mode emulation of looking and choosing from a menubar.
-This command is used when you click the mouse in the menubar
-on a console which has no window system but does have a mouse.
-See the documentation for `tmm-prompt'."
- (interactive "e")
- (tmm-menubar (car (posn-x-y (event-start event)))))
-
-(defvar tmm-mid-prompt "==>"
- "*String to insert between shortcut and menu item.
-If nil, there will be no shortcuts. It should not consist only of spaces,
-or else the correct item might not be found in the `*Completions*' buffer.")
-
-(defvar tmm-mb-map nil
- "A place to store minibuffer map.")
-
-(defvar tmm-completion-prompt
- "Press PageUp Key to reach this buffer from the minibuffer.
-Alternatively, you can use Up/Down keys (or your History keys) to change
-the item in the minibuffer, and press RET when you are done, or press the
-marked letters to pick up your choice. Type C-g or ESC ESC ESC to cancel.
-"
- "*Help text to insert on the top of the completion buffer.
-To save space, you can set this to nil,
-in which case the standard introduction text is deleted too.")
-
-(defvar tmm-shortcut-style '(downcase upcase)
- "*What letters to use as menu shortcuts.
-Must be either one of the symbols `downcase' or `upcase',
-or else a list of the two in the order you prefer.")
-
-(defvar tmm-shortcut-words 2
- "*How many successive words to try for shortcuts, nil means all.
-If you use only one of `downcase' or `upcase' for `tmm-shortcut-style',
-specify nil for this variable.")
-
-;;;###autoload
-(defun tmm-prompt (menu &optional in-popup default-item)
- "Text-mode emulation of calling the bindings in keymap.
-Creates a text-mode menu of possible choices. You can access the elements
-in the menu in two ways:
- *) via history mechanism from minibuffer;
- *) Or via completion-buffer that is automatically shown.
-The last alternative is currently a hack, you cannot use mouse reliably.
-
-MENU is like the MENU argument to `x-popup-menu': either a
-keymap or an alist of alists.
-DEFAULT-ITEM, if non-nil, specifies an initial default choice.
-Its value should be an event that has a binding in MENU."
- ;; If the optional argument IN-POPUP is t,
- ;; then MENU is an alist of elements of the form (STRING . VALUE).
- ;; That is used for recursive calls only.
- (let ((gl-str "Menu bar") ;; The menu bar itself is not a menu keymap
- ; so it doesn't have a name.
- tmm-km-list out history history-len tmm-table-undef tmm-c-prompt
- tmm-old-mb-map tmm-old-comp-map tmm-short-cuts
- chosen-string choice
- (not-menu (not (keymapp menu))))
- (run-hooks 'activate-menubar-hook)
- ;; Compute tmm-km-list from MENU.
- ;; tmm-km-list is an alist of (STRING . MEANING).
- ;; It has no other elements.
- ;; The order of elements in tmm-km-list is the order of the menu bar.
- (mapcar (function (lambda (elt)
- (if (stringp elt)
- (setq gl-str elt)
- (and (listp elt) (tmm-get-keymap elt not-menu)))))
- menu)
- ;; Choose an element of tmm-km-list; put it in choice.
- (if (and not-menu (= 1 (length tmm-km-list)))
- ;; If this is the top-level of an x-popup-menu menu,
- ;; and there is just one pane, choose that one silently.
- ;; This way we only ask the user one question,
- ;; for which element of that pane.
- (setq choice (cdr (car tmm-km-list)))
- (and tmm-km-list
- (let ((index-of-default 0))
- (if tmm-mid-prompt
- (setq tmm-km-list (tmm-add-shortcuts tmm-km-list))
- t)
- ;; Find the default item's index within the menu bar.
- ;; We use this to decide the initial minibuffer contents
- ;; and initial history position.
- (if default-item
- (let ((tail menu))
- (while (and tail
- (not (eq (car-safe (car tail)) default-item)))
- ;; Be careful to count only the elements of MENU
- ;; that actually constitute menu bar items.
- (if (and (consp (car tail))
- (stringp (car-safe (cdr (car tail)))))
- (setq index-of-default (1+ index-of-default)))
- (setq tail (cdr tail)))))
- (setq history (reverse (mapcar 'car tmm-km-list)))
- (setq history-len (length history))
- (setq history (append history history history history))
- (setq tmm-c-prompt (nth (- history-len 1 index-of-default) history))
- (add-hook 'minibuffer-setup-hook 'tmm-add-prompt)
- (unwind-protect
- (setq out
- (completing-read
- (concat gl-str " (up/down to change, PgUp to menu): ")
- tmm-km-list nil t nil
- (cons 'history (- (* 2 history-len) index-of-default))))
- (save-excursion
- (remove-hook 'minibuffer-setup-hook 'tmm-add-prompt)
- (if (get-buffer "*Completions*")
- (progn
- (set-buffer "*Completions*")
- (use-local-map tmm-old-comp-map)
- (bury-buffer (current-buffer)))))
- )))
- (setq choice (cdr (assoc out tmm-km-list)))
- (and (null choice)
- (> (length out) (length tmm-c-prompt))
- (string= (substring out 0 (length tmm-c-prompt)) tmm-c-prompt)
- (setq out (substring out (length tmm-c-prompt))
- choice (cdr (assoc out tmm-km-list))))
- (and (null choice)
- (setq out (try-completion out tmm-km-list)
- choice (cdr (assoc out tmm-km-list)))))
- ;; CHOICE is now (STRING . MEANING). Separate the two parts.
- (setq chosen-string (car choice))
- (setq choice (cdr choice))
- (cond (in-popup
- ;; We just did the inner level of a -popup menu.
- choice)
- ;; We just did the outer level. Do the inner level now.
- (not-menu (tmm-prompt choice t))
- ;; We just handled a menu keymap and found another keymap.
- ((keymapp choice)
- (if (symbolp choice)
- (setq choice (indirect-function choice)))
- (condition-case nil
- (require 'mouse)
- (error nil))
- (condition-case nil
- (x-popup-menu nil choice) ; Get the shortcuts
- (error nil))
- (tmm-prompt choice))
- ;; We just handled a menu keymap and found a command.
- (choice
- (if chosen-string
- (progn
- (setq last-command-event chosen-string)
- (call-interactively choice))
- choice)))))
-
-(defun tmm-add-shortcuts (list)
- "Adds shortcuts to cars of elements of the list.
-Takes a list of lists with a string as car, returns list with
-shortcuts added to these cars.
-Stores a list of all the shortcuts in the free variable `tmm-short-cuts'."
- (let ((tmm-next-shortcut-digit ?0))
- (mapcar 'tmm-add-one-shortcut (reverse list))))
-
-(defsubst tmm-add-one-shortcut (elt)
-;; uses the free vars tmm-next-shortcut-digit and tmm-short-cuts
- (let* ((str (car elt))
- (paren (string-match "(" str))
- (pos 0) (word 0) char)
- (catch 'done ; ??? is this slow?
- (while (and (or (not tmm-shortcut-words) ; no limit on words
- (< word tmm-shortcut-words)) ; try n words
- (setq pos (string-match "\\w+" str pos)) ; get next word
- (not (and paren (> pos paren)))) ; don't go past "(binding.."
- (if (or (= pos 0)
- (/= (aref str (1- pos)) ?.)) ; avoid file extensions
- (let ((shortcut-style
- (if (listp tmm-shortcut-style) ; convert to list
- tmm-shortcut-style
- (list tmm-shortcut-style))))
- (while shortcut-style ; try upcase and downcase variants
- (setq char (funcall (car shortcut-style) (aref str pos)))
- (if (not (memq char tmm-short-cuts)) (throw 'done char))
- (setq shortcut-style (cdr shortcut-style)))))
- (setq word (1+ word))
- (setq pos (match-end 0)))
- (while (<= tmm-next-shortcut-digit ?9) ; no letter shortcut, pick a digit
- (setq char tmm-next-shortcut-digit)
- (setq tmm-next-shortcut-digit (1+ tmm-next-shortcut-digit))
- (if (not (memq char tmm-short-cuts)) (throw 'done char)))
- (setq char nil))
- (if char (setq tmm-short-cuts (cons char tmm-short-cuts)))
- (cons (concat (if char (concat (char-to-string char) tmm-mid-prompt)
- ;; keep them lined up in columns
- (make-string (1+ (length tmm-mid-prompt)) ?\ ))
- str)
- (cdr elt))))
-
-;; This returns the old map.
-(defun tmm-define-keys (minibuffer)
- (let ((map (make-sparse-keymap)))
- (suppress-keymap map t)
- (mapcar
- (function
- (lambda (c)
- (if (listp tmm-shortcut-style)
- (define-key map (char-to-string c) 'tmm-shortcut)
- ;; only one kind of letters are shortcuts, so map both upcase and
- ;; downcase input to the same
- (define-key map (char-to-string (downcase c)) 'tmm-shortcut)
- (define-key map (char-to-string (upcase c)) 'tmm-shortcut))))
- tmm-short-cuts)
- (if minibuffer
- (progn
- (define-key map [pageup] 'tmm-goto-completions)
- (define-key map [prior] 'tmm-goto-completions)
- (define-key map "\ev" 'tmm-goto-completions)
- (define-key map "\C-n" 'next-history-element)
- (define-key map "\C-p" 'previous-history-element)))
- (prog1 (current-local-map)
- (use-local-map (append map (current-local-map))))))
-
-(defun tmm-completion-delete-prompt ()
- (set-buffer standard-output)
- (goto-char 1)
- (delete-region 1 (search-forward "Possible completions are:\n")))
-
-(defun tmm-add-prompt ()
- (remove-hook 'minibuffer-setup-hook 'tmm-add-prompt)
- (make-local-hook 'minibuffer-exit-hook)
- (add-hook 'minibuffer-exit-hook 'tmm-delete-map nil t)
- (let ((win (selected-window)))
- (setq tmm-old-mb-map (tmm-define-keys t))
- ;; Get window and hide it for electric mode to get correct size
- (save-window-excursion
- (let ((completions
- (mapcar 'car minibuffer-completion-table)))
- (or tmm-completion-prompt
- (add-hook 'completion-setup-hook
- 'tmm-completion-delete-prompt 'append))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list completions))
- (remove-hook 'completion-setup-hook 'tmm-completion-delete-prompt))
- (if tmm-completion-prompt
- (progn
- (set-buffer "*Completions*")
- (goto-char 1)
- (insert tmm-completion-prompt)))
- )
- (save-excursion
- (other-window 1) ; Electric-pop-up-window does
- ; not work in minibuffer
- (set-buffer (window-buffer (Electric-pop-up-window "*Completions*")))
-
- (setq tmm-old-comp-map (tmm-define-keys nil))
-
- (select-window win) ; Cannot use
- ; save-window-excursion, since
- ; it restores the size
- )
- (insert tmm-c-prompt)))
-
-(defun tmm-delete-map ()
- (remove-hook 'minibuffer-exit-hook 'tmm-delete-map t)
- (if tmm-old-mb-map
- (use-local-map tmm-old-mb-map)))
-
-(defun tmm-shortcut ()
- "Choose the shortcut that the user typed."
- (interactive)
- (let ((c last-command-char) s)
- (if (symbolp tmm-shortcut-style)
- (setq c (funcall tmm-shortcut-style c)))
- (if (memq c tmm-short-cuts)
- (if (equal (buffer-name) "*Completions*")
- (progn
- (beginning-of-buffer)
- (re-search-forward
- (concat "\\(^\\|[ \t]\\)" (char-to-string c) tmm-mid-prompt))
- (choose-completion))
- (erase-buffer) ; In minibuffer
- (mapcar (lambda (elt)
- (if (string=
- (substring (car elt) 0
- (min (1+ (length tmm-mid-prompt))
- (length (car elt))))
- (concat (char-to-string c) tmm-mid-prompt))
- (setq s (car elt))))
- tmm-km-list)
- (insert s)
- (exit-minibuffer)))))
-
-(defun tmm-goto-completions ()
- (interactive)
- (setq tmm-c-prompt (buffer-string))
- (erase-buffer)
- (switch-to-buffer-other-window "*Completions*")
- (search-forward tmm-c-prompt)
- (search-backward tmm-c-prompt))
-
-(defun tmm-get-keymap (elt &optional in-x-menu)
- "Prepends (DOCSTRING EVENT BINDING) to free variable `tmm-km-list'.
-The values are deduced from the argument ELT, that should be an
-element of keymap, an `x-popup-menu' argument, or an element of
-`x-popup-menu' argument (when IN-X-MENU is not-nil).
-This function adds the element only if it is not already present.
-It uses the free variable `tmm-table-undef' to keep undefined keys."
- (let (km str cache (event (car elt)))
- (setq elt (cdr elt))
- (if (eq elt 'undefined)
- (setq tmm-table-undef (cons (cons event nil) tmm-table-undef))
- (or
- (assoc event tmm-table-undef)
- (and (if (listp elt)
- (keymapp elt)
- (fboundp elt))
- (setq km elt))
- (and (if (listp (cdr-safe elt))
- (keymapp (cdr-safe elt))
- (fboundp (cdr-safe elt)))
- (setq km (cdr elt))
- (and (stringp (car elt)) (setq str (car elt))))
- (and (if (listp (cdr-safe (cdr-safe elt)))
- (keymapp (cdr-safe (cdr-safe elt)))
- (fboundp (cdr-safe (cdr-safe elt))))
- (setq km (cdr (cdr elt)))
- (and (stringp (car elt)) (setq str (car elt)))
- (or (and str
- (stringp (cdr (car (cdr elt)))) ; keyseq cache
- (setq cache (cdr (car (cdr elt))))
- cache (setq str (concat str cache))) str))
- (and (if (listp (cdr-safe (cdr-safe (cdr-safe elt))))
- (keymapp (cdr-safe (cdr-safe (cdr-safe elt))))
- (fboundp (cdr-safe (cdr-safe (cdr-safe elt)))))
- ; New style of easy-menu
- (setq km (cdr (cdr (cdr elt))))
- (and (stringp (car elt)) (setq str (car elt)))
- (or (and str
- (stringp (cdr (car (cdr (cdr elt))))) ; keyseq cache
- (setq cache (cdr (car (cdr (cdr elt)))))
- cache (setq str (concat str cache)))
- str))
- (and (stringp event) ; x-popup or x-popup element
- (if (or in-x-menu (stringp (car-safe elt)))
- (setq str event event nil km elt)
- (setq str event event nil km (cons 'keymap elt))
- )))
- (and km (stringp km) (setq str km))
- (and km str
- (or (assoc str tmm-km-list)
- (setq tmm-km-list
- (cons (cons str (cons event km)) tmm-km-list)))
- ))))
-
-(defun tmm-get-keybind (keyseq)
- "Return the current binding of KEYSEQ, merging prefix definitions.
-If KEYSEQ is a prefix key that has local and global bindings,
-we merge them into a single keymap which shows the proper order of the menu.
-However, for the menu bar itself, the value does not take account
-of `menu-bar-final-items'."
- (let (allbind bind)
- (setq bind (key-binding keyseq))
- ;; If KEYSEQ is a prefix key, then BIND is either nil
- ;; or a symbol defined as a keymap (which satisfies keymapp).
- (if (keymapp bind)
- (setq bind nil))
- ;; If we have a non-keymap definition, return that.
- (or bind
- (progn
- ;; Otherwise, it is a prefix, so make a list of the subcommands.
- ;; Make a list of all the bindings in all the keymaps.
- (setq allbind (mapcar 'cdr (minor-mode-key-binding keyseq)))
- (setq allbind (cons (local-key-binding keyseq) allbind))
- (setq allbind (cons (global-key-binding keyseq) allbind))
- ;; Merge all the elements of ALLBIND into one keymap.
- (mapcar (lambda (in)
- (if (and (symbolp in) (keymapp in))
- (setq in (symbol-function in)))
- (and in (keymapp in)
- (if (keymapp bind)
- (setq bind (nconc bind (copy-sequence (cdr in))))
- (setq bind (copy-sequence in)))))
- allbind)
- ;; Return that keymap.
- bind))))
-
-(add-hook 'calendar-load-hook (lambda () (require 'cal-menu)))
-
-(provide 'tmm)
-
-;;; tmm.el ends here
diff --git a/lisp/type-break.el b/lisp/type-break.el
deleted file mode 100644
index 690f0842a39..00000000000
--- a/lisp/type-break.el
+++ /dev/null
@@ -1,688 +0,0 @@
-;;; type-break.el --- encourage rests from typing at appropriate intervals
-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-
-;; Author: Noah Friedman <friedman@prep.ai.mit.edu>
-;; Maintainer: friedman@prep.ai.mit.edu
-;; Keywords: extensions, timers
-;; Status: known to work in GNU Emacs 19.25 or later.
-;; Created: 1994-07-13
-;; $Id$
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;;; The docstring for the function `type-break-mode' summarizes most of the
-;;; details of the interface.
-
-;;; This package relies on the assumption that you live entirely in emacs,
-;;; as the author does. If that's not the case for you (e.g. you often
-;;; suspend emacs or work in other windows) then this won't help very much;
-;;; it will depend on just how often you switch back to emacs. At the very
-;;; least, you will want to turn off the keystroke thresholds and rest
-;;; interval tracking.
-
-;;; This package was inspired by Roland McGrath's hanoi-break.el.
-;;; Thanks to both Roland McGrath <roland@gnu.ai.mit.edu> and Mark Ashton
-;;; <mpashton@gnu.ai.mit.edu> for feedback and ideas.
-
-;;; Code:
-
-
-(require 'timer)
-
-;; Make this nil initially so that the call to type-break-mode at the end
-;; will cause scheduling and so forth to happen.
-;;;###autoload
-(defvar type-break-mode nil
- "*Non-`nil' means typing break mode is enabled.
-See the docstring for the `type-break-mode' command for more information.")
-
-;;;###autoload
-(defvar type-break-interval (* 60 60)
- "*Number of seconds between scheduled typing breaks.")
-
-;;;###autoload
-(defvar type-break-good-rest-interval (/ type-break-interval 6)
- "*Number of seconds of idle time considered to be an adequate typing rest.
-
-When this variable is non-`nil', emacs checks the idle time between
-keystrokes. If this idle time is long enough to be considered a \"good\"
-rest from typing, then the next typing break is simply rescheduled for later.
-
-If a break is interrupted before this much time elapses, the user will be
-asked whether or not really to interrupt the break.")
-
-;;;###autoload
-(defvar type-break-keystroke-threshold
- ;; Assuming typing speed is 35wpm (on the average, do you really
- ;; type more than that in a minute? I spend a lot of time reading mail
- ;; and simply studying code in buffers) and average word length is
- ;; about 5 letters, default upper threshold to the average number of
- ;; keystrokes one is likely to type in a break interval. That way if the
- ;; user goes through a furious burst of typing activity, cause a typing
- ;; break to be required sooner than originally scheduled.
- ;; Conversely, the minimum threshold should be about a fifth of this.
- (let* ((wpm 35)
- (avg-word-length 5)
- (upper (* wpm avg-word-length (/ type-break-interval 60)))
- (lower (/ upper 5)))
- (cons lower upper))
- "*Upper and lower bound on number of keystrokes for considering typing break.
-This structure is a pair of numbers.
-
-The first number is the minimum number of keystrokes that must have been
-entered since the last typing break before considering another one, even if
-the scheduled time has elapsed; the break is simply rescheduled until later
-if the minimum threshold hasn't been reached. If this first value is nil,
-then there is no minimum threshold; as soon as the scheduled time has
-elapsed, the user will always be queried.
-
-The second number is the maximum number of keystrokes that can be entered
-before a typing break is requested immediately, pre-empting the originally
-scheduled break. If this second value is nil, then no pre-emptive breaks
-will occur; only scheduled ones will.
-
-Keys with bucky bits (shift, control, meta, etc) are counted as only one
-keystroke even though they really require multiple keys to generate them.")
-
-(defvar type-break-time-warning-intervals '(300 120 60 30)
- "*List of time intervals for warnings about upcoming typing break.
-At each of the intervals (specified in seconds) away from a scheduled
-typing break, print a warning in the echo area.")
-
-(defvar type-break-keystroke-warning-intervals '(300 200 100 50)
- "*List of keystroke measurements for warnings about upcoming typing break.
-At each of the intervals (specified in keystrokes) away from the upper
-keystroke threshold, print a warning in the echo area.
-If either this variable or the upper threshold is set, then no warnings
-Will occur.")
-
-(defvar type-break-query-interval 60
- "*Number of seconds between queries to take a break, if put off.
-The user will continue to be prompted at this interval until he or she
-finally submits to taking a typing break.")
-
-(defvar type-break-warning-repeat 40
- "*Number of keystrokes for which warnings should be repeated.
-That is, for each of this many keystrokes the warning is redisplayed
-in the echo area to make sure it's really seen.")
-
-(defvar type-break-query-function 'yes-or-no-p
- "Function to use for making query for a typing break.
-It should take a string as an argument, the prompt.
-Usually this should be set to `yes-or-no-p' or `y-or-n-p'.")
-
-(defvar type-break-demo-functions
- '(type-break-demo-boring type-break-demo-life type-break-demo-hanoi)
- "*List of functions to consider running as demos during typing breaks.
-When a typing break begins, one of these functions is selected randomly
-to have emacs do something interesting.
-
-Any function in this list should start a demo which ceases as soon as a
-key is pressed.")
-
-(defvar type-break-post-command-hook nil
- "Hook run indirectly by post-command-hook for typing break functions.")
-
-;; These are internal variables. Do not set them yourself.
-
-(defvar type-break-alarm-p nil)
-(defvar type-break-keystroke-count 0)
-(defvar type-break-time-last-break nil)
-(defvar type-break-time-next-break nil)
-(defvar type-break-time-last-command (current-time))
-(defvar type-break-current-time-warning-interval nil)
-(defvar type-break-current-keystroke-warning-interval nil)
-(defvar type-break-time-warning-count 0)
-(defvar type-break-keystroke-warning-count 0)
-
-
-;;;###autoload
-(defun type-break-mode (&optional prefix)
- "Enable or disable typing-break mode.
-This is a minor mode, but it is global to all buffers by default.
-
-When this mode is enabled, the user is encouraged to take typing breaks at
-appropriate intervals; either after a specified amount of time or when the
-user has exceeded a keystroke threshold. When the time arrives, the user
-is asked to take a break. If the user refuses at that time, emacs will ask
-again in a short period of time. The idea is to give the user enough time
-to find a good breaking point in his or her work, but be sufficiently
-annoying to discourage putting typing breaks off indefinitely.
-
-A negative prefix argument disables this mode.
-No argument or any non-negative argument enables it.
-
-The user may enable or disable this mode by setting the variable of the
-same name, though setting it in that way doesn't reschedule a break or
-reset the keystroke counter.
-
-If the mode was previously disabled and is enabled as a consequence of
-calling this function, it schedules a break with `type-break-schedule' to
-make sure one occurs (the user can call that command to reschedule the
-break at any time). It also initializes the keystroke counter.
-
-The variable `type-break-interval' specifies the number of seconds to
-schedule between regular typing breaks. This variable doesn't directly
-affect the time schedule; it simply provides a default for the
-`type-break-schedule' command.
-
-If set, the variable `type-break-good-rest-interval' specifies the minimum
-amount of time which is considered a reasonable typing break. Whenever
-that time has elapsed, typing breaks are automatically rescheduled for
-later even if emacs didn't prompt you to take one first. Also, if a break
-is ended before this much time has elapsed, the user will be asked whether
-or not to continue.
-
-The variable `type-break-keystroke-threshold' is used to determine the
-thresholds at which typing breaks should be considered. You can use
-the command `type-break-guestimate-keystroke-threshold' to try to
-approximate good values for this.
-
-Finally, the command `type-break-statistics' prints interesting things."
- (interactive "P")
- ;; make sure it's there.
- (add-hook 'post-command-hook 'type-break-run-tb-post-command-hook 'append)
- (add-hook 'type-break-post-command-hook 'type-break-check)
-
- (let ((already-enabled type-break-mode))
- (setq type-break-mode (>= (prefix-numeric-value prefix) 0))
-
- (cond
- ((and already-enabled type-break-mode)
- (and (interactive-p)
- (message "type-break-mode is enabled")))
- (type-break-mode
- (type-break-keystroke-reset)
- (type-break-schedule)
- (and (interactive-p)
- (message "type-break-mode is enabled and reset")))
- ((interactive-p)
- (message "type-break-mode is disabled"))))
- type-break-mode)
-
-;;;###autoload
-(defun type-break ()
- "Take a typing break.
-
-During the break, a demo selected from the functions listed in
-`type-break-demo-functions' is run.
-
-After the typing break is finished, the next break is scheduled
-as per the function `type-break-schedule'."
- (interactive)
- (type-break-cancel-schedule)
- (let ((continue t)
- (start-time (current-time)))
- (setq type-break-time-last-break start-time)
- (while continue
- (save-window-excursion
- ;; Eat the screen.
- (and (eq (selected-window) (minibuffer-window))
- (other-window 1))
- (delete-other-windows)
- (scroll-right (window-width))
- (message "Press any key to resume from typing break.")
-
- (random t)
- (let* ((len (length type-break-demo-functions))
- (idx (random len))
- (fn (nth idx type-break-demo-functions)))
- (condition-case ()
- (funcall fn)
- (error nil))))
-
- (cond
- (type-break-good-rest-interval
- (let ((break-secs (type-break-time-difference
- start-time (current-time))))
- (cond
- ((>= break-secs type-break-good-rest-interval)
- (setq continue nil))
- ;; Don't be pedantic; if user's rest was only a minute short,
- ;; why bother?
- ((> 60 (abs (- break-secs type-break-good-rest-interval)))
- (setq continue nil))
- ((funcall
- type-break-query-function
- (format "You really ought to rest %s more. Continue break? "
- (type-break-format-time (- type-break-good-rest-interval
- break-secs)))))
- (t
- (setq continue nil)))))
- (t (setq continue nil)))))
-
- (type-break-keystroke-reset)
- (type-break-schedule))
-
-
-(defun type-break-schedule (&optional time)
- "Schedule a typing break for TIME seconds from now.
-If time is not specified, default to `type-break-interval'."
- (interactive (list (and current-prefix-arg
- (prefix-numeric-value current-prefix-arg))))
- (or time (setq time type-break-interval))
- (type-break-cancel-schedule)
- (type-break-time-warning-schedule time 'reset)
- (run-at-time time nil 'type-break-alarm)
- (setq type-break-time-next-break
- (type-break-time-sum (current-time) time)))
-
-(defun type-break-cancel-schedule ()
- (type-break-cancel-time-warning-schedule)
- (let ((timer-dont-exit t))
- (cancel-function-timers 'type-break-alarm))
- (setq type-break-alarm-p nil)
- (setq type-break-time-next-break nil))
-
-(defun type-break-time-warning-schedule (&optional time resetp)
- (let (type-break-current-time-warning-interval)
- (type-break-cancel-time-warning-schedule))
- (cond
- (type-break-time-warning-intervals
- (and resetp
- (setq type-break-current-time-warning-interval
- type-break-time-warning-intervals))
-
- (or time
- (setq time (type-break-time-difference (current-time)
- type-break-time-next-break)))
-
- (while (and type-break-current-time-warning-interval
- (> (car type-break-current-time-warning-interval) time))
- (setq type-break-current-time-warning-interval
- (cdr type-break-current-time-warning-interval)))
-
- (cond
- (type-break-current-time-warning-interval
- (setq time (- time (car type-break-current-time-warning-interval)))
- (setq type-break-current-time-warning-interval
- (cdr type-break-current-time-warning-interval))
-
- (let (type-break-current-time-warning-interval)
- (type-break-cancel-time-warning-schedule))
- (run-at-time time nil 'type-break-time-warning-alarm))))))
-
-(defun type-break-cancel-time-warning-schedule ()
- (let ((timer-dont-exit t))
- (cancel-function-timers 'type-break-time-warning-alarm))
- (remove-hook 'type-break-post-command-hook 'type-break-time-warning)
- (setq type-break-current-time-warning-interval
- type-break-time-warning-intervals))
-
-(defun type-break-alarm ()
- (setq type-break-alarm-p t))
-
-(defun type-break-time-warning-alarm ()
- (type-break-time-warning-schedule)
- (setq type-break-time-warning-count type-break-warning-repeat)
- (add-hook 'type-break-post-command-hook 'type-break-time-warning 'append))
-
-
-(defun type-break-run-tb-post-command-hook ()
- (and type-break-mode
- (run-hooks 'type-break-post-command-hook)))
-
-(defun type-break-check ()
- "Ask to take a typing break if appropriate.
-This may be the case either because the scheduled time has come \(and the
-minimum keystroke threshold has been reached\) or because the maximum
-keystroke threshold has been exceeded."
- (let* ((min-threshold (car type-break-keystroke-threshold))
- (max-threshold (cdr type-break-keystroke-threshold)))
- (and type-break-good-rest-interval
- (progn
- (and (> (type-break-time-difference
- type-break-time-last-command (current-time))
- type-break-good-rest-interval)
- (progn
- (type-break-keystroke-reset)
- (setq type-break-time-last-break (current-time))
- (type-break-schedule)))
- (setq type-break-time-last-command (current-time))))
-
- (and type-break-keystroke-threshold
- (setq type-break-keystroke-count
- (+ type-break-keystroke-count (length (this-command-keys)))))
-
- ;; This has been optimized for speed; calls to input-pending-p and
- ;; checking for the minibuffer window are only done if it would
- ;; matter for the sake of querying user.
- (cond
- (type-break-alarm-p
- (cond
- ((input-pending-p))
- ((eq (selected-window) (minibuffer-window)))
- ((and min-threshold
- (< type-break-keystroke-count min-threshold))
- (type-break-schedule))
- (t
- ;; If keystroke count is within min-threshold of
- ;; max-threshold, lower it to reduce the liklihood of an
- ;; immediate subsequent query.
- (and max-threshold
- min-threshold
- (< (- max-threshold type-break-keystroke-count) min-threshold)
- (progn
- (type-break-keystroke-reset)
- (setq type-break-keystroke-count min-threshold)))
- (type-break-query))))
- ((and type-break-keystroke-warning-intervals
- max-threshold
- (= type-break-keystroke-warning-count 0)
- (type-break-check-keystroke-warning)))
- ((and max-threshold
- (> type-break-keystroke-count max-threshold)
- (not (input-pending-p))
- (not (eq (selected-window) (minibuffer-window))))
- (type-break-keystroke-reset)
- (setq type-break-keystroke-count (or min-threshold 0))
- (type-break-query)))))
-
-;; This should return t if warnings were enabled, nil otherwise.
-(defsubst type-break-check-keystroke-warning ()
- (let ((left (- (cdr type-break-keystroke-threshold)
- type-break-keystroke-count)))
- (cond
- ((null (car type-break-current-keystroke-warning-interval))
- nil)
- ((> left (car type-break-current-keystroke-warning-interval))
- nil)
- (t
- (while (and (car type-break-current-keystroke-warning-interval)
- (< left (car type-break-current-keystroke-warning-interval)))
- (setq type-break-current-keystroke-warning-interval
- (cdr type-break-current-keystroke-warning-interval)))
- (setq type-break-keystroke-warning-count type-break-warning-repeat)
- (add-hook 'type-break-post-command-hook 'type-break-keystroke-warning)
- t))))
-
-(defun type-break-query ()
- (condition-case ()
- (cond
- ((let ((type-break-mode nil))
- (funcall type-break-query-function "Take a break from typing now? "))
- (type-break))
- (t
- (type-break-schedule type-break-query-interval)))
- (quit
- (type-break-schedule type-break-query-interval))))
-
-(defun type-break-time-warning ()
- (cond
- ((and (car type-break-keystroke-threshold)
- (< type-break-keystroke-count (car type-break-keystroke-threshold))))
- ((> type-break-time-warning-count 0)
- (cond
- ((eq (selected-window) (minibuffer-window)))
- (t
- ;; Pause for a moment so previous messages can be seen.
- (sit-for 2)
- (message "Warning: typing break due in %s."
- (type-break-format-time
- (type-break-time-difference (current-time)
- type-break-time-next-break)))
- (setq type-break-time-warning-count
- (1- type-break-time-warning-count)))))
- (t
- (remove-hook 'type-break-post-command-hook 'type-break-time-warning))))
-
-(defun type-break-keystroke-warning ()
- (cond
- ((> type-break-keystroke-warning-count 0)
- (cond
- ((eq (selected-window) (minibuffer-window)))
- (t
- (sit-for 2)
- (message "Warning: typing break due in %s keystrokes."
- (- (cdr type-break-keystroke-threshold)
- type-break-keystroke-count))
- (setq type-break-keystroke-warning-count
- (1- type-break-keystroke-warning-count)))))
- (t
- (remove-hook 'type-break-post-command-hook
- 'type-break-keystroke-warning))))
-
-
-;;;###autoload
-(defun type-break-statistics ()
- "Print statistics about typing breaks in a temporary buffer.
-This includes the last time a typing break was taken, when the next one is
-scheduled, the keystroke thresholds and the current keystroke count, etc."
- (interactive)
- (with-output-to-temp-buffer "*Typing Break Statistics*"
- (princ (format "Typing break statistics\n-----------------------\n
-Last typing break : %s
-Next scheduled typing break : %s\n
-Minimum keystroke threshold : %s
-Maximum keystroke threshold : %s
-Current keystroke count : %s"
- (if type-break-time-last-break
- (current-time-string type-break-time-last-break)
- "never")
- (if (and type-break-mode type-break-time-next-break)
- (format "%s\t(%s from now)"
- (current-time-string type-break-time-next-break)
- (type-break-format-time
- (type-break-time-difference
- (current-time)
- type-break-time-next-break)))
- "none scheduled")
- (or (car type-break-keystroke-threshold) "none")
- (or (cdr type-break-keystroke-threshold) "none")
- type-break-keystroke-count))))
-
-;;;###autoload
-(defun type-break-guestimate-keystroke-threshold (wpm &optional wordlen frac)
- "Guess values for the minimum/maximum keystroke threshold for typing breaks.
-If called interactively, the user is prompted for their guess as to how
-many words per minute they usually type. From that, the command sets the
-values in `type-break-keystroke-threshold' based on a fairly simple
-algorithm involving assumptions about the average length of words (5).
-For the minimum threshold, it uses about a quarter of the computed maximum
-threshold.
-
-When called from lisp programs, the optional args WORDLEN and FRAC can be
-used to override the default assumption about average word length and the
-fraction of the maximum threshold to which to set the minimum threshold.
-FRAC should be the inverse of the fractional value; for example, a value of
-2 would mean to use one half, a value of 4 would mean to use one quarter, etc."
- (interactive "NHow many words per minute do you type? ")
- (let* ((upper (* wpm (or wordlen 5) (/ type-break-interval 60)))
- (lower (/ upper (or frac 5))))
- (or type-break-keystroke-threshold
- (setq type-break-keystroke-threshold (cons nil nil)))
- (setcar type-break-keystroke-threshold lower)
- (setcdr type-break-keystroke-threshold upper)
- (if (interactive-p)
- (message "min threshold: %d\tmax threshold: %d" lower upper)
- type-break-keystroke-threshold)))
-
-
-;;; misc functions
-
-;; Compute the difference, in seconds, between a and b, two structures
-;; similar to those returned by `current-time'.
-;; Use addition rather than logand since that is more robust; the low 16
-;; bits of the seconds might have been incremented, making it more than 16
-;; bits wide.
-(defsubst type-break-time-difference (a b)
- (+ (lsh (- (car b) (car a)) 16)
- (- (car (cdr b)) (car (cdr a)))))
-
-;; Return (in a new list the same in structure to that returned by
-;; `current-time') the sum of the arguments. Each argument may be a time
-;; list or a single integer, a number of seconds.
-;; This function keeps the high and low 16 bits of the seconds properly
-;; balanced so that the lower value never exceeds 16 bits. Otherwise, when
-;; the result is passed to `current-time-string' it will toss some of the
-;; "low" bits and return the wrong value.
-(defun type-break-time-sum (&rest tmlist)
- (let ((high 0)
- (low 0)
- (micro 0)
- tem)
- (while tmlist
- (setq tem (car tmlist))
- (setq tmlist (cdr tmlist))
- (cond
- ((numberp tem)
- (setq low (+ low tem)))
- (t
- (setq high (+ high (or (car tem) 0)))
- (setq low (+ low (or (car (cdr tem)) 0)))
- (setq micro (+ micro (or (car (cdr (cdr tem))) 0))))))
-
- (and (>= micro 1000000)
- (progn
- (setq tem (/ micro 1000000))
- (setq low (+ low tem))
- (setq micro (- micro (* tem 1000000)))))
-
- (setq tem (lsh low -16))
- (and (> tem 0)
- (progn
- (setq low (logand low 65535))
- (setq high (+ high tem))))
-
- (list high low micro)))
-
-(defsubst type-break-format-time (secs)
- (let ((mins (/ secs 60)))
- (cond
- ((= mins 1) (format "%d minute" mins))
- ((> mins 0) (format "%d minutes" mins))
- ((= secs 1) (format "%d second" secs))
- (t (format "%d seconds" secs)))))
-
-(defun type-break-keystroke-reset ()
- (setq type-break-keystroke-count 0)
- (setq type-break-keystroke-warning-count 0)
- (setq type-break-current-keystroke-warning-interval
- type-break-keystroke-warning-intervals)
- (remove-hook 'type-break-post-command-hook 'type-break-keystroke-warning))
-
-
-;;; Demo wrappers
-
-;; This is a wrapper around hanoi that calls it with an arg large enough to
-;; make the largest discs possible that will fit in the window.
-;; Also, clean up the *Hanoi* buffer after we're done.
-(defun type-break-demo-hanoi ()
- "Take a hanoiing typing break."
- (and (get-buffer "*Hanoi*")
- (kill-buffer "*Hanoi*"))
- (condition-case ()
- (progn
- (hanoi (/ (window-width) 8))
- ;; Wait for user to come back.
- (read-char)
- (kill-buffer "*Hanoi*"))
- (quit
- ;; eat char
- (read-char)
- (and (get-buffer "*Hanoi*")
- (kill-buffer "*Hanoi*")))))
-
-;; This is a wrapper around life that calls it with a `sleep' arg to make
-;; it run a little more leisurely.
-;; Also, clean up the *Life* buffer after we're done.
-(defun type-break-demo-life ()
- "Take a typing break and get a life."
- (let ((continue t))
- (while continue
- (setq continue nil)
- (and (get-buffer "*Life*")
- (kill-buffer "*Life*"))
- (condition-case ()
- (progn
- (life 3)
- ;; wait for user to return
- (read-char)
- (kill-buffer "*Life*"))
- (life-extinct
- (message (get 'life-extinct 'error-message))
- (sit-for 3)
- ;; restart demo
- (setq continue t))
- (quit
- (and (get-buffer "*Life*")
- (kill-buffer "*Life*")))))))
-
-;; Boring demo, but doesn't use many cycles
-(defun type-break-demo-boring ()
- "Boring typing break demo."
- (let ((rmsg "Press any key to resume from typing break")
- (buffer-name "*Typing Break Buffer*")
- line col pos
- elapsed timeleft tmsg)
- (condition-case ()
- (progn
- (switch-to-buffer (get-buffer-create buffer-name))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (setq line (1+ (/ (window-height) 2)))
- (setq col (/ (- (window-width) (length rmsg)) 2))
- (insert (make-string line ?\C-j)
- (make-string col ?\ )
- rmsg)
- (forward-line -1)
- (beginning-of-line)
- (setq pos (point))
- (while (not (input-pending-p))
- (delete-region pos (progn
- (goto-char pos)
- (end-of-line)
- (point)))
- (setq elapsed (type-break-time-difference
- type-break-time-last-break
- (current-time)))
- (cond
- (type-break-good-rest-interval
- (setq timeleft (- type-break-good-rest-interval elapsed))
- (if (> timeleft 0)
- (setq tmsg (format "You should rest for %s more"
- (type-break-format-time timeleft)))
- (setq tmsg (format "Typing break has lasted %s"
- (type-break-format-time elapsed)))))
- (t
- (setq tmsg (format "Typing break has lasted %s"
- (type-break-format-time elapsed)))))
- (setq col (/ (- (window-width) (length tmsg)) 2))
- (insert (make-string col ?\ ) tmsg)
- (goto-char (point-min))
- (sit-for 60))
- (read-char)
- (kill-buffer buffer-name))
- (quit
- (and (get-buffer buffer-name)
- (kill-buffer buffer-name))))))
-
-
-(provide 'type-break)
-
-;; Do not do this at load time because it makes it impossible to load this
-;; file into temacs and then dump it.
-;(type-break-mode t)
-
-;; local variables:
-;; vc-make-backup-files: t
-;; end:
-
-;;; type-break.el ends here
diff --git a/lisp/uncompress.el b/lisp/uncompress.el
deleted file mode 100644
index cdfa1882d38..00000000000
--- a/lisp/uncompress.el
+++ /dev/null
@@ -1,97 +0,0 @@
-;;; uncompress.el --- auto-decompression hook for visiting .Z files
-
-;; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package can be used to arrange for automatic uncompress of
-;; files packed with the UNIX compress(1) utility when they are visited.
-;; All that's necessary is to load it. This can conveniently be done from
-;; your .emacs file.
-
-;;; Code:
-
-;; 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.
-
-(defvar uncompress-program "gunzip"
- "Program to use for uncompression.")
-
-(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-program 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)))
-(or (assoc "\\.gz$" auto-mode-alist)
- (setq auto-mode-alist
- (cons '("\\.gz$" . uncompress-while-visiting) auto-mode-alist)))
-
-(defun uncompress-while-visiting ()
- "Temporary \"major mode\" used for .Z and .gz files, to uncompress them.
-It then selects a major mode from the uncompressed file name and contents."
- (if (and (not (null buffer-file-name))
- (string-match "\\.Z$" buffer-file-name))
- (set-visited-file-name
- (substring buffer-file-name 0 (match-beginning 0)))
- (if (and (not (null buffer-file-name))
- (string-match "\\.gz$" buffer-file-name))
- (set-visited-file-name
- (substring buffer-file-name 0 (match-beginning 0)))))
- (message "Uncompressing...")
- (let ((buffer-read-only nil))
- (shell-command-on-region (point-min) (point-max) uncompress-program 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)))
-
-(defun find-compressed-version ()
- "Hook to read and uncompress the compressed version of a file."
- ;; Just pretend we had visited the compressed file,
- ;; and uncompress-while-visiting will do the rest.
- (let (name)
- (if (file-exists-p (setq name (concat buffer-file-name ".Z")))
- (setq buffer-file-name name)
- (if (file-exists-p (setq name (concat buffer-file-name ".gz")))
- (setq buffer-file-name name)))
- (if (eq name buffer-file-name)
- (progn
- (insert-file-contents buffer-file-name t)
- (goto-char (point-min))
- (setq error nil)
- t))))
-
-(provide 'uncompress)
-
-;;; uncompress.el ends here
diff --git a/lisp/uniquify.el b/lisp/uniquify.el
deleted file mode 100644
index 0152721dad0..00000000000
--- a/lisp/uniquify.el
+++ /dev/null
@@ -1,384 +0,0 @@
-;;; uniquify.el --- unique buffer names dependent on file name
-
-;; Copyright (c) 1989, 1995 Free Software Foundation, Inc.
-
-;; Author: Dick King <king@reasoning.com>
-;; Maintainer: Michael Ernst <mernst@theory.lcs.mit.edu>
-;; Created: 15 May 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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Emacs's standard method for making buffer names unique adds <2>, <3>,
-;; etc. to the end of (all but one of) the buffers. This file replaces
-;; that behavior, for buffers visiting files and dired buffers, with a
-;; uniquification that adds parts of the file name until the buffer names
-;; are unique. For instance, buffers visiting /u/mernst/tmp/Makefile and
-;; /usr/projects/zaphod/Makefile would be named Makefile|tmp and
-;; Makefile|zaphod, respectively (instead of Makefile and Makefile<2>).
-;; Other buffer name styles are also available.
-
-;; To use this file, just load it.
-;; To disable it after loading, set variable uniquify-buffer-name-style to nil.
-;; For other options, see "User-visible variables", below.
-
-;; A version of uniquify.el that works under Emacs 18, Emacs 19, XEmacs,
-;; and InfoDock is available from the maintainer.
-
-;;; Change Log:
-
-;; Originally by Dick King <king@reasoning.com> 15 May 86
-;; Converted for Emacs 18 by Stephen Gildea <gildea@lcs.mit.edu>
-;; Make uniquify-min-dir-content 0 truly non-invasive. gildea 23 May 89
-;; Some cleanup. uniquify-min-dir-content default 0. gildea 01 Jun 89
-;; Don't rename to "". Michael Ernst <mernst@theory.lcs.mit.edu> 15 Jun 94
-;; Add kill-buffer-hook. Kenneth Manheimer <ken.manheimer@nist.gov> 09 May 95
-;; Add advice for rename-buffer and create-file-buffer, handle dired buffers,
-;; kill-buffer-rationalize-buffer-names-p, documentation. mernst 24 May 95
-;; Remove free variables, fix typos. mernst 5 Jun 95
-;; Efficiently support Emacs 19.27 & earlier. ken.manheimer, mernst 10 Jun 95
-;; Rename user options to "uniquify-...", add uniquify-reverse-dir-content-p,
-;; add uniquify-ask-about-buffer-names-p. king, mernst 13 Jun 95
-;; Prefix functions by "uniquify-..."; rename mnemonic-buffer-names to
-;; uniquify-buffer-name-style; add 'forward and 'post-forward-angle-brackets
-;; styles; remove uniquify-reverse-dir-content-p; add
-;; uniquify-trailing-separator-p. mernst 4 Aug 95
-
-;; Valuable feedback was provided by
-;; Paul Smith <psmith@baynetworks.com>,
-;; Alastair Burt <burt@dfki.uni-kl.de>,
-;; Bob Weiner <weiner@footloose.sps.mot.com>,
-;; Albert L. Ting <alt@vlibs.com>,
-;; gyro@reasoning.com.
-
-
-;;; Code:
-
-(provide 'uniquify)
-
-;;; User-visible variables
-
-(defvar uniquify-buffer-name-style 'post-forward
- "*If non-nil, buffer names are uniquified with parts of directory name.
-The value determines the buffer name style and is one of `forward',
-`reverse', `post-forward' (the default), or `post-forward-angle-brackets'.
-For example, files `/foo/bar/mumble/name' and `/baz/quux/mumble/name'
-would have the following buffer names in the various styles:
- forward bar/mumble/name quux/mumble/name
- reverse name\\mumble\\bar name\\mumble\\quux
- post-forward name|bar/mumble name|quux/mumble
- post-forward-angle-brackets name<bar/mumble> name<quux/mumble>
- nil name name<2>")
-
-(defvar uniquify-after-kill-buffer-p nil
- "*If non-nil, rerationalize buffer names after a buffer has been killed.
-This can be dangerous if Emacs Lisp code is keeping track of buffers by their
-names (rather than keeping pointers to the buffers themselves).")
-
-(defconst uniquify-ask-about-buffer-names-p nil
- "*If non-nil, permit user to choose names for buffers with same base file.
-If the user chooses to name a buffer, uniquification is preempted and no
-other buffer names are changed.")
-
-(defvar uniquify-min-dir-content 0
- "*Minimum parts of directory name included in buffer name.")
-
-(defvar uniquify-separator nil
- "*String separator for buffer name components.
-When `uniquify-buffer-name-style' is `post-forward', separates
-base file name from directory part in buffer names (default \"|\").
-When `uniquify-buffer-name-style' is `reverse', separates all
-file name components (default \"\\\").")
-
-(defvar uniquify-trailing-separator-p nil
- "*If non-nil, add a file name separator to dired buffer names.
-If `uniquify-buffer-name-style' is `forward', add the separator at the end;
-if it is `reverse', add the separator at the beginning; otherwise, this
-variable is ignored.")
-
-
-;;; Utilities
-
-(defmacro uniquify-push (item list)
- (` (setq (, list) (cons (, item) (, list)))))
-
-(defmacro uniquify-fix-list-base (a)
- (` (car (, a))))
-
-(defmacro uniquify-fix-list-filename (a)
- (` (car (cdr (, a)))))
-
-(defmacro uniquify-fix-list-buffer (a)
- (` (car (cdr (cdr (, a))))))
-
-(defmacro uniquify-cadddr (a)
- (` (car (cdr (cdr (cdr (, a)))))))
-
-;; Internal variables used free
-(defvar uniquify-non-file-buffer-names nil)
-(defvar uniquify-possibly-resolvable nil)
-
-;;; Main entry point.
-
-(defun uniquify-rationalize-file-buffer-names (&optional newbuffile newbuf)
- "Makes file buffer names unique by adding segments from file name.
-If `uniquify-min-dir-content' > 0, always pulls that many
-file name elements. Arguments cause only a subset of buffers to be renamed."
- (interactive)
- (let (fix-list
- uniquify-non-file-buffer-names
- (depth uniquify-min-dir-content))
- (let ((buffers (buffer-list)))
- (while buffers
- (let* ((buffer (car buffers))
- (bfn (if (eq buffer newbuf)
- (and newbuffile
- (expand-file-name newbuffile))
- (uniquify-buffer-file-name buffer)))
- (rawname (and bfn (file-name-nondirectory bfn)))
- (deserving (and rawname
- (or (not newbuffile)
- (equal rawname
- (file-name-nondirectory newbuffile))))))
- (if deserving
- (uniquify-push (list rawname bfn buffer nil) fix-list)
- (uniquify-push (list (buffer-name buffer))
- uniquify-non-file-buffer-names)))
- (setq buffers (cdr buffers))))
- ;; selects buffers whose names may need changing, and others that
- ;; may conflict.
- (setq fix-list
- (sort fix-list 'uniquify-fix-list-filename-lessp))
- ;; bringing conflicting names together
- (uniquify-rationalize-a-list fix-list depth)
- (mapcar 'uniquify-unrationalized-buffer fix-list)))
-
-;; uniquify's version of buffer-file-name
-(defun uniquify-buffer-file-name (buffer)
- "Return name of file BUFFER is visiting, or nil if none.
-Works on dired buffers as well as ordinary file-visiting buffers."
- (or (buffer-file-name buffer)
- (save-excursion
- (set-buffer buffer)
- list-buffers-directory)))
-
-(defun uniquify-fix-list-filename-lessp (fixlist1 fixlist2)
- (uniquify-filename-lessp
- (uniquify-fix-list-filename fixlist1) (uniquify-fix-list-filename fixlist2)))
-
-;; This examines the filename components in reverse order.
-(defun uniquify-filename-lessp (s1 s2)
- (let ((s1f (file-name-nondirectory s1))
- (s2f (file-name-nondirectory s2)))
- (and (not (equal s2f ""))
- (or (string-lessp s1f s2f)
- (and (equal s1f s2f)
- (let ((s1d (file-name-directory s1))
- (s2d (file-name-directory s2)))
- (and (not (<= (length s2d) 1))
- (or (<= (length s1d) 1)
- (uniquify-filename-lessp
- (substring s1d 0 -1)
- (substring s2d 0 -1))))))))))
-
-;; Was named do-the-buffers-you-couldnt-rationalize
-(defun uniquify-unrationalized-buffer (item)
- (or (uniquify-cadddr item) nil)) ;maybe better in the future
-
-(defun uniquify-rationalize-a-list (fix-list depth)
- (let (conflicting-sublist
- (old-name "")
- proposed-name uniquify-possibly-resolvable)
- (while fix-list
- (let ((item (car fix-list)))
- (setq proposed-name (uniquify-get-proposed-name item depth))
- (if (not (equal proposed-name old-name))
- (progn
- (uniquify-rationalize-conflicting-sublist
- conflicting-sublist old-name depth)
- (setq conflicting-sublist nil)))
- (uniquify-push item conflicting-sublist)
- (setq old-name proposed-name))
- (setq fix-list (cdr fix-list)))
- (uniquify-rationalize-conflicting-sublist
- conflicting-sublist old-name depth)))
-
-(defun uniquify-get-proposed-name (item depth)
- (let (index
- (extra-string "")
- (n depth)
- (base (uniquify-fix-list-base item))
- (fn (uniquify-fix-list-filename item)))
- (while (and (> n 0)
- (setq index (string-match
- (concat "\\(^\\|/[^/]*\\)/"
- (regexp-quote extra-string)
- (regexp-quote base)
- "\\'")
- fn)))
- (setq extra-string (substring fn
- (if (zerop index) 0 (1+ index))
- ;; (- (length base)) fails for base = "".
- ;; Equivalently, we could have used
- ;; (apply 'substring ...
- ;; (and (not (string= "" base))
- ;; (list (- (length base)))))
- (- (length fn) (length base)))
- n (1- n)))
- (if (zerop n) (setq uniquify-possibly-resolvable t))
-
-
- ;; Distinguish directories by adding extra separator.
- (if (and uniquify-trailing-separator-p
- (file-directory-p fn)
- (not (string-equal base "")))
- (cond ((eq uniquify-buffer-name-style 'forward)
- (setq base (concat base "/")))
- ((eq uniquify-buffer-name-style 'reverse)
- (setq base (concat (or uniquify-separator "\\") base)))))
-
- ;; Trim trailing separator on directory part
- (if (and (not (string-equal extra-string ""))
- (or (eq uniquify-buffer-name-style 'post-forward)
- (eq uniquify-buffer-name-style 'post-forward-angle-brackets)))
- (setq extra-string (substring extra-string 0
- (- (length extra-string) 1))))
-
- (cond ((string-equal extra-string "")
- base)
- ((string-equal base "")
- extra-string)
- ((eq uniquify-buffer-name-style 'forward)
- (concat extra-string base))
- ((eq uniquify-buffer-name-style 'reverse)
- (concat base (uniquify-reverse-components extra-string)))
- ((eq uniquify-buffer-name-style 'post-forward)
- (concat base (or uniquify-separator "|") extra-string))
- ((eq uniquify-buffer-name-style 'post-forward-angle-brackets)
- (concat base "<" extra-string ">"))
- (t (error "Bad value for uniquify-buffer-name-style: %s"
- uniquify-buffer-name-style)))))
-
-
-;; Deal with conflicting-sublist, which is set by uniquify-rationalize-a-list.
-;; This is only called by uniquify-rationalize-a-list.
-(defun uniquify-rationalize-conflicting-sublist (conflicting-sublist old-name depth)
- (or (null conflicting-sublist)
- (and (null (cdr conflicting-sublist))
- (not (assoc old-name uniquify-non-file-buffer-names))
- (or (and (not (string= old-name ""))
- (uniquify-rename-buffer (car conflicting-sublist) old-name))
- t))
- (if uniquify-possibly-resolvable
- (uniquify-rationalize-a-list conflicting-sublist (1+ depth)))))
-
-(defun uniquify-rename-buffer (item newname)
- (let ((buffer (uniquify-fix-list-buffer item)))
- (if (not (equal newname (buffer-name buffer)))
- (let ((unset (current-buffer))
- ;; avoid hooks on rename-buffer
- (uniquify-buffer-name-style nil))
- (set-buffer buffer)
- (rename-buffer newname)
- (set-buffer unset))))
- (rplaca (nthcdr 3 item) t))
-
-(defun uniquify-reverse-components (instring)
- (let ((sofar '())
- (cursor 0)
- (len (length instring))
- (sep (or uniquify-separator "\\")))
- (while (< cursor len)
- (if (= (aref instring cursor) ?/)
- (setq sofar (cons sep sofar)
- cursor (1+ cursor))
- (let ((first-slash (or (string-match "/" instring cursor) len)))
- (setq sofar (cons (substring instring cursor first-slash) sofar)
- cursor first-slash))))
- (apply (function concat) sofar)))
-
-
-;;; Hooks from the rest of Emacs
-
-;; Emacs 19 (Emacs or XEmacs)
-
-;; The logical place to put all this code is in generate-new-buffer-name.
-;; It's written in C, so we would add a generate-new-buffer-name-function
-;; which, if non-nil, would be called instead of the C. One problem with
-;; that is that generate-new-buffer-name takes a potential buffer name as
-;; its argument -- not other information, such as what file the buffer will
-;; visit.
-
-;; The below solution works because generate-new-buffer-name is called
-;; only by rename-buffer (which, as of 19.29, is never called from C) and
-;; generate-new-buffer, which is called only by Lisp functions
-;; create-file-buffer and rename-uniquely. Rename-uniquely generally
-;; isn't used for buffers visiting files, so it's sufficient to hook
-;; rename-buffer and create-file-buffer. (Setting find-file-hooks isn't
-;; sufficient.)
-
-(defadvice rename-buffer (after rename-buffer-uniquify activate)
- "Uniquify buffer names with parts of directory name."
- (if (and uniquify-buffer-name-style
- ;; UNIQUE argument
- (ad-get-arg 1))
- (progn
- (if uniquify-after-kill-buffer-p
- ;; call with no argument; rationalize vs. old name as well as new
- (uniquify-rationalize-file-buffer-names)
- ;; call with argument: rationalize vs. new name only
- (uniquify-rationalize-file-buffer-names
- (uniquify-buffer-file-name (current-buffer)) (current-buffer)))
- (setq ad-return-value (buffer-name (current-buffer))))))
-
-(defadvice create-file-buffer (after create-file-buffer-uniquify activate)
- "Uniquify buffer names with parts of directory name."
- (if uniquify-buffer-name-style
- (uniquify-rationalize-file-buffer-names (ad-get-arg 0) ad-return-value)))
-
-;; Buffer deletion
-;; Rerationalize after a buffer is killed, to reduce coinciding buffer names.
-;; This mechanism uses `kill-buffer-hook', which runs *before* deletion.
-;; That means that the kill-buffer-hook function cannot just delete the
-;; buffer -- it has to set something to do the rationalization *later*.
-;; It actually puts another function on `post-command-hook'. This other
-;; function runs the rationalization and then removes itself from the hook.
-;; Is there a better way to accomplish this?
-;; (This ought to set some global variables so the work is done only for
-;; buffers with names similar to the deleted buffer. -MDE)
-
-(defun delay-uniquify-rationalize-file-buffer-names ()
- "Add `delayed-uniquify-rationalize-file-buffer-names' to `post-command-hook'.
-For use on, eg, `kill-buffer-hook', to rationalize *after* buffer deletion."
- (if (and uniquify-buffer-name-style
- uniquify-after-kill-buffer-p)
- (add-hook 'post-command-hook
- 'delayed-uniquify-rationalize-file-buffer-names)))
-
-(defun delayed-uniquify-rationalize-file-buffer-names ()
- "Rerationalize buffer names and remove self from `post-command-hook'.
-See also `delay-rationalize-file-buffer-names' for hook setter."
- (uniquify-rationalize-file-buffer-names)
- (remove-hook 'post-command-hook
- 'delayed-uniquify-rationalize-file-buffer-names))
-
-(add-hook 'kill-buffer-hook 'delay-uniquify-rationalize-file-buffer-names)
-
-;;; uniquify.el ends here
-
diff --git a/lisp/unused.el b/lisp/unused.el
deleted file mode 100644
index 1cb956b213f..00000000000
--- a/lisp/unused.el
+++ /dev/null
@@ -1,44 +0,0 @@
-;;; unused.el --- editing commands in GNU Emacs that turned out not to be used.
-;;; This file is in the public domain, as it was distributed in
-;;; 1985 or 1986 without a copyright notice. Written by RMS.
-
-;; Maintainer: FSF
-;; Keywords: emulations
-
-;;; Commentary:
-
-;; These were added with an eye to making possible a more CCA-compatible
-;; command set; but that turned out not to be interesting.
-
-;;; Code:
-
-(defun mark-beginning-of-buffer ()
- "Set mark at the beginning of the buffer."
- (interactive)
- (push-mark (point-min)))
-
-(defun mark-end-of-buffer ()
- "Set mark at the end of the buffer."
- (interactive)
- (push-mark (point-max)))
-
-(defun upcase-char (arg)
- "Uppercasify ARG chars starting from point. Point doesn't move"
- (interactive "p")
- (save-excursion
- (upcase-region (point) (progn (forward-char arg) (point)))))
-
-(defun forward-to-word (arg)
- "Move forward until encountering the beginning of a word.
-With argument, do this that many times."
- (interactive "p")
- (or (re-search-forward (if (> arg 0) "\\W\\b" "\\b\\W") nil t arg)
- (goto-char (if (> arg 0) (point-max) (point-min)))))
-
-(defun backward-to-word (arg)
- "Move backward until encountering the end of a word.
-With argument, do this that many times."
- (interactive "p")
- (forward-to-word (- arg)))
-
-;;; unused.el ends here
diff --git a/lisp/userlock.el b/lisp/userlock.el
deleted file mode 100644
index 7844f4544bf..00000000000
--- a/lisp/userlock.el
+++ /dev/null
@@ -1,149 +0,0 @@
-;;; userlock.el --- handle file access contention between multiple users
-
-;; Copyright (C) 1985, 1986 Free Software Foundation, inc.
-
-;; Maintainer: FSF
-;; Keywords: internal
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This file is autoloaded to handle certain conditions
-;; detected by the file-locking code within Emacs.
-;; The two entry points are `ask-user-about-lock' and
-;; `ask-user-about-supersession-threat'.
-
-;;; Code:
-
-(put 'file-locked 'error-conditions '(file-locked file-error error))
-
-;;;###autoload
-(defun ask-user-about-lock (fn opponent)
- "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."
- (discard-input)
- (save-window-excursion
- (let (answer)
- (while (null answer)
- (message "%s is locking %s: action (s, q, p, ?)? " opponent fn)
- (let ((tem (let ((inhibit-quit t)
- (cursor-in-echo-area t))
- (prog1 (downcase (read-char))
- (setq quit-flag nil)))))
- (if (= tem help-char)
- (ask-user-about-lock-help)
- (setq answer (assoc tem '((?s . t)
- (?q . yield)
- (?\C-g . yield)
- (?p . nil)
- (?? . help))))
- (cond ((null answer)
- (beep)
- (message "Please type q, s, or p; or ? for help")
- (sit-for 3))
- ((eq (cdr answer) 'help)
- (ask-user-about-lock-help)
- (setq answer nil))
- ((eq (cdr answer) 'yield)
- (signal 'file-locked (list "File is locked" fn opponent)))))))
- (cdr answer))))
-
-(defun ask-user-about-lock-help ()
- (with-output-to-temp-buffer "*Help*"
- (princ "It has been detected that you want to modify a file that someone else has
-already started modifying in EMACS.
-
-You can <s>teal the file; The other user becomes the
- intruder if (s)he ever unmodifies the file and then changes it again.
-You can <p>roceed; you edit at your own (and the other user's) risk.
-You can <q>uit; don't modify this file.")
- (save-excursion
- (set-buffer standard-output)
- (help-mode))))
-
-(put
- 'file-supersession 'error-conditions '(file-supersession file-error error))
-
-;;;###autoload
-(defun ask-user-about-supersession-threat (fn)
- "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.
-The buffer in question is current when this function is called."
- (discard-input)
- (save-window-excursion
- (let (answer)
- (while (null answer)
- (message "%s changed on disk; really edit the buffer? (y, n, r or C-h) "
- (file-name-nondirectory fn))
- (let ((tem (downcase (let ((cursor-in-echo-area t))
- (read-char)))))
- (setq answer
- (if (= tem help-char)
- 'help
- (cdr (assoc tem '((?n . yield)
- (?\C-g . yield)
- (?y . proceed)
- (?r . revert)
- (?? . help))))))
- (cond ((null answer)
- (beep)
- (message "Please type y, n or r; or ? for help")
- (sit-for 3))
- ((eq answer 'help)
- (ask-user-about-supersession-help)
- (setq answer nil))
- ((eq answer 'revert)
- (revert-buffer nil (not (buffer-modified-p)))
- ; ask confirmation iff buffer modified
- (signal 'file-supersession
- (list "File reverted" fn)))
- ((eq answer 'yield)
- (signal 'file-supersession
- (list "File changed on disk" fn))))))
- (message
- "File on disk now will become a backup file if you save these changes.")
- (setq buffer-backed-up nil))))
-
-(defun ask-user-about-supersession-help ()
- (with-output-to-temp-buffer "*Help*"
- (princ "You want to modify a buffer whose disk file has changed
-since you last read it in or saved it with this buffer.
-
-If you say `y' to go ahead and modify this buffer,
-you risk ruining the work of whoever rewrote the file.
-If you say `r' to revert, the contents of the buffer are refreshed
-from the file on disk.
-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.")
- (save-excursion
- (set-buffer standard-output)
- (help-mode))))
-
-;;; userlock.el ends here
diff --git a/lisp/vc-hooks.el b/lisp/vc-hooks.el
deleted file mode 100644
index ffcb5930de7..00000000000
--- a/lisp/vc-hooks.el
+++ /dev/null
@@ -1,1075 +0,0 @@
-;;; vc-hooks.el --- resident support for version-control
-
-;; Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
-;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
-;; Maintainer: Andre Spiegel <spiegel@inf.fu-berlin.de>
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This is the always-loaded portion of VC.
-;; It takes care VC-related activities that are done when you visit a file,
-;; so that vc.el itself is loaded only when you use a VC command.
-;; See the commentary of vc.el.
-
-;;; Code:
-
-;; Customization Variables (the rest is in vc.el)
-
-(defvar vc-default-back-end nil
- "*Back-end actually used by this interface; may be SCCS or RCS.
-The value is only computed when needed to avoid an expensive search.")
-
-(defvar vc-handle-cvs t
- "*If non-nil, use VC for files managed with CVS.
-If it is nil, don't use VC for those files.")
-
-(defvar vc-rcsdiff-knows-brief nil
- "*Indicates whether rcsdiff understands the --brief option.
-The value is either `yes', `no', or nil. If it is nil, VC tries
-to use --brief and sets this variable to remember whether it worked.")
-
-(defvar vc-path
- (if (file-directory-p "/usr/sccs")
- '("/usr/sccs")
- nil)
- "*List of extra directories to search for version control commands.")
-
-(defvar vc-master-templates
- '(("%sRCS/%s,v" . RCS) ("%s%s,v" . RCS) ("%sRCS/%s" . RCS)
- ("%sSCCS/s.%s" . SCCS) ("%ss.%s". SCCS)
- vc-find-cvs-master)
- "*Where to look for version-control master files.
-The first pair corresponding to a given back end is used as a template
-when creating new masters.")
-
-(defvar vc-make-backup-files nil
- "*If non-nil, backups of registered files are made as with other files.
-If nil (the default), files covered by version control don't get backups.")
-
-(defvar vc-follow-symlinks 'ask
- "*Indicates what to do if you visit a symbolic link to a file
-that is under version control. Editing such a file through the
-link bypasses the version control system, which is dangerous and
-probably not what you want.
- If this variable is t, VC follows the link and visits the real file,
-telling you about it in the echo area. If it is `ask', VC asks for
-confirmation whether it should follow the link. If nil, the link is
-visited and a warning displayed.")
-
-(defvar vc-display-status t
- "*If non-nil, display revision number and lock status in modeline.
-Otherwise, not displayed.")
-
-(defvar vc-consult-headers t
- "*If non-nil, identify work files by searching for version headers.")
-
-(defvar vc-keep-workfiles t
- "*If non-nil, don't delete working files after registering changes.
-If the back-end is CVS, workfiles are always kept, regardless of the
-value of this flag.")
-
-(defvar vc-mistrust-permissions nil
- "*If non-nil, don't assume that permissions and ownership track
-version-control status. If nil, do rely on the permissions.
-See also variable `vc-consult-headers'.")
-
-(defun vc-mistrust-permissions (file)
- ;; Access function to the above.
- (or (eq vc-mistrust-permissions 't)
- (and vc-mistrust-permissions
- (funcall vc-mistrust-permissions
- (vc-backend-subdirectory-name file)))))
-
-;; Tell Emacs about this new kind of minor mode
-(if (not (assoc 'vc-mode minor-mode-alist))
- (setq minor-mode-alist (cons '(vc-mode vc-mode)
- minor-mode-alist)))
-
-(make-variable-buffer-local 'vc-mode)
-(put 'vc-mode 'permanent-local t)
-
-;; We need a notion of per-file properties because the version
-;; control state of a file is expensive to derive --- we compute
-;; them when the file is initially found, keep them up to date
-;; during any subsequent VC operations, and forget them when
-;; the buffer is killed.
-
-(defmacro vc-error-occurred (&rest body)
- (list 'condition-case nil (cons 'progn (append body '(nil))) '(error t)))
-
-(defvar vc-file-prop-obarray [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
- "Obarray for per-file properties.")
-
-(defvar vc-buffer-backend t)
-(make-variable-buffer-local 'vc-buffer-backend)
-
-(defun vc-file-setprop (file property value)
- ;; set per-file property
- (put (intern file vc-file-prop-obarray) property value))
-
-(defun vc-file-getprop (file property)
- ;; get per-file property
- (get (intern file vc-file-prop-obarray) property))
-
-(defun vc-file-clearprops (file)
- ;; clear all properties of a given file
- (setplist (intern file vc-file-prop-obarray) nil))
-
-;;; Functions that determine property values, by examining the
-;;; working file, the master file, or log program output
-
-(defun vc-match-substring (bn)
- (buffer-substring (match-beginning bn) (match-end bn)))
-
-(defun vc-lock-file (file)
- ;; Generate lock file name corresponding to FILE
- (let ((master (vc-name file)))
- (and
- master
- (string-match "\\(.*/\\)s\\.\\(.*\\)" master)
- (concat
- (substring master (match-beginning 1) (match-end 1))
- "p."
- (substring master (match-beginning 2) (match-end 2))))))
-
-(defun vc-parse-buffer (patterns &optional file properties)
- ;; Use PATTERNS to parse information out of the current buffer.
- ;; Each element of PATTERNS is a list of 2 to 3 elements. The first element
- ;; is the pattern to be matched, and the second (an integer) is the
- ;; number of the subexpression that should be returned. If there's
- ;; a third element (also the number of a subexpression), that
- ;; subexpression is assumed to be a date field and we want the most
- ;; recent entry matching the template.
- ;; If FILE and PROPERTIES are given, the latter must be a list of
- ;; properties of the same length as PATTERNS; each property is assigned
- ;; the corresponding value.
- (mapcar (function (lambda (p)
- (goto-char (point-min))
- (cond
- ((eq (length p) 2) ;; search for first entry
- (let ((value nil))
- (if (re-search-forward (car p) nil t)
- (setq value (vc-match-substring (elt p 1))))
- (if file
- (progn (vc-file-setprop file (car properties) value)
- (setq properties (cdr properties))))
- value))
- ((eq (length p) 3) ;; search for latest entry
- (let ((latest-date "") (latest-val))
- (while (re-search-forward (car p) nil t)
- (let ((date (vc-match-substring (elt p 2))))
- (if (string< latest-date date)
- (progn
- (setq latest-date date)
- (setq latest-val
- (vc-match-substring (elt p 1)))))))
- (if file
- (progn (vc-file-setprop file (car properties) latest-val)
- (setq properties (cdr properties))))
- latest-val)))))
- patterns)
- )
-
-(defun vc-insert-file (file &optional limit blocksize)
- ;; Insert the contents of FILE into the current buffer.
- ;; Optional argument LIMIT is a regexp. If present,
- ;; the file is inserted in chunks of size BLOCKSIZE
- ;; (default 8 kByte), until the first occurrence of
- ;; LIMIT is found. The function returns nil if FILE
- ;; doesn't exist.
- (erase-buffer)
- (cond ((file-exists-p file)
- (cond (limit
- (if (not blocksize) (setq blocksize 8192))
- (let (found s)
- (while (not found)
- (setq s (buffer-size))
- (goto-char (1+ s))
- (setq found
- (or (zerop (car (cdr
- (insert-file-contents file nil s
- (+ s blocksize)))))
- (progn (beginning-of-line)
- (re-search-forward limit nil t)))))))
- (t (insert-file-contents file)))
- (set-buffer-modified-p nil)
- (auto-save-mode nil)
- t)
- (t nil)))
-
-(defun vc-parse-locks (file locks)
- ;; Parse RCS or SCCS locks.
- ;; The result is a list of the form ((VERSION USER) (VERSION USER) ...),
- ;; which is returned and stored into the property `vc-master-locks'.
- (if (not locks)
- (vc-file-setprop file 'vc-master-locks 'none)
- (let ((found t) (index 0) master-locks version user)
- (cond ((eq (vc-backend file) 'SCCS)
- (while (string-match "^\\([0-9.]+\\) [0-9.]+ \\([^ ]+\\) .*\n?"
- locks index)
- (setq version (substring locks
- (match-beginning 1) (match-end 1)))
- (setq user (substring locks
- (match-beginning 2) (match-end 2)))
- (setq master-locks (append master-locks
- (list (cons version user))))
- (setq index (match-end 0))))
- ((eq (vc-backend file) 'RCS)
- (while (string-match "[ \t\n]*\\([^:]+\\):\\([0-9.]+\\)"
- locks index)
- (setq version (substring locks
- (match-beginning 2) (match-end 2)))
- (setq user (substring locks
- (match-beginning 1) (match-end 1)))
- (setq master-locks (append master-locks
- (list (cons version user))))
- (setq index (match-end 0)))
- (if (string-match ";[ \t\n]+strict;" locks index)
- (vc-file-setprop file 'vc-checkout-model 'manual)
- (vc-file-setprop file 'vc-checkout-model 'implicit))))
- (vc-file-setprop file 'vc-master-locks (or master-locks 'none)))))
-
-(defun vc-simple-command (okstatus command file &rest args)
- ;; Simple version of vc-do-command, for use in vc-hooks only.
- ;; Don't switch to the *vc-info* buffer before running the
- ;; command, because that would change its default directory
- (save-excursion (set-buffer (get-buffer-create "*vc-info*"))
- (erase-buffer))
- (let ((exec-path (append vc-path exec-path)) exec-status
- ;; Add vc-path to PATH for the execution of this command.
- (process-environment
- (cons (concat "PATH=" (getenv "PATH")
- path-separator
- (mapconcat 'identity vc-path path-separator))
- process-environment)))
- (setq exec-status
- (apply 'call-process command nil "*vc-info*" nil
- (append args (list file))))
- (cond ((> exec-status okstatus)
- (switch-to-buffer (get-file-buffer file))
- (shrink-window-if-larger-than-buffer
- (display-buffer "*vc-info*"))
- (error "Couldn't find version control information")))
- exec-status))
-
-(defun vc-fetch-master-properties (file)
- ;; Fetch those properties of FILE that are stored in the master file.
- ;; For an RCS file, we don't get vc-latest-version vc-your-latest-version
- ;; here because that is slow.
- ;; That gets done if/when the functions vc-latest-version
- ;; and vc-your-latest-version get called.
- (save-excursion
- (cond
- ((eq (vc-backend file) 'SCCS)
- (set-buffer (get-buffer-create "*vc-info*"))
- (if (vc-insert-file (vc-lock-file file))
- (vc-parse-locks file (buffer-string))
- (vc-file-setprop file 'vc-master-locks 'none))
- (vc-insert-file (vc-name file) "^\001e")
- (vc-parse-buffer
- (list '("^\001d D \\([^ ]+\\)" 1)
- (list (concat "^\001d D \\([^ ]+\\) .* "
- (regexp-quote (vc-user-login-name)) " ") 1))
- file
- '(vc-latest-version vc-your-latest-version)))
-
- ((eq (vc-backend file) 'RCS)
- (set-buffer (get-buffer-create "*vc-info*"))
- (vc-insert-file (vc-name file) "^[0-9]")
- (vc-parse-buffer
- (list '("^head[ \t\n]+\\([^;]+\\);" 1)
- '("^branch[ \t\n]+\\([^;]+\\);" 1)
- '("^locks[ \t\n]*\\([^;]*;\\([ \t\n]*strict;\\)?\\)" 1))
- file
- '(vc-head-version
- vc-default-branch
- vc-master-locks))
- ;; determine vc-master-workfile-version: it is either the head
- ;; of the trunk, the head of the default branch, or the
- ;; "default branch" itself, if that is a full revision number.
- (let ((default-branch (vc-file-getprop file 'vc-default-branch)))
- (cond
- ;; no default branch
- ((or (not default-branch) (string= "" default-branch))
- (vc-file-setprop file 'vc-master-workfile-version
- (vc-file-getprop file 'vc-head-version)))
- ;; default branch is actually a revision
- ((string-match "^[0-9]+\\.[0-9]+\\(\\.[0-9]+\\.[0-9]+\\)*$"
- default-branch)
- (vc-file-setprop file 'vc-master-workfile-version default-branch))
- ;; else, search for the head of the default branch
- (t (vc-insert-file (vc-name file) "^desc")
- (vc-parse-buffer (list (list
- (concat "^\\("
- (regexp-quote default-branch)
- "\\.[0-9]+\\)\ndate[ \t]+\\([0-9.]+\\);") 1 2))
- file '(vc-master-workfile-version)))))
- ;; translate the locks
- (vc-parse-locks file (vc-file-getprop file 'vc-master-locks)))
-
- ((eq (vc-backend file) 'CVS)
- (save-excursion
- ;; Call "cvs status" in the right directory, passing only the
- ;; nondirectory part of the file name -- otherwise CVS might
- ;; silently give a wrong result.
- (let ((default-directory (file-name-directory file)))
- (vc-simple-command 0 "cvs" (file-name-nondirectory file) "status"))
- (set-buffer (get-buffer "*vc-info*"))
- (vc-parse-buffer
- ;; CVS 1.3 says "RCS Version:", other releases "RCS Revision:",
- ;; and CVS 1.4a1 says "Repository revision:".
- '(("\\(RCS Version\\|RCS Revision\\|Repository revision\\):[\t ]+\\([0-9.]+\\)" 2)
- ("^File: [^ \t]+[ \t]+Status: \\(.*\\)" 1))
- file
- '(vc-latest-version vc-cvs-status))
- ;; Translate those status values that we understand into symbols.
- ;; Any other value is converted to nil.
- (let ((status (vc-file-getprop file 'vc-cvs-status)))
- (cond
- ((string-match "Up-to-date" status)
- (vc-file-setprop file 'vc-cvs-status 'up-to-date)
- (vc-file-setprop file 'vc-checkout-time
- (nth 5 (file-attributes file))))
- ((vc-file-setprop file 'vc-cvs-status
- (cond
- ((string-match "Locally Modified" status) 'locally-modified)
- ((string-match "Needs Merge" status) 'needs-merge)
- ((string-match "Needs \\(Checkout\\|Patch\\)" status)
- 'needs-checkout)
- ((string-match "Unresolved Conflict" status) 'unresolved-conflict)
- ((string-match "Locally Added" status) 'locally-added)
- (t 'unknown)
- ))))))))
- (if (get-buffer "*vc-info*")
- (kill-buffer (get-buffer "*vc-info*")))))
-
-;;; Functions that determine property values, by examining the
-;;; working file, the master file, or log program output
-
-(defun vc-consult-rcs-headers (file)
- ;; Search for RCS headers in FILE, and set properties
- ;; accordingly. This function can be disabled by setting
- ;; vc-consult-headers to nil.
- ;; Returns: nil if no headers were found
- ;; (or if the feature is disabled,
- ;; or if there is currently no buffer
- ;; visiting FILE)
- ;; 'rev if a workfile revision was found
- ;; 'rev-and-lock if revision and lock info was found
- (cond
- ((or (not vc-consult-headers)
- (not (get-file-buffer file))) nil)
- ((let (status version locking-user)
- (save-excursion
- (set-buffer (get-file-buffer file))
- (goto-char (point-min))
- (cond
- ;; search for $Id or $Header
- ;; -------------------------
- ((or (and (search-forward "$Id: " nil t)
- (looking-at "[^ ]+ \\([0-9.]+\\) "))
- (and (progn (goto-char (point-min))
- (search-forward "$Header: " nil t))
- (looking-at "[^ ]+ \\([0-9.]+\\) ")))
- (goto-char (match-end 0))
- ;; if found, store the revision number ...
- (setq version (buffer-substring-no-properties (match-beginning 1)
- (match-end 1)))
- ;; ... and check for the locking state
- (cond
- ((looking-at
- (concat "[0-9]+[/-][01][0-9][/-][0-3][0-9] " ; date
- "[0-2][0-9]:[0-5][0-9]+:[0-6][0-9]+\\([+-][0-9:]+\\)? " ; time
- "[^ ]+ [^ ]+ ")) ; author & state
- (goto-char (match-end 0)) ; [0-6] in regexp handles leap seconds
- (cond
- ;; unlocked revision
- ((looking-at "\\$")
- (setq locking-user 'none)
- (setq status 'rev-and-lock))
- ;; revision is locked by some user
- ((looking-at "\\([^ ]+\\) \\$")
- (setq locking-user
- (buffer-substring-no-properties (match-beginning 1)
- (match-end 1)))
- (setq status 'rev-and-lock))
- ;; everything else: false
- (nil)))
- ;; unexpected information in
- ;; keyword string --> quit
- (nil)))
- ;; search for $Revision
- ;; --------------------
- ((re-search-forward (concat "\\$"
- "Revision: \\([0-9.]+\\) \\$")
- nil t)
- ;; if found, store the revision number ...
- (setq version (buffer-substring-no-properties (match-beginning 1)
- (match-end 1)))
- ;; and see if there's any lock information
- (goto-char (point-min))
- (if (re-search-forward (concat "\\$" "Locker:") nil t)
- (cond ((looking-at " \\([^ ]+\\) \\$")
- (setq locking-user (buffer-substring-no-properties
- (match-beginning 1)
- (match-end 1)))
- (setq status 'rev-and-lock))
- ((looking-at " *\\$")
- (setq locking-user 'none)
- (setq status 'rev-and-lock))
- (t
- (setq locking-user 'none)
- (setq status 'rev-and-lock)))
- (setq status 'rev)))
- ;; else: nothing found
- ;; -------------------
- (t nil)))
- (if status (vc-file-setprop file 'vc-workfile-version version))
- (and (eq status 'rev-and-lock)
- (eq (vc-backend file) 'RCS)
- (vc-file-setprop file 'vc-locking-user locking-user)
- ;; If the file has headers, we don't want to query the master file,
- ;; because that would eliminate all the performance gain the headers
- ;; brought us. We therefore use a heuristic for the checkout model
- ;; now: If we trust the file permissions, and the file is not
- ;; locked, then if the file is read-only the checkout model is
- ;; `manual', otherwise `implicit'.
- (not (vc-mistrust-permissions file))
- (not (vc-locking-user file))
- (if (string-match ".r-..-..-." (nth 8 (file-attributes file)))
- (vc-file-setprop file 'vc-checkout-model 'manual)
- (vc-file-setprop file 'vc-checkout-model 'implicit)))
- status))))
-
-;;; Access functions to file properties
-;;; (Properties should be _set_ using vc-file-setprop, but
-;;; _retrieved_ only through these functions, which decide
-;;; if the property is already known or not. A property should
-;;; only be retrieved by vc-file-getprop if there is no
-;;; access function.)
-
-;;; properties indicating the backend
-;;; being used for FILE
-
-(defun vc-backend-subdirectory-name (&optional file)
- ;; Where the master and lock files for the current directory are kept
- (symbol-name
- (or
- (and file (vc-backend file))
- vc-default-back-end
- (setq vc-default-back-end (if (vc-find-binary "rcs") 'RCS 'SCCS)))))
-
-(defun vc-name (file)
- "Return the master name of a file, nil if it is not registered.
-For CVS, the full name of CVS/Entries is returned."
- (or (vc-file-getprop file 'vc-name)
- (let ((name-and-type (vc-registered file)))
- (if name-and-type
- (progn
- (vc-file-setprop file 'vc-backend (cdr name-and-type))
- (vc-file-setprop file 'vc-name (car name-and-type)))))))
-
-(defun vc-backend (file)
- "Return the version-control type of a file, nil if it is not registered."
- (and file
- (or (vc-file-getprop file 'vc-backend)
- (let ((name-and-type (vc-registered file)))
- (if name-and-type
- (progn
- (vc-file-setprop file 'vc-name (car name-and-type))
- (vc-file-setprop file 'vc-backend (cdr name-and-type))))))))
-
-(defun vc-checkout-model (file)
- ;; Return `manual' if the user has to type C-x C-q to check out FILE.
- ;; Return `implicit' if the file can be modified without locking it first.
- (or
- (vc-file-getprop file 'vc-checkout-model)
- (cond
- ((eq (vc-backend file) 'SCCS)
- (vc-file-setprop file 'vc-checkout-model 'manual))
- ((eq (vc-backend file) 'RCS)
- (vc-consult-rcs-headers file)
- (or (vc-file-getprop file 'vc-checkout-model)
- (progn (vc-fetch-master-properties file)
- (vc-file-getprop file 'vc-checkout-model))))
- ((eq (vc-backend file) 'CVS)
- (vc-file-setprop file 'vc-checkout-model
- (if (getenv "CVSREAD") 'manual 'implicit))))))
-
-;;; properties indicating the locking state
-
-(defun vc-cvs-status (file)
- ;; Return the cvs status of FILE
- ;; (Status field in output of "cvs status")
- (cond ((vc-file-getprop file 'vc-cvs-status))
- (t (vc-fetch-master-properties file)
- (vc-file-getprop file 'vc-cvs-status))))
-
-(defun vc-master-locks (file)
- ;; Return the lock entries in the master of FILE.
- ;; Return 'none if there are no such entries, and a list
- ;; of the form ((VERSION USER) (VERSION USER) ...) otherwise.
- (cond ((vc-file-getprop file 'vc-master-locks))
- (t (vc-fetch-master-properties file)
- (vc-file-getprop file 'vc-master-locks))))
-
-(defun vc-master-locking-user (file)
- ;; Return the master file's idea of who is locking
- ;; the current workfile version of FILE.
- ;; Return 'none if it is not locked.
- (let ((master-locks (vc-master-locks file)) lock)
- (if (eq master-locks 'none) 'none
- ;; search for a lock on the current workfile version
- (setq lock (assoc (vc-workfile-version file) master-locks))
- (cond (lock (cdr lock))
- ('none)))))
-
-(defun vc-lock-from-permissions (file)
- ;; If the permissions can be trusted for this file, determine the
- ;; locking state from them. Returns (user-login-name), `none', or nil.
- ;; This implementation assumes that any file which is under version
- ;; control and has -rw-r--r-- is locked by its owner. This is true
- ;; for both RCS and SCCS, which keep unlocked files at -r--r--r--.
- ;; We have to be careful not to exclude files with execute bits on;
- ;; scripts can be under version control too. Also, we must ignore the
- ;; group-read and other-read bits, since paranoid users turn them off.
- ;; This hack wins because calls to the somewhat expensive
- ;; `vc-fetch-master-properties' function only have to be made if
- ;; (a) the file is locked by someone other than the current user,
- ;; or (b) some untoward manipulation behind vc's back has changed
- ;; the owner or the `group' or `other' write bits.
- (let ((attributes (file-attributes file)))
- (if (not (vc-mistrust-permissions file))
- (cond ((string-match ".r-..-..-." (nth 8 attributes))
- (vc-file-setprop file 'vc-locking-user 'none))
- ((and (= (nth 2 attributes) (user-uid))
- (string-match ".rw..-..-." (nth 8 attributes)))
- (vc-file-setprop file 'vc-locking-user (vc-user-login-name)))
- (nil)))))
-
-(defun vc-user-login-name (&optional uid)
- ;; Return the name under which the user is logged in, as a string.
- ;; (With optional argument UID, return the name of that user.)
- ;; This function does the same as `user-login-name', but unlike
- ;; that, it never returns nil. If a UID cannot be resolved, that
- ;; UID is returned as a string.
- (or (user-login-name uid)
- (and uid (number-to-string uid))
- (number-to-string (user-uid))))
-
-(defun vc-file-owner (file)
- ;; Return who owns FILE (user name, as a string).
- (vc-user-login-name (nth 2 (file-attributes file))))
-
-(defun vc-rcs-lock-from-diff (file)
- ;; Diff the file against the master version. If differences are found,
- ;; mark the file locked. This is only used for RCS with non-strict
- ;; locking. (If "rcsdiff" doesn't understand --brief, we do a double-take
- ;; and remember the fact for the future.)
- (let* ((version (concat "-r" (vc-workfile-version file)))
- (status (if (eq vc-rcsdiff-knows-brief 'no)
- (vc-simple-command 1 "rcsdiff" file version)
- (vc-simple-command 2 "rcsdiff" file "--brief" version))))
- (if (eq status 2)
- (if (not vc-rcsdiff-knows-brief)
- (setq vc-rcsdiff-knows-brief 'no
- status (vc-simple-command 1 "rcsdiff" file version))
- (error "rcsdiff failed."))
- (if (not vc-rcsdiff-knows-brief) (setq vc-rcsdiff-knows-brief 'yes)))
- (if (zerop status)
- (vc-file-setprop file 'vc-locking-user 'none)
- (vc-file-setprop file 'vc-locking-user (vc-file-owner file)))))
-
-(defun vc-locking-user (file)
- ;; Return the name of the person currently holding a lock on FILE.
- ;; Return nil if there is no such person.
- ;; Under CVS, a file is considered locked if it has been modified since
- ;; it was checked out.
- ;; The property is cached. It is only looked up if it is currently nil.
- ;; Note that, for a file that is not locked, the actual property value
- ;; is `none', to distinguish it from an unknown locking state. That value
- ;; is converted to nil by this function, and returned to the caller.
- (let ((locking-user (vc-file-getprop file 'vc-locking-user)))
- (if locking-user
- ;; if we already know the property, return it
- (if (eq locking-user 'none) nil locking-user)
-
- ;; otherwise, infer the property...
- (cond
- ((eq (vc-backend file) 'CVS)
- (or (and (eq (vc-checkout-model file) 'manual)
- (vc-lock-from-permissions file))
- (and (equal (vc-file-getprop file 'vc-checkout-time)
- (nth 5 (file-attributes file)))
- (vc-file-setprop file 'vc-locking-user 'none))
- (vc-file-setprop file 'vc-locking-user (vc-file-owner file))))
-
- ((eq (vc-backend file) 'RCS)
- (let (p-lock)
-
- ;; Check for RCS headers first
- (or (eq (vc-consult-rcs-headers file) 'rev-and-lock)
-
- ;; If there are no headers, try to learn it
- ;; from the permissions.
- (and (setq p-lock (vc-lock-from-permissions file))
- (if (eq p-lock 'none)
-
- ;; If the permissions say "not locked", we know
- ;; that the checkout model must be `manual'.
- (vc-file-setprop file 'vc-checkout-model 'manual)
-
- ;; If the permissions say "locked", we can only trust
- ;; this *if* the checkout model is `manual'.
- (eq (vc-checkout-model file) 'manual)))
-
- ;; Otherwise, use lock information from the master file.
- (vc-file-setprop file 'vc-locking-user
- (vc-master-locking-user file)))
-
- ;; Finally, if the file is not explicitly locked
- ;; it might still be locked implicitly.
- (and (eq (vc-file-getprop file 'vc-locking-user) 'none)
- (eq (vc-checkout-model file) 'implicit)
- (vc-rcs-lock-from-diff file))))
-
- ((eq (vc-backend file) 'SCCS)
- (or (vc-lock-from-permissions file)
- (vc-file-setprop file 'vc-locking-user
- (vc-master-locking-user file)))))
-
- ;; convert a possible 'none value
- (setq locking-user (vc-file-getprop file 'vc-locking-user))
- (if (eq locking-user 'none) nil locking-user))))
-
-;;; properties to store current and recent version numbers
-
-(defun vc-latest-version (file)
- ;; Return version level of the latest version of FILE
- (cond ((vc-file-getprop file 'vc-latest-version))
- (t (vc-fetch-properties file)
- (vc-file-getprop file 'vc-latest-version))))
-
-(defun vc-your-latest-version (file)
- ;; Return version level of the latest version of FILE checked in by you
- (cond ((vc-file-getprop file 'vc-your-latest-version))
- (t (vc-fetch-properties file)
- (vc-file-getprop file 'vc-your-latest-version))))
-
-(defun vc-master-workfile-version (file)
- ;; Return the master file's idea of what is the current workfile version.
- ;; This property is defined for RCS only.
- (cond ((vc-file-getprop file 'vc-master-workfile-version))
- (t (vc-fetch-master-properties file)
- (vc-file-getprop file 'vc-master-workfile-version))))
-
-(defun vc-fetch-properties (file)
- ;; Fetch vc-latest-version and vc-your-latest-version
- ;; if that wasn't already done.
- (cond
- ((eq (vc-backend file) 'RCS)
- (save-excursion
- (set-buffer (get-buffer-create "*vc-info*"))
- (vc-insert-file (vc-name file) "^desc")
- (vc-parse-buffer
- (list '("^\\([0-9]+\\.[0-9.]+\\)\ndate[ \t]+\\([0-9.]+\\);" 1 2)
- (list (concat "^\\([0-9]+\\.[0-9.]+\\)\n"
- "date[ \t]+\\([0-9.]+\\);[ \t]+"
- "author[ \t]+"
- (regexp-quote (vc-user-login-name)) ";") 1 2))
- file
- '(vc-latest-version vc-your-latest-version))
- (if (get-buffer "*vc-info*")
- (kill-buffer (get-buffer "*vc-info*")))))
- (t (vc-fetch-master-properties file))
- ))
-
-(defun vc-workfile-version (file)
- ;; Return version level of the current workfile FILE
- ;; This is attempted by first looking at the RCS keywords.
- ;; If there are no keywords in the working file,
- ;; vc-master-workfile-version is taken.
- ;; Note that this property is cached, that is, it is only
- ;; looked up if it is nil.
- ;; For SCCS, this property is equivalent to vc-latest-version.
- (cond ((vc-file-getprop file 'vc-workfile-version))
- ((eq (vc-backend file) 'SCCS) (vc-latest-version file))
- ((eq (vc-backend file) 'RCS)
- (if (vc-consult-rcs-headers file)
- (vc-file-getprop file 'vc-workfile-version)
- (let ((rev (cond ((vc-master-workfile-version file))
- ((vc-latest-version file)))))
- (vc-file-setprop file 'vc-workfile-version rev)
- rev)))
- ((eq (vc-backend file) 'CVS)
- (if (vc-consult-rcs-headers file) ;; CVS
- (vc-file-getprop file 'vc-workfile-version)
- (catch 'found
- (vc-find-cvs-master (file-name-directory file)
- (file-name-nondirectory file)))
- (vc-file-getprop file 'vc-workfile-version)))))
-
-;;; actual version-control code starts here
-
-(defun vc-registered (file)
- (let (handler handlers)
- (if (boundp 'file-name-handler-alist)
- (setq handler (find-file-name-handler file 'vc-registered)))
- (if handler
- (funcall handler 'vc-registered file)
- ;; Search for a master corresponding to the given file
- (let ((dirname (or (file-name-directory file) ""))
- (basename (file-name-nondirectory file)))
- (catch 'found
- (mapcar
- (function (lambda (s)
- (if (atom s)
- (funcall s dirname basename)
- (let ((trial (format (car s) dirname basename)))
- (if (and (file-exists-p trial)
- ;; Make sure the file we found with name
- ;; TRIAL is not the source file itself.
- ;; That can happen with RCS-style names
- ;; if the file name is truncated
- ;; (e.g. to 14 chars). See if either
- ;; directory or attributes differ.
- (or (not (string= dirname
- (file-name-directory trial)))
- (not (equal
- (file-attributes file)
- (file-attributes trial)))))
- (throw 'found (cons trial (cdr s))))))))
- vc-master-templates)
- nil)))))
-
-(defun vc-find-cvs-master (dirname basename)
- ;; Check if DIRNAME/BASENAME is handled by CVS.
- ;; If it is, do a (throw 'found (cons MASTER 'CVS)).
- ;; Note: This function throws the name of CVS/Entries
- ;; NOT that of the RCS master file (because we wouldn't be able
- ;; to access it under remote CVS).
- ;; The function returns nil if DIRNAME/BASENAME is not handled by CVS.
- (if (and vc-handle-cvs
- (file-directory-p (concat dirname "CVS/"))
- (file-readable-p (concat dirname "CVS/Entries")))
- (let (buffer time (fold case-fold-search)
- (file (concat dirname basename)))
- (unwind-protect
- (save-excursion
- (setq buffer (set-buffer (get-buffer-create "*vc-info*")))
- (vc-insert-file (concat dirname "CVS/Entries"))
- (goto-char (point-min))
- ;; make sure the file name is searched
- ;; case-sensitively
- (setq case-fold-search nil)
- (cond
- ;; normal entry
- ((re-search-forward
- (concat "^/" (regexp-quote basename)
- "/\\([^/]*\\)/[^ /]* \\([A-Z][a-z][a-z]\\) *\\([0-9]*\\) \\([0-9]*\\):\\([0-9]*\\):\\([0-9]*\\) \\([0-9]*\\)")
- nil t)
- (setq case-fold-search fold) ;; restore the old value
- ;; We found it. Store away version number now that we
- ;; are anyhow so close to finding it.
- (vc-file-setprop file
- 'vc-workfile-version
- (match-string 1))
- ;; If the file hasn't been modified since checkout,
- ;; store the checkout-time.
- (let ((mtime (nth 5 (file-attributes file)))
- (second (string-to-number (match-string 6)))
- (minute (string-to-number (match-string 5)))
- (hour (string-to-number (match-string 4)))
- (day (string-to-number (match-string 3)))
- (year (string-to-number (match-string 7))))
- (if (equal mtime
- (encode-time
- second minute hour day
- (/ (string-match
- (match-string 2)
- "xxxJanFebMarAprMayJunJulAugSepOctNovDec")
- 3)
- year 0))
- (vc-file-setprop file 'vc-checkout-time mtime)
- (vc-file-setprop file 'vc-checkout-time 0)))
- (throw 'found (cons (concat dirname "CVS/Entries") 'CVS)))
- ;; entry for a "locally added" file (not yet committed)
- ((re-search-forward
- (concat "^/" (regexp-quote basename) "/0/Initial ") nil t)
- (setq case-fold-search fold) ;; restore the old value
- (vc-file-setprop file 'vc-checkout-time 0)
- (vc-file-setprop file 'vc-workfile-version "0")
- (throw 'found (cons (concat dirname "CVS/Entries") 'CVS)))
- (t (setq case-fold-search fold) ;; restore the old value
- nil)))
- (kill-buffer buffer)))))
-
-(defun vc-buffer-backend ()
- "Return the version-control type of the visited file, or nil if none."
- (if (eq vc-buffer-backend t)
- (setq vc-buffer-backend (vc-backend (buffer-file-name)))
- vc-buffer-backend))
-
-(defun vc-toggle-read-only (&optional verbose)
- "Change read-only status of current buffer, perhaps via version control.
-If the buffer is visiting a file registered with version control,
-then check the file in or out. Otherwise, just change the read-only flag
-of the buffer. With prefix argument, ask for version number."
- (interactive "P")
- (if (vc-backend (buffer-file-name))
- (vc-next-action verbose)
- (toggle-read-only)))
-(define-key global-map "\C-x\C-q" 'vc-toggle-read-only)
-
-(defun vc-after-save ()
- ;; Function to be called by basic-save-buffer (in files.el).
- ;; If the file in the current buffer is under version control,
- ;; not locked, and the checkout model for it is `implicit',
- ;; mark it "locked" and redisplay the mode line.
- (let ((file (buffer-file-name)))
- (and (vc-file-getprop file 'vc-backend)
- ;; ...check the property directly, not through the function of the
- ;; same name. Otherwise Emacs would check for a master file
- ;; each time a non-version-controlled buffer is saved.
- ;; The property is computed when the file is visited, so if it
- ;; is `nil' now, it is certain that the file is NOT
- ;; version-controlled.
- (or (and (equal (vc-file-getprop file 'vc-checkout-time)
- (nth 5 (file-attributes file)))
- ;; File has been saved in the same second in which
- ;; it was checked out. Clear the checkout-time
- ;; to avoid confusion.
- (vc-file-setprop file 'vc-checkout-time nil))
- t)
- (not (vc-locking-user file))
- (eq (vc-checkout-model file) 'implicit)
- (vc-file-setprop file 'vc-locking-user (vc-user-login-name))
- (or (and (eq (vc-backend file) 'CVS)
- (vc-file-setprop file 'vc-cvs-status nil))
- t)
- (vc-mode-line file))))
-
-(defun vc-mode-line (file &optional label)
- "Set `vc-mode' to display type of version control for FILE.
-The value is set in the current buffer, which should be the buffer
-visiting FILE. Second optional arg LABEL is put in place of version
-control system name."
- (interactive (list buffer-file-name nil))
- (let ((vc-type (vc-backend file)))
- (setq vc-mode
- (and vc-type
- (concat " " (or label (symbol-name vc-type))
- (and vc-display-status (vc-status file)))))
- ;; If the file is locked by some other user, make
- ;; the buffer read-only. Like this, even root
- ;; cannot modify a file that someone else has locked.
- (and vc-type
- (equal file (buffer-file-name))
- (vc-locking-user file)
- (not (string= (vc-user-login-name) (vc-locking-user file)))
- (setq buffer-read-only t))
- ;; If the user is root, and the file is not owner-writable,
- ;; then pretend that we can't write it
- ;; even though we can (because root can write anything).
- ;; This way, even root cannot modify a file that isn't locked.
- (and vc-type
- (equal file (buffer-file-name))
- (not buffer-read-only)
- (zerop (user-real-uid))
- (zerop (logand (file-modes (buffer-file-name)) 128))
- (setq buffer-read-only t))
- (force-mode-line-update)
- ;;(set-buffer-modified-p (buffer-modified-p)) ;;use this if Emacs 18
- vc-type))
-
-(defun vc-status (file)
- ;; Return string for placement in modeline by `vc-mode-line'.
- ;; Format:
- ;;
- ;; "-REV" if the revision is not locked
- ;; ":REV" if the revision is locked by the user
- ;; ":LOCKER:REV" if the revision is locked by somebody else
- ;; " @@" for a CVS file that is added, but not yet committed
- ;;
- ;; In the CVS case, a "locked" working file is a
- ;; working file that is modified with respect to the master.
- ;; The file is "locked" from the moment when the user saves
- ;; the modified buffer.
- ;;
- ;; This function assumes that the file is registered.
-
- (let ((locker (vc-locking-user file))
- (rev (vc-workfile-version file)))
- (cond ((string= "0" rev)
- " @@")
- ((not locker)
- (concat "-" rev))
- ((string= locker (vc-user-login-name))
- (concat ":" rev))
- (t
- (concat ":" locker ":" rev)))))
-
-(defun vc-follow-link ()
- ;; If the current buffer visits a symbolic link, this function makes it
- ;; visit the real file instead. If the real file is already visited in
- ;; another buffer, make that buffer current, and kill the buffer
- ;; that visits the link.
- (let* ((truename (abbreviate-file-name (file-chase-links buffer-file-name)))
- (true-buffer (find-buffer-visiting truename))
- (this-buffer (current-buffer)))
- (if (eq true-buffer this-buffer)
- (progn
- (kill-buffer this-buffer)
- ;; In principle, we could do something like set-visited-file-name.
- ;; However, it can't be exactly the same as set-visited-file-name.
- ;; I'm not going to work out the details right now. -- rms.
- (set-buffer (find-file-noselect truename)))
- (set-buffer true-buffer)
- (kill-buffer this-buffer))))
-
-;;; install a call to the above as a find-file hook
-(defun vc-find-file-hook ()
- ;; Recompute whether file is version controlled,
- ;; if user has killed the buffer and revisited.
- (cond
- (buffer-file-name
- (vc-file-clearprops buffer-file-name)
- (cond
- ((vc-backend buffer-file-name)
- (vc-mode-line buffer-file-name)
- (cond ((not vc-make-backup-files)
- ;; Use this variable, not make-backup-files,
- ;; because this is for things that depend on the file name.
- (make-local-variable 'backup-inhibited)
- (setq backup-inhibited t))))
- ((let* ((link (file-symlink-p buffer-file-name))
- (link-type (and link (vc-backend (file-chase-links link)))))
- (if link-type
- (cond ((eq vc-follow-symlinks nil)
- (message
- "Warning: symbolic link to %s-controlled source file" link-type))
- ((or (not (eq vc-follow-symlinks 'ask))
- ;; If we already visited this file by following
- ;; the link, don't ask again if we try to visit
- ;; it again. GUD does that, and repeated questions
- ;; are painful.
- (get-file-buffer
- (abbreviate-file-name (file-chase-links buffer-file-name))))
-
- (vc-follow-link)
- (message "Followed link to %s" buffer-file-name)
- (vc-find-file-hook))
- (t
- (if (yes-or-no-p (format
- "Symbolic link to %s-controlled source file; follow link? " link-type))
- (progn (vc-follow-link)
- (message "Followed link to %s" buffer-file-name)
- (vc-find-file-hook))
- (message
- "Warning: editing through the link bypasses version control")
- ))))))))))
-
-(add-hook 'find-file-hooks 'vc-find-file-hook)
-
-;;; more hooks, this time for file-not-found
-(defun vc-file-not-found-hook ()
- "When file is not found, try to check it out from RCS or SCCS.
-Returns t if checkout was successful, nil otherwise."
- (if (vc-backend buffer-file-name)
- (save-excursion
- (require 'vc)
- (setq default-directory (file-name-directory (buffer-file-name)))
- (not (vc-error-occurred (vc-checkout buffer-file-name))))))
-
-(add-hook 'find-file-not-found-hooks 'vc-file-not-found-hook)
-
-;; Discard info about a file when we kill its buffer.
-(defun vc-kill-buffer-hook ()
- (if (stringp (buffer-file-name))
- (progn
- (vc-file-clearprops (buffer-file-name))
- (kill-local-variable 'vc-buffer-backend))))
-
-;;;(add-hook 'kill-buffer-hook 'vc-kill-buffer-hook)
-
-;;; Now arrange for bindings and autoloading of the main package.
-;;; Bindings for this have to go in the global map, as we'll often
-;;; want to call them from random buffers.
-
-(setq vc-prefix-map (lookup-key global-map "\C-xv"))
-(if (not (keymapp vc-prefix-map))
- (progn
- (setq vc-prefix-map (make-sparse-keymap))
- (define-key global-map "\C-xv" vc-prefix-map)
- (define-key vc-prefix-map "a" 'vc-update-change-log)
- (define-key vc-prefix-map "c" 'vc-cancel-version)
- (define-key vc-prefix-map "d" 'vc-directory)
- (define-key vc-prefix-map "h" 'vc-insert-headers)
- (define-key vc-prefix-map "i" 'vc-register)
- (define-key vc-prefix-map "l" 'vc-print-log)
- (define-key vc-prefix-map "r" 'vc-retrieve-snapshot)
- (define-key vc-prefix-map "s" 'vc-create-snapshot)
- (define-key vc-prefix-map "u" 'vc-revert-buffer)
- (define-key vc-prefix-map "v" 'vc-next-action)
- (define-key vc-prefix-map "=" 'vc-diff)
- (define-key vc-prefix-map "~" 'vc-version-other-window)))
-
-(if (not (boundp 'vc-menu-map))
- ;; Don't do the menu bindings if menu-bar.el wasn't loaded to defvar
- ;; vc-menu-map.
- ()
- ;;(define-key vc-menu-map [show-files]
- ;; '("Show Files under VC" . (vc-directory t)))
- (define-key vc-menu-map [vc-directory] '("Show Locked Files" . vc-directory))
- (define-key vc-menu-map [separator1] '("----"))
- (define-key vc-menu-map [vc-rename-file] '("Rename File" . vc-rename-file))
- (define-key vc-menu-map [vc-version-other-window]
- '("Show Other Version" . vc-version-other-window))
- (define-key vc-menu-map [vc-diff] '("Compare with Last Version" . vc-diff))
- (define-key vc-menu-map [vc-update-change-log]
- '("Update ChangeLog" . vc-update-change-log))
- (define-key vc-menu-map [vc-print-log] '("Show History" . vc-print-log))
- (define-key vc-menu-map [separator2] '("----"))
- (define-key vc-menu-map [undo] '("Undo Last Check-In" . vc-cancel-version))
- (define-key vc-menu-map [vc-revert-buffer]
- '("Revert to Last Version" . vc-revert-buffer))
- (define-key vc-menu-map [vc-insert-header]
- '("Insert Header" . vc-insert-headers))
- (define-key vc-menu-map [vc-menu-check-in] '("Check In" . vc-next-action))
- (define-key vc-menu-map [vc-check-out] '("Check Out" . vc-toggle-read-only))
- (define-key vc-menu-map [vc-register] '("Register" . vc-register)))
-
-(put 'vc-rename-file 'menu-enable 'vc-mode)
-(put 'vc-version-other-window 'menu-enable 'vc-mode)
-(put 'vc-diff 'menu-enable 'vc-mode)
-(put 'vc-update-change-log 'menu-enable
- '(eq (vc-buffer-backend) 'RCS))
-(put 'vc-print-log 'menu-enable 'vc-mode)
-(put 'vc-cancel-version 'menu-enable 'vc-mode)
-(put 'vc-revert-buffer 'menu-enable 'vc-mode)
-(put 'vc-insert-headers 'menu-enable 'vc-mode)
-(put 'vc-next-action 'menu-enable 'vc-mode)
-(put 'vc-toggle-read-only 'menu-enable 'vc-mode)
-(put 'vc-register 'menu-enable '(and buffer-file-name (not vc-mode)))
-
-(provide 'vc-hooks)
-
-;;; vc-hooks.el ends here
diff --git a/lisp/vc.el b/lisp/vc.el
deleted file mode 100644
index 9e1e4d5fabb..00000000000
--- a/lisp/vc.el
+++ /dev/null
@@ -1,2792 +0,0 @@
-;;; vc.el --- drive a version-control system from within Emacs
-
-;; Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
-
-;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
-;; Maintainer: Andre Spiegel <spiegel@inf.fu-berlin.de>
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This mode is fully documented in the Emacs user's manual.
-;;
-;; This was designed and implemented by Eric Raymond <esr@snark.thyrsus.com>.
-;; Paul Eggert <eggert@twinsun.com>, Sebastian Kremer <sk@thp.uni-koeln.de>,
-;; and Richard Stallman contributed valuable criticism, support, and testing.
-;; CVS support was added by Per Cederqvist <ceder@lysator.liu.se>
-;; in Jan-Feb 1994. Further enhancements came from ttn.netcom.com and
-;; Andre Spiegel <spiegel@inf.fu-berlin.de>.
-;;
-;; Supported version-control systems presently include SCCS, RCS, and CVS.
-;;
-;; Some features will not work with old RCS versions. Where
-;; appropriate, VC finds out which version you have, and allows or
-;; disallows those features (stealing locks, for example, works only
-;; from 5.6.2 onwards).
-;; Even initial checkins will fail if your RCS version is so old that ci
-;; doesn't understand -t-; this has been known to happen to people running
-;; NExTSTEP 3.0.
-;;
-;; You can support the RCS -x option by adding pairs to the
-;; vc-master-templates list.
-;;
-;; Proper function of the SCCS diff commands requires the shellscript vcdiff
-;; to be installed somewhere on Emacs's path for executables.
-;;
-;; If your site uses the ChangeLog convention supported by Emacs, the
-;; function vc-comment-to-change-log should prove a useful checkin hook.
-;;
-;; This code depends on call-process passing back the subprocess exit
-;; status. Thus, you need Emacs 18.58 or later to run it. For the
-;; vc-directory command to work properly as documented, you need 19.
-;; You also need Emacs 19's ring.el.
-;;
-;; The vc code maintains some internal state in order to reduce expensive
-;; version-control operations to a minimum. Some names are only computed
-;; once. If you perform version control operations with RCS/SCCS/CVS while
-;; vc's back is turned, or move/rename master files while vc is running,
-;; vc may get seriously confused. Don't do these things!
-;;
-;; Developer's notes on some concurrency issues are included at the end of
-;; the file.
-
-;;; Code:
-
-(require 'vc-hooks)
-(require 'ring)
-(eval-when-compile (require 'dired)) ; for dired-map-over-marks macro
-
-(if (not (assoc 'vc-parent-buffer minor-mode-alist))
- (setq minor-mode-alist
- (cons '(vc-parent-buffer vc-parent-buffer-name)
- minor-mode-alist)))
-
-;; To implement support for a new version-control system, add another
-;; branch to the vc-backend-dispatch macro and fill it in in each
-;; call. The variable vc-master-templates in vc-hooks.el will also
-;; have to change.
-
-(defmacro vc-backend-dispatch (f s r c)
- "Execute FORM1, FORM2 or FORM3 for SCCS, RCS or CVS respectively.
-If FORM3 is `RCS', use FORM2 for CVS as well as RCS.
-\(CVS shares some code with RCS)."
- (list 'let (list (list 'type (list 'vc-backend f)))
- (list 'cond
- (list (list 'eq 'type (quote 'SCCS)) s) ;; SCCS
- (list (list 'eq 'type (quote 'RCS)) r) ;; RCS
- (list (list 'eq 'type (quote 'CVS)) ;; CVS
- (if (eq c 'RCS) r c))
- )))
-
-;; General customization
-
-(defvar vc-suppress-confirm nil
- "*If non-nil, treat user as expert; suppress yes-no prompts on some things.")
-(defvar vc-initial-comment nil
- "*If non-nil, prompt for initial comment when a file is registered.")
-(defvar vc-command-messages nil
- "*If non-nil, display run messages from back-end commands.")
-(defvar vc-register-switches nil
- "*A string or list of strings specifying extra switches passed
-to the register program by \\[vc-register].")
-(defvar vc-checkin-switches nil
- "*A string or list of strings specifying extra switches passed
-to the checkin program by \\[vc-checkin].")
-(defvar vc-checkout-switches nil
- "*A string or list of strings specifying extra switches passed
-to the checkout program by \\[vc-checkout].")
-(defvar vc-directory-exclusion-list '("SCCS" "RCS" "CVS")
- "*A list of directory names ignored by functions that recursively
-walk file trees.")
-
-(defconst vc-maximum-comment-ring-size 32
- "Maximum number of saved comments in the comment ring.")
-
-;;; This is duplicated in diff.el.
-(defvar diff-switches "-c"
- "*A string or list of strings specifying switches to be be passed to diff.")
-
-;;;###autoload
-(defvar vc-checkin-hook nil
- "*List of functions called after a checkin is done. See `run-hooks'.")
-
-;; Header-insertion hair
-
-(defvar vc-header-alist
- '((SCCS "\%W\%") (RCS "\$Id\$") (CVS "\$Id\$"))
- "*Header keywords to be inserted by `vc-insert-headers'.
-Must be a list of two-element lists, the first element of each must
-be `RCS', `CVS', or `SCCS'. The second element is the string to
-be inserted for this particular backend.")
-(defvar vc-static-header-alist
- '(("\\.c$" .
- "\n#ifndef lint\nstatic char vcid[] = \"\%s\";\n#endif /* lint */\n"))
- "*Associate static header string templates with file types. A \%s in the
-template is replaced with the first string associated with the file's
-version-control type in `vc-header-alist'.")
-
-(defvar vc-comment-alist
- '((nroff-mode ".\\\"" ""))
- "*Special comment delimiters to be used in generating vc headers only.
-Add an entry in this list if you need to override the normal comment-start
-and comment-end variables. This will only be necessary if the mode language
-is sensitive to blank lines.")
-
-;; Default is to be extra careful for super-user.
-(defvar vc-checkout-carefully (= (user-uid) 0)
- "*Non-nil means be extra-careful in checkout.
-Verify that the file really is not locked
-and that its contents match what the master file says.")
-
-(defvar vc-rcs-release nil
- "*The release number of your RCS installation, as a string.
-If nil, VC itself computes this value when it is first needed.")
-
-(defvar vc-sccs-release nil
- "*The release number of your SCCS installation, as a string.
-If nil, VC itself computes this value when it is first needed.")
-
-(defvar vc-cvs-release nil
- "*The release number of your CVS installation, as a string.
-If nil, VC itself computes this value when it is first needed.")
-
-;; Variables the user doesn't need to know about.
-(defvar vc-log-entry-mode nil)
-(defvar vc-log-operation nil)
-(defvar vc-log-after-operation-hook nil)
-(defvar vc-checkout-writable-buffer-hook 'vc-checkout-writable-buffer)
-;; In a log entry buffer, this is a local variable
-;; that points to the buffer for which it was made
-;; (either a file, or a VC dired buffer).
-(defvar vc-parent-buffer nil)
-(defvar vc-parent-buffer-name nil)
-
-(defvar vc-log-file)
-(defvar vc-log-version)
-
-(defconst vc-name-assoc-file "VC-names")
-
-(defvar vc-dired-mode nil)
-(make-variable-buffer-local 'vc-dired-mode)
-
-(defvar vc-comment-ring (make-ring vc-maximum-comment-ring-size))
-(defvar vc-comment-ring-index nil)
-(defvar vc-last-comment-match nil)
-
-;; Back-portability to Emacs 18
-
-(defun file-executable-p-18 (f)
- (let ((modes (file-modes f)))
- (and modes (not (zerop (logand 292))))))
-
-(defun file-regular-p-18 (f)
- (let ((attributes (file-attributes f)))
- (and attributes (not (car attributes)))))
-
-; Conditionally rebind some things for Emacs 18 compatibility
-(if (not (boundp 'minor-mode-map-alist))
- (progn
- (setq compilation-old-error-list nil)
- (fset 'file-executable-p 'file-executable-p-18)
- (fset 'shrink-window-if-larger-than-buffer 'beginning-of-buffer)
- ))
-
-(if (not (fboundp 'file-regular-p))
- (fset 'file-regular-p 'file-regular-p-18))
-
-;;; Find and compare backend releases
-
-(defun vc-backend-release (backend)
- ;; Returns which backend release is installed on this system.
- (cond
- ((eq backend 'RCS)
- (or vc-rcs-release
- (and (zerop (vc-do-command nil 2 "rcs" nil nil "-V"))
- (save-excursion
- (set-buffer (get-buffer "*vc*"))
- (setq vc-rcs-release
- (car (vc-parse-buffer
- '(("^RCS version \\([0-9.]+ *.*\\)" 1)))))))
- (setq vc-rcs-release 'unknown)))
- ((eq backend 'CVS)
- (or vc-cvs-release
- (and (zerop (vc-do-command nil 1 "cvs" nil nil "-v"))
- (save-excursion
- (set-buffer (get-buffer "*vc*"))
- (setq vc-cvs-release
- (car (vc-parse-buffer
- '(("^Concurrent Versions System (CVS) \\([0-9.]+\\)"
- 1)))))))
- (setq vc-cvs-release 'unknown)))
- ((eq backend 'SCCS)
- vc-sccs-release)))
-
-(defun vc-release-greater-or-equal (r1 r2)
- ;; Compare release numbers, represented as strings.
- ;; Release components are assumed cardinal numbers, not decimal
- ;; fractions (5.10 is a higher release than 5.9). Omitted fields
- ;; are considered lower (5.6.7 is earlier than 5.6.7.1).
- ;; Comparison runs till the end of the string is found, or a
- ;; non-numeric component shows up (5.6.7 is earlier than "5.6.7 beta",
- ;; which is probably not what you want in some cases).
- ;; This code is suitable for existing RCS release numbers.
- ;; CVS releases are handled reasonably, too (1.3 < 1.4* < 1.5).
- (let (v1 v2 i1 i2)
- (catch 'done
- (or (and (string-match "^\\.?\\([0-9]+\\)" r1)
- (setq i1 (match-end 0))
- (setq v1 (string-to-number (match-string 1 r1)))
- (or (and (string-match "^\\.?\\([0-9]+\\)" r2)
- (setq i2 (match-end 0))
- (setq v2 (string-to-number (match-string 1 r2)))
- (if (> v1 v2) (throw 'done t)
- (if (< v1 v2) (throw 'done nil)
- (throw 'done
- (vc-release-greater-or-equal
- (substring r1 i1)
- (substring r2 i2)))))))
- (throw 'done t)))
- (or (and (string-match "^\\.?\\([0-9]+\\)" r2)
- (throw 'done nil))
- (throw 'done t)))))
-
-(defun vc-backend-release-p (backend release)
- ;; Return t if we have RELEASE of BACKEND or better
- (let (i r (ri 0) (ii 0) is rs (installation (vc-backend-release backend)))
- (if (not (eq installation 'unknown))
- (cond
- ((or (eq backend 'RCS) (eq backend 'CVS))
- (vc-release-greater-or-equal installation release))))))
-
-;;; functions that operate on RCS revision numbers
-
-(defun vc-trunk-p (rev)
- ;; return t if REV is a revision on the trunk
- (not (eq nil (string-match "\\`[0-9]+\\.[0-9]+\\'" rev))))
-
-(defun vc-branch-part (rev)
- ;; return the branch part of a revision number REV
- (substring rev 0 (string-match "\\.[0-9]+\\'" rev)))
-
-;; File property caching
-
-(defun vc-clear-context ()
- "Clear all cached file properties and the comment ring."
- (interactive)
- (fillarray vc-file-prop-obarray nil)
- ;; Note: there is potential for minor lossage here if there is an open
- ;; log buffer with a nonzero local value of vc-comment-ring-index.
- (setq vc-comment-ring (make-ring vc-maximum-comment-ring-size)))
-
-(defun vc-file-clear-masterprops (file)
- ;; clear all properties of FILE that were retrieved
- ;; from the master file
- (vc-file-setprop file 'vc-latest-version nil)
- (vc-file-setprop file 'vc-your-latest-version nil)
- (vc-backend-dispatch file
- (progn ;; SCCS
- (vc-file-setprop file 'vc-master-locks nil))
- (progn ;; RCS
- (vc-file-setprop file 'vc-default-branch nil)
- (vc-file-setprop file 'vc-head-version nil)
- (vc-file-setprop file 'vc-master-workfile-version nil)
- (vc-file-setprop file 'vc-master-locks nil))
- (progn
- (vc-file-setprop file 'vc-cvs-status nil))))
-
-(defun vc-head-version (file)
- ;; Return the RCS head version of FILE
- (cond ((vc-file-getprop file 'vc-head-version))
- (t (vc-fetch-master-properties file)
- (vc-file-getprop file 'vc-head-version))))
-
-;; Random helper functions
-
-(defun vc-latest-on-branch-p (file)
- ;; return t iff the current workfile version of FILE is
- ;; the latest on its branch.
- (vc-backend-dispatch file
- ;; SCCS
- (string= (vc-workfile-version file) (vc-latest-version file))
- ;; RCS
- (let ((workfile-version (vc-workfile-version file)) tip-version)
- (if (vc-trunk-p workfile-version)
- (progn
- ;; Re-fetch the head version number. This is to make
- ;; sure that no-one has checked in a new version behind
- ;; our back.
- (vc-fetch-master-properties file)
- (string= (vc-file-getprop file 'vc-head-version)
- workfile-version))
- ;; If we are not on the trunk, we need to examine the
- ;; whole current branch. (vc-master-workfile-version
- ;; is not what we need.)
- (save-excursion
- (set-buffer (get-buffer-create "*vc-info*"))
- (vc-insert-file (vc-name file) "^desc")
- (setq tip-version (car (vc-parse-buffer (list (list
- (concat "^\\(" (regexp-quote (vc-branch-part workfile-version))
- "\\.[0-9]+\\)\ndate[ \t]+\\([0-9.]+\\);") 1 2)))))
- (if (get-buffer "*vc-info*")
- (kill-buffer (get-buffer "*vc-info*")))
- (string= tip-version workfile-version))))
- ;; CVS
- t))
-
-(defun vc-registration-error (file)
- (if file
- (error "File %s is not under version control" file)
- (error "Buffer %s is not associated with a file" (buffer-name))))
-
-(defvar vc-binary-assoc nil)
-
-(defun vc-find-binary (name)
- "Look for a command anywhere on the subprocess-command search path."
- (or (cdr (assoc name vc-binary-assoc))
- (catch 'found
- (mapcar
- (function
- (lambda (s)
- (if s
- (let ((full (concat s "/" name)))
- (if (file-executable-p full)
- (progn
- (setq vc-binary-assoc
- (cons (cons name full) vc-binary-assoc))
- (throw 'found full)))))))
- exec-path)
- nil)))
-
-(defun vc-do-command (buffer okstatus command file last &rest flags)
- "Execute a version-control command, notifying user and checking for errors.
-Output from COMMAND goes to BUFFER, or *vc* if BUFFER is nil.
-The command is successful if its exit status does not exceed OKSTATUS.
-The last argument of the command is the master name of FILE if LAST is
-`MASTER', or the workfile of FILE if LAST is `WORKFILE'; this is appended
-to an optional list of FLAGS."
- (and file (setq file (expand-file-name file)))
- (if (not buffer) (setq buffer "*vc*"))
- (if vc-command-messages
- (message "Running %s on %s..." command file))
- (let ((obuf (current-buffer)) (camefrom (current-buffer))
- (squeezed nil)
- (vc-file (and file (vc-name file)))
- (olddir default-directory)
- status)
- (set-buffer (get-buffer-create buffer))
- (set (make-local-variable 'vc-parent-buffer) camefrom)
- (set (make-local-variable 'vc-parent-buffer-name)
- (concat " from " (buffer-name camefrom)))
- (setq default-directory olddir)
-
- (erase-buffer)
-
- (mapcar
- (function (lambda (s) (and s (setq squeezed (append squeezed (list s))))))
- flags)
- (if (and vc-file (eq last 'MASTER))
- (setq squeezed (append squeezed (list vc-file))))
- (if (eq last 'WORKFILE)
- (progn
- (let* ((pwd (expand-file-name default-directory))
- (preflen (length pwd)))
- (if (string= (substring file 0 preflen) pwd)
- (setq file (substring file preflen))))
- (setq squeezed (append squeezed (list file)))))
- (let ((exec-path (append vc-path exec-path))
- ;; Add vc-path to PATH for the execution of this command.
- (process-environment
- (cons (concat "PATH=" (getenv "PATH")
- path-separator
- (mapconcat 'identity vc-path path-separator))
- process-environment))
- (w32-quote-process-args t))
- (setq status (apply 'call-process command nil t nil squeezed)))
- (goto-char (point-max))
- (set-buffer-modified-p nil)
- (forward-line -1)
- (if (or (not (integerp status)) (< okstatus status))
- (progn
- (pop-to-buffer buffer)
- (goto-char (point-min))
- (shrink-window-if-larger-than-buffer)
- (error "Running %s...FAILED (%s)" command
- (if (integerp status)
- (format "status %d" status)
- status))
- )
- (if vc-command-messages
- (message "Running %s...OK" command))
- )
- (set-buffer obuf)
- status)
- )
-
-;;; Save a bit of the text around POSN in the current buffer, to help
-;;; us find the corresponding position again later. This works even
-;;; if all markers are destroyed or corrupted.
-;;; A lot of this was shamelessly lifted from Sebastian Kremer's rcs.el mode.
-(defun vc-position-context (posn)
- (list posn
- (buffer-size)
- (buffer-substring posn
- (min (point-max) (+ posn 100)))))
-
-;;; Return the position of CONTEXT in the current buffer, or nil if we
-;;; couldn't find it.
-(defun vc-find-position-by-context (context)
- (let ((context-string (nth 2 context)))
- (if (equal "" context-string)
- (point-max)
- (save-excursion
- (let ((diff (- (nth 1 context) (buffer-size))))
- (if (< diff 0) (setq diff (- diff)))
- (goto-char (nth 0 context))
- (if (or (search-forward context-string nil t)
- ;; Can't use search-backward since the match may continue
- ;; after point.
- (progn (goto-char (- (point) diff (length context-string)))
- ;; goto-char doesn't signal an error at
- ;; beginning of buffer like backward-char would
- (search-forward context-string nil t)))
- ;; to beginning of OSTRING
- (- (point) (length context-string))))))))
-
-(defun vc-buffer-context ()
- ;; Return a list '(point-context mark-context reparse); from which
- ;; vc-restore-buffer-context can later restore the context.
- (let ((point-context (vc-position-context (point)))
- ;; Use mark-marker to avoid confusion in transient-mark-mode.
- (mark-context (if (eq (marker-buffer (mark-marker)) (current-buffer))
- (vc-position-context (mark-marker))))
- ;; Make the right thing happen in transient-mark-mode.
- (mark-active nil)
- ;; We may want to reparse the compilation buffer after revert
- (reparse (and (boundp 'compilation-error-list) ;compile loaded
- (let ((curbuf (current-buffer)))
- ;; Construct a list; each elt is nil or a buffer
- ;; iff that buffer is a compilation output buffer
- ;; that contains markers into the current buffer.
- (save-excursion
- (mapcar (function
- (lambda (buffer)
- (set-buffer buffer)
- (let ((errors (or
- compilation-old-error-list
- compilation-error-list))
- (buffer-error-marked-p nil))
- (while (and (consp errors)
- (not buffer-error-marked-p))
- (and (markerp (cdr (car errors)))
- (eq buffer
- (marker-buffer
- (cdr (car errors))))
- (setq buffer-error-marked-p t))
- (setq errors (cdr errors)))
- (if buffer-error-marked-p buffer))))
- (buffer-list)))))))
- (list point-context mark-context reparse)))
-
-(defun vc-restore-buffer-context (context)
- ;; Restore point/mark, and reparse any affected compilation buffers.
- ;; CONTEXT is that which vc-buffer-context returns.
- (let ((point-context (nth 0 context))
- (mark-context (nth 1 context))
- (reparse (nth 2 context)))
- ;; Reparse affected compilation buffers.
- (while reparse
- (if (car reparse)
- (save-excursion
- (set-buffer (car reparse))
- (let ((compilation-last-buffer (current-buffer)) ;select buffer
- ;; Record the position in the compilation buffer of
- ;; the last error next-error went to.
- (error-pos (marker-position
- (car (car-safe compilation-error-list)))))
- ;; Reparse the error messages as far as they were parsed before.
- (compile-reinitialize-errors '(4) compilation-parsing-end)
- ;; Move the pointer up to find the error we were at before
- ;; reparsing. Now next-error should properly go to the next one.
- (while (and compilation-error-list
- (/= error-pos (car (car compilation-error-list))))
- (setq compilation-error-list (cdr compilation-error-list))))))
- (setq reparse (cdr reparse)))
-
- ;; Restore point and mark
- (let ((new-point (vc-find-position-by-context point-context)))
- (if new-point (goto-char new-point)))
- (if mark-context
- (let ((new-mark (vc-find-position-by-context mark-context)))
- (if new-mark (set-mark new-mark))))))
-
-(defun vc-revert-buffer1 (&optional arg no-confirm)
- ;; Revert buffer, try to keep point and mark where user expects them in spite
- ;; of changes because of expanded version-control key words.
- ;; This is quite important since otherwise typeahead won't work as expected.
- (interactive "P")
- (widen)
- (let ((context (vc-buffer-context)))
- ;; t means don't call normal-mode; that's to preserve various minor modes.
- (revert-buffer arg no-confirm t)
- (vc-restore-buffer-context context)))
-
-
-(defun vc-buffer-sync (&optional not-urgent)
- ;; Make sure the current buffer and its working file are in sync
- ;; NOT-URGENT means it is ok to continue if the user says not to save.
- (if (buffer-modified-p)
- (if (or vc-suppress-confirm
- (y-or-n-p (format "Buffer %s modified; save it? " (buffer-name))))
- (save-buffer)
- (if not-urgent
- nil
- (error "Aborted")))))
-
-
-(defun vc-workfile-unchanged-p (file &optional want-differences-if-changed)
- ;; Has the given workfile changed since last checkout?
- (let ((checkout-time (vc-file-getprop file 'vc-checkout-time))
- (lastmod (nth 5 (file-attributes file))))
- (or (equal checkout-time lastmod)
- (and (or (not checkout-time) want-differences-if-changed)
- (let ((unchanged (zerop (vc-backend-diff file nil nil
- (not want-differences-if-changed)))))
- ;; 0 stands for an unknown time; it can't match any mod time.
- (vc-file-setprop file 'vc-checkout-time (if unchanged lastmod 0))
- unchanged)))))
-
-(defun vc-next-action-on-file (file verbose &optional comment)
- ;;; If comment is specified, it will be used as an admin or checkin comment.
- (let ((vc-file (vc-name file))
- (vc-type (vc-backend file))
- owner version buffer)
- (cond
-
- ;; if there is no master file corresponding, create one
- ((not vc-file)
- (vc-register verbose comment)
- (if vc-initial-comment
- (setq vc-log-after-operation-hook
- 'vc-checkout-writable-buffer-hook)
- (vc-checkout-writable-buffer file)))
-
- ;; CVS: changes to the master file need to be
- ;; merged back into the working file
- ((and (eq vc-type 'CVS)
- (or (eq (vc-cvs-status file) 'needs-checkout)
- (eq (vc-cvs-status file) 'needs-merge)))
- (if (or vc-dired-mode
- (yes-or-no-p
- (format "%s is not up-to-date. Merge in changes now? "
- (buffer-name))))
- (progn
- (if vc-dired-mode
- (and (setq buffer (get-file-buffer file))
- (buffer-modified-p buffer)
- (switch-to-buffer-other-window buffer)
- (vc-buffer-sync t))
- (setq buffer (current-buffer))
- (vc-buffer-sync t))
- (if (and buffer (buffer-modified-p buffer)
- (not (yes-or-no-p
- (format
- "Buffer %s modified; merge file on disc anyhow? "
- (buffer-name buffer)))))
- (error "Merge aborted"))
- (if (not (zerop (vc-backend-merge-news file)))
- ;; Overlaps detected - what now? Should use some
- ;; fancy RCS conflict resolving package, or maybe
- ;; emerge, but for now, simply warn the user with a
- ;; message.
- (message "Conflicts detected!"))
- (and buffer
- (vc-resynch-buffer file t (not (buffer-modified-p buffer)))))
- (error "%s needs update" (buffer-name))))
-
- ;; if there is no lock on the file, assert one and get it
- ((not (setq owner (vc-locking-user file)))
- (if (and vc-checkout-carefully
- (not (vc-workfile-unchanged-p file t)))
- (if (save-window-excursion
- (pop-to-buffer "*vc-diff*")
- (goto-char (point-min))
- (insert-string (format "Changes to %s since last lock:\n\n"
- file))
- (not (beep))
- (yes-or-no-p
- (concat "File has unlocked changes, "
- "claim lock retaining changes? ")))
- (progn (vc-backend-steal file)
- (vc-mode-line file))
- (if (not (yes-or-no-p "Revert to checked-in version, instead? "))
- (error "Checkout aborted")
- (vc-revert-buffer1 t t)
- (vc-checkout-writable-buffer file))
- )
- (if verbose
- (if (not (eq vc-type 'SCCS))
- (vc-checkout file nil
- (read-string "Branch or version to move to: "))
- (error "Sorry, this is not implemented for SCCS"))
- (if (vc-latest-on-branch-p file)
- (vc-checkout-writable-buffer file)
- (if (yes-or-no-p
- "This is not the latest version. Really lock it? ")
- (vc-checkout-writable-buffer file)
- (if (yes-or-no-p "Lock the latest version instead? ")
- (vc-checkout-writable-buffer file
- (if (vc-trunk-p (vc-workfile-version file))
- "" ;; this means check out latest on trunk
- (vc-branch-part (vc-workfile-version file)))))))
- )))
-
- ;; a checked-out version exists, but the user may not own the lock
- ((and (not (eq vc-type 'CVS))
- (not (string-equal owner (vc-user-login-name))))
- (if comment
- (error "Sorry, you can't steal the lock on %s this way" file))
- (and (eq vc-type 'RCS)
- (not (vc-backend-release-p 'RCS "5.6.2"))
- (error "File is locked by %s" owner))
- (vc-steal-lock
- file
- (if verbose (read-string "Version to steal: ")
- (vc-workfile-version file))
- owner))
-
- ;; OK, user owns the lock on the file
- (t
- (if vc-dired-mode
- (find-file-other-window file)
- (find-file file))
-
- ;; give luser a chance to save before checking in.
- (vc-buffer-sync)
-
- ;; Revert if file is unchanged and buffer is too.
- ;; If buffer is modified, that means the user just said no
- ;; to saving it; in that case, don't revert,
- ;; because the user might intend to save
- ;; after finishing the log entry.
- (if (and (vc-workfile-unchanged-p file)
- (not (buffer-modified-p)))
- ;; DO NOT revert the file without asking the user!
- (cond
- ((yes-or-no-p "Revert to master version? ")
- (vc-backend-revert file)
- (vc-resynch-window file t t)))
-
- ;; user may want to set nonstandard parameters
- (if verbose
- (setq version (read-string "New version level: ")))
-
- ;; OK, let's do the checkin
- (vc-checkin file version comment)
- )))))
-
-(defun vc-next-action-dired (file rev comment)
- ;; Do a vc-next-action-on-file on all the marked files, possibly
- ;; passing on the log comment we've just entered.
- (let ((configuration (current-window-configuration))
- (dired-buffer (current-buffer))
- (dired-dir default-directory))
- (dired-map-over-marks
- (let ((file (dired-get-filename)) p
- (default-directory default-directory))
- (message "Processing %s..." file)
- ;; Adjust the default directory so that checkouts
- ;; go to the right place.
- (setq default-directory (file-name-directory file))
- (vc-next-action-on-file file nil comment)
- (set-buffer dired-buffer)
- (setq default-directory dired-dir)
- (vc-dired-update-line file)
- (set-window-configuration configuration)
- (message "Processing %s...done" file))
- nil t)))
-
-;; Here's the major entry point.
-
-;;;###autoload
-(defun vc-next-action (verbose)
- "Do the next logical checkin or checkout operation on the current file.
- If you call this from within a VC dired buffer with no files marked,
-it will operate on the file in the current line.
- If you call this from within a VC dired buffer, and one or more
-files are marked, it will accept a log message and then operate on
-each one. The log message will be used as a comment for any register
-or checkin operations, but ignored when doing checkouts. Attempted
-lock steals will raise an error.
- A prefix argument lets you specify the version number to use.
-
-For RCS and SCCS files:
- If the file is not already registered, this registers it for version
-control and then retrieves a writable, locked copy for editing.
- If the file is registered and not locked by anyone, this checks out
-a writable and locked file ready for editing.
- If the file is checked out and locked by the calling user, this
-first checks to see if the file has changed since checkout. If not,
-it performs a revert.
- If the file has been changed, this pops up a buffer for entry
-of a log message; when the message has been entered, it checks in the
-resulting changes along with the log message as change commentary. If
-the variable `vc-keep-workfiles' is non-nil (which is its default), a
-read-only copy of the changed file is left in place afterwards.
- If the file is registered and locked by someone else, you are given
-the option to steal the lock.
-
-For CVS files:
- If the file is not already registered, this registers it for version
-control. This does a \"cvs add\", but no \"cvs commit\".
- If the file is added but not committed, it is committed.
- If your working file is changed, but the repository file is
-unchanged, this pops up a buffer for entry of a log message; when the
-message has been entered, it checks in the resulting changes along
-with the logmessage as change commentary. A writable file is retained.
- If the repository file is changed, you are asked if you want to
-merge in the changes into your working copy."
-
- (interactive "P")
- (catch 'nogo
- (if vc-dired-mode
- (let ((files (dired-get-marked-files)))
- (if (string= ""
- (mapconcat
- (function (lambda (f)
- (if (eq (vc-backend f) 'CVS)
- (if (or (eq (vc-cvs-status f) 'locally-modified)
- (eq (vc-cvs-status f) 'locally-added))
- "@" "")
- (if (vc-locking-user f) "@" ""))))
- files ""))
- (vc-next-action-dired nil nil "dummy")
- (vc-start-entry nil nil nil
- "Enter a change comment for the marked files."
- 'vc-next-action-dired))
- (throw 'nogo nil)))
- (while vc-parent-buffer
- (pop-to-buffer vc-parent-buffer))
- (if buffer-file-name
- (vc-next-action-on-file buffer-file-name verbose)
- (vc-registration-error nil))))
-
-;;; These functions help the vc-next-action entry point
-
-(defun vc-checkout-writable-buffer (&optional file rev)
- "Retrieve a writable copy of the latest version of the current buffer's file."
- (vc-checkout (or file (buffer-file-name)) t rev)
- )
-
-;;;###autoload
-(defun vc-register (&optional override comment)
- "Register the current file into your version-control system."
- (interactive "P")
- (or buffer-file-name
- (error "No visited file"))
- (let ((master (vc-name buffer-file-name)))
- (and master (file-exists-p master)
- (error "This file is already registered"))
- (and master
- (not (y-or-n-p "Previous master file has vanished. Make a new one? "))
- (error "This file is already registered")))
- ;; Watch out for new buffers of size 0: the corresponding file
- ;; does not exist yet, even though buffer-modified-p is nil.
- (if (and (not (buffer-modified-p))
- (zerop (buffer-size))
- (not (file-exists-p buffer-file-name)))
- (set-buffer-modified-p t))
- (vc-buffer-sync)
- (cond ((not vc-make-backup-files)
- ;; inhibit backup for this buffer
- (make-local-variable 'backup-inhibited)
- (setq backup-inhibited t)))
- (vc-admin
- buffer-file-name
- (and override
- (read-string
- (format "Initial version level for %s: " buffer-file-name))))
- )
-
-(defun vc-resynch-window (file &optional keep noquery)
- ;; If the given file is in the current buffer,
- ;; either revert on it so we see expanded keywords,
- ;; or unvisit it (depending on vc-keep-workfiles)
- ;; NOQUERY if non-nil inhibits confirmation for reverting.
- ;; NOQUERY should be t *only* if it is known the only difference
- ;; between the buffer and the file is due to RCS rather than user editing!
- (and (string= buffer-file-name file)
- (if keep
- (progn
- ;; temporarily remove vc-find-file-hook, so that
- ;; we don't lose the properties
- (remove-hook 'find-file-hooks 'vc-find-file-hook)
- (vc-revert-buffer1 t noquery)
- (add-hook 'find-file-hooks 'vc-find-file-hook)
- (vc-mode-line buffer-file-name))
- (kill-buffer (current-buffer)))))
-
-(defun vc-resynch-buffer (file &optional keep noquery)
- ;; if FILE is currently visited, resynch its buffer
- (let ((buffer (get-file-buffer file)))
- (if buffer
- (save-excursion
- (set-buffer buffer)
- (vc-resynch-window file keep noquery)))))
-
-(defun vc-start-entry (file rev comment msg action &optional after-hook)
- ;; Accept a comment for an operation on FILE revision REV. If COMMENT
- ;; is nil, pop up a VC-log buffer, emit MSG, and set the
- ;; action on close to ACTION; otherwise, do action immediately.
- ;; Remember the file's buffer in vc-parent-buffer (current one if no file).
- ;; AFTER-HOOK specifies the local value for vc-log-operation-hook.
- (let ((parent (if file (find-file-noselect file) (current-buffer))))
- (if comment
- (set-buffer (get-buffer-create "*VC-log*"))
- (pop-to-buffer (get-buffer-create "*VC-log*")))
- (set (make-local-variable 'vc-parent-buffer) parent)
- (set (make-local-variable 'vc-parent-buffer-name)
- (concat " from " (buffer-name vc-parent-buffer)))
- (if file (vc-mode-line file))
- (vc-log-mode)
- (make-local-variable 'vc-log-after-operation-hook)
- (if after-hook
- (setq vc-log-after-operation-hook after-hook))
- (setq vc-log-operation action)
- (setq vc-log-file file)
- (setq vc-log-version rev)
- (if comment
- (progn
- (erase-buffer)
- (if (eq comment t)
- (vc-finish-logentry t)
- (insert comment)
- (vc-finish-logentry nil)))
- (message "%s Type C-c C-c when done." msg))))
-
-(defun vc-admin (file rev &optional comment)
- "Check a file into your version-control system.
-FILE is the unmodified name of the file. REV should be the base version
-level to check it in under. COMMENT, if specified, is the checkin comment."
- (vc-start-entry file rev
- (or comment (not vc-initial-comment))
- "Enter initial comment." 'vc-backend-admin
- nil))
-
-(defun vc-checkout (file &optional writable rev)
- "Retrieve a copy of the latest version of the given file."
- ;; If ftp is on this system and the name matches the ange-ftp format
- ;; for a remote file, the user is trying something that won't work.
- (if (and (string-match "^/[^/:]+:" file) (vc-find-binary "ftp"))
- (error "Sorry, you can't check out files over FTP"))
- (vc-backend-checkout file writable rev)
- (vc-resynch-buffer file t t))
-
-(defun vc-steal-lock (file rev &optional owner)
- "Steal the lock on the current workfile."
- (let (file-description)
- (if (not owner)
- (setq owner (vc-locking-user file)))
- (if rev
- (setq file-description (format "%s:%s" file rev))
- (setq file-description file))
- (if (not (y-or-n-p (format "Take the lock on %s from %s? "
- file-description owner)))
- (error "Steal cancelled"))
- (pop-to-buffer (get-buffer-create "*VC-mail*"))
- (setq default-directory (expand-file-name "~/"))
- (auto-save-mode auto-save-default)
- (mail-mode)
- (erase-buffer)
- (mail-setup owner (format "Stolen lock on %s" file-description) nil nil nil
- (list (list 'vc-finish-steal file rev)))
- (goto-char (point-max))
- (insert
- (format "I stole the lock on %s, " file-description)
- (current-time-string)
- ".\n")
- (message "Please explain why you stole the lock. Type C-c C-c when done.")))
-
-;; This is called when the notification has been sent.
-(defun vc-finish-steal (file version)
- (vc-backend-steal file version)
- (if (get-file-buffer file)
- (save-excursion
- (set-buffer (get-file-buffer file))
- (vc-resynch-window file t t))))
-
-(defun vc-checkin (file &optional rev comment)
- "Check in the file specified by FILE.
-The optional argument REV may be a string specifying the new version level
-\(if nil increment the current level). The file is either retained with write
-permissions zeroed, or deleted (according to the value of `vc-keep-workfiles').
-If the back-end is CVS, a writable workfile is always kept.
-COMMENT is a comment string; if omitted, a buffer is
-popped up to accept a comment."
- (vc-start-entry file rev comment
- "Enter a change comment." 'vc-backend-checkin
- 'vc-checkin-hook))
-
-;;; Here is a checkin hook that may prove useful to sites using the
-;;; ChangeLog facility supported by Emacs.
-(defun vc-comment-to-change-log (&optional whoami file-name)
- "Enter last VC comment into change log file for current buffer's file.
-Optional arg (interactive prefix) non-nil means prompt for user name and site.
-Second arg is file name of change log. \
-If nil, uses `change-log-default-name'."
- (interactive (if current-prefix-arg
- (list current-prefix-arg
- (prompt-for-change-log-name))))
- ;; Make sure the defvar for add-log-current-defun-function has been executed
- ;; before binding it.
- (require 'add-log)
- (let (;; Extract the comment first so we get any error before doing anything.
- (comment (ring-ref vc-comment-ring 0))
- ;; Don't let add-change-log-entry insert a defun name.
- (add-log-current-defun-function 'ignore)
- end)
- ;; Call add-log to do half the work.
- (add-change-log-entry whoami file-name t t)
- ;; Insert the VC comment, leaving point before it.
- (setq end (save-excursion (insert comment) (point-marker)))
- (if (looking-at "\\s *\\s(")
- ;; It starts with an open-paren, as in "(foo): Frobbed."
- ;; So remove the ": " add-log inserted.
- (delete-char -2))
- ;; Canonicalize the white space between the file name and comment.
- (just-one-space)
- ;; Indent rest of the text the same way add-log indented the first line.
- (let ((indentation (current-indentation)))
- (save-excursion
- (while (< (point) end)
- (forward-line 1)
- (indent-to indentation))
- (setq end (point))))
- ;; Fill the inserted text, preserving open-parens at bol.
- (let ((paragraph-separate (concat paragraph-separate "\\|\\s *\\s("))
- (paragraph-start (concat paragraph-start "\\|\\s *\\s(")))
- (beginning-of-line)
- (fill-region (point) end))
- ;; Canonicalize the white space at the end of the entry so it is
- ;; separated from the next entry by a single blank line.
- (skip-syntax-forward " " end)
- (delete-char (- (skip-syntax-backward " ")))
- (or (eobp) (looking-at "\n\n")
- (insert "\n"))))
-
-
-(defun vc-finish-logentry (&optional nocomment)
- "Complete the operation implied by the current log entry."
- (interactive)
- ;; Check and record the comment, if any.
- (if (not nocomment)
- (progn
- (goto-char (point-max))
- (if (not (bolp))
- (newline))
- ;; Comment too long?
- (vc-backend-logentry-check vc-log-file)
- ;; Record the comment in the comment ring
- (ring-insert vc-comment-ring (buffer-string))
- ))
- ;; Sync parent buffer in case the user modified it while editing the comment.
- ;; But not if it is a vc-dired buffer.
- (save-excursion
- (set-buffer vc-parent-buffer)
- (or vc-dired-mode
- (vc-buffer-sync)))
- (if (not vc-log-operation) (error "No log operation is pending"))
- ;; save the parameters held in buffer-local variables
- (let ((log-operation vc-log-operation)
- (log-file vc-log-file)
- (log-version vc-log-version)
- (log-entry (buffer-string))
- (after-hook vc-log-after-operation-hook))
- ;; Return to "parent" buffer of this checkin and remove checkin window
- (pop-to-buffer vc-parent-buffer)
- (let ((logbuf (get-buffer "*VC-log*")))
- (delete-windows-on logbuf)
- (kill-buffer logbuf))
- ;; OK, do it to it
- (save-excursion
- (funcall log-operation
- log-file
- log-version
- log-entry))
- ;; Now make sure we see the expanded headers
- (if buffer-file-name
- (vc-resynch-window buffer-file-name vc-keep-workfiles t))
- (run-hooks after-hook)))
-
-;; Code for access to the comment ring
-
-(defun vc-previous-comment (arg)
- "Cycle backwards through comment history."
- (interactive "*p")
- (let ((len (ring-length vc-comment-ring)))
- (cond ((<= len 0)
- (message "Empty comment ring")
- (ding))
- (t
- (erase-buffer)
- ;; Initialize the index on the first use of this command
- ;; so that the first M-p gets index 0, and the first M-n gets
- ;; index -1.
- (if (null vc-comment-ring-index)
- (setq vc-comment-ring-index
- (if (> arg 0) -1
- (if (< arg 0) 1 0))))
- (setq vc-comment-ring-index
- (mod (+ vc-comment-ring-index arg) len))
- (message "%d" (1+ vc-comment-ring-index))
- (insert (ring-ref vc-comment-ring vc-comment-ring-index))))))
-
-(defun vc-next-comment (arg)
- "Cycle forwards through comment history."
- (interactive "*p")
- (vc-previous-comment (- arg)))
-
-(defun vc-comment-search-reverse (str)
- "Searches backwards through comment history for substring match."
- (interactive "sComment substring: ")
- (if (string= str "")
- (setq str vc-last-comment-match)
- (setq vc-last-comment-match str))
- (if (null vc-comment-ring-index)
- (setq vc-comment-ring-index -1))
- (let ((str (regexp-quote str))
- (len (ring-length vc-comment-ring))
- (n (1+ vc-comment-ring-index)))
- (while (and (< n len) (not (string-match str (ring-ref vc-comment-ring n))))
- (setq n (+ n 1)))
- (cond ((< n len)
- (vc-previous-comment (- n vc-comment-ring-index)))
- (t (error "Not found")))))
-
-(defun vc-comment-search-forward (str)
- "Searches forwards through comment history for substring match."
- (interactive "sComment substring: ")
- (if (string= str "")
- (setq str vc-last-comment-match)
- (setq vc-last-comment-match str))
- (if (null vc-comment-ring-index)
- (setq vc-comment-ring-index 0))
- (let ((str (regexp-quote str))
- (len (ring-length vc-comment-ring))
- (n vc-comment-ring-index))
- (while (and (>= n 0) (not (string-match str (ring-ref vc-comment-ring n))))
- (setq n (- n 1)))
- (cond ((>= n 0)
- (vc-next-comment (- n vc-comment-ring-index)))
- (t (error "Not found")))))
-
-;; Additional entry points for examining version histories
-
-;;;###autoload
-(defun vc-diff (historic &optional not-urgent)
- "Display diffs between file versions.
-Normally this compares the current file and buffer with the most recent
-checked in version of that file. This uses no arguments.
-With a prefix argument, it reads the file name to use
-and two version designators specifying which versions to compare."
- (interactive (list current-prefix-arg t))
- (if vc-dired-mode
- (set-buffer (find-file-noselect (dired-get-filename))))
- (while vc-parent-buffer
- (pop-to-buffer vc-parent-buffer))
- (if historic
- (call-interactively 'vc-version-diff)
- (if (or (null buffer-file-name) (null (vc-name buffer-file-name)))
- (error
- "There is no version-control master associated with this buffer"))
- (let ((file buffer-file-name)
- unchanged)
- (or (and file (vc-name file))
- (vc-registration-error file))
- (vc-buffer-sync not-urgent)
- (setq unchanged (vc-workfile-unchanged-p buffer-file-name))
- (if unchanged
- (message "No changes to %s since latest version" file)
- (vc-backend-diff file)
- ;; Ideally, we'd like at this point to parse the diff so that
- ;; the buffer effectively goes into compilation mode and we
- ;; can visit the old and new change locations via next-error.
- ;; Unfortunately, this is just too painful to do. The basic
- ;; problem is that the `old' file doesn't exist to be
- ;; visited. This plays hell with numerous assumptions in
- ;; the diff.el and compile.el machinery.
- (set-buffer "*vc-diff*")
- (setq default-directory (file-name-directory file))
- (if (= 0 (buffer-size))
- (progn
- (setq unchanged t)
- (message "No changes to %s since latest version" file))
- (pop-to-buffer "*vc-diff*")
- (goto-char (point-min))
- (shrink-window-if-larger-than-buffer)))
- (not unchanged))))
-
-(defun vc-version-diff (file rel1 rel2)
- "For FILE, report diffs between two stored versions REL1 and REL2 of it.
-If FILE is a directory, generate diffs between versions for all registered
-files in or below it."
- (interactive "FFile or directory to diff: \nsOlder version: \nsNewer version: ")
- (if (string-equal rel1 "") (setq rel1 nil))
- (if (string-equal rel2 "") (setq rel2 nil))
- (if (file-directory-p file)
- (let ((camefrom (current-buffer)))
- (set-buffer (get-buffer-create "*vc-status*"))
- (set (make-local-variable 'vc-parent-buffer) camefrom)
- (set (make-local-variable 'vc-parent-buffer-name)
- (concat " from " (buffer-name camefrom)))
- (erase-buffer)
- (insert "Diffs between "
- (or rel1 "last version checked in")
- " and "
- (or rel2 "current workfile(s)")
- ":\n\n")
- (set-buffer (get-buffer-create "*vc-diff*"))
- (cd file)
- (vc-file-tree-walk
- default-directory
- (function (lambda (f)
- (message "Looking at %s" f)
- (and
- (not (file-directory-p f))
- (vc-registered f)
- (vc-backend-diff f rel1 rel2)
- (append-to-buffer "*vc-status*" (point-min) (point-max)))
- )))
- (pop-to-buffer "*vc-status*")
- (insert "\nEnd of diffs.\n")
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- )
- (if (zerop (vc-backend-diff file rel1 rel2))
- (message "No changes to %s between %s and %s." file rel1 rel2)
- (pop-to-buffer "*vc-diff*"))))
-
-;;;###autoload
-(defun vc-version-other-window (rev)
- "Visit version REV of the current buffer in another window.
-If the current buffer is named `F', the version is named `F.~REV~'.
-If `F.~REV~' already exists, it is used instead of being re-created."
- (interactive "sVersion to visit (default is latest version): ")
- (if vc-dired-mode
- (set-buffer (find-file-noselect (dired-get-filename))))
- (while vc-parent-buffer
- (pop-to-buffer vc-parent-buffer))
- (if (and buffer-file-name (vc-name buffer-file-name))
- (let* ((version (if (string-equal rev "")
- (vc-latest-version buffer-file-name)
- rev))
- (filename (concat buffer-file-name ".~" version "~")))
- (or (file-exists-p filename)
- (vc-backend-checkout buffer-file-name nil version filename))
- (find-file-other-window filename))
- (vc-registration-error buffer-file-name)))
-
-;; Header-insertion code
-
-;;;###autoload
-(defun vc-insert-headers ()
- "Insert headers in a file for use with your version-control system.
-Headers desired are inserted at the start of the buffer, and are pulled from
-the variable `vc-header-alist'."
- (interactive)
- (if vc-dired-mode
- (find-file-other-window (dired-get-filename)))
- (while vc-parent-buffer
- (pop-to-buffer vc-parent-buffer))
- (save-excursion
- (save-restriction
- (widen)
- (if (or (not (vc-check-headers))
- (y-or-n-p "Version headers already exist. Insert another set? "))
- (progn
- (let* ((delims (cdr (assq major-mode vc-comment-alist)))
- (comment-start-vc (or (car delims) comment-start "#"))
- (comment-end-vc (or (car (cdr delims)) comment-end ""))
- (hdstrings (cdr (assoc (vc-backend (buffer-file-name)) vc-header-alist))))
- (mapcar (function (lambda (s)
- (insert comment-start-vc "\t" s "\t"
- comment-end-vc "\n")))
- hdstrings)
- (if vc-static-header-alist
- (mapcar (function (lambda (f)
- (if (string-match (car f) buffer-file-name)
- (insert (format (cdr f) (car hdstrings))))))
- vc-static-header-alist))
- )
- )))))
-
-(defun vc-clear-headers ()
- ;; Clear all version headers in the current buffer, i.e. reset them
- ;; to the nonexpanded form. Only implemented for RCS, yet.
- ;; Don't lose point and mark during this.
- (let ((context (vc-buffer-context)))
- (goto-char (point-min))
- (while (re-search-forward "\\$\\([A-Za-z]+\\): [^\\$]+\\$" nil t)
- (replace-match "$\\1$"))
- (vc-restore-buffer-context context)))
-
-;; The VC directory major mode. Coopt Dired for this.
-;; All VC commands get mapped into logical equivalents.
-
-(define-derived-mode vc-dired-mode dired-mode "Dired under VC"
- "The major mode used in VC directory buffers. It is derived from Dired.
-All Dired commands operate normally. Users currently locking listed files
-are listed in place of the file's owner and group.
-Keystrokes bound to VC commands will execute as though they had been called
-on a buffer attached to the file named in the current Dired buffer line."
- (setq vc-dired-mode t))
-
-(define-key vc-dired-mode-map "\C-xv" vc-prefix-map)
-(define-key vc-dired-mode-map "g" 'vc-dired-update)
-(define-key vc-dired-mode-map "=" 'vc-diff)
-
-(defun vc-dired-state-info (file)
- ;; Return the string that indicates the version control status
- ;; on a VC dired line.
- (let ((cvs-state (and (eq (vc-backend file) 'CVS)
- (vc-cvs-status file))))
- (if cvs-state
- (cond ((eq cvs-state 'up-to-date) nil)
- ((eq cvs-state 'needs-checkout) "patch")
- ((eq cvs-state 'locally-modified) "modified")
- ((eq cvs-state 'needs-merge) "merge")
- ((eq cvs-state 'unresolved-conflict) "conflict")
- ((eq cvs-state 'locally-added) "added"))
- (vc-locking-user file))))
-
-(defun vc-dired-reformat-line (x)
- ;; Hack a directory-listing line, plugging in locking-user info in
- ;; place of the user and group info. Should have the beneficial
- ;; side-effect of shortening the listing line. Each call starts with
- ;; point immediately following the dired mark area on the line to be
- ;; hacked.
- ;;
- ;; Simplest possible one:
- ;; (insert (concat x "\t")))
- ;;
- ;; This code, like dired, assumes UNIX -l format.
- (let ((pos (point)) limit perm owner date-and-file)
- (end-of-line)
- (setq limit (point))
- (goto-char pos)
- (cond
- ((or
- (re-search-forward ;; owner and group
-"\\([drwxlts-]+ \\) *[0-9]+ \\([^ ]+\\) +[^ ]+ +[0-9]+\\( [^ 0-9]+ [0-9 ][0-9] .*\\)"
- limit t)
- (re-search-forward ;; only owner displayed
-"\\([drwxlts-]+ \\) *[0-9]+ \\([^ ]+\\) +[0-9]+\\( [^ 0-9]+ [0-9 ][0-9] .*\\)"
- limit t))
- (setq perm (match-string 1)
- owner (match-string 2)
- date-and-file (match-string 3)))
- ((re-search-forward ;; OS/2 -l format, no links, owner, group
-"\\([drwxlts-]+ \\) *[0-9]+\\( [^ 0-9]+ [0-9 ][0-9] .*\\)"
- limit t)
- (setq perm (match-string 1)
- date-and-file (match-string 2))))
- (if x (setq x (concat "(" x ")")))
- (let ((rep (substring (concat x " ") 0 10)))
- (replace-match (concat perm rep date-and-file)))))
-
-(defun vc-dired-update-line (file)
- ;; Update the vc-dired listing line of file -- it is assumed
- ;; that point is already on this line. Don't use dired-do-redisplay
- ;; for this, because it cannot handle the way vc-dired deals with
- ;; subdirectories.
- (beginning-of-line)
- (forward-char 2)
- (let ((start (point)))
- (forward-line 1)
- (beginning-of-line)
- (delete-region start (point))
- (insert-directory file dired-listing-switches)
- (forward-line -1)
- (end-of-line)
- (delete-char (- (length file)))
- (insert (substring file (length (expand-file-name default-directory))))
- (goto-char start))
- (vc-dired-reformat-line (vc-dired-state-info file)))
-
-(defun vc-dired-update (verbose)
- (interactive "P")
- (vc-directory default-directory verbose))
-
-;;; Note in Emacs 18 the following defun gets overridden
-;;; with the symbol 'vc-directory-18. See below.
-;;;###autoload
-(defun vc-directory (dirname verbose)
- "Show version-control status of the current directory and subdirectories.
-Normally it creates a Dired buffer that lists only the locked files
-in all these directories. With a prefix argument, it lists all files."
- (interactive "DDired under VC (directory): \nP")
- (require 'dired)
- (setq dirname (expand-file-name dirname))
- ;; force a trailing slash
- (if (not (eq (elt dirname (1- (length dirname))) ?/))
- (setq dirname (concat dirname "/")))
- (let (nonempty
- (dl (length dirname))
- (filelist nil) (statelist nil)
- (old-dir default-directory)
- dired-buf
- dired-buf-mod-count)
- (vc-file-tree-walk
- dirname
- (function
- (lambda (f)
- (if (vc-registered f)
- (let ((state (vc-dired-state-info f)))
- (and (or verbose state)
- (setq filelist (cons (substring f dl) filelist))
- (setq statelist (cons state statelist))))))))
- (save-window-excursion
- (save-excursion
- ;; This uses a semi-documented feature of dired; giving a switch
- ;; argument forces the buffer to refresh each time.
- (setq dired-buf
- (dired-internal-noselect
- (cons dirname (nreverse filelist))
- dired-listing-switches 'vc-dired-mode))
- (setq nonempty (not (eq 0 (length filelist))))))
- (switch-to-buffer dired-buf)
- ;; Make a few modifications to the header
- (setq buffer-read-only nil)
- (goto-char (point-min))
- (forward-line 1) ;; Skip header line
- (let ((start (point))) ;; Erase (but don't remove) the
- (end-of-line) ;; "wildcard" line.
- (delete-region start (point)))
- (beginning-of-line)
- (if nonempty
- (progn
- ;; Plug the version information into the individual lines
- (mapcar
- (function
- (lambda (x)
- (forward-char 2) ;; skip dired's mark area
- (vc-dired-reformat-line x)
- (forward-line 1))) ;; go to next line
- (nreverse statelist))
- (setq buffer-read-only t)
- (goto-char (point-min))
- (dired-next-line 2)
- )
- (dired-next-line 1)
- (insert " ")
- (setq buffer-read-only t)
- (message "No files are currently %s under %s"
- (if verbose "registered" "locked") dirname))
- ))
-
-;; Emacs 18 version
-(defun vc-directory-18 (verbose)
- "Show version-control status of all files under the current directory."
- (interactive "P")
- (let (nonempty (dir default-directory))
- (save-excursion
- (set-buffer (get-buffer-create "*vc-status*"))
- (erase-buffer)
- (cd dir)
- (vc-file-tree-walk
- default-directory
- (function (lambda (f)
- (if (vc-registered f)
- (let ((user (vc-locking-user f)))
- (if (or user verbose)
- (insert (format
- "%s %s\n"
- (concat user) f))))))))
- (setq nonempty (not (zerop (buffer-size)))))
-
- (if nonempty
- (progn
- (pop-to-buffer "*vc-status*" t)
- (goto-char (point-min))
- (shrink-window-if-larger-than-buffer)))
- (message "No files are currently %s under %s"
- (if verbose "registered" "locked") default-directory))
- )
-
-(or (boundp 'minor-mode-map-alist)
- (fset 'vc-directory 'vc-directory-18))
-
-;; Named-configuration support for SCCS
-
-(defun vc-add-triple (name file rev)
- (save-excursion
- (find-file (expand-file-name
- vc-name-assoc-file
- (file-name-as-directory
- (expand-file-name (vc-backend-subdirectory-name file)
- (file-name-directory file)))))
- (goto-char (point-max))
- (insert name "\t:\t" file "\t" rev "\n")
- (basic-save-buffer)
- (kill-buffer (current-buffer))
- ))
-
-(defun vc-record-rename (file newname)
- (save-excursion
- (find-file
- (expand-file-name
- vc-name-assoc-file
- (file-name-as-directory
- (expand-file-name (vc-backend-subdirectory-name file)
- (file-name-directory file)))))
- (goto-char (point-min))
- ;; (replace-regexp (concat ":" (regexp-quote file) "$") (concat ":" newname))
- (while (re-search-forward (concat ":" (regexp-quote file) "$") nil t)
- (replace-match (concat ":" newname) nil nil))
- (basic-save-buffer)
- (kill-buffer (current-buffer))
- ))
-
-(defun vc-lookup-triple (file name)
- ;; Return the numeric version corresponding to a named snapshot of file
- ;; If name is nil or a version number string it's just passed through
- (cond ((null name) name)
- ((let ((firstchar (aref name 0)))
- (and (>= firstchar ?0) (<= firstchar ?9)))
- name)
- (t
- (save-excursion
- (set-buffer (get-buffer-create "*vc-info*"))
- (vc-insert-file
- (expand-file-name
- vc-name-assoc-file
- (file-name-as-directory
- (expand-file-name (vc-backend-subdirectory-name file)
- (file-name-directory file)))))
- (prog1
- (car (vc-parse-buffer
- (list (list (concat name "\t:\t" file "\t\\(.+\\)") 1))))
- (kill-buffer "*vc-info*"))))
- ))
-
-;; Named-configuration entry points
-
-(defun vc-snapshot-precondition ()
- ;; Scan the tree below the current directory.
- ;; If any files are locked, return the name of the first such file.
- ;; (This means, neither snapshot creation nor retrieval is allowed.)
- ;; If one or more of the files are currently visited, return `visited'.
- ;; Otherwise, return nil.
- (let ((status nil))
- (catch 'vc-locked-example
- (vc-file-tree-walk
- default-directory
- (function (lambda (f)
- (and (vc-registered f)
- (if (vc-locking-user f) (throw 'vc-locked-example f)
- (if (get-file-buffer f) (setq status 'visited)))))))
- status)))
-
-;;;###autoload
-(defun vc-create-snapshot (name)
- "Make a snapshot called NAME.
-The snapshot is made from all registered files at or below the current
-directory. For each file, the version level of its latest
-version becomes part of the named configuration."
- (interactive "sNew snapshot name: ")
- (let ((result (vc-snapshot-precondition)))
- (if (stringp result)
- (error "File %s is locked" result)
- (vc-file-tree-walk
- default-directory
- (function (lambda (f) (and
- (vc-name f)
- (vc-backend-assign-name f name)))))
- )))
-
-;;;###autoload
-(defun vc-retrieve-snapshot (name)
- "Retrieve the snapshot called NAME.
-This function fails if any files are locked at or below the current directory
-Otherwise, all registered files are checked out (unlocked) at their version
-levels in the snapshot."
- (interactive "sSnapshot name to retrieve: ")
- (let ((result (vc-snapshot-precondition))
- (update nil))
- (if (stringp result)
- (error "File %s is locked" result)
- (if (eq result 'visited)
- (setq update (yes-or-no-p "Update the affected buffers? ")))
- (vc-file-tree-walk
- default-directory
- (function (lambda (f) (and
- (vc-name f)
- (vc-error-occurred
- (vc-backend-checkout f nil name)
- (if update (vc-resynch-buffer f t t)))))))
- )))
-
-;; Miscellaneous other entry points
-
-;;;###autoload
-(defun vc-print-log ()
- "List the change log of the current buffer in a window."
- (interactive)
- (if vc-dired-mode
- (set-buffer (find-file-noselect (dired-get-filename))))
- (while vc-parent-buffer
- (pop-to-buffer vc-parent-buffer))
- (if (and buffer-file-name (vc-name buffer-file-name))
- (let ((file buffer-file-name))
- (vc-backend-print-log file)
- (pop-to-buffer (get-buffer-create "*vc*"))
- (setq default-directory (file-name-directory file))
- (goto-char (point-max)) (forward-line -1)
- (while (looking-at "=*\n")
- (delete-char (- (match-end 0) (match-beginning 0)))
- (forward-line -1))
- (goto-char (point-min))
- (if (looking-at "[\b\t\n\v\f\r ]+")
- (delete-char (- (match-end 0) (match-beginning 0))))
- (shrink-window-if-larger-than-buffer)
- ;; move point to the log entry for the current version
- (and (not (eq (vc-backend file) 'SCCS))
- (re-search-forward
- ;; also match some context, for safety
- (concat "----\nrevision " (vc-workfile-version file)
- "\\(\tlocked by:.*\n\\|\n\\)date: ") nil t)
- ;; set the display window so that
- ;; the whole log entry is displayed
- (let (start end lines)
- (beginning-of-line) (forward-line -1) (setq start (point))
- (if (not (re-search-forward "^----*\nrevision" nil t))
- (setq end (point-max))
- (beginning-of-line) (forward-line -1) (setq end (point)))
- (setq lines (count-lines start end))
- (cond
- ;; if the global information and this log entry fit
- ;; into the window, display from the beginning
- ((< (count-lines (point-min) end) (window-height))
- (goto-char (point-min))
- (recenter 0)
- (goto-char start))
- ;; if the whole entry fits into the window,
- ;; display it centered
- ((< (1+ lines) (window-height))
- (goto-char start)
- (recenter (1- (- (/ (window-height) 2) (/ lines 2)))))
- ;; otherwise (the entry is too large for the window),
- ;; display from the start
- (t
- (goto-char start)
- (recenter 0)))))
- )
- (vc-registration-error buffer-file-name)
- )
- )
-
-;;;###autoload
-(defun vc-revert-buffer ()
- "Revert the current buffer's file back to the latest checked-in version.
-This asks for confirmation if the buffer contents are not identical
-to that version.
-If the back-end is CVS, this will give you the most recent revision of
-the file on the branch you are editing."
- (interactive)
- (if vc-dired-mode
- (find-file-other-window (dired-get-filename)))
- (while vc-parent-buffer
- (pop-to-buffer vc-parent-buffer))
- (let ((file buffer-file-name)
- ;; This operation should always ask for confirmation.
- (vc-suppress-confirm nil)
- (obuf (current-buffer)) (changed (vc-diff nil t)))
- (if (and changed (not (yes-or-no-p "Discard changes? ")))
- (progn
- (if (and (window-dedicated-p (selected-window))
- (one-window-p t 'selected-frame))
- (make-frame-invisible (selected-frame))
- (delete-window))
- (error "Revert cancelled"))
- (set-buffer obuf))
- (if changed
- (if (and (window-dedicated-p (selected-window))
- (one-window-p t 'selected-frame))
- (make-frame-invisible (selected-frame))
- (delete-window)))
- (vc-backend-revert file)
- (vc-resynch-window file t t)
- )
- )
-
-;;;###autoload
-(defun vc-cancel-version (norevert)
- "Get rid of most recently checked in version of this file.
-A prefix argument means do not revert the buffer afterwards."
- (interactive "P")
- (if vc-dired-mode
- (find-file-other-window (dired-get-filename)))
- (while vc-parent-buffer
- (pop-to-buffer vc-parent-buffer))
- (cond
- ((not (vc-registered (buffer-file-name)))
- (vc-registration-error (buffer-file-name)))
- ((eq (vc-backend (buffer-file-name)) 'CVS)
- (error "Unchecking files under CVS is dangerous and not supported in VC"))
- ((vc-locking-user (buffer-file-name))
- (error "This version is locked; use vc-revert-buffer to discard changes"))
- ((not (vc-latest-on-branch-p (buffer-file-name)))
- (error "This is not the latest version--VC cannot cancel it")))
- (let* ((target (vc-workfile-version (buffer-file-name)))
- (recent (if (vc-trunk-p target) "" (vc-branch-part target)))
- (config (current-window-configuration)) done)
- (if (null (yes-or-no-p (format "Remove version %s from master? " target)))
- nil
- (setq norevert (or norevert (not
- (yes-or-no-p "Revert buffer to most recent remaining version? "))))
- (vc-backend-uncheck (buffer-file-name) target)
- ;; Check out the most recent remaining version. If it fails, because
- ;; the whole branch got deleted, do a double-take and check out the
- ;; version where the branch started.
- (while (not done)
- (condition-case err
- (progn
- (if norevert
- ;; Check out locked, but only to disc, and keep
- ;; modifications in the buffer.
- (vc-backend-checkout (buffer-file-name) t recent)
- ;; Check out unlocked, and revert buffer.
- (vc-checkout (buffer-file-name) nil recent))
- (setq done t))
- ;; If the checkout fails, vc-do-command signals an error.
- ;; We catch this error, check the reason, correct the
- ;; version number, and try a second time.
- (error (set-buffer "*vc*")
- (goto-char (point-min))
- (if (search-forward "no side branches present for" nil t)
- (progn (setq recent (vc-branch-part recent))
- ;; vc-do-command popped up a window with
- ;; the error message. Get rid of it, by
- ;; restoring the old window configuration.
- (set-window-configuration config))
- ;; No, it was some other error: re-signal it.
- (signal (car err) (cdr err))))))
- ;; If norevert, clear version headers and mark the buffer modified.
- (if norevert
- (progn
- (set-visited-file-name (buffer-file-name))
- (if (not vc-make-backup-files)
- ;; inhibit backup for this buffer
- (progn (make-local-variable 'backup-inhibited)
- (setq backup-inhibited t)))
- (if (eq (vc-backend (buffer-file-name)) 'RCS)
- (progn (setq buffer-read-only nil)
- (vc-clear-headers)))
- (vc-mode-line (buffer-file-name))))
- (message "Version %s has been removed from the master" target)
- )))
-
-;;;###autoload
-(defun vc-rename-file (old new)
- "Rename file OLD to NEW, and rename its master file likewise."
- (interactive "fVC rename file: \nFRename to: ")
- ;; There are several ways of renaming files under CVS 1.3, but they all
- ;; have serious disadvantages. See the FAQ (available from think.com in
- ;; pub/cvs/). I'd rather send the user an error, than do something he might
- ;; consider to be wrong. When the famous, long-awaited rename database is
- ;; implemented things might change for the better. This is unlikely to occur
- ;; until CVS 2.0 is released. --ceder 1994-01-23 21:27:51
- (if (eq (vc-backend old) 'CVS)
- (error "Renaming files under CVS is dangerous and not supported in VC"))
- (let ((oldbuf (get-file-buffer old)))
- (if (and oldbuf (buffer-modified-p oldbuf))
- (error "Please save files before moving them"))
- (if (get-file-buffer new)
- (error "Already editing new file name"))
- (if (file-exists-p new)
- (error "New file already exists"))
- (let ((oldmaster (vc-name old)))
- (if oldmaster
- (progn
- (if (vc-locking-user old)
- (error "Please check in files before moving them"))
- (if (or (file-symlink-p oldmaster)
- ;; This had FILE, I changed it to OLD. -- rms.
- (file-symlink-p (vc-backend-subdirectory-name old)))
- (error "This is not a safe thing to do in the presence of symbolic links"))
- (rename-file
- oldmaster
- (let ((backend (vc-backend old))
- (newdir (or (file-name-directory new) ""))
- (newbase (file-name-nondirectory new)))
- (catch 'found
- (mapcar
- (function
- (lambda (s)
- (if (eq backend (cdr s))
- (let* ((newmaster (format (car s) newdir newbase))
- (newmasterdir (file-name-directory newmaster)))
- (if (or (not newmasterdir)
- (file-directory-p newmasterdir))
- (throw 'found newmaster))))))
- vc-master-templates)
- (error "New file lacks a version control directory"))))))
- (if (or (not oldmaster) (file-exists-p old))
- (rename-file old new)))
-; ?? Renaming a file might change its contents due to keyword expansion.
-; We should really check out a new copy if the old copy was precisely equal
-; to some checked in version. However, testing for this is tricky....
- (if oldbuf
- (save-excursion
- (set-buffer oldbuf)
- (let ((buffer-read-only buffer-read-only))
- (set-visited-file-name new))
- (vc-backend new)
- (vc-mode-line new)
- (set-buffer-modified-p nil))))
- ;; This had FILE, I changed it to OLD. -- rms.
- (vc-backend-dispatch old
- (vc-record-rename old new) ;SCCS
- nil ;RCS
- nil ;CVS
- )
- )
-
-;;;###autoload
-(defun vc-update-change-log (&rest args)
- "Find change log file and add entries from recent RCS/CVS logs.
-Normally, find log entries for all registered files in the default
-directory using `rcs2log', which finds CVS logs preferentially.
-The mark is left at the end of the text prepended to the change log.
-
-With prefix arg of C-u, only find log entries for the current buffer's file.
-
-With any numeric prefix arg, find log entries for all currently visited
-files that are under version control. This puts all the entries in the
-log for the default directory, which may not be appropriate.
-
-From a program, any arguments are assumed to be filenames and are
-passed to the `rcs2log' script after massaging to be relative to the
-default directory."
- (interactive
- (cond ((consp current-prefix-arg) ;C-u
- (list buffer-file-name))
- (current-prefix-arg ;Numeric argument.
- (let ((files nil)
- (buffers (buffer-list))
- file)
- (while buffers
- (setq file (buffer-file-name (car buffers)))
- (and file (vc-backend file)
- (setq files (cons file files)))
- (setq buffers (cdr buffers)))
- files))
- (t
- ;; `rcs2log' will find the relevant RCS or CVS files
- ;; relative to the curent directory if none supplied.
- nil)))
- (let ((odefault default-directory)
- (full-name (or add-log-full-name
- (user-full-name)
- (user-login-name)
- (format "uid%d" (number-to-string (user-uid)))))
- (mailing-address (or add-log-mailing-address
- user-mail-address)))
- (find-file-other-window (find-change-log))
- (barf-if-buffer-read-only)
- (vc-buffer-sync)
- (undo-boundary)
- (goto-char (point-min))
- (push-mark)
- (message "Computing change log entries...")
- (message "Computing change log entries... %s"
- (if (eq 0 (apply 'call-process "rcs2log" nil '(t nil) nil
- "-u"
- (concat (vc-user-login-name)
- "\t"
- full-name
- "\t"
- mailing-address)
- (mapcar (function
- (lambda (f)
- (file-relative-name
- (if (file-name-absolute-p f)
- f
- (concat odefault f)))))
- args)))
- "done" "failed"))))
-
-;; Collect back-end-dependent stuff here
-
-(defun vc-backend-admin (file &optional rev comment)
- ;; Register a file into the version-control system
- ;; Automatically retrieves a read-only version of the file with
- ;; keywords expanded if vc-keep-workfiles is non-nil, otherwise
- ;; it deletes the workfile.
- (vc-file-clearprops file)
- (or vc-default-back-end
- (setq vc-default-back-end (if (vc-find-binary "rcs") 'RCS 'SCCS)))
- (message "Registering %s..." file)
- (let ((switches
- (if (stringp vc-register-switches)
- (list vc-register-switches)
- vc-register-switches))
- (backend
- (cond
- ((file-exists-p (vc-backend-subdirectory-name)) vc-default-back-end)
- ((file-exists-p "RCS") 'RCS)
- ((file-exists-p "SCCS") 'SCCS)
- ((file-exists-p "CVS") 'CVS)
- (t vc-default-back-end))))
- (cond ((eq backend 'SCCS)
- (apply 'vc-do-command nil 0 "admin" file 'MASTER ;; SCCS
- (and rev (concat "-r" rev))
- "-fb"
- (concat "-i" file)
- (and comment (concat "-y" comment))
- (format
- (car (rassq 'SCCS vc-master-templates))
- (or (file-name-directory file) "")
- (file-name-nondirectory file))
- switches)
- (delete-file file)
- (if vc-keep-workfiles
- (vc-do-command nil 0 "get" file 'MASTER)))
- ((eq backend 'RCS)
- (apply 'vc-do-command nil 0 "ci" file 'WORKFILE ;; RCS
- ;; if available, use the secure registering option
- (and (vc-backend-release-p 'RCS "5.6.4") "-i")
- (concat (if vc-keep-workfiles "-u" "-r") rev)
- (and comment (concat "-t-" comment))
- switches))
- ((eq backend 'CVS)
- (apply 'vc-do-command nil 0 "cvs" file 'WORKFILE ;; CVS
- "add"
- (and comment (string-match "[^\t\n ]" comment)
- (concat "-m" comment))
- switches)
- )))
- (message "Registering %s...done" file)
- )
-
-(defun vc-backend-checkout (file &optional writable rev workfile)
- ;; Retrieve a copy of a saved version into a workfile
- (let ((filename (or workfile file))
- (file-buffer (get-file-buffer file))
- switches)
- (message "Checking out %s..." filename)
- (save-excursion
- ;; Change buffers to get local value of vc-checkout-switches.
- (if file-buffer (set-buffer file-buffer))
- (setq switches (if (stringp vc-checkout-switches)
- (list vc-checkout-switches)
- vc-checkout-switches))
- ;; Save this buffer's default-directory
- ;; and use save-excursion to make sure it is restored
- ;; in the same buffer it was saved in.
- (let ((default-directory default-directory))
- (save-excursion
- ;; Adjust the default-directory so that the check-out creates
- ;; the file in the right place.
- (setq default-directory (file-name-directory filename))
- (vc-backend-dispatch file
- (progn ;; SCCS
- (and rev (string= rev "") (setq rev nil))
- (if workfile
- ;; Some SCCS implementations allow checking out directly to a
- ;; file using the -G option, but then some don't so use the
- ;; least common denominator approach and use the -p option
- ;; ala RCS.
- (let ((vc-modes (logior (file-modes (vc-name file))
- (if writable 128 0)))
- (failed t))
- (unwind-protect
- (progn
- (apply 'vc-do-command
- nil 0 "/bin/sh" file 'MASTER "-c"
- ;; Some shells make the "" dummy argument into $0
- ;; while others use the shell's name as $0 and
- ;; use the "" as $1. The if-statement
- ;; converts the latter case to the former.
- (format "if [ x\"$1\" = x ]; then shift; fi; \
- umask %o; exec >\"$1\" || exit; \
- shift; umask %o; exec get \"$@\""
- (logand 511 (lognot vc-modes))
- (logand 511 (lognot (default-file-modes))))
- "" ; dummy argument for shell's $0
- filename
- (if writable "-e")
- "-p"
- (and rev
- (concat "-r" (vc-lookup-triple file rev)))
- switches)
- (setq failed nil))
- (and failed (file-exists-p filename)
- (delete-file filename))))
- (apply 'vc-do-command nil 0 "get" file 'MASTER ;; SCCS
- (if writable "-e")
- (and rev (concat "-r" (vc-lookup-triple file rev)))
- switches)
- (vc-file-setprop file 'vc-workfile-version nil)))
- (if workfile ;; RCS
- ;; RCS doesn't let us check out into arbitrary file names directly.
- ;; Use `co -p' and make stdout point to the correct file.
- (let ((vc-modes (logior (file-modes (vc-name file))
- (if writable 128 0)))
- (failed t))
- (unwind-protect
- (progn
- (apply 'vc-do-command
- nil 0 "/bin/sh" file 'MASTER "-c"
- ;; See the SCCS case, above, regarding the
- ;; if-statement.
- (format "if [ x\"$1\" = x ]; then shift; fi; \
- umask %o; exec >\"$1\" || exit; \
- shift; umask %o; exec co \"$@\""
- (logand 511 (lognot vc-modes))
- (logand 511 (lognot (default-file-modes))))
- "" ; dummy argument for shell's $0
- filename
- (if writable "-l")
- (concat "-p" rev)
- switches)
- (setq failed nil))
- (and failed (file-exists-p filename) (delete-file filename))))
- (let (new-version)
- ;; if we should go to the head of the trunk,
- ;; clear the default branch first
- (and rev (string= rev "")
- (vc-do-command nil 0 "rcs" file 'MASTER "-b"))
- ;; now do the checkout
- (apply 'vc-do-command
- nil 0 "co" file 'MASTER
- ;; If locking is not strict, force to overwrite
- ;; the writable workfile.
- (if (eq (vc-checkout-model file) 'implicit) "-f")
- (if writable "-l")
- (if rev (concat "-r" rev)
- ;; if no explicit revision was specified,
- ;; check out that of the working file
- (let ((workrev (vc-workfile-version file)))
- (if workrev (concat "-r" workrev)
- nil)))
- switches)
- ;; determine the new workfile version
- (save-excursion
- (set-buffer "*vc*")
- (goto-char (point-min))
- (setq new-version
- (if (re-search-forward "^revision \\([0-9.]+\\).*\n" nil t)
- (buffer-substring (match-beginning 1) (match-end 1)))))
- (vc-file-setprop file 'vc-workfile-version new-version)
- ;; if necessary, adjust the default branch
- (and rev (not (string= rev ""))
- (vc-do-command nil 0 "rcs" file 'MASTER
- (concat "-b" (if (vc-latest-on-branch-p file)
- (if (vc-trunk-p new-version) nil
- (vc-branch-part new-version))
- new-version))))))
- (if workfile ;; CVS
- ;; CVS is much like RCS
- (let ((failed t))
- (unwind-protect
- (progn
- (apply 'vc-do-command
- nil 0 "/bin/sh" file 'WORKFILE "-c"
- "exec >\"$1\" || exit; shift; exec cvs update \"$@\""
- "" ; dummy argument for shell's $0
- workfile
- (concat "-r" rev)
- "-p"
- switches)
- (setq failed nil))
- (and failed (file-exists-p filename) (delete-file filename))))
- ;; default for verbose checkout: clear the sticky tag
- ;; so that the actual update will get the head of the trunk
- (and rev (string= rev "")
- (vc-do-command nil 0 "cvs" file 'WORKFILE "update" "-A"))
- ;; If a revision was specified, check that out.
- (if rev
- (apply 'vc-do-command nil 0 "cvs" file 'WORKFILE
- (and writable (eq (vc-checkout-model file) 'manual) "-w")
- "update"
- (and rev (not (string= rev ""))
- (concat "-r" rev))
- switches)
- ;; If no revision was specified, simply make the file writable.
- (and writable
- (or (eq (vc-checkout-model file) 'manual)
- (zerop (logand 128 (file-modes file))))
- (set-file-modes file (logior 128 (file-modes file)))))
- (if rev (vc-file-setprop file 'vc-workfile-version nil))))
- (cond
- ((not workfile)
- (vc-file-clear-masterprops file)
- (if writable
- (vc-file-setprop file 'vc-locking-user (vc-user-login-name)))
- (vc-file-setprop file
- 'vc-checkout-time (nth 5 (file-attributes file)))))
- (message "Checking out %s...done" filename))))))
-
-(defun vc-backend-logentry-check (file)
- (vc-backend-dispatch file
- (if (>= (buffer-size) 512) ;; SCCS
- (progn
- (goto-char 512)
- (error
- "Log must be less than 512 characters; point is now at pos 512")))
- nil ;; RCS
- nil) ;; CVS
- )
-
-(defun vc-backend-checkin (file rev comment)
- ;; Register changes to FILE as level REV with explanatory COMMENT.
- ;; Automatically retrieves a read-only version of the file with
- ;; keywords expanded if vc-keep-workfiles is non-nil, otherwise
- ;; it deletes the workfile.
- ;; Adaptation for RCS branch support: if this is an explicit checkin,
- ;; or if the checkin creates a new branch, set the master file branch
- ;; accordingly.
- (message "Checking in %s..." file)
- ;; "This log message intentionally left almost blank".
- ;; RCS 5.7 gripes about white-space-only comments too.
- (or (and comment (string-match "[^\t\n ]" comment))
- (setq comment "*** empty log message ***"))
- (save-excursion
- ;; Change buffers to get local value of vc-checkin-switches.
- (set-buffer (or (get-file-buffer file) (current-buffer)))
- (let ((switches
- (if (stringp vc-checkin-switches)
- (list vc-checkin-switches)
- vc-checkin-switches)))
- ;; Clear the master-properties. Do that here, not at the
- ;; end, because if the check-in fails we want them to get
- ;; re-computed before the next try.
- (vc-file-clear-masterprops file)
- (vc-backend-dispatch file
- ;; SCCS
- (progn
- (apply 'vc-do-command nil 0 "delta" file 'MASTER
- (if rev (concat "-r" rev))
- (concat "-y" comment)
- switches)
- (vc-file-setprop file 'vc-locking-user 'none)
- (vc-file-setprop file 'vc-workfile-version nil)
- (if vc-keep-workfiles
- (vc-do-command nil 0 "get" file 'MASTER))
- )
- ;; RCS
- (let ((old-version (vc-workfile-version file)) new-version)
- (apply 'vc-do-command nil 0 "ci" file 'MASTER
- ;; if available, use the secure check-in option
- (and (vc-backend-release-p 'RCS "5.6.4") "-j")
- (concat (if vc-keep-workfiles "-u" "-r") rev)
- (concat "-m" comment)
- switches)
- (vc-file-setprop file 'vc-locking-user 'none)
- (vc-file-setprop file 'vc-workfile-version nil)
-
- ;; determine the new workfile version
- (set-buffer "*vc*")
- (goto-char (point-min))
- (if (or (re-search-forward
- "new revision: \\([0-9.]+\\);" nil t)
- (re-search-forward
- "reverting to previous revision \\([0-9.]+\\)" nil t))
- (progn (setq new-version (buffer-substring (match-beginning 1)
- (match-end 1)))
- (vc-file-setprop file 'vc-workfile-version new-version)))
-
- ;; if we got to a different branch, adjust the default
- ;; branch accordingly
- (cond
- ((and old-version new-version
- (not (string= (vc-branch-part old-version)
- (vc-branch-part new-version))))
- (vc-do-command nil 0 "rcs" file 'MASTER
- (if (vc-trunk-p new-version) "-b"
- (concat "-b" (vc-branch-part new-version))))
- ;; If this is an old RCS release, we might have
- ;; to remove a remaining lock.
- (if (not (vc-backend-release-p 'RCS "5.6.2"))
- ;; exit status of 1 is also accepted.
- ;; It means that the lock was removed before.
- (vc-do-command nil 1 "rcs" file 'MASTER
- (concat "-u" old-version))))))
- ;; CVS
- (progn
- ;; explicit check-in to the trunk requires a
- ;; double check-in (first unexplicit) (CVS-1.3)
- (condition-case nil
- (progn
- (if (and rev (vc-trunk-p rev))
- (apply 'vc-do-command nil 0 "cvs" file 'WORKFILE
- "ci" "-m" "intermediate"
- switches))
- (apply 'vc-do-command nil 0 "cvs" file 'WORKFILE
- "ci" (if rev (concat "-r" rev))
- (concat "-m" comment)
- switches))
- (error (if (eq (vc-cvs-status file) 'needs-merge)
- ;; The CVS output will be on top of this message.
- (error "Type C-x 0 C-x C-q to merge in changes")
- (error "Check-in failed"))))
- ;; determine and store the new workfile version
- (set-buffer "*vc*")
- (goto-char (point-min))
- (if (re-search-forward
- "^\\(new\\|initial\\) revision: \\([0-9.]+\\)" nil t)
- (vc-file-setprop file 'vc-workfile-version
- (buffer-substring (match-beginning 2)
- (match-end 2)))
- (vc-file-setprop file 'vc-workfile-version nil))
- ;; if this was an explicit check-in, remove the sticky tag
- (if rev
- (vc-do-command nil 0 "cvs" file 'WORKFILE "update" "-A"))
- (vc-file-setprop file 'vc-locking-user 'none)
- (vc-file-setprop file 'vc-checkout-time
- (nth 5 (file-attributes file)))))))
- (message "Checking in %s...done" file))
-
-(defun vc-backend-revert (file)
- ;; Revert file to latest checked-in version.
- ;; (for RCS, to workfile version)
- (message "Reverting %s..." file)
- (vc-file-clear-masterprops file)
- (vc-backend-dispatch
- file
- ;; SCCS
- (progn
- (vc-do-command nil 0 "unget" file 'MASTER nil)
- (vc-do-command nil 0 "get" file 'MASTER nil))
- ;; RCS
- (vc-do-command nil 0 "co" file 'MASTER
- "-f" (concat "-u" (vc-workfile-version file)))
- ;; CVS
- (progn
- (delete-file file)
- (vc-do-command nil 0 "cvs" file 'WORKFILE "update")))
- (vc-file-setprop file 'vc-locking-user 'none)
- (vc-file-setprop file 'vc-checkout-time (nth 5 (file-attributes file)))
- (message "Reverting %s...done" file)
- )
-
-(defun vc-backend-steal (file &optional rev)
- ;; Steal the lock on the current workfile. Needs RCS 5.6.2 or later for -M.
- (message "Stealing lock on %s..." file)
- (vc-backend-dispatch file
- (progn ;SCCS
- (vc-do-command nil 0 "unget" file 'MASTER "-n" (if rev (concat "-r" rev)))
- (vc-do-command nil 0 "get" file 'MASTER "-g" (if rev (concat "-r" rev)))
- )
- (vc-do-command nil 0 "rcs" file 'MASTER ;RCS
- "-M" (concat "-u" rev) (concat "-l" rev))
- (error "You cannot steal a CVS lock; there are no CVS locks to steal") ;CVS
- )
- (vc-file-setprop file 'vc-locking-user (vc-user-login-name))
- (message "Stealing lock on %s...done" file)
- )
-
-(defun vc-backend-uncheck (file target)
- ;; Undo the latest checkin.
- (message "Removing last change from %s..." file)
- (vc-backend-dispatch file
- (vc-do-command nil 0 "rmdel" file 'MASTER (concat "-r" target))
- (vc-do-command nil 0 "rcs" file 'MASTER (concat "-o" target))
- nil ;; this is never reached under CVS
- )
- (message "Removing last change from %s...done" file)
- )
-
-(defun vc-backend-print-log (file)
- ;; Get change log associated with FILE.
- (vc-backend-dispatch
- file
- (vc-do-command nil 0 "prs" file 'MASTER)
- (vc-do-command nil 0 "rlog" file 'MASTER)
- (vc-do-command nil 0 "cvs" file 'WORKFILE "log")))
-
-(defun vc-backend-assign-name (file name)
- ;; Assign to a FILE's latest version a given NAME.
- (vc-backend-dispatch file
- (vc-add-triple name file (vc-latest-version file)) ;; SCCS
- (vc-do-command nil 0 "rcs" file 'MASTER (concat "-n" name ":")) ;; RCS
- (vc-do-command nil 0 "cvs" file 'WORKFILE "tag" name) ;; CVS
- )
- )
-
-(defun vc-backend-diff (file &optional oldvers newvers cmp)
- ;; Get a difference report between two versions of FILE.
- ;; Get only a brief comparison report if CMP, a difference report otherwise.
- (let ((backend (vc-backend file)))
- (cond
- ((eq backend 'SCCS)
- (setq oldvers (vc-lookup-triple file oldvers))
- (setq newvers (vc-lookup-triple file newvers)))
- ((eq backend 'RCS)
- (if (not oldvers) (setq oldvers (vc-workfile-version file)))
- ;; If we know that --brief is not supported, don't try it.
- (setq cmp (and cmp (not (eq vc-rcsdiff-knows-brief 'no))))))
- ;; SCCS and RCS shares a lot of code.
- (cond
- ((or (eq backend 'SCCS) (eq backend 'RCS))
- (let* ((command (if (eq backend 'SCCS) "vcdiff" "rcsdiff"))
- (mode (if (eq backend 'RCS) 'WORKFILE 'MASTER))
- (options (append (list (and cmp "--brief")
- "-q"
- (and oldvers (concat "-r" oldvers))
- (and newvers (concat "-r" newvers)))
- (and (not cmp)
- (if (listp diff-switches)
- diff-switches
- (list diff-switches)))))
- (status (apply 'vc-do-command "*vc-diff*" 2
- command file mode options)))
- ;; If --brief didn't work, do a double-take and remember it
- ;; for the future.
- (if (eq status 2)
- (prog1
- (apply 'vc-do-command "*vc-diff*" 1 command file 'WORKFILE
- (if cmp (cdr options) options))
- (if cmp (setq vc-rcsdiff-knows-brief 'no)))
- ;; If --brief DID work, remember that, too.
- (and cmp (not vc-rcsdiff-knows-brief)
- (setq vc-rcsdiff-knows-brief 'yes))
- status)))
- ;; CVS is different.
- ((eq backend 'CVS)
- (if (string= (vc-workfile-version file) "0") ;CVS
- ;; This file is added but not yet committed; there is no master file.
- (if (or oldvers newvers)
- (error "No revisions of %s exist" file)
- (if cmp 1 ;; file is added but not committed,
- ;; we regard this as "changed".
- ;; diff it against /dev/null.
- (apply 'vc-do-command
- "*vc-diff*" 1 "diff" file 'WORKFILE
- (append (if (listp diff-switches)
- diff-switches
- (list diff-switches)) '("/dev/null")))))
- ;; cmp is not yet implemented -- we always do a full diff.
- (apply 'vc-do-command
- "*vc-diff*" 1 "cvs" file 'WORKFILE "diff"
- (and oldvers (concat "-r" oldvers))
- (and newvers (concat "-r" newvers))
- (if (listp diff-switches)
- diff-switches
- (list diff-switches)))))
- (t
- (vc-registration-error file)))))
-
-(defun vc-backend-merge-news (file)
- ;; Merge in any new changes made to FILE.
- (message "Merging changes into %s..." file)
- (prog1
- (vc-backend-dispatch
- file
- (error "vc-backend-merge-news not meaningful for SCCS files") ;SCCS
- (error "vc-backend-merge-news not meaningful for RCS files") ;RCS
- (save-excursion ; CVS
- (vc-file-clear-masterprops file)
- (vc-file-setprop file 'vc-workfile-version nil)
- (vc-file-setprop file 'vc-locking-user nil)
- (vc-do-command nil 0 "cvs" file 'WORKFILE "update")
- ;; CVS doesn't return an error code if conflicts are detected.
- ;; Since we want to warn the user about it (and possibly start
- ;; emerge later), scan the output and see if this occurred.
- (set-buffer (get-buffer "*vc*"))
- (goto-char (point-min))
- (if (re-search-forward "^cvs update: conflicts found in .*" nil t)
- 1 ;; error code for caller
- 0 ;; no conflict detected
- )))
- (message "Merging changes into %s...done" file)))
-
-(defun vc-check-headers ()
- "Check if the current file has any headers in it."
- (interactive)
- (save-excursion
- (goto-char (point-min))
- (vc-backend-dispatch buffer-file-name
- (re-search-forward "%[MIRLBSDHTEGUYFPQCZWA]%" nil t) ;; SCCS
- (re-search-forward "\\$[A-Za-z\300-\326\330-\366\370-\377]+\\(: [\t -#%-\176\240-\377]*\\)?\\$" nil t) ;; RCS
- 'RCS ;; CVS works like RCS in this regard.
- )
- ))
-
-;; Back-end-dependent stuff ends here.
-
-;; Set up key bindings for use while editing log messages
-
-(defun vc-log-mode ()
- "Minor mode for driving version-control tools.
-These bindings are added to the global keymap when you enter this mode:
-\\[vc-next-action] perform next logical version-control operation on current file
-\\[vc-register] register current file
-\\[vc-toggle-read-only] like next-action, but won't register files
-\\[vc-insert-headers] insert version-control headers in current file
-\\[vc-print-log] display change history of current file
-\\[vc-revert-buffer] revert buffer to latest version
-\\[vc-cancel-version] undo latest checkin
-\\[vc-diff] show diffs between file versions
-\\[vc-version-other-window] visit old version in another window
-\\[vc-directory] show all files locked by any user in or below .
-\\[vc-update-change-log] add change log entry from recent checkins
-
-While you are entering a change log message for a version, the following
-additional bindings will be in effect.
-
-\\[vc-finish-logentry] proceed with check in, ending log message entry
-
-Whenever you do a checkin, your log comment is added to a ring of
-saved comments. These can be recalled as follows:
-
-\\[vc-next-comment] replace region with next message in comment ring
-\\[vc-previous-comment] replace region with previous message in comment ring
-\\[vc-comment-search-reverse] search backward for regexp in the comment ring
-\\[vc-comment-search-forward] search backward for regexp in the comment ring
-
-Entry to the change-log submode calls the value of text-mode-hook, then
-the value of vc-log-mode-hook.
-
-Global user options:
- vc-initial-comment If non-nil, require user to enter a change
- comment upon first checkin of the file.
-
- vc-keep-workfiles Non-nil value prevents workfiles from being
- deleted when changes are checked in
-
- vc-suppress-confirm Suppresses some confirmation prompts,
- notably for reversions.
-
- vc-header-alist Which keywords to insert when adding headers
- with \\[vc-insert-headers]. Defaults to
- '(\"\%\W\%\") under SCCS, '(\"\$Id\$\") under
- RCS and CVS.
-
- vc-static-header-alist By default, version headers inserted in C files
- get stuffed in a static string area so that
- ident(RCS/CVS) or what(SCCS) can see them in
- the compiled object code. You can override
- this by setting this variable to nil, or change
- the header template by changing it.
-
- vc-command-messages if non-nil, display run messages from the
- actual version-control utilities (this is
- intended primarily for people hacking vc
- itself).
-"
- (interactive)
- (set-syntax-table text-mode-syntax-table)
- (use-local-map vc-log-entry-mode)
- (setq local-abbrev-table text-mode-abbrev-table)
- (setq major-mode 'vc-log-mode)
- (setq mode-name "VC-Log")
- (make-local-variable 'vc-log-file)
- (make-local-variable 'vc-log-version)
- (make-local-variable 'vc-comment-ring-index)
- (set-buffer-modified-p nil)
- (setq buffer-file-name nil)
- (run-hooks 'text-mode-hook 'vc-log-mode-hook)
-)
-
-;; Initialization code, to be done just once at load-time
-(if vc-log-entry-mode
- nil
- (setq vc-log-entry-mode (make-sparse-keymap))
- (define-key vc-log-entry-mode "\M-n" 'vc-next-comment)
- (define-key vc-log-entry-mode "\M-p" 'vc-previous-comment)
- (define-key vc-log-entry-mode "\M-r" 'vc-comment-search-reverse)
- (define-key vc-log-entry-mode "\M-s" 'vc-comment-search-forward)
- (define-key vc-log-entry-mode "\C-c\C-c" 'vc-finish-logentry)
- )
-
-;;; These things should probably be generally available
-
-(defun vc-file-tree-walk (dirname func &rest args)
- "Walk recursively through DIRNAME.
-Invoke FUNC f ARGS on each non-directory file f underneath it."
- (vc-file-tree-walk-internal (expand-file-name dirname) func args)
- (message "Traversing directory %s...done" dirname))
-
-(defun vc-file-tree-walk-internal (file func args)
- (if (not (file-directory-p file))
- (apply func file args)
- (message "Traversing directory %s..." (abbreviate-file-name file))
- (let ((dir (file-name-as-directory file)))
- (mapcar
- (function
- (lambda (f) (or
- (string-equal f ".")
- (string-equal f "..")
- (member f vc-directory-exclusion-list)
- (let ((dirf (concat dir f)))
- (or
- (file-symlink-p dirf) ;; Avoid possible loops
- (vc-file-tree-walk-internal dirf func args))))))
- (directory-files dir)))))
-
-(provide 'vc)
-
-;;; DEVELOPER'S NOTES ON CONCURRENCY PROBLEMS IN THIS CODE
-;;;
-;;; These may be useful to anyone who has to debug or extend the package.
-;;; (Note that this information corresponds to versions 5.x. Some of it
-;;; might have been invalidated by the additions to support branching
-;;; and RCS keyword lookup. AS, 1995/03/24)
-;;;
-;;; A fundamental problem in VC is that there are time windows between
-;;; vc-next-action's computations of the file's version-control state and
-;;; the actions that change it. This is a window open to lossage in a
-;;; multi-user environment; someone else could nip in and change the state
-;;; of the master during it.
-;;;
-;;; The performance problem is that rlog/prs calls are very expensive; we want
-;;; to avoid them as much as possible.
-;;;
-;;; ANALYSIS:
-;;;
-;;; The performance problem, it turns out, simplifies in practice to the
-;;; problem of making vc-locking-user fast. The two other functions that call
-;;; prs/rlog will not be so commonly used that the slowdown is a problem; one
-;;; makes snapshots, the other deletes the calling user's last change in the
-;;; master.
-;;;
-;;; The race condition implies that we have to either (a) lock the master
-;;; during the entire execution of vc-next-action, or (b) detect and
-;;; recover from errors resulting from dispatch on an out-of-date state.
-;;;
-;;; Alternative (a) appears to be infeasible. The problem is that we can't
-;;; guarantee that the lock will ever be removed. Suppose a user starts a
-;;; checkin, the change message buffer pops up, and the user, having wandered
-;;; off to do something else, simply forgets about it?
-;;;
-;;; Alternative (b), on the other hand, works well with a cheap way to speed up
-;;; vc-locking-user. Usually, if a file is registered, we can read its locked/
-;;; unlocked state and its current owner from its permissions.
-;;;
-;;; This shortcut will fail if someone has manually changed the workfile's
-;;; permissions; also if developers are munging the workfile in several
-;;; directories, with symlinks to a master (in this latter case, the
-;;; permissions shortcut will fail to detect a lock asserted from another
-;;; directory).
-;;;
-;;; Note that these cases correspond exactly to the errors which could happen
-;;; because of a competing checkin/checkout race in between two instances of
-;;; vc-next-action.
-;;;
-;;; For VC's purposes, a workfile/master pair may have the following states:
-;;;
-;;; A. Unregistered. There is a workfile, there is no master.
-;;;
-;;; B. Registered and not locked by anyone.
-;;;
-;;; C. Locked by calling user and unchanged.
-;;;
-;;; D. Locked by the calling user and changed.
-;;;
-;;; E. Locked by someone other than the calling user.
-;;;
-;;; This makes for 25 states and 20 error conditions. Here's the matrix:
-;;;
-;;; VC's idea of state
-;;; |
-;;; V Actual state RCS action SCCS action Effect
-;;; A B C D E
-;;; A . 1 2 3 4 ci -u -t- admin -fb -i<file> initial admin
-;;; B 5 . 6 7 8 co -l get -e checkout
-;;; C 9 10 . 11 12 co -u unget; get revert
-;;; D 13 14 15 . 16 ci -u -m<comment> delta -y<comment>; get checkin
-;;; E 17 18 19 20 . rcs -u -M -l unget -n ; get -g steal lock
-;;;
-;;; All commands take the master file name as a last argument (not shown).
-;;;
-;;; In the discussion below, a "self-race" is a pathological situation in
-;;; which VC operations are being attempted simultaneously by two or more
-;;; Emacsen running under the same username.
-;;;
-;;; The vc-next-action code has the following windows:
-;;;
-;;; Window P:
-;;; Between the check for existence of a master file and the call to
-;;; admin/checkin in vc-buffer-admin (apparent state A). This window may
-;;; never close if the initial-comment feature is on.
-;;;
-;;; Window Q:
-;;; Between the call to vc-workfile-unchanged-p in and the immediately
-;;; following revert (apparent state C).
-;;;
-;;; Window R:
-;;; Between the call to vc-workfile-unchanged-p in and the following
-;;; checkin (apparent state D). This window may never close.
-;;;
-;;; Window S:
-;;; Between the unlock and the immediately following checkout during a
-;;; revert operation (apparent state C). Included in window Q.
-;;;
-;;; Window T:
-;;; Between vc-locking-user and the following checkout (apparent state B).
-;;;
-;;; Window U:
-;;; Between vc-locking-user and the following revert (apparent state C).
-;;; Includes windows Q and S.
-;;;
-;;; Window V:
-;;; Between vc-locking-user and the following checkin (apparent state
-;;; D). This window may never be closed if the user fails to complete the
-;;; checkin message. Includes window R.
-;;;
-;;; Window W:
-;;; Between vc-locking-user and the following steal-lock (apparent
-;;; state E). This window may never close if the user fails to complete
-;;; the steal-lock message. Includes window X.
-;;;
-;;; Window X:
-;;; Between the unlock and the immediately following re-lock during a
-;;; steal-lock operation (apparent state E). This window may never cloce
-;;; if the user fails to complete the steal-lock message.
-;;;
-;;; Errors:
-;;;
-;;; Apparent state A ---
-;;;
-;;; 1. File looked unregistered but is actually registered and not locked.
-;;;
-;;; Potential cause: someone else's admin during window P, with
-;;; caller's admin happening before their checkout.
-;;;
-;;; RCS: Prior to version 5.6.4, ci fails with message
-;;; "no lock set by <user>". From 5.6.4 onwards, VC uses the new
-;;; ci -i option and the message is "<file>,v: already exists".
-;;; SCCS: admin will fail with error (ad19).
-;;;
-;;; We can let these errors be passed up to the user.
-;;;
-;;; 2. File looked unregistered but is actually locked by caller, unchanged.
-;;;
-;;; Potential cause: self-race during window P.
-;;;
-;;; RCS: Prior to version 5.6.4, reverts the file to the last saved
-;;; version and unlocks it. From 5.6.4 onwards, VC uses the new
-;;; ci -i option, failing with message "<file>,v: already exists".
-;;; SCCS: will fail with error (ad19).
-;;;
-;;; Either of these consequences is acceptable.
-;;;
-;;; 3. File looked unregistered but is actually locked by caller, changed.
-;;;
-;;; Potential cause: self-race during window P.
-;;;
-;;; RCS: Prior to version 5.6.4, VC registers the caller's workfile as
-;;; a delta with a null change comment (the -t- switch will be
-;;; ignored). From 5.6.4 onwards, VC uses the new ci -i option,
-;;; failing with message "<file>,v: already exists".
-;;; SCCS: will fail with error (ad19).
-;;;
-;;; 4. File looked unregistered but is locked by someone else.
-;;;
-;;; Potential cause: someone else's admin during window P, with
-;;; caller's admin happening *after* their checkout.
-;;;
-;;; RCS: Prior to version 5.6.4, ci fails with a
-;;; "no lock set by <user>" message. From 5.6.4 onwards,
-;;; VC uses the new ci -i option, failing with message
-;;; "<file>,v: already exists".
-;;; SCCS: will fail with error (ad19).
-;;;
-;;; We can let these errors be passed up to the user.
-;;;
-;;; Apparent state B ---
-;;;
-;;; 5. File looked registered and not locked, but is actually unregistered.
-;;;
-;;; Potential cause: master file got nuked during window P.
-;;;
-;;; RCS: will fail with "RCS/<file>: No such file or directory"
-;;; SCCS: will fail with error ut4.
-;;;
-;;; We can let these errors be passed up to the user.
-;;;
-;;; 6. File looked registered and not locked, but is actually locked by the
-;;; calling user and unchanged.
-;;;
-;;; Potential cause: self-race during window T.
-;;;
-;;; RCS: in the same directory as the previous workfile, co -l will fail
-;;; with "co error: writable foo exists; checkout aborted". In any other
-;;; directory, checkout will succeed.
-;;; SCCS: will fail with ge17.
-;;;
-;;; Either of these consequences is acceptable.
-;;;
-;;; 7. File looked registered and not locked, but is actually locked by the
-;;; calling user and changed.
-;;;
-;;; As case 6.
-;;;
-;;; 8. File looked registered and not locked, but is actually locked by another
-;;; user.
-;;;
-;;; Potential cause: someone else checks it out during window T.
-;;;
-;;; RCS: co error: revision 1.3 already locked by <user>
-;;; SCCS: fails with ge4 (in directory) or ut7 (outside it).
-;;;
-;;; We can let these errors be passed up to the user.
-;;;
-;;; Apparent state C ---
-;;;
-;;; 9. File looks locked by calling user and unchanged, but is unregistered.
-;;;
-;;; As case 5.
-;;;
-;;; 10. File looks locked by calling user and unchanged, but is actually not
-;;; locked.
-;;;
-;;; Potential cause: a self-race in window U, or by the revert's
-;;; landing during window X of some other user's steal-lock or window S
-;;; of another user's revert.
-;;;
-;;; RCS: succeeds, refreshing the file from the identical version in
-;;; the master.
-;;; SCCS: fails with error ut4 (p file nonexistent).
-;;;
-;;; Either of these consequences is acceptable.
-;;;
-;;; 11. File is locked by calling user. It looks unchanged, but is actually
-;;; changed.
-;;;
-;;; Potential cause: the file would have to be touched by a self-race
-;;; during window Q.
-;;;
-;;; The revert will succeed, removing whatever changes came with
-;;; the touch. It is theoretically possible that work could be lost.
-;;;
-;;; 12. File looks like it's locked by the calling user and unchanged, but
-;;; it's actually locked by someone else.
-;;;
-;;; Potential cause: a steal-lock in window V.
-;;;
-;;; RCS: co error: revision <rev> locked by <user>; use co -r or rcs -u
-;;; SCCS: fails with error un2
-;;;
-;;; We can pass these errors up to the user.
-;;;
-;;; Apparent state D ---
-;;;
-;;; 13. File looks like it's locked by the calling user and changed, but it's
-;;; actually unregistered.
-;;;
-;;; Potential cause: master file got nuked during window P.
-;;;
-;;; RCS: Prior to version 5.6.4, checks in the user's version as an
-;;; initial delta. From 5.6.4 onwards, VC uses the new ci -j
-;;; option, failing with message "no such file or directory".
-;;; SCCS: will fail with error ut4.
-;;;
-;;; This case is kind of nasty. Under RCS prior to version 5.6.4,
-;;; VC may fail to detect the loss of previous version information.
-;;;
-;;; 14. File looks like it's locked by the calling user and changed, but it's
-;;; actually unlocked.
-;;;
-;;; Potential cause: self-race in window V, or the checkin happening
-;;; during the window X of someone else's steal-lock or window S of
-;;; someone else's revert.
-;;;
-;;; RCS: ci will fail with "no lock set by <user>".
-;;; SCCS: delta will fail with error ut4.
-;;;
-;;; 15. File looks like it's locked by the calling user and changed, but it's
-;;; actually locked by the calling user and unchanged.
-;;;
-;;; Potential cause: another self-race --- a whole checkin/checkout
-;;; sequence by the calling user would have to land in window R.
-;;;
-;;; SCCS: checks in a redundant delta and leaves the file unlocked as usual.
-;;; RCS: reverts to the file state as of the second user's checkin, leaving
-;;; the file unlocked.
-;;;
-;;; It is theoretically possible that work could be lost under RCS.
-;;;
-;;; 16. File looks like it's locked by the calling user and changed, but it's
-;;; actually locked by a different user.
-;;;
-;;; RCS: ci error: no lock set by <user>
-;;; SCCS: unget will fail with error un2
-;;;
-;;; We can pass these errors up to the user.
-;;;
-;;; Apparent state E ---
-;;;
-;;; 17. File looks like it's locked by some other user, but it's actually
-;;; unregistered.
-;;;
-;;; As case 13.
-;;;
-;;; 18. File looks like it's locked by some other user, but it's actually
-;;; unlocked.
-;;;
-;;; Potential cause: someone released a lock during window W.
-;;;
-;;; RCS: The calling user will get the lock on the file.
-;;; SCCS: unget -n will fail with cm4.
-;;;
-;;; Either of these consequences will be OK.
-;;;
-;;; 19. File looks like it's locked by some other user, but it's actually
-;;; locked by the calling user and unchanged.
-;;;
-;;; Potential cause: the other user relinquishing a lock followed by
-;;; a self-race, both in window W.
-;;;
-;;; Under both RCS and SCCS, both unlock and lock will succeed, making
-;;; the sequence a no-op.
-;;;
-;;; 20. File looks like it's locked by some other user, but it's actually
-;;; locked by the calling user and changed.
-;;;
-;;; As case 19.
-;;;
-;;; PROBLEM CASES:
-;;;
-;;; In order of decreasing severity:
-;;;
-;;; Cases 11 and 15 are the only ones that potentially lose work.
-;;; They would require a self-race for this to happen.
-;;;
-;;; Case 13 in RCS loses information about previous deltas, retaining
-;;; only the information in the current workfile. This can only happen
-;;; if the master file gets nuked in window P.
-;;;
-;;; Case 3 in RCS and case 15 under SCCS insert a redundant delta with
-;;; no change comment in the master. This would require a self-race in
-;;; window P or R respectively.
-;;;
-;;; Cases 2, 10, 19 and 20 do extra work, but make no changes.
-;;;
-;;; Unfortunately, it appears to me that no recovery is possible in these
-;;; cases. They don't yield error messages, so there's no way to tell that
-;;; a race condition has occurred.
-;;;
-;;; All other cases don't change either the workfile or the master, and
-;;; trigger command errors which the user will see.
-;;;
-;;; Thus, there is no explicit recovery code.
-
-;;; vc.el ends here
diff --git a/lisp/view.el b/lisp/view.el
deleted file mode 100644
index bbc168b6f9c..00000000000
--- a/lisp/view.el
+++ /dev/null
@@ -1,469 +0,0 @@
-;;; view.el --- peruse file or buffer without editing.
-
-;; Copyright (C) 1985, 1989, 1994, 1995 Free Software Foundation, Inc.
-
-;; Author: K. Shane Hartman
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This package provides the `view' minor mode documented in the Emacs
-;; user's manual.
-
-;;; Code:
-
-;;;###autoload
-(defvar view-highlight-face 'highlight
- "*The overlay face used for highlighting the match found by View mode search.")
-
-(defvar view-mode nil "Non-nil if View mode is enabled.")
-(make-variable-buffer-local 'view-mode)
-
-(defvar view-mode-auto-exit nil
- "Non-nil means scrolling past the end of buffer exits View mode.
-Some commands, such as \\[view-file], set this to t locally;
-the only way to override that is to set it to nil using `view-mode-hook'.")
-
-(make-variable-buffer-local 'view-mode-auto-exit)
-
-(defvar view-old-buffer-read-only nil)
-(make-variable-buffer-local 'view-old-buffer-read-only)
-(defvar view-old-Helper-return-blurb)
-(make-variable-buffer-local 'view-old-Helper-return-blurb)
-
-(defvar view-scroll-size nil)
-(make-variable-buffer-local 'view-scroll-size)
-
-(defvar view-last-regexp nil)
-(make-variable-buffer-local 'view-last-regexp)
-
-(defvar view-exit-action nil)
-(make-variable-buffer-local 'view-exit-action)
-(defvar view-return-here nil)
-(make-variable-buffer-local 'view-return-here)
-(defvar view-exit-position nil)
-(make-variable-buffer-local 'view-exit-position)
-
-(defvar view-overlay nil
- "Overlay used to display where a search operation found its match.
-This is local in each buffer, once it is used.")
-(make-variable-buffer-local 'view-overlay)
-
-(or (assq 'view-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(view-mode " View") minor-mode-alist)))
-
-(defvar view-mode-map nil)
-(if view-mode-map
- nil
- (setq view-mode-map (make-keymap))
- ;; We used to call suppress-keymap here, but that isn't good in a minor mode.
- ;; Self-inserting characters will beep anyway, since the buffer is read-only,
- ;; and we should not interfere with letters that serve as useful commands.
- (define-key view-mode-map "q" 'view-exit)
- (define-key view-mode-map "<" 'beginning-of-buffer)
- (define-key view-mode-map ">" 'end-of-buffer)
- (define-key view-mode-map "\ev" 'View-scroll-lines-backward)
- (define-key view-mode-map "\C-v" 'View-scroll-lines-forward)
- (define-key view-mode-map " " 'View-scroll-lines-forward)
- (define-key view-mode-map "\C-?" 'View-scroll-lines-backward)
- (define-key view-mode-map "\n" 'View-scroll-one-more-line)
- (define-key view-mode-map "\r" 'View-scroll-one-more-line)
- (define-key view-mode-map "z" 'View-scroll-lines-forward-set-scroll-size)
- (define-key view-mode-map "g" 'View-goto-line)
- (define-key view-mode-map "=" 'what-line)
- (define-key view-mode-map "." 'set-mark-command)
- (define-key view-mode-map "'" 'View-back-to-mark)
- (define-key view-mode-map "@" 'View-back-to-mark)
- (define-key view-mode-map "x" 'exchange-point-and-mark)
- (define-key view-mode-map "h" 'describe-mode)
- (define-key view-mode-map "?" 'describe-mode)
- (define-key view-mode-map "s" 'isearch-forward)
- (define-key view-mode-map "r" 'isearch-backward)
- (define-key view-mode-map "/" 'View-search-regexp-forward)
- (define-key view-mode-map "\\" 'View-search-regexp-backward)
- ;; This conflicts with the standard binding of isearch-regexp-forward
- (define-key view-mode-map "\e\C-s" 'View-search-regexp-forward)
- (define-key view-mode-map "\e\C-r" 'View-search-regexp-backward)
- (define-key view-mode-map "n" 'View-search-last-regexp-forward)
- (define-key view-mode-map "p" 'View-search-last-regexp-backward)
- )
-
-(or (assq 'view-mode minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons (cons 'view-mode view-mode-map) minor-mode-map-alist)))
-
-
-;;;###autoload
-(defun view-file (file-name)
- "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.
-
-This command runs the normal hook `view-mode-hook'."
- (interactive "fView file: ")
- (let ((old-buf (current-buffer))
- (had-a-buf (get-file-buffer file-name))
- (buf-to-view (find-file-noselect file-name)))
- ;; This used to pass t as second argument,
- ;; but then the buffer did not show up in the Buffers menu.
- (switch-to-buffer buf-to-view had-a-buf)
- (view-mode-enter old-buf
- (and (not had-a-buf) (not (buffer-modified-p buf-to-view))
- 'kill-buffer))))
-
-;;;###autoload
-(defun view-file-other-window (file-name)
- "View FILE in View mode in other window.
-Return 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.
-
-This command runs the normal hook `view-mode-hook'."
- (interactive "fView file: ")
- (let ((old-arrangement (current-window-configuration))
- (had-a-buf (get-file-buffer file-name))
- (buf-to-view (find-file-noselect file-name)))
- (switch-to-buffer-other-window buf-to-view)
- (view-mode-enter old-arrangement
- (and (not had-a-buf) (not (buffer-modified-p buf-to-view))
- 'kill-buffer))))
-
-;;;###autoload
-(defun view-buffer (buffer-name)
- "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.
-
-This command runs the normal hook `view-mode-hook'."
- (interactive "bView buffer: ")
- (let ((old-buf (current-buffer)))
- (switch-to-buffer buffer-name t)
- (view-mode-enter old-buf nil)))
-
-;;;###autoload
-(defun view-buffer-other-window (buffer-name not-return)
- "View BUFFER in View mode in another window.
-Return to previous buffer when done, unless NOT-RETURN is non-nil.
-
-The usual Emacs commands are not available in View mode; 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.
-
-This command runs the normal hook `view-mode-hook'."
- (interactive "bView buffer:\nP")
- (let ((return-to (and not-return (current-window-configuration))))
- (switch-to-buffer-other-window buffer-name)
- (view-mode-enter return-to)))
-
-;;;###autoload
-(defun view-mode (&optional arg)
- "Toggle View mode.
-With a prefix argument, turn View mode on if the argument is >= zero
-and off if it is not.
-
-If you use this function to turn on View mode, then subsequently
-\"exiting\" View mode does nothing except turn View mode off. The
-other way to turn View mode on is by calling `view-mode-enter';
-that is what Lisp programs usually use.
-
-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).
-\\[help-command] 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 exit view-mode and return to previous buffer."
- (interactive "P")
- (setq view-mode
- (if (null arg)
- (not view-mode)
- (> (prefix-numeric-value arg) 0)))
- (force-mode-line-update))
-
-(defun view-mode-enter (&optional prev-buffer action)
- "Enter View mode, a Minor mode for viewing text but not editing it.
-See the function `view-mode' for more details.
-
-This function runs the normal hook `view-mode-hook'.
-
-\\{view-mode-map}"
-; Not interactive because dangerous things happen
-; if you call it without passing a buffer as argument
-; and they are not easy to fix.
-; (interactive)
- (setq view-old-buffer-read-only buffer-read-only)
- (setq view-old-Helper-return-blurb
- (and (boundp 'Helper-return-blurb) Helper-return-blurb))
-
- ;; Enable view-exit to make use of the data we just saved
- ;; and to perform the exit action.
- (setq view-mode-auto-exit t)
-
- (setq buffer-read-only t)
- (setq view-mode t)
- (setq Helper-return-blurb
- (format "continue viewing %s"
- (if (buffer-file-name)
- (file-name-nondirectory (buffer-file-name))
- (buffer-name))))
-
- (setq view-exit-action action)
- (setq view-return-here prev-buffer)
- (setq view-exit-position (point-marker))
-
- (beginning-of-line)
- (setq goal-column nil)
-
- (run-hooks 'view-mode-hook)
- (message "%s"
- (substitute-command-keys
- "Type \\[help-command] for help, \\[describe-mode] for commands, \\[view-exit] to quit.")))
-
-(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 view-mode nil)
- (and view-overlay (delete-overlay view-overlay))
- (force-mode-line-update)
- (cond (view-mode-auto-exit
- (setq buffer-read-only view-old-buffer-read-only)
- (setq view-mode-auto-exit nil)
-
- (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))
- (cond
- ((bufferp view-return-here)
- (switch-to-buffer view-return-here))
- ((window-configuration-p view-return-here)
- (set-window-configuration view-return-here)))
- (if action (funcall action viewed-buffer))))))
-
-(defun view-window-size () (1- (window-height)))
-
-(defun view-scroll-size ()
- (min (view-window-size) (or view-scroll-size (view-window-size))))
-
-(defvar view-mode-hook nil
- "Normal hook run when starting to view a buffer or file.")
-
-;(defun view-last-command (&optional who what)
-; (setq view-last-command-entry this-command)
-; (setq view-last-command who)
-; (setq view-last-command-argument what))
-
-;(defun View-repeat-last-command ()
-; "Repeat last command issued in View mode."
-; (interactive)
-; (if (and view-last-command
-; (eq view-last-command-entry last-command))
-; (funcall view-last-command view-last-command-argument))
-; (setq this-command view-last-command-entry))
-
-(defun View-goto-line (line)
- "Move to line LINE in View mode.
-Display is centered at LINE. Sets mark at starting position and pushes
-mark ring."
- (interactive "p")
- (push-mark)
- (goto-line line)
- (recenter (/ (view-window-size) 2)))
-
-(defun View-scroll-lines-forward (&optional lines)
- "Scroll forward in View mode, or exit if end of text is visible.
-No arg means whole window full, or number of lines set by \\[View-scroll-lines-forward-set-scroll-size].
-Arg is number of lines to scroll."
- (interactive "P")
- (setq lines
- (if lines (prefix-numeric-value lines)
- (view-scroll-size)))
- (if (and (pos-visible-in-window-p (point-max))
- ;; Allow scrolling backward at the end of the buffer.
- (> lines 0)
- view-mode-auto-exit)
- (view-exit)
- ;; (view-last-command 'View-scroll-lines-forward lines)
- (if (>= lines (view-window-size))
- (scroll-up nil)
- (if (>= (- lines) (view-window-size))
- (scroll-down nil)
- (scroll-up lines)))
- (cond ((pos-visible-in-window-p (point-max))
- (goto-char (point-max))
- (message "%s"
- (substitute-command-keys
- "End. Type \\[view-exit] to quit viewing."))))
- (move-to-window-line -1)
- (beginning-of-line)))
-
-(defun View-scroll-lines-forward-set-scroll-size (&optional lines)
- "Scroll forward LINES lines in View mode, setting the \"scroll size\".
-This is the number of lines which \\[View-scroll-lines-forward] and \\[View-scroll-lines-backward] scroll by default.
-The absolute value of LINES is used, so this command can be used to scroll
-backwards (but \"scroll size\" is always positive). If LINES is greater than
-window height or omitted, then window height is assumed. If LINES is less
-than window height then scrolling context is provided from previous screen."
- (interactive "P")
- (if (not lines)
- (setq view-scroll-size (view-window-size))
- (setq lines (prefix-numeric-value lines))
- (setq view-scroll-size
- (min (if (> lines 0) lines (- lines)) (view-window-size))))
- (View-scroll-lines-forward lines))
-
-(defun View-scroll-one-more-line (&optional arg)
- "Scroll one more line up in View mode.
-With ARG scroll one line down."
- (interactive "P")
- (View-scroll-lines-forward (if (not arg) 1 -1)))
-
-(defun View-scroll-lines-backward (&optional lines)
- "Scroll backward in View mode.
-No arg means whole window full, or number of lines set by \\[View-scroll-lines-forward-set-scroll-size].
-Arg is number of lines to scroll."
- (interactive "P")
- (View-scroll-lines-forward (if lines
- (- (prefix-numeric-value lines))
- (- (view-scroll-size)))))
-
-(defun View-search-regexp-forward (n regexp)
- "Search forward for Nth occurrence of REGEXP.
-Displays line found at center of window. REGEXP is remembered for
-searching with \\[View-search-last-regexp-forward] and \\[View-search-last-regexp-backward]. Sets mark at starting position and pushes mark ring.
-
-The variable `view-highlight-face' controls the face that is used
-for highlighting the match that is found."
- (interactive "p\nsSearch forward (regexp): ")
-;;;(view-last-command 'View-search-last-regexp-forward n)
- (view-search n (if (equal regexp "") view-last-regexp regexp)))
-
-(defun View-search-regexp-backward (n regexp)
- "Search backward from window start for Nth instance of REGEXP.
-Displays line found at center of window. REGEXP is remembered for
-searching with \\[View-search-last-regexp-forward] and \\[View-search-last-regexp-backward]. Sets mark at starting position and pushes mark ring.
-
-The variable `view-highlight-face' controls the face that is used
-for highlighting the match that is found."
- (interactive "p\nsSearch backward (regexp): ")
- (View-search-regexp-forward (- n)
- (if (equal regexp "") view-last-regexp regexp)))
-
-(defun View-search-last-regexp-forward (n)
- "Search forward from window end for Nth instance of last regexp.
-Displays line found at center of window. Sets mark at starting position
-and pushes mark ring.
-
-The variable `view-highlight-face' controls the face that is used
-for highlighting the match that is found."
- (interactive "p")
- (if view-last-regexp
- (View-search-regexp-forward n view-last-regexp)
- (error "No previous View-mode search")))
-
-(defun View-search-last-regexp-backward (n)
- "Search backward from window start for Nth instance of last regexp.
-Displays line found at center of window. Sets mark at starting position and
-pushes mark ring.
-
-The variable `view-highlight-face' controls the face that is used
-for highlighting the match that is found."
- (interactive "p")
- (if view-last-regexp
- (View-search-regexp-backward n view-last-regexp)
- (error "No previous View-mode search")))
-
-(defun View-back-to-mark (&optional ignore)
- "Return to last mark set in View mode, else beginning of file.
-Displays line at center of window. Pops mark ring so successive
-invocations return to earlier marks."
- (interactive)
- (goto-char (or (mark t) (point-min)))
- (pop-mark)
- (recenter (/ (view-window-size) 2)))
-
-(defun view-search (times regexp)
- (setq view-last-regexp regexp)
- (let (where)
- (save-excursion
- (move-to-window-line (if (< times 0) 0 -1))
- (if (re-search-forward regexp nil t times)
- (setq where (point))))
- (if where
- (progn
- (push-mark)
- (goto-char where)
- (if view-overlay
- (move-overlay view-overlay (match-beginning 0) (match-end 0))
- (setq view-overlay
- (make-overlay (match-beginning 0) (match-end 0))))
- (overlay-put view-overlay 'face view-highlight-face)
- (beginning-of-line)
- (recenter (/ (view-window-size) 2)))
- (message "Can't find occurrence %d of %s" times regexp)
- (sit-for 4))))
-
-
-(provide 'view)
-
-;;; view.el ends here
diff --git a/lisp/vms-patch.el b/lisp/vms-patch.el
deleted file mode 100644
index 41dcd99fbcb..00000000000
--- a/lisp/vms-patch.el
+++ /dev/null
@@ -1,192 +0,0 @@
-;;; vms-patch.el --- override parts of files.el for VMS.
-
-;; Copyright (C) 1986, 1992 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: vms
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;;; Functions that need redefinition
-
-;;; VMS file names are upper case, but buffer names are more
-;;; convenient in lower case.
-
-(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."
- (generate-new-buffer (downcase (file-name-nondirectory filename))))
-
-;;; Given a string FN, return a similar name which is a legal VMS filename.
-;;; This is used to avoid invalid auto save file names.
-(defun make-legal-file-name (fn)
- (setq fn (copy-sequence fn))
- (let ((dot nil) (indx 0) (len (length fn)) chr)
- (while (< indx len)
- (setq chr (aref fn indx))
- (cond
- ((eq chr ?.) (if dot (aset fn indx ?_) (setq dot t)))
- ((not (or (and (>= chr ?a) (<= chr ?z)) (and (>= chr ?A) (<= chr ?Z))
- (and (>= chr ?0) (<= chr ?9))
- (eq chr ?$) (eq chr ?_) (and (eq chr ?-) (> indx 0))))
- (aset fn indx ?_)))
- (setq indx (1+ indx))))
- fn)
-
-;;; Auto save filesnames start with _$ and end with $.
-
-(defun make-auto-save-file-name ()
- "Return file name to use for auto-saves of current buffer.
-This function does not consider `auto-save-visited-file-name';
-the caller should check that before calling this function.
-This is a separate function so that your `.emacs' file or the site's
-`site-init.el' can redefine it.
-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 "_$_" (make-legal-file-name (buffer-name)) "$"))))
-
-(defun auto-save-file-name-p (filename)
- "Return t if FILENAME can be yielded by `make-auto-save-file-name'.
-FILENAME should lack slashes.
-This is a separate function so that your `.emacs' file or the site's
-`site-init.el' can redefine it."
- (string-match "^_\\$.*\\$" filename))
-
-;;;
-;;; This goes along with kepteditor.com which defines these logicals
-;;; If EMACS_COMMAND_ARGS is defined, it supersedes EMACS_FILE_NAME,
-;;; which is probably set up incorrectly anyway.
-;;; The function command-line-again is a kludge, but it does the job.
-;;;
-(defun vms-suspend-resume-hook ()
- "When resuming suspended Emacs, check for file to be found.
-If the logical name `EMACS_FILE_NAME' is defined, `find-file' that file."
- (let ((file (vms-system-info "LOGICAL" "EMACS_FILE_NAME"))
- (args (vms-system-info "LOGICAL" "EMACS_COMMAND_ARGS"))
- (line (vms-system-info "LOGICAL" "EMACS_FILE_LINE")))
- (if (not args)
- (if file
- (progn (find-file file)
- (if line (goto-line (string-to-int line)))))
- (cd (file-name-directory file))
- (vms-command-line-again))))
-
-(setq suspend-resume-hook 'vms-suspend-resume-hook)
-
-(defun vms-suspend-hook ()
- "Don't allow suspending if logical name `DONT_SUSPEND_EMACS' is defined."
- (if (vms-system-info "LOGICAL" "DONT_SUSPEND_EMACS")
- (error "Can't suspend this emacs"))
- nil)
-
-(setq suspend-hook 'vms-suspend-hook)
-
-;;;
-;;; A kludge that allows reprocessing of the command line. This is mostly
-;;; to allow a spawned VMS mail process to do something reasonable when
-;;; used in conjunction with the modifications to sysdep.c that allow
-;;; Emacs to attach to a "foster" parent.
-;;;
-(defun vms-command-line-again ()
- "Reprocess command line arguments. VMS specific.
-Command line arguments are initialized from the logical EMACS_COMMAND_ARGS
-which is defined by kepteditor.com. On VMS this allows attaching to a
-spawned Emacs and doing things like \"emacs -l myfile.el -f doit\""
- (let* ((args (downcase (vms-system-info "LOGICAL" "EMACS_COMMAND_ARGS")))
- (command-line-args (list "emacs"))
- (beg 0)
- (end 0)
- (len (length args))
- this-char)
- (if args
- (progn
-;;; replace non-printable stuff with spaces
- (while (< beg (length args))
- (if (or (> 33 (setq this-char (aref args beg)))
- (< 127 this-char))
- (aset args beg 32))
- (setq beg (1+ beg)))
- (setq beg (1- (length args)))
- (while (= 32 (aref args beg)) (setq beg (1- beg)))
- (setq args (substring args 0 (1+ beg)))
- (setq beg 0)
-;;; now start parsing args
- (while (< beg (length args))
- (while (and (< beg (length args))
- (or (> 33 (setq this-char (aref args beg)))
- (< 127 this-char))
- (setq beg (1+ beg))))
- (setq end (1+ beg))
- (while (and (< end (length args))
- (< 32 (setq this-char (aref args end)))
- (> 127 this-char))
- (setq end (1+ end)))
- (setq command-line-args (append
- command-line-args
- (list (substring args beg end))))
- (setq beg (1+ end)))
- (command-line)))))
-
-(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)))
-
-;;;
-;;; Fuctions for using Emacs as a VMS Mail editor
-;;;
-(autoload 'vms-pmail-setup "vms-pmail"
- "Set up file assuming use by VMS Mail utility.
-The buffer is put into text-mode, auto-save is turned off and the
-following bindings are established.
-
-\\[vms-pmail-save-and-exit] vms-pmail-save-and-exit
-\\[vms-pmail-abort] vms-pmail-abort
-
-All other Emacs commands are still available."
- t)
-
-;;; vms-patch.el ends here
diff --git a/lisp/vmsproc.el b/lisp/vmsproc.el
deleted file mode 100644
index 020dcb304d0..00000000000
--- a/lisp/vmsproc.el
+++ /dev/null
@@ -1,146 +0,0 @@
-;;; vmsproc.el --- run asynchronous VMS subprocesses under Emacs
-
-;; Copyright (C) 1986 Free Software Foundation, Inc.
-
-;; Author: Mukesh Prasad
-;; Maintainer: FSF
-;; Keywords: vms
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(defvar display-subprocess-window nil
- "If non-nil, the subprocess 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")))
-
-(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))))
-
-(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)
-
-;;; vmsproc.el ends here
diff --git a/lisp/vt-control.el b/lisp/vt-control.el
deleted file mode 100644
index 23ccb957988..00000000000
--- a/lisp/vt-control.el
+++ /dev/null
@@ -1,107 +0,0 @@
-;;; vt-control.el --- Common VTxxx control functions
-
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-;; Author: Rob Riepel <riepel@networking.stanford.edu>
-;; Maintainer: Rob Riepel <riepel@networking.stanford.edu>
-;; Keywords: terminals
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The functions contained in this file send various VT control codes
-;; to the terminal where emacs is running. The following functions are
-;; available.
-
-;; Function Action
-
-;; vt-wide set wide screen (132 characters)
-;; vt-narrow set narrow screen (80 characters)
-;; vt-toggle-screen toggle wide/narrow screen
-;; vt-keypad-on set applications keypad on
-;; vt-keypad-off set applications keypad off
-;; vt-numlock toggle applications keypad on/off
-
-;;; Usage:
-
-;; To use enable these functions, simply load this file.
-
-;; Note: vt-control makes no effort to determine how the terminal is
-;; initially set. It assumes the terminal starts with a width
-;; of 80 characters and the applications keypad enabled. Nor
-;; does vt-control try to restore the terminal when emacs is
-;; killed or suspended.
-
-;;; Code:
-
-
-;;; Global variables
-
-(defvar vt-applications-keypad-p t
- "If non-nil, keypad is in applications mode.")
-
-(defvar vt-wide-p nil
- "If non-nil, the screen is 132 characters wide.")
-
-
-;;; Screen width functions.
-
-(defun vt-wide nil
- "Set the screen 132 characters wide."
- (interactive)
- (send-string-to-terminal "\e[?3h")
- (set-screen-width 132)
- (setq vt-wide-p t))
-
-(defun vt-narrow nil
- "Set the screen 80 characters wide."
- (interactive)
- (send-string-to-terminal "\e[?3l")
- (set-screen-width 80)
- (setq vt-wide-p nil))
-
-(defun vt-toggle-screen nil
- "Toggle between 80 and 132 character screen width."
- (interactive)
- (if vt-wide-p (vt-narrow) (vt-wide)))
-
-
-;;; Applications keypad functions.
-
-(defun vt-keypad-on (&optional tell)
- "Turn on the VT applications keypad."
- (interactive)
- (send-string-to-terminal "\e=")
- (setq vt-applications-keypad-p t)
- (if (or tell (interactive-p)) (message "Applications keypad enabled.")))
-
-(defun vt-keypad-off (&optional tell)
- "Turn off the VT applications keypad."
- (interactive "p")
- (send-string-to-terminal "\e>")
- (setq vt-applications-keypad-p nil)
- (if (or tell (interactive-p)) (message "Applications keypad disabled.")))
-
-(defun vt-numlock nil
- "Toggle VT application keypad on and off."
- (interactive)
- (if vt-applications-keypad-p (vt-keypad-off (interactive-p))
- (vt-keypad-on (interactive-p))))
-
-;;; vt-control.el ends here
diff --git a/lisp/vt100-led.el b/lisp/vt100-led.el
deleted file mode 100644
index 17d3e3a53e7..00000000000
--- a/lisp/vt100-led.el
+++ /dev/null
@@ -1,68 +0,0 @@
-;;; vt100-led.el --- functions for LED control on VT-100 terminals & clones.
-
-;; Copyright (C) 1988 Free Software Foundation, Inc.
-
-;; Author: Howard Gayle
-;; Maintainer: FSF
-;; Keywords: hardware
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(defvar led-state (make-vector 5 nil)
- "The internal state of the LEDs. Choices are nil, t, `flash.
-Element 0 is not used.")
-
-(defun led-flash (l)
- "Flash LED l."
- (aset led-state l 'flash)
- (led-update))
-
-(defun led-off (&optional l)
- "Turn off vt100 led number L. With no argument, turn them all off."
- (interactive "P")
- (if l
- (aset led-state (prefix-numeric-value l) nil)
- (fillarray led-state nil))
- (led-update))
-
-(defun led-on (l)
- "Turn on LED l."
- (aset led-state l t)
- (led-update))
-
-(defun led-update ()
- "Update the terminal's LEDs to reflect the internal state."
- (let ((f "\e[?0") ; String to flash.
- (o "\e[0") ; String for steady on.
- (l 1)) ; Current LED number.
- (while (/= l 5)
- (let ((s (aref led-state l)))
- (cond
- ((eq s 'flash)
- (setq f (concat f ";" (int-to-string l))))
- (s
- (setq o (concat o ";" (int-to-string l))))))
- (setq l (1+ l)))
- (setq o (concat o "q" f "t"))
- (send-string-to-terminal o)))
-
-(provide 'vt100-led)
-
-;;; vt100-led.el ends here
diff --git a/lisp/w32-fns.el b/lisp/w32-fns.el
deleted file mode 100644
index 720fbed211b..00000000000
--- a/lisp/w32-fns.el
+++ /dev/null
@@ -1,88 +0,0 @@
-;;; w32-fns.el --- Lisp routines for Windows NT.
-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-
-;; Author: Geoff Voelker (voelker@cs.washington.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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; (August 12, 1993)
-;; Created.
-
-;; (November 21, 1994)
-;; [C-M-backspace] defined.
-;; mode-line-format defined to show buffer file type.
-;; audio bell initialized.
-
-;;; Code:
-
-;; Map delete and backspace
-(define-key function-key-map [backspace] "\177")
-(define-key function-key-map [delete] "\C-d")
-(define-key function-key-map [M-backspace] [?\M-\177])
-(define-key function-key-map [C-M-backspace] [\C-\M-delete])
-
-;; Ignore case on file-name completion
-(setq completion-ignore-case t)
-
-;; The cmd.exe shell uses the "/c" switch instead of the "-c" switch
-;; for executing its command line argument (from simple.el).
-(setq shell-command-switch "/c")
-
-;; For appending suffixes to directories and files in shell completions.
-(add-hook 'shell-mode-hook
- '(lambda () (setq comint-completion-addsuffix '("\\" . " "))))
-
-;;; Avoid creating auto-save file names containing invalid characters
-;;; (primarily "*", eg. for the *mail* buffer).
-(fset 'original-make-auto-save-file-name
- (symbol-function 'make-auto-save-file-name))
-
-(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' as that variable is checked
-before calling this function. You can redefine this for customization.
-See also `auto-save-file-name-p'."
- (let ((name (original-make-auto-save-file-name))
- (start 0))
- ;; destructively replace occurences of * or ? with $
- (while (string-match "[?*]" name start)
- (aset name (match-beginning 0) ?$)
- (setq start (1+ (match-end 0))))
- name))
-
-;;; Fix interface to (X-specific) mouse.el
-(defun x-set-selection (type data)
- (or type (setq type 'PRIMARY))
- (put 'x-selections type data))
-
-(defun x-get-selection (&optional type data-type)
- (or type (setq type 'PRIMARY))
- (get 'x-selections type))
-
-(fmakunbound 'font-menu-add-default)
-(global-unset-key [C-down-mouse-1])
-(global-unset-key [C-down-mouse-2])
-(global-unset-key [C-down-mouse-3])
-
-;;; Set to a system sound if you want a fancy bell.
-(set-message-beep nil)
-
-;;; w32-fns.el ends here
diff --git a/lisp/webjump.el b/lisp/webjump.el
deleted file mode 100644
index 7812cce6fea..00000000000
--- a/lisp/webjump.el
+++ /dev/null
@@ -1,427 +0,0 @@
-;;; webjump.el --- programmable Web hotlist
-
-;; Copyright (C) 1996 Free Software Foundation
-
-;; Author: Neil W. Van Dyke <nwv@acm.org>
-;; Created: Fri 09 Aug 1996
-;; Keywords: comm www
-;; X-URL: http://www.cs.brown.edu/people/nwv/
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; WebJump provides a sort of ``programmable hotlist'' of Web sites that can
-;; quickly be invoked in your Web browser. Each Web site in the hotlist has a
-;; name, and you select the desired site name via a completing string prompt in
-;; the minibuffer. The URL for each Web site is defined as a static string or
-;; a built-in or custom function, allowing interactive prompting for
-;; site-specific queries and options.
-
-;; Note that WebJump was originally intended to complement your conventional
-;; browser-based hotlist, not replace it. (Though there's no reason you
-;; couldn't use WebJump for your entire hotlist if you were so inclined.)
-
-;; The `webjump-sites' variable, which defines the hotlist, defaults to some
-;; example sites. You'll probably want to override it with your own favorite
-;; sites. The documentation for the variable describes the syntax.
-
-;; You may wish to add something like the following to your `.emacs' file:
-;;
-;; (load "webjump")
-;; (global-set-key "\C-cj" 'webjump)
-;; (setq webjump-sites
-;; (append '(
-;; ("My Home Page" . "www.someisp.net/users/joebobjr/")
-;; ("Pop's Site" . "www.joebob-and-son.com/")
-;; )
-;; webjump-sample-sites))
-;;
-;; The above loads this package, binds `C-c j' to invoke WebJump, and adds
-;; your personal favorite sites to the hotlist.
-
-;; The `webjump-sample-sites' constant mostly contains sites that are expected
-;; to be generally useful to Emacs users or that have some sort of query which
-;; can be coded in WebJump. There are two main goals of this sample site list:
-;; (1) demonstrate WebJump capabilities and usage; (2) provide definitions for
-;; many popular sites so that people don't have to reinvent the wheel. A few
-;; assorted other sites have been thrown in on a whim. No commercial sites are
-;; included unless they provide a free, generally-useful service. Inclusion of
-;; a site does not represent an endorsement. Please contact the maintainer
-;; with change requests.
-
-;; The `browse-url' package is used to submit URLs to the browser, so any
-;; browser-specific configuration should be done there.
-
-;; WebJump inherits a small amount code from my `altavista.el' package, and is
-;; intended to obsolete that package.
-
-;;; Code:
-
-;;-------------------------------------------------------- Package Dependencies
-
-(require 'browse-url)
-
-;;------------------------------------------------------------------- Constants
-
-(defvar webjump-sample-sites
- '(("AltaVista" .
- [simple-query
- "www.altavista.digital.com"
- "www.altavista.digital.com/cgi-bin/query?pg=aq&what=web&fmt=.&q="
- "&r=&d0=&d1="])
- ("Archie" .
- [simple-query "http://hoohoo.ncsa.uiuc.edu/cgi-bin/AA.pl"
- "http://hoohoo.ncsa.uiuc.edu/cgi-bin/AA.pl?query=" ""])
- ("Bastard Operator from Hell" . "www.replay.com/bofh/")
- ("Brown University" .
- [simple-query "www.brown.edu" "www.brown.edu/cgi-local/bsearch?" ""])
- ("Computer Professionals for Social Responsibility" . "www.cpsr.org/dox/")
- ("Digital Espresso" .
- [simple-query "www.io.org/~mentor/DigitalEspresso.html"
- "www.jars.com/cgi-bin/aglimpse/01?query="
- "&case=on&whole=on&errors=0&maxfiles=100&maxlines=30"])
- ("Dilbert" . "www.unitedmedia.com/comics/dilbert/")
- ("Electronic Frontier Foundation" . "www.eff.org")
- ("Emacs Lisp Archive" .
- "ftp://archive.cis.ohio-state.edu/pub/gnu/emacs/elisp-archive/")
- ("Free Software Foundation" . "www.fsf.org")
- ("GNU FTP Archive". [mirrors
- "ftp://prep.ai.mit.edu/pub/gnu/"
- ;; ASIA:
- "ftp://ftp.cs.titech.ac.jp"
- "ftp://tron.um.u-tokyo.ac.jp/pub/GNU/prep"
- "ftp://cair-archive.kaist.ac.kr/pub/gnu"
- "ftp://ftp.nectec.or.th/pub/mirrors/gnu"
- ;; AUSTRALIA:
- "ftp://archie.au/gnu"
- "ftp://archie.oz/gnu"
- "ftp://archie.oz.au/gnu"
- ;; AFRICA:
- "ftp://ftp.sun.ac.za/pub/gnu"
- ;; MIDDLE-EAST:
- "ftp://ftp.technion.ac.il/pub/unsupported/gnu"
- ;; EUROPE:
- "ftp://irisa.irisa.fr/pub/gnu"
- "ftp://ftp.univ-lyon1.fr/pub/gnu"
- "ftp://ftp.mcc.ac.uk"
- "ftp://unix.hensa.ac.uk/mirrors/uunet/systems/gnu"
- "ftp://src.doc.ic.ac.uk/gnu"
- "ftp://ftp.ieunet.ie/pub/gnu"
- "ftp://ftp.eunet.ch"
- "ftp://nic.switch.ch/mirror/gnu"
- "ftp://ftp.informatik.rwth-aachen.de/pub/gnu"
- "ftp://ftp.informatik.tu-muenchen.de"
- "ftp://ftp.win.tue.nl/pub/gnu"
- "ftp://ftp.nl.net"
- "ftp://ftp.etsimo.uniovi.es/pub/gnu"
- "ftp://ftp.funet.fi/pub/gnu"
- "ftp://ftp.denet.dk"
- "ftp://ftp.stacken.kth.se"
- "ftp://isy.liu.se"
- "ftp://ftp.luth.se/pub/unix/gnu"
- "ftp://ftp.sunet.se/pub/gnu"
- "ftp://archive.eu.net"
- ;; SOUTH AMERICA:
- "ftp://ftp.inf.utfsm.cl/pub/gnu"
- "ftp://ftp.unicamp.br/pub/gnu"
- ;; WESTERN CANADA:
- "ftp://ftp.cs.ubc.ca/mirror2/gnu"
- ;; USA:
- "ftp://wuarchive.wustl.edu/systems/gnu"
- "ftp://labrea.stanford.edu"
- "ftp://ftp.digex.net/pub/gnu"
- "ftp://ftp.kpc.com/pub/mirror/gnu"
- "ftp://f.ms.uky.edu/pub3/gnu"
- "ftp://jaguar.utah.edu/gnustuff"
- "ftp://ftp.hawaii.edu/mirrors/gnu"
- "ftp://uiarchive.cso.uiuc.edu/pub/gnu"
- "ftp://ftp.cs.columbia.edu/archives/gnu/prep"
- "ftp://gatekeeper.dec.com/pub/GNU"
- "ftp://ftp.uu.net/systems/gnu"
- ])
- ("Insidious Big Brother Database" . "home.netscape.com/people/jwz/bbdb/")
- ("Interactive Weather Information Network" . webjump-to-iwin)
- ("Java API" . webjump-to-javaapi)
- ("Lycos" .
- [simple-query "www.lycos.com" "www.lycos.com/cgi-bin/pursuit?query=" ""])
- ("Mailcrypt" . "cag-www.lcs.mit.edu/mailcrypt/")
- ("Pretty Good Privacy" . "web.mit.edu/network/pgp.html")
- ("Playboy" . (if (webjump-adult-p) "www.playboy.com" "www.whitehouse.gov"))
- ("Usenet FAQs" .
- [simple-query "www.cis.ohio-state.edu/hypertext/faq/usenet/FAQ-List.html"
- "www.cis.ohio-state.edu/htbin/search-usenet-faqs/form?find="
- ""])
- ("Risks Digest" . webjump-to-risks)
- ("RTFM Usenet FAQs by Group" .
- "ftp://rtfm.mit.edu/pub/usenet-by-group/")
- ("RTFM Usenet FAQs by Hierachy" .
- "ftp://rtfm.mit.edu/pub/usenet-by-hierarchy/")
- ("Webster" .
- [simple-query "c.gp.cs.cmu.edu:5103/prog/webster"
- "gs213.sp.cs.cmu.edu/prog/webster?" ""])
- ("X Consortium Archive". "ftp.x.org")
- ("Yahoo" .
- [simple-query "www.yahoo.com" "search.yahoo.com/bin/search?p=" ""])
- ("Yahoo Emacs" .
- "www.yahoo.com/Computers_and_Internet/Software/Editors/Emacs/")
- ("Yahoo Reference" "www.yahoo.com/Reference/")
- )
- "Sample hotlist for WebJump.")
-
-(defvar webjump-state-to-postal-alist
- '(("Alabama" . "al") ("Alaska" . "ak") ("Arizona" . "az") ("Arkansas" . "ar")
- ("California" . "ca") ("Colorado" . "co") ("Connecticut" . "ct")
- ("Delaware" . "de") ("Florida" . "fl") ("Georgia" . "ga") ("Hawaii" . "hi")
- ("Idaho" . "id") ("Illinois" . "il") ("Indiana" . "in") ("Iowa" . "ia")
- ("Kansas" . "ks") ("Kentucky" . "ky") ("Louisiana" . "la") ("Maine" . "me")
- ("Maryland" . "md") ("Massachusetts" . "ma") ("Michigan" . "mi")
- ("Minnesota" . "mn") ("Mississippi" . "ms") ("Missouri" . "mo")
- ("Montana" . "mt") ("Nebraska" . "ne") ("Nevada" . "nv")
- ("New Hampshire" . "nh") ("New Jersey" . "nj") ("New Mexico" . "nm")
- ("New York" . "ny") ("North Carolina" . "nc") ("North Dakota" . "nd")
- ("Ohio" . "oh") ("Oklahoma" . "ok") ("Oregon" . "or")
- ("Pennsylvania" . "pa") ("Rhode Island" . "ri") ("South Carolina" . "sc")
- ("South Dakota" . "sd") ("Tennessee" . "tn") ("Texas" . "tx")
- ("Utah" . "ut") ("Vermont" . "vt") ("Virginia" . "va")
- ("Washington" . "wa") ("West Virginia" . "wv") ("Wisconsin" . "wi")
- ("Wyoming" . "wy")))
-
-;;------------------------------------------------------------ Option Variables
-
-(defvar webjump-sites
- webjump-sample-sites
- "*Hotlist for WebJump.
-
-The hotlist is represented as an association list, with the CAR of each cell
-being the name of the Web site, and the CDR being the definition for the URL of
-that site. The URL definition can be a string (the URL), a vector (specifying
-a special \"builtin\" which returns a URL), a symbol (name of a function which
-returns a URL), or a list (which when `eval'ed yields a URL).
-
-If the URL definition is a vector, then a \"builtin\" is used. A builtin has a
-Lisp-like syntax, with the name as the first element of the vector, and any
-arguments as the following elements. The three current builtins are `name',
-which returns the name of the site as the URL, `simple-query', which
-returns a URL that is a function of a query entered by the user, and `mirrors',
-which allows the user to select from among multiple mirror sites for the same
-content.
-
-The first argument to the `simple-query' builtin is a static URL to use if the
-user enters a blank query. The second and third arguments are the prefix and
-suffix, respectively, to add to the encoded query the user enters. This
-builtin covers Web sites that have single-string searches with the query
-embedded in the URL.
-
-The arguments to the `mirrors' builtin are URLs of mirror sites.
-
-If the symbol of a function is given, then the function will be called with the
-Web site name (the one you specified in the CAR of the alist cell) as a
-parameter. This might come in handy for various kludges.
-
-For convenience, if the `http://', `ftp://', or `file://' prefix is missing
-from a URL, WebJump will make a guess at what you wanted and prepend it before
-submitting the URL.")
-
-;;------------------------------------------------------- Sample Site Functions
-
-(defun webjump-to-iwin (name)
- (let ((prefix "http://iwin.nws.noaa.gov/")
- (state (webjump-read-choice name "state"
- (append '(("Puerto Rico" . "pr"))
- webjump-state-to-postal-alist))))
- (if state
- (concat prefix "iwin/" state "/"
- (webjump-read-choice name "option"
- '(("Hourly Report" . "hourly")
- ("State Forecast" . "state")
- ("Local Forecast" . "local")
- ("Zone Forecast" . "zone")
- ("Short-Term Forecast" . "shortterm")
- ("Weather Summary" . "summary")
- ("Public Information" . "public")
- ("Climatic Data" . "climate")
- ("Aviation Products" . "aviation")
- ("Hydro Products" . "hydro")
- ("Special Weather" . "special")
- ("Watches and Warnings" . "warnings"))
- "zone")
- ".html")
- prefix)))
-
-(defun webjump-to-javaapi (name)
- (let* ((prefix "http://www.javasoft.com/products/JDK/CurrentRelease/api/")
- (packages '(("java.applet") ("java.awt") ("java.awt.image")
- ("java.awt.peer") ("java.io") ("java.lang") ("java.net")
- ("java.util") ("sun.tools.debug")))
- (completion-ignore-case t)
- (package (completing-read (concat name " package: ") packages nil t)))
- (if (webjump-null-or-blank-string-p package)
- (concat prefix "packages.html")
- (concat prefix "Package-" package ".html"))))
-
-(defun webjump-to-risks (name)
- (let (issue volume)
- (if (and (setq volume (webjump-read-number (concat name " volume")))
- (setq issue (webjump-read-number (concat name " issue"))))
- (format "catless.ncl.ac.uk/Risks/%d.%02d.html" volume issue)
- "catless.ncl.ac.uk/Risks/")))
-
-;;-------------------------------------------------------------- Core Functions
-
-;;;###autoload
-(defun webjump ()
- "Jumps to a Web site from a programmable hotlist.
-
-See the documentation for the `webjump-sites' variable for how to customize the
-hotlist.
-
-Feedback on WebJump can be sent to the author, Neil W. Van Dyke <nwv@acm.org>,
-or submitted via `\\[webjump-submit-bug-report]'. The latest version can be
-gotten from `http://www.cs.brown.edu/people/nwv/'."
- (interactive)
- (let* ((completion-ignore-case t)
- (item (assoc (completing-read "WebJump to site: " webjump-sites nil t)
- webjump-sites))
- (name (car item))
- (expr (cdr item)))
- (funcall browse-url-browser-function
- (webjump-url-fix
- (cond ((not expr) "")
- ((stringp expr) expr)
- ((vectorp expr) (webjump-builtin expr name))
- ((listp expr) (eval expr))
- ((symbolp expr)
- (if (fboundp expr)
- (funcall expr name)
- (error "WebJump URL function \"%s\" undefined." expr)))
- (t (error "WebJump URL expression for \"%s\" invalid."
- name)))))))
-
-(defun webjump-adult-p ()
- (and (boundp 'age) (integerp age) (>= age 21)))
-
-(defun webjump-builtin (expr name)
- (if (< (length expr) 1)
- (error "WebJump URL builtin for \"%s\" empty." name))
- (let ((builtin (aref expr 0)))
- (cond
- ((eq builtin 'mirrors)
- (if (= (length expr) 1)
- (error
- "WebJump URL builtin \"mirrors\" for \"%s\" needs at least 1 arg."))
- (webjump-choose-mirror name (cdr (append expr nil))))
- ((eq builtin 'name)
- name)
- ((eq builtin 'simple-query)
- (webjump-builtin-check-args expr name 3)
- (webjump-do-simple-query name (aref expr 1) (aref expr 2) (aref expr 3)))
- (t (error "WebJump URL builtin \"%s\" for \"%s\" invalid."
- builtin name)))))
-
-(defun webjump-builtin-check-args (expr name count)
- (or (= (length expr) (1+ count))
- (error "WebJump URL builtin \"%s\" for \"%s\" needs %d args."
- (aref expr 0) name count)))
-
-(defun webjump-choose-mirror (name urls)
- (webjump-read-url-choice (concat name " mirror")
- urls
- (webjump-mirror-default urls)))
-
-(defun webjump-do-simple-query (name noquery-url query-prefix query-suffix)
- (let ((query (webjump-read-string (concat name " query"))))
- (if query
- (concat query-prefix (webjump-url-encode query) query-suffix)
- noquery-url)))
-
-(defun webjump-mirror-default (urls)
- ;; Note: This should be modified to apply some simple kludges/heuristics to
- ;; pick a site which is likely "close". As a tie-breaker among candidates
- ;; judged equally desirable, randomness should be used.
- (car urls))
-
-(defun webjump-read-choice (name what choices &optional default)
- (let* ((completion-ignore-case t)
- (choice (completing-read (concat name " " what ": ") choices nil t)))
- (if (webjump-null-or-blank-string-p choice)
- default
- (cdr (assoc choice choices)))))
-
-(defun webjump-read-number (prompt)
- ;; Note: I should make this more robust someday.
- (let ((input (webjump-read-string prompt)))
- (if input (string-to-number input))))
-
-(defun webjump-read-string (prompt)
- (let ((input (read-string (concat prompt ": "))))
- (if (webjump-null-or-blank-string-p input) nil input)))
-
-(defun webjump-read-url-choice (what urls &optional default)
- ;; Note: Convert this to use `webjump-read-choice' someday.
- (let* ((completions (mapcar (function (lambda (n) (cons n n)))
- urls))
- (input (completing-read (concat what
- ;;(if default " (RET for default)" "")
- ": ")
- completions
- nil
- t)))
- (if (webjump-null-or-blank-string-p input)
- default
- (car (assoc input completions)))))
-
-(defun webjump-null-or-blank-string-p (str)
- (or (null str) (string-match "^[ \t]*$" str)))
-
-(defun webjump-url-encode (str)
- (mapconcat '(lambda (c)
- (cond ((= c 32) "+")
- ((or (and (>= c ?a) (<= c ?z))
- (and (>= c ?A) (<= c ?Z))
- (and (>= c ?0) (<= c ?9)))
- (char-to-string c))
- (t (upcase (format "%%%02x" c)))))
- str
- ""))
-
-(defun webjump-url-fix (url)
- (if (webjump-null-or-blank-string-p url)
- ""
- (webjump-url-fix-trailing-slash
- (cond
- ((string-match "^[a-zA-Z]+:" url) url)
- ((string-match "^/" url) (concat "file://" url))
- ((string-match "^\\([^\\./]+\\)" url)
- (concat (if (string= (downcase (match-string 1 url)) "ftp")
- "ftp"
- "http")
- "://"
- url))
- (t url)))))
-
-(defun webjump-url-fix-trailing-slash (url)
- (if (string-match "^[a-zA-Z]+://[^/]+$" url)
- (concat url "/")
- url))
-
-;;-----------------------------------------------------------------------------
-
-(provide 'webjump)
-
-;; webjump.el ends here
diff --git a/lisp/window.el b/lisp/window.el
deleted file mode 100644
index 0b55ccbe9a3..00000000000
--- a/lisp/window.el
+++ /dev/null
@@ -1,298 +0,0 @@
-;;; window.el --- GNU Emacs window commands aside from those written in C.
-
-;; Copyright (C) 1985, 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-;;;; Window tree functions.
-
-(defun one-window-p (&optional nomini all-frames)
- "Returns non-nil if the selected window is the only window (in its frame).
-Optional arg NOMINI non-nil means don't count the minibuffer
-even if it is active.
-
-The optional arg ALL-FRAMES t means count windows on all frames.
-If it is `visible', count windows on all visible frames.
-ALL-FRAMES nil or omitted means count only the selected frame,
-plus the minibuffer it uses (which may be on another frame).
-If ALL-FRAMES is neither nil nor t, count only the selected frame."
- (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) all-frames))))
-
-(defun walk-windows (proc &optional minibuf all-frames)
- "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. MINIBUF nil or omitted means count the minibuffer iff
-it is active. MINIBUF neither t nor nil means not to count the
-minibuffer even if it is active.
-
-Several frames may share a single minibuffer; if the minibuffer
-counts, all windows on all frames that share that minibuffer count
-too. Therefore, if you are using a separate minibuffer frame
-and the minibuffer is active and MINIBUF says it counts,
-`walk-windows' includes the windows in the frame from which you
-entered the minibuffer, as well as the minibuffer window.
-
-ALL-FRAMES is the optional third argument.
-ALL-FRAMES nil or omitted means cycle within the frames as specified above.
-ALL-FRAMES = `visible' means include windows on all visible frames.
-ALL-FRAMES = 0 means include windows on all visible and iconified frames.
-ALL-FRAMES = t means include windows on all frames including invisible frames.
-Anything else means restrict to the selected frame."
- ;; If we start from the minibuffer window, don't fail to come back to it.
- (if (window-minibuffer-p (selected-window))
- (setq minibuf t))
- (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-frames))
- (funcall proc walk-windows-current)
- (not (eq walk-windows-current walk-windows-start))))))
-
-(defun minibuffer-window-active-p (window)
- "Return t if WINDOW (a minibuffer window) is now active."
- (eq window (active-minibuffer-window)))
-
-(defmacro save-selected-window (&rest body)
- "Execute BODY, then select the window that was selected before BODY."
- (list 'let
- '((save-selected-window-window (selected-window)))
- (list 'unwind-protect
- (cons 'progn body)
- (list 'select-window 'save-selected-window-window))))
-
-(defun count-windows (&optional minibuf)
- "Returns the number of visible windows.
-Optional arg MINIBUF non-nil means count the minibuffer
-even if it is inactive."
- (let ((count 0))
- (walk-windows (function (lambda (w)
- (setq count (+ count 1))))
- minibuf)
- count))
-
-(defun balance-windows ()
- "Makes all visible windows the same height (approximately)."
- (interactive)
- (let ((count -1) levels newsizes size
- ;; Don't count the lines that are above the uppermost windows.
- ;; (These are the menu bar lines, if any.)
- (mbl (nth 1 (window-edges (frame-first-window (selected-frame))))))
- ;; Find all the different vpos's at which windows start,
- ;; then count them. But ignore levels that differ by only 1.
- (save-window-excursion
- (let (tops (prev-top -2))
- (walk-windows (function (lambda (w)
- (setq tops (cons (nth 1 (window-edges w))
- tops))))
- 'nomini)
- (setq tops (sort tops '<))
- (while tops
- (if (> (car tops) (1+ prev-top))
- (setq prev-top (car tops)
- count (1+ count)))
- (setq levels (cons (cons (car tops) count) levels))
- (setq tops (cdr tops)))
- (setq count (1+ count))))
- ;; Subdivide the frame into that many vertical levels.
- (setq size (/ (- (frame-height) mbl) count))
- (walk-windows (function
- (lambda (w)
- (select-window w)
- (let ((newtop (cdr (assq (nth 1 (window-edges))
- levels)))
- (newbot (or (cdr (assq (+ (window-height)
- (nth 1 (window-edges)))
- levels))
- count)))
- (setq newsizes
- (cons (cons w (* size (- newbot newtop)))
- newsizes)))))
- 'nomini)
- (walk-windows (function (lambda (w)
- (select-window w)
- (let ((newsize (cdr (assq w newsizes))))
- (enlarge-window (- newsize
- (window-height))))))
- 'nomini)))
-
-;;; I think this should be the default; I think people will prefer it--rms.
-(defvar split-window-keep-point t
- "*If non-nil, split windows keeps the original point in both children.
-This is often more convenient for editing.
-If nil, adjust point in each of the two windows to minimize redisplay.
-This is convenient on slow terminals, but point can move strangely.")
-
-(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.
-Negative arg means select the size of the lowermost window instead.
-With no argument, split equally or close to it.
-Both windows display the same buffer now current.
-
-If the variable split-window-keep-point is non-nil, both new windows
-will get the same value of point as the current window. This is often
-more convenient for editing.
-
-Otherwise, we chose window starts so as to minimize the amount of
-redisplay; this is convenient on slow terminals. 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."
- (interactive "P")
- (let ((old-w (selected-window))
- (old-point (point))
- (size (and arg (prefix-numeric-value arg)))
- (window-full-p nil)
- new-w bottom switch moved)
- (and size (< size 0) (setq size (+ (window-height) size)))
- (setq new-w (split-window nil size))
- (or split-window-keep-point
- (progn
- (save-excursion
- (set-buffer (window-buffer))
- (goto-char (window-start))
- (setq moved (vertical-motion (window-height)))
- (set-window-start new-w (point))
- (if (> (point) (window-point new-w))
- (set-window-point new-w (point)))
- (and (= moved (window-height))
- (progn
- (setq window-full-p t)
- (vertical-motion -1)))
- (setq bottom (point)))
- (and window-full-p
- (<= bottom (point))
- (set-window-point old-w (1- bottom)))
- (and window-full-p
- (<= (window-start new-w) old-point)
- (progn
- (set-window-point new-w old-point)
- (select-window new-w)))))
- new-w))
-
-(defun split-window-horizontally (&optional arg)
- "Split current window into two windows side by side.
-This window becomes the leftmost of the two, and gets ARG columns.
-Negative arg means select the size of the rightmost window instead.
-No arg means split equally."
- (interactive "P")
- (let ((size (and arg (prefix-numeric-value arg))))
- (and size (< size 0)
- (setq size (+ (window-width) size)))
- (split-window nil size t)))
-
-(defun enlarge-window-horizontally (arg)
- "Make current window ARG columns wider."
- (interactive "p")
- (enlarge-window arg t))
-
-(defun shrink-window-horizontally (arg)
- "Make current window ARG columns narrower."
- (interactive "p")
- (shrink-window arg t))
-
-(defun shrink-window-if-larger-than-buffer (&optional window)
- "Shrink the WINDOW to be as small as possible to display its contents.
-Do not shrink to less than `window-min-height' lines.
-Do nothing if the buffer contains more lines than the present window height,
-or if some of the window's contents are scrolled out of view,
-or if the window is not the full width of the frame,
-or if the window is the only window of its frame."
- (interactive)
- (or window (setq window (selected-window)))
- (save-excursion
- (set-buffer (window-buffer window))
- (let* ((w (selected-window)) ;save-window-excursion can't win
- (buffer-file-name buffer-file-name)
- (p (point))
- (n 0)
- (ignore-final-newline
- ;; If buffer ends with a newline, ignore it when counting height
- ;; unless point is after it.
- (and (not (eobp))
- (eq ?\n (char-after (1- (point-max))))))
- (buffer-read-only nil)
- (modified (buffer-modified-p))
- (buffer (current-buffer))
- (params (frame-parameters (window-frame window)))
- (mini (cdr (assq 'minibuffer params)))
- (edges (window-edges (selected-window))))
- (if (and (< 1 (let ((frame (selected-frame)))
- (select-frame (window-frame window))
- (unwind-protect
- (count-windows)
- (select-frame frame))))
- (= (window-width window) (frame-width (window-frame window)))
- (pos-visible-in-window-p (point-min) window)
- (not (eq mini 'only))
- (or (not mini)
- (< (nth 3 edges)
- (nth 1 (window-edges mini)))
- (> (nth 1 edges)
- (cdr (assq 'menu-bar-lines params)))))
- (unwind-protect
- (progn
- (select-window (or window w))
- (goto-char (point-min))
- (while (pos-visible-in-window-p
- (- (point-max)
- (if ignore-final-newline 1 0)))
- ;; defeat file locking... don't try this at home, kids!
- (setq buffer-file-name nil)
- (insert ?\n) (setq n (1+ n)))
- (if (> n 0)
- (shrink-window (min (1- n)
- (- (window-height)
- window-min-height)))))
- (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))))))
-
-(defun kill-buffer-and-window ()
- "Kill the current buffer and delete the selected window."
- (interactive)
- (if (yes-or-no-p (format "Kill buffer `%s'? " (buffer-name)))
- (let ((buffer (current-buffer)))
- (delete-window (selected-window))
- (kill-buffer buffer))
- (error "Aborted")))
-
-(define-key ctl-x-map "2" 'split-window-vertically)
-(define-key ctl-x-map "3" 'split-window-horizontally)
-(define-key ctl-x-map "}" 'enlarge-window-horizontally)
-(define-key ctl-x-map "{" 'shrink-window-horizontally)
-(define-key ctl-x-map "-" 'shrink-window-if-larger-than-buffer)
-(define-key ctl-x-map "+" 'balance-windows)
-(define-key ctl-x-4-map "0" 'kill-buffer-and-window)
-
-;;; windows.el ends here
diff --git a/lisp/x-apollo.el b/lisp/x-apollo.el
deleted file mode 100644
index e86b7f2eee0..00000000000
--- a/lisp/x-apollo.el
+++ /dev/null
@@ -1,90 +0,0 @@
-;;; x-apollo.el --- Apollo support functions
-
-;; Copyright (C) 1995 Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(defun apollo-kill-entire-line ()
- "Kill the entire line containing point."
- (interactive)
- (beginning-of-line)
- (kill-line 1))
-
-(defun apollo-scroll-window-right ()
- "Scroll window to right ten columns."
- (interactive)
- (scroll-left 10))
-
-(defun apollo-scroll-window-left ()
- "Scroll window to left ten columns."
- (interactive)
- (scroll-right 10))
-
-(defun apollo-scroll-window-forward-line ()
- "Move window forward one line leaving cursor at position in window."
- (interactive)
- (scroll-up 1))
-
-(defun apollo-scroll-window-backward-line ()
- "Move window backward one line leaving cursor at position in window."
- (interactive)
- (scroll-down 1))
-
-;;; Define and Enable the Function Key Bindings.
-
-(global-set-key [S-tab] "\C-i") ;Shift TAB
-(global-set-key [C-tab] "\C-i") ;Control TAB
-(global-set-key [S-return] "\C-m") ;Shift RET
-(global-set-key [C-return] "\C-m") ;Control RET
-(global-set-key [linedel] 'apollo-kill-entire-line) ;LINE DEL
-(global-set-key [chardel] 'delete-char) ;CHAR DEL
-(global-set-key [leftbar] 'beginning-of-line) ;LEFT BAR ARROW
-(global-set-key [rightbar] 'end-of-line) ;RIGHT BAR ARROW
-(global-set-key [leftbox] 'apollo-scroll-window-left) ;LEFT BOX ARROW
-(global-set-key [rightbox] 'apollo-scroll-window-right) ;RIGHT BOX ARROW
-(global-set-key [S-up] 'apollo-scroll-window-backward-line) ;Shift UP ARROW
-(global-set-key [S-down] 'apollo-scroll-window-forward-line) ;Shift DOWN ARROW
-(global-set-key [select] 'set-mark-command) ;MARK
-(global-set-key [S-insert] 'overwrite-mode) ;INS MODE
-(global-set-key [S-linedel] 'yank) ;Shift LINE DEL
-(global-set-key [S-chardel] 'delete-char) ;Shift CHAR DEL
-(global-set-key [copy] 'copy-region-as-kill) ;COPY
-(global-set-key [S-cut] 'kill-region) ;CUT
-(global-set-key [paste] 'yank) ;PASTE
-(global-set-key [S-undo] 'undo) ;UNDO
-(global-set-key [S-left] 'backward-word) ;Shift LEFT ARROW
-(global-set-key [S-right] 'forward-word) ;Shift RIGHT ARROW
-(global-set-key [upbox] 'scroll-down) ;UP BOX ARROW
-(global-set-key [S-upbox] 'beginning-of-buffer) ;Shift UP BOX ARROW
-(global-set-key [downbox] 'scroll-up) ;DOWN BOX ARROW
-(global-set-key [S-downbox] 'end-of-buffer) ;Shift DOWN BOX ARROW
-(global-set-key [S-redo] 'toggle-read-only) ;Shift AGAIN
-(global-set-key [exit] 'save-buffer) ;EXIT
-(global-set-key [S-cancel] 'kill-buffer) ;ABORT
-(global-set-key [S-save] 'save-buffer) ;SAVE
-(global-set-key [S-leftbar] 'beginning-of-buffer) ;Shift LEFT BAR ARROW
-(global-set-key [cmd] 'execute-extended-command) ;CMD
-(global-set-key [S-rightbar] 'end-of-buffer) ;Shift RIGHT BAR ARROW
-(global-set-key [next] 'other-window) ;NEXT WNDW
-(global-set-key [S-next] 'delete-window) ;Shift NEXT WNDW
-(global-set-key [read] 'find-file-read-only) ;READ
-(global-set-key [edit] 'find-file) ;EDIT
-(global-set-key [S-shell] 'shell) ;SHELL
-(global-set-key [S-help] 'manual-entry) ;HELP
diff --git a/lisp/x-menu.el b/lisp/x-menu.el
deleted file mode 100644
index 4863ceec9ac..00000000000
--- a/lisp/x-menu.el
+++ /dev/null
@@ -1,145 +0,0 @@
-;;; x-menu.el --- menu support for X
-
-;; 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 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Code:
-
-(defun x-menu-mode ()
- "Major mode for creating permanent menus for use with X.
-These menus are implemented entirely in Lisp; popup menus, implemented
-with x-popup-menu, are implemented using XMenu primitives."
- (make-local-variable 'x-menu-items-per-line)
- (make-local-variable 'x-menu-item-width)
- (make-local-variable 'x-menu-items-alist)
- (make-local-variable 'x-process-mouse-hook)
- (make-local-variable 'x-menu-assoc-buffer)
- (setq buffer-read-only t)
- (setq truncate-lines t)
- (setq x-process-mouse-hook 'x-menu-pick-entry)
- (setq mode-line-buffer-identification '("MENU: %32b")))
-
-(defvar x-menu-max-width 0)
-(defvar x-menu-items-per-line 0)
-(defvar x-menu-item-width 0)
-(defvar x-menu-items-alist nil)
-(defvar x-menu-assoc-buffer nil)
-
-(defvar x-menu-item-spacing 1
- "*Minimum horizontal spacing between objects in a permanent X menu.")
-
-(defun x-menu-create-menu (name)
- "Create a permanent X menu.
-Returns an item which should be used as a
-menu object whenever referring to the menu."
- (let ((old (current-buffer))
- (buf (get-buffer-create name)))
- (set-buffer buf)
- (x-menu-mode)
- (setq x-menu-assoc-buffer old)
- (set-buffer old)
- buf))
-
-(defun x-menu-change-associated-buffer (menu buffer)
- "Change associated buffer of MENU to BUFFER.
-BUFFER should be a buffer object."
- (let ((old (current-buffer)))
- (set-buffer menu)
- (setq x-menu-assoc-buffer buffer)
- (set-buffer old)))
-
-(defun x-menu-add-item (menu item binding)
- "Add to MENU an item with name ITEM, associated with BINDING.
-Following a sequence of calls to x-menu-add-item, a call to x-menu-compute
-should be performed before the menu will be made available to the user.
-
-BINDING should be a function of one argument, which is the numerical
-button/key code as defined in x-menu.el."
- (let ((old (current-buffer))
- elt)
- (set-buffer menu)
- (if (setq elt (assoc item x-menu-items-alist))
- (rplacd elt binding)
- (setq x-menu-items-alist (append x-menu-items-alist
- (list (cons item binding)))))
- (set-buffer old)
- item))
-
-(defun x-menu-delete-item (menu item)
- "Delete from MENU the item named ITEM.
-Call `x-menu-compute' before making the menu available to the user."
- (let ((old (current-buffer))
- elt)
- (set-buffer menu)
- (if (setq elt (assoc item x-menu-items-alist))
- (rplaca elt nil))
- (set-buffer old)
- item))
-
-(defun x-menu-activate (menu)
- "Compute all necessary parameters for MENU.
-This must be called whenever a menu is modified before it is made
-available to the user. This also creates the menu itself."
- (let ((buf (current-buffer)))
- (pop-to-buffer menu)
- (let (buffer-read-only)
- (setq x-menu-max-width (1- (frame-width)))
- (setq x-menu-item-width 0)
- (let (items-head
- (items-tail x-menu-items-alist))
- (while items-tail
- (if (car (car items-tail))
- (progn (setq items-head (cons (car items-tail) items-head))
- (setq x-menu-item-width
- (max x-menu-item-width
- (length (car (car items-tail)))))))
- (setq items-tail (cdr items-tail)))
- (setq x-menu-items-alist (reverse items-head)))
- (setq x-menu-item-width (+ x-menu-item-spacing x-menu-item-width))
- (setq x-menu-items-per-line
- (max 1 (/ x-menu-max-width x-menu-item-width)))
- (erase-buffer)
- (let ((items-head x-menu-items-alist))
- (while items-head
- (let ((items 0))
- (while (and items-head
- (<= (setq items (1+ items)) x-menu-items-per-line))
- (insert (format (concat "%"
- (int-to-string x-menu-item-width) "s")
- (car (car items-head))))
- (setq items-head (cdr items-head))))
- (insert ?\n)))
- (shrink-window (max 0
- (- (window-height)
- (1+ (count-lines (point-min) (point-max))))))
- (goto-char (point-min)))
- (pop-to-buffer buf)))
-
-(defun x-menu-pick-entry (position event)
- "Internal function for dispatching on mouse/menu events"
- (let* ((x (min (1- x-menu-items-per-line)
- (/ (current-column) x-menu-item-width)))
- (y (- (count-lines (point-min) (point))
- (if (zerop (current-column)) 0 1)))
- (item (+ x (* y x-menu-items-per-line)))
- (litem (cdr (nth item x-menu-items-alist))))
- (and litem (funcall litem event)))
- (pop-to-buffer x-menu-assoc-buffer))
-
-;;; x-menu.el ends here
diff --git a/lisp/xscheme.el b/lisp/xscheme.el
deleted file mode 100644
index 05792774684..00000000000
--- a/lisp/xscheme.el
+++ /dev/null
@@ -1,878 +0,0 @@
-;;; xscheme.el --- run Scheme under Emacs
-
-;; Copyright (C) 1986, 1987, 1989, 1990 Free Software Foundation, Inc.
-
-;; Maintainer: FSF
-;; Keywords: languages, lisp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; A major mode for editing Scheme and interacting with MIT's C-Scheme.
-;;
-;; Requires C-Scheme release 5 or later
-;; Changes to Control-G handler require runtime version 13.85 or later
-
-;;; Code:
-
-(require 'scheme)
-
-(defvar scheme-program-name "scheme"
- "*Program invoked by the `run-scheme' command.")
-
-(defvar scheme-band-name nil
- "*Band loaded by the `run-scheme' command.")
-
-(defvar scheme-program-arguments nil
- "*Arguments passed to the Scheme program by the `run-scheme' command.")
-
-(defvar xscheme-allow-pipelined-evaluation t
- "If non-nil, an expression may be transmitted while another is evaluating.
-Otherwise, attempting to evaluate an expression before the previous expression
-has finished evaluating will signal an error.")
-
-(defvar xscheme-startup-message
- "This is the Scheme process buffer.
-Type \\[advertised-xscheme-send-previous-expression] to evaluate the expression before point.
-Type \\[xscheme-send-control-g-interrupt] to abort evaluation.
-Type \\[describe-mode] for more information.
-
-"
- "String to insert into Scheme process buffer first time it is started.
-Is processed with `substitute-command-keys' first.")
-
-(defvar xscheme-signal-death-message nil
- "If non-nil, causes a message to be generated when the Scheme process dies.")
-
-(defun xscheme-evaluation-commands (keymap)
- (define-key keymap "\e\C-x" 'xscheme-send-definition)
- (define-key keymap "\C-x\C-e" 'advertised-xscheme-send-previous-expression)
- (define-key keymap "\eo" 'xscheme-send-buffer)
- (define-key keymap "\ez" 'xscheme-send-definition)
- (define-key keymap "\e\C-m" 'xscheme-send-previous-expression)
- (define-key keymap "\e\C-z" 'xscheme-send-region))
-
-(defun xscheme-interrupt-commands (keymap)
- (define-key keymap "\C-c\C-s" 'xscheme-select-process-buffer)
- (define-key keymap "\C-c\C-b" 'xscheme-send-breakpoint-interrupt)
- (define-key keymap "\C-c\C-c" 'xscheme-send-control-g-interrupt)
- (define-key keymap "\C-c\C-u" 'xscheme-send-control-u-interrupt)
- (define-key keymap "\C-c\C-x" 'xscheme-send-control-x-interrupt))
-
-(xscheme-evaluation-commands scheme-mode-map)
-(xscheme-interrupt-commands scheme-mode-map)
-
-(defun run-scheme (command-line)
- "Run MIT Scheme in an inferior process.
-Output goes to the buffer `*scheme*'.
-With argument, asks for a command line."
- (interactive
- (list (let ((default
- (or xscheme-process-command-line
- (xscheme-default-command-line))))
- (if current-prefix-arg
- (read-string "Run Scheme: " default)
- default))))
- (setq xscheme-process-command-line command-line)
- (pop-to-buffer (xscheme-start-process command-line)))
-
-(defun reset-scheme ()
- "Reset the Scheme process."
- (interactive)
- (let ((process (get-process "scheme")))
- (cond ((or (not process)
- (not (eq (process-status process) 'run))
- (yes-or-no-p
-"The Scheme process is running, are you SURE you want to reset it? "))
- (message "Resetting Scheme process...")
- (if process (kill-process process t))
- (xscheme-start-process xscheme-process-command-line)
- (message "Resetting Scheme process...done")))))
-
-(defun xscheme-default-command-line ()
- (concat scheme-program-name " -emacs"
- (if scheme-program-arguments
- (concat " " scheme-program-arguments)
- "")
- (if scheme-band-name
- (concat " -band " scheme-band-name)
- "")))
-
-;;;; Interaction Mode
-
-(defun scheme-interaction-mode ()
- "Major mode for interacting with the inferior Scheme process.
-Like scheme-mode except that:
-
-\\[advertised-xscheme-send-previous-expression] sends the expression before point to the Scheme process as input
-\\[xscheme-yank-previous-send] yanks the expression most recently sent to Scheme
-
-All output from the Scheme process is written in the Scheme process
-buffer, which is initially named \"*scheme*\". The result of
-evaluating a Scheme expression is also printed in the process buffer,
-preceded by the string \";Value: \" to highlight it. If the process
-buffer is not visible at that time, the value will also be displayed
-in the minibuffer. If an error occurs, the process buffer will
-automatically pop up to show you the error message.
-
-While the Scheme process is running, the modelines of all buffers in
-scheme-mode are modified to show the state of the process. The
-possible states and their meanings are:
-
-input waiting for input
-run evaluating
-gc garbage collecting
-
-The process buffer's modeline contains additional information where
-the buffer's name is normally displayed: the command interpreter level
-and type.
-
-Scheme maintains a stack of command interpreters. Every time an error
-or breakpoint occurs, the current command interpreter is pushed on the
-command interpreter stack, and a new command interpreter is started.
-One example of why this is done is so that an error that occurs while
-you are debugging another error will not destroy the state of the
-initial error, allowing you to return to it after the second error has
-been fixed.
-
-The command interpreter level indicates how many interpreters are in
-the command interpreter stack. It is initially set to one, and it is
-incremented every time that stack is pushed, and decremented every
-time it is popped. The following commands are useful for manipulating
-the command interpreter stack:
-
-\\[xscheme-send-breakpoint-interrupt] pushes the stack once
-\\[xscheme-send-control-u-interrupt] pops the stack once
-\\[xscheme-send-control-g-interrupt] pops everything off
-\\[xscheme-send-control-x-interrupt] aborts evaluation, doesn't affect stack
-
-Some possible command interpreter types and their meanings are:
-
-[Evaluator] read-eval-print loop for evaluating expressions
-[Debugger] single character commands for debugging errors
-[Where] single character commands for examining environments
-
-Starting with release 6.2 of Scheme, the latter two types of command
-interpreters will change the major mode of the Scheme process buffer
-to scheme-debugger-mode , in which the evaluation commands are
-disabled, and the keys which normally self insert instead send
-themselves to the Scheme process. The command character ? will list
-the available commands.
-
-For older releases of Scheme, the major mode will be be
-scheme-interaction-mode , and the command characters must be sent as
-if they were expressions.
-
-Commands:
-Delete converts tabs to spaces as it moves back.
-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."
- (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))
-
-(defun scheme-interaction-mode-initialize ()
- (use-local-map scheme-interaction-mode-map)
- (setq major-mode 'scheme-interaction-mode)
- (setq mode-name "Scheme Interaction"))
-
-(defun scheme-interaction-mode-commands (keymap)
- (define-key keymap "\C-c\C-m" 'xscheme-send-current-line)
- (define-key keymap "\C-c\C-p" 'xscheme-send-proceed)
- (define-key keymap "\C-c\C-y" 'xscheme-yank-previous-send))
-
-(defvar scheme-interaction-mode-map nil)
-(if (not scheme-interaction-mode-map)
- (progn
- (setq scheme-interaction-mode-map (make-keymap))
- (scheme-mode-commands scheme-interaction-mode-map)
- (xscheme-interrupt-commands scheme-interaction-mode-map)
- (xscheme-evaluation-commands scheme-interaction-mode-map)
- (scheme-interaction-mode-commands scheme-interaction-mode-map)))
-
-(defun xscheme-enter-interaction-mode ()
- (save-excursion
- (set-buffer (xscheme-process-buffer))
- (if (not (eq major-mode 'scheme-interaction-mode))
- (if (eq major-mode 'scheme-debugger-mode)
- (scheme-interaction-mode-initialize)
- (scheme-interaction-mode)))))
-
-(fset 'advertised-xscheme-send-previous-expression
- 'xscheme-send-previous-expression)
-
-;;;; Debugger Mode
-
-(defun scheme-debugger-mode ()
- "Major mode for executing the Scheme debugger.
-Like scheme-mode except that the evaluation commands
-are disabled, and characters that would normally be self inserting are
-sent to the Scheme process instead. Typing ? will show you which
-characters perform useful functions.
-
-Commands:
-\\{scheme-debugger-mode-map}"
- (error "Illegal entry to scheme-debugger-mode"))
-
-(defun scheme-debugger-mode-initialize ()
- (use-local-map scheme-debugger-mode-map)
- (setq major-mode 'scheme-debugger-mode)
- (setq mode-name "Scheme Debugger"))
-
-(defun scheme-debugger-mode-commands (keymap)
- (let ((char ? ))
- (while (< char 127)
- (define-key keymap (char-to-string char) 'scheme-debugger-self-insert)
- (setq char (1+ char)))))
-
-(defvar scheme-debugger-mode-map nil)
-(if (not scheme-debugger-mode-map)
- (progn
- (setq scheme-debugger-mode-map (make-keymap))
- (scheme-mode-commands scheme-debugger-mode-map)
- (xscheme-interrupt-commands scheme-debugger-mode-map)
- (scheme-debugger-mode-commands scheme-debugger-mode-map)))
-
-(defun scheme-debugger-self-insert ()
- "Transmit this character to the Scheme process."
- (interactive)
- (xscheme-send-char last-command-char))
-
-(defun xscheme-enter-debugger-mode (prompt-string)
- (save-excursion
- (set-buffer (xscheme-process-buffer))
- (if (not (eq major-mode 'scheme-debugger-mode))
- (progn
- (if (not (eq major-mode 'scheme-interaction-mode))
- (scheme-interaction-mode))
- (scheme-debugger-mode-initialize)))))
-
-(defun xscheme-debugger-mode-p ()
- (let ((buffer (xscheme-process-buffer)))
- (and buffer
- (save-excursion
- (set-buffer buffer)
- (eq major-mode 'scheme-debugger-mode)))))
-
-;;;; Evaluation Commands
-
-(defun xscheme-send-string (&rest strings)
- "Send the string arguments to the Scheme process.
-The strings are concatenated and terminated by a newline."
- (cond ((not (xscheme-process-running-p))
- (if (yes-or-no-p "The Scheme process has died. Reset it? ")
- (progn
- (reset-scheme)
- (xscheme-wait-for-process)
- (goto-char (point-max))
- (apply 'insert-before-markers strings)
- (xscheme-send-string-1 strings))))
- ((xscheme-debugger-mode-p) (error "No sends allowed in debugger mode"))
- ((and (not xscheme-allow-pipelined-evaluation)
- xscheme-running-p)
- (error "No sends allowed while Scheme running"))
- (t (xscheme-send-string-1 strings))))
-
-(defun xscheme-send-string-1 (strings)
- (let ((string (apply 'concat strings)))
- (xscheme-send-string-2 string)
- (if (eq major-mode 'scheme-interaction-mode)
- (setq xscheme-previous-send string))))
-
-(defun xscheme-send-string-2 (string)
- (let ((process (get-process "scheme")))
- (send-string process (concat string "\n"))
- (if (xscheme-process-buffer-current-p)
- (set-marker (process-mark process) (point)))))
-
-(defun xscheme-yank-previous-send ()
- "Insert the most recent expression at point."
- (interactive)
- (push-mark)
- (insert xscheme-previous-send))
-
-(defun xscheme-select-process-buffer ()
- "Select the Scheme process buffer and move to its output point."
- (interactive)
- (let ((process (or (get-process "scheme") (error "No scheme process"))))
- (let ((buffer (or (process-buffer process) (error "No process buffer"))))
- (let ((window (get-buffer-window buffer)))
- (if window
- (select-window window)
- (switch-to-buffer buffer))
- (goto-char (process-mark process))))))
-
-(defun xscheme-send-region (start end)
- "Send the current region to the Scheme process.
-The region is sent terminated by a newline."
- (interactive "r")
- (if (xscheme-process-buffer-current-p)
- (progn (goto-char end)
- (set-marker (process-mark (get-process "scheme")) end)))
- (xscheme-send-string (buffer-substring start end)))
-
-(defun xscheme-send-definition ()
- "Send the current definition to the Scheme process.
-If the current line begins with a non-whitespace character,
-parse an expression from the beginning of the line and send that instead."
- (interactive)
- (let ((start nil) (end nil))
- (save-excursion
- (end-of-defun)
- (setq end (point))
- (if (re-search-backward "^\\s(" nil t)
- (setq start (point))
- (error "Can't find definition")))
- (xscheme-send-region start end)))
-
-(defun xscheme-send-next-expression ()
- "Send the expression to the right of `point' to the Scheme process."
- (interactive)
- (let ((start (point)))
- (xscheme-send-region start (save-excursion (forward-sexp) (point)))))
-
-(defun xscheme-send-previous-expression ()
- "Send the expression to the left of `point' to the Scheme process."
- (interactive)
- (let ((end (point)))
- (xscheme-send-region (save-excursion (backward-sexp) (point)) end)))
-
-(defun xscheme-send-current-line ()
- "Send the current line to the Scheme process.
-Useful for working with debugging Scheme under adb."
- (interactive)
- (let ((line
- (save-excursion
- (beginning-of-line)
- (let ((start (point)))
- (end-of-line)
- (buffer-substring start (point))))))
- (end-of-line)
- (insert ?\n)
- (xscheme-send-string-2 line)))
-
-(defun xscheme-send-buffer ()
- "Send the current buffer to the Scheme process."
- (interactive)
- (if (xscheme-process-buffer-current-p)
- (error "Not allowed to send this buffer's contents to Scheme"))
- (xscheme-send-region (point-min) (point-max)))
-
-(defun xscheme-send-char (char)
- "Prompt for a character and send it to the Scheme process."
- (interactive "cCharacter to send: ")
- (send-string "scheme" (char-to-string char)))
-
-;;;; Interrupts
-
-(defun xscheme-send-breakpoint-interrupt ()
- "Cause the Scheme process to enter a breakpoint."
- (interactive)
- (xscheme-send-interrupt ?b nil))
-
-(defun xscheme-send-proceed ()
- "Cause the Scheme process to proceed from a breakpoint."
- (interactive)
- (send-string "scheme" "(proceed)\n"))
-
-(defun xscheme-send-control-g-interrupt ()
- "Cause the Scheme processor to halt and flush input.
-Control returns to the top level rep loop."
- (interactive)
- (let ((inhibit-quit t))
- (cond ((not xscheme-control-g-synchronization-p)
- (interrupt-process "scheme"))
- (xscheme-control-g-disabled-p
- (message "Relax..."))
- (t
- (setq xscheme-control-g-disabled-p t)
- (message "Sending C-G interrupt to Scheme...")
- (interrupt-process "scheme")
- (send-string "scheme" (char-to-string 0))))))
-
-(defun xscheme-send-control-u-interrupt ()
- "Cause the Scheme process to halt, returning to previous rep loop."
- (interactive)
- (xscheme-send-interrupt ?u t))
-
-(defun xscheme-send-control-x-interrupt ()
- "Cause the Scheme process to halt, returning to current rep loop."
- (interactive)
- (xscheme-send-interrupt ?x t))
-
-;;; This doesn't really work right -- Scheme just gobbles the first
-;;; character in the input. There is no way for us to guarantee that
-;;; the argument to this procedure is the first char unless we put
-;;; some kind of marker in the input stream.
-
-(defun xscheme-send-interrupt (char mark-p)
- "Send a ^A type interrupt to the Scheme process."
- (interactive "cInterrupt character to send: ")
- (quit-process "scheme")
- (send-string "scheme" (char-to-string char))
- (if (and mark-p xscheme-control-g-synchronization-p)
- (send-string "scheme" (char-to-string 0))))
-
-;;;; Internal Variables
-
-(defvar xscheme-process-command-line nil
- "Command used to start the most recent Scheme process.")
-
-(defvar xscheme-previous-send ""
- "Most recent expression transmitted to the Scheme process.")
-
-(defvar xscheme-process-filter-state 'idle
- "State of scheme process escape reader state machine:
-idle waiting for an escape sequence
-reading-type received an altmode but nothing else
-reading-string reading prompt string")
-
-(defvar xscheme-running-p nil
- "This variable, if nil, indicates that the scheme process is
-waiting for input. Otherwise, it is busy evaluating something.")
-
-(defconst xscheme-control-g-synchronization-p t
- "If non-nil, insert markers in the scheme input stream to indicate when
-control-g interrupts were signaled. Do not allow more control-g's to be
-signaled until the scheme process acknowledges receipt.")
-
-(defvar xscheme-control-g-disabled-p nil
- "This variable, if non-nil, indicates that a control-g is being processed
-by the scheme process, so additional control-g's are to be ignored.")
-
-(defvar xscheme-allow-output-p t
- "This variable, if nil, prevents output from the scheme process
-from being inserted into the process-buffer.")
-
-(defvar xscheme-prompt ""
- "The current scheme prompt string.")
-
-(defvar xscheme-string-accumulator ""
- "Accumulator for the string being received from the scheme process.")
-
-(defvar xscheme-string-receiver nil
- "Procedure to send the string argument from the scheme process.")
-
-(defvar xscheme-start-hook nil
- "If non-nil, a procedure to call when the Scheme process is started.
-When called, the current buffer will be the Scheme process-buffer.")
-
-(defvar xscheme-runlight-string nil)
-(defvar xscheme-mode-string nil)
-(defvar xscheme-filter-input nil)
-
-;;;; Basic Process Control
-
-(defun xscheme-start-process (command-line)
- (let ((buffer (get-buffer-create "*scheme*")))
- (let ((process (get-buffer-process buffer)))
- (save-excursion
- (set-buffer buffer)
- (if (and process (memq (process-status process) '(run stop)))
- (set-marker (process-mark process) (point-max))
- (progn (if process (delete-process process))
- (goto-char (point-max))
- (scheme-interaction-mode)
- (if (bobp)
- (insert-before-markers
- (substitute-command-keys xscheme-startup-message)))
- (setq process
- (let ((process-connection-type nil))
- (apply 'start-process
- (cons "scheme"
- (cons buffer
- (xscheme-parse-command-line
- command-line))))))
- (set-marker (process-mark process) (point-max))
- (xscheme-process-filter-initialize t)
- (xscheme-modeline-initialize)
- (set-process-sentinel process 'xscheme-process-sentinel)
- (set-process-filter process 'xscheme-process-filter)
- (run-hooks 'xscheme-start-hook)))))
- buffer))
-
-(defun xscheme-parse-command-line (string)
- (setq string (substitute-in-file-name string))
- (let ((start 0)
- (result '()))
- (while start
- (let ((index (string-match "[ \t]" string start)))
- (setq start
- (cond ((not index)
- (setq result
- (cons (substring string start)
- result))
- nil)
- ((= index start)
- (string-match "[^ \t]" string start))
- (t
- (setq result
- (cons (substring string start index)
- result))
- (1+ index))))))
- (nreverse result)))
-
-(defun xscheme-wait-for-process ()
- (sleep-for 2)
- (while xscheme-running-p
- (sleep-for 1)))
-
-(defun xscheme-process-running-p ()
- "True iff there is a Scheme process whose status is `run'."
- (let ((process (get-process "scheme")))
- (and process
- (eq (process-status process) 'run))))
-
-(defun xscheme-process-buffer ()
- (let ((process (get-process "scheme")))
- (and process (process-buffer process))))
-
-(defun xscheme-process-buffer-window ()
- (let ((buffer (xscheme-process-buffer)))
- (and buffer (get-buffer-window buffer))))
-
-(defun xscheme-process-buffer-current-p ()
- "True iff the current buffer is the Scheme process buffer."
- (eq (xscheme-process-buffer) (current-buffer)))
-
-;;;; Process Filter
-
-(defun xscheme-process-sentinel (proc reason)
- (xscheme-process-filter-initialize (eq reason 'run))
- (if (eq reason 'run)
- (xscheme-modeline-initialize)
- (progn
- (setq scheme-mode-line-process "")
- (setq xscheme-mode-string "no process")))
- (if (and (not (memq reason '(run stop)))
- xscheme-signal-death-message)
- (progn (beep)
- (message
-"The Scheme process has died! Do M-x reset-scheme to restart it"))))
-
-(defun xscheme-process-filter-initialize (running-p)
- (setq xscheme-process-filter-state 'idle)
- (setq xscheme-running-p running-p)
- (setq xscheme-control-g-disabled-p nil)
- (setq xscheme-allow-output-p t)
- (setq xscheme-prompt "")
- (setq scheme-mode-line-process '(": " xscheme-runlight-string)))
-
-(defun xscheme-process-filter (proc string)
- (let ((xscheme-filter-input string))
- (while xscheme-filter-input
- (cond ((eq xscheme-process-filter-state 'idle)
- (let ((start (string-match "\e" xscheme-filter-input)))
- (if start
- (progn
- (xscheme-process-filter-output
- (substring xscheme-filter-input 0 start))
- (setq xscheme-filter-input
- (substring xscheme-filter-input (1+ start)))
- (setq xscheme-process-filter-state 'reading-type))
- (let ((string xscheme-filter-input))
- (setq xscheme-filter-input nil)
- (xscheme-process-filter-output string)))))
- ((eq xscheme-process-filter-state 'reading-type)
- (if (zerop (length xscheme-filter-input))
- (setq xscheme-filter-input nil)
- (let ((char (aref xscheme-filter-input 0)))
- (setq xscheme-filter-input
- (substring xscheme-filter-input 1))
- (let ((entry (assoc char xscheme-process-filter-alist)))
- (if entry
- (funcall (nth 2 entry) (nth 1 entry))
- (progn
- (xscheme-process-filter-output ?\e char)
- (setq xscheme-process-filter-state 'idle)))))))
- ((eq xscheme-process-filter-state 'reading-string)
- (let ((start (string-match "\e" xscheme-filter-input)))
- (if start
- (let ((string
- (concat xscheme-string-accumulator
- (substring xscheme-filter-input 0 start))))
- (setq xscheme-filter-input
- (substring xscheme-filter-input (1+ start)))
- (setq xscheme-process-filter-state 'idle)
- (funcall xscheme-string-receiver string))
- (progn
- (setq xscheme-string-accumulator
- (concat xscheme-string-accumulator
- xscheme-filter-input))
- (setq xscheme-filter-input nil)))))
- (t
- (error "Scheme process filter -- bad state"))))))
-
-;;;; Process Filter Output
-
-(defun xscheme-process-filter-output (&rest args)
- (if xscheme-allow-output-p
- (let ((string (apply 'concat args)))
- (save-excursion
- (xscheme-goto-output-point)
- (while (string-match "\\(\007\\|\f\\)" string)
- (let ((start (match-beginning 0))
- (end (match-end 0)))
- (insert-before-markers (substring string 0 start))
- (if (= ?\f (aref string start))
- (progn
- (if (not (bolp))
- (insert-before-markers ?\n))
- (insert-before-markers ?\f))
- (beep))
- (setq string (substring string (1+ start)))))
- (insert-before-markers string)))))
-
-(defun xscheme-guarantee-newlines (n)
- (if xscheme-allow-output-p
- (save-excursion
- (xscheme-goto-output-point)
- (let ((stop nil))
- (while (and (not stop)
- (bolp))
- (setq n (1- n))
- (if (bobp)
- (setq stop t)
- (backward-char))))
- (xscheme-goto-output-point)
- (while (> n 0)
- (insert-before-markers ?\n)
- (setq n (1- n))))))
-
-(defun xscheme-goto-output-point ()
- (let ((process (get-process "scheme")))
- (set-buffer (process-buffer process))
- (goto-char (process-mark process))))
-
-(defun xscheme-modeline-initialize ()
- (setq xscheme-runlight-string "")
- (setq xscheme-mode-string "")
- (setq mode-line-buffer-identification '("Scheme: " xscheme-mode-string)))
-
-(defun xscheme-set-runlight (runlight)
- (setq xscheme-runlight-string runlight)
- (force-mode-line-update t))
-
-;;;; Process Filter Operations
-
-(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
- xscheme-process-filter:simple-action)
- (?b xscheme-start-gc
- xscheme-process-filter:simple-action)
- (?e xscheme-finish-gc
- xscheme-process-filter:simple-action)
- (?f xscheme-exit-input-wait
- xscheme-process-filter:simple-action)
- (?g xscheme-enable-control-g
- xscheme-process-filter:simple-action)
- (?i xscheme-prompt-for-expression
- xscheme-process-filter:string-action)
- (?m xscheme-message
- xscheme-process-filter:string-action)
- (?n xscheme-prompt-for-confirmation
- xscheme-process-filter:string-action)
- (?o xscheme-output-goto
- xscheme-process-filter:simple-action)
- (?p xscheme-set-prompt
- xscheme-process-filter:string-action)
- (?s xscheme-enter-input-wait
- xscheme-process-filter:simple-action)
- (?v xscheme-write-value
- xscheme-process-filter:string-action)
- (?w xscheme-cd
- xscheme-process-filter:string-action)
- (?z xscheme-display-process-buffer
- xscheme-process-filter:simple-action)
- (?c xscheme-unsolicited-read-char
- xscheme-process-filter:simple-action))
- "Table used to decide how to handle process filter commands.
-Value is a list of entries, each entry is a list of three items.
-
-The first item is the character that the process filter dispatches on.
-The second item is the action to be taken, a function.
-The third item is the handler for the entry, a function.
-
-When the process filter sees a command whose character matches a
-particular entry, it calls the handler with two arguments: the action
-and the string containing the rest of the process filter's input
-stream. It is the responsibility of the handler to invoke the action
-with the appropriate arguments, and to reenter the process filter with
-the remaining input.")
-
-(defun xscheme-process-filter:simple-action (action)
- (setq xscheme-process-filter-state 'idle)
- (funcall action))
-
-(defun xscheme-process-filter:string-action (action)
- (setq xscheme-string-receiver action)
- (setq xscheme-string-accumulator "")
- (setq xscheme-process-filter-state 'reading-string))
-
-(defconst xscheme-runlight:running "run"
- "The character displayed when the Scheme process is running.")
-
-(defconst xscheme-runlight:input "input"
- "The character displayed when the Scheme process is waiting for input.")
-
-(defconst xscheme-runlight:gc "gc"
- "The character displayed when the Scheme process is garbage collecting.")
-
-(defun xscheme-start-gc ()
- (xscheme-set-runlight xscheme-runlight:gc))
-
-(defun xscheme-finish-gc ()
- (xscheme-set-runlight
- (if xscheme-running-p xscheme-runlight:running xscheme-runlight:input)))
-
-(defun xscheme-enter-input-wait ()
- (xscheme-set-runlight xscheme-runlight:input)
- (setq xscheme-running-p nil))
-
-(defun xscheme-exit-input-wait ()
- (xscheme-set-runlight xscheme-runlight:running)
- (setq xscheme-running-p t))
-
-(defun xscheme-enable-control-g ()
- (setq xscheme-control-g-disabled-p nil))
-
-(defun xscheme-display-process-buffer ()
- (let ((window (or (xscheme-process-buffer-window)
- (display-buffer (xscheme-process-buffer)))))
- (save-window-excursion
- (select-window window)
- (xscheme-goto-output-point)
- (if (xscheme-debugger-mode-p)
- (xscheme-enter-interaction-mode)))))
-
-(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))))
-
-(defun xscheme-write-value (string)
- (if (zerop (length string))
- (xscheme-write-message-1 "(no value)" ";No value")
- (xscheme-write-message-1 string (format ";Value: %s" string))))
-
-(defun xscheme-write-message-1 (message-string output-string)
- (let* ((process (get-process "scheme"))
- (window (get-buffer-window (process-buffer process))))
- (if (or (not window)
- (not (pos-visible-in-window-p (process-mark process)
- window)))
- (message "%s" message-string)))
- (xscheme-guarantee-newlines 1)
- (xscheme-process-filter-output output-string))
-
-(defun xscheme-set-prompt-variable (string)
- (setq xscheme-prompt string))
-
-(defun xscheme-set-prompt (string)
- (setq xscheme-prompt string)
- (xscheme-guarantee-newlines 2)
- (setq xscheme-mode-string (xscheme-coerce-prompt string))
- (force-mode-line-update t))
-
-(defun xscheme-output-goto ()
- (xscheme-goto-output-point)
- (xscheme-guarantee-newlines 2))
-
-(defun xscheme-coerce-prompt (string)
- (if (string-match "^[0-9]+ " string)
- (let ((end (match-end 0)))
- (concat (substring string 0 end)
- (let ((prompt (substring string end)))
- (let ((entry (assoc prompt xscheme-prompt-alist)))
- (if entry
- (cdr entry)
- prompt)))))
- string))
-
-(defvar xscheme-prompt-alist
- '(("[Normal REPL]" . "[Evaluator]")
- ("[Error REPL]" . "[Evaluator]")
- ("[Breakpoint REPL]" . "[Evaluator]")
- ("[Debugger REPL]" . "[Evaluator]")
- ("[Visiting environment]" . "[Evaluator]")
- ("[Environment Inspector]" . "[Where]"))
- "An alist which maps the Scheme command interpreter type to a print string.")
-
-(defun xscheme-cd (directory-string)
- (save-excursion
- (set-buffer (xscheme-process-buffer))
- (cd directory-string)))
-
-(defun xscheme-prompt-for-confirmation (prompt-string)
- (xscheme-send-char (if (y-or-n-p prompt-string) ?y ?n)))
-
-(defun xscheme-prompt-for-expression (prompt-string)
- (xscheme-send-string-2
- (read-from-minibuffer prompt-string nil xscheme-prompt-for-expression-map)))
-
-(defvar xscheme-prompt-for-expression-map nil)
-(if (not xscheme-prompt-for-expression-map)
- (progn
- (setq xscheme-prompt-for-expression-map
- (copy-keymap minibuffer-local-map))
- (substitute-key-definition 'exit-minibuffer
- 'xscheme-prompt-for-expression-exit
- xscheme-prompt-for-expression-map)))
-
-(defun xscheme-prompt-for-expression-exit ()
- (interactive)
- (if (eq (xscheme-region-expression-p (point-min) (point-max)) 'one)
- (exit-minibuffer)
- (error "input must be a single, complete expression")))
-
-(defun xscheme-region-expression-p (start end)
- (save-excursion
- (let ((old-syntax-table (syntax-table)))
- (unwind-protect
- (progn
- (set-syntax-table scheme-mode-syntax-table)
- (let ((state (parse-partial-sexp start end)))
- (and (zerop (car state)) ;depth = 0
- (nth 2 state) ;last-sexp exists, i.e. >= 1 sexps
- (let ((state (parse-partial-sexp start (nth 2 state))))
- (if (nth 2 state) 'many 'one)))))
- (set-syntax-table old-syntax-table)))))
-
-(provide 'xscheme)
-
-;;; xscheme.el ends here
diff --git a/lisp/xt-mouse.el b/lisp/xt-mouse.el
deleted file mode 100644
index 1564034cc7f..00000000000
--- a/lisp/xt-mouse.el
+++ /dev/null
@@ -1,190 +0,0 @@
-;;; xt-mouse.el --- Support the mouse when emacs run in an xterm.
-
-;; Copyright (C) 1994 Free Software Foundation
-
-;; Author: Per Abrahamsen <abraham@iesd.auc.dk>
-;; Keywords: mouse, terminals
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Comments:
-
-;; Enable mouse support when running inside an xterm or Linux console.
-
-;; This is actually useful when you are running X11 locally, but is
-;; working on remote machine over a modem line or through a gateway.
-
-;; It works by translating xterm escape codes into generic emacs mouse
-;; events so it should work with any package that uses the mouse.
-
-;; The xterm mouse escape codes are supposedly also supported by the
-;; Linux console, but I have not been able to verify this.
-
-;; You don't have to turn off xterm mode to use the normal xterm mouse
-;; functionality, it is still available by holding down the SHIFT key
-;; when you press the mouse button.
-
-;;; Todo:
-
-;; Support multi-click -- somehow.
-
-;; Clicking on the mode-line does not work, although it should.
-
-;;; Code:
-
-(define-key function-key-map "\e[M" 'xterm-mouse-translate)
-
-(defvar xterm-mouse-last)
-
-(defun xterm-mouse-translate (event)
- ;; Read a click and release event from XTerm.
- (save-excursion
- (save-window-excursion
- (deactivate-mark)
- (let* ((xterm-mouse-last)
- (down (xterm-mouse-event))
- (down-command (nth 0 down))
- (down-data (nth 1 down))
- (down-where (nth 1 down-data))
- (down-binding (key-binding (if (symbolp down-where)
- (vector down-where down-command)
- (vector down-command)))))
- (or (and (eq (read-char) ?\e)
- (eq (read-char) ?\[)
- (eq (read-char) ?M))
- (error "Unexpected escape sequence from XTerm"))
- (let* ((click (xterm-mouse-event))
- (click-command (nth 0 click))
- (click-data (nth 1 click))
- (click-where (nth 1 click-data)))
- (if (memq down-binding '(nil ignore))
- (if (and (symbolp click-where)
- (not (eq 'menu-bar click-where)))
- (vector (list click-where click-data) click)
- (vector click))
- (setq unread-command-events
- (if (eq down-where click-where)
- (list click)
- (list
- ;; Cheat `mouse-drag-region' with move event.
- (list 'mouse-movement click-data)
- ;; Generate a drag event.
- (if (symbolp down-where)
- 0
- (list (intern (concat "drag-mouse-" (+ 1 xterm-mouse-last)))
- down-data click-data))
- )))
- (if (and (symbolp down-where)
- (not (eq 'menu-bar down-where)))
- (vector (list down-where down-data) down)
- (vector down))))))))
-
-(defvar xterm-mouse-x 0
- "Position of last xterm mouse event relative to the frame.")
-
-(defvar xterm-mouse-y 0
- "Position of last xterm mouse event relative to the frame.")
-
-(defadvice mouse-position (around xterm-mouse activate)
- "Use last key from xterm-mouse-mode if available."
- (let ((answer ad-do-it))
- (setq ad-return-value
- (if xterm-mouse-mode
- (cons (car answer) (cons xterm-mouse-x xterm-mouse-y))
- answer))))
-
-(defun xterm-mouse-event ()
- ;; Convert XTerm mouse event to Emacs mouse event.
- (let* ((type (- (read-char) ? ))
- (x (- (read-char) ? 1))
- (y (- (read-char) ? 1))
- (point (cons x y))
- (window (window-at x y))
- (where (if window
- (coordinates-in-window-p point window)
- 'menu-bar))
- (pos (if (consp where)
- (progn
- (select-window window)
- (goto-char (window-start window))
- (move-to-window-line (cdr where))
- (move-to-column (+ (car where) (current-column)
- (if (string-match "\\` \\*Minibuf"
- (buffer-name))
- (- (minibuffer-prompt-width))
- 0)
- (max 0 (1- (window-hscroll)))))
- (point))
- where))
- (mouse (intern (if (eq type 3)
- (concat "mouse-" (+ 1 xterm-mouse-last))
- (setq xterm-mouse-last type)
- (concat "down-mouse-" (+ 1 type))))))
- (setq xterm-mouse-x x
- xterm-mouse-y y)
- (list mouse
- (list window pos point
- (/ (nth 2 (current-time)) 1000)))))
-
-;; Indicator for the xterm-mouse mode.
-(defvar xterm-mouse-mode nil)
-
-(or (assq 'xterm-mouse-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(xterm-mouse-mode (" Mouse")) minor-mode-alist)))
-
-;;;###autoload
-(defun xterm-mouse-mode (arg)
- "Toggle XTerm mouse mode.
-With prefix arg, turn XTerm mouse mode on iff arg is positive.
-
-Turn it on to use emacs mouse commands, and off to use xterm mouse commands."
- (interactive "P")
- (if (or (and (null arg) xterm-mouse-mode)
- (<= (prefix-numeric-value arg) 0))
- ;; Turn it off
- (if xterm-mouse-mode
- (progn
- (turn-off-xterm-mouse-tracking)
- (setq xterm-mouse-mode nil)
- (set-buffer-modified-p (buffer-modified-p))))
- ;;Turn it on
- (if xterm-mouse-mode
- ()
- (setq xterm-mouse-mode t)
- (turn-on-xterm-mouse-tracking)
- (set-buffer-modified-p (buffer-modified-p)))))
-
-(defun turn-on-xterm-mouse-tracking ()
- ;; Enable emacs mouse tracking in xterm.
- (if xterm-mouse-mode
- (send-string-to-terminal "\e[?1000h")))
-
-(defun turn-off-xterm-mouse-tracking ()
- ;; Disable disable emacs mouse tracking in xterm.
- (if xterm-mouse-mode
- (send-string-to-terminal "\e[?1000l")))
-
-;; Restore normal mouse behaviour outside Emacs.
-(add-hook 'suspend-hook 'turn-off-xterm-mouse-tracking)
-(add-hook 'suspend-resume-hook 'turn-on-xterm-mouse-tracking)
-(add-hook 'kill-emacs-hook 'turn-off-xterm-mouse-tracking)
-
-(provide 'xt-mouse)
-
-;;; xt-mouse.el ends here
diff --git a/lispref/=buffer-local.texi b/lispref/=buffer-local.texi
deleted file mode 100644
index 4c4e0ca4362..00000000000
--- a/lispref/=buffer-local.texi
+++ /dev/null
@@ -1,94 +0,0 @@
-@c -*-texinfo-*-
-@setfilename ../info/locals
-@node Standard Buffer-Local Variables, Standard Keymaps, Standard Errors, Top
-@appendix Standard Buffer-Local Variables
-
- The table below shows all of the variables that are automatically
-local (when set) in each buffer in Emacs Version 18 with the common
-packages loaded.
-
-@table @code
-@item abbrev-mode
-@xref{Abbrevs}.
-
-@item auto-fill-function
-@xref{Auto Filling}.
-
-@item buffer-auto-save-file-name
-@xref{Auto-Saving}.
-
-@item buffer-backed-up
-@xref{Backup Files}.
-
-@item buffer-display-table
-@xref{Active Display Table}.
-
-@item buffer-file-name
-@xref{Buffer File Name}.
-
-@item buffer-file-truename
-@xref{Buffer File Name}.
-
-@item buffer-read-only
-@xref{Read Only Buffers}.
-
-@item buffer-saved-size
-@xref{Point}.
-
-@item case-fold-search
-@xref{Searching and Case}.
-
-@item ctl-arrow
-@xref{Control Char Display}.
-
-@item default-directory
-@xref{System Environment}.
-
-@item fill-column
-@xref{Auto Filling}.
-
-@item left-margin
-@xref{Indentation}.
-
-@item list-buffers-directory
-@xref{Buffer File Name}.
-
-@item local-abbrev-table
-@xref{Abbrevs}.
-
-@item major-mode
-@xref{Mode Help}.
-
-@item mark-ring
-@xref{The Mark}.
-
-@item minor-modes
-@xref{Minor Modes}.
-
-@item mode-name
-@xref{Mode Line Variables}.
-
-@item overwrite-mode
-@xref{Insertion}.
-
-@item paragraph-separate
-@xref{Standard Regexps}.
-
-@item paragraph-start
-@xref{Standard Regexps}.
-
-@item require-final-newline
-@xref{Insertion}.
-
-@item selective-display
-@xref{Selective Display}.
-
-@item selective-display-ellipses
-@xref{Selective Display}.
-
-@item tab-width
-@xref{Control Char Display}.
-
-@item truncate-lines
-@xref{Truncation}.
-@end table
diff --git a/lispref/Makefile.in b/lispref/Makefile.in
deleted file mode 100644
index f00ad600f6f..00000000000
--- a/lispref/Makefile.in
+++ /dev/null
@@ -1,129 +0,0 @@
-# Makefile for the GNU Emacs Lisp Reference Manual.
-#
-# 11 August 1990
-
-# Redefine `TEX' if `tex' does not invoke plain TeX. For example:
-# TEX=platex
-
-TEX=tex
-MAKE=make
-
-# Where the TeX macros are kept:
-texmacrodir = /usr/local/lib/tex/macros
-
-# Where the Emacs hierarchy lives ($EMACS in the INSTALL document for Emacs.)
-# For example:
-# emacslibdir = /usr/local/gnu/lib/emacs
-
-# Directory where Emacs is installed, by default:
-emacslibdir = /usr/local/emacs
-
-# Unless you have a nonstandard Emacs installation, these shouldn't have to
-# be changed.
-prefix = /usr/local
-infodir = ${prefix}/info
-
-# The name of the manual:
-
-VERSION=2.4.2
-manual = elisp-manual-19-$(VERSION)
-
-# Uncomment this line for permuted index.
-# permuted_index = 1
-
-# List of all the texinfo files in the manual:
-
-srcs = elisp.texi back.texi \
- abbrevs.texi anti.texi backups.texi locals.texi buffers.texi \
- calendar.texi commands.texi compile.texi control.texi debugging.texi \
- display.texi edebug.texi errors.texi eval.texi files.texi \
- frames.texi functions.texi help.texi hooks.texi \
- internals.texi intro.texi keymaps.texi lists.texi \
- loading.texi macros.texi maps.texi markers.texi \
- minibuf.texi modes.texi numbers.texi objects.texi \
- os.texi positions.texi processes.texi searching.texi \
- sequences.texi streams.texi strings.texi symbols.texi \
- syntax.texi text.texi tips.texi variables.texi \
- windows.texi \
- index.unperm index.perm
-
-.PHONY: elisp.dvi clean
-
-# The info file is named `elisp'.
-# We depend on makeinfo.c rather than makeinfo -- there's no need to rebuild
-# everything just because makeinfo isn't part of the distribution.
-
-elisp: $(srcs) index.texi makeinfo.c
- $(MAKE) makeinfo
- rm -f elisp-*
- ./makeinfo elisp.texi
-
-elisp.dvi: $(srcs) index.texi texindex
- # Avoid losing old contents of aux file entirely.
- -mv elisp.aux elisp.oaux
- # First shot to define xrefs:
- $(TEX) elisp.texi
- if [ a${permuted_index} != a ]; \
- then \
- ./permute-index; \
- mv permuted.fns elisp.fns; \
- else \
- ./texindex elisp.??; \
- fi
- $(TEX) elisp.texi
-
-index.texi:
- if [ a${permuted_index} != a ]; \
- then \
- ln -s index.perm index.texi; \
- else \
- ln -s index.unperm index.texi; \
- fi
-
-install: elisp
- ./mkinstalldirs $(infodir)
- cp elisp elisp-* $(infodir)
- @echo also add the line for elisp to $(infodir)/dir.
-
-installall: install
- install -c texinfo.tex $(texmacrodir)
-
-clean:
- rm -f *.toc *.aux *.log *.cp *.cps *.fn *.fns *.tp *.tps \
- *.vr *.vrs *.pg *.pgs *.ky *.kys
- rm -f make.out core
- rm -f makeinfo.o makeinfo getopt.o getopt1.o
- rm -f texindex.o texindex index.texi
-
-maintainer-clean: clean
- rm -f elisp elisp-*
-
-dist:
- -mkdir temp
- -mkdir temp/$(manual)
- -ln README Makefile permute-index $(srcs) \
- texinfo.tex getopt.c getopt1.c getopt.h \
- elisp.dvi elisp.aux elisp.??s elisp elisp-[0-9] elisp-[0-9][0-9] temp/$(manual)
- -(cd temp/$(manual); rm -f texindex.c makeinfo.c mkinstalldirs)
- cp texindex.c makeinfo.c mkinstalldirs temp/$(manual)
- (cd temp/$(manual); rm -f *~)
- (cd temp; tar chf - $(manual)) | gzip > $(manual).tar.gz
- -rm -rf temp
-
-# Make two programs used in generating output from texinfo.
-
-CFLAGS = -g
-
-texindex: texindex.o
- $(CC) -o $@ $(LDFLAGS) $(CFLAGS) $?
-texindex.o: texindex.c
-
-MAKEINFO_MAJOR = 1
-MAKEINFO_MINOR = 0
-MAKEINFO_FLAGS = -DMAKEINFO_MAJOR=$(MAKEINFO_MAJOR) -DMAKEINFO_MINOR=$(MAKEINFO_MINOR)
-
-makeinfo: makeinfo.o getopt.o getopt1.o
- $(CC) $(LDFLAGS) -o makeinfo makeinfo.o getopt.o getopt1.o
-
-makeinfo.o: makeinfo.c
- $(CC) -c $(CFLAGS) $(MAKEINFO_FLAGS) makeinfo.c
diff --git a/lispref/README b/lispref/README
deleted file mode 100644
index ba603cfc0b5..00000000000
--- a/lispref/README
+++ /dev/null
@@ -1,50 +0,0 @@
-README for Edition 2.4 of the Emacs Lisp Reference Manual.
-
-* This directory contains the texinfo source files for the Reference
-Manual, make-permuted-index, and the latest version of texinfo.tex,
-which handles forms that cannot be handled by the older versions of
-texinfo.tex. Also, it contains makeinfo.c.
-
-* Report Lisp Manual bugs to bug-lisp-manual@prep.ai.mit.edu. We
-don't read these bug reports until it's time for a new edition. To
-report other Emacs bugs, use bug-gnu-emacs@prep.ai.mit.edu.
-To ask questions, use the newsgroup gnu.emacs.help.
-
-* The Emacs Lisp Reference Manual is quite large. It totals around
-700 pages in smallbook format; the info files total almost two
-megabytes.
-
-* You can format this manual either for Info or for printing hardcopy
-using TeX.
-
-* You can buy nicely printed copies from the Free Software Foundation.
-For info, send mail to gnu@prep.ai.mit.edu or phone 617-542-5942.
-Buying a manual from the Free Software Foundation helps support our
-GNU development work.
-
-** This distribution contains a Makefile that you can use with GNU Make.
-Otherwise, here are detailed instructions:
-
-** HARDCOPY: A copy of the version of `texinfo.tex' that formats this
-manual is included in this distribution.
-
-The master file for formatting this manual for Tex is called
-`elisp.texi'. It contains @include commands to include all the
-chapters that make up the manual. In addition, `elisp.texi' has
-the title page in a new format designed by Karl Berry, using the
-@titlespec command.
-
-To create a DVI file with a sorted index, execute the following
-commands in the shell:
-
-% make index.texi
-% make elisp.dvi
-
-*** To create a DVI file with a permuted index, you may experiment
-with `make-permuted-index'.
-
-** INFO: A copy of makeinfo.c that will format this manual for Info is
-included in this distribution. This program is written in C and can
-be used separately from Emacs. `makeinfo' produces much better error
-messages than the old `texinfo-format-buffer'. You can run `makeinfo'
-it on the `elisp.texi' file.
diff --git a/lispref/abbrevs.texi b/lispref/abbrevs.texi
deleted file mode 100644
index 914e2659450..00000000000
--- a/lispref/abbrevs.texi
+++ /dev/null
@@ -1,344 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/abbrevs
-@node Abbrevs, Processes, Syntax Tables, Top
-@chapter Abbrevs And Abbrev Expansion
-@cindex abbrev
-@cindex abbrev table
-
- An abbreviation or @dfn{abbrev} is a string of characters that may be
-expanded to a longer string. The user can insert the abbrev string and
-find it replaced automatically with the expansion of the abbrev. This
-saves typing.
-
- The set of abbrevs currently in effect is recorded in an @dfn{abbrev
-table}. Each buffer has a local abbrev table, but normally all buffers
-in the same major mode share one abbrev table. There is also a global
-abbrev table. Normally both are used.
-
- An abbrev table is represented as an obarray containing a symbol for
-each abbreviation. The symbol's name is the abbreviation; its value is
-the expansion; its function definition is the hook function to do the
-expansion (@pxref{Defining Abbrevs}); its property list cell contains
-the use count, the number of times the abbreviation has been expanded.
-Because these symbols are not interned in the usual obarray, they will
-never appear as the result of reading a Lisp expression; in fact,
-normally they are never used except by the code that handles abbrevs.
-Therefore, it is safe to use them in an extremely nonstandard way.
-@xref{Creating Symbols}.
-
- For the user-level commands for abbrevs, see @ref{Abbrevs,, Abbrev
-Mode, emacs, The GNU Emacs Manual}.
-
-@menu
-* Abbrev Mode:: Setting up Emacs for abbreviation.
-* Tables: Abbrev Tables. Creating and working with abbrev tables.
-* Defining Abbrevs:: Specifying abbreviations and their expansions.
-* Files: Abbrev Files. Saving abbrevs in files.
-* Expansion: Abbrev Expansion. Controlling expansion; expansion subroutines.
-* Standard Abbrev Tables:: Abbrev tables used by various major modes.
-@end menu
-
-@node Abbrev Mode, Abbrev Tables, Abbrevs, Abbrevs
-@comment node-name, next, previous, up
-@section Setting Up Abbrev Mode
-
- Abbrev mode is a minor mode controlled by the value of the variable
-@code{abbrev-mode}.
-
-@defvar abbrev-mode
-A non-@code{nil} value of this variable turns on the automatic expansion
-of abbrevs when their abbreviations are inserted into a buffer.
-If the value is @code{nil}, abbrevs may be defined, but they are not
-expanded automatically.
-
-This variable automatically becomes local when set in any fashion.
-@end defvar
-
-@defvar default-abbrev-mode
-This is the value of @code{abbrev-mode} for buffers that do not override it.
-This is the same as @code{(default-value 'abbrev-mode)}.
-@end defvar
-
-@node Abbrev Tables, Defining Abbrevs, Abbrev Mode, Abbrevs
-@section Abbrev Tables
-
- This section describes how to create and manipulate abbrev tables.
-
-@defun make-abbrev-table
-This function creates and returns a new, empty abbrev table---an obarray
-containing no symbols. It is a vector filled with zeros.
-@end defun
-
-@defun clear-abbrev-table table
-This function undefines all the abbrevs in abbrev table @var{table},
-leaving it empty. The function returns @code{nil}.
-@end defun
-
-@defun define-abbrev-table tabname definitions
-This function defines @var{tabname} (a symbol) as an abbrev table name,
-i.e., as a variable whose value is an abbrev table. It defines abbrevs
-in the table according to @var{definitions}, a list of elements of the
-form @code{(@var{abbrevname} @var{expansion} @var{hook}
-@var{usecount})}. The value is always @code{nil}.
-@end defun
-
-@defvar abbrev-table-name-list
-This is a list of symbols whose values are abbrev tables.
-@code{define-abbrev-table} adds the new abbrev table name to this list.
-@end defvar
-
-@defun insert-abbrev-table-description name &optional human
-This function inserts before point a description of the abbrev table
-named @var{name}. The argument @var{name} is a symbol whose value is an
-abbrev table. The value is always @code{nil}.
-
-If @var{human} is non-@code{nil}, the description is human-oriented.
-Otherwise the description is a Lisp expression---a call to
-@code{define-abbrev-table} that would define @var{name} exactly as it
-is currently defined.
-@end defun
-
-@node Defining Abbrevs, Abbrev Files, Abbrev Tables, Abbrevs
-@comment node-name, next, previous, up
-@section Defining Abbrevs
-
- These functions define an abbrev in a specified abbrev table.
-@code{define-abbrev} is the low-level basic function, while
-@code{add-abbrev} is used by commands that ask for information from the
-user.
-
-@defun add-abbrev table type arg
-This function adds an abbreviation to abbrev table @var{table} based on
-information from the user. The argument @var{type} is a string
-describing in English the kind of abbrev this will be (typically,
-@code{"global"} or @code{"mode-specific"}); this is used in prompting
-the user. The argument @var{arg} is the number of words in the
-expansion.
-
-The return value is the symbol that internally represents the new
-abbrev, or @code{nil} if the user declines to confirm redefining an
-existing abbrev.
-@end defun
-
-@defun define-abbrev table name expansion hook
-This function defines an abbrev in @var{table} named @var{name}, to
-expand to @var{expansion}, and call @var{hook}. The return value is an
-uninterned symbol that represents the abbrev inside Emacs; its name is
-@var{name}.
-
-The argument @var{name} should be a string. The argument
-@var{expansion} should be a string, or @code{nil} to undefine the
-abbrev.
-
-The argument @var{hook} is a function or @code{nil}. If @var{hook} is
-non-@code{nil}, then it is called with no arguments after the abbrev is
-replaced with @var{expansion}; point is located at the end of
-@var{expansion} when @var{hook} is called.
-
-The use count of the abbrev is initialized to zero.
-@end defun
-
-@defopt only-global-abbrevs
-If this variable is non-@code{nil}, it means that the user plans to use
-global abbrevs only. This tells the commands that define mode-specific
-abbrevs to define global ones instead. This variable does not alter the
-behavior of the functions in this section; it is examined by their
-callers.
-@end defopt
-
-@node Abbrev Files, Abbrev Expansion, Defining Abbrevs, Abbrevs
-@section Saving Abbrevs in Files
-
- A file of saved abbrev definitions is actually a file of Lisp code.
-The abbrevs are saved in the form of a Lisp program to define the same
-abbrev tables with the same contents. Therefore, you can load the file
-with @code{load} (@pxref{How Programs Do Loading}). However, the
-function @code{quietly-read-abbrev-file} is provided as a more
-convenient interface.
-
- User-level facilities such as @code{save-some-buffers} can save
-abbrevs in a file automatically, under the control of variables
-described here.
-
-@defopt abbrev-file-name
-This is the default file name for reading and saving abbrevs.
-@end defopt
-
-@defun quietly-read-abbrev-file filename
-This function reads abbrev definitions from a file named @var{filename},
-previously written with @code{write-abbrev-file}. If @var{filename} is
-@code{nil}, the file specified in @code{abbrev-file-name} is used.
-@code{save-abbrevs} is set to @code{t} so that changes will be saved.
-
-This function does not display any messages. It returns @code{nil}.
-@end defun
-
-@defopt save-abbrevs
-A non-@code{nil} value for @code{save-abbrev} means that Emacs should
-save abbrevs when files are saved. @code{abbrev-file-name} specifies
-the file to save the abbrevs in.
-@end defopt
-
-@defvar abbrevs-changed
-This variable is set non-@code{nil} by defining or altering any
-abbrevs. This serves as a flag for various Emacs commands to offer to
-save your abbrevs.
-@end defvar
-
-@deffn Command write-abbrev-file filename
-Save all abbrev definitions, in all abbrev tables, in the file
-@var{filename}, in the form of a Lisp program that when loaded will
-define the same abbrevs. This function returns @code{nil}.
-@end deffn
-
-@node Abbrev Expansion, Standard Abbrev Tables, Abbrev Files, Abbrevs
-@comment node-name, next, previous, up
-@section Looking Up and Expanding Abbreviations
-
- Abbrevs are usually expanded by commands for interactive use,
-including @code{self-insert-command}. This section describes the
-subroutines used in writing such functions, as well as the variables
-they use for communication.
-
-@defun abbrev-symbol abbrev &optional table
-This function returns the symbol representing the abbrev named
-@var{abbrev}. The value returned is @code{nil} if that abbrev is not
-defined. The optional second argument @var{table} is the abbrev table
-to look it up in. If @var{table} is @code{nil}, this function tries
-first the current buffer's local abbrev table, and second the global
-abbrev table.
-@end defun
-
-@defun abbrev-expansion abbrev &optional table
-This function returns the string that @var{abbrev} would expand into (as
-defined by the abbrev tables used for the current buffer). The optional
-argument @var{table} specifies the abbrev table to use, as in
-@code{abbrev-symbol}.
-@end defun
-
-@deffn Command expand-abbrev
-This command expands the abbrev before point, if any.
-If point does not follow an abbrev, this command does nothing.
-The command returns @code{t} if it did expansion, @code{nil} otherwise.
-@end deffn
-
-@deffn Command abbrev-prefix-mark &optional arg
-Mark current point as the beginning of an abbrev. The next call to
-@code{expand-abbrev} will use the text from here to point (where it is
-then) as the abbrev to expand, rather than using the previous word as
-usual.
-@end deffn
-
-@defopt abbrev-all-caps
-When this is set non-@code{nil}, an abbrev entered entirely in upper
-case is expanded using all upper case. Otherwise, an abbrev entered
-entirely in upper case is expanded by capitalizing each word of the
-expansion.
-@end defopt
-
-@defvar abbrev-start-location
-This is the buffer position for @code{expand-abbrev} to use as the start
-of the next abbrev to be expanded. (@code{nil} means use the word
-before point instead.) @code{abbrev-start-location} is set to
-@code{nil} each time @code{expand-abbrev} is called. This variable is
-also set by @code{abbrev-prefix-mark}.
-@end defvar
-
-@defvar abbrev-start-location-buffer
-The value of this variable is the buffer for which
-@code{abbrev-start-location} has been set. Trying to expand an abbrev
-in any other buffer clears @code{abbrev-start-location}. This variable
-is set by @code{abbrev-prefix-mark}.
-@end defvar
-
-@defvar last-abbrev
-This is the @code{abbrev-symbol} of the last abbrev expanded. This
-information is left by @code{expand-abbrev} for the sake of the
-@code{unexpand-abbrev} command.
-@end defvar
-
-@defvar last-abbrev-location
-This is the location of the last abbrev expanded. This contains
-information left by @code{expand-abbrev} for the sake of the
-@code{unexpand-abbrev} command.
-@end defvar
-
-@defvar last-abbrev-text
-This is the exact expansion text of the last abbrev expanded, after case
-conversion (if any). Its value is @code{nil} if the abbrev has already
-been unexpanded. This contains information left by @code{expand-abbrev}
-for the sake of the @code{unexpand-abbrev} command.
-@end defvar
-
-@c Emacs 19 feature
-@defvar pre-abbrev-expand-hook
-This is a normal hook whose functions are executed, in sequence, just
-before any expansion of an abbrev. @xref{Hooks}. Since it is a normal
-hook, the hook functions receive no arguments. However, they can find
-the abbrev to be expanded by looking in the buffer before point.
-@end defvar
-
- The following sample code shows a simple use of
-@code{pre-abbrev-expand-hook}. If the user terminates an abbrev with a
-punctuation character, the hook function asks for confirmation. Thus,
-this hook allows the user to decide whether to expand the abbrev, and
-aborts expansion if it is not confirmed.
-
-@smallexample
-(add-hook 'pre-abbrev-expand-hook 'query-if-not-space)
-
-;; @r{This is the function invoked by @code{pre-abbrev-expand-hook}.}
-
-;; @r{If the user terminated the abbrev with a space, the function does}
-;; @r{nothing (that is, it returns so that the abbrev can expand). If the}
-;; @r{user entered some other character, this function asks whether}
-;; @r{expansion should continue.}
-
-;; @r{If the user answers the prompt with @kbd{y}, the function returns}
-;; @r{@code{nil} (because of the @code{not} function), but that is}
-;; @r{acceptable; the return value has no effect on expansion.}
-
-(defun query-if-not-space ()
- (if (/= ?\ (preceding-char))
- (if (not (y-or-n-p "Do you want to expand this abbrev? "))
- (error "Not expanding this abbrev"))))
-@end smallexample
-
-@node Standard Abbrev Tables, , Abbrev Expansion, Abbrevs
-@comment node-name, next, previous, up
-@section Standard Abbrev Tables
-
- Here we list the variables that hold the abbrev tables for the
-preloaded major modes of Emacs.
-
-@defvar global-abbrev-table
-This is the abbrev table for mode-independent abbrevs. The abbrevs
-defined in it apply to all buffers. Each buffer may also have a local
-abbrev table, whose abbrev definitions take precedence over those in the
-global table.
-@end defvar
-
-@defvar local-abbrev-table
-The value of this buffer-local variable is the (mode-specific)
-abbreviation table of the current buffer.
-@end defvar
-
-@defvar fundamental-mode-abbrev-table
-This is the local abbrev table used in Fundamental mode; in other words,
-it is the local abbrev table in all buffers in Fundamental mode.
-@end defvar
-
-@defvar text-mode-abbrev-table
-This is the local abbrev table used in Text mode.
-@end defvar
-
-@defvar c-mode-abbrev-table
-This is the local abbrev table used in C mode.
-@end defvar
-
-@defvar lisp-mode-abbrev-table
-This is the local abbrev table used in Lisp mode and Emacs Lisp mode.
-@end defvar
diff --git a/lispref/anti.texi b/lispref/anti.texi
deleted file mode 100644
index ca94cf3d196..00000000000
--- a/lispref/anti.texi
+++ /dev/null
@@ -1,619 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1993 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@node Antinews, Index, Standard Hooks, Top
-@appendix Emacs 18 Antinews
-
-For those users who live backwards in time, here is information about
-downgrading to Emacs version 18. We hope you will enjoy the greater
-simplicity that results from the absence of many Emacs 19 features.
-
-@section Old Features in the Lisp Language
-
-The following functions are missing or different in Emacs version 18.
-
-@itemize @bullet
-@item
-The functions @code{delete}, @code{member}, @code{indirect-function},
-@code{map-y-or-n-p}, and @code{invocation-name} have been removed.
-
-@item
-The function @code{read} now skips a terminator character that
-terminates a symbol when reading from a buffer. Thus, if you use
-@code{read} on a buffer containing @samp{foo(bar)} following point, it
-returns @code{foo} and leaves point after the open-parenthesis. This
-means there's no way you can properly read the list @samp{(bar)}, but
-that's the way the cookie crumbles.
-
-Because of this simplification, it's no longer necessary for an input
-stream function to accept an optional argument. In Emacs 18, an input
-stream is always called with no arguments, and should always return
-the next character of input.
-
-@item
-The function @code{documentation} takes just one argument;
-@code{documentation-property} takes just two.
-
-@item
-@code{random} no longer has the optional argument @var{n}.
-
-@item
-You can no longer arrange to run a hook if a particular Lisp library is
-loaded. The variable @code{after-load-alist} and the function
-@code{eval-after-load} have been removed.
-
-@item
-The function @code{autoload} no longer supports autoloading a keymap.
-
-@item
-``Magic'' comments of the form @samp{;;;###autoload} are now just
-comments. They don't do anything in particular except look pretty.
-If you want a function to be autoloaded by default, edit @file{loaddefs.h}
-by hand. What do you think editors are for?
-
-@item
-We took out the @samp{%S} from the @code{format} function, and the
-optional argument @var{noescap} from @code{prin1-to-string}. We removed
-the @code{print-level} variable.
-@end itemize
-
-@section Compilation Features
-
-@itemize @bullet
-@item
-Inline functions are nonexistent in Emacs 18. We find they make the
-calling function unnecessarily large. (Small size is one of the
-features of Emacs 18.)
-
-@item
-We eliminated the two special forms, @code{eval-when-compile} and
-@code{eval-and-compile}, as well as the @code{compile-defun} command.
-
-@item
-When you load a Lisp file or library, you will no longer receive a
-warning if the directory contains both a @samp{.elc} file and a new
-@samp{.el} file that is newer. So be on your toes.
-
-@item
-We removed the special data type for byte-code functions. Compiled
-functions now work by means of an interpreted function which calls
-the function @code{bytecode}. That function runs the byte code
-interpreter.
-@end itemize
-
-@section Floating Point Numbers
-
-Emacs 18 doesn't have or need floating point arithmetic built in.
-It has a handy Lisp program that allows you to emulate floating point.
-You'll have to write programs specially to use it, though.
-
-As a result, certain macros, functions, and predicates no longer handle
-specifications for floating point numbers.
-
-@itemize @bullet
-@item
-The function @code{string-to-number}, the predicate @code{floatp}, and
-the variable @code{float-output-format} have all been eliminated.
-
-@item
-The functions @code{float}, @code{truncate}, @code{floor}, @code{ceil},
-@code{round}, and @code{logb} do not exist; neither do the functions
-@code{abs}, @code{cos}, @code{sin}, @code{tan}, @code{acos},
-@code{asin}, @code{atan}, @code{exp}, @code{expt}, @code{log10},
-@code{log}, or @code{sqrt}.
-
-@item
-The @code{format} function no longer handles the specifications
-@samp{%e}, @samp{%f} and @samp{%g} for printing floating point numbers;
-likewise for @code{message}.
-@end itemize
-
-@section Changes in Basic Editing Functions
-
-@itemize @bullet
-@item
-@code{kill-new} and @code{kill-append}, the primitives for putting text
-in the kill ring, have been eliminated.
-@c @code{kill-append} seems to exist as a non-documented (no doc string)
-@c primitive in emacs 18. but news.texi said it was new for 19.
-
-@item
-The variables @code{interprogram-paste-function} and
-@code{interprogram-cut-function} have been removed in Emacs 18.
-
-In addition, there's no need for @code{mark-active} and
-@code{deactivate-mark} because there is no Transient Mark mode. We also
-removed the hooks @code{activate-mark-hook} and
-@code{deactivate-mark-hook}.
-
-@item
-The @code{kill-region} function can no longer be used in read-only
-buffers. The @code{compare-buffer-substrings} and @code{current-kill}
-functions have been removed.
-
-@item
-The variable @code{overwrite-mode-binary} has been removed.
-
-@item
-The function @code{move-to-column} allows just one argument,
-@var{column}.
-
-@item
-The search functions now just return @code{t} when successful. This
-affects the functions @code{search-forward}, @code{search-backward},
-@code{word-search-forward}, @code{word-search-backward},
-@code{re-search-forward}, and @code{re-search-backward}.
-
-@item
-When you do regular expression searching or matching, there is a fixed
-limit of ten @samp{\(@dots{}\)} pairs that you can get information about
-with @code{match-beginning} and @code{match-end}. Moreover,
-@code{save-match-data} does not exist; you must use an explicit
-@code{unwind-protect} to save the match data.
-
-@item
-@code{translate-region} is gone.
-
-@item
-The variables @code{before-change-function},
-@code{after-change-function}, and @code{first-change-hook} have been
-eliminated.
-
-@item
-The second argument to @code{insert-abbrev-table-description} is no
-longer optional.
-@end itemize
-
-@section Text Properties
-
-We eliminated text properties.
-
-@section Features for Files
-
-Many file-related functions have been eliminated or simplified. Here is
-a basic listing of these functions.
-
-@itemize @bullet
-@item
-The functions @code{file-accessible-directory-p}, @code{file-truename},
-@code{make-directory}, @code{delete-directory},
-@code{set-visited-file-modtime}, @code{directory-abbrev-alist},
-@code{abbreviate-file-name}, @code{write-region},
-@code{write-contents-hooks}, @code{after-save-hook},
-@code{set-default-file-modes}, @code{default-file-modes}, and
-@code{unix-sync} have been eliminated.
-
-@item
-We got rid of the ``initial file name'' argument to
-@code{read-file-name}.
-
-@item
-Additionally, we removed the 12th element from the list returned by
-@code{file-attributes}.
-
-@item
-@code{directory-files} always sorts the list of files. It's not user
-friendly to process the files in any haphazard order.
-
-@item
-We eliminated the variables @code{write-contents-hooks} and
-@code{local-write-file-hooks}.
-@end itemize
-
-@section Making Certain File Names ``Magic''
-
-There are no more magic filenames. Sorry, but all the mana has been
-used up.
-
-@section Frames
-
-There is only one frame in Emacs 18, so all of the frame functions have
-been eliminated.
-
-@section X Window System Features
-
-We have simplified the way Emacs and X interact by removing a great deal
-of creeping featurism.
-
-@itemize @bullet
-@item
-The functions @code{mouse-position} and @code{set-mouse-position}, and
-the special form @code{track-mouse}, have been eliminated.
-
-@item
-Likewise, the functions @code{x-set-selection}, @code{x-set-cut-buffer},
-@code{x-close-current-connection}, and @code{x-open-connection} have all
-been removed from Emacs Lisp 18.
-
-@item
-We removed a series of functions that gave information about the X
-server and the screen you were using; after all, the whole point of X is
-that all servers are equivalent. The names of the removed functions
-are: @code{x-display-screens}, @code{x-server-version},
-@code{x-server-vendor}, @code{x-display-pixel-height},
-@code{x-display-mm-height}, @code{x-display-pixel-width},
-@code{x-display-mm-width}, @code{x-display-backing-store},
-@code{x-display-save-under}, @code{x-display-planes},
-@code{x-display-visual-class}, @code{x-display-color-p}, and
-@code{x-display-color-cells}.
-
-@item
-Additionally, we removed the variable @code{x-no-window-manager} and the
-functions @code{x-synchronize} and @code{x-get-resource}.
-
-@item
-We didn't abolish @code{x-display-color-p}, but we renamed it to
-@code{x-color-display-p}. We did abolish @code{x-color-defined-p}.
-
-@item
-@code{x-popup-menu} no longer accepts a keymap for its first argument.
-
-@item
-We removed both the function @code{x-rebind-key} and the related
-function @code{x-rebind-keys}.
-
-@item
-We abolished @code{x-parse-geometry}.
-@end itemize
-
-@section Window Actions that Were No Longer Useful
-
-Various behaviors of windows in Emacs 19 were obsolete by the time Emacs
-18 was due to come out. We have removed them. These changes are listed
-below.
-
-@itemize @bullet
-@item
-We removed the functions @code{window-at}, @code{window-minibuffer-p},
-@code{set-window-dedicated-p}, @code{coordinates-in-window-p},
-@code{walk-windows}, @code{window-dedicated-p}, and @code{window-end}.
-
-@item
-We removed the variables @code{pop-up-frames},
-@code{pop-up-frame-function}, @code{display-buffer-function}, and
-@code{other-window-scroll-buffer}.
-
-@item
-The function @code{minibuffer-window} no longer accepts a frame as
-argument, since frames as objects do not exist in Emacs version 18. It
-returns the window used for minibuffers.
-
-@item
-The functions @code{next-window} and @code{previous-window} no longer
-accept the @var{all-frames} argument since there is just one frame.
-
-@item
-The functions @code{get-lru-window}, @code{get-largest-window},
-@code{get-buffer-window}, and @code{get-buffer-window} also no longer
-take the optional argument @var{all-frames} because there is just one
-frame to search.
-@end itemize
-
-@section Display Features
-
-@itemize @bullet
-@item
-There are no overlays, and no faces.
-
-@item
-We eliminated the mode line spec @samp{%l} that in later versions used
-to display the current line number. We removed the variables
-@code{line-number-mode} and @code{line-number-display-limit}.
-
-@item
-@code{baud-rate} is now a function rather than a variable.
-
-@item
-You can no longer call @code{message} with @code{nil} as the only
-argument; therefore, you can not reliably make the contents of the
-minibuffer visible.
-
-@item
-The variable @code{temp-buffer-show-function} has been renamed
-@code{temp-buffer-show-hook}.
-
-@item
-We removed the function @code{force-mode-line-update}. Use
-the following idiom instead:
-
-@example
-(set-buffer-modified-p (buffer-modified-p))
-@end example
-
-@item
-Display tables no longer exist. We know what the @sc{ASCII} characters
-should look like, and we made them look that way.
-@end itemize
-
-@section Working with Input Events
-
-The big news about input events is that we got rid of function key
-and mouse events. Now the only input events are characters.
-What's more, these characters now have to be in the range of 0 to 127,
-optionally with a meta bit. This makes for big simplifications.
-
-@itemize @bullet
-@item
-Functions like @code{define-key}, @code{global-set-key},
-@code{read-key-sequence}, and @code{local-set-key} used to accept
-strings or vectors in Emacs 19; now they only accept strings.
-
-@item
-The documentation functions (@code{single-key-description},
-@code{key-description}, etc.) also no longer accept vectors, but they do
-accept strings.
-
-@item
-We removed the @code{read-event}, @code{event-start},
-@code{posn-window}, @code{posn-point}, @code{posn-col-row},
-@code{posn-timestamp}, @code{scroll-bar-scale}, and @code{event-end}
-functions, since they were useful only for non-character events.
-
-@item
-We removed the @code{unread-command-events} and @code{last-event-frame}
-variables.
-
-@item
-The functions @code{this-command-keys} and @code{recent-keys} now always
-return a string. Likewise, a keyboard macro's definition can only be a
-string, not a vector.
-
-@item
-We eliminated @samp{e} as an interactive specification since it
-was useful only with non-character events.
-
-@item
-In Emacs 18, we represent Meta characters as character objects with the
-same encoding used in strings: 128 plus the corresponding non-Meta
-@sc{ASCII} character.
-@end itemize
-
-@section Menus
-
-@itemize @bullet
-@item
-You can no longer define menus as keymaps; good system design requires
-crafting a special-purpose interface for each facility, so it can
-precisely fit the requirements of that facility. We decided that
-unifying keymaps and menus was simply too much of a strain.
-
-@item
-In Emacs 18, you can activate menus only with the mouse. Using them
-with a keyboard was too confusing for too many users.
-
-@item
-Emacs 18 has no menu bars. All functions and variables related to the
-menu bar have been eliminated.
-@end itemize
-
-@section Changes in Minibuffer Features
-
-@itemize @bullet
-@item
-The minibuffer history feature has been eliminated. Thus, we removed
-the optional argument @var{hist} from the minibuffer input functions
-@code{read-from-minibuffer} and @code{completing-read}.
-
-@item
-The @var{initial} argument to @code{read-from-minibuffer} and other
-minibuffer input functions can no longer be a cons cell
-@code{(@var{string} . @var{position})}.
-
-@item
-In the function @code{read-no-blanks-input}, the @var{initial} argument
-is no longer optional.
-@end itemize
-
-@section New Features for Defining Commands
-
-@itemize @bullet
-@item
-The special meaning of @samp{@@} in an interactive specification has
-been eliminated.
-
-@item
-Emacs 18 does not support use of format-style @samp{%}-sequences in the
-prompt strings in interactive specifications.
-
-@item
-The property @code{enable-recursive-minibuffers} no longer has any
-special meaning.
-@end itemize
-
-@section Removed Features for Reading Input
-
-@itemize @bullet
-@item
-We removed the third argument (@var{meta}) from the function
-@code{set-input-mode}. Consequently, we added the variable
-@code{meta-flag}; set it to @code{t} to enable use of a Meta key, and
-to @code{nil} to disable it. (Those are the only two alternatives.)
-
-@item
-We also removed the variable @code{extra-keyboard-modifiers}.
-
-@item
-We removed the function @code{keyboard-translate} and the variables
-@code{num-input-keys} and @code{function-key-map}.
-@end itemize
-
-@section Removed Syntax Table Features
-
-@itemize @bullet
-@item
-We eliminated the functions @code{skip-syntax-forward},
-@code{skip-syntax-backward}, @code{forward-comment}.
-
-@item
-We removed the syntax flag for ``prefix syntax'' and the flag for the
-alternate comment style. Emacs 18 supports only one style of comment
-in any given syntax table.
-
-@item
-We abolished the variable @code{words-include-escapes}.
-@end itemize
-
-@section The Case Table
-
-@itemize @bullet
-@item
-Case tables do not exist in Emacs 18. Due to this change, we have
-removed the associated functions @code{set-standard-case-table},
-@code{standard-case-table}, @code{current-case-table},
-@code{set-case-table}, and @code{set-case-syntax-pair}.
-@end itemize
-
-@section Features for Dealing with Buffers
-
-@itemize @bullet
-@item
-We eliminated several functions for dealing with buffers:
-@code{buffer-modified-tick} and @code{generate-new-buffer-name}.
-
-@item
-We renamed @code{buffer-disable-undo} to @code{buffer-flush-undo}---a
-more picturesque name, you will agree.
-
-@item
-The function @code{other-buffer} takes just one argument in Emacs 18.
-
-@item
-The function @code{rename-buffer} now requires you to specify precisely
-the new name you want.
-
-@item
-We removed the local variable @code{list-buffers-directory}.
-
-@item
-We got rid of the hook @code{kill-buffer-hook}.
-@end itemize
-
-@section Local Variables Features
-
-@itemize @bullet
-@item
-The function @code{kill-all-local-variables} always eliminates all
-buffer-local variables of the current buffer. No more exceptions.
-
-@item
-Making a variable buffer-local when it is void now sets it to
-@code{nil}.
-
-@item
-We eliminated the functions @code{default-boundp}, because it is no
-longer possible for the default binding of a variable to be void.
-
-@item
-The special forms @code{defconst} and @code{defvar} now set the
-variable's local value rather than its default value when the variable
-is local in the current buffer.
-@end itemize
-
-@section Features for Subprocesses
-
-@itemize @bullet
-@item
-@code{call-process} and @code{call-process-region} no longer indicate
-the termination status of the subprocess. We call on users to have faith
-that the subprocess executed properly.
-
-@item
-The standard asynchronous subprocess features do not work on VMS;
-instead, special VMS asynchronous subprocess functions have been added.
-Since they are only for VMS, we can't be bothered documenting them;
-sorry. Use the source, Luke!
-
-@item
-The function @code{signal-process} has been removed.
-
-@item
-We eliminated the transaction queue feature, and the associated
-functions @code{tq-create}, @code{tq-enqueue}, and @code{tq-close}.
-@end itemize
-
-@section Dealing with Times And Time Delays
-
-@itemize @bullet
-@item
-We removed the functions @code{current-time}, @code{current-time-zone},
-@code{run-at-time}, and @code{cancel-timer}.
-
-@item
-The function @code{current-time-string} no longer accepts any optional
-arguments.
-
-@item
-The functions @code{sit-for} and @code{sleep-for} no longer allow an
-optional argument to let you specify the time period in milliseconds;
-just in seconds. Additionally, we took out the optional third argument
-@var{nodisp} from @code{sit-for}.
-
-@item
-We removed the optional second and third arguments from the
-@code{accept-process-output} function. It accepts just one argument,
-the process.
-@end itemize
-
-@need 3000
-
-@section Features not Available for Lisp Debuggers
-
-@itemize @bullet
-@item
-In Emacs 18, you can no longer specify to invoke the Lisp debugger only
-upon encountering certain types of errors. Any non-@code{nil} value for
-the variable @code{debug-on-error} says to invoke the debugger for any
-error whatever.
-
-@item
-We removed the variable @code{command-debug-status} and the function
-@code{backtrace-frame}.
-@end itemize
-
-@section Memory Allocation Changes
-
-@itemize @bullet
-@item
-We removed the function @code{memory-limit}.
-
-@item
-The list returned by @code{garbage-collect} no longer contains an
-element to describe floating point numbers, since there aren't any
-floating point numbers in Emacs 18.
-@end itemize
-
-@section Hook Changes
-
-@itemize @bullet
-@item
-We removed the hooks @code{pre-abbrev-expand-hook},
-@code{pre-command-hook}, @code{post-command-hook}, and
-@code{auto-save-hook}.
-
-@item
-We removed the variable
-@code{revert-buffer-insert-file-contents-function}.
-
-@item
-We also removed the new function @code{add-hook}; you will have to set
-your hooks by hand. If you want to get really into the swing of things,
-set your hook variables the archaic way: store just one function rather
-than a list of functions. But that is optional.
-
-@item
-The variable @code{lisp-indent-hook} has been renamed to
-@code{lisp-indent-function}.
-
-@item
-The variable @code{auto-fill-function} has been renamed to
-@code{auto-fill-hook}.
-
-@item
-The @code{blink-paren-function} has been renamed to
-@code{blink-paren-hook}.
-
-@item
-The variable @code{temp-buffer-show-function} has been renamed to
-@code{temp-buffer-show-hook}.
-@end itemize
diff --git a/lispref/backups.texi b/lispref/backups.texi
deleted file mode 100644
index d25908fe57c..00000000000
--- a/lispref/backups.texi
+++ /dev/null
@@ -1,648 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/backups
-@node Backups and Auto-Saving, Buffers, Files, Top
-@chapter Backups and Auto-Saving
-
- Backup files and auto-save files are two methods by which Emacs tries
-to protect the user from the consequences of crashes or of the user's
-own errors. Auto-saving preserves the text from earlier in the current
-editing session; backup files preserve file contents prior to the
-current session.
-
-@menu
-* Backup Files:: How backup files are made; how their names are chosen.
-* Auto-Saving:: How auto-save files are made; how their names are chosen.
-* Reverting:: @code{revert-buffer}, and how to customize what it does.
-@end menu
-
-@node Backup Files
-@section Backup Files
-@cindex backup file
-
- A @dfn{backup file} is a copy of the old contents of a file you are
-editing. Emacs makes a backup file the first time you save a buffer
-into its visited file. Normally, this means that the backup file
-contains the contents of the file as it was before the current editing
-session. The contents of the backup file normally remain unchanged once
-it exists.
-
- Backups are usually made by renaming the visited file to a new name.
-Optionally, you can specify that backup files should be made by copying
-the visited file. This choice makes a difference for files with
-multiple names; it also can affect whether the edited file remains owned
-by the original owner or becomes owned by the user editing it.
-
- By default, Emacs makes a single backup file for each file edited.
-You can alternatively request numbered backups; then each new backup
-file gets a new name. You can delete old numbered backups when you
-don't want them any more, or Emacs can delete them automatically.
-
-@menu
-* Making Backups:: How Emacs makes backup files, and when.
-* Rename or Copy:: Two alternatives: renaming the old file or copying it.
-* Numbered Backups:: Keeping multiple backups for each source file.
-* Backup Names:: How backup file names are computed; customization.
-@end menu
-
-@node Making Backups
-@subsection Making Backup Files
-
-@defun backup-buffer
- This function makes a backup of the file visited by the current
-buffer, if appropriate. It is called by @code{save-buffer} before
-saving the buffer the first time.
-@end defun
-
-@defvar buffer-backed-up
- This buffer-local variable indicates whether this buffer's file has
-been backed up on account of this buffer. If it is non-@code{nil}, then
-the backup file has been written. Otherwise, the file should be backed
-up when it is next saved (if backups are enabled). This is a
-permanent local; @code{kill-local-variables} does not alter it.
-@end defvar
-
-@defopt make-backup-files
-This variable determines whether or not to make backup files. If it
-is non-@code{nil}, then Emacs creates a backup of each file when it is
-saved for the first time---provided that @code{backup-inhibited}
-is @code{nil} (see below).
-
-The following example shows how to change the @code{make-backup-files}
-variable only in the @file{RMAIL} buffer and not elsewhere. Setting it
-@code{nil} stops Emacs from making backups of the @file{RMAIL} file,
-which may save disk space. (You would put this code in your
-@file{.emacs} file.)
-
-@smallexample
-@group
-(add-hook 'rmail-mode-hook
- (function (lambda ()
- (make-local-variable
- 'make-backup-files)
- (setq make-backup-files nil))))
-@end group
-@end smallexample
-@end defopt
-
-@defvar backup-enable-predicate
-This variable's value is a function to be called on certain occasions to
-decide whether a file should have backup files. The function receives
-one argument, a file name to consider. If the function returns
-@code{nil}, backups are disabled for that file. Otherwise, the other
-variables in this section say whether and how to make backups.
-
-The default value is this:
-
-@example
-(lambda (name)
- (or (< (length name) 5)
- (not (string-equal "/tmp/"
- (substring name 0 5)))))
-@end example
-@end defvar
-
-@defvar backup-inhibited
-If this variable is non-@code{nil}, backups are inhibited. It records
-the result of testing @code{backup-enable-predicate} on the visited file
-name. It can also coherently be used by other mechanisms that inhibit
-backups based on which file is visited. For example, VC sets this
-variable non-@code{nil} to prevent making backups for files managed
-with a version control system.
-
-This is a permanent local, so that changing the major mode does not lose
-its value. Major modes should not set this variable---they should set
-@code{make-backup-files} instead.
-@end defvar
-
-@node Rename or Copy
-@subsection Backup by Renaming or by Copying?
-@cindex backup files, how to make them
-
- There are two ways that Emacs can make a backup file:
-
-@itemize @bullet
-@item
-Emacs can rename the original file so that it becomes a backup file, and
-then write the buffer being saved into a new file. After this
-procedure, any other names (i.e., hard links) of the original file now
-refer to the backup file. The new file is owned by the user doing the
-editing, and its group is the default for new files written by the user
-in that directory.
-
-@item
-Emacs can copy the original file into a backup file, and then overwrite
-the original file with new contents. After this procedure, any other
-names (i.e., hard links) of the original file still refer to the current
-version of the file. The file's owner and group will be unchanged.
-@end itemize
-
- The first method, renaming, is the default.
-
- The variable @code{backup-by-copying}, if non-@code{nil}, says to use
-the second method, which is to copy the original file and overwrite it
-with the new buffer contents. The variable @code{file-precious-flag},
-if non-@code{nil}, also has this effect (as a sideline of its main
-significance). @xref{Saving Buffers}.
-
-@defvar backup-by-copying
-If this variable is non-@code{nil}, Emacs always makes backup files by
-copying.
-@end defvar
-
- The following two variables, when non-@code{nil}, cause the second
-method to be used in certain special cases. They have no effect on the
-treatment of files that don't fall into the special cases.
-
-@defvar backup-by-copying-when-linked
-If this variable is non-@code{nil}, Emacs makes backups by copying for
-files with multiple names (hard links).
-
-This variable is significant only if @code{backup-by-copying} is
-@code{nil}, since copying is always used when that variable is
-non-@code{nil}.
-@end defvar
-
-@defvar backup-by-copying-when-mismatch
-If this variable is non-@code{nil}, Emacs makes backups by copying in cases
-where renaming would change either the owner or the group of the file.
-
-The value has no effect when renaming would not alter the owner or
-group of the file; that is, for files which are owned by the user and
-whose group matches the default for a new file created there by the
-user.
-
-This variable is significant only if @code{backup-by-copying} is
-@code{nil}, since copying is always used when that variable is
-non-@code{nil}.
-@end defvar
-
-@node Numbered Backups
-@subsection Making and Deleting Numbered Backup Files
-
- If a file's name is @file{foo}, the names of its numbered backup
-versions are @file{foo.~@var{v}~}, for various integers @var{v}, like
-this: @file{foo.~1~}, @file{foo.~2~}, @file{foo.~3~}, @dots{},
-@file{foo.~259~}, and so on.
-
-@defopt version-control
-This variable controls whether to make a single non-numbered backup
-file or multiple numbered backups.
-
-@table @asis
-@item @code{nil}
-Make numbered backups if the visited file already has numbered backups;
-otherwise, do not.
-
-@item @code{never}
-Do not make numbered backups.
-
-@item @var{anything else}
-Make numbered backups.
-@end table
-@end defopt
-
- The use of numbered backups ultimately leads to a large number of
-backup versions, which must then be deleted. Emacs can do this
-automatically or it can ask the user whether to delete them.
-
-@defopt kept-new-versions
-The value of this variable is the number of newest versions to keep
-when a new numbered backup is made. The newly made backup is included
-in the count. The default value is 2.
-@end defopt
-
-@defopt kept-old-versions
-The value of this variable is the number of oldest versions to keep
-when a new numbered backup is made. The default value is 2.
-@end defopt
-
- If there are backups numbered 1, 2, 3, 5, and 7, and both of these
-variables have the value 2, then the backups numbered 1 and 2 are kept
-as old versions and those numbered 5 and 7 are kept as new versions;
-backup version 3 is excess. The function @code{find-backup-file-name}
-(@pxref{Backup Names}) is responsible for determining which backup
-versions to delete, but does not delete them itself.
-
-@defopt trim-versions-without-asking
-If this variable is non-@code{nil}, then saving a file deletes excess
-backup versions silently. Otherwise, it asks the user whether to delete
-them.
-@end defopt
-
-@defopt dired-kept-versions
-This variable specifies how many of the newest backup versions to keep
-in the Dired command @kbd{.} (@code{dired-clean-directory}). That's the
-same thing @code{kept-new-versions} specifies when you make a new backup
-file. The default value is 2.
-@end defopt
-
-@node Backup Names
-@subsection Naming Backup Files
-
- The functions in this section are documented mainly because you can
-customize the naming conventions for backup files by redefining them.
-If you change one, you probably need to change the rest.
-
-@defun backup-file-name-p filename
-This function returns a non-@code{nil} value if @var{filename} is a
-possible name for a backup file. A file with the name @var{filename}
-need not exist; the function just checks the name.
-
-@smallexample
-@group
-(backup-file-name-p "foo")
- @result{} nil
-@end group
-@group
-(backup-file-name-p "foo~")
- @result{} 3
-@end group
-@end smallexample
-
-The standard definition of this function is as follows:
-
-@smallexample
-@group
-(defun backup-file-name-p (file)
- "Return non-nil if FILE is a backup file \
-name (numeric or not)..."
- (string-match "~$" file))
-@end group
-@end smallexample
-
-@noindent
-Thus, the function returns a non-@code{nil} value if the file name ends
-with a @samp{~}. (We use a backslash to split the documentation
-string's first line into two lines in the text, but produce just one
-line in the string itself.)
-
-This simple expression is placed in a separate function to make it easy
-to redefine for customization.
-@end defun
-
-@defun make-backup-file-name filename
-This function returns a string that is the name to use for a
-non-numbered backup file for file @var{filename}. On Unix, this is just
-@var{filename} with a tilde appended.
-
-The standard definition of this function is as follows:
-
-@smallexample
-@group
-(defun make-backup-file-name (file)
- "Create the non-numeric backup file name for FILE.
-@dots{}"
- (concat file "~"))
-@end group
-@end smallexample
-
-You can change the backup-file naming convention by redefining this
-function. The following example redefines @code{make-backup-file-name}
-to prepend a @samp{.} in addition to appending a tilde:
-
-@smallexample
-@group
-(defun make-backup-file-name (filename)
- (concat "." filename "~"))
-@end group
-
-@group
-(make-backup-file-name "backups.texi")
- @result{} ".backups.texi~"
-@end group
-@end smallexample
-@end defun
-
-@defun find-backup-file-name filename
-This function computes the file name for a new backup file for
-@var{filename}. It may also propose certain existing backup files for
-deletion. @code{find-backup-file-name} returns a list whose @sc{car} is
-the name for the new backup file and whose @sc{cdr} is a list of backup
-files whose deletion is proposed.
-
-Two variables, @code{kept-old-versions} and @code{kept-new-versions},
-determine which backup versions should be kept. This function keeps
-those versions by excluding them from the @sc{cdr} of the value.
-@xref{Numbered Backups}.
-
-In this example, the value says that @file{~rms/foo.~5~} is the name
-to use for the new backup file, and @file{~rms/foo.~3~} is an ``excess''
-version that the caller should consider deleting now.
-
-@smallexample
-@group
-(find-backup-file-name "~rms/foo")
- @result{} ("~rms/foo.~5~" "~rms/foo.~3~")
-@end group
-@end smallexample
-@end defun
-
-@c Emacs 19 feature
-@defun file-newest-backup filename
-This function returns the name of the most recent backup file for
-@var{filename}, or @code{nil} if that file has no backup files.
-
-Some file comparison commands use this function so that they can
-automatically compare a file with its most recent backup.
-@end defun
-
-@node Auto-Saving
-@section Auto-Saving
-@cindex auto-saving
-
- Emacs periodically saves all files that you are visiting; this is
-called @dfn{auto-saving}. Auto-saving prevents you from losing more
-than a limited amount of work if the system crashes. By default,
-auto-saves happen every 300 keystrokes, or after around 30 seconds of
-idle time. @xref{Auto-Save, Auto-Save, Auto-Saving: Protection Against
-Disasters, emacs, The GNU Emacs Manual}, for information on auto-save
-for users. Here we describe the functions used to implement auto-saving
-and the variables that control them.
-
-@defvar buffer-auto-save-file-name
-This buffer-local variable is the name of the file used for
-auto-saving the current buffer. It is @code{nil} if the buffer
-should not be auto-saved.
-
-@example
-@group
-buffer-auto-save-file-name
-=> "/xcssun/users/rms/lewis/#files.texi#"
-@end group
-@end example
-@end defvar
-
-@deffn Command auto-save-mode arg
-When used interactively without an argument, this command is a toggle
-switch: it turns on auto-saving of the current buffer if it is off, and
-vice-versa. With an argument @var{arg}, the command turns auto-saving
-on if the value of @var{arg} is @code{t}, a nonempty list, or a positive
-integer. Otherwise, it turns auto-saving off.
-@end deffn
-
-@defun auto-save-file-name-p filename
-This function returns a non-@code{nil} value if @var{filename} is a
-string that could be the name of an auto-save file. It works based on
-knowledge of the naming convention for auto-save files: a name that
-begins and ends with hash marks (@samp{#}) is a possible auto-save file
-name. The argument @var{filename} should not contain a directory part.
-
-@example
-@group
-(make-auto-save-file-name)
- @result{} "/xcssun/users/rms/lewis/#files.texi#"
-@end group
-@group
-(auto-save-file-name-p "#files.texi#")
- @result{} 0
-@end group
-@group
-(auto-save-file-name-p "files.texi")
- @result{} nil
-@end group
-@end example
-
-The standard definition of this function is as follows:
-
-@example
-@group
-(defun auto-save-file-name-p (filename)
- "Return non-nil if FILENAME can be yielded by..."
- (string-match "^#.*#$" filename))
-@end group
-@end example
-
-This function exists so that you can customize it if you wish to
-change the naming convention for auto-save files. If you redefine it,
-be sure to redefine the function @code{make-auto-save-file-name}
-correspondingly.
-@end defun
-
-@defun make-auto-save-file-name
-This function returns the file name to use for auto-saving the current
-buffer. This is just the file name with hash marks (@samp{#}) appended
-and prepended to it. This function does not look at the variable
-@code{auto-save-visited-file-name} (described below); you should check
-that before calling this function.
-
-@example
-@group
-(make-auto-save-file-name)
- @result{} "/xcssun/users/rms/lewis/#backup.texi#"
-@end group
-@end example
-
-The standard definition of this function is as follows:
-
-@example
-@group
-(defun make-auto-save-file-name ()
- "Return file name to use for auto-saves \
-of current buffer.
-@dots{}"
- (if buffer-file-name
-@end group
-@group
- (concat
- (file-name-directory buffer-file-name)
- "#"
- (file-name-nondirectory buffer-file-name)
- "#")
- (expand-file-name
- (concat "#%" (buffer-name) "#"))))
-@end group
-@end example
-
-This exists as a separate function so that you can redefine it to
-customize the naming convention for auto-save files. Be sure to
-change @code{auto-save-file-name-p} in a corresponding way.
-@end defun
-
-@defvar auto-save-visited-file-name
-If this variable is non-@code{nil}, Emacs auto-saves buffers in
-the files they are visiting. That is, the auto-save is done in the same
-file that you are editing. Normally, this variable is @code{nil}, so
-auto-save files have distinct names that are created by
-@code{make-auto-save-file-name}.
-
-When you change the value of this variable, the value does not take
-effect until the next time auto-save mode is reenabled in any given
-buffer. If auto-save mode is already enabled, auto-saves continue to go
-in the same file name until @code{auto-save-mode} is called again.
-@end defvar
-
-@defun recent-auto-save-p
-This function returns @code{t} if the current buffer has been
-auto-saved since the last time it was read in or saved.
-@end defun
-
-@defun set-buffer-auto-saved
-This function marks the current buffer as auto-saved. The buffer will
-not be auto-saved again until the buffer text is changed again. The
-function returns @code{nil}.
-@end defun
-
-@defopt auto-save-interval
-The value of this variable is the number of characters that Emacs
-reads from the keyboard between auto-saves. Each time this many more
-characters are read, auto-saving is done for all buffers in which it is
-enabled.
-@end defopt
-
-@defopt auto-save-timeout
-The value of this variable is the number of seconds of idle time that
-should cause auto-saving. Each time the user pauses for this long,
-Emacs auto-saves any buffers that need it. (Actually, the specified
-timeout is multiplied by a factor depending on the size of the current
-buffer.)
-@end defopt
-
-@defvar auto-save-hook
-This normal hook is run whenever an auto-save is about to happen.
-@end defvar
-
-@defopt auto-save-default
-If this variable is non-@code{nil}, buffers that are visiting files
-have auto-saving enabled by default. Otherwise, they do not.
-@end defopt
-
-@deffn Command do-auto-save &optional no-message current-only
-This function auto-saves all buffers that need to be auto-saved. It
-saves all buffers for which auto-saving is enabled and that have been
-changed since the previous auto-save.
-
-Normally, if any buffers are auto-saved, a message that says
-@samp{Auto-saving...} is displayed in the echo area while auto-saving is
-going on. However, if @var{no-message} is non-@code{nil}, the message
-is inhibited.
-
-If @var{current-only} is non-@code{nil}, only the current buffer
-is auto-saved.
-@end deffn
-
-@defun delete-auto-save-file-if-necessary
-This function deletes the current buffer's auto-save file if
-@code{delete-auto-save-files} is non-@code{nil}. It is called every
-time a buffer is saved.
-@end defun
-
-@defvar delete-auto-save-files
-This variable is used by the function
-@code{delete-auto-save-file-if-necessary}. If it is non-@code{nil},
-Emacs deletes auto-save files when a true save is done (in the visited
-file). This saves disk space and unclutters your directory.
-@end defvar
-
-@defun rename-auto-save-file
-This function adjusts the current buffer's auto-save file name if the
-visited file name has changed. It also renames an existing auto-save
-file. If the visited file name has not changed, this function does
-nothing.
-@end defun
-
-@defvar buffer-saved-size
-The value of this buffer-local variable is the length of the current
-buffer as of the last time it was read in, saved, or auto-saved. This is
-used to detect a substantial decrease in size, and turn off auto-saving
-in response.
-
-If it is -1, that means auto-saving is temporarily shut off in this
-buffer due to a substantial deletion. Explicitly saving the buffer
-stores a positive value in this variable, thus reenabling auto-saving.
-Turning auto-save mode off or on also alters this variable.
-@end defvar
-
-@defvar auto-save-list-file-name
-This variable (if non-@code{nil}) specifies a file for recording the
-names of all the auto-save files. Each time Emacs does auto-saving, it
-writes two lines into this file for each buffer that has auto-saving
-enabled. The first line gives the name of the visited file (it's empty
-if the buffer has none), and the second gives the name of the auto-save
-file.
-
-If Emacs exits normally, it deletes this file. If Emacs crashes, you
-can look in the file to find all the auto-save files that might contain
-work that was otherwise lost. The @code{recover-session} command uses
-these files.
-
-The default name for this file is in your home directory and starts with
-@samp{.saves-}. It also contains the Emacs process @sc{id} and the host
-name.
-@end defvar
-
-@node Reverting
-@section Reverting
-
- 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 with the @code{revert-buffer} command. @xref{Reverting, ,
-Reverting a Buffer, emacs, The GNU Emacs Manual}.
-
-@deffn Command revert-buffer &optional check-auto-save noconfirm
-This command replaces the buffer text with the text of the visited
-file on disk. This action undoes all changes since the file was visited
-or saved.
-
-If the argument @var{check-auto-save} is non-@code{nil}, and the
-latest auto-save file is more recent than the visited file,
-@code{revert-buffer} asks the user whether to use that instead.
-Otherwise, it always uses the text of the visited file itself.
-Interactively, @var{check-auto-save} is set if there is a numeric prefix
-argument.
-
-Normally, @code{revert-buffer} asks for confirmation before it changes
-the buffer; but if the argument @var{noconfirm} is non-@code{nil},
-@code{revert-buffer} does not ask for confirmation.
-
-Reverting tries to preserve marker positions in the buffer by using the
-replacement feature of @code{insert-file-contents}. If the buffer
-contents and the file contents are identical before the revert
-operation, reverting preserves all the markers. If they are not
-identical, reverting does change the buffer; then it preserves the
-markers in the unchanged text (if any) at the beginning and end of the
-buffer. Preserving any additional markers would be problematical.
-@end deffn
-
-You can customize how @code{revert-buffer} does its work by setting
-these variables---typically, as buffer-local variables.
-
-@defvar revert-buffer-function
-The value of this variable is the function to use to revert this buffer.
-If non-@code{nil}, it is called as a function with no arguments to do
-the work of reverting. If the value is @code{nil}, reverting works the
-usual way.
-
-Modes such as Dired mode, in which the text being edited does not
-consist of a file's contents but can be regenerated in some other
-fashion, give this variable a buffer-local value that is a function to
-regenerate the contents.
-@end defvar
-
-@defvar revert-buffer-insert-file-contents-function
-The value of this variable, if non-@code{nil}, is the function to use to
-insert the updated contents when reverting this buffer. The function
-receives two arguments: first the file name to use; second, @code{t} if
-the user has asked to read the auto-save file.
-@end defvar
-
-@defvar before-revert-hook
-This normal hook is run by @code{revert-buffer} before actually
-inserting the modified contents---but only if
-@code{revert-buffer-function} is @code{nil}.
-
-Font Lock mode uses this hook to record that the buffer contents are no
-longer fontified.
-@end defvar
-
-@defvar after-revert-hook
-This normal hook is run by @code{revert-buffer} after actually inserting
-the modified contents---but only if @code{revert-buffer-function} is
-@code{nil}.
-
-Font Lock mode uses this hook to recompute the fonts for the updated
-buffer contents.
-@end defvar
-
diff --git a/lispref/book-spine.texinfo b/lispref/book-spine.texinfo
deleted file mode 100644
index 8633d477aca..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 19.25
-@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/lispref/buffers.texi b/lispref/buffers.texi
deleted file mode 100644
index de2d43052d9..00000000000
--- a/lispref/buffers.texi
+++ /dev/null
@@ -1,911 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/buffers
-@node Buffers, Windows, Backups and Auto-Saving, Top
-@chapter Buffers
-@cindex buffer
-
- A @dfn{buffer} is a Lisp object containing text to be edited. Buffers
-are used to hold the contents of files that are being visited; there may
-also be buffers that are not visiting files. While several buffers may
-exist at one time, exactly one buffer is designated the @dfn{current
-buffer} at any time. Most editing commands act on the contents of the
-current buffer. Each buffer, including the current buffer, may or may
-not be displayed in any windows.
-
-@menu
-* Buffer Basics:: What is a buffer?
-* Current Buffer:: Designating a buffer as current
- so primitives will access its contents.
-* Buffer Names:: Accessing and changing buffer names.
-* Buffer File Name:: The buffer file name indicates which file is visited.
-* Buffer Modification:: A buffer is @dfn{modified} if it needs to be saved.
-* Modification Time:: Determining whether the visited file was changed
- ``behind Emacs's back''.
-* Read Only Buffers:: Modifying text is not allowed in a read-only buffer.
-* The Buffer List:: How to look at all the existing buffers.
-* Creating Buffers:: Functions that create buffers.
-* Killing Buffers:: Buffers exist until explicitly killed.
-* Indirect Buffers:: An indirect buffer shares text with some other buffer.
-@end menu
-
-@node Buffer Basics
-@comment node-name, next, previous, up
-@section Buffer Basics
-
-@ifinfo
- A @dfn{buffer} is a Lisp object containing text to be edited. Buffers
-are used to hold the contents of files that are being visited; there may
-also be buffers that are not visiting files. While several buffers may
-exist at one time, exactly one buffer is designated the @dfn{current
-buffer} at any time. Most editing commands act on the contents of the
-current buffer. Each buffer, including the current buffer, may or may
-not be displayed in any windows.
-@end ifinfo
-
- Buffers in Emacs editing are objects that have distinct names and hold
-text that can be edited. Buffers appear to Lisp programs as a special
-data type. You can think of the contents of a buffer as an extendable
-string; insertions and deletions may occur in any part of the buffer.
-@xref{Text}.
-
- A Lisp buffer object contains numerous pieces of information. Some of
-this information is directly accessible to the programmer through
-variables, while other information is accessible only through
-special-purpose functions. For example, the visited file name is
-directly accessible through a variable, while the value of point is
-accessible only through a primitive function.
-
- Buffer-specific information that is directly accessible is stored in
-@dfn{buffer-local} variable bindings, which are variable values that are
-effective only in a particular buffer. This feature allows each buffer
-to override the values of certain variables. Most major modes override
-variables such as @code{fill-column} or @code{comment-column} in this
-way. For more information about buffer-local variables and functions
-related to them, see @ref{Buffer-Local Variables}.
-
- For functions and variables related to visiting files in buffers, see
-@ref{Visiting Files} and @ref{Saving Buffers}. For functions and
-variables related to the display of buffers in windows, see
-@ref{Buffers and Windows}.
-
-@defun bufferp object
-This function returns @code{t} if @var{object} is a buffer,
-@code{nil} otherwise.
-@end defun
-
-@node Current Buffer
-@section The Current Buffer
-@cindex selecting a buffer
-@cindex changing to another buffer
-@cindex current buffer
-
- There are, in general, many buffers in an Emacs session. At any time,
-one of them is designated as the @dfn{current buffer}. This is the
-buffer in which most editing takes place, because most of the primitives
-for examining or changing text in a buffer operate implicitly on the
-current buffer (@pxref{Text}). Normally the buffer that is displayed on
-the screen in the selected window is the current buffer, but this is not
-always so: a Lisp program can designate any buffer as current
-temporarily in order to operate on its contents, without changing what
-is displayed on the screen.
-
- The way to designate a current buffer in a Lisp program is by calling
-@code{set-buffer}. The specified buffer remains current until a new one
-is designated.
-
- When an editing command returns to the editor command loop, the
-command loop designates the buffer displayed in the selected window as
-current, to prevent confusion: the buffer that the cursor is in when
-Emacs reads a command is the buffer that the command will apply to.
-(@xref{Command Loop}.) Therefore, @code{set-buffer} is not the way to
-switch visibly to a different buffer so that the user can edit it. For
-this, you must use the functions described in @ref{Displaying Buffers}.
-
- However, Lisp functions that change to a different current buffer
-should not depend on the command loop to set it back afterwards.
-Editing commands written in Emacs Lisp can be called from other programs
-as well as from the command loop. It is convenient for the caller if
-the subroutine does not change which buffer is current (unless, of
-course, that is the subroutine's purpose). Therefore, you should
-normally use @code{set-buffer} within a @code{save-excursion} that will
-restore the current buffer when your function is done
-(@pxref{Excursions}). Here is an example, the code for the command
-@code{append-to-buffer} (with the documentation string abridged):
-
-@example
-@group
-(defun append-to-buffer (buffer start end)
- "Append to specified buffer the text of the region.
-@dots{}"
- (interactive "BAppend to buffer: \nr")
- (let ((oldbuf (current-buffer)))
- (save-excursion
- (set-buffer (get-buffer-create buffer))
- (insert-buffer-substring oldbuf start end))))
-@end group
-@end example
-
-@noindent
-This function binds a local variable to the current buffer, and then
-@code{save-excursion} records the values of point, the mark, and the
-original buffer. Next, @code{set-buffer} makes another buffer current.
-Finally, @code{insert-buffer-substring} copies the string from the
-original current buffer to the new current buffer.
-
- If the buffer appended to happens to be displayed in some window,
-the next redisplay will show how its text has changed. Otherwise, you
-will not see the change immediately on the screen. The buffer becomes
-current temporarily during the execution of the command, but this does
-not cause it to be displayed.
-
- If you make local bindings (with @code{let} or function arguments) for
-a variable that may also have buffer-local bindings, make sure that the
-same buffer is current at the beginning and at the end of the local
-binding's scope. Otherwise you might bind it in one buffer and unbind
-it in another! There are two ways to do this. In simple cases, you may
-see that nothing ever changes the current buffer within the scope of the
-binding. Otherwise, use @code{save-excursion} to make sure that the
-buffer current at the beginning is current again whenever the variable
-is unbound.
-
- It is not reliable to change the current buffer back with
-@code{set-buffer}, because that won't do the job if a quit happens while
-the wrong buffer is current. Here is what @emph{not} to do:
-
-@example
-@group
-(let (buffer-read-only
- (obuf (current-buffer)))
- (set-buffer @dots{})
- @dots{}
- (set-buffer obuf))
-@end group
-@end example
-
-@noindent
-Using @code{save-excursion}, as shown below, handles quitting, errors,
-and @code{throw}, as well as ordinary evaluation.
-
-@example
-@group
-(let (buffer-read-only)
- (save-excursion
- (set-buffer @dots{})
- @dots{}))
-@end group
-@end example
-
-@defun current-buffer
-This function returns the current buffer.
-
-@example
-@group
-(current-buffer)
- @result{} #<buffer buffers.texi>
-@end group
-@end example
-@end defun
-
-@defun set-buffer buffer-or-name
-This function makes @var{buffer-or-name} the current buffer. It does
-not display the buffer in the currently selected window or in any other
-window, so the user cannot necessarily see the buffer. But Lisp
-programs can in any case work on it.
-
-This function returns the buffer identified by @var{buffer-or-name}.
-An error is signaled if @var{buffer-or-name} does not identify an
-existing buffer.
-@end defun
-
-@node Buffer Names
-@section Buffer Names
-@cindex buffer names
-
- Each buffer has a unique name, which is a string. Many of the
-functions that work on buffers accept either a buffer or a buffer name
-as an argument. Any argument called @var{buffer-or-name} is of this
-sort, and an error is signaled if it is neither a string nor a buffer.
-Any argument called @var{buffer} must be an actual buffer
-object, not a name.
-
- Buffers that are ephemeral and generally uninteresting to the user
-have names starting with a space, so that the @code{list-buffers} and
-@code{buffer-menu} commands don't mention them. A name starting with
-space also initially disables recording undo information; see
-@ref{Undo}.
-
-@defun buffer-name &optional buffer
-This function returns the name of @var{buffer} as a string. If
-@var{buffer} is not supplied, it defaults to the current buffer.
-
-If @code{buffer-name} returns @code{nil}, it means that @var{buffer}
-has been killed. @xref{Killing Buffers}.
-
-@example
-@group
-(buffer-name)
- @result{} "buffers.texi"
-@end group
-
-@group
-(setq foo (get-buffer "temp"))
- @result{} #<buffer temp>
-@end group
-@group
-(kill-buffer foo)
- @result{} nil
-@end group
-@group
-(buffer-name foo)
- @result{} nil
-@end group
-@group
-foo
- @result{} #<killed buffer>
-@end group
-@end example
-@end defun
-
-@deffn Command rename-buffer newname &optional unique
-This function renames the current buffer to @var{newname}. An error
-is signaled if @var{newname} is not a string, or if there is already a
-buffer with that name. The function returns @var{newname}.
-
-@c Emacs 19 feature
-Ordinarily, @code{rename-buffer} signals an error if @var{newname} is
-already in use. However, if @var{unique} is non-@code{nil}, it modifies
-@var{newname} to make a name that is not in use. Interactively, you can
-make @var{unique} non-@code{nil} with a numeric prefix argument.
-
-One application of this command is to rename the @samp{*shell*} buffer
-to some other name, thus making it possible to create a second shell
-buffer under the name @samp{*shell*}.
-@end deffn
-
-@defun get-buffer buffer-or-name
-This function returns the buffer specified by @var{buffer-or-name}.
-If @var{buffer-or-name} is a string and there is no buffer with that
-name, the value is @code{nil}. If @var{buffer-or-name} is a buffer, it
-is returned as given. (That is not very useful, so the argument is usually
-a name.) For example:
-
-@example
-@group
-(setq b (get-buffer "lewis"))
- @result{} #<buffer lewis>
-@end group
-@group
-(get-buffer b)
- @result{} #<buffer lewis>
-@end group
-@group
-(get-buffer "Frazzle-nots")
- @result{} nil
-@end group
-@end example
-
-See also the function @code{get-buffer-create} in @ref{Creating Buffers}.
-@end defun
-
-@c Emacs 19 feature
-@defun generate-new-buffer-name starting-name
-This function returns a name that would be unique for a new buffer---but
-does not create the buffer. It starts with @var{starting-name}, and
-produces a name not currently in use for any buffer by appending a
-number inside of @samp{<@dots{}>}.
-
-See the related function @code{generate-new-buffer} in @ref{Creating
-Buffers}.
-@end defun
-
-@node Buffer File Name
-@section Buffer File Name
-@cindex visited file
-@cindex buffer file name
-@cindex file name of buffer
-
- The @dfn{buffer file name} is the name of the file that is visited in
-that buffer. When a buffer is not visiting a file, its buffer file name
-is @code{nil}. Most of the time, the buffer name is the same as the
-nondirectory part of the buffer file name, but the buffer file name and
-the buffer name are distinct and can be set independently.
-@xref{Visiting Files}.
-
-@defun buffer-file-name &optional buffer
-This function returns the absolute file name of the file that
-@var{buffer} is visiting. If @var{buffer} is not visiting any file,
-@code{buffer-file-name} returns @code{nil}. If @var{buffer} is not
-supplied, it defaults to the current buffer.
-
-@example
-@group
-(buffer-file-name (other-buffer))
- @result{} "/usr/user/lewis/manual/files.texi"
-@end group
-@end example
-@end defun
-
-@defvar buffer-file-name
-This buffer-local variable contains the name of the file being visited
-in the current buffer, or @code{nil} if it is not visiting a file. It
-is a permanent local, unaffected by @code{kill-local-variables}.
-
-@example
-@group
-buffer-file-name
- @result{} "/usr/user/lewis/manual/buffers.texi"
-@end group
-@end example
-
-It is risky to change this variable's value without doing various other
-things. See the definition of @code{set-visited-file-name} in
-@file{files.el}; some of the things done there, such as changing the
-buffer name, are not strictly necessary, but others are essential to
-avoid confusing Emacs.
-@end defvar
-
-@defvar buffer-file-truename
-This buffer-local variable holds the truename of the file visited in the
-current buffer, or @code{nil} if no file is visited. It is a permanent
-local, unaffected by @code{kill-local-variables}. @xref{Truenames}.
-@end defvar
-
-@defvar buffer-file-number
-This buffer-local variable holds the file number and directory device
-number of the file visited in the current buffer, or @code{nil} if no
-file or a nonexistent file is visited. It is a permanent local,
-unaffected by @code{kill-local-variables}. @xref{Truenames}.
-
-The value is normally a list of the form @code{(@var{filenum}
-@var{devnum})}. This pair of numbers uniquely identifies the file among
-all files accessible on the system. See the function
-@code{file-attributes}, in @ref{File Attributes}, for more information
-about them.
-@end defvar
-
-@defun get-file-buffer filename
-This function returns the buffer visiting file @var{filename}. If
-there is no such buffer, it returns @code{nil}. The argument
-@var{filename}, which must be a string, is expanded (@pxref{File Name
-Expansion}), then compared against the visited file names of all live
-buffers.
-
-@example
-@group
-(get-file-buffer "buffers.texi")
- @result{} #<buffer buffers.texi>
-@end group
-@end example
-
-In unusual circumstances, there can be more than one buffer visiting
-the same file name. In such cases, this function returns the first
-such buffer in the buffer list.
-@end defun
-
-@deffn Command set-visited-file-name filename
-If @var{filename} is a non-empty string, this function changes the
-name of the file visited in current buffer to @var{filename}. (If the
-buffer had no visited file, this gives it one.) The @emph{next time}
-the buffer is saved it will go in the newly-specified file. This
-command marks the buffer as modified, since it does not (as far as Emacs
-knows) match the contents of @var{filename}, even if it matched the
-former visited file.
-
-If @var{filename} is @code{nil} or the empty string, that stands for
-``no visited file''. In this case, @code{set-visited-file-name} marks
-the buffer as having no visited file.
-
-@c Wordy to avoid overfull hbox. --rjc 16mar92
-When the function @code{set-visited-file-name} is called interactively, it
-prompts for @var{filename} in the minibuffer.
-
-See also @code{clear-visited-file-modtime} and
-@code{verify-visited-file-modtime} in @ref{Buffer Modification}.
-@end deffn
-
-@defvar list-buffers-directory
-This buffer-local variable records a string to display in a buffer
-listing in place of the visited file name, for buffers that don't have a
-visited file name. Dired buffers use this variable.
-@end defvar
-
-@node Buffer Modification
-@section Buffer Modification
-@cindex buffer modification
-@cindex modification flag (of buffer)
-
- Emacs keeps a flag called the @dfn{modified flag} for each buffer, to
-record whether you have changed the text of the buffer. This flag is
-set to @code{t} whenever you alter the contents of the buffer, and
-cleared to @code{nil} when you save it. Thus, the flag shows whether
-there are unsaved changes. The flag value is normally shown in the mode
-line (@pxref{Mode Line Variables}), and controls saving (@pxref{Saving
-Buffers}) and auto-saving (@pxref{Auto-Saving}).
-
- Some Lisp programs set the flag explicitly. For example, the function
-@code{set-visited-file-name} sets the flag to @code{t}, because the text
-does not match the newly-visited file, even if it is unchanged from the
-file formerly visited.
-
- The functions that modify the contents of buffers are described in
-@ref{Text}.
-
-@defun buffer-modified-p &optional buffer
-This function returns @code{t} if the buffer @var{buffer} has been modified
-since it was last read in from a file or saved, or @code{nil}
-otherwise. If @var{buffer} is not supplied, the current buffer
-is tested.
-@end defun
-
-@defun set-buffer-modified-p flag
-This function marks the current buffer as modified if @var{flag} is
-non-@code{nil}, or as unmodified if the flag is @code{nil}.
-
-Another effect of calling this function is to cause unconditional
-redisplay of the mode line for the current buffer. In fact, the
-function @code{force-mode-line-update} works by doing this:
-
-@example
-@group
-(set-buffer-modified-p (buffer-modified-p))
-@end group
-@end example
-@end defun
-
-@deffn Command not-modified
-This command marks the current buffer as unmodified, and not needing to
-be saved. With prefix arg, it marks the buffer as modified, so that it
-will be saved at the next suitable occasion.
-
-Don't use this function in programs, since it prints a message in the
-echo area; use @code{set-buffer-modified-p} (above) instead.
-@end deffn
-
-@c Emacs 19 feature
-@defun buffer-modified-tick &optional buffer
-This function returns @var{buffer}'s modification-count. This is a
-counter that increments every time the buffer is modified. If
-@var{buffer} is @code{nil} (or omitted), the current buffer is used.
-@end defun
-
-@node Modification Time
-@comment node-name, next, previous, up
-@section Comparison of Modification Time
-@cindex comparison of modification time
-@cindex modification time, comparison of
-
- Suppose that you visit a file and make changes in its buffer, and
-meanwhile the file itself is changed on disk. At this point, saving the
-buffer would overwrite the changes in the file. Occasionally this may
-be what you want, but usually it would lose valuable information. Emacs
-therefore checks the file's modification time using the functions
-described below before saving the file.
-
-@defun verify-visited-file-modtime buffer
-This function compares what @var{buffer} has recorded for the
-modification time of its visited file against the actual modification
-time of the file as recorded by the operating system. The two should be
-the same unless some other process has written the file since Emacs
-visited or saved it.
-
-The function returns @code{t} if the last actual modification time and
-Emacs's recorded modification time are the same, @code{nil} otherwise.
-@end defun
-
-@defun clear-visited-file-modtime
-This function clears out the record of the last modification time of
-the file being visited by the current buffer. As a result, the next
-attempt to save this buffer will not complain of a discrepancy in
-file modification times.
-
-This function is called in @code{set-visited-file-name} and other
-exceptional places where the usual test to avoid overwriting a changed
-file should not be done.
-@end defun
-
-@c Emacs 19 feature
-@defun visited-file-modtime
-This function returns the buffer's recorded last file modification time,
-as a list of the form @code{(@var{high} . @var{low})}. (This is the
-same format that @code{file-attributes} uses to return time values; see
-@ref{File Attributes}.)
-@end defun
-
-@c Emacs 19 feature
-@defun set-visited-file-modtime &optional time
-This function updates the buffer's record of the last modification time
-of the visited file, to the value specified by @var{time} if @var{time}
-is not @code{nil}, and otherwise to the last modification time of the
-visited file.
-
-If @var{time} is not @code{nil}, it should have the form
-@code{(@var{high} . @var{low})} or @code{(@var{high} @var{low})}, in
-either case containing two integers, each of which holds 16 bits of the
-time.
-
-This function is useful if the buffer was not read from the file
-normally, or if the file itself has been changed for some known benign
-reason.
-@end defun
-
-@defun ask-user-about-supersession-threat filename
-@cindex obsolete buffer
-This function is used to ask a user how to proceed after an attempt to
-modify an obsolete buffer visiting file @var{filename}. An
-@dfn{obsolete buffer} is an unmodified buffer for which the associated
-file on disk is newer than the last save-time of the buffer. This means
-some other program has probably altered the file.
-
-@kindex file-supersession
-Depending on the user's answer, the function may return normally, in
-which case the modification of the buffer proceeds, or it may signal a
-@code{file-supersession} error with data @code{(@var{filename})}, in which
-case the proposed buffer modification is not allowed.
-
-This function is called automatically by Emacs on the proper
-occasions. It exists so you can customize Emacs by redefining it.
-See the file @file{userlock.el} for the standard definition.
-
-See also the file locking mechanism in @ref{File Locks}.
-@end defun
-
-@node Read Only Buffers
-@section Read-Only Buffers
-@cindex read-only buffer
-@cindex buffer, read-only
-
- If a buffer is @dfn{read-only}, then you cannot change its contents,
-although you may change your view of the contents by scrolling and
-narrowing.
-
- Read-only buffers are used in two kinds of situations:
-
-@itemize @bullet
-@item
-A buffer visiting a write-protected file is normally read-only.
-
-Here, the purpose is to show the user that editing the buffer with the
-aim of saving it in the file may be futile or undesirable. The user who
-wants to change the buffer text despite this can do so after clearing
-the read-only flag with @kbd{C-x C-q}.
-
-@item
-Modes such as Dired and Rmail make buffers read-only when altering the
-contents with the usual editing commands is probably a mistake.
-
-The special commands of these modes bind @code{buffer-read-only} to
-@code{nil} (with @code{let}) or bind @code{inhibit-read-only} to
-@code{t} around the places where they change the text.
-@end itemize
-
-@defvar buffer-read-only
-This buffer-local variable specifies whether the buffer is read-only.
-The buffer is read-only if this variable is non-@code{nil}.
-@end defvar
-
-@defvar inhibit-read-only
-If this variable is non-@code{nil}, then read-only buffers and read-only
-characters may be modified. Read-only characters in a buffer are those
-that have non-@code{nil} @code{read-only} properties (either text
-properties or overlay properties). @xref{Special Properties}, for more
-information about text properties. @xref{Overlays}, for more
-information about overlays and their properties.
-
-If @code{inhibit-read-only} is @code{t}, all @code{read-only} character
-properties have no effect. If @code{inhibit-read-only} is a list, then
-@code{read-only} character properties have no effect if they are members
-of the list (comparison is done with @code{eq}).
-@end defvar
-
-@deffn Command toggle-read-only
-This command changes whether the current buffer is read-only. It is
-intended for interactive use; don't use it in programs. At any given
-point in a program, you should know whether you want the read-only flag
-on or off; so you can set @code{buffer-read-only} explicitly to the
-proper value, @code{t} or @code{nil}.
-@end deffn
-
-@defun barf-if-buffer-read-only
-This function signals a @code{buffer-read-only} error if the current
-buffer is read-only. @xref{Interactive Call}, for another way to
-signal an error if the current buffer is read-only.
-@end defun
-
-@node The Buffer List
-@section The Buffer List
-@cindex buffer list
-
- The @dfn{buffer list} is a list of all live buffers. Creating a
-buffer adds it to this list, and killing a buffer deletes it. The order
-of the buffers in the list is based primarily on how recently each
-buffer has been displayed in the selected window. Buffers move to the
-front of the list when they are selected and to the end when they are
-buried. Several functions, notably @code{other-buffer}, use this
-ordering. A buffer list displayed for the user also follows this order.
-
-@defun buffer-list
-This function returns a list of all buffers, including those whose names
-begin with a space. The elements are actual buffers, not their names.
-
-@example
-@group
-(buffer-list)
- @result{} (#<buffer buffers.texi>
- #<buffer *Minibuf-1*> #<buffer buffer.c>
- #<buffer *Help*> #<buffer TAGS>)
-@end group
-
-@group
-;; @r{Note that the name of the minibuffer}
-;; @r{begins with a space!}
-(mapcar (function buffer-name) (buffer-list))
- @result{} ("buffers.texi" " *Minibuf-1*"
- "buffer.c" "*Help*" "TAGS")
-@end group
-@end example
-@end defun
-
- The list that @code{buffer-list} returns is constructed specifically
-by @code{buffer-list}; it is not an internal Emacs data structure, and
-modifying it has no effect on the order of buffers. If you want to
-change the order of buffers in the list, here is an easy way:
-
-@example
-(defun reorder-buffer-list (new-list)
- (while new-list
- (bury-buffer (car new-list))
- (setq new-list (cdr new-list))))
-@end example
-
- With this method, you can specify any order for the list, but there is
-no danger of losing a buffer or adding something that is not a valid
-live buffer.
-
-@defun other-buffer &optional buffer visible-ok
-This function returns the first buffer in the buffer list other than
-@var{buffer}. Usually this is the buffer most recently shown in
-the selected window, aside from @var{buffer}. Buffers whose
-names start with a space are not considered.
-
-If @var{buffer} is not supplied (or if it is not a buffer), then
-@code{other-buffer} returns the first buffer on the buffer list that is
-not visible in any window in a visible frame.
-
-If the selected frame has a non-@code{nil} @code{buffer-predicate}
-parameter, then @code{other-buffer} uses that predicate to decide which
-buffers to consider. It calls the predicate once for each buffer, and
-if the value is @code{nil}, that buffer is ignored. @xref{X Frame
-Parameters}.
-
-@c Emacs 19 feature
-If @var{visible-ok} is @code{nil}, @code{other-buffer} avoids returning
-a buffer visible in any window on any visible frame, except as a last
-resort. If @var{visible-ok} is non-@code{nil}, then it does not matter
-whether a buffer is displayed somewhere or not.
-
-If no suitable buffer exists, the buffer @samp{*scratch*} is returned
-(and created, if necessary).
-@end defun
-
-@deffn Command bury-buffer &optional buffer-or-name
-This function puts @var{buffer-or-name} at the end of the buffer list
-without changing the order of any of the other buffers on the list.
-This buffer therefore becomes the least desirable candidate for
-@code{other-buffer} to return.
-
-If @var{buffer-or-name} is @code{nil} or omitted, this means to bury the
-current buffer. In addition, if the buffer is displayed in the selected
-window, this switches to some other buffer (obtained using
-@code{other-buffer}) in the selected window. But if the buffer is
-displayed in some other window, it remains displayed there.
-
-If you wish to replace a buffer in all the windows that display it, use
-@code{replace-buffer-in-windows}. @xref{Buffers and Windows}.
-@end deffn
-
-@node Creating Buffers
-@section Creating Buffers
-@cindex creating buffers
-@cindex buffers, creating
-
- This section describes the two primitives for creating buffers.
-@code{get-buffer-create} creates a buffer if it finds no existing buffer
-with the specified name; @code{generate-new-buffer} always creates a new
-buffer and gives it a unique name.
-
- Other functions you can use to create buffers include
-@code{with-output-to-temp-buffer} (@pxref{Temporary Displays}) and
-@code{create-file-buffer} (@pxref{Visiting Files}). Starting a
-subprocess can also create a buffer (@pxref{Processes}).
-
-@defun get-buffer-create name
-This function returns a buffer named @var{name}. It returns an existing
-buffer with that name, if one exists; otherwise, it creates a new
-buffer. The buffer does not become the current buffer---this function
-does not change which buffer is current.
-
-An error is signaled if @var{name} is not a string.
-
-@example
-@group
-(get-buffer-create "foo")
- @result{} #<buffer foo>
-@end group
-@end example
-
-The major mode for the new buffer is set to Fundamental mode. The
-variable @code{default-major-mode} is handled at a higher level.
-@xref{Auto Major Mode}.
-@end defun
-
-@defun generate-new-buffer name
-This function returns a newly created, empty buffer, but does not make
-it current. If there is no buffer named @var{name}, then that is the
-name of the new buffer. If that name is in use, this function adds
-suffixes of the form @samp{<@var{n}>} to @var{name}, where @var{n} is an
-integer. It tries successive integers starting with 2 until it finds an
-available name.
-
-An error is signaled if @var{name} is not a string.
-
-@example
-@group
-(generate-new-buffer "bar")
- @result{} #<buffer bar>
-@end group
-@group
-(generate-new-buffer "bar")
- @result{} #<buffer bar<2>>
-@end group
-@group
-(generate-new-buffer "bar")
- @result{} #<buffer bar<3>>
-@end group
-@end example
-
-The major mode for the new buffer is set to Fundamental mode. The
-variable @code{default-major-mode} is handled at a higher level.
-@xref{Auto Major Mode}.
-
-See the related function @code{generate-new-buffer-name} in @ref{Buffer
-Names}.
-@end defun
-
-@node Killing Buffers
-@section Killing Buffers
-@cindex killing buffers
-@cindex buffers, killing
-
- @dfn{Killing a buffer} makes its name unknown to Emacs and makes its
-text space available for other use.
-
- The buffer object for the buffer that has been killed remains in
-existence as long as anything refers to it, but it is specially marked
-so that you cannot make it current or display it. Killed buffers retain
-their identity, however; two distinct buffers, when killed, remain
-distinct according to @code{eq}.
-
- If you kill a buffer that is current or displayed in a window, Emacs
-automatically selects or displays some other buffer instead. This means
-that killing a buffer can in general change the current buffer.
-Therefore, when you kill a buffer, you should also take the precautions
-associated with changing the current buffer (unless you happen to know
-that the buffer being killed isn't current). @xref{Current Buffer}.
-
- If you kill a buffer that is the base buffer of one or more indirect
-buffers, the indirect buffers are automatically killed as well.
-
- The @code{buffer-name} of a killed buffer is @code{nil}. You can use
-this feature to test whether a buffer has been killed:
-
-@example
-@group
-(defun buffer-killed-p (buffer)
- "Return t if BUFFER is killed."
- (not (buffer-name buffer)))
-@end group
-@end example
-
-@deffn Command kill-buffer buffer-or-name
-This function kills the buffer @var{buffer-or-name}, freeing all its
-memory for other uses or to be returned to the operating system. It
-returns @code{nil}.
-
-Any processes that have this buffer as the @code{process-buffer} are
-sent the @code{SIGHUP} signal, which normally causes them to terminate.
-(The basic meaning of @code{SIGHUP} is that a dialup line has been
-disconnected.) @xref{Deleting Processes}.
-
-If the buffer is visiting a file and contains unsaved changes,
-@code{kill-buffer} asks the user to confirm before the buffer is killed.
-It does this even if not called interactively. To prevent the request
-for confirmation, clear the modified flag before calling
-@code{kill-buffer}. @xref{Buffer Modification}.
-
-Killing a buffer that is already dead has no effect.
-
-@smallexample
-(kill-buffer "foo.unchanged")
- @result{} nil
-(kill-buffer "foo.changed")
-
----------- Buffer: Minibuffer ----------
-Buffer foo.changed modified; kill anyway? (yes or no) @kbd{yes}
----------- Buffer: Minibuffer ----------
-
- @result{} nil
-@end smallexample
-@end deffn
-
-@defvar kill-buffer-query-functions
-After confirming unsaved changes, @code{kill-buffer} calls the functions
-in the list @code{kill-buffer-query-functions}, in order of appearance,
-with no arguments. The buffer being killed is the current buffer when
-they are called. The idea is that these functions ask for confirmation
-from the user for various nonstandard reasons. If any of them returns
-@code{nil}, @code{kill-buffer} spares the buffer's life.
-@end defvar
-
-@defvar kill-buffer-hook
-This is a normal hook run by @code{kill-buffer} after asking all the
-questions it is going to ask, just before actually killing the buffer.
-The buffer to be killed is current when the hook functions run.
-@xref{Hooks}.
-@end defvar
-
-@defvar buffer-offer-save
-This variable, if non-@code{nil} in a particular buffer, tells
-@code{save-buffers-kill-emacs} and @code{save-some-buffers} to offer to
-save that buffer, just as they offer to save file-visiting buffers. The
-variable @code{buffer-offer-save} automatically becomes buffer-local
-when set for any reason. @xref{Buffer-Local Variables}.
-@end defvar
-
-@node Indirect Buffers
-@section Indirect Buffers
-@cindex indirect buffers
-@cindex base buffer
-
- An @dfn{indirect buffer} shares the text of some other buffer, which
-is called the @dfn{base buffer} of the indirect buffer. In some ways it
-is the analogue, for buffers, of a symbolic link among files. The base
-buffer may not itself be an indirect buffer.
-
- The text of the indirect buffer is always identical to the text of its
-base buffer; changes made by editing either one are visible immediately
-in the other. This includes the text properties as well as the characters
-themselves.
-
- But in all other respects, the indirect buffer and its base buffer are
-completely separate. They have different names, different values of
-point, different narrowing, different markers and overlays (though
-inserting or deleting text in either buffer relocates the markers and
-overlays for both), different major modes, and different local
-variables.
-
- An indirect buffer cannot visit a file, but its base buffer can. If
-you try to save the indirect buffer, that actually works by saving the
-base buffer.
-
- Killing an indirect buffer has no effect on its base buffer. Killing
-the base buffer effectively kills the indirect buffer in that it cannot
-ever again be the current buffer.
-
-@deffn Command make-indirect-buffer base-buffer name
-This creates an indirect buffer named @var{name} whose base buffer
-is @var{base-buffer}. The argument @var{base-buffer} may be a buffer
-or a string.
-
-If @var{base-buffer} is an indirect buffer, its base buffer is used as
-the base for the new buffer.
-@end deffn
-
-@defun buffer-base-buffer buffer
-This function returns the base buffer of @var{buffer}. If @var{buffer}
-is not indirect, the value is @code{nil}. Otherwise, the value is
-another buffer, which is never an indirect buffer.
-@end defun
-
diff --git a/lispref/calendar.texi b/lispref/calendar.texi
deleted file mode 100644
index 8e42a530f25..00000000000
--- a/lispref/calendar.texi
+++ /dev/null
@@ -1,908 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@node Calendar, Tips, Display, Top
-@chapter Customizing the Calendar and Diary
-
- There are many customizations that you can use to make the calendar and
-diary suit your personal tastes.
-
-@menu
-* Calendar Customizing:: Defaults you can set.
-* Holiday Customizing:: Defining your own holidays.
-* Date Display Format:: Changing the format.
-* Time Display Format:: Changing the format.
-* Daylight Savings:: Changing the default.
-* Diary Customizing:: Defaults you can set.
-* Hebrew/Islamic Entries:: How to obtain them.
-* Fancy Diary Display:: Enhancing the diary display, sorting entries,
- using included diary files.
-* Sexp Diary Entries:: Fancy things you can do.
-* Appt Customizing:: Customizing appointment reminders.
-@end menu
-
-@node Calendar Customizing
-@section Customizing the Calendar
-@vindex view-diary-entries-initially
-
- If you set the variable @code{view-diary-entries-initially} to
-@code{t}, calling up the calendar automatically displays the diary
-entries for the current date as well. The diary dates appear only if
-the current date is visible. If you add both of the following lines to
-your @file{.emacs} file:@refill
-
-@example
-(setq view-diary-entries-initially t)
-(calendar)
-@end example
-
-@noindent
-this displays both the calendar and diary windows whenever you start Emacs.
-
-@vindex view-calendar-holidays-initially
- Similarly, if you set the variable
-@code{view-calendar-holidays-initially} to @code{t}, entering the
-calendar automatically displays a list of holidays for the current
-three-month period. The holiday list appears in a separate
-window.
-
-@vindex mark-diary-entries-in-calendar
- You can set the variable @code{mark-diary-entries-in-calendar} to
-@code{t} in order to mark any dates with diary entries. This takes
-effect whenever the calendar window contents are recomputed. There are
-two ways of marking these dates: by changing the face (@pxref{Faces}),
-if the display supports that, or by placing a plus sign (@samp{+})
-beside the date otherwise.
-
-@vindex mark-holidays-in-calendar
- Similarly, setting the variable @code{mark-holidays-in-calendar} to
-@code{t} marks holiday dates, either with a change of face or with an
-asterisk (@samp{*}).
-
-@vindex calendar-holiday-marker
-@vindex diary-entry-marker
- The variable @code{calendar-holiday-marker} specifies how to mark a
-date as being a holiday. Its value may be a character to insert next to
-the date, or a face name to use for displaying the date. Likewise, the
-variable @code{diary-entry-marker} specifies how to mark a date that has
-diary entries. The calendar creates faces named @code{holiday-face} and
-@code{diary-face} for these purposes; those symbols are the default
-values of these variables, when Emacs supports multiple faces on your
-terminal.
-
-@vindex calendar-load-hook
- The variable @code{calendar-load-hook} is a normal hook run when the
-calendar package is first loaded (before actually starting to display
-the calendar).
-
-@vindex initial-calendar-window-hook
- Starting the calendar runs the normal hook
-@code{initial-calendar-window-hook}. Recomputation of the calendar
-display does not run this hook. But if you leave the calendar with the
-@kbd{q} command and reenter it, the hook runs again.@refill
-
-@vindex today-visible-calendar-hook
- The variable @code{today-visible-calendar-hook} is a normal hook run
-after the calendar buffer has been prepared with the calendar when the
-current date is visible in the window. One use of this hook is to
-replace today's date with asterisks; to do that, use the hook function
-@code{calendar-star-date}.
-
-@findex calendar-star-date
-@example
-(add-hook 'today-visible-calendar-hook 'calendar-star-date)
-@end example
-
-@noindent
-Another standard hook function marks the current date, either by
-changing its face or by adding an asterisk. Here's how to use it:
-
-@findex calendar-mark-today
-@example
-(add-hook 'today-visible-calendar-hook 'calendar-mark-today)
-@end example
-
-@noindent
-@vindex calendar-today-marker
-The variable @code{calendar-today-marker} specifies how to mark today's
-date. Its value should be a character to insert next to the date or a
-face name to use for displaying the date. A face named
-@code{calendar-today-face} is provided for this purpose; that symbol is
-the default for this variable when Emacs supports multiple faces on your
-terminal.
-
-@vindex today-invisible-calendar-hook
-@noindent
- A similar normal hook, @code{today-invisible-calendar-hook} is run if
-the current date is @emph{not} visible in the window.
-
-@node Holiday Customizing
-@section Customizing the Holidays
-
-@vindex calendar-holidays
-@vindex christian-holidays
-@vindex hebrew-holidays
-@vindex islamic-holidays
- Emacs knows about holidays defined by entries on one of several lists.
-You can customize these lists of holidays to your own needs, adding or
-deleting holidays. The lists of holidays that Emacs uses are for
-general holidays (@code{general-holidays}), local holidays
-(@code{local-holidays}), Christian holidays (@code{christian-holidays}),
-Hebrew (Jewish) holidays (@code{hebrew-holidays}), Islamic (Moslem)
-holidays (@code{islamic-holidays}), and other holidays
-(@code{other-holidays}).
-
-@vindex general-holidays
- The general holidays are, by default, holidays common throughout the
-United States. To eliminate these holidays, set @code{general-holidays}
-to @code{nil}.
-
-@vindex local-holidays
- There are no default local holidays (but sites may supply some). You
-can set the variable @code{local-holidays} to any list of holidays, as
-described below.
-
-@vindex all-christian-calendar-holidays
-@vindex all-hebrew-calendar-holidays
-@vindex all-islamic-calendar-holidays
- By default, Emacs does not include all the holidays of the religions
-that it knows, only those commonly found in secular calendars. For a
-more extensive collection of religious holidays, you can set any (or
-all) of the variables @code{all-christian-calendar-holidays},
-@code{all-hebrew-calendar-holidays}, or
-@code{all-islamic-calendar-holidays} to @code{t}. If you want to
-eliminate the religious holidays, set any or all of the corresponding
-variables @code{christian-holidays}, @code{hebrew-holidays}, and
-@code{islamic-holidays} to @code{nil}.@refill
-
-@vindex other-holidays
- You can set the variable @code{other-holidays} to any list of
-holidays. This list, normally empty, is intended for individual use.
-
-@cindex holiday forms
- Each of the lists (@code{general-holidays}, @code{local-holidays},
-@code{christian-holidays}, @code{hebrew-holidays},
-@code{islamic-holidays}, and @code{other-holidays}) is a list of
-@dfn{holiday forms}, each holiday form describing a holiday (or
-sometimes a list of holidays).
-
- Here is a table of the possible kinds of holiday form. Day numbers
-and month numbers count starting from 1, but ``dayname'' numbers
-count Sunday as 0. The element @var{string} is always the
-name of the holiday, as a string.
-
-@table @code
-@item (holiday-fixed @var{month} @var{day} @var{string})
-A fixed date on the Gregorian calendar.
-
-@item (holiday-float @var{month} @var{dayname} @var{k} @var{string})
-The @var{k}th @var{dayname} in @var{month} on the Gregorian calendar
-(@var{dayname}=0 for Sunday, and so on); negative @var{k} means count back
-from the end of the month.
-
-@item (holiday-hebrew @var{month} @var{day} @var{string})
-A fixed date on the Hebrew calendar.
-
-@item (holiday-islamic @var{month} @var{day} @var{string})
-A fixed date on the Islamic calendar.
-
-@item (holiday-julian @var{month} @var{day} @var{string})
-A fixed date on the Julian calendar.
-
-@item (holiday-sexp @var{sexp} @var{string})
-A date calculated by the Lisp expression @var{sexp}. The expression
-should use the variable @code{year} to compute and return the date of a
-holiday, or @code{nil} if the holiday doesn't happen this year. The
-value of @var{sexp} must represent the date as a list of the form
-@code{(@var{month} @var{day} @var{year})}.
-
-@item (if @var{condition} @var{holiday-form})
-A holiday that happens only if @var{condition} is true.
-
-@item (@var{function} @r{[}@var{args}@r{]})
-A list of dates calculated by the function @var{function}, called with
-arguments @var{args}.
-@end table
-
- For example, suppose you want to add Bastille Day, celebrated in
-France on July 14. You can do this as follows:
-
-@smallexample
-(setq other-holidays '((holiday-fixed 7 14 "Bastille Day")))
-@end smallexample
-
-@noindent
-The holiday form @code{(holiday-fixed 7 14 "Bastille Day")} specifies the
-fourteenth day of the seventh month (July).
-
- Many holidays occur on a specific day of the week, at a specific time
-of month. Here is a holiday form describing Hurricane Supplication Day,
-celebrated in the Virgin Islands on the fourth Monday in August:
-
-@smallexample
-(holiday-float 8 1 4 "Hurricane Supplication Day")
-@end smallexample
-
-@noindent
-Here the 8 specifies August, the 1 specifies Monday (Sunday is 0,
-Tuesday is 2, and so on), and the 4 specifies the fourth occurrence in
-the month (1 specifies the first occurrence, 2 the second occurrence,
-@minus{}1 the last occurrence, @minus{}2 the second-to-last occurrence, and
-so on).
-
- You can specify holidays that occur on fixed days of the Hebrew,
-Islamic, and Julian calendars too. For example,
-
-@smallexample
-(setq other-holidays
- '((holiday-hebrew 10 2 "Last day of Hanukkah")
- (holiday-islamic 3 12 "Mohammed's Birthday")
- (holiday-julian 4 2 "Jefferson's Birthday")))
-@end smallexample
-
-@noindent
-adds the last day of Hanukkah (since the Hebrew months are numbered with
-1 starting from Nisan), the Islamic feast celebrating Mohammed's
-birthday (since the Islamic months are numbered from 1 starting with
-Muharram), and Thomas Jefferson's birthday, which is 2 April 1743 on the
-Julian calendar.
-
- To include a holiday conditionally, use either Emacs Lisp's @code{if} or the
-@code{holiday-sexp} form. For example, American presidential elections
-occur on the first Tuesday after the first Monday in November of years
-divisible by 4:
-
-@smallexample
-(holiday-sexp (if (= 0 (% year 4))
- (calendar-gregorian-from-absolute
- (1+ (calendar-dayname-on-or-before
- 1 (+ 6 (calendar-absolute-from-gregorian
- (list 11 1 year))))))
- "US Presidential Election"))
-@end smallexample
-
-@noindent
-or
-
-@smallexample
-(if (= 0 (% displayed-year 4))
- (fixed 11
- (extract-calendar-day
- (calendar-gregorian-from-absolute
- (1+ (calendar-dayname-on-or-before
- 1 (+ 6 (calendar-absolute-from-gregorian
- (list 11 1 displayed-year)))))))
- "US Presidential Election"))
-@end smallexample
-
- Some holidays just don't fit into any of these forms because special
-calculations are involved in their determination. In such cases you
-must write a Lisp function to do the calculation. To include eclipses,
-for example, add @code{(eclipses)} to @code{other-holidays}
-and write an Emacs Lisp function @code{eclipses} that returns a
-(possibly empty) list of the relevant Gregorian dates among the range
-visible in the calendar window, with descriptive strings, like this:
-
-@smallexample
-(((6 27 1991) "Lunar Eclipse") ((7 11 1991) "Solar Eclipse") ... )
-@end smallexample
-
-@node Date Display Format
-@section Date Display Format
-@vindex calendar-date-display-form
-
- You can customize the manner of displaying dates in the diary, in mode
-lines, and in messages by setting @code{calendar-date-display-form}.
-This variable holds a list of expressions that can involve the variables
-@code{month}, @code{day}, and @code{year}, which are all numbers in
-string form, and @code{monthname} and @code{dayname}, which are both
-alphabetic strings. In the American style, the default value of this
-list is as follows:
-
-@smallexample
-((if dayname (concat dayname ", ")) monthname " " day ", " year)
-@end smallexample
-
-@noindent
-while in the European style this value is the default:
-
-@smallexample
-((if dayname (concat dayname ", ")) day " " monthname " " year)
-@end smallexample
-
-@noindent
-The ISO standard date representation is this:
-
-@smallexample
-(year "-" month "-" day)
-@end smallexample
-
-@noindent
-This specifies a typical American format:
-
-@smallexample
-(month "/" day "/" (substring year -2))
-@end smallexample
-
-@node Time Display Format
-@section Time Display Format
-@vindex calendar-time-display-form
-
- The calendar and diary by default display times of day in the
-conventional American style with the hours from 1 through 12, minutes,
-and either @samp{am} or @samp{pm}. If you prefer the European style,
-also known in the US as military, in which the hours go from 00 to 23,
-you can alter the variable @code{calendar-time-display-form}. This
-variable is a list of expressions that can involve the variables
-@code{12-hours}, @code{24-hours}, and @code{minutes}, which are all
-numbers in string form, and @code{am-pm} and @code{time-zone}, which are
-both alphabetic strings. The default value of
-@code{calendar-time-display-form} is as follows:
-
-@smallexample
-(12-hours ":" minutes am-pm
- (if time-zone " (") time-zone (if time-zone ")"))
-@end smallexample
-
-@noindent
-Here is a value that provides European style times:
-
-@smallexample
-(24-hours ":" minutes
- (if time-zone " (") time-zone (if time-zone ")"))
-@end smallexample
-
-@node Daylight Savings
-@section Daylight Savings Time
-@cindex daylight savings time
-
- Emacs understands the difference between standard time and daylight
-savings time---the times given for sunrise, sunset, solstices,
-equinoxes, and the phases of the moon take that into account. The rules
-for daylight savings time vary from place to place and have also varied
-historically from year to year. To do the job properly, Emacs needs to
-know which rules to use.
-
- Some operating systems keep track of the rules that apply to the place
-where you are; on these systems, Emacs gets the information it needs
-from the system automatically. If some or all of this information is
-missing, Emacs fills in the gaps with the rules currently used in
-Cambridge, Massachusetts, which is the center of GNU's world.
-
-
-@vindex calendar-daylight-savings-starts
-@vindex calendar-daylight-savings-ends
- If the default choice of rules is not appropriate for your location,
-you can tell Emacs the rules to use by setting the variables
-@code{calendar-daylight-savings-starts} and
-@code{calendar-daylight-savings-ends}. Their values should be Lisp
-expressions that refer to the variable @code{year}, and evaluate to the
-Gregorian date on which daylight savings time starts or (respectively)
-ends, in the form of a list @code{(@var{month} @var{day} @var{year})}.
-The values should be @code{nil} if your area does not use daylight
-savings time.
-
- Emacs uses these expressions to determine the start and end dates of
-daylight savings time as holidays and for correcting times of day in the
-solar and lunar calculations.
-
- The values for Cambridge, Massachusetts are as follows:
-
-@example
-@group
-(calendar-nth-named-day 1 0 4 year)
-(calendar-nth-named-day -1 0 10 year)
-@end group
-@end example
-
-@noindent
-i.e., the first 0th day (Sunday) of the fourth month (April) in
-the year specified by @code{year}, and the last Sunday of the tenth month
-(October) of that year. If daylight savings time were
-changed to start on October 1, you would set
-@code{calendar-daylight-savings-starts} to this:
-
-@example
-(list 10 1 year)
-@end example
-
- For a more complex example, suppose daylight savings time begins on
-the first of Nisan on the Hebrew calendar. You should set
-@code{calendar-daylight-savings-starts} to this value:
-
-@example
-(calendar-gregorian-from-absolute
- (calendar-absolute-from-hebrew
- (list 1 1 (+ year 3760))))
-@end example
-
-@noindent
-because Nisan is the first month in the Hebrew calendar and the Hebrew
-year differs from the Gregorian year by 3760 at Nisan.
-
- If there is no daylight savings time at your location, or if you want
-all times in standard time, set @code{calendar-daylight-savings-starts}
-and @code{calendar-daylight-savings-ends} to @code{nil}.
-
-@vindex calendar-daylight-time-offset
- The variable @code{calendar-daylight-time-offset} specifies the
-difference between daylight savings time and standard time, measured in
-minutes. The value for Cambridge is 60.
-
-@vindex calendar-daylight-savings-starts-time
-@vindex calendar-daylight-savings-ends-time
- The variable @code{calendar-daylight-savings-starts-time} and the
-variable @code{calendar-daylight-savings-ends-time} specify the number
-of minutes after midnight local time when the transition to and from
-daylight savings time should occur. For Cambridge, both variables'
-values are 120.
-
-@node Diary Customizing
-@section Customizing the Diary
-
-@vindex holidays-in-diary-buffer
- Ordinarily, the mode line of the diary buffer window indicates any
-holidays that fall on the date of the diary entries. The process of
-checking for holidays can take several seconds, so including holiday
-information delays the display of the diary buffer noticeably. If you'd
-prefer to have a faster display of the diary buffer but without the
-holiday information, set the variable @code{holidays-in-diary-buffer} to
-@code{nil}.@refill
-
-@vindex number-of-diary-entries
- The variable @code{number-of-diary-entries} controls the number of
-days of diary entries to be displayed at one time. It affects the
-initial display when @code{view-diary-entries-initially} is @code{t}, as
-well as the command @kbd{M-x diary}. For example, the default value is
-1, which says to display only the current day's diary entries. If the
-value is 2, both the current day's and the next day's entries are
-displayed. The value can also be a vector of seven elements: for
-example, if the value is @code{[0 2 2 2 2 4 1]} then no diary entries
-appear on Sunday, the current date's and the next day's diary entries
-appear Monday through Thursday, Friday through Monday's entries appear
-on Friday, while on Saturday only that day's entries appear.
-
-@vindex print-diary-entries-hook
-@findex print-diary-entries
- The variable @code{print-diary-entries-hook} is a normal hook run
-after preparation of a temporary buffer containing just the diary
-entries currently visible in the diary buffer. (The other, irrelevant
-diary entries are really absent from the temporary buffer; in the diary
-buffer, they are merely hidden.) The default value of this hook does
-the printing with the command @code{lpr-buffer}. If you want to use a
-different command to do the printing, just change the value of this
-hook. Other uses might include, for example, rearranging the lines into
-order by day and time.
-
-@vindex diary-date-forms
- You can customize the form of dates in your diary file, if neither the
-standard American nor European styles suits your needs, by setting the
-variable @code{diary-date-forms}. This variable is a list of patterns
-for recognizing a date. Each date pattern is a list whose elements may
-be regular expressions (@pxref{Regular Expressions}) or the symbols
-@code{month}, @code{day}, @code{year}, @code{monthname}, and
-@code{dayname}. All these elements serve as patterns that match certain
-kinds of text in the diary file. In order for the date pattern, as a
-whole, to match, all of its elements must match consecutively.
-
- A regular expression in a date pattern matches in its usual fashion,
-using the standard syntax table altered so that @samp{*} is a word
-constituent.
-
- The symbols @code{month}, @code{day}, @code{year}, @code{monthname},
-and @code{dayname} match the month number, day number, year number,
-month name, and day name of the date being considered. The symbols that
-match numbers allow leading zeros; those that match names allow
-three-letter abbreviations and capitalization. All the symbols can
-match @samp{*}; since @samp{*} in a diary entry means ``any day'', ``any
-month'', and so on, it should match regardless of the date being
-considered.
-
- The default value of @code{diary-date-forms} in the American style is
-this:
-
-@example
-((month "/" day "[^/0-9]")
- (month "/" day "/" year "[^0-9]")
- (monthname " *" day "[^,0-9]")
- (monthname " *" day ", *" year "[^0-9]")
- (dayname "\\W"))
-@end example
-
- The date patterns in the list must be @emph{mutually exclusive} and
-must not match any portion of the diary entry itself, just the date and
-one character of whitespace. If, to be mutually exclusive, the pattern
-must match a portion of the diary entry text---beyond the whitespace
-that ends the date---then the first element of the date pattern
-@emph{must} be @code{backup}. This causes the date recognizer to back
-up to the beginning of the current word of the diary entry, after
-finishing the match. Even if you use @code{backup}, the date pattern
-must absolutely not match more than a portion of the first word of the
-diary entry. The default value of @code{diary-date-forms} in the
-European style is this list:
-
-@example
-((day "/" month "[^/0-9]")
- (day "/" month "/" year "[^0-9]")
- (backup day " *" monthname "\\W+\\<[^*0-9]")
- (day " *" monthname " *" year "[^0-9]")
- (dayname "\\W"))
-@end example
-
-@noindent
-Notice the use of @code{backup} in the third pattern, because it needs
-to match part of a word beyond the date itself to distinguish it from
-the fourth pattern.
-
-@node Hebrew/Islamic Entries
-@section Hebrew- and Islamic-Date Diary Entries
-
- Your diary file can have entries based on Hebrew or Islamic dates, as
-well as entries based on the world-standard Gregorian calendar.
-However, because recognition of such entries is time-consuming and most
-people don't use them, you must explicitly enable their use. If you
-want the diary to recognize Hebrew-date diary entries, for example,
-you must do this:
-
-@vindex nongregorian-diary-listing-hook
-@vindex nongregorian-diary-marking-hook
-@findex list-hebrew-diary-entries
-@findex mark-hebrew-diary-entries
-@smallexample
-(add-hook 'nongregorian-diary-listing-hook 'list-hebrew-diary-entries)
-(add-hook 'nongregorian-diary-marking-hook 'mark-hebrew-diary-entries)
-@end smallexample
-
-@noindent
-If you want Islamic-date entries, do this:
-
-@findex list-islamic-diary-entries
-@findex mark-islamic-diary-entries
-@smallexample
-(add-hook 'nongregorian-diary-listing-hook 'list-islamic-diary-entries)
-(add-hook 'nongregorian-diary-marking-hook 'mark-islamic-diary-entries)
-@end smallexample
-
- Hebrew- and Islamic-date diary entries have the same formats as
-Gregorian-date diary entries, except that @samp{H} precedes a Hebrew
-date and @samp{I} precedes an Islamic date. Moreover, because the
-Hebrew and Islamic month names are not uniquely specified by the first
-three letters, you may not abbreviate them. For example, a diary entry
-for the Hebrew date Heshvan 25 could look like this:
-
-@smallexample
-HHeshvan 25 Happy Hebrew birthday!
-@end smallexample
-
-@noindent
-and would appear in the diary for any date that corresponds to Heshvan 25
-on the Hebrew calendar. And here is Islamic-date diary entry that matches
-Dhu al-Qada 25:
-
-@smallexample
-IDhu al-Qada 25 Happy Islamic birthday!
-@end smallexample
-
- As with Gregorian-date diary entries, Hebrew- and Islamic-date entries
-are nonmarking if they are preceded with an ampersand (@samp{&}).
-
- Here is a table of commands used in the calendar to create diary entries
-that match the selected date and other dates that are similar in the Hebrew
-or Islamic calendar:
-
-@table @kbd
-@item i h d
-Add a diary entry for the Hebrew date corresponding to the selected date
-(@code{insert-hebrew-diary-entry}).
-@item i h m
-Add a diary entry for the day of the Hebrew month corresponding to the
-selected date (@code{insert-monthly-hebrew-diary-entry}). This diary
-entry matches any date that has the same Hebrew day-within-month as the
-selected date.
-@item i h y
-Add a diary entry for the day of the Hebrew year corresponding to the
-selected date (@code{insert-yearly-hebrew-diary-entry}). This diary
-entry matches any date which has the same Hebrew month and day-within-month
-as the selected date.
-@item i i d
-Add a diary entry for the Islamic date corresponding to the selected date
-(@code{insert-islamic-diary-entry}).
-@item i i m
-Add a diary entry for the day of the Islamic month corresponding to the
-selected date (@code{insert-monthly-islamic-diary-entry}).
-@item i i y
-Add a diary entry for the day of the Islamic year corresponding to the
-selected date (@code{insert-yearly-islamic-diary-entry}).
-@end table
-
-@findex insert-hebrew-diary-entry
-@findex insert-monthly-hebrew-diary-entry
-@findex insert-yearly-hebrew-diary-entry
-@findex insert-islamic-diary-entry
-@findex insert-monthly-islamic-diary-entry
-@findex insert-yearly-islamic-diary-entry
- These commands work much like the corresponding commands for ordinary
-diary entries: they apply to the date that point is on in the calendar
-window, and what they do is insert just the date portion of a diary entry
-at the end of your diary file. You must then insert the rest of the
-diary entry.
-
-@node Fancy Diary Display
-@section Fancy Diary Display
-@vindex diary-display-hook
-@findex simple-diary-display
-
- Diary display works by preparing the diary buffer and then running the
-hook @code{diary-display-hook}. The default value of this hook
-(@code{simple-diary-display}) hides the irrelevant diary entries and
-then displays the buffer. However, if you specify the hook as follows,
-
-@cindex diary buffer
-@findex fancy-diary-display
-@example
-(add-hook 'diary-display-hook 'fancy-diary-display)
-@end example
-
-@noindent
-this enables fancy diary display. It displays diary entries and
-holidays by copying them into a special buffer that exists only for the
-sake of display. Copying to a separate buffer provides an opportunity
-to change the displayed text to make it prettier---for example, to sort
-the entries by the dates they apply to.
-
- As with simple diary display, you can print a hard copy of the buffer
-with @code{print-diary-entries}. To print a hard copy of a day-by-day
-diary for a week by positioning point on Sunday of that week, type
-@kbd{7 d} and then do @kbd{M-x print-diary-entries}. As usual, the
-inclusion of the holidays slows down the display slightly; you can speed
-things up by setting the variable @code{holidays-in-diary-buffer} to
-@code{nil}.
-
-@vindex diary-list-include-blanks
- Ordinarily, the fancy diary buffer does not show days for which there are
-no diary entries, even if that day is a holiday. If you want such days to be
-shown in the fancy diary buffer, set the variable
-@code{diary-list-include-blanks} to @code{t}.@refill
-
-@cindex sorting diary entries
- If you use the fancy diary display, you can use the normal hook
-@code{list-diary-entries-hook} to sort each day's diary entries by their
-time of day. Here's how
-
-@findex sort-diary-entries
-@example
-(add-hook 'list-diary-entries-hook 'sort-diary-entries t)
-@end example
-
-@noindent
-For each day, this sorts diary entries that begin with a recognizable
-time of day according to their times. Diary entries without times come
-first within each day.
-
- Fancy diary display also has the ability to process included diary
-files. This permits a group of people to share a diary file for events
-that apply to all of them. Lines in the diary file of this form:
-
-@smallexample
-#include "@var{filename}"
-@end smallexample
-
-@noindent
-includes the diary entries from the file @var{filename} in the fancy
-diary buffer. The include mechanism is recursive, so that included files
-can include other files, and so on; you must be careful not to have a
-cycle of inclusions, of course. Here is how to enable the include
-facility:
-
-@vindex list-diary-entries-hook
-@vindex mark-diary-entries-hook
-@findex include-other-diary-files
-@findex mark-included-diary-files
-@smallexample
-(add-hook 'list-diary-entries-hook 'include-other-diary-files)
-(add-hook 'mark-diary-entries-hook 'mark-included-diary-files)
-@end smallexample
-
-The include mechanism works only with the fancy diary display, because
-ordinary diary display shows the entries directly from your diary file.
-
-@node Sexp Diary Entries
-@section Sexp Entries and the Fancy Diary Display
-@cindex sexp diary entries
-
- Sexp diary entries allow you to do more than just have complicated
-conditions under which a diary entry applies. If you use the fancy
-diary display, sexp entries can generate the text of the entry depending
-on the date itself. For example, an anniversary diary entry can insert
-the number of years since the anniversary date into the text of the
-diary entry. Thus the @samp{%d} in this dairy entry:
-
-@findex diary-anniversary
-@smallexample
-%%(diary-anniversary 10 31 1948) Arthur's birthday (%d years old)
-@end smallexample
-
-@noindent
-gets replaced by the age, so on October 31, 1990 the entry appears in
-the fancy diary buffer like this:
-
-@smallexample
-Arthur's birthday (42 years old)
-@end smallexample
-
-@noindent
-If the diary file instead contains this entry:
-
-@smallexample
-%%(diary-anniversary 10 31 1948) Arthur's %d%s birthday
-@end smallexample
-
-@noindent
-the entry in the fancy diary buffer for October 31, 1990 appears like this:
-
-@smallexample
-Arthur's 42nd birthday
-@end smallexample
-
- Similarly, cyclic diary entries can interpolate the number of repetitions
-that have occurred:
-
-@findex diary-cyclic
-@smallexample
-%%(diary-cyclic 50 1 1 1990) Renew medication (%d%s time)
-@end smallexample
-
-@noindent
-looks like this:
-
-@smallexample
-Renew medication (5th time)
-@end smallexample
-
-@noindent
-in the fancy diary display on September 8, 1990.
-
- The generality of sexp diary entries lets you specify any diary entry
-that you can describe algorithmically. A sexp diary entry contains an
-expression that computes whether the entry applies to any given date.
-If its value is non-@code{nil}, the entry applies to that date;
-otherwise, it does not. The expression can use the variable @code{date}
-to find the date being considered; its value is a list (@var{month}
-@var{day} @var{year}) that refers to the Gregorian calendar.
-
- Suppose you get paid on the 21st of the month if it is a weekday, and
-on the Friday before if the 21st is on a weekend. Here is how to write
-a sexp diary entry that matches those dates:
-
-@smallexample
-&%%(let ((dayname (calendar-day-of-week date))
- (day (car (cdr date))))
- (or (and (= day 21) (memq dayname '(1 2 3 4 5)))
- (and (memq day '(19 20)) (= dayname 5)))
- ) Pay check deposited
-@end smallexample
-
- The following sexp diary entries take advantage of the ability (in the fancy
-diary display) to concoct diary entries whose text varies based on the date:
-
-@findex diary-sunrise-sunset
-@findex diary-phases-of-moon
-@findex diary-day-of-year
-@findex diary-iso-date
-@findex diary-julian-date
-@findex diary-astro-day-number
-@findex diary-hebrew-date
-@findex diary-islamic-date
-@findex diary-french-date
-@findex diary-mayan-date
-@table @code
-@item %%(diary-sunrise-sunset)
-Make a diary entry for the local times of today's sunrise and sunset.
-@item %%(diary-phases-of-moon)
-Make a diary entry for the phases (quarters) of the moon.
-@item %%(diary-day-of-year)
-Make a diary entry with today's day number in the current year and the number
-of days remaining in the current year.
-@item %%(diary-iso-date)
-Make a diary entry with today's equivalent ISO commercial date.
-@item %%(diary-julian-date)
-Make a diary entry with today's equivalent date on the Julian calendar.
-@item %%(diary-astro-day-number)
-Make a diary entry with today's equivalent astronomical (Julian) day number.
-@item %%(diary-hebrew-date)
-Make a diary entry with today's equivalent date on the Hebrew calendar.
-@item %%(diary-islamic-date)
-Make a diary entry with today's equivalent date on the Islamic calendar.
-@item %%(diary-french-date)
-Make a diary entry with today's equivalent date on the French Revolutionary
-calendar.
-@item %%(diary-mayan-date)
-Make a diary entry with today's equivalent date on the Mayan calendar.
-@end table
-
-@noindent
-Thus including the diary entry
-
-@example
-&%%(diary-hebrew-date)
-@end example
-
-@noindent
-causes every day's diary display to contain the equivalent date on the
-Hebrew calendar, if you are using the fancy diary display. (With simple
-diary display, the line @samp{&%%(diary-hebrew-date)} appears in the
-diary for any date, but does nothing particularly useful.)
-
- These functions can be used to construct sexp diary entries based on
-the Hebrew calendar in certain standard ways:
-
-@cindex rosh hodesh
-@findex diary-rosh-hodesh
-@cindex parasha, weekly
-@findex diary-parasha
-@cindex candle lighting times
-@findex diary-sabbath-candles
-@cindex omer count
-@findex diary-omer
-@cindex yahrzeits
-@findex diary-yahrzeit
-@table @code
-@item %%(diary-rosh-hodesh)
-Make a diary entry that tells the occurrence and ritual announcement of each
-new Hebrew month.
-@item %%(diary-parasha)
-Make a Saturday diary entry that tells the weekly synagogue scripture reading.
-@item %%(diary-sabbath-candles)
-Make a Friday diary entry that tells the @emph{local time} of Sabbath
-candle lighting.
-@item %%(diary-omer)
-Make a diary entry that gives the omer count, when appropriate.
-@item %%(diary-yahrzeit @var{month} @var{day} @var{year}) @var{name}
-Make a diary entry marking the anniversary of a date of death. The date
-is the @emph{Gregorian} (civil) date of death. The diary entry appears
-on the proper Hebrew calendar anniversary and on the day before. (In
-the European style, the order of the parameters is changed to @var{day},
-@var{month}, @var{year}.)
-@end table
-
-@node Appt Customizing
-@section Customizing Appointment Reminders
-
- You can specify exactly how Emacs reminds you of an appointment, and
-how far in advance it begins doing so, by setting these variables:
-
-@vindex appt-message-warning-time
-@vindex appt-audible
-@vindex appt-visible
-@vindex appt-display-mode-line
-@vindex appt-msg-window
-@vindex appt-display-duration
-@vindex appt-disp-window-function
-@vindex appt-delete-window-function
-@table @code
-@item appt-message-warning-time
-The time in minutes before an appointment that the reminder begins. The
-default is 10 minutes.
-@item appt-audible
-If this is non-@code{nil}, Emacs rings the
-terminal bell for appointment reminders. The default is @code{t}.
-@item appt-visible
-If this is non-@code{nil}, Emacs displays the appointment
-message in the echo area. The default is @code{t}.
-@item appt-display-mode-line
-If this is non-@code{nil}, Emacs displays the number of minutes
-to the appointment on the mode line. The default is @code{t}.
-@item appt-msg-window
-If this is non-@code{nil}, Emacs displays the appointment
-message in another window. The default is @code{t}.
-@item appt-disp-window-function
-This variable holds a function to use to create the other window
-for the appointment message.
-@item appt-delete-window-function
-This variable holds a function to use to get rid of the appointment
-message window, when its time is up.
-@item appt-display-duration
-The number of seconds to display an appointment message. The default
-is 5 seconds.
-@end table
diff --git a/lispref/commands.texi b/lispref/commands.texi
deleted file mode 100644
index d8199e27161..00000000000
--- a/lispref/commands.texi
+++ /dev/null
@@ -1,2493 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/commands
-@node Command Loop, Keymaps, Minibuffers, Top
-@chapter Command Loop
-@cindex editor command loop
-@cindex command loop
-
- When you run Emacs, it enters the @dfn{editor command loop} almost
-immediately. This loop reads key sequences, executes their definitions,
-and displays the results. In this chapter, we describe how these things
-are done, and the subroutines that allow Lisp programs to do them.
-
-@menu
-* Command Overview:: How the command loop reads commands.
-* Defining Commands:: Specifying how a function should read arguments.
-* Interactive Call:: Calling a command, so that it will read arguments.
-* Command Loop Info:: Variables set by the command loop for you to examine.
-* Input Events:: What input looks like when you read it.
-* Reading Input:: How to read input events from the keyboard or mouse.
-* Waiting:: Waiting for user input or elapsed time.
-* Quitting:: How @kbd{C-g} works. How to catch or defer quitting.
-* Prefix Command Arguments:: How the commands to set prefix args work.
-* Recursive Editing:: Entering a recursive edit,
- and why you usually shouldn't.
-* Disabling Commands:: How the command loop handles disabled commands.
-* Command History:: How the command history is set up, and how accessed.
-* Keyboard Macros:: How keyboard macros are implemented.
-@end menu
-
-@node Command Overview
-@section Command Loop Overview
-
- The first thing the command loop must do is read a key sequence, which
-is a sequence of events that translates into a command. It does this by
-calling the function @code{read-key-sequence}. Your Lisp code can also
-call this function (@pxref{Key Sequence Input}). Lisp programs can also
-do input at a lower level with @code{read-event} (@pxref{Reading One
-Event}) or discard pending input with @code{discard-input}
-(@pxref{Event Input Misc}).
-
- The key sequence is translated into a command through the currently
-active keymaps. @xref{Key Lookup}, for information on how this is done.
-The result should be a keyboard macro or an interactively callable
-function. If the key is @kbd{M-x}, then it reads the name of another
-command, which it then calls. This is done by the command
-@code{execute-extended-command} (@pxref{Interactive Call}).
-
- To execute a command requires first reading the arguments for it.
-This is done by calling @code{command-execute} (@pxref{Interactive
-Call}). For commands written in Lisp, the @code{interactive}
-specification says how to read the arguments. This may use the prefix
-argument (@pxref{Prefix Command Arguments}) or may read with prompting
-in the minibuffer (@pxref{Minibuffers}). For example, the command
-@code{find-file} has an @code{interactive} specification which says to
-read a file name using the minibuffer. The command's function body does
-not use the minibuffer; if you call this command from Lisp code as a
-function, you must supply the file name string as an ordinary Lisp
-function argument.
-
- If the command is a string or vector (i.e., a keyboard macro) then
-@code{execute-kbd-macro} is used to execute it. You can call this
-function yourself (@pxref{Keyboard Macros}).
-
- To terminate the execution of a running command, type @kbd{C-g}. This
-character causes @dfn{quitting} (@pxref{Quitting}).
-
-@defvar pre-command-hook
-The editor command loop runs this normal hook before each command. At
-that time, @code{this-command} contains the command that is about to
-run, and @code{last-command} describes the previous command.
-@xref{Hooks}.
-@end defvar
-
-@defvar post-command-hook
-The editor command loop runs this normal hook after each command
-(including commands terminated prematurely by quitting or by errors),
-and also when the command loop is first entered. At that time,
-@code{this-command} describes the command that just ran, and
-@code{last-command} describes the command before that. @xref{Hooks}.
-@end defvar
-
- Quitting is suppressed while running @code{pre-command-hook} and
-@code{post-command-hook}. If an error happens while executing one of
-these hooks, it terminates execution of the hook, but that is all it
-does.
-
-@node Defining Commands
-@section Defining Commands
-@cindex defining commands
-@cindex commands, defining
-@cindex functions, making them interactive
-@cindex interactive function
-
- A Lisp function becomes a command when its body contains, at top
-level, a form that calls the special form @code{interactive}. This
-form does nothing when actually executed, but its presence serves as a
-flag to indicate that interactive calling is permitted. Its argument
-controls the reading of arguments for an interactive call.
-
-@menu
-* Using Interactive:: General rules for @code{interactive}.
-* Interactive Codes:: The standard letter-codes for reading arguments
- in various ways.
-* Interactive Examples:: Examples of how to read interactive arguments.
-@end menu
-
-@node Using Interactive
-@subsection Using @code{interactive}
-
- This section describes how to write the @code{interactive} form that
-makes a Lisp function an interactively-callable command.
-
-@defspec interactive arg-descriptor
-@cindex argument descriptors
-This special form declares that the function in which it appears is a
-command, and that it may therefore be called interactively (via
-@kbd{M-x} or by entering a key sequence bound to it). The argument
-@var{arg-descriptor} declares how to compute the arguments to the
-command when the command is called interactively.
-
-A command may be called from Lisp programs like any other function, but
-then the caller supplies the arguments and @var{arg-descriptor} has no
-effect.
-
-The @code{interactive} form has its effect because the command loop
-(actually, its subroutine @code{call-interactively}) scans through the
-function definition looking for it, before calling the function. Once
-the function is called, all its body forms including the
-@code{interactive} form are executed, but at this time
-@code{interactive} simply returns @code{nil} without even evaluating its
-argument.
-@end defspec
-
-There are three possibilities for the argument @var{arg-descriptor}:
-
-@itemize @bullet
-@item
-It may be omitted or @code{nil}; then the command is called with no
-arguments. This leads quickly to an error if the command requires one
-or more arguments.
-
-@item
-It may be a Lisp expression that is not a string; then it should be a
-form that is evaluated to get a list of arguments to pass to the
-command.
-@cindex argument evaluation form
-
-If this expression reads keyboard input (this includes using the
-minibuffer), keep in mind that the integer value of point or the mark
-before reading input may be incorrect after reading input. This is
-because the current buffer may be receiving subprocess output;
-if subprocess output arrives while the command is waiting for input,
-it could relocate point and the mark.
-
-Here's an example of what @emph{not} to do:
-
-@smallexample
-(interactive
- (list (region-beginning) (region-end)
- (read-string "Foo: " nil 'my-history)))
-@end smallexample
-
-@noindent
-Here's how to avoid the problem, by examining point and the mark only
-after reading the keyboard input:
-
-@smallexample
-(interactive
- (let ((string (read-string "Foo: " nil 'my-history)))
- (list (region-beginning) (region-end) string)))
-@end smallexample
-
-@item
-@cindex argument prompt
-It may be a string; then its contents should consist of a code character
-followed by a prompt (which some code characters use and some ignore).
-The prompt ends either with the end of the string or with a newline.
-Here is a simple example:
-
-@smallexample
-(interactive "bFrobnicate buffer: ")
-@end smallexample
-
-@noindent
-The code letter @samp{b} says to read the name of an existing buffer,
-with completion. The buffer name is the sole argument passed to the
-command. The rest of the string is a prompt.
-
-If there is a newline character in the string, it terminates the prompt.
-If the string does not end there, then the rest of the string should
-contain another code character and prompt, specifying another argument.
-You can specify any number of arguments in this way.
-
-@c Emacs 19 feature
-The prompt string can use @samp{%} to include previous argument values
-(starting with the first argument) in the prompt. This is done using
-@code{format} (@pxref{Formatting Strings}). For example, here is how
-you could read the name of an existing buffer followed by a new name to
-give to that buffer:
-
-@smallexample
-@group
-(interactive "bBuffer to rename: \nsRename buffer %s to: ")
-@end group
-@end smallexample
-
-@cindex @samp{*} in interactive
-@cindex read-only buffers in interactive
-If the first character in the string is @samp{*}, then an error is
-signaled if the buffer is read-only.
-
-@cindex @samp{@@} in interactive
-@c Emacs 19 feature
-If the first character in the string is @samp{@@}, and if the key
-sequence used to invoke the command includes any mouse events, then
-the window associated with the first of those events is selected
-before the command is run.
-
-You can use @samp{*} and @samp{@@} together; the order does not matter.
-Actual reading of arguments is controlled by the rest of the prompt
-string (starting with the first character that is not @samp{*} or
-@samp{@@}).
-@end itemize
-
-@node Interactive Codes
-@comment node-name, next, previous, up
-@subsection Code Characters for @code{interactive}
-@cindex interactive code description
-@cindex description for interactive codes
-@cindex codes, interactive, description of
-@cindex characters for interactive codes
-
- The code character descriptions below contain a number of key words,
-defined here as follows:
-
-@table @b
-@item Completion
-@cindex interactive completion
-Provide completion. @key{TAB}, @key{SPC}, and @key{RET} perform name
-completion because the argument is read using @code{completing-read}
-(@pxref{Completion}). @kbd{?} displays a list of possible completions.
-
-@item Existing
-Require the name of an existing object. An invalid name is not
-accepted; the commands to exit the minibuffer do not exit if the current
-input is not valid.
-
-@item Default
-@cindex default argument string
-A default value of some sort is used if the user enters no text in the
-minibuffer. The default depends on the code character.
-
-@item No I/O
-This code letter computes an argument without reading any input.
-Therefore, it does not use a prompt string, and any prompt string you
-supply is ignored.
-
-Even though the code letter doesn't use a prompt string, you must follow
-it with a newline if it is not the last code character in the string.
-
-@item Prompt
-A prompt immediately follows the code character. The prompt ends either
-with the end of the string or with a newline.
-
-@item Special
-This code character is meaningful only at the beginning of the
-interactive string, and it does not look for a prompt or a newline.
-It is a single, isolated character.
-@end table
-
-@cindex reading interactive arguments
- Here are the code character descriptions for use with @code{interactive}:
-
-@table @samp
-@item *
-Signal an error if the current buffer is read-only. Special.
-
-@item @@
-Select the window mentioned in the first mouse event in the key
-sequence that invoked this command. Special.
-
-@item a
-A function name (i.e., a symbol satisfying @code{fboundp}). Existing,
-Completion, Prompt.
-
-@item b
-The name of an existing buffer. By default, uses the name of the
-current buffer (@pxref{Buffers}). Existing, Completion, Default,
-Prompt.
-
-@item B
-A buffer name. The buffer need not exist. By default, uses the name of
-a recently used buffer other than the current buffer. Completion,
-Default, Prompt.
-
-@item c
-A character. The cursor does not move into the echo area. Prompt.
-
-@item C
-A command name (i.e., a symbol satisfying @code{commandp}). Existing,
-Completion, Prompt.
-
-@item d
-@cindex position argument
-The position of point, as an integer (@pxref{Point}). No I/O.
-
-@item D
-A directory name. The default is the current default directory of the
-current buffer, @code{default-directory} (@pxref{System Environment}).
-Existing, Completion, Default, Prompt.
-
-@item e
-The first or next mouse event in the key sequence that invoked the command.
-More precisely, @samp{e} gets events that are lists, so you can look at
-the data in the lists. @xref{Input Events}. No I/O.
-
-You can use @samp{e} more than once in a single command's interactive
-specification. If the key sequence that invoked the command has
-@var{n} events that are lists, the @var{n}th @samp{e} provides the
-@var{n}th such event. Events that are not lists, such as function keys
-and @sc{ASCII} characters, do not count where @samp{e} is concerned.
-
-@item f
-A file name of an existing file (@pxref{File Names}). The default
-directory is @code{default-directory}. Existing, Completion, Default,
-Prompt.
-
-@item F
-A file name. The file need not exist. Completion, Default, Prompt.
-
-@item k
-A key sequence (@pxref{Keymap Terminology}). This keeps reading events
-until a command (or undefined command) is found in the current key
-maps. The key sequence argument is represented as a string or vector.
-The cursor does not move into the echo area. Prompt.
-
-This kind of input is used by commands such as @code{describe-key} and
-@code{global-set-key}.
-
-@item K
-A key sequence, whose definition you intend to change. This works like
-@samp{k}, except that it suppresses, for the last input event in the key
-sequence, the conversions that are normally used (when necessary) to
-convert an undefined key into a defined one.
-
-@item m
-@cindex marker argument
-The position of the mark, as an integer. No I/O.
-
-@item n
-A number read with the minibuffer. If the input is not a number, the
-user is asked to try again. The prefix argument, if any, is not used.
-Prompt.
-
-@item N
-@cindex raw prefix argument usage
-The numeric prefix argument; but if there is no prefix argument, read a
-number as with @kbd{n}. Requires a number. @xref{Prefix Command
-Arguments}. Prompt.
-
-@item p
-@cindex numeric prefix argument usage
-The numeric prefix argument. (Note that this @samp{p} is lower case.)
-No I/O.
-
-@item P
-The raw prefix argument. (Note that this @samp{P} is upper case.) No
-I/O.
-
-@item r
-@cindex region argument
-Point and the mark, as two numeric arguments, smallest first. This is
-the only code letter that specifies two successive arguments rather than
-one. No I/O.
-
-@item s
-Arbitrary text, read in the minibuffer and returned as a string
-(@pxref{Text from Minibuffer}). Terminate the input with either
-@key{LFD} or @key{RET}. (@kbd{C-q} may be used to include either of
-these characters in the input.) Prompt.
-
-@item S
-An interned symbol whose name is read in the minibuffer. Any whitespace
-character terminates the input. (Use @kbd{C-q} to include whitespace in
-the string.) Other characters that normally terminate a symbol (e.g.,
-parentheses and brackets) do not do so here. Prompt.
-
-@item v
-A variable declared to be a user option (i.e., satisfying the predicate
-@code{user-variable-p}). @xref{High-Level Completion}. Existing,
-Completion, Prompt.
-
-@item x
-A Lisp object, specified with its read syntax, terminated with a
-@key{LFD} or @key{RET}. The object is not evaluated. @xref{Object from
-Minibuffer}. Prompt.
-
-@item X
-@cindex evaluated expression argument
-A Lisp form is read as with @kbd{x}, but then evaluated so that its
-value becomes the argument for the command. Prompt.
-@end table
-
-@node Interactive Examples
-@comment node-name, next, previous, up
-@subsection Examples of Using @code{interactive}
-@cindex examples of using @code{interactive}
-@cindex @code{interactive}, examples of using
-
- Here are some examples of @code{interactive}:
-
-@example
-@group
-(defun foo1 () ; @r{@code{foo1} takes no arguments,}
- (interactive) ; @r{just moves forward two words.}
- (forward-word 2))
- @result{} foo1
-@end group
-
-@group
-(defun foo2 (n) ; @r{@code{foo2} takes one argument,}
- (interactive "p") ; @r{which is the numeric prefix.}
- (forward-word (* 2 n)))
- @result{} foo2
-@end group
-
-@group
-(defun foo3 (n) ; @r{@code{foo3} takes one argument,}
- (interactive "nCount:") ; @r{which is read with the Minibuffer.}
- (forward-word (* 2 n)))
- @result{} foo3
-@end group
-
-@group
-(defun three-b (b1 b2 b3)
- "Select three existing buffers.
-Put them into three windows, selecting the last one."
-@end group
- (interactive "bBuffer1:\nbBuffer2:\nbBuffer3:")
- (delete-other-windows)
- (split-window (selected-window) 8)
- (switch-to-buffer b1)
- (other-window 1)
- (split-window (selected-window) 8)
- (switch-to-buffer b2)
- (other-window 1)
- (switch-to-buffer b3))
- @result{} three-b
-@group
-(three-b "*scratch*" "declarations.texi" "*mail*")
- @result{} nil
-@end group
-@end example
-
-@node Interactive Call
-@section Interactive Call
-@cindex interactive call
-
- After the command loop has translated a key sequence into a
-definition, it invokes that definition using the function
-@code{command-execute}. If the definition is a function that is a
-command, @code{command-execute} calls @code{call-interactively}, which
-reads the arguments and calls the command. You can also call these
-functions yourself.
-
-@defun commandp object
-Returns @code{t} if @var{object} is suitable for calling interactively;
-that is, if @var{object} is a command. Otherwise, returns @code{nil}.
-
-The interactively callable objects include strings and vectors (treated
-as keyboard macros), lambda expressions that contain a top-level call to
-@code{interactive}, byte-code function objects made from such lambda
-expressions, autoload objects that are declared as interactive
-(non-@code{nil} fourth argument to @code{autoload}), and some of the
-primitive functions.
-
-A symbol is @code{commandp} if its function definition is
-@code{commandp}.
-
-Keys and keymaps are not commands. Rather, they are used to look up
-commands (@pxref{Keymaps}).
-
-See @code{documentation} in @ref{Accessing Documentation}, for a
-realistic example of using @code{commandp}.
-@end defun
-
-@defun call-interactively command &optional record-flag
-This function calls the interactively callable function @var{command},
-reading arguments according to its interactive calling specifications.
-An error is signaled if @var{command} is not a function or if it cannot
-be called interactively (i.e., is not a command). Note that keyboard
-macros (strings and vectors) are not accepted, even though they are
-considered commands, because they are not functions.
-
-@cindex record command history
-If @var{record-flag} is non-@code{nil}, then this command and its
-arguments are unconditionally added to the list @code{command-history}.
-Otherwise, the command is added only if it uses the minibuffer to read
-an argument. @xref{Command History}.
-@end defun
-
-@defun command-execute command &optional record-flag
-@cindex keyboard macro execution
-This function executes @var{command} as an editing command. The
-argument @var{command} must satisfy the @code{commandp} predicate; i.e.,
-it must be an interactively callable function or a keyboard macro.
-
-A string or vector as @var{command} is executed with
-@code{execute-kbd-macro}. A function is passed to
-@code{call-interactively}, along with the optional @var{record-flag}.
-
-A symbol is handled by using its function definition in its place. A
-symbol with an @code{autoload} definition counts as a command if it was
-declared to stand for an interactively callable function. Such a
-definition is handled by loading the specified library and then
-rechecking the definition of the symbol.
-@end defun
-
-@deffn Command execute-extended-command prefix-argument
-@cindex read command name
-This function reads a command name from the minibuffer using
-@code{completing-read} (@pxref{Completion}). Then it uses
-@code{command-execute} to call the specified command. Whatever that
-command returns becomes the value of @code{execute-extended-command}.
-
-@cindex execute with prefix argument
-If the command asks for a prefix argument, it receives the value
-@var{prefix-argument}. If @code{execute-extended-command} is called
-interactively, the current raw prefix argument is used for
-@var{prefix-argument}, and thus passed on to whatever command is run.
-
-@c !!! Should this be @kindex?
-@cindex @kbd{M-x}
-@code{execute-extended-command} is the normal definition of @kbd{M-x},
-so it uses the string @w{@samp{M-x }} as a prompt. (It would be better
-to take the prompt from the events used to invoke
-@code{execute-extended-command}, but that is painful to implement.) A
-description of the value of the prefix argument, if any, also becomes
-part of the prompt.
-
-@example
-@group
-(execute-extended-command 1)
----------- Buffer: Minibuffer ----------
-1 M-x forward-word RET
----------- Buffer: Minibuffer ----------
- @result{} t
-@end group
-@end example
-@end deffn
-
-@defun interactive-p
-This function returns @code{t} if the containing function (the one whose
-code includes the call to @code{interactive-p}) was called
-interactively, with the function @code{call-interactively}. (It makes
-no difference whether @code{call-interactively} was called from Lisp or
-directly from the editor command loop.) If the containing function was
-called by Lisp evaluation (or with @code{apply} or @code{funcall}), then
-it was not called interactively.
-
-The most common use of @code{interactive-p} is for deciding whether to
-print an informative message. As a special exception,
-@code{interactive-p} returns @code{nil} whenever a keyboard macro is
-being run. This is to suppress the informative messages and speed
-execution of the macro.
-
-For example:
-
-@example
-@group
-(defun foo ()
- (interactive)
- (and (interactive-p)
- (message "foo")))
- @result{} foo
-@end group
-
-@group
-(defun bar ()
- (interactive)
- (setq foobar (list (foo) (interactive-p))))
- @result{} bar
-@end group
-
-@group
-;; @r{Type @kbd{M-x foo}.}
- @print{} foo
-@end group
-
-@group
-;; @r{Type @kbd{M-x bar}.}
-;; @r{This does not print anything.}
-@end group
-
-@group
-foobar
- @result{} (nil t)
-@end group
-@end example
-@end defun
-
-@node Command Loop Info
-@comment node-name, next, previous, up
-@section Information from the Command Loop
-
-The editor command loop sets several Lisp variables to keep status
-records for itself and for commands that are run.
-
-@defvar last-command
-This variable records the name of the previous command executed by the
-command loop (the one before the current command). Normally the value
-is a symbol with a function definition, but this is not guaranteed.
-
-The value is copied from @code{this-command} when a command returns to
-the command loop, except when the command specifies a prefix argument
-for the following command.
-
-This variable is always local to the current terminal and cannot be
-buffer-local. @xref{Multiple Displays}.
-@end defvar
-
-@defvar this-command
-@cindex current command
-This variable records the name of the command now being executed by
-the editor command loop. Like @code{last-command}, it is normally a symbol
-with a function definition.
-
-The command loop sets this variable just before running a command, and
-copies its value into @code{last-command} when the command finishes
-(unless the command specifies a prefix argument for the following
-command).
-
-@cindex kill command repetition
-Some commands set this variable during their execution, as a flag for
-whatever command runs next. In particular, the functions for killing text
-set @code{this-command} to @code{kill-region} so that any kill commands
-immediately following will know to append the killed text to the
-previous kill.
-@end defvar
-
-If you do not want a particular command to be recognized as the previous
-command in the case where it got an error, you must code that command to
-prevent this. One way is to set @code{this-command} to @code{t} at the
-beginning of the command, and set @code{this-command} back to its proper
-value at the end, like this:
-
-@example
-(defun foo (args@dots{})
- (interactive @dots{})
- (let ((old-this-command this-command))
- (setq this-command t)
- @r{@dots{}do the work@dots{}}
- (setq this-command old-this-command)))
-@end example
-
-@defun this-command-keys
-This function returns a string or vector containing the key sequence
-that invoked the present command, plus any previous commands that
-generated the prefix argument for this command. The value is a string
-if all those events were characters. @xref{Input Events}.
-
-@example
-@group
-(this-command-keys)
-;; @r{Now use @kbd{C-u C-x C-e} to evaluate that.}
- @result{} "^U^X^E"
-@end group
-@end example
-@end defun
-
-@defvar last-nonmenu-event
-This variable holds the last input event read as part of a key
-sequence, not counting events resulting from mouse menus.
-
-One use of this variable is to figure out a good default location to
-pop up another menu.
-@end defvar
-
-@defvar last-command-event
-@defvarx last-command-char
-This variable is set to the last input event that was read by the
-command loop as part of a command. The principal use of this variable
-is in @code{self-insert-command}, which uses it to decide which
-character to insert.
-
-@example
-@group
-last-command-event
-;; @r{Now use @kbd{C-u C-x C-e} to evaluate that.}
- @result{} 5
-@end group
-@end example
-
-@noindent
-The value is 5 because that is the @sc{ASCII} code for @kbd{C-e}.
-
-The alias @code{last-command-char} exists for compatibility with
-Emacs version 18.
-@end defvar
-
-@c Emacs 19 feature
-@defvar last-event-frame
-This variable records which frame the last input event was directed to.
-Usually this is the frame that was selected when the event was
-generated, but if that frame has redirected input focus to another
-frame, the value is the frame to which the event was redirected.
-@xref{Input Focus}.
-@end defvar
-
-@node Input Events
-@section Input Events
-@cindex events
-@cindex input events
-
-The Emacs command loop reads a sequence of @dfn{input events} that
-represent keyboard or mouse activity. The events for keyboard activity
-are characters or symbols; mouse events are always lists. This section
-describes the representation and meaning of input events in detail.
-
-@defun eventp object
-This function returns non-@code{nil} if @var{object} is an input event.
-@end defun
-
-@menu
-* Keyboard Events:: Ordinary characters--keys with symbols on them.
-* Function Keys:: Function keys--keys with names, not symbols.
-* Mouse Events:: Overview of mouse events.
-* Click Events:: Pushing and releasing a mouse button.
-* Drag Events:: Moving the mouse before releasing the button.
-* Button-Down Events:: A button was pushed and not yet released.
-* Repeat Events:: Double and triple click (or drag, or down).
-* Motion Events:: Just moving the mouse, not pushing a button.
-* Focus Events:: Moving the mouse between frames.
-* Misc Events:: Other events window systems can generate.
-* Event Examples:: Examples of the lists for mouse events.
-* Classifying Events:: Finding the modifier keys in an event symbol.
- Event types.
-* Accessing Events:: Functions to extract info from events.
-* Strings of Events:: Special considerations for putting
- keyboard character events in a string.
-@end menu
-
-@node Keyboard Events
-@subsection Keyboard Events
-
-There are two kinds of input you can get from the keyboard: ordinary
-keys, and function keys. Ordinary keys correspond to characters; the
-events they generate are represented in Lisp as characters. In Emacs
-versions 18 and earlier, characters were the only events. The event
-type of a character event is the character itself (an integer);
-see @ref{Classifying Events}.
-
-@cindex modifier bits (of input character)
-@cindex basic code (of input character)
-An input character event consists of a @dfn{basic code} between 0 and
-255, plus any or all of these @dfn{modifier bits}:
-
-@table @asis
-@item meta
-The
-@iftex
-$2^{27}$
-@end iftex
-@ifinfo
-2**27
-@end ifinfo
-bit in the character code indicates a character
-typed with the meta key held down.
-
-@item control
-The
-@iftex
-$2^{26}$
-@end iftex
-@ifinfo
-2**26
-@end ifinfo
-bit in the character code indicates a non-@sc{ASCII}
-control character.
-
-@sc{ASCII} control characters such as @kbd{C-a} have special basic
-codes of their own, so Emacs needs no special bit to indicate them.
-Thus, the code for @kbd{C-a} is just 1.
-
-But if you type a control combination not in @sc{ASCII}, such as
-@kbd{%} with the control key, the numeric value you get is the code
-for @kbd{%} plus
-@iftex
-$2^{26}$
-@end iftex
-@ifinfo
-2**26
-@end ifinfo
-(assuming the terminal supports non-@sc{ASCII}
-control characters).
-
-@item shift
-The
-@iftex
-$2^{25}$
-@end iftex
-@ifinfo
-2**25
-@end ifinfo
-bit in the character code indicates an @sc{ASCII} control
-character typed with the shift key held down.
-
-For letters, the basic code indicates upper versus lower case; for
-digits and punctuation, the shift key selects an entirely different
-character with a different basic code. In order to keep within
-the @sc{ASCII} character set whenever possible, Emacs avoids using
-the
-@iftex
-$2^{25}$
-@end iftex
-@ifinfo
-2**25
-@end ifinfo
-bit for those characters.
-
-However, @sc{ASCII} provides no way to distinguish @kbd{C-A} from
-@kbd{C-a}, so Emacs uses the
-@iftex
-$2^{25}$
-@end iftex
-@ifinfo
-2**25
-@end ifinfo
-bit in @kbd{C-A} and not in
-@kbd{C-a}.
-
-@item hyper
-The
-@iftex
-$2^{24}$
-@end iftex
-@ifinfo
-2**24
-@end ifinfo
-bit in the character code indicates a character
-typed with the hyper key held down.
-
-@item super
-The
-@iftex
-$2^{23}$
-@end iftex
-@ifinfo
-2**23
-@end ifinfo
-bit in the character code indicates a character
-typed with the super key held down.
-
-@item alt
-The
-@iftex
-$2^{22}$
-@end iftex
-@ifinfo
-2**22
-@end ifinfo
-bit in the character code indicates a character typed with
-the alt key held down. (On some terminals, the key labeled @key{ALT}
-is actually the meta key.)
-@end table
-
- It is best to avoid mentioning specific bit numbers in your program.
-To test the modifier bits of a character, use the function
-@code{event-modifiers} (@pxref{Classifying Events}). When making key
-bindings, you can use the read syntax for characters with modifier bits
-(@samp{\C-}, @samp{\M-}, and so on). For making key bindings with
-@code{define-key}, you can use lists such as @code{(control hyper ?x)} to
-specify the characters (@pxref{Changing Key Bindings}). The function
-@code{event-convert-list} converts such a list into an event type
-(@pxref{Classifying Events}).
-
-@node Function Keys
-@subsection Function Keys
-
-@cindex function keys
-Most keyboards also have @dfn{function keys}---keys that have names or
-symbols that are not characters. Function keys are represented in Lisp
-as symbols; the symbol's name is the function key's label, in lower
-case. For example, pressing a key labeled @key{F1} places the symbol
-@code{f1} in the input stream.
-
-The event type of a function key event is the event symbol itself.
-@xref{Classifying Events}.
-
-Here are a few special cases in the symbol-naming convention for
-function keys:
-
-@table @asis
-@item @code{backspace}, @code{tab}, @code{newline}, @code{return}, @code{delete}
-These keys correspond to common @sc{ASCII} control characters that have
-special keys on most keyboards.
-
-In @sc{ASCII}, @kbd{C-i} and @key{TAB} are the same character. If the
-terminal can distinguish between them, Emacs conveys the distinction to
-Lisp programs by representing the former as the integer 9, and the
-latter as the symbol @code{tab}.
-
-Most of the time, it's not useful to distinguish the two. So normally
-@code{function-key-map} (@pxref{Translating Input}) is set up to map
-@code{tab} into 9. Thus, a key binding for character code 9 (the
-character @kbd{C-i}) also applies to @code{tab}. Likewise for the other
-symbols in this group. The function @code{read-char} likewise converts
-these events into characters.
-
-In @sc{ASCII}, @key{BS} is really @kbd{C-h}. But @code{backspace}
-converts into the character code 127 (@key{DEL}), not into code 8
-(@key{BS}). This is what most users prefer.
-
-@item @code{left}, @code{up}, @code{right}, @code{down}
-Cursor arrow keys
-@item @code{kp-add}, @code{kp-decimal}, @code{kp-divide}, @dots{}
-Keypad keys (to the right of the regular keyboard).
-@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{kp-home}, @code{kp-left}, @code{kp-up}, @code{kp-right}, @code{kp-down}
-Keypad arrow keys. Emacs normally translates these
-into the non-keypad keys @code{home}, @code{left}, @dots{}
-@item @code{kp-prior}, @code{kp-next}, @code{kp-end}, @code{kp-begin}, @code{kp-insert}, @code{kp-delete}
-Additional keypad duplicates of keys ordinarily found elsewhere. Emacs
-normally translates these into the like-named non-keypad keys.
-@end table
-
-You can use the modifier keys @key{ALT}, @key{CTRL}, @key{HYPER},
-@key{META}, @key{SHIFT}, and @key{SUPER} with function keys. The way to
-represent them is with prefixes in the symbol name:
-
-@table @samp
-@item A-
-The alt modifier.
-@item C-
-The control modifier.
-@item H-
-The hyper modifier.
-@item M-
-The meta modifier.
-@item S-
-The shift modifier.
-@item s-
-The super modifier.
-@end table
-
-Thus, the symbol for the key @key{F3} with @key{META} held down is
-@code{M-f3}. When you use more than one prefix, we recommend you
-write them in alphabetical order; but the order does not matter in
-arguments to the key-binding lookup and modification functions.
-
-@node Mouse Events
-@subsection Mouse Events
-
-Emacs supports four kinds of mouse events: click events, drag events,
-button-down events, and motion events. All mouse events are represented
-as lists. The @sc{car} of the list is the event type; this says which
-mouse button was involved, and which modifier keys were used with it.
-The event type can also distinguish double or triple button presses
-(@pxref{Repeat Events}). The rest of the list elements give position
-and time information.
-
-For key lookup, only the event type matters: two events of the same type
-necessarily run the same command. The command can access the full
-values of these events using the @samp{e} interactive code.
-@xref{Interactive Codes}.
-
-A key sequence that starts with a mouse event is read using the keymaps
-of the buffer in the window that the mouse was in, not the current
-buffer. This does not imply that clicking in a window selects that
-window or its buffer---that is entirely under the control of the command
-binding of the key sequence.
-
-@node Click Events
-@subsection Click Events
-@cindex click event
-@cindex mouse click event
-
-When the user presses a mouse button and releases it at the same
-location, that generates a @dfn{click} event. Mouse click events have
-this form:
-
-@example
-(@var{event-type}
- (@var{window} @var{buffer-pos} (@var{x} . @var{y}) @var{timestamp})
- @var{click-count})
-@end example
-
-Here is what the elements normally mean:
-
-@table @asis
-@item @var{event-type}
-This is a symbol that indicates which mouse button was used. It is
-one of the symbols @code{mouse-1}, @code{mouse-2}, @dots{}, where the
-buttons are numbered left to right.
-
-You can also use prefixes @samp{A-}, @samp{C-}, @samp{H-}, @samp{M-},
-@samp{S-} and @samp{s-} for modifiers alt, control, hyper, meta, shift
-and super, just as you would with function keys.
-
-This symbol also serves as the event type of the event. Key bindings
-describe events by their types; thus, if there is a key binding for
-@code{mouse-1}, that binding would apply to all events whose
-@var{event-type} is @code{mouse-1}.
-
-@item @var{window}
-This is the window in which the click occurred.
-
-@item @var{x}, @var{y}
-These are the pixel-denominated coordinates of the click, relative to
-the top left corner of @var{window}, which is @code{(0 . 0)}.
-
-@item @var{buffer-pos}
-This is the buffer position of the character clicked on.
-
-@item @var{timestamp}
-This is the time at which the event occurred, in milliseconds. (Since
-this value wraps around the entire range of Emacs Lisp integers in about
-five hours, it is useful only for relating the times of nearby events.)
-
-@item @var{click-count}
-This is the number of rapid repeated presses so far of the same mouse
-button. @xref{Repeat Events}.
-@end table
-
-The meanings of @var{buffer-pos}, @var{x} and @var{y} are somewhat
-different when the event location is in a special part of the screen,
-such as the mode line or a scroll bar.
-
-If the location is in a scroll bar, then @var{buffer-pos} is the symbol
-@code{vertical-scroll-bar} or @code{horizontal-scroll-bar}, and the pair
-@code{(@var{x} . @var{y})} is replaced with a pair @code{(@var{portion}
-. @var{whole})}, where @var{portion} is the distance of the click from
-the top or left end of the scroll bar, and @var{whole} is the length of
-the entire scroll bar.
-
-If the position is on a mode line or the vertical line separating
-@var{window} from its neighbor to the right, then @var{buffer-pos} is
-the symbol @code{mode-line} or @code{vertical-line}. For the mode line,
-@var{y} does not have meaningful data. For the vertical line, @var{x}
-does not have meaningful data.
-
-In one special case, @var{buffer-pos} is a list containing a symbol (one
-of the symbols listed above) instead of just the symbol. This happens
-after the imaginary prefix keys for the event are inserted into the
-input stream. @xref{Key Sequence Input}.
-
-@node Drag Events
-@subsection Drag Events
-@cindex drag event
-@cindex mouse drag event
-
-With Emacs, you can have a drag event without even changing your
-clothes. A @dfn{drag event} happens every time the user presses a mouse
-button and then moves the mouse to a different character position before
-releasing the button. Like all mouse events, drag events are
-represented in Lisp as lists. The lists record both the starting mouse
-position and the final position, like this:
-
-@example
-(@var{event-type}
- (@var{window1} @var{buffer-pos1} (@var{x1} . @var{y1}) @var{timestamp1})
- (@var{window2} @var{buffer-pos2} (@var{x2} . @var{y2}) @var{timestamp2})
- @var{click-count})
-@end example
-
-For a drag event, the name of the symbol @var{event-type} contains the
-prefix @samp{drag-}. The second and third elements of the event give
-the starting and ending position of the drag. Aside from that, the data
-have the same meanings as in a click event (@pxref{Click Events}). You
-can access the second element of any mouse event in the same way, with
-no need to distinguish drag events from others.
-
-The @samp{drag-} prefix follows the modifier key prefixes such as
-@samp{C-} and @samp{M-}.
-
-If @code{read-key-sequence} receives a drag event that has no key
-binding, and the corresponding click event does have a binding, it
-changes the drag event into a click event at the drag's starting
-position. This means that you don't have to distinguish between click
-and drag events unless you want to.
-
-@node Button-Down Events
-@subsection Button-Down Events
-@cindex button-down event
-
-Click and drag events happen when the user releases a mouse button.
-They cannot happen earlier, because there is no way to distinguish a
-click from a drag until the button is released.
-
-If you want to take action as soon as a button is pressed, you need to
-handle @dfn{button-down} events.@footnote{Button-down is the
-conservative antithesis of drag.} These occur as soon as a button is
-pressed. They are represented by lists that look exactly like click
-events (@pxref{Click Events}), except that the @var{event-type} symbol
-name contains the prefix @samp{down-}. The @samp{down-} prefix follows
-modifier key prefixes such as @samp{C-} and @samp{M-}.
-
-The function @code{read-key-sequence}, and therefore the Emacs command
-loop as well, ignore any button-down events that don't have command
-bindings. This means that you need not worry about defining button-down
-events unless you want them to do something. The usual reason to define
-a button-down event is so that you can track mouse motion (by reading
-motion events) until the button is released. @xref{Motion Events}.
-
-@node Repeat Events
-@subsection Repeat Events
-@cindex repeat events
-@cindex double-click events
-@cindex triple-click events
-
-If you press the same mouse button more than once in quick succession
-without moving the mouse, Emacs generates special @dfn{repeat} mouse
-events for the second and subsequent presses.
-
-The most common repeat events are @dfn{double-click} events. Emacs
-generates a double-click event when you click a button twice; the event
-happens when you release the button (as is normal for all click
-events).
-
-The event type of a double-click event contains the prefix
-@samp{double-}. Thus, a double click on the second mouse button with
-@key{meta} held down comes to the Lisp program as
-@code{M-double-mouse-2}. If a double-click event has no binding, the
-binding of the corresponding ordinary click event is used to execute
-it. Thus, you need not pay attention to the double click feature
-unless you really want to.
-
-When the user performs a double click, Emacs generates first an ordinary
-click event, and then a double-click event. Therefore, you must design
-the command binding of the double click event to assume that the
-single-click command has already run. It must produce the desired
-results of a double click, starting from the results of a single click.
-
-This is convenient, if the meaning of a double click somehow ``builds
-on'' the meaning of a single click---which is recommended user interface
-design practice for double clicks.
-
-If you click a button, then press it down again and start moving the
-mouse with the button held down, then you get a @dfn{double-drag} event
-when you ultimately release the button. Its event type contains
-@samp{double-drag} instead of just @samp{drag}. If a double-drag event
-has no binding, Emacs looks for an alternate binding as if the event
-were an ordinary drag.
-
-Before the double-click or double-drag event, Emacs generates a
-@dfn{double-down} event when the user presses the button down for the
-second time. Its event type contains @samp{double-down} instead of just
-@samp{down}. If a double-down event has no binding, Emacs looks for an
-alternate binding as if the event were an ordinary button-down event.
-If it finds no binding that way either, the double-down event is
-ignored.
-
-To summarize, when you click a button and then press it again right
-away, Emacs generates a down event and a click event for the first
-click, a double-down event when you press the button again, and finally
-either a double-click or a double-drag event.
-
-If you click a button twice and then press it again, all in quick
-succession, Emacs generates a @dfn{triple-down} event, followed by
-either a @dfn{triple-click} or a @dfn{triple-drag}. The event types of
-these events contain @samp{triple} instead of @samp{double}. If any
-triple event has no binding, Emacs uses the binding that it would use
-for the corresponding double event.
-
-If you click a button three or more times and then press it again, the
-events for the presses beyond the third are all triple events. Emacs
-does not have separate event types for quadruple, quintuple, etc.@:
-events. However, you can look at the event list to find out precisely
-how many times the button was pressed.
-
-@defun event-click-count event
-This function returns the number of consecutive button presses that led
-up to @var{event}. If @var{event} is a double-down, double-click or
-double-drag event, the value is 2. If @var{event} is a triple event,
-the value is 3 or greater. If @var{event} is an ordinary mouse event
-(not a repeat event), the value is 1.
-@end defun
-
-@defvar double-click-time
-To generate repeat events, successive mouse button presses must be at
-the same screen position, and the number of milliseconds between
-successive button presses must be less than the value of
-@code{double-click-time}. Setting @code{double-click-time} to
-@code{nil} disables multi-click detection entirely. Setting it to
-@code{t} removes the time limit; Emacs then detects multi-clicks by
-position only.
-@end defvar
-
-@node Motion Events
-@subsection Motion Events
-@cindex motion event
-@cindex mouse motion events
-
-Emacs sometimes generates @dfn{mouse motion} events to describe motion
-of the mouse without any button activity. Mouse motion events are
-represented by lists that look like this:
-
-@example
-(mouse-movement
- (@var{window} @var{buffer-pos} (@var{x} . @var{y}) @var{timestamp}))
-@end example
-
-The second element of the list describes the current position of the
-mouse, just as in a click event (@pxref{Click Events}).
-
-The special form @code{track-mouse} enables generation of motion events
-within its body. Outside of @code{track-mouse} forms, Emacs does not
-generate events for mere motion of the mouse, and these events do not
-appear.
-
-@defspec track-mouse body@dots{}
-This special form executes @var{body}, with generation of mouse motion
-events enabled. Typically @var{body} would use @code{read-event}
-to read the motion events and modify the display accordingly.
-
-When the user releases the button, that generates a click event.
-Typically, @var{body} should return when it sees the click event, and
-discard that event.
-@end defspec
-
-@node Focus Events
-@subsection Focus Events
-@cindex focus event
-
-Window systems provide general ways for the user to control which window
-gets keyboard input. This choice of window is called the @dfn{focus}.
-When the user does something to switch between Emacs frames, that
-generates a @dfn{focus event}. The normal definition of a focus event,
-in the global keymap, is to select a new frame within Emacs, as the user
-would expect. @xref{Input Focus}.
-
-Focus events are represented in Lisp as lists that look like this:
-
-@example
-(switch-frame @var{new-frame})
-@end example
-
-@noindent
-where @var{new-frame} is the frame switched to.
-
-Most X window managers are set up so that just moving the mouse into a
-window is enough to set the focus there. Emacs appears to do this,
-because it changes the cursor to solid in the new frame. However, there
-is no need for the Lisp program to know about the focus change until
-some other kind of input arrives. So Emacs generates a focus event only
-when the user actually types a keyboard key or presses a mouse button in
-the new frame; just moving the mouse between frames does not generate a
-focus event.
-
-A focus event in the middle of a key sequence would garble the
-sequence. So Emacs never generates a focus event in the middle of a key
-sequence. If the user changes focus in the middle of a key
-sequence---that is, after a prefix key---then Emacs reorders the events
-so that the focus event comes either before or after the multi-event key
-sequence, and not within it.
-
-@node Misc Events
-@subsection Miscellaneous Window System Events
-
-A few other event types represent occurrences within the window system.
-
-@table @code
-@cindex @code{delete-frame} event
-@item (delete-frame (@var{frame}))
-This kind of event indicates that the user gave the window manager
-a command to delete a particular window, which happens to be an Emacs frame.
-
-The standard definition of the @code{delete-frame} event is to delete @var{frame}.
-
-@cindex @code{iconify-frame} event
-@item (iconify-frame (@var{frame}))
-This kind of event indicates that the user iconified @var{frame} using
-the window manager. Its standard definition is @code{ignore}; since the
-frame has already been iconified, Emacs has no work to do. The purpose
-of this event type is so that you can keep track of such events if you
-want to.
-
-@cindex @code{make-frame-visible} event
-@item (make-frame-visible (@var{frame}))
-This kind of event indicates that the user deiconified @var{frame} using
-the window manager. Its standard definition is @code{ignore}; since the
-frame has already been made visible, Emacs has no work to do.
-@end table
-
- If one of these events arrives in the middle of a key sequence---that
-is, after a prefix key---then Emacs reorders the events so that this
-event comes either before or after the multi-event key sequence, not
-within it.
-
-@node Event Examples
-@subsection Event Examples
-
-If the user presses and releases the left mouse button over the same
-location, that generates a sequence of events like this:
-
-@smallexample
-(down-mouse-1 (#<window 18 on NEWS> 2613 (0 . 38) -864320))
-(mouse-1 (#<window 18 on NEWS> 2613 (0 . 38) -864180))
-@end smallexample
-
-While holding the control key down, the user might hold down the
-second mouse button, and drag the mouse from one line to the next.
-That produces two events, as shown here:
-
-@smallexample
-(C-down-mouse-2 (#<window 18 on NEWS> 3440 (0 . 27) -731219))
-(C-drag-mouse-2 (#<window 18 on NEWS> 3440 (0 . 27) -731219)
- (#<window 18 on NEWS> 3510 (0 . 28) -729648))
-@end smallexample
-
-While holding down the meta and shift keys, the user might press the
-second mouse button on the window's mode line, and then drag the mouse
-into another window. That produces a pair of events like these:
-
-@smallexample
-(M-S-down-mouse-2 (#<window 18 on NEWS> mode-line (33 . 31) -457844))
-(M-S-drag-mouse-2 (#<window 18 on NEWS> mode-line (33 . 31) -457844)
- (#<window 20 on carlton-sanskrit.tex> 161 (33 . 3)
- -453816))
-@end smallexample
-
-@node Classifying Events
-@subsection Classifying Events
-@cindex event type
-
- Every event has an @dfn{event type}, which classifies the event for
-key binding purposes. For a keyboard event, the event type equals the
-event value; thus, the event type for a character is the character, and
-the event type for a function key symbol is the symbol itself. For
-events that are lists, the event type is the symbol in the @sc{car} of
-the list. Thus, the event type is always a symbol or a character.
-
- Two events of the same type are equivalent where key bindings are
-concerned; thus, they always run the same command. That does not
-necessarily mean they do the same things, however, as some commands look
-at the whole event to decide what to do. For example, some commands use
-the location of a mouse event to decide where in the buffer to act.
-
- Sometimes broader classifications of events are useful. For example,
-you might want to ask whether an event involved the @key{META} key,
-regardless of which other key or mouse button was used.
-
- The functions @code{event-modifiers} and @code{event-basic-type} are
-provided to get such information conveniently.
-
-@defun event-modifiers event
-This function returns a list of the modifiers that @var{event} has. The
-modifiers are symbols; they include @code{shift}, @code{control},
-@code{meta}, @code{alt}, @code{hyper} and @code{super}. In addition,
-the modifiers list of a mouse event symbol always contains one of
-@code{click}, @code{drag}, and @code{down}.
-
-The argument @var{event} may be an entire event object, or just an event
-type.
-
-Here are some examples:
-
-@example
-(event-modifiers ?a)
- @result{} nil
-(event-modifiers ?\C-a)
- @result{} (control)
-(event-modifiers ?\C-%)
- @result{} (control)
-(event-modifiers ?\C-\S-a)
- @result{} (control shift)
-(event-modifiers 'f5)
- @result{} nil
-(event-modifiers 's-f5)
- @result{} (super)
-(event-modifiers 'M-S-f5)
- @result{} (meta shift)
-(event-modifiers 'mouse-1)
- @result{} (click)
-(event-modifiers 'down-mouse-1)
- @result{} (down)
-@end example
-
-The modifiers list for a click event explicitly contains @code{click},
-but the event symbol name itself does not contain @samp{click}.
-@end defun
-
-@defun event-basic-type event
-This function returns the key or mouse button that @var{event}
-describes, with all modifiers removed. For example:
-
-@example
-(event-basic-type ?a)
- @result{} 97
-(event-basic-type ?A)
- @result{} 97
-(event-basic-type ?\C-a)
- @result{} 97
-(event-basic-type ?\C-\S-a)
- @result{} 97
-(event-basic-type 'f5)
- @result{} f5
-(event-basic-type 's-f5)
- @result{} f5
-(event-basic-type 'M-S-f5)
- @result{} f5
-(event-basic-type 'down-mouse-1)
- @result{} mouse-1
-@end example
-@end defun
-
-@defun mouse-movement-p object
-This function returns non-@code{nil} if @var{object} is a mouse movement
-event.
-@end defun
-
-@defun event-convert-list list
-This function converts a list of modifier names and a basic event type
-to an event type which specifies all of them. For example,
-
-@example
-(event-convert-list '(control ?a))
- @result{} 1
-(event-convert-list '(control meta ?a))
- @result{} -134217727
-(event-convert-list '(control super f1))
- @result{} C-s-f1
-@end example
-@end defun
-
-@node Accessing Events
-@subsection Accessing Events
-
- This section describes convenient functions for accessing the data in
-a mouse button or motion event.
-
- These two functions return the starting or ending position of a
-mouse-button event. The position is a list of this form:
-
-@example
-(@var{window} @var{buffer-position} (@var{x} . @var{y}) @var{timestamp})
-@end example
-
-@defun event-start event
-This returns the starting position of @var{event}.
-
-If @var{event} is a click or button-down event, this returns the
-location of the event. If @var{event} is a drag event, this returns the
-drag's starting position.
-@end defun
-
-@defun event-end event
-This returns the ending position of @var{event}.
-
-If @var{event} is a drag event, this returns the position where the user
-released the mouse button. If @var{event} is a click or button-down
-event, the value is actually the starting position, which is the only
-position such events have.
-@end defun
-
- These five functions take a position as described above, and return
-various parts of it.
-
-@defun posn-window position
-Return the window that @var{position} is in.
-@end defun
-
-@defun posn-point position
-Return the buffer position in @var{position}. This is an integer.
-@end defun
-
-@defun posn-x-y position
-Return the pixel-based x and y coordinates in @var{position}, as a cons
-cell @code{(@var{x} . @var{y})}.
-@end defun
-
-@defun posn-col-row position
-Return the row and column (in units of characters) of @var{position}, as
-a cons cell @code{(@var{col} . @var{row})}. These are computed from the
-@var{x} and @var{y} values actually found in @var{position}.
-@end defun
-
-@defun posn-timestamp position
-Return the timestamp in @var{position}.
-@end defun
-
-@defun scroll-bar-event-ratio event
-This function returns the fractional vertical position of a scroll bar
-event within the scroll bar. The value is a cons cell
-@code{(@var{portion} . @var{whole})} containing two integers whose ratio
-is the fractional position.
-@end defun
-
-@defun scroll-bar-scale ratio total
-This function multiplies (in effect) @var{ratio} by @var{total},
-rounding the result to an integer. The argument @var{ratio} is not a
-number, but rather a pair @code{(@var{num} . @var{denom})}---typically a
-value returned by @code{scroll-bar-event-ratio}.
-
-This function is handy for scaling a position on a scroll bar into a
-buffer position. Here's how to do that:
-
-@example
-(+ (point-min)
- (scroll-bar-scale
- (posn-x-y (event-start event))
- (- (point-max) (point-min))))
-@end example
-
-Recall that scroll bar events have two integers forming ratio in place
-of a pair of x and y coordinates.
-@end defun
-
-@node Strings of Events
-@subsection Putting Keyboard Events in Strings
-
- In most of the places where strings are used, we conceptualize the
-string as containing text characters---the same kind of characters found
-in buffers or files. Occasionally Lisp programs use strings that
-conceptually contain keyboard characters; for example, they may be key
-sequences or keyboard macro definitions. There are special rules for
-how to put keyboard characters into a string, because they are not
-limited to the range of 0 to 255 as text characters are.
-
- A keyboard character typed using the @key{META} key is called a
-@dfn{meta character}. The numeric code for such an event includes the
-@iftex
-$2^{27}$
-@end iftex
-@ifinfo
-2**27
-@end ifinfo
-bit; it does not even come close to fitting in a string. However,
-earlier Emacs versions used a different representation for these
-characters, which gave them codes in the range of 128 to 255. That did
-fit in a string, and many Lisp programs contain string constants that
-use @samp{\M-} to express meta characters, especially as the argument to
-@code{define-key} and similar functions.
-
- We provide backward compatibility to run those programs using special
-rules for how to put a keyboard character event in a string. Here are
-the rules:
-
-@itemize @bullet
-@item
-If the keyboard character value is in the range of 0 to 127, it can go
-in the string unchanged.
-
-@item
-The meta variants of those characters, with codes in the range of
-@iftex
-$2^{27}$
-@end iftex
-@ifinfo
-2**27
-@end ifinfo
-to
-@iftex
-$2^{27} + 127$,
-@end iftex
-@ifinfo
-2**27+127,
-@end ifinfo
-can also go in the string, but you must change their
-numeric values. You must set the
-@iftex
-$2^{7}$
-@end iftex
-@ifinfo
-2**7
-@end ifinfo
-bit instead of the
-@iftex
-$2^{27}$
-@end iftex
-@ifinfo
-2**27
-@end ifinfo
-bit,
-resulting in a value between 128 and 255.
-
-@item
-Other keyboard character events cannot fit in a string. This includes
-keyboard events in the range of 128 to 255.
-@end itemize
-
- Functions such as @code{read-key-sequence} that can construct strings
-of keyboard input characters follow these rules. They construct vectors
-instead of strings, when the events won't fit in a string.
-
- When you use the read syntax @samp{\M-} in a string, it produces a
-code in the range of 128 to 255---the same code that you get if you
-modify the corresponding keyboard event to put it in the string. Thus,
-meta events in strings work consistently regardless of how they get into
-the strings.
-
- The reason we changed the representation of meta characters as
-keyboard events is to make room for basic character codes beyond 127,
-and support meta variants of such larger character codes.
-
- New programs can avoid dealing with these special compatibility rules
-by using vectors instead of strings for key sequences when there is any
-possibility that they might contain meta characters, and by using
-@code{listify-key-sequence} to access a string of events.
-
-@defun listify-key-sequence key
-This function converts the string or vector @var{key} to a list of
-events, which you can put in @code{unread-command-events}. Converting a
-vector is simple, but converting a string is tricky because of the
-special representation used for meta characters in a string.
-@end defun
-
-@node Reading Input
-@section Reading Input
-
- The editor command loop reads keyboard input using the function
-@code{read-key-sequence}, which uses @code{read-event}. These and other
-functions for keyboard input are also available for use in Lisp
-programs. See also @code{momentary-string-display} in @ref{Temporary
-Displays}, and @code{sit-for} in @ref{Waiting}. @xref{Terminal Input},
-for functions and variables for controlling terminal input modes and
-debugging terminal input. @xref{Translating Input}, for features you
-can use for translating or modifying input events while reading them.
-
- For higher-level input facilities, see @ref{Minibuffers}.
-
-@menu
-* Key Sequence Input:: How to read one key sequence.
-* Reading One Event:: How to read just one event.
-* Quoted Character Input:: Asking the user to specify a character.
-* Event Input Misc:: How to reread or throw away input events.
-@end menu
-
-@node Key Sequence Input
-@subsection Key Sequence Input
-@cindex key sequence input
-
- The command loop reads input a key sequence at a time, by calling
-@code{read-key-sequence}. Lisp programs can also call this function;
-for example, @code{describe-key} uses it to read the key to describe.
-
-@defun read-key-sequence prompt
-@cindex key sequence
-This function reads a key sequence and returns it as a string or
-vector. It keeps reading events until it has accumulated a full key
-sequence; that is, enough to specify a non-prefix command using the
-currently active keymaps.
-
-If the events are all characters and all can fit in a string, then
-@code{read-key-sequence} returns a string (@pxref{Strings of Events}).
-Otherwise, it returns a vector, since a vector can hold all kinds of
-events---characters, symbols, and lists. The elements of the string or
-vector are the events in the key sequence.
-
-The function @code{read-key-sequence} suppresses quitting: @kbd{C-g}
-typed while reading with this function works like any other character,
-and does not set @code{quit-flag}. @xref{Quitting}.
-
-The argument @var{prompt} is either a string to be displayed in the echo
-area as a prompt, or @code{nil}, meaning not to display a prompt.
-
-In the example below, the prompt @samp{?} is displayed in the echo area,
-and the user types @kbd{C-x C-f}.
-
-@example
-(read-key-sequence "?")
-
-@group
----------- Echo Area ----------
-?@kbd{C-x C-f}
----------- Echo Area ----------
-
- @result{} "^X^F"
-@end group
-@end example
-@end defun
-
-@defvar num-input-keys
-@c Emacs 19 feature
-This variable's value is the number of key sequences processed so far in
-this Emacs session. This includes key sequences read from the terminal
-and key sequences read from keyboard macros being executed.
-@end defvar
-
-@cindex upper case key sequence
-@cindex downcasing in @code{lookup-key}
-If an input character is an upper-case letter and has no key binding,
-but its lower-case equivalent has one, then @code{read-key-sequence}
-converts the character to lower case. Note that @code{lookup-key} does
-not perform case conversion in this way.
-
-The function @code{read-key-sequence} also transforms some mouse events.
-It converts unbound drag events into click events, and discards unbound
-button-down events entirely. It also reshuffles focus events and
-miscellaneous window events so that they never appear in a key sequence
-with any other events.
-
-When mouse events occur in special parts of a window, such as a mode
-line or a scroll bar, the event type shows nothing special---it is the
-same symbol that would normally represent that combination of mouse
-button and modifier keys. The information about the window part is
-kept elsewhere in the event---in the coordinates. But
-@code{read-key-sequence} translates this information into imaginary
-prefix keys, all of which are symbols: @code{mode-line},
-@code{vertical-line}, @code{horizontal-scroll-bar} and
-@code{vertical-scroll-bar}.
-
-You can define meanings for mouse clicks in special window parts by
-defining key sequences using these imaginary prefix keys.
-
-For example, if you call @code{read-key-sequence} and then click the
-mouse on the window's mode line, you get two events, like this:
-
-@example
-(read-key-sequence "Click on the mode line: ")
- @result{} [mode-line
- (mouse-1
- (#<window 6 on NEWS> mode-line
- (40 . 63) 5959987))]
-@end example
-
-@node Reading One Event
-@subsection Reading One Event
-
- The lowest level functions for command input are those that read a
-single event.
-
-@defun read-event
-This function reads and returns the next event of command input, waiting
-if necessary until an event is available. Events can come directly from
-the user or from a keyboard macro.
-
-The function @code{read-event} does not display any message to indicate
-it is waiting for input; use @code{message} first, if you wish to
-display one. If you have not displayed a message, @code{read-event}
-prompts by echoing: it displays descriptions of the events that led to
-or were read by the current command. @xref{The Echo Area}.
-
-If @code{cursor-in-echo-area} is non-@code{nil}, then @code{read-event}
-moves the cursor temporarily to the echo area, to the end of any message
-displayed there. Otherwise @code{read-event} does not move the cursor.
-
-Here is what happens if you call @code{read-event} and then press the
-right-arrow function key:
-
-@example
-@group
-(read-event)
- @result{} right
-@end group
-@end example
-@end defun
-
-@defun read-char
-This function reads and returns a character of command input. It
-discards any events that are not characters, until it gets a character.
-
-In the first example, the user types the character @kbd{1} (@sc{ASCII}
-code 49). The second example shows a keyboard macro definition that
-calls @code{read-char} from the minibuffer using @code{eval-expression}.
-@code{read-char} reads the keyboard macro's very next character, which
-is @kbd{1}. Then @code{eval-expression} displays its return value in
-the echo area.
-
-@example
-@group
-(read-char)
- @result{} 49
-@end group
-
-@group
-;; @r{We assume here you use @kbd{M-:} to evaluate this.}
-(symbol-function 'foo)
- @result{} "^[:(read-char)^M1"
-@end group
-@group
-(execute-kbd-macro 'foo)
- @print{} 49
- @result{} nil
-@end group
-@end example
-@end defun
-
-@node Quoted Character Input
-@subsection Quoted Character Input
-@cindex quoted character input
-
- You can use the function @code{read-quoted-char} to ask the user to
-specify a character, and allow the user to specify a control or meta
-character conveniently, either literally or as an octal character code.
-The command @code{quoted-insert} uses this function.
-
-@defun read-quoted-char &optional prompt
-@cindex octal character input
-@cindex control characters, reading
-@cindex nonprinting characters, reading
-This function is like @code{read-char}, except that if the first
-character read is an octal digit (0-7), it reads up to two more octal digits
-(but stopping if a non-octal digit is found) and returns the
-character represented by those digits in octal.
-
-Quitting is suppressed when the first character is read, so that the
-user can enter a @kbd{C-g}. @xref{Quitting}.
-
-If @var{prompt} is supplied, it specifies a string for prompting the
-user. The prompt string is always displayed in the echo area, followed
-by a single @samp{-}.
-
-In the following example, the user types in the octal number 177 (which
-is 127 in decimal).
-
-@example
-(read-quoted-char "What character")
-
-@group
----------- Echo Area ----------
-What character-@kbd{177}
----------- Echo Area ----------
-
- @result{} 127
-@end group
-@end example
-@end defun
-
-@need 2000
-@node Event Input Misc
-@subsection Miscellaneous Event Input Features
-
-This section describes how to ``peek ahead'' at events without using
-them up, how to check for pending input, and how to discard pending
-input.
-
-@defvar unread-command-events
-@cindex next input
-@cindex peeking at input
-This variable holds a list of events waiting to be read as command
-input. The events are used in the order they appear in the list, and
-removed one by one as they are used.
-
-The variable is needed because in some cases a function reads a event
-and then decides not to use it. Storing the event in this variable
-causes it to be processed normally, by the command loop or by the
-functions to read command input.
-
-@cindex prefix argument unreading
-For example, the function that implements numeric prefix arguments reads
-any number of digits. When it finds a non-digit event, it must unread
-the event so that it can be read normally by the command loop.
-Likewise, incremental search uses this feature to unread events with no
-special meaning in a search, because these events should exit the search
-and then execute normally.
-
-The reliable and easy way to extract events from a key sequence so as to
-put them in @code{unread-command-events} is to use
-@code{listify-key-sequence} (@pxref{Strings of Events}).
-@end defvar
-
-@defvar unread-command-char
-This variable holds a character to be read as command input.
-A value of -1 means ``empty''.
-
-This variable is mostly obsolete now that you can use
-@code{unread-command-events} instead; it exists only to support programs
-written for Emacs versions 18 and earlier.
-@end defvar
-
-@defun input-pending-p
-@cindex waiting for command key input
-This function determines whether any command input is currently
-available to be read. It returns immediately, with value @code{t} if
-there is available input, @code{nil} otherwise. On rare occasions it
-may return @code{t} when no input is available.
-@end defun
-
-@defvar last-input-event
-This variable records the last terminal input event read, whether
-as part of a command or explicitly by a Lisp program.
-
-In the example below, the Lisp program reads the character @kbd{1},
-@sc{ASCII} code 49. It becomes the value of @code{last-input-event},
-while @kbd{C-e} (we assume @kbd{C-x C-e} command is used to evaluate
-this expression) remains the value of @code{last-command-event}.
-
-@example
-@group
-(progn (print (read-char))
- (print last-command-event)
- last-input-event)
- @print{} 49
- @print{} 5
- @result{} 49
-@end group
-@end example
-
-@vindex last-input-char
-The alias @code{last-input-char} exists for compatibility with
-Emacs version 18.
-@end defvar
-
-@defun discard-input
-@cindex flush input
-@cindex discard input
-@cindex terminate keyboard macro
-This function discards the contents of the terminal input buffer and
-cancels any keyboard macro that might be in the process of definition.
-It returns @code{nil}.
-
-In the following example, the user may type a number of characters right
-after starting the evaluation of the form. After the @code{sleep-for}
-finishes sleeping, @code{discard-input} discards any characters typed
-during the sleep.
-
-@example
-(progn (sleep-for 2)
- (discard-input))
- @result{} nil
-@end example
-@end defun
-
-@node Waiting
-@section Waiting for Elapsed Time or Input
-@cindex pausing
-@cindex waiting
-
- The wait functions are designed to wait for a certain amount of time
-to pass or until there is input. For example, you may wish to pause in
-the middle of a computation to allow the user time to view the display.
-@code{sit-for} pauses and updates the screen, and returns immediately if
-input comes in, while @code{sleep-for} pauses without updating the
-screen.
-
-@defun sit-for seconds &optional millisec nodisp
-This function performs redisplay (provided there is no pending input
-from the user), then waits @var{seconds} seconds, or until input is
-available. The value is @code{t} if @code{sit-for} waited the full
-time with no input arriving (see @code{input-pending-p} in @ref{Event
-Input Misc}). Otherwise, the value is @code{nil}.
-
-The argument @var{seconds} need not be an integer. If it is a floating
-point number, @code{sit-for} waits for a fractional number of seconds.
-Some systems support only a whole number of seconds; on these systems,
-@var{seconds} is rounded down.
-
-The optional argument @var{millisec} specifies an additional waiting
-period measured in milliseconds. This adds to the period specified by
-@var{seconds}. If the system doesn't support waiting fractions of a
-second, you get an error if you specify nonzero @var{millisec}.
-
-@cindex forcing redisplay
-Redisplay is always preempted if input arrives, and does not happen at
-all if input is available before it starts. Thus, there is no way to
-force screen updating if there is pending input; however, if there is no
-input pending, you can force an update with no delay by using
-@code{(sit-for 0)}.
-
-If @var{nodisp} is non-@code{nil}, then @code{sit-for} does not
-redisplay, but it still returns as soon as input is available (or when
-the timeout elapses).
-
-Iconifying or deiconifying a frame makes @code{sit-for} return, because
-that generates an event. @xref{Misc Events}.
-
-The usual purpose of @code{sit-for} is to give the user time to read
-text that you display.
-@end defun
-
-@defun sleep-for seconds &optional millisec
-This function simply pauses for @var{seconds} seconds without updating
-the display. It pays no attention to available input. It returns
-@code{nil}.
-
-The argument @var{seconds} need not be an integer. If it is a floating
-point number, @code{sleep-for} waits for a fractional number of seconds.
-Some systems support only a whole number of seconds; on these systems,
-@var{seconds} is rounded down.
-
-The optional argument @var{millisec} specifies an additional waiting
-period measured in milliseconds. This adds to the period specified by
-@var{seconds}. If the system doesn't support waiting fractions of a
-second, you get an error if you specify nonzero @var{millisec}.
-
-Use @code{sleep-for} when you wish to guarantee a delay.
-@end defun
-
- @xref{Time of Day}, for functions to get the current time.
-
-@node Quitting
-@section Quitting
-@cindex @kbd{C-g}
-@cindex quitting
-
- Typing @kbd{C-g} while a Lisp function is running causes Emacs to
-@dfn{quit} whatever it is doing. This means that control returns to the
-innermost active command loop.
-
- Typing @kbd{C-g} while the command loop is waiting for keyboard input
-does not cause a quit; it acts as an ordinary input character. In the
-simplest case, you cannot tell the difference, because @kbd{C-g}
-normally runs the command @code{keyboard-quit}, whose effect is to quit.
-However, when @kbd{C-g} follows a prefix key, the result is an undefined
-key. The effect is to cancel the prefix key as well as any prefix
-argument.
-
- In the minibuffer, @kbd{C-g} has a different definition: it aborts out
-of the minibuffer. This means, in effect, that it exits the minibuffer
-and then quits. (Simply quitting would return to the command loop
-@emph{within} the minibuffer.) The reason why @kbd{C-g} does not quit
-directly when the command reader is reading input is so that its meaning
-can be redefined in the minibuffer in this way. @kbd{C-g} following a
-prefix key is not redefined in the minibuffer, and it has its normal
-effect of canceling the prefix key and prefix argument. This too
-would not be possible if @kbd{C-g} always quit directly.
-
- When @kbd{C-g} does directly quit, it does so by setting the variable
-@code{quit-flag} to @code{t}. Emacs checks this variable at appropriate
-times and quits if it is not @code{nil}. Setting @code{quit-flag}
-non-@code{nil} in any way thus causes a quit.
-
- At the level of C code, quitting cannot happen just anywhere; only at the
-special places that check @code{quit-flag}. The reason for this is
-that quitting at other places might leave an inconsistency in Emacs's
-internal state. Because quitting is delayed until a safe place, quitting
-cannot make Emacs crash.
-
- Certain functions such as @code{read-key-sequence} or
-@code{read-quoted-char} prevent quitting entirely even though they wait
-for input. Instead of quitting, @kbd{C-g} serves as the requested
-input. In the case of @code{read-key-sequence}, this serves to bring
-about the special behavior of @kbd{C-g} in the command loop. In the
-case of @code{read-quoted-char}, this is so that @kbd{C-q} can be used
-to quote a @kbd{C-g}.
-
- You can prevent quitting for a portion of a Lisp function by binding
-the variable @code{inhibit-quit} to a non-@code{nil} value. Then,
-although @kbd{C-g} still sets @code{quit-flag} to @code{t} as usual, the
-usual result of this---a quit---is prevented. Eventually,
-@code{inhibit-quit} will become @code{nil} again, such as when its
-binding is unwound at the end of a @code{let} form. At that time, if
-@code{quit-flag} is still non-@code{nil}, the requested quit happens
-immediately. This behavior is ideal when you wish to make sure that
-quitting does not happen within a ``critical section'' of the program.
-
-@cindex @code{read-quoted-char} quitting
- In some functions (such as @code{read-quoted-char}), @kbd{C-g} is
-handled in a special way that does not involve quitting. This is done
-by reading the input with @code{inhibit-quit} bound to @code{t}, and
-setting @code{quit-flag} to @code{nil} before @code{inhibit-quit}
-becomes @code{nil} again. This excerpt from the definition of
-@code{read-quoted-char} shows how this is done; it also shows that
-normal quitting is permitted after the first character of input.
-
-@example
-(defun read-quoted-char (&optional prompt)
- "@dots{}@var{documentation}@dots{}"
- (let ((count 0) (code 0) char)
- (while (< count 3)
- (let ((inhibit-quit (zerop count))
- (help-form nil))
- (and prompt (message "%s-" prompt))
- (setq char (read-char))
- (if inhibit-quit (setq quit-flag nil)))
- @dots{})
- (logand 255 code)))
-@end example
-
-@defvar quit-flag
-If this variable is non-@code{nil}, then Emacs quits immediately, unless
-@code{inhibit-quit} is non-@code{nil}. Typing @kbd{C-g} ordinarily sets
-@code{quit-flag} non-@code{nil}, regardless of @code{inhibit-quit}.
-@end defvar
-
-@defvar inhibit-quit
-This variable determines whether Emacs should quit when @code{quit-flag}
-is set to a value other than @code{nil}. If @code{inhibit-quit} is
-non-@code{nil}, then @code{quit-flag} has no special effect.
-@end defvar
-
-@deffn Command keyboard-quit
-This function signals the @code{quit} condition with @code{(signal 'quit
-nil)}. This is the same thing that quitting does. (See @code{signal}
-in @ref{Errors}.)
-@end deffn
-
- You can specify a character other than @kbd{C-g} to use for quitting.
-See the function @code{set-input-mode} in @ref{Terminal Input}.
-
-@node Prefix Command Arguments
-@section Prefix Command Arguments
-@cindex prefix argument
-@cindex raw prefix argument
-@cindex numeric prefix argument
-
- Most Emacs commands can use a @dfn{prefix argument}, a number
-specified before the command itself. (Don't confuse prefix arguments
-with prefix keys.) The prefix argument is at all times represented by a
-value, which may be @code{nil}, meaning there is currently no prefix
-argument. Each command may use the prefix argument or ignore it.
-
- There are two representations of the prefix argument: @dfn{raw} and
-@dfn{numeric}. The editor command loop uses the raw representation
-internally, and so do the Lisp variables that store the information, but
-commands can request either representation.
-
- Here are the possible values of a raw prefix argument:
-
-@itemize @bullet
-@item
-@code{nil}, meaning there is no prefix argument. Its numeric value is
-1, but numerous commands make a distinction between @code{nil} and the
-integer 1.
-
-@item
-An integer, which stands for itself.
-
-@item
-A list of one element, which is an integer. This form of prefix
-argument results from one or a succession of @kbd{C-u}'s with no
-digits. The numeric value is the integer in the list, but some
-commands make a distinction between such a list and an integer alone.
-
-@item
-The symbol @code{-}. This indicates that @kbd{M--} or @kbd{C-u -} was
-typed, without following digits. The equivalent numeric value is
-@minus{}1, but some commands make a distinction between the integer
-@minus{}1 and the symbol @code{-}.
-@end itemize
-
-We illustrate these possibilities by calling the following function with
-various prefixes:
-
-@example
-@group
-(defun display-prefix (arg)
- "Display the value of the raw prefix arg."
- (interactive "P")
- (message "%s" arg))
-@end group
-@end example
-
-@noindent
-Here are the results of calling @code{display-prefix} with various
-raw prefix arguments:
-
-@example
- M-x display-prefix @print{} nil
-
-C-u M-x display-prefix @print{} (4)
-
-C-u C-u M-x display-prefix @print{} (16)
-
-C-u 3 M-x display-prefix @print{} 3
-
-M-3 M-x display-prefix @print{} 3 ; @r{(Same as @code{C-u 3}.)}
-
-C-u - M-x display-prefix @print{} -
-
-M-- M-x display-prefix @print{} - ; @r{(Same as @code{C-u -}.)}
-
-C-u - 7 M-x display-prefix @print{} -7
-
-M-- 7 M-x display-prefix @print{} -7 ; @r{(Same as @code{C-u -7}.)}
-@end example
-
- Emacs uses two variables to store the prefix argument:
-@code{prefix-arg} and @code{current-prefix-arg}. Commands such as
-@code{universal-argument} that set up prefix arguments for other
-commands store them in @code{prefix-arg}. In contrast,
-@code{current-prefix-arg} conveys the prefix argument to the current
-command, so setting it has no effect on the prefix arguments for future
-commands.
-
- Normally, commands specify which representation to use for the prefix
-argument, either numeric or raw, in the @code{interactive} declaration.
-(@xref{Using Interactive}.) Alternatively, functions may look at the
-value of the prefix argument directly in the variable
-@code{current-prefix-arg}, but this is less clean.
-
-@defun prefix-numeric-value arg
-This function returns the numeric meaning of a valid raw prefix argument
-value, @var{arg}. The argument may be a symbol, a number, or a list.
-If it is @code{nil}, the value 1 is returned; if it is @code{-}, the
-value @minus{}1 is returned; if it is a number, that number is returned;
-if it is a list, the @sc{car} of that list (which should be a number) is
-returned.
-@end defun
-
-@defvar current-prefix-arg
-This variable holds the raw prefix argument for the @emph{current}
-command. Commands may examine it directly, but the usual method for
-accessing it is with @code{(interactive "P")}.
-@end defvar
-
-@defvar prefix-arg
-The value of this variable is the raw prefix argument for the
-@emph{next} editing command. Commands that specify prefix arguments for
-the following command work by setting this variable.
-@end defvar
-
- Do not call @code{universal-argument}, @code{digit-argument}, or
-@code{negative-argument} unless you intend to let the user enter the
-prefix argument for the @emph{next} command.
-
-@deffn Command universal-argument
-This command reads input and specifies a prefix argument for the
-following command. Don't call this command yourself unless you know
-what you are doing.
-@end deffn
-
-@deffn Command digit-argument arg
-This command adds to the prefix argument for the following command. The
-argument @var{arg} is the raw prefix argument as it was before this
-command; it is used to compute the updated prefix argument. Don't call
-this command yourself unless you know what you are doing.
-@end deffn
-
-@deffn Command negative-argument arg
-This command adds to the numeric argument for the next command. The
-argument @var{arg} is the raw prefix argument as it was before this
-command; its value is negated to form the new prefix argument. Don't
-call this command yourself unless you know what you are doing.
-@end deffn
-
-@node Recursive Editing
-@section Recursive Editing
-@cindex recursive command loop
-@cindex recursive editing level
-@cindex command loop, recursive
-
- The Emacs command loop is entered automatically when Emacs starts up.
-This top-level invocation of the command loop never exits; it keeps
-running as long as Emacs does. Lisp programs can also invoke the
-command loop. Since this makes more than one activation of the command
-loop, we call it @dfn{recursive editing}. A recursive editing level has
-the effect of suspending whatever command invoked it and permitting the
-user to do arbitrary editing before resuming that command.
-
- The commands available during recursive editing are the same ones
-available in the top-level editing loop and defined in the keymaps.
-Only a few special commands exit the recursive editing level; the others
-return to the recursive editing level when they finish. (The special
-commands for exiting are always available, but they do nothing when
-recursive editing is not in progress.)
-
- All command loops, including recursive ones, set up all-purpose error
-handlers so that an error in a command run from the command loop will
-not exit the loop.
-
-@cindex minibuffer input
- Minibuffer input is a special kind of recursive editing. It has a few
-special wrinkles, such as enabling display of the minibuffer and the
-minibuffer window, but fewer than you might suppose. Certain keys
-behave differently in the minibuffer, but that is only because of the
-minibuffer's local map; if you switch windows, you get the usual Emacs
-commands.
-
-@cindex @code{throw} example
-@kindex exit
-@cindex exit recursive editing
-@cindex aborting
- To invoke a recursive editing level, call the function
-@code{recursive-edit}. This function contains the command loop; it also
-contains a call to @code{catch} with tag @code{exit}, which makes it
-possible to exit the recursive editing level by throwing to @code{exit}
-(@pxref{Catch and Throw}). If you throw a value other than @code{t},
-then @code{recursive-edit} returns normally to the function that called
-it. The command @kbd{C-M-c} (@code{exit-recursive-edit}) does this.
-Throwing a @code{t} value causes @code{recursive-edit} to quit, so that
-control returns to the command loop one level up. This is called
-@dfn{aborting}, and is done by @kbd{C-]} (@code{abort-recursive-edit}).
-
- Most applications should not use recursive editing, except as part of
-using the minibuffer. Usually it is more convenient for the user if you
-change the major mode of the current buffer temporarily to a special
-major mode, which should have a command to go back to the previous mode.
-(The @kbd{e} command in Rmail uses this technique.) Or, if you wish to
-give the user different text to edit ``recursively'', create and select
-a new buffer in a special mode. In this mode, define a command to
-complete the processing and go back to the previous buffer. (The
-@kbd{m} command in Rmail does this.)
-
- Recursive edits are useful in debugging. You can insert a call to
-@code{debug} into a function definition as a sort of breakpoint, so that
-you can look around when the function gets there. @code{debug} invokes
-a recursive edit but also provides the other features of the debugger.
-
- Recursive editing levels are also used when you type @kbd{C-r} in
-@code{query-replace} or use @kbd{C-x q} (@code{kbd-macro-query}).
-
-@defun recursive-edit
-@cindex suspend evaluation
-This function invokes the editor command loop. It is called
-automatically by the initialization of Emacs, to let the user begin
-editing. When called from a Lisp program, it enters a recursive editing
-level.
-
- In the following example, the function @code{simple-rec} first
-advances point one word, then enters a recursive edit, printing out a
-message in the echo area. The user can then do any editing desired, and
-then type @kbd{C-M-c} to exit and continue executing @code{simple-rec}.
-
-@example
-(defun simple-rec ()
- (forward-word 1)
- (message "Recursive edit in progress")
- (recursive-edit)
- (forward-word 1))
- @result{} simple-rec
-(simple-rec)
- @result{} nil
-@end example
-@end defun
-
-@deffn Command exit-recursive-edit
-This function exits from the innermost recursive edit (including
-minibuffer input). Its definition is effectively @code{(throw 'exit
-nil)}.
-@end deffn
-
-@deffn Command abort-recursive-edit
-This function aborts the command that requested the innermost recursive
-edit (including minibuffer input), by signaling @code{quit}
-after exiting the recursive edit. Its definition is effectively
-@code{(throw 'exit t)}. @xref{Quitting}.
-@end deffn
-
-@deffn Command top-level
-This function exits all recursive editing levels; it does not return a
-value, as it jumps completely out of any computation directly back to
-the main command loop.
-@end deffn
-
-@defun recursion-depth
-This function returns the current depth of recursive edits. When no
-recursive edit is active, it returns 0.
-@end defun
-
-@node Disabling Commands
-@section Disabling Commands
-@cindex disabled command
-
- @dfn{Disabling a command} marks the command as requiring user
-confirmation before it can be executed. Disabling is used for commands
-which might be confusing to beginning users, to prevent them from using
-the commands by accident.
-
-@kindex disabled
- The low-level mechanism for disabling a command is to put 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 this:
-
-@example
-(put 'upcase-region 'disabled t)
-@end example
-
-@noindent
-For a few commands, these properties are present by default and may be
-removed by the @file{.emacs} file.
-
- If the value of the @code{disabled} property is a string, the message
-saying the command is disabled includes that string. For example:
-
-@example
-(put 'delete-region 'disabled
- "Text deleted this way cannot be yanked back!\n")
-@end example
-
- @xref{Disabling,,, emacs, The GNU Emacs Manual}, for the details on
-what happens when a disabled command is invoked interactively.
-Disabling a command has no effect on calling it as a function from Lisp
-programs.
-
-@deffn Command enable-command command
-Allow @var{command} to be executed without special confirmation from now
-on, and (if the user confirms) alter the user's @file{.emacs} file so
-that this will apply to future sessions.
-@end deffn
-
-@deffn Command disable-command command
-Require special confirmation to execute @var{command} from now on, and
-(if the user confirms) alter the user's @file{.emacs} file so that this
-will apply to future sessions.
-@end deffn
-
-@defvar disabled-command-hook
-This normal hook is run instead of a disabled command, when the user
-invokes the disabled command interactively. The hook functions can use
-@code{this-command-keys} to determine what the user typed to run the
-command, and thus find the command itself. @xref{Hooks}.
-
-By default, @code{disabled-command-hook} contains a function that asks
-the user whether to proceed.
-@end defvar
-
-@node Command History
-@section Command History
-@cindex command history
-@cindex complex command
-@cindex history of commands
-
- The command loop keeps a history of the complex commands that have
-been executed, to make it convenient to repeat these commands. A
-@dfn{complex command} is one for which the interactive argument reading
-uses the minibuffer. This includes any @kbd{M-x} command, any
-@kbd{M-:} command, and any command whose @code{interactive}
-specification reads an argument from the minibuffer. Explicit use of
-the minibuffer during the execution of the command itself does not cause
-the command to be considered complex.
-
-@defvar command-history
-This variable's value is a list of recent complex commands, each
-represented as a form to evaluate. It continues to accumulate all
-complex commands for the duration of the editing session, but all but
-the first (most recent) thirty elements are deleted when a garbage
-collection takes place (@pxref{Garbage Collection}).
-
-@example
-@group
-command-history
-@result{} ((switch-to-buffer "chistory.texi")
- (describe-key "^X^[")
- (visit-tags-table "~/emacs/src/")
- (find-tag "repeat-complex-command"))
-@end group
-@end example
-@end defvar
-
- This history list is actually a special case of minibuffer history
-(@pxref{Minibuffer History}), with one special twist: the elements are
-expressions rather than strings.
-
- There are a number of commands devoted to the editing and recall of
-previous commands. The commands @code{repeat-complex-command}, and
-@code{list-command-history} are described in the user manual
-(@pxref{Repetition,,, emacs, The GNU Emacs Manual}). Within the
-minibuffer, the history commands used are the same ones available in any
-minibuffer.
-
-@node Keyboard Macros
-@section Keyboard Macros
-@cindex keyboard macros
-
- A @dfn{keyboard macro} is a canned sequence of input events that can
-be considered a command and made the definition of a key. The Lisp
-representation of a keyboard macro is a string or vector containing the
-events. Don't confuse keyboard macros with Lisp macros
-(@pxref{Macros}).
-
-@defun execute-kbd-macro macro &optional count
-This function executes @var{macro} as a sequence of events. If
-@var{macro} is a string or vector, then the events in it are executed
-exactly as if they had been input by the user. The sequence is
-@emph{not} expected to be a single key sequence; normally a keyboard
-macro definition consists of several key sequences concatenated.
-
-If @var{macro} is a symbol, then its function definition is used in
-place of @var{macro}. If that is another symbol, this process repeats.
-Eventually the result should be a string or vector. If the result is
-not a symbol, string, or vector, an error is signaled.
-
-The argument @var{count} is a repeat count; @var{macro} is executed that
-many times. If @var{count} is omitted or @code{nil}, @var{macro} is
-executed once. If it is 0, @var{macro} is executed over and over until it
-encounters an error or a failing search.
-@end defun
-
-@defvar executing-macro
-This variable contains the string or vector that defines the keyboard
-macro that is currently executing. It is @code{nil} if no macro is
-currently executing. A command can test this variable to behave
-differently when run from an executing macro. Do not set this variable
-yourself.
-@end defvar
-
-@defvar defining-kbd-macro
-This variable indicates whether a keyboard macro is being defined. A
-command can test this variable to behave differently while a macro is
-being defined. The commands @code{start-kbd-macro} and
-@code{end-kbd-macro} set this variable---do not set it yourself.
-
-The variable is always local to the current terminal and cannot be
-buffer-local. @xref{Multiple Displays}.
-@end defvar
-
-@defvar last-kbd-macro
-This variable is the definition of the most recently defined keyboard
-macro. Its value is a string or vector, or @code{nil}.
-
-The variable is always local to the current terminal and cannot be
-buffer-local. @xref{Multiple Displays}.
-@end defvar
-
diff --git a/lispref/compile.texi b/lispref/compile.texi
deleted file mode 100644
index d43ea51f074..00000000000
--- a/lispref/compile.texi
+++ /dev/null
@@ -1,731 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/compile
-@node Byte Compilation, Debugging, Loading, Top
-@chapter Byte Compilation
-@cindex byte-code
-@cindex compilation
-
- GNU Emacs Lisp has a @dfn{compiler} that translates functions written
-in Lisp into a special representation called @dfn{byte-code} that can be
-executed more efficiently. The compiler replaces Lisp function
-definitions with byte-code. When a byte-code function is called, its
-definition is evaluated by the @dfn{byte-code interpreter}.
-
- Because the byte-compiled code is evaluated by the byte-code
-interpreter, instead of being executed directly by the machine's
-hardware (as true compiled code is), byte-code is completely
-transportable from machine to machine without recompilation. It is not,
-however, as fast as true compiled code.
-
- In general, any version of Emacs can run byte-compiled code produced
-by recent earlier versions of Emacs, but the reverse is not true. In
-particular, if you compile a program with Emacs 19.29, the compiled
-code does not run in earlier versions.
-@iftex
-@xref{Docs and Compilation}.
-@end iftex
-Files compiled in versions before 19.29 may not work in 19.29 if they
-contain character constants with modifier bits, because the bits were
-renumbered in Emacs 19.29.
-
- @xref{Compilation Errors}, for how to investigate errors occurring in
-byte compilation.
-
-@menu
-* Speed of Byte-Code:: An example of speedup from byte compilation.
-* Compilation Functions:: Byte compilation functions.
-* Docs and Compilation:: Dynamic loading of documentation strings.
-* Dynamic Loading:: Dynamic loading of individual functions.
-* Eval During Compile:: Code to be evaluated when you compile.
-* Byte-Code Objects:: The data type used for byte-compiled functions.
-* Disassembly:: Disassembling byte-code; how to read byte-code.
-@end menu
-
-@node Speed of Byte-Code
-@section Performance of Byte-Compiled Code
-
- A byte-compiled function is not as efficient as a primitive function
-written in C, but runs much faster than the version written in Lisp.
-Here is an example:
-
-@example
-@group
-(defun silly-loop (n)
- "Return time before and after N iterations of a loop."
- (let ((t1 (current-time-string)))
- (while (> (setq n (1- n))
- 0))
- (list t1 (current-time-string))))
-@result{} silly-loop
-@end group
-
-@group
-(silly-loop 100000)
-@result{} ("Fri Mar 18 17:25:57 1994"
- "Fri Mar 18 17:26:28 1994") ; @r{31 seconds}
-@end group
-
-@group
-(byte-compile 'silly-loop)
-@result{} @r{[Compiled code not shown]}
-@end group
-
-@group
-(silly-loop 100000)
-@result{} ("Fri Mar 18 17:26:52 1994"
- "Fri Mar 18 17:26:58 1994") ; @r{6 seconds}
-@end group
-@end example
-
- In this example, the interpreted code required 31 seconds to run,
-whereas the byte-compiled code required 6 seconds. These results are
-representative, but actual results will vary greatly.
-
-@node Compilation Functions
-@comment node-name, next, previous, up
-@section The Compilation Functions
-@cindex compilation functions
-
- You can byte-compile an individual function or macro definition with
-the @code{byte-compile} function. You can compile a whole file with
-@code{byte-compile-file}, or several files with
-@code{byte-recompile-directory} or @code{batch-byte-compile}.
-
- The byte compiler produces error messages and warnings about each file
-in a buffer called @samp{*Compile-Log*}. These report things in your
-program that suggest a problem but are not necessarily erroneous.
-
-@cindex macro compilation
- Be careful when byte-compiling code that uses macros. Macro calls are
-expanded when they are compiled, so the macros must already be defined
-for proper compilation. For more details, see @ref{Compiling Macros}.
-
- Normally, compiling a file does not evaluate the file's contents or
-load the file. But it does execute any @code{require} calls at top
-level in the file. One way to ensure that necessary macro definitions
-are available during compilation is to require the file that defines
-them (@pxref{Named Features}). To avoid loading the macro definition files
-when someone @emph{runs} the compiled program, write
-@code{eval-when-compile} around the @code{require} calls (@pxref{Eval
-During Compile}).
-
-@defun byte-compile symbol
-This function byte-compiles the function definition of @var{symbol},
-replacing the previous definition with the compiled one. The function
-definition of @var{symbol} must be the actual code for the function;
-i.e., the compiler does not follow indirection to another symbol.
-@code{byte-compile} returns the new, compiled definition of
-@var{symbol}.
-
- If @var{symbol}'s definition is a byte-code function object,
-@code{byte-compile} does nothing and returns @code{nil}. Lisp records
-only one function definition for any symbol, and if that is already
-compiled, non-compiled code is not available anywhere. So there is no
-way to ``compile the same definition again.''
-
-@example
-@group
-(defun factorial (integer)
- "Compute factorial of INTEGER."
- (if (= 1 integer) 1
- (* integer (factorial (1- integer)))))
-@result{} factorial
-@end group
-
-@group
-(byte-compile 'factorial)
-@result{}
-#[(integer)
- "^H\301U\203^H^@@\301\207\302^H\303^HS!\"\207"
- [integer 1 * factorial]
- 4 "Compute factorial of INTEGER."]
-@end group
-@end example
-
-@noindent
-The result is a byte-code function object. The string it contains is
-the actual byte-code; each character in it is an instruction or an
-operand of an instruction. The vector contains all the constants,
-variable names and function names used by the function, except for
-certain primitives that are coded as special instructions.
-@end defun
-
-@deffn Command compile-defun
-This command reads the defun containing point, compiles it, and
-evaluates the result. If you use this on a defun that is actually a
-function definition, the effect is to install a compiled version of that
-function.
-@end deffn
-
-@deffn Command byte-compile-file filename
-This function compiles a file of Lisp code named @var{filename} into
-a file of byte-code. The output file's name is made by appending
-@samp{c} to the end of @var{filename}.
-
-Compilation works by reading the input file one form at a time. If it
-is a definition of a function or macro, the compiled function or macro
-definition is written out. Other forms are batched together, then each
-batch is compiled, and written so that its compiled code will be
-executed when the file is read. All comments are discarded when the
-input file is read.
-
-This command returns @code{t}. When called interactively, it prompts
-for the file name.
-
-@example
-@group
-% ls -l push*
--rw-r--r-- 1 lewis 791 Oct 5 20:31 push.el
-@end group
-
-@group
-(byte-compile-file "~/emacs/push.el")
- @result{} t
-@end group
-
-@group
-% ls -l push*
--rw-r--r-- 1 lewis 791 Oct 5 20:31 push.el
--rw-rw-rw- 1 lewis 638 Oct 8 20:25 push.elc
-@end group
-@end example
-@end deffn
-
-@deffn Command byte-recompile-directory directory flag
-@cindex library compilation
-This function recompiles every @samp{.el} file in @var{directory} that
-needs recompilation. A file needs recompilation if a @samp{.elc} file
-exists but is older than the @samp{.el} file.
-
-When a @samp{.el} file has no corresponding @samp{.elc} file, then
-@var{flag} says what to do. If it is @code{nil}, these files are
-ignored. If it is non-@code{nil}, the user is asked whether to compile
-each such file.
-
-The returned value of this command is unpredictable.
-@end deffn
-
-@defun batch-byte-compile
-This function runs @code{byte-compile-file} on files specified on the
-command line. This function must be used only in a batch execution of
-Emacs, as it kills Emacs on completion. An error in one file does not
-prevent processing of subsequent files. (The file that gets the error
-will not, of course, produce any compiled code.)
-
-@example
-% emacs -batch -f batch-byte-compile *.el
-@end example
-@end defun
-
-@defun byte-code code-string data-vector max-stack
-@cindex byte-code interpreter
-This function actually interprets byte-code. A byte-compiled function
-is actually defined with a body that calls @code{byte-code}. Don't call
-this function yourself. Only the byte compiler knows how to generate
-valid calls to this function.
-
-In newer Emacs versions (19 and up), byte-code is usually executed as
-part of a byte-code function object, and only rarely due to an explicit
-call to @code{byte-code}.
-@end defun
-
-@node Docs and Compilation
-@section Documentation Strings and Compilation
-@cindex dynamic loading of documentation
-
- Functions and variables loaded from a byte-compiled file access their
-documentation strings dynamically from the file whenever needed. This
-saves space within Emacs, and makes loading faster because the
-documentation strings themselves need not be processed while loading the
-file. Actual access to the documentation strings becomes slower as a
-result, but this normally is not enough to bother users.
-
- Dynamic access to documentation strings does have drawbacks:
-
-@itemize @bullet
-@item
-If you delete or move the compiled file after loading it, Emacs can no
-longer access the documentation strings for the functions and variables
-in the file.
-
-@item
-If you alter the compiled file (such as by compiling a new version),
-then further access to documentation strings in this file will give
-nonsense results.
-@end itemize
-
- If your site installs Emacs following the usual procedures, these
-problems will never normally occur. Installing a new version uses a new
-directory with a different name; as long as the old version remains
-installed, its files will remain unmodified in the places where they are
-expected to be.
-
- However, if you have built Emacs yourself and use it from the
-directory where you built it, you will experience this problem
-occasionally if you edit and recompile Lisp files. When it happens, you
-can cure the problem by reloading the file after recompiling it.
-
- Byte-compiled files made with Emacs 19.29 will not load into older
-versions because the older versions don't support this feature. You can
-turn off this feature by setting @code{byte-compile-dynamic-docstrings}
-to @code{nil}. Once this is done, you can compile files that will load
-into older Emacs versions. You can do this globally, or for one source
-file by specifying a file-local binding for the variable. Here's one
-way to do that:
-
-@example
--*-byte-compile-dynamic-docstrings: nil;-*-
-@end example
-
-@defvar byte-compile-dynamic-docstrings
-If this is non-@code{nil}, the byte compiler generates compiled files
-that are set up for dynamic loading of documentation strings.
-@end defvar
-
-@cindex @samp{#@@@var{count}}
-@cindex @samp{#$}
- The dynamic documentation string feature writes compiled files that
-use a special Lisp reader construct, @samp{#@@@var{count}}. This
-construct skips the next @var{count} characters. It also uses the
-@samp{#$} construct, which stands for ``the name of this file, as a
-string.'' It is best not to use these constructs in Lisp source files.
-
-@node Dynamic Loading
-@section Dynamic Loading of Individual Functions
-
-@cindex dynamic loading of functions
-@cindex lazy loading
- When you compile a file, you can optionally enable the @dfn{dynamic
-function loading} feature (also known as @dfn{lazy loading}). With
-dynamic function loading, loading the file doesn't fully read the
-function definitions in the file. Instead, each function definition
-contains a place-holder which refers to the file. The first time each
-function is called, it reads the full definition from the file, to
-replace the place-holder.
-
- The advantage of dynamic function loading is that loading the file
-becomes much faster. This is a good thing for a file which contains
-many separate commands, provided that using one of them does not imply
-you will soon (or ever) use the rest. A specialized mode which provides
-many keyboard commands often has that usage pattern: a user may invoke
-the mode, but use only a few of the commands it provides.
-
- The dynamic loading feature has certain disadvantages:
-
-@itemize @bullet
-@item
-If you delete or move the compiled file after loading it, Emacs can no
-longer load the remaining function definitions not already loaded.
-
-@item
-If you alter the compiled file (such as by compiling a new version),
-then trying to load any function not already loaded will get nonsense
-results.
-@end itemize
-
- If you compile a new version of the file, the best thing to do is
-immediately load the new compiled file. That will prevent any future
-problems.
-
- The byte compiler uses the dynamic function loading feature if the
-variable @code{byte-compile-dynamic} is non-@code{nil} at compilation
-time. Do not set this variable globally, since dynamic loading is
-desirable only for certain files. Instead, enable the feature for
-specific source files with file-local variable bindings, like this:
-
-@example
--*-byte-compile-dynamic: t;-*-
-@end example
-
-@defvar byte-compile-dynamic
-If this is non-@code{nil}, the byte compiler generates compiled files
-that are set up for dynamic function loading.
-@end defvar
-
-@defun fetch-bytecode function
-This immediately finishes loading the definition of @var{function} from
-its byte-compiled file, if it is not fully loaded already. The argument
-@var{function} may be a byte-code function object or a function name.
-@end defun
-
-@node Eval During Compile
-@section Evaluation During Compilation
-
- These features permit you to write code to be evaluated during
-compilation of a program.
-
-@defspec eval-and-compile body
-This form marks @var{body} to be evaluated both when you compile the
-containing code and when you run it (whether compiled or not).
-
-You can get a similar result by putting @var{body} in a separate file
-and referring to that file with @code{require}. Using @code{require} is
-preferable if there is a substantial amount of code to be executed in
-this way.
-@end defspec
-
-@defspec eval-when-compile body
-This form marks @var{body} to be evaluated at compile time and not when
-the compiled program is loaded. The result of evaluation by the
-compiler becomes a constant which appears in the compiled program. When
-the program is interpreted, not compiled at all, @var{body} is evaluated
-normally.
-
-At top level, this is analogous to the Common Lisp idiom
-@code{(eval-when (compile eval) @dots{})}. Elsewhere, the Common Lisp
-@samp{#.} reader macro (but not when interpreting) is closer to what
-@code{eval-when-compile} does.
-@end defspec
-
-@node Byte-Code Objects
-@section Byte-Code Function Objects
-@cindex compiled function
-@cindex byte-code function
-
- Byte-compiled functions have a special data type: they are
-@dfn{byte-code function objects}.
-
- Internally, a byte-code function object is much like a vector;
-however, the evaluator handles this data type specially when it appears
-as a function to be called. The printed representation for a byte-code
-function object is like that for a vector, with an additional @samp{#}
-before the opening @samp{[}.
-
- In Emacs version 18, there was no byte-code function object data type;
-compiled functions used the function @code{byte-code} to run the byte
-code.
-
- A byte-code function object must have at least four elements; there is
-no maximum number, but only the first six elements are actually used.
-They are:
-
-@table @var
-@item arglist
-The list of argument symbols.
-
-@item byte-code
-The string containing the byte-code instructions.
-
-@item constants
-The vector of Lisp objects referenced by the byte code. These include
-symbols used as function names and variable names.
-
-@item stacksize
-The maximum stack size this function needs.
-
-@item docstring
-The documentation string (if any); otherwise, @code{nil}. The value may
-be a number or a list, in case the documentation string is stored in a
-file. Use the function @code{documentation} to get the real
-documentation string (@pxref{Accessing Documentation}).
-
-@item interactive
-The interactive spec (if any). This can be a string or a Lisp
-expression. It is @code{nil} for a function that isn't interactive.
-@end table
-
-Here's an example of a byte-code function object, in printed
-representation. It is the definition of the command
-@code{backward-sexp}.
-
-@example
-#[(&optional arg)
- "^H\204^F^@@\301^P\302^H[!\207"
- [arg 1 forward-sexp]
- 2
- 254435
- "p"]
-@end example
-
- The primitive way to create a byte-code object is with
-@code{make-byte-code}:
-
-@defun make-byte-code &rest elements
-This function constructs and returns a byte-code function object
-with @var{elements} as its elements.
-@end defun
-
- You should not try to come up with the elements for a byte-code
-function yourself, because if they are inconsistent, Emacs may crash
-when you call the function. Always leave it to the byte compiler to
-create these objects; it makes the elements consistent (we hope).
-
- You can access the elements of a byte-code object using @code{aref};
-you can also use @code{vconcat} to create a vector with the same
-elements.
-
-@node Disassembly
-@section Disassembled Byte-Code
-@cindex disassembled byte-code
-
- People do not write byte-code; that job is left to the byte compiler.
-But we provide a disassembler to satisfy a cat-like curiosity. The
-disassembler converts the byte-compiled code into humanly readable
-form.
-
- The byte-code interpreter is implemented as a simple stack machine.
-It pushes values onto a stack of its own, then pops them off to use them
-in calculations whose results are themselves pushed back on the stack.
-When a byte-code function returns, it pops a value off the stack and
-returns it as the value of the function.
-
- In addition to the stack, byte-code functions can use, bind, and set
-ordinary Lisp variables, by transferring values between variables and
-the stack.
-
-@deffn Command disassemble object &optional stream
-This function prints the disassembled code for @var{object}. If
-@var{stream} is supplied, then output goes there. Otherwise, the
-disassembled code is printed to the stream @code{standard-output}. The
-argument @var{object} can be a function name or a lambda expression.
-
-As a special exception, if this function is used interactively,
-it outputs to a buffer named @samp{*Disassemble*}.
-@end deffn
-
- Here are two examples of using the @code{disassemble} function. We
-have added explanatory comments to help you relate the byte-code to the
-Lisp source; these do not appear in the output of @code{disassemble}.
-These examples show unoptimized byte-code. Nowadays byte-code is
-usually optimized, but we did not want to rewrite these examples, since
-they still serve their purpose.
-
-@example
-@group
-(defun factorial (integer)
- "Compute factorial of an integer."
- (if (= 1 integer) 1
- (* integer (factorial (1- integer)))))
- @result{} factorial
-@end group
-
-@group
-(factorial 4)
- @result{} 24
-@end group
-
-@group
-(disassemble 'factorial)
- @print{} byte-code for factorial:
- doc: Compute factorial of an integer.
- args: (integer)
-@end group
-
-@group
-0 constant 1 ; @r{Push 1 onto stack.}
-
-1 varref integer ; @r{Get value of @code{integer}}
- ; @r{from the environment}
- ; @r{and push the value}
- ; @r{onto the stack.}
-@end group
-
-@group
-2 eqlsign ; @r{Pop top two values off stack,}
- ; @r{compare them,}
- ; @r{and push result onto stack.}
-@end group
-
-@group
-3 goto-if-nil 10 ; @r{Pop and test top of stack;}
- ; @r{if @code{nil}, go to 10,}
- ; @r{else continue.}
-@end group
-
-@group
-6 constant 1 ; @r{Push 1 onto top of stack.}
-
-7 goto 17 ; @r{Go to 17 (in this case, 1 will be}
- ; @r{returned by the function).}
-@end group
-
-@group
-10 constant * ; @r{Push symbol @code{*} onto stack.}
-
-11 varref integer ; @r{Push value of @code{integer} onto stack.}
-@end group
-
-@group
-12 constant factorial ; @r{Push @code{factorial} onto stack.}
-
-13 varref integer ; @r{Push value of @code{integer} onto stack.}
-
-14 sub1 ; @r{Pop @code{integer}, decrement value,}
- ; @r{push new value onto stack.}
-@end group
-
-@group
- ; @r{Stack now contains:}
- ; @minus{} @r{decremented value of @code{integer}}
- ; @minus{} @r{@code{factorial}}
- ; @minus{} @r{value of @code{integer}}
- ; @minus{} @r{@code{*}}
-@end group
-
-@group
-15 call 1 ; @r{Call function @code{factorial} using}
- ; @r{the first (i.e., the top) element}
- ; @r{of the stack as the argument;}
- ; @r{push returned value onto stack.}
-@end group
-
-@group
- ; @r{Stack now contains:}
- ; @minus{} @r{result of recursive}
- ; @r{call to @code{factorial}}
- ; @minus{} @r{value of @code{integer}}
- ; @minus{} @r{@code{*}}
-@end group
-
-@group
-16 call 2 ; @r{Using the first two}
- ; @r{(i.e., the top two)}
- ; @r{elements of the stack}
- ; @r{as arguments,}
- ; @r{call the function @code{*},}
- ; @r{pushing the result onto the stack.}
-@end group
-
-@group
-17 return ; @r{Return the top element}
- ; @r{of the stack.}
- @result{} nil
-@end group
-@end example
-
-The @code{silly-loop} function is somewhat more complex:
-
-@example
-@group
-(defun silly-loop (n)
- "Return time before and after N iterations of a loop."
- (let ((t1 (current-time-string)))
- (while (> (setq n (1- n))
- 0))
- (list t1 (current-time-string))))
- @result{} silly-loop
-@end group
-
-@group
-(disassemble 'silly-loop)
- @print{} byte-code for silly-loop:
- doc: Return time before and after N iterations of a loop.
- args: (n)
-
-0 constant current-time-string ; @r{Push}
- ; @r{@code{current-time-string}}
- ; @r{onto top of stack.}
-@end group
-
-@group
-1 call 0 ; @r{Call @code{current-time-string}}
- ; @r{ with no argument,}
- ; @r{ pushing result onto stack.}
-@end group
-
-@group
-2 varbind t1 ; @r{Pop stack and bind @code{t1}}
- ; @r{to popped value.}
-@end group
-
-@group
-3 varref n ; @r{Get value of @code{n} from}
- ; @r{the environment and push}
- ; @r{the value onto the stack.}
-@end group
-
-@group
-4 sub1 ; @r{Subtract 1 from top of stack.}
-@end group
-
-@group
-5 dup ; @r{Duplicate the top of the stack;}
- ; @r{i.e., copy the top of}
- ; @r{the stack and push the}
- ; @r{copy onto the stack.}
-@end group
-
-@group
-6 varset n ; @r{Pop the top of the stack,}
- ; @r{and bind @code{n} to the value.}
-
- ; @r{In effect, the sequence @code{dup varset}}
- ; @r{copies the top of the stack}
- ; @r{into the value of @code{n}}
- ; @r{without popping it.}
-@end group
-
-@group
-7 constant 0 ; @r{Push 0 onto stack.}
-@end group
-
-@group
-8 gtr ; @r{Pop top two values off stack,}
- ; @r{test if @var{n} is greater than 0}
- ; @r{and push result onto stack.}
-@end group
-
-@group
-9 goto-if-nil-else-pop 17 ; @r{Goto 17 if @code{n} <= 0}
- ; @r{(this exits the while loop).}
- ; @r{else pop top of stack}
- ; @r{and continue}
-@end group
-
-@group
-12 constant nil ; @r{Push @code{nil} onto stack}
- ; @r{(this is the body of the loop).}
-@end group
-
-@group
-13 discard ; @r{Discard result of the body}
- ; @r{of the loop (a while loop}
- ; @r{is always evaluated for}
- ; @r{its side effects).}
-@end group
-
-@group
-14 goto 3 ; @r{Jump back to beginning}
- ; @r{of while loop.}
-@end group
-
-@group
-17 discard ; @r{Discard result of while loop}
- ; @r{by popping top of stack.}
- ; @r{This result is the value @code{nil} that}
- ; @r{was not popped by the goto at 9.}
-@end group
-
-@group
-18 varref t1 ; @r{Push value of @code{t1} onto stack.}
-@end group
-
-@group
-19 constant current-time-string ; @r{Push}
- ; @r{@code{current-time-string}}
- ; @r{onto top of stack.}
-@end group
-
-@group
-20 call 0 ; @r{Call @code{current-time-string} again.}
-@end group
-
-@group
-21 list2 ; @r{Pop top two elements off stack,}
- ; @r{create a list of them,}
- ; @r{and push list onto stack.}
-@end group
-
-@group
-22 unbind 1 ; @r{Unbind @code{t1} in local environment.}
-
-23 return ; @r{Return value of the top of stack.}
-
- @result{} nil
-@end group
-@end example
-
-
diff --git a/lispref/control.texi b/lispref/control.texi
deleted file mode 100644
index 4973599d877..00000000000
--- a/lispref/control.texi
+++ /dev/null
@@ -1,1157 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/control
-@node Control Structures, Variables, Evaluation, Top
-@chapter Control Structures
-@cindex special forms for control structures
-@cindex control structures
-
- A Lisp program consists of expressions or @dfn{forms} (@pxref{Forms}).
-We control the order of execution of the forms by enclosing them in
-@dfn{control structures}. Control structures are special forms which
-control when, whether, or how many times to execute the forms they
-contain.
-
- The simplest order of execution is sequential execution: first form
-@var{a}, then form @var{b}, and so on. This is what happens when you
-write several forms in succession in the body of a function, or at top
-level in a file of Lisp code---the forms are executed in the order
-written. We call this @dfn{textual order}. For example, if a function
-body consists of two forms @var{a} and @var{b}, evaluation of the
-function evaluates first @var{a} and then @var{b}, and the function's
-value is the value of @var{b}.
-
- Explicit control structures make possible an order of execution other
-than sequential.
-
- Emacs Lisp provides several kinds of control structure, including
-other varieties of sequencing, conditionals, iteration, and (controlled)
-jumps---all discussed below. The built-in control structures are
-special forms since their subforms are not necessarily evaluated or not
-evaluated sequentially. You can use macros to define your own control
-structure constructs (@pxref{Macros}).
-
-@menu
-* Sequencing:: Evaluation in textual order.
-* Conditionals:: @code{if}, @code{cond}.
-* Combining Conditions:: @code{and}, @code{or}, @code{not}.
-* Iteration:: @code{while} loops.
-* Nonlocal Exits:: Jumping out of a sequence.
-@end menu
-
-@node Sequencing
-@section Sequencing
-
- Evaluating forms in the order they appear is the most common way
-control passes from one form to another. In some contexts, such as in a
-function body, this happens automatically. Elsewhere you must use a
-control structure construct to do this: @code{progn}, the simplest
-control construct of Lisp.
-
- A @code{progn} special form looks like this:
-
-@example
-@group
-(progn @var{a} @var{b} @var{c} @dots{})
-@end group
-@end example
-
-@noindent
-and it says to execute the forms @var{a}, @var{b}, @var{c} and so on, in
-that order. These forms are called the body of the @code{progn} form.
-The value of the last form in the body becomes the value of the entire
-@code{progn}.
-
-@cindex implicit @code{progn}
- In the early days of Lisp, @code{progn} was the only way to execute
-two or more forms in succession and use the value of the last of them.
-But programmers found they often needed to use a @code{progn} in the
-body of a function, where (at that time) only one form was allowed. So
-the body of a function was made into an ``implicit @code{progn}'':
-several forms are allowed just as in the body of an actual @code{progn}.
-Many other control structures likewise contain an implicit @code{progn}.
-As a result, @code{progn} is not used as often as it used to be. It is
-needed now most often inside an @code{unwind-protect}, @code{and},
-@code{or}, or in the @var{then}-part of an @code{if}.
-
-@defspec progn forms@dots{}
-This special form evaluates all of the @var{forms}, in textual
-order, returning the result of the final form.
-
-@example
-@group
-(progn (print "The first form")
- (print "The second form")
- (print "The third form"))
- @print{} "The first form"
- @print{} "The second form"
- @print{} "The third form"
-@result{} "The third form"
-@end group
-@end example
-@end defspec
-
- Two other control constructs likewise evaluate a series of forms but return
-a different value:
-
-@defspec prog1 form1 forms@dots{}
-This special form evaluates @var{form1} and all of the @var{forms}, in
-textual order, returning the result of @var{form1}.
-
-@example
-@group
-(prog1 (print "The first form")
- (print "The second form")
- (print "The third form"))
- @print{} "The first form"
- @print{} "The second form"
- @print{} "The third form"
-@result{} "The first form"
-@end group
-@end example
-
-Here is a way to remove the first element from a list in the variable
-@code{x}, then return the value of that former element:
-
-@example
-(prog1 (car x) (setq x (cdr x)))
-@end example
-@end defspec
-
-@defspec prog2 form1 form2 forms@dots{}
-This special form evaluates @var{form1}, @var{form2}, and all of the
-following @var{forms}, in textual order, returning the result of
-@var{form2}.
-
-@example
-@group
-(prog2 (print "The first form")
- (print "The second form")
- (print "The third form"))
- @print{} "The first form"
- @print{} "The second form"
- @print{} "The third form"
-@result{} "The second form"
-@end group
-@end example
-@end defspec
-
-@node Conditionals
-@section Conditionals
-@cindex conditional evaluation
-
- Conditional control structures choose among alternatives. Emacs Lisp
-has two conditional forms: @code{if}, which is much the same as in other
-languages, and @code{cond}, which is a generalized case statement.
-
-@defspec if condition then-form else-forms@dots{}
-@code{if} chooses between the @var{then-form} and the @var{else-forms}
-based on the value of @var{condition}. If the evaluated @var{condition} is
-non-@code{nil}, @var{then-form} is evaluated and the result returned.
-Otherwise, the @var{else-forms} are evaluated in textual order, and the
-value of the last one is returned. (The @var{else} part of @code{if} is
-an example of an implicit @code{progn}. @xref{Sequencing}.)
-
-If @var{condition} has the value @code{nil}, and no @var{else-forms} are
-given, @code{if} returns @code{nil}.
-
-@code{if} is a special form because the branch that is not selected is
-never evaluated---it is ignored. Thus, in the example below,
-@code{true} is not printed because @code{print} is never called.
-
-@example
-@group
-(if nil
- (print 'true)
- 'very-false)
-@result{} very-false
-@end group
-@end example
-@end defspec
-
-@defspec cond clause@dots{}
-@code{cond} chooses among an arbitrary number of alternatives. Each
-@var{clause} in the @code{cond} must be a list. The @sc{car} of this
-list is the @var{condition}; the remaining elements, if any, the
-@var{body-forms}. Thus, a clause looks like this:
-
-@example
-(@var{condition} @var{body-forms}@dots{})
-@end example
-
-@code{cond} tries the clauses in textual order, by evaluating the
-@var{condition} of each clause. If the value of @var{condition} is
-non-@code{nil}, the clause ``succeeds''; then @code{cond} evaluates its
-@var{body-forms}, and the value of the last of @var{body-forms} becomes
-the value of the @code{cond}. The remaining clauses are ignored.
-
-If the value of @var{condition} is @code{nil}, the clause ``fails'', so
-the @code{cond} moves on to the following clause, trying its
-@var{condition}.
-
-If every @var{condition} evaluates to @code{nil}, so that every clause
-fails, @code{cond} returns @code{nil}.
-
-A clause may also look like this:
-
-@example
-(@var{condition})
-@end example
-
-@noindent
-Then, if @var{condition} is non-@code{nil} when tested, the value of
-@var{condition} becomes the value of the @code{cond} form.
-
-The following example has four clauses, which test for the cases where
-the value of @code{x} is a number, string, buffer and symbol,
-respectively:
-
-@example
-@group
-(cond ((numberp x) x)
- ((stringp x) x)
- ((bufferp x)
- (setq temporary-hack x) ; @r{multiple body-forms}
- (buffer-name x)) ; @r{in one clause}
- ((symbolp x) (symbol-value x)))
-@end group
-@end example
-
-Often we want to execute the last clause whenever none of the previous
-clauses was successful. To do this, we use @code{t} as the
-@var{condition} of the last clause, like this: @code{(t
-@var{body-forms})}. The form @code{t} evaluates to @code{t}, which is
-never @code{nil}, so this clause never fails, provided the @code{cond}
-gets to it at all.
-
-For example,
-
-@example
-@group
-(cond ((eq a 'hack) 'foo)
- (t "default"))
-@result{} "default"
-@end group
-@end example
-
-@noindent
-This expression is a @code{cond} which returns @code{foo} if the value
-of @code{a} is 1, and returns the string @code{"default"} otherwise.
-@end defspec
-
-Any conditional construct can be expressed with @code{cond} or with
-@code{if}. Therefore, the choice between them is a matter of style.
-For example:
-
-@example
-@group
-(if @var{a} @var{b} @var{c})
-@equiv{}
-(cond (@var{a} @var{b}) (t @var{c}))
-@end group
-@end example
-
-@node Combining Conditions
-@section Constructs for Combining Conditions
-
- This section describes three constructs that are often used together
-with @code{if} and @code{cond} to express complicated conditions. The
-constructs @code{and} and @code{or} can also be used individually as
-kinds of multiple conditional constructs.
-
-@defun not condition
-This function tests for the falsehood of @var{condition}. It returns
-@code{t} if @var{condition} is @code{nil}, and @code{nil} otherwise.
-The function @code{not} is identical to @code{null}, and we recommend
-using the name @code{null} if you are testing for an empty list.
-@end defun
-
-@defspec and conditions@dots{}
-The @code{and} special form tests whether all the @var{conditions} are
-true. It works by evaluating the @var{conditions} one by one in the
-order written.
-
-If any of the @var{conditions} evaluates to @code{nil}, then the result
-of the @code{and} must be @code{nil} regardless of the remaining
-@var{conditions}; so @code{and} returns right away, ignoring the
-remaining @var{conditions}.
-
-If all the @var{conditions} turn out non-@code{nil}, then the value of
-the last of them becomes the value of the @code{and} form.
-
-Here is an example. The first condition returns the integer 1, which is
-not @code{nil}. Similarly, the second condition returns the integer 2,
-which is not @code{nil}. The third condition is @code{nil}, so the
-remaining condition is never evaluated.
-
-@example
-@group
-(and (print 1) (print 2) nil (print 3))
- @print{} 1
- @print{} 2
-@result{} nil
-@end group
-@end example
-
-Here is a more realistic example of using @code{and}:
-
-@example
-@group
-(if (and (consp foo) (eq (car foo) 'x))
- (message "foo is a list starting with x"))
-@end group
-@end example
-
-@noindent
-Note that @code{(car foo)} is not executed if @code{(consp foo)} returns
-@code{nil}, thus avoiding an error.
-
-@code{and} can be expressed in terms of either @code{if} or @code{cond}.
-For example:
-
-@example
-@group
-(and @var{arg1} @var{arg2} @var{arg3})
-@equiv{}
-(if @var{arg1} (if @var{arg2} @var{arg3}))
-@equiv{}
-(cond (@var{arg1} (cond (@var{arg2} @var{arg3}))))
-@end group
-@end example
-@end defspec
-
-@defspec or conditions@dots{}
-The @code{or} special form tests whether at least one of the
-@var{conditions} is true. It works by evaluating all the
-@var{conditions} one by one in the order written.
-
-If any of the @var{conditions} evaluates to a non-@code{nil} value, then
-the result of the @code{or} must be non-@code{nil}; so @code{or} returns
-right away, ignoring the remaining @var{conditions}. The value it
-returns is the non-@code{nil} value of the condition just evaluated.
-
-If all the @var{conditions} turn out @code{nil}, then the @code{or}
-expression returns @code{nil}.
-
-For example, this expression tests whether @code{x} is either 0 or
-@code{nil}:
-
-@example
-(or (eq x nil) (eq x 0))
-@end example
-
-Like the @code{and} construct, @code{or} can be written in terms of
-@code{cond}. For example:
-
-@example
-@group
-(or @var{arg1} @var{arg2} @var{arg3})
-@equiv{}
-(cond (@var{arg1})
- (@var{arg2})
- (@var{arg3}))
-@end group
-@end example
-
-You could almost write @code{or} in terms of @code{if}, but not quite:
-
-@example
-@group
-(if @var{arg1} @var{arg1}
- (if @var{arg2} @var{arg2}
- @var{arg3}))
-@end group
-@end example
-
-@noindent
-This is not completely equivalent because it can evaluate @var{arg1} or
-@var{arg2} twice. By contrast, @code{(or @var{arg1} @var{arg2}
-@var{arg3})} never evaluates any argument more than once.
-@end defspec
-
-@node Iteration
-@section Iteration
-@cindex iteration
-@cindex recursion
-
- Iteration means executing part of a program repetitively. For
-example, you might want to repeat some computation once for each element
-of a list, or once for each integer from 0 to @var{n}. You can do this
-in Emacs Lisp with the special form @code{while}:
-
-@defspec while condition forms@dots{}
-@code{while} first evaluates @var{condition}. If the result is
-non-@code{nil}, it evaluates @var{forms} in textual order. Then it
-reevaluates @var{condition}, and if the result is non-@code{nil}, it
-evaluates @var{forms} again. This process repeats until @var{condition}
-evaluates to @code{nil}.
-
-There is no limit on the number of iterations that may occur. The loop
-will continue until either @var{condition} evaluates to @code{nil} or
-until an error or @code{throw} jumps out of it (@pxref{Nonlocal Exits}).
-
-The value of a @code{while} form is always @code{nil}.
-
-@example
-@group
-(setq num 0)
- @result{} 0
-@end group
-@group
-(while (< num 4)
- (princ (format "Iteration %d." num))
- (setq num (1+ num)))
- @print{} Iteration 0.
- @print{} Iteration 1.
- @print{} Iteration 2.
- @print{} Iteration 3.
- @result{} nil
-@end group
-@end example
-
-If you would like to execute something on each iteration before the
-end-test, put it together with the end-test in a @code{progn} as the
-first argument of @code{while}, as shown here:
-
-@example
-@group
-(while (progn
- (forward-line 1)
- (not (looking-at "^$"))))
-@end group
-@end example
-
-@noindent
-This moves forward one line and continues moving by lines until it
-reaches an empty. It is unusual in that the @code{while} has no body,
-just the end test (which also does the real work of moving point).
-@end defspec
-
-@node Nonlocal Exits
-@section Nonlocal Exits
-@cindex nonlocal exits
-
- A @dfn{nonlocal exit} is a transfer of control from one point in a
-program to another remote point. Nonlocal exits can occur in Emacs Lisp
-as a result of errors; you can also use them under explicit control.
-Nonlocal exits unbind all variable bindings made by the constructs being
-exited.
-
-@menu
-* Catch and Throw:: Nonlocal exits for the program's own purposes.
-* Examples of Catch:: Showing how such nonlocal exits can be written.
-* Errors:: How errors are signaled and handled.
-* Cleanups:: Arranging to run a cleanup form if an error happens.
-@end menu
-
-@node Catch and Throw
-@subsection Explicit Nonlocal Exits: @code{catch} and @code{throw}
-
- Most control constructs affect only the flow of control within the
-construct itself. The function @code{throw} is the exception to this
-rule of normal program execution: it performs a nonlocal exit on
-request. (There are other exceptions, but they are for error handling
-only.) @code{throw} is used inside a @code{catch}, and jumps back to
-that @code{catch}. For example:
-
-@example
-@group
-(catch 'foo
- (progn
- @dots{}
- (throw 'foo t)
- @dots{}))
-@end group
-@end example
-
-@noindent
-The @code{throw} transfers control straight back to the corresponding
-@code{catch}, which returns immediately. The code following the
-@code{throw} is not executed. The second argument of @code{throw} is used
-as the return value of the @code{catch}.
-
- The @code{throw} and the @code{catch} are matched through the first
-argument: @code{throw} searches for a @code{catch} whose first argument
-is @code{eq} to the one specified. Thus, in the above example, the
-@code{throw} specifies @code{foo}, and the @code{catch} specifies the
-same symbol, so that @code{catch} is applicable. If there is more than
-one applicable @code{catch}, the innermost one takes precedence.
-
- Executing @code{throw} exits all Lisp constructs up to the matching
-@code{catch}, including function calls. When binding constructs such as
-@code{let} or function calls are exited in this way, the bindings are
-unbound, just as they are when these constructs exit normally
-(@pxref{Local Variables}). Likewise, @code{throw} restores the buffer
-and position saved by @code{save-excursion} (@pxref{Excursions}), and
-the narrowing status saved by @code{save-restriction} and the window
-selection saved by @code{save-window-excursion} (@pxref{Window
-Configurations}). It also runs any cleanups established with the
-@code{unwind-protect} special form when it exits that form
-(@pxref{Cleanups}).
-
- The @code{throw} need not appear lexically within the @code{catch}
-that it jumps to. It can equally well be called from another function
-called within the @code{catch}. As long as the @code{throw} takes place
-chronologically after entry to the @code{catch}, and chronologically
-before exit from it, it has access to that @code{catch}. This is why
-@code{throw} can be used in commands such as @code{exit-recursive-edit}
-that throw back to the editor command loop (@pxref{Recursive Editing}).
-
-@cindex CL note---only @code{throw} in Emacs
-@quotation
-@b{Common Lisp note:} Most other versions of Lisp, including Common Lisp,
-have several ways of transferring control nonsequentially: @code{return},
-@code{return-from}, and @code{go}, for example. Emacs Lisp has only
-@code{throw}.
-@end quotation
-
-@defspec catch tag body@dots{}
-@cindex tag on run time stack
-@code{catch} establishes a return point for the @code{throw} function. The
-return point is distinguished from other such return points by @var{tag},
-which may be any Lisp object. The argument @var{tag} is evaluated normally
-before the return point is established.
-
-With the return point in effect, @code{catch} evaluates the forms of the
-@var{body} in textual order. If the forms execute normally, without
-error or nonlocal exit, the value of the last body form is returned from
-the @code{catch}.
-
-If a @code{throw} is done within @var{body} specifying the same value
-@var{tag}, the @code{catch} exits immediately; the value it returns is
-whatever was specified as the second argument of @code{throw}.
-@end defspec
-
-@defun throw tag value
-The purpose of @code{throw} is to return from a return point previously
-established with @code{catch}. The argument @var{tag} is used to choose
-among the various existing return points; it must be @code{eq} to the value
-specified in the @code{catch}. If multiple return points match @var{tag},
-the innermost one is used.
-
-The argument @var{value} is used as the value to return from that
-@code{catch}.
-
-@kindex no-catch
-If no return point is in effect with tag @var{tag}, then a @code{no-catch}
-error is signaled with data @code{(@var{tag} @var{value})}.
-@end defun
-
-@node Examples of Catch
-@subsection Examples of @code{catch} and @code{throw}
-
- One way to use @code{catch} and @code{throw} is to exit from a doubly
-nested loop. (In most languages, this would be done with a ``go to''.)
-Here we compute @code{(foo @var{i} @var{j})} for @var{i} and @var{j}
-varying from 0 to 9:
-
-@example
-@group
-(defun search-foo ()
- (catch 'loop
- (let ((i 0))
- (while (< i 10)
- (let ((j 0))
- (while (< j 10)
- (if (foo i j)
- (throw 'loop (list i j)))
- (setq j (1+ j))))
- (setq i (1+ i))))))
-@end group
-@end example
-
-@noindent
-If @code{foo} ever returns non-@code{nil}, we stop immediately and return a
-list of @var{i} and @var{j}. If @code{foo} always returns @code{nil}, the
-@code{catch} returns normally, and the value is @code{nil}, since that
-is the result of the @code{while}.
-
- Here are two tricky examples, slightly different, showing two
-return points at once. First, two return points with the same tag,
-@code{hack}:
-
-@example
-@group
-(defun catch2 (tag)
- (catch tag
- (throw 'hack 'yes)))
-@result{} catch2
-@end group
-
-@group
-(catch 'hack
- (print (catch2 'hack))
- 'no)
-@print{} yes
-@result{} no
-@end group
-@end example
-
-@noindent
-Since both return points have tags that match the @code{throw}, it goes to
-the inner one, the one established in @code{catch2}. Therefore,
-@code{catch2} returns normally with value @code{yes}, and this value is
-printed. Finally the second body form in the outer @code{catch}, which is
-@code{'no}, is evaluated and returned from the outer @code{catch}.
-
- Now let's change the argument given to @code{catch2}:
-
-@example
-@group
-(defun catch2 (tag)
- (catch tag
- (throw 'hack 'yes)))
-@result{} catch2
-@end group
-
-@group
-(catch 'hack
- (print (catch2 'quux))
- 'no)
-@result{} yes
-@end group
-@end example
-
-@noindent
-We still have two return points, but this time only the outer one has
-the tag @code{hack}; the inner one has the tag @code{quux} instead.
-Therefore, @code{throw} makes the outer @code{catch} return the value
-@code{yes}. The function @code{print} is never called, and the
-body-form @code{'no} is never evaluated.
-
-@node Errors
-@subsection Errors
-@cindex errors
-
- When Emacs Lisp attempts to evaluate a form that, for some reason,
-cannot be evaluated, it @dfn{signals} an @dfn{error}.
-
- When an error is signaled, Emacs's default reaction is to print an
-error message and terminate execution of the current command. This is
-the right thing to do in most cases, such as if you type @kbd{C-f} at
-the end of the buffer.
-
- In complicated programs, simple termination may not be what you want.
-For example, the program may have made temporary changes in data
-structures, or created temporary buffers that should be deleted before
-the program is finished. In such cases, you would use
-@code{unwind-protect} to establish @dfn{cleanup expressions} to be
-evaluated in case of error. (@xref{Cleanups}.) Occasionally, you may
-wish the program to continue execution despite an error in a subroutine.
-In these cases, you would use @code{condition-case} to establish
-@dfn{error handlers} to recover control in case of error.
-
- Resist the temptation to use error handling to transfer control from
-one part of the program to another; use @code{catch} and @code{throw}
-instead. @xref{Catch and Throw}.
-
-@menu
-* Signaling Errors:: How to report an error.
-* Processing of Errors:: What Emacs does when you report an error.
-* Handling Errors:: How you can trap errors and continue execution.
-* Error Symbols:: How errors are classified for trapping them.
-@end menu
-
-@node Signaling Errors
-@subsubsection How to Signal an Error
-@cindex signaling errors
-
- Most errors are signaled ``automatically'' within Lisp primitives
-which you call for other purposes, such as if you try to take the
-@sc{car} of an integer or move forward a character at the end of the
-buffer; you can also signal errors explicitly with the functions
-@code{error} and @code{signal}.
-
- Quitting, which happens when the user types @kbd{C-g}, is not
-considered an error, but it is handled almost like an error.
-@xref{Quitting}.
-
-@defun error format-string &rest args
-This function signals an error with an error message constructed by
-applying @code{format} (@pxref{String Conversion}) to
-@var{format-string} and @var{args}.
-
-These examples show typical uses of @code{error}:
-
-@example
-@group
-(error "You have committed an error.
- Try something else.")
- @error{} You have committed an error.
- Try something else.
-@end group
-
-@group
-(error "You have committed %d errors." 10)
- @error{} You have committed 10 errors.
-@end group
-@end example
-
-@code{error} works by calling @code{signal} with two arguments: the
-error symbol @code{error}, and a list containing the string returned by
-@code{format}.
-
-If you want to use your own string as an error message verbatim, don't
-just write @code{(error @var{string})}. If @var{string} contains
-@samp{%}, it will be interpreted as a format specifier, with undesirable
-results. Instead, use @code{(error "%s" @var{string})}.
-@end defun
-
-@defun signal error-symbol data
-This function signals an error named by @var{error-symbol}. The
-argument @var{data} is a list of additional Lisp objects relevant to the
-circumstances of the error.
-
-The argument @var{error-symbol} must be an @dfn{error symbol}---a symbol
-bearing a property @code{error-conditions} whose value is a list of
-condition names. This is how Emacs Lisp classifies different sorts of
-errors.
-
-The number and significance of the objects in @var{data} depends on
-@var{error-symbol}. For example, with a @code{wrong-type-arg} error,
-there are two objects in the list: a predicate that describes the type
-that was expected, and the object that failed to fit that type.
-@xref{Error Symbols}, for a description of error symbols.
-
-Both @var{error-symbol} and @var{data} are available to any error
-handlers that handle the error: @code{condition-case} binds a local
-variable to a list of the form @code{(@var{error-symbol} .@:
-@var{data})} (@pxref{Handling Errors}). If the error is not handled,
-these two values are used in printing the error message.
-
-The function @code{signal} never returns (though in older Emacs versions
-it could sometimes return).
-
-@smallexample
-@group
-(signal 'wrong-number-of-arguments '(x y))
- @error{} Wrong number of arguments: x, y
-@end group
-
-@group
-(signal 'no-such-error '("My unknown error condition."))
- @error{} peculiar error: "My unknown error condition."
-@end group
-@end smallexample
-@end defun
-
-@cindex CL note---no continuable errors
-@quotation
-@b{Common Lisp note:} Emacs Lisp has nothing like the Common Lisp
-concept of continuable errors.
-@end quotation
-
-@node Processing of Errors
-@subsubsection How Emacs Processes Errors
-
-When an error is signaled, @code{signal} searches for an active
-@dfn{handler} for the error. A handler is a sequence of Lisp
-expressions designated to be executed if an error happens in part of the
-Lisp program. If the error has an applicable handler, the handler is
-executed, and control resumes following the handler. The handler
-executes in the environment of the @code{condition-case} that
-established it; all functions called within that @code{condition-case}
-have already been exited, and the handler cannot return to them.
-
-If there is no applicable handler for the error, the current command is
-terminated and control returns to the editor command loop, because the
-command loop has an implicit handler for all kinds of errors. The
-command loop's handler uses the error symbol and associated data to
-print an error message.
-
-@cindex @code{debug-on-error} use
-An error that has no explicit handler may call the Lisp debugger. The
-debugger is enabled if the variable @code{debug-on-error} (@pxref{Error
-Debugging}) is non-@code{nil}. Unlike error handlers, the debugger runs
-in the environment of the error, so that you can examine values of
-variables precisely as they were at the time of the error.
-
-@node Handling Errors
-@subsubsection Writing Code to Handle Errors
-@cindex error handler
-@cindex handling errors
-
- The usual effect of signaling an error is to terminate the command
-that is running and return immediately to the Emacs editor command loop.
-You can arrange to trap errors occurring in a part of your program by
-establishing an error handler, with the special form
-@code{condition-case}. A simple example looks like this:
-
-@example
-@group
-(condition-case nil
- (delete-file filename)
- (error nil))
-@end group
-@end example
-
-@noindent
-This deletes the file named @var{filename}, catching any error and
-returning @code{nil} if an error occurs.
-
- The second argument of @code{condition-case} is called the
-@dfn{protected form}. (In the example above, the protected form is a
-call to @code{delete-file}.) The error handlers go into effect when
-this form begins execution and are deactivated when this form returns.
-They remain in effect for all the intervening time. In particular, they
-are in effect during the execution of functions called by this form, in
-their subroutines, and so on. This is a good thing, since, strictly
-speaking, errors can be signaled only by Lisp primitives (including
-@code{signal} and @code{error}) called by the protected form, not by the
-protected form itself.
-
- The arguments after the protected form are handlers. Each handler
-lists one or more @dfn{condition names} (which are symbols) to specify
-which errors it will handle. The error symbol specified when an error
-is signaled also defines a list of condition names. A handler applies
-to an error if they have any condition names in common. In the example
-above, there is one handler, and it specifies one condition name,
-@code{error}, which covers all errors.
-
- The search for an applicable handler checks all the established handlers
-starting with the most recently established one. Thus, if two nested
-@code{condition-case} forms offer to handle the same error, the inner of
-the two will actually handle it.
-
- When an error is handled, control returns to the handler. Before this
-happens, Emacs unbinds all variable bindings made by binding constructs
-that are being exited and executes the cleanups of all
-@code{unwind-protect} forms that are exited. Once control arrives at
-the handler, the body of the handler is executed.
-
- After execution of the handler body, execution returns from the
-@code{condition-case} form. Because the protected form is exited
-completely before execution of the handler, the handler cannot resume
-execution at the point of the error, nor can it examine variable
-bindings that were made within the protected form. All it can do is
-clean up and proceed.
-
- @code{condition-case} is often used to trap errors that are
-predictable, such as failure to open a file in a call to
-@code{insert-file-contents}. It is also used to trap errors that are
-totally unpredictable, such as when the program evaluates an expression
-read from the user.
-
- Error signaling and handling have some resemblance to @code{throw} and
-@code{catch}, but they are entirely separate facilities. An error
-cannot be caught by a @code{catch}, and a @code{throw} cannot be handled
-by an error handler (though using @code{throw} when there is no suitable
-@code{catch} signals an error that can be handled).
-
-@defspec condition-case var protected-form handlers@dots{}
-This special form establishes the error handlers @var{handlers} around
-the execution of @var{protected-form}. If @var{protected-form} executes
-without error, the value it returns becomes the value of the
-@code{condition-case} form; in this case, the @code{condition-case} has
-no effect. The @code{condition-case} form makes a difference when an
-error occurs during @var{protected-form}.
-
-Each of the @var{handlers} is a list of the form @code{(@var{conditions}
-@var{body}@dots{})}. Here @var{conditions} is an error condition name
-to be handled, or a list of condition names; @var{body} is one or more
-Lisp expressions to be executed when this handler handles an error.
-Here are examples of handlers:
-
-@smallexample
-@group
-(error nil)
-
-(arith-error (message "Division by zero"))
-
-((arith-error file-error)
- (message
- "Either division by zero or failure to open a file"))
-@end group
-@end smallexample
-
-Each error that occurs has an @dfn{error symbol} that describes what
-kind of error it is. The @code{error-conditions} property of this
-symbol is a list of condition names (@pxref{Error Symbols}). Emacs
-searches all the active @code{condition-case} forms for a handler that
-specifies one or more of these condition names; the innermost matching
-@code{condition-case} handles the error. Within this
-@code{condition-case}, the first applicable handler handles the error.
-
-After executing the body of the handler, the @code{condition-case}
-returns normally, using the value of the last form in the handler body
-as the overall value.
-
-@cindex error description
-The argument @var{var} is a variable. @code{condition-case} does not
-bind this variable when executing the @var{protected-form}, only when it
-handles an error. At that time, it binds @var{var} locally to an
-@dfn{error description}, which is a list giving the particulars of the
-error. The error description has the form @code{(@var{error-symbol}
-. @var{data})}. The handler can refer to this list to decide what to
-do. For example, if the error is for failure opening a file, the file
-name is the second element of @var{data}---the third element of the
-error description.
-
-If @var{var} is @code{nil}, that means no variable is bound. Then the
-error symbol and associated data are not available to the handler.
-@end defspec
-
-@defun error-message-string error-description
-This function returns the error message string for a given error
-descriptor. It is useful if you want to handle an error by printing the
-usual error message for that error.
-@end defun
-
-@cindex @code{arith-error} example
-Here is an example of using @code{condition-case} to handle the error
-that results from dividing by zero. The handler displays the error
-message (but without a beep), then returns a very large number.
-
-@smallexample
-@group
-(defun safe-divide (dividend divisor)
- (condition-case err
- ;; @r{Protected form.}
- (/ dividend divisor)
- ;; @r{The handler.}
- (arith-error ; @r{Condition.}
- ;; @r{Display the usual message for this error.}
- (message "%s" (error-message-string err))
- 1000000)))
-@result{} safe-divide
-@end group
-
-@group
-(safe-divide 5 0)
- @print{} Arithmetic error: (arith-error)
-@result{} 1000000
-@end group
-@end smallexample
-
-@noindent
-The handler specifies condition name @code{arith-error} so that it will handle only division-by-zero errors. Other kinds of errors will not be handled, at least not by this @code{condition-case}. Thus,
-
-@smallexample
-@group
-(safe-divide nil 3)
- @error{} Wrong type argument: integer-or-marker-p, nil
-@end group
-@end smallexample
-
- Here is a @code{condition-case} that catches all kinds of errors,
-including those signaled with @code{error}:
-
-@smallexample
-@group
-(setq baz 34)
- @result{} 34
-@end group
-
-@group
-(condition-case err
- (if (eq baz 35)
- t
- ;; @r{This is a call to the function @code{error}.}
- (error "Rats! The variable %s was %s, not 35" 'baz baz))
- ;; @r{This is the handler; it is not a form.}
- (error (princ (format "The error was: %s" err))
- 2))
-@print{} The error was: (error "Rats! The variable baz was 34, not 35")
-@result{} 2
-@end group
-@end smallexample
-
-@node Error Symbols
-@subsubsection Error Symbols and Condition Names
-@cindex error symbol
-@cindex error name
-@cindex condition name
-@cindex user-defined error
-@kindex error-conditions
-
- When you signal an error, you specify an @dfn{error symbol} to specify
-the kind of error you have in mind. Each error has one and only one
-error symbol to categorize it. This is the finest classification of
-errors defined by the Emacs Lisp language.
-
- These narrow classifications are grouped into a hierarchy of wider
-classes called @dfn{error conditions}, identified by @dfn{condition
-names}. The narrowest such classes belong to the error symbols
-themselves: each error symbol is also a condition name. There are also
-condition names for more extensive classes, up to the condition name
-@code{error} which takes in all kinds of errors. Thus, each error has
-one or more condition names: @code{error}, the error symbol if that
-is distinct from @code{error}, and perhaps some intermediate
-classifications.
-
- In order for a symbol to be an error symbol, it must have an
-@code{error-conditions} property which gives a list of condition names.
-This list defines the conditions that this kind of error belongs to.
-(The error symbol itself, and the symbol @code{error}, should always be
-members of this list.) Thus, the hierarchy of condition names is
-defined by the @code{error-conditions} properties of the error symbols.
-
- In addition to the @code{error-conditions} list, the error symbol
-should have an @code{error-message} property whose value is a string to
-be printed when that error is signaled but not handled. If the
-@code{error-message} property exists, but is not a string, the error
-message @samp{peculiar error} is used.
-@cindex peculiar error
-
- Here is how we define a new error symbol, @code{new-error}:
-
-@example
-@group
-(put 'new-error
- 'error-conditions
- '(error my-own-errors new-error))
-@result{} (error my-own-errors new-error)
-@end group
-@group
-(put 'new-error 'error-message "A new error")
-@result{} "A new error"
-@end group
-@end example
-
-@noindent
-This error has three condition names: @code{new-error}, the narrowest
-classification; @code{my-own-errors}, which we imagine is a wider
-classification; and @code{error}, which is the widest of all.
-
- The error string should start with a capital letter but it should
-not end with a period. This is for consistency with the rest of Emacs.
-
- Naturally, Emacs will never signal @code{new-error} on its own; only
-an explicit call to @code{signal} (@pxref{Signaling Errors}) in your
-code can do this:
-
-@example
-@group
-(signal 'new-error '(x y))
- @error{} A new error: x, y
-@end group
-@end example
-
- This error can be handled through any of the three condition names.
-This example handles @code{new-error} and any other errors in the class
-@code{my-own-errors}:
-
-@example
-@group
-(condition-case foo
- (bar nil t)
- (my-own-errors nil))
-@end group
-@end example
-
- The significant way that errors are classified is by their condition
-names---the names used to match errors with handlers. An error symbol
-serves only as a convenient way to specify the intended error message
-and list of condition names. It would be cumbersome to give
-@code{signal} a list of condition names rather than one error symbol.
-
- By contrast, using only error symbols without condition names would
-seriously decrease the power of @code{condition-case}. Condition names
-make it possible to categorize errors at various levels of generality
-when you write an error handler. Using error symbols alone would
-eliminate all but the narrowest level of classification.
-
- @xref{Standard Errors}, for a list of all the standard error symbols
-and their conditions.
-
-@node Cleanups
-@subsection Cleaning Up from Nonlocal Exits
-
- The @code{unwind-protect} construct is essential whenever you
-temporarily put a data structure in an inconsistent state; it permits
-you to ensure the data are consistent in the event of an error or throw.
-
-@defspec unwind-protect body cleanup-forms@dots{}
-@cindex cleanup forms
-@cindex protected forms
-@cindex error cleanup
-@cindex unwinding
-@code{unwind-protect} executes the @var{body} with a guarantee that the
-@var{cleanup-forms} will be evaluated if control leaves @var{body}, no
-matter how that happens. The @var{body} may complete normally, or
-execute a @code{throw} out of the @code{unwind-protect}, or cause an
-error; in all cases, the @var{cleanup-forms} will be evaluated.
-
-If the @var{body} forms finish normally, @code{unwind-protect} returns
-the value of the last @var{body} form, after it evaluates the
-@var{cleanup-forms}. If the @var{body} forms do not finish,
-@code{unwind-protect} does not return any value in the normal sense.
-
-Only the @var{body} is actually protected by the @code{unwind-protect}.
-If any of the @var{cleanup-forms} themselves exits nonlocally (e.g., via
-a @code{throw} or an error), @code{unwind-protect} is @emph{not}
-guaranteed to evaluate the rest of them. If the failure of one of the
-@var{cleanup-forms} has the potential to cause trouble, then protect it
-with another @code{unwind-protect} around that form.
-
-The number of currently active @code{unwind-protect} forms counts,
-together with the number of local variable bindings, against the limit
-@code{max-specpdl-size} (@pxref{Local Variables}).
-@end defspec
-
- For example, here we make an invisible buffer for temporary use, and
-make sure to kill it before finishing:
-
-@smallexample
-@group
-(save-excursion
- (let ((buffer (get-buffer-create " *temp*")))
- (set-buffer buffer)
- (unwind-protect
- @var{body}
- (kill-buffer buffer))))
-@end group
-@end smallexample
-
-@noindent
-You might think that we could just as well write @code{(kill-buffer
-(current-buffer))} and dispense with the variable @code{buffer}.
-However, the way shown above is safer, if @var{body} happens to get an
-error after switching to a different buffer! (Alternatively, you could
-write another @code{save-excursion} around the body, to ensure that the
-temporary buffer becomes current in time to kill it.)
-
-@findex ftp-login
- Here is an actual example taken from the file @file{ftp.el}. It
-creates a process (@pxref{Processes}) to try to establish a connection
-to a remote machine. As the function @code{ftp-login} is highly
-susceptible to numerous problems that the writer of the function cannot
-anticipate, it is protected with a form that guarantees deletion of the
-process in the event of failure. Otherwise, Emacs might fill up with
-useless subprocesses.
-
-@smallexample
-@group
-(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)))))
-@end group
-@end smallexample
-
- This example actually has a small bug: if the user types @kbd{C-g} to
-quit, and the quit happens immediately after the function
-@code{ftp-setup-buffer} returns but before the variable @code{process} is
-set, the process will not be killed. There is no easy way to fix this bug,
-but at least it is very unlikely.
-
- Here is another example which uses @code{unwind-protect} to make sure
-to kill a temporary buffer. In this example, the value returned by
-@code{unwind-protect} is used.
-
-@smallexample
-(defun shell-command-string (cmd)
- "Return the output of the shell command CMD, as a string."
- (save-excursion
- (set-buffer (generate-new-buffer " OS*cmd"))
- (shell-command cmd t)
- (unwind-protect
- (buffer-string)
- (kill-buffer (current-buffer)))))
-@end smallexample
diff --git a/lispref/debugging.texi b/lispref/debugging.texi
deleted file mode 100644
index b045d93b94e..00000000000
--- a/lispref/debugging.texi
+++ /dev/null
@@ -1,724 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/debugging
-@node Debugging, Read and Print, Byte Compilation, Top
-@chapter Debugging Lisp Programs
-
- There are three ways to investigate a problem in an Emacs Lisp program,
-depending on what you are doing with the program when the problem appears.
-
-@itemize @bullet
-@item
-If the problem occurs when you run the program, you can use a Lisp
-debugger (either the default debugger or Edebug) to investigate what is
-happening during execution.
-
-@item
-If the problem is syntactic, so that Lisp cannot even read the program,
-you can use the Emacs facilities for editing Lisp to localize it.
-
-@item
-If the problem occurs when trying to compile the program with the byte
-compiler, you need to know how to examine the compiler's input buffer.
-@end itemize
-
-@menu
-* Debugger:: How the Emacs Lisp debugger is implemented.
-* Syntax Errors:: How to find syntax errors.
-* Compilation Errors:: How to find errors that show up in byte compilation.
-* Edebug:: A source-level Emacs Lisp debugger.
-@end menu
-
- Another useful debugging tool is the dribble file. When a dribble
-file is open, Emacs copies all keyboard input characters to that file.
-Afterward, you can examine the file to find out what input was used.
-@xref{Terminal Input}.
-
- For debugging problems in terminal descriptions, the
-@code{open-termscript} function can be useful. @xref{Terminal Output}.
-
-@node Debugger
-@section The Lisp Debugger
-@cindex debugger
-@cindex Lisp debugger
-@cindex break
-
- The @dfn{Lisp debugger} provides the ability to suspend evaluation of
-a form. While evaluation is suspended (a state that is commonly known
-as a @dfn{break}), you may examine the run time stack, examine the
-values of local or global variables, or change those values. Since a
-break is a recursive edit, all the usual editing facilities of Emacs are
-available; you can even run programs that will enter the debugger
-recursively. @xref{Recursive Editing}.
-
-@menu
-* Error Debugging:: Entering the debugger when an error happens.
-* Infinite Loops:: Stopping and debugging a program that doesn't exit.
-* Function Debugging:: Entering it when a certain function is called.
-* Explicit Debug:: Entering it at a certain point in the program.
-* Using Debugger:: What the debugger does; what you see while in it.
-* Debugger Commands:: Commands used while in the debugger.
-* Invoking the Debugger:: How to call the function @code{debug}.
-* Internals of Debugger:: Subroutines of the debugger, and global variables.
-@end menu
-
-@node Error Debugging
-@subsection Entering the Debugger on an Error
-@cindex error debugging
-@cindex debugging errors
-
- The most important time to enter the debugger is when a Lisp error
-happens. This allows you to investigate the immediate causes of the
-error.
-
- However, entry to the debugger is not a normal consequence of an
-error. Many commands frequently get Lisp errors when invoked in
-inappropriate contexts (such as @kbd{C-f} at the end of the buffer) and
-during ordinary editing it would be very unpleasant to enter the
-debugger each time this happens. If you want errors to enter the
-debugger, set the variable @code{debug-on-error} to non-@code{nil}.
-
-@defopt debug-on-error
-This variable determines whether the debugger is called when an error is
-signaled and not handled. If @code{debug-on-error} is @code{t}, all
-errors call the debugger. If it is @code{nil}, none call the debugger.
-
-The value can also be a list of error conditions that should call the
-debugger. For example, if you set it to the list
-@code{(void-variable)}, then only errors about a variable that has no
-value invoke the debugger.
-
-When this variable is non-@code{nil}, Emacs does not catch errors that
-happen in process filter functions and sentinels. Therefore, these
-errors also can invoke the debugger. @xref{Processes}.
-@end defopt
-
-@defopt debug-ignored-errors
-This variable specifies certain kinds of errors that should not enter
-the debugger. Its value is a list of error condition symbols and/or
-regular expressions. If the error has any of those condition symbols,
-or if the error message matches any of the regular expressions, then
-that error does not enter the debugger, regardless of the value of
-@code{debug-on-error}.
-
-The normal value of this variable lists several errors that happen often
-during editing but rarely result from bugs in Lisp programs.
-@end defopt
-
- To debug an error that happens during loading of the @file{.emacs}
-file, use the option @samp{-debug-init}, which binds
-@code{debug-on-error} to @code{t} while @file{.emacs} is loaded and
-inhibits use of @code{condition-case} to catch init file errors.
-
- If your @file{.emacs} file sets @code{debug-on-error}, the effect may
-not last past the end of loading @file{.emacs}. (This is an undesirable
-byproduct of the code that implements the @samp{-debug-init} command
-line option.) The best way to make @file{.emacs} set
-@code{debug-on-error} permanently is with @code{after-init-hook}, like
-this:
-
-@example
-(add-hook 'after-init-hook
- '(lambda () (setq debug-on-error t)))
-@end example
-
-@node Infinite Loops
-@subsection Debugging Infinite Loops
-@cindex infinite loops
-@cindex loops, infinite
-@cindex quitting from infinite loop
-@cindex stopping an infinite loop
-
- When a program loops infinitely and fails to return, your first
-problem is to stop the loop. On most operating systems, you can do this
-with @kbd{C-g}, which causes quit.
-
- Ordinary quitting gives no information about why the program was
-looping. To get more information, you can set the variable
-@code{debug-on-quit} 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}. Likewise, @code{debug-on-quit} has no effect on
-errors.
-
- Once you have the debugger running in the middle of the infinite loop,
-you can proceed from the debugger using the stepping commands. If you
-step through the entire loop, you will probably get enough information
-to solve the problem.
-
-@defopt debug-on-quit
-This variable determines whether the debugger is called when @code{quit}
-is signaled and not handled. If @code{debug-on-quit} is non-@code{nil},
-then the debugger is called whenever you quit (that is, type @kbd{C-g}).
-If @code{debug-on-quit} is @code{nil}, then the debugger is not called
-when you quit. @xref{Quitting}.
-@end defopt
-
-@node Function Debugging
-@subsection Entering the Debugger on a Function Call
-@cindex function call debugging
-@cindex debugging specific functions
-
- To investigate a problem that happens in the middle of a program, one
-useful technique is to enter the debugger whenever a certain function is
-called. You can do this to the function in which the problem occurs,
-and then step through the function, or you can do this to a function
-called shortly before the problem, step quickly over the call to that
-function, and then step through its caller.
-
-@deffn Command debug-on-entry function-name
- This function requests @var{function-name} to invoke the debugger each time
-it is called. It works by inserting the form @code{(debug 'debug)} into
-the function definition as the first form.
-
- Any function defined as Lisp code may be set to break on entry,
-regardless of whether it is interpreted code or compiled code. If the
-function is a command, it will enter the debugger when called from Lisp
-and when called interactively (after the reading of the arguments). You
-can't debug primitive functions (i.e., those written in C) this way.
-
- When @code{debug-on-entry} is called interactively, it prompts
-for @var{function-name} in the minibuffer.
-
- If the function is already set up to invoke the debugger on entry,
-@code{debug-on-entry} does nothing.
-
- @strong{Note:} if you redefine a function after using
-@code{debug-on-entry} on it, the code to enter the debugger is lost.
-
- @code{debug-on-entry} returns @var{function-name}.
-
-@example
-@group
-(defun fact (n)
- (if (zerop n) 1
- (* n (fact (1- n)))))
- @result{} fact
-@end group
-@group
-(debug-on-entry 'fact)
- @result{} fact
-@end group
-@group
-(fact 3)
-@end group
-
-@group
------- Buffer: *Backtrace* ------
-Entering:
-* fact(3)
- eval-region(4870 4878 t)
- byte-code("...")
- eval-last-sexp(nil)
- (let ...)
- eval-insert-last-sexp(nil)
-* call-interactively(eval-insert-last-sexp)
------- Buffer: *Backtrace* ------
-@end group
-
-@group
-(symbol-function 'fact)
- @result{} (lambda (n)
- (debug (quote debug))
- (if (zerop n) 1 (* n (fact (1- n)))))
-@end group
-@end example
-@end deffn
-
-@deffn Command cancel-debug-on-entry function-name
-This function undoes the effect of @code{debug-on-entry} on
-@var{function-name}. When called interactively, it prompts for
-@var{function-name} in the minibuffer. If @var{function-name} is
-@code{nil} or the empty string, it cancels debugging for all functions.
-
-If @code{cancel-debug-on-entry} is called more than once on the same
-function, the second call does nothing. @code{cancel-debug-on-entry}
-returns @var{function-name}.
-@end deffn
-
-@node Explicit Debug
-@subsection Explicit Entry to the Debugger
-
- You can cause the debugger to be called at a certain point in your
-program by writing the expression @code{(debug)} at that point. To do
-this, visit the source file, insert the text @samp{(debug)} at the
-proper place, and type @kbd{C-M-x}. Be sure to undo this insertion
-before you save the file!
-
- The place where you insert @samp{(debug)} must be a place where an
-additional form can be evaluated and its value ignored. (If the value
-of @code{(debug)} isn't ignored, it will alter the execution of the
-program!) The most common suitable places are inside a @code{progn} or
-an implicit @code{progn} (@pxref{Sequencing}).
-
-@node Using Debugger
-@subsection Using the Debugger
-
- 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 the error message and associated data, if it was invoked due to an
-error).
-
- The backtrace buffer is read-only and uses a special major mode,
-Debugger mode, in which letters are defined as debugger commands. The
-usual Emacs editing commands are available; thus, you can switch windows
-to examine the buffer that was being edited at the time of the error,
-switch buffers, visit files, or do any other sort of editing. However,
-the debugger is a recursive editing level (@pxref{Recursive Editing})
-and it is wise to go back to the backtrace buffer and exit the debugger
-(with the @kbd{q} command) when you are finished with it. Exiting
-the debugger gets out of the recursive edit and kills the backtrace
-buffer.
-
-@cindex current stack frame
- The backtrace buffer shows you the functions that are executing and
-their argument values. It also allows you to specify a stack frame by
-moving point to the line describing that frame. (A stack frame is the
-place where the Lisp interpreter records information about a particular
-invocation of a function.) The frame whose line point is on is
-considered the @dfn{current frame}. Some of the debugger commands
-operate on the current frame.
-
- The debugger itself must be run byte-compiled, since it makes
-assumptions about how many stack frames are used for the debugger
-itself. These assumptions are false if the debugger is running
-interpreted.
-
-@need 3000
-
-@node Debugger Commands
-@subsection Debugger Commands
-@cindex debugger command list
-
- Inside the debugger (in Debugger mode), these special commands are
-available in addition to the usual cursor motion commands. (Keep in
-mind that all the usual facilities of Emacs, such as switching windows
-or buffers, are still available.)
-
- The most important use of debugger commands is for stepping through
-code, so that you can see how control flows. The debugger can step
-through the control structures of an interpreted function, but cannot do
-so in a byte-compiled function. If you would like to step through a
-byte-compiled function, replace it with an interpreted definition of the
-same function. (To do this, visit the source file for the function and
-type @kbd{C-M-x} on its definition.)
-
- Here is a list of Debugger mode commands:
-
-@table @kbd
-@item c
-Exit the debugger and continue execution. When continuing is possible,
-it resumes execution of the program 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).
-
-Continuing is possible after entry to the debugger due to function entry
-or exit, explicit invocation, or quitting. You cannot continue if the
-debugger was entered because of an error.
-
-@item d
-Continue execution, but enter the debugger the next time any 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 so that the debugger will be
-called again when the frame is exited. You can use the @kbd{u} command
-to cancel this flag.
-
-@item b
-Flag the current frame so that the debugger will be entered when the
-frame is exited. Frames flagged in this way are marked with stars
-in the backtrace buffer.
-
-@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. The debugger alters certain important
-variables, and the current buffer, as part of its operation; @kbd{e}
-temporarily restores their outside-the-debugger values so you can
-examine them. This makes the debugger more transparent. By contrast,
-@kbd{M-:} does nothing special in the debugger; it shows you the
-variable values within the debugger.
-
-@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, and not 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 @kbd{r} command is useful 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. It
-is also useful if you call @code{debug} and use its return value.
-Otherwise, @kbd{r} has the same effect as @kbd{c}, and the specified
-return value does not matter.
-
-You can't use @kbd{r} when the debugger was entered due to an error.
-@end table
-
-@node Invoking the Debugger
-@subsection Invoking the Debugger
-
- Here we describe fully the function used to invoke the debugger.
-
-@defun debug &rest debugger-args
-This function enters the debugger. It switches buffers to a buffer
-named @samp{*Backtrace*} (or @samp{*Backtrace*<2>} if it is the second
-recursive entry to the debugger, etc.), and fills it with information
-about the stack of Lisp function calls. It then enters a recursive
-edit, showing the backtrace buffer in Debugger mode.
-
-The Debugger mode @kbd{c} and @kbd{r} commands exit the recursive edit;
-then @code{debug} switches back to the previous buffer and returns to
-whatever called @code{debug}. This is the only way the function
-@code{debug} can return to its caller.
-
-If the first of the @var{debugger-args} passed to @code{debug} is
-@code{nil} (or if it is not one of the special values in the table
-below), then @code{debug} displays the rest of its arguments at the
-top of the @samp{*Backtrace*} buffer. This mechanism is used to display
-a message to the user.
-
-However, if the first argument passed to @code{debug} is one of the
-following special values, then it has special significance. Normally,
-these values are passed to @code{debug} only by the internals of Emacs
-and the debugger, and not by programmers calling @code{debug}.
-
-The special values are:
-
-@table @code
-@item lambda
-@cindex @code{lambda} in debug
-A first argument of @code{lambda} means @code{debug} was called because
-of entry to a function when @code{debug-on-next-call} was
-non-@code{nil}. The debugger displays @samp{Entering:} as a line of
-text at the top of the buffer.
-
-@item debug
-@code{debug} as first argument indicates a call to @code{debug} because
-of entry to a function that was set to debug on entry. The debugger
-displays @samp{Entering:}, just as in the @code{lambda} case. It also
-marks the stack frame for that function so that it will invoke the
-debugger when exited.
-
-@item t
-When the first argument is @code{t}, this indicates a call to
-@code{debug} due to evaluation of a list form when
-@code{debug-on-next-call} is non-@code{nil}. The debugger displays the
-following as the top line in the buffer:
-
-@smallexample
-Beginning evaluation of function call form:
-@end smallexample
-
-@item exit
-When the first argument is @code{exit}, it indicates the exit of a
-stack frame previously marked to invoke the debugger on exit. The
-second argument given to @code{debug} in this case is the value being
-returned from the frame. The debugger displays @samp{Return value:} on
-the top line of the buffer, followed by the value being returned.
-
-@item error
-@cindex @code{error} in debug
-When the first argument is @code{error}, the debugger indicates that
-it is being entered because an error or @code{quit} was signaled and not
-handled, by displaying @samp{Signaling:} followed by the error signaled
-and any arguments to @code{signal}. For example,
-
-@example
-@group
-(let ((debug-on-error t))
- (/ 1 0))
-@end group
-
-@group
------- Buffer: *Backtrace* ------
-Signaling: (arith-error)
- /(1 0)
-...
------- Buffer: *Backtrace* ------
-@end group
-@end example
-
-If an error was signaled, presumably the variable
-@code{debug-on-error} is non-@code{nil}. If @code{quit} was signaled,
-then presumably the variable @code{debug-on-quit} is non-@code{nil}.
-
-@item nil
-Use @code{nil} as the first of the @var{debugger-args} when you want
-to enter the debugger explicitly. The rest of the @var{debugger-args}
-are printed on the top line of the buffer. You can use this feature to
-display messages---for example, to remind yourself of the conditions
-under which @code{debug} is called.
-@end table
-@end defun
-
-@node Internals of Debugger
-@subsection Internals of the Debugger
-
- This section describes functions and variables used internally by the
-debugger.
-
-@defvar debugger
-The value of this variable is the function to call to invoke the
-debugger. Its value must be a function of any number of arguments (or,
-more typically, the name of a function). Presumably this function will
-enter some kind of debugger. The default value of the variable is
-@code{debug}.
-
-The first argument that Lisp hands to the function indicates why it
-was called. The convention for arguments is detailed in the description
-of @code{debug}.
-@end defvar
-
-@deffn Command backtrace
-@cindex run time stack
-@cindex call stack
-This function prints a trace of Lisp function calls currently active.
-This is the function used by @code{debug} to fill up the
-@samp{*Backtrace*} buffer. It is written in C, since it must have access
-to the stack to determine which function calls are active. The return
-value is always @code{nil}.
-
-In the following example, a Lisp expression calls @code{backtrace}
-explicitly. This prints the backtrace to the stream
-@code{standard-output}: in this case, to the buffer
-@samp{backtrace-output}. Each line of the backtrace represents one
-function call. The line shows the values of the function's arguments if
-they are all known. If they are still being computed, the line says so.
-The arguments of special forms are elided.
-
-@smallexample
-@group
-(with-output-to-temp-buffer "backtrace-output"
- (let ((var 1))
- (save-excursion
- (setq var (eval '(progn
- (1+ var)
- (list 'testing (backtrace))))))))
-
- @result{} nil
-@end group
-
-@group
------------ Buffer: backtrace-output ------------
- backtrace()
- (list ...computing arguments...)
- (progn ...)
- eval((progn (1+ var) (list (quote testing) (backtrace))))
- (setq ...)
- (save-excursion ...)
- (let ...)
- (with-output-to-temp-buffer ...)
- eval-region(1973 2142 #<buffer *scratch*>)
- byte-code("... for eval-print-last-sexp ...")
- eval-print-last-sexp(nil)
-* call-interactively(eval-print-last-sexp)
------------ Buffer: backtrace-output ------------
-@end group
-@end smallexample
-
-The character @samp{*} indicates a frame whose debug-on-exit flag is
-set.
-@end deffn
-
-@ignore @c Not worth mentioning
-@defopt stack-trace-on-error
-@cindex stack trace
-This variable controls whether Lisp automatically displays a
-backtrace buffer after every error that is not handled. A quit signal
-counts as an error for this variable. If it is non-@code{nil} then a
-backtrace is shown in a pop-up buffer named @samp{*Backtrace*} on every
-error. If it is @code{nil}, then a backtrace is not shown.
-
-When a backtrace is shown, that buffer is not selected. If either
-@code{debug-on-quit} or @code{debug-on-error} is also non-@code{nil}, then
-a backtrace is shown in one buffer, and the debugger is popped up in
-another buffer with its own backtrace.
-
-We consider this feature to be obsolete and superseded by the debugger
-itself.
-@end defopt
-@end ignore
-
-@defvar debug-on-next-call
-@cindex @code{eval}, and debugging
-@cindex @code{apply}, and debugging
-@cindex @code{funcall}, and debugging
-If this variable is non-@code{nil}, it says to call the debugger before
-the next @code{eval}, @code{apply} or @code{funcall}. Entering the
-debugger sets @code{debug-on-next-call} to @code{nil}.
-
-The @kbd{d} command in the debugger works by setting this variable.
-@end defvar
-
-@defun backtrace-debug level flag
-This function sets the debug-on-exit flag of the stack frame @var{level}
-levels down the stack, giving it the value @var{flag}. If @var{flag} is
-non-@code{nil}, this will cause the debugger to be entered when that
-frame later exits. Even a nonlocal exit through that frame will enter
-the debugger.
-
-This function is used only by the debugger.
-@end defun
-
-@defvar command-debug-status
-This variable records the debugging status of the current interactive
-command. Each time a command is called interactively, this variable is
-bound to @code{nil}. The debugger can set this variable to leave
-information for future debugger invocations during the same command.
-
-The advantage, for the debugger, of using this variable rather than
-another global variable is that the data will never carry over to a
-subsequent command invocation.
-@end defvar
-
-@defun backtrace-frame frame-number
-The function @code{backtrace-frame} is intended for use in Lisp
-debuggers. It returns information about what computation is happening
-in the stack frame @var{frame-number} levels down.
-
-If that frame has not evaluated the arguments yet (or is a special
-form), the value is @code{(nil @var{function} @var{arg-forms}@dots{})}.
-
-If that frame has evaluated its arguments and called its function
-already, the value is @code{(t @var{function}
-@var{arg-values}@dots{})}.
-
-In the return value, @var{function} is whatever was supplied as the
-@sc{car} of the evaluated list, or a @code{lambda} expression in the
-case of a macro call. If the function has a @code{&rest} argument, that
-is represented as the tail of the list @var{arg-values}.
-
-If @var{frame-number} is out of range, @code{backtrace-frame} returns
-@code{nil}.
-@end defun
-
-@node Syntax Errors
-@section Debugging Invalid Lisp Syntax
-
- The Lisp reader reports invalid syntax, but cannot say where the real
-problem is. For example, the error ``End of file during parsing'' in
-evaluating an expression indicates an excess of open parentheses (or
-square brackets). The reader detects this imbalance at the end of the
-file, but it cannot figure out where the close parenthesis should have
-been. Likewise, ``Invalid read syntax: ")"'' indicates an excess close
-parenthesis or missing open parenthesis, but does not say where the
-missing parenthesis belongs. How, then, to find what to change?
-
- If the problem is not simply an imbalance of parentheses, a useful
-technique is to try @kbd{C-M-e} at the beginning of each defun, and see
-if it goes to the place where that defun appears to end. If it does
-not, there is a problem in that defun.
-
- However, unmatched parentheses are the most common syntax errors in
-Lisp, and we can give further advice for those cases.
-
-@menu
-* Excess Open:: How to find a spurious open paren or missing close.
-* Excess Close:: How to find a spurious close paren or missing open.
-@end menu
-
-@node Excess Open
-@subsection Excess Open Parentheses
-
- The first step is to find the defun that is unbalanced. If there is
-an excess open parenthesis, the way to do this is to insert a
-close parenthesis at the end of the file and type @kbd{C-M-b}
-(@code{backward-sexp}). This will move you to the beginning of the
-defun that is unbalanced. (Then type @kbd{C-@key{SPC} C-_ C-u
-C-@key{SPC}} to set the mark there, undo the insertion of the
-close parenthesis, and finally return to the mark.)
-
- The next step is to determine precisely what is wrong. There is no
-way to be sure of this except to study the program, but often the
-existing indentation is a clue to where the parentheses should have
-been. The easiest way to use this clue is to reindent with @kbd{C-M-q}
-and see what moves.
-
- Before you do this, make sure the defun has enough close parentheses.
-Otherwise, @kbd{C-M-q} will get an error, or will reindent all the rest
-of the file until the end. So move to the end of the defun and insert a
-close parenthesis there. Don't use @kbd{C-M-e} to move there, since
-that too will fail to work until the defun is balanced.
-
- Now you can go to the beginning of the defun and type @kbd{C-M-q}.
-Usually all the lines from a certain point to the end of the function
-will shift to the right. There is probably a missing close parenthesis,
-or a superfluous open parenthesis, near that point. (However, don't
-assume this is true; study the code to make sure.) Once you have found
-the discrepancy, undo the @kbd{C-M-q} with @kbd{C-_}, since the old
-indentation is probably appropriate to the intended parentheses.
-
- After you think you have fixed the problem, use @kbd{C-M-q} again. If
-the old indentation actually fit the intended nesting of parentheses,
-and you have put back those parentheses, @kbd{C-M-q} should not change
-anything.
-
-@node Excess Close
-@subsection Excess Close Parentheses
-
- To deal with an excess close parenthesis, first insert an open
-parenthesis at the beginning of the file, back up over it, and type
-@kbd{C-M-f} to find the end of the unbalanced defun. (Then type
-@kbd{C-@key{SPC} C-_ C-u C-@key{SPC}} to set the mark there, undo the
-insertion of the open parenthesis, and finally return to the mark.)
-
- Then find the actual matching close parenthesis by typing @kbd{C-M-f}
-at the beginning of the defun. This will leave you somewhere short of
-the place where the defun ought to end. It is possible that you will
-find a spurious close parenthesis in that vicinity.
-
- If you don't see a problem at that point, the next thing to do is to
-type @kbd{C-M-q} at the beginning of the defun. A range of lines will
-probably shift left; if so, the missing open parenthesis or spurious
-close parenthesis is probably near the first of those lines. (However,
-don't assume this is true; study the code to make sure.) Once you have
-found the discrepancy, undo the @kbd{C-M-q} with @kbd{C-_}, since the
-old indentation is probably appropriate to the intended parentheses.
-
- After you think you have fixed the problem, use @kbd{C-M-q} again. If
-the old indentation actually fit the intended nesting of parentheses,
-and you have put back those parentheses, @kbd{C-M-q} should not change
-anything.
-
-@node Compilation Errors, Edebug, Syntax Errors, Debugging
-@section Debugging Problems in Compilation
-
- When an error happens during byte compilation, it is normally due to
-invalid syntax in the program you are compiling. The compiler prints a
-suitable error message in the @samp{*Compile-Log*} buffer, and then
-stops. The message may state a function name in which the error was
-found, or it may not. Either way, here is how to find out where in the
-file the error occurred.
-
- What you should do is switch to the buffer @w{@samp{ *Compiler Input*}}.
-(Note that the buffer name starts with a space, so it does not show
-up in @kbd{M-x list-buffers}.) This buffer contains the program being
-compiled, and point shows how far the byte compiler was able to read.
-
- If the error was due to invalid Lisp syntax, point shows exactly where
-the invalid syntax was @emph{detected}. The cause of the error is not
-necessarily near by! Use the techniques in the previous section to find
-the error.
-
- If the error was detected while compiling a form that had been read
-successfully, then point is located at the end of the form. In this
-case, this technique can't localize the error precisely, but can still
-show you which function to check.
-
-@include edebug.texi
diff --git a/lispref/display.texi b/lispref/display.texi
deleted file mode 100644
index ae91f450924..00000000000
--- a/lispref/display.texi
+++ /dev/null
@@ -1,1464 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/display
-@node Display, Calendar, System Interface, Top
-@chapter Emacs Display
-
- This chapter describes a number of features related to the display
-that Emacs presents to the user.
-
-@menu
-* Refresh Screen:: Clearing the screen and redrawing everything on it.
-* Screen Size:: How big is the Emacs screen.
-* Truncation:: Folding or wrapping long text lines.
-* The Echo Area:: Where messages are displayed.
-* Invisible Text:: Hiding part of the buffer text.
-* Selective Display:: Hiding part of the buffer text (the old way).
-* Overlay Arrow:: Display of an arrow to indicate position.
-* Temporary Displays:: Displays that go away automatically.
-* Overlays:: Use overlays to highlight parts of the buffer.
-* Faces:: A face defines a graphics appearance: font, color, etc.
-* Blinking:: How Emacs shows the matching open parenthesis.
-* Inverse Video:: Specifying how the screen looks.
-* Usual Display:: The usual conventions for displaying nonprinting chars.
-* Display Tables:: How to specify other conventions.
-* Beeping:: Audible signal to the user.
-* Window Systems:: Which window system is being used.
-@end menu
-
-@node Refresh Screen
-@section Refreshing the Screen
-
-The function @code{redraw-frame} redisplays the entire contents of a
-given frame. @xref{Frames}.
-
-@c Emacs 19 feature
-@defun redraw-frame frame
-This function clears and redisplays frame @var{frame}.
-@end defun
-
-Even more powerful is @code{redraw-display}:
-
-@deffn Command redraw-display
-This function clears and redisplays all visible frames.
-@end deffn
-
- Processing user input takes absolute priority over redisplay. If you
-call these functions when input is available, they do nothing
-immediately, but a full redisplay does happen eventually---after all the
-input has been processed.
-
- Normally, suspending and resuming Emacs also refreshes the screen.
-Some terminal emulators record separate contents for display-oriented
-programs such as Emacs and for ordinary sequential display. If you are
-using such a terminal, you might want to inhibit the redisplay on
-resumption.
-
-@defvar no-redraw-on-reenter
-@cindex suspend (cf. @code{no-redraw-on-reenter})
-@cindex resume (cf. @code{no-redraw-on-reenter})
-This variable controls whether Emacs redraws the entire screen after it
-has been suspended and resumed. Non-@code{nil} means yes, @code{nil}
-means no.
-@end defvar
-
-@node Screen Size
-@section Screen Size
-@cindex size of screen
-@cindex screen size
-@cindex display lines
-@cindex display columns
-@cindex resize redisplay
-
- The screen size functions access or specify the height or width of
-the terminal. When you are using multiple frames, they apply to the
-selected frame (@pxref{Frames}).
-
-@defun screen-height
-This function returns the number of lines on the screen that are
-available for display.
-
-@example
-@group
-(screen-height)
- @result{} 50
-@end group
-@end example
-@end defun
-
-@defun screen-width
-This function returns the number of columns on the screen that are
-available for display.
-
-@example
-@group
-(screen-width)
- @result{} 80
-@end group
-@end example
-@end defun
-
-@defun set-screen-height lines &optional not-actual-size
-This function declares that the terminal can display @var{lines} lines.
-The sizes of existing windows are altered proportionally to fit.
-
-If @var{not-actual-size} is non-@code{nil}, then Emacs displays
-@var{lines} lines of output, but does not change its value for the
-actual height of the screen. (Knowing the correct actual size may be
-necessary for correct cursor positioning.) Using a smaller height than
-the terminal actually implements may be useful to reproduce behavior
-observed on a smaller screen, or if the terminal malfunctions when using
-its whole screen.
-
-If @var{lines} is different from what it was previously, then the
-entire screen is cleared and redisplayed using the new size.
-
-This function returns @code{nil}.
-@end defun
-
-@defun set-screen-width columns &optional not-actual-size
-This function declares that the terminal can display @var{columns}
-columns. The details are as in @code{set-screen-height}.
-@end defun
-
-@node Truncation
-@section Truncation
-@cindex line wrapping
-@cindex continuation lines
-@cindex @samp{$} in display
-@cindex @samp{\} in display
-
- When a line of text extends beyond the right edge of a window, the
-line can either be continued on the next screen line, or truncated to
-one screen line. The additional screen lines used to display a long
-text line are called @dfn{continuation} lines. Normally, a @samp{$} in
-the rightmost column of the window indicates truncation; a @samp{\} on
-the rightmost column indicates a line that ``wraps'' or is continued
-onto the next line. (The display table can specify alternative
-indicators; see @ref{Display Tables}.)
-
- Note that continuation is different from filling; continuation happens
-on the screen only, not in the buffer contents, and it breaks a line
-precisely at the right margin, not at a word boundary. @xref{Filling}.
-
-@defopt truncate-lines
-This buffer-local variable controls how Emacs displays lines that extend
-beyond the right edge of the window. The default is @code{nil}, which
-specifies continuation. If the value is non-@code{nil}, then these
-lines are truncated.
-
-If the variable @code{truncate-partial-width-windows} is non-@code{nil},
-then truncation is always used for side-by-side windows (within one
-frame) regardless of the value of @code{truncate-lines}.
-@end defopt
-
-@defopt default-truncate-lines
-This variable is the default value for @code{truncate-lines}, for
-buffers that do not have local values for it.
-@end defopt
-
-@defopt truncate-partial-width-windows
-This variable controls display of lines that extend beyond the right
-edge of the window, in side-by-side windows (@pxref{Splitting Windows}).
-If it is non-@code{nil}, these lines are truncated; otherwise,
-@code{truncate-lines} says what to do with them.
-@end defopt
-
- You can override the images that indicate continuation or truncation
-with the display table; see @ref{Display Tables}.
-
- If your buffer contains @strong{very} long lines, and you use
-continuation to display them, just thinking about them can make Emacs
-redisplay slow. The column computation and indentation functions also
-become slow. Then you might find it advisable to set
-@code{cache-long-line-scans} to @code{t}.
-
-@defvar cache-long-line-scans
-If this variable is non-@code{nil}, various indentation and motion
-functions, and Emacs redisplay, cache the results of scanning the
-buffer, and consult the cache to avoid rescanning regions of the buffer
-unless they are modified.
-
-Turning on the cache slows down processing of short lines somewhat.
-
-This variable is automatically local in every buffer.
-@end defvar
-
-@node The Echo Area
-@section The Echo Area
-@cindex error display
-@cindex echo area
-
-The @dfn{echo area} is used for displaying messages made with the
-@code{message} primitive, and for echoing keystrokes. It is not the
-same as the minibuffer, despite the fact that the minibuffer appears
-(when active) in the same place on the screen as the echo area. The
-@cite{GNU Emacs Manual} specifies the rules for resolving conflicts
-between the echo area and the minibuffer for use of that screen space
-(@pxref{Minibuffer,, The Minibuffer, emacs, The GNU Emacs Manual}).
-Error messages appear in the echo area; see @ref{Errors}.
-
-You can write output in the echo area by using the Lisp printing
-functions with @code{t} as the stream (@pxref{Output Functions}), or as
-follows:
-
-@defun message string &rest arguments
-This function displays a one-line message in the echo area. The
-argument @var{string} is similar to a C language @code{printf} control
-string. See @code{format} in @ref{String Conversion}, for the details
-on the conversion specifications. @code{message} returns the
-constructed string.
-
-In batch mode, @code{message} prints the message text on the standard
-error stream, followed by a newline.
-
-@c Emacs 19 feature
-If @var{string} is @code{nil}, @code{message} clears the echo area. If
-the minibuffer is active, this brings the minibuffer contents back onto
-the screen immediately.
-
-@example
-@group
-(message "Minibuffer depth is %d."
- (minibuffer-depth))
- @print{} Minibuffer depth is 0.
-@result{} "Minibuffer depth is 0."
-@end group
-
-@group
----------- Echo Area ----------
-Minibuffer depth is 0.
----------- Echo Area ----------
-@end group
-@end example
-@end defun
-
-Almost all the messages displayed in the echo area are also recorded
-in the @samp{*Messages*} buffer.
-
-@defopt message-log-max
-This variable specifies how many lines to keep in the @samp{*Messages*}
-buffer. The value @code{t} means there is no limit on how many lines to
-keep. The value @code{nil} disables message logging entirely. Here's
-how to display a message and prevent it from being logged:
-
-@example
-(let (message-log-max)
- (message @dots{}))
-@end example
-@end defopt
-
-@defvar echo-keystrokes
-This variable determines how much time should elapse before command
-characters echo. Its value must be an integer, which specifies the
-number of seconds to wait before echoing. If the user types a prefix
-key (such as @kbd{C-x}) and then delays this many seconds before
-continuing, the prefix key is echoed in the echo area. Any subsequent
-characters in the same command will be echoed as well.
-
-If the value is zero, then command input is not echoed.
-@end defvar
-
-@defvar cursor-in-echo-area
-This variable controls where the cursor appears when a message is
-displayed in the echo area. If it is non-@code{nil}, then the cursor
-appears at the end of the message. Otherwise, the cursor appears at
-point---not in the echo area at all.
-
-The value is normally @code{nil}; Lisp programs bind it to @code{t}
-for brief periods of time.
-@end defvar
-
-@node Invisible Text
-@section Invisible Text
-
-@cindex invisible text
-You can make characters @dfn{invisible}, so that they do not appear on
-the screen, with the @code{invisible} property. This can be either a
-text property or a property of an overlay.
-
-In the simplest case, any non-@code{nil} @code{invisible} property makes
-a character invisible. This is the default case---if you don't alter
-the default value of @code{buffer-invisibility-spec}, this is how the
-@code{invisibility} property works. This feature is much like selective
-display (@pxref{Selective Display}), but more general and cleaner.
-
-More generally, you can use the variable @code{buffer-invisibility-spec}
-to control which values of the @code{invisible} property make text
-invisible. This permits you to classify the text into different subsets
-in advance, by giving them different @code{invisible} values, and
-subsequently make various subsets visible or invisible by changing the
-value of @code{buffer-invisibility-spec}.
-
-Controlling visibility with @code{buffer-invisibility-spec} is
-especially useful in a program to display the list of entries in a data
-base. It permits the implementation of convenient filtering commands to
-view just a part of the entries in the data base. Setting this variable
-is very fast, much faster than scanning all the text in the buffer
-looking for properties to change.
-
-@defvar buffer-invisibility-spec
-This variable specifies which kinds of @code{invisible} properties
-actually make a character invisible.
-
-@table @asis
-@item @code{t}
-A character is invisible if its @code{invisible} property is
-non-@code{nil}. This is the default.
-
-@item a list
-Each element of the list makes certain characters invisible.
-Ultimately, a character is invisible if any of the elements of this list
-applies to it. The list can have two kinds of elements:
-
-@table @code
-@item @var{atom}
-A character is invisible if its @code{invisible} propery value
-is @var{atom} or if it is a list with @var{atom} as a member.
-
-@item (@var{atom} . t)
-A character is invisible if its @code{invisible} propery value
-is @var{atom} or if it is a list with @var{atom} as a member.
-Moreover, if this character is at the end of a line and is followed
-by a visible newline, it displays an ellipsis.
-@end table
-@end table
-@end defvar
-
-@vindex line-move-ignore-invisible
- Ordinarily, commands that operate on text or move point do not care
-whether the text is invisible. The user-level line motion commands
-explicitly ignore invisible newlines if
-@code{line-move-ignore-invisible} is non-@code{nil}, but only because
-they are explicitly programmed to do so.
-
-@node Selective Display
-@section Selective Display
-@cindex selective display
-
- @dfn{Selective display} is a pair of features that hide certain
-lines on the screen.
-
- The first variant, explicit selective display, is designed for use in
-a Lisp program. The program controls which lines are hidden by altering
-the text. Outline mode has traditionally used this variant. It has
-been partially replaced by the invisible text feature (@pxref{Invisible
-Text}); there is a new version of Outline mode which uses that instead.
-
- In the second variant, the choice of lines to hide is made
-automatically based on indentation. This variant is designed to be a
-user-level feature.
-
- The way you control explicit selective display is by replacing a
-newline (control-j) with a carriage return (control-m). The text that
-was formerly a line following that newline is now invisible. Strictly
-speaking, it is temporarily no longer a line at all, since only newlines
-can separate lines; it is now part of the previous line.
-
- Selective display does not directly affect editing commands. For
-example, @kbd{C-f} (@code{forward-char}) moves point unhesitatingly into
-invisible text. However, the replacement of newline characters with
-carriage return characters affects some editing commands. For example,
-@code{next-line} skips invisible lines, since it searches only for
-newlines. Modes that use selective display can also define commands
-that take account of the newlines, or that make parts of the text
-visible or invisible.
-
- When you write a selectively displayed buffer into a file, all the
-control-m's are output as newlines. This means that when you next read
-in the file, it looks OK, with nothing invisible. The selective display
-effect is seen only within Emacs.
-
-@defvar selective-display
-This buffer-local variable enables selective display. This means that
-lines, or portions of lines, may be made invisible.
-
-@itemize @bullet
-@item
-If the value of @code{selective-display} is @code{t}, then any portion
-of a line that follows a control-m is not displayed.
-
-@item
-If the value of @code{selective-display} is a positive integer, then
-lines that start with more than that many columns of indentation are not
-displayed.
-@end itemize
-
-When some portion of a buffer is invisible, the vertical movement
-commands operate as if that portion did not exist, allowing a single
-@code{next-line} command to skip any number of invisible lines.
-However, character movement commands (such as @code{forward-char}) do
-not skip the invisible portion, and it is possible (if tricky) to insert
-or delete text in an invisible portion.
-
-In the examples below, we show the @emph{display appearance} of the
-buffer @code{foo}, which changes with the value of
-@code{selective-display}. The @emph{contents} of the buffer do not
-change.
-
-@example
-@group
-(setq selective-display nil)
- @result{} nil
-
----------- Buffer: foo ----------
-1 on this column
- 2on this column
- 3n this column
- 3n this column
- 2on this column
-1 on this column
----------- Buffer: foo ----------
-@end group
-
-@group
-(setq selective-display 2)
- @result{} 2
-
----------- Buffer: foo ----------
-1 on this column
- 2on this column
- 2on this column
-1 on this column
----------- Buffer: foo ----------
-@end group
-@end example
-@end defvar
-
-@defvar selective-display-ellipses
-If this buffer-local variable is non-@code{nil}, then Emacs displays
-@samp{@dots{}} at the end of a line that is followed by invisible text.
-This example is a continuation of the previous one.
-
-@example
-@group
-(setq selective-display-ellipses t)
- @result{} t
-
----------- Buffer: foo ----------
-1 on this column
- 2on this column ...
- 2on this column
-1 on this column
----------- Buffer: foo ----------
-@end group
-@end example
-
-You can use a display table to substitute other text for the ellipsis
-(@samp{@dots{}}). @xref{Display Tables}.
-@end defvar
-
-@node Overlay Arrow
-@section The Overlay Arrow
-@cindex overlay arrow
-
- The @dfn{overlay arrow} is useful for directing the user's attention
-to a particular line in a buffer. For example, in the modes used for
-interface to debuggers, the overlay arrow indicates the line of code
-about to be executed.
-
-@defvar overlay-arrow-string
-This variable holds the string to display to call attention to a
-particular line, or @code{nil} if the arrow feature is not in use.
-@end defvar
-
-@defvar overlay-arrow-position
-This variable holds a marker that indicates where to display the overlay
-arrow. It should point at the beginning of a line. The arrow text
-appears at the beginning of that line, overlaying any text that would
-otherwise appear. Since the arrow is usually short, and the line
-usually begins with indentation, normally nothing significant is
-overwritten.
-
-The overlay string is displayed only in the buffer that this marker
-points into. Thus, only one buffer can have an overlay arrow at any
-given time.
-@c !!! overlay-arrow-position: but the overlay string may remain in the display
-@c of some other buffer until an update is required. This should be fixed
-@c now. Is it?
-@end defvar
-
- You can do the same job by creating an overlay with a
-@code{before-string} property. @xref{Overlay Properties}.
-
-@node Temporary Displays
-@section Temporary Displays
-
- Temporary displays are used by commands to put output into a buffer
-and then present it to the user for perusal rather than for editing.
-Many of the help commands use this feature.
-
-@defspec with-output-to-temp-buffer buffer-name forms@dots{}
-This function executes @var{forms} while arranging to insert any
-output they print into the buffer named @var{buffer-name}. The buffer
-is then shown in some window for viewing, displayed but not selected.
-
-The string @var{buffer-name} specifies the temporary buffer, which
-need not already exist. The argument must be a string, not a buffer.
-The buffer is erased initially (with no questions asked), and it is
-marked as unmodified after @code{with-output-to-temp-buffer} exits.
-
-@code{with-output-to-temp-buffer} binds @code{standard-output} to the
-temporary buffer, then it evaluates the forms in @var{forms}. Output
-using the Lisp output functions within @var{forms} goes by default to
-that buffer (but screen display and messages in the echo area, although
-they are ``output'' in the general sense of the word, are not affected).
-@xref{Output Functions}.
-
-The value of the last form in @var{forms} is returned.
-
-@example
-@group
----------- Buffer: foo ----------
- This is the contents of foo.
----------- Buffer: foo ----------
-@end group
-
-@group
-(with-output-to-temp-buffer "foo"
- (print 20)
- (print standard-output))
-@result{} #<buffer foo>
-
----------- Buffer: foo ----------
-20
-
-#<buffer foo>
-
----------- Buffer: foo ----------
-@end group
-@end example
-@end defspec
-
-@defvar temp-buffer-show-function
-If this variable is non-@code{nil}, @code{with-output-to-temp-buffer}
-calls it as a function to do the job of displaying a help buffer. The
-function gets one argument, which is the buffer it should display.
-
-In Emacs versions 18 and earlier, this variable was called
-@code{temp-buffer-show-hook}.
-@end defvar
-
-@defun momentary-string-display string position &optional char message
-This function momentarily displays @var{string} in the current buffer at
-@var{position}. It has no effect on the undo list or on the buffer's
-modification status.
-
-The momentary display remains until the next input event. If the next
-input event is @var{char}, @code{momentary-string-display} ignores it
-and returns. Otherwise, that event remains buffered for subsequent use
-as input. Thus, typing @var{char} will simply remove the string from
-the display, while typing (say) @kbd{C-f} will remove the string from
-the display and later (presumably) move point forward. The argument
-@var{char} is a space by default.
-
-The return value of @code{momentary-string-display} is not meaningful.
-
-If the string @var{string} does not contain control characters, you can
-do the same job in a more general way by creating an overlay with a
-@code{before-string} property. @xref{Overlay Properties}.
-
-If @var{message} is non-@code{nil}, it is displayed in the echo area
-while @var{string} is displayed in the buffer. If it is @code{nil}, a
-default message says to type @var{char} to continue.
-
-In this example, point is initially located at the beginning of the
-second line:
-
-@example
-@group
----------- Buffer: foo ----------
-This is the contents of foo.
-@point{}Second line.
----------- Buffer: foo ----------
-@end group
-
-@group
-(momentary-string-display
- "**** Important Message! ****"
- (point) ?\r
- "Type RET when done reading")
-@result{} t
-@end group
-
-@group
----------- Buffer: foo ----------
-This is the contents of foo.
-**** Important Message! ****Second line.
----------- Buffer: foo ----------
-
----------- Echo Area ----------
-Type RET when done reading
----------- Echo Area ----------
-@end group
-@end example
-@end defun
-
-@node Overlays
-@section Overlays
-@cindex overlays
-
-You can use @dfn{overlays} to alter the appearance of a buffer's text on
-the screen, for the sake of presentation features. An overlay is an
-object that belongs to a particular buffer, and has a specified
-beginning and end. It also has properties that you can examine and set;
-these affect the display of the text within the overlay.
-
-@menu
-* Overlay Properties:: How to read and set properties.
- What properties do to the screen display.
-* Managing Overlays:: Creating, moving, finding overlays.
-@end menu
-
-@node Overlay Properties
-@subsection Overlay Properties
-
-Overlay properties are like text properties in some respects, but the
-differences are more important than the similarities. Text properties
-are considered a part of the text; overlays are specifically considered
-not to be part of the text. Thus, copying text between various buffers
-and strings preserves text properties, but does not try to preserve
-overlays. Changing a buffer's text properties marks the buffer as
-modified, while moving an overlay or changing its properties does not.
-Unlike text propery changes, overlay changes are not recorded in the
-buffer's undo list.
-
-@table @code
-@item priority
-@kindex priority @r{(overlay property)}
-This property's value (which should be a nonnegative number) determines
-the priority of the overlay. The priority matters when two or more
-overlays cover the same character and both specify a face for display;
-the one whose @code{priority} value is larger takes priority over the
-other, and its face attributes override the face attributes of the lower
-priority overlay.
-
-Currently, all overlays take priority over text properties. Please
-avoid using negative priority values, as we have not yet decided just
-what they should mean.
-
-@item window
-@kindex window @r{(overlay property)}
-If the @code{window} property is non-@code{nil}, then the overlay
-applies only on that window.
-
-@item category
-@kindex category @r{(overlay property)}
-If an overlay has a @code{category} property, we call it the
-@dfn{category} of the overlay. It should be a symbol. The properties
-of the symbol serve as defaults for the properties of the overlay.
-
-@item face
-@kindex face @r{(overlay property)}
-This property controls the font and color of text. Its value is a face
-name or a list of face names. @xref{Faces}, for more information. This
-feature may be temporary; in the future, we may replace it with other
-ways of specifying how to display text.
-
-@item mouse-face
-@kindex mouse-face @r{(overlay property)}
-This property is used instead of @code{face} when the mouse is within
-the range of the overlay. This feature may be temporary, like
-@code{face}.
-
-@item modification-hooks
-@kindex modification-hooks @r{(overlay property)}
-This property's value is a list of functions to be called if any
-character within the overlay is changed or if text is inserted strictly
-within the overlay.
-
-The hook functions are called both before and after each change.
-If the functions save the information they receive, and compare notes
-between calls, they can determine exactly what change has been made
-in the buffer text.
-
-When called before a change, each function receives four arguments: the
-overlay, @code{nil}, and the beginning and end of the text range to be
-modified.
-
-When called after a change, each function receives five arguments: the
-overlay, @code{t}, the beginning and end of the text range just
-modified, and the length of the pre-change text replaced by that range.
-(For an insertion, the pre-change length is zero; for a deletion, that
-length is the number of characters deleted, and the post-change
-beginning and end are equal.)
-
-@item insert-in-front-hooks
-@kindex insert-in-front-hooks @r{(overlay property)}
-This property's value is a list of functions to be called before and
-after inserting text right at the beginning of the overlay. The calling
-conventions are the same as for the @code{modification-hooks} functions.
-
-@item insert-behind-hooks
-@kindex insert-behind-hooks @r{(overlay property)}
-This property's value is a list of functions to be called before and
-after inserting text right at the end of the overlay. The calling
-conventions are the same as for the @code{modification-hooks} functions.
-
-@item invisible
-@kindex invisible @r{(overlay property)}
-The @code{invisible} property can make the text in the overlay
-invisible, which means that it does not appear on the screen.
-@xref{Invisible Text}, for details.
-
-@ignore This isn't implemented yet
-@item intangible
-@kindex intangible @r{(overlay property)}
-The @code{intangible} property on an overlay works just like the
-@code{intangible} text property. @xref{Special Properties}, for details.
-@end ignore
-
-@item before-string
-@kindex before-string @r{(overlay property)}
-This property's value is a string to add to the display at the beginning
-of the overlay. The string does not appear in the buffer in any
-sense---only on the screen. The string should contain only characters
-that display as a single column---control characters, including tabs or
-newlines, will give strange results.
-
-@item after-string
-@kindex after-string @r{(overlay property)}
-This property's value is a string to add to the display at the end of
-the overlay. The string does not appear in the buffer in any
-sense---only on the screen. The string should contain only characters
-that display as a single column---control characters, including tabs or
-newlines, will give strange results.
-
-@item evaporate
-@kindex evaporate @r{(overlay property)}
-If this property is non-@code{nil}, the overlay is deleted automatically
-if it ever becomes empty (i.e., if it spans no characters).
-
-@item local-map
-@cindex keymap of character
-@kindex local-map @r{(text property)}
-If this property is non-@code{nil}, it specifies a keymap for a portion
-of the text. The property's value replaces the buffer's local map, when
-the character after point is within the overlay. @xref{Active Keymaps}.
-@end table
-
- These are the functions for reading and writing the properties of an
-overlay.
-
-@defun overlay-get overlay prop
-This function returns the value of property @var{prop} recorded in
-@var{overlay}, if any. If @var{overlay} does not record any value for
-that property, but it does have a @code{category} property which is a
-symbol, that symbol's @var{prop} property is used. Otherwise, the value
-is @code{nil}.
-@end defun
-
-@defun overlay-put overlay prop value
-This function sets the value of property @var{prop} recorded in
-@var{overlay} to @var{value}. It returns @var{value}.
-@end defun
-
- See also the function @code{get-char-property} which checks both
-overlay properties and text properties for a given character.
-@xref{Examining Properties}.
-
-@node Managing Overlays
-@subsection Managing Overlays
-
- This section describes the functions to create, delete and move
-overlays, and to examine their contents.
-
-@defun make-overlay start end &optional buffer
-This function creates and returns an overlay that belongs to
-@var{buffer} and ranges from @var{start} to @var{end}. Both @var{start}
-and @var{end} must specify buffer positions; they may be integers or
-markers. If @var{buffer} is omitted, the overlay is created in the
-current buffer.
-@end defun
-
-@defun overlay-start overlay
-This function returns the position at which @var{overlay} starts.
-@end defun
-
-@defun overlay-end overlay
-This function returns the position at which @var{overlay} ends.
-@end defun
-
-@defun overlay-buffer overlay
-This function returns the buffer that @var{overlay} belongs to.
-@end defun
-
-@defun delete-overlay overlay
-This function deletes @var{overlay}. The overlay continues to exist as
-a Lisp object, but ceases to be part of the buffer it belonged to, and
-ceases to have any effect on display.
-@end defun
-
-@defun move-overlay overlay start end &optional buffer
-This function moves @var{overlay} to @var{buffer}, and places its bounds
-at @var{start} and @var{end}. Both arguments @var{start} and @var{end}
-must specify buffer positions; they may be integers or markers. If
-@var{buffer} is omitted, the overlay stays in the same buffer.
-
-The return value is @var{overlay}.
-
-This is the only valid way to change the endpoints of an overlay. Do
-not try modifying the markers in the overlay by hand, as that fails to
-update other vital data structures and can cause some overlays to be
-``lost''.
-@end defun
-
-@defun overlays-at pos
-This function returns a list of all the overlays that contain position
-@var{pos} in the current buffer. The list is in no particular order.
-An overlay contains position @var{pos} if it begins at or before
-@var{pos}, and ends after @var{pos}.
-@end defun
-
-@defun next-overlay-change pos
-This function returns the buffer position of the next beginning or end
-of an overlay, after @var{pos}.
-@end defun
-
-@defun previous-overlay-change pos
-This function returns the buffer position of the previous beginning or
-end of an overlay, before @var{pos}.
-@end defun
-
-@node Faces
-@section Faces
-@cindex face
-
-A @dfn{face} is a named collection of graphical attributes: font,
-foreground color, background color and optional underlining. Faces
-control the display of text on the screen.
-
-@cindex face id
-Each face has its own @dfn{face id number} which distinguishes faces at
-low levels within Emacs. However, for most purposes, you can refer to
-faces in Lisp programs by their names.
-
-@defun facep object
-This function returns @code{t} if @var{object} is a face name symbol (or
-if it is a vector of the kind used internally to record face data). It
-returns @code{nil} otherwise.
-@end defun
-
-Each face name is meaningful for all frames, and by default it has the
-same meaning in all frames. But you can arrange to give a particular
-face name a special meaning in one frame if you wish.
-
-@menu
-* Standard Faces:: The faces Emacs normally comes with.
-* Merging Faces:: How Emacs decides which face to use for a character.
-* Face Functions:: How to define and examine faces.
-@end menu
-
-@node Standard Faces
-@subsection Standard Faces
-
- This table lists all the standard faces and their uses.
-
-@table @code
-@item default
-@kindex default @r{(face name)}
-This face is used for ordinary text.
-
-@item modeline
-@kindex modeline @r{(face name)}
-This face is used for mode lines and menu bars.
-
-@item region
-@kindex region @r{(face name)}
-This face is used for highlighting the region in Transient Mark mode.
-
-@item secondary-selection
-@kindex secondary-selection @r{(face name)}
-This face is used to show any secondary selection you have made.
-
-@item highlight
-@kindex highlight @r{(face name)}
-This face is meant to be used for highlighting for various purposes.
-
-@item underline
-@kindex underline @r{(face name)}
-This face underlines text.
-
-@item bold
-@kindex bold @r{(face name)}
-This face uses a bold font, if possible. It uses the bold variant of
-the frame's font, if it has one. It's up to you to choose a default
-font that has a bold variant, if you want to use one.
-
-@item italic
-@kindex italic @r{(face name)}
-This face uses the italic variant of the frame's font, if it has one.
-
-@item bold-italic
-@kindex bold-italic @r{(face name)}
-This face uses the bold italic variant of the frame's font, if it has
-one.
-@end table
-
-@node Merging Faces
-@subsection Merging Faces for Display
-
- Here are all the ways to specify which face to use for display of text:
-
-@itemize @bullet
-@item
-With defaults. Each frame has a @dfn{default face}, whose id number is
-zero, which is used for all text that doesn't somehow specify another
-face.
-
-@item
-With text properties. A character may have a @code{face} property; if so,
-it is displayed with that face. @xref{Special Properties}.
-
-If the character has a @code{mouse-face} property, that is used instead
-of the @code{face} property when the mouse is ``near enough'' to the
-character.
-
-@item
-With overlays. An overlay may have @code{face} and @code{mouse-face}
-properties too; they apply to all the text covered by the overlay.
-
-@item
-With a region that is active. In Transient Mark mode, the region is
-highlighted with a particular face (see @code{region-face}, below).
-
-@item
-With special glyphs. Each glyph can specify a particular face id
-number. @xref{Glyphs}.
-@end itemize
-
- If these various sources together specify more than one face for a
-particular character, Emacs merges the attributes of the various faces
-specified. The attributes of the faces of special glyphs come first;
-then comes the face for region highlighting, if appropriate;
-then come attributes of faces from overlays, followed by those from text
-properties, and last the default face.
-
- When multiple overlays cover one character, an overlay with higher
-priority overrides those with lower priority. @xref{Overlays}.
-
- If an attribute such as the font or a color is not specified in any of
-the above ways, the frame's own font or color is used.
-
-@node Face Functions
-@subsection Functions for Working with Faces
-
- The attributes a face can specify include the font, the foreground
-color, the background color, and underlining. The face can also leave
-these unspecified by giving the value @code{nil} for them.
-
- Here are the primitives for creating and changing faces.
-
-@defun make-face name
-This function defines a new face named @var{name}, initially with all
-attributes @code{nil}. It does nothing if there is already a face named
-@var{name}.
-@end defun
-
-@defun face-list
-This function returns a list of all defined face names.
-@end defun
-
-@defun copy-face old-face new-name &optional frame new-frame
-This function defines the face @var{new-name} as a copy of the existing
-face named @var{old-face}. It creates the face @var{new-name} if that
-doesn't already exist.
-
-If the optional argument @var{frame} is given, this function applies
-only to that frame. Otherwise it applies to each frame individually,
-copying attributes from @var{old-face} in each frame to @var{new-face}
-in the same frame.
-
-If the optional argument @var{new-frame} is given, then @code{copy-face}
-copies the attributes of @var{old-face} in @var{frame} to @var{new-name}
-in @var{new-frame}.
-@end defun
-
- You can modify the attributes of an existing face with the following
-functions. If you specify @var{frame}, they affect just that frame;
-otherwise, they affect all frames as well as the defaults that apply to
-new frames.
-
-@defun set-face-foreground face color &optional frame
-@defunx set-face-background face color &optional frame
-These functions set the foreground (or background, respectively) color
-of face @var{face} to @var{color}. The argument @var{color} should be a
-string, the name of a color.
-
-Certain shades of gray are implemented by stipple patterns on
-black-and-white screens.
-@end defun
-
-@defun set-face-stipple face pattern &optional frame
-This function sets the background stipple pattern of face @var{face} to
-@var{pattern}. The argument @var{pattern} should be the name of a
-stipple pattern defined by the X server, or @code{nil} meaning don't use
-stipple.
-
-Normally there is no need to pay attention to stipple patterns, because
-they are used automatically to handle certain shades of gray.
-@end defun
-
-@defun set-face-font face font &optional frame
-This function sets the font of face @var{face}. The argument @var{font}
-should be a string.
-@end defun
-
-@defun set-face-underline-p face underline-p &optional frame
-This function sets the underline attribute of face @var{face}.
-Non-@code{nil} means do underline; @code{nil} means don't.
-@end defun
-
-@defun invert-face face &optional frame
-Swap the foreground and background colors of face @var{face}. If the
-face doesn't specify both foreground and background, then its foreground
-and background are set to the default background and foreground,
-respectively.
-@end defun
-
- These functions examine the attributes of a face. If you don't
-specify @var{frame}, they refer to the default data for new frames.
-
-@defun face-foreground face &optional frame
-@defunx face-background face &optional frame
-These functions return the foreground color (or background color,
-respectively) of face @var{face}, as a string.
-@end defun
-
-@defun face-stipple face &optional frame
-This function returns the name of the background stipple pattern of face
-@var{face}, or @code{nil} if it doesn't have one.
-@end defun
-
-@defun face-font face &optional frame
-This function returns the name of the font of face @var{face}.
-@end defun
-
-@defun face-underline-p face &optional frame
-This function returns the underline attribute of face @var{face}.
-@end defun
-
-@defun face-id face
-This function returns the face id number of face @var{face}.
-@end defun
-
-@defun face-equal face1 face2 &optional frame
-This returns @code{t} if the faces @var{face1} and @var{face2} have the
-same attributes for display.
-@end defun
-
-@defun face-differs-from-default-p face &optional frame
-This returns @code{t} if the face @var{face} displays differently from
-the default face. A face is considered to be ``the same'' as the normal
-face if each attribute is either the same as that of the default face or
-@code{nil} (meaning to inherit from the default).
-@end defun
-
-@defvar region-face
-This variable's value specifies the face id to use to display characters
-in the region when it is active (in Transient Mark mode only). The face
-thus specified takes precedence over all faces that come from text
-properties and overlays, for characters in the region. @xref{The Mark},
-for more information about Transient Mark mode.
-
-Normally, the value is the id number of the face named @code{region}.
-@end defvar
-
-@node Blinking
-@section Blinking Parentheses
-@cindex parenthesis matching
-@cindex blinking
-@cindex balancing parentheses
-@cindex close parenthesis
-
- This section describes the mechanism by which Emacs shows a matching
-open parenthesis when the user inserts a close parenthesis.
-
-@vindex blink-paren-hook
-@defvar blink-paren-function
-The value of this variable should be a function (of no arguments) to
-be called whenever a character with close parenthesis syntax is inserted.
-The value of @code{blink-paren-function} may be @code{nil}, in which
-case nothing is done.
-
-@quotation
-@strong{Please note:} This variable was named @code{blink-paren-hook} in
-older Emacs versions, but since it is not called with the standard
-convention for hooks, it was renamed to @code{blink-paren-function} in
-version 19.
-@end quotation
-@end defvar
-
-@defvar blink-matching-paren
-If this variable is @code{nil}, then @code{blink-matching-open} does
-nothing.
-@end defvar
-
-@defvar blink-matching-paren-distance
-This variable specifies the maximum distance to scan for a matching
-parenthesis before giving up.
-@end defvar
-
-@defvar blink-matching-paren-delay
-This variable specifies the number of seconds for the cursor to remain
-at the matching parenthesis. A fraction of a second often gives
-good results, but the default is 1, which works on all systems.
-@end defvar
-
-@defun blink-matching-open
-This function is the default value of @code{blink-paren-function}. It
-assumes that point follows a character with close parenthesis syntax and
-moves the cursor momentarily to the matching opening character. If that
-character is not already on the screen, it displays the character's
-context in the echo area. To avoid long delays, this function does not
-search farther than @code{blink-matching-paren-distance} characters.
-
-Here is an example of calling this function explicitly.
-
-@smallexample
-@group
-(defun interactive-blink-matching-open ()
-@c Do not break this line! -- rms.
-@c The first line of a doc string
-@c must stand alone.
- "Indicate momentarily the start of sexp before point."
- (interactive)
-@end group
-@group
- (let ((blink-matching-paren-distance
- (buffer-size))
- (blink-matching-paren t))
- (blink-matching-open)))
-@end group
-@end smallexample
-@end defun
-
-@node Inverse Video
-@section Inverse Video
-@cindex Inverse Video
-
-@defopt inverse-video
-@cindex highlighting
-This variable controls whether Emacs uses inverse video for all text
-on the screen. Non-@code{nil} means yes, @code{nil} means no. The
-default is @code{nil}.
-@end defopt
-
-@defopt mode-line-inverse-video
-This variable controls the use of inverse video for mode lines. If it
-is non-@code{nil}, then mode lines are displayed in inverse video.
-Otherwise, mode lines are displayed normally, just like text. The
-default is @code{t}.
-
-For X window frames, this displays mode lines using the face named
-@code{modeline}, which is normally the inverse of the default face
-unless you change it.
-@end defopt
-
-@node Usual Display
-@section Usual Display Conventions
-
- The usual display conventions define how to display each character
-code. You can override these conventions by setting up a display table
-(@pxref{Display Tables}). Here are the usual display conventions:
-
-@itemize @bullet
-@item
-Character codes 32 through 126 map to glyph codes 32 through 126.
-Normally this means they display as themselves.
-
-@item
-Character code 9 is a horizontal tab. It displays as whitespace
-up to a position determined by @code{tab-width}.
-
-@item
-Character code 10 is a newline.
-
-@item
-All other codes in the range 0 through 31, and code 127, display in one
-of two ways according to the value of @code{ctl-arrow}. If it is
-non-@code{nil}, these codes map to sequences of two glyphs, where the
-first glyph is the @sc{ASCII} code for @samp{^}. (A display table can
-specify a glyph to use instead of @samp{^}.) Otherwise, these codes map
-just like the codes in the range 128 to 255.
-
-@item
-Character codes 128 through 255 map to sequences of four glyphs, where
-the first glyph is the @sc{ASCII} code for @samp{\}, and the others are
-digit characters representing the code in octal. (A display table can
-specify a glyph to use instead of @samp{\}.)
-@end itemize
-
- The usual display conventions apply even when there is a display
-table, for any character whose entry in the active display table is
-@code{nil}. Thus, when you set up a display table, you need only
-specify the characters for which you want unusual behavior.
-
- These variables affect the way certain characters are displayed on the
-screen. Since they change the number of columns the characters occupy,
-they also affect the indentation functions.
-
-@defopt ctl-arrow
-@cindex control characters in display
-This buffer-local variable controls how control characters are
-displayed. If it is non-@code{nil}, they are displayed as a caret
-followed by the character: @samp{^A}. If it is @code{nil}, they are
-displayed as a backslash followed by three octal digits: @samp{\001}.
-@end defopt
-
-@c Following may have overfull hbox.
-@defvar default-ctl-arrow
-The value of this variable is the default value for @code{ctl-arrow} in
-buffers that do not override it. @xref{Default Value}.
-@end defvar
-
-@defopt tab-width
-The value of this variable is the spacing between tab stops used for
-displaying tab characters in Emacs buffers. The default is 8. Note
-that this feature is completely independent from the user-settable tab
-stops used by the command @code{tab-to-tab-stop}. @xref{Indent Tabs}.
-@end defopt
-
-@node Display Tables
-@section Display Tables
-
-@cindex display table
-You can use the @dfn{display table} feature to control how all 256
-possible character codes display on the screen. This is useful for
-displaying European languages that have letters not in the @sc{ASCII}
-character set.
-
-The display table maps each character code into a sequence of
-@dfn{glyphs}, each glyph being an image that takes up one character
-position on the screen. You can also define how to display each glyph
-on your terminal, using the @dfn{glyph table}.
-
-@menu
-* Display Table Format:: What a display table consists of.
-* Active Display Table:: How Emacs selects a display table to use.
-* Glyphs:: How to define a glyph, and what glyphs mean.
-* ISO Latin 1:: How to use display tables
- to support the ISO Latin 1 character set.
-@end menu
-
-@node Display Table Format
-@subsection Display Table Format
-
- A display table is actually an array of 262 elements.
-
-@defun make-display-table
-This creates and returns a display table. The table initially has
-@code{nil} in all elements.
-@end defun
-
- The first 256 elements correspond to character codes; the @var{n}th
-element says how to display the character code @var{n}. The value
-should be @code{nil} or a vector of glyph values (@pxref{Glyphs}). If
-an element is @code{nil}, it says to display that character according to
-the usual display conventions (@pxref{Usual Display}).
-
- If you use the display table to change the display of newline
-characters, the whole buffer will be displayed as one long ``line.''
-
- The remaining six elements of a display table serve special purposes,
-and @code{nil} means use the default stated below.
-
-@table @asis
-@item 256
-The glyph for the end of a truncated screen line (the default for this
-is @samp{$}). @xref{Glyphs}.
-@item 257
-The glyph for the end of a continued line (the default is @samp{\}).
-@item 258
-The glyph for indicating a character displayed as an octal character
-code (the default is @samp{\}).
-@item 259
-The glyph for indicating a control character (the default is @samp{^}).
-@item 260
-A vector of glyphs for indicating the presence of invisible lines (the
-default is @samp{...}). @xref{Selective Display}.
-@item 261
-The glyph used to draw the border between side-by-side windows (the
-default is @samp{|}). @xref{Splitting Windows}.
-@end table
-
- For example, here is how to construct a display table that mimics the
-effect of setting @code{ctl-arrow} to a non-@code{nil} value:
-
-@example
-(setq disptab (make-display-table))
-(let ((i 0))
- (while (< i 32)
- (or (= i ?\t) (= i ?\n)
- (aset disptab i (vector ?^ (+ i 64))))
- (setq i (1+ i)))
- (aset disptab 127 (vector ?^ ??)))
-@end example
-
-@node Active Display Table
-@subsection Active Display Table
-@cindex active display table
-
- Each window can specify a display table, and so can each buffer. When
-a buffer @var{b} is displayed in window @var{w}, display uses the
-display table for window @var{w} if it has one; otherwise, the display
-table for buffer @var{b} if it has one; otherwise, the standard display
-table if any. The display table chosen is called the @dfn{active}
-display table.
-
-@defun window-display-table window
-This function returns @var{window}'s display table, or @code{nil}
-if @var{window} does not have an assigned display table.
-@end defun
-
-@defun set-window-display-table window table
-This function sets the display table of @var{window} to @var{table}.
-The argument @var{table} should be either a display table or
-@code{nil}.
-@end defun
-
-@defvar buffer-display-table
-This variable is automatically local in all buffers; its value in a
-particular buffer is the display table for that buffer, or @code{nil} if
-the buffer does not have an assigned display table.
-@end defvar
-
-@defvar standard-display-table
-This variable's value is the default display table, used whenever a
-window has no display table and neither does the buffer displayed in
-that window. This variable is @code{nil} by default.
-@end defvar
-
- If there is no display table to use for a particular window---that is,
-if the window has none, its buffer has none, and
-@code{standard-display-table} has none---then Emacs uses the usual
-display conventions for all character codes in that window. @xref{Usual
-Display}.
-
-@node Glyphs
-@subsection Glyphs
-
-@cindex glyph
- A @dfn{glyph} is a generalization of a character; it stands for an
-image that takes up a single character position on the screen. Glyphs
-are represented in Lisp as integers, just as characters are.
-
-@cindex glyph table
- The meaning of each integer, as a glyph, is defined by the glyph
-table, which is the value of the variable @code{glyph-table}.
-
-@defvar glyph-table
-The value of this variable is the current glyph table. It should be a
-vector; the @var{g}th element defines glyph code @var{g}. If the value
-is @code{nil} instead of a vector, then all glyphs are simple (see
-below).
-@end defvar
-
- Here are the possible types of elements in the glyph table:
-
-@table @var
-@item string
-Send the characters in @var{string} to the terminal to output
-this glyph. This alternative is available on character terminals,
-but not under X.
-
-@item integer
-Define this glyph code as an alias for code @var{integer}. You can use
-an alias to specify a face code for the glyph; see below.
-
-@item @code{nil}
-This glyph is simple. On an ordinary terminal, the glyph code mod 256
-is the character to output. With X, the glyph code mod 256 is the
-character to output, and the glyph code divided by 256 specifies the
-@dfn{face id number} to use while outputting it. @xref{Faces}.
-@end table
-
- If a glyph code is greater than or equal to the length of the glyph
-table, that code is automatically simple.
-
-@node ISO Latin 1
-@subsection ISO Latin 1
-
-If you have a terminal that can handle the entire ISO Latin 1 character
-set, you can arrange to use that character set as follows:
-
-@example
-(require 'disp-table)
-;; @r{Set char codes 160--255 to display as themselves.}
-;; @r{(Codes 128--159 are the additional control characters.)}
-(standard-display-8bit 160 255)
-@end example
-
-If you are editing buffers written in the ISO Latin 1 character set and
-your terminal doesn't handle anything but @sc{ASCII}, you can load the
-file @file{iso-ascii} to set up a display table that displays the other
-ISO characters as explanatory sequences of @sc{ASCII} characters. For
-example, the character ``o with umlaut'' displays as @samp{@{"o@}}.
-
-Some European countries have terminals that don't support ISO Latin 1
-but do support the special characters for that country's language. You
-can define a display table to work one language using such terminals.
-For an example, see @file{lisp/iso-swed.el}, which handles certain
-Swedish terminals.
-
-You can load the appropriate display table for your terminal
-automatically by writing a terminal-specific Lisp file for the terminal
-type.
-
-@node Beeping
-@section Beeping
-@cindex beeping
-@cindex bell
-
- You can make Emacs ring a bell (or blink the screen) to attract the
-user's attention. Be conservative about how often you do this; frequent
-bells can become irritating. Also be careful not to use beeping alone
-when signaling an error is appropriate. (@xref{Errors}.)
-
-@defun ding &optional dont-terminate
-@cindex keyboard macro termination
-This function beeps, or flashes the screen (see @code{visible-bell} below).
-It also terminates any keyboard macro currently executing unless
-@var{dont-terminate} is non-@code{nil}.
-@end defun
-
-@defun beep &optional dont-terminate
-This is a synonym for @code{ding}.
-@end defun
-
-@defvar visible-bell
-This variable determines whether Emacs should flash the screen to
-represent a bell. Non-@code{nil} means yes, @code{nil} means no. This
-is effective under X windows, and on a character-only terminal provided
-the terminal's Termcap entry defines the visible bell capability
-(@samp{vb}).
-@end defvar
-
-@node Window Systems
-@section Window Systems
-
- Emacs works with several window systems, most notably the X Window
-System. Both Emacs and X use the term ``window'', but use it
-differently. An Emacs frame is a single window as far as X is
-concerned; the individual Emacs windows are not known to X at all.
-
-@defvar window-system
-@cindex X Window System
-This variable tells Lisp programs what window system Emacs is running
-under. Its value should be a symbol such as @code{x} (if Emacs is
-running under X) or @code{nil} (if Emacs is running on an ordinary
-terminal).
-@end defvar
-
-@defvar window-setup-hook
-This variable is a normal hook which Emacs runs after loading your
-@file{.emacs} file and the default initialization file (if any), after
-loading terminal-specific Lisp code, and after running the hook
-@code{term-setup-hook}.
-
-This hook is used for internal purposes: setting up communication with
-the window system, and creating the initial window. Users should not
-interfere with it.
-@end defvar
diff --git a/lispref/edebug.texi b/lispref/edebug.texi
deleted file mode 100644
index 0f95fa9fb0c..00000000000
--- a/lispref/edebug.texi
+++ /dev/null
@@ -1,1545 +0,0 @@
-@comment -*-texinfo-*-
-
-@c This file is intended to be used as a section within the Emacs Lisp
-@c Reference Manual. It may also be used by an independent Edebug User
-@c Manual, edebug.tex, in which case the Edebug node below should be used
-@c with the following links to the Bugs section and to the top level:
-
-@c , Bugs and Todo List, Top, Top
-
-@node Edebug,, Compilation Errors, Debugging
-@section Edebug
-@cindex Edebug mode
-
-@cindex Edebug
- Edebug is a source-level debugger for Emacs Lisp programs with which
-you can:
-
-@itemize @bullet
-@item
-Step through evaluation, stopping before and after each expression.
-
-@item
-Set conditional or unconditional breakpoints.
-
-@item
-Stop when a specified condition is true (the global break event).
-
-@item
-Trace slow or fast, stopping briefly at each stop point, or
-at each breakpoint.
-
-@item
-Display expression results and evaluate expressions as if outside of
-Edebug.
-
-@item
-Automatically reevaluate a list of expressions and
-display their results each time Edebug updates the display.
-
-@item
-Output trace info on function enter and exit.
-
-@item
-Stop when an error occurs.
-
-@item
-Display a backtrace, omitting Edebug's own frames.
-
-@item
-Specify argument evaluation for macros and defining forms.
-
-@item
-Obtain rudimentary coverage testing and frequency counts.
-@end itemize
-
-The first three sections below should tell you enough about Edebug to
-enable you to use it.
-
-@menu
-* Using Edebug:: Introduction to use of Edebug.
-* Instrumenting:: You must instrument your code
- in order to debug it with Edebug.
-* Modes: Edebug Execution Modes. Execution modes, stopping more or less often.
-* Jumping:: Commands to jump to a specified place.
-* Misc: Edebug Misc. Miscellaneous commands.
-* Breakpoints:: Setting breakpoints to make the program stop.
-* Trapping Errors:: trapping errors with Edebug.
-* Views: Edebug Views. Views inside and outside of Edebug.
-* Eval: Edebug Eval. Evaluating expressions within Edebug.
-* Eval List:: Expressions whose values are displayed
- each time you enter Edebug.
-* Printing in Edebug:: Customization of printing.
-* Trace Buffer:: How to produce trace output in a buffer.
-* Coverage Testing:: How to test evaluation coverage.
-* The Outside Context:: Data that Edebug saves and restores.
-* Instrumenting Macro Calls:: Specifying how to handle macro calls.
-* Options: Edebug Options. Option variables for customizing Edebug.
-@end menu
-
-@node Using Edebug
-@subsection Using Edebug
-
- To debug a Lisp program with Edebug, you must first @dfn{instrument}
-the Lisp code that you want to debug. A simple way to do this is to
-first move point into the definition of a function or macro and then do
-@kbd{C-u C-M-x} (@code{eval-defun} with a prefix argument). See
-@ref{Instrumenting}, for alternative ways to instrument code.
-
- Once a function is instrumented, any call to the function activates
-Edebug. Activating Edebug may stop execution and let you step through
-the function, or it may update the display and continue execution while
-checking for debugging commands, depending on which Edebug execution
-mode you have selected. The default execution mode is step, which does
-stop execution. @xref{Edebug Execution Modes}.
-
- Within Edebug, you normally view an Emacs buffer showing the source of
-the Lisp code you are debugging. This is referred to as the @dfn{source
-code buffer}. This buffer is temporarily read-only.
-
- An arrow at the left margin indicates the line where the function is
-executing. Point initially shows where within the line the function is
-executing, but this ceases to be true if you move point yourself.
-
- If you instrument the definition of @code{fac} (shown below) and then
-execute @code{(fac 3)}, here is what you normally see. Point is at the
-open-parenthesis before @code{if}.
-
-@example
-(defun fac (n)
-=>@point{}(if (< 0 n)
- (* n (fac (1- n)))
- 1))
-@end example
-
-@cindex stop points
-The places within a function where Edebug can stop execution are called
-@dfn{stop points}. These occur both before and after each subexpression
-that is a list, and also after each variable reference.
-Here we show with periods the stop points found in the function
-@code{fac}:
-
-@example
-(defun fac (n)
- .(if .(< 0 n.).
- .(* n. .(fac (1- n.).).).
- 1).)
-@end example
-
-The special commands of Edebug are available in the source code buffer
-in addition to the commands of Emacs Lisp mode. For example, you can
-type the Edebug command @key{SPC} to execute until the next stop point.
-If you type @key{SPC} once after entry to @code{fac}, here is the
-display you will see:
-
-@example
-(defun fac (n)
-=>(if @point{}(< 0 n)
- (* n (fac (1- n)))
- 1))
-@end example
-
-When Edebug stops execution after an expression, it displays the
-expression's value in the echo area.
-
-Other frequently used commands are @kbd{b} to set a breakpoint at a stop
-point, @kbd{g} to execute until a breakpoint is reached, and @kbd{q} to
-exit Edebug and return to the top-level command loop. Type @kbd{?} to
-display a list of all Edebug commands.
-
-@node Instrumenting
-@subsection Instrumenting for Edebug
-
- In order to use Edebug to debug Lisp code, you must first
-@dfn{instrument} the code. Instrumenting code inserts additional code
-into it, to invoke Edebug at the proper places.
-
-@kindex C-M-x
-@findex eval-defun (Edebug)
- Once you have loaded Edebug, the command @kbd{C-M-x}
-(@code{eval-defun}) is redefined so that when invoked with a prefix
-argument on a definition, it instruments the definition before
-evaluating it. (The source code itself is not modified.) If the
-variable @code{edebug-all-defs} is non-@code{nil}, that inverts the
-meaning of the prefix argument: then @kbd{C-M-x} instruments the
-definition @emph{unless} it has a prefix argument. The default value of
-@code{edebug-all-defs} is @code{nil}. The command @kbd{M-x
-edebug-all-defs} toggles the value of the variable
-@code{edebug-all-defs}.
-
-@findex edebug-all-forms
-@findex eval-region (Edebug)
-@findex eval-current-buffer (Edebug)
- If @code{edebug-all-defs} is non-@code{nil}, then the commands
-@code{eval-region}, @code{eval-current-buffer}, and @code{eval-buffer}
-also instrument any definitions they evaluate. Similarly,
-@code{edebug-all-forms} controls whether @code{eval-region} should
-instrument @emph{any} form, even non-defining forms. This doesn't apply
-to loading or evaluations in the minibuffer. The command @kbd{M-x
-edebug-all-forms} toggles this option.
-
-@findex edebug-eval-top-level-form
-Another command, @kbd{M-x edebug-eval-top-level-form}, is available to
-instrument any top-level form regardless of the value of
-@code{edebug-all-defs} or @code{edebug-all-forms}.
-
-When Edebug is about to instrument code for the first time in a session,
-it runs the hook @code{edebug-setup-hook}, then sets it to @code{nil}.
-You can use this to load up Edebug specifications associated with a
-package you are using, but only when you also use Edebug.
-
-While Edebug is active, the command @kbd{I}
-(@code{edebug-instrument-callee}) instruments the definition of the
-function or macro called by the list form after point, if is not already
-instrumented. This is possible only if Edebug knows where to find the
-source for that function; after loading Edebug, @code{eval-region}
-records the position of every definition it evaluates, even if not
-instrumenting it. See also the @kbd{i} command (@pxref{Jumping}), which
-steps into the call after instrumenting the function.
-
-@cindex special forms (Edebug)
-@cindex interactive commands (Edebug)
-@cindex anonymous lambda expressions (Edebug)
-@cindex Common Lisp (Edebug)
-@pindex cl.el (Edebug)
-@pindex cl-specs.el
- Edebug knows how to instrument all the standard special forms, an
-interactive form with an expression argument, anonymous lambda
-expressions, and other defining forms. Edebug cannot know what a
-user-defined macro will do with the arguments of a macro call, so you
-must tell it; @xref{Instrumenting Macro Calls}, for details.
-
-@findex eval-expression (Edebug)
- To remove instrumentation from a definition, simply reevaluate its
-definition in a way that does not instrument. There are two ways of
-evaluating forms that never instrument them: from a file with
-@code{load}, and from the minibuffer with @code{eval-expression}
-(@kbd{M-:}).
-
- If Edebug detects a syntax error while instrumenting, it leaves point
-at the erroneous code and signals an @code{invalid-read-syntax} error.
-
- @xref{Edebug Eval}, for other evaluation functions available
-inside of Edebug.
-
-@node Edebug Execution Modes
-@subsection Edebug Execution Modes
-
-@cindex Edebug execution modes
-Edebug supports several execution modes for running the program you are
-debugging. We call these alternatives @dfn{Edebug execution modes}; do
-not confuse them with major or minor modes. The current Edebug execution mode
-determines how far Edebug continues execution before stopping---whether
-it stops at each stop point, or continues to the next breakpoint, for
-example---and how much Edebug displays the progress of the evaluation
-before it stops.
-
-Normally, you specify the Edebug execution mode by typing a command to
-continue the program in a certain mode. Here is a table of these
-commands. All except for @kbd{S} resume execution of the program, at
-least for a certain distance.
-
-@table @kbd
-@item S
-Stop: don't execute any more of the program for now, just wait for more
-Edebug commands (@code{edebug-stop}).
-
-@item @key{SPC}
-Step: stop at the next stop point encountered (@code{edebug-step-mode}).
-
-@item n
-Next: stop at the next stop point encountered after an expression
-(@code{edebug-next-mode}). Also see @code{edebug-forward-sexp} in
-@ref{Edebug Misc}.
-
-@item t
-Trace: pause one second at each Edebug stop point (@code{edebug-trace-mode}).
-
-@item T
-Rapid trace: update the display at each stop point, but don't actually
-pause (@code{edebug-Trace-fast-mode}).
-
-@item g
-Go: run until the next breakpoint (@code{edebug-go-mode}). @xref{Breakpoints}.
-
-@item c
-Continue: pause one second at each breakpoint, and then continue
-(@code{edebug-continue-mode}).
-
-@item C
-Rapid continue: move point to each breakpoint, but don't pause
-(@code{edebug-Continue-fast-mode}).
-
-@item G
-Go non-stop: ignore breakpoints (@code{edebug-Go-nonstop-mode}). You
-can still stop the program by typing @kbd{S}, or any editing command.
-@end table
-
-In general, the execution modes earlier in the above list run the
-program more slowly or stop sooner than the modes later in the list.
-
-While executing or tracing, you can interrupt the execution by typing
-any Edebug command. Edebug stops the program at the next stop point and
-then executes the command you typed. For example, typing @kbd{t} during
-execution switches to trace mode at the next stop point. You can use
-@kbd{S} to stop execution without doing anything else.
-
-If your function happens to read input, a character you type intending
-to interrupt execution may be read by the function instead. You can
-avoid such unintended results by paying attention to when your program
-wants input.
-
-@cindex keyboard macros (Edebug)
-Keyboard macros containing the commands in this section do not
-completely work: exiting from Edebug, to resume the program, loses track
-of the keyboard macro. This is not easy to fix. Also, defining or
-executing a keyboard macro outside of Edebug does not affect commands
-inside Edebug. This is usually an advantage. But see the
-@code{edebug-continue-kbd-macro} option (@pxref{Edebug Options}).
-
-When you enter a new Edebug level, the initial execution mode comes from
-the value of the variable @code{edebug-initial-mode}. By default, this
-specifies step mode. Note that you may reenter the same Edebug level
-several times if, for example, an instrumented function is called
-several times from one command.
-
-
-@node Jumping
-@subsection Jumping
-
- The commands described in this section execute until they reach a
-specified location. All except @kbd{i} make a temporary breakpoint to
-establish the place to stop, then switch to go mode. Any other
-breakpoint reached before the intended stop point will also stop
-execution. @xref{Breakpoints}, for the details on breakpoints.
-
- These commands may fail to work as expected in case of nonlocal exit,
-because a nonlocal exit can bypass the temporary breakpoint where you
-expected the program to stop.
-
-@table @kbd
-@item h
-Proceed to the stop point near where point is (@code{edebug-goto-here}).
-
-@item f
-Run the program forward over one expression
-(@code{edebug-forward-sexp}).
-
-@item o
-Run the program until the end of the containing sexp.
-
-@item i
-Step into the function or macro called by the form after point.
-@end table
-
-The @kbd{h} command proceeds to the stop point near the current location
-if point, using a temporary breakpoint. See @ref{Breakpoints}, for more
-about breakpoints.
-
-The @kbd{f} command runs the program forward over one expression. More
-precisely, it sets a temporary breakpoint at the position that
-@kbd{C-M-f} would reach, then executes in go mode so that the program
-will stop at breakpoints.
-
-With a prefix argument @var{n}, the temporary breakpoint is placed
-@var{n} sexps beyond point. If the containing list ends before @var{n}
-more elements, then the place to stop is after the containing
-expression.
-
-Be careful that the position @kbd{C-M-f} finds is a place that the
-program will really get to; this may not be true in a
-@code{cond}, for example.
-
-The @kbd{f} command does @code{forward-sexp} starting at point, rather
-than at the stop point, for flexibility. If you want to execute one
-expression @emph{from the current stop point}, type @kbd{w} first, to
-move point there, and then type @kbd{f}.
-
-The @kbd{o} command continues ``out of'' an expression. It places a
-temporary breakpoint at the end of the sexp containing point. If the
-containing sexp is a function definition itself, @kbd{o} continues until
-just before the last sexp in the definition. If that is where you are
-now, it returns from the function and then stops. In other words, this
-command does not exit the currently executing function unless you are
-positioned after the last sexp.
-
-The @kbd{i} command steps into the function or macro called by the list
-form after point, and stops at its first stop point. Note that the form
-need not be the one about to be evaluated. But if the form is a
-function call about to be evaluated, remember to use this command before
-any of the arguments are evaluated, since otherwise it will be too late.
-
-The @kbd{i} command instruments the function or macro it's supposed to
-step into, if it isn't instrumented already. This is convenient, but keep
-in mind that the function or macro remains instrumented unless you explicitly
-arrange to deinstrument it.
-
-@node Edebug Misc
-@subsection Miscellaneous Edebug Commands
-
- Some miscellaneous Edebug commands are described here.
-
-@table @kbd
-@item ?
-Display the help message for Edebug (@code{edebug-help}).
-
-@item C-]
-Abort one level back to the previous command level
-(@code{abort-recursive-edit}).
-
-@item q
-Return to the top level editor command loop (@code{top-level}). This
-exits all recursive editing levels, including all levels of Edebug
-activity. However, instrumented code protected with
-@code{unwind-protect} or @code{condition-case} forms may resume
-debugging.
-
-@item Q
-Like @kbd{q} but don't stop even for protected code
-(@code{top-level-nonstop}).
-
-@item r
-Redisplay the most recently known expression result in the echo area
-(@code{edebug-previous-result}).
-
-@item d
-Display a backtrace, excluding Edebug's own functions for clarity
-(@code{edebug-backtrace}).
-
-You cannot use debugger commands in the backtrace buffer in Edebug as
-you would in the standard debugger.
-
-The backtrace buffer is killed automatically when you continue
-execution.
-@end table
-
-From the Edebug recursive edit, you may invoke commands that activate
-Edebug again recursively. Any time Edebug is active, you can quit to
-the top level with @kbd{q} or abort one recursive edit level with
-@kbd{C-]}. You can display a backtrace of all the
-pending evaluations with @kbd{d}.
-
-@node Breakpoints
-@subsection Breakpoints
-
-@cindex breakpoints
-Edebug's step mode stops execution at the next stop point reached.
-There are three other ways to stop Edebug execution once it has started:
-breakpoints, the global break condition, and source breakpoints.
-
-While using Edebug, you can specify @dfn{breakpoints} in the program you
-are testing: points where execution should stop. You can set a
-breakpoint at any stop point, as defined in @ref{Using Edebug}. For
-setting and unsetting breakpoints, the stop point that is affected is
-the first one at or after point in the source code buffer. Here are the
-Edebug commands for breakpoints:
-
-@table @kbd
-@item b
-Set a breakpoint at the stop point at or after point
-(@code{edebug-set-breakpoint}). If you use a prefix argument, the
-breakpoint is temporary (it turns off the first time it stops the
-program).
-
-@item u
-Unset the breakpoint (if any) at the stop point at or after
-point (@code{edebug-unset-breakpoint}).
-
-@item x @var{condition} @key{RET}
-Set a conditional breakpoint which stops the program only if
-@var{condition} evaluates to a non-@code{nil} value
-(@code{edebug-set-conditional-breakpoint}). With a prefix argument, the
-breakpoint is temporary.
-
-@item B
-Move point to the next breakpoint in the current definition
-(@code{edebug-next-breakpoint}).
-@end table
-
-While in Edebug, you can set a breakpoint with @kbd{b} and unset one
-with @kbd{u}. First move point to the Edebug stop point of your choice,
-then type @kbd{b} or @kbd{u} to set or unset a breakpoint there.
-Unsetting a breakpoint where none has been set has no effect.
-
-Reevaluating or reinstrumenting a definition forgets all its breakpoints.
-
-A @dfn{conditional breakpoint} tests a condition each time the program
-gets there. Any errors that occur as a result of evaluating the
-condition are ignored, as if the result were @code{nil}. To set a
-conditional breakpoint, use @kbd{x}, and specify the condition
-expression in the minibuffer. Setting a conditional breakpoint at a
-stop point that has a previously established conditional breakpoint puts
-the previous condition expression in the minibuffer so you can edit it.
-
-You can make a conditional or unconditional breakpoint
-@dfn{temporary} by using a prefix arg with the command to set the
-breakpoint. When a temporary breakpoint stops the program, it is
-automatically unset.
-
-Edebug always stops or pauses at a breakpoint except when the Edebug
-mode is Go-nonstop. In that mode, it ignores breakpoints entirely.
-
-To find out where your breakpoints are, use the @kbd{B} command, which
-moves point to the next breakpoint following point, within the same
-function, or to the first breakpoint if there are no following
-breakpoints. This command does not continue execution---it just moves
-point in the buffer.
-
-@menu
-* Global Break Condition:: Breaking on an event.
-* Source Breakpoints:: Embedding breakpoints in source code.
-@end menu
-
-
-@node Global Break Condition
-@subsubsection Global Break Condition
-
-@cindex stopping on events
-@cindex global break condition
- A @dfn{global break condition} stops execution when a specified
-condition is satisfied, no matter where that may occur. Edebug
-evaluates the global break condition at every stop point. If it
-evaluates to a non-@code{nil} value, then execution stops or pauses
-depending on the execution mode, as if a breakpoint had been hit. If
-evaluating the condition gets an error, execution does not stop.
-
-@findex edebug-set-global-break-condition
-@vindex edebug-global-break-condition
- The condition expression is stored in
-@code{edebug-global-break-condition}. You can specify a new expression
-using the @kbd{X} command (@code{edebug-set-global-break-condition}).
-
- The global break condition is the simplest way to find where in your
-code some event occurs, but it makes code run much more slowly. So you
-should reset the condition to @code{nil} when not using it.
-
-@node Source Breakpoints
-@subsubsection Source Breakpoints
-
-@findex edebug
-@cindex source breakpoints
- All breakpoints in a definition are forgotten each time you
-reinstrument it. To make a breakpoint that won't be forgotten, you can
-write a @dfn{source breakpoint}, which is simply a call to the function
-@code{edebug} in your source code. You can, of course, make such a call
-conditional. For example, in the @code{fac} function, insert the first
-line as shown below to stop when the argument reaches zero:
-
-@example
-(defun fac (n)
- (if (= n 0) (edebug))
- (if (< 0 n)
- (* n (fac (1- n)))
- 1))
-@end example
-
-When the @code{fac} definition is instrumented and the function is
-called, the call to @code{edebug} acts as a breakpoint. Depending on
-the execution mode, Edebug stops or pauses there.
-
-If no instrumented code is being executed when @code{edebug} is called,
-that function calls @code{debug}.
-@c This may not be a good idea anymore.
-
-@node Trapping Errors
-@subsection Trapping Errors
-
-Emacs normally displays an error message when an error is signaled and
-not handled with @code{condition-case}. While Edebug is active, it
-normally responds to all unhandled errors. You can customize this with
-the options @code{edebug-on-error} and @code{edebug-on-quit}; see
-@ref{Edebug Options}.
-
-When Edebug responds to an error, it shows the last stop point
-encountered before the error. This may be the location of a call to a
-function which was not instrumented, within which the error actually
-occurred. For an unbound variable error, the last known stop point
-might be quite distant from the offending variable reference. In that
-case you might want to display a full backtrace (@pxref{Edebug Misc}).
-
-@c Edebug should be changed for the following: -- dan
-If you change @code{debug-on-error} or @code{debug-on-quit} while
-Edebug is active, these changes will be forgotten when Edebug becomes
-inactive. Furthermore, during Edebug's recursive edit, these variables
-are bound to the values they had outside of Edebug.
-
-@node Edebug Views
-@subsection Edebug Views
-
-These Edebug commands let you view aspects of the buffer and window
-status that obtained before entry to Edebug. The outside window
-configuration is the collection of windows and contents that were in
-effect outside of Edebug.
-
-@table @kbd
-@item v
-Temporarily view the outside window configuration
-(@code{edebug-view-outside}).
-
-@item p
-Temporarily display the outside current buffer with point at its outside
-position (@code{edebug-bounce-point}). With a prefix argument @var{n},
-pause for @var{n} seconds instead.
-
-@item w
-Move point back to the current stop point (@code{edebug-where}) in the
-source code buffer. Also, if you use this command in a different window
-displaying the same buffer, that window will be used instead to display
-the current definition in the future.
-
-@item W
-@c Its function is not simply to forget the saved configuration -- dan
-Toggle whether Edebug saves and restores the outside window
-configuration (@code{edebug-toggle-save-windows}).
-
-With a prefix argument, @code{W} only toggles saving and restoring of
-the selected window. To specify a window that is not displaying the
-source code buffer, you must use @kbd{C-x X W} from the global keymap.
-@end table
-
-You can view the outside window configuration with @kbd{v} or just
-bounce to the point in the current buffer with @kbd{p}, even if
-it is not normally displayed. After moving point, you may wish to jump
-back to the stop point with @kbd{w} from a source code buffer.
-
-Each time you use @kbd{W} to turn saving @emph{off}, Edebug forgets the
-saved outside window configuration---so that even if you turn saving
-back @emph{on}, the current window configuration remains unchanged when
-you next exit Edebug (by continuing the program). However, the
-automatic redisplay of @samp{*edebug*} and @samp{*edebug-trace*} may
-conflict with the buffers you wish to see unless you have enough windows
-open.
-
-@node Edebug Eval
-@subsection Evaluation
-
-While within Edebug, you can evaluate expressions ``as if'' Edebug were
-not running. Edebug tries to be invisible to the expression's
-evaluation and printing. Evaluation of expressions that cause side
-effects will work as expected except for things that Edebug explicitly
-saves and restores. @xref{The Outside Context}, for details on this
-process.
-
-@table @kbd
-@item e @var{exp} @key{RET}
-Evaluate expression @var{exp} in the context outside of Edebug
-(@code{edebug-eval-expression}). That is, Edebug tries to minimize its
-interference with the evaluation.
-
-@item M-: @var{exp} @key{RET}
-Evaluate expression @var{exp} in the context of Edebug itself.
-
-@item C-x C-e
-Evaluate the expression before point, in the context outside of Edebug
-(@code{edebug-eval-last-sexp}).
-@end table
-
-@cindex lexical binding (Edebug)
-Edebug supports evaluation of expressions containing references to
-lexically bound symbols created by the following constructs in
-@file{cl.el} (version 2.03 or later): @code{lexical-let},
-@code{macrolet}, and @code{symbol-macrolet}.
-
-
-@node Eval List
-@subsection Evaluation List Buffer
-
-You can use the @dfn{evaluation list buffer}, called @samp{*edebug*}, to
-evaluate expressions interactively. You can also set up the
-@dfn{evaluation list} of expressions to be evaluated automatically each
-time Edebug updates the display.
-
-@table @kbd
-@item E
-Switch to the evaluation list buffer @samp{*edebug*}
-(@code{edebug-visit-eval-list}).
-@end table
-
-In the @samp{*edebug*} buffer you can use the commands of Lisp
-Interaction mode (@pxref{Lisp Interaction,,, emacs, The GNU Emacs
-Manual}) as well as these special commands:
-
-@table @kbd
-@item LFD
-Evaluate the expression before point, in the outside context, and insert
-the value in the buffer (@code{edebug-eval-print-last-sexp}).
-
-@item C-x C-e
-Evaluate the expression before point, in the context outside of Edebug
-(@code{edebug-eval-last-sexp}).
-
-@item C-c C-u
-Build a new evaluation list from the contents of the buffer
-(@code{edebug-update-eval-list}).
-
-@item C-c C-d
-Delete the evaluation list group that point is in
-(@code{edebug-delete-eval-item}).
-
-@item C-c C-w
-Switch back to the source code buffer at the current stop point
-(@code{edebug-where}).
-@end table
-
-You can evaluate expressions in the evaluation list window with
-@kbd{LFD} or @kbd{C-x C-e}, just as you would in @samp{*scratch*};
-but they are evaluated in the context outside of Edebug.
-
-The expressions you enter interactively (and their results) are lost
-when you continue execution; but you can set up an @dfn{evaluation list}
-consisting of expressions to be evaluated each time execution stops.
-
-@cindex evaluation list group
-To do this, write one or more @dfn{evaluation list groups} in the
-evaluation list buffer. An evaluation list group consists of one or
-more Lisp expressions. Groups are separated by comment lines.
-
-The command @kbd{C-c C-u} (@code{edebug-update-eval-list}) rebuilds the
-evaluation list, scanning the buffer and using the first expression of
-each group. (The idea is that the second expression of the group is the
-value previously computed and displayed.)
-
-Be careful not to add expressions that execute instrumented code since
-that would cause an infinite loop.
-@c There ought to be a way to fix this.
-
-Each entry to Edebug redisplays the evaluation list by inserting each
-expression in the buffer, followed by its current value. It also
-inserts comment lines so that each expression becomes its own group.
-Thus, if you type @kbd{C-c C-u} again without changing the buffer text,
-the evaluation list is effectively unchanged.
-
-If an error occurs during an evaluation from the evaluation list, the
-error message is displayed in a string as if it were the result.
-Therefore, expressions that use variables not currently valid do not
-interrupt your debugging.
-
-Here is an example of what the evaluation list window looks like after
-several expressions have been added to it:
-
-@smallexample
-(current-buffer)
-#<buffer *scratch*>
-;---------------------------------------------------------------
-(selected-window)
-#<window 16 on *scratch*>
-;---------------------------------------------------------------
-(point)
-196
-;---------------------------------------------------------------
-bad-var
-"Symbol's value as variable is void: bad-var"
-;---------------------------------------------------------------
-(recursion-depth)
-0
-;---------------------------------------------------------------
-this-command
-eval-last-sexp
-;---------------------------------------------------------------
-@end smallexample
-
-To delete a group, move point into it and type @kbd{C-c C-d}, or simply
-delete the text for the group and update the evaluation list with
-@kbd{C-c C-u}. To add a new expression to the evaluation list, insert
-the expression at a suitable place, and insert a new comment line. (You
-need not insert dashes in the comment line---its contents don't matter.)
-Then type @kbd{C-c C-u}.
-
-After selecting @samp{*edebug*}, you can return to the source code
-buffer with @kbd{C-c C-w}. The @samp{*edebug*} buffer is killed when
-you continue execution, and recreated next time it is needed.
-
-
-@node Printing in Edebug
-@subsection Printing in Edebug
-
-@cindex printing (Edebug)
-@cindex printing circular structures
-@pindex cust-print
- If an expression in your program produces a value containing circular
-list structure, you may get an error when Edebug attempts to print it.
-
-@vindex edebug-print-length
-@vindex edebug-print-level
- One way to cope with circular structure is to set @code{print-length}
-or @code{print-level} to truncate the printing. Edebug does this for
-you; it binds @code{print-length} and @code{print-level} to 50 if they
-were @code{nil}. (Actually, the variables @code{edebug-print-length}
-and @code{edebug-print-level} specify the values to use within Edebug.)
-@xref{Output Variables}.
-
- You can also print circular structures and structures that share
-elements more informatively by using the @file{cust-print} package.
-
- To load @file{cust-print} and activate custom printing only for
-Edebug, simply use the command @kbd{M-x edebug-install-custom-print}.
-To restore the standard print functions, use @kbd{M-x
-edebug-uninstall-custom-print}.
-
- Here is an example of code that creates a circular structure:
-
-@example
-(setq a '(x y))
-(setcar a a))
-@end example
-
-@noindent
-Custom printing prints this as @samp{Result: #1=(#1# y)}. The
-@samp{#1=} notation labels the structure that follows it with the label
-@samp{1}, and the @samp{#1#} notation references the previously labelled
-structure. This notation is used for any shared elements of lists or
-vectors.
-
- Other programs can also use custom printing; see @file{cust-print.el}
-for details.
-
-@node Trace Buffer
-@subsection Trace Buffer
-@cindex trace buffer
-
- Edebug can record an execution trace, storing it in a buffer named
-@samp{*edebug-trace*}. This is a log of function calls and returns,
-showing the function names and their arguments and values. To enable
-trace recording, set @code{edebug-trace} to a non-@code{nil} value.
-
- Making a trace buffer is not the same thing as using trace execution
-mode (@pxref{Edebug Execution Modes}).
-
- When trace recording is enabled, each function entry and exit adds
-lines to the trace buffer. A function entry record looks like
-@samp{::::@{} followed by the function name and argument values. A
-function exit record looks like @samp{::::@}} followed by the function
-name and result of the function.
-
- The number of @samp{:}s in an entry shows its recursion depth. You
-can use the braces in the trace buffer to find the matching beginning or
-end of function calls.
-
-@findex edebug-print-trace-before
-@findex edebug-print-trace-after
- You can customize trace recording for function entry and exit by
-redefining the functions @code{edebug-print-trace-before} and
-@code{edebug-print-trace-after}.
-
-@defmac edebug-tracing string body@dots{}
-This macro requests additional trace information around the execution
-of the @var{body} forms. The argument @var{string} specifies text
-to put in the trace buffer. All the arguments are evaluated.
-@code{edebug-tracing} returns the value of the last form in @var{body}.
-@end defmac
-
-@defun edebug-trace format-string &rest format-args
-This function inserts text in the trace buffer. It computes the text
-with @code{(apply 'format @var{format-string} @var{format-args})}.
-It also appends a newline to separate entries.
-@end defun
-
- @code{edebug-tracing} and @code{edebug-trace} insert lines in the trace
-buffer even if Edebug is not active.
-
- Adding text to the trace buffer also scrolls its window to show the
-last lines inserted.
-
-@node Coverage Testing
-@subsection Coverage Testing
-
-@cindex coverage testing
-@cindex frequency counts
-@cindex performance analysis
-Edebug provides rudimentary coverage testing and display of execution
-frequency. All execution of an instrumented function accumulates
-frequency counts, both before and after evaluation of each instrumented
-expression, even if the execution mode is Go-nonstop. Coverage testing
-is more expensive, so it is only done if @code{edebug-test-coverage} is
-non-@code{nil}. The command @kbd{M-x edebug-display-freq-count}
-displays both the frequency data and the coverage data (if recorded).
-
-@deffn Command edebug-display-freq-count
-This command displays the frequency count data for each line of the
-current definition.
-
-The frequency counts appear as comment lines after each line of code, and
-you can undo all insertions with one @code{undo} command. The counts
-appear under the @kbd{(} before an expression or the @kbd{)} after
-an expression, or on the last character of a symbol. Values do not appear if
-they are equal to the previous count on the same line.
-
-The character @samp{=} following the count for an expression says that
-the expression has returned the same value each time it was evaluated
-This is the only coverage information that Edebug records.
-
-To clear the frequency count and coverage data for a definition,
-reinstrument it.
-@end deffn
-
-For example, after evaluating @code{(fac 5)} with a source
-breakpoint, and setting @code{edebug-test-coverage} to @code{t}, when
-the breakpoint is reached, the frequency data looks like this:
-
-@example
-(defun fac (n)
- (if (= n 0) (edebug))
-;#6 1 0 =5
- (if (< 0 n)
-;#5 =
- (* n (fac (1- n)))
-;# 5 0
- 1))
-;# 0
-@end example
-
-The comment lines show that @code{fac} was called 6 times. The
-first @code{if} statement returned 5 times with the same result each
-time; the same is true of the condition on the second @code{if}.
-The recursive call of @code{fac} did not return at all.
-
-
-@node The Outside Context
-@subsection The Outside Context
-
-Edebug tries to be transparent to the program you are debugging, but it
-does not succeed completely. Edebug also tries to be transparent when
-you evaluate expressions with @kbd{e} or with the evaluation list
-buffer, by temporarily restoring the outside context. This section
-explains precisely what context Edebug restores, and how Edebug fails to
-be completely transparent.
-
-@menu
-* Checking Whether to Stop:: When Edebug decides what to do.
-* Edebug Display Update:: When Edebug updates the display.
-* Edebug Recursive Edit:: When Edebug stops execution.
-@end menu
-
-@node Checking Whether to Stop
-@subsubsection Checking Whether to Stop
-
-Whenever Edebug is entered, it needs to save and restore certain data
-before even deciding whether to make trace information or stop the
-program.
-
-@itemize @bullet
-@item
-@code{max-lisp-eval-depth} and @code{max-specpdl-size} are both
-incremented one time to reduce Edebug's impact on the stack.
-You could, however, still run out of stack space when using Edebug.
-
-@item
-The state of keyboard macro execution is saved and restored. While
-Edebug is active, @code{executing-macro} is bound to
-@code{edebug-continue-kbd-macro}.
-
-@end itemize
-
-
-@node Edebug Display Update
-@subsubsection Edebug Display Update
-
-@c This paragraph is not filled, because LaLiberte's conversion script
-@c needs an xref to be on just one line.
-When Edebug needs to display something (e.g., in trace mode), it saves
-the current window configuration from ``outside'' Edebug
-(@pxref{Window Configurations}). When you exit Edebug (by continuing
-the program), it restores the previous window configuration.
-
-Emacs redisplays only when it pauses. Usually, when you continue
-execution, the program comes back into Edebug at a breakpoint or after
-stepping without pausing or reading input in between. In such cases,
-Emacs never gets a chance to redisplay the ``outside'' configuration.
-What you see is the same window configuration as the last time Edebug
-was active, with no interruption.
-
-Entry to Edebug for displaying something also saves and restores the
-following data, but some of these are deliberately not restored if an
-error or quit signal occurs.
-
-@itemize @bullet
-@item
-@cindex current buffer point and mark (Edebug)
-Which buffer is current, and the positions of point and the mark in the
-current buffer, are saved and restored.
-
-@item
-@cindex window configuration (Edebug)
-The outside window configuration is saved and restored if
-@code{edebug-save-windows} is non-@code{nil} (@pxref{Edebug Display Update}).
-
-The window configuration is not restored on error or quit, but the
-outside selected window @emph{is} reselected even on error or quit in
-case a @code{save-excursion} is active. If the value of
-@code{edebug-save-windows} is a list, only the listed windows are saved
-and restored.
-
-The window start and horizontal scrolling of the source code buffer are
-not restored, however, so that the display remains coherent within Edebug.
-
-@item
-The value of point in each displayed buffer is saved and restored if
-@code{edebug-save-displayed-buffer-points} is non-@code{nil}.
-
-@item
-The variables @code{overlay-arrow-position} and
-@code{overlay-arrow-string} are saved and restored. So you can safely
-invoke Edebug from the recursive edit elsewhere in the same buffer.
-
-@item
-@code{cursor-in-echo-area} is locally bound to @code{nil} so that
-the cursor shows up in the window.
-@end itemize
-
-@node Edebug Recursive Edit
-@subsubsection Edebug Recursive Edit
-
-When Edebug is entered and actually reads commands from the user, it
-saves (and later restores) these additional data:
-
-@itemize @bullet
-@item
-The current match data. @xref{Match Data}.
-
-@item
-@code{last-command}, @code{this-command}, @code{last-command-char},
-@code{last-input-char}, @code{last-input-event},
-@code{last-command-event}, @code{last-event-frame},
-@code{last-nonmenu-event}, and @code{track-mouse}. Commands used within
-Edebug do not affect these variables outside of Edebug.
-
-The key sequence returned by @code{this-command-keys} is changed by
-executing commands within Edebug and there is no way to reset
-the key sequence from Lisp.
-
-Edebug cannot save and restore the value of
-@code{unread-command-events}. Entering Edebug while this variable has a
-nontrivial value can interfere with execution of the program you are
-debugging.
-
-@item
-Complex commands executed while in Edebug are added to the variable
-@code{command-history}. In rare cases this can alter execution.
-
-@item
-Within Edebug, the recursion depth appears one deeper than the recursion
-depth outside Edebug. This is not true of the automatically updated
-evaluation list window.
-
-@item
-@code{standard-output} and @code{standard-input} are bound to @code{nil}
-by the @code{recursive-edit}, but Edebug temporarily restores them during
-evaluations.
-
-@item
-The state of keyboard macro definition is saved and restored. While
-Edebug is active, @code{defining-kbd-macro} is bound to
-@code{edebug-continue-kbd-macro}.
-@end itemize
-
-@node Instrumenting Macro Calls
-@subsection Instrumenting Macro Calls
-
-When Edebug instruments an expression that calls a Lisp macro, it needs
-additional advice to do the job properly. This is because there is no
-way to tell which subexpressions of the macro call are forms to be
-evaluated. (Evaluation may occur explicitly in the macro body, or when
-the resulting expansion is evaluated, or any time later.) You must
-explain the format of calls to each macro to enable Edebug to handle it.
-To do this, use @code{def-edebug-spec} to define the format of
-calls to a given macro.
-
-@deffn Macro def-edebug-spec macro specification
-Specify which expressions of a call to macro @var{macro} are forms to be
-evaluated. For simple macros, the @var{specification} often looks very
-similar to the formal argument list of the macro definition, but
-specifications are much more general than macro arguments.
-
-The @var{macro} argument may actually be any symbol, not just a macro
-name.
-@end deffn
-
-Here is a simple example that defines the specification for the
-@code{for} macro described in the Emacs Lisp Reference Manual, followed
-by an alternative, equivalent specification.
-
-@example
-(def-edebug-spec for
- (symbolp "from" form "to" form "do" &rest form))
-
-(def-edebug-spec for
- (symbolp ['from form] ['to form] ['do body]))
-@end example
-
-Here is a table of the possibilities for @var{specification} and how each
-directs processing of arguments.
-
-@table @asis
-@item @code{t}
-All arguments are instrumented for evaluation.
-
-@item @code{0}
-None of the arguments is instrumented.
-
-@item a symbol
-The symbol must have an Edebug specification which is used instead.
-This indirection is repeated until another kind of specification is
-found. This allows you to inherit the specification for another macro.
-
-@item a list
-The elements of the list describe the types of the arguments of a
-calling form. The possible elements of a specification list are
-described in the following sections.
-@end table
-
-@menu
-* Specification List:: How to specify complex patterns of evaluation.
-* Backtracking:: What Edebug does when matching fails.
-* Specification Examples:: To help understand specifications.
-@end menu
-
-
-@node Specification List
-@subsubsection Specification List
-
-@cindex Edebug specification list
-A @dfn{specification list} is required for an Edebug specification if
-some arguments of a macro call are evaluated while others are not. Some
-elements in a specification list match one or more arguments, but others
-modify the processing of all following elements. The latter, called
-@dfn{specification keywords}, are symbols beginning with @samp{&} (such
-as @code{&optional}).
-
-A specification list may contain sublists which match arguments that are
-themselves lists, or it may contain vectors used for grouping. Sublists
-and groups thus subdivide the specification list into a hierarchy of
-levels. Specification keywords only apply to the remainder of the
-sublist or group they are contained in.
-
-When a specification list involves alternatives or repetition, matching
-it against an actual macro call may require backtracking.
-@xref{Backtracking}, for more details.
-
-Edebug specifications provide the power of regular expression matching,
-plus some context-free grammar constructs: the matching of sublists with
-balanced parentheses, recursive processing of forms, and recursion via
-indirect specifications.
-
-Here's a table of the possible elements of a specification list, with
-their meanings:
-
-@table @code
-@item sexp
-A single Lisp object, not unevaluated.
-@c "unevaluated expression" is not meaningful, because
-@c an expression is a Lisp object intended for evaluation.
-
-@item form
-A single evaluated expression, which is instrumented.
-
-@item place
-@findex edebug-unwrap
-A place to store a value, as in the Common Lisp @code{setf} construct.
-
-@item body
-Short for @code{&rest form}. See @code{&rest} below.
-
-@item function-form
-A function form: either a quoted function symbol, a quoted lambda
-expression, or a form (that should evaluate to a function symbol or
-lambda expression). This is useful when an argument that's a lambda
-expression might be quoted with @code{quote} rather than
-@code{function}, since it instruments the body of the lambda expression
-either way.
-
-@item lambda-expr
-A lambda expression with no quoting.
-
-@item &optional
-@kindex &optional @r{(Edebug)}
-All following elements in the specification list are optional; as soon
-as one does not match, Edebug stops matching at this level.
-
-To make just a few elements optional followed by non-optional elements,
-use @code{[&optional @var{specs}@dots{}]}. To specify that several
-elements must all match or none, use @code{&optional
-[@var{specs}@dots{}]}. See the @code{defun} example below.
-
-@item &rest
-@kindex &rest @r{(Edebug)}
-All following elements in the specification list are repeated zero or
-more times. All the elements need not match in the last repetition,
-however.
-
-To repeat only a few elements, use @code{[&rest @var{specs}@dots{}]}.
-To specify several elements that must all match on every repetition, use
-@code{&rest [@var{specs}@dots{}]}.
-
-@item &or
-@kindex &or @r{(Edebug)}
-Each of the following elements in the specification list is an
-alternative. One of the alternatives must match, or the @code{&or}
-specification fails.
-
-Each list element following @code{&or} is a single alternative. To
-group two or more list elements as a single alternative, enclose them in
-@code{[@dots{}]}.
-
-@item &not
-@kindex &not @r{(Edebug)}
-Each of the following elements is matched as alternatives as if by using
-@code{&or}, but if any of them match, the specification fails. If none
-of them match, nothing is matched, but the @code{&not} specification
-succeeds.
-
-@item &define
-@kindex &define @r{(Edebug)}
-Indicates that the specification is for a defining form. The defining
-form itself is not instrumented (i.e. Edebug does not stop before and
-after the defining form), but forms inside it typically will be
-instrumented. The @code{&define} keyword should be the first element in
-a list specification.
-
-@item nil
-This is successful when there are no more arguments to match at the
-current argument list level; otherwise it fails. See sublist
-specifications and the backquote example below.
-
-@item gate
-@cindex preventing backtracking
-No argument is matched but backtracking through the gate is disabled
-while matching the remainder of the specifications at this level. This
-is primarily used to generate more specific syntax error messages. See
-@ref{Backtracking}, for more details. Also see the @code{let} example
-below.
-
-@item @var{other-symbol}
-@cindex indirect specifications
-Any other symbol in a specification list may be a predicate or an
-indirect specification.
-
-If the symbol has an Edebug specification, this @dfn{indirect
-specification} should be either a list specification that is used in
-place of the symbol, or a function that is called to process the
-arguments. The specification may be defined with @code{def-edebug-spec}
-just as for macros. See the @code{defun} example below.
-
-Otherwise, the symbol should be a predicate. The predicate is called
-with the argument and the specification fails if the predicate returns
-@code{nil}. In either case, that argument is not instrumented.
-
-Some suitable predicates include @code{symbolp}, @code{integerp},
-@code{stringp}, @code{vectorp}, and @code{atom}.
-
-@item [@var{elements}@dots{}]
-@cindex [@dots{}] (Edebug)
-A vector of elements groups the elements into a single @dfn{group
-specification}. Its meaning has nothing to do with vectors.
-
-@item "@var{string}"
-The argument should be a symbol named @var{string}. This specification
-is equivalent to the quoted symbol, @code{'@var{symbol}}, where the name
-of @var{symbol} is the @var{string}, but the string form is preferred.
-
-@item (vector @var{elements}@dots{})
-The argument should be a vector whose elements must match the
-@var{elements} in the specification. See the backquote example below.
-
-@item (@var{elements}@dots{})
-Any other list is a @dfn{sublist specification} and the argument must be
-a list whose elements match the specification @var{elements}.
-
-@cindex dotted lists (Edebug)
-A sublist specification may be a dotted list and the corresponding list
-argument may then be a dotted list. Alternatively, the last @sc{cdr} of a
-dotted list specification may be another sublist specification (via a
-grouping or an indirect specification, e.g. @code{(spec . [(more
-specs@dots{})])}) whose elements match the non-dotted list arguments.
-This is useful in recursive specifications such as in the backquote
-example below. Also see the description of a @code{nil} specification
-above for terminating such recursion.
-
-Note that a sublist specification written as @code{(specs . nil)}
-is equivalent to @code{(specs)}, and @code{(specs .
-(sublist-elements@dots{}))} is equivalent to @code{(specs
-sublist-elements@dots{})}.
-@end table
-
-@c Need to document extensions with &symbol and :symbol
-
-Here is a list of additional specifications that may only appear after
-@code{&define}. See the @code{defun} example below.
-
-@table @code
-@item name
-The argument, a symbol, is the name of the defining form.
-
-A defining form is not required to have a name field; and it may have
-multiple name fields.
-
-@item :name
-This construct does not actually match an argument. The element
-following @code{:name} should be a symbol; it is used as an additional
-name component for the definition. You can use this to add a unique,
-static component to the name of the definition. It may be used more
-than once.
-
-@item arg
-The argument, a symbol, is the name of an argument of the defining form.
-However, lambda list keywords (symbols starting with @samp{@code{&}})
-are not allowed.
-
-@item lambda-list
-@cindex lambda-list (Edebug)
-This matches a lambda list---the argument list of a lambda expression.
-
-@item def-body
-The argument is the body of code in a definition. This is like
-@code{body}, described above, but a definition body must be instrumented
-with a different Edebug call that looks up information associated with
-the definition. Use @code{def-body} for the highest level list of forms
-within the definition.
-
-@item def-form
-The argument is a single, highest-level form in a definition. This is
-like @code{def-body}, except use this to match a single form rather than
-a list of forms. As a special case, @code{def-form} also means that
-tracing information is not output when the form is executed. See the
-@code{interactive} example below.
-@end table
-
-@node Backtracking
-@subsubsection Backtracking
-
-@cindex backtracking
-@cindex syntax error (Edebug)
-If a specification fails to match at some point, this does not
-necessarily mean a syntax error will be signaled; instead,
-@dfn{backtracking} will take place until all alternatives have been
-exhausted. Eventually every element of the argument list must be
-matched by some element in the specification, and every required element
-in the specification must match some argument.
-
-Backtracking is disabled for the remainder of a sublist or group when
-certain conditions occur, described below. Backtracking is reenabled
-when a new alternative is established by @code{&optional}, @code{&rest},
-or @code{&or}. It is also reenabled initially when processing a
-sublist or group specification or an indirect specification.
-
-You might want to disable backtracking to commit to some alternative so
-that Edebug can provide a more specific syntax error message. Normally,
-if no alternative matches, Edebug reports that none matched, but if one
-alternative is committed to, Edebug can report how it failed to match.
-
-First, backtracking is disabled while matching any of the form
-specifications (i.e. @code{form}, @code{body}, @code{def-form}, and
-@code{def-body}). These specifications will match any form so any error
-must be in the form itself rather than at a higher level.
-
-Second, backtracking is disabled after successfully matching a quoted
-symbol or string specification, since this usually indicates a
-recognized construct. If you have a set of alternative constructs that
-all begin with the same symbol, you can usually work around this
-constraint by factoring the symbol out of the alternatives, e.g.,
-@code{["foo" &or [first case] [second case] ...]}.
-
-Third, backtracking may be explicitly disabled by using the
-@code{gate} specification. This is useful when you know that
-no higher alternatives may apply.
-
-@node Specification Examples
-@subsubsection Specification Examples
-
-It may be easier to understand Edebug specifications by studying
-the examples provided here.
-
-A @code{let} special form has a sequence of bindings and a body. Each
-of the bindings is either a symbol or a sublist with a symbol and
-optional value. In the specification below, notice the @code{gate}
-inside of the sublist to prevent backtracking once a sublist is found.
-
-@example
-(def-edebug-spec let
- ((&rest
- &or symbolp (gate symbolp &optional form))
- body))
-@end example
-
-Edebug uses the following specifications for @code{defun} and
-@code{defmacro} and the associated argument list and @code{interactive}
-specifications. It is necessary to handle interactive forms specially
-since an expression argument it is actually evaluated outside of the
-function body.
-
-@smallexample
-(def-edebug-spec defmacro defun) ; @r{Indirect ref to @code{defun} spec.}
-(def-edebug-spec defun
- (&define name lambda-list
- [&optional stringp] ; @r{Match the doc string, if present.}
- [&optional ("interactive" interactive)]
- def-body))
-
-(def-edebug-spec lambda-list
- (([&rest arg]
- [&optional ["&optional" arg &rest arg]]
- &optional ["&rest" arg]
- )))
-
-(def-edebug-spec interactive
- (&optional &or stringp def-form)) ; @r{Notice: @code{def-form}}
-@end smallexample
-
-The specification for backquote below illustrates how to match
-dotted lists and use @code{nil} to terminate recursion. It also
-illustrates how components of a vector may be matched. (The actual
-specification defined by Edebug does not support dotted lists because
-doing so causes very deep recursion that could fail.)
-
-@smallexample
-(def-edebug-spec ` (backquote-form)) ; @r{Alias just for clarity.}
-
-(def-edebug-spec backquote-form
- (&or ([&or "," ",@@"] &or ("quote" backquote-form) form)
- (backquote-form . [&or nil backquote-form])
- (vector &rest backquote-form)
- sexp))
-@end smallexample
-
-
-@node Edebug Options
-@subsection Edebug Options
-
- These options affect the behavior of Edebug:
-
-@defopt edebug-setup-hook
-Functions to call before Edebug is used. Each time it is set to a new
-value, Edebug will call those functions once and then
-@code{edebug-setup-hook} is reset to @code{nil}. You could use this to
-load up Edebug specifications associated with a package you are using
-but only when you also use Edebug.
-@xref{Instrumenting}.
-@end defopt
-
-@defopt edebug-all-defs
-If this is non-@code{nil}, normal evaluation of defining forms such as
-@code{defun} and @code{defmacro} instruments them for Edebug. This
-applies to @code{eval-defun}, @code{eval-region}, @code{eval-buffer},
-and @code{eval-current-buffer}.
-
-Use the command @kbd{M-x edebug-all-defs} to toggle the value of this
-option. @xref{Instrumenting}.
-@end defopt
-
-@defopt edebug-all-forms
-If this is non-@code{nil}, the commands @code{eval-defun},
-@code{eval-region}, @code{eval-buffer}, and @code{eval-current-buffer}
-instrument all forms, even those that don't define anything.
-This doesn't apply to loading or evaluations in the minibuffer.
-
-Use the command @kbd{M-x edebug-all-forms} to toggle the value of this
-option. @xref{Instrumenting}.
-@end defopt
-
-@defopt edebug-save-windows
-If this is non-@code{nil}, Edebug saves and restores the window
-configuration. That takes some time, so if your program does not care
-what happens to the window configurations, it is better to set this
-variable to @code{nil}.
-
-If the value is a list, only the listed windows are saved and
-restored.
-
-You can use the @kbd{W} command in Edebug to change this variable
-interactively. @xref{Edebug Display Update}.
-@end defopt
-
-@defopt edebug-save-displayed-buffer-points
-If this is non-@code{nil}, Edebug saves and restores point in all
-displayed buffers.
-
-Saving and restoring point in other buffers is necessary if you are
-debugging code that changes the point of a buffer which is displayed in
-a non-selected window. If Edebug or the user then selects the window,
-point in that buffer will move to the window's value of point.
-
-Saving and restoring point in all buffers is expensive, since it
-requires selecting each window twice, so enable this only if you need
-it. @xref{Edebug Display Update}.
-@end defopt
-
-@defopt edebug-initial-mode
-If this variable is non-@code{nil}, it specifies the initial execution
-mode for Edebug when it is first activated. Possible values are
-@code{step}, @code{next}, @code{go}, @code{Go-nonstop}, @code{trace},
-@code{Trace-fast}, @code{continue}, and @code{Continue-fast}.
-
-The default value is @code{step}.
-@xref{Edebug Execution Modes}.
-@end defopt
-
-@defopt edebug-trace
-@findex edebug-print-trace-before
-@findex edebug-print-trace-after
-Non-@code{nil} means display a trace of function entry and exit.
-Tracing output is displayed in a buffer named @samp{*edebug-trace*}, one
-function entry or exit per line, indented by the recursion level.
-
-The default value is @code{nil}.
-
-Also see @code{edebug-tracing}, in @xref{Trace Buffer}.
-@end defopt
-
-@defopt edebug-test-coverage
-If non-@code{nil}, Edebug tests coverage of all expressions debugged.
-This is done by comparing the result of each expression
-with the previous result. Coverage is considered OK if two different
-results are found. So to sufficiently test the coverage of your code,
-try to execute it under conditions that evaluate all expressions more
-than once, and produce different results for each expression.
-
-Use @kbd{M-x edebug-display-freq-count} to display the frequency count
-and coverage information for a definition.
-@xref{Coverage Testing}.
-@end defopt
-
-@defopt edebug-continue-kbd-macro
-If non-@code{nil}, continue defining or executing any keyboard macro
-that is executing outside of Edebug. Use this with caution since it is not
-debugged.
-@xref{Edebug Execution Modes}.
-@end defopt
-
-@defopt edebug-print-length
-If non-@code{nil}, bind @code{print-length} to this while printing
-results in Edebug. The default value is @code{50}.
-@xref{Printing in Edebug}.
-@end defopt
-
-@defopt edebug-print-level
-If non-@code{nil}, bind @code{print-level} to this while printing
-results in Edebug. The default value is @code{50}.
-@end defopt
-
-@defopt edebug-print-circle
-If non-@code{nil}, bind @code{print-circle} to this while printing
-results in Edebug. The default value is @code{nil}.
-@end defopt
-
-@defopt edebug-on-error
-Edebug binds @code{debug-on-error} to this value, if
-@code{debug-on-error} was previously @code{nil}. @xref{Trapping
-Errors}.
-@end defopt
-
-@defopt edebug-on-quit
-Edebug binds @code{debug-on-quit} to this value, if
-@code{debug-on-quit} was previously @code{nil}. @xref{Trapping
-Errors}.
-@end defopt
-
- If you change the values of @code{edebug-on-error} or
-@code{edebug-on-quit} while Edebug is active, their values won't be used
-until the @emph{next} time Edebug is invoked via a new command.
-@c Not necessarily a deeper command level.
-@c A new command is not precisely true, but that is close enough -- dan
-
-@defopt edebug-global-break-condition
-If non-@code{nil}, an expression to test for at every stop point.
-If the result is non-nil, then break. Errors are ignored.
-@xref{Global Break Condition}.
-@end defopt
diff --git a/lispref/elisp-covers.texi b/lispref/elisp-covers.texi
deleted file mode 100644
index aa9d23b8444..00000000000
--- a/lispref/elisp-covers.texi
+++ /dev/null
@@ -1,248 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-@comment %**start of header
-@setfilename covers.info
-@settitle GNU Emacs Lisp Reference Manual
-@comment %**end of header
-
-@titlepage
-@c ================ Volume 1 ================
-@w{ }
-@sp 2
-@center @titlefont{The}
-@sp 1
-@center @titlefont{GNU}
-@sp 1
-@center @titlefont{Emacs Lisp}
-@sp 1
-@center @titlefont{Reference}
-@sp 1
-@center @titlefont{Manual}
-@sp 2
-@center GNU Emacs Version 19
-@center for Unix Users
-@center Edition 2.3, June 1994
-@sp 2
-@center @titlefont{Volume 1}
-@sp 2
-@center by Bil Lewis, Dan LaLiberte,
-@center and the GNU Manual Group
-
-@page
-@c ================ Volume 2 ================
-@w{ }
-@sp 5
-@center @titlefont{The}
-@sp 1
-@center @titlefont{GNU}
-@sp 1
-@center @titlefont{Emacs Lisp}
-@sp 1
-@center @titlefont{Reference}
-@sp 1
-@center @titlefont{Manual}
-@sp 2
-@center GNU Emacs Version 19
-@center for Unix Users
-@center Edition 2.3, June 1994
-@sp 2
-@center @titlefont{Volume 2}
-@sp 2
-@center by Bil Lewis,
-@center Dan LaLiberte, and
-@center the GNU Manual Group
-
-@page
-@c ================ Volume 1 with baseline skip 16pt ================
-
-@tex
-\global\baselineskip = 16pt
-@end tex
-
-16 pts baseline skip:
-
-@w{ }
-@sp 2
-@center @titlefont{The}
-@sp 1
-@center @titlefont{GNU}
-@sp 1
-@center @titlefont{Emacs Lisp}
-@sp 1
-@center @titlefont{Reference}
-@sp 1
-@center @titlefont{Manual}
-@sp 2
-@center GNU Emacs Version 19
-@center for Unix Users
-@center Edition 2.3, June 1994
-@sp 2
-@center @titlefont{Volume 1}
-@sp 2
-@center by Bil Lewis, Dan LaLiberte,
-@center and the GNU Manual Group
-
-@page
-@c ================ Volume 1 with baseline skip 18pt ================
-
-@tex
-\global\baselineskip = 18pt
-@end tex
-
-18 pts baseline skip, with 15pts between sections
-
-@w{ }
-@sp 2
-@center @titlefont{The}
-@sp 1
-@center @titlefont{GNU}
-@sp 1
-@center @titlefont{Emacs Lisp}
-@sp 1
-@center @titlefont{Reference}
-@sp 1
-@center @titlefont{Manual}
-@tex
-\global\baselineskip = 15pt
-@end tex
-
-@sp 2
-@center GNU Emacs Version 19
-@center for Unix Users
-@center Edition 2.3, June 1994
-@sp 2
-@center @titlefont{Volume 1}
-@sp 2
-@center by Bil Lewis,
-@center Dan LaLiberte, and
-@center the GNU Manual Group
-
-@page
-@c ================ Volume 1 with more baseline skip 24 pts ================
-
-@tex
-\global\baselineskip = 24pt
-@end tex
-
-24 pts baseline skip:
-
-@w{ }
-@sp 2
-@center @titlefont{The}
-@sp 1
-@center @titlefont{GNU}
-@sp 1
-@center @titlefont{Emacs Lisp}
-@sp 1
-@center @titlefont{Reference}
-@sp 1
-@center @titlefont{Manual}
-@sp 2
-@center GNU Emacs Version 19
-@center for Unix Users
-@center Edition 2.3, June 1994
-@sp 2
-@center @titlefont{Volume 1}
-@sp 2
-@center by Bil Lewis, Dan LaLiberte,
-@center and the GNU Manual Group
-
-@page
-@c ================ Volume 2 with more baseline skip 18 pts ================
-
-@tex
-\global\baselineskip = 18pt
-@end tex
-
-18 pts baseline skip:
-
-@w{ }
-@sp 5
-@center @titlefont{The}
-@sp 1
-@center @titlefont{GNU}
-@sp 1
-@center @titlefont{Emacs Lisp}
-@sp 1
-@center @titlefont{Reference}
-@sp 1
-@center @titlefont{Manual}
-@sp 2
-@center GNU Emacs Version 19
-@center for Unix Users
-@center Edition 2.3, June 1994
-@sp 2
-@center @titlefont{Volume 2}
-@sp 2
-@center by Bil Lewis, Dan LaLiberte,
-@center and the GNU Manual Group
-
-@page
-@c ================ Volume 2 with more baseline skip 24 pts ================
-
-@tex
-\global\baselineskip = 24pt
-@end tex
-
-24 pts baseline skip:
-
-@w{ }
-@sp 5
-@center @titlefont{The}
-@sp 1
-@center @titlefont{GNU}
-@sp 1
-@center @titlefont{Emacs Lisp}
-@sp 1
-@center @titlefont{Reference}
-@sp 1
-@center @titlefont{Manual}
-@sp 2
-@center GNU Emacs Version 19
-@center for Unix Users
-@center Edition 2.3, June 1994
-@sp 2
-@center @titlefont{Volume 2}
-@sp 2
-@center by Bil Lewis, Dan LaLiberte,
-@center and the GNU Manual Group
-
-
-@page
-@c ================ Spine 1 ================
-
-@w{@titlefont{The GNU Emacs Lisp Reference Manual --- Vol. 1}}
-@sp 4
-@center GNU Emacs Version 19
-@center for Unix Users
-@center Edition 2.3, June 1994
-@sp 4
-@center by Bil Lewis, Dan LaLiberte,
-@center and the GNU Manual Group
-
-@sp 4
-@author The GNU Emacs Lisp Reference Manual --- Vol. 1
-@sp 3
-@author FSF
-
-@author
-
-@page
-@c ================ Spine 2 ================
-
-@w{@titlefont{The GNU Emacs Lisp Reference Manual --- Vol. 2}}
-@sp 4
-@center GNU Emacs Version 19
-@center for Unix Users
-@center Edition 2.3, June 1994
-@sp 4
-@center by Bil Lewis, Dan LaLiberte,
-@center and the GNU Manual Group
-
-
-@sp 4
-@author The GNU Emacs Lisp Reference Manual --- Vol. 2
-@sp 3
-@author FSF
-
-@end titlepage
-@bye
diff --git a/lispref/elisp-vol1.texi b/lispref/elisp-vol1.texi
deleted file mode 100644
index 2d9e96311c5..00000000000
--- a/lispref/elisp-vol1.texi
+++ /dev/null
@@ -1,1047 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-@c %**start of header
-@setfilename elisp
-@settitle GNU Emacs Lisp Reference Manual: Volume 1
-@smallbook
-@c %**end of header
-
-
-@tex
-%%%% Experiment with smaller skip before sections and subsections.
-%%%% --rjc 30mar92
-
-\global\secheadingskip = 17pt plus 6pt minus 3pt
-\global\subsecheadingskip = 14pt plus 6pt minus 3pt
-
-% The defaults are:
-% \secheadingskip = 21pt plus 8pt minus 4pt
-% \subsecheadingskip = 17pt plus 8pt minus 4pt
-@end tex
-
-@finalout
-@c tex
-@c \overfullrule=0pt
-@c end tex
-
-@c Start volume 1 chapter numbering on chapter 1;
-@c this must be listed as chapno 0.
-@tex
-\global\chapno=0
-@end tex
-
-@c ================================================================
-@c Note: I was unable to figure out how to get .aux files copied
-@c properly in the time I had. Hence need to copy .aux file before
-@c running Tex. --rjc
-
-@tex
-
-\message{}
-\message{Redefining contents commands...}
-\message{}
-
-% Special @contents command
-
-% This inputs fixed up table of contents file rather than create new one.
-\global\def\contents{%
- \startcontents{Table of Contents}%
- \input elisp1-toc-ready.toc
- \endgroup
- \vfill \eject
-}
-
-% Special @summarycontents command
-% This inputs fixed up table of contents file rather than create new one.
-\global\def\summarycontents{%
- \startcontents{Short Contents}%
- %
- \let\chapentry = \shortchapentry
- \let\unnumbchapentry = \shortunnumberedentry
- % We want a true roman here for the page numbers.
- \secfonts
- \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
- \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 elisp1-toc-ready.toc
- \endgroup
- \vfill \eject
-}
-
-\message{}
-\message{Formatting special two volume edition...Volume 1...}
-\message{}
-@end tex
-@c ================================================================
-
-
-@c ==> This `elisp-small.texi' is a `smallbook' version of the manual.
-
-@c ==== Following are acceptable over and underfull hboxes in TeX ====
-
-@c -----
-@c [163] [164] [165] [166]) (loading.texi Chapter 13 [167] [168] [169]
-@c Overfull \hbox (20.5428pt too wide) in paragraph at lines 131--131
-@c []@ninett
-@c setenv EMAC-SLOAD-PATH .:/user/bil/emacs:/usr/local/lib/emacs/lisp[]
-@c -----
-@c (minibuf.texi Chapter 17 [206] [207] [208] [209] [210] [211] [212] [213]
-@c [214] [215]
-@c Overfull \hbox (2.09094pt too wide) in paragraph at lines 550--560
-@c @texttt map[] @textrm if @textsl require-match @textrm is
-@c @texttt nil[]@textrm , or else with the keymap @texttt minibuffer-
-@c -----
-@c (locals.texi Appendix @char 68 [533] [534]
-@c Underfull \hbox (badness 2512) in paragraph at lines 4--4
-@c []@chaprm Appendix DStandard Buffer-Local
-
-@c -------------------------------------------------------------------
-
-@c
-@c Combine indices.
-@synindex cp fn
-@syncodeindex vr fn
-@syncodeindex ky fn
-@syncodeindex pg fn
-@syncodeindex tp fn
-@c oops: texinfo-format-buffer ignores synindex
-@c
-
-@ifinfo
-This file documents GNU Emacs Lisp.
-
-@c The edition number appears in several places in this file
-@c and also in the file intro.texi.
-This is edition 2.4 of the GNU Emacs Lisp Reference
-Manual. It corresponds to Emacs Version 19.29.
-@c Please REMEMBER to update edition number in *four* places in this file
-@c and also in *one* place in ==> intro.texi <==
-@c huh? i only found three real places where the edition is stated, and
-@c one place where it is not stated explicitly ("this info file is newer
-@c than the foobar edition"). --mew 13sep93
-
-Published by the Free Software Foundation
-59 Temple Place, Suite 330
-Boston, MA 02111-1307 USA
-
-Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995 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.
-
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided also that the
-section entitled ``GNU General Public License'' is 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 section entitled ``GNU General Public License'' may be
-included in a translation approved by the Free Software Foundation
-instead of in the original English.
-@end ifinfo
-
-@setchapternewpage odd
-
-@iftex
-@shorttitlepage The GNU Emacs Lisp Reference Manual: Volume 1
-@end iftex
-@titlepage
-@sp 1
-@center @titlefont{The}
-@sp 1
-@center @titlefont{GNU Emacs Lisp}
-@sp 1
-@center @titlefont{Reference Manual}
-@sp 2
-@center GNU Emacs Version 19.29
-@center for Unix Users
-@sp 1
-@center Edition 2.4, June 1995
-@sp 2
-@center @titlefont{Volume 1}
-@sp 3
-@center by Bil Lewis, Dan LaLiberte,
-@center and the GNU Manual Group
-@page
-@vskip 0pt plus 1filll
-Copyright @copyright{} 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-@sp 2
-Edition 2.4 @*
-Revised for Emacs Version 19.29,@*
-June, 1995.@*
-@sp 2
-ISBN 1-882114-71-X
-
-@sp 2
-Published by the Free Software Foundation @*
-59 Temple Place, Suite 330 @*
-Boston, MA 02111-1307 USA
-
-@sp 1
-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
-section entitled ``GNU General Public License'' is 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 section entitled ``GNU General Public License'' may be
-included in a translation approved by the Free Software Foundation
-instead of in the original English.
-
-@sp 2
-Cover art by Etienne Suvasa.
-@end titlepage
-@page
-
-@node Top, Copying, (dir), (dir)
-
-@ifinfo
-This Info file contains edition 2.4 of the GNU Emacs Lisp Reference
-Manual, corresponding to GNU Emacs version 19.29.
-@end ifinfo
-
-@menu
-* Copying:: Conditions for copying and changing GNU Emacs.
-* Introduction:: Introduction and conventions used.
-
-* Lisp Data Types:: Data types of objects in Emacs Lisp.
-* Numbers:: Numbers and arithmetic functions.
-* Strings and Characters:: Strings, and functions that work on them.
-* Lists:: Lists, cons cells, and related functions.
-* Sequences Arrays Vectors:: Lists, strings and vectors are called sequences.
- Certain functions act on any kind of sequence.
- The description of vectors is here as well.
-* Symbols:: Symbols represent names, uniquely.
-
-* Evaluation:: How Lisp expressions are evaluated.
-* Control Structures:: Conditionals, loops, nonlocal exits.
-* Variables:: Using symbols in programs to stand for values.
-* Functions:: A function is a Lisp program
- that can be invoked from other functions.
-* Macros:: Macros are a way to extend the Lisp language.
-
-* Loading:: Reading files of Lisp code into Lisp.
-* Byte Compilation:: Compilation makes programs run faster.
-* Debugging:: Tools and tips for debugging Lisp programs.
-
-* Read and Print:: Converting Lisp objects to text and back.
-* Minibuffers:: Using the minibuffer to read input.
-* Command Loop:: How the editor command loop works,
- and how you can call its subroutines.
-* Keymaps:: Defining the bindings from keys to commands.
-* Modes:: Defining major and minor modes.
-* Documentation:: Writing and using documentation strings.
-
-* Files:: Accessing files.
-* Backups and Auto-Saving:: Controlling how backups and auto-save
- files are made.
-* Buffers:: Creating and using buffer objects.
-* Windows:: Manipulating windows and displaying buffers.
-* Frames:: Making multiple X windows.
-* Positions:: Buffer positions and motion functions.
-* Markers:: Markers represent positions and update
- automatically when the text is changed.
-
-* Text:: Examining and changing text in buffers.
-* Searching and Matching:: Searching buffers for strings or regexps.
-* Syntax Tables:: The syntax table controls word and list parsing.
-* Abbrevs:: How Abbrev mode works, and its data structures.
-
-* Processes:: Running and communicating with subprocesses.
-* System Interface:: Getting the user id, system type, environment
- variables, and other such things.
-* Display:: Parameters controlling screen usage.
- The bell. Waiting for input.
-* Calendar:: Customizing the calendar and diary.
-
-Appendices
-
-* Tips:: Advice for writing Lisp programs.
-* GNU Emacs Internals:: Building and dumping Emacs;
- internal data structures.
-* Standard Errors:: List of all error symbols.
-* Standard Buffer-Local Variables:: List of variables local in all buffers.
-* Standard Keymaps:: List of standard keymaps.
-* Standard Hooks:: List of standard hook variables.
-
-* Index:: Index including concepts, functions, variables,
- and other terms.
-
- --- The Detailed Node Listing ---
-
-Here are other nodes that are inferiors of those already listed,
-mentioned here so you can get to them in one step:
-
-Introduction
-
-* Caveats:: Flaws and a request for help.
-* Lisp History:: Emacs Lisp is descended from Maclisp.
-* Conventions:: How the manual is formatted.
-* Acknowledgements:: The authors, editors, and sponsors of this manual.
-
-Conventions
-
-* Some Terms:: Explanation of terms we use in this manual.
-* nil and t:: How the symbols @code{nil} and @code{t} are used.
-* Evaluation Notation:: The format we use for examples of evaluation.
-* Printing Notation:: The format we use for examples that print output.
-* Error Messages:: The format we use for examples of errors.
-* Buffer Text Notation:: The format we use for buffer contents in examples.
-* Format of Descriptions:: Notation for describing functions, variables, etc.
-
-Format of Descriptions
-
-* A Sample Function Description::
-* A Sample Variable Description::
-
-Lisp Data Types
-
-* Printed Representation:: How Lisp objects are represented as text.
-* Comments:: Comments and their formatting conventions.
-* Programming Types:: Types found in all Lisp systems.
-* Editing Types:: Types specific to Emacs.
-* Type Predicates:: Tests related to types.
-* Equality Predicates:: Tests of equality between any two objects.
-
-Programming Types
-
-* Integer Type:: Numbers without fractional parts.
-* Floating Point Type:: Numbers with fractional parts and with a large range.
-* Character Type:: The representation of letters, numbers and
- control characters.
-* Sequence Type:: Both lists and arrays are classified as sequences.
-* Cons Cell Type:: Cons cells, and lists (which are made from cons cells).
-* Array Type:: Arrays include strings and vectors.
-* String Type:: An (efficient) array of characters.
-* Vector Type:: One-dimensional arrays.
-* Symbol Type:: A multi-use object that refers to a function,
- variable, property list, or itself.
-* Function Type:: A piece of executable code you can call from elsewhere.
-* Macro Type:: A method of expanding an expression into another
- expression, more fundamental but less pretty.
-* Primitive Function Type:: A function written in C, callable from Lisp.
-* Byte-Code Type:: A function written in Lisp, then compiled.
-* Autoload Type:: A type used for automatically loading seldom-used
- functions.
-
-List Type
-
-* Dotted Pair Notation:: An alternative syntax for lists.
-* Association List Type:: A specially constructed list.
-
-Editing Types
-
-* Buffer Type:: The basic object of editing.
-* Window Type:: What makes buffers visible.
-* Window Configuration Type::Save what the screen looks like.
-* Marker Type:: A position in a buffer.
-* Process Type:: A process running on the underlying OS.
-* Stream Type:: Receive or send characters.
-* Keymap Type:: What function a keystroke invokes.
-* Syntax Table Type:: What a character means.
-
-Numbers
-
-* Integer Basics:: Representation and range of integers.
-* Float Basics:: Representation and range of floating point.
-* Predicates on Numbers:: Testing for numbers.
-* Comparison of Numbers:: Equality and inequality predicates.
-* Arithmetic Operations:: How to add, subtract, multiply and divide.
-* Bitwise Operations:: Logical and, or, not, shifting.
-* Numeric Conversions:: Converting float to integer and vice versa.
-* Math Functions:: Trig, exponential and logarithmic functions.
-* Random Numbers:: Obtaining random integers, predictable or not.
-
-Strings and Characters
-
-* String Basics:: Basic properties of strings and characters.
-* Predicates for Strings:: Testing whether an object is a string or char.
-* Creating Strings:: Functions to allocate new strings.
-* Text Comparison:: Comparing characters or strings.
-* String Conversion:: Converting characters or strings and vice versa.
-* Formatting Strings:: @code{format}: Emacs's analog of @code{printf}.
-* Character Case:: Case conversion functions.
-
-Lists
-
-* Cons Cells:: How lists are made out of cons cells.
-* Lists as Boxes:: Graphical notation to explain lists.
-* List-related Predicates:: Is this object a list? Comparing two lists.
-* List Elements:: Extracting the pieces of a list.
-* Building Lists:: Creating list structure.
-* Modifying Lists:: Storing new pieces into an existing list.
-* Sets And Lists:: A list can represent a finite mathematical set.
-* Association Lists:: A list can represent a finite relation or mapping.
-
-Modifying Existing List Structure
-
-* Setcar:: Replacing an element in a list.
-* Setcdr:: Replacing part of the list backbone.
- This can be used to remove or add elements.
-* Rearrangement:: Reordering the elements in a list; combining lists.
-
-Sequences, Arrays, and Vectors
-
-* Sequence Functions:: Functions that accept any kind of sequence.
-* Arrays:: Characteristics of arrays in Emacs Lisp.
-* Array Functions:: Functions specifically for arrays.
-* Vectors:: Functions specifically for vectors.
-
-Symbols
-
-* Symbol Components:: Symbols have names, values, function definitions
- and property lists.
-* Definitions:: A definition says how a symbol will be used.
-* Creating Symbols:: How symbols are kept unique.
-* Property Lists:: Each symbol has a property list
- for recording miscellaneous information.
-
-Evaluation
-
-* Intro Eval:: Evaluation in the scheme of things.
-* Eval:: How to invoke the Lisp interpreter explicitly.
-* Forms:: How various sorts of objects are evaluated.
-* Quoting:: Avoiding evaluation (to put constants in
- the program).
-
-Kinds of Forms
-
-* Self-Evaluating Forms:: Forms that evaluate to themselves.
-* Symbol Forms:: Symbols evaluate as variables.
-* Classifying Lists:: How to distinguish various sorts of list forms.
-* Function Forms:: Forms that call functions.
-* Macro Forms:: Forms that call macros.
-* Special Forms:: ``Special forms'' are idiosyncratic primitives,
- most of them extremely important.
-* Autoloading:: Functions set up to load files
- containing their real definitions.
-
-Control Structures
-
-* Sequencing:: Evaluation in textual order.
-* Conditionals:: @code{if}, @code{cond}.
-* Combining Conditions:: @code{and}, @code{or}, @code{not}.
-* Iteration:: @code{while} loops.
-* Nonlocal Exits:: Jumping out of a sequence.
-
-Nonlocal Exits
-
-* Catch and Throw:: Nonlocal exits for the program's own purposes.
-* Examples of Catch:: Showing how such nonlocal exits can be written.
-* Errors:: How errors are signaled and handled.
-* Cleanups:: Arranging to run a cleanup form if an
- error happens.
-
-Errors
-
-* Signaling Errors:: How to report an error.
-* Processing of Errors:: What Emacs does when you report an error.
-* Handling Errors:: How you can trap errors and continue execution.
-* Error Symbols:: How errors are classified for trapping them.
-
-Variables
-
-* Global Variables:: Variable values that exist permanently, everywhere.
-* Constant Variables:: Certain "variables" have values that never change.
-* Local Variables:: Variable values that exist only temporarily.
-* Void Variables:: Symbols that lack values.
-* Defining Variables:: A definition says a symbol is used as a variable.
-* Accessing Variables:: Examining values of variables whose names
- are known only at run time.
-* Setting Variables:: Storing new values in variables.
-* Variable Scoping:: How Lisp chooses among local and global values.
-* Buffer-Local Variables:: Variable values in effect only in one buffer.
-
-Scoping Rules for Variable Bindings
-
-* Scope:: Scope means where in the program a value
- is visible. Comparison with other languages.
-* Extent:: Extent means how long in time a value exists.
-* Impl of Scope:: Two ways to implement dynamic scoping.
-* Using Scoping:: How to use dynamic scoping carefully and
- avoid problems.
-
-Buffer-Local Variables
-
-* Intro to Buffer-Local:: Introduction and concepts.
-* Creating Buffer-Local:: Creating and destroying buffer-local bindings.
-* Default Value:: The default value is seen in buffers
- that don't have their own local values.
-
-Functions
-
-* What Is a Function:: Lisp functions vs primitives; terminology.
-* Lambda Expressions:: How functions are expressed as Lisp objects.
-* Function Names:: A symbol can serve as the name of a function.
-* Defining Functions:: Lisp expressions for defining functions.
-* Calling Functions:: How to use an existing function.
-* Mapping Functions:: Applying a function to each element of a list, etc.
-* Anonymous Functions:: Lambda-expressions are functions with no names.
-* Function Cells:: Accessing or setting the function definition
- of a symbol.
-* Related Topics:: Cross-references to specific Lisp primitives
- that have a special bearing on how
- functions work.
-
-Lambda Expressions
-
-* Lambda Components:: The parts of a lambda expression.
-* Simple Lambda:: A simple example.
-* Argument List:: Details and special features of argument lists.
-* Function Documentation:: How to put documentation in a function.
-
-Macros
-
-* Simple Macro:: A basic example.
-* Expansion:: How, when and why macros are expanded.
-* Compiling Macros:: How macros are expanded by the compiler.
-* Defining Macros:: How to write a macro definition.
-* Backquote:: Easier construction of list structure.
-* Problems with Macros:: Don't evaluate the macro arguments too many times.
- Don't hide the user's variables.
-
-Loading
-
-* How Programs Do Loading:: The @code{load} function and others.
-* Autoload:: Setting up a function to autoload.
-* Named Features:: Loading a library if it isn't already loaded.
-* Repeated Loading:: Precautions about loading a file twice.
-
-Byte Compilation
-
-* Compilation Functions:: Byte compilation functions.
-* Disassembly:: Disassembling byte-code; how to read byte-code.
-
-Debugging Lisp Programs
-
-* Debugger:: How the Emacs Lisp debugger is implemented.
-* Syntax Errors:: How to find syntax errors.
-* Compilation Errors:: How to find errors that show up in
- byte compilation.
-* Edebug:: A source-level Emacs Lisp debugger.
-
-The Lisp Debugger
-
-* Error Debugging:: Entering the debugger when an error happens.
-* Function Debugging:: Entering it when a certain function is called.
-* Explicit Debug:: Entering it at a certain point in the program.
-* Using Debugger:: What the debugger does; what you see while in it.
-* Debugger Commands:: Commands used while in the debugger.
-* Invoking the Debugger:: How to call the function @code{debug}.
-* Internals of Debugger:: Subroutines of the debugger, and global variables.
-
-Debugging Invalid Lisp Syntax
-
-* Excess Open:: How to find a spurious open paren or missing close.
-* Excess Close:: How to find a spurious close paren or missing open.
-
-Reading and Printing Lisp Objects
-
-* Streams Intro:: Overview of streams, reading and printing.
-* Input Streams:: Various data types that can be used as
- input streams.
-* Input Functions:: Functions to read Lisp objects from text.
-* Output Streams:: Various data types that can be used as
- output streams.
-* Output Functions:: Functions to print Lisp objects as text.
-
-Minibuffers
-
-* Intro to Minibuffers:: Basic information about minibuffers.
-* Text from Minibuffer:: How to read a straight text string.
-* Object from Minibuffer:: How to read a Lisp object or expression.
-* Completion:: How to invoke and customize completion.
-* Yes-or-No Queries:: Asking a question with a simple answer.
-* Minibuffer Misc:: Various customization hooks and variables.
-
-Completion
-
-* Basic Completion:: Low-level functions for completing strings.
- (These are too low level to use the minibuffer.)
-* Minibuffer Completion:: Invoking the minibuffer with completion.
-* Completion Commands:: Minibuffer commands that do completion.
-* High-Level Completion:: Convenient special cases of completion
- (reading buffer name, file name, etc.)
-* Reading File Names:: Using completion to read file names.
-* Programmed Completion:: Finding the completions for a given file name.
-
-Command Loop
-
-* Command Overview:: How the command loop reads commands.
-* Defining Commands:: Specifying how a function should read arguments.
-* Interactive Call:: Calling a command, so that it will read arguments.
-* Command Loop Info:: Variables set by the command loop for you to examine.
-* Input Events:: What input looks like when you read it.
-* Reading Input:: How to read input events from the keyboard or mouse.
-* Waiting:: Waiting for user input or elapsed time.
-* Quitting:: How @kbd{C-g} works. How to catch or defer quitting.
-* Prefix Command Arguments:: How the commands to set prefix args work.
-* Recursive Editing:: Entering a recursive edit,
- and why you usually shouldn't.
-* Disabling Commands:: How the command loop handles disabled commands.
-* Command History:: How the command history is set up, and how accessed.
-* Keyboard Macros:: How keyboard macros are implemented.
-
-Defining Commands
-
-* Using Interactive:: General rules for @code{interactive}.
-* Interactive Codes:: The standard letter-codes for reading arguments
- in various ways.
-* Interactive Examples:: Examples of how to read interactive arguments.
-
-Keymaps
-
-* Keymap Terminology:: Definitions of terms pertaining to keymaps.
-* Format of Keymaps:: What a keymap looks like as a Lisp object.
-* Creating Keymaps:: Functions to create and copy keymaps.
-* Inheritance and Keymaps:: How one keymap can inherit the bindings
- of another keymap.
-* Prefix Keys:: Defining a key with a keymap as its definition.
-* Menu Keymaps:: A keymap can define a menu for X windows
- or for use from the terminal.
-* Active Keymaps:: Each buffer has a local keymap
- to override the standard (global) bindings.
- Each minor mode can also override them.
-* Key Lookup:: How extracting elements from keymaps works.
-* Functions for Key Lookup:: How to request key lookup.
-* Changing Key Bindings:: Redefining a key in a keymap.
-* Key Binding Commands:: Interactive interfaces for redefining keys.
-* Scanning Keymaps:: Looking through all keymaps, for printing help.
-
-Major and Minor Modes
-
-* Major Modes:: Defining major modes.
-* Minor Modes:: Defining minor modes.
-* Mode Line Format:: Customizing the text that appears in the mode line.
-* Hooks:: How to use hooks; how to write code that
- provides hooks.
-
-Major Modes
-
-* Major Mode Conventions:: Coding conventions for keymaps, etc.
-* Example Major Modes:: Text mode and Lisp modes.
-* Auto Major Mode:: How Emacs chooses the major mode automatically.
-* Mode Help:: Finding out how to use a mode.
-
-Minor Modes
-
-* Minor Mode Conventions:: Tips for writing a minor mode.
-* Keymaps and Minor Modes:: How a minor mode can have its own keymap.
-
-Mode Line Format
-
-* Mode Line Data:: The data structure that controls the mode line.
-* Mode Line Variables:: Variables used in that data structure.
-* %-Constructs:: Putting information into a mode line.
-
-Documentation
-
-* Documentation Basics:: Good style for doc strings.
- Where to put them. How Emacs stores them.
-* Accessing Documentation:: How Lisp programs can access doc strings.
-* Keys in Documentation:: Substituting current key bindings.
-* Describing Characters:: Making printable descriptions of
- non-printing characters and key sequences.
-* Help Functions:: Subroutines used by Emacs help facilities.
-
-Files
-
-* Visiting Files:: Reading files into Emacs buffers for editing.
-* Saving Buffers:: Writing changed buffers back into files.
-* Reading from Files:: Reading files into other buffers.
-* Writing to Files:: Writing new files from parts of buffers.
-* File Locks:: Locking and unlocking files, to prevent
- simultaneous editing by two people.
-* Information about Files:: Testing existence, accessibility, size of files.
-* Contents of Directories:: Getting a list of the files in a directory.
-* Changing File Attributes:: Renaming files, changing protection, etc.
-* File Names:: Decomposing and expanding file names.
-
-Visiting Files
-
-* Visiting Functions:: The usual interface functions for visiting.
-* Subroutines of Visiting:: Lower-level subroutines that they use.
-
-Information about Files
-
-* Testing Accessibility:: Is a given file readable? Writable?
-* Kinds of Files:: Is it a directory? A link?
-* File Attributes:: How large is it? Any other names? Etc.
-
-File Names
-
-* File Name Components:: The directory part of a file name, and the rest.
-* Directory Names:: A directory's name as a directory
- is different from its name as a file.
-* Relative File Names:: Some file names are relative to a
- current directory.
-* File Name Expansion:: Converting relative file names to absolute ones.
-* Unique File Names:: Generating names for temporary files.
-* File Name Completion:: Finding the completions for a given file name.
-
-Backups and Auto-Saving
-
-* Backup Files:: How backup files are made; how their names
- are chosen.
-* Auto-Saving:: How auto-save files are made; how their
- names are chosen.
-* Reverting:: @code{revert-buffer}, and how to customize
- what it does.
-
-Backup Files
-
-* Making Backups:: How Emacs makes backup files, and when.
-* Rename or Copy:: Two alternatives: renaming the old file
- or copying it.
-* Numbered Backups:: Keeping multiple backups for each source file.
-* Backup Names:: How backup file names are computed; customization.
-
-Buffers
-
-* Buffer Basics:: What is a buffer?
-* Buffer Names:: Accessing and changing buffer names.
-* Buffer File Name:: The buffer file name indicates which file
- is visited.
-* Buffer Modification:: A buffer is @dfn{modified} if it needs to be saved.
-* Modification Time:: Determining whether the visited file was changed
- ``behind Emacs's back''.
-* Read Only Buffers:: Modifying text is not allowed in a
- read-only buffer.
-* The Buffer List:: How to look at all the existing buffers.
-* Creating Buffers:: Functions that create buffers.
-* Killing Buffers:: Buffers exist until explicitly killed.
-* Current Buffer:: Designating a buffer as current
- so primitives will access its contents.
-
-Windows
-
-* Basic Windows:: Basic information on using windows.
-* Splitting Windows:: Splitting one window into two windows.
-* Deleting Windows:: Deleting a window gives its space to other windows.
-* Selecting Windows:: The selected window is the one that you edit in.
-* Cyclic Window Ordering:: Moving around the existing windows.
-* Buffers and Windows:: Each window displays the contents of a buffer.
-* Displaying Buffers:: Higher-lever functions for displaying a buffer
- and choosing a window for it.
-* Window Point:: Each window has its own location of point.
-* Window Start:: The display-start position controls which text
- is on-screen in the window.
-* Vertical Scrolling:: Moving text up and down in the window.
-* Horizontal Scrolling:: Moving text sideways on the window.
-* Size of Window:: Accessing the size of a window.
-* Resizing Windows:: Changing the size of a window.
-* Window Configurations:: Saving and restoring the state of the screen.
-
-Frames
-
-* Creating Frames:: Creating additional frames.
-* Multiple Displays:: Creating frames on other X displays.
-* Frame Parameters:: Controlling frame size, position, font, etc.
-* Frame Titles:: Automatic updating of frame titles.
-* Deleting Frames:: Frames last until explicitly deleted.
-* Finding All Frames:: How to examine all existing frames.
-* Frames and Windows:: A frame contains windows;
- display of text always works through windows.
-* Minibuffers and Frames:: How a frame finds the minibuffer to use.
-* Input Focus:: Specifying the selected frame.
-* Visibility of Frames:: Frames may be visible or invisible, or icons.
-* Raising and Lowering:: Raising a frame makes it hide other X windows;
- lowering it makes the others hide them.
-* Frame Configurations:: Saving the state of all frames.
-* Mouse Tracking:: Getting events that say when the mouse moves.
-* Mouse Position:: Asking where the mouse is, or moving it.
-* Pop-Up Menus:: Displaying a menu for the user to select from.
-* Dialog Boxes:: Displaying a box to ask yes or no.
-* Pointer Shapes:: Specifying the shape of the mouse pointer.
-* X Selections:: Transferring text to and from other X clients.
-* Color Names:: Getting the definitions of color names.
-* Resources:: Getting resource values from the server.
-* Server Data:: Getting info about the X server.
-
-Positions
-
-* Point:: The special position where editing takes place.
-* Motion:: Changing point.
-* Excursions:: Temporary motion and buffer changes.
-* Narrowing:: Restricting editing to a portion of the buffer.
-
-Motion
-
-* Character Motion:: Moving in terms of characters.
-* Word Motion:: Moving in terms of words.
-* Buffer End Motion:: Moving to the beginning or end of the buffer.
-* Text Lines:: Moving in terms of lines of text.
-* Screen Lines:: Moving in terms of lines as displayed.
-* List Motion:: Moving by parsing lists and sexps.
-* Skipping Characters:: Skipping characters belonging to a certain set.
-
-Markers
-
-* Overview of Markers:: The components of a marker, and how it relocates.
-* Predicates on Markers:: Testing whether an object is a marker.
-* Creating Markers:: Making empty markers or markers at certain places.
-* Information from Markers:: Finding the marker's buffer or character
- position.
-* Changing Markers:: Moving the marker to a new buffer or position.
-* The Mark:: How ``the mark'' is implemented with a marker.
-* The Region:: How to access ``the region''.
-
-Text
-
-* Near Point:: Examining text in the vicinity of point.
-* Buffer Contents:: Examining text in a general fashion.
-* Insertion:: Adding new text to a buffer.
-* Commands for Insertion:: User-level commands to insert text.
-* Deletion:: Removing text from a buffer.
-* User-Level Deletion:: User-level commands to delete text.
-* The Kill Ring:: Where removed text sometimes is saved for
- later use.
-* Undo:: Undoing changes to the text of a buffer.
-* Auto Filling:: How auto-fill mode is implemented to break lines.
-* Filling:: Functions for explicit filling.
-* Margins:: How to specify margins for filling commands.
-* Sorting:: Functions for sorting parts of the buffer.
-* Indentation:: Functions to insert or adjust indentation.
-* Columns:: Computing horizontal positions, and using them.
-* Case Changes:: Case conversion of parts of the buffer.
-* Substitution:: Replacing a given character wherever it appears.
-* Registers:: How registers are implemented. Accessing
- the text or position stored in a register.
-
-The Kill Ring
-
-* Kill Ring Concepts:: What text looks like in the kill ring.
-* Kill Functions:: Functions that kill text.
-* Yank Commands:: Commands that access the kill ring.
-* Low-Level Kill Ring:: Functions and variables for kill ring access.
-* Internals of Kill Ring:: Variables that hold kill-ring data.
-
-Indentation
-
-* Primitive Indent:: Functions used to count and insert indentation.
-* Mode-Specific Indent:: Customize indentation for different modes.
-* Region Indent:: Indent all the lines in a region.
-* Relative Indent:: Indent the current line based on previous lines.
-* Indent Tabs:: Adjustable, typewriter-like tab stops.
-* Motion by Indent:: Move to first non-blank character.
-
-Searching and Matching
-
-* String Search:: Search for an exact match.
-* Regular Expressions:: Describing classes of strings.
-* Regexp Search:: Searching for a match for a regexp.
-* Match Data:: Finding out which part of the text matched
- various parts of a regexp, after regexp search.
-* Saving Match Data:: Saving and restoring this information.
-* Standard Regexps:: Useful regexps for finding sentences, pages,...
-* Searching and Case:: Case-independent or case-significant searching.
-
-Regular Expressions
-
-* Syntax of Regexps:: Rules for writing regular expressions.
-* Regexp Example:: Illustrates regular expression syntax.
-
-Syntax Tables
-
-* Syntax Descriptors:: How characters are classified.
-* Syntax Table Functions:: How to create, examine and alter syntax tables.
-* Parsing Expressions:: Parsing balanced expressions
- using the syntax table.
-* Standard Syntax Tables:: Syntax tables used by various major modes.
-* Syntax Table Internals:: How syntax table information is stored.
-
-Syntax Descriptors
-
-* Syntax Class Table:: Table of syntax classes.
-* Syntax Flags:: Additional flags each character can have.
-
-Abbrevs And Abbrev Expansion
-
-* Abbrev Mode:: Setting up Emacs for abbreviation.
-* Tables: Abbrev Tables. Creating and working with abbrev tables.
-* Defining Abbrevs:: Specifying abbreviations and their expansions.
-* Files: Abbrev Files. Saving abbrevs in files.
-* Expansion: Abbrev Expansion. Controlling expansion; expansion subroutines.
-* Standard Abbrev Tables:: Abbrev tables used by various major modes.
-
-Processes
-
-* Subprocess Creation:: Functions that start subprocesses.
-* Synchronous Processes:: Details of using synchronous subprocesses.
-* Asynchronous Processes:: Starting up an asynchronous subprocess.
-* Deleting Processes:: Eliminating an asynchronous subprocess.
-* Process Information:: Accessing run-status and other attributes.
-* Input to Processes:: Sending input to an asynchronous subprocess.
-* Signals to Processes:: Stopping, continuing or interrupting
- an asynchronous subprocess.
-* Output from Processes:: Collecting output from an asynchronous subprocess.
-* Sentinels:: Sentinels run when process run-status changes.
-* Network:: Opening network connections.
-
-Receiving Output from Processes
-
-* Process Buffers:: If no filter, output is put in a buffer.
-* Filter Functions:: Filter functions accept output from the process.
-* Accepting Output:: How to wait until process output arrives.
-
-Operating System Interface
-
-* Starting Up:: Customizing Emacs start-up processing.
-* Getting Out:: How exiting works (permanent or temporary).
-* System Environment:: Distinguish the name and kind of system.
-* Terminal Input:: Recording terminal input for debugging.
-* Terminal Output:: Recording terminal output for debugging.
-* Flow Control:: How to turn output flow control on or off.
-* Batch Mode:: Running Emacs without terminal interaction.
-
-Starting Up Emacs
-
-* Start-up Summary:: Sequence of actions Emacs performs at start-up.
-* Init File:: Details on reading the init file (@file{.emacs}).
-* Terminal-Specific:: How the terminal-specific Lisp file is read.
-* Command Line Arguments:: How command line arguments are processed,
- and how you can customize them.
-
-Getting out of Emacs
-
-* Killing Emacs:: Exiting Emacs irreversibly.
-* Suspending Emacs:: Exiting Emacs reversibly.
-
-Emacs Display
-
-* Refresh Screen:: Clearing the screen and redrawing everything on it.
-* Truncation:: Folding or wrapping long text lines.
-* The Echo Area:: Where messages are displayed.
-* Selective Display:: Hiding part of the buffer text.
-* Overlay Arrow:: Display of an arrow to indicate position.
-* Temporary Displays:: Displays that go away automatically.
-* Waiting:: Forcing display update and waiting for user.
-* Blinking:: How Emacs shows the matching open parenthesis.
-* Usual Display:: How control characters are displayed.
-* Beeping:: Audible signal to the user.
-* Window Systems:: Which window system is being used.
-
-GNU Emacs Internals
-
-* Building Emacs:: How to preload Lisp libraries into Emacs.
-* Pure Storage:: A kludge to make preloaded Lisp functions sharable.
-* Garbage Collection:: Reclaiming space for Lisp objects no longer used.
-* Object Internals:: Data formats of buffers, windows, processes.
-* Writing Emacs Primitives:: Writing C code for Emacs.
-
-Object Internals
-
-* Buffer Internals:: Components of a buffer structure.
-* Window Internals:: Components of a window structure.
-* Process Internals:: Components of a process structure.
-@end menu
-
-@c ================ Volume 1 ================
-
-@include intro.texi
-@include objects.texi
-@include numbers.texi
-@include strings.texi
-
-@include lists.texi
-@include sequences.texi
-@include symbols.texi
-@include eval.texi
-
-@include control.texi
-@include variables.texi
-@include functions.texi
-@include macros.texi
-
-@include loading.texi
-@include compile.texi
-@include debugging.texi
-@include streams.texi
-
-@include minibuf.texi
-@include commands.texi
-@include keymaps.texi
-@include modes.texi
-
-@c ================ Beginning of Volume 2 ================
-
-@c include help.texi
-@c include files.texi
-@c include backups.texi
-@c include buffers.texi
-
-@c include windows.texi
-@c include frames.texi
-@c include positions.texi
-@c include markers.texi
-@c include text.texi
-
-@c include searching.texi
-@c include syntax.texi
-@c include abbrevs.texi
-
-@c include processes.texi
-@c include os.texi
-@c include display.texi
-@c include calendar.texi
-
-@c MOVE to Emacs Manual: include misc-modes.texi
-
-@c appendices
-
-@c REMOVE this: include non-hacker.texi
-
-@c include tips.texi
-@c include internals.texi
-@c include errors.texi
-@c include locals.texi
-@c include maps.texi
-@c include hooks.texi
-@c include anti.texi
-
-@include index-vol1.texi
-
-@page
-@c Print the tables of contents
-@summarycontents
-@contents
-@c That's all
-
-@bye
-
-
-These words prevent "local variables" above from confusing Emacs.
diff --git a/lispref/elisp-vol2.texi b/lispref/elisp-vol2.texi
deleted file mode 100644
index d0aaba76925..00000000000
--- a/lispref/elisp-vol2.texi
+++ /dev/null
@@ -1,1046 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-@c %**start of header
-@setfilename elisp
-@settitle GNU Emacs Lisp Reference Manual: Volume 2
-@smallbook
-@c %**end of header
-
-
-@tex
-%%%% Experiment with smaller skip before sections and subsections.
-%%%% --rjc 30mar92
-
-\global\secheadingskip = 17pt plus 6pt minus 3pt
-\global\subsecheadingskip = 14pt plus 6pt minus 3pt
-
-% The defaults are:
-% \secheadingskip = 21pt plus 8pt minus 4pt
-% \subsecheadingskip = 17pt plus 8pt minus 4pt
-@end tex
-
-@finalout
-@c tex
-@c \overfullrule=0pt
-@c end tex
-
-@c Start volume 2 chapter numbering on chapter 21;
-@c this must be listed as chapno 20.
-@tex
-\global\chapno=20
-@end tex
-
-@c ================================================================
-@c Note: I was unable to figure out how to get .aux files copied
-@c properly in the time I had. Hence need to copy .aux file before
-@c running Tex. --rjc
-
-@tex
-
-\message{}
-\message{Redefining contents commands...}
-\message{}
-
-% Special @contents command
-
-% This inputs fixed up table of contents file rather than create new one.
-\global\def\contents{%
- \startcontents{Table of Contents}%
- \input elisp2-toc-ready.toc
- \endgroup
- \vfill \eject
-}
-
-% Special @summarycontents command
-% This inputs fixed up table of contents file rather than create new one.
-\global\def\summarycontents{%
- \startcontents{Short Contents}%
- %
- \let\chapentry = \shortchapentry
- \let\unnumbchapentry = \shortunnumberedentry
- % We want a true roman here for the page numbers.
- \secfonts
- \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
- \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 elisp2-toc-ready.toc
- \endgroup
- \vfill \eject
-}
-
-\message{}
-\message{Formatting special two volume edition...Volume 2...}
-\message{}
-@end tex
-@c ================================================================
-
-
-@c ==> This `elisp-small.texi' is a `smallbook' version of the manual.
-
-@c ==== Following are acceptable over and underfull hboxes in TeX ====
-
-@c -----
-@c [163] [164] [165] [166]) (loading.texi Chapter 13 [167] [168] [169]
-@c Overfull \hbox (20.5428pt too wide) in paragraph at lines 131--131
-@c []@ninett
-@c setenv EMAC-SLOAD-PATH .:/user/bil/emacs:/usr/local/lib/emacs/lisp[]
-@c -----
-@c (minibuf.texi Chapter 17 [206] [207] [208] [209] [210] [211] [212] [213]
-@c [214] [215]
-@c Overfull \hbox (2.09094pt too wide) in paragraph at lines 550--560
-@c @texttt map[] @textrm if @textsl require-match @textrm is
-@c @texttt nil[]@textrm , or else with the keymap @texttt minibuffer-
-@c -----
-@c (locals.texi Appendix @char 68 [533] [534]
-@c Underfull \hbox (badness 2512) in paragraph at lines 4--4
-@c []@chaprm Appendix DStandard Buffer-Local
-
-@c -------------------------------------------------------------------
-
-@c
-@c Combine indices.
-@synindex cp fn
-@syncodeindex vr fn
-@syncodeindex ky fn
-@syncodeindex pg fn
-@syncodeindex tp fn
-@c oops: texinfo-format-buffer ignores synindex
-@c
-
-@ifinfo
-This file documents GNU Emacs Lisp.
-
-@c The edition number appears in several places in this file
-@c and also in the file intro.texi.
-This is edition 2.4 of the GNU Emacs Lisp Reference
-Manual. It corresponds to Emacs Version 19.29.
-@c Please REMEMBER to update edition number in *four* places in this file
-@c and also in *one* place in ==> intro.texi <==
-@c huh? i only found three real places where the edition is stated, and
-@c one place where it is not stated explicitly ("this info file is newer
-@c than the foobar edition"). --mew 13sep93
-
-Published by the Free Software Foundation
-59 Temple Place, Suite 330
-Boston, MA 02111-1307 USA
-
-Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995 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.
-
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided also that the
-section entitled ``GNU General Public License'' is 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 section entitled ``GNU General Public License'' may be
-included in a translation approved by the Free Software Foundation
-instead of in the original English.
-@end ifinfo
-
-@setchapternewpage odd
-
-@iftex
-@shorttitlepage The GNU Emacs Lisp Reference Manual: Volume 2
-@end iftex
-@titlepage
-@sp 1
-@center @titlefont{The}
-@sp 1
-@center @titlefont{GNU Emacs Lisp}
-@sp 1
-@center @titlefont{Reference Manual}
-@sp 2
-@center GNU Emacs Version 19.29
-@center for Unix Users
-@sp 1
-@center Edition 2.4, June 1995
-@sp 2
-@center @titlefont{Volume 2}
-@sp 3
-@center by Bil Lewis, Dan LaLiberte,
-@center and the GNU Manual Group
-@page
-@vskip 0pt plus 1filll
-Copyright @copyright{} 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-@sp 2
-Edition 2.4 @*
-Revised for Emacs Version 19.29,@*
-June, 1995.@*
-@sp 2
-ISBN 1-882114-71-X
-
-@sp 2
-Published by the Free Software Foundation @*
-59 Temple Place, Suite 330 @*
-Boston, MA 02111-1307 USA
-
-@sp 1
-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
-section entitled ``GNU General Public License'' is 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 section entitled ``GNU General Public License'' may be
-included in a translation approved by the Free Software Foundation
-instead of in the original English.
-
-@sp 2
-Cover art by Etienne Suvasa.
-@end titlepage
-@page
-
-@node Top, Copying, (dir), (dir)
-
-@ifinfo
-This Info file contains edition 2.4 of the GNU Emacs Lisp Reference
-Manual, corresponding to GNU Emacs version 19.29.
-@end ifinfo
-
-@menu
-* Copying:: Conditions for copying and changing GNU Emacs.
-* Introduction:: Introduction and conventions used.
-
-* Lisp Data Types:: Data types of objects in Emacs Lisp.
-* Numbers:: Numbers and arithmetic functions.
-* Strings and Characters:: Strings, and functions that work on them.
-* Lists:: Lists, cons cells, and related functions.
-* Sequences Arrays Vectors:: Lists, strings and vectors are called sequences.
- Certain functions act on any kind of sequence.
- The description of vectors is here as well.
-* Symbols:: Symbols represent names, uniquely.
-
-* Evaluation:: How Lisp expressions are evaluated.
-* Control Structures:: Conditionals, loops, nonlocal exits.
-* Variables:: Using symbols in programs to stand for values.
-* Functions:: A function is a Lisp program
- that can be invoked from other functions.
-* Macros:: Macros are a way to extend the Lisp language.
-
-* Loading:: Reading files of Lisp code into Lisp.
-* Byte Compilation:: Compilation makes programs run faster.
-* Debugging:: Tools and tips for debugging Lisp programs.
-
-* Read and Print:: Converting Lisp objects to text and back.
-* Minibuffers:: Using the minibuffer to read input.
-* Command Loop:: How the editor command loop works,
- and how you can call its subroutines.
-* Keymaps:: Defining the bindings from keys to commands.
-* Modes:: Defining major and minor modes.
-* Documentation:: Writing and using documentation strings.
-
-* Files:: Accessing files.
-* Backups and Auto-Saving:: Controlling how backups and auto-save
- files are made.
-* Buffers:: Creating and using buffer objects.
-* Windows:: Manipulating windows and displaying buffers.
-* Frames:: Making multiple X windows.
-* Positions:: Buffer positions and motion functions.
-* Markers:: Markers represent positions and update
- automatically when the text is changed.
-
-* Text:: Examining and changing text in buffers.
-* Searching and Matching:: Searching buffers for strings or regexps.
-* Syntax Tables:: The syntax table controls word and list parsing.
-* Abbrevs:: How Abbrev mode works, and its data structures.
-
-* Processes:: Running and communicating with subprocesses.
-* System Interface:: Getting the user id, system type, environment
- variables, and other such things.
-* Display:: Parameters controlling screen usage.
- The bell. Waiting for input.
-* Calendar:: Customizing the calendar and diary.
-
-Appendices
-
-* Tips:: Advice for writing Lisp programs.
-* GNU Emacs Internals:: Building and dumping Emacs;
- internal data structures.
-* Standard Errors:: List of all error symbols.
-* Standard Buffer-Local Variables:: List of variables local in all buffers.
-* Standard Keymaps:: List of standard keymaps.
-* Standard Hooks:: List of standard hook variables.
-
-* Index:: Index including concepts, functions, variables,
- and other terms.
-
- --- The Detailed Node Listing ---
-
-Here are other nodes that are inferiors of those already listed,
-mentioned here so you can get to them in one step:
-
-Introduction
-
-* Caveats:: Flaws and a request for help.
-* Lisp History:: Emacs Lisp is descended from Maclisp.
-* Conventions:: How the manual is formatted.
-* Acknowledgements:: The authors, editors, and sponsors of this manual.
-
-Conventions
-
-* Some Terms:: Explanation of terms we use in this manual.
-* nil and t:: How the symbols @code{nil} and @code{t} are used.
-* Evaluation Notation:: The format we use for examples of evaluation.
-* Printing Notation:: The format we use for examples that print output.
-* Error Messages:: The format we use for examples of errors.
-* Buffer Text Notation:: The format we use for buffer contents in examples.
-* Format of Descriptions:: Notation for describing functions, variables, etc.
-
-Format of Descriptions
-
-* A Sample Function Description::
-* A Sample Variable Description::
-
-Lisp Data Types
-
-* Printed Representation:: How Lisp objects are represented as text.
-* Comments:: Comments and their formatting conventions.
-* Programming Types:: Types found in all Lisp systems.
-* Editing Types:: Types specific to Emacs.
-* Type Predicates:: Tests related to types.
-* Equality Predicates:: Tests of equality between any two objects.
-
-Programming Types
-
-* Integer Type:: Numbers without fractional parts.
-* Floating Point Type:: Numbers with fractional parts and with a large range.
-* Character Type:: The representation of letters, numbers and
- control characters.
-* Sequence Type:: Both lists and arrays are classified as sequences.
-* Cons Cell Type:: Cons cells, and lists (which are made from cons cells).
-* Array Type:: Arrays include strings and vectors.
-* String Type:: An (efficient) array of characters.
-* Vector Type:: One-dimensional arrays.
-* Symbol Type:: A multi-use object that refers to a function,
- variable, property list, or itself.
-* Function Type:: A piece of executable code you can call from elsewhere.
-* Macro Type:: A method of expanding an expression into another
- expression, more fundamental but less pretty.
-* Primitive Function Type:: A function written in C, callable from Lisp.
-* Byte-Code Type:: A function written in Lisp, then compiled.
-* Autoload Type:: A type used for automatically loading seldom-used
- functions.
-
-List Type
-
-* Dotted Pair Notation:: An alternative syntax for lists.
-* Association List Type:: A specially constructed list.
-
-Editing Types
-
-* Buffer Type:: The basic object of editing.
-* Window Type:: What makes buffers visible.
-* Window Configuration Type::Save what the screen looks like.
-* Marker Type:: A position in a buffer.
-* Process Type:: A process running on the underlying OS.
-* Stream Type:: Receive or send characters.
-* Keymap Type:: What function a keystroke invokes.
-* Syntax Table Type:: What a character means.
-
-Numbers
-
-* Integer Basics:: Representation and range of integers.
-* Float Basics:: Representation and range of floating point.
-* Predicates on Numbers:: Testing for numbers.
-* Comparison of Numbers:: Equality and inequality predicates.
-* Arithmetic Operations:: How to add, subtract, multiply and divide.
-* Bitwise Operations:: Logical and, or, not, shifting.
-* Numeric Conversions:: Converting float to integer and vice versa.
-* Math Functions:: Trig, exponential and logarithmic functions.
-* Random Numbers:: Obtaining random integers, predictable or not.
-
-Strings and Characters
-
-* String Basics:: Basic properties of strings and characters.
-* Predicates for Strings:: Testing whether an object is a string or char.
-* Creating Strings:: Functions to allocate new strings.
-* Text Comparison:: Comparing characters or strings.
-* String Conversion:: Converting characters or strings and vice versa.
-* Formatting Strings:: @code{format}: Emacs's analog of @code{printf}.
-* Character Case:: Case conversion functions.
-
-Lists
-
-* Cons Cells:: How lists are made out of cons cells.
-* Lists as Boxes:: Graphical notation to explain lists.
-* List-related Predicates:: Is this object a list? Comparing two lists.
-* List Elements:: Extracting the pieces of a list.
-* Building Lists:: Creating list structure.
-* Modifying Lists:: Storing new pieces into an existing list.
-* Sets And Lists:: A list can represent a finite mathematical set.
-* Association Lists:: A list can represent a finite relation or mapping.
-
-Modifying Existing List Structure
-
-* Setcar:: Replacing an element in a list.
-* Setcdr:: Replacing part of the list backbone.
- This can be used to remove or add elements.
-* Rearrangement:: Reordering the elements in a list; combining lists.
-
-Sequences, Arrays, and Vectors
-
-* Sequence Functions:: Functions that accept any kind of sequence.
-* Arrays:: Characteristics of arrays in Emacs Lisp.
-* Array Functions:: Functions specifically for arrays.
-* Vectors:: Functions specifically for vectors.
-
-Symbols
-
-* Symbol Components:: Symbols have names, values, function definitions
- and property lists.
-* Definitions:: A definition says how a symbol will be used.
-* Creating Symbols:: How symbols are kept unique.
-* Property Lists:: Each symbol has a property list
- for recording miscellaneous information.
-
-Evaluation
-
-* Intro Eval:: Evaluation in the scheme of things.
-* Eval:: How to invoke the Lisp interpreter explicitly.
-* Forms:: How various sorts of objects are evaluated.
-* Quoting:: Avoiding evaluation (to put constants in
- the program).
-
-Kinds of Forms
-
-* Self-Evaluating Forms:: Forms that evaluate to themselves.
-* Symbol Forms:: Symbols evaluate as variables.
-* Classifying Lists:: How to distinguish various sorts of list forms.
-* Function Forms:: Forms that call functions.
-* Macro Forms:: Forms that call macros.
-* Special Forms:: ``Special forms'' are idiosyncratic primitives,
- most of them extremely important.
-* Autoloading:: Functions set up to load files
- containing their real definitions.
-
-Control Structures
-
-* Sequencing:: Evaluation in textual order.
-* Conditionals:: @code{if}, @code{cond}.
-* Combining Conditions:: @code{and}, @code{or}, @code{not}.
-* Iteration:: @code{while} loops.
-* Nonlocal Exits:: Jumping out of a sequence.
-
-Nonlocal Exits
-
-* Catch and Throw:: Nonlocal exits for the program's own purposes.
-* Examples of Catch:: Showing how such nonlocal exits can be written.
-* Errors:: How errors are signaled and handled.
-* Cleanups:: Arranging to run a cleanup form if an
- error happens.
-
-Errors
-
-* Signaling Errors:: How to report an error.
-* Processing of Errors:: What Emacs does when you report an error.
-* Handling Errors:: How you can trap errors and continue execution.
-* Error Symbols:: How errors are classified for trapping them.
-
-Variables
-
-* Global Variables:: Variable values that exist permanently, everywhere.
-* Constant Variables:: Certain "variables" have values that never change.
-* Local Variables:: Variable values that exist only temporarily.
-* Void Variables:: Symbols that lack values.
-* Defining Variables:: A definition says a symbol is used as a variable.
-* Accessing Variables:: Examining values of variables whose names
- are known only at run time.
-* Setting Variables:: Storing new values in variables.
-* Variable Scoping:: How Lisp chooses among local and global values.
-* Buffer-Local Variables:: Variable values in effect only in one buffer.
-
-Scoping Rules for Variable Bindings
-
-* Scope:: Scope means where in the program a value
- is visible. Comparison with other languages.
-* Extent:: Extent means how long in time a value exists.
-* Impl of Scope:: Two ways to implement dynamic scoping.
-* Using Scoping:: How to use dynamic scoping carefully and
- avoid problems.
-
-Buffer-Local Variables
-
-* Intro to Buffer-Local:: Introduction and concepts.
-* Creating Buffer-Local:: Creating and destroying buffer-local bindings.
-* Default Value:: The default value is seen in buffers
- that don't have their own local values.
-
-Functions
-
-* What Is a Function:: Lisp functions vs primitives; terminology.
-* Lambda Expressions:: How functions are expressed as Lisp objects.
-* Function Names:: A symbol can serve as the name of a function.
-* Defining Functions:: Lisp expressions for defining functions.
-* Calling Functions:: How to use an existing function.
-* Mapping Functions:: Applying a function to each element of a list, etc.
-* Anonymous Functions:: Lambda-expressions are functions with no names.
-* Function Cells:: Accessing or setting the function definition
- of a symbol.
-* Related Topics:: Cross-references to specific Lisp primitives
- that have a special bearing on how
- functions work.
-
-Lambda Expressions
-
-* Lambda Components:: The parts of a lambda expression.
-* Simple Lambda:: A simple example.
-* Argument List:: Details and special features of argument lists.
-* Function Documentation:: How to put documentation in a function.
-
-Macros
-
-* Simple Macro:: A basic example.
-* Expansion:: How, when and why macros are expanded.
-* Compiling Macros:: How macros are expanded by the compiler.
-* Defining Macros:: How to write a macro definition.
-* Backquote:: Easier construction of list structure.
-* Problems with Macros:: Don't evaluate the macro arguments too many times.
- Don't hide the user's variables.
-
-Loading
-
-* How Programs Do Loading:: The @code{load} function and others.
-* Autoload:: Setting up a function to autoload.
-* Named Features:: Loading a library if it isn't already loaded.
-* Repeated Loading:: Precautions about loading a file twice.
-
-Byte Compilation
-
-* Compilation Functions:: Byte compilation functions.
-* Disassembly:: Disassembling byte-code; how to read byte-code.
-
-Debugging Lisp Programs
-
-* Debugger:: How the Emacs Lisp debugger is implemented.
-* Syntax Errors:: How to find syntax errors.
-* Compilation Errors:: How to find errors that show up in
- byte compilation.
-* Edebug:: A source-level Emacs Lisp debugger.
-
-The Lisp Debugger
-
-* Error Debugging:: Entering the debugger when an error happens.
-* Function Debugging:: Entering it when a certain function is called.
-* Explicit Debug:: Entering it at a certain point in the program.
-* Using Debugger:: What the debugger does; what you see while in it.
-* Debugger Commands:: Commands used while in the debugger.
-* Invoking the Debugger:: How to call the function @code{debug}.
-* Internals of Debugger:: Subroutines of the debugger, and global variables.
-
-Debugging Invalid Lisp Syntax
-
-* Excess Open:: How to find a spurious open paren or missing close.
-* Excess Close:: How to find a spurious close paren or missing open.
-
-Reading and Printing Lisp Objects
-
-* Streams Intro:: Overview of streams, reading and printing.
-* Input Streams:: Various data types that can be used as
- input streams.
-* Input Functions:: Functions to read Lisp objects from text.
-* Output Streams:: Various data types that can be used as
- output streams.
-* Output Functions:: Functions to print Lisp objects as text.
-
-Minibuffers
-
-* Intro to Minibuffers:: Basic information about minibuffers.
-* Text from Minibuffer:: How to read a straight text string.
-* Object from Minibuffer:: How to read a Lisp object or expression.
-* Completion:: How to invoke and customize completion.
-* Yes-or-No Queries:: Asking a question with a simple answer.
-* Minibuffer Misc:: Various customization hooks and variables.
-
-Completion
-
-* Basic Completion:: Low-level functions for completing strings.
- (These are too low level to use the minibuffer.)
-* Minibuffer Completion:: Invoking the minibuffer with completion.
-* Completion Commands:: Minibuffer commands that do completion.
-* High-Level Completion:: Convenient special cases of completion
- (reading buffer name, file name, etc.)
-* Reading File Names:: Using completion to read file names.
-* Programmed Completion:: Finding the completions for a given file name.
-
-Command Loop
-
-* Command Overview:: How the command loop reads commands.
-* Defining Commands:: Specifying how a function should read arguments.
-* Interactive Call:: Calling a command, so that it will read arguments.
-* Command Loop Info:: Variables set by the command loop for you to examine.
-* Input Events:: What input looks like when you read it.
-* Reading Input:: How to read input events from the keyboard or mouse.
-* Waiting:: Waiting for user input or elapsed time.
-* Quitting:: How @kbd{C-g} works. How to catch or defer quitting.
-* Prefix Command Arguments:: How the commands to set prefix args work.
-* Recursive Editing:: Entering a recursive edit,
- and why you usually shouldn't.
-* Disabling Commands:: How the command loop handles disabled commands.
-* Command History:: How the command history is set up, and how accessed.
-* Keyboard Macros:: How keyboard macros are implemented.
-
-Defining Commands
-
-* Using Interactive:: General rules for @code{interactive}.
-* Interactive Codes:: The standard letter-codes for reading arguments
- in various ways.
-* Interactive Examples:: Examples of how to read interactive arguments.
-
-Keymaps
-
-* Keymap Terminology:: Definitions of terms pertaining to keymaps.
-* Format of Keymaps:: What a keymap looks like as a Lisp object.
-* Creating Keymaps:: Functions to create and copy keymaps.
-* Inheritance and Keymaps:: How one keymap can inherit the bindings
- of another keymap.
-* Prefix Keys:: Defining a key with a keymap as its definition.
-* Menu Keymaps:: A keymap can define a menu for X windows
- or for use from the terminal.
-* Active Keymaps:: Each buffer has a local keymap
- to override the standard (global) bindings.
- Each minor mode can also override them.
-* Key Lookup:: How extracting elements from keymaps works.
-* Functions for Key Lookup:: How to request key lookup.
-* Changing Key Bindings:: Redefining a key in a keymap.
-* Key Binding Commands:: Interactive interfaces for redefining keys.
-* Scanning Keymaps:: Looking through all keymaps, for printing help.
-
-Major and Minor Modes
-
-* Major Modes:: Defining major modes.
-* Minor Modes:: Defining minor modes.
-* Mode Line Format:: Customizing the text that appears in the mode line.
-* Hooks:: How to use hooks; how to write code that
- provides hooks.
-
-Major Modes
-
-* Major Mode Conventions:: Coding conventions for keymaps, etc.
-* Example Major Modes:: Text mode and Lisp modes.
-* Auto Major Mode:: How Emacs chooses the major mode automatically.
-* Mode Help:: Finding out how to use a mode.
-
-Minor Modes
-
-* Minor Mode Conventions:: Tips for writing a minor mode.
-* Keymaps and Minor Modes:: How a minor mode can have its own keymap.
-
-Mode Line Format
-
-* Mode Line Data:: The data structure that controls the mode line.
-* Mode Line Variables:: Variables used in that data structure.
-* %-Constructs:: Putting information into a mode line.
-
-Documentation
-
-* Documentation Basics:: Good style for doc strings.
- Where to put them. How Emacs stores them.
-* Accessing Documentation:: How Lisp programs can access doc strings.
-* Keys in Documentation:: Substituting current key bindings.
-* Describing Characters:: Making printable descriptions of
- non-printing characters and key sequences.
-* Help Functions:: Subroutines used by Emacs help facilities.
-
-Files
-
-* Visiting Files:: Reading files into Emacs buffers for editing.
-* Saving Buffers:: Writing changed buffers back into files.
-* Reading from Files:: Reading files into other buffers.
-* Writing to Files:: Writing new files from parts of buffers.
-* File Locks:: Locking and unlocking files, to prevent
- simultaneous editing by two people.
-* Information about Files:: Testing existence, accessibility, size of files.
-* Contents of Directories:: Getting a list of the files in a directory.
-* Changing File Attributes:: Renaming files, changing protection, etc.
-* File Names:: Decomposing and expanding file names.
-
-Visiting Files
-
-* Visiting Functions:: The usual interface functions for visiting.
-* Subroutines of Visiting:: Lower-level subroutines that they use.
-
-Information about Files
-
-* Testing Accessibility:: Is a given file readable? Writable?
-* Kinds of Files:: Is it a directory? A link?
-* File Attributes:: How large is it? Any other names? Etc.
-
-File Names
-
-* File Name Components:: The directory part of a file name, and the rest.
-* Directory Names:: A directory's name as a directory
- is different from its name as a file.
-* Relative File Names:: Some file names are relative to a
- current directory.
-* File Name Expansion:: Converting relative file names to absolute ones.
-* Unique File Names:: Generating names for temporary files.
-* File Name Completion:: Finding the completions for a given file name.
-
-Backups and Auto-Saving
-
-* Backup Files:: How backup files are made; how their names
- are chosen.
-* Auto-Saving:: How auto-save files are made; how their
- names are chosen.
-* Reverting:: @code{revert-buffer}, and how to customize
- what it does.
-
-Backup Files
-
-* Making Backups:: How Emacs makes backup files, and when.
-* Rename or Copy:: Two alternatives: renaming the old file
- or copying it.
-* Numbered Backups:: Keeping multiple backups for each source file.
-* Backup Names:: How backup file names are computed; customization.
-
-Buffers
-
-* Buffer Basics:: What is a buffer?
-* Buffer Names:: Accessing and changing buffer names.
-* Buffer File Name:: The buffer file name indicates which file
- is visited.
-* Buffer Modification:: A buffer is @dfn{modified} if it needs to be saved.
-* Modification Time:: Determining whether the visited file was changed
- ``behind Emacs's back''.
-* Read Only Buffers:: Modifying text is not allowed in a
- read-only buffer.
-* The Buffer List:: How to look at all the existing buffers.
-* Creating Buffers:: Functions that create buffers.
-* Killing Buffers:: Buffers exist until explicitly killed.
-* Current Buffer:: Designating a buffer as current
- so primitives will access its contents.
-
-Windows
-
-* Basic Windows:: Basic information on using windows.
-* Splitting Windows:: Splitting one window into two windows.
-* Deleting Windows:: Deleting a window gives its space to other windows.
-* Selecting Windows:: The selected window is the one that you edit in.
-* Cyclic Window Ordering:: Moving around the existing windows.
-* Buffers and Windows:: Each window displays the contents of a buffer.
-* Displaying Buffers:: Higher-lever functions for displaying a buffer
- and choosing a window for it.
-* Window Point:: Each window has its own location of point.
-* Window Start:: The display-start position controls which text
- is on-screen in the window.
-* Vertical Scrolling:: Moving text up and down in the window.
-* Horizontal Scrolling:: Moving text sideways on the window.
-* Size of Window:: Accessing the size of a window.
-* Resizing Windows:: Changing the size of a window.
-* Window Configurations:: Saving and restoring the state of the screen.
-
-Frames
-
-* Creating Frames:: Creating additional frames.
-* Multiple Displays:: Creating frames on other X displays.
-* Frame Parameters:: Controlling frame size, position, font, etc.
-* Frame Titles:: Automatic updating of frame titles.
-* Deleting Frames:: Frames last until explicitly deleted.
-* Finding All Frames:: How to examine all existing frames.
-* Frames and Windows:: A frame contains windows;
- display of text always works through windows.
-* Minibuffers and Frames:: How a frame finds the minibuffer to use.
-* Input Focus:: Specifying the selected frame.
-* Visibility of Frames:: Frames may be visible or invisible, or icons.
-* Raising and Lowering:: Raising a frame makes it hide other X windows;
- lowering it makes the others hide them.
-* Frame Configurations:: Saving the state of all frames.
-* Mouse Tracking:: Getting events that say when the mouse moves.
-* Mouse Position:: Asking where the mouse is, or moving it.
-* Pop-Up Menus:: Displaying a menu for the user to select from.
-* Dialog Boxes:: Displaying a box to ask yes or no.
-* Pointer Shapes:: Specifying the shape of the mouse pointer.
-* X Selections:: Transferring text to and from other X clients.
-* Color Names:: Getting the definitions of color names.
-* Resources:: Getting resource values from the server.
-* Server Data:: Getting info about the X server.
-
-Positions
-
-* Point:: The special position where editing takes place.
-* Motion:: Changing point.
-* Excursions:: Temporary motion and buffer changes.
-* Narrowing:: Restricting editing to a portion of the buffer.
-
-Motion
-
-* Character Motion:: Moving in terms of characters.
-* Word Motion:: Moving in terms of words.
-* Buffer End Motion:: Moving to the beginning or end of the buffer.
-* Text Lines:: Moving in terms of lines of text.
-* Screen Lines:: Moving in terms of lines as displayed.
-* List Motion:: Moving by parsing lists and sexps.
-* Skipping Characters:: Skipping characters belonging to a certain set.
-
-Markers
-
-* Overview of Markers:: The components of a marker, and how it relocates.
-* Predicates on Markers:: Testing whether an object is a marker.
-* Creating Markers:: Making empty markers or markers at certain places.
-* Information from Markers:: Finding the marker's buffer or character
- position.
-* Changing Markers:: Moving the marker to a new buffer or position.
-* The Mark:: How ``the mark'' is implemented with a marker.
-* The Region:: How to access ``the region''.
-
-Text
-
-* Near Point:: Examining text in the vicinity of point.
-* Buffer Contents:: Examining text in a general fashion.
-* Insertion:: Adding new text to a buffer.
-* Commands for Insertion:: User-level commands to insert text.
-* Deletion:: Removing text from a buffer.
-* User-Level Deletion:: User-level commands to delete text.
-* The Kill Ring:: Where removed text sometimes is saved for
- later use.
-* Undo:: Undoing changes to the text of a buffer.
-* Auto Filling:: How auto-fill mode is implemented to break lines.
-* Filling:: Functions for explicit filling.
-* Margins:: How to specify margins for filling commands.
-* Sorting:: Functions for sorting parts of the buffer.
-* Indentation:: Functions to insert or adjust indentation.
-* Columns:: Computing horizontal positions, and using them.
-* Case Changes:: Case conversion of parts of the buffer.
-* Substitution:: Replacing a given character wherever it appears.
-* Registers:: How registers are implemented. Accessing
- the text or position stored in a register.
-
-The Kill Ring
-
-* Kill Ring Concepts:: What text looks like in the kill ring.
-* Kill Functions:: Functions that kill text.
-* Yank Commands:: Commands that access the kill ring.
-* Low-Level Kill Ring:: Functions and variables for kill ring access.
-* Internals of Kill Ring:: Variables that hold kill-ring data.
-
-Indentation
-
-* Primitive Indent:: Functions used to count and insert indentation.
-* Mode-Specific Indent:: Customize indentation for different modes.
-* Region Indent:: Indent all the lines in a region.
-* Relative Indent:: Indent the current line based on previous lines.
-* Indent Tabs:: Adjustable, typewriter-like tab stops.
-* Motion by Indent:: Move to first non-blank character.
-
-Searching and Matching
-
-* String Search:: Search for an exact match.
-* Regular Expressions:: Describing classes of strings.
-* Regexp Search:: Searching for a match for a regexp.
-* Match Data:: Finding out which part of the text matched
- various parts of a regexp, after regexp search.
-* Saving Match Data:: Saving and restoring this information.
-* Standard Regexps:: Useful regexps for finding sentences, pages,...
-* Searching and Case:: Case-independent or case-significant searching.
-
-Regular Expressions
-
-* Syntax of Regexps:: Rules for writing regular expressions.
-* Regexp Example:: Illustrates regular expression syntax.
-
-Syntax Tables
-
-* Syntax Descriptors:: How characters are classified.
-* Syntax Table Functions:: How to create, examine and alter syntax tables.
-* Parsing Expressions:: Parsing balanced expressions
- using the syntax table.
-* Standard Syntax Tables:: Syntax tables used by various major modes.
-* Syntax Table Internals:: How syntax table information is stored.
-
-Syntax Descriptors
-
-* Syntax Class Table:: Table of syntax classes.
-* Syntax Flags:: Additional flags each character can have.
-
-Abbrevs And Abbrev Expansion
-
-* Abbrev Mode:: Setting up Emacs for abbreviation.
-* Tables: Abbrev Tables. Creating and working with abbrev tables.
-* Defining Abbrevs:: Specifying abbreviations and their expansions.
-* Files: Abbrev Files. Saving abbrevs in files.
-* Expansion: Abbrev Expansion. Controlling expansion; expansion subroutines.
-* Standard Abbrev Tables:: Abbrev tables used by various major modes.
-
-Processes
-
-* Subprocess Creation:: Functions that start subprocesses.
-* Synchronous Processes:: Details of using synchronous subprocesses.
-* Asynchronous Processes:: Starting up an asynchronous subprocess.
-* Deleting Processes:: Eliminating an asynchronous subprocess.
-* Process Information:: Accessing run-status and other attributes.
-* Input to Processes:: Sending input to an asynchronous subprocess.
-* Signals to Processes:: Stopping, continuing or interrupting
- an asynchronous subprocess.
-* Output from Processes:: Collecting output from an asynchronous subprocess.
-* Sentinels:: Sentinels run when process run-status changes.
-* Network:: Opening network connections.
-
-Receiving Output from Processes
-
-* Process Buffers:: If no filter, output is put in a buffer.
-* Filter Functions:: Filter functions accept output from the process.
-* Accepting Output:: How to wait until process output arrives.
-
-Operating System Interface
-
-* Starting Up:: Customizing Emacs start-up processing.
-* Getting Out:: How exiting works (permanent or temporary).
-* System Environment:: Distinguish the name and kind of system.
-* Terminal Input:: Recording terminal input for debugging.
-* Terminal Output:: Recording terminal output for debugging.
-* Flow Control:: How to turn output flow control on or off.
-* Batch Mode:: Running Emacs without terminal interaction.
-
-Starting Up Emacs
-
-* Start-up Summary:: Sequence of actions Emacs performs at start-up.
-* Init File:: Details on reading the init file (@file{.emacs}).
-* Terminal-Specific:: How the terminal-specific Lisp file is read.
-* Command Line Arguments:: How command line arguments are processed,
- and how you can customize them.
-
-Getting out of Emacs
-
-* Killing Emacs:: Exiting Emacs irreversibly.
-* Suspending Emacs:: Exiting Emacs reversibly.
-
-Emacs Display
-
-* Refresh Screen:: Clearing the screen and redrawing everything on it.
-* Truncation:: Folding or wrapping long text lines.
-* The Echo Area:: Where messages are displayed.
-* Selective Display:: Hiding part of the buffer text.
-* Overlay Arrow:: Display of an arrow to indicate position.
-* Temporary Displays:: Displays that go away automatically.
-* Waiting:: Forcing display update and waiting for user.
-* Blinking:: How Emacs shows the matching open parenthesis.
-* Usual Display:: How control characters are displayed.
-* Beeping:: Audible signal to the user.
-* Window Systems:: Which window system is being used.
-
-GNU Emacs Internals
-
-* Building Emacs:: How to preload Lisp libraries into Emacs.
-* Pure Storage:: A kludge to make preloaded Lisp functions sharable.
-* Garbage Collection:: Reclaiming space for Lisp objects no longer used.
-* Object Internals:: Data formats of buffers, windows, processes.
-* Writing Emacs Primitives:: Writing C code for Emacs.
-
-Object Internals
-
-* Buffer Internals:: Components of a buffer structure.
-* Window Internals:: Components of a window structure.
-* Process Internals:: Components of a process structure.
-@end menu
-
-@c ================ Volume 1 ================
-
-@c include intro.texi
-@c include objects.texi
-@c include numbers.texi
-@c include strings.texi
-
-@c include lists.texi
-@c include sequences.texi
-@c include symbols.texi
-@c include eval.texi
-
-@c include control.texi
-@c include variables.texi
-@c include functions.texi
-@c include macros.texi
-
-@c include loading.texi
-@c include compile.texi
-@c include debugging.texi
-@c include streams.texi
-
-@c include minibuf.texi
-@c include commands.texi
-@c include keymaps.texi
-@c include modes.texi
-
-@c ================ Beginning of Volume 2 ================
-
-@include help.texi
-@include files.texi
-@include backups.texi
-@include buffers.texi
-
-@include windows.texi
-@include frames.texi
-@include positions.texi
-@include markers.texi
-@include text.texi
-
-@include searching.texi
-@include syntax.texi
-@include abbrevs.texi
-
-@include processes.texi
-@include os.texi
-@include display.texi
-@include calendar.texi
-
-@c MOVE to Emacs Manual: include misc-modes.texi
-
-@c appendices
-
-@c REMOVE this: include non-hacker.texi
-
-@include tips.texi
-@include internals.texi
-@include errors.texi
-@include locals.texi
-@include maps.texi
-@include hooks.texi
-
-@include index-vol2.texi
-
-@page
-@c Print the tables of contents
-@summarycontents
-@contents
-@c That's all
-
-@bye
-
-
-These words prevent "local variables" above from confusing Emacs.
diff --git a/lispref/elisp.texi b/lispref/elisp.texi
deleted file mode 100644
index adb16771ebf..00000000000
--- a/lispref/elisp.texi
+++ /dev/null
@@ -1,942 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-@c %**start of header
-@setfilename elisp
-@settitle GNU Emacs Lisp Reference Manual
-@c %**end of header
-
-@ifinfo
-This version is the edition 2.4.2 of the GNU Emacs Lisp
-Reference Manual. It corresponds to Emacs Version 19.34.
-@c Please REMEMBER to update edition number in *four* places in this file
-@c and also in *one* place in intro.texi
-
-Published by the Free Software Foundation
-59 Temple Place, Suite 330
-Boston, MA 02111-1307 USA
-
-Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996 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.
-
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided also that the
-section entitled ``GNU General Public License'' is 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 section entitled ``GNU General Public License'' may be
-included in a translation approved by the Free Software Foundation
-instead of in the original English.
-@end ifinfo
-
-@c Combine indices.
-@synindex cp fn
-@syncodeindex vr fn
-@syncodeindex ky fn
-@syncodeindex pg fn
-@syncodeindex tp fn
-
-@setchapternewpage odd
-@finalout
-
-@titlepage
-@title GNU Emacs Lisp Reference Manual
-@subtitle GNU Emacs Version 19
-@subtitle for Unix Users
-@c The edition number appears in several places in this file
-@c and also in the file intro.texi.
-@subtitle Revision 2.4.2, December 1996
-
-@author by Bil Lewis, Dan LaLiberte, Richard Stallman
-@author and the GNU Manual Group
-@page
-@vskip 0pt plus 1filll
-Copyright @copyright{} 1990, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
-@sp 2
-Edition 2.4.2 @*
-Revised for Emacs Version 19.34,@*
-July 1996.@*
-@sp 2
-ISBN 1-882114-71-X
-
-@sp 2
-Published by the Free Software Foundation @*
-59 Temple Place, Suite 330@*
-Boston, MA 02111-1307 USA
-
-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
-section entitled ``GNU General Public License'' is 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 section entitled ``GNU General Public License'' may be
-included in a translation approved by the Free Software Foundation
-instead of in the original English.
-
-Cover art by Etienne Suvasa.
-@end titlepage
-@page
-
-@node Top, Copying, (dir), (dir)
-
-@ifinfo
-This Info file contains edition 2.4.2 of the GNU Emacs Lisp
-Reference Manual, corresponding to GNU Emacs version 19.34.
-@end ifinfo
-
-@menu
-* Copying:: Conditions for copying and changing GNU Emacs.
-* Introduction:: Introduction and conventions used.
-
-* Lisp Data Types:: Data types of objects in Emacs Lisp.
-* Numbers:: Numbers and arithmetic functions.
-* Strings and Characters:: Strings, and functions that work on them.
-* Lists:: Lists, cons cells, and related functions.
-* Sequences Arrays Vectors:: Lists, strings and vectors are called sequences.
- Certain functions act on any kind of sequence.
- The description of vectors is here as well.
-* Symbols:: Symbols represent names, uniquely.
-
-* Evaluation:: How Lisp expressions are evaluated.
-* Control Structures:: Conditionals, loops, nonlocal exits.
-* Variables:: Using symbols in programs to stand for values.
-* Functions:: A function is a Lisp program
- that can be invoked from other functions.
-* Macros:: Macros are a way to extend the Lisp language.
-
-* Loading:: Reading files of Lisp code into Lisp.
-* Byte Compilation:: Compilation makes programs run faster.
-* Debugging:: Tools and tips for debugging Lisp programs.
-
-* Read and Print:: Converting Lisp objects to text and back.
-* Minibuffers:: Using the minibuffer to read input.
-* Command Loop:: How the editor command loop works,
- and how you can call its subroutines.
-* Keymaps:: Defining the bindings from keys to commands.
-* Modes:: Defining major and minor modes.
-* Documentation:: Writing and using documentation strings.
-
-* Files:: Accessing files.
-* Backups and Auto-Saving:: Controlling how backups and auto-save
- files are made.
-* Buffers:: Creating and using buffer objects.
-* Windows:: Manipulating windows and displaying buffers.
-* Frames:: Making multiple X windows.
-* Positions:: Buffer positions and motion functions.
-* Markers:: Markers represent positions and update
- automatically when the text is changed.
-
-* Text:: Examining and changing text in buffers.
-* Searching and Matching:: Searching buffers for strings or regexps.
-* Syntax Tables:: The syntax table controls word and list parsing.
-* Abbrevs:: How Abbrev mode works, and its data structures.
-
-* Processes:: Running and communicating with subprocesses.
-* System Interface:: Getting the user id, system type, environment
- variables, and other such things.
-* Display:: Parameters controlling screen usage.
- The bell. Waiting for input.
-* Calendar:: Customizing the calendar and diary.
-
-Appendices
-
-* Tips:: Advice for writing Lisp programs.
-* GNU Emacs Internals:: Building and dumping Emacs;
- internal data structures.
-* Standard Errors:: List of all error symbols.
-* Standard Buffer-Local Variables:: List of variables local in all buffers.
-* Standard Keymaps:: List of standard keymaps.
-* Standard Hooks:: List of standard hook variables.
-
-* Index:: Index including concepts, functions, variables,
- and other terms.
-
- --- The Detailed Node Listing ---
-
-Here are other nodes that are inferiors of those already listed,
-mentioned here so you can get to them in one step:
-
-Introduction
-
-* Caveats:: Flaws and a request for help.
-* Lisp History:: Emacs Lisp is descended from Maclisp.
-* Conventions:: How the manual is formatted.
-* Acknowledgements:: The authors, editors, and sponsors of this manual.
-
-Conventions
-
-* Some Terms:: Explanation of terms we use in this manual.
-* nil and t:: How the symbols @code{nil} and @code{t} are used.
-* Evaluation Notation:: The format we use for examples of evaluation.
-* Printing Notation:: The format we use for examples that print output.
-* Error Messages:: The format we use for examples of errors.
-* Buffer Text Notation:: The format we use for buffer contents in examples.
-* Format of Descriptions:: Notation for describing functions, variables, etc.
-
-Format of Descriptions
-
-* A Sample Function Description::
-* A Sample Variable Description::
-
-Lisp Data Types
-
-* Printed Representation:: How Lisp objects are represented as text.
-* Comments:: Comments and their formatting conventions.
-* Programming Types:: Types found in all Lisp systems.
-* Editing Types:: Types specific to Emacs.
-* Type Predicates:: Tests related to types.
-* Equality Predicates:: Tests of equality between any two objects.
-
-Programming Types
-
-* Integer Type:: Numbers without fractional parts.
-* Floating Point Type:: Numbers with fractional parts and with a large range.
-* Character Type:: The representation of letters, numbers and
- control characters.
-* Sequence Type:: Both lists and arrays are classified as sequences.
-* Cons Cell Type:: Cons cells, and lists (which are made from cons cells).
-* Array Type:: Arrays include strings and vectors.
-* String Type:: An (efficient) array of characters.
-* Vector Type:: One-dimensional arrays.
-* Symbol Type:: A multi-use object that refers to a function,
- variable, property list, or itself.
-* Function Type:: A piece of executable code you can call from elsewhere.
-* Macro Type:: A method of expanding an expression into another
- expression, more fundamental but less pretty.
-* Primitive Function Type:: A function written in C, callable from Lisp.
-* Byte-Code Type:: A function written in Lisp, then compiled.
-* Autoload Type:: A type used for automatically loading seldom-used
- functions.
-
-List Type
-
-* Dotted Pair Notation:: An alternative syntax for lists.
-* Association List Type:: A specially constructed list.
-
-Editing Types
-
-* Buffer Type:: The basic object of editing.
-* Window Type:: What makes buffers visible.
-* Window Configuration Type::Save what the screen looks like.
-* Marker Type:: A position in a buffer.
-* Process Type:: A process running on the underlying OS.
-* Stream Type:: Receive or send characters.
-* Keymap Type:: What function a keystroke invokes.
-* Syntax Table Type:: What a character means.
-
-Numbers
-
-* Integer Basics:: Representation and range of integers.
-* Float Basics:: Representation and range of floating point.
-* Predicates on Numbers:: Testing for numbers.
-* Comparison of Numbers:: Equality and inequality predicates.
-* Arithmetic Operations:: How to add, subtract, multiply and divide.
-* Bitwise Operations:: Logical and, or, not, shifting.
-* Numeric Conversions:: Converting float to integer and vice versa.
-* Math Functions:: Trig, exponential and logarithmic functions.
-* Random Numbers:: Obtaining random integers, predictable or not.
-
-Strings and Characters
-
-* String Basics:: Basic properties of strings and characters.
-* Predicates for Strings:: Testing whether an object is a string or char.
-* Creating Strings:: Functions to allocate new strings.
-* Text Comparison:: Comparing characters or strings.
-* String Conversion:: Converting characters or strings and vice versa.
-* Formatting Strings:: @code{format}: Emacs's analog of @code{printf}.
-* Character Case:: Case conversion functions.
-
-Lists
-
-* Cons Cells:: How lists are made out of cons cells.
-* Lists as Boxes:: Graphical notation to explain lists.
-* List-related Predicates:: Is this object a list? Comparing two lists.
-* List Elements:: Extracting the pieces of a list.
-* Building Lists:: Creating list structure.
-* Modifying Lists:: Storing new pieces into an existing list.
-* Sets And Lists:: A list can represent a finite mathematical set.
-* Association Lists:: A list can represent a finite relation or mapping.
-
-Modifying Existing List Structure
-
-* Setcar:: Replacing an element in a list.
-* Setcdr:: Replacing part of the list backbone.
- This can be used to remove or add elements.
-* Rearrangement:: Reordering the elements in a list; combining lists.
-
-Sequences, Arrays, and Vectors
-
-* Sequence Functions:: Functions that accept any kind of sequence.
-* Arrays:: Characteristics of arrays in Emacs Lisp.
-* Array Functions:: Functions specifically for arrays.
-* Vectors:: Functions specifically for vectors.
-
-Symbols
-
-* Symbol Components:: Symbols have names, values, function definitions
- and property lists.
-* Definitions:: A definition says how a symbol will be used.
-* Creating Symbols:: How symbols are kept unique.
-* Property Lists:: Each symbol has a property list
- for recording miscellaneous information.
-
-Evaluation
-
-* Intro Eval:: Evaluation in the scheme of things.
-* Eval:: How to invoke the Lisp interpreter explicitly.
-* Forms:: How various sorts of objects are evaluated.
-* Quoting:: Avoiding evaluation (to put constants in
- the program).
-
-Kinds of Forms
-
-* Self-Evaluating Forms:: Forms that evaluate to themselves.
-* Symbol Forms:: Symbols evaluate as variables.
-* Classifying Lists:: How to distinguish various sorts of list forms.
-* Function Forms:: Forms that call functions.
-* Macro Forms:: Forms that call macros.
-* Special Forms:: ``Special forms'' are idiosyncratic primitives,
- most of them extremely important.
-* Autoloading:: Functions set up to load files
- containing their real definitions.
-
-Control Structures
-
-* Sequencing:: Evaluation in textual order.
-* Conditionals:: @code{if}, @code{cond}.
-* Combining Conditions:: @code{and}, @code{or}, @code{not}.
-* Iteration:: @code{while} loops.
-* Nonlocal Exits:: Jumping out of a sequence.
-
-Nonlocal Exits
-
-* Catch and Throw:: Nonlocal exits for the program's own purposes.
-* Examples of Catch:: Showing how such nonlocal exits can be written.
-* Errors:: How errors are signaled and handled.
-* Cleanups:: Arranging to run a cleanup form if an
- error happens.
-
-Errors
-
-* Signaling Errors:: How to report an error.
-* Processing of Errors:: What Emacs does when you report an error.
-* Handling Errors:: How you can trap errors and continue execution.
-* Error Symbols:: How errors are classified for trapping them.
-
-Variables
-
-* Global Variables:: Variable values that exist permanently, everywhere.
-* Constant Variables:: Certain "variables" have values that never change.
-* Local Variables:: Variable values that exist only temporarily.
-* Void Variables:: Symbols that lack values.
-* Defining Variables:: A definition says a symbol is used as a variable.
-* Accessing Variables:: Examining values of variables whose names
- are known only at run time.
-* Setting Variables:: Storing new values in variables.
-* Variable Scoping:: How Lisp chooses among local and global values.
-* Buffer-Local Variables:: Variable values in effect only in one buffer.
-
-Scoping Rules for Variable Bindings
-
-* Scope:: Scope means where in the program a value
- is visible. Comparison with other languages.
-* Extent:: Extent means how long in time a value exists.
-* Impl of Scope:: Two ways to implement dynamic scoping.
-* Using Scoping:: How to use dynamic scoping carefully and
- avoid problems.
-
-Buffer-Local Variables
-
-* Intro to Buffer-Local:: Introduction and concepts.
-* Creating Buffer-Local:: Creating and destroying buffer-local bindings.
-* Default Value:: The default value is seen in buffers
- that don't have their own local values.
-
-Functions
-
-* What Is a Function:: Lisp functions vs primitives; terminology.
-* Lambda Expressions:: How functions are expressed as Lisp objects.
-* Function Names:: A symbol can serve as the name of a function.
-* Defining Functions:: Lisp expressions for defining functions.
-* Calling Functions:: How to use an existing function.
-* Mapping Functions:: Applying a function to each element of a list, etc.
-* Anonymous Functions:: Lambda-expressions are functions with no names.
-* Function Cells:: Accessing or setting the function definition
- of a symbol.
-* Related Topics:: Cross-references to specific Lisp primitives
- that have a special bearing on how
- functions work.
-
-Lambda Expressions
-
-* Lambda Components:: The parts of a lambda expression.
-* Simple Lambda:: A simple example.
-* Argument List:: Details and special features of argument lists.
-* Function Documentation:: How to put documentation in a function.
-
-Macros
-
-* Simple Macro:: A basic example.
-* Expansion:: How, when and why macros are expanded.
-* Compiling Macros:: How macros are expanded by the compiler.
-* Defining Macros:: How to write a macro definition.
-* Backquote:: Easier construction of list structure.
-* Problems with Macros:: Don't evaluate the macro arguments too many times.
- Don't hide the user's variables.
-
-Loading
-
-* How Programs Do Loading:: The @code{load} function and others.
-* Autoload:: Setting up a function to autoload.
-* Named Features:: Loading a library if it isn't already loaded.
-* Repeated Loading:: Precautions about loading a file twice.
-
-Byte Compilation
-
-* Compilation Functions:: Byte compilation functions.
-* Disassembly:: Disassembling byte-code; how to read byte-code.
-
-Debugging Lisp Programs
-
-* Debugger:: How the Emacs Lisp debugger is implemented.
-* Syntax Errors:: How to find syntax errors.
-* Compilation Errors:: How to find errors that show up in
- byte compilation.
-* Edebug:: A source-level Emacs Lisp debugger.
-
-The Lisp Debugger
-
-* Error Debugging:: Entering the debugger when an error happens.
-* Function Debugging:: Entering it when a certain function is called.
-* Explicit Debug:: Entering it at a certain point in the program.
-* Using Debugger:: What the debugger does; what you see while in it.
-* Debugger Commands:: Commands used while in the debugger.
-* Invoking the Debugger:: How to call the function @code{debug}.
-* Internals of Debugger:: Subroutines of the debugger, and global variables.
-
-Debugging Invalid Lisp Syntax
-
-* Excess Open:: How to find a spurious open paren or missing close.
-* Excess Close:: How to find a spurious close paren or missing open.
-
-Reading and Printing Lisp Objects
-
-* Streams Intro:: Overview of streams, reading and printing.
-* Input Streams:: Various data types that can be used as
- input streams.
-* Input Functions:: Functions to read Lisp objects from text.
-* Output Streams:: Various data types that can be used as
- output streams.
-* Output Functions:: Functions to print Lisp objects as text.
-
-Minibuffers
-
-* Intro to Minibuffers:: Basic information about minibuffers.
-* Text from Minibuffer:: How to read a straight text string.
-* Object from Minibuffer:: How to read a Lisp object or expression.
-* Completion:: How to invoke and customize completion.
-* Yes-or-No Queries:: Asking a question with a simple answer.
-* Minibuffer Misc:: Various customization hooks and variables.
-
-Completion
-
-* Basic Completion:: Low-level functions for completing strings.
- (These are too low level to use the minibuffer.)
-* Minibuffer Completion:: Invoking the minibuffer with completion.
-* Completion Commands:: Minibuffer commands that do completion.
-* High-Level Completion:: Convenient special cases of completion
- (reading buffer name, file name, etc.)
-* Reading File Names:: Using completion to read file names.
-* Programmed Completion:: Finding the completions for a given file name.
-
-Command Loop
-
-* Command Overview:: How the command loop reads commands.
-* Defining Commands:: Specifying how a function should read arguments.
-* Interactive Call:: Calling a command, so that it will read arguments.
-* Command Loop Info:: Variables set by the command loop for you to examine.
-* Input Events:: What input looks like when you read it.
-* Reading Input:: How to read input events from the keyboard or mouse.
-* Waiting:: Waiting for user input or elapsed time.
-* Quitting:: How @kbd{C-g} works. How to catch or defer quitting.
-* Prefix Command Arguments:: How the commands to set prefix args work.
-* Recursive Editing:: Entering a recursive edit,
- and why you usually shouldn't.
-* Disabling Commands:: How the command loop handles disabled commands.
-* Command History:: How the command history is set up, and how accessed.
-* Keyboard Macros:: How keyboard macros are implemented.
-
-Defining Commands
-
-* Using Interactive:: General rules for @code{interactive}.
-* Interactive Codes:: The standard letter-codes for reading arguments
- in various ways.
-* Interactive Examples:: Examples of how to read interactive arguments.
-
-Keymaps
-
-* Keymap Terminology:: Definitions of terms pertaining to keymaps.
-* Format of Keymaps:: What a keymap looks like as a Lisp object.
-* Creating Keymaps:: Functions to create and copy keymaps.
-* Inheritance and Keymaps:: How one keymap can inherit the bindings
- of another keymap.
-* Prefix Keys:: Defining a key with a keymap as its definition.
-* Menu Keymaps:: A keymap can define a menu for X windows
- or for use from the terminal.
-* Active Keymaps:: Each buffer has a local keymap
- to override the standard (global) bindings.
- Each minor mode can also override them.
-* Key Lookup:: How extracting elements from keymaps works.
-* Functions for Key Lookup:: How to request key lookup.
-* Changing Key Bindings:: Redefining a key in a keymap.
-* Key Binding Commands:: Interactive interfaces for redefining keys.
-* Scanning Keymaps:: Looking through all keymaps, for printing help.
-
-Major and Minor Modes
-
-* Major Modes:: Defining major modes.
-* Minor Modes:: Defining minor modes.
-* Mode Line Format:: Customizing the text that appears in the mode line.
-* Hooks:: How to use hooks; how to write code that
- provides hooks.
-
-Major Modes
-
-* Major Mode Conventions:: Coding conventions for keymaps, etc.
-* Example Major Modes:: Text mode and Lisp modes.
-* Auto Major Mode:: How Emacs chooses the major mode automatically.
-* Mode Help:: Finding out how to use a mode.
-
-Minor Modes
-
-* Minor Mode Conventions:: Tips for writing a minor mode.
-* Keymaps and Minor Modes:: How a minor mode can have its own keymap.
-
-Mode Line Format
-
-* Mode Line Data:: The data structure that controls the mode line.
-* Mode Line Variables:: Variables used in that data structure.
-* %-Constructs:: Putting information into a mode line.
-
-Documentation
-
-* Documentation Basics:: Good style for doc strings.
- Where to put them. How Emacs stores them.
-* Accessing Documentation:: How Lisp programs can access doc strings.
-* Keys in Documentation:: Substituting current key bindings.
-* Describing Characters:: Making printable descriptions of
- non-printing characters and key sequences.
-* Help Functions:: Subroutines used by Emacs help facilities.
-
-Files
-
-* Visiting Files:: Reading files into Emacs buffers for editing.
-* Saving Buffers:: Writing changed buffers back into files.
-* Reading from Files:: Reading files into other buffers.
-* Writing to Files:: Writing new files from parts of buffers.
-* File Locks:: Locking and unlocking files, to prevent
- simultaneous editing by two people.
-* Information about Files:: Testing existence, accessibility, size of files.
-* Contents of Directories:: Getting a list of the files in a directory.
-* Changing File Attributes:: Renaming files, changing protection, etc.
-* File Names:: Decomposing and expanding file names.
-
-Visiting Files
-
-* Visiting Functions:: The usual interface functions for visiting.
-* Subroutines of Visiting:: Lower-level subroutines that they use.
-
-Information about Files
-
-* Testing Accessibility:: Is a given file readable? Writable?
-* Kinds of Files:: Is it a directory? A link?
-* File Attributes:: How large is it? Any other names? Etc.
-
-File Names
-
-* File Name Components:: The directory part of a file name, and the rest.
-* Directory Names:: A directory's name as a directory
- is different from its name as a file.
-* Relative File Names:: Some file names are relative to a
- current directory.
-* File Name Expansion:: Converting relative file names to absolute ones.
-* Unique File Names:: Generating names for temporary files.
-* File Name Completion:: Finding the completions for a given file name.
-
-Backups and Auto-Saving
-
-* Backup Files:: How backup files are made; how their names
- are chosen.
-* Auto-Saving:: How auto-save files are made; how their
- names are chosen.
-* Reverting:: @code{revert-buffer}, and how to customize
- what it does.
-
-Backup Files
-
-* Making Backups:: How Emacs makes backup files, and when.
-* Rename or Copy:: Two alternatives: renaming the old file
- or copying it.
-* Numbered Backups:: Keeping multiple backups for each source file.
-* Backup Names:: How backup file names are computed; customization.
-
-Buffers
-
-* Buffer Basics:: What is a buffer?
-* Buffer Names:: Accessing and changing buffer names.
-* Buffer File Name:: The buffer file name indicates which file
- is visited.
-* Buffer Modification:: A buffer is @dfn{modified} if it needs to be saved.
-* Modification Time:: Determining whether the visited file was changed
- ``behind Emacs's back''.
-* Read Only Buffers:: Modifying text is not allowed in a
- read-only buffer.
-* The Buffer List:: How to look at all the existing buffers.
-* Creating Buffers:: Functions that create buffers.
-* Killing Buffers:: Buffers exist until explicitly killed.
-* Current Buffer:: Designating a buffer as current
- so primitives will access its contents.
-
-Windows
-
-* Basic Windows:: Basic information on using windows.
-* Splitting Windows:: Splitting one window into two windows.
-* Deleting Windows:: Deleting a window gives its space to other windows.
-* Selecting Windows:: The selected window is the one that you edit in.
-* Cyclic Window Ordering:: Moving around the existing windows.
-* Buffers and Windows:: Each window displays the contents of a buffer.
-* Displaying Buffers:: Higher-lever functions for displaying a buffer
- and choosing a window for it.
-* Window Point:: Each window has its own location of point.
-* Window Start:: The display-start position controls which text
- is on-screen in the window.
-* Vertical Scrolling:: Moving text up and down in the window.
-* Scrolling Hooks:: Hooks that run when you scroll a window.
-* Horizontal Scrolling:: Moving text sideways on the window.
-* Size of Window:: Accessing the size of a window.
-* Resizing Windows:: Changing the size of a window.
-* Window Configurations:: Saving and restoring the state of the screen.
-
-Frames
-
-* Creating Frames:: Creating additional frames.
-* Multiple Displays:: Creating frames on other X displays.
-* Frame Parameters:: Controlling frame size, position, font, etc.
-* Frame Titles:: Automatic updating of frame titles.
-* Deleting Frames:: Frames last until explicitly deleted.
-* Finding All Frames:: How to examine all existing frames.
-* Frames and Windows:: A frame contains windows;
- display of text always works through windows.
-* Minibuffers and Frames:: How a frame finds the minibuffer to use.
-* Input Focus:: Specifying the selected frame.
-* Visibility of Frames:: Frames may be visible or invisible, or icons.
-* Raising and Lowering:: Raising a frame makes it hide other X windows;
- lowering it makes the others hide them.
-* Frame Configurations:: Saving the state of all frames.
-* Mouse Tracking:: Getting events that say when the mouse moves.
-* Mouse Position:: Asking where the mouse is, or moving it.
-* Pop-Up Menus:: Displaying a menu for the user to select from.
-* Dialog Boxes:: Displaying a box to ask yes or no.
-* Pointer Shapes:: Specifying the shape of the mouse pointer.
-* X Selections:: Transferring text to and from other X clients.
-* Color Names:: Getting the definitions of color names.
-* Resources:: Getting resource values from the server.
-* Server Data:: Getting info about the X server.
-
-Positions
-
-* Point:: The special position where editing takes place.
-* Motion:: Changing point.
-* Excursions:: Temporary motion and buffer changes.
-* Narrowing:: Restricting editing to a portion of the buffer.
-
-Motion
-
-* Character Motion:: Moving in terms of characters.
-* Word Motion:: Moving in terms of words.
-* Buffer End Motion:: Moving to the beginning or end of the buffer.
-* Text Lines:: Moving in terms of lines of text.
-* Screen Lines:: Moving in terms of lines as displayed.
-* List Motion:: Moving by parsing lists and sexps.
-* Skipping Characters:: Skipping characters belonging to a certain set.
-
-Markers
-
-* Overview of Markers:: The components of a marker, and how it relocates.
-* Predicates on Markers:: Testing whether an object is a marker.
-* Creating Markers:: Making empty markers or markers at certain places.
-* Information from Markers:: Finding the marker's buffer or character
- position.
-* Changing Markers:: Moving the marker to a new buffer or position.
-* The Mark:: How ``the mark'' is implemented with a marker.
-* The Region:: How to access ``the region''.
-
-Text
-
-* Near Point:: Examining text in the vicinity of point.
-* Buffer Contents:: Examining text in a general fashion.
-* Insertion:: Adding new text to a buffer.
-* Commands for Insertion:: User-level commands to insert text.
-* Deletion:: Removing text from a buffer.
-* User-Level Deletion:: User-level commands to delete text.
-* The Kill Ring:: Where removed text sometimes is saved for
- later use.
-* Undo:: Undoing changes to the text of a buffer.
-* Auto Filling:: How auto-fill mode is implemented to break lines.
-* Filling:: Functions for explicit filling.
-* Margins:: How to specify margins for filling commands.
-* Sorting:: Functions for sorting parts of the buffer.
-* Indentation:: Functions to insert or adjust indentation.
-* Columns:: Computing horizontal positions, and using them.
-* Case Changes:: Case conversion of parts of the buffer.
-* Text Properties:: Assigning Lisp property lists to text characters.
-* Substitution:: Replacing a given character wherever it appears.
-* Transposition:: Swapping two portions of a buffer.
-* Registers:: How registers are implemented. Accessing
- the text or position stored in a register.
-* Change Hooks:: Supplying functions to be run when text is changed.
-
-The Kill Ring
-
-* Kill Ring Concepts:: What text looks like in the kill ring.
-* Kill Functions:: Functions that kill text.
-* Yank Commands:: Commands that access the kill ring.
-* Low-Level Kill Ring:: Functions and variables for kill ring access.
-* Internals of Kill Ring:: Variables that hold kill-ring data.
-
-Indentation
-
-* Primitive Indent:: Functions used to count and insert indentation.
-* Mode-Specific Indent:: Customize indentation for different modes.
-* Region Indent:: Indent all the lines in a region.
-* Relative Indent:: Indent the current line based on previous lines.
-* Indent Tabs:: Adjustable, typewriter-like tab stops.
-* Motion by Indent:: Move to first non-blank character.
-
-Text Properties
-
-* Examining Properties:: Looking at the properties of one character.
-* Changing Properties:: Setting the properties of a range of text.
-* Property Search:: Searching for where a property changes value.
-* Special Properties:: Particular properties with special meanings.
-* Format Properties:: Properties for representing formatting of text.
-* Sticky Properties:: How inserted text gets properties from
- neighboring text.
-* Saving Properties:: Saving text properties in files, and reading
- them back.
-* Lazy Properties:: Computing text properties in a lazy fashion
- only when text is examined.
-* Not Intervals:: Why text properties do not use
- Lisp-visible text intervals.
-
-Searching and Matching
-
-* String Search:: Search for an exact match.
-* Regular Expressions:: Describing classes of strings.
-* Regexp Search:: Searching for a match for a regexp.
-* Match Data:: Finding out which part of the text matched
- various parts of a regexp, after regexp search.
-* Saving Match Data:: Saving and restoring this information.
-* Standard Regexps:: Useful regexps for finding sentences, pages,...
-* Searching and Case:: Case-independent or case-significant searching.
-
-Regular Expressions
-
-* Syntax of Regexps:: Rules for writing regular expressions.
-* Regexp Example:: Illustrates regular expression syntax.
-
-Syntax Tables
-
-* Syntax Descriptors:: How characters are classified.
-* Syntax Table Functions:: How to create, examine and alter syntax tables.
-* Parsing Expressions:: Parsing balanced expressions
- using the syntax table.
-* Standard Syntax Tables:: Syntax tables used by various major modes.
-* Syntax Table Internals:: How syntax table information is stored.
-
-Syntax Descriptors
-
-* Syntax Class Table:: Table of syntax classes.
-* Syntax Flags:: Additional flags each character can have.
-
-Abbrevs And Abbrev Expansion
-
-* Abbrev Mode:: Setting up Emacs for abbreviation.
-* Tables: Abbrev Tables. Creating and working with abbrev tables.
-* Defining Abbrevs:: Specifying abbreviations and their expansions.
-* Files: Abbrev Files. Saving abbrevs in files.
-* Expansion: Abbrev Expansion. Controlling expansion; expansion subroutines.
-* Standard Abbrev Tables:: Abbrev tables used by various major modes.
-
-Processes
-
-* Subprocess Creation:: Functions that start subprocesses.
-* Synchronous Processes:: Details of using synchronous subprocesses.
-* Asynchronous Processes:: Starting up an asynchronous subprocess.
-* Deleting Processes:: Eliminating an asynchronous subprocess.
-* Process Information:: Accessing run-status and other attributes.
-* Input to Processes:: Sending input to an asynchronous subprocess.
-* Signals to Processes:: Stopping, continuing or interrupting
- an asynchronous subprocess.
-* Output from Processes:: Collecting output from an asynchronous subprocess.
-* Sentinels:: Sentinels run when process run-status changes.
-* Network:: Opening network connections.
-
-Receiving Output from Processes
-
-* Process Buffers:: If no filter, output is put in a buffer.
-* Filter Functions:: Filter functions accept output from the process.
-* Accepting Output:: How to wait until process output arrives.
-
-Operating System Interface
-
-* Starting Up:: Customizing Emacs start-up processing.
-* Getting Out:: How exiting works (permanent or temporary).
-* System Environment:: Distinguish the name and kind of system.
-* Terminal Input:: Recording terminal input for debugging.
-* Terminal Output:: Recording terminal output for debugging.
-* Flow Control:: How to turn output flow control on or off.
-* Batch Mode:: Running Emacs without terminal interaction.
-
-Starting Up Emacs
-
-* Start-up Summary:: Sequence of actions Emacs performs at start-up.
-* Init File:: Details on reading the init file (@file{.emacs}).
-* Terminal-Specific:: How the terminal-specific Lisp file is read.
-* Command Line Arguments:: How command line arguments are processed,
- and how you can customize them.
-
-Getting out of Emacs
-
-* Killing Emacs:: Exiting Emacs irreversibly.
-* Suspending Emacs:: Exiting Emacs reversibly.
-
-Emacs Display
-
-* Refresh Screen:: Clearing the screen and redrawing everything on it.
-* Truncation:: Folding or wrapping long text lines.
-* The Echo Area:: Where messages are displayed.
-* Selective Display:: Hiding part of the buffer text.
-* Overlay Arrow:: Display of an arrow to indicate position.
-* Temporary Displays:: Displays that go away automatically.
-* Waiting:: Forcing display update and waiting for user.
-* Blinking:: How Emacs shows the matching open parenthesis.
-* Usual Display:: How control characters are displayed.
-* Beeping:: Audible signal to the user.
-* Window Systems:: Which window system is being used.
-
-GNU Emacs Internals
-
-* Building Emacs:: How to preload Lisp libraries into Emacs.
-* Pure Storage:: A kludge to make preloaded Lisp functions sharable.
-* Garbage Collection:: Reclaiming space for Lisp objects no longer used.
-* Object Internals:: Data formats of buffers, windows, processes.
-* Writing Emacs Primitives:: Writing C code for Emacs.
-
-Object Internals
-
-* Buffer Internals:: Components of a buffer structure.
-* Window Internals:: Components of a window structure.
-* Process Internals:: Components of a process structure.
-@end menu
-
-@include intro.texi
-@include objects.texi
-@include numbers.texi
-@include strings.texi
-
-@include lists.texi
-@include sequences.texi
-@include symbols.texi
-@include eval.texi
-
-@include control.texi
-@include variables.texi
-@include functions.texi
-@include macros.texi
-
-@include loading.texi
-@include compile.texi
-@include debugging.texi
-@include streams.texi
-
-@include minibuf.texi
-@include commands.texi
-@include keymaps.texi
-@include modes.texi
-
-@include help.texi
-@include files.texi
-@include backups.texi
-@include buffers.texi
-
-@include windows.texi
-@include frames.texi
-@include positions.texi
-@include markers.texi
-@include text.texi
-
-@include searching.texi
-@include syntax.texi
-@include abbrevs.texi
-
-@include processes.texi
-@include os.texi
-@include display.texi
-@include calendar.texi
-
-@c MOVE to Emacs Manual: include misc-modes.texi
-
-@c appendices
-
-@c REMOVE this: include non-hacker.texi
-
-@include tips.texi
-@include internals.texi
-@include errors.texi
-@include locals.texi
-@include maps.texi
-@include hooks.texi
-
-@include index.texi
-
-@c Print the tables of contents
-@summarycontents
-@contents
-@c That's all
-
-@bye
-
-
-These words prevent "local variables" above from confusing Emacs.
diff --git a/lispref/errors.texi b/lispref/errors.texi
deleted file mode 100644
index aa3dde754d6..00000000000
--- a/lispref/errors.texi
+++ /dev/null
@@ -1,158 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/errors
-@node Standard Errors, Standard Buffer-Local Variables, GNU Emacs Internals, Top
-@appendix Standard Errors
-
- Here is the complete list of the error symbols in standard Emacs,
-grouped by concept. The list includes each symbol's message (on the
-@code{error-message} property of the symbol) and a cross reference to a
-description of how the error can occur.
-
- Each error symbol has an @code{error-conditions} property that is a
-list of symbols. Normally this list includes the error symbol itself
-and the symbol @code{error}. Occasionally it includes additional
-symbols, which are intermediate classifications, narrower than
-@code{error} but broader than a single error symbol. For example, all
-the errors in accessing files have the condition @code{file-error}.
-
- As a special exception, the error symbol @code{quit} does not have the
-condition @code{error}, because quitting is not considered an error.
-
- @xref{Errors}, for an explanation of how errors are generated and
-handled.
-
-@table @code
-@item @var{symbol}
-@var{string}; @var{reference}.
-
-@item error
-@code{"error"}@*
-@xref{Errors}.
-
-@item quit
-@code{"Quit"}@*
-@xref{Quitting}.
-
-@item args-out-of-range
-@code{"Args out of range"}@*
-@xref{Sequences Arrays Vectors}.
-
-@item arith-error
-@code{"Arithmetic error"}@*
-See @code{/} and @code{%} in @ref{Numbers}.
-
-@item beginning-of-buffer
-@code{"Beginning of buffer"}@*
-@xref{Motion}.
-
-@item buffer-read-only
-@code{"Buffer is read-only"}@*
-@xref{Read Only Buffers}.
-
-@item cyclic-function-indirection
-@code{"Symbol's chain of function indirections contains a@*
-loop"}@*
-@xref{Function Indirection}.
-
-@item end-of-buffer
-@code{"End of buffer"}@*
-@xref{Motion}.
-
-@item end-of-file
-@code{"End of file during parsing"}@*
-This is not a @code{file-error}.@*
-@xref{Input Functions}.
-
-@item file-error
-This error and its subcategories do not have error-strings, because the
-error message is constructed from the data items alone when the error
-condition @code{file-error} is present.@*
-@xref{Files}.
-
-@item file-locked
-This is a @code{file-error}.@*
-@xref{File Locks}.
-
-@item file-already-exists
-This is a @code{file-error}.@*
-@xref{Writing to Files}.
-
-@item file-supersession
-This is a @code{file-error}.@*
-@xref{Modification Time}.
-
-@item invalid-function
-@code{"Invalid function"}@*
-@xref{Classifying Lists}.
-
-@item invalid-read-syntax
-@code{"Invalid read syntax"}@*
-@xref{Input Functions}.
-
-@item invalid-regexp
-@code{"Invalid regexp"}@*
-@xref{Regular Expressions}.
-
-@item no-catch
-@code{"No catch for tag"}@*
-@xref{Catch and Throw}.
-
-@item search-failed
-@code{"Search failed"}@*
-@xref{Searching and Matching}.
-
-@item setting-constant
-@code{"Attempt to set a constant symbol"}@*
-The values of the symbols @code{nil} and @code{t}
-may not be changed.@*
-@xref{Constant Variables, , Variables that Never Change}.
-
-@item undefined-color
-@code{"Undefined color"}@*
-@xref{Color Names}.
-
-@item void-function
-@code{"Symbol's function definition is void"}@*
-@xref{Function Cells}.
-
-@item void-variable
-@code{"Symbol's value as variable is void"}@*
-@xref{Accessing Variables}.
-
-@item wrong-number-of-arguments
-@code{"Wrong number of arguments"}@*
-@xref{Classifying Lists}.
-
-@item wrong-type-argument
-@code{"Wrong type argument"}@*
-@xref{Type Predicates}.
-@end table
-
- These error types, which are all classified as special cases of
-@code{arith-error}, can occur on certain systems for invalid use of
-mathematical functions.
-
-@table @code
-@item domain-error
-@code{"Arithmetic domain error"}@*
-@xref{Math Functions}.
-
-@item overflow-error
-@code{"Arithmetic overflow error"}@*
-@xref{Math Functions}.
-
-@item range-error
-@code{"Arithmetic range error"}@*
-@xref{Math Functions}.
-
-@item singularity-error
-@code{"Arithmetic singularity error"}@*
-@xref{Math Functions}.
-
-@item underflow-error
-@code{"Arithmetic underflow error"}@*
-@xref{Math Functions}.
-@end table
diff --git a/lispref/eval.texi b/lispref/eval.texi
deleted file mode 100644
index 494a8145baf..00000000000
--- a/lispref/eval.texi
+++ /dev/null
@@ -1,706 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/eval
-@node Evaluation, Control Structures, Symbols, Top
-@chapter Evaluation
-@cindex evaluation
-@cindex interpreter
-@cindex interpreter
-@cindex value of expression
-
- The @dfn{evaluation} of expressions in Emacs Lisp is performed by the
-@dfn{Lisp interpreter}---a program that receives a Lisp object as input
-and computes its @dfn{value as an expression}. How it does this depends
-on the data type of the object, according to rules described in this
-chapter. The interpreter runs automatically to evaluate portions of
-your program, but can also be called explicitly via the Lisp primitive
-function @code{eval}.
-
-@ifinfo
-@menu
-* Intro Eval:: Evaluation in the scheme of things.
-* Eval:: How to invoke the Lisp interpreter explicitly.
-* Forms:: How various sorts of objects are evaluated.
-* Quoting:: Avoiding evaluation (to put constants in the program).
-@end menu
-
-@node Intro Eval
-@section Introduction to Evaluation
-
- The Lisp interpreter, or evaluator, is the program that computes
-the value of an expression that is given to it. When a function
-written in Lisp is called, the evaluator computes the value of the
-function by evaluating the expressions in the function body. Thus,
-running any Lisp program really means running the Lisp interpreter.
-
- How the evaluator handles an object depends primarily on the data
-type of the object.
-@end ifinfo
-
-@cindex forms
-@cindex expression
- A Lisp object that is intended for evaluation is called an
-@dfn{expression} or a @dfn{form}. The fact that expressions are data
-objects and not merely text is one of the fundamental differences
-between Lisp-like languages and typical programming languages. Any
-object can be evaluated, but in practice only numbers, symbols, lists
-and strings are evaluated very often.
-
- It is very common to read a Lisp expression and then evaluate the
-expression, but reading and evaluation are separate activities, and
-either can be performed alone. Reading per se does not evaluate
-anything; it converts the printed representation of a Lisp object to the
-object itself. It is up to the caller of @code{read} whether this
-object is a form to be evaluated, or serves some entirely different
-purpose. @xref{Input Functions}.
-
- Do not confuse evaluation with command key interpretation. The
-editor command loop translates keyboard input into a command (an
-interactively callable function) using the active keymaps, and then
-uses @code{call-interactively} to invoke the command. The execution of
-the command itself involves evaluation if the command is written in
-Lisp, but that is not a part of command key interpretation itself.
-@xref{Command Loop}.
-
-@cindex recursive evaluation
- Evaluation is a recursive process. That is, evaluation of a form may
-call @code{eval} to evaluate parts of the form. For example, evaluation
-of a function call first evaluates each argument of the function call,
-and then evaluates each form in the function body. Consider evaluation
-of the form @code{(car x)}: the subform @code{x} must first be evaluated
-recursively, so that its value can be passed as an argument to the
-function @code{car}.
-
- Evaluation of a function call ultimately calls the function specified
-in it. @xref{Functions}. The execution of the function may itself work
-by evaluating the function definition; or the function may be a Lisp
-primitive implemented in C, or it may be a byte-compiled function
-(@pxref{Byte Compilation}).
-
-@cindex environment
- The evaluation of forms takes place in a context called the
-@dfn{environment}, which consists of the current values and bindings of
-all Lisp variables.@footnote{This definition of ``environment'' is
-specifically not intended to include all the data that can affect the
-result of a program.} Whenever the form refers to a variable without
-creating a new binding for it, the value of the binding in the current
-environment is used. @xref{Variables}.
-
-@cindex side effect
- Evaluation of a form may create new environments for recursive
-evaluation by binding variables (@pxref{Local Variables}). These
-environments are temporary and vanish by the time evaluation of the form
-is complete. The form may also make changes that persist; these changes
-are called @dfn{side effects}. An example of a form that produces side
-effects is @code{(setq foo 1)}.
-
- The details of what evaluation means for each kind of form are
-described below (@pxref{Forms}).
-
-@node Eval
-@section Eval
-@c ??? Perhaps this should be the last section in the chapter.
-
- Most often, forms are evaluated automatically, by virtue of their
-occurrence in a program being run. On rare occasions, you may need to
-write code that evaluates a form that is computed at run time, such as
-after reading a form from text being edited or getting one from a
-property list. On these occasions, use the @code{eval} function.
-
- @strong{Note:} it is generally cleaner and more flexible to call
-functions that are stored in data structures, rather than to evaluate
-expressions stored in data structures. Using functions provides the
-ability to pass information to them as arguments.
-
- The functions and variables described in this section evaluate forms,
-specify limits to the evaluation process, or record recently returned
-values. Loading a file also does evaluation (@pxref{Loading}).
-
-@defun eval form
-This is the basic function for performing evaluation. It evaluates
-@var{form} in the current environment and returns the result. How the
-evaluation proceeds depends on the type of the object (@pxref{Forms}).
-
-Since @code{eval} is a function, the argument expression that appears
-in a call to @code{eval} is evaluated twice: once as preparation before
-@code{eval} is called, and again by the @code{eval} function itself.
-Here is an example:
-
-@example
-@group
-(setq foo 'bar)
- @result{} bar
-@end group
-@group
-(setq bar 'baz)
- @result{} baz
-;; @r{@code{eval} receives argument @code{bar}, which is the value of @code{foo}}
-(eval foo)
- @result{} baz
-(eval 'foo)
- @result{} bar
-@end group
-@end example
-
-The number of currently active calls to @code{eval} is limited to
-@code{max-lisp-eval-depth} (see below).
-@end defun
-
-@deffn Command eval-region start end &optional stream
-This function evaluates the forms in the current buffer in the region
-defined by the positions @var{start} and @var{end}. It reads forms from
-the region and calls @code{eval} on them until the end of the region is
-reached, or until an error is signaled and not handled.
-
-If @var{stream} is supplied, @code{standard-output} is bound to it
-during the evaluation.
-
-You can use the variable @code{load-read-function} to specify a function
-for @code{eval-region} to use instead of @code{read} for reading
-expressions. @xref{How Programs Do Loading}.
-
-@code{eval-region} always returns @code{nil}.
-@end deffn
-
-@cindex evaluation of buffer contents
-@deffn Command eval-current-buffer &optional stream
-This is like @code{eval-region} except that it operates on the whole
-buffer.
-@end deffn
-
-@defvar max-lisp-eval-depth
-This variable defines the maximum depth allowed in calls to @code{eval},
-@code{apply}, and @code{funcall} before an error is signaled (with error
-message @code{"Lisp nesting exceeds max-lisp-eval-depth"}). This counts
-internal uses of those functions, such as for calling the functions
-mentioned in Lisp expressions, and recursive evaluation of function call
-arguments and function body forms.
-
-This limit, with the associated error when it is exceeded, is one way
-that Lisp avoids infinite recursion on an ill-defined function.
-@cindex Lisp nesting error
-
-The default value of this variable is 200. If you set it to a value
-less than 100, Lisp will reset it to 100 if the given value is reached.
-
-@code{max-specpdl-size} provides another limit on nesting.
-@xref{Local Variables}.
-@end defvar
-
-@defvar values
-The value of this variable is a list of the values returned by all the
-expressions that were read from buffers (including the minibuffer),
-evaluated, and printed. The elements are ordered most recent first.
-
-@example
-@group
-(setq x 1)
- @result{} 1
-@end group
-@group
-(list 'A (1+ 2) auto-save-default)
- @result{} (A 3 t)
-@end group
-@group
-values
- @result{} ((A 3 t) 1 @dots{})
-@end group
-@end example
-
-This variable is useful for referring back to values of forms recently
-evaluated. It is generally a bad idea to print the value of
-@code{values} itself, since this may be very long. Instead, examine
-particular elements, like this:
-
-@example
-@group
-;; @r{Refer to the most recent evaluation result.}
-(nth 0 values)
- @result{} (A 3 t)
-@end group
-@group
-;; @r{That put a new element on,}
-;; @r{so all elements move back one.}
-(nth 1 values)
- @result{} (A 3 t)
-@end group
-@group
-;; @r{This gets the element that was next-to-most-recent}
-;; @r{before this example.}
-(nth 3 values)
- @result{} 1
-@end group
-@end example
-@end defvar
-
-@node Forms
-@section Kinds of Forms
-
- A Lisp object that is intended to be evaluated is called a @dfn{form}.
-How Emacs evaluates a form depends on its data type. Emacs has three
-different kinds of form that are evaluated differently: symbols, lists,
-and ``all other types''. This section describes all three kinds,
-starting with ``all other types'' which are self-evaluating forms.
-
-@menu
-* Self-Evaluating Forms:: Forms that evaluate to themselves.
-* Symbol Forms:: Symbols evaluate as variables.
-* Classifying Lists:: How to distinguish various sorts of list forms.
-* Function Indirection:: When a symbol appears as the car of a list,
- we find the real function via the symbol.
-* Function Forms:: Forms that call functions.
-* Macro Forms:: Forms that call macros.
-* Special Forms:: ``Special forms'' are idiosyncratic primitives,
- most of them extremely important.
-* Autoloading:: Functions set up to load files
- containing their real definitions.
-@end menu
-
-@node Self-Evaluating Forms
-@subsection Self-Evaluating Forms
-@cindex vector evaluation
-@cindex literal evaluation
-@cindex self-evaluating form
-
- A @dfn{self-evaluating form} is any form that is not a list or symbol.
-Self-evaluating forms evaluate to themselves: the result of evaluation
-is the same object that was evaluated. Thus, the number 25 evaluates to
-25, and the string @code{"foo"} evaluates to the string @code{"foo"}.
-Likewise, evaluation of a vector does not cause evaluation of the
-elements of the vector---it returns the same vector with its contents
-unchanged.
-
-@example
-@group
-'123 ; @r{An object, shown without evaluation.}
- @result{} 123
-@end group
-@group
-123 ; @r{Evaluated as usual---result is the same.}
- @result{} 123
-@end group
-@group
-(eval '123) ; @r{Evaluated ``by hand''---result is the same.}
- @result{} 123
-@end group
-@group
-(eval (eval '123)) ; @r{Evaluating twice changes nothing.}
- @result{} 123
-@end group
-@end example
-
- It is common to write numbers, characters, strings, and even vectors
-in Lisp code, taking advantage of the fact that they self-evaluate.
-However, it is quite unusual to do this for types that lack a read
-syntax, because there's no way to write them textually. It is possible
-to construct Lisp expressions containing these types by means of a Lisp
-program. Here is an example:
-
-@example
-@group
-;; @r{Build an expression containing a buffer object.}
-(setq buffer (list 'print (current-buffer)))
- @result{} (print #<buffer eval.texi>)
-@end group
-@group
-;; @r{Evaluate it.}
-(eval buffer)
- @print{} #<buffer eval.texi>
- @result{} #<buffer eval.texi>
-@end group
-@end example
-
-@node Symbol Forms
-@subsection Symbol Forms
-@cindex symbol evaluation
-
- When a symbol is evaluated, it is treated as a variable. The result
-is the variable's value, if it has one. If it has none (if its value
-cell is void), an error is signaled. For more information on the use of
-variables, see @ref{Variables}.
-
- In the following example, we set the value of a symbol with
-@code{setq}. Then we evaluate the symbol, and get back the value that
-@code{setq} stored.
-
-@example
-@group
-(setq a 123)
- @result{} 123
-@end group
-@group
-(eval 'a)
- @result{} 123
-@end group
-@group
-a
- @result{} 123
-@end group
-@end example
-
- The symbols @code{nil} and @code{t} are treated specially, so that the
-value of @code{nil} is always @code{nil}, and the value of @code{t} is
-always @code{t}; you cannot set or bind them to any other values. Thus,
-these two symbols act like self-evaluating forms, even though
-@code{eval} treats them like any other symbol.
-
-@node Classifying Lists
-@subsection Classification of List Forms
-@cindex list form evaluation
-
- A form that is a nonempty list is either a function call, a macro
-call, or a special form, according to its first element. These three
-kinds of forms are evaluated in different ways, described below. The
-remaining list elements constitute the @dfn{arguments} for the function,
-macro, or special form.
-
- The first step in evaluating a nonempty list is to examine its first
-element. This element alone determines what kind of form the list is
-and how the rest of the list is to be processed. The first element is
-@emph{not} evaluated, as it would be in some Lisp dialects such as
-Scheme.
-
-@node Function Indirection
-@subsection Symbol Function Indirection
-@cindex symbol function indirection
-@cindex indirection
-@cindex void function
-
- If the first element of the list is a symbol then evaluation examines
-the symbol's function cell, and uses its contents instead of the
-original symbol. If the contents are another symbol, this process,
-called @dfn{symbol function indirection}, is repeated until it obtains a
-non-symbol. @xref{Function Names}, for more information about using a
-symbol as a name for a function stored in the function cell of the
-symbol.
-
- One possible consequence of this process is an infinite loop, in the
-event that a symbol's function cell refers to the same symbol. Or a
-symbol may have a void function cell, in which case the subroutine
-@code{symbol-function} signals a @code{void-function} error. But if
-neither of these things happens, we eventually obtain a non-symbol,
-which ought to be a function or other suitable object.
-
-@kindex invalid-function
-@cindex invalid function
- More precisely, we should now have a Lisp function (a lambda
-expression), a byte-code function, a primitive function, a Lisp macro, a
-special form, or an autoload object. Each of these types is a case
-described in one of the following sections. If the object is not one of
-these types, the error @code{invalid-function} is signaled.
-
- The following example illustrates the symbol indirection process. We
-use @code{fset} to set the function cell of a symbol and
-@code{symbol-function} to get the function cell contents
-(@pxref{Function Cells}). Specifically, we store the symbol @code{car}
-into the function cell of @code{first}, and the symbol @code{first} into
-the function cell of @code{erste}.
-
-@smallexample
-@group
-;; @r{Build this function cell linkage:}
-;; ------------- ----- ------- -------
-;; | #<subr car> | <-- | car | <-- | first | <-- | erste |
-;; ------------- ----- ------- -------
-@end group
-@end smallexample
-
-@smallexample
-@group
-(symbol-function 'car)
- @result{} #<subr car>
-@end group
-@group
-(fset 'first 'car)
- @result{} car
-@end group
-@group
-(fset 'erste 'first)
- @result{} first
-@end group
-@group
-(erste '(1 2 3)) ; @r{Call the function referenced by @code{erste}.}
- @result{} 1
-@end group
-@end smallexample
-
- By contrast, the following example calls a function without any symbol
-function indirection, because the first element is an anonymous Lisp
-function, not a symbol.
-
-@smallexample
-@group
-((lambda (arg) (erste arg))
- '(1 2 3))
- @result{} 1
-@end group
-@end smallexample
-
-@noindent
-Executing the function itself evaluates its body; this does involve
-symbol function indirection when calling @code{erste}.
-
- The built-in function @code{indirect-function} provides an easy way to
-perform symbol function indirection explicitly.
-
-@c Emacs 19 feature
-@defun indirect-function function
-This function returns the meaning of @var{function} as a function. If
-@var{function} is a symbol, then it finds @var{function}'s function
-definition and starts over with that value. If @var{function} is not a
-symbol, then it returns @var{function} itself.
-
-Here is how you could define @code{indirect-function} in Lisp:
-
-@smallexample
-(defun indirect-function (function)
- (if (symbolp function)
- (indirect-function (symbol-function function))
- function))
-@end smallexample
-@end defun
-
-@node Function Forms
-@subsection Evaluation of Function Forms
-@cindex function form evaluation
-@cindex function call
-
- If the first element of a list being evaluated is a Lisp function
-object, byte-code object or primitive function object, then that list is
-a @dfn{function call}. For example, here is a call to the function
-@code{+}:
-
-@example
-(+ 1 x)
-@end example
-
- The first step in evaluating a function call is to evaluate the
-remaining elements of the list from left to right. The results are the
-actual argument values, one value for each list element. The next step
-is to call the function with this list of arguments, effectively using
-the function @code{apply} (@pxref{Calling Functions}). If the function
-is written in Lisp, the arguments are used to bind the argument
-variables of the function (@pxref{Lambda Expressions}); then the forms
-in the function body are evaluated in order, and the value of the last
-body form becomes the value of the function call.
-
-@node Macro Forms
-@subsection Lisp Macro Evaluation
-@cindex macro call evaluation
-
- If the first element of a list being evaluated is a macro object, then
-the list is a @dfn{macro call}. When a macro call is evaluated, the
-elements of the rest of the list are @emph{not} initially evaluated.
-Instead, these elements themselves are used as the arguments of the
-macro. The macro definition computes a replacement form, called the
-@dfn{expansion} of the macro, to be evaluated in place of the original
-form. The expansion may be any sort of form: a self-evaluating
-constant, a symbol, or a list. If the expansion is itself a macro call,
-this process of expansion repeats until some other sort of form results.
-
- Ordinary evaluation of a macro call finishes by evaluating the
-expansion. However, the macro expansion is not necessarily evaluated
-right away, or at all, because other programs also expand macro calls,
-and they may or may not evaluate the expansions.
-
- Normally, the argument expressions are not evaluated as part of
-computing the macro expansion, but instead appear as part of the
-expansion, so they are computed when the expansion is computed.
-
- For example, given a macro defined as follows:
-
-@example
-@group
-(defmacro cadr (x)
- (list 'car (list 'cdr x)))
-@end group
-@end example
-
-@noindent
-an expression such as @code{(cadr (assq 'handler list))} is a macro
-call, and its expansion is:
-
-@example
-(car (cdr (assq 'handler list)))
-@end example
-
-@noindent
-Note that the argument @code{(assq 'handler list)} appears in the
-expansion.
-
-@xref{Macros}, for a complete description of Emacs Lisp macros.
-
-@node Special Forms
-@subsection Special Forms
-@cindex special form evaluation
-
- A @dfn{special form} is a primitive function specially marked so that
-its arguments are not all evaluated. Most special forms define control
-structures or perform variable bindings---things which functions cannot
-do.
-
- Each special form has its own rules for which arguments are evaluated
-and which are used without evaluation. Whether a particular argument is
-evaluated may depend on the results of evaluating other arguments.
-
- Here is a list, in alphabetical order, of all of the special forms in
-Emacs Lisp with a reference to where each is described.
-
-@table @code
-@item and
-@pxref{Combining Conditions}
-
-@item catch
-@pxref{Catch and Throw}
-
-@item cond
-@pxref{Conditionals}
-
-@item condition-case
-@pxref{Handling Errors}
-
-@item defconst
-@pxref{Defining Variables}
-
-@item defmacro
-@pxref{Defining Macros}
-
-@item defun
-@pxref{Defining Functions}
-
-@item defvar
-@pxref{Defining Variables}
-
-@item function
-@pxref{Anonymous Functions}
-
-@item if
-@pxref{Conditionals}
-
-@item interactive
-@pxref{Interactive Call}
-
-@item let
-@itemx let*
-@pxref{Local Variables}
-
-@item or
-@pxref{Combining Conditions}
-
-@item prog1
-@itemx prog2
-@itemx progn
-@pxref{Sequencing}
-
-@item quote
-@pxref{Quoting}
-
-@item save-excursion
-@pxref{Excursions}
-
-@item save-restriction
-@pxref{Narrowing}
-
-@item save-window-excursion
-@pxref{Window Configurations}
-
-@item setq
-@pxref{Setting Variables}
-
-@item setq-default
-@pxref{Creating Buffer-Local}
-
-@item track-mouse
-@pxref{Mouse Tracking}
-
-@item unwind-protect
-@pxref{Nonlocal Exits}
-
-@item while
-@pxref{Iteration}
-
-@item with-output-to-temp-buffer
-@pxref{Temporary Displays}
-@end table
-
-@cindex CL note---special forms compared
-@quotation
-@b{Common Lisp note:} Here are some comparisons of special forms in
-GNU Emacs Lisp and Common Lisp. @code{setq}, @code{if}, and
-@code{catch} are special forms in both Emacs Lisp and Common Lisp.
-@code{defun} is a special form in Emacs Lisp, but a macro in Common
-Lisp. @code{save-excursion} is a special form in Emacs Lisp, but
-doesn't exist in Common Lisp. @code{throw} is a special form in
-Common Lisp (because it must be able to throw multiple values), but it
-is a function in Emacs Lisp (which doesn't have multiple
-values).@refill
-@end quotation
-
-@node Autoloading
-@subsection Autoloading
-
- The @dfn{autoload} feature allows you to call a function or macro
-whose function definition has not yet been loaded into Emacs. It
-specifies which file contains the definition. When an autoload object
-appears as a symbol's function definition, calling that symbol as a
-function automatically loads the specified file; then it calls the real
-definition loaded from that file. @xref{Autoload}.
-
-@node Quoting
-@section Quoting
-@cindex quoting
-
- The special form @code{quote} returns its single argument, as written,
-without evaluating it. This provides a way to include constant symbols
-and lists, which are not self-evaluating objects, in a program. (It is
-not necessary to quote self-evaluating objects such as numbers, strings,
-and vectors.)
-
-@defspec quote object
-This special form returns @var{object}, without evaluating it.
-@end defspec
-
-@cindex @samp{'} for quoting
-@cindex quoting using apostrophe
-@cindex apostrophe for quoting
-Because @code{quote} is used so often in programs, Lisp provides a
-convenient read syntax for it. An apostrophe character (@samp{'})
-followed by a Lisp object (in read syntax) expands to a list whose first
-element is @code{quote}, and whose second element is the object. Thus,
-the read syntax @code{'x} is an abbreviation for @code{(quote x)}.
-
-Here are some examples of expressions that use @code{quote}:
-
-@example
-@group
-(quote (+ 1 2))
- @result{} (+ 1 2)
-@end group
-@group
-(quote foo)
- @result{} foo
-@end group
-@group
-'foo
- @result{} foo
-@end group
-@group
-''foo
- @result{} (quote foo)
-@end group
-@group
-'(quote foo)
- @result{} (quote foo)
-@end group
-@group
-['foo]
- @result{} [(quote foo)]
-@end group
-@end example
-
- Other quoting constructs include @code{function} (@pxref{Anonymous
-Functions}), which causes an anonymous lambda expression written in Lisp
-to be compiled, and @samp{`} (@pxref{Backquote}), which is used to quote
-only part of a list, while computing and substituting other parts.
diff --git a/lispref/files.texi b/lispref/files.texi
deleted file mode 100644
index db196c8f7ee..00000000000
--- a/lispref/files.texi
+++ /dev/null
@@ -1,2254 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/files
-@node Files, Backups and Auto-Saving, Documentation, Top
-@comment node-name, next, previous, up
-@chapter Files
-
- In Emacs, you can find, create, view, save, and otherwise work with
-files and file directories. This chapter describes most of the
-file-related functions of Emacs Lisp, but a few others are described in
-@ref{Buffers}, and those related to backups and auto-saving are
-described in @ref{Backups and Auto-Saving}.
-
- Many of the file functions take one or more arguments that are file
-names. A file name is actually a string. Most of these functions
-expand file name arguments using @code{expand-file-name}, so that
-@file{~} is handled correctly, as are relative file names (including
-@samp{../}). These functions don't recognize environment variable
-substitutions such as @samp{$HOME}. @xref{File Name Expansion}.
-
-@menu
-* Visiting Files:: Reading files into Emacs buffers for editing.
-* Saving Buffers:: Writing changed buffers back into files.
-* Reading from Files:: Reading files into buffers without visiting.
-* Writing to Files:: Writing new files from parts of buffers.
-* File Locks:: Locking and unlocking files, to prevent
- simultaneous editing by two people.
-* Information about Files:: Testing existence, accessibility, size of files.
-* Changing File Attributes:: Renaming files, changing protection, etc.
-* File Names:: Decomposing and expanding file names.
-* Contents of Directories:: Getting a list of the files in a directory.
-* Create/Delete Dirs:: Creating and Deleting Directories.
-* Magic File Names:: Defining "magic" special handling
- for certain file names.
-* Format Conversion:: Conversion to and from various file formats.
-* Files and MS-DOS:: Distinguishing text and binary files on MS-DOS.
-@end menu
-
-@node Visiting Files
-@section Visiting Files
-@cindex finding files
-@cindex visiting files
-
- Visiting a file means reading a file into a buffer. Once this is
-done, we say that the buffer is @dfn{visiting} that file, and call the
-file ``the visited file'' of the buffer.
-
- A file and a buffer are two different things. A file is information
-recorded permanently in the computer (unless you delete it). A buffer,
-on the other hand, is information inside of Emacs that will vanish at
-the end of the editing session (or when you kill the buffer). Usually,
-a buffer contains information that you have copied from a file; then we
-say the buffer is visiting that file. The copy in the buffer is what
-you modify with editing commands. Such changes to the buffer do not
-change the file; therefore, to make the changes permanent, you must
-@dfn{save} the buffer, which means copying the altered buffer contents
-back into the file.
-
- In spite of the distinction between files and buffers, people often
-refer to a file when they mean a buffer and vice-versa. Indeed, we say,
-``I am editing a file,'' rather than, ``I am editing a buffer that I
-will soon save as a file of the same name.'' Humans do not usually need
-to make the distinction explicit. When dealing with a computer program,
-however, it is good to keep the distinction in mind.
-
-@menu
-* Visiting Functions:: The usual interface functions for visiting.
-* Subroutines of Visiting:: Lower-level subroutines that they use.
-@end menu
-
-@node Visiting Functions
-@subsection Functions for Visiting Files
-
- This section describes the functions normally used to visit files.
-For historical reasons, these functions have names starting with
-@samp{find-} rather than @samp{visit-}. @xref{Buffer File Name}, for
-functions and variables that access the visited file name of a buffer or
-that find an existing buffer by its visited file name.
-
- In a Lisp program, if you want to look at the contents of a file but
-not alter it, the fastest way is to use @code{insert-file-contents} in a
-temporary buffer. Visiting the file is not necessary and takes longer.
-@xref{Reading from Files}.
-
-@deffn Command find-file filename
-This command selects a buffer visiting the file @var{filename},
-using an existing buffer if there is one, and otherwise creating a
-new buffer and reading the file into it. It also returns that buffer.
-
-The body of the @code{find-file} function is very simple and looks
-like this:
-
-@example
-(switch-to-buffer (find-file-noselect filename))
-@end example
-
-@noindent
-(See @code{switch-to-buffer} in @ref{Displaying Buffers}.)
-
-When @code{find-file} is called interactively, it prompts for
-@var{filename} in the minibuffer.
-@end deffn
-
-@defun find-file-noselect filename
-This function is the guts of all the file-visiting functions. It finds
-or creates a buffer visiting the file @var{filename}, and returns it.
-It uses an existing buffer if there is one, and otherwise creates a new
-buffer and reads the file into it. You may make the buffer current or
-display it in a window if you wish, but this function does not do so.
-
-When @code{find-file-noselect} uses an existing buffer, it first
-verifies that the file has not changed since it was last visited or
-saved in that buffer. If the file has changed, then this function asks
-the user whether to reread the changed file. If the user says
-@samp{yes}, any changes previously made in the buffer are lost.
-
-If @code{find-file-noselect} needs to create a buffer, and there is no
-file named @var{filename}, it displays the message @samp{New file} in
-the echo area, and leaves the buffer empty.
-
-The @code{find-file-noselect} function calls @code{after-find-file}
-after reading the file (@pxref{Subroutines of Visiting}). That function
-sets the buffer major mode, parses local variables, warns the user if
-there exists an auto-save file more recent than the file just visited,
-and finishes by running the functions in @code{find-file-hooks}.
-
-The @code{find-file-noselect} function returns the buffer that is
-visiting the file @var{filename}.
-
-@example
-@group
-(find-file-noselect "/etc/fstab")
- @result{} #<buffer fstab>
-@end group
-@end example
-@end defun
-
-@deffn Command find-file-other-window filename
-This command selects a buffer visiting the file @var{filename}, but
-does so in a window other than the selected window. It may use another
-existing window or split a window; see @ref{Displaying Buffers}.
-
-When this command is called interactively, it prompts for
-@var{filename}.
-@end deffn
-
-@deffn Command find-file-read-only filename
-This command selects a buffer visiting the file @var{filename}, like
-@code{find-file}, but it marks the buffer as read-only. @xref{Read Only
-Buffers}, for related functions and variables.
-
-When this command is called interactively, it prompts for
-@var{filename}.
-@end deffn
-
-@deffn Command view-file filename
-This command visits @var{filename} in View mode, and displays it in a
-recursive edit, returning to the previous buffer when done. View mode
-is a mode that allows you to skim rapidly through the file but does not
-let you modify it. Entering View mode runs the normal hook
-@code{view-mode-hook}. @xref{Hooks}.
-
-When @code{view-file} is called interactively, it prompts for
-@var{filename}.
-@end deffn
-
-@defvar find-file-hooks
-The value of this variable is a list of functions to be called after a
-file is visited. The file's local-variables specification (if any) will
-have been processed before the hooks are run. The buffer visiting the
-file is current when the hook functions are run.
-
-This variable works just like a normal hook, but we think that renaming
-it would not be advisable.
-@end defvar
-
-@defvar find-file-not-found-hooks
-The value of this variable is a list of functions to be called when
-@code{find-file} or @code{find-file-noselect} is passed a nonexistent
-file name. @code{find-file-noselect} calls these functions as soon as
-it detects a nonexistent file. It calls them in the order of the list,
-until one of them returns non-@code{nil}. @code{buffer-file-name} is
-already set up.
-
-This is not a normal hook because the values of the functions are
-used and they may not all be called.
-@end defvar
-
-@node Subroutines of Visiting
-@comment node-name, next, previous, up
-@subsection Subroutines of Visiting
-
- The @code{find-file-noselect} function uses the
-@code{create-file-buffer} and @code{after-find-file} functions as
-subroutines. Sometimes it is useful to call them directly.
-
-@defun create-file-buffer filename
-This function creates a suitably named buffer for visiting
-@var{filename}, and returns it. It uses @var{filename} (sans directory)
-as the name if that name is free; otherwise, it appends a string such as
-@samp{<2>} to get an unused name. See also @ref{Creating Buffers}.
-
-@strong{Please note:} @code{create-file-buffer} does @emph{not}
-associate the new buffer with a file and does not select the buffer.
-It also does not use the default major mode.
-
-@example
-@group
-(create-file-buffer "foo")
- @result{} #<buffer foo>
-@end group
-@group
-(create-file-buffer "foo")
- @result{} #<buffer foo<2>>
-@end group
-@group
-(create-file-buffer "foo")
- @result{} #<buffer foo<3>>
-@end group
-@end example
-
-This function is used by @code{find-file-noselect}.
-It uses @code{generate-new-buffer} (@pxref{Creating Buffers}).
-@end defun
-
-@defun after-find-file &optional error warn
-This function sets the buffer major mode, and parses local variables
-(@pxref{Auto Major Mode}). It is called by @code{find-file-noselect}
-and by the default revert function (@pxref{Reverting}).
-
-@cindex new file message
-@cindex file open error
-If reading the file got an error because the file does not exist, but
-its directory does exist, the caller should pass a non-@code{nil} value
-for @var{error}. In that case, @code{after-find-file} issues a warning:
-@samp{(New File)}. For more serious errors, the caller should usually not
-call @code{after-find-file}.
-
-If @var{warn} is non-@code{nil}, then this function issues a warning
-if an auto-save file exists and is more recent than the visited file.
-
-The last thing @code{after-find-file} does is call all the functions
-in @code{find-file-hooks}.
-@end defun
-
-@node Saving Buffers
-@section Saving Buffers
-
- When you edit a file in Emacs, you are actually working on a buffer
-that is visiting that file---that is, the contents of the file are
-copied into the buffer and the copy is what you edit. Changes to the
-buffer do not change the file until you @dfn{save} the buffer, which
-means copying the contents of the buffer into the file.
-
-@deffn Command save-buffer &optional backup-option
-This function saves the contents of the current buffer in its visited
-file if the buffer has been modified since it was last visited or saved.
-Otherwise it does nothing.
-
-@code{save-buffer} is responsible for making backup files. Normally,
-@var{backup-option} is @code{nil}, and @code{save-buffer} makes a backup
-file only if this is the first save since visiting the file. Other
-values for @var{backup-option} request the making of backup files in
-other circumstances:
-
-@itemize @bullet
-@item
-With an argument of 4 or 64, reflecting 1 or 3 @kbd{C-u}'s, the
-@code{save-buffer} function marks this version of the file to be
-backed up when the buffer is next saved.
-
-@item
-With an argument of 16 or 64, reflecting 2 or 3 @kbd{C-u}'s, the
-@code{save-buffer} function unconditionally backs up the previous
-version of the file before saving it.
-@end itemize
-@end deffn
-
-@deffn Command save-some-buffers &optional save-silently-p exiting
-This command saves some modified file-visiting buffers. Normally it
-asks the user about each buffer. But if @var{save-silently-p} is
-non-@code{nil}, it saves all the file-visiting buffers without querying
-the user.
-
-The optional @var{exiting} argument, if non-@code{nil}, requests this
-function to offer also to save certain other buffers that are not
-visiting files. These are buffers that have a non-@code{nil} local
-value of @code{buffer-offer-save}. (A user who says yes to saving one
-of these is asked to specify a file name to use.) The
-@code{save-buffers-kill-emacs} function passes a non-@code{nil} value
-for this argument.
-@end deffn
-
-@defvar buffer-offer-save
-When this variable is non-@code{nil} in a buffer, Emacs offers to save
-the buffer on exit even if the buffer is not visiting a file. The
-variable is automatically local in all buffers. Normally, Mail mode
-(used for editing outgoing mail) sets this to @code{t}.
-@end defvar
-
-@deffn Command write-file filename
-This function writes the current buffer into file @var{filename}, makes
-the buffer visit that file, and marks it not modified. Then it renames
-the buffer based on @var{filename}, appending a string like @samp{<2>}
-if necessary to make a unique buffer name. It does most of this work by
-calling @code{set-visited-file-name} and @code{save-buffer}.
-@end deffn
-
- Saving a buffer runs several hooks. It also performs format
-conversion (@pxref{Format Conversion}), and may save text properties in
-``annotations'' (@pxref{Saving Properties}).
-
-@defvar write-file-hooks
-The value of this variable is a list of functions to be called before
-writing out a buffer to its visited file. If one of them returns
-non-@code{nil}, the file is considered already written and the rest of
-the functions are not called, nor is the usual code for writing the file
-executed.
-
-If a function in @code{write-file-hooks} returns non-@code{nil}, it
-is responsible for making a backup file (if that is appropriate).
-To do so, execute the following code:
-
-@example
-(or buffer-backed-up (backup-buffer))
-@end example
-
-You might wish to save the file modes value returned by
-@code{backup-buffer} and use that to set the mode bits of the file that
-you write. This is what @code{save-buffer} normally does.
-
-Even though this is not a normal hook, you can use @code{add-hook} and
-@code{remove-hook} to manipulate the list. @xref{Hooks}.
-@end defvar
-
-@c Emacs 19 feature
-@defvar local-write-file-hooks
-This works just like @code{write-file-hooks}, but it is intended
-to be made local to particular buffers. It's not a good idea to make
-@code{write-file-hooks} local to a buffer---use this variable instead.
-
-The variable is marked as a permanent local, so that changing the major
-mode does not alter a buffer-local value. This is convenient for
-packages that read ``file'' contents in special ways, and set up hooks
-to save the data in a corresponding way.
-@end defvar
-
-@c Emacs 19 feature
-@defvar write-contents-hooks
-This works just like @code{write-file-hooks}, but it is intended for
-hooks that pertain to the contents of the file, as opposed to hooks that
-pertain to where the file came from. Such hooks are usually set up by
-major modes, as buffer-local bindings for this variable.
-
-This variable automatically becomes buffer-local whenever it is set;
-switching to a new major mode always resets this variable. When you use
-@code{add-hooks} to add an element to this hook, you should @emph{not}
-specify a non-@code{nil} @var{local} argument, since this variable is
-used @emph{only} locally.
-@end defvar
-
-@c Emacs 19 feature
-@defvar after-save-hook
-This normal hook runs after a buffer has been saved in its visited file.
-@end defvar
-
-@defvar file-precious-flag
-If this variable is non-@code{nil}, then @code{save-buffer} protects
-against I/O errors while saving by writing the new file to a temporary
-name instead of the name it is supposed to have, and then renaming it to
-the intended name after it is clear there are no errors. This procedure
-prevents problems such as a lack of disk space from resulting in an
-invalid file.
-
-As a side effect, backups are necessarily made by copying. @xref{Rename
-or Copy}. Yet, at the same time, saving a precious file always breaks
-all hard links between the file you save and other file names.
-
-Some modes set this variable non-@code{nil} locally in particular
-buffers.
-@end defvar
-
-@defopt require-final-newline
-This variable determines whether files may be written out that do
-@emph{not} end with a newline. If the value of the variable is
-@code{t}, then @code{save-buffer} silently adds a newline at the end of
-the file whenever the buffer being saved does not already end in one.
-If the value of the variable is non-@code{nil}, but not @code{t}, then
-@code{save-buffer} asks the user whether to add a newline each time the
-case arises.
-
-If the value of the variable is @code{nil}, then @code{save-buffer}
-doesn't add newlines at all. @code{nil} is the default value, but a few
-major modes set it to @code{t} in particular buffers.
-@end defopt
-
-@deffn Command set-visited-file-name filename &optional no-query
-This function changes the visited file name of the current buffer to
-@var{filename}. It also renames the buffer based on @var{filename},
-appending a string like @samp{<2>} if necessary to make a unique buffer
-name. It marks the buffer as @emph{modified},a since the contents do not
-(as far as Emacs knows) match the actual file's contents.
-
-If the specified file already exists, @code{set-visited-file-name}
-asks for confirmation unless @var{no-query} is non-@code{nil}.
-@end deffn
-
-@node Reading from Files
-@comment node-name, next, previous, up
-@section Reading from Files
-
- You can copy a file from the disk and insert it into a buffer
-using the @code{insert-file-contents} function. Don't use the user-level
-command @code{insert-file} in a Lisp program, as that sets the mark.
-
-@defun insert-file-contents filename &optional visit beg end replace
-This function inserts the contents of file @var{filename} into the
-current buffer after point. It returns a list of the absolute file name
-and the length of the data inserted. An error is signaled if
-@var{filename} is not the name of a file that can be read.
-
-The function @code{insert-file-contents} checks the file contents
-against the defined file formats, and converts the file contents if
-appropriate. @xref{Format Conversion}. It also calls the functions in
-the list @code{after-insert-file-functions}; see @ref{Saving
-Properties}.
-
-If @var{visit} is non-@code{nil}, this function additionally marks the
-buffer as unmodified and sets up various fields in the buffer so that it
-is visiting the file @var{filename}: these include the buffer's visited
-file name and its last save file modtime. This feature is used by
-@code{find-file-noselect} and you probably should not use it yourself.
-
-If @var{beg} and @var{end} are non-@code{nil}, they should be integers
-specifying the portion of the file to insert. In this case, @var{visit}
-must be @code{nil}. For example,
-
-@example
-(insert-file-contents filename nil 0 500)
-@end example
-
-@noindent
-inserts the first 500 characters of a file.
-
-If the argument @var{replace} is non-@code{nil}, it means to replace the
-contents of the buffer (actually, just the accessible portion) with the
-contents of the file. This is better than simply deleting the buffer
-contents and inserting the whole file, because (1) it preserves some
-marker positions and (2) it puts less data in the undo list.
-@end defun
-
-If you want to pass a file name to another process so that another
-program can read the file, use the function @code{file-local-copy}; see
-@ref{Magic File Names}.
-
-@node Writing to Files
-@comment node-name, next, previous, up
-@section Writing to Files
-
- You can write the contents of a buffer, or part of a buffer, directly
-to a file on disk using the @code{append-to-file} and
-@code{write-region} functions. Don't use these functions to write to
-files that are being visited; that could cause confusion in the
-mechanisms for visiting.
-
-@deffn Command append-to-file start end filename
-This function appends the contents of the region delimited by
-@var{start} and @var{end} in the current buffer to the end of file
-@var{filename}. If that file does not exist, it is created. This
-function returns @code{nil}.
-
-An error is signaled if @var{filename} specifies a nonwritable file,
-or a nonexistent file in a directory where files cannot be created.
-@end deffn
-
-@deffn Command write-region start end filename &optional append visit
-This function writes the region delimited by @var{start} and @var{end}
-in the current buffer into the file specified by @var{filename}.
-
-@c Emacs 19 feature
-If @var{start} is a string, then @code{write-region} writes or appends
-that string, rather than text from the buffer.
-
-If @var{append} is non-@code{nil}, then the specified text is appended
-to the existing file contents (if any).
-
-If @var{visit} is @code{t}, then Emacs establishes an association
-between the buffer and the file: the buffer is then visiting that file.
-It also sets the last file modification time for the current buffer to
-@var{filename}'s modtime, and marks the buffer as not modified. This
-feature is used by @code{save-buffer}, but you probably should not use
-it yourself.
-
-@c Emacs 19 feature
-If @var{visit} is a string, it specifies the file name to visit. This
-way, you can write the data to one file (@var{filename}) while recording
-the buffer as visiting another file (@var{visit}). The argument
-@var{visit} is used in the echo area message and also for file locking;
-@var{visit} is stored in @code{buffer-file-name}. This feature is used
-to implement @code{file-precious-flag}; don't use it yourself unless you
-really know what you're doing.
-
-The function @code{write-region} converts the data which it writes to
-the appropriate file formats specified by @code{buffer-file-format}.
-@xref{Format Conversion}. It also calls the functions in the list
-@code{write-region-annotate-functions}; see @ref{Saving Properties}.
-
-Normally, @code{write-region} displays a message @samp{Wrote file
-@var{filename}} in the echo area. If @var{visit} is neither @code{t}
-nor @code{nil} nor a string, then this message is inhibited. This
-feature is useful for programs that use files for internal purposes,
-files that the user does not need to know about.
-@end deffn
-
-@node File Locks
-@section File Locks
-@cindex file locks
-
- When two users edit the same file at the same time, they are likely to
-interfere with each other. Emacs tries to prevent this situation from
-arising by recording a @dfn{file lock} when a file is being modified.
-Emacs can then detect the first attempt to modify a buffer visiting a
-file that is locked by another Emacs job, and ask the user what to do.
-
- File locks do not work properly when multiple machines can share
-file systems, such as with NFS. Perhaps a better file locking system
-will be implemented in the future. When file locks do not work, it is
-possible for two users to make changes simultaneously, but Emacs can
-still warn the user who saves second. Also, the detection of
-modification of a buffer visiting a file changed on disk catches some
-cases of simultaneous editing; see @ref{Modification Time}.
-
-@defun file-locked-p filename
- This function returns @code{nil} if the file @var{filename} is not
-locked by this Emacs process. It returns @code{t} if it is locked by
-this Emacs, and it returns the name of the user who has locked it if it
-is locked by someone else.
-
-@example
-@group
-(file-locked-p "foo")
- @result{} nil
-@end group
-@end example
-@end defun
-
-@defun lock-buffer &optional filename
- This function locks the file @var{filename}, if the current buffer is
-modified. The argument @var{filename} defaults to the current buffer's
-visited file. Nothing is done if the current buffer is not visiting a
-file, or is not modified.
-@end defun
-
-@defun unlock-buffer
-This function unlocks the file being visited in the current buffer,
-if the buffer is modified. If the buffer is not modified, then
-the file should not be locked, so this function does nothing. It also
-does nothing if the current buffer is not visiting a file.
-@end defun
-
-@defun ask-user-about-lock file other-user
-This function is called when the user tries to modify @var{file}, but it
-is locked by another user named @var{other-user}. The value it returns
-determines what happens next:
-
-@itemize @bullet
-@item
-A value of @code{t} says to grab the lock on the file. Then
-this user may edit the file and @var{other-user} loses the lock.
-
-@item
-A value of @code{nil} says to ignore the lock and let this
-user edit the file anyway.
-
-@item
-@kindex file-locked
-This function may instead signal a @code{file-locked} error, in which
-case the change that the user was about to make does not take place.
-
-The error message for this error looks like this:
-
-@example
-@error{} File is locked: @var{file} @var{other-user}
-@end example
-
-@noindent
-where @code{file} is the name of the file and @var{other-user} is the
-name of the user who has locked the file.
-@end itemize
-
- The default definition of this function asks the user to choose what
-to do. If you wish, you can replace the @code{ask-user-about-lock}
-function with your own version that decides in another way. The code
-for its usual definition is in @file{userlock.el}.
-@end defun
-
-@node Information about Files
-@section Information about Files
-
- The functions described in this section all operate on strings that
-designate file names. All the functions have names that begin with the
-word @samp{file}. These functions all return information about actual
-files or directories, so their arguments must all exist as actual files
-or directories unless otherwise noted.
-
-@menu
-* Testing Accessibility:: Is a given file readable? Writable?
-* Kinds of Files:: Is it a directory? A symbolic link?
-* Truenames:: Eliminating symbolic links from a file name.
-* File Attributes:: How large is it? Any other names? Etc.
-@end menu
-
-@node Testing Accessibility
-@comment node-name, next, previous, up
-@subsection Testing Accessibility
-@cindex accessibility of a file
-@cindex file accessibility
-
- These functions test for permission to access a file in specific ways.
-
-@defun file-exists-p filename
-This function returns @code{t} if a file named @var{filename} appears
-to exist. This does not mean you can necessarily read the file, only
-that you can find out its attributes. (On Unix, this is true if the
-file exists and you have execute permission on the containing
-directories, regardless of the protection of the file itself.)
-
-If the file does not exist, or if fascist access control policies
-prevent you from finding the attributes of the file, this function
-returns @code{nil}.
-@end defun
-
-@defun file-readable-p filename
-This function returns @code{t} if a file named @var{filename} exists
-and you can read it. It returns @code{nil} otherwise.
-
-@example
-@group
-(file-readable-p "files.texi")
- @result{} t
-@end group
-@group
-(file-exists-p "/usr/spool/mqueue")
- @result{} t
-@end group
-@group
-(file-readable-p "/usr/spool/mqueue")
- @result{} nil
-@end group
-@end example
-@end defun
-
-@c Emacs 19 feature
-@defun file-executable-p filename
-This function returns @code{t} if a file named @var{filename} exists and
-you can execute it. It returns @code{nil} otherwise. If the file is a
-directory, execute permission means you can check the existence and
-attributes of files inside the directory, and open those files if their
-modes permit.
-@end defun
-
-@defun file-writable-p filename
-This function returns @code{t} if the file @var{filename} can be written
-or created by you, and @code{nil} otherwise. A file is writable if the
-file exists and you can write it. It is creatable if it does not exist,
-but the specified directory does exist and you can write in that
-directory.
-
-In the third example below, @file{foo} is not writable because the
-parent directory does not exist, even though the user could create such
-a directory.
-
-@example
-@group
-(file-writable-p "~/foo")
- @result{} t
-@end group
-@group
-(file-writable-p "/foo")
- @result{} nil
-@end group
-@group
-(file-writable-p "~/no-such-dir/foo")
- @result{} nil
-@end group
-@end example
-@end defun
-
-@c Emacs 19 feature
-@defun file-accessible-directory-p dirname
-This function returns @code{t} if you have permission to open existing
-files in the directory whose name as a file is @var{dirname}; otherwise
-(or if there is no such directory), it returns @code{nil}. The value
-of @var{dirname} may be either a directory name or the file name of a
-directory.
-
-Example: after the following,
-
-@example
-(file-accessible-directory-p "/foo")
- @result{} nil
-@end example
-
-@noindent
-we can deduce that any attempt to read a file in @file{/foo/} will
-give an error.
-@end defun
-
-@defun file-ownership-preserved-p filename
-This function returns @code{t} if deleting the file @var{filename} and
-then creating it anew would keep the file's owner unchanged.
-@end defun
-
-@defun file-newer-than-file-p filename1 filename2
-@cindex file age
-@cindex file modification time
-This function returns @code{t} if the file @var{filename1} is
-newer than file @var{filename2}. If @var{filename1} does not
-exist, it returns @code{nil}. If @var{filename2} does not exist,
-it returns @code{t}.
-
-In the following example, assume that the file @file{aug-19} was written
-on the 19th, @file{aug-20} was written on the 20th, and the file
-@file{no-file} doesn't exist at all.
-
-@example
-@group
-(file-newer-than-file-p "aug-19" "aug-20")
- @result{} nil
-@end group
-@group
-(file-newer-than-file-p "aug-20" "aug-19")
- @result{} t
-@end group
-@group
-(file-newer-than-file-p "aug-19" "no-file")
- @result{} t
-@end group
-@group
-(file-newer-than-file-p "no-file" "aug-19")
- @result{} nil
-@end group
-@end example
-
-You can use @code{file-attributes} to get a file's last modification
-time as a list of two numbers. @xref{File Attributes}.
-@end defun
-
-@node Kinds of Files
-@comment node-name, next, previous, up
-@subsection Distinguishing Kinds of Files
-
- This section describes how to distinguish various kinds of files, such
-as directories, symbolic links, and ordinary files.
-
-@defun file-symlink-p filename
-@cindex file symbolic links
-If the file @var{filename} is a symbolic link, the @code{file-symlink-p}
-function returns the file name to which it is linked. This may be the
-name of a text file, a directory, or even another symbolic link, or it
-may be a nonexistent file name.
-
-If the file @var{filename} is not a symbolic link (or there is no such file),
-@code{file-symlink-p} returns @code{nil}.
-
-@example
-@group
-(file-symlink-p "foo")
- @result{} nil
-@end group
-@group
-(file-symlink-p "sym-link")
- @result{} "foo"
-@end group
-@group
-(file-symlink-p "sym-link2")
- @result{} "sym-link"
-@end group
-@group
-(file-symlink-p "/bin")
- @result{} "/pub/bin"
-@end group
-@end example
-
-@c !!! file-symlink-p: should show output of ls -l for comparison
-@end defun
-
-@defun file-directory-p filename
-This function returns @code{t} if @var{filename} is the name of an
-existing directory, @code{nil} otherwise.
-
-@example
-@group
-(file-directory-p "~rms")
- @result{} t
-@end group
-@group
-(file-directory-p "~rms/lewis/files.texi")
- @result{} nil
-@end group
-@group
-(file-directory-p "~rms/lewis/no-such-file")
- @result{} nil
-@end group
-@group
-(file-directory-p "$HOME")
- @result{} nil
-@end group
-@group
-(file-directory-p
- (substitute-in-file-name "$HOME"))
- @result{} t
-@end group
-@end example
-@end defun
-
-@defun file-regular-p filename
-This function returns @code{t} if the file @var{filename} exists and is
-a regular file (not a directory, symbolic link, named pipe, terminal, or
-other I/O device).
-@end defun
-
-@node Truenames
-@subsection Truenames
-@cindex truename (of file)
-
-@c Emacs 19 features
- The @dfn{truename} of a file is the name that you get by following
-symbolic links until none remain, then expanding to get rid of @samp{.}
-and @samp{..} as components. Strictly speaking, a file need not have a
-unique truename; the number of distinct truenames a file has is equal to
-the number of hard links to the file. However, truenames are useful
-because they eliminate symbolic links as a cause of name variation.
-
-@defun file-truename filename
-The function @code{file-truename} returns the true name of the file
-@var{filename}. This is the name that you get by following symbolic
-links until none remain. The argument must be an absolute file name.
-@end defun
-
- @xref{Buffer File Name}, for related information.
-
-@node File Attributes
-@comment node-name, next, previous, up
-@subsection Other Information about Files
-
- This section describes the functions for getting detailed information
-about a file, other than its contents. This information includes the
-mode bits that control access permission, the owner and group numbers,
-the number of names, the inode number, the size, and the times of access
-and modification.
-
-@defun file-modes filename
-@cindex permission
-@cindex file attributes
-This function returns the mode bits of @var{filename}, as an integer.
-The mode bits are also called the file permissions, and they specify
-access control in the usual Unix fashion. If the low-order bit is 1,
-then the file is executable by all users, if the second-lowest-order bit
-is 1, then the file is writable by all users, etc.
-
-The highest value returnable is 4095 (7777 octal), meaning that
-everyone has read, write, and execute permission, that the @sc{suid} bit
-is set for both others and group, and that the sticky bit is set.
-
-@example
-@group
-(file-modes "~/junk/diffs")
- @result{} 492 ; @r{Decimal integer.}
-@end group
-@group
-(format "%o" 492)
- @result{} "754" ; @r{Convert to octal.}
-@end group
-
-@group
-(set-file-modes "~/junk/diffs" 438)
- @result{} nil
-@end group
-
-@group
-(format "%o" 438)
- @result{} "666" ; @r{Convert to octal.}
-@end group
-
-@group
-% ls -l diffs
- -rw-rw-rw- 1 lewis 0 3063 Oct 30 16:00 diffs
-@end group
-@end example
-@end defun
-
-@defun file-nlinks filename
-This functions returns the number of names (i.e., hard links) that
-file @var{filename} has. If the file does not exist, then this function
-returns @code{nil}. Note that symbolic links have no effect on this
-function, because they are not considered to be names of the files they
-link to.
-
-@example
-@group
-% ls -l foo*
--rw-rw-rw- 2 rms 4 Aug 19 01:27 foo
--rw-rw-rw- 2 rms 4 Aug 19 01:27 foo1
-@end group
-
-@group
-(file-nlinks "foo")
- @result{} 2
-@end group
-@group
-(file-nlinks "doesnt-exist")
- @result{} nil
-@end group
-@end example
-@end defun
-
-@defun file-attributes filename
-This function returns a list of attributes of file @var{filename}. If
-the specified file cannot be opened, it returns @code{nil}.
-
-The elements of the list, in order, are:
-
-@enumerate 0
-@item
-@code{t} for a directory, a string for a symbolic link (the name
-linked to), or @code{nil} for a text file.
-
-@c Wordy so as to prevent an overfull hbox. --rjc 15mar92
-@item
-The number of names the file has. Alternate names, also known as hard
-links, can be created by using the @code{add-name-to-file} function
-(@pxref{Changing File Attributes}).
-
-@item
-The file's @sc{uid}.
-
-@item
-The file's @sc{gid}.
-
-@item
-The time of last access, as a list of two integers.
-The first integer has the high-order 16 bits of time,
-the second has the low 16 bits. (This is similar to the
-value of @code{current-time}; see @ref{Time of Day}.)
-
-@item
-The time of last modification as a list of two integers (as above).
-
-@item
-The time of last status change as a list of two integers (as above).
-
-@item
-The size of the file in bytes.
-
-@item
-The file's modes, as a string of ten letters or dashes,
-as in @samp{ls -l}.
-
-@item
-@code{t} if the file's @sc{gid} would change if file were
-deleted and recreated; @code{nil} otherwise.
-
-@item
-The file's inode number.
-
-@item
-The file system number of the file system that the file is in. This
-element and the file's inode number together give enough information to
-distinguish any two files on the system---no two files can have the same
-values for both of these numbers.
-@end enumerate
-
-For example, here are the file attributes for @file{files.texi}:
-
-@example
-@group
-(file-attributes "files.texi")
- @result{} (nil
- 1
- 2235
- 75
- (8489 20284)
- (8489 20284)
- (8489 20285)
- 14906
- "-rw-rw-rw-"
- nil
- 129500
- -32252)
-@end group
-@end example
-
-@noindent
-and here is how the result is interpreted:
-
-@table @code
-@item nil
-is neither a directory nor a symbolic link.
-
-@item 1
-has only one name (the name @file{files.texi} in the current default
-directory).
-
-@item 2235
-is owned by the user with @sc{uid} 2235.
-
-@item 75
-is in the group with @sc{gid} 75.
-
-@item (8489 20284)
-was last accessed on Aug 19 00:09.
-
-@item (8489 20284)
-was last modified on Aug 19 00:09.
-
-@item (8489 20285)
-last had its inode changed on Aug 19 00:09.
-
-@item 14906
-is 14906 characters long.
-
-@item "-rw-rw-rw-"
-has a mode of read and write access for the owner, group, and world.
-
-@item nil
-would retain the same @sc{gid} if it were recreated.
-
-@item 129500
-has an inode number of 129500.
-@item -32252
-is on file system number -32252.
-@end table
-@end defun
-
-@node Changing File Attributes
-@section Changing File Names and Attributes
-@cindex renaming files
-@cindex copying files
-@cindex deleting files
-@cindex linking files
-@cindex setting modes of files
-
- The functions in this section rename, copy, delete, link, and set the
-modes of files.
-
- In the functions that have an argument @var{newname}, if a file by the
-name of @var{newname} already exists, the actions taken depend on the
-value of the argument @var{ok-if-already-exists}:
-
-@itemize @bullet
-@item
-Signal a @code{file-already-exists} error if
-@var{ok-if-already-exists} is @code{nil}.
-
-@item
-Request confirmation if @var{ok-if-already-exists} is a number.
-
-@item
-Replace the old file without confirmation if @var{ok-if-already-exists}
-is any other value.
-@end itemize
-
-@defun add-name-to-file oldname newname &optional ok-if-already-exists
-@cindex file with multiple names
-@cindex file hard link
-This function gives the file named @var{oldname} the additional name
-@var{newname}. This means that @var{newname} becomes a new ``hard
-link'' to @var{oldname}.
-
-In the first part of the following example, we list two files,
-@file{foo} and @file{foo3}.
-
-@example
-@group
-% ls -l fo*
--rw-rw-rw- 1 rms 29 Aug 18 20:32 foo
--rw-rw-rw- 1 rms 24 Aug 18 20:31 foo3
-@end group
-@end example
-
-Now we create a hard link, by calling @code{add-name-to-file}, then list
-the files again. This shows two names for one file, @file{foo} and
-@file{foo2}.
-
-@example
-@group
-(add-name-to-file "~/lewis/foo1" "~/lewis/foo2")
- @result{} nil
-@end group
-
-@group
-% ls -l fo*
--rw-rw-rw- 2 rms 29 Aug 18 20:32 foo
--rw-rw-rw- 2 rms 29 Aug 18 20:32 foo2
--rw-rw-rw- 1 rms 24 Aug 18 20:31 foo3
-@end group
-@end example
-
-@c !!! Check whether this set of examples is consistent. --rjc 15mar92
- Finally, we evaluate the following:
-
-@example
-(add-name-to-file "~/lewis/foo" "~/lewis/foo3" t)
-@end example
-
-@noindent
-and list the files again. Now there are three names
-for one file: @file{foo}, @file{foo2}, and @file{foo3}. The old
-contents of @file{foo3} are lost.
-
-@example
-@group
-(add-name-to-file "~/lewis/foo1" "~/lewis/foo3")
- @result{} nil
-@end group
-
-@group
-% ls -l fo*
--rw-rw-rw- 3 rms 29 Aug 18 20:32 foo
--rw-rw-rw- 3 rms 29 Aug 18 20:32 foo2
--rw-rw-rw- 3 rms 29 Aug 18 20:32 foo3
-@end group
-@end example
-
- This function is meaningless on VMS, where multiple names for one file
-are not allowed.
-
- See also @code{file-nlinks} in @ref{File Attributes}.
-@end defun
-
-@deffn Command rename-file filename newname &optional ok-if-already-exists
-This command renames the file @var{filename} as @var{newname}.
-
-If @var{filename} has additional names aside from @var{filename}, it
-continues to have those names. In fact, adding the name @var{newname}
-with @code{add-name-to-file} and then deleting @var{filename} has the
-same effect as renaming, aside from momentary intermediate states.
-
-In an interactive call, this function prompts for @var{filename} and
-@var{newname} in the minibuffer; also, it requests confirmation if
-@var{newname} already exists.
-@end deffn
-
-@deffn Command copy-file oldname newname &optional ok-if-exists time
-This command copies the file @var{oldname} to @var{newname}. An
-error is signaled if @var{oldname} does not exist.
-
-If @var{time} is non-@code{nil}, then this functions gives the new
-file the same last-modified time that the old one has. (This works on
-only some operating systems.)
-
-In an interactive call, this function prompts for @var{filename} and
-@var{newname} in the minibuffer; also, it requests confirmation if
-@var{newname} already exists.
-@end deffn
-
-@deffn Command delete-file filename
-@pindex rm
-This command deletes the file @var{filename}, like the shell command
-@samp{rm @var{filename}}. If the file has multiple names, it continues
-to exist under the other names.
-
-A suitable kind of @code{file-error} error is signaled if the file
-does not exist, or is not deletable. (On Unix, a file is deletable if
-its directory is writable.)
-
-See also @code{delete-directory} in @ref{Create/Delete Dirs}.
-@end deffn
-
-@deffn Command make-symbolic-link filename newname &optional ok-if-exists
-@pindex ln
-@kindex file-already-exists
-This command makes a symbolic link to @var{filename}, named
-@var{newname}. This is like the shell command @samp{ln -s
-@var{filename} @var{newname}}.
-
-In an interactive call, this function prompts for @var{filename} and
-@var{newname} in the minibuffer; also, it requests confirmation if
-@var{newname} already exists.
-@end deffn
-
-@defun define-logical-name varname string
-This function defines the logical name @var{name} to have the value
-@var{string}. It is available only on VMS.
-@end defun
-
-@defun set-file-modes filename mode
-This function sets mode bits of @var{filename} to @var{mode} (which must
-be an integer). Only the low 12 bits of @var{mode} are used.
-@end defun
-
-@c Emacs 19 feature
-@defun set-default-file-modes mode
-This function sets the default file protection for new files created by
-Emacs and its subprocesses. Every file created with Emacs initially has
-this protection. On Unix, the default protection is the bitwise
-complement of the ``umask'' value.
-
-The argument @var{mode} must be an integer. Only the low 9 bits of
-@var{mode} are used.
-
-Saving a modified version of an existing file does not count as creating
-the file; it does not change the file's mode, and does not use the
-default file protection.
-@end defun
-
-@defun default-file-modes
-This function returns the current default protection value.
-@end defun
-
-@cindex MS-DOS and file modes
-@cindex file modes and MS-DOS
- On MS-DOS, there is no such thing as an ``executable'' file mode bit.
-So Emacs considers a file executable if its name ends in @samp{.com},
-@samp{.bat} or @samp{.exe}. This is reflected in the values returned
-by @code{file-modes} and @code{file-attributes}.
-
-@node File Names
-@section File Names
-@cindex file names
-
- Files are generally referred to by their names, in Emacs as elsewhere.
-File names in Emacs are represented as strings. The functions that
-operate on a file all expect a file name argument.
-
- In addition to operating on files themselves, Emacs Lisp programs
-often need to operate on the names; i.e., to take them apart and to use
-part of a name to construct related file names. This section describes
-how to manipulate file names.
-
- The functions in this section do not actually access files, so they
-can operate on file names that do not refer to an existing file or
-directory.
-
- On VMS, all these functions understand both VMS file-name syntax and
-Unix syntax. This is so that all the standard Lisp libraries can
-specify file names in Unix syntax and work properly on VMS without
-change. On MS-DOS, these functions understand MS-DOS file-name syntax
-as well as Unix syntax.
-
-@menu
-* File Name Components:: The directory part of a file name, and the rest.
-* Directory Names:: A directory's name as a directory
- is different from its name as a file.
-* Relative File Names:: Some file names are relative to a current directory.
-* File Name Expansion:: Converting relative file names to absolute ones.
-* Unique File Names:: Generating names for temporary files.
-* File Name Completion:: Finding the completions for a given file name.
-* Standard File Names:: If your package uses a fixed file name,
- how to handle various operating systems simply.
-@end menu
-
-@node File Name Components
-@subsection File Name Components
-@cindex directory part (of file name)
-@cindex nondirectory part (of file name)
-@cindex version number (in file name)
-
- The operating system groups files into directories. To specify a
-file, you must specify the directory and the file's name within that
-directory. Therefore, Emacs considers a file name as having two main
-parts: the @dfn{directory name} part, and the @dfn{nondirectory} part
-(or @dfn{file name within the directory}). Either part may be empty.
-Concatenating these two parts reproduces the original file name.
-
- On Unix, the directory part is everything up to and including the last
-slash; the nondirectory part is the rest. The rules in VMS syntax are
-complicated.
-
- For some purposes, the nondirectory part is further subdivided into
-the name proper and the @dfn{version number}. On Unix, only backup
-files have version numbers in their names; on VMS, every file has a
-version number, but most of the time the file name actually used in
-Emacs omits the version number. Version numbers are found mostly in
-directory lists.
-
-@defun file-name-directory filename
- This function returns the directory part of @var{filename} (or
-@code{nil} if @var{filename} does not include a directory part). On
-Unix, the function returns a string ending in a slash. On VMS, it
-returns a string ending in one of the three characters @samp{:},
-@samp{]}, or @samp{>}.
-
-@example
-@group
-(file-name-directory "lewis/foo") ; @r{Unix example}
- @result{} "lewis/"
-@end group
-@group
-(file-name-directory "foo") ; @r{Unix example}
- @result{} nil
-@end group
-@group
-(file-name-directory "[X]FOO.TMP") ; @r{VMS example}
- @result{} "[X]"
-@end group
-@end example
-@end defun
-
-@defun file-name-nondirectory filename
- This function returns the nondirectory part of @var{filename}.
-
-@example
-@group
-(file-name-nondirectory "lewis/foo")
- @result{} "foo"
-@end group
-@group
-(file-name-nondirectory "foo")
- @result{} "foo"
-@end group
-@group
-;; @r{The following example is accurate only on VMS.}
-(file-name-nondirectory "[X]FOO.TMP")
- @result{} "FOO.TMP"
-@end group
-@end example
-@end defun
-
-@defun file-name-sans-versions filename
- This function returns @var{filename} without any file version numbers,
-backup version numbers, or trailing tildes.
-
-@example
-@group
-(file-name-sans-versions "~rms/foo.~1~")
- @result{} "~rms/foo"
-@end group
-@group
-(file-name-sans-versions "~rms/foo~")
- @result{} "~rms/foo"
-@end group
-@group
-(file-name-sans-versions "~rms/foo")
- @result{} "~rms/foo"
-@end group
-@group
-;; @r{The following example applies to VMS only.}
-(file-name-sans-versions "foo;23")
- @result{} "foo"
-@end group
-@end example
-@end defun
-
-@defun file-name-sans-extension filename
-This function returns @var{filename} minus its ``extension,'' if any.
-The extension, in a file name, is the part that starts with the last
-@samp{.} in the last name component. For example,
-
-@example
-(file-name-sans-extension "foo.lose.c")
- @result{} "foo.lose"
-(file-name-sans-extension "big.hack/foo")
- @result{} "big.hack/foo"
-@end example
-@end defun
-
-@node Directory Names
-@comment node-name, next, previous, up
-@subsection Directory Names
-@cindex directory name
-@cindex file name of directory
-
- A @dfn{directory name} is the name of a directory. A directory is a
-kind of file, and it has a file name, which is related to the directory
-name but not identical to it. (This is not quite the same as the usual
-Unix terminology.) These two different names for the same entity are
-related by a syntactic transformation. On Unix, this is simple: a
-directory name ends in a slash, whereas the directory's name as a file
-lacks that slash. On VMS, the relationship is more complicated.
-
- The difference between a directory name and its name as a file is
-subtle but crucial. When an Emacs variable or function argument is
-described as being a directory name, a file name of a directory is not
-acceptable.
-
- The following two functions convert between directory names and file
-names. They do nothing special with environment variable substitutions
-such as @samp{$HOME}, and the constructs @samp{~}, and @samp{..}.
-
-@defun file-name-as-directory filename
-This function returns a string representing @var{filename} in a form
-that the operating system will interpret as the name of a directory. In
-Unix, this means appending a slash to the string. On VMS, the function
-converts a string of the form @file{[X]Y.DIR.1} to the form
-@file{[X.Y]}.
-
-@example
-@group
-(file-name-as-directory "~rms/lewis")
- @result{} "~rms/lewis/"
-@end group
-@end example
-@end defun
-
-@defun directory-file-name dirname
-This function returns a string representing @var{dirname} in a form
-that the operating system will interpret as the name of a file. On
-Unix, this means removing a final slash from the string. On VMS, the
-function converts a string of the form @file{[X.Y]} to
-@file{[X]Y.DIR.1}.
-
-@example
-@group
-(directory-file-name "~lewis/")
- @result{} "~lewis"
-@end group
-@end example
-@end defun
-
-@cindex directory name abbreviation
- Directory name abbreviations are useful for directories that are
-normally accessed through symbolic links. Sometimes the users recognize
-primarily the link's name as ``the name'' of the directory, and find it
-annoying to see the directory's ``real'' name. If you define the link
-name as an abbreviation for the ``real'' name, Emacs shows users the
-abbreviation instead.
-
-@defvar directory-abbrev-alist
-The variable @code{directory-abbrev-alist} contains an alist of
-abbreviations to use for file directories. Each element has the form
-@code{(@var{from} . @var{to})}, and says to replace @var{from} with
-@var{to} when it appears in a directory name. The @var{from} string is
-actually a regular expression; it should always start with @samp{^}.
-The function @code{abbreviate-file-name} performs these substitutions.
-
-You can set this variable in @file{site-init.el} to describe the
-abbreviations appropriate for your site.
-
-Here's an example, from a system on which file system @file{/home/fsf}
-and so on are normally accessed through symbolic links named @file{/fsf}
-and so on.
-
-@example
-(("^/home/fsf" . "/fsf")
- ("^/home/gp" . "/gp")
- ("^/home/gd" . "/gd"))
-@end example
-@end defvar
-
- To convert a directory name to its abbreviation, use this
-function:
-
-@defun abbreviate-file-name dirname
-This function applies abbreviations from @code{directory-abbrev-alist}
-to its argument, and substitutes @samp{~} for the user's home
-directory.
-@end defun
-
-@node Relative File Names
-@subsection Absolute and Relative File Names
-@cindex absolute file name
-@cindex relative file name
-
- All the directories in the file system form a tree starting at the
-root directory. A file name can specify all the directory names
-starting from the root of the tree; then it is called an @dfn{absolute}
-file name. Or it can specify the position of the file in the tree
-relative to a default directory; then it is called a @dfn{relative}
-file name. On Unix, an absolute file name starts with a slash or a
-tilde (@samp{~}), and a relative one does not. The rules on VMS are
-complicated.
-
-@defun file-name-absolute-p filename
-This function returns @code{t} if file @var{filename} is an absolute
-file name, @code{nil} otherwise. On VMS, this function understands both
-Unix syntax and VMS syntax.
-
-@example
-@group
-(file-name-absolute-p "~rms/foo")
- @result{} t
-@end group
-@group
-(file-name-absolute-p "rms/foo")
- @result{} nil
-@end group
-@group
-(file-name-absolute-p "/user/rms/foo")
- @result{} t
-@end group
-@end example
-@end defun
-
-@node File Name Expansion
-@subsection Functions that Expand Filenames
-@cindex expansion of file names
-
- @dfn{Expansion} of a file name means converting a relative file name
-to an absolute one. Since this is done relative to a default directory,
-you must specify the default directory name as well as the file name to
-be expanded. Expansion also simplifies file names by eliminating
-redundancies such as @file{./} and @file{@var{name}/../}.
-
-@defun expand-file-name filename &optional directory
-This function converts @var{filename} to an absolute file name. If
-@var{directory} is supplied, it is the directory to start with if
-@var{filename} is relative. (The value of @var{directory} should itself
-be an absolute directory name; it may start with @samp{~}.)
-Otherwise, the current buffer's value of @code{default-directory} is
-used. For example:
-
-@example
-@group
-(expand-file-name "foo")
- @result{} "/xcssun/users/rms/lewis/foo"
-@end group
-@group
-(expand-file-name "../foo")
- @result{} "/xcssun/users/rms/foo"
-@end group
-@group
-(expand-file-name "foo" "/usr/spool/")
- @result{} "/usr/spool/foo"
-@end group
-@group
-(expand-file-name "$HOME/foo")
- @result{} "/xcssun/users/rms/lewis/$HOME/foo"
-@end group
-@end example
-
-Filenames containing @samp{.} or @samp{..} are simplified to their
-canonical form:
-
-@example
-@group
-(expand-file-name "bar/../foo")
- @result{} "/xcssun/users/rms/lewis/foo"
-@end group
-@end example
-
-@samp{~/} is expanded into the user's home directory. A @samp{/} or
-@samp{~} following a @samp{/} is taken to be the start of an absolute
-file name that overrides what precedes it, so everything before that
-@samp{/} or @samp{~} is deleted. For example:
-
-@example
-@group
-(expand-file-name
- "/a1/gnu//usr/local/lib/emacs/etc/MACHINES")
- @result{} "/usr/local/lib/emacs/etc/MACHINES"
-@end group
-@group
-(expand-file-name "/a1/gnu/~/foo")
- @result{} "/xcssun/users/rms/foo"
-@end group
-@end example
-
-@noindent
-In both cases, @file{/a1/gnu/} is discarded because an absolute file
-name follows it.
-
-Note that @code{expand-file-name} does @emph{not} expand environment
-variables; only @code{substitute-in-file-name} does that.
-@end defun
-
-@c Emacs 19 feature
-@defun file-relative-name filename directory
-This function does the inverse of expansion---it tries to return a
-relative name that is equivalent to @var{filename} when interpreted
-relative to @var{directory}. (If such a relative name would be longer
-than the absolute name, it returns the absolute name instead.)
-
-@example
-(file-relative-name "/foo/bar" "/foo/")
- @result{} "bar")
-(file-relative-name "/foo/bar" "/hack/")
- @result{} "/foo/bar")
-@end example
-@end defun
-
-@defvar default-directory
-The value of this buffer-local variable is the default directory for the
-current buffer. It should be an absolute directory name; it may start
-with @samp{~}. This variable is local in every buffer.
-
-@code{expand-file-name} uses the default directory when its second
-argument is @code{nil}.
-
-On Unix systems, the value is always a string ending with a slash.
-
-@example
-@group
-default-directory
- @result{} "/user/lewis/manual/"
-@end group
-@end example
-@end defvar
-
-@defun substitute-in-file-name filename
-This function replaces environment variables references in
-@var{filename} with the environment variable values. Following standard
-Unix shell syntax, @samp{$} is the prefix to substitute an environment
-variable value.
-
-The environment variable name is the series of alphanumeric characters
-(including underscores) that follow the @samp{$}. If the character following
-the @samp{$} is a @samp{@{}, then the variable name is everything up to the
-matching @samp{@}}.
-
-@c Wordy to avoid overfull hbox. --rjc 15mar92
-Here we assume that the environment variable @code{HOME}, which holds
-the user's home directory name, has value @samp{/xcssun/users/rms}.
-
-@example
-@group
-(substitute-in-file-name "$HOME/foo")
- @result{} "/xcssun/users/rms/foo"
-@end group
-@end example
-
-If a @samp{~} or a @samp{/} appears following a @samp{/}, after
-substitution, everything before the following @samp{/} is discarded:
-
-@example
-@group
-(substitute-in-file-name "bar/~/foo")
- @result{} "~/foo"
-@end group
-@group
-(substitute-in-file-name "/usr/local/$HOME/foo")
- @result{} "/xcssun/users/rms/foo"
-@end group
-@end example
-
-On VMS, @samp{$} substitution is not done, so this function does nothing
-on VMS except discard superfluous initial components as shown above.
-@end defun
-
-@node Unique File Names
-@subsection Generating Unique File Names
-
- Some programs need to write temporary files. Here is the usual way to
-construct a name for such a file:
-
-@example
-(make-temp-name (concat "/tmp/" @var{name-of-application}))
-@end example
-
-@noindent
-Here we use the directory @file{/tmp/} because that is the standard
-place on Unix for temporary files. The job of @code{make-temp-name} is
-to prevent two different users or two different jobs from trying to use
-the same name.
-
-@defun make-temp-name string
-This function generates string that can be used as a unique name. The
-name starts with @var{string}, and ends with a number that is different
-in each Emacs job.
-
-@example
-@group
-(make-temp-name "/tmp/foo")
- @result{} "/tmp/foo021304"
-@end group
-@end example
-
-To prevent conflicts among different libraries running in the same
-Emacs, each Lisp program that uses @code{make-temp-name} should have its
-own @var{string}. The number added to the end of the name distinguishes
-between the same application running in different Emacs jobs.
-@end defun
-
-@node File Name Completion
-@subsection File Name Completion
-@cindex file name completion subroutines
-@cindex completion, file name
-
- This section describes low-level subroutines for completing a file
-name. For other completion functions, see @ref{Completion}.
-
-@defun file-name-all-completions partial-filename directory
-This function returns a list of all possible completions for a file
-whose name starts with @var{partial-filename} in directory
-@var{directory}. The order of the completions is the order of the files
-in the directory, which is unpredictable and conveys no useful
-information.
-
-The argument @var{partial-filename} must be a file name containing no
-directory part and no slash. The current buffer's default directory is
-prepended to @var{directory}, if @var{directory} is not absolute.
-
-In the following example, suppose that @file{~rms/lewis} is the current
-default directory, and has five files whose names begin with @samp{f}:
-@file{foo}, @file{file~}, @file{file.c}, @file{file.c.~1~}, and
-@file{file.c.~2~}.@refill
-
-@example
-@group
-(file-name-all-completions "f" "")
- @result{} ("foo" "file~" "file.c.~2~"
- "file.c.~1~" "file.c")
-@end group
-
-@group
-(file-name-all-completions "fo" "")
- @result{} ("foo")
-@end group
-@end example
-@end defun
-
-@defun file-name-completion filename directory
-This function completes the file name @var{filename} in directory
-@var{directory}. It returns the longest prefix common to all file names
-in directory @var{directory} that start with @var{filename}.
-
-If only one match exists and @var{filename} matches it exactly, the
-function returns @code{t}. The function returns @code{nil} if directory
-@var{directory} contains no name starting with @var{filename}.
-
-In the following example, suppose that the current default directory
-has five files whose names begin with @samp{f}: @file{foo},
-@file{file~}, @file{file.c}, @file{file.c.~1~}, and
-@file{file.c.~2~}.@refill
-
-@example
-@group
-(file-name-completion "fi" "")
- @result{} "file"
-@end group
-
-@group
-(file-name-completion "file.c.~1" "")
- @result{} "file.c.~1~"
-@end group
-
-@group
-(file-name-completion "file.c.~1~" "")
- @result{} t
-@end group
-
-@group
-(file-name-completion "file.c.~3" "")
- @result{} nil
-@end group
-@end example
-@end defun
-
-@defopt completion-ignored-extensions
-@code{file-name-completion} usually ignores file names that end in any
-string in this list. It does not ignore them when all the possible
-completions end in one of these suffixes or when a buffer showing all
-possible completions is displayed.@refill
-
-A typical value might look like this:
-
-@example
-@group
-completion-ignored-extensions
- @result{} (".o" ".elc" "~" ".dvi")
-@end group
-@end example
-@end defopt
-
-@node Standard File Names
-@subsection Standard File Names
-
- Most of the file names used in Lisp programs are entered by the user.
-But occasionally a Lisp program needs to specify a standard file name
-for a particular use---typically, to hold customization information
-about each user. For example, abbrev definitions are stored (by
-default) in the file @file{~/.abbrev_defs}; the @code{completion}
-package stores completions in the file @file{~/.completions}. These are
-two of the many standard file names used by parts of Emacs for certain
-purposes.
-
- Various operating systems have their own conventions for valid file
-names and for which file names to use for user profile data. A Lisp
-program which reads a file using a standard file name ought to use, on
-each type of system, a file name suitable for that system. The function
-@code{convert-standard-filename} makes this easy to do.
-
-@defun convert-standard-filename filename
-This function alters the file name @var{filename} to fit the conventions
-of the operating system in use, and returns the result as a new string.
-@end defun
-
- The recommended way to specify a standard file name in a Lisp program
-is to choose a name which fits the conventions of GNU and Unix systems,
-usually with a nondirectory part that starts with a period, and pass it
-to @code{convert-standard-filename} instead of using it directly. Here
-is an example from the @code{completion} package:
-
-@example
-(defvar save-completions-file-name
- (convert-standard-filename "~/.completions")
- "*The file name to save completions to.")
-@end example
-
- On GNU and Unix systems, and on some other systems as well,
-@code{convert-standard-filename} returns its argument unchanged. On
-some other systems, it alters the name to fit the systems's conventions.
-
- For example, on MS-DOS the alterations made by this function include
-converting a leading @samp{.} to @samp{_}, converting a @samp{_} in the
-middle of the name to @samp{.} if there is no other @samp{.}, inserting
-a @samp{.} after eight characters if there is none, and truncating to
-three characters after the @samp{.}. (It makes other changes as well.)
-Thus, @file{.abbrev_defs} becomes @file{_abbrev.def}, and
-@file{.completions} becomes @file{_complet.ion}.
-
-@node Contents of Directories
-@section Contents of Directories
-@cindex directory-oriented functions
-@cindex file names in directory
-
- A directory is a kind of file that contains other files entered under
-various names. Directories are a feature of the file system.
-
- Emacs can list the names of the files in a directory as a Lisp list,
-or display the names in a buffer using the @code{ls} shell command. In
-the latter case, it can optionally display information about each file,
-depending on the options passed to the @code{ls} command.
-
-@defun directory-files directory &optional full-name match-regexp nosort
-This function returns a list of the names of the files in the directory
-@var{directory}. By default, the list is in alphabetical order.
-
-If @var{full-name} is non-@code{nil}, the function returns the files'
-absolute file names. Otherwise, it returns the names relative to
-the specified directory.
-
-If @var{match-regexp} is non-@code{nil}, this function returns only
-those file names that contain a match for that regular expression---the
-other file names are excluded from the list.
-
-@c Emacs 19 feature
-If @var{nosort} is non-@code{nil}, @code{directory-files} does not sort
-the list, so you get the file names in no particular order. Use this if
-you want the utmost possible speed and don't care what order the files
-are processed in. If the order of processing is visible to the user,
-then the user will probably be happier if you do sort the names.
-
-@example
-@group
-(directory-files "~lewis")
- @result{} ("#foo#" "#foo.el#" "." ".."
- "dired-mods.el" "files.texi"
- "files.texi.~1~")
-@end group
-@end example
-
-An error is signaled if @var{directory} is not the name of a directory
-that can be read.
-@end defun
-
-@defun file-name-all-versions file dirname
-This function returns a list of all versions of the file named
-@var{file} in directory @var{dirname}.
-@end defun
-
-@defun insert-directory file switches &optional wildcard full-directory-p
-This function inserts (in the current buffer) a directory listing for
-directory @var{file}, formatted with @code{ls} according to
-@var{switches}. It leaves point after the inserted text.
-
-The argument @var{file} may be either a directory name or a file
-specification including wildcard characters. If @var{wildcard} is
-non-@code{nil}, that means treat @var{file} as a file specification with
-wildcards.
-
-If @var{full-directory-p} is non-@code{nil}, that means @var{file} is a
-directory and switches do not contain @samp{-d}, so that the listing
-should show the full contents of the directory. (The @samp{-d} option
-to @code{ls} says to describe a directory itself rather than its
-contents.)
-
-This function works by running a directory listing program whose name is
-in the variable @code{insert-directory-program}. If @var{wildcard} is
-non-@code{nil}, it also runs the shell specified by
-@code{shell-file-name}, to expand the wildcards.
-@end defun
-
-@defvar insert-directory-program
-This variable's value is the program to run to generate a directory listing
-for the function @code{insert-directory}.
-@end defvar
-
-@node Create/Delete Dirs
-@section Creating and Deleting Directories
-@c Emacs 19 features
-
- Most Emacs Lisp file-manipulation functions get errors when used on
-files that are directories. For example, you cannot delete a directory
-with @code{delete-file}. These special functions exist to create and
-delete directories.
-
-@defun make-directory dirname
-This function creates a directory named @var{dirname}.
-@end defun
-
-@defun delete-directory dirname
-This function deletes the directory named @var{dirname}. The function
-@code{delete-file} does not work for files that are directories; you
-must use @code{delete-directory} for them. If the directory contains
-any files, @code{delete-directory} signals an error.
-@end defun
-
-@node Magic File Names
-@section Making Certain File Names ``Magic''
-@cindex magic file names
-
-@c Emacs 19 feature
-You can implement special handling for certain file names. This is
-called making those names @dfn{magic}. You must supply a regular
-expression to define the class of names (all those that match the
-regular expression), plus a handler that implements all the primitive
-Emacs file operations for file names that do match.
-
-The variable @code{file-name-handler-alist} holds a list of handlers,
-together with regular expressions that determine when to apply each
-handler. Each element has this form:
-
-@example
-(@var{regexp} . @var{handler})
-@end example
-
-@noindent
-All the Emacs primitives for file access and file name transformation
-check the given file name against @code{file-name-handler-alist}. If
-the file name matches @var{regexp}, the primitives handle that file by
-calling @var{handler}.
-
-The first argument given to @var{handler} is the name of the primitive;
-the remaining arguments are the arguments that were passed to that
-operation. (The first of these arguments is typically the file name
-itself.) For example, if you do this:
-
-@example
-(file-exists-p @var{filename})
-@end example
-
-@noindent
-and @var{filename} has handler @var{handler}, then @var{handler} is
-called like this:
-
-@example
-(funcall @var{handler} 'file-exists-p @var{filename})
-@end example
-
-Here are the operations that a magic file name handler gets to handle:
-
-@noindent
-@code{add-name-to-file}, @code{copy-file}, @code{delete-directory},
-@code{delete-file},@*
-@code{diff-latest-backup-file},
-@code{directory-file-name},
-@code{directory-files},@*
-@code{dired-call-process},
-@code{dired-compress-file}, @code{dired-uncache},
-@code{expand-file-name},@*
-@code{file-accessible-directory-p},
-@code{file-attributes}, @code{file-directory-p},@*
-@code{file-executable-p}, @code{file-exists-p}, @code{file-local-copy},
-@code{file-modes}, @code{file-name-all-completions},
-@code{file-name-as-directory}, @code{file-name-completion},@*
-@code{file-name-directory},
-@code{file-name-nondirectory},
-@code{file-name-sans-versions}, @code{file-newer-than-file-p},
-@code{file-ownership-preserved-p},
-@code{file-readable-p}, @code{file-regular-p}, @code{file-symlink-p},
-@code{file-truename}, @code{file-writable-p},
-@code{find-backup-file-name},
-@code{get-file-buffer},
-@code{insert-directory},@*
-@code{insert-file-contents},
-@code{load}, @code{make-directory},
-@code{make-symbolic-link}, @code{rename-file}, @code{set-file-modes},
-@code{set-visited-file-modtime}, @code{shell-command}.
-@code{unhandled-file-name-directory},@*
-@code{vc-registered},
-@code{verify-visited-file-modtime}, @code{write-region}.
-
-Handlers for @code{insert-file-contents} typically need to clear the
-buffer's modified flag, with @code{(set-buffer-modified-p nil)}, if the
-@var{visit} argument is non-@code{nil}. This also has the effect of
-unlocking the buffer if it is locked.
-
-The handler function must handle all of the above operations, and
-possibly others to be added in the future. It need not implement all
-these operations itself---when it has nothing special to do for a
-certain operation, it can reinvoke the primitive, to handle the
-operation ``in the usual way''. It should always reinvoke the primitive
-for an operation it does not recognize. Here's one way to do this:
-
-@smallexample
-(defun my-file-handler (operation &rest args)
- ;; @r{First check for the specific operations}
- ;; @r{that we have special handling for.}
- (cond ((eq operation 'insert-file-contents) @dots{})
- ((eq operation 'write-region) @dots{})
- @dots{}
- ;; @r{Handle any operation we don't know about.}
- (t (let ((inhibit-file-name-handlers
- (cons 'my-file-handler
- (and (eq inhibit-file-name-operation operation)
- inhibit-file-name-handlers)))
- (inhibit-file-name-operation operation))
- (apply operation args)))))
-@end smallexample
-
-When a handler function decides to call the ordinary Emacs primitive for
-the operation at hand, it needs to prevent the primitive from calling
-the same handler once again, thus leading to an infinite recursion. The
-example above shows how to do this, with the variables
-@code{inhibit-file-name-handlers} and
-@code{inhibit-file-name-operation}. Be careful to use them exactly as
-shown above; the details are crucial for proper behavior in the case of
-multiple handlers, and for operations that have two file names that may
-each have handlers.
-
-@defvar inhibit-file-name-handlers
-This variable holds a list of handlers whose use is presently inhibited
-for a certain operation.
-@end defvar
-
-@defvar inhibit-file-name-operation
-The operation for which certain handlers are presently inhibited.
-@end defvar
-
-@defun find-file-name-handler file operation
-This function returns the handler function for file name @var{file}, or
-@code{nil} if there is none. The argument @var{operation} should be the
-operation to be performed on the file---the value you will pass to the
-handler as its first argument when you call it. The operation is needed
-for comparison with @code{inhibit-file-name-operation}.
-@end defun
-
-@defun file-local-copy filename
-This function copies file @var{filename} to an ordinary non-magic file,
-if it isn't one already.
-
-If @var{filename} specifies a ``magic'' file name, which programs
-outside Emacs cannot directly read or write, this copies the contents to
-an ordinary file and returns that file's name.
-
-If @var{filename} is an ordinary file name, not magic, then this function
-does nothing and returns @code{nil}.
-@end defun
-
-@defun unhandled-file-name-directory filename
-This function returns the name of a directory that is not magic.
-It uses the directory part of @var{filename} if that is not magic.
-Otherwise, it asks the handler what to do.
-
-This is useful for running a subprocess; every subprocess must have a
-non-magic directory to serve as its current directory, and this function
-is a good way to come up with one.
-@end defun
-
-@node Format Conversion
-@section File Format Conversion
-
-@cindex file format conversion
-@cindex encoding file formats
-@cindex decoding file formats
- The variable @code{format-alist} defines a list of @dfn{file formats},
-which describe textual representations used in files for the data (text,
-text-properties, and possibly other information) in an Emacs buffer.
-Emacs performs format conversion if appropriate when reading and writing
-files.
-
-@defvar format-alist
-This list contains one format definition for each defined file format.
-@end defvar
-
-@cindex format definition
-Each format definition is a list of this form:
-
-@example
-(@var{name} @var{doc-string} @var{regexp} @var{from-fn} @var{to-fn} @var{modify} @var{mode-fn})
-@end example
-
-Here is what the elements in a format definition mean:
-
-@table @var
-@item name
-The name of this format.
-
-@item doc-string
-A documentation string for the format.
-
-@item regexp
-A regular expression which is used to recognize files represented in
-this format.
-
-@item from-fn
-A function to call to decode data in this format (to convert file data into
-the usual Emacs data representation).
-
-The @var{from-fn} is called with two args, @var{begin} and @var{end},
-which specify the part of the buffer it should convert. It should convert
-the text by editing it in place. Since this can change the length of the
-text, @var{from-fn} should return the modified end position.
-
-One responsibility of @var{from-fn} is to make sure that the beginning
-of the file no longer matches @var{regexp}. Otherwise it is likely to
-get called again.
-
-@item to-fn
-A function to call to encode data in this format (to convert
-the usual Emacs data representation into this format).
-
-The @var{to-fn} is called with two args, @var{begin} and @var{end},
-which specify the part of the buffer it should convert. There are
-two ways it can do the conversion:
-
-@itemize @bullet
-@item
-By editing the buffer in place. In this case, @var{to-fn} should
-return the end-position of the range of text, as modified.
-
-@item
-By returning a list of annotations. This is a list of elements of the
-form @code{(@var{position} . @var{string})}, where @var{position} is an
-integer specifying the relative position in the text to be written, and
-@var{string} is the annotation to add there. The list must be sorted in
-order of position when @var{to-fn} returns it.
-
-When @code{write-region} actually writes the text from the buffer to the
-file, it intermixes the specified annotations at the corresponding
-positions. All this takes place without modifying the buffer.
-@end itemize
-
-@item modify
-A flag, @code{t} if the encoding function modifies the buffer, and
-@code{nil} if it works by returning a list of annotations.
-
-@item mode
-A mode function to call after visiting a file converted from this
-format.
-@end table
-
-The function @code{insert-file-contents} automatically recognizes file
-formats when it reads the specified file. It checks the text of the
-beginning of the file against the regular expressions of the format
-definitions, and if it finds a match, it calls the decoding function for
-that format. Then it checks all the known formats over again.
-It keeps checking them until none of them is applicable.
-
-Visiting a file, with @code{find-file-noselect} or the commands that use
-it, performs conversion likewise (because it calls
-@code{insert-file-contents}); it also calls the mode function for each
-format that it decodes. It stores a list of the format names in the
-buffer-local variable @code{buffer-file-format}.
-
-@defvar buffer-file-format
-This variable states the format of the visited file. More precisely,
-this is a list of the file format names that were decoded in the course
-of visiting the current buffer's file. It is always local in all
-buffers.
-@end defvar
-
-When @code{write-region} writes data into a file, it first calls the
-encoding functions for the formats listed in @code{buffer-file-format},
-in the order of appearance in the list.
-
-@defun format-write-file file format
-This command writes the current buffer contents into the file @var{file}
-in format @var{format}, and makes that format the default for future
-saves of the buffer. The argument @var{format} is a list of format
-names.
-@end defun
-
-@defun format-find-file file format
-This command finds the file @var{file}, converting it according to
-format @var{format}. It also makes @var{format} the default if the
-buffer is saved later.
-
-The argument @var{format} is a list of format names. If @var{format} is
-@code{nil}, no conversion takes place. Interactively, typing just
-@key{RET} for @var{format} specifies @code{nil}.
-@end defun
-
-@defun format-insert-file file format %optional beg end
-This command inserts the contents of file @var{file}, converting it
-according to format @var{format}. If @var{beg} and @var{end} are
-non-@code{nil}, they specify which part of the file to read, as in
-@code{insert-file-contents} (@pxref{Reading from Files}).
-
-The return value is like what @code{insert-file-contents} returns: a
-list of the absolute file name and the length of the data inserted
-(after conversion).
-
-The argument @var{format} is a list of format names. If @var{format} is
-@code{nil}, no conversion takes place. Interactively, typing just
-@key{RET} for @var{format} specifies @code{nil}.
-@end defun
-
-@defvar auto-save-file-format
-This variable specifies the format to use for auto-saving. Its value is
-a list of format names, just like the value of
-@code{buffer-file-format}; but it is used instead of
-@code{buffer-file-format} for writing auto-save files. This variable
-is always local in all buffers.
-@end defvar
-
-@node Files and MS-DOS
-@section Files and MS-DOS
-@cindex MS-DOS file types
-@cindex file types on MS-DOS
-@cindex text files and binary files
-@cindex binary files and text files
-@cindex Windows file types
-
- Emacs on MS-DOS and on Windows NT or 95 makes a distinction between
-text files and binary files. This is necessary because ordinary text
-files on MS-DOS use a two character sequence between lines:
-carriage-return and linefeed (@sc{crlf}). Emacs expects just a newline
-character (a linefeed) between lines. When Emacs reads or writes a text
-file on MS-DOS, it needs to convert the line separators. This means it
-needs to know which files are text files and which are binary. It makes
-this decision when visiting a file, and records the decision in the
-variable @code{buffer-file-type} for use when the file is saved.
-
- @xref{MS-DOS Subprocesses}, for a related feature for subprocesses.
-
-@defvar buffer-file-type
-This variable, automatically local in each buffer, records the file type
-of the buffer's visited file. The value is @code{nil} for text,
-@code{t} for binary.
-@end defvar
-
-@defun find-buffer-file-type filename
-This function determines whether file @var{filename} is a text file
-or a binary file. It returns @code{nil} for text, @code{t} for binary.
-@end defun
-
-@defopt file-name-buffer-file-type-alist
-This variable holds an alist for distinguishing text files from binary
-files. Each element has the form (@var{regexp} . @var{type}), where
-@var{regexp} is matched against the file name, and @var{type} may be is
-@code{nil} for text, @code{t} for binary, or a function to call to
-compute which. If it is a function, then it is called with a single
-argument (the file name) and should return @code{t} or @code{nil}.
-@end defopt
-
-@defopt default-buffer-file-type
-This variable specifies the default file type for files whose names
-don't indicate anything in particular. Its value should be @code{nil}
-for text, or @code{t} for binary.
-@end defopt
-
-@deffn Command find-file-text filename
-Like @code{find-file}, but treat the file as text regardless of its name.
-@end deffn
-
-@deffn Command find-file-binary filename
-Like @code{find-file}, but treat the file as binary regardless of its
-name.
-@end deffn
diff --git a/lispref/frames.texi b/lispref/frames.texi
deleted file mode 100644
index f75b8a3b5eb..00000000000
--- a/lispref/frames.texi
+++ /dev/null
@@ -1,1363 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/frames
-@node Frames, Positions, Windows, Top
-@chapter Frames
-@cindex frame
-
- A @dfn{frame} is a rectangle on the screen that contains one or more
-Emacs windows. A frame initially contains a single main window (plus
-perhaps a minibuffer window), which you can subdivide vertically or
-horizontally into smaller windows.
-
-@cindex terminal frame
-@cindex X window frame
- When Emacs runs on a text-only terminal, it starts with one
-@dfn{terminal frame}. If you create additional ones, Emacs displays
-one and only one at any given time---on the terminal screen, of course.
-
- When Emacs communicates directly with an X server, it does not have a
-terminal frame; instead, it starts with a single @dfn{X window frame}.
-It can display multiple X window frames at the same time, each in its
-own X window.
-
-@defun framep object
-This predicate returns @code{t} if @var{object} is a frame, and
-@code{nil} otherwise.
-@end defun
-
-@menu
-* Creating Frames:: Creating additional frames.
-* Multiple Displays:: Creating frames on other X displays.
-* Frame Parameters:: Controlling frame size, position, font, etc.
-* Frame Titles:: Automatic updating of frame titles.
-* Deleting Frames:: Frames last until explicitly deleted.
-* Finding All Frames:: How to examine all existing frames.
-* Frames and Windows:: A frame contains windows;
- display of text always works through windows.
-* Minibuffers and Frames:: How a frame finds the minibuffer to use.
-* Input Focus:: Specifying the selected frame.
-* Visibility of Frames:: Frames may be visible or invisible, or icons.
-* Raising and Lowering:: Raising a frame makes it hide other X windows;
- lowering it makes the others hide them.
-* Frame Configurations:: Saving the state of all frames.
-* Mouse Tracking:: Getting events that say when the mouse moves.
-* Mouse Position:: Asking where the mouse is, or moving it.
-* Pop-Up Menus:: Displaying a menu for the user to select from.
-* Dialog Boxes:: Displaying a box to ask yes or no.
-* Pointer Shapes:: Specifying the shape of the mouse pointer.
-* X Selections:: Transferring text to and from other X clients.
-* Color Names:: Getting the definitions of color names.
-* Resources:: Getting resource values from the server.
-* Server Data:: Getting info about the X server.
-@end menu
-
- @xref{Display}, for related information.
-
-@node Creating Frames
-@section Creating Frames
-
-To create a new frame, call the function @code{make-frame}.
-
-@defun make-frame &optional alist
-This function creates a new frame. If you are using X, it makes
-an X window frame; otherwise, it makes a terminal frame.
-
-The argument is an alist specifying frame parameters. Any parameters
-not mentioned in @var{alist} default according to the value of the
-variable @code{default-frame-alist}; parameters not specified even there
-default from the standard X defaults file and X resources.
-
-The set of possible parameters depends in principle on what kind of
-window system Emacs uses to display its frames. @xref{X Frame
-Parameters}, for documentation of individual parameters you can specify.
-@end defun
-
-@defvar before-make-frame-hook
-A normal hook run by @code{make-frame} before it actually creates the
-frame.
-@end defvar
-
-@defvar after-make-frame-hook
-A normal hook run by @code{make-frame} after it creates the frame.
-@end defvar
-
-@node Multiple Displays
-@section Multiple Displays
-@cindex multiple displays
-@cindex multiple X terminals
-@cindex displays, multiple
-
- A single Emacs can talk to more than one X Windows display.
-Initially, Emacs uses just one display---the one chosen with the
-@code{DISPLAY} environment variable or with the @samp{--display} option
-(@pxref{Initial Options,,, emacs, The GNU Emacs Manual}). To connect to
-another display, use the command @code{make-frame-on-display} or specify
-the @code{display} frame parameter when you create the frame.
-
- Emacs treats each X server as a separate terminal, giving each one its
-own selected frame and its own minibuffer windows. A few Lisp variables
-have values local to the current terminal (that is, the terminal
-corresponding to the currently selected frame): these are
-@code{default-minibuffer-frame}, @code{defining-kbd-macro},
-@code{last-kbd-macro}, and @code{system-key-alist}. These variables are
-always terminal-local and can never be buffer-local.
-
- A single X server can handle more than one screen. A display name
-@samp{@var{host}.@var{server}.@var{screen}} has three parts; the last
-part specifies the screen number for a given server. When you use two
-screens belonging to one server, Emacs knows by the similarity in their
-names that they share a single keyboard, and it treats them as a single
-terminal.
-
-@deffn Command make-frame-on-display display &optional parameters
-This creates a new frame on display @var{display}, taking the other
-frame parameters from @var{parameters}. Aside from the @var{display}
-argument, it is like @code{make-frame} (@pxref{Creating Frames}).
-@end deffn
-
-@defun x-display-list
-This returns a list that indicates which X displays Emacs has a
-connection to. The elements of the list are strings, and each one is
-a display name.
-@end defun
-
-@defun x-open-connection display &optional xrm-string
-This function opens a connection to the X display @var{display}. It
-does not create a frame on that display, but it permits you to check
-that communication can be established with that display.
-
-The optional argument @var{resource-string}, if not @code{nil}, is a
-string of resource names and values, in the same format used in the
-@file{.Xresources} file. The values you specify override the resource
-values recorded in the X server itself; they apply to all Emacs frames
-created on this display. Here's an example of what this string might
-look like:
-
-@example
-"*BorderWidth: 3\n*InternalBorder: 2\n"
-@end example
-
-@xref{Resources}.
-@end defun
-
-@defun x-close-connection display
-This function closes the connection to display @var{display}. Before
-you can do this, you must first delete all the frames that were open on
-that display (@pxref{Deleting Frames}).
-@end defun
-
-@node Frame Parameters
-@section Frame Parameters
-
-A frame has many parameters that control its appearance and behavior.
-Just what parameters a frame has depends on what display mechanism it
-uses.
-
-Frame parameters exist for the sake of window systems. A terminal frame
-has a few parameters, mostly for compatibility's sake; only the height,
-width and @code{buffer-predicate} parameters really do something.
-
-@menu
-* Parameter Access:: How to change a frame's parameters.
-* Initial Parameters:: Specifying frame parameters when you make a frame.
-* X Frame Parameters:: List of frame parameters.
-* Size and Position:: Changing the size and position of a frame.
-@end menu
-
-@node Parameter Access
-@subsection Access to Frame Parameters
-
-These functions let you read and change the parameter values of a
-frame.
-
-@defun frame-parameters frame
-The function @code{frame-parameters} returns an alist listing all the
-parameters of @var{frame} and their values.
-@end defun
-
-@defun modify-frame-parameters frame alist
-This function alters the parameters of frame @var{frame} based on the
-elements of @var{alist}. Each element of @var{alist} has the form
-@code{(@var{parm} . @var{value})}, where @var{parm} is a symbol naming a
-parameter. If you don't mention a parameter in @var{alist}, its value
-doesn't change.
-@end defun
-
-@node Initial Parameters
-@subsection Initial Frame Parameters
-
-You can specify the parameters for the initial startup frame
-by setting @code{initial-frame-alist} in your @file{.emacs} file.
-
-@defvar initial-frame-alist
-This variable's value is an alist of parameter values used when creating
-the initial X window frame. You can set this variable to specify the
-appearance of the initial frame without altering subsequent frames.
-Each element has the form:
-
-@example
-(@var{parameter} . @var{value})
-@end example
-
-Emacs creates the initial frame before it reads your @file{~/.emacs}
-file. After reading that file, Emacs checks @code{initial-frame-alist},
-and applies the parameter settings in the altered value to the already
-created initial frame.
-
-If these settings affect the frame geometry and appearance, you'll see
-the frame appear with the wrong ones and then change to the specified
-ones. If that bothers you, you can specify the same geometry and
-appearance with X resources; those do take affect before the frame is
-created. @xref{Resources X,, X Resources, emacs, The GNU Emacs Manual}.
-
-X resource settings typically apply to all frames. If you want to
-specify some X resources solely for the sake of the initial frame, and
-you don't want them to apply to subsequent frames, here's how to achieve
-this. Specify parameters in @code{default-frame-alist} to override the
-X resources for subsequent frames; then, to prevent these from affecting
-the initial frame, specify the same parameters in
-@code{initial-frame-alist} with values that match the X resources.
-@end defvar
-
-If these parameters specify a separate minibuffer-only frame with
-@code{(minibuffer . nil)}, and you have not created one, Emacs creates
-one for you.
-
-@defvar minibuffer-frame-alist
-This variable's value is an alist of parameter values used when creating
-an initial minibuffer-only frame---if such a frame is needed, according
-to the parameters for the main initial frame.
-@end defvar
-
-@defvar default-frame-alist
-This is an alist specifying default values of frame parameters for all
-Emacs frames---the first frame, and subsequent frames. In many cases,
-you can get the same results by means of X resources.
-@end defvar
-
-See also @code{special-display-frame-alist}, in @ref{Choosing Window}.
-
-If you use options that specify window appearance when you invoke Emacs,
-they take effect by adding elements to @code{default-frame-alist}. One
-exception is @samp{-geometry}, which adds the specified position to
-@code{initial-frame-alist} instead. @xref{Command Arguments,,, emacs,
-The GNU Emacs Manual}.
-
-@node X Frame Parameters
-@subsection X Window Frame Parameters
-
-Just what parameters a frame has depends on what display mechanism it
-uses. Here is a table of the parameters of an X window frame; of these,
-@code{name}, @code{height}, @code{width}, and @code{buffer-predicate}
-provide meaningful information in non-X frames.
-
-@table @code
-@item name
-The name of the frame. Most window managers display the frame's name in
-the frame's border, at the top of the frame. If you don't specify a
-name, and you have more than one frame, Emacs sets the frame name based
-on the buffer displayed in the frame's selected window.
-
-If you specify the frame name explicitly when you create the frame, the
-name is also used (instead of the name of the Emacs executable) when
-looking up X resources for the frame.
-
-@item display
-The display on which to open this frame. It should be a string of the
-form @code{"@var{host}:@var{dpy}.@var{screen}"}, just like the
-@code{DISPLAY} environment variable.
-
-@item left
-The screen position of the left edge, in pixels, with respect to the
-left edge of the screen. The value may be a positive number @var{pos},
-or a list of the form @code{(+ @var{pos})} which permits specifying a
-negative @var{pos} value.
-
-A negative number @minus{}@var{pos}, or a list of the form @code{(-
-@var{pos})}, actually specifies the position of the right edge of the
-window with respect to the right edge of the screen. A positive value
-of @var{pos} counts toward the left. If the parameter is a negative
-integer @minus{}@var{pos} then @var{pos} is positive!
-
-Some window managers ignore program-specified positions. If you want to
-be sure the position you specify is not ignored, specify a
-non-@code{nil} value for the @code{user-position} parameter as well.
-
-@item top
-The screen position of the top edge, in pixels, with respect to the
-top edge of the screen. The value may be a positive number @var{pos},
-or a list of the form @code{(+ @var{pos})} which permits specifying a
-negative @var{pos} value.
-
-A negative number @minus{}@var{pos}, or a list of the form @code{(-
-@var{pos})}, actually specifies the position of the bottom edge of the
-window with respect to the bottom edge of the screen. A positive value
-of @var{pos} counts toward the top. If the parameter is a negative
-integer @minus{}@var{pos} then @var{pos} is positive!
-
-Some window managers ignore program-specified positions. If you want to
-be sure the position you specify is not ignored, specify a
-non-@code{nil} value for the @code{user-position} parameter as well.
-
-@item icon-left
-The screen position of the left edge @emph{of the frame's icon}, in
-pixels, counting from the left edge of the screen. This takes effect if
-and when the frame is iconified.
-
-@item icon-top
-The screen position of the top edge @emph{of the frame's icon}, in
-pixels, counting from the top edge of the screen. This takes effect if
-and when the frame is iconified.
-
-@item user-position
-When you create a frame and specify its screen position with the
-@code{left} and @code{top} parameters, use this parameter to say whether
-the specified position was user-specified (explicitly requested in some
-way by a human user) or merely program-specified (chosen by a program).
-A non-@code{nil} value says the position was user-specified.
-
-Window managers generally heed user-specified positions, and some heed
-program-specified positions too. But many ignore program-specified
-positions, placing the window in a default fashion or letting the user
-place it with the mouse. Some window managers, including @code{twm},
-let the user specify whether to obey program-specified positions or
-ignore them.
-
-When you call @code{make-frame}, you should specify a non-@code{nil}
-value for this parameter if the values of the @code{left} and @code{top}
-parameters represent the user's stated preference; otherwise, use
-@code{nil}.
-
-@item height
-The height of the frame contents, in characters. (To get the height in
-pixels, call @code{frame-pixel-height}; see @ref{Size and Position}.)
-
-@item width
-The width of the frame contents, in characters. (To get the height in
-pixels, call @code{frame-pixel-width}; see @ref{Size and Position}.)
-
-@item window-id
-The number of the X window for the frame.
-
-@item minibuffer
-Whether this frame has its own minibuffer. The value @code{t} means
-yes, @code{nil} means no, @code{only} means this frame is just a
-minibuffer. If the value is a minibuffer window (in some other frame),
-the new frame uses that minibuffer.
-
-@item buffer-predicate
-The buffer-predicate function for this frame. The function
-@code{other-buffer} uses this predicate (from the selected frame) to
-decide which buffers it should consider, if the predicate is not
-@code{nil}. It calls the predicate with one arg, a buffer, once for
-each buffer; if the predicate returns a non-@code{nil} value, it
-considers that buffer.
-
-@item font
-The name of the font for displaying text in the frame. This is a
-string.
-
-@item auto-raise
-Whether selecting the frame raises it (non-@code{nil} means yes).
-
-@item auto-lower
-Whether deselecting the frame lowers it (non-@code{nil} means yes).
-
-@item vertical-scroll-bars
-Whether the frame has scroll bars for vertical scrolling
-(non-@code{nil} means yes).
-
-@item horizontal-scroll-bars
-Whether the frame has scroll bars for horizontal scrolling
-(non-@code{nil} means yes). (Horizontal scroll bars are not currently
-implemented.)
-
-@item scroll-bar-width
-The width of the vertical scroll bar, in pixels.
-
-@item icon-type
-The type of icon to use for this frame when it is iconified. If the
-value is a string, that specifies a file containing a bitmap to use.
-Any other non-@code{nil} value specifies the default bitmap icon (a
-picture of a gnu); @code{nil} specifies a text icon.
-
-@item icon-name
-The name to use in the icon for this frame, when and if the icon
-appears. If this is @code{nil}, the frame's title is used.
-
-@item foreground-color
-The color to use for the image of a character. This is a string; the X
-server defines the meaningful color names.
-
-@item background-color
-The color to use for the background of characters.
-
-@item mouse-color
-The color for the mouse pointer.
-
-@item cursor-color
-The color for the cursor that shows point.
-
-@item border-color
-The color for the border of the frame.
-
-@item cursor-type
-The way to display the cursor. The legitimate values are @code{bar},
-@code{box}, and @code{(bar . @var{width})}. The symbol @code{box}
-specifies an ordinary black box overlaying the character after point;
-that is the default. The symbol @code{bar} specifies a vertical bar
-between characters as the cursor. @code{(bar . @var{width})} specifies
-a bar @var{width} pixels wide.
-
-@item border-width
-The width in pixels of the window border.
-
-@item internal-border-width
-The distance in pixels between text and border.
-
-@item unsplittable
-If non-@code{nil}, this frame's window is never split automatically.
-
-@item visibility
-The state of visibility of the frame. There are three possibilities:
-@code{nil} for invisible, @code{t} for visible, and @code{icon} for
-iconified. @xref{Visibility of Frames}.
-
-@item menu-bar-lines
-The number of lines to allocate at the top of the frame for a menu bar.
-The default is 1. @xref{Menu Bar}. (In Emacs versions that use the X
-toolkit, there is only one menu bar line; all that matters about the
-number you specify is whether it is greater than zero.)
-
-@item parent-id
-@c ??? Not yet working.
-The X window number of the window that should be the parent of this one.
-Specifying this lets you create an Emacs window inside some other
-application's window. (It is not certain this will be implemented; try
-it and see if it works.)
-@end table
-
-@node Size and Position
-@subsection Frame Size And Position
-
- You can read or change the size and position of a frame using the
-frame parameters @code{left}, @code{top}, @code{height}, and
-@code{width}. Whatever geometry parameters you don't specify are chosen
-by the window manager in its usual fashion.
-
- Here are some special features for working with sizes and positions:
-
-@defun set-frame-position frame left top
-This function sets the position of the top left corner of @var{frame} to
-@var{left} and @var{top}. These arguments are measured in pixels, and
-count from the top left corner of the screen. Negative parameter values
-count up or rightward from the top left corner of the screen.
-@end defun
-
-@defun frame-height &optional frame
-@defunx frame-width &optional frame
-These functions return the height and width of @var{frame}, measured in
-characters. If you don't supply @var{frame}, they use the selected
-frame.
-@end defun
-
-@defun frame-pixel-height &optional frame
-@defunx frame-pixel-width &optional frame
-These functions return the height and width of @var{frame}, measured in
-pixels. If you don't supply @var{frame}, they use the selected frame.
-@end defun
-
-@defun frame-char-height &optional frame
-@defunx frame-char-width &optional frame
-These functions return the height and width of a character in
-@var{frame}, measured in pixels. The values depend on the choice of
-font. If you don't supply @var{frame}, these functions use the selected
-frame.
-@end defun
-
-@defun set-frame-size frame cols rows
-This function sets the size of @var{frame}, measured in characters;
-@var{cols} and @var{rows} specify the new width and height.
-
-To set the size based on values measured in pixels, use
-@code{frame-char-height} and @code{frame-char-width} to convert
-them to units of characters.
-@end defun
-
- The old-fashioned functions @code{set-screen-height} and
-@code{set-screen-width}, which were used to specify the height and width
-of the screen in Emacs versions that did not support multiple frames,
-are still usable. They apply to the selected frame. @xref{Screen
-Size}.
-
-@defun x-parse-geometry geom
-@cindex geometry specification
-The function @code{x-parse-geometry} converts a standard X windows
-geometry string to an alist that you can use as part of the argument to
-@code{make-frame}.
-
-The alist describes which parameters were specified in @var{geom}, and
-gives the values specified for them. Each element looks like
-@code{(@var{parameter} . @var{value})}. The possible @var{parameter}
-values are @code{left}, @code{top}, @code{width}, and @code{height}.
-
-For the size parameters, the value must be an integer. The position
-parameter names @code{left} and @code{top} are not totally accurate,
-because some values indicate the position of the right or bottom edges
-instead. These are the @var{value} possibilities for the position
-parameters:
-
-@table @asis
-@item an integer
-A positive integer relates the left edge or top edge of the window to
-the left or top edge of the screen. A negative integer relates the
-right or bottom edge of the window to the right or bottom edge of the
-screen.
-
-@item @code{(+ @var{position})}
-This specifies the position of the left or top edge of the window
-relative to the left or top edge of the screen. The integer
-@var{position} may be positive or negative; a negative value specifies a
-position outside the screen.
-
-@item @code{(- @var{position})}
-This specifies the position of the right or bottom edge of the window
-relative to the right or bottom edge of the screen. The integer
-@var{position} may be positive or negative; a negative value specifies a
-position outside the screen.
-@end table
-
-Here is an example:
-
-@example
-(x-parse-geometry "35x70+0-0")
- @result{} ((width . 35) (height . 70)
- (left . 0) (top - 0))
-@end example
-@end defun
-
-@ignore
-New functions @code{set-frame-height} and @code{set-frame-width} set the
-size of a specified frame. The frame is the first argument; the size is
-the second.
-@end ignore
-
-@node Frame Titles
-@section Frame Titles
-
-Every frame has a title; most window managers display the frame title at
-the top of the frame. You can specify an explicit title with the
-@code{name} frame property. But normally you don't specify this
-explicitly, and Emacs computes the title automatically.
-
-Emacs computes the frame title based on a template stored in the
-variable @code{frame-title-format}.
-
-@defvar frame-title-format
-This variable specifies how to compute a title for a frame
-when you have not explicitly specified one.
-
-The variable's value is actually a mode line construct, just like
-@code{mode-line-format}. @xref{Mode Line Data}.
-@end defvar
-
-@defvar icon-title-format
-This variable specifies how to compute the title for an iconified frame,
-when you have not explicitly specified the frame title. This title
-appears in the icon itself.
-@end defvar
-
-@defvar multiple-frames
-This variable is set automatically by Emacs. Its value is @code{t} when
-there are two or more frames (not counting minibuffer-only frames or
-invisible frames). The default value of @code{frame-title-format} uses
-@code{multiple-frames} so as to put the buffer name in the frame title
-only when there is more than one frame.
-@end defvar
-
-@node Deleting Frames
-@section Deleting Frames
-@cindex deletion of frames
-
-Frames remain potentially visible until you explicitly @dfn{delete}
-them. A deleted frame cannot appear on the screen, but continues to
-exist as a Lisp object until there are no references to it. There is no
-way to cancel the deletion of a frame aside from restoring a saved frame
-configuration (@pxref{Frame Configurations}); this is similar to the
-way windows behave.
-
-@deffn Command delete-frame &optional frame
-This function deletes the frame @var{frame}. By default, @var{frame} is
-the selected frame.
-@end deffn
-
-@defun frame-live-p frame
-The function @code{frame-live-p} returns non-@code{nil} if the frame
-@var{frame} has not been deleted.
-@end defun
-
- Some window managers provide a command to delete a window. These work
-by sending a special message to the program that operates the window.
-When Emacs gets one of these commands, it generates a
-@code{delete-frame} event, whose normal definition is a command that
-calls the function @code{delete-frame}. @xref{Misc Events}.
-
-@node Finding All Frames
-@section Finding All Frames
-
-@defun frame-list
-The function @code{frame-list} returns a list of all the frames that
-have not been deleted. It is analogous to @code{buffer-list} for
-buffers. The list that you get is newly created, so modifying the list
-doesn't have any effect on the internals of Emacs.
-@end defun
-
-@defun visible-frame-list
-This function returns a list of just the currently visible frames.
-@xref{Visibility of Frames}. (Terminal frames always count as
-``visible'', even though only the selected one is actually displayed.)
-@end defun
-
-@defun next-frame &optional frame minibuf
-The function @code{next-frame} lets you cycle conveniently through all
-the frames from an arbitrary starting point. It returns the ``next''
-frame after @var{frame} in the cycle. If @var{frame} is omitted or
-@code{nil}, it defaults to the selected frame.
-
-The second argument, @var{minibuf}, says which frames to consider:
-
-@table @asis
-@item @code{nil}
-Exclude minibuffer-only frames.
-@item @code{visible}
-Consider all visible frames.
-@item 0
-Consider all visible or iconified frames.
-@item a window
-Consider only the frames using that particular window as their
-minibuffer.
-@item anything else
-Consider all frames.
-@end table
-@end defun
-
-@defun previous-frame &optional frame minibuf
-Like @code{next-frame}, but cycles through all frames in the opposite
-direction.
-@end defun
-
- See also @code{next-window} and @code{previous-window}, in @ref{Cyclic
-Window Ordering}.
-
-@node Frames and Windows
-@section Frames and Windows
-
- Each window is part of one and only one frame; you can get the frame
-with @code{window-frame}.
-
-@defun window-frame window
-This function returns the frame that @var{window} is on.
-@end defun
-
- All the non-minibuffer windows in a frame are arranged in a cyclic
-order. The order runs from the frame's top window, which is at the
-upper left corner, down and to the right, until it reaches the window at
-the lower right corner (always the minibuffer window, if the frame has
-one), and then it moves back to the top.
-
-@defun frame-top-window frame
-This returns the topmost, leftmost window of frame @var{frame}.
-@end defun
-
-At any time, exactly one window on any frame is @dfn{selected within the
-frame}. The significance of this designation is that selecting the
-frame also selects this window. You can get the frame's current
-selected window with @code{frame-selected-window}.
-
-@defun frame-selected-window frame
-This function returns the window on @var{frame} that is selected within
-@var{frame}.
-@end defun
-
-Conversely, selecting a window for Emacs with @code{select-window} also
-makes that window selected within its frame. @xref{Selecting Windows}.
-
-Another function that (usually) returns one of the windows in a frame is
-@code{minibuffer-window}. @xref{Minibuffer Misc}.
-
-@node Minibuffers and Frames
-@section Minibuffers and Frames
-
-Normally, each frame has its own minibuffer window at the bottom, which
-is used whenever that frame is selected. If the frame has a minibuffer,
-you can get it with @code{minibuffer-window} (@pxref{Minibuffer Misc}).
-
-However, you can also create a frame with no minibuffer. Such a frame
-must use the minibuffer window of some other frame. When you create the
-frame, you can specify explicitly the minibuffer window to use (in some
-other frame). If you don't, then the minibuffer is found in the frame
-which is the value of the variable @code{default-minibuffer-frame}. Its
-value should be a frame that does have a minibuffer.
-
-If you use a minibuffer-only frame, you might want that frame to raise
-when you enter the minibuffer. If so, set the variable
-@code{minibuffer-auto-raise} to @code{t}. @xref{Raising and Lowering}.
-
-@defvar default-minibuffer-frame
-This variable specifies the frame to use for the minibuffer window, by
-default. It is always local to the current terminal and cannot be
-buffer-local. @xref{Multiple Displays}.
-@end defvar
-
-@node Input Focus
-@section Input Focus
-@cindex input focus
-@cindex selected frame
-
-At any time, one frame in Emacs is the @dfn{selected frame}. The selected
-window always resides on the selected frame.
-
-@defun selected-frame
-This function returns the selected frame.
-@end defun
-
-The X server normally directs keyboard input to the X window that the
-mouse is in. Some window managers use mouse clicks or keyboard events
-to @dfn{shift the focus} to various X windows, overriding the normal
-behavior of the server.
-
-Lisp programs can switch frames ``temporarily'' by calling
-the function @code{select-frame}. This does not override the window
-manager; rather, it escapes from the window manager's control until
-that control is somehow reasserted.
-
-When using a text-only terminal, there is no window manager; therefore,
-@code{switch-frame} is the only way to switch frames, and the effect
-lasts until overridden by a subsequent call to @code{switch-frame}.
-Only the selected terminal frame is actually displayed on the terminal.
-Each terminal screen except for the initial one has a number, and the
-number of the selected frame appears in the mode line after the word
-@samp{Emacs} (@pxref{Mode Line Variables}).
-
-@c ??? This is not yet implemented properly.
-@defun select-frame frame
-This function selects frame @var{frame}, temporarily disregarding the
-focus of the X server if any. The selection of @var{frame} lasts until
-the next time the user does something to select a different frame, or
-until the next time this function is called.
-@end defun
-
-Emacs cooperates with the X server and the window managers by arranging
-to select frames according to what the server and window manager ask
-for. It does so by generating a special kind of input event, called a
-@dfn{focus} event. The command loop handles a focus event by calling
-@code{handle-switch-frame}. @xref{Focus Events}.
-
-@deffn Command handle-switch-frame frame
-This function handles a focus event by selecting frame @var{frame}.
-
-Focus events normally do their job by invoking this command.
-Don't call it for any other reason.
-@end deffn
-
-@defun redirect-frame-focus frame focus-frame
-This function redirects focus from @var{frame} to @var{focus-frame}.
-This means that @var{focus-frame} will receive subsequent keystrokes
-intended for @var{frame}. After such an event, the value of
-@code{last-event-frame} will be @var{focus-frame}. Also, switch-frame
-events specifying @var{frame} will instead select @var{focus-frame}.
-
-If @var{focus-frame} is @code{nil}, that cancels any existing
-redirection for @var{frame}, which therefore once again receives its own
-events.
-
-One use of focus redirection is for frames that don't have minibuffers.
-These frames use minibuffers on other frames. Activating a minibuffer
-on another frame redirects focus to that frame. This puts the focus on
-the minibuffer's frame, where it belongs, even though the mouse remains
-in the frame that activated the minibuffer.
-
-Selecting a frame can also change focus redirections. Selecting frame
-@code{bar}, when @code{foo} had been selected, changes any redirections
-pointing to @code{foo} so that they point to @code{bar} instead. This
-allows focus redirection to work properly when the user switches from
-one frame to another using @code{select-window}.
-
-This means that a frame whose focus is redirected to itself is treated
-differently from a frame whose focus is not redirected.
-@code{select-frame} affects the former but not the latter.
-
-The redirection lasts until @code{redirect-frame-focus} is called to
-change it.
-@end defun
-
-@node Visibility of Frames
-@section Visibility of Frames
-@cindex visible frame
-@cindex invisible frame
-@cindex iconified frame
-@cindex frame visibility
-
-An X window frame may be @dfn{visible}, @dfn{invisible}, or
-@dfn{iconified}. If it is visible, you can see its contents. If it is
-iconified, the frame's contents do not appear on the screen, but an icon
-does. If the frame is invisible, it doesn't show on the screen, not
-even as an icon.
-
-Visibility is meaningless for terminal frames, since only the selected
-one is actually displayed in any case.
-
-@deffn Command make-frame-visible &optional frame
-This function makes frame @var{frame} visible. If you omit @var{frame},
-it makes the selected frame visible.
-@end deffn
-
-@deffn Command make-frame-invisible &optional frame
-This function makes frame @var{frame} invisible. If you omit
-@var{frame}, it makes the selected frame invisible.
-@end deffn
-
-@deffn Command iconify-frame &optional frame
-This function iconifies frame @var{frame}. If you omit @var{frame}, it
-iconifies the selected frame.
-@end deffn
-
-@defun frame-visible-p frame
-This returns the visibility status of frame @var{frame}. The value is
-@code{t} if @var{frame} is visible, @code{nil} if it is invisible, and
-@code{icon} if it is iconified.
-@end defun
-
- The visibility status of a frame is also available as a frame
-parameter. You can read or change it as such. @xref{X Frame
-Parameters}.
-
- The user can iconify and deiconify frames with the window manager.
-This happens below the level at which Emacs can exert any control, but
-Emacs does provide events that you can use to keep track of such
-changes. @xref{Misc Events}.
-
-@node Raising and Lowering
-@section Raising and Lowering Frames
-
-The X Window System uses a desktop metaphor. Part of this metaphor is
-the idea that windows are stacked in a notional third dimension
-perpendicular to the screen surface, and thus ordered from ``highest''
-to ``lowest''. Where two windows overlap, the one higher up covers the
-one underneath. Even a window at the bottom of the stack can be seen if
-no other window overlaps it.
-
-@cindex raising a frame
-@cindex lowering a frame
-A window's place in this ordering is not fixed; in fact, users tend to
-change the order frequently. @dfn{Raising} a window means moving it
-``up'', to the top of the stack. @dfn{Lowering} a window means moving
-it to the bottom of the stack. This motion is in the notional third
-dimension only, and does not change the position of the window on the
-screen.
-
-You can raise and lower Emacs's X windows with these functions:
-
-@deffn Command raise-frame frame
-This function raises frame @var{frame}.
-@end deffn
-
-@deffn Command lower-frame frame
-This function lowers frame @var{frame}.
-@end deffn
-
-@defopt minibuffer-auto-raise
-If this is non-@code{nil}, activation of the minibuffer raises the frame
-that the minibuffer window is in.
-@end defopt
-
-You can also enable auto-raise (raising automatically when a frame is
-selected) or auto-lower (lowering automatically when it is deselected)
-for any frame using frame parameters. @xref{X Frame Parameters}.
-
-@node Frame Configurations
-@section Frame Configurations
-@cindex frame configuration
-
- A @dfn{frame configuration} records the current arrangement of frames,
-all their properties, and the window configuration of each one.
-
-@defun current-frame-configuration
-This function returns a frame configuration list that describes
-the current arrangement of frames and their contents.
-@end defun
-
-@defun set-frame-configuration configuration
-This function restores the state of frames described in
-@var{configuration}.
-@end defun
-
-@node Mouse Tracking
-@section Mouse Tracking
-@cindex mouse tracking
-@cindex tracking the mouse
-
-Sometimes it is useful to @dfn{track} the mouse, which means to display
-something to indicate where the mouse is and move the indicator as the
-mouse moves. For efficient mouse tracking, you need a way to wait until
-the mouse actually moves.
-
-The convenient way to track the mouse is to ask for events to represent
-mouse motion. Then you can wait for motion by waiting for an event. In
-addition, you can easily handle any other sorts of events that may
-occur. That is useful, because normally you don't want to track the
-mouse forever---only until some other event, such as the release of a
-button.
-
-@defspec track-mouse body@dots{}
-Execute @var{body}, meanwhile generating input events for mouse motion.
-The code in @var{body} can read these events with @code{read-event} or
-@code{read-key-sequence}. @xref{Motion Events}, for the format of mouse
-motion events.
-
-The value of @code{track-mouse} is that of the last form in @var{body}.
-@end defspec
-
-The usual purpose of tracking mouse motion is to indicate on the screen
-the consequences of pushing or releasing a button at the current
-position.
-
-In many cases, you can avoid the need to track the mouse by using
-the @code{mouse-face} text property (@pxref{Special Properties}).
-That works at a much lower level and runs more smoothly than
-Lisp-level mouse tracking.
-
-@ignore
-@c These are not implemented yet.
-
-These functions change the screen appearance instantaneously. The
-effect is transient, only until the next ordinary Emacs redisplay. That
-is ok for mouse tracking, since it doesn't make sense for mouse tracking
-to change the text, and the body of @code{track-mouse} normally reads
-the events itself and does not do redisplay.
-
-@defun x-contour-region window beg end
-This function draws lines to make a box around the text from @var{beg}
-to @var{end}, in window @var{window}.
-@end defun
-
-@defun x-uncontour-region window beg end
-This function erases the lines that would make a box around the text
-from @var{beg} to @var{end}, in window @var{window}. Use it to remove
-a contour that you previously made by calling @code{x-contour-region}.
-@end defun
-
-@defun x-draw-rectangle frame left top right bottom
-This function draws a hollow rectangle on frame @var{frame} with the
-specified edge coordinates, all measured in pixels from the inside top
-left corner. It uses the cursor color, the one used for indicating the
-location of point.
-@end defun
-
-@defun x-erase-rectangle frame left top right bottom
-This function erases a hollow rectangle on frame @var{frame} with the
-specified edge coordinates, all measured in pixels from the inside top
-left corner. Erasure means redrawing the text and background that
-normally belong in the specified rectangle.
-@end defun
-@end ignore
-
-@node Mouse Position
-@section Mouse Position
-@cindex mouse position
-@cindex position of mouse
-
- The functions @code{mouse-position} and @code{set-mouse-position}
-give access to the current position of the mouse.
-
-@defun mouse-position
-This function returns a description of the position of the mouse. The
-value looks like @code{(@var{frame} @var{x} . @var{y})}, where @var{x}
-and @var{y} are integers giving the position in characters relative to
-the top left corner of the inside of @var{frame}.
-@end defun
-
-@defun set-mouse-position frame x y
-This function @dfn{warps the mouse} to position @var{x}, @var{y} in
-frame @var{frame}. The arguments @var{x} and @var{y} are integers,
-giving the position in characters relative to the top left corner of the
-inside of @var{frame}.
-@end defun
-
-@defun mouse-pixel-position
-This function is like @code{mouse-position} except that it returns
-coordinates in units of pixels rather than units of characters.
-@end defun
-
-@defun set-mouse-pixel-position frame x y
-This function warps the mouse like @code{set-mouse-position} except that
-@var{x} and @var{y} are in units of pixels rather than units of
-characters. These coordinates are not required to be within the frame.
-@end defun
-
-@need 3000
-
-@node Pop-Up Menus
-@section Pop-Up Menus
-
- When using X windows, a Lisp program can pop up a menu which the
-user can choose from with the mouse.
-
-@defun x-popup-menu position menu
-This function displays a pop-up menu and returns an indication of
-what selection the user makes.
-
-The argument @var{position} specifies where on the screen to put the
-menu. It can be either a mouse button event (which says to put the menu
-where the user actuated the button) or a list of this form:
-
-@example
-((@var{xoffset} @var{yoffset}) @var{window})
-@end example
-
-@noindent
-where @var{xoffset} and @var{yoffset} are coordinates, measured in
-pixels, counting from the top left corner of @var{window}'s frame.
-
-If @var{position} is @code{t}, it means to use the current mouse
-position. If @var{position} is @code{nil}, it means to precompute the
-key binding equivalents for the keymaps specified in @var{menu},
-without actually displaying or popping up the menu.
-
-The argument @var{menu} says what to display in the menu. It can be a
-keymap or a list of keymaps (@pxref{Menu Keymaps}). Alternatively, it
-can have the following form:
-
-@example
-(@var{title} @var{pane1} @var{pane2}...)
-@end example
-
-@noindent
-where each pane is a list of form
-
-@example
-(@var{title} (@var{line} . @var{item})...)
-@end example
-
-Each @var{line} should be a string, and each @var{item} should be the
-value to return if that @var{line} is chosen.
-@end defun
-
- @strong{Usage note:} Don't use @code{x-popup-menu} to display a menu if
-a prefix key with a menu keymap would do the job. If you use a menu
-keymap to implement a menu, @kbd{C-h c} and @kbd{C-h a} can see the
-individual items in that menu and provide help for them. If instead you
-implement the menu by defining a command that calls @code{x-popup-menu},
-the help facilities cannot know what happens inside that command, so
-they cannot give any help for the menu's items.
-
- The menu bar mechanism, which lets you switch between submenus by
-moving the mouse, cannot look within the definition of a command to see
-that it calls @code{x-popup-menu}. Therefore, if you try to implement a
-submenu using @code{x-popup-menu}, it cannot work with the menu bar in
-an integrated fashion. This is why all menu bar submenus are
-implemented with menu keymaps within the parent menu, and never with
-@code{x-popup-menu}. @xref{Menu Bar},
-
- If you want a menu bar submenu to have contents that vary, you should
-still use a menu keymap to implement it. To make the contents vary, add
-a hook function to @code{menu-bar-update-hook} to update the contents of
-the menu keymap as necessary.
-
-@node Dialog Boxes
-@section Dialog Boxes
-@cindex dialog boxes
-
- A dialog box is a variant of a pop-up menu. It looks a little
-different (if Emacs uses an X toolkit), it always appears in the center
-of a frame, and it has just one level and one pane. The main use of
-dialog boxes is for asking questions that the user can answer with
-``yes'', ``no'', and a few other alternatives. The functions
-@code{y-or-n-p} and @code{yes-or-no-p} use dialog boxes instead of the
-keyboard, when called from commands invoked by mouse clicks.
-
-@defun x-popup-dialog position contents
-This function displays a pop-up dialog box and returns an indication of
-what selection the user makes. The argument @var{contents} specifies
-the alternatives to offer; it has this format:
-
-@example
-(@var{title} (@var{string} . @var{value})@dots{})
-@end example
-
-@noindent
-which looks like the list that specifies a single pane for
-@code{x-popup-menu}.
-
-The return value is @var{value} from the chosen alternative.
-
-An element of the list may be just a string instead of a cons cell
-@code{(@var{string} . @var{value})}. That makes a box that cannot
-be selected.
-
-If @code{nil} appears in the list, it separates the left-hand items from
-the right-hand items; items that precede the @code{nil} appear on the
-left, and items that follow the @code{nil} appear on the right. If you
-don't include a @code{nil} in the list, then approximately half the
-items appear on each side.
-
-Dialog boxes always appear in the center of a frame; the argument
-@var{position} specifies which frame. The possible values are as in
-@code{x-popup-menu}, but the precise coordinates don't matter; only the
-frame matters.
-
-If your Emacs executable does not use an X toolkit, then it cannot
-display a real dialog box; so instead it displays the same items in a
-pop-up menu in the center of the frame.
-@end defun
-
-@node Pointer Shapes
-@section Pointer Shapes
-@cindex pointer shape
-@cindex mouse pointer shape
-
- These variables specify which shape to use for the mouse pointer in
-various situations:
-
-@table @code
-@item x-pointer-shape
-@vindex x-pointer-shape
-This variable specifies the pointer shape to use ordinarily in the Emacs
-frame.
-
-@item x-sensitive-text-pointer-shape
-@vindex x-sensitive-text-pointer-shape
-This variable specifies the pointer shape to use when the mouse
-is over mouse-sensitive text.
-@end table
-
- These variables affect newly created frames. They do not normally
-affect existing frames; however, if you set the mouse color of a frame,
-that also updates its pointer shapes based on the current values of
-these variables. @xref{X Frame Parameters}.
-
- The values you can use, to specify either of these pointer shapes, are
-defined in the file @file{lisp/term/x-win.el}. Use @kbd{M-x apropos
-@key{RET} x-pointer @key{RET}} to see a list of them.
-
-@node X Selections
-@section X Selections
-@cindex selection (for X windows)
-
-The X server records a set of @dfn{selections} which permit transfer of
-data between application programs. The various selections are
-distinguished by @dfn{selection types}, represented in Emacs by
-symbols. X clients including Emacs can read or set the selection for
-any given type.
-
-@defun x-set-selection type data
-This function sets a ``selection'' in the X server. It takes two
-arguments: a selection type @var{type}, and the value to assign to it,
-@var{data}. If @var{data} is @code{nil}, it means to clear out the
-selection. Otherwise, @var{data} may be a string, a symbol, an integer
-(or a cons of two integers or list of two integers), an overlay, or a
-cons of two markers pointing to the same buffer. An overlay or a pair
-of markers stands for text in the overlay or between the markers.
-
-The data may also be a vector of valid non-vector selection values.
-
-Each possible @var{type} has its own selection value, which changes
-independently. The usual values of @var{type} are @code{PRIMARY} and
-@code{SECONDARY}; these are symbols with upper-case names, in accord
-with X Window System conventions. The default is @code{PRIMARY}.
-@end defun
-
-@defun x-get-selection &optional type data-type
-This function accesses selections set up by Emacs or by other X
-clients. It takes two optional arguments, @var{type} and
-@var{data-type}. The default for @var{type}, the selection type, is
-@code{PRIMARY}.
-
-The @var{data-type} argument specifies the form of data conversion to
-use, to convert the raw data obtained from another X client into Lisp
-data. Meaningful values include @code{TEXT}, @code{STRING},
-@code{TARGETS}, @code{LENGTH}, @code{DELETE}, @code{FILE_NAME},
-@code{CHARACTER_POSITION}, @code{LINE_NUMBER}, @code{COLUMN_NUMBER},
-@code{OWNER_OS}, @code{HOST_NAME}, @code{USER}, @code{CLASS},
-@code{NAME}, @code{ATOM}, and @code{INTEGER}. (These are symbols with
-upper-case names in accord with X conventions.) The default for
-@var{data-type} is @code{STRING}.
-@end defun
-
-@cindex cut buffer
-The X server also has a set of numbered @dfn{cut buffers} which can
-store text or other data being moved between applications. Cut buffers
-are considered obsolete, but Emacs supports them for the sake of X
-clients that still use them.
-
-@defun x-get-cut-buffer n
-This function returns the contents of cut buffer number @var{n}.
-@end defun
-
-@defun x-set-cut-buffer string
-This function stores @var{string} into the first cut buffer (cut buffer
-0), moving the other values down through the series of cut buffers, much
-like the way successive kills in Emacs move down the kill ring.
-@end defun
-
-@node Color Names
-@section Color Names
-
-@defun x-color-defined-p color &optional frame
-This function reports whether a color name is meaningful. It returns
-@code{t} if so; otherwise, @code{nil}. The argument @var{frame} says
-which frame's display to ask about; if @var{frame} is omitted or
-@code{nil}, the selected frame is used.
-
-Note that this does not tell you whether the display you are using
-really supports that color. You can ask for any defined color on any
-kind of display, and you will get some result---that is how the X server
-works. Here's an approximate way to test whether your display supports
-the color @var{color}:
-
-@example
-(defun x-color-supported-p (color &optional frame)
- (and (x-color-defined-p color frame)
- (or (x-display-color-p frame)
- (member color '("black" "white"))
- (and (> (x-display-planes frame) 1)
- (equal color "gray")))))
-@end example
-@end defun
-
-@defun x-color-values color &optional frame
-This function returns a value that describes what @var{color} should
-ideally look like. If @var{color} is defined, the value is a list of
-three integers, which give the amount of red, the amount of green, and
-the amount of blue. Each integer ranges in principle from 0 to 65535,
-but in practice no value seems to be above 65280. If @var{color} is not
-defined, the value is @code{nil}.
-
-@example
-(x-color-values "black")
- @result{} (0 0 0)
-(x-color-values "white")
- @result{} (65280 65280 65280)
-(x-color-values "red")
- @result{} (65280 0 0)
-(x-color-values "pink")
- @result{} (65280 49152 51968)
-(x-color-values "hungry")
- @result{} nil
-@end example
-
-The color values are returned for @var{frame}'s display. If @var{frame}
-is omitted or @code{nil}, the information is return for the selected
-frame's display.
-@end defun
-
-@node Resources
-@section X Resources
-
-@defun x-get-resource attribute class &optional component subclass
-The function @code{x-get-resource} retrieves a resource value from the X
-Windows defaults database.
-
-Resources are indexed by a combination of a @dfn{key} and a @dfn{class}.
-This function searches using a key of the form
-@samp{@var{instance}.@var{attribute}} (where @var{instance} is the name
-under which Emacs was invoked), and using @samp{Emacs.@var{class}} as
-the class.
-
-The optional arguments @var{component} and @var{subclass} add to the key
-and the class, respectively. You must specify both of them or neither.
-If you specify them, the key is
-@samp{@var{instance}.@var{component}.@var{attribute}}, and the class is
-@samp{Emacs.@var{class}.@var{subclass}}.
-@end defun
-
- @xref{Resources X,, X Resources, emacs, The GNU Emacs Manual}.
-
-@node Server Data
-@section Data about the X Server
-
- This section describes functions you can use to get information about
-the capabilities and origin of an X display that Emacs is using. Each
-of these functions lets you specify the display you are interested in:
-the @var{display} argument can be either a display name, or a frame
-(meaning use the display that frame is on). If you omit the
-@var{display} argument, or specify @code{nil}, that means to use the
-selected frame's display.
-
-@defun x-display-screens &optional display
-This function returns the number of screens associated with the display.
-@end defun
-
-@defun x-server-version &optional display
-This function returns the list of version numbers of the X server
-running the display.
-@end defun
-
-@defun x-server-vendor &optional display
-This function returns the vendor that provided the X server software.
-@end defun
-
-@defun x-display-pixel-height &optional display
-This function returns the height of the screen in pixels.
-@end defun
-
-@defun x-display-mm-height &optional display
-This function returns the height of the screen in millimeters.
-@end defun
-
-@defun x-display-pixel-width &optional display
-This function returns the width of the screen in pixels.
-@end defun
-
-@defun x-display-mm-width &optional display
-This function returns the width of the screen in millimeters.
-@end defun
-
-@defun x-display-backing-store &optional display
-This function returns the backing store capability of the screen.
-Values can be the symbols @code{always}, @code{when-mapped}, or
-@code{not-useful}.
-@end defun
-
-@defun x-display-save-under &optional display
-This function returns non-@code{nil} if the display supports the
-SaveUnder feature.
-@end defun
-
-@defun x-display-planes &optional display
-This function returns the number of planes the display supports.
-@end defun
-
-@defun x-display-visual-class &optional display
-This function returns the visual class for the screen. The value is one
-of the symbols @code{static-gray}, @code{gray-scale},
-@code{static-color}, @code{pseudo-color}, @code{true-color}, and
-@code{direct-color}.
-@end defun
-
-@defun x-display-grayscale-p &optional display
-This function returns @code{t} if the screen can display shades of gray.
-@end defun
-
-@defun x-display-color-p &optional display
-This function returns @code{t} if the screen is a color screen.
-@end defun
-
-@defun x-display-color-cells &optional display
-This function returns the number of color cells the screen supports.
-@end defun
-
-@ignore
-@defvar x-no-window-manager
-This variable's value is is @code{t} if no X window manager is in use.
-@end defvar
-@end ignore
-
-@ignore
-@item
-The functions @code{x-pixel-width} and @code{x-pixel-height} return the
-width and height of an X Window frame, measured in pixels.
-@end ignore
diff --git a/lispref/front-cover-1.texi b/lispref/front-cover-1.texi
deleted file mode 100644
index cde9f952e9a..00000000000
--- a/lispref/front-cover-1.texi
+++ /dev/null
@@ -1,52 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-@comment %**start of header
-@setfilename front1.info
-@settitle GNU Emacs Lisp Reference Manual
-@smallbook
-@comment %**end of header
-
-@titlepage
-.
-@sp 2
-@center @titlefont{The}
-@sp 1
-@center @titlefont{GNU}
-@sp 1
-@center @titlefont{Emacs Lisp}
-@sp 1
-@center @titlefont{Reference}
-@sp 1
-@center @titlefont{Manual}
-@sp 2
-@center GNU Emacs Version 19
-@center for Unix Users
-@center Edition 2.3, June 1994
-@sp 2
-@center @titlefont{Volume 1}
-@sp 2
-@center by Bil Lewis, Dan LaLiberte,
-@center and the GNU Manual Group
-@page
-.
-@sp 5
-@center @titlefont{The}
-@sp 1
-@center @titlefont{GNU}
-@sp 1
-@center @titlefont{Emacs Lisp}
-@sp 1
-@center @titlefont{Reference}
-@sp 1
-@center @titlefont{Manual}
-@sp 2
-@center GNU Emacs Version 19
-@center for Unix Users
-@center Edition 2.3, June 1994
-@sp 2
-@center @titlefont{Volume 2}
-@sp 2
-@center by Bil Lewis, Dan LaLiberte,
-@center and the GNU Manual Group
-
-@end titlepage
-@bye
diff --git a/lispref/functions.texi b/lispref/functions.texi
deleted file mode 100644
index 035d231cf48..00000000000
--- a/lispref/functions.texi
+++ /dev/null
@@ -1,1138 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/functions
-@node Functions, Macros, Variables, Top
-@chapter Functions
-
- A Lisp program is composed mainly of Lisp functions. This chapter
-explains what functions are, how they accept arguments, and how to
-define them.
-
-@menu
-* What Is a Function:: Lisp functions vs. primitives; terminology.
-* Lambda Expressions:: How functions are expressed as Lisp objects.
-* Function Names:: A symbol can serve as the name of a function.
-* Defining Functions:: Lisp expressions for defining functions.
-* Calling Functions:: How to use an existing function.
-* Mapping Functions:: Applying a function to each element of a list, etc.
-* Anonymous Functions:: Lambda expressions are functions with no names.
-* Function Cells:: Accessing or setting the function definition
- of a symbol.
-* Inline Functions:: Defining functions that the compiler will open code.
-* Related Topics:: Cross-references to specific Lisp primitives
- that have a special bearing on how functions work.
-@end menu
-
-@node What Is a Function
-@section What Is a Function?
-
- In a general sense, a function is a rule for carrying on a computation
-given several values called @dfn{arguments}. The result of the
-computation is called the value of the function. The computation can
-also have side effects: lasting changes in the values of variables or
-the contents of data structures.
-
- Here are important terms for functions in Emacs Lisp and for other
-function-like objects.
-
-@table @dfn
-@item function
-@cindex function
-In Emacs Lisp, a @dfn{function} is anything that can be applied to
-arguments in a Lisp program. In some cases, we use it more
-specifically to mean a function written in Lisp. Special forms and
-macros are not functions.
-
-@item primitive
-@cindex primitive
-@cindex subr
-@cindex built-in function
-A @dfn{primitive} is a function callable from Lisp that is written in C,
-such as @code{car} or @code{append}. These functions are also called
-@dfn{built-in} functions or @dfn{subrs}. (Special forms are also
-considered primitives.)
-
-Usually the reason that a function is a primitives is because it is
-fundamental, because it provides a low-level interface to operating
-system services, or because it needs to run fast. Primitives can be
-modified or added only by changing the C sources and recompiling the
-editor. See @ref{Writing Emacs Primitives}.
-
-@item lambda expression
-A @dfn{lambda expression} is a function written in Lisp.
-These are described in the following section.
-@ifinfo
-@xref{Lambda Expressions}.
-@end ifinfo
-
-@item special form
-A @dfn{special form} is a primitive that is like a function but does not
-evaluate all of its arguments in the usual way. It may evaluate only
-some of the arguments, or may evaluate them in an unusual order, or
-several times. Many special forms are described in @ref{Control
-Structures}.
-
-@item macro
-@cindex macro
-A @dfn{macro} is a construct defined in Lisp by the programmer. It
-differs from a function in that it translates a Lisp expression that you
-write into an equivalent expression to be evaluated instead of the
-original expression. Macros enable Lisp programmers to do the sorts of
-things that special forms can do. @xref{Macros}, for how to define and
-use macros.
-
-@item command
-@cindex command
-A @dfn{command} is an object that @code{command-execute} can invoke; it
-is a possible definition for a key sequence. Some functions are
-commands; a function written in Lisp is a command if it contains an
-interactive declaration (@pxref{Defining Commands}). Such a function
-can be called from Lisp expressions like other functions; in this case,
-the fact that the function is a command makes no difference.
-
-Keyboard macros (strings and vectors) are commands also, even though
-they are not functions. A symbol is a command if its function
-definition is a command; such symbols can be invoked with @kbd{M-x}.
-The symbol is a function as well if the definition is a function.
-@xref{Command Overview}.
-
-@item keystroke command
-@cindex keystroke command
-A @dfn{keystroke command} is a command that is bound to a key sequence
-(typically one to three keystrokes). The distinction is made here
-merely to avoid confusion with the meaning of ``command'' in non-Emacs
-editors; for Lisp programs, the distinction is normally unimportant.
-
-@item byte-code function
-A @dfn{byte-code function} is a function that has been compiled by the
-byte compiler. @xref{Byte-Code Type}.
-@end table
-
-@defun subrp object
-This function returns @code{t} if @var{object} is a built-in function
-(i.e., a Lisp primitive).
-
-@example
-@group
-(subrp 'message) ; @r{@code{message} is a symbol,}
- @result{} nil ; @r{not a subr object.}
-@end group
-@group
-(subrp (symbol-function 'message))
- @result{} t
-@end group
-@end example
-@end defun
-
-@defun byte-code-function-p object
-This function returns @code{t} if @var{object} is a byte-code
-function. For example:
-
-@example
-@group
-(byte-code-function-p (symbol-function 'next-line))
- @result{} t
-@end group
-@end example
-@end defun
-
-@node Lambda Expressions
-@section Lambda Expressions
-@cindex lambda expression
-
- A function written in Lisp is a list that looks like this:
-
-@example
-(lambda (@var{arg-variables}@dots{})
- @r{[}@var{documentation-string}@r{]}
- @r{[}@var{interactive-declaration}@r{]}
- @var{body-forms}@dots{})
-@end example
-
-@noindent
-Such a list is called a @dfn{lambda expression}. In Emacs Lisp, it
-actually is valid as an expression---it evaluates to itself. In some
-other Lisp dialects, a lambda expression is not a valid expression at
-all. In either case, its main use is not to be evaluated as an
-expression, but to be called as a function.
-
-@menu
-* Lambda Components:: The parts of a lambda expression.
-* Simple Lambda:: A simple example.
-* Argument List:: Details and special features of argument lists.
-* Function Documentation:: How to put documentation in a function.
-@end menu
-
-@node Lambda Components
-@subsection Components of a Lambda Expression
-
-@ifinfo
-
- A function written in Lisp (a ``lambda expression'') is a list that
-looks like this:
-
-@example
-(lambda (@var{arg-variables}@dots{})
- [@var{documentation-string}]
- [@var{interactive-declaration}]
- @var{body-forms}@dots{})
-@end example
-@end ifinfo
-
-@cindex lambda list
- The first element of a lambda expression is always the symbol
-@code{lambda}. This indicates that the list represents a function. The
-reason functions are defined to start with @code{lambda} is so that
-other lists, intended for other uses, will not accidentally be valid as
-functions.
-
- The second element is a list of symbols--the argument variable names.
-This is called the @dfn{lambda list}. When a Lisp function is called,
-the argument values are matched up against the variables in the lambda
-list, which are given local bindings with the values provided.
-@xref{Local Variables}.
-
- The documentation string is a Lisp string object placed within the
-function definition to describe the function for the Emacs help
-facilities. @xref{Function Documentation}.
-
- The interactive declaration is a list of the form @code{(interactive
-@var{code-string})}. This declares how to provide arguments if the
-function is used interactively. Functions with this declaration are called
-@dfn{commands}; they can be called using @kbd{M-x} or bound to a key.
-Functions not intended to be called in this way should not have interactive
-declarations. @xref{Defining Commands}, for how to write an interactive
-declaration.
-
-@cindex body of function
- The rest of the elements are the @dfn{body} of the function: the Lisp
-code to do the work of the function (or, as a Lisp programmer would say,
-``a list of Lisp forms to evaluate''). The value returned by the
-function is the value returned by the last element of the body.
-
-@node Simple Lambda
-@subsection A Simple Lambda-Expression Example
-
- Consider for example the following function:
-
-@example
-(lambda (a b c) (+ a b c))
-@end example
-
-@noindent
-We can call this function by writing it as the @sc{car} of an
-expression, like this:
-
-@example
-@group
-((lambda (a b c) (+ a b c))
- 1 2 3)
-@end group
-@end example
-
-@noindent
-This call evaluates the body of the lambda expression with the variable
-@code{a} bound to 1, @code{b} bound to 2, and @code{c} bound to 3.
-Evaluation of the body adds these three numbers, producing the result 6;
-therefore, this call to the function returns the value 6.
-
- Note that the arguments can be the results of other function calls, as in
-this example:
-
-@example
-@group
-((lambda (a b c) (+ a b c))
- 1 (* 2 3) (- 5 4))
-@end group
-@end example
-
-@noindent
-This evaluates the arguments @code{1}, @code{(* 2 3)}, and @code{(- 5
-4)} from left to right. Then it applies the lambda expression to the
-argument values 1, 6 and 1 to produce the value 8.
-
- It is not often useful to write a lambda expression as the @sc{car} of
-a form in this way. You can get the same result, of making local
-variables and giving them values, using the special form @code{let}
-(@pxref{Local Variables}). And @code{let} is clearer and easier to use.
-In practice, lambda expressions are either stored as the function
-definitions of symbols, to produce named functions, or passed as
-arguments to other functions (@pxref{Anonymous Functions}).
-
- However, calls to explicit lambda expressions were very useful in the
-old days of Lisp, before the special form @code{let} was invented. At
-that time, they were the only way to bind and initialize local
-variables.
-
-@node Argument List
-@subsection Advanced Features of Argument Lists
-@kindex wrong-number-of-arguments
-@cindex argument binding
-@cindex binding arguments
-
- Our simple sample function, @code{(lambda (a b c) (+ a b c))},
-specifies three argument variables, so it must be called with three
-arguments: if you try to call it with only two arguments or four
-arguments, you get a @code{wrong-number-of-arguments} error.
-
- It is often convenient to write a function that allows certain
-arguments to be omitted. For example, the function @code{substring}
-accepts three arguments---a string, the start index and the end
-index---but the third argument defaults to the @var{length} of the
-string if you omit it. It is also convenient for certain functions to
-accept an indefinite number of arguments, as the functions @code{list}
-and @code{+} do.
-
-@cindex optional arguments
-@cindex rest arguments
-@kindex &optional
-@kindex &rest
- To specify optional arguments that may be omitted when a function
-is called, simply include the keyword @code{&optional} before the optional
-arguments. To specify a list of zero or more extra arguments, include the
-keyword @code{&rest} before one final argument.
-
- Thus, the complete syntax for an argument list is as follows:
-
-@example
-@group
-(@var{required-vars}@dots{}
- @r{[}&optional @var{optional-vars}@dots{}@r{]}
- @r{[}&rest @var{rest-var}@r{]})
-@end group
-@end example
-
-@noindent
-The square brackets indicate that the @code{&optional} and @code{&rest}
-clauses, and the variables that follow them, are optional.
-
- A call to the function requires one actual argument for each of the
-@var{required-vars}. There may be actual arguments for zero or more of
-the @var{optional-vars}, and there cannot be any actual arguments beyond
-that unless the lambda list uses @code{&rest}. In that case, there may
-be any number of extra actual arguments.
-
- If actual arguments for the optional and rest variables are omitted,
-then they always default to @code{nil}. There is no way for the
-function to distinguish between an explicit argument of @code{nil} and
-an omitted argument. However, the body of the function is free to
-consider @code{nil} an abbreviation for some other meaningful value.
-This is what @code{substring} does; @code{nil} as the third argument to
-@code{substring} means to use the length of the string supplied.
-
-@cindex CL note---default optional arg
-@quotation
-@b{Common Lisp note:} Common Lisp allows the function to specify what
-default value to use when an optional argument is omitted; Emacs Lisp
-always uses @code{nil}.
-@end quotation
-
- For example, an argument list that looks like this:
-
-@example
-(a b &optional c d &rest e)
-@end example
-
-@noindent
-binds @code{a} and @code{b} to the first two actual arguments, which are
-required. If one or two more arguments are provided, @code{c} and
-@code{d} are bound to them respectively; any arguments after the first
-four are collected into a list and @code{e} is bound to that list. If
-there are only two arguments, @code{c} is @code{nil}; if two or three
-arguments, @code{d} is @code{nil}; if four arguments or fewer, @code{e}
-is @code{nil}.
-
- There is no way to have required arguments following optional
-ones---it would not make sense. To see why this must be so, suppose
-that @code{c} in the example were optional and @code{d} were required.
-Suppose three actual arguments are given; which variable would the third
-argument be for? Similarly, it makes no sense to have any more
-arguments (either required or optional) after a @code{&rest} argument.
-
- Here are some examples of argument lists and proper calls:
-
-@smallexample
-((lambda (n) (1+ n)) ; @r{One required:}
- 1) ; @r{requires exactly one argument.}
- @result{} 2
-((lambda (n &optional n1) ; @r{One required and one optional:}
- (if n1 (+ n n1) (1+ n))) ; @r{1 or 2 arguments.}
- 1 2)
- @result{} 3
-((lambda (n &rest ns) ; @r{One required and one rest:}
- (+ n (apply '+ ns))) ; @r{1 or more arguments.}
- 1 2 3 4 5)
- @result{} 15
-@end smallexample
-
-@node Function Documentation
-@subsection Documentation Strings of Functions
-@cindex documentation of function
-
- A lambda expression may optionally have a @dfn{documentation string} just
-after the lambda list. This string does not affect execution of the
-function; it is a kind of comment, but a systematized comment which
-actually appears inside the Lisp world and can be used by the Emacs help
-facilities. @xref{Documentation}, for how the @var{documentation-string} is
-accessed.
-
- It is a good idea to provide documentation strings for all the
-functions in your program, even those that are only called from within
-your program. Documentation strings are like comments, except that they
-are easier to access.
-
- The first line of the documentation string should stand on its own,
-because @code{apropos} displays just this first line. It should consist
-of one or two complete sentences that summarize the function's purpose.
-
- The start of the documentation string is usually indented in the source file,
-but since these spaces come before the starting double-quote, they are not part of
-the string. Some people make a practice of indenting any additional
-lines of the string so that the text lines up in the program source.
-@emph{This is a mistake.} The indentation of the following lines is
-inside the string; what looks nice in the source code will look ugly
-when displayed by the help commands.
-
- You may wonder how the documentation string could be optional, since
-there are required components of the function that follow it (the body).
-Since evaluation of a string returns that string, without any side effects,
-it has no effect if it is not the last form in the body. Thus, in
-practice, there is no confusion between the first form of the body and the
-documentation string; if the only body form is a string then it serves both
-as the return value and as the documentation.
-
-@node Function Names
-@section Naming a Function
-@cindex function definition
-@cindex named function
-@cindex function name
-
- In most computer languages, every function has a name; the idea of a
-function without a name is nonsensical. In Lisp, a function in the
-strictest sense has no name. It is simply a list whose first element is
-@code{lambda}, or a primitive subr-object.
-
- However, a symbol can serve as the name of a function. This happens
-when you put the function in the symbol's @dfn{function cell}
-(@pxref{Symbol Components}). Then the symbol itself becomes a valid,
-callable function, equivalent to the list or subr-object that its
-function cell refers to. The contents of the function cell are also
-called the symbol's @dfn{function definition}. The procedure of using a
-symbol's function definition in place of the symbol is called
-@dfn{symbol function indirection}; see @ref{Function Indirection}.
-
- In practice, nearly all functions are given names in this way and
-referred to through their names. For example, the symbol @code{car} works
-as a function and does what it does because the primitive subr-object
-@code{#<subr car>} is stored in its function cell.
-
- We give functions names because it is convenient to refer to them by
-their names in Lisp expressions. For primitive subr-objects such as
-@code{#<subr car>}, names are the only way you can refer to them: there
-is no read syntax for such objects. For functions written in Lisp, the
-name is more convenient to use in a call than an explicit lambda
-expression. Also, a function with a name can refer to itself---it can
-be recursive. Writing the function's name in its own definition is much
-more convenient than making the function definition point to itself
-(something that is not impossible but that has various disadvantages in
-practice).
-
- We often identify functions with the symbols used to name them. For
-example, we often speak of ``the function @code{car}'', not
-distinguishing between the symbol @code{car} and the primitive
-subr-object that is its function definition. For most purposes, there
-is no need to distinguish.
-
- Even so, keep in mind that a function need not have a unique name. While
-a given function object @emph{usually} appears in the function cell of only
-one symbol, this is just a matter of convenience. It is easy to store
-it in several symbols using @code{fset}; then each of the symbols is
-equally well a name for the same function.
-
- A symbol used as a function name may also be used as a variable;
-these two uses of a symbol are independent and do not conflict.
-
-@node Defining Functions
-@section Defining Functions
-@cindex defining a function
-
- We usually give a name to a function when it is first created. This
-is called @dfn{defining a function}, and it is done with the
-@code{defun} special form.
-
-@defspec defun name argument-list body-forms
-@code{defun} is the usual way to define new Lisp functions. It
-defines the symbol @var{name} as a function that looks like this:
-
-@example
-(lambda @var{argument-list} . @var{body-forms})
-@end example
-
-@code{defun} stores this lambda expression in the function cell of
-@var{name}. It returns the value @var{name}, but usually we ignore this
-value.
-
-As described previously (@pxref{Lambda Expressions}),
-@var{argument-list} is a list of argument names and may include the
-keywords @code{&optional} and @code{&rest}. Also, the first two forms
-in @var{body-forms} may be a documentation string and an interactive
-declaration.
-
-There is no conflict if the same symbol @var{name} is also used as a
-variable, since the symbol's value cell is independent of the function
-cell. @xref{Symbol Components}.
-
-Here are some examples:
-
-@example
-@group
-(defun foo () 5)
- @result{} foo
-@end group
-@group
-(foo)
- @result{} 5
-@end group
-
-@group
-(defun bar (a &optional b &rest c)
- (list a b c))
- @result{} bar
-@end group
-@group
-(bar 1 2 3 4 5)
- @result{} (1 2 (3 4 5))
-@end group
-@group
-(bar 1)
- @result{} (1 nil nil)
-@end group
-@group
-(bar)
-@error{} Wrong number of arguments.
-@end group
-
-@group
-(defun capitalize-backwards ()
- "Upcase the last letter of a word."
- (interactive)
- (backward-word 1)
- (forward-word 1)
- (backward-char 1)
- (capitalize-word 1))
- @result{} capitalize-backwards
-@end group
-@end example
-
-Be careful not to redefine existing functions unintentionally.
-@code{defun} redefines even primitive functions such as @code{car}
-without any hesitation or notification. Redefining a function already
-defined is often done deliberately, and there is no way to distinguish
-deliberate redefinition from unintentional redefinition.
-@end defspec
-
-@defun defalias name definition
-This special form defines the symbol @var{name} as a function, with
-definition @var{definition} (which can be any valid Lisp function).
-
-The proper place to use @code{defalias} is where a specific function
-name is being defined---especially where that name appears explicitly in
-the source file being loaded. This is because @code{defalias} records
-which file defined the function, just like @code{defun}
-(@pxref{Unloading}).
-
-By contrast, in programs that manipulate function definitions for other
-purposes, it is better to use @code{fset}, which does not keep such
-records.
-@end defun
-
- See also @code{defsubst}, which defines a function like @code{defun}
-and tells the Lisp compiler to open-code it. @xref{Inline Functions}.
-
-@node Calling Functions
-@section Calling Functions
-@cindex function invocation
-@cindex calling a function
-
- Defining functions is only half the battle. Functions don't do
-anything until you @dfn{call} them, i.e., tell them to run. Calling a
-function is also known as @dfn{invocation}.
-
- The most common way of invoking a function is by evaluating a list.
-For example, evaluating the list @code{(concat "a" "b")} calls the
-function @code{concat} with arguments @code{"a"} and @code{"b"}.
-@xref{Evaluation}, for a description of evaluation.
-
- When you write a list as an expression in your program, the function
-name is part of the program. This means that you choose which function
-to call, and how many arguments to give it, when you write the program.
-Usually that's just what you want. Occasionally you need to decide at
-run time which function to call. To do that, use the functions
-@code{funcall} and @code{apply}.
-
-@defun funcall function &rest arguments
-@code{funcall} calls @var{function} with @var{arguments}, and returns
-whatever @var{function} returns.
-
-Since @code{funcall} is a function, all of its arguments, including
-@var{function}, are evaluated before @code{funcall} is called. This
-means that you can use any expression to obtain the function to be
-called. It also means that @code{funcall} does not see the expressions
-you write for the @var{arguments}, only their values. These values are
-@emph{not} evaluated a second time in the act of calling @var{function};
-@code{funcall} enters the normal procedure for calling a function at the
-place where the arguments have already been evaluated.
-
-The argument @var{function} must be either a Lisp function or a
-primitive function. Special forms and macros are not allowed, because
-they make sense only when given the ``unevaluated'' argument
-expressions. @code{funcall} cannot provide these because, as we saw
-above, it never knows them in the first place.
-
-@example
-@group
-(setq f 'list)
- @result{} list
-@end group
-@group
-(funcall f 'x 'y 'z)
- @result{} (x y z)
-@end group
-@group
-(funcall f 'x 'y '(z))
- @result{} (x y (z))
-@end group
-@group
-(funcall 'and t nil)
-@error{} Invalid function: #<subr and>
-@end group
-@end example
-
-Compare these example with the examples of @code{apply}.
-@end defun
-
-@defun apply function &rest arguments
-@code{apply} calls @var{function} with @var{arguments}, just like
-@code{funcall} but with one difference: the last of @var{arguments} is a
-list of arguments to give to @var{function}, rather than a single
-argument. We also say that @code{apply} @dfn{spreads} this list so that
-each individual element becomes an argument.
-
-@code{apply} returns the result of calling @var{function}. As with
-@code{funcall}, @var{function} must either be a Lisp function or a
-primitive function; special forms and macros do not make sense in
-@code{apply}.
-
-@example
-@group
-(setq f 'list)
- @result{} list
-@end group
-@group
-(apply f 'x 'y 'z)
-@error{} Wrong type argument: listp, z
-@end group
-@group
-(apply '+ 1 2 '(3 4))
- @result{} 10
-@end group
-@group
-(apply '+ '(1 2 3 4))
- @result{} 10
-@end group
-
-@group
-(apply 'append '((a b c) nil (x y z) nil))
- @result{} (a b c x y z)
-@end group
-@end example
-
-For an interesting example of using @code{apply}, see the description of
-@code{mapcar}, in @ref{Mapping Functions}.
-@end defun
-
-@cindex functionals
- It is common for Lisp functions to accept functions as arguments or
-find them in data structures (especially in hook variables and property
-lists) and call them using @code{funcall} or @code{apply}. Functions
-that accept function arguments are often called @dfn{functionals}.
-
- Sometimes, when you call a functional, it is useful to supply a no-op
-function as the argument. Here are two different kinds of no-op
-function:
-
-@defun identity arg
-This function returns @var{arg} and has no side effects.
-@end defun
-
-@defun ignore &rest args
-This function ignores any arguments and returns @code{nil}.
-@end defun
-
-@node Mapping Functions
-@section Mapping Functions
-@cindex mapping functions
-
- A @dfn{mapping function} applies a given function to each element of a
-list or other collection. Emacs Lisp has three such functions;
-@code{mapcar} and @code{mapconcat}, which scan a list, are described
-here. For the third mapping function, @code{mapatoms}, see
-@ref{Creating Symbols}.
-
-@defun mapcar function sequence
-@code{mapcar} applies @var{function} to each element of @var{sequence}
-in turn, and returns a list of the results.
-
-The argument @var{sequence} may be a list, a vector, or a string. The
-result is always a list. The length of the result is the same as the
-length of @var{sequence}.
-
-@smallexample
-@group
-@exdent @r{For example:}
-
-(mapcar 'car '((a b) (c d) (e f)))
- @result{} (a c e)
-(mapcar '1+ [1 2 3])
- @result{} (2 3 4)
-(mapcar 'char-to-string "abc")
- @result{} ("a" "b" "c")
-@end group
-
-@group
-;; @r{Call each function in @code{my-hooks}.}
-(mapcar 'funcall my-hooks)
-@end group
-
-@group
-(defun mapcar* (f &rest args)
- "Apply FUNCTION to successive cars of all ARGS.
-Return the list of results."
- ;; @r{If no list is exhausted,}
- (if (not (memq 'nil args))
- ;; @r{apply function to @sc{CAR}s.}
- (cons (apply f (mapcar 'car args))
- (apply 'mapcar* f
- ;; @r{Recurse for rest of elements.}
- (mapcar 'cdr args)))))
-@end group
-
-@group
-(mapcar* 'cons '(a b c) '(1 2 3 4))
- @result{} ((a . 1) (b . 2) (c . 3))
-@end group
-@end smallexample
-@end defun
-
-@defun mapconcat function sequence separator
-@code{mapconcat} applies @var{function} to each element of
-@var{sequence}: the results, which must be strings, are concatenated.
-Between each pair of result strings, @code{mapconcat} inserts the string
-@var{separator}. Usually @var{separator} contains a space or comma or
-other suitable punctuation.
-
-The argument @var{function} must be a function that can take one
-argument and return a string.
-
-@smallexample
-@group
-(mapconcat 'symbol-name
- '(The cat in the hat)
- " ")
- @result{} "The cat in the hat"
-@end group
-
-@group
-(mapconcat (function (lambda (x) (format "%c" (1+ x))))
- "HAL-8000"
- "")
- @result{} "IBM.9111"
-@end group
-@end smallexample
-@end defun
-
-@node Anonymous Functions
-@section Anonymous Functions
-@cindex anonymous function
-
- In Lisp, a function is a list that starts with @code{lambda}, a
-byte-code function compiled from such a list, or alternatively a
-primitive subr-object; names are ``extra''. Although usually functions
-are defined with @code{defun} and given names at the same time, it is
-occasionally more concise to use an explicit lambda expression---an
-anonymous function. Such a list is valid wherever a function name is.
-
- Any method of creating such a list makes a valid function. Even this:
-
-@smallexample
-@group
-(setq silly (append '(lambda (x)) (list (list '+ (* 3 4) 'x))))
-@result{} (lambda (x) (+ 12 x))
-@end group
-@end smallexample
-
-@noindent
-This computes a list that looks like @code{(lambda (x) (+ 12 x))} and
-makes it the value (@emph{not} the function definition!) of
-@code{silly}.
-
- Here is how we might call this function:
-
-@example
-@group
-(funcall silly 1)
-@result{} 13
-@end group
-@end example
-
-@noindent
-(It does @emph{not} work to write @code{(silly 1)}, because this function
-is not the @emph{function definition} of @code{silly}. We have not given
-@code{silly} any function definition, just a value as a variable.)
-
- Most of the time, anonymous functions are constants that appear in
-your program. For example, you might want to pass one as an argument
-to the function @code{mapcar}, which applies any given function to each
-element of a list. Here we pass an anonymous function that multiplies
-a number by two:
-
-@example
-@group
-(defun double-each (list)
- (mapcar '(lambda (x) (* 2 x)) list))
-@result{} double-each
-@end group
-@group
-(double-each '(2 11))
-@result{} (4 22)
-@end group
-@end example
-
-@noindent
-In such cases, we usually use the special form @code{function} instead
-of simple quotation to quote the anonymous function.
-
-@defspec function function-object
-@cindex function quoting
-This special form returns @var{function-object} without evaluating it.
-In this, it is equivalent to @code{quote}. However, it serves as a
-note to the Emacs Lisp compiler that @var{function-object} is intended
-to be used only as a function, and therefore can safely be compiled.
-Contrast this with @code{quote}, in @ref{Quoting}.
-@end defspec
-
- Using @code{function} instead of @code{quote} makes a difference
-inside a function or macro that you are going to compile. For example:
-
-@example
-@group
-(defun double-each (list)
- (mapcar (function (lambda (x) (* 2 x))) list))
-@result{} double-each
-@end group
-@group
-(double-each '(2 11))
-@result{} (4 22)
-@end group
-@end example
-
-@noindent
-If this definition of @code{double-each} is compiled, the anonymous
-function is compiled as well. By contrast, in the previous definition
-where ordinary @code{quote} is used, the argument passed to
-@code{mapcar} is the precise list shown:
-
-@example
-(lambda (x) (* x 2))
-@end example
-
-@noindent
-The Lisp compiler cannot assume this list is a function, even though it
-looks like one, since it does not know what @code{mapcar} does with the
-list. Perhaps @code{mapcar} will check that the @sc{car} of the third
-element is the symbol @code{*}! The advantage of @code{function} is
-that it tells the compiler to go ahead and compile the constant
-function.
-
- We sometimes write @code{function} instead of @code{quote} when
-quoting the name of a function, but this usage is just a sort of
-comment.
-
-@example
-(function @var{symbol}) @equiv{} (quote @var{symbol}) @equiv{} '@var{symbol}
-@end example
-
- See @code{documentation} in @ref{Accessing Documentation}, for a
-realistic example using @code{function} and an anonymous function.
-
-@node Function Cells
-@section Accessing Function Cell Contents
-
- The @dfn{function definition} of a symbol is the object stored in the
-function cell of the symbol. The functions described here access, test,
-and set the function cell of symbols.
-
- See also the function @code{indirect-function} in @ref{Function
-Indirection}.
-
-@defun symbol-function symbol
-@kindex void-function
-This returns the object in the function cell of @var{symbol}. If the
-symbol's function cell is void, a @code{void-function} error is
-signaled.
-
-This function does not check that the returned object is a legitimate
-function.
-
-@example
-@group
-(defun bar (n) (+ n 2))
- @result{} bar
-@end group
-@group
-(symbol-function 'bar)
- @result{} (lambda (n) (+ n 2))
-@end group
-@group
-(fset 'baz 'bar)
- @result{} bar
-@end group
-@group
-(symbol-function 'baz)
- @result{} bar
-@end group
-@end example
-@end defun
-
-@cindex void function cell
- If you have never given a symbol any function definition, we say that
-that symbol's function cell is @dfn{void}. In other words, the function
-cell does not have any Lisp object in it. If you try to call such a symbol
-as a function, it signals a @code{void-function} error.
-
- Note that void is not the same as @code{nil} or the symbol
-@code{void}. The symbols @code{nil} and @code{void} are Lisp objects,
-and can be stored into a function cell just as any other object can be
-(and they can be valid functions if you define them in turn with
-@code{defun}). A void function cell contains no object whatsoever.
-
- You can test the voidness of a symbol's function definition with
-@code{fboundp}. After you have given a symbol a function definition, you
-can make it void once more using @code{fmakunbound}.
-
-@defun fboundp symbol
-This function returns @code{t} if the symbol has an object in its
-function cell, @code{nil} otherwise. It does not check that the object
-is a legitimate function.
-@end defun
-
-@defun fmakunbound symbol
-This function makes @var{symbol}'s function cell void, so that a
-subsequent attempt to access this cell will cause a @code{void-function}
-error. (See also @code{makunbound}, in @ref{Local Variables}.)
-
-@example
-@group
-(defun foo (x) x)
- @result{} x
-@end group
-@group
-(foo 1)
- @result{}1
-@end group
-@group
-(fmakunbound 'foo)
- @result{} x
-@end group
-@group
-(foo 1)
-@error{} Symbol's function definition is void: foo
-@end group
-@end example
-@end defun
-
-@defun fset symbol definition
-This function stores @var{definition} in the function cell of @var{symbol}.
-The result is @var{definition}. Normally @var{definition} should be a function
-or the name of a function, but this is not checked.
-
-There are three normal uses of this function:
-
-@itemize @bullet
-@item
-Copying one symbol's function definition to another. (In other words,
-making an alternate name for a function.)
-
-@item
-Giving a symbol a function definition that is not a list and therefore
-cannot be made with @code{defun}. For example, you can use @code{fset}
-to give a symbol @code{s1} a function definition which is another symbol
-@code{s2}; then @code{s1} serves as an alias for whatever definition
-@code{s2} presently has.
-
-@item
-In constructs for defining or altering functions. If @code{defun}
-were not a primitive, it could be written in Lisp (as a macro) using
-@code{fset}.
-@end itemize
-
-Here are examples of the first two uses:
-
-@example
-@group
-;; @r{Give @code{first} the same definition @code{car} has.}
-(fset 'first (symbol-function 'car))
- @result{} #<subr car>
-@end group
-@group
-(first '(1 2 3))
- @result{} 1
-@end group
-
-@group
-;; @r{Make the symbol @code{car} the function definition of @code{xfirst}.}
-(fset 'xfirst 'car)
- @result{} car
-@end group
-@group
-(xfirst '(1 2 3))
- @result{} 1
-@end group
-@group
-(symbol-function 'xfirst)
- @result{} car
-@end group
-@group
-(symbol-function (symbol-function 'xfirst))
- @result{} #<subr car>
-@end group
-
-@group
-;; @r{Define a named keyboard macro.}
-(fset 'kill-two-lines "\^u2\^k")
- @result{} "\^u2\^k"
-@end group
-@end example
-
-See also the related function @code{defalias}, in @ref{Defining
-Functions}.
-@end defun
-
- When writing a function that extends a previously defined function,
-the following idiom is sometimes used:
-
-@example
-(fset 'old-foo (symbol-function 'foo))
-(defun foo ()
- "Just like old-foo, except more so."
-@group
- (old-foo)
- (more-so))
-@end group
-@end example
-
-@noindent
-This does not work properly if @code{foo} has been defined to autoload.
-In such a case, when @code{foo} calls @code{old-foo}, Lisp attempts
-to define @code{old-foo} by loading a file. Since this presumably
-defines @code{foo} rather than @code{old-foo}, it does not produce the
-proper results. The only way to avoid this problem is to make sure the
-file is loaded before moving aside the old definition of @code{foo}.
-
- But it is unmodular and unclean, in any case, for a Lisp file to
-redefine a function defined elsewhere.
-
-@node Inline Functions
-@section Inline Functions
-@cindex inline functions
-
-@findex defsubst
-You can define an @dfn{inline function} by using @code{defsubst} instead
-of @code{defun}. An inline function works just like an ordinary
-function except for one thing: when you compile a call to the function,
-the function's definition is open-coded into the caller.
-
-Making a function inline makes explicit calls run faster. But it also
-has disadvantages. For one thing, it reduces flexibility; if you change
-the definition of the function, calls already inlined still use the old
-definition until you recompile them. Since the flexibility of
-redefining functions is an important feature of Emacs, you should not
-make a function inline unless its speed is really crucial.
-
-Another disadvantage is that making a large function inline can increase
-the size of compiled code both in files and in memory. Since the speed
-advantage of inline functions is greatest for small functions, you
-generally should not make large functions inline.
-
-It's possible to define a macro to expand into the same code that an
-inline function would execute. But the macro would have a limitation:
-you can use it only explicitly---a macro cannot be called with
-@code{apply}, @code{mapcar} and so on. Also, it takes some work to
-convert an ordinary function into a macro. (@xref{Macros}.) To convert
-it into an inline function is very easy; simply replace @code{defun}
-with @code{defsubst}. Since each argument of an inline function is
-evaluated exactly once, you needn't worry about how many times the
-body uses the arguments, as you do for macros. (@xref{Argument
-Evaluation}.)
-
-Inline functions can be used and open-coded later on in the same file,
-following the definition, just like macros.
-
-@c Emacs versions prior to 19 did not have inline functions.
-
-@node Related Topics
-@section Other Topics Related to Functions
-
- Here is a table of several functions that do things related to
-function calling and function definitions. They are documented
-elsewhere, but we provide cross references here.
-
-@table @code
-@item apply
-See @ref{Calling Functions}.
-
-@item autoload
-See @ref{Autoload}.
-
-@item call-interactively
-See @ref{Interactive Call}.
-
-@item commandp
-See @ref{Interactive Call}.
-
-@item documentation
-See @ref{Accessing Documentation}.
-
-@item eval
-See @ref{Eval}.
-
-@item funcall
-See @ref{Calling Functions}.
-
-@item ignore
-See @ref{Calling Functions}.
-
-@item indirect-function
-See @ref{Function Indirection}.
-
-@item interactive
-See @ref{Using Interactive}.
-
-@item interactive-p
-See @ref{Interactive Call}.
-
-@item mapatoms
-See @ref{Creating Symbols}.
-
-@item mapcar
-See @ref{Mapping Functions}.
-
-@item mapconcat
-See @ref{Mapping Functions}.
-
-@item undefined
-See @ref{Key Lookup}.
-@end table
-
diff --git a/lispref/help.texi b/lispref/help.texi
deleted file mode 100644
index 5b0b2f993ba..00000000000
--- a/lispref/help.texi
+++ /dev/null
@@ -1,627 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/help
-@node Documentation, Files, Modes, Top
-@chapter Documentation
-@cindex documentation strings
-
- GNU Emacs Lisp has convenient on-line help facilities, most of which
-derive their information from the documentation strings associated with
-functions and variables. This chapter describes how to write good
-documentation strings for your Lisp programs, as well as how to write
-programs to access documentation.
-
- Note that the documentation strings for Emacs are not the same thing
-as the Emacs manual. Manuals have their own source files, written in
-the Texinfo language; documentation strings are specified in the
-definitions of the functions and variables they apply to. A collection
-of documentation strings is not sufficient as a manual because a good
-manual is not organized in that fashion; it is organized in terms of
-topics of discussion.
-
-@menu
-* Documentation Basics:: Good style for doc strings.
- Where to put them. How Emacs stores them.
-* Accessing Documentation:: How Lisp programs can access doc strings.
-* Keys in Documentation:: Substituting current key bindings.
-* Describing Characters:: Making printable descriptions of
- non-printing characters and key sequences.
-* Help Functions:: Subroutines used by Emacs help facilities.
-@end menu
-
-@node Documentation Basics
-@comment node-name, next, previous, up
-@section Documentation Basics
-@cindex documentation conventions
-@cindex writing a documentation string
-@cindex string, writing a doc string
-
- A documentation string is written using the Lisp syntax for strings,
-with double-quote characters surrounding the text of the string. This
-is because it really is a Lisp string object. The string serves as
-documentation when it is written in the proper place in the definition
-of a function or variable. In a function definition, the documentation
-string follows the argument list. In a variable definition, the
-documentation string follows the initial value of the variable.
-
- When you write a documentation string, make the first line a complete
-sentence (or two complete sentences) since some commands, such as
-@code{apropos}, show only the first line of a multi-line documentation
-string. Also, you should not indent the second line of a documentation
-string, if you have one, because that looks odd when you use @kbd{C-h f}
-(@code{describe-function}) or @kbd{C-h v} (@code{describe-variable}).
-@xref{Documentation Tips}.
-
- Documentation strings may contain several special substrings, which
-stand for key bindings to be looked up in the current keymaps when the
-documentation is displayed. This allows documentation strings to refer
-to the keys for related commands and be accurate even when a user
-rearranges the key bindings. (@xref{Accessing Documentation}.)
-
- Within the Lisp world, a documentation string accessible through the
-function or variable that it describes:
-
-@itemize @bullet
-@item
-The documentation for a function is stored in the function definition
-itself (@pxref{Lambda Expressions}). The function
-@code{documentation} knows how to extract it.
-
-@item
-@kindex variable-documentation
-The documentation for a variable is stored in the variable's property
-list under the property name @code{variable-documentation}. The
-function @code{documentation-property} knows how to extract it.
-@end itemize
-
-@cindex @file{DOC} (documentation) file
-@cindex @file{emacs/etc/DOC-@var{version}}
-@cindex @file{etc/DOC-@var{version}}
-To save space, the documentation for preloaded functions and variables
-(including primitive functions and autoloaded functions) is stored in
-the file @file{emacs/etc/DOC-@var{version}}. The documentation for
-functions and variables loaded during the Emacs session from
-byte-compiled files is stored in those files (@pxref{Docs and
-Compilation}).
-
-The data structure inside Emacs has an integer offset into the file, or
-a list containing a string and an integer, in place of the documentation
-string. The functions @code{documentation} and
-@code{documentation-property} use that information to read the
-documentation from the appropriate file; this is transparent to the
-user.
-
- For information on the uses of documentation strings, see @ref{Help, ,
-Help, emacs, The GNU Emacs Manual}.
-
-@c Wordy to prevent overfull hbox. --rjc 15mar92
- The @file{emacs/lib-src} directory contains two utilities that you can
-use to print nice-looking hardcopy for the file
-@file{emacs/etc/DOC-@var{version}}. These are @file{sorted-doc.c} and
-@file{digest-doc.c}.
-
-@node Accessing Documentation
-@section Access to Documentation Strings
-
-@defun documentation-property symbol property &optional verbatim
-This function returns the documentation string that is recorded
-@var{symbol}'s property list under property @var{property}. It
-retrieves the text from a file if necessary, and runs
-@code{substitute-command-keys} to substitute actual key bindings. (This
-substitution is not done if @var{verbatim} is non-@code{nil}; the
-@var{verbatim} argument exists only as of Emacs 19.)
-
-@smallexample
-@group
-(documentation-property 'command-line-processed
- 'variable-documentation)
- @result{} "t once command line has been processed"
-@end group
-@group
-(symbol-plist 'command-line-processed)
- @result{} (variable-documentation 188902)
-@end group
-@end smallexample
-@end defun
-
-@defun documentation function &optional verbatim
-This function returns the documentation string of @var{function}. It
-reads the text from a file if necessary. Then (unless @var{verbatim} is
-non-@code{nil}) it calls @code{substitute-command-keys}, to return a
-value containing the actual (current) key bindings.
-
-The function @code{documentation} signals a @code{void-function} error
-if @var{function} has no function definition. However, it is ok if
-the function definition has no documentation string. In that case,
-@code{documentation} returns @code{nil}.
-@end defun
-
-@c Wordy to prevent overfull hboxes. --rjc 15mar92
-Here is an example of using the two functions, @code{documentation} and
-@code{documentation-property}, to display the documentation strings for
-several symbols in a @samp{*Help*} buffer.
-
-@smallexample
-@group
-(defun describe-symbols (pattern)
- "Describe the Emacs Lisp symbols matching PATTERN.
-All symbols that have PATTERN in their name are described
-in the `*Help*' buffer."
- (interactive "sDescribe symbols matching: ")
- (let ((describe-func
- (function
- (lambda (s)
-@end group
-@group
- ;; @r{Print description of symbol.}
- (if (fboundp s) ; @r{It is a function.}
- (princ
- (format "%s\t%s\n%s\n\n" s
- (if (commandp s)
- (let ((keys (where-is-internal s)))
- (if keys
- (concat
- "Keys: "
- (mapconcat 'key-description
- keys " "))
- "Keys: none"))
- "Function")
-@end group
-@group
- (or (documentation s)
- "not documented"))))
-
- (if (boundp s) ; @r{It is a variable.}
-@end group
-@group
- (princ
- (format "%s\t%s\n%s\n\n" s
- (if (user-variable-p s)
- "Option " "Variable")
-@end group
-@group
- (or (documentation-property
- s 'variable-documentation)
- "not documented")))))))
- sym-list)
-@end group
-
-@group
- ;; @r{Build a list of symbols that match pattern.}
- (mapatoms (function
- (lambda (sym)
- (if (string-match pattern (symbol-name sym))
- (setq sym-list (cons sym sym-list))))))
-@end group
-
-@group
- ;; @r{Display the data.}
- (with-output-to-temp-buffer "*Help*"
- (mapcar describe-func (sort sym-list 'string<))
- (print-help-return-message))))
-@end group
-@end smallexample
-
- The @code{describe-symbols} function works like @code{apropos},
-but provides more information.
-
-@smallexample
-@group
-(describe-symbols "goal")
-
----------- Buffer: *Help* ----------
-goal-column Option
-*Semipermanent goal column for vertical motion, as set by @dots{}
-@end group
-@c Do not blithely break or fill these lines.
-@c That makes them incorrect.
-
-@group
-set-goal-column Command: C-x C-n
-Set the current horizontal position as a goal for C-n and C-p.
-@end group
-@c DO NOT put a blank line here! That is factually inaccurate!
-@group
-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 C-n and C-p resume vertical motion.
-The goal column is stored in the variable `goal-column'.
-@end group
-
-@group
-temporary-goal-column Variable
-Current goal column for vertical motion.
-It is the column where point was
-at the start of current run of vertical motion commands.
-When the `track-eol' feature is doing its job, the value is 9999.
----------- Buffer: *Help* ----------
-@end group
-@end smallexample
-
-@defun Snarf-documentation filename
- This function is used only during Emacs initialization, just before
-the runnable Emacs is dumped. It finds the file offsets of the
-documentation strings stored in the file @var{filename}, and records
-them in the in-core function definitions and variable property lists in
-place of the actual strings. @xref{Building Emacs}.
-
- Emacs finds the file @var{filename} in the @file{emacs/etc} directory.
-When the dumped Emacs is later executed, the same file is found in the
-directory @code{doc-directory}. Usually @var{filename} is
-@code{"DOC-@var{version}"}.
-@end defun
-
-@c Emacs 19 feature
-@defvar doc-directory
-This variable holds the name of the directory which should contion the
-file @code{"DOC-@var{version}"} that contains documentation strings for
-built-in and preloaded functions and variables.
-
-In most cases, this is the same as @code{data-directory}. They may be
-different when you run Emacs from the directory where you built it,
-without actually installing it. See @code{data-directory} in @ref{Help
-Functions}.
-
-In older Emacs versions, @code{exec-directory} was used for this.
-@end defvar
-
-@node Keys in Documentation
-@section Substituting Key Bindings in Documentation
-@cindex documentation, keys in
-@cindex keys in documentation strings
-@cindex substituting keys in documentation
-
- When documentation strings refer to key sequences, they should use the
-current, actual key bindings. They can do so using certain special text
-sequences described below. Accessing documentation strings in the usual
-way substitutes current key binding information for these special
-sequences. This works by calling @code{substitute-command-keys}. You
-can also call that function yourself.
-
- Here is a list of the special sequences and what they mean:
-
-@table @code
-@item \[@var{command}]
-stands for a key sequence that will invoke @var{command}, or @samp{M-x
-@var{command}} if @var{command} has no key bindings.
-
-@item \@{@var{mapvar}@}
-stands for a summary of the value of @var{mapvar}, which should be a
-keymap. The summary is made by @code{describe-bindings}.
-
-@item \<@var{mapvar}>
-stands for no text itself. It is used for a side effect: it specifies
-@var{mapvar} as the keymap for any following @samp{\[@var{command}]}
-sequences in this documentation string.
-
-@item \=
-quotes the following character and is discarded; thus, @samp{\=\[} puts
-@samp{\[} into the output, and @samp{\=\=} puts @samp{\=} into the
-output.
-@end table
-
-@strong{Please note:} Each @samp{\} must be doubled when written in a
-string in Emacs Lisp.
-
-@defun substitute-command-keys string
-This function scans @var{string} for the above special sequences and
-replaces them by what they stand for, returning the result as a string.
-This permits display of documentation that refers accurately to the
-user's own customized key bindings.
-@end defun
-
- Here are examples of the special sequences:
-
-@smallexample
-@group
-(substitute-command-keys
- "To abort recursive edit, type: \\[abort-recursive-edit]")
-@result{} "To abort recursive edit, type: C-]"
-@end group
-
-@group
-(substitute-command-keys
- "The keys that are defined for the minibuffer here are:
- \\@{minibuffer-local-must-match-map@}")
-@result{} "The keys that are defined for the minibuffer here are:
-@end group
-
-? minibuffer-completion-help
-SPC minibuffer-complete-word
-TAB minibuffer-complete
-LFD minibuffer-complete-and-exit
-RET minibuffer-complete-and-exit
-C-g abort-recursive-edit
-"
-
-@group
-(substitute-command-keys
- "To abort a recursive edit from the minibuffer, type\
-\\<minibuffer-local-must-match-map>\\[abort-recursive-edit].")
-@result{} "To abort a recursive edit from the minibuffer, type C-g."
-@end group
-@end smallexample
-
-@node Describing Characters
-@section Describing Characters for Help Messages
-
- These functions convert events, key sequences or characters to textual
-descriptions. These descriptions are useful for including arbitrary
-text characters or key sequences in messages, because they convert
-non-printing and whitespace characters to sequences of printing
-characters. The description of a non-whitespace printing character is
-the character itself.
-
-@defun key-description sequence
-@cindex Emacs event standard notation
-This function returns a string containing the Emacs standard notation
-for the input events in @var{sequence}. The argument @var{sequence} may
-be a string, vector or list. @xref{Input Events}, for more information
-about valid events. See also the examples for
-@code{single-key-description}, below.
-@end defun
-
-@defun single-key-description event
-@cindex event printing
-@cindex character printing
-@cindex control character printing
-@cindex meta character printing
-This function returns a string describing @var{event} in the standard
-Emacs notation for keyboard input. A normal printing character appears
-as itself, but a control character turns into a string starting with
-@samp{C-}, a meta character turns into a string starting with @samp{M-},
-and space, linefeed, etc.@: appear as @samp{SPC}, @samp{LFD}, etc. A
-function key symbol appears as itself. An event that is a list appears
-as the name of the symbol in the @sc{car} of the list.
-
-@smallexample
-@group
-(single-key-description ?\C-x)
- @result{} "C-x"
-@end group
-@group
-(key-description "\C-x \M-y \n \t \r \f123")
- @result{} "C-x SPC M-y SPC LFD SPC TAB SPC RET SPC C-l 1 2 3"
-@end group
-@group
-(single-key-description 'C-mouse-1)
- @result{} "C-mouse-1"
-@end group
-@end smallexample
-@end defun
-
-@defun text-char-description character
-This function returns a string describing @var{character} in the
-standard Emacs notation for characters that appear in text---like
-@code{single-key-description}, except that control characters are
-represented with a leading caret (which is how control characters in
-Emacs buffers are usually displayed).
-
-@smallexample
-@group
-(text-char-description ?\C-c)
- @result{} "^C"
-@end group
-@group
-(text-char-description ?\M-m)
- @result{} "M-m"
-@end group
-@group
-(text-char-description ?\C-\M-m)
- @result{} "M-^M"
-@end group
-@end smallexample
-@end defun
-
-@node Help Functions
-@section Help Functions
-
- Emacs provides a variety of on-line help functions, all accessible to
-the user as subcommands of the prefix @kbd{C-h}. For more information
-about them, see @ref{Help, , Help, emacs, The GNU Emacs Manual}. Here
-we describe some program-level interfaces to the same information.
-
-@deffn Command apropos regexp &optional do-all predicate
-This function finds all symbols whose names contain a match for the
-regular expression @var{regexp}, and returns a list of them
-(@pxref{Regular Expressions}). It also displays the symbols in a buffer
-named @samp{*Help*}, each with a one-line description.
-
-@c Emacs 19 feature
-If @var{do-all} is non-@code{nil}, then @code{apropos} also shows
-key bindings for the functions that are found.
-
-If @var{predicate} is non-@code{nil}, it should be a function to be
-called on each symbol that has matched @var{regexp}. Only symbols for
-which @var{predicate} returns a non-@code{nil} value are listed or
-displayed.
-
-In the first of the following examples, @code{apropos} finds all the
-symbols with names containing @samp{exec}. In the second example, it
-finds and returns only those symbols that are also commands.
-(We don't show the output that results in the @samp{*Help*} buffer.)
-
-@smallexample
-@group
-(apropos "exec")
- @result{} (Buffer-menu-execute command-execute exec-directory
- exec-path execute-extended-command execute-kbd-macro
- executing-kbd-macro executing-macro)
-@end group
-
-@group
-(apropos "exec" nil 'commandp)
- @result{} (Buffer-menu-execute execute-extended-command)
-@end group
-@ignore
-@group
----------- Buffer: *Help* ----------
-Buffer-menu-execute
- Function: Save and/or delete buffers marked with
- M-x Buffer-menu-save or M-x Buffer-menu-delete commands.
-execute-extended-command ESC x
- Function: Read function name, then read its
- arguments and call it.
----------- Buffer: *Help* ----------
-@end group
-@end ignore
-@end smallexample
-
-The command @kbd{C-h a} (@code{command-apropos}) calls @code{apropos},
-but specifies a @var{predicate} to restrict the output to symbols that
-are commands. The call to @code{apropos} looks like this:
-
-@smallexample
-(apropos string t 'commandp)
-@end smallexample
-@end deffn
-
-@c Emacs 19 feature
-@deffn Command super-apropos regexp &optional do-all
-This function differs from @code{apropos} in that it searches
-documentation strings as well as symbol names for matches for
-@var{regexp}. By default, it searches the documentation strings only
-for preloaded functions and variables. If @var{do-all} is
-non-@code{nil}, it scans the names and documentation strings of all
-functions and variables.
-@end deffn
-
-@defvar help-map
-The value of this variable is a local keymap for characters following the
-Help key, @kbd{C-h}.
-@end defvar
-
-@deffn {Prefix Command} help-command
-This symbol is not a function; its function definition is actually the
-keymap known as @code{help-map}. It is defined in @file{help.el} as
-follows:
-
-@smallexample
-@group
-(define-key global-map "\C-h" 'help-command)
-(fset 'help-command help-map)
-@end group
-@end smallexample
-@end deffn
-
-@defun print-help-return-message &optional function
-This function builds a string that explains how to restore the previous
-state of the windows after a help command. After building the message,
-it applies @var{function} to it if @var{function} is non-@code{nil}.
-Otherwise it calls @code{message} to display it in the echo area.
-
-This function expects to be called inside a
-@code{with-output-to-temp-buffer} special form, and expects
-@code{standard-output} to have the value bound by that special form.
-For an example of its use, see the long example in @ref{Accessing
-Documentation}.
-@end defun
-
-@defvar help-char
-The value of this variable is the help character---the character that
-Emacs recognizes as meaning Help. By default, it is 8, which is
-@kbd{C-h}. When Emacs reads this character, if @code{help-form} is
-non-@code{nil} Lisp expression, it evaluates that expression, and
-displays the result in a window if it is a string.
-
-Usually the value of @code{help-form}'s value is @code{nil}. Then the
-help character has no special meaning at the level of command input, and
-it becomes part of a key sequence in the normal way. The standard key
-binding of @kbd{C-h} is a prefix key for several general-purpose help
-features.
-
-The help character is special after prefix keys, too. If it has no
-binding as a subcommand of the prefix key, it runs
-@code{describe-prefix-bindings}, which displays a list of all the
-subcommands of the prefix key.
-@end defvar
-
-@defvar help-form
-If this variable is non-@code{nil}, its value is a form to evaluate
-whenever the character @code{help-char} is read. If evaluating the form
-produces a string, that string is displayed.
-
-A command that calls @code{read-event} or @code{read-char} probably
-should bind @code{help-form} to a non-@code{nil} expression while it
-does input. (The exception is when @kbd{C-h} is meaningful input.)
-Evaluating this expression should result in a string that explains what
-the input is for and how to enter it properly.
-
-Entry to the minibuffer binds this variable to the value of
-@code{minibuffer-help-form} (@pxref{Minibuffer Misc}).
-@end defvar
-
-@defvar prefix-help-command
-This variable holds a function to print help for a prefix character.
-The function is called when the user types a prefix key followed by the
-help character, and the help character has no binding after that prefix.
-The variable's default value is @code{describe-prefix-bindings}.
-@end defvar
-
-@defun describe-prefix-bindings
-This function calls @code{describe-bindings} to display a list of all
-the subcommands of the prefix key of the most recent key sequence. The
-prefix described consists of all but the last event of that key
-sequence. (The last event is, presumably, the help character.)
-@end defun
-
- The following two functions are found in the library @file{helper}.
-They are for modes that want to provide help without relinquishing
-control, such as the ``electric'' modes. You must load that library
-with @code{(require 'helper)} in order to use them. Their names begin
-with @samp{Helper} to distinguish them from the ordinary help functions.
-
-@deffn Command Helper-describe-bindings
-This command pops up a window displaying a help buffer containing a
-listing of all of the key bindings from both the local and global keymaps.
-It works by calling @code{describe-bindings}.
-@end deffn
-
-@deffn Command Helper-help
-This command provides help for the current mode. It prompts the user
-in the minibuffer with the message @samp{Help (Type ? for further
-options)}, and then provides assistance in finding out what the key
-bindings are, and what the mode is intended for. It returns @code{nil}.
-
-This can be customized by changing the map @code{Helper-help-map}.
-@end deffn
-
-@c Emacs 19 feature
-@defvar data-directory
-This variable holds the name of the directory in which Emacs finds
-certain documentation and text files that come with Emacs. In older
-Emacs versions, @code{exec-directory} was used for this.
-@end defvar
-
-@c Emacs 19 feature
-@defmac make-help-screen fname help-line help-text help-map
-This macro defines a help command named @var{fname} that acts like a
-prefix key that shows a list of the subcommands it offers.
-
-When invoked, @var{fname} displays @var{help-text} in a window, then
-reads and executes a key sequence according to @var{help-map}. The
-string @var{help-text} should describe the bindings available in
-@var{help-map}.
-
-The command @var{fname} is defined to handle a few events itself, by
-scrolling the display of @var{help-text}. When @var{fname} reads one of
-those special events, it does the scrolling and then reads another
-event. When it reads an event that is not one of those few, and which
-has a binding in @var{help-map}, it executes that key's binding and
-then returns.
-
-The argument @var{help-line} should be a single-line summary of the
-alternatives in @var{help-map}. In the current version of Emacs, this
-argument is used only if you set the option @code{three-step-help} to
-@code{t}.
-@end defmac
-
-@defopt three-step-help
-If this variable is non-@code{nil}, commands defined with
-@code{make-help-screen} display their @var{help-line} strings in the
-echo area at first, and display the longer @var{help-text} strings only
-if the user types the help character again.
-@end defopt
diff --git a/lispref/hooks.texi b/lispref/hooks.texi
deleted file mode 100644
index 046ac7cc5d5..00000000000
--- a/lispref/hooks.texi
+++ /dev/null
@@ -1,129 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/hooks
-@node Standard Hooks, Index, Standard Keymaps, Top
-@appendix Standard Hooks
-
-The following is a list of hook variables that let you provide
-functions to be called from within Emacs on suitable occasions.
-
-Most of these variables have names ending with @samp{-hook}. They are
-@dfn{normal hooks}, run by means of @code{run-hooks}. The value of such
-a hook is a list of functions; the functions are called with no
-arguments and their values are completely ignored. The recommended way
-to put a new function on such a hook is to call @code{add-hook}.
-@xref{Hooks}, for more information about using hooks.
-
-The variables whose names end in @samp{-hooks} or @samp{-functions} are
-usually @dfn{abnormal hooks}; their values are lists of functions, but
-these functions are called in a special way (they are passed arguments,
-or their values are used). A few of these variables are actually normal
-hooks which were named before we established the convention that normal
-hooks' names should end in @samp{-hook}.
-
-The variables whose names end in @samp{-function} have single functions
-as their values. (In older Emacs versions, some of these variables had
-names ending in @samp{-hook} even though they were not normal hooks;
-however, we have renamed all of those.)
-
-@c !!! need xref to where each hook is documented or else document it
-@c by specifying what is expected, and when it is called relative to
-@c mode initialization.)
-
-@table @code
-@item activate-mark-hook
-@item after-change-function
-@item after-change-functions
-@item after-init-hook
-@item after-insert-file-functions
-@item after-make-frame-hook
-@item auto-fill-function
-@item auto-save-hook
-@item before-change-function
-@item before-change-functions
-@item before-init-hook
-@item before-make-frame-hook
-@item blink-paren-function
-@item c-mode-hook
-@item calendar-load-hook
-@item command-history-hook
-@item comment-indent-function
-@item deactivate-mark-hook
-@item diary-display-hook
-@item diary-hook
-@item dired-mode-hook
-@item disabled-command-hook
-@item edit-picture-hook
-@item electric-buffer-menu-mode-hook
-@item electric-command-history-hook
-@item electric-help-mode-hook
-@item emacs-lisp-mode-hook
-@item find-file-hooks
-@item find-file-not-found-hooks
-@item first-change-hook
-@item fortran-comment-hook
-@item fortran-mode-hook
-@item ftp-setup-write-file-hooks
-@item ftp-write-file-hook
-@item indent-mim-hook
-@item initial-calendar-window-hook
-@item kill-buffer-query-functions
-@item kill-emacs-query-functions
-@item LaTeX-mode-hook
-@item ledit-mode-hook
-@item lisp-indent-function
-@item lisp-interaction-mode-hook
-@item lisp-mode-hook
-@item list-diary-entries-hook
-@item m2-mode-hook
-@item mail-mode-hook
-@item mail-setup-hook
-@item mark-diary-entries-hook
-@item medit-mode-hook
-@item mh-compose-letter-hook
-@item mh-folder-mode-hook
-@item mh-letter-mode-hook
-@item mim-mode-hook
-@item minibuffer-setup-hook
-@item minibuffer-exit-hook
-@item news-mode-hook
-@item news-reply-mode-hook
-@item news-setup-hook
-@item nongregorian-diary-listing-hook
-@item nongregorian-diary-marking-hook
-@item nroff-mode-hook
-@item outline-mode-hook
-@item plain-TeX-mode-hook
-@item post-command-hook
-@item pre-abbrev-expand-hook
-@item pre-command-hook
-@item print-diary-entries-hook
-@item prolog-mode-hook
-@item protect-innocence-hook
-@item rmail-edit-mode-hook
-@item rmail-mode-hook
-@item rmail-summary-mode-hook
-@item scheme-indent-hook
-@item scheme-mode-hook
-@item scribe-mode-hook
-@item shell-mode-hook
-@item shell-set-directory-error-hook
-@item suspend-hook
-@item suspend-resume-hook
-@item temp-buffer-show-function
-@item term-setup-hook
-@item terminal-mode-hook
-@item terminal-mode-break-hook
-@item TeX-mode-hook
-@item text-mode-hook
-@item today-visible-calendar-hook
-@item today-invisible-calendar-hook
-@item vi-mode-hook
-@item view-hook
-@item window-setup-hook
-@item write-contents-hooks
-@item write-file-hooks
-@item write-region-annotate-functions
-@end table
diff --git a/lispref/internals.texi b/lispref/internals.texi
deleted file mode 100644
index 48323f79d33..00000000000
--- a/lispref/internals.texi
+++ /dev/null
@@ -1,960 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/internals
-@node GNU Emacs Internals, Standard Errors, Tips, Top
-@comment node-name, next, previous, up
-@appendix GNU Emacs Internals
-
-This chapter describes how the runnable Emacs executable is dumped with
-the preloaded Lisp libraries in it, how storage is allocated, and some
-internal aspects of GNU Emacs that may be of interest to C programmers.
-
-@menu
-* Building Emacs:: How to preload Lisp libraries into Emacs.
-* Pure Storage:: A kludge to make preloaded Lisp functions sharable.
-* Garbage Collection:: Reclaiming space for Lisp objects no longer used.
-* Writing Emacs Primitives:: Writing C code for Emacs.
-* Object Internals:: Data formats of buffers, windows, processes.
-@end menu
-
-@node Building Emacs, Pure Storage, GNU Emacs Internals, GNU Emacs Internals
-@appendixsec Building Emacs
-@cindex building Emacs
-@pindex temacs
-
- This section explains the steps involved in building the Emacs
-executable. You don't have to know this material to build and install
-Emacs, since the makefiles do all these things automatically. This
-information is pertinent to Emacs maintenance.
-
- Compilation of the C source files in the @file{src} directory
-produces an executable file called @file{temacs}, also called a
-@dfn{bare impure Emacs}. It contains the Emacs Lisp interpreter and I/O
-routines, but not the editing commands.
-
-@cindex @file{loadup.el}
- The command @w{@samp{temacs -l loadup}} uses @file{temacs} to create
-the real runnable Emacs executable. These arguments direct
-@file{temacs} to evaluate the Lisp files specified in the file
-@file{loadup.el}. These files set up the normal Emacs editing
-environment, resulting in an Emacs that is still impure but no longer
-bare.
-
- It takes a substantial time to load the standard Lisp files. Luckily,
-you don't have to do this each time you run Emacs; @file{temacs} can
-dump out an executable program called @file{emacs} that has these files
-preloaded. @file{emacs} starts more quickly because it does not need to
-load the files. This is the Emacs executable that is normally
-installed.
-
- To create @file{emacs}, use the command @samp{temacs -batch -l loadup
-dump}. The purpose of @samp{-batch} here is to prevent @file{temacs}
-from trying to initialize any of its data on the terminal; this ensures
-that the tables of terminal information are empty in the dumped Emacs.
-The argument @samp{dump} tells @file{loadup.el} to dump a new executable
-named @file{emacs}.
-
- Some operating systems don't support dumping. On those systems, you
-must start Emacs with the @samp{temacs -l loadup} command each time you
-use it. This takes a substantial time, but since you need to start
-Emacs once a day at most---or once a week if you never log out---the
-extra time is not too severe a problem.
-
-@cindex @file{site-load.el}
- You can specify additional files to preload by writing a library named
-@file{site-load.el} that loads them. You may need to increase the value
-of @code{PURESIZE}, in @file{src/puresize.h}, to make room for the
-additional data. (Try adding increments of 20000 until it is big
-enough.) However, the advantage of preloading additional files
-decreases as machines get faster. On modern machines, it is usually not
-advisable.
-
- After @file{loadup.el} reads @file{site-load.el}, it finds the
-documentation strings for primitive and preloaded functions (and
-variables) in the file @file{etc/DOC} where they are stored, by calling
-@code{Snarf-documentation} (@pxref{Accessing Documentation}).
-
-@cindex @file{site-init.el}
- You can specify other Lisp expressions to execute just before dumping
-by putting them in a library named @file{site-init.el}. This file is
-executed after the documentation strings are found.
-
- If you want to preload function or variable definitions, there are
-three ways you can do this and make their documentation strings
-accessible when you subsequently run Emacs:
-
-@itemize @bullet
-@item
-Arrange to scan these files when producing the @file{etc/DOC} file,
-and load them with @file{site-load.el}.
-
-@item
-Load the files with @file{site-init.el}, then copy the files into the
-installation directory for Lisp files when you install Emacs.
-
-@item
-Specify a non-@code{nil} value for
-@code{byte-compile-dynamic-docstrings} as a local variable in each these
-files, and load them with either @file{site-load.el} or
-@file{site-init.el}. (This method has the drawback that the
-documentation strings take up space in Emacs all the time.)
-@end itemize
-
- It is not advisable to put anything in @file{site-load.el} or
-@file{site-init.el} that would alter any of the features that users
-expect in an ordinary unmodified Emacs. If you feel you must override
-normal features for your site, do it with @file{default.el}, so that
-users can override your changes if they wish. @xref{Start-up Summary}.
-
-@defun dump-emacs to-file from-file
-@cindex unexec
- This function dumps the current state of Emacs into an executable file
-@var{to-file}. It takes symbols from @var{from-file} (this is normally
-the executable file @file{temacs}).
-
-If you use this function in an Emacs that was already dumped, you must
-set @code{command-line-processed} to @code{nil} first for good results.
-@xref{Command Line Arguments}.
-@end defun
-
-@deffn Command emacs-version
- This function returns a string describing the version of Emacs that is
-running. It is useful to include this string in bug reports.
-
-@example
-@group
-(emacs-version)
- @result{} "GNU Emacs 19.29.1 (i386-debian-linux) \
- of Tue Jun 6 1995 on balloon"
-@end group
-@end example
-
-Called interactively, the function prints the same information in the
-echo area.
-@end deffn
-
-@defvar emacs-build-time
-The value of this variable is the time at which Emacs was built at the
-local site.
-
-@example
-@group
-emacs-build-time
- @result{} "Tue Jun 6 14:55:57 1995"
-@end group
-@end example
-@end defvar
-
-@defvar emacs-version
-The value of this variable is the version of Emacs being run. It is a
-string such as @code{"19.29.1"}.
-@end defvar
-
- The following two variables did not exist before Emacs version 19.23,
-which reduces their usefulness at present, but we hope they will be
-convenient in the future.
-
-@defvar emacs-major-version
-The major version number of Emacs, as an integer. For Emacs version
-19.29, the value is 19.
-@end defvar
-
-@defvar emacs-minor-version
-The minor version number of Emacs, as an integer. For Emacs version
-19.29, the value is 29.
-@end defvar
-
-@node Pure Storage, Garbage Collection, Building Emacs, GNU Emacs Internals
-@appendixsec Pure Storage
-@cindex pure storage
-
- Emacs Lisp uses two kinds of storage for user-created Lisp objects:
-@dfn{normal storage} and @dfn{pure storage}. Normal storage is where
-all the new data created during an Emacs session is kept; see the
-following section for information on normal storage. Pure storage is
-used for certain data in the preloaded standard Lisp files---data that
-should never change during actual use of Emacs.
-
- Pure storage is allocated only while @file{temacs} is loading the
-standard preloaded Lisp libraries. In the file @file{emacs}, it is
-marked as read-only (on operating systems that permit this), so that
-the memory space can be shared by all the Emacs jobs running on the
-machine at once. Pure storage is not expandable; a fixed amount is
-allocated when Emacs is compiled, and if that is not sufficient for the
-preloaded libraries, @file{temacs} crashes. If that happens, you must
-increase the compilation parameter @code{PURESIZE} in the file
-@file{src/puresize.h}. This normally won't happen unless you try to
-preload additional libraries or add features to the standard ones.
-
-@defun purecopy object
-This function makes a copy of @var{object} in pure storage and returns
-it. It copies strings by simply making a new string with the same
-characters in pure storage. It recursively copies the contents of
-vectors and cons cells. It does not make copies of other objects such
-as symbols, but just returns them unchanged. It signals an error if
-asked to copy markers.
-
-This function is a no-op except while Emacs is being built and dumped;
-it is usually called only in the file @file{emacs/lisp/loaddefs.el}, but
-a few packages call it just in case you decide to preload them.
-@end defun
-
-@defvar pure-bytes-used
-The value of this variable is the number of bytes of pure storage
-allocated so far. Typically, in a dumped Emacs, this number is very
-close to the total amount of pure storage available---if it were not,
-we would preallocate less.
-@end defvar
-
-@defvar purify-flag
-This variable determines whether @code{defun} should make a copy of the
-function definition in pure storage. If it is non-@code{nil}, then the
-function definition is copied into pure storage.
-
-This flag is @code{t} while loading all of the basic functions for
-building Emacs initially (allowing those functions to be sharable and
-non-collectible). Dumping Emacs as an executable always writes
-@code{nil} in this variable, regardless of the value it actually has
-before and after dumping.
-
-You should not change this flag in a running Emacs.
-@end defvar
-
-@node Garbage Collection, Writing Emacs Primitives, Pure Storage, GNU Emacs Internals
-@appendixsec Garbage Collection
-@cindex garbage collector
-
-@cindex memory allocation
- When a program creates a list or the user defines a new function (such
-as by loading a library), that data is placed in normal storage. If
-normal storage runs low, then Emacs asks the operating system to
-allocate more memory in blocks of 1k bytes. Each block is used for one
-type of Lisp object, so symbols, cons cells, markers, etc., are
-segregated in distinct blocks in memory. (Vectors, long strings,
-buffers and certain other editing types, which are fairly large, are
-allocated in individual blocks, one per object, while small strings are
-packed into blocks of 8k bytes.)
-
- It is quite common to use some storage for a while, then release it by
-(for example) killing a buffer or deleting the last pointer to an
-object. Emacs provides a @dfn{garbage collector} to reclaim this
-abandoned storage. (This name is traditional, but ``garbage recycler''
-might be a more intuitive metaphor for this facility.)
-
- The garbage collector operates by finding and marking all Lisp objects
-that are still accessible to Lisp programs. To begin with, it assumes
-all the symbols, their values and associated function definitions, and
-any data presently on the stack, are accessible. Any objects that can
-be reached indirectly through other accessible objects are also
-accessible.
-
- When marking is finished, all objects still unmarked are garbage. No
-matter what the Lisp program or the user does, it is impossible to refer
-to them, since there is no longer a way to reach them. Their space
-might as well be reused, since no one will miss them. The second
-(``sweep'') phase of the garbage collector arranges to reuse them.
-
-@cindex free list
- The sweep phase puts unused cons cells onto a @dfn{free list}
-for future allocation; likewise for symbols and markers. It compacts
-the accessible strings so they occupy fewer 8k blocks; then it frees the
-other 8k blocks. Vectors, buffers, windows, and other large objects are
-individually allocated and freed using @code{malloc} and @code{free}.
-
-@cindex CL note---allocate more storage
-@quotation
-@b{Common Lisp note:} Unlike other Lisps, GNU Emacs Lisp does not
-call the garbage collector when the free list is empty. Instead, it
-simply requests the operating system to allocate more storage, and
-processing continues until @code{gc-cons-threshold} bytes have been
-used.
-
-This means that you can make sure that the garbage collector will not
-run during a certain portion of a Lisp program by calling the garbage
-collector explicitly just before it (provided that portion of the
-program does not use so much space as to force a second garbage
-collection).
-@end quotation
-
-@deffn Command garbage-collect
-This command runs a garbage collection, and returns information on
-the amount of space in use. (Garbage collection can also occur
-spontaneously if you use more than @code{gc-cons-threshold} bytes of
-Lisp data since the previous garbage collection.)
-
-@code{garbage-collect} returns a list containing the following
-information:
-
-@example
-@group
-((@var{used-conses} . @var{free-conses})
- (@var{used-syms} . @var{free-syms})
-@end group
- (@var{used-markers} . @var{free-markers})
- @var{used-string-chars}
- @var{used-vector-slots}
- (@var{used-floats} . @var{free-floats}))
-
-@group
-(garbage-collect)
- @result{} ((3435 . 2332) (1688 . 0)
- (57 . 417) 24510 3839 (4 . 1))
-@end group
-@end example
-
-Here is a table explaining each element:
-
-@table @var
-@item used-conses
-The number of cons cells in use.
-
-@item free-conses
-The number of cons cells for which space has been obtained from the
-operating system, but that are not currently being used.
-
-@item used-syms
-The number of symbols in use.
-
-@item free-syms
-The number of symbols for which space has been obtained from the
-operating system, but that are not currently being used.
-
-@item used-markers
-The number of markers in use.
-
-@item free-markers
-The number of markers for which space has been obtained from the
-operating system, but that are not currently being used.
-
-@item used-string-chars
-The total size of all strings, in characters.
-
-@item used-vector-slots
-The total number of elements of existing vectors.
-
-@item used-floats
-@c Emacs 19 feature
-The number of floats in use.
-
-@item free-floats
-@c Emacs 19 feature
-The number of floats for which space has been obtained from the
-operating system, but that are not currently being used.
-@end table
-@end deffn
-
-@defopt garbage-collection-messages
-If this variable is non-@code{nil}, Emacs displays a message at the
-beginning and end of garbage collection. The default value is
-@code{nil}, meaning there are no such messages.
-@end defopt
-
-@defopt gc-cons-threshold
-The value of this variable is the number of bytes of storage that must
-be allocated for Lisp objects after one garbage collection in order to
-trigger another garbage collection. A cons cell counts as eight bytes,
-a string as one byte per character plus a few bytes of overhead, and so
-on; space allocated to the contents of buffers does not count. Note
-that the subsequent garbage collection does not happen immediately when
-the threshold is exhausted, but only the next time the Lisp evaluator is
-called.
-
-The initial threshold value is 300,000. If you specify a larger
-value, garbage collection will happen less often. This reduces the
-amount of time spent garbage collecting, but increases total memory use.
-You may want to do this when running a program that creates lots of
-Lisp data.
-
-You can make collections more frequent by specifying a smaller value,
-down to 10,000. A value less than 10,000 will remain in effect only
-until the subsequent garbage collection, at which time
-@code{garbage-collect} will set the threshold back to 10,000.
-@end defopt
-
-@c Emacs 19 feature
-@defun memory-limit
-This function returns the address of the last byte Emacs has allocated,
-divided by 1024. We divide the value by 1024 to make sure it fits in a
-Lisp integer.
-
-You can use this to get a general idea of how your actions affect the
-memory usage.
-@end defun
-
-@node Writing Emacs Primitives, Object Internals, Garbage Collection, GNU Emacs Internals
-@appendixsec Writing Emacs Primitives
-@cindex primitive function internals
-
- Lisp primitives are Lisp functions implemented in C. The details of
-interfacing the C function so that Lisp can call it are handled by a few
-C macros. The only way to really understand how to write new C code is
-to read the source, but we can explain some things here.
-
- An example of a special form is the definition of @code{or}, from
-@file{eval.c}. (An ordinary function would have the same general
-appearance.)
-
-@cindex garbage collection protection
-@smallexample
-@group
-DEFUN ("or", For, Sor, 0, UNEVALLED, 0,
- "Eval args until one of them yields non-nil; return that value.\n\
-The remaining args are not evalled at all.\n\
-@end group
-@group
-If all args return nil, return nil.")
- (args)
- Lisp_Object args;
-@{
- register Lisp_Object val;
- Lisp_Object args_left;
- struct gcpro gcpro1;
-@end group
-
-@group
- if (NULL (args))
- return Qnil;
-
- args_left = args;
- GCPRO1 (args_left);
-@end group
-
-@group
- do
- @{
- val = Feval (Fcar (args_left));
- if (!NULL (val))
- break;
- args_left = Fcdr (args_left);
- @}
- while (!NULL (args_left));
-@end group
-
-@group
- UNGCPRO;
- return val;
-@}
-@end group
-@end smallexample
-
- Let's start with a precise explanation of the arguments to the
-@code{DEFUN} macro. Here is a template for them:
-
-@example
-DEFUN (@var{lname}, @var{fname}, @var{sname}, @var{min}, @var{max}, @var{interactive}, @var{doc})
-@end example
-
-@table @var
-@item lname
-This is the name of the Lisp symbol to define as the function name; in
-the example above, it is @code{or}.
-
-@item fname
-This is the C function name for this function. This is
-the name that is used in C code for calling the function. The name is,
-by convention, @samp{F} prepended to the Lisp name, with all dashes
-(@samp{-}) in the Lisp name changed to underscores. Thus, to call this
-function from C code, call @code{For}. Remember that the arguments must
-be of type @code{Lisp_Object}; various macros and functions for creating
-values of type @code{Lisp_Object} are declared in the file
-@file{lisp.h}.
-
-@item sname
-This is a C variable name to use for a structure that holds the data for
-the subr object that represents the function in Lisp. This structure
-conveys the Lisp symbol name to the initialization routine that will
-create the symbol and store the subr object as its definition. By
-convention, this name is always @var{fname} with @samp{F} replaced with
-@samp{S}.
-
-@item min
-This is the minimum number of arguments that the function requires. The
-function @code{or} allows a minimum of zero arguments.
-
-@item max
-This is the maximum number of arguments that the function accepts, if
-there is a fixed maximum. Alternatively, it can be @code{UNEVALLED},
-indicating a special form that receives unevaluated arguments, or
-@code{MANY}, indicating an unlimited number of evaluated arguments (the
-equivalent of @code{&rest}). Both @code{UNEVALLED} and @code{MANY} are
-macros. If @var{max} is a number, it may not be less than @var{min} and
-it may not be greater than seven.
-
-@item interactive
-This is an interactive specification, a string such as might be used as
-the argument of @code{interactive} in a Lisp function. In the case of
-@code{or}, it is 0 (a null pointer), indicating that @code{or} cannot be
-called interactively. A value of @code{""} indicates a function that
-should receive no arguments when called interactively.
-
-@item doc
-This is the documentation string. It is written just like a
-documentation string for a function defined in Lisp, except you must
-write @samp{\n\} at the end of each line. In particular, the first line
-should be a single sentence.
-@end table
-
- After the call to the @code{DEFUN} macro, you must write the argument
-name list that every C function must have, followed by ordinary C
-declarations for the arguments. For a function with a fixed maximum
-number of arguments, declare a C argument for each Lisp argument, and
-give them all type @code{Lisp_Object}. When a Lisp function has no
-upper limit on the number of arguments, its implementation in C actually
-receives exactly two arguments: the first is the number of Lisp
-arguments, and the second is the address of a block containing their
-values. They have types @code{int} and @w{@code{Lisp_Object *}}.
-
- Within the function @code{For} itself, note the use of the macros
-@code{GCPRO1} and @code{UNGCPRO}. @code{GCPRO1} is used to ``protect''
-a variable from garbage collection---to inform the garbage collector that
-it must look in that variable and regard its contents as an accessible
-object. This is necessary whenever you call @code{Feval} or anything
-that can directly or indirectly call @code{Feval}. At such a time, any
-Lisp object that you intend to refer to again must be protected somehow.
-@code{UNGCPRO} cancels the protection of the variables that are
-protected in the current function. It is necessary to do this explicitly.
-
- For most data types, it suffices to protect at least one pointer to
-the object; as long as the object is not recycled, all pointers to it
-remain valid. This is not so for strings, because the garbage collector
-can move them. When the garbage collector moves a string, it relocates
-all the pointers it knows about; any other pointers become invalid.
-Therefore, you must protect all pointers to strings across any point
-where garbage collection may be possible.
-
- The macro @code{GCPRO1} protects just one local variable. If you want
-to protect two, use @code{GCPRO2} instead; repeating @code{GCPRO1} will
-not work. Macros @code{GCPRO3} and @code{GCPRO4} also exist.
-
- These macros implicitly use local variables such as @code{gcpro1}; you
-must declare these explicitly, with type @code{struct gcpro}. Thus, if
-you use @code{GCPRO2}, you must declare @code{gcpro1} and @code{gcpro2}.
-Alas, we can't explain all the tricky details here.
-
- You must not use C initializers for static or global variables unless
-they are never written once Emacs is dumped. These variables with
-initializers are allocated in an area of memory that becomes read-only
-(on certain operating systems) as a result of dumping Emacs. @xref{Pure
-Storage}.
-
- Do not use static variables within functions---place all static
-variables at top level in the file. This is necessary because Emacs on
-some operating systems defines the keyword @code{static} as a null
-macro. (This definition is used because those systems put all variables
-declared static in a place that becomes read-only after dumping, whether
-they have initializers or not.)
-
- Defining the C function is not enough to make a Lisp primitive
-available; you must also create the Lisp symbol for the primitive and
-store a suitable subr object in its function cell. The code looks like
-this:
-
-@example
-defsubr (&@var{subr-structure-name});
-@end example
-
-@noindent
-Here @var{subr-structure-name} is the name you used as the third
-argument to @code{DEFUN}.
-
- If you add a new primitive to a file that already has Lisp primitives
-defined in it, find the function (near the end of the file) named
-@code{syms_of_@var{something}}, and add the call to @code{defsubr}
-there. If the file doesn't have this function, or if you create a new
-file, add to it a @code{syms_of_@var{filename}} (e.g.,
-@code{syms_of_myfile}). Then find the spot in @file{emacs.c} where all
-of these functions are called, and add a call to
-@code{syms_of_@var{filename}} there.
-
- The function @code{syms_of_@var{filename}} is also the place to define
-any C variables that are to be visible as Lisp variables.
-@code{DEFVAR_LISP} makes a C variable of type @code{Lisp_Object} visible
-in Lisp. @code{DEFVAR_INT} makes a C variable of type @code{int}
-visible in Lisp with a value that is always an integer.
-@code{DEFVAR_BOOL} makes a C variable of type @code{int} visible in Lisp
-with a value that is either @code{t} or @code{nil}.
-
- Here is another example function, with more complicated arguments.
-This comes from the code for the X Window System, and it demonstrates
-the use of macros and functions to manipulate Lisp objects.
-
-@smallexample
-@group
-DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
- Scoordinates_in_window_p, 2, 2,
- "xSpecify coordinate pair: \nXExpression which evals to window: ",
- "Return non-nil if POSITIONS is in WINDOW.\n\
- \(POSITIONS is a list, (SCREEN-X SCREEN-Y)\)\n\
-@end group
-@group
- 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;
-@end group
-
-@group
- 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);
-@end group
-@group
- 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);
-@end group
-@group
- if (XINT (ycoord) == (screen_height - 1))
- return Qnil;
-@end group
-@group
- if ((XINT (ycoord) < XINT (XWINDOW (window)->top))
- || (XINT (ycoord) >= (XINT (XWINDOW (window)->top)
- + XINT (XWINDOW (window)->height)) - 1))
- return Qnil;
-@end group
-@group
- XFASTINT (ycoord) -= XFASTINT (XWINDOW (window)->top);
- return (Fcons (xcoord, Fcons (ycoord, Qnil)));
-@}
-@end group
-@end smallexample
-
- Note that C code cannot call functions by name unless they are defined
-in C. The way to call a function written in Lisp is to use
-@code{Ffuncall}, which embodies the Lisp function @code{funcall}. Since
-the Lisp function @code{funcall} accepts an unlimited number of
-arguments, in C it takes two: the number of Lisp-level arguments, and a
-one-dimensional array containing their values. The first Lisp-level
-argument is the Lisp function to call, and the rest are the arguments to
-pass to it. Since @code{Ffuncall} can call the evaluator, you must
-protect pointers from garbage collection around the call to
-@code{Ffuncall}.
-
- The C functions @code{call0}, @code{call1}, @code{call2}, and so on,
-provide handy ways to call a Lisp function conveniently with a fixed
-number of arguments. They work by calling @code{Ffuncall}.
-
- @file{eval.c} is a very good file to look through for examples;
-@file{lisp.h} contains the definitions for some important macros and
-functions.
-
-@node Object Internals, , Writing Emacs Primitives, GNU Emacs Internals
-@appendixsec Object Internals
-@cindex object internals
-
- GNU Emacs Lisp manipulates many different types of data. The actual
-data are stored in a heap and the only access that programs have to it is
-through pointers. Pointers are thirty-two bits wide in most
-implementations. Depending on the operating system and type of machine
-for which you compile Emacs, twenty-four to twenty-six bits are used to
-address the object, and the remaining six to eight bits are used for a
-tag that identifies the object's type.
-
- Because Lisp objects are represented as tagged pointers, it is always
-possible to determine the Lisp data type of any object. The C data type
-@code{Lisp_Object} can hold any Lisp object of any data type. Ordinary
-variables have type @code{Lisp_Object}, which means they can hold any
-type of Lisp value; you can determine the actual data type only at run
-time. The same is true for function arguments; if you want a function
-to accept only a certain type of argument, you must check the type
-explicitly using a suitable predicate (@pxref{Type Predicates}).
-@cindex type checking internals
-
-@menu
-* Buffer Internals:: Components of a buffer structure.
-* Window Internals:: Components of a window structure.
-* Process Internals:: Components of a process structure.
-@end menu
-
-@node Buffer Internals, Window Internals, Object Internals, Object Internals
-@appendixsubsec Buffer Internals
-@cindex internals, of buffer
-@cindex buffer internals
-
- Buffers contain fields not directly accessible by the Lisp programmer.
-We describe them here, naming them by the names used in the C code.
-Many are accessible indirectly in Lisp programs via Lisp primitives.
-
-@table @code
-@item name
-The buffer name is a string that names the buffer. It is guaranteed to
-be unique. @xref{Buffer Names}.
-
-@item save_modified
-This field contains the time when the buffer was last saved, as an integer.
-@xref{Buffer Modification}.
-
-@item modtime
-This field contains the modification time of the visited file. It is
-set when the file is written or read. Every time the buffer is written
-to the file, this field is compared to the modification time of the
-file. @xref{Buffer Modification}.
-
-@item auto_save_modified
-This field contains the time when the buffer was last auto-saved.
-
-@item last_window_start
-This field contains the @code{window-start} position in the buffer as of
-the last time the buffer was displayed in a window.
-
-@item undo_list
-This field points to the buffer's undo list. @xref{Undo}.
-
-@item syntax_table_v
-This field contains the syntax table for the buffer. @xref{Syntax Tables}.
-
-@item downcase_table
-This field contains the conversion table for converting text to lower case.
-@xref{Case Table}.
-
-@item upcase_table
-This field contains the conversion table for converting text to upper case.
-@xref{Case Table}.
-
-@item case_canon_table
-This field contains the conversion table for canonicalizing text for
-case-folding search. @xref{Case Table}.
-
-@item case_eqv_table
-This field contains the equivalence table for case-folding search.
-@xref{Case Table}.
-
-@item display_table
-This field contains the buffer's display table, or @code{nil} if it doesn't
-have one. @xref{Display Tables}.
-
-@item markers
-This field contains the chain of all markers that currently point into
-the buffer. Deletion of text in the buffer, and motion of the buffer's
-gap, must check each of these markers and perhaps update it.
-@xref{Markers}.
-
-@item backed_up
-This field is a flag that tells whether a backup file has been made
-for the visited file of this buffer.
-
-@item mark
-This field contains the mark for the buffer. The mark is a marker,
-hence it is also included on the list @code{markers}. @xref{The Mark}.
-
-@item mark_active
-This field is non-@code{nil} if the buffer's mark is active.
-
-@item local_var_alist
-This field contains the association list describing the variables local
-in this buffer, and their values, with the exception of local variables
-that have special slots in the buffer object. (Those slots are omitted
-from this table.) @xref{Buffer-Local Variables}.
-
-@item base_buffer
-This field holds the buffer's base buffer (if it is an indirect buffer),
-or @code{nil}.
-
-@item keymap
-This field holds the buffer's local keymap. @xref{Keymaps}.
-
-@item overlay_center
-This field holds the current overlay center position. @xref{Overlays}.
-
-@item overlays_before
-This field holds a list of the overlays in this buffer that end at or
-before the current overlay center position. They are sorted in order of
-decreasing end position.
-
-@item overlays_after
-This field holds a list of the overlays in this buffer that end after
-the current overlay center position. They are sorted in order of
-increasing beginning position.
-@end table
-
-@node Window Internals, Process Internals, Buffer Internals, Object Internals
-@appendixsubsec Window Internals
-@cindex internals, of window
-@cindex window internals
-
- Windows have the following accessible fields:
-
-@table @code
-@item frame
-The frame that this window is on.
-
-@item mini_p
-Non-@code{nil} if this window is a minibuffer window.
-
-@item buffer
-The buffer that the window is displaying. This may change often during
-the life of the window.
-
-@item dedicated
-Non-@code{nil} if this window is dedicated to its buffer.
-
-@item pointm
-@cindex window point internals
-This is the value of point in the current buffer when this window is
-selected; when it is not selected, it retains its previous value.
-
-@item start
-The position in the buffer that is the first character to be displayed
-in the window.
-
-@item force_start
-If this flag is non-@code{nil}, it says that the window has been
-scrolled explicitly by the Lisp program. This affects what the next
-redisplay does if point is off the screen: instead of scrolling the
-window to show the text around point, it moves point to a location that
-is on the screen.
-
-@item last_modified
-The @code{modified} field of the window's buffer, as of the last time
-a redisplay completed in this window.
-
-@item last_point
-The buffer's value of point, as of the last time
-a redisplay completed in this window.
-
-@item left
-This is the left-hand edge of the window, measured in columns. (The
-leftmost column on the screen is @w{column 0}.)
-
-@item top
-This is the top edge of the window, measured in lines. (The top line on
-the screen is @w{line 0}.)
-
-@item height
-The height of the window, measured in lines.
-
-@item width
-The width of the window, measured in columns.
-
-@item next
-This is the window that is the next in the chain of siblings. It is
-@code{nil} in a window that is the rightmost or bottommost of a group of
-siblings.
-
-@item prev
-This is the window that is the previous in the chain of siblings. It is
-@code{nil} in a window that is the leftmost or topmost of a group of
-siblings.
-
-@item parent
-Internally, Emacs arranges windows in a tree; each group of siblings has
-a parent window whose area includes all the siblings. This field points
-to a window's parent.
-
-Parent windows do not display buffers, and play little role in display
-except to shape their child windows. Emacs Lisp programs usually have
-no access to the parent windows; they operate on the windows at the
-leaves of the tree, which actually display buffers.
-
-@item hscroll
-This is the number of columns that the display in the window is scrolled
-horizontally to the left. Normally, this is 0.
-
-@item use_time
-This is the last time that the window was selected. The function
-@code{get-lru-window} uses this field.
-
-@item display_table
-The window's display table, or @code{nil} if none is specified for it.
-
-@item update_mode_line
-Non-@code{nil} means this window's mode line needs to be updated.
-
-@item base_line_number
-The line number of a certain position in the buffer, or @code{nil}.
-This is used for displaying the line number of point in the mode line.
-
-@item base_line_pos
-The position in the buffer for which the line number is known, or
-@code{nil} meaning none is known.
-
-@item region_showing
-If the region (or part of it) is highlighted in this window, this field
-holds the mark position that made one end of that region. Otherwise,
-this field is @code{nil}.
-@end table
-
-@node Process Internals, , Window Internals, Object Internals
-@appendixsubsec Process Internals
-@cindex internals, of process
-@cindex process internals
-
- The fields of a process are:
-
-@table @code
-@item name
-A string, the name of the process.
-
-@item command
-A list containing the command arguments that were used to start this
-process.
-
-@item filter
-A function used to accept output from the process instead of a buffer,
-or @code{nil}.
-
-@item sentinel
-A function called whenever the process receives a signal, or @code{nil}.
-
-@item buffer
-The associated buffer of the process.
-
-@item pid
-An integer, the Unix process @sc{id}.
-
-@item childp
-A flag, non-@code{nil} if this is really a child process.
-It is @code{nil} for a network connection.
-
-@item mark
-A marker indicating the position of the end of the last output from this
-process inserted into the buffer. This is often but not always the end
-of the buffer.
-
-@item kill_without_query
-If this is non-@code{nil}, killing Emacs while this process is still
-running does not ask for confirmation about killing the process.
-
-@item raw_status_low
-@itemx raw_status_high
-These two fields record 16 bits each of the process status returned by
-the @code{wait} system call.
-
-@item status
-The process status, as @code{process-status} should return it.
-
-@item tick
-@itemx update_tick
-If these two fields are not equal, a change in the status of the process
-needs to be reported, either by running the sentinel or by inserting a
-message in the process buffer.
-
-@item pty_flag
-Non-@code{nil} if communication with the subprocess uses a @sc{pty};
-@code{nil} if it uses a pipe.
-
-@item infd
-The file descriptor for input from the process.
-
-@item outfd
-The file descriptor for output to the process.
-
-@item subtty
-The file descriptor for the terminal that the subprocess is using. (On
-some systems, there is no need to record this, so the value is
-@code{nil}.)
-
-@item tty_name
-The name of the terminal that the subprocess is using,
-or @code{nil} if it is using pipes.
-@end table
diff --git a/lispref/intro.texi b/lispref/intro.texi
deleted file mode 100644
index def0d1c84bc..00000000000
--- a/lispref/intro.texi
+++ /dev/null
@@ -1,866 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/intro
-
-@node Copying, Introduction, Top, Top
-@comment node-name, next, previous, up
-@unnumbered GNU GENERAL PUBLIC LICENSE
-@center Version 2, June 1991
-
-@display
-Copyright @copyright{} 1989, 1991 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 licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU 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. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), 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 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 show them these terms so they know 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.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
-@iftex
-@unnumberedsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-@end iftex
-@ifinfo
-@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-@end ifinfo
-
-@enumerate 0
-@item
-This License 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 derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term ``modification''.) Each licensee is addressed as ``you''.
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-@item
-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 License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-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.
-
-@item
-You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-@enumerate a
-@item
-You must cause the modified files to carry prominent notices
-stating that you changed the files and the date of any change.
-
-@item
-You must cause any work that you distribute or publish, that in
-whole or in part contains or is derived from the Program or any
-part thereof, to be licensed as a whole at no charge to all third
-parties under the terms of this License.
-
-@item
-If the modified program normally reads commands interactively
-when run, you must cause it, when started running for such
-interactive use in the most ordinary 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
-License. (Exception: if the Program itself is interactive but
-does not normally print such an announcement, your work based on
-the Program is not required to print an announcement.)
-@end enumerate
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-@item
-You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-@enumerate a
-@item
-Accompany it with the complete corresponding machine-readable
-source code, which must be distributed under the terms of Sections
-1 and 2 above on a medium customarily used for software interchange; or,
-
-@item
-Accompany it with a written offer, valid for at least three
-years, to give any third party, for a charge no more than your
-cost of physically performing source distribution, a complete
-machine-readable copy of the corresponding source code, to be
-distributed under the terms of Sections 1 and 2 above on a medium
-customarily used for software interchange; or,
-
-@item
-Accompany it with the information you received as to the offer
-to distribute corresponding source code. (This alternative is
-allowed only for noncommercial distribution and only if you
-received the program in object code or executable form with such
-an offer, in accord with Subsection b above.)
-@end enumerate
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-@item
-You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-@item
-You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing 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 for copying, distributing or modifying
-the Program or works based on it.
-
-@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.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-@item
-If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-@item
-If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-@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 this 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
-this 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
-
-@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 the public, 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 an 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 2
-of the License, 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 @samp{show w} and @samp{show c} should show
-the appropriate parts of the General Public License. Of course, the
-commands you use may be called something other than @samp{show w} and
-@samp{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:
-
-@smallexample
-@group
-Yoyodyne, Inc., hereby disclaims all copyright
-interest in the program `Gnomovision'
-(which makes passes at compilers) written
-by James Hacker.
-
-@var{signature of Ty Coon}, 1 April 1989
-Ty Coon, President of Vice
-@end group
-@end smallexample
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
-
-@node Introduction, Lisp Data Types, Copying, Top
-@chapter Introduction
-
- Most of the GNU Emacs text editor is written in the programming
-language called Emacs Lisp. You can write new code in Emacs Lisp and
-install it as an extension to the editor. However, Emacs Lisp is more
-than a mere ``extension language''; it is a full computer programming
-language in its own right. You can use it as you would any other
-programming language.
-
- Because Emacs Lisp is designed for use in an editor, it has special
-features for scanning and parsing text as well as features for handling
-files, buffers, displays, subprocesses, and so on. Emacs Lisp is
-closely integrated with the editing facilities; thus, editing commands
-are functions that can also conveniently be called from Lisp programs,
-and parameters for customization are ordinary Lisp variables.
-
- This manual describes Emacs Lisp, presuming considerable familiarity
-with the use of Emacs for editing. (See @cite{The GNU Emacs Manual}
-for this basic information.) Generally speaking, the earlier chapters
-describe features of Emacs Lisp that have counterparts in many
-programming languages, and later chapters describe features that are
-peculiar to Emacs Lisp or relate specifically to editing.
-
- This is edition 2.4.
-
-@menu
-* Caveats:: Flaws and a request for help.
-* Lisp History:: Emacs Lisp is descended from Maclisp.
-* Conventions:: How the manual is formatted.
-* Acknowledgements:: The authors, editors, and sponsors of this manual.
-@end menu
-
-@node Caveats
-@section Caveats
-
- This manual has gone through numerous drafts. It is nearly complete
-but not flawless. There are a few topics that are not covered, either
-because we consider them secondary (such as most of the individual
-modes) or because they are yet to be written. Because we are not able
-to deal with them completely, we have left out several parts
-intentionally. This includes most information about usage on VMS.
-
- The manual should be fully correct in what it does cover, and it is
-therefore open to criticism on anything it says---from specific examples
-and descriptive text, to the ordering of chapters and sections. If
-something is confusing, or you find that you have to look at the sources
-or experiment to learn something not covered in the manual, then perhaps
-the manual should be fixed. Please let us know.
-
-@iftex
- As you use the manual, we ask that you mark pages with corrections so
-you can later look them up and send them in. If you think of a simple,
-real-life example for a function or group of functions, please make an
-effort to write it up and send it in. Please reference any comments to
-the chapter name, section name, and function name, as appropriate, since
-page numbers and chapter and section numbers will change and we may have
-trouble finding the text you are talking about. Also state the number
-of the edition you are criticizing.
-@end iftex
-@ifinfo
-
-As you use this manual, we ask that you send corrections as soon as you
-find them. If you think of a simple, real life example for a function
-or group of functions, please make an effort to write it up and send it
-in. Please reference any comments to the node name and function or
-variable name, as appropriate. Also state the number of the edition
-which you are criticizing.
-@end ifinfo
-
-Please mail comments and corrections to
-
-@example
-bug-lisp-manual@@prep.ai.mit.edu
-@end example
-
-@noindent
-We let mail to this list accumulate unread until someone decides to
-apply the corrections. Months, and sometimes years, go by between
-updates. So please attach no significance to the lack of a reply---your
-mail @emph{will} be acted on in due time. If you want to contact the
-Emacs maintainers more quickly, send mail to
-@code{bug-gnu-emacs@@prep.ai.mit.edu}.
-
-@display
- --Bil Lewis, Dan LaLiberte, Richard Stallman
-@end display
-
-@node Lisp History
-@section Lisp History
-@cindex Lisp history
-
- Lisp (LISt Processing language) was first developed in the late 1950's
-at the Massachusetts Institute of Technology for research in artificial
-intelligence. The great power of the Lisp language makes it superior
-for other purposes as well, such as writing editing commands.
-
-@cindex Maclisp
-@cindex Common Lisp
- Dozens of Lisp implementations have been built over the years, each
-with its own idiosyncrasies. Many of them were inspired by Maclisp,
-which was written in the 1960's at MIT's Project MAC. Eventually the
-implementors of the descendants of Maclisp came together and developed a
-standard for Lisp systems, called Common Lisp.
-
- GNU Emacs Lisp is largely inspired by Maclisp, and a little by Common
-Lisp. If you know Common Lisp, you will notice many similarities.
-However, many of the features of Common Lisp have been omitted or
-simplified in order to reduce the memory requirements of GNU Emacs.
-Sometimes the simplifications are so drastic that a Common Lisp user
-might be very confused. We will occasionally point out how GNU Emacs
-Lisp differs from Common Lisp. If you don't know Common Lisp, don't
-worry about it; this manual is self-contained.
-
-@node Conventions
-@section Conventions
-
-This section explains the notational conventions that are used in this
-manual. You may want to skip this section and refer back to it later.
-
-@menu
-* Some Terms:: Explanation of terms we use in this manual.
-* nil and t:: How the symbols @code{nil} and @code{t} are used.
-* Evaluation Notation:: The format we use for examples of evaluation.
-* Printing Notation:: The format we use for examples that print output.
-* Error Messages:: The format we use for examples of errors.
-* Buffer Text Notation:: The format we use for buffer contents in examples.
-* Format of Descriptions:: Notation for describing functions, variables, etc.
-@end menu
-
-@node Some Terms
-@subsection Some Terms
-
- Throughout this manual, the phrases ``the Lisp reader'' and ``the Lisp
-printer'' are used to refer to those routines in Lisp that convert
-textual representations of Lisp objects into actual Lisp objects, and vice
-versa. @xref{Printed Representation}, for more details. You, the
-person reading this manual, are thought of as ``the programmer'' and are
-addressed as ``you''. ``The user'' is the person who uses Lisp programs,
-including those you write.
-
-@cindex fonts
- Examples of Lisp code appear in this font or form: @code{(list 1 2
-3)}. Names that represent arguments or metasyntactic variables appear
-in this font or form: @var{first-number}.
-
-@node nil and t
-@subsection @code{nil} and @code{t}
-@cindex @code{nil}, uses of
-@cindex truth value
-@cindex boolean
-@cindex false
-
- In Lisp, the symbol @code{nil} has three separate meanings: it
-is a symbol with the name @samp{nil}; it is the logical truth value
-@var{false}; and it is the empty list---the list of zero elements.
-When used as a variable, @code{nil} always has the value @code{nil}.
-
- As far as the Lisp reader is concerned, @samp{()} and @samp{nil} are
-identical: they stand for the same object, the symbol @code{nil}. The
-different ways of writing the symbol are intended entirely for human
-readers. After the Lisp reader has read either @samp{()} or @samp{nil},
-there is no way to determine which representation was actually written
-by the programmer.
-
- In this manual, we use @code{()} when we wish to emphasize that it
-means the empty list, and we use @code{nil} when we wish to emphasize
-that it means the truth value @var{false}. That is a good convention to use
-in Lisp programs also.
-
-@example
-(cons 'foo ()) ; @r{Emphasize the empty list}
-(not nil) ; @r{Emphasize the truth value @var{false}}
-@end example
-
-@cindex @code{t} and truth
-@cindex true
- In contexts where a truth value is expected, any non-@code{nil} value
-is considered to be @var{true}. However, @code{t} is the preferred way
-to represent the truth value @var{true}. When you need to choose a
-value which represents @var{true}, and there is no other basis for
-choosing, use @code{t}. The symbol @code{t} always has value @code{t}.
-
- In Emacs Lisp, @code{nil} and @code{t} are special symbols that always
-evaluate to themselves. This is so that you do not need to quote them
-to use them as constants in a program. An attempt to change their
-values results in a @code{setting-constant} error. @xref{Accessing
-Variables}.
-
-@node Evaluation Notation
-@subsection Evaluation Notation
-@cindex evaluation notation
-@cindex documentation notation
-
- A Lisp expression that you can evaluate is called a @dfn{form}.
-Evaluating a form always produces a result, which is a Lisp object. In
-the examples in this manual, this is indicated with @samp{@result{}}:
-
-@example
-(car '(1 2))
- @result{} 1
-@end example
-
-@noindent
-You can read this as ``@code{(car '(1 2))} evaluates to 1''.
-
- When a form is a macro call, it expands into a new form for Lisp to
-evaluate. We show the result of the expansion with
-@samp{@expansion{}}. We may or may not show the actual result of the
-evaluation of the expanded form.
-
-@example
-(third '(a b c))
- @expansion{} (car (cdr (cdr '(a b c))))
- @result{} c
-@end example
-
- Sometimes to help describe one form we show another form that
-produces identical results. The exact equivalence of two forms is
-indicated with @samp{@equiv{}}.
-
-@example
-(make-sparse-keymap) @equiv{} (list 'keymap)
-@end example
-
-@node Printing Notation
-@subsection Printing Notation
-@cindex printing notation
-
- Many of the examples in this manual print text when they are
-evaluated. If you execute example code in a Lisp Interaction buffer
-(such as the buffer @samp{*scratch*}), the printed text is inserted into
-the buffer. If you execute the example by other means (such as by
-evaluating the function @code{eval-region}), the printed text is
-displayed in the echo area. You should be aware that text displayed in
-the echo area is truncated to a single line.
-
- Examples in this manual indicate printed text with @samp{@print{}},
-irrespective of where that text goes. The value returned by evaluating
-the form (here @code{bar}) follows on a separate line.
-
-@example
-@group
-(progn (print 'foo) (print 'bar))
- @print{} foo
- @print{} bar
- @result{} bar
-@end group
-@end example
-
-@node Error Messages
-@subsection Error Messages
-@cindex error message notation
-
- Some examples signal errors. This normally displays an error message
-in the echo area. We show the error message on a line starting with
-@samp{@error{}}. Note that @samp{@error{}} itself does not appear in
-the echo area.
-
-@example
-(+ 23 'x)
-@error{} Wrong type argument: integer-or-marker-p, x
-@end example
-
-@node Buffer Text Notation
-@subsection Buffer Text Notation
-@cindex buffer text notation
-
- Some examples show modifications to text in a buffer, with ``before''
-and ``after'' versions of the text. These examples show the contents of
-the buffer in question between two lines of dashes containing the buffer
-name. In addition, @samp{@point{}} indicates the location of point.
-(The symbol for point, of course, is not part of the text in the buffer;
-it indicates the place @emph{between} two characters where point is
-located.)
-
-@example
----------- Buffer: foo ----------
-This is the @point{}contents of foo.
----------- Buffer: foo ----------
-
-(insert "changed ")
- @result{} nil
----------- Buffer: foo ----------
-This is the changed @point{}contents of foo.
----------- Buffer: foo ----------
-@end example
-
-@node Format of Descriptions
-@subsection Format of Descriptions
-@cindex description format
-
- Functions, variables, macros, commands, user options, and special
-forms are described in this manual in a uniform format. The first
-line of a description contains the name of the item followed by its
-arguments, if any.
-@ifinfo
-The category---function, variable, or whatever---appears at the
-beginning of the line.
-@end ifinfo
-@iftex
-The category---function, variable, or whatever---is printed next to the
-right margin.
-@end iftex
-The description follows on succeeding lines, sometimes with examples.
-
-@menu
-* A Sample Function Description:: A description of an imaginary
- function, @code{foo}.
-* A Sample Variable Description:: A description of an imaginary
- variable,
- @code{electric-future-map}.
-@end menu
-
-@node A Sample Function Description
-@subsubsection A Sample Function Description
-@cindex function descriptions
-@cindex command descriptions
-@cindex macro descriptions
-@cindex special form descriptions
-
- In a function description, the name of the function being described
-appears first. It is followed on the same line by a list of parameters.
-The names used for the parameters are also used in the body of the
-description.
-
- The appearance of the keyword @code{&optional} in the parameter list
-indicates that the arguments for subsequent parameters may be omitted
-(omitted parameters default to @code{nil}). Do not write
-@code{&optional} when you call the function.
-
- The keyword @code{&rest} (which will always be followed by a single
-parameter) indicates that any number of arguments can follow. The value
-of the single following parameter will be a list of all these arguments.
-Do not write @code{&rest} when you call the function.
-
- Here is a description of an imaginary function @code{foo}:
-
-@defun foo integer1 &optional integer2 &rest integers
-The function @code{foo} subtracts @var{integer1} from @var{integer2},
-then adds all the rest of the arguments to the result. If @var{integer2}
-is not supplied, then the number 19 is used by default.
-
-@example
-(foo 1 5 3 9)
- @result{} 16
-(foo 5)
- @result{} 14
-@end example
-
-More generally,
-
-@example
-(foo @var{w} @var{x} @var{y}@dots{})
-@equiv{}
-(+ (- @var{x} @var{w}) @var{y}@dots{})
-@end example
-@end defun
-
- Any parameter whose name contains the name of a type (e.g.,
-@var{integer}, @var{integer1} or @var{buffer}) is expected to be of that
-type. A plural of a type (such as @var{buffers}) often means a list of
-objects of that type. Parameters named @var{object} may be of any type.
-(@xref{Lisp Data Types}, for a list of Emacs object types.)
-Parameters with other sorts of names (e.g., @var{new-file}) are
-discussed specifically in the description of the function. In some
-sections, features common to parameters of several functions are
-described at the beginning.
-
- @xref{Lambda Expressions}, for a more complete description of optional
-and rest arguments.
-
- Command, macro, and special form descriptions have the same format,
-but the word `Function' is replaced by `Command', `Macro', or `Special
-Form', respectively. Commands are simply functions that may be called
-interactively; macros process their arguments differently from functions
-(the arguments are not evaluated), but are presented the same way.
-
- Special form descriptions use a more complex notation to specify
-optional and repeated parameters because they can break the argument
-list down into separate arguments in more complicated ways.
-@samp{@code{@r{[}@var{optional-arg}@r{]}}} means that @var{optional-arg} is
-optional and @samp{@var{repeated-args}@dots{}} stands for zero or more
-arguments. Parentheses are used when several arguments are grouped into
-additional levels of list structure. Here is an example:
-
-@defspec count-loop (@var{var} [@var{from} @var{to} [@var{inc}]]) @var{body}@dots{}
-This imaginary special form implements a loop that executes the
-@var{body} forms and then increments the variable @var{var} on each
-iteration. On the first iteration, the variable has the value
-@var{from}; on subsequent iterations, it is incremented by 1 (or by
-@var{inc} if that is given). The loop exits before executing @var{body}
-if @var{var} equals @var{to}. Here is an example:
-
-@example
-(count-loop (i 0 10)
- (prin1 i) (princ " ")
- (prin1 (aref vector i)) (terpri))
-@end example
-
-If @var{from} and @var{to} are omitted, then @var{var} is bound to
-@code{nil} before the loop begins, and the loop exits if @var{var} is
-non-@code{nil} at the beginning of an iteration. Here is an example:
-
-@example
-(count-loop (done)
- (if (pending)
- (fixit)
- (setq done t)))
-@end example
-
-In this special form, the arguments @var{from} and @var{to} are
-optional, but must both be present or both absent. If they are present,
-@var{inc} may optionally be specified as well. These arguments are
-grouped with the argument @var{var} into a list, to distinguish them
-from @var{body}, which includes all remaining elements of the form.
-@end defspec
-
-@node A Sample Variable Description
-@subsubsection A Sample Variable Description
-@cindex variable descriptions
-@cindex option descriptions
-
- A @dfn{variable} is a name that can hold a value. Although any
-variable can be set by the user, certain variables that exist
-specifically so that users can change them are called @dfn{user
-options}. Ordinary variables and user options are described using a
-format like that for functions except that there are no arguments.
-
- Here is a description of the imaginary @code{electric-future-map}
-variable.@refill
-
-@defvar electric-future-map
-The value of this variable is a full keymap used by Electric Command
-Future mode. The functions in this map allow you to edit commands you
-have not yet thought about executing.
-@end defvar
-
- User option descriptions have the same format, but `Variable' is
-replaced by `User Option'.
-
-@node Acknowledgements
-@section Acknowledgements
-
- This manual was written by Robert Krawitz, Bil Lewis, Dan LaLiberte,
-Richard M. Stallman and Chris Welty, the volunteers of the GNU manual
-group, in an effort extending over several years. Robert J. Chassell
-helped to review and edit the manual, with the support of the Defense
-Advanced Research Projects Agency, ARPA Order 6082, arranged by Warren
-A. Hunt, Jr. of Computational Logic, Inc.
-
- Corrections were supplied by Karl Berry, Jim Blandy, Bard Bloom,
-Stephane Boucher, David Boyes, Alan Carroll, Richard Davis, Lawrence
-R. Dodd, Peter Doornbosch, David A. Duff, Chris Eich, Beverly
-Erlebacher, David Eckelkamp, Ralf Fassel, Eirik Fuller, Stephen Gildea,
-Bob Glickstein, Eric Hanchrow, George Hartzell, Nathan Hess, Masayuki
-Ida, Dan Jacobson, Jak Kirman, Bob Knighten, Frederick M. Korz, Joe
-Lammens, Glenn M. Lewis, K. Richard Magill, Brian Marick, Roland
-McGrath, Skip Montanaro, John Gardiner Myers, Thomas A. Peterson,
-Francesco Potorti, Friedrich Pukelsheim, Arnold D. Robbins, Raul
-Rockwell, Per Starback, Shinichirou Sugou, Kimmo Suominen, Edward Tharp,
-Bill Trost, Rickard Westman, Jean White, Matthew Wilding, Carl Witty,
-Dale Worley, Rusty Wright, and David D. Zuhn.
diff --git a/lispref/keymaps.texi b/lispref/keymaps.texi
deleted file mode 100644
index 77ac4ecce75..00000000000
--- a/lispref/keymaps.texi
+++ /dev/null
@@ -1,1776 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/keymaps
-@node Keymaps, Modes, Command Loop, Top
-@chapter Keymaps
-@cindex keymap
-
- The bindings between input events and commands are recorded in data
-structures called @dfn{keymaps}. Each binding in a keymap associates
-(or @dfn{binds}) an individual event type either with another keymap or
-with a command. When an event is bound to a keymap, that keymap is
-used to look up the next input event; this continues until a command
-is found. The whole process is called @dfn{key lookup}.
-
-@menu
-* Keymap Terminology:: Definitions of terms pertaining to keymaps.
-* Format of Keymaps:: What a keymap looks like as a Lisp object.
-* Creating Keymaps:: Functions to create and copy keymaps.
-* Inheritance and Keymaps:: How one keymap can inherit the bindings
- of another keymap.
-* Prefix Keys:: Defining a key with a keymap as its definition.
-* Active Keymaps:: Each buffer has a local keymap
- to override the standard (global) bindings.
- A minor mode can also override them.
-* Key Lookup:: How extracting elements from keymaps works.
-* Functions for Key Lookup:: How to request key lookup.
-* Changing Key Bindings:: Redefining a key in a keymap.
-* Key Binding Commands:: Interactive interfaces for redefining keys.
-* Scanning Keymaps:: Looking through all keymaps, for printing help.
-* Menu Keymaps:: A keymap can define a menu.
-@end menu
-
-@node Keymap Terminology
-@section Keymap Terminology
-@cindex key
-@cindex keystroke
-@cindex key binding
-@cindex binding of a key
-@cindex complete key
-@cindex undefined key
-
- A @dfn{keymap} is a table mapping event types to definitions (which
-can be any Lisp objects, though only certain types are meaningful for
-execution by the command loop). Given an event (or an event type) and a
-keymap, Emacs can get the event's definition. Events include ordinary
-@sc{ASCII} characters, function keys, and mouse actions (@pxref{Input
-Events}).
-
- A sequence of input events that form a unit is called a
-@dfn{key sequence}, or @dfn{key} for short. A sequence of one event
-is always a key sequence, and so are some multi-event sequences.
-
- A keymap determines a binding or definition for any key sequence. If
-the key sequence is a single event, its binding is the definition of the
-event in the keymap. The binding of a key sequence of more than one
-event is found by an iterative process: the binding of the first event
-is found, and must be a keymap; then the second event's binding is found
-in that keymap, and so on until all the events in the key sequence are
-used up.
-
- If the binding of a key sequence is a keymap, we call the key sequence
-a @dfn{prefix key}. Otherwise, we call it a @dfn{complete key} (because
-no more events can be added to it). If the binding is @code{nil},
-we call the key @dfn{undefined}. Examples of prefix keys are @kbd{C-c},
-@kbd{C-x}, and @kbd{C-x 4}. Examples of defined complete keys are
-@kbd{X}, @key{RET}, and @kbd{C-x 4 C-f}. Examples of undefined complete
-keys are @kbd{C-x C-g}, and @kbd{C-c 3}. @xref{Prefix Keys}, for more
-details.
-
- The rule for finding the binding of a key sequence assumes that the
-intermediate bindings (found for the events before the last) are all
-keymaps; if this is not so, the sequence of events does not form a
-unit---it is not really a key sequence. In other words, removing one or
-more events from the end of any valid key must always yield a prefix
-key. For example, @kbd{C-f C-n} is not a key; @kbd{C-f} is not a prefix
-key, so a longer sequence starting with @kbd{C-f} cannot be a key.
-
- Note that the set of possible multi-event key sequences depends on the
-bindings for prefix keys; therefore, it can be different for different
-keymaps, and can change when bindings are changed. However, a one-event
-sequence is always a key sequence, because it does not depend on any
-prefix keys for its well-formedness.
-
- At any time, several primary keymaps are @dfn{active}---that is, in
-use for finding key bindings. These are the @dfn{global map}, which is
-shared by all buffers; the @dfn{local keymap}, which is usually
-associated with a specific major mode; and zero or more @dfn{minor mode
-keymaps}, which belong to currently enabled minor modes. (Not all minor
-modes have keymaps.) The local keymap bindings shadow (i.e., take
-precedence over) the corresponding global bindings. The minor mode
-keymaps shadow both local and global keymaps. @xref{Active Keymaps},
-for details.
-
-@node Format of Keymaps
-@section Format of Keymaps
-@cindex format of keymaps
-@cindex keymap format
-@cindex full keymap
-@cindex sparse keymap
-
- A keymap is a list whose @sc{car} is the symbol @code{keymap}. The
-remaining elements of the list define the key bindings of the keymap.
-Use the function @code{keymapp} (see below) to test whether an object is
-a keymap.
-
- Each ordinary binding applies to events of a particular @dfn{event
-type}, which is always a character or a symbol. @xref{Classifying
-Events}.
-
- An ordinary element of a keymap is a cons cell of the form
-@code{(@var{type} .@: @var{binding})}. This specifies one binding, for
-events of type @var{type}.
-
-@cindex default key binding
-@c Emacs 19 feature
- A cons cell whose @sc{car} is @code{t} is a @dfn{default key binding};
-any event not bound by other elements of the keymap is given
-@var{binding} as its binding. Default bindings allow a keymap to bind
-all possible event types without having to enumerate all of them. A
-keymap that has a default binding completely masks any lower-precedence
-keymap.
-
- If an element of a keymap is a vector, the vector counts as bindings
-for all the @sc{ASCII} characters; vector element @var{n} is the binding
-for the character with code @var{n}. This is a compact way to
-record lots of bindings. A keymap with such a vector is called a
-@dfn{full keymap}. Other keymaps are called @dfn{sparse keymaps}.
-
- When a keymap contains a vector, it always defines a binding for every
-@sc{ASCII} character even if the vector element is @code{nil}. Such a
-binding of @code{nil} overrides any default binding in the keymap.
-However, default bindings are still meaningful for events that are not
-@sc{ASCII} characters. A binding of @code{nil} does @emph{not}
-override lower-precedence keymaps; thus, if the local map gives a
-binding of @code{nil}, Emacs uses the binding from the global map.
-
-@cindex keymap prompt string
-@cindex overall prompt string
-@cindex prompt string of keymap
- Aside from bindings, a keymap can also have a string as an element.
-This is called the @dfn{overall prompt string} and makes it possible to
-use the keymap as a menu. @xref{Menu Keymaps}.
-
-@cindex meta characters lookup
- Keymaps do not directly record bindings for the meta characters, whose
-codes are from 128 to 255. Instead, meta characters are regarded for
-purposes of key lookup as sequences of two characters, the first of
-which is @key{ESC} (or whatever is currently the value of
-@code{meta-prefix-char}). Thus, the key @kbd{M-a} is really represented
-as @kbd{@key{ESC} a}, and its global binding is found at the slot for
-@kbd{a} in @code{esc-map} (@pxref{Prefix Keys}).
-
- Here as an example is the local keymap for Lisp mode, a sparse
-keymap. It defines bindings for @key{DEL} and @key{TAB}, plus @kbd{C-c
-C-l}, @kbd{M-C-q}, and @kbd{M-C-x}.
-
-@example
-@group
-lisp-mode-map
-@result{}
-@end group
-@group
-(keymap
- ;; @key{TAB}
- (9 . lisp-indent-line)
-@end group
-@group
- ;; @key{DEL}
- (127 . backward-delete-char-untabify)
-@end group
-@group
- (3 keymap
- ;; @kbd{C-c C-l}
- (12 . run-lisp))
-@end group
-@group
- (27 keymap
- ;; @r{@kbd{M-C-q}, treated as @kbd{@key{ESC} C-q}}
- (17 . indent-sexp)
- ;; @r{@kbd{M-C-x}, treated as @kbd{@key{ESC} C-x}}
- (24 . lisp-send-defun)))
-@end group
-@end example
-
-@defun keymapp object
-This function returns @code{t} if @var{object} is a keymap, @code{nil}
-otherwise. More precisely, this function tests for a list whose
-@sc{car} is @code{keymap}.
-
-@example
-@group
-(keymapp '(keymap))
- @result{} t
-@end group
-@group
-(keymapp (current-global-map))
- @result{} t
-@end group
-@end example
-@end defun
-
-@node Creating Keymaps
-@section Creating Keymaps
-@cindex creating keymaps
-
- Here we describe the functions for creating keymaps.
-
-@c ??? This should come after makr-sparse-keymap
-@defun make-keymap &optional prompt
-This function creates and returns a new full keymap (i.e., one
-containing a vector of length 128 for defining all the @sc{ASCII}
-characters). The new keymap initially binds all @sc{ASCII} characters
-to @code{nil}, and does not bind any other kind of event.
-
-@example
-@group
-(make-keymap)
- @result{} (keymap [nil nil nil @dots{} nil nil])
-@end group
-@end example
-
-If you specify @var{prompt}, that becomes the overall prompt string for
-the keymap. The prompt string is useful for menu keymaps (@pxref{Menu
-Keymaps}).
-@end defun
-
-@defun make-sparse-keymap &optional prompt
-This function creates and returns a new sparse keymap with no entries.
-The new keymap does not bind any events. The argument @var{prompt}
-specifies a prompt string, as in @code{make-keymap}.
-
-@example
-@group
-(make-sparse-keymap)
- @result{} (keymap)
-@end group
-@end example
-@end defun
-
-@defun copy-keymap keymap
-This function returns a copy of @var{keymap}. Any keymaps that
-appear directly as bindings in @var{keymap} are also copied recursively,
-and so on to any number of levels. However, recursive copying does not
-take place when the definition of a character is a symbol whose function
-definition is a keymap; the same symbol appears in the new copy.
-@c Emacs 19 feature
-
-@example
-@group
-(setq map (copy-keymap (current-local-map)))
-@result{} (keymap
-@end group
-@group
- ;; @r{(This implements meta characters.)}
- (27 keymap
- (83 . center-paragraph)
- (115 . center-line))
- (9 . tab-to-tab-stop))
-@end group
-
-@group
-(eq map (current-local-map))
- @result{} nil
-@end group
-@group
-(equal map (current-local-map))
- @result{} t
-@end group
-@end example
-@end defun
-
-@node Inheritance and Keymaps
-@section Inheritance and Keymaps
-@cindex keymap inheritance
-@cindex inheriting a keymap's bindings
-
- A keymap can inherit the bindings of another keymap, which we call the
-@dfn{parent keymap}. Such a keymap looks like this:
-
-@example
-(keymap @var{bindings}@dots{} . @var{parent-keymap})
-@end example
-
-@noindent
-The effect is that this keymap inherits all the bindings of
-@var{parent-keymap}, whatever they may be at the time a key is looked up,
-but can add to them or override them with @var{bindings}.
-
-If you change the bindings in @var{parent-keymap} using @code{define-key}
-or other key-binding functions, these changes are visible in the
-inheriting keymap unless shadowed by @var{bindings}. The converse is
-not true: if you use @code{define-key} to change the inheriting keymap,
-that affects @var{bindings}, but has no effect on @var{parent-keymap}.
-
-The proper way to construct a keymap with a parent is to use
-@code{set-keymap-parent}; if you have code that directly constructs a
-keymap with a parent, please convert the program to use
-@code{set-keymap-parent} instead.
-
-@defun keymap-parent keymap
-This returns the parent keymap of @var{keymap}. If @var{keymap}
-has no parent, @code{keymap-parent} returns @code{nil}.
-@end defun
-
-@defun set-keymap-parent keymap parent
-This sets the parent keymap of @var{keymap} to @var{parent}, and returns
-@var{parent}. If @var{parent} is @code{nil}, this function gives
-@var{keymap} no parent at all.
-
-If @var{keymap} has submaps (bindings for prefix keys), they too receive
-new parent keymaps that reflect what @var{parent} specifies for those
-prefix keys.
-@end defun
-
-Here is an example showing how to make a keymap that inherits
-from @code{text-mode-map}:
-
-@example
-(let ((map (make-sparse-keymap)))
- (set-keymap-parent map text-mode-map)
- map)
-@end example
-
-@node Prefix Keys
-@section Prefix Keys
-@cindex prefix key
-
- A @dfn{prefix key} has an associated keymap that defines what to do
-with key sequences that start with the prefix key. For example,
-@kbd{C-x} is a prefix key, and it uses a keymap that is also stored in
-the variable @code{ctl-x-map}. Here is a list of the standard prefix
-keys of Emacs and their keymaps:
-
-@itemize @bullet
-@item
-@vindex esc-map
-@findex ESC-prefix
-@code{esc-map} is used for events that follow @key{ESC}. Thus, the
-global definitions of all meta characters are actually found here. This
-map is also the function definition of @code{ESC-prefix}.
-
-@item
-@cindex @kbd{C-h}
-@code{help-map} is used for events that follow @kbd{C-h}.
-
-@item
-@cindex @kbd{C-c}
-@vindex mode-specific-map
-@code{mode-specific-map} is for events that follow @kbd{C-c}. This
-map is not actually mode specific; its name was chosen to be informative
-for the user in @kbd{C-h b} (@code{display-bindings}), where it
-describes the main use of the @kbd{C-c} prefix key.
-
-@item
-@cindex @kbd{C-x}
-@vindex ctl-x-map
-@findex Control-X-prefix
-@code{ctl-x-map} is the map used for events that follow @kbd{C-x}. This
-map is also the function definition of @code{Control-X-prefix}.
-
-@item
-@cindex @kbd{C-x 4}
-@vindex ctl-x-4-map
-@code{ctl-x-4-map} is used for events that follow @kbd{C-x 4}.
-
-@c Emacs 19 feature
-@item
-@cindex @kbd{C-x 5}
-@vindex ctl-x-5-map
-@code{ctl-x-5-map} is used for events that follow @kbd{C-x 5}.
-
-@c Emacs 19 feature
-@item
-@cindex @kbd{C-x n}
-@cindex @kbd{C-x r}
-@cindex @kbd{C-x a}
-The prefix keys @kbd{C-x n}, @kbd{C-x r} and @kbd{C-x a} use keymaps
-that have no special name.
-@end itemize
-
- The binding of a prefix key is the keymap to use for looking up the
-events that follow the prefix key. (It may instead be a symbol whose
-function definition is a keymap. The effect is the same, but the symbol
-serves as a name for the prefix key.) Thus, the binding of @kbd{C-x} is
-the symbol @code{Control-X-prefix}, whose function definition is the
-keymap for @kbd{C-x} commands. (The same keymap is also the value of
-@code{ctl-x-map}.)
-
- Prefix key definitions can appear in any active keymap. 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 and minor modes can redefine a key as a prefix by
-putting a prefix key definition for it in the local map or the minor
-mode's map. @xref{Active Keymaps}.
-
- If a key is defined as a prefix in more than one active map, then its
-various definitions are in effect merged: the commands defined in the
-minor mode keymaps come first, followed by those in the local map's
-prefix definition, and then by those from the global map.
-
- In the following example, we make @kbd{C-p} a prefix key in the local
-keymap, in such a way that @kbd{C-p} is identical to @kbd{C-x}. Then
-the binding for @kbd{C-p C-f} is the function @code{find-file}, just
-like @kbd{C-x C-f}. The key sequence @kbd{C-p 6} is not found in any
-active keymap.
-
-@example
-@group
-(use-local-map (make-sparse-keymap))
- @result{} nil
-@end group
-@group
-(local-set-key "\C-p" ctl-x-map)
- @result{} nil
-@end group
-@group
-(key-binding "\C-p\C-f")
- @result{} find-file
-@end group
-
-@group
-(key-binding "\C-p6")
- @result{} nil
-@end group
-@end example
-
-@defun define-prefix-command symbol
-@cindex prefix command
-This function defines @var{symbol} as a prefix command: it creates a
-full keymap and stores it as @var{symbol}'s function definition.
-Storing the symbol as the binding of a key makes the key a prefix key
-that has a name. The function also sets @var{symbol} as a variable, to
-have the keymap as its value. It returns @var{symbol}.
-
- In Emacs version 18, only the function definition of @var{symbol} was
-set, not the value as a variable.
-@end defun
-
-@node Active Keymaps
-@section Active Keymaps
-@cindex active keymap
-@cindex global keymap
-@cindex local keymap
-
- Emacs normally contains many keymaps; at any given time, just a few of
-them are @dfn{active} in that they participate in the interpretation
-of user input. These are the global keymap, the current buffer's
-local keymap, and the keymaps of any enabled minor modes.
-
- The @dfn{global keymap} holds the bindings of keys that are defined
-regardless of the current buffer, such as @kbd{C-f}. The variable
-@code{global-map} holds this keymap, which is always active.
-
- Each buffer may have another keymap, its @dfn{local keymap}, which may
-contain new or overriding definitions for keys. The current buffer's
-local keymap is always active except when @code{overriding-local-map}
-overrides it. Text properties can specify an alternative local map for
-certain parts of the buffer; see @ref{Special Properties}.
-
- Each minor mode may have a keymap; if it does, the keymap is active
-when the minor mode is enabled.
-
- The variable @code{overriding-local-map}, if non-@code{nil}, specifies
-another local keymap that overrides the buffer's local map and all the
-minor mode keymaps.
-
- All the active keymaps are used together to determine what command to
-execute when a key is entered. Emacs searches these maps one by one, in
-order of decreasing precedence, until it finds a binding in one of the maps.
-
- Normally, Emacs @emph{first} searches for the key in the minor mode
-maps (one map at a time); if they do not supply a binding for the key,
-Emacs searches the local map; if that too has no binding, Emacs then
-searches the global map. However, if @code{overriding-local-map} is
-non-@code{nil}, Emacs searches that map first, followed by the global
-map.
-
- The procedure for searching a single keymap is called
-@dfn{key lookup}; see @ref{Key Lookup}.
-
-@cindex major mode keymap
- Since every buffer that uses the same major mode normally uses the
-same local keymap, you can think of the keymap as local to the mode. A
-change to the local keymap of a buffer (using @code{local-set-key}, for
-example) is seen also in the other buffers that share that keymap.
-
- The local keymaps that are used for Lisp mode, C mode, and several
-other major modes exist even if they have not yet been used. These
-local maps are the values of the variables @code{lisp-mode-map},
-@code{c-mode-map}, and so on. For most other modes, which are less
-frequently used, the local keymap is constructed only when the mode is
-used for the first time in a session.
-
- The minibuffer has local keymaps, too; they contain various completion
-and exit commands. @xref{Intro to Minibuffers}.
-
- @xref{Standard Keymaps}, for a list of standard keymaps.
-
-@defvar global-map
-This variable contains the default global keymap that maps Emacs
-keyboard input to commands. The global keymap is normally this keymap.
-The default global keymap is a full keymap that binds
-@code{self-insert-command} to all of the printing characters.
-
-It is normal practice to change the bindings in the global map, but you
-should not assign this variable any value other than the keymap it starts
-out with.
-@end defvar
-
-@defun current-global-map
-This function returns the current global keymap. This is the
-same as the value of @code{global-map} unless you change one or the
-other.
-
-@example
-@group
-(current-global-map)
-@result{} (keymap [set-mark-command beginning-of-line @dots{}
- delete-backward-char])
-@end group
-@end example
-@end defun
-
-@defun current-local-map
-This function returns the current buffer's local keymap, or @code{nil}
-if it has none. In the following example, the keymap for the
-@samp{*scratch*} buffer (using Lisp Interaction mode) is a sparse keymap
-in which the entry for @key{ESC}, @sc{ASCII} code 27, is another sparse
-keymap.
-
-@example
-@group
-(current-local-map)
-@result{} (keymap
- (10 . eval-print-last-sexp)
- (9 . lisp-indent-line)
- (127 . backward-delete-char-untabify)
-@end group
-@group
- (27 keymap
- (24 . eval-defun)
- (17 . indent-sexp)))
-@end group
-@end example
-@end defun
-
-@defun current-minor-mode-maps
-This function returns a list of the keymaps of currently enabled minor modes.
-@end defun
-
-@defun use-global-map keymap
-This function makes @var{keymap} the new current global keymap. It
-returns @code{nil}.
-
-It is very unusual to change the global keymap.
-@end defun
-
-@defun use-local-map keymap
-This function makes @var{keymap} the new local keymap of the current
-buffer. If @var{keymap} is @code{nil}, then the buffer has no local
-keymap. @code{use-local-map} returns @code{nil}. Most major mode
-commands use this function.
-@end defun
-
-@c Emacs 19 feature
-@defvar minor-mode-map-alist
-This variable is an alist describing keymaps that may or may not be
-active according to the values of certain variables. Its elements look
-like this:
-
-@example
-(@var{variable} . @var{keymap})
-@end example
-
-The keymap @var{keymap} is active whenever @var{variable} has a
-non-@code{nil} value. Typically @var{variable} is the variable that
-enables or disables a minor mode. @xref{Keymaps and Minor Modes}.
-
-Note that elements of @code{minor-mode-map-alist} do not have the same
-structure as elements of @code{minor-mode-alist}. The map must be the
-@sc{cdr} of the element; a list with the map as the second element will
-not do.
-
-What's more, the keymap itself must appear in the @sc{cdr}. It does not
-work to store a variable in the @sc{cdr} and make the map the value of
-that variable.
-
-When more than one minor mode keymap is active, their order of priority
-is the order of @code{minor-mode-map-alist}. But you should design
-minor modes so that they don't interfere with each other. If you do
-this properly, the order will not matter.
-
-See also @code{minor-mode-key-binding}, above. See @ref{Keymaps and
-Minor Modes}, for more information about minor modes.
-@end defvar
-
-@defvar overriding-local-map
-If non-@code{nil}, this variable holds a keymap to use instead of the
-buffer's local keymap and instead of all the minor mode keymaps. This
-keymap, if any, overrides all other maps that would have been active,
-except for the current global map.
-@end defvar
-
-@defvar overriding-terminal-local-map
-If non-@code{nil}, this variable holds a keymap to use instead of
-@code{overriding-local-map}, the buffer's local keymap and all the minor
-mode keymaps.
-
-This variable is always local to the current terminal and cannot be
-buffer-local. @xref{Multiple Displays}. It is used to implement
-incremental search mode.
-@end defvar
-
-@defvar overriding-local-map-menu-flag
-If this variable is non-@code{nil}, the value of
-@code{overriding-local-map} or @code{overriding-terminal-local-map} can
-affect the display of the menu bar. The default value is @code{nil}, so
-those map variables have no effect on the menu bar.
-
-Note that these two map variables do affect the execution of key
-sequences entered using the menu bar, even if they do not affect the
-menu bar display. So if a menu bar key sequence comes in, you should
-clear the variables before looking up and executing that key sequence.
-Modes that use the variables would typically do this anyway; normally
-they respond to events that they do not handle by ``unreading'' them and
-exiting.
-@end defvar
-
-@node Key Lookup
-@section Key Lookup
-@cindex key lookup
-@cindex keymap entry
-
- @dfn{Key lookup} is the process of finding the binding of a key
-sequence from a given keymap. Actual execution of the binding is not
-part of key lookup.
-
- Key lookup uses just the event type of each event in the key
-sequence; the rest of the event is ignored. In fact, a key sequence
-used for key lookup may designate mouse events with just their types
-(symbols) instead of with entire mouse events (lists). @xref{Input
-Events}. Such a pseudo-key-sequence is insufficient for
-@code{command-execute}, but it is sufficient for looking up or rebinding
-a key.
-
- When the key sequence consists of multiple events, key lookup
-processes the events sequentially: the binding of the first event is
-found, and must be a keymap; then the second event's binding is found in
-that keymap, and so on until all the events in the key sequence are used
-up. (The binding thus found for the last event may or may not be a
-keymap.) Thus, the process of key lookup is defined in terms of a
-simpler process for looking up a single event in a keymap. How that is
-done depends on the type of object associated with the event in that
-keymap.
-
- Let's use the term @dfn{keymap entry} to describe the value found by
-looking up an event type in a keymap. (This doesn't include the item
-string and other extra elements in menu key bindings because
-@code{lookup-key} and other key lookup functions don't include them in
-the returned value.) While any Lisp object may be stored in a keymap as
-a keymap entry, not all make sense for key lookup. Here is a list of
-the meaningful kinds of keymap entries:
-
-@table @asis
-@item @code{nil}
-@cindex @code{nil} in keymap
-@code{nil} means that the events used so far in the lookup form an
-undefined key. When a keymap fails to mention an event type at all, and
-has no default binding, that is equivalent to a binding of @code{nil}
-for that event type.
-
-@item @var{keymap}
-@cindex keymap in keymap
-The events used so far in the lookup form a prefix key. The next
-event of the key sequence is looked up in @var{keymap}.
-
-@item @var{command}
-@cindex command in keymap
-The events used so far in the lookup form a complete key,
-and @var{command} is its binding. @xref{What Is a Function}.
-
-@item @var{array}
-@cindex string in keymap
-The array (either a string or a vector) is a keyboard macro. The events
-used so far in the lookup form a complete key, and the array is its
-binding. See @ref{Keyboard Macros}, for more information.
-
-@item @var{list}
-@cindex list in keymap
-The meaning of a list depends on the types of the elements of the list.
-
-@itemize @bullet
-@item
-If the @sc{car} of @var{list} is the symbol @code{keymap}, then the list
-is a keymap, and is treated as a keymap (see above).
-
-@item
-@cindex @code{lambda} in keymap
-If the @sc{car} of @var{list} is @code{lambda}, then the list is a
-lambda expression. This is presumed to be a command, and is treated as
-such (see above).
-
-@item
-If the @sc{car} of @var{list} is a keymap and the @sc{cdr} is an event
-type, then this is an @dfn{indirect entry}:
-
-@example
-(@var{othermap} . @var{othertype})
-@end example
-
-When key lookup encounters an indirect entry, it looks up instead the
-binding of @var{othertype} in @var{othermap} and uses that.
-
-This feature permits you to define one key as an alias for another key.
-For example, an entry whose @sc{car} is the keymap called @code{esc-map}
-and whose @sc{cdr} is 32 (the code for @key{SPC}) means, ``Use the global
-binding of @kbd{Meta-@key{SPC}}, whatever that may be.''
-@end itemize
-
-@item @var{symbol}
-@cindex symbol in keymap
-The function definition of @var{symbol} is used in place of
-@var{symbol}. If that too is a symbol, then this process is repeated,
-any number of times. Ultimately this should lead to an object that is
-a keymap, a command or a keyboard macro. A list is allowed if it is a
-keymap or a command, but indirect entries are not understood when found
-via symbols.
-
-Note that keymaps and keyboard macros (strings and vectors) are not
-valid functions, so a symbol with a keymap, string, or vector as its
-function definition is invalid as a function. It is, however, valid as
-a key binding. If the definition is a keyboard macro, then the symbol
-is also valid as an argument to @code{command-execute}
-(@pxref{Interactive Call}).
-
-@cindex @code{undefined} in keymap
-The symbol @code{undefined} is worth special mention: it means to treat
-the key as undefined. Strictly speaking, the key is defined, and its
-binding is the command @code{undefined}; but that command does the same
-thing that is done automatically for an undefined key: it rings the bell
-(by calling @code{ding}) but does not signal an error.
-
-@cindex preventing prefix key
-@code{undefined} is used in local keymaps to override a global key
-binding and make the key ``undefined'' locally. A local binding of
-@code{nil} would fail to do this because it would not override the
-global binding.
-
-@item @var{anything else}
-If any other type of object is found, the events used so far in the
-lookup form a complete key, and the object is its binding, but the
-binding is not executable as a command.
-@end table
-
- In short, a keymap entry may be a keymap, a command, a keyboard macro,
-a symbol that leads to one of them, or an indirection or @code{nil}.
-Here is an example of a sparse keymap with two characters bound to
-commands and one bound to another keymap. This map is the normal value
-of @code{emacs-lisp-mode-map}. Note that 9 is the code for @key{TAB},
-127 for @key{DEL}, 27 for @key{ESC}, 17 for @kbd{C-q} and 24 for
-@kbd{C-x}.
-
-@example
-@group
-(keymap (9 . lisp-indent-line)
- (127 . backward-delete-char-untabify)
- (27 keymap (17 . indent-sexp) (24 . eval-defun)))
-@end group
-@end example
-
-@node Functions for Key Lookup
-@section Functions for Key Lookup
-
- Here are the functions and variables pertaining to key lookup.
-
-@defun lookup-key keymap key &optional accept-defaults
-This function returns the definition of @var{key} in @var{keymap}. If
-the string or vector @var{key} is not a valid key sequence according to
-the prefix keys specified in @var{keymap} (which means it is ``too
-long'' and has extra events at the end), then the value is a number, the
-number of events at the front of @var{key} that compose a complete key.
-
-@c Emacs 19 feature
-If @var{accept-defaults} is non-@code{nil}, then @code{lookup-key}
-considers default bindings as well as bindings for the specific events
-in @var{key}. Otherwise, @code{lookup-key} reports only bindings for
-the specific sequence @var{key}, ignoring default bindings except when
-you explicitly ask about them. (To do this, supply @code{t} as an
-element of @var{key}; see @ref{Format of Keymaps}.)
-
-All the other functions described in this chapter that look up keys use
-@code{lookup-key}.
-
-@example
-@group
-(lookup-key (current-global-map) "\C-x\C-f")
- @result{} find-file
-@end group
-@group
-(lookup-key (current-global-map) "\C-x\C-f12345")
- @result{} 2
-@end group
-@end example
-
- If @var{key} contains a meta character, that character is implicitly
-replaced by a two-character sequence: the value of
-@code{meta-prefix-char}, followed by the corresponding non-meta
-character. Thus, the first example below is handled by conversion into
-the second example.
-
-@example
-@group
-(lookup-key (current-global-map) "\M-f")
- @result{} forward-word
-@end group
-@group
-(lookup-key (current-global-map) "\ef")
- @result{} forward-word
-@end group
-@end example
-
-Unlike @code{read-key-sequence}, this function does not modify the
-specified events in ways that discard information (@pxref{Key Sequence
-Input}). In particular, it does not convert letters to lower case and
-it does not change drag events to clicks.
-@end defun
-
-@deffn Command undefined
-Used in keymaps to undefine keys. It calls @code{ding}, but does
-not cause an error.
-@end deffn
-
-@defun key-binding key &optional accept-defaults
-This function returns the binding for @var{key} in the current
-keymaps, trying all the active keymaps. The result is @code{nil} if
-@var{key} is undefined in the keymaps.
-
-@c Emacs 19 feature
-The argument @var{accept-defaults} controls checking for default
-bindings, as in @code{lookup-key} (above).
-
-An error is signaled if @var{key} is not a string or a vector.
-
-@example
-@group
-(key-binding "\C-x\C-f")
- @result{} find-file
-@end group
-@end example
-@end defun
-
-@defun local-key-binding key &optional accept-defaults
-This function returns the binding for @var{key} in the current
-local keymap, or @code{nil} if it is undefined there.
-
-@c Emacs 19 feature
-The argument @var{accept-defaults} controls checking for default bindings,
-as in @code{lookup-key} (above).
-@end defun
-
-@defun global-key-binding key &optional accept-defaults
-This function returns the binding for command @var{key} in the
-current global keymap, or @code{nil} if it is undefined there.
-
-@c Emacs 19 feature
-The argument @var{accept-defaults} controls checking for default bindings,
-as in @code{lookup-key} (above).
-@end defun
-
-@c Emacs 19 feature
-@defun minor-mode-key-binding key &optional accept-defaults
-This function returns a list of all the active minor mode bindings of
-@var{key}. More precisely, it returns an alist of pairs
-@code{(@var{modename} . @var{binding})}, where @var{modename} is the
-variable that enables the minor mode, and @var{binding} is @var{key}'s
-binding in that mode. If @var{key} has no minor-mode bindings, the
-value is @code{nil}.
-
-If the first binding is not a prefix command, all subsequent bindings
-from other minor modes are omitted, since they would be completely
-shadowed. Similarly, the list omits non-prefix bindings that follow
-prefix bindings.
-
-The argument @var{accept-defaults} controls checking for default
-bindings, as in @code{lookup-key} (above).
-@end defun
-
-@defvar meta-prefix-char
-@cindex @key{ESC}
-This variable is the meta-prefix character code. It is used when
-translating a meta character to a two-character sequence so it can be
-looked up in a keymap. For useful results, the value should be a prefix
-event (@pxref{Prefix Keys}). The default value is 27, which is the
-@sc{ASCII} code for @key{ESC}.
-
-As long as the value of @code{meta-prefix-char} remains 27, key
-lookup translates @kbd{M-b} into @kbd{@key{ESC} b}, which is normally
-defined as the @code{backward-word} command. However, if you set
-@code{meta-prefix-char} to 24, the code for @kbd{C-x}, then Emacs will
-translate @kbd{M-b} into @kbd{C-x b}, whose standard binding is the
-@code{switch-to-buffer} command.
-
-@smallexample
-@group
-meta-prefix-char ; @r{The default value.}
- @result{} 27
-@end group
-@group
-(key-binding "\M-b")
- @result{} backward-word
-@end group
-@group
-?\C-x ; @r{The print representation}
- @result{} 24 ; @r{of a character.}
-@end group
-@group
-(setq meta-prefix-char 24)
- @result{} 24
-@end group
-@group
-(key-binding "\M-b")
- @result{} switch-to-buffer ; @r{Now, typing @kbd{M-b} is}
- ; @r{like typing @kbd{C-x b}.}
-
-(setq meta-prefix-char 27) ; @r{Avoid confusion!}
- @result{} 27 ; @r{Restore the default value!}
-@end group
-@end smallexample
-@end defvar
-
-@node Changing Key Bindings
-@section Changing Key Bindings
-@cindex changing key bindings
-@cindex rebinding
-
- The way to rebind a key is to change its entry in a keymap. If you
-change a binding in the global keymap, the change is effective in all
-buffers (though it has no direct effect in buffers that shadow the
-global binding with a local one). If you change the current buffer's
-local map, that usually affects all buffers using the same major mode.
-The @code{global-set-key} and @code{local-set-key} functions are
-convenient interfaces for these operations (@pxref{Key Binding
-Commands}). You can also use @code{define-key}, a more general
-function; then you must specify explicitly the map to change.
-
-@cindex meta character key constants
-@cindex control character key constants
- In writing the key sequence to rebind, it is good to use the special
-escape sequences for control and meta characters (@pxref{String Type}).
-The syntax @samp{\C-} means that the following character is a control
-character and @samp{\M-} means that the following character is a meta
-character. Thus, the string @code{"\M-x"} is read as containing a
-single @kbd{M-x}, @code{"\C-f"} is read as containing a single
-@kbd{C-f}, and @code{"\M-\C-x"} and @code{"\C-\M-x"} are both read as
-containing a single @kbd{C-M-x}. You can also use this escape syntax in
-vectors, as well as others that aren't allowed in strings; one example
-is @samp{[?\C-\H-x home]}. @xref{Character Type}.
-
- The key definition and lookup functions accept an alternate syntax for
-event types in a key sequence that is a vector: you can use a list
-containing modifier names plus one base event (a character or function
-key name). For example, @code{(control ?a)} is equivalent to
-@code{?\C-a} and @code{(hyper control left)} is equivalent to
-@code{C-H-left}.
-
- One advantage of using a list to represent the event type is that the
-precise numeric codes for the modifier bits don't appear in compiled
-files.
-
- For the functions below, an error is signaled if @var{keymap} is not a
-keymap or if @var{key} is not a string or vector representing a key
-sequence. You can use event types (symbols) as shorthand for events
-that are lists.
-
-@defun define-key keymap key binding
-This function sets the binding for @var{key} in @var{keymap}. (If
-@var{key} is more than one event long, the change is actually made
-in another keymap reached from @var{keymap}.) The argument
-@var{binding} can be any Lisp object, but only certain types are
-meaningful. (For a list of meaningful types, see @ref{Key Lookup}.)
-The value returned by @code{define-key} is @var{binding}.
-
-@cindex invalid prefix key error
-@cindex key sequence error
-Every prefix of @var{key} must be a prefix key (i.e., bound to a
-keymap) or undefined; otherwise an error is signaled.
-
-If some prefix of @var{key} is undefined, then @code{define-key} defines
-it as a prefix key so that the rest of @var{key} may be defined as
-specified.
-@end defun
-
- Here is an example that creates a sparse keymap and makes a number of
-bindings in it:
-
-@smallexample
-@group
-(setq map (make-sparse-keymap))
- @result{} (keymap)
-@end group
-@group
-(define-key map "\C-f" 'forward-char)
- @result{} forward-char
-@end group
-@group
-map
- @result{} (keymap (6 . forward-char))
-@end group
-
-@group
-;; @r{Build sparse submap for @kbd{C-x} and bind @kbd{f} in that.}
-(define-key map "\C-xf" 'forward-word)
- @result{} forward-word
-@end group
-@group
-map
-@result{} (keymap
- (24 keymap ; @kbd{C-x}
- (102 . forward-word)) ; @kbd{f}
- (6 . forward-char)) ; @kbd{C-f}
-@end group
-
-@group
-;; @r{Bind @kbd{C-p} to the @code{ctl-x-map}.}
-(define-key map "\C-p" ctl-x-map)
-;; @code{ctl-x-map}
-@result{} [nil @dots{} find-file @dots{} backward-kill-sentence]
-@end group
-
-@group
-;; @r{Bind @kbd{C-f} to @code{foo} in the @code{ctl-x-map}.}
-(define-key map "\C-p\C-f" 'foo)
-@result{} 'foo
-@end group
-@group
-map
-@result{} (keymap ; @r{Note @code{foo} in @code{ctl-x-map}.}
- (16 keymap [nil @dots{} foo @dots{} backward-kill-sentence])
- (24 keymap
- (102 . forward-word))
- (6 . forward-char))
-@end group
-@end smallexample
-
-@noindent
-Note that storing a new binding for @kbd{C-p C-f} actually works by
-changing an entry in @code{ctl-x-map}, and this has the effect of
-changing the bindings of both @kbd{C-p C-f} and @kbd{C-x C-f} in the
-default global map.
-
-@defun substitute-key-definition olddef newdef keymap &optional oldmap
-@cindex replace bindings
-This function replaces @var{olddef} with @var{newdef} for any keys in
-@var{keymap} that were bound to @var{olddef}. In other words,
-@var{olddef} is replaced with @var{newdef} wherever it appears. The
-function returns @code{nil}.
-
-For example, this redefines @kbd{C-x C-f}, if you do it in an Emacs with
-standard bindings:
-
-@smallexample
-@group
-(substitute-key-definition
- 'find-file 'find-file-read-only (current-global-map))
-@end group
-@end smallexample
-
-@c Emacs 19 feature
-If @var{oldmap} is non-@code{nil}, then its bindings determine which
-keys to rebind. The rebindings still happen in @var{keymap}, not in
-@var{oldmap}. Thus, you can change one map under the control of the
-bindings in another. For example,
-
-@smallexample
-(substitute-key-definition
- 'delete-backward-char 'my-funny-delete
- my-map global-map)
-@end smallexample
-
-@noindent
-puts the special deletion command in @code{my-map} for whichever keys
-are globally bound to the standard deletion command.
-
-@ignore
-@c Emacs 18 only
-Prefix keymaps that appear within @var{keymap} are not checked
-recursively for keys bound to @var{olddef}; they are not changed at all.
-Perhaps it would be better to check nested keymaps recursively.
-@end ignore
-
-Here is an example showing a keymap before and after substitution:
-
-@smallexample
-@group
-(setq map '(keymap
- (?1 . olddef-1)
- (?2 . olddef-2)
- (?3 . olddef-1)))
-@result{} (keymap (49 . olddef-1) (50 . olddef-2) (51 . olddef-1))
-@end group
-
-@group
-(substitute-key-definition 'olddef-1 'newdef map)
-@result{} nil
-@end group
-@group
-map
-@result{} (keymap (49 . newdef) (50 . olddef-2) (51 . newdef))
-@end group
-@end smallexample
-@end defun
-
-@defun suppress-keymap keymap &optional nodigits
-@cindex @code{self-insert-command} override
-This function changes the contents of the full keymap @var{keymap} by
-making all the printing characters undefined. More precisely, it binds
-them to the command @code{undefined}. This makes ordinary insertion of
-text impossible. @code{suppress-keymap} returns @code{nil}.
-
-If @var{nodigits} is @code{nil}, then @code{suppress-keymap} defines
-digits to run @code{digit-argument}, and @kbd{-} to run
-@code{negative-argument}. Otherwise it makes them undefined like the
-rest of the printing characters.
-
-@cindex yank suppression
-@cindex @code{quoted-insert} suppression
-The @code{suppress-keymap} function does not make it impossible to
-modify a buffer, as it does not suppress commands such as @code{yank}
-and @code{quoted-insert}. To prevent any modification of a buffer, make
-it read-only (@pxref{Read Only Buffers}).
-
-Since this function modifies @var{keymap}, you would normally use it
-on a newly created keymap. Operating on an existing keymap
-that is used for some other purpose is likely to cause trouble; for
-example, suppressing @code{global-map} would make it impossible to use
-most of Emacs.
-
-Most often, @code{suppress-keymap} is used to initialize local
-keymaps of modes such as Rmail and Dired where insertion of text is not
-desirable and the buffer is read-only. Here is an example taken from
-the file @file{emacs/lisp/dired.el}, showing how the local keymap for
-Dired mode is set up:
-
-@smallexample
-@group
- @dots{}
- (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)
- @dots{}
-@end group
-@end smallexample
-@end defun
-
-@node Key Binding Commands
-@section Commands for Binding Keys
-
- This section describes some convenient interactive interfaces for
-changing key bindings. They work by calling @code{define-key}.
-
- People often use @code{global-set-key} in their @file{.emacs} file for
-simple customization. For example,
-
-@smallexample
-(global-set-key "\C-x\C-\\" 'next-line)
-@end smallexample
-
-@noindent
-or
-
-@smallexample
-(global-set-key [?\C-x ?\C-\\] 'next-line)
-@end smallexample
-
-@noindent
-or
-
-@smallexample
-(global-set-key [(control ?x) (control ?\\)] 'next-line)
-@end smallexample
-
-@noindent
-redefines @kbd{C-x C-\} to move down a line.
-
-@smallexample
-(global-set-key [M-mouse-1] 'mouse-set-point)
-@end smallexample
-
-@noindent
-redefines the first (leftmost) mouse button, typed with the Meta key, to
-set point where you click.
-
-@deffn Command global-set-key key definition
-This function sets the binding of @var{key} in the current global map
-to @var{definition}.
-
-@smallexample
-@group
-(global-set-key @var{key} @var{definition})
-@equiv{}
-(define-key (current-global-map) @var{key} @var{definition})
-@end group
-@end smallexample
-@end deffn
-
-@deffn Command global-unset-key key
-@cindex unbinding keys
-This function removes the binding of @var{key} from the current
-global map.
-
-One use of this function is in preparation for defining a longer key
-that uses @var{key} as a prefix---which would not be allowed if
-@var{key} has a non-prefix binding. For example:
-
-@smallexample
-@group
-(global-unset-key "\C-l")
- @result{} nil
-@end group
-@group
-(global-set-key "\C-l\C-l" 'redraw-display)
- @result{} nil
-@end group
-@end smallexample
-
-This function is implemented simply using @code{define-key}:
-
-@smallexample
-@group
-(global-unset-key @var{key})
-@equiv{}
-(define-key (current-global-map) @var{key} nil)
-@end group
-@end smallexample
-@end deffn
-
-@deffn Command local-set-key key definition
-This function sets the binding of @var{key} in the current local
-keymap to @var{definition}.
-
-@smallexample
-@group
-(local-set-key @var{key} @var{definition})
-@equiv{}
-(define-key (current-local-map) @var{key} @var{definition})
-@end group
-@end smallexample
-@end deffn
-
-@deffn Command local-unset-key key
-This function removes the binding of @var{key} from the current
-local map.
-
-@smallexample
-@group
-(local-unset-key @var{key})
-@equiv{}
-(define-key (current-local-map) @var{key} nil)
-@end group
-@end smallexample
-@end deffn
-
-@node Scanning Keymaps
-@section Scanning Keymaps
-
- This section describes functions used to scan all the current keymaps
-for the sake of printing help information.
-
-@defun accessible-keymaps keymap &optional prefix
-This function returns a list of all the keymaps that can be accessed
-(via prefix keys) from @var{keymap}. The value is an association list
-with elements of the form @code{(@var{key} .@: @var{map})}, where
-@var{key} is a prefix key whose definition in @var{keymap} is
-@var{map}.
-
-The elements of the alist are ordered so that the @var{key} increases
-in length. The first element is always @code{("" .@: @var{keymap})},
-because the specified keymap is accessible from itself with a prefix of
-no events.
-
-If @var{prefix} is given, it should be a prefix key sequence; then
-@code{accessible-keymaps} includes only the submaps whose prefixes start
-with @var{prefix}. These elements look just as they do in the value of
-@code{(accessible-keymaps)}; the only difference is that some elements
-are omitted.
-
-In the example below, the returned alist indicates that the key
-@key{ESC}, which is displayed as @samp{^[}, is a prefix key whose
-definition is the sparse keymap @code{(keymap (83 .@: center-paragraph)
-(115 .@: foo))}.
-
-@smallexample
-@group
-(accessible-keymaps (current-local-map))
-@result{}(("" keymap
- (27 keymap ; @r{Note this keymap for @key{ESC} is repeated below.}
- (83 . center-paragraph)
- (115 . center-line))
- (9 . tab-to-tab-stop))
-@end group
-
-@group
- ("^[" keymap
- (83 . center-paragraph)
- (115 . foo)))
-@end group
-@end smallexample
-
-In the following example, @kbd{C-h} is a prefix key that uses a sparse
-keymap starting with @code{(keymap (118 . describe-variable)@dots{})}.
-Another prefix, @kbd{C-x 4}, uses a keymap which is also the value of
-the variable @code{ctl-x-4-map}. The event @code{mode-line} is one of
-several dummy events used as prefixes for mouse actions in special parts
-of a window.
-
-@smallexample
-@group
-(accessible-keymaps (current-global-map))
-@result{} (("" keymap [set-mark-command beginning-of-line @dots{}
- delete-backward-char])
-@end group
-@group
- ("^H" keymap (118 . describe-variable) @dots{}
- (8 . help-for-help))
-@end group
-@group
- ("^X" keymap [x-flush-mouse-queue @dots{}
- backward-kill-sentence])
-@end group
-@group
- ("^[" keymap [mark-sexp backward-sexp @dots{}
- backward-kill-word])
-@end group
- ("^X4" keymap (15 . display-buffer) @dots{})
-@group
- ([mode-line] keymap
- (S-mouse-2 . mouse-split-window-horizontally) @dots{}))
-@end group
-@end smallexample
-
-@noindent
-These are not all the keymaps you would see in an actual case.
-@end defun
-
-@defun where-is-internal command &optional keymap firstonly noindirect
-This function returns a list of key sequences (of any length) that are
-bound to @var{command} in a set of keymaps.
-
-The argument @var{command} can be any object; it is compared with all
-keymap entries using @code{eq}.
-
-If @var{keymap} is @code{nil}, then the maps used are the current active
-keymaps, disregarding @code{overriding-local-map} (that is, pretending
-its value is @code{nil}). If @var{keymap} is non-@code{nil}, then the
-maps searched are @var{keymap} and the global keymap.
-
-Usually it's best to use @code{overriding-local-map} as the expression
-for @var{keymap}. Then @code{where-is-internal} searches precisely the
-keymaps that are active. To search only the global map, pass
-@code{(keymap)} (an empty keymap) as @var{keymap}.
-
-If @var{firstonly} is @code{non-ascii}, then the value is a single
-string representing the first key sequence found, rather than a list of
-all possible key sequences. If @var{firstonly} is @code{t}, then the
-value is the first key sequence, except that key sequences consisting
-entirely of @sc{ASCII} characters (or meta variants of @sc{ASCII}
-characters) are preferred to all other key sequences.
-
-If @var{noindirect} is non-@code{nil}, @code{where-is-internal} doesn't
-follow indirect keymap bindings. This makes it possible to search for
-an indirect definition itself.
-
-This function is used by @code{where-is} (@pxref{Help, , Help, emacs,
-The GNU Emacs Manual}).
-
-@smallexample
-@group
-(where-is-internal 'describe-function)
- @result{} ("\^hf" "\^hd")
-@end group
-@end smallexample
-@end defun
-
-@deffn Command describe-bindings prefix
-This function creates a listing of all defined keys and their
-definitions. It writes the listing in a buffer named @samp{*Help*} and
-displays it in a window.
-
-If @var{prefix} is non-@code{nil}, it should be a prefix key; then the
-listing includes only keys that start with @var{prefix}.
-
-The listing describes meta characters as @key{ESC} followed by the
-corresponding non-meta character.
-
-When several characters with consecutive @sc{ASCII} codes have the
-same definition, they are shown together, as
-@samp{@var{firstchar}..@var{lastchar}}. In this instance, you need to
-know the @sc{ASCII} codes to understand which characters this means.
-For example, in the default global map, the characters @samp{@key{SPC}
-..@: ~} are described by a single line. @key{SPC} is @sc{ASCII} 32,
-@kbd{~} is @sc{ASCII} 126, and the characters between them include all
-the normal printing characters, (e.g., letters, digits, punctuation,
-etc.@:); all these characters are bound to @code{self-insert-command}.
-@end deffn
-
-@node Menu Keymaps
-@section Menu Keymaps
-@cindex menu keymaps
-
-@c Emacs 19 feature
-A keymap can define a menu as well as bindings for keyboard keys and
-mouse button. Menus are usually actuated with the mouse, but they can
-work with the keyboard also.
-
-@menu
-* Defining Menus:: How to make a keymap that defines a menu.
-* Mouse Menus:: How users actuate the menu with the mouse.
-* Keyboard Menus:: How they actuate it with the keyboard.
-* Menu Example:: Making a simple menu.
-* Menu Bar:: How to customize the menu bar.
-* Modifying Menus:: How to add new items to a menu.
-@end menu
-
-@node Defining Menus
-@subsection Defining Menus
-@cindex defining menus
-@cindex menu prompt string
-@cindex prompt string (of menu)
-
-A keymap is suitable for menu use if it has an @dfn{overall prompt
-string}, which is a string that appears as an element of the keymap.
-(@xref{Format of Keymaps}.) The string should describe the purpose of
-the menu. The easiest way to construct a keymap with a prompt string is
-to specify the string as an argument when you call @code{make-keymap} or
-@code{make-sparse-keymap} (@pxref{Creating Keymaps}).
-
-The order of items in the menu is the same as the order of bindings in
-the keymap. Since @code{define-key} puts new bindings at the front, you
-should define the menu items starting at the bottom of the menu and
-moving to the top, if you care about the order. When you add an item to
-an existing menu, you can specify its position in the menu using
-@code{define-key-after} (@pxref{Modifying Menus}).
-
-The individual bindings in the menu keymap should have item
-strings; these strings become the items displayed in the menu. A
-binding with an item string looks like this:
-
-@example
-(@var{string} . @var{real-binding})
-@end example
-
-The item string for a binding should be short---one or two words. It
-should describe the action of the command it corresponds to.
-
-You can also supply a second string, called the help string, as follows:
-
-@example
-(@var{string} @var{help-string} . @var{real-binding})
-@end example
-
-Currently Emacs does not actually use @var{help-string}; it knows only
-how to ignore @var{help-string} in order to extract @var{real-binding}.
-In the future we may use @var{help-string} as extended documentation for
-the menu item, available on request.
-
-As far as @code{define-key} is concerned, @var{string} and
-@var{help-string} are part of the event's binding. However,
-@code{lookup-key} returns just @var{real-binding}, and only
-@var{real-binding} is used for executing the key.
-
-If @var{real-binding} is @code{nil}, then @var{string} appears in the
-menu but cannot be selected.
-
-If @var{real-binding} is a symbol and has a non-@code{nil}
-@code{menu-enable} property, that property is an expression that
-controls whether the menu item is enabled. Every time the keymap is
-used to display a menu, Emacs evaluates the expression, and it enables
-the menu item only if the expression's value is non-@code{nil}. When a
-menu item is disabled, it is displayed in a ``fuzzy'' fashion, and
-cannot be selected with the mouse.
-
-The menu bar does not recalculate which items are enabled every time you
-look at a menu. This is because the X toolkit requires the whole tree
-of menus in advance. To force recalculation of the menu bar, call
-@code{force-mode-line-update} (@pxref{Mode Line Format}).
-
-You've probably noticed that menu items show the equivalent keyboard key
-sequence (if any) to invoke the same command. To save time on
-recalculation, menu display caches this information in a sublist in the
-binding, like this:
-
-@c This line is not too long--rms.
-@example
-(@var{string} @r{[}@var{help-string}@r{]} (@var{key-binding-data}) . @var{real-binding})
-@end example
-
-Don't put these sublists in the menu item yourself; menu display
-calculates them automatically. Don't add keyboard equivalents to the
-item strings in a mouse menu, since that is redundant.
-
-Sometimes it is useful to make menu items that use the ``same'' command
-but with different enable conditions. You can do this by defining alias
-commands. Here's an example that makes two aliases for
-@code{toggle-read-only} and gives them different enable conditions:
-
-@example
-(defalias 'make-read-only 'toggle-read-only)
-(put 'make-read-only 'menu-enable '(not buffer-read-only))
-(defalias 'make-writable 'toggle-read-only)
-(put 'make-writable 'menu-enable 'buffer-read-only)
-@end example
-
-When using aliases in menus, often it is useful to display the
-equivalent key bindings for the ``real'' command name, not the aliases
-(which typically don't have any key bindings except for the menu
-itself). To request this, give the alias symbol a non-@code{nil}
-@code{menu-alias} property. Thus,
-
-@example
-(put 'make-read-only 'menu-alias t)
-(put 'make-writable 'menu-alias t)
-@end example
-
-@noindent
-causes menu items for @code{make-read-only} and @code{make-writable} to
-show the keyboard bindings for @code{toggle-read-only}.
-
-@node Mouse Menus
-@subsection Menus and the Mouse
-
-The way to make a menu keymap produce a menu is to make it the
-definition of a prefix key.
-
-If the prefix key ends with a mouse event, Emacs handles the menu keymap
-by popping up a visible menu, so that the user can select a choice with
-the mouse. When the user clicks on a menu item, the event generated is
-whatever character or symbol has the binding that brought about that
-menu item. (A menu item may generate a series of events if the menu has
-multiple levels or comes from the menu bar.)
-
-It's often best to use a button-down event to trigger the menu. Then
-the user can select a menu item by releasing the button.
-
-A single keymap can appear as multiple menu panes, if you explicitly
-arrange for this. The way to do this is to make a keymap for each pane,
-then create a binding for each of those maps in the main keymap of the
-menu. Give each of these bindings an item string that starts with
-@samp{@@}. The rest of the item string becomes the name of the pane.
-See the file @file{lisp/mouse.el} for an example of this. Any ordinary
-bindings with @samp{@@}-less item strings are grouped into one pane,
-which appears along with the other panes explicitly created for the
-submaps.
-
-X toolkit menus don't have panes; instead, they can have submenus.
-Every nested keymap becomes a submenu, whether the item string starts
-with @samp{@@} or not. In a toolkit version of Emacs, the only thing
-special about @samp{@@} at the beginning of an item string is that the
-@samp{@@} doesn't appear in the menu item.
-
-You can also get multiple panes from separate keymaps. The full
-definition of a prefix key always comes from merging the definitions
-supplied by the various active keymaps (minor mode, local, and
-global). When more than one of these keymaps is a menu, each of them
-makes a separate pane or panes. @xref{Active Keymaps}.
-
-In toolkit versions of Emacs, menus don't have panes, so submenus are
-used to represent the separate keymaps. Each keymap's contribution
-becomes one submenu.
-
-A Lisp program can explicitly pop up a menu and receive the user's
-choice. You can use keymaps for this also. @xref{Pop-Up Menus}.
-
-@node Keyboard Menus
-@subsection Menus and the Keyboard
-
-When a prefix key ending with a keyboard event (a character or function
-key) has a definition that is a menu keymap, the user can use the
-keyboard to choose a menu item.
-
-Emacs displays the menu alternatives (the item strings of the bindings)
-in the echo area. If they don't all fit at once, the user can type
-@key{SPC} to see the next line of alternatives. Successive uses of
-@key{SPC} eventually get to the end of the menu and then cycle around to
-the beginning. (The variable @code{menu-prompt-more-char} specifies
-which character is used for this; @key{SPC} is the default.)
-
-When the user has found the desired alternative from the menu, he or she
-should type the corresponding character---the one whose binding is that
-alternative.
-
-@ignore
-In a menu intended for keyboard use, each menu item must clearly
-indicate what character to type. The best convention to use is to make
-the character the first letter of the item string---that is something
-users will understand without being told. We plan to change this; by
-the time you read this manual, keyboard menus may explicitly name the
-key for each alternative.
-@end ignore
-
-This way of using menus in an Emacs-like editor was inspired by the
-Hierarkey system.
-
-@defvar menu-prompt-more-char
-This variable specifies the character to use to ask to see
-the next line of a menu. Its initial value is 32, the code
-for @key{SPC}.
-@end defvar
-
-@node Menu Example
-@subsection Menu Example
-
- Here is a simple example of how to set up a menu for mouse use.
-
-@example
-(defvar my-menu-map
- (make-sparse-keymap "Key Commands <==> Functions"))
-(fset 'help-for-keys my-menu-map)
-
-(define-key my-menu-map [bindings]
- '("List all keystroke commands" . describe-bindings))
-(define-key my-menu-map [key]
- '("Describe key briefly" . describe-key-briefly))
-(define-key my-menu-map [key-verbose]
- '("Describe key verbose" . describe-key))
-(define-key my-menu-map [function]
- '("Describe Lisp function" . describe-function))
-(define-key my-menu-map [where-is]
- '("Where is this command" . where-is))
-
-(define-key global-map [C-S-down-mouse-1] 'help-for-keys)
-@end example
-
- The symbols used in the key sequences bound in the menu are fictitious
-``function keys''; they don't appear on the keyboard, but that doesn't
-stop you from using them in the menu. Their names were chosen to be
-mnemonic, because they show up in the output of @code{where-is} and
-@code{apropos} to identify the corresponding menu items.
-
- However, if you want the menu to be usable from the keyboard as well,
-you must bind real @sc{ASCII} characters as well as fictitious function
-keys.
-
-@node Menu Bar
-@subsection The Menu Bar
-@cindex menu bar
-
- Most window systems allow each frame to have a @dfn{menu bar}---a
-permanently displayed menu stretching horizontally across the top of the
-frame. The items of the menu bar are the subcommands of the fake
-``function key'' @code{menu-bar}, as defined by all the active keymaps.
-
- To add an item to the menu bar, invent a fake ``function key'' of your
-own (let's call it @var{key}), and make a binding for the key sequence
-@code{[menu-bar @var{key}]}. Most often, the binding is a menu keymap,
-so that pressing a button on the menu bar item leads to another menu.
-
- When more than one active keymap defines the same fake function key
-for the menu bar, the item appears just once. If the user clicks on
-that menu bar item, it brings up a single, combined submenu containing
-all the subcommands of that item---the global subcommands, the local
-subcommands, and the minor mode subcommands, all together.
-
- The variable @code{overriding-local-map} is normally ignored when
-determining the menu bar contents. That is, the menu bar is computed
-from the keymaps that would be active if @code{overriding-local-map}
-were @code{nil}. @xref{Active Keymaps}.
-
- In order for a frame to display a menu bar, its @code{menu-bar-lines}
-parameter must be greater than zero. Emacs uses just one line for the
-menu bar itself; if you specify more than one line, the other lines
-serve to separate the menu bar from the windows in the frame. We
-recommend 1 or 2 as the value of @code{menu-bar-lines}. @xref{X Frame
-Parameters}.
-
- Here's an example of setting up a menu bar item:
-
-@example
-@group
-(modify-frame-parameters (selected-frame)
- '((menu-bar-lines . 2)))
-@end group
-
-@group
-;; @r{Make a menu keymap (with a prompt string)}
-;; @r{and make it the menu bar item's definition.}
-(define-key global-map [menu-bar words]
- (cons "Words" (make-sparse-keymap "Words")))
-@end group
-
-@group
-;; @r{Define specific subcommands in the item's menu.}
-(define-key global-map
- [menu-bar words forward]
- '("Forward word" . forward-word))
-@end group
-@group
-(define-key global-map
- [menu-bar words backward]
- '("Backward word" . backward-word))
-@end group
-@end example
-
- A local keymap can cancel a menu bar item made by the global keymap by
-rebinding the same fake function key with @code{undefined} as the
-binding. For example, this is how Dired suppresses the @samp{Edit} menu
-bar item:
-
-@example
-(define-key dired-mode-map [menu-bar edit] 'undefined)
-@end example
-
-@noindent
-@code{edit} is the fake function key used by the global map for the
-@samp{Edit} menu bar item. The main reason to suppress a global
-menu bar item is to regain space for mode-specific items.
-
-@defvar menu-bar-final-items
-Normally the menu bar shows global items followed by items defined by the
-local maps.
-
-This variable holds a list of fake function keys for items to display at
-the end of the menu bar rather than in normal sequence. The default
-value is @code{(help)}; thus, the @samp{Help} menu item normally appears
-at the end of the menu bar, following local menu items.
-@end defvar
-
-@defvar menu-bar-update-hook
-This normal hook is run whenever the user clicks on the menu bar, before
-displaying a submenu. You can use it to update submenus whose contents
-should vary.
-@end defvar
-
-@node Modifying Menus
-@subsection Modifying Menus
-
- When you insert a new item in an existing menu, you probably want to
-put it in a particular place among the menu's existing items. If you
-use @code{define-key} to add the item, it normally goes at the front of
-the menu. To put it elsewhere, use @code{define-key-after}:
-
-@defun define-key-after map key binding after
-Define a binding in @var{map} for @var{key}, with value @var{binding},
-just like @code{define-key}, but position the binding in @var{map} after
-the binding for the event @var{after}. The argument @var{key} should
-be of length one---a vector or string with just one element.
-
-For example,
-
-@example
-(define-key-after my-menu [drink]
- '("Drink" . drink-command) 'eat)
-@end example
-
-@noindent
-makes a binding for the fake function key @key{drink} and puts it
-right after the binding for @key{eat}.
-
-Here is how to insert an item called @samp{Work} in the @samp{Signals}
-menu of Shell mode, after the item @code{break}:
-
-@example
-(define-key-after
- (lookup-key shell-mode-map [menu-bar signals])
- [work] '("Work" . work-command) 'break)
-@end example
-
-Note that @var{key} is a sequence containing just one event type, but
-@var{after} is just an event type (not a sequence).
-@end defun
diff --git a/lispref/lists.texi b/lispref/lists.texi
deleted file mode 100644
index da9d57319ed..00000000000
--- a/lispref/lists.texi
+++ /dev/null
@@ -1,1416 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/lists
-@node Lists, Sequences Arrays Vectors, Strings and Characters, Top
-@chapter Lists
-@cindex list
-@cindex element (of list)
-
- A @dfn{list} represents a sequence of zero or more elements (which may
-be any Lisp objects). The important difference between lists and
-vectors is that two or more lists can share part of their structure; in
-addition, you can insert or delete elements in a list without copying
-the whole list.
-
-@menu
-* Cons Cells:: How lists are made out of cons cells.
-* Lists as Boxes:: Graphical notation to explain lists.
-* List-related Predicates:: Is this object a list? Comparing two lists.
-* List Elements:: Extracting the pieces of a list.
-* Building Lists:: Creating list structure.
-* Modifying Lists:: Storing new pieces into an existing list.
-* Sets And Lists:: A list can represent a finite mathematical set.
-* Association Lists:: A list can represent a finite relation or mapping.
-@end menu
-
-@node Cons Cells
-@section Lists and Cons Cells
-@cindex lists and cons cells
-@cindex @code{nil} and lists
-
- Lists in Lisp are not a primitive data type; they are built up from
-@dfn{cons cells}. A cons cell is a data object that represents an
-ordered pair. It records two Lisp objects, one labeled as the @sc{car},
-and the other labeled as the @sc{cdr}. These names are traditional; see
-@ref{Cons Cell Type}. @sc{cdr} is pronounced ``could-er.''
-
- A list is a series of cons cells chained together, one cons cell per
-element of the list. By convention, the @sc{car}s of the cons cells are
-the elements of the list, and the @sc{cdr}s are used to chain the list:
-the @sc{cdr} of each cons cell is the following cons cell. The @sc{cdr}
-of the last cons cell is @code{nil}. This asymmetry between the
-@sc{car} and the @sc{cdr} is entirely a matter of convention; at the
-level of cons cells, the @sc{car} and @sc{cdr} slots have the same
-characteristics.
-
-@cindex list structure
- Because most cons cells are used as part of lists, the phrase
-@dfn{list structure} has come to mean any structure made out of cons
-cells.
-
- The symbol @code{nil} is considered a list as well as a symbol; it is
-the list with no elements. For convenience, the symbol @code{nil} is
-considered to have @code{nil} as its @sc{cdr} (and also as its
-@sc{car}).
-
- The @sc{cdr} of any nonempty list @var{l} is a list containing all the
-elements of @var{l} except the first.
-
-@node Lists as Boxes
-@comment node-name, next, previous, up
-@section Lists as Linked Pairs of Boxes
-@cindex box representation for lists
-@cindex lists represented as boxes
-@cindex cons cell as box
-
- A cons cell can be illustrated as a pair of boxes. The first box
-represents the @sc{car} and the second box represents the @sc{cdr}.
-Here is an illustration of the two-element list, @code{(tulip lily)},
-made from two cons cells:
-
-@example
-@group
- --------------- ---------------
-| car | cdr | | car | cdr |
-| tulip | o---------->| lily | nil |
-| | | | | |
- --------------- ---------------
-@end group
-@end example
-
- Each pair of boxes represents a cons cell. Each box ``refers to'',
-``points to'' or ``contains'' a Lisp object. (These terms are
-synonymous.) The first box, which is the @sc{car} of the first cons
-cell, contains the symbol @code{tulip}. The arrow from the @sc{cdr} of
-the first cons cell to the second cons cell indicates that the @sc{cdr}
-of the first cons cell points to the second cons cell.
-
- The same list can be illustrated in a different sort of box notation
-like this:
-
-@example
-@group
- ___ ___ ___ ___
- |___|___|--> |___|___|--> nil
- | |
- | |
- --> tulip --> lily
-@end group
-@end example
-
- Here is a more complex illustration, showing the three-element list,
-@code{((pine needles) oak maple)}, the first element of which is a
-two-element list:
-
-@example
-@group
- ___ ___ ___ ___ ___ ___
- |___|___|--> |___|___|--> |___|___|--> nil
- | | |
- | | |
- | --> oak --> maple
- |
- | ___ ___ ___ ___
- --> |___|___|--> |___|___|--> nil
- | |
- | |
- --> pine --> needles
-@end group
-@end example
-
- The same list represented in the first box notation looks like this:
-
-@example
-@group
- -------------- -------------- --------------
-| car | cdr | | car | cdr | | car | cdr |
-| o | o------->| oak | o------->| maple | nil |
-| | | | | | | | | |
- -- | --------- -------------- --------------
- |
- |
- | -------------- ----------------
- | | car | cdr | | car | cdr |
- ------>| pine | o------->| needles | nil |
- | | | | | |
- -------------- ----------------
-@end group
-@end example
-
- @xref{Cons Cell Type}, for the read and print syntax of cons cells and
-lists, and for more ``box and arrow'' illustrations of lists.
-
-@node List-related Predicates
-@section Predicates on Lists
-
- The following predicates test whether a Lisp object is an atom, is a
-cons cell or is a list, or whether it is the distinguished object
-@code{nil}. (Many of these predicates can be defined in terms of the
-others, but they are used so often that it is worth having all of them.)
-
-@defun consp object
-This function returns @code{t} if @var{object} is a cons cell, @code{nil}
-otherwise. @code{nil} is not a cons cell, although it @emph{is} a list.
-@end defun
-
-@defun atom object
-@cindex atoms
-This function returns @code{t} if @var{object} is an atom, @code{nil}
-otherwise. All objects except cons cells are atoms. The symbol
-@code{nil} is an atom and is also a list; it is the only Lisp object
-that is both.
-
-@example
-(atom @var{object}) @equiv{} (not (consp @var{object}))
-@end example
-@end defun
-
-@defun listp object
-This function returns @code{t} if @var{object} is a cons cell or
-@code{nil}. Otherwise, it returns @code{nil}.
-
-@example
-@group
-(listp '(1))
- @result{} t
-@end group
-@group
-(listp '())
- @result{} t
-@end group
-@end example
-@end defun
-
-@defun nlistp object
-This function is the opposite of @code{listp}: it returns @code{t} if
-@var{object} is not a list. Otherwise, it returns @code{nil}.
-
-@example
-(listp @var{object}) @equiv{} (not (nlistp @var{object}))
-@end example
-@end defun
-
-@defun null object
-This function returns @code{t} if @var{object} is @code{nil}, and
-returns @code{nil} otherwise. This function is identical to @code{not},
-but as a matter of clarity we use @code{null} when @var{object} is
-considered a list and @code{not} when it is considered a truth value
-(see @code{not} in @ref{Combining Conditions}).
-
-@example
-@group
-(null '(1))
- @result{} nil
-@end group
-@group
-(null '())
- @result{} t
-@end group
-@end example
-@end defun
-
-@need 2000
-
-@node List Elements
-@section Accessing Elements of Lists
-@cindex list elements
-
-@defun car cons-cell
-This function returns the value pointed to by the first pointer of the
-cons cell @var{cons-cell}. Expressed another way, this function
-returns the @sc{car} of @var{cons-cell}.
-
-As a special case, if @var{cons-cell} is @code{nil}, then @code{car}
-is defined to return @code{nil}; therefore, any list is a valid argument
-for @code{car}. An error is signaled if the argument is not a cons cell
-or @code{nil}.
-
-@example
-@group
-(car '(a b c))
- @result{} a
-@end group
-@group
-(car '())
- @result{} nil
-@end group
-@end example
-@end defun
-
-@defun cdr cons-cell
-This function returns the value pointed to by the second pointer of
-the cons cell @var{cons-cell}. Expressed another way, this function
-returns the @sc{cdr} of @var{cons-cell}.
-
-As a special case, if @var{cons-cell} is @code{nil}, then @code{cdr}
-is defined to return @code{nil}; therefore, any list is a valid argument
-for @code{cdr}. An error is signaled if the argument is not a cons cell
-or @code{nil}.
-
-@example
-@group
-(cdr '(a b c))
- @result{} (b c)
-@end group
-@group
-(cdr '())
- @result{} nil
-@end group
-@end example
-@end defun
-
-@defun car-safe object
-This function lets you take the @sc{car} of a cons cell while avoiding
-errors for other data types. It returns the @sc{car} of @var{object} if
-@var{object} is a cons cell, @code{nil} otherwise. This is in contrast
-to @code{car}, which signals an error if @var{object} is not a list.
-
-@example
-@group
-(car-safe @var{object})
-@equiv{}
-(let ((x @var{object}))
- (if (consp x)
- (car x)
- nil))
-@end group
-@end example
-@end defun
-
-@defun cdr-safe object
-This function lets you take the @sc{cdr} of a cons cell while
-avoiding errors for other data types. It returns the @sc{cdr} of
-@var{object} if @var{object} is a cons cell, @code{nil} otherwise.
-This is in contrast to @code{cdr}, which signals an error if
-@var{object} is not a list.
-
-@example
-@group
-(cdr-safe @var{object})
-@equiv{}
-(let ((x @var{object}))
- (if (consp x)
- (cdr x)
- nil))
-@end group
-@end example
-@end defun
-
-@defun nth n list
-This function returns the @var{n}th element of @var{list}. Elements
-are numbered starting with zero, so the @sc{car} of @var{list} is
-element number zero. If the length of @var{list} is @var{n} or less,
-the value is @code{nil}.
-
-If @var{n} is negative, @code{nth} returns the first element of
-@var{list}.
-
-@example
-@group
-(nth 2 '(1 2 3 4))
- @result{} 3
-@end group
-@group
-(nth 10 '(1 2 3 4))
- @result{} nil
-@end group
-@group
-(nth -3 '(1 2 3 4))
- @result{} 1
-
-(nth n x) @equiv{} (car (nthcdr n x))
-@end group
-@end example
-@end defun
-
-@defun nthcdr n list
-This function returns the @var{n}th @sc{cdr} of @var{list}. In other
-words, it removes the first @var{n} links of @var{list} and returns
-what follows.
-
-If @var{n} is zero or negative, @code{nthcdr} returns all of
-@var{list}. If the length of @var{list} is @var{n} or less,
-@code{nthcdr} returns @code{nil}.
-
-@example
-@group
-(nthcdr 1 '(1 2 3 4))
- @result{} (2 3 4)
-@end group
-@group
-(nthcdr 10 '(1 2 3 4))
- @result{} nil
-@end group
-@group
-(nthcdr -3 '(1 2 3 4))
- @result{} (1 2 3 4)
-@end group
-@end example
-@end defun
-
-@node Building Lists
-@comment node-name, next, previous, up
-@section Building Cons Cells and Lists
-@cindex cons cells
-@cindex building lists
-
- Many functions build lists, as lists reside at the very heart of Lisp.
-@code{cons} is the fundamental list-building function; however, it is
-interesting to note that @code{list} is used more times in the source
-code for Emacs than @code{cons}.
-
-@defun cons object1 object2
-This function is the fundamental function used to build new list
-structure. It creates a new cons cell, making @var{object1} the
-@sc{car}, and @var{object2} the @sc{cdr}. It then returns the new cons
-cell. The arguments @var{object1} and @var{object2} may be any Lisp
-objects, but most often @var{object2} is a list.
-
-@example
-@group
-(cons 1 '(2))
- @result{} (1 2)
-@end group
-@group
-(cons 1 '())
- @result{} (1)
-@end group
-@group
-(cons 1 2)
- @result{} (1 . 2)
-@end group
-@end example
-
-@cindex consing
-@code{cons} is often used to add a single element to the front of a
-list. This is called @dfn{consing the element onto the list}. For
-example:
-
-@example
-(setq list (cons newelt list))
-@end example
-
-Note that there is no conflict between the variable named @code{list}
-used in this example and the function named @code{list} described below;
-any symbol can serve both purposes.
-@end defun
-
-@defun list &rest objects
-This function creates a list with @var{objects} as its elements. The
-resulting list is always @code{nil}-terminated. If no @var{objects}
-are given, the empty list is returned.
-
-@example
-@group
-(list 1 2 3 4 5)
- @result{} (1 2 3 4 5)
-@end group
-@group
-(list 1 2 '(3 4 5) 'foo)
- @result{} (1 2 (3 4 5) foo)
-@end group
-@group
-(list)
- @result{} nil
-@end group
-@end example
-@end defun
-
-@defun make-list length object
-This function creates a list of length @var{length}, in which all the
-elements have the identical value @var{object}. Compare
-@code{make-list} with @code{make-string} (@pxref{Creating Strings}).
-
-@example
-@group
-(make-list 3 'pigs)
- @result{} (pigs pigs pigs)
-@end group
-@group
-(make-list 0 'pigs)
- @result{} nil
-@end group
-@end example
-@end defun
-
-@defun append &rest sequences
-@cindex copying lists
-This function returns a list containing all the elements of
-@var{sequences}. The @var{sequences} may be lists, vectors, or strings,
-but the last one should be a list. All arguments except the last one
-are copied, so none of them are altered.
-
-More generally, the final argument to @code{append} may be any Lisp
-object. The final argument is not copied or converted; it becomes the
-@sc{cdr} of the last cons cell in the new list. If the final argument
-is itself a list, then its elements become in effect elements of the
-result list. If the final element is not a list, the result is a
-``dotted list'' since its final @sc{cdr} is not @code{nil} as required
-in a true list.
-
-See @code{nconc} in @ref{Rearrangement}, for a way to join lists with no
-copying.
-
-Here is an example of using @code{append}:
-
-@example
-@group
-(setq trees '(pine oak))
- @result{} (pine oak)
-(setq more-trees (append '(maple birch) trees))
- @result{} (maple birch pine oak)
-@end group
-
-@group
-trees
- @result{} (pine oak)
-more-trees
- @result{} (maple birch pine oak)
-@end group
-@group
-(eq trees (cdr (cdr more-trees)))
- @result{} t
-@end group
-@end example
-
-You can see how @code{append} works by looking at a box diagram. The
-variable @code{trees} is set to the list @code{(pine oak)} and then the
-variable @code{more-trees} is set to the list @code{(maple birch pine
-oak)}. However, the variable @code{trees} continues to refer to the
-original list:
-
-@smallexample
-@group
-more-trees trees
-| |
-| ___ ___ ___ ___ -> ___ ___ ___ ___
- --> |___|___|--> |___|___|--> |___|___|--> |___|___|--> nil
- | | | |
- | | | |
- --> maple -->birch --> pine --> oak
-@end group
-@end smallexample
-
-An empty sequence contributes nothing to the value returned by
-@code{append}. As a consequence of this, a final @code{nil} argument
-forces a copy of the previous argument.
-
-@example
-@group
-trees
- @result{} (pine oak)
-@end group
-@group
-(setq wood (append trees ()))
- @result{} (pine oak)
-@end group
-@group
-wood
- @result{} (pine oak)
-@end group
-@group
-(eq wood trees)
- @result{} nil
-@end group
-@end example
-
-@noindent
-This once was the usual way to copy a list, before the function
-@code{copy-sequence} was invented. @xref{Sequences Arrays Vectors}.
-
-With the help of @code{apply}, we can append all the lists in a list of
-lists:
-
-@example
-@group
-(apply 'append '((a b c) nil (x y z) nil))
- @result{} (a b c x y z)
-@end group
-@end example
-
-If no @var{sequences} are given, @code{nil} is returned:
-
-@example
-@group
-(append)
- @result{} nil
-@end group
-@end example
-
-Here are some examples where the final argument is not a list:
-
-@example
-(append '(x y) 'z)
- @result{} (x y . z)
-(append '(x y) [z])
- @result{} (x y . [z])
-@end example
-
-@noindent
-The second example shows that when the final argument is a sequence but
-not a list, the sequence's elements do not become elements of the
-resulting list. Instead, the sequence becomes the final @sc{cdr}, like
-any other non-list final argument.
-
-The @code{append} function also allows integers as arguments. It
-converts them to strings of digits, making up the decimal print
-representation of the integer, and then uses the strings instead of the
-original integers. @strong{Don't use this feature; we plan to eliminate
-it. If you already use this feature, change your programs now!} The
-proper way to convert an integer to a decimal number in this way is with
-@code{format} (@pxref{Formatting Strings}) or @code{number-to-string}
-(@pxref{String Conversion}).
-@end defun
-
-@defun reverse list
-This function creates a new list whose elements are the elements of
-@var{list}, but in reverse order. The original argument @var{list} is
-@emph{not} altered.
-
-@example
-@group
-(setq x '(1 2 3 4))
- @result{} (1 2 3 4)
-@end group
-@group
-(reverse x)
- @result{} (4 3 2 1)
-x
- @result{} (1 2 3 4)
-@end group
-@end example
-@end defun
-
-@node Modifying Lists
-@section Modifying Existing List Structure
-
- You can modify the @sc{car} and @sc{cdr} contents of a cons cell with the
-primitives @code{setcar} and @code{setcdr}.
-
-@cindex CL note---@code{rplaca} vrs @code{setcar}
-@quotation
-@findex rplaca
-@findex rplacd
-@b{Common Lisp note:} Common Lisp uses functions @code{rplaca} and
-@code{rplacd} to alter list structure; they change structure the same
-way as @code{setcar} and @code{setcdr}, but the Common Lisp functions
-return the cons cell while @code{setcar} and @code{setcdr} return the
-new @sc{car} or @sc{cdr}.
-@end quotation
-
-@menu
-* Setcar:: Replacing an element in a list.
-* Setcdr:: Replacing part of the list backbone.
- This can be used to remove or add elements.
-* Rearrangement:: Reordering the elements in a list; combining lists.
-@end menu
-
-@node Setcar
-@subsection Altering List Elements with @code{setcar}
-
- Changing the @sc{car} of a cons cell is done with @code{setcar}. When
-used on a list, @code{setcar} replaces one element of a list with a
-different element.
-
-@defun setcar cons object
-This function stores @var{object} as the new @sc{car} of @var{cons},
-replacing its previous @sc{car}. It returns the value @var{object}.
-For example:
-
-@example
-@group
-(setq x '(1 2))
- @result{} (1 2)
-@end group
-@group
-(setcar x 4)
- @result{} 4
-@end group
-@group
-x
- @result{} (4 2)
-@end group
-@end example
-@end defun
-
- When a cons cell is part of the shared structure of several lists,
-storing a new @sc{car} into the cons changes one element of each of
-these lists. Here is an example:
-
-@example
-@group
-;; @r{Create two lists that are partly shared.}
-(setq x1 '(a b c))
- @result{} (a b c)
-(setq x2 (cons 'z (cdr x1)))
- @result{} (z b c)
-@end group
-
-@group
-;; @r{Replace the @sc{car} of a shared link.}
-(setcar (cdr x1) 'foo)
- @result{} foo
-x1 ; @r{Both lists are changed.}
- @result{} (a foo c)
-x2
- @result{} (z foo c)
-@end group
-
-@group
-;; @r{Replace the @sc{car} of a link that is not shared.}
-(setcar x1 'baz)
- @result{} baz
-x1 ; @r{Only one list is changed.}
- @result{} (baz foo c)
-x2
- @result{} (z foo c)
-@end group
-@end example
-
- Here is a graphical depiction of the shared structure of the two lists
-in the variables @code{x1} and @code{x2}, showing why replacing @code{b}
-changes them both:
-
-@example
-@group
- ___ ___ ___ ___ ___ ___
-x1---> |___|___|----> |___|___|--> |___|___|--> nil
- | --> | |
- | | | |
- --> a | --> b --> c
- |
- ___ ___ |
-x2--> |___|___|--
- |
- |
- --> z
-@end group
-@end example
-
- Here is an alternative form of box diagram, showing the same relationship:
-
-@example
-@group
-x1:
- -------------- -------------- --------------
-| car | cdr | | car | cdr | | car | cdr |
-| a | o------->| b | o------->| c | nil |
-| | | -->| | | | | |
- -------------- | -------------- --------------
- |
-x2: |
- -------------- |
-| car | cdr | |
-| z | o----
-| | |
- --------------
-@end group
-@end example
-
-@node Setcdr
-@subsection Altering the CDR of a List
-
- The lowest-level primitive for modifying a @sc{cdr} is @code{setcdr}:
-
-@defun setcdr cons object
-This function stores @var{object} as the new @sc{cdr} of @var{cons},
-replacing its previous @sc{cdr}. It returns the value @var{object}.
-@end defun
-
- Here is an example of replacing the @sc{cdr} of a list with a
-different list. All but the first element of the list are removed in
-favor of a different sequence of elements. The first element is
-unchanged, because it resides in the @sc{car} of the list, and is not
-reached via the @sc{cdr}.
-
-@example
-@group
-(setq x '(1 2 3))
- @result{} (1 2 3)
-@end group
-@group
-(setcdr x '(4))
- @result{} (4)
-@end group
-@group
-x
- @result{} (1 4)
-@end group
-@end example
-
- You can delete elements from the middle of a list by altering the
-@sc{cdr}s of the cons cells in the list. For example, here we delete
-the second element, @code{b}, from the list @code{(a b c)}, by changing
-the @sc{cdr} of the first cell:
-
-@example
-@group
-(setq x1 '(a b c))
- @result{} (a b c)
-(setcdr x1 (cdr (cdr x1)))
- @result{} (c)
-x1
- @result{} (a c)
-@end group
-@end example
-
-@need 4000
- Here is the result in box notation:
-
-@example
-@group
- --------------------
- | |
- -------------- | -------------- | --------------
-| car | cdr | | | car | cdr | -->| car | cdr |
-| a | o----- | b | o-------->| c | nil |
-| | | | | | | | |
- -------------- -------------- --------------
-@end group
-@end example
-
-@noindent
-The second cons cell, which previously held the element @code{b}, still
-exists and its @sc{car} is still @code{b}, but it no longer forms part
-of this list.
-
- It is equally easy to insert a new element by changing @sc{cdr}s:
-
-@example
-@group
-(setq x1 '(a b c))
- @result{} (a b c)
-(setcdr x1 (cons 'd (cdr x1)))
- @result{} (d b c)
-x1
- @result{} (a d b c)
-@end group
-@end example
-
- Here is this result in box notation:
-
-@smallexample
-@group
- -------------- ------------- -------------
-| car | cdr | | car | cdr | | car | cdr |
-| a | o | -->| b | o------->| c | nil |
-| | | | | | | | | | |
- --------- | -- | ------------- -------------
- | |
- ----- --------
- | |
- | --------------- |
- | | car | cdr | |
- -->| d | o------
- | | |
- ---------------
-@end group
-@end smallexample
-
-@node Rearrangement
-@subsection Functions that Rearrange Lists
-@cindex rearrangement of lists
-@cindex modification of lists
-
- Here are some functions that rearrange lists ``destructively'' by
-modifying the @sc{cdr}s of their component cons cells. We call these
-functions ``destructive'' because they chew up the original lists passed
-to them as arguments, to produce a new list that is the returned value.
-
-@ifinfo
- See @code{delq}, in @ref{Sets And Lists}, for another function
-that modifies cons cells.
-@end ifinfo
-@iftex
- The function @code{delq} in the following section is another example
-of destructive list manipulation.
-@end iftex
-
-@defun nconc &rest lists
-@cindex concatenating lists
-@cindex joining lists
-This function returns a list containing all the elements of @var{lists}.
-Unlike @code{append} (@pxref{Building Lists}), the @var{lists} are
-@emph{not} copied. Instead, the last @sc{cdr} of each of the
-@var{lists} is changed to refer to the following list. The last of the
-@var{lists} is not altered. For example:
-
-@example
-@group
-(setq x '(1 2 3))
- @result{} (1 2 3)
-@end group
-@group
-(nconc x '(4 5))
- @result{} (1 2 3 4 5)
-@end group
-@group
-x
- @result{} (1 2 3 4 5)
-@end group
-@end example
-
- Since the last argument of @code{nconc} is not itself modified, it is
-reasonable to use a constant list, such as @code{'(4 5)}, as in the
-above example. For the same reason, the last argument need not be a
-list:
-
-@example
-@group
-(setq x '(1 2 3))
- @result{} (1 2 3)
-@end group
-@group
-(nconc x 'z)
- @result{} (1 2 3 . z)
-@end group
-@group
-x
- @result{} (1 2 3 . z)
-@end group
-@end example
-
-A common pitfall is to use a quoted constant list as a non-last
-argument to @code{nconc}. If you do this, your program will change
-each time you run it! Here is what happens:
-
-@smallexample
-@group
-(defun add-foo (x) ; @r{We want this function to add}
- (nconc '(foo) x)) ; @r{@code{foo} to the front of its arg.}
-@end group
-
-@group
-(symbol-function 'add-foo)
- @result{} (lambda (x) (nconc (quote (foo)) x))
-@end group
-
-@group
-(setq xx (add-foo '(1 2))) ; @r{It seems to work.}
- @result{} (foo 1 2)
-@end group
-@group
-(setq xy (add-foo '(3 4))) ; @r{What happened?}
- @result{} (foo 1 2 3 4)
-@end group
-@group
-(eq xx xy)
- @result{} t
-@end group
-
-@group
-(symbol-function 'add-foo)
- @result{} (lambda (x) (nconc (quote (foo 1 2 3 4) x)))
-@end group
-@end smallexample
-@end defun
-
-@defun nreverse list
-@cindex reversing a list
- This function reverses the order of the elements of @var{list}.
-Unlike @code{reverse}, @code{nreverse} alters its argument by reversing
-the @sc{cdr}s in the cons cells forming the list. The cons cell that
-used to be the last one in @var{list} becomes the first cell of the
-value.
-
- For example:
-
-@example
-@group
-(setq x '(1 2 3 4))
- @result{} (1 2 3 4)
-@end group
-@group
-x
- @result{} (1 2 3 4)
-(nreverse x)
- @result{} (4 3 2 1)
-@end group
-@group
-;; @r{The cell that was first is now last.}
-x
- @result{} (1)
-@end group
-@end example
-
- To avoid confusion, we usually store the result of @code{nreverse}
-back in the same variable which held the original list:
-
-@example
-(setq x (nreverse x))
-@end example
-
- Here is the @code{nreverse} of our favorite example, @code{(a b c)},
-presented graphically:
-
-@smallexample
-@group
-@r{Original list head:} @r{Reversed list:}
- ------------- ------------- ------------
-| car | cdr | | car | cdr | | car | cdr |
-| a | nil |<-- | b | o |<-- | c | o |
-| | | | | | | | | | | | |
- ------------- | --------- | - | -------- | -
- | | | |
- ------------- ------------
-@end group
-@end smallexample
-@end defun
-
-@defun sort list predicate
-@cindex stable sort
-@cindex sorting lists
-This function sorts @var{list} stably, though destructively, and
-returns the sorted list. It compares elements using @var{predicate}. A
-stable sort is one in which elements with equal sort keys maintain their
-relative order before and after the sort. Stability is important when
-successive sorts are used to order elements according to different
-criteria.
-
-The argument @var{predicate} must be a function that accepts two
-arguments. It is called with two elements of @var{list}. To get an
-increasing order sort, the @var{predicate} should return @code{t} if the
-first element is ``less than'' the second, or @code{nil} if not.
-
-The destructive aspect of @code{sort} is that it rearranges the cons
-cells forming @var{list} by changing @sc{cdr}s. A nondestructive sort
-function would create new cons cells to store the elements in their
-sorted order. If you wish to make a sorted copy without destroying the
-original, copy it first with @code{copy-sequence} and then sort.
-
-Sorting does not change the @sc{car}s of the cons cells in @var{list};
-the cons cell that originally contained the element @code{a} in
-@var{list} still has @code{a} in its @sc{car} after sorting, but it now
-appears in a different position in the list due to the change of
-@sc{cdr}s. For example:
-
-@example
-@group
-(setq nums '(1 3 2 6 5 4 0))
- @result{} (1 3 2 6 5 4 0)
-@end group
-@group
-(sort nums '<)
- @result{} (0 1 2 3 4 5 6)
-@end group
-@group
-nums
- @result{} (1 2 3 4 5 6)
-@end group
-@end example
-
-@noindent
-Note that the list in @code{nums} no longer contains 0; this is the same
-cons cell that it was before, but it is no longer the first one in the
-list. Don't assume a variable that formerly held the argument now holds
-the entire sorted list! Instead, save the result of @code{sort} and use
-that. Most often we store the result back into the variable that held
-the original list:
-
-@example
-(setq nums (sort nums '<))
-@end example
-
-@xref{Sorting}, for more functions that perform sorting.
-See @code{documentation} in @ref{Accessing Documentation}, for a
-useful example of @code{sort}.
-@end defun
-
-@node Sets And Lists
-@section Using Lists as Sets
-@cindex lists as sets
-@cindex sets
-
- A list can represent an unordered mathematical set---simply consider a
-value an element of a set if it appears in the list, and ignore the
-order of the list. To form the union of two sets, use @code{append} (as
-long as you don't mind having duplicate elements). Other useful
-functions for sets include @code{memq} and @code{delq}, and their
-@code{equal} versions, @code{member} and @code{delete}.
-
-@cindex CL note---lack @code{union}, @code{intersection}
-@quotation
-@b{Common Lisp note:} Common Lisp has functions @code{union} (which
-avoids duplicate elements) and @code{intersection} for set operations,
-but GNU Emacs Lisp does not have them. You can write them in Lisp if
-you wish.
-@end quotation
-
-@defun memq object list
-@cindex membership in a list
-This function tests to see whether @var{object} is a member of
-@var{list}. If it is, @code{memq} returns a list starting with the
-first occurrence of @var{object}. Otherwise, it returns @code{nil}.
-The letter @samp{q} in @code{memq} says that it uses @code{eq} to
-compare @var{object} against the elements of the list. For example:
-
-@example
-@group
-(memq 'b '(a b c b a))
- @result{} (b c b a)
-@end group
-@group
-(memq '(2) '((1) (2))) ; @r{@code{(2)} and @code{(2)} are not @code{eq}.}
- @result{} nil
-@end group
-@end example
-@end defun
-
-@defun delq object list
-@cindex deletion of elements
-This function destructively removes all elements @code{eq} to
-@var{object} from @var{list}. The letter @samp{q} in @code{delq} says
-that it uses @code{eq} to compare @var{object} against the elements of
-the list, like @code{memq}.
-@end defun
-
-When @code{delq} deletes elements from the front of the list, it does so
-simply by advancing down the list and returning a sublist that starts
-after those elements:
-
-@example
-@group
-(delq 'a '(a b c)) @equiv{} (cdr '(a b c))
-@end group
-@end example
-
-When an element to be deleted appears in the middle of the list,
-removing it involves changing the @sc{cdr}s (@pxref{Setcdr}).
-
-@example
-@group
-(setq sample-list '(a b c (4)))
- @result{} (a b c (4))
-@end group
-@group
-(delq 'a sample-list)
- @result{} (b c (4))
-@end group
-@group
-sample-list
- @result{} (a b c (4))
-@end group
-@group
-(delq 'c sample-list)
- @result{} (a b (4))
-@end group
-@group
-sample-list
- @result{} (a b (4))
-@end group
-@end example
-
-Note that @code{(delq 'c sample-list)} modifies @code{sample-list} to
-splice out the third element, but @code{(delq 'a sample-list)} does not
-splice anything---it just returns a shorter list. Don't assume that a
-variable which formerly held the argument @var{list} now has fewer
-elements, or that it still holds the original list! Instead, save the
-result of @code{delq} and use that. Most often we store the result back
-into the variable that held the original list:
-
-@example
-(setq flowers (delq 'rose flowers))
-@end example
-
-In the following example, the @code{(4)} that @code{delq} attempts to match
-and the @code{(4)} in the @code{sample-list} are not @code{eq}:
-
-@example
-@group
-(delq '(4) sample-list)
- @result{} (a c (4))
-@end group
-@end example
-
-The following two functions are like @code{memq} and @code{delq} but use
-@code{equal} rather than @code{eq} to compare elements. They are new in
-Emacs 19.
-
-@defun member object list
-The function @code{member} tests to see whether @var{object} is a member
-of @var{list}, comparing members with @var{object} using @code{equal}.
-If @var{object} is a member, @code{member} returns a list starting with
-its first occurrence in @var{list}. Otherwise, it returns @code{nil}.
-
-Compare this with @code{memq}:
-
-@example
-@group
-(member '(2) '((1) (2))) ; @r{@code{(2)} and @code{(2)} are @code{equal}.}
- @result{} ((2))
-@end group
-@group
-(memq '(2) '((1) (2))) ; @r{@code{(2)} and @code{(2)} are not @code{eq}.}
- @result{} nil
-@end group
-@group
-;; @r{Two strings with the same contents are @code{equal}.}
-(member "foo" '("foo" "bar"))
- @result{} ("foo" "bar")
-@end group
-@end example
-@end defun
-
-@defun delete object list
-This function destructively removes all elements @code{equal} to
-@var{object} from @var{list}. It is to @code{delq} as @code{member} is
-to @code{memq}: it uses @code{equal} to compare elements with
-@var{object}, like @code{member}; when it finds an element that matches,
-it removes the element just as @code{delq} would. For example:
-
-@example
-@group
-(delete '(2) '((2) (1) (2)))
- @result{} ((1))
-@end group
-@end example
-@end defun
-
-@quotation
-@b{Common Lisp note:} The functions @code{member} and @code{delete} in
-GNU Emacs Lisp are derived from Maclisp, not Common Lisp. The Common
-Lisp versions do not use @code{equal} to compare elements.
-@end quotation
-
- See also the function @code{add-to-list}, in @ref{Setting Variables},
-for another way to add an element to a list stored in a variable.
-
-@node Association Lists
-@section Association Lists
-@cindex association list
-@cindex alist
-
- An @dfn{association list}, or @dfn{alist} for short, records a mapping
-from keys to values. It is a list of cons cells called
-@dfn{associations}: the @sc{car} of each cell is the @dfn{key}, and the
-@sc{cdr} is the @dfn{associated value}.@footnote{This usage of ``key''
-is not related to the term ``key sequence''; it means a value used to
-look up an item in a table. In this case, the table is the alist, and
-the alist associations are the items.}
-
- Here is an example of an alist. The key @code{pine} is associated with
-the value @code{cones}; the key @code{oak} is associated with
-@code{acorns}; and the key @code{maple} is associated with @code{seeds}.
-
-@example
-@group
-'((pine . cones)
- (oak . acorns)
- (maple . seeds))
-@end group
-@end example
-
- The associated values in an alist may be any Lisp objects; so may the
-keys. For example, in the following alist, the symbol @code{a} is
-associated with the number @code{1}, and the string @code{"b"} is
-associated with the @emph{list} @code{(2 3)}, which is the @sc{cdr} of
-the alist element:
-
-@example
-((a . 1) ("b" 2 3))
-@end example
-
- Sometimes it is better to design an alist to store the associated
-value in the @sc{car} of the @sc{cdr} of the element. Here is an
-example:
-
-@example
-'((rose red) (lily white) (buttercup yellow))
-@end example
-
-@noindent
-Here we regard @code{red} as the value associated with @code{rose}. One
-advantage of this method is that you can store other related
-information---even a list of other items---in the @sc{cdr} of the
-@sc{cdr}. One disadvantage is that you cannot use @code{rassq} (see
-below) to find the element containing a given value. When neither of
-these considerations is important, the choice is a matter of taste, as
-long as you are consistent about it for any given alist.
-
- Note that the same alist shown above could be regarded as having the
-associated value in the @sc{cdr} of the element; the value associated
-with @code{rose} would be the list @code{(red)}.
-
- Association lists are often used to record information that you might
-otherwise keep on a stack, since new associations may be added easily to
-the front of the list. When searching an association list for an
-association with a given key, the first one found is returned, if there
-is more than one.
-
- In Emacs Lisp, it is @emph{not} an error if an element of an
-association list is not a cons cell. The alist search functions simply
-ignore such elements. Many other versions of Lisp signal errors in such
-cases.
-
- Note that property lists are similar to association lists in several
-respects. A property list behaves like an association list in which
-each key can occur only once. @xref{Property Lists}, for a comparison
-of property lists and association lists.
-
-@defun assoc key alist
-This function returns the first association for @var{key} in
-@var{alist}. It compares @var{key} against the alist elements using
-@code{equal} (@pxref{Equality Predicates}). It returns @code{nil} if no
-association in @var{alist} has a @sc{car} @code{equal} to @var{key}.
-For example:
-
-@smallexample
-(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))
- @result{} ((pine . cones) (oak . acorns) (maple . seeds))
-(assoc 'oak trees)
- @result{} (oak . acorns)
-(cdr (assoc 'oak trees))
- @result{} acorns
-(assoc 'birch trees)
- @result{} nil
-@end smallexample
-
-Here is another example, in which the keys and values are not symbols:
-
-@smallexample
-(setq needles-per-cluster
- '((2 "Austrian Pine" "Red Pine")
- (3 "Pitch Pine")
- (5 "White Pine")))
-
-(cdr (assoc 3 needles-per-cluster))
- @result{} ("Pitch Pine")
-(cdr (assoc 2 needles-per-cluster))
- @result{} ("Austrian Pine" "Red Pine")
-@end smallexample
-@end defun
-
-@defun rassoc value alist
-This function returns the first association with value @var{value} in
-@var{alist}. It returns @code{nil} if no association in @var{alist} has
-a @sc{cdr} @code{equal} to @var{value}.
-
-@code{rassoc} is like @code{assoc} except that it compares the @sc{cdr} of
-each @var{alist} association instead of the @sc{car}. You can think of
-this as ``reverse @code{assoc}'', finding the key for a given value.
-@end defun
-
-@defun assq key alist
-This function is like @code{assoc} in that it returns the first
-association for @var{key} in @var{alist}, but it makes the comparison
-using @code{eq} instead of @code{equal}. @code{assq} returns @code{nil}
-if no association in @var{alist} has a @sc{car} @code{eq} to @var{key}.
-This function is used more often than @code{assoc}, since @code{eq} is
-faster than @code{equal} and most alists use symbols as keys.
-@xref{Equality Predicates}.
-
-@smallexample
-(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))
- @result{} ((pine . cones) (oak . acorns) (maple . seeds))
-(assq 'pine trees)
- @result{} (pine . cones)
-@end smallexample
-
-On the other hand, @code{assq} is not usually useful in alists where the
-keys may not be symbols:
-
-@smallexample
-(setq leaves
- '(("simple leaves" . oak)
- ("compound leaves" . horsechestnut)))
-
-(assq "simple leaves" leaves)
- @result{} nil
-(assoc "simple leaves" leaves)
- @result{} ("simple leaves" . oak)
-@end smallexample
-@end defun
-
-@defun rassq value alist
-This function returns the first association with value @var{value} in
-@var{alist}. It returns @code{nil} if no association in @var{alist} has
-a @sc{cdr} @code{eq} to @var{value}.
-
-@code{rassq} is like @code{assq} except that it compares the @sc{cdr} of
-each @var{alist} association instead of the @sc{car}. You can think of
-this as ``reverse @code{assq}'', finding the key for a given value.
-
-For example:
-
-@smallexample
-(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))
-
-(rassq 'acorns trees)
- @result{} (oak . acorns)
-(rassq 'spores trees)
- @result{} nil
-@end smallexample
-
-Note that @code{rassq} cannot search for a value stored in the @sc{car}
-of the @sc{cdr} of an element:
-
-@smallexample
-(setq colors '((rose red) (lily white) (buttercup yellow)))
-
-(rassq 'white colors)
- @result{} nil
-@end smallexample
-
-In this case, the @sc{cdr} of the association @code{(lily white)} is not
-the symbol @code{white}, but rather the list @code{(white)}. This
-becomes clearer if the association is written in dotted pair notation:
-
-@smallexample
-(lily white) @equiv{} (lily . (white))
-@end smallexample
-@end defun
-
-@defun copy-alist alist
-@cindex copying alists
-This function returns a two-level deep copy of @var{alist}: it creates a
-new copy of each association, so that you can alter the associations of
-the new alist without changing the old one.
-
-@smallexample
-@group
-(setq needles-per-cluster
- '((2 . ("Austrian Pine" "Red Pine"))
- (3 . ("Pitch Pine"))
-@end group
- (5 . ("White Pine"))))
-@result{}
-((2 "Austrian Pine" "Red Pine")
- (3 "Pitch Pine")
- (5 "White Pine"))
-
-(setq copy (copy-alist needles-per-cluster))
-@result{}
-((2 "Austrian Pine" "Red Pine")
- (3 "Pitch Pine")
- (5 "White Pine"))
-
-(eq needles-per-cluster copy)
- @result{} nil
-(equal needles-per-cluster copy)
- @result{} t
-(eq (car needles-per-cluster) (car copy))
- @result{} nil
-(cdr (car (cdr needles-per-cluster)))
- @result{} ("Pitch Pine")
-@group
-(eq (cdr (car (cdr needles-per-cluster)))
- (cdr (car (cdr copy))))
- @result{} t
-@end group
-@end smallexample
-
- This example shows how @code{copy-alist} makes it possible to change
-the associations of one copy without affecting the other:
-
-@smallexample
-@group
-(setcdr (assq 3 copy) '("Martian Vacuum Pine"))
-(cdr (assq 3 needles-per-cluster))
- @result{} ("Pitch Pine")
-@end group
-@end smallexample
-@end defun
-
-
diff --git a/lispref/loading.texi b/lispref/loading.texi
deleted file mode 100644
index 29c2480f1f5..00000000000
--- a/lispref/loading.texi
+++ /dev/null
@@ -1,680 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/loading
-@node Loading, Byte Compilation, Macros, Top
-@chapter Loading
-@cindex loading
-@cindex library
-@cindex Lisp library
-
- Loading a file of Lisp code means bringing its contents into the Lisp
-environment in the form of Lisp objects. Emacs finds and opens the
-file, reads the text, evaluates each form, and then closes the file.
-
- The load functions evaluate all the expressions in a file just
-as the @code{eval-current-buffer} function evaluates all the
-expressions in a buffer. The difference is that the load functions
-read and evaluate the text in the file as found on disk, not the text
-in an Emacs buffer.
-
-@cindex top-level form
- The loaded file must contain Lisp expressions, either as source code
-or as byte-compiled code. Each form in the file is called a
-@dfn{top-level form}. There is no special format for the forms in a
-loadable file; any form in a file may equally well be typed directly
-into a buffer and evaluated there. (Indeed, most code is tested this
-way.) Most often, the forms are function definitions and variable
-definitions.
-
- A file containing Lisp code is often called a @dfn{library}. Thus,
-the ``Rmail library'' is a file containing code for Rmail mode.
-Similarly, a ``Lisp library directory'' is a directory of files
-containing Lisp code.
-
-@menu
-* How Programs Do Loading:: The @code{load} function and others.
-* Autoload:: Setting up a function to autoload.
-* Repeated Loading:: Precautions about loading a file twice.
-* Named Features:: Loading a library if it isn't already loaded.
-* Unloading:: How to ``unload'' a library that was loaded.
-* Hooks for Loading:: Providing code to be run when
- particular libraries are loaded.
-@end menu
-
-@node How Programs Do Loading
-@section How Programs Do Loading
-
- Emacs Lisp has several interfaces for loading. For example,
-@code{autoload} creates a placeholder object for a function in a file;
-trying to call the autoloading function loads the file to get the
-function's real definition (@pxref{Autoload}). @code{require} loads a
-file if it isn't already loaded (@pxref{Named Features}). Ultimately, all
-these facilities call the @code{load} function to do the work.
-
-@defun load filename &optional missing-ok nomessage nosuffix
-This function finds and opens a file of Lisp code, evaluates all the
-forms in it, and closes the file.
-
-To find the file, @code{load} first looks for a file named
-@file{@var{filename}.elc}, that is, for a file whose name is
-@var{filename} with @samp{.elc} appended. If such a file exists, it is
-loaded. If there is no file by that name, then @code{load} looks for a
-file named @file{@var{filename}.el}. If that file exists, it is loaded.
-Finally, if neither of those names is found, @code{load} looks for a
-file named @var{filename} with nothing appended, and loads it if it
-exists. (The @code{load} function is not clever about looking at
-@var{filename}. In the perverse case of a file named @file{foo.el.el},
-evaluation of @code{(load "foo.el")} will indeed find it.)
-
-If the optional argument @var{nosuffix} is non-@code{nil}, then the
-suffixes @samp{.elc} and @samp{.el} are not tried. In this case, you
-must specify the precise file name you want.
-
-If @var{filename} is a relative file name, such as @file{foo} or
-@file{baz/foo.bar}, @code{load} searches for the file using the variable
-@code{load-path}. It appends @var{filename} to each of the directories
-listed in @code{load-path}, and loads the first file it finds whose name
-matches. The current default directory is tried only if it is specified
-in @code{load-path}, where @code{nil} stands for the default directory.
-@code{load} tries all three possible suffixes in the first directory in
-@code{load-path}, then all three suffixes in the second directory, and
-so on.
-
-If you get a warning that @file{foo.elc} is older than @file{foo.el}, it
-means you should consider recompiling @file{foo.el}. @xref{Byte
-Compilation}.
-
-Messages like @samp{Loading foo...} and @samp{Loading foo...done} appear
-in the echo area during loading unless @var{nomessage} is
-non-@code{nil}.
-
-@cindex load errors
-Any unhandled errors while loading a file terminate loading. If the
-load was done for the sake of @code{autoload}, any function definitions
-made during the loading are undone.
-
-@kindex file-error
-If @code{load} can't find the file to load, then normally it signals the
-error @code{file-error} (with @samp{Cannot open load file
-@var{filename}}). But if @var{missing-ok} is non-@code{nil}, then
-@code{load} just returns @code{nil}.
-
-You can use the variable @code{load-read-function} to specify a function
-for @code{load} to use instead of @code{read} for reading expressions.
-See below.
-
-@code{load} returns @code{t} if the file loads successfully.
-@end defun
-
-@ignore
-@deffn Command load-file filename
-This function loads the file @var{filename}. If @var{filename} is an
-absolute file name, then it is loaded. If it is relative, then the
-current default directory is assumed. @code{load-path} is not used, and
-suffixes are not appended. Use this function if you wish to specify
-the file to be loaded exactly.
-@end deffn
-
-@deffn Command load-library library
-This function loads the library named @var{library}. A library is
-nothing more than a file that may be loaded as described earlier. This
-function is identical to @code{load}, save that it reads a file name
-interactively with completion.
-@end deffn
-@end ignore
-
-@defopt load-path
-@cindex @code{EMACSLOADPATH} environment variable
-The value of this variable is a list of directories to search when
-loading files with @code{load}. Each element is a string (which must be
-a directory name) or @code{nil} (which stands for the current working
-directory). The value of @code{load-path} is initialized from the
-environment variable @code{EMACSLOADPATH}, if that exists; otherwise its
-default value is specified in @file{emacs/src/paths.h} when Emacs is
-built.
-
-The syntax of @code{EMACSLOADPATH} is the same as used for @code{PATH};
-@samp{:} (or @samp{;}, according to the operating system) separates
-directory names, and @samp{.} is used for the current default directory.
-Here is an example of how to set your @code{EMACSLOADPATH} variable from
-a @code{csh} @file{.login} file:
-
-@c This overfull hbox is OK. --rjc 16mar92
-@smallexample
-setenv EMACSLOADPATH .:/user/bil/emacs:/usr/lib/emacs/lisp
-@end smallexample
-
-Here is how to set it using @code{sh}:
-
-@smallexample
-export EMACSLOADPATH
-EMACSLOADPATH=.:/user/bil/emacs:/usr/local/lib/emacs/lisp
-@end smallexample
-
-Here is an example of code you can place in a @file{.emacs} file to add
-several directories to the front of your default @code{load-path}:
-
-@smallexample
-@group
-(setq load-path
- (append (list nil "/user/bil/emacs"
- "/usr/local/lisplib"
- "~/emacs")
- load-path))
-@end group
-@end smallexample
-
-@c Wordy to rid us of an overfull hbox. --rjc 15mar92
-@noindent
-In this example, the path searches the current working directory first,
-followed then by the @file{/user/bil/emacs} directory, the
-@file{/usr/local/lisplib} directory, and the @file{~/emacs} directory,
-which are then followed by the standard directories for Lisp code.
-
-The command line options @samp{-l} or @samp{-load} specify a Lisp
-library to load as part of Emacs startup. Since this file might be in
-the current directory, Emacs 18 temporarily adds the current directory
-to the front of @code{load-path} so the file can be found there. Newer
-Emacs versions also find such files in the current directory, but
-without altering @code{load-path}.
-
-Dumping Emacs uses a special value of @code{load-path}. If the value of
-@code{load-path} at the end of dumping is unchanged (that is, still the
-same special value), the dumped Emacs switches to the ordinary
-@code{load-path} value when it starts up, as described above. But if
-@code{load-path} has any other value at the end of dumping, that value
-is used for execution of the dumped Emacs also.
-
-Therefore, if you want to change @code{load-path} temporarily for
-loading a few libraries in @file{site-init.el} or @file{site-load.el},
-you should bind @code{load-path} locally with @code{let} around the
-calls to @code{load}.
-@end defopt
-
- The default value of @code{load-path}, when running an Emacs which has
-been installed on the system, looks like this:
-
-@smallexample
-("/usr/local/share/emacs/@var{version}/site-lisp"
- "/usr/local/share/emacs/site-lisp"
- "/usr/local/share/emacs/@var{version}/lisp")
-@end smallexample
-
- The last of these three directories is where the Lisp files of Emacs
-itself are installed; the first two are for additional Lisp packages
-installed at your site. The first directory is for locally installed
-packages that belong with a particular Emacs version; the second is for
-locally installed packages that can be used with any installed Emacs
-version.
-
- There are several reasons why a Lisp package that works well in one
-Emacs version can cause trouble in another. Sometimes packages need
-updating for incompatible changes in Emacs; sometimes they depend on
-undocumented internal Emacs data that can change without notice;
-sometimes a newer Emacs version incorporates a version of the package,
-and should be used only with that version.
-
- If you run Emacs from the directory where it was built---that is, an
-executable that has not been formally installed---then @code{load-path}
-normally contains two additional directories. These are the @code{lisp}
-and @code{site-lisp} subdirectories of the main build directory. (Both
-are represented as absolute file names.)
-
-@defvar load-in-progress
-This variable is non-@code{nil} if Emacs is in the process of loading a
-file, and it is @code{nil} otherwise.
-@end defvar
-
-@defvar load-read-function
-This variable specifies an alternate expression-reading function for
-@code{load} and @code{eval-region} to use instead of @code{read}.
-The function should accept one argument, just as @code{read} does.
-
-Normally, the variable's value is @code{nil}, which means those
-functions should use @code{read}.
-@end defvar
-
- To learn how @code{load} is used to build Emacs, see @ref{Building Emacs}.
-
-@node Autoload
-@section Autoload
-@cindex autoload
-
- The @dfn{autoload} facility allows you to make a function or macro
-known in Lisp, but put off loading the file that defines it. The first
-call to the function automatically reads the proper file to install the
-real definition and other associated code, then runs the real definition
-as if it had been loaded all along.
-
- There are two ways to set up an autoloaded function: by calling
-@code{autoload}, and by writing a special ``magic'' comment in the
-source before the real definition. @code{autoload} is the low-level
-primitive for autoloading; any Lisp program can call @code{autoload} at
-any time. Magic comments do nothing on their own; they serve as a guide
-for the command @code{update-file-autoloads}, which constructs calls to
-@code{autoload} and arranges to execute them when Emacs is built. Magic
-comments are the most convenient way to make a function autoload, but
-only for packages installed along with Emacs.
-
-@defun autoload function filename &optional docstring interactive type
-This function defines the function (or macro) named @var{function} so as
-to load automatically from @var{filename}. The string @var{filename}
-specifies the file to load to get the real definition of @var{function}.
-
-The argument @var{docstring} is the documentation string for the
-function. Normally, this is the identical to the documentation string
-in the function definition itself. Specifying the documentation string
-in the call to @code{autoload} makes it possible to look at the
-documentation without loading the function's real definition.
-
-If @var{interactive} is non-@code{nil}, then the function can be called
-interactively. This lets completion in @kbd{M-x} work without loading
-the function's real definition. The complete interactive specification
-need not be given here; it's not needed unless the user actually calls
-@var{function}, and when that happens, it's time to load the real
-definition.
-
-You can autoload macros and keymaps as well as ordinary functions.
-Specify @var{type} as @code{macro} if @var{function} is really a macro.
-Specify @var{type} as @code{keymap} if @var{function} is really a
-keymap. Various parts of Emacs need to know this information without
-loading the real definition.
-
-An autoloaded keymap loads automatically during key lookup when a prefix
-key's binding is the symbol @var{function}. Autoloading does not occur
-for other kinds of access to the keymap. In particular, it does not
-happen when a Lisp program gets the keymap from the value of a variable
-and calls @code{define-key}; not even if the variable name is the same
-symbol @var{function}.
-
-@cindex function cell in autoload
-If @var{function} already has a non-void function definition that is not
-an autoload object, @code{autoload} does nothing and returns @code{nil}.
-If the function cell of @var{function} is void, or is already an autoload
-object, then it is defined as an autoload object like this:
-
-@example
-(autoload @var{filename} @var{docstring} @var{interactive} @var{type})
-@end example
-
-For example,
-
-@example
-@group
-(symbol-function 'run-prolog)
- @result{} (autoload "prolog" 169681 t nil)
-@end group
-@end example
-
-@noindent
-In this case, @code{"prolog"} is the name of the file to load, 169681
-refers to the documentation string in the @file{emacs/etc/DOC} file
-(@pxref{Documentation Basics}), @code{t} means the function is
-interactive, and @code{nil} that it is not a macro or a keymap.
-@end defun
-
-@cindex autoload errors
- The autoloaded file usually contains other definitions and may require
-or provide one or more features. If the file is not completely loaded
-(due to an error in the evaluation of its contents), any function
-definitions or @code{provide} calls that occurred during the load are
-undone. This is to ensure that the next attempt to call any function
-autoloading from this file will try again to load the file. If not for
-this, then some of the functions in the file might appear defined, but
-they might fail to work properly for the lack of certain subroutines
-defined later in the file and not loaded successfully.
-
- If the autoloaded file fails to define the desired Lisp function or
-macro, then an error is signaled with data @code{"Autoloading failed to
-define function @var{function-name}"}.
-
-@findex update-file-autoloads
-@findex update-directory-autoloads
- A magic autoload comment looks like @samp{;;;###autoload}, on a line
-by itself, just before the real definition of the function in its
-autoloadable source file. The command @kbd{M-x update-file-autoloads}
-writes a corresponding @code{autoload} call into @file{loaddefs.el}.
-Building Emacs loads @file{loaddefs.el} and thus calls @code{autoload}.
-@kbd{M-x update-directory-autoloads} is even more powerful; it updates
-autoloads for all files in the current directory.
-
- The same magic comment can copy any kind of form into
-@file{loaddefs.el}. If the form following the magic comment is not a
-function definition, it is copied verbatim. You can also use a magic
-comment to execute a form at build time @emph{without} executing it when
-the file itself is loaded. To do this, write the form @emph{on the same
-line} as the magic comment. Since it is in a comment, it does nothing
-when you load the source file; but @code{update-file-autoloads} copies
-it to @file{loaddefs.el}, where it is executed while building Emacs.
-
- The following example shows how @code{doctor} is prepared for
-autoloading with a magic comment:
-
-@smallexample
-;;;###autoload
-(defun doctor ()
- "Switch to *doctor* buffer and start giving psychotherapy."
- (interactive)
- (switch-to-buffer "*doctor*")
- (doctor-mode))
-@end smallexample
-
-@noindent
-Here's what that produces in @file{loaddefs.el}:
-
-@smallexample
-(autoload 'doctor "doctor"
- "\
-Switch to *doctor* buffer and start giving psychotherapy."
- t)
-@end smallexample
-
-@noindent
-The backslash and newline immediately following the double-quote are a
-convention used only in the preloaded Lisp files such as
-@file{loaddefs.el}; they tell @code{make-docfile} to put the
-documentation string in the @file{etc/DOC} file. @xref{Building Emacs}.
-
-@node Repeated Loading
-@section Repeated Loading
-@cindex repeated loading
-
- You may load one file more than once in an Emacs session. For
-example, after you have rewritten and reinstalled a function definition
-by editing it in a buffer, you may wish to return to the original
-version; you can do this by reloading the file it came from.
-
- When you load or reload files, bear in mind that the @code{load} and
-@code{load-library} functions automatically load a byte-compiled file
-rather than a non-compiled file of similar name. If you rewrite a file
-that you intend to save and reinstall, remember to byte-compile it if
-necessary; otherwise you may find yourself inadvertently reloading the
-older, byte-compiled file instead of your newer, non-compiled file!
-
- When writing the forms in a Lisp library file, keep in mind that the
-file might be loaded more than once. For example, the choice of
-@code{defvar} vs.@: @code{defconst} for defining a variable depends on
-whether it is desirable to reinitialize the variable if the library is
-reloaded: @code{defconst} does so, and @code{defvar} does not.
-(@xref{Defining Variables}.)
-
- The simplest way to add an element to an alist is like this:
-
-@example
-(setq minor-mode-alist
- (cons '(leif-mode " Leif") minor-mode-alist))
-@end example
-
-@noindent
-But this would add multiple elements if the library is reloaded.
-To avoid the problem, write this:
-
-@example
-(or (assq 'leif-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(leif-mode " Leif") minor-mode-alist)))
-@end example
-
- To add an element to a list just once, use @code{add-to-list}
-(@pxref{Setting Variables}).
-
- Occasionally you will want to test explicitly whether a library has
-already been loaded. Here's one way to test, in a library, whether it
-has been loaded before:
-
-@example
-(defvar foo-was-loaded)
-
-(if (not (boundp 'foo-was-loaded))
- @var{execute-first-time-only})
-
-(setq foo-was-loaded t)
-@end example
-
-@noindent
-If the library uses @code{provide} to provide a named feature, you can
-use @code{featurep} to test whether the library has been loaded.
-@ifinfo
-@xref{Named Features}.
-@end ifinfo
-
-@node Named Features
-@section Features
-@cindex features
-@cindex requiring features
-@cindex providing features
-
- @code{provide} and @code{require} are an alternative to
-@code{autoload} for loading files automatically. They work in terms of
-named @dfn{features}. Autoloading is triggered by calling a specific
-function, but a feature is loaded the first time another program asks
-for it by name.
-
- A feature name is a symbol that stands for a collection of functions,
-variables, etc. The file that defines them should @dfn{provide} the
-feature. Another program that uses them may ensure they are defined by
-@dfn{requiring} the feature. This loads the file of definitions if it
-hasn't been loaded already.
-
- To require the presence of a feature, call @code{require} with the
-feature name as argument. @code{require} looks in the global variable
-@code{features} to see whether the desired feature has been provided
-already. If not, it loads the feature from the appropriate file. This
-file should call @code{provide} at the top level to add the feature to
-@code{features}; if it fails to do so, @code{require} signals an error.
-@cindex load error with require
-
- Features are normally named after the files that provide them, so that
-@code{require} need not be given the file name.
-
- For example, in @file{emacs/lisp/prolog.el},
-the definition for @code{run-prolog} includes the following code:
-
-@smallexample
-(defun run-prolog ()
- "Run an inferior Prolog process, with I/O via buffer *prolog*."
- (interactive)
- (require 'comint)
- (switch-to-buffer (make-comint "prolog" prolog-program-name))
- (inferior-prolog-mode))
-@end smallexample
-
-@noindent
-The expression @code{(require 'comint)} loads the file @file{comint.el}
-if it has not yet been loaded. This ensures that @code{make-comint} is
-defined.
-
-The @file{comint.el} file contains the following top-level expression:
-
-@smallexample
-(provide 'comint)
-@end smallexample
-
-@noindent
-This adds @code{comint} to the global @code{features} list, so that
-@code{(require 'comint)} will henceforth know that nothing needs to be
-done.
-
-@cindex byte-compiling @code{require}
- When @code{require} is used at top level in a file, it takes effect
-when you byte-compile that file (@pxref{Byte Compilation}) as well as
-when you load it. This is in case the required package contains macros
-that the byte compiler must know about.
-
- Although top-level calls to @code{require} are evaluated during
-byte compilation, @code{provide} calls are not. Therefore, you can
-ensure that a file of definitions is loaded before it is byte-compiled
-by including a @code{provide} followed by a @code{require} for the same
-feature, as in the following example.
-
-@smallexample
-@group
-(provide 'my-feature) ; @r{Ignored by byte compiler,}
- ; @r{evaluated by @code{load}.}
-(require 'my-feature) ; @r{Evaluated by byte compiler.}
-@end group
-@end smallexample
-
-@noindent
-The compiler ignores the @code{provide}, then processes the
-@code{require} by loading the file in question. Loading the file does
-execute the @code{provide} call, so the subsequent @code{require} call
-does nothing while loading.
-
-@defun provide feature
-This function announces that @var{feature} is now loaded, or being
-loaded, into the current Emacs session. This means that the facilities
-associated with @var{feature} are or will be available for other Lisp
-programs.
-
-The direct effect of calling @code{provide} is to add @var{feature} to
-the front of the list @code{features} if it is not already in the list.
-The argument @var{feature} must be a symbol. @code{provide} returns
-@var{feature}.
-
-@smallexample
-features
- @result{} (bar bish)
-
-(provide 'foo)
- @result{} foo
-features
- @result{} (foo bar bish)
-@end smallexample
-
-When a file is loaded to satisfy an autoload, and it stops due to an
-error in the evaluating its contents, any function definitions or
-@code{provide} calls that occurred during the load are undone.
-@xref{Autoload}.
-@end defun
-
-@defun require feature &optional filename
-This function checks whether @var{feature} is present in the current
-Emacs session (using @code{(featurep @var{feature})}; see below). If it
-is not, then @code{require} loads @var{filename} with @code{load}. If
-@var{filename} is not supplied, then the name of the symbol
-@var{feature} is used as the file name to load.
-
-If loading the file fails to provide @var{feature}, @code{require}
-signals an error, @samp{Required feature @var{feature} was not
-provided}.
-@end defun
-
-@defun featurep feature
-This function returns @code{t} if @var{feature} has been provided in the
-current Emacs session (i.e., @var{feature} is a member of
-@code{features}.)
-@end defun
-
-@defvar features
-The value of this variable is a list of symbols that are the features
-loaded in the current Emacs session. Each symbol was put in this list
-with a call to @code{provide}. The order of the elements in the
-@code{features} list is not significant.
-@end defvar
-
-@node Unloading
-@section Unloading
-@cindex unloading
-
-@c Emacs 19 feature
- You can discard the functions and variables loaded by a library to
-reclaim memory for other Lisp objects. To do this, use the function
-@code{unload-feature}:
-
-@deffn Command unload-feature feature &optional force
-This command unloads the library that provided feature @var{feature}.
-It undefines all functions, macros, and variables defined in that
-library with @code{defconst}, @code{defvar}, @code{defun},
-@code{defmacro}, @code{defsubst} and @code{defalias}. It then restores
-any autoloads formerly associated with those symbols. (Loading
-saves these in the @code{autoload} property of the symbol.)
-
-Ordinarily, @code{unload-feature} refuses to unload a library on which
-other loaded libraries depend. (A library @var{a} depends on library
-@var{b} if @var{a} contains a @code{require} for @var{b}.) If the
-optional argument @var{force} is non-@code{nil}, dependencies are
-ignored and you can unload any library.
-@end deffn
-
- The @code{unload-feature} function is written in Lisp; its actions are
-based on the variable @code{load-history}.
-
-@defvar load-history
-This variable's value is an alist connecting library names with the
-names of functions and variables they define, the features they provide,
-and the features they require.
-
-Each element is a list and describes one library. The @sc{car} of the
-list is the name of the library, as a string. The rest of the list is
-composed of these kinds of objects:
-
-@itemize @bullet
-@item
-Symbols that were defined by this library.
-@item
-Lists of the form @code{(require . @var{feature})} indicating
-features that were required.
-@item
-Lists of the form @code{(provide . @var{feature})} indicating
-features that were provided.
-@end itemize
-
-The value of @code{load-history} may have one element whose @sc{car} is
-@code{nil}. This element describes definitions made with
-@code{eval-buffer} on a buffer that is not visiting a file.
-@end defvar
-
- The command @code{eval-region} updates @code{load-history}, but does so
-by adding the symbols defined to the element for the file being visited,
-rather than replacing that element.
-
-@node Hooks for Loading
-@section Hooks for Loading
-@cindex loading hooks
-@cindex hooks for loading
-
-You can ask for code to be executed if and when a particular library is
-loaded, by calling @code{eval-after-load}.
-
-@defun eval-after-load library form
-This function arranges to evaluate @var{form} at the end of loading the
-library @var{library}, if and when @var{library} is loaded. If
-@var{library} is already loaded, it evaluates @var{form} right away.
-
-The library name @var{library} must exactly match the argument of
-@code{load}. To get the proper results when an installed library is
-found by searching @code{load-path}, you should not include any
-directory names in @var{library}.
-
-An error in @var{form} does not undo the load, but does prevent
-execution of the rest of @var{form}.
-@end defun
-
-In general, well-designed Lisp programs should not use this feature.
-The clean and modular ways to interact with a Lisp library are (1)
-examine and set the library's variables (those which are meant for
-outside use), and (2) call the library's functions. If you wish to
-do (1), you can do it immediately---there is no need to wait for when
-the library is loaded. To do (2), you must load the library (preferably
-with @code{require}).
-
-But it is ok to use @code{eval-after-load} in your personal customizations
-if you don't feel they must meet the design standards of programs to be
-released.
-
-@defvar after-load-alist
-An alist of expressions to evaluate if and when particular libraries are
-loaded. Each element looks like this:
-
-@example
-(@var{filename} @var{forms}@dots{})
-@end example
-
-The function @code{load} checks @code{after-load-alist} in order to
-implement @code{eval-after-load}.
-@end defvar
-
-@c Emacs 19 feature
diff --git a/lispref/locals.texi b/lispref/locals.texi
deleted file mode 100644
index 86e6750248c..00000000000
--- a/lispref/locals.texi
+++ /dev/null
@@ -1,150 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/locals
-@node Standard Buffer-Local Variables, Standard Keymaps, Standard Errors, Top
-@appendix Buffer-Local Variables
-@c The title "Standard Buffer-Local Variables" is too long for
-@c smallbook. --rjc 30mar92
-
- The table below lists the general-purpose Emacs variables that are
-automatically local (when set) in each buffer. Many Lisp packages
-define such variables for their internal use; we don't list them here.
-
-@table @code
-@item abbrev-mode
-@pxref{Abbrevs}
-
-@item auto-fill-function
-@pxref{Auto Filling}
-
-@item buffer-auto-save-file-name
-@pxref{Auto-Saving}
-
-@item buffer-backed-up
-@pxref{Backup Files}
-
-@item buffer-display-table
-@pxref{Display Tables}
-
-@item buffer-file-format
-@pxref{Format Conversion}
-
-@item buffer-file-name
-@pxref{Buffer File Name}
-
-@item buffer-file-number
-@pxref{Buffer File Name}
-
-@item buffer-file-truename
-@pxref{Buffer File Name}
-
-@item buffer-file-type
-@pxref{Files and MS-DOS}
-
-@item buffer-invisibility-spec
-@pxref{Invisible Text}
-
-@item buffer-offer-save
-@pxref{Saving Buffers}
-
-@item buffer-read-only
-@pxref{Read Only Buffers}
-
-@item buffer-saved-size
-@pxref{Point}
-
-@item buffer-undo-list
-@pxref{Undo}
-
-@item cache-long-line-scans
-@pxref{Text Lines}
-
-@item case-fold-search
-@pxref{Searching and Case}
-
-@item ctl-arrow
-@pxref{Usual Display}
-
-@item comment-column
-@pxref{Comments,,, emacs, The GNU Emacs Manual}
-
-@item default-directory
-@pxref{System Environment}
-
-@item defun-prompt-regexp
-@pxref{List Motion}
-
-@item fill-column
-@pxref{Auto Filling}
-
-@item goal-column
-@pxref{Moving Point,,, emacs, The GNU Emacs Manual}
-
-@item left-margin
-@pxref{Indentation}
-
-@item local-abbrev-table
-@pxref{Abbrevs}
-
-@item local-write-file-hooks
-@pxref{Saving Buffers}
-
-@item major-mode
-@pxref{Mode Help}
-
-@item mark-active
-@pxref{The Mark}
-
-@item mark-ring
-@pxref{The Mark}
-
-@item minor-modes
-@pxref{Minor Modes}
-
-@item mode-line-buffer-identification
-@pxref{Mode Line Variables}
-
-@item mode-line-format
-@pxref{Mode Line Data}
-
-@item mode-line-modified
-@pxref{Mode Line Variables}
-
-@item mode-line-process
-@pxref{Mode Line Variables}
-
-@item mode-name
-@pxref{Mode Line Variables}
-
-@item overwrite-mode
-@pxref{Insertion}
-
-@item paragraph-separate
-@pxref{Standard Regexps}
-
-@item paragraph-start
-@pxref{Standard Regexps}
-
-@item point-before-scroll
-Used for communication between mouse commands and scroll-bar commands.
-
-@item require-final-newline
-@pxref{Insertion}
-
-@item selective-display
-@pxref{Selective Display}
-
-@item selective-display-ellipses
-@pxref{Selective Display}
-
-@item tab-width
-@pxref{Usual Display}
-
-@item truncate-lines
-@pxref{Truncation}
-
-@item vc-mode
-@pxref{Mode Line Variables}
-@end table
diff --git a/lispref/macros.texi b/lispref/macros.texi
deleted file mode 100644
index 22a07f14dbe..00000000000
--- a/lispref/macros.texi
+++ /dev/null
@@ -1,579 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/macros
-@node Macros, Loading, Functions, Top
-@chapter Macros
-@cindex macros
-
- @dfn{Macros} enable you to define new control constructs and other
-language features. A macro is defined much like a function, but instead
-of telling how to compute a value, it tells how to compute another Lisp
-expression which will in turn compute the value. We call this
-expression the @dfn{expansion} of the macro.
-
- Macros can do this because they operate on the unevaluated expressions
-for the arguments, not on the argument values as functions do. They can
-therefore construct an expansion containing these argument expressions
-or parts of them.
-
- If you are using a macro to do something an ordinary function could
-do, just for the sake of speed, consider using an inline function
-instead. @xref{Inline Functions}.
-
-@menu
-* Simple Macro:: A basic example.
-* Expansion:: How, when and why macros are expanded.
-* Compiling Macros:: How macros are expanded by the compiler.
-* Defining Macros:: How to write a macro definition.
-* Backquote:: Easier construction of list structure.
-* Problems with Macros:: Don't evaluate the macro arguments too many times.
- Don't hide the user's variables.
-@end menu
-
-@node Simple Macro
-@section A Simple Example of a Macro
-
- Suppose we would like to define a Lisp construct to increment a
-variable value, much like the @code{++} operator in C. We would like to
-write @code{(inc x)} and have the effect of @code{(setq x (1+ x))}.
-Here's a macro definition that does the job:
-
-@findex inc
-@example
-@group
-(defmacro inc (var)
- (list 'setq var (list '1+ var)))
-@end group
-@end example
-
- When this is called with @code{(inc x)}, the argument @code{var} has
-the value @code{x}---@emph{not} the @emph{value} of @code{x}. The body
-of the macro uses this to construct the expansion, which is @code{(setq
-x (1+ x))}. Once the macro definition returns this expansion, Lisp
-proceeds to evaluate it, thus incrementing @code{x}.
-
-@node Expansion
-@section Expansion of a Macro Call
-@cindex expansion of macros
-@cindex macro call
-
- A macro call looks just like a function call in that it is a list which
-starts with the name of the macro. The rest of the elements of the list
-are the arguments of the macro.
-
- Evaluation of the macro call begins like evaluation of a function call
-except for one crucial difference: the macro arguments are the actual
-expressions appearing in the macro call. They are not evaluated before
-they are given to the macro definition. By contrast, the arguments of a
-function are results of evaluating the elements of the function call
-list.
-
- Having obtained the arguments, Lisp invokes the macro definition just
-as a function is invoked. The argument variables of the macro are bound
-to the argument values from the macro call, or to a list of them in the
-case of a @code{&rest} argument. And the macro body executes and
-returns its value just as a function body does.
-
- The second crucial difference between macros and functions is that the
-value returned by the macro body is not the value of the macro call.
-Instead, it is an alternate expression for computing that value, also
-known as the @dfn{expansion} of the macro. The Lisp interpreter
-proceeds to evaluate the expansion as soon as it comes back from the
-macro.
-
- Since the expansion is evaluated in the normal manner, it may contain
-calls to other macros. It may even be a call to the same macro, though
-this is unusual.
-
- You can see the expansion of a given macro call by calling
-@code{macroexpand}.
-
-@defun macroexpand form &optional environment
-@cindex macro expansion
-This function expands @var{form}, if it is a macro call. If the result
-is another macro call, it is expanded in turn, until something which is
-not a macro call results. That is the value returned by
-@code{macroexpand}. If @var{form} is not a macro call to begin with, it
-is returned as given.
-
-Note that @code{macroexpand} does not look at the subexpressions of
-@var{form} (although some macro definitions may do so). Even if they
-are macro calls themselves, @code{macroexpand} does not expand them.
-
-The function @code{macroexpand} does not expand calls to inline functions.
-Normally there is no need for that, since a call to an inline function is
-no harder to understand than a call to an ordinary function.
-
-If @var{environment} is provided, it specifies an alist of macro
-definitions that shadow the currently defined macros. Byte compilation
-uses this feature.
-
-@smallexample
-@group
-(defmacro inc (var)
- (list 'setq var (list '1+ var)))
- @result{} inc
-@end group
-
-@group
-(macroexpand '(inc r))
- @result{} (setq r (1+ r))
-@end group
-
-@group
-(defmacro inc2 (var1 var2)
- (list 'progn (list 'inc var1) (list 'inc var2)))
- @result{} inc2
-@end group
-
-@group
-(macroexpand '(inc2 r s))
- @result{} (progn (inc r) (inc s)) ; @r{@code{inc} not expanded here.}
-@end group
-@end smallexample
-@end defun
-
-@node Compiling Macros
-@section Macros and Byte Compilation
-@cindex byte-compiling macros
-
- You might ask why we take the trouble to compute an expansion for a
-macro and then evaluate the expansion. Why not have the macro body
-produce the desired results directly? The reason has to do with
-compilation.
-
- When a macro call appears in a Lisp program being compiled, the Lisp
-compiler calls the macro definition just as the interpreter would, and
-receives an expansion. But instead of evaluating this expansion, it
-compiles the expansion as if it had appeared directly in the program.
-As a result, the compiled code produces the value and side effects
-intended for the macro, but executes at full compiled speed. This would
-not work if the macro body computed the value and side effects
-itself---they would be computed at compile time, which is not useful.
-
- In order for compilation of macro calls to work, the macros must be
-defined in Lisp when the calls to them are compiled. The compiler has a
-special feature to help you do this: if a file being compiled contains a
-@code{defmacro} form, the macro is defined temporarily for the rest of
-the compilation of that file. To use this feature, you must define the
-macro in the same file where it is used and before its first use.
-
- Byte-compiling a file executes any @code{require} calls at top-level
-in the file. This is in case the file needs the required packages for
-proper compilation. One way to ensure that necessary macro definitions
-are available during compilation is to require the files that define
-them (@pxref{Named Features}). To avoid loading the macro definition files
-when someone @emph{runs} the compiled program, write
-@code{eval-when-compile} around the @code{require} calls (@pxref{Eval
-During Compile}).
-
-@node Defining Macros
-@section Defining Macros
-
- A Lisp macro is a list whose @sc{car} is @code{macro}. Its @sc{cdr} should
-be a function; expansion of the macro works by applying the function
-(with @code{apply}) to the list of unevaluated argument-expressions
-from the macro call.
-
- It is possible to use an anonymous Lisp macro just like an anonymous
-function, but this is never done, because it does not make sense to pass
-an anonymous macro to functionals such as @code{mapcar}. In practice,
-all Lisp macros have names, and they are usually defined with the
-special form @code{defmacro}.
-
-@defspec defmacro name argument-list body-forms@dots{}
-@code{defmacro} defines the symbol @var{name} as a macro that looks
-like this:
-
-@example
-(macro lambda @var{argument-list} . @var{body-forms})
-@end example
-
-This macro object is stored in the function cell of @var{name}. The
-value returned by evaluating the @code{defmacro} form is @var{name}, but
-usually we ignore this value.
-
-The shape and meaning of @var{argument-list} is the same as in a
-function, and the keywords @code{&rest} and @code{&optional} may be used
-(@pxref{Argument List}). Macros may have a documentation string, but
-any @code{interactive} declaration is ignored since macros cannot be
-called interactively.
-@end defspec
-
-@node Backquote
-@section Backquote
-@cindex backquote (list substitution)
-@cindex ` (list substitution)
-@findex `
-
- Macros often need to construct large list structures from a mixture of
-constants and nonconstant parts. To make this easier, use the macro
-@samp{`} (often called @dfn{backquote}).
-
- Backquote allows you to quote a list, but selectively evaluate
-elements of that list. In the simplest case, it is identical to the
-special form @code{quote} (@pxref{Quoting}). For example, these
-two forms yield identical results:
-
-@example
-@group
-`(a list of (+ 2 3) elements)
- @result{} (a list of (+ 2 3) elements)
-@end group
-@group
-'(a list of (+ 2 3) elements)
- @result{} (a list of (+ 2 3) elements)
-@end group
-@end example
-
-@findex , @r{(with Backquote)}
-The special marker @samp{,} inside of the argument to backquote
-indicates a value that isn't constant. Backquote evaluates the
-argument of @samp{,} and puts the value in the list structure:
-
-@example
-@group
-(list 'a 'list 'of (+ 2 3) 'elements)
- @result{} (a list of 5 elements)
-@end group
-@group
-`(a list of ,(+ 2 3) elements)
- @result{} (a list of 5 elements)
-@end group
-@end example
-
-@findex ,@@ @r{(with Backquote)}
-@cindex splicing (with backquote)
-You can also @dfn{splice} an evaluated value into the resulting list,
-using the special marker @samp{,@@}. The elements of the spliced list
-become elements at the same level as the other elements of the resulting
-list. The equivalent code without using @samp{`} is often unreadable.
-Here are some examples:
-
-@example
-@group
-(setq some-list '(2 3))
- @result{} (2 3)
-@end group
-@group
-(cons 1 (append some-list '(4) some-list))
- @result{} (1 2 3 4 2 3)
-@end group
-@group
-`(1 ,@@some-list 4 ,@@some-list)
- @result{} (1 2 3 4 2 3)
-@end group
-
-@group
-(setq list '(hack foo bar))
- @result{} (hack foo bar)
-@end group
-@group
-(cons 'use
- (cons 'the
- (cons 'words (append (cdr list) '(as elements)))))
- @result{} (use the words foo bar as elements)
-@end group
-@group
-`(use the words ,@@(cdr list) as elements)
- @result{} (use the words foo bar as elements)
-@end group
-@end example
-
-@quotation
-Before Emacs version 19.29, @samp{`} used a different syntax which
-required an extra level of parentheses around the entire backquote
-construct. Likewise, each @samp{,} or @samp{,@@} substition required an
-extra level of parentheses surrounding both the @samp{,} or @samp{,@@}
-and the following expression. The old syntax required whitespace
-between the @samp{`}, @samp{,} or @samp{,@@} and the following
-expression.
-
-This syntax is still accepted, but no longer recommended except for
-compatibility with old Emacs versions.
-@end quotation
-
-@node Problems with Macros
-@section Common Problems Using Macros
-
- The basic facts of macro expansion have counterintuitive consequences.
-This section describes some important consequences that can lead to
-trouble, and rules to follow to avoid trouble.
-
-@menu
-* Argument Evaluation:: The expansion should evaluate each macro arg once.
-* Surprising Local Vars:: Local variable bindings in the expansion
- require special care.
-* Eval During Expansion:: Don't evaluate them; put them in the expansion.
-* Repeated Expansion:: Avoid depending on how many times expansion is done.
-@end menu
-
-@node Argument Evaluation
-@subsection Evaluating Macro Arguments Repeatedly
-
- When defining a macro you must pay attention to the number of times
-the arguments will be evaluated when the expansion is executed. The
-following macro (used to facilitate iteration) illustrates the problem.
-This macro allows us to write a simple ``for'' loop such as one might
-find in Pascal.
-
-@findex for
-@smallexample
-@group
-(defmacro for (var from init to final do &rest body)
- "Execute a simple \"for\" loop.
-For example, (for i from 1 to 10 do (print i))."
- (list 'let (list (list var init))
- (cons 'while (cons (list '<= var final)
- (append body (list (list 'inc var)))))))
-@end group
-@result{} for
-
-@group
-(for i from 1 to 3 do
- (setq square (* i i))
- (princ (format "\n%d %d" i square)))
-@expansion{}
-@end group
-@group
-(let ((i 1))
- (while (<= i 3)
- (setq square (* i i))
- (princ (format "%d %d" i square))
- (inc i)))
-@end group
-@group
-
- @print{}1 1
- @print{}2 4
- @print{}3 9
-@result{} nil
-@end group
-@end smallexample
-
-@noindent
-(The arguments @code{from}, @code{to}, and @code{do} in this macro are
-``syntactic sugar''; they are entirely ignored. The idea is that you
-will write noise words (such as @code{from}, @code{to}, and @code{do})
-in those positions in the macro call.)
-
-Here's an equivalent definition simplified through use of backquote:
-
-@smallexample
-@group
-(defmacro for (var from init to final do &rest body)
- "Execute a simple \"for\" loop.
-For example, (for i from 1 to 10 do (print i))."
- `(let ((,var ,init))
- (while (<= ,var ,final)
- ,@@body
- (inc ,var))))
-@end group
-@end smallexample
-
-Both forms of this definition (with backquote and without) suffer from
-the defect that @var{final} is evaluated on every iteration. If
-@var{final} is a constant, this is not a problem. If it is a more
-complex form, say @code{(long-complex-calculation x)}, this can slow
-down the execution significantly. If @var{final} has side effects,
-executing it more than once is probably incorrect.
-
-@cindex macro argument evaluation
-A well-designed macro definition takes steps to avoid this problem by
-producing an expansion that evaluates the argument expressions exactly
-once unless repeated evaluation is part of the intended purpose of the
-macro. Here is a correct expansion for the @code{for} macro:
-
-@smallexample
-@group
-(let ((i 1)
- (max 3))
- (while (<= i max)
- (setq square (* i i))
- (princ (format "%d %d" i square))
- (inc i)))
-@end group
-@end smallexample
-
-Here is a macro definition that creates this expansion:
-
-@smallexample
-@group
-(defmacro for (var from init to final do &rest body)
- "Execute a simple for loop: (for i from 1 to 10 do (print i))."
- `(let ((,var ,init)
- (max ,final))
- (while (<= ,var max)
- ,@@body
- (inc ,var))))
-@end group
-@end smallexample
-
- Unfortunately, this introduces another problem.
-@ifinfo
-Proceed to the following node.
-@end ifinfo
-
-@node Surprising Local Vars
-@subsection Local Variables in Macro Expansions
-
-@ifinfo
- In the previous section, the definition of @code{for} was fixed as
-follows to make the expansion evaluate the macro arguments the proper
-number of times:
-
-@smallexample
-@group
-(defmacro for (var from init to final do &rest body)
- "Execute a simple for loop: (for i from 1 to 10 do (print i))."
-@end group
-@group
- `(let ((,var ,init)
- (max ,final))
- (while (<= ,var max)
- ,@@body
- (inc ,var))))
-@end group
-@end smallexample
-@end ifinfo
-
- The new definition of @code{for} has a new problem: it introduces a
-local variable named @code{max} which the user does not expect. This
-causes trouble in examples such as the following:
-
-@smallexample
-@group
-(let ((max 0))
- (for x from 0 to 10 do
- (let ((this (frob x)))
- (if (< max this)
- (setq max this)))))
-@end group
-@end smallexample
-
-@noindent
-The references to @code{max} inside the body of the @code{for}, which
-are supposed to refer to the user's binding of @code{max}, really access
-the binding made by @code{for}.
-
-The way to correct this is to use an uninterned symbol instead of
-@code{max} (@pxref{Creating Symbols}). The uninterned symbol can be
-bound and referred to just like any other symbol, but since it is
-created by @code{for}, we know that it cannot already appear in the
-user's program. Since it is not interned, there is no way the user can
-put it into the program later. It will never appear anywhere except
-where put by @code{for}. Here is a definition of @code{for} that works
-this way:
-
-@smallexample
-@group
-(defmacro for (var from init to final do &rest body)
- "Execute a simple for loop: (for i from 1 to 10 do (print i))."
- (let ((tempvar (make-symbol "max")))
- `(let ((,var ,init)
- (,tempvar ,final))
- (while (<= ,var ,tempvar)
- ,@@body
- (inc ,var)))))
-@end group
-@end smallexample
-
-@noindent
-This creates an uninterned symbol named @code{max} and puts it in the
-expansion instead of the usual interned symbol @code{max} that appears
-in expressions ordinarily.
-
-@node Eval During Expansion
-@subsection Evaluating Macro Arguments in Expansion
-
- Another problem can happen if you evaluate any of the macro argument
-expressions during the computation of the expansion, such as by calling
-@code{eval} (@pxref{Eval}). If the argument is supposed to refer to the
-user's variables, you may have trouble if the user happens to use a
-variable with the same name as one of the macro arguments. Inside the
-macro body, the macro argument binding is the most local binding of this
-variable, so any references inside the form being evaluated do refer
-to it. Here is an example:
-
-@example
-@group
-(defmacro foo (a)
- (list 'setq (eval a) t))
- @result{} foo
-@end group
-@group
-(setq x 'b)
-(foo x) @expansion{} (setq b t)
- @result{} t ; @r{and @code{b} has been set.}
-;; @r{but}
-(setq a 'c)
-(foo a) @expansion{} (setq a t)
- @result{} t ; @r{but this set @code{a}, not @code{c}.}
-
-@end group
-@end example
-
- It makes a difference whether the user's variable is named @code{a} or
-@code{x}, because @code{a} conflicts with the macro argument variable
-@code{a}.
-
- Another reason not to call @code{eval} in a macro definition is that
-it probably won't do what you intend in a compiled program. The
-byte-compiler runs macro definitions while compiling the program, when
-the program's own computations (which you might have wished to access
-with @code{eval}) don't occur and its local variable bindings don't
-exist.
-
- The safe way to work with the run-time value of an expression is to
-put the expression into the macro expansion, so that its value is
-computed as part of executing the expansion.
-
-@node Repeated Expansion
-@subsection How Many Times is the Macro Expanded?
-
- Occasionally problems result from the fact that a macro call is
-expanded each time it is evaluated in an interpreted function, but is
-expanded only once (during compilation) for a compiled function. If the
-macro definition has side effects, they will work differently depending
-on how many times the macro is expanded.
-
- In particular, constructing objects is a kind of side effect. If the
-macro is called once, then the objects are constructed only once. In
-other words, the same structure of objects is used each time the macro
-call is executed. In interpreted operation, the macro is reexpanded
-each time, producing a fresh collection of objects each time. Usually
-this does not matter---the objects have the same contents whether they
-are shared or not. But if the surrounding program does side effects
-on the objects, it makes a difference whether they are shared. Here is
-an example:
-
-@lisp
-@group
-(defmacro empty-object ()
- (list 'quote (cons nil nil)))
-@end group
-
-@group
-(defun initialize (condition)
- (let ((object (empty-object)))
- (if condition
- (setcar object condition))
- object))
-@end group
-@end lisp
-
-@noindent
-If @code{initialize} is interpreted, a new list @code{(nil)} is
-constructed each time @code{initialize} is called. Thus, no side effect
-survives between calls. If @code{initialize} is compiled, then the
-macro @code{empty-object} is expanded during compilation, producing a
-single ``constant'' @code{(nil)} that is reused and altered each time
-@code{initialize} is called.
-
-One way to avoid pathological cases like this is to think of
-@code{empty-object} as a funny kind of constant, not as a memory
-allocation construct. You wouldn't use @code{setcar} on a constant such
-as @code{'(nil)}, so naturally you won't use it on @code{(empty-object)}
-either.
diff --git a/lispref/maps.texi b/lispref/maps.texi
deleted file mode 100644
index 77dc80001b9..00000000000
--- a/lispref/maps.texi
+++ /dev/null
@@ -1,190 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/maps
-@node Standard Keymaps, Standard Hooks, Standard Buffer-Local Variables, Top
-@appendix Standard Keymaps
-
-The following symbols are used as the names for various keymaps.
-Some of these exist when Emacs is first started, others are
-loaded only when their respective mode is used. This is not
-an exhaustive list.
-
-Almost all of these maps are used as local maps. Indeed, of the modes
-that presently exist, only Vip mode and Terminal mode ever change the
-global keymap.
-
-@table @code
-@item Buffer-menu-mode-map
-@vindex Buffer-menu-mode-map
-A full keymap used by Buffer Menu mode.
-
-@item c-mode-map
-@vindex c-mode-map
-A sparse keymap used by C mode.
-
-@item command-history-map
-@vindex command-history-map
-A full keymap used by Command History mode.
-
-@item ctl-x-4-map
-@vindex ctl-x-4-map
-A sparse keymap for subcommands of the prefix @kbd{C-x 4}.
-
-@item ctl-x-5-map
-@vindex ctl-x-5-map
-A sparse keymap for subcommands of the prefix @kbd{C-x 5}.
-
-@item ctl-x-map
-@vindex ctl-x-map
-A full keymap for @kbd{C-x} commands.
-
-@item debugger-mode-map
-@vindex debugger-mode-map
-A full keymap used by Debugger mode.
-
-@item dired-mode-map
-@vindex dired-mode-map
-A full keymap for @code{dired-mode} buffers.
-
-@item edit-abbrevs-map
-@vindex edit-abbrevs-map
-A sparse keymap used in @code{edit-abbrevs}.
-
-@item edit-tab-stops-map
-@vindex edit-tab-stops-map
-A sparse keymap used in @code{edit-tab-stops}.
-
-@item electric-buffer-menu-mode-map
-@vindex electric-buffer-menu-mode-map
-A full keymap used by Electric Buffer Menu mode.
-
-@item electric-history-map
-@vindex electric-history-map
-A full keymap used by Electric Command History mode.
-
-@item emacs-lisp-mode-map
-@vindex emacs-lisp-mode-map
-A sparse keymap used by Emacs Lisp mode.
-
-@item facemenu-menu
-@vindex facemenu-menu
-The keymap that displays the Text Properties menu.
-
-@item facemenu-background-menu
-@vindex facemenu-background-menu
-The keymap that displays the Background Color submenu of the Text
-Properties menu.
-
-@item facemenu-face-menu
-@vindex facemenu-face-menu
-The keymap that displays the Face submenu of the Text Properties menu.
-
-@item facemenu-foreground-menu
-@vindex facemenu-foreground-menu
-The keymap that displays the Foreground Color submenu of the Text
-Properties menu.
-
-@item facemenu-indentation-menu
-@vindex facemenu-indentation-menu
-The keymap that displays the Indentation submenu of the Text Properties menu.
-
-@item facemenu-justification-menu
-@vindex facemenu-justification-menu
-The keymap that displays the Justification submenu of the Text
-Properties menu.
-
-@item facemenu-special-menu
-@vindex facemenu-special-menu
-The keymap that displays the Special Props submenu of the Text
-Properties menu.
-
-@item function-key-map
-@vindex function-key-map
-The keymap for translating keypad and function keys.@*
-If there are none, then it contains an empty sparse keymap.
-
-@item fundamental-mode-map
-@vindex fundamental-mode-map
-The local keymap for Fundamental mode.@*
-It is empty and should not be changed.
-
-@item Helper-help-map
-@vindex Helper-help-map
-A full keymap used by the help utility package.@*
-It has the same keymap in its value cell and in its function
-cell.
-
-@item Info-edit-map
-@vindex Info-edit-map
-A sparse keymap used by the @kbd{e} command of Info.
-
-@item Info-mode-map
-@vindex Info-mode-map
-A sparse keymap containing Info commands.
-
-@item isearch-mode-map
-@vindex isearch-mode-map
-A keymap that defines the characters you can type within incremental
-search.
-
-@item key-translation-map
-@vindex key-translation-map
-A keymap for translating keys. This one overrides ordinary key
-bindings, unlike @code{function-key-map}.
-
-@item lisp-interaction-mode-map
-@vindex lisp-interaction-mode-map
-A sparse keymap used by Lisp mode.
-
-@item lisp-mode-map
-@vindex lisp-mode-map
-A sparse keymap used by Lisp mode.
-
-@item menu-bar-edit-menu
-@vindex menu-bar-edit-menu
-The keymap which displays the Edit menu in the menu bar.
-
-@item menu-bar-files-menu
-@vindex menu-bar-files-menu
-The keymap which displays the Files menu in the menu bar.
-
-@item menu-bar-help-menu
-@vindex menu-bar-help-menu
-The keymap which displays the Help menu in the menu bar.
-
-@item menu-bar-search-menu
-@vindex menu-bar-search-menu
-The keymap which displays the Search menu in the menu bar.
-
-@item menu-bar-tools-menu
-@vindex menu-bar-tools-menu
-The keymap which displays the Tools menu in the menu bar.
-
-@item mode-specific-map
-@vindex mode-specific-map
-The keymap for characters following @kbd{C-c}. Note, this is in the
-global map. This map is not actually mode specific: its name was chosen
-to be informative for the user in @kbd{C-h b} (@code{display-bindings}),
-where it describes the main use of the @kbd{C-c} prefix key.
-
-@item occur-mode-map
-@vindex occur-mode-map
-A local keymap used by Occur mode.
-
-@item query-replace-map
-@vindex query-replace-map
-A local keymap used for responses in @code{query-replace} and related
-commands; also for @code{y-or-n-p} and @code{map-y-or-n-p}. The functions
-that use this map do not support prefix keys; they look up one event at a
-time.
-
-@item text-mode-map
-@vindex text-mode-map
-A sparse keymap used by Text mode.
-
-@item view-mode-map
-@vindex view-mode-map
-A full keymap used by View mode.
-@end table
diff --git a/lispref/markers.texi b/lispref/markers.texi
deleted file mode 100644
index 8c41fa17f17..00000000000
--- a/lispref/markers.texi
+++ /dev/null
@@ -1,579 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/markers
-@node Markers, Text, Positions, Top
-@chapter Markers
-@cindex markers
-
- A @dfn{marker} is a Lisp object used to specify a position in a buffer
-relative to the surrounding text. A marker changes its offset from the
-beginning of the buffer automatically whenever text is inserted or
-deleted, so that it stays with the two characters on either side of it.
-
-@menu
-* Overview of Markers:: The components of a marker, and how it relocates.
-* Predicates on Markers:: Testing whether an object is a marker.
-* Creating Markers:: Making empty markers or markers at certain places.
-* Information from Markers:: Finding the marker's buffer or character position.
-* Changing Markers:: Moving the marker to a new buffer or position.
-* The Mark:: How ``the mark'' is implemented with a marker.
-* The Region:: How to access ``the region''.
-@end menu
-
-@node Overview of Markers
-@section Overview of Markers
-
- A marker specifies a buffer and a position in that buffer. The marker
-can be used to represent a position in the functions that require one,
-just as an integer could be used. @xref{Positions}, for a complete
-description of positions.
-
- A marker has two attributes: the marker position, and the marker
-buffer. The marker position is an integer that is equivalent (at a
-given time) to the marker as a position in that buffer. But the
-marker's position value can change often during the life of the marker.
-Insertion and deletion of text in the buffer relocate the marker. The
-idea is that a marker positioned between two characters remains between
-those two characters despite insertion and deletion elsewhere in the
-buffer. Relocation changes the integer equivalent of the marker.
-
-@cindex marker relocation
- Deleting text around a marker's position leaves the marker between the
-characters immediately before and after the deleted text. Inserting
-text at the position of a marker normally leaves the marker in front of
-the new text---unless it is inserted with @code{insert-before-markers}
-(@pxref{Insertion}).
-
-@cindex marker garbage collection
- Insertion and deletion in a buffer must check all the markers and
-relocate them if necessary. This slows processing in a buffer with a
-large number of markers. For this reason, it is a good idea to make a
-marker point nowhere if you are sure you don't need it any more.
-Unreferenced markers are garbage collected eventually, but until then
-will continue to use time if they do point somewhere.
-
-@cindex markers as numbers
- Because it is common to perform arithmetic operations on a marker
-position, most of the arithmetic operations (including @code{+} and
-@code{-}) accept markers as arguments. In such cases, the marker
-stands for its current position.
-
-Here are examples of creating markers, setting markers, and moving point
-to markers:
-
-@example
-@group
-;; @r{Make a new marker that initially does not point anywhere:}
-(setq m1 (make-marker))
- @result{} #<marker in no buffer>
-@end group
-
-@group
-;; @r{Set @code{m1} to point between the 99th and 100th characters}
-;; @r{in the current buffer:}
-(set-marker m1 100)
- @result{} #<marker at 100 in markers.texi>
-@end group
-
-@group
-;; @r{Now insert one character at the beginning of the buffer:}
-(goto-char (point-min))
- @result{} 1
-(insert "Q")
- @result{} nil
-@end group
-
-@group
-;; @r{@code{m1} is updated appropriately.}
-m1
- @result{} #<marker at 101 in markers.texi>
-@end group
-
-@group
-;; @r{Two markers that point to the same position}
-;; @r{are not @code{eq}, but they are @code{equal}.}
-(setq m2 (copy-marker m1))
- @result{} #<marker at 101 in markers.texi>
-(eq m1 m2)
- @result{} nil
-(equal m1 m2)
- @result{} t
-@end group
-
-@group
-;; @r{When you are finished using a marker, make it point nowhere.}
-(set-marker m1 nil)
- @result{} #<marker in no buffer>
-@end group
-@end example
-
-@node Predicates on Markers
-@section Predicates on Markers
-
- You can test an object to see whether it is a marker, or whether it is
-either an integer or a marker. The latter test is useful in connection
-with the arithmetic functions that work with both markers and integers.
-
-@defun markerp object
-This function returns @code{t} if @var{object} is a marker, @code{nil}
-otherwise. Note that integers are not markers, even though many
-functions will accept either a marker or an integer.
-@end defun
-
-@defun integer-or-marker-p object
-This function returns @code{t} if @var{object} is an integer or a marker,
-@code{nil} otherwise.
-@end defun
-
-@defun number-or-marker-p object
-This function returns @code{t} if @var{object} is a number (either kind)
-or a marker, @code{nil} otherwise.
-@end defun
-
-@node Creating Markers
-@section Functions That Create Markers
-
- When you create a new marker, you can make it point nowhere, or point
-to the present position of point, or to the beginning or end of the
-accessible portion of the buffer, or to the same place as another given
-marker.
-
-@defun make-marker
-This functions returns a newly created marker that does not point
-anywhere.
-
-@example
-@group
-(make-marker)
- @result{} #<marker in no buffer>
-@end group
-@end example
-@end defun
-
-@defun point-marker
-This function returns a new marker that points to the present position
-of point in the current buffer. @xref{Point}. For an example, see
-@code{copy-marker}, below.
-@end defun
-
-@defun point-min-marker
-This function returns a new marker that points to the beginning of the
-accessible portion of the buffer. This will be the beginning of the
-buffer unless narrowing is in effect. @xref{Narrowing}.
-@end defun
-
-@defun point-max-marker
-@cindex end of buffer marker
-This function returns a new marker that points to the end of the
-accessible portion of the buffer. This will be the end of the buffer
-unless narrowing is in effect. @xref{Narrowing}.
-
-Here are examples of this function and @code{point-min-marker}, shown in
-a buffer containing a version of the source file for the text of this
-chapter.
-
-@example
-@group
-(point-min-marker)
- @result{} #<marker at 1 in markers.texi>
-(point-max-marker)
- @result{} #<marker at 15573 in markers.texi>
-@end group
-
-@group
-(narrow-to-region 100 200)
- @result{} nil
-@end group
-@group
-(point-min-marker)
- @result{} #<marker at 100 in markers.texi>
-@end group
-@group
-(point-max-marker)
- @result{} #<marker at 200 in markers.texi>
-@end group
-@end example
-@end defun
-
-@defun copy-marker marker-or-integer
-If passed a marker as its argument, @code{copy-marker} returns a
-new marker that points to the same place and the same buffer as does
-@var{marker-or-integer}. If passed an integer as its argument,
-@code{copy-marker} returns a new marker that points to position
-@var{marker-or-integer} in the current buffer.
-
-If passed an integer argument less than 1, @code{copy-marker} returns a
-new marker that points to the beginning of the current buffer. If
-passed an integer argument greater than the length of the buffer,
-@code{copy-marker} returns a new marker that points to the end of the
-buffer.
-
-An error is signaled if @var{marker} is neither a marker nor an
-integer.
-
-@example
-@group
-(setq p (point-marker))
- @result{} #<marker at 2139 in markers.texi>
-@end group
-
-@group
-(setq q (copy-marker p))
- @result{} #<marker at 2139 in markers.texi>
-@end group
-
-@group
-(eq p q)
- @result{} nil
-@end group
-
-@group
-(equal p q)
- @result{} t
-@end group
-
-@group
-(copy-marker 0)
- @result{} #<marker at 1 in markers.texi>
-@end group
-
-@group
-(copy-marker 20000)
- @result{} #<marker at 7572 in markers.texi>
-@end group
-@end example
-@end defun
-
-@node Information from Markers
-@section Information from Markers
-
- This section describes the functions for accessing the components of a
-marker object.
-
-@defun marker-position marker
-This function returns the position that @var{marker} points to, or
-@code{nil} if it points nowhere.
-@end defun
-
-@defun marker-buffer marker
-This function returns the buffer that @var{marker} points into, or
-@code{nil} if it points nowhere.
-
-@example
-@group
-(setq m (make-marker))
- @result{} #<marker in no buffer>
-@end group
-@group
-(marker-position m)
- @result{} nil
-@end group
-@group
-(marker-buffer m)
- @result{} nil
-@end group
-
-@group
-(set-marker m 3770 (current-buffer))
- @result{} #<marker at 3770 in markers.texi>
-@end group
-@group
-(marker-buffer m)
- @result{} #<buffer markers.texi>
-@end group
-@group
-(marker-position m)
- @result{} 3770
-@end group
-@end example
-@end defun
-
- Two distinct markers are considered @code{equal} (even though not
-@code{eq}) to each other if they have the same position and buffer, or
-if they both point nowhere.
-
-@node Changing Markers
-@section Changing Marker Positions
-
- This section describes how to change the position of an existing
-marker. When you do this, be sure you know whether the marker is used
-outside of your program, and, if so, what effects will result from
-moving it---otherwise, confusing things may happen in other parts of
-Emacs.
-
-@defun set-marker marker position &optional buffer
-This function moves @var{marker} to @var{position}
-in @var{buffer}. If @var{buffer} is not provided, it defaults to
-the current buffer.
-
-If @var{position} is less than 1, @code{set-marker} moves @var{marker}
-to the beginning of the buffer. If @var{position} is greater than the
-size of the buffer, @code{set-marker} moves marker to the end of the
-buffer. If @var{position} is @code{nil} or a marker that points
-nowhere, then @var{marker} is set to point nowhere.
-
-The value returned is @var{marker}.
-
-@example
-@group
-(setq m (point-marker))
- @result{} #<marker at 4714 in markers.texi>
-@end group
-@group
-(set-marker m 55)
- @result{} #<marker at 55 in markers.texi>
-@end group
-@group
-(setq b (get-buffer "foo"))
- @result{} #<buffer foo>
-@end group
-@group
-(set-marker m 0 b)
- @result{} #<marker at 1 in foo>
-@end group
-@end example
-@end defun
-
-@defun move-marker marker position &optional buffer
-This is another name for @code{set-marker}.
-@end defun
-
-@node The Mark
-@section The Mark
-@cindex mark, the
-@cindex mark ring
-
- One special marker in each buffer is designated @dfn{the mark}. It
-records a position for the user for the sake of commands such as
-@kbd{C-w} and @kbd{C-x @key{TAB}}. Lisp programs should set the mark
-only to values that have a potential use to the user, and never for
-their own internal purposes. For example, the @code{replace-regexp}
-command sets the mark to the value of point before doing any
-replacements, because this enables the user to move back there
-conveniently after the replace is finished.
-
- Many commands are designed so that when called interactively they
-operate on the text between point and the mark. If you are writing such
-a command, don't examine the mark directly; instead, use
-@code{interactive} with the @samp{r} specification. This provides the
-values of point and the mark as arguments to the command in an
-interactive call, but permits other Lisp programs to specify arguments
-explicitly. @xref{Interactive Codes}.
-
- Each buffer has its own value of the mark that is independent of the
-value of the mark in other buffers. When a buffer is created, the mark
-exists but does not point anywhere. We consider this state as ``the
-absence of a mark in that buffer.''
-
- Once the mark ``exists'' in a buffer, it normally never ceases to
-exist. However, it may become @dfn{inactive}, if Transient Mark mode is
-enabled. The variable @code{mark-active}, which is always local in all
-buffers, indicates whether the mark is active: non-@code{nil} means yes.
-A command can request deactivation of the mark upon return to the editor
-command loop by setting @code{deactivate-mark} to a non-@code{nil} value
-(but this causes deactivation only if Transient Mark mode is enabled).
-
- The main motivation for using Transient Mark mode is that this mode
-also enables highlighting of the region when the mark is active.
-@xref{Display}.
-
- In addition to the mark, each buffer has a @dfn{mark ring} which is a
-list of markers containing previous values of the mark. When editing
-commands change the mark, they should normally save the old value of the
-mark on the mark ring. The variable @code{mark-ring-max} specifies the
-maximum number of entries in the mark ring; once the list becomes this
-long, adding a new element deletes the last element.
-
-@defun mark &optional force
-@cindex current buffer mark
-This function returns the current buffer's mark position as an integer.
-
-If the mark is inactive, @code{mark} normally signals an error.
-However, if @var{force} is non-@code{nil}, then @code{mark} returns the
-mark position anyway---or @code{nil}, if the mark is not yet set for
-this buffer.
-@end defun
-
-@defun mark-marker
-This function returns the current buffer's mark. This is the very marker
-that records the mark location inside Emacs, not a copy. Therefore,
-changing this marker's position will directly affect the position of the mark.
-Don't do it unless that is the effect you want.
-
-@example
-@group
-(setq m (mark-marker))
- @result{} #<marker at 3420 in markers.texi>
-@end group
-@group
-(set-marker m 100)
- @result{} #<marker at 100 in markers.texi>
-@end group
-@group
-(mark-marker)
- @result{} #<marker at 100 in markers.texi>
-@end group
-@end example
-
-Like any marker, this marker can be set to point at any buffer you like.
-We don't recommend that you make it point at any buffer other than the
-one of which it is the mark. If you do, it will yield perfectly
-consistent, but rather odd, results.
-@end defun
-
-@ignore
-@deffn Command set-mark-command jump
-If @var{jump} is @code{nil}, this command sets the mark to the value
-of point and pushes the previous value of the mark on the mark ring. The
-message @samp{Mark set} is also displayed in the echo area.
-
-If @var{jump} is not @code{nil}, this command sets point to the value
-of the mark, and sets the mark to the previous saved mark value, which
-is popped off the mark ring.
-
-This function is @emph{only} intended for interactive use.
-@end deffn
-@end ignore
-
-@defun set-mark position
-This function sets the mark to @var{position}, and activates the mark.
-The old value of the mark is @emph{not} pushed onto the mark ring.
-
-@strong{Please note:} Use this function only if 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
-@code{mark-ring}. For this reason, most applications should use
-@code{push-mark} and @code{pop-mark}, not @code{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. An
-editing command should not alter the mark unless altering the mark is
-part of the user-level functionality of the command. (And, in that
-case, this effect should be documented.) To remember a location for
-internal use in the Lisp program, store it in a Lisp variable. For
-example:
-
-@example
-@group
-(let ((beg (point)))
- (forward-line 1)
- (delete-region beg (point))).
-@end group
-@end example
-@end defun
-
-@c for interactive use only
-@ignore
-@deffn Command exchange-point-and-mark
-This function exchanges the positions of point and the mark.
-It is intended for interactive use.
-@end deffn
-@end ignore
-
-@defun push-mark &optional position nomsg activate
-This function sets the current buffer's mark to @var{position}, and
-pushes a copy of the previous mark onto @code{mark-ring}. If
-@var{position} is @code{nil}, then the value of point is used.
-@code{push-mark} returns @code{nil}.
-
-The function @code{push-mark} normally @emph{does not} activate the
-mark. To do that, specify @code{t} for the argument @var{activate}.
-
-A @samp{Mark set} message is displayed unless @var{nomsg} is
-non-@code{nil}.
-@end defun
-
-@defun pop-mark
-This function pops off the top element of @code{mark-ring} and makes
-that mark become the buffer's actual mark. This does not move point in
-the buffer, and it does nothing if @code{mark-ring} is empty. It
-deactivates the mark.
-
-The return value is not meaningful.
-@end defun
-
-@defopt transient-mark-mode
-@cindex Transient Mark mode
-This variable if non-@code{nil} enables Transient Mark mode, in which
-every buffer-modifying primitive sets @code{deactivate-mark}. The
-consequence of this is that commands that modify the buffer normally
-make the mark inactive.
-@end defopt
-
-@defvar deactivate-mark
-If an editor command sets this variable non-@code{nil}, then the editor
-command loop deactivates the mark after the command returns, but only if
-Transient Mark mode is enabled.
-@end defvar
-
-@defun deactivate-mark
-This function deactivates the mark, but only if Transient Mark mode
-is enabled.
-@end defun
-
-@defvar mark-active
-The mark is active when this variable is non-@code{nil}. This variable
-is always local in each buffer.
-@end defvar
-
-@defvar activate-mark-hook
-@defvarx deactivate-mark-hook
-These normal hooks are run, respectively, when the mark becomes active
-and when it becomes inactive. The hook @code{activate-mark-hook} is also
-run at the end of a command if the mark is active and the region may
-have changed.
-@end defvar
-
-@defvar mark-ring
-The value of this buffer-local variable is the list of saved former
-marks of the current buffer, most recent first.
-
-@example
-@group
-mark-ring
-@result{} (#<marker at 11050 in markers.texi>
- #<marker at 10832 in markers.texi>
- @dots{})
-@end group
-@end example
-@end defvar
-
-@defopt mark-ring-max
-The value of this variable is the maximum size of @code{mark-ring}. If
-more marks than this are pushed onto the @code{mark-ring},
-@code{push-mark} discards an old mark when it adds a new one.
-@end defopt
-
-@node The Region
-@section The Region
-@cindex region, the
-
- The text between point and the mark is known as @dfn{the region}.
-Various functions operate on text delimited by point and the mark, but
-only those functions specifically related to the region itself are
-described here.
-
-@defun region-beginning
-This function returns the position of the beginning of the region (as
-an integer). This is the position of either point or the mark,
-whichever is smaller.
-
-If the mark does not point anywhere, an error is signaled.
-@end defun
-
-@defun region-end
-This function returns the position of the end of the region (as an
-integer). This is the position of either point or the mark, whichever is
-larger.
-
-If the mark does not point anywhere, an error is signaled.
-@end defun
-
- Few programs need to use the @code{region-beginning} and
-@code{region-end} functions. A command designed to operate on a region
-should normally use @code{interactive} with the @samp{r} specification
-to find the beginning and end of the region. This lets other Lisp
-programs specify the bounds explicitly as arguments. (@xref{Interactive
-Codes}.)
diff --git a/lispref/minibuf.texi b/lispref/minibuf.texi
deleted file mode 100644
index 9ff436a8fc1..00000000000
--- a/lispref/minibuf.texi
+++ /dev/null
@@ -1,1452 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/minibuf
-@node Minibuffers, Command Loop, Read and Print, Top
-@chapter Minibuffers
-@cindex arguments, reading
-@cindex complex arguments
-@cindex minibuffer
-
- A @dfn{minibuffer} is a special buffer that Emacs commands use to read
-arguments more complicated than the single numeric prefix argument.
-These arguments include file names, buffer names, and command names (as
-in @kbd{M-x}). The minibuffer is displayed on the bottom line of the
-screen, in the same place as the echo area, but only while it is in
-use for reading an argument.
-
-@menu
-* Intro to Minibuffers:: Basic information about minibuffers.
-* Text from Minibuffer:: How to read a straight text string.
-* Object from Minibuffer:: How to read a Lisp object or expression.
-* Minibuffer History:: Recording previous minibuffer inputs
- so the user can reuse them.
-* Completion:: How to invoke and customize completion.
-* Yes-or-No Queries:: Asking a question with a simple answer.
-* Multiple Queries:: Asking a series of similar questions.
-* Minibuffer Misc:: Various customization hooks and variables.
-@end menu
-
-@node Intro to Minibuffers
-@section Introduction to Minibuffers
-
- In most ways, a minibuffer is a normal Emacs buffer. Most operations
-@emph{within} a buffer, such as editing commands, work normally in a
-minibuffer. However, many operations for managing buffers do not apply
-to minibuffers. The name of a minibuffer always has the form @w{@samp{
-*Minibuf-@var{number}}}, and it cannot be changed. Minibuffers are
-displayed only in special windows used only for minibuffers; these
-windows always appear at the bottom of a frame. (Sometime frames have
-no minibuffer window, and sometimes a special kind of frame contains
-nothing but a minibuffer window; see @ref{Minibuffers and Frames}.)
-
- The minibuffer's window is normally a single line. You can resize it
-temporarily with the window sizing commands; it reverts to its normal
-size when the minibuffer is exited. You can resize it permanently by
-using the window sizing commands in the frame's other window, when the
-minibuffer is not active. If the frame contains just a minibuffer, you
-can change the minibuffer's size by changing the frame's size.
-
- If a command uses a minibuffer while there is an active minibuffer,
-this is called a @dfn{recursive minibuffer}. The first minibuffer is
-named @w{@samp{ *Minibuf-0*}}. Recursive minibuffers are named by
-incrementing the number at the end of the name. (The names begin with a
-space so that they won't show up in normal buffer lists.) Of several
-recursive minibuffers, the innermost (or most recently entered) is the
-active minibuffer. We usually call this ``the'' minibuffer. You can
-permit or forbid recursive minibuffers by setting the variable
-@code{enable-recursive-minibuffers} or by putting properties of that
-name on command symbols (@pxref{Minibuffer Misc}).
-
- Like other buffers, a minibuffer may use any of several local keymaps
-(@pxref{Keymaps}); these contain various exit commands and in some cases
-completion commands (@pxref{Completion}).
-
-@itemize @bullet
-@item
-@code{minibuffer-local-map} is 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.
-@end itemize
-
-@node Text from Minibuffer
-@section Reading Text Strings with the Minibuffer
-
- Most often, the minibuffer is used to read text as a string. It can
-also be used to read a Lisp object in textual form. The most basic
-primitive for minibuffer input is @code{read-from-minibuffer}; it can do
-either one.
-
- In most cases, you should not call minibuffer input functions in the
-middle of a Lisp function. Instead, do all minibuffer input as part of
-reading the arguments for a command, in the @code{interactive} spec.
-@xref{Defining Commands}.
-
-@defun read-from-minibuffer prompt-string &optional initial-contents keymap read hist
-This function is the most general way to get input through the
-minibuffer. By default, it accepts arbitrary text and returns it as a
-string; however, if @var{read} is non-@code{nil}, then it uses
-@code{read} to convert the text into a Lisp object (@pxref{Input
-Functions}).
-
-The first thing this function does is to activate a minibuffer and
-display it with @var{prompt-string} as the prompt. This value must be a
-string.
-
-Then, if @var{initial-contents} is a string, @code{read-from-minibuffer}
-inserts it into the minibuffer, leaving point at the end. The
-minibuffer appears with this text as its contents.
-
-@c Emacs 19 feature
-The value of @var{initial-contents} may also be a cons cell of the form
-@code{(@var{string} . @var{position})}. This means to insert
-@var{string} in the minibuffer but put point @var{position} characters
-from the beginning, rather than at the end.
-
-If @var{keymap} is non-@code{nil}, that keymap is the local keymap to
-use in the minibuffer. If @var{keymap} is omitted or @code{nil}, the
-value of @code{minibuffer-local-map} is used as the keymap. Specifying
-a keymap is the most important way to customize the minibuffer for
-various applications such as completion.
-
-The argument @var{hist} specifies which history list variable to use
-for saving the input and for history commands used in the minibuffer.
-It defaults to @code{minibuffer-history}. @xref{Minibuffer History}.
-
-When the user types a command to exit the minibuffer,
-@code{read-from-minibuffer} uses the text in the minibuffer to produce
-its return value. Normally it simply makes a string containing that
-text. However, if @var{read} is non-@code{nil},
-@code{read-from-minibuffer} reads the text and returns the resulting
-Lisp object, unevaluated. (@xref{Input Functions}, for information
-about reading.)
-@end defun
-
-@defun read-string prompt &optional initial
-This function reads a string from the minibuffer and returns it. The
-arguments @var{prompt} and @var{initial} are used as in
-@code{read-from-minibuffer}. The keymap used is
-@code{minibuffer-local-map}.
-
-This is a simplified interface to the
-@code{read-from-minibuffer} function:
-
-@smallexample
-@group
-(read-string @var{prompt} @var{initial})
-@equiv{}
-(read-from-minibuffer @var{prompt} @var{initial} nil nil nil)
-@end group
-@end smallexample
-@end defun
-
-@defvar minibuffer-local-map
-This is the default local keymap for reading from the minibuffer. By
-default, it makes the following bindings:
-
-@table @asis
-@item @key{LFD}
-@code{exit-minibuffer}
-
-@item @key{RET}
-@code{exit-minibuffer}
-
-@item @kbd{C-g}
-@code{abort-recursive-edit}
-
-@item @kbd{M-n}
-@code{next-history-element}
-
-@item @kbd{M-p}
-@code{previous-history-element}
-
-@item @kbd{M-r}
-@code{next-matching-history-element}
-
-@item @kbd{M-s}
-@code{previous-matching-history-element}
-@end table
-@end defvar
-
-@c In version 18, initial is required
-@c Emacs 19 feature
-@defun read-no-blanks-input prompt &optional initial
-This function reads a string from the minibuffer, but does not allow
-whitespace characters as part of the input: instead, those characters
-terminate the input. The arguments @var{prompt} and @var{initial} are
-used as in @code{read-from-minibuffer}.
-
-This is a simplified interface to the @code{read-from-minibuffer}
-function, and passes the value of the @code{minibuffer-local-ns-map}
-keymap as the @var{keymap} argument for that function. Since the keymap
-@code{minibuffer-local-ns-map} does not rebind @kbd{C-q}, it @emph{is}
-possible to put a space into the string, by quoting it.
-
-@smallexample
-@group
-(read-no-blanks-input @var{prompt} @var{initial})
-@equiv{}
-(read-from-minibuffer @var{prompt} @var{initial} minibuffer-local-ns-map)
-@end group
-@end smallexample
-@end defun
-
-@defvar minibuffer-local-ns-map
-This built-in variable is the keymap used as the minibuffer local keymap
-in the function @code{read-no-blanks-input}. By default, it makes the
-following bindings, in addition to those of @code{minibuffer-local-map}:
-
-@table @asis
-@item @key{SPC}
-@cindex @key{SPC} in minibuffer
-@code{exit-minibuffer}
-
-@item @key{TAB}
-@cindex @key{TAB} in minibuffer
-@code{exit-minibuffer}
-
-@item @kbd{?}
-@cindex @kbd{?} in minibuffer
-@code{self-insert-and-exit}
-@end table
-@end defvar
-
-@node Object from Minibuffer
-@section Reading Lisp Objects with the Minibuffer
-
- This section describes functions for reading Lisp objects with the
-minibuffer.
-
-@defun read-minibuffer prompt &optional initial
-This function reads a Lisp object in the minibuffer and returns it,
-without evaluating it. The arguments @var{prompt} and @var{initial} are
-used as in @code{read-from-minibuffer}.
-
-This is a simplified interface to the
-@code{read-from-minibuffer} function:
-
-@smallexample
-@group
-(read-minibuffer @var{prompt} @var{initial})
-@equiv{}
-(read-from-minibuffer @var{prompt} @var{initial} nil t)
-@end group
-@end smallexample
-
-Here is an example in which we supply the string @code{"(testing)"} as
-initial input:
-
-@smallexample
-@group
-(read-minibuffer
- "Enter an expression: " (format "%s" '(testing)))
-
-;; @r{Here is how the minibuffer is displayed:}
-@end group
-
-@group
----------- Buffer: Minibuffer ----------
-Enter an expression: (testing)@point{}
----------- Buffer: Minibuffer ----------
-@end group
-@end smallexample
-
-@noindent
-The user can type @key{RET} immediately to use the initial input as a
-default, or can edit the input.
-@end defun
-
-@defun eval-minibuffer prompt &optional initial
-This function reads a Lisp expression in the minibuffer, evaluates it,
-then returns the result. The arguments @var{prompt} and @var{initial}
-are used as in @code{read-from-minibuffer}.
-
-This function simply evaluates the result of a call to
-@code{read-minibuffer}:
-
-@smallexample
-@group
-(eval-minibuffer @var{prompt} @var{initial})
-@equiv{}
-(eval (read-minibuffer @var{prompt} @var{initial}))
-@end group
-@end smallexample
-@end defun
-
-@defun edit-and-eval-command prompt form
-This function reads a Lisp expression in the minibuffer, and then
-evaluates it. The difference between this command and
-@code{eval-minibuffer} is that here the initial @var{form} is not
-optional and it is treated as a Lisp object to be converted to printed
-representation rather than as a string of text. It is printed with
-@code{prin1}, so if it is a string, double-quote characters (@samp{"})
-appear in the initial text. @xref{Output Functions}.
-
-The first thing @code{edit-and-eval-command} does is to activate the
-minibuffer with @var{prompt} as the prompt. Then it inserts the printed
-representation of @var{form} in the minibuffer, and lets the user edit.
-When the user exits the minibuffer, the edited text is read with
-@code{read} and then evaluated. The resulting value becomes the value
-of @code{edit-and-eval-command}.
-
-In the following example, we offer the user an expression with initial
-text which is a valid form already:
-
-@smallexample
-@group
-(edit-and-eval-command "Please edit: " '(forward-word 1))
-
-;; @r{After evaluation of the preceding expression,}
-;; @r{the following appears in the minibuffer:}
-@end group
-
-@group
----------- Buffer: Minibuffer ----------
-Please edit: (forward-word 1)@point{}
----------- Buffer: Minibuffer ----------
-@end group
-@end smallexample
-
-@noindent
-Typing @key{RET} right away would exit the minibuffer and evaluate the
-expression, thus moving point forward one word.
-@code{edit-and-eval-command} returns @code{nil} in this example.
-@end defun
-
-@node Minibuffer History
-@section Minibuffer History
-@cindex minibuffer history
-@cindex history list
-
-A @dfn{minibuffer history list} records previous minibuffer inputs so
-the user can reuse them conveniently. A history list is actually a
-symbol, not a list; it is a variable whose value is a list of strings
-(previous inputs), most recent first.
-
-There are many separate history lists, used for different kinds of
-inputs. It's the Lisp programmer's job to specify the right history
-list for each use of the minibuffer.
-
-The basic minibuffer input functions @code{read-from-minibuffer} and
-@code{completing-read} both accept an optional argument named @var{hist}
-which is how you specify the history list. Here are the possible
-values:
-
-@table @asis
-@item @var{variable}
-Use @var{variable} (a symbol) as the history list.
-
-@item (@var{variable} . @var{startpos})
-Use @var{variable} (a symbol) as the history list, and assume that the
-initial history position is @var{startpos} (an integer, counting from
-zero which specifies the most recent element of the history).
-
-If you specify @var{startpos}, then you should also specify that element
-of the history as the initial minibuffer contents, for consistency.
-@end table
-
-If you don't specify @var{hist}, then the default history list
-@code{minibuffer-history} is used. For other standard history lists,
-see below. You can also create your own history list variable; just
-initialize it to @code{nil} before the first use.
-
-Both @code{read-from-minibuffer} and @code{completing-read} add new
-elements to the history list automatically, and provide commands to
-allow the user to reuse items on the list. The only thing your program
-needs to do to use a history list is to initialize it and to pass its
-name to the input functions when you wish. But it is safe to modify the
-list by hand when the minibuffer input functions are not using it.
-
-@defvar minibuffer-history
-The default history list for minibuffer history input.
-@end defvar
-
-@defvar query-replace-history
-A history list for arguments to @code{query-replace} (and similar
-arguments to other commands).
-@end defvar
-
-@defvar file-name-history
-A history list for file name arguments.
-@end defvar
-
-@defvar regexp-history
-A history list for regular expression arguments.
-@end defvar
-
-@defvar extended-command-history
-A history list for arguments that are names of extended commands.
-@end defvar
-
-@defvar shell-command-history
-A history list for arguments that are shell commands.
-@end defvar
-
-@defvar read-expression-history
-A history list for arguments that are Lisp expressions to evaluate.
-@end defvar
-
-@node Completion
-@section Completion
-@cindex completion
-
- @dfn{Completion} is a feature that fills in the rest of a name
-starting from an abbreviation for it. Completion works by comparing the
-user's input against a list of valid names and determining how much of
-the name is determined uniquely by what the user has typed. For
-example, when you type @kbd{C-x b} (@code{switch-to-buffer}) and then
-type the first few letters of the name of the buffer to which you wish
-to switch, and then type @key{TAB} (@code{minibuffer-complete}), Emacs
-extends the name as far as it can.
-
- Standard Emacs commands offer completion for names of symbols, files,
-buffers, and processes; with the functions in this section, you can
-implement completion for other kinds of names.
-
- The @code{try-completion} function is the basic primitive for
-completion: it returns the longest determined completion of a given
-initial string, with a given set of strings to match against.
-
- The function @code{completing-read} provides a higher-level interface
-for completion. A call to @code{completing-read} specifies how to
-determine the list of valid names. The function then activates the
-minibuffer with a local keymap that binds a few keys to commands useful
-for completion. Other functions provide convenient simple interfaces
-for reading certain kinds of names with completion.
-
-@menu
-* Basic Completion:: Low-level functions for completing strings.
- (These are too low level to use the minibuffer.)
-* Minibuffer Completion:: Invoking the minibuffer with completion.
-* Completion Commands:: Minibuffer commands that do completion.
-* High-Level Completion:: Convenient special cases of completion
- (reading buffer name, file name, etc.)
-* Reading File Names:: Using completion to read file names.
-* Programmed Completion:: Finding the completions for a given file name.
-@end menu
-
-@node Basic Completion
-@subsection Basic Completion Functions
-
- The two functions @code{try-completion} and @code{all-completions}
-have nothing in themselves to do with minibuffers. We describe them in
-this chapter so as to keep them near the higher-level completion
-features that do use the minibuffer.
-
-@defun try-completion string collection &optional predicate
-This function returns the longest common substring of all possible
-completions of @var{string} in @var{collection}. The value of
-@var{collection} must be an alist, an obarray, or a function that
-implements a virtual set of strings (see below).
-
-Completion compares @var{string} against each of the permissible
-completions specified by @var{collection}; if the beginning of the
-permissible completion equals @var{string}, it matches. If no permissible
-completions match, @code{try-completion} returns @code{nil}. If only
-one permissible completion matches, and the match is exact, then
-@code{try-completion} returns @code{t}. Otherwise, the value is the
-longest initial sequence common to all the permissible completions that
-match.
-
-If @var{collection} is an alist (@pxref{Association Lists}), the
-@sc{car}s of the alist elements form the set of permissible completions.
-
-@cindex obarray in completion
-If @var{collection} is an obarray (@pxref{Creating Symbols}), the names
-of all symbols in the obarray form the set of permissible completions. The
-global variable @code{obarray} holds an obarray containing the names of
-all interned Lisp symbols.
-
-Note that the only valid way to make a new obarray is to create it
-empty and then add symbols to it one by one using @code{intern}.
-Also, you cannot intern a given symbol in more than one obarray.
-
-If the argument @var{predicate} is non-@code{nil}, then it must be a
-function of one argument. It is used to test each possible match, and
-the match is accepted only if @var{predicate} returns non-@code{nil}.
-The argument given to @var{predicate} is either a cons cell from the alist
-(the @sc{car} of which is a string) or else it is a symbol (@emph{not} a
-symbol name) from the obarray.
-
-You can also use a symbol that is a function as @var{collection}. Then
-the function is solely responsible for performing completion;
-@code{try-completion} returns whatever this function returns. The
-function is called with three arguments: @var{string}, @var{predicate}
-and @code{nil}. (The reason for the third argument is so that the same
-function can be used in @code{all-completions} and do the appropriate
-thing in either case.) @xref{Programmed Completion}.
-
-In the first of the following examples, the string @samp{foo} is
-matched by three of the alist @sc{car}s. All of the matches begin with
-the characters @samp{fooba}, so that is the result. In the second
-example, there is only one possible match, and it is exact, so the value
-is @code{t}.
-
-@smallexample
-@group
-(try-completion
- "foo"
- '(("foobar1" 1) ("barfoo" 2) ("foobaz" 3) ("foobar2" 4)))
- @result{} "fooba"
-@end group
-
-@group
-(try-completion "foo" '(("barfoo" 2) ("foo" 3)))
- @result{} t
-@end group
-@end smallexample
-
-In the following example, numerous symbols begin with the characters
-@samp{forw}, and all of them begin with the word @samp{forward}. In
-most of the symbols, this is followed with a @samp{-}, but not in all,
-so no more than @samp{forward} can be completed.
-
-@smallexample
-@group
-(try-completion "forw" obarray)
- @result{} "forward"
-@end group
-@end smallexample
-
-Finally, in the following example, only two of the three possible
-matches pass the predicate @code{test} (the string @samp{foobaz} is
-too short). Both of those begin with the string @samp{foobar}.
-
-@smallexample
-@group
-(defun test (s)
- (> (length (car s)) 6))
- @result{} test
-@end group
-@group
-(try-completion
- "foo"
- '(("foobar1" 1) ("barfoo" 2) ("foobaz" 3) ("foobar2" 4))
- 'test)
- @result{} "foobar"
-@end group
-@end smallexample
-@end defun
-
-@defun all-completions string collection &optional predicate nospace
-This function returns a list of all possible completions of
-@var{string}. The parameters to this function are the same as to
-@code{try-completion}.
-
-If @var{collection} is a function, it is called with three arguments:
-@var{string}, @var{predicate} and @code{t}; then @code{all-completions}
-returns whatever the function returns. @xref{Programmed Completion}.
-
-If @var{nospace} is non-@code{nil}, completions that start with a space
-are ignored unless @var{string} also starts with a space.
-
-Here is an example, using the function @code{test} shown in the
-example for @code{try-completion}:
-
-@smallexample
-@group
-(defun test (s)
- (> (length (car s)) 6))
- @result{} test
-@end group
-
-@group
-(all-completions
- "foo"
- '(("foobar1" 1) ("barfoo" 2) ("foobaz" 3) ("foobar2" 4))
- 'test)
- @result{} ("foobar1" "foobar2")
-@end group
-@end smallexample
-@end defun
-
-@defvar completion-ignore-case
-If the value of this variable is
-non-@code{nil}, Emacs does not consider case significant in completion.
-@end defvar
-
-@node Minibuffer Completion
-@subsection Completion and the Minibuffer
-
- This section describes the basic interface for reading from the
-minibuffer with completion.
-
-@defun completing-read prompt collection &optional predicate require-match initial hist
-This function reads a string in the minibuffer, assisting the user by
-providing completion. It activates the minibuffer with prompt
-@var{prompt}, which must be a string. If @var{initial} is
-non-@code{nil}, @code{completing-read} inserts it into the minibuffer as
-part of the input. Then it allows the user to edit the input, providing
-several commands to attempt completion.
-
-The actual completion is done by passing @var{collection} and
-@var{predicate} to the function @code{try-completion}. This happens in
-certain commands bound in the local keymaps used for completion.
-
-If @var{require-match} is @code{t}, the usual minibuffer exit commands
-won't exit unless the input completes to an element of @var{collection}.
-If @var{require-match} is neither @code{nil} nor @code{t}, then the exit
-commands won't exit unless the input typed is itself an element of
-@var{collection}. If @var{require-match} is @code{nil}, the exit
-commands work regardless of the input in the minibuffer.
-
-The user can exit with null input by typing @key{RET} with an empty
-minibuffer. Then @code{completing-read} returns @code{""}. This is how
-the user requests whatever default the command uses for the value being
-read. The user can return using @key{RET} in this way regardless of the
-value of @var{require-match}, and regardless of whether the empty string
-is included in @var{collection}.
-
-The function @code{completing-read} works by calling
-@code{read-minibuffer}. It uses @code{minibuffer-local-completion-map}
-as the keymap if @var{require-match} is @code{nil}, and uses
-@code{minibuffer-local-must-match-map} if @var{require-match} is
-non-@code{nil}. @xref{Completion Commands}.
-
-The argument @var{hist} specifies which history list variable to use for
-saving the input and for minibuffer history commands. It defaults to
-@code{minibuffer-history}. @xref{Minibuffer History}.
-
-Completion ignores case when comparing the input against the possible
-matches, if the built-in variable @code{completion-ignore-case} is
-non-@code{nil}. @xref{Basic Completion}.
-
-Here's an example of using @code{completing-read}:
-
-@smallexample
-@group
-(completing-read
- "Complete a foo: "
- '(("foobar1" 1) ("barfoo" 2) ("foobaz" 3) ("foobar2" 4))
- nil t "fo")
-@end group
-
-@group
-;; @r{After evaluation of the preceding expression,}
-;; @r{the following appears in the minibuffer:}
-
----------- Buffer: Minibuffer ----------
-Complete a foo: fo@point{}
----------- Buffer: Minibuffer ----------
-@end group
-@end smallexample
-
-@noindent
-If the user then types @kbd{@key{DEL} @key{DEL} b @key{RET}},
-@code{completing-read} returns @code{barfoo}.
-
-The @code{completing-read} function binds three variables to pass
-information to the commands that actually do completion. These
-variables are @code{minibuffer-completion-table},
-@code{minibuffer-completion-predicate} and
-@code{minibuffer-completion-confirm}. For more information about them,
-see @ref{Completion Commands}.
-@end defun
-
-@node Completion Commands
-@subsection Minibuffer Commands That Do Completion
-
- This section describes the keymaps, commands and user options used in
-the minibuffer to do completion.
-
-@defvar minibuffer-local-completion-map
-@code{completing-read} uses this value as the local keymap when an
-exact match of one of the completions is not required. By default, this
-keymap makes the following bindings:
-
-@table @asis
-@item @kbd{?}
-@code{minibuffer-completion-help}
-
-@item @key{SPC}
-@code{minibuffer-complete-word}
-
-@item @key{TAB}
-@code{minibuffer-complete}
-@end table
-
-@noindent
-with other characters bound as in @code{minibuffer-local-map}
-(@pxref{Text from Minibuffer}).
-@end defvar
-
-@defvar minibuffer-local-must-match-map
-@code{completing-read} uses this value as the local keymap when an
-exact match of one of the completions is required. Therefore, no keys
-are bound to @code{exit-minibuffer}, the command that exits the
-minibuffer unconditionally. By default, this keymap makes the following
-bindings:
-
-@table @asis
-@item @kbd{?}
-@code{minibuffer-completion-help}
-
-@item @key{SPC}
-@code{minibuffer-complete-word}
-
-@item @key{TAB}
-@code{minibuffer-complete}
-
-@item @key{LFD}
-@code{minibuffer-complete-and-exit}
-
-@item @key{RET}
-@code{minibuffer-complete-and-exit}
-@end table
-
-@noindent
-with other characters bound as in @code{minibuffer-local-map}.
-@end defvar
-
-@defvar minibuffer-completion-table
-The value of this variable is the alist or obarray used for completion
-in the minibuffer. This is the global variable that contains what
-@code{completing-read} passes to @code{try-completion}. It is used by
-minibuffer completion commands such as @code{minibuffer-complete-word}.
-@end defvar
-
-@defvar minibuffer-completion-predicate
-This variable's value is the predicate that @code{completing-read}
-passes to @code{try-completion}. The variable is also used by the other
-minibuffer completion functions.
-@end defvar
-
-@deffn Command minibuffer-complete-word
-This function completes the minibuffer contents by at most a single
-word. Even if the minibuffer contents have only one completion,
-@code{minibuffer-complete-word} does not add any characters beyond the
-first character that is not a word constituent. @xref{Syntax Tables}.
-@end deffn
-
-@deffn Command minibuffer-complete
-This function completes the minibuffer contents as far as possible.
-@end deffn
-
-@deffn Command minibuffer-complete-and-exit
-This function completes the minibuffer contents, and exits if
-confirmation is not required, i.e., if
-@code{minibuffer-completion-confirm} is @code{nil}. If confirmation
-@emph{is} required, it is given by repeating this command
-immediately---the command is programmed to work without confirmation
-when run twice in succession.
-@end deffn
-
-@defvar minibuffer-completion-confirm
-When the value of this variable is non-@code{nil}, Emacs asks for
-confirmation of a completion before exiting the minibuffer. The
-function @code{minibuffer-complete-and-exit} checks the value of this
-variable before it exits.
-@end defvar
-
-@deffn Command minibuffer-completion-help
-This function creates a list of the possible completions of the
-current minibuffer contents. It works by calling @code{all-completions}
-using the value of the variable @code{minibuffer-completion-table} as
-the @var{collection} argument, and the value of
-@code{minibuffer-completion-predicate} as the @var{predicate} argument.
-The list of completions is displayed as text in a buffer named
-@samp{*Completions*}.
-@end deffn
-
-@defun display-completion-list completions
-This function displays @var{completions} to the stream in
-@code{standard-output}, usually a buffer. (@xref{Read and Print}, for more
-information about streams.) The argument @var{completions} is normally
-a list of completions just returned by @code{all-completions}, but it
-does not have to be. Each element may be a symbol or a string, either
-of which is simply printed, or a list of two strings, which is printed
-as if the strings were concatenated.
-
-This function is called by @code{minibuffer-completion-help}. The
-most common way to use it is together with
-@code{with-output-to-temp-buffer}, like this:
-
-@example
-(with-output-to-temp-buffer "*Completions*"
- (display-completion-list
- (all-completions (buffer-string) my-alist)))
-@end example
-@end defun
-
-@defopt completion-auto-help
-If this variable is non-@code{nil}, the completion commands
-automatically display a list of possible completions whenever nothing
-can be completed because the next character is not uniquely determined.
-@end defopt
-
-@node High-Level Completion
-@subsection High-Level Completion Functions
-
- This section describes the higher-level convenient functions for
-reading certain sorts of names with completion.
-
- In most cases, you should not call these functions in the middle of a
-Lisp function. When possible, do all minibuffer input as part of
-reading the arguments for a command, in the @code{interactive} spec.
-@xref{Defining Commands}.
-
-@defun read-buffer prompt &optional default existing
-This function reads the name of a buffer and returns it as a string.
-The argument @var{default} is the default name to use, the value to
-return if the user exits with an empty minibuffer. If non-@code{nil},
-it should be a string or a buffer. It is mentioned in the prompt, but
-is not inserted in the minibuffer as initial input.
-
-If @var{existing} is non-@code{nil}, then the name specified must be
-that of an existing buffer. The usual commands to exit the minibuffer
-do not exit if the text is not valid, and @key{RET} does completion to
-attempt to find a valid name. (However, @var{default} is not checked
-for validity; it is returned, whatever it is, if the user exits with the
-minibuffer empty.)
-
-In the following example, the user enters @samp{minibuffer.t}, and
-then types @key{RET}. The argument @var{existing} is @code{t}, and the
-only buffer name starting with the given input is
-@samp{minibuffer.texi}, so that name is the value.
-
-@example
-(read-buffer "Buffer name? " "foo" t)
-@group
-;; @r{After evaluation of the preceding expression,}
-;; @r{the following prompt appears,}
-;; @r{with an empty minibuffer:}
-@end group
-
-@group
----------- Buffer: Minibuffer ----------
-Buffer name? (default foo) @point{}
----------- Buffer: Minibuffer ----------
-@end group
-
-@group
-;; @r{The user types @kbd{minibuffer.t @key{RET}}.}
- @result{} "minibuffer.texi"
-@end group
-@end example
-@end defun
-
-@defun read-command prompt
-This function reads the name of a command and returns it as a Lisp
-symbol. The argument @var{prompt} is used as in
-@code{read-from-minibuffer}. Recall that a command is anything for
-which @code{commandp} returns @code{t}, and a command name is a symbol
-for which @code{commandp} returns @code{t}. @xref{Interactive Call}.
-
-@example
-(read-command "Command name? ")
-
-@group
-;; @r{After evaluation of the preceding expression,}
-;; @r{the following prompt appears with an empty minibuffer:}
-@end group
-
-@group
----------- Buffer: Minibuffer ----------
-Command name?
----------- Buffer: Minibuffer ----------
-@end group
-@end example
-
-@noindent
-If the user types @kbd{forward-c @key{RET}}, then this function returns
-@code{forward-char}.
-
-The @code{read-command} function is a simplified interface to
-@code{completing-read}. It uses the variable @code{obarray} so as to
-complete in the set of extant Lisp symbols, and it uses the
-@code{commandp} predicate so as to accept only command names:
-
-@cindex @code{commandp} example
-@example
-@group
-(read-command @var{prompt})
-@equiv{}
-(intern (completing-read @var{prompt} obarray
- 'commandp t nil))
-@end group
-@end example
-@end defun
-
-@defun read-variable prompt
-This function reads the name of a user variable and returns it as a
-symbol.
-
-@example
-@group
-(read-variable "Variable name? ")
-
-;; @r{After evaluation of the preceding expression,}
-;; @r{the following prompt appears,}
-;; @r{with an empty minibuffer:}
-@end group
-
-@group
----------- Buffer: Minibuffer ----------
-Variable name? @point{}
----------- Buffer: Minibuffer ----------
-@end group
-@end example
-
-@noindent
-If the user then types @kbd{fill-p @key{RET}}, @code{read-variable}
-returns @code{fill-prefix}.
-
-This function is similar to @code{read-command}, but uses the
-predicate @code{user-variable-p} instead of @code{commandp}:
-
-@cindex @code{user-variable-p} example
-@example
-@group
-(read-variable @var{prompt})
-@equiv{}
-(intern
- (completing-read @var{prompt} obarray
- 'user-variable-p t nil))
-@end group
-@end example
-@end defun
-
-@node Reading File Names
-@subsection Reading File Names
-
- Here is another high-level completion function, designed for reading a
-file name. It provides special features including automatic insertion
-of the default directory.
-
-@defun read-file-name prompt &optional directory default existing initial
-This function reads a file name in the minibuffer, prompting with
-@var{prompt} and providing completion. If @var{default} is
-non-@code{nil}, then the function returns @var{default} if the user just
-types @key{RET}. @var{default} is not checked for validity; it is
-returned, whatever it is, if the user exits with the minibuffer empty.
-
-If @var{existing} is non-@code{nil}, then the user must specify the name
-of an existing file; @key{RET} performs completion to make the name
-valid if possible, and then refuses to exit if it is not valid. If the
-value of @var{existing} is neither @code{nil} nor @code{t}, then
-@key{RET} also requires confirmation after completion. If
-@var{existing} is @code{nil}, then the name of a nonexistent file is
-acceptable.
-
-The argument @var{directory} specifies the directory to use for
-completion of relative file names. If @code{insert-default-directory}
-is non-@code{nil}, @var{directory} is also inserted in the minibuffer as
-initial input. It defaults to the current buffer's value of
-@code{default-directory}.
-
-@c Emacs 19 feature
-If you specify @var{initial}, that is an initial file name to insert in
-the buffer (after with @var{directory}, if that is inserted). In this
-case, point goes at the beginning of @var{initial}. The default for
-@var{initial} is @code{nil}---don't insert any file name. To see what
-@var{initial} does, try the command @kbd{C-x C-v}.
-
-Here is an example:
-
-@example
-@group
-(read-file-name "The file is ")
-
-;; @r{After evaluation of the preceding expression,}
-;; @r{the following appears in the minibuffer:}
-@end group
-
-@group
----------- Buffer: Minibuffer ----------
-The file is /gp/gnu/elisp/@point{}
----------- Buffer: Minibuffer ----------
-@end group
-@end example
-
-@noindent
-Typing @kbd{manual @key{TAB}} results in the following:
-
-@example
-@group
----------- Buffer: Minibuffer ----------
-The file is /gp/gnu/elisp/manual.texi@point{}
----------- Buffer: Minibuffer ----------
-@end group
-@end example
-
-@c Wordy to avoid overfull hbox in smallbook mode.
-@noindent
-If the user types @key{RET}, @code{read-file-name} returns the file name
-as the string @code{"/gp/gnu/elisp/manual.texi"}.
-@end defun
-
-@defopt insert-default-directory
-This variable is used by @code{read-file-name}. Its value controls
-whether @code{read-file-name} starts by placing the name of the default
-directory in the minibuffer, plus the initial file name if any. If the
-value of this variable is @code{nil}, then @code{read-file-name} does
-not place any initial input in the minibuffer (unless you specify
-initial input with the @var{initial} argument). In that case, the
-default directory is still used for completion of relative file names,
-but is not displayed.
-
-For example:
-
-@example
-@group
-;; @r{Here the minibuffer starts out with the default directory.}
-(let ((insert-default-directory t))
- (read-file-name "The file is "))
-@end group
-
-@group
----------- Buffer: Minibuffer ----------
-The file is ~lewis/manual/@point{}
----------- Buffer: Minibuffer ----------
-@end group
-
-@group
-;; @r{Here the minibuffer is empty and only the prompt}
-;; @r{appears on its line.}
-(let ((insert-default-directory nil))
- (read-file-name "The file is "))
-@end group
-
-@group
----------- Buffer: Minibuffer ----------
-The file is @point{}
----------- Buffer: Minibuffer ----------
-@end group
-@end example
-@end defopt
-
-@node Programmed Completion
-@subsection Programmed Completion
-@cindex programmed completion
-
- Sometimes it is not possible to create an alist or an obarray
-containing all the intended possible completions. In such a case, you
-can supply your own function to compute the completion of a given string.
-This is called @dfn{programmed completion}.
-
- To use this feature, pass a symbol with a function definition as the
-@var{collection} argument to @code{completing-read}. The function
-@code{completing-read} arranges to pass your completion function along
-to @code{try-completion} and @code{all-completions}, which will then let
-your function do all the work.
-
- The completion function should accept three arguments:
-
-@itemize @bullet
-@item
-The string to be completed.
-
-@item
-The predicate function to filter possible matches, or @code{nil} if
-none. Your function should call the predicate for each possible match,
-and ignore the possible match if the predicate returns @code{nil}.
-
-@item
-A flag specifying the type of operation.
-@end itemize
-
- There are three flag values for three operations:
-
-@itemize @bullet
-@item
-@code{nil} specifies @code{try-completion}. The completion function
-should return the completion of the specified string, or @code{t} if the
-string is a unique and exact match already, or @code{nil} if the string
-matches no possibility.
-
-If the string is an exact match for one possibility, but also matches
-other longer possibilities, the function shuold return the string, not
-@code{t}.
-
-@item
-@code{t} specifies @code{all-completions}. The completion function
-should return a list of all possible completions of the specified
-string.
-
-@item
-@code{lambda} specifies a test for an exact match. The completion
-function should return @code{t} if the specified string is an exact
-match for some possibility; @code{nil} otherwise.
-@end itemize
-
- It would be consistent and clean for completion functions to allow
-lambda expressions (lists that are functions) as well as function
-symbols as @var{collection}, but this is impossible. Lists as
-completion tables are already assigned another meaning---as alists. It
-would be unreliable to fail to handle an alist normally because it is
-also a possible function. So you must arrange for any function you wish
-to use for completion to be encapsulated in a symbol.
-
- Emacs uses programmed completion when completing file names.
-@xref{File Name Completion}.
-
-@node Yes-or-No Queries
-@section Yes-or-No Queries
-@cindex asking the user questions
-@cindex querying the user
-@cindex yes-or-no questions
-
- This section describes functions used to ask the user a yes-or-no
-question. The function @code{y-or-n-p} can be answered with a single
-character; it is useful for questions where an inadvertent wrong answer
-will not have serious consequences. @code{yes-or-no-p} is suitable for
-more momentous questions, since it requires three or four characters to
-answer.
-
- If either of these functions is called in a command that was invoked
-using the mouse---more precisely, if @code{last-nonmenu-event}
-(@pxref{Command Loop Info}) is either @code{nil} or a list---then it
-uses a dialog box or pop-up menu to ask the question. Otherwise, it
-uses keyboard input. You can force use of the mouse or use of keyboard
-input by binding @code{last-nonmenu-event} to a suitable value around
-the call.
-
- Strictly speaking, @code{yes-or-no-p} uses the minibuffer and
-@code{y-or-n-p} does not; but it seems best to describe them together.
-
-@defun y-or-n-p prompt
-This function asks the user a question, expecting input in the echo
-area. It returns @code{t} if the user types @kbd{y}, @code{nil} if the
-user types @kbd{n}. This function also accepts @key{SPC} to mean yes
-and @key{DEL} to mean no. It accepts @kbd{C-]} to mean ``quit'', like
-@kbd{C-g}, because the question might look like a minibuffer and for
-that reason the user might try to use @kbd{C-]} to get out. The answer
-is a single character, with no @key{RET} needed to terminate it. Upper
-and lower case are equivalent.
-
-``Asking the question'' means printing @var{prompt} in the echo area,
-followed by the string @w{@samp{(y or n) }}. If the input is not one of
-the expected answers (@kbd{y}, @kbd{n}, @kbd{@key{SPC}},
-@kbd{@key{DEL}}, or something that quits), the function responds
-@samp{Please answer y or n.}, and repeats the request.
-
-This function does not actually use the minibuffer, since it does not
-allow editing of the answer. It actually uses the echo area (@pxref{The
-Echo Area}), which uses the same screen space as the minibuffer. The
-cursor moves to the echo area while the question is being asked.
-
-The answers and their meanings, even @samp{y} and @samp{n}, are not
-hardwired. The keymap @code{query-replace-map} specifies them.
-@xref{Search and Replace}.
-
-In the following example, the user first types @kbd{q}, which is
-invalid. At the next prompt the user types @kbd{y}.
-
-@smallexample
-@group
-(y-or-n-p "Do you need a lift? ")
-
-;; @r{After evaluation of the preceding expression,}
-;; @r{the following prompt appears in the echo area:}
-@end group
-
-@group
----------- Echo area ----------
-Do you need a lift? (y or n)
----------- Echo area ----------
-@end group
-
-;; @r{If the user then types @kbd{q}, the following appears:}
-
-@group
----------- Echo area ----------
-Please answer y or n. Do you need a lift? (y or n)
----------- Echo area ----------
-@end group
-
-;; @r{When the user types a valid answer,}
-;; @r{it is displayed after the question:}
-
-@group
----------- Echo area ----------
-Do you need a lift? (y or n) y
----------- Echo area ----------
-@end group
-@end smallexample
-
-@noindent
-We show successive lines of echo area messages, but only one actually
-appears on the screen at a time.
-@end defun
-
-@defun y-or-n-p-with-timeout prompt seconds default-value
-Like @code{y-or-n-p}, except that if the user fails to answer within
-@var{seconds} seconds, this function stops waiting and returns
-@var{default-value}. It works by setting up a timer; see @ref{Timers}.
-The argument @var{seconds} may be an integer or a floating point number.
-@end defun
-
-@defun yes-or-no-p prompt
-This function asks the user a question, expecting input in the
-minibuffer. It returns @code{t} if the user enters @samp{yes},
-@code{nil} if the user types @samp{no}. The user must type @key{RET} to
-finalize the response. Upper and lower case are equivalent.
-
-@code{yes-or-no-p} starts by displaying @var{prompt} in the echo area,
-followed by @w{@samp{(yes or no) }}. The user must type one of the
-expected responses; otherwise, the function responds @samp{Please answer
-yes or no.}, waits about two seconds and repeats the request.
-
-@code{yes-or-no-p} requires more work from the user than
-@code{y-or-n-p} and is appropriate for more crucial decisions.
-
-Here is an example:
-
-@smallexample
-@group
-(yes-or-no-p "Do you really want to remove everything? ")
-
-;; @r{After evaluation of the preceding expression,}
-;; @r{the following prompt appears,}
-;; @r{with an empty minibuffer:}
-@end group
-
-@group
----------- Buffer: minibuffer ----------
-Do you really want to remove everything? (yes or no)
----------- Buffer: minibuffer ----------
-@end group
-@end smallexample
-
-@noindent
-If the user first types @kbd{y @key{RET}}, which is invalid because this
-function demands the entire word @samp{yes}, it responds by displaying
-these prompts, with a brief pause between them:
-
-@smallexample
-@group
----------- Buffer: minibuffer ----------
-Please answer yes or no.
-Do you really want to remove everything? (yes or no)
----------- Buffer: minibuffer ----------
-@end group
-@end smallexample
-@end defun
-
-@node Multiple Queries
-@section Asking Multiple Y-or-N Questions
-
- When you have a series of similar questions to ask, such as ``Do you
-want to save this buffer'' for each buffer in turn, you should use
-@code{map-y-or-n-p} to ask the collection of questions, rather than
-asking each question individually. This gives the user certain
-convenient facilities such as the ability to answer the whole series at
-once.
-
-@defun map-y-or-n-p prompter actor list &optional help action-alist
-This function, new in Emacs 19, asks the user a series of questions,
-reading a single-character answer in the echo area for each one.
-
-The value of @var{list} specifies the objects to ask questions about.
-It should be either a list of objects or a generator function. If it is
-a function, it should expect no arguments, and should return either the
-next object to ask about, or @code{nil} meaning stop asking questions.
-
-The argument @var{prompter} specifies how to ask each question. If
-@var{prompter} is a string, the question text is computed like this:
-
-@example
-(format @var{prompter} @var{object})
-@end example
-
-@noindent
-where @var{object} is the next object to ask about (as obtained from
-@var{list}).
-
-If not a string, @var{prompter} should be a function of one argument
-(the next object to ask about) and should return the question text. If
-the value is a string, that is the question to ask the user. The
-function can also return @code{t} meaning do act on this object (and
-don't ask the user), or @code{nil} meaning ignore this object (and don't
-ask the user).
-
-The argument @var{actor} says how to act on the answers that the user
-gives. It should be a function of one argument, and it is called with
-each object that the user says yes for. Its argument is always an
-object obtained from @var{list}.
-
-If the argument @var{help} is given, it should be a list of this form:
-
-@example
-(@var{singular} @var{plural} @var{action})
-@end example
-
-@noindent
-where @var{singular} is a string containing a singular noun that
-describes the objects conceptually being acted on, @var{plural} is the
-corresponding plural noun, and @var{action} is a transitive verb
-describing what @var{actor} does.
-
-If you don't specify @var{help}, the default is @code{("object"
-"objects" "act on")}.
-
-Each time a question is asked, the user may enter @kbd{y}, @kbd{Y}, or
-@key{SPC} to act on that object; @kbd{n}, @kbd{N}, or @key{DEL} to skip
-that object; @kbd{!} to act on all following objects; @key{ESC} or
-@kbd{q} to exit (skip all following objects); @kbd{.} (period) to act on
-the current object and then exit; or @kbd{C-h} to get help. These are
-the same answers that @code{query-replace} accepts. The keymap
-@code{query-replace-map} defines their meaning for @code{map-y-or-n-p}
-as well as for @code{query-replace}; see @ref{Search and Replace}.
-
-You can use @var{action-alist} to specify additional possible answers
-and what they mean. It is an alist of elements of the form
-@code{(@var{char} @var{function} @var{help})}, each of which defines one
-additional answer. In this element, @var{char} is a character (the
-answer); @var{function} is a function of one argument (an object from
-@var{list}); @var{help} is a string.
-
-When the user responds with @var{char}, @code{map-y-or-n-p} calls
-@var{function}. If it returns non-@code{nil}, the object is considered
-``acted upon'', and @code{map-y-or-n-p} advances to the next object in
-@var{list}. If it returns @code{nil}, the prompt is repeated for the
-same object.
-
-If @code{map-y-or-n-p} is called in a command that was invoked using the
-mouse---more precisely, if @code{last-nonmenu-event} (@pxref{Command
-Loop Info}) is either @code{nil} or a list---then it uses a dialog box
-or pop-up menu to ask the question. In this case, it does not use
-keyboard input or the echo area. You can force use of the mouse or use
-of keyboard input by binding @code{last-nonmenu-event} to a suitable
-value around the call.
-
-The return value of @code{map-y-or-n-p} is the number of objects acted on.
-@end defun
-
-@node Minibuffer Misc
-@comment node-name, next, previous, up
-@section Minibuffer Miscellany
-
- This section describes some basic functions and variables related to
-minibuffers.
-
-@deffn Command exit-minibuffer
-This command exits the active minibuffer. It is normally bound to
-keys in minibuffer local keymaps.
-@end deffn
-
-@deffn Command self-insert-and-exit
-This command exits the active minibuffer after inserting the last
-character typed on the keyboard (found in @code{last-command-char};
-@pxref{Command Loop Info}).
-@end deffn
-
-@deffn Command previous-history-element n
-This command replaces the minibuffer contents with the value of the
-@var{n}th previous (older) history element.
-@end deffn
-
-@deffn Command next-history-element n
-This command replaces the minibuffer contents with the value of the
-@var{n}th more recent history element.
-@end deffn
-
-@deffn Command previous-matching-history-element pattern
-This command replaces the minibuffer contents with the value of the
-previous (older) history element that matches @var{pattern} (a regular
-expression).
-@end deffn
-
-@deffn Command next-matching-history-element pattern
-This command replaces the minibuffer contents with the value of the next
-(newer) history element that matches @var{pattern} (a regular
-expression).
-@end deffn
-
-@defun minibuffer-prompt
-This function returns the prompt string of the currently active
-minibuffer. If no minibuffer is active, it returns @code{nil}.
-@end defun
-
-@defun minibuffer-prompt-width
-This function returns the display width of the prompt string of the
-currently active minibuffer. If no minibuffer is active, it returns 0.
-@end defun
-
-@defvar minibuffer-setup-hook
-This is a normal hook that is run whenever the minibuffer is entered.
-@xref{Hooks}.
-@end defvar
-
-@defvar minibuffer-exit-hook
-This is a normal hook that is run whenever the minibuffer is exited.
-@xref{Hooks}.
-@end defvar
-
-@defvar minibuffer-help-form
-The current value of this variable is used to rebind @code{help-form}
-locally inside the minibuffer (@pxref{Help Functions}).
-@end defvar
-
-@defun active-minibuffer-window
-This function returns the currently active minibuffer window, or
-@code{nil} if none is currently active.
-@end defun
-
-@defun minibuffer-window &optional frame
-This function returns the minibuffer window used for frame @var{frame}.
-If @var{frame} is @code{nil}, that stands for the current frame. Note
-that the minibuffer window used by a frame need not be part of that
-frame---a frame that has no minibuffer of its own necessarily uses some
-other frame's minibuffer window.
-@end defun
-
-@c Emacs 19 feature
-@defun window-minibuffer-p window
-This function returns non-@code{nil} if @var{window} is a minibuffer window.
-@end defun
-
-It is not correct to determine whether a given window is a minibuffer by
-comparing it with the result of @code{(minibuffer-window)}, because
-there can be more than one minibuffer window if there is more than one
-frame.
-
-@defun minibuffer-window-active-p window
-This function returns non-@code{nil} if @var{window}, assumed to be
-a minibuffer window, is currently active.
-@end defun
-
-@defvar minibuffer-scroll-window
-If the value of this variable is non-@code{nil}, it should be a window
-object. When the function @code{scroll-other-window} is called in the
-minibuffer, it scrolls this window.
-@end defvar
-
-Finally, some functions and variables deal with recursive minibuffers
-(@pxref{Recursive Editing}):
-
-@defun minibuffer-depth
-This function returns the current depth of activations of the
-minibuffer, a nonnegative integer. If no minibuffers are active, it
-returns zero.
-@end defun
-
-@defopt enable-recursive-minibuffers
-If this variable is non-@code{nil}, you can invoke commands (such as
-@code{find-file}) that use minibuffers even while in the minibuffer
-window. Such invocation produces a recursive editing level for a new
-minibuffer. The outer-level minibuffer is invisible while you are
-editing the inner one.
-
-This variable only affects invoking the minibuffer while the
-minibuffer window is selected. If you switch windows while in the
-minibuffer, you can always invoke minibuffer commands while some other
-window is selected.
-@end defopt
-
-@c Emacs 19 feature
-If a command name has a property @code{enable-recursive-minibuffers}
-that is non-@code{nil}, then the command can use the minibuffer to read
-arguments even if it is invoked from the minibuffer. The minibuffer
-command @code{next-matching-history-element} (normally @kbd{M-s} in the
-minibuffer) uses this feature.
diff --git a/lispref/modes.texi b/lispref/modes.texi
deleted file mode 100644
index dda63c9c0e5..00000000000
--- a/lispref/modes.texi
+++ /dev/null
@@ -1,1425 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/modes
-@node Modes, Documentation, Keymaps, Top
-@chapter Major and Minor Modes
-@cindex mode
-
- A @dfn{mode} is a set of definitions that customize Emacs and can be
-turned on and off while you edit. There are two varieties of modes:
-@dfn{major modes}, which are mutually exclusive and used for editing
-particular kinds of text, and @dfn{minor modes}, which provide features
-that users can enable individually.
-
- This chapter describes how to write both major and minor modes, how to
-indicate them in the mode line, and how they run hooks supplied by the
-user. For related topics such as keymaps and syntax tables, see
-@ref{Keymaps}, and @ref{Syntax Tables}.
-
-@menu
-* Major Modes:: Defining major modes.
-* Minor Modes:: Defining minor modes.
-* Mode Line Format:: Customizing the text that appears in the mode line.
-* Hooks:: How to use hooks; how to write code that provides hooks.
-@end menu
-
-@node Major Modes
-@section Major Modes
-@cindex major mode
-@cindex Fundamental mode
-
- Major modes specialize Emacs for editing particular kinds of text.
-Each buffer has only one major mode at a time.
-
- The least specialized major mode is called @dfn{Fundamental mode}.
-This mode has no mode-specific definitions or variable settings, so each
-Emacs command behaves in its default manner, and each option is in its
-default state. All other major modes redefine various keys and options.
-For example, Lisp Interaction mode provides special key bindings for
-@key{LFD} (@code{eval-print-last-sexp}), @key{TAB}
-(@code{lisp-indent-line}), and other keys.
-
- When you need to write several editing commands to help you perform a
-specialized editing task, creating a new major mode is usually a good
-idea. In practice, writing a major mode is easy (in contrast to
-writing a minor mode, which is often difficult).
-
- If the new mode is similar to an old one, it is often unwise to modify
-the old one to serve two purposes, since it may become harder to use and
-maintain. Instead, copy and rename an existing major mode definition
-and alter the copy---or define a @dfn{derived mode} (@pxref{Derived
-Modes}). For example, Rmail Edit mode, which is in
-@file{emacs/lisp/rmailedit.el}, is a major mode that is very similar to
-Text mode except that it provides three additional commands. Its
-definition is distinct from that of Text mode, but was derived from it.
-
- Rmail Edit mode is an example of a case where one piece of text is put
-temporarily into a different major mode so it can be edited in a
-different way (with ordinary Emacs commands rather than Rmail). In such
-cases, the temporary major mode usually has a command to switch back to
-the buffer's usual mode (Rmail mode, in this case). You might be
-tempted to present the temporary redefinitions inside a recursive edit
-and restore the usual ones when the user exits; but this is a bad idea
-because it constrains the user's options when it is done in more than
-one buffer: recursive edits must be exited most-recently-entered first.
-Using alternative major modes avoids this limitation. @xref{Recursive
-Editing}.
-
- The standard GNU Emacs Lisp library directory contains the code for
-several major modes, in files including @file{text-mode.el},
-@file{texinfo.el}, @file{lisp-mode.el}, @file{c-mode.el}, and
-@file{rmail.el}. You can look at these libraries to see how modes are
-written. Text mode is perhaps the simplest major mode aside from
-Fundamental mode. Rmail mode is a complicated and specialized mode.
-
-@menu
-* Major Mode Conventions:: Coding conventions for keymaps, etc.
-* Example Major Modes:: Text mode and Lisp modes.
-* Auto Major Mode:: How Emacs chooses the major mode automatically.
-* Mode Help:: Finding out how to use a mode.
-* Derived Modes:: Defining a new major mode based on another major
- mode.
-@end menu
-
-@node Major Mode Conventions
-@subsection Major Mode Conventions
-
- The code for existing major modes follows various coding conventions,
-including conventions for local keymap and syntax table initialization,
-global names, and hooks. Please follow these conventions when you
-define a new major mode:
-
-@itemize @bullet
-@item
-Define a command whose name ends in @samp{-mode}, with no arguments,
-that switches to the new mode in the current buffer. This command
-should set up the keymap, syntax table, and local variables in an
-existing buffer without changing the buffer's text.
-
-@item
-Write a documentation string for this command that describes the
-special commands available in this mode. @kbd{C-h m}
-(@code{describe-mode}) in your mode will display this string.
-
-The documentation string may include the special documentation
-substrings, @samp{\[@var{command}]}, @samp{\@{@var{keymap}@}}, and
-@samp{\<@var{keymap}>}, that enable the documentation to adapt
-automatically to the user's own key bindings. @xref{Keys in
-Documentation}.
-
-@item
-The major mode command should start by calling
-@code{kill-all-local-variables}. This is what gets rid of the local
-variables of the major mode previously in effect.
-
-@item
-The major mode command should set the variable @code{major-mode} to the
-major mode command symbol. This is how @code{describe-mode} discovers
-which documentation to print.
-
-@item
-The major mode command should set the variable @code{mode-name} to the
-``pretty'' name of the mode, as a string. This appears in the mode
-line.
-
-@item
-@cindex functions in modes
-Since all global names are in the same name space, all the global
-variables, constants, and functions that are part of the mode should
-have names that start with the major mode name (or with an abbreviation
-of it if the name is long). @xref{Style Tips}.
-
-@item
-@cindex keymaps in modes
-The major mode should usually have its own keymap, which is used as the
-local keymap in all buffers in that mode. The major mode function
-should call @code{use-local-map} to install this local map.
-@xref{Active Keymaps}, for more information.
-
-This keymap should be kept in a global variable named
-@code{@var{modename}-mode-map}. Normally the library that defines the
-mode sets this variable.
-
-@xref{Tips for Defining}, for advice about how to write the code to set
-up the mode's keymap variable.
-
-@item
-@cindex syntax tables in modes
-The mode may have its own syntax table or may share one with other
-related modes. If it has its own syntax table, it should store this in
-a variable named @code{@var{modename}-mode-syntax-table}. @xref{Syntax
-Tables}.
-
-@item
-If the mode handles a language that has a syntax for comments, it should
-set the variables that define the comment syntax. @xref{Options for
-Comments,, Options Controlling Comments, emacs, The GNU Emacs Manual}.
-
-@item
-@cindex abbrev tables in modes
-The mode may have its own abbrev table or may share one with other
-related modes. If it has its own abbrev table, it should store this in
-a variable named @code{@var{modename}-mode-abbrev-table}. @xref{Abbrev
-Tables}.
-
-@item
-@vindex font-lock-defaults
-The mode should specify how to do highlighting for Font Lock mode, by
-setting up a buffer-local value for the variable
-@code{font-lock-defaults}.
-
-@item
-@vindex imenu-generic-expression
-@vindex imenu-create-index-function
-The mode should specify how Imenu should find the definitions or
-sections of a buffer, by setting up a buffer-local value for the
-variable @code{imenu-generic-expression} or
-@code{imenu-create-index-function}.
-
-@item
-Use @code{defvar} to set mode-related variables, so that they are not
-reinitialized if they already have a value. (Such reinitialization
-could discard customizations made by the user.)
-
-@item
-@cindex buffer-local variables in modes
-To make a buffer-local binding for an Emacs customization variable, use
-@code{make-local-variable} in the major mode command, not
-@code{make-variable-buffer-local}. The latter function would make the
-variable local to every buffer in which it is subsequently set, which
-would affect buffers that do not use this mode. It is undesirable for a
-mode to have such global effects. @xref{Buffer-Local Variables}.
-
-It's ok to use @code{make-variable-buffer-local}, if you wish, for a
-variable used only within a single Lisp package.
-
-@item
-@cindex mode hook
-@cindex major mode hook
-Each major mode should have a @dfn{mode hook} named
-@code{@var{modename}-mode-hook}. The major mode command should run that
-hook, with @code{run-hooks}, as the very last thing it
-does. @xref{Hooks}.
-
-@item
-The major mode command may also run the hooks of some more basic modes.
-For example, @code{indented-text-mode} runs @code{text-mode-hook} as
-well as @code{indented-text-mode-hook}. It may run these other hooks
-immediately before the mode's own hook (that is, after everything else),
-or it may run them earlier.
-
-@item
-If something special should be done if the user switches a buffer from
-this mode to any other major mode, the mode can set a local value for
-@code{change-major-mode-hook}.
-
-@item
-If this mode is appropriate only for specially-prepared text, then the
-major mode command symbol should have a property named @code{mode-class}
-with value @code{special}, put on as follows:
-
-@cindex @code{mode-class} property
-@cindex @code{special}
-@example
-(put 'funny-mode 'mode-class 'special)
-@end example
-
-@noindent
-This tells Emacs that new buffers created while the current buffer has
-Funny mode should not inherit Funny mode. Modes such as Dired, Rmail,
-and Buffer List use this feature.
-
-@item
-If you want to make the new mode the default for files with certain
-recognizable names, add an element to @code{auto-mode-alist} to select
-the mode for those file names. If you define the mode command to
-autoload, you should add this element in the same file that calls
-@code{autoload}. Otherwise, it is sufficient to add the element in the
-file that contains the mode definition. @xref{Auto Major Mode}.
-
-@item
-@cindex @file{.emacs} customization
-In the documentation, you should provide a sample @code{autoload} form
-and an example of how to add to @code{auto-mode-alist}, that users can
-include in their @file{.emacs} files.
-
-@item
-@cindex mode loading
-The top-level forms in the file defining the mode should be written so
-that they may be evaluated more than once without adverse consequences.
-Even if you never load the file more than once, someone else will.
-@end itemize
-
-@defvar change-major-mode-hook
-This normal hook is run by @code{kill-all-local-variables} before it
-does anything else. This gives major modes a way to arrange for
-something special to be done if the user switches to a different major
-mode. For best results, make this variable buffer-local, so that it
-will disappear after doing its job and will not interfere with the
-subsequent major mode. @xref{Hooks}.
-@end defvar
-
-@node Example Major Modes
-@subsection Major Mode Examples
-
- Text mode is perhaps the simplest mode besides Fundamental mode.
-Here are excerpts from @file{text-mode.el} that illustrate many of
-the conventions listed above:
-
-@smallexample
-@group
-;; @r{Create mode-specific tables.}
-(defvar text-mode-syntax-table nil
- "Syntax table used while in text mode.")
-@end group
-
-@group
-(if text-mode-syntax-table
- () ; @r{Do not change the table if it is already set up.}
- (setq text-mode-syntax-table (make-syntax-table))
- (modify-syntax-entry ?\" ". " text-mode-syntax-table)
- (modify-syntax-entry ?\\ ". " text-mode-syntax-table)
- (modify-syntax-entry ?' "w " text-mode-syntax-table))
-@end group
-
-@group
-(defvar text-mode-abbrev-table nil
- "Abbrev table used while in text mode.")
-(define-abbrev-table 'text-mode-abbrev-table ())
-@end group
-
-@group
-(defvar text-mode-map nil) ; @r{Create a mode-specific keymap.}
-
-(if text-mode-map
- () ; @r{Do not change the keymap if it is already set up.}
- (setq text-mode-map (make-sparse-keymap))
- (define-key text-mode-map "\t" 'tab-to-tab-stop)
- (define-key text-mode-map "\es" 'center-line)
- (define-key text-mode-map "\eS" 'center-paragraph))
-@end group
-@end smallexample
-
- Here is the complete major mode function definition for Text mode:
-
-@smallexample
-@group
-(defun text-mode ()
- "Major mode for editing text intended for humans to read.
- Special commands: \\@{text-mode-map@}
-@end group
-@group
-Turning on text-mode runs the hook `text-mode-hook'."
- (interactive)
- (kill-all-local-variables)
-@end group
-@group
- (use-local-map text-mode-map) ; @r{This provides the local keymap.}
- (setq mode-name "Text") ; @r{This name goes into the mode line.}
- (setq major-mode 'text-mode) ; @r{This is how @code{describe-mode}}
- ; @r{finds the doc string to print.}
- (setq local-abbrev-table text-mode-abbrev-table)
- (set-syntax-table text-mode-syntax-table)
- (run-hooks 'text-mode-hook)) ; @r{Finally, this permits the user to}
- ; @r{customize the mode with a hook.}
-@end group
-@end smallexample
-
-@cindex @file{lisp-mode.el}
- The three Lisp modes (Lisp mode, Emacs Lisp mode, and Lisp
-Interaction mode) have more features than Text mode and the code is
-correspondingly more complicated. Here are excerpts from
-@file{lisp-mode.el} that illustrate how these modes are written.
-
-@cindex syntax table example
-@smallexample
-@group
-;; @r{Create mode-specific table variables.}
-(defvar lisp-mode-syntax-table nil "")
-(defvar emacs-lisp-mode-syntax-table nil "")
-(defvar lisp-mode-abbrev-table nil "")
-@end group
-
-@group
-(if (not emacs-lisp-mode-syntax-table) ; @r{Do not change the table}
- ; @r{if it is already set.}
- (let ((i 0))
- (setq emacs-lisp-mode-syntax-table (make-syntax-table))
-@end group
-
-@group
- ;; @r{Set syntax of chars up to 0 to class of chars that are}
- ;; @r{part of symbol names but not words.}
- ;; @r{(The number 0 is @code{48} in the @sc{ASCII} character set.)}
- (while (< i ?0)
- (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
- (setq i (1+ i)))
- @dots{}
-@end group
-@group
- ;; @r{Set the syntax for other characters.}
- (modify-syntax-entry ? " " emacs-lisp-mode-syntax-table)
- (modify-syntax-entry ?\t " " emacs-lisp-mode-syntax-table)
- @dots{}
-@end group
-@group
- (modify-syntax-entry ?\( "() " emacs-lisp-mode-syntax-table)
- (modify-syntax-entry ?\) ")( " emacs-lisp-mode-syntax-table)
- @dots{}))
-;; @r{Create an abbrev table for lisp-mode.}
-(define-abbrev-table 'lisp-mode-abbrev-table ())
-@end group
-@end smallexample
-
- Much code is shared among the three Lisp modes. The following
-function sets various variables; it is called by each of the major Lisp
-mode functions:
-
-@smallexample
-@group
-(defun lisp-mode-variables (lisp-syntax)
- ;; @r{The @code{lisp-syntax} argument is @code{nil} in Emacs Lisp mode,}
- ;; @r{and @code{t} in the other two Lisp modes.}
- (cond (lisp-syntax
- (if (not lisp-mode-syntax-table)
- ;; @r{The Emacs Lisp mode syntax table always exists, but}
- ;; @r{the Lisp Mode syntax table is created the first time a}
- ;; @r{mode that needs it is called. This is to save space.}
-@end group
-@group
- (progn (setq lisp-mode-syntax-table
- (copy-syntax-table emacs-lisp-mode-syntax-table))
- ;; @r{Change some entries for Lisp mode.}
- (modify-syntax-entry ?\| "\" "
- lisp-mode-syntax-table)
- (modify-syntax-entry ?\[ "_ "
- lisp-mode-syntax-table)
- (modify-syntax-entry ?\] "_ "
- lisp-mode-syntax-table)))
-@end group
-@group
- (set-syntax-table lisp-mode-syntax-table)))
- (setq local-abbrev-table lisp-mode-abbrev-table)
- @dots{})
-@end group
-@end smallexample
-
- Functions such as @code{forward-paragraph} use the value of the
-@code{paragraph-start} variable. Since Lisp code is different from
-ordinary text, the @code{paragraph-start} variable needs to be set
-specially to handle Lisp. Also, comments are indented in a special
-fashion in Lisp and the Lisp modes need their own mode-specific
-@code{comment-indent-function}. The code to set these variables is the
-rest of @code{lisp-mode-variables}.
-
-@smallexample
-@group
- (make-local-variable 'paragraph-start)
- ;; @r{Having @samp{^} is not clean, but @code{page-delimiter}}
- ;; @r{has them too, and removing those is a pain.}
- (setq paragraph-start (concat "^$\\|" page-delimiter))
- @dots{}
-@end group
-@group
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'lisp-comment-indent))
-@end group
-@end smallexample
-
- Each of the different Lisp modes has a slightly different keymap. For
-example, Lisp mode binds @kbd{C-c C-l} to @code{run-lisp}, but the other
-Lisp modes do not. However, all Lisp modes have some commands in
-common. The following function adds these common commands to a given
-keymap.
-
-@smallexample
-@group
-(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))
-@end group
-@end smallexample
-
- Here is an example of using @code{lisp-mode-commands} to initialize a
-keymap, as part of the code for Emacs Lisp mode. First we declare a
-variable with @code{defvar} to hold the mode-specific keymap. When this
-@code{defvar} executes, it sets the variable to @code{nil} if it was
-void. Then we set up the keymap if the variable is @code{nil}.
-
- This code avoids changing the keymap or the variable if it is already
-set up. This lets the user customize the keymap.
-
-@smallexample
-@group
-(defvar emacs-lisp-mode-map () "")
-(if emacs-lisp-mode-map
- ()
- (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))
-@end group
-@end smallexample
-
- Finally, here is the complete major mode function definition for
-Emacs Lisp mode.
-
-@smallexample
-@group
-(defun emacs-lisp-mode ()
- "Major mode for editing Lisp code to run in Emacs.
-Commands:
-Delete converts tabs to spaces as it moves back.
-Blank lines separate paragraphs. Semicolons start comments.
-\\@{emacs-lisp-mode-map@}
-@end group
-@group
-Entry to this mode runs the hook `emacs-lisp-mode-hook'."
- (interactive)
- (kill-all-local-variables)
- (use-local-map emacs-lisp-mode-map) ; @r{This provides the local keymap.}
- (set-syntax-table emacs-lisp-mode-syntax-table)
-@end group
-@group
- (setq major-mode 'emacs-lisp-mode) ; @r{This is how @code{describe-mode}}
- ; @r{finds out what to describe.}
- (setq mode-name "Emacs-Lisp") ; @r{This goes into the mode line.}
- (lisp-mode-variables nil) ; @r{This defines various variables.}
- (run-hooks 'emacs-lisp-mode-hook)) ; @r{This permits the user to use a}
- ; @r{hook to customize the mode.}
-@end group
-@end smallexample
-
-@node Auto Major Mode
-@subsection How Emacs Chooses a Major Mode
-
- Based on information in the file name or in the file itself, Emacs
-automatically selects a major mode for the new buffer when a file is
-visited.
-
-@deffn Command fundamental-mode
- Fundamental mode is a major mode that is not specialized for anything
-in particular. Other major modes are defined in effect by comparison
-with this one---their definitions say what to change, starting from
-Fundamental mode. The @code{fundamental-mode} function does @emph{not}
-run any hooks; you're not supposed to customize it. (If you want Emacs
-to behave differently in Fundamental mode, change the @emph{global}
-state of Emacs.)
-@end deffn
-
-@deffn Command normal-mode &optional find-file
-This function establishes the proper major mode and local variable
-bindings for the current buffer. First it calls @code{set-auto-mode},
-then it runs @code{hack-local-variables} to parse, and bind or
-evaluate as appropriate, any local variables.
-
-If the @var{find-file} argument to @code{normal-mode} is
-non-@code{nil}, @code{normal-mode} assumes that the @code{find-file}
-function is calling it. In this case, it may process a local variables
-list at the end of the file and in the @samp{-*-} line. The variable
-@code{enable-local-variables} controls whether to do so.
-
-If you run @code{normal-mode} interactively, the argument
-@var{find-file} is normally @code{nil}. In this case,
-@code{normal-mode} unconditionally processes any local variables list.
-@xref{File variables, , Local Variables in Files, emacs, The GNU Emacs
-Manual}, for the syntax of the local variables section of a file.
-
-@cindex file mode specification error
-@code{normal-mode} uses @code{condition-case} around the call to the
-major mode function, so errors are caught and reported as a @samp{File
-mode specification error}, followed by the original error message.
-@end deffn
-
-@defopt enable-local-variables
-This variable controls processing of local variables lists in files
-being visited. A value of @code{t} means process the local variables
-lists unconditionally; @code{nil} means ignore them; anything else means
-ask the user what to do for each file. The default value is @code{t}.
-@end defopt
-
-@defvar ignored-local-variables
-This variable holds a list of variables that should not be
-set by a local variables list. Any value specified
-for one of these variables is ignored.
-@end defvar
-
-In addition to this list, any variable whose name has a non-@code{nil}
-@code{risky-local-variable} property is also ignored.
-
-@defopt enable-local-eval
-This variable controls processing of @samp{Eval:} in local variables
-lists in files being visited. A value of @code{t} means process them
-unconditionally; @code{nil} means ignore them; anything else means ask
-the user what to do for each file. The default value is @code{maybe}.
-@end defopt
-
-@defun set-auto-mode
-@cindex visited file mode
- This function selects the major mode that is appropriate for the
-current buffer. It may base its decision on the value of the @w{@samp{-*-}}
-line, on the visited file name (using @code{auto-mode-alist}), on the
-@w{@samp{#!}} line (using @code{interpreter-mode-alist}), or on the
-value of a local variable. However, this function does not look for
-the @samp{mode:} local variable near the end of a file; the
-@code{hack-local-variables} function does that. @xref{Choosing Modes, ,
-How Major Modes are Chosen, emacs, The GNU Emacs Manual}.
-@end defun
-
-@defopt default-major-mode
- This variable holds the default major mode for new buffers. The
-standard value is @code{fundamental-mode}.
-
- If the value of @code{default-major-mode} is @code{nil}, Emacs uses
-the (previously) current buffer's major mode for the major mode of a new
-buffer. However, if the major mode symbol has a @code{mode-class}
-property with value @code{special}, then it is not used for new buffers;
-Fundamental mode is used instead. The modes that have this property are
-those such as Dired and Rmail that are useful only with text that has
-been specially prepared.
-@end defopt
-
-@defun set-buffer-major-mode buffer
-This function sets the major mode of @var{buffer} to the value of
-@code{default-major-mode}. If that variable is @code{nil}, it uses
-the current buffer's major mode (if that is suitable).
-
-The low-level primitives for creating buffers do not use this function,
-but medium-level commands such as @code{switch-to-buffer} and
-@code{find-file-noselect} use it whenever they create buffers.
-@end defun
-
-@defvar initial-major-mode
-@cindex @samp{*scratch*}
-The value of this variable determines the major mode of the initial
-@samp{*scratch*} buffer. The value should be a symbol that is a major
-mode command name. The default value is @code{lisp-interaction-mode}.
-@end defvar
-
-@defvar auto-mode-alist
-This variable contains an association list of file name patterns
-(regular expressions; @pxref{Regular Expressions}) and corresponding
-major mode functions. Usually, the file name patterns test for
-suffixes, such as @samp{.el} and @samp{.c}, but this need not be the
-case. An ordinary element of the alist looks like @code{(@var{regexp} .
-@var{mode-function})}.
-
-For example,
-
-@smallexample
-@group
-(("^/tmp/fol/" . text-mode)
- ("\\.texinfo\\'" . texinfo-mode)
- ("\\.texi\\'" . texinfo-mode)
-@end group
-@group
- ("\\.el\\'" . emacs-lisp-mode)
- ("\\.c\\'" . c-mode)
- ("\\.h\\'" . c-mode)
- @dots{})
-@end group
-@end smallexample
-
-When you visit a file whose expanded file name (@pxref{File Name
-Expansion}) matches a @var{regexp}, @code{set-auto-mode} calls the
-corresponding @var{mode-function}. This feature enables Emacs to select
-the proper major mode for most files.
-
-If an element of @code{auto-mode-alist} has the form @code{(@var{regexp}
-@var{function} t)}, then after calling @var{function}, Emacs searches
-@code{auto-mode-alist} again for a match against the portion of the file
-name that did not match before.
-
-This match-again feature is useful for uncompression packages: an entry
-of the form @code{("\\.gz\\'" . @var{function})} can uncompress the file
-and then put the uncompressed file in the proper mode according to the
-name sans @samp{.gz}.
-
-Here is an example of how to prepend several pattern pairs to
-@code{auto-mode-alist}. (You might use this sort of expression in your
-@file{.emacs} file.)
-
-@smallexample
-@group
-(setq auto-mode-alist
- (append
- ;; @r{File name starts with a dot.}
- '(("/\\.[^/]*\\'" . fundamental-mode)
- ;; @r{File name has no dot.}
- ("[^\\./]*\\'" . fundamental-mode)
- ;; @r{File name ends in @samp{.C}.}
- ("\\.C\\'" . c++-mode))
- auto-mode-alist))
-@end group
-@end smallexample
-@end defvar
-
-@defvar interpreter-mode-alist
-This variable specifes major modes to use for scripts that specify a
-command interpreter in an @samp{#!} line. Its value is a list of
-elements of the form @code{(@var{interpreter} . @var{mode})}; for
-example, @code{("perl" . perl-mode)} is one element present by default.
-The element says to use mode @var{mode} if the file specifies
-@var{interpreter}.
-
-This variable is applicable only when the @code{auto-mode-alist} does
-not indicate which major mode to use.
-@end defvar
-
-@defun hack-local-variables &optional force
- This function parses, and binds or evaluates as appropriate, any local
-variables for the current buffer.
-
- The handling of @code{enable-local-variables} documented for
-@code{normal-mode} actually takes place here. The argument @var{force}
-usually comes from the argument @var{find-file} given to
-@code{normal-mode}.
-@end defun
-
-@node Mode Help
-@subsection Getting Help about a Major Mode
-@cindex mode help
-@cindex help for major mode
-@cindex documentation for major mode
-
- The @code{describe-mode} function is used to provide information
-about major modes. It is normally called with @kbd{C-h m}. The
-@code{describe-mode} function uses the value of @code{major-mode},
-which is why every major mode function needs to set the
-@code{major-mode} variable.
-
-@deffn Command describe-mode
-This function displays the documentation of the current major mode.
-
-The @code{describe-mode} function calls the @code{documentation}
-function using the value of @code{major-mode} as an argument. Thus, it
-displays the documentation string of the major mode function.
-(@xref{Accessing Documentation}.)
-@end deffn
-
-@defvar major-mode
-This variable holds the symbol for the current buffer's major mode.
-This symbol should have a function definition that is the command to
-switch to that major mode. The @code{describe-mode} function uses the
-documentation string of the function as the documentation of the major
-mode.
-@end defvar
-
-@node Derived Modes
-@subsection Defining Derived Modes
-
- It's often useful to define a new major mode in terms of an existing
-one. An easy way to do this is to use @code{define-derived-mode}.
-
-@defmac define-derived-mode variant parent name docstring body@dots{}
-This construct defines @var{variant} as a major mode command, using
-@var{name} as the string form of the mode name.
-
-The new command @var{variant} is defined to call the function
-@var{parent}, then override certain aspects of that parent mode:
-
-@itemize @bullet
-@item
-The new mode has its own keymap, named @code{@var{variant}-map}.
-@code{define-derived-mode} initializes this map to inherit from
-@code{@var{parent}-map}, if it is not already set.
-
-@item
-The new mode has its own syntax table, kept in the variable
-@code{@var{variant}-syntax-table}.
-@code{define-derived-mode} initializes this variable by copying
-@code{@var{parent}-syntax-table}, if it is not already set.
-
-@item
-The new mode has its own abbrev table, kept in the variable
-@code{@var{variant}-abbrev-table}.
-@code{define-derived-mode} initializes this variable by copying
-@code{@var{parent}-abbrev-table}, if it is not already set.
-
-@item
-The new mode has its own mode hook, @code{@var{variant}-hook},
-which it runs in standard fashion as the very last thing that it does.
-(The new mode also runs the mode hook of @var{parent} as part
-of calling @var{parent}.)
-@end itemize
-
-In addition, you can specify how to override other aspects of
-@var{parent} with @var{body}. The command @var{variant}
-evaluates the forms in @var{body} after setting up all its usual
-overrides, just before running @code{@var{variant}-hook}.
-
-The argument @var{docstring} specifies the documentation string for the
-new mode. If you omit @var{docstring}, @code{define-derived-mode}
-generates a documentation string.
-
-Here is a hypothetical example:
-
-@example
-(define-derived-mode hypertext-mode
- text-mode "Hypertext"
- "Major mode for hypertext.
-\\@{hypertext-mode-map@}"
- (setq case-fold-search nil))
-
-(define-key hypertext-mode-map
- [down-mouse-3] 'do-hyper-link)
-@end example
-@end defmac
-
-@node Minor Modes
-@section Minor Modes
-@cindex minor mode
-
- A @dfn{minor mode} provides features that users may enable or disable
-independently of the choice of major mode. Minor modes can be enabled
-individually or in combination. Minor modes would be better named
-``Generally available, optional feature modes'' except that such a name is
-unwieldy.
-
- A minor mode is not usually a modification of single major mode. For
-example, Auto Fill mode may be used in any major mode that permits text
-insertion. To be general, a minor mode must be effectively independent
-of the things major modes do.
-
- A minor mode is often much more difficult to implement than a major
-mode. One reason is that you should be able to activate and deactivate
-minor modes in any order. A minor mode should be able to have its
-desired effect regardless of the major mode and regardless of the other
-minor modes in effect.
-
- Often the biggest problem in implementing a minor mode is finding a
-way to insert the necessary hook into the rest of Emacs. Minor mode
-keymaps make this easier than it used to be.
-
-@menu
-* Minor Mode Conventions:: Tips for writing a minor mode.
-* Keymaps and Minor Modes:: How a minor mode can have its own keymap.
-@end menu
-
-@node Minor Mode Conventions
-@subsection Conventions for Writing Minor Modes
-@cindex minor mode conventions
-@cindex conventions for writing minor modes
-
- There are conventions for writing minor modes just as there are for
-major modes. Several of the major mode conventions apply to minor
-modes as well: those regarding the name of the mode initialization
-function, the names of global symbols, and the use of keymaps and
-other tables.
-
- In addition, there are several conventions that are specific to
-minor modes.
-
-@itemize @bullet
-@item
-@cindex mode variable
-Make a variable whose name ends in @samp{-mode} to represent the minor
-mode. Its value should enable or disable the mode (@code{nil} to
-disable; anything else to enable.) We call this the @dfn{mode
-variable}.
-
-This variable is used in conjunction with the @code{minor-mode-alist} to
-display the minor mode name in the mode line. It can also enable
-or disable a minor mode keymap. Individual commands or hooks can also
-check the variable's value.
-
-If you want the minor mode to be enabled separately in each buffer,
-make the variable buffer-local.
-
-@item
-Define a command whose name is the same as the mode variable.
-Its job is to enable and disable the mode by setting the variable.
-
-The command should accept one optional argument. If the argument is
-@code{nil}, it should toggle the mode (turn it on if it is off, and off
-if it is on). Otherwise, it should turn the mode on if the argument is
-a positive integer, a symbol other than @code{nil} or @code{-}, or a
-list whose @sc{car} is such an integer or symbol; it should turn the
-mode off otherwise.
-
-Here is an example taken from the definition of @code{transient-mark-mode}.
-It shows the use of @code{transient-mark-mode} as a variable that enables or
-disables the mode's behavior, and also shows the proper way to toggle,
-enable or disable the minor mode based on the raw prefix argument value.
-
-@smallexample
-@group
-(setq transient-mark-mode
- (if (null arg) (not transient-mark-mode)
- (> (prefix-numeric-value arg) 0)))
-@end group
-@end smallexample
-
-@item
-Add an element to @code{minor-mode-alist} for each minor mode
-(@pxref{Mode Line Variables}). This element should be a list of the
-following form:
-
-@smallexample
-(@var{mode-variable} @var{string})
-@end smallexample
-
-Here @var{mode-variable} is the variable that controls enabling of the
-minor mode, and @var{string} is a short string, starting with a space,
-to represent the mode in the mode line. These strings must be short so
-that there is room for several of them at once.
-
-When you add an element to @code{minor-mode-alist}, use @code{assq} to
-check for an existing element, to avoid duplication. For example:
-
-@smallexample
-@group
-(or (assq 'leif-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(leif-mode " Leif") minor-mode-alist)))
-@end group
-@end smallexample
-@end itemize
-
-@node Keymaps and Minor Modes
-@subsection Keymaps and Minor Modes
-
- Each minor mode can have its own keymap, which is active when the mode
-is enabled. To set up a keymap for a minor mode, add an element to the
-alist @code{minor-mode-map-alist}. @xref{Active Keymaps}.
-
-@cindex @code{self-insert-command}, minor modes
-One use of minor mode keymaps is to modify the behavior of certain
-self-inserting characters so that they do something else as well as
-self-insert. In general, this is the only way to do that, since the
-facilities for customizing @code{self-insert-command} are limited to
-special cases (designed for abbrevs and Auto Fill mode). (Do not try
-substituting your own definition of @code{self-insert-command} for the
-standard one. The editor command loop handles this function specially.)
-
-@node Mode Line Format
-@section Mode Line Format
-@cindex mode line
-
- Each Emacs window (aside from minibuffer windows) includes a mode line,
-which displays status information about the buffer displayed in the
-window. The mode line contains information about the buffer, such as its
-name, associated file, depth of recursive editing, and the major and
-minor modes.
-
- This section describes how the contents of the mode line are
-controlled. It is in the chapter on modes because much of the
-information displayed in the mode line relates to the enabled major and
-minor modes.
-
- @code{mode-line-format} is a buffer-local variable that holds a
-template used to display the mode line of the current buffer. All
-windows for the same buffer use the same @code{mode-line-format} and
-their mode lines appear the same (except for scrolling percentages and
-line numbers).
-
- The mode line of a window is normally updated whenever a different
-buffer is shown in the window, or when the buffer's modified-status
-changes from @code{nil} to @code{t} or vice-versa. If you modify any of
-the variables referenced by @code{mode-line-format} (@pxref{Mode Line
-Variables}), you may want to force an update of the mode line so as to
-display the new information.
-
-@c Emacs 19 feature
-@defun force-mode-line-update
-Force redisplay of the current buffer's mode line.
-@end defun
-
- The mode line is usually displayed in inverse video; see
-@code{mode-line-inverse-video} in @ref{Inverse Video}.
-
-@menu
-* Mode Line Data:: The data structure that controls the mode line.
-* Mode Line Variables:: Variables used in that data structure.
-* %-Constructs:: Putting information into a mode line.
-@end menu
-
-@node Mode Line Data
-@subsection The Data Structure of the Mode Line
-@cindex mode line construct
-
- The mode line contents are controlled by a data structure of lists,
-strings, symbols, and numbers kept in the buffer-local variable
-@code{mode-line-format}. The data structure is called a @dfn{mode line
-construct}, and it is built in recursive fashion out of simpler mode line
-constructs. The same data structure is used for constructing
-frame titles (@pxref{Frame Titles}).
-
-@defvar mode-line-format
-The value of this variable is a mode line construct with overall
-responsibility for the mode line format. The value of this variable
-controls which other variables are used to form the mode line text, and
-where they appear.
-@end defvar
-
- A mode line construct may be as simple as a fixed string of text, but
-it usually specifies how to use other variables to construct the text.
-Many of these variables are themselves defined to have mode line
-constructs as their values.
-
- The default value of @code{mode-line-format} incorporates the values
-of variables such as @code{mode-name} and @code{minor-mode-alist}.
-Because of this, very few modes need to alter @code{mode-line-format}.
-For most purposes, it is sufficient to alter the variables referenced by
-@code{mode-line-format}.
-
- A mode line construct may be a list, a symbol, or a string. If the
-value is a list, each element may be a list, a symbol, or a string.
-
-@table @code
-@cindex percent symbol in mode line
-@item @var{string}
-A string as a mode line construct is displayed verbatim in the mode line
-except for @dfn{@code{%}-constructs}. Decimal digits after the @samp{%}
-specify the field width for space filling on the right (i.e., the data
-is left justified). @xref{%-Constructs}.
-
-@item @var{symbol}
-A symbol as a mode line construct stands for its value. The value of
-@var{symbol} is used as a mode line construct, in place of @var{symbol}.
-However, the symbols @code{t} and @code{nil} are ignored; so is any
-symbol whose value is void.
-
-There is one exception: if the value of @var{symbol} is a string, it is
-displayed verbatim: the @code{%}-constructs are not recognized.
-
-@item (@var{string} @var{rest}@dots{}) @r{or} (@var{list} @var{rest}@dots{})
-A list whose first element is a string or list means to process all the
-elements recursively and concatenate the results. This is the most
-common form of mode line construct.
-
-@item (@var{symbol} @var{then} @var{else})
-A list whose first element is a symbol is a conditional. Its meaning
-depends on the value of @var{symbol}. If the value is non-@code{nil},
-the second element, @var{then}, is processed recursively as a mode line
-element. But if the value of @var{symbol} is @code{nil}, the third
-element, @var{else}, is processed recursively. You may omit @var{else};
-then the mode line element displays nothing if the value of @var{symbol}
-is @code{nil}.
-
-@item (@var{width} @var{rest}@dots{})
-A list whose first element is an integer specifies truncation or
-padding of the results of @var{rest}. The remaining elements
-@var{rest} are processed recursively as mode line constructs and
-concatenated together. Then the result is space filled (if
-@var{width} is positive) or truncated (to @minus{}@var{width} columns,
-if @var{width} is negative) on the right.
-
-For example, the usual way to show what percentage of a buffer is above
-the top of the window is to use a list like this: @code{(-3 "%p")}.
-@end table
-
- If you do alter @code{mode-line-format} itself, the new value should
-use the same variables that appear in the default value (@pxref{Mode
-Line Variables}), rather than duplicating their contents or displaying
-the information in another fashion. This way, customizations made by
-the user or by Lisp programs (such as @code{display-time} and major
-modes) via changes to those variables remain effective.
-
-@cindex Shell mode @code{mode-line-format}
- Here is an example of a @code{mode-line-format} that might be
-useful for @code{shell-mode}, since it contains the hostname and default
-directory.
-
-@example
-@group
-(setq mode-line-format
- (list ""
- 'mode-line-modified
- "%b--"
-@end group
- (getenv "HOST") ; @r{One element is not constant.}
- ":"
- 'default-directory
- " "
- 'global-mode-string
- " %[("
- 'mode-name
- 'mode-line-process
- 'minor-mode-alist
- "%n"
- ")%]----"
-@group
- '(line-number-mode "L%l--")
- '(-3 . "%p")
- "-%-"))
-@end group
-@end example
-
-@node Mode Line Variables
-@subsection Variables Used in the Mode Line
-
- This section describes variables incorporated by the
-standard value of @code{mode-line-format} into the text of the mode
-line. There is nothing inherently special about these variables; any
-other variables could have the same effects on the mode line if
-@code{mode-line-format} were changed to use them.
-
-@defvar mode-line-modified
-This variable holds the value of the mode-line construct that displays
-whether the current buffer is modified.
-
-The default value of @code{mode-line-modified} is @code{("--%1*%1+-")}.
-This means that the mode line displays @samp{--**-} if the buffer is
-modified, @samp{-----} if the buffer is not modified, @samp{--%%-} if
-the buffer is read only, and @samp{--%*--} if the buffer is read only
-and modified.
-
-Changing this variable does not force an update of the mode line.
-@end defvar
-
-@defvar mode-line-buffer-identification
-This variable identifies the buffer being displayed in the window. Its
-default value is @code{("%F: %17b")}, which means that it usually
-displays @samp{Emacs:} followed by seventeen characters of the buffer
-name. (In a terminal frame, it displays the frame name instead of
-@samp{Emacs}; this has the effect of showing the frame number.) You may
-want to change this in modes such as Rmail that do not behave like a
-``normal'' Emacs.
-@end defvar
-
-@defvar global-mode-string
-This variable holds a mode line spec that appears in the mode line by
-default, just after the buffer name. The command @code{display-time}
-sets @code{global-mode-string} to refer to the variable
-@code{display-time-string}, which holds a string containing the time and
-load information.
-
-The @samp{%M} construct substitutes the value of
-@code{global-mode-string}, but this is obsolete, since the variable is
-included directly in the mode line.
-@end defvar
-
-@defvar mode-name
-This buffer-local variable holds the ``pretty'' name of the current
-buffer's major mode. Each major mode should set this variable so that the
-mode name will appear in the mode line.
-@end defvar
-
-@defvar minor-mode-alist
-This variable holds an association list whose elements specify how the
-mode line should indicate that a minor mode is active. Each element of
-the @code{minor-mode-alist} should be a two-element list:
-
-@example
-(@var{minor-mode-variable} @var{mode-line-string})
-@end example
-
-More generally, @var{mode-line-string} can be any mode line spec. It
-appears in the mode line when the value of @var{minor-mode-variable} is
-non-@code{nil}, and not otherwise. These strings should begin with
-spaces so that they don't run together. Conventionally, the
-@var{minor-mode-variable} for a specific mode is set to a non-@code{nil}
-value when that minor mode is activated.
-
-The default value of @code{minor-mode-alist} is:
-
-@example
-@group
-minor-mode-alist
-@result{} ((vc-mode vc-mode)
- (abbrev-mode " Abbrev")
- (overwrite-mode overwrite-mode)
- (auto-fill-function " Fill")
- (defining-kbd-macro " Def")
- (isearch-mode isearch-mode))
-@end group
-@end example
-
-@code{minor-mode-alist} is not buffer-local. The variables mentioned
-in the alist should be buffer-local if the minor mode can be enabled
-separately in each buffer.
-@end defvar
-
-@defvar mode-line-process
-This buffer-local variable contains the mode line information on process
-status in modes used for communicating with subprocesses. It is
-displayed immediately following the major mode name, with no intervening
-space. For example, its value in the @samp{*shell*} buffer is
-@code{(":@: %s")}, which allows the shell to display its status along
-with the major mode as: @samp{(Shell:@: run)}. Normally this variable
-is @code{nil}.
-@end defvar
-
-@defvar default-mode-line-format
-This variable holds the default @code{mode-line-format} for buffers
-that do not override it. This is the same as @code{(default-value
-'mode-line-format)}.
-
-The default value of @code{default-mode-line-format} is:
-
-@example
-@group
-(""
- mode-line-modified
- mode-line-buffer-identification
- " "
- global-mode-string
- " %[("
- mode-name
-@end group
-@group
- mode-line-process
- minor-mode-alist
- "%n"
- ")%]----"
- (line-number-mode "L%l--")
- (-3 . "%p")
- "-%-")
-@end group
-@end example
-@end defvar
-
-@defvar vc-mode
-The variable @code{vc-mode}, local in each buffer, records whether the
-buffer's visited file is maintained with version control, and, if so,
-which kind. Its value is @code{nil} for no version control, or a string
-that appears in the mode line.
-@end defvar
-
-@node %-Constructs
-@subsection @code{%}-Constructs in the Mode Line
-
- The following table lists the recognized @code{%}-constructs and what
-they mean. In any construct except @samp{%%}, you can add a decimal
-integer after the @samp{%} to specify how many characters to display.
-
-@table @code
-@item %b
-The current buffer name, obtained with the @code{buffer-name} function.
-@xref{Buffer Names}.
-
-@item %f
-The visited file name, obtained with the @code{buffer-file-name}
-function. @xref{Buffer File Name}.
-
-@item %F
-The name of the selected frame.
-
-@item %c
-The current column number of point.
-
-@item %l
-The current line number of point.
-
-@item %*
-@samp{%} if the buffer is read only (see @code{buffer-read-only}); @*
-@samp{*} if the buffer is modified (see @code{buffer-modified-p}); @*
-@samp{-} otherwise. @xref{Buffer Modification}.
-
-@item %+
-@samp{*} if the buffer is modified (see @code{buffer-modified-p}); @*
-@samp{%} if the buffer is read only (see @code{buffer-read-only}); @*
-@samp{-} otherwise. This differs from @samp{%*} only for a modified
-read-only buffer. @xref{Buffer Modification}.
-
-@item %&
-@samp{*} if the buffer is modified, and @samp{-} otherwise.
-
-@item %s
-The status of the subprocess belonging to the current buffer, obtained with
-@code{process-status}. @xref{Process Information}.
-
-@item %t
-Whether the visited file is a text file or a binary file. (This is a
-meaningful distinction only on certain operating systems.)
-
-@item %p
-The percentage of the buffer text above the @strong{top} of window, or
-@samp{Top}, @samp{Bottom} or @samp{All}.
-
-@item %P
-The percentage of the buffer text that is above the @strong{bottom} of
-the window (which includes the text visible in the window, as well as
-the text above the top), plus @samp{Top} if the top of the buffer is
-visible on screen; or @samp{Bottom} or @samp{All}.
-
-@item %n
-@samp{Narrow} when narrowing is in effect; nothing otherwise (see
-@code{narrow-to-region} in @ref{Narrowing}).
-
-@item %[
-An indication of the depth of recursive editing levels (not counting
-minibuffer levels): one @samp{[} for each editing level.
-@xref{Recursive Editing}.
-
-@item %]
-One @samp{]} for each recursive editing level (not counting minibuffer
-levels).
-
-@item %%
-The character @samp{%}---this is how to include a literal @samp{%} in a
-string in which @code{%}-constructs are allowed.
-
-@item %-
-Dashes sufficient to fill the remainder of the mode line.
-@end table
-
-The following two @code{%}-constructs are still supported, but they are
-obsolete, since you can get the same results with the variables
-@code{mode-name} and @code{global-mode-string}.
-
-@table @code
-@item %m
-The value of @code{mode-name}.
-
-@item %M
-The value of @code{global-mode-string}. Currently, only
-@code{display-time} modifies the value of @code{global-mode-string}.
-@end table
-
-@node Hooks
-@section Hooks
-@cindex hooks
-
- A @dfn{hook} is a variable where you can store a function or functions
-to be called on a particular occasion by an existing program. Emacs
-provides hooks for the sake of customization. Most often, hooks are set
-up in the @file{.emacs} file, but Lisp programs can set them also.
-@xref{Standard Hooks}, for a list of standard hook variables.
-
- Most of the hooks in Emacs are @dfn{normal hooks}. These variables
-contain lists of functions to be called with no arguments. When the
-hook name ends in @samp{-hook}, that tells you it is normal. We try to
-make all hooks normal, as much as possible, so that you can use them in
-a uniform way.
-
- Every major mode function is supposed to run a normal hook called the
-@dfn{mode hook} as the last step of initialization. This makes it easy
-for a user to customize the behavior of the mode, by overriding the
-local variable assignments already made by the mode. But hooks are used
-in other contexts too. For example, the hook @code{suspend-hook} runs
-just before Emacs suspends itself (@pxref{Suspending Emacs}).
-
- The recommended way to add a hook function to a normal hook is by
-calling @code{add-hook} (see below). The hook functions may be any of
-the valid kinds of functions that @code{funcall} accepts (@pxref{What Is
-a Function}). Most normal hook variables are initially void;
-@code{add-hook} knows how to deal with this.
-
- If the hook variable's name does not end with @samp{-hook}, that
-indicates it is probably an abnormal hook; you should look at its
-documentation to see how to use the hook properly.
-
- If the variable's name ends in @samp{-functions} or @samp{-hooks},
-then the value is a list of functions, but it is abnormal in that either
-these functions are called with arguments or their values are used in
-some way. You can use @code{add-hook} to add a function to the list,
-but you must take care in writing the function. (A few of these
-variables are actually normal hooks which were named before we
-established the convention of using @samp{-hook} for them.)
-
- If the variable's name ends in @samp{-function}, then its value
-is just a single function, not a list of functions.
-
- Here's an expression that uses a mode hook to turn on Auto Fill mode
-when in Lisp Interaction mode:
-
-@example
-(add-hook 'lisp-interaction-mode-hook 'turn-on-auto-fill)
-@end example
-
- The next example shows how to use a hook to customize the way Emacs
-formats C code. (People often have strong personal preferences for one
-format or another.) Here the hook function is an anonymous lambda
-expression.
-
-@cindex lambda expression in hook
-@example
-@group
-(add-hook 'c-mode-hook
- (function (lambda ()
- (setq c-indent-level 4
- c-argdecl-indent 0
- c-label-offset -4
-@end group
-@group
- c-continued-statement-indent 0
- c-brace-offset 0
- comment-column 40))))
-
-(setq c++-mode-hook c-mode-hook)
-@end group
-@end example
-
- At the appropriate time, Emacs uses the @code{run-hooks} function to
-run particular hooks. This function calls the hook functions that have
-been added with @code{add-hook}.
-
-@defun run-hooks &rest hookvar
-This function takes one or more hook variable names as arguments, and
-runs each hook in turn. Each @var{hookvar} argument should be a symbol
-that is a hook variable. These arguments are processed in the order
-specified.
-
-If a hook variable has a non-@code{nil} value, that value may be a
-function or a list of functions. If the value is a function (either a
-lambda expression or a symbol with a function definition), it is
-called. If it is a list, the elements are called, in order.
-The hook functions are called with no arguments.
-
-For example, here's how @code{emacs-lisp-mode} runs its mode hook:
-
-@example
-(run-hooks 'emacs-lisp-mode-hook)
-@end example
-@end defun
-
-@defun add-hook hook function &optional append local
-This function is the handy way to add function @var{function} to hook
-variable @var{hook}. The argument @var{function} may be any valid Lisp
-function with the proper number of arguments. For example,
-
-@example
-(add-hook 'text-mode-hook 'my-text-hook-function)
-@end example
-
-@noindent
-adds @code{my-text-hook-function} to the hook called @code{text-mode-hook}.
-
-You can use @code{add-hook} for abnormal hooks as well as for normal
-hooks.
-
-It is best to design your hook functions so that the order in which they
-are executed does not matter. Any dependence on the order is ``asking
-for trouble.'' However, the order is predictable: normally,
-@var{function} goes at the front of the hook list, so it will be
-executed first (barring another @code{add-hook} call).
-
-If the optional argument @var{append} is non-@code{nil}, the new hook
-function goes at the end of the hook list and will be executed last.
-
-If @var{local} is non-@code{nil}, that says to make the new hook
-function local to the current buffer. Before you can do this, you must
-make the hook itself buffer-local by calling @code{make-local-hook}
-(@strong{not} @code{make-local-variable}). If the hook itself is not
-buffer-local, then the value of @var{local} makes no difference---the
-hook function is always global.
-@end defun
-
-@defun remove-hook hook function &optional local
-This function removes @var{function} from the hook variable @var{hook}.
-
-If @var{local} is non-@code{nil}, that says to remove @var{function}
-from the local hook list instead of from the global hook list. If the
-hook itself is not buffer-local, then the value of @var{local} makes no
-difference.
-@end defun
-
-@defun make-local-hook hook
-This function makes the hook variable @code{hook} local to the current
-buffer. When a hook variable is local, it can have local and global
-hook functions, and @code{run-hooks} runs all of them.
-
-This function works by making @code{t} an element of the buffer-local
-value. That serves as a flag to use the hook functions in the default
-value of the hook variable as well as those in the local value. Since
-@code{run-hooks} understands this flag, @code{make-local-hook} works
-with all normal hooks. It works for only some non-normal hooks---those
-whose callers have been updated to understand this meaning of @code{t}.
-
-Do not use @code{make-local-variable} directly for hook variables; it is
-not sufficient.
-@end defun
diff --git a/lispref/numbers.texi b/lispref/numbers.texi
deleted file mode 100644
index 6189e3da42f..00000000000
--- a/lispref/numbers.texi
+++ /dev/null
@@ -1,1034 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/numbers
-@node Numbers, Strings and Characters, Lisp Data Types, Top
-@chapter Numbers
-@cindex integers
-@cindex numbers
-
- GNU Emacs supports two numeric data types: @dfn{integers} and
-@dfn{floating point numbers}. Integers are whole numbers such as
-@minus{}3, 0, 7, 13, and 511. Their values are exact. Floating point
-numbers are numbers with fractional parts, such as @minus{}4.5, 0.0, or
-2.71828. They can also be expressed in exponential notation:
-1.5e2 equals 150; in this example, @samp{e2} stands for ten to the
-second power, and is multiplied by 1.5. Floating point values are not
-exact; they have a fixed, limited amount of precision.
-
- Support for floating point numbers is a new feature in Emacs 19, and it
-is controlled by a separate compilation option, so you may encounter a site
-where Emacs does not support them.
-
-@menu
-* Integer Basics:: Representation and range of integers.
-* Float Basics:: Representation and range of floating point.
-* Predicates on Numbers:: Testing for numbers.
-* Comparison of Numbers:: Equality and inequality predicates.
-* Numeric Conversions:: Converting float to integer and vice versa.
-* Arithmetic Operations:: How to add, subtract, multiply and divide.
-* Rounding Operations:: Explicitly rounding floating point numbers.
-* Bitwise Operations:: Logical and, or, not, shifting.
-* Math Functions:: Trig, exponential and logarithmic functions.
-* Random Numbers:: Obtaining random integers, predictable or not.
-@end menu
-
-@node Integer Basics
-@comment node-name, next, previous, up
-@section Integer Basics
-
- The range of values for an integer depends on the machine. The
-minimum range is @minus{}134217728 to 134217727 (28 bits; i.e.,
-@ifinfo
--2**27
-@end ifinfo
-@tex
-$-2^{27}$
-@end tex
-to
-@ifinfo
-2**27 - 1),
-@end ifinfo
-@tex
-$2^{27}-1$),
-@end tex
-but some machines may provide a wider range. Many examples in this
-chapter assume an integer has 28 bits.
-@cindex overflow
-
- The Lisp reader reads an integer as a sequence of digits with optional
-initial sign and optional final period.
-
-@example
- 1 ; @r{The integer 1.}
- 1. ; @r{The integer 1.}
-+1 ; @r{Also the integer 1.}
--1 ; @r{The integer @minus{}1.}
- 268435457 ; @r{Also the integer 1, due to overflow.}
- 0 ; @r{The integer 0.}
--0 ; @r{The integer 0.}
-@end example
-
- To understand how various functions work on integers, especially the
-bitwise operators (@pxref{Bitwise Operations}), it is often helpful to
-view the numbers in their binary form.
-
- In 28-bit binary, the decimal integer 5 looks like this:
-
-@example
-0000 0000 0000 0000 0000 0000 0101
-@end example
-
-@noindent
-(We have inserted spaces between groups of 4 bits, and two spaces
-between groups of 8 bits, to make the binary integer easier to read.)
-
- The integer @minus{}1 looks like this:
-
-@example
-1111 1111 1111 1111 1111 1111 1111
-@end example
-
-@noindent
-@cindex two's complement
-@minus{}1 is represented as 28 ones. (This is called @dfn{two's
-complement} notation.)
-
- The negative integer, @minus{}5, is creating by subtracting 4 from
-@minus{}1. In binary, the decimal integer 4 is 100. Consequently,
-@minus{}5 looks like this:
-
-@example
-1111 1111 1111 1111 1111 1111 1011
-@end example
-
- In this implementation, the largest 28-bit binary integer value is
-134,217,727 in decimal. In binary, it looks like this:
-
-@example
-0111 1111 1111 1111 1111 1111 1111
-@end example
-
- Since the arithmetic functions do not check whether integers go
-outside their range, when you add 1 to 134,217,727, the value is the
-negative integer @minus{}134,217,728:
-
-@example
-(+ 1 134217727)
- @result{} -134217728
- @result{} 1000 0000 0000 0000 0000 0000 0000
-@end example
-
- Many of the following functions accept markers for arguments as well
-as integers. (@xref{Markers}.) More precisely, the actual arguments to
-such functions may be either integers or markers, which is why we often
-give these arguments the name @var{int-or-marker}. When the argument
-value is a marker, its position value is used and its buffer is ignored.
-
-@ignore
- In version 19, except where @emph{integer} is specified as an
-argument, all of the functions for markers and integers also work for
-floating point numbers.
-@end ignore
-
-@node Float Basics
-@section Floating Point Basics
-
-@cindex @code{LISP_FLOAT_TYPE} configuration macro
- Emacs version 19 supports floating point numbers, if compiled with the
-macro @code{LISP_FLOAT_TYPE} defined. The precise range of floating
-point numbers is machine-specific; it is the same as the range of the C
-data type @code{double} on the machine in question.
-
- The printed representation for floating point numbers requires either
-a decimal point (with at least one digit following), an exponent, or
-both. For example, @samp{1500.0}, @samp{15e2}, @samp{15.0e2},
-@samp{1.5e3}, and @samp{.15e4} are five ways of writing a floating point
-number whose value is 1500. They are all equivalent. You can also use
-a minus sign to write negative floating point numbers, as in
-@samp{-1.0}.
-
-@cindex IEEE floating point
-@cindex positive infinity
-@cindex negative infinity
-@cindex infinity
-@cindex NaN
- Most modern computers support the IEEE floating point standard, which
-provides for positive infinity and negative infinity as floating point
-values. It also provides for a class of values called NaN or
-``not-a-number''; numerical functions return such values in cases where
-there is no correct answer. For example, @code{(sqrt -1.0)} returns a
-NaN. For practical purposes, there's no significant difference between
-different NaN values in Emacs Lisp, and there's no rule for precisely
-which NaN value should be used in a particular case, so this manual
-doesn't try to distinguish them. Emacs Lisp has no read syntax for NaNs
-or infinities; perhaps we should create a syntax in the future.
-
- You can use @code{logb} to extract the binary exponent of a floating
-point number (or estimate the logarithm of an integer):
-
-@defun logb number
-This function returns the binary exponent of @var{number}. More
-precisely, the value is the logarithm of @var{number} base 2, rounded
-down to an integer.
-@end defun
-
-@node Predicates on Numbers
-@section Type Predicates for Numbers
-
- The functions in this section test whether the argument is a number or
-whether it is a certain sort of number. The functions @code{integerp}
-and @code{floatp} can take any type of Lisp object as argument (the
-predicates would not be of much use otherwise); but the @code{zerop}
-predicate requires a number as its argument. See also
-@code{integer-or-marker-p} and @code{number-or-marker-p}, in
-@ref{Predicates on Markers}.
-
-@defun floatp object
-This predicate tests whether its argument is a floating point
-number and returns @code{t} if so, @code{nil} otherwise.
-
-@code{floatp} does not exist in Emacs versions 18 and earlier.
-@end defun
-
-@defun integerp object
-This predicate tests whether its argument is an integer, and returns
-@code{t} if so, @code{nil} otherwise.
-@end defun
-
-@defun numberp object
-This predicate tests whether its argument is a number (either integer or
-floating point), and returns @code{t} if so, @code{nil} otherwise.
-@end defun
-
-@defun wholenump object
-@cindex natural numbers
-The @code{wholenump} predicate (whose name comes from the phrase
-``whole-number-p'') tests to see whether its argument is a nonnegative
-integer, and returns @code{t} if so, @code{nil} otherwise. 0 is
-considered non-negative.
-
-@findex natnump
-@code{natnump} is an obsolete synonym for @code{wholenump}.
-@end defun
-
-@defun zerop number
-This predicate tests whether its argument is zero, and returns @code{t}
-if so, @code{nil} otherwise. The argument must be a number.
-
-These two forms are equivalent: @code{(zerop x)} @equiv{} @code{(= x 0)}.
-@end defun
-
-@node Comparison of Numbers
-@section Comparison of Numbers
-@cindex number equality
-
- To test numbers for numerical equality, you should normally use
-@code{=}, not @code{eq}. There can be many distinct floating point
-number objects with the same numeric value. If you use @code{eq} to
-compare them, then you test whether two values are the same
-@emph{object}. By contrast, @code{=} compares only the numeric values
-of the objects.
-
- At present, each integer value has a unique Lisp object in Emacs Lisp.
-Therefore, @code{eq} is equivalent @code{=} where integers are
-concerned. It is sometimes convenient to use @code{eq} for comparing an
-unknown value with an integer, because @code{eq} does not report an
-error if the unknown value is not a number---it accepts arguments of any
-type. By contrast, @code{=} signals an error if the arguments are not
-numbers or markers. However, it is a good idea to use @code{=} if you
-can, even for comparing integers, just in case we change the
-representation of integers in a future Emacs version.
-
- There is another wrinkle: because floating point arithmetic is not
-exact, it is often a bad idea to check for equality of two floating
-point values. Usually it is better to test for approximate equality.
-Here's a function to do this:
-
-@example
-(defvar fuzz-factor 1.0e-6)
-(defun approx-equal (x y)
- (or (and (= x 0) (= y 0))
- (< (/ (abs (- x y))
- (max (abs x) (abs y)))
- fuzz-factor)))
-@end example
-
-@cindex CL note---integers vrs @code{eq}
-@quotation
-@b{Common Lisp note:} Comparing numbers in Common Lisp always requires
-@code{=} because Common Lisp implements multi-word integers, and two
-distinct integer objects can have the same numeric value. Emacs Lisp
-can have just one integer object for any given value because it has a
-limited range of integer values.
-@end quotation
-
-@defun = number-or-marker1 number-or-marker2
-This function tests whether its arguments are numerically equal, and
-returns @code{t} if so, @code{nil} otherwise.
-@end defun
-
-@defun /= number-or-marker1 number-or-marker2
-This function tests whether its arguments are numerically equal, and
-returns @code{t} if they are not, and @code{nil} if they are.
-@end defun
-
-@defun < number-or-marker1 number-or-marker2
-This function tests whether its first argument is strictly less than
-its second argument. It returns @code{t} if so, @code{nil} otherwise.
-@end defun
-
-@defun <= number-or-marker1 number-or-marker2
-This function tests whether its first argument is less than or equal
-to its second argument. It returns @code{t} if so, @code{nil}
-otherwise.
-@end defun
-
-@defun > number-or-marker1 number-or-marker2
-This function tests whether its first argument is strictly greater
-than its second argument. It returns @code{t} if so, @code{nil}
-otherwise.
-@end defun
-
-@defun >= number-or-marker1 number-or-marker2
-This function tests whether its first argument is greater than or
-equal to its second argument. It returns @code{t} if so, @code{nil}
-otherwise.
-@end defun
-
-@defun max number-or-marker &rest numbers-or-markers
-This function returns the largest of its arguments.
-
-@example
-(max 20)
- @result{} 20
-(max 1 2.5)
- @result{} 2.5
-(max 1 3 2.5)
- @result{} 3
-@end example
-@end defun
-
-@defun min number-or-marker &rest numbers-or-markers
-This function returns the smallest of its arguments.
-
-@example
-(min -4 1)
- @result{} -4
-@end example
-@end defun
-
-@node Numeric Conversions
-@section Numeric Conversions
-@cindex rounding in conversions
-
-To convert an integer to floating point, use the function @code{float}.
-
-@defun float number
-This returns @var{number} converted to floating point.
-If @var{number} is already a floating point number, @code{float} returns
-it unchanged.
-@end defun
-
-There are four functions to convert floating point numbers to integers;
-they differ in how they round. These functions accept integer arguments
-also, and return such arguments unchanged.
-
-@defun truncate number
-This returns @var{number}, converted to an integer by rounding towards
-zero.
-@end defun
-
-@defun floor number &optional divisor
-This returns @var{number}, converted to an integer by rounding downward
-(towards negative infinity).
-
-If @var{divisor} is specified, @var{number} is divided by @var{divisor}
-before the floor is taken; this is the division operation that
-corresponds to @code{mod}. An @code{arith-error} results if
-@var{divisor} is 0.
-@end defun
-
-@defun ceiling number
-This returns @var{number}, converted to an integer by rounding upward
-(towards positive infinity).
-@end defun
-
-@defun round number
-This returns @var{number}, converted to an integer by rounding towards the
-nearest integer. Rounding a value equidistant between two integers
-may choose the integer closer to zero, or it may prefer an even integer,
-depending on your machine.
-@end defun
-
-@node Arithmetic Operations
-@section Arithmetic Operations
-
- Emacs Lisp provides the traditional four arithmetic operations:
-addition, subtraction, multiplication, and division. Remainder and modulus
-functions supplement the division functions. The functions to
-add or subtract 1 are provided because they are traditional in Lisp and
-commonly used.
-
- All of these functions except @code{%} return a floating point value
-if any argument is floating.
-
- It is important to note that in GNU Emacs Lisp, arithmetic functions
-do not check for overflow. Thus @code{(1+ 134217727)} may evaluate to
-@minus{}134217728, depending on your hardware.
-
-@defun 1+ number-or-marker
-This function returns @var{number-or-marker} plus 1.
-For example,
-
-@example
-(setq foo 4)
- @result{} 4
-(1+ foo)
- @result{} 5
-@end example
-
-This function is not analogous to the C operator @code{++}---it does not
-increment a variable. It just computes a sum. Thus, if we continue,
-
-@example
-foo
- @result{} 4
-@end example
-
-If you want to increment the variable, you must use @code{setq},
-like this:
-
-@example
-(setq foo (1+ foo))
- @result{} 5
-@end example
-@end defun
-
-@defun 1- number-or-marker
-This function returns @var{number-or-marker} minus 1.
-@end defun
-
-@defun abs number
-This returns the absolute value of @var{number}.
-@end defun
-
-@defun + &rest numbers-or-markers
-This function adds its arguments together. When given no arguments,
-@code{+} returns 0.
-
-@example
-(+)
- @result{} 0
-(+ 1)
- @result{} 1
-(+ 1 2 3 4)
- @result{} 10
-@end example
-@end defun
-
-@defun - &optional number-or-marker &rest other-numbers-or-markers
-The @code{-} function serves two purposes: negation and subtraction.
-When @code{-} has a single argument, the value is the negative of the
-argument. When there are multiple arguments, @code{-} subtracts each of
-the @var{other-numbers-or-markers} from @var{number-or-marker},
-cumulatively. If there are no arguments, the result is 0.
-
-@example
-(- 10 1 2 3 4)
- @result{} 0
-(- 10)
- @result{} -10
-(-)
- @result{} 0
-@end example
-@end defun
-
-@defun * &rest numbers-or-markers
-This function multiplies its arguments together, and returns the
-product. When given no arguments, @code{*} returns 1.
-
-@example
-(*)
- @result{} 1
-(* 1)
- @result{} 1
-(* 1 2 3 4)
- @result{} 24
-@end example
-@end defun
-
-@defun / dividend divisor &rest divisors
-This function divides @var{dividend} by @var{divisor} and returns the
-quotient. If there are additional arguments @var{divisors}, then it
-divides @var{dividend} by each divisor in turn. Each argument may be a
-number or a marker.
-
-If all the arguments are integers, then the result is an integer too.
-This means the result has to be rounded. On most machines, the result
-is rounded towards zero after each division, but some machines may round
-differently with negative arguments. This is because the Lisp function
-@code{/} is implemented using the C division operator, which also
-permits machine-dependent rounding. As a practical matter, all known
-machines round in the standard fashion.
-
-@cindex @code{arith-error} in division
-If you divide by 0, an @code{arith-error} error is signaled.
-(@xref{Errors}.)
-
-@example
-@group
-(/ 6 2)
- @result{} 3
-@end group
-(/ 5 2)
- @result{} 2
-(/ 25 3 2)
- @result{} 4
-(/ -17 6)
- @result{} -2
-@end example
-
-The result of @code{(/ -17 6)} could in principle be -3 on some
-machines.
-@end defun
-
-@defun % dividend divisor
-@cindex remainder
-This function returns the integer remainder after division of @var{dividend}
-by @var{divisor}. The arguments must be integers or markers.
-
-For negative arguments, the remainder is in principle machine-dependent
-since the quotient is; but in practice, all known machines behave alike.
-
-An @code{arith-error} results if @var{divisor} is 0.
-
-@example
-(% 9 4)
- @result{} 1
-(% -9 4)
- @result{} -1
-(% 9 -4)
- @result{} 1
-(% -9 -4)
- @result{} -1
-@end example
-
-For any two integers @var{dividend} and @var{divisor},
-
-@example
-@group
-(+ (% @var{dividend} @var{divisor})
- (* (/ @var{dividend} @var{divisor}) @var{divisor}))
-@end group
-@end example
-
-@noindent
-always equals @var{dividend}.
-@end defun
-
-@defun mod dividend divisor
-@cindex modulus
-This function returns the value of @var{dividend} modulo @var{divisor};
-in other words, the remainder after division of @var{dividend}
-by @var{divisor}, but with the same sign as @var{divisor}.
-The arguments must be numbers or markers.
-
-Unlike @code{%}, @code{mod} returns a well-defined result for negative
-arguments. It also permits floating point arguments; it rounds the
-quotient downward (towards minus infinity) to an integer, and uses that
-quotient to compute the remainder.
-
-An @code{arith-error} results if @var{divisor} is 0.
-
-@example
-@group
-(mod 9 4)
- @result{} 1
-@end group
-@group
-(mod -9 4)
- @result{} 3
-@end group
-@group
-(mod 9 -4)
- @result{} -3
-@end group
-@group
-(mod -9 -4)
- @result{} -1
-@end group
-@group
-(mod 5.5 2.5)
- @result{} .5
-@end group
-@end example
-
-For any two numbers @var{dividend} and @var{divisor},
-
-@example
-@group
-(+ (mod @var{dividend} @var{divisor})
- (* (floor @var{dividend} @var{divisor}) @var{divisor}))
-@end group
-@end example
-
-@noindent
-always equals @var{dividend}, subject to rounding error if either
-argument is floating point. For @code{floor}, see @ref{Numeric
-Conversions}.
-@end defun
-
-@node Rounding Operations
-@section Rounding Operations
-@cindex rounding without conversion
-
-The functions @code{ffloor}, @code{fceiling}, @code{fround} and
-@code{ftruncate} take a floating point argument and return a floating
-point result whose value is a nearby integer. @code{ffloor} returns the
-nearest integer below; @code{fceiling}, the nearest integer above;
-@code{ftruncate}, the nearest integer in the direction towards zero;
-@code{fround}, the nearest integer.
-
-@defun ffloor float
-This function rounds @var{float} to the next lower integral value, and
-returns that value as a floating point number.
-@end defun
-
-@defun fceiling float
-This function rounds @var{float} to the next higher integral value, and
-returns that value as a floating point number.
-@end defun
-
-@defun ftruncate float
-This function rounds @var{float} towards zero to an integral value, and
-returns that value as a floating point number.
-@end defun
-
-@defun fround float
-This function rounds @var{float} to the nearest integral value,
-and returns that value as a floating point number.
-@end defun
-
-@node Bitwise Operations
-@section Bitwise Operations on Integers
-
- In a computer, an integer is represented as a binary number, a
-sequence of @dfn{bits} (digits which are either zero or one). A bitwise
-operation acts on the individual bits of such a sequence. For example,
-@dfn{shifting} moves the whole sequence left or right one or more places,
-reproducing the same pattern ``moved over''.
-
- The bitwise operations in Emacs Lisp apply only to integers.
-
-@defun lsh integer1 count
-@cindex logical shift
-@code{lsh}, which is an abbreviation for @dfn{logical shift}, shifts the
-bits in @var{integer1} to the left @var{count} places, or to the right
-if @var{count} is negative, bringing zeros into the vacated bits. If
-@var{count} is negative, @code{lsh} shifts zeros into the leftmost
-(most-significant) bit, producing a positive result even if
-@var{integer1} is negative. Contrast this with @code{ash}, below.
-
-Here are two examples of @code{lsh}, shifting a pattern of bits one
-place to the left. We show only the low-order eight bits of the binary
-pattern; the rest are all zero.
-
-@example
-@group
-(lsh 5 1)
- @result{} 10
-;; @r{Decimal 5 becomes decimal 10.}
-00000101 @result{} 00001010
-
-(lsh 7 1)
- @result{} 14
-;; @r{Decimal 7 becomes decimal 14.}
-00000111 @result{} 00001110
-@end group
-@end example
-
-@noindent
-As the examples illustrate, shifting the pattern of bits one place to
-the left produces a number that is twice the value of the previous
-number.
-
-Shifting a pattern of bits two places to the left produces results
-like this (with 8-bit binary numbers):
-
-@example
-@group
-(lsh 3 2)
- @result{} 12
-;; @r{Decimal 3 becomes decimal 12.}
-00000011 @result{} 00001100
-@end group
-@end example
-
-On the other hand, shifting one place to the right looks like this:
-
-@example
-@group
-(lsh 6 -1)
- @result{} 3
-;; @r{Decimal 6 becomes decimal 3.}
-00000110 @result{} 00000011
-@end group
-
-@group
-(lsh 5 -1)
- @result{} 2
-;; @r{Decimal 5 becomes decimal 2.}
-00000101 @result{} 00000010
-@end group
-@end example
-
-@noindent
-As the example illustrates, shifting one place to the right divides the
-value of a positive integer by two, rounding downward.
-
-The function @code{lsh}, like all Emacs Lisp arithmetic functions, does
-not check for overflow, so shifting left can discard significant bits
-and change the sign of the number. For example, left shifting
-134,217,727 produces @minus{}2 on a 28-bit machine:
-
-@example
-(lsh 134217727 1) ; @r{left shift}
- @result{} -2
-@end example
-
-In binary, in the 28-bit implementation, the argument looks like this:
-
-@example
-@group
-;; @r{Decimal 134,217,727}
-0111 1111 1111 1111 1111 1111 1111
-@end group
-@end example
-
-@noindent
-which becomes the following when left shifted:
-
-@example
-@group
-;; @r{Decimal @minus{}2}
-1111 1111 1111 1111 1111 1111 1110
-@end group
-@end example
-@end defun
-
-@defun ash integer1 count
-@cindex arithmetic shift
-@code{ash} (@dfn{arithmetic shift}) shifts the bits in @var{integer1}
-to the left @var{count} places, or to the right if @var{count}
-is negative.
-
-@code{ash} gives the same results as @code{lsh} except when
-@var{integer1} and @var{count} are both negative. In that case,
-@code{ash} puts ones in the empty bit positions on the left, while
-@code{lsh} puts zeros in those bit positions.
-
-Thus, with @code{ash}, shifting the pattern of bits one place to the right
-looks like this:
-
-@example
-@group
-(ash -6 -1) @result{} -3
-;; @r{Decimal @minus{}6 becomes decimal @minus{}3.}
-1111 1111 1111 1111 1111 1111 1010
- @result{}
-1111 1111 1111 1111 1111 1111 1101
-@end group
-@end example
-
-In contrast, shifting the pattern of bits one place to the right with
-@code{lsh} looks like this:
-
-@example
-@group
-(lsh -6 -1) @result{} 134217725
-;; @r{Decimal @minus{}6 becomes decimal 134,217,725.}
-1111 1111 1111 1111 1111 1111 1010
- @result{}
-0111 1111 1111 1111 1111 1111 1101
-@end group
-@end example
-
-Here are other examples:
-
-@c !!! Check if lined up in smallbook format! XDVI shows problem
-@c with smallbook but not with regular book! --rjc 16mar92
-@smallexample
-@group
- ; @r{ 28-bit binary values}
-
-(lsh 5 2) ; 5 = @r{0000 0000 0000 0000 0000 0000 0101}
- @result{} 20 ; = @r{0000 0000 0000 0000 0000 0001 0100}
-@end group
-@group
-(ash 5 2)
- @result{} 20
-(lsh -5 2) ; -5 = @r{1111 1111 1111 1111 1111 1111 1011}
- @result{} -20 ; = @r{1111 1111 1111 1111 1111 1110 1100}
-(ash -5 2)
- @result{} -20
-@end group
-@group
-(lsh 5 -2) ; 5 = @r{0000 0000 0000 0000 0000 0000 0101}
- @result{} 1 ; = @r{0000 0000 0000 0000 0000 0000 0001}
-@end group
-@group
-(ash 5 -2)
- @result{} 1
-@end group
-@group
-(lsh -5 -2) ; -5 = @r{1111 1111 1111 1111 1111 1111 1011}
- @result{} 4194302 ; = @r{0011 1111 1111 1111 1111 1111 1110}
-@end group
-@group
-(ash -5 -2) ; -5 = @r{1111 1111 1111 1111 1111 1111 1011}
- @result{} -2 ; = @r{1111 1111 1111 1111 1111 1111 1110}
-@end group
-@end smallexample
-@end defun
-
-@defun logand &rest ints-or-markers
-@cindex logical and
-@cindex bitwise and
-This function returns the ``logical and'' of the arguments: the
-@var{n}th bit is set in the result if, and only if, the @var{n}th bit is
-set in all the arguments. (``Set'' means that the value of the bit is 1
-rather than 0.)
-
-For example, using 4-bit binary numbers, the ``logical and'' of 13 and
-12 is 12: 1101 combined with 1100 produces 1100.
-In both the binary numbers, the leftmost two bits are set (i.e., they
-are 1's), so the leftmost two bits of the returned value are set.
-However, for the rightmost two bits, each is zero in at least one of
-the arguments, so the rightmost two bits of the returned value are 0's.
-
-@noindent
-Therefore,
-
-@example
-@group
-(logand 13 12)
- @result{} 12
-@end group
-@end example
-
-If @code{logand} is not passed any argument, it returns a value of
-@minus{}1. This number is an identity element for @code{logand}
-because its binary representation consists entirely of ones. If
-@code{logand} is passed just one argument, it returns that argument.
-
-@smallexample
-@group
- ; @r{ 28-bit binary values}
-
-(logand 14 13) ; 14 = @r{0000 0000 0000 0000 0000 0000 1110}
- ; 13 = @r{0000 0000 0000 0000 0000 0000 1101}
- @result{} 12 ; 12 = @r{0000 0000 0000 0000 0000 0000 1100}
-@end group
-
-@group
-(logand 14 13 4) ; 14 = @r{0000 0000 0000 0000 0000 0000 1110}
- ; 13 = @r{0000 0000 0000 0000 0000 0000 1101}
- ; 4 = @r{0000 0000 0000 0000 0000 0000 0100}
- @result{} 4 ; 4 = @r{0000 0000 0000 0000 0000 0000 0100}
-@end group
-
-@group
-(logand)
- @result{} -1 ; -1 = @r{1111 1111 1111 1111 1111 1111 1111}
-@end group
-@end smallexample
-@end defun
-
-@defun logior &rest ints-or-markers
-@cindex logical inclusive or
-@cindex bitwise or
-This function returns the ``inclusive or'' of its arguments: the @var{n}th bit
-is set in the result if, and only if, the @var{n}th bit is set in at least
-one of the arguments. If there are no arguments, the result is zero,
-which is an identity element for this operation. If @code{logior} is
-passed just one argument, it returns that argument.
-
-@smallexample
-@group
- ; @r{ 28-bit binary values}
-
-(logior 12 5) ; 12 = @r{0000 0000 0000 0000 0000 0000 1100}
- ; 5 = @r{0000 0000 0000 0000 0000 0000 0101}
- @result{} 13 ; 13 = @r{0000 0000 0000 0000 0000 0000 1101}
-@end group
-
-@group
-(logior 12 5 7) ; 12 = @r{0000 0000 0000 0000 0000 0000 1100}
- ; 5 = @r{0000 0000 0000 0000 0000 0000 0101}
- ; 7 = @r{0000 0000 0000 0000 0000 0000 0111}
- @result{} 15 ; 15 = @r{0000 0000 0000 0000 0000 0000 1111}
-@end group
-@end smallexample
-@end defun
-
-@defun logxor &rest ints-or-markers
-@cindex bitwise exclusive or
-@cindex logical exclusive or
-This function returns the ``exclusive or'' of its arguments: the
-@var{n}th bit is set in the result if, and only if, the @var{n}th bit is
-set in an odd number of the arguments. If there are no arguments, the
-result is 0, which is an identity element for this operation. If
-@code{logxor} is passed just one argument, it returns that argument.
-
-@smallexample
-@group
- ; @r{ 28-bit binary values}
-
-(logxor 12 5) ; 12 = @r{0000 0000 0000 0000 0000 0000 1100}
- ; 5 = @r{0000 0000 0000 0000 0000 0000 0101}
- @result{} 9 ; 9 = @r{0000 0000 0000 0000 0000 0000 1001}
-@end group
-
-@group
-(logxor 12 5 7) ; 12 = @r{0000 0000 0000 0000 0000 0000 1100}
- ; 5 = @r{0000 0000 0000 0000 0000 0000 0101}
- ; 7 = @r{0000 0000 0000 0000 0000 0000 0111}
- @result{} 14 ; 14 = @r{0000 0000 0000 0000 0000 0000 1110}
-@end group
-@end smallexample
-@end defun
-
-@defun lognot integer
-@cindex logical not
-@cindex bitwise not
-This function returns the logical complement of its argument: the @var{n}th
-bit is one in the result if, and only if, the @var{n}th bit is zero in
-@var{integer}, and vice-versa.
-
-@example
-(lognot 5)
- @result{} -6
-;; 5 = @r{0000 0000 0000 0000 0000 0000 0101}
-;; @r{becomes}
-;; -6 = @r{1111 1111 1111 1111 1111 1111 1010}
-@end example
-@end defun
-
-@node Math Functions
-@section Standard Mathematical Functions
-@cindex transcendental functions
-@cindex mathematical functions
-
-These mathematical functions are available if floating point is
-supported. They allow integers as well as floating point numbers
-as arguments.
-
-@defun sin arg
-@defunx cos arg
-@defunx tan arg
-These are the ordinary trigonometric functions, with argument measured
-in radians.
-@end defun
-
-@defun asin arg
-The value of @code{(asin @var{arg})} is a number between @minus{}pi/2
-and pi/2 (inclusive) whose sine is @var{arg}; if, however, @var{arg}
-is out of range (outside [-1, 1]), then the result is a NaN.
-@end defun
-
-@defun acos arg
-The value of @code{(acos @var{arg})} is a number between 0 and pi
-(inclusive) whose cosine is @var{arg}; if, however, @var{arg}
-is out of range (outside [-1, 1]), then the result is a NaN.
-@end defun
-
-@defun atan arg
-The value of @code{(atan @var{arg})} is a number between @minus{}pi/2
-and pi/2 (exclusive) whose tangent is @var{arg}.
-@end defun
-
-@defun exp arg
-This is the exponential function; it returns @i{e} to the power
-@var{arg}. @i{e} is a fundamental mathematical constant also called the
-base of natural logarithms.
-@end defun
-
-@defun log arg &optional base
-This function returns the logarithm of @var{arg}, with base @var{base}.
-If you don't specify @var{base}, the base @var{e} is used. If @var{arg}
-is negative, the result is a NaN.
-@end defun
-
-@ignore
-@defun expm1 arg
-This function returns @code{(1- (exp @var{arg}))}, but it is more
-accurate than that when @var{arg} is negative and @code{(exp @var{arg})}
-is close to 1.
-@end defun
-
-@defun log1p arg
-This function returns @code{(log (1+ @var{arg}))}, but it is more
-accurate than that when @var{arg} is so small that adding 1 to it would
-lose accuracy.
-@end defun
-@end ignore
-
-@defun log10 arg
-This function returns the logarithm of @var{arg}, with base 10. If
-@var{arg} is negative, the result is a NaN. @code{(log10 @var{x})}
-@equiv{} @code{(log @var{x} 10)}, at least approximately.
-@end defun
-
-@defun expt x y
-This function returns @var{x} raised to power @var{y}. If both
-arguments are integers and @var{y} is positive, the result is an
-integer; in this case, it is truncated to fit the range of possible
-integer values.
-@end defun
-
-@defun sqrt arg
-This returns the square root of @var{arg}. If @var{arg} is negative,
-the value is a NaN.
-@end defun
-
-@node Random Numbers
-@section Random Numbers
-@cindex random numbers
-
-A deterministic computer program cannot generate true random numbers.
-For most purposes, @dfn{pseudo-random numbers} suffice. A series of
-pseudo-random numbers is generated in a deterministic fashion. The
-numbers are not truly random, but they have certain properties that
-mimic a random series. For example, all possible values occur equally
-often in a pseudo-random series.
-
-In Emacs, pseudo-random numbers are generated from a ``seed'' number.
-Starting from any given seed, the @code{random} function always
-generates the same sequence of numbers. Emacs always starts with the
-same seed value, so the sequence of values of @code{random} is actually
-the same in each Emacs run! For example, in one operating system, the
-first call to @code{(random)} after you start Emacs always returns
--1457731, and the second one always returns -7692030. This
-repeatability is helpful for debugging.
-
-If you want truly unpredictable random numbers, execute @code{(random
-t)}. This chooses a new seed based on the current time of day and on
-Emacs's process @sc{id} number.
-
-@defun random &optional limit
-This function returns a pseudo-random integer. Repeated calls return a
-series of pseudo-random integers.
-
-If @var{limit} is a positive integer, the value is chosen to be
-nonnegative and less than @var{limit}.
-
-If @var{limit} is @code{t}, it means to choose a new seed based on the
-current time of day and on Emacs's process @sc{id} number.
-@c "Emacs'" is incorrect usage!
-
-On some machines, any integer representable in Lisp may be the result
-of @code{random}. On other machines, the result can never be larger
-than a certain maximum or less than a certain (negative) minimum.
-@end defun
diff --git a/lispref/objects.texi b/lispref/objects.texi
deleted file mode 100644
index 78412e2c312..00000000000
--- a/lispref/objects.texi
+++ /dev/null
@@ -1,1592 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/objects
-@node Lisp Data Types, Numbers, Introduction, Top
-@chapter Lisp Data Types
-@cindex object
-@cindex Lisp object
-@cindex type
-@cindex data type
-
- A Lisp @dfn{object} is a piece of data used and manipulated by Lisp
-programs. For our purposes, a @dfn{type} or @dfn{data type} is a set of
-possible objects.
-
- Every object belongs to at least one type. Objects of the same type
-have similar structures and may usually be used in the same contexts.
-Types can overlap, and objects can belong to two or more types.
-Consequently, we can ask whether an object belongs to a particular type,
-but not for ``the'' type of an object.
-
-@cindex primitive type
- A few fundamental object types are built into Emacs. These, from
-which all other types are constructed, are called @dfn{primitive
-types}. Each object belongs to one and only one primitive type. These
-types include @dfn{integer}, @dfn{float}, @dfn{cons}, @dfn{symbol},
-@dfn{string}, @dfn{vector}, @dfn{subr}, @dfn{byte-code function}, and
-several special types, such as @dfn{buffer}, that are related to
-editing. (@xref{Editing Types}.)
-
- Each primitive type has a corresponding Lisp function that checks
-whether an object is a member of that type.
-
- Note that Lisp is unlike many other languages in that Lisp objects are
-@dfn{self-typing}: the primitive type of the object is implicit in the
-object itself. For example, if an object is a vector, nothing can treat
-it as a number; Lisp knows it is a vector, not a number.
-
- In most languages, the programmer must declare the data type of each
-variable, and the type is known by the compiler but not represented in
-the data. Such type declarations do not exist in Emacs Lisp. A Lisp
-variable can have any type of value, and it remembers whatever value
-you store in it, type and all.
-
- This chapter describes the purpose, printed representation, and read
-syntax of each of the standard types in GNU Emacs Lisp. Details on how
-to use these types can be found in later chapters.
-
-@menu
-* Printed Representation:: How Lisp objects are represented as text.
-* Comments:: Comments and their formatting conventions.
-* Programming Types:: Types found in all Lisp systems.
-* Editing Types:: Types specific to Emacs.
-* Type Predicates:: Tests related to types.
-* Equality Predicates:: Tests of equality between any two objects.
-@end menu
-
-@node Printed Representation
-@comment node-name, next, previous, up
-@section Printed Representation and Read Syntax
-@cindex printed representation
-@cindex read syntax
-
- The @dfn{printed representation} of an object is the format of the
-output generated by the Lisp printer (the function @code{prin1}) for
-that object. The @dfn{read syntax} of an object is the format of the
-input accepted by the Lisp reader (the function @code{read}) for that
-object. Most objects have more than one possible read syntax. Some
-types of object have no read syntax; except for these cases, the printed
-representation of an object is also a read syntax for it.
-
- In other languages, an expression is text; it has no other form. In
-Lisp, an expression is primarily a Lisp object and only secondarily the
-text that is the object's read syntax. Often there is no need to
-emphasize this distinction, but you must keep it in the back of your
-mind, or you will occasionally be very confused.
-
-@cindex hash notation
- Every type has a printed representation. Some types have no read
-syntax, since it may not make sense to enter objects of these types
-directly in a Lisp program. For example, the buffer type does not have
-a read syntax. Objects of these types are printed in @dfn{hash
-notation}: the characters @samp{#<} followed by a descriptive string
-(typically the type name followed by the name of the object), and closed
-with a matching @samp{>}. Hash notation cannot be read at all, so the
-Lisp reader signals the error @code{invalid-read-syntax} whenever it
-encounters @samp{#<}.
-@kindex invalid-read-syntax
-
-@example
-(current-buffer)
- @result{} #<buffer objects.texi>
-@end example
-
- When you evaluate an expression interactively, the Lisp interpreter
-first reads the textual representation of it, producing a Lisp object,
-and then evaluates that object (@pxref{Evaluation}). However,
-evaluation and reading are separate activities. Reading returns the
-Lisp object represented by the text that is read; the object may or may
-not be evaluated later. @xref{Input Functions}, for a description of
-@code{read}, the basic function for reading objects.
-
-@node Comments
-@comment node-name, next, previous, up
-@section Comments
-@cindex comments
-@cindex @samp{;} in comment
-
- A @dfn{comment} is text that is written in a program only for the sake
-of humans that read the program, and that has no effect on the meaning
-of the program. In Lisp, a semicolon (@samp{;}) starts a comment if it
-is not within a string or character constant. The comment continues to
-the end of line. The Lisp reader discards comments; they do not become
-part of the Lisp objects which represent the program within the Lisp
-system.
-
- The @samp{#@@@var{count}} construct, which skips the next @var{count}
-characters, is useful for program-generated comments containing binary
-data. The Emacs Lisp byte compiler uses this in its output files
-(@pxref{Byte Compilation}). It isn't meant for source files, however.
-
- @xref{Comment Tips}, for conventions for formatting comments.
-
-@node Programming Types
-@section Programming Types
-@cindex programming types
-
- There are two general categories of types in Emacs Lisp: those having
-to do with Lisp programming, and those having to do with editing. The
-former exist in many Lisp implementations, in one form or another. The
-latter are unique to Emacs Lisp.
-
-@menu
-* Integer Type:: Numbers without fractional parts.
-* Floating Point Type:: Numbers with fractional parts and with a large range.
-* Character Type:: The representation of letters, numbers and
- control characters.
-* Symbol Type:: A multi-use object that refers to a function,
- variable, or property list, and has a unique identity.
-* Sequence Type:: Both lists and arrays are classified as sequences.
-* Cons Cell Type:: Cons cells, and lists (which are made from cons cells).
-* Array Type:: Arrays include strings and vectors.
-* String Type:: An (efficient) array of characters.
-* Vector Type:: One-dimensional arrays.
-* Function Type:: A piece of executable code you can call from elsewhere.
-* Macro Type:: A method of expanding an expression into another
- expression, more fundamental but less pretty.
-* Primitive Function Type:: A function written in C, callable from Lisp.
-* Byte-Code Type:: A function written in Lisp, then compiled.
-* Autoload Type:: A type used for automatically loading seldom-used
- functions.
-@end menu
-
-@node Integer Type
-@subsection Integer Type
-
- The range of values for integers in Emacs Lisp is @minus{}134217728 to
-134217727 (28 bits; i.e.,
-@ifinfo
--2**27
-@end ifinfo
-@tex
-$-2^{27}$
-@end tex
-to
-@ifinfo
-2**27 - 1)
-@end ifinfo
-@tex
-$2^{28}-1$)
-@end tex
-on most machines. (Some machines may provide a wider range.) It is
-important to note that the Emacs Lisp arithmetic functions do not check
-for overflow. Thus @code{(1+ 134217727)} is @minus{}134217728 on most
-machines.
-
- The read syntax for integers is a sequence of (base ten) digits with an
-optional sign at the beginning and an optional period at the end. The
-printed representation produced by the Lisp interpreter never has a
-leading @samp{+} or a final @samp{.}.
-
-@example
-@group
--1 ; @r{The integer -1.}
-1 ; @r{The integer 1.}
-1. ; @r{Also The integer 1.}
-+1 ; @r{Also the integer 1.}
-268435457 ; @r{Also the integer 1!}
- ; @r{ (on a 28-bit implementation)}
-@end group
-@end example
-
- @xref{Numbers}, for more information.
-
-@node Floating Point Type
-@subsection Floating Point Type
-
- Emacs version 19 supports floating point numbers (though there is a
-compilation option to disable them). The precise range of floating
-point numbers is machine-specific.
-
- The printed representation for floating point numbers requires either
-a decimal point (with at least one digit following), an exponent, or
-both. For example, @samp{1500.0}, @samp{15e2}, @samp{15.0e2},
-@samp{1.5e3}, and @samp{.15e4} are five ways of writing a floating point
-number whose value is 1500. They are all equivalent.
-
- @xref{Numbers}, for more information.
-
-@node Character Type
-@subsection Character Type
-@cindex @sc{ASCII} character codes
-
- A @dfn{character} in Emacs Lisp is nothing more than an integer. In
-other words, characters are represented by their character codes. For
-example, the character @kbd{A} is represented as the @w{integer 65}.
-
- Individual characters are not often used in programs. It is far more
-common to work with @emph{strings}, which are sequences composed of
-characters. @xref{String Type}.
-
- Characters in strings, buffers, and files are currently limited to the
-range of 0 to 255---eight bits. If you store a larger integer into a
-string, buffer or file, it is truncated to that range. Characters that
-represent keyboard input have a much wider range.
-
-@cindex read syntax for characters
-@cindex printed representation for characters
-@cindex syntax for characters
- Since characters are really integers, the printed representation of a
-character is a decimal number. This is also a possible read syntax for
-a character, but writing characters that way in Lisp programs is a very
-bad idea. You should @emph{always} use the special read syntax formats
-that Emacs Lisp provides for characters. These syntax formats start
-with a question mark.
-
- The usual read syntax for alphanumeric characters is a question mark
-followed by the character; thus, @samp{?A} for the character
-@kbd{A}, @samp{?B} for the character @kbd{B}, and @samp{?a} for the
-character @kbd{a}.
-
- For example:
-
-@example
-?Q @result{} 81 ?q @result{} 113
-@end example
-
- You can use the same syntax for punctuation characters, but it is
-often a good idea to add a @samp{\} so that the Emacs commands for
-editing Lisp code don't get confused. For example, @samp{?\ } is the
-way to write the space character. If the character is @samp{\}, you
-@emph{must} use a second @samp{\} to quote it: @samp{?\\}.
-
-@cindex whitespace
-@cindex bell character
-@cindex @samp{\a}
-@cindex backspace
-@cindex @samp{\b}
-@cindex tab
-@cindex @samp{\t}
-@cindex vertical tab
-@cindex @samp{\v}
-@cindex formfeed
-@cindex @samp{\f}
-@cindex newline
-@cindex @samp{\n}
-@cindex return
-@cindex @samp{\r}
-@cindex escape
-@cindex @samp{\e}
- You can express the characters Control-g, backspace, tab, newline,
-vertical tab, formfeed, return, and escape as @samp{?\a}, @samp{?\b},
-@samp{?\t}, @samp{?\n}, @samp{?\v}, @samp{?\f}, @samp{?\r}, @samp{?\e},
-respectively. Those values are 7, 8, 9, 10, 11, 12, 13, and 27 in
-decimal. Thus,
-
-@example
-?\a @result{} 7 ; @r{@kbd{C-g}}
-?\b @result{} 8 ; @r{backspace, @key{BS}, @kbd{C-h}}
-?\t @result{} 9 ; @r{tab, @key{TAB}, @kbd{C-i}}
-?\n @result{} 10 ; @r{newline, @key{LFD}, @kbd{C-j}}
-?\v @result{} 11 ; @r{vertical tab, @kbd{C-k}}
-?\f @result{} 12 ; @r{formfeed character, @kbd{C-l}}
-?\r @result{} 13 ; @r{carriage return, @key{RET}, @kbd{C-m}}
-?\e @result{} 27 ; @r{escape character, @key{ESC}, @kbd{C-[}}
-?\\ @result{} 92 ; @r{backslash character, @kbd{\}}
-@end example
-
-@cindex escape sequence
- These sequences which start with backslash are also known as
-@dfn{escape sequences}, because backslash plays the role of an escape
-character; this usage has nothing to do with the character @key{ESC}.
-
-@cindex control characters
- Control characters may be represented using yet another read syntax.
-This consists of a question mark followed by a backslash, caret, and the
-corresponding non-control character, in either upper or lower case. For
-example, both @samp{?\^I} and @samp{?\^i} are valid read syntax for the
-character @kbd{C-i}, the character whose value is 9.
-
- Instead of the @samp{^}, you can use @samp{C-}; thus, @samp{?\C-i} is
-equivalent to @samp{?\^I} and to @samp{?\^i}:
-
-@example
-?\^I @result{} 9 ?\C-I @result{} 9
-@end example
-
- For use in strings and buffers, you are limited to the control
-characters that exist in @sc{ASCII}, but for keyboard input purposes,
-you can turn any character into a control character with @samp{C-}. The
-character codes for these non-@sc{ASCII} control characters include the
-@iftex
-$2^{26}$
-@end iftex
-@ifinfo
-2**26
-@end ifinfo
-bit as well as the code for the corresponding non-control
-character. Ordinary terminals have no way of generating non-@sc{ASCII}
-control characters, but you can generate them straightforwardly using an
-X terminal.
-
- For historical reasons, Emacs treats the @key{DEL} character as
-the control equivalent of @kbd{?}:
-
-@example
-?\^? @result{} 127 ?\C-? @result{} 127
-@end example
-
-@noindent
-As a result, it is currently not possible to represent the character
-@kbd{Control-?}, which is a meaningful input character under X. It is
-not easy to change this as various Lisp files refer to @key{DEL} in this
-way.
-
- For representing control characters to be found in files or strings,
-we recommend the @samp{^} syntax; for control characters in keyboard
-input, we prefer the @samp{C-} syntax. This does not affect the meaning
-of the program, but may guide the understanding of people who read it.
-
-@cindex meta characters
- A @dfn{meta character} is a character typed with the @key{META}
-modifier key. The integer that represents such a character has the
-@iftex
-$2^{27}$
-@end iftex
-@ifinfo
-2**27
-@end ifinfo
-bit set (which on most machines makes it a negative number). We
-use high bits for this and other modifiers to make possible a wide range
-of basic character codes.
-
- In a string, the
-@iftex
-$2^{7}$
-@end iftex
-@ifinfo
-2**7
-@end ifinfo
-bit indicates a meta character, so the meta
-characters that can fit in a string have codes in the range from 128 to
-255, and are the meta versions of the ordinary @sc{ASCII} characters.
-(In Emacs versions 18 and older, this convention was used for characters
-outside of strings as well.)
-
- The read syntax for meta characters uses @samp{\M-}. For example,
-@samp{?\M-A} stands for @kbd{M-A}. You can use @samp{\M-} together with
-octal character codes (see below), with @samp{\C-}, or with any other
-syntax for a character. Thus, you can write @kbd{M-A} as @samp{?\M-A},
-or as @samp{?\M-\101}. Likewise, you can write @kbd{C-M-b} as
-@samp{?\M-\C-b}, @samp{?\C-\M-b}, or @samp{?\M-\002}.
-
- The case of an ordinary letter is indicated by its character code as
-part of @sc{ASCII}, but @sc{ASCII} has no way to represent whether a
-control character is upper case or lower case. Emacs uses the
-@iftex
-$2^{25}$
-@end iftex
-@ifinfo
-2**25
-@end ifinfo
-bit to indicate that the shift key was used for typing a control
-character. This distinction is possible only when you use X terminals
-or other special terminals; ordinary terminals do not indicate the
-distinction to the computer in any way.
-
-@cindex hyper characters
-@cindex super characters
-@cindex alt characters
- The X Window System defines three other modifier bits that can be set
-in a character: @dfn{hyper}, @dfn{super} and @dfn{alt}. The syntaxes
-for these bits are @samp{\H-}, @samp{\s-} and @samp{\A-}. Thus,
-@samp{?\H-\M-\A-x} represents @kbd{Alt-Hyper-Meta-x}.
-@iftex
-Numerically, the
-bit values are $2^{22}$ for alt, $2^{23}$ for super and $2^{24}$ for hyper.
-@end iftex
-@ifinfo
-Numerically, the
-bit values are 2**22 for alt, 2**23 for super and 2**24 for hyper.
-@end ifinfo
-
-@cindex @samp{?} in character constant
-@cindex question mark in character constant
-@cindex @samp{\} in character constant
-@cindex backslash in character constant
-@cindex octal character code
- Finally, the most general read syntax consists of a question mark
-followed by a backslash and the character code in octal (up to three
-octal digits); thus, @samp{?\101} for the character @kbd{A},
-@samp{?\001} for the character @kbd{C-a}, and @code{?\002} for the
-character @kbd{C-b}. Although this syntax can represent any @sc{ASCII}
-character, it is preferred only when the precise octal value is more
-important than the @sc{ASCII} representation.
-
-@example
-@group
-?\012 @result{} 10 ?\n @result{} 10 ?\C-j @result{} 10
-?\101 @result{} 65 ?A @result{} 65
-@end group
-@end example
-
- A backslash is allowed, and harmless, preceding any character without
-a special escape meaning; thus, @samp{?\+} is equivalent to @samp{?+}.
-There is no reason to add a backslash before most characters. However,
-you should add a backslash before any of the characters
-@samp{()\|;'`"#.,} to avoid confusing the Emacs commands for editing
-Lisp code. Also add a backslash before whitespace characters such as
-space, tab, newline and formfeed. However, it is cleaner to use one of
-the easily readable escape sequences, such as @samp{\t}, instead of an
-actual whitespace character such as a tab.
-
-@node Symbol Type
-@subsection Symbol Type
-
- A @dfn{symbol} in GNU Emacs Lisp is an object with a name. The symbol
-name serves as the printed representation of the symbol. In ordinary
-use, the name is unique---no two symbols have the same name.
-
- A symbol can serve as a variable, as a function name, or to hold a
-property list. Or it may serve only to be distinct from all other Lisp
-objects, so that its presence in a data structure may be recognized
-reliably. In a given context, usually only one of these uses is
-intended. But you can use one symbol in all of these ways,
-independently.
-
-@cindex @samp{\} in symbols
-@cindex backslash in symbols
- A symbol name can contain any characters whatever. Most symbol names
-are written with letters, digits, and the punctuation characters
-@samp{-+=*/}. Such names require no special punctuation; the characters
-of the name suffice as long as the name does not look like a number.
-(If it does, write a @samp{\} at the beginning of the name to force
-interpretation as a symbol.) The characters @samp{_~!@@$%^&:<>@{@}} are
-less often used but also require no special punctuation. Any other
-characters may be included in a symbol's name by escaping them with a
-backslash. In contrast to its use in strings, however, a backslash in
-the name of a symbol simply quotes the single character that follows the
-backslash. For example, in a string, @samp{\t} represents a tab
-character; in the name of a symbol, however, @samp{\t} merely quotes the
-letter @kbd{t}. To have a symbol with a tab character in its name, you
-must actually use a tab (preceded with a backslash). But it's rare to
-do such a thing.
-
-@cindex CL note---case of letters
-@quotation
-@b{Common Lisp note:} In Common Lisp, lower case letters are always
-``folded'' to upper case, unless they are explicitly escaped. In Emacs
-Lisp, upper case and lower case letters are distinct.
-@end quotation
-
- Here are several examples of symbol names. Note that the @samp{+} in
-the fifth example is escaped to prevent it from being read as a number.
-This is not necessary in the sixth example because the rest of the name
-makes it invalid as a number.
-
-@example
-@group
-foo ; @r{A symbol named @samp{foo}.}
-FOO ; @r{A symbol named @samp{FOO}, different from @samp{foo}.}
-char-to-string ; @r{A symbol named @samp{char-to-string}.}
-@end group
-@group
-1+ ; @r{A symbol named @samp{1+}}
- ; @r{(not @samp{+1}, which is an integer).}
-@end group
-@group
-\+1 ; @r{A symbol named @samp{+1}}
- ; @r{(not a very readable name).}
-@end group
-@group
-\(*\ 1\ 2\) ; @r{A symbol named @samp{(* 1 2)} (a worse name).}
-@c the @'s in this next line use up three characters, hence the
-@c apparent misalignment of the comment.
-+-*/_~!@@$%^&=:<>@{@} ; @r{A symbol named @samp{+-*/_~!@@$%^&=:<>@{@}}.}
- ; @r{These characters need not be escaped.}
-@end group
-@end example
-
-@node Sequence Type
-@subsection Sequence Types
-
- A @dfn{sequence} is a Lisp object that represents an ordered set of
-elements. There are two kinds of sequence in Emacs Lisp, lists and
-arrays. Thus, an object of type list or of type array is also
-considered a sequence.
-
- Arrays are further subdivided into strings and vectors. Vectors can
-hold elements of any type, but string elements must be characters in the
-range from 0 to 255. However, the characters in a string can have text
-properties like characters in a buffer (@pxref{Text Properties});
-vectors do not support text properties even when their elements happen
-to be characters.
-
- Lists, strings and vectors are different, but they have important
-similarities. For example, all have a length @var{l}, and all have
-elements which can be indexed from zero to @var{l} minus one. Also,
-several functions, called sequence functions, accept any kind of
-sequence. For example, the function @code{elt} can be used to extract
-an element of a sequence, given its index. @xref{Sequences Arrays
-Vectors}.
-
- It is impossible to read the same sequence twice, since sequences are
-always created anew upon reading. If you read the read syntax for a
-sequence twice, you get two sequences with equal contents. There is one
-exception: the empty list @code{()} always stands for the same object,
-@code{nil}.
-
-@node Cons Cell Type
-@subsection Cons Cell and List Types
-@cindex address field of register
-@cindex decrement field of register
-
- A @dfn{cons cell} is an object comprising two pointers named the
-@sc{car} and the @sc{cdr}. Each of them can point to any Lisp object.
-
- A @dfn{list} is a series of cons cells, linked together so that the
-@sc{cdr} of each cons cell points either to another cons cell or to the
-empty list. @xref{Lists}, for functions that work on lists. Because
-most cons cells are used as part of lists, the phrase @dfn{list
-structure} has come to refer to any structure made out of cons cells.
-
- The names @sc{car} and @sc{cdr} have only historical meaning now. The
-original Lisp implementation ran on an @w{IBM 704} computer which
-divided words into two parts, called the ``address'' part and the
-``decrement''; @sc{car} was an instruction to extract the contents of
-the address part of a register, and @sc{cdr} an instruction to extract
-the contents of the decrement. By contrast, ``cons cells'' are named
-for the function @code{cons} that creates them, which in turn is named
-for its purpose, the construction of cells.
-
-@cindex atom
- Because cons cells are so central to Lisp, we also have a word for
-``an object which is not a cons cell''. These objects are called
-@dfn{atoms}.
-
-@cindex parenthesis
- The read syntax and printed representation for lists are identical, and
-consist of a left parenthesis, an arbitrary number of elements, and a
-right parenthesis.
-
- Upon reading, each object inside the parentheses becomes an element
-of the list. That is, a cons cell is made for each element. The
-@sc{car} of the cons cell points to the element, and its @sc{cdr} points
-to the next cons cell of the list, which holds the next element in the
-list. The @sc{cdr} of the last cons cell is set to point to @code{nil}.
-
-@cindex box diagrams, for lists
-@cindex diagrams, boxed, for lists
- A list can be illustrated by a diagram in which the cons cells are
-shown as pairs of boxes. (The Lisp reader cannot read such an
-illustration; unlike the textual notation, which can be understood by
-both humans and computers, the box illustrations can be understood only
-by humans.) The following represents the three-element list @code{(rose
-violet buttercup)}:
-
-@example
-@group
- ___ ___ ___ ___ ___ ___
- |___|___|--> |___|___|--> |___|___|--> nil
- | | |
- | | |
- --> rose --> violet --> buttercup
-@end group
-@end example
-
- In this diagram, each box represents a slot that can refer to any Lisp
-object. Each pair of boxes represents a cons cell. Each arrow is a
-reference to a Lisp object, either an atom or another cons cell.
-
- In this example, the first box, the @sc{car} of the first cons cell,
-refers to or ``contains'' @code{rose} (a symbol). The second box, the
-@sc{cdr} of the first cons cell, refers to the next pair of boxes, the
-second cons cell. The @sc{car} of the second cons cell refers to
-@code{violet} and the @sc{cdr} refers to the third cons cell. The
-@sc{cdr} of the third (and last) cons cell refers to @code{nil}.
-
-Here is another diagram of the same list, @code{(rose violet
-buttercup)}, sketched in a different manner:
-
-@smallexample
-@group
- --------------- ---------------- -------------------
-| car | cdr | | car | cdr | | car | cdr |
-| rose | o-------->| violet | o-------->| buttercup | nil |
-| | | | | | | | |
- --------------- ---------------- -------------------
-@end group
-@end smallexample
-
-@cindex @samp{(@dots{})} in lists
-@cindex @code{nil} in lists
-@cindex empty list
- A list with no elements in it is the @dfn{empty list}; it is identical
-to the symbol @code{nil}. In other words, @code{nil} is both a symbol
-and a list.
-
- Here are examples of lists written in Lisp syntax:
-
-@example
-(A 2 "A") ; @r{A list of three elements.}
-() ; @r{A list of no elements (the empty list).}
-nil ; @r{A list of no elements (the empty list).}
-("A ()") ; @r{A list of one element: the string @code{"A ()"}.}
-(A ()) ; @r{A list of two elements: @code{A} and the empty list.}
-(A nil) ; @r{Equivalent to the previous.}
-((A B C)) ; @r{A list of one element}
- ; @r{(which is a list of three elements).}
-@end example
-
- Here is the list @code{(A ())}, or equivalently @code{(A nil)},
-depicted with boxes and arrows:
-
-@example
-@group
- ___ ___ ___ ___
- |___|___|--> |___|___|--> nil
- | |
- | |
- --> A --> nil
-@end group
-@end example
-
-@menu
-* Dotted Pair Notation:: An alternative syntax for lists.
-* Association List Type:: A specially constructed list.
-@end menu
-
-@node Dotted Pair Notation
-@comment node-name, next, previous, up
-@subsubsection Dotted Pair Notation
-@cindex dotted pair notation
-@cindex @samp{.} in lists
-
- @dfn{Dotted pair notation} is an alternative syntax for cons cells
-that represents the @sc{car} and @sc{cdr} explicitly. In this syntax,
-@code{(@var{a} .@: @var{b})} stands for a cons cell whose @sc{car} is
-the object @var{a}, and whose @sc{cdr} is the object @var{b}. Dotted
-pair notation is therefore more general than list syntax. In the dotted
-pair notation, the list @samp{(1 2 3)} is written as @samp{(1 . (2 . (3
-. nil)))}. For @code{nil}-terminated lists, the two notations produce
-the same result, but list notation is usually clearer and more
-convenient when it is applicable. When printing a list, the dotted pair
-notation is only used if the @sc{cdr} of a cell is not a list.
-
- Here's how box notation can illustrate dotted pairs. This example
-shows the pair @code{(rose . violet)}:
-
-@example
-@group
- ___ ___
- |___|___|--> violet
- |
- |
- --> rose
-@end group
-@end example
-
- Dotted pair notation can be combined with list notation to represent a
-chain of cons cells with a non-@code{nil} final @sc{cdr}. For example,
-@code{(rose violet . buttercup)} is equivalent to @code{(rose . (violet
-. buttercup))}. The object looks like this:
-
-@example
-@group
- ___ ___ ___ ___
- |___|___|--> |___|___|--> buttercup
- | |
- | |
- --> rose --> violet
-@end group
-@end example
-
- These diagrams make it evident why @w{@code{(rose .@: violet .@:
-buttercup)}} is invalid syntax; it would require a cons cell that has
-three parts rather than two.
-
- The list @code{(rose violet)} is equivalent to @code{(rose . (violet))}
-and looks like this:
-
-@example
-@group
- ___ ___ ___ ___
- |___|___|--> |___|___|--> nil
- | |
- | |
- --> rose --> violet
-@end group
-@end example
-
- Similarly, the three-element list @code{(rose violet buttercup)}
-is equivalent to @code{(rose . (violet . (buttercup)))}.
-@ifinfo
-It looks like this:
-
-@example
-@group
- ___ ___ ___ ___ ___ ___
- |___|___|--> |___|___|--> |___|___|--> nil
- | | |
- | | |
- --> rose --> violet --> buttercup
-@end group
-@end example
-@end ifinfo
-
-@node Association List Type
-@comment node-name, next, previous, up
-@subsubsection Association List Type
-
- An @dfn{association list} or @dfn{alist} is a specially-constructed
-list whose elements are cons cells. In each element, the @sc{car} is
-considered a @dfn{key}, and the @sc{cdr} is considered an
-@dfn{associated value}. (In some cases, the associated value is stored
-in the @sc{car} of the @sc{cdr}.) Association lists are often used as
-stacks, since it is easy to add or remove associations at the front of
-the list.
-
- For example,
-
-@example
-(setq alist-of-colors
- '((rose . red) (lily . white) (buttercup . yellow)))
-@end example
-
-@noindent
-sets the variable @code{alist-of-colors} to an alist of three elements. In the
-first element, @code{rose} is the key and @code{red} is the value.
-
- @xref{Association Lists}, for a further explanation of alists and for
-functions that work on alists.
-
-@node Array Type
-@subsection Array Type
-
- An @dfn{array} is composed of an arbitrary number of slots for
-referring to other Lisp objects, arranged in a contiguous block of
-memory. Accessing any element of an array takes the same amount of
-time. In contrast, accessing an element of a list requires time
-proportional to the position of the element in the list. (Elements at
-the end of a list take longer to access than elements at the beginning
-of a list.)
-
- Emacs defines two types of array, strings and vectors. A string is an
-array of characters and a vector is an array of arbitrary objects. Both
-are one-dimensional. (Most other programming languages support
-multidimensional arrays, but they are not essential; you can get the
-same effect with an array of arrays.) Each type of array has its own
-read syntax; see @ref{String Type}, and @ref{Vector Type}.
-
- An array may have any length up to the largest integer; but once
-created, it has a fixed size. The first element of an array has index
-zero, the second element has index 1, and so on. This is called
-@dfn{zero-origin} indexing. For example, an array of four elements has
-indices 0, 1, 2, @w{and 3}.
-
- The array type is contained in the sequence type and contains both the
-string type and the vector type.
-
-@node String Type
-@subsection String Type
-
- A @dfn{string} is an array of characters. Strings are used for many
-purposes in Emacs, as can be expected in a text editor; for example, as
-the names of Lisp symbols, as messages for the user, and to represent
-text extracted from buffers. Strings in Lisp are constants: evaluation
-of a string returns the same string.
-
-@cindex @samp{"} in strings
-@cindex double-quote in strings
-@cindex @samp{\} in strings
-@cindex backslash in strings
- The read syntax for strings is a double-quote, an arbitrary number of
-characters, and another double-quote, @code{"like this"}. The Lisp
-reader accepts the same formats for reading the characters of a string
-as it does for reading single characters (without the question mark that
-begins a character literal). You can enter a nonprinting character such
-as tab, @kbd{C-a} or @kbd{M-C-A} using the convenient escape sequences,
-like this: @code{"\t, \C-a, \M-\C-a"}. You can include a double-quote
-in a string by preceding it with a backslash; thus, @code{"\""} is a
-string containing just a single double-quote character.
-(@xref{Character Type}, for a description of the read syntax for
-characters.)
-
- If you use the @samp{\M-} syntax to indicate a meta character in a
-string constant, this sets the
-@iftex
-$2^{7}$
-@end iftex
-@ifinfo
-2**7
-@end ifinfo
-bit of the character in the string.
-This is not the same representation that the meta modifier has in a
-character on its own (not inside a string). @xref{Character Type}.
-
- Strings cannot hold characters that have the hyper, super, or alt
-modifiers; they can hold @sc{ASCII} control characters, but no others.
-They do not distinguish case in @sc{ASCII} control characters.
-
- The printed representation of a string consists of a double-quote, the
-characters it contains, and another double-quote. However, you must
-escape any backslash or double-quote characters in the string with a
-backslash, like this: @code{"this \" is an embedded quote"}.
-
- The newline character is not special in the read syntax for strings;
-if you write a new line between the double-quotes, it becomes a
-character in the string. But an escaped newline---one that is preceded
-by @samp{\}---does not become part of the string; i.e., the Lisp reader
-ignores an escaped newline while reading a string.
-@cindex newline in strings
-
-@example
-"It is useful to include newlines
-in documentation strings,
-but the newline is \
-ignored if escaped."
- @result{} "It is useful to include newlines
-in documentation strings,
-but the newline is ignored if escaped."
-@end example
-
- A string can hold properties of the text it contains, in addition to
-the characters themselves. This enables programs that copy text between
-strings and buffers to preserve the properties with no special effort.
-@xref{Text Properties}. Strings with text properties have a special
-read and print syntax:
-
-@example
-#("@var{characters}" @var{property-data}...)
-@end example
-
-@noindent
-where @var{property-data} consists of zero or more elements, in groups
-of three as follows:
-
-@example
-@var{beg} @var{end} @var{plist}
-@end example
-
-@noindent
-The elements @var{beg} and @var{end} are integers, and together specify
-a range of indices in the string; @var{plist} is the property list for
-that range.
-
- @xref{Strings and Characters}, for functions that work on strings.
-
-@node Vector Type
-@subsection Vector Type
-
- A @dfn{vector} is a one-dimensional array of elements of any type. It
-takes a constant amount of time to access any element of a vector. (In
-a list, the access time of an element is proportional to the distance of
-the element from the beginning of the list.)
-
- The printed representation of a vector consists of a left square
-bracket, the elements, and a right square bracket. This is also the
-read syntax. Like numbers and strings, vectors are considered constants
-for evaluation.
-
-@example
-[1 "two" (three)] ; @r{A vector of three elements.}
- @result{} [1 "two" (three)]
-@end example
-
- @xref{Vectors}, for functions that work with vectors.
-
-@node Function Type
-@subsection Function Type
-
- Just as functions in other programming languages are executable,
-@dfn{Lisp function} objects are pieces of executable code. However,
-functions in Lisp are primarily Lisp objects, and only secondarily the
-text which represents them. These Lisp objects are lambda expressions:
-lists whose first element is the symbol @code{lambda} (@pxref{Lambda
-Expressions}).
-
- In most programming languages, it is impossible to have a function
-without a name. In Lisp, a function has no intrinsic name. A lambda
-expression is also called an @dfn{anonymous function} (@pxref{Anonymous
-Functions}). A named function in Lisp is actually a symbol with a valid
-function in its function cell (@pxref{Defining Functions}).
-
- Most of the time, functions are called when their names are written in
-Lisp expressions in Lisp programs. However, you can construct or obtain
-a function object at run time and then call it with the primitive
-functions @code{funcall} and @code{apply}. @xref{Calling Functions}.
-
-@node Macro Type
-@subsection Macro Type
-
- A @dfn{Lisp macro} is a user-defined construct that extends the Lisp
-language. It is represented as an object much like a function, but with
-different parameter-passing semantics. A Lisp macro has the form of a
-list whose first element is the symbol @code{macro} and whose @sc{cdr}
-is a Lisp function object, including the @code{lambda} symbol.
-
- Lisp macro objects are usually defined with the built-in
-@code{defmacro} function, but any list that begins with @code{macro} is
-a macro as far as Emacs is concerned. @xref{Macros}, for an explanation
-of how to write a macro.
-
-@node Primitive Function Type
-@subsection Primitive Function Type
-@cindex special forms
-
- A @dfn{primitive function} is a function callable from Lisp but
-written in the C programming language. Primitive functions are also
-called @dfn{subrs} or @dfn{built-in functions}. (The word ``subr'' is
-derived from ``subroutine''.) Most primitive functions evaluate all
-their arguments when they are called. A primitive function that does
-not evaluate all its arguments is called a @dfn{special form}
-(@pxref{Special Forms}).@refill
-
- It does not matter to the caller of a function whether the function is
-primitive. However, this does matter if you try to substitute a
-function written in Lisp for a primitive of the same name. The reason
-is that the primitive function may be called directly from C code.
-Calls to the redefined function from Lisp will use the new definition,
-but calls from C code may still use the built-in definition.
-
- The term @dfn{function} refers to all Emacs functions, whether written
-in Lisp or C. @xref{Function Type}, for information about the
-functions written in Lisp.
-
- Primitive functions have no read syntax and print in hash notation
-with the name of the subroutine.
-
-@example
-@group
-(symbol-function 'car) ; @r{Access the function cell}
- ; @r{of the symbol.}
- @result{} #<subr car>
-(subrp (symbol-function 'car)) ; @r{Is this a primitive function?}
- @result{} t ; @r{Yes.}
-@end group
-@end example
-
-@node Byte-Code Type
-@subsection Byte-Code Function Type
-
-The byte compiler produces @dfn{byte-code function objects}.
-Internally, a byte-code function object is much like a vector; however,
-the evaluator handles this data type specially when it appears as a
-function to be called. @xref{Byte Compilation}, for information about
-the byte compiler.
-
-The printed representation and read syntax for a byte-code function
-object is like that for a vector, with an additional @samp{#} before the
-opening @samp{[}.
-
-@node Autoload Type
-@subsection Autoload Type
-
- An @dfn{autoload object} is a list whose first element is the symbol
-@code{autoload}. It is stored as the function definition of a symbol as
-a placeholder for the real definition; it says that the real definition
-is found in a file of Lisp code that should be loaded when necessary.
-The autoload object contains the name of the file, plus some other
-information about the real definition.
-
- After the file has been loaded, the symbol should have a new function
-definition that is not an autoload object. The new definition is then
-called as if it had been there to begin with. From the user's point of
-view, the function call works as expected, using the function definition
-in the loaded file.
-
- An autoload object is usually created with the function
-@code{autoload}, which stores the object in the function cell of a
-symbol. @xref{Autoload}, for more details.
-
-@node Editing Types
-@section Editing Types
-@cindex editing types
-
- The types in the previous section are common to many Lisp dialects.
-Emacs Lisp provides several additional data types for purposes connected
-with editing.
-
-@menu
-* Buffer Type:: The basic object of editing.
-* Marker Type:: A position in a buffer.
-* Window Type:: Buffers are displayed in windows.
-* Frame Type:: Windows subdivide frames.
-* Window Configuration Type:: Recording the way a frame is subdivided.
-* Process Type:: A process running on the underlying OS.
-* Stream Type:: Receive or send characters.
-* Keymap Type:: What function a keystroke invokes.
-* Syntax Table Type:: What a character means.
-* Display Table Type:: How display tables are represented.
-* Overlay Type:: How an overlay is represented.
-@end menu
-
-@node Buffer Type
-@subsection Buffer Type
-
- A @dfn{buffer} is an object that holds text that can be edited
-(@pxref{Buffers}). Most buffers hold the contents of a disk file
-(@pxref{Files}) so they can be edited, but some are used for other
-purposes. Most buffers are also meant to be seen by the user, and
-therefore displayed, at some time, in a window (@pxref{Windows}). But a
-buffer need not be displayed in any window.
-
- The contents of a buffer are much like a string, but buffers are not
-used like strings in Emacs Lisp, and the available operations are
-different. For example, insertion of text into a buffer is very
-efficient, whereas ``inserting'' text into a string requires
-concatenating substrings, and the result is an entirely new string
-object.
-
- Each buffer has a designated position called @dfn{point}
-(@pxref{Positions}). At any time, one buffer is the @dfn{current
-buffer}. Most editing commands act on the contents of the current
-buffer in the neighborhood of point. Many of the standard Emacs
-functions manipulate or test the characters in the current buffer; a
-whole chapter in this manual is devoted to describing these functions
-(@pxref{Text}).
-
- Several other data structures are associated with each buffer:
-
-@itemize @bullet
-@item
-a local syntax table (@pxref{Syntax Tables});
-
-@item
-a local keymap (@pxref{Keymaps}); and,
-
-@item
-a local variable binding list (@pxref{Buffer-Local Variables}).
-
-@item
-a list of overlays (@pxref{Overlays}).
-
-@item
-text properties for the text in the buffer (@pxref{Text Properties}).
-@end itemize
-
-@noindent
-The local keymap and variable list contain entries that individually
-override global bindings or values. These are used to customize the
-behavior of programs in different buffers, without actually changing the
-programs.
-
- A buffer may be @dfn{indirect}, which means it shares the text
-of another buffer. @xref{Indirect Buffers}.
-
- Buffers have no read syntax. They print in hash notation, showing the
-buffer name.
-
-@example
-@group
-(current-buffer)
- @result{} #<buffer objects.texi>
-@end group
-@end example
-
-@node Marker Type
-@subsection Marker Type
-
- A @dfn{marker} denotes a position in a specific buffer. Markers
-therefore have two components: one for the buffer, and one for the
-position. Changes in the buffer's text automatically relocate the
-position value as necessary to ensure that the marker always points
-between the same two characters in the buffer.
-
- Markers have no read syntax. They print in hash notation, giving the
-current character position and the name of the buffer.
-
-@example
-@group
-(point-marker)
- @result{} #<marker at 10779 in objects.texi>
-@end group
-@end example
-
-@xref{Markers}, for information on how to test, create, copy, and move
-markers.
-
-@node Window Type
-@subsection Window Type
-
- A @dfn{window} describes the portion of the terminal screen that Emacs
-uses to display a buffer. Every window has one associated buffer, whose
-contents appear in the window. By contrast, a given buffer may appear
-in one window, no window, or several windows.
-
- Though many windows may exist simultaneously, at any time one window
-is designated the @dfn{selected window}. This is the window where the
-cursor is (usually) displayed when Emacs is ready for a command. The
-selected window usually displays the current buffer, but this is not
-necessarily the case.
-
- Windows are grouped on the screen into frames; each window belongs to
-one and only one frame. @xref{Frame Type}.
-
- Windows have no read syntax. They print in hash notation, giving the
-window number and the name of the buffer being displayed. The window
-numbers exist to identify windows uniquely, since the buffer displayed
-in any given window can change frequently.
-
-@example
-@group
-(selected-window)
- @result{} #<window 1 on objects.texi>
-@end group
-@end example
-
- @xref{Windows}, for a description of the functions that work on windows.
-
-@node Frame Type
-@subsection Frame Type
-
- A @var{frame} is a rectangle on the screen that contains one or more
-Emacs windows. A frame initially contains a single main window (plus
-perhaps a minibuffer window) which you can subdivide vertically or
-horizontally into smaller windows.
-
- Frames have no read syntax. They print in hash notation, giving the
-frame's title, plus its address in core (useful to identify the frame
-uniquely).
-
-@example
-@group
-(selected-frame)
- @result{} #<frame xemacs@@mole.gnu.ai.mit.edu 0xdac80>
-@end group
-@end example
-
- @xref{Frames}, for a description of the functions that work on frames.
-
-@node Window Configuration Type
-@subsection Window Configuration Type
-@cindex screen layout
-
- A @dfn{window configuration} stores information about the positions,
-sizes, and contents of the windows in a frame, so you can recreate the
-same arrangement of windows later.
-
- Window configurations do not have a read syntax; their print syntax
-looks like @samp{#<window-configuration>}. @xref{Window
-Configurations}, for a description of several functions related to
-window configurations.
-
-@node Process Type
-@subsection Process Type
-
- The word @dfn{process} usually means a running program. Emacs itself
-runs in a process of this sort. However, in Emacs Lisp, a process is a
-Lisp object that designates a subprocess created by the Emacs process.
-Programs such as shells, GDB, ftp, and compilers, running in
-subprocesses of Emacs, extend the capabilities of Emacs.
-
- An Emacs subprocess takes textual input from Emacs and returns textual
-output to Emacs for further manipulation. Emacs can also send signals
-to the subprocess.
-
- Process objects have no read syntax. They print in hash notation,
-giving the name of the process:
-
-@example
-@group
-(process-list)
- @result{} (#<process shell>)
-@end group
-@end example
-
-@xref{Processes}, for information about functions that create, delete,
-return information about, send input or signals to, and receive output
-from processes.
-
-@node Stream Type
-@subsection Stream Type
-
- A @dfn{stream} is an object that can be used as a source or sink for
-characters---either to supply characters for input or to accept them as
-output. Many different types can be used this way: markers, buffers,
-strings, and functions. Most often, input streams (character sources)
-obtain characters from the keyboard, a buffer, or a file, and output
-streams (character sinks) send characters to a buffer, such as a
-@file{*Help*} buffer, or to the echo area.
-
- The object @code{nil}, in addition to its other meanings, may be used
-as a stream. It stands for the value of the variable
-@code{standard-input} or @code{standard-output}. Also, the object
-@code{t} as a stream specifies input using the minibuffer
-(@pxref{Minibuffers}) or output in the echo area (@pxref{The Echo
-Area}).
-
- Streams have no special printed representation or read syntax, and
-print as whatever primitive type they are.
-
- @xref{Read and Print}, for a description of functions
-related to streams, including parsing and printing functions.
-
-@node Keymap Type
-@subsection Keymap Type
-
- A @dfn{keymap} maps keys typed by the user to commands. This mapping
-controls how the user's command input is executed. A keymap is actually
-a list whose @sc{car} is the symbol @code{keymap}.
-
- @xref{Keymaps}, for information about creating keymaps, handling prefix
-keys, local as well as global keymaps, and changing key bindings.
-
-@node Syntax Table Type
-@subsection Syntax Table Type
-
- A @dfn{syntax table} is a vector of 256 integers. Each element of the
-vector defines how one character is interpreted when it appears in a
-buffer. For example, in C mode (@pxref{Major Modes}), the @samp{+}
-character is punctuation, but in Lisp mode it is a valid character in a
-symbol. These modes specify different interpretations by changing the
-syntax table entry for @samp{+}, at index 43 in the syntax table.
-
- Syntax tables are used only for scanning text in buffers, not for
-reading Lisp expressions. The table the Lisp interpreter uses to read
-expressions is built into the Emacs source code and cannot be changed;
-thus, to change the list delimiters to be @samp{@{} and @samp{@}}
-instead of @samp{(} and @samp{)} would be impossible.
-
- @xref{Syntax Tables}, for details about syntax classes and how to make
-and modify syntax tables.
-
-@node Display Table Type
-@subsection Display Table Type
-
- A @dfn{display table} specifies how to display each character code.
-Each buffer and each window can have its own display table. A display
-table is actually a vector of length 262. @xref{Display Tables}.
-
-@node Overlay Type
-@subsection Overlay Type
-
- An @dfn{overlay} specifies temporary alteration of the display
-appearance of a part of a buffer. It contains markers delimiting a
-range of the buffer, plus a property list (a list whose elements are
-alternating property names and values). Overlays are used to present
-parts of the buffer temporarily in a different display style. They have
-no read syntax, and print in hash notation, giving the buffer name and
-range of positions.
-
- @xref{Overlays}, for how to create and use overlays.
-
-@node Type Predicates
-@section Type Predicates
-@cindex predicates
-@cindex type checking
-@kindex wrong-type-argument
-
- The Emacs Lisp interpreter itself does not perform type checking on
-the actual arguments passed to functions when they are called. It could
-not do so, since function arguments in Lisp do not have declared data
-types, as they do in other programming languages. It is therefore up to
-the individual function to test whether each actual argument belongs to
-a type that the function can use.
-
- All built-in functions do check the types of their actual arguments
-when appropriate, and signal a @code{wrong-type-argument} error if an
-argument is of the wrong type. For example, here is what happens if you
-pass an argument to @code{+} that it cannot handle:
-
-@example
-@group
-(+ 2 'a)
- @error{} Wrong type argument: integer-or-marker-p, a
-@end group
-@end example
-
-@cindex type predicates
-@cindex testing types
- If you want your program to handle different types differently, you
-must do explicit type checking. The most common way to check the type
-of an object is to call a @dfn{type predicate} function. Emacs has a
-type predicate for each type, as well as some predicates for
-combinations of types.
-
- A type predicate function takes one argument; it returns @code{t} if
-the argument belongs to the appropriate type, and @code{nil} otherwise.
-Following a general Lisp convention for predicate functions, most type
-predicates' names end with @samp{p}.
-
- Here is an example which uses the predicates @code{listp} to check for
-a list and @code{symbolp} to check for a symbol.
-
-@example
-(defun add-on (x)
- (cond ((symbolp x)
- ;; If X is a symbol, put it on LIST.
- (setq list (cons x list)))
- ((listp x)
- ;; If X is a list, add its elements to LIST.
- (setq list (append x list)))
-@need 3000
- (t
- ;; We only handle symbols and lists.
- (error "Invalid argument %s in add-on" x))))
-@end example
-
- Here is a table of predefined type predicates, in alphabetical order,
-with references to further information.
-
-@table @code
-@item atom
-@xref{List-related Predicates, atom}.
-
-@item arrayp
-@xref{Array Functions, arrayp}.
-
-@item bufferp
-@xref{Buffer Basics, bufferp}.
-
-@item byte-code-function-p
-@xref{Byte-Code Type, byte-code-function-p}.
-
-@item case-table-p
-@xref{Case Table, case-table-p}.
-
-@item char-or-string-p
-@xref{Predicates for Strings, char-or-string-p}.
-
-@item commandp
-@xref{Interactive Call, commandp}.
-
-@item consp
-@xref{List-related Predicates, consp}.
-
-@item floatp
-@xref{Predicates on Numbers, floatp}.
-
-@item frame-live-p
-@xref{Deleting Frames, frame-live-p}.
-
-@item framep
-@xref{Frames, framep}.
-
-@item integer-or-marker-p
-@xref{Predicates on Markers, integer-or-marker-p}.
-
-@item integerp
-@xref{Predicates on Numbers, integerp}.
-
-@item keymapp
-@xref{Creating Keymaps, keymapp}.
-
-@item listp
-@xref{List-related Predicates, listp}.
-
-@item markerp
-@xref{Predicates on Markers, markerp}.
-
-@item wholenump
-@xref{Predicates on Numbers, wholenump}.
-
-@item nlistp
-@xref{List-related Predicates, nlistp}.
-
-@item numberp
-@xref{Predicates on Numbers, numberp}.
-
-@item number-or-marker-p
-@xref{Predicates on Markers, number-or-marker-p}.
-
-@item overlayp
-@xref{Overlays, overlayp}.
-
-@item processp
-@xref{Processes, processp}.
-
-@item sequencep
-@xref{Sequence Functions, sequencep}.
-
-@item stringp
-@xref{Predicates for Strings, stringp}.
-
-@item subrp
-@xref{Function Cells, subrp}.
-
-@item symbolp
-@xref{Symbols, symbolp}.
-
-@item syntax-table-p
-@xref{Syntax Tables, syntax-table-p}.
-
-@item user-variable-p
-@xref{Defining Variables, user-variable-p}.
-
-@item vectorp
-@xref{Vectors, vectorp}.
-
-@item window-configuration-p
-@xref{Window Configurations, window-configuration-p}.
-
-@item window-live-p
-@xref{Deleting Windows, window-live-p}.
-
-@item windowp
-@xref{Basic Windows, windowp}.
-@end table
-
- The most general way to check the type of an object is to call the
-function @code{type-of}. Recall that each object belongs to one and
-only one primitive type; @code{type-of} tells you which one (@pxref{Lisp
-Data Types}). But @code{type-of} knows nothing about non-primitive
-types. In most cases, it is more convenient to use type predicates than
-@code{type-of}.
-
-@defun type-of object
-This function returns a symbol naming the primitive type of
-@var{object}. The value is one of the symbols @code{symbol},
-@code{integer}, @code{float}, @code{string}, @code{cons}, @code{vector},
-@code{marker}, @code{overlay}, @code{window}, @code{buffer},
-@code{subr}, @code{compiled-function}, @code{process}, or
-@code{window-configuration}.
-
-@example
-(type-of 1)
- @result{} integer
-(type-of 'nil)
- @result{} symbol
-(type-of '()) ; @r{@code{()} is @code{nil}.}
- @result{} symbol
-(type-of '(x))
- @result{} cons
-@end example
-@end defun
-
-@node Equality Predicates
-@section Equality Predicates
-@cindex equality
-
- Here we describe two functions that test for equality between any two
-objects. Other functions test equality between objects of specific
-types, e.g., strings. For these predicates, see the appropriate chapter
-describing the data type.
-
-@defun eq object1 object2
-This function returns @code{t} if @var{object1} and @var{object2} are
-the same object, @code{nil} otherwise. The ``same object'' means that a
-change in one will be reflected by the same change in the other.
-
-@code{eq} returns @code{t} if @var{object1} and @var{object2} are
-integers with the same value. Also, since symbol names are normally
-unique, if the arguments are symbols with the same name, they are
-@code{eq}. For other types (e.g., lists, vectors, strings), two
-arguments with the same contents or elements are not necessarily
-@code{eq} to each other: they are @code{eq} only if they are the same
-object.
-
-(The @code{make-symbol} function returns an uninterned symbol that is
-not interned in the standard @code{obarray}. When uninterned symbols
-are in use, symbol names are no longer unique. Distinct symbols with
-the same name are not @code{eq}. @xref{Creating Symbols}.)
-
-@example
-@group
-(eq 'foo 'foo)
- @result{} t
-@end group
-
-@group
-(eq 456 456)
- @result{} t
-@end group
-
-@group
-(eq "asdf" "asdf")
- @result{} nil
-@end group
-
-@group
-(eq '(1 (2 (3))) '(1 (2 (3))))
- @result{} nil
-@end group
-
-@group
-(setq foo '(1 (2 (3))))
- @result{} (1 (2 (3)))
-(eq foo foo)
- @result{} t
-(eq foo '(1 (2 (3))))
- @result{} nil
-@end group
-
-@group
-(eq [(1 2) 3] [(1 2) 3])
- @result{} nil
-@end group
-
-@group
-(eq (point-marker) (point-marker))
- @result{} nil
-@end group
-@end example
-
-@end defun
-
-@defun equal object1 object2
-This function returns @code{t} if @var{object1} and @var{object2} have
-equal components, @code{nil} otherwise. Whereas @code{eq} tests if its
-arguments are the same object, @code{equal} looks inside nonidentical
-arguments to see if their elements are the same. So, if two objects are
-@code{eq}, they are @code{equal}, but the converse is not always true.
-
-@example
-@group
-(equal 'foo 'foo)
- @result{} t
-@end group
-
-@group
-(equal 456 456)
- @result{} t
-@end group
-
-@group
-(equal "asdf" "asdf")
- @result{} t
-@end group
-@group
-(eq "asdf" "asdf")
- @result{} nil
-@end group
-
-@group
-(equal '(1 (2 (3))) '(1 (2 (3))))
- @result{} t
-@end group
-@group
-(eq '(1 (2 (3))) '(1 (2 (3))))
- @result{} nil
-@end group
-
-@group
-(equal [(1 2) 3] [(1 2) 3])
- @result{} t
-@end group
-@group
-(eq [(1 2) 3] [(1 2) 3])
- @result{} nil
-@end group
-
-@group
-(equal (point-marker) (point-marker))
- @result{} t
-@end group
-
-@group
-(eq (point-marker) (point-marker))
- @result{} nil
-@end group
-@end example
-
-Comparison of strings is case-sensitive and takes account of text
-properties as well as the characters in the strings. To compare
-two strings' characters without comparing their text properties,
-use @code{string=} (@pxref{Text Comparison}).
-
-@example
-@group
-(equal "asdf" "ASDF")
- @result{} nil
-@end group
-@end example
-
-Two distinct buffers are never @code{equal}, even if their contents
-are the same.
-@end defun
-
- The test for equality is implemented recursively, and circular lists may
-therefore cause infinite recursion (leading to an error).
diff --git a/lispref/os.texi b/lispref/os.texi
deleted file mode 100644
index 3c7e46518f3..00000000000
--- a/lispref/os.texi
+++ /dev/null
@@ -1,1700 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/os
-@node System Interface, Display, Processes, Top
-@chapter Operating System Interface
-
- This chapter is about starting and getting out of Emacs, access to
-values in the operating system environment, and terminal input, output,
-and flow control.
-
- @xref{Building Emacs}, for related information. See also
-@ref{Display}, for additional operating system status information
-pertaining to the terminal and the screen.
-
-@menu
-* Starting Up:: Customizing Emacs start-up processing.
-* Getting Out:: How exiting works (permanent or temporary).
-* System Environment:: Distinguish the name and kind of system.
-* User Identification:: Finding the name and user id of the user.
-* Time of Day:: Getting the current time.
-* Time Conversion:: Converting a time from numeric form to a string, or
- to calendrical data (or vice versa).
-* Timers:: Setting a timer to call a function at a certain time.
-* Terminal Input:: Recording terminal input for debugging.
-* Terminal Output:: Recording terminal output for debugging.
-* Special Keysyms:: Defining system-specific key symbols for X windows.
-* Flow Control:: How to turn output flow control on or off.
-* Batch Mode:: Running Emacs without terminal interaction.
-@end menu
-
-@node Starting Up
-@section Starting Up Emacs
-
- This section describes what Emacs does when it is started, and how you
-can customize these actions.
-
-@menu
-* Start-up Summary:: Sequence of actions Emacs performs at start-up.
-* Init File:: Details on reading the init file (@file{.emacs}).
-* Terminal-Specific:: How the terminal-specific Lisp file is read.
-* Command Line Arguments:: How command line arguments are processed,
- and how you can customize them.
-@end menu
-
-@node Start-up Summary
-@subsection Summary: Sequence of Actions at Start Up
-@cindex initialization
-@cindex start up of Emacs
-@cindex @file{startup.el}
-
- The order of operations performed (in @file{startup.el}) by Emacs when
-it is started up is as follows:
-
-@enumerate
-@item
-It loads the initialization library for the window system, if you are
-using a window system. This library's name is
-@file{term/@var{windowsystem}-win.el}.
-
-@item
-It processes the initial options. (Some of them are handled
-even earlier than this.)
-
-@item
-It initializes the X window frame and faces, if appropriate.
-
-@item
-It runs the normal hook @code{before-init-hook}.
-
-@item
-It loads the library @file{site-start}, unless the option
-@samp{-no-site-file} was specified. The library's file name is usually
-@file{site-start.el}.
-@cindex @file{site-start.el}
-
-@item
-It loads the file @file{~/.emacs} unless @samp{-q} was specified on
-the command line. (This is not done in @samp{-batch} mode.) The @samp{-u}
-option can specify the user name whose home directory should be used
-instead of @file{~}.
-
-@item
-It loads the library @file{default} unless @code{inhibit-default-init}
-is non-@code{nil}. (This is not done in @samp{-batch} mode or if
-@samp{-q} was specified on the command line.) The library's file name
-is usually @file{default.el}.
-@cindex @file{default.el}
-
-@item
-It runs the normal hook @code{after-init-hook}.
-
-@item
-It sets the major mode according to @code{initial-major-mode}, provided
-the buffer @samp{*scratch*} is still current and still in Fundamental
-mode.
-
-@item
-It loads the terminal-specific Lisp file, if any, except when in batch
-mode or using a window system.
-
-@item
-It displays the initial echo area message, unless you have suppressed
-that with @code{inhibit-startup-echo-area-message}.
-
-@item
-It processes the action arguments from the command line.
-
-@item
-It runs @code{term-setup-hook}.
-
-@item
-It calls @code{frame-notice-user-settings}, which modifies the
-parameters of the selected frame according to whatever the init files
-specify.
-
-@item
-It runs @code{window-setup-hook}. @xref{Window Systems}.
-
-@item
-It displays copyleft, nonwarranty, and basic use information, provided
-there were no remaining command line arguments (a few steps above) and
-the value of @code{inhibit-startup-message} is @code{nil}.
-@end enumerate
-
-@defopt inhibit-startup-message
-This variable inhibits the initial startup messages (the nonwarranty,
-etc.). If it is non-@code{nil}, then the messages are not printed.
-
-This variable exists so you can set it in your personal init file, once
-you are familiar with the contents of the startup message. Do not set
-this variable in the init file of a new user, or in a way that affects
-more than one user, because that would prevent new users from receiving
-the information they are supposed to see.
-@end defopt
-
-@defopt inhibit-startup-echo-area-message
-This variable controls the display of the startup echo area message.
-You can suppress the startup echo area message by adding text with this
-form to your @file{.emacs} file:
-
-@example
-(setq inhibit-startup-echo-area-message
- "@var{your-login-name}")
-@end example
-
-Simply setting @code{inhibit-startup-echo-area-message} to your login
-name is not sufficient to inhibit the message; Emacs explicitly checks
-whether @file{.emacs} contains an expression as shown above. Your login
-name must appear in the expression as a Lisp string constant.
-
-This way, you can easily inhibit the message for yourself if you wish,
-but thoughtless copying of your @file{.emacs} file will not inhibit the
-message for someone else.
-@end defopt
-
-@node Init File
-@subsection The Init File: @file{.emacs}
-@cindex init file
-@cindex @file{.emacs}
-
- When you start Emacs, it normally attempts to load the file
-@file{.emacs} from your home directory. This file, if it exists, must
-contain Lisp code. It is called your @dfn{init file}. The command line
-switches @samp{-q} and @samp{-u} affect the use of the init file;
-@samp{-q} says not to load an init file, and @samp{-u} says to load a
-specified user's init file instead of yours. @xref{Entering Emacs,,,
-emacs, The GNU Emacs Manual}.
-
-@cindex default init file
- A site may have a @dfn{default init file}, which is the library named
-@file{default.el}. Emacs finds the @file{default.el} file through the
-standard search path for libraries (@pxref{How Programs Do Loading}).
-The Emacs distribution does not come with this file; sites may provide
-one for local customizations. If the default init file exists, it is
-loaded whenever you start Emacs, except in batch mode or if @samp{-q} is
-specified. But your own personal init file, if any, is loaded first; if
-it sets @code{inhibit-default-init} to a non-@code{nil} value, then
-Emacs does not subsequently load the @file{default.el} file.
-
- Another file for site-customization is @file{site-start.el}. Emacs
-loads this @emph{before} the user's init file. You can inhibit the
-loading of this file with the option @samp{-no-site-file}.
-
-@defvar site-run-file
-This variable specifies the site-customization file to load
-before the user's init file. Its normal value is @code{"site-start"}.
-@end defvar
-
- If there is a great deal of code in your @file{.emacs} file, you
-should move it into another file named @file{@var{something}.el},
-byte-compile it (@pxref{Byte Compilation}), and make your @file{.emacs}
-file load the other file using @code{load} (@pxref{Loading}).
-
- @xref{Init File Examples,,, emacs, The GNU Emacs Manual}, for
-examples of how to make various commonly desired customizations in your
-@file{.emacs} file.
-
-@defopt inhibit-default-init
-This variable prevents Emacs from loading the default initialization
-library file for your session of Emacs. If its value is non-@code{nil},
-then the default library is not loaded. The default value is
-@code{nil}.
-@end defopt
-
-@defvar before-init-hook
-@defvarx after-init-hook
-These two normal hooks are run just before, and just after, loading of
-the user's init file, @file{default.el}, and/or @file{site-start.el}.
-@end defvar
-
-@node Terminal-Specific
-@subsection Terminal-Specific Initialization
-@cindex terminal-specific initialization
-
- Each terminal type can have its own Lisp library that Emacs loads when
-run on that type of terminal. For a terminal type named @var{termtype},
-the library is called @file{term/@var{termtype}}. Emacs finds the file
-by searching the @code{load-path} directories as it does for other
-files, and trying the @samp{.elc} and @samp{.el} suffixes. Normally,
-terminal-specific Lisp library is located in @file{emacs/lisp/term}, a
-subdirectory of the @file{emacs/lisp} directory in which most Emacs Lisp
-libraries are kept.@refill
-
- The library's name is constructed by concatenating the value of the
-variable @code{term-file-prefix} and the terminal type. Normally,
-@code{term-file-prefix} has the value @code{"term/"}; changing this
-is not recommended.
-
- The usual function of a terminal-specific library is to enable special
-keys to send sequences that Emacs can recognize. It may also need to
-set or add to @code{function-key-map} if the Termcap entry does not
-specify all the terminal's function keys. @xref{Terminal Input}.
-
-@cindex Termcap
- When the name of 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 @file{term/aaa} library. If necessary, the library can evaluate
-@code{(getenv "TERM")} to find the full name of the terminal
-type.@refill
-
- Your @file{.emacs} file can prevent the loading of the
-terminal-specific library by setting the variable
-@code{term-file-prefix} to @code{nil}. This feature is useful when
-experimenting with your own peculiar customizations.
-
- You can also arrange to override some of the actions of the
-terminal-specific library by setting the variable
-@code{term-setup-hook}. This is a normal hook which Emacs runs using
-@code{run-hooks} at the end of Emacs initialization, after loading both
-your @file{.emacs} file and any terminal-specific libraries. You can
-use this variable to define initializations for terminals that do not
-have their own libraries. @xref{Hooks}.
-
-@defvar term-file-prefix
-@cindex @code{TERM} environment variable
-If the @code{term-file-prefix} variable is non-@code{nil}, Emacs loads
-a terminal-specific initialization file as follows:
-
-@example
-(load (concat term-file-prefix (getenv "TERM")))
-@end example
-
-@noindent
-You may set the @code{term-file-prefix} variable to @code{nil} in your
-@file{.emacs} file if you do not wish to load the
-terminal-initialization file. To do this, put the following in
-your @file{.emacs} file: @code{(setq term-file-prefix nil)}.
-@end defvar
-
-@defvar term-setup-hook
-This variable is a normal hook that Emacs runs after loading your
-@file{.emacs} file, the default initialization file (if any) and the
-terminal-specific Lisp file.
-
-You can use @code{term-setup-hook} to override the definitions made by a
-terminal-specific file.
-@end defvar
-
- See @code{window-setup-hook} in @ref{Window Systems}, for a related
-feature.
-
-@node Command Line Arguments
-@subsection Command Line Arguments
-@cindex command line arguments
-
- You can use command line arguments to request various actions when you
-start Emacs. Since you do not need to start Emacs more than once per
-day, and will often leave your Emacs session running longer than that,
-command line arguments are hardly ever used. As a practical matter, it
-is best to avoid making the habit of using them, since this habit would
-encourage you to kill and restart Emacs unnecessarily often. These
-options exist for two reasons: to be compatible with other editors (for
-invocation by other programs) and to enable shell scripts to run
-specific Lisp programs.
-
- This section describes how Emacs processes command line arguments,
-and how you can customize them.
-
-@ignore
- (Note that some other editors require you to start afresh each time
-you want to edit a file. With this kind of editor, you will probably
-specify the file as a command line argument. 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.)
-@end ignore
-
-@defun command-line
-This function parses the command line that Emacs was called with,
-processes it, loads the user's @file{.emacs} file and displays the
-startup messages.
-@end defun
-
-@defvar command-line-processed
-The value of this variable is @code{t} once the command line has been
-processed.
-
-If you redump Emacs by calling @code{dump-emacs}, you may wish to set
-this variable to @code{nil} first in order to cause the new dumped Emacs
-to process its new command line arguments.
-@end defvar
-
-@defvar command-switch-alist
-@cindex switches on command line
-@cindex options on command line
-@cindex command line options
-The value of this variable is an alist of user-defined command-line
-options and associated handler functions. This variable exists so you
-can add elements to it.
-
-A @dfn{command line option} is an argument on the command line of the
-form:
-
-@example
--@var{option}
-@end example
-
-The elements of the @code{command-switch-alist} look like this:
-
-@example
-(@var{option} . @var{handler-function})
-@end example
-
-The @var{handler-function} is called to handle @var{option} and receives
-the option name as its sole argument.
-
-In some cases, the option is followed in the command line by an
-argument. In these cases, the @var{handler-function} can find all the
-remaining command-line arguments in the variable
-@code{command-line-args-left}. (The entire list of command-line
-arguments is in @code{command-line-args}.)
-
-The command line arguments are parsed by the @code{command-line-1}
-function in the @file{startup.el} file. See also @ref{Command
-Switches, , Command Line Switches and Arguments, emacs, The GNU Emacs
-Manual}.
-@end defvar
-
-@defvar command-line-args
-The value of this variable is the list of command line arguments passed
-to Emacs.
-@end defvar
-
-@defvar command-line-functions
-This variable's value is a list of functions for handling an
-unrecognized command-line argument. Each time the next argument to be
-processed has no special meaning, the functions in this list are called,
-in order of appearance, until one of them returns a non-@code{nil}
-value.
-
-These functions are called with no arguments. They can access the
-command-line argument under consideration through the variable
-@code{argi}. The remaining arguments (not including the current one)
-are in the variable @code{command-line-args-left}.
-
-When a function recognizes and processes the argument in @code{argi}, it
-should return a non-@code{nil} value to say it has dealt with that
-argument. If it has also dealt with some of the following arguments, it
-can indicate that by deleting them from @code{command-line-args-left}.
-
-If all of these functions return @code{nil}, then the argument is used
-as a file name to visit.
-@end defvar
-
-@node Getting Out
-@section Getting Out of Emacs
-@cindex exiting Emacs
-
- There are two ways to get out of Emacs: you can kill the Emacs job,
-which exits permanently, or you can suspend it, which permits you to
-reenter the Emacs process later. As a practical matter, you seldom kill
-Emacs---only when you are about to log out. Suspending is much more
-common.
-
-@menu
-* Killing Emacs:: Exiting Emacs irreversibly.
-* Suspending Emacs:: Exiting Emacs reversibly.
-@end menu
-
-@node Killing Emacs
-@comment node-name, next, previous, up
-@subsection Killing Emacs
-@cindex killing Emacs
-
- Killing Emacs means ending the execution of the Emacs process. The
-parent process normally resumes control. The low-level primitive for
-killing Emacs is @code{kill-emacs}.
-
-@defun kill-emacs &optional exit-data
-This function exits the Emacs process and kills it.
-
-If @var{exit-data} is an integer, then it is used as the exit status
-of the Emacs process. (This is useful primarily in batch operation; see
-@ref{Batch Mode}.)
-
-If @var{exit-data} is a string, its contents are stuffed into the
-terminal input buffer so that the shell (or whatever program next reads
-input) can read them.
-@end defun
-
- All the information in the Emacs process, aside from files that have
-been saved, is lost when the Emacs is killed. Because killing Emacs
-inadvertently can lose a lot of work, Emacs queries for confirmation
-before actually terminating if you have buffers that need saving or
-subprocesses that are running. This is done in the function
-@code{save-buffers-kill-emacs}.
-
-@defvar kill-emacs-query-functions
-After asking the standard questions, @code{save-buffers-kill-emacs}
-calls the functions in the list @code{kill-buffer-query-functions}, in
-order of appearance, with no arguments. These functions can ask for
-additional confirmation from the user. If any of them returns
-non-@code{nil}, Emacs is not killed.
-@end defvar
-
-@defvar kill-emacs-hook
-This variable is a normal hook; once @code{save-buffers-kill-emacs} is
-finished with all file saving and confirmation, it runs the functions in
-this hook.
-@end defvar
-
-@node Suspending Emacs
-@subsection Suspending Emacs
-@cindex suspending Emacs
-
- @dfn{Suspending Emacs} means stopping Emacs temporarily and returning
-control to its superior process, which is usually the shell. This
-allows you to resume editing later in the same Emacs process, with the
-same buffers, the same kill ring, the same undo history, and so on. To
-resume Emacs, use the appropriate command in the parent shell---most
-likely @code{fg}.
-
- Some operating systems do not support suspension of jobs; on these
-systems, ``suspension'' actually creates a new shell temporarily as a
-subprocess of Emacs. Then you would exit the shell to return to Emacs.
-
- Suspension is not useful with window systems such as X, because the
-Emacs job may not have a parent that can resume it again, and in any
-case you can give input to some other job such as a shell merely by
-moving to a different window. Therefore, suspending is not allowed
-when Emacs is an X client.
-
-@defun suspend-emacs string
-This function stops Emacs and returns control to the superior process.
-If and when the superior process resumes Emacs, @code{suspend-emacs}
-returns @code{nil} to its caller in Lisp.
-
-If @var{string} is non-@code{nil}, its characters are sent to be read
-as terminal input by Emacs's superior shell. The characters in
-@var{string} are not echoed by the superior shell; only the results
-appear.
-
-Before suspending, @code{suspend-emacs} runs the normal hook
-@code{suspend-hook}. In Emacs version 18, @code{suspend-hook} was not a
-normal hook; its value was a single function, and if its value was
-non-@code{nil}, then @code{suspend-emacs} returned immediately without
-actually suspending anything.
-
-After the user resumes Emacs, @code{suspend-emacs} runs the normal hook
-@code{suspend-resume-hook}. @xref{Hooks}.
-
-The next redisplay after resumption will redraw the entire screen,
-unless the variable @code{no-redraw-on-reenter} is non-@code{nil}
-(@pxref{Refresh Screen}).
-
-In the following example, note that @samp{pwd} is not echoed after
-Emacs is suspended. But it is read and executed by the shell.
-
-@smallexample
-@group
-(suspend-emacs)
- @result{} nil
-@end group
-
-@group
-(add-hook 'suspend-hook
- (function (lambda ()
- (or (y-or-n-p
- "Really suspend? ")
- (error "Suspend cancelled")))))
- @result{} (lambda nil
- (or (y-or-n-p "Really suspend? ")
- (error "Suspend cancelled")))
-@end group
-@group
-(add-hook 'suspend-resume-hook
- (function (lambda () (message "Resumed!"))))
- @result{} (lambda nil (message "Resumed!"))
-@end group
-@group
-(suspend-emacs "pwd")
- @result{} nil
-@end group
-@group
----------- Buffer: Minibuffer ----------
-Really suspend? @kbd{y}
----------- Buffer: Minibuffer ----------
-@end group
-
-@group
----------- Parent Shell ----------
-lewis@@slug[23] % /user/lewis/manual
-lewis@@slug[24] % fg
-@end group
-
-@group
----------- Echo Area ----------
-Resumed!
-@end group
-@end smallexample
-@end defun
-
-@defvar suspend-hook
-This variable is a normal hook run before suspending.
-@end defvar
-
-@defvar suspend-resume-hook
-This variable is a normal hook run after suspending.
-@end defvar
-
-@node System Environment
-@section Operating System Environment
-@cindex operating system environment
-
- Emacs provides access to variables in the operating system environment
-through various functions. These variables include the name of the
-system, the user's @sc{uid}, and so on.
-
-@defvar system-type
-The value of this variable is a symbol indicating the type of operating
-system Emacs is operating on. Here is a table of the possible values:
-
-@table @code
-@item aix-v3
-AIX.
-
-@item berkeley-unix
-Berkeley BSD.
-
-@item dgux
-Data General DGUX operating system.
-
-@item gnu
-A GNU system (using the GNU kernel, which consists of the HURD and Mach).
-
-@item gnu/linux
-A variant GNU system using the Linux kernel.
-
-@item hpux
-Hewlett-Packard HPUX operating system.
-
-@item irix
-Silicon Graphics Irix system.
-
-@item ms-dos
-Microsoft MS-DOS ``operating system.''
-
-@item next-mach
-NeXT Mach-based system.
-
-@item rtu
-Masscomp RTU, UCB universe.
-
-@item unisoft-unix
-UniSoft UniPlus.
-
-@item usg-unix-v
-AT&T System V.
-
-@item vax-vms
-VAX VMS.
-
-@item windows-nt
-Microsoft windows NT.
-
-@item xenix
-SCO Xenix 386.
-@end table
-
-We do not wish to add new symbols to make finer distinctions unless it
-is absolutely necessary! In fact, we hope to eliminate some of these
-alternatives in the future. We recommend using
-@code{system-configuration} to distinguish between different operating
-systems.
-@end defvar
-
-@defvar system-configuration
-This variable holds the three-part configuration name for the
-hardware/software configuration of your system, as a string. The
-convenient way to test parts of this string is with @code{string-match}.
-@end defvar
-
-@defun system-name
-This function returns the name of the machine you are running on.
-@example
-(system-name)
- @result{} "prep.ai.mit.edu"
-@end example
-@end defun
-
-@vindex system-name
- The symbol @code{system-name} is a variable as well as a function. In
-fact, the function returns whatever value the variable
-@code{system-name} currently holds. Thus, you can set the variable
-@code{system-name} in case Emacs is confused about the name of your
-system. The variable is also useful for constructing frame titles
-(@pxref{Frame Titles}).
-
-@defvar mail-host-address
-If this variable is non-@code{nil}, it is used instead of
-@code{system-name} for purposes of generating email addresses. For
-example, it is used when constructing the default value of
-@code{user-mail-address}. @xref{User Identification}. (Since this is
-done when Emacs starts up, the value actually used is the one saved when
-Emacs was dumped. @xref{Building Emacs}.)
-@end defvar
-
-@defun getenv var
-@cindex environment variable access
-This function returns the value of the environment variable @var{var},
-as a string. Within Emacs, the environment variable values are kept in
-the Lisp variable @code{process-environment}.
-
-@example
-@group
-(getenv "USER")
- @result{} "lewis"
-@end group
-
-@group
-lewis@@slug[10] % printenv
-PATH=.:/user/lewis/bin:/usr/bin:/usr/local/bin
-USER=lewis
-@end group
-@group
-TERM=ibmapa16
-SHELL=/bin/csh
-HOME=/user/lewis
-@end group
-@end example
-@end defun
-
-@c Emacs 19 feature
-@deffn Command setenv variable value
-This command sets the value of the environment variable named
-@var{variable} to @var{value}. Both arguments should be strings. This
-function works by modifying @code{process-environment}; binding that
-variable with @code{let} is also reasonable practice.
-@end deffn
-
-@defvar process-environment
-This variable is a list of strings, each describing one environment
-variable. The functions @code{getenv} and @code{setenv} work by means
-of this variable.
-
-@smallexample
-@group
-process-environment
-@result{} ("l=/usr/stanford/lib/gnuemacs/lisp"
- "PATH=.:/user/lewis/bin:/usr/class:/nfsusr/local/bin"
- "USER=lewis"
-@end group
-@group
- "TERM=ibmapa16"
- "SHELL=/bin/csh"
- "HOME=/user/lewis")
-@end group
-@end smallexample
-@end defvar
-
-@defvar path-separator
-This variable holds a string which says which character separates
-directories in a search path (as found in an environment variable). Its
-value is @code{":"} for Unix and GNU systems, and @code{";"} for MS-DOS
-and Windows NT.
-@end defvar
-
-@defvar invocation-name
-This variable holds the program name under which Emacs was invoked. The
-value is a string, and does not include a directory name.
-@end defvar
-
-@defvar invocation-directory
-This variable holds the directory from which the Emacs executable was
-invoked, or perhaps @code{nil} if that directory cannot be determined.
-@end defvar
-
-@defvar installation-directory
-If non-@code{nil}, this is a directory within which to look for the
-@file{lib-src} and @file{etc} subdirectories. This is non-@code{nil}
-when Emacs can't find those directories in their standard installed
-locations, but can find them in a directory related somehow to the one
-containing the Emacs executable.
-@end defvar
-
-@defun load-average
-This function returns the current 1-minute, 5-minute and 15-minute
-load averages in a list. The values are integers that are 100 times
-the system load averages. (The load averages indicate the number of
-processes trying to run.)
-
-@example
-@group
-(load-average)
- @result{} (169 48 36)
-@end group
-
-@group
-lewis@@rocky[5] % uptime
- 11:55am up 1 day, 19:37, 3 users,
- load average: 1.69, 0.48, 0.36
-@end group
-@end example
-@end defun
-
-@defun emacs-pid
-This function returns the process @sc{id} of the Emacs process.
-@end defun
-
-@defun setprv privilege-name &optional setp getprv
-This function sets or resets a VMS privilege. (It does not exist on
-Unix.) The first arg is the privilege name, as a string. The second
-argument, @var{setp}, is @code{t} or @code{nil}, indicating whether the
-privilege is to be turned on or off. Its default is @code{nil}. The
-function returns @code{t} if successful, @code{nil} otherwise.
-
- If the third argument, @var{getprv}, is non-@code{nil}, @code{setprv}
-does not change the privilege, but returns @code{t} or @code{nil}
-indicating whether the privilege is currently enabled.
-@end defun
-
-@node User Identification
-@section User Identification
-
-@defvar user-mail-address
-This holds the nominal email address of the user who is using Emacs.
-Emacs normally sets this variable to a default value after reading your
-init files, but not if you have already set it. So you can set the
-variable to some other value in your @file{~/.emacs} file if you do not
-want to use the default value.
-@end defvar
-
-@defun user-login-name &optional uid
-If you don't specify @var{uid}, this function returns the name under
-which the user is logged in. If the environment variable @code{LOGNAME}
-is set, that value is used. Otherwise, if the environment variable
-@code{USER} is set, that value is used. Otherwise, the value is based
-on the effective @sc{uid}, not the real @sc{uid}.
-
-If you specify @var{uid}, the value is the user name that corresponds
-to @var{uid} (which should be an integer).
-
-@example
-@group
-(user-login-name)
- @result{} "lewis"
-@end group
-@end example
-@end defun
-
-@defun user-real-login-name
-This function returns the user name corresponding to Emacs's real
-@sc{uid}. This ignores the effective @sc{uid} and ignores the
-environment variables @code{LOGNAME} and @code{USER}.
-@end defun
-
-@defun user-full-name
-This function returns the full name of the user.
-
-@example
-@group
-(user-full-name)
- @result{} "Bil Lewis"
-@end group
-@end example
-@end defun
-
-@vindex user-full-name
-@vindex user-real-login-name
-@vindex user-login-name
- The symbols @code{user-login-name}, @code{user-real-login-name} and
-@code{user-full-name} are variables as well as functions. The functions
-return the same values that the variables hold. These variables allow
-you to ``fake out'' Emacs by telling the functions what to return. The
-variables are also useful for constructing frame titles (@pxref{Frame
-Titles}).
-
-@defun user-real-uid
-This function returns the real @sc{uid} of the user.
-
-@example
-@group
-(user-real-uid)
- @result{} 19
-@end group
-@end example
-@end defun
-
-@defun user-uid
-This function returns the effective @sc{uid} of the user.
-@end defun
-
-@node Time of Day
-@section Time of Day
-
- This section explains how to determine the current time and the time
-zone.
-
-@defun current-time-string &optional time-value
-This function returns the current time and date as a humanly-readable
-string. The format of the string is unvarying; the number of characters
-used for each part is always the same, so you can reliably use
-@code{substring} to extract pieces of it. It is wise to count the
-characters from the beginning of the string rather than from the end, as
-additional information may be added at the end.
-
-@c Emacs 19 feature
-The argument @var{time-value}, if given, specifies a time to format
-instead of the current time. The argument should be a list whose first
-two elements are integers. Thus, you can use times obtained from
-@code{current-time} (see below) and from @code{file-attributes}
-(@pxref{File Attributes}).
-
-@example
-@group
-(current-time-string)
- @result{} "Wed Oct 14 22:21:05 1987"
-@end group
-@end example
-@end defun
-
-@c Emacs 19 feature
-@defun current-time
-This function returns the system's time value as a list of three
-integers: @code{(@var{high} @var{low} @var{microsec})}. The integers
-@var{high} and @var{low} combine to give the number of seconds since
-0:00 January 1, 1970, which is
-@ifinfo
-@var{high} * 2**16 + @var{low}.
-@end ifinfo
-@tex
-$high*2^{16}+low$.
-@end tex
-
-The third element, @var{microsec}, gives the microseconds since the
-start of the current second (or 0 for systems that return time only on
-the resolution of a second).
-
-The first two elements can be compared with file time values such as you
-get with the function @code{file-attributes}. @xref{File Attributes}.
-@end defun
-
-@c Emacs 19 feature
-@defun current-time-zone &optional time-value
-This function returns a list describing the time zone that the user is
-in.
-
-The value has the form @code{(@var{offset} @var{name})}. Here
-@var{offset} is an integer giving the number of seconds ahead of UTC
-(east of Greenwich). A negative value means west of Greenwich. The
-second element, @var{name} is a string giving the name of the time
-zone. Both elements change when daylight savings time begins or ends;
-if the user has specified a time zone that does not use a seasonal time
-adjustment, then the value is constant through time.
-
-If the operating system doesn't supply all the information necessary to
-compute the value, both elements of the list are @code{nil}.
-
-The argument @var{time-value}, if given, specifies a time to analyze
-instead of the current time. The argument should be a cons cell
-containing two integers, or a list whose first two elements are
-integers. Thus, you can use times obtained from @code{current-time}
-(see above) and from @code{file-attributes} (@pxref{File Attributes}).
-@end defun
-
-@node Time Conversion
-@section Time Conversion
-
- These functions convert time values (lists of two or three integers)
-to strings or to calendrical information. There is also a function to
-convert calendrical information to a time value. You can get time
-values from the functions @code{current-time} (@pxref{Time of Day}) and
-@code{file-attributes} (@pxref{File Attributes}).
-
-Many operating systems are limited to time values that contain 32 bits
-of information; these systems typically handle only the times from
-1901-12-13 20:45:52 UTC through 2038-01-19 03:14:07 UTC. However, some
-operating systems have larger time values, and can represent times far
-in the past or future.
-
-Time conversion functions always use the Gregorian calendar, even for
-dates before the Gregorian calendar was introduced. Year numbers count
-the number of years since the year 1 B.C., and do not skip zero as
-traditional Gregorian years do; for example, the year number -37
-represents the Gregorian year 38 B.C@.
-
-@defun format-time-string format-string time
-This function converts @var{time} to a string according to
-@var{format-string}. The argument @var{format-string} may contain
-@samp{%}-sequences which say to substitute parts of the time. Here is a
-table of what the @samp{%}-sequences mean:
-
-@table @samp
-@item %a
-This stands for the abbreviated name of the day of week.
-@item %A
-This stands for the full name of the day of week.
-@item %b
-This stands for the abbreviated name of the month.
-@item %B
-This stands for the full name of the month.
-@item %c
-This is a synonym for @samp{%x %X}.
-@item %C
-This has a locale-specific meaning. In the default locale (named C), it
-is equivalent to @samp{%A, %B %e, %Y}.
-@item %d
-This stands for the day of month, zero-padded.
-@item %D
-This is a synonym for @samp{%m/%d/%y}.
-@item %e
-This stands for the day of month, blank-padded.
-@item %h
-This is a synonym for @samp{%b}.
-@item %H
-This stands for the hour (00-23).
-@item %I
-This stands for the hour (00-12).
-@item %j
-This stands for the day of the year (001-366).
-@item %k
-This stands for the hour (0-23), blank padded.
-@item %l
-This stands for the hour (1-12), blank padded.
-@item %m
-This stands for the month (01-12).
-@item %M
-This stands for the minute (00-59).
-@item %n
-This stands for a newline.
-@item %p
-This stands for @samp{AM} or @samp{PM}, as appropriate.
-@item %r
-This is a synonym for @samp{%I:%M:%S %p}.
-@item %R
-This is a synonym for @samp{%H:%M}.
-@item %S
-This stands for the seconds (00-60).
-@item %t
-This stands for a tab character.
-@item %T
-This is a synonym for @samp{%H:%M:%S}.
-@item %U
-This stands for the week of the year (01-52), assuming that weeks
-start on Sunday.
-@item %w
-This stands for the numeric day of week (0-6). Sunday is day 0.
-@item %W
-This stands for the week of the year (01-52), assuming that weeks
-start on Monday.
-@item %x
-This has a locale-specific meaning. In the default locale (named C), it
-is equivalent to @samp{%D}.
-@item %X
-This has a locale-specific meaning. In the default locale (named C), it
-is equivalent to @samp{%T}.
-@item %y
-This stands for the year without century (00-99).
-@item %Y
-This stands for the year with century.
-@item %Z
-This stands for the time zone abbreviation.
-@end table
-@end defun
-
-@defun decode-time time
-This function converts a time value into calendrical information. The
-return value is a list of nine elements, as follows:
-
-@example
-(@var{seconds} @var{minutes} @var{hour} @var{day} @var{month} @var{year} @var{dow} @var{dst} @var{zone})
-@end example
-
-Here is what the elements mean:
-
-@table @var
-@item sec
-The number of seconds past the minute, as an integer between 0 and 59.
-@item minute
-The number of minutes past the hour, as an integer between 0 and 59.
-@item hour
-The hour of the day, as an integer between 0 and 23.
-@item day
-The day of the month, as an integer between 1 and 31.
-@item month
-The month of the year, as an integer between 1 and 12.
-@item year
-The year, an integer typically greater than 1900.
-@item dow
-The day of week, as an integer between 0 and 6, where 0 stands for
-Sunday.
-@item dst
-@code{t} if daylight savings time is effect, otherwise @code{nil}.
-@item zone
-An integer indicating the time zone, as the number of seconds east of
-Greenwich.
-@end table
-
-Note that Common Lisp has different meanings for @var{dow} and
-@var{zone}.
-@end defun
-
-@defun encode-time seconds minutes hour day month year &optional @dots{}zone
-This function is the inverse of @code{decode-time}. It converts seven
-items of calendrical data into a time value. For the meanings of the
-arguments, see the table above under @code{decode-time}.
-
-Year numbers less than 100 are treated just like other year numbers. If
-you want them to stand for years above 1900, you must alter them yourself
-before you call @code{encode-time}.
-
-The optional argument @var{zone} defaults to the current time zone and
-its daylight savings time rules. If specified, it can be either a list
-(as you would get from @code{current-time-zone}) or an integer (as you
-would get from @code{decode-time}). The specified zone is used without
-any further alteration for daylight savings time.
-
-If you pass more than seven arguments to @code{encode-time}, the first
-six are used as @var{seconds} through @var{year}, the last argument is
-used as @var{zone}, and the arguments in between are ignored. This
-feature makes it possible to use the elements of a list returned by
-@code{decode-time} as the arguments to @code{encode-time}, like this:
-
-@example
-(apply 'encode-time (decode-time @dots{}))
-@end example
-@end defun
-
-@node Timers
-@section Timers for Delayed Execution
-@cindex timer
-
- You can set up a @dfn{timer} to call a function at a specified future time or
-after a certain length of idleness.
-
- Emacs cannot run a timer at any arbitrary point in a Lisp program; it
-can run them only when Emacs could accept output from a subprocess:
-namely, while waiting or inside certain primitive functions such as
-@code{sit-for} or @code{read-char} which @emph{can} wait. Therefore, a
-timer's execution may be delayed if Emacs is busy. However, the time of
-execution is very precise if Emacs is idle.
-
-@defun run-at-time time repeat function &rest args
-This function arranges to call @var{function} with arguments @var{args}
-at time @var{time}. The argument @var{function} is a function to call
-later, and @var{args} are the arguments to give it when it is called.
-The time @var{time} is specified as a string.
-
-Absolute times may be specified in a variety of formats; The form
-@samp{@var{hour}:@var{min}:@var{sec} @var{timezone}
-@var{month}/@var{day}/@var{year}}, where all fields are numbers, works;
-the format that @code{current-time-string} returns is also allowed.
-
-To specify a relative time, use numbers followed by units.
-For example:
-
-@table @samp
-@item 1 min
-denotes 1 minute from now.
-@item 1 min 5 sec
-denotes 65 seconds from now.
-@item 1 min 2 sec 3 hour 4 day 5 week 6 fortnight 7 month 8 year
-denotes exactly 103 months, 123 days, and 10862 seconds from now.
-@end table
-
-If @var{time} is a number (integer or floating point), that specifies a
-relative time measured in seconds.
-
-The argument @var{repeat} specifies how often to repeat the call. If
-@var{repeat} is @code{nil}, there are no repetitions; @var{function} is
-called just once, at @var{time}. If @var{repeat} is a number, it
-specifies a repetition period measured in seconds. In any case,
-@var{repeat} has no effect on when @emph{first} call takes
-place---@var{time} alone specifies that.
-
-The function @code{run-at-time} returns a timer value that identifies
-the particular scheduled future action. You can use this value to call
-@code{cancel-timer} (see below).
-@end defun
-
-@defmac with-timeout (seconds timeout-forms@dots{}) body@dots{}
-Execute @var{body}, but give up after @var{seconds} seconds. If
-@var{body} finishes before the time is up, @code{with-timeout} returns
-the value of the last form in @var{body}. If, however, the execution of
-@var{body} is cut short by the timeout, then @code{with-timeout}
-executes all the @var{timeout-forms} and returns the value of the last
-of them.
-
-This macro works by set a timer to run after @var{seconds} seconds. If
-@var{body} finishes before that time, it cancels the timer. If the
-timer actually runs, it terminates execution of @var{body}, then
-executes @var{timeout-forms}.
-
-Since timers can run within a Lisp program only when the program calls a
-primitive that can wait, @code{with-timeout} cannot stop executing
-@var{body} while it is in the midst of a computation---only when it
-calls one of those primitives. So use @code{with-timeout} only with a
-@var{body} that waits for input, not one that does a long computation.
-@end defmac
-
- The function @code{y-or-n-p-with-timeout} provides a simple way to use
-a timer to avoid waiting too long for an answer. @xref{Yes-or-No
-Queries}.
-
-@defun run-with-idle-timer secs repeat function &rest args
-Set up a timer which runs when Emacs has been idle for @var{secs}
-seconds. The value of @var{secs} may be an integer or a floating point
-number.
-
-If @var{repeat} is @code{nil}, the timer runs just once, the first time
-Emacs remains idle for a long enough time. More often @var{repeat} is
-non-@code{nil}, which means to run the timer @emph{each time} Emacs
-remains idle for @var{secs} seconds.
-
-The function @code{run-with-idle-timer} returns a timer value which you
-can use in calling @code{cancel-timer} (see below).
-@end defun
-
-@cindex idleness
- Emacs becomes ``idle'' when it starts waiting for user input, and it
-remains idle until the user provides some input. If a timer is set for
-five seconds of idleness, it runs approximately five seconds after Emacs
-first became idle. Even if its @var{repeat} is true, this timer will
-not run again as long as Emacs remains idle, because the duration of
-idleness will continue to increase and will not go down to five seconds
-again.
-
- Emacs can do various things while idle: garbage collect, autosave or
-handle data from a subprocess. But these interludes during idleness
-have little effect on idle timers. An idle timer set for 600 seconds
-will run when ten minutes have elapsed since the last user command was
-finished, even if subprocess output has been accepted thousands of times
-within those ten minutes, even if there have been garbage collections
-and autosaves.
-
- When the user supplies input, Emacs becomes non-idle while executing the
-input. Then it becomes idle again, and all the idle timers that are
-set up to repeat will subsequently run another time, one by one.
-
-@defun cancel-timer timer
-Cancel the requested action for @var{timer}, which should be a value
-previously returned by @code{run-at-time} or @code{run-with-idle-timer}.
-This cancels the effect of that call to @code{run-at-time}; the arrival
-of the specified time will not cause anything special to happen.
-@end defun
-
-@node Terminal Input
-@section Terminal Input
-@cindex terminal input
-
- This section describes functions and variables for recording or
-manipulating terminal input. See @ref{Display}, for related
-functions.
-
-@menu
-* Input Modes:: Options for how input is processed.
-* Translating Input:: Low level conversion of some characters or events
- into others.
-* Recording Input:: Saving histories of recent or all input events.
-@end menu
-
-@node Input Modes
-@subsection Input Modes
-@cindex input modes
-@cindex terminal input modes
-
-@defun set-input-mode interrupt flow meta quit-char
-This function sets the mode for reading keyboard input. If
-@var{interrupt} is non-null, then Emacs uses input interrupts. If it is
-@code{nil}, then it uses @sc{cbreak} mode. When Emacs communicates
-directly with X, it ignores this argument and uses interrupts if that is
-the way it knows how to communicate.
-
-If @var{flow} is non-@code{nil}, then Emacs uses @sc{xon/xoff} (@kbd{C-q},
-@kbd{C-s}) flow control for output to the terminal. This has no effect except
-in @sc{cbreak} mode. @xref{Flow Control}.
-
-The default setting is system dependent. Some systems always use
-@sc{cbreak} mode regardless of what is specified.
-
-@c Emacs 19 feature
-The argument @var{meta} controls support for input character codes
-above 127. If @var{meta} is @code{t}, Emacs converts characters with
-the 8th bit set into Meta characters. If @var{meta} is @code{nil},
-Emacs disregards the 8th bit; this is necessary when the terminal uses
-it as a parity bit. If @var{meta} is neither @code{t} nor @code{nil},
-Emacs uses all 8 bits of input unchanged. This is good for terminals
-using European 8-bit character sets.
-
-@c Emacs 19 feature
-If @var{quit-char} is non-@code{nil}, it specifies the character to
-use for quitting. Normally this character is @kbd{C-g}.
-@xref{Quitting}.
-@end defun
-
-The @code{current-input-mode} function returns the input mode settings
-Emacs is currently using.
-
-@c Emacs 19 feature
-@defun current-input-mode
-This function returns current mode for reading keyboard input. It
-returns a list, corresponding to the arguments of @code{set-input-mode},
-of the form @code{(@var{interrupt} @var{flow} @var{meta} @var{quit})} in
-which:
-@table @var
-@item interrupt
-is non-@code{nil} when Emacs is using interrupt-driven input. If
-@code{nil}, Emacs is using @sc{cbreak} mode.
-@item flow
-is non-@code{nil} if Emacs uses @sc{xon/xoff} (@kbd{C-q}, @kbd{C-s})
-flow control for output to the terminal. This value has no effect
-unless @var{interrupt} is non-@code{nil}.
-@item meta
-is @code{t} if Emacs treats the eighth bit of input characters as
-the meta bit; @code{nil} means Emacs clears the eighth bit of every
-input character; any other value means Emacs uses all eight bits as the
-basic character code.
-@item quit
-is the character Emacs currently uses for quitting, usually @kbd{C-g}.
-@end table
-@end defun
-
-@node Translating Input
-@subsection Translating Input Events
-@cindex translating input events
-
- This section describes features for translating input events into
-other input events before they become part of key sequences. These
-features apply to each event in the order they are described here: each
-event is first modified according to @code{extra-keyboard-modifiers},
-then translated through @code{keyboard-translate-table} (if applicable).
-If it is being read as part of a key sequence, it is then added to the
-sequece being read; then subsequences containing it are checked first
-with @code{function-key-map} and then with @code{key-translation-map}.
-
-@c Emacs 19 feature
-@defvar extra-keyboard-modifiers
-This variable lets Lisp programs ``press'' the modifier keys on the
-keyboard. The value is a bit mask:
-
-@table @asis
-@item 1
-The @key{SHIFT} key.
-@item 2
-The @key{LOCK} key.
-@item 4
-The @key{CTL} key.
-@item 8
-The @key{META} key.
-@end table
-
-Each time the user types a keyboard key, it is altered as if the
-modifier keys specified in the bit mask were held down.
-
-When using X windows, the program can ``press'' any of the modifier
-keys in this way. Otherwise, only the @key{CTL} and @key{META} keys can
-be virtually pressed.
-@end defvar
-
-@defvar keyboard-translate-table
-This variable is the translate table for keyboard characters. It lets
-you reshuffle the keys on the keyboard without changing any command
-bindings. Its value must be a string or @code{nil}.
-
-If @code{keyboard-translate-table} is a string, then each character read
-from the keyboard is looked up in this string and the character in the
-string is used instead. If the string is of length @var{n}, character codes
-@var{n} and up are untranslated.
-
-In the example below, we set @code{keyboard-translate-table} to a
-string of 128 characters. Then we fill it in to swap the characters
-@kbd{C-s} and @kbd{C-\} and the characters @kbd{C-q} and @kbd{C-^}.
-Subsequently, typing @kbd{C-\} has all the usual effects of typing
-@kbd{C-s}, and vice versa. (@xref{Flow Control} for more information on
-this subject.)
-
-@cindex flow control example
-@example
-@group
-(defun evade-flow-control ()
- "Replace C-s with C-\ and C-q with C-^."
- (interactive)
-@end group
-@group
- (let ((the-table (make-string 128 0)))
- (let ((i 0))
- (while (< i 128)
- (aset the-table i i)
- (setq i (1+ i))))
-@end group
- ;; @r{Swap @kbd{C-s} and @kbd{C-\}.}
- (aset the-table ?\034 ?\^s)
- (aset the-table ?\^s ?\034)
-@group
- ;; @r{Swap @kbd{C-q} and @kbd{C-^}.}
- (aset the-table ?\036 ?\^q)
- (aset the-table ?\^q ?\036)
- (setq keyboard-translate-table the-table)))
-@end group
-@end example
-
-Note that this translation is the first thing that happens to a
-character after it is read from the terminal. Record-keeping features
-such as @code{recent-keys} and dribble files record the characters after
-translation.
-@end defvar
-
-@defun keyboard-translate from to
-This function modifies @code{keyboard-translate-table} to translate
-character code @var{from} into character code @var{to}. It creates
-or enlarges the translate table if necessary.
-@end defun
-
- The remaining translation features translate subsequences of key
-sequences being read. They are implemented in @code{read-key-sequence}
-and have no effect on @code{read-char}.
-
-@defvar function-key-map
-This variable holds a keymap that describes the character sequences
-sent by function keys on an ordinary character terminal. This keymap
-uses the same data structure as other keymaps, but is used differently: it
-specifies translations to make while reading event sequences.
-
-If @code{function-key-map} ``binds'' a key sequence @var{k} to a vector
-@var{v}, then when @var{k} appears as a subsequence @emph{anywhere} in a
-key sequence, it is replaced with the events in @var{v}.
-
-For example, VT100 terminals send @kbd{@key{ESC} O P} when the
-keypad PF1 key is pressed. Therefore, we want Emacs to translate
-that sequence of events into the single event @code{pf1}. We accomplish
-this by ``binding'' @kbd{@key{ESC} O P} to @code{[pf1]} in
-@code{function-key-map}, when using a VT100.
-
-Thus, typing @kbd{C-c @key{PF1}} sends the character sequence @kbd{C-c
-@key{ESC} O P}; later the function @code{read-key-sequence} translates
-this back into @kbd{C-c @key{PF1}}, which it returns as the vector
-@code{[?\C-c pf1]}.
-
-Entries in @code{function-key-map} are ignored if they conflict with
-bindings made in the minor mode, local, or global keymaps. The intent
-is that the character sequences that function keys send should not have
-command bindings in their own right.
-
-The value of @code{function-key-map} is usually set up automatically
-according to the terminal's Terminfo or Termcap entry, but sometimes
-those need help from terminal-specific Lisp files. Emacs comes with
-terminal-specific files for many common terminals; their main purpose is
-to make entries in @code{function-key-map} beyond those that can be
-deduced from Termcap and Terminfo. @xref{Terminal-Specific}.
-
-Emacs versions 18 and earlier used totally different means of detecting
-the character sequences that represent function keys.
-@end defvar
-
-@defvar key-translation-map
-This variable is another keymap used just like @code{function-key-map}
-to translate input events into other events. It differs from
-@code{function-key-map} in two ways:
-
-@itemize @bullet
-@item
-@code{key-translation-map} goes to work after @code{function-key-map} is
-finished; it receives the results of translation by
-@code{function-key-map}.
-
-@item
-@code{key-translation-map} overrides actual key bindings. For example,
-if @kbd{C-x f} has a binding in @code{key-translation-map}, that
-translation takes effect even though @kbd{C-x f} also has a key binding
-in the global map.
-@end itemize
-
-The intent of @code{key-translation-map} is for users to map one
-character set to another, including ordinary characters normally bound
-to @code{self-insert-command}.
-@end defvar
-
-@cindex key translation function
-You can use @code{function-key-map} or @code{key-translation-map} for
-more than simple aliases, by using a function, instead of a key
-sequence, as the ``translation'' of a key. Then this function is called
-to compute the translation of that key.
-
-The key translation function receives one argument, which is the prompt
-that was specified in @code{read-key-sequence}---or @code{nil} if the
-key sequence is being read by the editor command loop. In most cases
-you can ignore the prompt value.
-
-If the function reads input itself, it can have the effect of altering
-the event that follows. For example, here's how to define @kbd{C-c h}
-to turn the character that follows into a Hyper character:
-
-@example
-@group
-(defun hyperify (prompt)
- (let ((e (read-event)))
- (vector (if (numberp e)
- (logior (lsh 1 20) e)
- (if (memq 'hyper (event-modifiers e))
- e
- (add-event-modifier "H-" e))))))
-
-(defun add-event-modifier (string e)
- (let ((symbol (if (symbolp e) e (car e))))
- (setq symbol (intern (concat string
- (symbol-name symbol))))
-@end group
-@group
- (if (symbolp e)
- symbol
- (cons symbol (cdr e)))))
-
-(define-key function-key-map "\C-ch" 'hyperify)
-@end group
-@end example
-
-@pindex iso-transl
-@cindex Latin-1 character set (input)
-@cindex ISO Latin-1 characters (input)
-The @file{iso-transl} library uses this feature to provide a way of
-inputting non-ASCII Latin-1 characters.
-
-@node Recording Input
-@subsection Recording Input
-
-@defun recent-keys
-This function returns a vector containing the last 100 input events
-from the keyboard or mouse. All input events are included, whether or
-not they were used as parts of key sequences. Thus, you always get the
-last 100 inputs, not counting keyboard macros. (Events from keyboard
-macros are excluded because they are less interesting for debugging; it
-should be enough to see the events that invoked the macros.)
-@end defun
-
-@deffn Command open-dribble-file filename
-@cindex dribble file
-This function opens a @dfn{dribble file} named @var{filename}. When a
-dribble file is open, each input event from the keyboard or mouse (but
-not those from keyboard macros) is written in that file. A
-non-character event is expressed using its printed representation
-surrounded by @samp{<@dots{}>}.
-
-You close the dribble file by calling this function with an argument
-of @code{nil}.
-
-This function is normally used to record the input necessary to
-trigger an Emacs bug, for the sake of a bug report.
-
-@example
-@group
-(open-dribble-file "~/dribble")
- @result{} nil
-@end group
-@end example
-@end deffn
-
- See also the @code{open-termscript} function (@pxref{Terminal Output}).
-
-@node Terminal Output
-@section Terminal Output
-@cindex terminal output
-
- The terminal output functions send output to the terminal or keep
-track of output sent to the terminal. The variable @code{baud-rate}
-tells you what Emacs thinks is the output speed of the terminal.
-
-@defvar baud-rate
-This variable's value is the output speed of the terminal, as far as
-Emacs knows. Setting this variable does not change the speed of actual
-data transmission, but the value is used for calculations such as
-padding. It also affects decisions about whether to scroll part of the
-screen or repaint---even when using a window system. (We designed it
-this way despite the fact that a window system has no true ``output
-speed'', to give you a way to tune these decisions.)
-
-The value is measured in baud.
-@end defvar
-
- If you are running across a network, and different parts of the
-network work at different baud rates, the value returned by Emacs may be
-different from the value used by your local terminal. Some network
-protocols communicate the local terminal speed to the remote machine, so
-that Emacs and other programs can get the proper value, but others do
-not. If Emacs has the wrong value, it makes decisions that are less
-than optimal. To fix the problem, set @code{baud-rate}.
-
-@defun baud-rate
-This function returns the value of the variable @code{baud-rate}. In
-Emacs versions 18 and earlier, this was the only way to find out the
-terminal speed.
-@end defun
-
-@defun send-string-to-terminal string
-This function sends @var{string} to the terminal without alteration.
-Control characters in @var{string} have terminal-dependent effects.
-
-One use of this function is to define function keys on terminals that
-have downloadable function key definitions. For example, this is how on
-certain terminals to define function key 4 to move forward four
-characters (by transmitting the characters @kbd{C-u C-f} to the
-computer):
-
-@example
-@group
-(send-string-to-terminal "\eF4\^U\^F")
- @result{} nil
-@end group
-@end example
-@end defun
-
-@deffn Command open-termscript filename
-@cindex termscript file
-This function is used to open a @dfn{termscript file} that will record
-all the characters sent by Emacs to the terminal. It returns
-@code{nil}. Termscript files are useful for investigating problems
-where Emacs garbles the screen, problems that are due to incorrect
-Termcap entries or to undesirable settings of terminal options more
-often than to actual Emacs bugs. Once you are certain which characters
-were actually output, you can determine reliably whether they correspond
-to the Termcap specifications in use.
-
-See also @code{open-dribble-file} in @ref{Terminal Input}.
-
-@example
-@group
-(open-termscript "../junk/termscript")
- @result{} nil
-@end group
-@end example
-@end deffn
-
-@node Special Keysyms
-@section System-Specific X11 Keysyms
-
-To define system-specific X11 keysyms, set the variable
-@code{system-key-alist}.
-
-@defvar system-key-alist
-This variable's value should be an alist with one element for each
-system-specific keysym. An element has this form: @code{(@var{code}
-. @var{symbol})}, where @var{code} is the numeric keysym code (not
-including the ``vendor specific'' bit, 1 << 28), and @var{symbol} is the
-name for the function key.
-
-For example @code{(168 . mute-acute)} defines a system-specific key used
-by HP X servers whose numeric code is (1 << 28) + 168.
-
-It is not a problem if the alist defines keysyms for other X servers, as
-long as they don't conflict with the ones used by the X server actually
-in use.
-
-The variable is always local to the current X terminal and cannot be
-buffer-local. @xref{Multiple Displays}.
-@end defvar
-
-@node Flow Control
-@section Flow Control
-@cindex flow control characters
-
- This section attempts to answer the question ``Why does Emacs choose
-to use flow-control characters in its command character set?'' For a
-second view on this issue, read the comments on flow control in the
-@file{emacs/INSTALL} file from the distribution; for help with Termcap
-entries and DEC terminal concentrators, see @file{emacs/etc/TERMS}.
-
-@cindex @kbd{C-s}
-@cindex @kbd{C-q}
- At one time, most terminals did not need flow control, and none used
-@code{C-s} and @kbd{C-q} for flow control. Therefore, the choice of
-@kbd{C-s} and @kbd{C-q} as command characters was uncontroversial.
-Emacs, for economy of keystrokes and portability, used nearly all the
-@sc{ASCII} control characters, with mnemonic meanings when possible;
-thus, @kbd{C-s} for search and @kbd{C-q} for quote.
-
- Later, some terminals were introduced which required these characters
-for flow control. They were not very good terminals for full-screen
-editing, so Emacs maintainers did not pay attention. In later years,
-flow control with @kbd{C-s} and @kbd{C-q} became widespread among
-terminals, but by this time it was usually an option. And the majority
-of users, who can turn flow control off, were unwilling to switch to
-less mnemonic key bindings for the sake of flow control.
-
- So which usage is ``right'', Emacs's or that of some terminal and
-concentrator manufacturers? This question has no simple answer.
-
- One reason why we are reluctant to cater to the problems caused by
-@kbd{C-s} and @kbd{C-q} is that they are gratuitous. There are other
-techniques (albeit less common in practice) for flow control that
-preserve transparency of the character stream. Note also that their use
-for flow control is not an official standard. Interestingly, on the
-model 33 teletype with a paper tape punch (which is very old), @kbd{C-s}
-and @kbd{C-q} were sent by the computer to turn the punch on and off!
-
- As X servers and other window systems replace character-only
-terminals, this problem is gradually being cured. For the mean time,
-Emacs provides a convenient way of enabling flow control if you want it:
-call the function @code{enable-flow-control}.
-
-@defun enable-flow-control
-This function enables use of @kbd{C-s} and @kbd{C-q} for output flow
-control, and provides the characters @kbd{C-\} and @kbd{C-^} as aliases
-for them using @code{keyboard-translate-table} (@pxref{Translating Input}).
-@end defun
-
-You can use the function @code{enable-flow-control-on} in your
-@file{.emacs} file to enable flow control automatically on certain
-terminal types.
-
-@defun enable-flow-control-on &rest termtypes
-This function enables flow control, and the aliases @kbd{C-\} and @kbd{C-^},
-if the terminal type is one of @var{termtypes}. For example:
-
-@smallexample
-(enable-flow-control-on "vt200" "vt300" "vt101" "vt131")
-@end smallexample
-@end defun
-
- Here is how @code{enable-flow-control} does its job:
-
-@enumerate
-@item
-@cindex @sc{cbreak}
-It sets @sc{cbreak} mode for terminal input, and tells the operating
-system to handle flow control, with @code{(set-input-mode nil t)}.
-
-@item
-It sets up @code{keyboard-translate-table} to translate @kbd{C-\} and
-@kbd{C-^} into @kbd{C-s} and @kbd{C-q}. Except at its very
-lowest level, Emacs never knows that the characters typed were anything
-but @kbd{C-s} and @kbd{C-q}, so you can in effect type them as @kbd{C-\}
-and @kbd{C-^} even when they are input for other commands.
-@xref{Translating Input}.
-@end enumerate
-
-If the terminal is the source of the flow control characters, then once
-you enable kernel flow control handling, you probably can make do with
-less padding than normal for that terminal. You can reduce the amount
-of padding by customizing the Termcap entry. You can also reduce it by
-setting @code{baud-rate} to a smaller value so that Emacs uses a smaller
-speed when calculating the padding needed. @xref{Terminal Output}.
-
-@node Batch Mode
-@section Batch Mode
-@cindex batch mode
-@cindex noninteractive use
-
- The command line option @samp{-batch} causes Emacs to run
-noninteractively. In this mode, Emacs does not read commands from the
-terminal, it does not alter the terminal modes, and it does not expect
-to be outputting to an erasable screen. The idea is that you specify
-Lisp programs to run; when they are finished, Emacs should exit. The
-way to specify the programs to run is with @samp{-l @var{file}}, which
-loads the library named @var{file}, and @samp{-f @var{function}}, which
-calls @var{function} with no arguments.
-
- Any Lisp program output that would normally go to the echo area,
-either using @code{message} or using @code{prin1}, etc., with @code{t}
-as the stream, goes instead to Emacs's standard error descriptor when
-in batch mode. Thus, Emacs behaves much like a noninteractive
-application program. (The echo area output that Emacs itself normally
-generates, such as command echoing, is suppressed entirely.)
-
-@defvar noninteractive
-This variable is non-@code{nil} when Emacs is running in batch mode.
-@end defvar
diff --git a/lispref/positions.texi b/lispref/positions.texi
deleted file mode 100644
index 1d02377565a..00000000000
--- a/lispref/positions.texi
+++ /dev/null
@@ -1,897 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/positions
-@node Positions, Markers, Frames, Top
-@chapter Positions
-@cindex position (in buffer)
-
- A @dfn{position} is the index of a character in the text of a buffer.
-More precisely, a position identifies the place between two characters
-(or before the first character, or after the last character), so we can
-speak of the character before or after a given position. However, we
-often speak of the character ``at'' a position, meaning the character
-after that position.
-
- Positions are usually represented as integers starting from 1, but can
-also be represented as @dfn{markers}---special objects that relocate
-automatically when text is inserted or deleted so they stay with the
-surrounding characters. @xref{Markers}.
-
-@menu
-* Point:: The special position where editing takes place.
-* Motion:: Changing point.
-* Excursions:: Temporary motion and buffer changes.
-* Narrowing:: Restricting editing to a portion of the buffer.
-@end menu
-
-@node Point
-@section Point
-@cindex point
-
- @dfn{Point} is a special buffer position used by many editing
-commands, including the self-inserting typed characters and text
-insertion functions. Other commands move point through the text
-to allow editing and insertion at different places.
-
- Like other positions, point designates a place between two characters
-(or before the first character, or after the last character), rather
-than a particular character. Usually terminals display the cursor over
-the character that immediately follows point; point is actually before
-the character on which the cursor sits.
-
-@cindex point with narrowing
- The value of point is a number between 1 and the buffer size plus 1.
-If narrowing is in effect (@pxref{Narrowing}), then point is constrained
-to fall within the accessible portion of the buffer (possibly at one end
-of it).
-
- Each buffer has its own value of point, which is independent of the
-value of point in other buffers. Each window also has a value of point,
-which is independent of the value of point in other windows on the same
-buffer. This is why point can have different values in various windows
-that display the same buffer. When a buffer appears in only one window,
-the buffer's point and the window's point normally have the same value,
-so the distinction is rarely important. @xref{Window Point}, for more
-details.
-
-@defun point
-@cindex current buffer position
-This function returns the value of point in the current buffer,
-as an integer.
-
-@need 700
-@example
-@group
-(point)
- @result{} 175
-@end group
-@end example
-@end defun
-
-@defun point-min
-This function returns the minimum accessible value of point in the
-current buffer. This is normally 1, but if narrowing is in effect, it
-is the position of the start of the region that you narrowed to.
-(@xref{Narrowing}.)
-@end defun
-
-@defun point-max
-This function returns the maximum accessible value of point in the
-current buffer. This is @code{(1+ (buffer-size))}, unless narrowing is
-in effect, in which case it is the position of the end of the region
-that you narrowed to. (@xref{Narrowing}).
-@end defun
-
-@defun buffer-end flag
-This function returns @code{(point-min)} if @var{flag} is less than 1,
-@code{(point-max)} otherwise. The argument @var{flag} must be a number.
-@end defun
-
-@defun buffer-size
-This function returns the total number of characters in the current
-buffer. In the absence of any narrowing (@pxref{Narrowing}),
-@code{point-max} returns a value one larger than this.
-
-@example
-@group
-(buffer-size)
- @result{} 35
-@end group
-@group
-(point-max)
- @result{} 36
-@end group
-@end example
-@end defun
-
-@node Motion
-@section Motion
-
- Motion functions change the value of point, either relative to the
-current value of point, relative to the beginning or end of the buffer,
-or relative to the edges of the selected window. @xref{Point}.
-
-@menu
-* Character Motion:: Moving in terms of characters.
-* Word Motion:: Moving in terms of words.
-* Buffer End Motion:: Moving to the beginning or end of the buffer.
-* Text Lines:: Moving in terms of lines of text.
-* Screen Lines:: Moving in terms of lines as displayed.
-* List Motion:: Moving by parsing lists and sexps.
-* Skipping Characters:: Skipping characters belonging to a certain set.
-@end menu
-
-@node Character Motion
-@subsection Motion by Characters
-
- These functions move point based on a count of characters.
-@code{goto-char} is the fundamental primitive; the other functions use
-that.
-
-@deffn Command goto-char position
-This function sets point in the current buffer to the value
-@var{position}. If @var{position} is less than 1, it moves point to the
-beginning of the buffer. If @var{position} is greater than the length
-of the buffer, it moves point to the end.
-
-If narrowing is in effect, @var{position} still counts from the
-beginning of the buffer, but point cannot go outside the accessible
-portion. If @var{position} is out of range, @code{goto-char} moves
-point to the beginning or the end of the accessible portion.
-
-When this function is called interactively, @var{position} is the
-numeric prefix argument, if provided; otherwise it is read from the
-minibuffer.
-
-@code{goto-char} returns @var{position}.
-@end deffn
-
-@deffn Command forward-char &optional count
-@c @kindex beginning-of-buffer
-@c @kindex end-of-buffer
-This function moves point @var{count} characters forward, towards the
-end of the buffer (or backward, towards the beginning of the buffer, if
-@var{count} is negative). If the function attempts to move point past
-the beginning or end of the buffer (or the limits of the accessible
-portion, when narrowing is in effect), an error is signaled with error
-code @code{beginning-of-buffer} or @code{end-of-buffer}.
-
-In an interactive call, @var{count} is the numeric prefix argument.
-@end deffn
-
-@deffn Command backward-char &optional count
-This function moves point @var{count} characters backward, towards the
-beginning of the buffer (or forward, towards the end of the buffer, if
-@var{count} is negative). If the function attempts to move point past
-the beginning or end of the buffer (or the limits of the accessible
-portion, when narrowing is in effect), an error is signaled with error
-code @code{beginning-of-buffer} or @code{end-of-buffer}.
-
-In an interactive call, @var{count} is the numeric prefix argument.
-@end deffn
-
-@node Word Motion
-@subsection Motion by Words
-
- These functions for parsing words use the syntax table to decide
-whether a given character is part of a word. @xref{Syntax Tables}.
-
-@deffn Command forward-word count
-This function moves point forward @var{count} words (or backward if
-@var{count} is negative). Normally it returns @code{t}. If this motion
-encounters the beginning or end of the buffer, or the limits of the
-accessible portion when narrowing is in effect, point stops there
-and the value is @code{nil}.
-
-In an interactive call, @var{count} is set to the numeric prefix
-argument.
-@end deffn
-
-@deffn Command backward-word count
-This function is just like @code{forward-word}, except that it moves
-backward until encountering the front of a word, rather than forward.
-
-In an interactive call, @var{count} is set to the numeric prefix
-argument.
-
-This function is rarely used in programs, as it is more efficient to
-call @code{forward-word} with a negative argument.
-@end deffn
-
-@defvar words-include-escapes
-@c Emacs 19 feature
-This variable affects the behavior of @code{forward-word} and everything
-that uses it. If it is non-@code{nil}, then characters in the
-``escape'' and ``character quote'' syntax classes count as part of
-words. Otherwise, they do not.
-@end defvar
-
-@node Buffer End Motion
-@subsection Motion to an End of the Buffer
-
- To move point to the beginning of the buffer, write:
-
-@example
-@group
-(goto-char (point-min))
-@end group
-@end example
-
-@noindent
-Likewise, to move to the end of the buffer, use:
-
-@example
-@group
-(goto-char (point-max))
-@end group
-@end example
-
- Here are two commands that users use to do these things. They are
-documented here to warn you not to use them in Lisp programs, because
-they set the mark and display messages in the echo area.
-
-@deffn Command beginning-of-buffer &optional n
-This function moves point to the beginning of the buffer (or the limits
-of the accessible portion, when narrowing is in effect), setting the
-mark at the previous position. If @var{n} is non-@code{nil}, then it
-puts point @var{n} tenths of the way from the beginning of the buffer.
-
-In an interactive call, @var{n} is the numeric prefix argument,
-if provided; otherwise @var{n} defaults to @code{nil}.
-
-Don't use this function in Lisp programs!
-@end deffn
-
-@deffn Command end-of-buffer &optional n
-This function moves point to the end of the buffer (or the limits of
-the accessible portion, when narrowing is in effect), setting the mark
-at the previous position. If @var{n} is non-@code{nil}, then it puts
-point @var{n} tenths of the way from the end of the buffer.
-
-In an interactive call, @var{n} is the numeric prefix argument,
-if provided; otherwise @var{n} defaults to @code{nil}.
-
-Don't use this function in Lisp programs!
-@end deffn
-
-@node Text Lines
-@subsection Motion by Text Lines
-@cindex lines
-
- Text lines are portions of the buffer delimited by newline characters,
-which are regarded as part of the previous line. The first text line
-begins at the beginning of the buffer, and the last text line ends at
-the end of the buffer whether or not the last character is a newline.
-The division of the buffer into text lines is not affected by the width
-of the window, by line continuation in display, or by how tabs and
-control characters are displayed.
-
-@deffn Command goto-line line
-This function moves point to the front of the @var{line}th line,
-counting from line 1 at beginning of the buffer. If @var{line} is less
-than 1, it moves point to the beginning of the buffer. If @var{line} is
-greater than the number of lines in the buffer, it moves point to the
-end of the buffer---that is, the @emph{end of the last line} of the
-buffer. This is the only case in which @code{goto-line} does not
-necessarily move to the beginning of a line.
-
-If narrowing is in effect, then @var{line} still counts from the
-beginning of the buffer, but point cannot go outside the accessible
-portion. So @code{goto-line} moves point to the beginning or end of the
-accessible portion, if the line number specifies an inaccessible
-position.
-
-The return value of @code{goto-line} is the difference between
-@var{line} and the line number of the line to which point actually was
-able to move (in the full buffer, before taking account of narrowing).
-Thus, the value is positive if the scan encounters the real end of the
-buffer. The value is zero if scan encounters the end of the accessible
-portion but not the real end of the buffer.
-
-In an interactive call, @var{line} is the numeric prefix argument if
-one has been provided. Otherwise @var{line} is read in the minibuffer.
-@end deffn
-
-@deffn Command beginning-of-line &optional count
-This function moves point to the beginning of the current line. With an
-argument @var{count} not @code{nil} or 1, it moves forward
-@var{count}@minus{}1 lines and then to the beginning of the line.
-
-If this function reaches the end of the buffer (or of the accessible
-portion, if narrowing is in effect), it positions point there. No error
-is signaled.
-@end deffn
-
-@deffn Command end-of-line &optional count
-This function moves point to the end of the current line. With an
-argument @var{count} not @code{nil} or 1, it moves forward
-@var{count}@minus{}1 lines and then to the end of the line.
-
-If this function reaches the end of the buffer (or of the accessible
-portion, if narrowing is in effect), it positions point there. No error
-is signaled.
-@end deffn
-
-@deffn Command forward-line &optional count
-@cindex beginning of line
-This function moves point forward @var{count} lines, to the beginning of
-the line. If @var{count} is negative, it moves point
-@minus{}@var{count} lines backward, to the beginning of a line. If
-@var{count} is zero, it moves point to the beginning of the current
-line.
-
-If @code{forward-line} encounters the beginning or end of the buffer (or
-of the accessible portion) before finding that many lines, it sets point
-there. No error is signaled.
-
-@code{forward-line} returns the difference between @var{count} and the
-number of lines actually moved. If you attempt to move down five lines
-from the beginning of a buffer that has only three lines, point stops at
-the end of the last line, and the value will be 2.
-
-In an interactive call, @var{count} is the numeric prefix argument.
-@end deffn
-
-@defun count-lines start end
-@cindex lines in region
-This function returns the number of lines between the positions
-@var{start} and @var{end} in the current buffer. If @var{start} and
-@var{end} are equal, then it returns 0. Otherwise it returns at least
-1, even if @var{start} and @var{end} are on the same line. This is
-because the text between them, considered in isolation, must contain at
-least one line unless it is empty.
-
-Here is an example of using @code{count-lines}:
-
-@example
-@group
-(defun current-line ()
- "Return the vertical position of point@dots{}"
- (+ (count-lines (window-start) (point))
- (if (= (current-column) 0) 1 0)
- -1))
-@end group
-@end example
-@end defun
-
-@ignore
-@c ================
-The @code{previous-line} and @code{next-line} commands are functions
-that should not be used in programs. They are for users and are
-mentioned here only for completeness.
-
-@deffn Command previous-line count
-@cindex goal column
-This function moves point up @var{count} lines (down if @var{count}
-is negative). In moving, it attempts to keep point in the ``goal column''
-(normally the same column that it was at the beginning of the move).
-
-If there is no character in the target line exactly under the current
-column, point 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 it attempts to move beyond the top or bottom of the buffer (or clipped
-region), then point is positioned in the goal column in the top or
-bottom line. No error is signaled.
-
-In an interactive call, @var{count} will be the numeric
-prefix argument.
-
-The command @code{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
-@code{forward-line} with a negative argument instead. It is usually easier
-to use and more reliable (no dependence on goal column, etc.).
-@end deffn
-
-@deffn Command next-line count
-This function moves point down @var{count} lines (up if @var{count}
-is negative). In moving, it attempts to keep point in the ``goal column''
-(normally the same column that it was at the beginning of the move).
-
-If there is no character in the target line exactly under the current
-column, point 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 it attempts to move beyond the top or bottom of the buffer (or clipped
-region), then point is positioned in the goal column in the top or
-bottom line. No error is signaled.
-
-In the case where the @var{count} is 1, and point is on the last
-line of the buffer (or clipped region), a new empty line is inserted at the
-end of the buffer (or clipped region) and point moved there.
-
-In an interactive call, @var{count} will be the numeric
-prefix argument.
-
-The command @code{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
-@code{forward-line} instead. It is usually easier
-to use and more reliable (no dependence on goal column, etc.).
-@end deffn
-
-@c ================
-@end ignore
-
- Also see the functions @code{bolp} and @code{eolp} in @ref{Near Point}.
-These functions do not move point, but test whether it is already at the
-beginning or end of a line.
-
-@node Screen Lines
-@subsection Motion by Screen Lines
-
- The line functions in the previous section count text lines, delimited
-only by newline characters. By contrast, these functions count screen
-lines, which are defined by the way the text appears on the screen. A
-text line is a single screen line if it is short enough to fit the width
-of the selected window, but otherwise it may occupy several screen
-lines.
-
- In some cases, text lines are truncated on the screen rather than
-continued onto additional screen lines. In these cases,
-@code{vertical-motion} moves point much like @code{forward-line}.
-@xref{Truncation}.
-
- Because the width of a given string depends on the flags that control
-the appearance of certain characters, @code{vertical-motion} behaves
-differently, for a given piece of text, depending on the buffer it is
-in, and even on the selected window (because the width, the truncation
-flag, and display table may vary between windows). @xref{Usual
-Display}.
-
- These functions scan text to determine where screen lines break, and
-thus take time proportional to the distance scanned. If you intend to
-use them heavily, Emacs provides caches which may improve the
-performance of your code. @xref{Text Lines, cache-long-line-scans}.
-
-
-@defun vertical-motion count &optional window
-This function moves point to the start of the screen line @var{count}
-screen lines down from the screen line containing point. If @var{count}
-is negative, it moves up instead.
-
-@code{vertical-motion} returns the number of lines moved. The value may
-be less in absolute value than @var{count} if the beginning or end of
-the buffer was reached.
-
-The window @var{window} is used for obtaining parameters such as the
-width, the horizontal scrolling, and the display table. But
-@code{vertical-motion} always operates on the current buffer, even if
-@var{window} currently displays some other buffer.
-@end defun
-
-@deffn Command move-to-window-line count
-This function moves point with respect to the text currently displayed
-in the selected window. It moves point to the beginning of the screen
-line @var{count} screen lines from the top of the window. If
-@var{count} is negative, that specifies a position
-@w{@minus{}@var{count}} lines from the bottom (or the last line of the
-buffer, if the buffer ends above the specified screen position).
-
-If @var{count} is @code{nil}, then point moves to the beginning of the
-line in the middle of the window. If the absolute value of @var{count}
-is greater than the size of the window, then point moves to the place
-that would appear on that screen line if the window were tall enough.
-This will probably cause the next redisplay to scroll to bring that
-location onto the screen.
-
-In an interactive call, @var{count} is the numeric prefix argument.
-
-The value returned is the window line number point has moved to, with
-the top line in the window numbered 0.
-@end deffn
-
-@defun compute-motion from frompos to topos width offsets window
-This function scans the current buffer, calculating screen positions.
-It scans the buffer forward from position @var{from}, assuming that is
-at screen coordinates @var{frompos}, to position @var{to} or coordinates
-@var{topos}, whichever comes first. It returns the ending buffer
-position and screen coordinates.
-
-The coordinate arguments @var{frompos} and @var{topos} are cons cells of
-the form @code{(@var{hpos} . @var{vpos})}.
-
-The argument @var{width} is the number of columns available to display
-text; this affects handling of continuation lines. Use the value
-returned by @code{window-width} for the window of your choice;
-normally, use @code{(window-width @var{window})}.
-
-The argument @var{offsets} is either @code{nil} or a cons cell of the
-form @code{(@var{hscroll} . @var{tab-offset})}. Here @var{hscroll} is
-the number of columns not being displayed at the left margin; most
-callers get this from @code{window-hscroll}. Meanwhile,
-@var{tab-offset} is the offset between column numbers on the screen and
-column numbers in the buffer. This can be nonzero in a continuation
-line, when the previous screen lines' widths do not add up to a multiple
-of @code{tab-width}. It is always zero in a non-continuation line.
-
-The window @var{window} serves only to specify which display table to
-use. @code{compute-motion} always operates on the current buffer,
-regardless of what buffer is displayed in @var{window}.
-
-The return value is a list of five elements:
-
-@example
-(@var{pos} @var{vpos} @var{hpos} @var{prevhpos} @var{contin})
-@end example
-
-@noindent
-Here @var{pos} is the buffer position where the scan stopped, @var{vpos}
-is the vertical screen position, and @var{hpos} is the horizontal screen
-position.
-
-The result @var{prevhpos} is the horizontal position one character back
-from @var{pos}. The result @var{contin} is @code{t} if the last line
-was continued after (or within) the previous character.
-
-For example, to find the buffer position of column @var{col} of line
-@var{line} of a certain window, pass the window's display start location
-as @var{from} and the window's upper-left coordinates as @var{frompos}.
-Pass the buffer's @code{(point-max)} as @var{to}, to limit the scan to
-the end of the accessible portion of the buffer, and pass @var{line} and
-@var{col} as @var{topos}. Here's a function that does this:
-
-@example
-(defun coordinates-of-position (col line)
- (car (compute-motion (window-start)
- '(0 . 0)
- (point-max)
- (cons col line)
- (window-width)
- (cons (window-hscroll) 0)
- (selected-window))))
-@end example
-
-When you use @code{compute-motion} for the minibuffer, you need to use
-@code{minibuffer-prompt-width} to get the horizontal position of the
-beginning of the first screen line. @xref{Minibuffer Misc}.
-@end defun
-
-@node List Motion
-@comment node-name, next, previous, up
-@subsection Moving over Balanced Expressions
-@cindex sexp motion
-@cindex Lisp expression motion
-@cindex list motion
-
- Here are several functions concerned with balanced-parenthesis
-expressions (also called @dfn{sexps} in connection with moving across
-them in Emacs). The syntax table controls how these functions interpret
-various characters; see @ref{Syntax Tables}. @xref{Parsing
-Expressions}, for lower-level primitives for scanning sexps or parts of
-sexps. For user-level commands, see @ref{Lists Commands,,, emacs, GNU
-Emacs Manual}.
-
-@deffn Command forward-list arg
-This function moves forward across @var{arg} balanced groups of
-parentheses. (Other syntactic entities such as words or paired string
-quotes are ignored.)
-@end deffn
-
-@deffn Command backward-list arg
-This function moves backward across @var{arg} balanced groups of
-parentheses. (Other syntactic entities such as words or paired string
-quotes are ignored.)
-@end deffn
-
-@deffn Command up-list arg
-This function moves forward out of @var{arg} levels of parentheses.
-A negative argument means move backward but still to a less deep spot.
-@end deffn
-
-@deffn Command down-list arg
-This function moves forward into @var{arg} levels of parentheses. A
-negative argument means move backward but still go
-deeper in parentheses (@minus{}@var{arg} levels).
-@end deffn
-
-@deffn Command forward-sexp arg
-This function moves forward across @var{arg} balanced expressions.
-Balanced expressions include both those delimited by parentheses and
-other kinds, such as words and string constants. For example,
-
-@example
-@group
----------- Buffer: foo ----------
-(concat@point{} "foo " (car x) y z)
----------- Buffer: foo ----------
-@end group
-
-@group
-(forward-sexp 3)
- @result{} nil
-
----------- Buffer: foo ----------
-(concat "foo " (car x) y@point{} z)
----------- Buffer: foo ----------
-@end group
-@end example
-@end deffn
-
-@deffn Command backward-sexp arg
-This function moves backward across @var{arg} balanced expressions.
-@end deffn
-
-@deffn Command beginning-of-defun arg
-This function moves back to the @var{arg}th beginning of a defun. If
-@var{arg} is negative, this actually moves forward, but it still moves
-to the beginning of a defun, not to the end of one.
-@end deffn
-
-@deffn Command end-of-defun arg
-This function moves forward to the @var{arg}th end of a defun. If
-@var{arg} is negative, this actually moves backward, but it still moves
-to the end of a defun, not to the beginning of one.
-@end deffn
-
-@defopt defun-prompt-regexp
-If non-@code{nil}, this variable holds a regular expression that
-specifies what text can appear before the open-parenthesis that starts a
-defun. That is to say, a defun begins on a line that starts with a
-match for this regular expression, followed by a character with
-open-parenthesis syntax.
-@end defopt
-
-@node Skipping Characters
-@comment node-name, next, previous, up
-@subsection Skipping Characters
-@cindex skipping characters
-
- The following two functions move point over a specified set of
-characters. For example, they are often used to skip whitespace. For
-related functions, see @ref{Motion and Syntax}.
-
-@defun skip-chars-forward character-set &optional limit
-This function moves point in the current buffer forward, skipping over a
-given set of characters. It examines the character following point,
-then advances point if the character matches @var{character-set}. This
-continues until it reaches a character that does not match. The
-function returns @code{nil}.
-
-The argument @var{character-set} is like the inside of a
-@samp{[@dots{}]} in a regular expression except that @samp{]} is never
-special and @samp{\} quotes @samp{^}, @samp{-} or @samp{\}. Thus,
-@code{"a-zA-Z"} skips over all letters, stopping before the first
-nonletter, and @code{"^a-zA-Z"} skips nonletters stopping before the
-first letter. @xref{Regular Expressions}.
-
-If @var{limit} is supplied (it must be a number or a marker), it
-specifies the maximum position in the buffer that point can be skipped
-to. Point will stop at or before @var{limit}.
-
-In the following example, point is initially located directly before the
-@samp{T}. After the form is evaluated, point is located at the end of
-that line (between the @samp{t} of @samp{hat} and the newline). The
-function skips all letters and spaces, but not newlines.
-
-@example
-@group
----------- Buffer: foo ----------
-I read "@point{}The cat in the hat
-comes back" twice.
----------- Buffer: foo ----------
-@end group
-
-@group
-(skip-chars-forward "a-zA-Z ")
- @result{} nil
-
----------- Buffer: foo ----------
-I read "The cat in the hat@point{}
-comes back" twice.
----------- Buffer: foo ----------
-@end group
-@end example
-@end defun
-
-@defun skip-chars-backward character-set &optional limit
-This function moves point backward, skipping characters that match
-@var{character-set}, until @var{limit}. It just like
-@code{skip-chars-forward} except for the direction of motion.
-@end defun
-
-@node Excursions
-@section Excursions
-@cindex excursion
-
- It is often useful to move point ``temporarily'' within a localized
-portion of the program, or to switch buffers temporarily. This is
-called an @dfn{excursion}, and it is done with the @code{save-excursion}
-special form. This construct saves the current buffer and its values of
-point and the mark so they can be restored after the completion of the
-excursion.
-
- The forms for saving and restoring the configuration of windows are
-described elsewhere (see @ref{Window Configurations}, and @pxref{Frame
-Configurations}).
-
-@defspec save-excursion forms@dots{}
-@cindex mark excursion
-@cindex point excursion
-@cindex current buffer excursion
-The @code{save-excursion} special form saves the identity of the current
-buffer and the values of point and the mark in it, evaluates
-@var{forms}, and finally restores the buffer and its saved values of
-point and the mark. All three saved values are restored even in case of
-an abnormal exit via @code{throw} or error (@pxref{Nonlocal Exits}).
-
-The @code{save-excursion} special form is the standard way to switch
-buffers or move point within one part of a program and avoid affecting
-the rest of the program. It is used more than 500 times in the Lisp
-sources of Emacs.
-
-@code{save-excursion} does not save the values of point and the mark for
-other buffers, so changes in other buffers remain in effect after
-@code{save-excursion} exits.
-
-@cindex window excursions
-Likewise, @code{save-excursion} does not restore window-buffer
-correspondences altered by functions such as @code{switch-to-buffer}.
-One way to restore these correspondences, and the selected window, is to
-use @code{save-window-excursion} inside @code{save-excursion}
-(@pxref{Window Configurations}).
-
-The value returned by @code{save-excursion} is the result of the last of
-@var{forms}, or @code{nil} if no @var{forms} are given.
-
-@example
-@group
-(save-excursion
- @var{forms})
-@equiv{}
-(let ((old-buf (current-buffer))
- (old-pnt (point-marker))
- (old-mark (copy-marker (mark-marker))))
- (unwind-protect
- (progn @var{forms})
- (set-buffer old-buf)
- (goto-char old-pnt)
- (set-marker (mark-marker) old-mark)))
-@end group
-@end example
-@end defspec
-
-@node Narrowing
-@section Narrowing
-@cindex narrowing
-@cindex restriction (in a buffer)
-@cindex accessible portion (of a buffer)
-
- @dfn{Narrowing} means limiting the text addressable by Emacs editing
-commands to a limited range of characters in a buffer. The text that
-remains addressable is called the @dfn{accessible portion} of the
-buffer.
-
- Narrowing is specified with two buffer positions which become the
-beginning and end of the accessible portion. For most editing commands
-and most Emacs primitives, these positions replace the values of the
-beginning and end of the buffer. While narrowing is in effect, no text
-outside the accessible portion is displayed, and point cannot move
-outside the accessible portion.
-
- Values such as positions or line numbers, which usually count from the
-beginning of the buffer, do so despite narrowing, but the functions
-which use them refuse to operate on text that is inaccessible.
-
- The commands for saving buffers are unaffected by narrowing; they save
-the entire buffer regardless of any narrowing.
-
-@deffn Command narrow-to-region start end
-This function sets the accessible portion of the current buffer to start
-at @var{start} and end at @var{end}. Both arguments should be character
-positions.
-
-In an interactive call, @var{start} and @var{end} are set to the bounds
-of the current region (point and the mark, with the smallest first).
-@end deffn
-
-@deffn Command narrow-to-page move-count
-This function sets the accessible portion of the current buffer to
-include just the current page. An optional first argument
-@var{move-count} non-@code{nil} means to move forward or backward by
-@var{move-count} pages and then narrow. The variable
-@code{page-delimiter} specifies where pages start and end
-(@pxref{Standard Regexps}).
-
-In an interactive call, @var{move-count} is set to the numeric prefix
-argument.
-@end deffn
-
-@deffn Command widen
-@cindex widening
-This function cancels any narrowing in the current buffer, so that the
-entire contents are accessible. This is called @dfn{widening}.
-It is equivalent to the following expression:
-
-@example
-(narrow-to-region 1 (1+ (buffer-size)))
-@end example
-@end deffn
-
-@defspec save-restriction body@dots{}
-This special form saves the current bounds of the accessible portion,
-evaluates the @var{body} forms, and finally restores the saved bounds,
-thus restoring the same state of narrowing (or absence thereof) formerly
-in effect. The state of narrowing is restored even in the event of an
-abnormal exit via @code{throw} or error (@pxref{Nonlocal Exits}).
-Therefore, this construct is a clean way to narrow a buffer temporarily.
-
-The value returned by @code{save-restriction} is that returned by the
-last form in @var{body}, or @code{nil} if no body forms were given.
-
-@c Wordy to avoid overfull hbox. --rjc 16mar92
-@strong{Caution:} it is easy to make a mistake when using the
-@code{save-restriction} construct. Read the entire description here
-before you try it.
-
-If @var{body} changes the current buffer, @code{save-restriction} still
-restores the restrictions on the original buffer (the buffer whose
-restructions it saved from), but it does not restore the identity of the
-current buffer.
-
-@code{save-restriction} does @emph{not} restore point and the mark; use
-@code{save-excursion} for that. If you use both @code{save-restriction}
-and @code{save-excursion} together, @code{save-excursion} should come
-first (on the outside). Otherwise, the old point value would be
-restored with temporary narrowing still in effect. If the old point
-value were outside the limits of the temporary narrowing, this would
-fail to restore it accurately.
-
-The @code{save-restriction} special form records the values of the
-beginning and end of the accessible portion as distances from the
-beginning and end of the buffer. In other words, it records the amount
-of inaccessible text before and after the accessible portion.
-
-This method yields correct results if @var{body} does further narrowing.
-However, @code{save-restriction} can become confused if the body widens
-and then make changes outside the range of the saved narrowing. When
-this is what you want to do, @code{save-restriction} is not the right
-tool for the job. Here is what you must use instead:
-
-@example
-@group
-(let ((beg (point-min-marker))
- (end (point-max-marker)))
- (unwind-protect
- (progn @var{body})
- (save-excursion
- (set-buffer (marker-buffer beg))
- (narrow-to-region beg end))))
-@end group
-@end example
-
-Here is a simple example of correct use of @code{save-restriction}:
-
-@example
-@group
----------- Buffer: foo ----------
-This is the contents of foo
-This is the contents of foo
-This is the contents of foo@point{}
----------- Buffer: foo ----------
-@end group
-
-@group
-(save-excursion
- (save-restriction
- (goto-char 1)
- (forward-line 2)
- (narrow-to-region 1 (point))
- (goto-char (point-min))
- (replace-string "foo" "bar")))
-
----------- Buffer: foo ----------
-This is the contents of bar
-This is the contents of bar
-This is the contents of foo@point{}
----------- Buffer: foo ----------
-@end group
-@end example
-@end defspec
diff --git a/lispref/processes.texi b/lispref/processes.texi
deleted file mode 100644
index 359366cf066..00000000000
--- a/lispref/processes.texi
+++ /dev/null
@@ -1,1233 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/processes
-@node Processes, System Interface, Abbrevs, Top
-@chapter Processes
-@cindex child process
-@cindex parent process
-@cindex subprocess
-@cindex process
-
- In the terminology of operating systems, a @dfn{process} is a space in
-which a program can execute. Emacs runs in a process. Emacs Lisp
-programs can invoke other programs in processes of their own. These are
-called @dfn{subprocesses} or @dfn{child processes} of the Emacs process,
-which is their @dfn{parent process}.
-
- A subprocess of Emacs may be @dfn{synchronous} or @dfn{asynchronous},
-depending on how it is created. When you create a synchronous
-subprocess, the Lisp program waits for the subprocess to terminate
-before continuing execution. When you create an asynchronous
-subprocess, it can run in parallel with the Lisp program. This kind of
-subprocess is represented within Emacs by a Lisp object which is also
-called a ``process''. Lisp programs can use this object to communicate
-with the subprocess or to control it. For example, you can send
-signals, obtain status information, receive output from the process, or
-send input to it.
-
-@defun processp object
-This function returns @code{t} if @var{object} is a process,
-@code{nil} otherwise.
-@end defun
-
-@menu
-* Subprocess Creation:: Functions that start subprocesses.
-* Synchronous Processes:: Details of using synchronous subprocesses.
-* MS-DOS Subprocesses:: On MS-DOS, you must indicate text vs binary
- for data sent to and from a subprocess.
-* Asynchronous Processes:: Starting up an asynchronous subprocess.
-* Deleting Processes:: Eliminating an asynchronous subprocess.
-* Process Information:: Accessing run-status and other attributes.
-* Input to Processes:: Sending input to an asynchronous subprocess.
-* Signals to Processes:: Stopping, continuing or interrupting
- an asynchronous subprocess.
-* Output from Processes:: Collecting output from an asynchronous subprocess.
-* Sentinels:: Sentinels run when process run-status changes.
-* Transaction Queues:: Transaction-based communication with subprocesses.
-* Network:: Opening network connections.
-@end menu
-
-@node Subprocess Creation
-@section Functions that Create Subprocesses
-
- There are three functions that create a new subprocess in which to run
-a program. One of them, @code{start-process}, creates an asynchronous
-process and returns a process object (@pxref{Asynchronous Processes}).
-The other two, @code{call-process} and @code{call-process-region},
-create a synchronous process and do not return a process object
-(@pxref{Synchronous Processes}).
-
- Synchronous and asynchronous processes are explained in following
-sections. Since the three functions are all called in a similar
-fashion, their common arguments are described here.
-
-@cindex execute program
-@cindex @code{PATH} environment variable
-@cindex @code{HOME} environment variable
- In all cases, the function's @var{program} argument specifies the
-program to be run. An error is signaled if the file is not found or
-cannot be executed. If the file name is relative, the variable
-@code{exec-path} contains a list of directories to search. Emacs
-initializes @code{exec-path} when it starts up, based on the value of
-the environment variable @code{PATH}. The standard file name
-constructs, @samp{~}, @samp{.}, and @samp{..}, are interpreted as usual
-in @code{exec-path}, but environment variable substitutions
-(@samp{$HOME}, etc.) are not recognized; use
-@code{substitute-in-file-name} to perform them (@pxref{File Name
-Expansion}).
-
- Each of the subprocess-creating functions has a @var{buffer-or-name}
-argument which specifies where the standard output from the program will
-go. If @var{buffer-or-name} is @code{nil}, that says to discard the
-output unless a filter function handles it. (@xref{Filter Functions},
-and @ref{Read and Print}.) Normally, you should avoid having multiple
-processes send output to the same buffer because their output would be
-intermixed randomly.
-
-@cindex program arguments
- All three of the subprocess-creating functions have a @code{&rest}
-argument, @var{args}. The @var{args} must all be strings, and they are
-supplied to @var{program} as separate command line arguments. Wildcard
-characters and other shell constructs are not allowed in these strings,
-since they are passed directly to the specified program.
-
- @strong{Please note:} The argument @var{program} contains only the
-name of the program; it may not contain any command-line arguments. You
-must use @var{args} to provide those.
-
- The subprocess gets its current directory from the value of
-@code{default-directory} (@pxref{File Name Expansion}).
-
-@cindex environment variables, subprocesses
- The subprocess inherits its environment from Emacs; but you can
-specify overrides for it with @code{process-environment}. @xref{System
-Environment}.
-
-@defvar exec-directory
-@pindex wakeup
-The value of this variable is the name of a directory (a string) that
-contains programs that come with GNU Emacs, that are intended for Emacs
-to invoke. The program @code{wakeup} is an example of such a program;
-the @code{display-time} command uses it to get a reminder once per
-minute.
-@end defvar
-
-@defopt exec-path
-The value of this variable is a list of directories to search for
-programs to run in subprocesses. Each element is either the name of a
-directory (i.e., a string), or @code{nil}, which stands for the default
-directory (which is the value of @code{default-directory}).
-@cindex program directories
-
-The value of @code{exec-path} is used by @code{call-process} and
-@code{start-process} when the @var{program} argument is not an absolute
-file name.
-@end defopt
-
-@node Synchronous Processes
-@section Creating a Synchronous Process
-@cindex synchronous subprocess
-
- After a @dfn{synchronous process} is created, Emacs waits for the
-process to terminate before continuing. Starting Dired is an example of
-this: it runs @code{ls} in a synchronous process, then modifies the
-output slightly. Because the process is synchronous, the entire
-directory listing arrives in the buffer before Emacs tries to do
-anything with it.
-
- While Emacs waits for the synchronous subprocess to terminate, the
-user can quit by typing @kbd{C-g}. The first @kbd{C-g} tries to kill
-the subprocess with a @code{SIGINT} signal; but it waits until the
-subprocess actually terminates before quitting. If during that time the
-user types another @kbd{C-g}, that kills the subprocess instantly with
-@code{SIGKILL} and quits immediately. @xref{Quitting}.
-
- The synchronous subprocess functions returned @code{nil} in version
-18. In version 19, they return an indication of how the process
-terminated.
-
-@defun call-process program &optional infile destination display &rest args
-This function calls @var{program} in a separate process and waits for
-it to finish.
-
-The standard input for the process comes from file @var{infile} if
-@var{infile} is not @code{nil} and from @file{/dev/null} otherwise.
-The argument @var{destination} says where to put the process output.
-Here are the possibilities:
-
-@table @asis
-@item a buffer
-Insert the output in that buffer, before point. This includes both the
-standard output stream and the standard error stream of the process.
-
-@item a string
-Find the buffer with that name, then insert the output in that buffer,
-before point.
-
-@item @code{t}
-Insert the output in the current buffer, before point.
-
-@item @code{nil}
-Discard the output.
-
-@item 0
-Discard the output, and return immediately without waiting
-for the subprocess to finish.
-
-In this case, the process is not truly synchronous, since it can run in
-parallel with Emacs; but you can think of it as synchronous in that
-Emacs is essentially finished with the subprocess as soon as this
-function returns.
-
-@item (@var{real-destination} @var{error-destination})
-Keep the standard output stream separate from the standard error stream;
-deal with the ordinary output as specified by @var{real-destination},
-and dispose of the error output according to @var{error-destination}.
-The value @code{nil} means discard it, @code{t} means mix it with the
-ordinary output, and a string specifies a file name to redirect error
-output into.
-
-You can't directly specify a buffer to put the error output in; that is
-too difficult to implement. But you can achieve this result by sending
-the error output to a temporary file and then inserting the file into a
-buffer.
-@end table
-
-If @var{display} is non-@code{nil}, then @code{call-process} redisplays
-the buffer as output is inserted. Otherwise the function does no
-redisplay, and the results become visible on the screen only when Emacs
-redisplays that buffer in the normal course of events.
-
-The remaining arguments, @var{args}, are strings that specify command
-line arguments for the program.
-
-The value returned by @code{call-process} (unless you told it not to
-wait) indicates the reason for process termination. A number gives the
-exit status of the subprocess; 0 means success, and any other value
-means failure. If the process terminated with a signal,
-@code{call-process} returns a string describing the signal.
-
-In the examples below, the buffer @samp{foo} is current.
-
-@smallexample
-@group
-(call-process "pwd" nil t)
- @result{} nil
-
----------- Buffer: foo ----------
-/usr/user/lewis/manual
----------- Buffer: foo ----------
-@end group
-
-@group
-(call-process "grep" nil "bar" nil "lewis" "/etc/passwd")
- @result{} nil
-
----------- Buffer: bar ----------
-lewis:5LTsHm66CSWKg:398:21:Bil Lewis:/user/lewis:/bin/csh
-
----------- Buffer: bar ----------
-@end group
-@end smallexample
-
-The @code{insert-directory} function contains a good example of the use
-of @code{call-process}:
-
-@smallexample
-@group
-(call-process insert-directory-program nil t nil switches
- (if full-directory-p
- (concat (file-name-as-directory file) ".")
- file))
-@end group
-@end smallexample
-@end defun
-
-@defun call-process-region start end program &optional delete destination display &rest args
-This function sends the text between @var{start} to @var{end} as
-standard input to a process running @var{program}. It deletes the text
-sent if @var{delete} is non-@code{nil}; this is useful when @var{buffer}
-is @code{t}, to insert the output in the current buffer.
-
-The arguments @var{destination} and @var{display} control what to do
-with the output from the subprocess, and whether to update the display
-as it comes in. For details, see the description of
-@code{call-process}, above. If @var{destination} is the integer 0,
-@code{call-process-region} discards the output and returns @code{nil}
-immediately, without waiting for the subprocess to finish.
-
-The remaining arguments, @var{args}, are strings that specify command
-line arguments for the program.
-
-The return value of @code{call-process-region} is just like that of
-@code{call-process}: @code{nil} if you told it to return without
-waiting; otherwise, a number or string which indicates how the
-subprocess terminated.
-
-In the following example, we use @code{call-process-region} to run the
-@code{cat} utility, with standard input being the first five characters
-in buffer @samp{foo} (the word @samp{input}). @code{cat} copies its
-standard input into its standard output. Since the argument
-@var{destination} is @code{t}, this output is inserted in the current
-buffer.
-
-@smallexample
-@group
----------- Buffer: foo ----------
-input@point{}
----------- Buffer: foo ----------
-@end group
-
-@group
-(call-process-region 1 6 "cat" nil t)
- @result{} nil
-
----------- Buffer: foo ----------
-inputinput@point{}
----------- Buffer: foo ----------
-@end group
-@end smallexample
-
- The @code{shell-command-on-region} command uses
-@code{call-process-region} like this:
-
-@smallexample
-@group
-(call-process-region
- start end
- shell-file-name ; @r{Name of program.}
- nil ; @r{Do not delete region.}
- buffer ; @r{Send output to @code{buffer}.}
- nil ; @r{No redisplay during output.}
- "-c" command) ; @r{Arguments for the shell.}
-@end group
-@end smallexample
-@end defun
-
-@node MS-DOS Subprocesses
-@section MS-DOS Subprocesses
-
- On MS-DOS, you must indicate whether the data going to and from
-a synchronous subprocess are text or binary. Text data requires
-translation between the end-of-line convention used within Emacs
-(a single newline character) and the convention used outside Emacs
-(the two-character sequence, @sc{crlf}).
-
- The variable @code{binary-process-input} applies to input sent to the
-subprocess, and @code{binary-process-output} applies to output received
-from it. A non-@code{nil} value means the data is non-text; @code{nil}
-means the data is text, and calls for conversion.
-
-@defvar binary-process-input
-If this variable is @code{nil}, convert newlines to @sc{crlf} sequences in
-the input to a synchronous subprocess.
-@end defvar
-
-@defvar binary-process-output
-If this variable is @code{nil}, convert @sc{crlf} sequences to newlines in
-the output from a synchronous subprocess.
-@end defvar
-
- @xref{Files and MS-DOS}, for related information.
-
-@node Asynchronous Processes
-@section Creating an Asynchronous Process
-@cindex asynchronous subprocess
-
- After an @dfn{asynchronous process} is created, Emacs and the Lisp
-program both continue running immediately. The process may thereafter
-run in parallel with Emacs, and the two may communicate with each other
-using the functions described in following sections. Here we describe
-how to create an asynchronous process with @code{start-process}.
-
-@defun start-process name buffer-or-name program &rest args
-This function creates a new asynchronous subprocess and starts the
-program @var{program} running in it. It returns a process object that
-stands for the new subprocess in Lisp. The argument @var{name}
-specifies the name for the process object; if a process with this name
-already exists, then @var{name} is modified (by adding @samp{<1>}, etc.)
-to be unique. The buffer @var{buffer-or-name} is the buffer to
-associate with the process.
-
-The remaining arguments, @var{args}, are strings that specify command
-line arguments for the program.
-
-In the example below, the first process is started and runs (rather,
-sleeps) for 100 seconds. Meanwhile, the second process is started, and
-given the name @samp{my-process<1>} for the sake of uniqueness. It
-inserts the directory listing at the end of the buffer @samp{foo},
-before the first process finishes. Then it finishes, and a message to
-that effect is inserted in the buffer. Much later, the first process
-finishes, and another message is inserted in the buffer for it.
-
-@smallexample
-@group
-(start-process "my-process" "foo" "sleep" "100")
- @result{} #<process my-process>
-@end group
-
-@group
-(start-process "my-process" "foo" "ls" "-l" "/user/lewis/bin")
- @result{} #<process my-process<1>>
-
----------- Buffer: foo ----------
-total 2
-lrwxrwxrwx 1 lewis 14 Jul 22 10:12 gnuemacs --> /emacs
--rwxrwxrwx 1 lewis 19 Jul 30 21:02 lemon
-
-Process my-process<1> finished
-
-Process my-process finished
----------- Buffer: foo ----------
-@end group
-@end smallexample
-@end defun
-
-@defun start-process-shell-command name buffer-or-name command &rest command-args
-This function is like @code{start-process} except that it uses a shell
-to execute the specified command. The argument @var{command} is a shell
-command name, and @var{command-args} are the arguments for the shell
-command.
-@end defun
-
-@defvar process-connection-type
-@cindex pipes
-@cindex @sc{pty}s
-This variable controls the type of device used to communicate with
-asynchronous subprocesses. If it is non-@code{nil}, then @sc{pty}s are
-used, when available. Otherwise, pipes are used.
-
-@sc{pty}s are usually preferable for processes visible to the user, as
-in Shell mode, because they allow job control (@kbd{C-c}, @kbd{C-z},
-etc.) to work between the process and its children whereas pipes do not.
-For subprocesses used for internal purposes by programs, it is often
-better to use a pipe, because they are more efficient. In addition, the
-total number of @sc{pty}s is limited on many systems and it is good not
-to waste them.
-
-The value @code{process-connection-type} is used when
-@code{start-process} is called. So you can specify how to communicate
-with one subprocess by binding the variable around the call to
-@code{start-process}.
-
-@smallexample
-@group
-(let ((process-connection-type nil)) ; @r{Use a pipe.}
- (start-process @dots{}))
-@end group
-@end smallexample
-
-To determine whether a given subprocess actually got a pipe or a
-@sc{pty}, use the function @code{process-tty-name} (@pxref{Process
-Information}).
-@end defvar
-
-@node Deleting Processes
-@section Deleting Processes
-@cindex deleting processes
-
- @dfn{Deleting a process} disconnects Emacs immediately from the
-subprocess, and removes it from the list of active processes. It sends
-a signal to the subprocess to make the subprocess terminate, but this is
-not guaranteed to happen immediately. The process object itself
-continues to exist as long as other Lisp objects point to it. The
-process mark continues to point to the same place as before (usually
-into a buffer where output from the process was being inserted).
-
- You can delete a process explicitly at any time. Processes are
-deleted automatically after they terminate, but not necessarily right
-away. If you delete a terminated process explicitly before it is
-deleted automatically, no harm results.
-
-@defvar delete-exited-processes
-This variable controls automatic deletion of processes that have
-terminated (due to calling @code{exit} or to a signal). If it is
-@code{nil}, then they continue to exist until the user runs
-@code{list-processes}. Otherwise, they are deleted immediately after
-they exit.
-@end defvar
-
-@defun delete-process name
-This function deletes the process associated with @var{name}, killing it
-with a @code{SIGHUP} signal. The argument @var{name} may be a process,
-the name of a process, a buffer, or the name of a buffer.
-
-@smallexample
-@group
-(delete-process "*shell*")
- @result{} nil
-@end group
-@end smallexample
-@end defun
-
-@defun process-kill-without-query process
-This function declares that Emacs need not query the user if
-@var{process} is still running when Emacs is exited. The process will
-be deleted silently. The value is @code{t}.
-
-@smallexample
-@group
-(process-kill-without-query (get-process "shell"))
- @result{} t
-@end group
-@end smallexample
-@end defun
-
-@node Process Information
-@section Process Information
-
- Several functions return information about processes.
-@code{list-processes} is provided for interactive use.
-
-@deffn Command list-processes
-This command displays a listing of all living processes. In addition,
-it finally deletes any process whose status was @samp{Exited} or
-@samp{Signaled}. It returns @code{nil}.
-@end deffn
-
-@defun process-list
-This function returns a list of all processes that have not been deleted.
-
-@smallexample
-@group
-(process-list)
- @result{} (#<process display-time> #<process shell>)
-@end group
-@end smallexample
-@end defun
-
-@defun get-process name
-This function returns the process named @var{name}, or @code{nil} if
-there is none. An error is signaled if @var{name} is not a string.
-
-@smallexample
-@group
-(get-process "shell")
- @result{} #<process shell>
-@end group
-@end smallexample
-@end defun
-
-@defun process-command process
-This function returns the command that was executed to start
-@var{process}. This is a list of strings, the first string being the
-program executed and the rest of the strings being the arguments that
-were given to the program.
-
-@smallexample
-@group
-(process-command (get-process "shell"))
- @result{} ("/bin/csh" "-i")
-@end group
-@end smallexample
-@end defun
-
-@defun process-id process
-This function returns the @sc{pid} of @var{process}. This is an
-integer that distinguishes the process @var{process} from all other
-processes running on the same computer at the current time. The
-@sc{pid} of a process is chosen by the operating system kernel when the
-process is started and remains constant as long as the process exists.
-@end defun
-
-@defun process-name process
-This function returns the name of @var{process}.
-@end defun
-
-@defun process-status process-name
-This function returns the status of @var{process-name} as a symbol.
-The argument @var{process-name} must be a process, a buffer, a
-process name (string) or a buffer name (string).
-
-The possible values for an actual subprocess are:
-
-@table @code
-@item run
-for a process that is running.
-@item stop
-for a process that is stopped but continuable.
-@item exit
-for a process that has exited.
-@item signal
-for a process that has received a fatal signal.
-@item open
-for a network connection that is open.
-@item closed
-for a network connection that is closed. Once a connection
-is closed, you cannot reopen it, though you might be able to open
-a new connection to the same place.
-@item nil
-if @var{process-name} is not the name of an existing process.
-@end table
-
-@smallexample
-@group
-(process-status "shell")
- @result{} run
-@end group
-@group
-(process-status (get-buffer "*shell*"))
- @result{} run
-@end group
-@group
-x
- @result{} #<process xx<1>>
-(process-status x)
- @result{} exit
-@end group
-@end smallexample
-
-For a network connection, @code{process-status} returns one of the symbols
-@code{open} or @code{closed}. The latter means that the other side
-closed the connection, or Emacs did @code{delete-process}.
-
-In earlier Emacs versions (prior to version 19), the status of a network
-connection was @code{run} if open, and @code{exit} if closed.
-@end defun
-
-@defun process-exit-status process
-This function returns the exit status of @var{process} or the signal
-number that killed it. (Use the result of @code{process-status} to
-determine which of those it is.) If @var{process} has not yet
-terminated, the value is 0.
-@end defun
-
-@defun process-tty-name process
-This function returns the terminal name that @var{process} is using for
-its communication with Emacs---or @code{nil} if it is using pipes
-instead of a terminal (see @code{process-connection-type} in
-@ref{Asynchronous Processes}).
-@end defun
-
-@node Input to Processes
-@section Sending Input to Processes
-@cindex process input
-
- Asynchronous subprocesses receive input when it is sent to them by
-Emacs, which is done with the functions in this section. You must
-specify the process to send input to, and the input data to send. The
-data appears on the ``standard input'' of the subprocess.
-
- Some operating systems have limited space for buffered input in a
-@sc{pty}. On these systems, Emacs sends an @sc{eof} periodically amidst
-the other characters, to force them through. For most programs,
-these @sc{eof}s do no harm.
-
-@defun process-send-string process-name string
-This function sends @var{process-name} the contents of @var{string} as
-standard input. The argument @var{process-name} must be a process or
-the name of a process. If it is @code{nil}, the current buffer's
-process is used.
-
- The function returns @code{nil}.
-
-@smallexample
-@group
-(process-send-string "shell<1>" "ls\n")
- @result{} nil
-@end group
-
-
-@group
----------- Buffer: *shell* ----------
-...
-introduction.texi syntax-tables.texi~
-introduction.texi~ text.texi
-introduction.txt text.texi~
-...
----------- Buffer: *shell* ----------
-@end group
-@end smallexample
-@end defun
-
-@deffn Command process-send-region process-name start end
-This function sends the text in the region defined by @var{start} and
-@var{end} as standard input to @var{process-name}, which is a process or
-a process name. (If it is @code{nil}, the current buffer's process is
-used.)
-
-An error is signaled unless both @var{start} and @var{end} are
-integers or markers that indicate positions in the current buffer. (It
-is unimportant which number is larger.)
-@end deffn
-
-@defun process-send-eof &optional process-name
- This function makes @var{process-name} see an end-of-file in its
-input. The @sc{eof} comes after any text already sent to it.
-
- If @var{process-name} is not supplied, or if it is @code{nil}, then
-this function sends the @sc{eof} to the current buffer's process. An
-error is signaled if the current buffer has no process.
-
- The function returns @var{process-name}.
-
-@smallexample
-@group
-(process-send-eof "shell")
- @result{} "shell"
-@end group
-@end smallexample
-@end defun
-
-@node Signals to Processes
-@section Sending Signals to Processes
-@cindex process signals
-@cindex sending signals
-@cindex signals
-
- @dfn{Sending a signal} to a subprocess is a way of interrupting its
-activities. There are several different signals, each with its own
-meaning. The set of signals and their names is defined by the operating
-system. For example, the signal @code{SIGINT} means that the user has
-typed @kbd{C-c}, or that some analogous thing has happened.
-
- Each signal has a standard effect on the subprocess. Most signals
-kill the subprocess, but some stop or resume execution instead. Most
-signals can optionally be handled by programs; if the program handles
-the signal, then we can say nothing in general about its effects.
-
- You can send signals explicitly by calling the functions in this
-section. Emacs also sends signals automatically at certain times:
-killing a buffer sends a @code{SIGHUP} signal to all its associated
-processes; killing Emacs sends a @code{SIGHUP} signal to all remaining
-processes. (@code{SIGHUP} is a signal that usually indicates that the
-user hung up the phone.)
-
- Each of the signal-sending functions takes two optional arguments:
-@var{process-name} and @var{current-group}.
-
- The argument @var{process-name} must be either a process, the name of
-one, or @code{nil}. If it is @code{nil}, the process defaults to the
-process associated with the current buffer. An error is signaled if
-@var{process-name} does not identify a process.
-
- The argument @var{current-group} is a flag that makes a difference
-when you are running a job-control shell as an Emacs subprocess. If it
-is non-@code{nil}, then the signal is sent to the current process-group
-of the terminal that Emacs uses to communicate with the subprocess. If
-the process is a job-control shell, this means the shell's current
-subjob. If it is @code{nil}, the signal is sent to the process group of
-the immediate subprocess of Emacs. If the subprocess is a job-control
-shell, this is the shell itself.
-
- The flag @var{current-group} has no effect when a pipe is used to
-communicate with the subprocess, because the operating system does not
-support the distinction in the case of pipes. For the same reason,
-job-control shells won't work when a pipe is used. See
-@code{process-connection-type} in @ref{Asynchronous Processes}.
-
-@defun interrupt-process &optional process-name current-group
-This function interrupts the process @var{process-name} by sending the
-signal @code{SIGINT}. Outside of Emacs, typing the ``interrupt
-character'' (normally @kbd{C-c} on some systems, and @code{DEL} on
-others) sends this signal. When the argument @var{current-group} is
-non-@code{nil}, you can think of this function as ``typing @kbd{C-c}''
-on the terminal by which Emacs talks to the subprocess.
-@end defun
-
-@defun kill-process &optional process-name current-group
-This function kills the process @var{process-name} by sending the
-signal @code{SIGKILL}. This signal kills the subprocess immediately,
-and cannot be handled by the subprocess.
-@end defun
-
-@defun quit-process &optional process-name current-group
-This function sends the signal @code{SIGQUIT} to the process
-@var{process-name}. This signal is the one sent by the ``quit
-character'' (usually @kbd{C-b} or @kbd{C-\}) when you are not inside
-Emacs.
-@end defun
-
-@defun stop-process &optional process-name current-group
-This function stops the process @var{process-name} by sending the
-signal @code{SIGTSTP}. Use @code{continue-process} to resume its
-execution.
-
-On systems with job control, the ``stop character'' (usually @kbd{C-z})
-sends this signal (outside of Emacs). When @var{current-group} is
-non-@code{nil}, you can think of this function as ``typing @kbd{C-z}''
-on the terminal Emacs uses to communicate with the subprocess.
-@end defun
-
-@defun continue-process &optional process-name current-group
-This function resumes execution of the process @var{process} by sending
-it the signal @code{SIGCONT}. This presumes that @var{process-name} was
-stopped previously.
-@end defun
-
-@c Emacs 19 feature
-@defun signal-process pid signal
-This function sends a signal to process @var{pid}, which need not be
-a child of Emacs. The argument @var{signal} specifies which signal
-to send; it should be an integer.
-@end defun
-
-@node Output from Processes
-@section Receiving Output from Processes
-@cindex process output
-@cindex output from processes
-
- There are two ways to receive the output that a subprocess writes to
-its standard output stream. The output can be inserted in a buffer,
-which is called the associated buffer of the process, or a function
-called the @dfn{filter function} can be called to act on the output. If
-the process has no buffer and no filter function, its output is
-discarded.
-
-@menu
-* Process Buffers:: If no filter, output is put in a buffer.
-* Filter Functions:: Filter functions accept output from the process.
-* Accepting Output:: Explicitly permitting subprocess output.
- Waiting for subprocess output.
-@end menu
-
-@node Process Buffers
-@subsection Process Buffers
-
- A process can (and usually does) have an @dfn{associated buffer},
-which is an ordinary Emacs buffer that is used for two purposes: storing
-the output from the process, and deciding when to kill the process. You
-can also use the buffer to identify a process to operate on, since in
-normal practice only one process is associated with any given buffer.
-Many applications of processes also use the buffer for editing input to
-be sent to the process, but this is not built into Emacs Lisp.
-
- Unless the process has a filter function (@pxref{Filter Functions}),
-its output is inserted in the associated buffer. The position to insert
-the output is determined by the @code{process-mark}, which is then
-updated to point to the end of the text just inserted. Usually, but not
-always, the @code{process-mark} is at the end of the buffer.
-
-@defun process-buffer process
-This function returns the associated buffer of the process
-@var{process}.
-
-@smallexample
-@group
-(process-buffer (get-process "shell"))
- @result{} #<buffer *shell*>
-@end group
-@end smallexample
-@end defun
-
-@defun process-mark process
-This function returns the process marker for @var{process}, which is the
-marker that says where to insert output from the process.
-
-If @var{process} does not have a buffer, @code{process-mark} returns a
-marker that points nowhere.
-
-Insertion of process output in a buffer uses this marker to decide where
-to insert, and updates it to point after the inserted text. That is why
-successive batches of output are inserted consecutively.
-
-Filter functions normally should use this marker in the same fashion
-as is done by direct insertion of output in the buffer. A good
-example of a filter function that uses @code{process-mark} is found at
-the end of the following section.
-
-When the user is expected to enter input in the process buffer for
-transmission to the process, the process marker is useful for
-distinguishing the new input from previous output.
-@end defun
-
-@defun set-process-buffer process buffer
-This function sets the buffer associated with @var{process} to
-@var{buffer}. If @var{buffer} is @code{nil}, the process becomes
-associated with no buffer.
-@end defun
-
-@defun get-buffer-process buffer-or-name
-This function returns the process associated with @var{buffer-or-name}.
-If there are several processes associated with it, then one is chosen.
-(Presently, the one chosen is the one most recently created.) It is
-usually a bad idea to have more than one process associated with the
-same buffer.
-
-@smallexample
-@group
-(get-buffer-process "*shell*")
- @result{} #<process shell>
-@end group
-@end smallexample
-
-Killing the process's buffer deletes the process, which kills the
-subprocess with a @code{SIGHUP} signal (@pxref{Signals to Processes}).
-@end defun
-
-@node Filter Functions
-@subsection Process Filter Functions
-@cindex filter function
-@cindex process filter
-
- A process @dfn{filter function} is a function that receives the
-standard output from the associated process. If a process has a filter,
-then @emph{all} output from that process is passed to the filter. The
-process buffer is used directly for output from the process only when
-there is no filter.
-
- A filter function must accept two arguments: the associated process and
-a string, which is the output. The function is then free to do whatever it
-chooses with the output.
-
- A filter function runs only while Emacs is waiting (e.g., for terminal
-input, or for time to elapse, or for process output). This avoids the
-timing errors that could result from running filters at random places in
-the middle of other Lisp programs. You may explicitly cause Emacs to
-wait, so that filter functions will run, by calling @code{sit-for} or
-@code{sleep-for} (@pxref{Waiting}), or @code{accept-process-output}
-(@pxref{Accepting Output}). Emacs is also waiting when the command loop
-is reading input.
-
- Quitting is normally inhibited within a filter function---otherwise,
-the effect of typing @kbd{C-g} at command level or to quit a user
-command would be unpredictable. If you want to permit quitting inside a
-filter function, bind @code{inhibit-quit} to @code{nil}.
-@xref{Quitting}.
-
- If an error happens during execution of a filter function, it is
-caught automatically, so that it doesn't stop the execution of whatever
-program was running when the filter function was started. However, if
-@code{debug-on-error} is non-@code{nil}, the error-catching is turned
-off. This makes it possible to use the Lisp debugger to debug the
-filter function. @xref{Debugger}.
-
- Many filter functions sometimes or always insert the text in the
-process's buffer, mimicking the actions of Emacs when there is no
-filter. Such filter functions need to use @code{set-buffer} in order to
-be sure to insert in that buffer. To avoid setting the current buffer
-semipermanently, these filter functions must use @code{unwind-protect}
-to make sure to restore the previous current buffer. They should also
-update the process marker, and in some cases update the value of point.
-Here is how to do these things:
-
-@smallexample
-@group
-(defun ordinary-insertion-filter (proc string)
- (let ((old-buffer (current-buffer)))
- (unwind-protect
- (let (moving)
- (set-buffer (process-buffer proc))
- (setq moving (= (point) (process-mark proc)))
-@end group
-@group
- (save-excursion
- ;; @r{Insert the text, moving the process-marker.}
- (goto-char (process-mark proc))
- (insert string)
- (set-marker (process-mark proc) (point)))
- (if moving (goto-char (process-mark proc))))
- (set-buffer old-buffer))))
-@end group
-@end smallexample
-
-@noindent
-The reason to use an explicit @code{unwind-protect} rather than letting
-@code{save-excursion} restore the current buffer is so as to preserve
-the change in point made by @code{goto-char}.
-
- To make the filter force the process buffer to be visible whenever new
-text arrives, insert the following line just before the
-@code{unwind-protect}:
-
-@smallexample
-(display-buffer (process-buffer proc))
-@end smallexample
-
- To force point to move to the end of the new output no matter where
-it was previously, eliminate the variable @code{moving} and call
-@code{goto-char} unconditionally.
-
- In earlier Emacs versions, every filter function that did regexp
-searching or matching had to explicitly save and restore the match data.
-Now Emacs does this automatically; filter functions never need to do it
-explicitly. @xref{Match Data}.
-
- A filter function that writes the output into the buffer of the
-process should check whether the buffer is still alive. If it tries to
-insert into a dead buffer, it will get an error. If the buffer is dead,
-@code{(buffer-name (process-buffer @var{process}))} returns @code{nil}.
-
- The output to the function may come in chunks of any size. A program
-that produces the same output twice in a row may send it as one batch
-of 200 characters one time, and five batches of 40 characters the next.
-
-@defun set-process-filter process filter
-This function gives @var{process} the filter function @var{filter}. If
-@var{filter} is @code{nil}, it gives the process no filter.
-@end defun
-
-@defun process-filter process
-This function returns the filter function of @var{process}, or @code{nil}
-if it has none.
-@end defun
-
- Here is an example of use of a filter function:
-
-@smallexample
-@group
-(defun keep-output (process output)
- (setq kept (cons output kept)))
- @result{} keep-output
-@end group
-@group
-(setq kept nil)
- @result{} nil
-@end group
-@group
-(set-process-filter (get-process "shell") 'keep-output)
- @result{} keep-output
-@end group
-@group
-(process-send-string "shell" "ls ~/other\n")
- @result{} nil
-kept
- @result{} ("lewis@@slug[8] % "
-@end group
-@group
-"FINAL-W87-SHORT.MSS backup.otl kolstad.mss~
-address.txt backup.psf kolstad.psf
-backup.bib~ david.mss resume-Dec-86.mss~
-backup.err david.psf resume-Dec.psf
-backup.mss dland syllabus.mss
-"
-"#backups.mss# backup.mss~ kolstad.mss
-")
-@end group
-@end smallexample
-
-@ignore @c The code in this example doesn't show the right way to do things.
-Here is another, more realistic example, which demonstrates how to use
-the process mark to do insertion in the same fashion as is done when
-there is no filter function:
-
-@smallexample
-@group
-;; @r{Insert input in the buffer specified by @code{my-shell-buffer}}
-;; @r{and make sure that buffer is shown in some window.}
-(defun my-process-filter (proc str)
- (let ((cur (selected-window))
- (pop-up-windows t))
- (pop-to-buffer my-shell-buffer)
-@end group
-@group
- (goto-char (point-max))
- (insert str)
- (set-marker (process-mark proc) (point-max))
- (select-window cur)))
-@end group
-@end smallexample
-@end ignore
-
-@node Accepting Output
-@subsection Accepting Output from Processes
-
- Output from asynchronous subprocesses normally arrives only while
-Emacs is waiting for some sort of external event, such as elapsed time
-or terminal input. Occasionally it is useful in a Lisp program to
-explicitly permit output to arrive at a specific point, or even to wait
-until output arrives from a process.
-
-@defun accept-process-output &optional process seconds millisec
-This function allows Emacs to read pending output from processes. The
-output is inserted in the associated buffers or given to their filter
-functions. If @var{process} is non-@code{nil} then this function does
-not return until some output has been received from @var{process}.
-
-@c Emacs 19 feature
-The arguments @var{seconds} and @var{millisec} let you specify timeout
-periods. The former specifies a period measured in seconds and the
-latter specifies one measured in milliseconds. The two time periods
-thus specified are added together, and @code{accept-process-output}
-returns after that much time whether or not there has been any
-subprocess output.
-
-The argument @var{seconds} need not be an integer. If it is a floating
-point number, this function waits for a fractional number of seconds.
-Some systems support only a whole number of seconds; on these systems,
-@var{seconds} is rounded down. If the system doesn't support waiting
-fractions of a second, you get an error if you specify nonzero
-@var{millisec}.
-
-Not all operating systems support waiting periods other than multiples
-of a second; on those that do not, you get an error if you specify
-nonzero @var{millisec}.
-
-The function @code{accept-process-output} returns non-@code{nil} if it
-did get some output, or @code{nil} if the timeout expired before output
-arrived.
-@end defun
-
-@node Sentinels
-@section Sentinels: Detecting Process Status Changes
-@cindex process sentinel
-@cindex sentinel
-
- A @dfn{process sentinel} is a function that is called whenever the
-associated process changes status for any reason, including signals
-(whether sent by Emacs or caused by the process's own actions) that
-terminate, stop, or continue the process. The process sentinel is also
-called if the process exits. The sentinel receives two arguments: the
-process for which the event occurred, and a string describing the type
-of event.
-
- The string describing the event looks like one of the following:
-
-@itemize @bullet
-@item
-@code{"finished\n"}.
-
-@item
-@code{"exited abnormally with code @var{exitcode}\n"}.
-
-@item
-@code{"@var{name-of-signal}\n"}.
-
-@item
-@code{"@var{name-of-signal} (core dumped)\n"}.
-@end itemize
-
- A sentinel runs only while Emacs is waiting (e.g., for terminal input,
-or for time to elapse, or for process output). This avoids the timing
-errors that could result from running them at random places in the
-middle of other Lisp programs. A program can wait, so that sentinels
-will run, by calling @code{sit-for} or @code{sleep-for}
-(@pxref{Waiting}), or @code{accept-process-output} (@pxref{Accepting
-Output}). Emacs is also waiting when the command loop is reading input.
-
- Quitting is normally inhibited within a sentinel---otherwise, the
-effect of typing @kbd{C-g} at command level or to quit a user command
-would be unpredictable. If you want to permit quitting inside a
-sentinel, bind @code{inhibit-quit} to @code{nil}. @xref{Quitting}.
-
- A sentinel that writes the output into the buffer of the process
-should check whether the buffer is still alive. If it tries to insert
-into a dead buffer, it will get an error. If the buffer is dead,
-@code{(buffer-name (process-buffer @var{process}))} returns @code{nil}.
-
- If an error happens during execution of a sentinel, it is caught
-automatically, so that it doesn't stop the execution of whatever
-programs was running when the sentinel was started. However, if
-@code{debug-on-error} is non-@code{nil}, the error-catching is turned
-off. This makes it possible to use the Lisp debugger to debug the
-sentinel. @xref{Debugger}.
-
- In earlier Emacs versions, every sentinel that did regexp searching or
-matching had to explicitly save and restore the match data. Now Emacs
-does this automatically; sentinels never need to do it explicitly.
-@xref{Match Data}.
-
-@defun set-process-sentinel process sentinel
-This function associates @var{sentinel} with @var{process}. If
-@var{sentinel} is @code{nil}, then the process will have no sentinel.
-The default behavior when there is no sentinel is to insert a message in
-the process's buffer when the process status changes.
-
-@smallexample
-@group
-(defun msg-me (process event)
- (princ
- (format "Process: %s had the event `%s'" process event)))
-(set-process-sentinel (get-process "shell") 'msg-me)
- @result{} msg-me
-@end group
-@group
-(kill-process (get-process "shell"))
- @print{} Process: #<process shell> had the event `killed'
- @result{} #<process shell>
-@end group
-@end smallexample
-@end defun
-
-@defun process-sentinel process
-This function returns the sentinel of @var{process}, or @code{nil} if it
-has none.
-@end defun
-
-@defun waiting-for-user-input-p
-While a sentinel or filter function is running, this function returns
-non-@code{nil} if Emacs was waiting for keyboard input from the user at
-the time the sentinel or filter function was called, @code{nil} if it
-was not.
-@end defun
-
-@node Transaction Queues
-@section Transaction Queues
-@cindex transaction queue
-
-You can use a @dfn{transaction queue} for more convenient communication
-with subprocesses using transactions. First use @code{tq-create} to
-create a transaction queue communicating with a specified process. Then
-you can call @code{tq-enqueue} to send a transaction.
-
-@defun tq-create process
-This function creates and returns a transaction queue communicating with
-@var{process}. The argument @var{process} should be a subprocess
-capable of sending and receiving streams of bytes. It may be a child
-process, or it may be a TCP connection to a server, possibly on another
-machine.
-@end defun
-
-@defun tq-enqueue queue question regexp closure fn
-This function sends a transaction to queue @var{queue}. Specifying the
-queue has the effect of specifying the subprocess to talk to.
-
-The argument @var{question} is the outgoing message that starts the
-transaction. The argument @var{fn} is the function to call when the
-corresponding answer comes back; it is called with two arguments:
-@var{closure}, and the answer received.
-
-The argument @var{regexp} is a regular expression that should match the
-entire answer, but nothing less; that's how @code{tq-enqueue} determines
-where the answer ends.
-
-The return value of @code{tq-enqueue} itself is not meaningful.
-@end defun
-
-@defun tq-close queue
-Shut down transaction queue @var{queue}, waiting for all pending transactions
-to complete, and then terminate the connection or child process.
-@end defun
-
-Transaction queues are implemented by means of a filter function.
-@xref{Filter Functions}.
-
-@node Network
-@section Network Connections
-@cindex network connection
-@cindex TCP
-
- Emacs Lisp programs can open TCP network connections to other processes on
-the same machine or other machines. A network connection is handled by Lisp
-much like a subprocess, and is represented by a process object.
-However, the process you are communicating with is not a child of the
-Emacs process, so you can't kill it or send it signals. All you can do
-is send and receive data. @code{delete-process} closes the connection,
-but does not kill the process at the other end; that process must decide
-what to do about closure of the connection.
-
- You can distinguish process objects representing network connections
-from those representing subprocesses with the @code{process-status}
-function. It always returns either @code{open} or @code{closed} for a
-network connection, and it never returns either of those values for a
-real subprocess. @xref{Process Information}.
-
-@defun open-network-stream name buffer-or-name host service
-This function opens a TCP connection for a service to a host. It
-returns a process object to represent the connection.
-
-The @var{name} argument specifies the name for the process object. It
-is modified as necessary to make it unique.
-
-The @var{buffer-or-name} argument is the buffer to associate with the
-connection. Output from the connection is inserted in the buffer,
-unless you specify a filter function to handle the output. If
-@var{buffer-or-name} is @code{nil}, it means that the connection is not
-associated with any buffer.
-
-The arguments @var{host} and @var{service} specify where to connect to;
-@var{host} is the host name (a string), and @var{service} is the name of
-a defined network service (a string) or a port number (an integer).
-@end defun
diff --git a/lispref/searching.texi b/lispref/searching.texi
deleted file mode 100644
index a9e45998926..00000000000
--- a/lispref/searching.texi
+++ /dev/null
@@ -1,1368 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/searching
-@node Searching and Matching, Syntax Tables, Text, Top
-@chapter Searching and Matching
-@cindex searching
-
- GNU Emacs provides two ways to search through a buffer for specified
-text: exact string searches and regular expression searches. After a
-regular expression search, you can examine the @dfn{match data} to
-determine which text matched the whole regular expression or various
-portions of it.
-
-@menu
-* String Search:: Search for an exact match.
-* Regular Expressions:: Describing classes of strings.
-* Regexp Search:: Searching for a match for a regexp.
-* POSIX Regexps:: Searching POSIX-style for the longest match.
-* Search and Replace:: Internals of @code{query-replace}.
-* Match Data:: Finding out which part of the text matched
- various parts of a regexp, after regexp search.
-* Searching and Case:: Case-independent or case-significant searching.
-* Standard Regexps:: Useful regexps for finding sentences, pages,...
-@end menu
-
- The @samp{skip-chars@dots{}} functions also perform a kind of searching.
-@xref{Skipping Characters}.
-
-@node String Search
-@section Searching for Strings
-@cindex string search
-
- These are the primitive functions for searching through the text in a
-buffer. They are meant for use in programs, but you may call them
-interactively. If you do so, they prompt for the search string;
-@var{limit} and @var{noerror} are set to @code{nil}, and @var{repeat}
-is set to 1.
-
-@deffn Command search-forward string &optional limit noerror repeat
- This function searches forward from point for an exact match for
-@var{string}. If successful, it sets point to the end of the occurrence
-found, and returns the new value of point. If no match is found, the
-value and side effects depend on @var{noerror} (see below).
-@c Emacs 19 feature
-
- In the following example, point is initially at the beginning of the
-line. Then @code{(search-forward "fox")} moves point after the last
-letter of @samp{fox}:
-
-@example
-@group
----------- Buffer: foo ----------
-@point{}The quick brown fox jumped over the lazy dog.
----------- Buffer: foo ----------
-@end group
-
-@group
-(search-forward "fox")
- @result{} 20
-
----------- Buffer: foo ----------
-The quick brown fox@point{} jumped over the lazy dog.
----------- Buffer: foo ----------
-@end group
-@end example
-
- The argument @var{limit} specifies the upper bound to the search. (It
-must be a position in the current buffer.) No match extending after
-that position is accepted. If @var{limit} is omitted or @code{nil}, it
-defaults to the end of the accessible portion of the buffer.
-
-@kindex search-failed
- What happens when the search fails depends on the value of
-@var{noerror}. If @var{noerror} is @code{nil}, a @code{search-failed}
-error is signaled. If @var{noerror} is @code{t}, @code{search-forward}
-returns @code{nil} and does nothing. If @var{noerror} is neither
-@code{nil} nor @code{t}, then @code{search-forward} moves point to the
-upper bound and returns @code{nil}. (It would be more consistent now
-to return the new position of point in that case, but some programs
-may depend on a value of @code{nil}.)
-
-If @var{repeat} is supplied (it must be a positive number), then the
-search is repeated that many times (each time starting at the end of the
-previous time's match). If these successive searches succeed, the
-function succeeds, moving point and returning its new value. Otherwise
-the search fails.
-@end deffn
-
-@deffn Command search-backward string &optional limit noerror repeat
-This function searches backward from point for @var{string}. It is
-just like @code{search-forward} except that it searches backwards and
-leaves point at the beginning of the match.
-@end deffn
-
-@deffn Command word-search-forward string &optional limit noerror repeat
-@cindex word search
-This function searches forward from point for a ``word'' match for
-@var{string}. If it finds a match, it sets point to the end of the
-match found, and returns the new value of point.
-@c Emacs 19 feature
-
-Word matching regards @var{string} as a sequence of words, disregarding
-punctuation that separates them. It searches the buffer for the same
-sequence of words. Each word must be distinct in the buffer (searching
-for the word @samp{ball} does not match the word @samp{balls}), but the
-details of punctuation and spacing are ignored (searching for @samp{ball
-boy} does match @samp{ball. Boy!}).
-
-In this example, point is initially at the beginning of the buffer; the
-search leaves it between the @samp{y} and the @samp{!}.
-
-@example
-@group
----------- Buffer: foo ----------
-@point{}He said "Please! Find
-the ball boy!"
----------- Buffer: foo ----------
-@end group
-
-@group
-(word-search-forward "Please find the ball, boy.")
- @result{} 35
-
----------- Buffer: foo ----------
-He said "Please! Find
-the ball boy@point{}!"
----------- Buffer: foo ----------
-@end group
-@end example
-
-If @var{limit} is non-@code{nil} (it must be a position in the current
-buffer), then it is the upper bound to the search. The match found must
-not extend after that position.
-
-If @var{noerror} is @code{nil}, then @code{word-search-forward} signals
-an error if the search fails. If @var{noerror} is @code{t}, then it
-returns @code{nil} instead of signaling an error. If @var{noerror} is
-neither @code{nil} nor @code{t}, it moves point to @var{limit} (or the
-end of the buffer) and returns @code{nil}.
-
-If @var{repeat} is non-@code{nil}, then the search is repeated that many
-times. Point is positioned at the end of the last match.
-@end deffn
-
-@deffn Command word-search-backward string &optional limit noerror repeat
-This function searches backward from point for a word match to
-@var{string}. This function is just like @code{word-search-forward}
-except that it searches backward and normally leaves point at the
-beginning of the match.
-@end deffn
-
-@node Regular Expressions
-@section Regular Expressions
-@cindex regular expression
-@cindex regexp
-
- A @dfn{regular expression} (@dfn{regexp}, for short) is a pattern that
-denotes a (possibly infinite) set of strings. Searching for matches for
-a regexp is a very powerful operation. This section explains how to write
-regexps; the following section says how to search for them.
-
-@menu
-* Syntax of Regexps:: Rules for writing regular expressions.
-* Regexp Example:: Illustrates regular expression syntax.
-@end menu
-
-@node Syntax of Regexps
-@subsection 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 that 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 in the future. Any other character
-appearing in a regular expression is ordinary, unless a @samp{\}
-precedes it.
-
-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}.@refill
-
-Any two regular expressions @var{a} and @var{b} can be concatenated. The
-result is a regular expression that 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 more powerful, you
-need to use one of the special characters. Here is a list of them:
-
-@need 1200
-@table @kbd
-@item .@: @r{(Period)}
-@cindex @samp{.} in regexp
-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 that begins with @samp{a} and ends with
-@samp{b}.@refill
-
-@item *
-@cindex @samp{*} in regexp
-is not a construct by itself; it is a suffix operator that means to
-repeat the preceding regular expression 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 @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{*}-modified construct in case that makes
-it possible to match the rest of the pattern. For example, in 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
-
-Nested repetition operators can be extremely slow if they specify
-backtracking loops. For example, it could take hours for the regular
-expression @samp{\(x+y*\)*a} to match the sequence
-@samp{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxz}. The slowness is because
-Emacs must try each imaginable way of grouping the 35 @samp{x}'s before
-concluding that none of them can work. To make sure your regular
-expressions run fast, check nested repetitions carefully.
-
-@item +
-@cindex @samp{+} in regexp
-is a suffix operator similar to @samp{*} except that the preceding
-expression must match at least once. So, for example, @samp{ca+r}
-matches the strings @samp{car} and @samp{caaaar} but not the string
-@samp{cr}, whereas @samp{ca*r} matches all three strings.
-
-@item ?
-@cindex @samp{?} in regexp
-is a suffix operator similar to @samp{*} except that the preceding
-expression can match either once or not at all. For example,
-@samp{ca?r} matches @samp{car} or @samp{cr}, but does not match anyhing
-else.
-
-@item [ @dots{} ]
-@cindex character set (in regexp)
-@cindex @samp{[} in regexp
-@cindex @samp{]} in regexp
-@samp{[} begins a @dfn{character set}, which is terminated by a
-@samp{]}. In the simplest case, the characters between the two brackets
-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
-
-The usual regular expression special characters are not special inside a
-character set. A completely different set of special characters exists
-inside character sets: @samp{]}, @samp{-} and @samp{^}.@refill
-
-@samp{-} is used for ranges of characters. To write a range, write 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 a period.@refill
-
-To include a @samp{]} in a character set, make it the first character.
-For example, @samp{[]a]} matches @samp{]} or @samp{a}. To include a
-@samp{-}, write @samp{-} as the first character in the set, or put it
-immediately after a range. (You can replace one individual character
-@var{c} with the range @samp{@var{c}-@var{c}} to make a place to put the
-@samp{-}.) There is no way to write a set containing just @samp{-} and
-@samp{]}.
-
-To include @samp{^} in a set, put it anywhere but at the beginning of
-the set.
-
-@item [^ @dots{} ]
-@cindex @samp{^} in regexp
-@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 (thus, @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 ^
-@cindex @samp{^} in regexp
-@cindex beginning of line in regexp
-is a special character that matches the empty string, but only at the
-beginning of a line in the text being matched. Otherwise it fails to
-match anything. Thus, @samp{^foo} matches a @samp{foo} that occurs at
-the beginning of a line.
-
-When matching a string instead of a buffer, @samp{^} matches at the
-beginning of the string or after a newline character @samp{\n}.
-
-@item $
-@cindex @samp{$} in regexp
-is similar to @samp{^} but matches only at the end of a line. Thus,
-@samp{x+$} matches a string of one @samp{x} or more at the end of a line.
-
-When matching a string instead of a buffer, @samp{$} matches at the end
-of the string or before a newline character @samp{\n}.
-
-@item \
-@cindex @samp{\} in regexp
-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 that matches only @samp{$}, and @samp{\[} is a regular
-expression that matches only @samp{[}, and so on.
-
-Note that @samp{\} also has special meaning in the read syntax of Lisp
-strings (@pxref{String Type}), and must be quoted with @samp{\}. For
-example, the regular expression that matches the @samp{\} character is
-@samp{\\}. To write a Lisp string that contains the characters
-@samp{\\}, Lisp syntax requires you to quote each @samp{\} with another
-@samp{\}. Therefore, the read syntax for a regular expression matching
-@samp{\} is @code{"\\\\"}.@refill
-@end table
-
-@strong{Please 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; quote the
-special character anyway, regardless of where it appears.@refill
-
-For the most part, @samp{\} followed by any character matches only
-that character. However, there are several exceptions: characters
-that, 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 \|
-@cindex @samp{|} in regexp
-@cindex regexp alternative
-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} matches.@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{} \)
-@cindex @samp{(} in regexp
-@cindex @samp{)} in regexp
-@cindex regexp grouping
-is a grouping construct that serves three purposes:
-
-@enumerate
-@item
-To enclose a set of @samp{\|} alternatives for other operations. Thus,
-the regular expression @samp{\(foo\|bar\)x} matches either @samp{foox}
-or @samp{barx}.
-
-@item
-To enclose an expression for a suffix operator such as @samp{*} to act
-on. Thus, @samp{ba\(na\)*} matches @samp{bananana}, etc., with any
-(zero or more) number of @samp{na} strings.@refill
-
-@item
-To record 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 that 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}
-matches the same text that matched the @var{digit}th occurrence of a
-@samp{\( @dots{} \)} construct.
-
-In other words, 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 match that same text, whatever it
-may have been.
-
-The strings matching the first nine @samp{\( @dots{} \)} constructs
-appearing in a regular expression are assigned numbers 1 through 9 in
-the order that the open parentheses appear in the regular expression.
-So you can use @samp{\1} through @samp{\9} to refer to the text matched
-by the corresponding @samp{\( @dots{} \)} constructs.
-
-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 \w
-@cindex @samp{\w} in regexp
-matches any word-constituent character. The editor syntax table
-determines which characters these are. @xref{Syntax Tables}.
-
-@item \W
-@cindex @samp{\W} in regexp
-matches any character that is not a word constituent.
-
-@item \s@var{code}
-@cindex @samp{\s} in regexp
-matches any character whose syntax is @var{code}. Here @var{code} is a
-character that represents a syntax code: thus, @samp{w} for word
-constituent, @samp{-} for whitespace, @samp{(} for open parenthesis,
-etc. @xref{Syntax Tables}, for a list of syntax codes and the
-characters that stand for them.
-
-@item \S@var{code}
-@cindex @samp{\S} in regexp
-matches any character whose syntax is not @var{code}.
-@end table
-
- The following regular expression constructs match the empty string---that is,
-they don't use up any characters---but whether they match depends on the
-context.
-
-@table @kbd
-@item \`
-@cindex @samp{\`} in regexp
-matches the empty string, but only at the beginning
-of the buffer or string being matched against.
-
-@item \'
-@cindex @samp{\'} in regexp
-matches the empty string, but only at the end of
-the buffer or string being matched against.
-
-@item \=
-@cindex @samp{\=} in regexp
-matches the empty string, but only at point.
-(This construct is not defined when matching against a string.)
-
-@item \b
-@cindex @samp{\b} in regexp
-matches the empty string, but only 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
-@cindex @samp{\B} in regexp
-matches the empty string, but @emph{not} at the beginning or
-end of a word.
-
-@item \<
-@cindex @samp{\<} in regexp
-matches the empty string, but only at the beginning of a word.
-
-@item \>
-@cindex @samp{\>} in regexp
-matches the empty string, but only at the end of a word.
-@end table
-
-@kindex invalid-regexp
- Not every string is a valid regular expression. For example, a string
-with unbalanced square brackets is invalid (with a few exceptions, such
-as @samp{[]]}), and so is a string that ends with a single @samp{\}. If
-an invalid regular expression is passed to any of the search functions,
-an @code{invalid-regexp} error is signaled.
-
-@defun regexp-quote string
-This function returns a regular expression string that matches exactly
-@var{string} and nothing else. This allows you to request an exact
-string match when calling a function that wants a regular expression.
-
-@example
-@group
-(regexp-quote "^The cat$")
- @result{} "\\^The cat\\$"
-@end group
-@end example
-
-One use of @code{regexp-quote} is to combine an exact string match with
-context described as a regular expression. For example, this searches
-for the string that is the value of @code{string}, surrounded by
-whitespace:
-
-@example
-@group
-(re-search-forward
- (concat "\\s-" (regexp-quote string) "\\s-"))
-@end group
-@end example
-@end defun
-
-@node Regexp Example
-@comment node-name, next, previous, up
-@subsection Complex Regexp Example
-
- Here is a complicated regexp, used by Emacs to recognize the end of a
-sentence together with any whitespace that follows. It is the value of
-the variable @code{sentence-end}.
-
- First, we show the regexp as a string in Lisp syntax to distinguish
-spaces from tab characters. The string constant begins and ends with a
-double-quote. @samp{\"} stands for a double-quote as part of the
-string, @samp{\\} for a backslash as part of the string, @samp{\t} for a
-tab and @samp{\n} for a newline.
-
-@example
-"[.?!][]\"')@}]*\\($\\| $\\|\t\\| \\)[ \t\n]*"
-@end example
-
- In contrast, if you evaluate the variable @code{sentence-end}, you
-will see the following:
-
-@example
-@group
-sentence-end
-@result{}
-"[.?!][]\"')@}]*\\($\\| $\\| \\| \\)[
-]*"
-@end group
-@end example
-
-@noindent
-In this output, tab and newline appear as themselves.
-
- This regular expression contains four parts in succession and can be
-deciphered as follows:
-
-@table @code
-@item [.?!]
-The first part of the pattern is a character set that matches any one of
-three characters: period, question mark, and exclamation mark. The
-match must begin with one of these three characters.
-
-@item []\"')@}]*
-The second part of the pattern matches any closing braces and quotation
-marks, zero or more of them, that may follow the period, question mark
-or exclamation mark. The @code{\"} is Lisp syntax for a double-quote in
-a string. The @samp{*} at the end indicates that the immediately
-preceding regular expression (a character set, in this case) may be
-repeated zero or more times.
-
-@item \\($\\|@ $\\|\t\\|@ @ \\)
-The third part of the pattern matches the whitespace that follows the
-end of a sentence: the end of a line, or a tab, or two spaces. The
-double backslashes mark the parentheses and vertical bars as regular
-expression syntax; the parentheses delimit a group and the vertical bars
-separate alternatives. The dollar sign is used to match the end of a
-line.
-
-@item [ \t\n]*
-Finally, the last part of the pattern matches any additional whitespace
-beyond the minimum needed to end a sentence.
-@end table
-
-@node Regexp Search
-@section Regular Expression Searching
-@cindex regular expression searching
-@cindex regexp searching
-@cindex searching for regexp
-
- In GNU Emacs, you can search for the next match for a regexp either
-incrementally or not. For incremental search commands, see @ref{Regexp
-Search, , Regular Expression Search, emacs, The GNU Emacs Manual}. Here
-we describe only the search functions useful in programs. The principal
-one is @code{re-search-forward}.
-
-@deffn Command re-search-forward regexp &optional limit noerror repeat
-This function searches forward in the current buffer for a string of
-text that is matched by the regular expression @var{regexp}. The
-function skips over any amount of text that is not matched by
-@var{regexp}, and leaves point at the end of the first match found.
-It returns the new value of point.
-
-If @var{limit} is non-@code{nil} (it must be a position in the current
-buffer), then it is the upper bound to the search. No match extending
-after that position is accepted.
-
-What happens when the search fails depends on the value of
-@var{noerror}. If @var{noerror} is @code{nil}, a @code{search-failed}
-error is signaled. If @var{noerror} is @code{t},
-@code{re-search-forward} does nothing and returns @code{nil}. If
-@var{noerror} is neither @code{nil} nor @code{t}, then
-@code{re-search-forward} moves point to @var{limit} (or the end of the
-buffer) and returns @code{nil}.
-
-If @var{repeat} is supplied (it must be a positive number), then the
-search is repeated that many times (each time starting at the end of the
-previous time's match). If these successive searches succeed, the
-function succeeds, moving point and returning its new value. Otherwise
-the search fails.
-
-In the following example, point is initially before the @samp{T}.
-Evaluating the search call moves point to the end of that line (between
-the @samp{t} of @samp{hat} and the newline).
-
-@example
-@group
----------- Buffer: foo ----------
-I read "@point{}The cat in the hat
-comes back" twice.
----------- Buffer: foo ----------
-@end group
-
-@group
-(re-search-forward "[a-z]+" nil t 5)
- @result{} 27
-
----------- Buffer: foo ----------
-I read "The cat in the hat@point{}
-comes back" twice.
----------- Buffer: foo ----------
-@end group
-@end example
-@end deffn
-
-@deffn Command re-search-backward regexp &optional limit noerror repeat
-This function searches backward in the current buffer for a string of
-text that is matched by the regular expression @var{regexp}, leaving
-point at the beginning of the first text found.
-
-This function is analogous to @code{re-search-forward}, but they are not
-simple mirror images. @code{re-search-forward} finds the match whose
-beginning is as close as possible to the starting point. If
-@code{re-search-backward} were a perfect mirror image, it would find the
-match whose end is as close as possible. However, in fact it finds the
-match whose beginning is as close as possible. The reason is that
-matching a regular expression at a given spot always works from
-beginning to end, and starts at a specified beginning position.
-
-A true mirror-image of @code{re-search-forward} would require a special
-feature for matching regexps from end to beginning. It's not worth the
-trouble of implementing that.
-@end deffn
-
-@defun string-match regexp string &optional start
-This function returns the index of the start of the first match for
-the regular expression @var{regexp} in @var{string}, or @code{nil} if
-there is no match. If @var{start} is non-@code{nil}, the search starts
-at that index in @var{string}.
-
-For example,
-
-@example
-@group
-(string-match
- "quick" "The quick brown fox jumped quickly.")
- @result{} 4
-@end group
-@group
-(string-match
- "quick" "The quick brown fox jumped quickly." 8)
- @result{} 27
-@end group
-@end example
-
-@noindent
-The index of the first character of the
-string is 0, the index of the second character is 1, and so on.
-
-After this function returns, the index of the first character beyond
-the match is available as @code{(match-end 0)}. @xref{Match Data}.
-
-@example
-@group
-(string-match
- "quick" "The quick brown fox jumped quickly." 8)
- @result{} 27
-@end group
-
-@group
-(match-end 0)
- @result{} 32
-@end group
-@end example
-@end defun
-
-@defun looking-at regexp
-This function determines whether the text in the current buffer directly
-following point matches the regular expression @var{regexp}. ``Directly
-following'' means precisely that: the search is ``anchored'' and it can
-succeed only starting with the first character following point. The
-result is @code{t} if so, @code{nil} otherwise.
-
-This function does not move point, but it updates the match data, which
-you can access using @code{match-beginning} and @code{match-end}.
-@xref{Match Data}.
-
-In this example, point is located directly before the @samp{T}. If it
-were anywhere else, the result would be @code{nil}.
-
-@example
-@group
----------- Buffer: foo ----------
-I read "@point{}The cat in the hat
-comes back" twice.
----------- Buffer: foo ----------
-
-(looking-at "The cat in the hat$")
- @result{} t
-@end group
-@end example
-@end defun
-
-@node POSIX Regexps
-@section POSIX Regular Expression Searching
-
- The usual regular expression functions do backtracking when necessary
-to handle the @samp{\|} and repetition constructs, but they continue
-this only until they find @emph{some} match. Then they succeed and
-report the first match found.
-
- This section describes alternative search functions which perform the
-full backtracking specified by the POSIX standard for regular expression
-matching. They continue backtracking until they have tried all
-possibilities and found all matches, so they can report the longest
-match, as required by POSIX. This is much slower, so use these
-functions only when you really need the longest match.
-
- In Emacs versions prior to 19.29, these functions did not exist, and
-the functions described above implemented full POSIX backtracking.
-
-@defun posix-search-forward regexp &optional limit noerror repeat
-This is like @code{re-search-forward} except that it performs the full
-backtracking specified by the POSIX standard for regular expression
-matching.
-@end defun
-
-@defun posix-search-backward regexp &optional limit noerror repeat
-This is like @code{re-search-backward} except that it performs the full
-backtracking specified by the POSIX standard for regular expression
-matching.
-@end defun
-
-@defun posix-looking-at regexp
-This is like @code{looking-at} except that it performs the full
-backtracking specified by the POSIX standard for regular expression
-matching.
-@end defun
-
-@defun posix-string-match regexp string &optional start
-This is like @code{string-match} except that it performs the full
-backtracking specified by the POSIX standard for regular expression
-matching.
-@end defun
-
-@ignore
-@deffn Command delete-matching-lines regexp
-This function is identical to @code{delete-non-matching-lines}, save
-that it deletes what @code{delete-non-matching-lines} keeps.
-
-In the example below, point is located on the first line of text.
-
-@example
-@group
----------- Buffer: foo ----------
-We hold these truths
-to be self-evident,
-that all men are created
-equal, and that they are
----------- Buffer: foo ----------
-@end group
-
-@group
-(delete-matching-lines "the")
- @result{} nil
-
----------- Buffer: foo ----------
-to be self-evident,
-that all men are created
----------- Buffer: foo ----------
-@end group
-@end example
-@end deffn
-
-@deffn Command flush-lines regexp
-This function is the same as @code{delete-matching-lines}.
-@end deffn
-
-@defun delete-non-matching-lines regexp
-This function deletes all lines following point which don't
-contain a match for the regular expression @var{regexp}.
-@end defun
-
-@deffn Command keep-lines regexp
-This function is the same as @code{delete-non-matching-lines}.
-@end deffn
-
-@deffn Command how-many regexp
-This function counts the number of matches for @var{regexp} there are in
-the current buffer following point. It prints this number in
-the echo area, returning the string printed.
-@end deffn
-
-@deffn Command count-matches regexp
-This function is a synonym of @code{how-many}.
-@end deffn
-
-@deffn Command list-matching-lines regexp nlines
-This function is a synonym of @code{occur}.
-Show all lines following point containing a match for @var{regexp}.
-Display each line with @var{nlines} lines before and after,
-or @code{-}@var{nlines} before if @var{nlines} is negative.
-@var{nlines} defaults to @code{list-matching-lines-default-context-lines}.
-Interactively it is the prefix arg.
-
-The lines are shown in a buffer named @samp{*Occur*}.
-It serves as a menu to find any of the occurrences in this buffer.
-@kbd{C-h m} (@code{describe-mode} in that buffer gives help.
-@end deffn
-
-@defopt list-matching-lines-default-context-lines
-Default value is 0.
-Default number of context lines to include around a @code{list-matching-lines}
-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.
-@end defopt
-@end ignore
-
-@node Search and Replace
-@section Search and Replace
-@cindex replacement
-
-@defun perform-replace from-string replacements query-flag regexp-flag delimited-flag &optional repeat-count map
-This function is the guts of @code{query-replace} and related commands.
-It searches for occurrences of @var{from-string} and replaces some or
-all of them. If @var{query-flag} is @code{nil}, it replaces all
-occurrences; otherwise, it asks the user what to do about each one.
-
-If @var{regexp-flag} is non-@code{nil}, then @var{from-string} is
-considered a regular expression; otherwise, it must match literally. If
-@var{delimited-flag} is non-@code{nil}, then only replacements
-surrounded by word boundaries are considered.
-
-The argument @var{replacements} specifies what to replace occurrences
-with. If it is a string, that string is used. It can also be a list of
-strings, to be used in cyclic order.
-
-If @var{repeat-count} is non-@code{nil}, it should be an integer. Then
-it specifies how many times to use each of the strings in the
-@var{replacements} list before advancing cyclicly to the next one.
-
-Normally, the keymap @code{query-replace-map} defines the possible user
-responses for queries. The argument @var{map}, if non-@code{nil}, is a
-keymap to use instead of @code{query-replace-map}.
-@end defun
-
-@defvar query-replace-map
-This variable holds a special keymap that defines the valid user
-responses for @code{query-replace} and related functions, as well as
-@code{y-or-n-p} and @code{map-y-or-n-p}. It is unusual in two ways:
-
-@itemize @bullet
-@item
-The ``key bindings'' are not commands, just symbols that are meaningful
-to the functions that use this map.
-
-@item
-Prefix keys are not supported; each key binding must be for a single event
-key sequence. This is because the functions don't use read key sequence to
-get the input; instead, they read a single event and look it up ``by hand.''
-@end itemize
-@end defvar
-
-Here are the meaningful ``bindings'' for @code{query-replace-map}.
-Several of them are meaningful only for @code{query-replace} and
-friends.
-
-@table @code
-@item act
-Do take the action being considered---in other words, ``yes.''
-
-@item skip
-Do not take action for this question---in other words, ``no.''
-
-@item exit
-Answer this question ``no,'' and give up on the entire series of
-questions, assuming that the answers will be ``no.''
-
-@item act-and-exit
-Answer this question ``yes,'' and give up on the entire series of
-questions, assuming that subsequent answers will be ``no.''
-
-@item act-and-show
-Answer this question ``yes,'' but show the results---don't advance yet
-to the next question.
-
-@item automatic
-Answer this question and all subsequent questions in the series with
-``yes,'' without further user interaction.
-
-@item backup
-Move back to the previous place that a question was asked about.
-
-@item edit
-Enter a recursive edit to deal with this question---instead of any
-other action that would normally be taken.
-
-@item delete-and-edit
-Delete the text being considered, then enter a recursive edit to replace
-it.
-
-@item recenter
-Redisplay and center the window, then ask the same question again.
-
-@item quit
-Perform a quit right away. Only @code{y-or-n-p} and related functions
-use this answer.
-
-@item help
-Display some help, then ask again.
-@end table
-
-@node Match Data
-@section The Match Data
-@cindex match data
-
- Emacs keeps track of the positions of the start and end of segments of
-text found during a regular expression search. This means, for example,
-that you can search for a complex pattern, such as a date in an Rmail
-message, and then extract parts of the match under control of the
-pattern.
-
- Because the match data normally describe the most recent search only,
-you must be careful not to do another search inadvertently between the
-search you wish to refer back to and the use of the match data. If you
-can't avoid another intervening search, you must save and restore the
-match data around it, to prevent it from being overwritten.
-
-@menu
-* Simple Match Data:: Accessing single items of match data,
- such as where a particular subexpression started.
-* Replacing Match:: Replacing a substring that was matched.
-* Entire Match Data:: Accessing the entire match data at once, as a list.
-* Saving Match Data:: Saving and restoring the match data.
-@end menu
-
-@node Simple Match Data
-@subsection Simple Match Data Access
-
- This section explains how to use the match data to find out what was
-matched by the last search or match operation.
-
- You can ask about the entire matching text, or about a particular
-parenthetical subexpression of a regular expression. The @var{count}
-argument in the functions below specifies which. If @var{count} is
-zero, you are asking about the entire match. If @var{count} is
-positive, it specifies which subexpression you want.
-
- Recall that the subexpressions of a regular expression are those
-expressions grouped with escaped parentheses, @samp{\(@dots{}\)}. The
-@var{count}th subexpression is found by counting occurrences of
-@samp{\(} from the beginning of the whole regular expression. The first
-subexpression is numbered 1, the second 2, and so on. Only regular
-expressions can have subexpressions---after a simple string search, the
-only information available is about the entire match.
-
-@defun match-string count &optional in-string
-This function returns, as a string, the text matched in the last search
-or match operation. It returns the entire text if @var{count} is zero,
-or just the portion corresponding to the @var{count}th parenthetical
-subexpression, if @var{count} is positive. If @var{count} is out of
-range, or if that subexpression didn't match anything, the value is
-@code{nil}.
-
-If the last such operation was done against a string with
-@code{string-match}, then you should pass the same string as the
-argument @var{in-string}. Otherwise, after a buffer search or match,
-you should omit @var{in-string} or pass @code{nil} for it; but you
-should make sure that the current buffer when you call
-@code{match-string} is the one in which you did the searching or
-matching.
-@end defun
-
-@defun match-beginning count
-This function returns the position of the start of text matched by the
-last regular expression searched for, or a subexpression of it.
-
-If @var{count} is zero, then the value is the position of the start of
-the entire match. Otherwise, @var{count} specifies a subexpression in
-the regular expresion, and the value of the function is the starting
-position of the match for that subexpression.
-
-The value is @code{nil} for a subexpression inside a @samp{\|}
-alternative that wasn't used in the match.
-@end defun
-
-@defun match-end count
-This function is like @code{match-beginning} except that it returns the
-position of the end of the match, rather than the position of the
-beginning.
-@end defun
-
- Here is an example of using the match data, with a comment showing the
-positions within the text:
-
-@example
-@group
-(string-match "\\(qu\\)\\(ick\\)"
- "The quick fox jumped quickly.")
- ;0123456789
- @result{} 4
-@end group
-
-@group
-(match-string 0 "The quick fox jumped quickly.")
- @result{} "quick"
-(match-string 1 "The quick fox jumped quickly.")
- @result{} "qu"
-(match-string 2 "The quick fox jumped quickly.")
- @result{} "ick"
-@end group
-
-@group
-(match-beginning 1) ; @r{The beginning of the match}
- @result{} 4 ; @r{with @samp{qu} is at index 4.}
-@end group
-
-@group
-(match-beginning 2) ; @r{The beginning of the match}
- @result{} 6 ; @r{with @samp{ick} is at index 6.}
-@end group
-
-@group
-(match-end 1) ; @r{The end of the match}
- @result{} 6 ; @r{with @samp{qu} is at index 6.}
-
-(match-end 2) ; @r{The end of the match}
- @result{} 9 ; @r{with @samp{ick} is at index 9.}
-@end group
-@end example
-
- Here is another example. Point is initially located at the beginning
-of the line. Searching moves point to between the space and the word
-@samp{in}. The beginning of the entire match is at the 9th character of
-the buffer (@samp{T}), and the beginning of the match for the first
-subexpression is at the 13th character (@samp{c}).
-
-@example
-@group
-(list
- (re-search-forward "The \\(cat \\)")
- (match-beginning 0)
- (match-beginning 1))
- @result{} (9 9 13)
-@end group
-
-@group
----------- Buffer: foo ----------
-I read "The cat @point{}in the hat comes back" twice.
- ^ ^
- 9 13
----------- Buffer: foo ----------
-@end group
-@end example
-
-@noindent
-(In this case, the index returned is a buffer position; the first
-character of the buffer counts as 1.)
-
-@node Replacing Match
-@subsection Replacing the Text That Matched
-
- This function replaces the text matched by the last search with
-@var{replacement}.
-
-@cindex case in replacements
-@defun replace-match replacement &optional fixedcase literal string subexp
-This function replaces the text in the buffer (or in @var{string}) that
-was matched by the last search. It replaces that text with
-@var{replacement}.
-
-If you did the last search in a buffer, you should specify @code{nil}
-for @var{string}. Then @code{replace-match} does the replacement by
-editing the buffer; it leaves point at the end of the replacement text,
-and returns @code{t}.
-
-If you did the search in a string, pass the same string as @var{string}.
-Then @code{replace-match} does the replacement by constructing and
-returning a new string.
-
-If @var{fixedcase} is non-@code{nil}, then the case of the replacement
-text is not changed; otherwise, the replacement text is converted to a
-different case depending upon the capitalization of the text to be
-replaced. If the original text is all upper case, the replacement text
-is converted to upper case. If the first word of the original text is
-capitalized, then the first word of the replacement text is capitalized.
-If the original text contains just one word, and that word is a capital
-letter, @code{replace-match} considers this a capitalized first word
-rather than all upper case.
-
-If @code{case-replace} is @code{nil}, then case conversion is not done,
-regardless of the value of @var{fixed-case}. @xref{Searching and Case}.
-
-If @var{literal} is non-@code{nil}, then @var{replacement} is inserted
-exactly as it is, the only alterations being case changes as needed.
-If it is @code{nil} (the default), then the character @samp{\} is treated
-specially. If a @samp{\} appears in @var{replacement}, then it must be
-part of one of the following sequences:
-
-@table @asis
-@item @samp{\&}
-@cindex @samp{&} in replacement
-@samp{\&} stands for the entire text being replaced.
-
-@item @samp{\@var{n}}
-@cindex @samp{\@var{n}} in replacement
-@samp{\@var{n}}, where @var{n} is a digit, stands for the text that
-matched the @var{n}th subexpression in the original regexp.
-Subexpressions are those expressions grouped inside @samp{\(@dots{}\)}.
-
-@item @samp{\\}
-@cindex @samp{\} in replacement
-@samp{\\} stands for a single @samp{\} in the replacement text.
-@end table
-
-If @var{subexp} is non-@code{nil}, that says to replace just
-subexpression number @var{subexp} of the regexp that was matched, not
-the entire match. For example, after matching @samp{foo \(ba*r\)},
-calling @code{replace-match} with 1 as @var{subexp} means to replace
-just the text that matched @samp{\(ba*r\)}.
-@end defun
-
-@node Entire Match Data
-@subsection Accessing the Entire Match Data
-
- The functions @code{match-data} and @code{set-match-data} read or
-write the entire match data, all at once.
-
-@defun match-data
-This function returns a newly constructed list containing all the
-information on what text the last search matched. Element zero is the
-position of the beginning of the match for the whole expression; element
-one is the position of the end of the match for the expression. The
-next two elements are the positions of the beginning and end of the
-match for the first subexpression, and so on. In general, element
-@ifinfo
-number 2@var{n}
-@end ifinfo
-@tex
-number {\mathsurround=0pt $2n$}
-@end tex
-corresponds to @code{(match-beginning @var{n})}; and
-element
-@ifinfo
-number 2@var{n} + 1
-@end ifinfo
-@tex
-number {\mathsurround=0pt $2n+1$}
-@end tex
-corresponds to @code{(match-end @var{n})}.
-
-All the elements are markers or @code{nil} if matching was done on a
-buffer, and all are integers or @code{nil} if matching was done on a
-string with @code{string-match}. (In Emacs 18 and earlier versions,
-markers were used even for matching on a string, except in the case
-of the integer 0.)
-
-As always, there must be no possibility of intervening searches between
-the call to a search function and the call to @code{match-data} that is
-intended to access the match data for that search.
-
-@example
-@group
-(match-data)
- @result{} (#<marker at 9 in foo>
- #<marker at 17 in foo>
- #<marker at 13 in foo>
- #<marker at 17 in foo>)
-@end group
-@end example
-@end defun
-
-@defun set-match-data match-list
-This function sets the match data from the elements of @var{match-list},
-which should be a list that was the value of a previous call to
-@code{match-data}.
-
-If @var{match-list} refers to a buffer that doesn't exist, you don't get
-an error; that sets the match data in a meaningless but harmless way.
-
-@findex store-match-data
-@code{store-match-data} is an alias for @code{set-match-data}.
-@end defun
-
-@node Saving Match Data
-@subsection Saving and Restoring the Match Data
-
- When you call a function that may do a search, you may need to save
-and restore the match data around that call, if you want to preserve the
-match data from an earlier search for later use. Here is an example
-that shows the problem that arises if you fail to save the match data:
-
-@example
-@group
-(re-search-forward "The \\(cat \\)")
- @result{} 48
-(foo) ; @r{Perhaps @code{foo} does}
- ; @r{more searching.}
-(match-end 0)
- @result{} 61 ; @r{Unexpected result---not 48!}
-@end group
-@end example
-
- You can save and restore the match data with @code{save-match-data}:
-
-@defmac save-match-data body@dots{}
-This special form executes @var{body}, saving and restoring the match
-data around it.
-@end defmac
-
- You can use @code{set-match-data} together with @code{match-data} to
-imitate the effect of the special form @code{save-match-data}. This is
-useful for writing code that can run in Emacs 18. Here is how:
-
-@example
-@group
-(let ((data (match-data)))
- (unwind-protect
- @dots{} ; @r{May change the original match data.}
- (set-match-data data)))
-@end group
-@end example
-
- Emacs automatically saves and restores the match data when it runs
-process filter functions (@pxref{Filter Functions}) and process
-sentinels (@pxref{Sentinels}).
-
-@ignore
- Here is a function which restores the match data provided the buffer
-associated with it still exists.
-
-@smallexample
-@group
-(defun restore-match-data (data)
-@c It is incorrect to split the first line of a doc string.
-@c If there's a problem here, it should be solved in some other way.
- "Restore the match data DATA unless the buffer is missing."
- (catch 'foo
- (let ((d data))
-@end group
- (while d
- (and (car d)
- (null (marker-buffer (car d)))
-@group
- ;; @file{match-data} @r{buffer is deleted.}
- (throw 'foo nil))
- (setq d (cdr d)))
- (set-match-data data))))
-@end group
-@end smallexample
-@end ignore
-
-@node Searching and Case
-@section Searching and Case
-@cindex searching and case
-
- By default, searches in Emacs ignore the case of the text they are
-searching through; if you specify searching for @samp{FOO}, then
-@samp{Foo} or @samp{foo} is also considered a match. Regexps, and in
-particular character sets, are included: thus, @samp{[aB]} would match
-@samp{a} or @samp{A} or @samp{b} or @samp{B}.
-
- 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 buffer-local variable; altering the
-variable affects only the current buffer. (@xref{Intro to
-Buffer-Local}.) Alternatively, you may change the value of
-@code{default-case-fold-search}, which is the default value of
-@code{case-fold-search} for buffers that do not override it.
-
- Note that the user-level incremental search feature handles case
-distinctions differently. When given a lower case letter, it looks for
-a match of either case, but when given an upper case letter, it looks
-for an upper case letter only. But this has nothing to do with the
-searching functions Lisp functions use.
-
-@defopt case-replace
-This variable determines whether the replacement functions should
-preserve case. If the variable is @code{nil}, that means to use the
-replacement text verbatim. A non-@code{nil} value means to convert the
-case of the replacement text according to the text being replaced.
-
-The function @code{replace-match} is where this variable actually has
-its effect. @xref{Replacing Match}.
-@end defopt
-
-@defopt case-fold-search
-This buffer-local variable determines whether searches should ignore
-case. If the variable is @code{nil} they do not ignore case; otherwise
-they do ignore case.
-@end defopt
-
-@defvar default-case-fold-search
-The value of this variable is the default value for
-@code{case-fold-search} in buffers that do not override it. This is the
-same as @code{(default-value 'case-fold-search)}.
-@end defvar
-
-@node Standard Regexps
-@section Standard Regular Expressions Used in Editing
-@cindex regexps used standardly in editing
-@cindex standard regexps used in editing
-
- This section describes some variables that hold regular expressions
-used for certain purposes in editing:
-
-@defvar page-delimiter
-This is the regexp describing line-beginnings that separate pages. The
-default value is @code{"^\014"} (i.e., @code{"^^L"} or @code{"^\C-l"});
-this matches a line that starts with a formfeed character.
-@end defvar
-
- The following two regular expressions should @emph{not} assume the
-match always starts at the beginning of a line; they should not use
-@samp{^} to anchor the match. Most often, the paragraph commands do
-check for a match only at the beginning of a line, which means that
-@samp{^} would be superfluous. When there is a nonzero left margin,
-they accept matches that start after the left margin. In that case, a
-@samp{^} would be incorrect. However, a @samp{^} is harmless in modes
-where a left margin is never used.
-
-@defvar paragraph-separate
-This is the regular expression for recognizing the beginning of a line
-that separates paragraphs. (If you change this, you may have to
-change @code{paragraph-start} also.) The default value is
-@w{@code{"[@ \t\f]*$"}}, which matches a line that consists entirely of
-spaces, tabs, and form feeds (after its left margin).
-@end defvar
-
-@defvar paragraph-start
-This is the regular expression for recognizing the beginning of a line
-that starts @emph{or} separates paragraphs. The default value is
-@w{@code{"[@ \t\n\f]"}}, which matches a line starting with a space, tab,
-newline, or form feed (after its left margin).
-@end defvar
-
-@defvar sentence-end
-This is the regular expression describing the end of a sentence. (All
-paragraph boundaries also end sentences, regardless.) The default value
-is:
-
-@example
-"[.?!][]\"')@}]*\\($\\| $\\|\t\\| \\)[ \t\n]*"
-@end example
-
-This means a period, question mark or exclamation mark, followed
-optionally by a closing parenthetical character, followed by tabs,
-spaces or new lines.
-
-For a detailed explanation of this regular expression, see @ref{Regexp
-Example}.
-@end defvar
diff --git a/lispref/sequences.texi b/lispref/sequences.texi
deleted file mode 100644
index c6de3f1c94d..00000000000
--- a/lispref/sequences.texi
+++ /dev/null
@@ -1,493 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/sequences
-@node Sequences Arrays Vectors, Symbols, Lists, Top
-@chapter Sequences, Arrays, and Vectors
-@cindex sequence
-
- Recall that the @dfn{sequence} type is the union of three other Lisp
-types: lists, vectors, and strings. In other words, any list is a
-sequence, any vector is a sequence, and any string is a sequence. The
-common property that all sequences have is that each is an ordered
-collection of elements.
-
- An @dfn{array} is a single primitive object that has a slot for each
-elements. All the elements are accessible in constant time, but the
-length of an existing array cannot be changed. Strings and vectors are
-the two types of arrays.
-
- A list is a sequence of elements, but it is not a single primitive
-object; it is made of cons cells, one cell per element. Finding the
-@var{n}th element requires looking through @var{n} cons cells, so
-elements farther from the beginning of the list take longer to access.
-But it is possible to add elements to the list, or remove elements.
-
- The following diagram shows the relationship between these types:
-
-@example
-@group
- ___________________________________
- | |
- | Sequence |
- | ______ ______________________ |
- | | | | | |
- | | List | | Array | |
- | | | | ________ _______ | |
- | |______| | | | | | | |
- | | | Vector | | String| | |
- | | |________| |_______| | |
- | |______________________| |
- |___________________________________|
-@end group
-@end example
-
- The elements of vectors and lists may be any Lisp objects. The
-elements of strings are all characters.
-
-@menu
-* Sequence Functions:: Functions that accept any kind of sequence.
-* Arrays:: Characteristics of arrays in Emacs Lisp.
-* Array Functions:: Functions specifically for arrays.
-* Vectors:: Special characteristics of Emacs Lisp vectors.
-* Vector Functions:: Functions specifically for vectors.
-@end menu
-
-@node Sequence Functions
-@section Sequences
-
- In Emacs Lisp, a @dfn{sequence} is either a list, a vector or a
-string. The common property that all sequences have is that each is an
-ordered collection of elements. This section describes functions that
-accept any kind of sequence.
-
-@defun sequencep object
-Returns @code{t} if @var{object} is a list, vector, or
-string, @code{nil} otherwise.
-@end defun
-
-@defun copy-sequence sequence
-@cindex copying sequences
-Returns a copy of @var{sequence}. The copy is the same type of object
-as the original sequence, and it has the same elements in the same order.
-
-Storing a new element into the copy does not affect the original
-@var{sequence}, and vice versa. However, the elements of the new
-sequence are not copies; they are identical (@code{eq}) to the elements
-of the original. Therefore, changes made within these elements, as
-found via the copied sequence, are also visible in the original
-sequence.
-
-If the sequence is a string with text properties, the property list in
-the copy is itself a copy, not shared with the original's property
-list. However, the actual values of the properties are shared.
-@xref{Text Properties}.
-
-See also @code{append} in @ref{Building Lists}, @code{concat} in
-@ref{Creating Strings}, and @code{vconcat} in @ref{Vectors}, for others
-ways to copy sequences.
-
-@example
-@group
-(setq bar '(1 2))
- @result{} (1 2)
-@end group
-@group
-(setq x (vector 'foo bar))
- @result{} [foo (1 2)]
-@end group
-@group
-(setq y (copy-sequence x))
- @result{} [foo (1 2)]
-@end group
-
-@group
-(eq x y)
- @result{} nil
-@end group
-@group
-(equal x y)
- @result{} t
-@end group
-@group
-(eq (elt x 1) (elt y 1))
- @result{} t
-@end group
-
-@group
-;; @r{Replacing an element of one sequence.}
-(aset x 0 'quux)
-x @result{} [quux (1 2)]
-y @result{} [foo (1 2)]
-@end group
-
-@group
-;; @r{Modifying the inside of a shared element.}
-(setcar (aref x 1) 69)
-x @result{} [quux (69 2)]
-y @result{} [foo (69 2)]
-@end group
-@end example
-@end defun
-
-@defun length sequence
-@cindex string length
-@cindex list length
-@cindex vector length
-@cindex sequence length
-Returns the number of elements in @var{sequence}. If @var{sequence} is
-a cons cell that is not a list (because the final @sc{cdr} is not
-@code{nil}), a @code{wrong-type-argument} error is signaled.
-
-@example
-@group
-(length '(1 2 3))
- @result{} 3
-@end group
-@group
-(length ())
- @result{} 0
-@end group
-@group
-(length "foobar")
- @result{} 6
-@end group
-@group
-(length [1 2 3])
- @result{} 3
-@end group
-@end example
-@end defun
-
-@defun elt sequence index
-@cindex elements of sequences
-This function returns the element of @var{sequence} indexed by
-@var{index}. Legitimate values of @var{index} are integers ranging from
-0 up to one less than the length of @var{sequence}. If @var{sequence}
-is a list, then out-of-range values of @var{index} return @code{nil};
-otherwise, they trigger an @code{args-out-of-range} error.
-
-@example
-@group
-(elt [1 2 3 4] 2)
- @result{} 3
-@end group
-@group
-(elt '(1 2 3 4) 2)
- @result{} 3
-@end group
-@group
-(char-to-string (elt "1234" 2))
- @result{} "3"
-@end group
-@group
-(elt [1 2 3 4] 4)
- @error{}Args out of range: [1 2 3 4], 4
-@end group
-@group
-(elt [1 2 3 4] -1)
- @error{}Args out of range: [1 2 3 4], -1
-@end group
-@end example
-
-This function generalizes @code{aref} (@pxref{Array Functions}) and
-@code{nth} (@pxref{List Elements}).
-@end defun
-
-@node Arrays
-@section Arrays
-@cindex array
-
- An @dfn{array} object has slots that hold a number of other Lisp
-objects, called the elements of the array. Any element of an array may
-be accessed in constant time. In contrast, an element of a list
-requires access time that is proportional to the position of the element
-in the list.
-
- When you create an array, you must specify how many elements it has.
-The amount of space allocated depends on the number of elements.
-Therefore, it is impossible to change the size of an array once it is
-created; you cannot add or remove elements. However, you can replace an
-element with a different value.
-
- Emacs defines two types of array, both of which are one-dimensional:
-@dfn{strings} and @dfn{vectors}. A vector is a general array; its
-elements can be any Lisp objects. A string is a specialized array; its
-elements must be characters (i.e., integers between 0 and 255). Each
-type of array has its own read syntax. @xref{String Type}, and
-@ref{Vector Type}.
-
- Both kinds of array share these characteristics:
-
-@itemize @bullet
-@item
-The first element of an array has index zero, the second element has
-index 1, and so on. This is called @dfn{zero-origin} indexing. For
-example, an array of four elements has indices 0, 1, 2, @w{and 3}.
-
-@item
-The elements of an array may be referenced or changed with the functions
-@code{aref} and @code{aset}, respectively (@pxref{Array Functions}).
-@end itemize
-
- In principle, if you wish to have an array of text characters, you
-could use either a string or a vector. In practice, we always choose
-strings for such applications, for four reasons:
-
-@itemize @bullet
-@item
-They occupy one-fourth the space of a vector of the same elements.
-
-@item
-Strings are printed in a way that shows the contents more clearly
-as characters.
-
-@item
-Strings can hold text properties. @xref{Text Properties}.
-
-@item
-Many of the specialized editing and I/O facilities of Emacs accept only
-strings. For example, you cannot insert a vector of characters into a
-buffer the way you can insert a string. @xref{Strings and Characters}.
-@end itemize
-
- By contrast, for an array of keyboard input characters (such as a key
-sequence), a vector may be necessary, because many keyboard input
-characters are outside the range that will fit in a string. @xref{Key
-Sequence Input}.
-
-@node Array Functions
-@section Functions that Operate on Arrays
-
- In this section, we describe the functions that accept both strings
-and vectors.
-
-@defun arrayp object
-This function returns @code{t} if @var{object} is an array (i.e., either a
-vector or a string).
-
-@example
-@group
-(arrayp [a])
-@result{} t
-(arrayp "asdf")
-@result{} t
-@end group
-@end example
-@end defun
-
-@defun aref array index
-@cindex array elements
-This function returns the @var{index}th element of @var{array}. The
-first element is at index zero.
-
-@example
-@group
-(setq primes [2 3 5 7 11 13])
- @result{} [2 3 5 7 11 13]
-(aref primes 4)
- @result{} 11
-(elt primes 4)
- @result{} 11
-@end group
-
-@group
-(aref "abcdefg" 1)
- @result{} 98 ; @r{@samp{b} is @sc{ASCII} code 98.}
-@end group
-@end example
-
-See also the function @code{elt}, in @ref{Sequence Functions}.
-@end defun
-
-@defun aset array index object
-This function sets the @var{index}th element of @var{array} to be
-@var{object}. It returns @var{object}.
-
-@example
-@group
-(setq w [foo bar baz])
- @result{} [foo bar baz]
-(aset w 0 'fu)
- @result{} fu
-w
- @result{} [fu bar baz]
-@end group
-
-@group
-(setq x "asdfasfd")
- @result{} "asdfasfd"
-(aset x 3 ?Z)
- @result{} 90
-x
- @result{} "asdZasfd"
-@end group
-@end example
-
-If @var{array} is a string and @var{object} is not a character, a
-@code{wrong-type-argument} error results.
-@end defun
-
-@defun fillarray array object
-This function fills the array @var{array} with @var{object}, so that
-each element of @var{array} is @var{object}. It returns @var{array}.
-
-@example
-@group
-(setq a [a b c d e f g])
- @result{} [a b c d e f g]
-(fillarray a 0)
- @result{} [0 0 0 0 0 0 0]
-a
- @result{} [0 0 0 0 0 0 0]
-@end group
-@group
-(setq s "When in the course")
- @result{} "When in the course"
-(fillarray s ?-)
- @result{} "------------------"
-@end group
-@end example
-
-If @var{array} is a string and @var{object} is not a character, a
-@code{wrong-type-argument} error results.
-@end defun
-
-The general sequence functions @code{copy-sequence} and @code{length}
-are often useful for objects known to be arrays. @xref{Sequence Functions}.
-
-@node Vectors
-@section Vectors
-@cindex vector
-
- Arrays in Lisp, like arrays in most languages, are blocks of memory
-whose elements can be accessed in constant time. A @dfn{vector} is a
-general-purpose array; its elements can be any Lisp objects. (The other
-kind of array in Emacs Lisp is the @dfn{string}, whose elements must be
-characters.) Vectors in Emacs serve as syntax tables (vectors of
-integers), as obarrays (vectors of symbols), and in keymaps (vectors of
-commands). They are also used internally as part of the representation
-of a byte-compiled function; if you print such a function, you will see
-a vector in it.
-
- In Emacs Lisp, the indices of the elements of a vector start from zero
-and count up from there.
-
- Vectors are printed with square brackets surrounding the elements.
-Thus, a vector whose elements are the symbols @code{a}, @code{b} and
-@code{a} is printed as @code{[a b a]}. You can write vectors in the
-same way in Lisp input.
-
- A vector, like a string or a number, is considered a constant for
-evaluation: the result of evaluating it is the same vector. This does
-not evaluate or even examine the elements of the vector.
-@xref{Self-Evaluating Forms}.
-
- Here are examples of these principles:
-
-@example
-@group
-(setq avector [1 two '(three) "four" [five]])
- @result{} [1 two (quote (three)) "four" [five]]
-(eval avector)
- @result{} [1 two (quote (three)) "four" [five]]
-(eq avector (eval avector))
- @result{} t
-@end group
-@end example
-
-@node Vector Functions
-@section Functions That Operate on Vectors
-
- Here are some functions that relate to vectors:
-
-@defun vectorp object
-This function returns @code{t} if @var{object} is a vector.
-
-@example
-@group
-(vectorp [a])
- @result{} t
-(vectorp "asdf")
- @result{} nil
-@end group
-@end example
-@end defun
-
-@defun vector &rest objects
-This function creates and returns a vector whose elements are the
-arguments, @var{objects}.
-
-@example
-@group
-(vector 'foo 23 [bar baz] "rats")
- @result{} [foo 23 [bar baz] "rats"]
-(vector)
- @result{} []
-@end group
-@end example
-@end defun
-
-@defun make-vector length object
-This function returns a new vector consisting of @var{length} elements,
-each initialized to @var{object}.
-
-@example
-@group
-(setq sleepy (make-vector 9 'Z))
- @result{} [Z Z Z Z Z Z Z Z Z]
-@end group
-@end example
-@end defun
-
-@defun vconcat &rest sequences
-@cindex copying vectors
-This function returns a new vector containing all the elements of the
-@var{sequences}. The arguments @var{sequences} may be lists, vectors,
-or strings. If no @var{sequences} are given, an empty vector is
-returned.
-
-The value is a newly constructed vector that is not @code{eq} to any
-existing vector.
-
-@example
-@group
-(setq a (vconcat '(A B C) '(D E F)))
- @result{} [A B C D E F]
-(eq a (vconcat a))
- @result{} nil
-@end group
-@group
-(vconcat)
- @result{} []
-(vconcat [A B C] "aa" '(foo (6 7)))
- @result{} [A B C 97 97 foo (6 7)]
-@end group
-@end example
-
-The @code{vconcat} function also allows integers as arguments. It
-converts them to strings of digits, making up the decimal print
-representation of the integer, and then uses the strings instead of the
-original integers. @strong{Don't use this feature; we plan to eliminate
-it. If you already use this feature, change your programs now!} The
-proper way to convert an integer to a decimal number in this way is with
-@code{format} (@pxref{Formatting Strings}) or @code{number-to-string}
-(@pxref{String Conversion}).
-
-For other concatenation functions, see @code{mapconcat} in @ref{Mapping
-Functions}, @code{concat} in @ref{Creating Strings}, and @code{append}
-in @ref{Building Lists}.
-@end defun
-
- The @code{append} function provides a way to convert a vector into a
-list with the same elements (@pxref{Building Lists}):
-
-@example
-@group
-(setq avector [1 two (quote (three)) "four" [five]])
- @result{} [1 two (quote (three)) "four" [five]]
-(append avector nil)
- @result{} (1 two (quote (three)) "four" [five])
-@end group
-@end example
diff --git a/lispref/streams.texi b/lispref/streams.texi
deleted file mode 100644
index 4088c80ad7f..00000000000
--- a/lispref/streams.texi
+++ /dev/null
@@ -1,735 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/streams
-@node Read and Print, Minibuffers, Debugging, Top
-@comment node-name, next, previous, up
-@chapter Reading and Printing Lisp Objects
-
- @dfn{Printing} and @dfn{reading} are the operations of converting Lisp
-objects to textual form and vice versa. They use the printed
-representations and read syntax described in @ref{Lisp Data Types}.
-
- This chapter describes the Lisp functions for reading and printing.
-It also describes @dfn{streams}, which specify where to get the text (if
-reading) or where to put it (if printing).
-
-@menu
-* Streams Intro:: Overview of streams, reading and printing.
-* Input Streams:: Various data types that can be used as input streams.
-* Input Functions:: Functions to read Lisp objects from text.
-* Output Streams:: Various data types that can be used as output streams.
-* Output Functions:: Functions to print Lisp objects as text.
-* Output Variables:: Variables that control what the printing functions do.
-@end menu
-
-@node Streams Intro
-@section Introduction to Reading and Printing
-@cindex Lisp reader
-@cindex printing
-@cindex reading
-
- @dfn{Reading} a Lisp object means parsing a Lisp expression in textual
-form and producing a corresponding Lisp object. This is how Lisp
-programs get into Lisp from files of Lisp code. We call the text the
-@dfn{read syntax} of the object. For example, the text @samp{(a .@: 5)}
-is the read syntax for a cons cell whose @sc{car} is @code{a} and whose
-@sc{cdr} is the number 5.
-
- @dfn{Printing} a Lisp object means producing text that represents that
-object---converting the object to its printed representation. Printing
-the cons cell described above produces the text @samp{(a .@: 5)}.
-
- Reading and printing are more or less inverse operations: printing the
-object that results from reading a given piece of text often produces
-the same text, and reading the text that results from printing an object
-usually produces a similar-looking object. For example, printing the
-symbol @code{foo} produces the text @samp{foo}, and reading that text
-returns the symbol @code{foo}. Printing a list whose elements are
-@code{a} and @code{b} produces the text @samp{(a b)}, and reading that
-text produces a list (but not the same list) with elements @code{a}
-and @code{b}.
-
- However, these two operations are not precisely inverses. There are
-three kinds of exceptions:
-
-@itemize @bullet
-@item
-Printing can produce text that cannot be read. For example, buffers,
-windows, frames, subprocesses and markers print into text that starts
-with @samp{#}; if you try to read this text, you get an error. There is
-no way to read those data types.
-
-@item
-One object can have multiple textual representations. For example,
-@samp{1} and @samp{01} represent the same integer, and @samp{(a b)} and
-@samp{(a .@: (b))} represent the same list. Reading will accept any of
-the alternatives, but printing must choose one of them.
-
-@item
-Comments can appear at certain points in the middle of an object's
-read sequence without affecting the result of reading it.
-@end itemize
-
-@node Input Streams
-@section Input Streams
-@cindex stream (for reading)
-@cindex input stream
-
- Most of the Lisp functions for reading text take an @dfn{input stream}
-as an argument. The input stream specifies where or how to get the
-characters of the text to be read. Here are the possible types of input
-stream:
-
-@table @asis
-@item @var{buffer}
-@cindex buffer input stream
-The input characters are read from @var{buffer}, starting with the
-character directly after point. Point advances as characters are read.
-
-@item @var{marker}
-@cindex marker input stream
-The input characters are read from the buffer that @var{marker} is in,
-starting with the character directly after the marker. The marker
-position advances as characters are read. The value of point in the
-buffer has no effect when the stream is a marker.
-
-@item @var{string}
-@cindex string input stream
-The input characters are taken from @var{string}, starting at the first
-character in the string and using as many characters as required.
-
-@item @var{function}
-@cindex function input stream
-The input characters are generated by @var{function}, one character per
-call. Normally @var{function} is called with no arguments, and should
-return a character.
-
-@cindex unreading
-Occasionally @var{function} is called with one argument (always a
-character). When that happens, @var{function} should save the argument
-and arrange to return it on the next call. This is called
-@dfn{unreading} the character; it happens when the Lisp reader reads one
-character too many and wants to ``put it back where it came from''.
-
-@item @code{t}
-@cindex @code{t} input stream
-@code{t} used as a stream means that the input is read from the
-minibuffer. In fact, the minibuffer is invoked once and the text
-given by the user is made into a string that is then used as the
-input stream.
-
-@item @code{nil}
-@cindex @code{nil} input stream
-@code{nil} supplied as an input stream means to use the value of
-@code{standard-input} instead; that value is the @dfn{default input
-stream}, and must be a non-@code{nil} input stream.
-
-@item @var{symbol}
-A symbol as input stream is equivalent to the symbol's function
-definition (if any).
-@end table
-
- Here is an example of reading from a stream that is a buffer, showing
-where point is located before and after:
-
-@example
-@group
----------- Buffer: foo ----------
-This@point{} is the contents of foo.
----------- Buffer: foo ----------
-@end group
-
-@group
-(read (get-buffer "foo"))
- @result{} is
-@end group
-@group
-(read (get-buffer "foo"))
- @result{} the
-@end group
-
-@group
----------- Buffer: foo ----------
-This is the@point{} contents of foo.
----------- Buffer: foo ----------
-@end group
-@end example
-
-@noindent
-Note that the first read skips a space. Reading skips any amount of
-whitespace preceding the significant text.
-
- In Emacs 18, reading a symbol discarded the delimiter terminating the
-symbol. Thus, point would end up at the beginning of @samp{contents}
-rather than after @samp{the}. The Emacs 19 behavior is superior because
-it correctly handles input such as @samp{bar(foo)}, where the
-open-parenthesis that ends one object is needed as the beginning of
-another object.
-
- Here is an example of reading from a stream that is a marker,
-initially positioned at the beginning of the buffer shown. The value
-read is the symbol @code{This}.
-
-@example
-@group
-
----------- Buffer: foo ----------
-This is the contents of foo.
----------- Buffer: foo ----------
-@end group
-
-@group
-(setq m (set-marker (make-marker) 1 (get-buffer "foo")))
- @result{} #<marker at 1 in foo>
-@end group
-@group
-(read m)
- @result{} This
-@end group
-@group
-m
- @result{} #<marker at 5 in foo> ;; @r{Before the first space.}
-@end group
-@end example
-
- Here we read from the contents of a string:
-
-@example
-@group
-(read "(When in) the course")
- @result{} (When in)
-@end group
-@end example
-
- The following example reads from the minibuffer. The
-prompt is: @w{@samp{Lisp expression: }}. (That is always the prompt
-used when you read from the stream @code{t}.) The user's input is shown
-following the prompt.
-
-@example
-@group
-(read t)
- @result{} 23
----------- Buffer: Minibuffer ----------
-Lisp expression: @kbd{23 @key{RET}}
----------- Buffer: Minibuffer ----------
-@end group
-@end example
-
- Finally, here is an example of a stream that is a function, named
-@code{useless-stream}. Before we use the stream, we initialize the
-variable @code{useless-list} to a list of characters. Then each call to
-the function @code{useless-stream} obtains the next character in the list
-or unreads a character by adding it to the front of the list.
-
-@example
-@group
-(setq useless-list (append "XY()" nil))
- @result{} (88 89 40 41)
-@end group
-
-@group
-(defun useless-stream (&optional unread)
- (if unread
- (setq useless-list (cons unread useless-list))
- (prog1 (car useless-list)
- (setq useless-list (cdr useless-list)))))
- @result{} useless-stream
-@end group
-@end example
-
-@noindent
-Now we read using the stream thus constructed:
-
-@example
-@group
-(read 'useless-stream)
- @result{} XY
-@end group
-
-@group
-useless-list
- @result{} (40 41)
-@end group
-@end example
-
-@noindent
-Note that the open and close parentheses remains in the list. The Lisp
-reader encountered the open parenthesis, decided that it ended the
-input, and unread it. Another attempt to read from the stream at this
-point would read @samp{()} and return @code{nil}.
-
-@defun get-file-char
-This function is used internally as an input stream to read from the
-input file opened by the function @code{load}. Don't use this function
-yourself.
-@end defun
-
-@node Input Functions
-@section Input Functions
-
- This section describes the Lisp functions and variables that pertain
-to reading.
-
- In the functions below, @var{stream} stands for an input stream (see
-the previous section). If @var{stream} is @code{nil} or omitted, it
-defaults to the value of @code{standard-input}.
-
-@kindex end-of-file
- An @code{end-of-file} error is signaled if reading encounters an
-unterminated list, vector, or string.
-
-@defun read &optional stream
-This function reads one textual Lisp expression from @var{stream},
-returning it as a Lisp object. This is the basic Lisp input function.
-@end defun
-
-@defun read-from-string string &optional start end
-@cindex string to object
-This function reads the first textual Lisp expression from the text in
-@var{string}. It returns a cons cell whose @sc{car} is that expression,
-and whose @sc{cdr} is an integer giving the position of the next
-remaining character in the string (i.e., the first one not read).
-
-If @var{start} is supplied, then reading begins at index @var{start} in
-the string (where the first character is at index 0). If @var{end} is
-also supplied, then reading stops just before that index, as if the rest
-of the string were not there.
-
-For example:
-
-@example
-@group
-(read-from-string "(setq x 55) (setq y 5)")
- @result{} ((setq x 55) . 11)
-@end group
-@group
-(read-from-string "\"A short string\"")
- @result{} ("A short string" . 16)
-@end group
-
-@group
-;; @r{Read starting at the first character.}
-(read-from-string "(list 112)" 0)
- @result{} ((list 112) . 10)
-@end group
-@group
-;; @r{Read starting at the second character.}
-(read-from-string "(list 112)" 1)
- @result{} (list . 5)
-@end group
-@group
-;; @r{Read starting at the seventh character,}
-;; @r{and stopping at the ninth.}
-(read-from-string "(list 112)" 6 8)
- @result{} (11 . 8)
-@end group
-@end example
-@end defun
-
-@defvar standard-input
-This variable holds the default input stream---the stream that
-@code{read} uses when the @var{stream} argument is @code{nil}.
-@end defvar
-
-@node Output Streams
-@section Output Streams
-@cindex stream (for printing)
-@cindex output stream
-
- An output stream specifies what to do with the characters produced
-by printing. Most print functions accept an output stream as an
-optional argument. Here are the possible types of output stream:
-
-@table @asis
-@item @var{buffer}
-@cindex buffer output stream
-The output characters are inserted into @var{buffer} at point.
-Point advances as characters are inserted.
-
-@item @var{marker}
-@cindex marker output stream
-The output characters are inserted into the buffer that @var{marker}
-points into, at the marker position. The marker position advances as
-characters are inserted. The value of point in the buffer has no effect
-on printing when the stream is a marker.
-
-@item @var{function}
-@cindex function output stream
-The output characters are passed to @var{function}, which is responsible
-for storing them away. It is called with a single character as
-argument, as many times as there are characters to be output, and is
-free to do anything at all with the characters it receives.
-
-@item @code{t}
-@cindex @code{t} output stream
-The output characters are displayed in the echo area.
-
-@item @code{nil}
-@cindex @code{nil} output stream
-@code{nil} specified as an output stream means to the value of
-@code{standard-output} instead; that value is the @dfn{default output
-stream}, and must be a non-@code{nil} output stream.
-
-@item @var{symbol}
-A symbol as output stream is equivalent to the symbol's function
-definition (if any).
-@end table
-
- Many of the valid output streams are also valid as input streams. The
-difference between input and output streams is therefore mostly one of
-how you use a Lisp object, not a distinction of types of object.
-
- Here is an example of a buffer used as an output stream. Point is
-initially located as shown immediately before the @samp{h} in
-@samp{the}. At the end, point is located directly before that same
-@samp{h}.
-
-@cindex print example
-@example
-@group
-(setq m (set-marker (make-marker) 10 (get-buffer "foo")))
- @result{} #<marker at 10 in foo>
-@end group
-
-@group
----------- Buffer: foo ----------
-This is t@point{}he contents of foo.
----------- Buffer: foo ----------
-@end group
-
-(print "This is the output" (get-buffer "foo"))
- @result{} "This is the output"
-
-@group
-m
- @result{} #<marker at 32 in foo>
-@end group
-@group
----------- Buffer: foo ----------
-This is t
-"This is the output"
-@point{}he contents of foo.
----------- Buffer: foo ----------
-@end group
-@end example
-
- Now we show a use of a marker as an output stream. Initially, the
-marker is in buffer @code{foo}, between the @samp{t} and the @samp{h} in
-the word @samp{the}. At the end, the marker has advanced over the
-inserted text so that it remains positioned before the same @samp{h}.
-Note that the location of point, shown in the usual fashion, has no
-effect.
-
-@example
-@group
----------- Buffer: foo ----------
-"This is the @point{}output"
----------- Buffer: foo ----------
-@end group
-
-@group
-m
- @result{} #<marker at 11 in foo>
-@end group
-
-@group
-(print "More output for foo." m)
- @result{} "More output for foo."
-@end group
-
-@group
----------- Buffer: foo ----------
-"This is t
-"More output for foo."
-he @point{}output"
----------- Buffer: foo ----------
-@end group
-
-@group
-m
- @result{} #<marker at 35 in foo>
-@end group
-@end example
-
- The following example shows output to the echo area:
-
-@example
-@group
-(print "Echo Area output" t)
- @result{} "Echo Area output"
----------- Echo Area ----------
-"Echo Area output"
----------- Echo Area ----------
-@end group
-@end example
-
- Finally, we show the use of a function as an output stream. The
-function @code{eat-output} takes each character that it is given and
-conses it onto the front of the list @code{last-output} (@pxref{Building
-Lists}). At the end, the list contains all the characters output, but
-in reverse order.
-
-@example
-@group
-(setq last-output nil)
- @result{} nil
-@end group
-
-@group
-(defun eat-output (c)
- (setq last-output (cons c last-output)))
- @result{} eat-output
-@end group
-
-@group
-(print "This is the output" 'eat-output)
- @result{} "This is the output"
-@end group
-
-@group
-last-output
- @result{} (10 34 116 117 112 116 117 111 32 101 104
- 116 32 115 105 32 115 105 104 84 34 10)
-@end group
-@end example
-
-@noindent
-Now we can put the output in the proper order by reversing the list:
-
-@example
-@group
-(concat (nreverse last-output))
- @result{} "
-\"This is the output\"
-"
-@end group
-@end example
-
-@noindent
-Calling @code{concat} converts the list to a string so you can see its
-contents more clearly.
-
-@node Output Functions
-@section Output Functions
-
- This section describes the Lisp functions for printing Lisp objects.
-
-@cindex @samp{"} in printing
-@cindex @samp{\} in printing
-@cindex quoting characters in printing
-@cindex escape characters in printing
- Some of the Emacs printing functions add quoting characters to the
-output when necessary so that it can be read properly. The quoting
-characters used are @samp{"} and @samp{\}; they distinguish strings from
-symbols, and prevent punctuation characters in strings and symbols from
-being taken as delimiters when reading. @xref{Printed Representation},
-for full details. You specify quoting or no quoting by the choice of
-printing function.
-
- If the text is to be read back into Lisp, then it is best to print
-with quoting characters to avoid ambiguity. Likewise, if the purpose is
-to describe a Lisp object clearly for a Lisp programmer. However, if
-the purpose of the output is to look nice for humans, then it is better
-to print without quoting.
-
- Printing a self-referent Lisp object requires an infinite amount of
-text. In certain cases, trying to produce this text leads to a stack
-overflow. Emacs detects such recursion and prints @samp{#@var{level}}
-instead of recursively printing an object already being printed. For
-example, here @samp{#0} indicates a recursive reference to the object at
-level 0 of the current print operation:
-
-@example
-(setq foo (list nil))
- @result{} (nil)
-(setcar foo foo)
- @result{} (#0)
-@end example
-
- In the functions below, @var{stream} stands for an output stream.
-(See the previous section for a description of output streams.) If
-@var{stream} is @code{nil} or omitted, it defaults to the value of
-@code{standard-output}.
-
-@defun print object &optional stream
-@cindex Lisp printer
-The @code{print} function is a convenient way of printing. It outputs
-the printed representation of @var{object} to @var{stream}, printing in
-addition one newline before @var{object} and another after it. Quoting
-characters are used. @code{print} returns @var{object}. For example:
-
-@example
-@group
-(progn (print 'The\ cat\ in)
- (print "the hat")
- (print " came back"))
- @print{}
- @print{} The\ cat\ in
- @print{}
- @print{} "the hat"
- @print{}
- @print{} " came back"
- @print{}
- @result{} " came back"
-@end group
-@end example
-@end defun
-
-@defun prin1 object &optional stream
-This function outputs the printed representation of @var{object} to
-@var{stream}. It does not print newlines to separate output as
-@code{print} does, but it does use quoting characters just like
-@code{print}. It returns @var{object}.
-
-@example
-@group
-(progn (prin1 'The\ cat\ in)
- (prin1 "the hat")
- (prin1 " came back"))
- @print{} The\ cat\ in"the hat"" came back"
- @result{} " came back"
-@end group
-@end example
-@end defun
-
-@defun princ object &optional stream
-This function outputs the printed representation of @var{object} to
-@var{stream}. It returns @var{object}.
-
-This function is intended to produce output that is readable by people,
-not by @code{read}, so it doesn't insert quoting characters and doesn't
-put double-quotes around the contents of strings. It does not add any
-spacing between calls.
-
-@example
-@group
-(progn
- (princ 'The\ cat)
- (princ " in the \"hat\""))
- @print{} The cat in the "hat"
- @result{} " in the \"hat\""
-@end group
-@end example
-@end defun
-
-@defun terpri &optional stream
-@cindex newline in print
-This function outputs a newline to @var{stream}. The name stands
-for ``terminate print''.
-@end defun
-
-@defun write-char character &optional stream
-This function outputs @var{character} to @var{stream}. It returns
-@var{character}.
-@end defun
-
-@defun prin1-to-string object &optional noescape
-@cindex object to string
-This function returns a string containing the text that @code{prin1}
-would have printed for the same argument.
-
-@example
-@group
-(prin1-to-string 'foo)
- @result{} "foo"
-@end group
-@group
-(prin1-to-string (mark-marker))
- @result{} "#<marker at 2773 in strings.texi>"
-@end group
-@end example
-
-If @var{noescape} is non-@code{nil}, that inhibits use of quoting
-characters in the output. (This argument is supported in Emacs versions
-19 and later.)
-
-@example
-@group
-(prin1-to-string "foo")
- @result{} "\"foo\""
-@end group
-@group
-(prin1-to-string "foo" t)
- @result{} "foo"
-@end group
-@end example
-
-See @code{format}, in @ref{String Conversion}, for other ways to obtain
-the printed representation of a Lisp object as a string.
-@end defun
-
-@node Output Variables
-@section Variables Affecting Output
-
-@defvar standard-output
-The value of this variable is the default output stream---the stream
-that print functions use when the @var{stream} argument is @code{nil}.
-@end defvar
-
-@defvar print-escape-newlines
-@cindex @samp{\n} in print
-@cindex escape characters
-If this variable is non-@code{nil}, then newline characters in strings
-are printed as @samp{\n} and formfeeds are printed as @samp{\f}.
-Normally these characters are printed as actual newlines and formfeeds.
-
-This variable affects the print functions @code{prin1} and @code{print},
-as well as everything that uses them. It does not affect @code{princ}.
-Here is an example using @code{prin1}:
-
-@example
-@group
-(prin1 "a\nb")
- @print{} "a
- @print{} b"
- @result{} "a
-b"
-@end group
-
-@group
-(let ((print-escape-newlines t))
- (prin1 "a\nb"))
- @print{} "a\nb"
- @result{} "a
-b"
-@end group
-@end example
-
-@noindent
-In the second expression, the local binding of
-@code{print-escape-newlines} is in effect during the call to
-@code{prin1}, but not during the printing of the result.
-@end defvar
-
-@defvar print-length
-@cindex printing limits
-The value of this variable is the maximum number of elements of a list,
-vector or bitvector that will be printed. If an object being printed has
-more than this many elements, it is abbreviated with an ellipsis.
-
-If the value is @code{nil} (the default), then there is no limit.
-
-@example
-@group
-(setq print-length 2)
- @result{} 2
-@end group
-@group
-(print '(1 2 3 4 5))
- @print{} (1 2 ...)
- @result{} (1 2 ...)
-@end group
-@end example
-@end defvar
-
-@defvar print-level
-The value of this variable is the maximum depth of nesting of
-parentheses and brackets when printed. Any list or vector at a depth
-exceeding this limit is abbreviated with an ellipsis. A value of
-@code{nil} (which is the default) means no limit.
-
-This variable exists in version 19 and later versions.
-@end defvar
diff --git a/lispref/strings.texi b/lispref/strings.texi
deleted file mode 100644
index d5b9b4c7193..00000000000
--- a/lispref/strings.texi
+++ /dev/null
@@ -1,828 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/strings
-@node Strings and Characters, Lists, Numbers, Top
-@comment node-name, next, previous, up
-@chapter Strings and Characters
-@cindex strings
-@cindex character arrays
-@cindex characters
-@cindex bytes
-
- A string in Emacs Lisp is an array that contains an ordered sequence
-of characters. Strings are used as names of symbols, buffers, and
-files, to send messages to users, to hold text being copied between
-buffers, and for many other purposes. Because strings are so important,
-Emacs Lisp has many functions expressly for manipulating them. Emacs
-Lisp programs use strings more often than individual characters.
-
- @xref{Strings of Events}, for special considerations for strings of
-keyboard character events.
-
-@menu
-* Basics: String Basics. Basic properties of strings and characters.
-* Predicates for Strings:: Testing whether an object is a string or char.
-* Creating Strings:: Functions to allocate new strings.
-* Text Comparison:: Comparing characters or strings.
-* String Conversion:: Converting characters or strings and vice versa.
-* Formatting Strings:: @code{format}: Emacs's analog of @code{printf}.
-* Character Case:: Case conversion functions.
-* Case Table:: Customizing case conversion.
-@end menu
-
-@node String Basics
-@section String and Character Basics
-
- Strings in Emacs Lisp are arrays that contain an ordered sequence of
-characters. Characters are represented in Emacs Lisp as integers;
-whether an integer was intended as a character or not is determined only
-by how it is used. Thus, strings really contain integers.
-
- The length of a string (like any array) is fixed and independent of
-the string contents, and cannot be altered. Strings in Lisp are
-@emph{not} terminated by a distinguished character code. (By contrast,
-strings in C are terminated by a character with @sc{ASCII} code 0.)
-This means that any character, including the null character (@sc{ASCII}
-code 0), is a valid element of a string.@refill
-
- Since strings are considered arrays, you can operate on them with the
-general array functions. (@xref{Sequences Arrays Vectors}.) For
-example, you can access or change individual characters in a string
-using the functions @code{aref} and @code{aset} (@pxref{Array
-Functions}).
-
- Each character in a string is stored in a single byte. Therefore,
-numbers not in the range 0 to 255 are truncated when stored into a
-string. This means that a string takes up much less memory than a
-vector of the same length.
-
- Sometimes key sequences are represented as strings. When a string is
-a key sequence, string elements in the range 128 to 255 represent meta
-characters (which are extremely large integers) rather than keyboard
-events in the range 128 to 255.
-
- Strings cannot hold characters that have the hyper, super or alt
-modifiers; they can hold @sc{ASCII} control characters, but no other
-control characters. They do not distinguish case in @sc{ASCII} control
-characters. @xref{Character Type}, for more information about
-representation of meta and other modifiers for keyboard input
-characters.
-
- Strings are useful for holding regular expressions. You can also
-match regular expressions against strings (@pxref{Regexp Search}). The
-functions @code{match-string} (@pxref{Simple Match Data}) and
-@code{replace-match} (@pxref{Replacing Match}) are useful for
-decomposing and modifying strings based on regular expression matching.
-
- Like a buffer, a string can contain text properties for the characters
-in it, as well as the characters themselves. @xref{Text Properties}.
-All the Lisp primitives that copy text from strings to buffers or other
-strings also copy the properties of the characters being copied.
-
- @xref{Text}, for information about functions that display strings or
-copy them into buffers. @xref{Character Type}, and @ref{String Type},
-for information about the syntax of characters and strings.
-
-@node Predicates for Strings
-@section The Predicates for Strings
-
-For more information about general sequence and array predicates,
-see @ref{Sequences Arrays Vectors}, and @ref{Arrays}.
-
-@defun stringp object
- This function returns @code{t} if @var{object} is a string, @code{nil}
-otherwise.
-@end defun
-
-@defun char-or-string-p object
- This function returns @code{t} if @var{object} is a string or a
-character (i.e., an integer), @code{nil} otherwise.
-@end defun
-
-@node Creating Strings
-@section Creating Strings
-
- The following functions create strings, either from scratch, or by
-putting strings together, or by taking them apart.
-
-@defun make-string count character
- This function returns a string made up of @var{count} repetitions of
-@var{character}. If @var{count} is negative, an error is signaled.
-
-@example
-(make-string 5 ?x)
- @result{} "xxxxx"
-(make-string 0 ?x)
- @result{} ""
-@end example
-
- Other functions to compare with this one include @code{char-to-string}
-(@pxref{String Conversion}), @code{make-vector} (@pxref{Vectors}), and
-@code{make-list} (@pxref{Building Lists}).
-@end defun
-
-@defun substring string start &optional end
-This function returns a new string which consists of those characters
-from @var{string} in the range from (and including) the character at the
-index @var{start} up to (but excluding) the character at the index
-@var{end}. The first character is at index zero.
-
-@example
-@group
-(substring "abcdefg" 0 3)
- @result{} "abc"
-@end group
-@end example
-
-@noindent
-Here the index for @samp{a} is 0, the index for @samp{b} is 1, and the
-index for @samp{c} is 2. Thus, three letters, @samp{abc}, are copied
-from the string @code{"abcdefg"}. The index 3 marks the character
-position up to which the substring is copied. The character whose index
-is 3 is actually the fourth character in the string.
-
-A negative number counts from the end of the string, so that @minus{}1
-signifies the index of the last character of the string. For example:
-
-@example
-@group
-(substring "abcdefg" -3 -1)
- @result{} "ef"
-@end group
-@end example
-
-@noindent
-In this example, the index for @samp{e} is @minus{}3, the index for
-@samp{f} is @minus{}2, and the index for @samp{g} is @minus{}1.
-Therefore, @samp{e} and @samp{f} are included, and @samp{g} is excluded.
-
-When @code{nil} is used as an index, it stands for the length of the
-string. Thus,
-
-@example
-@group
-(substring "abcdefg" -3 nil)
- @result{} "efg"
-@end group
-@end example
-
-Omitting the argument @var{end} is equivalent to specifying @code{nil}.
-It follows that @code{(substring @var{string} 0)} returns a copy of all
-of @var{string}.
-
-@example
-@group
-(substring "abcdefg" 0)
- @result{} "abcdefg"
-@end group
-@end example
-
-@noindent
-But we recommend @code{copy-sequence} for this purpose (@pxref{Sequence
-Functions}).
-
-If the characters copied from @var{string} have text properties, the
-properties are copied into the new string also. @xref{Text Properties}.
-
-A @code{wrong-type-argument} error is signaled if either @var{start} or
-@var{end} is not an integer or @code{nil}. An @code{args-out-of-range}
-error is signaled if @var{start} indicates a character following
-@var{end}, or if either integer is out of range for @var{string}.
-
-Contrast this function with @code{buffer-substring} (@pxref{Buffer
-Contents}), which returns a string containing a portion of the text in
-the current buffer. The beginning of a string is at index 0, but the
-beginning of a buffer is at index 1.
-@end defun
-
-@defun concat &rest sequences
-@cindex copying strings
-@cindex concatenating strings
-This function returns a new string consisting of the characters in the
-arguments passed to it (along with their text properties, if any). The
-arguments may be strings, lists of numbers, or vectors of numbers; they
-are not themselves changed. If @code{concat} receives no arguments, it
-returns an empty string.
-
-@example
-(concat "abc" "-def")
- @result{} "abc-def"
-(concat "abc" (list 120 (+ 256 121)) [122])
- @result{} "abcxyz"
-;; @r{@code{nil} is an empty sequence.}
-(concat "abc" nil "-def")
- @result{} "abc-def"
-(concat "The " "quick brown " "fox.")
- @result{} "The quick brown fox."
-(concat)
- @result{} ""
-@end example
-
-@noindent
-The second example above shows how characters stored in strings are
-taken modulo 256. In other words, each character in the string is
-stored in one byte.
-
-The @code{concat} function always constructs a new string that is
-not @code{eq} to any existing string.
-
-When an argument is an integer (not a sequence of integers), it is
-converted to a string of digits making up the decimal printed
-representation of the integer. @strong{Don't use this feature; we plan
-to eliminate it. If you already use this feature, change your programs
-now!} The proper way to convert an integer to a decimal number in this
-way is with @code{format} (@pxref{Formatting Strings}) or
-@code{number-to-string} (@pxref{String Conversion}).
-
-@example
-@group
-(concat 137)
- @result{} "137"
-(concat 54 321)
- @result{} "54321"
-@end group
-@end example
-
-For information about other concatenation functions, see the
-description of @code{mapconcat} in @ref{Mapping Functions},
-@code{vconcat} in @ref{Vectors}, and @code{append} in @ref{Building
-Lists}.
-@end defun
-
-@need 2000
-@node Text Comparison
-@section Comparison of Characters and Strings
-@cindex string equality
-
-@defun char-equal character1 character2
-This function returns @code{t} if the arguments represent the same
-character, @code{nil} otherwise. This function ignores differences
-in case if @code{case-fold-search} is non-@code{nil}.
-
-@example
-(char-equal ?x ?x)
- @result{} t
-(char-to-string (+ 256 ?x))
- @result{} "x"
-(char-equal ?x (+ 256 ?x))
- @result{} t
-@end example
-@end defun
-
-@defun string= string1 string2
-This function returns @code{t} if the characters of the two strings
-match exactly; case is significant.
-
-@example
-(string= "abc" "abc")
- @result{} t
-(string= "abc" "ABC")
- @result{} nil
-(string= "ab" "ABC")
- @result{} nil
-@end example
-
-The function @code{string=} ignores the text properties of the
-two strings. To compare strings in a way that compares their text
-properties also, use @code{equal} (@pxref{Equality Predicates}).
-@end defun
-
-@defun string-equal string1 string2
-@code{string-equal} is another name for @code{string=}.
-@end defun
-
-@cindex lexical comparison
-@defun string< string1 string2
-@c (findex string< causes problems for permuted index!!)
-This function compares two strings a character at a time. First it
-scans both the strings at once to find the first pair of corresponding
-characters that do not match. If the lesser character of those two is
-the character from @var{string1}, then @var{string1} is less, and this
-function returns @code{t}. If the lesser character is the one from
-@var{string2}, then @var{string1} is greater, and this function returns
-@code{nil}. If the two strings match entirely, the value is @code{nil}.
-
-Pairs of characters are compared by their @sc{ASCII} codes. Keep in
-mind that lower case letters have higher numeric values in the
-@sc{ASCII} character set than their upper case counterparts; numbers and
-many punctuation characters have a lower numeric value than upper case
-letters.
-
-@example
-@group
-(string< "abc" "abd")
- @result{} t
-(string< "abd" "abc")
- @result{} nil
-(string< "123" "abc")
- @result{} t
-@end group
-@end example
-
-When the strings have different lengths, and they match up to the
-length of @var{string1}, then the result is @code{t}. If they match up
-to the length of @var{string2}, the result is @code{nil}. A string of
-no characters is less than any other string.
-
-@example
-@group
-(string< "" "abc")
- @result{} t
-(string< "ab" "abc")
- @result{} t
-(string< "abc" "")
- @result{} nil
-(string< "abc" "ab")
- @result{} nil
-(string< "" "")
- @result{} nil
-@end group
-@end example
-@end defun
-
-@defun string-lessp string1 string2
-@code{string-lessp} is another name for @code{string<}.
-@end defun
-
- See also @code{compare-buffer-substrings} in @ref{Comparing Text}, for
-a way to compare text in buffers. The function @code{string-match},
-which matches a regular expression against a string, can be used
-for a kind of string comparison; see @ref{Regexp Search}.
-
-@node String Conversion
-@comment node-name, next, previous, up
-@section Conversion of Characters and Strings
-@cindex conversion of strings
-
- This section describes functions for conversions between characters,
-strings and integers. @code{format} and @code{prin1-to-string}
-(@pxref{Output Functions}) can also convert Lisp objects into strings.
-@code{read-from-string} (@pxref{Input Functions}) can ``convert'' a
-string representation of a Lisp object into an object.
-
- @xref{Documentation}, for functions that produce textual descriptions
-of text characters and general input events
-(@code{single-key-description} and @code{text-char-description}). These
-functions are used primarily for making help messages.
-
-@defun char-to-string character
-@cindex character to string
- This function returns a new string with a length of one character.
-The value of @var{character}, modulo 256, is used to initialize the
-element of the string.
-
-This function is similar to @code{make-string} with an integer argument
-of 1. (@xref{Creating Strings}.) This conversion can also be done with
-@code{format} using the @samp{%c} format specification.
-(@xref{Formatting Strings}.)
-
-@example
-(char-to-string ?x)
- @result{} "x"
-(char-to-string (+ 256 ?x))
- @result{} "x"
-(make-string 1 ?x)
- @result{} "x"
-@end example
-@end defun
-
-@defun string-to-char string
-@cindex string to character
- This function returns the first character in @var{string}. If the
-string is empty, the function returns 0. The value is also 0 when the
-first character of @var{string} is the null character, @sc{ASCII} code
-0.
-
-@example
-(string-to-char "ABC")
- @result{} 65
-(string-to-char "xyz")
- @result{} 120
-(string-to-char "")
- @result{} 0
-(string-to-char "\000")
- @result{} 0
-@end example
-
-This function may be eliminated in the future if it does not seem useful
-enough to retain.
-@end defun
-
-@defun number-to-string number
-@cindex integer to string
-@cindex integer to decimal
-This function returns a string consisting of the printed
-representation of @var{number}, which may be an integer or a floating
-point number. The value starts with a sign if the argument is
-negative.
-
-@example
-(number-to-string 256)
- @result{} "256"
-(number-to-string -23)
- @result{} "-23"
-(number-to-string -23.5)
- @result{} "-23.5"
-@end example
-
-@cindex int-to-string
-@code{int-to-string} is a semi-obsolete alias for this function.
-
-See also the function @code{format} in @ref{Formatting Strings}.
-@end defun
-
-@defun string-to-number string
-@cindex string to number
-This function returns the numeric value of the characters in
-@var{string}, read in base ten. It skips spaces and tabs at the
-beginning of @var{string}, then reads as much of @var{string} as it can
-interpret as a number. (On some systems it ignores other whitespace at
-the beginning, not just spaces and tabs.) If the first character after
-the ignored whitespace is not a digit or a minus sign, this function
-returns 0.
-
-@example
-(string-to-number "256")
- @result{} 256
-(string-to-number "25 is a perfect square.")
- @result{} 25
-(string-to-number "X256")
- @result{} 0
-(string-to-number "-4.5")
- @result{} -4.5
-@end example
-
-@findex string-to-int
-@code{string-to-int} is an obsolete alias for this function.
-@end defun
-
-@node Formatting Strings
-@comment node-name, next, previous, up
-@section Formatting Strings
-@cindex formatting strings
-@cindex strings, formatting them
-
- @dfn{Formatting} means constructing a string by substitution of
-computed values at various places in a constant string. This string
-controls how the other values are printed as well as where they appear;
-it is called a @dfn{format string}.
-
- Formatting is often useful for computing messages to be displayed. In
-fact, the functions @code{message} and @code{error} provide the same
-formatting feature described here; they differ from @code{format} only
-in how they use the result of formatting.
-
-@defun format string &rest objects
- This function returns a new string that is made by copying
-@var{string} and then replacing any format specification
-in the copy with encodings of the corresponding @var{objects}. The
-arguments @var{objects} are the computed values to be formatted.
-@end defun
-
-@cindex @samp{%} in format
-@cindex format specification
- A format specification is a sequence of characters beginning with a
-@samp{%}. Thus, if there is a @samp{%d} in @var{string}, the
-@code{format} function replaces it with the printed representation of
-one of the values to be formatted (one of the arguments @var{objects}).
-For example:
-
-@example
-@group
-(format "The value of fill-column is %d." fill-column)
- @result{} "The value of fill-column is 72."
-@end group
-@end example
-
- If @var{string} contains more than one format specification, the
-format specifications correspond with successive values from
-@var{objects}. Thus, the first format specification in @var{string}
-uses the first such value, the second format specification uses the
-second such value, and so on. Any extra format specifications (those
-for which there are no corresponding values) cause unpredictable
-behavior. Any extra values to be formatted are ignored.
-
- Certain format specifications require values of particular types.
-However, no error is signaled if the value actually supplied fails to
-have the expected type. Instead, the output is likely to be
-meaningless.
-
- Here is a table of valid format specifications:
-
-@table @samp
-@item %s
-Replace the specification with the printed representation of the object,
-made without quoting. Thus, strings are represented by their contents
-alone, with no @samp{"} characters, and symbols appear without @samp{\}
-characters.
-
-If there is no corresponding object, the empty string is used.
-
-@item %S
-Replace the specification with the printed representation of the object,
-made with quoting. Thus, strings are enclosed in @samp{"} characters,
-and @samp{\} characters appear where necessary before special characters.
-
-If there is no corresponding object, the empty string is used.
-
-@item %o
-@cindex integer to octal
-Replace the specification with the base-eight representation of an
-integer.
-
-@item %d
-Replace the specification with the base-ten representation of an
-integer.
-
-@item %x
-@cindex integer to hexadecimal
-Replace the specification with the base-sixteen representation of an
-integer.
-
-@item %c
-Replace the specification with the character which is the value given.
-
-@item %e
-Replace the specification with the exponential notation for a floating
-point number.
-
-@item %f
-Replace the specification with the decimal-point notation for a floating
-point number.
-
-@item %g
-Replace the specification with notation for a floating point number,
-using either exponential notation or decimal-point notation whichever
-is shorter.
-
-@item %%
-A single @samp{%} is placed in the string. This format specification is
-unusual in that it does not use a value. For example, @code{(format "%%
-%d" 30)} returns @code{"% 30"}.
-@end table
-
- Any other format character results in an @samp{Invalid format
-operation} error.
-
- Here are several examples:
-
-@example
-@group
-(format "The name of this buffer is %s." (buffer-name))
- @result{} "The name of this buffer is strings.texi."
-
-(format "The buffer object prints as %s." (current-buffer))
- @result{} "The buffer object prints as strings.texi."
-
-(format "The octal value of %d is %o,
- and the hex value is %x." 18 18 18)
- @result{} "The octal value of 18 is 22,
- and the hex value is 12."
-@end group
-@end example
-
-@cindex numeric prefix
-@cindex field width
-@cindex padding
- All the specification characters allow an optional numeric prefix
-between the @samp{%} and the character. The optional numeric prefix
-defines the minimum width for the object. If the printed representation
-of the object contains fewer characters than this, then it is padded.
-The padding is on the left if the prefix is positive (or starts with
-zero) and on the right if the prefix is negative. The padding character
-is normally a space, but if the numeric prefix starts with a zero, zeros
-are used for padding.
-
-@example
-(format "%06d is padded on the left with zeros" 123)
- @result{} "000123 is padded on the left with zeros"
-
-(format "%-6d is padded on the right" 123)
- @result{} "123 is padded on the right"
-@end example
-
- @code{format} never truncates an object's printed representation, no
-matter what width you specify. Thus, you can use a numeric prefix to
-specify a minimum spacing between columns with no risk of losing
-information.
-
- In the following three examples, @samp{%7s} specifies a minimum width
-of 7. In the first case, the string inserted in place of @samp{%7s} has
-only 3 letters, so 4 blank spaces are inserted for padding. In the
-second case, the string @code{"specification"} is 13 letters wide but is
-not truncated. In the third case, the padding is on the right.
-
-@smallexample
-@group
-(format "The word `%7s' actually has %d letters in it."
- "foo" (length "foo"))
- @result{} "The word ` foo' actually has 3 letters in it."
-@end group
-
-@group
-(format "The word `%7s' actually has %d letters in it."
- "specification" (length "specification"))
- @result{} "The word `specification' actually has 13 letters in it."
-@end group
-
-@group
-(format "The word `%-7s' actually has %d letters in it."
- "foo" (length "foo"))
- @result{} "The word `foo ' actually has 3 letters in it."
-@end group
-@end smallexample
-
-@node Character Case
-@comment node-name, next, previous, up
-@section Character Case
-@cindex upper case
-@cindex lower case
-@cindex character case
-
- The character case functions change the case of single characters or
-of the contents of strings. The functions convert only alphabetic
-characters (the letters @samp{A} through @samp{Z} and @samp{a} through
-@samp{z}); other characters are not altered. The functions do not
-modify the strings that are passed to them as arguments.
-
- The examples below use the characters @samp{X} and @samp{x} which have
-@sc{ASCII} codes 88 and 120 respectively.
-
-@defun downcase string-or-char
-This function converts a character or a string to lower case.
-
-When the argument to @code{downcase} is a string, the function creates
-and returns a new string in which each letter in the argument that is
-upper case is converted to lower case. When the argument to
-@code{downcase} is a character, @code{downcase} returns the
-corresponding lower case character. This value is an integer. If the
-original character is lower case, or is not a letter, then the value
-equals the original character.
-
-@example
-(downcase "The cat in the hat")
- @result{} "the cat in the hat"
-
-(downcase ?X)
- @result{} 120
-@end example
-@end defun
-
-@defun upcase string-or-char
-This function converts a character or a string to upper case.
-
-When the argument to @code{upcase} is a string, the function creates
-and returns a new string in which each letter in the argument that is
-lower case is converted to upper case.
-
-When the argument to @code{upcase} is a character, @code{upcase}
-returns the corresponding upper case character. This value is an integer.
-If the original character is upper case, or is not a letter, then the
-value equals the original character.
-
-@example
-(upcase "The cat in the hat")
- @result{} "THE CAT IN THE HAT"
-
-(upcase ?x)
- @result{} 88
-@end example
-@end defun
-
-@defun capitalize string-or-char
-@cindex capitalization
-This function capitalizes strings or characters. If
-@var{string-or-char} is a string, the function creates and returns a new
-string, whose contents are a copy of @var{string-or-char} in which each
-word has been capitalized. This means that the first character of each
-word is converted to upper case, and the rest are converted to lower
-case.
-
-The definition of a word is any sequence of consecutive characters that
-are assigned to the word constituent syntax class in the current syntax
-table (@xref{Syntax Class Table}).
-
-When the argument to @code{capitalize} is a character, @code{capitalize}
-has the same result as @code{upcase}.
-
-@example
-(capitalize "The cat in the hat")
- @result{} "The Cat In The Hat"
-
-(capitalize "THE 77TH-HATTED CAT")
- @result{} "The 77th-Hatted Cat"
-
-@group
-(capitalize ?x)
- @result{} 88
-@end group
-@end example
-@end defun
-
-@node Case Table
-@section The Case Table
-
- You can customize case conversion by installing a special @dfn{case
-table}. A case table specifies the mapping between upper case and lower
-case letters. It affects both the string and character case conversion
-functions (see the previous section) and those that apply to text in the
-buffer (@pxref{Case Changes}). You need a case table if you are using a
-language which has letters other than the standard @sc{ASCII} letters.
-
- A case table is a list of this form:
-
-@example
-(@var{downcase} @var{upcase} @var{canonicalize} @var{equivalences})
-@end example
-
-@noindent
-where each element is either @code{nil} or a string of length 256. The
-element @var{downcase} says how to map each character to its lower-case
-equivalent. The element @var{upcase} maps each character to its
-upper-case equivalent. If lower and upper case characters are in
-one-to-one correspondence, use @code{nil} for @var{upcase}; then Emacs
-deduces the upcase table from @var{downcase}.
-
- For some languages, upper and lower case letters are not in one-to-one
-correspondence. There may be two different lower case letters with the
-same upper case equivalent. In these cases, you need to specify the
-maps for both directions.
-
- The element @var{canonicalize} maps each character to a canonical
-equivalent; any two characters that are related by case-conversion have
-the same canonical equivalent character.
-
- The element @var{equivalences} is a map that cyclicly permutes each
-equivalence class (of characters with the same canonical equivalent).
-(For ordinary @sc{ASCII}, this would map @samp{a} into @samp{A} and
-@samp{A} into @samp{a}, and likewise for each set of equivalent
-characters.)
-
- When you construct a case table, you can provide @code{nil} for
-@var{canonicalize}; then Emacs fills in this string from @var{upcase}
-and @var{downcase}. You can also provide @code{nil} for
-@var{equivalences}; then Emacs fills in this string from
-@var{canonicalize}. In a case table that is actually in use, those
-components are non-@code{nil}. Do not try to specify @var{equivalences}
-without also specifying @var{canonicalize}.
-
- Each buffer has a case table. Emacs also has a @dfn{standard case
-table} which is copied into each buffer when you create the buffer.
-Changing the standard case table doesn't affect any existing buffers.
-
- Here are the functions for working with case tables:
-
-@defun case-table-p object
-This predicate returns non-@code{nil} if @var{object} is a valid case
-table.
-@end defun
-
-@defun set-standard-case-table table
-This function makes @var{table} the standard case table, so that it will
-apply to any buffers created subsequently.
-@end defun
-
-@defun standard-case-table
-This returns the standard case table.
-@end defun
-
-@defun current-case-table
-This function returns the current buffer's case table.
-@end defun
-
-@defun set-case-table table
-This sets the current buffer's case table to @var{table}.
-@end defun
-
- The following three functions are convenient subroutines for packages
-that define non-@sc{ASCII} character sets. They modify a string
-@var{downcase-table} provided as an argument; this should be a string to
-be used as the @var{downcase} part of a case table. They also modify
-the standard syntax table. @xref{Syntax Tables}.
-
-@defun set-case-syntax-pair uc lc downcase-table
-This function specifies a pair of corresponding letters, one upper case
-and one lower case.
-@end defun
-
-@defun set-case-syntax-delims l r downcase-table
-This function makes characters @var{l} and @var{r} a matching pair of
-case-invariant delimiters.
-@end defun
-
-@defun set-case-syntax char syntax downcase-table
-This function makes @var{char} case-invariant, with syntax
-@var{syntax}.
-@end defun
-
-@deffn Command describe-buffer-case-table
-This command displays a description of the contents of the current
-buffer's case table.
-@end deffn
-
-@cindex ISO Latin 1
-@pindex iso-syntax
-You can load the library @file{iso-syntax} to set up the standard syntax
-table and define a case table for the 8-bit ISO Latin 1 character set.
diff --git a/lispref/symbols.texi b/lispref/symbols.texi
deleted file mode 100644
index 9c20df9c4ae..00000000000
--- a/lispref/symbols.texi
+++ /dev/null
@@ -1,528 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/symbols
-@node Symbols, Evaluation, Sequences Arrays Vectors, Top
-@chapter Symbols
-@cindex symbol
-
- A @dfn{symbol} is an object with a unique name. This chapter
-describes symbols, their components, their property lists, and how they
-are created and interned. Separate chapters describe the use of symbols
-as variables and as function names; see @ref{Variables}, and
-@ref{Functions}. For the precise read syntax for symbols, see
-@ref{Symbol Type}.
-
- You can test whether an arbitrary Lisp object is a symbol
-with @code{symbolp}:
-
-@defun symbolp object
-This function returns @code{t} if @var{object} is a symbol, @code{nil}
-otherwise.
-@end defun
-
-@menu
-* Symbol Components:: Symbols have names, values, function definitions
- and property lists.
-* Definitions:: A definition says how a symbol will be used.
-* Creating Symbols:: How symbols are kept unique.
-* Property Lists:: Each symbol has a property list
- for recording miscellaneous information.
-@end menu
-
-@node Symbol Components, Definitions, Symbols, Symbols
-@section Symbol Components
-@cindex symbol components
-
- Each symbol has four components (or ``cells''), each of which
-references another object:
-
-@table @asis
-@item Print name
-@cindex print name cell
-The @dfn{print name cell} holds a string that names the symbol for
-reading and printing. See @code{symbol-name} in @ref{Creating Symbols}.
-
-@item Value
-@cindex value cell
-The @dfn{value cell} holds the current value of the symbol as a
-variable. When a symbol is used as a form, the value of the form is the
-contents of the symbol's value cell. See @code{symbol-value} in
-@ref{Accessing Variables}.
-
-@item Function
-@cindex function cell
-The @dfn{function cell} holds the function definition of the symbol.
-When a symbol is used as a function, its function definition is used in
-its place. This cell is also used to make a symbol stand for a keymap
-or a keyboard macro, for editor command execution. Because each symbol
-has separate value and function cells, variables and function names do
-not conflict. See @code{symbol-function} in @ref{Function Cells}.
-
-@item Property list
-@cindex property list cell
-The @dfn{property list cell} holds the property list of the symbol. See
-@code{symbol-plist} in @ref{Property Lists}.
-@end table
-
- The print name cell always holds a string, and cannot be changed. The
-other three cells can be set individually to any specified Lisp object.
-
- The print name cell holds the string that is the name of the symbol.
-Since symbols are represented textually by their names, it is important
-not to have two symbols with the same name. The Lisp reader ensures
-this: every time it reads a symbol, it looks for an existing symbol with
-the specified name before it creates a new one. (In GNU Emacs Lisp,
-this lookup uses a hashing algorithm and an obarray; see @ref{Creating
-Symbols}.)
-
- In normal usage, the function cell usually contains a function or
-macro, as that is what the Lisp interpreter expects to see there
-(@pxref{Evaluation}). Keyboard macros (@pxref{Keyboard Macros}),
-keymaps (@pxref{Keymaps}) and autoload objects (@pxref{Autoloading}) are
-also sometimes stored in the function cell of symbols. We often refer
-to ``the function @code{foo}'' when we really mean the function stored
-in the function cell of the symbol @code{foo}. We make the distinction
-only when necessary.
-
- The property list cell normally should hold a correctly formatted
-property list (@pxref{Property Lists}), as a number of functions expect
-to see a property list there.
-
- The function cell or the value cell may be @dfn{void}, which means
-that the cell does not reference any object. (This is not the same
-thing as holding the symbol @code{void}, nor the same as holding the
-symbol @code{nil}.) Examining a cell that is void results in an error,
-such as @samp{Symbol's value as variable is void}.
-
- The four functions @code{symbol-name}, @code{symbol-value},
-@code{symbol-plist}, and @code{symbol-function} return the contents of
-the four cells of a symbol. Here as an example we show the contents of
-the four cells of the symbol @code{buffer-file-name}:
-
-@example
-(symbol-name 'buffer-file-name)
- @result{} "buffer-file-name"
-(symbol-value 'buffer-file-name)
- @result{} "/gnu/elisp/symbols.texi"
-(symbol-plist 'buffer-file-name)
- @result{} (variable-documentation 29529)
-(symbol-function 'buffer-file-name)
- @result{} #<subr buffer-file-name>
-@end example
-
-@noindent
-Because this symbol is the variable which holds the name of the file
-being visited in the current buffer, the value cell contents we see are
-the name of the source file of this chapter of the Emacs Lisp Manual.
-The property list cell contains the list @code{(variable-documentation
-29529)} which tells the documentation functions where to find the
-documentation string for the variable @code{buffer-file-name} in the
-@file{DOC} file. (29529 is the offset from the beginning of the
-@file{DOC} file to where that documentation string begins.) The
-function cell contains the function for returning the name of the file.
-@code{buffer-file-name} names a primitive function, which has no read
-syntax and prints in hash notation (@pxref{Primitive Function Type}). A
-symbol naming a function written in Lisp would have a lambda expression
-(or a byte-code object) in this cell.
-
-@node Definitions, Creating Symbols, Symbol Components, Symbols
-@section Defining Symbols
-@cindex definition of a symbol
-
- A @dfn{definition} in Lisp is a special form that announces your
-intention to use a certain symbol in a particular way. In Emacs Lisp,
-you can define a symbol as a variable, or define it as a function (or
-macro), or both independently.
-
- A definition construct typically specifies a value or meaning for the
-symbol for one kind of use, plus documentation for its meaning when used
-in this way. Thus, when you define a symbol as a variable, you can
-supply an initial value for the variable, plus documentation for the
-variable.
-
- @code{defvar} and @code{defconst} are special forms that define a
-symbol as a global variable. They are documented in detail in
-@ref{Defining Variables}.
-
- @code{defun} defines a symbol as a function, creating a lambda
-expression and storing it in the function cell of the symbol. This
-lambda expression thus becomes the function definition of the symbol.
-(The term ``function definition'', meaning the contents of the function
-cell, is derived from the idea that @code{defun} gives the symbol its
-definition as a function.) @code{defsubst} and @code{defalias} are two
-other ways of defining a function. @xref{Functions}.
-
- @code{defmacro} defines a symbol as a macro. It creates a macro
-object and stores it in the function cell of the symbol. Note that a
-given symbol can be a macro or a function, but not both at once, because
-both macro and function definitions are kept in the function cell, and
-that cell can hold only one Lisp object at any given time.
-@xref{Macros}.
-
- In Emacs Lisp, a definition is not required in order to use a symbol
-as a variable or function. Thus, you can make a symbol a global
-variable with @code{setq}, whether you define it first or not. The real
-purpose of definitions is to guide programmers and programming tools.
-They inform programmers who read the code that certain symbols are
-@emph{intended} to be used as variables, or as functions. In addition,
-utilities such as @file{etags} and @file{make-docfile} recognize
-definitions, and add appropriate information to tag tables and the
-@file{emacs/etc/DOC-@var{version}} file. @xref{Accessing Documentation}.
-
-@node Creating Symbols, Property Lists, Definitions, Symbols
-@section Creating and Interning Symbols
-@cindex reading symbols
-
- To understand how symbols are created in GNU Emacs Lisp, you must know
-how Lisp reads them. Lisp must ensure that it finds the same symbol
-every time it reads the same set of characters. Failure to do so would
-cause complete confusion.
-
-@cindex symbol name hashing
-@cindex hashing
-@cindex obarray
-@cindex bucket (in obarray)
- When the Lisp reader encounters a symbol, it reads all the characters
-of the name. Then it ``hashes'' those characters to find an index in a
-table called an @dfn{obarray}. Hashing is an efficient method of
-looking something up. For example, instead of searching a telephone
-book cover to cover when looking up Jan Jones, you start with the J's
-and go from there. That is a simple version of hashing. Each element
-of the obarray is a @dfn{bucket} which holds all the symbols with a
-given hash code; to look for a given name, it is sufficient to look
-through all the symbols in the bucket for that name's hash code.
-
-@cindex interning
- If a symbol with the desired name is found, the reader uses that
-symbol. If the obarray does not contain a symbol with that name, the
-reader makes a new symbol and adds it to the obarray. Finding or adding
-a symbol with a certain name is called @dfn{interning} it, and the
-symbol is then called an @dfn{interned symbol}.
-
- Interning ensures that each obarray has just one symbol with any
-particular name. Other like-named symbols may exist, but not in the
-same obarray. Thus, the reader gets the same symbols for the same
-names, as long as you keep reading with the same obarray.
-
-@cindex symbol equality
-@cindex uninterned symbol
- No obarray contains all symbols; in fact, some symbols are not in any
-obarray. They are called @dfn{uninterned symbols}. An uninterned
-symbol has the same four cells as other symbols; however, the only way
-to gain access to it is by finding it in some other object or as the
-value of a variable.
-
- In Emacs Lisp, an obarray is actually a vector. Each element of the
-vector is a bucket; its value is either an interned symbol whose name
-hashes to that bucket, or 0 if the bucket is empty. Each interned
-symbol has an internal link (invisible to the user) to the next symbol
-in the bucket. Because these links are invisible, there is no way to
-find all the symbols in an obarray except using @code{mapatoms} (below).
-The order of symbols in a bucket is not significant.
-
- In an empty obarray, every element is 0, and you can create an obarray
-with @code{(make-vector @var{length} 0)}. @strong{This is the only
-valid way to create an obarray.} Prime numbers as lengths tend
-to result in good hashing; lengths one less than a power of two are also
-good.
-
- @strong{Do not try to put symbols in an obarray yourself.} This does
-not work---only @code{intern} can enter a symbol in an obarray properly.
-@strong{Do not try to intern one symbol in two obarrays.} This would
-garble both obarrays, because a symbol has just one slot to hold the
-following symbol in the obarray bucket. The results would be
-unpredictable.
-
- It is possible for two different symbols to have the same name in
-different obarrays; these symbols are not @code{eq} or @code{equal}.
-However, this normally happens only as part of the abbrev mechanism
-(@pxref{Abbrevs}).
-
-@cindex CL note---symbol in obarrays
-@quotation
-@b{Common Lisp note:} In Common Lisp, a single symbol may be interned in
-several obarrays.
-@end quotation
-
- Most of the functions below take a name and sometimes an obarray as
-arguments. A @code{wrong-type-argument} error is signaled if the name
-is not a string, or if the obarray is not a vector.
-
-@defun symbol-name symbol
-This function returns the string that is @var{symbol}'s name. For example:
-
-@example
-@group
-(symbol-name 'foo)
- @result{} "foo"
-@end group
-@end example
-
-Changing the string by substituting characters, etc, does change the
-name of the symbol, but fails to update the obarray, so don't do it!
-@end defun
-
-@defun make-symbol name
-This function returns a newly-allocated, uninterned symbol whose name is
-@var{name} (which must be a string). Its value and function definition
-are void, and its property list is @code{nil}. In the example below,
-the value of @code{sym} is not @code{eq} to @code{foo} because it is a
-distinct uninterned symbol whose name is also @samp{foo}.
-
-@example
-(setq sym (make-symbol "foo"))
- @result{} foo
-(eq sym 'foo)
- @result{} nil
-@end example
-@end defun
-
-@defun intern name &optional obarray
-This function returns the interned symbol whose name is @var{name}. If
-there is no such symbol in the obarray @var{obarray}, @code{intern}
-creates a new one, adds it to the obarray, and returns it. If
-@var{obarray} is omitted, the value of the global variable
-@code{obarray} is used.
-
-@example
-(setq sym (intern "foo"))
- @result{} foo
-(eq sym 'foo)
- @result{} t
-
-(setq sym1 (intern "foo" other-obarray))
- @result{} foo
-(eq sym 'foo)
- @result{} nil
-@end example
-@end defun
-
-@defun intern-soft name &optional obarray
-This function returns the symbol in @var{obarray} whose name is
-@var{name}, or @code{nil} if @var{obarray} has no symbol with that name.
-Therefore, you can use @code{intern-soft} to test whether a symbol with
-a given name is already interned. If @var{obarray} is omitted, the
-value of the global variable @code{obarray} is used.
-
-@smallexample
-(intern-soft "frazzle") ; @r{No such symbol exists.}
- @result{} nil
-(make-symbol "frazzle") ; @r{Create an uninterned one.}
- @result{} frazzle
-@group
-(intern-soft "frazzle") ; @r{That one cannot be found.}
- @result{} nil
-@end group
-@group
-(setq sym (intern "frazzle")) ; @r{Create an interned one.}
- @result{} frazzle
-@end group
-@group
-(intern-soft "frazzle") ; @r{That one can be found!}
- @result{} frazzle
-@end group
-@group
-(eq sym 'frazzle) ; @r{And it is the same one.}
- @result{} t
-@end group
-@end smallexample
-@end defun
-
-@defvar obarray
-This variable is the standard obarray for use by @code{intern} and
-@code{read}.
-@end defvar
-
-@defun mapatoms function &optional obarray
-This function calls @var{function} for each symbol in the obarray
-@var{obarray}. It returns @code{nil}. If @var{obarray} is omitted, it
-defaults to the value of @code{obarray}, the standard obarray for
-ordinary symbols.
-
-@smallexample
-(setq count 0)
- @result{} 0
-(defun count-syms (s)
- (setq count (1+ count)))
- @result{} count-syms
-(mapatoms 'count-syms)
- @result{} nil
-count
- @result{} 1871
-@end smallexample
-
-See @code{documentation} in @ref{Accessing Documentation}, for another
-example using @code{mapatoms}.
-@end defun
-
-@defun unintern symbol &optional obarray
-This function deletes @var{symbol} from the obarray @var{obarray}. If
-@code{symbol} is not actually in the obarray, @code{unintern} does
-nothing. If @var{obarray} is @code{nil}, the current obarray is used.
-
-If you provide a string instead of a symbol as @var{symbol}, it stands
-for a symbol name. Then @code{unintern} deletes the symbol (if any) in
-the obarray which has that name. If there is no such symbol,
-@code{unintern} does nothing.
-
-If @code{unintern} does delete a symbol, it returns @code{t}. Otherwise
-it returns @code{nil}.
-@end defun
-
-@node Property Lists,, Creating Symbols, Symbols
-@section Property Lists
-@cindex property list
-@cindex plist
-
- A @dfn{property list} (@dfn{plist} for short) is a list of paired
-elements stored in the property list cell of a symbol. Each of the
-pairs associates a property name (usually a symbol) with a property or
-value. Property lists are generally used to record information about a
-symbol, such as its documentation as a variable, the name of the file
-where it was defined, or perhaps even the grammatical class of the
-symbol (representing a word) in a language-understanding system.
-
- Character positions in a string or buffer can also have property lists.
-@xref{Text Properties}.
-
- The property names and values in a property list can be any Lisp
-objects, but the names are usually symbols. They are compared using
-@code{eq}. Here is an example of a property list, found on the symbol
-@code{progn} when the compiler is loaded:
-
-@example
-(lisp-indent-function 0 byte-compile byte-compile-progn)
-@end example
-
-@noindent
-Here @code{lisp-indent-function} and @code{byte-compile} are property
-names, and the other two elements are the corresponding values.
-
-@menu
-* Plists and Alists:: Comparison of the advantages of property
- lists and association lists.
-* Symbol Plists:: Functions to access symbols' property lists.
-* Other Plists:: Accessing property lists stored elsewhere.
-@end menu
-
-@node Plists and Alists
-@subsection Property Lists and Association Lists
-
-@cindex property lists vs association lists
- Association lists (@pxref{Association Lists}) are very similar to
-property lists. In contrast to association lists, the order of the
-pairs in the property list is not significant since the property names
-must be distinct.
-
- Property lists are better than association lists for attaching
-information to various Lisp function names or variables. If all the
-associations are recorded in one association list, the program will need
-to search that entire list each time a function or variable is to be
-operated on. By contrast, if the information is recorded in the
-property lists of the function names or variables themselves, each
-search will scan only the length of one property list, which is usually
-short. This is why the documentation for a variable is recorded in a
-property named @code{variable-documentation}. The byte compiler
-likewise uses properties to record those functions needing special
-treatment.
-
- However, association lists have their own advantages. Depending on
-your application, it may be faster to add an association to the front of
-an association list than to update a property. All properties for a
-symbol are stored in the same property list, so there is a possibility
-of a conflict between different uses of a property name. (For this
-reason, it is a good idea to choose property names that are probably
-unique, such as by including the name of the library in the property
-name.) An association list may be used like a stack where associations
-are pushed on the front of the list and later discarded; this is not
-possible with a property list.
-
-@node Symbol Plists
-@subsection Property List Functions for Symbols
-
-@defun symbol-plist symbol
-This function returns the property list of @var{symbol}.
-@end defun
-
-@defun setplist symbol plist
-This function sets @var{symbol}'s property list to @var{plist}.
-Normally, @var{plist} should be a well-formed property list, but this is
-not enforced.
-
-@smallexample
-(setplist 'foo '(a 1 b (2 3) c nil))
- @result{} (a 1 b (2 3) c nil)
-(symbol-plist 'foo)
- @result{} (a 1 b (2 3) c nil)
-@end smallexample
-
-For symbols in special obarrays, which are not used for ordinary
-purposes, it may make sense to use the property list cell in a
-nonstandard fashion; in fact, the abbrev mechanism does so
-(@pxref{Abbrevs}).
-@end defun
-
-@defun get symbol property
-This function finds the value of the property named @var{property} in
-@var{symbol}'s property list. If there is no such property, @code{nil}
-is returned. Thus, there is no distinction between a value of
-@code{nil} and the absence of the property.
-
-The name @var{property} is compared with the existing property names
-using @code{eq}, so any object is a legitimate property.
-
-See @code{put} for an example.
-@end defun
-
-@defun put symbol property value
-This function puts @var{value} onto @var{symbol}'s property list under
-the property name @var{property}, replacing any previous property value.
-The @code{put} function returns @var{value}.
-
-@smallexample
-(put 'fly 'verb 'transitive)
- @result{}'transitive
-(put 'fly 'noun '(a buzzing little bug))
- @result{} (a buzzing little bug)
-(get 'fly 'verb)
- @result{} transitive
-(symbol-plist 'fly)
- @result{} (verb transitive noun (a buzzing little bug))
-@end smallexample
-@end defun
-
-@node Other Plists
-@subsection Property Lists Outside Symbols
-
- These two functions are useful for manipulating property lists
-that are stored in places other than symbols:
-
-@defun plist-get plist property
-This returns the value of the @var{property} property
-stored in the property list @var{plist}. For example,
-
-@example
-(plist-get '(foo 4) 'foo)
- @result{} 4
-@end example
-@end defun
-
-@defun plist-put plist property value
-This stores @var{value} as the value of the @var{property} property in
-the property list @var{plist}. It may modify @var{plist} destructively,
-or it may construct a new list structure without altering the old. The
-function returns the modified property list, so you can store that back
-in the place where you got @var{plist}. For example,
-
-@example
-(setq my-plist '(bar t foo 4))
- @result{} (bar t foo 4)
-(setq my-plist (plist-put my-plist 'foo 69))
- @result{} (bar t foo 69)
-(setq my-plist (plist-put my-plist 'quux '(a)))
- @result{} (quux (a) bar t foo 5)
-@end example
-@end defun
-
diff --git a/lispref/syntax.texi b/lispref/syntax.texi
deleted file mode 100644
index 585df47580a..00000000000
--- a/lispref/syntax.texi
+++ /dev/null
@@ -1,723 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/syntax
-@node Syntax Tables, Abbrevs, Searching and Matching, Top
-@chapter Syntax Tables
-@cindex parsing
-@cindex syntax table
-@cindex text parsing
-
- A @dfn{syntax table} specifies the syntactic textual function of each
-character. This information is used by the parsing commands, the
-complex movement commands, and others to determine where words, symbols,
-and other syntactic constructs begin and end. The current syntax table
-controls the meaning of the word motion functions (@pxref{Word Motion})
-and the list motion functions (@pxref{List Motion}) as well as the
-functions in this chapter.
-
-@menu
-* Basics: Syntax Basics. Basic concepts of syntax tables.
-* Desc: Syntax Descriptors. How characters are classified.
-* Syntax Table Functions:: How to create, examine and alter syntax tables.
-* Motion and Syntax:: Moving over characters with certain syntaxes.
-* Parsing Expressions:: Parsing balanced expressions
- using the syntax table.
-* Standard Syntax Tables:: Syntax tables used by various major modes.
-* Syntax Table Internals:: How syntax table information is stored.
-@end menu
-
-@node Syntax Basics
-@section Syntax Table Concepts
-
-@ifinfo
- A @dfn{syntax table} provides Emacs with the information that
-determines the syntactic use of each character in a buffer. This
-information is used by the parsing commands, the complex movement
-commands, and others to determine where words, symbols, and other
-syntactic constructs begin and end. The current syntax table controls
-the meaning of the word motion functions (@pxref{Word Motion}) and the
-list motion functions (@pxref{List Motion}) as well as the functions in
-this chapter.
-@end ifinfo
-
- A syntax table is a vector of 256 elements; it contains one entry for
-each of the 256 possible characters in an 8-bit byte. Each element is
-an integer that encodes the syntax of the character in question.
-
- Syntax tables are used only for moving across text, not for the Emacs
-Lisp reader. Emacs Lisp uses built-in syntactic rules when reading Lisp
-expressions, and these rules cannot be changed.
-
- Each buffer has its own major mode, and each major mode has its own
-idea of the syntactic class of various characters. For example, in Lisp
-mode, the character @samp{;} begins a comment, but in C mode, it
-terminates a statement. To support these variations, Emacs makes the
-choice of syntax table local to each buffer. Typically, each major
-mode has its own syntax table and installs that table in each buffer
-that uses that mode. Changing this table alters the syntax in all
-those buffers as well as in any buffers subsequently put in that mode.
-Occasionally several similar modes share one syntax table.
-@xref{Example Major Modes}, for an example of how to set up a syntax
-table.
-
-A syntax table can inherit the data for some characters from the
-standard syntax table, while specifying other characters itself. The
-``inherit'' syntax class means ``inherit this character's syntax from
-the standard syntax table.'' Most major modes' syntax tables inherit
-the syntax of character codes 0 through 31 and 128 through 255. This is
-useful with character sets such as ISO Latin-1 that have additional
-alphabetic characters in the range 128 to 255. Just changing the
-standard syntax for these characters affects all major modes.
-
-@defun syntax-table-p object
-This function returns @code{t} if @var{object} is a vector of length 256
-elements. This means that the vector may be a syntax table. However,
-according to this test, any vector of length 256 is considered to be a
-syntax table, no matter what its contents.
-@end defun
-
-@node Syntax Descriptors
-@section Syntax Descriptors
-@cindex syntax classes
-
- This section describes the syntax classes and flags that denote the
-syntax of a character, and how they are represented as a @dfn{syntax
-descriptor}, which is a Lisp string that you pass to
-@code{modify-syntax-entry} to specify the desired syntax.
-
- Emacs defines a number of @dfn{syntax classes}. Each syntax table
-puts each character into one class. There is no necessary relationship
-between the class of a character in one syntax table and its class in
-any other table.
-
- Each class is designated by a mnemonic character, which serves as the
-name of the class when you need to specify a class. Usually the
-designator character is one that is frequently in that class; however,
-its meaning as a designator is unvarying and independent of what syntax
-that character currently has.
-
-@cindex syntax descriptor
- A syntax descriptor is a Lisp string that specifies a syntax class, a
-matching character (used only for the parenthesis classes) and flags.
-The first character is the designator for a syntax class. The second
-character is the character to match; if it is unused, put a space there.
-Then come the characters for any desired flags. If no matching
-character or flags are needed, one character is sufficient.
-
- For example, the descriptor for the character @samp{*} in C mode is
-@samp{@w{. 23}} (i.e., punctuation, matching character slot unused,
-second character of a comment-starter, first character of an
-comment-ender), and the entry for @samp{/} is @samp{@w{. 14}} (i.e.,
-punctuation, matching character slot unused, first character of a
-comment-starter, second character of a comment-ender).
-
-@menu
-* Syntax Class Table:: Table of syntax classes.
-* Syntax Flags:: Additional flags each character can have.
-@end menu
-
-@node Syntax Class Table
-@subsection Table of Syntax Classes
-
- Here is a table of syntax classes, the characters that stand for them,
-their meanings, and examples of their use.
-
-@deffn {Syntax class} @w{whitespace character}
-@dfn{Whitespace characters} (designated with @w{@samp{@ }} or @samp{-})
-separate symbols and words from each other. Typically, whitespace
-characters have no other syntactic significance, and multiple whitespace
-characters are syntactically equivalent to a single one. Space, tab,
-newline and formfeed are almost always classified as whitespace.
-@end deffn
-
-@deffn {Syntax class} @w{word constituent}
-@dfn{Word constituents} (designated with @samp{w}) are parts of normal
-English words and are typically used in variable and command names in
-programs. All upper- and lower-case letters, and the digits, are typically
-word constituents.
-@end deffn
-
-@deffn {Syntax class} @w{symbol constituent}
-@dfn{Symbol constituents} (designated with @samp{_}) are the extra
-characters that are used in variable and command names along with word
-constituents. For example, the symbol constituents class is used in
-Lisp mode to indicate that certain characters may be part of symbol
-names even though they are not part of English words. These characters
-are @samp{$&*+-_<>}. In standard C, the only non-word-constituent
-character that is valid in symbols is underscore (@samp{_}).
-@end deffn
-
-@deffn {Syntax class} @w{punctuation character}
-@dfn{Punctuation characters} (@samp{.}) are those characters that are
-used as punctuation in English, or are used in some way in a programming
-language to separate symbols from one another. Most programming
-language modes, including Emacs Lisp mode, have no characters in this
-class since the few characters that are not symbol or word constituents
-all have other uses.
-@end deffn
-
-@deffn {Syntax class} @w{open parenthesis character}
-@deffnx {Syntax class} @w{close parenthesis character}
-@cindex parenthesis syntax
-Open and close @dfn{parenthesis characters} are characters used in
-dissimilar pairs to surround sentences or expressions. Such a grouping
-is begun with an open parenthesis character and terminated with a close.
-Each open parenthesis character matches a particular close parenthesis
-character, and vice versa. Normally, Emacs indicates momentarily the
-matching open parenthesis when you insert a close parenthesis.
-@xref{Blinking}.
-
-The class of open parentheses is designated with @samp{(}, and that of
-close parentheses with @samp{)}.
-
-In English text, and in C code, the parenthesis pairs are @samp{()},
-@samp{[]}, and @samp{@{@}}. In Emacs Lisp, the delimiters for lists and
-vectors (@samp{()} and @samp{[]}) are classified as parenthesis
-characters.
-@end deffn
-
-@deffn {Syntax class} @w{string quote}
-@dfn{String quote characters} (designated with @samp{"}) are used in
-many languages, including Lisp and C, to delimit string constants. The
-same string quote character appears at the beginning and the end of a
-string. Such quoted strings do not nest.
-
-The parsing facilities of Emacs consider a string as a single token.
-The usual syntactic meanings of the characters in the string are
-suppressed.
-
-The Lisp modes have two string quote characters: double-quote (@samp{"})
-and vertical bar (@samp{|}). @samp{|} is not used in Emacs Lisp, but it
-is used in Common Lisp. C also has two string quote characters:
-double-quote for strings, and single-quote (@samp{'}) for character
-constants.
-
-English text has no string quote characters because English is not a
-programming language. Although quotation marks are used in English,
-we do not want them to turn off the usual syntactic properties of
-other characters in the quotation.
-@end deffn
-
-@deffn {Syntax class} @w{escape}
-An @dfn{escape character} (designated with @samp{\}) starts an escape
-sequence such as is used in C string and character constants. The
-character @samp{\} belongs to this class in both C and Lisp. (In C, it
-is used thus only inside strings, but it turns out to cause no trouble
-to treat it this way throughout C code.)
-
-Characters in this class count as part of words if
-@code{words-include-escapes} is non-@code{nil}. @xref{Word Motion}.
-@end deffn
-
-@deffn {Syntax class} @w{character quote}
-A @dfn{character quote character} (designated with @samp{/}) quotes the
-following character so that it loses its normal syntactic meaning. This
-differs from an escape character in that only the character immediately
-following is ever affected.
-
-Characters in this class count as part of words if
-@code{words-include-escapes} is non-@code{nil}. @xref{Word Motion}.
-
-This class is used for backslash in @TeX{} mode.
-@end deffn
-
-@deffn {Syntax class} @w{paired delimiter}
-@dfn{Paired delimiter characters} (designated with @samp{$}) are like
-string quote characters except that the syntactic properties of the
-characters between the delimiters are not suppressed. Only @TeX{} mode
-uses a paired delimiter presently---the @samp{$} that both enters and
-leaves math mode.
-@end deffn
-
-@deffn {Syntax class} @w{expression prefix}
-An @dfn{expression prefix operator} (designated with @samp{'}) is used
-for syntactic operators that are part of an expression if they appear
-next to one. These characters in Lisp include the apostrophe, @samp{'}
-(used for quoting), the comma, @samp{,} (used in macros), and @samp{#}
-(used in the read syntax for certain data types).
-@end deffn
-
-@deffn {Syntax class} @w{comment starter}
-@deffnx {Syntax class} @w{comment ender}
-@cindex comment syntax
-The @dfn{comment starter} and @dfn{comment ender} characters are used in
-various languages to delimit comments. These classes are designated
-with @samp{<} and @samp{>}, respectively.
-
-English text has no comment characters. In Lisp, the semicolon
-(@samp{;}) starts a comment and a newline or formfeed ends one.
-@end deffn
-
-@deffn {Syntax class} @w{inherit}
-This syntax class does not specify a syntax. It says to look in the
-standard syntax table to find the syntax of this character. The
-designator for this syntax code is @samp{@@}.
-@end deffn
-
-@node Syntax Flags
-@subsection Syntax Flags
-@cindex syntax flags
-
- In addition to the classes, entries for characters in a syntax table
-can include flags. There are six possible flags, represented by the
-characters @samp{1}, @samp{2}, @samp{3}, @samp{4}, @samp{b} and
-@samp{p}.
-
- All the flags except @samp{p} are used to describe multi-character
-comment delimiters. The digit flags indicate that a character can
-@emph{also} be part of a comment sequence, in addition to the syntactic
-properties associated with its character class. The flags are
-independent of the class and each other for the sake of characters such
-as @samp{*} in C mode, which is a punctuation character, @emph{and} the
-second character of a start-of-comment sequence (@samp{/*}), @emph{and}
-the first character of an end-of-comment sequence (@samp{*/}).
-
-The flags for a character @var{c} are:
-
-@itemize @bullet
-@item
-@samp{1} means @var{c} is the start of a two-character comment-start
-sequence.
-
-@item
-@samp{2} means @var{c} is the second character of such a sequence.
-
-@item
-@samp{3} means @var{c} is the start of a two-character comment-end
-sequence.
-
-@item
-@samp{4} means @var{c} is the second character of such a sequence.
-
-@item
-@c Emacs 19 feature
-@samp{b} means that @var{c} as a comment delimiter belongs to the
-alternative ``b'' comment style.
-
-Emacs supports two comment styles simultaneously in any one syntax
-table. This is for the sake of C++. Each style of comment syntax has
-its own comment-start sequence and its own comment-end sequence. Each
-comment must stick to one style or the other; thus, if it starts with
-the comment-start sequence of style ``b'', it must also end with the
-comment-end sequence of style ``b''.
-
-The two comment-start sequences must begin with the same character; only
-the second character may differ. Mark the second character of the
-``b''-style comment-start sequence with the @samp{b} flag.
-
-A comment-end sequence (one or two characters) applies to the ``b''
-style if its first character has the @samp{b} flag set; otherwise, it
-applies to the ``a'' style.
-
-The appropriate comment syntax settings for C++ are as follows:
-
-@table @asis
-@item @samp{/}
-@samp{124b}
-@item @samp{*}
-@samp{23}
-@item newline
-@samp{>b}
-@end table
-
-This defines four comment-delimiting sequences:
-
-@table @asis
-@item @samp{/*}
-This is a comment-start sequence for ``a'' style because the
-second character, @samp{*}, does not have the @samp{b} flag.
-
-@item @samp{//}
-This is a comment-start sequence for ``b'' style because the second
-character, @samp{/}, does have the @samp{b} flag.
-
-@item @samp{*/}
-This is a comment-end sequence for ``a'' style because the first
-character, @samp{*}, does not have the @samp{b} flag
-
-@item newline
-This is a comment-end sequence for ``b'' style, because the newline
-character has the @samp{b} flag.
-@end table
-
-@item
-@c Emacs 19 feature
-@samp{p} identifies an additional ``prefix character'' for Lisp syntax.
-These characters are treated as whitespace when they appear between
-expressions. When they appear within an expression, they are handled
-according to their usual syntax codes.
-
-The function @code{backward-prefix-chars} moves back over these
-characters, as well as over characters whose primary syntax class is
-prefix (@samp{'}). @xref{Motion and Syntax}.
-@end itemize
-
-@node Syntax Table Functions
-@section Syntax Table Functions
-
- In this section we describe functions for creating, accessing and
-altering syntax tables.
-
-@defun make-syntax-table
-This function creates a new syntax table. Character codes 0 through
-31 and 128 through 255 are set up to inherit from the standard syntax
-table. The other character codes are set up by copying what the
-standard syntax table says about them.
-
-Most major mode syntax tables are created in this way.
-@end defun
-
-@defun copy-syntax-table &optional table
-This function constructs a copy of @var{table} and returns it. If
-@var{table} is not supplied (or is @code{nil}), it returns a copy of the
-current syntax table. Otherwise, an error is signaled if @var{table} is
-not a syntax table.
-@end defun
-
-@deffn Command modify-syntax-entry char syntax-descriptor &optional table
-This function sets the syntax entry for @var{char} according to
-@var{syntax-descriptor}. The syntax is changed only for @var{table},
-which defaults to the current buffer's syntax table, and not in any
-other syntax table. The argument @var{syntax-descriptor} specifies the
-desired syntax; this is a string beginning with a class designator
-character, and optionally containing a matching character and flags as
-well. @xref{Syntax Descriptors}.
-
-This function always returns @code{nil}. The old syntax information in
-the table for this character is discarded.
-
-An error is signaled if the first character of the syntax descriptor is not
-one of the twelve syntax class designator characters. An error is also
-signaled if @var{char} is not a character.
-
-@example
-@group
-@exdent @r{Examples:}
-
-;; @r{Put the space character in class whitespace.}
-(modify-syntax-entry ?\ " ")
- @result{} nil
-@end group
-
-@group
-;; @r{Make @samp{$} an open parenthesis character,}
-;; @r{with @samp{^} as its matching close.}
-(modify-syntax-entry ?$ "(^")
- @result{} nil
-@end group
-
-@group
-;; @r{Make @samp{^} a close parenthesis character,}
-;; @r{with @samp{$} as its matching open.}
-(modify-syntax-entry ?^ ")$")
- @result{} nil
-@end group
-
-@group
-;; @r{Make @samp{/} a punctuation character,}
-;; @r{the first character of a start-comment sequence,}
-;; @r{and the second character of an end-comment sequence.}
-;; @r{This is used in C mode.}
-(modify-syntax-entry ?/ ". 14")
- @result{} nil
-@end group
-@end example
-@end deffn
-
-@defun char-syntax character
-This function returns the syntax class of @var{character}, represented
-by its mnemonic designator character. This @emph{only} returns the
-class, not any matching parenthesis or flags.
-
-An error is signaled if @var{char} is not a character.
-
-The following examples apply to C mode. The first example shows that
-the syntax class of space is whitespace (represented by a space). The
-second example shows that the syntax of @samp{/} is punctuation. This
-does not show the fact that it is also part of comment-start and -end
-sequences. The third example shows that open parenthesis is in the class
-of open parentheses. This does not show the fact that it has a matching
-character, @samp{)}.
-
-@example
-@group
-(char-to-string (char-syntax ?\ ))
- @result{} " "
-@end group
-
-@group
-(char-to-string (char-syntax ?/))
- @result{} "."
-@end group
-
-@group
-(char-to-string (char-syntax ?\())
- @result{} "("
-@end group
-@end example
-@end defun
-
-@defun set-syntax-table table
-This function makes @var{table} the syntax table for the current buffer.
-It returns @var{table}.
-@end defun
-
-@defun syntax-table
-This function returns the current syntax table, which is the table for
-the current buffer.
-@end defun
-
-@node Motion and Syntax
-@section Motion and Syntax
-
- This section describes functions for moving across characters in
-certain syntax classes. None of these functions exists in Emacs
-version 18 or earlier.
-
-@defun skip-syntax-forward syntaxes &optional limit
-This function moves point forward across characters having syntax classes
-mentioned in @var{syntaxes}. It stops when it encounters the end of
-the buffer, or position @var{limit} (if specified), or a character it is
-not supposed to skip.
-@ignore @c may want to change this.
-The return value is the distance traveled, which is a nonnegative
-integer.
-@end ignore
-@end defun
-
-@defun skip-syntax-backward syntaxes &optional limit
-This function moves point backward across characters whose syntax
-classes are mentioned in @var{syntaxes}. It stops when it encounters
-the beginning of the buffer, or position @var{limit} (if specified), or a
-character it is not supposed to skip.
-@ignore @c may want to change this.
-The return value indicates the distance traveled. It is an integer that
-is zero or less.
-@end ignore
-@end defun
-
-@defun backward-prefix-chars
-This function moves point backward over any number of characters with
-expression prefix syntax. This includes both characters in the
-expression prefix syntax class, and characters with the @samp{p} flag.
-@end defun
-
-@node Parsing Expressions
-@section Parsing Balanced Expressions
-
- Here are several functions for parsing and scanning balanced
-expressions, also known as @dfn{sexps}, in which parentheses match in
-pairs. The syntax table controls the interpretation of characters, so
-these functions can be used for Lisp expressions when in Lisp mode and
-for C expressions when in C mode. @xref{List Motion}, for convenient
-higher-level functions for moving over balanced expressions.
-
-@defun parse-partial-sexp start limit &optional target-depth stop-before state stop-comment
-This function parses a sexp in the current buffer starting at
-@var{start}, not scanning past @var{limit}. It stops at position
-@var{limit} or when certain criteria described below are met, and sets
-point to the location where parsing stops. It returns a value
-describing the status of the parse at the point where it stops.
-
-If @var{state} is @code{nil}, @var{start} is assumed to be at the top
-level of parenthesis structure, such as the beginning of a function
-definition. Alternatively, you might wish to resume parsing in the
-middle of the structure. To do this, you must provide a @var{state}
-argument that describes the initial status of parsing.
-
-@cindex parenthesis depth
-If the third argument @var{target-depth} is non-@code{nil}, parsing
-stops if the depth in parentheses becomes equal to @var{target-depth}.
-The depth starts at 0, or at whatever is given in @var{state}.
-
-If the fourth argument @var{stop-before} is non-@code{nil}, parsing
-stops when it comes to any character that starts a sexp. If
-@var{stop-comment} is non-@code{nil}, parsing stops when it comes to the
-start of a comment.
-
-@cindex parse state
-The fifth argument @var{state} is an eight-element list of the same
-form as the value of this function, described below. The return value
-of one call may be used to initialize the state of the parse on another
-call to @code{parse-partial-sexp}.
-
-The result is a list of eight elements describing the final state of
-the parse:
-
-@enumerate 0
-@item
-The depth in parentheses, counting from 0.
-
-@item
-@cindex innermost containing parentheses
-The character position of the start of the innermost parenthetical
-grouping containing the stopping point; @code{nil} if none.
-
-@item
-@cindex previous complete subexpression
-The character position of the start of the last complete subexpression
-terminated; @code{nil} if none.
-
-@item
-@cindex inside string
-Non-@code{nil} if inside a string. More precisely, this is the
-character that will terminate the string.
-
-@item
-@cindex inside comment
-@code{t} if inside a comment (of either style).
-
-@item
-@cindex quote character
-@code{t} if point is just after a quote character.
-
-@item
-The minimum parenthesis depth encountered during this scan.
-
-@item
-@code{t} if inside a comment of style ``b''.
-@end enumerate
-
-Elements 0, 3, 4, 5 and 7 are significant in the argument @var{state}.
-
-@cindex indenting with parentheses
-This function is most often used to compute indentation for languages
-that have nested parentheses.
-@end defun
-
-@defun scan-lists from count depth
-This function scans forward @var{count} balanced parenthetical groupings
-from character number @var{from}. It returns the character position
-where the scan stops.
-
-If @var{depth} is nonzero, parenthesis depth counting begins from that
-value. The only candidates for stopping are places where the depth in
-parentheses becomes zero; @code{scan-lists} counts @var{count} such
-places and then stops. Thus, a positive value for @var{depth} means go
-out @var{depth} levels of parenthesis.
-
-Scanning ignores comments if @code{parse-sexp-ignore-comments} is
-non-@code{nil}.
-
-If the scan reaches the beginning or end of the buffer (or its
-accessible portion), and the depth is not zero, an error is signaled.
-If the depth is zero but the count is not used up, @code{nil} is
-returned.
-@end defun
-
-@defun scan-sexps from count
-This function scans forward @var{count} sexps from character position
-@var{from}. It returns the character position where the scan stops.
-
-Scanning ignores comments if @code{parse-sexp-ignore-comments} is
-non-@code{nil}.
-
-If the scan reaches the beginning or end of (the accessible part of) the
-buffer in the middle of a parenthetical grouping, an error is signaled.
-If it reaches the beginning or end between groupings but before count is
-used up, @code{nil} is returned.
-@end defun
-
-@defvar parse-sexp-ignore-comments
-@cindex skipping comments
-If the value is non-@code{nil}, then comments are treated as
-whitespace by the functions in this section and by @code{forward-sexp}.
-
-In older Emacs versions, this feature worked only when the comment
-terminator is something like @samp{*/}, and appears only to end a
-comment. In languages where newlines terminate comments, it was
-necessary make this variable @code{nil}, since not every newline is the
-end of a comment. This limitation no longer exists.
-@end defvar
-
-You can use @code{forward-comment} to move forward or backward over
-one comment or several comments.
-
-@defun forward-comment count
-This function moves point forward across @var{count} comments (backward,
-if @var{count} is negative). If it finds anything other than a comment
-or whitespace, it stops, leaving point at the place where it stopped.
-It also stops after satisfying @var{count}.
-@end defun
-
-To move forward over all comments and whitespace following point, use
-@code{(forward-comment (buffer-size))}. @code{(buffer-size)} is a good
-argument to use, because the number of comments in the buffer cannot
-exceed that many.
-
-@node Standard Syntax Tables
-@section Some Standard Syntax Tables
-
- Most of the major modes in Emacs have their own syntax tables. Here
-are several of them:
-
-@defun standard-syntax-table
-This function returns the standard syntax table, which is the syntax
-table used in Fundamental mode.
-@end defun
-
-@defvar text-mode-syntax-table
-The value of this variable is the syntax table used in Text mode.
-@end defvar
-
-@defvar c-mode-syntax-table
-The value of this variable is the syntax table for C-mode buffers.
-@end defvar
-
-@defvar emacs-lisp-mode-syntax-table
-The value of this variable is the syntax table used in Emacs Lisp mode
-by editing commands. (It has no effect on the Lisp @code{read}
-function.)
-@end defvar
-
-@node Syntax Table Internals
-@section Syntax Table Internals
-@cindex syntax table internals
-
- Each element of a syntax table is an integer that encodes the syntax
-of one character: the syntax class, possible matching character, and
-flags. Lisp programs don't usually work with the elements directly; the
-Lisp-level syntax table functions usually work with syntax descriptors
-(@pxref{Syntax Descriptors}).
-
- The low 8 bits of each element of a syntax table indicate the
-syntax class.
-
-@table @asis
-@item @i{Integer}
-@i{Class}
-@item 0
-whitespace
-@item 1
-punctuation
-@item 2
-word
-@item 3
-symbol
-@item 4
-open parenthesis
-@item 5
-close parenthesis
-@item 6
-expression prefix
-@item 7
-string quote
-@item 8
-paired delimiter
-@item 9
-escape
-@item 10
-character quote
-@item 11
-comment-start
-@item 12
-comment-end
-@item 13
-inherit
-@end table
-
- The next 8 bits are the matching opposite parenthesis (if the
-character has parenthesis syntax); otherwise, they are not meaningful.
-The next 6 bits are the flags.
diff --git a/lispref/text.texi b/lispref/text.texi
deleted file mode 100644
index fb718fa41e1..00000000000
--- a/lispref/text.texi
+++ /dev/null
@@ -1,3016 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/text
-@node Text, Searching and Matching, Markers, Top
-@chapter Text
-@cindex text
-
- This chapter describes the functions that deal with the text in a
-buffer. Most examine, insert, or delete text in the current buffer,
-often in the vicinity of point. Many are interactive. All the
-functions that change the text provide for undoing the changes
-(@pxref{Undo}).
-
- Many text-related functions operate on a region of text defined by two
-buffer positions passed in arguments named @var{start} and @var{end}.
-These arguments should be either markers (@pxref{Markers}) or numeric
-character positions (@pxref{Positions}). The order of these arguments
-does not matter; it is all right for @var{start} to be the end of the
-region and @var{end} the beginning. For example, @code{(delete-region 1
-10)} and @code{(delete-region 10 1)} are equivalent. An
-@code{args-out-of-range} error is signaled if either @var{start} or
-@var{end} is outside the accessible portion of the buffer. In an
-interactive call, point and the mark are used for these arguments.
-
-@cindex buffer contents
- Throughout this chapter, ``text'' refers to the characters in the
-buffer, together with their properties (when relevant).
-
-@menu
-* Near Point:: Examining text in the vicinity of point.
-* Buffer Contents:: Examining text in a general fashion.
-* Comparing Text:: Comparing substrings of buffers.
-* Insertion:: Adding new text to a buffer.
-* Commands for Insertion:: User-level commands to insert text.
-* Deletion:: Removing text from a buffer.
-* User-Level Deletion:: User-level commands to delete text.
-* The Kill Ring:: Where removed text sometimes is saved for later use.
-* Undo:: Undoing changes to the text of a buffer.
-* Maintaining Undo:: How to enable and disable undo information.
- How to control how much information is kept.
-* Filling:: Functions for explicit filling.
-* Margins:: How to specify margins for filling commands.
-* Auto Filling:: How auto-fill mode is implemented to break lines.
-* Sorting:: Functions for sorting parts of the buffer.
-* Columns:: Computing horizontal positions, and using them.
-* Indentation:: Functions to insert or adjust indentation.
-* Case Changes:: Case conversion of parts of the buffer.
-* Text Properties:: Assigning Lisp property lists to text characters.
-* Substitution:: Replacing a given character wherever it appears.
-* Transposition:: Swapping two portions of a buffer.
-* Registers:: How registers are implemented. Accessing the text or
- position stored in a register.
-* Change Hooks:: Supplying functions to be run when text is changed.
-@end menu
-
-@node Near Point
-@section Examining Text Near Point
-
- Many functions are provided to look at the characters around point.
-Several simple functions are described here. See also @code{looking-at}
-in @ref{Regexp Search}.
-
-@defun char-after position
-This function returns the character in the current buffer at (i.e.,
-immediately after) position @var{position}. If @var{position} is out of
-range for this purpose, either before the beginning of the buffer, or at
-or beyond the end, then the value is @code{nil}.
-
-In the following example, assume that the first character in the
-buffer is @samp{@@}:
-
-@example
-@group
-(char-to-string (char-after 1))
- @result{} "@@"
-@end group
-@end example
-@end defun
-
-@defun following-char
-This function returns the character following point in the current
-buffer. This is similar to @code{(char-after (point))}. However, if
-point is at the end of the buffer, then @code{following-char} returns 0.
-
-Remember that point is always between characters, and the terminal
-cursor normally appears over the character following point. Therefore,
-the character returned by @code{following-char} is the character the
-cursor is over.
-
-In this example, point is between the @samp{a} and the @samp{c}.
-
-@example
-@group
----------- Buffer: foo ----------
-Gentlemen may cry ``Pea@point{}ce! Peace!,''
-but there is no peace.
----------- Buffer: foo ----------
-@end group
-
-@group
-(char-to-string (preceding-char))
- @result{} "a"
-(char-to-string (following-char))
- @result{} "c"
-@end group
-@end example
-@end defun
-
-@defun preceding-char
-This function returns the character preceding point in the current
-buffer. See above, under @code{following-char}, for an example. If
-point is at the beginning of the buffer, @code{preceding-char} returns
-0.
-@end defun
-
-@defun bobp
-This function returns @code{t} if point is at the beginning of the
-buffer. If narrowing is in effect, this means the beginning of the
-accessible portion of the text. See also @code{point-min} in
-@ref{Point}.
-@end defun
-
-@defun eobp
-This function returns @code{t} if point is at the end of the buffer.
-If narrowing is in effect, this means the end of accessible portion of
-the text. See also @code{point-max} in @xref{Point}.
-@end defun
-
-@defun bolp
-This function returns @code{t} if point is at the beginning of a line.
-@xref{Text Lines}. The beginning of the buffer (or its accessible
-portion) always counts as the beginning of a line.
-@end defun
-
-@defun eolp
-This function returns @code{t} if point is at the end of a line. The
-end of the buffer (or of its accessible portion) is always considered
-the end of a line.
-@end defun
-
-@node Buffer Contents
-@section Examining Buffer Contents
-
- This section describes two functions that allow a Lisp program to
-convert any portion of the text in the buffer into a string.
-
-@defun buffer-substring start end
-This function returns a string containing a copy of the text of the
-region defined by positions @var{start} and @var{end} in the current
-buffer. If the arguments are not positions in the accessible portion of
-the buffer, @code{buffer-substring} signals an @code{args-out-of-range}
-error.
-
-It is not necessary for @var{start} to be less than @var{end}; the
-arguments can be given in either order. But most often the smaller
-argument is written first.
-
-If the text being copied has any text properties, these are copied into
-the string along with the characters they belong to. @xref{Text
-Properties}. However, overlays (@pxref{Overlays}) in the buffer and
-their properties are ignored, not copied.
-
-@example
-@group
----------- Buffer: foo ----------
-This is the contents of buffer foo
-
----------- Buffer: foo ----------
-@end group
-
-@group
-(buffer-substring 1 10)
-@result{} "This is t"
-@end group
-@group
-(buffer-substring (point-max) 10)
-@result{} "he contents of buffer foo
-"
-@end group
-@end example
-@end defun
-
-@defun buffer-substring-no-properties start end
-This is like @code{buffer-substring}, except that it does not copy text
-properties, just the characters themselves. @xref{Text Properties}.
-Here's an example of using this function to get a word to look up in an
-alist:
-
-@example
-(setq flammable
- (assoc (buffer-substring start end)
- '(("wood" . t) ("paper" . t)
- ("steel" . nil) ("asbestos" . nil))))
-@end example
-
-If this were written using @code{buffer-substring} instead, it would not
-work reliably; any text properties that happened to be in the word
-copied from the buffer would make the comparisons fail.
-@end defun
-
-@defun buffer-string
-This function returns the contents of the accessible portion of the
-current buffer as a string. This is the portion between
-@code{(point-min)} and @code{(point-max)} (@pxref{Narrowing}).
-
-@example
-@group
----------- Buffer: foo ----------
-This is the contents of buffer foo
-
----------- Buffer: foo ----------
-
-(buffer-string)
- @result{} "This is the contents of buffer foo
-"
-@end group
-@end example
-@end defun
-
-@node Comparing Text
-@section Comparing Text
-@cindex comparing buffer text
-
- This function lets you compare portions of the text in a buffer, without
-copying them into strings first.
-
-@defun compare-buffer-substrings buffer1 start1 end1 buffer2 start2 end2
-This function lets you compare two substrings of the same buffer or two
-different buffers. The first three arguments specify one substring,
-giving a buffer and two positions within the buffer. The last three
-arguments specify the other substring in the same way. You can use
-@code{nil} for @var{buffer1}, @var{buffer2}, or both to stand for the
-current buffer.
-
-The value is negative if the first substring is less, positive if the
-first is greater, and zero if they are equal. The absolute value of
-the result is one plus the index of the first differing characters
-within the substrings.
-
-This function ignores case when comparing characters
-if @code{case-fold-search} is non-@code{nil}. It always ignores
-text properties.
-
-Suppose the current buffer contains the text @samp{foobarbar
-haha!rara!}; then in this example the two substrings are @samp{rbar }
-and @samp{rara!}. The value is 2 because the first substring is greater
-at the second character.
-
-@example
-(compare-buffer-substring nil 6 11 nil 16 21)
- @result{} 2
-@end example
-@end defun
-
-@node Insertion
-@section Inserting Text
-@cindex insertion of text
-@cindex text insertion
-
- @dfn{Insertion} means adding new text to a buffer. The inserted text
-goes at point---between the character before point and the character
-after point.
-
- Insertion relocates markers that point at positions after the
-insertion point, so that they stay with the surrounding text
-(@pxref{Markers}). When a marker points at the place of insertion,
-insertion normally doesn't relocate the marker, so that it points to the
-beginning of the inserted text; however, certain special functions such
-as @code{insert-before-markers} relocate such markers to point after the
-inserted text.
-
-@cindex insertion before point
-@cindex before point, insertion
- Some insertion functions leave point before the inserted text, while
-other functions leave it after. We call the former insertion @dfn{after
-point} and the latter insertion @dfn{before point}.
-
- Insertion functions signal an error if the current buffer is
-read-only.
-
- These functions copy text characters from strings and buffers along
-with their properties. The inserted characters have exactly the same
-properties as the characters they were copied from. By contrast,
-characters specified as separate arguments, not part of a string or
-buffer, inherit their text properties from the neighboring text.
-
-@defun insert &rest args
-This function inserts the strings and/or characters @var{args} into the
-current buffer, at point, moving point forward. In other words, it
-inserts the text before point. An error is signaled unless all
-@var{args} are either strings or characters. The value is @code{nil}.
-@end defun
-
-@defun insert-before-markers &rest args
-This function inserts the strings and/or characters @var{args} into the
-current buffer, at point, moving point forward. An error is signaled
-unless all @var{args} are either strings or characters. The value is
-@code{nil}.
-
-This function is unlike the other insertion functions in that it
-relocates markers initially pointing at the insertion point, to point
-after the inserted text.
-@end defun
-
-@defun insert-char character count &optional inherit
-This function inserts @var{count} instances of @var{character} into the
-current buffer before point. The argument @var{count} must be a number,
-and @var{character} must be a character. The value is @code{nil}.
-@c It's unfortunate that count comes second. Not like make-string, etc.
-
-If @var{inherit} is non-@code{nil}, then the inserted characters inherit
-sticky text properties from the two characters before and after the
-insertion point. @xref{Sticky Properties}.
-@end defun
-
-@defun insert-buffer-substring from-buffer-or-name &optional start end
-This function inserts a portion of buffer @var{from-buffer-or-name}
-(which must already exist) into the current buffer before point. The
-text inserted is the region from @var{start} and @var{end}. (These
-arguments default to the beginning and end of the accessible portion of
-that buffer.) This function returns @code{nil}.
-
-In this example, the form is executed with buffer @samp{bar} as the
-current buffer. We assume that buffer @samp{bar} is initially empty.
-
-@example
-@group
----------- Buffer: foo ----------
-We hold these truths to be self-evident, that all
----------- Buffer: foo ----------
-@end group
-
-@group
-(insert-buffer-substring "foo" 1 20)
- @result{} nil
-
----------- Buffer: bar ----------
-We hold these truth@point{}
----------- Buffer: bar ----------
-@end group
-@end example
-@end defun
-
- @xref{Sticky Properties}, for other insertion functions that inherit
-text properties from the nearby text in addition to inserting it.
-Whitespace inserted by indentation functions also inherits text
-properties.
-
-@node Commands for Insertion
-@section User-Level Insertion Commands
-
- This section describes higher-level commands for inserting text,
-commands intended primarily for the user but useful also in Lisp
-programs.
-
-@deffn Command insert-buffer from-buffer-or-name
-This command inserts the entire contents of @var{from-buffer-or-name}
-(which must exist) into the current buffer after point. It leaves
-the mark after the inserted text. The value is @code{nil}.
-@end deffn
-
-@deffn Command self-insert-command count
-@cindex character insertion
-@cindex self-insertion
-This command inserts the last character typed; it does so @var{count}
-times, before point, and returns @code{nil}. Most printing characters
-are bound to this command. In routine use, @code{self-insert-command}
-is the most frequently called function in Emacs, but programs rarely use
-it except to install it on a keymap.
-
-In an interactive call, @var{count} is the numeric prefix argument.
-
-This command calls @code{auto-fill-function} whenever that is
-non-@code{nil} and the character inserted is a space or a newline
-(@pxref{Auto Filling}).
-
-@c Cross refs reworded to prevent overfull hbox. --rjc 15mar92
-This command performs abbrev expansion if Abbrev mode is enabled and
-the inserted character does not have word-constituent
-syntax. (@xref{Abbrevs}, and @ref{Syntax Class Table}.)
-
-This is also responsible for calling @code{blink-paren-function} when
-the inserted character has close parenthesis syntax (@pxref{Blinking}).
-@end deffn
-
-@deffn Command newline &optional number-of-newlines
-This command inserts newlines into the current buffer before point.
-If @var{number-of-newlines} is supplied, that many newline characters
-are inserted.
-
-@cindex newline and Auto Fill mode
-This function calls @code{auto-fill-function} if the current column
-number is greater than the value of @code{fill-column} and
-@var{number-of-newlines} is @code{nil}. Typically what
-@code{auto-fill-function} does is insert a newline; thus, the overall
-result in this case is to insert two newlines at different places: one
-at point, and another earlier in the line. @code{newline} does not
-auto-fill if @var{number-of-newlines} is non-@code{nil}.
-
-This command indents to the left margin if that is not zero.
-@xref{Margins}.
-
-The value returned is @code{nil}. In an interactive call, @var{count}
-is the numeric prefix argument.
-@end deffn
-
-@deffn Command split-line
-This command splits the current line, moving the portion of the line
-after point down vertically so that it is on the next line directly
-below where it was before. Whitespace is inserted as needed at the
-beginning of the lower line, using the @code{indent-to} function.
-@code{split-line} returns the position of point.
-
-Programs hardly ever use this function.
-@end deffn
-
-@defvar overwrite-mode
-This variable controls whether overwrite mode is in effect: a
-non-@code{nil} value enables the mode. It is automatically made
-buffer-local when set in any fashion.
-@end defvar
-
-@node Deletion
-@section Deleting Text
-
-@cindex deletion vs killing
- Deletion means removing part of the text in a buffer, without saving
-it in the kill ring (@pxref{The Kill Ring}). Deleted text can't be
-yanked, but can be reinserted using the undo mechanism (@pxref{Undo}).
-Some deletion functions do save text in the kill ring in some special
-cases.
-
- All of the deletion functions operate on the current buffer, and all
-return a value of @code{nil}.
-
-@defun erase-buffer
-This function deletes the entire text of the current buffer, leaving it
-empty. If the buffer is read-only, it signals a @code{buffer-read-only}
-error. Otherwise, it deletes the text without asking for any
-confirmation. It returns @code{nil}.
-
-Normally, deleting a large amount of text from a buffer inhibits further
-auto-saving of that buffer ``because it has shrunk''. However,
-@code{erase-buffer} does not do this, the idea being that the future
-text is not really related to the former text, and its size should not
-be compared with that of the former text.
-@end defun
-
-@deffn Command delete-region start end
-This command deletes the text in the current buffer in the region
-defined by @var{start} and @var{end}. The value is @code{nil}. If
-point was inside the deleted region, its value afterward is @var{start}.
-Otherwise, point relocates with the surrounding text, as markers do.
-@end deffn
-
-@deffn Command delete-char count &optional killp
-This command deletes @var{count} characters directly after point, or
-before point if @var{count} is negative. If @var{killp} is
-non-@code{nil}, then it saves the deleted characters in the kill ring.
-
-In an interactive call, @var{count} is the numeric prefix argument, and
-@var{killp} is the unprocessed prefix argument. Therefore, if a prefix
-argument is supplied, the text is saved in the kill ring. If no prefix
-argument is supplied, then one character is deleted, but not saved in
-the kill ring.
-
-The value returned is always @code{nil}.
-@end deffn
-
-@deffn Command delete-backward-char count &optional killp
-@cindex delete previous char
-This command deletes @var{count} characters directly before point, or
-after point if @var{count} is negative. If @var{killp} is
-non-@code{nil}, then it saves the deleted characters in the kill ring.
-
-In an interactive call, @var{count} is the numeric prefix argument, and
-@var{killp} is the unprocessed prefix argument. Therefore, if a prefix
-argument is supplied, the text is saved in the kill ring. If no prefix
-argument is supplied, then one character is deleted, but not saved in
-the kill ring.
-
-The value returned is always @code{nil}.
-@end deffn
-
-@deffn Command backward-delete-char-untabify count &optional killp
-@cindex tab deletion
-This command deletes @var{count} characters backward, changing tabs
-into spaces. When the next character to be deleted is a tab, it is
-first replaced with the proper number of spaces to preserve alignment
-and then one of those spaces is deleted instead of the tab. If
-@var{killp} is non-@code{nil}, then the command saves the deleted
-characters in the kill ring.
-
-Conversion of tabs to spaces happens only if @var{count} is positive.
-If it is negative, exactly @minus{}@var{count} characters after point
-are deleted.
-
-In an interactive call, @var{count} is the numeric prefix argument, and
-@var{killp} is the unprocessed prefix argument. Therefore, if a prefix
-argument is supplied, the text is saved in the kill ring. If no prefix
-argument is supplied, then one character is deleted, but not saved in
-the kill ring.
-
-The value returned is always @code{nil}.
-@end deffn
-
-@node User-Level Deletion
-@section User-Level Deletion Commands
-
- This section describes higher-level commands for deleting text,
-commands intended primarily for the user but useful also in Lisp
-programs.
-
-@deffn Command delete-horizontal-space
-@cindex deleting whitespace
-This function deletes all spaces and tabs around point. It returns
-@code{nil}.
-
-In the following examples, we call @code{delete-horizontal-space} four
-times, once on each line, with point between the second and third
-characters on the line each time.
-
-@example
-@group
----------- Buffer: foo ----------
-I @point{}thought
-I @point{} thought
-We@point{} thought
-Yo@point{}u thought
----------- Buffer: foo ----------
-@end group
-
-@group
-(delete-horizontal-space) ; @r{Four times.}
- @result{} nil
-
----------- Buffer: foo ----------
-Ithought
-Ithought
-Wethought
-You thought
----------- Buffer: foo ----------
-@end group
-@end example
-@end deffn
-
-@deffn Command delete-indentation &optional join-following-p
-This function joins the line point is on to the previous line, deleting
-any whitespace at the join and in some cases replacing it with one
-space. If @var{join-following-p} is non-@code{nil},
-@code{delete-indentation} joins this line to the following line
-instead. The value is @code{nil}.
-
-If there is a fill prefix, and the second of the lines being joined
-starts with the prefix, then @code{delete-indentation} deletes the
-fill prefix before joining the lines. @xref{Margins}.
-
-In the example below, point is located on the line starting
-@samp{events}, and it makes no difference if there are trailing spaces
-in the preceding line.
-
-@smallexample
-@group
----------- Buffer: foo ----------
-When in the course of human
-@point{} events, it becomes necessary
----------- Buffer: foo ----------
-@end group
-
-(delete-indentation)
- @result{} nil
-
-@group
----------- Buffer: foo ----------
-When in the course of human@point{} events, it becomes necessary
----------- Buffer: foo ----------
-@end group
-@end smallexample
-
-After the lines are joined, the function @code{fixup-whitespace} is
-responsible for deciding whether to leave a space at the junction.
-@end deffn
-
-@defun fixup-whitespace
-This function replaces all the white space surrounding point with either
-one space or no space, according to the context. It returns @code{nil}.
-
-At the beginning or end of a line, the appropriate amount of space is
-none. Before a character with close parenthesis syntax, or after a
-character with open parenthesis or expression-prefix syntax, no space is
-also appropriate. Otherwise, one space is appropriate. @xref{Syntax
-Class Table}.
-
-In the example below, @code{fixup-whitespace} is called the first time
-with point before the word @samp{spaces} in the first line. For the
-second invocation, point is directly after the @samp{(}.
-
-@smallexample
-@group
----------- Buffer: foo ----------
-This has too many @point{}spaces
-This has too many spaces at the start of (@point{} this list)
----------- Buffer: foo ----------
-@end group
-
-@group
-(fixup-whitespace)
- @result{} nil
-(fixup-whitespace)
- @result{} nil
-@end group
-
-@group
----------- Buffer: foo ----------
-This has too many spaces
-This has too many spaces at the start of (this list)
----------- Buffer: foo ----------
-@end group
-@end smallexample
-@end defun
-
-@deffn Command just-one-space
-@comment !!SourceFile simple.el
-This command replaces any spaces and tabs around point with a single
-space. It returns @code{nil}.
-@end deffn
-
-@deffn Command delete-blank-lines
-This function deletes blank lines surrounding point. If point is on a
-blank line with one or more blank lines before or after it, then all but
-one of them are deleted. If point is on an isolated blank line, then it
-is deleted. If point is on a nonblank line, the command deletes all
-blank lines following it.
-
-A blank line is defined as a line containing only tabs and spaces.
-
-@code{delete-blank-lines} returns @code{nil}.
-@end deffn
-
-@node The Kill Ring
-@section The Kill Ring
-@cindex kill ring
-
- @dfn{Kill} functions delete text like the deletion functions, but save
-it so that the user can reinsert it by @dfn{yanking}. Most of these
-functions have @samp{kill-} in their name. By contrast, the functions
-whose names start with @samp{delete-} normally do not save text for
-yanking (though they can still be undone); these are ``deletion''
-functions.
-
- Most of the kill commands are primarily for interactive use, and are
-not described here. What we do describe are the functions provided for
-use in writing such commands. You can use these functions to write
-commands for killing text. When you need to delete text for internal
-purposes within a Lisp function, you should normally use deletion
-functions, so as not to disturb the kill ring contents.
-@xref{Deletion}.
-
- Killed text is saved for later yanking in the @dfn{kill ring}. This
-is a list that holds a number of recent kills, not just the last text
-kill. We call this a ``ring'' because yanking treats it as having
-elements in a cyclic order. The list is kept in the variable
-@code{kill-ring}, and can be operated on with the usual functions for
-lists; there are also specialized functions, described in this section,
-that treat it as a ring.
-
- Some people think this use of the word ``kill'' is unfortunate, since
-it refers to operations that specifically @emph{do not} destroy the
-entities ``killed''. This is in sharp contrast to ordinary life, in
-which death is permanent and ``killed'' entities do not come back to
-life. Therefore, other metaphors have been proposed. For example, the
-term ``cut ring'' makes sense to people who, in pre-computer days, used
-scissors and paste to cut up and rearrange manuscripts. However, it
-would be difficult to change the terminology now.
-
-@menu
-* Kill Ring Concepts:: What text looks like in the kill ring.
-* Kill Functions:: Functions that kill text.
-* Yank Commands:: Commands that access the kill ring.
-* Low-Level Kill Ring:: Functions and variables for kill ring access.
-* Internals of Kill Ring:: Variables that hold kill-ring data.
-@end menu
-
-@node Kill Ring Concepts
-@comment node-name, next, previous, up
-@subsection Kill Ring Concepts
-
- The kill ring records killed text as strings in a list, most recent
-first. A short kill ring, for example, might look like this:
-
-@example
-("some text" "a different piece of text" "even older text")
-@end example
-
-@noindent
-When the list reaches @code{kill-ring-max} entries in length, adding a
-new entry automatically deletes the last entry.
-
- When kill commands are interwoven with other commands, each kill
-command makes a new entry in the kill ring. Multiple kill commands in
-succession build up a single entry in the kill ring, which would be
-yanked as a unit; the second and subsequent consecutive kill commands
-add text to the entry made by the first one.
-
- For yanking, one entry in the kill ring is designated the ``front'' of
-the ring. Some yank commands ``rotate'' the ring by designating a
-different element as the ``front.'' But this virtual rotation doesn't
-change the list itself---the most recent entry always comes first in the
-list.
-
-@node Kill Functions
-@comment node-name, next, previous, up
-@subsection Functions for Killing
-
- @code{kill-region} is the usual subroutine for killing text. Any
-command that calls this function is a ``kill command'' (and should
-probably have @samp{kill} in its name). @code{kill-region} puts the
-newly killed text in a new element at the beginning of the kill ring or
-adds it to the most recent element. It uses the @code{last-command}
-variable to determine whether the previous command was a kill command,
-and if so appends the killed text to the most recent entry.
-
-@deffn Command kill-region start end
-This function kills the text in the region defined by @var{start} and
-@var{end}. The text is deleted but saved in the kill ring, along with
-its text properties. The value is always @code{nil}.
-
-In an interactive call, @var{start} and @var{end} are point and
-the mark.
-
-@c Emacs 19 feature
-If the buffer is read-only, @code{kill-region} modifies the kill ring
-just the same, then signals an error without modifying the buffer. This
-is convenient because it lets the user use all the kill commands to copy
-text into the kill ring from a read-only buffer.
-@end deffn
-
-@deffn Command copy-region-as-kill start end
-This command saves the region defined by @var{start} and @var{end} on
-the kill ring (including text properties), but does not delete the text
-from the buffer. It returns @code{nil}. It also indicates the extent
-of the text copied by moving the cursor momentarily, or by displaying a
-message in the echo area.
-
-The command does not set @code{this-command} to @code{kill-region}, so a
-subsequent kill command does not append to the same kill ring entry.
-
-Don't call @code{copy-region-as-kill} in Lisp programs unless you aim to
-support Emacs 18. For Emacs 19, it is better to use @code{kill-new} or
-@code{kill-append} instead. @xref{Low-Level Kill Ring}.
-@end deffn
-
-@node Yank Commands
-@comment node-name, next, previous, up
-@subsection Functions for Yanking
-
- @dfn{Yanking} means reinserting an entry of previously killed text
-from the kill ring. The text properties are copied too.
-
-@deffn Command yank &optional arg
-@cindex inserting killed text
-This command inserts before point the text in the first entry in the
-kill ring. It positions the mark at the beginning of that text, and
-point at the end.
-
-If @var{arg} is a list (which occurs interactively when the user
-types @kbd{C-u} with no digits), then @code{yank} inserts the text as
-described above, but puts point before the yanked text and puts the mark
-after it.
-
-If @var{arg} is a number, then @code{yank} inserts the @var{arg}th most
-recently killed text---the @var{arg}th element of the kill ring list.
-
-@code{yank} does not alter the contents of the kill ring or rotate it.
-It returns @code{nil}.
-@end deffn
-
-@deffn Command yank-pop arg
-This command replaces the just-yanked entry from the kill ring with a
-different entry from the kill ring.
-
-This is allowed only immediately after a @code{yank} or another
-@code{yank-pop}. At such a time, the region contains text that was just
-inserted by yanking. @code{yank-pop} deletes that text and inserts in
-its place a different piece of killed text. It does not add the deleted
-text to the kill ring, since it is already in the kill ring somewhere.
-
-If @var{arg} is @code{nil}, then the replacement text is the previous
-element of the kill ring. If @var{arg} is numeric, the replacement is
-the @var{arg}th previous kill. If @var{arg} is negative, a more recent
-kill is the replacement.
-
-The sequence of kills in the kill ring wraps around, so that after the
-oldest one comes the newest one, and before the newest one goes the
-oldest.
-
-The value is always @code{nil}.
-@end deffn
-
-@node Low-Level Kill Ring
-@subsection Low-Level Kill Ring
-
- These functions and variables provide access to the kill ring at a lower
-level, but still convenient for use in Lisp programs. They take care of
-interaction with X Window selections. They do not exist in Emacs
-version 18.
-
-@defun current-kill n &optional do-not-move
-The function @code{current-kill} rotates the yanking pointer which
-designates the ``front'' of the kill ring by @var{n} places (from newer
-kills to older ones), and returns the text at that place in the ring.
-
-If the optional second argument @var{do-not-move} is non-@code{nil},
-then @code{current-kill} doesn't alter the yanking pointer; it just
-returns the @var{n}th kill, counting from the current yanking pointer.
-
-If @var{n} is zero, indicating a request for the latest kill,
-@code{current-kill} calls the value of
-@code{interprogram-paste-function} (documented below) before consulting
-the kill ring.
-@end defun
-
-@defun kill-new string
-This function puts the text @var{string} into the kill ring as a new
-entry at the front of the ring. It discards the oldest entry if
-appropriate. It also invokes the value of
-@code{interprogram-cut-function} (see below).
-@end defun
-
-@defun kill-append string before-p
-This function appends the text @var{string} to the first entry in the
-kill ring. Normally @var{string} goes at the end of the entry, but if
-@var{before-p} is non-@code{nil}, it goes at the beginning. This
-function also invokes the value of @code{interprogram-cut-function} (see
-below).
-@end defun
-
-@defvar interprogram-paste-function
-This variable provides a way of transferring killed text from other
-programs, when you are using a window system. Its value should be
-@code{nil} or a function of no arguments.
-
-If the value is a function, @code{current-kill} calls it to get the
-``most recent kill''. If the function returns a non-@code{nil} value,
-then that value is used as the ``most recent kill''. If it returns
-@code{nil}, then the first element of @code{kill-ring} is used.
-
-The normal use of this hook is to get the X server's primary selection
-as the most recent kill, even if the selection belongs to another X
-client. @xref{X Selections}.
-@end defvar
-
-@defvar interprogram-cut-function
-This variable provides a way of communicating killed text to other
-programs, when you are using a window system. Its value should be
-@code{nil} or a function of one argument.
-
-If the value is a function, @code{kill-new} and @code{kill-append} call
-it with the new first element of the kill ring as an argument.
-
-The normal use of this hook is to set the X server's primary selection
-to the newly killed text.
-@end defvar
-
-@node Internals of Kill Ring
-@comment node-name, next, previous, up
-@subsection Internals of the Kill Ring
-
- The variable @code{kill-ring} holds the kill ring contents, in the
-form of a list of strings. The most recent kill is always at the front
-of the list.
-
- The @code{kill-ring-yank-pointer} variable points to a link in the
-kill ring list, whose @sc{car} is the text to yank next. We say it
-identifies the ``front'' of the ring. Moving
-@code{kill-ring-yank-pointer} to a different link is called
-@dfn{rotating the kill ring}. We call the kill ring a ``ring'' because
-the functions that move the yank pointer wrap around from the end of the
-list to the beginning, or vice-versa. Rotation of the kill ring is
-virtual; it does not change the value of @code{kill-ring}.
-
- Both @code{kill-ring} and @code{kill-ring-yank-pointer} are Lisp
-variables whose values are normally lists. The word ``pointer'' in the
-name of the @code{kill-ring-yank-pointer} indicates that the variable's
-purpose is to identify one element of the list for use by the next yank
-command.
-
- The value of @code{kill-ring-yank-pointer} is always @code{eq} to one
-of the links in the kill ring list. The element it identifies is the
-@sc{car} of that link. Kill commands, which change the kill ring, also
-set this variable to the value of @code{kill-ring}. The effect is to
-rotate the ring so that the newly killed text is at the front.
-
- Here is a diagram that shows the variable @code{kill-ring-yank-pointer}
-pointing to the second entry in the kill ring @code{("some text" "a
-different piece of text" "yet older text")}.
-
-@example
-@group
-kill-ring kill-ring-yank-pointer
- | |
- | ___ ___ ---> ___ ___ ___ ___
- --> |___|___|------> |___|___|--> |___|___|--> nil
- | | |
- | | |
- | | -->"yet older text"
- | |
- | --> "a different piece of text"
- |
- --> "some text"
-@end group
-@end example
-
-@noindent
-This state of affairs might occur after @kbd{C-y} (@code{yank})
-immediately followed by @kbd{M-y} (@code{yank-pop}).
-
-@defvar kill-ring
-This variable holds the list of killed text sequences, most recently
-killed first.
-@end defvar
-
-@defvar kill-ring-yank-pointer
-This variable's value indicates which element of the kill ring is at the
-``front'' of the ring for yanking. More precisely, the value is a tail
-of the value of @code{kill-ring}, and its @sc{car} is the kill string
-that @kbd{C-y} should yank.
-@end defvar
-
-@defopt kill-ring-max
-The value of this variable is the maximum length to which the kill
-ring can grow, before elements are thrown away at the end. The default
-value for @code{kill-ring-max} is 30.
-@end defopt
-
-@node Undo
-@comment node-name, next, previous, up
-@section Undo
-@cindex redo
-
- Most buffers have an @dfn{undo list}, which records all changes made
-to the buffer's text so that they can be undone. (The buffers that
-don't have one are usually special-purpose buffers for which Emacs
-assumes that undoing is not useful.) All the primitives that modify the
-text in the buffer automatically add elements to the front of the undo
-list, which is in the variable @code{buffer-undo-list}.
-
-@defvar buffer-undo-list
-This variable's value is the undo list of the current buffer.
-A value of @code{t} disables the recording of undo information.
-@end defvar
-
-Here are the kinds of elements an undo list can have:
-
-@table @code
-@item @var{integer}
-This kind of element records a previous value of point. Ordinary cursor
-motion does not get any sort of undo record, but deletion commands use
-these entries to record where point was before the command.
-
-@item (@var{beg} . @var{end})
-This kind of element indicates how to delete text that was inserted.
-Upon insertion, the text occupied the range @var{beg}--@var{end} in the
-buffer.
-
-@item (@var{text} . @var{position})
-This kind of element indicates how to reinsert text that was deleted.
-The deleted text itself is the string @var{text}. The place to
-reinsert it is @code{(abs @var{position})}.
-
-@item (t @var{high} . @var{low})
-This kind of element indicates that an unmodified buffer became
-modified. The elements @var{high} and @var{low} are two integers, each
-recording 16 bits of the visited file's modification time as of when it
-was previously visited or saved. @code{primitive-undo} uses those
-values to determine whether to mark the buffer as unmodified once again;
-it does so only if the file's modification time matches those numbers.
-
-@item (nil @var{property} @var{value} @var{beg} . @var{end})
-This kind of element records a change in a text property.
-Here's how you might undo the change:
-
-@example
-(put-text-property @var{beg} @var{end} @var{property} @var{value})
-@end example
-
-@item (@var{marker} . @var{adjustment})
-This kind of element records the fact that the marker @var{marker} was
-relocated due to deletion of surrounding text, and that it moved
-@var{adjustment} character positions. Undoing this element moves
-@var{marker} @minus{} @var{adjustment} characters.
-
-@item @var{position}
-This element indicates where point was at an earlier time. Undoing this
-element sets point to @var{position}. Deletion normally creates an
-element of this kind as well as a reinsertion element.
-
-@item nil
-This element is a boundary. The elements between two boundaries are
-called a @dfn{change group}; normally, each change group corresponds to
-one keyboard command, and undo commands normally undo an entire group as
-a unit.
-@end table
-
-@defun undo-boundary
-This function places a boundary element in the undo list. The undo
-command stops at such a boundary, and successive undo commands undo
-to earlier and earlier boundaries. This function returns @code{nil}.
-
-The editor command loop automatically creates an undo boundary before
-each key sequence is executed. Thus, each undo normally undoes the
-effects of one command. Self-inserting input characters are an
-exception. The command loop makes a boundary for the first such
-character; the next 19 consecutive self-inserting input characters do
-not make boundaries, and then the 20th does, and so on as long as
-self-inserting characters continue.
-
-All buffer modifications add a boundary whenever the previous undoable
-change was made in some other buffer. This way, a command that modifies
-several buffers makes a boundary in each buffer it changes.
-
-Calling this function explicitly is useful for splitting the effects of
-a command into more than one unit. For example, @code{query-replace}
-calls @code{undo-boundary} after each replacement, so that the user can
-undo individual replacements one by one.
-@end defun
-
-@defun primitive-undo count list
-This is the basic function for undoing elements of an undo list.
-It undoes the first @var{count} elements of @var{list}, returning
-the rest of @var{list}. You could write this function in Lisp,
-but it is convenient to have it in C.
-
-@code{primitive-undo} adds elements to the buffer's undo list when it
-changes the buffer. Undo commands avoid confusion by saving the undo
-list value at the beginning of a sequence of undo operations. Then the
-undo operations use and update the saved value. The new elements added
-by undoing are not part of this saved value, so they don't interfere with
-continuing to undo.
-@end defun
-
-@node Maintaining Undo
-@section Maintaining Undo Lists
-
- This section describes how to enable and disable undo information for
-a given buffer. It also explains how the undo list is truncated
-automatically so it doesn't get too big.
-
- Recording of undo information in a newly created buffer is normally
-enabled to start with; but if the buffer name starts with a space, the
-undo recording is initially disabled. You can explicitly enable or
-disable undo recording with the following two functions, or by setting
-@code{buffer-undo-list} yourself.
-
-@deffn Command buffer-enable-undo &optional buffer-or-name
-This command enables recording undo information for buffer
-@var{buffer-or-name}, so that subsequent changes can be undone. If no
-argument is supplied, then the current buffer is used. This function
-does nothing if undo recording is already enabled in the buffer. It
-returns @code{nil}.
-
-In an interactive call, @var{buffer-or-name} is the current buffer.
-You cannot specify any other buffer.
-@end deffn
-
-@defun buffer-disable-undo &optional buffer
-@defunx buffer-flush-undo &optional buffer
-@cindex disable undo
-This function discards the undo list of @var{buffer}, and disables
-further recording of undo information. As a result, it is no longer
-possible to undo either previous changes or any subsequent changes. If
-the undo list of @var{buffer} is already disabled, this function
-has no effect.
-
-This function returns @code{nil}. It cannot be called interactively.
-
-The name @code{buffer-flush-undo} is not considered obsolete, but the
-preferred name @code{buffer-disable-undo} is new as of Emacs versions
-19.
-@end defun
-
- As editing continues, undo lists get longer and longer. To prevent
-them from using up all available memory space, garbage collection trims
-them back to size limits 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: @code{undo-limit} and @code{undo-strong-limit}.
-
-@defvar undo-limit
-This is the soft limit for the acceptable size of an undo list. The
-change group at which this size is exceeded is the last one kept.
-@end defvar
-
-@defvar undo-strong-limit
-This is the upper limit for the acceptable size of an undo list. The
-change group at which this size is exceeded is discarded itself (along
-with all older change groups). There is one exception: the very latest
-change group is never discarded no matter how big it is.
-@end defvar
-
-@node Filling
-@comment node-name, next, previous, up
-@section Filling
-@cindex filling, explicit
-
- @dfn{Filling} means adjusting the lengths of lines (by moving the line
-breaks) so that they are nearly (but no greater than) a specified
-maximum width. Additionally, lines can be @dfn{justified}, which means
-inserting spaces to make the left and/or right margins line up
-precisely. The width is controlled by the variable @code{fill-column}.
-For ease of reading, lines should be no longer than 70 or so columns.
-
- You can use Auto Fill mode (@pxref{Auto Filling}) to fill text
-automatically as you insert it, but changes to existing text may leave
-it improperly filled. Then you must fill the text explicitly.
-
- Most of the commands in this section return values that are not
-meaningful. All the functions that do filling take note of the current
-left margin, current right margin, and current justification style
-(@pxref{Margins}). If the current justification style is
-@code{none}, the filling functions don't actually do anything.
-
- Several of the filling functions have an argument @var{justify}.
-If it is non-@code{nil}, that requests some kind of justification. It
-can be @code{left}, @code{right}, @code{full}, or @code{center}, to
-request a specific style of justification. If it is @code{t}, that
-means to use the current justification style for this part of the text
-(see @code{current-justification}, below).
-
- When you call the filling functions interactively, using a prefix
-argument implies the value @code{full} for @var{justify}.
-
-@deffn Command fill-paragraph justify
-@cindex filling a paragraph
-This command fills the paragraph at or after point. If
-@var{justify} is non-@code{nil}, each line is justified as well.
-It uses the ordinary paragraph motion commands to find paragraph
-boundaries. @xref{Paragraphs,,, emacs, The Emacs Manual}.
-@end deffn
-
-@deffn Command fill-region start end &optional justify
-This command fills each of the paragraphs in the region from @var{start}
-to @var{end}. It justifies as well if @var{justify} is
-non-@code{nil}.
-
-The variable @code{paragraph-separate} controls how to distinguish
-paragraphs. @xref{Standard Regexps}.
-@end deffn
-
-@deffn Command fill-individual-paragraphs start end &optional justify mail-flag
-This command fills each paragraph in the region according to its
-individual fill prefix. Thus, if the lines of a paragraph were indented
-with spaces, the filled paragraph will remain indented in the same
-fashion.
-
-The first two arguments, @var{start} and @var{end}, are the beginning
-and end of the region to be filled. The third and fourth arguments,
-@var{justify} and @var{mail-flag}, are optional. If
-@var{justify} is non-@code{nil}, the paragraphs are justified as
-well as filled. If @var{mail-flag} is non-@code{nil}, it means the
-function is operating on a mail message and therefore should not fill
-the header lines.
-
-Ordinarily, @code{fill-individual-paragraphs} regards each change in
-indentation as starting a new paragraph. If
-@code{fill-individual-varying-indent} is non-@code{nil}, then only
-separator lines separate paragraphs. That mode can handle indented
-paragraphs with additional indentation on the first line.
-@end deffn
-
-@defopt fill-individual-varying-indent
-This variable alters the action of @code{fill-individual-paragraphs} as
-described above.
-@end defopt
-
-@deffn Command fill-region-as-paragraph start end &optional justify
-This command considers a region of text as a paragraph and fills it. If
-the region was made up of many paragraphs, the blank lines between
-paragraphs are removed. This function justifies as well as filling when
-@var{justify} is non-@code{nil}.
-
-In an interactive call, any prefix argument requests justification.
-
-In Adaptive Fill mode, which is enabled by default, calling the function
-@code{fill-region-as-paragraph} on an indented paragraph when there is
-no fill prefix uses the indentation of the second line of the paragraph
-as the fill prefix.
-@end deffn
-
-@deffn Command justify-current-line how eop nosqueeze
-This command inserts spaces between the words of the current line so
-that the line ends exactly at @code{fill-column}. It returns
-@code{nil}.
-
-The argument @var{how}, if non-@code{nil} specifies explicitly the style
-of justification. It can be @code{left}, @code{right}, @code{full},
-@code{center}, or @code{none}. If it is @code{t}, that means to do
-follow specified justification style (see @code{current-justification},
-below). @code{nil} means to do full justification.
-
-If @var{eop} is non-@code{nil}, that means do left-justification if
-@code{current-justification} specifies full justification. This is used
-for the last line of a paragraph; even if the paragraph as a whole is
-fully justified, the last line should not be.
-
-If @var{nosqueeze} is non-@code{nil}, that means do not change interior
-whitespace.
-@end deffn
-
-@defopt default-justification
-This variable's value specifies the style of justification to use for
-text that doesn't specify a style with a text property. The possible
-values are @code{left}, @code{right}, @code{full}, @code{center}, or
-@code{none}. The default value is @code{left}.
-@end defopt
-
-@defun current-justification
-This function returns the proper justification style to use for filling
-the text around point.
-@end defun
-
-@defvar fill-paragraph-function
-This variable provides a way for major modes to override the filling of
-paragraphs. If the value is non-@code{nil}, @code{fill-paragraph} calls
-this function to do the work. If the function returns a non-@code{nil}
-value, @code{fill-paragraph} assumes the job is done, and immediately
-returns that value.
-
-The usual use of this feature is to fill comments in programming
-language modes. If the function needs to fill a paragraph in the usual
-way, it can do so as follows:
-
-@example
-(let ((fill-paragraph-function nil))
- (fill-paragraph arg))
-@end example
-@end defvar
-
-@defvar use-hard-newlines
-If this variable is non-@code{nil}, the filling functions do not delete
-newlines that have the @code{hard} text property. These ``hard
-newlines'' act as paragraph separators.
-@end defvar
-
-@node Margins
-@section Margins for Filling
-
-@defopt fill-prefix
-This variable specifies a string of text that appears at the beginning
-of normal text lines and should be disregarded when filling them. Any
-line that fails to start with the fill prefix is considered the start of
-a paragraph; so is any line that starts with the fill prefix followed by
-additional whitespace. Lines that start with the fill prefix but no
-additional whitespace are ordinary text lines that can be filled
-together. The resulting filled lines also start with the fill prefix.
-
-The fill prefix follows the left margin whitespace, if any.
-@end defopt
-
-@defopt fill-column
-This buffer-local variable specifies the maximum width of filled
-lines. Its value should be an integer, which is a number of columns.
-All the filling, justification and centering commands are affected by
-this variable, including Auto Fill mode (@pxref{Auto Filling}).
-
-As a practical matter, if you are writing text for other people to
-read, you should set @code{fill-column} to no more than 70. Otherwise
-the line will be too long for people to read comfortably, and this can
-make the text seem clumsy.
-@end defopt
-
-@defvar default-fill-column
-The value of this variable is the default value for @code{fill-column} in
-buffers that do not override it. This is the same as
-@code{(default-value 'fill-column)}.
-
-The default value for @code{default-fill-column} is 70.
-@end defvar
-
-@deffn Command set-left-margin from to margin
-This sets the @code{left-margin} property on the text from @var{from} to
-@var{to} to the value @var{margin}. If Auto Fill mode is enabled, this
-command also refills the region to fit the new margin.
-@end deffn
-
-@deffn Command set-right-margin from to margin
-This sets the @code{right-margin} property on the text from @var{from}
-to @var{to} to the value @var{margin}. If Auto Fill mode is enabled,
-this command also refills the region to fit the new margin.
-@end deffn
-
-@defun current-left-margin
-This function returns the proper left margin value to use for filling
-the text around point. The value is the sum of the @code{left-margin}
-property of the character at the start of the current line (or zero if
-none), and the value of the variable @code{left-margin}.
-@end defun
-
-@defun current-fill-column
-This function returns the proper fill column value to use for filling
-the text around point. The value is the value of the @code{fill-column}
-variable, minus the value of the @code{right-margin} property of the
-character after point.
-@end defun
-
-@deffn Command move-to-left-margin &optional n force
-This function moves point to the left margin of the current line. The
-column moved to is determined by calling the function
-@code{current-left-margin}. If the argument @var{n} is non-@code{nil},
-@code{move-to-left-margin} moves forward @var{n}@minus{}1 lines first.
-
-If @var{force} is non-@code{nil}, that says to fix the line's
-indentation if that doesn't match the left margin value.
-@end deffn
-
-@defun delete-to-left-margin from to
-This function removes left margin indentation from the text
-between @var{from} and @var{to}. The amount of indentation
-to delete is determined by calling @code{current-left-margin}.
-In no case does this function delete non-whitespace.
-@end defun
-
-@defun indent-to-left-margin
-This is the default @code{indent-line-function}, used in Fundamental
-mode, Text mode, etc. Its effect is to adjust the indentation at the
-beginning of the current line to the value specified by the variable
-@code{left-margin}. This may involve either inserting or deleting
-whitespace.
-@end defun
-
-@defvar left-margin
-This variable specifies the base left margin column. In Fundamental
-mode, @key{LFD} indents to this column. This variable automatically
-becomes buffer-local when set in any fashion.
-@end defvar
-
-@node Auto Filling
-@comment node-name, next, previous, up
-@section Auto Filling
-@cindex filling, automatic
-@cindex Auto Fill mode
-
- Auto Fill mode is a minor mode that fills lines automatically as text
-is inserted. This section describes the hook used by Auto Fill mode.
-For a description of functions that you can call explicitly to fill and
-justify existing text, see @ref{Filling}.
-
- Auto Fill mode also enables the functions that change the margins and
-justification style to refill portions of the text. @xref{Margins}.
-
-@defvar auto-fill-function
-The value of this variable should be a function (of no arguments) to be
-called after self-inserting a space or a newline. It may be @code{nil},
-in which case nothing special is done in that case.
-
-The value of @code{auto-fill-function} is @code{do-auto-fill} when
-Auto-Fill mode is enabled. That is a function whose sole purpose is to
-implement the usual strategy for breaking a line.
-
-@quotation
-In older Emacs versions, this variable was named @code{auto-fill-hook},
-but since it is not called with the standard convention for hooks, it
-was renamed to @code{auto-fill-function} in version 19.
-@end quotation
-@end defvar
-
-@defvar normal-auto-fill-function
-This variable specifies the function to use for
-@code{auto-fill-function}, if and when Auto Fill is turned on. Major
-modes can set this locally to alter how Auto Fill works.
-@end defvar
-
-@node Sorting
-@section Sorting Text
-@cindex sorting text
-
- The sorting functions described in this section all rearrange text in
-a buffer. This is in contrast to the function @code{sort}, which
-rearranges the order of the elements of a list (@pxref{Rearrangement}).
-The values returned by these functions are not meaningful.
-
-@defun sort-subr reverse nextrecfun endrecfun &optional startkeyfun endkeyfun
-This function is the general text-sorting routine that divides a buffer
-into records and sorts them. Most of the commands in this section use
-this function.
-
-To understand how @code{sort-subr} works, consider the whole accessible
-portion of the buffer as being divided into disjoint pieces called
-@dfn{sort records}. The records may or may not be contiguous; they may
-not overlap. A portion of each sort record (perhaps all of it) is
-designated as the sort key. Sorting rearranges the records in order by
-their sort keys.
-
-Usually, the records are rearranged in order of ascending sort key.
-If the first argument to the @code{sort-subr} function, @var{reverse},
-is non-@code{nil}, the sort records are rearranged in order of
-descending sort key.
-
-The next four arguments to @code{sort-subr} are functions that are
-called to move point across a sort record. They are called many times
-from within @code{sort-subr}.
-
-@enumerate
-@item
-@var{nextrecfun} is called with point at the end of a record. This
-function moves point to the start of the next record. The first record
-is assumed to start at the position of point when @code{sort-subr} is
-called. Therefore, you should usually move point to the beginning of
-the buffer before calling @code{sort-subr}.
-
-This function can indicate there are no more sort records by leaving
-point at the end of the buffer.
-
-@item
-@var{endrecfun} is called with point within a record. It moves point to
-the end of the record.
-
-@item
-@var{startkeyfun} is called to move point from the start of a record to
-the start of the sort key. This argument is optional; if it is omitted,
-the whole record is the sort key. If supplied, the function should
-either return a non-@code{nil} value to be used as the sort key, or
-return @code{nil} to indicate that the sort key is in the buffer
-starting at point. In the latter case, @var{endkeyfun} is called to
-find the end of the sort key.
-
-@item
-@var{endkeyfun} is called to move point from the start of the sort key
-to the end of the sort key. This argument is optional. If
-@var{startkeyfun} returns @code{nil} and this argument is omitted (or
-@code{nil}), then the sort key extends to the end of the record. There
-is no need for @var{endkeyfun} if @var{startkeyfun} returns a
-non-@code{nil} value.
-@end enumerate
-
-As an example of @code{sort-subr}, here is the complete function
-definition for @code{sort-lines}:
-
-@example
-@group
-;; @r{Note that the first two lines of doc string}
-;; @r{are effectively one line when viewed by a user.}
-(defun sort-lines (reverse beg end)
- "Sort lines in region alphabetically.
-Called from a program, there are three arguments:
-@end group
-@group
-REVERSE (non-nil means reverse order),
-and BEG and END (the region to sort)."
- (interactive "P\nr")
- (save-restriction
- (narrow-to-region beg end)
- (goto-char (point-min))
- (sort-subr reverse
- 'forward-line
- 'end-of-line)))
-@end group
-@end example
-
-Here @code{forward-line} moves point to the start of the next record,
-and @code{end-of-line} moves point to the end of record. We do not pass
-the arguments @var{startkeyfun} and @var{endkeyfun}, because the entire
-record is used as the sort key.
-
-The @code{sort-paragraphs} function is very much the same, except that
-its @code{sort-subr} call looks like this:
-
-@example
-@group
-(sort-subr reverse
- (function
- (lambda ()
- (skip-chars-forward "\n \t\f")))
- 'forward-paragraph)
-@end group
-@end example
-@end defun
-
-@deffn Command sort-regexp-fields reverse record-regexp key-regexp start end
-This command sorts the region between @var{start} and @var{end}
-alphabetically as specified by @var{record-regexp} and @var{key-regexp}.
-If @var{reverse} is a negative integer, then sorting is in reverse
-order.
-
-Alphabetical sorting means that two sort keys are compared by
-comparing the first characters of each, the second characters of each,
-and so on. If a mismatch is found, it means that the sort keys are
-unequal; the sort key whose character is less at the point of first
-mismatch is the lesser sort key. The individual characters are compared
-according to their numerical values. Since Emacs uses the @sc{ASCII}
-character set, the ordering in that set determines alphabetical order.
-@c version 19 change
-
-The value of the @var{record-regexp} argument specifies how to divide
-the buffer into sort records. At the end of each record, a search is
-done for this regular expression, and the text that matches it is the
-next record. For example, the regular expression @samp{^.+$}, which
-matches lines with at least one character besides a newline, would make
-each such line into a sort record. @xref{Regular Expressions}, for a
-description of the syntax and meaning of regular expressions.
-
-The value of the @var{key-regexp} argument specifies what part of each
-record is the sort key. The @var{key-regexp} could match the whole
-record, or only a part. In the latter case, the rest of the record has
-no effect on the sorted order of records, but it is carried along when
-the record moves to its new position.
-
-The @var{key-regexp} argument can refer to the text matched by a
-subexpression of @var{record-regexp}, or it can be a regular expression
-on its own.
-
-If @var{key-regexp} is:
-
-@table @asis
-@item @samp{\@var{digit}}
-then the text matched by the @var{digit}th @samp{\(...\)} parenthesis
-grouping in @var{record-regexp} is the sort key.
-
-@item @samp{\&}
-then the whole record is the sort key.
-
-@item a regular expression
-then @code{sort-regexp-fields} searches for a match for the regular
-expression within the record. If such a match is found, it is the sort
-key. If there is no match for @var{key-regexp} within a record then
-that record is ignored, which means its position in the buffer is not
-changed. (The other records may move around it.)
-@end table
-
-For example, if you plan to sort all the lines in the region by the
-first word on each line starting with the letter @samp{f}, you should
-set @var{record-regexp} to @samp{^.*$} and set @var{key-regexp} to
-@samp{\<f\w*\>}. The resulting expression looks like this:
-
-@example
-@group
-(sort-regexp-fields nil "^.*$" "\\<f\\w*\\>"
- (region-beginning)
- (region-end))
-@end group
-@end example
-
-If you call @code{sort-regexp-fields} interactively, it prompts for
-@var{record-regexp} and @var{key-regexp} in the minibuffer.
-@end deffn
-
-@deffn Command sort-lines reverse start end
-This command alphabetically sorts lines in the region between
-@var{start} and @var{end}. If @var{reverse} is non-@code{nil}, the sort
-is in reverse order.
-@end deffn
-
-@deffn Command sort-paragraphs reverse start end
-This command alphabetically sorts paragraphs in the region between
-@var{start} and @var{end}. If @var{reverse} is non-@code{nil}, the sort
-is in reverse order.
-@end deffn
-
-@deffn Command sort-pages reverse start end
-This command alphabetically sorts pages in the region between
-@var{start} and @var{end}. If @var{reverse} is non-@code{nil}, the sort
-is in reverse order.
-@end deffn
-
-@deffn Command sort-fields field start end
-This command sorts lines in the region between @var{start} and
-@var{end}, comparing them alphabetically by the @var{field}th field
-of each line. Fields are separated by whitespace and numbered starting
-from 1. If @var{field} is negative, sorting is by the
-@w{@minus{}@var{field}th} field from the end of the line. This command
-is useful for sorting tables.
-@end deffn
-
-@deffn Command sort-numeric-fields field start end
-This command sorts lines in the region between @var{start} and
-@var{end}, comparing them numerically by the @var{field}th field of each
-line. The specified field must contain a number in each line of the
-region. Fields are separated by whitespace and numbered starting from
-1. If @var{field} is negative, sorting is by the
-@w{@minus{}@var{field}th} field from the end of the line. This command
-is useful for sorting tables.
-@end deffn
-
-@deffn Command sort-columns reverse &optional beg end
-This command sorts the lines in the region between @var{beg} and
-@var{end}, comparing them alphabetically by a certain range of columns.
-The column positions of @var{beg} and @var{end} bound the range of
-columns to sort on.
-
-If @var{reverse} is non-@code{nil}, the sort is in reverse order.
-
-One unusual thing about this command is that the entire line
-containing position @var{beg}, and the entire line containing position
-@var{end}, are included in the region sorted.
-
-Note that @code{sort-columns} uses the @code{sort} utility program,
-and so cannot work properly on text containing tab characters. Use
-@kbd{M-x @code{untabify}} to convert tabs to spaces before sorting.
-@end deffn
-
-@node Columns
-@comment node-name, next, previous, up
-@section Counting Columns
-@cindex columns
-@cindex counting columns
-@cindex horizontal position
-
- The column functions convert between a character position (counting
-characters from the beginning of the buffer) and a column position
-(counting screen characters from the beginning of a line).
-
- A character counts according to the number of columns it occupies on
-the screen. This means control characters count as occupying 2 or 4
-columns, depending upon the value of @code{ctl-arrow}, and tabs count as
-occupying a number of columns that depends on the value of
-@code{tab-width} and on the column where the tab begins. @xref{Usual Display}.
-
- Column number computations ignore the width of the window and the
-amount of horizontal scrolling. Consequently, a column value can be
-arbitrarily high. The first (or leftmost) column is numbered 0.
-
-@defun current-column
-This function returns the horizontal position of point, measured in
-columns, counting from 0 at the left margin. The column position is the
-sum of the widths of all the displayed representations of the characters
-between the start of the current line and point.
-
-For an example of using @code{current-column}, see the description of
-@code{count-lines} in @ref{Text Lines}.
-@end defun
-
-@defun move-to-column column &optional force
-This function moves point to @var{column} in the current line. The
-calculation of @var{column} takes into account the widths of the
-displayed representations of the characters between the start of the
-line and point.
-
-If column @var{column} is beyond the end of the line, point moves to the
-end of the line. If @var{column} is negative, point moves to the
-beginning of the line.
-
-If it is impossible to move to column @var{column} because that is in
-the middle of a multicolumn character such as a tab, point moves to the
-end of that character. However, if @var{force} is non-@code{nil}, and
-@var{column} is in the middle of a tab, then @code{move-to-column}
-converts the tab into spaces so that it can move precisely to column
-@var{column}. Other multicolumn characters can cause anomalies despite
-@var{force}, since there is no way to split them.
-
-The argument @var{force} also has an effect if the line isn't long
-enough to reach column @var{column}; in that case, it says to add
-whitespace at the end of the line to reach that column.
-
-If @var{column} is not an integer, an error is signaled.
-
-The return value is the column number actually moved to.
-@end defun
-
-@node Indentation
-@section Indentation
-@cindex indentation
-
- The indentation functions are used to examine, move to, and change
-whitespace that is at the beginning of a line. Some of the functions
-can also change whitespace elsewhere on a line. Columns and indentation
-count from zero at the left margin.
-
-@menu
-* Primitive Indent:: Functions used to count and insert indentation.
-* Mode-Specific Indent:: Customize indentation for different modes.
-* Region Indent:: Indent all the lines in a region.
-* Relative Indent:: Indent the current line based on previous lines.
-* Indent Tabs:: Adjustable, typewriter-like tab stops.
-* Motion by Indent:: Move to first non-blank character.
-@end menu
-
-@node Primitive Indent
-@subsection Indentation Primitives
-
- This section describes the primitive functions used to count and
-insert indentation. The functions in the following sections use these
-primitives.
-
-@defun current-indentation
-@comment !!Type Primitive Function
-@comment !!SourceFile indent.c
-This function returns the indentation of the current line, which is
-the horizontal position of the first nonblank character. If the
-contents are entirely blank, then this is the horizontal position of the
-end of the line.
-@end defun
-
-@deffn Command indent-to column &optional minimum
-@comment !!Type Primitive Function
-@comment !!SourceFile indent.c
-This function indents from point with tabs and spaces until @var{column}
-is reached. If @var{minimum} is specified and non-@code{nil}, then at
-least that many spaces are inserted even if this requires going beyond
-@var{column}. Otherwise the function does nothing if point is already
-beyond @var{column}. The value is the column at which the inserted
-indentation ends.
-
-The inserted whitespace characters inherit text properties from the
-surrounding text (usually, from the preceding text only). @xref{Sticky
-Properties}.
-@end deffn
-
-@defopt indent-tabs-mode
-@comment !!SourceFile indent.c
-If this variable is non-@code{nil}, indentation functions can insert
-tabs as well as spaces. Otherwise, they insert only spaces. Setting
-this variable automatically makes it local to the current buffer.
-@end defopt
-
-@node Mode-Specific Indent
-@subsection Indentation Controlled by Major Mode
-
- An important function of each major mode is to customize the @key{TAB}
-key to indent properly for the language being edited. This section
-describes the mechanism of the @key{TAB} key and how to control it.
-The functions in this section return unpredictable values.
-
-@defvar indent-line-function
-This variable's value is the function to be used by @key{TAB} (and
-various commands) to indent the current line. The command
-@code{indent-according-to-mode} does no more than call this function.
-
-In Lisp mode, the value is the symbol @code{lisp-indent-line}; in C
-mode, @code{c-indent-line}; in Fortran mode, @code{fortran-indent-line}.
-In Fundamental mode, Text mode, and many other modes with no standard
-for indentation, the value is @code{indent-to-left-margin} (which is the
-default value).
-@end defvar
-
-@deffn Command indent-according-to-mode
-This command calls the function in @code{indent-line-function} to
-indent the current line in a way appropriate for the current major mode.
-@end deffn
-
-@deffn Command indent-for-tab-command
-This command calls the function in @code{indent-line-function} to indent
-the current line; except that if that function is
-@code{indent-to-left-margin}, it calls @code{insert-tab} instead. (That
-is a trivial command that inserts a tab character.)
-@end deffn
-
-@deffn Command newline-and-indent
-@comment !!SourceFile simple.el
-This function inserts a newline, then indents the new line (the one
-following the newline just inserted) according to the major mode.
-
-It does indentation by calling the current @code{indent-line-function}.
-In programming language modes, this is the same thing @key{TAB} does,
-but in some text modes, where @key{TAB} inserts a tab,
-@code{newline-and-indent} indents to the column specified by
-@code{left-margin}.
-@end deffn
-
-@deffn Command reindent-then-newline-and-indent
-@comment !!SourceFile simple.el
-This command reindents the current line, inserts a newline at point,
-and then reindents the new line (the one following the newline just
-inserted).
-
-This command does indentation on both lines according to the current
-major mode, by calling the current value of @code{indent-line-function}.
-In programming language modes, this is the same thing @key{TAB} does,
-but in some text modes, where @key{TAB} inserts a tab,
-@code{reindent-then-newline-and-indent} indents to the column specified
-by @code{left-margin}.
-@end deffn
-
-@node Region Indent
-@subsection Indenting an Entire Region
-
- This section describes commands that indent all the lines in the
-region. They return unpredictable values.
-
-@deffn Command indent-region start end to-column
-This command indents each nonblank line starting between @var{start}
-(inclusive) and @var{end} (exclusive). If @var{to-column} is
-@code{nil}, @code{indent-region} indents each nonblank line by calling
-the current mode's indentation function, the value of
-@code{indent-line-function}.
-
-If @var{to-column} is non-@code{nil}, it should be an integer
-specifying the number of columns of indentation; then this function
-gives each line exactly that much indentation, by either adding or
-deleting whitespace.
-
-If there is a fill prefix, @code{indent-region} indents each line
-by making it start with the fill prefix.
-@end deffn
-
-@defvar indent-region-function
-The value of this variable is a function that can be used by
-@code{indent-region} as a short cut. You should design the function so
-that it will produce the same results as indenting the lines of the
-region one by one, but presumably faster.
-
-If the value is @code{nil}, there is no short cut, and
-@code{indent-region} actually works line by line.
-
-A short-cut function is useful in modes such as C mode and Lisp mode,
-where the @code{indent-line-function} must scan from the beginning of
-the function definition: applying it to each line would be quadratic in
-time. The short cut can update the scan information as it moves through
-the lines indenting them; this takes linear time. In a mode where
-indenting a line individually is fast, there is no need for a short cut.
-
-@code{indent-region} with a non-@code{nil} argument @var{to-column} has
-a different meaning and does not use this variable.
-@end defvar
-
-@deffn Command indent-rigidly start end count
-@comment !!SourceFile indent.el
-This command indents all lines starting between @var{start}
-(inclusive) and @var{end} (exclusive) sideways by @var{count} columns.
-This ``preserves the shape'' of the affected region, moving it as a
-rigid unit. Consequently, this command is useful not only for indenting
-regions of unindented text, but also for indenting regions of formatted
-code.
-
-For example, if @var{count} is 3, this command adds 3 columns of
-indentation to each of the lines beginning in the region specified.
-
-In Mail mode, @kbd{C-c C-y} (@code{mail-yank-original}) uses
-@code{indent-rigidly} to indent the text copied from the message being
-replied to.
-@end deffn
-
-@defun indent-code-rigidly start end columns &optional nochange-regexp
-This is like @code{indent-rigidly}, except that it doesn't alter lines
-that start within strings or comments.
-
-In addition, it doesn't alter a line if @var{nochange-regexp} matches at
-the beginning of the line (if @var{nochange-regexp} is non-@code{nil}).
-@end defun
-
-@node Relative Indent
-@subsection Indentation Relative to Previous Lines
-
- This section describes two commands that indent the current line
-based on the contents of previous lines.
-
-@deffn Command indent-relative &optional unindented-ok
-This command inserts whitespace at point, extending to the same
-column as the next @dfn{indent point} of the previous nonblank line. An
-indent point is a non-whitespace character following whitespace. The
-next indent point is the first one at a column greater than the current
-column of point. For example, if point is underneath and to the left of
-the first non-blank character of a line of text, it moves to that column
-by inserting whitespace.
-
-If the previous nonblank line has no next indent point (i.e., none at a
-great enough column position), @code{indent-relative} either does
-nothing (if @var{unindented-ok} is non-@code{nil}) or calls
-@code{tab-to-tab-stop}. Thus, if point is underneath and to the right
-of the last column of a short line of text, this command ordinarily
-moves point to the next tab stop by inserting whitespace.
-
-The return value of @code{indent-relative} is unpredictable.
-
-In the following example, point is at the beginning of the second
-line:
-
-@example
-@group
- This line is indented twelve spaces.
-@point{}The quick brown fox jumped.
-@end group
-@end example
-
-@noindent
-Evaluation of the expression @code{(indent-relative nil)} produces the
-following:
-
-@example
-@group
- This line is indented twelve spaces.
- @point{}The quick brown fox jumped.
-@end group
-@end example
-
- In this example, point is between the @samp{m} and @samp{p} of
-@samp{jumped}:
-
-@example
-@group
- This line is indented twelve spaces.
-The quick brown fox jum@point{}ped.
-@end group
-@end example
-
-@noindent
-Evaluation of the expression @code{(indent-relative nil)} produces the
-following:
-
-@example
-@group
- This line is indented twelve spaces.
-The quick brown fox jum @point{}ped.
-@end group
-@end example
-@end deffn
-
-@deffn Command indent-relative-maybe
-@comment !!SourceFile indent.el
-This command indents the current line like the previous nonblank line.
-It calls @code{indent-relative} with @code{t} as the @var{unindented-ok}
-argument. The return value is unpredictable.
-
-If the previous nonblank line has no indent points beyond the current
-column, this command does nothing.
-@end deffn
-
-@node Indent Tabs
-@comment node-name, next, previous, up
-@subsection Adjustable ``Tab Stops''
-@cindex tabs stops for indentation
-
- This section explains the mechanism for user-specified ``tab stops''
-and the mechanisms that use and set them. The name ``tab stops'' is
-used because the feature is similar to that of the tab stops on a
-typewriter. The feature works by inserting an appropriate number of
-spaces and tab characters to reach the next tab stop column; it does not
-affect the display of tab characters in the buffer (@pxref{Usual
-Display}). Note that the @key{TAB} character as input uses this tab
-stop feature only in a few major modes, such as Text mode.
-
-@deffn Command tab-to-tab-stop
-This command inserts spaces or tabs up to the next tab stop column
-defined by @code{tab-stop-list}. It searches the list for an element
-greater than the current column number, and uses that element as the
-column to indent to. It does nothing if no such element is found.
-@end deffn
-
-@defopt tab-stop-list
-This variable is the list of tab stop columns used by
-@code{tab-to-tab-stops}. The elements should be integers in increasing
-order. The tab stop columns need not be evenly spaced.
-
-Use @kbd{M-x edit-tab-stops} to edit the location of tab stops
-interactively.
-@end defopt
-
-@node Motion by Indent
-@subsection Indentation-Based Motion Commands
-
- These commands, primarily for interactive use, act based on the
-indentation in the text.
-
-@deffn Command back-to-indentation
-@comment !!SourceFile simple.el
-This command moves point to the first non-whitespace character in the
-current line (which is the line in which point is located). It returns
-@code{nil}.
-@end deffn
-
-@deffn Command backward-to-indentation arg
-@comment !!SourceFile simple.el
-This command moves point backward @var{arg} lines and then to the
-first nonblank character on that line. It returns @code{nil}.
-@end deffn
-
-@deffn Command forward-to-indentation arg
-@comment !!SourceFile simple.el
-This command moves point forward @var{arg} lines and then to the first
-nonblank character on that line. It returns @code{nil}.
-@end deffn
-
-@node Case Changes
-@comment node-name, next, previous, up
-@section Case Changes
-@cindex case changes
-
- The case change commands described here work on text in the current
-buffer. @xref{Character Case}, for case conversion commands that work
-on strings and characters. @xref{Case Table}, for how to customize
-which characters are upper or lower case and how to convert them.
-
-@deffn Command capitalize-region start end
-This function capitalizes all words in the region defined by
-@var{start} and @var{end}. To capitalize means to convert each word's
-first character to upper case and convert the rest of each word to lower
-case. The function returns @code{nil}.
-
-If one end of the region is in the middle of a word, the part of the
-word within the region is treated as an entire word.
-
-When @code{capitalize-region} is called interactively, @var{start} and
-@var{end} are point and the mark, with the smallest first.
-
-@example
-@group
----------- Buffer: foo ----------
-This is the contents of the 5th foo.
----------- Buffer: foo ----------
-@end group
-
-@group
-(capitalize-region 1 44)
-@result{} nil
-
----------- Buffer: foo ----------
-This Is The Contents Of The 5th Foo.
----------- Buffer: foo ----------
-@end group
-@end example
-@end deffn
-
-@deffn Command downcase-region start end
-This function converts all of the letters in the region defined by
-@var{start} and @var{end} to lower case. The function returns
-@code{nil}.
-
-When @code{downcase-region} is called interactively, @var{start} and
-@var{end} are point and the mark, with the smallest first.
-@end deffn
-
-@deffn Command upcase-region start end
-This function converts all of the letters in the region defined by
-@var{start} and @var{end} to upper case. The function returns
-@code{nil}.
-
-When @code{upcase-region} is called interactively, @var{start} and
-@var{end} are point and the mark, with the smallest first.
-@end deffn
-
-@deffn Command capitalize-word count
-This function capitalizes @var{count} words after point, moving point
-over as it does. To capitalize means to convert each word's first
-character to upper case and convert the rest of each word to lower case.
-If @var{count} is negative, the function capitalizes the
-@minus{}@var{count} previous words but does not move point. The value
-is @code{nil}.
-
-If point is in the middle of a word, the part of the word before point
-is ignored when moving forward. The rest is treated as an entire word.
-
-When @code{capitalize-word} is called interactively, @var{count} is
-set to the numeric prefix argument.
-@end deffn
-
-@deffn Command downcase-word count
-This function converts the @var{count} words after point to all lower
-case, moving point over as it does. If @var{count} is negative, it
-converts the @minus{}@var{count} previous words but does not move point.
-The value is @code{nil}.
-
-When @code{downcase-word} is called interactively, @var{count} is set
-to the numeric prefix argument.
-@end deffn
-
-@deffn Command upcase-word count
-This function converts the @var{count} words after point to all upper
-case, moving point over as it does. If @var{count} is negative, it
-converts the @minus{}@var{count} previous words but does not move point.
-The value is @code{nil}.
-
-When @code{upcase-word} is called interactively, @var{count} is set to
-the numeric prefix argument.
-@end deffn
-
-@node Text Properties
-@section Text Properties
-@cindex text properties
-@cindex attributes of text
-@cindex properties of text
-
- Each character position in a buffer or a string can have a @dfn{text
-property list}, much like the property list of a symbol (@pxref{Property
-Lists}). The properties belong to a particular character at a
-particular place, such as, the letter @samp{T} at the beginning of this
-sentence or the first @samp{o} in @samp{foo}---if the same character
-occurs in two different places, the two occurrences generally have
-different properties.
-
- Each property has a name and a value. Both of these can be any Lisp
-object, but the name is normally a symbol. The usual way to access the
-property list is to specify a name and ask what value corresponds to it.
-
- If a character has a @code{category} property, we call it the
-@dfn{category} of the character. It should be a symbol. The properties
-of the symbol serve as defaults for the properties of the character.
-
- Copying text between strings and buffers preserves the properties
-along with the characters; this includes such diverse functions as
-@code{substring}, @code{insert}, and @code{buffer-substring}.
-
-@menu
-* Examining Properties:: Looking at the properties of one character.
-* Changing Properties:: Setting the properties of a range of text.
-* Property Search:: Searching for where a property changes value.
-* Special Properties:: Particular properties with special meanings.
-* Format Properties:: Properties for representing formatting of text.
-* Sticky Properties:: How inserted text gets properties from
- neighboring text.
-* Saving Properties:: Saving text properties in files, and reading
- them back.
-* Lazy Properties:: Computing text properties in a lazy fashion
- only when text is examined.
-* Not Intervals:: Why text properties do not use
- Lisp-visible text intervals.
-@end menu
-
-@node Examining Properties
-@subsection Examining Text Properties
-
- The simplest way to examine text properties is to ask for the value of
-a particular property of a particular character. For that, use
-@code{get-text-property}. Use @code{text-properties-at} to get the
-entire property list of a character. @xref{Property Search}, for
-functions to examine the properties of a number of characters at once.
-
- These functions handle both strings and buffers. Keep in mind that
-positions in a string start from 0, whereas positions in a buffer start
-from 1.
-
-@defun get-text-property pos prop &optional object
-This function returns the value of the @var{prop} property of the
-character after position @var{pos} in @var{object} (a buffer or
-string). The argument @var{object} is optional and defaults to the
-current buffer.
-
-If there is no @var{prop} property strictly speaking, but the character
-has a category that is a symbol, then @code{get-text-property} returns
-the @var{prop} property of that symbol.
-@end defun
-
-@defun get-char-property pos prop &optional object
-This function is like @code{get-text-property}, except that it checks
-overlays first and then text properties. @xref{Overlays}.
-
-The argument @var{object} may be a string, a buffer, or a window. If it
-is a window, then the buffer displayed in that window is used for text
-properties and overlays, but only the overlays active for that window
-are considered. If @var{object} is a buffer, then all overlays in that
-buffer are considered, as well as text properties. If @var{object} is a
-string, only text properties are considered, since strings never have
-overlays.
-@end defun
-
-@defun text-properties-at position &optional object
-This function returns the entire property list of the character at
-@var{position} in the string or buffer @var{object}. If @var{object} is
-@code{nil}, it defaults to the current buffer.
-@end defun
-
-@defvar default-text-properties
-This variable holds a property list giving default values for text
-properties. Whenever a character does not specify a value for a
-property, neither directly nor through a category symbol, the value
-stored in this list is used instead. Here is an example:
-
-@example
-(setq default-text-properties '(foo 69))
-;; @r{Make sure character 1 has no properties of its own.}
-(set-text-properties 1 2 nil)
-;; @r{What we get, when we ask, is the default value.}
-(get-text-property 1 'foo)
- @result{} 69
-@end example
-@end defvar
-
-@node Changing Properties
-@subsection Changing Text Properties
-
- The primitives for changing properties apply to a specified range of
-text. The function @code{set-text-properties} (see end of section) sets
-the entire property list of the text in that range; more often, it is
-useful to add, change, or delete just certain properties specified by
-name.
-
- Since text properties are considered part of the buffer's contents, and
-can affect how the buffer looks on the screen, any change in the text
-properties is considered a buffer modification. Buffer text property
-changes are undoable (@pxref{Undo}).
-
-@defun put-text-property start end prop value &optional object
-This function sets the @var{prop} property to @var{value} for the text
-between @var{start} and @var{end} in the string or buffer @var{object}.
-If @var{object} is @code{nil}, it defaults to the current buffer.
-@end defun
-
-@defun add-text-properties start end props &optional object
-This function modifies the text properties for the text between
-@var{start} and @var{end} in the string or buffer @var{object}. If
-@var{object} is @code{nil}, it defaults to the current buffer.
-
-The argument @var{props} specifies which properties to change. It
-should have the form of a property list (@pxref{Property Lists}): a list
-whose elements include the property names followed alternately by the
-corresponding values.
-
-The return value is @code{t} if the function actually changed some
-property's value; @code{nil} otherwise (if @var{props} is @code{nil} or
-its values agree with those in the text).
-
-For example, here is how to set the @code{comment} and @code{face}
-properties of a range of text:
-
-@example
-(add-text-properties @var{start} @var{end}
- '(comment t face highlight))
-@end example
-@end defun
-
-@defun remove-text-properties start end props &optional object
-This function deletes specified text properties from the text between
-@var{start} and @var{end} in the string or buffer @var{object}. If
-@var{object} is @code{nil}, it defaults to the current buffer.
-
-The argument @var{props} specifies which properties to delete. It
-should have the form of a property list (@pxref{Property Lists}): a list
-whose elements are property names alternating with corresponding values.
-But only the names matter---the values that accompany them are ignored.
-For example, here's how to remove the @code{face} property.
-
-@example
-(remove-text-properties @var{start} @var{end} '(face nil))
-@end example
-
-The return value is @code{t} if the function actually changed some
-property's value; @code{nil} otherwise (if @var{props} is @code{nil} or
-if no character in the specified text had any of those properties).
-@end defun
-
-@defun set-text-properties start end props &optional object
-This function completely replaces the text property list for the text
-between @var{start} and @var{end} in the string or buffer @var{object}.
-If @var{object} is @code{nil}, it defaults to the current buffer.
-
-The argument @var{props} is the new property list. It should be a list
-whose elements are property names alternating with corresponding values.
-
-After @code{set-text-properties} returns, all the characters in the
-specified range have identical properties.
-
-If @var{props} is @code{nil}, the effect is to get rid of all properties
-from the specified range of text. Here's an example:
-
-@example
-(set-text-properties @var{start} @var{end} nil)
-@end example
-@end defun
-
-See also the function @code{buffer-substring-no-properties}
-(@pxref{Buffer Contents}) which copies text from the buffer
-but does not copy its properties.
-
-@node Property Search
-@subsection Property Search Functions
-
-In typical use of text properties, most of the time several or many
-consecutive characters have the same value for a property. Rather than
-writing your programs to examine characters one by one, it is much
-faster to process chunks of text that have the same property value.
-
-Here are functions you can use to do this. They use @code{eq} for
-comparing property values. In all cases, @var{object} defaults to the
-current buffer.
-
-For high performance, it's very important to use the @var{limit}
-argument to these functions, especially the ones that search for a
-single property---otherwise, they may spend a long time scanning to the
-end of the buffer, if the property you are interested in does not change.
-
-Remember that a position is always between two characters; the position
-returned by these functions is between two characters with different
-properties.
-
-@defun next-property-change pos &optional object limit
-The function scans the text forward from position @var{pos} in the
-string or buffer @var{object} till it finds a change in some text
-property, then returns the position of the change. In other words, it
-returns the position of the first character beyond @var{pos} whose
-properties are not identical to those of the character just after
-@var{pos}.
-
-If @var{limit} is non-@code{nil}, then the scan ends at position
-@var{limit}. If there is no property change before that point,
-@code{next-property-change} returns @var{limit}.
-
-The value is @code{nil} if the properties remain unchanged all the way
-to the end of @var{object} and @var{limit} is @code{nil}. If the value
-is non-@code{nil}, it is a position greater than or equal to @var{pos}.
-The value equals @var{pos} only when @var{limit} equals @var{pos}.
-
-Here is an example of how to scan the buffer by chunks of text within
-which all properties are constant:
-
-@smallexample
-(while (not (eobp))
- (let ((plist (text-properties-at (point)))
- (next-change
- (or (next-property-change (point) (current-buffer))
- (point-max))))
- @r{Process text from point to @var{next-change}@dots{}}
- (goto-char next-change)))
-@end smallexample
-@end defun
-
-@defun next-single-property-change pos prop &optional object limit
-The function scans the text forward from position @var{pos} in the
-string or buffer @var{object} till it finds a change in the @var{prop}
-property, then returns the position of the change. In other words, it
-returns the position of the first character beyond @var{pos} whose
-@var{prop} property differs from that of the character just after
-@var{pos}.
-
-If @var{limit} is non-@code{nil}, then the scan ends at position
-@var{limit}. If there is no property change before that point,
-@code{next-single-property-change} returns @var{limit}.
-
-The value is @code{nil} if the property remains unchanged all the way to
-the end of @var{object} and @var{limit} is @code{nil}. If the value is
-non-@code{nil}, it is a position greater than or equal to @var{pos}; it
-equals @var{pos} only if @var{limit} equals @var{pos}.
-@end defun
-
-@defun previous-property-change pos &optional object limit
-This is like @code{next-property-change}, but scans back from @var{pos}
-instead of forward. If the value is non-@code{nil}, it is a position
-less than or equal to @var{pos}; it equals @var{pos} only if @var{limit}
-equals @var{pos}.
-@end defun
-
-@defun previous-single-property-change pos prop &optional object limit
-This is like @code{next-single-property-change}, but scans back from
-@var{pos} instead of forward. If the value is non-@code{nil}, it is a
-position less than or equal to @var{pos}; it equals @var{pos} only if
-@var{limit} equals @var{pos}.
-@end defun
-
-@defun text-property-any start end prop value &optional object
-This function returns non-@code{nil} if at least one character between
-@var{start} and @var{end} has a property @var{prop} whose value is
-@var{value}. More precisely, it returns the position of the first such
-character. Otherwise, it returns @code{nil}.
-
-The optional fifth argument, @var{object}, specifies the string or
-buffer to scan. Positions are relative to @var{object}. The default
-for @var{object} is the current buffer.
-@end defun
-
-@defun text-property-not-all start end prop value &optional object
-This function returns non-@code{nil} if at least one character between
-@var{start} and @var{end} has a property @var{prop} whose value differs
-from @var{value}. More precisely, it returns the position of the
-first such character. Otherwise, it returns @code{nil}.
-
-The optional fifth argument, @var{object}, specifies the string or
-buffer to scan. Positions are relative to @var{object}. The default
-for @var{object} is the current buffer.
-@end defun
-
-@node Special Properties
-@subsection Properties with Special Meanings
-
- Here is a table of text property names that have special built-in
-meanings. The following section lists a few more special property names
-that are used to control filling. All other names have no standard
-meaning, and you can use them as you like.
-
-@table @code
-@cindex category of text character
-@kindex category @r{(text property)}
-@item category
-If a character has a @code{category} property, we call it the
-@dfn{category} of the character. It should be a symbol. The properties
-of the symbol serve as defaults for the properties of the character.
-
-@item face
-@cindex face codes of text
-@kindex face @r{(text property)}
-You can use the property @code{face} to control the font and color of
-text. Its value is a face name or a list of face names. @xref{Faces},
-for more information. This feature may be temporary; in the future, we
-may replace it with other ways of specifying how to display text.
-
-@item mouse-face
-@kindex mouse-face @r{(text property)}
-The property @code{mouse-face} is used instead of @code{face} when the
-mouse is on or near the character. For this purpose, ``near'' means
-that all text between the character and where the mouse is have the same
-@code{mouse-face} property value.
-
-@item local-map
-@cindex keymap of character
-@kindex local-map @r{(text property)}
-You can specify a different keymap for a portion of the text by means of
-a @code{local-map} property. The property's value for the character
-after point, if non-@code{nil}, replaces the buffer's local map.
-@xref{Active Keymaps}.
-
-@item read-only
-@cindex read-only character
-@kindex read-only @r{(text property)}
-If a character has the property @code{read-only}, then modifying that
-character is not allowed. Any command that would do so gets an error.
-
-Insertion next to a read-only character is an error if inserting
-ordinary text there would inherit the @code{read-only} property due to
-stickiness. Thus, you can control permission to insert next to
-read-only text by controlling the stickiness. @xref{Sticky Properties}.
-
-Since changing properties counts as modifying the buffer, it is not
-possible to remove a @code{read-only} property unless you know the
-special trick: bind @code{inhibit-read-only} to a non-@code{nil} value
-and then remove the property. @xref{Read Only Buffers}.
-
-@item invisible
-@kindex invisible @r{(text property)}
-A non-@code{nil} @code{invisible} property can make a character invisible
-on the screen. @xref{Invisible Text}, for details.
-
-@item intangible
-@kindex intangible @r{(text property)}
-If a group of consecutive characters have equal and non-@code{nil}
-@code{intangible} properties, then you cannot place point between them.
-If you try to move point forward into the group, point actually moves to
-the end of the group. If you try to move point backward into the group,
-point actually moves to the start of the group.
-
-When the variable @code{inhibit-point-motion-hooks} is non-@code{nil},
-the @code{intangible} property is ignored.
-
-@item modification-hooks
-@cindex change hooks for a character
-@cindex hooks for changing a character
-@kindex modification-hooks @r{(text property)}
-If a character has the property @code{modification-hooks}, then its
-value should be a list of functions; modifying that character calls all
-of those functions. Each function receives two arguments: the beginning
-and end of the part of the buffer being modified. Note that if a
-particular modification hook function appears on several characters
-being modified by a single primitive, you can't predict how many times
-the function will be called.
-
-@item insert-in-front-hooks
-@itemx insert-behind-hooks
-@kindex insert-in-front-hooks @r{(text property)}
-@kindex insert-behind-hooks @r{(text property)}
-The operation of inserting text in a buffer also calls the functions
-listed in the @code{insert-in-front-hooks} property of the following
-character and in the @code{insert-behind-hooks} property of the
-preceding character. These functions receive two arguments, the
-beginning and end of the inserted text. The functions are called
-@emph{after} the actual insertion takes place.
-
-See also @ref{Change Hooks}, for other hooks that are called
-when you change text in a buffer.
-
-@item point-entered
-@itemx point-left
-@cindex hooks for motion of point
-@kindex point-entered @r{(text property)}
-@kindex point-left @r{(text property)}
-The special properties @code{point-entered} and @code{point-left}
-record hook functions that report motion of point. Each time point
-moves, Emacs compares these two property values:
-
-@itemize @bullet
-@item
-the @code{point-left} property of the character after the old location,
-and
-@item
-the @code{point-entered} property of the character after the new
-location.
-@end itemize
-
-@noindent
-If these two values differ, each of them is called (if not @code{nil})
-with two arguments: the old value of point, and the new one.
-
-The same comparison is made for the characters before the old and new
-locations. The result may be to execute two @code{point-left} functions
-(which may be the same function) and/or two @code{point-entered}
-functions (which may be the same function). In any case, all the
-@code{point-left} functions are called first, followed by all the
-@code{point-entered} functions.
-
-A primitive function may examine characters at various positions
-without moving point to those positions. Only an actual change in the
-value of point runs these hook functions.
-@end table
-
-@defvar inhibit-point-motion-hooks
-When this variable is non-@code{nil}, @code{point-left} and
-@code{point-entered} hooks are not run, and the @code{intangible}
-property has no effect.
-@end defvar
-
-@node Format Properties
-@subsection Formatted Text Properties
-
- These text properties affect the behavior of the fill commands. They
-are used for representing formatted text. @xref{Filling}, and
-@ref{Margins}.
-
-@table @code
-@item hard
-If a newline character has this property, it is a ``hard'' newline.
-The fill commands do not alter hard newlines and do not move words
-across them. However, this property takes effect only if the variable
-@code{use-hard-newlines} is non-@code{nil}.
-
-@item right-margin
-This property specifies an extra right margin for filling this part of the
-text.
-
-@item left-margin
-This property specifies an extra left margin for filling this part of the
-text.
-
-@item justification
-This property specifies the style of justification for filling this part
-of the text.
-@end table
-
-@node Sticky Properties
-@subsection Stickiness of Text Properties
-@cindex sticky text properties
-@cindex inheritance of text properties
-
- Self-inserting characters normally take on the same properties as the
-preceding character. This is called @dfn{inheritance} of properties.
-
- In a Lisp program, you can do insertion with inheritance or without,
-depending on your choice of insertion primitive. The ordinary text
-insertion functions such as @code{insert} do not inherit any properties.
-They insert text with precisely the properties of the string being
-inserted, and no others. This is correct for programs that copy text
-from one context to another---for example, into or out of the kill ring.
-To insert with inheritance, use the special primitives described in this
-section. Self-inserting characters inherit properties because they work
-using these primitives.
-
- When you do insertion with inheritance, @emph{which} properties are
-inherited depends on two specific properties: @code{front-sticky} and
-@code{rear-nonsticky}.
-
- Insertion after a character inherits those of its properties that are
-@dfn{rear-sticky}. Insertion before a character inherits those of its
-properties that are @dfn{front-sticky}. By default, a text property is
-rear-sticky but not front-sticky. Thus, the default is to inherit all
-the properties of the preceding character, and nothing from the
-following character. You can request different behavior by specifying
-the stickiness of certain properties.
-
- If a character's @code{front-sticky} property is @code{t}, then all
-its properties are front-sticky. If the @code{front-sticky} property is
-a list, then the sticky properties of the character are those whose
-names are in the list. For example, if a character has a
-@code{front-sticky} property whose value is @code{(face read-only)},
-then insertion before the character can inherit its @code{face} property
-and its @code{read-only} property, but no others.
-
- The @code{rear-nonsticky} works the opposite way. Every property is
-rear-sticky by default, so the @code{rear-nonsticky} property says which
-properties are @emph{not} rear-sticky. If a character's
-@code{rear-nonsticky} property is @code{t}, then none of its properties
-are rear-sticky. If the @code{rear-nonsticky} property is a list,
-properties are rear-sticky @emph{unless} their names are in the list.
-
- When you insert text with inheritance, it inherits all the rear-sticky
-properties of the preceding character, and all the front-sticky
-properties of the following character. The previous character's
-properties take precedence when both sides offer different sticky values
-for the same property.
-
- Here are the functions that insert text with inheritance of properties:
-
-@defun insert-and-inherit &rest strings
-Insert the strings @var{strings}, just like the function @code{insert},
-but inherit any sticky properties from the adjoining text.
-@end defun
-
-@defun insert-before-markers-and-inherit &rest strings
-Insert the strings @var{strings}, just like the function
-@code{insert-before-markers}, but inherit any sticky properties from the
-adjoining text.
-@end defun
-
-@node Saving Properties
-@subsection Saving Text Properties in Files
-@cindex text properties in files
-@cindex saving text properties
-
- You can save text properties in files, and restore text properties
-when inserting the files, using these two hooks:
-
-@defvar write-region-annotate-functions
-This variable's value is a list of functions for @code{write-region} to
-run to encode text properties in some fashion as annotations to the text
-being written in the file. @xref{Writing to Files}.
-
-Each function in the list is called with two arguments: the start and
-end of the region to be written. These functions should not alter the
-contents of the buffer. Instead, they should return lists indicating
-annotations to write in the file in addition to the text in the
-buffer.
-
-Each function should return a list of elements of the form
-@code{(@var{position} . @var{string})}, where @var{position} is an
-integer specifying the relative position in the text to be written, and
-@var{string} is the annotation to add there.
-
-Each list returned by one of these functions must be already sorted in
-increasing order by @var{position}. If there is more than one function,
-@code{write-region} merges the lists destructively into one sorted list.
-
-When @code{write-region} actually writes the text from the buffer to the
-file, it intermixes the specified annotations at the corresponding
-positions. All this takes place without modifying the buffer.
-@end defvar
-
-@defvar after-insert-file-functions
-This variable holds a list of functions for @code{insert-file-contents}
-to call after inserting a file's contents. These functions should scan
-the inserted text for annotations, and convert them to the text
-properties they stand for.
-
-Each function receives one argument, the length of the inserted text;
-point indicates the start of that text. The function should scan that
-text for annotations, delete them, and create the text properties that
-the annotations specify. The function should return the updated length
-of the inserted text, as it stands after those changes. The value
-returned by one function becomes the argument to the next function.
-
-These functions should always return with point at the beginning of
-the inserted text.
-
-The intended use of @code{after-insert-file-functions} is for converting
-some sort of textual annotations into actual text properties. But other
-uses may be possible.
-@end defvar
-
-We invite users to write Lisp programs to store and retrieve text
-properties in files, using these hooks, and thus to experiment with
-various data formats and find good ones. Eventually we hope users
-will produce good, general extensions we can install in Emacs.
-
-We suggest not trying to handle arbitrary Lisp objects as property
-names or property values---because a program that general is probably
-difficult to write, and slow. Instead, choose a set of possible data
-types that are reasonably flexible, and not too hard to encode.
-
-@xref{Format Conversion}, for a related feature.
-
-@c ??? In next edition, merge this info Format Conversion.
-
-@node Lazy Properties
-@subsection Lazy Computation of Text Properties
-
- Instead of computing text properties for all the text in the buffer,
-you can arrange to compute the text properties for parts of the text
-when and if something depends on them.
-
- The primitive that extracts text from the buffer along with its
-properties is @code{buffer-substring}. Before examining the properties,
-this function runs the abnormal hook @code{buffer-access-fontify-functions}.
-
-@defvar buffer-access-fontify-functions
-This variable holds a list of functions for computing text properties.
-Before @code{buffer-substring} copies the text and text properties for a
-portion of the buffer, it calls all the functions in this list. Each of
-the functions receives two arguments that specify the range of the
-buffer being accessed. (The buffer itself is always the current
-buffer.)
-@end defvar
-
- The function @code{buffer-substring-no-properties} does not call these
-functions, since it ignores text properties anyway.
-
- In order to prevent the hook functions from being called more than
-once for the same part of the buffer, you can use the variable
-@code{buffer-access-fontified-property}.
-
-@defvar buffer-access-fontified-property
-If this value's variable is non-@code{nil}, it is a symbol which is used
-as a text property name. A non-@code{nil} value for that text property
-means, ``the other text properties for this character have already been
-computed.''
-
-If all the characters in the range specified for @code{buffer-substring}
-have a non-@code{nil} value for this property, @code{buffer-substring}
-does not call the @code{buffer-access-fontify-functions} functions. It
-assumes these characters already have the right text properties, and
-just copies the properties they already have.
-
-The normal way to use this feature is that the
-@code{buffer-access-fontify-functions} functions add this property, as
-well as others, to the characters they operate on. That way, they avoid
-being called over and over for the same text.
-@end defvar
-
-@node Not Intervals
-@subsection Why Text Properties are not Intervals
-@cindex intervals
-
- Some editors that support adding attributes to text in the buffer do
-so by letting the user specify ``intervals'' within the text, and adding
-the properties to the intervals. Those editors permit the user or the
-programmer to determine where individual intervals start and end. We
-deliberately provided a different sort of interface in Emacs Lisp to
-avoid certain paradoxical behavior associated with text modification.
-
- If the actual subdivision into intervals is meaningful, that means you
-can distinguish between a buffer that is just one interval with a
-certain property, and a buffer containing the same text subdivided into
-two intervals, both of which have that property.
-
- Suppose you take the buffer with just one interval and kill part of
-the text. The text remaining in the buffer is one interval, and the
-copy in the kill ring (and the undo list) becomes a separate interval.
-Then if you yank back the killed text, you get two intervals with the
-same properties. Thus, editing does not preserve the distinction
-between one interval and two.
-
- Suppose we ``fix'' this problem by coalescing the two intervals when
-the text is inserted. That works fine if the buffer originally was a
-single interval. But suppose instead that we have two adjacent
-intervals with the same properties, and we kill the text of one interval
-and yank it back. The same interval-coalescence feature that rescues
-the other case causes trouble in this one: after yanking, we have just
-one interval. One again, editing does not preserve the distinction
-between one interval and two.
-
- Insertion of text at the border between intervals also raises
-questions that have no satisfactory answer.
-
- However, it is easy to arrange for editing to behave consistently for
-questions of the form, ``What are the properties of this character?''
-So we have decided these are the only questions that make sense; we have
-not implemented asking questions about where intervals start or end.
-
- In practice, you can usually use the property search functions in
-place of explicit interval boundaries. You can think of them as finding
-the boundaries of intervals, assuming that intervals are always
-coalesced whenever possible. @xref{Property Search}.
-
- Emacs also provides explicit intervals as a presentation feature; see
-@ref{Overlays}.
-
-@node Substitution
-@section Substituting for a Character Code
-
- The following functions replace characters within a specified region
-based on their character codes.
-
-@defun subst-char-in-region start end old-char new-char &optional noundo
-@cindex replace characters
-This function replaces all occurrences of the character @var{old-char}
-with the character @var{new-char} in the region of the current buffer
-defined by @var{start} and @var{end}.
-
-@cindex Outline mode
-@cindex undo avoidance
-If @var{noundo} is non-@code{nil}, then @code{subst-char-in-region} does
-not record the change for undo and does not mark the buffer as modified.
-This feature is used for controlling selective display (@pxref{Selective
-Display}).
-
-@code{subst-char-in-region} does not move point and returns
-@code{nil}.
-
-@example
-@group
----------- Buffer: foo ----------
-This is the contents of the buffer before.
----------- Buffer: foo ----------
-@end group
-
-@group
-(subst-char-in-region 1 20 ?i ?X)
- @result{} nil
-
----------- Buffer: foo ----------
-ThXs Xs the contents of the buffer before.
----------- Buffer: foo ----------
-@end group
-@end example
-@end defun
-
-@defun translate-region start end table
-This function applies a translation table to the characters in the
-buffer between positions @var{start} and @var{end}.
-
-The translation table @var{table} is a string; @code{(aref @var{table}
-@var{ochar})} gives the translated character corresponding to
-@var{ochar}. If the length of @var{table} is less than 256, any
-characters with codes larger than the length of @var{table} are not
-altered by the translation.
-
-The return value of @code{translate-region} is the number of
-characters that were actually changed by the translation. This does
-not count characters that were mapped into themselves in the
-translation table.
-@end defun
-
-@node Registers
-@section Registers
-@cindex registers
-
- A register is a sort of variable used in Emacs editing that can hold a
-marker, a string, a rectangle, a window configuration (of one frame), or
-a frame configuration (of all frames). Each register is named by a
-single character. All characters, including control and meta characters
-(but with the exception of @kbd{C-g}), can be used to name registers.
-Thus, there are 255 possible registers. A register is designated in
-Emacs Lisp by a character that is its name.
-
- The functions in this section return unpredictable values unless
-otherwise stated.
-@c Will change in version 19
-
-@defvar register-alist
-This variable is an alist of elements of the form @code{(@var{name} .
-@var{contents})}. Normally, there is one element for each Emacs
-register that has been used.
-
-The object @var{name} is a character (an integer) identifying the
-register. The object @var{contents} is a string, marker, or list
-representing the register contents. A string represents text stored in
-the register. A marker represents a position. A list represents a
-rectangle; its elements are strings, one per line of the rectangle.
-@end defvar
-
-@defun get-register reg
-This function returns the contents of the register
-@var{reg}, or @code{nil} if it has no contents.
-@end defun
-
-@defun set-register reg value
-This function sets the contents of register @var{reg} to @var{value}.
-A register can be set to any value, but the other register functions
-expect only certain data types. The return value is @var{value}.
-@end defun
-
-@deffn Command view-register reg
-This command displays what is contained in register @var{reg}.
-@end deffn
-
-@ignore
-@deffn Command point-to-register reg
-This command stores both the current location of point and the current
-buffer in register @var{reg} as a marker.
-@end deffn
-
-@deffn Command jump-to-register reg
-@deffnx Command register-to-point reg
-@comment !!SourceFile register.el
-This command restores the status recorded in register @var{reg}.
-
-If @var{reg} contains a marker, it moves point to the position stored in
-the marker. Since both the buffer and the location within the buffer
-are stored by the @code{point-to-register} function, this command can
-switch you to another buffer.
-
-If @var{reg} contains a window configuration or a frame configuration.
-@code{jump-to-register} restores that configuration.
-@end deffn
-@end ignore
-
-@deffn Command insert-register reg &optional beforep
-This command inserts contents of register @var{reg} into the current
-buffer.
-
-Normally, this command puts point before the inserted text, and the
-mark after it. However, if the optional second argument @var{beforep}
-is non-@code{nil}, it puts the mark before and point after.
-You can pass a non-@code{nil} second argument @var{beforep} to this
-function interactively by supplying any prefix argument.
-
-If the register contains a rectangle, then the rectangle is inserted
-with its upper left corner at point. This means that text is inserted
-in the current line and underneath it on successive lines.
-
-If the register contains something other than saved text (a string) or
-a rectangle (a list), currently useless things happen. This may be
-changed in the future.
-@end deffn
-
-@ignore
-@deffn Command copy-to-register reg start end &optional delete-flag
-This command copies the region from @var{start} to @var{end} into
-register @var{reg}. If @var{delete-flag} is non-@code{nil}, it deletes
-the region from the buffer after copying it into the register.
-@end deffn
-
-@deffn Command prepend-to-register reg start end &optional delete-flag
-This command prepends the region from @var{start} to @var{end} into
-register @var{reg}. If @var{delete-flag} is non-@code{nil}, it deletes
-the region from the buffer after copying it to the register.
-@end deffn
-
-@deffn Command append-to-register reg start end &optional delete-flag
-This command appends the region from @var{start} to @var{end} to the
-text already in register @var{reg}. If @var{delete-flag} is
-non-@code{nil}, it deletes the region from the buffer after copying it
-to the register.
-@end deffn
-
-@deffn Command copy-rectangle-to-register reg start end &optional delete-flag
-This command copies a rectangular region from @var{start} to @var{end}
-into register @var{reg}. If @var{delete-flag} is non-@code{nil}, it
-deletes the region from the buffer after copying it to the register.
-@end deffn
-
-@deffn Command window-configuration-to-register reg
-This function stores the window configuration of the selected frame in
-register @var{reg}.
-@end deffn
-
-@deffn Command frame-configuration-to-register reg
-This function stores the current frame configuration in register
-@var{reg}.
-@end deffn
-@end ignore
-
-@node Transposition
-@section Transposition of Text
-
- This subroutine is used by the transposition commands.
-
-@defun transpose-regions start1 end1 start2 end2 &optional leave-markers
-This function exchanges two nonoverlapping portions of the buffer.
-Arguments @var{start1} and @var{end1} specify the bounds of one portion
-and arguments @var{start2} and @var{end2} specify the bounds of the
-other portion.
-
-Normally, @code{transpose-regions} relocates markers with the transposed
-text; a marker previously positioned within one of the two transposed
-portions moves along with that portion, thus remaining between the same
-two characters in their new position. However, if @var{leave-markers}
-is non-@code{nil}, @code{transpose-regions} does not do this---it leaves
-all markers unrelocated.
-@end defun
-
-@node Change Hooks
-@section Change Hooks
-@cindex change hooks
-@cindex hooks for text changes
-
- These hook variables let you arrange to take notice of all changes in
-all buffers (or in a particular buffer, if you make them buffer-local).
-See also @ref{Special Properties}, for how to detect changes to specific
-parts of the text.
-
- The functions you use in these hooks should save and restore the match
-data if they do anything that uses regular expressions; otherwise, they
-will interfere in bizarre ways with the editing operations that call
-them.
-
-@defvar before-change-functions
-This variable holds a list of a functions to call before any buffer
-modification. Each function gets two arguments, the beginning and end
-of the region that is about to change, represented as integers. The
-buffer that is about to change is always the current buffer.
-@end defvar
-
-@defvar after-change-functions
-This variable holds a list of a functions to call after any buffer
-modification. Each function receives three arguments: the beginning and
-end of the region just changed, and the length of the text that existed
-before the change. (To get the current length, subtract the region
-beginning from the region end.) All three arguments are integers. The
-buffer that's about to change is always the current buffer.
-@end defvar
-
-@defvar before-change-function
-This obsolete variable holds one function to call before any buffer
-modification (or @code{nil} for no function). It is called just like
-the functions in @code{before-change-functions}.
-@end defvar
-
-@defvar after-change-function
-This obsolete variable holds one function to call after any buffer modification
-(or @code{nil} for no function). It is called just like the functions in
-@code{after-change-functions}.
-@end defvar
-
-The four variables above are temporarily bound to @code{nil} during the
-time that any of these functions is running. This means that if one of
-these functions changes the buffer, that change won't run these
-functions. If you do want a hook function to make changes that run
-these functions, make it bind these variables back to their usual
-values.
-
-One inconvenient result of this protective feature is that you cannot
-have a function in @code{after-change-functions} or
-@code{before-change-functions} which changes the value of that variable.
-But that's not a real limitation. If you want those functions to change
-the list of functions to run, simply add one fixed function to the hook,
-and code that function to look in another variable for other functions
-to call. Here is an example:
-
-@example
-(setq my-own-after-change-functions nil)
-(defun indirect-after-change-function (beg end len)
- (let ((list my-own-after-change-functions))
- (while list
- (funcall (car list) beg end len)
- (setq list (cdr list)))))
-(add-hooks 'after-change-functions
- 'indirect-after-change-function)
-@end example
-
-@defvar first-change-hook
-This variable is a normal hook that is run whenever a buffer is changed
-that was previously in the unmodified state.
-@end defvar
diff --git a/lispref/tips.texi b/lispref/tips.texi
deleted file mode 100644
index 1d797fb3ef9..00000000000
--- a/lispref/tips.texi
+++ /dev/null
@@ -1,683 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/tips
-@node Tips, GNU Emacs Internals, Calendar, Top
-@appendix Tips and Standards
-@cindex tips
-@cindex standards of coding style
-@cindex coding standards
-
- This chapter describes no additional features of Emacs Lisp.
-Instead it gives advice on making effective use of the features described
-in the previous chapters.
-
-@menu
-* Style Tips:: Writing clean and robust programs.
-* Compilation Tips:: Making compiled code run fast.
-* Documentation Tips:: Writing readable documentation strings.
-* Comment Tips:: Conventions for writing comments.
-* Library Headers:: Standard headers for library packages.
-@end menu
-
-@node Style Tips
-@section Writing Clean Lisp Programs
-
- Here are some tips for avoiding common errors in writing Lisp code
-intended for widespread use:
-
-@itemize @bullet
-@item
-Since all global variables share the same name space, and all functions
-share another name space, you should choose a short word to distinguish
-your program from other Lisp programs. Then take care to begin the
-names of all global variables, constants, and functions with the chosen
-prefix. This helps avoid name conflicts.
-
-This recommendation applies even to names for traditional Lisp
-primitives that are not primitives in Emacs Lisp---even to @code{cadr}.
-Believe it or not, there is more than one plausible way to define
-@code{cadr}. Play it safe; append your name prefix to produce a name
-like @code{foo-cadr} or @code{mylib-cadr} instead.
-
-If you write a function that you think ought to be added to Emacs under
-a certain name, such as @code{twiddle-files}, don't call it by that name
-in your program. Call it @code{mylib-twiddle-files} in your program,
-and send mail to @samp{bug-gnu-emacs@@prep.ai.mit.edu} suggesting we add
-it to Emacs. If and when we do, we can change the name easily enough.
-
-If one prefix is insufficient, your package may use two or three
-alternative common prefixes, so long as they make sense.
-
-Separate the prefix from the rest of the symbol name with a hyphen,
-@samp{-}. This will be consistent with Emacs itself and with most Emacs
-Lisp programs.
-
-@item
-It is often useful to put a call to @code{provide} in each separate
-library program, at least if there is more than one entry point to the
-program.
-
-@item
-If a file requires certain other library programs to be loaded
-beforehand, then the comments at the beginning of the file should say
-so. Also, use @code{require} to make sure they are loaded.
-
-@item
-If one file @var{foo} uses a macro defined in another file @var{bar},
-@var{foo} should contain this expression before the first use of the
-macro:
-
-@example
-(eval-when-compile (require '@var{bar}))
-@end example
-
-@noindent
-(And @var{bar} should contain @code{(provide '@var{bar})}, to make the
-@code{require} work.) This will cause @var{bar} to be loaded when you
-byte-compile @var{foo}. Otherwise, you risk compiling @var{foo} without
-the necessary macro loaded, and that would produce compiled code that
-won't work right. @xref{Compiling Macros}.
-
-Using @code{eval-when-compile} avoids loading @var{bar} when
-the compiled version of @var{foo} is @emph{used}.
-
-@item
-If you define a major mode, make sure to run a hook variable using
-@code{run-hooks}, just as the existing major modes do. @xref{Hooks}.
-
-@item
-If the purpose of a function is to tell you whether a certain condition
-is true or false, give the function a name that ends in @samp{p}. If
-the name is one word, add just @samp{p}; if the name is multiple words,
-add @samp{-p}. Examples are @code{framep} and @code{frame-live-p}.
-
-@item
-If a user option variable records a true-or-false condition, give it a
-name that ends in @samp{-flag}.
-
-@item
-Please do not define @kbd{C-c @var{letter}} as a key in your major
-modes. These sequences are reserved for users; they are the
-@strong{only} sequences reserved for users, so we cannot do without
-them.
-
-Instead, define sequences consisting of @kbd{C-c} followed by a control
-character, a digit, or certain punctuation characters. These sequences
-are reserved for major modes.
-
-Changing all the major modes in Emacs 18 so they would follow this
-convention was a lot of work. Abandoning this convention would make
-that work go to waste, and inconvenience users.
-
-@item
-Sequences consisting of @kbd{C-c} followed by @kbd{@{}, @kbd{@}},
-@kbd{<}, @kbd{>}, @kbd{:} or @kbd{;} are also reserved for major modes.
-
-@item
-Sequences consisting of @kbd{C-c} followed by any other punctuation
-character are allocated for minor modes. Using them in a major mode is
-not absolutely prohibited, but if you do that, the major mode binding
-may be shadowed from time to time by minor modes.
-
-@item
-You should not bind @kbd{C-h} following any prefix character (including
-@kbd{C-c}). If you don't bind @kbd{C-h}, it is automatically available
-as a help character for listing the subcommands of the prefix character.
-
-@item
-You should not bind a key sequence ending in @key{ESC} except following
-another @key{ESC}. (That is, it is ok to bind a sequence ending in
-@kbd{@key{ESC} @key{ESC}}.)
-
-The reason for this rule is that a non-prefix binding for @key{ESC} in
-any context prevents recognition of escape sequences as function keys in
-that context.
-
-@item
-Applications should not bind mouse events based on button 1 with the
-shift key held down. These events include @kbd{S-mouse-1},
-@kbd{M-S-mouse-1}, @kbd{C-S-mouse-1}, and so on. They are reserved for
-users.
-
-@item
-Modes should redefine @kbd{mouse-2} as a command to follow some sort of
-reference in the text of a buffer, if users usually would not want to
-alter the text in that buffer by hand. Modes such as Dired, Info,
-Compilation, and Occur redefine it in this way.
-
-@item
-When a package provides a modification of ordinary Emacs behavior, it is
-good to include a command to enable and disable the feature, Provide a
-command named @code{@var{whatever}-mode} which turns the feature on or
-off, and make it autoload (@pxref{Autoload}). Design the package so
-that simply loading it has no visible effect---that should not enable
-the feature. Users will request the feature by invoking the command.
-
-@item
-It is a bad idea to define aliases for the Emacs primitives. Use the
-standard names instead.
-
-@item
-Redefining an Emacs primitive is an even worse idea.
-It may do the right thing for a particular program, but
-there is no telling what other programs might break as a result.
-
-@item
-If a file does replace any of the functions or library programs of
-standard Emacs, prominent comments at the beginning of the file should
-say which functions are replaced, and how the behavior of the
-replacements differs from that of the originals.
-
-@item
-Please keep the names of your Emacs Lisp source files to 13 characters
-or less. This way, if the files are compiled, the compiled files' names
-will be 14 characters or less, which is short enough to fit on all kinds
-of Unix systems.
-
-@item
-Don't use @code{next-line} or @code{previous-line} in programs; nearly
-always, @code{forward-line} is more convenient as well as more
-predictable and robust. @xref{Text Lines}.
-
-@item
-Don't call functions that set the mark, unless setting the mark is one
-of the intended features of your program. The mark is a user-level
-feature, so it is incorrect to change the mark except to supply a value
-for the user's benefit. @xref{The Mark}.
-
-In particular, don't use these functions:
-
-@itemize @bullet
-@item
-@code{beginning-of-buffer}, @code{end-of-buffer}
-@item
-@code{replace-string}, @code{replace-regexp}
-@end itemize
-
-If you just want to move point, or replace a certain string, without any
-of the other features intended for interactive users, you can replace
-these functions with one or two lines of simple Lisp code.
-
-@item
-Use lists rather than vectors, except when there is a particular reason
-to use a vector. Lisp has more facilities for manipulating lists than
-for vectors, and working with lists is usually more convenient.
-
-Vectors are advantageous for tables that are substantial in size and are
-accessed in random order (not searched front to back), provided there is
-no need to insert or delete elements (only lists allow that).
-
-@item
-The recommended way to print a message in the echo area is with
-the @code{message} function, not @code{princ}. @xref{The Echo Area}.
-
-@item
-When you encounter an error condition, call the function @code{error}
-(or @code{signal}). The function @code{error} does not return.
-@xref{Signaling Errors}.
-
-Do not use @code{message}, @code{throw}, @code{sleep-for},
-or @code{beep} to report errors.
-
-@item
-An error message should start with a capital letter but should not end
-with a period.
-
-@item
-Many commands that take a long time to execute display a message that
-says @samp{Operating...} when they start, and change it to
-@samp{Operating...done} when they finish. Please keep the style of
-these messages uniform: @emph{no} space around the ellipsis, and
-@emph{no} period at the end.
-
-@item
-Try to avoid using recursive edits. Instead, do what the Rmail @kbd{e}
-command does: use a new local keymap that contains one command defined
-to switch back to the old local keymap. Or do what the
-@code{edit-options} command does: switch to another buffer and let the
-user switch back at will. @xref{Recursive Editing}.
-
-@item
-In some other systems there is a convention of choosing variable names
-that begin and end with @samp{*}. We don't use that convention in Emacs
-Lisp, so please don't use it in your programs. (Emacs uses such names
-only for program-generated buffers.) The users will find Emacs more
-coherent if all libraries use the same conventions.
-
-@item
-Try to avoid compiler warnings about undefined free variables, by adding
-@code{defvar} definitions for these variables.
-
-If you bind a variable in one function, and use it or set it in another
-function, the compiler warns about the latter function unless the
-variable has a definition. But often these variables have short names,
-and it is not clean for Lisp packages to define such variables names.
-Therefore, you should rename the variable to start with the name prefix
-used for the other functions and variables in your package.
-
-@item
-Indent each function with @kbd{C-M-q} (@code{indent-sexp}) using the
-default indentation parameters.
-
-@item
-Don't make a habit of putting close-parentheses on lines by themselves;
-Lisp programmers find this disconcerting. Once in a while, when there
-is a sequence of many consecutive close-parentheses, it may make sense
-to split them in one or two significant places.
-
-@item
-Please put a copyright notice on the file if you give copies to anyone.
-Use the same lines that appear at the top of the Lisp files in Emacs
-itself. If you have not signed papers to assign the copyright to the
-Foundation, then place your name in the copyright notice in place of the
-Foundation's name.
-@end itemize
-
-@node Compilation Tips
-@section Tips for Making Compiled Code Fast
-@cindex execution speed
-@cindex speedups
-
- Here are ways of improving the execution speed of byte-compiled
-Lisp programs.
-
-@itemize @bullet
-@item
-@cindex profiling
-@cindex timing programs
-@cindex @file{profile.el}
-Use the @file{profile} library to profile your program. See the file
-@file{profile.el} for instructions.
-
-@item
-Use iteration rather than recursion whenever possible.
-Function calls are slow in Emacs Lisp even when a compiled function
-is calling another compiled function.
-
-@item
-Using the primitive list-searching functions @code{memq}, @code{member},
-@code{assq}, or @code{assoc} is even faster than explicit iteration. It
-may be worth rearranging a data structure so that one of these primitive
-search functions can be used.
-
-@item
-Certain built-in functions are handled specially in byte-compiled code,
-avoiding the need for an ordinary function call. It is a good idea to
-use these functions rather than alternatives. To see whether a function
-is handled specially by the compiler, examine its @code{byte-compile}
-property. If the property is non-@code{nil}, then the function is
-handled specially.
-
-For example, the following input will show you that @code{aref} is
-compiled specially (@pxref{Array Functions}) while @code{elt} is not
-(@pxref{Sequence Functions}):
-
-@example
-@group
-(get 'aref 'byte-compile)
- @result{} byte-compile-two-args
-@end group
-
-@group
-(get 'elt 'byte-compile)
- @result{} nil
-@end group
-@end example
-
-@item
-If calling a small function accounts for a substantial part of your
-program's running time, make the function inline. This eliminates
-the function call overhead. Since making a function inline reduces
-the flexibility of changing the program, don't do it unless it gives
-a noticeable speedup in something slow enough that users care about
-the speed. @xref{Inline Functions}.
-@end itemize
-
-@node Documentation Tips
-@section Tips for Documentation Strings
-
- Here are some tips for the writing of documentation strings.
-
-@itemize @bullet
-@item
-Every command, function, or variable intended for users to know about
-should have a documentation string.
-
-@item
-An internal variable or subroutine of a Lisp program might as well have
-a documentation string. In earlier Emacs versions, you could save space
-by using a comment instead of a documentation string, but that is no
-longer the case.
-
-@item
-The first line of the documentation string should consist of one or two
-complete sentences that stand on their own as a summary. @kbd{M-x
-apropos} displays just the first line, and if it doesn't stand on its
-own, the result looks bad. In particular, start the first line with a
-capital letter and end with a period.
-
-The documentation string can have additional lines that expand on the
-details of how to use the function or variable. The additional lines
-should be made up of complete sentences also, but they may be filled if
-that looks good.
-
-@item
-For consistency, phrase the verb in the first sentence of a
-documentation string as an infinitive with ``to'' omitted. For
-instance, use ``Return the cons of A and B.'' in preference to ``Returns
-the cons of A and B@.'' Usually it looks good to do likewise for the
-rest of the first paragraph. Subsequent paragraphs usually look better
-if they have proper subjects.
-
-@item
-Write documentation strings in the active voice, not the passive, and in
-the present tense, not the future. For instance, use ``Return a list
-containing A and B.'' instead of ``A list containing A and B will be
-returned.''
-
-@item
-Avoid using the word ``cause'' (or its equivalents) unnecessarily.
-Instead of, ``Cause Emacs to display text in boldface,'' write just
-``Display text in boldface.''
-
-@item
-Do not start or end a documentation string with whitespace.
-
-@item
-Format the documentation string so that it fits in an Emacs window on an
-80-column screen. It is a good idea for most lines to be no wider than
-60 characters. The first line can be wider if necessary to fit the
-information that ought to be there.
-
-However, rather than simply filling the entire documentation string, you
-can make it much more readable by choosing line breaks with care.
-Use blank lines between topics if the documentation string is long.
-
-@item
-@strong{Do not} indent subsequent lines of a documentation string so
-that the text is lined up in the source code with the text of the first
-line. This looks nice in the source code, but looks bizarre when users
-view the documentation. Remember that the indentation before the
-starting double-quote is not part of the string!
-
-@item
-When the user tries to use a disabled command, Emacs displays just the
-first paragraph of its documentation string---everything through the
-first blank line. If you wish, you can choose which information to
-include before the first blank line so as to make this display useful.
-
-@item
-A variable's documentation string should start with @samp{*} if the
-variable is one that users would often want to set interactively. If
-the value is a long list, or a function, or if the variable would be set
-only in init files, then don't start the documentation string with
-@samp{*}. @xref{Defining Variables}.
-
-@item
-The documentation string for a variable that is a yes-or-no flag should
-start with words such as ``Non-nil means@dots{}'', to make it clear that
-all non-@code{nil} values are equivalent and indicate explicitly what
-@code{nil} and non-@code{nil} mean.
-
-@item
-When a function's documentation string mentions the value of an argument
-of the function, use the argument name in capital letters as if it were
-a name for that value. Thus, the documentation string of the function
-@code{/} refers to its second argument as @samp{DIVISOR}, because the
-actual argument name is @code{divisor}.
-
-Also use all caps for meta-syntactic variables, such as when you show
-the decomposition of a list or vector into subunits, some of which may
-vary.
-
-@item
-@iftex
-When a documentation string refers to a Lisp symbol, write it as it
-would be printed (which usually means in lower case), with single-quotes
-around it. For example: @samp{`lambda'}. There are two exceptions:
-write @code{t} and @code{nil} without single-quotes.
-@end iftex
-@ifinfo
-When a documentation string refers to a Lisp symbol, write it as it
-would be printed (which usually means in lower case), with single-quotes
-around it. For example: @samp{lambda}. There are two exceptions: write
-t and nil without single-quotes. (In this manual, we normally do use
-single-quotes for those symbols.)
-@end ifinfo
-
-@item
-Don't write key sequences directly in documentation strings. Instead,
-use the @samp{\\[@dots{}]} construct to stand for them. For example,
-instead of writing @samp{C-f}, write the construct
-@samp{\\[forward-char]}. When Emacs displays the documentation string,
-it substitutes whatever key is currently bound to @code{forward-char}.
-(This is normally @samp{C-f}, but it may be some other character if the
-user has moved key bindings.) @xref{Keys in Documentation}.
-
-@item
-In documentation strings for a major mode, you will want to refer to the
-key bindings of that mode's local map, rather than global ones.
-Therefore, use the construct @samp{\\<@dots{}>} once in the
-documentation string to specify which key map to use. Do this before
-the first use of @samp{\\[@dots{}]}. The text inside the
-@samp{\\<@dots{}>} should be the name of the variable containing the
-local keymap for the major mode.
-
-It is not practical to use @samp{\\[@dots{}]} very many times, because
-display of the documentation string will become slow. So use this to
-describe the most important commands in your major mode, and then use
-@samp{\\@{@dots{}@}} to display the rest of the mode's keymap.
-@end itemize
-
-@node Comment Tips
-@section Tips on Writing Comments
-
- We recommend these conventions for where to put comments and how to
-indent them:
-
-@table @samp
-@item ;
-Comments that start with a single semicolon, @samp{;}, should all be
-aligned to the same column on the right of the source code. Such
-comments usually explain how the code on the same line does its job. In
-Lisp mode and related modes, the @kbd{M-;} (@code{indent-for-comment})
-command automatically inserts such a @samp{;} in the right place, or
-aligns such a comment if it is already present.
-
-This and following examples are taken from the Emacs sources.
-
-@smallexample
-@group
-(setq base-version-list ; there was a base
- (assoc (substring fn 0 start-vn) ; version to which
- file-version-assoc-list)) ; this looks like
- ; a subversion
-@end group
-@end smallexample
-
-@item ;;
-Comments that start with two semicolons, @samp{;;}, should be aligned to
-the same level of indentation as the code. Such comments usually
-describe the purpose of the following lines or the state of the program
-at that point. For example:
-
-@smallexample
-@group
-(prog1 (setq auto-fill-function
- @dots{}
- @dots{}
- ;; update mode line
- (force-mode-line-update)))
-@end group
-@end smallexample
-
-Every function that has no documentation string (because it is use only
-internally within the package it belongs to), should have instead a
-two-semicolon comment right before the function, explaining what the
-function does and how to call it properly. Explain precisely what each
-argument means and how the function interprets its possible values.
-
-@item ;;;
-Comments that start with three semicolons, @samp{;;;}, should start at
-the left margin. Such comments are used outside function definitions to
-make general statements explaining the design principles of the program.
-For example:
-
-@smallexample
-@group
-;;; This Lisp code is run in Emacs
-;;; when it is to operate as a server
-;;; for other processes.
-@end group
-@end smallexample
-
-Another use for triple-semicolon comments is for commenting out lines
-within a function. We use triple-semicolons for this precisely so that
-they remain at the left margin.
-
-@smallexample
-(defun foo (a)
-;;; This is no longer necessary.
-;;; (force-mode-line-update)
- (message "Finished with %s" a))
-@end smallexample
-
-@item ;;;;
-Comments that start with four semicolons, @samp{;;;;}, should be aligned
-to the left margin and are used for headings of major sections of a
-program. For example:
-
-@smallexample
-;;;; The kill ring
-@end smallexample
-@end table
-
-@noindent
-The indentation commands of the Lisp modes in Emacs, such as @kbd{M-;}
-(@code{indent-for-comment}) and @key{TAB} (@code{lisp-indent-line})
-automatically indent comments according to these conventions,
-depending on the number of semicolons. @xref{Comments,,
-Manipulating Comments, emacs, The GNU Emacs Manual}.
-
-@node Library Headers
-@section Conventional Headers for Emacs Libraries
-@cindex header comments
-@cindex library header comments
-
- Emacs 19 has conventions for using special comments in Lisp libraries
-to divide them into sections and give information such as who wrote
-them. This section explains these conventions. First, an example:
-
-@smallexample
-@group
-;;; lisp-mnt.el --- minor mode for Emacs Lisp maintainers
-
-;; Copyright (C) 1992 Free Software Foundation, Inc.
-@end group
-
-;; Author: Eric S. Raymond <esr@@snark.thyrsus.com>
-;; Maintainer: Eric S. Raymond <esr@@snark.thyrsus.com>
-;; Created: 14 Jul 1992
-;; Version: 1.2
-@group
-;; Keywords: docs
-
-;; This file is part of GNU Emacs.
-@var{copying permissions}@dots{}
-@end group
-@end smallexample
-
- The very first line should have this format:
-
-@example
-;;; @var{filename} --- @var{description}
-@end example
-
-@noindent
-The description should be complete in one line.
-
- After the copyright notice come several @dfn{header comment} lines,
-each beginning with @samp{;; @var{header-name}:}. Here is a table of
-the conventional possibilities for @var{header-name}:
-
-@table @samp
-@item Author
-This line states the name and net address of at least the principal
-author of the library.
-
-If there are multiple authors, you can list them on continuation lines
-led by @code{;;} and a tab character, like this:
-
-@smallexample
-@group
-;; Author: Ashwin Ram <Ram-Ashwin@@cs.yale.edu>
-;; Dave Sill <de5@@ornl.gov>
-;; Dave Brennan <brennan@@hal.com>
-;; Eric Raymond <esr@@snark.thyrsus.com>
-@end group
-@end smallexample
-
-@item Maintainer
-This line should contain a single name/address as in the Author line, or
-an address only, or the string @samp{FSF}. If there is no maintainer
-line, the person(s) in the Author field are presumed to be the
-maintainers. The example above is mildly bogus because the maintainer
-line is redundant.
-
-The idea behind the @samp{Author} and @samp{Maintainer} lines is to make
-possible a Lisp function to ``send mail to the maintainer'' without
-having to mine the name out by hand.
-
-Be sure to surround the network address with @samp{<@dots{}>} if
-you include the person's full name as well as the network address.
-
-@item Created
-This optional line gives the original creation date of the
-file. For historical interest only.
-
-@item Version
-If you wish to record version numbers for the individual Lisp program, put
-them in this line.
-
-@item Adapted-By
-In this header line, place the name of the person who adapted the
-library for installation (to make it fit the style conventions, for
-example).
-
-@item Keywords
-This line lists keywords for the @code{finder-by-keyword} help command.
-This field is important; it's how people will find your package when
-they're looking for things by topic area. To separate the keywords, you
-can use spaces, commas, or both.
-@end table
-
- Just about every Lisp library ought to have the @samp{Author} and
-@samp{Keywords} header comment lines. Use the others if they are
-appropriate. You can also put in header lines with other header
-names---they have no standard meanings, so they can't do any harm.
-
- We use additional stylized comments to subdivide the contents of the
-library file. Here is a table of them:
-
-@table @samp
-@item ;;; Commentary:
-This begins introductory comments that explain how the library works.
-It should come right after the copying permissions.
-
-@item ;;; Change log:
-This begins change log information stored in the library file (if you
-store the change history there). For most of the Lisp
-files distributed with Emacs, the change history is kept in the file
-@file{ChangeLog} and not in the source file at all; these files do
-not have a @samp{;;; Change log:} line.
-
-@item ;;; Code:
-This begins the actual code of the program.
-
-@item ;;; @var{filename} ends here
-This is the @dfn{footer line}; it appears at the very end of the file.
-Its purpose is to enable people to detect truncated versions of the file
-from the lack of a footer line.
-@end table
diff --git a/lispref/variables.texi b/lispref/variables.texi
deleted file mode 100644
index 22813ea5b63..00000000000
--- a/lispref/variables.texi
+++ /dev/null
@@ -1,1427 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/variables
-@node Variables, Functions, Control Structures, Top
-@chapter Variables
-@cindex variable
-
- A @dfn{variable} is a name used in a program to stand for a value.
-Nearly all programming languages have variables of some sort. In the
-text of a Lisp program, variables are written using the syntax for
-symbols.
-
- In Lisp, unlike most programming languages, programs are represented
-primarily as Lisp objects and only secondarily as text. The Lisp
-objects used for variables are symbols: the symbol name is the variable
-name, and the variable's value is stored in the value cell of the
-symbol. The use of a symbol as a variable is independent of its use as
-a function name. @xref{Symbol Components}.
-
- The Lisp objects that constitute a Lisp program determine the textual
-form of the program---it is simply the read syntax for those Lisp
-objects. This is why, for example, a variable in a textual Lisp program
-is written using the read syntax for the symbol that represents the
-variable.
-
-@menu
-* Global Variables:: Variable values that exist permanently, everywhere.
-* Constant Variables:: Certain "variables" have values that never change.
-* Local Variables:: Variable values that exist only temporarily.
-* Void Variables:: Symbols that lack values.
-* Defining Variables:: A definition says a symbol is used as a variable.
-* Tips for Defining:: How to avoid bad results from quitting
- within the code to initialize a variable.
-* Accessing Variables:: Examining values of variables whose names
- are known only at run time.
-* Setting Variables:: Storing new values in variables.
-* Variable Scoping:: How Lisp chooses among local and global values.
-* Buffer-Local Variables:: Variable values in effect only in one buffer.
-@end menu
-
-@node Global Variables
-@section Global Variables
-@cindex global variable
-
- The simplest way to use a variable is @dfn{globally}. This means that
-the variable has just one value at a time, and this value is in effect
-(at least for the moment) throughout the Lisp system. The value remains
-in effect until you specify a new one. When a new value replaces the
-old one, no trace of the old value remains in the variable.
-
- You specify a value for a symbol with @code{setq}. For example,
-
-@example
-(setq x '(a b))
-@end example
-
-@noindent
-gives the variable @code{x} the value @code{(a b)}. Note that
-@code{setq} does not evaluate its first argument, the name of the
-variable, but it does evaluate the second argument, the new value.
-
- Once the variable has a value, you can refer to it by using the symbol
-by itself as an expression. Thus,
-
-@example
-@group
-x @result{} (a b)
-@end group
-@end example
-
-@noindent
-assuming the @code{setq} form shown above has already been executed.
-
- If you do another @code{setq}, the new value replaces the old one:
-
-@example
-@group
-x
- @result{} (a b)
-@end group
-@group
-(setq x 4)
- @result{} 4
-@end group
-@group
-x
- @result{} 4
-@end group
-@end example
-
-@node Constant Variables
-@section Variables That Never Change
-@vindex nil
-@vindex t
-@kindex setting-constant
-
- Emacs Lisp has two special symbols, @code{nil} and @code{t}, that
-always evaluate to themselves. These symbols cannot be rebound, nor can
-their value cells be changed. An attempt to change the value of
-@code{nil} or @code{t} signals a @code{setting-constant} error.
-
-@example
-@group
-nil @equiv{} 'nil
- @result{} nil
-@end group
-@group
-(setq nil 500)
-@error{} Attempt to set constant symbol: nil
-@end group
-@end example
-
-@node Local Variables
-@section Local Variables
-@cindex binding local variables
-@cindex local variables
-@cindex local binding
-@cindex global binding
-
- Global variables have values that last until explicitly superseded
-with new values. Sometimes it is useful to create variable values that
-exist temporarily---only while within a certain part of the program.
-These values are called @dfn{local}, and the variables so used are
-called @dfn{local variables}.
-
- For example, when a function is called, its argument variables receive
-new local values that last until the function exits. The @code{let}
-special form explicitly establishes new local values for specified
-variables; these last until exit from the @code{let} form.
-
-@cindex shadowing of variables
- Establishing a local value saves away the previous value (or lack of
-one) of the variable. When the life span of the local value is over,
-the previous value is restored. In the mean time, we say that the
-previous value is @dfn{shadowed} and @dfn{not visible}. Both global and
-local values may be shadowed (@pxref{Scope}).
-
- If you set a variable (such as with @code{setq}) while it is local,
-this replaces the local value; it does not alter the global value, or
-previous local values that are shadowed. To model this behavior, we
-speak of a @dfn{local binding} of the variable as well as a local value.
-
- The local binding is a conceptual place that holds a local value.
-Entry to a function, or a special form such as @code{let}, creates the
-local binding; exit from the function or from the @code{let} removes the
-local binding. As long as the local binding lasts, the variable's value
-is stored within it. Use of @code{setq} or @code{set} while there is a
-local binding stores a different value into the local binding; it does
-not create a new binding.
-
- We also speak of the @dfn{global binding}, which is where
-(conceptually) the global value is kept.
-
-@cindex current binding
- A variable can have more than one local binding at a time (for
-example, if there are nested @code{let} forms that bind it). In such a
-case, the most recently created local binding that still exists is the
-@dfn{current binding} of the variable. (This is called @dfn{dynamic
-scoping}; see @ref{Variable Scoping}.) If there are no local bindings,
-the variable's global binding is its current binding. We also call the
-current binding the @dfn{most-local existing binding}, for emphasis.
-Ordinary evaluation of a symbol always returns the value of its current
-binding.
-
- The special forms @code{let} and @code{let*} exist to create
-local bindings.
-
-@defspec let (bindings@dots{}) forms@dots{}
-This special form binds variables according to @var{bindings} and then
-evaluates all of the @var{forms} in textual order. The @code{let}-form
-returns the value of the last form in @var{forms}.
-
-Each of the @var{bindings} is either @w{(i) a} symbol, in which case
-that symbol is bound to @code{nil}; or @w{(ii) a} list of the form
-@code{(@var{symbol} @var{value-form})}, in which case @var{symbol} is
-bound to the result of evaluating @var{value-form}. If @var{value-form}
-is omitted, @code{nil} is used.
-
-All of the @var{value-form}s in @var{bindings} are evaluated in the
-order they appear and @emph{before} any of the symbols are bound. Here
-is an example of this: @code{Z} is bound to the old value of @code{Y},
-which is 2, not the new value, 1.
-
-@example
-@group
-(setq Y 2)
- @result{} 2
-@end group
-@group
-(let ((Y 1)
- (Z Y))
- (list Y Z))
- @result{} (1 2)
-@end group
-@end example
-@end defspec
-
-@defspec let* (bindings@dots{}) forms@dots{}
-This special form is like @code{let}, but it binds each variable right
-after computing its local value, before computing the local value for
-the next variable. Therefore, an expression in @var{bindings} can
-reasonably refer to the preceding symbols bound in this @code{let*}
-form. Compare the following example with the example above for
-@code{let}.
-
-@example
-@group
-(setq Y 2)
- @result{} 2
-@end group
-@group
-(let* ((Y 1)
- (Z Y)) ; @r{Use the just-established value of @code{Y}.}
- (list Y Z))
- @result{} (1 1)
-@end group
-@end example
-@end defspec
-
- Here is a complete list of the other facilities that create local
-bindings:
-
-@itemize @bullet
-@item
-Function calls (@pxref{Functions}).
-
-@item
-Macro calls (@pxref{Macros}).
-
-@item
-@code{condition-case} (@pxref{Errors}).
-@end itemize
-
- Variables can also have buffer-local bindings (@pxref{Buffer-Local
-Variables}); a few variables have terminal-local bindings
-(@pxref{Multiple Displays}). These kinds of bindings work somewhat like
-ordinary local bindings, but they are localized depending on ``where''
-you are in Emacs, rather than localized in time.
-
-@defvar max-specpdl-size
-@cindex variable limit error
-@cindex evaluation error
-@cindex infinite recursion
- This variable defines the limit on the total number of local variable
-bindings and @code{unwind-protect} cleanups (@pxref{Nonlocal Exits})
-that are allowed before signaling an error (with data @code{"Variable
-binding depth exceeds max-specpdl-size"}).
-
- This limit, with the associated error when it is exceeded, is one way
-that Lisp avoids infinite recursion on an ill-defined function.
-
- The default value is 600.
-
- @code{max-lisp-eval-depth} provides another limit on depth of nesting.
-@xref{Eval}.
-@end defvar
-
-@node Void Variables
-@section When a Variable is ``Void''
-@kindex void-variable
-@cindex void variable
-
- If you have never given a symbol any value as a global variable, we
-say that that symbol's global value is @dfn{void}. In other words, the
-symbol's value cell does not have any Lisp object in it. If you try to
-evaluate the symbol, you get a @code{void-variable} error rather than
-a value.
-
- Note that a value of @code{nil} is not the same as void. The symbol
-@code{nil} is a Lisp object and can be the value of a variable just as any
-other object can be; but it is @emph{a value}. A void variable does not
-have any value.
-
- After you have given a variable a value, you can make it void once more
-using @code{makunbound}.
-
-@defun makunbound symbol
-This function makes the current binding of @var{symbol} void.
-Subsequent attempts to use this symbol's value as a variable will signal
-the error @code{void-variable}, unless or until you set it again.
-
-@code{makunbound} returns @var{symbol}.
-
-@example
-@group
-(makunbound 'x) ; @r{Make the global value}
- ; @r{of @code{x} void.}
- @result{} x
-@end group
-@group
-x
-@error{} Symbol's value as variable is void: x
-@end group
-@end example
-
-If @var{symbol} is locally bound, @code{makunbound} affects the most
-local existing binding. This is the only way a symbol can have a void
-local binding, since all the constructs that create local bindings
-create them with values. In this case, the voidness lasts at most as
-long as the binding does; when the binding is removed due to exit from
-the construct that made it, the previous or global binding is reexposed
-as usual, and the variable is no longer void unless the newly reexposed
-binding was void all along.
-
-@smallexample
-@group
-(setq x 1) ; @r{Put a value in the global binding.}
- @result{} 1
-(let ((x 2)) ; @r{Locally bind it.}
- (makunbound 'x) ; @r{Void the local binding.}
- x)
-@error{} Symbol's value as variable is void: x
-@end group
-@group
-x ; @r{The global binding is unchanged.}
- @result{} 1
-
-(let ((x 2)) ; @r{Locally bind it.}
- (let ((x 3)) ; @r{And again.}
- (makunbound 'x) ; @r{Void the innermost-local binding.}
- x)) ; @r{And refer: it's void.}
-@error{} Symbol's value as variable is void: x
-@end group
-
-@group
-(let ((x 2))
- (let ((x 3))
- (makunbound 'x)) ; @r{Void inner binding, then remove it.}
- x) ; @r{Now outer @code{let} binding is visible.}
- @result{} 2
-@end group
-@end smallexample
-@end defun
-
- A variable that has been made void with @code{makunbound} is
-indistinguishable from one that has never received a value and has
-always been void.
-
- You can use the function @code{boundp} to test whether a variable is
-currently void.
-
-@defun boundp variable
-@code{boundp} returns @code{t} if @var{variable} (a symbol) is not void;
-more precisely, if its current binding is not void. It returns
-@code{nil} otherwise.
-
-@smallexample
-@group
-(boundp 'abracadabra) ; @r{Starts out void.}
- @result{} nil
-@end group
-@group
-(let ((abracadabra 5)) ; @r{Locally bind it.}
- (boundp 'abracadabra))
- @result{} t
-@end group
-@group
-(boundp 'abracadabra) ; @r{Still globally void.}
- @result{} nil
-@end group
-@group
-(setq abracadabra 5) ; @r{Make it globally nonvoid.}
- @result{} 5
-@end group
-@group
-(boundp 'abracadabra)
- @result{} t
-@end group
-@end smallexample
-@end defun
-
-@node Defining Variables
-@section Defining Global Variables
-@cindex variable definition
-
- You may announce your intention to use a symbol as a global variable
-with a @dfn{variable definition}: a special form, either @code{defconst}
-or @code{defvar}.
-
- In Emacs Lisp, definitions serve three purposes. First, they inform
-people who read the code that certain symbols are @emph{intended} to be
-used a certain way (as variables). Second, they inform the Lisp system
-of these things, supplying a value and documentation. Third, they
-provide information to utilities such as @code{etags} and
-@code{make-docfile}, which create data bases of the functions and
-variables in a program.
-
- The difference between @code{defconst} and @code{defvar} is primarily
-a matter of intent, serving to inform human readers of whether programs
-will change the variable. Emacs Lisp does not restrict the ways in
-which a variable can be used based on @code{defconst} or @code{defvar}
-declarations. However, it does make a difference for initialization:
-@code{defconst} unconditionally initializes the variable, while
-@code{defvar} initializes it only if it is void.
-
- One would expect user option variables to be defined with
-@code{defconst}, since programs do not change them. Unfortunately, this
-has bad results if the definition is in a library that is not preloaded:
-@code{defconst} would override any prior value when the library is
-loaded. Users would like to be able to set user options in their init
-files, and override the default values given in the definitions. For
-this reason, user options must be defined with @code{defvar}.
-
-@defspec defvar symbol [value [doc-string]]
-This special form defines @var{symbol} as a value and initializes it.
-The definition informs a person reading your code that @var{symbol} is
-used as a variable that programs are likely to set or change. It is
-also used for all user option variables except in the preloaded parts of
-Emacs. Note that @var{symbol} is not evaluated; the symbol to be
-defined must appear explicitly in the @code{defvar}.
-
-If @var{symbol} already has a value (i.e., it is not void), @var{value}
-is not even evaluated, and @var{symbol}'s value remains unchanged. If
-@var{symbol} is void and @var{value} is specified, @code{defvar}
-evaluates it and sets @var{symbol} to the result. (If @var{value} is
-omitted, the value of @var{symbol} is not changed in any case.)
-
-When you evaluate a top-level @code{defvar} form with @kbd{C-M-x} in
-Emacs Lisp mode (@code{eval-defun}), a special feature of
-@code{eval-defun} evaluates it as a @code{defconst}. The purpose of
-this is to make sure the variable's value is reinitialized, when you ask
-for it specifically.
-
-If @var{symbol} has a buffer-local binding in the current buffer,
-@code{defvar} sets the default value, not the local value.
-@xref{Buffer-Local Variables}.
-
-If the @var{doc-string} argument appears, it specifies the documentation
-for the variable. (This opportunity to specify documentation is one of
-the main benefits of defining the variable.) The documentation is
-stored in the symbol's @code{variable-documentation} property. The
-Emacs help functions (@pxref{Documentation}) look for this property.
-
-If the first character of @var{doc-string} is @samp{*}, it means that
-this variable is considered a user option. This lets users set the
-variable conventiently using the commands @code{set-variable} and
-@code{edit-options}.
-
-For example, this form defines @code{foo} but does not set its value:
-
-@example
-@group
-(defvar foo)
- @result{} foo
-@end group
-@end example
-
-The following example sets the value of @code{bar} to @code{23}, and
-gives it a documentation string:
-
-@example
-@group
-(defvar bar 23
- "The normal weight of a bar.")
- @result{} bar
-@end group
-@end example
-
-The following form changes the documentation string for @code{bar},
-making it a user option, but does not change the value, since @code{bar}
-already has a value. (The addition @code{(1+ 23)} is not even
-performed.)
-
-@example
-@group
-(defvar bar (1+ 23)
- "*The normal weight of a bar.")
- @result{} bar
-@end group
-@group
-bar
- @result{} 23
-@end group
-@end example
-
-Here is an equivalent expression for the @code{defvar} special form:
-
-@example
-@group
-(defvar @var{symbol} @var{value} @var{doc-string})
-@equiv{}
-(progn
- (if (not (boundp '@var{symbol}))
- (setq @var{symbol} @var{value}))
- (if '@var{doc-string}
- (put '@var{symbol} 'variable-documentation '@var{doc-string}))
- '@var{symbol})
-@end group
-@end example
-
-The @code{defvar} form returns @var{symbol}, but it is normally used
-at top level in a file where its value does not matter.
-@end defspec
-
-@defspec defconst symbol [value [doc-string]]
-This special form defines @var{symbol} as a value and initializes it.
-It informs a person reading your code that @var{symbol} has a global
-value, established here, that will not normally be changed or locally
-bound by the execution of the program. The user, however, may be
-welcome to change it. Note that @var{symbol} is not evaluated; the
-symbol to be defined must appear explicitly in the @code{defconst}.
-
-@code{defconst} always evaluates @var{value} and sets the global value
-of @var{symbol} to the result, provided @var{value} is given. If
-@var{symbol} has a buffer-local binding in the current buffer,
-@code{defconst} sets the default value, not the local value.
-
-@strong{Please note:} Don't use @code{defconst} for user option
-variables in libraries that are not standardly preloaded. The user
-should be able to specify a value for such a variable in the
-@file{.emacs} file, so that it will be in effect if and when the library
-is loaded later.
-
-Here, @code{pi} is a constant that presumably ought not to be changed
-by anyone (attempts by the Indiana State Legislature notwithstanding).
-As the second form illustrates, however, this is only advisory.
-
-@example
-@group
-(defconst pi 3.1415 "Pi to five places.")
- @result{} pi
-@end group
-@group
-(setq pi 3)
- @result{} pi
-@end group
-@group
-pi
- @result{} 3
-@end group
-@end example
-@end defspec
-
-@defun user-variable-p variable
-@cindex user option
-This function returns @code{t} if @var{variable} is a user option---a
-variable intended to be set by the user for customization---and
-@code{nil} otherwise. (Variables other than user options exist for the
-internal purposes of Lisp programs, and users need not know about them.)
-
-User option variables are distinguished from other variables by the
-first character of the @code{variable-documentation} property. If the
-property exists and is a string, and its first character is @samp{*},
-then the variable is a user option.
-@end defun
-
-@kindex variable-interactive
- If a user option variable has a @code{variable-interactive} property,
-the @code{set-variable} command uses that value to control reading the
-new value for the variable. The property's value is used as if it were
-to @code{interactive} (@pxref{Using Interactive}).
-
- @strong{Warning:} If the @code{defconst} and @code{defvar} special
-forms are used while the variable has a local binding, they set the
-local binding's value; the global binding is not changed. This is not
-what we really want. To prevent it, use these special forms at top
-level in a file, where normally no local binding is in effect, and make
-sure to load the file before making a local binding for the variable.
-
-@node Tips for Defining
-@section Tips for Defining Variables Robustly
-
- When defining and initializing a variable that holds a complicated
-value (such as a keymap with bindings in it), it's best to put the
-entire computation of the value into the @code{defvar}, like this:
-
-@example
-(defvar my-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key my-mode-map "\C-c\C-a" 'my-command)
- @dots{}
- map)
- @var{docstring})
-@end example
-
-@noindent
-This method has several benefits. First, if the user quits while
-loading the file, the variable is either still uninitialized or
-initialized properly, never in-between. If it is uninitialized,
-reloading the file will initialize it properly. Second, reloading the
-file once the variable is initialized will not alter it; that is
-important if the user has run hooks to alter part of the contents (such
-as, to rebind keys). Third, evaluating the @code{defvar} form with
-@kbd{C-M-x} @emph{will} reinitialize the map completely.
-
- Putting so much code in the @code{defvar} form has one disadvantage:
-it puts the documentation string far away from the line which names the
-variable. Here's a safe way to avoid that:
-
-@example
-(defvar my-mode-map nil
- @var{docstring})
-(if my-mode-map
- nil
- (let ((map (make-sparse-keymap)))
- (define-key my-mode-map "\C-c\C-a" 'my-command)
- @dots{}
- (setq my-mode-map map)))
-@end example
-
-@noindent
-This has all the same advantages as putting the initialization inside
-the @code{defvar}, except that you must type @kbd{C-M-x} twice, once on
-each form, if you do want to reinitialize the variable.
-
- But be careful not to write the code like this:
-
-@example
-(defvar my-mode-map nil
- @var{docstring})
-(if my-mode-map
- nil
- (setq my-mode-map (make-sparse-keymap))
- (define-key my-mode-map "\C-c\C-a" 'my-command)
- @dots{})
-@end example
-
-@noindent
-This code sets the variable, then alters it, but only if the variable
-had been @code{ni}. If the user quits just after the @code{setq}, that
-leaves the variable neither correctly initialized nor void nor
-@code{nil}. Once that happens, reloading the file will not initialize
-the variable; it will remain incomplete.
-
-@node Accessing Variables
-@section Accessing Variable Values
-
- The usual way to reference a variable is to write the symbol which
-names it (@pxref{Symbol Forms}). This requires you to specify the
-variable name when you write the program. Usually that is exactly what
-you want to do. Occasionally you need to choose at run time which
-variable to reference; then you can use @code{symbol-value}.
-
-@defun symbol-value symbol
-This function returns the value of @var{symbol}. This is the value in
-the innermost local binding of the symbol, or its global value if it
-has no local bindings.
-
-@example
-@group
-(setq abracadabra 5)
- @result{} 5
-@end group
-@group
-(setq foo 9)
- @result{} 9
-@end group
-
-@group
-;; @r{Here the symbol @code{abracadabra}}
-;; @r{is the symbol whose value is examined.}
-(let ((abracadabra 'foo))
- (symbol-value 'abracadabra))
- @result{} foo
-@end group
-
-@group
-;; @r{Here the value of @code{abracadabra},}
-;; @r{which is @code{foo},}
-;; @r{is the symbol whose value is examined.}
-(let ((abracadabra 'foo))
- (symbol-value abracadabra))
- @result{} 9
-@end group
-
-@group
-(symbol-value 'abracadabra)
- @result{} 5
-@end group
-@end example
-
-A @code{void-variable} error is signaled if @var{symbol} has neither a
-local binding nor a global value.
-@end defun
-
-@node Setting Variables
-@section How to Alter a Variable Value
-
- The usual way to change the value of a variable is with the special
-form @code{setq}. When you need to compute the choice of variable at
-run time, use the function @code{set}.
-
-@defspec setq [symbol form]@dots{}
-This special form is the most common method of changing a variable's
-value. Each @var{symbol} is given a new value, which is the result of
-evaluating the corresponding @var{form}. The most-local existing
-binding of the symbol is changed.
-
-@code{setq} does not evaluate @var{symbol}; it sets the symbol that you
-write. We say that this argument is @dfn{automatically quoted}. The
-@samp{q} in @code{setq} stands for ``quoted.''
-
-The value of the @code{setq} form is the value of the last @var{form}.
-
-@example
-@group
-(setq x (1+ 2))
- @result{} 3
-@end group
-x ; @r{@code{x} now has a global value.}
- @result{} 3
-@group
-(let ((x 5))
- (setq x 6) ; @r{The local binding of @code{x} is set.}
- x)
- @result{} 6
-@end group
-x ; @r{The global value is unchanged.}
- @result{} 3
-@end example
-
-Note that the first @var{form} is evaluated, then the first
-@var{symbol} is set, then the second @var{form} is evaluated, then the
-second @var{symbol} is set, and so on:
-
-@example
-@group
-(setq x 10 ; @r{Notice that @code{x} is set before}
- y (1+ x)) ; @r{the value of @code{y} is computed.}
- @result{} 11
-@end group
-@end example
-@end defspec
-
-@defun set symbol value
-This function sets @var{symbol}'s value to @var{value}, then returns
-@var{value}. Since @code{set} is a function, the expression written for
-@var{symbol} is evaluated to obtain the symbol to set.
-
-The most-local existing binding of the variable is the binding that is
-set; shadowed bindings are not affected.
-
-@example
-@group
-(set one 1)
-@error{} Symbol's value as variable is void: one
-@end group
-@group
-(set 'one 1)
- @result{} 1
-@end group
-@group
-(set 'two 'one)
- @result{} one
-@end group
-@group
-(set two 2) ; @r{@code{two} evaluates to symbol @code{one}.}
- @result{} 2
-@end group
-@group
-one ; @r{So it is @code{one} that was set.}
- @result{} 2
-(let ((one 1)) ; @r{This binding of @code{one} is set,}
- (set 'one 3) ; @r{not the global value.}
- one)
- @result{} 3
-@end group
-@group
-one
- @result{} 2
-@end group
-@end example
-
-If @var{symbol} is not actually a symbol, a @code{wrong-type-argument}
-error is signaled.
-
-@example
-(set '(x y) 'z)
-@error{} Wrong type argument: symbolp, (x y)
-@end example
-
-Logically speaking, @code{set} is a more fundamental primitive than
-@code{setq}. Any use of @code{setq} can be trivially rewritten to use
-@code{set}; @code{setq} could even be defined as a macro, given the
-availability of @code{set}. However, @code{set} itself is rarely used;
-beginners hardly need to know about it. It is useful only for choosing
-at run time which variable to set. For example, the command
-@code{set-variable}, which reads a variable name from the user and then
-sets the variable, needs to use @code{set}.
-
-@cindex CL note---@code{set} local
-@quotation
-@b{Common Lisp note:} In Common Lisp, @code{set} always changes the
-symbol's special value, ignoring any lexical bindings. In Emacs Lisp,
-all variables and all bindings are (in effect) special, so @code{set}
-always affects the most local existing binding.
-@end quotation
-@end defun
-
- One other function for setting a variable is designed to add
-an element to a list if it is not already present in the list.
-
-@defun add-to-list symbol element
-This function sets the variable @var{symbol} by consing @var{element}
-onto the old value, if @var{element} is not already a member of that
-value. It returns the resulting list, whether updated or not. The
-value of @var{symbol} had better be a list already before the call.
-
-The argument @var{symbol} is not implicitly quoted; @code{add-to-list}
-is an ordinary function, like @code{set} and unlike @code{setq}. Quote
-the argument yourself if that is what you want.
-
-Here's a scenario showing how to use @code{add-to-list}:
-
-@example
-(setq foo '(a b))
- @result{} (a b)
-
-(add-to-list 'foo 'c) ;; @r{Add @code{c}.}
- @result{} (c a b)
-
-(add-to-list 'foo 'b) ;; @r{No effect.}
- @result{} (c a b)
-
-foo ;; @r{@code{foo} was changed.}
- @result{} (c a b)
-@end example
-@end defun
-
- An equivalent expression for @code{(add-to-list '@var{var}
-@var{value})} is this:
-
-@example
-(or (member @var{value} @var{var})
- (setq @var{var} (cons @var{value} @var{var})))
-@end example
-
-@node Variable Scoping
-@section Scoping Rules for Variable Bindings
-
- A given symbol @code{foo} may have several local variable bindings,
-established at different places in the Lisp program, as well as a global
-binding. The most recently established binding takes precedence over
-the others.
-
-@cindex scope
-@cindex extent
-@cindex dynamic scoping
- Local bindings in Emacs Lisp have @dfn{indefinite scope} and
-@dfn{dynamic extent}. @dfn{Scope} refers to @emph{where} textually in
-the source code the binding can be accessed. Indefinite scope means
-that any part of the program can potentially access the variable
-binding. @dfn{Extent} refers to @emph{when}, as the program is
-executing, the binding exists. Dynamic extent means that the binding
-lasts as long as the activation of the construct that established it.
-
- The combination of dynamic extent and indefinite scope is called
-@dfn{dynamic scoping}. By contrast, most programming languages use
-@dfn{lexical scoping}, in which references to a local variable must be
-located textually within the function or block that binds the variable.
-
-@cindex CL note---special variables
-@quotation
-@b{Common Lisp note:} Variables declared ``special'' in Common Lisp
-are dynamically scoped, like variables in Emacs Lisp.
-@end quotation
-
-@menu
-* Scope:: Scope means where in the program a value is visible.
- Comparison with other languages.
-* Extent:: Extent means how long in time a value exists.
-* Impl of Scope:: Two ways to implement dynamic scoping.
-* Using Scoping:: How to use dynamic scoping carefully and avoid problems.
-@end menu
-
-@node Scope
-@subsection Scope
-
- Emacs Lisp uses @dfn{indefinite scope} for local variable bindings.
-This means that any function anywhere in the program text might access a
-given binding of a variable. Consider the following function
-definitions:
-
-@example
-@group
-(defun binder (x) ; @r{@code{x} is bound in @code{binder}.}
- (foo 5)) ; @r{@code{foo} is some other function.}
-@end group
-
-@group
-(defun user () ; @r{@code{x} is used in @code{user}.}
- (list x))
-@end group
-@end example
-
- In a lexically scoped language, the binding of @code{x} in
-@code{binder} would never be accessible in @code{user}, because
-@code{user} is not textually contained within the function
-@code{binder}. However, in dynamically scoped Emacs Lisp, @code{user}
-may or may not refer to the binding of @code{x} established in
-@code{binder}, depending on circumstances:
-
-@itemize @bullet
-@item
-If we call @code{user} directly without calling @code{binder} at all,
-then whatever binding of @code{x} is found, it cannot come from
-@code{binder}.
-
-@item
-If we define @code{foo} as follows and call @code{binder}, then the
-binding made in @code{binder} will be seen in @code{user}:
-
-@example
-@group
-(defun foo (lose)
- (user))
-@end group
-@end example
-
-@item
-If we define @code{foo} as follows and call @code{binder}, then the
-binding made in @code{binder} @emph{will not} be seen in @code{user}:
-
-@example
-(defun foo (x)
- (user))
-@end example
-
-@noindent
-Here, when @code{foo} is called by @code{binder}, it binds @code{x}.
-(The binding in @code{foo} is said to @dfn{shadow} the one made in
-@code{binder}.) Therefore, @code{user} will access the @code{x} bound
-by @code{foo} instead of the one bound by @code{binder}.
-@end itemize
-
-@node Extent
-@subsection Extent
-
- @dfn{Extent} refers to the time during program execution that a
-variable name is valid. In Emacs Lisp, a variable is valid only while
-the form that bound it is executing. This is called @dfn{dynamic
-extent}. ``Local'' or ``automatic'' variables in most languages,
-including C and Pascal, have dynamic extent.
-
- One alternative to dynamic extent is @dfn{indefinite extent}. This
-means that a variable binding can live on past the exit from the form
-that made the binding. Common Lisp and Scheme, for example, support
-this, but Emacs Lisp does not.
-
- To illustrate this, the function below, @code{make-add}, returns a
-function that purports to add @var{n} to its own argument @var{m}.
-This would work in Common Lisp, but it does not work as intended in
-Emacs Lisp, because after the call to @code{make-add} exits, the
-variable @code{n} is no longer bound to the actual argument 2.
-
-@example
-(defun make-add (n)
- (function (lambda (m) (+ n m)))) ; @r{Return a function.}
- @result{} make-add
-(fset 'add2 (make-add 2)) ; @r{Define function @code{add2}}
- ; @r{with @code{(make-add 2)}.}
- @result{} (lambda (m) (+ n m))
-(add2 4) ; @r{Try to add 2 to 4.}
-@error{} Symbol's value as variable is void: n
-@end example
-
-@cindex closures not available
- Some Lisp dialects have ``closures'', objects that are like functions
-but record additional variable bindings. Emacs Lisp does not have
-closures.
-
-@node Impl of Scope
-@subsection Implementation of Dynamic Scoping
-@cindex deep binding
-
- A simple sample implementation (which is not how Emacs Lisp actually
-works) may help you understand dynamic binding. This technique is
-called @dfn{deep binding} and was used in early Lisp systems.
-
- Suppose there is a stack of bindings: variable-value pairs. At entry
-to a function or to a @code{let} form, we can push bindings on the stack
-for the arguments or local variables created there. We can pop those
-bindings from the stack at exit from the binding construct.
-
- We can find the value of a variable by searching the stack from top to
-bottom for a binding for that variable; the value from that binding is
-the value of the variable. To set the variable, we search for the
-current binding, then store the new value into that binding.
-
- As you can see, a function's bindings remain in effect as long as it
-continues execution, even during its calls to other functions. That is
-why we say the extent of the binding is dynamic. And any other function
-can refer to the bindings, if it uses the same variables while the
-bindings are in effect. That is why we say the scope is indefinite.
-
-@cindex shallow binding
- The actual implementation of variable scoping in GNU Emacs Lisp uses a
-technique called @dfn{shallow binding}. Each variable has a standard
-place in which its current value is always found---the value cell of the
-symbol.
-
- In shallow binding, setting the variable works by storing a value in
-the value cell. Creating a new binding works by pushing the old value
-(belonging to a previous binding) on a stack, and storing the local value
-in the value cell. Eliminating a binding works by popping the old value
-off the stack, into the value cell.
-
- We use shallow binding because it has the same results as deep
-binding, but runs faster, since there is never a need to search for a
-binding.
-
-@node Using Scoping
-@subsection Proper Use of Dynamic Scoping
-
- Binding a variable in one function and using it in another is a
-powerful technique, but if used without restraint, it can make programs
-hard to understand. There are two clean ways to use this technique:
-
-@itemize @bullet
-@item
-Use or bind the variable only in a few related functions, written close
-together in one file. Such a variable is used for communication within
-one program.
-
-You should write comments to inform other programmers that they can see
-all uses of the variable before them, and to advise them not to add uses
-elsewhere.
-
-@item
-Give the variable a well-defined, documented meaning, and make all
-appropriate functions refer to it (but not bind it or set it) wherever
-that meaning is relevant. For example, the variable
-@code{case-fold-search} is defined as ``non-@code{nil} means ignore case
-when searching''; various search and replace functions refer to it
-directly or through their subroutines, but do not bind or set it.
-
-Then you can bind the variable in other programs, knowing reliably what
-the effect will be.
-@end itemize
-
- In either case, you should define the variable with @code{defvar}.
-This helps other people understand your program by telling them to look
-for inter-function usage. It also avoids a warning from the byte
-compiler. Choose the variable's name to avoid name conflicts---don't
-use short names like @code{x}.
-
-@node Buffer-Local Variables
-@section Buffer-Local Variables
-@cindex variables, buffer-local
-@cindex buffer-local variables
-
- Global and local variable bindings are found in most programming
-languages in one form or another. Emacs also supports another, unusual
-kind of variable binding: @dfn{buffer-local} bindings, which apply only
-to one buffer. Emacs Lisp is meant for programming editing commands,
-and having different values for a variable in different buffers is an
-important customization method. (A few variables have bindings that
-are local to a given X terminal; see @ref{Multiple Displays}.)
-
-@menu
-* Intro to Buffer-Local:: Introduction and concepts.
-* Creating Buffer-Local:: Creating and destroying buffer-local bindings.
-* Default Value:: The default value is seen in buffers
- that don't have their own local values.
-@end menu
-
-@node Intro to Buffer-Local
-@subsection Introduction to Buffer-Local Variables
-
- A buffer-local variable has a buffer-local binding associated with a
-particular buffer. The binding is in effect when that buffer is
-current; otherwise, it is not in effect. If you set the variable while
-a buffer-local binding is in effect, the new value goes in that binding,
-so the global binding is unchanged; this means that the change is
-visible in that buffer alone.
-
- A variable may have buffer-local bindings in some buffers but not in
-others. The global binding is shared by all the buffers that don't have
-their own bindings. Thus, if you set the variable in a buffer that does
-not have a buffer-local binding for it, the new value is visible in all
-buffers except those with buffer-local bindings. (Here we are assuming
-that there are no @code{let}-style local bindings to complicate the issue.)
-
- The most common use of buffer-local bindings is for major modes to change
-variables that control the behavior of commands. For example, C mode and
-Lisp mode both set the variable @code{paragraph-start} to specify that only
-blank lines separate paragraphs. They do this by making the variable
-buffer-local in the buffer that is being put into C mode or Lisp mode, and
-then setting it to the new value for that mode.
-
- The usual way to make a buffer-local binding is with
-@code{make-local-variable}, which is what major mode commands use. This
-affects just the current buffer; all other buffers (including those yet to
-be created) continue to share the global value.
-
-@cindex automatically buffer-local
- A more powerful operation is to mark the variable as
-@dfn{automatically buffer-local} by calling
-@code{make-variable-buffer-local}. You can think of this as making the
-variable local in all buffers, even those yet to be created. More
-precisely, the effect is that setting the variable automatically makes
-the variable local to the current buffer if it is not already so. All
-buffers start out by sharing the global value of the variable as usual,
-but any @code{setq} creates a buffer-local binding for the current
-buffer. The new value is stored in the buffer-local binding, leaving
-the (default) global binding untouched. The global value can no longer
-be changed with @code{setq}; you need to use @code{setq-default} to do
-that.
-
- @strong{Warning:} When a variable has local values in one or more
-buffers, you can get Emacs very confused by binding the variable with
-@code{let}, changing to a different current buffer in which a different
-binding is in effect, and then exiting the @code{let}. This can
-scramble the values of the global and local bindings.
-
- To preserve your sanity, avoid that series of actions. If you use
-@code{save-excursion} around each piece of code that changes to a
-different current buffer, you will not have this problem. Here is an
-example of what to avoid:
-
-@example
-@group
-(setq foo 'b)
-(set-buffer "a")
-(make-local-variable 'foo)
-@end group
-(setq foo 'a)
-(let ((foo 'temp))
- (set-buffer "b")
- @var{body}@dots{})
-@group
-foo @result{} 'a ; @r{The old buffer-local value from buffer @samp{a}}
- ; @r{is now the default value.}
-@end group
-@group
-(set-buffer "a")
-foo @result{} 'temp ; @r{The local value that should be gone}
- ; @r{is now the buffer-local value in buffer @samp{a}.}
-@end group
-@end example
-
-@noindent
-But @code{save-excursion} as shown here avoids the problem:
-
-@example
-@group
-(let ((foo 'temp))
- (save-excursion
- (set-buffer "b")
- @var{body}@dots{}))
-@end group
-@end example
-
- Note that references to @code{foo} in @var{body} access the
-buffer-local binding of buffer @samp{b}.
-
- When a file specifies local variable values, these become buffer-local
-values when you visit the file. @xref{Auto Major Mode}.
-
-@node Creating Buffer-Local
-@subsection Creating and Deleting Buffer-Local Bindings
-
-@deffn Command make-local-variable variable
-This function creates a buffer-local binding in the current buffer for
-@var{variable} (a symbol). Other buffers are not affected. The value
-returned is @var{variable}.
-
-@c Emacs 19 feature
-The buffer-local value of @var{variable} starts out as the same value
-@var{variable} previously had. If @var{variable} was void, it remains
-void.
-
-@example
-@group
-;; @r{In buffer @samp{b1}:}
-(setq foo 5) ; @r{Affects all buffers.}
- @result{} 5
-@end group
-@group
-(make-local-variable 'foo) ; @r{Now it is local in @samp{b1}.}
- @result{} foo
-@end group
-@group
-foo ; @r{That did not change}
- @result{} 5 ; @r{the value.}
-@end group
-@group
-(setq foo 6) ; @r{Change the value}
- @result{} 6 ; @r{in @samp{b1}.}
-@end group
-@group
-foo
- @result{} 6
-@end group
-
-@group
-;; @r{In buffer @samp{b2}, the value hasn't changed.}
-(save-excursion
- (set-buffer "b2")
- foo)
- @result{} 5
-@end group
-@end example
-
-Making a variable buffer-local within a @code{let}-binding for that
-variable does not work. This is because @code{let} does not distinguish
-between different kinds of bindings; it knows only which variable the
-binding was made for.
-
-If the variable is terminal-local, this function signals an error. Such
-variables cannot have buffer-local bindings as well. @xref{Multiple
-Displays}.
-
-@strong{Note:} do not use @code{make-local-variable} for a hook
-variable. Instead, use @code{make-local-hook}. @xref{Hooks}.
-@end deffn
-
-@deffn Command make-variable-buffer-local variable
-This function marks @var{variable} (a symbol) automatically
-buffer-local, so that any subsequent attempt to set it will make it
-local to the current buffer at the time.
-
-The value returned is @var{variable}.
-
-@strong{Note:} It is a mistake to use @code{make-variable-buffer-local}
-for user-option variables, simply because users @emph{might} want to
-customize them differently in different buffers. Users can make any
-variable local, when they wish to.
-
-The main use of @code{make-variable-buffer-local} is when a variable is
-used for internal purposes, and the Lisp program depends on having
-separate values in separate buffers.
-@end deffn
-
-@defun local-variable-p variable &optional buffer
-This returns @code{t} if @var{variable} is buffer-local in buffer
-@var{buffer} (which defaults to the current buffer); otherwise,
-@code{nil}.
-@end defun
-
-@defun buffer-local-variables &optional buffer
-This function returns a list describing the buffer-local variables in
-buffer @var{buffer}. It returns an association list (@pxref{Association
-Lists}) in which each association contains one buffer-local variable and
-its value. When a buffer-local variable is void in @var{buffer}, then
-it appears directly in the resulting list. If @var{buffer} is omitted,
-the current buffer is used.
-
-@example
-@group
-(make-local-variable 'foobar)
-(makunbound 'foobar)
-(make-local-variable 'bind-me)
-(setq bind-me 69)
-@end group
-(setq lcl (buffer-local-variables))
- ;; @r{First, built-in variables local in all buffers:}
-@result{} ((mark-active . nil)
- (buffer-undo-list nil)
- (mode-name . "Fundamental")
- @dots{}
-@group
- ;; @r{Next, non-built-in local variables.}
- ;; @r{This one is local and void:}
- foobar
- ;; @r{This one is local and nonvoid:}
- (bind-me . 69))
-@end group
-@end example
-
-Note that storing new values into the @sc{cdr}s of cons cells in this
-list does @emph{not} change the local values of the variables.
-@end defun
-
-@deffn Command kill-local-variable variable
-This function deletes the buffer-local binding (if any) for
-@var{variable} (a symbol) in the current buffer. As a result, the
-global (default) binding of @var{variable} becomes visible in this
-buffer. Usually this results in a change in the value of
-@var{variable}, since the global value is usually different from the
-buffer-local value just eliminated.
-
-If you kill the local binding of a variable that automatically becomes
-local when set, this makes the global value visible in the current
-buffer. However, if you set the variable again, that will once again
-create a local binding for it.
-
-@code{kill-local-variable} returns @var{variable}.
-
-This function is a command because it is sometimes useful to kill one
-buffer-local variable interactively, just as it is useful to create
-buffer-local variables interactively.
-@end deffn
-
-@defun kill-all-local-variables
-This function eliminates all the buffer-local variable bindings of the
-current buffer except for variables marked as ``permanent''. As a
-result, the buffer will see the default values of most variables.
-
-This function also resets certain other information pertaining to the
-buffer: it sets the local keymap to @code{nil}, the syntax table to the
-value of @code{standard-syntax-table}, and the abbrev table to the value
-of @code{fundamental-mode-abbrev-table}.
-
-Every major mode command begins by calling this function, which has the
-effect of switching to Fundamental mode and erasing most of the effects
-of the previous major mode. To ensure that this does its job, the
-variables that major modes set should not be marked permanent.
-
-@code{kill-all-local-variables} returns @code{nil}.
-@end defun
-
-@c Emacs 19 feature
-@cindex permanent local variable
-A local variable is @dfn{permanent} if the variable name (a symbol) has a
-@code{permanent-local} property that is non-@code{nil}. Permanent
-locals are appropriate for data pertaining to where the file came from
-or how to save it, rather than with how to edit the contents.
-
-@node Default Value
-@subsection The Default Value of a Buffer-Local Variable
-@cindex default value
-
- The global value of a variable with buffer-local bindings is also
-called the @dfn{default} value, because it is the value that is in
-effect except when specifically overridden.
-
- The functions @code{default-value} and @code{setq-default} access and
-change a variable's default value regardless of whether the current
-buffer has a buffer-local binding. For example, you could use
-@code{setq-default} to change the default setting of
-@code{paragraph-start} for most buffers; and this would work even when
-you are in a C or Lisp mode buffer that has a buffer-local value for
-this variable.
-
-@c Emacs 19 feature
- The special forms @code{defvar} and @code{defconst} also set the
-default value (if they set the variable at all), rather than any local
-value.
-
-@defun default-value symbol
-This function returns @var{symbol}'s default value. This is the value
-that is seen in buffers that do not have their own values for this
-variable. If @var{symbol} is not buffer-local, this is equivalent to
-@code{symbol-value} (@pxref{Accessing Variables}).
-@end defun
-
-@c Emacs 19 feature
-@defun default-boundp symbol
-The function @code{default-boundp} tells you whether @var{symbol}'s
-default value is nonvoid. If @code{(default-boundp 'foo)} returns
-@code{nil}, then @code{(default-value 'foo)} would get an error.
-
-@code{default-boundp} is to @code{default-value} as @code{boundp} is to
-@code{symbol-value}.
-@end defun
-
-@defspec setq-default symbol value
-This sets the default value of @var{symbol} to @var{value}. It does not
-evaluate @var{symbol}, but does evaluate @var{value}. The value of the
-@code{setq-default} form is @var{value}.
-
-If a @var{symbol} is not buffer-local for the current buffer, and is not
-marked automatically buffer-local, @code{setq-default} has the same
-effect as @code{setq}. If @var{symbol} is buffer-local for the current
-buffer, then this changes the value that other buffers will see (as long
-as they don't have a buffer-local value), but not the value that the
-current buffer sees.
-
-@example
-@group
-;; @r{In buffer @samp{foo}:}
-(make-local-variable 'local)
- @result{} local
-@end group
-@group
-(setq local 'value-in-foo)
- @result{} value-in-foo
-@end group
-@group
-(setq-default local 'new-default)
- @result{} new-default
-@end group
-@group
-local
- @result{} value-in-foo
-@end group
-@group
-(default-value 'local)
- @result{} new-default
-@end group
-
-@group
-;; @r{In (the new) buffer @samp{bar}:}
-local
- @result{} new-default
-@end group
-@group
-(default-value 'local)
- @result{} new-default
-@end group
-@group
-(setq local 'another-default)
- @result{} another-default
-@end group
-@group
-(default-value 'local)
- @result{} another-default
-@end group
-
-@group
-;; @r{Back in buffer @samp{foo}:}
-local
- @result{} value-in-foo
-(default-value 'local)
- @result{} another-default
-@end group
-@end example
-@end defspec
-
-@defun set-default symbol value
-This function is like @code{setq-default}, except that @var{symbol} is
-evaluated.
-
-@example
-@group
-(set-default (car '(a b c)) 23)
- @result{} 23
-@end group
-@group
-(default-value 'a)
- @result{} 23
-@end group
-@end example
-@end defun
diff --git a/lispref/windows.texi b/lispref/windows.texi
deleted file mode 100644
index 36b422d21c7..00000000000
--- a/lispref/windows.texi
+++ /dev/null
@@ -1,1817 +0,0 @@
-@c -*-texinfo-*-
-@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-@c See the file elisp.texi for copying conditions.
-@setfilename ../info/windows
-@node Windows, Frames, Buffers, Top
-@chapter Windows
-
- This chapter describes most of the functions and variables related to
-Emacs windows. See @ref{Display}, for information on how text is
-displayed in windows.
-
-@menu
-* Basic Windows:: Basic information on using windows.
-* Splitting Windows:: Splitting one window into two windows.
-* Deleting Windows:: Deleting a window gives its space to other windows.
-* Selecting Windows:: The selected window is the one that you edit in.
-* Cyclic Window Ordering:: Moving around the existing windows.
-* Buffers and Windows:: Each window displays the contents of a buffer.
-* Displaying Buffers:: Higher-lever functions for displaying a buffer
- and choosing a window for it.
-* Choosing Window:: How to choose a window for displaying a buffer.
-* Window Point:: Each window has its own location of point.
-* Window Start:: The display-start position controls which text
- is on-screen in the window.
-* Vertical Scrolling:: Moving text up and down in the window.
-* Scrolling Hooks:: Hooks that run when you scroll a window.
-* Horizontal Scrolling:: Moving text sideways on the window.
-* Size of Window:: Accessing the size of a window.
-* Resizing Windows:: Changing the size of a window.
-* Coordinates and Windows:: Converting coordinates to windows.
-* Window Configurations:: Saving and restoring the state of the screen.
-@end menu
-
-@node Basic Windows
-@section Basic Concepts of Emacs Windows
-@cindex window
-@cindex selected window
-
- A @dfn{window} in Emacs is the physical area of the screen in which a
-buffer is displayed. The term is also used to refer to a Lisp object that
-represents that screen area in Emacs Lisp. It should be
-clear from the context which is meant.
-
- Emacs groups windows into frames. A frame represents an area of
-screen available for Emacs to use. Each frame always contains at least
-one window, but you can subdivide it vertically or horizontally into
-multiple nonoverlapping Emacs windows.
-
- In each frame, at any time, one and only one window is designated as
-@dfn{selected within the frame}. The frame's cursor appears in that
-window. At ant time, one frame is the selected frame; and the window
-selected within that frame is @dfn{the selected window}. The selected
-window's buffer is usually the current buffer (except when
-@code{set-buffer} has been used). @xref{Current Buffer}.
-
- For practical purposes, a window exists only while it is displayed in
-a frame. Once removed from the frame, the window is effectively deleted
-and should not be used, @emph{even though there may still be references
-to it} from other Lisp objects. Restoring a saved window configuration
-is the only way for a window no longer on the screen to come back to
-life. (@xref{Deleting Windows}.)
-
- Each window has the following attributes:
-
-@itemize @bullet
-@item
-containing frame
-
-@item
-window height
-
-@item
-window width
-
-@item
-window edges with respect to the screen or frame
-
-@item
-the buffer it displays
-
-@item
-position within the buffer at the upper left of the window
-
-@item
-amount of horizontal scrolling, in columns
-
-@item
-point
-
-@item
-the mark
-
-@item
-how recently the window was selected
-@end itemize
-
-@cindex multiple windows
- Users create multiple windows so they can look at several buffers at
-once. Lisp libraries use multiple windows for a variety of reasons, but
-most often to display related information. In Rmail, for example, you
-can move through a summary buffer in one window while the other window
-shows messages one at a time as they are reached.
-
- The meaning of ``window'' in Emacs is similar to what it means in the
-context of general-purpose window systems such as X, but not identical.
-The X Window System places X windows on the screen; Emacs uses one or
-more X windows as frames, and subdivides them into
-Emacs windows. When you use Emacs on a character-only terminal, Emacs
-treats the whole terminal screen as one frame.
-
-@cindex terminal screen
-@cindex screen of terminal
-@cindex tiled windows
- Most window systems support arbitrarily located overlapping windows.
-In contrast, Emacs windows are @dfn{tiled}; they never overlap, and
-together they fill the whole screen or frame. Because of the way
-in which Emacs creates new windows and resizes them, you can't create
-every conceivable tiling of windows on an Emacs frame. @xref{Splitting
-Windows}, and @ref{Size of Window}.
-
- @xref{Display}, for information on how the contents of the
-window's buffer are displayed in the window.
-
-@defun windowp object
- This function returns @code{t} if @var{object} is a window.
-@end defun
-
-@node Splitting Windows
-@section Splitting Windows
-@cindex splitting windows
-@cindex window splitting
-
- The functions described here are the primitives used to split a window
-into two windows. Two higher level functions sometimes split a window,
-but not always: @code{pop-to-buffer} and @code{display-buffer}
-(@pxref{Displaying Buffers}).
-
- The functions described here do not accept a buffer as an argument.
-The two ``halves'' of the split window initially display the same buffer
-previously visible in the window that was split.
-
-@deffn Command split-window &optional window size horizontal
-This function splits @var{window} into two windows. The original
-window @var{window} remains the selected window, but occupies only
-part of its former screen area. The rest is occupied by a newly created
-window which is returned as the value of this function.
-
- If @var{horizontal} is non-@code{nil}, then @var{window} splits into
-two side by side windows. The original window @var{window} keeps the
-leftmost @var{size} columns, and gives the rest of the columns to the
-new window. Otherwise, it splits into windows one above the other, and
-@var{window} keeps the upper @var{size} lines and gives the rest of the
-lines to the new window. The original window is therefore the
-left-hand or upper of the two, and the new window is the right-hand or
-lower.
-
- If @var{window} is omitted or @code{nil}, then the selected window is
-split. If @var{size} is omitted or @code{nil}, then @var{window} is
-divided evenly into two parts. (If there is an odd line, it is
-allocated to the new window.) When @code{split-window} is called
-interactively, all its arguments are @code{nil}.
-
- The following example starts with one window on a screen that is 50
-lines high by 80 columns wide; then the window is split.
-
-@smallexample
-@group
-(setq w (selected-window))
- @result{} #<window 8 on windows.texi>
-(window-edges) ; @r{Edges in order:}
- @result{} (0 0 80 50) ; @r{left--top--right--bottom}
-@end group
-
-@group
-;; @r{Returns window created}
-(setq w2 (split-window w 15))
- @result{} #<window 28 on windows.texi>
-@end group
-@group
-(window-edges w2)
- @result{} (0 15 80 50) ; @r{Bottom window;}
- ; @r{top is line 15}
-@end group
-@group
-(window-edges w)
- @result{} (0 0 80 15) ; @r{Top window}
-@end group
-@end smallexample
-
-The screen looks like this:
-
-@smallexample
-@group
- __________
- | | line 0
- | w |
- |__________|
- | | line 15
- | w2 |
- |__________|
- line 50
- column 0 column 80
-@end group
-@end smallexample
-
-Next, the top window is split horizontally:
-
-@smallexample
-@group
-(setq w3 (split-window w 35 t))
- @result{} #<window 32 on windows.texi>
-@end group
-@group
-(window-edges w3)
- @result{} (35 0 80 15) ; @r{Left edge at column 35}
-@end group
-@group
-(window-edges w)
- @result{} (0 0 35 15) ; @r{Right edge at column 35}
-@end group
-@group
-(window-edges w2)
- @result{} (0 15 80 50) ; @r{Bottom window unchanged}
-@end group
-@end smallexample
-
-@need 3000
-Now, the screen looks like this:
-
-@smallexample
-@group
- column 35
- __________
- | | | line 0
- | w | w3 |
- |___|______|
- | | line 15
- | w2 |
- |__________|
- line 50
- column 0 column 80
-@end group
-@end smallexample
-
-Normally, Emacs indicates the border between two side-by-side windows
-with a scroll bar (@pxref{X Frame Parameters,Scroll Bars}) or @samp{|}
-characters. The display table can specify alternative border
-characters; see @ref{Display Tables}.
-@end deffn
-
-@deffn Command split-window-vertically size
-This function splits the selected window into two windows, one above
-the other, leaving the selected window with @var{size} lines.
-
-This function is simply an interface to @code{split-windows}.
-Here is the complete function definition for it:
-
-@smallexample
-@group
-(defun split-window-vertically (&optional arg)
- "Split current window into two windows, @dots{}"
- (interactive "P")
- (split-window nil (and arg (prefix-numeric-value arg))))
-@end group
-@end smallexample
-@end deffn
-
-@deffn Command split-window-horizontally size
-This function splits the selected window into two windows
-side-by-side, leaving the selected window with @var{size} columns.
-
-This function is simply an interface to @code{split-windows}. Here is
-the complete definition for @code{split-window-horizontally} (except for
-part of the documentation string):
-
-@smallexample
-@group
-(defun split-window-horizontally (&optional arg)
- "Split selected window into two windows, side by side..."
- (interactive "P")
- (split-window nil (and arg (prefix-numeric-value arg)) t))
-@end group
-@end smallexample
-@end deffn
-
-@defun one-window-p &optional no-mini all-frames
-This function returns non-@code{nil} if there is only one window. The
-argument @var{no-mini}, if non-@code{nil}, means don't count the
-minibuffer even if it is active; otherwise, the minibuffer window is
-included, if active, in the total number of windows, which is compared
-against one.
-
-The argument @var{all-frames} specifies which frames to consider. Here
-are the possible values and their meanings:
-
-@table @asis
-@item @code{nil}
-Count the windows in the selected frame, plus the minibuffer used
-by that frame even if it lies in some other frame.
-
-@item @code{t}
-Count all windows in all existing frames.
-
-@item @code{visible}
-Count all windows in all visible frames.
-
-@item 0
-Count all windows in all visible or iconified frames.
-
-@item anything else
-Count precisely the windows in the selected frame, and no others.
-@end table
-@end defun
-
-@node Deleting Windows
-@section Deleting Windows
-@cindex deleting windows
-
-A window remains visible on its frame unless you @dfn{delete} it by
-calling certain functions that delete windows. A deleted window cannot
-appear on the screen, but continues to exist as a Lisp object until
-there are no references to it. There is no way to cancel the deletion
-of a window aside from restoring a saved window configuration
-(@pxref{Window Configurations}). Restoring a window configuration also
-deletes any windows that aren't part of that configuration.
-
- When you delete a window, the space it took up is given to one
-adjacent sibling. (In Emacs version 18, the space was divided evenly
-among all the siblings.)
-
-@c Emacs 19 feature
-@defun window-live-p window
-This function returns @code{nil} if @var{window} is deleted, and
-@code{t} otherwise.
-
-@strong{Warning:} Erroneous information or fatal errors may result from
-using a deleted window as if it were live.
-@end defun
-
-@deffn Command delete-window &optional window
-This function removes @var{window} from the display. If @var{window}
-is omitted, then the selected window is deleted. An error is signaled
-if there is only one window when @code{delete-window} is called.
-
-This function returns @code{nil}.
-
-When @code{delete-window} is called interactively, @var{window}
-defaults to the selected window.
-@end deffn
-
-@deffn Command delete-other-windows &optional window
-This function makes @var{window} the only window on its frame, by
-deleting the other windows in that frame. If @var{window} is omitted or
-@code{nil}, then the selected window is used by default.
-
-The result is @code{nil}.
-@end deffn
-
-@deffn Command delete-windows-on buffer &optional frame
-This function deletes all windows showing @var{buffer}. If there are
-no windows showing @var{buffer}, it does nothing.
-
-@code{delete-windows-on} operates frame by frame. If a frame has
-several windows showing different buffers, then those showing
-@var{buffer} are removed, and the others expand to fill the space. If
-all windows in some frame are showing @var{buffer} (including the case
-where there is only one window), then the frame reverts to having a
-single window showing another buffer chosen with @code{other-buffer}.
-@xref{The Buffer List}.
-
-The argument @var{frame} controls which frames to operate on:
-
-@itemize @bullet
-@item
-If it is @code{nil}, operate on the selected frame.
-@item
-If it is @code{t}, operate on all frames.
-@item
-If it is @code{visible}, operate on all visible frames.
-@item 0
-If it is 0, operate on all visible or iconified frames.
-@item
-If it is a frame, operate on that frame.
-@end itemize
-
-This function always returns @code{nil}.
-@end deffn
-
-@node Selecting Windows
-@section Selecting Windows
-@cindex selecting windows
-
- When a window is selected, the buffer in the window becomes the current
-buffer, and the cursor will appear in it.
-
-@defun selected-window
-This function returns the selected window. This is the window in
-which the cursor appears and to which many commands apply.
-@end defun
-
-@defun select-window window
-This function makes @var{window} the selected window. The cursor then
-appears in @var{window} (on redisplay). The buffer being displayed in
-@var{window} is immediately designated the current buffer.
-
-The return value is @var{window}.
-
-@example
-@group
-(setq w (next-window))
-(select-window w)
- @result{} #<window 65 on windows.texi>
-@end group
-@end example
-@end defun
-
-@defmac save-selected-window forms@dots{}
-This macro records the selected window, executes @var{forms}
-in sequence, then restores the earlier selected window.
-
-This macro does not save or restore anything about the sizes, arrangement
-or contents of windows; therefore, if the @var{forms} change them,
-the change persists.
-
-Each frame, at any time, has a window selected within the frame. This
-macro only saves @emph{the} selected window; it does not save anything
-about other frames. If the @var{forms} select some other frame and
-alter the window selected within it, the change persists.
-@end defmac
-
-@cindex finding windows
- The following functions choose one of the windows on the screen,
-offering various criteria for the choice.
-
-@defun get-lru-window &optional frame
-This function returns the window least recently ``used'' (that is,
-selected). The selected window is always the most recently used window.
-
-The selected window can be the least recently used window if it is the
-only window. A newly created window becomes the least recently used
-window until it is selected. A minibuffer window is never a candidate.
-
-The argument @var{frame} controls which windows are considered.
-
-@itemize @bullet
-@item
-If it is @code{nil}, consider windows on the selected frame.
-@item
-If it is @code{t}, consider windows on all frames.
-@item
-If it is @code{visible}, consider windows on all visible frames.
-@item
-If it is 0, consider windows on all visible or iconified frames.
-@item
-If it is a frame, consider windows on that frame.
-@end itemize
-@end defun
-
-@defun get-largest-window &optional frame
-This function returns the window with the largest area (height times
-width). If there are no side-by-side windows, then this is the window
-with the most lines. A minibuffer window is never a candidate.
-
-If there are two windows of the same size, then the function returns
-the window that is first in the cyclic ordering of windows (see
-following section), starting from the selected window.
-
-The argument @var{frame} controls which set of windows are
-considered. See @code{get-lru-window}, above.
-@end defun
-
-@node Cyclic Window Ordering
-@comment node-name, next, previous, up
-@section Cyclic Ordering of Windows
-@cindex cyclic ordering of windows
-@cindex ordering of windows, cyclic
-@cindex window ordering, cyclic
-
- When you use the command @kbd{C-x o} (@code{other-window}) to select
-the next window, it moves through all the windows on the screen in a
-specific cyclic order. For any given configuration of windows, this
-order never varies. It is called the @dfn{cyclic ordering of windows}.
-
- This ordering generally goes from top to bottom, and from left to
-right. But it may go down first or go right first, depending on the
-order in which the windows were split.
-
- If the first split was vertical (into windows one above each other),
-and then the subwindows were split horizontally, then the ordering is
-left to right in the top of the frame, and then left to right in the
-next lower part of the frame, and so on. If the first split was
-horizontal, the ordering is top to bottom in the left part, and so on.
-In general, within each set of siblings at any level in the window tree,
-the order is left to right, or top to bottom.
-
-@defun next-window &optional window minibuf all-frames
-@cindex minibuffer window
-This function returns the window following @var{window} in the cyclic
-ordering of windows. This is the window that @kbd{C-x o} would select
-if typed when @var{window} is selected. If @var{window} is the only
-window visible, then this function returns @var{window}. If omitted,
-@var{window} defaults to the selected window.
-
-The value of the argument @var{minibuf} determines whether the
-minibuffer is included in the window order. Normally, when
-@var{minibuf} is @code{nil}, the minibuffer is included if it is
-currently active; this is the behavior of @kbd{C-x o}. (The minibuffer
-window is active while the minibuffer is in use. @xref{Minibuffers}.)
-
-If @var{minibuf} is @code{t}, then the cyclic ordering includes the
-minibuffer window even if it is not active.
-
-If @var{minibuf} is neither @code{t} nor @code{nil}, then the minibuffer
-window is not included even if it is active.
-
-The argument @var{all-frames} specifies which frames to consider. Here
-are the possible values and their meanings:
-
-@table @asis
-@item @code{nil}
-Consider all the windows in @var{window}'s frame, plus the minibuffer
-used by that frame even if it lies in some other frame.
-
-@item @code{t}
-Consider all windows in all existing frames.
-
-@item @code{visible}
-Consider all windows in all visible frames. (To get useful results, you
-must ensure @var{window} is in a visible frame.)
-
-@item 0
-Consider all windows in all visible or iconified frames.
-
-@item anything else
-Consider precisely the windows in @var{window}'s frame, and no others.
-@end table
-
-This example assumes there are two windows, both displaying the
-buffer @samp{windows.texi}:
-
-@example
-@group
-(selected-window)
- @result{} #<window 56 on windows.texi>
-@end group
-@group
-(next-window (selected-window))
- @result{} #<window 52 on windows.texi>
-@end group
-@group
-(next-window (next-window (selected-window)))
- @result{} #<window 56 on windows.texi>
-@end group
-@end example
-@end defun
-
-@defun previous-window &optional window minibuf all-frames
-This function returns the window preceding @var{window} in the cyclic
-ordering of windows. The other arguments specify which windows to
-include in the cycle, as in @code{next-window}.
-@end defun
-
-@deffn Command other-window count
-This function selects the @var{count}th following window in the cyclic
-order. If count is negative, then it selects the @minus{}@var{count}th
-preceding window. It returns @code{nil}.
-
-In an interactive call, @var{count} is the numeric prefix argument.
-@end deffn
-
-@c Emacs 19 feature
-@defun walk-windows proc &optional minibuf all-frames
-This function cycles through all windows, calling @code{proc}
-once for each window with the window as its sole argument.
-
-The optional arguments @var{minibuf} and @var{all-frames} specify the
-set of windows to include in the scan. See @code{next-window}, above,
-for details.
-@end defun
-
-@node Buffers and Windows
-@section Buffers and Windows
-@cindex examining windows
-@cindex windows, controlling precisely
-@cindex buffers, controlled in windows
-
- This section describes low-level functions to examine windows or to
-display buffers in windows in a precisely controlled fashion.
-@iftex
-See the following section for
-@end iftex
-@ifinfo
-@xref{Displaying Buffers}, for
-@end ifinfo
-related functions that find a window to use and specify a buffer for it.
-The functions described there are easier to use than these, but they
-employ heuristics in choosing or creating a window; use these functions
-when you need complete control.
-
-@defun set-window-buffer window buffer-or-name
-This function makes @var{window} display @var{buffer-or-name} as its
-contents. It returns @code{nil}.
-
-@example
-@group
-(set-window-buffer (selected-window) "foo")
- @result{} nil
-@end group
-@end example
-@end defun
-
-@defun window-buffer &optional window
-This function returns the buffer that @var{window} is displaying. If
-@var{window} is omitted, this function returns the buffer for the
-selected window.
-
-@example
-@group
-(window-buffer)
- @result{} #<buffer windows.texi>
-@end group
-@end example
-@end defun
-
-@defun get-buffer-window buffer-or-name &optional all-frames
-This function returns a window currently displaying
-@var{buffer-or-name}, or @code{nil} if there is none. If there are
-several such windows, then the function returns the first one in the
-cyclic ordering of windows, starting from the selected window.
-@xref{Cyclic Window Ordering}.
-
-The argument @var{all-frames} controls which windows to consider.
-
-@itemize @bullet
-@item
-If it is @code{nil}, consider windows on the selected frame.
-@item
-If it is @code{t}, consider windows on all frames.
-@item
-If it is @code{visible}, consider windows on all visible frames.
-@item
-If it is 0, consider windows on all visible or iconified frames.
-@item
-If it is a frame, consider windows on that frame.
-@end itemize
-@end defun
-
-@defun get-buffer-window-list buffer-or-name &optional minibuf all-frames
-This function returns a list of all the windows currently displaying
-@var{buffer-or-name}.
-
-The two optional arguments work like the optional arguments of
-@code{next-window} (@pxref{Cyclic Window Ordering}); they are @emph{not}
-like the single optional argument of @code{get-buffer-window}. Perhaps
-we should change @code{get-buffer-window} in the future to make it
-compatible with the other functions.
-
-The argument @var{all-frames} controls which windows to consider.
-
-@itemize @bullet
-@item
-If it is @code{nil}, consider windows on the selected frame.
-@item
-If it is @code{t}, consider windows on all frames.
-@item
-If it is @code{visible}, consider windows on all visible frames.
-@item
-If it is 0, consider windows on all visible or iconified frames.
-@item
-If it is a frame, consider windows on that frame.
-@end itemize
-@end defun
-
-@node Displaying Buffers
-@section Displaying Buffers in Windows
-@cindex switching to a buffer
-@cindex displaying a buffer
-
- In this section we describe convenient functions that choose a window
-automatically and use it to display a specified buffer. These functions
-can also split an existing window in certain circumstances. We also
-describe variables that parameterize the heuristics used for choosing a
-window.
-@iftex
-See the preceding section for
-@end iftex
-@ifinfo
-@xref{Buffers and Windows}, for
-@end ifinfo
-low-level functions that give you more precise control.
-
- Do not use the functions in this section in order to make a buffer
-current so that a Lisp program can access or modify it; they are too
-drastic for that purpose, since they change the display of buffers in
-windows, which is gratuitous and will surprise the user. Instead, use
-@code{set-buffer} (@pxref{Current Buffer}) and @code{save-excursion}
-(@pxref{Excursions}), which designate buffers as current for programmed
-access without affecting the display of buffers in windows.
-
-@deffn Command switch-to-buffer buffer-or-name &optional norecord
-This function makes @var{buffer-or-name} the current buffer, and also
-displays the buffer in the selected window. This means that a human can
-see the buffer and subsequent keyboard commands will apply to it.
-Contrast this with @code{set-buffer}, which makes @var{buffer-or-name}
-the current buffer but does not display it in the selected window.
-@xref{Current Buffer}.
-
-If @var{buffer-or-name} does not identify an existing buffer, then a new
-buffer by that name is created. The major mode for the new buffer is
-set according to the variable @code{default-major-mode}. @xref{Auto
-Major Mode}.
-
-Normally the specified buffer is put at the front of the buffer list.
-This affects the operation of @code{other-buffer}. However, if
-@var{norecord} is non-@code{nil}, this is not done. @xref{The Buffer
-List}.
-
-The @code{switch-to-buffer} function is often used interactively, as
-the binding of @kbd{C-x b}. It is also used frequently in programs. It
-always returns @code{nil}.
-@end deffn
-
-@deffn Command switch-to-buffer-other-window buffer-or-name
-This function makes @var{buffer-or-name} the current buffer and
-displays it in a window not currently selected. It then selects that
-window. The handling of the buffer is the same as in
-@code{switch-to-buffer}.
-
-The currently selected window is absolutely never used to do the job.
-If it is the only window, then it is split to make a distinct window for
-this purpose. If the selected window is already displaying the buffer,
-then it continues to do so, but another window is nonetheless found to
-display it in as well.
-@end deffn
-
-@defun pop-to-buffer buffer-or-name &optional other-window
-This function makes @var{buffer-or-name} the current buffer and
-switches to it in some window, preferably not the window previously
-selected. The ``popped-to'' window becomes the selected window within
-its frame.
-
-If the variable @code{pop-up-frames} is non-@code{nil},
-@code{pop-to-buffer} looks for a window in any visible frame already
-displaying the buffer; if there is one, it returns that window and makes
-it be selected within its frame. If there is none, it creates a new
-frame and displays the buffer in it.
-
-If @code{pop-up-frames} is @code{nil}, then @code{pop-to-buffer}
-operates entirely within the selected frame. (If the selected frame has
-just a minibuffer, @code{pop-to-buffer} operates within the most
-recently selected frame that was not just a minibuffer.)
-
-If the variable @code{pop-up-windows} is non-@code{nil}, windows may
-be split to create a new window that is different from the original
-window. For details, see @ref{Choosing Window}.
-
-If @var{other-window} is non-@code{nil}, @code{pop-to-buffer} finds or
-creates another window even if @var{buffer-or-name} is already visible
-in the selected window. Thus @var{buffer-or-name} could end up
-displayed in two windows. On the other hand, if @var{buffer-or-name} is
-already displayed in the selected window and @var{other-window} is
-@code{nil}, then the selected window is considered sufficient display
-for @var{buffer-or-name}, so that nothing needs to be done.
-
-All the variables that affect @code{display-buffer} affect
-@code{pop-to-buffer} as well. @xref{Choosing Window}.
-
-If @var{buffer-or-name} is a string that does not name an existing
-buffer, a buffer by that name is created. The major mode for the new
-buffer is set according to the variable @code{default-major-mode}.
-@xref{Auto Major Mode}.
-@end defun
-
-@deffn Command replace-buffer-in-windows buffer
-This function replaces @var{buffer} with some other buffer in all
-windows displaying it. The other buffer used is chosen with
-@code{other-buffer}. In the usual applications of this function, you
-don't care which other buffer is used; you just want to make sure that
-@var{buffer} is no longer displayed.
-
-This function returns @code{nil}.
-@end deffn
-
-@node Choosing Window
-@section Choosing a Window for Display
-
- This section describes the basic facility that chooses a window to
-display a buffer in---@code{display-buffer}. All the higher-level
-functions and commands use this subroutine. Here we describe how to use
-@code{display-buffer} and how to customize it.
-
-@deffn Command display-buffer buffer-or-name &optional not-this-window
-This command makes @var{buffer-or-name} appear in some window, like
-@code{pop-to-buffer}, but it does not select that window and does not
-make the buffer current. The identity of the selected window is
-unaltered by this function.
-
-If @var{not-this-window} is non-@code{nil}, it means to display the
-specified buffer in a window other than the selected one, even if it is
-already on display in the selected window. This can cause the buffer to
-appear in two windows at once. Otherwise, if @var{buffer-or-name} is
-already being displayed in any window, that is good enough, so this
-function does nothing.
-
-@code{display-buffer} returns the window chosen to display
-@var{buffer-or-name}.
-
-Precisely how @code{display-buffer} finds or creates a window depends on
-the variables described below.
-@end deffn
-
-@defopt pop-up-windows
-This variable controls whether @code{display-buffer} makes new windows.
-If it is non-@code{nil} and there is only one window, then that window
-is split. If it is @code{nil}, then @code{display-buffer} does not
-split the single window, but uses it whole.
-@end defopt
-
-@defopt split-height-threshold
-This variable determines when @code{display-buffer} may split a window,
-if there are multiple windows. @code{display-buffer} always splits the
-largest window if it has at least this many lines. If the largest
-window is not this tall, it is split only if it is the sole window and
-@code{pop-up-windows} is non-@code{nil}.
-@end defopt
-
-@c Emacs 19 feature
-@defopt pop-up-frames
-This variable controls whether @code{display-buffer} makes new frames.
-If it is non-@code{nil}, @code{display-buffer} looks for an existing
-window already displaying the desired buffer, on any visible frame. If
-it finds one, it returns that window. Otherwise it makes a new frame.
-The variables @code{pop-up-windows} and @code{split-height-threshold} do
-not matter if @code{pop-up-frames} is non-@code{nil}.
-
-If @code{pop-up-frames} is @code{nil}, then @code{display-buffer} either
-splits a window or reuses one.
-
-@xref{Frames}, for more information.
-@end defopt
-
-@c Emacs 19 feature
-@defvar pop-up-frame-function
-This variable specifies how to make a new frame if @code{pop-up-frames}
-is non-@code{nil}.
-
-Its value should be a function of no arguments. When
-@code{display-buffer} makes a new frame, it does so by calling that
-function, which should return a frame. The default value of the
-variable is a function that creates a frame using parameters from
-@code{pop-up-frame-alist}.
-@end defvar
-
-@defvar pop-up-frame-alist
-This variable holds an alist specifying frame parameters used when
-@code{display-buffer} makes a new frame. @xref{Frame Parameters}, for
-more information about frame parameters.
-@end defvar
-
-@defvar special-display-buffer-names
-A list of buffer names for buffers that should be displayed specially.
-If the buffer's name is in this list, @code{display-buffer} handles the
-buffer specially.
-
-By default, special display means to give the buffer a dedicated frame.
-
-If an element is a list, instead of a string, then the @sc{car} of the
-list is the buffer name, and the rest of the list says how to create the
-frame. There are two possibilities for the rest of the list. It can be
-an alist, specifying frame parameters, or it can contain a function and
-arguments to give to it. (The function's first argument is always the
-buffer to be displayed; the arguments from the list come after that.)
-@end defvar
-
-@defvar special-display-regexps
-A list of regular expressions that specify buffers that should be
-displayed specially. If the buffer's name matches any of the regular
-expressions in this list, @code{display-buffer} handles the buffer
-specially.
-
-By default, special display means to give the buffer a dedicated frame.
-
-If an element is a list, instead of a string, then the @sc{car} of the
-list is the regular expression, and the rest of the list says how to
-create the frame. See above, under @code{special-display-buffer-names}.
-@end defvar
-
-@defvar special-display-function
-This variable holds the function to call to display a buffer specially.
-It receives the buffer as an argument, and should return the window in
-which it is displayed.
-
-The default value of this variable is
-@code{special-display-popup-frame}.
-@end defvar
-
-@defun special-display-popup-frame buffer
-This function makes @var{buffer} visible in a frame of its own. If
-@var{buffer} is already displayed in a window in some frame, it makes
-the frame visible and raises it, to use that window. Otherwise, it
-creates a frame that will be dedicated to @var{buffer}.
-
-This function uses an existing window displaying @var{buffer} whether or
-not it is in a frame of its own; but if you set up the above variables
-in your init file, before @var{buffer} was created, then presumably the
-window was previously made by this function.
-@end defun
-
-@defopt special-display-frame-alist
-This variable holds frame parameters for
-@code{special-display-popup-frame} to use when it creates a frame.
-@end defopt
-
-@defopt same-window-buffer-names
-A list of buffer names for buffers that should be displayed in the
-selected window. If the buffer's name is in this list,
-@code{display-buffer} handles the buffer by switching to it in the
-selected window.
-@end defopt
-
-@defopt same-window-regexps
-A list of regular expressions that specify buffers that should be
-displayed in the selected window. If the buffer's name matches any of
-the regular expressions in this list, @code{display-buffer} handles the
-buffer by switching to it in the selected window.
-@end defopt
-
-@c Emacs 19 feature
-@defvar display-buffer-function
-This variable is the most flexible way to customize the behavior of
-@code{display-buffer}. If it is non-@code{nil}, it should be a function
-that @code{display-buffer} calls to do the work. The function should
-accept two arguments, the same two arguments that @code{display-buffer}
-received. It should choose or create a window, display the specified
-buffer, and then return the window.
-
-This hook takes precedence over all the other options and hooks
-described above.
-@end defvar
-
-@c Emacs 19 feature
-@cindex dedicated window
-A window can be marked as ``dedicated'' to its buffer. Then
-@code{display-buffer} does not try to use that window.
-
-@defun window-dedicated-p window
-This function returns @code{t} if @var{window} is marked as dedicated;
-otherwise @code{nil}.
-@end defun
-
-@defun set-window-dedicated-p window flag
-This function marks @var{window} as dedicated if @var{flag} is
-non-@code{nil}, and nondedicated otherwise.
-@end defun
-
-@node Window Point
-@section Windows and Point
-@cindex window position
-@cindex window point
-@cindex position in window
-@cindex point in window
-
- Each window has its own value of point, independent of the value of
-point in other windows displaying the same buffer. This makes it useful
-to have multiple windows showing one buffer.
-
-@itemize @bullet
-@item
-The window point is established when a window is first created; it is
-initialized from the buffer's point, or from the window point of another
-window opened on the buffer if such a window exists.
-
-@item
-Selecting a window sets the value of point in its buffer to the window's
-value of point. Conversely, deselecting a window sets the window's
-value of point from that of the buffer. Thus, when you switch between
-windows that display a given buffer, the point value for the selected
-window is in effect in the buffer, while the point values for the other
-windows are stored in those windows.
-
-@item
-As long as the selected window displays the current buffer, the window's
-point and the buffer's point always move together; they remain equal.
-
-@item
-@xref{Positions}, for more details on buffer positions.
-@end itemize
-
- As far as the user is concerned, point is where the cursor is, and
-when the user switches to another buffer, the cursor jumps to the
-position of point in that buffer.
-
-@defun window-point window
-This function returns the current position of point in @var{window}.
-For a nonselected window, this is the value point would have (in that
-window's buffer) if that window were selected.
-
-When @var{window} is the selected window and its buffer is also the
-current buffer, the value returned is the same as point in that buffer.
-
-Strictly speaking, it would be more correct to return the
-``top-level'' value of point, outside of any @code{save-excursion}
-forms. But that value is hard to find.
-@end defun
-
-@defun set-window-point window position
-This function positions point in @var{window} at position
-@var{position} in @var{window}'s buffer.
-@end defun
-
-@node Window Start
-@section The Window Start Position
-
- Each window contains a marker used to keep track of a buffer position
-that specifies where in the buffer display should start. This position
-is called the @dfn{display-start} position of the window (or just the
-@dfn{start}). The character after this position is the one that appears
-at the upper left corner of the window. It is usually, but not
-inevitably, at the beginning of a text line.
-
-@defun window-start &optional window
-@cindex window top line
-This function returns the display-start position of window
-@var{window}. If @var{window} is @code{nil}, the selected window is
-used. For example,
-
-@example
-@group
-(window-start)
- @result{} 7058
-@end group
-@end example
-
-When you create a window, or display a different buffer in it, the
-display-start position is set to a display-start position recently used
-for the same buffer, or 1 if the buffer doesn't have any.
-
-Redisplay updates the window-start position (if you have not specified
-it explicitly since the previous redisplay) so that point appears on the
-screen. Nothing except redisplay automatically changes the window-start
-position; if you move point, do not expect the window-start position to
-change in response until after the next redisplay.
-
-For a realistic example of using @code{window-start}, see the
-description of @code{count-lines} in @ref{Text Lines}.
-@end defun
-
-@defun window-end &optional window
-This function returns the position of the end of the display in window
-@var{window}. If @var{window} is @code{nil}, the selected window is
-used.
-
-Simply changing the buffer text or moving point does not update the
-value that @code{window-end} returns. The value is updated only when
-Emacs redisplays and redisplay actually finishes.
-
-If the last redisplay of @var{window} was preempted, and did not finish,
-Emacs does not know the position of the end of display in that window.
-In that case, this function returns a value that is not correct. In a
-future version, @code{window-end} will return @code{nil} in that case.
-@ignore
-in that case, this function returns @code{nil}. You can compute where
-the end of the window @emph{would} have been, if redisplay had finished,
-like this:
-
-@example
-(save-excursion
- (goto-char (window-start window))
- (vertical-motion (1- (window-height window))
- window)
- (point))
-@end example
-@end ignore
-@end defun
-
-@defun set-window-start window position &optional noforce
-This function sets the display-start position of @var{window} to
-@var{position} in @var{window}'s buffer. It returns @var{position}.
-
-The display routines insist that the position of point be visible when a
-buffer is displayed. Normally, they change the display-start position
-(that is, scroll the window) whenever necessary to make point visible.
-However, if you specify the start position with this function using
-@code{nil} for @var{noforce}, it means you want display to start at
-@var{position} even if that would put the location of point off the
-screen. If this does place point off screen, the display routines move
-point to the left margin on the middle line in the window.
-
-For example, if point @w{is 1} and you set the start of the window @w{to
-2}, then point would be ``above'' the top of the window. The display
-routines will automatically move point if it is still 1 when redisplay
-occurs. Here is an example:
-
-@example
-@group
-;; @r{Here is what @samp{foo} looks like before executing}
-;; @r{the @code{set-window-start} expression.}
-@end group
-
-@group
----------- Buffer: foo ----------
-@point{}This is the contents of buffer foo.
-2
-3
-4
-5
-6
----------- Buffer: foo ----------
-@end group
-
-@group
-(set-window-start
- (selected-window)
- (1+ (window-start)))
-@result{} 2
-@end group
-
-@group
-;; @r{Here is what @samp{foo} looks like after executing}
-;; @r{the @code{set-window-start} expression.}
----------- Buffer: foo ----------
-his is the contents of buffer foo.
-2
-3
-@point{}4
-5
-6
----------- Buffer: foo ----------
-@end group
-@end example
-
-If @var{noforce} is non-@code{nil}, and @var{position} would place point
-off screen at the next redisplay, then redisplay computes a new window-start
-position that works well with point, and thus @var{position} is not used.
-@end defun
-
-@defun pos-visible-in-window-p &optional position window
-This function returns @code{t} if @var{position} is within the range
-of text currently visible on the screen in @var{window}. It returns
-@code{nil} if @var{position} is scrolled vertically out of view. The
-argument @var{position} defaults to the current position of point;
-@var{window}, to the selected window. Here is an example:
-
-@example
-@group
-(or (pos-visible-in-window-p
- (point) (selected-window))
- (recenter 0))
-@end group
-@end example
-
-The @code{pos-visible-in-window-p} function considers only vertical
-scrolling. If @var{position} is out of view only because @var{window}
-has been scrolled horizontally, @code{pos-visible-in-window-p} returns
-@code{t}. @xref{Horizontal Scrolling}.
-@end defun
-
-@node Vertical Scrolling
-@section Vertical Scrolling
-@cindex vertical scrolling
-@cindex scrolling vertically
-
- Vertical scrolling means moving the text up or down in a window. It
-works by changing the value of the window's display-start location. It
-may also change the value of @code{window-point} to keep it on the
-screen.
-
- In the commands @code{scroll-up} and @code{scroll-down}, the directions
-``up'' and ``down'' refer to the motion of the text in the buffer at which
-you are looking through the window. Imagine that the text is
-written on a long roll of paper and that the scrolling commands move the
-paper up and down. Thus, if you are looking at text in the middle of a
-buffer and repeatedly call @code{scroll-down}, you will eventually see
-the beginning of the buffer.
-
- Some people have urged that the opposite convention be used: they
-imagine that the window moves over text that remains in place. Then
-``down'' commands would take you to the end of the buffer. This view is
-more consistent with the actual relationship between windows and the
-text in the buffer, but it is less like what the user sees. The
-position of a window on the terminal does not move, and short scrolling
-commands clearly move the text up or down on the screen. We have chosen
-names that fit the user's point of view.
-
- The scrolling functions (aside from @code{scroll-other-window}) have
-unpredictable results if the current buffer is different from the buffer
-that is displayed in the selected window. @xref{Current Buffer}.
-
-@deffn Command scroll-up &optional count
-This function scrolls the text in the selected window upward
-@var{count} lines. If @var{count} is negative, scrolling is actually
-downward.
-
-If @var{count} is @code{nil} (or omitted), then the length of scroll
-is @code{next-screen-context-lines} lines less than the usable height of
-the window (not counting its mode line).
-
-@code{scroll-up} returns @code{nil}.
-@end deffn
-
-@deffn Command scroll-down &optional count
-This function scrolls the text in the selected window downward
-@var{count} lines. If @var{count} is negative, scrolling is actually
-upward.
-
-If @var{count} is omitted or @code{nil}, then the length of the scroll
-is @code{next-screen-context-lines} lines less than the usable height of
-the window (not counting its mode line).
-
-@code{scroll-down} returns @code{nil}.
-@end deffn
-
-@deffn Command scroll-other-window &optional count
-This function scrolls the text in another window upward @var{count}
-lines. Negative values of @var{count}, or @code{nil}, are handled
-as in @code{scroll-up}.
-
-You can specify a buffer to scroll with the variable
-@code{other-window-scroll-buffer}. When the selected window is the
-minibuffer, the next window is normally the one at the top left corner.
-You can specify a different window to scroll with the variable
-@code{minibuffer-scroll-window}. This variable has no effect when any
-other window is selected. @xref{Minibuffer Misc}.
-
-When the minibuffer is active, it is the next window if the selected
-window is the one at the bottom right corner. In this case,
-@code{scroll-other-window} attempts to scroll the minibuffer. If the
-minibuffer contains just one line, it has nowhere to scroll to, so the
-line reappears after the echo area momentarily displays the message
-``Beginning of buffer''.
-@end deffn
-
-@c Emacs 19 feature
-@defvar other-window-scroll-buffer
-If this variable is non-@code{nil}, it tells @code{scroll-other-window}
-which buffer to scroll.
-@end defvar
-
-@defopt scroll-step
-This variable controls how scrolling is done automatically when point
-moves off the screen. If the value is zero, then redisplay scrolls the
-text to center point vertically in the window. If the value is a
-positive integer @var{n}, then redisplay brings point back on screen by
-scrolling @var{n} lines in either direction, if possible; otherwise, it
-centers point. The default value is zero.
-@end defopt
-
-@defopt next-screen-context-lines
-The value of this variable is the number of lines of continuity to
-retain when scrolling by full screens. For example, @code{scroll-up}
-with an argument of @code{nil} scrolls so that this many lines at the
-bottom of the window appear instead at the top. The default value is
-@code{2}.
-@end defopt
-
-@deffn Command recenter &optional count
-@cindex centering point
-This function scrolls the selected window to put the text where point
-is located at a specified vertical position within the window.
-
-If @var{count} is a nonnegative number, it puts the line containing
-point @var{count} lines down from the top of the window. If @var{count}
-is a negative number, then it counts upward from the bottom of the
-window, so that @minus{}1 stands for the last usable line in the window.
-If @var{count} is a non-@code{nil} list, then it stands for the line in
-the middle of the window.
-
-If @var{count} is @code{nil}, @code{recenter} puts the line containing
-point in the middle of the window, then clears and redisplays the entire
-selected frame.
-
-When @code{recenter} is called interactively, @var{count} is the raw
-prefix argument. Thus, typing @kbd{C-u} as the prefix sets the
-@var{count} to a non-@code{nil} list, while typing @kbd{C-u 4} sets
-@var{count} to 4, which positions the current line four lines from the
-top.
-
-With an argument of zero, @code{recenter} positions the current line at
-the top of the window. This action is so handy that some people make a
-separate key binding to do this. For example,
-
-@example
-@group
-(defun line-to-top-of-window ()
- "Scroll current line to top of window.
-Replaces three keystroke sequence C-u 0 C-l."
- (interactive)
- (recenter 0))
-
-(global-set-key [kp-multiply] 'line-to-top-of-window)
-@end group
-@end example
-@end deffn
-
-@node Scrolling Hooks
-@section Hooks for Vertical Scrolling
-
-This section describes how a Lisp program can take action whenever a
-window displays a different part of its buffer or a different buffer.
-There are three actions that can change this: scrolling the window,
-switching buffers in the window, and changing the size of the window.
-The first two actions run @code{window-scroll-functions}; the last runs
-@code{window-size-change-functions}. The paradigmatic use of these
-hooks is Lazy Lock mode; see @ref{Support Modes, Lazy Lock, Font Lock
-Support Modes, emacs, The GNU Emacs Manual}.
-
-@defvar window-scroll-functions
-This variable holds a list of functions that Emacs should call before
-redisplaying a window with scrolling. It is not a normal hook, because
-each function is called with two arguments: the window, and its new
-display-start position.
-
-Displaying a different buffer in the window also runs these functions.
-
-These functions cannot expect @code{window-end} (@pxref{Window Start})
-to return a meaningful value, because that value is updated only by
-redisplaying the buffer. So if one of these functions needs to know the
-last character that will fit in the window with its current
-display-start position, it has to find that character using
-@code{vertical-motion} (@pxref{Screen Lines}).
-@end defvar
-
-@defvar window-size-change-functions
-This variable holds a list of functions to be called if the size of any
-window changes for any reason. The functions are called just once per
-redisplay, and just once for each frame on which size changes have
-occurred.
-
-Each function receives the frame as its sole argument. There is no
-direct way to find out which windows on that frame have changed size, or
-precisely how. However, if a size-change function records, at each
-call, the existing windows and their sizes, it can also compare the
-present sizes and the previous sizes.
-
-Creating or deleting windows counts as a size change, and therefore
-causes these functions to be called. Changing the frame size also
-counts, because it changes the sizes of the existing windows.
-
-It is not a good idea to use @code{save-window-excursion} (@pxref{Window
-Configurations}) in these functions, because that always counts as a
-size change, and it would cause these functions to be called over and
-over. In most cases, @code{save-selected-window} (@pxref{Selecting
-Windows}) is what you need here.
-@end defvar
-
-@node Horizontal Scrolling
-@section Horizontal Scrolling
-@cindex horizontal scrolling
-
- Because we read English first from top to bottom and second from left
-to right, horizontal scrolling is not like vertical scrolling. Vertical
-scrolling involves selection of a contiguous portion of text to display.
-Horizontal scrolling causes part of each line to go off screen. The
-amount of horizontal scrolling is therefore specified as a number of
-columns rather than as a position in the buffer. It has nothing to do
-with the display-start position returned by @code{window-start}.
-
- Usually, no horizontal scrolling is in effect; then the leftmost
-column is at the left edge of the window. In this state, scrolling to
-the right is meaningless, since there is no data to the left of the
-screen to be revealed by it; so this is not allowed. Scrolling to the
-left is allowed; it scrolls the first columns of text off the edge of
-the window and can reveal additional columns on the right that were
-truncated before. Once a window has a nonzero amount of leftward
-horizontal scrolling, you can scroll it back to the right, but only so
-far as to reduce the net horizontal scroll to zero. There is no limit
-to how far left you can scroll, but eventually all the text will
-disappear off the left edge.
-
-@deffn Command scroll-left count
-This function scrolls the selected window @var{count} columns to the
-left (or to the right if @var{count} is negative). The return value is
-the total amount of leftward horizontal scrolling in effect after the
-change---just like the value returned by @code{window-hscroll} (below).
-@end deffn
-
-@deffn Command scroll-right count
-This function scrolls the selected window @var{count} columns to the
-right (or to the left if @var{count} is negative). The return value is
-the total amount of leftward horizontal scrolling in effect after the
-change---just like the value returned by @code{window-hscroll} (below).
-
-Once you scroll a window as far right as it can go, back to its normal
-position where the total leftward scrolling is zero, attempts to scroll
-any farther right have no effect.
-@end deffn
-
-@defun window-hscroll &optional window
-This function returns the total leftward horizontal scrolling of
-@var{window}---the number of columns by which the text in @var{window}
-is scrolled left past the left margin.
-
-The value is never negative. It is zero when no horizontal scrolling
-has been done in @var{window} (which is usually the case).
-
-If @var{window} is @code{nil}, the selected window is used.
-
-@example
-@group
-(window-hscroll)
- @result{} 0
-@end group
-@group
-(scroll-left 5)
- @result{} 5
-@end group
-@group
-(window-hscroll)
- @result{} 5
-@end group
-@end example
-@end defun
-
-@defun set-window-hscroll window columns
-This function sets the number of columns from the left margin that
-@var{window} is scrolled to the value of @var{columns}. The argument
-@var{columns} should be zero or positive; if not, it is taken as zero.
-
-The value returned is @var{columns}.
-
-@example
-@group
-(set-window-hscroll (selected-window) 10)
- @result{} 10
-@end group
-@end example
-@end defun
-
- Here is how you can determine whether a given position @var{position}
-is off the screen due to horizontal scrolling:
-
-@example
-@group
-(defun hscroll-on-screen (window position)
- (save-excursion
- (goto-char position)
- (and
- (>= (- (current-column) (window-hscroll window)) 0)
- (< (- (current-column) (window-hscroll window))
- (window-width window)))))
-@end group
-@end example
-
-@node Size of Window
-@section The Size of a Window
-@cindex window size
-@cindex size of window
-
- An Emacs window is rectangular, and its size information consists of
-the height (the number of lines) and the width (the number of character
-positions in each line). The mode line is included in the height. But
-the width does not count the scroll bar or the column of @samp{|}
-characters that separates side-by-side windows.
-
- The following three functions return size information about a window:
-
-@defun window-height &optional window
-This function returns the number of lines in @var{window}, including
-its mode line. If @var{window} fills its entire frame, this is one less
-than the value of @code{frame-height} on that frame (since the last line
-is always reserved for the minibuffer).
-
-If @var{window} is @code{nil}, the function uses the selected window.
-
-@example
-@group
-(window-height)
- @result{} 23
-@end group
-@group
-(split-window-vertically)
- @result{} #<window 4 on windows.texi>
-@end group
-@group
-(window-height)
- @result{} 11
-@end group
-@end example
-@end defun
-
-@defun window-width &optional window
-This function returns the number of columns in @var{window}. If
-@var{window} fills its entire frame, this is the same as the value of
-@code{frame-width} on that frame. The width does not include the
-window's scroll bar or the column of @samp{|} characters that separates
-side-by-side windows.
-
-If @var{window} is @code{nil}, the function uses the selected window.
-
-@example
-@group
-(window-width)
- @result{} 80
-@end group
-@end example
-@end defun
-
-@defun window-edges &optional window
-This function returns a list of the edge coordinates of @var{window}.
-If @var{window} is @code{nil}, the selected window is used.
-
-The order of the list is @code{(@var{left} @var{top} @var{right}
-@var{bottom})}, all elements relative to 0, 0 at the top left corner of
-the frame. The element @var{right} of the value is one more than the
-rightmost column used by @var{window}, and @var{bottom} is one more than
-the bottommost row used by @var{window} and its mode-line.
-
-When you have side-by-side windows, the right edge value for a window
-with a neighbor on the right includes the width of the separator between
-the window and that neighbor. This separator may be a column of
-@samp{|} characters or it may be a scroll bar. Since the width of the
-window does not include this separator, the width does not equal the
-difference between the right and left edges in this case.
-
-Here is the result obtained on a typical 24-line terminal with just one
-window:
-
-@example
-@group
-(window-edges (selected-window))
- @result{} (0 0 80 23)
-@end group
-@end example
-
-@noindent
-The bottom edge is at line 23 because the last line is the echo area.
-
-If @var{window} is at the upper left corner of its frame, then
-@var{bottom} is the same as the value of @code{(window-height)},
-@var{right} is almost the same as the value of
-@code{(window-width)}@footnote{They are not exactly equal because
-@var{right} includes the vertical separator line or scroll bar, while
-@code{(window-width)} does not.}, and @var{top} and @var{left} are zero.
-For example, the edges of the following window are @w{@samp{0 0 5 8}}.
-Assuming that the frame has more than 8 columns, the last column of the
-window (column 7) holds a border rather than text. The last row (row 4)
-holds the mode line, shown here with @samp{xxxxxxxxx}.
-
-@example
-@group
- 0
- _______
- 0 | |
- | |
- | |
- | |
- xxxxxxxxx 4
-
- 7
-@end group
-@end example
-
-When there are side-by-side windows, any window not at the right edge of
-its frame has a separator in its last column or columns. The separator
-counts as one or two columns in the width of the window. A window never
-includes a separator on its left, since that belongs to the window to
-the left.
-
-In the following example, let's suppose that the frame is 7
-columns wide. Then the edges of the left window are @w{@samp{0 0 4 3}}
-and the edges of the right window are @w{@samp{4 0 7 3}}.
-
-@example
-@group
- ___ ___
- | | |
- | | |
- xxxxxxxxx
-
- 0 34 7
-@end group
-@end example
-@end defun
-
-@node Resizing Windows
-@section Changing the Size of a Window
-@cindex window resizing
-@cindex changing window size
-@cindex window size, changing
-
- The window size functions fall into two classes: high-level commands
-that change the size of windows and low-level functions that access
-window size. Emacs does not permit overlapping windows or gaps between
-windows, so resizing one window affects other windows.
-
-@deffn Command enlarge-window size &optional horizontal
-This function makes the selected window @var{size} lines taller,
-stealing lines from neighboring windows. It takes the lines from one
-window at a time until that window is used up, then takes from another.
-If a window from which lines are stolen shrinks below
-@code{window-min-height} lines, that window disappears.
-
-If @var{horizontal} is non-@code{nil}, this function makes
-@var{window} wider by @var{size} columns, stealing columns instead of
-lines. If a window from which columns are stolen shrinks below
-@code{window-min-width} columns, that window disappears.
-
-If the requested size would exceed that of the window's frame, then the
-function makes the window occupy the entire height (or width) of the
-frame.
-
-If @var{size} is negative, this function shrinks the window by
-@minus{}@var{size} lines or columns. If that makes the window smaller
-than the minimum size (@code{window-min-height} and
-@code{window-min-width}), @code{enlarge-window} deletes the window.
-
-@code{enlarge-window} returns @code{nil}.
-@end deffn
-
-@deffn Command enlarge-window-horizontally columns
-This function makes the selected window @var{columns} wider.
-It could be defined as follows:
-
-@example
-@group
-(defun enlarge-window-horizontally (columns)
- (enlarge-window columns t))
-@end group
-@end example
-@end deffn
-
-@deffn Command shrink-window size &optional horizontal
-This function is like @code{enlarge-window} but negates the argument
-@var{size}, making the selected window smaller by giving lines (or
-columns) to the other windows. If the window shrinks below
-@code{window-min-height} or @code{window-min-width}, then it disappears.
-
-If @var{size} is negative, the window is enlarged by @minus{}@var{size}
-lines or columns.
-@end deffn
-
-@deffn Command shrink-window-horizontally columns
-This function makes the selected window @var{columns} narrower.
-It could be defined as follows:
-
-@example
-@group
-(defun shrink-window-horizontally (columns)
- (shrink-window columns t))
-@end group
-@end example
-@end deffn
-
-@cindex minimum window size
- The following two variables constrain the window-size-changing
-functions to a minimum height and width.
-
-@defopt window-min-height
-The value of this variable determines how short a window may become
-before it is automatically deleted. Making a window smaller than
-@code{window-min-height} automatically deletes it, and no window may be
-created shorter than this. The absolute minimum height is two (allowing
-one line for the mode line, and one line for the buffer display).
-Actions that change window sizes reset this variable to two if it is
-less than two. The default value is 4.
-@end defopt
-
-@defopt window-min-width
-The value of this variable determines how narrow a window may become
-before it automatically deleted. Making a window smaller than
-@code{window-min-width} automatically deletes it, and no window may be
-created narrower than this. The absolute minimum width is one; any
-value below that is ignored. The default value is 10.
-@end defopt
-
-@node Coordinates and Windows
-@section Coordinates and Windows
-
-This section describes how to relate screen coordinates to windows.
-
-@defun window-at x y &optional frame
-This function returns the window containing the specified cursor
-position in the frame @var{frame}. The coordinates @var{x} and @var{y}
-are measured in characters and count from the top left corner of the
-frame. If they are out of range, @code{window-at} returns @code{nil}.
-
-If you omit @var{frame}, the selected frame is used.
-@end defun
-
-@defun coordinates-in-window-p coordinates window
-This function checks whether a particular frame position falls within
-the window @var{window}.
-
-@need 3000
-The argument @var{coordinates} is a cons cell of this form:
-
-@example
-(@var{x} . @var{y})
-@end example
-
-@noindent
-The coordinates @var{x} and @var{y} are measured in characters, and
-count from the top left corner of the screen or frame.
-
-The value of @code{coordinates-in-window-p} is non-@code{nil} if the
-coordinates are inside @var{window}. The value also indicates what part
-of the window the position is in, as follows:
-
-@table @code
-@item (@var{relx} . @var{rely})
-The coordinates are inside @var{window}. The numbers @var{relx} and
-@var{rely} are the equivalent window-relative coordinates for the
-specified position, counting from 0 at the top left corner of the
-window.
-
-@item mode-line
-The coordinates are in the mode line of @var{window}.
-
-@item vertical-split
-The coordinates are in the vertical line between @var{window} and its
-neighbor to the right. This value occurs only if the window doesn't
-have a scroll bar; positions in a scroll bar are considered outside the
-window.
-
-@item nil
-The coordinates are not in any part of @var{window}.
-@end table
-
-The function @code{coordinates-in-window-p} does not require a frame as
-argument because it always uses the frame that @var{window} is on.
-@end defun
-
-@node Window Configurations
-@section Window Configurations
-@cindex window configurations
-@cindex saving window information
-
- A @dfn{window configuration} records the entire layout of a
-frame---all windows, their sizes, which buffers they contain, what part
-of each buffer is displayed, and the values of point and the mark. You
-can bring back an entire previous layout by restoring a window
-configuration previously saved.
-
- If you want to record all frames instead of just one, use a frame
-configuration instead of a window configuration. @xref{Frame
-Configurations}.
-
-@defun current-window-configuration
-This function returns a new object representing Emacs's current window
-configuration, namely the number of windows, their sizes and current
-buffers, which window is the selected window, and for each window the
-displayed buffer, the display-start position, and the positions of point
-and the mark. An exception is made for point in the current buffer,
-whose value is not saved.
-@end defun
-
-@defun set-window-configuration configuration
-This function restores the configuration of Emacs's windows and
-buffers to the state specified by @var{configuration}. The argument
-@var{configuration} must be a value that was previously returned by
-@code{current-window-configuration}.
-
-This function always counts as a window size change and triggers
-execution of the @code{window-size-change-functions}. (It doesn't know
-how to tell whether the new configuration actually differs from the old
-one.)
-
-Here is a way of using this function to get the same effect
-as @code{save-window-excursion}:
-
-@example
-@group
-(let ((config (current-window-configuration)))
- (unwind-protect
- (progn (split-window-vertically nil)
- @dots{})
- (set-window-configuration config)))
-@end group
-@end example
-@end defun
-
-@defspec save-window-excursion forms@dots{}
-This special form records the window configuration, executes @var{forms}
-in sequence, then restores the earlier window configuration. The window
-configuration includes the value of point and the portion of the buffer
-that is visible. It also includes the choice of selected window.
-However, it does not include the value of point in the current buffer;
-use @code{save-excursion} if you wish to preserve that.
-
-Don't use this construct when @code{save-selected-window} is all you need.
-
-Exit from @code{save-window-excursion} always triggers execution of the
-@code{window-size-change-functions}. (It doesn't know how to tell
-whether the restored configuration actually differs from the one in
-effect at the end of the @var{forms}.)
-
-The return value is the value of the final form in @var{forms}.
-For example:
-
-@example
-@group
-(split-window)
- @result{} #<window 25 on control.texi>
-@end group
-@group
-(setq w (selected-window))
- @result{} #<window 19 on control.texi>
-@end group
-@group
-(save-window-excursion
- (delete-other-windows w)
- (switch-to-buffer "foo")
- 'do-something)
- @result{} do-something
- ;; @r{The screen is now split again.}
-@end group
-@end example
-@end defspec
-
-@defun window-configuration-p object
-This function returns @code{t} if @var{object} is a window configuration.
-@end defun
-
- Primitives to look inside of window configurations would make sense,
-but none are implemented. It is not clear they are useful enough to be
-worth implementing.
diff --git a/lwlib/Makefile.in b/lwlib/Makefile.in
deleted file mode 100644
index 647c6b08562..00000000000
--- a/lwlib/Makefile.in
+++ /dev/null
@@ -1,79 +0,0 @@
-# This was taken from the output of Imake
-# and set up to be configured by ../configure.
-# Some parts Copyright (c) 1992, 1993 Lucid, Inc.
-
-srcdir=@srcdir@
-VPATH=@srcdir@
-C_SWITCH_X_SITE=@C_SWITCH_X_SITE@
-
-CC=@CC@
-CFLAGS=@CFLAGS@
-CPP=@CPP@
-LN_S=@LN_S@
-RANLIB=@RANLIB@
-# See below--@X_TOOLKIT_TYPE@ is used below.
-USE_X_TOOLKIT=@X_TOOLKIT_TYPE@
-
- TOP = .
-
- AR = ar cq
-
- LN = ln -s
- RM = rm -f
-
- LUCID_OBJS = lwlib-Xlw.o xlwmenu.o lwlib-Xaw.o
- MOTIF_OBJS = lwlib-Xm.o
- OLIT_OBJS = lwlib-Xol.o lwlib-Xolmb.o
-
-TOOLKIT_DEFINES = -DUSE_$(USE_X_TOOLKIT)
- TOOLKIT_OBJS = $(@X_TOOLKIT_TYPE@_OBJS)
-
- OBJS = lwlib.o $(TOOLKIT_OBJS) lwlib-utils.o
-
-# ../src is needed to find config.h.
-ALL_CFLAGS= $(C_SWITCH_SITE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \
- $(C_SWITCH_X_SYSTEM) $(C_SWITCH_MACHINE) $(CPPFLAGS) $(CFLAGS) \
- -DEMACS_BITMAP_FILES -DHAVE_CONFIG_H -Demacs \
- -I. -I../src -I${srcdir} -I${srcdir}/../src
-
-.c.o:
- $(CC) -c ${ALL_CFLAGS} $<
-
-all:: liblw.a
-
-liblw.a: $(OBJS)
- $(RM) $@
- $(AR) $@ $(OBJS)
- @echo Do not be alarmed if the following ranlib command
- @echo fails due to the absence of a ranlib program on your system.
- -$(RANLIB) $@ || true
-#If running ranlib fails, probably there is none.
-#That's ok. So don't stop the build.
-
-# Depend on Makefile so that we recompile if TOOLKIT_DEFINES changes.
-lwlib.o: $(srcdir)/lwlib.c Makefile
- $(CC) -c $(TOOLKIT_DEFINES) $(ALL_CFLAGS) $(srcdir)/lwlib.c
-
-xrdb-cpp.o: $(srcdir)/xrdb-cpp.c
- $(CC) -c "-DCPP_PROGRAM=$(CPP)" $(ALL_CFLAGS) $(srcdir)/xrdb-cpp.c
-
-lwlib-utils.o: lwlib-utils.h
-lwlib.o: lwlib.h lwlib-int.h
-lwlib-Xlw.o: lwlib.h lwlib-int.h
-lwlib-Xaw.o: lwlib.h lwlib-int.h
-lwlib-Xm.o: lwlib.h lwlib-int.h lwlib-utils.h
-lwlib-Xol.o: lwlib.h lwlib-int.h
-lwlib-Xolmb.o: lwlib-Xolmb.h lwlib-XolmbP.h
-xlwmenu.o: xlwmenu.c xlwmenu.h lwlib.h xlwmenuP.h
-
-mostlyclean:
- $(RM) *.o core errs ,* *~ *.a .emacs_* make.log MakeOut \#*
-
-clean: mostlyclean
-distclean: clean
-maintainer-clean: distclean
-
-TAGS:
- ../lib-src/etags -t *.[ch]
-tags: TAGS
-.PHONY: tags
diff --git a/lwlib/dispatch.c b/lwlib/dispatch.c
deleted file mode 100644
index 5c554d67fd2..00000000000
--- a/lwlib/dispatch.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/* Defines a function to find the Widget that XtDispatchEvent() would use.
- Copyright (C) 1992 Lucid, Inc.
-
-This file is part of the Lucid Widget Library.
-
-The Lucid Widget Library is free software; you can 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.
-
-The Lucid Widget Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/*
- * The function XtWidgetToDispatchTo(), given an XEvent, returns the
- * widget that XtDispatchEvent() would send that event to if called now.
- * This file copies much code from the X11r4 Xt source, and is thus a
- * portability problem. It also requires data structures defined in
- * IntrinsicI.h, which is a non-exported Xt header file, so you can't
- * compile this file unless you have the Xt sources online.
- */
-
-#include <IntrinsicI.h> /* Don't change this: see comments in Imakefile. */
-#include <X11/Xatom.h>
-#include "dispatch.h"
-
-#include <X11/Xlib.h>
-#include <X11/cursorfont.h>
-#include <X11/Xutil.h>
-
-#ifdef XlibSpecificationRelease
-#if XlibSpecificationRelease >= 5
-#define HAVE_X11R5
-#endif
-#endif
-
-/* ## All of the code on this page was copied from the X11R5 lib/Xt/Event.c,
- ## but is compatible with X11R4; the code in Event.c is different, but
- ## functionally equivalent for our purposes.
- */
-
-#if __STDC__
-#define Const const
-#else
-#define Const /**/
-#endif
-
-#define NonMaskableMask ((EventMask)0x80000000L)
-
-#define COMP_EXPOSE (widget->core.widget_class->core_class.compress_exposure)
-#define COMP_EXPOSE_TYPE (COMP_EXPOSE & 0x0f)
-#define GRAPHICS_EXPOSE ((XtExposeGraphicsExpose & COMP_EXPOSE) || \
- (XtExposeGraphicsExposeMerged & COMP_EXPOSE))
-#define NO_EXPOSE (XtExposeNoExpose & COMP_EXPOSE)
-
-
-/* -- lots of stuff we don't need to copy, omitted -- */
-
-
-static EventMask Const masks[] = {
- 0, /* Error, should never see */
- 0, /* Reply, should never see */
- KeyPressMask, /* KeyPress */
- KeyReleaseMask, /* KeyRelease */
- ButtonPressMask, /* ButtonPress */
- ButtonReleaseMask, /* ButtonRelease */
- PointerMotionMask /* MotionNotify */
- | ButtonMotionMask,
- EnterWindowMask, /* EnterNotify */
- LeaveWindowMask, /* LeaveNotify */
- FocusChangeMask, /* FocusIn */
- FocusChangeMask, /* FocusOut */
- KeymapStateMask, /* KeymapNotify */
- ExposureMask, /* Expose */
- NonMaskableMask, /* GraphicsExpose, in GC */
- NonMaskableMask, /* NoExpose, in GC */
- VisibilityChangeMask, /* VisibilityNotify */
- SubstructureNotifyMask, /* CreateNotify */
- StructureNotifyMask /* DestroyNotify */
- | SubstructureNotifyMask,
- StructureNotifyMask /* UnmapNotify */
- | SubstructureNotifyMask,
- StructureNotifyMask /* MapNotify */
- | SubstructureNotifyMask,
- SubstructureRedirectMask, /* MapRequest */
- StructureNotifyMask /* ReparentNotify */
- | SubstructureNotifyMask,
- StructureNotifyMask /* ConfigureNotify */
- | SubstructureNotifyMask,
- SubstructureRedirectMask, /* ConfigureRequest */
- StructureNotifyMask /* GravityNotify */
- | SubstructureNotifyMask,
- ResizeRedirectMask, /* ResizeRequest */
- StructureNotifyMask /* CirculateNotify */
- | SubstructureNotifyMask,
- SubstructureRedirectMask, /* CirculateRequest */
- PropertyChangeMask, /* PropertyNotify */
- NonMaskableMask, /* SelectionClear */
- NonMaskableMask, /* SelectionRequest */
- NonMaskableMask, /* SelectionNotify */
- ColormapChangeMask, /* ColormapNotify */
- NonMaskableMask, /* ClientMessage */
- NonMaskableMask /* MappingNotify */
-};
-
-#ifndef HAVE_X11R5
-
-static /* in R5, this is not static, so we don't need to define it at all */
-EventMask _XtConvertTypeToMask (eventType)
- int eventType;
-{
- eventType &= 0x7f; /* Events sent with XSendEvent have high bit set. */
- if (eventType < XtNumber(masks))
- return masks[eventType];
- else
- return 0;
-}
-
-#endif /* not HAVE_X11R5 */
-
-/* -- _XtOnGrabList() omitted -- */
-
-
-static Widget LookupSpringLoaded(grabList)
- XtGrabList grabList;
-{
- XtGrabList gl;
-
- for (gl = grabList; gl != NULL; gl = gl->next) {
- if (gl->spring_loaded)
- if (XtIsSensitive(gl->widget))
- return gl->widget;
- else
- return NULL;
- if (gl->exclusive) break;
- }
- return NULL;
-}
-
-
-
-/* This function is new. */
-
-static Boolean WouldDispatchEvent(event, widget, mask, pd)
- register XEvent *event;
- Widget widget;
- EventMask mask;
- XtPerDisplay pd;
-{
- XtEventRec *p;
- Boolean would_dispatched = False;
-
- if ((mask == ExposureMask) ||
- ((event->type == NoExpose) && NO_EXPOSE) ||
- ((event->type == GraphicsExpose) && GRAPHICS_EXPOSE) )
- if (widget->core.widget_class->core_class.expose != NULL )
- return True;
-
-
- if ((mask == VisibilityChangeMask) &&
- XtClass(widget)->core_class.visible_interest)
- return True;
-
- for (p=widget->core.event_table; p != NULL; p = p->next)
- if ((mask & p->mask) != 0
-#ifndef HAVE_X11R5
- || (mask == 0 && p->non_filter)
-#endif
- )
- return True;
-
- return False;
-}
-
-
-/* #### This function is mostly copied from DecideToDispatch().
- */
-
-typedef enum _GrabType {pass, ignore, remap} GrabType;
-
-Widget
-XtWidgetToDispatchTo (XEvent* event)
-{
- register Widget widget;
- EventMask mask;
- GrabType grabType;
- Widget dspWidget;
- Time time = 0;
- XtPerDisplay pd;
- XtPerDisplayInput pdi;
- XtGrabList grabList;
-
- widget = XtWindowToWidget (event->xany.display, event->xany.window);
- pd = _XtGetPerDisplay(event->xany.display);
- pdi = _XtGetPerDisplayInput(event->xany.display);
- grabList = *_XtGetGrabList(pdi);
-
- mask = _XtConvertTypeToMask(event->xany.type);
- grabType = pass;
- switch (event->xany.type & 0x7f) {
- case KeyPress:
- case KeyRelease: grabType = remap; break;
- case ButtonPress:
- case ButtonRelease: grabType = remap; break;
- case MotionNotify: grabType = ignore;
-#define XKnownButtons (Button1MotionMask|Button2MotionMask|Button3MotionMask|\
- Button4MotionMask|Button5MotionMask)
- mask |= (event->xmotion.state & XKnownButtons);
-#undef XKnownButtons
- break;
- case EnterNotify: grabType = ignore; break;
- }
-
- if (widget == NULL) {
- if (grabType != remap) return False;
- /* event occurred in a non-widget window, but we've promised also
- to dispatch it to the nearest accessible spring_loaded widget */
- else if ((widget = LookupSpringLoaded(grabList)) != NULL)
- return widget;
- return False;
- }
-
- switch(grabType) {
- case pass:
- return widget;
-
- case ignore:
- if ((grabList == NULL || _XtOnGrabList(widget,grabList))
- && XtIsSensitive(widget)) {
- return widget;
- }
- return NULL;
-
- case remap:
-
- {
- Widget was_dispatched_to= NULL;
- extern Widget _XtFindRemapWidget();
- extern void _XtUngrabBadGrabs();
-
- dspWidget = _XtFindRemapWidget(event, widget, mask, pdi);
-
- if ((grabList == NULL ||
- _XtOnGrabList(dspWidget, grabList)) &&
- XtIsSensitive(dspWidget)) {
- if (WouldDispatchEvent (event, dspWidget, mask, pd))
- was_dispatched_to = dspWidget;
- }
-
- /* Also dispatch to nearest accessible spring_loaded. */
- /* Fetch this afterward to reflect modal list changes */
- grabList = *_XtGetGrabList(pdi);
- widget = LookupSpringLoaded(grabList);
- if (widget != NULL && widget != dspWidget) {
- if (!was_dispatched_to)
- was_dispatched_to = widget;
- }
-
- return was_dispatched_to;
- }
- }
- /* should never reach here */
- return NULL;
-}
diff --git a/lwlib/lwlib-Xaw.c b/lwlib/lwlib-Xaw.c
deleted file mode 100644
index 21685659ae5..00000000000
--- a/lwlib/lwlib-Xaw.c
+++ /dev/null
@@ -1,648 +0,0 @@
-/* The lwlib interface to Athena widgets.
- Copyright (C) 1993 Chuck Thompson <cthomp@cs.uiuc.edu>
-
-This file is part of the Lucid Widget Library.
-
-The Lucid Widget Library is free software; you can 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.
-
-The Lucid Widget Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include <stdio.h>
-
-#include "lwlib-Xaw.h"
-
-#include <X11/StringDefs.h>
-#include <X11/IntrinsicP.h>
-#include <X11/CoreP.h>
-#include <X11/Shell.h>
-
-#include <X11/Xaw/Scrollbar.h>
-#include <X11/Xaw/Paned.h>
-#include <X11/Xaw/Dialog.h>
-#include <X11/Xaw/Form.h>
-#include <X11/Xaw/Command.h>
-#include <X11/Xaw/Label.h>
-
-#include <X11/Xatom.h>
-
-static void xaw_generic_callback (/*Widget, XtPointer, XtPointer*/);
-
-
-Boolean
-lw_xaw_widget_p (widget)
- Widget widget;
-{
- return (XtIsSubclass (widget, scrollbarWidgetClass) ||
- XtIsSubclass (widget, dialogWidgetClass));
-}
-
-static void
-xaw_update_scrollbar (instance, widget, val)
- widget_instance *instance;
- Widget widget;
- widget_value *val;
-{
-#if 0
- if (val->scrollbar_data)
- {
- scrollbar_values *data = val->scrollbar_data;
- Dimension height, width;
- Dimension pos_x, pos_y;
- int widget_shown, widget_topOfThumb;
- float new_shown, new_topOfThumb;
-
- XtVaGetValues (widget,
- XtNheight, &height,
- XtNwidth, &width,
- XtNx, &pos_x,
- XtNy, &pos_y,
- XtNtopOfThumb, &widget_topOfThumb,
- XtNshown, &widget_shown,
- 0);
-
- /*
- * First size and position the scrollbar widget.
- * We need to position it to second-guess the Paned widget's notion
- * of what should happen when the WMShell gets resized.
- */
- if (height != data->scrollbar_height || pos_y != data->scrollbar_pos)
- {
- XtConfigureWidget (widget, pos_x, data->scrollbar_pos,
- width, data->scrollbar_height, 0);
-
- XtVaSetValues (widget,
- XtNlength, data->scrollbar_height,
- XtNthickness, width,
- 0);
- }
-
- /*
- * Now the size the scrollbar's slider.
- */
- new_shown = (float) data->slider_size /
- (float) (data->maximum - data->minimum);
-
- new_topOfThumb = (float) (data->slider_position - data->minimum) /
- (float) (data->maximum - data->minimum);
-
- if (new_shown > 1.0)
- new_shown = 1.0;
- if (new_shown < 0)
- new_shown = 0;
-
- if (new_topOfThumb > 1.0)
- new_topOfThumb = 1.0;
- if (new_topOfThumb < 0)
- new_topOfThumb = 0;
-
- if (new_shown != widget_shown || new_topOfThumb != widget_topOfThumb)
- XawScrollbarSetThumb (widget, new_topOfThumb, new_shown);
- }
-#endif
-}
-
-void
-xaw_update_one_widget (instance, widget, val, deep_p)
- widget_instance *instance;
- Widget widget;
- widget_value *val;
- Boolean deep_p;
-{
-#if 0
- if (XtIsSubclass (widget, scrollbarWidgetClass))
- {
- xaw_update_scrollbar (instance, widget, val);
- }
-#endif
- if (XtIsSubclass (widget, dialogWidgetClass))
- {
- Arg al[1];
- int ac = 0;
- XtSetArg (al[ac], XtNlabel, val->contents->value); ac++;
- XtSetValues (widget, al, ac);
- }
- else if (XtIsSubclass (widget, commandWidgetClass))
- {
- Dimension bw = 0;
- Arg al[3];
-
- XtVaGetValues (widget, XtNborderWidth, &bw, 0);
- if (bw == 0)
- /* Don't let buttons end up with 0 borderwidth, that's ugly...
- Yeah, all this should really be done through app-defaults files
- or fallback resources, but that's a whole different can of worms
- that I don't feel like opening right now. Making Athena widgets
- not look like shit is just entirely too much work.
- */
- {
- XtSetArg (al[0], XtNborderWidth, 1);
- XtSetValues (widget, al, 1);
- }
-
- XtSetArg (al[0], XtNlabel, val->value);
- XtSetArg (al[1], XtNsensitive, val->enabled);
- /* Force centered button text. Se above. */
- XtSetArg (al[2], XtNjustify, XtJustifyCenter);
- XtSetValues (widget, al, 3);
- XtRemoveAllCallbacks (widget, XtNcallback);
- XtAddCallback (widget, XtNcallback, xaw_generic_callback, instance);
- }
-}
-
-void
-xaw_update_one_value (instance, widget, val)
- widget_instance *instance;
- Widget widget;
- widget_value *val;
-{
- /* This function is not used by the scrollbars and those are the only
- Athena widget implemented at the moment so do nothing. */
- return;
-}
-
-void
-xaw_destroy_instance (instance)
- widget_instance *instance;
-{
- if (XtIsSubclass (instance->widget, dialogWidgetClass))
- /* Need to destroy the Shell too. */
- XtDestroyWidget (XtParent (instance->widget));
- else
- XtDestroyWidget (instance->widget);
-}
-
-void
-xaw_popup_menu (widget)
- Widget widget;
-{
- /* An Athena menubar has not been implemented. */
- return;
-}
-
-void
-xaw_pop_instance (instance, up)
- widget_instance *instance;
- Boolean up;
-{
- Widget widget = instance->widget;
-
- if (up)
- {
- if (XtIsSubclass (widget, dialogWidgetClass))
- {
- /* For dialogs, we need to call XtPopup on the parent instead
- of calling XtManageChild on the widget.
- Also we need to hack the shell's WM_PROTOCOLS to get it to
- understand what the close box is supposed to do!!
- */
- Display *dpy = XtDisplay (widget);
- Widget shell = XtParent (widget);
- Atom props [2];
- int i = 0;
- props [i++] = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
- XChangeProperty (dpy, XtWindow (shell),
- XInternAtom (dpy, "WM_PROTOCOLS", False),
- XA_ATOM, 32, PropModeAppend,
- (unsigned char *) props, i);
-
- /* Center the widget in its parent. Why isn't this kind of crap
- done automatically? I thought toolkits were supposed to make
- life easier?
- */
- {
- unsigned int x, y, w, h;
- Widget topmost = instance->parent;
- Arg args[2];
-
- w = shell->core.width;
- h = shell->core.height;
- while (topmost->core.parent && XtIsRealized (topmost->core.parent))
- topmost = topmost->core.parent;
- if (topmost->core.width < w) x = topmost->core.x;
- else x = topmost->core.x + ((topmost->core.width - w) / 2);
- if (topmost->core.height < h) y = topmost->core.y;
- else y = topmost->core.y + ((topmost->core.height - h) / 2);
- /* Using XtMoveWidget caused the widget to come
- out in the wrong place with vtwm.
- Question of virtual vs real coords, perhaps. */
- XtSetArg (args[0], XtNx, x);
- XtSetArg (args[1], XtNy, y);
- XtSetValues (shell, args, 2);
- }
-
- /* Finally, pop it up. */
- XtPopup (shell, XtGrabNonexclusive);
- }
- else
- XtManageChild (widget);
- }
- else
- {
- if (XtIsSubclass (widget, dialogWidgetClass))
- XtUnmanageChild (XtParent (widget));
- else
- XtUnmanageChild (widget);
- }
-}
-
-
-/* Dialog boxes */
-
-static char overrideTrans[] =
- "<Message>WM_PROTOCOLS: lwlib_delete_dialog()";
-static void wm_delete_window();
-static XtActionsRec xaw_actions [] = {
- {"lwlib_delete_dialog", wm_delete_window}
-};
-static Boolean actions_initted = False;
-
-static Widget
-make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot, radio_box, list, left_buttons, right_buttons)
- char* name;
- Widget parent;
- Boolean pop_up_p;
- char* shell_title;
- char* icon_name;
- Boolean text_input_slot;
- Boolean radio_box;
- Boolean list;
- int left_buttons;
- int right_buttons;
-{
- Arg av [20];
- int ac = 0;
- int i, bc;
- char button_name [255];
- Widget shell;
- Widget dialog;
- Widget button;
- XtTranslations override;
-
- if (! pop_up_p) abort (); /* not implemented */
- if (text_input_slot) abort (); /* not implemented */
- if (radio_box) abort (); /* not implemented */
- if (list) abort (); /* not implemented */
-
- if (! actions_initted)
- {
- XtAppContext app = XtWidgetToApplicationContext (parent);
- XtAppAddActions (app, xaw_actions,
- sizeof (xaw_actions) / sizeof (xaw_actions[0]));
- actions_initted = True;
- }
-
- override = XtParseTranslationTable (overrideTrans);
-
- ac = 0;
- XtSetArg (av[ac], XtNtitle, shell_title); ac++;
- XtSetArg (av[ac], XtNallowShellResize, True); ac++;
-
- /* Don't allow any geometry request from the user. */
- XtSetArg (av[ac], XtNgeometry, 0); ac++;
-
- shell = XtCreatePopupShell ("dialog", transientShellWidgetClass,
- parent, av, ac);
- XtOverrideTranslations (shell, override);
-
- ac = 0;
- dialog = XtCreateManagedWidget (name, dialogWidgetClass, shell, av, ac);
-
- bc = 0;
- button = 0;
- for (i = 0; i < left_buttons; i++)
- {
- ac = 0;
- XtSetArg (av [ac], XtNfromHoriz, button); ac++;
- XtSetArg (av [ac], XtNleft, XtChainLeft); ac++;
- XtSetArg (av [ac], XtNright, XtChainLeft); ac++;
- XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
- XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
- XtSetArg (av [ac], XtNresizable, True); ac++;
- sprintf (button_name, "button%d", ++bc);
- button = XtCreateManagedWidget (button_name, commandWidgetClass,
- dialog, av, ac);
- }
- if (right_buttons)
- {
- /* Create a separator
-
- I want the separator to take up the slack between the buttons on
- the right and the buttons on the left (that is I want the buttons
- after the separator to be packed against the right edge of the
- window) but I can't seem to make it do it.
- */
- ac = 0;
- XtSetArg (av [ac], XtNfromHoriz, button); ac++;
-/* XtSetArg (av [ac], XtNfromVert, XtNameToWidget (dialog, "label")); ac++; */
- XtSetArg (av [ac], XtNleft, XtChainLeft); ac++;
- XtSetArg (av [ac], XtNright, XtChainRight); ac++;
- XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
- XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
- XtSetArg (av [ac], XtNlabel, ""); ac++;
- XtSetArg (av [ac], XtNwidth, 30); ac++; /* #### aaack!! */
- XtSetArg (av [ac], XtNborderWidth, 0); ac++;
- XtSetArg (av [ac], XtNshapeStyle, XmuShapeRectangle); ac++;
- XtSetArg (av [ac], XtNresizable, False); ac++;
- XtSetArg (av [ac], XtNsensitive, False); ac++;
- button = XtCreateManagedWidget ("separator",
- /* labelWidgetClass, */
- /* This has to be Command to fake out
- the Dialog widget... */
- commandWidgetClass,
- dialog, av, ac);
- }
- for (i = 0; i < right_buttons; i++)
- {
- ac = 0;
- XtSetArg (av [ac], XtNfromHoriz, button); ac++;
- XtSetArg (av [ac], XtNleft, XtChainRight); ac++;
- XtSetArg (av [ac], XtNright, XtChainRight); ac++;
- XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
- XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
- XtSetArg (av [ac], XtNresizable, True); ac++;
- sprintf (button_name, "button%d", ++bc);
- button = XtCreateManagedWidget (button_name, commandWidgetClass,
- dialog, av, ac);
- }
-
- return dialog;
-}
-
-Widget
-xaw_create_dialog (instance)
- widget_instance* instance;
-{
- char *name = instance->info->type;
- Widget parent = instance->parent;
- Widget widget;
- Boolean pop_up_p = instance->pop_up_p;
- char *shell_name = 0;
- char *icon_name;
- Boolean text_input_slot = False;
- Boolean radio_box = False;
- Boolean list = False;
- int total_buttons;
- int left_buttons = 0;
- int right_buttons = 1;
-
- switch (name [0]) {
- case 'E': case 'e':
- icon_name = "dbox-error";
- shell_name = "Error";
- break;
-
- case 'I': case 'i':
- icon_name = "dbox-info";
- shell_name = "Information";
- break;
-
- case 'L': case 'l':
- list = True;
- icon_name = "dbox-question";
- shell_name = "Prompt";
- break;
-
- case 'P': case 'p':
- text_input_slot = True;
- icon_name = "dbox-question";
- shell_name = "Prompt";
- break;
-
- case 'Q': case 'q':
- icon_name = "dbox-question";
- shell_name = "Question";
- break;
- }
-
- total_buttons = name [1] - '0';
-
- if (name [3] == 'T' || name [3] == 't')
- {
- text_input_slot = False;
- radio_box = True;
- }
- else if (name [3])
- right_buttons = name [4] - '0';
-
- left_buttons = total_buttons - right_buttons;
-
- widget = make_dialog (name, parent, pop_up_p,
- shell_name, icon_name, text_input_slot, radio_box,
- list, left_buttons, right_buttons);
-
- return widget;
-}
-
-
-static void
-xaw_generic_callback (widget, closure, call_data)
- Widget widget;
- XtPointer closure;
- XtPointer call_data;
-{
- widget_instance *instance = (widget_instance *) closure;
- Widget instance_widget;
- LWLIB_ID id;
- XtPointer user_data;
-
- lw_internal_update_other_instances (widget, closure, call_data);
-
- if (! instance)
- return;
- if (widget->core.being_destroyed)
- return;
-
- instance_widget = instance->widget;
- if (!instance_widget)
- return;
-
- id = instance->info->id;
-
-#if 0
- user_data = NULL;
- XtVaGetValues (widget, XtNuserData, &user_data, 0);
-#else
- /* Damn! Athena doesn't give us a way to hang our own data on the
- buttons, so we have to go find it... I guess this assumes that
- all instances of a button have the same call data. */
- {
- widget_value *val = instance->info->val->contents;
- char *name = XtName (widget);
- while (val)
- {
- if (val->name && !strcmp (val->name, name))
- break;
- val = val->next;
- }
- if (! val) abort ();
- user_data = val->call_data;
- }
-#endif
-
- if (instance->info->selection_cb)
- instance->info->selection_cb (widget, id, user_data);
-}
-
-static void
-wm_delete_window (shell, closure, call_data)
- Widget shell;
- XtPointer closure;
- XtPointer call_data;
-{
- LWLIB_ID id;
- Widget *kids = 0;
- Widget widget;
- if (! XtIsSubclass (shell, shellWidgetClass))
- abort ();
- XtVaGetValues (shell, XtNchildren, &kids, 0);
- if (!kids || !*kids)
- abort ();
- widget = kids [0];
- if (! XtIsSubclass (widget, dialogWidgetClass))
- abort ();
- id = lw_get_widget_id (widget);
- if (! id) abort ();
-
- {
- widget_info *info = lw_get_widget_info (id);
- if (! info) abort ();
- if (info->selection_cb)
- info->selection_cb (widget, id, (XtPointer) -1);
- }
-
- lw_destroy_all_widgets (id);
-}
-
-
-/* Scrollbars */
-
-static void
-xaw_scrollbar_scroll (widget, closure, call_data)
- Widget widget;
- XtPointer closure;
- XtPointer call_data;
-{
-#if 0
- widget_instance *instance = (widget_instance *) closure;
- LWLIB_ID id;
- scroll_event event_data;
-
- if (!instance || widget->core.being_destroyed)
- return;
-
- id = instance->info->id;
- event_data.slider_value = 0;
- event_data.time = 0;
-
- if ((int) call_data > 0)
- event_data.action = SCROLLBAR_PAGE_DOWN;
- else
- event_data.action = SCROLLBAR_PAGE_UP;
-
- if (instance->info->pre_activate_cb)
- instance->info->pre_activate_cb (widget, id, (XtPointer) &event_data);
-#endif
-}
-
-static void
-xaw_scrollbar_jump (widget, closure, call_data)
- Widget widget;
- XtPointer closure;
- XtPointer call_data;
-{
-#if 0
- widget_instance *instance = (widget_instance *) closure;
- LWLIB_ID id;
- scroll_event event_data;
- scrollbar_values *val =
- (scrollbar_values *) instance->info->val->scrollbar_data;
- float percent;
-
- if (!instance || widget->core.being_destroyed)
- return;
-
- id = instance->info->id;
-
- percent = * (float *) call_data;
- event_data.slider_value =
- (int) (percent * (float) (val->maximum - val->minimum)) + val->minimum;
-
- event_data.time = 0;
- event_data.action = SCROLLBAR_DRAG;
-
- if (instance->info->pre_activate_cb)
- instance->info->pre_activate_cb (widget, id, (XtPointer) &event_data);
-#endif
-}
-
-static Widget
-xaw_create_scrollbar (instance)
- widget_instance *instance;
-{
-#if 0
- Arg av[20];
- int ac = 0;
- Dimension width;
- Widget scrollbar;
-
- XtVaGetValues (instance->parent, XtNwidth, &width, 0);
-
- XtSetArg (av[ac], XtNshowGrip, 0); ac++;
- XtSetArg (av[ac], XtNresizeToPreferred, 1); ac++;
- XtSetArg (av[ac], XtNallowResize, True); ac++;
- XtSetArg (av[ac], XtNskipAdjust, True); ac++;
- XtSetArg (av[ac], XtNwidth, width); ac++;
- XtSetArg (av[ac], XtNmappedWhenManaged, True); ac++;
-
- scrollbar =
- XtCreateWidget (instance->info->name, scrollbarWidgetClass,
- instance->parent, av, ac);
-
- /* We have to force the border width to be 0 otherwise the
- geometry manager likes to start looping for awhile... */
- XtVaSetValues (scrollbar, XtNborderWidth, 0, 0);
-
- XtRemoveAllCallbacks (scrollbar, "jumpProc");
- XtRemoveAllCallbacks (scrollbar, "scrollProc");
-
- XtAddCallback (scrollbar, "jumpProc", xaw_scrollbar_jump,
- (XtPointer) instance);
- XtAddCallback (scrollbar, "scrollProc", xaw_scrollbar_scroll,
- (XtPointer) instance);
-
- return scrollbar;
-#endif
-}
-
-static Widget
-xaw_create_main (instance)
- widget_instance *instance;
-{
- Arg al[1];
- int ac;
-
- /* Create a vertical Paned to hold menubar */
- ac = 0;
- XtSetArg (al[ac], XtNborderWidth, 0); ac++;
- return XtCreateWidget (instance->info->name, panedWidgetClass,
- instance->parent, al, ac);
-}
-
-widget_creation_entry
-xaw_creation_table [] =
-{
- {"scrollbar", xaw_create_scrollbar},
- {"main", xaw_create_main},
- {NULL, NULL}
-};
diff --git a/lwlib/lwlib-Xaw.h b/lwlib/lwlib-Xaw.h
deleted file mode 100644
index 958cd9c5986..00000000000
--- a/lwlib/lwlib-Xaw.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef LWLIB_XAW_H
-#define LWLIB_XAW_H
-
-#include "lwlib-int.h"
-
-extern widget_creation_entry xaw_creation_table [];
-
-Widget
-xaw_create_dialog ();
-
-Boolean
-lw_xaw_widget_p ();
-
-void
-xaw_update_one_widget ();
-
-void
-xaw_update_one_value ();
-
-void
-xaw_destroy_instance ();
-
-void
-xaw_popup_menu ();
-
-void
-xaw_pop_instance ();
-
-#endif /* LWLIB_XAW_H */
diff --git a/lwlib/lwlib-Xlw.c b/lwlib/lwlib-Xlw.c
deleted file mode 100644
index a927d40bf25..00000000000
--- a/lwlib/lwlib-Xlw.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/* The lwlib interface to "xlwmenu" menus.
- Copyright (C) 1992 Lucid, Inc.
-
-This file is part of the Lucid Widget Library.
-
-The Lucid Widget Library is free software; you can 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.
-
-The Lucid Widget Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include "lwlib-Xlw.h"
-#include <X11/StringDefs.h>
-#include <X11/IntrinsicP.h>
-#include <X11/ObjectP.h>
-#include <X11/CompositeP.h>
-#include <X11/Shell.h>
-#include "xlwmenu.h"
-
- /* Menu callbacks */
-static void
-pre_hook (w, client_data, call_data)
- Widget w;
- XtPointer client_data;
- XtPointer call_data;
-{
- widget_instance* instance = (widget_instance*)client_data;
- widget_value* val;
-
- if (w->core.being_destroyed)
- return;
-
- val = lw_get_widget_value_for_widget (instance, w);
- if (instance->info->pre_activate_cb)
- instance->info->pre_activate_cb (w, instance->info->id,
- val ? val->call_data : NULL);
-}
-
-static void
-pick_hook (w, client_data, call_data)
- Widget w;
- XtPointer client_data;
- XtPointer call_data;
-{
- widget_instance* instance = (widget_instance*)client_data;
- widget_value* contents_val = (widget_value*)call_data;
- widget_value* widget_val;
- XtPointer widget_arg;
-
- if (w->core.being_destroyed)
- return;
-
- if (instance->info->selection_cb && contents_val && contents_val->enabled
- && !contents_val->contents)
- instance->info->selection_cb (w, instance->info->id,
- contents_val->call_data);
-
- widget_val = lw_get_widget_value_for_widget (instance, w);
- widget_arg = widget_val ? widget_val->call_data : NULL;
- if (instance->info->post_activate_cb)
- instance->info->post_activate_cb (w, instance->info->id, widget_arg);
-
-}
-
- /* creation functions */
-
-static Widget
-xlw_create_menubar (instance)
- widget_instance* instance;
-{
- Widget widget;
- Arg al[5];
- int ac = 0;
-
- XtSetArg (al[ac], XtNmenu, instance->info->val); ac++;
-#ifdef emacs
- XtSetArg (al[ac], XtNshowGrip, 0); ac++;
- XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
- XtSetArg (al[ac], XtNallowResize, 1); ac++;
-#endif
-
- /* This used to use XtVaCreateWidget, but an old Xt version
- has a bug in XtVaCreateWidget that frees instance->info->name. */
- widget
- = XtCreateWidget (instance->info->name, xlwMenuWidgetClass,
- instance->parent, al, ac);
-
- XtAddCallback (widget, XtNopen, pre_hook, (XtPointer)instance);
- XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
- return widget;
-}
-
-static Widget
-xlw_create_popup_menu (instance)
- widget_instance* instance;
-{
- Widget popup_shell
- = XtCreatePopupShell (instance->info->name, overrideShellWidgetClass,
- instance->parent, NULL, 0);
-
- Widget widget;
- Arg al[2];
- int ac = 0;
-
- XtSetArg (al[ac], XtNmenu, instance->info->val); ac++;
- XtSetArg (al[ac], XtNhorizontal, False); ac++;
-
- /* This used to use XtVaManagedCreateWidget, but an old Xt version
- has a bug in XtVaManagedCreateWidget that frees instance->info->name. */
- widget
- = XtCreateManagedWidget ("popup", xlwMenuWidgetClass,
- popup_shell, al, ac);
-
- XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
-
- return popup_shell;
-}
-
-widget_creation_entry
-xlw_creation_table [] =
-{
- {"menubar", xlw_create_menubar},
- {"popup", xlw_create_popup_menu},
- {NULL, NULL}
-};
-
-Boolean
-lw_lucid_widget_p (widget)
- Widget widget;
-{
- WidgetClass the_class = XtClass (widget);
-
- if (the_class == xlwMenuWidgetClass)
- return True;
- if (the_class == overrideShellWidgetClass)
- return (XtClass (((CompositeWidget)widget)->composite.children [0])
- == xlwMenuWidgetClass);
- return False;
-}
-
-void
-xlw_update_one_widget (instance, widget, val, deep_p)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
- Boolean deep_p;
-{
- XlwMenuWidget mw;
- Arg al[1];
-
- if (XtIsShell (widget))
- mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
- else
- mw = (XlwMenuWidget)widget;
-
- /* This used to use XtVaSetValues, but some old Xt versions
- that have a bug in XtVaCreateWidget might have it here too. */
- XtSetArg (al[0], XtNmenu, instance->info->val);
-
- XtSetValues (widget, al, 1);
-}
-
-void
-xlw_update_one_value (instance, widget, val)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
-{
- return;
-}
-
-void
-xlw_pop_instance (instance, up)
- widget_instance* instance;
- Boolean up;
-{
-}
-
-void
-xlw_popup_menu (widget, event)
- Widget widget;
- XEvent *event;
-{
- XButtonPressedEvent dummy;
- XlwMenuWidget mw;
-
- if (!XtIsShell (widget))
- return;
-
- mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
-
- if (event)
- pop_up_menu (mw, event);
- else
- {
- dummy.type = ButtonPress;
- dummy.serial = 0;
- dummy.send_event = 0;
- dummy.display = XtDisplay (widget);
- dummy.window = XtWindow (XtParent (widget));
- dummy.time = CurrentTime;
- dummy.button = 0;
- XQueryPointer (dummy.display, dummy.window, &dummy.root,
- &dummy.subwindow, &dummy.x_root, &dummy.y_root,
- &dummy.x, &dummy.y, &dummy.state);
-
- pop_up_menu (mw, &dummy);
- }
-}
-
- /* Destruction of instances */
-void
-xlw_destroy_instance (instance)
- widget_instance* instance;
-{
- if (instance->widget)
- XtDestroyWidget (instance->widget);
-}
-
diff --git a/lwlib/lwlib-Xlw.h b/lwlib/lwlib-Xlw.h
deleted file mode 100644
index 037e18af89d..00000000000
--- a/lwlib/lwlib-Xlw.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef LWLIB_XLW_H
-#define LWLIB_XLW_H
-
-#include "lwlib-int.h"
-
-extern widget_creation_entry xlw_creation_table [];
-extern widget_creation_function xlw_create_dialog;
-
-Boolean
-lw_lucid_widget_p (/* Widget widget */);
-
-void
-xlw_update_one_widget (/* widget_instance* instance, Widget widget,
- widget_value* val, Boolean deep_p */);
-
-void
-xlw_update_one_value (/* widget_instance* instance, Widget widget,
- widget_value* val */);
-
-void
-xlw_destroy_instance (/* widget_instance* instance */);
-
-void
-xlw_pop_instance (/* widget_instance* instance, Boolean up */);
-
-void
-xlw_popup_menu (/* Widget widget */);
-
-#endif /* LWLIB_XLW_H */
diff --git a/lwlib/lwlib-Xm.c b/lwlib/lwlib-Xm.c
deleted file mode 100644
index 2050c295755..00000000000
--- a/lwlib/lwlib-Xm.c
+++ /dev/null
@@ -1,1779 +0,0 @@
-/* The lwlib interface to Motif widgets.
- Copyright (C) 1992 Lucid, Inc.
-
-This file is part of the Lucid Widget Library.
-
-The Lucid Widget Library is free software; you can 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.
-
-The Lucid Widget Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-
-#include <X11/StringDefs.h>
-#include <X11/IntrinsicP.h>
-#include <X11/ObjectP.h>
-#include <X11/CoreP.h>
-#include <X11/CompositeP.h>
-
-#include "lwlib-Xm.h"
-#include "lwlib-utils.h"
-
-#include <Xm/BulletinB.h>
-#include <Xm/CascadeB.h>
-#include <Xm/CascadeBG.h>
-#include <Xm/DrawingA.h>
-#include <Xm/FileSB.h>
-#include <Xm/Label.h>
-#include <Xm/List.h>
-#include <Xm/MainW.h>
-#include <Xm/MenuShell.h>
-#include <Xm/MessageB.h>
-#include <Xm/PanedW.h>
-#include <Xm/PushB.h>
-#include <Xm/PushBG.h>
-#include <Xm/ArrowB.h>
-#include <Xm/SelectioB.h>
-#include <Xm/Text.h>
-#include <Xm/TextF.h>
-#include <Xm/ToggleB.h>
-#include <Xm/ToggleBG.h>
-#include <Xm/RowColumn.h>
-#include <Xm/ScrolledW.h>
-#include <Xm/Separator.h>
-#include <Xm/DialogS.h>
-#include <Xm/Form.h>
-
-static void xm_pull_down_callback (/* Widget, XtPointer, XtPointer */);
-static void xm_internal_update_other_instances (/* Widget, XtPointer,
- XtPointer */);
-static void xm_generic_callback (/* Widget, XtPointer, XtPointer */);
-static void xm_nosel_callback (/* Widget, XtPointer, XtPointer */);
-static void xm_pop_down_callback (/* Widget, XtPointer, XtPointer */);
-
-static void xm_update_menu (/* widget_instance*, Widget, widget_value*,
- Boolean) */);
-
-
- /* Structures to keep destroyed instances */
-typedef struct _destroyed_instance
-{
- char* name;
- char* type;
- Widget widget;
- Widget parent;
- Boolean pop_up_p;
- struct _destroyed_instance* next;
-} destroyed_instance;
-
-static destroyed_instance*
-all_destroyed_instances = NULL;
-
-static destroyed_instance*
-make_destroyed_instance (name, type, widget, parent, pop_up_p)
- char* name;
- char* type;
- Widget widget;
- Widget parent;
- Boolean pop_up_p;
-{
- destroyed_instance* instance =
- (destroyed_instance*)malloc (sizeof (destroyed_instance));
- instance->name = safe_strdup (name);
- instance->type = safe_strdup (type);
- instance->widget = widget;
- instance->parent = parent;
- instance->pop_up_p = pop_up_p;
- instance->next = NULL;
- return instance;
-}
-
-static void
-free_destroyed_instance (instance)
- destroyed_instance* instance;
-{
- free (instance->name);
- free (instance->type);
- free (instance);
-}
-
- /* motif utility functions */
-Widget
-first_child (widget)
- Widget widget;
-{
- return ((CompositeWidget)widget)->composite.children [0];
-}
-
-Boolean
-lw_motif_widget_p (widget)
- Widget widget;
-{
- return
- XtClass (widget) == xmDialogShellWidgetClass
- || XmIsPrimitive (widget) || XmIsManager (widget) || XmIsGadget (widget);
-}
-
-static XmString
-resource_motif_string (widget, name)
- Widget widget;
- char* name;
-{
- XtResource resource;
- XmString result = 0;
-
- resource.resource_name = name;
- resource.resource_class = XmCXmString;
- resource.resource_type = XmRXmString;
- resource.resource_size = sizeof (XmString);
- resource.resource_offset = 0;
- resource.default_type = XtRImmediate;
- resource.default_addr = 0;
-
- XtGetSubresources (widget, (XtPointer)&result, "dialogString",
- "DialogString", &resource, 1, NULL, 0);
- return result;
-}
-
-/* Destroy all of the children of WIDGET
- starting with number FIRST_CHILD_TO_DESTROY. */
-
-static void
-destroy_all_children (widget, first_child_to_destroy)
- Widget widget;
- int first_child_to_destroy;
-{
- Widget* children;
- unsigned int number;
- int i;
-
- children = XtCompositeChildren (widget, &number);
- if (children)
- {
- XtUnmanageChildren (children + first_child_to_destroy,
- number - first_child_to_destroy);
-
- /* Unmanage all children and destroy them. They will only be
- really destroyed when we get out of DispatchEvent. */
- for (i = first_child_to_destroy; i < number; i++)
- {
- Arg al[2];
- Widget submenu = 0;
- /* Cascade buttons have submenus,and these submenus
- need to be freed. But they are not included in
- XtCompositeChildren. So get it out of the cascade button
- and free it. If this child is not a cascade button,
- then submenu should remain unchanged. */
- XtSetArg (al[0], XmNsubMenuId, &submenu);
- XtGetValues (children[i], al, 1);
- if (submenu)
- XtDestroyWidget (submenu);
- XtDestroyWidget (children[i]);
- }
-
- XtFree ((char *) children);
- }
-}
-
- /* update the label of anything subclass of a label */
-static void
-xm_update_label (instance, widget, val)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
-{
- XmString res_string = 0;
- XmString built_string = 0;
- XmString key_string = 0;
- Arg al [256];
- int ac;
-
- ac = 0;
-
- if (val->value)
- {
- res_string = resource_motif_string (widget, val->value);
-
- if (res_string)
- {
- XtSetArg (al [ac], XmNlabelString, res_string); ac++;
- }
- else
- {
- built_string =
- XmStringCreateLtoR (val->value, XmSTRING_DEFAULT_CHARSET);
- XtSetArg (al [ac], XmNlabelString, built_string); ac++;
- }
- XtSetArg (al [ac], XmNlabelType, XmSTRING); ac++;
- }
-
- if (val->key)
- {
- key_string = XmStringCreateLtoR (val->key, XmSTRING_DEFAULT_CHARSET);
- XtSetArg (al [ac], XmNacceleratorText, key_string); ac++;
- }
-
- if (ac)
- XtSetValues (widget, al, ac);
-
- if (built_string)
- XmStringFree (built_string);
-
- if (key_string)
- XmStringFree (key_string);
-}
-
- /* update of list */
-static void
-xm_update_list (instance, widget, val)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
-{
- widget_value* cur;
- int i;
- XtRemoveAllCallbacks (widget, XmNsingleSelectionCallback);
- XtAddCallback (widget, XmNsingleSelectionCallback, xm_generic_callback,
- instance);
- for (cur = val->contents, i = 0; cur; cur = cur->next)
- if (cur->value)
- {
- XmString xmstr = XmStringCreate (cur->value, XmSTRING_DEFAULT_CHARSET);
- i += 1;
- XmListAddItem (widget, xmstr, 0);
- if (cur->selected)
- XmListSelectPos (widget, i, False);
- XmStringFree (xmstr);
- }
-}
-
- /* update of buttons */
-static void
-xm_update_pushbutton (instance, widget, val)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
-{
- XtVaSetValues (widget, XmNalignment, XmALIGNMENT_CENTER, 0);
- XtRemoveAllCallbacks (widget, XmNactivateCallback);
- XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
-}
-
-static void
-xm_update_cascadebutton (instance, widget, val)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
-{
- /* Should also rebuild the menu by calling ...update_menu... */
- XtRemoveAllCallbacks (widget, XmNcascadingCallback);
- XtAddCallback (widget, XmNcascadingCallback, xm_pull_down_callback,
- instance);
-}
-
- /* update toggle and radiobox */
-static void
-xm_update_toggle (instance, widget, val)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
-{
- XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
- XtAddCallback (widget, XmNvalueChangedCallback,
- xm_internal_update_other_instances, instance);
- XtVaSetValues (widget, XmNset, val->selected,
- XmNalignment, XmALIGNMENT_BEGINNING, 0);
-}
-
-static void
-xm_update_radiobox (instance, widget, val)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
-
-{
- Widget toggle;
- widget_value* cur;
-
- /* update the callback */
- XtRemoveAllCallbacks (widget, XmNentryCallback);
- XtAddCallback (widget, XmNentryCallback, xm_generic_callback, instance);
-
- /* first update all the toggles */
- /* Energize kernel interface is currently bad. It sets the selected widget
- with the selected flag but returns it by its name. So we currently
- have to support both setting the selection with the selected slot
- of val contents and setting it with the "value" slot of val. The latter
- has a higher priority. This to be removed when the kernel is fixed. */
- for (cur = val->contents; cur; cur = cur->next)
- {
- toggle = XtNameToWidget (widget, cur->value);
- if (toggle)
- {
- XtVaSetValues (toggle, XmNsensitive, cur->enabled, 0);
- if (!val->value && cur->selected)
- XtVaSetValues (toggle, XmNset, cur->selected, 0);
- if (val->value && strcmp (val->value, cur->value))
- XtVaSetValues (toggle, XmNset, False, 0);
- }
- }
-
- /* The selected was specified by the value slot */
- if (val->value)
- {
- toggle = XtNameToWidget (widget, val->value);
- if (toggle)
- XtVaSetValues (toggle, XmNset, True, 0);
- }
-}
-
- /* update a popup menu, pulldown menu or a menubar */
-static Boolean
-all_dashes_p (s)
- char* s;
-{
- char* t;
- for (t = s; *t; t++)
- if (*t != '-')
- return False;
- return True;
-}
-
-/* KEEP_FIRST_CHILDREN gives the number of initial children to keep. */
-
-static void
-make_menu_in_widget (instance, widget, val, keep_first_children)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
- int keep_first_children;
-{
- Widget* children = 0;
- int num_children;
- int child_index;
- widget_value* cur;
- Widget button = 0;
- Widget menu;
- Arg al [256];
- int ac;
- Boolean menubar_p;
-
- Widget* old_children;
- unsigned int old_num_children;
-
- old_children = XtCompositeChildren (widget, &old_num_children);
-
- /* Allocate the children array */
- for (num_children = 0, cur = val; cur; num_children++, cur = cur->next);
- children = (Widget*)XtMalloc (num_children * sizeof (Widget));
-
- /* tricky way to know if this RowColumn is a menubar or a pulldown... */
- menubar_p = False;
- XtSetArg (al[0], XmNisHomogeneous, &menubar_p);
- XtGetValues (widget, al, 1);
-
- /* add the unmap callback for popups and pulldowns */
- /*** this sounds bogus ***/
- if (!menubar_p)
- XtAddCallback (XtParent (widget), XmNpopdownCallback,
- xm_pop_down_callback, (XtPointer)instance);
-
- /* Preserve the first KEEP_FIRST_CHILDREN old children. */
- for (child_index = 0, cur = val; child_index < keep_first_children;
- child_index++, cur = cur->next)
- children[child_index] = old_children[child_index];
-
- /* Check that those are all we have
- (the caller should have deleted the rest). */
- if (old_num_children != keep_first_children)
- abort ();
-
- /* Create the rest. */
- for (child_index = keep_first_children; cur; child_index++, cur = cur->next)
- {
- ac = 0;
- XtSetArg (al [ac], XmNsensitive, cur->enabled); ac++;
- XtSetArg (al [ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
- XtSetArg (al [ac], XmNuserData, cur->call_data); ac++;
-
- if (instance->pop_up_p && !cur->contents && !cur->call_data
- && !all_dashes_p (cur->name))
- {
- ac = 0;
- XtSetArg (al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
- button = XmCreateLabel (widget, cur->name, al, ac);
- }
- else if (all_dashes_p (cur->name))
- {
- button = XmCreateSeparator (widget, cur->name, NULL, 0);
- }
- else if (!cur->contents)
- {
- if (menubar_p)
- button = XmCreateCascadeButton (widget, cur->name, al, ac);
- else if (!cur->call_data)
- button = XmCreateLabel (widget, cur->name, al, ac);
- else
- button = XmCreatePushButtonGadget (widget, cur->name, al, ac);
-
- xm_update_label (instance, button, cur);
-
- /* don't add a callback to a simple label */
- if (cur->call_data)
- XtAddCallback (button, XmNactivateCallback, xm_generic_callback,
- (XtPointer)instance);
- }
- else
- {
- menu = XmCreatePulldownMenu (widget, cur->name, NULL, 0);
- make_menu_in_widget (instance, menu, cur->contents, 0);
- XtSetArg (al [ac], XmNsubMenuId, menu); ac++;
- /* non-zero values don't work reliably in
- conjunction with Emacs' event loop */
- XtSetArg (al [ac], XmNmappingDelay, 0); ac++;
- button = XmCreateCascadeButtonGadget (widget, cur->name, al, ac);
-
- xm_update_label (instance, button, cur);
-
- XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
- (XtPointer)instance);
- }
-
- children [child_index] = button;
- }
-
- XtManageChildren (children, num_children);
-
- /* Last entry is the help button. Has to be done after managing
- * the buttons otherwise the menubar is only 4 pixels high... */
- if (button)
- {
- ac = 0;
- XtSetArg (al [ac], XmNmenuHelpWidget, button); ac++;
- XtSetValues (widget, al, ac);
- }
-
- XtFree ((char *) children);
- if (old_children)
- XtFree ((char *) old_children);
-}
-
-static void
-update_one_menu_entry (instance, widget, val, deep_p)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
- Boolean deep_p;
-{
- Arg al [256];
- int ac;
- Widget menu;
- widget_value* contents;
-
- if (val->this_one_change == NO_CHANGE)
- return;
-
- /* update the sensitivity and userdata */
- /* Common to all widget types */
- XtVaSetValues (widget,
- XmNsensitive, val->enabled,
- XmNuserData, val->call_data,
- 0);
-
- /* update the menu button as a label. */
- if (val->this_one_change >= VISIBLE_CHANGE)
- xm_update_label (instance, widget, val);
-
- /* update the pulldown/pullaside as needed */
- ac = 0;
- menu = NULL;
- XtSetArg (al [ac], XmNsubMenuId, &menu); ac++;
- XtGetValues (widget, al, ac);
-
- contents = val->contents;
-
- if (!menu)
- {
- if (contents)
- {
- unsigned int old_num_children, i;
- Widget parent;
- Widget *widget_list;
-
- parent = XtParent (widget);
- widget_list = XtCompositeChildren (parent, &old_num_children);
-
- /* Find the widget position within the parent's widget list. */
- for (i = 0; i < old_num_children; i++)
- if (strcmp (XtName (widget_list[i]), XtName (widget)) == 0)
- break;
- if (i == old_num_children)
- abort ();
- if (XmIsCascadeButton (widget_list[i]))
- {
- menu = XmCreatePulldownMenu (parent, XtName(widget), NULL, 0);
- make_menu_in_widget (instance, menu, contents, 0);
- ac = 0;
- XtSetArg (al [ac], XmNsubMenuId, menu); ac++;
- XtSetValues (widget, al, ac);
- }
- else
- {
- Widget button;
-
- /* The current menuitem is a XmPushButtonGadget, it
- needs to be replaced by a CascadeButtonGadget */
- XtDestroyWidget (widget_list[i]);
- menu = XmCreatePulldownMenu (parent, val->name, NULL, 0);
- make_menu_in_widget (instance, menu, contents, 0);
- ac = 0;
- XtSetArg (al [ac], XmNsubMenuId, menu); ac++;
- /* Non-zero values don't work reliably in
- conjunction with Emacs' event loop */
- XtSetArg (al [ac], XmNmappingDelay, 0); ac++;
- /* Tell Motif to put it in the right place */
- XtSetArg (al [ac], XmNpositionIndex, i); ac++;
- button = XmCreateCascadeButtonGadget (parent, val->name, al, ac);
- xm_update_label (instance, button, val);
-
- XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
- (XtPointer)instance);
- XtManageChild (button);
- }
- }
- }
- else if (!contents)
- {
- ac = 0;
- XtSetArg (al [ac], XmNsubMenuId, NULL); ac++;
- XtSetValues (widget, al, ac);
- XtDestroyWidget (menu);
- }
- else if (deep_p && contents->change != NO_CHANGE)
- xm_update_menu (instance, menu, val, 1);
-}
-
-static void
-xm_update_menu (instance, widget, val, deep_p)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
- Boolean deep_p;
-{
- Widget* children;
- unsigned int num_children;
- int num_children_to_keep = 0;
- int i;
- widget_value* cur;
-
- children = XtCompositeChildren (widget, &num_children);
-
- /* Widget is a RowColumn widget whose contents have to be updated
- * to reflect the list of items in val->contents */
-
- /* See how many buttons we can keep, and how many we
- must completely replace. */
- if (val->contents == 0)
- num_children_to_keep = 0;
- else if (val->contents->change == STRUCTURAL_CHANGE)
- {
- if (children)
- {
- for (i = 0, cur = val->contents;
- (i < num_children
- && cur); /* how else to ditch unwanted children ?? - mgd */
- i++, cur = cur->next)
- {
- if (cur->this_one_change == STRUCTURAL_CHANGE)
- break;
- }
-
- num_children_to_keep = i;
- }
- }
- else
- num_children_to_keep = num_children;
-
- /* Update all the buttons of the RowColumn, in order,
- except for those we are going to replace entirely. */
- if (children)
- {
- for (i = 0, cur = val->contents; i < num_children_to_keep; i++)
- {
- if (!cur)
- {
- num_children_to_keep = i;
- break;
- }
- if (children [i]->core.being_destroyed
- || strcmp (XtName (children [i]), cur->name))
- continue;
- update_one_menu_entry (instance, children [i], cur, deep_p);
- cur = cur->next;
- }
- }
-
- /* Now replace from scratch all the buttons after the last
- place that the top-level structure changed. */
- if (val->contents->change == STRUCTURAL_CHANGE)
- {
- destroy_all_children (widget, num_children_to_keep);
- make_menu_in_widget (instance, widget, val->contents,
- num_children_to_keep);
- }
-
- XtFree ((char *) children);
-}
-
-
-/* update text widgets */
-
-static void
-xm_update_text (instance, widget, val)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
-{
- XmTextSetString (widget, val->value ? val->value : "");
- XtRemoveAllCallbacks (widget, XmNactivateCallback);
- XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
- XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
- XtAddCallback (widget, XmNvalueChangedCallback,
- xm_internal_update_other_instances, instance);
-}
-
-static void
-xm_update_text_field (instance, widget, val)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
-{
- XmTextFieldSetString (widget, val->value ? val->value : "");
- XtRemoveAllCallbacks (widget, XmNactivateCallback);
- XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
- XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
- XtAddCallback (widget, XmNvalueChangedCallback,
- xm_internal_update_other_instances, instance);
-}
-
-
-/* update a motif widget */
-
-void
-xm_update_one_widget (instance, widget, val, deep_p)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
- Boolean deep_p;
-{
- WidgetClass class;
-
- /* Mark as not edited */
- val->edited = False;
-
- /* Common to all widget types */
- XtVaSetValues (widget,
- XmNsensitive, val->enabled,
- XmNuserData, val->call_data,
- 0);
-
- /* Common to all label like widgets */
- if (XtIsSubclass (widget, xmLabelWidgetClass))
- xm_update_label (instance, widget, val);
-
- class = XtClass (widget);
- /* Class specific things */
- if (class == xmPushButtonWidgetClass ||
- class == xmArrowButtonWidgetClass)
- {
- xm_update_pushbutton (instance, widget, val);
- }
- else if (class == xmCascadeButtonWidgetClass)
- {
- xm_update_cascadebutton (instance, widget, val);
- }
- else if (class == xmToggleButtonWidgetClass
- || class == xmToggleButtonGadgetClass)
- {
- xm_update_toggle (instance, widget, val);
- }
- else if (class == xmRowColumnWidgetClass)
- {
- Boolean radiobox = 0;
- int ac = 0;
- Arg al [1];
-
- XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
- XtGetValues (widget, al, ac);
-
- if (radiobox)
- xm_update_radiobox (instance, widget, val);
- else
- xm_update_menu (instance, widget, val, deep_p);
- }
- else if (class == xmTextWidgetClass)
- {
- xm_update_text (instance, widget, val);
- }
- else if (class == xmTextFieldWidgetClass)
- {
- xm_update_text_field (instance, widget, val);
- }
- else if (class == xmListWidgetClass)
- {
- xm_update_list (instance, widget, val);
- }
-}
-
- /* getting the value back */
-void
-xm_update_one_value (instance, widget, val)
- widget_instance* instance;
- Widget widget;
- widget_value* val;
-{
- WidgetClass class = XtClass (widget);
- widget_value *old_wv;
-
- /* copy the call_data slot into the "return" widget_value */
- for (old_wv = instance->info->val->contents; old_wv; old_wv = old_wv->next)
- if (!strcmp (val->name, old_wv->name))
- {
- val->call_data = old_wv->call_data;
- break;
- }
-
- if (class == xmToggleButtonWidgetClass || class == xmToggleButtonGadgetClass)
- {
- XtVaGetValues (widget, XmNset, &val->selected, 0);
- val->edited = True;
- }
- else if (class == xmTextWidgetClass)
- {
- if (val->value)
- free (val->value);
- val->value = XmTextGetString (widget);
- val->edited = True;
- }
- else if (class == xmTextFieldWidgetClass)
- {
- if (val->value)
- free (val->value);
- val->value = XmTextFieldGetString (widget);
- val->edited = True;
- }
- else if (class == xmRowColumnWidgetClass)
- {
- Boolean radiobox = 0;
- int ac = 0;
- Arg al [1];
-
- XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
- XtGetValues (widget, al, ac);
-
- if (radiobox)
- {
- CompositeWidget radio = (CompositeWidget)widget;
- int i;
- for (i = 0; i < radio->composite.num_children; i++)
- {
- int set = False;
- Widget toggle = radio->composite.children [i];
-
- XtVaGetValues (toggle, XmNset, &set, 0);
- if (set)
- {
- if (val->value)
- free (val->value);
- val->value = safe_strdup (XtName (toggle));
- }
- }
- val->edited = True;
- }
- }
- else if (class == xmListWidgetClass)
- {
- int pos_cnt;
- int* pos_list;
- if (XmListGetSelectedPos (widget, &pos_list, &pos_cnt))
- {
- int i;
- widget_value* cur;
- for (cur = val->contents, i = 0; cur; cur = cur->next)
- if (cur->value)
- {
- int j;
- cur->selected = False;
- i += 1;
- for (j = 0; j < pos_cnt; j++)
- if (pos_list [j] == i)
- {
- cur->selected = True;
- val->value = safe_strdup (cur->name);
- }
- }
- val->edited = 1;
- XtFree ((char *) pos_list);
- }
- }
-}
-
-
-/* This function is for activating a button from a program. It's wrong because
- we pass a NULL argument in the call_data which is not Motif compatible.
- This is used from the XmNdefaultAction callback of the List widgets to
- have a double-click put down a dialog box like the button would do.
- I could not find a way to do that with accelerators.
- */
-static void
-activate_button (widget, closure, call_data)
- Widget widget;
- XtPointer closure;
- XtPointer call_data;
-{
- Widget button = (Widget)closure;
- XtCallCallbacks (button, XmNactivateCallback, NULL);
-}
-
-/* creation functions */
-
-/* dialogs */
-static Widget
-make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
- radio_box, list, left_buttons, right_buttons)
- char* name;
- Widget parent;
- Boolean pop_up_p;
- char* shell_title;
- char* icon_name;
- Boolean text_input_slot;
- Boolean radio_box;
- Boolean list;
- int left_buttons;
- int right_buttons;
-{
- Widget result;
- Widget form;
- Widget row;
- Widget icon;
- Widget icon_separator;
- Widget message;
- Widget value = 0;
- Widget separator;
- Widget button = 0;
- Widget children [16]; /* for the final XtManageChildren */
- int n_children;
- Arg al[64]; /* Arg List */
- int ac; /* Arg Count */
- int i;
-
- if (pop_up_p)
- {
- ac = 0;
- XtSetArg(al[ac], XmNtitle, shell_title); ac++;
- XtSetArg(al[ac], XtNallowShellResize, True); ac++;
- XtSetArg(al[ac], XmNdeleteResponse, XmUNMAP); ac++;
- result = XmCreateDialogShell (parent, "dialog", al, ac);
- ac = 0;
- XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
-/* XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
- XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
- form = XmCreateForm (result, shell_title, al, ac);
- }
- else
- {
- ac = 0;
- XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
- XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
- form = XmCreateForm (parent, shell_title, al, ac);
- result = form;
- }
-
- n_children = left_buttons + right_buttons + 1;
- ac = 0;
- XtSetArg(al[ac], XmNpacking, n_children == 3?
- XmPACK_COLUMN: XmPACK_TIGHT); ac++;
- XtSetArg(al[ac], XmNorientation, n_children == 3?
- XmVERTICAL: XmHORIZONTAL); ac++;
- XtSetArg(al[ac], XmNnumColumns, left_buttons + right_buttons + 1); ac++;
- XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
- XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
- XtSetArg(al[ac], XmNspacing, 13); ac++;
- XtSetArg(al[ac], XmNadjustLast, False); ac++;
- XtSetArg(al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
- XtSetArg(al[ac], XmNisAligned, True); ac++;
- XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
- XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
- XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
- XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
- XtSetArg(al[ac], XmNleftOffset, 13); ac++;
- XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
- XtSetArg(al[ac], XmNrightOffset, 13); ac++;
- row = XmCreateRowColumn (form, "row", al, ac);
-
- n_children = 0;
- for (i = 0; i < left_buttons; i++)
- {
- char button_name [16];
- sprintf (button_name, "button%d", i + 1);
- ac = 0;
- if (i == 0)
- {
- XtSetArg(al[ac], XmNhighlightThickness, 1); ac++;
- XtSetArg(al[ac], XmNshowAsDefault, TRUE); ac++;
- }
- XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
- XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
- children [n_children] = XmCreatePushButton (row, button_name, al, ac);
-
- if (i == 0)
- {
- button = children [n_children];
- ac = 0;
- XtSetArg(al[ac], XmNdefaultButton, button); ac++;
- XtSetValues (row, al, ac);
- }
-
- n_children++;
- }
-
- /* invisible separator button */
- ac = 0;
- XtSetArg (al[ac], XmNmappedWhenManaged, FALSE); ac++;
- children [n_children] = XmCreateLabel (row, "separator_button", al, ac);
- n_children++;
-
- for (i = 0; i < right_buttons; i++)
- {
- char button_name [16];
- sprintf (button_name, "button%d", left_buttons + i + 1);
- ac = 0;
- XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
- XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
- children [n_children] = XmCreatePushButton (row, button_name, al, ac);
- if (! button) button = children [n_children];
- n_children++;
- }
-
- XtManageChildren (children, n_children);
-
- ac = 0;
- XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
- XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
- XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
- XtSetArg(al[ac], XmNbottomWidget, row); ac++;
- XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
- XtSetArg(al[ac], XmNleftOffset, 0); ac++;
- XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
- XtSetArg(al[ac], XmNrightOffset, 0); ac++;
- separator = XmCreateSeparator (form, "", al, ac);
-
- ac = 0;
- XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
- XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
- XtSetArg(al[ac], XmNtopOffset, 13); ac++;
- XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
- XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
- XtSetArg(al[ac], XmNleftOffset, 13); ac++;
- XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
- icon = XmCreateLabel (form, icon_name, al, ac);
-
- ac = 0;
- XtSetArg(al[ac], XmNmappedWhenManaged, FALSE); ac++;
- XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
- XtSetArg(al[ac], XmNtopOffset, 6); ac++;
- XtSetArg(al[ac], XmNtopWidget, icon); ac++;
- XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
- XtSetArg(al[ac], XmNbottomOffset, 6); ac++;
- XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
- XtSetArg(al[ac], XmNleftAttachment, XmATTACH_NONE); ac++;
- XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
- icon_separator = XmCreateLabel (form, "", al, ac);
-
- if (text_input_slot)
- {
- ac = 0;
- XtSetArg(al[ac], XmNcolumns, 50); ac++;
- XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
- XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
- XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
- XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
- XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
- XtSetArg(al[ac], XmNleftOffset, 13); ac++;
- XtSetArg(al[ac], XmNleftWidget, icon); ac++;
- XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
- XtSetArg(al[ac], XmNrightOffset, 13); ac++;
- value = XmCreateTextField (form, "value", al, ac);
- }
- else if (radio_box)
- {
- Widget radio_butt;
- ac = 0;
- XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
- XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
- XtSetArg(al[ac], XmNspacing, 13); ac++;
- XtSetArg(al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
- XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++;
- XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
- XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
- XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
- XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
- XtSetArg(al[ac], XmNleftOffset, 13); ac++;
- XtSetArg(al[ac], XmNleftWidget, icon); ac++;
- XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
- XtSetArg(al[ac], XmNrightOffset, 13); ac++;
- value = XmCreateRadioBox (form, "radiobutton1", al, ac);
- ac = 0;
- i = 0;
- radio_butt = XmCreateToggleButtonGadget (value, "radio1", al, ac);
- children [i++] = radio_butt;
- radio_butt = XmCreateToggleButtonGadget (value, "radio2", al, ac);
- children [i++] = radio_butt;
- radio_butt = XmCreateToggleButtonGadget (value, "radio3", al, ac);
- children [i++] = radio_butt;
- XtManageChildren (children, i);
- }
- else if (list)
- {
- ac = 0;
- XtSetArg(al[ac], XmNvisibleItemCount, 5); ac++;
- XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
- XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
- XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
- XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
- XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
- XtSetArg(al[ac], XmNleftOffset, 13); ac++;
- XtSetArg(al[ac], XmNleftWidget, icon); ac++;
- XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
- XtSetArg(al[ac], XmNrightOffset, 13); ac++;
- value = XmCreateScrolledList (form, "list", al, ac);
-
- /* this is the easiest way I found to have the dble click in the
- list activate the default button */
- XtAddCallback (value, XmNdefaultActionCallback, activate_button, button);
- }
-
- ac = 0;
- XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
- XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
- XtSetArg(al[ac], XmNtopOffset, 13); ac++;
- XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
- XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
- XtSetArg(al[ac], XmNbottomWidget,
- text_input_slot || radio_box || list ? value : separator); ac++;
- XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
- XtSetArg(al[ac], XmNleftOffset, 13); ac++;
- XtSetArg(al[ac], XmNleftWidget, icon); ac++;
- XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
- XtSetArg(al[ac], XmNrightOffset, 13); ac++;
- message = XmCreateLabel (form, "message", al, ac);
-
- if (list)
- XtManageChild (value);
-
- i = 0;
- children [i] = row; i++;
- children [i] = separator; i++;
- if (text_input_slot || radio_box)
- {
- children [i] = value; i++;
- }
- children [i] = message; i++;
- children [i] = icon; i++;
- children [i] = icon_separator; i++;
- XtManageChildren (children, i);
-
- if (text_input_slot || list)
- {
- XtInstallAccelerators (value, button);
- XtSetKeyboardFocus (result, value);
- }
- else
- {
- XtInstallAccelerators (form, button);
- XtSetKeyboardFocus (result, button);
- }
-
- return result;
-}
-
-static destroyed_instance*
-find_matching_instance (instance)
- widget_instance* instance;
-{
- destroyed_instance* cur;
- destroyed_instance* prev;
- char* type = instance->info->type;
- char* name = instance->info->name;
-
- for (prev = NULL, cur = all_destroyed_instances;
- cur;
- prev = cur, cur = cur->next)
- {
- if (!strcmp (cur->name, name)
- && !strcmp (cur->type, type)
- && cur->parent == instance->parent
- && cur->pop_up_p == instance->pop_up_p)
- {
- if (prev)
- prev->next = cur->next;
- else
- all_destroyed_instances = cur->next;
- return cur;
- }
- /* do some cleanup */
- else if (!cur->widget)
- {
- if (prev)
- prev->next = cur->next;
- else
- all_destroyed_instances = cur->next;
- free_destroyed_instance (cur);
- cur = prev ? prev : all_destroyed_instances;
- }
- }
- return NULL;
-}
-
-static void
-mark_dead_instance_destroyed (widget, closure, call_data)
- Widget widget;
- XtPointer closure;
- XtPointer call_data;
-{
- destroyed_instance* instance = (destroyed_instance*)closure;
- instance->widget = NULL;
-}
-
-static void
-recenter_widget (widget)
- Widget widget;
-{
- Widget parent = XtParent (widget);
- Screen* screen = XtScreen (widget);
- Dimension screen_width = WidthOfScreen (screen);
- Dimension screen_height = HeightOfScreen (screen);
- Dimension parent_width = 0;
- Dimension parent_height = 0;
- Dimension child_width = 0;
- Dimension child_height = 0;
- Position x;
- Position y;
-
- XtVaGetValues (widget, XtNwidth, &child_width, XtNheight, &child_height, 0);
- XtVaGetValues (parent, XtNwidth, &parent_width, XtNheight, &parent_height,
- 0);
-
- x = (((Position)parent_width) - ((Position)child_width)) / 2;
- y = (((Position)parent_height) - ((Position)child_height)) / 2;
-
- XtTranslateCoords (parent, x, y, &x, &y);
-
- if (x + child_width > screen_width)
- x = screen_width - child_width;
- if (x < 0)
- x = 0;
-
- if (y + child_height > screen_height)
- y = screen_height - child_height;
- if (y < 0)
- y = 0;
-
- XtVaSetValues (widget, XtNx, x, XtNy, y, 0);
-}
-
-static Widget
-recycle_instance (instance)
- destroyed_instance* instance;
-{
- Widget widget = instance->widget;
-
- /* widget is NULL if the parent was destroyed. */
- if (widget)
- {
- Widget focus;
- Widget separator;
-
- /* Remove the destroy callback as the instance is not in the list
- anymore */
- XtRemoveCallback (instance->parent, XtNdestroyCallback,
- mark_dead_instance_destroyed,
- (XtPointer)instance);
-
- /* Give the focus to the initial item */
- focus = XtNameToWidget (widget, "*value");
- if (!focus)
- focus = XtNameToWidget (widget, "*button1");
- if (focus)
- XtSetKeyboardFocus (widget, focus);
-
- /* shrink the separator label back to their original size */
- separator = XtNameToWidget (widget, "*separator_button");
- if (separator)
- XtVaSetValues (separator, XtNwidth, 5, XtNheight, 5, 0);
-
- /* Center the dialog in its parent */
- recenter_widget (widget);
- }
- free_destroyed_instance (instance);
- return widget;
-}
-
-Widget
-xm_create_dialog (instance)
- widget_instance* instance;
-{
- char* name = instance->info->type;
- Widget parent = instance->parent;
- Widget widget;
- Boolean pop_up_p = instance->pop_up_p;
- char* shell_name = 0;
- char* icon_name;
- Boolean text_input_slot = False;
- Boolean radio_box = False;
- Boolean list = False;
- int total_buttons;
- int left_buttons = 0;
- int right_buttons = 1;
- destroyed_instance* dead_one;
-
- /* try to find a widget to recycle */
- dead_one = find_matching_instance (instance);
- if (dead_one)
- {
- Widget recycled_widget = recycle_instance (dead_one);
- if (recycled_widget)
- return recycled_widget;
- }
-
- switch (name [0]){
- case 'E': case 'e':
- icon_name = "dbox-error";
- shell_name = "Error";
- break;
-
- case 'I': case 'i':
- icon_name = "dbox-info";
- shell_name = "Information";
- break;
-
- case 'L': case 'l':
- list = True;
- icon_name = "dbox-question";
- shell_name = "Prompt";
- break;
-
- case 'P': case 'p':
- text_input_slot = True;
- icon_name = "dbox-question";
- shell_name = "Prompt";
- break;
-
- case 'Q': case 'q':
- icon_name = "dbox-question";
- shell_name = "Question";
- break;
- }
-
- total_buttons = name [1] - '0';
-
- if (name [3] == 'T' || name [3] == 't')
- {
- text_input_slot = False;
- radio_box = True;
- }
- else if (name [3])
- right_buttons = name [4] - '0';
-
- left_buttons = total_buttons - right_buttons;
-
- widget = make_dialog (name, parent, pop_up_p,
- shell_name, icon_name, text_input_slot, radio_box,
- list, left_buttons, right_buttons);
-
- XtAddCallback (widget, XmNpopdownCallback, xm_nosel_callback,
- (XtPointer) instance);
- return widget;
-}
-
-/* Create a menu bar. We turn off the f10 key
- because we have not yet managed to make it work right in Motif. */
-
-static Widget
-make_menubar (instance)
- widget_instance* instance;
-{
- Arg al[1];
- int ac;
-
- ac = 0;
- XtSetArg(al[0], XmNmenuAccelerator, 0);
- return XmCreateMenuBar (instance->parent, instance->info->name, al, 1);
-}
-
-static void
-remove_grabs (shell, closure, call_data)
- Widget shell;
- XtPointer closure;
- XtPointer call_data;
-{
- Widget menu = (Widget) closure;
- XmRemoveFromPostFromList (menu, XtParent (XtParent (menu)));
-}
-
-static Widget
-make_popup_menu (instance)
- widget_instance* instance;
-{
- Widget parent = instance->parent;
- Window parent_window = parent->core.window;
- Widget result;
-
- /* sets the parent window to 0 to fool Motif into not generating a grab */
- parent->core.window = 0;
- result = XmCreatePopupMenu (parent, instance->info->name, NULL, 0);
- XtAddCallback (XtParent (result), XmNpopdownCallback, remove_grabs,
- (XtPointer)result);
- parent->core.window = parent_window;
- return result;
-}
-static Widget
-make_main (instance)
- widget_instance* instance;
-{
- Widget parent = instance->parent;
- Widget result;
- Arg al[2];
- int ac;
-
- ac = 0;
- XtSetArg (al[ac], XtNborderWidth, 0); ac++;
- XtSetArg (al[ac], XmNspacing, 0); ac++;
- result = XmCreateMainWindow (parent, instance->info->name, al, ac);
- return result;
-}
-
- /* Table of functions to create widgets */
-
-#ifdef ENERGIZE
-
-/* interface with the XDesigner generated functions */
-typedef Widget (*widget_maker) (Widget);
-extern Widget create_project_p_sheet (Widget parent);
-extern Widget create_debugger_p_sheet (Widget parent);
-extern Widget create_breaklist_p_sheet (Widget parent);
-extern Widget create_le_browser_p_sheet (Widget parent);
-extern Widget create_class_browser_p_sheet (Widget parent);
-extern Widget create_call_browser_p_sheet (Widget parent);
-extern Widget create_build_dialog (Widget parent);
-extern Widget create_editmode_dialog (Widget parent);
-extern Widget create_search_dialog (Widget parent);
-extern Widget create_project_display_dialog (Widget parent);
-
-static Widget
-make_one (widget_instance* instance, widget_maker fn)
-{
- Widget result;
- Arg al [64];
- int ac = 0;
-
- if (instance->pop_up_p)
- {
- XtSetArg (al [ac], XmNallowShellResize, TRUE); ac++;
- result = XmCreateDialogShell (instance->parent, "dialog", NULL, 0);
- XtAddCallback (result, XmNpopdownCallback, &xm_nosel_callback,
- (XtPointer) instance);
- (*fn) (result);
- }
- else
- {
- result = (*fn) (instance->parent);
- XtRealizeWidget (result);
- }
- return result;
-}
-
-static Widget
-make_project_p_sheet (widget_instance* instance)
-{
- return make_one (instance, create_project_p_sheet);
-}
-
-static Widget
-make_debugger_p_sheet (widget_instance* instance)
-{
- return make_one (instance, create_debugger_p_sheet);
-}
-
-static Widget
-make_breaklist_p_sheet (widget_instance* instance)
-{
- return make_one (instance, create_breaklist_p_sheet);
-}
-
-static Widget
-make_le_browser_p_sheet (widget_instance* instance)
-{
- return make_one (instance, create_le_browser_p_sheet);
-}
-
-static Widget
-make_class_browser_p_sheet (widget_instance* instance)
-{
- return make_one (instance, create_class_browser_p_sheet);
-}
-
-static Widget
-make_call_browser_p_sheet (widget_instance* instance)
-{
- return make_one (instance, create_call_browser_p_sheet);
-}
-
-static Widget
-make_build_dialog (widget_instance* instance)
-{
- return make_one (instance, create_build_dialog);
-}
-
-static Widget
-make_editmode_dialog (widget_instance* instance)
-{
- return make_one (instance, create_editmode_dialog);
-}
-
-static Widget
-make_search_dialog (widget_instance* instance)
-{
- return make_one (instance, create_search_dialog);
-}
-
-static Widget
-make_project_display_dialog (widget_instance* instance)
-{
- return make_one (instance, create_project_display_dialog);
-}
-
-#endif /* ENERGIZE */
-
-widget_creation_entry
-xm_creation_table [] =
-{
- {"menubar", make_menubar},
- {"popup", make_popup_menu},
- {"main", make_main},
-#ifdef ENERGIZE
- {"project_p_sheet", make_project_p_sheet},
- {"debugger_p_sheet", make_debugger_p_sheet},
- {"breaklist_psheet", make_breaklist_p_sheet},
- {"leb_psheet", make_le_browser_p_sheet},
- {"class_browser_psheet", make_class_browser_p_sheet},
- {"ctree_browser_psheet", make_call_browser_p_sheet},
- {"build", make_build_dialog},
- {"editmode", make_editmode_dialog},
- {"search", make_search_dialog},
- {"project_display", make_project_display_dialog},
-#endif /* ENERGIZE */
- {NULL, NULL}
-};
-
- /* Destruction of instances */
-void
-xm_destroy_instance (instance)
- widget_instance* instance;
-{
- Widget widget = instance->widget;
- /* recycle the dialog boxes */
- /* Disable the recycling until we can find a way to have the dialog box
- get reasonable layout after we modify its contents. */
- if (0
- && XtClass (widget) == xmDialogShellWidgetClass)
- {
- destroyed_instance* dead_instance =
- make_destroyed_instance (instance->info->name,
- instance->info->type,
- instance->widget,
- instance->parent,
- instance->pop_up_p);
- dead_instance->next = all_destroyed_instances;
- all_destroyed_instances = dead_instance;
- XtUnmanageChild (first_child (instance->widget));
- XFlush (XtDisplay (instance->widget));
- XtAddCallback (instance->parent, XtNdestroyCallback,
- mark_dead_instance_destroyed, (XtPointer)dead_instance);
- }
- else
- {
- /* This might not be necessary now that the nosel is attached to
- popdown instead of destroy, but it can't hurt. */
- XtRemoveCallback (instance->widget, XtNdestroyCallback,
- xm_nosel_callback, (XtPointer)instance);
- XtDestroyWidget (instance->widget);
- }
-}
-
- /* popup utility */
-void
-xm_popup_menu (widget, event)
- Widget widget;
- XEvent *event;
-{
- XButtonPressedEvent dummy;
-
- if (event == 0)
- {
- dummy.type = ButtonPress;
- dummy.serial = 0;
- dummy.send_event = 0;
- dummy.display = XtDisplay (widget);
- dummy.window = XtWindow (XtParent (widget));
- dummy.time = 0;
- dummy.button = 0;
- XQueryPointer (dummy.display, dummy.window, &dummy.root,
- &dummy.subwindow, &dummy.x_root, &dummy.y_root,
- &dummy.x, &dummy.y, &dummy.state);
- event = (XEvent *) &dummy;
- }
-
- if (event->type == ButtonPress || event->type == ButtonRelease)
- {
- /* This is so totally ridiculous: there's NO WAY to tell Motif
- that *any* button can select a menu item. Only one button
- can have that honor.
- */
- char *trans = 0;
- if (event->xbutton.state & Button5Mask) trans = "<Btn5Down>";
- else if (event->xbutton.state & Button4Mask) trans = "<Btn4Down>";
- else if (event->xbutton.state & Button3Mask) trans = "<Btn3Down>";
- else if (event->xbutton.state & Button2Mask) trans = "<Btn2Down>";
- else if (event->xbutton.state & Button1Mask) trans = "<Btn1Down>";
- if (trans) XtVaSetValues (widget, XmNmenuPost, trans, 0);
- XmMenuPosition (widget, (XButtonPressedEvent *) event);
- }
- XtManageChild (widget);
-}
-
-static void
-set_min_dialog_size (w)
- Widget w;
-{
- short width;
- short height;
- XtVaGetValues (w, XmNwidth, &width, XmNheight, &height, 0);
- XtVaSetValues (w, XmNminWidth, width, XmNminHeight, height, 0);
-}
-
-void
-xm_pop_instance (instance, up)
- widget_instance* instance;
- Boolean up;
-{
- Widget widget = instance->widget;
-
- if (XtClass (widget) == xmDialogShellWidgetClass)
- {
- Widget widget_to_manage = first_child (widget);
- if (up)
- {
- XtManageChild (widget_to_manage);
- set_min_dialog_size (widget);
- XtSetKeyboardFocus (instance->parent, widget);
- }
- else
- XtUnmanageChild (widget_to_manage);
- }
- else
- {
- if (up)
- XtManageChild (widget);
- else
- XtUnmanageChild (widget);
- }
-}
-
-
-/* motif callback */
-
-enum do_call_type { pre_activate, selection, no_selection, post_activate };
-
-static void
-do_call (widget, closure, type)
- Widget widget;
- XtPointer closure;
- enum do_call_type type;
-{
- Arg al [256];
- int ac;
- XtPointer user_data;
- widget_instance* instance = (widget_instance*)closure;
- Widget instance_widget;
- LWLIB_ID id;
-
- if (!instance)
- return;
- if (widget->core.being_destroyed)
- return;
-
- instance_widget = instance->widget;
- if (!instance_widget)
- return;
-
- id = instance->info->id;
- ac = 0;
- user_data = NULL;
- XtSetArg (al [ac], XmNuserData, &user_data); ac++;
- XtGetValues (widget, al, ac);
- switch (type)
- {
- case pre_activate:
- if (instance->info->pre_activate_cb)
- instance->info->pre_activate_cb (widget, id, user_data);
- break;
- case selection:
- if (instance->info->selection_cb)
- instance->info->selection_cb (widget, id, user_data);
- break;
- case no_selection:
- if (instance->info->selection_cb)
- instance->info->selection_cb (widget, id, (XtPointer) -1);
- break;
- case post_activate:
- if (instance->info->post_activate_cb)
- instance->info->post_activate_cb (widget, id, user_data);
- break;
- default:
- abort ();
- }
-}
-
-/* Like lw_internal_update_other_instances except that it does not do
- anything if its shell parent is not managed. This is to protect
- lw_internal_update_other_instances to dereference freed memory
- if the widget was ``destroyed'' by caching it in the all_destroyed_instances
- list */
-static void
-xm_internal_update_other_instances (widget, closure, call_data)
- Widget widget;
- XtPointer closure;
- XtPointer call_data;
-{
- Widget parent;
- for (parent = widget; parent; parent = XtParent (parent))
- if (XtIsShell (parent))
- break;
- else if (!XtIsManaged (parent))
- return;
- lw_internal_update_other_instances (widget, closure, call_data);
-}
-
-static void
-xm_generic_callback (widget, closure, call_data)
- Widget widget;
- XtPointer closure;
- XtPointer call_data;
-{
- lw_internal_update_other_instances (widget, closure, call_data);
- do_call (widget, closure, selection);
-}
-
-static void
-xm_nosel_callback (widget, closure, call_data)
- Widget widget;
- XtPointer closure;
- XtPointer call_data;
-{
- /* This callback is only called when a dialog box is dismissed with the wm's
- destroy button (WM_DELETE_WINDOW.) We want the dialog box to be destroyed
- in that case, not just unmapped, so that it releases its keyboard grabs.
- But there are problems with running our callbacks while the widget is in
- the process of being destroyed, so we set XmNdeleteResponse to XmUNMAP
- instead of XmDESTROY and then destroy it ourself after having run the
- callback.
- */
- do_call (widget, closure, no_selection);
- XtDestroyWidget (widget);
-}
-
-static void
-xm_pull_down_callback (widget, closure, call_data)
- Widget widget;
- XtPointer closure;
- XtPointer call_data;
-{
- do_call (widget, closure, pre_activate);
-}
-
-static void
-xm_pop_down_callback (widget, closure, call_data)
- Widget widget;
- XtPointer closure;
- XtPointer call_data;
-{
- widget_instance *instance = (widget_instance *) closure;
-
- if ((!instance->pop_up_p && (XtParent (widget) == instance->widget))
- || (XtParent (widget) == instance->parent))
- do_call (widget, closure, post_activate);
-}
-
-
-/* set the keyboard focus */
-void
-xm_set_keyboard_focus (parent, w)
- Widget parent;
- Widget w;
-{
- XmProcessTraversal (w, 0);
- XtSetKeyboardFocus (parent, w);
-}
-
-/* Motif hack to set the main window areas. */
-void
-xm_set_main_areas (parent, menubar, work_area)
- Widget parent;
- Widget menubar;
- Widget work_area;
-{
- XmMainWindowSetAreas (parent,
- menubar, /* menubar (maybe 0) */
- 0, /* command area (psheets) */
- 0, /* horizontal scroll */
- 0, /* vertical scroll */
- work_area); /* work area */
-}
-
-/* Motif hack to control resizing on the menubar. */
-void
-xm_manage_resizing (w, flag)
- Widget w;
- Boolean flag;
-{
- if (flag)
- {
- /* Enable the edit widget for resizing. */
- Arg al[1];
-
- XtSetArg (al[0], XtNallowShellResize, 0);
- XtSetValues (w, al, 1);
- }
- else
- {
- /* Disable the edit widget from resizing. */
- Arg al[1];
-
- XtSetArg (al[0], XtNallowShellResize, 0);
- XtSetValues (w, al, 1);
- }
-}
diff --git a/lwlib/lwlib-Xm.h b/lwlib/lwlib-Xm.h
deleted file mode 100644
index 08c3d76f6ce..00000000000
--- a/lwlib/lwlib-Xm.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef LWLIB_XM_H
-#define LWLIB_XM_H
-
-#include "lwlib-int.h"
-
-extern widget_creation_entry xm_creation_table [];
-
-Widget
-xm_create_dialog (/* widget_instance* instance */);
-
-Boolean
-lw_motif_widget_p (/* Widget widget */);
-
-void
-xm_update_one_widget (/* widget_instance* instance, Widget widget,
- widget_value* val, Boolean deep_p */);
-
-void
-xm_update_one_value (/* widget_instance* instance, Widget widget,
- widget_value* val */);
-
-void
-xm_destroy_instance (/* widget_instance* instance */);
-
-void
-xm_set_keyboard_focus (/* Widget parent, Widget w */);
-
-void
-xm_popup_menu (/* Widget widget */);
-
-void
-xm_pop_instance (/* widget_instance* instance, Boolean up */);
-
-void
-xm_set_main_areas (/* Widget parent, Widget menubar, Widget work_area */);
-
-void
-xm_manage_resizing (/* Widget w, Boolean flag */);
-
-#endif /* LWLIB_XM_H */
diff --git a/lwlib/lwlib-Xol.c b/lwlib/lwlib-Xol.c
deleted file mode 100644
index d34e70e1324..00000000000
--- a/lwlib/lwlib-Xol.c
+++ /dev/null
@@ -1,317 +0,0 @@
-#include "lwlib-Xol.h"
-#include <X11/StringDefs.h>
-#include <X11/IntrinsicP.h>
-#include <X11/CompositeP.h>
-#include <X11/Shell.h>
-#include <Xol/Menu.h>
-#include <Xol/OpenLook.h>
-#include <Xol/MenuButton.h>
-#include <Xol/OblongButt.h>
-#include <Xol/ControlAre.h>
-#include <Xol/Stub.h>
-#include <Xol/StaticText.h>
-
- /* forward declarations */
-static void
-update_menu_widget (widget_instance* instance, Widget widget,
- widget_value* val);
-
- /* Menu callbacks */
-static void
-pre_hook (Widget w, caddr_t client_data, caddr_t call_data)
-{
- OlVirtualEvent ve = (OlVirtualEvent)call_data;
- widget_instance* instance = (widget_instance*)client_data;
-
- if (w->core.being_destroyed)
- return;
-
- if (XtParent (w) == instance->widget)
- {
- if (ve->xevent->type == ButtonPress && instance->info->pre_activate_cb)
- instance->info->pre_activate_cb (instance->widget, instance->info->id,
- NULL);
- }
-}
-
-static void
-post_hook (Widget w, caddr_t client_data, caddr_t call_data)
-{
- widget_instance* instance = (widget_instance*)client_data;
-
- if (w->core.being_destroyed)
- return;
-
- if (instance->info->post_activate_cb)
- instance->info->post_activate_cb (w, instance->info->id, NULL);
-}
-
-static void
-pick_hook (Widget w, caddr_t client_data, caddr_t call_data)
-{
- widget_instance* instance = 0;
- widget_value* val = (widget_value*)client_data;
-
- if (w->core.being_destroyed)
- return;
-
- XtVaGetValues (w, XtNuserData, &instance, 0);
-
- if (!instance)
- return;
-
- if (instance->info->selection_cb && val && val->enabled
- && !val->contents)
- instance->info->selection_cb (w, instance->info->id, val->call_data);
-}
-
- /* creation functions */
-static Widget
-xol_create_menubar (widget_instance* instance)
-{
- Widget widget =
- XtVaCreateWidget (instance->info->name, controlAreaWidgetClass,
- instance->parent, 0);
- return widget;
-}
-
-static Widget
-xol_create_popup_menu (widget_instance* instance)
-{
- Widget popup_shell =
- XtCreatePopupShell (instance->info->name, menuShellWidgetClass,
- instance->parent, NULL, 0);
- return popup_shell;
-}
-
-widget_creation_entry
-xol_creation_table [] =
-{
- {"menubar", xol_create_menubar},
- {"popup", xol_create_popup_menu},
- {NULL, NULL}
-};
-
-Widget
-xol_create_dialog (widget_instance* instance)
-{
- return NULL;
-}
-
-Boolean
-lw_olit_widget_p (Widget widget)
-{
- return True;
-}
-
- /* update functions */
-static void
-destroy_all_children (Widget widget)
-{
- Widget* children;
- unsigned int number;
- int i;
-
- children = (Widget *) XtCompositeChildren (widget, &number);
- if (children)
- {
- /* Unmanage all children and destroy them. They will only be
- * really destroyed when we get out of DispatchEvent. */
- for (i = 0; i < number; i++)
- {
- Widget child = children [i];
- if (!child->core.being_destroyed)
- {
- XtUnmanageChild (child);
- XtDestroyWidget (child);
- }
- }
- XtFree (children);
- }
-}
-
-static Boolean
-all_dashes_p (char* s)
-{
- char* t;
- for (t = s; *t; t++)
- if (*t != '-')
- return False;
- return True;
-}
-
-static void
-make_menu_in_widget (widget_instance* instance, Widget widget,
- widget_value* val)
-{
- widget_value* cur;
- Widget button;
- Arg al [256];
- int ac;
- String label;
-
- for (cur = val; cur; cur = cur->next)
- {
- ac = 0;
- XtSetArg (al [ac], XtNsensitive, cur->enabled); ac++;
- XtSetArg (al [ac], XtNuserData, instance); ac++;
- XtSetArg (al [ac], XtNacceleratorText, cur->key); ac++;
-
-/* label = (char *) resource_string (widget, cur->name);*/
- label = cur->name;
- if (label)
- {
- XtSetArg (al [ac], XtNlabel, label); ac++;
- }
-
- if (all_dashes_p (cur->name))
- {
- /* no separator in OpenLook just make some space. */
- XtSetArg (al [ac], XtNheight, 5); ac++;
- XtSetArg (al [ac], XtNwidth, 5); ac++;
- button = XtCreateWidget (cur->name, stubWidgetClass, widget, al, ac);
- }
- else if (!cur->contents)
- {
- if (!cur->call_data)
- button =
- XtCreateManagedWidget (cur->name, staticTextWidgetClass, widget,
- al, ac);
- else
- {
- button =
- XtCreateManagedWidget (cur->name, oblongButtonWidgetClass,
- widget, al, ac);
- XtAddCallback (button, XtNselect, pick_hook, cur);
- }
- }
- else
- {
- Widget menu = NULL;
- button =
- XtCreateManagedWidget (cur->name, menuButtonWidgetClass, widget,
- al, ac);
- XtVaGetValues (button, XtNmenuPane, &menu, 0);
- if (!menu)
- abort ();
- make_menu_in_widget (instance, menu, cur->contents);
- OlAddCallback (button, XtNconsumeEvent, pre_hook, instance);
- }
- }
-}
-
-static void
-update_one_menu_entry (widget_instance* instance, Widget widget,
- widget_value* val)
-{
- Arg al [256];
- int ac;
- Widget menu;
- widget_value* contents;
-
- if (val->change == NO_CHANGE)
- return;
-
- /* update the sensitivity */
- XtVaSetValues (widget, XtNsensitive, val->enabled, 0);
-
- /* update the pulldown/pullaside as needed */
- ac = 0;
- menu = NULL;
- XtVaGetValues (widget, XtNmenuPane, &menu, 0);
- contents = val->contents;
-
- if (!menu)
- {
- if (contents)
- {
- /* in OLIT this would have to be a structural change on the
- button. */
- abort ();
- }
- }
- else if (!contents)
- {
- /* in OLIT this would have to be a structural change on the button. */
- abort ();
- }
- else if (contents->change != NO_CHANGE)
- update_menu_widget (instance, menu, val);
-}
-
-static void
-update_menu_widget (widget_instance* instance, Widget widget,
- widget_value* val)
-
-{
- if (val->change == STRUCTURAL_CHANGE
- || val->contents->change == STRUCTURAL_CHANGE)
- {
- destroy_all_children (widget);
- make_menu_in_widget (instance, widget, val->contents);
- }
- else
- {
- /* Update all the buttons of the composite widget in order. */
- Widget* children;
- unsigned int num_children;
- int i;
- widget_value* cur;
-
- children = (Widget *) XtCompositeChildren (widget, &num_children);
- if (children)
- {
- for (i = 0, cur = val->contents; i < num_children; i++)
- {
- if (!cur)
- abort ();
- if (children [i]->core.being_destroyed
- || strcmp (XtName (children [i]), cur->name))
- continue;
- update_one_menu_entry (instance, children [i], cur);
- cur = cur->next;
- }
- XtFree (children);
- }
- if (cur)
- abort ();
- }
-}
-
-void
-xol_update_one_widget (widget_instance* instance, Widget widget,
- widget_value* val, Boolean deep_p)
-{
- Widget menu = widget;
-
- if (XtIsShell (widget))
- XtVaGetValues (widget, XtNmenuPane, &menu, 0);
-
- update_menu_widget (instance, menu, val);
-}
-
-void
-xol_update_one_value (widget_instance* instance, Widget widget,
- widget_value* val)
-{
- return;
-}
-
-void
-xol_pop_instance (widget_instance* instance, Boolean up)
-{
-}
-
-void
-xol_popup_menu (Widget widget)
-{
- OlMenuPost (widget);
-}
-
- /* Destruction of instances */
-void
-xol_destroy_instance (widget_instance* instance)
-{
- XtDestroyWidget (instance->widget);
-}
-
diff --git a/lwlib/lwlib-Xol.h b/lwlib/lwlib-Xol.h
deleted file mode 100644
index 3bf8d11e9e3..00000000000
--- a/lwlib/lwlib-Xol.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef LWLIB_XOL_H
-#define LWLIB_XOL_H
-
-#include "lwlib-int.h"
-
-extern widget_creation_entry xol_creation_table [];
-extern Widget xol_create_dialog (widget_instance *);
-
-Boolean
-lw_olit_widget_p (Widget widget);
-
-void
-xol_update_one_widget (widget_instance* instance, Widget widget,
- widget_value* val, Boolean deep_p);
-
-void
-xol_update_one_value (widget_instance* instance, Widget widget,
- widget_value* val);
-
-void
-xol_destroy_instance (widget_instance* instance);
-
-void
-xol_pop_instance (widget_instance* instance, Boolean up);
-
-void
-xol_popup_menu (Widget widget);
-
-#endif /* LWLIB_XOL_H */
diff --git a/lwlib/lwlib-Xolmb.c b/lwlib/lwlib-Xolmb.c
deleted file mode 100644
index a49e8ab5405..00000000000
--- a/lwlib/lwlib-Xolmb.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/* An OLIT menubar widget, by Chuck Thompson <cthomp@cs.uiuc.edu>
- Copyright (C) 1993 Lucid, Inc.
-
-This file is part of the Lucid Widget Library.
-
-The Lucid Widget Library is free software; you can 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.
-
-The Lucid Widget Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include <X11/IntrinsicP.h>
-#include <X11/Intrinsic.h>
-#include <X11/CompositeP.h>
-#include <X11/Composite.h>
-#include "lwlib-Xol-mbP.h"
-#include "lwlib-Xol-mb.h"
-
-#define HORIZ_SPACING 4
-#define VERT_SPACING 4
-
-static void Initialize();
-static void Resize();
-static void ChangeManaged();
-static Boolean SetValues();
-static XtGeometryResult GeometryManager();
-static XtGeometryResult PreferredSize();
-static void do_layout();
-static XtGeometryResult try_layout();
-
-lwMenuBarClassRec lwMenubarClassRec =
-{
- {
- /* core_class members */
-
- (WidgetClass) &compositeClassRec, /* superclass */
- "Menubar", /* class_name */
- sizeof(lwMenuBarRec), /* widget_size */
- NULL, /* class_initialize */
- NULL, /* class_part_initialize */
- FALSE, /* class_inited */
- Initialize, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- NULL, /* resources */
- 0, /* num_resources */
- NULLQUARK, /* xrm_class */
- TRUE, /* compress_motion */
- XtExposeCompressMaximal, /* compress_exposure */
- TRUE, /* compress_enterleave */
- FALSE, /* visible_interest */
- NULL, /* destroy */
- Resize, /* resize */
- NULL, /* expose */
- NULL, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- PreferredSize, /* query_geometry */
- NULL, /* display_accelerator */
- NULL, /* extension */
- },
- {
- /* composite_class members */
-
- GeometryManager, /* geometry_manager */
- ChangeManaged, /* change_managed */
- XtInheritInsertChild, /* insert_child */
- XtInheritDeleteChild, /* delete_child */
- NULL, /* extension */
- },
- {
- /* Menubar class members */
-
- 0, /* empty */
- }
-};
-WidgetClass lwMenubarWidgetClass = (WidgetClass) &lwMenubarClassRec;
-
-
-static void Initialize (request, new)
- lwMenuBarWidget request, new;
-{
- if (request->core.width <= 0)
- new->core.width = 1;
- if (request->core.height <= 0)
- new->core.height = 23;
-}
-
-static void
-Resize (w)
- lwMenuBarWidget w;
-{
- do_layout(w);
-}
-
-static void
-do_layout (parent)
- lwMenuBarWidget parent;
-{
- Widget child;
- int cnt;
- int managed_children = 0;
- int managed_width = 0;
- int new_pos = 0;
-
- /*
- * Determine number of children which will fit on one line.
- * For now we ignore the rest, making sure they are unmanaged.
- */
-
- cnt = 0;
- while ((cnt < (int) parent->composite.num_children) &&
- (managed_width < (int) parent->core.width))
- {
- child = parent->composite.children[cnt++];
- managed_children++;
- managed_width += child->core.width + child->core.border_width * 2 +
- HORIZ_SPACING;
- }
-
- if (managed_width > (int) parent->core.width)
- managed_children--;
-
- /*
- * Correct positioning of children.
- */
-
- cnt = 0;
- while (managed_children)
- {
- child = parent->composite.children[cnt++];
-
- if (!child->core.managed)
- XtManageChild (child);
-
- if ((child->core.x != new_pos) || (child->core.y != 0))
- XtMoveWidget (child, new_pos, 0);
- new_pos += child->core.width + child->core.border_width * 2 +
- HORIZ_SPACING;
-
- managed_children--;
- }
-
- /*
- * Make sure all remaining children are unmanaged.
- */
-
- while (cnt < parent->composite.num_children)
- {
- child = parent->composite.children[cnt];
-
- if (child->core.managed)
- XtUnmanageChild (child);
-
- if ((child->core.x != parent->core.width) ||
- (child->core.y != parent->core.height))
- XtMoveWidget (child, parent->core.width, parent->core.height);
-
- cnt++;
- }
-}
-
-
-static XtGeometryResult
-PreferredSize (w, request, preferred)
- lwMenuBarWidget w;
- XtWidgetGeometry *request, *preferred;
-{
- Widget child;
- int cnt;
-
- /*
- * If no changes are being made to the width or height, just agree.
- */
-
- if (!(request->request_mode & CWWidth) &&
- !(request->request_mode & CWHeight))
- return (XtGeometryYes);
-
- /*
- * Right now assume everything goes in one row. Calculate the
- * minimum required width and height.
- */
-
- preferred->width = 0;
- preferred->height = 0;
-
- for (cnt = 0; cnt < w->composite.num_children; cnt++)
- {
- child = w->composite.children[cnt];
- if (child->core.managed)
- {
- preferred->width += child->core.width + child->core.border_width*2 +
- HORIZ_SPACING;
- if (preferred->height < (Dimension) (child->core.height +
- child->core.border_width * 2))
- preferred->height = child->core.height +
- child->core.border_width * 2;
- }
- }
-
- preferred->request_mode = CWWidth | CWHeight;
-
- /*
- * Case: both height and width requested
- */
-
- if ((request->request_mode & CWWidth) &&
- (request->request_mode & CWHeight))
- {
- /*
- * Ok if same or bigger.
- */
-
- if (preferred->width <= request->width &&
- preferred->height <= request->height)
- {
- preferred->width = request->width;
- return (XtGeometryYes);
- }
-
- /*
- * If both dimensions are too small, say no.
- */
-
- else
- if (preferred->width > request->width &&
- preferred->height > request->height)
- return (XtGeometryNo);
-
- /*
- * Otherwise one must be right, so say almost.
- */
-
- else
- return (XtGeometryAlmost);
- }
-
- /*
- * If only one dimension is requested, either its OK or it isn't.
- */
-
- else
- {
- if (request->request_mode & CWWidth)
- {
- if (preferred->width <= request->width)
- {
- preferred->width = request->width;
- return (XtGeometryYes);
- }
- else
- return (XtGeometryNo);
- }
- else if (request->request_mode & CWHeight)
- {
- if (preferred->height <= request->height)
- {
- return (XtGeometryYes);
- }
- else
- return (XtGeometryNo);
- }
-
- return (XtGeometryYes);
- }
-}
-
-
-static XtGeometryResult
-GeometryManager (w, request, reply)
- Widget w;
- XtWidgetGeometry *request;
- XtWidgetGeometry *reply;
-{
-
- lwMenuBarWidget parent = (lwMenuBarWidget) w->core.parent;
-
- /*
- * If the widget wants to move, just say no.
- */
-
- if ((request->request_mode & CWX && request->x != w->core.x) ||
- (request->request_mode & CWY && request->y != w->core.y))
- return (XtGeometryNo);
-
- /*
- * Since everything "fits" for now, grant all requests.
- */
-
- if (request->request_mode & CWWidth)
- w->core.width = request->width;
- if (request->request_mode & CWHeight)
- w->core.height = request->height;
- if (request->request_mode & CWBorderWidth)
- w->core.border_width = request->border_width;
-
- do_layout (parent);
- return (XtGeometryYes);
-}
-
-
-static XtGeometryResult
-try_layout (parent)
- lwMenuBarWidget parent;
-{
- Widget child;
- int cnt;
- int managed_children = 0;
- int managed_width = 0;
- int new_pos = 0;
-
- /*
- * Determine number of children which will fit on one line.
- * For now we ignore the rest, making sure they are unmanaged.
- */
-
- cnt = 0;
- while ((cnt < (int) parent->composite.num_children) &&
- (managed_width < (int) parent->core.width))
- {
- child = parent->composite.children[cnt++];
- if (child->core.managed)
- {
- managed_children++;
- managed_width += child->core.width + child->core.border_width * 2 +
- HORIZ_SPACING;
- }
- }
-
- if (managed_width > (int) parent->core.width)
- return (XtGeometryNo);
- else
- return (XtGeometryYes);
-}
-
-
-
-static void
-ChangeManaged (w)
- lwMenuBarWidget w;
-{
- XtGeometryResult result;
-
- result = try_layout (w);
-
- if (result != XtGeometryYes)
- {
- XtUnmanageChild (w->composite.children[w->composite.num_children - 1]);
- XtMoveWidget (w->composite.children[w->composite.num_children-1],
- w->core.width, w->core.height);
- }
-
- do_layout (w);
-}
diff --git a/lwlib/lwlib-Xolmb.h b/lwlib/lwlib-Xolmb.h
deleted file mode 100644
index d2ce13b3ecb..00000000000
--- a/lwlib/lwlib-Xolmb.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* An OLIT menubar widget, by Chuck Thompson <cthomp@cs.uiuc.edu>
- Copyright (C) 1993 Lucid, Inc.
-
-This file is part of the Lucid Widget Library.
-
-The Lucid Widget Library is free software; you can 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.
-
-The Lucid Widget Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifndef LW_MENUBAR_H
-#define LW_MENUBAR_H
-extern WidgetClass lwMenubarWidgetClass;
-typedef struct _lwMenuBarClassRec *lwMenuBarWidgetClass;
-typedef struct _lwMenuBarRec *lwMenuBarWidget;
-#endif /* LW_MENUBAR_H */
diff --git a/lwlib/lwlib-XolmbP.h b/lwlib/lwlib-XolmbP.h
deleted file mode 100644
index 84267dbc6b8..00000000000
--- a/lwlib/lwlib-XolmbP.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* An OLIT menubar widget, by Chuck Thompson <cthomp@cs.uiuc.edu>
- Copyright (C) 1993 Lucid, Inc.
-
-This file is part of the Lucid Widget Library.
-
-The Lucid Widget Library is free software; you can 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.
-
-The Lucid Widget Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifndef LW_MENUBARP_H
-#define LW_MENUBARP_H
-
-typedef struct _lwMenuBarClassPart
-{
- int ignore;
-} lwMenuBarClassPart;
-
-typedef struct _lwMenuBarClassRec
-{
- CoreClassPart core_class;
- CompositeClassPart composite_class;
- lwMenuBarClassPart menubar_class;
-} lwMenuBarClassRec;
-
-extern lwMenuBarClassRec lwMenubarClassRec;
-
-typedef struct
-{
- int empty;
-} lwMenuBarPart;
-
-typedef struct _lwMenuBarRec
-{
- CorePart core;
- CompositePart composite;
- lwMenuBarPart menubar;
-} lwMenuBarRec;
-
-#endif /* LW_MENUBARP_H */
diff --git a/lwlib/lwlib-int.h b/lwlib/lwlib-int.h
deleted file mode 100644
index 3649a241738..00000000000
--- a/lwlib/lwlib-int.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef LWLIB_INTERNAL_H
-#define LWLIB_INTERNAL_H
-
-#include "lwlib.h"
-
-/*
-extern char *strdup (const char *);
-extern int strcasecmp (const char *, const char *);
-*/
-extern char *safe_strdup ();
-
-typedef struct _widget_instance
-{
- Widget widget;
- Widget parent;
- Boolean pop_up_p;
- struct _widget_info* info;
- struct _widget_instance* next;
-} widget_instance;
-
-typedef struct _widget_info
-{
- char* type;
- char* name;
- LWLIB_ID id;
- widget_value* val;
- Boolean busy;
- lw_callback pre_activate_cb;
- lw_callback selection_cb;
- lw_callback post_activate_cb;
- struct _widget_instance* instances;
- struct _widget_info* next;
-} widget_info;
-
-typedef Widget
-(*widget_creation_function) ();
-
-typedef struct _widget_creation_entry
-{
- char* type;
- widget_creation_function function;
-} widget_creation_entry;
-
-/* update all other instances of a widget. Can be used in a callback when
- a widget has been used by the user */
-void
-lw_internal_update_other_instances ();
-
-/* get the widget_value for a widget in a given instance */
-widget_value*
-lw_get_widget_value_for_widget ();
-
-widget_info *lw_get_widget_info ();
-
-#endif /* LWLIB_INTERNAL_H */
diff --git a/lwlib/lwlib-utils.c b/lwlib/lwlib-utils.c
deleted file mode 100644
index cd7c9c540f2..00000000000
--- a/lwlib/lwlib-utils.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/* Defines some widget utility functions.
- Copyright (C) 1992 Lucid, Inc.
-
-This file is part of the Lucid Widget Library.
-
-The Lucid Widget Library is free software; you can 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.
-
-The Lucid Widget Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-/* Definitions of these in config.h can cause
- declaration conflicts later on between declarations for index
- and declarations for strchr. This file doesn't use
- index and rindex, so cancel them. */
-#undef index
-#undef rindex
-
-#include <X11/Xatom.h>
-#include <X11/IntrinsicP.h>
-#include <X11/ObjectP.h>
-#include "lwlib-utils.h"
-
-/* Redisplay the contents of the widget, without first clearing it. */
-void
-XtNoClearRefreshWidget (widget)
- Widget widget;
-{
- XEvent event;
-
- event.type = Expose;
- event.xexpose.serial = 0;
- event.xexpose.send_event = 0;
- event.xexpose.display = XtDisplay (widget);
- event.xexpose.window = XtWindow (widget);
- event.xexpose.x = 0;
- event.xexpose.y = 0;
- event.xexpose.width = widget->core.width;
- event.xexpose.height = widget->core.height;
- event.xexpose.count = 0;
-
- (*widget->core.widget_class->core_class.expose)
- (widget, &event, (Region)NULL);
-}
-
-
-/*
- * Apply a function to all the subwidgets of a given widget recursively.
-*/
-void
-XtApplyToWidgets (w, proc, arg)
- Widget w;
- XtApplyToWidgetsProc proc;
- XtPointer arg;
-{
- if (XtIsComposite (w))
- {
- CompositeWidget cw = (CompositeWidget) w;
- /* We have to copy the children list before mapping over it, because
- the procedure might add/delete elements, which would lose badly.
- */
- int nkids = cw->composite.num_children;
- Widget *kids = (Widget *) malloc (sizeof (Widget) * nkids);
- int i;
- lwlib_bcopy (cw->composite.children, kids, sizeof (Widget) * nkids);
- for (i = 0; i < nkids; i++)
-/* This prevent us from using gadgets, why is it here? */
-/* if (XtIsWidget (kids [i])) */
- {
- /* do the kiddies first in case we're destroying */
- XtApplyToWidgets (kids [i], proc, arg);
- proc (kids [i], arg);
- }
- free (kids);
- }
-}
-
-
-/*
- * Apply a function to all the subwidgets of a given widget recursively.
- * Stop as soon as the function returns non NULL and returns this as a value.
- */
-void *
-XtApplyUntilToWidgets (w, proc, arg)
- Widget w;
- XtApplyUntilToWidgetsProc proc;
- XtPointer arg;
-{
- void* result;
- if (XtIsComposite (w))
- {
- CompositeWidget cw = (CompositeWidget)w;
- int i;
- for (i = 0; i < cw->composite.num_children; i++)
- if (XtIsWidget (cw->composite.children [i])){
- result = proc (cw->composite.children [i], arg);
- if (result)
- return result;
- result = XtApplyUntilToWidgets (cw->composite.children [i], proc,
- arg);
- if (result)
- return result;
- }
- }
- return NULL;
-}
-
-
-/*
- * Returns a copy of the list of all children of a composite widget
- */
-Widget *
-XtCompositeChildren (widget, number)
- Widget widget;
- unsigned int* number;
-{
- CompositeWidget cw = (CompositeWidget)widget;
- Widget* result;
- int n;
- int i;
-
- if (!XtIsComposite (widget))
- {
- *number = 0;
- return NULL;
- }
- n = cw->composite.num_children;
- result = (Widget*)XtMalloc (n * sizeof (Widget));
- *number = n;
- for (i = 0; i < n; i++)
- result [i] = cw->composite.children [i];
- return result;
-}
-
-Boolean
-XtWidgetBeingDestroyedP (widget)
- Widget widget;
-{
- return widget->core.being_destroyed;
-}
-
-void
-XtSafelyDestroyWidget (widget)
- Widget widget;
-{
-#if 0
-
- /* this requires IntrinsicI.h (actually, InitialI.h) */
-
- XtAppContext app = XtWidgetToApplicationContext(widget);
-
- if (app->dispatch_level == 0)
- {
- app->dispatch_level = 1;
- XtDestroyWidget (widget);
- /* generates an event so that the event loop will be called */
- XChangeProperty (XtDisplay (widget), XtWindow (widget),
- XA_STRING, XA_STRING, 32, PropModeAppend, NULL, 0);
- app->dispatch_level = 0;
- }
- else
- XtDestroyWidget (widget);
-
-#else
- abort ();
-#endif
-}
diff --git a/lwlib/lwlib-utils.h b/lwlib/lwlib-utils.h
deleted file mode 100644
index 020d2a982dc..00000000000
--- a/lwlib/lwlib-utils.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _LWLIB_UTILS_H_
-#define _LWLIB_UTILS_H_
-
-void XtNoClearRefreshWidget (/* Widget */);
-
-typedef void (*XtApplyToWidgetsProc) (/* Widget, XtPointer */);
-typedef void* (*XtApplyUntilToWidgetsProc) (/* Widget, XtPointer */);
-
-void XtApplyToWidgets (/* Widget, XtApplyToWidgetsProc, XtPointer */);
-void *XtApplyUntilToWidgets (/* Widget, XtApplyUntilToWidgetsProc, XtPointer */);
-
-Widget *XtCompositeChildren (/* Widget, unsigned int * */);
-
-/* returns True is the widget is being destroyed, False otherwise */
-Boolean
-XtWidgetBeingDestroyedP (/* Widget widget */);
-
-void XtSafelyDestroyWidget (/* Widget */);
-
-#endif /* _LWLIB_UTILS_H_ */
diff --git a/lwlib/lwlib.c b/lwlib/lwlib.c
deleted file mode 100644
index 981c92e5686..00000000000
--- a/lwlib/lwlib.c
+++ /dev/null
@@ -1,1386 +0,0 @@
-/* A general interface to the widgets of different toolkits.
- Copyright (C) 1992, 1993 Lucid, Inc.
-
-This file is part of the Lucid Widget Library.
-
-The Lucid Widget Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-The Lucid Widget Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifdef NeXT
-#undef __STRICT_BSD__ /* ick */
-#endif
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <ctype.h>
-#include "lwlib-int.h"
-#include "lwlib-utils.h"
-#include <X11/StringDefs.h>
-
-#ifdef __osf__
-#include <string.h>
-#include <stdlib.h>
-extern long *xmalloc();
-#endif
-
-#if defined (USE_LUCID)
-#include "lwlib-Xlw.h"
-#endif
-#if defined (USE_MOTIF)
-#include "lwlib-Xm.h"
-#else /* not USE_MOTIF */
-#if defined (USE_LUCID)
-#define USE_XAW
-#endif /* not USE_MOTIF && USE_LUCID */
-#endif
-#if defined (USE_OLIT)
-#include "lwlib-Xol.h"
-#endif
-#if defined (USE_XAW)
-#include "lwlib-Xaw.h"
-#endif
-
-#if !defined (USE_LUCID) && !defined (USE_MOTIF) && !defined (USE_OLIT)
-ERROR! At least one of USE_LUCID, USE_MOTIF or USE_OLIT must be defined.
-#endif
-
-#if defined (USE_MOTIF) && defined (USE_OLIT)
-ERROR! no more than one of USE_MOTIF and USE_OLIT may be defined.
-#endif
-
-#ifndef max
-#define max(x, y) ((x) > (y) ? (x) : (y))
-#endif
-
-/* List of all widgets managed by the library. */
-static widget_info*
-all_widget_info = NULL;
-
-#ifdef USE_MOTIF
-char *lwlib_toolkit_type = "motif";
-#else
-char *lwlib_toolkit_type = "lucid";
-#endif
- /* Forward declarations */
-static void
-instantiate_widget_instance (/* widget_instance* instance */);
-
-lwlib_memset (address, value, length)
- char *address;
- int value;
- int length;
-{
- int i;
-
- for (i = 0; i < length; i++)
- address[i] = value;
-}
-
-lwlib_bcopy (from, to, length)
- char *from;
- char *to;
- int length;
-{
- int i;
-
- for (i = 0; i < length; i++)
- to[i] = from[i];
-}
- /* utility functions for widget_instance and widget_info */
-char *
-safe_strdup (s)
- char *s;
-{
- char *result;
- if (! s) return 0;
- result = (char *) malloc (strlen (s) + 1);
- if (! result)
- return 0;
- strcpy (result, s);
- return result;
-}
-
-/* Like strcmp but ignore differences in case. */
-
-static int
-my_strcasecmp (s1, s2)
- char *s1, *s2;
-{
- while (1)
- {
- int c1 = *s1++;
- int c2 = *s2++;
- if (isupper (c1))
- c1 = tolower (c1);
- if (isupper (c2))
- c2 = tolower (c2);
- if (c1 != c2)
- return (c1 > c2 ? 1 : -1);
- if (c1 == 0)
- return 0;
- }
-}
-
-static void
-safe_free_str (s)
- char *s;
-{
- if (s) free (s);
-}
-
-static widget_value *widget_value_free_list = 0;
-static int malloc_cpt = 0;
-
-widget_value *
-malloc_widget_value ()
-{
- widget_value *wv;
- if (widget_value_free_list)
- {
- wv = widget_value_free_list;
- widget_value_free_list = wv->free_list;
- wv->free_list = 0;
- }
- else
- {
- wv = (widget_value *) malloc (sizeof (widget_value));
- malloc_cpt++;
- }
- lwlib_memset (wv, 0, sizeof (widget_value));
- return wv;
-}
-
-/* this is analogous to free(). It frees only what was allocated
- by malloc_widget_value(), and no substructures.
- */
-void
-free_widget_value (wv)
- widget_value *wv;
-{
- if (wv->free_list)
- abort ();
-
- if (malloc_cpt > 25)
- {
- /* When the number of already allocated cells is too big,
- We free it. */
- free (wv);
- malloc_cpt--;
- }
- else
- {
- wv->free_list = widget_value_free_list;
- widget_value_free_list = wv;
- }
-}
-
-static void
-free_widget_value_tree (wv)
- widget_value *wv;
-{
- if (!wv)
- return;
-
- if (wv->name) free (wv->name);
- if (wv->value) free (wv->value);
- if (wv->key) free (wv->key);
-
- wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
-
- if (wv->toolkit_data && wv->free_toolkit_data)
- {
- XtFree (wv->toolkit_data);
- wv->toolkit_data = (void *) 0xDEADBEEF;
- }
-
- if (wv->contents && (wv->contents != (widget_value*)1))
- {
- free_widget_value_tree (wv->contents);
- wv->contents = (widget_value *) 0xDEADBEEF;
- }
- if (wv->next)
- {
- free_widget_value_tree (wv->next);
- wv->next = (widget_value *) 0xDEADBEEF;
- }
- free_widget_value (wv);
-}
-
-static widget_value *
-copy_widget_value_tree (val, change)
- widget_value* val;
- change_type change;
-{
- widget_value* copy;
-
- if (!val)
- return NULL;
- if (val == (widget_value *) 1)
- return val;
-
- copy = malloc_widget_value ();
- copy->name = safe_strdup (val->name);
- copy->value = safe_strdup (val->value);
- copy->key = safe_strdup (val->key);
- copy->enabled = val->enabled;
- copy->selected = val->selected;
- copy->edited = False;
- copy->change = change;
- copy->this_one_change = change;
- copy->contents = copy_widget_value_tree (val->contents, change);
- copy->call_data = val->call_data;
- copy->next = copy_widget_value_tree (val->next, change);
- copy->toolkit_data = NULL;
- copy->free_toolkit_data = False;
- return copy;
-}
-
-static widget_info *
-allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
- char* type;
- char* name;
- LWLIB_ID id;
- widget_value* val;
- lw_callback pre_activate_cb;
- lw_callback selection_cb;
- lw_callback post_activate_cb;
-{
- widget_info* info = (widget_info*)malloc (sizeof (widget_info));
- info->type = safe_strdup (type);
- info->name = safe_strdup (name);
- info->id = id;
- info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
- info->busy = False;
- info->pre_activate_cb = pre_activate_cb;
- info->selection_cb = selection_cb;
- info->post_activate_cb = post_activate_cb;
- info->instances = NULL;
-
- info->next = all_widget_info;
- all_widget_info = info;
-
- return info;
-}
-
-static void
-free_widget_info (info)
- widget_info* info;
-{
- safe_free_str (info->type);
- safe_free_str (info->name);
- free_widget_value_tree (info->val);
- lwlib_memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
- free (info);
-}
-
-static void
-mark_widget_destroyed (widget, closure, call_data)
- Widget widget;
- XtPointer closure;
- XtPointer call_data;
-{
- widget_instance* instance = (widget_instance*)closure;
-
- /* be very conservative */
- if (instance->widget == widget)
- instance->widget = NULL;
-}
-
-static widget_instance *
-allocate_widget_instance (info, parent, pop_up_p)
- widget_info* info;
- Widget parent;
- Boolean pop_up_p;
-{
- widget_instance* instance =
- (widget_instance*)malloc (sizeof (widget_instance));
- instance->parent = parent;
- instance->pop_up_p = pop_up_p;
- instance->info = info;
- instance->next = info->instances;
- info->instances = instance;
-
- instantiate_widget_instance (instance);
-
- XtAddCallback (instance->widget, XtNdestroyCallback,
- mark_widget_destroyed, (XtPointer)instance);
- return instance;
-}
-
-static void
-free_widget_instance (instance)
- widget_instance* instance;
-{
- lwlib_memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
- free (instance);
-}
-
-static widget_info *
-get_widget_info (id, remove_p)
- LWLIB_ID id;
- Boolean remove_p;
-{
- widget_info* info;
- widget_info* prev;
- for (prev = NULL, info = all_widget_info;
- info;
- prev = info, info = info->next)
- if (info->id == id)
- {
- if (remove_p)
- {
- if (prev)
- prev->next = info->next;
- else
- all_widget_info = info->next;
- }
- return info;
- }
- return NULL;
-}
-
-/* Internal function used by the library dependent implementation to get the
- widget_value for a given widget in an instance */
-widget_info *
-lw_get_widget_info (id)
- LWLIB_ID id;
-{
- return get_widget_info (id, 0);
-}
-
-static widget_instance *
-get_widget_instance (widget, remove_p)
- Widget widget;
- Boolean remove_p;
-{
- widget_info* info;
- widget_instance* instance;
- widget_instance* prev;
- for (info = all_widget_info; info; info = info->next)
- for (prev = NULL, instance = info->instances;
- instance;
- prev = instance, instance = instance->next)
- if (instance->widget == widget)
- {
- if (remove_p)
- {
- if (prev)
- prev->next = instance->next;
- else
- info->instances = instance->next;
- }
- return instance;
- }
- return (widget_instance *) 0;
-}
-
-static widget_instance*
-find_instance (id, parent, pop_up_p)
- LWLIB_ID id;
- Widget parent;
- Boolean pop_up_p;
-{
- widget_info* info = get_widget_info (id, False);
- widget_instance* instance;
-
- if (info)
- for (instance = info->instances; instance; instance = instance->next)
- if (instance->parent == parent && instance->pop_up_p == pop_up_p)
- return instance;
-
- return NULL;
-}
-
-
-/* utility function for widget_value */
-static Boolean
-safe_strcmp (s1, s2)
- char* s1;
- char* s2;
-{
- if (!!s1 ^ !!s2) return True;
- return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
-}
-
-
-#if 0
-# define EXPLAIN(name, oc, nc, desc, a1, a2) \
- printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
- name, \
- (oc == NO_CHANGE ? "none" : \
- (oc == INVISIBLE_CHANGE ? "invisible" : \
- (oc == VISIBLE_CHANGE ? "visible" : \
- (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
- oc, \
- (nc == NO_CHANGE ? "none" : \
- (nc == INVISIBLE_CHANGE ? "invisible" : \
- (nc == VISIBLE_CHANGE ? "visible" : \
- (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
- nc, desc, a1, a2)
-#else
-# define EXPLAIN(name, oc, nc, desc, a1, a2)
-#endif
-
-
-static widget_value *
-merge_widget_value (val1, val2, level)
- widget_value* val1;
- widget_value* val2;
- int level;
-{
- change_type change, this_one_change;
- widget_value* merged_next;
- widget_value* merged_contents;
-
- if (!val1)
- {
- if (val2)
- return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
- else
- return NULL;
- }
- if (!val2)
- {
- free_widget_value_tree (val1);
- return NULL;
- }
-
- change = NO_CHANGE;
-
- if (safe_strcmp (val1->name, val2->name))
- {
- EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
- val1->name, val2->name);
- change = max (change, STRUCTURAL_CHANGE);
- safe_free_str (val1->name);
- val1->name = safe_strdup (val2->name);
- }
- if (safe_strcmp (val1->value, val2->value))
- {
- EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
- val1->value, val2->value);
- change = max (change, VISIBLE_CHANGE);
- safe_free_str (val1->value);
- val1->value = safe_strdup (val2->value);
- }
- if (safe_strcmp (val1->key, val2->key))
- {
- EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
- val1->key, val2->key);
- change = max (change, VISIBLE_CHANGE);
- safe_free_str (val1->key);
- val1->key = safe_strdup (val2->key);
- }
- if (val1->enabled != val2->enabled)
- {
- EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
- val1->enabled, val2->enabled);
- change = max (change, VISIBLE_CHANGE);
- val1->enabled = val2->enabled;
- }
- if (val1->selected != val2->selected)
- {
- EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
- val1->selected, val2->selected);
- change = max (change, VISIBLE_CHANGE);
- val1->selected = val2->selected;
- }
- if (val1->call_data != val2->call_data)
- {
- EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
- val1->call_data, val2->call_data);
- change = max (change, INVISIBLE_CHANGE);
- val1->call_data = val2->call_data;
- }
-
- if (level > 0)
- {
- merged_contents =
- merge_widget_value (val1->contents, val2->contents, level - 1);
-
- if (val1->contents && !merged_contents)
- {
- /* This used to say INVISIBLE_CHANGE,
- but it is visible and vitally important when
- the contents of the menu bar itself are entirely deleted.
-
- But maybe it doesn't matter. This fails to fix the bug. */
- EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(contents gone)",
- 0, 0);
- change = max (change, STRUCTURAL_CHANGE);
- }
- else if (merged_contents && merged_contents->change != NO_CHANGE)
- {
- EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
- 0, 0);
- change = max (change, INVISIBLE_CHANGE);
-#if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
-#ifdef USE_MOTIF
- change = max (merged_contents->change, change);
-#endif
-#endif
- }
-
- val1->contents = merged_contents;
- }
-
- this_one_change = change;
-
- merged_next = merge_widget_value (val1->next, val2->next, level);
-
- if (val1->next && !merged_next)
- {
- EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
- 0, 0);
- change = max (change, STRUCTURAL_CHANGE);
- }
- else if (merged_next)
- {
- if (merged_next->change)
- EXPLAIN (val1->name, change, merged_next->change, "(following change)",
- 0, 0);
- change = max (change, merged_next->change);
- }
-
- val1->next = merged_next;
-
- val1->this_one_change = this_one_change;
- val1->change = change;
-
- if (change > NO_CHANGE && val1->toolkit_data)
- {
- if (val1->free_toolkit_data)
- XtFree (val1->toolkit_data);
- val1->toolkit_data = NULL;
- }
-
- return val1;
-}
-
-
-/* modifying the widgets */
-static Widget
-name_to_widget (instance, name)
- widget_instance* instance;
- char* name;
-{
- Widget widget = NULL;
-
- if (!instance->widget)
- return NULL;
-
- if (!strcmp (XtName (instance->widget), name))
- widget = instance->widget;
- else
- {
- int length = strlen (name) + 2;
- char* real_name = (char *) xmalloc (length);
- real_name [0] = '*';
- strcpy (real_name + 1, name);
-
- widget = XtNameToWidget (instance->widget, real_name);
-
- free (real_name);
- }
- return widget;
-}
-
-static void
-set_one_value (instance, val, deep_p)
- widget_instance* instance;
- widget_value* val;
- Boolean deep_p;
-{
- Widget widget = name_to_widget (instance, val->name);
-
- if (widget)
- {
-#if defined (USE_LUCID)
- if (lw_lucid_widget_p (instance->widget))
- xlw_update_one_widget (instance, widget, val, deep_p);
-#endif
-#if defined (USE_MOTIF)
- if (lw_motif_widget_p (instance->widget))
- xm_update_one_widget (instance, widget, val, deep_p);
-#endif
-#if defined (USE_OLIT)
- if (lw_olit_widget_p (instance->widget))
- xol_update_one_widget (instance, widget, val, deep_p);
-#endif
-#if defined (USE_XAW)
- if (lw_xaw_widget_p (instance->widget))
- xaw_update_one_widget (instance, widget, val, deep_p);
-#endif
- }
-}
-
-static void
-update_one_widget_instance (instance, deep_p)
- widget_instance* instance;
- Boolean deep_p;
-{
- widget_value *val;
-
- if (!instance->widget)
- /* the widget was destroyed */
- return;
-
- for (val = instance->info->val; val; val = val->next)
- if (val->change != NO_CHANGE)
- set_one_value (instance, val, deep_p);
-}
-
-static void
-update_all_widget_values (info, deep_p)
- widget_info* info;
- Boolean deep_p;
-{
- widget_instance* instance;
- widget_value* val;
-
- for (instance = info->instances; instance; instance = instance->next)
- update_one_widget_instance (instance, deep_p);
-
- for (val = info->val; val; val = val->next)
- val->change = NO_CHANGE;
-}
-
-void
-lw_modify_all_widgets (id, val, deep_p)
- LWLIB_ID id;
- widget_value* val;
- Boolean deep_p;
-{
- widget_info* info = get_widget_info (id, False);
- widget_value* new_val;
- widget_value* next_new_val;
- widget_value* cur;
- widget_value* prev;
- widget_value* next;
- int found;
-
- if (!info)
- return;
-
- for (new_val = val; new_val; new_val = new_val->next)
- {
- next_new_val = new_val->next;
- new_val->next = NULL;
- found = False;
- for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
- if (!strcmp (cur->name, new_val->name))
- {
- found = True;
- next = cur->next;
- cur->next = NULL;
- cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
- if (prev)
- prev->next = cur ? cur : next;
- else
- info->val = cur ? cur : next;
- if (cur)
- cur->next = next;
- break;
- }
- if (!found)
- {
- /* Could not find it, add it */
- if (prev)
- prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
- else
- info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
- }
- new_val->next = next_new_val;
- }
-
- update_all_widget_values (info, deep_p);
-}
-
-
-/* creating the widgets */
-
-static void
-initialize_widget_instance (instance)
- widget_instance* instance;
-{
- widget_value* val;
-
- for (val = instance->info->val; val; val = val->next)
- val->change = STRUCTURAL_CHANGE;
-
- update_one_widget_instance (instance, True);
-
- for (val = instance->info->val; val; val = val->next)
- val->change = NO_CHANGE;
-}
-
-
-static widget_creation_function
-find_in_table (type, table)
- char* type;
- widget_creation_entry* table;
-{
- widget_creation_entry* cur;
- for (cur = table; cur->type; cur++)
- if (!my_strcasecmp (type, cur->type))
- return cur->function;
- return NULL;
-}
-
-static Boolean
-dialog_spec_p (name)
- char* name;
-{
- /* return True if name matches [EILPQeilpq][1-9][Bb] or
- [EILPQeilpq][1-9][Bb][Rr][1-9] */
- if (!name)
- return False;
-
- switch (name [0])
- {
- case 'E': case 'I': case 'L': case 'P': case 'Q':
- case 'e': case 'i': case 'l': case 'p': case 'q':
- if (name [1] >= '0' && name [1] <= '9')
- {
- if (name [2] != 'B' && name [2] != 'b')
- return False;
- if (!name [3])
- return True;
- if ((name [3] == 'T' || name [3] == 't') && !name [4])
- return True;
- if ((name [3] == 'R' || name [3] == 'r')
- && name [4] >= '0' && name [4] <= '9' && !name [5])
- return True;
- return False;
- }
- else
- return False;
-
- default:
- return False;
- }
-}
-
-static void
-instantiate_widget_instance (instance)
- widget_instance* instance;
-{
- widget_creation_function function = NULL;
-
-#if defined (USE_LUCID)
- if (!function)
- function = find_in_table (instance->info->type, xlw_creation_table);
-#endif
-#if defined(USE_MOTIF)
- if (!function)
- function = find_in_table (instance->info->type, xm_creation_table);
-#endif
-#if defined (USE_OLIT)
- if (!function)
- function = find_in_table (instance->info->type, xol_creation_table);
-#endif
-#if defined (USE_XAW)
- if (!function)
- function = find_in_table (instance->info->type, xaw_creation_table);
-#endif
-
- if (!function)
- {
- if (dialog_spec_p (instance->info->type))
- {
-#if defined (USE_LUCID)
- /* not yet */
-#endif
-#if defined(USE_MOTIF)
- if (!function)
- function = xm_create_dialog;
-#endif
-#if defined (USE_XAW)
- if (!function)
- function = xaw_create_dialog;
-#endif
-#if defined (USE_OLIT)
- /* not yet */
-#endif
- }
- }
-
- if (!function)
- {
- printf ("No creation function for widget type %s\n",
- instance->info->type);
- abort ();
- }
-
- instance->widget = (*function) (instance);
-
- if (!instance->widget)
- abort ();
-
- /* XtRealizeWidget (instance->widget);*/
-}
-
-void
-lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
- char* type;
- char* name;
- LWLIB_ID id;
- widget_value* val;
- lw_callback pre_activate_cb;
- lw_callback selection_cb;
- lw_callback post_activate_cb;
-{
- if (!get_widget_info (id, False))
- allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
- post_activate_cb);
-}
-
-Widget
-lw_get_widget (id, parent, pop_up_p)
- LWLIB_ID id;
- Widget parent;
- Boolean pop_up_p;
-{
- widget_instance* instance;
-
- instance = find_instance (id, parent, pop_up_p);
- return instance ? instance->widget : NULL;
-}
-
-Widget
-lw_make_widget (id, parent, pop_up_p)
- LWLIB_ID id;
- Widget parent;
- Boolean pop_up_p;
-{
- widget_instance* instance;
- widget_info* info;
-
- instance = find_instance (id, parent, pop_up_p);
- if (!instance)
- {
- info = get_widget_info (id, False);
- if (!info)
- return NULL;
- instance = allocate_widget_instance (info, parent, pop_up_p);
- initialize_widget_instance (instance);
- }
- if (!instance->widget)
- abort ();
- return instance->widget;
-}
-
-Widget
-lw_create_widget (type, name, id, val, parent, pop_up_p, pre_activate_cb, selection_cb, post_activate_cb)
- char* type;
- char* name;
- LWLIB_ID id;
- widget_value* val;
- Widget parent;
- Boolean pop_up_p;
- lw_callback pre_activate_cb;
- lw_callback selection_cb;
- lw_callback post_activate_cb;
-{
- lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
- post_activate_cb);
- return lw_make_widget (id, parent, pop_up_p);
-}
-
-
-/* destroying the widgets */
-static void
-destroy_one_instance (instance)
- widget_instance* instance;
-{
- /* Remove the destroy callback on the widget; that callback will try to
- dereference the instance object (to set its widget slot to 0, since the
- widget is dead.) Since the instance is now dead, we don't have to worry
- about the fact that its widget is dead too.
-
- This happens in the Phase2Destroy of the widget, so this callback would
- not have been run until arbitrarily long after the instance was freed.
- */
- if (instance->widget)
- XtRemoveCallback (instance->widget, XtNdestroyCallback,
- mark_widget_destroyed, (XtPointer)instance);
-
- if (instance->widget)
- {
- /* The else are pretty tricky here, including the empty statement
- at the end because it would be very bad to destroy a widget
- twice. */
-#if defined (USE_LUCID)
- if (lw_lucid_widget_p (instance->widget))
- xlw_destroy_instance (instance);
- else
-#endif
-#if defined (USE_MOTIF)
- if (lw_motif_widget_p (instance->widget))
- xm_destroy_instance (instance);
- else
-#endif
-#if defined (USE_OLIT)
- if (lw_olit_widget_p (instance->widget))
- xol_destroy_instance (instance);
- else
-#endif
-#if defined (USE_XAW)
- if (lw_xaw_widget_p (instance->widget))
- xaw_destroy_instance (instance);
- else
-#endif
- /* do not remove the empty statement */
- ;
- }
-
- free_widget_instance (instance);
-}
-
-void
-lw_destroy_widget (w)
- Widget w;
-{
- widget_instance* instance = get_widget_instance (w, True);
-
- if (instance)
- {
- widget_info *info = instance->info;
- /* instance has already been removed from the list; free it */
- destroy_one_instance (instance);
- /* if there are no instances left, free the info too */
- if (!info->instances)
- lw_destroy_all_widgets (info->id);
- }
-}
-
-void
-lw_destroy_all_widgets (id)
- LWLIB_ID id;
-{
- widget_info* info = get_widget_info (id, True);
- widget_instance* instance;
- widget_instance* next;
-
- if (info)
- {
- for (instance = info->instances; instance; )
- {
- next = instance->next;
- destroy_one_instance (instance);
- instance = next;
- }
- free_widget_info (info);
- }
-}
-
-void
-lw_destroy_everything ()
-{
- while (all_widget_info)
- lw_destroy_all_widgets (all_widget_info->id);
-}
-
-void
-lw_destroy_all_pop_ups ()
-{
- widget_info* info;
- widget_info* next;
- widget_instance* instance;
-
- for (info = all_widget_info; info; info = next)
- {
- next = info->next;
- instance = info->instances;
- if (instance && instance->pop_up_p)
- lw_destroy_all_widgets (info->id);
- }
-}
-
-#ifdef USE_MOTIF
-extern Widget first_child (/* Widget */); /* garbage */
-#endif
-
-Widget
-lw_raise_all_pop_up_widgets ()
-{
- widget_info* info;
- widget_instance* instance;
- Widget result = NULL;
-
- for (info = all_widget_info; info; info = info->next)
- for (instance = info->instances; instance; instance = instance->next)
- if (instance->pop_up_p)
- {
- Widget widget = instance->widget;
- if (widget)
- {
- if (XtIsManaged (widget)
-#ifdef USE_MOTIF
- /* What a complete load of crap!!!!
- When a dialogShell is on the screen, it is not managed!
- */
- || (lw_motif_widget_p (instance->widget) &&
- XtIsManaged (first_child (widget)))
-#endif
- )
- {
- if (!result)
- result = widget;
- XMapRaised (XtDisplay (widget), XtWindow (widget));
- }
- }
- }
- return result;
-}
-
-static void
-lw_pop_all_widgets (id, up)
- LWLIB_ID id;
- Boolean up;
-{
- widget_info* info = get_widget_info (id, False);
- widget_instance* instance;
-
- if (info)
- for (instance = info->instances; instance; instance = instance->next)
- if (instance->pop_up_p && instance->widget)
- {
-#if defined (USE_LUCID)
- if (lw_lucid_widget_p (instance->widget))
- {
- XtRealizeWidget (instance->widget);
- xlw_pop_instance (instance, up);
- }
-#endif
-#if defined (USE_MOTIF)
- if (lw_motif_widget_p (instance->widget))
- {
- XtRealizeWidget (instance->widget);
- xm_pop_instance (instance, up);
- }
-#endif
-#if defined (USE_OLIT)
- if (lw_olit_widget_p (instance->widget))
- {
- XtRealizeWidget (instance->widget);
- xol_pop_instance (instance, up);
- }
-#endif
-#if defined (USE_XAW)
- if (lw_xaw_widget_p (instance->widget))
- {
- XtRealizeWidget (XtParent (instance->widget));
- XtRealizeWidget (instance->widget);
- xaw_pop_instance (instance, up);
- }
-#endif
- }
-}
-
-void
-lw_pop_up_all_widgets (id)
- LWLIB_ID id;
-{
- lw_pop_all_widgets (id, True);
-}
-
-void
-lw_pop_down_all_widgets (id)
- LWLIB_ID id;
-{
- lw_pop_all_widgets (id, False);
-}
-
-void
-lw_popup_menu (widget, event)
- Widget widget;
- XEvent *event;
-{
-#if defined (USE_LUCID)
- if (lw_lucid_widget_p (widget))
- xlw_popup_menu (widget, event);
-#endif
-#if defined (USE_MOTIF)
- if (lw_motif_widget_p (widget))
- xm_popup_menu (widget, event);
-#endif
-#if defined (USE_OLIT)
- if (lw_olit_widget_p (widget))
- xol_popup_menu (widget, event);
-#endif
-#if defined (USE_XAW)
- if (lw_xaw_widget_p (widget))
- xaw_popup_menu (widget, event);
-#endif
-}
-
- /* get the values back */
-static Boolean
-get_one_value (instance, val)
- widget_instance* instance;
- widget_value* val;
-{
- Widget widget = name_to_widget (instance, val->name);
-
- if (widget)
- {
-#if defined (USE_LUCID)
- if (lw_lucid_widget_p (instance->widget))
- xlw_update_one_value (instance, widget, val);
-#endif
-#if defined (USE_MOTIF)
- if (lw_motif_widget_p (instance->widget))
- xm_update_one_value (instance, widget, val);
-#endif
-#if defined (USE_OLIT)
- if (lw_olit_widget_p (instance->widget))
- xol_update_one_value (instance, widget, val);
-#endif
-#if defined (USE_XAW)
- if (lw_xaw_widget_p (instance->widget))
- xaw_update_one_value (instance, widget, val);
-#endif
- return True;
- }
- else
- return False;
-}
-
-Boolean
-lw_get_some_values (id, val_out)
- LWLIB_ID id;
- widget_value* val_out;
-{
- widget_info* info = get_widget_info (id, False);
- widget_instance* instance;
- widget_value* val;
- Boolean result = False;
-
- if (!info)
- return False;
-
- instance = info->instances;
- if (!instance)
- return False;
-
- for (val = val_out; val; val = val->next)
- if (get_one_value (instance, val))
- result = True;
-
- return result;
-}
-
-widget_value*
-lw_get_all_values (id)
- LWLIB_ID id;
-{
- widget_info* info = get_widget_info (id, False);
- widget_value* val = info->val;
- if (lw_get_some_values (id, val))
- return val;
- else
- return NULL;
-}
-
-/* internal function used by the library dependent implementation to get the
- widget_value for a given widget in an instance */
-widget_value*
-lw_get_widget_value_for_widget (instance, w)
- widget_instance* instance;
- Widget w;
-{
- char* name = XtName (w);
- widget_value* cur;
- for (cur = instance->info->val; cur; cur = cur->next)
- if (!strcmp (cur->name, name))
- return cur;
- return NULL;
-}
-
- /* update other instances value when one thing changed */
-
-/* To forbid recursive calls */
-static Boolean lwlib_updating;
-
-/* This function can be used as a an XtCallback for the widgets that get
- modified to update other instances of the widgets. Closure should be the
- widget_instance. */
-void
-lw_internal_update_other_instances (widget, closure, call_data)
- Widget widget;
- XtPointer closure;
- XtPointer call_data;
-{
- widget_instance* instance = (widget_instance*)closure;
- char* name = XtName (widget);
- widget_info* info;
- widget_instance* cur;
- widget_value* val;
-
- /* Avoid possibly infinite recursion. */
- if (lwlib_updating)
- return;
-
- /* protect against the widget being destroyed */
- if (XtWidgetBeingDestroyedP (widget))
- return;
-
- /* Return immediately if there are no other instances */
- info = instance->info;
- if (!info->instances->next)
- return;
-
- lwlib_updating = True;
-
- for (val = info->val; val && strcmp (val->name, name); val = val->next);
-
- if (val && get_one_value (instance, val))
- for (cur = info->instances; cur; cur = cur->next)
- if (cur != instance)
- set_one_value (cur, val, True);
-
- lwlib_updating = False;
-}
-
-
- /* get the id */
-
-LWLIB_ID
-lw_get_widget_id (w)
- Widget w;
-{
- widget_instance* instance = get_widget_instance (w, False);
-
- return instance ? instance->info->id : 0;
-}
-
- /* set the keyboard focus */
-void
-lw_set_keyboard_focus (parent, w)
- Widget parent;
- Widget w;
-{
-#if defined (USE_MOTIF)
- xm_set_keyboard_focus (parent, w);
-#else
- XtSetKeyboardFocus (parent, w);
-#endif
-}
-
- /* Show busy */
-static void
-show_one_widget_busy (w, flag)
- Widget w;
- Boolean flag;
-{
- Pixel foreground = 0;
- Pixel background = 1;
- Widget widget_to_invert = XtNameToWidget (w, "*sheet");
- if (!widget_to_invert)
- widget_to_invert = w;
-
- XtVaGetValues (widget_to_invert,
- XtNforeground, &foreground,
- XtNbackground, &background,
- 0);
- XtVaSetValues (widget_to_invert,
- XtNforeground, background,
- XtNbackground, foreground,
- 0);
-}
-
-void
-lw_show_busy (w, busy)
- Widget w;
- Boolean busy;
-{
- widget_instance* instance = get_widget_instance (w, False);
- widget_info* info;
- widget_instance* next;
-
- if (instance)
- {
- info = instance->info;
- if (info->busy != busy)
- {
- for (next = info->instances; next; next = next->next)
- if (next->widget)
- show_one_widget_busy (next->widget, busy);
- info->busy = busy;
- }
- }
-}
-
-/* This hack exists because Lucid/Athena need to execute the strange
- function below to support geometry management. */
-void
-lw_refigure_widget (w, doit)
- Widget w;
- Boolean doit;
-{
-#if defined (USE_XAW)
- XawPanedSetRefigureMode (w, doit);
-#endif
-#if defined (USE_MOTIF)
- if (doit)
- XtManageChild (w);
- else
- XtUnmanageChild (w);
-#endif
-}
-
-/* Toolkit independent way of determining if an event window is in the
- menubar. */
-Boolean
-lw_window_is_in_menubar (win, menubar_widget)
- Window win;
- Widget menubar_widget;
-{
- return menubar_widget
-#if defined (USE_LUCID)
- && XtWindow (menubar_widget) == win;
-#endif
-#if defined (USE_MOTIF)
- && ((XtWindow (menubar_widget) == win)
- || (XtWindowToWidget (XtDisplay (menubar_widget), win)
- && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget), win))
- == menubar_widget)));
-#endif
-}
-
-/* Motif hack to set the main window areas. */
-void
-lw_set_main_areas (parent, menubar, work_area)
- Widget parent;
- Widget menubar;
- Widget work_area;
-{
-#if defined (USE_MOTIF)
- xm_set_main_areas (parent, menubar, work_area);
-#endif
-}
-
-/* Manage resizing for Motif. This disables resizing when the menubar
- is about to be modified. */
-void
-lw_allow_resizing (w, flag)
- Widget w;
- Boolean flag;
-{
-#if defined (USE_MOTIF)
- xm_manage_resizing (w, flag);
-#endif
-}
diff --git a/lwlib/lwlib.h b/lwlib/lwlib.h
deleted file mode 100644
index 6bf26fe23c4..00000000000
--- a/lwlib/lwlib.h
+++ /dev/null
@@ -1,122 +0,0 @@
-#ifndef LWLIB_H
-#define LWLIB_H
-
-#include <X11/Intrinsic.h>
-
-/*
-** Widget values depend on the Widget type:
-**
-** widget: (name value key enabled data contents/selected)
-**
-** label: ("name" "string" NULL NULL NULL NULL)
-** button: ("name" "string" "key" T/F data <default-button-p>)
-** button w/menu:
-** ("name" "string" "key" T/F data (label|button|button w/menu...))
-** menubar: ("name" NULL NULL T/F data (button w/menu))
-** selectable thing:
-** ("name" "string" "key" T/F data T/F)
-** checkbox: selectable thing
-** radio: ("name" NULL NULL T/F data (selectable thing...))
-** strings: ("name" NULL NULL T/F data (selectable thing...))
-** text: ("name" "string" <ign> T/F data)
-** main: ("name")
-*/
-
-typedef unsigned long LWLIB_ID;
-
-typedef enum _change_type
-{
- NO_CHANGE = 0,
- INVISIBLE_CHANGE = 1,
- VISIBLE_CHANGE = 2,
- STRUCTURAL_CHANGE = 3
-} change_type;
-
-typedef struct _widget_value
-{
- /* name of widget */
- char* name;
- /* value (meaning depend on widget type) */
- char* value;
- /* keyboard equivalent. no implications for XtTranslations */
- char* key;
- /* true if enabled */
- Boolean enabled;
- /* true if selected */
- Boolean selected;
- /* true if was edited (maintained by get_value) */
- Boolean edited;
- /* true if has changed (maintained by lw library) */
- change_type change;
- /* true if this widget itself has changed,
- but not counting the other widgets found in the `next' field. */
- change_type this_one_change;
- /* Contents of the sub-widgets, also selected slot for checkbox */
- struct _widget_value* contents;
- /* data passed to callback */
- XtPointer call_data;
- /* next one in the list */
- struct _widget_value* next;
- /* slot for the toolkit dependent part. Always initialize to NULL. */
- void* toolkit_data;
- /* tell us if we should free the toolkit data slot when freeing the
- widget_value itself. */
- Boolean free_toolkit_data;
-
- /* we resource the widget_value structures; this points to the next
- one on the free list if this one has been deallocated.
- */
- struct _widget_value *free_list;
-} widget_value;
-
-
-typedef void (*lw_callback) (/* Widget w, LWLIB_ID id, void* data */);
-
-void lw_register_widget (/* char* type, char* name, LWLIB_ID id,
- widget_value* val, lw_callback pre_activate_cb,
- lw_callback selection_cb,
- lw_callback post_activate_cb */);
-Widget lw_get_widget (/* LWLIB_ID id, Widget parent, Boolean pop_up_p */);
-Widget lw_make_widget (/* LWLIB_ID id, Widget parent, Boolean pop_up_p */);
-Widget lw_create_widget (/* char* type, char* name, LWLIB_ID id,
- widget_value* val, Widget parent, Boolean pop_up_p,
- lw_callback pre_activate_cb,
- lw_callback selection_cb,
- lw_callback post_activate_cb */);
-LWLIB_ID lw_get_widget_id (/* Widget w */);
-void lw_modify_all_widgets (/* LWLIB_ID id, widget_value* val, Boolean deep_p */);
-void lw_destroy_widget (/* Widget w */);
-void lw_destroy_all_widgets (/* LWLIB_ID id */);
-void lw_destroy_everything (/* void */);
-void lw_destroy_all_pop_ups (/* void */);
-Widget lw_raise_all_pop_up_widgets (/* void */);
-widget_value* lw_get_all_values (/* LWLIB_ID id */);
-Boolean lw_get_some_values (/* LWLIB_ID id, widget_value* val */);
-void lw_pop_up_all_widgets (/* LWLIB_ID id */);
-void lw_pop_down_all_widgets (/* LWLIB_ID id */);
-widget_value *malloc_widget_value ();
-void free_widget_value (/* widget_value * */);
-void lw_popup_menu (/* Widget */);
-
-/* Toolkit independent way of focusing on a Widget at the Xt level. */
-void lw_set_keyboard_focus (/* Widget parent, Widget w */);
-
-/* Silly Energize hack to invert the "sheet" button */
-void lw_show_busy (/* Widget w, Boolean busy */);
-
-/* Silly hack to assist with Lucid/Athena geometry management. */
-void lw_refigure_widget (/* Widget w, Boolean doit */);
-
-/* Toolkit independent way of determining if an event occurred on a
- menubar. */
-Boolean lw_window_is_in_menubar (/* Window win, Widget menubar_widget */);
-
-/* Manage resizing: TRUE permits resizing widget w; FALSE disallows it. */
-void lw_allow_resizing (/* Widget w, Boolean flag */);
-
-/* Set up the main window. */
-void lw_set_main_areas (/* Widget parent,
- Widget menubar,
- Widget work_area */);
-
-#endif /* LWLIB_H */
diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c
deleted file mode 100644
index 24e80e23edc..00000000000
--- a/lwlib/xlwmenu.c
+++ /dev/null
@@ -1,1584 +0,0 @@
-/* Implements a lightweight menubar widget.
- Copyright (C) 1992 Lucid, Inc.
-
-This file is part of the Lucid Widget Library.
-
-The Lucid Widget Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-The Lucid Widget Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Created by devin@lucid.com */
-
-#include <stdio.h>
-
-#include <sys/types.h>
-#include <X11/Xos.h>
-#include <X11/IntrinsicP.h>
-#include <X11/ObjectP.h>
-#include <X11/StringDefs.h>
-#include <X11/cursorfont.h>
-#include <X11/bitmaps/gray>
-#include "xlwmenuP.h"
-
-static int pointer_grabbed;
-static XEvent menu_post_event;
-
-XFontStruct *xlwmenu_default_font;
-
-static char
-xlwMenuTranslations [] =
-"<BtnDown>: start()\n\
-<Motion>: drag()\n\
-<BtnUp>: select()\n\
-<Key>Shift_L: nothing()\n\
-<Key>Shift_R: nothing()\n\
-<Key>Meta_L: nothing()\n\
-<Key>Meta_R: nothing()\n\
-<Key>Control_L: nothing()\n\
-<Key>Control_R: nothing()\n\
-<Key>Hyper_L: nothing()\n\
-<Key>Hyper_R: nothing()\n\
-<Key>Super_L: nothing()\n\
-<Key>Super_R: nothing()\n\
-<Key>Alt_L: nothing()\n\
-<Key>Alt_R: nothing()\n\
-<Key>Caps_Lock: nothing()\n\
-<Key>Shift_Lock: nothing()\n\
-<KeyUp>Shift_L: nothing()\n\
-<KeyUp>Shift_R: nothing()\n\
-<KeyUp>Meta_L: nothing()\n\
-<KeyUp>Meta_R: nothing()\n\
-<KeyUp>Control_L: nothing()\n\
-<KeyUp>Control_R: nothing()\n\
-<KeyUp>Hyper_L: nothing()\n\
-<KeyUp>Hyper_R: nothing()\n\
-<KeyUp>Super_L: nothing()\n\
-<KeyUp>Super_R: nothing()\n\
-<KeyUp>Alt_L: nothing()\n\
-<KeyUp>Alt_R: nothing()\n\
-<KeyUp>Caps_Lock: nothing()\n\
-<KeyUp>Shift_Lock:nothing()\n\
-<Key>: key()\n\
-<KeyUp>: key()\n\
-";
-
-#define offset(field) XtOffset(XlwMenuWidget, field)
-static XtResource
-xlwMenuResources[] =
-{
- {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
- offset(menu.font),XtRString, "XtDefaultFont"},
- {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
- offset(menu.foreground), XtRString, "XtDefaultForeground"},
- {XtNbuttonForeground, XtCButtonForeground, XtRPixel, sizeof(Pixel),
- offset(menu.button_foreground), XtRString, "XtDefaultForeground"},
- {XtNmargin, XtCMargin, XtRDimension, sizeof(Dimension),
- offset(menu.margin), XtRImmediate, (XtPointer)0},
- {XtNhorizontalSpacing, XtCMargin, XtRDimension, sizeof(Dimension),
- offset(menu.horizontal_spacing), XtRImmediate, (XtPointer)3},
- {XtNverticalSpacing, XtCMargin, XtRDimension, sizeof(Dimension),
- offset(menu.vertical_spacing), XtRImmediate, (XtPointer)1},
- {XtNarrowSpacing, XtCMargin, XtRDimension, sizeof(Dimension),
- offset(menu.arrow_spacing), XtRImmediate, (XtPointer)10},
-
- {XmNshadowThickness, XmCShadowThickness, XtRDimension,
- sizeof (Dimension), offset (menu.shadow_thickness),
- XtRImmediate, (XtPointer) 2},
- {XmNtopShadowColor, XmCTopShadowColor, XtRPixel, sizeof (Pixel),
- offset (menu.top_shadow_color), XtRImmediate, (XtPointer)-1},
- {XmNbottomShadowColor, XmCBottomShadowColor, XtRPixel, sizeof (Pixel),
- offset (menu.bottom_shadow_color), XtRImmediate, (XtPointer)-1},
- {XmNtopShadowPixmap, XmCTopShadowPixmap, XtRPixmap, sizeof (Pixmap),
- offset (menu.top_shadow_pixmap), XtRImmediate, (XtPointer)None},
- {XmNbottomShadowPixmap, XmCBottomShadowPixmap, XtRPixmap, sizeof (Pixmap),
- offset (menu.bottom_shadow_pixmap), XtRImmediate, (XtPointer)None},
-
- {XtNopen, XtCCallback, XtRCallback, sizeof(XtPointer),
- offset(menu.open), XtRCallback, (XtPointer)NULL},
- {XtNselect, XtCCallback, XtRCallback, sizeof(XtPointer),
- offset(menu.select), XtRCallback, (XtPointer)NULL},
- {XtNmenu, XtCMenu, XtRPointer, sizeof(XtPointer),
- offset(menu.contents), XtRImmediate, (XtPointer)NULL},
- {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
- offset(menu.cursor_shape), XtRString, (XtPointer)"right_ptr"},
- {XtNhorizontal, XtCHorizontal, XtRInt, sizeof(int),
- offset(menu.horizontal), XtRImmediate, (XtPointer)True},
-};
-#undef offset
-
-static Boolean XlwMenuSetValues();
-static void XlwMenuRealize();
-static void XlwMenuRedisplay();
-static void XlwMenuResize();
-static void XlwMenuInitialize();
-static void XlwMenuRedisplay();
-static void XlwMenuDestroy();
-static void XlwMenuClassInitialize();
-static void Start();
-static void Drag();
-static void Select();
-static void Key();
-static void Nothing();
-
-static XtActionsRec
-xlwMenuActionsList [] =
-{
- {"start", Start},
- {"drag", Drag},
- {"select", Select},
- {"key", Key},
- {"nothing", Nothing},
-};
-
-#define SuperClass ((CoreWidgetClass)&coreClassRec)
-
-XlwMenuClassRec xlwMenuClassRec =
-{
- { /* CoreClass fields initialization */
- (WidgetClass) SuperClass, /* superclass */
- "XlwMenu", /* class_name */
- sizeof(XlwMenuRec), /* size */
- XlwMenuClassInitialize, /* class_initialize */
- NULL, /* class_part_initialize */
- FALSE, /* class_inited */
- XlwMenuInitialize, /* initialize */
- NULL, /* initialize_hook */
- XlwMenuRealize, /* realize */
- xlwMenuActionsList, /* actions */
- XtNumber(xlwMenuActionsList), /* num_actions */
- xlwMenuResources, /* resources */
- XtNumber(xlwMenuResources), /* resource_count */
- NULLQUARK, /* xrm_class */
- TRUE, /* compress_motion */
- TRUE, /* compress_exposure */
- TRUE, /* compress_enterleave */
- FALSE, /* visible_interest */
- XlwMenuDestroy, /* destroy */
- XlwMenuResize, /* resize */
- XlwMenuRedisplay, /* expose */
- XlwMenuSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- xlwMenuTranslations, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL /* extension */
- }, /* XlwMenuClass fields initialization */
- {
- 0 /* dummy */
- },
-};
-
-WidgetClass xlwMenuWidgetClass = (WidgetClass) &xlwMenuClassRec;
-
-int submenu_destroyed;
-
-static int next_release_must_exit;
-
- /* Utilities */
-static void
-push_new_stack (mw, val)
- XlwMenuWidget mw;
- widget_value* val;
-{
- if (!mw->menu.new_stack)
- {
- mw->menu.new_stack_length = 10;
- mw->menu.new_stack =
- (widget_value**)XtCalloc (mw->menu.new_stack_length,
- sizeof (widget_value*));
- }
- else if (mw->menu.new_depth == mw->menu.new_stack_length)
- {
- mw->menu.new_stack_length *= 2;
- mw->menu.new_stack =
- (widget_value**)XtRealloc ((char*)mw->menu.new_stack,
- mw->menu.new_stack_length * sizeof (widget_value*));
- }
- mw->menu.new_stack [mw->menu.new_depth++] = val;
-}
-
-static void
-pop_new_stack_if_no_contents (mw)
- XlwMenuWidget mw;
-{
- if (mw->menu.new_depth)
- {
- if (!mw->menu.new_stack [mw->menu.new_depth - 1]->contents)
- mw->menu.new_depth -= 1;
- }
-}
-
-static void
-make_old_stack_space (mw, n)
- XlwMenuWidget mw;
- int n;
-{
- if (!mw->menu.old_stack)
- {
- mw->menu.old_stack_length = 10;
- mw->menu.old_stack =
- (widget_value**)XtCalloc (mw->menu.old_stack_length,
- sizeof (widget_value*));
- }
- else if (mw->menu.old_stack_length < n)
- {
- mw->menu.old_stack_length *= 2;
- mw->menu.old_stack =
- (widget_value**)XtRealloc ((char*)mw->menu.old_stack,
- mw->menu.old_stack_length * sizeof (widget_value*));
- }
-}
-
- /* Size code */
-static Boolean
-all_dashes_p (s)
- char *s;
-{
- char* p;
- for (p = s; *p == '-'; p++);
- return !*p;
-}
-
-int
-string_width (mw, s)
- XlwMenuWidget mw;
- char *s;
-{
- XCharStruct xcs;
- int drop;
-
- XTextExtents (mw->menu.font, s, strlen (s), &drop, &drop, &drop, &xcs);
- return xcs.width;
-}
-
-static int
-arrow_width (mw)
- XlwMenuWidget mw;
-{
- return mw->menu.font->ascent / 2 | 1;
-}
-
-static XtResource
-nameResource[] =
-{
- {"labelString", "LabelString", XtRString, sizeof(String),
- 0, XtRImmediate, 0},
-};
-
-static char*
-resource_widget_value (mw, val)
- XlwMenuWidget mw;
- widget_value *val;
-{
- if (!val->toolkit_data)
- {
- char* resourced_name = NULL;
- char* complete_name;
- XtGetSubresources ((Widget) mw,
- (XtPointer) &resourced_name,
- val->name, val->name,
- nameResource, 1, NULL, 0);
- if (!resourced_name)
- resourced_name = val->name;
- if (!val->value)
- {
- complete_name = (char *) XtMalloc (strlen (resourced_name) + 1);
- strcpy (complete_name, resourced_name);
- }
- else
- {
- int complete_length =
- strlen (resourced_name) + strlen (val->value) + 2;
- complete_name = XtMalloc (complete_length);
- *complete_name = 0;
- strcat (complete_name, resourced_name);
- strcat (complete_name, " ");
- strcat (complete_name, val->value);
- }
-
- val->toolkit_data = complete_name;
- val->free_toolkit_data = True;
- }
- return (char*)val->toolkit_data;
-}
-
-/* Returns the sizes of an item */
-static void
-size_menu_item (mw, val, horizontal_p, label_width, rest_width, height)
- XlwMenuWidget mw;
- widget_value* val;
- int horizontal_p;
- int* label_width;
- int* rest_width;
- int* height;
-{
- if (all_dashes_p (val->name))
- {
- *height = 2;
- *label_width = 1;
- *rest_width = 0;
- }
- else
- {
- *height =
- mw->menu.font->ascent + mw->menu.font->descent
- + 2 * mw->menu.vertical_spacing + 2 * mw->menu.shadow_thickness;
-
- *label_width =
- string_width (mw, resource_widget_value (mw, val))
- + mw->menu.horizontal_spacing + mw->menu.shadow_thickness;
-
- *rest_width = mw->menu.horizontal_spacing + mw->menu.shadow_thickness;
- if (!horizontal_p)
- {
- if (val->contents)
- *rest_width += arrow_width (mw) + mw->menu.arrow_spacing;
- else if (val->key)
- *rest_width +=
- string_width (mw, val->key) + mw->menu.arrow_spacing;
- }
- }
-}
-
-static void
-size_menu (mw, level)
- XlwMenuWidget mw;
- int level;
-{
- unsigned int label_width = 0;
- int rest_width = 0;
- int max_rest_width = 0;
- unsigned int height = 0;
- int horizontal_p = mw->menu.horizontal && (level == 0);
- widget_value* val;
- window_state* ws;
-
- if (level >= mw->menu.old_depth)
- abort ();
-
- ws = &mw->menu.windows [level];
- ws->width = 0;
- ws->height = 0;
- ws->label_width = 0;
-
- for (val = mw->menu.old_stack [level]->contents; val; val = val->next)
- {
- size_menu_item (mw, val, horizontal_p, &label_width, &rest_width,
- &height);
- if (horizontal_p)
- {
- ws->width += label_width + rest_width;
- if (height > ws->height)
- ws->height = height;
- }
- else
- {
- if (label_width > ws->label_width)
- ws->label_width = label_width;
- if (rest_width > max_rest_width)
- max_rest_width = rest_width;
- ws->height += height;
- }
- }
-
- if (horizontal_p)
- ws->label_width = 0;
- else
- ws->width = ws->label_width + max_rest_width;
-
- ws->width += 2 * mw->menu.shadow_thickness;
- ws->height += 2 * mw->menu.shadow_thickness;
-}
-
-
- /* Display code */
-static void
-draw_arrow (mw, window, gc, x, y, width)
- XlwMenuWidget mw;
- Window window;
- GC gc;
- int x;
- int y;
- int width;
-{
- XPoint points [3];
- points [0].x = x;
- points [0].y = y + mw->menu.font->ascent;
- points [1].x = x;
- points [1].y = y;
- points [2].x = x + width;
- points [2].y = y + mw->menu.font->ascent / 2;
-
- XFillPolygon (XtDisplay (mw), window, gc, points, 3, Convex,
- CoordModeOrigin);
-}
-
-static void
-draw_shadow_rectangle (mw, window, x, y, width, height, erase_p)
- XlwMenuWidget mw;
- Window window;
- int x;
- int y;
- int width;
- int height;
- int erase_p;
-{
- Display *dpy = XtDisplay (mw);
- GC top_gc = !erase_p ? mw->menu.shadow_top_gc : mw->menu.background_gc;
- GC bottom_gc = !erase_p ? mw->menu.shadow_bottom_gc : mw->menu.background_gc;
- int thickness = mw->menu.shadow_thickness;
- XPoint points [4];
- points [0].x = x;
- points [0].y = y;
- points [1].x = x + width;
- points [1].y = y;
- points [2].x = x + width - thickness;
- points [2].y = y + thickness;
- points [3].x = x;
- points [3].y = y + thickness;
- XFillPolygon (dpy, window, top_gc, points, 4, Convex, CoordModeOrigin);
- points [0].x = x;
- points [0].y = y + thickness;
- points [1].x = x;
- points [1].y = y + height;
- points [2].x = x + thickness;
- points [2].y = y + height - thickness;
- points [3].x = x + thickness;
- points [3].y = y + thickness;
- XFillPolygon (dpy, window, top_gc, points, 4, Convex, CoordModeOrigin);
- points [0].x = x + width;
- points [0].y = y;
- points [1].x = x + width - thickness;
- points [1].y = y + thickness;
- points [2].x = x + width - thickness;
- points [2].y = y + height - thickness;
- points [3].x = x + width;
- points [3].y = y + height - thickness;
- XFillPolygon (dpy, window, bottom_gc, points, 4, Convex, CoordModeOrigin);
- points [0].x = x;
- points [0].y = y + height;
- points [1].x = x + width;
- points [1].y = y + height;
- points [2].x = x + width;
- points [2].y = y + height - thickness;
- points [3].x = x + thickness;
- points [3].y = y + height - thickness;
- XFillPolygon (dpy, window, bottom_gc, points, 4, Convex, CoordModeOrigin);
-}
-
-
-/* Display the menu item and increment where.x and where.y to show how large
-** the menu item was.
-*/
-static void
-display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p, just_compute_p)
- XlwMenuWidget mw;
- widget_value* val;
- window_state* ws;
- XPoint* where;
- Boolean highlighted_p;
- Boolean horizontal_p;
- Boolean just_compute_p;
-{
- GC deco_gc;
- GC text_gc;
- int font_ascent = mw->menu.font->ascent;
- int font_descent = mw->menu.font->descent;
- int shadow = mw->menu.shadow_thickness;
- int separator_p = all_dashes_p (val->name);
- int h_spacing = mw->menu.horizontal_spacing;
- int v_spacing = mw->menu.vertical_spacing;
- int label_width;
- int rest_width;
- int height;
- int width;
- int button_p;
-
- /* compute the sizes of the item */
- size_menu_item (mw, val, horizontal_p, &label_width, &rest_width, &height);
-
- if (horizontal_p)
- width = label_width + rest_width;
- else
- {
- label_width = ws->label_width;
- width = ws->width - 2 * shadow;
- }
-
-#if 0
- /* see if it should be a button in the menubar */
- button_p = horizontal_p && val->call_data;
-#endif
- button_p = 0;
-
- /* Only highlight an enabled item that has a callback. */
- if (highlighted_p)
- if (!val->enabled || !(val->call_data || val->contents))
- highlighted_p = 0;
-
- /* do the drawing. */
- if (!just_compute_p)
- {
- /* Add the shadow border of the containing menu */
- int x = where->x + shadow;
- int y = where->y + shadow;
-
- /* pick the foreground and background GC. */
- if (val->enabled)
- text_gc = button_p ? mw->menu.button_gc : mw->menu.foreground_gc;
- else
- text_gc =
- button_p ? mw->menu.inactive_button_gc : mw->menu.inactive_gc;
- deco_gc = mw->menu.foreground_gc;
-
- if (separator_p)
- {
- XDrawLine (XtDisplay (mw), ws->window, mw->menu.shadow_bottom_gc,
- x, y, x + width, y);
- XDrawLine (XtDisplay (mw), ws->window, mw->menu.shadow_top_gc,
- x, y + 1, x + width, y + 1);
- }
- else
- {
- int x_offset = x + h_spacing + shadow;
- char* display_string = resource_widget_value (mw, val);
- draw_shadow_rectangle (mw, ws->window, x, y, width, height, True);
-
- /* Deal with centering a menu title. */
- if (!horizontal_p && !val->contents && !val->call_data)
- {
- int l = string_width (mw, display_string);
-
- if (width > l)
- x_offset = (width - l) >> 1;
- }
- XDrawString (XtDisplay (mw), ws->window, text_gc, x_offset,
- y + v_spacing + shadow + font_ascent,
- display_string, strlen (display_string));
-
- if (!horizontal_p)
- {
- if (val->contents)
- {
- int a_w = arrow_width (mw);
- draw_arrow (mw, ws->window, deco_gc,
- x + width - arrow_width (mw)
- - mw->menu.horizontal_spacing
- - mw->menu.shadow_thickness,
- y + v_spacing + shadow, a_w);
- }
- else if (val->key)
- {
- XDrawString (XtDisplay (mw), ws->window, text_gc,
- x + label_width + mw->menu.arrow_spacing,
- y + v_spacing + shadow + font_ascent,
- val->key, strlen (val->key));
- }
- }
-
- else if (button_p)
- {
-#if 1
- XDrawRectangle (XtDisplay (mw), ws->window, deco_gc,
- x + shadow, y + shadow,
- label_width + h_spacing - 1,
- font_ascent + font_descent + 2 * v_spacing - 1);
- draw_shadow_rectangle (mw, ws->window, x, y, width, height,
- False);
-#else
- highlighted_p = True;
-#endif
- }
- else
- {
- XDrawRectangle (XtDisplay (mw), ws->window,
- mw->menu.background_gc,
- x + shadow, y + shadow,
- label_width + h_spacing - 1,
- font_ascent + font_descent + 2 * v_spacing - 1);
- draw_shadow_rectangle (mw, ws->window, x, y, width, height,
- True);
- }
-
- if (highlighted_p)
- draw_shadow_rectangle (mw, ws->window, x, y, width, height, False);
- }
- }
-
- where->x += width;
- where->y += height;
-}
-
-static void
-display_menu (mw, level, just_compute_p, highlighted_pos, hit, hit_return,
- this, that)
- XlwMenuWidget mw;
- int level;
- Boolean just_compute_p;
- XPoint* highlighted_pos;
- XPoint* hit;
- widget_value** hit_return;
- widget_value* this;
- widget_value* that;
-{
- widget_value* val;
- widget_value* following_item;
- window_state* ws;
- XPoint where;
- int horizontal_p = mw->menu.horizontal && (level == 0);
- int highlighted_p;
- int just_compute_this_one_p;
-
- if (level >= mw->menu.old_depth)
- abort ();
-
- if (level < mw->menu.old_depth - 1)
- following_item = mw->menu.old_stack [level + 1];
- else
- following_item = NULL;
-
- if (hit)
- *hit_return = NULL;
-
- where.x = 0;
- where.y = 0;
-
- ws = &mw->menu.windows [level];
- for (val = mw->menu.old_stack [level]->contents; val; val = val->next)
- {
- highlighted_p = val == following_item;
- if (highlighted_p && highlighted_pos)
- {
- if (horizontal_p)
- highlighted_pos->x = where.x;
- else
- highlighted_pos->y = where.y;
- }
-
- just_compute_this_one_p =
- just_compute_p || ((this || that) && val != this && val != that);
-
- display_menu_item (mw, val, ws, &where, highlighted_p, horizontal_p,
- just_compute_this_one_p);
-
- if (highlighted_p && highlighted_pos)
- {
- if (horizontal_p)
- highlighted_pos->y = where.y;
- else
- highlighted_pos->x = where.x;
- }
-
- if (hit
- && !*hit_return
- && (horizontal_p ? hit->x < where.x : hit->y < where.y)
- && !all_dashes_p (val->name))
- *hit_return = val;
-
- if (horizontal_p)
- where.y = 0;
- else
- where.x = 0;
- }
-
- if (!just_compute_p)
- draw_shadow_rectangle (mw, ws->window, 0, 0, ws->width, ws->height, False);
-}
-
- /* Motion code */
-static void
-set_new_state (mw, val, level)
- XlwMenuWidget mw;
- widget_value* val;
- int level;
-{
- int i;
-
- mw->menu.new_depth = 0;
- for (i = 0; i < level; i++)
- push_new_stack (mw, mw->menu.old_stack [i]);
- push_new_stack (mw, val);
-}
-
-static void
-make_windows_if_needed (mw, n)
- XlwMenuWidget mw;
- int n;
-{
- int i;
- int start_at;
- XSetWindowAttributes xswa;
- int mask;
- Window root = RootWindowOfScreen (DefaultScreenOfDisplay (XtDisplay (mw)));
- window_state* windows;
-
- if (mw->menu.windows_length >= n)
- return;
-
- xswa.save_under = True;
- xswa.override_redirect = True;
- xswa.background_pixel = mw->core.background_pixel;
- xswa.border_pixel = mw->core.border_pixel;
- xswa.event_mask =
- ExposureMask | PointerMotionMask | PointerMotionHintMask
- | ButtonReleaseMask | ButtonPressMask;
- xswa.cursor = mw->menu.cursor_shape;
- mask = CWSaveUnder | CWOverrideRedirect | CWBackPixel | CWBorderPixel
- | CWEventMask | CWCursor;
-
- if (!mw->menu.windows)
- {
- mw->menu.windows =
- (window_state*)XtMalloc (n * sizeof (window_state));
- start_at = 0;
- }
- else
- {
- mw->menu.windows =
- (window_state*)XtRealloc ((char*)mw->menu.windows,
- n * sizeof (window_state));
- start_at = mw->menu.windows_length;
- }
- mw->menu.windows_length = n;
-
- windows = mw->menu.windows;
-
- for (i = start_at; i < n; i++)
- {
- windows [i].x = 0;
- windows [i].y = 0;
- windows [i].width = 1;
- windows [i].height = 1;
- windows [i].window =
- XCreateWindow (XtDisplay (mw), root, 0, 0, 1, 1,
- 0, 0, CopyFromParent, CopyFromParent, mask, &xswa);
- }
-}
-
-/* Make the window fit in the screen */
-static void
-fit_to_screen (mw, ws, previous_ws, horizontal_p)
- XlwMenuWidget mw;
- window_state* ws;
- window_state* previous_ws;
- Boolean horizontal_p;
-{
- unsigned int screen_width = WidthOfScreen (XtScreen (mw));
- unsigned int screen_height = HeightOfScreen (XtScreen (mw));
-
- if (ws->x < 0)
- ws->x = 0;
- else if (ws->x + ws->width > screen_width)
- {
- if (!horizontal_p)
- ws->x = previous_ws->x - ws->width;
- else
- ws->x = screen_width - ws->width;
- if (ws->x < 0)
- ws->x = 0;
- }
- if (ws->y < 0)
- ws->y = 0;
- else if (ws->y + ws->height > screen_height)
- {
- if (horizontal_p)
- ws->y = previous_ws->y - ws->height;
- else
- ws->y = screen_height - ws->height;
- if (ws->y < 0)
- ws->y = 0;
- }
-}
-
-/* Updates old_stack from new_stack and redisplays. */
-static void
-remap_menubar (mw)
- XlwMenuWidget mw;
-{
- int i;
- int last_same;
- XPoint selection_position;
- int old_depth = mw->menu.old_depth;
- int new_depth = mw->menu.new_depth;
- widget_value** old_stack;
- widget_value** new_stack;
- window_state* windows;
- widget_value* old_selection;
- widget_value* new_selection;
-
- /* Check that enough windows and old_stack are ready. */
- make_windows_if_needed (mw, new_depth);
- make_old_stack_space (mw, new_depth);
- windows = mw->menu.windows;
- old_stack = mw->menu.old_stack;
- new_stack = mw->menu.new_stack;
-
- /* compute the last identical different entry */
- for (i = 1; i < old_depth && i < new_depth; i++)
- if (old_stack [i] != new_stack [i])
- break;
- last_same = i - 1;
-
- /* Memorize the previously selected item to be able to refresh it */
- old_selection = last_same + 1 < old_depth ? old_stack [last_same + 1] : NULL;
- if (old_selection && !old_selection->enabled)
- old_selection = NULL;
- new_selection = last_same + 1 < new_depth ? new_stack [last_same + 1] : NULL;
- if (new_selection && !new_selection->enabled)
- new_selection = NULL;
-
- /* updates old_state from new_state. It has to be done now because
- display_menu (called below) uses the old_stack to know what to display. */
- for (i = last_same + 1; i < new_depth; i++)
- old_stack [i] = new_stack [i];
- mw->menu.old_depth = new_depth;
-
- /* refresh the last selection */
- selection_position.x = 0;
- selection_position.y = 0;
- display_menu (mw, last_same, new_selection == old_selection,
- &selection_position, NULL, NULL, old_selection, new_selection);
-
- /* Now popup the new menus */
- for (i = last_same + 1; i < new_depth && new_stack [i]->contents; i++)
- {
- window_state* previous_ws = &windows [i - 1];
- window_state* ws = &windows [i];
-
- ws->x =
- previous_ws->x + selection_position.x + mw->menu.shadow_thickness;
- if (!mw->menu.horizontal || i > 1)
- ws->x += mw->menu.shadow_thickness;
- ws->y =
- previous_ws->y + selection_position.y + mw->menu.shadow_thickness;
-
- size_menu (mw, i);
-
- fit_to_screen (mw, ws, previous_ws, mw->menu.horizontal && i == 1);
-
- XClearWindow (XtDisplay (mw), ws->window);
- XMoveResizeWindow (XtDisplay (mw), ws->window, ws->x, ws->y,
- ws->width, ws->height);
- XMapRaised (XtDisplay (mw), ws->window);
- display_menu (mw, i, False, &selection_position, NULL, NULL, NULL, NULL);
- }
-
- /* unmap the menus that popped down */
- for (i = new_depth - 1; i < old_depth; i++)
- if (i >= new_depth || !new_stack [i]->contents)
- XUnmapWindow (XtDisplay (mw), windows [i].window);
-}
-
-static Boolean
-motion_event_is_in_menu (mw, ev, level, relative_pos)
- XlwMenuWidget mw;
- XMotionEvent* ev;
- int level;
- XPoint* relative_pos;
-{
- window_state* ws = &mw->menu.windows [level];
- int x = level == 0 ? ws->x : ws->x + mw->menu.shadow_thickness;
- int y = level == 0 ? ws->y : ws->y + mw->menu.shadow_thickness;
- relative_pos->x = ev->x_root - x;
- relative_pos->y = ev->y_root - y;
- return (x < ev->x_root && ev->x_root < x + ws->width
- && y < ev->y_root && ev->y_root < y + ws->height);
-}
-
-static Boolean
-map_event_to_widget_value (mw, ev, val, level)
- XlwMenuWidget mw;
- XMotionEvent* ev;
- widget_value** val;
- int* level;
-{
- int i;
- XPoint relative_pos;
- window_state* ws;
-
- *val = NULL;
-
- /* Find the window */
- for (i = mw->menu.old_depth - 1; i >= 0; i--)
- {
- ws = &mw->menu.windows [i];
- if (ws && motion_event_is_in_menu (mw, ev, i, &relative_pos))
- {
- display_menu (mw, i, True, NULL, &relative_pos, val, NULL, NULL);
-
- if (*val)
- {
- *level = i + 1;
- return True;
- }
- }
- }
- return False;
-}
-
- /* Procedures */
-static void
-make_drawing_gcs (mw)
- XlwMenuWidget mw;
-{
- XGCValues xgcv;
-
- xgcv.font = mw->menu.font->fid;
- xgcv.foreground = mw->menu.foreground;
- xgcv.background = mw->core.background_pixel;
- mw->menu.foreground_gc = XtGetGC ((Widget)mw,
- GCFont | GCForeground | GCBackground,
- &xgcv);
-
- xgcv.font = mw->menu.font->fid;
- xgcv.foreground = mw->menu.button_foreground;
- xgcv.background = mw->core.background_pixel;
- mw->menu.button_gc = XtGetGC ((Widget)mw,
- GCFont | GCForeground | GCBackground,
- &xgcv);
-
- xgcv.font = mw->menu.font->fid;
- xgcv.foreground = mw->menu.foreground;
- xgcv.background = mw->core.background_pixel;
- xgcv.fill_style = FillStippled;
- xgcv.stipple = mw->menu.gray_pixmap;
- mw->menu.inactive_gc = XtGetGC ((Widget)mw,
- (GCFont | GCForeground | GCBackground
- | GCFillStyle | GCStipple), &xgcv);
-
- xgcv.font = mw->menu.font->fid;
- xgcv.foreground = mw->menu.button_foreground;
- xgcv.background = mw->core.background_pixel;
- xgcv.fill_style = FillStippled;
- xgcv.stipple = mw->menu.gray_pixmap;
- mw->menu.inactive_button_gc = XtGetGC ((Widget)mw,
- (GCFont | GCForeground | GCBackground
- | GCFillStyle | GCStipple), &xgcv);
-
- xgcv.font = mw->menu.font->fid;
- xgcv.foreground = mw->core.background_pixel;
- xgcv.background = mw->menu.foreground;
- mw->menu.background_gc = XtGetGC ((Widget)mw,
- GCFont | GCForeground | GCBackground,
- &xgcv);
-}
-
-static void
-release_drawing_gcs (mw)
- XlwMenuWidget mw;
-{
- XtReleaseGC ((Widget) mw, mw->menu.foreground_gc);
- XtReleaseGC ((Widget) mw, mw->menu.button_gc);
- XtReleaseGC ((Widget) mw, mw->menu.inactive_gc);
- XtReleaseGC ((Widget) mw, mw->menu.inactive_button_gc);
- XtReleaseGC ((Widget) mw, mw->menu.background_gc);
- /* let's get some segvs if we try to use these... */
- mw->menu.foreground_gc = (GC) -1;
- mw->menu.button_gc = (GC) -1;
- mw->menu.inactive_gc = (GC) -1;
- mw->menu.inactive_button_gc = (GC) -1;
- mw->menu.background_gc = (GC) -1;
-}
-
-#define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \
- ? ((unsigned long) (x)) : ((unsigned long) (y)))
-
-static void
-make_shadow_gcs (mw)
- XlwMenuWidget mw;
-{
- XGCValues xgcv;
- unsigned long pm = 0;
- Display *dpy = XtDisplay ((Widget) mw);
- Colormap cmap = DefaultColormapOfScreen (XtScreen ((Widget) mw));
- XColor topc, botc;
- int top_frobbed = 0, bottom_frobbed = 0;
-
- if (mw->menu.top_shadow_color == -1)
- mw->menu.top_shadow_color = mw->core.background_pixel;
- if (mw->menu.bottom_shadow_color == -1)
- mw->menu.bottom_shadow_color = mw->menu.foreground;
-
- if (mw->menu.top_shadow_color == mw->core.background_pixel ||
- mw->menu.top_shadow_color == mw->menu.foreground)
- {
- topc.pixel = mw->core.background_pixel;
- XQueryColor (dpy, cmap, &topc);
- /* don't overflow/wrap! */
- topc.red = MINL (65535, topc.red * 1.2);
- topc.green = MINL (65535, topc.green * 1.2);
- topc.blue = MINL (65535, topc.blue * 1.2);
- if (XAllocColor (dpy, cmap, &topc))
- {
- mw->menu.top_shadow_color = topc.pixel;
- top_frobbed = 1;
- }
- }
- if (mw->menu.bottom_shadow_color == mw->menu.foreground ||
- mw->menu.bottom_shadow_color == mw->core.background_pixel)
- {
- botc.pixel = mw->core.background_pixel;
- XQueryColor (dpy, cmap, &botc);
- botc.red *= 0.6;
- botc.green *= 0.6;
- botc.blue *= 0.6;
- if (XAllocColor (dpy, cmap, &botc))
- {
- mw->menu.bottom_shadow_color = botc.pixel;
- bottom_frobbed = 1;
- }
- }
-
- if (top_frobbed && bottom_frobbed)
- {
- int top_avg = ((topc.red / 3) + (topc.green / 3) + (topc.blue / 3));
- int bot_avg = ((botc.red / 3) + (botc.green / 3) + (botc.blue / 3));
- if (bot_avg > top_avg)
- {
- Pixel tmp = mw->menu.top_shadow_color;
- mw->menu.top_shadow_color = mw->menu.bottom_shadow_color;
- mw->menu.bottom_shadow_color = tmp;
- }
- else if (topc.pixel == botc.pixel)
- {
- if (botc.pixel == mw->menu.foreground)
- mw->menu.top_shadow_color = mw->core.background_pixel;
- else
- mw->menu.bottom_shadow_color = mw->menu.foreground;
- }
- }
-
- if (!mw->menu.top_shadow_pixmap &&
- mw->menu.top_shadow_color == mw->core.background_pixel)
- {
- mw->menu.top_shadow_pixmap = mw->menu.gray_pixmap;
- mw->menu.top_shadow_color = mw->menu.foreground;
- }
- if (!mw->menu.bottom_shadow_pixmap &&
- mw->menu.bottom_shadow_color == mw->core.background_pixel)
- {
- mw->menu.bottom_shadow_pixmap = mw->menu.gray_pixmap;
- mw->menu.bottom_shadow_color = mw->menu.foreground;
- }
-
- xgcv.fill_style = FillStippled;
- xgcv.foreground = mw->menu.top_shadow_color;
- xgcv.stipple = mw->menu.top_shadow_pixmap;
- pm = (xgcv.stipple ? GCStipple|GCFillStyle : 0);
- mw->menu.shadow_top_gc = XtGetGC ((Widget)mw, GCForeground | pm, &xgcv);
-
- xgcv.foreground = mw->menu.bottom_shadow_color;
- xgcv.stipple = mw->menu.bottom_shadow_pixmap;
- pm = (xgcv.stipple ? GCStipple|GCFillStyle : 0);
- mw->menu.shadow_bottom_gc = XtGetGC ((Widget)mw, GCForeground | pm, &xgcv);
-}
-
-
-static void
-release_shadow_gcs (mw)
- XlwMenuWidget mw;
-{
- XtReleaseGC ((Widget) mw, mw->menu.shadow_top_gc);
- XtReleaseGC ((Widget) mw, mw->menu.shadow_bottom_gc);
-}
-
-static void
-XlwMenuInitialize (request, mw, args, num_args)
- Widget request;
- XlwMenuWidget mw;
- ArgList args;
- Cardinal *num_args;
-{
- /* Get the GCs and the widget size */
- XSetWindowAttributes xswa;
- int mask;
-
- Window window = RootWindowOfScreen (DefaultScreenOfDisplay (XtDisplay (mw)));
- Display* display = XtDisplay (mw);
-
-#if 0
- widget_value *tem = (widget_value *) XtMalloc (sizeof (widget_value));
-
- /* _XtCreate is freeing the object that was passed to us,
- so make a copy that we will actually keep. */
- lwlib_bcopy (mw->menu.contents, tem, sizeof (widget_value));
- mw->menu.contents = tem;
-#endif
-
-/* mw->menu.cursor = XCreateFontCursor (display, mw->menu.cursor_shape); */
- mw->menu.cursor = mw->menu.cursor_shape;
-
- mw->menu.gray_pixmap
- = XCreatePixmapFromBitmapData (display, window, gray_bits,
- gray_width, gray_height,
- (unsigned long)1, (unsigned long)0, 1);
-
- /* I don't understand why this ends up 0 sometimes,
- but it does. This kludge works around it.
- Can anyone find a real fix? -- rms. */
- if (mw->menu.font == 0)
- mw->menu.font = xlwmenu_default_font;
-
- make_drawing_gcs (mw);
- make_shadow_gcs (mw);
-
- xswa.background_pixel = mw->core.background_pixel;
- xswa.border_pixel = mw->core.border_pixel;
- mask = CWBackPixel | CWBorderPixel;
-
- mw->menu.popped_up = False;
-
- mw->menu.old_depth = 1;
- mw->menu.old_stack = (widget_value**)XtMalloc (sizeof (widget_value*));
- mw->menu.old_stack_length = 1;
- mw->menu.old_stack [0] = mw->menu.contents;
-
- mw->menu.new_depth = 0;
- mw->menu.new_stack = 0;
- mw->menu.new_stack_length = 0;
- push_new_stack (mw, mw->menu.contents);
-
- mw->menu.windows = (window_state*)XtMalloc (sizeof (window_state));
- mw->menu.windows_length = 1;
- mw->menu.windows [0].x = 0;
- mw->menu.windows [0].y = 0;
- mw->menu.windows [0].width = 0;
- mw->menu.windows [0].height = 0;
- size_menu (mw, 0);
-
- mw->core.width = mw->menu.windows [0].width;
- mw->core.height = mw->menu.windows [0].height;
-}
-
-static void
-XlwMenuClassInitialize ()
-{
-}
-
-static void
-XlwMenuRealize (w, valueMask, attributes)
- Widget w;
- Mask *valueMask;
- XSetWindowAttributes *attributes;
-{
- XlwMenuWidget mw = (XlwMenuWidget)w;
- XSetWindowAttributes xswa;
- int mask;
-
- (*xlwMenuWidgetClass->core_class.superclass->core_class.realize)
- (w, valueMask, attributes);
-
- xswa.save_under = True;
- xswa.cursor = mw->menu.cursor_shape;
- mask = CWSaveUnder | CWCursor;
- XChangeWindowAttributes (XtDisplay (w), XtWindow (w), mask, &xswa);
-
- mw->menu.windows [0].window = XtWindow (w);
- mw->menu.windows [0].x = w->core.x;
- mw->menu.windows [0].y = w->core.y;
- mw->menu.windows [0].width = w->core.width;
- mw->menu.windows [0].height = w->core.height;
-}
-
-/* Only the toplevel menubar/popup is a widget so it's the only one that
- receives expose events through Xt. So we repaint all the other panes
- when receiving an Expose event. */
-static void
-XlwMenuRedisplay (w, ev, region)
- Widget w;
- XEvent* ev;
- Region region;
-{
- XlwMenuWidget mw = (XlwMenuWidget)w;
- int i;
-
- /* If we have a depth beyond 1, it's because a submenu was displayed.
- If the submenu has been destroyed, set the depth back to 1. */
- if (submenu_destroyed)
- {
- mw->menu.old_depth = 1;
- submenu_destroyed = 0;
- }
-
- for (i = 0; i < mw->menu.old_depth; i++)
- display_menu (mw, i, False, NULL, NULL, NULL, NULL, NULL);
-}
-
-static void
-XlwMenuDestroy (w)
- Widget w;
-{
- int i;
- XlwMenuWidget mw = (XlwMenuWidget) w;
-
- if (pointer_grabbed)
- XtUngrabPointer ((Widget)w, CurrentTime);
- pointer_grabbed = 0;
-
- submenu_destroyed = 1;
-
- release_drawing_gcs (mw);
- release_shadow_gcs (mw);
-
- /* this doesn't come from the resource db but is created explicitly
- so we must free it ourselves. */
- XFreePixmap (XtDisplay (mw), mw->menu.gray_pixmap);
- mw->menu.gray_pixmap = (Pixmap) -1;
-
-#if 0
- /* Do free mw->menu.contents because nowadays we copy it
- during initialization. */
- XtFree (mw->menu.contents);
-#endif
-
- /* Don't free mw->menu.contents because that comes from our creator.
- The `*_stack' elements are just pointers into `contents' so leave
- that alone too. But free the stacks themselves. */
- if (mw->menu.old_stack) XtFree ((char *) mw->menu.old_stack);
- if (mw->menu.new_stack) XtFree ((char *) mw->menu.new_stack);
-
- /* Remember, you can't free anything that came from the resource
- database. This includes:
- mw->menu.cursor
- mw->menu.top_shadow_pixmap
- mw->menu.bottom_shadow_pixmap
- mw->menu.font
- Also the color cells of top_shadow_color, bottom_shadow_color,
- foreground, and button_foreground will never be freed until this
- client exits. Nice, eh?
- */
-
- /* start from 1 because the one in slot 0 is w->core.window */
- for (i = 1; i < mw->menu.windows_length; i++)
- XDestroyWindow (XtDisplay (mw), mw->menu.windows [i].window);
- if (mw->menu.windows)
- XtFree ((char *) mw->menu.windows);
-}
-
-static Boolean
-XlwMenuSetValues (current, request, new)
- Widget current;
- Widget request;
- Widget new;
-{
- XlwMenuWidget oldmw = (XlwMenuWidget)current;
- XlwMenuWidget newmw = (XlwMenuWidget)new;
- Boolean redisplay = False;
- int i;
-
- if (newmw->menu.contents
- && newmw->menu.contents->contents
- && newmw->menu.contents->contents->change >= VISIBLE_CHANGE)
- redisplay = True;
- /* Do redisplay if the contents are entirely eliminated. */
- if (newmw->menu.contents
- && newmw->menu.contents->contents == 0
- && newmw->menu.contents->change >= VISIBLE_CHANGE)
- redisplay = True;
-
- if (newmw->core.background_pixel != oldmw->core.background_pixel
- || newmw->menu.foreground != oldmw->menu.foreground
- || newmw->menu.font != oldmw->menu.font)
- {
- release_drawing_gcs (newmw);
- make_drawing_gcs (newmw);
- redisplay = True;
-
- for (i = 0; i < oldmw->menu.windows_length; i++)
- {
- XSetWindowBackground (XtDisplay (oldmw),
- oldmw->menu.windows [i].window,
- newmw->core.background_pixel);
- /* clear windows and generate expose events */
- XClearArea (XtDisplay (oldmw), oldmw->menu.windows[i].window,
- 0, 0, 0, 0, True);
- }
- }
-
- return redisplay;
-}
-
-static void
-XlwMenuResize (w)
- Widget w;
-{
- XlwMenuWidget mw = (XlwMenuWidget)w;
-
- if (mw->menu.popped_up)
- {
- /* Don't allow the popup menu to resize itself. */
- mw->core.width = mw->menu.windows [0].width;
- mw->core.height = mw->menu.windows [0].height;
- mw->core.parent->core.width = mw->core.width ;
- mw->core.parent->core.height = mw->core.height ;
- }
- else
- {
- mw->menu.windows [0].width = mw->core.width;
- mw->menu.windows [0].height = mw->core.height;
- }
-}
-
- /* Action procedures */
-static void
-handle_single_motion_event (mw, ev)
- XlwMenuWidget mw;
- XMotionEvent* ev;
-{
- widget_value* val;
- int level;
-
- if (!map_event_to_widget_value (mw, ev, &val, &level))
- pop_new_stack_if_no_contents (mw);
- else
- set_new_state (mw, val, level);
- remap_menubar (mw);
-
- /* Sync with the display. Makes it feel better on X terms. */
- XSync (XtDisplay (mw), False);
-}
-
-static void
-handle_motion_event (mw, ev)
- XlwMenuWidget mw;
- XMotionEvent* ev;
-{
- int x = ev->x_root;
- int y = ev->y_root;
- int state = ev->state;
-
- handle_single_motion_event (mw, ev);
-
- /* allow motion events to be generated again */
- if (ev->is_hint
- && XQueryPointer (XtDisplay (mw), ev->window,
- &ev->root, &ev->subwindow,
- &ev->x_root, &ev->y_root,
- &ev->x, &ev->y,
- &ev->state)
- && ev->state == state
- && (ev->x_root != x || ev->y_root != y))
- handle_single_motion_event (mw, ev);
-}
-
-static void
-Start (w, ev, params, num_params)
- Widget w;
- XEvent *ev;
- String *params;
- Cardinal *num_params;
-{
- XlwMenuWidget mw = (XlwMenuWidget)w;
-
- if (!mw->menu.popped_up)
- {
- menu_post_event = *ev;
- pop_up_menu (mw, ev);
- }
- else
- {
- /* If we push a button while the menu is posted semipermanently,
- releasing the button should always pop the menu down. */
- next_release_must_exit = 1;
-
- /* notes the absolute position of the menubar window */
- mw->menu.windows [0].x = ev->xmotion.x_root - ev->xmotion.x;
- mw->menu.windows [0].y = ev->xmotion.y_root - ev->xmotion.y;
-
- /* handles the down like a move, slots are compatible */
- handle_motion_event (mw, &ev->xmotion);
- }
-}
-
-static void
-Drag (w, ev, params, num_params)
- Widget w;
- XEvent *ev;
- String *params;
- Cardinal *num_params;
-{
- XlwMenuWidget mw = (XlwMenuWidget)w;
- if (mw->menu.popped_up)
- handle_motion_event (mw, &ev->xmotion);
-}
-
-/* Do nothing.
- This is how we handle presses and releases of modifier keys. */
-static void
-Nothing (w, ev, params, num_params)
- Widget w;
- XEvent *ev;
- String *params;
- Cardinal *num_params;
-{
-}
-
-/* Handle key press and release events while menu is popped up.
- Our action is to get rid of the menu. */
-static void
-Key (w, ev, params, num_params)
- Widget w;
- XEvent *ev;
- String *params;
- Cardinal *num_params;
-{
- XlwMenuWidget mw = (XlwMenuWidget)w;
-
- /* Pop down everything. */
- mw->menu.new_depth = 1;
- remap_menubar (mw);
-
- if (mw->menu.popped_up)
- {
- mw->menu.popped_up = False;
- XtUngrabPointer ((Widget)mw, ev->xmotion.time);
- if (XtIsShell (XtParent ((Widget) mw)))
- XtPopdown (XtParent ((Widget) mw));
- else
- {
- XtRemoveGrab ((Widget) mw);
- display_menu (mw, 0, False, NULL, NULL, NULL, NULL, NULL);
- }
- }
-
- /* callback */
- XtCallCallbackList ((Widget)mw, mw->menu.select, (XtPointer)0);
-}
-
-static void
-Select (w, ev, params, num_params)
- Widget w;
- XEvent *ev;
- String *params;
- Cardinal *num_params;
-{
- XlwMenuWidget mw = (XlwMenuWidget)w;
- widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1];
-
- /* If user releases the button quickly, without selecting anything,
- after the initial down-click that brought the menu up,
- do nothing. */
- if ((selected_item == 0
- || ((widget_value *) selected_item)->call_data == 0)
- && !next_release_must_exit
- && (ev->xbutton.time - menu_post_event.xbutton.time
- < XtGetMultiClickTime (XtDisplay (w))))
- return;
-
- /* pop down everything. */
- mw->menu.new_depth = 1;
- remap_menubar (mw);
-
- if (mw->menu.popped_up)
- {
- mw->menu.popped_up = False;
- XtUngrabPointer ((Widget)mw, ev->xmotion.time);
- if (XtIsShell (XtParent ((Widget) mw)))
- XtPopdown (XtParent ((Widget) mw));
- else
- {
- XtRemoveGrab ((Widget) mw);
- display_menu (mw, 0, False, NULL, NULL, NULL, NULL, NULL);
- }
- }
-
- /* callback */
- XtCallCallbackList ((Widget)mw, mw->menu.select, (XtPointer)selected_item);
-}
-
-
- /* Special code to pop-up a menu */
-void
-pop_up_menu (mw, event)
- XlwMenuWidget mw;
- XButtonPressedEvent* event;
-{
- int x = event->x_root;
- int y = event->y_root;
- int w;
- int h;
- int borderwidth = mw->menu.shadow_thickness;
- Screen* screen = XtScreen (mw);
- Display *display = XtDisplay (mw);
-
- next_release_must_exit = 0;
-
- XtCallCallbackList ((Widget)mw, mw->menu.open, NULL);
-
- if (XtIsShell (XtParent ((Widget)mw)))
- size_menu (mw, 0);
-
- w = mw->menu.windows [0].width;
- h = mw->menu.windows [0].height;
-
- x -= borderwidth;
- y -= borderwidth;
- if (x < borderwidth)
- x = borderwidth;
- if (x + w + 2 * borderwidth > WidthOfScreen (screen))
- x = WidthOfScreen (screen) - w - 2 * borderwidth;
- if (y < borderwidth)
- y = borderwidth;
- if (y + h + 2 * borderwidth> HeightOfScreen (screen))
- y = HeightOfScreen (screen) - h - 2 * borderwidth;
-
- mw->menu.popped_up = True;
- if (XtIsShell (XtParent ((Widget)mw)))
- {
- XtConfigureWidget (XtParent ((Widget)mw), x, y, w, h,
- XtParent ((Widget)mw)->core.border_width);
- XtPopup (XtParent ((Widget)mw), XtGrabExclusive);
- display_menu (mw, 0, False, NULL, NULL, NULL, NULL, NULL);
- mw->menu.windows [0].x = x + borderwidth;
- mw->menu.windows [0].y = y + borderwidth;
- }
- else
- {
- XEvent *ev = (XEvent *) event;
-
- XtAddGrab ((Widget) mw, True, True);
-
- /* notes the absolute position of the menubar window */
- mw->menu.windows [0].x = ev->xmotion.x_root - ev->xmotion.x;
- mw->menu.windows [0].y = ev->xmotion.y_root - ev->xmotion.y;
- }
-
-#ifdef emacs
- x_catch_errors (display);
-#endif
- XtGrabPointer ((Widget)mw, False,
- (PointerMotionMask
- | PointerMotionHintMask
- | ButtonReleaseMask
- | ButtonPressMask),
- GrabModeAsync, GrabModeAsync, None,
- mw->menu.cursor_shape,
- event->time);
- pointer_grabbed = 1;
-#ifdef emacs
- if (x_had_errors_p (display))
- {
- pointer_grabbed = 0;
- XtUngrabPointer ((Widget)mw, event->time);
- }
- x_uncatch_errors (display);
-#endif
-
- handle_motion_event (mw, (XMotionEvent*)event);
-}
diff --git a/lwlib/xlwmenu.h b/lwlib/xlwmenu.h
deleted file mode 100644
index 949fbf76589..00000000000
--- a/lwlib/xlwmenu.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef _XlwMenu_h
-#define _XlwMenu_h
-
-/***********************************************************************
- *
- * XlwMenu Widget
- *
- ***********************************************************************/
-
-#include "lwlib.h"
-
-/* Resource names used by the XlwMenu widget */
-#define XtNbuttonForeground "buttonForeground"
-#define XtCButtonForeground "ButtonForeground"
-#define XtNmargin "margin"
-#define XtNhorizontalSpacing "horizontalSpacing"
-#define XtNverticalSpacing "verticalSpacing"
-#define XtNarrowSpacing "arrowSpacing"
-#define XtNmenu "menu"
-#define XtCMenu "Menu"
-#define XtNopen "open"
-#define XtNselect "select"
-#define XtNmenuBorderWidth "menuBorderWidth"
-#define XtNhorizontal "horizontal"
-#define XtCHorizontal "Horizontal"
-#define XtNcursor "cursor"
-#define XtNCursor "Cursor"
-#define XtNshowGrip "showGrip"
-#define XtCShowGrip "ShowGrip"
-#define XtNresizeToPreferred "resizeToPreferred"
-#define XtCResizeToPreferred "ResizeToPreferred"
-#define XtNallowResize "allowResize"
-#define XtCAllowResize "AllowResize"
-
-/* Motif-compatible resource names */
-#define XmNshadowThickness "shadowThickness"
-#define XmCShadowThickness "ShadowThickness"
-#define XmNtopShadowColor "topShadowColor"
-#define XmCTopShadowColor "TopShadowColor"
-#define XmNbottomShadowColor "bottomShadowColor"
-#define XmCBottomShadowColor "BottomShadowColor"
-#define XmNtopShadowPixmap "topShadowPixmap"
-#define XmCTopShadowPixmap "TopShadowPixmap"
-#define XmNbottomShadowPixmap "bottomShadowPixmap"
-#define XmCBottomShadowPixmap "BottomShadowPixmap"
-#define XmRHorizontalDimension "HorizontalDimension"
-
-typedef struct _XlwMenuRec *XlwMenuWidget;
-typedef struct _XlwMenuClassRec *XlwMenuWidgetClass;
-
-extern WidgetClass xlwMenuWidgetClass;
-
-void
-pop_up_menu ();
-
-#endif /* _XlwMenu_h */
diff --git a/lwlib/xlwmenuP.h b/lwlib/xlwmenuP.h
deleted file mode 100644
index 79f454fefc4..00000000000
--- a/lwlib/xlwmenuP.h
+++ /dev/null
@@ -1,91 +0,0 @@
-#ifndef _XlwMenuP_h
-#define _XlwMenuP_h
-
-#include "xlwmenu.h"
-#include <X11/CoreP.h>
-
-/* Elements in the stack arrays. */
-typedef struct _window_state
-{
- Window window;
- Position x;
- Position y;
- Dimension width;
- Dimension height;
- Dimension label_width;
-} window_state;
-
-
-/* New fields for the XlwMenu widget instance record */
-typedef struct _XlwMenu_part
-{
- /* slots set by the resources */
- XFontStruct* font;
- Pixel foreground;
- Pixel button_foreground;
- Dimension margin;
- Dimension horizontal_spacing;
- Dimension vertical_spacing;
- Dimension arrow_spacing;
- Dimension shadow_thickness;
- Pixel top_shadow_color;
- Pixel bottom_shadow_color;
- Pixmap top_shadow_pixmap;
- Pixmap bottom_shadow_pixmap;
- Cursor cursor_shape;
- XtCallbackList open;
- XtCallbackList select;
- widget_value* contents;
- int horizontal;
-
- /* State of the XlwMenu */
- int old_depth;
- widget_value** old_stack;
- int old_stack_length;
-
- /* New state after the user moved */
- int new_depth;
- widget_value** new_stack;
- int new_stack_length;
-
- /* Window resources */
- window_state* windows;
- int windows_length;
-
- /* Internal part, set by the XlwMenu */
- GC foreground_gc;
- GC button_gc;
- GC background_gc;
- GC inactive_gc;
- GC inactive_button_gc;
- GC shadow_top_gc;
- GC shadow_bottom_gc;
- Cursor cursor;
- Boolean popped_up;
- Pixmap gray_pixmap;
-} XlwMenuPart;
-
-/* Full instance record declaration */
-typedef struct _XlwMenuRec
-{
- CorePart core;
- XlwMenuPart menu;
-} XlwMenuRec;
-
-/* New fields for the XlwMenu widget class record */
-typedef struct
-{
- int dummy;
-} XlwMenuClassPart;
-
-/* Full class record declaration. */
-typedef struct _XlwMenuClassRec
-{
- CoreClassPart core_class;
- XlwMenuClassPart menu_class;
-} XlwMenuClassRec;
-
-/* Class pointer. */
-extern XlwMenuClassRec xlwMenuClassRec;
-
-#endif /* _XlwMenuP_h */
diff --git a/make-dist b/make-dist
deleted file mode 100755
index 6acc8d51390..00000000000
--- a/make-dist
+++ /dev/null
@@ -1,495 +0,0 @@
-#!/bin/sh
-
-#### make-dist: create an Emacs distribution tar file from the current
-#### source tree. This basically creates a duplicate directory
-#### structure, and then hard links into it only those files that should
-#### be distributed. This means that if you add a file with an odd name,
-#### you should make sure that this script will include it.
-
-# Copyright (C) 1995 Free Software Foundation, Inc.
-#
-# This file is part of GNU Emacs.
-#
-# GNU Emacs is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# GNU Emacs is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Emacs; see the file COPYING. If not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-progname="$0"
-
-### Exit if a command fails.
-### set -e
-
-### Print out each line we read, for debugging's sake.
-### set -v
-
-update=yes
-clean_up=no
-make_tar=no
-newer=""
-
-while [ $# -gt 0 ]; do
- case "$1" in
- ## This option tells make-dist to delete the staging directory
- ## when done. It is useless to use this unless you make a tar file.
- "--clean-up" )
- clean_up=yes
- ;;
- ## This option tells make-dist to make a tar file.
- "--tar" )
- make_tar=yes
- ;;
- ## This option tells make-dist not to recompile or do analogous things.
- "--no-update" )
- update=no
- ;;
- ## This option tells make-dist to make the distribution normally, then
- ## remove all files older than the given timestamp file. This is useful
- ## for creating incremental or patch distributions.
- "--newer")
- newer="$2"
- new_extension=".new"
- shift
- ;;
- ## This option tells make-dist to use `compress' instead of gzip.
- ## Normally, make-dist uses gzip whenever it is present.
- "--compress")
- default_gzip="compress"
- ;;
- * )
- echo "${progname}: Unrecognized argument: $1" >&2
- exit 1
- ;;
- esac
- shift
-done
-
-### Make sure we're running in the right place.
-if [ ! -d src -o ! -f src/lisp.h -o ! -d lisp -o ! -f lisp/version.el ]; then
- echo "${progname}: Can't find \`src/lisp.h' and \`lisp/version.el'." >&2
- echo "${progname} must be run in the top directory of the Emacs" >&2
- echo "distribution tree. cd to that directory and try again." >&2
- exit 1
-fi
-
-### Find where to run Emacs.
-if [ $update = yes ];
-then
- if [ -f src/emacs ];
- then
- EMACS=`pwd`/src/emacs
- else
- if [ x$EMACS = x ];
- then
- echo You must specify the EMACS environment variable 2>&1
- exit 1
- fi
- fi
-fi
-
-### Find out which version of Emacs this is.
-shortversion=`grep 'defconst[ ]*emacs-version' lisp/version.el \
- | sed -e 's/^.*"\([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/'`
-version=`grep 'defconst[ ]*emacs-version' lisp/version.el \
- | sed -e 's/^[^"]*"\([^"]*\)".*$/\1/'`
-if [ ! "${version}" ]; then
- echo "${progname}: can't find current Emacs version in \`./lisp/version.el'" >&2
- exit 1
-fi
-
-echo Version numbers are $version and $shortversion
-
-if [ $update = yes ];
-then
- if grep -s "GNU Emacs version ${shortversion}" ./man/emacs.texi > /dev/null; then
- true
- else
- echo "You must update the version number in \`./man/emacs.texi'"
- sleep 5
- fi
-fi
-
-### Make sure we don't already have a directory emacs-${version}.
-
-emacsname="emacs-${version}${new_extension}"
-
-if [ -d ${emacsname} ]
-then
- echo Directory "${emacsname}" already exists >&2
- exit 1
-fi
-
-### Make sure the subdirectory is available.
-tempparent="make-dist.tmp.$$"
-if [ -d ${tempparent} ]; then
- echo "${progname}: staging directory \`${tempparent}' already exists.
-Perhaps a previous invocation of \`${progname}' failed to clean up after
-itself. Check that directories whose names are of the form
-\`make-dist.tmp.NNNNN' don't contain any important information, remove
-them, and try again." >&2
- exit 1
-fi
-
-### Check for .elc files with no corresponding .el file.
-ls -1 lisp/*.el | sed 's/\.el$/.elc/' > /tmp/el
-ls -1 lisp/*.elc > /tmp/elc
-bogosities="`comm -13 /tmp/el /tmp/elc`"
-if [ "${bogosities}" != "" ]; then
- echo "The following .elc files have no corresponding .el files:"
- echo "${bogosities}"
-fi
-rm -f /tmp/el /tmp/elc
-
-### Check for .el files that would overflow the 14-char limit if compiled.
-long=`find lisp -name '[a-zA-Z0-9]??????????*.el' -print`
-if [ "$long" != "" ]; then
- echo "The following .el file names are too long:"
- echo "$long"
-fi
-
-### Make sure configure is newer than configure.in.
-if [ "x`ls -t configure configure.in | head -1`" != "xconfigure" ]; then
- echo "\`./configure.in' is newer than \`./configure'" >&2
- echo "Running autoconf" >&2
- autoconf || { x=$?; echo Autoconf FAILED! >&2; exit $x; }
-fi
-
-if [ $update = yes ];
-then
- echo "Updating Info files"
-
- (cd man; make info)
-
- echo "Updating finder-inf.el"
-
- (cd lisp; $EMACS -batch -l finder -f finder-compile-keywords-make-dist)
-
- echo "Recompiling Lisp files"
-
- $EMACS -batch -f batch-byte-recompile-directory lisp
-
- echo "Updating autoloads"
-
- $EMACS -batch -f batch-update-autoloads lisp
-fi
-
-echo "Making lisp/MANIFEST"
-
-(cd lisp; head -1 [!=]*.el | grep '^;' | sed -e 's/;;; //' > MANIFEST)
-
-echo "Creating staging directory: \`${tempparent}'"
-
-mkdir ${tempparent}
-tempdir="${tempparent}/${emacsname}"
-
-### This trap ensures that the staging directory will be cleaned up even
-### when the script is interrupted in mid-career.
-if [ "${clean_up}" = yes ]; then
- trap "echo 'Interrupted...cleaning up the staging directory'; rm -rf ${tempparent}; exit 1" 1 2 15
-fi
-
-echo "Creating top directory: \`${tempdir}'"
-mkdir ${tempdir}
-
-### We copy in the top-level files before creating the subdirectories in
-### hopes that this will make the top-level files appear first in the
-### tar file; this means that people can start reading the INSTALL and
-### README while the rest of the tar file is still unpacking. Whoopee.
-echo "Making links to top-level files"
-ln GETTING.GNU.SOFTWARE INSTALL PROBLEMS README BUGS move-if-change ${tempdir}
-ln ChangeLog Makefile.in configure configure.in ${tempdir}
-ln config.bat make-dist update-subdirs vpath.sed ${tempdir}
-### Copy these files; they're cross-filesystem symlinks.
-cp mkinstalldirs ${tempdir}
-cp config.sub ${tempdir}
-cp config.guess ${tempdir}
-cp install.sh ${tempdir}
-
-echo "Updating version number in README"
-(cd ${tempdir}
- awk \
- '$1 " " $2 " " $3 " " $4 " " $5 == "This directory tree holds version" { $6 = version; print $0 }
- $1 " " $2 " " $3 " " $4 " " $5 != "This directory tree holds version"' \
- version=${version} README > tmp.README
- mv tmp.README README)
-
-
-echo "Creating subdirectories"
-for subdir in lisp lisp/term site-lisp \
- src src/m src/s src/bitmaps lib-src oldXMenu lwlib \
- nt nt/inc nt/inc/sys nt/inc/arpa nt/inc/netinet \
- etc etc/e lock cpp info man msdos vms; do
- mkdir ${tempdir}/${subdir}
-done
-
-echo "Making links to \`lisp'"
-### Don't distribute TAGS, =*.el files, site-init.el, site-load.el, or default.el.
-(cd lisp
- ln [a-zA-Z]*.el ../${tempdir}/lisp
- ln [a-zA-Z]*.elc ../${tempdir}/lisp
- ln [a-zA-Z]*.dat ../${tempdir}/lisp
- ## simula.el doesn't keep abbreviations in simula.defns any more.
- ## ln [a-zA-Z]*.defns ../${tempdir}/lisp
- ln ChangeLog Makefile makefile.nt ChangeLog.? README ../${tempdir}/lisp
- cd ../${tempdir}/lisp
- rm -f TAGS =*
- rm -f subdirs.el
- rm -f site-init site-init.el site-init.elc
- rm -f site-load site-load.el site-load.elc
- rm -f site-start site-start.el site-start.elc
- rm -f default default.el default.elc)
-
-#echo "Making links to \`lisp/calc-2.02'"
-#### Don't distribute =*.el files, TAGS or backups.
-#(cd lisp/calc-2.02
-# ln [a-zA-Z]*.el ../../${tempdir}/lisp/calc-2.02
-# ln [a-zA-Z]*.elc ../../${tempdir}/lisp/calc-2.02
-# ln calc.info* calc.texinfo calc-refcard.* ../../${tempdir}/lisp/calc-2.02
-# ln INSTALL Makefile README README.prev ../../${tempdir}/lisp/calc-2.02
-# cd ../../${tempdir}/lisp/calc-2.02
-# rm -f *~ TAGS)
-
-echo "Making links to \`lisp/term'"
-### Don't distribute =*.el files or TAGS.
-(cd lisp/term
- ln [a-zA-Z]*.el ../../${tempdir}/lisp/term
- ln [a-zA-Z]*.elc ../../${tempdir}/lisp/term
- ln README ../../${tempdir}/lisp/term
- rm -f =* TAGS)
-
-echo "Making links to \`src'"
-### Don't distribute =*.[ch] files, or the configured versions of
-### config.in, paths.in, or Makefile.in, or TAGS.
-(cd src
- echo " (It is ok if ln fails in some cases.)"
- ln [a-zA-Z]*.c ../${tempdir}/src
- ln [a-zA-Z]*.h ../${tempdir}/src
- ln [a-zA-Z]*.s ../${tempdir}/src
- ln [a-zA-Z]*.in ../${tempdir}/src
- ln [a-zA-Z]*.opt ../${tempdir}/src
- ## If we ended up with a symlink, or if we did not get anything
- ## due to a cross-device symlink, copy the file.
- for file in [a-zA-Z]*.[hcs] [a-zA-Z]*.in [a-zA-Z]*.opt; do
- if test -f ../${tempdir}/src/$file; then
- # test -f appears to succeed for a symlink
- if test -L ../${tempdir}/src/$file; then
- rm ../${tempdir}/src/$file
- cp $file ../${tempdir}/src
- chmod a-w ../${tempdir}/src/$file
- fi
- else
- rm ../${tempdir}/src/$file
- cp $file ../${tempdir}/src
- chmod a-w ../${tempdir}/src/$file
- fi
- done
- ln README ChangeLog ChangeLog.*[0-9] ../${tempdir}/src
- ln makefile.nt vms-pp.trans ../${tempdir}/src
- ln .gdbinit .dbxinit ../${tempdir}/src
- cd ../${tempdir}/src
- rm -f config.h paths.h Makefile Makefile.c
- rm -f =* TAGS)
-
-echo "Making links to \`src/bitmaps'"
-(cd src/bitmaps
- ln README *.xbm ../../${tempdir}/src/bitmaps)
-
-echo "Making links to \`src/m'"
-(cd src/m
- # We call files for miscellaneous input (to linker etc) .inp.
- ln README [a-zA-Z0-9]*.h *.inp ../../${tempdir}/src/m)
-
-echo "Making links to \`src/s'"
-(cd src/s
- ln README [a-zA-Z0-9]*.h ../../${tempdir}/src/s)
-
-echo "Making links to \`lib-src'"
-(cd lib-src
- ln [a-zA-Z]*.[chy] ../${tempdir}/lib-src
- ln ChangeLog Makefile.in README testfile vcdiff ../${tempdir}/lib-src
- ln emacs.csh rcs2log rcs-checkin makefile.nt ../${tempdir}/lib-src
- ## If we ended up with a symlink, or if we did not get anything
- ## due to a cross-device symlink, copy the file.
- for file in [a-zA-Z]*.[chy]; do
- if test -f ../${tempdir}/lib-src/$file; then
- # test -f appears to succeed for a symlink
- if test -L ../${tempdir}/lib-src/$file; then
- rm ../${tempdir}/lib-src/$file
- cp $file ../${tempdir}/lib-src
- chmod a-w ../${tempdir}/lib-src/$file
- fi
- else
- rm ../${tempdir}/lib-src/$file
- cp $file ../${tempdir}/lib-src
- chmod a-w ../${tempdir}/lib-src/$file
- fi
- done
- cd ../${tempdir}/lib-src
- rm -f Makefile.c
- rm -f =* TAGS)
-
-echo "Making links to \`nt'"
-(cd nt
- ln emacs.ico emacs.rc config.nt [a-z]*.in [a-z]*.c ../${tempdir}/nt
- ln [a-z]*.bat [a-z]*.h makefile.def makefile.nt ../${tempdir}/nt
- ln TODO ChangeLog INSTALL README ../${tempdir}/nt)
-
-echo "Making links to \`nt/inc'"
-(cd nt/inc
- ln [a-z]*.h ../../${tempdir}/nt/inc)
-
-echo "Making links to \`nt/inc/sys'"
-(cd nt/inc/sys
- ln [a-z]*.h ../../../${tempdir}/nt/inc/sys)
-
-echo "Making links to \`nt/inc/arpa'"
-(cd nt/inc/arpa
- ln [a-z]*.h ../../../${tempdir}/nt/inc/arpa)
-
-echo "Making links to \`nt/inc/netinet'"
-(cd nt/inc/netinet
- ln [a-z]*.h ../../../${tempdir}/nt/inc/netinet)
-
-echo "Making links to \`msdos'"
-(cd msdos
- ln ChangeLog emacs.ico emacs.pif ../${tempdir}/msdos
- ln is_exec.c sigaction.c mainmake mainmake.v2 sed*.inp ../${tempdir}/msdos
- cd ../${tempdir}/msdos
- rm -f =*)
-
-echo "Making links to \`oldXMenu'"
-(cd oldXMenu
- ln *.c *.h *.in ../${tempdir}/oldXMenu
- ln README Imakefile ChangeLog ../${tempdir}/oldXMenu
- ln compile.com descrip.mms ../${tempdir}/oldXMenu)
-
-echo "Making links to \`lwlib'"
-(cd lwlib
- ln *.c *.h *.in ../${tempdir}/lwlib
- ln README Imakefile ChangeLog ../${tempdir}/lwlib
- cd ../${tempdir}/lwlib
- rm -f lwlib-Xol*)
-
-echo "Making links to \`etc'"
-### Don't distribute = files, TAGS, DOC files, backups, autosaves, or
-### tex litter.
-(cd etc
- ln `ls -d * | grep -v 'RCS' | grep -v 'Old' | grep -v '^e$'` ../${tempdir}/etc
- cd ../${tempdir}/etc
- rm -f DOC* *~ \#*\# *.dvi *.log *.orig *.rej *,v =* core
- rm -f TAGS)
-
-echo "Making links to \`etc/e'"
-(cd etc/e
- ln `ls -d * | grep -v 'RCS'` ../../${tempdir}/etc/e
- cd ../../${tempdir}/etc/e
- rm -f *~ \#*\# *,v =* core)
-
-echo "Making links to \`cpp'"
-(cd cpp
- ln cccp.c cexp.y Makefile README ../${tempdir}/cpp)
-
-echo "Making links to \`info'"
-# Don't distribute backups or autosaves.
-(cd info
- ln [a-zA-Z]* ../${tempdir}/info
- cd ../${tempdir}/info
- # Avoid an error when expanding the wildcards later.
- ln emacs dummy~ ; ln emacs \#dummy\#
- rm -f *~ \#*\# core)
-
-echo "Making links to \`man'"
-(cd man
- ln *.texi *.aux *.cps *.fns *.kys *.vrs ../${tempdir}/man
- test -f README && ln README ../${tempdir}/man
- test -f Makefile.in && ln Makefile.in ../${tempdir}/man
- ln ChangeLog split-man ../${tempdir}/man
- cp texinfo.tex ../${tempdir}/man
- cd ../${tempdir}/man
- rm -f \#*\# =* *~ core emacs-index* *.Z *.z xmail
- rm -f emacs.?? termcap.?? gdb.?? *.log *.toc *.dvi *.oaux)
-
-echo "Making links to \`vms'"
-(cd vms
- ln [0-9a-zA-Z]* ../${tempdir}/vms
- cd ../${tempdir}/vms
- rm -f *~)
-
-### It would be nice if they could all be symlinks to etc's copy, but
-### you're not supposed to have any symlinks in distribution tar files.
-echo "Making sure copying notices are all copies of \`etc/COPYING'"
-rm -f ${tempdir}/etc/COPYING
-cp etc/COPYING ${tempdir}/etc/COPYING
-for subdir in lisp src lib-src info msdos; do
- if [ -f ${tempdir}/${subdir}/COPYING ]; then
- rm ${tempdir}/${subdir}/COPYING
- fi
- cp etc/COPYING ${tempdir}/${subdir}
-done
-
-#### Make sure that there aren't any hard links between files in the
-#### distribution; people with afs can't deal with that. Okay,
-#### actually we just re-copy anything with a link count greater
-#### than two. (Yes, strictly greater than 2 is correct; since we
-#### created these files by linking them in from the original tree,
-#### they'll have exactly two links normally.)
-####
-#### Commented out since it's not strictly necessary; it should suffice
-#### to just break the link on alloca.c.
-#echo "Breaking intra-tree links."
-#find ${tempdir} ! -type d -links +2 \
-# -exec cp -p {} $$ \; -exec rm -f {} \; -exec mv $$ {} \;
-rm -f $tempdir/lib-src/alloca.c
-cp $tempdir/src/alloca.c $tempdir/lib-src/alloca.c
-
-if [ "${newer}" ]; then
- echo "Removing files older than $newer"
- ## We remove .elc files unconditionally, on the theory that anyone picking
- ## up an incremental distribution already has a running Emacs to byte-compile
- ## them with.
- find ${tempparent} \( -name '*.elc' -o ! -newer ${newer} \) -exec rm -f {} \;
-fi
-
-if [ "${make_tar}" = yes ]; then
- if [ "${default_gzip}" = "" ]; then
- echo "Looking for gzip"
- temppath=`echo $PATH | sed 's/^:/.:/
- s/::/:.:/g
- s/:$/:./
- s/:/ /g'`
- default_gzip=`(
- for dir in ${temppath}; do
- if [ -f ${dir}/gzip ]; then echo 'gzip --best'; exit 0; fi
- done
- echo compress
- )`
- fi
- case "${default_gzip}" in
- compress* ) gzip_extension=.Z ;;
- * ) gzip_extension=.gz ;;
- esac
- echo "Creating tar file"
- (cd ${tempparent} ; tar cvf - ${emacsname} ) \
- | ${default_gzip} \
- > ${emacsname}.tar${gzip_extension}
-fi
-
-if [ "${clean_up}" = yes ]; then
- echo "Cleaning up the staging directory"
- rm -rf ${tempparent}
-else
- (cd ${tempparent}; mv ${emacsname} ..)
- rm -rf ${tempparent}
-fi
-
-### make-dist ends here
diff --git a/man/Makefile.in b/man/Makefile.in
deleted file mode 100644
index 9fdebc7e1cc..00000000000
--- a/man/Makefile.in
+++ /dev/null
@@ -1,166 +0,0 @@
-#### Makefile for the Emacs Manual and other documentation.
-
-# Where to find the source code. The source code for Emacs's C kernel is
-# expected to be in ${srcdir}/src, and the source code for Emacs's
-# utility programs is expected to be in ${srcdir}/lib-src. This is
-# set by the configure script's `--srcdir' option.
-srcdir=@srcdir@
-
-# Tell make where to find source files; this is needed for the makefiles.
-VPATH=@srcdir@
-
-
-# The makeinfo program is part of the Texinfo distribution.
-MAKEINFO = makeinfo
-INFO_TARGETS = ../info/emacs ../info/ccmode ../info/cl ../info/dired-x \
- ../info/ediff ../info/forms ../info/gnus ../info/info \
- ../info/mh-e ../info/sc ../info/vip ../info/viper \
- ../info/message
-DVI_TARGETS = emacs.dvi cc-mode.dvi cl.dvi dired-x.dvi ediff.dvi forms.dvi \
- gnus.dvi mh-e.dvi sc.dvi vip.dvi viper.dvi message.dvi
-INFOSOURCES = info.texi info-stnd.texi
-
-# The following rule does not work with all versions of `make'.
-.SUFFIXES: .texi .dvi
-.texi.dvi:
- texi2dvi $<
-
-TEXI2DVI = texi2dvi
-
-EMACSSOURCES= \
- ${srcdir}/emacs.texi \
- ${srcdir}/screen.texi \
- ${srcdir}/commands.texi \
- ${srcdir}/entering.texi \
- ${srcdir}/basic.texi \
- ${srcdir}/mini.texi \
- ${srcdir}/m-x.texi \
- ${srcdir}/help.texi \
- ${srcdir}/mark.texi \
- ${srcdir}/killing.texi \
- ${srcdir}/regs.texi \
- ${srcdir}/display.texi \
- ${srcdir}/search.texi \
- ${srcdir}/fixit.texi \
- ${srcdir}/files.texi \
- ${srcdir}/buffers.texi \
- ${srcdir}/windows.texi \
- ${srcdir}/frames.texi \
- ${srcdir}/major.texi \
- ${srcdir}/indent.texi \
- ${srcdir}/text.texi \
- ${srcdir}/programs.texi \
- ${srcdir}/building.texi \
- ${srcdir}/abbrevs.texi \
- ${srcdir}/picture.texi \
- ${srcdir}/sending.texi \
- ${srcdir}/rmail.texi \
- ${srcdir}/dired.texi \
- ${srcdir}/calendar.texi \
- ${srcdir}/misc.texi \
- ${srcdir}/custom.texi \
- ${srcdir}/trouble.texi \
- ${srcdir}/cmdargs.texi \
- ${srcdir}/anti.texi \
- ${srcdir}/gnu.texi \
- ${srcdir}/gnu1.texi \
- ${srcdir}/glossary.texi
-
-info: $(INFO_TARGETS)
-
-dvi: $(DVI_TARGETS)
-
-# Note that all the Info targets build the Info files
-# in srcdir. There is no provision for Info files
-# to exist in the build directory.
-# In a distribution of Emacs, the Info files should be up to date.
-
-../info/info: ${INFOSOURCES}
- cd $(srcdir); $(MAKEINFO) --no-split info.texi
-
-info.dvi: ${INFOSOURCES}
- TEXINPUTS="$(srcdir) $(TEXINPUTS)"; $(TEXI2DVI) ${srcdir}/info.texi
-
-../info/emacs: ${EMACSSOURCES}
- cd $(srcdir); $(MAKEINFO) emacs.texi
-
-emacs.dvi: ${EMACSSOURCES}
- TEXINPUTS="$(srcdir) $(TEXINPUTS)"; $(TEXI2DVI) ${srcdir}/emacs.texi
-
-../info/ccmode: cc-mode.texi
- cd $(srcdir); $(MAKEINFO) cc-mode.texi
-cc-mode.dvi: cc-mode.texi
- TEXINPUTS="$(srcdir) $(TEXINPUTS)"; $(TEXI2DVI) ${srcdir}/cc-mode.texi
-
-../info/cl: cl.texi
- cd $(srcdir); $(MAKEINFO) cl.texi
-cl.dvi: cl.texi
- TEXINPUTS="$(srcdir) $(TEXINPUTS)"; $(TEXI2DVI) ${srcdir}/cl.texi
-
-../info/dired-x: dired-x.texi
- cd $(srcdir); $(MAKEINFO) dired-x.texi
-dired-x.dvi: dired-x.texi
- TEXINPUTS="$(srcdir) $(TEXINPUTS)"; $(TEXI2DVI) ${srcdir}/dired-x.texi
-
-../info/ediff: ediff.texi
- cd $(srcdir); $(MAKEINFO) ediff.texi
-ediff.dvi: ediff.texi
- TEXINPUTS="$(srcdir) $(TEXINPUTS)"; $(TEXI2DVI) ${srcdir}/ediff.texi
-
-../info/forms: forms.texi
- cd $(srcdir); $(MAKEINFO) forms.texi
-forms.dvi: forms.texi
- TEXINPUTS="$(srcdir) $(TEXINPUTS)"; $(TEXI2DVI) ${srcdir}/forms.texi
-
-../info/mh-e: mh-e.texi
- cd $(srcdir); $(MAKEINFO) mh-e.texi
-mh-e.dvi: mh-e.texi
- TEXINPUTS="$(srcdir) $(TEXINPUTS)"; $(TEXI2DVI) ${srcdir}/mh-e.texi
-
-../info/sc: sc.texi
- cd $(srcdir); $(MAKEINFO) sc.texi
-sc.dvi: sc.texi
- TEXINPUTS="$(srcdir) $(TEXINPUTS)"; $(TEXI2DVI) ${srcdir}/sc.texi
-
-../info/vip: vip.texi
- cd $(srcdir); $(MAKEINFO) vip.texi
-vip.dvi: vip.texi
- TEXINPUTS="$(srcdir) $(TEXINPUTS)"; $(TEXI2DVI) ${srcdir}/vip.texi
-
-../info/gnus: gnus.texi
- cd $(srcdir); $(MAKEINFO) gnus.texi
-gnus.dvi: gnus.texi
- TEXINPUTS="$(srcdir) $(TEXINPUTS)"; $(TEXI2DVI) ${srcdir}/gnus.texi
-
-../info/message: message.texi
- cd $(srcdir); $(MAKEINFO) message.texi
-message.dvi: message.texi
- TEXINPUTS="$(srcdir) $(TEXINPUTS)"; $(TEXI2DVI) ${srcdir}/message.texi
-
-../etc/GNU: gnu1.texi gnu.texi
- makeinfo --no-headers -o ../etc/GNU gnu1.texi
-
-../info/viper: viper.texi viper-cmd.texi
- cd $(srcdir); $(MAKEINFO) viper.texi
-viper.dvi: viper.texi viper-cmd.texi
- TEXINPUTS="$(srcdir) $(TEXINPUTS)"; $(TEXI2DVI) ${srcdir}/viper.texi
-
-mostlyclean:
- rm -f *.log *.cp *.fn *.ky *.pg *.vr core
-
-clean: mostlyclean
- rm -f *.dvi
-
-distclean: clean
-
-maintainer-clean: distclean
- rm -f *.aux *.cps *.fns *.kys *.pgs *.vrs
-# Don't delete these, because they are outside the current directory.
-# for file in $(INFO_TARGETS); do rm -f $${file}*; done
-
-
-# Formerly this directory had texindex.c and getopt.c in it
-# and this makefile built them to make texindex.
-# That caused trouble because this is run entirely in the source directory.
-# Since we expect to get texi2dvi from elsewhere,
-# it is ok to expect texindex from elsewhere also.
diff --git a/msdos/mainmake b/msdos/mainmake
deleted file mode 100644
index 66b70aae795..00000000000
--- a/msdos/mainmake
+++ /dev/null
@@ -1,76 +0,0 @@
-# make all to compile and build Emacs.
-# make install to install it.
-# make TAGS to update tags tables.
-#
-# make clean or make mostlyclean
-# Delete all files from the current directory that are normally
-# created by building the program. Don't delete the files that
-# record the configuration. Also preserve files that could be made
-# by building, but normally aren't because the distribution comes
-# with them.
-#
-# Delete `.dvi' files here if they are not part of the distribution.
-#
-# make distclean
-# Delete all files from the current directory that are created by
-# configuring or building the program. If you have unpacked the
-# source and built the program without creating any other files,
-# `make distclean' should leave only the files that were in the
-# distribution.
-#
-# make realclean
-# Delete everything from the current directory that can be
-# reconstructed with this Makefile. This typically includes
-# everything deleted by distclean, plus more: C source files
-# produced by Bison, tags tables, info files, and so on.
-#
-# make extraclean
-# Still more severe - delete backup and autosave files, too.
-
-all: lib-src src
-
-lib-src: FRC
- cd lib-src
- $(MAKE)
- cd ..
-
-src: FRC
- cd src
- $(MAKE)
- cd ..
-
-install: all
- -md bin
- cd lib-src
- coff2exe hexl
- coff2exe etags
- coff2exe ctags
- coff2exe b2m
- mv -f hexl.exe etags.exe ctags.exe b2m.exe ../bin/
- cd ..
- cd src
- coff2exe emacs
- stubedit emacs.exe minstack=512k
- mv -f emacs.exe ../bin/
- cd ..
-
-FRC:
-
-TAGS tags: lib-src
- cd src
- go32 ../lib-src/etags *.[ch] ../lisp/*.el ../lisp/term/*.el
- cd ..
-
-check:
- @echo "We don't have any tests for GNU Emacs yet."
-
-clean:
- cd lib-src
- $(MAKE) clean
- cd ..
- cd src
- $(MAKE) clean
- cd ..
- cd oldxmenu
- -$(MAKE) clean
- cd ..
diff --git a/msdos/mainmake.v2 b/msdos/mainmake.v2
deleted file mode 100644
index 121a1ec65cd..00000000000
--- a/msdos/mainmake.v2
+++ /dev/null
@@ -1,98 +0,0 @@
-# Top-level Makefile for Emacs under MS-DOS/DJGPP v2.0 or higher. -*-makefile-*-
-#
-# make all to compile and build Emacs.
-# make install to install it.
-# make TAGS to update tags tables.
-#
-# make clean or make mostlyclean
-# Delete all files from the current directory that are normally
-# created by building the program. Don't delete the files that
-# record the configuration. Also preserve files that could be made
-# by building, but normally aren't because the distribution comes
-# with them.
-#
-# Delete `.dvi' files here if they are not part of the distribution.
-#
-# make distclean
-# Delete all files from the current directory that are created by
-# configuring or building the program. If you have unpacked the
-# source and built the program without creating any other files,
-# `make distclean' should leave only the files that were in the
-# distribution.
-#
-# make realclean
-# Delete everything from the current directory that can be
-# reconstructed with this Makefile. This typically includes
-# everything deleted by distclean, plus more: C source files
-# produced by Bison, tags tables, info files, and so on.
-#
-# make extraclean
-# Still more severe - delete backup and autosave files, too.
-
-# Generate a full pathname of the top-level installation directory
-topdir := $(subst \,/,$(shell cd))
-
-all: lib-src src
-
-lib-src: FRC
- cd lib-src
- $(MAKE)
- cd ..
-
-src: FRC
- cd src
- $(MAKE)
- redir -o gdb.sed echo '/-geometry/s,^.*,set environment HOME $(topdir),'
- redir -oa gdb.sed echo '/environment *TERM/s/^.*/set environment TERM internal/'
- redir -oa gdb.sed echo '/x_error_quitter/s/^.*/set environment NAME root/'
- redir -o gdb.tmp sed -f gdb.sed _gdbinit
- redir -oa gdb.tmp echo 'set environment USER root'
- redir -oa gdb.tmp echo 'set environment EMACSPATH $(topdir)/bin'
- redir -oa gdb.tmp echo 'set environment SHELL $(subst \,/,$(COMSPEC))'
- redir -oa gdb.tmp echo 'set environment PATH $(subst \,/,$(PATH))'
- update gdb.tmp gdb.ini
- rm -f gdb.tmp gdb.sed
- cd ..
-
-install: all
- if not exist bin\\nul md bin
- cd lib-src
- if exist hexl.exe mv -f hexl.exe ../bin
- if exist etags.exe mv -f etags.exe ../bin
- if exist ctags.exe mv -f ctags.exe ../bin
- if exist b2m.exe mv -f b2m.exe ../bin
- cd ..
- cd src
- stubify emacs
- stubedit emacs.exe minstack=512k
- mv -f emacs.exe ../bin/
- cd ..
-
-FRC:
-
-TAGS tags: lib-src FRC
- cd lib-src
- if exist etags.exe mv -f etags.exe ../bin
- cd ..
- cd lisp
- ../bin/etags [a-zA-Z]*.el term/[a-zA-Z]*.el
- cd ..
- cd src
- ../bin/etags --include=../lisp/TAGS \
- '--regex=/[ ]*DEFVAR_[A-Z_ (]+"\([^"]+\)"/' *.c *.h s/msdos.h m/intel386.h
- cd ..
- ./bin/etags --include=src/TAGS
-
-check:
- @echo "We don't have any tests for GNU Emacs yet."
-
-clean:
- cd lib-src
- $(MAKE) clean
- cd ..
- cd src
- $(MAKE) clean
- cd ..
- cd oldxmenu
- -$(MAKE) clean
- cd ..
diff --git a/msdos/sed1.inp b/msdos/sed1.inp
deleted file mode 100644
index c40d6cac4ea..00000000000
--- a/msdos/sed1.inp
+++ /dev/null
@@ -1,38 +0,0 @@
-# -sed1.inp-------------------------------------------------------------
-# Configuration script for src/makefile
-# ----------------------------------------------------------------------
-#
-# In case src/Makefile needs to rebuild `make-doc.exe' (might happen under
-# Windows 95), make sure it gets built with commands that DOS
-# understands (one command per line).
-s/^#.*//
-s/^[ \f\t][ \f\t]*$//
-s/^ / /
-s/\.h\.in/.h-in/
-s!^ \./temacs! go32 temacs!
-s!/bin/sh!command.com!
-/^MAKE *=/s/^/# /
-/^SHELL *=/s/^/# /
-/^srcdir *=/s/@[^@\n]*@/./
-/^VPATH *=/s/@[^@\n]*@/./
-/^CC *=/s/@[^@\n]*@/gcc/
-/^CPP *=/s/@[^@\n]*@/gcc -e/
-/^CFLAGS *=/s/@[^@\n]*@/-O2 -g/
-/^LN_S *=/s/@[^@\n]*@/ln -s/
-/^M_FILE *=/s!@[^@\n]*@!m/intel386.h!
-/^S_FILE *=/s!@[^@\n]*@!s/msdos.h!
-/^@SET_MAKE@$/s/@SET_MAKE@//
-/^.\${libsrc}make-docfile.*>/s!make-docfile!make-doc.exe -o ../etc/DOC!
-/^.\${libsrc}make-doc/s!>.*$!!
-/^\${libsrc}make-docfile:/c\
-${libsrc}make-doc.exe:\
- cd ..\
- cd lib-src\
- $(MAKE) ${MFLAGS} make-docfile -W make-docfile.c\
- cd ..\
- cd src
-/^ cd \${libsrc}; \${MAKE} \${MFLAGS} make-docfile/d
-/\${libsrc}make-docfile/s/-docfile[ ]/-doc.exe /
-/^[ ]*$/d
-/^temacs:/s/prefix-args//
-/^ #/d
diff --git a/msdos/sed1v2.inp b/msdos/sed1v2.inp
deleted file mode 100644
index f7c127b29e6..00000000000
--- a/msdos/sed1v2.inp
+++ /dev/null
@@ -1,25 +0,0 @@
-# -sed1v2.inp-----------------------------------------------------------
-# Configuration script for src/makefile under DJGPP v2.x
-# ----------------------------------------------------------------------
-s/^#.*//
-s/^[ \f\t][ \f\t]*$//
-s/^ / /
-s/\.h\.in/.h-in/
-/^ \.\/temacs/i\
- stubedit temacs.exe minstack=40k
-/^MAKE *=/s/^/# /
-/^SHELL *=/s/^/# /
-/^srcdir *=/s/@[^@\n]*@/./
-/^VPATH *=/s/@[^@\n]*@/./
-/^CC *=/s/@[^@\n]*@/gcc/
-/^CPP *=/s/@[^@\n]*@/gcc -e/
-/^CFLAGS *=/s/@[^@\n]*@/-O2 -g/
-/^LN_S *=/s/@[^@\n]*@/ln -s/
-/^M_FILE *=/s!@[^@\n]*@!m/intel386.h!
-/^S_FILE *=/s!@[^@\n]*@!s/msdos.h!
-/^@SET_MAKE@$/s/@SET_MAKE@//
-/^.\${libsrc}make-docfile.*>/s!make-docfile!make-docfile -o ../etc/DOC!
-/^.\${libsrc}make-doc/s!>.*$!!
-/^[ ]*$/d
-/^temacs:/s/prefix-args//
-/^ #/d
diff --git a/msdos/sed1x.inp b/msdos/sed1x.inp
deleted file mode 100644
index dd9825de081..00000000000
--- a/msdos/sed1x.inp
+++ /dev/null
@@ -1,8 +0,0 @@
-# -sed1x.inp------------------------------------------------------------
-# Extra configuration script for src/makefile for DesqView/X
-# ----------------------------------------------------------------------
-s!^ cd \${oldXMenudir}; \${MAKE}.*$! ${MAKE} -C ${oldXMenudir}.!
-s!^ @true *$! @rem!
-s/DOC/DOC-X/g
-#/^LIBXMENU *=/s!= *!= ../oldxmenu/!
-/^temacs *:/s!OLDXMENU!LIBXMENU!
diff --git a/msdos/sed2.inp b/msdos/sed2.inp
deleted file mode 100644
index 64c2fa8248d..00000000000
--- a/msdos/sed2.inp
+++ /dev/null
@@ -1,49 +0,0 @@
-# -sed2.inp-------------------------------------------------------------
-# Configuration script for src/config.h
-# ----------------------------------------------------------------------
-/^#undef LISP_FLOAT_TYPE *$/s/undef/define/
-/^#undef GNU_MALLOC *$/s/undef/define/
-/^#undef REL_ALLOC *$/s/undef/define/
-/^#undef HAVE_SYS_SELECT/i\
-#if defined(__DJGPP__) && __DJGPP__ > 1\
-/* In v2.0 and later almost everything is defined in <sys/config.h> */\
-#include <sys/config.h>\
-#undef HAVE_SELECT\
-#undef _LIBC\
-#define HAVE_VFORK 1\
-#define HAVE_STRUCT_UTIMBUF 1\
-#define LOCALTIME_CACHE 1\
-#define HAVE_TZSET 1\
-#else /* not __DJGPP__ > 1 */
-/^#undef STDC_HEADERS *$/s/undef/define/
-/^#undef HAVE_SYS_TIMEB_H *$/s/undef/define/
-/^#undef HAVE_SYS_TIME_H *$/s/undef/define/
-# /^#undef HAVE_UNISTD_H *$/s/undef/define/
-/^#undef HAVE_GETTIMEOFDAY *$/s/undef/define/
-/^#undef HAVE_GETHOSTNAME *$/s/undef/define/
-/^#undef HAVE_DUP2 *$/s/undef/define/
-/^#undef HAVE_TM_ZONE *$/s/undef/define/
-/^#undef LOCALTIME_CACHE *$/s/undef/define/
-/^#undef HAVE_TZSET *$/s/undef/define/
-/^#undef TM_IN_SYS_TIME *$/s/undef/define/
-/^#undef TIME_WITH_SYS_TIME *$/s/undef/define/
-/^#undef HAVE_RENAME *$/s/undef/define/
-/^#undef HAVE_CLOSEDIR *$/s/undef/define/
-/^#undef HAVE_RANDOM *$/s/undef/define/
-/^#undef HAVE_MKDIR *$/s/undef/define/
-/^#undef HAVE_RMDIR *$/s/undef/define/
-/^#undef HAVE_BCMP *$/s/undef/define/
-/^#undef HAVE_BCOPY *$/s/undef/define/
-/^#undef HAVE_FREXP *$/s/undef/define/
-/^#undef HAVE_FTIME *$/s/undef/define/
-/^#undef HAVE_MKTIME *$/s/undef/define/
-/^#undef HAVE_STRERROR *$/s/undef/define/
-/^#undef HAVE_TIMEVAL *$/s/undef/define/
-/ HAVE_TIMEVAL/a\
-#endif /* not __DJGPP__ > 1 */
-s/^#define USER_FULL_NAME .*$/#define USER_FULL_NAME (getenv ("NAME"))/
-s/^#undef STACK_DIRECTION *$/#define STACK_DIRECTION -1/
-s/^#undef EMACS_CONFIGURATION *$/#define EMACS_CONFIGURATION "i386-unknown-msdos"/
-s/^#undef EMACS_CONFIG_OPTIONS *$/#define EMACS_CONFIG_OPTIONS "-"/
-s!^#undef config_opsysfile *$!#define config_opsysfile "s/msdos.h"!
-s!^#undef config_machfile *$!#define config_machfile "m/intel386.h"!
diff --git a/msdos/sed2x.inp b/msdos/sed2x.inp
deleted file mode 100644
index 87f1e60feb4..00000000000
--- a/msdos/sed2x.inp
+++ /dev/null
@@ -1,9 +0,0 @@
-# -sed2x.inp------------------------------------------------------------
-# Extra configuration script for src/config.h for DesqView/X
-# ----------------------------------------------------------------------
-/^#undef HAVE_X_WINDOWS *$/s/undef/define/
-/^#undef HAVE_X11 *$/s/undef/define/
-/^#undef HAVE_X_MENU *$/s/undef/define/
-/^#undef HAVE_XSCREENNUMBEROFSCREEN *$/s/undef/define/
-/^#undef HAVE_XSETWMPROTOCOLS *$/s/undef/define/
-/^#undef HAVE_SELECT *$/s/undef/define/
diff --git a/msdos/sed3.inp b/msdos/sed3.inp
deleted file mode 100644
index 335bffff439..00000000000
--- a/msdos/sed3.inp
+++ /dev/null
@@ -1,29 +0,0 @@
-# -sed3.inp-------------------------------------------------------------
-# Configuration script for lib-src/makefile
-# ----------------------------------------------------------------------
-/^# DIST: /d
-/^SHELL *=/s/^/# /
-/^CC *=/s/=.*$/=gcc/
-# Actually, here we should patch in the exact version number, but only
-# [ce]tags uses it. Don't pass it. This is more update-resistant.
-/-DVERSION=/s/-DVERSION="\\"\${version}\\""//
-/^configname *=/s/=.*$/=msdos/
-/^archlibdir *=/s!=.*$!=/emacs/bin!
-/^bindir *=/s!=.*$!=/emacs/bin!
-/^libdir *=/s!=.*$!=/emacs/bin!
-/^srcdir *=/s!=.*$!=.!
-/^VPATH *=/s!=.*$!=.!
-/^CFLAGS *=/s!=.*$!=-O2 -g!
-/^C_SWITCH_SYSTEM *=/s!=.*$!=-DMSDOS!
-/^LOADLIBES *=/s!=.*$!=!
-/^ALLOCA *=/s!=.*$!=alloca.o!
-/^INSTALLABLES/s/emacsclient *//
-s!^ \./! go32 ./!
-/^UTILITIES=/s/ wakeup//
-/^UTILITIES=/s/ movemail//
-/^UTILITIES=/s/ emacsserver//
-/^UTILITIES=/s/ timer//
-/^all *:/s/$/ make-docfile/
-s!^ go32 ./test-distrib! go32 ./test-dis!
-/-o make-docfile/a\
- coff2exe make-docfile
diff --git a/msdos/sed3v2.inp b/msdos/sed3v2.inp
deleted file mode 100644
index ea3e3fdd3a2..00000000000
--- a/msdos/sed3v2.inp
+++ /dev/null
@@ -1,25 +0,0 @@
-# -sed3v2.inp-------------------------------------------------------------
-# Configuration script for lib-src/makefile under DJGPP v2
-# ----------------------------------------------------------------------
-/^# DIST: /d
-/^SHELL *=/s/^/# /
-/^CC *=/s/=.*$/=gcc/
-# Actually, here we should patch in the exact version number, but only
-# [ce]tags uses it. Don't pass it. This is more update-resistant.
-/-DVERSION=/s/-DVERSION="\\"\${version}\\""//
-/^configname *=/s/=.*$/=msdos/
-/^archlibdir *=/s!=.*$!=/emacs/bin!
-/^bindir *=/s!=.*$!=/emacs/bin!
-/^libdir *=/s!=.*$!=/emacs/bin!
-/^srcdir *=/s!=.*$!=.!
-/^VPATH *=/s!=.*$!=.!
-/^CFLAGS *=/s!=.*$!=-O2 -g!
-/^C_SWITCH_SYSTEM *=/s!=.*$!=-DMSDOS!
-/^LOADLIBES *=/s!=.*$!=!
-/^ALLOCA *=/s!=.*$!=alloca.o!
-/^INSTALLABLES/s/emacsclient *//
-s!^ \./! !
-/^UTILITIES=/s/ wakeup//
-/^UTILITIES=/s/ movemail//
-/^UTILITIES=/s/ emacsserver//
-/^UTILITIES=/s/ timer//
diff --git a/msdos/sed4.inp b/msdos/sed4.inp
deleted file mode 100644
index b85b5bee5d7..00000000000
--- a/msdos/sed4.inp
+++ /dev/null
@@ -1,7 +0,0 @@
-# -sed4.inp-------------------------------------------------------------
-# Configuration script for src/paths.h
-# ----------------------------------------------------------------------
-/^#define *PATH_LOADSEARCH/s/".*"/rootrelativepath ("lisp")/
-/^#define *PATH_DATA/s/".*"/rootrelativepath ("etc")/
-/^#define *PATH_DOC/s/".*"/rootrelativepath ("etc")/
-/^#define *PATH_INFO/s/".*"/rootrelativepath ("info")/
diff --git a/msdos/sed5x.inp b/msdos/sed5x.inp
deleted file mode 100644
index 5c6ed3f9347..00000000000
--- a/msdos/sed5x.inp
+++ /dev/null
@@ -1,11 +0,0 @@
-# -sed5x.inp------------------------------------------------------------
-# Configuration script for oldxmenu/makefile for DesqView/X
-# ----------------------------------------------------------------------
-/^srcdir *=/s/@[^@\n]*@/./
-/^VPATH *=/s/@[^@\n]*@/./
-/^C_SWITCH_X_SITE *=/s/@[^@\n]*@//
-/^CC *=/s/@[^@\n]*@/gcc/
-/^CPP *=/s/@[^@\n]*@/gcc -e/
-/^CFLAGS *=/s/@[^@\n]*@/-O2 -g/
-/^LN_S *=/s/@[^@\n]*@/ln -s/
-s/|| true//
diff --git a/nt/_emacs b/nt/_emacs
deleted file mode 100644
index 76ef4e58c34..00000000000
--- a/nt/_emacs
+++ /dev/null
@@ -1,3 +0,0 @@
-;;; This is the user emacs startup file (.emacs in Unix land).
-
-(put 'eval-expression 'disabled nil)
diff --git a/nt/addpm.c b/nt/addpm.c
deleted file mode 100644
index 2138143ccd9..00000000000
--- a/nt/addpm.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/* Add entries to the GNU Emacs Program Manager folder.
- Copyright (C) 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/****************************************************************************
- *
- * Program: addpm (adds emacs to the Windows program manager)
- *
- * Usage:
- * argv[1] = install path for emacs
- * argv[2] = full path to icon for emacs (optional)
- */
-
-#include <windows.h>
-#include <ddeml.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-HDDEDATA CALLBACK
-DdeCallback (UINT uType, UINT uFmt, HCONV hconv,
- HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
- DWORD dwData1, DWORD dwData2)
-{
- return ((HDDEDATA) NULL);
-}
-
-#define DdeCommand(str) \
- DdeClientTransaction (str, strlen (str)+1, HConversation, (HSZ)NULL, \
- CF_TEXT, XTYP_EXECUTE, 30000, NULL)
-
-#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
-
-static struct entry
-{
- char *name;
- char *value;
-}
-env_vars[] =
-{
- {"emacs_dir", NULL},
- {"EMACSLOADPATH", "%emacs_dir%/lisp;%emacs_dir%/site-lisp"},
- {"SHELL", "%COMSPEC%"},
- {"EMACSDATA", "%emacs_dir%/etc"},
- {"EMACSPATH", "%emacs_dir%/bin"},
- {"EMACSLOCKDIR", "%emacs_dir%/lock"},
- {"INFOPATH", "%emacs_dir%/info"},
- {"EMACSDOC", "%emacs_dir%/etc"},
- {"TERM", "cmd"}
-};
-
-BOOL
-add_registry (path)
- char *path;
-{
- HKEY hrootkey = NULL;
- DWORD dwDisp;
- int i;
- BOOL ok = TRUE;
-
- /* Check both the current user and the local machine to see if we
- have any resources. */
-
- if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT,
- 0, "", REG_OPTION_NON_VOLATILE,
- KEY_WRITE, NULL, &hrootkey, &dwDisp) != ERROR_SUCCESS
- && RegCreateKeyEx (HKEY_CURRENT_USER, REG_ROOT,
- 0, "", REG_OPTION_NON_VOLATILE,
- KEY_WRITE, NULL, &hrootkey, &dwDisp) != ERROR_SUCCESS)
- {
- return FALSE;
- }
-
- for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
- {
- char * value = env_vars[i].value ? env_vars[i].value : path;
-
- if (RegSetValueEx (hrootkey, env_vars[i].name,
- 0, REG_EXPAND_SZ,
- value, lstrlen (value) + 1) != ERROR_SUCCESS)
- ok = FALSE;
- }
-
- RegCloseKey (hrootkey);
-
- return (ok);
-}
-
-int
-main (argc, argv)
- int argc;
- char *argv[];
-{
- DWORD idDde;
- HCONV HConversation;
- HSZ ProgMan;
- char additem[MAX_PATH*2 + 100];
- char *lpext;
-
- if (argc < 2 || argc > 3)
- {
- fprintf (stderr, "usage: addpm emacs_path [icon_path]\n");
- exit (1);
- }
-
- lpext = add_registry (argv[1]) ? "exe" : "bat";
-
- DdeInitialize (&idDde, (PFNCALLBACK)DdeCallback, APPCMD_CLIENTONLY, 0);
-
- ProgMan = DdeCreateStringHandle (idDde, "PROGMAN", CP_WINANSI);
-
- if (HConversation = DdeConnect (idDde, ProgMan, ProgMan, NULL))
- {
- DdeCommand ("[CreateGroup (Gnu Emacs)]");
- DdeCommand ("[ReplaceItem (Emacs)]");
- sprintf (additem, "[AddItem (%s\\bin\\runemacs.%s, Emacs%c%s)]",
- argv[1], lpext, (argc>2 ? ',' : ' '),
- (argc>2 ? argv[2] : ""));
- DdeCommand (additem);
-
- DdeDisconnect (HConversation);
- }
-
- DdeFreeStringHandle (idDde, ProgMan);
-
- DdeUninitialize (idDde);
-
- return (0);
-}
diff --git a/nt/config.nt b/nt/config.nt
deleted file mode 100644
index 6a59cdc1ba6..00000000000
--- a/nt/config.nt
+++ /dev/null
@@ -1,349 +0,0 @@
-/* GNU Emacs site configuration template file. -*- C -*-
- Copyright (C) 1988, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* No code in Emacs #includes config.h twice, but some of the code
- intended to work with other packages as well (like gmalloc.c)
- think they can include it as many times as they like. */
-#ifndef EMACS_CONFIG_H
-#define EMACS_CONFIG_H
-
-
-/* These are all defined in the top-level Makefile by configure.
- They're here only for reference. */
-
-/* Define LISP_FLOAT_TYPE if you want emacs to support floating-point
- numbers. */
-#undef LISP_FLOAT_TYPE
-
-/* Define GNU_MALLOC if you want to use the *new* GNU memory allocator. */
-#undef GNU_MALLOC
-
-/* Define REL_ALLOC if you want to use the relocating allocator for
- buffer space. */
-#undef REL_ALLOC
-
-/* Define HAVE_X_WINDOWS if you want to use the X window system. */
-#undef HAVE_X_WINDOWS
-
-/* Define HAVE_X11 if you want to use version 11 of X windows.
- Otherwise, Emacs expects to use version 10. */
-#undef HAVE_X11
-
-/* Define if using an X toolkit. */
-#undef USE_X_TOOLKIT
-
-/* Define this if you're using XFree386. */
-#undef HAVE_XFREE386
-
-/* Define HAVE_X_MENU if you want to use the X window menu system.
- This appears to work on some machines that support X
- and not on others. */
-#undef HAVE_X_MENU
-
-/* Define if we have the X11R6 or newer version of Xt. */
-#undef HAVE_X11XTR6
-
-/* Define if netdb.h declares h_errno. */
-#undef HAVE_H_ERRNO
-
-/* Nowadays we have frame objects even if we support only ASCII terminals. */
-#define MULTI_FRAME
-
-/* If we're using any sort of window system, define some consequences. */
-#ifdef HAVE_X_WINDOWS
-#define HAVE_WINDOW_SYSTEM
-#define MULTI_KBOARD
-#define HAVE_FACES
-#define HAVE_MOUSE
-#endif
-
-/* Define USE_TEXT_PROPERTIES to support visual and other properties
- on text. */
-#define USE_TEXT_PROPERTIES
-
-/* Define USER_FULL_NAME to return a string
- that is the user's full name.
- It can assume that the variable `pw'
- points to the password file entry for this user.
-
- At some sites, the pw_gecos field contains
- the user's full name. If neither this nor any other
- field contains the right thing, use pw_name,
- giving the user's login name, since that is better than nothing. */
-#define USER_FULL_NAME pw->pw_gecos
-
-/* Define AMPERSAND_FULL_NAME if you use the convention
- that & in the full name stands for the login id. */
-#undef AMPERSAND_FULL_NAME
-
-/* Things set by --with options in the configure script. */
-
-/* Define to support POP mail retrieval. */
-#undef MAIL_USE_POP
-
-/* Define to support Kerberos-authenticated POP mail retrieval. */
-#undef KERBEROS
-
-/* Define to support using a Hesiod database to find the POP server. */
-#undef HESIOD
-
-/* Some things figured out by the configure script, grouped as they are in
- configure.in. */
-#ifndef _ALL_SOURCE /* suppress warning if this is pre-defined */
-#undef _ALL_SOURCE
-#endif
-#undef HAVE_SYS_SELECT_H
-#undef HAVE_SYS_TIMEB_H
-#undef HAVE_SYS_TIME_H
-#undef HAVE_UNISTD_H
-#undef HAVE_UTIME_H
-#undef STDC_HEADERS
-#undef TIME_WITH_SYS_TIME
-
-#undef HAVE_LIBDNET
-#undef HAVE_LIBPTHREADS
-#undef HAVE_LIBRESOLV
-
-#undef HAVE_ALLOCA_H
-
-#undef HAVE_GETTIMEOFDAY
-#undef GETTIMEOFDAY_ONE_ARGUMENT
-#undef HAVE_GETHOSTNAME
-#undef HAVE_DUP2
-#undef HAVE_RENAME
-#undef HAVE_CLOSEDIR
-
-#undef TM_IN_SYS_TIME
-#undef HAVE_TM_ZONE
-#undef HAVE_TZNAME
-
-#undef const
-
-#undef HAVE_LONG_FILE_NAMES
-
-#undef CRAY_STACKSEG_END
-
-#undef UNEXEC_SRC
-
-#undef HAVE_LIBXBSD
-#undef HAVE_XRMSETDATABASE
-#undef HAVE_XSCREENRESOURCESTRING
-#undef HAVE_XSCREENNUMBEROFSCREEN
-#undef HAVE_XSETWMPROTOCOLS
-
-#undef HAVE_MKDIR
-#undef HAVE_RMDIR
-#undef HAVE_RANDOM
-#undef HAVE_LRAND48
-#undef HAVE_BCOPY
-#undef HAVE_BCMP
-#undef HAVE_LOGB
-#undef HAVE_FREXP
-#undef HAVE_FMOD
-#undef HAVE_FTIME
-#undef HAVE_RES_INIT /* For -lresolv on Suns. */
-#undef HAVE_SETSID
-#undef HAVE_FPATHCONF
-#undef HAVE_SELECT
-#undef HAVE_MKTIME
-#undef HAVE_EACCESS
-#undef HAVE_GETPAGESIZE
-#undef HAVE_INET_SOCKETS
-
-#undef HAVE_AIX_SMT_EXP
-
-/* Define if you have the ANSI `strerror' function.
- Otherwise you must have the variable `char *sys_errlist[]'. */
-#undef HAVE_STRERROR
-
-#undef HAVE_UTIMES
-
-/* Define if `sys_siglist' is declared by <signal.h>. */
-#undef SYS_SIGLIST_DECLARED
-
-/* Define if `struct utimbuf' is declared by <utime.h>. */
-#undef HAVE_STRUCT_UTIMBUF
-
-/* Define if `struct timeval' is declared by <sys/time.h>. */
-#undef HAVE_TIMEVAL
-
-/* If using GNU, then support inline function declarations. */
-#ifdef __GNUC__
-#define INLINE __inline__
-#else
-#define INLINE
-#endif
-
-#undef EMACS_CONFIGURATION
-
-#undef EMACS_CONFIG_OPTIONS
-
-/* The configuration script defines opsysfile to be the name of the
- s/SYSTEM.h file that describes the system type you are using. The file
- is chosen based on the configuration name you give.
-
- See the file ../etc/MACHINES for a list of systems and the
- configuration names to use for them.
-
- See s/template.h for documentation on writing s/SYSTEM.h files. */
-#undef config_opsysfile
-#include "s/ms-w32.h"
-
-/* The configuration script defines machfile to be the name of the
- m/MACHINE.h file that describes the machine you are using. The file is
- chosen based on the configuration name you give.
-
- See the file ../etc/MACHINES for a list of machines and the
- configuration names to use for them.
-
- See m/template.h for documentation on writing m/MACHINE.h files. */
-#undef config_machfile
-#include "m/intel386.h"
-
-/* These typedefs shouldn't appear when alloca.s or Makefile.in
- includes config.h. */
-#ifndef NOT_C_CODE
-#ifndef SPECIAL_EMACS_INT
-typedef long EMACS_INT;
-typedef unsigned long EMACS_UINT;
-#endif
-#endif
-
-/* Load in the conversion definitions if this system
- needs them and the source file being compiled has not
- said to inhibit this. There should be no need for you
- to alter these lines. */
-
-#ifdef SHORTNAMES
-#ifndef NO_SHORTNAMES
-#include "../shortnames/remap.h"
-#endif /* not NO_SHORTNAMES */
-#endif /* SHORTNAMES */
-
-/* If no remapping takes place, static variables cannot be dumped as
- pure, so don't worry about the `static' keyword. */
-#ifdef NO_REMAP
-#undef static
-#endif
-
-/* Define `subprocesses' should be defined if you want to
- have code for asynchronous subprocesses
- (as used in M-x compile and M-x shell).
- These do not work for some USG systems yet;
- for the ones where they work, the s/SYSTEM.h file defines this flag. */
-
-#ifndef VMS
-#ifndef USG
-/* #define subprocesses */
-#endif
-#endif
-
-/* Define LD_SWITCH_SITE to contain any special flags your loader may need. */
-#undef LD_SWITCH_SITE
-
-/* Define C_SWITCH_SITE to contain any special flags your compiler needs. */
-#undef C_SWITCH_SITE
-
-/* Define LD_SWITCH_X_SITE to contain any special flags your loader
- may need to deal with X Windows. 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. */
-#undef LD_SWITCH_X_SITE
-
-/* Define LD_SWITCH_X_SITE_AUX with an -R option
- in case it's needed (for Solaris, for example). */
-#undef LD_SWITCH_X_SITE_AUX
-
-/* Define C_SWITCH_X_SITE to contain any special flags your compiler
- may need to deal with X Windows. 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. */
-#undef C_SWITCH_X_SITE
-
-/* Define STACK_DIRECTION here, but not if m/foo.h did. */
-#ifndef STACK_DIRECTION
-#undef STACK_DIRECTION
-#endif
-
-/* Define the return type of signal handlers if the s-xxx file
- did not already do so. */
-#define RETSIGTYPE void
-
-/* SIGTYPE is the macro we actually use. */
-#ifndef SIGTYPE
-#define SIGTYPE RETSIGTYPE
-#endif
-
-#ifdef emacs /* Don't do this for lib-src. */
-/* Tell regex.c to use a type compatible with Emacs. */
-#define RE_TRANSLATE_TYPE Lisp_Object *
-#endif
-
-/* The rest of the code currently tests the CPP symbol BSTRING.
- Override any claims made by the system-description files.
- Note that on some SCO version it is possible to have bcopy and not bcmp. */
-#undef BSTRING
-#if defined (HAVE_BCOPY) && defined (HAVE_BCMP)
-#define BSTRING
-#endif
-
-/* Non-ANSI C compilers usually don't have volatile. */
-#ifndef HAVE_VOLATILE
-#ifndef __STDC__
-#define volatile
-#endif
-#endif
-
-/* Some of the files of Emacs which are intended for use with other
- programs assume that if you have a config.h file, you must declare
- the type of getenv.
-
- This declaration shouldn't appear when alloca.s or Makefile.in
- includes config.h. */
-#ifndef NOT_C_CODE
-extern char *getenv ();
-#endif
-
-#endif /* EMACS_CONFIG_H */
-
-/* These default definitions are good for almost all machines.
- The exceptions override them in m/*.h. */
-
-#ifndef BITS_PER_CHAR
-#define BITS_PER_CHAR 8
-#endif
-
-#ifndef BITS_PER_SHORT
-#define BITS_PER_SHORT 16
-#endif
-
-/* Note that lisp.h uses this in a preprocessor conditional, so it
- would not work to use sizeof. That being so, we do all of them
- without sizeof, for uniformity's sake. */
-#ifndef BITS_PER_INT
-#define BITS_PER_INT 32
-#endif
-
-#ifndef BITS_PER_LONG
-#define BITS_PER_LONG 32
-#endif
diff --git a/nt/config.w95 b/nt/config.w95
deleted file mode 100644
index bcba3475925..00000000000
--- a/nt/config.w95
+++ /dev/null
@@ -1,349 +0,0 @@
-/* GNU Emacs site configuration template file. -*- C -*-
- Copyright (C) 1988, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* No code in Emacs #includes config.h twice, but some of the code
- intended to work with other packages as well (like gmalloc.c)
- think they can include it as many times as they like. */
-#ifndef EMACS_CONFIG_H
-#define EMACS_CONFIG_H
-
-
-/* These are all defined in the top-level Makefile by configure.
- They're here only for reference. */
-
-/* Define LISP_FLOAT_TYPE if you want emacs to support floating-point
- numbers. */
-#undef LISP_FLOAT_TYPE
-
-/* Define GNU_MALLOC if you want to use the *new* GNU memory allocator. */
-#undef GNU_MALLOC
-
-/* Define REL_ALLOC if you want to use the relocating allocator for
- buffer space. */
-#undef REL_ALLOC
-
-/* Define HAVE_X_WINDOWS if you want to use the X window system. */
-#undef HAVE_X_WINDOWS
-
-/* Define HAVE_X11 if you want to use version 11 of X windows.
- Otherwise, Emacs expects to use version 10. */
-#undef HAVE_X11
-
-/* Define if using an X toolkit. */
-#undef USE_X_TOOLKIT
-
-/* Define this if you're using XFree386. */
-#undef HAVE_XFREE386
-
-/* Define HAVE_X_MENU if you want to use the X window menu system.
- This appears to work on some machines that support X
- and not on others. */
-#undef HAVE_X_MENU
-
-/* Define if we have the X11R6 or newer version of Xt. */
-#undef HAVE_X11XTR6
-
-/* Define if netdb.h declares h_errno. */
-#undef HAVE_H_ERRNO
-
-/* Nowadays we have frame objects even if we support only ASCII terminals. */
-#define MULTI_FRAME
-
-/* If we're using any sort of window system, define some consequences. */
-#ifdef HAVE_X_WINDOWS
-#define HAVE_WINDOW_SYSTEM
-#define MULTI_KBOARD
-#define HAVE_FACES
-#define HAVE_MOUSE
-#endif
-
-/* Define USE_TEXT_PROPERTIES to support visual and other properties
- on text. */
-#define USE_TEXT_PROPERTIES
-
-/* Define USER_FULL_NAME to return a string
- that is the user's full name.
- It can assume that the variable `pw'
- points to the password file entry for this user.
-
- At some sites, the pw_gecos field contains
- the user's full name. If neither this nor any other
- field contains the right thing, use pw_name,
- giving the user's login name, since that is better than nothing. */
-#define USER_FULL_NAME pw->pw_gecos
-
-/* Define AMPERSAND_FULL_NAME if you use the convention
- that & in the full name stands for the login id. */
-#undef AMPERSAND_FULL_NAME
-
-/* Things set by --with options in the configure script. */
-
-/* Define to support POP mail retrieval. */
-#undef MAIL_USE_POP
-
-/* Define to support Kerberos-authenticated POP mail retrieval. */
-#undef KERBEROS
-
-/* Define to support using a Hesiod database to find the POP server. */
-#undef HESIOD
-
-/* Some things figured out by the configure script, grouped as they are in
- configure.in. */
-#ifndef _ALL_SOURCE /* suppress warning if this is pre-defined */
-#undef _ALL_SOURCE
-#endif
-#undef HAVE_SYS_SELECT_H
-#undef HAVE_SYS_TIMEB_H
-#undef HAVE_SYS_TIME_H
-#undef HAVE_UNISTD_H
-#undef HAVE_UTIME_H
-#undef STDC_HEADERS
-#undef TIME_WITH_SYS_TIME
-
-#undef HAVE_LIBDNET
-#undef HAVE_LIBPTHREADS
-#undef HAVE_LIBRESOLV
-
-#undef HAVE_ALLOCA_H
-
-#undef HAVE_GETTIMEOFDAY
-#undef GETTIMEOFDAY_ONE_ARGUMENT
-#undef HAVE_GETHOSTNAME
-#undef HAVE_DUP2
-#undef HAVE_RENAME
-#undef HAVE_CLOSEDIR
-
-#undef TM_IN_SYS_TIME
-#undef HAVE_TM_ZONE
-#undef HAVE_TZNAME
-
-#undef const
-
-#undef HAVE_LONG_FILE_NAMES
-
-#undef CRAY_STACKSEG_END
-
-#undef UNEXEC_SRC
-
-#undef HAVE_LIBXBSD
-#undef HAVE_XRMSETDATABASE
-#undef HAVE_XSCREENRESOURCESTRING
-#undef HAVE_XSCREENNUMBEROFSCREEN
-#undef HAVE_XSETWMPROTOCOLS
-
-#undef HAVE_MKDIR
-#undef HAVE_RMDIR
-#undef HAVE_RANDOM
-#undef HAVE_LRAND48
-#undef HAVE_BCOPY
-#undef HAVE_BCMP
-#undef HAVE_LOGB
-#undef HAVE_FREXP
-#undef HAVE_FMOD
-#undef HAVE_FTIME
-#undef HAVE_RES_INIT /* For -lresolv on Suns. */
-#undef HAVE_SETSID
-#undef HAVE_FPATHCONF
-#undef HAVE_SELECT
-#undef HAVE_MKTIME
-#undef HAVE_EACCESS
-#undef HAVE_GETPAGESIZE
-#undef HAVE_INET_SOCKETS
-
-#undef HAVE_AIX_SMT_EXP
-
-/* Define if you have the ANSI `strerror' function.
- Otherwise you must have the variable `char *sys_errlist[]'. */
-#undef HAVE_STRERROR
-
-#undef HAVE_UTIMES
-
-/* Define if `sys_siglist' is declared by <signal.h>. */
-#undef SYS_SIGLIST_DECLARED
-
-/* Define if `struct utimbuf' is declared by <utime.h>. */
-#undef HAVE_STRUCT_UTIMBUF
-
-/* Define if `struct timeval' is declared by <sys/time.h>. */
-#undef HAVE_TIMEVAL
-
-/* If using GNU, then support inline function declarations. */
-#ifdef __GNUC__
-#define INLINE __inline__
-#else
-#define INLINE
-#endif
-
-#undef EMACS_CONFIGURATION
-
-#undef EMACS_CONFIG_OPTIONS
-
-/* The configuration script defines opsysfile to be the name of the
- s/SYSTEM.h file that describes the system type you are using. The file
- is chosen based on the configuration name you give.
-
- See the file ../etc/MACHINES for a list of systems and the
- configuration names to use for them.
-
- See s/template.h for documentation on writing s/SYSTEM.h files. */
-#undef config_opsysfile
-#include "s/windows95.h"
-
-/* The configuration script defines machfile to be the name of the
- m/MACHINE.h file that describes the machine you are using. The file is
- chosen based on the configuration name you give.
-
- See the file ../etc/MACHINES for a list of machines and the
- configuration names to use for them.
-
- See m/template.h for documentation on writing m/MACHINE.h files. */
-#undef config_machfile
-#include "m/intel386.h"
-
-/* These typedefs shouldn't appear when alloca.s or Makefile.in
- includes config.h. */
-#ifndef NOT_C_CODE
-#ifndef SPECIAL_EMACS_INT
-typedef long EMACS_INT;
-typedef unsigned long EMACS_UINT;
-#endif
-#endif
-
-/* Load in the conversion definitions if this system
- needs them and the source file being compiled has not
- said to inhibit this. There should be no need for you
- to alter these lines. */
-
-#ifdef SHORTNAMES
-#ifndef NO_SHORTNAMES
-#include "../shortnames/remap.h"
-#endif /* not NO_SHORTNAMES */
-#endif /* SHORTNAMES */
-
-/* If no remapping takes place, static variables cannot be dumped as
- pure, so don't worry about the `static' keyword. */
-#ifdef NO_REMAP
-#undef static
-#endif
-
-/* Define `subprocesses' should be defined if you want to
- have code for asynchronous subprocesses
- (as used in M-x compile and M-x shell).
- These do not work for some USG systems yet;
- for the ones where they work, the s/SYSTEM.h file defines this flag. */
-
-#ifndef VMS
-#ifndef USG
-/* #define subprocesses */
-#endif
-#endif
-
-/* Define LD_SWITCH_SITE to contain any special flags your loader may need. */
-#undef LD_SWITCH_SITE
-
-/* Define C_SWITCH_SITE to contain any special flags your compiler needs. */
-#undef C_SWITCH_SITE
-
-/* Define LD_SWITCH_X_SITE to contain any special flags your loader
- may need to deal with X Windows. 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. */
-#undef LD_SWITCH_X_SITE
-
-/* Define LD_SWITCH_X_SITE_AUX with an -R option
- in case it's needed (for Solaris, for example). */
-#undef LD_SWITCH_X_SITE_AUX
-
-/* Define C_SWITCH_X_SITE to contain any special flags your compiler
- may need to deal with X Windows. 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. */
-#undef C_SWITCH_X_SITE
-
-/* Define STACK_DIRECTION here, but not if m/foo.h did. */
-#ifndef STACK_DIRECTION
-#undef STACK_DIRECTION
-#endif
-
-/* Define the return type of signal handlers if the s-xxx file
- did not already do so. */
-#define RETSIGTYPE void
-
-/* SIGTYPE is the macro we actually use. */
-#ifndef SIGTYPE
-#define SIGTYPE RETSIGTYPE
-#endif
-
-#ifdef emacs /* Don't do this for lib-src. */
-/* Tell regex.c to use a type compatible with Emacs. */
-#define RE_TRANSLATE_TYPE Lisp_Object *
-#endif
-
-/* The rest of the code currently tests the CPP symbol BSTRING.
- Override any claims made by the system-description files.
- Note that on some SCO version it is possible to have bcopy and not bcmp. */
-#undef BSTRING
-#if defined (HAVE_BCOPY) && defined (HAVE_BCMP)
-#define BSTRING
-#endif
-
-/* Non-ANSI C compilers usually don't have volatile. */
-#ifndef HAVE_VOLATILE
-#ifndef __STDC__
-#define volatile
-#endif
-#endif
-
-/* Some of the files of Emacs which are intended for use with other
- programs assume that if you have a config.h file, you must declare
- the type of getenv.
-
- This declaration shouldn't appear when alloca.s or Makefile.in
- includes config.h. */
-#ifndef NOT_C_CODE
-extern char *getenv ();
-#endif
-
-#endif /* EMACS_CONFIG_H */
-
-/* These default definitions are good for almost all machines.
- The exceptions override them in m/*.h. */
-
-#ifndef BITS_PER_CHAR
-#define BITS_PER_CHAR 8
-#endif
-
-#ifndef BITS_PER_SHORT
-#define BITS_PER_SHORT 16
-#endif
-
-/* Note that lisp.h uses this in a preprocessor conditional, so it
- would not work to use sizeof. That being so, we do all of them
- without sizeof, for uniformity's sake. */
-#ifndef BITS_PER_INT
-#define BITS_PER_INT 32
-#endif
-
-#ifndef BITS_PER_LONG
-#define BITS_PER_LONG 32
-#endif
diff --git a/nt/ebuild.bat b/nt/ebuild.bat
deleted file mode 100755
index 32cea5af9fa..00000000000
--- a/nt/ebuild.bat
+++ /dev/null
@@ -1 +0,0 @@
-nmake -f makefile.nt all
diff --git a/nt/emacs.bat b/nt/emacs.bat
deleted file mode 100755
index 14e4893d6df..00000000000
--- a/nt/emacs.bat
+++ /dev/null
@@ -1,44 +0,0 @@
-@echo off
-
-REM Change this to the directory into which you installed Emacs:
-set emacs_path=C:\emacs
-
-REM
-REM You shouldn't have to change any of the below.
-REM
-
-REM Set OS specific values.
-set ARCH_SAVE=%PROCESSOR_ARCHITECTURE%
-set PROCESSOR_ARCHITECTURE=
-if "%ARCH_SAVE%" == "%PROCESSOR_ARCHITECTURE%" goto win95
-set PROCESSOR_ARCHITECTURE=%ARCH_SAVE%
-set SHELL=cmd
-goto next
-
-:win95
-set SHELL=command
-
-:next
-
-set EMACSLOADPATH=%emacs_path%\lisp
-set EMACSDATA=%emacs_path%\etc
-set EMACSPATH=%emacs_path%\bin
-set EMACSLOCKDIR=%emacs_path%\lock
-set INFOPATH=%emacs_path%\info
-set EMACSDOC=%emacs_path%\etc
-set TERM=CMD
-
-REM The variable HOME is used to find the startup file, ~\_emacs. Ideally,
-REM this will not be set in this file but should already be set before
-REM this file is invoked. If HOME is not set, use some generic default.
-
-set HOME_SAVE=%HOME%
-set HOME_EXISTS=yes
-set HOME_DEFAULT=C:\
-set HOME=
-if "%HOME%" == "%HOME_SAVE%" set HOME_EXISTS=no
-if "%HOME_EXISTS%" == "yes" set HOME=%HOME_SAVE%
-if "%HOME_EXISTS%" == "no" set HOME=%HOME_DEFAULT%
-if "%HOME_EXISTS%" == "no" echo HOME is not set! Using %HOME% as a default...
-
-%emacs_path%\bin\emacs.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
diff --git a/nt/emacs.bat.in b/nt/emacs.bat.in
deleted file mode 100644
index 0e594160fd8..00000000000
--- a/nt/emacs.bat.in
+++ /dev/null
@@ -1,38 +0,0 @@
-
-REM Here begins emacs.bat.in
-
-REM Set OS specific values.
-set ARCH_SAVE=%PROCESSOR_ARCHITECTURE%
-set PROCESSOR_ARCHITECTURE=
-if "%ARCH_SAVE%" == "%PROCESSOR_ARCHITECTURE%" goto win95
-set PROCESSOR_ARCHITECTURE=%ARCH_SAVE%
-set SHELL=cmd
-goto next
-
-:win95
-set SHELL=command
-
-:next
-
-set EMACSLOADPATH=%emacs_dir%\lisp;%emacs_dir%\site-lisp
-set EMACSDATA=%emacs_dir%\etc
-set EMACSPATH=%emacs_dir%\bin
-set EMACSLOCKDIR=%emacs_dir%\lock
-set INFOPATH=%emacs_dir%\info
-set EMACSDOC=%emacs_dir%\etc
-set TERM=CMD
-
-REM The variable HOME is used to find the startup file, ~\_emacs. Ideally,
-REM this will not be set in this file but should already be set before
-REM this file is invoked. If HOME is not set, use some generic default.
-
-set HOME_SAVE=%HOME%
-set HOME_EXISTS=yes
-set HOME_DEFAULT=C:\
-set HOME=
-if "%HOME%" == "%HOME_SAVE%" set HOME_EXISTS=no
-if "%HOME_EXISTS%" == "yes" set HOME=%HOME_SAVE%
-if "%HOME_EXISTS%" == "no" set HOME=%HOME_DEFAULT%
-if "%HOME_EXISTS%" == "no" echo HOME is not set! Using %HOME% as a default...
-
-%emacs_dir%\bin\emacs.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
diff --git a/nt/emacs.rc b/nt/emacs.rc
deleted file mode 100644
index 3c81f0aa403..00000000000
--- a/nt/emacs.rc
+++ /dev/null
@@ -1 +0,0 @@
-Emacs ICON emacs.ico
diff --git a/nt/fast-install.bat b/nt/fast-install.bat
deleted file mode 100755
index 157c4ab8751..00000000000
--- a/nt/fast-install.bat
+++ /dev/null
@@ -1 +0,0 @@
-nmake -f makefile.nt fast_install
diff --git a/nt/inc/arpa/inet.h b/nt/inc/arpa/inet.h
deleted file mode 100644
index f5d197c06e1..00000000000
--- a/nt/inc/arpa/inet.h
+++ /dev/null
@@ -1 +0,0 @@
-/* null version of <arpa/inet.h> - <sys/socket.h> has everything */
diff --git a/nt/inc/netdb.h b/nt/inc/netdb.h
deleted file mode 100644
index 5bf232e7f5c..00000000000
--- a/nt/inc/netdb.h
+++ /dev/null
@@ -1 +0,0 @@
-/* null version of <netdb.h> - <sys/socket.h> has everything */
diff --git a/nt/inc/netinet/in.h b/nt/inc/netinet/in.h
deleted file mode 100644
index 46fb0faccea..00000000000
--- a/nt/inc/netinet/in.h
+++ /dev/null
@@ -1 +0,0 @@
-/* null version of <netinet/in.h> - <sys/socket.h> has everything */
diff --git a/nt/inc/pwd.h b/nt/inc/pwd.h
deleted file mode 100644
index 6202ccd1e75..00000000000
--- a/nt/inc/pwd.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _PWD_H_
-#define _PWD_H_
-/*
- * pwd.h doesn't exist on NT, so we put together our own.
- */
-
-struct passwd {
- char *pw_name;
- char *pw_passwd;
- int pw_uid;
- int pw_gid;
- int pw_quota;
- char *pw_gecos;
- char *pw_dir;
- char *pw_shell;
-};
-
-#endif /* _PWD_H_ */
diff --git a/nt/inc/sys/dir.h b/nt/inc/sys/dir.h
deleted file mode 100644
index 203e27f2fe7..00000000000
--- a/nt/inc/sys/dir.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * map sys\dir.h to ..\..\..\src\ndir.h
- */
-
-#include "..\..\..\src\ndir.h"
diff --git a/nt/inc/sys/file.h b/nt/inc/sys/file.h
deleted file mode 100644
index 8536d0362f1..00000000000
--- a/nt/inc/sys/file.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * sys\file.h doesn't exist on NT - only needed for these constants
- */
-
-#define F_OK 0
-#define X_OK 1
-#define W_OK 2
-#define R_OK 4
diff --git a/nt/inc/sys/ioctl.h b/nt/inc/sys/ioctl.h
deleted file mode 100644
index dc0957873da..00000000000
--- a/nt/inc/sys/ioctl.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * sys\ioctl.h doesn't exist on NT...rather than including it conditionally
- * in many of the source files, we just extend the include path so that the
- * compiler will pick this up empty header instead.
- */
diff --git a/nt/inc/sys/param.h b/nt/inc/sys/param.h
deleted file mode 100644
index 397c5ffae66..00000000000
--- a/nt/inc/sys/param.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _PARAM_H_
-#define _PARAM_H_
-
-/*
- * sys\param.h doesn't exist on NT, so we'll make one.
- */
-
-#define NBPG 4096
-
-#endif /* _PARAM_H_ */
diff --git a/nt/inc/sys/socket.h b/nt/inc/sys/socket.h
deleted file mode 100644
index a8f00f83502..00000000000
--- a/nt/inc/sys/socket.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* Workable version of <sys/socket.h> based on winsock.h */
-
-#ifndef _SOCKET_H_
-#define _SOCKET_H_
-
-/* defeat the multiple include protection */
-#ifdef _WINSOCKAPI_
-#undef _WINSOCKAPI_
-#endif
-
-/* avoid confusion with our version of select */
-#ifdef select
-#undef select
-#define MUST_REDEF_SELECT
-#endif
-
-/* avoid clashing with our version of FD_SET if already defined */
-#ifdef FD_SET
-#undef FD_SET
-#undef FD_CLR
-#undef FD_ISSET
-#undef FD_ZERO
-#endif
-
-/* allow us to provide our own version of fd_set */
-#define fd_set ws_fd_set
-
-/* avoid duplicate definition of timeval */
-#ifdef HAVE_TIMEVAL
-#define timeval ws_timeval
-#endif
-
-#include <winsock.h>
-
-/* redefine select to reference our version */
-#ifdef MUST_REDEF_SELECT
-#define select sys_select
-#undef MUST_REDEF_SELECT
-#endif
-
-/* revert to our version of FD_SET */
-#undef FD_SET
-#undef FD_CLR
-#undef FD_ISSET
-#undef FD_ZERO
-#undef fd_set
-#include "w32.h"
-
-#ifdef HAVE_TIMEVAL
-#undef timeval
-#endif
-
-/* shadow functions where we provide our own wrapper */
-#define socket sys_socket
-#define bind sys_bind
-#define connect sys_connect
-#define htons sys_htons
-#define ntohs sys_ntohs
-#define inet_addr sys_inet_addr
-#define gethostname sys_gethostname
-#define gethostbyname sys_gethostbyname
-#define getservbyname sys_getservbyname
-
-int sys_socket(int af, int type, int protocol);
-int sys_bind (int s, const struct sockaddr *addr, int namelen);
-int sys_connect (int s, const struct sockaddr *addr, int namelen);
-u_short sys_htons (u_short hostshort);
-u_short sys_ntohs (u_short netshort);
-unsigned long sys_inet_addr (const char * cp);
-int sys_gethostname (char * name, int namelen);
-struct hostent * sys_gethostbyname(const char * name);
-struct servent * sys_getservbyname(const char * name, const char * proto);
-
-/* we are providing a real h_errno variable */
-#undef h_errno
-extern int h_errno;
-
-/* map winsock error codes to standard names */
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#define EINPROGRESS WSAEINPROGRESS
-#define EALREADY WSAEALREADY
-#define ENOTSOCK WSAENOTSOCK
-#define EDESTADDRREQ WSAEDESTADDRREQ
-#define EMSGSIZE WSAEMSGSIZE
-#define EPROTOTYPE WSAEPROTOTYPE
-#define ENOPROTOOPT WSAENOPROTOOPT
-#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
-#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
-#define EOPNOTSUPP WSAEOPNOTSUPP
-#define EPFNOSUPPORT WSAEPFNOSUPPORT
-#define EAFNOSUPPORT WSAEAFNOSUPPORT
-#define EADDRINUSE WSAEADDRINUSE
-#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
-#define ENETDOWN WSAENETDOWN
-#define ENETUNREACH WSAENETUNREACH
-#define ENETRESET WSAENETRESET
-#define ECONNABORTED WSAECONNABORTED
-#define ECONNRESET WSAECONNRESET
-#define ENOBUFS WSAENOBUFS
-#define EISCONN WSAEISCONN
-#define ENOTCONN WSAENOTCONN
-#define ESHUTDOWN WSAESHUTDOWN
-#define ETOOMANYREFS WSAETOOMANYREFS
-#define ETIMEDOUT WSAETIMEDOUT
-#define ECONNREFUSED WSAECONNREFUSED
-#define ELOOP WSAELOOP
-/* #define ENAMETOOLONG WSAENAMETOOLONG */
-#define EHOSTDOWN WSAEHOSTDOWN
-#define EHOSTUNREACH WSAEHOSTUNREACH
-/* #define ENOTEMPTY WSAENOTEMPTY */
-#define EPROCLIM WSAEPROCLIM
-#define EUSERS WSAEUSERS
-#define EDQUOT WSAEDQUOT
-#define ESTALE WSAESTALE
-#define EREMOTE WSAEREMOTE
-
-#endif /* _SOCKET_H_ */
-
-/* end of socket.h */
diff --git a/nt/inc/sys/time.h b/nt/inc/sys/time.h
deleted file mode 100644
index dc270998609..00000000000
--- a/nt/inc/sys/time.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * sys/time.h doesn't exist on NT
- */
-
-struct timeval
- {
- long tv_sec; /* seconds */
- long tv_usec; /* microseconds */
- };
-struct timezone
- {
- int tz_minuteswest; /* minutes west of Greenwich */
- int tz_dsttime; /* type of dst correction */
- };
-
-void gettimeofday (struct timeval *, struct timezone *);
-
-/* end of sys/time.h */
diff --git a/nt/inc/unistd.h b/nt/inc/unistd.h
deleted file mode 100644
index c1caa77a697..00000000000
--- a/nt/inc/unistd.h
+++ /dev/null
@@ -1 +0,0 @@
-/* Fake unistd.h: config.h already provides most of the relevant things. */
diff --git a/nt/install b/nt/install
deleted file mode 100644
index d9fbfa343c1..00000000000
--- a/nt/install
+++ /dev/null
@@ -1,88 +0,0 @@
- Building and Installing Emacs
- on Windows NT and Windows 95
-
-You need a compiler package to build and install Emacs on NT or Win95.
-If you don't have one, precompiled versions are available in
-ftp://ftp.cs.washington.edu/pub/ntemacs/<version>.
-
-Configuring:
-
-(1) In previous versions, you needed to edit makefile.def
- to reflect the compiler package that you are using. You should no
- longer have to do this if you have defined the INCLUDE and LIB
- environment variables, as is customary for use with Windows compilers.
- (Unless you are using MSVCNT 1.1, in which case you will need
- to set MSVCNT11 to be a non-zero value at the top of makefile.def.)
-
-(2) Choose the directory into which Emacs will be installed, and
- edit makefile.def to define INSTALL_DIR to be this directory.
- (Alternatively, if you have INSTALL_DIR set as an environment
- variable, the build process will ignore the value in makefile.def
- and use the value of the environment variable instead.) Note
- that if it is not installed in the directory in which it is built,
- the ~16 MB of lisp files will be copied into the installation directory.
-
- Also, makefile.def is sometimes unpacked read-only; use
-
- > attrib -r makefile.def
-
- to make it writable.
-
-(3) You may need to edit nt/paths.h to specify some other device
- instead of `C:'.
-
-Building:
-
-(4) The target to compile the sources is "all", and is recursive starting
- one directory up. The makefiles for the NT port are in files named
- "makefile.nt". To get things started, type in this directory:
-
- > nmake -f makefile.nt all
-
- or use the ebuild.bat file.
-
- When the files are compiled, you will see some warning messages declaring
- that some functions don't return a value, or that some data conversions
- will be lossy, etc. You can safely ignore these messages. The warnings
- may be fixed in the main FSF source at some point, but until then we
- will just live with them.
-
- NOTE: You should not have to edit src\paths.h to get Emacs to run
- correctly. All of the variables in src\paths.h are configured
- during start up using the nt\emacs.bat file (which gets installed
- as bin\emacs.bat -- see below).
-
-Installing:
-
-(5) Currently, Emacs requires a number of environment variables to be set
- for it to run correctly. A batch file, emacs.bat, is provided that
- sets these variables appropriately and then runs the executable
- (emacs.bat is generated using the definition of INSTALL_DIR in
- nt\makefile.def and the contents of nt\emacs.bat.in).
-
-(6) The install process will install the files necessary to run Emacs in
- INSTALL_DIR (which may be the directory in which it was built),
- and create a program manager/folder icon in a folder called GNU Emacs.
- From this directory, type:
-
- > nmake -f makefile.nt install
-
- or use the install.bat file.
-
-(7) Create the Emacs startup file. Under Unix, this file is .emacs;
- under NT and Win95, this files is _emacs. (If you would like to
- use a .emacs file that, for example, you share with a Unix version
- of Emacs, you can invoke Emacs with the -l option to specify the
- .emacs file that you would like to load.) Note that Emacs requires
- the environment variable HOME to be set in order for it to locate the
- _emacs file. Ideally, HOME should not be set in the emacs.bat file
- as it will be different for each user. (HOME could be set,
- for example, in the System panel of the Control Panel).
-
-(8) Either click on the icon, or run the emacs.bat file, and away you go.
-
- If you would like to resize the command window that Emacs uses,
- or change the font or colors, click on the program manager icon
- to start Emacs. Change the settings using the "-" menu in the upper
- left hand corner of the window, making sure to select the "Save"
- options in the dialog boxes as you do so. Exit Emacs and restart.
diff --git a/nt/install.bat b/nt/install.bat
deleted file mode 100755
index d506efe9d2f..00000000000
--- a/nt/install.bat
+++ /dev/null
@@ -1,7 +0,0 @@
-@echo off
-if (%1) == (speed) set BUILD_TYPE=spd
-if (%1) == (speed) shift
-if not (%1) == () set INSTALL_DIR=%1
-nmake -f makefile.nt install
-set INSTALL_DIR=
-set BUILD_TYPE=
diff --git a/nt/makefile.def b/nt/makefile.def
deleted file mode 100644
index e83b0b71b07..00000000000
--- a/nt/makefile.def
+++ /dev/null
@@ -1,200 +0,0 @@
-#
-# Makefile definition file for building GNU Emacs on Windows NT
-#
-# GNU Emacs is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# GNU Emacs is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Emacs; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-# Geoff Voelker (voelker@cs.washington.edu) 9-6-94
-
-#
-# BEGIN CONFIGURATION
-#
-
-# Define the following to build the GUI version
-#
-NTGUI=1
-
-# Set INSTALL_DIR to be the directory into which you want emacs installed.
-#
-!ifndef INSTALL_DIR
-INSTALL_DIR = C:\emacs
-!endif
-
-# Define MSVCNT11 to be nonzero if you are using the MSVCNT 1.1 environment.
-# MSVCNT11 = 1
-MSVCNT11 = 0
-
-#
-# END CONFIGURATION
-#
-
-# Check that the INCLUDE and LIB environment variables are set.
-#
-!ifndef INCLUDE
-!error The INCLUDE environment variable needs to be set.
-!endif
-!ifndef LIB
-!error The LIB environment variable needs to be set.
-!endif
-
-# Determine the architecture we're running on.
-# Define ARCH for our purposes;
-# Define CPU for use by ntwin32.mak;
-# Define CONFIG_H to the appropriate config.h for the system;
-#
-!ifdef PROCESSOR_ARCHITECTURE
-# We're on Windows NT
-CPU = $(PROCESSOR_ARCHITECTURE)
-CONFIG_H = config.nt
-OS_TYPE = winnt
-! if "$(PROCESSOR_ARCHITECTURE)" == "x86"
-ARCH = i386
-CPU = i386
-! else
-! if "$(PROCESSOR_ARCHITECTURE)" == "MIPS"
-ARCH = mips
-! else
-! if "$(PROCESSOR_ARCHITECTURE)" == "ALPHA"
-ARCH = alpha
-! else
-! if "$(PROCESSOR_ARCHITECTURE)" == "PPC"
-ARCH = ppc
-! else
-!error Unknown architecture type "$(PROCESSOR_ARCHITECTURE)"
-! endif
-! endif
-! endif
-! endif
-!else
-# We're on Windows 95
-ARCH = i386
-CPU = i386
-CONFIG_H = config.nt
-OS_TYPE = win95
-!endif
-
-# Include ntwin32.mak. So far, this file seems to be supported by every
-# Microsoft compiler on NT and Win95 and properly defines the executable
-# names and libraries necessary to build Emacs. I do not have access
-# to any other vendor compilers, so I do not know if they supply this
-# file, too. For now I'll assume that they do.
-#
-!include <ntwin32.mak>
-
-# Using cvtres is necessary on NT 3.10 and doesn't hurt on later platforms.
-CVTRES = cvtres.exe
-AR = $(implib)
-# The assignment $(CC) = $(cc) fails even though variables are case sensitive.
-LINK_TMP = $(link)
-LINK = $(LINK_TMP)
-CC_TMP = $(cc)
-CC = $(CC_TMP)
-
-# advapi32.lib is left off of $(baselibs) on NT 3.10
-!if "$(baselibs)" == "kernel32.lib "
-ADVAPI32 = advapi32.lib
-!else
-ADVAPI32 =
-!endif
-
-# Older ntwin32.mak files do not define libc; do it for them.
-!ifndef libc
-libc = libc.lib
-!endif
-
-# The base libraries for compiling Emacs on NT. With MSVC, this should
-# include oldnames.lib.
-!if $(MSVCNT11)
-BASE_LIBS = $(libc) $(baselibs) oldnames.lib
-!else
-BASE_LIBS = $(libc) $(baselibs)
-!endif
-
-# We want any debugging info in the executable.
-!if "$(LINK)" == "link32"
-SYS_LDFLAGS =
-!else
-SYS_LDFLAGS = -pdb:none -release -incremental:no -version:3.10
-!endif
-
-INC = -I.
-CFLAGS_COMMON = -nologo $(INC) $(ARCH_CFLAGS) $(LOCAL_FLAGS) -DWIN32_LEAN_AND_MEAN -D$(ARCH)
-!if $(MSVCNT11)
-CFLAGS = $(CFLAGS_COMMON) -D_CRTAPI1=_cdecl
-!else
-CFLAGS = $(CFLAGS_COMMON)
-!endif
-!ifdef NTGUI
-CFLAGS = $(CFLAGS) -DHAVE_NTGUI=1
-!endif
-
-!ifdef BUILD_TYPE
-OBJDIR = obj-$(BUILD_TYPE)
-!else
-OBJDIR = obj
-!endif
-$(OBJDIR):; -mkdir $(OBJDIR)
-BLD = $(OBJDIR)\$(ARCH)
-$(BLD): $(OBJDIR)
- -mkdir $(BLD)
-
-CP = copy
-CP_DIR = xcopy /f/r/i/e/d
-
-!if "$(OS_TYPE)" == "win95"
-DEL = deltree /y
-DEL_TREE = deltree /y
-!else
-DEL = del
-# This is completely braindamaged, but it's the only routine known to be there
-DEL_TREE = echo y | rmdir /s
-!endif
-
-# The location of the icon file
-EMACS_ICON_PATH = ..\nt\emacs.ico
-
-# Lets us add icons to the GNU Emacs folder
-ADDPM = ..\nt\$(BLD)\addpm.exe
-
-!if "$(ARCH)" == "i386"
-!if "$(BUILD_TYPE)" == "spd"
-ARCH_CFLAGS = -nologo -D_X86_=1 -c -Zel -W2 -H63 -O2b2 -G5d -Zi
-!else
-ARCH_CFLAGS = -nologo -D_X86_=1 -c -Zel -W2 -H63 -G3d -Zi -Od
-!endif
-ARCH_LDFLAGS = -align:0x1000 $(SYS_LDFLAGS)
-
-!else
-!if "$(ARCH)" == "mips"
-ARCH_CFLAGS = -D_MIPS_=1 -c -W2 -Zi -Od -Gt0
-ARCH_LDFLAGS = -align:0x1000 $(SYS_LDFLAGS)
-
-!else
-!if "$(ARCH)" == "alpha"
-ARCH_CFLAGS = -D_ALPHA_=1 -c -Ze -Zi -W2 -D__stdcall= -D__cdecl=
-ARCH_LDFLAGS = -align:0x2000 $(SYS_LDFLAGS)
-
-!else
-!if "$(ARCH)" == "ppc"
-# These flags are a guess...if they don't work, please send me mail.
-ARCH_CFLAGS = -D_PPC_=1 -c -Ze -Zi -W2 -Od
-ARCH_LDFLAGS = -align:0x1000 $(SYS_LDFLAGS)
-
-!else
-!ERROR Unknown architecture type "$(ARCH)".
-!endif
-!endif
-!endif
-!endif
diff --git a/nt/makefile.nt b/nt/makefile.nt
deleted file mode 100644
index 336dbfc836f..00000000000
--- a/nt/makefile.nt
+++ /dev/null
@@ -1,156 +0,0 @@
-#
-# Top level makefile for building GNU Emacs on Windows NT
-#
-# This file is part of GNU Emacs.
-#
-# GNU Emacs is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# GNU Emacs is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Emacs; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-# Geoff Voelker (voelker@cs.washington.edu) 11-20-93
-# 9-6-94
-!include makefile.def
-
-ALL = $(BLD)\addpm.exe $(BLD)\runemacs.exe
-!if $(MSVCNT11)
-TRES = $(BLD)\emacs.res
-!else
-TRES = $(BLD)\emacs.rbj
-!endif
-
-.c{$(BLD)}.obj:
- $(CC) $(CFLAGS) -Fo$@ $<
-
-addpm: $(BLD) $(BLD)\addpm.exe
-$(BLD)\addpm.obj: addpm.c
-$(BLD)\addpm.exe: $(BLD)\addpm.obj
- $(LINK) -out:$@ -subsystem:console -entry:mainCRTStartup \
- $(SYS_LDFLAGS) $** $(BASE_LIBS) $(ADVAPI32) user32.lib
-
-#
-# The resource file. NT 3.10 requires the use of cvtres; even though
-# it is not necessary on later versions, it is still ok to use it.
-#
-$(TRES): emacs.rc
- $(RC) -Fo$(BLD)\emacs.res $**
-!if !$(MSVCNT11)
- $(CVTRES) -r -$(ARCH) -o $@ $(BLD)\emacs.res
-!endif
-
-runemacs: $(BLD) $(BLD)\runemacs.exe
-$(BLD)\runemacs.obj: runemacs.c
-$(BLD)\runemacs.exe: $(BLD)\runemacs.obj $(TRES)
- $(LINK) -out:$@ -subsystem:windows -entry:WinMainCRTStartup \
- $(SYS_LDFLAGS) $** $(BASE_LIBS) $(ADVAPI32) user32.lib
-
-# Since Windows 95 does not support multiple commands on one command line
-# (e.g., in for loops), we cannot use for loops any more.
-# SUBDIRS = lib-src src lisp
-
-#
-# Build emacs
-#
-BUILD_CMD = $(MAKE) -f makefile.nt all
-all: $(BLD) $(ALL)
- cd ..\lib-src
- $(BUILD_CMD)
- cd ..\src
- $(BUILD_CMD)
- cd ..\lisp
- $(BUILD_CMD)
- cd ..\nt
-
-
-emacs.bat: emacs.bat.in
- echo @echo off > emacs.bat
- echo REM !!! Warning: This file automatically generated !!! >> emacs.bat
- echo set emacs_dir=$(INSTALL_DIR)>> emacs.bat
- type emacs.bat.in >> emacs.bat
-
-#
-# Build and install emacs in INSTALL_DIR
-#
-INSTALL_CMD = $(MAKE) -f makefile.nt install
-install: all emacs.bat
- - mkdir $(INSTALL_DIR)
- cd ..\lib-src
- $(INSTALL_CMD)
- cd ..\src
- $(INSTALL_CMD)
- cd ..\lisp
- $(INSTALL_CMD)
- cd ..\nt
- - $(CP) emacs.bat $(INSTALL_DIR)\bin
- - $(CP) $(BLD)\addpm.exe $(INSTALL_DIR)\bin
- - $(CP) $(BLD)\runemacs.exe $(INSTALL_DIR)\bin
- - $(ADDPM) $(INSTALL_DIR)
- - $(DEL) ..\same-dir.tst
- - $(DEL) $(INSTALL_DIR)\same-dir.tst
- echo SameDirTest > $(INSTALL_DIR)\same-dir.tst
- if not exist ..\same-dir.tst $(MAKE) -f makefile.nt real_install
- - $(DEL) ..\same-dir.tst
- - $(DEL) $(INSTALL_DIR)\same-dir.tst
-
-#
-# This installs executables from ..\bin into the installation directory
-# without building anything.
-#
-fast_install:
- - mkdir $(INSTALL_DIR)\data
- $(CP) ..\lib-src\DOC $(INSTALL_DIR)\etc
- - mkdir $(INSTALL_DIR)\bin
- - $(CP) emacs.bat $(INSTALL_DIR)\bin
- - $(CP) $(BLD)\addpm.exe $(INSTALL_DIR)\bin
- - $(CP) $(BLD)\runemacs.exe $(INSTALL_DIR)\bin
- - $(DEL) ..\same-dir.tst
- - $(DEL) $(INSTALL_DIR)\same-dir.tst
- echo SameDirTest > $(INSTALL_DIR)\same-dir.tst
- if not exist ..\same-dir.tst $(CP) ..\bin\emacs.exe $(INSTALL_DIR)\bin
- if not exist ..\same-dir.tst $(CP) ..\bin\etags.exe $(INSTALL_DIR)\bin
- if not exist ..\same-dir.tst $(CP) ..\bin\ctags.exe $(INSTALL_DIR)\bin
- if not exist ..\same-dir.tst nmake -f $(MAKE) real_install
- - $(DEL) ..\same-dir.tst
- - $(DEL) $(INSTALL_DIR)\same-dir.tst
-
-real_install:
- - $(DEL) ..\same-dir.tst
- - $(DEL) $(INSTALL_DIR)\same-dir.tst
- echo SameDirTest > $(INSTALL_DIR)\same-dir.tst
- - mkdir $(INSTALL_DIR)\etc
- - mkdir $(INSTALL_DIR)\info
- - mkdir $(INSTALL_DIR)\lock
- - mkdir $(INSTALL_DIR)\data
- - mkdir $(INSTALL_DIR)\site-lisp
- if not exist ..\same-dir.tst $(CP_DIR) ..\etc $(INSTALL_DIR)\etc
- if not exist ..\same-dir.tst $(CP_DIR) ..\info $(INSTALL_DIR)\info
- - $(DEL) ..\same-dir.tst
- - $(DEL) $(INSTALL_DIR)\same-dir.tst
-
-#
-# Maintenance
-#
-CLEAN_CMD = $(MAKE) -f makefile.nt clean
-clean:; - $(DEL) *~ *.pdb
- - $(DEL_TREE) deleted
- - $(DEL_TREE) $(OBJDIR)
- - $(DEL_TREE) ..\bin
- - $(DEL) ..\etc\DOC ..\etc\DOC-X
- - $(DEL) emacs.bat
- cd ..\lib-src
- $(CLEAN_CMD)
- cd ..\src
- $(CLEAN_CMD)
- cd ..\lisp
- $(CLEAN_CMD)
- cd ..\nt
diff --git a/nt/paths.h b/nt/paths.h
deleted file mode 100644
index f8a91e837cd..00000000000
--- a/nt/paths.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Hey Emacs, this is -*- C -*- code! */
-
-/* Backslashify the default paths for NT */
-
-/* The default search path for Lisp function "load".
- This sets load-path. */
-/* #define PATH_LOADSEARCH "/usr/local/lib/emacs/lisp" */
-#define PATH_LOADSEARCH "C:\\emacs\\lisp"
-
-/* Like PATH_LOADSEARCH, but used only when Emacs is dumping. This
- path is usually identical to PATH_LOADSEARCH except that the entry
- for the directory containing the installed lisp files has been
- replaced with ../lisp. */
-/* #define PATH_DUMPLOADSEARCH "../lisp" */
-#define PATH_DUMPLOADSEARCH "..\\..\\..\\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 name in it sets the Lisp
- variable exec-directory. exec-directory is used for finding
- executables and other architecture-dependent files. */
-/* #define PATH_EXEC "/usr/local/lib/emacs/etc" */
-#define PATH_EXEC "C:\\emacs\\bin"
-
-/* Where Emacs should look for its architecture-independent data
- files, like the NEWS file. The lisp variable data-directory
- is set to this value. */
-/* #define PATH_DATA "/usr/local/lib/emacs/data" */
-#define PATH_DATA "C:\\emacs\\data"
-
-/* Where Emacs should look for its docstring file. The lisp variable
- doc-directory is set to this value. */
-#define PATH_DOC "C:\\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/lib/emacs/lock/" */
-#define PATH_LOCK "C:\\emacs\\lock\\"
-
-/* Where the configuration process believes the info tree lives. The
- lisp variable configure-info-directory gets its value from this
- macro, and is then used to set the Info-default-directory-list. */
-/* #define PATH_INFO "/usr/local/info" */
-#define PATH_INFO "C:\\emacs\\info"
diff --git a/nt/runemacs.c b/nt/runemacs.c
deleted file mode 100644
index 88e14a30d81..00000000000
--- a/nt/runemacs.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- Simple program to start Emacs with its console window hidden.
-
- This program is provided purely for convenience, since most users will
- use Emacs in windowing (GUI) mode, and will not want to have an extra
- console window lying around. */
-
-/*
- You may want to define this if you want to be able to install updated
- emacs binaries even when other users are using the current version.
- The problem with some file servers (notably Novell) is that an open
- file cannot be overwritten, deleted, or even renamed. So if someone
- is running emacs.exe already, you cannot install a newer version.
- By defining CHOOSE_NEWEST_EXE, you can name your new emacs.exe
- something else which matches "emacs*.exe", and runemacs will
- automatically select the newest emacs executeable in the bin directory.
- (So you'll probably be able to delete the old version some hours/days
- later).
-*/
-
-/* #define CHOOSE_NEWEST_EXE */
-
-#define WIN32
-
-#include <windows.h>
-#include <string.h>
-#include <malloc.h>
-
-int WINAPI
-WinMain (HINSTANCE hSelf, HINSTANCE hPrev, LPSTR cmdline, int nShow)
-{
- STARTUPINFO start;
- SECURITY_ATTRIBUTES sec_attrs;
- SECURITY_DESCRIPTOR sec_desc;
- PROCESS_INFORMATION child;
- int wait_for_child = FALSE;
- DWORD ret_code = 0;
- char *new_cmdline;
- char *p;
- char modname[MAX_PATH];
-
- if (!GetModuleFileName (NULL, modname, MAX_PATH))
- goto error;
- if ((p = strrchr (modname, '\\')) == NULL)
- goto error;
- *p = 0;
-
- new_cmdline = alloca (MAX_PATH + strlen (cmdline) + 1);
- strcpy (new_cmdline, modname);
-
-#ifdef CHOOSE_NEWEST_EXE
- {
- /* Silly hack to allow new versions to be installed on
- server even when current version is in use. */
-
- char * best_name = alloca (MAX_PATH + 1);
- FILETIME best_time = {0,0};
- WIN32_FIND_DATA wfd;
- HANDLE fh;
- p = new_cmdline + strlen (new_cmdline);
- strcpy (p, "\\emacs*.exe ");
- fh = FindFirstFile (new_cmdline, &wfd);
- if (fh == INVALID_HANDLE_VALUE)
- goto error;
- do
- {
- if (wfd.ftLastWriteTime.dwHighDateTime > best_time.dwHighDateTime
- || (wfd.ftLastWriteTime.dwHighDateTime == best_time.dwHighDateTime
- && wfd.ftLastWriteTime.dwLowDateTime > best_time.dwLowDateTime))
- {
- best_time = wfd.ftLastWriteTime;
- strcpy (best_name, wfd.cFileName);
- }
- }
- while (FindNextFile (fh, &wfd));
- FindClose (fh);
- *p++ = '\\';
- strcpy (p, best_name);
- strcat (p, " ");
- }
-#else
- strcat (new_cmdline, "\\emacs.exe ");
-#endif
-
- /* Append original arguments if any; first look for -wait as first
- argument, and apply that ourselves. */
- if (strncmp (cmdline, "-wait", 5) == 0)
- {
- wait_for_child = TRUE;
- cmdline += 5;
- }
- strcat (new_cmdline, cmdline);
-
- /* Set emacs_dir variable if runemacs was in "%emacs_dir%\bin". */
- if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0)
- {
- *p = 0;
- for (p = modname; *p; p++)
- if (*p == '\\') *p = '/';
- SetEnvironmentVariable ("emacs_dir", modname);
- }
-
- memset (&start, 0, sizeof (start));
- start.cb = sizeof (start);
- start.dwFlags = STARTF_USESHOWWINDOW;
- start.wShowWindow = SW_HIDE;
-
- sec_attrs.nLength = sizeof (sec_attrs);
- sec_attrs.lpSecurityDescriptor = NULL;
- sec_attrs.bInheritHandle = FALSE;
-
- if (CreateProcess (NULL, new_cmdline, &sec_attrs, NULL, TRUE, 0,
- NULL, NULL, &start, &child))
- {
- if (wait_for_child)
- {
- WaitForSingleObject (child.hProcess, INFINITE);
- GetExitCodeProcess (child.hProcess, &ret_code);
- }
- CloseHandle (child.hThread);
- CloseHandle (child.hProcess);
- }
- else
- goto error;
- return (int) ret_code;
-
-error:
- MessageBox (NULL, "Could not start Emacs.", "Error", MB_ICONSTOP);
- return 1;
-}
diff --git a/src/.gdbinit b/src/.gdbinit
deleted file mode 100644
index ab47f0844ac..00000000000
--- a/src/.gdbinit
+++ /dev/null
@@ -1,272 +0,0 @@
-# Set up a mask to use.
-
-# Force loading of symbols, enough to give us gdb_valbits etc.
-set main
-
-# Find lwlib source files too.
-dir ../lwlib
-
-# This should be EMACS_INT, but in some cases that is a macro.
-# long ought to work in all cases right now.
-set $valmask = ((long)1 << gdb_valbits) - 1
-set $nonvalbits = gdb_emacs_intbits - gdb_valbits
-
-# Set up something to print out s-expressions.
-define pr
-set debug_print ($)
-end
-document pr
-Print the emacs s-expression which is $.
-Works only when an inferior emacs is executing.
-end
-
-define xtype
-output (enum Lisp_Type) (($ >> gdb_valbits) & 0x7)
-echo \n
-output ((($ >> gdb_valbits) & 0x7) == Lisp_Misc ? (enum Lisp_Misc_Type) (((struct Lisp_Free *) (($ & $valmask) | gdb_data_seg_bits))->type) : (($ >> gdb_valbits) & 0x7) == Lisp_Vectorlike ? ($size = ((struct Lisp_Vector *) (($ & $valmask) | gdb_data_seg_bits))->size, (enum pvec_type) (($size & PVEC_FLAG) ? $size & PVEC_TYPE_MASK : 0)) : 0)
-echo \n
-end
-document xtype
-Print the type of $, assuming it is an Emacs Lisp value.
-If the first type printed is Lisp_Vector or Lisp_Misc,
-the second line gives the more precise type.
-Otherwise the second line doesn't mean anything.
-end
-
-define xvectype
-set $size = ((struct Lisp_Vector *) (($ & $valmask) | gdb_data_seg_bits))->size
-output (enum pvec_type) (($size & PVEC_FLAG) ? $size & PVEC_TYPE_MASK : 0)
-echo \n
-end
-document xvectype
-Print the vector subtype of $, assuming it is a vector or pseudovector.
-end
-
-define xmisctype
-output (enum Lisp_Misc_Type) (((struct Lisp_Free *) (($ & $valmask) | gdb_data_seg_bits))->type)
-echo \n
-end
-document xmisctype
-Print the specific type of $, assuming it is some misc type.
-end
-
-define xint
-print (($ & $valmask) << $nonvalbits) >> $nonvalbits
-end
-document xint
-Print $, assuming it is an Emacs Lisp integer. This gets the sign right.
-end
-
-define xptr
-print (void *) (($ & $valmask) | gdb_data_seg_bits)
-end
-document xptr
-Print the pointer portion of $, assuming it is an Emacs Lisp value.
-end
-
-define xwindow
-print (struct window *) (($ & $valmask) | gdb_data_seg_bits)
-printf "%dx%d+%d+%d\n", $->width, $->height, $->left, $->top
-end
-document xwindow
-Print $ as a window pointer, assuming it is an Emacs Lisp window value.
-Print the window's position as "WIDTHxHEIGHT+LEFT+TOP".
-end
-
-define xmarker
-print (struct Lisp_Marker *) (($ & $valmask) | gdb_data_seg_bits)
-end
-document xmarker
-Print $ as a marker pointer, assuming it is an Emacs Lisp marker value.
-end
-
-define xoverlay
-print (struct Lisp_Overlay *) (($ & $valmask) | gdb_data_seg_bits)
-end
-document xoverlay
-Print $ as a overlay pointer, assuming it is an Emacs Lisp overlay value.
-end
-
-define xmiscfree
-print (struct Lisp_Free *) (($ & $valmask) | gdb_data_seg_bits)
-end
-document xmiscfree
-Print $ as a misc free-cell pointer, assuming it is an Emacs Lisp Misc value.
-end
-
-define xintfwd
-print (struct Lisp_Intfwd *) (($ & $valmask) | gdb_data_seg_bits)
-end
-document xintfwd
-Print $ as an integer forwarding pointer, assuming it is an Emacs Lisp Misc value.
-end
-
-define xboolfwd
-print (struct Lisp_Boolfwd *) (($ & $valmask) | gdb_data_seg_bits)
-end
-document xboolfwd
-Print $ as a boolean forwarding pointer, assuming it is an Emacs Lisp Misc value.
-end
-
-define xobjfwd
-print (struct Lisp_Objfwd *) (($ & $valmask) | gdb_data_seg_bits)
-end
-document xobjfwd
-Print $ as an object forwarding pointer, assuming it is an Emacs Lisp Misc value.
-end
-
-define xbufobjfwd
-print (struct Lisp_Buffer_Objfwd *) (($ & $valmask) | gdb_data_seg_bits)
-end
-document xbufobjfwd
-Print $ as a buffer-local object forwarding pointer, assuming it is an Emacs Lisp Misc value.
-end
-
-define xkbobjfwd
-print (struct Lisp_Kboard_Objfwd *) (($ & $valmask) | gdb_data_seg_bits)
-end
-document xkbobjfwd
-Print $ as a kboard-local object forwarding pointer, assuming it is an Emacs Lisp Misc value.
-end
-
-define xbuflocal
-print (struct Lisp_Buffer_Local_Value *) (($ & $valmask) | gdb_data_seg_bits)
-end
-document xbuflocal
-Print $ as a buffer-local-value pointer, assuming it is an Emacs Lisp Misc value.
-end
-
-define xbuffer
-print (struct buffer *) (($ & $valmask) | gdb_data_seg_bits)
-output &((struct Lisp_String *) ((($->name) & $valmask) | gdb_data_seg_bits))->data
-echo \n
-end
-document xbuffer
-Set $ as a buffer pointer, assuming it is an Emacs Lisp buffer value.
-Print the name of the buffer.
-end
-
-define xsymbol
-print (struct Lisp_Symbol *) ((((int) $) & $valmask) | gdb_data_seg_bits)
-output (char*)&$->name->data
-echo \n
-end
-document xsymbol
-Print the name and address of the symbol $.
-This command assumes that $ is an Emacs Lisp symbol value.
-end
-
-define xstring
-print (struct Lisp_String *) (($ & $valmask) | gdb_data_seg_bits)
-output ($->size > 1000) ? 0 : ($->data[0])@($->size)
-echo \n
-end
-document xstring
-Print the contents and address of the string $.
-This command assumes that $ is an Emacs Lisp string value.
-end
-
-define xvector
-print (struct Lisp_Vector *) (($ & $valmask) | gdb_data_seg_bits)
-output ($->size > 50) ? 0 : ($->contents[0])@($->size)
-echo \n
-end
-document xvector
-Print the contents and address of the vector $.
-This command assumes that $ is an Emacs Lisp vector value.
-end
-
-define xframe
-print (struct frame *) (($ & $valmask) | gdb_data_seg_bits)
-end
-document xframe
-Print $ as a frame pointer, assuming it is an Emacs Lisp frame value.
-end
-
-define xwinconfig
-print (struct save_window_data *) (($ & $valmask) | gdb_data_seg_bits)
-end
-document xwinconfig
-Print $ as a window configuration pointer, assuming it is an Emacs Lisp window configuration value.
-end
-
-define xcompiled
-print (struct Lisp_Vector *) (($ & $valmask) | gdb_data_seg_bits)
-output ($->contents[0])@($->size & 0xff)
-end
-document xcompiled
-Print $ as a compiled function pointer, assuming it is an Emacs Lisp compiled value.
-end
-
-define xcons
-print (struct Lisp_Cons *) (($ & $valmask) | gdb_data_seg_bits)
-output *$
-echo \n
-end
-document xcons
-Print the contents of $, assuming it is an Emacs Lisp cons.
-end
-
-define xcar
-print ((($ >> gdb_valbits) & 0xf) == Lisp_Cons ? ((struct Lisp_Cons *) (($ & $valmask) | gdb_data_seg_bits))->car : 0)
-end
-document xcar
-Print the car of $, assuming it is an Emacs Lisp pair.
-end
-
-define xcdr
-print ((($ >> gdb_valbits) & 0xf) == Lisp_Cons ? ((struct Lisp_Cons *) (($ & $valmask) | gdb_data_seg_bits))->cdr : 0)
-end
-document xcdr
-Print the cdr of $, assuming it is an Emacs Lisp pair.
-end
-
-define xsubr
-print (struct Lisp_Subr *) (($ & $valmask) | gdb_data_seg_bits)
-output *$
-echo \n
-end
-document xsubr
-Print the address of the subr which the Lisp_Object $ points to.
-end
-
-define xprocess
-print (struct Lisp_Process *) (($ & $valmask) | gdb_data_seg_bits)
-output *$
-echo \n
-end
-document xprocess
-Print the address of the struct Lisp_process which the Lisp_Object $ points to.
-end
-
-define xfloat
-print ((struct Lisp_Float *) (($ & $valmask) | gdb_data_seg_bits))->data
-end
-document xfloat
-Print $ assuming it is a lisp floating-point number.
-end
-
-define xscrollbar
-print (struct scrollbar *) (($ & $valmask) | gdb_data_seg_bits)
-output *$
-echo \n
-end
-document xscrollbar
-Print $ as a scrollbar pointer.
-end
-
-set print pretty on
-set print sevenbit-strings
-
-show environment DISPLAY
-show environment TERM
-set args -geometry 80x40+0+0
-
-# Don't let abort actually run, as it will make
-# stdio stop working and therefore the `pr' command above as well.
-break abort
-
-# If we are running in synchronous mode, we want a chance to look around
-# before Emacs exits. Perhaps we should put the break somewhere else
-# instead...
-break x_error_quitter
diff --git a/src/=Makefile.in b/src/=Makefile.in
deleted file mode 100644
index 1433f13e7a8..00000000000
--- a/src/=Makefile.in
+++ /dev/null
@@ -1,100 +0,0 @@
-# DIST: This is the distribution Makefile for Emacs. configure can
-# DIST: make most of the changes to this file you might want, so try
-# DIST: that first.
-
-MAKE = make
-# BSD doesn't have it as a default.
-
-# ==================== Things `configure' might edit ====================
-
-CC=cc
-CPP=cc -E
-CFLAGS=-g
-C_SWITCH_SYSTEM=
-srcdir=@srcdir@/src
-VPATH=@srcdir@/src
-LN_S=ln -s
-
-# ============================= Targets ==============================
-
-CPP = $(CC) -E -Is -Im
-#Note: an alternative is CPP = /lib/cpp
-
-# Just to avoid uncertainty.
-SHELL = /bin/sh
-
-SUBMAKEFLAGS = CC='${CC}' LN_S='${LN_S}' CFLAGS='${CFLAGS}' MAKE='${MAKE}'
-
-all: doall
-
-doall: xmakefile
- $(MAKE) ${SUBMAKEFLAGS} -f xmakefile ${MFLAGS} all
-
-mostlyclean:
- rm -f temacs prefix-args xmakefile* core \#* *.o libXMenu11.a
- rm -f ../etc/DOC
-clean: mostlyclean
- rm -f emacs-* emacs
-#This is used in making a distribution.
-#Do not use it on development directories!
-distclean: clean
- rm -f paths.h config.h ../etc/DOC-*
-realclean: distclean
- rm -f TAGS
-versionclean:
- -rm -f emacs emacs-* ../etc/DOC*
-extraclean: distclean
- -rm -f *~ \#* m/*~ s/*~
-
-emacs: doemacs
- @true
-
-doemacs: xmakefile
- $(MAKE) ${SUBMAKEFLAGS} -f xmakefile ${MFLAGS} emacs
-
-temacs: dotemacs
- @true
-
-dotemacs: xmakefile
- $(MAKE) ${SUBMAKEFLAGS} -f xmakefile ${MFLAGS} temacs
-
-SOURCES = *.[ch] [sm]/* COPYING Makefile.in ymakefile \
- config.h.in README COPYING ChangeLog vms.pp-trans
-unlock:
- chmod u+w $(SOURCES)
-
-relock:
- chmod -w $(SOURCES)
- chmod +w paths.h
-
-### Some makes, like Ultrix's make, complain if you put a comment in
-### the middle of a rule's command list! Dummies.
-
-### The flags for optimization and debugging depend on the
-### system, so take an ordinary CFLAGS value and choose the
-### appropriate CPP symbols to use in ymakefile.
-### If you have a problem with cc -E here, changing
-### the definition of CPP above may fix it.
-
-# Remake xmakefile whenever we reconfigure even if config.h didn't change.
-xmakefile: ymakefile config.h ../config.status
- -rm -f xmakefile xmakefile.new junk.c junk.cpp
- cp ${srcdir}/ymakefile junk.c
- ${CPP} -I. -I${srcdir} ${C_SWITCH_SYSTEM} ${CFLAGS} junk.c > junk.cpp
- < junk.cpp \
- sed -e 's/^#.*//' \
- -e 's/^[ \f\t][ \f\t]*$$//' \
- -e 's/^ / /' \
- -e 's|^\(srcdir *=\).*$$|\1'"${srcdir}"'|' \
- -e 's|^\(VPATH *=\).*$$|\1'"${srcdir}"'|' \
- | sed -n -e '/^..*$$/p' \
- > xmakefile.new
- mv -f xmakefile.new xmakefile
- chmod 444 xmakefile
- rm -f junk.c junk.cpp
-
-tagsfiles = [a-z]*.h [a-z]*.c ../lisp/[a-z]*.el ../lisp/term/[a-z]*.el
-TAGS: $(tagsfiles)
- etags $(tagsfiles)
-tags: TAGS
-.PHONY: tags
diff --git a/src/=XTests.c b/src/=XTests.c
deleted file mode 100644
index 4147ecd35d6..00000000000
--- a/src/=XTests.c
+++ /dev/null
@@ -1,179 +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[] = {4, 4};
- int dashes = 2;
-
- 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.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,
- &gc_values);
- XSetDashes (dpy, line_xor_gc, 0, dash_list, dashes);
-
- line_xor_inv_gc = XCreateGC (dpy, window,
- GCForeground | GCBackground | GCLineWidth,
- &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:
- switch (event.xbutton.button)
- {
- case Button1:
- XDrawLine (dpy, window, line_xor_gc, 25, 75, 300, 75);
- break;
-
- case Button2:
- XDrawLine (dpy, window, line_xor_inv_gc, 25, 25, 300, 25);
- break;
-
- case Button3:
- XDrawLine (dpy, window, line_xor_gc, 25, 25, 25, 125);
- 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/=XTests.h b/src/=XTests.h
deleted file mode 100644
index e91445af7ef..00000000000
--- a/src/=XTests.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#define page_glyf_width 30
-#define page_glyf_height 10
-static char page_glyf_bits[] = {
- 0xf0, 0xff, 0xff, 0x03, 0x08, 0x00, 0x00, 0x04, 0xc4, 0x19, 0xf3, 0x08,
- 0x42, 0xa5, 0x14, 0x10, 0xc1, 0xa5, 0x70, 0x20, 0x41, 0xbc, 0x16, 0x20,
- 0x42, 0xa4, 0x14, 0x10, 0x44, 0x24, 0xf3, 0x08, 0x08, 0x00, 0x00, 0x04,
- 0xf0, 0xff, 0xff, 0x03};
diff --git a/src/=convexos.h b/src/=convexos.h
deleted file mode 100644
index 94cdbf68346..00000000000
--- a/src/=convexos.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* Definitions file for GNU Emacs running on ConvexOS. */
-
-#include "bsd4-3.h"
-
-/* First pty name is /dev/pty?0. We have to search for it. */
-#undef FIRST_PTY_LETTER
-#define FIRST_PTY_LETTER first_pty_letter
-
-/* getpgrp requires no arguments. */
-#define GETPGRP_NO_ARG
diff --git a/src/=environ.c b/src/=environ.c
deleted file mode 100644
index 863f40ccd2a..00000000000
--- a/src/=environ.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/* Environment-hacking for GNU Emacs subprocess
- 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. */
-
-
-#include "config.h"
-#include "lisp.h"
-
-#ifdef MAINTAIN_ENVIRONMENT
-
-#ifdef VMS
-you lose -- this is un*x-only
-#endif
-
-/* alist of (name-string . value-string) */
-Lisp_Object Venvironment_alist;
-extern char **environ;
-
-void
-set_environment_alist (str, val)
- register Lisp_Object str, val;
-{
- register Lisp_Object tem;
-
- tem = Fassoc (str, Venvironment_alist);
- if (NULL (tem))
- if (NULL (val))
- ;
- else
- Venvironment_alist = Fcons (Fcons (str, val), Venvironment_alist);
- else
- if (NULL (val))
- Venvironment_alist = Fdelq (tem, Venvironment_alist);
- else
- XCONS (tem)->cdr = val;
-}
-
-
-
-static void
-initialize_environment_alist ()
-{
- register unsigned char **e, *s;
- extern char *index ();
-
- for (e = (unsigned char **) environ; *e; e++)
- {
- s = (unsigned char *) index (*e, '=');
- if (s)
- set_environment_alist (make_string (*e, s - *e),
- build_string (s + 1));
- }
-}
-
-
-unsigned char *
-getenv_1 (str, ephemeral)
- register unsigned char *str;
- int ephemeral; /* if ephmeral, don't need to gc-proof */
-{
- register Lisp_Object env;
- int len = strlen (str);
-
- for (env = Venvironment_alist; CONSP (env); env = XCONS (env)->cdr)
- {
- register Lisp_Object car = XCONS (env)->car;
- register Lisp_Object tem = XCONS (car)->car;
-
- if ((len == XSTRING (tem)->size) &&
- (!bcmp (str, XSTRING (tem)->data, len)))
- {
- /* Found it in the lisp environment */
- tem = XCONS (car)->cdr;
- if (ephemeral)
- /* Caller promises that gc won't make him lose */
- return XSTRING (tem)->data;
- else
- {
- register unsigned char **e;
- unsigned char *s;
- int ll = XSTRING (tem)->size;
-
- /* Look for element in the original unix environment */
- for (e = (unsigned char **) environ; *e; e++)
- if (!bcmp (str, *e, len) && *(*e + len) == '=')
- {
- s = *e + len + 1;
- if (strlen (s) >= ll)
- /* User hasn't either hasn't munged it or has set it
- to something shorter -- we don't have to cons */
- goto copy;
- else
- goto cons;
- };
- cons:
- /* User has setenv'ed it to a diferent value, and our caller
- isn't guaranteeing that he won't stash it away somewhere.
- We can't just return a pointer to the lisp string, as that
- will be corrupted when gc happens. So, we cons (in such
- a way that it can't be freed -- though this isn't such a
- problem since the only callers of getenv (as opposed to
- those of egetenv) are very early, before the user -could-
- have frobbed the environment. */
- s = (unsigned char *) xmalloc (ll + 1);
- copy:
- bcopy (XSTRING (tem)->data, s, ll + 1);
- return (s);
- }
- }
- }
- return ((unsigned char *) 0);
-}
-
-/* unsigned -- stupid delcaration in lisp.h */ char *
-getenv (str)
- register unsigned char *str;
-{
- return ((char *) getenv_1 (str, 0));
-}
-
-unsigned char *
-egetenv (str)
- register unsigned char *str;
-{
- return (getenv_1 (str, 1));
-}
-
-
-#if (1 == 1) /* use caller-alloca versions, rather than callee-malloc */
-int
-size_of_current_environ ()
-{
- register int size;
- Lisp_Object tem;
-
- tem = Flength (Venvironment_alist);
-
- size = (XINT (tem) + 1) * sizeof (unsigned char *);
- /* + 1 for environment-terminating 0 */
-
- for (tem = Venvironment_alist; !NULL (tem); tem = XCONS (tem)->cdr)
- {
- register Lisp_Object str, val;
-
- str = XCONS (XCONS (tem)->car)->car;
- val = XCONS (XCONS (tem)->car)->cdr;
-
- size += (XSTRING (str)->size +
- XSTRING (val)->size +
- 2); /* 1 for '=', 1 for '\000' */
- }
- return size;
-}
-
-void
-get_current_environ (memory_block)
- unsigned char **memory_block;
-{
- register unsigned char **e, *s;
- register int len;
- register Lisp_Object tem;
-
- e = memory_block;
-
- tem = Flength (Venvironment_alist);
-
- s = (unsigned char *) memory_block
- + (XINT (tem) + 1) * sizeof (unsigned char *);
-
- for (tem = Venvironment_alist; !NULL (tem); tem = XCONS (tem)->cdr)
- {
- register Lisp_Object str, val;
-
- str = XCONS (XCONS (tem)->car)->car;
- val = XCONS (XCONS (tem)->car)->cdr;
-
- *e++ = s;
- len = XSTRING (str)->size;
- bcopy (XSTRING (str)->data, s, len);
- s += len;
- *s++ = '=';
- len = XSTRING (val)->size;
- bcopy (XSTRING (val)->data, s, len);
- s += len;
- *s++ = '\000';
- }
- *e = 0;
-}
-
-#else
-/* dead code (this function mallocs, caller frees) superseded by above (which allows caller to use alloca) */
-unsigned char **
-current_environ ()
-{
- unsigned char **env;
- register unsigned char **e, *s;
- register int len, env_len;
- Lisp_Object tem;
- Lisp_Object str, val;
-
- tem = Flength (Venvironment_alist);
-
- env_len = (XINT (tem) + 1) * sizeof (char *);
- /* + 1 for terminating 0 */
-
- len = 0;
- for (tem = Venvironment_alist; !NULL (tem); tem = XCONS (tem)->cdr)
- {
- str = XCONS (XCONS (tem)->car)->car;
- val = XCONS (XCONS (tem)->car)->cdr;
-
- len += (XSTRING (str)->size +
- XSTRING (val)->size +
- 2);
- }
-
- e = env = (unsigned char **) xmalloc (env_len + len);
- s = (unsigned char *) env + env_len;
-
- for (tem = Venvironment_alist; !NULL (tem); tem = XCONS (tem)->cdr)
- {
- str = XCONS (XCONS (tem)->car)->car;
- val = XCONS (XCONS (tem)->car)->cdr;
-
- *e++ = s;
- len = XSTRING (str)->size;
- bcopy (XSTRING (str)->data, s, len);
- s += len;
- *s++ = '=';
- len = XSTRING (val)->size;
- bcopy (XSTRING (val)->data, s, len);
- s += len;
- *s++ = '\000';
- }
- *e = 0;
-
- return env;
-}
-
-#endif /* dead code */
-
-
-DEFUN ("getenv", Fgetenv, Sgetenv, 1, 2, "sEnvironment variable: \np",
- "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,\n\
- or the symbol t, meaning to return an alist representing the\n\
- current environment.")
- (str, interactivep)
- Lisp_Object str, interactivep;
-{
- Lisp_Object val;
-
- if (str == Qt) /* If arg is t, return whole environment */
- return (Fcopy_alist (Venvironment_alist));
-
- CHECK_STRING (str, 0);
- val = Fcdr (Fassoc (str, Venvironment_alist));
- if (!NULL (interactivep))
- {
- if (NULL (val))
- message ("%s not defined in environment", XSTRING (str)->data);
- else
- message ("\"%s\"", XSTRING (val)->data);
- }
- return val;
-}
-
-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.")
- (str, val)
- Lisp_Object str;
- Lisp_Object val;
-{
- Lisp_Object tem;
-
- CHECK_STRING (str, 0);
- if (!NULL (val))
- CHECK_STRING (val, 0);
-
- set_environment_alist (str, val);
- return val;
-}
-
-
-syms_of_environ ()
-{
- staticpro (&Venvironment_alist);
- defsubr (&Ssetenv);
- defsubr (&Sgetenv);
-}
-
-init_environ ()
-{
- Venvironment_alist = Qnil;
- initialize_environment_alist ();
-}
-
-#endif /* MAINTAIN_ENVIRONMENT */
diff --git a/src/=mach2.h b/src/=mach2.h
deleted file mode 100644
index c941c5ff2cf..00000000000
--- a/src/=mach2.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include "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
-
-/* Don't use -lc on the NeXT. */
-#define LIB_STANDARD -lsys_s
-#define LIB_MATH -lm
-
-#define environ _environ
-
-#define START_FILES pre-crt0.o
-#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/=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/=sol2-2.h b/src/=sol2-2.h
deleted file mode 100644
index 016f75e488a..00000000000
--- a/src/=sol2-2.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* casper@fwi.uva.nl says this file is not needed
- and sol2.h should work. */
-
-#include "sol2.h"
-
-/* Take care of libucb.a as well as X Windows. */
-#undef LD_SWITCH_SYSTEM
-#ifndef __GNUC__
-#define LD_SWITCH_SYSTEM -R/usr/openwin/lib:/usr/ucblib
-#else /* GCC */
-#define LD_SWITCH_SYSTEM -Xlinker -R/usr/openwin/lib:/usr/ucblib
-#endif /* GCC */
-
-/* Link with libucb.a. */
-#ifdef LIB_STANDARD
-#undef LIB_STANDARD
-#define LIB_STANDARD -lc -L/usr/ucblib -lucb
-#endif
diff --git a/src/=unexelf1.c b/src/=unexelf1.c
deleted file mode 100644
index a832755167e..00000000000
--- a/src/=unexelf1.c
+++ /dev/null
@@ -1,952 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
-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
-
-
- */
-
-/* Modified by wtien@urbana.mcd.mot.com of Motorola Inc.
- *
- * The above mechanism does not work if the unexeced ELF file is being
- * re-layout by other applications (such as `strip'). All the applications
- * that re-layout the internal of ELF will layout all sections in ascending
- * order of their file offsets. After the re-layout, the data2 section will
- * still be the LAST section in the section header vector, but its file offset
- * is now being pushed far away down, and causes part of it not to be mapped
- * in (ie. not covered by the load segment entry in PHDR vector), therefore
- * causes the new binary to fail.
- *
- * The solution is to modify the unexec algorithm to insert the new data2
- * section header right before the new bss section header, so their file
- * offsets will be in the ascending order. Since some of the section's (all
- * sections AFTER the bss section) indexes are now changed, we also need to
- * modify some fields to make them point to the right sections. This is done
- * by macro PATCH_INDEX. All the fields that need to be patched are:
- *
- * 1. ELF header e_shstrndx field.
- * 2. section header sh_link and sh_info field.
- * 3. symbol table entry st_shndx field.
- *
- * The above example now should look like:
-
- **** 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] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
- 0 0 0x4 0
-
-[17] 8 3 0x80c6800 0x7d800 0 .bss
- 0 0 0x4 0
-
-[18] 2 0 0 0x7d800 0x9b90 .symtab
- 19 371 0x4 0x10
-
-[19] 3 0 0 0x87390 0x8526 .strtab
- 0 0 0x1 0
-
-[20] 3 0 0 0x8f8b6 0x93 .shstrtab
- 0 0 0x1 0
-
-[21] 1 0 0 0x8f949 0x68b7 .comment
- 0 0 0x1 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>
-
-#ifdef __alpha__
-# include <sym.h> /* get COFF debugging symbol table declaration */
-#endif
-
-#if __GNU_LIBRARY__ - 0 >= 6
-# include <link.h> /* get ElfW etc */
-#endif
-
-#ifndef ElfW
-# ifdef __STDC__
-# define ElfW(type) Elf32_##type
-# else
-# define ElfW(type) Elf32_/**/type
-# endif
-#endif
-
-#ifndef emacs
-#define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1)
-#else
-#include <config.h>
-extern void fatal (char *, ...);
-#endif
-
-#ifndef ELF_BSS_SECTION_NAME
-#define ELF_BSS_SECTION_NAME ".bss"
-#endif
-
-/* Get the address of a particular section or program header entry,
- * accounting for the size of the entries.
- */
-/*
- On PPC Reference Platform running Solaris 2.5.1
- the plt section is also of type NOBI like the bss section.
- (not really stored) and therefore sections after the bss
- section start at the plt offset. The plt section is always
- the one just before the bss section.
- Thus, we modify the test from
- if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
- to
- if (NEW_SECTION_H (nn).sh_offset >=
- OLD_SECTION_H (old_bss_index-1).sh_offset)
- This is just a hack. We should put the new data section
- before the .plt section.
- And we should not have this routine at all but use
- the libelf library to read the old file and create the new
- file.
- The changed code is minimal and depends on prep set in m/prep.h
- Erik Deumens
- Quantum Theory Project
- University of Florida
- deumens@qtp.ufl.edu
- Apr 23, 1996
- */
-
-#define OLD_SECTION_H(n) \
- (*(ElfW(Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
-#define NEW_SECTION_H(n) \
- (*(ElfW(Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
-#define OLD_PROGRAM_H(n) \
- (*(ElfW(Phdr) *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
-#define NEW_PROGRAM_H(n) \
- (*(ElfW(Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
-
-#define PATCH_INDEX(n) \
- do { \
- if ((int) (n) >= old_bss_index) \
- (n)++; } while (0)
-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;
-{
- 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.
- */
- ElfW(Ehdr) *old_file_h, *new_file_h;
- ElfW(Phdr) *old_program_h, *new_program_h;
- ElfW(Shdr) *old_section_h, *new_section_h;
-
- /* Point to the section name table in the old file */
- char *old_section_names;
-
- ElfW(Addr) old_bss_addr, new_bss_addr;
- ElfW(Word) old_bss_size, new_data2_size;
- ElfW(Off) new_data2_offset;
- ElfW(Addr) new_data2_addr;
-
- int n, nn, 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 = (ElfW(Ehdr) *) old_base;
- old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
- old_section_h = (ElfW(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 < (int) 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,
- ELF_BSS_SECTION_NAME))
- 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)
- new_bss_addr = (ElfW(Addr)) sbrk (0);
-#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 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);
-
-#ifdef UNEXEC_USE_MAP_PRIVATE
- new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
- new_file, 0);
-#else
- new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
- new_file, 0);
-#endif
-
- if (new_base == (caddr_t) -1)
- fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
-
- new_file_h = (ElfW(Ehdr) *) new_base;
- new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
- new_section_h = (ElfW(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);
-
- /* Modify the e_shstrndx if necessary. */
- PATCH_INDEX (new_file_h->e_shstrndx);
-
- /* 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 (old_data_index = 1; old_data_index < (int) 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);
-
- /* Walk through all section headers, insert the new data2 section right
- before the new bss section. */
- for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++)
- {
- caddr_t src;
- /* If it is bss section, insert the new data2 section before it. */
- if (n == old_bss_index)
- {
- /* Steal the data section header for this data2 section. */
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
- new_file_h->e_shentsize);
-
- NEW_SECTION_H (nn).sh_addr = new_data2_addr;
- NEW_SECTION_H (nn).sh_offset = new_data2_offset;
- NEW_SECTION_H (nn).sh_size = new_data2_size;
- /* Use the bss section's alignment. This will assure that the
- new data2 section always be placed in the same spot as the old
- bss section by any other application. */
- NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign;
-
- /* Now copy over what we have in the memory now. */
- memcpy (NEW_SECTION_H (nn).sh_offset + new_base,
- (caddr_t) OLD_SECTION_H (n).sh_addr,
- new_data2_size);
- nn++;
- }
-
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
- old_file_h->e_shentsize);
-
- /* The new bss section's size is zero, and its file offset and virtual
- address should be off by NEW_DATA2_SIZE. */
- if (n == old_bss_index)
- {
- /* NN should be `old_bss_index + 1' at this point. */
- NEW_SECTION_H (nn).sh_offset += new_data2_size;
- NEW_SECTION_H (nn).sh_addr += new_data2_size;
- /* Let the new bss section address alignment be the same as the
- section address alignment followed the old bss section, so
- this section will be placed in exactly the same place. */
- NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
- NEW_SECTION_H (nn).sh_size = 0;
- }
- else
- {
- /* Any section that was original placed AFTER the bss
- section should now be off by NEW_DATA2_SIZE. */
-#ifdef SOLARIS_POWERPC
- /* On PPC Reference Platform running Solaris 2.5.1
- the plt section is also of type NOBI like the bss section.
- (not really stored) and therefore sections after the bss
- section start at the plt offset. The plt section is always
- the one just before the bss section.
- It would be better to put the new data section before
- the .plt section, or use libelf instead.
- Erik Deumens, deumens@qtp.ufl.edu. */
- if (NEW_SECTION_H (nn).sh_offset
- >= OLD_SECTION_H (old_bss_index-1).sh_offset)
- NEW_SECTION_H (nn).sh_offset += new_data2_size;
-#else
- if (round_up (NEW_SECTION_H (nn).sh_offset,
- OLD_SECTION_H (old_bss_index).sh_addralign)
- >= new_data2_offset)
- NEW_SECTION_H (nn).sh_offset += new_data2_size;
-#endif
- /* Any section that was originally placed after the section
- header table should now be off by the size of one section
- header table entry. */
- if (NEW_SECTION_H (nn).sh_offset > new_file_h->e_shoff)
- NEW_SECTION_H (nn).sh_offset += new_file_h->e_shentsize;
- }
-
- /* If any section hdr refers to the section after the new .data
- section, make it refer to next one because we have inserted
- a new section in between. */
-
- PATCH_INDEX (NEW_SECTION_H (nn).sh_link);
- /* For symbol tables, info is a symbol table index,
- so don't change it. */
- if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB
- && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM)
- PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
-
- /* Now, start to copy the content of sections. */
- if (NEW_SECTION_H (nn).sh_type == SHT_NULL
- || NEW_SECTION_H (nn).sh_type == SHT_NOBITS)
- continue;
-
- /* 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. */
- 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) OLD_SECTION_H (n).sh_addr;
- else
- src = old_base + OLD_SECTION_H (n).sh_offset;
-
- memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
- NEW_SECTION_H (nn).sh_size);
-
-#ifdef __alpha__
- /* Update Alpha COFF symbol table: */
- if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug")
- == 0)
- {
- pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base);
-
- symhdr->cbLineOffset += new_data2_size;
- symhdr->cbDnOffset += new_data2_size;
- symhdr->cbPdOffset += new_data2_size;
- symhdr->cbSymOffset += new_data2_size;
- symhdr->cbOptOffset += new_data2_size;
- symhdr->cbAuxOffset += new_data2_size;
- symhdr->cbSsOffset += new_data2_size;
- symhdr->cbSsExtOffset += new_data2_size;
- symhdr->cbFdOffset += new_data2_size;
- symhdr->cbRfdOffset += new_data2_size;
- symhdr->cbExtOffset += new_data2_size;
- }
-#endif /* __alpha__ */
-
- /* If it is the symbol table, its st_shndx field needs to be patched. */
- if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
- || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
- {
- ElfW(Shdr) *spt = &NEW_SECTION_H (nn);
- unsigned int num = spt->sh_size / spt->sh_entsize;
- ElfW(Sym) * sym = (ElfW(Sym) *) (NEW_SECTION_H (nn).sh_offset +
- new_base);
- for (; num--; sym++)
- {
- if ((sym->st_shndx == SHN_UNDEF)
- || (sym->st_shndx == SHN_ABS)
- || (sym->st_shndx == SHN_COMMON))
- continue;
-
- PATCH_INDEX (sym->st_shndx);
- }
- }
- }
-
- /* Update the symbol values of _edata and _end. */
- for (n = new_file_h->e_shnum - 1; n; n--)
- {
- byte *symnames;
- ElfW(Sym) *symp, *symendp;
-
- if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM
- && NEW_SECTION_H (n).sh_type != SHT_SYMTAB)
- continue;
-
- symnames = ((byte *) new_base
- + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset);
- symp = (ElfW(Sym) *) (NEW_SECTION_H (n).sh_offset + new_base);
- symendp = (ElfW(Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size);
-
- for (; symp < symendp; symp ++)
- if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
- || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0)
- memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
- }
-
- /* This loop seeks out relocation sections for the data section, so
- that it can undo relocations performed by the runtime linker. */
- for (n = new_file_h->e_shnum - 1; n; n--)
- {
- ElfW(Shdr) section = NEW_SECTION_H (n);
- switch (section.sh_type) {
- default:
- break;
- case SHT_REL:
- case SHT_RELA:
- /* This code handles two different size structs, but there should
- be no harm in that provided that r_offset is always the first
- member. */
- nn = section.sh_info;
- if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".data1"))
- {
- ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr -
- NEW_SECTION_H (nn).sh_offset;
- caddr_t reloc = old_base + section.sh_offset, end;
- for (end = reloc + section.sh_size; reloc < end;
- reloc += section.sh_entsize)
- {
- ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset;
-#ifdef __alpha__
- /* The Alpha ELF binutils currently have a bug that
- sometimes results in relocs that contain all
- zeroes. Work around this for now... */
- if (((ElfW(Rel) *) reloc)->r_offset == 0)
- continue;
-#endif
- memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr)));
- }
- }
- break;
- }
- }
-
-#ifdef UNEXEC_USE_MAP_PRIVATE
- if (lseek (new_file, 0, SEEK_SET) == -1)
- fatal ("Can't rewind (%s): errno %d\n", new_name, errno);
-
- if (write (new_file, new_base, new_file_size) != new_file_size)
- fatal ("Can't write (%s): errno %d\n", new_name, errno);
-#endif
-
- /* 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/=unexsgi.c b/src/=unexsgi.c
deleted file mode 100644
index 3f238592546..00000000000
--- a/src/=unexsgi.c
+++ /dev/null
@@ -1,888 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
-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
-
-
- */
-
-/* Modified by wtien@urbana.mcd.mot.com of Motorola Inc.
- *
- * The above mechanism does not work if the unexeced ELF file is being
- * re-layout by other applications (such as `strip'). All the applications
- * that re-layout the internal of ELF will layout all sections in ascending
- * order of their file offsets. After the re-layout, the data2 section will
- * still be the LAST section in the section header vector, but its file offset
- * is now being pushed far away down, and causes part of it not to be mapped
- * in (ie. not covered by the load segment entry in PHDR vector), therefore
- * causes the new binary to fail.
- *
- * The solution is to modify the unexec algorithm to insert the new data2
- * section header right before the new bss section header, so their file
- * offsets will be in the ascending order. Since some of the section's (all
- * sections AFTER the bss section) indexes are now changed, we also need to
- * modify some fields to make them point to the right sections. This is done
- * by macro PATCH_INDEX. All the fields that need to be patched are:
- *
- * 1. ELF header e_shstrndx field.
- * 2. section header sh_link and sh_info field.
- * 3. symbol table entry st_shndx field.
- *
- * The above example now should look like:
-
- **** 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] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
- 0 0 0x4 0
-
-[17] 8 3 0x80c6800 0x7d800 0 .bss
- 0 0 0x4 0
-
-[18] 2 0 0 0x7d800 0x9b90 .symtab
- 19 371 0x4 0x10
-
-[19] 3 0 0 0x87390 0x8526 .strtab
- 0 0 0x1 0
-
-[20] 3 0 0 0x8f8b6 0x93 .shstrtab
- 0 0 0x1 0
-
-[21] 1 0 0 0x8f949 0x68b7 .comment
- 0 0 0x1 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 <syms.h> /* for HDRR declaration */
-#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)))
-
-#define PATCH_INDEX(n) \
- do { \
- if ((n) >= old_bss_index) \
- (n)++; } while (0)
-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;
-}
-
-/* Return the index of the section named NAME.
- SECTION_NAMES, FILE_NAME and FILE_H give information
- about the file we are looking in.
-
- If we don't find the section NAME, that is a fatal error
- if NOERROR is 0; we return -1 if NOERROR is nonzero. */
-
-static int
-find_section (name, section_names, file_name, old_file_h, old_section_h, noerror)
- char *name;
- char *section_names;
- char *file_name;
- Elf32_Ehdr *old_file_h;
- Elf32_Shdr *old_section_h;
- int noerror;
-{
- int idx;
-
- for (idx = 1; idx < old_file_h->e_shnum; idx++)
- {
-#ifdef DEBUG
- fprintf (stderr, "Looking for %s - found %s\n", name,
- section_names + OLD_SECTION_H (idx).sh_name);
-#endif
- if (!strcmp (section_names + OLD_SECTION_H (idx).sh_name,
- name))
- break;
- }
- if (idx == old_file_h->e_shnum)
- {
- if (noerror)
- return -1;
- else
- fatal ("Can't find .bss in %s.\n", file_name, 0);
- }
-
- return idx;
-}
-
-/* ****************************************************************
- * 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;
- Elf32_Addr new_offsets_shift;
-
- int n, nn, old_bss_index, old_data_index, new_data2_index;
- int old_mdebug_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 mdebug section, if any. */
-
- old_mdebug_index = find_section (".mdebug", old_section_names,
- old_name, old_file_h, old_section_h, 1);
-
- /* Find the old .bss section. */
-
- old_bss_index = find_section (".bss", old_section_names,
- old_name, old_file_h, old_section_h, 0);
-
- /* Find the old .data section. Figure out parameters of
- the new data2 and bss sections. */
-
- old_data_index = find_section (".data", old_section_names,
- old_name, old_file_h, old_section_h, 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_data_index).sh_offset +
- (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
- new_offsets_shift = new_bss_addr -
- ((old_bss_addr & ~0xfff) + ((old_bss_addr & 0xfff) ? 0x1000 : 0));
-
-#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);
- fprintf (stderr, "new_offsets_shift %x\n", new_offsets_shift);
-#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 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_offsets_shift;
-
- 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_offsets_shift);
-
- /* 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);
-
- /* Modify the e_shstrndx if necessary. */
- PATCH_INDEX (new_file_h->e_shstrndx);
-
- /* Fix up file header. We'll add one section. Section header is
- further away now. */
-
- new_file_h->e_shoff += new_offsets_shift;
- 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;
-
- /* Supposedly this condition is okay for the SGI. */
-#if 0
- 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);
-#endif
-
- 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_offsets_shift;
- NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
-
-#if 1 /* 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_offsets_shift - old_bss_size;
-
- if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
- NEW_PROGRAM_H (n).p_offset += new_offsets_shift;
- }
-#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 (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);
-
- /* Walk through all section headers, insert the new data2 section right
- before the new bss section. */
- for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
- {
- caddr_t src;
-
- /* If it is bss section, insert the new data2 section before it. */
- if (n == old_bss_index)
- {
- /* Steal the data section header for this data2 section. */
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
- new_file_h->e_shentsize);
-
- NEW_SECTION_H (nn).sh_addr = new_data2_addr;
- NEW_SECTION_H (nn).sh_offset = new_data2_offset;
- NEW_SECTION_H (nn).sh_size = new_data2_size;
- /* Use the bss section's alignment. This will assure that the
- new data2 section always be placed in the same spot as the old
- bss section by any other application. */
- NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign;
-
- /* Now copy over what we have in the memory now. */
- memcpy (NEW_SECTION_H (nn).sh_offset + new_base,
- (caddr_t) OLD_SECTION_H (n).sh_addr,
- new_data2_size);
- nn++;
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
- old_file_h->e_shentsize);
-
- /* The new bss section's size is zero, and its file offset and virtual
- address should be off by NEW_OFFSETS_SHIFT. */
- NEW_SECTION_H (nn).sh_offset += new_offsets_shift;
- NEW_SECTION_H (nn).sh_addr = new_bss_addr;
- /* Let the new bss section address alignment be the same as the
- section address alignment followed the old bss section, so
- this section will be placed in exactly the same place. */
- NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
- NEW_SECTION_H (nn).sh_size = 0;
- }
- else
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
- old_file_h->e_shentsize);
-
- /* Any section that was original placed AFTER the bss
- section must now be adjusted by NEW_OFFSETS_SHIFT. */
-
- if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
- NEW_SECTION_H (nn).sh_offset += new_offsets_shift;
-
- /* If any section hdr refers to the section after the new .data
- section, make it refer to next one because we have inserted
- a new section in between. */
-
- PATCH_INDEX (NEW_SECTION_H (nn).sh_link);
- /* For symbol tables, info is a symbol table index,
- so don't change it. */
- if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB
- && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM)
- PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
-
- /* Now, start to copy the content of sections. */
- if (NEW_SECTION_H (nn).sh_type == SHT_NULL
- || NEW_SECTION_H (nn).sh_type == SHT_NOBITS)
- continue;
-
- /* 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. */
- if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
- || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1")
- || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".got"))
- src = (caddr_t) OLD_SECTION_H (n).sh_addr;
- else
- src = old_base + OLD_SECTION_H (n).sh_offset;
-
- memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
- NEW_SECTION_H (nn).sh_size);
-
- /* Adjust the HDRR offsets in .mdebug and copy the
- line data if it's in its usual 'hole' in the object.
- Makes the new file debuggable with dbx.
- patches up two problems: the absolute file offsets
- in the HDRR record of .mdebug (see /usr/include/syms.h), and
- the ld bug that gets the line table in a hole in the
- elf file rather than in the .mdebug section proper.
- David Anderson. davea@sgi.com Jan 16,1994. */
- if (n == old_mdebug_index)
- {
-#define MDEBUGADJUST(__ct,__fileaddr) \
- if (n_phdrr->__ct > 0) \
- { \
- n_phdrr->__fileaddr += movement; \
- }
-
- HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
- HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
- unsigned movement = new_offsets_shift;
-
- MDEBUGADJUST (idnMax, cbDnOffset);
- MDEBUGADJUST (ipdMax, cbPdOffset);
- MDEBUGADJUST (isymMax, cbSymOffset);
- MDEBUGADJUST (ioptMax, cbOptOffset);
- MDEBUGADJUST (iauxMax, cbAuxOffset);
- MDEBUGADJUST (issMax, cbSsOffset);
- MDEBUGADJUST (issExtMax, cbSsExtOffset);
- MDEBUGADJUST (ifdMax, cbFdOffset);
- MDEBUGADJUST (crfd, cbRfdOffset);
- MDEBUGADJUST (iextMax, cbExtOffset);
- /* The Line Section, being possible off in a hole of the object,
- requires special handling. */
- if (n_phdrr->cbLine > 0)
- {
- if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
- + OLD_SECTION_H (n).sh_size))
- {
- /* line data is in a hole in elf. do special copy and adjust
- for this ld mistake.
- */
- n_phdrr->cbLineOffset += movement;
-
- memcpy (n_phdrr->cbLineOffset + new_base,
- o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
- }
- else
- {
- /* somehow line data is in .mdebug as it is supposed to be. */
- MDEBUGADJUST (cbLine, cbLineOffset);
- }
- }
- }
-
- /* If it is the symbol table, its st_shndx field needs to be patched. */
- if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
- || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
- {
- Elf32_Shdr *spt = &NEW_SECTION_H (nn);
- unsigned int num = spt->sh_size / spt->sh_entsize;
- Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H (nn).sh_offset
- + new_base);
- for (; num--; sym++)
- {
- if (sym->st_shndx == SHN_UNDEF
- || sym->st_shndx == SHN_ABS
- || sym->st_shndx == SHN_COMMON)
- continue;
-
- PATCH_INDEX (sym->st_shndx);
- }
- }
- }
-
- /* 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/=x11term.h b/src/=x11term.h
deleted file mode 100644
index 367eeaacc95..00000000000
--- a/src/=x11term.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-#include <X11/cursorfont.h>
-#include <X11/Xutil.h>
-#include <X11/X10.h>
-
-#define XMOUSEBUFSIZE 64
-
-#ifndef sigmask
-#define sigmask(no) (1L << ((no) - 1))
-#endif
-
-#define BLOCK_INPUT_DECLARE() int BLOCK_INPUT_mask
-#ifdef SIGIO
-#define BLOCK_INPUT() EMACS_SIGBLOCKX (SIGIO, BLOCK_INPUT_mask)
-#define UNBLOCK_INPUT() \
- do { int _dummy; EMACS_SIGSETMASK (BLOCK_INPUT_mask, _dummy); } while (0)
-#else /* not SIGIO */
-#define BLOCK_INPUT()
-#define UNBLOCK_INPUT()
-#endif /* SIGIO */
-
-#define CLASS "Emacs" /* class id for GNU Emacs, used in .Xdefaults, etc. */
diff --git a/src/=xscrollbar.h b/src/=xscrollbar.h
deleted file mode 100644
index e1a3f45d247..00000000000
--- a/src/=xscrollbar.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/* Bitmaps and things for scrollbars.
- Copyright (C) 1989 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. */
-
-
-static void install_vertical_scrollbar ();
-static void install_horizontal_scrollbar ();
-static void x_set_horizontal_scrollbar ();
-static void x_set_vertical_scrollbar ();
-
-/* Prefix-characters for scroll bar commands in Vglobal_mouse_map.
- Choice of prefix depends on which region of the scroll bar. */
-
-enum scroll_bar_prefix
- { VSCROLL_BAR_PREFIX = 050, VSCROLL_SLIDER_PREFIX /* unused */,
- VSCROLL_THUMBUP_PREFIX, VSCROLL_THUMBDOWN_PREFIX,
- HSCROLL_BAR_PREFIX, HSCROLL_SLIDER_PREFIX /* unused */,
- HSCROLL_THUMBLEFT_PREFIX, HSCROLL_THUMBRIGHT_PREFIX };
-
-#define CROSS_WIDTH 16
-#define CROSS_HEIGHT 16
-
-#define CROSS_MASK_WIDTH 16
-#define CROSS_MASK_HEIGHT 16
-
-/* Vertical and Horizontal scroll bar widths. */
-#define VSCROLL_WIDTH 18
-#define HSCROLL_HEIGHT 18
-
-#ifdef HAVE_X11
-
-/* Arrow cursors for scroll bars. */
-
-Cursor up_arrow_cursor, down_arrow_cursor, v_double_arrow_cursor;
-Cursor left_arrow_cursor, right_arrow_cursor, h_double_arrow_cursor;
-
-static char cross_bits[] =
- {
- 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
- 0x80, 0x01, 0xfe, 0x7f, 0xfe, 0x7f, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
- 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00
- };
-
-static char gray_bits[] =
- {
- 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
- 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
- 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
- 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa
- };
-
-static char up_arrow_bits[] =
- {
- 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf8, 0x1f,
- 0xfc, 0x3f, 0xfe, 0x7f, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
- 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xff, 0xff
- };
-
-static char down_arrow_bits[] =
- {
- 0xff, 0xff, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
- 0x80, 0x01, 0x80, 0x01, 0xfe, 0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xf0, 0x0f,
- 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00
- };
-
-static char left_arrow_bits[] =
- {
- 0x00, 0x80, 0x80, 0x80, 0xc0, 0x80, 0xe0, 0x80, 0xf0, 0x80, 0xf8, 0x80,
- 0xfc, 0x80, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x80, 0xf8, 0x80, 0xf0, 0x80,
- 0xe0, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x00, 0x80
- };
-
-static char right_arrow_bits[] =
- {
- 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x01, 0x07, 0x01, 0x0f, 0x01, 0x1f,
- 0x01, 0x3f, 0xff, 0x7f, 0xff, 0x7f, 0x01, 0x3f, 0x01, 0x1f, 0x01, 0x0f,
- 0x01, 0x07, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00
- };
-
-static char cross_mask_bits[] =
- {
- 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xc0, 0x03,
- 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03
- };
-#else /* not HAVE_X11 */
-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};
-
-static short cross_mask_bits[] =
- {
- 0x03c0, 0x03c0, 0x03c0, 0x03c0,
- 0x03c0, 0x03c0, 0xffff, 0xffff,
- 0xffff, 0xffff, 0x03c0, 0x03c0,
- 0x03c0, 0x03c0, 0x03c0, 0x03c0,
- };
-#endif /* X10 */
diff --git a/src/=xselect.c.old b/src/=xselect.c.old
deleted file mode 100644
index 8a3e0443270..00000000000
--- a/src/=xselect.c.old
+++ /dev/null
@@ -1,950 +0,0 @@
-/* X Selection processing for emacs
- Copyright (C) 1990, 1992, 1993 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include "config.h"
-#include "lisp.h"
-#include "xterm.h"
-#include "buffer.h"
-#include "frame.h"
-
-#ifdef HAVE_X11
-
-/* Macros for X Selections */
-#define MAX_SELECTION(dpy) (((dpy)->max_request_size << 2) - 100)
-#define SELECTION_LENGTH(len,format) ((len) * ((format) >> 2))
-
-/* The timestamp of the last input event we received from the X server. */
-unsigned long last_event_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 SECONDARY selection owner. */
-Time x_begin_secondary_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;
-
-/* The value of the current SECONDARY selection. */
-Lisp_Object Vx_secondary_selection_value;
-
-/* Types of selections we may make. */
-Lisp_Object Qprimary, Qsecondary, Qclipboard;
-
-/* Emacs' selection property identifiers. */
-Atom Xatom_emacs_selection;
-Atom Xatom_emacs_secondary_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;
-
-/* Kinds of protocol things we may receive. */
-Atom Xatom_wm_take_focus;
-Atom Xatom_wm_save_yourself;
-Atom Xatom_wm_delete_window;
-
-/* Communication with window managers. */
-Atom Xatom_wm_protocols;
-
-/* These are to handle incremental selection transfer. */
-Window incr_requestor;
-Atom incr_property;
-int incr_nbytes;
-unsigned char *incr_value;
-unsigned char *incr_ptr;
-
-/* Declarations for handling cut buffers.
-
- Whenever we set a cut buffer or read a cut buffer's value, we cache
- it in cut_buffer_value. We look for PropertyNotify events about
- the CUT_BUFFER properties, and invalidate our cache accordingly.
- We ignore PropertyNotify events that we suspect were caused by our
- own changes to the cut buffers, so we can keep the cache valid
- longer.
-
- IS ALL THIS HAIR WORTH IT? Well, these functions get called every
- time an element goes into or is retrieved from the kill ring, and
- those ought to be quick. It's not fun in time or space to wait for
- 50k cut buffers to fly back and forth across the net. */
-
-/* The number of CUT_BUFFER properties defined under X. */
-#define NUM_CUT_BUFFERS (8)
-
-/* cut_buffer_atom[n] is the atom naming the nth cut buffer. */
-static Atom cut_buffer_atom[NUM_CUT_BUFFERS] = {
- XA_CUT_BUFFER0, XA_CUT_BUFFER1, XA_CUT_BUFFER2, XA_CUT_BUFFER3,
- XA_CUT_BUFFER4, XA_CUT_BUFFER5, XA_CUT_BUFFER6, XA_CUT_BUFFER7
-};
-
-/* cut_buffer_value is an eight-element vector;
- (aref cut_buffer_value n) is the cached value of cut buffer n, or
- Qnil if cut buffer n is unset. */
-static Lisp_Object cut_buffer_value;
-
-/* Bit N of cut_buffer_cached is true if (aref cut_buffer_value n) is
- known to be valid. This is cleared by PropertyNotify events
- handled by x_invalidate_cut_buffer_cache. It would be wonderful if
- that routine could just set the appropriate element of
- cut_buffer_value to some special value meaning "uncached", but that
- would lose if a GC happened to be in progress.
-
- Bit N of cut_buffer_just_set is true if cut buffer N has been set since
- the last PropertyNotify event; since we get an event even when we set
- the property ourselves, we should ignore one event after setting
- a cut buffer, so we don't have to throw away our cache. */
-#ifdef __STDC__
-volatile
-#endif
-static cut_buffer_cached, cut_buffer_just_set;
-
-
-/* Acquiring ownership of a selection. */
-
-
-/* Request selection ownership if we do not already have it. */
-
-static int
-own_selection (selection_type, time)
- Atom selection_type;
- Time time;
-{
- Window owner_window, selecting_window;
-
- if ((selection_type == XA_PRIMARY
- && !NILP (Vx_selection_value))
- || (selection_type == XA_SECONDARY
- && !NILP (Vx_secondary_selection_value))
- || (selection_type == Xatom_clipboard
- && !NILP (Vx_clipboard_value)))
- return 1;
-
- selecting_window = FRAME_X_WINDOW (selected_frame);
- XSetSelectionOwner (x_current_display, selection_type,
- selecting_window, time);
- owner_window = XGetSelectionOwner (x_current_display, selection_type);
-
- if (owner_window != selecting_window)
- return 0;
-
- return 1;
-}
-
-/* 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-set-selection", Fx_set_selection, Sx_set_selection,
- 2, 2, "",
- "Set the value of SELECTION to STRING.\n\
-SELECTION may be `primary', `secondary', or `clipboard'.\n\
-\n\
-Selections are a mechanism for cutting and pasting information between\n\
-X Windows clients. Emacs's kill ring commands set the `primary'\n\
-selection to the top string of the kill ring, making it available to\n\
-other clients, like xterm. Those commands also use the `primary'\n\
-selection to retrieve information from other clients.\n\
-\n\
-According to the Inter-Client Communications Conventions Manual:\n\
-\n\
-The `primary' selection \"... is used for all commands that take only a\n\
- single argument and is the principal means of communication between\n\
- clients that use the selection mechanism.\" In Emacs, this means\n\
- that the kill ring commands set the primary selection to the text\n\
- put in the kill ring.\n\
-\n\
-The `secondary' selection \"... is used as the second argument to\n\
- commands taking two arguments (for example, `exchange primary and\n\
- secondary selections'), and as a means of obtaining data when there\n\
- is a primary selection and the user does not want to disturb it.\"\n\
- I am not sure how Emacs should use the secondary selection; if you\n\
- come up with ideas, this function will at least let you get at it.\n\
-\n\
-The `clipboard' selection \"... is used to hold data that is being\n\
- transferred between clients, that is, data that usually is being\n\
- cut or copied, and then pasted.\" It seems that the `clipboard'\n\
- selection is for the most part equivalent to the `primary'\n\
- selection, so Emacs sets them both.\n\
-\n\
-Also see `x-selection', and the `interprogram-cut-function' variable.")
- (selection, string)
- register Lisp_Object selection, string;
-{
- Atom selection_type;
- Lisp_Object val;
- Time event_time = last_event_timestamp;
- CHECK_STRING (string, 0);
-
- val = Qnil;
-
- if (NILP (selection) || EQ (selection, Qprimary))
- {
- BLOCK_INPUT;
- if (own_selection (XA_PRIMARY, event_time))
- {
- x_begin_selection_own = event_time;
- val = Vx_selection_value = string;
- }
- UNBLOCK_INPUT;
- }
- else if (EQ (selection, Qsecondary))
- {
- BLOCK_INPUT;
- if (own_selection (XA_SECONDARY, event_time))
- {
- x_begin_secondary_selection_own = event_time;
- val = Vx_secondary_selection_value = string;
- }
- UNBLOCK_INPUT;
- }
- else if (EQ (selection, Qclipboard))
- {
- BLOCK_INPUT;
- if (own_selection (Xatom_clipboard, event_time))
- {
- x_begin_clipboard_own = event_time;
- val = Vx_clipboard_value = string;
- }
- UNBLOCK_INPUT;
- }
- else
- error ("Invalid X selection type");
-
- return val;
-}
-
-/* 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 frame *s = x_window_to_frame (old_owner);
-
- if (s) /* We are the owner */
- {
- if (selection == XA_PRIMARY)
- {
- x_begin_selection_own = 0;
- Vx_selection_value = Qnil;
- }
- else if (selection == XA_SECONDARY)
- {
- x_begin_secondary_selection_own = 0;
- Vx_secondary_selection_value = Qnil;
- }
- else if (selection == Xatom_clipboard)
- {
- x_begin_clipboard_own = 0;
- Vx_clipboard_value = Qnil;
- }
- else
- abort ();
- }
- else
- abort (); /* Inconsistent state. */
-}
-
-
-/* Answering selection requests. */
-
-int x_selection_alloc_error;
-int x_converting_selection;
-
-/* Reply to some client's request for our selection data.
- Data is placed in a property 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 == XA_SECONDARY)
- {
- emacs_own_time = x_begin_secondary_selection_own;
- selection_value = Vx_secondary_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 == NILP */
- || 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, 1);
- 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 NILP, 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_emacs_secondary_selection)
- Vx_secondary_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;
- }
- }
-}
-
-
-/* Requesting the value of a selection. */
-
-static Lisp_Object x_selection_arrival ();
-
-/* 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 a selection value from its owner. This will block until
- all the data is arrived. */
-
-static Lisp_Object
-get_selection_value (type)
- Atom type;
-{
- XEvent event;
- Lisp_Object val;
- Time requestor_time; /* Timestamp of selection request. */
- Window requestor_window;
-
- BLOCK_INPUT;
- requestor_time = last_event_timestamp;
- requestor_window = FRAME_X_WINDOW (selected_frame);
- XConvertSelection (x_current_display, type, 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 a 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-selection", Fx_selection, Sx_selection,
- 1, 1, "",
- "Return the value of SELECTION.\n\
-SELECTION is one of `primary', `secondary', or `clipboard'.\n\
-\n\
-Selections are a mechanism for cutting and pasting information between\n\
-X Windows clients. When the user selects text in an X application,\n\
-the application should set the primary selection to that text; Emacs's\n\
-kill ring commands will then check the value of the `primary'\n\
-selection, and return it as the most recent kill.\n\
-The documentation for `x-set-selection' gives more information on how\n\
-the different selection types are intended to be used.\n\
-Also see the `interprogram-paste-function' variable.")
- (selection)
- register Lisp_Object selection;
-{
- Atom selection_type;
-
- if (NILP (selection) || EQ (selection, Qprimary))
- {
- if (!NILP (Vx_selection_value))
- return Vx_selection_value;
-
- return get_selection_value (XA_PRIMARY);
- }
- else if (EQ (selection, Qsecondary))
- {
- if (!NILP (Vx_secondary_selection_value))
- return Vx_secondary_selection_value;
-
- return get_selection_value (XA_SECONDARY);
- }
- else if (EQ (selection, Qclipboard))
- {
- if (!NILP (Vx_clipboard_value))
- return Vx_clipboard_value;
-
- return get_selection_value (Xatom_clipboard);
- }
- else
- error ("Invalid X selection type");
-}
-
-static 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 == XA_SECONDARY)
- selection = Xatom_emacs_secondary_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;
-}
-
-
-/* Cut buffer management. */
-
-DEFUN ("x-get-cut-buffer", Fx_get_cut_buffer, Sx_get_cut_buffer, 0, 1, "",
- "Return the value of cut buffer N, or nil if it is unset.\n\
-If N is omitted, it defaults to zero.\n\
-Note that cut buffers have some problems that selections don't; try to\n\
-write your code to use cut buffers only for backward compatibility,\n\
-and use selections for the serious work.")
- (n)
- Lisp_Object n;
-{
- int buf_num;
-
- if (NILP (n))
- buf_num = 0;
- else
- {
- CHECK_NUMBER (n, 0);
- buf_num = XINT (n);
- }
-
- if (buf_num < 0 || buf_num >= NUM_CUT_BUFFERS)
- error ("cut buffer numbers must be from zero to seven");
-
- {
- Lisp_Object value;
-
- /* Note that no PropertyNotify events will be processed while
- input is blocked. */
- BLOCK_INPUT;
-
- if (cut_buffer_cached & (1 << buf_num))
- value = XVECTOR (cut_buffer_value)->contents[buf_num];
- else
- {
- /* Our cache is invalid; retrieve the property's value from
- the server. */
- int buf_len;
- char *buf = XFetchBuffer (x_current_display, &buf_len, buf_num);
-
- if (buf_len == 0)
- value = Qnil;
- else
- value = make_string (buf, buf_len);
-
- XVECTOR (cut_buffer_value)->contents[buf_num] = value;
- cut_buffer_cached |= (1 << buf_num);
-
- XFree (buf);
- }
-
- UNBLOCK_INPUT;
-
- return value;
- }
-}
-
-DEFUN ("x-set-cut-buffer", Fx_set_cut_buffer, Sx_set_cut_buffer, 2, 2, "",
- "Set the value of cut buffer N to STRING.\n\
-Note that cut buffers have some problems that selections don't; try to\n\
-write your code to use cut buffers only for backward compatibility,\n\
-and use selections for the serious work.")
- (n, string)
- Lisp_Object n, string;
-{
- int buf_num;
-
- CHECK_NUMBER (n, 0);
- CHECK_STRING (string, 1);
-
- buf_num = XINT (n);
-
- if (buf_num < 0 || buf_num >= NUM_CUT_BUFFERS)
- error ("cut buffer numbers must be from zero to seven");
-
- BLOCK_INPUT;
-
- /* DECwindows and some other servers don't seem to like setting
- properties to values larger than about 20k. For very large
- values, they signal an error, but for intermediate values they
- just seem to hang.
-
- We could just truncate the request, but it's better to let the
- user know that the strategy he/she's using isn't going to work
- than to have it work partially, but incorrectly. */
-
- if (XSTRING (string)->size == 0
- || XSTRING (string)->size > MAX_SELECTION (x_current_display))
- {
- XStoreBuffer (x_current_display, (char *) 0, 0, buf_num);
- string = Qnil;
- }
- else
- {
- XStoreBuffer (x_current_display,
- (char *) XSTRING (string)->data, XSTRING (string)->size,
- buf_num);
- }
-
- XVECTOR (cut_buffer_value)->contents[buf_num] = string;
- cut_buffer_cached |= (1 << buf_num);
- cut_buffer_just_set |= (1 << buf_num);
-
- UNBLOCK_INPUT;
-
- return string;
-}
-
-/* Ask the server to send us an event if any cut buffer is modified. */
-
-void
-x_watch_cut_buffer_cache ()
-{
- XSelectInput (x_current_display, ROOT_WINDOW, PropertyChangeMask);
-}
-
-/* The server has told us that a cut buffer has been modified; deal with that.
- Note that this function is called at interrupt level. */
-void
-x_invalidate_cut_buffer_cache (XPropertyEvent *event)
-{
- int i;
-
- /* See which cut buffer this is about, if any. */
- for (i = 0; i < NUM_CUT_BUFFERS; i++)
- if (event->atom == cut_buffer_atom[i])
- {
- int mask = (1 << i);
-
- if (cut_buffer_just_set & mask)
- cut_buffer_just_set &= ~mask;
- else
- cut_buffer_cached &= ~mask;
-
- break;
- }
-}
-
-
-/* Bureaucracy. */
-
-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-secondary-selection-value", &Vx_secondary_selection_value,
- "The value of emacs' last secondary cut-string.");
- Vx_secondary_selection_value = Qnil;
-
- DEFVAR_LISP ("x-clipboard-value", &Vx_clipboard_value,
- "The string emacs last sent to the clipboard.");
- Vx_clipboard_value = Qnil;
-
- Qprimary = intern ("primary");
- staticpro (&Qprimary);
- Qsecondary = intern ("secondary");
- staticpro (&Qsecondary);
- Qclipboard = intern ("clipboard");
- staticpro (&Qclipboard);
-
- defsubr (&Sx_set_selection);
- defsubr (&Sx_selection);
-
- cut_buffer_value = Fmake_vector (make_number (NUM_CUT_BUFFERS), Qnil);
- staticpro (&cut_buffer_value);
-
- defsubr (&Sx_get_cut_buffer);
- defsubr (&Sx_set_cut_buffer);
-}
-#endif /* X11 */
diff --git a/src/Makefile.in b/src/Makefile.in
deleted file mode 100644
index 15f87f643bc..00000000000
--- a/src/Makefile.in
+++ /dev/null
@@ -1,1067 +0,0 @@
-# Makefile for GNU Emacs.
-# Copyright (C) 1985, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
-
-# This file is part of GNU Emacs.
-
-# GNU Emacs is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-
-# GNU Emacs is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with GNU Emacs; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-# Here are the things that we expect ../configure to edit.
-srcdir=@srcdir@
-VPATH=@srcdir@
-CC=@CC@
-CPP=@CPP@
-CFLAGS=@CFLAGS@
-LN_S=@LN_S@
-# Substitute an assignment for the MAKE variable, because
-# BSD doesn't have it as a default.
-@SET_MAKE@
-
-# On Xenix and the IBM RS6000, double-dot gets screwed up.
-dot = .
-dotdot = ${dot}${dot}
-lispsource = ${srcdir}/$(dot)$(dot)/lisp/
-libsrc = $(dot)$(dot)/lib-src/
-etc = $(dot)$(dot)/etc/
-shortnamesdir = $(dot)$(dot)/shortnames/
-cppdir = $(dot)$(dot)/cpp/
-oldXMenudir = $(dot)$(dot)/oldXMenu/
-lwlibdir = $(dot)$(dot)/lwlib/
-
-# Configuration files for .o files to depend on.
-M_FILE = ${srcdir}/@machfile@
-S_FILE = ${srcdir}/@opsysfile@
-config_h = config.h $(M_FILE) $(S_FILE)
-
-# ========================== start of cpp stuff =======================
-/* From here on, comments must be done in C syntax. */
-
-CPPFLAGS=
-LDFLAGS=
-C_SWITCH_SYSTEM=
-
-/* just to be sure the sh is used */
-SHELL=/bin/sh
-
-#define THIS_IS_MAKEFILE
-#define NO_SHORTNAMES
-#define NOT_C_CODE
-#include "config.h"
-
-/* We won't really call alloca;
- don't let the file name alloca.c get messed up. */
-#ifdef alloca
-#undef alloca
-#endif
-
-/* Don't let the file name mktime.c get messed up. */
-#ifdef mktime
-#undef mktime
-#endif
-
-/* 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 be able to use the system make command. */
-#ifdef MAKE_COMMAND
-MAKE = MAKE_COMMAND
-#endif
-
-#ifdef C_COMPILER
-CC = C_COMPILER
-#endif
-
-/* GNU libc requires ORDINARY_LINK so that its own crt0 is used.
- Linux is an exception because it uses a funny variant of GNU libc. */
-#ifdef __GNU_LIBRARY__
-#ifndef LINUX
-#define ORDINARY_LINK
-#endif
-#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/SYSTEM.h files define this to request special libraries. */
-#ifndef LIBS_SYSTEM
-#define LIBS_SYSTEM
-#endif
-
-/* Some m/MACHINE.h files define this to request special libraries. */
-#ifndef LIBS_MACHINE
-#define LIBS_MACHINE
-#endif
-
-#ifndef LIB_MATH
-# ifdef LISP_FLOAT_TYPE
-# define LIB_MATH -lm
-# else /* ! defined (LISP_FLOAT_TYPE) */
-# define LIB_MATH
-# endif /* ! defined (LISP_FLOAT_TYPE) */
-#endif /* LIB_MATH */
-
-/* Some s/SYSTEM.h files define this to request special switches in ld. */
-#ifndef LD_SWITCH_SYSTEM
-#if !defined (__GNUC__) && (defined(COFF_ENCAPSULATE) || (defined (BSD_SYSTEM) && !defined (COFF)))
-#define LD_SWITCH_SYSTEM -X
-#else /* ! defined(COFF_ENCAPSULATE) || (defined (BSD_SYSTEM) && !defined (COFF)) */
-#define LD_SWITCH_SYSTEM
-#endif /* ! defined(COFF_ENCAPSULATE) || (defined (BSD_SYSTEM) && !defined (COFF)) */
-#endif /* LD_SWITCH_SYSTEM */
-
-/* Some m/MACHINE.h files define this to request special switches in ld. */
-#ifndef LD_SWITCH_MACHINE
-#define LD_SWITCH_MACHINE
-#endif
-
-/* Some m/MACHINE.h files define this to request special switches in cc. */
-#ifndef C_SWITCH_MACHINE
-#define C_SWITCH_MACHINE
-#endif
-
-/* Some s/SYSTEM.h files define this to request special switches in cc. */
-#ifndef C_SWITCH_SYSTEM
-#define C_SWITCH_SYSTEM
-#endif
-
-/* These macros are for switches specifically related to X Windows. */
-#ifndef C_SWITCH_X_MACHINE
-#define C_SWITCH_X_MACHINE
-#endif
-
-#ifndef C_SWITCH_X_SYSTEM
-#define C_SWITCH_X_SYSTEM
-#endif
-
-#ifndef C_SWITCH_X_SITE
-#define C_SWITCH_X_SITE
-#endif
-
-#ifndef LD_SWITCH_X_SITE
-#define LD_SWITCH_X_SITE
-#endif
-
-#ifndef LD_SWITCH_X_DEFAULT
-#define LD_SWITCH_X_DEFAULT
-#endif
-
-/* These can be passed in from config.h to define special load and
- compile switches needed by individual sites */
-#ifndef LD_SWITCH_SITE
-#define LD_SWITCH_SITE
-#endif
-
-#ifndef C_SWITCH_SITE
-#define C_SWITCH_SITE
-#endif
-
-#ifndef ORDINARY_LINK
-
-#ifndef CRT0_COMPILE
-#define CRT0_COMPILE $(CC) -c $(ALL_CFLAGS) C_SWITCH_ASM
-#endif
-
-#ifndef START_FILES
-#ifdef NO_REMAP
-#ifdef COFF_ENCAPSULATE
-#define START_FILES pre-crt0.o /usr/local/lib/gcc-crt0.o
-#else /* ! defined (COFF_ENCAPSULATE) */
-#define START_FILES pre-crt0.o /lib/crt0.o
-#endif /* ! defined (COFF_ENCAPSULATE) */
-#else /* ! defined (NO_REMAP) */
-#define START_FILES ecrt0.o
-#endif /* ! defined (NO_REMAP) */
-#endif /* START_FILES */
-STARTFILES = START_FILES
-
-#else /* ORDINARY_LINK */
-
-/* config.h might want to force START_FILES anyway */
-#ifdef START_FILES
-STARTFILES = START_FILES
-#endif /* START_FILES */
-
-#endif /* not ORDINARY_LINK */
-
-
-/* cc switches needed to make `asm' keyword work.
- Nothing special needed on most machines. */
-#ifndef C_SWITCH_ASM
-#define C_SWITCH_ASM
-#endif
-
-/* 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 standard one. */
-LOCALCPP= localcpp
-#endif /* ! defined (LONGNAMEBBBARFOOX) */
-
-#ifdef SHORTNAMES
-SHORT= shortnames
-#endif
-
-#ifdef USE_X_TOOLKIT
-#define USE_@X_TOOLKIT_TYPE@
-TOOLKIT_DEFINES = -DUSE_@X_TOOLKIT_TYPE@
-#else
-TOOLKIT_DEFINES =
-#endif
-
-/* 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. */
-
-/* -Demacs is needed to make some files produce the correct version
- for use in Emacs.
-
- -DHAVE_CONFIG_H is needed for some other files to take advantage of
- the information in `config.h'. */
-
-/* C_SWITCH_X_SITE must come before C_SWITCH_X_MACHINE and C_SWITCH_X_SYSTEM
- since it may have -I options that should override those two. */
-ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(TOOLKIT_DEFINES) $(MYCPPFLAG) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_SITE C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM ${CFLAGS}
-.c.o:
- $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $<
-
-#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_MENUS
-
-/* Include xmenu.o in the list of X object files. */
-XOBJ= xterm.o xfns.o xfaces.o xselect.o xrdb.o
-
-/* The X Menu stuff is present in the X10 distribution, but missing
- from X11. If we have X10, just use the installed library;
- otherwise, use our own copy. */
-#ifdef HAVE_X11
-#ifdef USE_X_TOOLKIT
-OLDXMENU=${lwlibdir}liblw.a
-LIBXMENU= $(OLDXMENU)
-#else /* not USE_X_TOOLKIT */
-OLDXMENU= ${oldXMenudir}libXMenu11.a
-LIBXMENU= $(OLDXMENU)
-#endif /* not USE_X_TOOLKIT */
-#else /* not HAVE_X11 */
-LIBXMENU= -lXMenu
-#endif /* not HAVE_X11 */
-
-#else /* not HAVE_MENUS */
-
-/* Otherwise, omit xmenu.o from the list of X object files, and
- don't worry about the menu library at all. */
-XOBJ= xterm.o xfns.o xfaces.o xselect.o xrdb.o
-LIBXMENU=
-#endif /* not HAVE_MENUS */
-
-#ifdef USE_X_TOOLKIT
-#define @X_TOOLKIT_TYPE@
-#if defined (LUCID) || defined (ATHENA)
-LIBW= -lXaw
-#endif
-#ifdef MOTIF
-#ifdef LIB_MOTIF
-LIBW= LIB_MOTIF
-#else
-LIBW= -lXm
-#endif
-#endif
-#ifdef OPEN_LOOK
-LIBW= -lXol
-#endif
-
-#ifdef HAVE_X11XTR6
-#ifdef NEED_LIBW
-LIBXTR6 = -lSM -lICE -lw
-#else
-LIBXTR6 = -lSM -lICE
-#endif
-#endif
-
-#ifndef LIBXMU
-#define LIBXMU -lXmu
-#endif
-
-#ifdef LIBXT_STATIC
-/* We assume the config files have defined STATIC_OPTION
- since that might depend on the operating system.
- (Don't forget you need different definitions with and without __GNUC__.) */
-LIBXT= STATIC_OPTION $(LIBW) LIBXMU -lXt $(LIBXTR6) -lXext DYNAMIC_OPTION
-#else /* not LIBXT_STATIC */
-LIBXT= $(LIBW) LIBXMU -lXt $(LIBXTR6) -lXext
-#endif /* not LIBXT_STATIC */
-
-#else /* not USE_X_TOOLKIT */
-LIBXT=
-#endif /* not USE_X_TOOLKIT */
-
-#ifdef HAVE_X11
-/* LD_SWITCH_X_DEFAULT comes after everything else that specifies
- options for where to find X libraries, but before those libraries. */
-X11_LDFLAGS = LD_SWITCH_X_SITE LD_SWITCH_X_DEFAULT
-LIBX= $(LIBXMENU) $(X11_LDFLAGS) $(LIBXT) LIB_X11_LIB LIBX11_MACHINE LIBX11_SYSTEM
-#else /* not HAVE_X11 */
-LIBX= $(LIBXMENU) LD_SWITCH_X_SITE -lX10 LIBX10_MACHINE LIBX10_SYSTEM
-#endif /* not HAVE_X11 */
-#endif /* not HAVE_X_WINDOWS */
-
-#ifndef ORDINARY_LINK
-/* Fix linking if compiled with GCC. */
-#ifdef __GNUC__
-
-#if __GNUC__ > 1
-
-#ifdef LINKER
-#define LINKER_WAS_SPECIFIED
-#endif
-
-/* Versions of GCC >= 2.0 put their library, libgcc.a, in obscure
- places that are difficult to figure out at make time. Fortunately,
- these same versions allow you to pass arbitrary flags on to the
- linker, so there's no reason not to use it as a linker.
-
- Well, it's not quite perfect. The `-nostdlib' keeps GCC from
- searching for libraries in its internal directories, so we have to
- ask GCC explicitly where to find libgcc.a. */
-
-#ifndef LINKER
-#define LINKER $(CC) -nostdlib
-#endif
-
-#ifndef LIB_GCC
-/* Ask GCC where to find libgcc.a. */
-#define LIB_GCC `$(CC) -print-libgcc-file-name`
-#endif /* not LIB_GCC */
-
-GNULIB_VAR = LIB_GCC
-
-#ifndef LINKER_WAS_SPECIFIED
-/* GCC passes any argument prefixed with -Xlinker directly to the
- linker. See prefix-args.c for an explanation of why we don't do
- this with the shell's `for' construct.
- Note that some people don't have '.' in their paths, so we must
- use ./prefix-args. */
-#define YMF_PASS_LDFLAGS(flags) `./prefix-args -Xlinker flags`
-#else
-#define YMF_PASS_LDFLAGS(flags) flags
-#endif
-
-#else /* __GNUC__ < 2 */
-
-#ifndef LIB_GCC
-#define LIB_GCC /usr/local/lib/gcc-gnulib
-#endif /* not LIB_GCC */
-GNULIB_VAR = `if [ -f LIB_GCC ] ; then echo LIB_GCC; else echo; fi`
-#endif /* __GNUC__ < 2 */
-#else /* not __GNUC__ */
-GNULIB_VAR =
-
-#endif /* not __GNUC__ */
-#endif /* not ORDINARY_LINK */
-
-/* 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
-
-#ifdef ORDINARY_LINK
-LD = $(CC)
-#else
-#ifdef COFF_ENCAPSULATE
-LD=$(CC) -nostdlib
-#else /* not ORDINARY_LINK */
-#ifdef LINKER
-LD=LINKER
-#else /* not LINKER */
-LD=ld
-#endif /* not LINKER */
-#endif /* not COFF_ENCAPSULATE */
-#endif /* not ORDINARY_LINK */
-
-ALL_LDFLAGS = LD_SWITCH_SYSTEM LD_SWITCH_MACHINE LD_SWITCH_SITE $(LDFLAGS)
-
-/* A macro which other sections of Makefile can redefine to munge the
- flags before they're passed to LD. This is helpful if you have
- redefined LD to something odd, like "gcc".
- (The YMF prefix is a holdover from the old name "ymakefile".)
- */
-#ifndef YMF_PASS_LDFLAGS
-#define YMF_PASS_LDFLAGS(flags) flags
-#endif
-
-/* Allow config.h to specify a replacement file for unexec.c. */
-#ifndef UNEXEC
-#define UNEXEC unexec.o
-#endif
-#ifndef UNEXEC_SRC
-#define UNEXEC_SRC unexec.c
-#endif
-
-#ifdef USE_TEXT_PROPERTIES
-#define INTERVAL_SRC intervals.h
-#define INTERVAL_OBJ intervals.o textprop.o
-#else
-#define INTERVAL_SRC
-#define INTERVAL_OBJ
-#endif
-
-#ifdef HAVE_GETLOADAVG
-#define GETLOADAVG_OBJ
-#else
-#define GETLOADAVG_OBJ getloadavg.o
-#endif
-
-#if HAVE_MKTIME && ! BROKEN_MKTIME
-#define MKTIME_OBJ
-#else
-#define MKTIME_OBJ mktime.o
-#endif
-
-#ifdef MSDOS
-#ifdef HAVE_X_WINDOWS
-#define MSDOS_OBJ dosfns.o msdos.o
-#else
-#define MSDOS_OBJ dosfns.o msdos.o xfaces.o
-#endif
-#else
-#define MSDOS_OBJ
-#endif
-
-
-/* lastfile must follow all files
- whose initialized data areas should be dumped as pure by dump-emacs. */
-obj= dispnew.o frame.o scroll.o xdisp.o xmenu.o window.o \
- cm.o term.o $(XOBJ) \
- emacs.o keyboard.o macros.o keymap.o sysdep.o \
- buffer.o filelock.o insdel.o marker.o INTERVAL_OBJ \
- minibuf.o fileio.o dired.o filemode.o \
- cmds.o casetab.o casefiddle.o indent.o search.o regex.o undo.o \
- alloc.o data.o doc.o editfns.o callint.o \
- eval.o floatfns.o fns.o print.o lread.o \
- abbrev.o syntax.o UNEXEC mocklisp.o bytecode.o \
- process.o callproc.o \
- region-cache.o \
- doprnt.o strftime.o MKTIME_OBJ GETLOADAVG_OBJ MSDOS_OBJ
-
-/* Object files used on some machine or other.
- These go in the DOC file on all machines
- in case they are needed there. */
-SOME_MACHINE_OBJECTS = sunfns.o dosfns.o msdos.o intervals.o textprop.o \
- xterm.o xfns.o xfaces.o xmenu.o xselect.o xrdb.o
-
-
-#ifdef TERMINFO
-/* Used to be -ltermcap here. If your machine needs that,
- define LIBS_TERMCAP in the m/MACHINE.h file. */
-#ifndef LIBS_TERMCAP
-#define LIBS_TERMCAP -lcurses
-#endif /* LIBS_TERMCAP */
-termcapobj = terminfo.o
-#else /* ! defined (TERMINFO) */
-#ifndef LIBS_TERMCAP
-#define LIBS_TERMCAP
-termcapobj = termcap.o tparam.o
-#else /* LIBS_TERMCAP */
-termcapobj = tparam.o
-#endif /* LIBS_TERMCAP */
-#endif /* ! defined (TERMINFO) */
-
-
-#ifndef SYSTEM_MALLOC
-
-#ifdef GNU_MALLOC /* New GNU malloc */
-#ifdef REL_ALLOC
-mallocobj = gmalloc.o ralloc.o vm-limit.o
-#else /* ! defined (REL_ALLOC) */
-mallocobj = gmalloc.o vm-limit.o
-#endif /* ! defined (REL_ALLOC) */
-#else /* Old GNU malloc */
-mallocobj = malloc.o
-#endif /* Old GNU malloc */
-
-#endif /* SYSTEM_MALLOC */
-
-
-#ifndef HAVE_ALLOCA
-allocaobj = alloca.o
-#else
-allocaobj =
-#endif
-
-#ifdef USE_X_TOOLKIT
-widgetobj= widget.o
-#else /* not USE_X_TOOLKIT */
-widgetobj=
-#endif /* not USE_X_TOOLKIT */
-
-
-/* define otherobj as list of object files that make-docfile
- should not be told about. */
-otherobj= $(termcapobj) lastfile.o $(mallocobj) $(allocaobj) $(widgetobj)
-
-#ifdef HAVE_FACES
-#define FACE_SUPPORT ${lispsource}faces.elc ${lispsource}facemenu.elc
-#else
-#define FACE_SUPPORT
-#endif
-
-#ifdef LISP_FLOAT_TYPE
-#define FLOAT_SUPPORT ${lispsource}float-sup.elc
-#else
-#define FLOAT_SUPPORT
-#endif
-
-#ifdef HAVE_MOUSE
-#define MOUSE_SUPPORT ${lispsource}menu-bar.elc ${lispsource}mouse.elc \
- ${lispsource}select.elc ${lispsource}scroll-bar.elc
-#else
-#define MOUSE_SUPPORT
-#endif
-
-#ifdef HAVE_X_WINDOWS
-#define X_WINDOWS_SUPPORT
-#else
-#define X_WINDOWS_SUPPORT
-#endif
-
-#ifdef VMS
-#define VMS_SUPPORT ${lispsource}vmsproc.elc ${lispsource}vms-patch.elc
-#else
-#define VMS_SUPPORT
-#endif
-
-#ifdef MSDOS
-#define MSDOS_SUPPORT ${lispsource}ls-lisp.elc ${lispsource}disp-table.elc \
- ${lispsource}dos-fns.elc ${lispsource}dos-w32.elc
-#else
-#define MSDOS_SUPPORT
-#endif
-
-#ifdef WINDOWSNT
-#define WINNT_SUPPORT ${lispsource}ls-lisp.elc ${lispsource}w32-fns.elc \
- ${lispsource}dos-w32.elc
-#else
-#define WINNT_SUPPORT
-#endif
-
-/* List of Lisp files loaded into the dumped Emacs. It's arranged
- like this because it's easier to generate it semi-mechanically from
- loadup.el this way.
-
- Note that this list should not include lisp files which might not
- be present, like site-load.el and site-init.el; this makefile
- expects them all to be either present or buildable.
-
- Always update shortlisp as well as this variable. */
-
-lisp= \
- ${lispsource}abbrev.elc \
- ${lispsource}buff-menu.elc \
- ${lispsource}byte-run.elc \
- ${lispsource}files.elc \
- ${lispsource}fill.elc \
- ${lispsource}format.elc \
- FACE_SUPPORT \
- MOUSE_SUPPORT \
- FLOAT_SUPPORT \
- ${lispsource}frame.elc\
- X_WINDOWS_SUPPORT \
- ${lispsource}help.elc \
- ${lispsource}indent.elc \
- ${lispsource}isearch.elc \
- ${lispsource}lisp-mode.elc \
- ${lispsource}lisp.elc \
- ${lispsource}loadup.el \
- ${lispsource}loaddefs.el \
- ${lispsource}map-ynp.elc \
- ${lispsource}page.elc \
- ${lispsource}paragraphs.elc \
- ${lispsource}paths.el \
- ${lispsource}register.elc \
- ${lispsource}replace.elc \
- ${lispsource}simple.elc \
- ${lispsource}startup.elc \
- ${lispsource}subr.elc \
- ${lispsource}text-mode.elc \
- ${lispsource}vc-hooks.elc \
- ${lispsource}ediff-hook.elc \
- VMS_SUPPORT \
- MSDOS_SUPPORT \
- WINNT_SUPPORT \
- ${lispsource}window.elc \
- ${lispsource}version.el
-
-/* These are relative file names for the Lisp files
- that are loaded unconditionally. This is used in make-docfile.
- It need not contain the files that are loaded conditionally
- because SOME_MACHINE_LISP has those. */
-shortlisp= \
- ../lisp/abbrev.elc \
- ../lisp/buff-menu.elc \
- ../lisp/byte-run.elc \
- ../lisp/files.elc \
- ../lisp/fill.elc \
- ../lisp/format.elc \
- ../lisp/help.elc \
- ../lisp/indent.elc \
- ../lisp/isearch.elc \
- ../lisp/lisp-mode.elc \
- ../lisp/lisp.elc \
- ../lisp/loadup.el \
- ../lisp/loaddefs.el \
- ../lisp/map-ynp.elc \
- ../lisp/page.elc \
- ../lisp/paragraphs.elc \
- ../lisp/paths.el \
- ../lisp/register.elc \
- ../lisp/replace.elc \
- ../lisp/simple.elc \
- ../lisp/startup.elc \
- ../lisp/subr.elc \
- ../lisp/text-mode.elc \
- ../lisp/vc-hooks.elc \
- ../lisp/ediff-hook.elc \
- ../lisp/window.elc \
- ../lisp/version.el
-
-/* Lisp files that may or may not be used.
- We must unconditionally put them in the DOC file.
- We use ../lisp/ to start the file names
- to reduce the size of the argument list for make-docfile
- for the sake of systems which can't handle large ones. */
-SOME_MACHINE_LISP = ${dotdot}/lisp/faces.elc ${dotdot}/lisp/facemenu.elc \
- ${dotdot}/lisp/float-sup.elc ${dotdot}/lisp/frame.elc \
- ${dotdot}/lisp/menu-bar.elc ${dotdot}/lisp/mouse.elc \
- ${dotdot}/lisp/select.elc ${dotdot}/lisp/scroll-bar.elc \
- ${dotdot}/lisp/vmsproc.elc ${dotdot}/lisp/vms-patch.elc \
- ${dotdot}/lisp/ls-lisp.elc ${dotdot}/lisp/dos-fns.elc \
- ${dotdot}/lisp/w32-fns.elc ${dotdot}/lisp/dos-w32.elc
-
-/* Construct full set of libraries to be linked.
- Note that SunOS needs -lm to come before -lc; otherwise, you get
- duplicated symbols. If the standard libraries were compiled
- with GCC, we might need gnulib again after them. */
-LIBES = $(LOADLIBES) $(LDLIBS) $(LIBX) LIBS_SYSTEM LIBS_MACHINE LIBS_TERMCAP \
- LIBS_DEBUG $(GNULIB_VAR) LIB_MATH LIB_STANDARD $(GNULIB_VAR)
-
-/* 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: emacs OTHER_FILES
-
-emacs: temacs ${etc}DOC ${lisp}
-#ifdef CANNOT_DUMP
- rm -f emacs
- ln temacs emacs
-#else
-#ifdef HAVE_SHM
- ./temacs -nl -batch -l loadup dump
-#else /* ! defined (HAVE_SHM) */
- ./temacs -batch -l loadup dump
-#endif /* ! defined (HAVE_SHM) */
-#endif /* ! defined (CANNOT_DUMP) */
-
-/* We run make-docfile twice because the command line may get too long
- on some systems. */
-/* ${SOME_MACHINE_OBJECTS} comes before ${obj} because some files may
- or may not be included in ${obj}, but they are always included in
- ${SOME_MACHINE_OBJECTS}. Since a file is processed when it is mentioned
- for the first time, this prevents any variation between configurations
- in the contents of the DOC file.
- Likewise for ${SOME_MACHINE_LISP}. */
-${etc}DOC: ${libsrc}make-docfile ${obj} ${lisp}
- -rm -f ${etc}DOC
- ${libsrc}make-docfile -d ${srcdir} ${SOME_MACHINE_OBJECTS} ${obj} > ${etc}DOC
- ${libsrc}make-docfile -a ${etc}DOC -d ${srcdir} ${SOME_MACHINE_LISP} ${shortlisp}
-
-${libsrc}make-docfile:
- cd ${libsrc}; ${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 prefix-args
- $(LD) YMF_PASS_LDFLAGS (${STARTFLAGS} ${ALL_LDFLAGS}) \
- -o temacs ${STARTFILES} ${obj} ${otherobj} \
- OBJECTS_SYSTEM OBJECTS_MACHINE ${LIBES}
-
-/* We don't use ALL_LDFLAGS because LD_SWITCH_SYSTEM and LD_SWITCH_MACHINE
- often contain options that have to do with using Emacs's crt0,
- which are only good with temacs. */
-prefix-args: prefix-args.c $(config_h)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) ${srcdir}/prefix-args.c -o prefix-args
-
-/* 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 ALL_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 /* ! defined (NEED_CPP) */
-CPP = $(CC) -E
-#endif /* ! defined (NEED_CPP) */
-
-#ifdef SHORTNAMES
-shortnames:
- cd ${shortnamesdir}; ${MAKE} ${MFLAGS}
-#endif
-
-/* Don't lose if this was not defined. */
-#ifndef OLDXMENU_OPTIONS
-#define OLDXMENU_OPTIONS
-#endif
-
-/* Don't lose if this was not defined. */
-#ifndef LWLIB_OPTIONS
-#define LWLIB_OPTIONS
-#endif
-
-#if defined (HAVE_X_WINDOWS) && defined (HAVE_X11) && defined (HAVE_MENUS)
-
-#ifdef USE_X_TOOLKIT
-$(OLDXMENU): really-lwlib
-
-/* Encode the values of these two macros in Make variables,
- so we can use $(...) to substitute their values within "...". */
-C_SWITCH_MACHINE_1 = C_SWITCH_MACHINE
-C_SWITCH_SYSTEM_1 = C_SWITCH_SYSTEM
-C_SWITCH_SITE_1 = C_SWITCH_SITE
-C_SWITCH_X_SITE_1 = C_SWITCH_X_SITE
-C_SWITCH_X_MACHINE_1 = C_SWITCH_X_MACHINE
-C_SWITCH_X_SYSTEM_1 = C_SWITCH_X_SYSTEM
-really-lwlib:
- cd ${lwlibdir}; ${MAKE} ${MFLAGS} LWLIB_OPTIONS \
- CC='${CC}' CFLAGS='${CFLAGS}' MAKE='${MAKE}' \
- "C_SWITCH_X_SITE=$(C_SWITCH_X_SITE_1)" \
- "C_SWITCH_X_MACHINE=$(C_SWITCH_X_MACHINE_1)" \
- "C_SWITCH_X_SYSTEM=$(C_SWITCH_X_SYSTEM_1)" \
- "C_SWITCH_SITE=$(C_SWITCH_SITE_1)" \
- "C_SWITCH_MACHINE=$(C_SWITCH_MACHINE_1)" \
- "C_SWITCH_SYSTEM=$(C_SWITCH_SYSTEM_1)"
- @true /* make -t should not create really-lwlib. */
-.PHONY: really-lwlib
-#else /* not USE_X_TOOLKIT */
-$(OLDXMENU): really-oldXMenu
-
-/* Encode the values of these two macros in Make variables,
- so we can use $(...) to substitute their values within "...". */
-C_SWITCH_MACHINE_1 = C_SWITCH_MACHINE
-C_SWITCH_SYSTEM_1 = C_SWITCH_SYSTEM
-C_SWITCH_SITE_1 = C_SWITCH_SITE
-C_SWITCH_X_SITE_1 = C_SWITCH_X_SITE
-C_SWITCH_X_MACHINE_1 = C_SWITCH_X_MACHINE
-C_SWITCH_X_SYSTEM_1 = C_SWITCH_X_SYSTEM
-really-oldXMenu:
- cd ${oldXMenudir}; ${MAKE} ${MFLAGS} OLDXMENU_OPTIONS \
- CC='${CC}' CFLAGS='${CFLAGS}' MAKE='${MAKE}' \
- "C_SWITCH_X_SITE=$(C_SWITCH_X_SITE_1)" \
- "C_SWITCH_X_MACHINE=$(C_SWITCH_X_MACHINE_1)" \
- "C_SWITCH_X_SYSTEM=$(C_SWITCH_X_SYSTEM_1)" \
- "C_SWITCH_SITE=$(C_SWITCH_SITE_1)" \
- "C_SWITCH_MACHINE=$(C_SWITCH_MACHINE_1)" \
- "C_SWITCH_SYSTEM=$(C_SWITCH_SYSTEM_1)"
- @true /* make -t should not create really-oldXMenu. */
-.PHONY: really-oldXMenu
-#endif /* not USE_X_TOOLKIT */
-#endif /* HAVE_X_WINDOWS && HAVE_X11 && HAVE_MENUS */
-
-../config.status:: paths.in
- @echo "The file paths.h needs to be set up from paths.in."
- @echo "Please run the `configure' script again."
- exit 1
-
-../config.status:: config.in
- @echo "The file config.h needs to be set up from config.in."
- @echo "Please run the `configure' script again."
- 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
-/* We could put something in alloca.c to #define free and malloc
- whenever emacs was #defined, but that's not appropriate for all
- users of alloca in Emacs. Check out ../lib-src/getopt.c. */
-alloca.o : alloca.c
- $(CC) -c $(CPPFLAGS) -Dfree=xfree -Dmalloc=xmalloc \
- $(ALL_CFLAGS) ${srcdir}/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. */
- -rm -f allocatem.c
- cp ${srcdir}/alloca.s allocatem.c
-/* Remove any ^L, blank lines, and preprocessor comments,
- since some assemblers barf on them. Use a different basename for the
- output file, since some stupid compilers (Green Hill's) use that
- name for the intermediate assembler file. */
- $(CPP) $(CPPFLAGS) $(ALL_CFLAGS) allocatem.c | \
- sed -e 's/ //' -e 's/^#.*//' | \
- sed -n -e '/^..*$$/p' > allocax.s
- -rm -f alloca.o
-/* Xenix, in particular, needs to run assembler via cc. */
- $(CC) -c allocax.s
- mv allocax.o alloca.o
- -rm -f allocax.s allocatem.c
-#endif /* HAVE_ALLOCA */
-#endif /* ! defined (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 window.h commands.h $(config_h)
-buffer.o: buffer.c buffer.h region-cache.h commands.h window.h \
- INTERVAL_SRC blockinput.h $(config_h)
-callint.o: callint.c window.h commands.h buffer.h mocklisp.h \
- keyboard.h $(config_h)
-callproc.o: callproc.c paths.h buffer.h commands.h $(config_h) \
- process.h systty.h syssignal.h
-casefiddle.o: casefiddle.c syntax.h commands.h buffer.h $(config_h)
-casetab.o: casetab.c buffer.h $(config_h)
-cm.o: cm.c cm.h termhooks.h $(config_h)
-cmds.o: cmds.c syntax.h buffer.h commands.h window.h $(config_h)
-pre-crt0.o: pre-crt0.c
-ecrt0.o: ecrt0.c $(config_h)
- CRT0_COMPILE ${srcdir}/ecrt0.c
-dired.o: dired.c commands.h buffer.h $(config_h) regex.h
-dispnew.o: dispnew.c commands.h frame.h window.h buffer.h dispextern.h \
- termchar.h termopts.h termhooks.h cm.h disptab.h systty.h systime.h \
- xterm.h blockinput.h $(config_h)
-doc.o: doc.c $(config_h) paths.h buffer.h keyboard.h
-doprnt.o: doprnt.c $(config_h)
-dosfns.o: buffer.h termchar.h termhooks.h frame.h msdos.h dosfns.h $(config_h)
-editfns.o: editfns.c window.h buffer.h systime.h INTERVAL_SRC $(config_h)
-emacs.o: emacs.c commands.h systty.h syssignal.h blockinput.h process.h \
- INTERVAL_SRC $(config_h)
-fileio.o: fileio.c window.h buffer.h systime.h INTERVAL_SRC $(config_h)
-filelock.o: filelock.c buffer.h paths.h $(config_h)
-filemode.o: filemode.c $(config_h)
-frame.o: frame.c xterm.h window.h frame.h termhooks.h commands.h keyboard.h \
- buffer.h $(config_h)
-getloadavg.o: getloadavg.c $(config_h)
-indent.o: indent.c frame.h window.h indent.h buffer.h $(config_h) termchar.h \
- termopts.h disptab.h region-cache.h
-insdel.o: insdel.c window.h buffer.h INTERVAL_SRC blockinput.h $(config_h)
-keyboard.o: keyboard.c termchar.h termhooks.h termopts.h buffer.h \
- commands.h frame.h window.h macros.h disptab.h keyboard.h syssignal.h \
- systty.h systime.h dispextern.h intervals.h blockinput.h xterm.h $(config_h)
-keymap.o: keymap.c buffer.h commands.h keyboard.h termhooks.h blockinput.h \
- puresize.h $(config_h)
-lastfile.o: lastfile.c $(config_h)
-macros.o: macros.c window.h buffer.h commands.h macros.h keyboard.h $(config_h)
-malloc.o: malloc.c $(config_h)
-gmalloc.o: gmalloc.c $(config_h)
-ralloc.o: ralloc.c $(config_h)
-vm-limit.o: vm-limit.c mem-limits.h $(config_h)
-marker.o: marker.c buffer.h $(config_h)
-minibuf.o: minibuf.c syntax.h dispextern.h frame.h window.h \
- buffer.h commands.h $(config_h)
-mktime.o: mktime.c $(config_h)
-mocklisp.o: mocklisp.c buffer.h $(config_h)
-msdos.o: msdos.c msdos.h dosfns.h systime.h termhooks.h dispextern.h \
- termopts.h frame.h window.h $(config_h)
-process.o: process.c process.h buffer.h window.h termhooks.h termopts.h \
- commands.h syssignal.h systime.h systty.h syswait.h frame.h \
- blockinput.h $(config_h)
-regex.o: regex.c syntax.h buffer.h $(config_h) regex.h
-region-cache.o: region-cache.c buffer.h region-cache.h
-scroll.o: scroll.c termchar.h dispextern.h frame.h $(config_h)
-search.o: search.c regex.h commands.h buffer.h region-cache.h syntax.h \
- blockinput.h $(config_h)
-strftime.o: strftime.c $(config_h)
- $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -Dstrftime=emacs_strftime $<
-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 \
- frame.h syssignal.h systty.h systime.h syswait.h blockinput.h window.h
-term.o: term.c termchar.h termhooks.h termopts.h $(config_h) cm.h frame.h \
- disptab.h keyboard.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)
-/* This hack is to discard any space that cpp might put at the beginning
- of UNEXEC when substituting it in. */
-UNEXEC_ALIAS=UNEXEC
-$(UNEXEC_ALIAS): UNEXEC_SRC $(config_h)
-widget.o: widget.c xterm.h frame.h dispextern.h widgetprv.h \
- ../lwlib/lwlib.h $(config_h)
-window.o: window.c indent.h commands.h frame.h window.h buffer.h termchar.h \
- termhooks.h disptab.h keyboard.h $(config_h)
-xdisp.o: xdisp.c macros.h commands.h indent.h buffer.h dispextern.h \
- termchar.h frame.h window.h disptab.h termhooks.h $(config_h)
-xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \
- window.h $(config_h)
-xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h \
- ../lwlib/lwlib.h blockinput.h paths.h $(config_h)
-xmenu.o: xmenu.c xterm.h termhooks.h window.h dispextern.h frame.h keyboard.h \
- ../lwlib/lwlib.h blockinput.h puresize.h msdos.h $(config_h)
-xterm.o: xterm.c xterm.h termhooks.h termopts.h termchar.h window.h \
- dispextern.h frame.h disptab.h blockinput.h systime.h syssignal.h \
- keyboard.h gnu.h sink.h sinkmask.h $(config_h)
-xselect.o: xselect.c dispextern.h frame.h xterm.h blockinput.h $(config_h)
-xrdb.o: xrdb.c $(config_h)
-hftctl.o: hftctl.c $(config_h)
-
-/* The files of Lisp proper */
-
-alloc.o: alloc.c frame.h window.h buffer.h puresize.h syssignal.h keyboard.h \
- blockinput.h $(config_h) INTERVAL_SRC
-bytecode.o: bytecode.c buffer.h syntax.h $(config_h)
-data.o: data.c buffer.h puresize.h syssignal.h keyboard.h $(config_h)
-eval.o: eval.c commands.h keyboard.h blockinput.h $(config_h)
-floatfns.o: floatfns.c $(config_h)
-fns.o: fns.c commands.h $(config_h) frame.h buffer.h keyboard.h \
- frame.h window.h INTERVAL_SRC
-print.o: print.c process.h frame.h window.h buffer.h keyboard.h $(config_h)
-lread.o: lread.c commands.h keyboard.h buffer.h paths.h $(config_h) \
- termhooks.h
-
-/* Text properties support */
-textprop.o: textprop.c buffer.h window.h intervals.h $(config_h)
-intervals.o: intervals.c buffer.h intervals.h keyboard.h puresize.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 window.h $(config_h)
-
-${libsrc}emacstool: ${libsrc}emacstool.c
- cd ${libsrc}; ${MAKE} ${MFLAGS} emacstool
-mostlyclean:
- rm -f temacs prefix-args core \#* *.o libXMenu11.a liblw.a
- rm -f ../etc/DOC
-clean: mostlyclean
- rm -f emacs-* emacs
-/**/# This is used in making a distribution.
-/**/# Do not use it on development directories!
-distclean: clean
- rm -f paths.h config.h Makefile Makefile.c ../etc/DOC-*
-maintainer-clean: distclean
- @echo "This command is intended for maintainers to use;"
- @echo "it deletes files that may require special tools to rebuild."
- rm -f TAGS
-versionclean:
- -rm -f emacs emacs-* ../etc/DOC*
-extraclean: distclean
- -rm -f *~ \#* m/?*~ s/?*~
-
-/* The rule for the [sm] files has to be written a little funny to
- avoid looking like a C comment to CPP. */
-SOURCES = *.[ch] [sm]/?* COPYING Makefile.in \
- config.in paths.in README COPYING ChangeLog vms.pp-trans
-unlock:
- chmod u+w $(SOURCES)
-
-relock:
- chmod -w $(SOURCES)
- chmod +w paths.h
-
-/* Arrange to make a tags table in ../lisp, and another in this dir
- which includes ../lisp/TAGS by reference. */
-ctagsfiles = [a-zA-Z]*.[hc]
-lisptagsfiles = ../lisp/[a-zA-Z]*.el
-TAGS: $(srcdir)/$(ctagsfiles)
- export DIR; DIR=`pwd`; cd ${srcdir}; \
- $$DIR/../lib-src/etags --include=../lisp/TAGS \
- --regex='/[ ]*DEFVAR_[A-Z_ (]+"\([^"]+\)"/' $(ctagsfiles)
-${lispsource}TAGS: ${lispsource}$(lisptagsfiles)
- cd ${lispsource}; $(MAKE) TAGS
-tags: TAGS ${lispsource}TAGS
-.PHONY: tags
diff --git a/src/abbrev.c b/src/abbrev.c
deleted file mode 100644
index 098d2863ef8..00000000000
--- a/src/abbrev.c
+++ /dev/null
@@ -1,579 +0,0 @@
-/* Primitives for word-abbrev mode.
- Copyright (C) 1985, 1986, 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include <stdio.h>
-#include "lisp.h"
-#include "commands.h"
-#include "buffer.h"
-#include "window.h"
-#include "syntax.h"
-
-/* An abbrev table is an obarray.
- Each defined abbrev is represented by a symbol in that obarray
- whose print name is the abbreviation.
- The symbol's value is a string which is the expansion.
- If its function definition is non-nil, it is called
- after the expansion is done.
- The plist slot of the abbrev symbol is its usage count. */
-
-/* List of all abbrev-table name symbols:
- symbols whose values are abbrev tables. */
-
-Lisp_Object Vabbrev_table_name_list;
-
-/* The table of global abbrevs. These are in effect
- in any buffer in which abbrev mode is turned on. */
-
-Lisp_Object Vglobal_abbrev_table;
-
-/* The local abbrev table used by default (in Fundamental Mode buffers) */
-
-Lisp_Object Vfundamental_mode_abbrev_table;
-
-/* Set nonzero when an abbrev definition is changed */
-
-int abbrevs_changed;
-
-int abbrev_all_caps;
-
-/* Non-nil => use this location as the start of abbrev to expand
- (rather than taking the word before point as the abbrev) */
-
-Lisp_Object Vabbrev_start_location;
-
-/* Buffer that Vabbrev_start_location applies to */
-Lisp_Object Vabbrev_start_location_buffer;
-
-/* The symbol representing the abbrev most recently expanded */
-
-Lisp_Object Vlast_abbrev;
-
-/* A string for the actual text of the abbrev most recently expanded.
- This has more info than Vlast_abbrev since case is significant. */
-
-Lisp_Object Vlast_abbrev_text;
-
-/* Character address of start of last abbrev expanded */
-
-int last_abbrev_point;
-
-/* Hook to run before expanding any abbrev. */
-
-Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;
-
-DEFUN ("make-abbrev-table", Fmake_abbrev_table, Smake_abbrev_table, 0, 0, 0,
- "Create a new, empty abbrev table object.")
- ()
-{
- return Fmake_vector (make_number (59), make_number (0));
-}
-
-DEFUN ("clear-abbrev-table", Fclear_abbrev_table, Sclear_abbrev_table, 1, 1, 0,
- "Undefine all abbrevs in abbrev table TABLE, leaving it empty.")
- (table)
- Lisp_Object table;
-{
- int i, size;
-
- CHECK_VECTOR (table, 0);
- size = XVECTOR (table)->size;
- abbrevs_changed = 1;
- for (i = 0; i < size; i++)
- XVECTOR (table)->contents[i] = make_number (0);
- return Qnil;
-}
-
-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 must be a string.\n\
-EXPANSION should usually be a string.\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.\n\
-If EXPANSION is not a string, the abbrev is a special one,\n\
- which does not expand in the usual way but only runs HOOK.")
- (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 (NILP (count))
- count = make_number (0);
- else
- CHECK_NUMBER (count, 0);
-
- sym = Fintern (name, table);
-
- oexp = XSYMBOL (sym)->value;
- ohook = XSYMBOL (sym)->function;
- if (!((EQ (oexp, expansion)
- || (STRINGP (oexp) && STRINGP (expansion)
- && (tem = Fstring_equal (oexp, expansion), !NILP (tem))))
- &&
- (EQ (ohook, hook)
- || (tem = Fequal (ohook, hook), !NILP (tem)))))
- abbrevs_changed = 1;
-
- Fset (sym, expansion);
- Ffset (sym, hook);
- Fsetplist (sym, count);
-
- return name;
-}
-
-DEFUN ("define-global-abbrev", Fdefine_global_abbrev, Sdefine_global_abbrev, 2, 2,
- "sDefine global abbrev: \nsExpansion for %s: ",
- "Define ABBREV as a global abbreviation for EXPANSION.")
- (abbrev, expansion)
- Lisp_Object abbrev, expansion;
-{
- Fdefine_abbrev (Vglobal_abbrev_table, Fdowncase (abbrev),
- expansion, Qnil, make_number (0));
- return abbrev;
-}
-
-DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2,
- "sDefine mode abbrev: \nsExpansion for %s: ",
- "Define ABBREV as a mode-specific abbreviation for EXPANSION.")
- (abbrev, expansion)
- Lisp_Object abbrev, expansion;
-{
- if (NILP (current_buffer->abbrev_table))
- error ("Major mode has no abbrev table");
-
- Fdefine_abbrev (current_buffer->abbrev_table, Fdowncase (abbrev),
- expansion, Qnil, make_number (0));
- return abbrev;
-}
-
-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\
-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.")
- (abbrev, table)
- Lisp_Object abbrev, table;
-{
- Lisp_Object sym;
- CHECK_STRING (abbrev, 0);
- if (!NILP (table))
- sym = Fintern_soft (abbrev, table);
- else
- {
- sym = Qnil;
- if (!NILP (current_buffer->abbrev_table))
- sym = Fintern_soft (abbrev, current_buffer->abbrev_table);
- if (NILP (XSYMBOL (sym)->value))
- sym = Qnil;
- if (NILP (sym))
- sym = Fintern_soft (abbrev, Vglobal_abbrev_table);
- }
- if (NILP (XSYMBOL (sym)->value)) return Qnil;
- return sym;
-}
-
-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.")
- (abbrev, table)
- Lisp_Object abbrev, table;
-{
- Lisp_Object sym;
- sym = Fabbrev_symbol (abbrev, table);
- if (NILP (sym)) return sym;
- return Fsymbol_value (sym);
-}
-
-/* Expand the word before point, if it is an abbrev.
- 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\
-Returns the abbrev symbol, if expansion took place.")
- ()
-{
- register char *buffer, *p;
- register int wordstart, wordend, idx;
- int whitecnt;
- int uccount = 0, lccount = 0;
- register Lisp_Object sym;
- Lisp_Object expansion, hook, tem;
- int oldmodiff = MODIFF;
- Lisp_Object value;
-
- value = Qnil;
-
- if (!NILP (Vrun_hooks))
- call1 (Vrun_hooks, Qpre_abbrev_expand_hook);
-
- wordstart = 0;
- if (!(BUFFERP (Vabbrev_start_location_buffer)
- && XBUFFER (Vabbrev_start_location_buffer) == current_buffer))
- Vabbrev_start_location = Qnil;
- if (!NILP (Vabbrev_start_location))
- {
- tem = Vabbrev_start_location;
- CHECK_NUMBER_COERCE_MARKER (tem, 0);
- wordstart = XINT (tem);
- Vabbrev_start_location = Qnil;
- if (wordstart < BEGV || wordstart > ZV)
- wordstart = 0;
- if (wordstart && wordstart != ZV && FETCH_CHAR (wordstart) == '-')
- del_range (wordstart, wordstart + 1);
- }
- if (!wordstart)
- wordstart = scan_words (PT, -1);
-
- if (!wordstart)
- return value;
-
- wordend = scan_words (wordstart, 1);
- if (!wordend)
- return value;
-
- if (wordend > PT)
- wordend = PT;
- whitecnt = PT - wordend;
- if (wordend <= wordstart)
- return value;
-
- p = buffer = (char *) alloca (wordend - wordstart);
-
- for (idx = wordstart; idx < wordend; idx++)
- {
- register int c = FETCH_CHAR (idx);
- if (UPPERCASEP (c))
- c = DOWNCASE (c), uccount++;
- else if (! NOCASEP (c))
- lccount++;
- *p++ = c;
- }
-
- if (VECTORP (current_buffer->abbrev_table))
- sym = oblookup (current_buffer->abbrev_table, buffer, p - buffer);
- else
- XSETFASTINT (sym, 0);
- if (INTEGERP (sym) || NILP (XSYMBOL (sym)->value))
- sym = oblookup (Vglobal_abbrev_table, buffer, p - buffer);
- if (INTEGERP (sym) || NILP (XSYMBOL (sym)->value))
- return value;
-
- if (INTERACTIVE && !EQ (minibuf_window, selected_window))
- {
- /* Add an undo boundary, in case we are doing this for
- a self-inserting command which has avoided making one so far. */
- SET_PT (wordend);
- Fundo_boundary ();
- }
-
- Vlast_abbrev_text
- = Fbuffer_substring (make_number (wordstart), make_number (wordend));
-
- /* Now sym is the abbrev symbol. */
- Vlast_abbrev = sym;
- value = sym;
- last_abbrev_point = wordstart;
-
- if (INTEGERP (XSYMBOL (sym)->plist))
- XSETINT (XSYMBOL (sym)->plist,
- XINT (XSYMBOL (sym)->plist) + 1); /* Increment use count */
-
- /* If this abbrev has an expansion, delete the abbrev
- and insert the expansion. */
- expansion = XSYMBOL (sym)->value;
- if (STRINGP (expansion))
- {
- SET_PT (wordstart);
-
- del_range (wordstart, wordend);
-
- insert_from_string (expansion, 0, XSTRING (expansion)->size, 1);
- SET_PT (PT + whitecnt);
-
- if (uccount && !lccount)
- {
- /* Abbrev was all caps */
- /* If expansion is multiple words, normally capitalize each word */
- /* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
- but Megatest 68000 compiler can't handle that */
- if (!abbrev_all_caps)
- if (scan_words (PT, -1) > scan_words (wordstart, 1))
- {
- Fupcase_initials_region (make_number (wordstart),
- make_number (PT));
- goto caped;
- }
- /* If expansion is one word, or if user says so, upcase it all. */
- Fupcase_region (make_number (wordstart), make_number (PT));
- caped: ;
- }
- else if (uccount)
- {
- /* Abbrev included some caps. Cap first initial of expansion */
- int pos = wordstart;
-
- /* Find the initial. */
- while (pos < PT
- && SYNTAX (*BUF_CHAR_ADDRESS (current_buffer, pos)) != Sword)
- pos++;
-
- /* Change just that. */
- Fupcase_initials_region (make_number (pos), make_number (pos + 1));
- }
- }
-
- hook = XSYMBOL (sym)->function;
- if (!NILP (hook))
- call0 (hook);
-
- return value;
-}
-
-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.")
- ()
-{
- int opoint = PT;
- int adjust = 0;
- if (last_abbrev_point < BEGV
- || last_abbrev_point > ZV)
- return Qnil;
- SET_PT (last_abbrev_point);
- if (STRINGP (Vlast_abbrev_text))
- {
- /* This isn't correct if Vlast_abbrev->function was used
- to do the expansion */
- Lisp_Object val;
- val = XSYMBOL (Vlast_abbrev)->value;
- if (!STRINGP (val))
- error ("value of abbrev-symbol must be a string");
- adjust = XSTRING (val)->size;
- del_range (PT, PT + adjust);
- /* Don't inherit properties here; just copy from old contents. */
- insert_from_string (Vlast_abbrev_text, 0,
- XSTRING (Vlast_abbrev_text)->size, 0);
- adjust -= XSTRING (Vlast_abbrev_text)->size;
- Vlast_abbrev_text = Qnil;
- }
- SET_PT (last_abbrev_point < opoint ? opoint - adjust : opoint);
- return Qnil;
-}
-
-static
-write_abbrev (sym, stream)
- Lisp_Object sym, stream;
-{
- Lisp_Object name;
- if (NILP (XSYMBOL (sym)->value))
- return;
- insert (" (", 5);
- XSETSTRING (name, XSYMBOL (sym)->name);
- Fprin1 (name, stream);
- insert (" ", 1);
- Fprin1 (XSYMBOL (sym)->value, stream);
- insert (" ", 1);
- Fprin1 (XSYMBOL (sym)->function, stream);
- insert (" ", 1);
- Fprin1 (XSYMBOL (sym)->plist, stream);
- insert (")\n", 2);
-}
-
-static
-describe_abbrev (sym, stream)
- Lisp_Object sym, stream;
-{
- Lisp_Object one;
-
- if (NILP (XSYMBOL (sym)->value))
- return;
- one = make_number (1);
- Fprin1 (Fsymbol_name (sym), stream);
- Findent_to (make_number (15), one);
- Fprin1 (XSYMBOL (sym)->plist, stream);
- Findent_to (make_number (20), one);
- Fprin1 (XSYMBOL (sym)->value, stream);
- if (!NILP (XSYMBOL (sym)->function))
- {
- Findent_to (make_number (45), one);
- Fprin1 (XSYMBOL (sym)->function, stream);
- }
- Fterpri (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\
-NAME is a symbol whose value is an abbrev table.\n\
-If optional 2nd arg READABLE is non-nil, a human-readable description\n\
-is inserted. 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.")
- (name, readable)
- Lisp_Object name, readable;
-{
- Lisp_Object table;
- Lisp_Object stream;
-
- CHECK_SYMBOL (name, 0);
- table = Fsymbol_value (name);
- CHECK_VECTOR (table, 0);
-
- XSETBUFFER (stream, current_buffer);
-
- if (!NILP (readable))
- {
- insert_string ("(");
- Fprin1 (name, stream);
- insert_string (")\n\n");
- map_obarray (table, describe_abbrev, stream);
- insert_string ("\n\n");
- }
- else
- {
- insert_string ("(define-abbrev-table '");
- Fprin1 (name, stream);
- insert_string (" '(\n");
- map_obarray (table, write_abbrev, stream);
- insert_string (" ))\n\n");
- }
-
- return Qnil;
-}
-
-DEFUN ("define-abbrev-table", Fdefine_abbrev_table, Sdefine_abbrev_table,
- 2, 2, 0,
- "Define TABLENAME (a symbol) as an abbrev table name.\n\
-Define abbrevs in it according to DEFINITIONS, which is a list of elements\n\
-of the form (ABBREVNAME EXPANSION HOOK USECOUNT).")
- (tablename, definitions)
- Lisp_Object tablename, definitions;
-{
- Lisp_Object name, exp, hook, count;
- Lisp_Object table, elt;
-
- CHECK_SYMBOL (tablename, 0);
- table = Fboundp (tablename);
- if (NILP (table) || (table = Fsymbol_value (tablename), NILP (table)))
- {
- table = Fmake_abbrev_table ();
- Fset (tablename, table);
- Vabbrev_table_name_list = Fcons (tablename, Vabbrev_table_name_list);
- }
- CHECK_VECTOR (table, 0);
-
- for (; !NILP (definitions); definitions = Fcdr (definitions))
- {
- elt = Fcar (definitions);
- name = Fcar (elt); elt = Fcdr (elt);
- exp = Fcar (elt); elt = Fcdr (elt);
- hook = Fcar (elt); elt = Fcdr (elt);
- count = Fcar (elt);
- Fdefine_abbrev (table, name, exp, hook, count);
- }
- return Qnil;
-}
-
-syms_of_abbrev ()
-{
- DEFVAR_LISP ("abbrev-table-name-list", &Vabbrev_table_name_list,
- "List of symbols whose values are abbrev tables.");
- Vabbrev_table_name_list = Fcons (intern ("fundamental-mode-abbrev-table"),
- Fcons (intern ("global-abbrev-table"),
- Qnil));
-
- DEFVAR_LISP ("global-abbrev-table", &Vglobal_abbrev_table,
- "The abbrev table whose abbrevs affect all buffers.\n\
-Each buffer may also have a local abbrev table.\n\
-If it does, the local table overrides the global one\n\
-for any particular abbrev defined in both.");
- Vglobal_abbrev_table = Fmake_abbrev_table ();
-
- DEFVAR_LISP ("fundamental-mode-abbrev-table", &Vfundamental_mode_abbrev_table,
- "The abbrev table of mode-specific abbrevs for Fundamental Mode.");
- Vfundamental_mode_abbrev_table = Fmake_abbrev_table ();
- 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'.");
-
- 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.");
-
- 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\
-nil means use the word before point as the abbrev.\n\
-Calling `expand-abbrev' sets this to nil.");
- 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'.");
- Vabbrev_start_location_buffer = Qnil;
-
- DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table, Qnil,
- "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.");
- abbrevs_changed = 0;
-
- DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps,
- "*Set non-nil means expand multi-word abbrevs all caps if abbrev was so.");
- abbrev_all_caps = 0;
-
- DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook,
- "Function or functions to be called before abbrev expansion is done.\n\
-This is the first thing that `expand-abbrev' does, and so this may change\n\
-the current abbrev table before abbrev lookup happens.");
- Vpre_abbrev_expand_hook = Qnil;
- Qpre_abbrev_expand_hook = intern ("pre-abbrev-expand-hook");
- staticpro (&Qpre_abbrev_expand_hook);
-
- defsubr (&Smake_abbrev_table);
- defsubr (&Sclear_abbrev_table);
- defsubr (&Sdefine_abbrev);
- defsubr (&Sdefine_global_abbrev);
- defsubr (&Sdefine_mode_abbrev);
- defsubr (&Sabbrev_expansion);
- defsubr (&Sabbrev_symbol);
- defsubr (&Sexpand_abbrev);
- defsubr (&Sunexpand_abbrev);
- defsubr (&Sinsert_abbrev_table_description);
- defsubr (&Sdefine_abbrev_table);
-}
diff --git a/src/acldef.h b/src/acldef.h
deleted file mode 100644
index cc4085c6aab..00000000000
--- a/src/acldef.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#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
deleted file mode 100644
index ad7e6beb4a3..00000000000
--- a/src/alloc.c
+++ /dev/null
@@ -1,2688 +0,0 @@
-/* Storage allocation and gc for GNU Emacs Lisp interpreter.
- Copyright (C) 1985, 86, 88, 93, 94, 95 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Note that this declares bzero on OSF/1. How dumb. */
-#include <signal.h>
-
-#include <config.h>
-#include "lisp.h"
-#include "intervals.h"
-#include "puresize.h"
-#ifndef standalone
-#include "buffer.h"
-#include "window.h"
-#include "frame.h"
-#include "blockinput.h"
-#include "keyboard.h"
-#endif
-
-#include "syssignal.h"
-
-extern char *sbrk ();
-
-/* The following come from gmalloc.c. */
-
-#if defined (__STDC__) && __STDC__
-#include <stddef.h>
-#define __malloc_size_t size_t
-#else
-#define __malloc_size_t unsigned int
-#endif
-extern __malloc_size_t _bytes_used;
-extern int __malloc_extra_blocks;
-
-extern Lisp_Object Vhistory_length;
-
-#define max(A,B) ((A) > (B) ? (A) : (B))
-#define min(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; \
- XSETCONS (val, (char *) address + size); \
- if ((char *) XCONS (val) != (char *) address + size) \
- { \
- xfree (address); \
- memory_full (); \
- } \
- } while (0)
-
-/* Value of _bytes_used, when spare_memory was freed. */
-static __malloc_size_t bytes_used_when_full;
-
-/* Number of bytes of consing done since the last gc */
-int consing_since_gc;
-
-/* Count the amount of consing of various sorts of space. */
-int cons_cells_consed;
-int floats_consed;
-int vector_cells_consed;
-int symbols_consed;
-int string_chars_consed;
-int misc_objects_consed;
-int intervals_consed;
-
-/* Number of bytes of consing since gc before another gc should be done. */
-int gc_cons_threshold;
-
-/* Nonzero during gc */
-int gc_in_progress;
-
-/* Nonzero means display messages at beginning and end of GC. */
-int garbage_collection_messages;
-
-#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 limits controlling how much undo information to keep. */
-int undo_limit;
-int undo_strong_limit;
-
-/* Points to memory space allocated as "spare",
- to be freed if we run out of memory. */
-static char *spare_memory;
-
-/* Amount of spare memory to keep in reserve. */
-#define SPARE_MEMORY (1 << 14)
-
-/* Number of extra blocks malloc should get when it needs more core. */
-static int malloc_hysteresis;
-
-/* Nonzero when malloc is called for allocating Lisp object space. */
-int allocating_for_lisp;
-
-/* Non-nil means defun should do purecopy on the function definition */
-Lisp_Object Vpurify_flag;
-
-#ifndef HAVE_SHM
-EMACS_INT pure[PURESIZE / sizeof (EMACS_INT)] = {0,}; /* Force it into data space! */
-#define PUREBEG (char *) pure
-#else
-#define pure PURE_SEG_BITS /* Use shared memory segment */
-#define PUREBEG (char *)PURE_SEG_BITS
-
-/* This variable is used only by the XPNTR macro when HAVE_SHM is
- defined. If we used the PURESIZE macro directly there, that would
- make most of emacs dependent on puresize.h, which we don't want -
- you should be able to change that without too much recompilation.
- So map_in_data initializes pure_size, and the dependencies work
- out. */
-EMACS_INT pure_size;
-#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;
-
-/* Pre-computed signal argument for use when memory is exhausted. */
-Lisp_Object memory_signal_data;
-
-/* Maximum amount of C stack to save when a GC happens. */
-
-#ifndef MAX_SAVE_STACK
-#define MAX_SAVE_STACK 16000
-#endif
-
-/* Define DONT_COPY_FLAG to be some bit which will always be zero in a
- pointer to a Lisp_Object, when that pointer is viewed as an integer.
- (On most machines, pointers are even, so we can use the low bit.
- Word-addressable architectures may need to override this in the m-file.)
- When linking references to small strings through the size field, we
- use this slot to hold the bit that would otherwise be interpreted as
- the GC mark bit. */
-#ifndef DONT_COPY_FLAG
-#define DONT_COPY_FLAG 1
-#endif /* no DONT_COPY_FLAG */
-
-/* Buffer in which we save a copy of the C stack at each GC. */
-
-char *stack_copy;
-int stack_copy_size;
-
-/* Non-zero means ignore malloc warnings. Set during initialization. */
-int ignore_warnings;
-
-Lisp_Object Qgc_cons_threshold, Qchar_table_extra_slots;
-
-static void mark_object (), mark_buffer (), mark_kboards ();
-static void clear_marks (), gc_sweep ();
-static void compact_strings ();
-
-/* Versions of malloc and realloc that print warnings as memory gets full. */
-
-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 ()
-{
-#ifndef SYSTEM_MALLOC
- bytes_used_when_full = _bytes_used;
-#endif
-
- /* The first time we get here, free the spare memory. */
- if (spare_memory)
- {
- free (spare_memory);
- spare_memory = 0;
- }
-
- /* This used to call error, but if we've run out of memory, we could get
- infinite recursion trying to build the string. */
- while (1)
- Fsignal (Qerror, memory_signal_data);
-}
-
-/* Called if we can't allocate relocatable space for a buffer. */
-
-void
-buffer_memory_full ()
-{
- /* If buffers use the relocating allocator,
- no need to free spare_memory, because we may have plenty of malloc
- space left that we could get, and if we don't, the malloc that fails
- will itself cause spare_memory to be freed.
- If buffers don't use the relocating allocator,
- treat this like any other failing malloc. */
-
-#ifndef REL_ALLOC
- memory_full ();
-#endif
-
- /* This used to call error, but if we've run out of memory, we could get
- infinite recursion trying to build the string. */
- while (1)
- Fsignal (Qerror, memory_signal_data);
-}
-
-/* like malloc routines but check for no memory and block interrupt input. */
-
-long *
-xmalloc (size)
- int size;
-{
- register long *val;
-
- BLOCK_INPUT;
- val = (long *) malloc (size);
- UNBLOCK_INPUT;
-
- if (!val && size) memory_full ();
- return val;
-}
-
-long *
-xrealloc (block, size)
- long *block;
- int size;
-{
- register long *val;
-
- BLOCK_INPUT;
- /* We must call malloc explicitly when BLOCK is 0, since some
- reallocs don't do this. */
- if (! block)
- val = (long *) malloc (size);
- else
- val = (long *) realloc (block, size);
- UNBLOCK_INPUT;
-
- if (!val && size) memory_full ();
- return val;
-}
-
-void
-xfree (block)
- long *block;
-{
- BLOCK_INPUT;
- free (block);
- UNBLOCK_INPUT;
-}
-
-
-/* Arranging to disable input signals while we're in malloc.
-
- This only works with GNU malloc. To help out systems which can't
- use GNU malloc, all the calls to malloc, realloc, and free
- elsewhere in the code should be inside a BLOCK_INPUT/UNBLOCK_INPUT
- pairs; unfortunately, we have no idea what C library functions
- might call malloc, so we can't really protect them unless you're
- using GNU malloc. Fortunately, most of the major operating can use
- GNU malloc. */
-
-#ifndef SYSTEM_MALLOC
-extern void * (*__malloc_hook) ();
-static void * (*old_malloc_hook) ();
-extern void * (*__realloc_hook) ();
-static void * (*old_realloc_hook) ();
-extern void (*__free_hook) ();
-static void (*old_free_hook) ();
-
-/* This function is used as the hook for free to call. */
-
-static void
-emacs_blocked_free (ptr)
- void *ptr;
-{
- BLOCK_INPUT;
- __free_hook = old_free_hook;
- free (ptr);
- /* If we released our reserve (due to running out of memory),
- and we have a fair amount free once again,
- try to set aside another reserve in case we run out once more. */
- if (spare_memory == 0
- /* Verify there is enough space that even with the malloc
- hysteresis this call won't run out again.
- The code here is correct as long as SPARE_MEMORY
- is substantially larger than the block size malloc uses. */
- && (bytes_used_when_full
- > _bytes_used + max (malloc_hysteresis, 4) * SPARE_MEMORY))
- spare_memory = (char *) malloc (SPARE_MEMORY);
-
- __free_hook = emacs_blocked_free;
- UNBLOCK_INPUT;
-}
-
-/* If we released our reserve (due to running out of memory),
- and we have a fair amount free once again,
- try to set aside another reserve in case we run out once more.
-
- This is called when a relocatable block is freed in ralloc.c. */
-
-void
-refill_memory_reserve ()
-{
- if (spare_memory == 0)
- spare_memory = (char *) malloc (SPARE_MEMORY);
-}
-
-/* This function is the malloc hook that Emacs uses. */
-
-static void *
-emacs_blocked_malloc (size)
- unsigned size;
-{
- void *value;
-
- BLOCK_INPUT;
- __malloc_hook = old_malloc_hook;
- __malloc_extra_blocks = malloc_hysteresis;
- value = (void *) malloc (size);
- __malloc_hook = emacs_blocked_malloc;
- UNBLOCK_INPUT;
-
- return value;
-}
-
-static void *
-emacs_blocked_realloc (ptr, size)
- void *ptr;
- unsigned size;
-{
- void *value;
-
- BLOCK_INPUT;
- __realloc_hook = old_realloc_hook;
- value = (void *) realloc (ptr, size);
- __realloc_hook = emacs_blocked_realloc;
- UNBLOCK_INPUT;
-
- return value;
-}
-
-void
-uninterrupt_malloc ()
-{
- old_free_hook = __free_hook;
- __free_hook = emacs_blocked_free;
-
- old_malloc_hook = __malloc_hook;
- __malloc_hook = emacs_blocked_malloc;
-
- old_realloc_hook = __realloc_hook;
- __realloc_hook = emacs_blocked_realloc;
-}
-#endif
-
-/* Interval allocation. */
-
-#ifdef USE_TEXT_PROPERTIES
-#define INTERVAL_BLOCK_SIZE \
- ((1020 - sizeof (struct interval_block *)) / sizeof (struct interval))
-
-struct interval_block
- {
- struct interval_block *next;
- struct interval intervals[INTERVAL_BLOCK_SIZE];
- };
-
-struct interval_block *interval_block;
-static int interval_block_index;
-
-INTERVAL interval_free_list;
-
-static void
-init_intervals ()
-{
- allocating_for_lisp = 1;
- interval_block
- = (struct interval_block *) malloc (sizeof (struct interval_block));
- allocating_for_lisp = 0;
- interval_block->next = 0;
- bzero ((char *) interval_block->intervals, sizeof interval_block->intervals);
- interval_block_index = 0;
- interval_free_list = 0;
-}
-
-#define INIT_INTERVALS init_intervals ()
-
-INTERVAL
-make_interval ()
-{
- INTERVAL val;
-
- if (interval_free_list)
- {
- val = interval_free_list;
- interval_free_list = interval_free_list->parent;
- }
- else
- {
- if (interval_block_index == INTERVAL_BLOCK_SIZE)
- {
- register struct interval_block *newi;
-
- allocating_for_lisp = 1;
- newi = (struct interval_block *) xmalloc (sizeof (struct interval_block));
-
- allocating_for_lisp = 0;
- VALIDATE_LISP_STORAGE (newi, sizeof *newi);
- newi->next = interval_block;
- interval_block = newi;
- interval_block_index = 0;
- }
- val = &interval_block->intervals[interval_block_index++];
- }
- consing_since_gc += sizeof (struct interval);
- intervals_consed++;
- RESET_INTERVAL (val);
- return val;
-}
-
-static int total_free_intervals, total_intervals;
-
-/* Mark the pointers of one interval. */
-
-static void
-mark_interval (i, dummy)
- register INTERVAL i;
- Lisp_Object dummy;
-{
- if (XMARKBIT (i->plist))
- abort ();
- mark_object (&i->plist);
- XMARK (i->plist);
-}
-
-static void
-mark_interval_tree (tree)
- register INTERVAL tree;
-{
- /* No need to test if this tree has been marked already; this
- function is always called through the MARK_INTERVAL_TREE macro,
- which takes care of that. */
-
- /* XMARK expands to an assignment; the LHS of an assignment can't be
- a cast. */
- XMARK (* (Lisp_Object *) &tree->parent);
-
- traverse_intervals (tree, 1, 0, mark_interval, Qnil);
-}
-
-#define MARK_INTERVAL_TREE(i) \
- do { \
- if (!NULL_INTERVAL_P (i) \
- && ! XMARKBIT ((Lisp_Object) i->parent)) \
- mark_interval_tree (i); \
- } while (0)
-
-/* The oddity in the call to XUNMARK is necessary because XUNMARK
- expands to an assignment to its argument, and most C compilers don't
- support casts on the left operand of `='. */
-#define UNMARK_BALANCE_INTERVALS(i) \
-{ \
- if (! NULL_INTERVAL_P (i)) \
- { \
- XUNMARK (* (Lisp_Object *) (&(i)->parent)); \
- (i) = balance_intervals (i); \
- } \
-}
-
-#else /* no interval use */
-
-#define INIT_INTERVALS
-
-#define UNMARK_BALANCE_INTERVALS(i)
-#define MARK_INTERVAL_TREE(i)
-
-#endif /* no interval use */
-
-/* Floating point allocation. */
-
-#ifdef LISP_FLOAT_TYPE
-/* Allocation of float cells, just like conses */
-/* We store float cells inside of float_blocks, allocating a new
- float_block with malloc whenever necessary. Float cells reclaimed by
- GC are put on a free list to be reallocated before allocating
- any new float cells from the latest float_block.
-
- Each float_block is just under 1020 bytes long,
- since malloc really allocates in units of powers of two
- and uses 4 bytes for its own overhead. */
-
-#define FLOAT_BLOCK_SIZE \
- ((1020 - sizeof (struct float_block *)) / sizeof (struct Lisp_Float))
-
-struct float_block
- {
- struct float_block *next;
- struct Lisp_Float floats[FLOAT_BLOCK_SIZE];
- };
-
-struct float_block *float_block;
-int float_block_index;
-
-struct Lisp_Float *float_free_list;
-
-void
-init_float ()
-{
- allocating_for_lisp = 1;
- float_block = (struct float_block *) malloc (sizeof (struct float_block));
- allocating_for_lisp = 0;
- float_block->next = 0;
- bzero ((char *) float_block->floats, sizeof float_block->floats);
- float_block_index = 0;
- float_free_list = 0;
-}
-
-/* Explicitly free a float cell. */
-free_float (ptr)
- struct Lisp_Float *ptr;
-{
- *(struct Lisp_Float **)&ptr->type = float_free_list;
- float_free_list = ptr;
-}
-
-Lisp_Object
-make_float (float_value)
- double float_value;
-{
- register Lisp_Object val;
-
- if (float_free_list)
- {
- XSETFLOAT (val, float_free_list);
- float_free_list = *(struct Lisp_Float **)&float_free_list->type;
- }
- else
- {
- if (float_block_index == FLOAT_BLOCK_SIZE)
- {
- register struct float_block *new;
-
- allocating_for_lisp = 1;
- new = (struct float_block *) xmalloc (sizeof (struct float_block));
- allocating_for_lisp = 0;
- VALIDATE_LISP_STORAGE (new, sizeof *new);
- new->next = float_block;
- float_block = new;
- float_block_index = 0;
- }
- XSETFLOAT (val, &float_block->floats[float_block_index++]);
- }
- XFLOAT (val)->data = float_value;
- XSETFASTINT (XFLOAT (val)->type, 0); /* bug chasing -wsr */
- consing_since_gc += sizeof (struct Lisp_Float);
- floats_consed++;
- return val;
-}
-
-#endif /* LISP_FLOAT_TYPE */
-
-/* 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 1020 bytes long,
- since malloc really allocates in units of powers of two
- and uses 4 bytes for its own overhead. */
-
-#define CONS_BLOCK_SIZE \
- ((1020 - 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 ()
-{
- allocating_for_lisp = 1;
- cons_block = (struct cons_block *) malloc (sizeof (struct cons_block));
- allocating_for_lisp = 0;
- cons_block->next = 0;
- bzero ((char *) 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;
-{
- *(struct Lisp_Cons **)&ptr->car = 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)
- {
- XSETCONS (val, cons_free_list);
- cons_free_list = *(struct Lisp_Cons **)&cons_free_list->car;
- }
- else
- {
- if (cons_block_index == CONS_BLOCK_SIZE)
- {
- register struct cons_block *new;
- allocating_for_lisp = 1;
- new = (struct cons_block *) xmalloc (sizeof (struct cons_block));
- allocating_for_lisp = 0;
- VALIDATE_LISP_STORAGE (new, sizeof *new);
- new->next = cons_block;
- cons_block = new;
- cons_block_index = 0;
- }
- XSETCONS (val, &cons_block->conses[cons_block_index++]);
- }
- XCONS (val)->car = car;
- XCONS (val)->cdr = cdr;
- consing_since_gc += sizeof (struct Lisp_Cons);
- cons_cells_consed++;
- return val;
-}
-
-DEFUN ("list", Flist, Slist, 0, MANY, 0,
- "Return a newly created list with specified arguments as elements.\n\
-Any number of arguments, even zero arguments, are allowed.")
- (nargs, args)
- int nargs;
- register Lisp_Object *args;
-{
- register Lisp_Object val;
- val = Qnil;
-
- while (nargs > 0)
- {
- nargs--;
- val = Fcons (args[nargs], val);
- }
- 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;
-
- CHECK_NATNUM (length, 0);
- size = XFASTINT (length);
-
- val = Qnil;
- while (size-- > 0)
- val = Fcons (init, val);
- return val;
-}
-
-/* Allocation of vectors */
-
-struct Lisp_Vector *all_vectors;
-
-struct Lisp_Vector *
-allocate_vectorlike (len)
- EMACS_INT len;
-{
- struct Lisp_Vector *p;
-
- allocating_for_lisp = 1;
- p = (struct Lisp_Vector *)xmalloc (sizeof (struct Lisp_Vector)
- + (len - 1) * sizeof (Lisp_Object));
- allocating_for_lisp = 0;
- VALIDATE_LISP_STORAGE (p, 0);
- consing_since_gc += (sizeof (struct Lisp_Vector)
- + (len - 1) * sizeof (Lisp_Object));
- vector_cells_consed += len;
-
- p->next = all_vectors;
- all_vectors = p;
- return p;
-}
-
-DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0,
- "Return a newly created vector of length LENGTH, with each element being INIT.\n\
-See also the function `vector'.")
- (length, init)
- register Lisp_Object length, init;
-{
- Lisp_Object vector;
- register EMACS_INT sizei;
- register int index;
- register struct Lisp_Vector *p;
-
- CHECK_NATNUM (length, 0);
- sizei = XFASTINT (length);
-
- p = allocate_vectorlike (sizei);
- p->size = sizei;
- for (index = 0; index < sizei; index++)
- p->contents[index] = init;
-
- XSETVECTOR (vector, p);
- return vector;
-}
-
-DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0,
- "Return a newly created char-table, with purpose PURPOSE.\n\
-Each element is initialized to INIT, which defaults to nil.\n\
-PURPOSE should be a symbol which has a `char-table-extra-slots' property.\n\
-The property's value should be an integer between 0 and 10.")
- (purpose, init)
- register Lisp_Object purpose, init;
-{
- Lisp_Object vector;
- Lisp_Object n;
- CHECK_SYMBOL (purpose, 1);
- n = Fget (purpose, Qchar_table_extra_slots);
- CHECK_NUMBER (n, 0);
- if (XINT (n) < 0 || XINT (n) > 10)
- args_out_of_range (n, Qnil);
- /* Add 2 to the size for the defalt and parent slots. */
- vector = Fmake_vector (make_number (CHAR_TABLE_STANDARD_SLOTS + XINT (n)),
- init);
- XCHAR_TABLE (vector)->parent = Qnil;
- XCHAR_TABLE (vector)->purpose = purpose;
- XSETCHAR_TABLE (vector, XCHAR_TABLE (vector));
- return vector;
-}
-
-DEFUN ("vector", Fvector, Svector, 0, MANY, 0,
- "Return a newly created vector with specified arguments as elements.\n\
-Any number of arguments, even zero arguments, are allowed.")
- (nargs, args)
- register int nargs;
- Lisp_Object *args;
-{
- register Lisp_Object len, val;
- register int index;
- register struct Lisp_Vector *p;
-
- XSETFASTINT (len, nargs);
- val = Fmake_vector (len, Qnil);
- p = XVECTOR (val);
- for (index = 0; index < nargs; index++)
- p->contents[index] = args[index];
- return val;
-}
-
-DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0,
- "Create a byte-code object with specified arguments as elements.\n\
-The arguments should be the arglist, bytecode-string, constant vector,\n\
-stack size, (optional) doc string, and (optional) interactive spec.\n\
-The first four arguments are required; at most six have any\n\
-significance.")
- (nargs, args)
- register int nargs;
- Lisp_Object *args;
-{
- register Lisp_Object len, val;
- register int index;
- register struct Lisp_Vector *p;
-
- XSETFASTINT (len, nargs);
- if (!NILP (Vpurify_flag))
- val = make_pure_vector ((EMACS_INT) nargs);
- else
- val = Fmake_vector (len, Qnil);
- p = XVECTOR (val);
- for (index = 0; index < nargs; index++)
- {
- if (!NILP (Vpurify_flag))
- args[index] = Fpurecopy (args[index]);
- p->contents[index] = args[index];
- }
- XSETCOMPILED (val, val);
- return val;
-}
-
-/* Allocation of symbols.
- Just like allocation of conses!
-
- Each symbol_block is just under 1020 bytes long,
- since malloc really allocates in units of powers of two
- and uses 4 bytes for its own overhead. */
-
-#define SYMBOL_BLOCK_SIZE \
- ((1020 - 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 ()
-{
- allocating_for_lisp = 1;
- symbol_block = (struct symbol_block *) malloc (sizeof (struct symbol_block));
- allocating_for_lisp = 0;
- symbol_block->next = 0;
- bzero ((char *) 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.")
- (name)
- Lisp_Object name;
-{
- register Lisp_Object val;
- register struct Lisp_Symbol *p;
-
- CHECK_STRING (name, 0);
-
- if (symbol_free_list)
- {
- XSETSYMBOL (val, symbol_free_list);
- symbol_free_list = *(struct Lisp_Symbol **)&symbol_free_list->value;
- }
- else
- {
- if (symbol_block_index == SYMBOL_BLOCK_SIZE)
- {
- struct symbol_block *new;
- allocating_for_lisp = 1;
- new = (struct symbol_block *) xmalloc (sizeof (struct symbol_block));
- allocating_for_lisp = 0;
- VALIDATE_LISP_STORAGE (new, sizeof *new);
- new->next = symbol_block;
- symbol_block = new;
- symbol_block_index = 0;
- }
- XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index++]);
- }
- p = XSYMBOL (val);
- p->name = XSTRING (name);
- p->obarray = Qnil;
- p->plist = Qnil;
- p->value = Qunbound;
- p->function = Qunbound;
- p->next = 0;
- consing_since_gc += sizeof (struct Lisp_Symbol);
- symbols_consed++;
- return val;
-}
-
-/* Allocation of markers and other objects that share that structure.
- Works like allocation of conses. */
-
-#define MARKER_BLOCK_SIZE \
- ((1020 - sizeof (struct marker_block *)) / sizeof (union Lisp_Misc))
-
-struct marker_block
- {
- struct marker_block *next;
- union Lisp_Misc markers[MARKER_BLOCK_SIZE];
- };
-
-struct marker_block *marker_block;
-int marker_block_index;
-
-union Lisp_Misc *marker_free_list;
-
-void
-init_marker ()
-{
- allocating_for_lisp = 1;
- marker_block = (struct marker_block *) malloc (sizeof (struct marker_block));
- allocating_for_lisp = 0;
- marker_block->next = 0;
- bzero ((char *) marker_block->markers, sizeof marker_block->markers);
- marker_block_index = 0;
- marker_free_list = 0;
-}
-
-/* Return a newly allocated Lisp_Misc object, with no substructure. */
-Lisp_Object
-allocate_misc ()
-{
- Lisp_Object val;
-
- if (marker_free_list)
- {
- XSETMISC (val, marker_free_list);
- marker_free_list = marker_free_list->u_free.chain;
- }
- else
- {
- if (marker_block_index == MARKER_BLOCK_SIZE)
- {
- struct marker_block *new;
- allocating_for_lisp = 1;
- new = (struct marker_block *) xmalloc (sizeof (struct marker_block));
- allocating_for_lisp = 0;
- VALIDATE_LISP_STORAGE (new, sizeof *new);
- new->next = marker_block;
- marker_block = new;
- marker_block_index = 0;
- }
- XSETMISC (val, &marker_block->markers[marker_block_index++]);
- }
- consing_since_gc += sizeof (union Lisp_Misc);
- misc_objects_consed++;
- return val;
-}
-
-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;
-
- val = allocate_misc ();
- XMISCTYPE (val) = Lisp_Misc_Marker;
- p = XMARKER (val);
- p->buffer = 0;
- p->bufpos = 0;
- p->chain = Qnil;
- p->insertion_type = 0;
- 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.
- 8188 is power of 2, minus 4 for malloc overhead. */
-#define STRING_BLOCK_SIZE (8188 - 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;
- EMACS_INT pos;
- };
-
-struct string_block
- {
- struct string_block *next, *prev;
- EMACS_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) + sizeof (struct Lisp_String) + PAD) \
- & ~(PAD - 1))
-#define PAD (sizeof (EMACS_INT))
-
-#if 0
-#define STRING_FULLSIZE(SIZE) \
-(((SIZE) + 2 * sizeof (EMACS_INT)) & ~(sizeof (EMACS_INT) - 1))
-#endif
-
-void
-init_strings ()
-{
- allocating_for_lisp = 1;
- current_string_block = (struct string_block *) malloc (sizeof (struct string_block));
- allocating_for_lisp = 0;
- 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;
-}
-
-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;
-
- CHECK_NATNUM (length, 0);
- CHECK_NUMBER (init, 1);
- val = make_uninit_string (XFASTINT (length));
- c = XINT (init);
- p = XSTRING (val)->data;
- end = p + XSTRING (val)->size;
- while (p != end)
- *p++ = c;
- *p = 0;
- return val;
-}
-
-DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0,
- "Return a newly created bitstring of length LENGTH, with INIT as each element.\n\
-Both LENGTH and INIT must be numbers. INIT matters only in whether it is t or nil.")
- (length, init)
- Lisp_Object length, init;
-{
- register Lisp_Object val;
- struct Lisp_Bool_Vector *p;
- int real_init, i;
- int length_in_chars, length_in_elts, bits_per_value;
-
- CHECK_NATNUM (length, 0);
-
- bits_per_value = sizeof (EMACS_INT) * BITS_PER_CHAR;
-
- length_in_elts = (XFASTINT (length) + bits_per_value - 1) / bits_per_value;
- length_in_chars = length_in_elts * sizeof (EMACS_INT);
-
- val = Fmake_vector (make_number (length_in_elts), Qnil);
- p = XBOOL_VECTOR (val);
- /* Get rid of any bits that would cause confusion. */
- p->vector_size = 0;
- XSETBOOL_VECTOR (val, p);
- p->size = XFASTINT (length);
-
- real_init = (NILP (init) ? 0 : -1);
- for (i = 0; i < length_in_chars ; i++)
- p->data[i] = real_init;
-
- return val;
-}
-
-Lisp_Object
-make_string (contents, length)
- char *contents;
- int length;
-{
- register Lisp_Object val;
- val = make_uninit_string (length);
- bcopy (contents, XSTRING (val)->data, length);
- return val;
-}
-
-Lisp_Object
-build_string (str)
- char *str;
-{
- return make_string (str, strlen (str));
-}
-
-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 */
- {
- XSETSTRING (val,
- ((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;
- allocating_for_lisp = 1;
- new = (struct string_block *) xmalloc (sizeof (struct string_block_head) + fullsize);
- allocating_for_lisp = 0;
- 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;
- XSETSTRING (val,
- ((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;
- allocating_for_lisp = 1;
- new = (struct string_block *) xmalloc (sizeof (struct string_block));
- allocating_for_lisp = 0;
- 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;
- XSETSTRING (val,
- (struct Lisp_String *) current_string_block->chars);
- }
-
- string_chars_consed += fullsize;
- XSTRING (val)->size = length;
- XSTRING (val)->data[length] = 0;
- INITIALIZE_INTERVAL (XSTRING (val), NULL_INTERVAL);
-
- return val;
-}
-
-/* Return a newly created vector or string with specified arguments as
- elements. If all the arguments are characters that can fit
- in a string of events, make a string; otherwise, make a vector.
-
- Any number of arguments, even zero arguments, are allowed. */
-
-Lisp_Object
-make_event_array (nargs, args)
- register int nargs;
- Lisp_Object *args;
-{
- int i;
-
- for (i = 0; i < nargs; i++)
- /* The things that fit in a string
- are characters that are in 0...127,
- after discarding the meta bit and all the bits above it. */
- if (!INTEGERP (args[i])
- || (XUINT (args[i]) & ~(-CHAR_META)) >= 0200)
- return Fvector (nargs, args);
-
- /* Since the loop exited, we know that all the things in it are
- characters, so we can make a string. */
- {
- Lisp_Object result;
-
- result = Fmake_string (nargs, make_number (0));
- for (i = 0; i < nargs; i++)
- {
- XSTRING (result)->data[i] = XINT (args[i]);
- /* Move the meta bit to the right place for a string char. */
- if (XINT (args[i]) & CHAR_META)
- XSTRING (result)->data[i] |= 0x80;
- }
-
- return result;
- }
-}
-
-/* Pure storage management. */
-
-/* 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 (EMACS_INT) + INTERVAL_PTR_SIZE + length + 1;
-
- if (pureptr + size > PURESIZE)
- error ("Pure Lisp storage exhausted");
- XSETSTRING (new, PUREBEG + pureptr);
- XSTRING (new)->size = length;
- bcopy (data, XSTRING (new)->data, length);
- XSTRING (new)->data[length] = 0;
-
- /* We must give strings in pure storage some kind of interval. So we
- give them a null one. */
-#if defined (USE_TEXT_PROPERTIES)
- XSTRING (new)->intervals = NULL_INTERVAL;
-#endif
- pureptr += (size + sizeof (EMACS_INT) - 1)
- / sizeof (EMACS_INT) * sizeof (EMACS_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");
- XSETCONS (new, PUREBEG + pureptr);
- pureptr += sizeof (struct Lisp_Cons);
- XCONS (new)->car = Fpurecopy (car);
- XCONS (new)->cdr = Fpurecopy (cdr);
- return new;
-}
-
-#ifdef LISP_FLOAT_TYPE
-
-Lisp_Object
-make_pure_float (num)
- double num;
-{
- register Lisp_Object new;
-
- /* Make sure that PUREBEG + pureptr is aligned on at least a sizeof
- (double) boundary. Some architectures (like the sparc) require
- this, and I suspect that floats are rare enough that it's no
- tragedy for those that do. */
- {
- int alignment;
- char *p = PUREBEG + pureptr;
-
-#ifdef __GNUC__
-#if __GNUC__ >= 2
- alignment = __alignof (struct Lisp_Float);
-#else
- alignment = sizeof (struct Lisp_Float);
-#endif
-#else
- alignment = sizeof (struct Lisp_Float);
-#endif
- p = (char *) (((unsigned long) p + alignment - 1) & - alignment);
- pureptr = p - PUREBEG;
- }
-
- if (pureptr + sizeof (struct Lisp_Float) > PURESIZE)
- error ("Pure Lisp storage exhausted");
- XSETFLOAT (new, PUREBEG + pureptr);
- pureptr += sizeof (struct Lisp_Float);
- XFLOAT (new)->data = num;
- XSETFASTINT (XFLOAT (new)->type, 0); /* bug chasing -wsr */
- return new;
-}
-
-#endif /* LISP_FLOAT_TYPE */
-
-Lisp_Object
-make_pure_vector (len)
- EMACS_INT len;
-{
- register Lisp_Object new;
- register EMACS_INT size = sizeof (struct Lisp_Vector) + (len - 1) * sizeof (Lisp_Object);
-
- if (pureptr + size > PURESIZE)
- error ("Pure Lisp storage exhausted");
-
- XSETVECTOR (new, 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;
-{
- if (NILP (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;
-
- if (CONSP (obj))
- return pure_cons (XCONS (obj)->car, XCONS (obj)->cdr);
-#ifdef LISP_FLOAT_TYPE
- else if (FLOATP (obj))
- return make_pure_float (XFLOAT (obj)->data);
-#endif /* LISP_FLOAT_TYPE */
- else if (STRINGP (obj))
- return make_pure_string (XSTRING (obj)->data, XSTRING (obj)->size);
- else if (COMPILEDP (obj) || VECTORP (obj))
- {
- register struct Lisp_Vector *vec;
- register int i, size;
-
- size = XVECTOR (obj)->size;
- if (size & PSEUDOVECTOR_FLAG)
- size &= PSEUDOVECTOR_SIZE_MASK;
- vec = XVECTOR (make_pure_vector ((EMACS_INT) size));
- for (i = 0; i < size; i++)
- vec->contents[i] = Fpurecopy (XVECTOR (obj)->contents[i]);
- if (COMPILEDP (obj))
- XSETCOMPILED (obj, vec);
- else
- XSETVECTOR (obj, vec);
- return obj;
- }
- else if (MARKERP (obj))
- error ("Attempt to copy a marker to pure storage");
- else
- return obj;
-}
-
-/* Recording what needs to be marked for gc. */
-
-struct gcpro *gcprolist;
-
-#define NSTATICS 768
-
-Lisp_Object *staticvec[NSTATICS] = {0};
-
-int staticidx = 0;
-
-/* 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 */
- };
-
-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;
- };
-
-/* Garbage collection! */
-
-int total_conses, total_markers, total_symbols, total_string_size, total_vector_size;
-int total_free_conses, total_free_markers, total_free_symbols;
-#ifdef LISP_FLOAT_TYPE
-int total_free_floats, total_floats;
-#endif /* LISP_FLOAT_TYPE */
-
-/* Temporarily prevent garbage collection. */
-
-int
-inhibit_garbage_collection ()
-{
- int count = specpdl_ptr - specpdl;
- Lisp_Object number;
- int nbits = min (VALBITS, BITS_PER_INT);
-
- XSETINT (number, ((EMACS_INT) 1 << (nbits - 1)) - 1);
-
- specbind (Qgc_cons_threshold, number);
-
- return count;
-}
-
-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\
- (USED-FLOATS . FREE-FLOATS) (USED-INTERVALS . FREE-INTERVALS))\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_glyphs;
- int omessage_length = echo_area_glyphs_length;
- char stack_top_variable;
- register int i;
-
- /* In case user calls debug_print during GC,
- don't let that cause a recursive GC. */
- consing_since_gc = 0;
-
- /* Save a copy of the contents of the stack, for debugging. */
-#if MAX_SAVE_STACK > 0
- if (NILP (Vpurify_flag))
- {
- i = &stack_top_variable - stack_bottom;
- if (i < 0) i = -i;
- if (i < MAX_SAVE_STACK)
- {
- if (stack_copy == 0)
- stack_copy = (char *) xmalloc (stack_copy_size = i);
- else if (stack_copy_size < i)
- stack_copy = (char *) xrealloc (stack_copy, (stack_copy_size = i));
- if (stack_copy)
- {
- if ((EMACS_INT) (&stack_top_variable - stack_bottom) > 0)
- bcopy (stack_bottom, stack_copy, i);
- else
- bcopy (&stack_top_variable, stack_copy, i);
- }
- }
- }
-#endif /* MAX_SAVE_STACK > 0 */
-
- if (garbage_collection_messages)
- message1_nolog ("Garbage collecting...");
-
- /* Don't keep command history around forever. */
- if (NUMBERP (Vhistory_length) && XINT (Vhistory_length) > 0)
- {
- tem = Fnthcdr (Vhistory_length, Vcommand_history);
- if (CONSP (tem))
- XCONS (tem)->cdr = Qnil;
- }
-
- /* Likewise for undo information. */
- {
- register struct buffer *nextb = all_buffers;
-
- 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_limit,
- undo_strong_limit);
- nextb = nextb->next;
- }
- }
-
- 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]);
- }
- }
- mark_kboards ();
-
- 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;
- if (gc_cons_threshold < 10000)
- gc_cons_threshold = 10000;
-
- if (garbage_collection_messages)
- {
- if (omessage || minibuf_level > 0)
- message2_nolog (omessage, omessage_length);
- else
- message1_nolog ("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),
- Fcons (Fcons
-#ifdef LISP_FLOAT_TYPE
- (make_number (total_floats),
- make_number (total_free_floats)),
-#else /* not LISP_FLOAT_TYPE */
- (make_number (0), make_number (0)),
-#endif /* not LISP_FLOAT_TYPE */
- Fcons (Fcons
-#ifdef USE_TEXT_PROPERTIES
- (make_number (total_intervals),
- make_number (total_free_intervals)),
-#else /* not USE_TEXT_PROPERTIES */
- (make_number (0), make_number (0)),
-#endif /* not USE_TEXT_PROPERTIES */
- 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++)
- if (sblk->markers[i].u_marker.type == Lisp_Misc_Marker)
- XUNMARK (sblk->markers[i].u_marker.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 referencing 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. */
-
-#define LAST_MARKED_SIZE 500
-Lisp_Object *last_marked[LAST_MARKED_SIZE];
-int last_marked_index;
-
-static void
-mark_object (argptr)
- Lisp_Object *argptr;
-{
- Lisp_Object *objptr = argptr;
- register Lisp_Object obj;
-
- loop:
- obj = *objptr;
- loop2:
- XUNMARK (obj);
-
- if ((PNTR_COMPARISON_TYPE) XPNTR (obj) < (PNTR_COMPARISON_TYPE) ((char *) pure + PURESIZE)
- && (PNTR_COMPARISON_TYPE) XPNTR (obj) >= (PNTR_COMPARISON_TYPE) pure)
- return;
-
- last_marked[last_marked_index++] = objptr;
- if (last_marked_index == LAST_MARKED_SIZE)
- last_marked_index = 0;
-
- switch (SWITCH_ENUM_CAST (XGCTYPE (obj)))
- {
- case Lisp_String:
- {
- register struct Lisp_String *ptr = XSTRING (obj);
-
- MARK_INTERVAL_TREE (ptr->intervals);
- 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.
- If the address includes MARKBIT, put that bit elsewhere
- when we store OBJPTR into the size field. */
-
- if (XMARKBIT (*objptr))
- {
- XSETFASTINT (*objptr, ptr->size);
- XMARK (*objptr);
- }
- else
- XSETFASTINT (*objptr, ptr->size);
-
- if ((EMACS_INT) objptr & DONT_COPY_FLAG)
- abort ();
- ptr->size = (EMACS_INT) objptr;
- if (ptr->size & MARKBIT)
- ptr->size ^= MARKBIT | DONT_COPY_FLAG;
- }
- }
- break;
-
- case Lisp_Vectorlike:
- if (GC_BUFFERP (obj))
- {
- if (!XMARKBIT (XBUFFER (obj)->name))
- mark_buffer (obj);
- }
- else if (GC_SUBRP (obj))
- break;
- else if (GC_COMPILEDP (obj))
- /* We could treat this just like a vector, but it is better
- to save the COMPILED_CONSTANTS element for last and avoid recursion
- there. */
- {
- register struct Lisp_Vector *ptr = XVECTOR (obj);
- register EMACS_INT size = ptr->size;
- /* See comment above under Lisp_Vector. */
- struct Lisp_Vector *volatile ptr1 = ptr;
- register int i;
-
- if (size & ARRAY_MARK_FLAG)
- break; /* Already marked */
- ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */
- size &= PSEUDOVECTOR_SIZE_MASK;
- for (i = 0; i < size; i++) /* and then mark its elements */
- {
- if (i != COMPILED_CONSTANTS)
- mark_object (&ptr1->contents[i]);
- }
- /* This cast should be unnecessary, but some Mips compiler complains
- (MIPS-ABI + SysVR4, DC/OSx, etc). */
- objptr = (Lisp_Object *) &ptr1->contents[COMPILED_CONSTANTS];
- goto loop;
- }
- else if (GC_FRAMEP (obj))
- {
- /* See comment above under Lisp_Vector for why this is volatile. */
- register struct frame *volatile ptr = XFRAME (obj);
- register EMACS_INT size = ptr->size;
-
- if (size & ARRAY_MARK_FLAG) break; /* Already marked */
- ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */
-
- mark_object (&ptr->name);
- mark_object (&ptr->icon_name);
- mark_object (&ptr->title);
- mark_object (&ptr->focus_frame);
- mark_object (&ptr->selected_window);
- mark_object (&ptr->minibuffer_window);
- mark_object (&ptr->param_alist);
- mark_object (&ptr->scroll_bars);
- mark_object (&ptr->condemned_scroll_bars);
- mark_object (&ptr->menu_bar_items);
- mark_object (&ptr->face_alist);
- mark_object (&ptr->menu_bar_vector);
- mark_object (&ptr->buffer_predicate);
- }
- else if (GC_BOOL_VECTOR_P (obj))
- {
- register struct Lisp_Vector *ptr = XVECTOR (obj);
-
- if (ptr->size & ARRAY_MARK_FLAG)
- break; /* Already marked */
- ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */
- }
- else
- {
- register struct Lisp_Vector *ptr = XVECTOR (obj);
- register EMACS_INT size = ptr->size;
- /* The reason we use ptr1 is to avoid an apparent hardware bug
- that happens occasionally on the FSF's HP 300s.
- The bug is that a2 gets clobbered by recursive calls to mark_object.
- The clobberage seems to happen during function entry,
- perhaps in the moveml instruction.
- Yes, this is a crock, but we have to do it. */
- struct Lisp_Vector *volatile ptr1 = ptr;
- register int i;
-
- if (size & ARRAY_MARK_FLAG) break; /* Already marked */
- ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */
- if (size & PSEUDOVECTOR_FLAG)
- size &= PSEUDOVECTOR_SIZE_MASK;
- for (i = 0; i < size; i++) /* and then mark its elements */
- mark_object (&ptr1->contents[i]);
- }
- break;
-
- case Lisp_Symbol:
- {
- /* See comment above under Lisp_Vector for why this is volatile. */
- register struct Lisp_Symbol *volatile ptr = XSYMBOL (obj);
- struct Lisp_Symbol *ptrx;
-
- if (XMARKBIT (ptr->plist)) break;
- XMARK (ptr->plist);
- mark_object ((Lisp_Object *) &ptr->value);
- mark_object (&ptr->function);
- mark_object (&ptr->plist);
- XSETTYPE (*(Lisp_Object *) &ptr->name, Lisp_String);
- mark_object (&ptr->name);
- ptr = ptr->next;
- if (ptr)
- {
- /* For the benefit of the last_marked log. */
- objptr = (Lisp_Object *)&XSYMBOL (obj)->next;
- ptrx = ptr; /* Use of ptrx avoids compiler bug on Sun */
- XSETSYMBOL (obj, ptrx);
- /* We can't goto loop here because *objptr doesn't contain an
- actual Lisp_Object with valid datatype field. */
- goto loop2;
- }
- }
- break;
-
- case Lisp_Misc:
- switch (XMISCTYPE (obj))
- {
- case Lisp_Misc_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 freed by gc. */
- break;
-
- case Lisp_Misc_Buffer_Local_Value:
- case Lisp_Misc_Some_Buffer_Local_Value:
- {
- register struct Lisp_Buffer_Local_Value *ptr
- = XBUFFER_LOCAL_VALUE (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;
- goto loop;
- }
- mark_object (&ptr->car);
- /* See comment above under Lisp_Vector for why not use ptr here. */
- objptr = &XBUFFER_LOCAL_VALUE (obj)->cdr;
- goto loop;
- }
-
- case Lisp_Misc_Intfwd:
- case Lisp_Misc_Boolfwd:
- case Lisp_Misc_Objfwd:
- case Lisp_Misc_Buffer_Objfwd:
- case Lisp_Misc_Kboard_Objfwd:
- /* 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;
-
- case Lisp_Misc_Overlay:
- {
- struct Lisp_Overlay *ptr = XOVERLAY (obj);
- if (!XMARKBIT (ptr->plist))
- {
- XMARK (ptr->plist);
- mark_object (&ptr->start);
- mark_object (&ptr->end);
- objptr = &ptr->plist;
- goto loop;
- }
- }
- break;
-
- default:
- abort ();
- }
- break;
-
- case Lisp_Cons:
- {
- 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;
- goto loop;
- }
- mark_object (&ptr->car);
- /* See comment above under Lisp_Vector for why not use ptr here. */
- objptr = &XCONS (obj)->cdr;
- goto loop;
- }
-
-#ifdef LISP_FLOAT_TYPE
- case Lisp_Float:
- XMARK (XFLOAT (obj)->type);
- break;
-#endif /* LISP_FLOAT_TYPE */
-
- case Lisp_Int:
- break;
-
- default:
- abort ();
- }
-}
-
-/* Mark the pointers in a buffer structure. */
-
-static void
-mark_buffer (buf)
- Lisp_Object buf;
-{
- register struct buffer *buffer = XBUFFER (buf);
- register Lisp_Object *ptr;
- Lisp_Object base_buffer;
-
- /* This is the buffer's markbit */
- mark_object (&buffer->name);
- XMARK (buffer->name);
-
- MARK_INTERVAL_TREE (BUF_INTERVALS (buffer));
-
-#if 0
- mark_object (buffer->syntax_table);
-
- /* Mark the various string-pointers in the buffer object.
- Since the strings may be relocated, we must mark them
- in their actual slots. So gc_sweep must convert each slot
- back to an ordinary C pointer. */
- XSETSTRING (*(Lisp_Object *)&buffer->upcase_table, buffer->upcase_table);
- mark_object ((Lisp_Object *)&buffer->upcase_table);
- XSETSTRING (*(Lisp_Object *)&buffer->downcase_table, buffer->downcase_table);
- mark_object ((Lisp_Object *)&buffer->downcase_table);
-
- XSETSTRING (*(Lisp_Object *)&buffer->sort_table, buffer->sort_table);
- mark_object ((Lisp_Object *)&buffer->sort_table);
- XSETSTRING (*(Lisp_Object *)&buffer->folding_sort_table, buffer->folding_sort_table);
- mark_object ((Lisp_Object *)&buffer->folding_sort_table);
-#endif
-
- for (ptr = &buffer->name + 1;
- (char *)ptr < (char *)buffer + sizeof (struct buffer);
- ptr++)
- mark_object (ptr);
-
- /* If this is an indirect buffer, mark its base buffer. */
- if (buffer->base_buffer && !XMARKBIT (buffer->base_buffer->name))
- {
- XSETBUFFER (base_buffer, buffer->base_buffer);
- mark_buffer (base_buffer);
- }
-}
-
-
-/* Mark the pointers in the kboard objects. */
-
-static void
-mark_kboards ()
-{
- KBOARD *kb;
- Lisp_Object *p;
- for (kb = all_kboards; kb; kb = kb->next_kboard)
- {
- if (kb->kbd_macro_buffer)
- for (p = kb->kbd_macro_buffer; p < kb->kbd_macro_ptr; p++)
- mark_object (p);
- mark_object (&kb->Vprefix_arg);
- mark_object (&kb->kbd_queue);
- mark_object (&kb->Vlast_kbd_macro);
- mark_object (&kb->Vsystem_key_alist);
- mark_object (&kb->system_key_syms);
- }
-}
-
-/* Sweep: 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))
- {
- num_free++;
- *(struct Lisp_Cons **)&cblk->conses[i].car = cons_free_list;
- 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;
- }
-
-#ifdef LISP_FLOAT_TYPE
- /* Put all unmarked floats on free list */
- {
- register struct float_block *fblk;
- register int lim = float_block_index;
- register int num_free = 0, num_used = 0;
-
- float_free_list = 0;
-
- for (fblk = float_block; fblk; fblk = fblk->next)
- {
- register int i;
- for (i = 0; i < lim; i++)
- if (!XMARKBIT (fblk->floats[i].type))
- {
- num_free++;
- *(struct Lisp_Float **)&fblk->floats[i].type = float_free_list;
- float_free_list = &fblk->floats[i];
- }
- else
- {
- num_used++;
- XUNMARK (fblk->floats[i].type);
- }
- lim = FLOAT_BLOCK_SIZE;
- }
- total_floats = num_used;
- total_free_floats = num_free;
- }
-#endif /* LISP_FLOAT_TYPE */
-
-#ifdef USE_TEXT_PROPERTIES
- /* Put all unmarked intervals on free list */
- {
- register struct interval_block *iblk;
- register int lim = interval_block_index;
- register int num_free = 0, num_used = 0;
-
- interval_free_list = 0;
-
- for (iblk = interval_block; iblk; iblk = iblk->next)
- {
- register int i;
-
- for (i = 0; i < lim; i++)
- {
- if (! XMARKBIT (iblk->intervals[i].plist))
- {
- iblk->intervals[i].parent = interval_free_list;
- interval_free_list = &iblk->intervals[i];
- num_free++;
- }
- else
- {
- num_used++;
- XUNMARK (iblk->intervals[i].plist);
- }
- }
- lim = INTERVAL_BLOCK_SIZE;
- }
- total_intervals = num_used;
- total_free_intervals = num_free;
- }
-#endif /* USE_TEXT_PROPERTIES */
-
- /* 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))
- {
- *(struct Lisp_Symbol **)&sblk->symbols[i].value = 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.
- Unchain each one first from the buffer it points into,
- but only if it's a real marker. */
- {
- register struct marker_block *mblk;
- 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;
- EMACS_INT already_free = -1;
-
- for (i = 0; i < lim; i++)
- {
- Lisp_Object *markword;
- switch (mblk->markers[i].u_marker.type)
- {
- case Lisp_Misc_Marker:
- markword = &mblk->markers[i].u_marker.chain;
- break;
- case Lisp_Misc_Buffer_Local_Value:
- case Lisp_Misc_Some_Buffer_Local_Value:
- markword = &mblk->markers[i].u_buffer_local_value.car;
- break;
- case Lisp_Misc_Overlay:
- markword = &mblk->markers[i].u_overlay.plist;
- break;
- case Lisp_Misc_Free:
- /* If the object was already free, keep it
- on the free list. */
- markword = &already_free;
- break;
- default:
- markword = 0;
- break;
- }
- if (markword && !XMARKBIT (*markword))
- {
- Lisp_Object tem;
- if (mblk->markers[i].u_marker.type == Lisp_Misc_Marker)
- {
- /* tem1 avoids Sun compiler bug */
- struct Lisp_Marker *tem1 = &mblk->markers[i].u_marker;
- XSETMARKER (tem, tem1);
- unchain_marker (tem);
- }
- /* Set the type of the freed object to Lisp_Misc_Free.
- We could leave the type alone, since nobody checks it,
- but this might catch bugs faster. */
- mblk->markers[i].u_marker.type = Lisp_Misc_Free;
- mblk->markers[i].u_free.chain = marker_free_list;
- marker_free_list = &mblk->markers[i];
- num_free++;
- }
- else
- {
- num_used++;
- if (markword)
- XUNMARK (*markword);
- }
- }
- 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;
- xfree (buffer);
- buffer = next;
- }
- else
- {
- XUNMARK (buffer->name);
- UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer));
-
-#if 0
- /* Each `struct Lisp_String *' was turned into a Lisp_Object
- for purposes of marking and relocation.
- Turn them back into C pointers now. */
- buffer->upcase_table
- = XSTRING (*(Lisp_Object *)&buffer->upcase_table);
- buffer->downcase_table
- = XSTRING (*(Lisp_Object *)&buffer->downcase_table);
- buffer->sort_table
- = XSTRING (*(Lisp_Object *)&buffer->sort_table);
- buffer->folding_sort_table
- = XSTRING (*(Lisp_Object *)&buffer->folding_sort_table);
-#endif
-
- 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;
- xfree (vector);
- vector = next;
- }
- else
- {
- vector->size &= ~ARRAY_MARK_FLAG;
- if (vector->size & PSEUDOVECTOR_FLAG)
- total_vector_size += (PSEUDOVECTOR_SIZE_MASK & vector->size);
- else
- 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;
- struct Lisp_String *s;
-
- while (sb)
- {
- s = (struct Lisp_String *) &sb->chars[0];
- if (s->size & ARRAY_MARK_FLAG)
- {
- ((struct Lisp_String *)(&sb->chars[0]))->size
- &= ~ARRAY_MARK_FLAG & ~MARKBIT;
- UNMARK_BALANCE_INTERVALS (s->intervals);
- total_string_size += ((struct Lisp_String *)(&sb->chars[0]))->size;
- prev = sb, sb = sb->next;
- }
- else
- {
- if (prev)
- prev->next = sb->next;
- else
- large_string_blocks = sb->next;
- next = sb->next;
- xfree (sb);
- sb = next;
- }
- }
- }
-}
-
-/* Compactify strings, relocate references, and free empty string blocks. */
-
-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 EMACS_INT size = nextstr->size;
-
- /* NEXTSTR is the old address of the next string.
- Just skip it if it isn't marked. */
- if (((EMACS_UINT) size & ~DONT_COPY_FLAG) > 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 (((EMACS_UINT) size & ~DONT_COPY_FLAG) > STRING_BLOCK_SIZE)
- {
- if (size & DONT_COPY_FLAG)
- size ^= MARKBIT | DONT_COPY_FLAG;
- size = *(EMACS_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 (EMACS_INT)
- + INTERVAL_PTR_SIZE);
-
- /* 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 (((EMACS_UINT) size & ~DONT_COPY_FLAG) > STRING_BLOCK_SIZE)
- {
- register Lisp_Object *objptr;
- if (size & DONT_COPY_FLAG)
- size ^= MARKBIT | DONT_COPY_FLAG;
- objptr = (Lisp_Object *)size;
-
- size = XFASTINT (*objptr) & ~MARKBIT;
- if (XMARKBIT (*objptr))
- {
- XSETSTRING (*objptr, newaddr);
- XMARK (*objptr);
- }
- else
- XSETSTRING (*objptr, newaddr);
- }
- /* Store the actual size in the size field. */
- newaddr->size = size;
-
-#ifdef USE_TEXT_PROPERTIES
- /* Now that the string has been relocated, rebalance its
- interval tree, and update the tree's parent pointer. */
- if (! NULL_INTERVAL_P (newaddr->intervals))
- {
- UNMARK_BALANCE_INTERVALS (newaddr->intervals);
- XSETSTRING (* (Lisp_Object *) &newaddr->intervals->parent,
- newaddr);
- }
-#endif /* USE_TEXT_PROPERTIES */
- }
- 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;
- xfree (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;
- xfree (to_sb);
- }
- else
- from_sb = to_sb;
- }
-}
-
-/* Debugging aids. */
-
-DEFUN ("memory-limit", Fmemory_limit, Smemory_limit, 0, 0, 0,
- "Return the address of the last byte Emacs has allocated, divided by 1024.\n\
-This may be helpful in debugging Emacs's memory usage.\n\
-We divide the value by 1024 to make sure it fits in a Lisp integer.")
- ()
-{
- Lisp_Object end;
-
- XSETINT (end, (EMACS_INT) sbrk (0) / 1024);
-
- return end;
-}
-
-DEFUN ("memory-use-counts", Fmemory_use_counts, Smemory_use_counts, 0, 0, 0,
- "Return a list of counters that measure how much consing there has been.\n\
-Each of these counters increments for a certain kind of object.\n\
-The counters wrap around from the largest positive integer to zero.\n\
-Garbage collection does not decrease them.\n\
-The elements of the value are as follows:\n\
- (CONSES FLOATS VECTOR-CELLS SYMBOLS STRING-CHARS MISCS INTERVALS)\n\
-All are in units of 1 = one object consed\n\
-except for VECTOR-CELLS and STRING-CHARS, which count the total length of\n\
-objects consed.\n\
-MISCS include overlays, markers, and some internal types.\n\
-Frames, windows, buffers, and subprocesses count as vectors\n\
- (but the contents of a buffer's text do not count here).")
- ()
-{
- Lisp_Object lisp_cons_cells_consed;
- Lisp_Object lisp_floats_consed;
- Lisp_Object lisp_vector_cells_consed;
- Lisp_Object lisp_symbols_consed;
- Lisp_Object lisp_string_chars_consed;
- Lisp_Object lisp_misc_objects_consed;
- Lisp_Object lisp_intervals_consed;
-
- XSETINT (lisp_cons_cells_consed,
- cons_cells_consed & ~(((EMACS_INT) 1) << (VALBITS - 1)));
- XSETINT (lisp_floats_consed,
- floats_consed & ~(((EMACS_INT) 1) << (VALBITS - 1)));
- XSETINT (lisp_vector_cells_consed,
- vector_cells_consed & ~(((EMACS_INT) 1) << (VALBITS - 1)));
- XSETINT (lisp_symbols_consed,
- symbols_consed & ~(((EMACS_INT) 1) << (VALBITS - 1)));
- XSETINT (lisp_string_chars_consed,
- string_chars_consed & ~(((EMACS_INT) 1) << (VALBITS - 1)));
- XSETINT (lisp_misc_objects_consed,
- misc_objects_consed & ~(((EMACS_INT) 1) << (VALBITS - 1)));
- XSETINT (lisp_intervals_consed,
- intervals_consed & ~(((EMACS_INT) 1) << (VALBITS - 1)));
-
- return Fcons (lisp_cons_cells_consed,
- Fcons (lisp_floats_consed,
- Fcons (lisp_vector_cells_consed,
- Fcons (lisp_symbols_consed,
- Fcons (lisp_string_chars_consed,
- Fcons (lisp_misc_objects_consed,
- Fcons (lisp_intervals_consed,
- Qnil)))))));
-}
-
-/* Initialization */
-
-init_alloc_once ()
-{
- /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */
- pureptr = 0;
-#ifdef HAVE_SHM
- pure_size = PURESIZE;
-#endif
- all_vectors = 0;
- ignore_warnings = 1;
- init_strings ();
- init_cons ();
- init_symbol ();
- init_marker ();
-#ifdef LISP_FLOAT_TYPE
- init_float ();
-#endif /* LISP_FLOAT_TYPE */
- INIT_INTERVALS;
-
-#ifdef REL_ALLOC
- malloc_hysteresis = 32;
-#else
- malloc_hysteresis = 0;
-#endif
-
- spare_memory = (char *) malloc (SPARE_MEMORY);
-
- ignore_warnings = 0;
- gcprolist = 0;
- staticidx = 0;
- consing_since_gc = 0;
- gc_cons_threshold = 100000 * sizeof (Lisp_Object);
-#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 ()
-{
- DEFVAR_INT ("gc-cons-threshold", &gc_cons_threshold,
- "*Number of bytes of consing between garbage collections.\n\
-Garbage collection can happen automatically once this many bytes have been\n\
-allocated since the last garbage collection. All data types count.\n\n\
-Garbage collection happens automatically only when `eval' is called.\n\n\
-By binding this temporarily to a large number, you can effectively\n\
-prevent garbage collection during a part of the program.");
-
- DEFVAR_INT ("pure-bytes-used", &pureptr,
- "Number of bytes of sharable Lisp data allocated so far.");
-
- DEFVAR_INT ("cons-cells-consed", &cons_cells_consed,
- "Number of cons cells that have been consed so far.");
-
- DEFVAR_INT ("floats-consed", &floats_consed,
- "Number of floats that have been consed so far.");
-
- DEFVAR_INT ("vector-cells-consed", &vector_cells_consed,
- "Number of vector cells that have been consed so far.");
-
- DEFVAR_INT ("symbols-consed", &symbols_consed,
- "Number of symbols that have been consed so far.");
-
- DEFVAR_INT ("string-chars-consed", &string_chars_consed,
- "Number of string characters that have been consed so far.");
-
- DEFVAR_INT ("misc-objects-consed", &misc_objects_consed,
- "Number of miscellaneous objects that have been consed so far.");
-
- DEFVAR_INT ("intervals-consed", &intervals_consed,
- "Number of intervals that have been consed 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.\n\
-This means that certain objects should be allocated in shared (pure) space.");
-
- DEFVAR_INT ("undo-limit", &undo_limit,
- "Keep no more undo information once it exceeds this size.\n\
-This limit 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_limit = 20000;
-
- DEFVAR_INT ("undo-strong-limit", &undo_strong_limit,
- "Don't keep more than this much size of undo information.\n\
-A command which pushes past this size is itself forgotten.\n\
-This limit 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_strong_limit = 30000;
-
- DEFVAR_BOOL ("garbage-collection-messages", &garbage_collection_messages,
- "Non-nil means display messages at start and end of garbage collection.");
- garbage_collection_messages = 0;
-
- /* We build this in advance because if we wait until we need it, we might
- not be able to allocate the memory to hold it. */
- memory_signal_data
- = Fcons (Qerror, Fcons (build_string ("Memory exhausted--use M-x save-some-buffers RET"), Qnil));
- staticpro (&memory_signal_data);
-
- staticpro (&Qgc_cons_threshold);
- Qgc_cons_threshold = intern ("gc-cons-threshold");
-
- staticpro (&Qchar_table_extra_slots);
- Qchar_table_extra_slots = intern ("char-table-extra-slots");
-
- defsubr (&Scons);
- defsubr (&Slist);
- defsubr (&Svector);
- defsubr (&Smake_byte_code);
- defsubr (&Smake_list);
- defsubr (&Smake_vector);
- defsubr (&Smake_char_table);
- defsubr (&Smake_string);
- defsubr (&Smake_bool_vector);
- defsubr (&Smake_symbol);
- defsubr (&Smake_marker);
- defsubr (&Spurecopy);
- defsubr (&Sgarbage_collect);
- defsubr (&Smemory_limit);
- defsubr (&Smemory_use_counts);
-}
diff --git a/src/alloca.c b/src/alloca.c
deleted file mode 100644
index 8f98b73dbb9..00000000000
--- a/src/alloca.c
+++ /dev/null
@@ -1,504 +0,0 @@
-/* alloca.c -- allocate automatically reclaimed memory
- (Mostly) portable public-domain implementation -- D A Gwyn
-
- 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.
- J.Otto Tennant <jot@cray.com> contributed the Cray support.
-
- 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. */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef emacs
-#include "blockinput.h"
-#endif
-
-/* If compiling with GCC 2, this file's not needed. */
-#if !defined (__GNUC__) || __GNUC__ < 2
-
-/* If someone has defined alloca as a macro,
- there must be some other way alloca is supposed to work. */
-#ifndef alloca
-
-#ifdef emacs
-#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 */
-
-/* If your stack is a linked list of frames, you have to
- provide an "address metric" ADDRESS_FUNCTION macro. */
-
-#if defined (CRAY) && defined (CRAY_STACKSEG_END)
-long i00afunc ();
-#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
-#else
-#define ADDRESS_FUNCTION(arg) &(arg)
-#endif
-
-#if __STDC__
-typedef void *pointer;
-#else
-typedef char *pointer;
-#endif
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-/* Different portions of Emacs need to call different versions of
- malloc. The Emacs executable needs alloca to call xmalloc, because
- ordinary malloc isn't protected from input signals. On the other
- hand, the utilities in lib-src need alloca to call malloc; some of
- them are very simple, and don't have an xmalloc routine.
-
- Non-Emacs programs expect this to call use xmalloc.
-
- Callers below should use malloc. */
-
-#ifndef emacs
-#define malloc xmalloc
-#endif
-extern pointer malloc ();
-
-/* 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 ()
-{
- static char *addr = NULL; /* Address of first `dummy', once known. */
- auto char dummy; /* To get stack address. */
-
- if (addr == NULL)
- { /* Initial entry. */
- addr = ADDRESS_FUNCTION (dummy);
-
- find_stack_direction (); /* Recurse once. */
- }
- else
- {
- /* Second entry. */
- if (ADDRESS_FUNCTION (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;
-
-static header *last_alloca_header = NULL; /* -> last alloca header. */
-
-/* Return 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. */
-
-pointer
-alloca (size)
- unsigned size;
-{
- auto char probe; /* Probes stack depth: */
- register char *depth = ADDRESS_FUNCTION (probe);
-
-#if STACK_DIRECTION == 0
- if (STACK_DIR == 0) /* Unknown growth direction. */
- find_stack_direction ();
-#endif
-
- /* Reclaim garbage, defined as all alloca'd storage that
- was allocated from deeper in the stack than currently. */
-
- {
- register header *hp; /* Traverses linked list. */
-
-#ifdef emacs
- BLOCK_INPUT;
-#endif
-
- 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. */
-
-#ifdef emacs
- UNBLOCK_INPUT;
-#endif
- }
-
- if (size == 0)
- return NULL; /* No allocation required. */
-
- /* Allocate combined header + user data storage. */
-
- {
- register pointer new = malloc (sizeof (header) + size);
- /* Address of header. */
-
- if (new == 0)
- abort();
-
- ((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));
- }
-}
-
-#if defined (CRAY) && defined (CRAY_STACKSEG_END)
-
-#ifdef DEBUG_I00AFUNC
-#include <stdio.h>
-#endif
-
-#ifndef CRAY_STACK
-#define CRAY_STACK
-#ifndef CRAY2
-/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
-struct stack_control_header
- {
- long shgrow:32; /* Number of times stack has grown. */
- long shaseg:32; /* Size of increments to stack. */
- long shhwm:32; /* High water mark of stack. */
- long shsize:32; /* Current size of stack (all segments). */
- };
-
-/* The stack segment linkage control information occurs at
- the high-address end of a stack segment. (The stack
- grows from low addresses to high addresses.) The initial
- part of the stack segment linkage control information is
- 0200 (octal) words. This provides for register storage
- for the routine which overflows the stack. */
-
-struct stack_segment_linkage
- {
- long ss[0200]; /* 0200 overflow words. */
- long sssize:32; /* Number of words in this segment. */
- long ssbase:32; /* Offset to stack base. */
- long:32;
- long sspseg:32; /* Offset to linkage control of previous
- segment of stack. */
- long:32;
- long sstcpt:32; /* Pointer to task common address block. */
- long sscsnm; /* Private control structure number for
- microtasking. */
- long ssusr1; /* Reserved for user. */
- long ssusr2; /* Reserved for user. */
- long sstpid; /* Process ID for pid based multi-tasking. */
- long ssgvup; /* Pointer to multitasking thread giveup. */
- long sscray[7]; /* Reserved for Cray Research. */
- long ssa0;
- long ssa1;
- long ssa2;
- long ssa3;
- long ssa4;
- long ssa5;
- long ssa6;
- long ssa7;
- long sss0;
- long sss1;
- long sss2;
- long sss3;
- long sss4;
- long sss5;
- long sss6;
- long sss7;
- };
-
-#else /* CRAY2 */
-/* The following structure defines the vector of words
- returned by the STKSTAT library routine. */
-struct stk_stat
- {
- long now; /* Current total stack size. */
- long maxc; /* Amount of contiguous space which would
- be required to satisfy the maximum
- stack demand to date. */
- long high_water; /* Stack high-water mark. */
- long overflows; /* Number of stack overflow ($STKOFEN) calls. */
- long hits; /* Number of internal buffer hits. */
- long extends; /* Number of block extensions. */
- long stko_mallocs; /* Block allocations by $STKOFEN. */
- long underflows; /* Number of stack underflow calls ($STKRETN). */
- long stko_free; /* Number of deallocations by $STKRETN. */
- long stkm_free; /* Number of deallocations by $STKMRET. */
- long segments; /* Current number of stack segments. */
- long maxs; /* Maximum number of stack segments so far. */
- long pad_size; /* Stack pad size. */
- long current_address; /* Current stack segment address. */
- long current_size; /* Current stack segment size. This
- number is actually corrupted by STKSTAT to
- include the fifteen word trailer area. */
- long initial_address; /* Address of initial segment. */
- long initial_size; /* Size of initial segment. */
- };
-
-/* The following structure describes the data structure which trails
- any stack segment. I think that the description in 'asdef' is
- out of date. I only describe the parts that I am sure about. */
-
-struct stk_trailer
- {
- long this_address; /* Address of this block. */
- long this_size; /* Size of this block (does not include
- this trailer). */
- long unknown2;
- long unknown3;
- long link; /* Address of trailer block of previous
- segment. */
- long unknown5;
- long unknown6;
- long unknown7;
- long unknown8;
- long unknown9;
- long unknown10;
- long unknown11;
- long unknown12;
- long unknown13;
- long unknown14;
- };
-
-#endif /* CRAY2 */
-#endif /* not CRAY_STACK */
-
-#ifdef CRAY2
-/* Determine a "stack measure" for an arbitrary ADDRESS.
- I doubt that "lint" will like this much. */
-
-static long
-i00afunc (long *address)
-{
- struct stk_stat status;
- struct stk_trailer *trailer;
- long *block, size;
- long result = 0;
-
- /* We want to iterate through all of the segments. The first
- step is to get the stack status structure. We could do this
- more quickly and more directly, perhaps, by referencing the
- $LM00 common block, but I know that this works. */
-
- STKSTAT (&status);
-
- /* Set up the iteration. */
-
- trailer = (struct stk_trailer *) (status.current_address
- + status.current_size
- - 15);
-
- /* There must be at least one stack segment. Therefore it is
- a fatal error if "trailer" is null. */
-
- if (trailer == 0)
- abort ();
-
- /* Discard segments that do not contain our argument address. */
-
- while (trailer != 0)
- {
- block = (long *) trailer->this_address;
- size = trailer->this_size;
- if (block == 0 || size == 0)
- abort ();
- trailer = (struct stk_trailer *) trailer->link;
- if ((block <= address) && (address < (block + size)))
- break;
- }
-
- /* Set the result to the offset in this segment and add the sizes
- of all predecessor segments. */
-
- result = address - block;
-
- if (trailer == 0)
- {
- return result;
- }
-
- do
- {
- if (trailer->this_size <= 0)
- abort ();
- result += trailer->this_size;
- trailer = (struct stk_trailer *) trailer->link;
- }
- while (trailer != 0);
-
- /* We are done. Note that if you present a bogus address (one
- not in any segment), you will get a different number back, formed
- from subtracting the address of the first block. This is probably
- not what you want. */
-
- return (result);
-}
-
-#else /* not CRAY2 */
-/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
- Determine the number of the cell within the stack,
- given the address of the cell. The purpose of this
- routine is to linearize, in some sense, stack addresses
- for alloca. */
-
-static long
-i00afunc (long address)
-{
- long stkl = 0;
-
- long size, pseg, this_segment, stack;
- long result = 0;
-
- struct stack_segment_linkage *ssptr;
-
- /* Register B67 contains the address of the end of the
- current stack segment. If you (as a subprogram) store
- your registers on the stack and find that you are past
- the contents of B67, you have overflowed the segment.
-
- B67 also points to the stack segment linkage control
- area, which is what we are really interested in. */
-
- stkl = CRAY_STACKSEG_END ();
- ssptr = (struct stack_segment_linkage *) stkl;
-
- /* If one subtracts 'size' from the end of the segment,
- one has the address of the first word of the segment.
-
- If this is not the first segment, 'pseg' will be
- nonzero. */
-
- pseg = ssptr->sspseg;
- size = ssptr->sssize;
-
- this_segment = stkl - size;
-
- /* It is possible that calling this routine itself caused
- a stack overflow. Discard stack segments which do not
- contain the target address. */
-
- while (!(this_segment <= address && address <= stkl))
- {
-#ifdef DEBUG_I00AFUNC
- fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
-#endif
- if (pseg == 0)
- break;
- stkl = stkl - pseg;
- ssptr = (struct stack_segment_linkage *) stkl;
- size = ssptr->sssize;
- pseg = ssptr->sspseg;
- this_segment = stkl - size;
- }
-
- result = address - this_segment;
-
- /* If you subtract pseg from the current end of the stack,
- you get the address of the previous stack segment's end.
- This seems a little convoluted to me, but I'll bet you save
- a cycle somewhere. */
-
- while (pseg != 0)
- {
-#ifdef DEBUG_I00AFUNC
- fprintf (stderr, "%011o %011o\n", pseg, size);
-#endif
- stkl = stkl - pseg;
- ssptr = (struct stack_segment_linkage *) stkl;
- size = ssptr->sssize;
- pseg = ssptr->sspseg;
- result += size;
- }
- return (result);
-}
-
-#endif /* not CRAY2 */
-#endif /* CRAY */
-
-#endif /* no alloca */
-#endif /* not GCC version 2 */
diff --git a/src/alloca.s b/src/alloca.s
deleted file mode 100644
index 5277586a2ea..00000000000
--- a/src/alloca.s
+++ /dev/null
@@ -1,350 +0,0 @@
-/* `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 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 2, 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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
-#ifdef emacs
-#include <config.h>
-#else
-#include "config.h"
-#endif
-
-#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 /* ns16000 */
-#endif /* ns32000 */
-#endif /* WICAT */
-#endif /* m68000 */
-#endif /* m68k */
-#endif /* hp9000s300 */
-
-
-#ifdef hp9000s300
-#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 address
- 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:
-#ifdef MOTOROLA_DELTA
-/* slightly modified version of alloca to motorola sysV/68 pcc - based
- compiler.
- this compiler saves used registers relative to %sp instead of %fp.
- alright, just make new copy of saved register set whenever we allocate
- new space from stack..
- this is true at last until SVR3V7 . bug has reported to Motorola. */
- set MAXREG,10 # max no of registers to save (d2-d7, a2-a5)
- mov.l (%sp)+,%a1 # pop return addr from top of stack
- mov.l (%sp)+,%d0 # pop size in bytes from top of stack
- mov.l %sp,%a0 # save stack pointer for register copy
- addq.l &3,%d0 # round size up to long word
- andi.l &-4,%d0 # mask out lower two bits of size
- mov.l %sp,%d1 # compute new value of sp to d1
- sub.l %d0,%d1 # pseudo-allocate by moving stack pointer
- sub.l &MAXREG*4,%d1 # allocate more space for saved regs.
- mov.l %d1,%sp # actual allocation.
- move.w &MAXREG-1,%d0 # d0 counts saved regs.
- mov.l %a2,%d1 # preserve a2.
- mov.l %sp,%a2 # make pointer to new reg save area.
-copy_regs_loop: # copy stuff from old save area.
- mov.l (%a0)+,(%a2)+ # save saved register
- dbra %d0,copy_regs_loop
- mov.l %a2,%a0 # now a2 is start of allocated space.
- mov.l %a2,%d0 # return it in both a0 and d0 to play safe.
- mov.l %d1,%a2 # restore a2.
- subq.l &4,%sp # new top of stack
- jmp (%a1) # far below normal return
-#else /* not MOTOROLA_DELTA */
- 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
-#endif /* not MOTOROLA_DELTA */
-
-#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 boundary
- 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
-#ifdef NS5 /* ns SysV assembler */
-#define IM $
-#define REGISTER(x) x
-#else
-#define IM $
-#define REGISTER(x) 0(x)
-#endif
-#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/blockinput.h b/src/blockinput.h
deleted file mode 100644
index a4bf3256335..00000000000
--- a/src/blockinput.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* blockinput.h - interface to blocking complicated interrupt-driven input.
- Copyright (C) 1989, 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* When Emacs is using signal-driven input, the processing of those
- input signals can get pretty hairy. For example, when Emacs is
- running under X windows, handling an input signal can entail
- retrieving events from the X event queue, or making other X calls.
-
- If an input signal occurs while Emacs is in the midst of some
- non-reentrant code, and the signal processing invokes that same
- code, we lose. For example, malloc and the Xlib functions aren't
- usually re-entrant, and both are used by the X input signal handler
- - if we try to process an input signal in the midst of executing
- any of these functions, we'll lose.
-
- To avoid this, we make the following requirements:
-
- * Everyone must evaluate BLOCK_INPUT before entering these functions,
- and then call UNBLOCK_INPUT after performing them. Calls
- BLOCK_INPUT and UNBLOCK_INPUT may be nested.
-
- * Any complicated interrupt handling code should test
- interrupt_input_blocked, and put off its work until later.
-
- * If the interrupt handling code wishes, it may set
- interrupt_input_pending to a non-zero value. If that flag is set
- when input becomes unblocked, UNBLOCK_INPUT will send a new SIGIO. */
-
-extern int interrupt_input_blocked;
-
-/* Nonzero means an input interrupt has arrived
- during the current critical section. */
-extern int interrupt_input_pending;
-
-/* Begin critical section. */
-#define BLOCK_INPUT (interrupt_input_blocked++)
-
-/* End critical section.
-
- If doing signal-driven input, and a signal came in when input was
- blocked, reinvoke the signal handler now to deal with it.
-
- We used to have two possible definitions of this macro - one for
- when SIGIO was #defined, and one for when it wasn't; when SIGIO
- wasn't #defined, we wouldn't bother to check if we should re-invoke
- the signal handler. But that doesn't work very well; some of the
- files which use this macro don't #include the right files to get
- SIGIO.
-
- So, we always test interrupt_input_pending now; that's not too
- expensive, and it'll never get set if we don't need to resignal. */
-#define UNBLOCK_INPUT \
- (interrupt_input_blocked--, \
- (interrupt_input_blocked < 0 ? (abort (), 0) : 0), \
- ((interrupt_input_blocked == 0 && interrupt_input_pending != 0) \
- ? (reinvoke_input_signal (), 0) \
- : 0))
-
-#define TOTALLY_UNBLOCK_INPUT (interrupt_input_blocked = 0)
-#define UNBLOCK_INPUT_RESIGNAL UNBLOCK_INPUT
diff --git a/src/buffer.c b/src/buffer.c
deleted file mode 100644
index 2c3ffdce136..00000000000
--- a/src/buffer.c
+++ /dev/null
@@ -1,4109 +0,0 @@
-/* Buffer manipulation primitives for GNU Emacs.
- Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994, 1995
- Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-
-#ifndef MAXPATHLEN
-/* in 4.1, param.h fails to define this. */
-#define MAXPATHLEN 1024
-#endif /* not MAXPATHLEN */
-
-#include <config.h>
-#include "lisp.h"
-#include "intervals.h"
-#include "window.h"
-#include "commands.h"
-#include "buffer.h"
-#include "region-cache.h"
-#include "indent.h"
-#include "blockinput.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 is negative, 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 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;
-
-/* This structure holds the required types for the values in the
- buffer-local slots. If a slot contains Qnil, then the
- corresponding buffer slot may contain a value of any type. If a
- slot contains an integer, then prospective values' tags must be
- equal to that integer. When a tag does not match, the function
- buffer_slot_type_mismatch will signal an error. */
-struct buffer buffer_local_types;
-
-/* Flags indicating which built-in buffer-local variables
- are permanent locals. */
-static int buffer_permanent_local_flags;
-
-Lisp_Object Fset_buffer ();
-void set_buffer_internal ();
-void set_buffer_internal_1 ();
-static void call_overlay_mod_hooks ();
-static void swap_out_buffer_local_variables ();
-static void reset_buffer_local_variables ();
-
-/* 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;
-
-/* Functions to call before and after each text change. */
-Lisp_Object Vbefore_change_function;
-Lisp_Object Vafter_change_function;
-Lisp_Object Vbefore_change_functions;
-Lisp_Object Vafter_change_functions;
-
-Lisp_Object Vtransient_mark_mode;
-
-/* t means ignore all read-only text properties.
- A list means ignore such a property if its value is a member of the list.
- Any non-nil value means ignore buffer-read-only. */
-Lisp_Object Vinhibit_read_only;
-
-/* List of functions to call that can query about killing a buffer.
- If any of these functions returns nil, we don't kill it. */
-Lisp_Object Vkill_buffer_query_functions;
-
-/* List of functions to call before changing an unmodified buffer. */
-Lisp_Object Vfirst_change_hook;
-
-Lisp_Object Qfirst_change_hook;
-Lisp_Object Qbefore_change_functions;
-Lisp_Object Qafter_change_functions;
-
-Lisp_Object Qfundamental_mode, Qmode_class, Qpermanent_local;
-
-Lisp_Object Qprotected_field;
-
-Lisp_Object QSFundamental; /* A string "Fundamental" */
-
-Lisp_Object Qkill_buffer_hook;
-
-Lisp_Object Qget_file_buffer;
-
-Lisp_Object Qoverlayp;
-
-Lisp_Object Qpriority, Qwindow, Qevaporate, Qbefore_string, Qafter_string;
-
-Lisp_Object Qmodification_hooks;
-Lisp_Object Qinsert_in_front_hooks;
-Lisp_Object Qinsert_behind_hooks;
-
-/* For debugging; temporary. See set_buffer_internal. */
-/* Lisp_Object Qlisp_mode, Vcheck_symbol; */
-
-nsberror (spec)
- Lisp_Object spec;
-{
- if (STRINGP (spec))
- error ("No buffer named %s", XSTRING (spec)->data);
- error ("Invalid buffer argument");
-}
-
-DEFUN ("buffer-live-p", Fbuffer_live_p, Sbuffer_live_p, 1, 1, 0,
- "Return non-nil if OBJECT is a buffer which has not been killed.\n\
-Value is nil if OBJECT is not a buffer or if it has been killed.")
- (object)
- Lisp_Object object;
-{
- return ((BUFFERP (object) && ! NILP (XBUFFER (object)->name))
- ? Qt : Qnil);
-}
-
-DEFUN ("buffer-list", Fbuffer_list, Sbuffer_list, 0, 0, 0,
- "Return a list of all existing live buffers.")
- ()
-{
- return Fmapcar (Qcdr, Vbuffer_alist);
-}
-
-/* Like Fassoc, but use Fstring_equal to compare
- (which ignores text properties),
- and don't ever QUIT. */
-
-static Lisp_Object
-assoc_ignore_text_properties (key, list)
- register Lisp_Object key;
- Lisp_Object list;
-{
- register Lisp_Object tail;
- for (tail = list; !NILP (tail); tail = Fcdr (tail))
- {
- register Lisp_Object elt, tem;
- elt = Fcar (tail);
- tem = Fstring_equal (Fcar (elt), key);
- if (!NILP (tem))
- return elt;
- }
- return Qnil;
-}
-
-DEFUN ("get-buffer", Fget_buffer, Sget_buffer, 1, 1, 0,
- "Return the buffer named NAME (a string).\n\
-If there is no live buffer named NAME, return nil.\n\
-NAME may also be a buffer; if so, the value is that buffer.")
- (name)
- register Lisp_Object name;
-{
- if (BUFFERP (name))
- return name;
- CHECK_STRING (name, 0);
-
- return Fcdr (assoc_ignore_text_properties (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\
-The buffer's `buffer-file-name' must match exactly the expansion of FILENAME.\n\
-If there is no such live buffer, return nil.\n\
-See also `find-buffer-visiting'.")
- (filename)
- register Lisp_Object filename;
-{
- register Lisp_Object tail, buf, tem;
- Lisp_Object handler;
-
- CHECK_STRING (filename, 0);
- filename = Fexpand_file_name (filename, Qnil);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qget_file_buffer);
- if (!NILP (handler))
- return call2 (handler, Qget_file_buffer, filename);
-
- for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- buf = Fcdr (XCONS (tail)->car);
- if (!BUFFERP (buf)) continue;
- if (!STRINGP (XBUFFER (buf)->filename)) continue;
- tem = Fstring_equal (XBUFFER (buf)->filename, filename);
- if (!NILP (tem))
- return buf;
- }
- return Qnil;
-}
-
-Lisp_Object
-get_truename_buffer (filename)
- register Lisp_Object filename;
-{
- register Lisp_Object tail, buf, tem;
-
- for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- buf = Fcdr (XCONS (tail)->car);
- if (!BUFFERP (buf)) continue;
- if (!STRINGP (XBUFFER (buf)->file_truename)) continue;
- tem = Fstring_equal (XBUFFER (buf)->file_truename, filename);
- if (!NILP (tem))
- return buf;
- }
- return Qnil;
-}
-
-/* Incremented for each buffer created, to assign the buffer number. */
-int buffer_count;
-
-DEFUN ("get-buffer-create", Fget_buffer_create, Sget_buffer_create, 1, 1, 0,
- "Return the buffer named NAME, or create such a buffer and return it.\n\
-A new buffer is created if there is no live buffer named NAME.\n\
-If NAME starts with a space, the new buffer does not keep undo information.\n\
-If NAME is a buffer instead of a string, then it is the value returned.\n\
-The value is never nil.")
- (name)
- register Lisp_Object name;
-{
- register Lisp_Object buf;
- register struct buffer *b;
-
- buf = Fget_buffer (name);
- if (!NILP (buf))
- return buf;
-
- if (XSTRING (name)->size == 0)
- error ("Empty string for buffer name is not allowed");
-
- b = (struct buffer *) xmalloc (sizeof (struct buffer));
-
- b->size = sizeof (struct buffer) / sizeof (EMACS_INT);
-
- /* An ordinary buffer uses its own struct buffer_text. */
- b->text = &b->own_text;
- b->base_buffer = 0;
-
- BUF_GAP_SIZE (b) = 20;
- BLOCK_INPUT;
- BUFFER_ALLOC (BUF_BEG_ADDR (b), BUF_GAP_SIZE (b));
- UNBLOCK_INPUT;
- if (! BUF_BEG_ADDR (b))
- buffer_memory_full ();
-
- BUF_PT (b) = 1;
- BUF_GPT (b) = 1;
- BUF_BEGV (b) = 1;
- BUF_ZV (b) = 1;
- BUF_Z (b) = 1;
- BUF_MODIFF (b) = 1;
- BUF_OVERLAY_MODIFF (b) = 1;
- BUF_SAVE_MODIFF (b) = 1;
- BUF_INTERVALS (b) = 0;
-
- b->newline_cache = 0;
- b->width_run_cache = 0;
- b->width_table = Qnil;
-
- /* Put this on the chain of all buffers including killed ones. */
- b->next = all_buffers;
- all_buffers = b;
-
- /* An ordinary buffer normally doesn't need markers
- to handle BEGV and ZV. */
- b->pt_marker = Qnil;
- b->begv_marker = Qnil;
- b->zv_marker = Qnil;
-
- name = Fcopy_sequence (name);
- INITIALIZE_INTERVAL (XSTRING (name), NULL_INTERVAL);
- b->name = name;
-
- if (XSTRING (name)->data[0] != ' ')
- b->undo_list = Qnil;
- else
- b->undo_list = Qt;
-
- reset_buffer (b);
- reset_buffer_local_variables (b, 1);
-
- /* Put this in the alist of all live buffers. */
- XSETBUFFER (buf, b);
- Vbuffer_alist = nconc2 (Vbuffer_alist, Fcons (Fcons (name, buf), Qnil));
-
- b->mark = Fmake_marker ();
- BUF_MARKERS (b) = Qnil;
- b->name = name;
- return buf;
-}
-
-DEFUN ("make-indirect-buffer", Fmake_indirect_buffer, Smake_indirect_buffer, 2, 2,
- "bMake indirect buffer (to buffer): \nBName of indirect buffer: ",
- "Create and return an indirect buffer for buffer BASE-BUFFER, named NAME.\n\
-BASE-BUFFER should be an existing buffer (or buffer name).\n\
-NAME should be a string which is not the name of an existing buffer.")
- (base_buffer, name)
- register Lisp_Object base_buffer, name;
-{
- register Lisp_Object buf;
- register struct buffer *b;
-
- buf = Fget_buffer (name);
- if (!NILP (buf))
- error ("Buffer name `%s' is in use", XSTRING (name)->data);
-
- base_buffer = Fget_buffer (base_buffer);
- if (NILP (base_buffer))
- error ("No such buffer: `%s'",
- XSTRING (XBUFFER (base_buffer)->name)->data);
-
- if (XSTRING (name)->size == 0)
- error ("Empty string for buffer name is not allowed");
-
- b = (struct buffer *) xmalloc (sizeof (struct buffer));
-
- b->size = sizeof (struct buffer) / sizeof (EMACS_INT);
-
- if (XBUFFER (base_buffer)->base_buffer)
- b->base_buffer = XBUFFER (base_buffer)->base_buffer;
- else
- b->base_buffer = XBUFFER (base_buffer);
-
- /* Use the base buffer's text object. */
- b->text = b->base_buffer->text;
-
- BUF_BEGV (b) = BUF_BEGV (b->base_buffer);
- BUF_ZV (b) = BUF_ZV (b->base_buffer);
- BUF_PT (b) = BUF_PT (b->base_buffer);
-
- b->newline_cache = 0;
- b->width_run_cache = 0;
- b->width_table = Qnil;
-
- /* Put this on the chain of all buffers including killed ones. */
- b->next = all_buffers;
- all_buffers = b;
-
- name = Fcopy_sequence (name);
- INITIALIZE_INTERVAL (XSTRING (name), NULL_INTERVAL);
- b->name = name;
-
- reset_buffer (b);
- reset_buffer_local_variables (b, 1);
-
- /* Put this in the alist of all live buffers. */
- XSETBUFFER (buf, b);
- Vbuffer_alist = nconc2 (Vbuffer_alist, Fcons (Fcons (name, buf), Qnil));
-
- b->mark = Fmake_marker ();
- b->name = name;
-
- /* Make sure the base buffer has markers for its narrowing. */
- if (NILP (b->base_buffer->pt_marker))
- {
- b->base_buffer->pt_marker = Fmake_marker ();
- Fset_marker (b->base_buffer->pt_marker,
- make_number (BUF_PT (b->base_buffer)), base_buffer);
- }
- if (NILP (b->base_buffer->begv_marker))
- {
- b->base_buffer->begv_marker = Fmake_marker ();
- Fset_marker (b->base_buffer->begv_marker,
- make_number (BUF_BEGV (b->base_buffer)), base_buffer);
- }
- if (NILP (b->base_buffer->zv_marker))
- {
- b->base_buffer->zv_marker = Fmake_marker ();
- Fset_marker (b->base_buffer->zv_marker,
- make_number (BUF_ZV (b->base_buffer)), base_buffer);
- XMARKER (b->base_buffer->zv_marker)->insertion_type = 1;
- }
-
- /* Give the indirect buffer markers for its narrowing. */
- b->pt_marker = Fmake_marker ();
- Fset_marker (b->pt_marker, make_number (BUF_PT (b)), buf);
- b->begv_marker = Fmake_marker ();
- Fset_marker (b->begv_marker, make_number (BUF_BEGV (b)), buf);
- b->zv_marker = Fmake_marker ();
- Fset_marker (b->zv_marker, make_number (BUF_ZV (b)), buf);
-
- XMARKER (b->zv_marker)->insertion_type = 1;
-
- return buf;
-}
-
-/* Reinitialize everything about a buffer except its name and contents
- and local variables. */
-
-void
-reset_buffer (b)
- register struct buffer *b;
-{
- b->filename = Qnil;
- b->file_truename = Qnil;
- b->directory = (current_buffer) ? current_buffer->directory : Qnil;
- b->modtime = 0;
- XSETFASTINT (b->save_length, 0);
- b->last_window_start = 1;
- b->backed_up = Qnil;
- b->auto_save_modified = 0;
- b->auto_save_failure_time = -1;
- b->auto_save_file_name = Qnil;
- b->read_only = Qnil;
- b->overlays_before = Qnil;
- b->overlays_after = Qnil;
- XSETFASTINT (b->overlay_center, 1);
- b->mark_active = Qnil;
- b->point_before_scroll = Qnil;
- b->file_format = Qnil;
- b->last_selected_window = Qnil;
- b->extra2 = Qnil;
- b->extra3 = Qnil;
-}
-
-/* Reset buffer B's local variables info.
- Don't use this on a buffer that has already been in use;
- it does not treat permanent locals consistently.
- Instead, use Fkill_all_local_variables.
-
- If PERMANENT_TOO is 1, then we reset permanent built-in
- buffer-local variables. If PERMANENT_TOO is 0,
- we preserve those. */
-
-static void
-reset_buffer_local_variables (b, permanent_too)
- register struct buffer *b;
- int permanent_too;
-{
- register int offset;
- int dont_reset;
-
- /* Decide which built-in local variables to reset. */
- if (permanent_too)
- dont_reset = 0;
- else
- dont_reset = buffer_permanent_local_flags;
-
- /* 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;
- b->minor_modes = Qnil;
-
- /* If the standard case table has been altered and invalidated,
- fix up its insides first. */
- if (! (CHAR_TABLE_P (XCHAR_TABLE (Vascii_downcase_table)->extras[0])
- && CHAR_TABLE_P (XCHAR_TABLE (Vascii_downcase_table)->extras[1])
- && CHAR_TABLE_P (XCHAR_TABLE (Vascii_downcase_table)->extras[2])))
- Fset_standard_case_table (Vascii_downcase_table);
-
- b->downcase_table = Vascii_downcase_table;
- b->upcase_table = XCHAR_TABLE (Vascii_downcase_table)->extras[0];
- b->case_canon_table = XCHAR_TABLE (Vascii_downcase_table)->extras[1];
- b->case_eqv_table = XCHAR_TABLE (Vascii_downcase_table)->extras[2];
- b->invisibility_spec = Qt;
-#ifndef DOS_NT
- b->buffer_file_type = Qnil;
-#endif
-
-#if 0
- b->sort_table = XSTRING (Vascii_sort_table);
- b->folding_sort_table = XSTRING (Vascii_folding_sort_table);
-#endif /* 0 */
-
- /* Reset all (or most) per-buffer variables to their defaults. */
- b->local_var_alist = Qnil;
- b->local_var_flags &= dont_reset;
-
- /* 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 EMACS_INT == sizeof Lisp_Object */
- {
- int flag = XINT (*(Lisp_Object *)(offset + (char *)&buffer_local_flags));
- if ((flag > 0
- /* Don't reset a permanent local. */
- && ! (dont_reset & flag))
- || flag == -2)
- *(Lisp_Object *)(offset + (char *)b)
- = *(Lisp_Object *)(offset + (char *)&buffer_defaults);
- }
-}
-
-/* We split this away from generate-new-buffer, because rename-buffer
- and set-visited-file-name ought to be able to use this to really
- rename the buffer properly. */
-
-DEFUN ("generate-new-buffer-name", Fgenerate_new_buffer_name, Sgenerate_new_buffer_name,
- 1, 2, 0,
- "Return a string that is the name of no existing buffer based on NAME.\n\
-If there is no live buffer named NAME, then return NAME.\n\
-Otherwise modify name by appending `<NUMBER>', incrementing NUMBER\n\
-until an unused name is found, and then return that name.\n\
-Optional second argument IGNORE specifies a name that is okay to use\n\
-\(if it is in the sequence to be tried)\n\
-even if a buffer with that name exists.")
- (name, ignore)
- register Lisp_Object name, ignore;
-{
- register Lisp_Object gentemp, tem;
- int count;
- char number[10];
-
- CHECK_STRING (name, 0);
-
- tem = Fget_buffer (name);
- if (NILP (tem))
- return name;
-
- count = 1;
- while (1)
- {
- sprintf (number, "<%d>", ++count);
- gentemp = concat2 (name, build_string (number));
- tem = Fstring_equal (gentemp, ignore);
- if (!NILP (tem))
- return gentemp;
- tem = Fget_buffer (gentemp);
- if (NILP (tem))
- return gentemp;
- }
-}
-
-
-DEFUN ("buffer-name", Fbuffer_name, Sbuffer_name, 0, 1, 0,
- "Return the name of BUFFER, as a string.\n\
-With no argument or nil as argument, return the name of the current buffer.")
- (buffer)
- register Lisp_Object buffer;
-{
- if (NILP (buffer))
- return current_buffer->name;
- CHECK_BUFFER (buffer, 0);
- return XBUFFER (buffer)->name;
-}
-
-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 or nil as argument means use the current buffer.")
- (buffer)
- register Lisp_Object buffer;
-{
- if (NILP (buffer))
- return current_buffer->filename;
- CHECK_BUFFER (buffer, 0);
- return XBUFFER (buffer)->filename;
-}
-
-DEFUN ("buffer-base-buffer", Fbuffer_base_buffer, Sbuffer_base_buffer,
- 0, 1, 0,
- "Return the base buffer of indirect buffer BUFFER.\n\
-If BUFFER is not indirect, return nil.")
- (buffer)
- register Lisp_Object buffer;
-{
- struct buffer *base;
- Lisp_Object base_buffer;
-
- if (NILP (buffer))
- base = current_buffer->base_buffer;
- else
- {
- CHECK_BUFFER (buffer, 0);
- base = XBUFFER (buffer)->base_buffer;
- }
-
- if (! base)
- return Qnil;
- XSETBUFFER (base_buffer, base);
- return base_buffer;
-}
-
-DEFUN ("buffer-local-variables", Fbuffer_local_variables,
- Sbuffer_local_variables, 0, 1, 0,
- "Return an alist of variables that are buffer-local in BUFFER.\n\
-Most elements look like (SYMBOL . VALUE), describing one variable.\n\
-For a symbol that is locally unbound, just the symbol appears in the value.\n\
-Note that storing new VALUEs in these elements doesn't change the variables.\n\
-No argument or nil as argument means use current buffer as BUFFER.")
- (buffer)
- register Lisp_Object buffer;
-{
- register struct buffer *buf;
- register Lisp_Object result;
-
- if (NILP (buffer))
- buf = current_buffer;
- else
- {
- CHECK_BUFFER (buffer, 0);
- buf = XBUFFER (buffer);
- }
-
- result = Qnil;
-
- {
- register Lisp_Object tail;
- for (tail = buf->local_var_alist; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- Lisp_Object val, elt;
-
- elt = XCONS (tail)->car;
-
- /* Reference each variable in the alist in buf.
- 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. */
- val = find_symbol_value (XCONS (elt)->car);
- /* Use the current buffer value only if buf is the current buffer. */
- if (buf != current_buffer)
- val = XCONS (elt)->cdr;
-
- /* If symbol is unbound, put just the symbol in the list. */
- if (EQ (val, Qunbound))
- result = Fcons (XCONS (elt)->car, result);
- /* Otherwise, put (symbol . value) in the list. */
- else
- result = Fcons (Fcons (XCONS (elt)->car, val), result);
- }
- }
-
- /* 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 (EMACS_INT))) /* sizeof EMACS_INT == sizeof Lisp_Object */
- {
- mask = XINT (*(Lisp_Object *)(offset + (char *)&buffer_local_flags));
- if (mask == -1 || (buf->local_var_flags & mask))
- if (SYMBOLP (*(Lisp_Object *)(offset
- + (char *)&buffer_local_symbols)))
- result = Fcons (Fcons (*((Lisp_Object *)
- (offset + (char *)&buffer_local_symbols)),
- *(Lisp_Object *)(offset + (char *)buf)),
- result);
- }
- }
-
- return result;
-}
-
-
-DEFUN ("buffer-modified-p", Fbuffer_modified_p, Sbuffer_modified_p,
- 0, 1, 0,
- "Return t if BUFFER was modified since its file was last read or saved.\n\
-No argument or nil as argument means use current buffer as BUFFER.")
- (buffer)
- register Lisp_Object buffer;
-{
- register struct buffer *buf;
- if (NILP (buffer))
- buf = current_buffer;
- else
- {
- CHECK_BUFFER (buffer, 0);
- buf = XBUFFER (buffer);
- }
-
- return BUF_SAVE_MODIFF (buf) < 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.\n\
-A non-nil FLAG means mark the buffer modified.")
- (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->file_truename;
- if (!NILP (fn))
- {
- already = SAVE_MODIFF < MODIFF;
- if (!already && !NILP (flag))
- lock_file (fn);
- else if (already && NILP (flag))
- unlock_file (fn);
- }
-#endif /* CLASH_DETECTION */
-
- SAVE_MODIFF = NILP (flag) ? MODIFF : 0;
- update_mode_lines++;
- return flag;
-}
-
-DEFUN ("buffer-modified-tick", Fbuffer_modified_tick, Sbuffer_modified_tick,
- 0, 1, 0,
- "Return BUFFER's tick counter, incremented for each change in text.\n\
-Each buffer has a tick counter which is incremented each time the text in\n\
-that buffer is changed. It wraps around occasionally.\n\
-No argument or nil as argument means use current buffer as BUFFER.")
- (buffer)
- register Lisp_Object buffer;
-{
- register struct buffer *buf;
- if (NILP (buffer))
- buf = current_buffer;
- else
- {
- CHECK_BUFFER (buffer, 0);
- buf = XBUFFER (buffer);
- }
-
- return make_number (BUF_MODIFF (buf));
-}
-
-DEFUN ("rename-buffer", Frename_buffer, Srename_buffer, 1, 2,
- "sRename buffer (to new name): \nP",
- "Change current buffer's name to NEWNAME (a string).\n\
-If second arg UNIQUE is nil or omitted, it is an error if a\n\
-buffer named NEWNAME already exists.\n\
-If UNIQUE is non-nil, come up with a new name using\n\
-`generate-new-buffer-name'.\n\
-Interactively, you can set UNIQUE with a prefix argument.\n\
-We return the name we actually gave the buffer.\n\
-This does not change the name of the visited file (if any).")
- (newname, unique)
- register Lisp_Object newname, unique;
-{
- register Lisp_Object tem, buf;
-
- CHECK_STRING (newname, 0);
-
- if (XSTRING (newname)->size == 0)
- error ("Empty string is invalid as a buffer name");
-
- tem = Fget_buffer (newname);
- /* Don't short-circuit if UNIQUE is t. That is a useful way to rename
- the buffer automatically so you can create another with the original name.
- It makes UNIQUE equivalent to
- (rename-buffer (generate-new-buffer-name NEWNAME)). */
- if (NILP (unique) && XBUFFER (tem) == current_buffer)
- return current_buffer->name;
- if (!NILP (tem))
- {
- if (!NILP (unique))
- newname = Fgenerate_new_buffer_name (newname, current_buffer->name);
- else
- error ("Buffer name `%s' is in use", XSTRING (newname)->data);
- }
-
- current_buffer->name = newname;
-
- /* Catch redisplay's attention. Unless we do this, the mode lines for
- any windows displaying current_buffer will stay unchanged. */
- update_mode_lines++;
-
- XSETBUFFER (buf, current_buffer);
- Fsetcar (Frassq (buf, Vbuffer_alist), newname);
- if (NILP (current_buffer->filename)
- && !NILP (current_buffer->auto_save_file_name))
- call0 (intern ("rename-auto-save-file"));
- /* Refetch since that last call may have done GC. */
- return current_buffer->name;
-}
-
-DEFUN ("other-buffer", Fother_buffer, Sother_buffer, 0, 2, 0,
- "Return most recently selected buffer other than BUFFER.\n\
-Buffers not visible in windows are preferred to visible buffers,\n\
-unless optional second argument VISIBLE-OK is non-nil.\n\
-If no other buffer exists, the buffer `*scratch*' is returned.\n\
-If BUFFER is omitted or nil, some interesting buffer is returned.")
- (buffer, visible_ok)
- register Lisp_Object buffer, visible_ok;
-{
- Lisp_Object Fset_buffer_major_mode ();
- register Lisp_Object tail, buf, notsogood, tem;
- notsogood = Qnil;
-
- for (tail = Vbuffer_alist; !NILP (tail); tail = Fcdr (tail))
- {
- buf = Fcdr (Fcar (tail));
- if (EQ (buf, buffer))
- continue;
- if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
- continue;
- /* If the selected frame has a buffer_predicate,
- disregard buffers that don't fit the predicate. */
- tem = frame_buffer_predicate ();
- if (!NILP (tem))
- {
- tem = call1 (tem, buf);
- if (NILP (tem))
- continue;
- }
-
- if (NILP (visible_ok))
- tem = Fget_buffer_window (buf, Qt);
- else
- tem = Qnil;
- if (NILP (tem))
- return buf;
- if (NILP (notsogood))
- notsogood = buf;
- }
- if (!NILP (notsogood))
- return notsogood;
- buf = Fget_buffer_create (build_string ("*scratch*"));
- Fset_buffer_major_mode (buf);
- return buf;
-}
-
-DEFUN ("buffer-disable-undo", Fbuffer_disable_undo, Sbuffer_disable_undo,
- 0, 1, "",
- "Make BUFFER stop keeping undo information.\n\
-No argument or nil as argument means do this for the current buffer.")
- (buffer)
- register Lisp_Object buffer;
-{
- Lisp_Object real_buffer;
-
- if (NILP (buffer))
- XSETBUFFER (real_buffer, current_buffer);
- else
- {
- real_buffer = Fget_buffer (buffer);
- if (NILP (real_buffer))
- nsberror (buffer);
- }
-
- XBUFFER (real_buffer)->undo_list = Qt;
-
- return Qnil;
-}
-
-DEFUN ("buffer-enable-undo", Fbuffer_enable_undo, Sbuffer_enable_undo,
- 0, 1, "",
- "Start keeping undo information for buffer BUFFER.\n\
-No argument or nil as argument means do this for the current buffer.")
- (buffer)
- register Lisp_Object buffer;
-{
- Lisp_Object real_buffer;
-
- if (NILP (buffer))
- XSETBUFFER (real_buffer, current_buffer);
- else
- {
- real_buffer = Fget_buffer (buffer);
- if (NILP (real_buffer))
- nsberror (buffer);
- }
-
- if (EQ (XBUFFER (real_buffer)->undo_list, Qt))
- XBUFFER (real_buffer)->undo_list = Qnil;
-
- return Qnil;
-}
-
-/*
- DEFVAR_LISP ("kill-buffer-hook", no_cell, "\
-Hook to be run (by `run-hooks', which see) when a buffer is killed.\n\
-The buffer being killed will be current while the hook is running.\n\
-See `kill-buffer'."
- */
-DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 1, 1, "bKill buffer: ",
- "Kill the buffer BUFFER.\n\
-The argument may be a buffer or may be the name of a buffer.\n\
-An argument of nil means kill the current buffer.\n\n\
-Value is t if the buffer is actually killed, nil if user says no.\n\n\
-The value of `kill-buffer-hook' (which may be local to that buffer),\n\
-if not void, is a list of functions to be called, with no arguments,\n\
-before the buffer is actually killed. The buffer to be killed is current\n\
-when the hook functions are called.\n\n\
-Any processes that have this buffer as the `process-buffer' are killed\n\
-with SIGHUP.")
- (buffer)
- Lisp_Object buffer;
-{
- Lisp_Object buf;
- register struct buffer *b;
- register Lisp_Object tem;
- register struct Lisp_Marker *m;
- struct gcpro gcpro1, gcpro2;
-
- if (NILP (buffer))
- buf = Fcurrent_buffer ();
- else
- buf = Fget_buffer (buffer);
- if (NILP (buf))
- nsberror (buffer);
-
- b = XBUFFER (buf);
-
- /* Avoid trouble for buffer already dead. */
- if (NILP (b->name))
- return Qnil;
-
- /* Query if the buffer is still modified. */
- if (INTERACTIVE && !NILP (b->filename)
- && BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
- {
- GCPRO1 (buf);
- tem = do_yes_or_no_p (format1 ("Buffer %s modified; kill anyway? ",
- XSTRING (b->name)->data));
- UNGCPRO;
- if (NILP (tem))
- return Qnil;
- }
-
- /* Run hooks with the buffer to be killed the current buffer. */
- {
- register Lisp_Object val;
- int count = specpdl_ptr - specpdl;
- Lisp_Object list;
-
- record_unwind_protect (save_excursion_restore, save_excursion_save ());
- set_buffer_internal (b);
-
- /* First run the query functions; if any query is answered no,
- don't kill the buffer. */
- for (list = Vkill_buffer_query_functions; !NILP (list); list = Fcdr (list))
- {
- tem = call0 (Fcar (list));
- if (NILP (tem))
- return unbind_to (count, Qnil);
- }
-
- /* Then run the hooks. */
- if (!NILP (Vrun_hooks))
- call1 (Vrun_hooks, Qkill_buffer_hook);
- unbind_to (count, 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 do_yes_or_no_p. */
-
- /* Don't kill the minibuffer now current. */
- if (EQ (buf, XWINDOW (minibuf_window)->buffer))
- return Qnil;
-
- if (NILP (b->name))
- return Qnil;
-
- /* When we kill a base buffer, kill all its indirect buffers.
- We do it at this stage so nothing terrible happens if they
- ask questions or their hooks get errors. */
- if (! b->base_buffer)
- {
- struct buffer *other;
-
- GCPRO1 (buf);
-
- for (other = all_buffers; other; other = other->next)
- /* all_buffers contains dead buffers too;
- don't re-kill them. */
- if (other->base_buffer == b && !NILP (other->name))
- {
- Lisp_Object buf;
- XSETBUFFER (buf, other);
- Fkill_buffer (buf);
- }
-
- UNGCPRO;
- }
-
- /* 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, Qnil);
- 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 */
-
- kill_buffer_processes (buf);
-
- tem = Vinhibit_quit;
- Vinhibit_quit = Qt;
- replace_buffer_in_all_windows (buf);
- Vbuffer_alist = Fdelq (Frassq (buf, Vbuffer_alist), Vbuffer_alist);
- Vinhibit_quit = tem;
-
- /* Delete any auto-save file, if we saved it in this session. */
- if (STRINGP (b->auto_save_file_name)
- && b->auto_save_modified != 0
- && SAVE_MODIFF < b->auto_save_modified)
- {
- Lisp_Object tem;
- tem = Fsymbol_value (intern ("delete-auto-save-files"));
- if (! NILP (tem))
- internal_delete_file (b->auto_save_file_name);
- }
-
- if (b->base_buffer)
- {
- /* Unchain all markers that belong to this indirect buffer.
- Don't unchain the markers that belong to the base buffer
- or its other indirect buffers. */
- for (tem = BUF_MARKERS (b); !NILP (tem); )
- {
- Lisp_Object next;
- m = XMARKER (tem);
- next = m->chain;
- if (m->buffer == b)
- unchain_marker (tem);
- tem = next;
- }
- }
- else
- {
- /* Unchain all markers of this buffer and its indirect buffers.
- and leave them pointing nowhere. */
- for (tem = BUF_MARKERS (b); !NILP (tem); )
- {
- m = XMARKER (tem);
- m->buffer = 0;
- tem = m->chain;
- m->chain = Qnil;
- }
- BUF_MARKERS (b) = Qnil;
-
-#ifdef USE_TEXT_PROPERTIES
- BUF_INTERVALS (b) = NULL_INTERVAL;
-#endif
-
- /* Perhaps we should explicitly free the interval tree here... */
- }
-
- /* Reset the local variables, so that this buffer's local values
- won't be protected from GC. They would be protected
- if they happened to remain encached in their symbols.
- This gets rid of them for certain. */
- swap_out_buffer_local_variables (b);
- reset_buffer_local_variables (b, 1);
-
- b->name = Qnil;
-
- BLOCK_INPUT;
- if (! b->base_buffer)
- BUFFER_FREE (BUF_BEG_ADDR (b));
-
- if (b->newline_cache)
- {
- free_region_cache (b->newline_cache);
- b->newline_cache = 0;
- }
- if (b->width_run_cache)
- {
- free_region_cache (b->width_run_cache);
- b->width_run_cache = 0;
- }
- b->width_table = Qnil;
- UNBLOCK_INPUT;
- b->undo_list = Qnil;
-
- return Qt;
-}
-
-/* Move the assoc for buffer BUF to the front of buffer-alist. Since
- we do this each time BUF is selected visibly, the more recently
- selected buffers are always closer to the front of the list. This
- means that other_buffer is more likely to choose a relevant buffer. */
-
-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);
- we cannot use Fdelq itself here because it allows quitting. */
-
- if (NILP (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 ("set-buffer-major-mode", Fset_buffer_major_mode, Sset_buffer_major_mode, 1, 1, 0,
- "Set an appropriate major mode for BUFFER, according to `default-major-mode'.\n\
-Use this function before selecting the buffer, since it may need to inspect\n\
-the current buffer's major mode.")
- (buffer)
- Lisp_Object buffer;
-{
- int count;
- Lisp_Object function;
-
- function = buffer_defaults.major_mode;
- if (NILP (function) && NILP (Fget (current_buffer->major_mode, Qmode_class)))
- function = current_buffer->major_mode;
-
- if (NILP (function) || EQ (function, Qfundamental_mode))
- return Qnil;
-
- count = specpdl_ptr - specpdl;
-
- /* 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 (buffer);
- call0 (function);
-
- return unbind_to (count, Qnil);
-}
-
-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 correspondences.")
- (buffer, norecord)
- Lisp_Object buffer, norecord;
-{
- register Lisp_Object buf;
- Lisp_Object tem;
-
- if (EQ (minibuf_window, selected_window))
- error ("Cannot switch buffers in minibuffer window");
- tem = Fwindow_dedicated_p (selected_window);
- if (!NILP (tem))
- error ("Cannot switch buffers in a dedicated window");
-
- if (NILP (buffer))
- buf = Fother_buffer (Fcurrent_buffer (), Qnil);
- else
- {
- buf = Fget_buffer (buffer);
- if (NILP (buf))
- {
- buf = Fget_buffer_create (buffer);
- Fset_buffer_major_mode (buf);
- }
- }
- Fset_buffer (buf);
- if (NILP (norecord))
- record_buffer (buf);
-
- Fset_window_buffer (EQ (selected_window, minibuf_window)
- ? Fnext_window (minibuf_window, Qnil, Qnil)
- : selected_window,
- buf);
-
- return buf;
-}
-
-DEFUN ("pop-to-buffer", Fpop_to_buffer, Spop_to_buffer, 1, 3, 0,
- "Select buffer BUFFER in some window, preferably a different one.\n\
-If BUFFER is nil, then some other buffer is chosen.\n\
-If `pop-up-windows' is non-nil, windows can be split to do this.\n\
-If optional second arg OTHER-WINDOW is non-nil, insist on finding another\n\
-window even if BUFFER is already visible in the selected window.\n\
-This uses the function `display-buffer' as a subroutine; see the documentation\n\
-of `display-buffer' for additional customization information.\n\
-\n\
-Optional third arg NORECORD non-nil means\n\
-do not put this buffer at the front of the list of recently selected ones.")
- (buffer, other_window, norecord)
- Lisp_Object buffer, other_window, norecord;
-{
- register Lisp_Object buf;
- if (NILP (buffer))
- buf = Fother_buffer (Fcurrent_buffer (), Qnil);
- else
- {
- buf = Fget_buffer (buffer);
- if (NILP (buf))
- {
- buf = Fget_buffer_create (buffer);
- Fset_buffer_major_mode (buf);
- }
- }
- Fset_buffer (buf);
- if (NILP (norecord))
- record_buffer (buf);
- Fselect_window (Fdisplay_buffer (buf, other_window));
- return buf;
-}
-
-DEFUN ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0,
- "Return the current buffer as a Lisp object.")
- ()
-{
- register Lisp_Object buf;
- XSETBUFFER (buf, current_buffer);
- return buf;
-}
-
-/* Set the current buffer to B. */
-
-void
-set_buffer_internal (b)
- register struct buffer *b;
-{
- register struct buffer *old_buf;
- register Lisp_Object tail, valcontents;
- Lisp_Object tem;
-
- if (current_buffer == b)
- return;
-
- windows_or_buffers_changed = 1;
- set_buffer_internal_1 (b);
-}
-
-/* Set the current buffer to B, and do not set windows_or_buffers_changed.
- This is used by redisplay. */
-
-void
-set_buffer_internal_1 (b)
- register struct buffer *b;
-{
- register struct buffer *old_buf;
- register Lisp_Object tail, valcontents;
- Lisp_Object tem;
-
- if (current_buffer == b)
- return;
-
- old_buf = current_buffer;
- current_buffer = b;
- last_known_column_point = -1; /* invalidate indentation cache */
-
- if (old_buf)
- {
- /* Put the undo list back in the base buffer, so that it appears
- that an indirect buffer shares the undo list of its base. */
- if (old_buf->base_buffer)
- old_buf->base_buffer->undo_list = old_buf->undo_list;
-
- /* If the old current buffer has markers to record PT, BEGV and ZV
- when it is not current, update them now. */
- if (! NILP (old_buf->pt_marker))
- {
- Lisp_Object obuf;
- XSETBUFFER (obuf, old_buf);
- Fset_marker (old_buf->pt_marker, BUF_PT (old_buf), obuf);
- }
- if (! NILP (old_buf->begv_marker))
- {
- Lisp_Object obuf;
- XSETBUFFER (obuf, old_buf);
- Fset_marker (old_buf->begv_marker, BUF_BEGV (old_buf), obuf);
- }
- if (! NILP (old_buf->zv_marker))
- {
- Lisp_Object obuf;
- XSETBUFFER (obuf, old_buf);
- Fset_marker (old_buf->zv_marker, BUF_ZV (old_buf), obuf);
- }
- }
-
- /* Get the undo list from the base buffer, so that it appears
- that an indirect buffer shares the undo list of its base. */
- if (b->base_buffer)
- b->undo_list = b->base_buffer->undo_list;
-
- /* If the new current buffer has markers to record PT, BEGV and ZV
- when it is not current, fetch them now. */
- if (! NILP (b->pt_marker))
- BUF_PT (b) = marker_position (b->pt_marker);
- if (! NILP (b->begv_marker))
- BUF_BEGV (b) = marker_position (b->begv_marker);
- if (! NILP (b->zv_marker))
- BUF_ZV (b) = marker_position (b->zv_marker);
-
- /* 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; !NILP (tail); tail = XCONS (tail)->cdr)
- {
- valcontents = XSYMBOL (XCONS (XCONS (tail)->car)->car)->value;
- if ((BUFFER_LOCAL_VALUEP (valcontents)
- || SOME_BUFFER_LOCAL_VALUEP (valcontents))
- && (tem = XBUFFER_LOCAL_VALUE (valcontents)->car,
- (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem))))
- /* 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; !NILP (tail); tail = XCONS (tail)->cdr)
- {
- valcontents = XSYMBOL (XCONS (XCONS (tail)->car)->car)->value;
- if ((BUFFER_LOCAL_VALUEP (valcontents)
- || SOME_BUFFER_LOCAL_VALUEP (valcontents))
- && (tem = XBUFFER_LOCAL_VALUE (valcontents)->car,
- (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem))))
- /* Just reference the variable
- to cause it to become set for this buffer. */
- Fsymbol_value (XCONS (XCONS (tail)->car)->car);
- }
-}
-
-/* Switch to buffer B temporarily for redisplay purposes.
- This avoids certain things that don't need to be done within redisplay. */
-
-void
-set_buffer_temp (b)
- struct buffer *b;
-{
- register struct buffer *old_buf;
-
- if (current_buffer == b)
- return;
-
- old_buf = current_buffer;
- current_buffer = b;
-
- if (old_buf)
- {
- /* If the old current buffer has markers to record PT, BEGV and ZV
- when it is not current, update them now. */
- if (! NILP (old_buf->pt_marker))
- {
- Lisp_Object obuf;
- XSETBUFFER (obuf, old_buf);
- Fset_marker (old_buf->pt_marker, BUF_PT (old_buf), obuf);
- }
- if (! NILP (old_buf->begv_marker))
- {
- Lisp_Object obuf;
- XSETBUFFER (obuf, old_buf);
- Fset_marker (old_buf->begv_marker, BUF_BEGV (old_buf), obuf);
- }
- if (! NILP (old_buf->zv_marker))
- {
- Lisp_Object obuf;
- XSETBUFFER (obuf, old_buf);
- Fset_marker (old_buf->zv_marker, BUF_ZV (old_buf), obuf);
- }
- }
-
- /* If the new current buffer has markers to record PT, BEGV and ZV
- when it is not current, fetch them now. */
- if (! NILP (b->pt_marker))
- BUF_PT (b) = marker_position (b->pt_marker);
- if (! NILP (b->begv_marker))
- BUF_BEGV (b) = marker_position (b->begv_marker);
- if (! NILP (b->zv_marker))
- BUF_ZV (b) = marker_position (b->zv_marker);
-}
-
-DEFUN ("set-buffer", Fset_buffer, Sset_buffer, 1, 1, 0,
- "Make the buffer BUFFER current for editing operations.\n\
-BUFFER may be a buffer or the name of an existing buffer.\n\
-See also `save-excursion' when you want to make a buffer current temporarily.\n\
-This function does not display the buffer, so its effect ends\n\
-when the current command terminates.\n\
-Use `switch-to-buffer' or `pop-to-buffer' to switch buffers permanently.")
- (buffer)
- register Lisp_Object buffer;
-{
- register Lisp_Object buf;
- buf = Fget_buffer (buffer);
- if (NILP (buf))
- nsberror (buffer);
- if (NILP (XBUFFER (buf)->name))
- error ("Selecting deleted buffer");
- set_buffer_internal (XBUFFER (buf));
- return buf;
-}
-
-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.")
- ()
-{
- if (!NILP (current_buffer->read_only)
- && NILP (Vinhibit_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\
-If BUFFER is nil or omitted, bury the current buffer.\n\
-Also, if BUFFER is nil or omitted, remove the current buffer from the\n\
-selected window if it is displayed there.")
- (buffer)
- register Lisp_Object buffer;
-{
- /* Figure out what buffer we're going to bury. */
- if (NILP (buffer))
- {
- XSETBUFFER (buffer, current_buffer);
-
- /* If we're burying the current buffer, unshow it. */
- Fswitch_to_buffer (Fother_buffer (buffer, Qnil), Qnil);
- }
- else
- {
- Lisp_Object buf1;
-
- buf1 = Fget_buffer (buffer);
- if (NILP (buf1))
- nsberror (buffer);
- buffer = buf1;
- }
-
- /* Move buffer to the end of the buffer list. */
- {
- register Lisp_Object aelt, link;
-
- aelt = Frassq (buffer, 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;
-}
-
-DEFUN ("erase-buffer", Ferase_buffer, Serase_buffer, 0, 0, "*",
- "Delete the entire contents of the current buffer.\n\
-Any narrowing restriction in effect (see `narrow-to-region') is removed,\n\
-so the buffer is truly empty after this.")
- ()
-{
- 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. */
- XSETFASTINT (current_buffer->save_length, 0);
- return Qnil;
-}
-
-validate_region (b, e)
- register Lisp_Object *b, *e;
-{
- CHECK_NUMBER_COERCE_MARKER (*b, 0);
- CHECK_NUMBER_COERCE_MARKER (*e, 1);
-
- if (XINT (*b) > XINT (*e))
- {
- Lisp_Object tem;
- tem = *b; *b = *e; *e = tem;
- }
-
- if (!(BEGV <= XINT (*b) && XINT (*b) <= XINT (*e)
- && XINT (*e) <= ZV))
- args_out_of_range (*b, *e);
-}
-
-DEFUN ("kill-all-local-variables", Fkill_all_local_variables, Skill_all_local_variables,
- 0, 0, 0,
- "Switch to Fundamental mode by killing current buffer's local variables.\n\
-Most local variable bindings are eliminated so that the default values\n\
-become effective once more. Also, the syntax table is set from\n\
-`standard-syntax-table', the local keymap is set to nil,\n\
-and the abbrev table from `fundamental-mode-abbrev-table'.\n\
-This function also forces redisplay of the mode line.\n\
-\n\
-Every function to select a new major mode starts by\n\
-calling this function.\n\n\
-As a special exception, local variables whose names have\n\
-a non-nil `permanent-local' property are not eliminated by this function.\n\
-\n\
-The first thing this function does is run\n\
-the normal hook `change-major-mode-hook'.")
- ()
-{
- register Lisp_Object alist, sym, tem;
- Lisp_Object oalist;
-
- if (!NILP (Vrun_hooks))
- call1 (Vrun_hooks, intern ("change-major-mode-hook"));
- oalist = current_buffer->local_var_alist;
-
- /* Make sure none of the bindings in oalist
- remain swapped in, in their symbols. */
-
- swap_out_buffer_local_variables (current_buffer);
-
- /* Actually eliminate all local bindings of this buffer. */
-
- reset_buffer_local_variables (current_buffer, 0);
-
- /* Redisplay mode lines; we are changing major mode. */
-
- update_mode_lines++;
-
- /* Any which are supposed to be permanent,
- make local again, with the same values they had. */
-
- for (alist = oalist; !NILP (alist); alist = XCONS (alist)->cdr)
- {
- sym = XCONS (XCONS (alist)->car)->car;
- tem = Fget (sym, Qpermanent_local);
- if (! NILP (tem))
- {
- Fmake_local_variable (sym);
- Fset (sym, XCONS (XCONS (alist)->car)->cdr);
- }
- }
-
- /* Force mode-line redisplay. Useful here because all major mode
- commands call this function. */
- update_mode_lines++;
-
- return Qnil;
-}
-
-/* Make sure no local variables remain set up with buffer B
- for their current values. */
-
-static void
-swap_out_buffer_local_variables (b)
- struct buffer *b;
-{
- Lisp_Object oalist, alist, sym, tem, buffer;
-
- XSETBUFFER (buffer, b);
- oalist = b->local_var_alist;
-
- for (alist = oalist; !NILP (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 (XBUFFER_LOCAL_VALUE (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 (XBUFFER_LOCAL_VALUE (XSYMBOL (sym)->value)->cdr)->cdr;
- /* Store the symbol's current value into the alist entry
- it is currently set up for. This is so that, if the
- local is marked permanent, and we make it local again
- later in Fkill_all_local_variables, we don't lose the value. */
- XCONS (XCONS (tem)->car)->cdr
- = do_symval_forwarding (XBUFFER_LOCAL_VALUE (XSYMBOL (sym)->value)->car);
- /* Switch to the symbol's default-value alist entry. */
- XCONS (tem)->car = tem;
- /* Mark it as current for buffer B. */
- XCONS (XBUFFER_LOCAL_VALUE (XSYMBOL (sym)->value)->cdr)->car
- = buffer;
- /* Store the current value into any forwarding in the symbol. */
- store_symval_forwarding (sym, XBUFFER_LOCAL_VALUE (XSYMBOL (sym)->value)->car,
- XCONS (tem)->cdr);
- }
- }
-}
-
-/* Find all the overlays in the current buffer that contain position POS.
- Return the number found, and store them in a vector in *VEC_PTR.
- Store in *LEN_PTR the size allocated for the vector.
- Store in *NEXT_PTR the next position after POS where an overlay starts,
- or ZV if there are no more overlays.
- Store in *PREV_PTR the previous position before POS where an overlay ends,
- or BEGV if there are no previous overlays.
- NEXT_PTR and/or PREV_PTR may be 0, meaning don't store that info.
-
- *VEC_PTR and *LEN_PTR should contain a valid vector and size
- when this function is called.
-
- If EXTEND is non-zero, we make the vector bigger if necessary.
- If EXTEND is zero, we never extend the vector,
- and we store only as many overlays as will fit.
- But we still return the total number of overlays. */
-
-int
-overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
- int pos;
- int extend;
- Lisp_Object **vec_ptr;
- int *len_ptr;
- int *next_ptr;
- int *prev_ptr;
-{
- Lisp_Object tail, overlay, start, end, result;
- int idx = 0;
- int len = *len_ptr;
- Lisp_Object *vec = *vec_ptr;
- int next = ZV;
- int prev = BEGV;
- int inhibit_storing = 0;
-
- for (tail = current_buffer->overlays_before;
- GC_CONSP (tail);
- tail = XCONS (tail)->cdr)
- {
- int startpos, endpos;
-
- overlay = XCONS (tail)->car;
-
- start = OVERLAY_START (overlay);
- end = OVERLAY_END (overlay);
- endpos = OVERLAY_POSITION (end);
- if (endpos < pos)
- {
- if (prev < endpos)
- prev = endpos;
- break;
- }
- if (endpos == pos)
- continue;
- startpos = OVERLAY_POSITION (start);
- if (startpos <= pos)
- {
- if (idx == len)
- {
- /* The supplied vector is full.
- Either make it bigger, or don't store any more in it. */
- if (extend)
- {
- *len_ptr = len *= 2;
- vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
- *vec_ptr = vec;
- }
- else
- inhibit_storing = 1;
- }
-
- if (!inhibit_storing)
- vec[idx] = overlay;
- /* Keep counting overlays even if we can't return them all. */
- idx++;
- }
- else if (startpos < next)
- next = startpos;
- }
-
- for (tail = current_buffer->overlays_after;
- GC_CONSP (tail);
- tail = XCONS (tail)->cdr)
- {
- int startpos, endpos;
-
- overlay = XCONS (tail)->car;
-
- start = OVERLAY_START (overlay);
- end = OVERLAY_END (overlay);
- startpos = OVERLAY_POSITION (start);
- if (pos < startpos)
- {
- if (startpos < next)
- next = startpos;
- break;
- }
- endpos = OVERLAY_POSITION (end);
- if (pos < endpos)
- {
- if (idx == len)
- {
- if (extend)
- {
- *len_ptr = len *= 2;
- vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
- *vec_ptr = vec;
- }
- else
- inhibit_storing = 1;
- }
-
- if (!inhibit_storing)
- vec[idx] = overlay;
- idx++;
- }
- else if (endpos < pos && endpos > prev)
- prev = endpos;
- }
-
- if (next_ptr)
- *next_ptr = next;
- if (prev_ptr)
- *prev_ptr = prev;
- return idx;
-}
-
-/* Find all the overlays in the current buffer that overlap the range BEG-END
- or are empty at BEG.
-
- Return the number found, and store them in a vector in *VEC_PTR.
- Store in *LEN_PTR the size allocated for the vector.
- Store in *NEXT_PTR the next position after POS where an overlay starts,
- or ZV if there are no more overlays.
- Store in *PREV_PTR the previous position before POS where an overlay ends,
- or BEGV if there are no previous overlays.
- NEXT_PTR and/or PREV_PTR may be 0, meaning don't store that info.
-
- *VEC_PTR and *LEN_PTR should contain a valid vector and size
- when this function is called.
-
- If EXTEND is non-zero, we make the vector bigger if necessary.
- If EXTEND is zero, we never extend the vector,
- and we store only as many overlays as will fit.
- But we still return the total number of overlays. */
-
-int
-overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
- int beg, end;
- int extend;
- Lisp_Object **vec_ptr;
- int *len_ptr;
- int *next_ptr;
- int *prev_ptr;
-{
- Lisp_Object tail, overlay, ostart, oend, result;
- int idx = 0;
- int len = *len_ptr;
- Lisp_Object *vec = *vec_ptr;
- int next = ZV;
- int prev = BEGV;
- int inhibit_storing = 0;
-
- for (tail = current_buffer->overlays_before;
- GC_CONSP (tail);
- tail = XCONS (tail)->cdr)
- {
- int startpos, endpos;
-
- overlay = XCONS (tail)->car;
-
- ostart = OVERLAY_START (overlay);
- oend = OVERLAY_END (overlay);
- endpos = OVERLAY_POSITION (oend);
- if (endpos < beg)
- {
- if (prev < endpos)
- prev = endpos;
- break;
- }
- startpos = OVERLAY_POSITION (ostart);
- /* Count an interval if it either overlaps the range
- or is empty at the start of the range. */
- if ((beg < endpos && startpos < end)
- || (startpos == endpos && beg == endpos))
- {
- if (idx == len)
- {
- /* The supplied vector is full.
- Either make it bigger, or don't store any more in it. */
- if (extend)
- {
- *len_ptr = len *= 2;
- vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
- *vec_ptr = vec;
- }
- else
- inhibit_storing = 1;
- }
-
- if (!inhibit_storing)
- vec[idx] = overlay;
- /* Keep counting overlays even if we can't return them all. */
- idx++;
- }
- else if (startpos < next)
- next = startpos;
- }
-
- for (tail = current_buffer->overlays_after;
- GC_CONSP (tail);
- tail = XCONS (tail)->cdr)
- {
- int startpos, endpos;
-
- overlay = XCONS (tail)->car;
-
- ostart = OVERLAY_START (overlay);
- oend = OVERLAY_END (overlay);
- startpos = OVERLAY_POSITION (ostart);
- if (end < startpos)
- {
- if (startpos < next)
- next = startpos;
- break;
- }
- endpos = OVERLAY_POSITION (oend);
- /* Count an interval if it either overlaps the range
- or is empty at the start of the range. */
- if ((beg < endpos && startpos < end)
- || (startpos == endpos && beg == endpos))
- {
- if (idx == len)
- {
- if (extend)
- {
- *len_ptr = len *= 2;
- vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
- *vec_ptr = vec;
- }
- else
- inhibit_storing = 1;
- }
-
- if (!inhibit_storing)
- vec[idx] = overlay;
- idx++;
- }
- else if (endpos < beg && endpos > prev)
- prev = endpos;
- }
-
- if (next_ptr)
- *next_ptr = next;
- if (prev_ptr)
- *prev_ptr = prev;
- return idx;
-}
-
-/* Fast function to just test if we're at an overlay boundary. */
-int
-overlay_touches_p (pos)
- int pos;
-{
- Lisp_Object tail, overlay;
-
- for (tail = current_buffer->overlays_before; GC_CONSP (tail);
- tail = XCONS (tail)->cdr)
- {
- int endpos;
-
- overlay = XCONS (tail)->car;
- if (!GC_OVERLAYP (overlay))
- abort ();
-
- endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
- if (endpos < pos)
- break;
- if (endpos == pos || OVERLAY_POSITION (OVERLAY_START (overlay)) == pos)
- return 1;
- }
-
- for (tail = current_buffer->overlays_after; GC_CONSP (tail);
- tail = XCONS (tail)->cdr)
- {
- int startpos;
-
- overlay = XCONS (tail)->car;
- if (!GC_OVERLAYP (overlay))
- abort ();
-
- startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
- if (pos < startpos)
- break;
- if (startpos == pos || OVERLAY_POSITION (OVERLAY_END (overlay)) == pos)
- return 1;
- }
- return 0;
-}
-
-struct sortvec
-{
- Lisp_Object overlay;
- int beg, end;
- int priority;
-};
-
-static int
-compare_overlays (s1, s2)
- struct sortvec *s1, *s2;
-{
- if (s1->priority != s2->priority)
- return s1->priority - s2->priority;
- if (s1->beg != s2->beg)
- return s1->beg - s2->beg;
- if (s1->end != s2->end)
- return s2->end - s1->end;
- return 0;
-}
-
-/* Sort an array of overlays by priority. The array is modified in place.
- The return value is the new size; this may be smaller than the original
- size if some of the overlays were invalid or were window-specific. */
-int
-sort_overlays (overlay_vec, noverlays, w)
- Lisp_Object *overlay_vec;
- int noverlays;
- struct window *w;
-{
- int i, j;
- struct sortvec *sortvec;
- sortvec = (struct sortvec *) alloca (noverlays * sizeof (struct sortvec));
-
- /* Put the valid and relevant overlays into sortvec. */
-
- for (i = 0, j = 0; i < noverlays; i++)
- {
- Lisp_Object tem;
- Lisp_Object overlay;
-
- overlay = overlay_vec[i];
- if (OVERLAY_VALID (overlay)
- && OVERLAY_POSITION (OVERLAY_START (overlay)) > 0
- && OVERLAY_POSITION (OVERLAY_END (overlay)) > 0)
- {
- /* If we're interested in a specific window, then ignore
- overlays that are limited to some other window. */
- if (w)
- {
- Lisp_Object window;
-
- window = Foverlay_get (overlay, Qwindow);
- if (WINDOWP (window) && XWINDOW (window) != w)
- continue;
- }
-
- /* This overlay is good and counts: put it into sortvec. */
- sortvec[j].overlay = overlay;
- sortvec[j].beg = OVERLAY_POSITION (OVERLAY_START (overlay));
- sortvec[j].end = OVERLAY_POSITION (OVERLAY_END (overlay));
- tem = Foverlay_get (overlay, Qpriority);
- if (INTEGERP (tem))
- sortvec[j].priority = XINT (tem);
- else
- sortvec[j].priority = 0;
- j++;
- }
- }
- noverlays = j;
-
- /* Sort the overlays into the proper order: increasing priority. */
-
- if (noverlays > 1)
- qsort (sortvec, noverlays, sizeof (struct sortvec), compare_overlays);
-
- for (i = 0; i < noverlays; i++)
- overlay_vec[i] = sortvec[i].overlay;
- return (noverlays);
-}
-
-struct sortstr
-{
- Lisp_Object string, string2;
- int size;
- int priority;
-};
-
-struct sortstrlist
-{
- struct sortstr *buf; /* An array that expands as needed; never freed. */
- int size; /* Allocated length of that array. */
- int used; /* How much of the array is currently in use. */
- int bytes; /* Total length of the strings in buf. */
-};
-
-/* Buffers for storing information about the overlays touching a given
- position. These could be automatic variables in overlay_strings, but
- it's more efficient to hold onto the memory instead of repeatedly
- allocating and freeing it. */
-static struct sortstrlist overlay_heads, overlay_tails;
-static char *overlay_str_buf;
-
-/* Allocated length of overlay_str_buf. */
-static int overlay_str_len;
-
-/* A comparison function suitable for passing to qsort. */
-static int
-cmp_for_strings (as1, as2)
- char *as1, *as2;
-{
- struct sortstr *s1 = (struct sortstr *)as1;
- struct sortstr *s2 = (struct sortstr *)as2;
- if (s1->size != s2->size)
- return s2->size - s1->size;
- if (s1->priority != s2->priority)
- return s1->priority - s2->priority;
- return 0;
-}
-
-static void
-record_overlay_string (ssl, str, str2, pri, size)
- struct sortstrlist *ssl;
- Lisp_Object str, str2, pri;
- int size;
-{
- if (ssl->used == ssl->size)
- {
- if (ssl->buf)
- ssl->size *= 2;
- else
- ssl->size = 5;
- ssl->buf = ((struct sortstr *)
- xrealloc (ssl->buf, ssl->size * sizeof (struct sortstr)));
- }
- ssl->buf[ssl->used].string = str;
- ssl->buf[ssl->used].string2 = str2;
- ssl->buf[ssl->used].size = size;
- ssl->buf[ssl->used].priority = (INTEGERP (pri) ? XINT (pri) : 0);
- ssl->used++;
- ssl->bytes += XSTRING (str)->size;
- if (STRINGP (str2))
- ssl->bytes += XSTRING (str2)->size;
-}
-
-/* Return the concatenation of the strings associated with overlays that
- begin or end at POS, ignoring overlays that are specific to a window
- other than W. The strings are concatenated in the appropriate order:
- shorter overlays nest inside longer ones, and higher priority inside
- lower. Normally all of the after-strings come first, but zero-sized
- overlays have their after-strings ride along with the before-strings
- because it would look strange to print them inside-out.
-
- Returns the string length, and stores the contents indirectly through
- PSTR, if that variable is non-null. The string may be overwritten by
- subsequent calls. */
-
-int
-overlay_strings (pos, w, pstr)
- int pos;
- struct window *w;
- unsigned char **pstr;
-{
- Lisp_Object ov, overlay, window, str;
- int startpos, endpos;
-
- overlay_heads.used = overlay_heads.bytes = 0;
- overlay_tails.used = overlay_tails.bytes = 0;
- for (ov = current_buffer->overlays_before; CONSP (ov); ov = XCONS (ov)->cdr)
- {
- overlay = XCONS (ov)->car;
- if (!OVERLAYP (overlay))
- abort ();
-
- startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
- endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
- if (endpos < pos)
- break;
- if (endpos != pos && startpos != pos)
- continue;
- window = Foverlay_get (overlay, Qwindow);
- if (WINDOWP (window) && XWINDOW (window) != w)
- continue;
- if (startpos == pos
- && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str)))
- record_overlay_string (&overlay_heads, str,
- (startpos == endpos
- ? Foverlay_get (overlay, Qafter_string)
- : Qnil),
- Foverlay_get (overlay, Qpriority),
- endpos - startpos);
- else if (endpos == pos
- && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str)))
- record_overlay_string (&overlay_tails, str, Qnil,
- Foverlay_get (overlay, Qpriority),
- endpos - startpos);
- }
- for (ov = current_buffer->overlays_after; CONSP (ov); ov = XCONS (ov)->cdr)
- {
- overlay = XCONS (ov)->car;
- if (!OVERLAYP (overlay))
- abort ();
-
- startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
- endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
- if (startpos > pos)
- break;
- if (endpos != pos && startpos != pos)
- continue;
- window = Foverlay_get (overlay, Qwindow);
- if (WINDOWP (window) && XWINDOW (window) != w)
- continue;
- if (startpos == pos
- && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str)))
- record_overlay_string (&overlay_heads, str,
- (startpos == endpos
- ? Foverlay_get (overlay, Qafter_string)
- : Qnil),
- Foverlay_get (overlay, Qpriority),
- endpos - startpos);
- else if (endpos == pos
- && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str)))
- record_overlay_string (&overlay_tails, str, Qnil,
- Foverlay_get (overlay, Qpriority),
- endpos - startpos);
- }
- if (overlay_tails.used > 1)
- qsort (overlay_tails.buf, overlay_tails.used, sizeof (struct sortstr),
- cmp_for_strings);
- if (overlay_heads.used > 1)
- qsort (overlay_heads.buf, overlay_heads.used, sizeof (struct sortstr),
- cmp_for_strings);
- if (overlay_heads.bytes || overlay_tails.bytes)
- {
- Lisp_Object tem;
- int i;
- char *p;
- int total = overlay_heads.bytes + overlay_tails.bytes;
-
- if (total > overlay_str_len)
- overlay_str_buf = (char *)xrealloc (overlay_str_buf,
- overlay_str_len = total);
- p = overlay_str_buf;
- for (i = overlay_tails.used; --i >= 0;)
- {
- tem = overlay_tails.buf[i].string;
- bcopy (XSTRING (tem)->data, p, XSTRING (tem)->size);
- p += XSTRING (tem)->size;
- }
- for (i = 0; i < overlay_heads.used; ++i)
- {
- tem = overlay_heads.buf[i].string;
- bcopy (XSTRING (tem)->data, p, XSTRING (tem)->size);
- p += XSTRING (tem)->size;
- tem = overlay_heads.buf[i].string2;
- if (STRINGP (tem))
- {
- bcopy (XSTRING (tem)->data, p, XSTRING (tem)->size);
- p += XSTRING (tem)->size;
- }
- }
- if (p != overlay_str_buf + total)
- abort ();
- if (pstr)
- *pstr = overlay_str_buf;
- return total;
- }
- return 0;
-}
-
-/* Shift overlays in BUF's overlay lists, to center the lists at POS. */
-
-void
-recenter_overlay_lists (buf, pos)
- struct buffer *buf;
- int pos;
-{
- Lisp_Object overlay, tail, next, prev, beg, end;
-
- /* See if anything in overlays_before should move to overlays_after. */
-
- /* We don't strictly need prev in this loop; it should always be nil.
- But we use it for symmetry and in case that should cease to be true
- with some future change. */
- prev = Qnil;
- for (tail = buf->overlays_before;
- CONSP (tail);
- prev = tail, tail = next)
- {
- next = XCONS (tail)->cdr;
- overlay = XCONS (tail)->car;
-
- /* If the overlay is not valid, get rid of it. */
- if (!OVERLAY_VALID (overlay))
-#if 1
- abort ();
-#else
- {
- /* Splice the cons cell TAIL out of overlays_before. */
- if (!NILP (prev))
- XCONS (prev)->cdr = next;
- else
- buf->overlays_before = next;
- tail = prev;
- continue;
- }
-#endif
-
- beg = OVERLAY_START (overlay);
- end = OVERLAY_END (overlay);
-
- if (OVERLAY_POSITION (end) > pos)
- {
- /* OVERLAY needs to be moved. */
- int where = OVERLAY_POSITION (beg);
- Lisp_Object other, other_prev;
-
- /* Splice the cons cell TAIL out of overlays_before. */
- if (!NILP (prev))
- XCONS (prev)->cdr = next;
- else
- buf->overlays_before = next;
-
- /* Search thru overlays_after for where to put it. */
- other_prev = Qnil;
- for (other = buf->overlays_after;
- CONSP (other);
- other_prev = other, other = XCONS (other)->cdr)
- {
- Lisp_Object otherbeg, otheroverlay, follower;
- int win;
-
- otheroverlay = XCONS (other)->car;
- if (! OVERLAY_VALID (otheroverlay))
- abort ();
-
- otherbeg = OVERLAY_START (otheroverlay);
- if (OVERLAY_POSITION (otherbeg) >= where)
- break;
- }
-
- /* Add TAIL to overlays_after before OTHER. */
- XCONS (tail)->cdr = other;
- if (!NILP (other_prev))
- XCONS (other_prev)->cdr = tail;
- else
- buf->overlays_after = tail;
- tail = prev;
- }
- else
- /* We've reached the things that should stay in overlays_before.
- All the rest of overlays_before must end even earlier,
- so stop now. */
- break;
- }
-
- /* See if anything in overlays_after should be in overlays_before. */
- prev = Qnil;
- for (tail = buf->overlays_after;
- CONSP (tail);
- prev = tail, tail = next)
- {
- next = XCONS (tail)->cdr;
- overlay = XCONS (tail)->car;
-
- /* If the overlay is not valid, get rid of it. */
- if (!OVERLAY_VALID (overlay))
-#if 1
- abort ();
-#else
- {
- /* Splice the cons cell TAIL out of overlays_after. */
- if (!NILP (prev))
- XCONS (prev)->cdr = next;
- else
- buf->overlays_after = next;
- tail = prev;
- continue;
- }
-#endif
-
- beg = OVERLAY_START (overlay);
- end = OVERLAY_END (overlay);
-
- /* Stop looking, when we know that nothing further
- can possibly end before POS. */
- if (OVERLAY_POSITION (beg) > pos)
- break;
-
- if (OVERLAY_POSITION (end) <= pos)
- {
- /* OVERLAY needs to be moved. */
- int where = OVERLAY_POSITION (end);
- Lisp_Object other, other_prev;
-
- /* Splice the cons cell TAIL out of overlays_after. */
- if (!NILP (prev))
- XCONS (prev)->cdr = next;
- else
- buf->overlays_after = next;
-
- /* Search thru overlays_before for where to put it. */
- other_prev = Qnil;
- for (other = buf->overlays_before;
- CONSP (other);
- other_prev = other, other = XCONS (other)->cdr)
- {
- Lisp_Object otherend, otheroverlay;
- int win;
-
- otheroverlay = XCONS (other)->car;
- if (! OVERLAY_VALID (otheroverlay))
- abort ();
-
- otherend = OVERLAY_END (otheroverlay);
- if (OVERLAY_POSITION (otherend) <= where)
- break;
- }
-
- /* Add TAIL to overlays_before before OTHER. */
- XCONS (tail)->cdr = other;
- if (!NILP (other_prev))
- XCONS (other_prev)->cdr = tail;
- else
- buf->overlays_before = tail;
- tail = prev;
- }
- }
-
- XSETFASTINT (buf->overlay_center, pos);
-}
-
-void
-adjust_overlays_for_insert (pos, length)
- int pos;
- int length;
-{
- /* After an insertion, the lists are still sorted properly,
- but we may need to update the value of the overlay center. */
- if (XFASTINT (current_buffer->overlay_center) >= pos)
- XSETFASTINT (current_buffer->overlay_center,
- XFASTINT (current_buffer->overlay_center) + length);
-}
-
-void
-adjust_overlays_for_delete (pos, length)
- int pos;
- int length;
-{
- if (XFASTINT (current_buffer->overlay_center) < pos)
- /* The deletion was to our right. No change needed; the before- and
- after-lists are still consistent. */
- ;
- else if (XFASTINT (current_buffer->overlay_center) > pos + length)
- /* The deletion was to our left. We need to adjust the center value
- to account for the change in position, but the lists are consistent
- given the new value. */
- XSETFASTINT (current_buffer->overlay_center,
- XFASTINT (current_buffer->overlay_center) - length);
- else
- /* We're right in the middle. There might be things on the after-list
- that now belong on the before-list. Recentering will move them,
- and also update the center point. */
- recenter_overlay_lists (current_buffer, pos);
-}
-
-/* Fix up overlays that were garbled as a result of permuting markers
- in the range START through END. Any overlay with at least one
- endpoint in this range will need to be unlinked from the overlay
- list and reinserted in its proper place.
- Such an overlay might even have negative size at this point.
- If so, we'll reverse the endpoints. Can you think of anything
- better to do in this situation? */
-void
-fix_overlays_in_range (start, end)
- register int start, end;
-{
- Lisp_Object tem, overlay;
- Lisp_Object before_list, after_list;
- Lisp_Object *ptail, *pbefore = &before_list, *pafter = &after_list;
- int startpos, endpos;
-
- /* This algorithm shifts links around instead of consing and GCing.
- The loop invariant is that before_list (resp. after_list) is a
- well-formed list except that its last element, the one that
- *pbefore (resp. *pafter) points to, is still uninitialized.
- So it's not a bug that before_list isn't initialized, although
- it may look strange. */
- for (ptail = &current_buffer->overlays_before; CONSP (*ptail);)
- {
- overlay = XCONS (*ptail)->car;
- endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
- if (endpos < start)
- break;
- startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
- if (endpos < end
- || (startpos >= start && startpos < end))
- {
- /* If the overlay is backwards, fix that now. */
- if (startpos > endpos)
- {
- int tem;
- Fset_marker (OVERLAY_START (overlay), endpos, Qnil);
- Fset_marker (OVERLAY_END (overlay), startpos, Qnil);
- tem = startpos; startpos = endpos; endpos = tem;
- }
- /* Add it to the end of the wrong list. Later on,
- recenter_overlay_lists will move it to the right place. */
- if (endpos < XINT (current_buffer->overlay_center))
- {
- *pafter = *ptail;
- pafter = &XCONS (*ptail)->cdr;
- }
- else
- {
- *pbefore = *ptail;
- pbefore = &XCONS (*ptail)->cdr;
- }
- *ptail = XCONS (*ptail)->cdr;
- }
- else
- ptail = &XCONS (*ptail)->cdr;
- }
- for (ptail = &current_buffer->overlays_after; CONSP (*ptail);)
- {
- overlay = XCONS (*ptail)->car;
- startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
- if (startpos >= end)
- break;
- endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
- if (startpos >= start
- || (endpos >= start && endpos < end))
- {
- if (startpos > endpos)
- {
- int tem;
- Fset_marker (OVERLAY_START (overlay), endpos, Qnil);
- Fset_marker (OVERLAY_END (overlay), startpos, Qnil);
- tem = startpos; startpos = endpos; endpos = tem;
- }
- if (endpos < XINT (current_buffer->overlay_center))
- {
- *pafter = *ptail;
- pafter = &XCONS (*ptail)->cdr;
- }
- else
- {
- *pbefore = *ptail;
- pbefore = &XCONS (*ptail)->cdr;
- }
- *ptail = XCONS (*ptail)->cdr;
- }
- else
- ptail = &XCONS (*ptail)->cdr;
- }
-
- /* Splice the constructed (wrong) lists into the buffer's lists,
- and let the recenter function make it sane again. */
- *pbefore = current_buffer->overlays_before;
- current_buffer->overlays_before = before_list;
- recenter_overlay_lists (current_buffer,
- XINT (current_buffer->overlay_center));
-
- *pafter = current_buffer->overlays_after;
- current_buffer->overlays_after = after_list;
- recenter_overlay_lists (current_buffer,
- XINT (current_buffer->overlay_center));
-}
-
-DEFUN ("overlayp", Foverlayp, Soverlayp, 1, 1, 0,
- "Return t if OBJECT is an overlay.")
- (object)
- Lisp_Object object;
-{
- return (OVERLAYP (object) ? Qt : Qnil);
-}
-
-DEFUN ("make-overlay", Fmake_overlay, Smake_overlay, 2, 5, 0,
- "Create a new overlay with range BEG to END in BUFFER.\n\
-If omitted, BUFFER defaults to the current buffer.\n\
-BEG and END may be integers or markers.\n\
-The fourth arg FRONT-ADVANCE, if non-nil, makes the\n\
-front delimiter advance when text is inserted there.\n\
-The fifth arg REAR-ADVANCE, if non-nil, makes the\n\
-rear delimiter advance when text is inserted there.")
- (beg, end, buffer, front_advance, rear_advance)
- Lisp_Object beg, end, buffer;
- Lisp_Object front_advance, rear_advance;
-{
- Lisp_Object overlay;
- struct buffer *b;
-
- if (NILP (buffer))
- XSETBUFFER (buffer, current_buffer);
- else
- CHECK_BUFFER (buffer, 2);
- if (MARKERP (beg)
- && ! EQ (Fmarker_buffer (beg), buffer))
- error ("Marker points into wrong buffer");
- if (MARKERP (end)
- && ! EQ (Fmarker_buffer (end), buffer))
- error ("Marker points into wrong buffer");
-
- CHECK_NUMBER_COERCE_MARKER (beg, 1);
- CHECK_NUMBER_COERCE_MARKER (end, 1);
-
- if (XINT (beg) > XINT (end))
- {
- Lisp_Object temp;
- temp = beg; beg = end; end = temp;
- }
-
- b = XBUFFER (buffer);
-
- beg = Fset_marker (Fmake_marker (), beg, buffer);
- end = Fset_marker (Fmake_marker (), end, buffer);
-
- if (!NILP (front_advance))
- XMARKER (beg)->insertion_type = 1;
- if (!NILP (rear_advance))
- XMARKER (end)->insertion_type = 1;
-
- overlay = allocate_misc ();
- XMISCTYPE (overlay) = Lisp_Misc_Overlay;
- XOVERLAY (overlay)->start = beg;
- XOVERLAY (overlay)->end = end;
- XOVERLAY (overlay)->plist = Qnil;
-
- /* Put the new overlay on the wrong list. */
- end = OVERLAY_END (overlay);
- if (OVERLAY_POSITION (end) < XINT (b->overlay_center))
- b->overlays_after = Fcons (overlay, b->overlays_after);
- else
- b->overlays_before = Fcons (overlay, b->overlays_before);
-
- /* This puts it in the right list, and in the right order. */
- recenter_overlay_lists (b, XINT (b->overlay_center));
-
- /* We don't need to redisplay the region covered by the overlay, because
- the overlay has no properties at the moment. */
-
- return overlay;
-}
-
-/* Mark a section of BUF as needing redisplay because of overlays changes. */
-
-static void
-modify_overlay (buf, start, end)
- struct buffer *buf;
- int start, end;
-{
- if (start == end)
- return;
-
- if (start > end)
- {
- int temp = start;
- start = end; end = temp;
- }
-
- /* If this is a buffer not in the selected window,
- we must do other windows. */
- if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
- windows_or_buffers_changed = 1;
- /* If it's not current, we can't use beg_unchanged, end_unchanged for it. */
- else if (buf != current_buffer)
- windows_or_buffers_changed = 1;
- /* If multiple windows show this buffer, we must do other windows. */
- else if (buffer_shared > 1)
- windows_or_buffers_changed = 1;
- else
- {
- if (unchanged_modified == MODIFF
- && overlay_unchanged_modified == OVERLAY_MODIFF)
- {
- beg_unchanged = start - BEG;
- end_unchanged = Z - end;
- }
- else
- {
- if (Z - end < end_unchanged)
- end_unchanged = Z - end;
- if (start - BEG < beg_unchanged)
- beg_unchanged = start - BEG;
- }
- }
-
- ++OVERLAY_MODIFF;
-}
-
-
-DEFUN ("move-overlay", Fmove_overlay, Smove_overlay, 3, 4, 0,
- "Set the endpoints of OVERLAY to BEG and END in BUFFER.\n\
-If BUFFER is omitted, leave OVERLAY in the same buffer it inhabits now.\n\
-If BUFFER is omitted, and OVERLAY is in no buffer, put it in the current\n\
-buffer.")
- (overlay, beg, end, buffer)
- Lisp_Object overlay, beg, end, buffer;
-{
- struct buffer *b, *ob;
- Lisp_Object obuffer;
- int count = specpdl_ptr - specpdl;
-
- CHECK_OVERLAY (overlay, 0);
- if (NILP (buffer))
- buffer = Fmarker_buffer (OVERLAY_START (overlay));
- if (NILP (buffer))
- XSETBUFFER (buffer, current_buffer);
- CHECK_BUFFER (buffer, 3);
-
- if (MARKERP (beg)
- && ! EQ (Fmarker_buffer (beg), buffer))
- error ("Marker points into wrong buffer");
- if (MARKERP (end)
- && ! EQ (Fmarker_buffer (end), buffer))
- error ("Marker points into wrong buffer");
-
- CHECK_NUMBER_COERCE_MARKER (beg, 1);
- CHECK_NUMBER_COERCE_MARKER (end, 1);
-
- if (XINT (beg) == XINT (end) && ! NILP (Foverlay_get (overlay, Qevaporate)))
- return Fdelete_overlay (overlay);
-
- if (XINT (beg) > XINT (end))
- {
- Lisp_Object temp;
- temp = beg; beg = end; end = temp;
- }
-
- specbind (Qinhibit_quit, Qt);
-
- obuffer = Fmarker_buffer (OVERLAY_START (overlay));
- b = XBUFFER (buffer);
- ob = XBUFFER (obuffer);
-
- /* If the overlay has changed buffers, do a thorough redisplay. */
- if (!EQ (buffer, obuffer))
- {
- /* Redisplay where the overlay was. */
- if (!NILP (obuffer))
- {
- Lisp_Object o_beg;
- Lisp_Object o_end;
-
- o_beg = OVERLAY_START (overlay);
- o_end = OVERLAY_END (overlay);
- o_beg = OVERLAY_POSITION (o_beg);
- o_end = OVERLAY_POSITION (o_end);
-
- modify_overlay (ob, XINT (o_beg), XINT (o_end));
- }
-
- /* Redisplay where the overlay is going to be. */
- modify_overlay (b, XINT (beg), XINT (end));
- }
- else
- /* Redisplay the area the overlay has just left, or just enclosed. */
- {
- Lisp_Object o_beg;
- Lisp_Object o_end;
- int change_beg, change_end;
-
- o_beg = OVERLAY_START (overlay);
- o_end = OVERLAY_END (overlay);
- o_beg = OVERLAY_POSITION (o_beg);
- o_end = OVERLAY_POSITION (o_end);
-
- if (XINT (o_beg) == XINT (beg))
- modify_overlay (b, XINT (o_end), XINT (end));
- else if (XINT (o_end) == XINT (end))
- modify_overlay (b, XINT (o_beg), XINT (beg));
- else
- {
- if (XINT (beg) < XINT (o_beg)) o_beg = beg;
- if (XINT (end) > XINT (o_end)) o_end = end;
- modify_overlay (b, XINT (o_beg), XINT (o_end));
- }
- }
-
- if (!NILP (obuffer))
- {
- ob->overlays_before = Fdelq (overlay, ob->overlays_before);
- ob->overlays_after = Fdelq (overlay, ob->overlays_after);
- }
-
- Fset_marker (OVERLAY_START (overlay), beg, buffer);
- Fset_marker (OVERLAY_END (overlay), end, buffer);
-
- /* Put the overlay on the wrong list. */
- end = OVERLAY_END (overlay);
- if (OVERLAY_POSITION (end) < XINT (b->overlay_center))
- b->overlays_after = Fcons (overlay, b->overlays_after);
- else
- b->overlays_before = Fcons (overlay, b->overlays_before);
-
- /* This puts it in the right list, and in the right order. */
- recenter_overlay_lists (b, XINT (b->overlay_center));
-
- return unbind_to (count, overlay);
-}
-
-DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
- "Delete the overlay OVERLAY from its buffer.")
- (overlay)
- Lisp_Object overlay;
-{
- Lisp_Object buffer;
- struct buffer *b;
- int count = specpdl_ptr - specpdl;
-
- CHECK_OVERLAY (overlay, 0);
-
- buffer = Fmarker_buffer (OVERLAY_START (overlay));
- if (NILP (buffer))
- return Qnil;
-
- b = XBUFFER (buffer);
-
- specbind (Qinhibit_quit, Qt);
-
- b->overlays_before = Fdelq (overlay, b->overlays_before);
- b->overlays_after = Fdelq (overlay, b->overlays_after);
-
- modify_overlay (b,
- marker_position (OVERLAY_START (overlay)),
- marker_position (OVERLAY_END (overlay)));
-
- Fset_marker (OVERLAY_START (overlay), Qnil, Qnil);
- Fset_marker (OVERLAY_END (overlay), Qnil, Qnil);
-
- return unbind_to (count, Qnil);
-}
-
-/* Overlay dissection functions. */
-
-DEFUN ("overlay-start", Foverlay_start, Soverlay_start, 1, 1, 0,
- "Return the position at which OVERLAY starts.")
- (overlay)
- Lisp_Object overlay;
-{
- CHECK_OVERLAY (overlay, 0);
-
- return (Fmarker_position (OVERLAY_START (overlay)));
-}
-
-DEFUN ("overlay-end", Foverlay_end, Soverlay_end, 1, 1, 0,
- "Return the position at which OVERLAY ends.")
- (overlay)
- Lisp_Object overlay;
-{
- CHECK_OVERLAY (overlay, 0);
-
- return (Fmarker_position (OVERLAY_END (overlay)));
-}
-
-DEFUN ("overlay-buffer", Foverlay_buffer, Soverlay_buffer, 1, 1, 0,
- "Return the buffer OVERLAY belongs to.")
- (overlay)
- Lisp_Object overlay;
-{
- CHECK_OVERLAY (overlay, 0);
-
- return Fmarker_buffer (OVERLAY_START (overlay));
-}
-
-DEFUN ("overlay-properties", Foverlay_properties, Soverlay_properties, 1, 1, 0,
- "Return a list of the properties on OVERLAY.\n\
-This is a copy of OVERLAY's plist; modifying its conses has no effect on\n\
-OVERLAY.")
- (overlay)
- Lisp_Object overlay;
-{
- CHECK_OVERLAY (overlay, 0);
-
- return Fcopy_sequence (XOVERLAY (overlay)->plist);
-}
-
-
-DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0,
- "Return a list of the overlays that contain position POS.")
- (pos)
- Lisp_Object pos;
-{
- int noverlays;
- Lisp_Object *overlay_vec;
- int len;
- Lisp_Object result;
-
- CHECK_NUMBER_COERCE_MARKER (pos, 0);
-
- len = 10;
- overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
-
- /* Put all the overlays we want in a vector in overlay_vec.
- Store the length in len. */
- noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
- (int *) 0, (int *) 0);
-
- /* Make a list of them all. */
- result = Flist (noverlays, overlay_vec);
-
- xfree (overlay_vec);
- return result;
-}
-
-DEFUN ("overlays-in", Foverlays_in, Soverlays_in, 2, 2, 0,
- "Return a list of the overlays that overlap the region BEG ... END.\n\
-Overlap means that at least one character is contained within the overlay\n\
-and also contained within the specified region.\n\
-Empty overlays are included in the result if they are located at BEG\n\
-or between BEG and END.")
- (beg, end)
- Lisp_Object beg, end;
-{
- int noverlays;
- Lisp_Object *overlay_vec;
- int len;
- Lisp_Object result;
-
- CHECK_NUMBER_COERCE_MARKER (beg, 0);
- CHECK_NUMBER_COERCE_MARKER (end, 0);
-
- len = 10;
- overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
-
- /* Put all the overlays we want in a vector in overlay_vec.
- Store the length in len. */
- noverlays = overlays_in (XINT (beg), XINT (end), 1, &overlay_vec, &len,
- (int *) 0, (int *) 0);
-
- /* Make a list of them all. */
- result = Flist (noverlays, overlay_vec);
-
- xfree (overlay_vec);
- return result;
-}
-
-DEFUN ("next-overlay-change", Fnext_overlay_change, Snext_overlay_change,
- 1, 1, 0,
- "Return the next position after POS where an overlay starts or ends.\n\
-If there are no more overlay boundaries after POS, return (point-max).")
- (pos)
- Lisp_Object pos;
-{
- int noverlays;
- int endpos;
- Lisp_Object *overlay_vec;
- int len;
- int i;
-
- CHECK_NUMBER_COERCE_MARKER (pos, 0);
-
- len = 10;
- overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
-
- /* Put all the overlays we want in a vector in overlay_vec.
- Store the length in len.
- endpos gets the position where the next overlay starts. */
- noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
- &endpos, (int *) 0);
-
- /* If any of these overlays ends before endpos,
- use its ending point instead. */
- for (i = 0; i < noverlays; i++)
- {
- Lisp_Object oend;
- int oendpos;
-
- oend = OVERLAY_END (overlay_vec[i]);
- oendpos = OVERLAY_POSITION (oend);
- if (oendpos < endpos)
- endpos = oendpos;
- }
-
- xfree (overlay_vec);
- return make_number (endpos);
-}
-
-DEFUN ("previous-overlay-change", Fprevious_overlay_change,
- Sprevious_overlay_change, 1, 1, 0,
- "Return the previous position before POS where an overlay starts or ends.\n\
-If there are no more overlay boundaries before POS, return (point-min).")
- (pos)
- Lisp_Object pos;
-{
- int noverlays;
- int prevpos;
- Lisp_Object *overlay_vec;
- int len;
- int i;
- Lisp_Object tail;
-
- CHECK_NUMBER_COERCE_MARKER (pos, 0);
-
- len = 10;
- overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
-
- /* At beginning of buffer, we know the answer;
- avoid bug subtracting 1 below. */
- if (XINT (pos) == BEGV)
- return pos;
-
- /* Put all the overlays we want in a vector in overlay_vec.
- Store the length in len.
- prevpos gets the position of an overlay end. */
- noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
- (int *) 0, &prevpos);
-
- /* If any of these overlays starts after prevpos,
- maybe use its starting point instead. */
- for (i = 0; i < noverlays; i++)
- {
- Lisp_Object ostart;
- int ostartpos;
-
- ostart = OVERLAY_START (overlay_vec[i]);
- ostartpos = OVERLAY_POSITION (ostart);
- if (ostartpos > prevpos && ostartpos < XINT (pos))
- prevpos = ostartpos;
- }
-
- /* If any overlay ends at pos, consider its starting point too. */
- for (tail = current_buffer->overlays_before;
- GC_CONSP (tail);
- tail = XCONS (tail)->cdr)
- {
- Lisp_Object overlay, ostart;
- int ostartpos;
-
- overlay = XCONS (tail)->car;
-
- ostart = OVERLAY_START (overlay);
- ostartpos = OVERLAY_POSITION (ostart);
- if (ostartpos > prevpos && ostartpos < XINT (pos))
- prevpos = ostartpos;
- }
-
- xfree (overlay_vec);
- return make_number (prevpos);
-}
-
-/* These functions are for debugging overlays. */
-
-DEFUN ("overlay-lists", Foverlay_lists, Soverlay_lists, 0, 0, 0,
- "Return a pair of lists giving all the overlays of the current buffer.\n\
-The car has all the overlays before the overlay center;\n\
-the cdr has all the overlays after the overlay center.\n\
-Recentering overlays moves overlays between these lists.\n\
-The lists you get are copies, so that changing them has no effect.\n\
-However, the overlays you get are the real objects that the buffer uses.")
- ()
-{
- Lisp_Object before, after;
- before = current_buffer->overlays_before;
- if (CONSP (before))
- before = Fcopy_sequence (before);
- after = current_buffer->overlays_after;
- if (CONSP (after))
- after = Fcopy_sequence (after);
-
- return Fcons (before, after);
-}
-
-DEFUN ("overlay-recenter", Foverlay_recenter, Soverlay_recenter, 1, 1, 0,
- "Recenter the overlays of the current buffer around position POS.")
- (pos)
- Lisp_Object pos;
-{
- CHECK_NUMBER_COERCE_MARKER (pos, 0);
-
- recenter_overlay_lists (current_buffer, XINT (pos));
- return Qnil;
-}
-
-DEFUN ("overlay-get", Foverlay_get, Soverlay_get, 2, 2, 0,
- "Get the property of overlay OVERLAY with property name PROP.")
- (overlay, prop)
- Lisp_Object overlay, prop;
-{
- Lisp_Object plist, fallback;
-
- CHECK_OVERLAY (overlay, 0);
-
- fallback = Qnil;
-
- for (plist = XOVERLAY (overlay)->plist;
- CONSP (plist) && CONSP (XCONS (plist)->cdr);
- plist = XCONS (XCONS (plist)->cdr)->cdr)
- {
- if (EQ (XCONS (plist)->car, prop))
- return XCONS (XCONS (plist)->cdr)->car;
- else if (EQ (XCONS (plist)->car, Qcategory))
- {
- Lisp_Object tem;
- tem = Fcar (Fcdr (plist));
- if (SYMBOLP (tem))
- fallback = Fget (tem, prop);
- }
- }
-
- return fallback;
-}
-
-DEFUN ("overlay-put", Foverlay_put, Soverlay_put, 3, 3, 0,
- "Set one property of overlay OVERLAY: give property PROP value VALUE.")
- (overlay, prop, value)
- Lisp_Object overlay, prop, value;
-{
- Lisp_Object tail, buffer;
- int changed;
-
- CHECK_OVERLAY (overlay, 0);
-
- buffer = Fmarker_buffer (OVERLAY_START (overlay));
-
- for (tail = XOVERLAY (overlay)->plist;
- CONSP (tail) && CONSP (XCONS (tail)->cdr);
- tail = XCONS (XCONS (tail)->cdr)->cdr)
- if (EQ (XCONS (tail)->car, prop))
- {
- changed = !EQ (XCONS (XCONS (tail)->cdr)->car, value);
- XCONS (XCONS (tail)->cdr)->car = value;
- goto found;
- }
- /* It wasn't in the list, so add it to the front. */
- changed = !NILP (value);
- XOVERLAY (overlay)->plist
- = Fcons (prop, Fcons (value, XOVERLAY (overlay)->plist));
- found:
- if (! NILP (buffer))
- {
- if (changed)
- modify_overlay (XBUFFER (buffer),
- marker_position (OVERLAY_START (overlay)),
- marker_position (OVERLAY_END (overlay)));
- if (EQ (prop, Qevaporate) && ! NILP (value)
- && (OVERLAY_POSITION (OVERLAY_START (overlay))
- == OVERLAY_POSITION (OVERLAY_END (overlay))))
- Fdelete_overlay (overlay);
- }
- return value;
-}
-
-/* Subroutine of report_overlay_modification. */
-
-/* Lisp vector holding overlay hook functions to call.
- Vector elements come in pairs.
- Each even-index element is a list of hook functions.
- The following odd-index element is the overlay they came from.
-
- Before the buffer change, we fill in this vector
- as we call overlay hook functions.
- After the buffer change, we get the functions to call from this vector.
- This way we always call the same functions before and after the change. */
-static Lisp_Object last_overlay_modification_hooks;
-
-/* Number of elements actually used in last_overlay_modification_hooks. */
-static int last_overlay_modification_hooks_used;
-
-/* Add one functionlist/overlay pair
- to the end of last_overlay_modification_hooks. */
-
-static void
-add_overlay_mod_hooklist (functionlist, overlay)
- Lisp_Object functionlist, overlay;
-{
- int oldsize = XVECTOR (last_overlay_modification_hooks)->size;
-
- if (last_overlay_modification_hooks_used == oldsize)
- {
- Lisp_Object old;
- old = last_overlay_modification_hooks;
- last_overlay_modification_hooks
- = Fmake_vector (make_number (oldsize * 2), Qnil);
- bcopy (XVECTOR (old)->contents,
- XVECTOR (last_overlay_modification_hooks)->contents,
- sizeof (Lisp_Object) * oldsize);
- }
- XVECTOR (last_overlay_modification_hooks)->contents[last_overlay_modification_hooks_used++] = functionlist;
- XVECTOR (last_overlay_modification_hooks)->contents[last_overlay_modification_hooks_used++] = overlay;
-}
-
-/* Run the modification-hooks of overlays that include
- any part of the text in START to END.
- If this change is an insertion, also
- run the insert-before-hooks of overlay starting at END,
- and the insert-after-hooks of overlay ending at START.
-
- This is called both before and after the modification.
- AFTER is nonzero when we call after the modification.
-
- ARG1, ARG2, ARG3 are arguments to pass to the hook functions.
- When AFTER is nonzero, they are the start position,
- the position after the inserted new text,
- and the length of deleted or replaced old text. */
-
-void
-report_overlay_modification (start, end, after, arg1, arg2, arg3)
- Lisp_Object start, end;
- int after;
- Lisp_Object arg1, arg2, arg3;
-{
- Lisp_Object prop, overlay, tail;
- /* 1 if this change is an insertion. */
- int insertion = (after ? XFASTINT (arg3) == 0 : EQ (start, end));
- int tail_copied;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
-
- overlay = Qnil;
- tail = Qnil;
- GCPRO5 (overlay, tail, arg1, arg2, arg3);
-
- if (after)
- {
- /* Call the functions recorded in last_overlay_modification_hooks
- rather than scanning the overlays again.
- First copy the vector contents, in case some of these hooks
- do subsequent modification of the buffer. */
- int size = last_overlay_modification_hooks_used;
- Lisp_Object *copy = (Lisp_Object *) alloca (size * sizeof (Lisp_Object));
- int i;
-
- bcopy (XVECTOR (last_overlay_modification_hooks)->contents,
- copy, size * sizeof (Lisp_Object));
- gcpro1.var = copy;
- gcpro1.nvars = size;
-
- for (i = 0; i < size;)
- {
- Lisp_Object prop, overlay;
- prop = copy[i++];
- overlay = copy[i++];
- call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
- }
- UNGCPRO;
- return;
- }
-
- /* We are being called before a change.
- Scan the overlays to find the functions to call. */
- last_overlay_modification_hooks_used = 0;
- tail_copied = 0;
- for (tail = current_buffer->overlays_before;
- CONSP (tail);
- tail = XCONS (tail)->cdr)
- {
- int startpos, endpos;
- Lisp_Object ostart, oend;
-
- overlay = XCONS (tail)->car;
-
- ostart = OVERLAY_START (overlay);
- oend = OVERLAY_END (overlay);
- endpos = OVERLAY_POSITION (oend);
- if (XFASTINT (start) > endpos)
- break;
- startpos = OVERLAY_POSITION (ostart);
- if (insertion && (XFASTINT (start) == startpos
- || XFASTINT (end) == startpos))
- {
- prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
- if (!NILP (prop))
- {
- /* Copy TAIL in case the hook recenters the overlay lists. */
- if (!tail_copied)
- tail = Fcopy_sequence (tail);
- tail_copied = 1;
- call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
- }
- }
- if (insertion && (XFASTINT (start) == endpos
- || XFASTINT (end) == endpos))
- {
- prop = Foverlay_get (overlay, Qinsert_behind_hooks);
- if (!NILP (prop))
- {
- if (!tail_copied)
- tail = Fcopy_sequence (tail);
- tail_copied = 1;
- call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
- }
- }
- /* Test for intersecting intervals. This does the right thing
- for both insertion and deletion. */
- if (XFASTINT (end) > startpos && XFASTINT (start) < endpos)
- {
- prop = Foverlay_get (overlay, Qmodification_hooks);
- if (!NILP (prop))
- {
- if (!tail_copied)
- tail = Fcopy_sequence (tail);
- tail_copied = 1;
- call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
- }
- }
- }
-
- tail_copied = 0;
- for (tail = current_buffer->overlays_after;
- CONSP (tail);
- tail = XCONS (tail)->cdr)
- {
- int startpos, endpos;
- Lisp_Object ostart, oend;
-
- overlay = XCONS (tail)->car;
-
- ostart = OVERLAY_START (overlay);
- oend = OVERLAY_END (overlay);
- startpos = OVERLAY_POSITION (ostart);
- endpos = OVERLAY_POSITION (oend);
- if (XFASTINT (end) < startpos)
- break;
- if (insertion && (XFASTINT (start) == startpos
- || XFASTINT (end) == startpos))
- {
- prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
- if (!NILP (prop))
- {
- if (!tail_copied)
- tail = Fcopy_sequence (tail);
- tail_copied = 1;
- call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
- }
- }
- if (insertion && (XFASTINT (start) == endpos
- || XFASTINT (end) == endpos))
- {
- prop = Foverlay_get (overlay, Qinsert_behind_hooks);
- if (!NILP (prop))
- {
- if (!tail_copied)
- tail = Fcopy_sequence (tail);
- tail_copied = 1;
- call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
- }
- }
- /* Test for intersecting intervals. This does the right thing
- for both insertion and deletion. */
- if (XFASTINT (end) > startpos && XFASTINT (start) < endpos)
- {
- prop = Foverlay_get (overlay, Qmodification_hooks);
- if (!NILP (prop))
- {
- if (!tail_copied)
- tail = Fcopy_sequence (tail);
- tail_copied = 1;
- call_overlay_mod_hooks (prop, overlay, after, arg1, arg2, arg3);
- }
- }
- }
-
- UNGCPRO;
-}
-
-static void
-call_overlay_mod_hooks (list, overlay, after, arg1, arg2, arg3)
- Lisp_Object list, overlay;
- int after;
- Lisp_Object arg1, arg2, arg3;
-{
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- GCPRO4 (list, arg1, arg2, arg3);
- if (! after)
- add_overlay_mod_hooklist (list, overlay);
-
- while (!NILP (list))
- {
- if (NILP (arg3))
- call4 (Fcar (list), overlay, after ? Qt : Qnil, arg1, arg2);
- else
- call5 (Fcar (list), overlay, after ? Qt : Qnil, arg1, arg2, arg3);
- list = Fcdr (list);
- }
- UNGCPRO;
-}
-
-/* Delete any zero-sized overlays at position POS, if the `evaporate'
- property is set. */
-void
-evaporate_overlays (pos)
- int pos;
-{
- Lisp_Object tail, overlay, hit_list;
-
- hit_list = Qnil;
- if (pos <= XFASTINT (current_buffer->overlay_center))
- for (tail = current_buffer->overlays_before; CONSP (tail);
- tail = XCONS (tail)->cdr)
- {
- int endpos;
- overlay = XCONS (tail)->car;
- endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
- if (endpos < pos)
- break;
- if (endpos == pos && OVERLAY_POSITION (OVERLAY_START (overlay)) == pos
- && ! NILP (Foverlay_get (overlay, Qevaporate)))
- hit_list = Fcons (overlay, hit_list);
- }
- else
- for (tail = current_buffer->overlays_after; CONSP (tail);
- tail = XCONS (tail)->cdr)
- {
- int startpos;
- overlay = XCONS (tail)->car;
- startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
- if (startpos > pos)
- break;
- if (startpos == pos && OVERLAY_POSITION (OVERLAY_END (overlay)) == pos
- && ! NILP (Foverlay_get (overlay, Qevaporate)))
- hit_list = Fcons (overlay, hit_list);
- }
- for (; CONSP (hit_list); hit_list = XCONS (hit_list)->cdr)
- Fdelete_overlay (XCONS (hit_list)->car);
-}
-
-/* Somebody has tried to store a value with an unacceptable type
- into the buffer-local slot with offset OFFSET. */
-void
-buffer_slot_type_mismatch (offset)
- int offset;
-{
- Lisp_Object sym;
- char *type_name;
- sym = *(Lisp_Object *)(offset + (char *)&buffer_local_symbols);
- switch (XINT (*(Lisp_Object *)(offset + (char *)&buffer_local_types)))
- {
- case Lisp_Int: type_name = "integers"; break;
- case Lisp_String: type_name = "strings"; break;
- case Lisp_Symbol: type_name = "symbols"; break;
- default:
- abort ();
- }
-
- error ("only %s should be stored in the buffer-local variable %s",
- type_name, XSYMBOL (sym)->name->data);
-}
-
-init_buffer_once ()
-{
- register Lisp_Object tem;
-
- buffer_permanent_local_flags = 0;
-
- /* Make sure all markable slots in buffer_defaults
- are initialized reasonably, so mark_buffer won't choke. */
- reset_buffer (&buffer_defaults);
- reset_buffer_local_variables (&buffer_defaults, 1);
- reset_buffer (&buffer_local_symbols);
- reset_buffer_local_variables (&buffer_local_symbols, 1);
- /* Prevent GC from getting confused. */
- buffer_defaults.text = &buffer_defaults.own_text;
- buffer_local_symbols.text = &buffer_local_symbols.own_text;
-#ifdef USE_TEXT_PROPERTIES
- BUF_INTERVALS (&buffer_defaults) = 0;
- BUF_INTERVALS (&buffer_local_symbols) = 0;
-#endif
- XSETBUFFER (Vbuffer_defaults, &buffer_defaults);
- XSETBUFFER (Vbuffer_local_symbols, &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_function = Qnil;
- buffer_defaults.selective_display = Qnil;
-#ifndef old
- buffer_defaults.selective_display_ellipses = Qt;
-#endif
- buffer_defaults.abbrev_table = Qnil;
- buffer_defaults.display_table = Qnil;
- buffer_defaults.undo_list = Qnil;
- buffer_defaults.mark_active = Qnil;
- buffer_defaults.file_format = Qnil;
- buffer_defaults.overlays_before = Qnil;
- buffer_defaults.overlays_after = Qnil;
- XSETFASTINT (buffer_defaults.overlay_center, BEG);
-
- XSETFASTINT (buffer_defaults.tab_width, 8);
- buffer_defaults.truncate_lines = Qnil;
- buffer_defaults.ctl_arrow = Qt;
-
-#ifdef DOS_NT
- buffer_defaults.buffer_file_type = Qnil; /* TEXT */
-#endif
- XSETFASTINT (buffer_defaults.fill_column, 70);
- XSETFASTINT (buffer_defaults.left_margin, 0);
- buffer_defaults.cache_long_line_scans = Qnil;
- buffer_defaults.file_truename = Qnil;
-
- /* 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 (EMACS_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);
- XSETINT (buffer_local_flags.filename, -1);
- XSETINT (buffer_local_flags.directory, -1);
- XSETINT (buffer_local_flags.backed_up, -1);
- XSETINT (buffer_local_flags.save_length, -1);
- XSETINT (buffer_local_flags.auto_save_file_name, -1);
- XSETINT (buffer_local_flags.read_only, -1);
- XSETINT (buffer_local_flags.major_mode, -1);
- XSETINT (buffer_local_flags.mode_name, -1);
- XSETINT (buffer_local_flags.undo_list, -1);
- XSETINT (buffer_local_flags.mark_active, -1);
- XSETINT (buffer_local_flags.point_before_scroll, -1);
- XSETINT (buffer_local_flags.file_truename, -1);
- XSETINT (buffer_local_flags.invisibility_spec, -1);
- XSETINT (buffer_local_flags.file_format, -1);
-
- XSETFASTINT (buffer_local_flags.mode_line_format, 1);
- XSETFASTINT (buffer_local_flags.abbrev_mode, 2);
- XSETFASTINT (buffer_local_flags.overwrite_mode, 4);
- XSETFASTINT (buffer_local_flags.case_fold_search, 8);
- XSETFASTINT (buffer_local_flags.auto_fill_function, 0x10);
- XSETFASTINT (buffer_local_flags.selective_display, 0x20);
-#ifndef old
- XSETFASTINT (buffer_local_flags.selective_display_ellipses, 0x40);
-#endif
- XSETFASTINT (buffer_local_flags.tab_width, 0x80);
- XSETFASTINT (buffer_local_flags.truncate_lines, 0x100);
- XSETFASTINT (buffer_local_flags.ctl_arrow, 0x200);
- XSETFASTINT (buffer_local_flags.fill_column, 0x400);
- XSETFASTINT (buffer_local_flags.left_margin, 0x800);
- XSETFASTINT (buffer_local_flags.abbrev_table, 0x1000);
- XSETFASTINT (buffer_local_flags.display_table, 0x2000);
-#ifdef DOS_NT
- XSETFASTINT (buffer_local_flags.buffer_file_type, 0x4000);
- /* Make this one a permanent local. */
- buffer_permanent_local_flags |= 0x4000;
-#endif
- XSETFASTINT (buffer_local_flags.syntax_table, 0x8000);
- XSETFASTINT (buffer_local_flags.cache_long_line_scans, 0x10000);
-
- 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");
-
- Qprotected_field = intern ("protected-field");
-
- Qpermanent_local = intern ("permanent-local");
-
- Qkill_buffer_hook = intern ("kill-buffer-hook");
-
- 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];
- char *pwd;
- struct stat dotstat, pwdstat;
- Lisp_Object temp;
- int rc;
-
- Fset_buffer (Fget_buffer_create (build_string ("*scratch*")));
-
- /* If PWD is accurate, use it instead of calling getwd. This is faster
- when PWD is right, and may avoid a fatal error. */
- if ((pwd = getenv ("PWD")) != 0 && IS_DIRECTORY_SEP (*pwd)
- && stat (pwd, &pwdstat) == 0
- && stat (".", &dotstat) == 0
- && dotstat.st_ino == pwdstat.st_ino
- && dotstat.st_dev == pwdstat.st_dev
- && strlen (pwd) < MAXPATHLEN)
- strcpy (buf, pwd);
- else 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. */
- rc = strlen (buf);
- if (!(IS_DIRECTORY_SEP (buf[rc - 1])))
- {
- buf[rc] = DIRECTORY_SEP;
- buf[rc + 1] = '\0';
- }
-#endif /* not VMS */
-
- current_buffer->directory = build_string (buf);
-
- /* Add /: to the front of the name
- if it would otherwise be treated as magic. */
- temp = Ffind_file_name_handler (current_buffer->directory, Qt);
- if (! NILP (temp))
- current_buffer->directory
- = concat2 (build_string ("/:"), current_buffer->directory);
-
- temp = get_minibuffer (0);
- XBUFFER (temp)->directory = current_buffer->directory;
-}
-
-/* initialize the buffer routines */
-syms_of_buffer ()
-{
- extern Lisp_Object Qdisabled;
-
- staticpro (&last_overlay_modification_hooks);
- last_overlay_modification_hooks
- = Fmake_vector (make_number (10), Qnil);
-
- staticpro (&Vbuffer_defaults);
- staticpro (&Vbuffer_local_symbols);
- staticpro (&Qfundamental_mode);
- staticpro (&Qmode_class);
- staticpro (&QSFundamental);
- staticpro (&Vbuffer_alist);
- staticpro (&Qprotected_field);
- staticpro (&Qpermanent_local);
- staticpro (&Qkill_buffer_hook);
- Qoverlayp = intern ("overlayp");
- staticpro (&Qoverlayp);
- Qevaporate = intern ("evaporate");
- staticpro (&Qevaporate);
- Qmodification_hooks = intern ("modification-hooks");
- staticpro (&Qmodification_hooks);
- Qinsert_in_front_hooks = intern ("insert-in-front-hooks");
- staticpro (&Qinsert_in_front_hooks);
- Qinsert_behind_hooks = intern ("insert-behind-hooks");
- staticpro (&Qinsert_behind_hooks);
- Qget_file_buffer = intern ("get-file-buffer");
- staticpro (&Qget_file_buffer);
- Qpriority = intern ("priority");
- staticpro (&Qpriority);
- Qwindow = intern ("window");
- staticpro (&Qwindow);
- Qbefore_string = intern ("before-string");
- staticpro (&Qbefore_string);
- Qafter_string = intern ("after-string");
- staticpro (&Qafter_string);
- Qfirst_change_hook = intern ("first-change-hook");
- staticpro (&Qfirst_change_hook);
- Qbefore_change_functions = intern ("before-change-functions");
- staticpro (&Qbefore_change_functions);
- Qafter_change_functions = intern ("after-change-functions");
- staticpro (&Qafter_change_functions);
-
- Fput (Qprotected_field, Qerror_conditions,
- Fcons (Qprotected_field, Fcons (Qerror, Qnil)));
- Fput (Qprotected_field, Qerror_message,
- build_string ("Attempt to modify a protected field"));
-
- /* 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 value of `mode-line-format' for buffers that don't override it.\n\
-This is the same as (default-value 'mode-line-format).");
-
- DEFVAR_LISP_NOPRO ("default-abbrev-mode",
- &buffer_defaults.abbrev_mode,
- "Default value of `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 value of `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 value of `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 value of `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 value of `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 value of `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 value of `case-fold-search' for buffers that don't override it.\n\
-This is the same as (default-value 'case-fold-search).");
-
-#ifdef DOS_NT
- DEFVAR_LISP_NOPRO ("default-buffer-file-type",
- &buffer_defaults.buffer_file_type,
- "Default file type for buffers that do not override it.\n\
-This is the same as (default-value 'buffer-file-type).\n\
-The file type is nil for text, t for binary.");
-#endif
-
- DEFVAR_PER_BUFFER ("mode-line-format", &current_buffer->mode_line_format,
- Qnil, 0);
-
-/* This doc string is too long for cpp; cpp dies if it isn't in a comment.
- But make-docfile finds it!
- DEFVAR_PER_BUFFER ("mode-line-format", &current_buffer->mode_line_format,
- Qnil,
- "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. %+ -- print *, % or hyphen.\n\
- % means buffer is read-only and * means it is modified.\n\
- For a modified read-only buffer, %* gives % and %+ gives *.\n\
- %s -- print process status. %l -- print the current line number.\n\
- %c -- print the current column number (this makes editing slower).\n\
- %p -- print percent of buffer above top of window, or Top, Bot or All.\n\
- %P -- print percent of buffer above bottom of window, perhaps plus Top,\n\
- or print Bottom or All.\n\
- %n -- print Narrow if appropriate.\n\
- %t -- print T if file is text, B if binary.\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,
- make_number (Lisp_Symbol),
- "Symbol for current buffer's major mode.");
-
- DEFVAR_PER_BUFFER ("mode-name", &current_buffer->mode_name,
- make_number (Lisp_String),
- "Pretty name of current buffer's major mode (a string).");
-
- DEFVAR_PER_BUFFER ("abbrev-mode", &current_buffer->abbrev_mode, Qnil,
- "Non-nil turns on automatic expansion of abbrevs as they are inserted.\n\
-Automatically becomes buffer-local when set in any fashion.");
-
- DEFVAR_PER_BUFFER ("case-fold-search", &current_buffer->case_fold_search,
- Qnil,
- "*Non-nil if searches should ignore case.\n\
-Automatically becomes buffer-local when set in any fashion.");
-
- DEFVAR_PER_BUFFER ("fill-column", &current_buffer->fill_column,
- make_number (Lisp_Int),
- "*Column beyond which automatic line-wrapping should happen.\n\
-Automatically becomes buffer-local when set in any fashion.");
-
- DEFVAR_PER_BUFFER ("left-margin", &current_buffer->left_margin,
- make_number (Lisp_Int),
- "*Column for the default indent-line-function to indent to.\n\
-Linefeed indents to this column in Fundamental mode.\n\
-Automatically becomes buffer-local when set in any fashion.");
-
- DEFVAR_PER_BUFFER ("tab-width", &current_buffer->tab_width,
- make_number (Lisp_Int),
- "*Distance between tab stops (for display of tab characters), in columns.\n\
-Automatically becomes buffer-local when set in any fashion.");
-
- DEFVAR_PER_BUFFER ("ctl-arrow", &current_buffer->ctl_arrow, Qnil,
- "*Non-nil means display control chars with uparrow.\n\
-Nil means use backslash and octal digits.\n\
-Automatically becomes buffer-local when set in any fashion.\n\
-This variable does not apply to characters whose display is specified\n\
-in the current display table (if there is one).");
-
- DEFVAR_PER_BUFFER ("truncate-lines", &current_buffer->truncate_lines, Qnil,
- "*Non-nil means do not display continuation lines;\n\
-give each line of text one screen line.\n\
-Automatically becomes buffer-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-frame width.");
-
-#ifdef DOS_NT
- DEFVAR_PER_BUFFER ("buffer-file-type", &current_buffer->buffer_file_type,
- Qnil,
- "Non-nil if the visited file is a binary file.\n\
-This variable is meaningful on MS-DOG and Windows NT.\n\
-On those systems, it is automatically local in every buffer.\n\
-On other systems, this variable is normally always nil.");
-#endif
-
- DEFVAR_PER_BUFFER ("default-directory", &current_buffer->directory,
- make_number (Lisp_String),
- "Name of default directory of current buffer. Should end with slash.\n\
-Each buffer has its own value of this variable.");
-
- DEFVAR_PER_BUFFER ("auto-fill-function", &current_buffer->auto_fill_function,
- Qnil,
- "Function called (if non-nil) to perform auto-fill.\n\
-It is called after self-inserting a space or newline.\n\
-Each buffer has its own value of this variable.\n\
-NOTE: This variable is not a hook;\n\
-its value may not be a list of functions.");
-
- DEFVAR_PER_BUFFER ("buffer-file-name", &current_buffer->filename,
- make_number (Lisp_String),
- "Name of file visited in current buffer, or nil if not visiting a file.\n\
-Each buffer has its own value of this variable.");
-
- DEFVAR_PER_BUFFER ("buffer-file-truename", &current_buffer->file_truename,
- make_number (Lisp_String),
- "Abbreviated truename of file visited in current buffer, or nil if none.\n\
-The truename of a file is calculated by `file-truename'\n\
-and then abbreviated with `abbreviate-file-name'.\n\
-Each buffer has its own value of this variable.");
-
- DEFVAR_PER_BUFFER ("buffer-auto-save-file-name",
- &current_buffer->auto_save_file_name,
- make_number (Lisp_String),
- "Name of file for auto-saving current buffer,\n\
-or nil if buffer should not be auto-saved.\n\
-Each buffer has its own value of this variable.");
-
- DEFVAR_PER_BUFFER ("buffer-read-only", &current_buffer->read_only, Qnil,
- "Non-nil if this buffer is read-only.\n\
-Each buffer has its own value of this variable.");
-
- DEFVAR_PER_BUFFER ("buffer-backed-up", &current_buffer->backed_up, Qnil,
- "Non-nil if this buffer's file has been backed up.\n\
-Backing up is done before the first time the file is saved.\n\
-Each buffer has its own value of this variable.");
-
- DEFVAR_PER_BUFFER ("buffer-saved-size", &current_buffer->save_length,
- make_number (Lisp_Int),
- "Length of current buffer when last read in, saved or auto-saved.\n\
-0 initially.\n\
-Each buffer has its own value of this variable.");
-
- DEFVAR_PER_BUFFER ("selective-display", &current_buffer->selective_display,
- Qnil,
- "Non-nil enables selective display:\n\
-Integer N as value means display only lines\n\
- that start with less than n columns of space.\n\
-A value of t means, after a ^M, all the rest of the line is invisible.\n\
- Then ^M's in the file are written into files as newlines.\n\n\
-Automatically becomes buffer-local when set in any fashion.");
-
-#ifndef old
- DEFVAR_PER_BUFFER ("selective-display-ellipses",
- &current_buffer->selective_display_ellipses,
- Qnil,
- "t means display ... on previous line when a line is invisible.\n\
-Automatically becomes buffer-local when set in any fashion.");
-#endif
-
- DEFVAR_PER_BUFFER ("overwrite-mode", &current_buffer->overwrite_mode, Qnil,
- "Non-nil if self-insertion should replace existing text.\n\
-The value should be one of `overwrite-mode-textual',\n\
-`overwrite-mode-binary', or nil.\n\
-If it is `overwrite-mode-textual', self-insertion still\n\
-inserts at the end of a line, and inserts when point is before a tab,\n\
-until the tab is filled in.\n\
-If `overwrite-mode-binary', self-insertion replaces newlines and tabs too.\n\
-Automatically becomes buffer-local when set in any fashion.");
-
-#if 0 /* The doc string is too long for some compilers,
- but make-docfile can find it in this comment. */
- DEFVAR_PER_BUFFER ("buffer-display-table", &current_buffer->display_table,
- Qnil,
- "Display table that controls display of the contents of current buffer.\n\
-Automatically becomes buffer-local when set in any fashion.\n\
-The display table is a char-table created with `make-display-table'.\n\
-The ordinary char-table elements control how to display each possible text\n\
-character. Each value should be a vector of characters or nil;\n\
-nil means display the character in the default fashion.\n\
-There are six extra slots to control the display of\n\
- the end of a truncated screen line (extra-slot 0, a single character);\n\
- the end of a continued line (extra-slot 1, a single character);\n\
- the escape character used to display character codes in octal\n\
- (extra-slot 2, a single character);\n\
- the character used as an arrow for control characters (extra-slot 3,\n\
- a single character);\n\
- the decoration indicating the presence of invisible lines (extra-slot 4,\n\
- a vector of characters);\n\
- the character used to draw the border between side-by-side windows\n\
- (extra-slot 5, a single character).\n\
-See also the functions `display-table-slot' and `set-display-table-slot'.\n\
-If this variable is nil, the value of `standard-display-table' is used.\n\
-Each window can have its own, overriding display table.");
-#endif
- DEFVAR_PER_BUFFER ("buffer-display-table", &current_buffer->display_table,
- Qnil, 0);
-
-/*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
- "Don't ask.");
-*/
- DEFVAR_LISP ("before-change-function", &Vbefore_change_function,
- "If non-nil, a function to call before each text change (obsolete).\n\
-Two arguments are passed to the function: the positions of\n\
-the beginning and end of the range of old text to be changed.\n\
-\(For an insertion, the beginning and end are at the same place.)\n\
-No information is given about the length of the text after the change.\n\
-\n\
-Buffer changes made while executing the `before-change-function'\n\
-don't call any before-change or after-change functions.\n\
-That's because these variables are temporarily set to nil.\n\
-As a result, a hook function cannot straightforwardly alter the value of\n\
-these variables. See the Emacs Lisp manual for a way of\n\
-accomplishing an equivalent result by using other variables.\n\n\
-This variable is obsolete; use `before-change-functions' instead.");
- Vbefore_change_function = Qnil;
-
- DEFVAR_LISP ("after-change-function", &Vafter_change_function,
- "If non-nil, a Function to call after each text change (obsolete).\n\
-Three arguments are passed to the function: the positions of\n\
-the beginning and end of the range of changed text,\n\
-and the length of the pre-change text replaced by that range.\n\
-\(For an insertion, the pre-change length is zero;\n\
-for a deletion, that length is the number of characters deleted,\n\
-and the post-change beginning and end are at the same place.)\n\
-\n\
-Buffer changes made while executing the `after-change-function'\n\
-don't call any before-change or after-change functions.\n\
-That's because these variables are temporarily set to nil.\n\
-As a result, a hook function cannot straightforwardly alter the value of\n\
-these variables. See the Emacs Lisp manual for a way of\n\
-accomplishing an equivalent result by using other variables.\n\n\
-This variable is obsolete; use `after-change-functions' instead.");
- Vafter_change_function = Qnil;
-
- DEFVAR_LISP ("before-change-functions", &Vbefore_change_functions,
- "List of functions to call before each text change.\n\
-Two arguments are passed to each function: the positions of\n\
-the beginning and end of the range of old text to be changed.\n\
-\(For an insertion, the beginning and end are at the same place.)\n\
-No information is given about the length of the text after the change.\n\
-\n\
-Buffer changes made while executing the `before-change-functions'\n\
-don't call any before-change or after-change functions.\n\
-That's because these variables are temporarily set to nil.\n\
-As a result, a hook function cannot straightforwardly alter the value of\n\
-these variables. See the Emacs Lisp manual for a way of\n\
-accomplishing an equivalent result by using other variables.");
- Vbefore_change_functions = Qnil;
-
- DEFVAR_LISP ("after-change-functions", &Vafter_change_functions,
- "List of function to call after each text change.\n\
-Three arguments are passed to each function: the positions of\n\
-the beginning and end of the range of changed text,\n\
-and the length of the pre-change text replaced by that range.\n\
-\(For an insertion, the pre-change length is zero;\n\
-for a deletion, that length is the number of characters deleted,\n\
-and the post-change beginning and end are at the same place.)\n\
-\n\
-Buffer changes made while executing the `after-change-functions'\n\
-don't call any before-change or after-change functions.\n\
-That's because these variables are temporarily set to nil.\n\
-As a result, a hook function cannot straightforwardly alter the value of\n\
-these variables. See the Emacs Lisp manual for a way of\n\
-accomplishing an equivalent result by using other variables.");
-
- Vafter_change_functions = Qnil;
-
- DEFVAR_LISP ("first-change-hook", &Vfirst_change_hook,
- "A list of functions to call before changing a buffer which is unmodified.\n\
-The functions are run using the `run-hooks' function.");
- Vfirst_change_hook = Qnil;
-
-#if 0 /* The doc string is too long for some compilers,
- but make-docfile can find it in this comment. */
- DEFVAR_PER_BUFFER ("buffer-undo-list", &current_buffer->undo_list, Qnil,
- "List of undo entries in current buffer.\n\
-Recent changes come first; older changes follow newer.\n\
-\n\
-An entry (BEG . END) represents an insertion which begins at\n\
-position BEG and ends at position END.\n\
-\n\
-An entry (TEXT . POSITION) represents the deletion of the string TEXT\n\
-from (abs POSITION). If POSITION is positive, point was at the front\n\
-of the text being deleted; if negative, point was at the end.\n\
-\n\
-An entry (t HIGH . LOW) indicates that the buffer previously had\n\
-\"unmodified\" status. HIGH and LOW are the high and low 16-bit portions\n\
-of the visited file's modification time, as of that time. If the\n\
-modification time of the most recent save is different, this entry is\n\
-obsolete.\n\
-\n\
-An entry (nil PROPERTY VALUE BEG . END) indicates that a text property\n\
-was modified between BEG and END. PROPERTY is the property name,\n\
-and VALUE is the old value.\n\
-\n\
-An entry (MARKER . DISTANCE) indicates that the marker MARKER\n\
-was adjusted in position by the offset DISTANCE (an integer).\n\
-\n\
-An entry of the form POSITION indicates that point was at the buffer\n\
-location given by the integer. Undoing an entry of this form places\n\
-point at POSITION.\n\
-\n\
-nil marks undo boundaries. The undo command treats the changes\n\
-between two undo boundaries as a single step to be undone.\n\
-\n\
-If the value of the variable is t, undo information is not recorded.");
-#endif
- DEFVAR_PER_BUFFER ("buffer-undo-list", &current_buffer->undo_list, Qnil,
- 0);
-
- DEFVAR_PER_BUFFER ("mark-active", &current_buffer->mark_active, Qnil,
- "Non-nil means the mark and region are currently active in this buffer.\n\
-Automatically local in all buffers.");
-
- DEFVAR_PER_BUFFER ("cache-long-line-scans", &current_buffer->cache_long_line_scans, Qnil,
- "Non-nil means that Emacs should use caches to handle long lines more quickly.\n\
-This variable is buffer-local, in all buffers.\n\
-\n\
-Normally, the line-motion functions work by scanning the buffer for\n\
-newlines. Columnar operations (like move-to-column and\n\
-compute-motion) also work by scanning the buffer, summing character\n\
-widths as they go. This works well for ordinary text, but if the\n\
-buffer's lines are very long (say, more than 500 characters), these\n\
-motion functions will take longer to execute. Emacs may also take\n\
-longer to update the display.\n\
-\n\
-If cache-long-line-scans is non-nil, these motion functions cache the\n\
-results of their scans, and consult the cache to avoid rescanning\n\
-regions of the buffer until the text is modified. The caches are most\n\
-beneficial when they prevent the most searching---that is, when the\n\
-buffer contains long lines and large regions of characters with the\n\
-same, fixed screen width.\n\
-\n\
-When cache-long-line-scans is non-nil, processing short lines will\n\
-become slightly slower (because of the overhead of consulting the\n\
-cache), and the caches will use memory roughly proportional to the\n\
-number of newlines and characters whose screen width varies.\n\
-\n\
-The caches require no explicit maintenance; their accuracy is\n\
-maintained internally by the Emacs primitives. Enabling or disabling\n\
-the cache should not affect the behavior of any of the motion\n\
-functions; it should only affect their performance.");
-
- DEFVAR_PER_BUFFER ("point-before-scroll", &current_buffer->point_before_scroll, Qnil,
- "Value of point before the last series of scroll operations, or nil.");
-
- DEFVAR_PER_BUFFER ("buffer-file-format", &current_buffer->file_format, Qnil,
- "List of formats to use when saving this buffer.\n\
-Formats are defined by `format-alist'. This variable is\n\
-set when a file is visited. Automatically local in all buffers.");
-
- DEFVAR_PER_BUFFER ("buffer-invisibility-spec",
- &current_buffer->invisibility_spec, Qnil,
- "Invisibility spec of this buffer.\n\
-The default is t, which means that text is invisible\n\
-if it has a non-nil `invisible' property.\n\
-If the value is a list, a text character is invisible if its `invisible'\n\
-property is an element in that list.\n\
-If an element is a cons cell of the form (PROP . ELLIPSIS),\n\
-then characters with property value PROP are invisible,\n\
-and they have an ellipsis as well if ELLIPSIS is non-nil.");
-
- DEFVAR_LISP ("transient-mark-mode", &Vtransient_mark_mode,
- "*Non-nil means deactivate the mark when the buffer contents change.\n\
-Non-nil also enables highlighting of the region whenever the mark is active.\n\
-The variable `highlight-nonselected-windows' controls whether to highlight\n\
-all windows or just the selected window.");
- Vtransient_mark_mode = Qnil;
-
- DEFVAR_LISP ("inhibit-read-only", &Vinhibit_read_only,
- "*Non-nil means disregard read-only status of buffers or characters.\n\
-If the value is t, disregard `buffer-read-only' and all `read-only'\n\
-text properties. If the value is a list, disregard `buffer-read-only'\n\
-and disregard a `read-only' text property if the property value\n\
-is a member of the list.");
- Vinhibit_read_only = Qnil;
-
- DEFVAR_LISP ("kill-buffer-query-functions", &Vkill_buffer_query_functions,
- "List of functions called with no args to query before killing a buffer.");
- Vkill_buffer_query_functions = Qnil;
-
- defsubr (&Sbuffer_live_p);
- defsubr (&Sbuffer_list);
- defsubr (&Sget_buffer);
- defsubr (&Sget_file_buffer);
- defsubr (&Sget_buffer_create);
- defsubr (&Smake_indirect_buffer);
- defsubr (&Sgenerate_new_buffer_name);
- defsubr (&Sbuffer_name);
-/*defsubr (&Sbuffer_number);*/
- defsubr (&Sbuffer_file_name);
- defsubr (&Sbuffer_base_buffer);
- defsubr (&Sbuffer_local_variables);
- defsubr (&Sbuffer_modified_p);
- defsubr (&Sset_buffer_modified_p);
- defsubr (&Sbuffer_modified_tick);
- defsubr (&Srename_buffer);
- defsubr (&Sother_buffer);
- defsubr (&Sbuffer_disable_undo);
- defsubr (&Sbuffer_enable_undo);
- defsubr (&Skill_buffer);
- defsubr (&Serase_buffer);
- defsubr (&Sset_buffer_major_mode);
- defsubr (&Sswitch_to_buffer);
- defsubr (&Spop_to_buffer);
- defsubr (&Scurrent_buffer);
- defsubr (&Sset_buffer);
- defsubr (&Sbarf_if_buffer_read_only);
- defsubr (&Sbury_buffer);
- defsubr (&Skill_all_local_variables);
-
- defsubr (&Soverlayp);
- defsubr (&Smake_overlay);
- defsubr (&Sdelete_overlay);
- defsubr (&Smove_overlay);
- defsubr (&Soverlay_start);
- defsubr (&Soverlay_end);
- defsubr (&Soverlay_buffer);
- defsubr (&Soverlay_properties);
- defsubr (&Soverlays_at);
- defsubr (&Soverlays_in);
- defsubr (&Snext_overlay_change);
- defsubr (&Sprevious_overlay_change);
- defsubr (&Soverlay_recenter);
- defsubr (&Soverlay_lists);
- defsubr (&Soverlay_get);
- defsubr (&Soverlay_put);
-}
-
-keys_of_buffer ()
-{
- initial_define_key (control_x_map, 'b', "switch-to-buffer");
- initial_define_key (control_x_map, 'k', "kill-buffer");
-
- /* This must not be in syms_of_buffer, because Qdisabled is not
- initialized when that function gets called. */
- Fput (intern ("erase-buffer"), Qdisabled, Qt);
-}
diff --git a/src/buffer.h b/src/buffer.h
deleted file mode 100644
index 76e8c84b543..00000000000
--- a/src/buffer.h
+++ /dev/null
@@ -1,532 +0,0 @@
-/* Header file for the buffer manipulation primitives.
- Copyright (C) 1985, 1986, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#ifdef USE_TEXT_PROPERTIES
-#define SET_PT(position) (set_point ((position), current_buffer))
-#define TEMP_SET_PT(position) (temp_set_point ((position), current_buffer))
-
-#define BUF_SET_PT(buffer, position) (set_point ((position), (buffer)))
-#define BUF_TEMP_SET_PT(buffer, position) (temp_set_point ((position), (buffer)))
-
-#else /* don't support text properties */
-
-#define SET_PT(position) (current_buffer->pt = (position))
-#define TEMP_SET_PT(position) (current_buffer->pt = (position))
-
-#define BUF_SET_PT(buffer, position) (buffer->pt = (position))
-#define BUF_TEMP_SET_PT(buffer, position) (buffer->pt = (position))
-#endif /* don't support text properties */
-
-/* Character position of beginning of buffer. */
-#define BEG (1)
-
-/* Character position of beginning of accessible range of buffer. */
-#define BEGV (current_buffer->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->pt + 0)
-
-/* 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->zv)
-
-/* Character position of end of buffer. */
-#define Z (current_buffer->text->z)
-
-/* Is the current buffer narrowed? */
-#define NARROWED ((BEGV != BEG) || (ZV != Z))
-
-/* Modification count. */
-#define MODIFF (current_buffer->text->modiff)
-
-/* Overlay modification count. */
-#define OVERLAY_MODIFF (current_buffer->text->overlay_modiff)
-
-/* Modification count as of last visit or save. */
-#define SAVE_MODIFF (current_buffer->text->save_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->begv))
-
-/* Address of point in buffer. */
-#define PT_ADDR (&FETCH_CHAR (current_buffer->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->zv))
-
-/* Size of gap. */
-#define GAP_SIZE (current_buffer->text->gap_size)
-
-/* Now similar macros for a specified buffer.
- Note that many of these evaluate the buffer argument more than once. */
-
-/* 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)->begv)
-
-/* Character position of point in buffer. */
-#define BUF_PT(buf) ((buf)->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)->zv)
-
-/* Character position of end of buffer. */
-#define BUF_Z(buf) ((buf)->text->z)
-
-/* Is this buffer narrowed? */
-#define BUF_NARROWED(buf) ((BUF_BEGV (buf) != BUF_BEG (buf)) \
- || (BUF_ZV (buf) != BUF_Z (buf)))
-
-/* Modification count. */
-#define BUF_MODIFF(buf) ((buf)->text->modiff)
-
-/* Modification count as of last visit or save. */
-#define BUF_SAVE_MODIFF(buf) ((buf)->text->save_modiff)
-
-/* Overlay modification count. */
-#define BUF_OVERLAY_MODIFF(buf) ((buf)->text->overlay_modiff)
-
-/* Interval tree of buffer. */
-#define BUF_INTERVALS(buf) ((buf)->text->intervals)
-
-/* Marker chain of buffer. */
-#define BUF_MARKERS(buf) ((buf)->text->markers)
-
-/* Address of beginning of buffer. */
-#define BUF_BEG_ADDR(buf) ((buf)->text->beg)
-
-/* Macro for setting the value of BUF_ZV (BUF) to VALUE,
- by varying the end of the accessible region. */
-#define SET_BUF_ZV(buf, value) ((buf)->zv = (value))
-#define SET_BUF_PT(buf, value) ((buf)->pt = (value))
-
-/* Size of gap. */
-#define BUF_GAP_SIZE(buf) ((buf)->text->gap_size)
-
-/* Return the address of character at position POS in buffer BUF.
- Note that both arguments can be computed more than once. */
-#define BUF_CHAR_ADDRESS(buf, pos) \
-((buf)->text->beg + (pos) - 1 \
- + ((pos) >= (buf)->text->gpt ? (buf)->text->gap_size : 0))
-
-/* 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)
-
-/* Convert the address of a char in the buffer into a character position. */
-#define BUF_PTR_CHAR_POS(buf, ptr) \
-((ptr) - (buf)->text->beg \
- - (ptr - (buf)->text->beg < (unsigned) BUF_GPT ((buf)) \
- ? 0 : BUF_GAP_SIZE ((buf))) \
- + 1)
-
-struct buffer_text
- {
- unsigned char *beg; /* Actual address of buffer contents. */
- int gpt; /* Index of gap in buffer. */
- 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. */
- int save_modiff; /* Previous value of modiff, as of last
- time buffer visited or saved a file. */
-
- int overlay_modiff; /* Counts modifications to overlays. */
-
- /* Properties of this buffer's text -- conditionally compiled. */
- DECLARE_INTERVALS
-
- /* The markers that refer to this buffer.
- This is actually a single marker ---
- successive elements in its marker `chain'
- are the other markers referring to this buffer. */
- Lisp_Object markers;
- };
-
-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. */
-
- EMACS_INT size;
-
- /* Next buffer, in chain of all buffers including killed buffers.
- This chain is used only for garbage collection, in order to
- collect killed buffers properly.
- Note that vectors and most pseudovectors are all on one chain,
- but buffers are on a separate chain of their own. */
- struct buffer *next;
-
- /* This structure holds the coordinates of the buffer contents
- in ordinary buffers. In indirect buffers, this is not used. */
- struct buffer_text own_text;
-
- /* This points to the `struct buffer_text' that used for this buffer.
- In an ordinary buffer, this is the own_text field above.
- In an indirect buffer, this is the own_text field of another buffer. */
- struct buffer_text *text;
-
- /* Position of point in buffer. */
- int pt;
- /* Index of beginning of accessible range. */
- int begv;
- /* Index of end of accessible range. */
- int zv;
-
- /* In an indirect buffer, this points to the base buffer.
- In an ordinary buffer, it is 0. */
- struct buffer *base_buffer;
-
- /* Flags saying which DEFVAR_PER_BUFFER variables
- are local to this buffer. */
- int local_var_flags;
- /* 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;
- /* The time at which we detected a failure to auto-save,
- Or -1 if we didn't have a failure. */
- int auto_save_failure_time;
- /* Position in buffer at which display started
- the last time this buffer was displayed. */
- int last_window_start;
-
- /* Set nonzero whenever the narrowing is changed in this buffer. */
- int clip_changed;
-
- /* If the long line scan cache is enabled (i.e. the buffer-local
- variable cache-long-line-scans is non-nil), newline_cache
- points to the newline cache, and width_run_cache points to the
- width run cache.
-
- The newline cache records which stretches of the buffer are
- known *not* to contain newlines, so that they can be skipped
- quickly when we search for newlines.
-
- The width run cache records which stretches of the buffer are
- known to contain characters whose widths are all the same. If
- the width run cache maps a character to a value > 0, that value is
- the character's width; if it maps a character to zero, we don't
- know what its width is. This allows compute_motion to process
- such regions very quickly, using algebra instead of inspecting
- each character. See also width_table, below. */
- struct region_cache *newline_cache;
- struct region_cache *width_run_cache;
-
- /* Everything from here down must be a Lisp_Object */
-
-
- /* The name of this buffer. */
- Lisp_Object name;
- /* The name of the file visited in this buffer, or nil. */
- Lisp_Object filename;
- /* Dir for expanding relative file names. */
- Lisp_Object directory;
- /* True iff this buffer has been backed up (if you write to the
- visited file and it hasn't been backed up, then a backup will
- be made). */
- /* This isn't really used by the C code, so could be deleted. */
- Lisp_Object backed_up;
- /* Length of file when last read or saved.
- This is not in the struct buffer_text
- because it's not used in indirect buffers at all. */
- Lisp_Object save_length;
- /* File name used for auto-saving this buffer.
- This is not in the struct buffer_text
- because it's not used in indirect buffers at all. */
- Lisp_Object auto_save_file_name;
-
- /* Non-nil if buffer read-only. */
- Lisp_Object read_only;
- /* "The mark". This is a marker which may
- point into this buffer or may point nowhere. */
- Lisp_Object mark;
-
- /* Alist of elements (SYMBOL . VALUE-IN-THIS-BUFFER)
- for all per-buffer variables of this buffer. */
- Lisp_Object local_var_alist;
-
- /* Symbol naming major mode (eg, lisp-mode). */
- Lisp_Object major_mode;
- /* Pretty name of major mode (eg, "Lisp"). */
- Lisp_Object mode_name;
- /* Mode line element that controls format of 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. */
- Lisp_Object syntax_table;
-
- /* Values of several buffer-local variables */
- /* tab-width is buffer-local so that redisplay can find it
- in buffers that are not current */
- Lisp_Object case_fold_search;
- 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;
- /* nil: text, t: binary.
- This value is meaningful only on certain operating systems. */
- Lisp_Object buffer_file_type;
-
- /* Case table for case-conversion in this buffer.
- This char-table maps each char into its lower-case version. */
- Lisp_Object downcase_table;
- /* Char-table mapping each char to its upper-case version. */
- Lisp_Object upcase_table;
- /* Char-table for conversion for case-folding search. */
- Lisp_Object case_canon_table;
- /* Char-table of equivalences for case-folding search. */
- Lisp_Object case_eqv_table;
-
- /* Non-nil means do not display continuation lines. */
- Lisp_Object truncate_lines;
- /* Non-nil means display ctl chars with uparrow. */
- Lisp_Object ctl_arrow;
- /* 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; `binary' if it should also
- overwrite newlines and tabs - for editing executables and the like. */
- 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;
- /* t means the mark and region are currently active. */
- Lisp_Object mark_active;
-
- /* Changes in the buffer are recorded here for undo.
- t means don't record anything.
- This information belongs to the base buffer of an indirect buffer,
- But we can't store it in the struct buffer_text
- because local variables have to be right in the struct buffer.
- So we copy it around in set_buffer_internal. */
- Lisp_Object undo_list;
-
- /* List of overlays that end at or before the current center,
- in order of end-position. */
- Lisp_Object overlays_before;
-
- /* List of overlays that end after the current center,
- in order of start-position. */
- Lisp_Object overlays_after;
-
- /* Position where the overlay lists are centered. */
- Lisp_Object overlay_center;
-
- /* List of symbols naming the file format used for visited file. */
- Lisp_Object file_format;
-
- /* True if the newline position cache and width run cache are
- enabled. See search.c and indent.c. */
- Lisp_Object cache_long_line_scans;
-
- /* If the width run cache is enabled, this table contains the
- character widths width_run_cache (see above) assumes. When we
- do a thorough redisplay, we compare this against the buffer's
- current display table to see whether the display table has
- affected the widths of any characters. If it has, we
- invalidate the width run cache, and re-initialize width_table. */
- Lisp_Object width_table;
-
- /* In an indirect buffer, or a buffer that is the base of an
- indirect buffer, this holds a marker that records
- PT for this buffer when the buffer is not current. */
- Lisp_Object pt_marker;
-
- /* In an indirect buffer, or a buffer that is the base of an
- indirect buffer, this holds a marker that records
- BEGV for this buffer when the buffer is not current. */
- Lisp_Object begv_marker;
-
- /* In an indirect buffer, or a buffer that is the base of an
- indirect buffer, this holds a marker that records
- ZV for this buffer when the buffer is not current. */
- Lisp_Object zv_marker;
-
- /* This holds the point value before the last scroll operation.
- Explicitly setting point sets this to nil. */
- Lisp_Object point_before_scroll;
-
- /* Truename of the visited file, or nil. */
- Lisp_Object file_truename;
-
- /* Invisibility spec of this buffer.
- t => any non-nil `invisible' property means invisible.
- A list => `invisible' property means invisible
- if it is memq in that list. */
- Lisp_Object invisibility_spec;
-
- /* This is the last window that was selected with this buffer in it,
- or nil if that window no longer displays this buffer. */
- Lisp_Object last_selected_window;
-
- /* These are so we don't have to recompile everything
- the next few times we add a new slot. */
- Lisp_Object extra2, extra3;
- };
-
-/* This points to the current buffer. */
-
-extern struct buffer *current_buffer;
-
-/* This structure holds the default values of the buffer-local variables
- 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. */
-
-extern struct buffer buffer_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 zero, then even though there may
- be a Lisp-level local variable for the slot, it has no default value,
- and the corresponding slot in buffer_defaults is not used. */
-
-extern struct buffer buffer_local_flags;
-
-/* For each buffer slot, this points to the Lisp symbol name
- for that slot in the current buffer. It is 0 for slots
- that don't have such names. */
-
-extern struct buffer buffer_local_symbols;
-
-/* This structure holds the required types for the values in the
- buffer-local slots. If a slot contains Qnil, then the
- corresponding buffer slot may contain a value of any type. If a
- slot contains an integer, then prospective values' tags must be
- equal to that integer. When a tag does not match, the function
- buffer_slot_type_mismatch will signal an error. The value Qnil may
- always be safely stored in any slot. */
-extern struct buffer buffer_local_types;
-
-/* Point in the current buffer. This is an obsolete alias
- and should be eliminated. */
-#define point (current_buffer->pt + 0)
-
-/* Return character at position n. No range checking. */
-#define FETCH_CHAR(n) *(((n)>= GPT ? GAP_SIZE : 0) + (n) + BEG_ADDR - 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)
-
-extern void reset_buffer ();
-extern void evaporate_overlays ();
-
-extern Lisp_Object Fbuffer_name ();
-extern Lisp_Object Fget_file_buffer ();
-extern Lisp_Object Fnext_overlay_change ();
-extern Lisp_Object Fdelete_overlay ();
-
-/* Functions to call before and after each text change. */
-extern Lisp_Object Vbefore_change_function;
-extern Lisp_Object Vafter_change_function;
-extern Lisp_Object Vbefore_change_functions;
-extern Lisp_Object Vafter_change_functions;
-extern Lisp_Object Vfirst_change_hook;
-extern Lisp_Object Qbefore_change_functions;
-extern Lisp_Object Qafter_change_functions;
-extern Lisp_Object Qfirst_change_hook;
-
-extern Lisp_Object Vdeactivate_mark;
-extern Lisp_Object Vtransient_mark_mode;
-
-/* Overlays */
-
-/* 1 if the OV is an overlay object. */
-#define OVERLAY_VALID(OV) (OVERLAYP (OV))
-
-/* Return the marker that stands for where OV starts in the buffer. */
-#define OVERLAY_START(OV) (XOVERLAY (OV)->start)
-
-/* Return the marker that stands for where OV ends in the buffer. */
-#define OVERLAY_END(OV) (XOVERLAY (OV)->end)
-
-/* Return the actual buffer position for the marker P.
- We assume you know which buffer it's pointing into. */
-
-#define OVERLAY_POSITION(P) \
- (GC_MARKERP (P) ? marker_position (P) : (abort (), 0))
-
-/* Allocation of buffer text. */
-
-#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
diff --git a/src/bytecode.c b/src/bytecode.c
deleted file mode 100644
index 38a1d3a0d5d..00000000000
--- a/src/bytecode.c
+++ /dev/null
@@ -1,1198 +0,0 @@
-/* Execution of byte code produced by bytecomp.el.
- Copyright (C) 1985, 1986, 1987, 1988, 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
-hacked on by jwz@lucid.com 17-jun-91
- o added a compile-time switch to turn on simple sanity checking;
- o put back the obsolete byte-codes for error-detection;
- o added a new instruction, unbind_all, which I will use for
- tail-recursion elimination;
- o made temp_output_buffer_show be called with the right number
- of args;
- o made the new bytecodes be called with args in the right order;
- o added metering support.
-
-by Hallvard:
- o added relative jump instructions;
- o all conditionals now only do QUIT if they jump.
- */
-
-#include <config.h>
-#include "lisp.h"
-#include "buffer.h"
-#include "syntax.h"
-
-/*
- * define BYTE_CODE_SAFE to enable some minor sanity checking (useful for
- * debugging the byte compiler...)
- *
- * define BYTE_CODE_METER to enable generation of a byte-op usage histogram.
- */
-/* #define BYTE_CODE_SAFE */
-/* #define BYTE_CODE_METER */
-
-
-#ifdef BYTE_CODE_METER
-
-Lisp_Object Vbyte_code_meter, Qbyte_code_meter;
-int byte_metering_on;
-
-#define METER_2(code1, code2) \
- XFASTINT (XVECTOR (XVECTOR (Vbyte_code_meter)->contents[(code1)]) \
- ->contents[(code2)])
-
-#define METER_1(code) METER_2 (0, (code))
-
-#define METER_CODE(last_code, this_code) \
-{ \
- if (byte_metering_on) \
- { \
- if (METER_1 (this_code) != ((1<<VALBITS)-1)) \
- METER_1 (this_code)++; \
- if (last_code \
- && METER_2 (last_code, this_code) != ((1<<VALBITS)-1))\
- METER_2 (last_code, this_code)++; \
- } \
-}
-
-#else /* no BYTE_CODE_METER */
-
-#define METER_CODE(last_code, this_code)
-
-#endif /* no BYTE_CODE_METER */
-
-
-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 Bmult 0137
-
-#define Bpoint 0140
-/* Was Bmark in v17. */
-#define Bsave_current_buffer 0141
-#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 /* No longer generated as of v19 */
-#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 Bforward_char 0165
-#define Bforward_word 0166
-#define Bskip_chars_forward 0167
-#define Bskip_chars_backward 0170
-#define Bforward_line 0171
-#define Bchar_syntax 0172
-#define Bbuffer_substring 0173
-#define Bdelete_region 0174
-#define Bnarrow_to_region 0175
-#define Bwiden 0176
-#define Bend_of_line 0177
-
-#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 Bunbind_all 0222
-
-#define Bset_marker 0223
-#define Bmatch_beginning 0224
-#define Bmatch_end 0225
-#define Bupcase 0226
-#define Bdowncase 0227
-
-#define Bstringeqlsign 0230
-#define Bstringlss 0231
-#define Bequal 0232
-#define Bnthcdr 0233
-#define Belt 0234
-#define Bmember 0235
-#define Bassq 0236
-#define Bnreverse 0237
-#define Bsetcar 0240
-#define Bsetcdr 0241
-#define Bcar_safe 0242
-#define Bcdr_safe 0243
-#define Bnconc 0244
-#define Bquo 0245
-#define Brem 0246
-#define Bnumberp 0247
-#define Bintegerp 0250
-
-#define BRgoto 0252
-#define BRgotoifnil 0253
-#define BRgotoifnonnil 0254
-#define BRgotoifnilelsepop 0255
-#define BRgotoifnonnilelsepop 0256
-
-#define BlistN 0257
-#define BconcatN 0260
-#define BinsertN 0261
-
-#define Bconstant 0300
-#define CONSTANTLIM 0100
-
-/* Fetch the next byte from the bytecode stream */
-
-#define FETCH *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. */
-
-/* This used to be #define PUSH(x) (*++stackp = (x))
- This oddity is necessary because Alliant can't be bothered to
- compile the preincrement operator properly, as of 4/91. -JimB */
-#define PUSH(x) (stackp++, *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)
-
-/* Garbage collect if we have consed enough since the last time.
- We do this at every branch, to avoid loops that never GC. */
-
-#define MAYBE_GC() \
- if (consing_since_gc > gc_cons_threshold) \
- { \
- Fgarbage_collect (); \
- HANDLE_RELOCATION (); \
- } \
- else
-
-/* Relocate BYTESTR if there has been a GC recently. */
-#define HANDLE_RELOCATION() \
- if (! EQ (string_saved, bytestr)) \
- { \
- pc = pc - XSTRING (string_saved)->data + XSTRING (bytestr)->data; \
- string_saved = bytestr; \
- } \
- else
-
-/* Check for jumping out of range. */
-#define CHECK_RANGE(ARG) \
- if (ARG >= bytestr_length) abort ()
-
-DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0,
- "Function used internally in byte-compiled code.\n\
-The first argument, BYTESTR, is a string of byte code;\n\
-the second, VECTOR, a vector of constants;\n\
-the third, MAXDEPTH, the maximum stack depth used in this function.\n\
-If the third argument is incorrect, Emacs may crash.")
- (bytestr, vector, maxdepth)
- Lisp_Object bytestr, vector, maxdepth;
-{
- struct gcpro gcpro1, gcpro2, gcpro3;
- int count = specpdl_ptr - specpdl;
-#ifdef BYTE_CODE_METER
- int this_op = 0;
- int prev_op;
-#endif
- register int op;
- unsigned char *pc;
- Lisp_Object *stack;
- register Lisp_Object *stackp;
- Lisp_Object *stacke;
- register Lisp_Object v1, v2;
- register Lisp_Object *vectorp = XVECTOR (vector)->contents;
-#ifdef BYTE_CODE_SAFE
- register int const_length = XVECTOR (vector)->size;
-#endif
- /* Copy of BYTESTR, saved so we can tell if BYTESTR was relocated. */
- Lisp_Object string_saved;
- /* Cached address of beginning of string,
- valid if BYTESTR equals STRING_SAVED. */
- register unsigned char *strbeg;
- int bytestr_length = XSTRING (bytestr)->size;
-
- CHECK_STRING (bytestr, 0);
- if (!VECTORP (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);
-
- /* Initialize the saved pc-pointer for fetching from the string. */
- string_saved = bytestr;
- pc = XSTRING (string_saved)->data;
-
- while (1)
- {
-#ifdef BYTE_CODE_SAFE
- if (stackp > stacke)
- error ("Byte code stack overflow (byte compiler bug), pc %d, depth %d",
- pc - XSTRING (string_saved)->data, stacke - stackp);
- if (stackp < stack)
- error ("Byte code stack underflow (byte compiler bug), pc %d",
- pc - XSTRING (string_saved)->data);
-#endif
-
- /* Update BYTESTR if we had a garbage collection. */
- HANDLE_RELOCATION ();
-
-#ifdef BYTE_CODE_METER
- prev_op = this_op;
- this_op = op = FETCH;
- METER_CODE (prev_op, op);
- switch (op)
-#else
- switch (op = FETCH)
-#endif
- {
- 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 (!SYMBOLP (v1))
- v2 = Fsymbol_value (v1);
- else
- {
- v2 = XSYMBOL (v1)->value;
- if (MISCP (v2) || EQ (v2, Qunbound))
- 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);
-#ifdef BYTE_CODE_METER
- if (byte_metering_on && SYMBOLP (TOP))
- {
- v1 = TOP;
- v2 = Fget (v1, Qbyte_code_meter);
- if (INTEGERP (v2)
- && XINT (v2) != ((1<<VALBITS)-1))
- {
- XSETINT (v2, XINT (v2) + 1);
- Fput (v1, Qbyte_code_meter, v2);
- }
- }
-#endif
- TOP = Ffuncall (op + 1, &TOP);
- 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, Qnil);
- break;
-
- case Bunbind_all:
- /* To unbind back to the beginning of this frame. Not used yet,
- but will be needed for tail-recursion elimination. */
- unbind_to (count, Qnil);
- break;
-
- case Bgoto:
- MAYBE_GC ();
- QUIT;
- op = FETCH2; /* pc = FETCH2 loses since FETCH2 contains pc++ */
- CHECK_RANGE (op);
- pc = XSTRING (string_saved)->data + op;
- break;
-
- case Bgotoifnil:
- MAYBE_GC ();
- op = FETCH2;
- if (NILP (POP))
- {
- QUIT;
- CHECK_RANGE (op);
- pc = XSTRING (string_saved)->data + op;
- }
- break;
-
- case Bgotoifnonnil:
- MAYBE_GC ();
- op = FETCH2;
- if (!NILP (POP))
- {
- QUIT;
- CHECK_RANGE (op);
- pc = XSTRING (string_saved)->data + op;
- }
- break;
-
- case Bgotoifnilelsepop:
- MAYBE_GC ();
- op = FETCH2;
- if (NILP (TOP))
- {
- QUIT;
- CHECK_RANGE (op);
- pc = XSTRING (string_saved)->data + op;
- }
- else DISCARD (1);
- break;
-
- case Bgotoifnonnilelsepop:
- MAYBE_GC ();
- op = FETCH2;
- if (!NILP (TOP))
- {
- QUIT;
- CHECK_RANGE (op);
- pc = XSTRING (string_saved)->data + op;
- }
- else DISCARD (1);
- break;
-
- case BRgoto:
- MAYBE_GC ();
- QUIT;
- pc += (int) *pc - 127;
- break;
-
- case BRgotoifnil:
- MAYBE_GC ();
- if (NILP (POP))
- {
- QUIT;
- pc += (int) *pc - 128;
- }
- pc++;
- break;
-
- case BRgotoifnonnil:
- MAYBE_GC ();
- if (!NILP (POP))
- {
- QUIT;
- pc += (int) *pc - 128;
- }
- pc++;
- break;
-
- case BRgotoifnilelsepop:
- MAYBE_GC ();
- op = *pc++;
- if (NILP (TOP))
- {
- QUIT;
- pc += op - 128;
- }
- else DISCARD (1);
- break;
-
- case BRgotoifnonnilelsepop:
- MAYBE_GC ();
- op = *pc++;
- if (!NILP (TOP))
- {
- QUIT;
- pc += op - 128;
- }
- 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_current_buffer:
- record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
- 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, Qnil);
- break;
-
- case Bnth:
- v1 = POP;
- v2 = TOP;
- nth_entry:
- CHECK_NUMBER (v2, 0);
- op = XINT (v2);
- immediate_quit = 1;
- while (--op >= 0)
- {
- if (CONSP (v1))
- v1 = XCONS (v1)->cdr;
- else if (!NILP (v1))
- {
- immediate_quit = 0;
- v1 = wrong_type_argument (Qlistp, v1);
- immediate_quit = 1;
- op++;
- }
- }
- immediate_quit = 0;
- goto docar;
-
- case Bsymbolp:
- TOP = SYMBOLP (TOP) ? Qt : Qnil;
- break;
-
- case Bconsp:
- TOP = CONSP (TOP) ? Qt : Qnil;
- break;
-
- case Bstringp:
- TOP = STRINGP (TOP) ? Qt : Qnil;
- break;
-
- case Blistp:
- TOP = CONSP (TOP) || NILP (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 = NILP (TOP) ? Qt : Qnil;
- break;
-
- case Bcar:
- v1 = TOP;
- docar:
- if (CONSP (v1)) TOP = XCONS (v1)->car;
- else if (NILP (v1)) TOP = Qnil;
- else Fcar (wrong_type_argument (Qlistp, v1));
- break;
-
- case Bcdr:
- v1 = TOP;
- if (CONSP (v1)) TOP = XCONS (v1)->cdr;
- else if (NILP (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 BlistN:
- op = FETCH;
- DISCARD (op - 1);
- TOP = Flist (op, &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 BconcatN:
- op = FETCH;
- DISCARD (op - 1);
- TOP = Fconcat (op, &TOP);
- break;
-
- case Bsub1:
- v1 = TOP;
- if (INTEGERP (v1))
- {
- XSETINT (v1, XINT (v1) - 1);
- TOP = v1;
- }
- else
- TOP = Fsub1 (v1);
- break;
-
- case Badd1:
- v1 = TOP;
- if (INTEGERP (v1))
- {
- XSETINT (v1, XINT (v1) + 1);
- TOP = v1;
- }
- else
- TOP = Fadd1 (v1);
- break;
-
- case Beqlsign:
- v2 = POP; v1 = TOP;
- CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (v1, 0);
- CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (v2, 0);
-#ifdef LISP_FLOAT_TYPE
- if (FLOATP (v1) || FLOATP (v2))
- {
- double f1, f2;
-
- f1 = (FLOATP (v1) ? XFLOAT (v1)->data : XINT (v1));
- f2 = (FLOATP (v2) ? XFLOAT (v2)->data : XINT (v2));
- TOP = (f1 == f2 ? Qt : Qnil);
- }
- else
-#endif
- 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 (INTEGERP (v1))
- {
- 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 Bmult:
- DISCARD (1);
- TOP = Ftimes (2, &TOP);
- break;
-
- case Bquo:
- DISCARD (1);
- TOP = Fquo (2, &TOP);
- break;
-
- case Brem:
- v1 = POP;
- TOP = Frem (TOP, v1);
- break;
-
- case Bpoint:
- XSETFASTINT (v1, PT);
- PUSH (v1);
- break;
-
- case Bgoto_char:
- TOP = Fgoto_char (TOP);
- break;
-
- case Binsert:
- TOP = Finsert (1, &TOP);
- break;
-
- case BinsertN:
- op = FETCH;
- DISCARD (op - 1);
- TOP = Finsert (op, &TOP);
- break;
-
- case Bpoint_max:
- XSETFASTINT (v1, ZV);
- PUSH (v1);
- break;
-
- case Bpoint_min:
- XSETFASTINT (v1, BEGV);
- PUSH (v1);
- break;
-
- case Bchar_after:
- TOP = Fchar_after (TOP);
- break;
-
- case Bfollowing_char:
- v1 = Ffollowing_char ();
- PUSH (v1);
- break;
-
- case Bpreceding_char:
- v1 = Fprevious_char ();
- PUSH (v1);
- break;
-
- case Bcurrent_column:
- XSETFASTINT (v1, current_column ());
- PUSH (v1);
- break;
-
- case Bindent_to:
- TOP = Findent_to (TOP, Qnil);
- 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 Binteractive_p:
- PUSH (Finteractive_p ());
- break;
-
- case Bforward_char:
- TOP = Fforward_char (TOP);
- break;
-
- case Bforward_word:
- TOP = Fforward_word (TOP);
- break;
-
- case Bskip_chars_forward:
- v1 = POP;
- TOP = Fskip_chars_forward (TOP, v1);
- break;
-
- case Bskip_chars_backward:
- v1 = POP;
- TOP = Fskip_chars_backward (TOP, v1);
- break;
-
- case Bforward_line:
- TOP = Fforward_line (TOP);
- break;
-
- case Bchar_syntax:
- CHECK_NUMBER (TOP, 0);
- XSETFASTINT (TOP,
- syntax_code_spec[(int) SYNTAX (XINT (TOP))]);
- break;
-
- case Bbuffer_substring:
- v1 = POP;
- TOP = Fbuffer_substring (TOP, v1);
- break;
-
- case Bdelete_region:
- v1 = POP;
- TOP = Fdelete_region (TOP, v1);
- break;
-
- case Bnarrow_to_region:
- v1 = POP;
- TOP = Fnarrow_to_region (TOP, v1);
- break;
-
- case Bwiden:
- PUSH (Fwiden ());
- break;
-
- case Bend_of_line:
- TOP = Fend_of_line (TOP);
- break;
-
- case Bset_marker:
- v1 = POP;
- v2 = POP;
- TOP = Fset_marker (TOP, v2, v1);
- break;
-
- case Bmatch_beginning:
- TOP = Fmatch_beginning (TOP);
- break;
-
- case Bmatch_end:
- TOP = Fmatch_end (TOP);
- break;
-
- case Bupcase:
- TOP = Fupcase (TOP);
- break;
-
- case Bdowncase:
- TOP = Fdowncase (TOP);
- break;
-
- case Bstringeqlsign:
- v1 = POP;
- TOP = Fstring_equal (TOP, v1);
- break;
-
- case Bstringlss:
- v1 = POP;
- TOP = Fstring_lessp (TOP, v1);
- break;
-
- case Bequal:
- v1 = POP;
- TOP = Fequal (TOP, v1);
- break;
-
- case Bnthcdr:
- v1 = POP;
- TOP = Fnthcdr (TOP, v1);
- break;
-
- case Belt:
- if (CONSP (TOP))
- {
- /* Exchange args and then do nth. */
- v2 = POP;
- v1 = TOP;
- goto nth_entry;
- }
- v1 = POP;
- TOP = Felt (TOP, v1);
- break;
-
- case Bmember:
- v1 = POP;
- TOP = Fmember (TOP, v1);
- break;
-
- case Bassq:
- v1 = POP;
- TOP = Fassq (TOP, v1);
- break;
-
- case Bnreverse:
- TOP = Fnreverse (TOP);
- break;
-
- case Bsetcar:
- v1 = POP;
- TOP = Fsetcar (TOP, v1);
- break;
-
- case Bsetcdr:
- v1 = POP;
- TOP = Fsetcdr (TOP, v1);
- break;
-
- case Bcar_safe:
- v1 = TOP;
- if (CONSP (v1))
- TOP = XCONS (v1)->car;
- else
- TOP = Qnil;
- break;
-
- case Bcdr_safe:
- v1 = TOP;
- if (CONSP (v1))
- TOP = XCONS (v1)->cdr;
- else
- TOP = Qnil;
- break;
-
- case Bnconc:
- DISCARD (1);
- TOP = Fnconc (2, &TOP);
- break;
-
- case Bnumberp:
- TOP = (NUMBERP (TOP) ? Qt : Qnil);
- break;
-
- case Bintegerp:
- TOP = INTEGERP (TOP) ? Qt : Qnil;
- break;
-
-#ifdef BYTE_CODE_SAFE
- case Bset_mark:
- error ("set-mark is an obsolete bytecode");
- break;
- case Bscan_buffer:
- error ("scan-buffer is an obsolete bytecode");
- break;
- case Bmark:
- error ("mark is an obsolete bytecode");
- break;
-#endif
-
- default:
-#ifdef BYTE_CODE_SAFE
- if (op < Bconstant)
- error ("unknown bytecode %d (byte compiler bug)", op);
- if ((op -= Bconstant) >= const_length)
- error ("no constant number %d (byte compiler bug)", op);
- PUSH (vectorp[op]);
-#else
- PUSH (vectorp[op - Bconstant]);
-#endif
- }
- }
-
- exit:
- UNGCPRO;
- /* Binds and unbinds are supposed to be compiled balanced. */
- if (specpdl_ptr - specpdl != count)
-#ifdef BYTE_CODE_SAFE
- error ("binding stack not balanced (serious byte compiler bug)");
-#else
- abort ();
-#endif
- return v1;
-}
-
-syms_of_bytecode ()
-{
- Qbytecode = intern ("byte-code");
- staticpro (&Qbytecode);
-
- defsubr (&Sbyte_code);
-
-#ifdef BYTE_CODE_METER
-
- DEFVAR_LISP ("byte-code-meter", &Vbyte_code_meter,
- "A vector of vectors which holds a histogram of byte-code usage.\n\
-(aref (aref byte-code-meter 0) CODE) indicates how many times the byte\n\
-opcode CODE has been executed.\n\
-(aref (aref byte-code-meter CODE1) CODE2), where CODE1 is not 0,\n\
-indicates how many times the byte opcodes CODE1 and CODE2 have been\n\
-executed in succession.");
- DEFVAR_BOOL ("byte-metering-on", &byte_metering_on,
- "If non-nil, keep profiling information on byte code usage.\n\
-The variable byte-code-meter indicates how often each byte opcode is used.\n\
-If a symbol has a property named `byte-code-meter' whose value is an\n\
-integer, it is incremented each time that symbol's function is called.");
-
- byte_metering_on = 0;
- Vbyte_code_meter = Fmake_vector (make_number (256), make_number (0));
- Qbyte_code_meter = intern ("byte-code-meter");
- staticpro (&Qbyte_code_meter);
- {
- int i = 256;
- while (i--)
- XVECTOR (Vbyte_code_meter)->contents[i] =
- Fmake_vector (make_number (256), make_number (0));
- }
-#endif
-}
diff --git a/src/callint.c b/src/callint.c
deleted file mode 100644
index 5cedc443933..00000000000
--- a/src/callint.c
+++ /dev/null
@@ -1,824 +0,0 @@
-/* Call a Lisp function interactively.
- Copyright (C) 1985, 1986, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include "lisp.h"
-#include "buffer.h"
-#include "commands.h"
-#include "keyboard.h"
-#include "window.h"
-#include "mocklisp.h"
-
-extern char *index ();
-
-extern Lisp_Object Qcursor_in_echo_area;
-
-Lisp_Object Vcurrent_prefix_arg, Qminus, Qplus;
-Lisp_Object Qcall_interactively;
-Lisp_Object Vcommand_history;
-
-Lisp_Object Vcommand_debug_status, Qcommand_debug_status;
-Lisp_Object Qenable_recursive_minibuffers;
-
-/* Non-nil means treat the mark as active
- even if mark_active is 0. */
-Lisp_Object Vmark_even_if_inactive;
-
-Lisp_Object Vmouse_leave_buffer_hook, Qmouse_leave_buffer_hook;
-
-Lisp_Object Qlist, Qlet, Qletx, Qsave_excursion;
-static Lisp_Object preserved_fns;
-
-/* Marker used within call-interactively to refer to point. */
-static Lisp_Object point_marker;
-
-/* Buffer for the prompt text used in Fcall_interactively. */
-static char *callint_message;
-
-/* Allocated length of that buffer. */
-static int callint_message_size;
-
-/* 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 foo (arg) \"Doc string\" (interactive \"p\") ...use arg...)\n\
-to make ARG be the prefix argument when `foo' is called as a command.\n\
-The \"call\" to `interactive' 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\
- Prompts are passed to format, and may use % escapes to print the\n\
- arguments that have already been read.\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\
-e -- Parametrized event (i.e., one that's a list) that invoked this command.\n\
- If used more than once, the Nth `e' returns the Nth parameterized event.\n\
- This skips events that are integers or symbols.\n\
-f -- Existing file name.\n\
-F -- Possibly nonexistent file name.\n\
-k -- Key sequence (downcase the last event if needed to get a definition).\n\
-K -- Key sequence to be redefined (do not downcase the last event).\n\
-m -- Value of mark as number. Does not do I/O.\n\
-n -- Number read using minibuffer.\n\
-N -- Raw prefix arg, 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 string begins with `*'\n\
- then an error is signaled if the buffer is read-only.\n\
- This happens before reading any arguments.\n\
-If the string begins with `@', then Emacs searches the key sequence\n\
- which invoked the command for its first mouse click (or any other\n\
- event which specifies a window), and selects that window before\n\
- reading any arguments. You may use both `@' and `*'; they are\n\
- processed in the order that they appear." */
-
-/* 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 (!INTEGERP (exp) && !STRINGP (exp)
- && !NILP (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;
- tem = Fmarker_buffer (current_buffer->mark);
- if (NILP (tem) || (XBUFFER (tem) != current_buffer))
- error ("The mark is not set now");
- if (!NILP (Vtransient_mark_mode) && NILP (Vmark_even_if_inactive)
- && NILP (current_buffer->mark_active))
- Fsignal (Qmark_inactive, Qnil);
-}
-
-
-DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 3, 0,
- "Call FUNCTION, reading args according to its interactive calling specs.\n\
-Return the value FUNCTION returns.\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_flag, keys)
- Lisp_Object function, record_flag, keys;
-{
- Lisp_Object *args, *visargs;
- unsigned char **argstrings;
- Lisp_Object fun;
- Lisp_Object funcar;
- Lisp_Object specs;
- Lisp_Object teml;
- Lisp_Object enable;
- int speccount = specpdl_ptr - specpdl;
-
- /* The index of the next element of this_command_keys to examine for
- the 'e' interactive code. */
- int next_event;
-
- Lisp_Object prefix_arg;
- unsigned char *string;
- unsigned char *tem;
-
- /* If varies[i] > 0, the i'th argument shouldn't just have its value
- in this call quoted in the command history. It should be
- recorded as a call to the function named callint_argfuns[varies[i]]. */
- int *varies;
-
- register int i, j;
- int count, foo;
- char prompt1[100];
- char *tem1;
- int arg_from_tty = 0;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
- int key_count;
-
- if (NILP (keys))
- keys = this_command_keys, key_count = this_command_key_count;
- else
- {
- CHECK_VECTOR (keys, 3);
- key_count = XVECTOR (keys)->size;
- }
-
- /* Save this now, since use of minibuffer will clobber it. */
- prefix_arg = Vcurrent_prefix_arg;
-
- retry:
-
- if (SYMBOLP (function))
- enable = Fget (function, Qenable_recursive_minibuffers);
-
- fun = indirect_function (function);
-
- specs = Qnil;
- string = 0;
-
- /* Decode the kind of function. Either handle it and return,
- or go to `lose' if not interactive, or go to `retry'
- to specify a different function, or set either STRING or SPECS. */
-
- if (SUBRP (fun))
- {
- string = (unsigned char *) XSUBR (fun)->prompt;
- if (!string)
- {
- lose:
- function = wrong_type_argument (Qcommandp, function);
- goto retry;
- }
- if ((EMACS_INT) string == 1)
- /* Let SPECS (which is nil) be used as the args. */
- string = 0;
- }
- else if (COMPILEDP (fun))
- {
- if ((XVECTOR (fun)->size & PSEUDOVECTOR_SIZE_MASK) <= COMPILED_INTERACTIVE)
- goto lose;
- specs = XVECTOR (fun)->contents[COMPILED_INTERACTIVE];
- }
- 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 (NILP (specs))
- goto lose;
- specs = Fcar (Fcdr (specs));
- }
- else if (EQ (funcar, Qmocklisp))
- {
- single_kboard_state ();
- return ml_apply (fun, Qinteractive);
- }
- else
- goto lose;
-
- /* If either specs or string is set to a string, use it. */
- if (STRINGP (specs))
- {
- /* 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 if (string == 0)
- {
- Lisp_Object input;
- i = num_input_chars;
- input = specs;
- /* Compute the arg values using the user's expression. */
- specs = Feval (specs);
- if (i != num_input_chars || !NILP (record_flag))
- {
- /* We should record this command on the command history. */
- Lisp_Object values, car;
- /* Make a copy of the list of values, for the command history,
- and turn them into things we can eval. */
- values = quotify_args (Fcopy_sequence (specs));
- /* If the list of args was produced with an explicit call to `list',
- look for elements that were computed with (region-beginning)
- or (region-end), and put those expressions into VALUES
- instead of the present values. */
- if (CONSP (input))
- {
- car = XCONS (input)->car;
- /* Skip through certain special forms. */
- while (EQ (car, Qlet) || EQ (car, Qletx)
- || EQ (car, Qsave_excursion))
- {
- while (CONSP (XCONS (input)->cdr))
- input = XCONS (input)->cdr;
- input = XCONS (input)->car;
- if (!CONSP (input))
- break;
- car = XCONS (input)->car;
- }
- if (EQ (car, Qlist))
- {
- Lisp_Object intail, valtail;
- for (intail = Fcdr (input), valtail = values;
- CONSP (valtail);
- intail = Fcdr (intail), valtail = Fcdr (valtail))
- {
- Lisp_Object elt;
- elt = Fcar (intail);
- if (CONSP (elt))
- {
- Lisp_Object presflag;
- presflag = Fmemq (Fcar (elt), preserved_fns);
- if (!NILP (presflag))
- Fsetcar (valtail, Fcar (intail));
- }
- }
- }
- }
- Vcommand_history
- = Fcons (Fcons (function, values), Vcommand_history);
- }
- single_kboard_state ();
- return apply1 (function, specs);
- }
-
- /* Here if function specifies a string to control parsing the defaults */
-
- /* Set next_event to point to the first event with parameters. */
- for (next_event = 0; next_event < key_count; next_event++)
- if (EVENT_HAS_PARAMETERS (XVECTOR (keys)->contents[next_event]))
- break;
-
- /* Handle special starting chars `*' and `@'. Also `-'. */
- /* Note that `+' is reserved for user extensions. */
- while (1)
- {
- if (*string == '+')
- error ("`+' is not used in `interactive' for ordinary commands");
- else if (*string == '*')
- {
- string++;
- if (!NILP (current_buffer->read_only))
- Fbarf_if_buffer_read_only ();
- }
- /* Ignore this for semi-compatibility with Lucid. */
- else if (*string == '-')
- string++;
- else if (*string == '@')
- {
- Lisp_Object event;
-
- event = XVECTOR (keys)->contents[next_event];
- if (EVENT_HAS_PARAMETERS (event)
- && (event = XCONS (event)->cdr, CONSP (event))
- && (event = XCONS (event)->car, CONSP (event))
- && (event = XCONS (event)->car, WINDOWP (event)))
- {
- if (MINI_WINDOW_P (XWINDOW (event))
- && ! (minibuf_level > 0 && EQ (event, minibuf_window)))
- error ("Attempt to select inactive minibuffer window");
-
- /* If the current buffer wants to clean up, let it. */
- if (!NILP (Vmouse_leave_buffer_hook))
- call1 (Vrun_hooks, Qmouse_leave_buffer_hook);
-
- Fselect_window (event);
- }
- string++;
- }
- else break;
- }
-
- /* Count the number of arguments the interactive spec would have
- us give to the function. */
- tem = string;
- for (j = 0; *tem; j++)
- {
- /* 'r' specifications ("point and mark as 2 numeric args")
- produce *two* arguments. */
- 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);
-
- if (!NILP (enable))
- specbind (Qenable_recursive_minibuffers, Qt);
-
- 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;
-
- /* Process the format-string in prompt1, putting the output
- into callint_message. Make callint_message bigger if necessary.
- We don't use a buffer on the stack, because the contents
- need to stay stable for a while. */
- while (1)
- {
- int nchars = doprnt (callint_message, callint_message_size,
- prompt1, (char *)0,
- j - 1, argstrings + 1);
- if (nchars < callint_message_size)
- break;
- callint_message_size *= 2;
- callint_message
- = (char *) xrealloc (callint_message, callint_message_size);
- }
-
- switch (*tem)
- {
- case 'a': /* Symbol defined as a function */
- visargs[i] = Fcompleting_read (build_string (callint_message),
- Vobarray, Qfboundp, Qt, Qnil, 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], Qnil);
- args[i] = Fread_buffer (build_string (callint_message), args[i], Qt);
- break;
-
- case 'B': /* Name of buffer, possibly nonexistent */
- args[i] = Fread_buffer (build_string (callint_message),
- Fother_buffer (Fcurrent_buffer (), Qnil),
- Qnil);
- break;
-
- case 'c': /* Character */
- /* Use message_nolog rather than message1_nolog here,
- so that nothing bad happens if callint_message is changed
- within Fread_char (by a timer, for example). */
- message_nolog ("%s", callint_message);
- args[i] = Fread_char ();
- message1_nolog ((char *) 0);
- /* 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 (callint_message),
- Vobarray, Qcommandp, Qt, Qnil, 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. */
- Fset_marker (point_marker, make_number (PT), Qnil);
- args[i] = point_marker;
- /* visargs[i] = Qnil; */
- varies[i] = 1;
- break;
-
- case 'D': /* Directory name. */
- args[i] = Fread_file_name (build_string (callint_message), Qnil,
- current_buffer->directory, Qlambda, Qnil);
- break;
-
- case 'f': /* Existing file name. */
- args[i] = Fread_file_name (build_string (callint_message),
- Qnil, Qnil, Qlambda, Qnil);
- break;
-
- case 'F': /* Possibly nonexistent file name. */
- args[i] = Fread_file_name (build_string (callint_message),
- Qnil, Qnil, Qnil, Qnil);
- break;
-
- case 'k': /* Key sequence. */
- {
- int speccount1 = specpdl_ptr - specpdl;
- specbind (Qcursor_in_echo_area, Qt);
- args[i] = Fread_key_sequence (build_string (callint_message),
- Qnil, Qnil, Qnil);
- unbind_to (speccount1, Qnil);
- teml = args[i];
- visargs[i] = Fkey_description (teml);
- }
- break;
-
- case 'K': /* Key sequence to be defined. */
- {
- int speccount1 = specpdl_ptr - specpdl;
- specbind (Qcursor_in_echo_area, Qt);
- args[i] = Fread_key_sequence (build_string (callint_message),
- Qnil, Qt, Qnil);
- teml = args[i];
- visargs[i] = Fkey_description (teml);
- unbind_to (speccount1, Qnil);
- }
- break;
-
- case 'e': /* The invoking event. */
- if (next_event >= key_count)
- error ("%s must be bound to an event with parameters",
- (SYMBOLP (function)
- ? (char *) XSYMBOL (function)->name->data
- : "command"));
- args[i] = XVECTOR (keys)->contents[next_event++];
- varies[i] = -1;
-
- /* Find the next parameterized event. */
- while (next_event < key_count
- && ! (EVENT_HAS_PARAMETERS
- (XVECTOR (keys)->contents[next_event])))
- next_event++;
-
- break;
-
- case 'm': /* Value of mark. Does not do I/O. */
- check_mark ();
- /* visargs[i] = Qnil; */
- args[i] = current_buffer->mark;
- varies[i] = 2;
- break;
-
- case 'N': /* Prefix arg, else number from minibuffer */
- if (!NILP (prefix_arg))
- goto have_prefix_arg;
- case 'n': /* Read number from minibuffer. */
- {
- int first = 1;
- do
- {
- Lisp_Object tem;
- if (! first)
- {
- message ("Please enter a number.");
- sit_for (1, 0, 0, 0);
- }
- first = 0;
-
- tem = Fread_from_minibuffer (build_string (callint_message),
- Qnil, Qnil, Qnil, Qnil);
- if (! STRINGP (tem) || XSTRING (tem)->size == 0)
- args[i] = Qnil;
- else
- args[i] = Fread (tem);
- }
- while (! NUMBERP (args[i]));
- }
- 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 ();
- Fset_marker (point_marker, make_number (PT), Qnil);
- /* visargs[i+1] = Qnil; */
- foo = marker_position (current_buffer->mark);
- /* visargs[i] = Qnil; */
- args[i] = PT < foo ? point_marker : current_buffer->mark;
- varies[i] = 3;
- args[++i] = PT > foo ? point_marker : current_buffer->mark;
- varies[i] = 4;
- break;
-
- case 's': /* String read via minibuffer. */
- args[i] = Fread_string (build_string (callint_message), Qnil, Qnil);
- break;
-
- case 'S': /* Any symbol. */
- visargs[i] = Fread_string (build_string (callint_message),
- Qnil, Qnil);
- /* 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 (callint_message));
- visargs[i] = last_minibuf_string;
- break;
-
- case 'x': /* Lisp expression read but not evaluated */
- args[i] = Fread_minibuffer (build_string (callint_message), Qnil);
- visargs[i] = last_minibuf_string;
- break;
-
- case 'X': /* Lisp expression read and evaluated */
- args[i] = Feval_minibuffer (build_string (callint_message), Qnil);
- visargs[i] = last_minibuf_string;
- break;
-
- /* We have a case for `+' so we get an error
- if anyone tries to define one here. */
- case '+':
- default:
- error ("Invalid control letter `%c' (%03o) in interactive calling string",
- *tem, *tem);
- }
-
- if (varies[i] == 0)
- arg_from_tty = 1;
-
- if (NILP (visargs[i]) && STRINGP (args[i]))
- visargs[i] = args[i];
-
- tem = (unsigned char *) index (tem, '\n');
- if (tem) tem++;
- else tem = (unsigned char *) "";
- }
- unbind_to (speccount, Qnil);
-
- QUIT;
-
- args[0] = function;
-
- if (arg_from_tty || !NILP (record_flag))
- {
- 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);
- }
-
- /* If we used a marker to hold point, mark, or an end of the region,
- temporarily, convert it to an integer now. */
- for (i = 1; i <= count; i++)
- if (varies[i] >= 1 && varies[i] <= 4)
- XSETINT (args[i], marker_position (args[i]));
-
- single_kboard_state ();
-
- {
- Lisp_Object val;
- specbind (Qcommand_debug_status, Qnil);
-
- val = Ffuncall (count + 1, args);
- UNGCPRO;
- return unbind_to (speccount, val);
- }
-}
-
-DEFUN ("prefix-numeric-value", Fprefix_numeric_value, Sprefix_numeric_value,
- 1, 1, 0,
- "Return numeric meaning of raw prefix argument RAW.\n\
-A raw prefix argument is what you get from `(interactive \"P\")'.\n\
-Its numeric meaning is what you would get from `(interactive \"p\")'.")
- (raw)
- Lisp_Object raw;
-{
- Lisp_Object val;
-
- if (NILP (raw))
- XSETFASTINT (val, 1);
- else if (EQ (raw, Qminus))
- XSETINT (val, -1);
- else if (CONSP (raw) && INTEGERP (XCONS (raw)->car))
- XSETINT (val, XINT (XCONS (raw)->car));
- else if (INTEGERP (raw))
- val = raw;
- else
- XSETFASTINT (val, 1);
-
- return val;
-}
-
-syms_of_callint ()
-{
- point_marker = Fmake_marker ();
- staticpro (&point_marker);
-
- preserved_fns = Fcons (intern ("region-beginning"),
- Fcons (intern ("region-end"),
- Fcons (intern ("point"),
- Fcons (intern ("mark"), Qnil))));
- staticpro (&preserved_fns);
-
- Qlist = intern ("list");
- staticpro (&Qlist);
- Qlet = intern ("let");
- staticpro (&Qlet);
- Qletx = intern ("let*");
- staticpro (&Qletx);
- Qsave_excursion = intern ("save-excursion");
- staticpro (&Qsave_excursion);
-
- Qminus = intern ("-");
- staticpro (&Qminus);
-
- Qplus = intern ("+");
- staticpro (&Qplus);
-
- Qcall_interactively = intern ("call-interactively");
- staticpro (&Qcall_interactively);
-
- Qcommand_debug_status = intern ("command-debug-status");
- staticpro (&Qcommand_debug_status);
-
- Qenable_recursive_minibuffers = intern ("enable-recursive-minibuffers");
- staticpro (&Qenable_recursive_minibuffers);
-
- Qmouse_leave_buffer_hook = intern ("mouse-leave-buffer-hook");
- staticpro (&Qmouse_leave_buffer_hook);
-
- callint_message_size = 100;
- callint_message = (char *) xmalloc (callint_message_size);
-
-
- DEFVAR_KBOARD ("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\").");
-
- 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;
-
- DEFVAR_LISP ("command-debug-status", &Vcommand_debug_status,
- "Debugging status of current interactive command.\n\
-Bound each time `call-interactively' is called;\n\
-may be set by the debugger as a reminder for itself.");
- Vcommand_debug_status = Qnil;
-
- DEFVAR_LISP ("mark-even-if-inactive", &Vmark_even_if_inactive,
- "*Non-nil means you can use the mark even when inactive.\n\
-This option makes a difference in Transient Mark mode.\n\
-When the option is non-nil, deactivation of the mark\n\
-turns off region highlighting, but commands that use the mark\n\
-behave as if the mark were still active.");
- Vmark_even_if_inactive = Qnil;
-
- DEFVAR_LISP ("mouse-leave-buffer-hook", &Vmouse_leave_buffer_hook,
- "Hook to run when about to switch windows with a mouse command.\n\
-Its purpose is to give temporary modes such as Isearch mode\n\
-a way to turn themselves off when a mouse command switches windows.");
- Vmouse_leave_buffer_hook = Qnil;
-
- defsubr (&Sinteractive);
- defsubr (&Scall_interactively);
- defsubr (&Sprefix_numeric_value);
-}
diff --git a/src/callproc.c b/src/callproc.c
deleted file mode 100644
index 5d743d30696..00000000000
--- a/src/callproc.c
+++ /dev/null
@@ -1,1182 +0,0 @@
-/* Synchronous subprocess invocation for GNU Emacs.
- Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <signal.h>
-#include <errno.h>
-
-#include <config.h>
-#include <stdio.h>
-
-extern int errno;
-extern char *strerror ();
-
-/* Define SIGCHLD as an alias for SIGCLD. */
-
-#if !defined (SIGCHLD) && defined (SIGCLD)
-#define SIGCHLD SIGCLD
-#endif /* SIGCLD */
-
-#include <sys/types.h>
-
-#include <sys/file.h>
-#ifdef USG5
-#define INCLUDED_FCNTL
-#include <fcntl.h>
-#endif
-
-#ifdef WINDOWSNT
-#define NOMINMAX
-#include <windows.h>
-#include <stdlib.h> /* for proper declaration of environ */
-#include <fcntl.h>
-#include "w32.h"
-#define _P_NOWAIT 1 /* from process.h */
-#endif
-
-#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
-#include "msdos.h"
-#define INCLUDED_FCNTL
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <errno.h>
-#endif /* MSDOS */
-
-#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>
-#include "process.h"
-#include "syssignal.h"
-#include "systty.h"
-
-#ifdef VMS
-extern noshare char **environ;
-#else
-extern char **environ;
-#endif
-
-#define max(a, b) ((a) > (b) ? (a) : (b))
-
-#ifdef DOS_NT
-/* When we are starting external processes we need to know whether they
- take binary input (no conversion) or text input (\n is converted to
- \r\n). Similar for output: if newlines are written as \r\n then it's
- text process output, otherwise it's binary. */
-Lisp_Object Vbinary_process_input;
-Lisp_Object Vbinary_process_output;
-#endif /* DOS_NT */
-
-Lisp_Object Vexec_path, Vexec_directory, Vdata_directory, Vdoc_directory;
-Lisp_Object Vconfigure_info_directory;
-Lisp_Object Vtemp_file_name_pattern;
-
-Lisp_Object Vshell_file_name;
-
-Lisp_Object Vprocess_environment;
-
-#ifdef DOS_NT
-Lisp_Object Qbuffer_file_type;
-#endif /* DOS_NT */
-
-/* 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;
-
-/* If synch_process_death is zero,
- this is exit code of synchronous subprocess. */
-int synch_process_retcode;
-
-extern Lisp_Object Vdoc_file_name;
-
-/* Clean up when exiting Fcall_process.
- On MSDOS, delete the temporary file on any kind of termination.
- On Unix, kill the process and any children on termination by signal. */
-
-/* Nonzero if this is termination due to exit. */
-static int call_process_exited;
-
-#ifndef VMS /* VMS version is in vmsproc.c. */
-
-static Lisp_Object
-call_process_kill (fdpid)
- Lisp_Object fdpid;
-{
- close (XFASTINT (Fcar (fdpid)));
- EMACS_KILLPG (XFASTINT (Fcdr (fdpid)), SIGKILL);
- synch_process_alive = 0;
- return Qnil;
-}
-
-Lisp_Object
-call_process_cleanup (fdpid)
- Lisp_Object fdpid;
-{
-#ifdef MSDOS
- /* for MSDOS fdpid is really (fd . tempfile) */
- register Lisp_Object file;
- file = Fcdr (fdpid);
- close (XFASTINT (Fcar (fdpid)));
- if (strcmp (XSTRING (file)-> data, NULL_DEVICE) != 0)
- unlink (XSTRING (file)->data);
-#else /* not MSDOS */
- register int pid = XFASTINT (Fcdr (fdpid));
-
-
- if (call_process_exited)
- {
- close (XFASTINT (Fcar (fdpid)));
- return Qnil;
- }
-
- if (EMACS_KILLPG (pid, SIGINT) == 0)
- {
- int count = specpdl_ptr - specpdl;
- record_unwind_protect (call_process_kill, fdpid);
- message1 ("Waiting for process to die...(type C-g again to kill it instantly)");
- immediate_quit = 1;
- QUIT;
- wait_for_termination (pid);
- immediate_quit = 0;
- specpdl_ptr = specpdl + count; /* Discard the unwind protect. */
- message1 ("Waiting for process to die...done");
- }
- synch_process_alive = 0;
- close (XFASTINT (Fcar (fdpid)));
-#endif /* not MSDOS */
- return Qnil;
-}
-
-DEFUN ("call-process", Fcall_process, Scall_process, 1, MANY, 0,
- "Call PROGRAM synchronously in separate process.\n\
-The 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\
-BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,\n\
-REAL-BUFFER says what to do with standard output, as above,\n\
-while STDERR-FILE says what to do with standard error in the child.\n\
-STDERR-FILE may be nil (discard standard error output),\n\
-t (mix it with ordinary output), or a file name string.\n\
-\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\
-\n\
-If BUFFER is 0, `call-process' returns immediately with value nil.\n\
-Otherwise it 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 SIGINT, or SIGKILL if you quit again.")
- (nargs, args)
- int nargs;
- register Lisp_Object *args;
-{
- Lisp_Object infile, buffer, current_dir, display, path;
- int fd[2];
- int filefd;
- register int pid;
- char buf[16384];
- char *bufptr = buf;
- int bufsize = 16384;
- int count = specpdl_ptr - specpdl;
- register unsigned char **new_argv
- = (unsigned char **) alloca ((max (2, nargs - 2)) * sizeof (char *));
- struct buffer *old = current_buffer;
- /* File to use for stderr in the child.
- t means use same as standard output. */
- Lisp_Object error_file;
-#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
- char *outf, *tempfile;
- int outfilefd;
-#endif
-#if 0
- int mask;
-#endif
- CHECK_STRING (args[0], 0);
-
- error_file = Qt;
-
-#ifndef subprocesses
- /* Without asynchronous processes we cannot have BUFFER == 0. */
- if (nargs >= 3 && INTEGERP (args[2]))
- error ("Operating system cannot handle asynchronous subprocesses");
-#endif /* subprocesses */
-
- if (nargs >= 2 && ! NILP (args[1]))
- {
- infile = Fexpand_file_name (args[1], current_buffer->directory);
- CHECK_STRING (infile, 1);
- }
- else
- infile = build_string (NULL_DEVICE);
-
- if (nargs >= 3)
- {
- buffer = args[2];
-
- /* If BUFFER is a list, its meaning is
- (BUFFER-FOR-STDOUT FILE-FOR-STDERR). */
- if (CONSP (buffer))
- {
- if (CONSP (XCONS (buffer)->cdr))
- {
- Lisp_Object stderr_file;
- stderr_file = XCONS (XCONS (buffer)->cdr)->car;
-
- if (NILP (stderr_file) || EQ (Qt, stderr_file))
- error_file = stderr_file;
- else
- error_file = Fexpand_file_name (stderr_file, Qnil);
- }
-
- buffer = XCONS (buffer)->car;
- }
-
- if (!(EQ (buffer, Qnil)
- || EQ (buffer, Qt)
- || XFASTINT (buffer) == 0))
- {
- Lisp_Object spec_buffer;
- spec_buffer = buffer;
- buffer = Fget_buffer (buffer);
- /* Mention the buffer name for a better error message. */
- if (NILP (buffer))
- CHECK_BUFFER (spec_buffer, 2);
- CHECK_BUFFER (buffer, 2);
- }
- }
- else
- buffer = Qnil;
-
- /* Make sure that the child will be able to chdir to the current
- buffer's current directory, or its unhandled equivalent. We
- can't just have the child check for an error when it does the
- chdir, since it's in a vfork.
-
- We have to GCPRO around this because Fexpand_file_name,
- Funhandled_file_name_directory, and Ffile_accessible_directory_p
- might call a file name handling function. The argument list is
- protected by the caller, so all we really have to worry about is
- buffer. */
- {
- struct gcpro gcpro1, gcpro2, gcpro3;
-
- current_dir = current_buffer->directory;
-
- GCPRO3 (infile, buffer, current_dir);
-
- current_dir
- = expand_and_dir_to_file (Funhandled_file_name_directory (current_dir),
- Qnil);
- if (NILP (Ffile_accessible_directory_p (current_dir)))
- report_file_error ("Setting current directory",
- Fcons (current_buffer->directory, Qnil));
-
- UNGCPRO;
- }
-
- display = nargs >= 4 ? args[3] : Qnil;
-
- filefd = open (XSTRING (infile)->data, O_RDONLY, 0);
- if (filefd < 0)
- {
- report_file_error ("Opening process input file", Fcons (infile, Qnil));
- }
- /* Search for program; barf if not found. */
- {
- struct gcpro gcpro1;
-
- GCPRO1 (current_dir);
- openp (Vexec_path, args[0], EXEC_SUFFIXES, &path, 1);
- UNGCPRO;
- }
- if (NILP (path))
- {
- close (filefd);
- report_file_error ("Searching for program", Fcons (args[0], Qnil));
- }
- new_argv[0] = XSTRING (path)->data;
- {
- register int i;
- for (i = 4; i < nargs; i++)
- {
- CHECK_STRING (args[i], i);
- new_argv[i - 3] = XSTRING (args[i])->data;
- }
- new_argv[i - 3] = 0;
- }
-
-#ifdef MSDOS /* MW, July 1993 */
- if ((outf = egetenv ("TMP")) || (outf = egetenv ("TEMP")))
- strcpy (tempfile = alloca (strlen (outf) + 20), outf);
- else
- {
- tempfile = alloca (20);
- *tempfile = '\0';
- }
- dostounix_filename (tempfile);
- if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/')
- strcat (tempfile, "/");
- strcat (tempfile, "detmp.XXX");
- mktemp (tempfile);
-
- outfilefd = creat (tempfile, S_IREAD | S_IWRITE);
- if (outfilefd < 0)
- {
- close (filefd);
- report_file_error ("Opening process output file",
- Fcons (build_string (tempfile), Qnil));
- }
- fd[0] = filefd;
- fd[1] = outfilefd;
-#endif /* MSDOS */
-
- if (INTEGERP (buffer))
- fd[1] = open (NULL_DEVICE, O_WRONLY), fd[0] = -1;
- else
- {
-#ifndef MSDOS
- pipe (fd);
-#endif
-#if 0
- /* Replaced by close_process_descs */
- set_exclusive_use (fd[0]);
-#endif
- }
-
- {
- /* 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];
- int fd_error = fd1;
-
-#if 0 /* Some systems don't have sigblock. */
- mask = sigblock (sigmask (SIGCHLD));
-#endif
-
- /* Record that we're about to create a synchronous process. */
- synch_process_alive = 1;
-
- /* These vars record information from process termination.
- Clear them now before process can possibly terminate,
- to avoid timing error if process terminates soon. */
- synch_process_death = 0;
- synch_process_retcode = 0;
-
- if (NILP (error_file))
- fd_error = open (NULL_DEVICE, O_WRONLY);
- else if (STRINGP (error_file))
- {
-#ifdef DOS_NT
- fd_error = open (XSTRING (error_file)->data,
- O_WRONLY | O_TRUNC | O_CREAT | O_TEXT,
- S_IREAD | S_IWRITE);
-#else /* not DOS_NT */
- fd_error = creat (XSTRING (error_file)->data, 0666);
-#endif /* not DOS_NT */
- }
-
- if (fd_error < 0)
- {
- close (filefd);
- if (fd[0] != filefd)
- close (fd[0]);
- if (fd1 >= 0)
- close (fd1);
-#ifdef MSDOS
- unlink (tempfile);
-#endif
- report_file_error ("Cannot redirect stderr",
- Fcons ((NILP (error_file)
- ? build_string (NULL_DEVICE) : error_file),
- Qnil));
- }
-#ifdef MSDOS /* MW, July 1993 */
- /* ??? Someone who knows MSDOG needs to check whether this properly
- closes all descriptors that it opens.
-
- Note that run_msdos_command() actually returns the child process
- exit status, not its PID, so we assign it to `synch_process_retcode'
- below. */
- pid = run_msdos_command (new_argv, current_dir,
- filefd, outfilefd, fd_error);
-
- /* Record that the synchronous process exited and note its
- termination status. */
- synch_process_alive = 0;
- synch_process_retcode = pid;
- if (synch_process_retcode < 0) /* means it couldn't be exec'ed */
- synch_process_death = strerror(errno);
-
- close (outfilefd);
- if (fd_error != outfilefd)
- close (fd_error);
- fd1 = -1; /* No harm in closing that one! */
- fd[0] = open (tempfile, NILP (Vbinary_process_output) ? O_TEXT : O_BINARY);
- if (fd[0] < 0)
- {
- unlink (tempfile);
- close (filefd);
- report_file_error ("Cannot re-open temporary file", Qnil);
- }
-#else /* not MSDOS */
-#ifdef WINDOWSNT
- pid = child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir);
-#else /* not WINDOWSNT */
- pid = vfork ();
-
- if (pid == 0)
- {
- if (fd[0] >= 0)
- close (fd[0]);
-#if defined(USG) && !defined(BSD_PGRPS)
- setpgrp ();
-#else
- setpgrp (pid, pid);
-#endif /* USG */
- child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir);
- }
-#endif /* not WINDOWSNT */
-
- /* The MSDOS case did this already. */
- if (fd_error >= 0)
- close (fd_error);
-#endif /* not MSDOS */
-
- environ = save_environ;
-
- /* Close most of our fd's, but not fd[0]
- since we will use that to read input from. */
- close (filefd);
- if (fd1 >= 0 && fd1 != fd_error)
- close (fd1);
- }
-
- if (pid < 0)
- {
- if (fd[0] >= 0)
- close (fd[0]);
- report_file_error ("Doing vfork", Qnil);
- }
-
- if (INTEGERP (buffer))
- {
- if (fd[0] >= 0)
- close (fd[0]);
-#ifndef subprocesses
- /* If Emacs has been built with asynchronous subprocess support,
- we don't need to do this, I think because it will then have
- the facilities for handling SIGCHLD. */
- wait_without_blocking ();
-#endif /* subprocesses */
- return Qnil;
- }
-
- /* Enable sending signal if user quits below. */
- call_process_exited = 0;
-
-#ifdef MSDOS
- /* MSDOS needs different cleanup information. */
- record_unwind_protect (call_process_cleanup,
- Fcons (make_number (fd[0]), build_string (tempfile)));
-#else
- record_unwind_protect (call_process_cleanup,
- Fcons (make_number (fd[0]), make_number (pid)));
-#endif /* not MSDOS */
-
-
- if (BUFFERP (buffer))
- Fset_buffer (buffer);
-
- immediate_quit = 1;
- QUIT;
-
- {
- register int nread;
- int first = 1;
- int total_read = 0;
-
- while (1)
- {
- /* Repeatedly read until we've filled as much as possible
- of the buffer size we have. But don't read
- less than 1024--save that for the next bufferful. */
-
- nread = 0;
- while (nread < bufsize - 1024)
- {
- int this_read
- = read (fd[0], bufptr + nread, bufsize - nread);
-
- if (this_read < 0)
- goto give_up;
-
- if (this_read == 0)
- goto give_up_1;
-
- nread += this_read;
- }
-
- give_up_1:
-
- /* Now NREAD is the total amount of data in the buffer. */
- if (nread == 0)
- break;
-
- immediate_quit = 0;
- total_read += nread;
-
- if (!NILP (buffer))
- insert (bufptr, nread);
-
- /* Make the buffer bigger as we continue to read more data,
- but not past 64k. */
- if (bufsize < 64 * 1024 && total_read > 32 * bufsize)
- {
- bufsize *= 2;
- bufptr = (char *) alloca (bufsize);
- }
-
- if (!NILP (display) && INTERACTIVE)
- {
- if (first)
- prepare_menu_bars ();
- first = 0;
- redisplay_preserve_echo_area ();
- }
- immediate_quit = 1;
- QUIT;
- }
- give_up: ;
- }
-
- /* Wait for it to terminate, unless it already has. */
- wait_for_termination (pid);
-
- immediate_quit = 0;
-
- set_buffer_internal (old);
-
- /* Don't kill any children that the subprocess may have left behind
- when exiting. */
- call_process_exited = 1;
-
- unbind_to (count, Qnil);
-
- if (synch_process_death)
- return build_string (synch_process_death);
- return make_number (synch_process_retcode);
-}
-#endif
-
-static Lisp_Object
-delete_temp_file (name)
- Lisp_Object name;
-{
- /* Use Fdelete_file (indirectly) because that runs a file name handler.
- We did that when writing the file, so we should do so when deleting. */
- internal_delete_file (name);
-}
-
-DEFUN ("call-process-region", Fcall_process_region, Scall_process_region,
- 3, MANY, 0,
- "Send text from START to END to a synchronous process running PROGRAM.\n\
-Delete the text if fourth arg DELETE is non-nil.\n\
-\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\
-BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,\n\
-REAL-BUFFER says what to do with standard output, as above,\n\
-while STDERR-FILE says what to do with standard error in the child.\n\
-STDERR-FILE may be nil (discard standard error output),\n\
-t (mix it with ordinary output), or a file name string.\n\
-\n\
-Sixth arg DISPLAY non-nil means redisplay buffer as output is inserted.\n\
-Remaining args are passed to PROGRAM at startup as command args.\n\
-\n\
-If BUFFER is nil, `call-process-region' returns immediately with value nil.\n\
-Otherwise it 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 SIGINT, or SIGKILL if you quit again.")
- (nargs, args)
- int nargs;
- register Lisp_Object *args;
-{
- struct gcpro gcpro1;
- Lisp_Object filename_string;
- register Lisp_Object start, end;
- int count = specpdl_ptr - specpdl;
-#ifdef DOS_NT
- char *tempfile;
- char *outf = '\0';
-
- if ((outf = egetenv ("TMP")) || (outf = egetenv ("TEMP")))
- strcpy (tempfile = alloca (strlen (outf) + 20), outf);
- else
- {
- tempfile = alloca (20);
- *tempfile = '\0';
- }
- if (!IS_DIRECTORY_SEP (tempfile[strlen (tempfile) - 1]))
- strcat (tempfile, "/");
- if ('/' == DIRECTORY_SEP)
- dostounix_filename (tempfile);
- else
- unixtodos_filename (tempfile);
-#ifdef WINDOWSNT
- strcat (tempfile, "emXXXXXX");
-#else
- strcat (tempfile, "detmp.XXX");
-#endif
-#else /* not DOS_NT */
- char *tempfile = (char *) alloca (XSTRING (Vtemp_file_name_pattern)->size + 1);
- bcopy (XSTRING (Vtemp_file_name_pattern)->data, tempfile,
- XSTRING (Vtemp_file_name_pattern)->size + 1);
-#endif /* not DOS_NT */
-
- mktemp (tempfile);
-
- filename_string = build_string (tempfile);
- GCPRO1 (filename_string);
- start = args[0];
- end = args[1];
-#ifdef DOS_NT
- specbind (Qbuffer_file_type, Vbinary_process_input);
- Fwrite_region (start, end, filename_string, Qnil, Qlambda, Qnil);
- unbind_to (count, Qnil);
-#else /* not DOS_NT */
- Fwrite_region (start, end, filename_string, Qnil, Qlambda, Qnil);
-#endif /* not DOS_NT */
-
- record_unwind_protect (delete_temp_file, filename_string);
-
- if (!NILP (args[3]))
- Fdelete_region (start, end);
-
- args[3] = filename_string;
-
- RETURN_UNGCPRO (unbind_to (count, Fcall_process (nargs - 2, args + 2)));
-}
-
-#ifndef VMS /* VMS version is in vmsproc.c. */
-
-/* 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 for the subprocess.
-
- SET_PGRP is nonzero if we should put the subprocess into a separate
- process group.
-
- CURRENT_DIR is an elisp string giving the path of the current
- directory the subprocess should have. Since we can't really signal
- a decent error from within the child, this should be verified as an
- executable directory by the parent. */
-
-child_setup (in, out, err, new_argv, set_pgrp, current_dir)
- int in, out, err;
- register char **new_argv;
- int set_pgrp;
- Lisp_Object current_dir;
-{
-#ifdef MSDOS
- /* The MSDOS port of gcc cannot fork, vfork, ... so we must call system
- instead. */
-#else /* not MSDOS */
- char **env;
- char *pwd_var;
-#ifdef WINDOWSNT
- int cpid;
- HANDLE handles[3];
-#endif /* WINDOWSNT */
-
- int pid = getpid ();
-
-#ifdef SET_EMACS_PRIORITY
- {
- extern int emacs_priority;
-
- if (emacs_priority < 0)
- nice (- emacs_priority);
- }
-#endif
-
-#ifdef subprocesses
- /* Close Emacs's descriptors that this process should not have. */
- close_process_descs ();
-#endif
- close_load_descs ();
-
- /* 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. */
- {
- register char *temp;
- register int i;
-
- i = XSTRING (current_dir)->size;
- pwd_var = (char *) alloca (i + 6);
- temp = pwd_var + 4;
- bcopy ("PWD=", pwd_var, 4);
- bcopy (XSTRING (current_dir)->data, temp, i);
- if (!IS_DIRECTORY_SEP (temp[i - 1])) temp[i++] = DIRECTORY_SEP;
- temp[i] = 0;
-
- /* We can't signal an Elisp error here; we're in a vfork. Since
- the callers check the current directory before forking, this
- should only return an error if the directory's permissions
- are changed between the check and this chdir, but we should
- at least check. */
- if (chdir (temp) < 0)
- _exit (errno);
-
- /* Strip trailing slashes for PWD, but leave "/" and "//" alone. */
- while (i > 2 && IS_DIRECTORY_SEP (temp[i - 1]))
- temp[--i] = 0;
- }
-
- /* 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;
- CONSP (tem) && STRINGP (XCONS (tem)->car);
- tem = XCONS (tem)->cdr)
- new_length++;
-
- /* new_length + 2 to include PWD and terminating 0. */
- env = new_env = (char **) alloca ((new_length + 2) * sizeof (char *));
-
- /* If we have a PWD envvar, pass one down,
- but with corrected value. */
- if (getenv ("PWD"))
- *new_env++ = pwd_var;
-
- /* Copy the Vprocess_environment strings into new_env. */
- for (tem = Vprocess_environment;
- CONSP (tem) && STRINGP (XCONS (tem)->car);
- tem = XCONS (tem)->cdr)
- {
- char **ep = env;
- char *string = (char *) XSTRING (XCONS (tem)->car)->data;
- /* See if this string duplicates any string already in the env.
- If so, don't put it in.
- When an env var has multiple definitions,
- we keep the definition that comes first in process-environment. */
- for (; ep != new_env; ep++)
- {
- char *p = *ep, *q = string;
- while (1)
- {
- if (*q == 0)
- /* The string is malformed; might as well drop it. */
- goto duplicate;
- if (*q != *p)
- break;
- if (*q == '=')
- goto duplicate;
- p++, q++;
- }
- }
- *new_env++ = string;
- duplicate: ;
- }
- *new_env = 0;
- }
-#ifdef WINDOWSNT
- prepare_standard_handles (in, out, err, handles);
-#else /* not WINDOWSNT */
- /* Make sure that in, out, and err are not actually already in
- descriptors zero, one, or two; this could happen if Emacs is
- started with its standard in, out, or error closed, as might
- happen under X. */
- {
- int oin = in, oout = out;
-
- /* We have to avoid relocating the same descriptor twice! */
-
- in = relocate_fd (in, 3);
-
- if (out == oin)
- out = in;
- else
- out = relocate_fd (out, 3);
-
- if (err == oin)
- err = in;
- else if (err == oout)
- err = out;
- else
- err = relocate_fd (err, 3);
- }
-
- close (0);
- close (1);
- close (2);
-
- dup2 (in, 0);
- dup2 (out, 1);
- dup2 (err, 2);
- close (in);
- close (out);
- close (err);
-#endif /* not WINDOWSNT */
-
-#if defined(USG) && !defined(BSD_PGRPS)
-#ifndef SETPGRP_RELEASES_CTTY
- setpgrp (); /* No arguments but equivalent in this case */
-#endif
-#else
- setpgrp (pid, pid);
-#endif /* USG */
- /* setpgrp_of_tty is incorrect here; it uses input_fd. */
- EMACS_SET_TTY_PGRP (0, &pid);
-
-#ifdef vipc
- something missing here;
-#endif /* vipc */
-
-#ifdef WINDOWSNT
- /* Spawn the child. (See ntproc.c:Spawnve). */
- cpid = spawnve (_P_NOWAIT, new_argv[0], new_argv, env);
- if (cpid == -1)
- /* An error occurred while trying to spawn the process. */
- report_file_error ("Spawning child process", Qnil);
- reset_standard_handles (in, out, err, handles);
- return cpid;
-#else /* not WINDOWSNT */
- /* 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, "Can't exec program: ", 20);
- write (1, new_argv[0], strlen (new_argv[0]));
- write (1, "\n", 1);
- _exit (1);
-#endif /* not WINDOWSNT */
-#endif /* not MSDOS */
-}
-
-/* Move the file descriptor FD so that its number is not less than MIN.
- If the file descriptor is moved at all, the original is freed. */
-int
-relocate_fd (fd, min)
- int fd, min;
-{
- if (fd >= min)
- return fd;
- else
- {
- int new = dup (fd);
- if (new == -1)
- {
- char *message1 = "Error while setting up child: ";
- char *errmessage = strerror (errno);
- char *message2 = "\n";
- write (2, message1, strlen (message1));
- write (2, errmessage, strlen (errmessage));
- write (2, message2, strlen (message2));
- _exit (1);
- }
- /* Note that we hold the original FD open while we recurse,
- to guarantee we'll get a new FD if we need it. */
- new = relocate_fd (new, min);
- close (fd);
- return new;
- }
-}
-
-static int
-getenv_internal (var, varlen, value, valuelen)
- char *var;
- int varlen;
- char **value;
- int *valuelen;
-{
- Lisp_Object scan;
-
- for (scan = Vprocess_environment; CONSP (scan); scan = XCONS (scan)->cdr)
- {
- Lisp_Object entry;
-
- entry = XCONS (scan)->car;
- if (STRINGP (entry)
- && XSTRING (entry)->size > varlen
- && XSTRING (entry)->data[varlen] == '='
-#ifdef WINDOWSNT
- /* NT environment variables are case insensitive. */
- && ! strnicmp (XSTRING (entry)->data, var, varlen)
-#else /* not WINDOWSNT */
- && ! bcmp (XSTRING (entry)->data, var, varlen)
-#endif /* not WINDOWSNT */
- )
- {
- *value = (char *) XSTRING (entry)->data + (varlen + 1);
- *valuelen = XSTRING (entry)->size - (varlen + 1);
- return 1;
- }
- }
-
- return 0;
-}
-
-DEFUN ("getenv", Fgetenv, Sgetenv, 1, 1, 0,
- "Return the value of environment variable VAR, as a string.\n\
-VAR should be a string. Value is nil if VAR is undefined in the environment.\n\
-This function consults the variable ``process-environment'' for its value.")
- (var)
- Lisp_Object var;
-{
- char *value;
- int valuelen;
-
- CHECK_STRING (var, 0);
- if (getenv_internal (XSTRING (var)->data, XSTRING (var)->size,
- &value, &valuelen))
- return make_string (value, valuelen);
- else
- return Qnil;
-}
-
-/* A version of getenv that consults process_environment, easily
- callable from C. */
-char *
-egetenv (var)
- char *var;
-{
- char *value;
- int valuelen;
-
- if (getenv_internal (var, strlen (var), &value, &valuelen))
- return value;
- else
- return 0;
-}
-
-#endif /* not VMS */
-
-/* This is run before init_cmdargs. */
-
-init_callproc_1 ()
-{
- char *data_dir = egetenv ("EMACSDATA");
- char *doc_dir = egetenv ("EMACSDOC");
-
- Vdata_directory
- = Ffile_name_as_directory (build_string (data_dir ? data_dir
- : PATH_DATA));
- Vdoc_directory
- = Ffile_name_as_directory (build_string (doc_dir ? doc_dir
- : PATH_DOC));
-
- /* Check the EMACSPATH environment variable, defaulting to the
- PATH_EXEC path from paths.h. */
- Vexec_path = decode_env_path ("EMACSPATH", PATH_EXEC);
- Vexec_directory = Ffile_name_as_directory (Fcar (Vexec_path));
- Vexec_path = nconc2 (decode_env_path ("PATH", ""), Vexec_path);
-}
-
-/* This is run after init_cmdargs, when Vinstallation_directory is valid. */
-
-init_callproc ()
-{
- char *data_dir = egetenv ("EMACSDATA");
-
- register char * sh;
- Lisp_Object tempdir;
-
- if (initialized && !NILP (Vinstallation_directory))
- {
- /* Add to the path the lib-src subdir of the installation dir. */
- Lisp_Object tem;
- tem = Fexpand_file_name (build_string ("lib-src"),
- Vinstallation_directory);
- if (NILP (Fmember (tem, Vexec_path)))
- {
-#ifndef DOS_NT
- /* MSDOS uses wrapped binaries, so don't do this. */
- Vexec_path = nconc2 (Vexec_path, Fcons (tem, Qnil));
- Vexec_directory = Ffile_name_as_directory (tem);
-#endif /* not DOS_NT */
- }
-
- /* Maybe use ../etc as well as ../lib-src. */
- if (data_dir == 0)
- {
- tem = Fexpand_file_name (build_string ("etc"),
- Vinstallation_directory);
- Vdoc_directory = Ffile_name_as_directory (tem);
- }
- }
-
- /* Look for the files that should be in etc. We don't use
- Vinstallation_directory, because these files are never installed
- near the executable, and they are never in the build
- directory when that's different from the source directory.
-
- Instead, if these files are not in the nominal place, we try the
- source directory. */
- if (data_dir == 0)
- {
- Lisp_Object tem, tem1, newdir;
-
- tem = Fexpand_file_name (build_string ("GNU"), Vdata_directory);
- tem1 = Ffile_exists_p (tem);
- if (NILP (tem1))
- {
- newdir = Fexpand_file_name (build_string ("../etc/"),
- build_string (PATH_DUMPLOADSEARCH));
- tem = Fexpand_file_name (build_string ("GNU"), newdir);
- tem1 = Ffile_exists_p (tem);
- if (!NILP (tem1))
- Vdata_directory = newdir;
- }
- }
-
- tempdir = Fdirectory_file_name (Vexec_directory);
- if (access (XSTRING (tempdir)->data, 0) < 0)
- dir_warning ("Warning: arch-dependent data dir (%s) does not exist.\n",
- Vexec_directory);
-
- tempdir = Fdirectory_file_name (Vdata_directory);
- if (access (XSTRING (tempdir)->data, 0) < 0)
- dir_warning ("Warning: arch-independent data dir (%s) does not exist.\n",
- Vdata_directory);
-
-#ifdef VMS
- Vshell_file_name = build_string ("*dcl*");
-#else
- sh = (char *) getenv ("SHELL");
- Vshell_file_name = build_string (sh ? sh : "/bin/sh");
-#endif
-
-#ifdef VMS
- Vtemp_file_name_pattern = build_string ("tmp:emacsXXXXXX.");
-#else
- if (getenv ("TMPDIR"))
- {
- char *dir = getenv ("TMPDIR");
- Vtemp_file_name_pattern
- = Fexpand_file_name (build_string ("emacsXXXXXX"),
- build_string (dir));
- }
- else
- Vtemp_file_name_pattern = build_string ("/tmp/emacsXXXXXX");
-#endif
-}
-
-set_process_environment ()
-{
- register char **envp;
-
- Vprocess_environment = Qnil;
-#ifndef CANNOT_DUMP
- if (initialized)
-#endif
- for (envp = environ; *envp; envp++)
- Vprocess_environment = Fcons (build_string (*envp),
- Vprocess_environment);
-}
-
-syms_of_callproc ()
-{
-#ifdef DOS_NT
- Qbuffer_file_type = intern ("buffer-file-type");
- staticpro (&Qbuffer_file_type);
-
- DEFVAR_LISP ("binary-process-input", &Vbinary_process_input,
- "*If non-nil then new subprocesses are assumed to take binary input.");
- Vbinary_process_input = Qnil;
-
- DEFVAR_LISP ("binary-process-output", &Vbinary_process_output,
- "*If non-nil then new subprocesses are assumed to produce binary output.");
- Vbinary_process_output = Qnil;
-#endif /* DOS_NT */
-
- 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 of architecture-dependent files that come with GNU Emacs,\n\
-especially executable programs intended for Emacs to invoke.");
-
- DEFVAR_LISP ("data-directory", &Vdata_directory,
- "Directory of architecture-independent files that come with GNU Emacs,\n\
-intended for Emacs to use.");
-
- DEFVAR_LISP ("doc-directory", &Vdoc_directory,
- "Directory containing the DOC file that comes with GNU Emacs.\n\
-This is usually the same as data-directory.");
-
- DEFVAR_LISP ("configure-info-directory", &Vconfigure_info_directory,
- "For internal use by the build procedure only.\n\
-This is the name of the directory in which the build procedure installed\n\
-Emacs's info files; the default value for Info-default-directory-list\n\
-includes this.");
- Vconfigure_info_directory = build_string (PATH_INFO);
-
- DEFVAR_LISP ("temp-file-name-pattern", &Vtemp_file_name_pattern,
- "Pattern for making names for temporary files.\n\
-This is used by `call-process-region'.");
- /* The real initialization is when we start again. */
- Vtemp_file_name_pattern = Qnil;
-
- DEFVAR_LISP ("process-environment", &Vprocess_environment,
- "List of environment variables for subprocesses to inherit.\n\
-Each element should be a string of the form ENVVARNAME=VALUE.\n\
-The environment which Emacs inherits is placed in this variable\n\
-when Emacs starts.");
-
-#ifndef VMS
- defsubr (&Scall_process);
- defsubr (&Sgetenv);
-#endif
- defsubr (&Scall_process_region);
-}
diff --git a/src/casefiddle.c b/src/casefiddle.c
deleted file mode 100644
index f4400814778..00000000000
--- a/src/casefiddle.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/* GNU Emacs case conversion functions.
- Copyright (C) 1985, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include "lisp.h"
-#include "buffer.h"
-#include "commands.h"
-#include "syntax.h"
-
-enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP};
-
-Lisp_Object
-casify_object (flag, obj)
- enum case_action flag;
- Lisp_Object obj;
-{
- register int i, c, len;
- register int inword = flag == CASE_DOWN;
-
- /* If the case table is flagged as modified, rescan it. */
- if (NILP (XCHAR_TABLE (current_buffer->downcase_table)->extras[1]))
- Fset_case_table (current_buffer->downcase_table);
-
- while (1)
- {
- if (INTEGERP (obj))
- {
- c = XINT (obj);
- if (c >= 0 && c <= 0400)
- {
- if (inword)
- XSETFASTINT (obj, DOWNCASE (c));
- else if (!UPPERCASEP (c))
- XSETFASTINT (obj, UPCASE1 (c));
- }
- return obj;
- }
- if (STRINGP (obj))
- {
- obj = Fcopy_sequence (obj);
- len = XSTRING (obj)->size;
- for (i = 0; i < len; i++)
- {
- c = XSTRING (obj)->data[i];
- if (inword && flag != CASE_CAPITALIZE_UP)
- c = DOWNCASE (c);
- else if (!UPPERCASEP (c)
- && (!inword || flag != CASE_CAPITALIZE_UP))
- c = UPCASE1 (c);
- XSTRING (obj)->data[i] = c;
- if ((int) flag >= (int) CASE_CAPITALIZE)
- inword = SYNTAX (c) == Sword;
- }
- return obj;
- }
- obj = wrong_type_argument (Qchar_or_string_p, 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--the value is a copy.\n\
-See also `capitalize', `downcase' and `upcase-initials'.")
- (obj)
- Lisp_Object obj;
-{
- return casify_object (CASE_UP, obj);
-}
-
-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--the value is a copy.")
- (obj)
- Lisp_Object obj;
-{
- return casify_object (CASE_DOWN, obj);
-}
-
-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--the value is a copy.")
- (obj)
- Lisp_Object obj;
-{
- return casify_object (CASE_CAPITALIZE, obj);
-}
-
-/* Like Fcapitalize but change only the initials. */
-
-DEFUN ("upcase-initials", Fupcase_initials, Supcase_initials, 1, 1, 0,
- "Convert the initial of each word in the argument to upper case.\n\
-Do not change the other letters of each word.\n\
-The argument may be a character or string. The result has the same type.\n\
-The argument object is not altered--the value is a copy.")
- (obj)
- Lisp_Object obj;
-{
- return casify_object (CASE_CAPITALIZE_UP, obj);
-}
-
-/* flag is CASE_UP, CASE_DOWN or CASE_CAPITALIZE or CASE_CAPITALIZE_UP.
- b and e specify range of buffer to operate on. */
-
-casify_region (flag, b, e)
- enum case_action flag;
- Lisp_Object b, e;
-{
- register int i;
- register int c;
- register int inword = flag == CASE_DOWN;
- int start, end;
-
- if (EQ (b, e))
- /* Not modifying because nothing marked */
- return;
-
- /* If the case table is flagged as modified, rescan it. */
- if (NILP (XCHAR_TABLE (current_buffer->downcase_table)->extras[1]))
- Fset_case_table (current_buffer->downcase_table);
-
- validate_region (&b, &e);
- start = XFASTINT (b);
- end = XFASTINT (e);
- modify_region (current_buffer, start, end);
- record_change (start, end - start);
-
- for (i = start; i < end; i++)
- {
- c = FETCH_CHAR (i);
- if (inword && flag != CASE_CAPITALIZE_UP)
- c = DOWNCASE (c);
- else if (!UPPERCASEP (c)
- && (!inword || flag != CASE_CAPITALIZE_UP))
- c = UPCASE1 (c);
- FETCH_CHAR (i) = c;
- if ((int) flag >= (int) CASE_CAPITALIZE)
- inword = SYNTAX (c) == Sword;
- }
-
- signal_after_change (start, end - start, end - start);
-}
-
-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'.")
- (beg, end)
- Lisp_Object beg, end;
-{
- casify_region (CASE_UP, beg, end);
- return Qnil;
-}
-
-DEFUN ("downcase-region", Fdowncase_region, Sdowncase_region, 2, 2, "r",
- "Convert the region to lower 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.")
- (beg, end)
- Lisp_Object beg, end;
-{
- casify_region (CASE_DOWN, beg, end);
- return Qnil;
-}
-
-DEFUN ("capitalize-region", Fcapitalize_region, Scapitalize_region, 2, 2, "r",
- "Convert the region to capitalized form.\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.")
- (beg, end)
- Lisp_Object beg, end;
-{
- casify_region (CASE_CAPITALIZE, beg, end);
- return Qnil;
-}
-
-/* Like Fcapitalize_region but change only the initials. */
-
-DEFUN ("upcase-initials-region", Fupcase_initials_region,
- Supcase_initials_region, 2, 2, "r",
- "Upcase the initial of each word in the region.\n\
-Subsequent letters of each word are not changed.\n\
-In programs, give two arguments, the starting and ending\n\
-character positions to operate on.")
- (beg, end)
- Lisp_Object beg, end;
-{
- casify_region (CASE_CAPITALIZE_UP, beg, end);
- return Qnil;
-}
-
-Lisp_Object
-operate_on_word (arg, newpoint)
- Lisp_Object arg;
- int *newpoint;
-{
- Lisp_Object val;
- int farend;
- int iarg;
-
- CHECK_NUMBER (arg, 0);
- iarg = XINT (arg);
- farend = scan_words (PT, iarg);
- if (!farend)
- farend = iarg > 0 ? ZV : BEGV;
-
- *newpoint = PT > farend ? PT : farend;
- XSETFASTINT (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'.")
- (arg)
- Lisp_Object arg;
-{
- Lisp_Object beg, end;
- int newpoint;
- XSETFASTINT (beg, PT);
- end = operate_on_word (arg, &newpoint);
- casify_region (CASE_UP, beg, end);
- SET_PT (newpoint);
- return Qnil;
-}
-
-DEFUN ("downcase-word", Fdowncase_word, Sdowncase_word, 1, 1, "p",
- "Convert following word (or ARG words) to lower case, moving over.\n\
-With negative argument, convert previous words but do not move.")
- (arg)
- Lisp_Object arg;
-{
- Lisp_Object beg, end;
- int newpoint;
- XSETFASTINT (beg, PT);
- end = operate_on_word (arg, &newpoint);
- casify_region (CASE_DOWN, beg, end);
- SET_PT (newpoint);
- return Qnil;
-}
-
-DEFUN ("capitalize-word", Fcapitalize_word, Scapitalize_word, 1, 1, "p",
- "Capitalize the following word (or ARG words), moving over.\n\
-This gives the word(s) a first character in upper case\n\
-and the rest lower case.\n\
-With negative argument, capitalize previous words but do not move.")
- (arg)
- Lisp_Object arg;
-{
- Lisp_Object beg, end;
- int newpoint;
- XSETFASTINT (beg, PT);
- end = operate_on_word (arg, &newpoint);
- casify_region (CASE_CAPITALIZE, beg, end);
- SET_PT (newpoint);
- return Qnil;
-}
-
-syms_of_casefiddle ()
-{
- defsubr (&Supcase);
- defsubr (&Sdowncase);
- defsubr (&Scapitalize);
- defsubr (&Supcase_initials);
- defsubr (&Supcase_region);
- defsubr (&Sdowncase_region);
- defsubr (&Scapitalize_region);
- defsubr (&Supcase_initials_region);
- defsubr (&Supcase_word);
- defsubr (&Sdowncase_word);
- defsubr (&Scapitalize_word);
-}
-
-keys_of_casefiddle ()
-{
- initial_define_key (control_x_map, Ctl('U'), "upcase-region");
- Fput (intern ("upcase-region"), Qdisabled, Qt);
- initial_define_key (control_x_map, Ctl('L'), "downcase-region");
- Fput (intern ("downcase-region"), Qdisabled, Qt);
-
- initial_define_key (meta_map, 'u', "upcase-word");
- initial_define_key (meta_map, 'l', "downcase-word");
- initial_define_key (meta_map, 'c', "capitalize-word");
-}
diff --git a/src/casetab.c b/src/casetab.c
deleted file mode 100644
index 3a008da5f40..00000000000
--- a/src/casetab.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/* GNU Emacs routines to deal with case tables.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Written by Howard Gayle. See chartab.c for details. */
-
-#include <config.h>
-#include "lisp.h"
-#include "buffer.h"
-
-Lisp_Object Qcase_table_p, Qcase_table;
-Lisp_Object Vascii_downcase_table, Vascii_upcase_table;
-Lisp_Object Vascii_canon_table, Vascii_eqv_table;
-
-static void compute_trt_inverse ();
-
-DEFUN ("case-table-p", Fcase_table_p, Scase_table_p, 1, 1, 0,
- "Return t iff OBJECT is a case table.\n\
-See `set-case-table' for more information on these data structures.")
- (object)
- Lisp_Object object;
-{
- Lisp_Object up, canon, eqv;
-
- if (! CHAR_TABLE_P (object))
- return Qnil;
- if (! EQ (XCHAR_TABLE (object)->purpose, Qcase_table))
- return Qnil;
-
- up = XCHAR_TABLE (object)->extras[0];
- canon = XCHAR_TABLE (object)->extras[1];
- eqv = XCHAR_TABLE (object)->extras[2];
-
- return ((NILP (up) || CHAR_TABLE_P (up))
- && ((NILP (canon) && NILP (eqv))
- || (CHAR_TABLE_P (canon)
- && (NILP (eqv) || CHAR_TABLE_P (eqv))))
- ? Qt : Qnil);
-}
-
-static Lisp_Object
-check_case_table (obj)
- Lisp_Object obj;
-{
- register Lisp_Object tem;
-
- while (tem = Fcase_table_p (obj), NILP (tem))
- obj = wrong_type_argument (Qcase_table_p, obj);
- return (obj);
-}
-
-DEFUN ("current-case-table", Fcurrent_case_table, Scurrent_case_table, 0, 0, 0,
- "Return the case table of the current buffer.")
- ()
-{
- return current_buffer->downcase_table;
-}
-
-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 Vascii_downcase_table;
-}
-
-static Lisp_Object set_case_table ();
-
-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 char-table which maps characters\n\
-to their lower-case equivalents. It also has three \"extra\" slots\n\
-which may be additional char-tables or nil.\n\
-These slots are called UPCASE, CANONICALIZE and EQUIVALENCES.\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; it may be nil, in which case it is\n\
- deduced from DOWNCASE and UPCASE.\n\
-EQUIVALENCES is a map that cyclicly permutes each equivalence class\n\
- (of characters with the same canonical equivalent); it may be nil,\n\
- in which case it is deduced from CANONICALIZE.")
- (table)
- Lisp_Object table;
-{
- return 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;
-{
- return set_case_table (table, 1);
-}
-
-static Lisp_Object
-set_case_table (table, standard)
- Lisp_Object table;
- int standard;
-{
- Lisp_Object up, canon, eqv;
-
- check_case_table (table);
-
- up = XCHAR_TABLE (table)->extras[0];
- canon = XCHAR_TABLE (table)->extras[1];
- eqv = XCHAR_TABLE (table)->extras[2];
-
- if (NILP (up))
- {
- up = Fmake_char_table (Qcase_table, Qnil);
- compute_trt_inverse (XCHAR_TABLE (table), XCHAR_TABLE (up));
- XCHAR_TABLE (table)->extras[0] = up;
- }
-
- if (NILP (canon))
- {
- register int i;
- Lisp_Object *upvec = XCHAR_TABLE (up)->contents;
- Lisp_Object *downvec = XCHAR_TABLE (table)->contents;
-
- canon = Fmake_char_table (Qcase_table, Qnil);
-
- /* 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++)
- XCHAR_TABLE (canon)->contents[i] = downvec[upvec[downvec[i]]];
- XCHAR_TABLE (table)->extras[1] = canon;
- }
-
- if (NILP (eqv))
- {
- eqv = Fmake_char_table (Qcase_table, Qnil);
- compute_trt_inverse (XCHAR_TABLE (canon), XCHAR_TABLE (eqv));
- XCHAR_TABLE (table)->extras[2] = eqv;
- }
-
- if (standard)
- Vascii_downcase_table = table;
- else
- {
- current_buffer->downcase_table = table;
- 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. */
-
-static void
-compute_trt_inverse (trt, inverse)
- struct Lisp_Char_Table *trt, *inverse;
-{
- register int i = 0400;
- register unsigned char c, q;
-
- while (i--)
- inverse->contents[i] = i;
- i = 0400;
- while (i--)
- {
- if ((q = trt->contents[i]) != (unsigned char) i)
- {
- c = inverse->contents[q];
- inverse->contents[q] = i;
- inverse->contents[i] = c;
- }
- }
-}
-
-init_casetab_once ()
-{
- register int i;
- Lisp_Object down, up;
- Qcase_table = intern ("case-table");
- staticpro (&Qcase_table);
-
- /* Intern this now in case it isn't already done.
- Setting this variable twice is harmless.
- But don't staticpro it here--that is done in alloc.c. */
- Qchar_table_extra_slots = intern ("char-table-extra-slots");
-
- /* Now we are ready to set up this property, so we can
- create char tables. */
- Fput (Qcase_table, Qchar_table_extra_slots, make_number (3));
-
- down = Fmake_char_table (Qcase_table, Qnil);
- Vascii_downcase_table = down;
-
- for (i = 0; i < 256; i++)
- XCHAR_TABLE (down)->contents[i] = (i >= 'A' && i <= 'Z') ? i + 040 : i;
-
- XCHAR_TABLE (down)->extras[1] = Fcopy_sequence (down);
-
- up = Fmake_char_table (Qcase_table, Qnil);
- XCHAR_TABLE (down)->extras[0] = up;
-
- for (i = 0; i < 256; i++)
- XCHAR_TABLE (up)->contents[i]
- = ((i >= 'A' && i <= 'Z')
- ? i + ('a' - 'A')
- : ((i >= 'a' && i <= 'z')
- ? i + ('A' - 'a')
- : i));
-
- XCHAR_TABLE (down)->extras[2] = Fcopy_sequence (up);
-}
-
-syms_of_casetab ()
-{
- Qcase_table_p = intern ("case-table-p");
- staticpro (&Qcase_table_p);
-
- staticpro (&Vascii_canon_table);
- staticpro (&Vascii_downcase_table);
- staticpro (&Vascii_eqv_table);
- staticpro (&Vascii_upcase_table);
-
- defsubr (&Scase_table_p);
- defsubr (&Scurrent_case_table);
- defsubr (&Sstandard_case_table);
- defsubr (&Sset_case_table);
- defsubr (&Sset_standard_case_table);
-}
diff --git a/src/chpdef.h b/src/chpdef.h
deleted file mode 100644
index 43f7bbf4345..00000000000
--- a/src/chpdef.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#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
deleted file mode 100644
index 7362822c95d..00000000000
--- a/src/cm.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/* Cursor motion subroutines for GNU Emacs.
- Copyright (C) 1985, 1995 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#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++;
- return c;
-}
-
-cmputc (c)
- char c;
-{
- if (termscript)
- fputc (c & 0177, termscript);
- putchar (c & 0177);
- return c;
-}
-
-/* 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
-
-/*
- * Terminals with magicwrap (xn) don't all behave identically.
- * The VT100 leaves the cursor in the last column but will wrap before
- * printing the next character. I hear that the Concept terminal does
- * the wrap immediately but ignores the next newline it sees. And some
- * terminals just have buggy firmware, and think that the cursor is still
- * in limbo if we use direct cursor addressing from the phantom column.
- * The only guaranteed safe thing to do is to emit a CRLF immediately
- * after we reach the last column; this takes us to a known state.
- */
-void
-cmcheckmagic ()
-{
- if (curX == FrameCols)
- {
- if (!MagicWrap || curY >= FrameRows - 1)
- abort ();
- if (termscript)
- putc ('\r', termscript);
- putchar ('\r');
- if (termscript)
- putc ('\n', termscript);
- putchar ('\n');
- curX = 0;
- curY++;
- }
-}
-
-
-/*
- * (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;
-}
-
-#if 0
-losecursor ()
-{
- curY = -1;
-}
-#endif
-
-#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)
- {
- /* We may have quick ways to go to the upper-left, bottom-left,
- * start-of-line, or start-of-next-line. Or it might be best to
- * start where we are. Examine the options, and pick the cheapest.
- */
-
- 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.
- * Return -1 if cannot.
- * Return -2 if size not specified.
- */
-
-Wcm_init ()
-{
-#if 0
- if (Wcm.cm_abs && !Wcm.cm_ds)
- return 0;
-#endif
- if (Wcm.cm_abs)
- 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;
- /* Check that we know the size of the screen.... */
- if (Wcm.cm_rows <= 0 || Wcm.cm_cols <= 0)
- return - 2;
- return 0;
-}
diff --git a/src/cm.h b/src/cm.h
deleted file mode 100644
index 336a3308fd8..00000000000
--- a/src/cm.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/* Cursor motion calculation definitions for GNU Emacs
- Copyright (C) 1985, 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Holds the minimum and maximum costs for the parametrized capabilities. */
-struct parmcap
- {
- int mincost, maxcost;
- };
-
-/* 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. */
-
-struct cm
- {
- /* Cursor position. -1 in *both* variables means the cursor
- position is unknown, in order to force absolute cursor motion. */
-
- int cm_curY; /* Current row */
- int cm_curX; /* Current column */
-
- /* Capabilities from termcap */
- char *cm_up; /* up (up) */
- char *cm_down; /* down (do) */
- char *cm_left; /* left (le) */
- char *cm_right; /* right (nd) */
- char *cm_home; /* home (ho) */
- char *cm_cr; /* carriage return (cr) */
- char *cm_ll; /* last line (ll) */
- char *cm_tab; /* tab (ta) */
- char *cm_backtab; /* backtab (bt) */
- char *cm_abs; /* absolute (cm) */
- char *cm_habs; /* horizontal absolute (ch) */
- char *cm_vabs; /* vertical absolute (cv) */
-#if 0
- char *cm_ds; /* "don't send" string (ds) */
-#endif
- char *cm_multiup; /* multiple up (UP) */
- char *cm_multidown; /* multiple down (DO) */
- char *cm_multileft; /* multiple left (LE) */
- char *cm_multiright; /* multiple right (RI) */
- int cm_cols; /* number of cols on screen (co) */
- int cm_rows; /* number of rows on screen (li) */
- int cm_tabwidth; /* tab width (it) */
- unsigned int cm_autowrap:1; /* autowrap flag (am) */
- unsigned int cm_magicwrap:1; /* VT-100: cursor stays in last col but
- will cm_wrap if next char is
- printing (xn) */
- unsigned int cm_usetabs:1; /* if set, use tabs */
- unsigned int cm_losewrap:1; /* if reach right margin, forget cursor
- location */
- unsigned int cm_autolf:1; /* \r performs a \r\n (rn) */
-
- /* Parametrized capabilities. This needs to be a struct since
- the costs are accessed through pointers. */
-
-#if 0
- struct parmcap cc_abs; /* absolute (cm) */
- struct parmcap cc_habs; /* horizontal absolute (ch) */
- struct parmcap cc_vabs; /* vertical absolute (cv) */
- struct parmcap cc_multiup; /* multiple up (UP) */
- struct parmcap cc_multidown; /* multiple down (DO) */
- struct parmcap cc_multileft; /* multiple left (LE) */
- struct parmcap cc_multiright; /* multiple right (RI) */
-#endif
-
- /* Costs for the non-parametrized capabilities */
- int cc_up; /* cost for up */
- int cc_down; /* etc. */
- int cc_left;
- int cc_right;
- int cc_home;
- int cc_cr;
- int cc_ll;
- int cc_tab;
- int cc_backtab;
- /* These are temporary, until the code is installed to use the
- struct parmcap fields above. */
- int cc_abs;
- int cc_habs;
- int cc_vabs;
- };
-
-extern struct cm Wcm; /* Terminal capabilities */
-extern char PC; /* Pad character */
-#ifdef HAVE_TERMIOS_H
-#include <termios.h>
-/* HJL's version of libc is said to need this on the Alpha. */
-speed_t ospeed;
-#else
-extern short ospeed; /* Output speed (from sg_ospeed) */
-#endif
-
-/* 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 Tab Wcm.cm_tab
-#define BackTab Wcm.cm_backtab
-#define TabWidth Wcm.cm_tabwidth
-#define CR Wcm.cm_cr
-#define Home Wcm.cm_home
-#define LastLine Wcm.cm_ll
-#define AbsPosition Wcm.cm_abs
-#define ColPosition Wcm.cm_habs
-#define RowPosition Wcm.cm_vabs
-#define MultiUp Wcm.cm_multiup
-#define MultiDown Wcm.cm_multidown
-#define MultiLeft Wcm.cm_multileft
-#define MultiRight Wcm.cm_multiright
-#define AutoWrap Wcm.cm_autowrap
-#define MagicWrap Wcm.cm_magicwrap
-#define UseTabs Wcm.cm_usetabs
-#define FrameRows Wcm.cm_rows
-#define FrameCols Wcm.cm_cols
-
-#define UpCost Wcm.cc_up
-#define DownCost Wcm.cc_down
-#define LeftCost Wcm.cc_left
-#define RightCost Wcm.cc_right
-#define HomeCost Wcm.cc_home
-#define CRCost Wcm.cc_cr
-#define LastLineCost Wcm.cc_ll
-#define TabCost Wcm.cc_tab
-#define BackTabCost Wcm.cc_backtab
-#define AbsPositionCost Wcm.cc_abs
-#define ColPositionCost Wcm.cc_habs
-#define RowPositionCost Wcm.cc_vabs
-#define MultiUpCost Wcm.cc_multiup
-#define MultiDownCost Wcm.cc_multidown
-#define MultiLeftCost Wcm.cc_multileft
-#define MultiRightCost Wcm.cc_multiright
-#endif
-
-#define cmat(row,col) (curY = (row), curX = (col))
-#define cmplus(n) \
- { \
- if ((curX += (n)) >= FrameCols && !MagicWrap) \
- { \
- if (Wcm.cm_losewrap) losecursor (); \
- else if (AutoWrap) curX = 0, curY++; \
- else curX--; \
- } \
- }
-
-#define losecursor() (curX = -1, curY = -1)
-
-extern int cost;
-extern int evalcost ();
-
-extern void cmcheckmagic ();
-extern int cmputc ();
-extern int cmcostinit ();
-extern int cmgoto ();
-extern int Wcm_clear ();
-extern int Wcm_init ();
diff --git a/src/cmds.c b/src/cmds.c
deleted file mode 100644
index db05b38460e..00000000000
--- a/src/cmds.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/* Simple built-in editing commands.
- Copyright (C) 1985, 93, 94, 95, 1996 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include "lisp.h"
-#include "commands.h"
-#include "buffer.h"
-#include "syntax.h"
-#include "window.h"
-#include "keyboard.h"
-
-Lisp_Object Qkill_forward_chars, Qkill_backward_chars, Vblink_paren_function;
-
-/* A possible value for a buffer's overwrite-mode variable. */
-Lisp_Object Qoverwrite_mode_binary;
-
-/* Non-nil means put this face on the next self-inserting character. */
-Lisp_Object Vself_insert_face;
-
-/* This is the command that set up Vself_insert_face. */
-Lisp_Object Vself_insert_face_command;
-
-extern Lisp_Object Qface;
-
-DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "p",
- "Move point right N characters (left if N is negative).\n\
-On reaching end of buffer, stop and signal error.")
- (n)
- Lisp_Object n;
-{
- if (NILP (n))
- XSETFASTINT (n, 1);
- else
- CHECK_NUMBER (n, 0);
-
- /* This used to just set point to point + XINT (n), and then check
- to see if it was within boundaries. But now that SET_PT can
- potentially do a lot of stuff (calling entering and exiting
- hooks, etcetera), that's not a good approach. So we validate the
- proposed position, then set point. */
- {
- int new_point = PT + XINT (n);
-
- if (new_point < BEGV)
- {
- SET_PT (BEGV);
- Fsignal (Qbeginning_of_buffer, Qnil);
- }
- if (new_point > ZV)
- {
- SET_PT (ZV);
- Fsignal (Qend_of_buffer, Qnil);
- }
-
- SET_PT (new_point);
- }
-
- return Qnil;
-}
-
-DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "p",
- "Move point left N characters (right if N is negative).\n\
-On attempt to pass beginning or end of buffer, stop and signal error.")
- (n)
- Lisp_Object n;
-{
- if (NILP (n))
- XSETFASTINT (n, 1);
- else
- CHECK_NUMBER (n, 0);
-
- XSETINT (n, - XINT (n));
- return Fforward_char (n);
-}
-
-DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 1, "p",
- "Move N lines forward (backward if N is negative).\n\
-Precisely, if point is on line I, move to the start of line I + N.\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 N - number of lines moved; if backward, N + number moved.\n\
-With positive N, a non-empty line at the end counts as one line\n\
- successfully moved (for the return value).")
- (n)
- Lisp_Object n;
-{
- int pos2 = PT;
- int pos;
- int count, shortage, negp;
-
- if (NILP (n))
- count = 1;
- else
- {
- CHECK_NUMBER (n, 0);
- count = XINT (n);
- }
-
- negp = count <= 0;
- pos = scan_buffer ('\n', pos2, 0, count - negp, &shortage, 1);
- if (shortage > 0
- && (negp
- || (ZV > BEGV
- && pos != pos2
- && FETCH_CHAR (pos - 1) != '\n')))
- shortage--;
- SET_PT (pos);
- return make_number (negp ? - shortage : shortage);
-}
-
-DEFUN ("beginning-of-line", Fbeginning_of_line, Sbeginning_of_line,
- 0, 1, "p",
- "Move point to beginning of current line.\n\
-With argument N not nil or 1, move forward N - 1 lines first.\n\
-If scan reaches end of buffer, stop there without error.")
- (n)
- Lisp_Object n;
-{
- if (NILP (n))
- XSETFASTINT (n, 1);
- else
- CHECK_NUMBER (n, 0);
-
- SET_PT (XINT (Fline_beginning_position (n)));
- return Qnil;
-}
-
-DEFUN ("end-of-line", Fend_of_line, Send_of_line,
- 0, 1, "p",
- "Move point to end of current line.\n\
-With argument N not nil or 1, move forward N - 1 lines first.\n\
-If scan reaches end of buffer, stop there without error.")
- (n)
- Lisp_Object n;
-{
- register int pos;
- register int stop;
-
- if (NILP (n))
- XSETFASTINT (n, 1);
- else
- CHECK_NUMBER (n, 0);
-
- SET_PT (XINT (Fline_end_position (n)));
-
- return Qnil;
-}
-
-DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "p\nP",
- "Delete the following N characters (previous if N is negative).\n\
-Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
-Interactively, N is the prefix arg, and KILLFLAG is set if\n\
-N was explicitly specified.")
- (n, killflag)
- Lisp_Object n, killflag;
-{
- CHECK_NUMBER (n, 0);
-
- if (NILP (killflag))
- {
- if (XINT (n) < 0)
- {
- if (PT + XINT (n) < BEGV)
- Fsignal (Qbeginning_of_buffer, Qnil);
- else
- del_range (PT + XINT (n), PT);
- }
- else
- {
- if (PT + XINT (n) > ZV)
- Fsignal (Qend_of_buffer, Qnil);
- else
- del_range (PT, PT + XINT (n));
- }
- }
- else
- {
- call1 (Qkill_forward_chars, n);
- }
- return Qnil;
-}
-
-DEFUN ("delete-backward-char", Fdelete_backward_char, Sdelete_backward_char,
- 1, 2, "p\nP",
- "Delete the previous N characters (following if N is negative).\n\
-Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
-Interactively, N is the prefix arg, and KILLFLAG is set if\n\
-N was explicitly specified.")
- (n, killflag)
- Lisp_Object n, killflag;
-{
- Lisp_Object value;
- int deleted_special = 0;
- int i;
-
- CHECK_NUMBER (n, 0);
-
- /* See if we are about to delete a tab or newline backwards. */
- for (i = 1; i <= XINT (n); i++)
- {
- if (PT - i < BEGV)
- break;
- if (FETCH_CHAR (PT - i) == '\t' || FETCH_CHAR (PT - i) == '\n')
- {
- deleted_special = 1;
- break;
- }
- }
-
- value = Fdelete_char (make_number (-XINT (n)), killflag);
-
- /* In overwrite mode, back over columns while clearing them out,
- unless at end of line. */
- if (XINT (n) > 0
- && ! NILP (current_buffer->overwrite_mode)
- && ! deleted_special
- && ! (PT == ZV || FETCH_CHAR (PT) == '\n'))
- {
- Finsert_char (make_number (' '), XINT (n));
- SET_PT (PT - XINT (n));
- }
-
- return value;
-}
-
-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.")
- (n)
- Lisp_Object n;
-{
- CHECK_NUMBER (n, 0);
-
- /* Barf if the key that invoked this was not a character. */
- if (!INTEGERP (last_command_char))
- bitch_at_user ();
- else if (XINT (n) >= 2 && NILP (current_buffer->overwrite_mode))
- {
- XSETFASTINT (n, XFASTINT (n) - 2);
- /* The first one might want to expand an abbrev. */
- internal_self_insert (XINT (last_command_char), 1);
- /* The bulk of the copies of this char can be inserted simply.
- We don't have to handle a user-specified face specially
- because it will get inherited from the first char inserted. */
- Finsert_char (last_command_char, n, Qt);
- /* The last one might want to auto-fill. */
- internal_self_insert (XINT (last_command_char), 0);
- }
- else
- while (XINT (n) > 0)
- {
- /* Ok since old and new vals both nonneg */
- XSETFASTINT (n, XFASTINT (n) - 1);
- internal_self_insert (XINT (last_command_char), XFASTINT (n) != 0);
- }
-
- return Qnil;
-}
-
-/* Insert character C1. If NOAUTOFILL is nonzero, don't do autofill
- even if it is enabled.
-
- If this insertion is suitable for direct output (completely simple),
- return 0. A value of 1 indicates this *might* not have been simple.
- A value of 2 means this did things that call for an undo boundary. */
-
-internal_self_insert (c1, noautofill)
- /* This has to be unsigned char; when it is char,
- some compilers sign-extend it in SYNTAX_ENTRY, despite
- the casts to unsigned char there. */
- unsigned char c1;
- int noautofill;
-{
- extern Lisp_Object Fexpand_abbrev ();
- int hairy = 0;
- Lisp_Object tem;
- register enum syntaxcode synt;
- register int c = c1;
- Lisp_Object overwrite;
-
- overwrite = current_buffer->overwrite_mode;
- if (!NILP (Vbefore_change_function) || !NILP (Vafter_change_function)
- || !NILP (Vbefore_change_functions) || !NILP (Vafter_change_functions))
- hairy = 1;
-
- if (!NILP (overwrite)
- && PT < ZV
- && (EQ (overwrite, Qoverwrite_mode_binary)
- || (c != '\n' && FETCH_CHAR (PT) != '\n'))
- && (EQ (overwrite, Qoverwrite_mode_binary)
- || FETCH_CHAR (PT) != '\t'
- || XINT (current_buffer->tab_width) <= 0
- || XFASTINT (current_buffer->tab_width) > 20
- || !((current_column () + 1) % XFASTINT (current_buffer->tab_width))))
- {
- del_range (PT, PT + 1);
- hairy = 2;
- }
- if (!NILP (current_buffer->abbrev_mode)
- && SYNTAX (c) != Sword
- && NILP (current_buffer->read_only)
- && PT > BEGV && SYNTAX (FETCH_CHAR (PT - 1)) == Sword)
- {
- int modiff = MODIFF;
- Lisp_Object sym;
-
- sym = Fexpand_abbrev ();
-
- /* If we expanded an abbrev which has only a hook,
- and the hook has a non-nil `no-self-insert' property,
- return right away--don't really self-insert. */
- if (! NILP (sym) && ! NILP (XSYMBOL (sym)->function)
- && SYMBOLP (XSYMBOL (sym)->function))
- {
- Lisp_Object prop;
- prop = Fget (XSYMBOL (sym)->function, intern ("no-self-insert"));
- if (! NILP (prop))
- return Qnil;
- }
-
- if (MODIFF != modiff)
- hairy = 2;
- }
- if ((c == ' ' || c == '\n')
- && !noautofill
- && !NILP (current_buffer->auto_fill_function))
- {
- Lisp_Object tem;
-
- insert_and_inherit (&c1, 1);
- if (c1 == '\n')
- /* After inserting a newline, move to previous line and fill */
- /* that. Must have the newline in place already so filling and */
- /* justification, if any, know where the end is going to be. */
- SET_PT (PT - 1);
- tem = call0 (current_buffer->auto_fill_function);
- if (c1 == '\n')
- SET_PT (PT + 1);
- if (!NILP (tem))
- hairy = 2;
- }
- else
- insert_and_inherit (&c1, 1);
-
-#ifdef HAVE_FACES
- /* If previous command specified a face to use, use it. */
- if (!NILP (Vself_insert_face)
- && EQ (current_kboard->Vlast_command, Vself_insert_face_command))
- {
- Lisp_Object before, after;
- XSETINT (before, PT - 1);
- XSETINT (after, PT);
- Fput_text_property (before, after, Qface, Vself_insert_face, Qnil);
- Vself_insert_face = Qnil;
- }
-#endif
- synt = SYNTAX (c);
- if ((synt == Sclose || synt == Smath)
- && !NILP (Vblink_paren_function) && INTERACTIVE
- && !noautofill)
- {
- call0 (Vblink_paren_function);
- hairy = 2;
- }
- return hairy;
-}
-
-/* module initialization */
-
-syms_of_cmds ()
-{
- Qkill_backward_chars = intern ("kill-backward-chars");
- staticpro (&Qkill_backward_chars);
-
- Qkill_forward_chars = intern ("kill-forward-chars");
- staticpro (&Qkill_forward_chars);
-
- Qoverwrite_mode_binary = intern ("overwrite-mode-binary");
- staticpro (&Qoverwrite_mode_binary);
-
- DEFVAR_LISP ("self-insert-face", &Vself_insert_face,
- "If non-nil, set the face of the next self-inserting character to this.\n\
-See also `self-insert-face-command'.");
- Vself_insert_face = Qnil;
-
- DEFVAR_LISP ("self-insert-face-command", &Vself_insert_face_command,
- "This is the command that set up `self-insert-face'.\n\
-If `last-command' does not equal this value, we ignore `self-insert-face'.");
- Vself_insert_face_command = Qnil;
-
- 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;
-
- defsubr (&Sforward_char);
- defsubr (&Sbackward_char);
- defsubr (&Sforward_line);
- defsubr (&Sbeginning_of_line);
- defsubr (&Send_of_line);
-
- defsubr (&Sdelete_char);
- defsubr (&Sdelete_backward_char);
-
- defsubr (&Sself_insert_command);
-}
-
-keys_of_cmds ()
-{
- int n;
-
- initial_define_key (global_map, Ctl ('I'), "self-insert-command");
- for (n = 040; n < 0177; n++)
- initial_define_key (global_map, n, "self-insert-command");
-#ifdef MSDOS
- for (n = 0200; n < 0240; n++)
- initial_define_key (global_map, n, "self-insert-command");
-#endif
- for (n = 0240; n < 0400; 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");
-}
diff --git a/src/commands.h b/src/commands.h
deleted file mode 100644
index 99c5ca75376..00000000000
--- a/src/commands.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Definitions needed by most editing commands.
- Copyright (C) 1985, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#define Ctl(c) ((c)&037)
-
-/* Define the names of keymaps, just so people can refer to them in
- calls to initial_define_key. These should *not* be used after
- initialization; use-global-map doesn't affect these; it sets
- current_global_map instead. */
-extern Lisp_Object global_map;
-extern Lisp_Object meta_map;
-extern Lisp_Object control_x_map;
-
-extern Lisp_Object Vminibuffer_local_map;
-
-extern Lisp_Object Vminibuffer_local_ns_map;
-
-/* keymap used for minibuffers when doing completion */
-extern Lisp_Object Vminibuffer_local_completion_map;
-
-/* keymap used for minibuffers when doing completion and require a match */
-extern Lisp_Object Vminibuffer_local_must_match_map;
-
-/* Last character of last key sequence. */
-extern Lisp_Object last_command_char;
-
-/* Last input character read as a command, not counting menus
- reached by the mouse. */
-extern Lisp_Object last_nonmenu_event;
-
-/* List of command events to be re-read, or Qnil. */
-extern Lisp_Object Vunread_command_events;
-
-/* Command char event to be re-read, or -1 if none.
- Setting this is obsolete, but some things should still check it. */
-extern int unread_command_char;
-
-/* The command being executed by the command loop.
- Commands may set this, and the value set will be copied into
- current_kboard->Vlast_command instead of the actual command. */
-extern Lisp_Object this_command;
-
-/* If not Qnil, this is a switch-frame event which we decided to put
- off until the end of a key sequence. This should be read as the
- next command input, after any Vunread_command_events.
-
- read_key_sequence uses this to delay switch-frame events until the
- end of the key sequence; Fread_char uses it to put off switch-frame
- events until a non-ASCII event is acceptable as input. */
-extern Lisp_Object unread_switch_frame;
-
-/* The value of point when the last command was executed. */
-extern int last_point_position;
-
-/* The buffer that was current when the last command was started. */
-extern Lisp_Object last_point_position_buffer;
-
-/* Nonzero means ^G can quit instantly */
-extern int immediate_quit;
-
-extern Lisp_Object Vexecuting_macro;
-
-/* Nonzero if input is coming from the keyboard */
-
-#define INTERACTIVE (NILP (Vexecuting_macro) && !noninteractive)
-
-/* Set this nonzero to force reconsideration of mode line. */
-
-extern int update_mode_lines;
-
-/* Nonzero means reading single-character input with prompt
- so put cursor on minibuffer after the prompt. */
-
-extern int cursor_in_echo_area;
diff --git a/src/config.in b/src/config.in
deleted file mode 100644
index 3925f242fd8..00000000000
--- a/src/config.in
+++ /dev/null
@@ -1,375 +0,0 @@
-/* GNU Emacs site configuration template file. -*- C -*-
- Copyright (C) 1988, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* No code in Emacs #includes config.h twice, but some of the code
- intended to work with other packages as well (like gmalloc.c)
- think they can include it as many times as they like. */
-#ifndef EMACS_CONFIG_H
-#define EMACS_CONFIG_H
-
-
-/* These are all defined in the top-level Makefile by configure.
- They're here only for reference. */
-
-/* Define LISP_FLOAT_TYPE if you want emacs to support floating-point
- numbers. */
-#undef LISP_FLOAT_TYPE
-
-/* Define GNU_MALLOC if you want to use the *new* GNU memory allocator. */
-#undef GNU_MALLOC
-
-/* Define REL_ALLOC if you want to use the relocating allocator for
- buffer space. */
-#undef REL_ALLOC
-
-/* Define HAVE_X_WINDOWS if you want to use the X window system. */
-#undef HAVE_X_WINDOWS
-
-/* Define HAVE_X11 if you want to use version 11 of X windows.
- Otherwise, Emacs expects to use version 10. */
-#undef HAVE_X11
-
-/* Define if using an X toolkit. */
-#undef USE_X_TOOLKIT
-
-/* Define this if you're using XFree386. */
-#undef HAVE_XFREE386
-
-/* Define HAVE_MENUS if you have mouse menus.
- (This is automatic if you use X, but the option to specify it remains.)
- It is also defined with other window systems that support xmenu.c. */
-#undef HAVE_MENUS
-
-/* Define if we have the X11R6 or newer version of Xt. */
-#undef HAVE_X11XTR6
-
-/* Define if we have the X11R6 or newer version of Xlib. */
-#undef HAVE_X11R6
-
-/* Define if we have the X11R5 or newer version of Xlib. */
-#undef HAVE_X11R5
-
-/* Define if netdb.h declares h_errno. */
-#undef HAVE_H_ERRNO
-
-/* If we're using any sort of window system, define some consequences. */
-#ifdef HAVE_X_WINDOWS
-#define HAVE_WINDOW_SYSTEM
-#define MULTI_KBOARD
-#define HAVE_FACES
-#define HAVE_MOUSE
-#endif
-
-/* Define USE_TEXT_PROPERTIES to support visual and other properties
- on text. */
-#define USE_TEXT_PROPERTIES
-
-/* Define USER_FULL_NAME to return a string
- that is the user's full name.
- It can assume that the variable `pw'
- points to the password file entry for this user.
-
- At some sites, the pw_gecos field contains
- the user's full name. If neither this nor any other
- field contains the right thing, use pw_name,
- giving the user's login name, since that is better than nothing. */
-#define USER_FULL_NAME pw->pw_gecos
-
-/* Define AMPERSAND_FULL_NAME if you use the convention
- that & in the full name stands for the login id. */
-/* Turned on June 1996 supposing nobody will mind it. */
-#define AMPERSAND_FULL_NAME
-
-/* Things set by --with options in the configure script. */
-
-/* Define to support POP mail retrieval. */
-#undef MAIL_USE_POP
-
-/* Define to support Kerberos-authenticated POP mail retrieval. */
-#undef KERBEROS
-
-/* Define to support using a Hesiod database to find the POP server. */
-#undef HESIOD
-
-/* Some things figured out by the configure script, grouped as they are in
- configure.in. */
-#ifndef _ALL_SOURCE /* suppress warning if this is pre-defined */
-#undef _ALL_SOURCE
-#endif
-#undef HAVE_SYS_SELECT_H
-#undef HAVE_SYS_TIMEB_H
-#undef HAVE_SYS_TIME_H
-#undef HAVE_UNISTD_H
-#undef HAVE_UTIME_H
-#undef HAVE_LINUX_VERSION_H
-#undef HAVE_SYS_SYSTEMINFO_H
-#undef HAVE_TERMIOS_H
-#undef HAVE_LIMITS_H
-#undef STDC_HEADERS
-#undef TIME_WITH_SYS_TIME
-
-#undef HAVE_LIBDNET
-#undef HAVE_LIBPTHREADS
-#undef HAVE_LIBRESOLV
-#undef HAVE_LIBXMU
-#undef HAVE_LIBNCURSES
-#undef HAVE_LIBKRB
-#undef HAVE_LIBDES
-
-/* Mail-file locking */
-#undef HAVE_LIBMAIL
-#undef HAVE_MAILLOCK_H
-#undef HAVE_TOUCHLOCK
-
-#undef HAVE_ALLOCA_H
-
-#undef HAVE_GETTIMEOFDAY
-/* If we don't have gettimeofday,
- the test for GETTIMEOFDAY_ONE_ARGUMENT may succeed,
- but we should ignore it. */
-#ifdef HAVE_GETTIMEOFDAY
-#undef GETTIMEOFDAY_ONE_ARGUMENT
-#endif
-#undef HAVE_GETHOSTNAME
-#undef HAVE_GETDOMAINNAME
-#undef HAVE_DUP2
-#undef HAVE_RENAME
-#undef HAVE_CLOSEDIR
-
-#undef TM_IN_SYS_TIME
-#undef HAVE_TM_ZONE
-#undef HAVE_TZNAME
-
-#undef const
-
-#undef HAVE_LONG_FILE_NAMES
-
-#undef CRAY_STACKSEG_END
-
-#undef UNEXEC_SRC
-
-#undef HAVE_LIBXBSD
-#undef HAVE_XRMSETDATABASE
-#undef HAVE_XSCREENRESOURCESTRING
-#undef HAVE_XSCREENNUMBEROFSCREEN
-#undef HAVE_XSETWMPROTOCOLS
-
-#undef HAVE_MKDIR
-#undef HAVE_RMDIR
-#undef HAVE_SYSINFO
-#undef HAVE_RANDOM
-#undef HAVE_LRAND48
-#undef HAVE_BCOPY
-#undef HAVE_BCMP
-#undef HAVE_LOGB
-#undef HAVE_FREXP
-#undef HAVE_FMOD
-#undef HAVE_FTIME
-#undef HAVE_RES_INIT /* For -lresolv on Suns. */
-#undef HAVE_SETSID
-#undef HAVE_FPATHCONF
-#undef HAVE_SELECT
-#undef HAVE_MKTIME
-#undef HAVE_EUIDACCESS
-#undef HAVE_GETPAGESIZE
-#undef HAVE_TZSET
-#undef HAVE_SETLOCALE
-#undef HAVE_UTIMES
-#undef HAVE_SETRLIMIT
-#undef HAVE_SETPGID
-#undef HAVE_GETCWD
-
-#undef LOCALTIME_CACHE
-#undef HAVE_INET_SOCKETS
-
-#undef HAVE_AIX_SMT_EXP
-
-/* Define if you have the ANSI `strerror' function.
- Otherwise you must have the variable `char *sys_errlist[]'. */
-#undef HAVE_STRERROR
-
-/* Define if `sys_siglist' is declared by <signal.h>. */
-#undef SYS_SIGLIST_DECLARED
-
-/* Define if `struct utimbuf' is declared by <utime.h>. */
-#undef HAVE_STRUCT_UTIMBUF
-
-/* Define if `struct timeval' is declared by <sys/time.h>. */
-#undef HAVE_TIMEVAL
-
-/* If using GNU, then support inline function declarations. */
-#ifdef __GNUC__
-#define INLINE __inline__
-#else
-#define INLINE
-#endif
-
-#undef EMACS_CONFIGURATION
-
-#undef EMACS_CONFIG_OPTIONS
-
-/* The configuration script defines opsysfile to be the name of the
- s/SYSTEM.h file that describes the system type you are using. The file
- is chosen based on the configuration name you give.
-
- See the file ../etc/MACHINES for a list of systems and the
- configuration names to use for them.
-
- See s/template.h for documentation on writing s/SYSTEM.h files. */
-#undef config_opsysfile
-#include config_opsysfile
-
-/* The configuration script defines machfile to be the name of the
- m/MACHINE.h file that describes the machine you are using. The file is
- chosen based on the configuration name you give.
-
- See the file ../etc/MACHINES for a list of machines and the
- configuration names to use for them.
-
- See m/template.h for documentation on writing m/MACHINE.h files. */
-#undef config_machfile
-#include config_machfile
-
-/* Load in the conversion definitions if this system
- needs them and the source file being compiled has not
- said to inhibit this. There should be no need for you
- to alter these lines. */
-
-#ifdef SHORTNAMES
-#ifndef NO_SHORTNAMES
-#include "../shortnames/remap.h"
-#endif /* not NO_SHORTNAMES */
-#endif /* SHORTNAMES */
-
-/* If no remapping takes place, static variables cannot be dumped as
- pure, so don't worry about the `static' keyword. */
-#ifdef NO_REMAP
-#undef static
-#endif
-
-/* Define `subprocesses' should be defined if you want to
- have code for asynchronous subprocesses
- (as used in M-x compile and M-x shell).
- These do not work for some USG systems yet;
- for the ones where they work, the s/SYSTEM.h file defines this flag. */
-
-#ifndef VMS
-#ifndef USG
-/* #define subprocesses */
-#endif
-#endif
-
-/* Define LD_SWITCH_SITE to contain any special flags your loader may need. */
-#undef LD_SWITCH_SITE
-
-/* Define C_SWITCH_SITE to contain any special flags your compiler needs. */
-#undef C_SWITCH_SITE
-
-/* Define LD_SWITCH_X_SITE to contain any special flags your loader
- may need to deal with X Windows. 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. */
-#undef LD_SWITCH_X_SITE
-
-/* Define LD_SWITCH_X_SITE_AUX with an -R option
- in case it's needed (for Solaris, for example). */
-#undef LD_SWITCH_X_SITE_AUX
-
-/* Define C_SWITCH_X_SITE to contain any special flags your compiler
- may need to deal with X Windows. 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. */
-#undef C_SWITCH_X_SITE
-
-/* Define STACK_DIRECTION here, but not if m/foo.h did. */
-#ifndef STACK_DIRECTION
-#undef STACK_DIRECTION
-#endif
-
-/* Define the return type of signal handlers if the s-xxx file
- did not already do so. */
-#define RETSIGTYPE void
-
-/* SIGTYPE is the macro we actually use. */
-#ifndef SIGTYPE
-#define SIGTYPE RETSIGTYPE
-#endif
-
-#ifdef emacs /* Don't do this for lib-src. */
-/* Tell regex.c to use a type compatible with Emacs. */
-#define RE_TRANSLATE_TYPE Lisp_Object *
-#endif
-
-/* Avoid link-time collision with system mktime if we will use our own. */
-#if ! HAVE_MKTIME || BROKEN_MKTIME
-#define mktime emacs_mktime
-#endif
-
-/* The rest of the code currently tests the CPP symbol BSTRING.
- Override any claims made by the system-description files.
- Note that on some SCO version it is possible to have bcopy and not bcmp. */
-#undef BSTRING
-#if defined (HAVE_BCOPY) && defined (HAVE_BCMP)
-#define BSTRING
-#endif
-
-/* Non-ANSI C compilers usually don't have volatile. */
-#ifndef HAVE_VOLATILE
-#ifndef __STDC__
-#define volatile
-#endif
-#endif
-
-/* Some of the files of Emacs which are intended for use with other
- programs assume that if you have a config.h file, you must declare
- the type of getenv.
-
- This declaration shouldn't appear when alloca.s or Makefile.in
- includes config.h. */
-#ifndef NOT_C_CODE
-extern char *getenv ();
-#endif
-
-#endif /* EMACS_CONFIG_H */
-
-/* These default definitions are good for almost all machines.
- The exceptions override them in m/MACHINE.h. */
-
-#ifndef BITS_PER_CHAR
-#define BITS_PER_CHAR 8
-#endif
-
-#ifndef BITS_PER_SHORT
-#define BITS_PER_SHORT 16
-#endif
-
-/* Note that lisp.h uses this in a preprocessor conditional, so it
- would not work to use sizeof. That being so, we do all of them
- without sizeof, for uniformity's sake. */
-#ifndef BITS_PER_INT
-#define BITS_PER_INT 32
-#endif
-
-#ifndef BITS_PER_LONG
-#define BITS_PER_LONG 32
-#endif
diff --git a/src/data.c b/src/data.c
deleted file mode 100644
index bd7d0bc4ac5..00000000000
--- a/src/data.c
+++ /dev/null
@@ -1,2723 +0,0 @@
-/* Primitive operations on Lisp data types for GNU Emacs Lisp interpreter.
- Copyright (C) 1985, 86, 88, 93, 94, 95 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <signal.h>
-
-#include <config.h>
-#include "lisp.h"
-#include "puresize.h"
-
-#ifndef standalone
-#include "buffer.h"
-#include "keyboard.h"
-#endif
-
-#include "syssignal.h"
-
-#ifdef LISP_FLOAT_TYPE
-
-#ifdef STDC_HEADERS
-#include <float.h>
-#include <stdlib.h>
-#endif
-
-/* If IEEE_FLOATING_POINT isn't defined, default it from FLT_*. */
-#ifndef IEEE_FLOATING_POINT
-#if (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
- && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
-#define IEEE_FLOATING_POINT 1
-#else
-#define IEEE_FLOATING_POINT 0
-#endif
-#endif
-
-/* Work around a problem that happens because math.h on hpux 7
- defines two static variables--which, in Emacs, are not really static,
- because `static' is defined as nothing. The problem is that they are
- here, in floatfns.c, and in lread.c.
- These macros prevent the name conflict. */
-#if defined (HPUX) && !defined (HPUX8)
-#define _MAXLDBL data_c_maxldbl
-#define _NMAXLDBL data_c_nmaxldbl
-#endif
-
-#include <math.h>
-#endif /* LISP_FLOAT_TYPE */
-
-#if !defined (atof)
-extern double atof ();
-#endif /* !atof */
-
-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, Qcyclic_function_indirection;
-Lisp_Object Qsetting_constant, Qinvalid_read_syntax;
-Lisp_Object Qinvalid_function, Qwrong_number_of_arguments, Qno_catch;
-Lisp_Object Qend_of_file, Qarith_error, Qmark_inactive;
-Lisp_Object Qbeginning_of_buffer, Qend_of_buffer, Qbuffer_read_only;
-Lisp_Object Qintegerp, Qnatnump, Qwholenump, Qsymbolp, Qlistp, Qconsp;
-Lisp_Object Qstringp, Qarrayp, Qsequencep, Qbufferp;
-Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp;
-Lisp_Object Qbuffer_or_string_p;
-Lisp_Object Qboundp, Qfboundp;
-Lisp_Object Qchar_table_p, Qvector_or_char_table_p;
-
-Lisp_Object Qcdr;
-Lisp_Object Qad_advice_info, Qad_activate;
-
-Lisp_Object Qrange_error, Qdomain_error, Qsingularity_error;
-Lisp_Object Qoverflow_error, Qunderflow_error;
-
-#ifdef LISP_FLOAT_TYPE
-Lisp_Object Qfloatp;
-Lisp_Object Qnumberp, Qnumber_or_marker_p;
-#endif
-
-static Lisp_Object Qinteger, Qsymbol, Qstring, Qcons, Qmarker, Qoverlay;
-static Lisp_Object Qfloat, Qwindow_configuration, Qprocess, Qwindow;
-static Lisp_Object Qcompiled_function, Qbuffer, Qframe, Qvector;
-static Lisp_Object Qchar_table, Qbool_vector;
-
-static Lisp_Object swap_in_symval_forwarding ();
-
-Lisp_Object
-wrong_type_argument (predicate, value)
- register Lisp_Object predicate, value;
-{
- register Lisp_Object tem;
- do
- {
- if (!EQ (Vmocklisp_arguments, Qt))
- {
- if (STRINGP (value) &&
- (EQ (predicate, Qintegerp) || EQ (predicate, Qinteger_or_marker_p)))
- return Fstring_to_number (value);
- if (INTEGERP (value) && EQ (predicate, Qstringp))
- return Fnumber_to_string (value);
- }
-
- /* If VALUE is not even a valid Lisp object, abort here
- where we can get a backtrace showing where it came from. */
- if ((unsigned int) XGCTYPE (value) >= Lisp_Type_Limit)
- abort ();
-
- value = Fsignal (Qwrong_type_argument, Fcons (predicate, Fcons (value, Qnil)));
- tem = call1 (predicate, value);
- }
- while (NILP (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))));
-}
-
-/* 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)
- EMACS_INT num;
-{
- if (num & (((EMACS_INT) 1) << (VALBITS - 1)))
- return num | (((EMACS_INT) (-1)) << VALBITS);
- else
- return num & ((((EMACS_INT) 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.")
- (object)
- Lisp_Object object;
-{
- if (NILP (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("type-of", Ftype_of, Stype_of, 1, 1, 0,
- "Return a symbol representing the type of OBJECT.\n\
-The symbol returned names the object's basic type;\n\
-for example, (type-of 1) returns `integer'.")
- (object)
- Lisp_Object object;
-{
- switch (XGCTYPE (object))
- {
- case Lisp_Int:
- return Qinteger;
-
- case Lisp_Symbol:
- return Qsymbol;
-
- case Lisp_String:
- return Qstring;
-
- case Lisp_Cons:
- return Qcons;
-
- case Lisp_Misc:
- switch (XMISCTYPE (object))
- {
- case Lisp_Misc_Marker:
- return Qmarker;
- case Lisp_Misc_Overlay:
- return Qoverlay;
- case Lisp_Misc_Float:
- return Qfloat;
- }
- abort ();
-
- case Lisp_Vectorlike:
- if (GC_WINDOW_CONFIGURATIONP (object))
- return Qwindow_configuration;
- if (GC_PROCESSP (object))
- return Qprocess;
- if (GC_WINDOWP (object))
- return Qwindow;
- if (GC_SUBRP (object))
- return Qsubr;
- if (GC_COMPILEDP (object))
- return Qcompiled_function;
- if (GC_BUFFERP (object))
- return Qbuffer;
- if (GC_CHAR_TABLE_P (object))
- return Qchar_table;
- if (GC_BOOL_VECTOR_P (object))
- return Qbool_vector;
- if (GC_FRAMEP (object))
- return Qframe;
- return Qvector;
-
-#ifdef LISP_FLOAT_TYPE
- case Lisp_Float:
- return Qfloat;
-#endif
-
- default:
- abort ();
- }
-}
-
-DEFUN ("consp", Fconsp, Sconsp, 1, 1, 0, "T if OBJECT is a cons cell.")
- (object)
- Lisp_Object object;
-{
- if (CONSP (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("atom", Fatom, Satom, 1, 1, 0, "T if OBJECT is not a cons cell. This includes nil.")
- (object)
- Lisp_Object object;
-{
- if (CONSP (object))
- return Qnil;
- return Qt;
-}
-
-DEFUN ("listp", Flistp, Slistp, 1, 1, 0, "T if OBJECT is a list. This includes nil.")
- (object)
- Lisp_Object object;
-{
- if (CONSP (object) || NILP (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("nlistp", Fnlistp, Snlistp, 1, 1, 0, "T if OBJECT is not a list. Lists include nil.")
- (object)
- Lisp_Object object;
-{
- if (CONSP (object) || NILP (object))
- return Qnil;
- return Qt;
-}
-
-DEFUN ("symbolp", Fsymbolp, Ssymbolp, 1, 1, 0, "T if OBJECT is a symbol.")
- (object)
- Lisp_Object object;
-{
- if (SYMBOLP (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("vectorp", Fvectorp, Svectorp, 1, 1, 0, "T if OBJECT is a vector.")
- (object)
- Lisp_Object object;
-{
- if (VECTORP (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("stringp", Fstringp, Sstringp, 1, 1, 0, "T if OBJECT is a string.")
- (object)
- Lisp_Object object;
-{
- if (STRINGP (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("char-table-p", Fchar_table_p, Schar_table_p, 1, 1, 0, "T if OBJECT is a char-table.")
- (object)
- Lisp_Object object;
-{
- if (CHAR_TABLE_P (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("vector-or-char-table-p", Fvector_or_char_table_p,
- Svector_or_char_table_p, 1, 1, 0,
- "T if OBJECT is a char-table or vector.")
- (object)
- Lisp_Object object;
-{
- if (VECTORP (object) || CHAR_TABLE_P (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("bool-vector-p", Fbool_vector_p, Sbool_vector_p, 1, 1, 0, "T if OBJECT is a bool-vector.")
- (object)
- Lisp_Object object;
-{
- if (BOOL_VECTOR_P (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("arrayp", Farrayp, Sarrayp, 1, 1, 0, "T if OBJECT is an array (string or vector).")
- (object)
- Lisp_Object object;
-{
- if (VECTORP (object) || STRINGP (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("sequencep", Fsequencep, Ssequencep, 1, 1, 0,
- "T if OBJECT is a sequence (list or array).")
- (object)
- register Lisp_Object object;
-{
- if (CONSP (object) || NILP (object) || VECTORP (object) || STRINGP (object)
- || CHAR_TABLE_P (object) || BOOL_VECTOR_P (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("bufferp", Fbufferp, Sbufferp, 1, 1, 0, "T if OBJECT is an editor buffer.")
- (object)
- Lisp_Object object;
-{
- if (BUFFERP (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("markerp", Fmarkerp, Smarkerp, 1, 1, 0, "T if OBJECT is a marker (editor pointer).")
- (object)
- Lisp_Object object;
-{
- if (MARKERP (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("subrp", Fsubrp, Ssubrp, 1, 1, 0, "T if OBJECT is a built-in function.")
- (object)
- Lisp_Object object;
-{
- if (SUBRP (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("byte-code-function-p", Fbyte_code_function_p, Sbyte_code_function_p,
- 1, 1, 0, "T if OBJECT is a byte-compiled function object.")
- (object)
- Lisp_Object object;
-{
- if (COMPILEDP (object))
- 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 (an integer) or a string.")
- (object)
- register Lisp_Object object;
-{
- if (INTEGERP (object) || STRINGP (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("integerp", Fintegerp, Sintegerp, 1, 1, 0, "T if OBJECT is an integer.")
- (object)
- Lisp_Object object;
-{
- if (INTEGERP (object))
- 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).")
- (object)
- register Lisp_Object object;
-{
- if (MARKERP (object) || INTEGERP (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("natnump", Fnatnump, Snatnump, 1, 1, 0,
- "T if OBJECT is a nonnegative integer.")
- (object)
- Lisp_Object object;
-{
- if (NATNUMP (object))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("numberp", Fnumberp, Snumberp, 1, 1, 0,
- "T if OBJECT is a number (floating point or integer).")
- (object)
- Lisp_Object object;
-{
- if (NUMBERP (object))
- return Qt;
- else
- return Qnil;
-}
-
-DEFUN ("number-or-marker-p", Fnumber_or_marker_p,
- Snumber_or_marker_p, 1, 1, 0,
- "T if OBJECT is a number or a marker.")
- (object)
- Lisp_Object object;
-{
- if (NUMBERP (object) || MARKERP (object))
- return Qt;
- return Qnil;
-}
-
-#ifdef LISP_FLOAT_TYPE
-DEFUN ("floatp", Ffloatp, Sfloatp, 1, 1, 0,
- "T if OBJECT is a floating point number.")
- (object)
- Lisp_Object object;
-{
- if (FLOATP (object))
- return Qt;
- return Qnil;
-}
-#endif /* LISP_FLOAT_TYPE */
-
-/* Extract and set components of lists */
-
-DEFUN ("car", Fcar, Scar, 1, 1, 0,
- "Return the car of LIST. If arg is nil, return nil.\n\
-Error if arg is not nil and not a cons cell. See also `car-safe'.")
- (list)
- register Lisp_Object list;
-{
- while (1)
- {
- if (CONSP (list))
- 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 (CONSP (object))
- return XCONS (object)->car;
- else
- return Qnil;
-}
-
-DEFUN ("cdr", Fcdr, Scdr, 1, 1, 0,
- "Return the cdr of LIST. If arg is nil, return nil.\n\
-Error if arg is not nil and not a cons cell. See also `cdr-safe'.")
-
- (list)
- register Lisp_Object list;
-{
- while (1)
- {
- if (CONSP (list))
- 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 (CONSP (object))
- return XCONS (object)->cdr;
- else
- return Qnil;
-}
-
-DEFUN ("setcar", Fsetcar, Ssetcar, 2, 2, 0,
- "Set the car of CELL to be NEWCAR. Returns NEWCAR.")
- (cell, newcar)
- register Lisp_Object cell, newcar;
-{
- if (!CONSP (cell))
- 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 CELL to be NEWCDR. Returns NEWCDR.")
- (cell, newcdr)
- register Lisp_Object cell, newcdr;
-{
- if (!CONSP (cell))
- 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.")
- (symbol)
- register Lisp_Object symbol;
-{
- Lisp_Object valcontents;
- CHECK_SYMBOL (symbol, 0);
-
- valcontents = XSYMBOL (symbol)->value;
-
- if (BUFFER_LOCAL_VALUEP (valcontents)
- || SOME_BUFFER_LOCAL_VALUEP (valcontents))
- valcontents = swap_in_symval_forwarding (symbol, valcontents);
-
- return (EQ (valcontents, Qunbound) ? Qnil : Qt);
-}
-
-DEFUN ("fboundp", Ffboundp, Sfboundp, 1, 1, 0, "T if SYMBOL's function definition is not void.")
- (symbol)
- register Lisp_Object symbol;
-{
- CHECK_SYMBOL (symbol, 0);
- return (EQ (XSYMBOL (symbol)->function, Qunbound) ? Qnil : Qt);
-}
-
-DEFUN ("makunbound", Fmakunbound, Smakunbound, 1, 1, 0, "Make SYMBOL's value be void.")
- (symbol)
- register Lisp_Object symbol;
-{
- CHECK_SYMBOL (symbol, 0);
- if (NILP (symbol) || EQ (symbol, Qt))
- return Fsignal (Qsetting_constant, Fcons (symbol, Qnil));
- Fset (symbol, Qunbound);
- return symbol;
-}
-
-DEFUN ("fmakunbound", Ffmakunbound, Sfmakunbound, 1, 1, 0, "Make SYMBOL's function definition be void.")
- (symbol)
- register Lisp_Object symbol;
-{
- CHECK_SYMBOL (symbol, 0);
- if (NILP (symbol) || EQ (symbol, Qt))
- return Fsignal (Qsetting_constant, Fcons (symbol, Qnil));
- XSYMBOL (symbol)->function = Qunbound;
- return symbol;
-}
-
-DEFUN ("symbol-function", Fsymbol_function, Ssymbol_function, 1, 1, 0,
- "Return SYMBOL's function definition. Error if that is void.")
- (symbol)
- register Lisp_Object symbol;
-{
- CHECK_SYMBOL (symbol, 0);
- if (EQ (XSYMBOL (symbol)->function, Qunbound))
- return Fsignal (Qvoid_function, Fcons (symbol, Qnil));
- return XSYMBOL (symbol)->function;
-}
-
-DEFUN ("symbol-plist", Fsymbol_plist, Ssymbol_plist, 1, 1, 0, "Return SYMBOL's property list.")
- (symbol)
- register Lisp_Object symbol;
-{
- CHECK_SYMBOL (symbol, 0);
- return XSYMBOL (symbol)->plist;
-}
-
-DEFUN ("symbol-name", Fsymbol_name, Ssymbol_name, 1, 1, 0, "Return SYMBOL's name, a string.")
- (symbol)
- register Lisp_Object symbol;
-{
- register Lisp_Object name;
-
- CHECK_SYMBOL (symbol, 0);
- XSETSTRING (name, XSYMBOL (symbol)->name);
- return name;
-}
-
-DEFUN ("fset", Ffset, Sfset, 2, 2, 0,
- "Set SYMBOL's function definition to DEFINITION, and return DEFINITION.")
- (symbol, definition)
- register Lisp_Object symbol, definition;
-{
- CHECK_SYMBOL (symbol, 0);
- if (NILP (symbol) || EQ (symbol, Qt))
- return Fsignal (Qsetting_constant, Fcons (symbol, Qnil));
- if (!NILP (Vautoload_queue) && !EQ (XSYMBOL (symbol)->function, Qunbound))
- Vautoload_queue = Fcons (Fcons (symbol, XSYMBOL (symbol)->function),
- Vautoload_queue);
- XSYMBOL (symbol)->function = definition;
- /* Handle automatic advice activation */
- if (CONSP (XSYMBOL (symbol)->plist) && !NILP (Fget (symbol, Qad_advice_info)))
- {
- call2 (Qad_activate, symbol, Qnil);
- definition = XSYMBOL (symbol)->function;
- }
- return definition;
-}
-
-DEFUN ("defalias", Fdefalias, Sdefalias, 2, 2, 0,
- "Set SYMBOL's function definition to DEFINITION, and return DEFINITION.\n\
-Associates the function with the current load file, if any.")
- (symbol, definition)
- register Lisp_Object symbol, definition;
-{
- CHECK_SYMBOL (symbol, 0);
- if (!NILP (Vautoload_queue) && !EQ (XSYMBOL (symbol)->function, Qunbound))
- Vautoload_queue = Fcons (Fcons (symbol, XSYMBOL (symbol)->function),
- Vautoload_queue);
- XSYMBOL (symbol)->function = definition;
- /* Handle automatic advice activation */
- if (CONSP (XSYMBOL (symbol)->plist) && !NILP (Fget (symbol, Qad_advice_info)))
- {
- call2 (Qad_activate, symbol, Qnil);
- definition = XSYMBOL (symbol)->function;
- }
- LOADHIST_ATTACH (symbol);
- return definition;
-}
-
-DEFUN ("setplist", Fsetplist, Ssetplist, 2, 2, 0,
- "Set SYMBOL's property list to NEWVAL, and return NEWVAL.")
- (symbol, newplist)
- register Lisp_Object symbol, newplist;
-{
- CHECK_SYMBOL (symbol, 0);
- XSYMBOL (symbol)->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.
- This does not handle buffer-local variables; use
- swap_in_symval_forwarding for that. */
-
-Lisp_Object
-do_symval_forwarding (valcontents)
- register Lisp_Object valcontents;
-{
- register Lisp_Object val;
- int offset;
- if (MISCP (valcontents))
- switch (XMISCTYPE (valcontents))
- {
- case Lisp_Misc_Intfwd:
- XSETINT (val, *XINTFWD (valcontents)->intvar);
- return val;
-
- case Lisp_Misc_Boolfwd:
- return (*XBOOLFWD (valcontents)->boolvar ? Qt : Qnil);
-
- case Lisp_Misc_Objfwd:
- return *XOBJFWD (valcontents)->objvar;
-
- case Lisp_Misc_Buffer_Objfwd:
- offset = XBUFFER_OBJFWD (valcontents)->offset;
- return *(Lisp_Object *)(offset + (char *)current_buffer);
-
- case Lisp_Misc_Kboard_Objfwd:
- offset = XKBOARD_OBJFWD (valcontents)->offset;
- return *(Lisp_Object *)(offset + (char *)current_kboard);
- }
- return valcontents;
-}
-
-/* Store NEWVAL into SYMBOL, where VALCONTENTS is found in the value cell
- of SYMBOL. If SYMBOL is buffer-local, VALCONTENTS should be the
- buffer-independent contents of the value cell: forwarded just one
- step past the buffer-localness. */
-
-void
-store_symval_forwarding (symbol, valcontents, newval)
- Lisp_Object symbol;
- register Lisp_Object valcontents, newval;
-{
- switch (SWITCH_ENUM_CAST (XTYPE (valcontents)))
- {
- case Lisp_Misc:
- switch (XMISCTYPE (valcontents))
- {
- case Lisp_Misc_Intfwd:
- CHECK_NUMBER (newval, 1);
- *XINTFWD (valcontents)->intvar = XINT (newval);
- if (*XINTFWD (valcontents)->intvar != XINT (newval))
- error ("Value out of range for variable `%s'",
- XSYMBOL (symbol)->name->data);
- break;
-
- case Lisp_Misc_Boolfwd:
- *XBOOLFWD (valcontents)->boolvar = NILP (newval) ? 0 : 1;
- break;
-
- case Lisp_Misc_Objfwd:
- *XOBJFWD (valcontents)->objvar = newval;
- break;
-
- case Lisp_Misc_Buffer_Objfwd:
- {
- int offset = XBUFFER_OBJFWD (valcontents)->offset;
- Lisp_Object type;
-
- type = *(Lisp_Object *)(offset + (char *)&buffer_local_types);
- if (! NILP (type) && ! NILP (newval)
- && XTYPE (newval) != XINT (type))
- buffer_slot_type_mismatch (offset);
-
- *(Lisp_Object *)(offset + (char *)current_buffer) = newval;
- }
- break;
-
- case Lisp_Misc_Kboard_Objfwd:
- (*(Lisp_Object *)((char *)current_kboard
- + XKBOARD_OBJFWD (valcontents)->offset))
- = newval;
- break;
-
- default:
- goto def;
- }
- break;
-
- default:
- def:
- valcontents = XSYMBOL (symbol)->value;
- if (BUFFER_LOCAL_VALUEP (valcontents)
- || SOME_BUFFER_LOCAL_VALUEP (valcontents))
- XBUFFER_LOCAL_VALUE (valcontents)->car = newval;
- else
- XSYMBOL (symbol)->value = newval;
- }
-}
-
-/* Set up the buffer-local symbol SYMBOL for validity in the current
- buffer. VALCONTENTS is the contents of its value cell.
- Return the value forwarded one step past the buffer-local indicator. */
-
-static Lisp_Object
-swap_in_symval_forwarding (symbol, valcontents)
- Lisp_Object symbol, valcontents;
-{
- /* valcontents is a pointer to a struct resembling the cons
- (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. */
-
- register Lisp_Object tem1;
- tem1 = XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->car;
-
- if (NILP (tem1) || current_buffer != XBUFFER (tem1))
- {
- tem1 = XCONS (XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->cdr)->car;
- Fsetcdr (tem1,
- do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->car));
- tem1 = assq_no_quit (symbol, current_buffer->local_var_alist);
- if (NILP (tem1))
- tem1 = XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->cdr;
- XCONS (XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->cdr)->car = tem1;
- XSETBUFFER (XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->car,
- current_buffer);
- store_symval_forwarding (symbol, XBUFFER_LOCAL_VALUE (valcontents)->car,
- Fcdr (tem1));
- }
- return XBUFFER_LOCAL_VALUE (valcontents)->car;
-}
-
-/* Find the value of a symbol, returning Qunbound if it's not bound.
- This is helpful for code which just wants to get a variable's value
- if it has one, without signaling an error.
- Note that it must not be possible to quit
- within this function. Great care is required for this. */
-
-Lisp_Object
-find_symbol_value (symbol)
- Lisp_Object symbol;
-{
- register Lisp_Object valcontents, tem1;
- register Lisp_Object val;
- CHECK_SYMBOL (symbol, 0);
- valcontents = XSYMBOL (symbol)->value;
-
- if (BUFFER_LOCAL_VALUEP (valcontents)
- || SOME_BUFFER_LOCAL_VALUEP (valcontents))
- valcontents = swap_in_symval_forwarding (symbol, valcontents);
-
- if (MISCP (valcontents))
- {
- switch (XMISCTYPE (valcontents))
- {
- case Lisp_Misc_Intfwd:
- XSETINT (val, *XINTFWD (valcontents)->intvar);
- return val;
-
- case Lisp_Misc_Boolfwd:
- return (*XBOOLFWD (valcontents)->boolvar ? Qt : Qnil);
-
- case Lisp_Misc_Objfwd:
- return *XOBJFWD (valcontents)->objvar;
-
- case Lisp_Misc_Buffer_Objfwd:
- return *(Lisp_Object *)(XBUFFER_OBJFWD (valcontents)->offset
- + (char *)current_buffer);
-
- case Lisp_Misc_Kboard_Objfwd:
- return *(Lisp_Object *)(XKBOARD_OBJFWD (valcontents)->offset
- + (char *)current_kboard);
- }
- }
-
- return valcontents;
-}
-
-DEFUN ("symbol-value", Fsymbol_value, Ssymbol_value, 1, 1, 0,
- "Return SYMBOL's value. Error if that is void.")
- (symbol)
- Lisp_Object symbol;
-{
- Lisp_Object val;
-
- val = find_symbol_value (symbol);
- if (EQ (val, Qunbound))
- return Fsignal (Qvoid_variable, Fcons (symbol, Qnil));
- else
- return val;
-}
-
-DEFUN ("set", Fset, Sset, 2, 2, 0,
- "Set SYMBOL's value to NEWVAL, and return NEWVAL.")
- (symbol, newval)
- register Lisp_Object symbol, newval;
-{
- int voide = EQ (newval, Qunbound);
-
- register Lisp_Object valcontents, tem1, current_alist_element;
-
- CHECK_SYMBOL (symbol, 0);
- if (NILP (symbol) || EQ (symbol, Qt))
- return Fsignal (Qsetting_constant, Fcons (symbol, Qnil));
- valcontents = XSYMBOL (symbol)->value;
-
- if (BUFFER_OBJFWDP (valcontents))
- {
- register int idx = XBUFFER_OBJFWD (valcontents)->offset;
- register int mask = XINT (*((Lisp_Object *)
- (idx + (char *)&buffer_local_flags)));
- if (mask > 0)
- current_buffer->local_var_flags |= mask;
- }
-
- else if (BUFFER_LOCAL_VALUEP (valcontents)
- || SOME_BUFFER_LOCAL_VALUEP (valcontents))
- {
- /* valcontents is actually a pointer to a struct resembling a cons,
- with contents something like:
- (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
- 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. */
-
- /* What value are we caching right now? */
- current_alist_element =
- XCONS (XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->cdr)->car;
-
- /* If the current buffer is not the buffer whose binding is
- currently cached, or if it's a Lisp_Buffer_Local_Value and
- we're looking at the default value, the cache is invalid; we
- need to write it out, and find the new CURRENT-ALIST-ELEMENT. */
- if ((current_buffer
- != XBUFFER (XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->car))
- || (BUFFER_LOCAL_VALUEP (valcontents)
- && EQ (XCONS (current_alist_element)->car,
- current_alist_element)))
- {
- /* Write out the cached value for the old buffer; copy it
- back to its alist element. This works if the current
- buffer only sees the default value, too. */
- Fsetcdr (current_alist_element,
- do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->car));
-
- /* Find the new value for CURRENT-ALIST-ELEMENT. */
- tem1 = Fassq (symbol, current_buffer->local_var_alist);
- if (NILP (tem1))
- {
- /* This buffer still sees the default value. */
-
- /* If the variable is a Lisp_Some_Buffer_Local_Value,
- make CURRENT-ALIST-ELEMENT point to itself,
- indicating that we're seeing the default value. */
- if (SOME_BUFFER_LOCAL_VALUEP (valcontents))
- tem1 = XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->cdr;
-
- /* If it's a Lisp_Buffer_Local_Value, give this buffer a
- new assoc for a local value and set
- CURRENT-ALIST-ELEMENT to point to that. */
- else
- {
- tem1 = Fcons (symbol, Fcdr (current_alist_element));
- current_buffer->local_var_alist =
- Fcons (tem1, current_buffer->local_var_alist);
- }
- }
- /* Cache the new buffer's assoc in CURRENT-ALIST-ELEMENT. */
- XCONS (XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->cdr)->car
- = tem1;
-
- /* Set BUFFER, now that CURRENT-ALIST-ELEMENT is accurate. */
- XSETBUFFER (XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->car,
- current_buffer);
- }
- valcontents = XBUFFER_LOCAL_VALUE (valcontents)->car;
- }
-
- /* If storing void (making the symbol void), forward only through
- buffer-local indicator, not through Lisp_Objfwd, etc. */
- if (voide)
- store_symval_forwarding (symbol, Qnil, newval);
- else
- store_symval_forwarding (symbol, valcontents, newval);
-
- return newval;
-}
-
-/* Access or set a buffer-local symbol's default value. */
-
-/* Return the default value of SYMBOL, but don't check for voidness.
- Return Qunbound if it is void. */
-
-Lisp_Object
-default_value (symbol)
- Lisp_Object symbol;
-{
- register Lisp_Object valcontents;
-
- CHECK_SYMBOL (symbol, 0);
- valcontents = XSYMBOL (symbol)->value;
-
- /* For a built-in buffer-local variable, get the default value
- rather than letting do_symval_forwarding get the current value. */
- if (BUFFER_OBJFWDP (valcontents))
- {
- register int idx = XBUFFER_OBJFWD (valcontents)->offset;
-
- if (XINT (*(Lisp_Object *) (idx + (char *) &buffer_local_flags)) != 0)
- return *(Lisp_Object *)(idx + (char *) &buffer_defaults);
- }
-
- /* Handle user-created local variables. */
- if (BUFFER_LOCAL_VALUEP (valcontents)
- || SOME_BUFFER_LOCAL_VALUEP (valcontents))
- {
- /* If var is set up for a buffer that lacks a local value for it,
- the current value is nominally the default value.
- But the current value slot may be more up to date, since
- ordinary setq stores just that slot. So use that. */
- Lisp_Object current_alist_element, alist_element_car;
- current_alist_element
- = XCONS (XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->cdr)->car;
- alist_element_car = XCONS (current_alist_element)->car;
- if (EQ (alist_element_car, current_alist_element))
- return do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->car);
- else
- return XCONS (XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->cdr)->cdr;
- }
- /* For other variables, get the current value. */
- return do_symval_forwarding (valcontents);
-}
-
-DEFUN ("default-boundp", Fdefault_boundp, Sdefault_boundp, 1, 1, 0,
- "Return T if SYMBOL has a non-void default value.\n\
-This is the value that is seen in buffers that do not have their own values\n\
-for this variable.")
- (symbol)
- Lisp_Object symbol;
-{
- register Lisp_Object value;
-
- value = default_value (symbol);
- return (EQ (value, Qunbound) ? Qnil : Qt);
-}
-
-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. The default value is meaningful for variables with\n\
-local bindings in certain buffers.")
- (symbol)
- Lisp_Object symbol;
-{
- register Lisp_Object value;
-
- value = default_value (symbol);
- if (EQ (value, Qunbound))
- return Fsignal (Qvoid_variable, Fcons (symbol, Qnil));
- return value;
-}
-
-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.")
- (symbol, value)
- Lisp_Object symbol, value;
-{
- register Lisp_Object valcontents, current_alist_element, alist_element_buffer;
-
- CHECK_SYMBOL (symbol, 0);
- valcontents = XSYMBOL (symbol)->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 (BUFFER_OBJFWDP (valcontents))
- {
- register int idx = XBUFFER_OBJFWD (valcontents)->offset;
- register struct buffer *b;
- register int mask = XINT (*((Lisp_Object *)
- (idx + (char *)&buffer_local_flags)));
-
- if (mask > 0)
- {
- *(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 (!BUFFER_LOCAL_VALUEP (valcontents)
- && !SOME_BUFFER_LOCAL_VALUEP (valcontents))
- return Fset (symbol, value);
-
- /* Store new value into the DEFAULT-VALUE slot */
- XCONS (XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->cdr)->cdr = value;
-
- /* If that slot is current, we must set the REALVALUE slot too */
- current_alist_element
- = XCONS (XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->cdr)->car;
- alist_element_buffer = Fcar (current_alist_element);
- if (EQ (alist_element_buffer, current_alist_element))
- store_symval_forwarding (symbol, XBUFFER_LOCAL_VALUE (valcontents)->car,
- value);
-
- return value;
-}
-
-DEFUN ("setq-default", Fsetq_default, Ssetq_default, 2, UNEVALLED, 0,
- "Set the default value of variable VAR to VALUE.\n\
-VAR, the variable name, is literal (not evaluated);\n\
-VALUE is an expression and it is evaluated.\n\
-The default value of a variable is seen in buffers\n\
-that do not have their own values for the variable.\n\
-\n\
-More generally, you can use multiple variables and values, as in\n\
- (setq-default SYMBOL VALUE SYMBOL VALUE...)\n\
-This sets each SYMBOL's default value to the corresponding VALUE.\n\
-The VALUE for the Nth SYMBOL can refer to the new default values\n\
-of previous SYMs.")
- (args)
- Lisp_Object args;
-{
- register Lisp_Object args_left;
- register Lisp_Object val, symbol;
- struct gcpro gcpro1;
-
- if (NILP (args))
- return Qnil;
-
- args_left = args;
- GCPRO1 (args);
-
- do
- {
- val = Feval (Fcar (Fcdr (args_left)));
- symbol = Fcar (args_left);
- Fset_default (symbol, val);
- args_left = Fcdr (Fcdr (args_left));
- }
- while (!NILP (args_left));
-
- UNGCPRO;
- return val;
-}
-
-/* Lisp functions for creating and removing buffer-local variables. */
-
-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\
-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.\n\
-The function `default-value' gets the default value and `set-default' sets it.")
- (variable)
- register Lisp_Object variable;
-{
- register Lisp_Object tem, valcontents, newval;
-
- CHECK_SYMBOL (variable, 0);
-
- valcontents = XSYMBOL (variable)->value;
- if (EQ (variable, Qnil) || EQ (variable, Qt) || KBOARD_OBJFWDP (valcontents))
- error ("Symbol %s may not be buffer-local", XSYMBOL (variable)->name->data);
-
- if (BUFFER_LOCAL_VALUEP (valcontents) || BUFFER_OBJFWDP (valcontents))
- return variable;
- if (SOME_BUFFER_LOCAL_VALUEP (valcontents))
- {
- XMISCTYPE (XSYMBOL (variable)->value) = Lisp_Misc_Buffer_Local_Value;
- return variable;
- }
- if (EQ (valcontents, Qunbound))
- XSYMBOL (variable)->value = Qnil;
- tem = Fcons (Qnil, Fsymbol_value (variable));
- XCONS (tem)->car = tem;
- newval = allocate_misc ();
- XMISCTYPE (newval) = Lisp_Misc_Buffer_Local_Value;
- XBUFFER_LOCAL_VALUE (newval)->car = XSYMBOL (variable)->value;
- XBUFFER_LOCAL_VALUE (newval)->cdr = Fcons (Fcurrent_buffer (), tem);
- XSYMBOL (variable)->value = newval;
- return variable;
-}
-
-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\
-\(The buffer-local value of VARIABLE starts out as the same value\n\
-VARIABLE previously had. If VARIABLE was void, it remains void.\)\n\
-See also `make-variable-buffer-local'.\n\n\
-If the variable is already arranged to become local when set,\n\
-this function causes a local value to exist for this buffer,\n\
-just as setting the variable would do.\n\
-\n\
-Do not use `make-local-variable' to make a hook variable buffer-local.\n\
-Use `make-local-hook' instead.")
- (variable)
- register Lisp_Object variable;
-{
- register Lisp_Object tem, valcontents;
-
- CHECK_SYMBOL (variable, 0);
-
- valcontents = XSYMBOL (variable)->value;
- if (EQ (variable, Qnil) || EQ (variable, Qt) || KBOARD_OBJFWDP (valcontents))
- error ("Symbol %s may not be buffer-local", XSYMBOL (variable)->name->data);
-
- if (BUFFER_LOCAL_VALUEP (valcontents) || BUFFER_OBJFWDP (valcontents))
- {
- tem = Fboundp (variable);
-
- /* Make sure the symbol has a local value in this particular buffer,
- by setting it to the same value it already has. */
- Fset (variable, (EQ (tem, Qt) ? Fsymbol_value (variable) : Qunbound));
- return variable;
- }
- /* Make sure symbol is set up to hold per-buffer values */
- if (!SOME_BUFFER_LOCAL_VALUEP (valcontents))
- {
- Lisp_Object newval;
- tem = Fcons (Qnil, do_symval_forwarding (valcontents));
- XCONS (tem)->car = tem;
- newval = allocate_misc ();
- XMISCTYPE (newval) = Lisp_Misc_Some_Buffer_Local_Value;
- XBUFFER_LOCAL_VALUE (newval)->car = XSYMBOL (variable)->value;
- XBUFFER_LOCAL_VALUE (newval)->cdr = Fcons (Qnil, tem);
- XSYMBOL (variable)->value = newval;
- }
- /* Make sure this buffer has its own value of symbol */
- tem = Fassq (variable, current_buffer->local_var_alist);
- if (NILP (tem))
- {
- /* Swap out any local binding for some other buffer, and make
- sure the current value is permanently recorded, if it's the
- default value. */
- find_symbol_value (variable);
-
- current_buffer->local_var_alist
- = Fcons (Fcons (variable, XCONS (XCONS (XBUFFER_LOCAL_VALUE (XSYMBOL (variable)->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 */
- {
- Lisp_Object *pvalbuf;
-
- valcontents = XSYMBOL (variable)->value;
-
- pvalbuf = &XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->car;
- if (current_buffer == XBUFFER (*pvalbuf))
- *pvalbuf = Qnil;
- }
- }
-
- /* If the symbol forwards into a C variable, then swap in the
- variable for this buffer immediately. If C code modifies the
- variable before we swap in, then that new value will clobber the
- default value the next time we swap. */
- valcontents = XBUFFER_LOCAL_VALUE (XSYMBOL (variable)->value)->car;
- if (INTFWDP (valcontents) || BOOLFWDP (valcontents) || OBJFWDP (valcontents))
- swap_in_symval_forwarding (variable, XSYMBOL (variable)->value);
-
- return variable;
-}
-
-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.")
- (variable)
- register Lisp_Object variable;
-{
- register Lisp_Object tem, valcontents;
-
- CHECK_SYMBOL (variable, 0);
-
- valcontents = XSYMBOL (variable)->value;
-
- if (BUFFER_OBJFWDP (valcontents))
- {
- register int idx = XBUFFER_OBJFWD (valcontents)->offset;
- register int mask = XINT (*((Lisp_Object*)
- (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 variable;
- }
-
- if (!BUFFER_LOCAL_VALUEP (valcontents)
- && !SOME_BUFFER_LOCAL_VALUEP (valcontents))
- return variable;
-
- /* Get rid of this buffer's alist element, if any */
-
- tem = Fassq (variable, current_buffer->local_var_alist);
- if (!NILP (tem))
- current_buffer->local_var_alist
- = Fdelq (tem, current_buffer->local_var_alist);
-
- /* If the symbol is set up for the current buffer, recompute its
- value. We have to do it now, or else forwarded objects won't
- work right. */
- {
- Lisp_Object *pvalbuf;
- valcontents = XSYMBOL (variable)->value;
- pvalbuf = &XCONS (XBUFFER_LOCAL_VALUE (valcontents)->cdr)->car;
- if (current_buffer == XBUFFER (*pvalbuf))
- {
- *pvalbuf = Qnil;
- find_symbol_value (variable);
- }
- }
-
- return variable;
-}
-
-DEFUN ("local-variable-p", Flocal_variable_p, Slocal_variable_p,
- 1, 2, 0,
- "Non-nil if VARIABLE has a local binding in buffer BUFFER.\n\
-BUFFER defaults to the current buffer.")
- (variable, buffer)
- register Lisp_Object variable, buffer;
-{
- Lisp_Object valcontents;
- register struct buffer *buf;
-
- if (NILP (buffer))
- buf = current_buffer;
- else
- {
- CHECK_BUFFER (buffer, 0);
- buf = XBUFFER (buffer);
- }
-
- CHECK_SYMBOL (variable, 0);
-
- valcontents = XSYMBOL (variable)->value;
- if (BUFFER_LOCAL_VALUEP (valcontents)
- || SOME_BUFFER_LOCAL_VALUEP (valcontents))
- {
- Lisp_Object tail, elt;
- for (tail = buf->local_var_alist; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- elt = XCONS (tail)->car;
- if (EQ (variable, XCONS (elt)->car))
- return Qt;
- }
- }
- if (BUFFER_OBJFWDP (valcontents))
- {
- int offset = XBUFFER_OBJFWD (valcontents)->offset;
- int mask = XINT (*(Lisp_Object *)(offset + (char *)&buffer_local_flags));
- if (mask == -1 || (buf->local_var_flags & mask))
- return Qt;
- }
- return Qnil;
-}
-
-DEFUN ("local-variable-if-set-p", Flocal_variable_if_set_p, Slocal_variable_if_set_p,
- 1, 2, 0,
- "Non-nil if VARIABLE will be local in buffer BUFFER if it is set there.\n\
-BUFFER defaults to the current buffer.")
- (variable, buffer)
- register Lisp_Object variable, buffer;
-{
- Lisp_Object valcontents;
- register struct buffer *buf;
-
- if (NILP (buffer))
- buf = current_buffer;
- else
- {
- CHECK_BUFFER (buffer, 0);
- buf = XBUFFER (buffer);
- }
-
- CHECK_SYMBOL (variable, 0);
-
- valcontents = XSYMBOL (variable)->value;
-
- /* This means that make-variable-buffer-local was done. */
- if (BUFFER_LOCAL_VALUEP (valcontents))
- return Qt;
- /* All these slots become local if they are set. */
- if (BUFFER_OBJFWDP (valcontents))
- return Qt;
- if (SOME_BUFFER_LOCAL_VALUEP (valcontents))
- {
- Lisp_Object tail, elt;
- for (tail = buf->local_var_alist; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- elt = XCONS (tail)->car;
- if (EQ (variable, XCONS (elt)->car))
- return Qt;
- }
- }
- return Qnil;
-}
-
-/* Find the function at the end of a chain of symbol function indirections. */
-
-/* If OBJECT is a symbol, find the end of its function chain and
- return the value found there. If OBJECT is not a symbol, just
- return it. If there is a cycle in the function chain, signal a
- cyclic-function-indirection error.
-
- This is like Findirect_function, except that it doesn't signal an
- error if the chain ends up unbound. */
-Lisp_Object
-indirect_function (object)
- register Lisp_Object object;
-{
- Lisp_Object tortoise, hare;
-
- hare = tortoise = object;
-
- for (;;)
- {
- if (!SYMBOLP (hare) || EQ (hare, Qunbound))
- break;
- hare = XSYMBOL (hare)->function;
- if (!SYMBOLP (hare) || EQ (hare, Qunbound))
- break;
- hare = XSYMBOL (hare)->function;
-
- tortoise = XSYMBOL (tortoise)->function;
-
- if (EQ (hare, tortoise))
- Fsignal (Qcyclic_function_indirection, Fcons (object, Qnil));
- }
-
- return hare;
-}
-
-DEFUN ("indirect-function", Findirect_function, Sindirect_function, 1, 1, 0,
- "Return the function at the end of OBJECT's function chain.\n\
-If OBJECT is a symbol, follow all function indirections and return the final\n\
-function binding.\n\
-If OBJECT is not a symbol, just return it.\n\
-Signal a void-function error if the final symbol is unbound.\n\
-Signal a cyclic-function-indirection error if there is a loop in the\n\
-function chain of symbols.")
- (object)
- register Lisp_Object object;
-{
- Lisp_Object result;
-
- result = indirect_function (object);
-
- if (EQ (result, Qunbound))
- return Fsignal (Qvoid_function, Fcons (object, Qnil));
- return result;
-}
-
-/* Extract and set vector and string elements */
-
-DEFUN ("aref", Faref, Saref, 2, 2, 0,
- "Return the element of ARRAY at index IDX.\n\
-ARRAY may be a vector, a string, a char-table, a bool-vector,\n\
-or a byte-code object. IDX starts at 0.")
- (array, idx)
- register Lisp_Object array;
- Lisp_Object idx;
-{
- register int idxval;
-
- CHECK_NUMBER (idx, 1);
- idxval = XINT (idx);
- if (STRINGP (array))
- {
- Lisp_Object val;
- if (idxval < 0 || idxval >= XSTRING (array)->size)
- args_out_of_range (array, idx);
- XSETFASTINT (val, (unsigned char) XSTRING (array)->data[idxval]);
- return val;
- }
- else if (BOOL_VECTOR_P (array))
- {
- int val;
-
- if (idxval < 0 || idxval >= XBOOL_VECTOR (array)->size)
- args_out_of_range (array, idx);
-
- val = (unsigned char) XBOOL_VECTOR (array)->data[idxval / BITS_PER_CHAR];
- return (val & (1 << (idxval % BITS_PER_CHAR)) ? Qt : Qnil);
- }
- else if (CHAR_TABLE_P (array))
- {
- Lisp_Object val;
-
- if (idxval < 0)
- args_out_of_range (array, idx);
-#if 1
- if ((unsigned) idxval >= CHAR_TABLE_ORDINARY_SLOTS)
- args_out_of_range (array, idx);
- return val = XCHAR_TABLE (array)->contents[idxval];
-#else /* 0 */
- if ((unsigned) idxval < CHAR_TABLE_ORDINARY_SLOTS)
- val = XCHAR_TABLE (array)->data[idxval];
- else
- {
- int charset;
- unsigned char c1, c2;
- Lisp_Object val, temp;
-
- BREAKUP_NON_ASCII_CHAR (idxval, charset, c1, c2);
-
- try_parent_char_table:
- val = XCHAR_TABLE (array)->contents[charset];
- if (c1 == 0 || !CHAR_TABLE_P (val))
- return val;
-
- temp = XCHAR_TABLE (val)->contents[c1];
- if (NILP (temp))
- val = XCHAR_TABLE (val)->defalt;
- else
- val = temp;
-
- if (NILP (val) && !NILP (XCHAR_TABLE (array)->parent))
- {
- array = XCHAR_TABLE (array)->parent;
- goto try_parent_char_table;
-
- }
-
- if (c2 == 0 || !CHAR_TABLE_P (val))
- return val;
-
- temp = XCHAR_TABLE (val)->contents[c2];
- if (NILP (temp))
- val = XCHAR_TABLE (val)->defalt;
- else
- val = temp;
-
- if (NILP (val) && !NILP (XCHAR_TABLE (array)->parent))
- {
- array = XCHAR_TABLE (array)->parent;
- goto try_parent_char_table;
- }
-
- return val;
- }
-#endif /* 0 */
- }
- else
- {
- int size;
- if (VECTORP (array))
- size = XVECTOR (array)->size;
- else if (COMPILEDP (array))
- size = XVECTOR (array)->size & PSEUDOVECTOR_SIZE_MASK;
- else
- wrong_type_argument (Qarrayp, array);
-
- if (idxval < 0 || idxval >= size)
- args_out_of_range (array, idx);
- return XVECTOR (array)->contents[idxval];
- }
-}
-
-DEFUN ("aset", Faset, Saset, 3, 3, 0,
- "Store into the element of ARRAY at index IDX the value NEWELT.\n\
-ARRAY may be a vector or a string. IDX starts at 0.")
- (array, idx, newelt)
- register Lisp_Object array;
- Lisp_Object idx, newelt;
-{
- register int idxval;
-
- CHECK_NUMBER (idx, 1);
- idxval = XINT (idx);
- if (!VECTORP (array) && !STRINGP (array) && !BOOL_VECTOR_P (array)
- && ! CHAR_TABLE_P (array))
- array = wrong_type_argument (Qarrayp, array);
- CHECK_IMPURE (array);
-
- if (VECTORP (array))
- {
- if (idxval < 0 || idxval >= XVECTOR (array)->size)
- args_out_of_range (array, idx);
- XVECTOR (array)->contents[idxval] = newelt;
- }
- else if (BOOL_VECTOR_P (array))
- {
- int val;
-
- if (idxval < 0 || idxval >= XBOOL_VECTOR (array)->size)
- args_out_of_range (array, idx);
-
- val = (unsigned char) XBOOL_VECTOR (array)->data[idxval / BITS_PER_CHAR];
-
- if (! NILP (newelt))
- val |= 1 << (idxval % BITS_PER_CHAR);
- else
- val &= ~(1 << (idxval % BITS_PER_CHAR));
- XBOOL_VECTOR (array)->data[idxval / BITS_PER_CHAR] = val;
- }
- else if (CHAR_TABLE_P (array))
- {
- Lisp_Object val;
-
- if (idxval < 0)
- args_out_of_range (array, idx);
-#if 1
- if (idxval >= CHAR_TABLE_ORDINARY_SLOTS)
- args_out_of_range (array, idx);
- XCHAR_TABLE (array)->contents[idxval] = newelt;
- return newelt;
-#else /* 0 */
- if (idxval < CHAR_TABLE_ORDINARY_SLOTS)
- val = XCHAR_TABLE (array)->contents[idxval];
- else
- {
- int charset;
- unsigned char c1, c2;
- Lisp_Object val, val2;
-
- BREAKUP_NON_ASCII_CHAR (idxval, charset, c1, c2);
-
- if (c1 == 0)
- return XCHAR_TABLE (array)->contents[charset] = newelt;
-
- val = XCHAR_TABLE (array)->contents[charset];
- if (!CHAR_TABLE_P (val))
- XCHAR_TABLE (array)->contents[charset]
- = val = Fmake_char_table (Qnil);
-
- if (c2 == 0)
- return XCHAR_TABLE (val)->contents[c1] = newelt;
-
- val2 = XCHAR_TABLE (val)->contents[c2];
- if (!CHAR_TABLE_P (val2))
- XCHAR_TABLE (val)->contents[charset]
- = val2 = Fmake_char_table (Qnil);
-
- return XCHAR_TABLE (val2)->contents[c2] = newelt;
- }
-#endif /* 0 */
- }
- else
- {
- if (idxval < 0 || idxval >= XSTRING (array)->size)
- args_out_of_range (array, idx);
- CHECK_NUMBER (newelt, 2);
- XSTRING (array)->data[idxval] = XINT (newelt);
- }
-
- return newelt;
-}
-
-/* Arithmetic functions */
-
-enum comparison { equal, notequal, less, grtr, less_or_equal, grtr_or_equal };
-
-Lisp_Object
-arithcompare (num1, num2, comparison)
- Lisp_Object num1, num2;
- enum comparison comparison;
-{
- double f1, f2;
- int floatp = 0;
-
-#ifdef LISP_FLOAT_TYPE
- CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (num1, 0);
- CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (num2, 0);
-
- if (FLOATP (num1) || FLOATP (num2))
- {
- floatp = 1;
- f1 = (FLOATP (num1)) ? XFLOAT (num1)->data : XINT (num1);
- f2 = (FLOATP (num2)) ? XFLOAT (num2)->data : XINT (num2);
- }
-#else
- CHECK_NUMBER_COERCE_MARKER (num1, 0);
- CHECK_NUMBER_COERCE_MARKER (num2, 0);
-#endif /* LISP_FLOAT_TYPE */
-
- switch (comparison)
- {
- case equal:
- if (floatp ? f1 == f2 : XINT (num1) == XINT (num2))
- return Qt;
- return Qnil;
-
- case notequal:
- if (floatp ? f1 != f2 : XINT (num1) != XINT (num2))
- return Qt;
- return Qnil;
-
- case less:
- if (floatp ? f1 < f2 : XINT (num1) < XINT (num2))
- return Qt;
- return Qnil;
-
- case less_or_equal:
- if (floatp ? f1 <= f2 : XINT (num1) <= XINT (num2))
- return Qt;
- return Qnil;
-
- case grtr:
- if (floatp ? f1 > f2 : XINT (num1) > XINT (num2))
- return Qt;
- return Qnil;
-
- case grtr_or_equal:
- if (floatp ? f1 >= f2 : XINT (num1) >= XINT (num2))
- return Qt;
- return Qnil;
-
- default:
- abort ();
- }
-}
-
-DEFUN ("=", Feqlsign, Seqlsign, 2, 2, 0,
- "T if two args, both numbers or markers, are equal.")
- (num1, num2)
- register Lisp_Object num1, num2;
-{
- return arithcompare (num1, num2, equal);
-}
-
-DEFUN ("<", Flss, Slss, 2, 2, 0,
- "T if first arg is less than second arg. Both must be numbers or markers.")
- (num1, num2)
- register Lisp_Object num1, num2;
-{
- return arithcompare (num1, num2, less);
-}
-
-DEFUN (">", Fgtr, Sgtr, 2, 2, 0,
- "T if first arg is greater than second arg. Both must be numbers or markers.")
- (num1, num2)
- register Lisp_Object num1, num2;
-{
- return arithcompare (num1, num2, grtr);
-}
-
-DEFUN ("<=", Fleq, Sleq, 2, 2, 0,
- "T if first arg is less than or equal to second arg.\n\
-Both must be numbers or markers.")
- (num1, num2)
- register Lisp_Object num1, num2;
-{
- return arithcompare (num1, num2, less_or_equal);
-}
-
-DEFUN (">=", Fgeq, Sgeq, 2, 2, 0,
- "T if first arg is greater than or equal to second arg.\n\
-Both must be numbers or markers.")
- (num1, num2)
- register Lisp_Object num1, num2;
-{
- return arithcompare (num1, num2, grtr_or_equal);
-}
-
-DEFUN ("/=", Fneq, Sneq, 2, 2, 0,
- "T if first arg is not equal to second arg. Both must be numbers or markers.")
- (num1, num2)
- register Lisp_Object num1, num2;
-{
- return arithcompare (num1, num2, notequal);
-}
-
-DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0, "T if NUMBER is zero.")
- (number)
- register Lisp_Object number;
-{
-#ifdef LISP_FLOAT_TYPE
- CHECK_NUMBER_OR_FLOAT (number, 0);
-
- if (FLOATP (number))
- {
- if (XFLOAT(number)->data == 0.0)
- return Qt;
- return Qnil;
- }
-#else
- CHECK_NUMBER (number, 0);
-#endif /* LISP_FLOAT_TYPE */
-
- if (!XINT (number))
- return Qt;
- return Qnil;
-}
-
-/* Convert between long values and pairs of Lisp integers. */
-
-Lisp_Object
-long_to_cons (i)
- unsigned long i;
-{
- unsigned int top = i >> 16;
- unsigned int bot = i & 0xFFFF;
- if (top == 0)
- return make_number (bot);
- if (top == (unsigned long)-1 >> 16)
- return Fcons (make_number (-1), make_number (bot));
- return Fcons (make_number (top), make_number (bot));
-}
-
-unsigned long
-cons_to_long (c)
- Lisp_Object c;
-{
- Lisp_Object top, bot;
- if (INTEGERP (c))
- return XINT (c);
- top = XCONS (c)->car;
- bot = XCONS (c)->cdr;
- if (CONSP (bot))
- bot = XCONS (bot)->car;
- return ((XINT (top) << 16) | XINT (bot));
-}
-
-DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0,
- "Convert NUMBER to a string by printing it in decimal.\n\
-Uses a minus sign if negative.\n\
-NUMBER may be an integer or a floating point number.")
- (number)
- Lisp_Object number;
-{
- char buffer[VALBITS];
-
-#ifndef LISP_FLOAT_TYPE
- CHECK_NUMBER (number, 0);
-#else
- CHECK_NUMBER_OR_FLOAT (number, 0);
-
- if (FLOATP (number))
- {
- char pigbuf[350]; /* see comments in float_to_string */
-
- float_to_string (pigbuf, XFLOAT(number)->data);
- return build_string (pigbuf);
- }
-#endif /* LISP_FLOAT_TYPE */
-
- if (sizeof (int) == sizeof (EMACS_INT))
- sprintf (buffer, "%d", XINT (number));
- else if (sizeof (long) == sizeof (EMACS_INT))
- sprintf (buffer, "%ld", XINT (number));
- else
- abort ();
- return build_string (buffer);
-}
-
-DEFUN ("string-to-number", Fstring_to_number, Sstring_to_number, 1, 1, 0,
- "Convert STRING to a number by parsing it as a decimal number.\n\
-This parses both integers and floating point numbers.\n\
-It ignores leading spaces and tabs.")
- (string)
- register Lisp_Object string;
-{
- Lisp_Object value;
- unsigned char *p;
-
- CHECK_STRING (string, 0);
-
- p = XSTRING (string)->data;
-
- /* Skip any whitespace at the front of the number. Some versions of
- atoi do this anyway, so we might as well make Emacs lisp consistent. */
- while (*p == ' ' || *p == '\t')
- p++;
-
-#ifdef LISP_FLOAT_TYPE
- if (isfloat_string (p))
- return make_float (atof (p));
-#endif /* LISP_FLOAT_TYPE */
-
- if (sizeof (int) == sizeof (EMACS_INT))
- XSETINT (value, atoi (p));
- else if (sizeof (long) == sizeof (EMACS_INT))
- XSETINT (value, atol (p));
- else
- abort ();
- return value;
-}
-
-enum arithop
- { Aadd, Asub, Amult, Adiv, Alogand, Alogior, Alogxor, Amax, Amin };
-
-extern Lisp_Object float_arith_driver ();
-extern Lisp_Object fmod_float ();
-
-Lisp_Object
-arith_driver (code, nargs, args)
- enum arithop code;
- int nargs;
- register Lisp_Object *args;
-{
- register Lisp_Object val;
- register int argnum;
- register EMACS_INT accum;
- register EMACS_INT next;
-
- switch (SWITCH_ENUM_CAST (code))
- {
- 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_... */
-#ifdef LISP_FLOAT_TYPE
- CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (val, argnum);
-
- if (FLOATP (val)) /* time to do serious math */
- return (float_arith_driver ((double) accum, argnum, code,
- nargs, args));
-#else
- CHECK_NUMBER_COERCE_MARKER (val, argnum);
-#endif /* LISP_FLOAT_TYPE */
- args[argnum] = val; /* runs into a compiler bug. */
- next = XINT (args[argnum]);
- switch (SWITCH_ENUM_CAST (code))
- {
- 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
- {
- if (next == 0)
- 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;
- }
- }
-
- XSETINT (val, accum);
- return val;
-}
-
-#ifdef LISP_FLOAT_TYPE
-
-#undef isnan
-#define isnan(x) ((x) != (x))
-
-Lisp_Object
-float_arith_driver (accum, argnum, code, nargs, args)
- double accum;
- register int argnum;
- enum arithop code;
- int nargs;
- register Lisp_Object *args;
-{
- register Lisp_Object val;
- double next;
-
- for (; argnum < nargs; argnum++)
- {
- val = args[argnum]; /* using args[argnum] as argument to CHECK_NUMBER_... */
- CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (val, argnum);
-
- if (FLOATP (val))
- {
- next = XFLOAT (val)->data;
- }
- else
- {
- args[argnum] = val; /* runs into a compiler bug. */
- next = XINT (args[argnum]);
- }
- switch (SWITCH_ENUM_CAST (code))
- {
- 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
- {
- if (! IEEE_FLOATING_POINT && next == 0)
- Fsignal (Qarith_error, Qnil);
- accum /= next;
- }
- break;
- case Alogand:
- case Alogior:
- case Alogxor:
- return wrong_type_argument (Qinteger_or_marker_p, val);
- case Amax:
- if (!argnum || isnan (next) || next > accum)
- accum = next;
- break;
- case Amin:
- if (!argnum || isnan (next) || next < accum)
- accum = next;
- break;
- }
- }
-
- return make_float (accum);
-}
-#endif /* LISP_FLOAT_TYPE */
-
-DEFUN ("+", Fplus, Splus, 0, MANY, 0,
- "Return sum of any number of arguments, which are numbers or markers.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
- return arith_driver (Aadd, nargs, args);
-}
-
-DEFUN ("-", Fminus, Sminus, 0, MANY, 0,
- "Negate number or subtract numbers or markers.\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 arguments, which are numbers or markers.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
- return arith_driver (Amult, nargs, args);
-}
-
-DEFUN ("/", Fquo, Squo, 2, MANY, 0,
- "Returns first argument divided by all the remaining arguments.\n\
-The arguments must be numbers or markers.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
- return arith_driver (Adiv, nargs, args);
-}
-
-DEFUN ("%", Frem, Srem, 2, 2, 0,
- "Returns remainder of X divided by Y.\n\
-Both must be integers or markers.")
- (x, y)
- register Lisp_Object x, y;
-{
- Lisp_Object val;
-
- CHECK_NUMBER_COERCE_MARKER (x, 0);
- CHECK_NUMBER_COERCE_MARKER (y, 1);
-
- if (XFASTINT (y) == 0)
- Fsignal (Qarith_error, Qnil);
-
- XSETINT (val, XINT (x) % XINT (y));
- return val;
-}
-
-#ifndef HAVE_FMOD
-double
-fmod (f1, f2)
- double f1, f2;
-{
- if (f2 < 0.0)
- f2 = -f2;
- return (f1 - f2 * floor (f1/f2));
-}
-#endif /* ! HAVE_FMOD */
-
-DEFUN ("mod", Fmod, Smod, 2, 2, 0,
- "Returns X modulo Y.\n\
-The result falls between zero (inclusive) and Y (exclusive).\n\
-Both X and Y must be numbers or markers.")
- (x, y)
- register Lisp_Object x, y;
-{
- Lisp_Object val;
- EMACS_INT i1, i2;
-
-#ifdef LISP_FLOAT_TYPE
- CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (x, 0);
- CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (y, 1);
-
- if (FLOATP (x) || FLOATP (y))
- return fmod_float (x, y);
-
-#else /* not LISP_FLOAT_TYPE */
- CHECK_NUMBER_COERCE_MARKER (x, 0);
- CHECK_NUMBER_COERCE_MARKER (y, 1);
-#endif /* not LISP_FLOAT_TYPE */
-
- i1 = XINT (x);
- i2 = XINT (y);
-
- if (i2 == 0)
- Fsignal (Qarith_error, Qnil);
-
- i1 %= i2;
-
- /* If the "remainder" comes out with the wrong sign, fix it. */
- if (i2 < 0 ? i1 > 0 : i1 < 0)
- i1 += i2;
-
- XSETINT (val, i1);
- return val;
-}
-
-DEFUN ("max", Fmax, Smax, 1, MANY, 0,
- "Return largest of all the arguments (which must be numbers or markers).\n\
-The value is always a number; markers are converted to 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 or markers).\n\
-The value is always a number; markers are converted to 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.\n\
-Arguments may be integers, or markers converted to integers.")
- (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.\n\
-Arguments may be integers, or markers converted to integers.")
- (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.\n\
-Arguments may be integers, or markers converted to integers.")
- (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.")
- (value, count)
- register Lisp_Object value, count;
-{
- register Lisp_Object val;
-
- CHECK_NUMBER (value, 0);
- CHECK_NUMBER (count, 1);
-
- if (XINT (count) > 0)
- XSETINT (val, XINT (value) << XFASTINT (count));
- else
- XSETINT (val, XINT (value) >> -XINT (count));
- 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.")
- (value, count)
- register Lisp_Object value, count;
-{
- register Lisp_Object val;
-
- CHECK_NUMBER (value, 0);
- CHECK_NUMBER (count, 1);
-
- if (XINT (count) > 0)
- XSETINT (val, (EMACS_UINT) XUINT (value) << XFASTINT (count));
- else
- XSETINT (val, (EMACS_UINT) XUINT (value) >> -XINT (count));
- return val;
-}
-
-DEFUN ("1+", Fadd1, Sadd1, 1, 1, 0,
- "Return NUMBER plus one. NUMBER may be a number or a marker.\n\
-Markers are converted to integers.")
- (number)
- register Lisp_Object number;
-{
-#ifdef LISP_FLOAT_TYPE
- CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (number, 0);
-
- if (FLOATP (number))
- return (make_float (1.0 + XFLOAT (number)->data));
-#else
- CHECK_NUMBER_COERCE_MARKER (number, 0);
-#endif /* LISP_FLOAT_TYPE */
-
- XSETINT (number, XINT (number) + 1);
- return number;
-}
-
-DEFUN ("1-", Fsub1, Ssub1, 1, 1, 0,
- "Return NUMBER minus one. NUMBER may be a number or a marker.\n\
-Markers are converted to integers.")
- (number)
- register Lisp_Object number;
-{
-#ifdef LISP_FLOAT_TYPE
- CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (number, 0);
-
- if (FLOATP (number))
- return (make_float (-1.0 + XFLOAT (number)->data));
-#else
- CHECK_NUMBER_COERCE_MARKER (number, 0);
-#endif /* LISP_FLOAT_TYPE */
-
- XSETINT (number, XINT (number) - 1);
- return number;
-}
-
-DEFUN ("lognot", Flognot, Slognot, 1, 1, 0,
- "Return the bitwise complement of NUMBER. NUMBER must be an integer.")
- (number)
- register Lisp_Object number;
-{
- CHECK_NUMBER (number, 0);
- XSETINT (number, ~XINT (number));
- return number;
-}
-
-void
-syms_of_data ()
-{
- Lisp_Object error_tail, arith_tail;
-
- 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");
- Qcyclic_function_indirection = intern ("cyclic-function-indirection");
- 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");
- Qmark_inactive = intern ("mark-inactive");
-
- Qlistp = intern ("listp");
- Qconsp = intern ("consp");
- Qsymbolp = intern ("symbolp");
- Qintegerp = intern ("integerp");
- Qnatnump = intern ("natnump");
- Qwholenump = intern ("wholenump");
- 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");
- Qbuffer_or_string_p = intern ("buffer-or-string-p");
- Qinteger_or_marker_p = intern ("integer-or-marker-p");
- Qboundp = intern ("boundp");
- Qfboundp = intern ("fboundp");
-
-#ifdef LISP_FLOAT_TYPE
- Qfloatp = intern ("floatp");
- Qnumberp = intern ("numberp");
- Qnumber_or_marker_p = intern ("number-or-marker-p");
-#endif /* LISP_FLOAT_TYPE */
-
- Qchar_table_p = intern ("char-table-p");
- Qvector_or_char_table_p = intern ("vector-or-char-table-p");
-
- Qcdr = intern ("cdr");
-
- /* Handle automatic advice activation */
- Qad_advice_info = intern ("ad-advice-info");
- Qad_activate = intern ("ad-activate");
-
- error_tail = Fcons (Qerror, Qnil);
-
- /* ERROR is used as a signaler for random errors for which nothing else is right */
-
- Fput (Qerror, Qerror_conditions,
- error_tail);
- 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, error_tail));
- Fput (Qwrong_type_argument, Qerror_message,
- build_string ("Wrong type argument"));
-
- Fput (Qargs_out_of_range, Qerror_conditions,
- Fcons (Qargs_out_of_range, error_tail));
- Fput (Qargs_out_of_range, Qerror_message,
- build_string ("Args out of range"));
-
- Fput (Qvoid_function, Qerror_conditions,
- Fcons (Qvoid_function, error_tail));
- Fput (Qvoid_function, Qerror_message,
- build_string ("Symbol's function definition is void"));
-
- Fput (Qcyclic_function_indirection, Qerror_conditions,
- Fcons (Qcyclic_function_indirection, error_tail));
- Fput (Qcyclic_function_indirection, Qerror_message,
- build_string ("Symbol's chain of function indirections contains a loop"));
-
- Fput (Qvoid_variable, Qerror_conditions,
- Fcons (Qvoid_variable, error_tail));
- Fput (Qvoid_variable, Qerror_message,
- build_string ("Symbol's value as variable is void"));
-
- Fput (Qsetting_constant, Qerror_conditions,
- Fcons (Qsetting_constant, error_tail));
- Fput (Qsetting_constant, Qerror_message,
- build_string ("Attempt to set a constant symbol"));
-
- Fput (Qinvalid_read_syntax, Qerror_conditions,
- Fcons (Qinvalid_read_syntax, error_tail));
- Fput (Qinvalid_read_syntax, Qerror_message,
- build_string ("Invalid read syntax"));
-
- Fput (Qinvalid_function, Qerror_conditions,
- Fcons (Qinvalid_function, error_tail));
- Fput (Qinvalid_function, Qerror_message,
- build_string ("Invalid function"));
-
- Fput (Qwrong_number_of_arguments, Qerror_conditions,
- Fcons (Qwrong_number_of_arguments, error_tail));
- Fput (Qwrong_number_of_arguments, Qerror_message,
- build_string ("Wrong number of arguments"));
-
- Fput (Qno_catch, Qerror_conditions,
- Fcons (Qno_catch, error_tail));
- Fput (Qno_catch, Qerror_message,
- build_string ("No catch for tag"));
-
- Fput (Qend_of_file, Qerror_conditions,
- Fcons (Qend_of_file, error_tail));
- Fput (Qend_of_file, Qerror_message,
- build_string ("End of file during parsing"));
-
- arith_tail = Fcons (Qarith_error, error_tail);
- Fput (Qarith_error, Qerror_conditions,
- arith_tail);
- Fput (Qarith_error, Qerror_message,
- build_string ("Arithmetic error"));
-
- Fput (Qbeginning_of_buffer, Qerror_conditions,
- Fcons (Qbeginning_of_buffer, error_tail));
- Fput (Qbeginning_of_buffer, Qerror_message,
- build_string ("Beginning of buffer"));
-
- Fput (Qend_of_buffer, Qerror_conditions,
- Fcons (Qend_of_buffer, error_tail));
- Fput (Qend_of_buffer, Qerror_message,
- build_string ("End of buffer"));
-
- Fput (Qbuffer_read_only, Qerror_conditions,
- Fcons (Qbuffer_read_only, error_tail));
- Fput (Qbuffer_read_only, Qerror_message,
- build_string ("Buffer is read-only"));
-
-#ifdef LISP_FLOAT_TYPE
- Qrange_error = intern ("range-error");
- Qdomain_error = intern ("domain-error");
- Qsingularity_error = intern ("singularity-error");
- Qoverflow_error = intern ("overflow-error");
- Qunderflow_error = intern ("underflow-error");
-
- Fput (Qdomain_error, Qerror_conditions,
- Fcons (Qdomain_error, arith_tail));
- Fput (Qdomain_error, Qerror_message,
- build_string ("Arithmetic domain error"));
-
- Fput (Qrange_error, Qerror_conditions,
- Fcons (Qrange_error, arith_tail));
- Fput (Qrange_error, Qerror_message,
- build_string ("Arithmetic range error"));
-
- Fput (Qsingularity_error, Qerror_conditions,
- Fcons (Qsingularity_error, Fcons (Qdomain_error, arith_tail)));
- Fput (Qsingularity_error, Qerror_message,
- build_string ("Arithmetic singularity error"));
-
- Fput (Qoverflow_error, Qerror_conditions,
- Fcons (Qoverflow_error, Fcons (Qdomain_error, arith_tail)));
- Fput (Qoverflow_error, Qerror_message,
- build_string ("Arithmetic overflow error"));
-
- Fput (Qunderflow_error, Qerror_conditions,
- Fcons (Qunderflow_error, Fcons (Qdomain_error, arith_tail)));
- Fput (Qunderflow_error, Qerror_message,
- build_string ("Arithmetic underflow error"));
-
- staticpro (&Qrange_error);
- staticpro (&Qdomain_error);
- staticpro (&Qsingularity_error);
- staticpro (&Qoverflow_error);
- staticpro (&Qunderflow_error);
-#endif /* LISP_FLOAT_TYPE */
-
- 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 (&Qcyclic_function_indirection);
- 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 (&Qmark_inactive);
-
- staticpro (&Qlistp);
- staticpro (&Qconsp);
- staticpro (&Qsymbolp);
- staticpro (&Qintegerp);
- staticpro (&Qnatnump);
- staticpro (&Qwholenump);
- staticpro (&Qstringp);
- staticpro (&Qarrayp);
- staticpro (&Qsequencep);
- staticpro (&Qbufferp);
- staticpro (&Qvectorp);
- staticpro (&Qchar_or_string_p);
- staticpro (&Qmarkerp);
- staticpro (&Qbuffer_or_string_p);
- staticpro (&Qinteger_or_marker_p);
-#ifdef LISP_FLOAT_TYPE
- staticpro (&Qfloatp);
- staticpro (&Qnumberp);
- staticpro (&Qnumber_or_marker_p);
-#endif /* LISP_FLOAT_TYPE */
- staticpro (&Qchar_table_p);
- staticpro (&Qvector_or_char_table_p);
-
- staticpro (&Qboundp);
- staticpro (&Qfboundp);
- staticpro (&Qcdr);
- staticpro (&Qad_advice_info);
- staticpro (&Qad_activate);
-
- /* Types that type-of returns. */
- Qinteger = intern ("integer");
- Qsymbol = intern ("symbol");
- Qstring = intern ("string");
- Qcons = intern ("cons");
- Qmarker = intern ("marker");
- Qoverlay = intern ("overlay");
- Qfloat = intern ("float");
- Qwindow_configuration = intern ("window-configuration");
- Qprocess = intern ("process");
- Qwindow = intern ("window");
- /* Qsubr = intern ("subr"); */
- Qcompiled_function = intern ("compiled-function");
- Qbuffer = intern ("buffer");
- Qframe = intern ("frame");
- Qvector = intern ("vector");
- Qchar_table = intern ("char-table");
- Qbool_vector = intern ("bool-vector");
-
- staticpro (&Qinteger);
- staticpro (&Qsymbol);
- staticpro (&Qstring);
- staticpro (&Qcons);
- staticpro (&Qmarker);
- staticpro (&Qoverlay);
- staticpro (&Qfloat);
- staticpro (&Qwindow_configuration);
- staticpro (&Qprocess);
- staticpro (&Qwindow);
- /* staticpro (&Qsubr); */
- staticpro (&Qcompiled_function);
- staticpro (&Qbuffer);
- staticpro (&Qframe);
- staticpro (&Qvector);
- staticpro (&Qchar_table);
- staticpro (&Qbool_vector);
-
- defsubr (&Seq);
- defsubr (&Snull);
- defsubr (&Stype_of);
- defsubr (&Slistp);
- defsubr (&Snlistp);
- defsubr (&Sconsp);
- defsubr (&Satom);
- defsubr (&Sintegerp);
- defsubr (&Sinteger_or_marker_p);
- defsubr (&Snumberp);
- defsubr (&Snumber_or_marker_p);
-#ifdef LISP_FLOAT_TYPE
- defsubr (&Sfloatp);
-#endif /* LISP_FLOAT_TYPE */
- defsubr (&Snatnump);
- defsubr (&Ssymbolp);
- defsubr (&Sstringp);
- defsubr (&Svectorp);
- defsubr (&Schar_table_p);
- defsubr (&Svector_or_char_table_p);
- defsubr (&Sbool_vector_p);
- defsubr (&Sarrayp);
- defsubr (&Ssequencep);
- defsubr (&Sbufferp);
- defsubr (&Smarkerp);
- defsubr (&Ssubrp);
- defsubr (&Sbyte_code_function_p);
- defsubr (&Schar_or_string_p);
- defsubr (&Scar);
- defsubr (&Scdr);
- defsubr (&Scar_safe);
- defsubr (&Scdr_safe);
- defsubr (&Ssetcar);
- defsubr (&Ssetcdr);
- defsubr (&Ssymbol_function);
- defsubr (&Sindirect_function);
- defsubr (&Ssymbol_plist);
- defsubr (&Ssymbol_name);
- defsubr (&Smakunbound);
- defsubr (&Sfmakunbound);
- defsubr (&Sboundp);
- defsubr (&Sfboundp);
- defsubr (&Sfset);
- defsubr (&Sdefalias);
- defsubr (&Ssetplist);
- defsubr (&Ssymbol_value);
- defsubr (&Sset);
- defsubr (&Sdefault_boundp);
- defsubr (&Sdefault_value);
- defsubr (&Sset_default);
- defsubr (&Ssetq_default);
- defsubr (&Smake_variable_buffer_local);
- defsubr (&Smake_local_variable);
- defsubr (&Skill_local_variable);
- defsubr (&Slocal_variable_p);
- defsubr (&Slocal_variable_if_set_p);
- defsubr (&Saref);
- defsubr (&Saset);
- defsubr (&Snumber_to_string);
- defsubr (&Sstring_to_number);
- 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 (&Smod);
- defsubr (&Smax);
- defsubr (&Smin);
- defsubr (&Slogand);
- defsubr (&Slogior);
- defsubr (&Slogxor);
- defsubr (&Slsh);
- defsubr (&Sash);
- defsubr (&Sadd1);
- defsubr (&Ssub1);
- defsubr (&Slognot);
-
- XSYMBOL (Qwholenump)->function = XSYMBOL (Qnatnump)->function;
-}
-
-SIGTYPE
-arith_error (signo)
- int signo;
-{
-#if defined(USG) && !defined(POSIX_SIGNALS)
- /* 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 */
-
- 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/dired.c b/src/dired.c
deleted file mode 100644
index 844c00687a2..00000000000
--- a/src/dired.c
+++ /dev/null
@@ -1,730 +0,0 @@
-/* Lisp functions for making directory listings.
- Copyright (C) 1985, 1986, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef VMS
-#include <string.h>
-#include <rms.h>
-#include <rmsdef.h>
-#endif
-
-/* The d_nameln member of a struct dirent includes the '\0' character
- on some systems, but not on others. What's worse, you can't tell
- at compile-time which one it will be, since it really depends on
- the sort of system providing the filesystem you're reading from,
- not the system you are running on. Paul Eggert
- <eggert@bi.twinsun.com> says this occurs when Emacs is running on a
- SunOS 4.1.2 host, reading a directory that is remote-mounted from a
- Solaris 2.1 host and is in a native Solaris 2.1 filesystem.
-
- Since applying strlen to the name always works, we'll just do that. */
-#define NAMLEN(p) strlen (p->d_name)
-
-#ifdef SYSV_SYSTEM_DIR
-
-#include <dirent.h>
-#define DIRENTRY struct dirent
-
-#else /* not SYSV_SYSTEM_DIR */
-
-#ifdef NONSYSTEM_DIR_LIBRARY
-#include "ndir.h"
-#else /* not NONSYSTEM_DIR_LIBRARY */
-#ifdef MSDOS
-#include <dirent.h>
-#else
-#include <sys/dir.h>
-#endif
-#endif /* not NONSYSTEM_DIR_LIBRARY */
-
-#ifndef MSDOS
-#define DIRENTRY struct direct
-
-extern DIR *opendir ();
-extern struct direct *readdir ();
-
-#endif /* not MSDOS */
-#endif /* not SYSV_SYSTEM_DIR */
-
-#ifdef MSDOS
-#define DIRENTRY_NONEMPTY(p) ((p)->d_name[0] != 0)
-#else
-#define DIRENTRY_NONEMPTY(p) ((p)->d_ino)
-#endif
-
-#include "lisp.h"
-#include "buffer.h"
-#include "commands.h"
-
-#include "regex.h"
-
-/* Returns a search buffer, with a fastmap allocated and ready to go. */
-extern struct re_pattern_buffer *compile_pattern ();
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
-/* if system does not have symbolic links, it does not have lstat.
- In that case, use ordinary stat instead. */
-
-#ifndef S_IFLNK
-#define lstat stat
-#endif
-
-extern int completion_ignore_case;
-extern Lisp_Object Vcompletion_regexp_list;
-
-Lisp_Object Vcompletion_ignored_extensions;
-Lisp_Object Qcompletion_ignore_case;
-Lisp_Object Qdirectory_files;
-Lisp_Object Qfile_name_completion;
-Lisp_Object Qfile_name_all_completions;
-Lisp_Object Qfile_attributes;
-
-DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
- "Return a list of names of files in DIRECTORY.\n\
-There are three optional arguments:\n\
-If FULL is non-nil, return absolute file names. Otherwise return names\n\
- that are relative to the specified directory.\n\
-If MATCH is non-nil, mention only file names that match the regexp MATCH.\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.")
- (directory, full, match, nosort)
- Lisp_Object directory, full, match, nosort;
-{
- DIR *d;
- int dirnamelen;
- Lisp_Object list, name, dirfilename;
- Lisp_Object handler;
- struct re_pattern_buffer *bufp;
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (directory, Qdirectory_files);
- if (!NILP (handler))
- {
- Lisp_Object args[6];
-
- args[0] = handler;
- args[1] = Qdirectory_files;
- args[2] = directory;
- args[3] = full;
- args[4] = match;
- args[5] = nosort;
- return Ffuncall (6, args);
- }
-
- {
- struct gcpro gcpro1, gcpro2;
-
- /* Because of file name handlers, these functions might call
- Ffuncall, and cause a GC. */
- GCPRO1 (match);
- directory = Fexpand_file_name (directory, Qnil);
- UNGCPRO;
- GCPRO2 (match, directory);
- dirfilename = Fdirectory_file_name (directory);
- UNGCPRO;
- }
-
- if (!NILP (match))
- {
- CHECK_STRING (match, 3);
-
- /* MATCH might be a flawed regular expression. Rather than
- catching and signaling our own errors, we just call
- compile_pattern to do the work for us. */
-#ifdef VMS
- bufp = compile_pattern (match, 0,
- buffer_defaults.downcase_table->contents, 0);
-#else
- bufp = compile_pattern (match, 0, 0, 0);
-#endif
- }
-
- /* Now *bufp is the compiled form of MATCH; don't call anything
- which might compile a new regexp until we're done with the loop! */
-
- /* Do this opendir after anything which might signal an error; if
- an error is signaled while the directory stream is open, we
- have to make sure it gets closed, and setting up an
- unwind_protect to do so would be a pain. */
- d = opendir (XSTRING (dirfilename)->data);
- if (! d)
- report_file_error ("Opening directory", Fcons (directory, Qnil));
-
- list = Qnil;
- dirnamelen = XSTRING (directory)->size;
-
- /* Loop reading blocks */
- while (1)
- {
- DIRENTRY *dp = readdir (d);
- int len;
-
- if (!dp) break;
- len = NAMLEN (dp);
- if (DIRENTRY_NONEMPTY (dp))
- {
- if (NILP (match)
- || (0 <= re_search (bufp, dp->d_name, len, 0, len, 0)))
- {
- if (!NILP (full))
- {
- int afterdirindex = dirnamelen;
- int total = len + dirnamelen;
- int needsep = 0;
-
- /* Decide whether we need to add a directory separator. */
-#ifndef VMS
- if (dirnamelen == 0
- || !IS_ANY_SEP (XSTRING (directory)->data[dirnamelen - 1]))
- needsep = 1;
-#endif /* VMS */
-
- name = make_uninit_string (total + needsep);
- bcopy (XSTRING (directory)->data, XSTRING (name)->data,
- dirnamelen);
- if (needsep)
- XSTRING (name)->data[afterdirindex++] = DIRECTORY_SEP;
- bcopy (dp->d_name,
- XSTRING (name)->data + afterdirindex, len);
- }
- else
- name = make_string (dp->d_name, len);
- list = Fcons (name, list);
- }
- }
- }
- closedir (d);
- if (!NILP (nosort))
- return list;
- return Fsort (Fnreverse (list), Qstring_lessp);
-}
-
-Lisp_Object file_name_completion ();
-
-DEFUN ("file-name-completion", Ffile_name_completion, Sfile_name_completion,
- 2, 2, 0,
- "Complete file name FILE in directory DIRECTORY.\n\
-Returns the longest string\n\
-common to all file names in DIRECTORY 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, directory)
- Lisp_Object file, directory;
-{
- Lisp_Object handler;
-
- /* If the directory name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (directory, Qfile_name_completion);
- if (!NILP (handler))
- return call3 (handler, Qfile_name_completion, file, directory);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (file, Qfile_name_completion);
- if (!NILP (handler))
- return call3 (handler, Qfile_name_completion, file, directory);
-
- return file_name_completion (file, directory, 0, 0);
-}
-
-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 DIRECTORY.\n\
-These are all file names in directory DIRECTORY which begin with FILE.")
- (file, directory)
- Lisp_Object file, directory;
-{
- Lisp_Object handler;
-
- /* If the directory name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (directory, Qfile_name_all_completions);
- if (!NILP (handler))
- return call3 (handler, Qfile_name_all_completions, file, directory);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (file, Qfile_name_all_completions);
- if (!NILP (handler))
- return call3 (handler, Qfile_name_all_completions, file, directory);
-
- return file_name_completion (file, directory, 1, 0);
-}
-
-Lisp_Object
-file_name_completion (file, dirname, all_flag, ver_flag)
- Lisp_Object file, dirname;
- int all_flag, ver_flag;
-{
- DIR *d;
- DIRENTRY *dp;
- int bestmatchsize, skip;
- register int compare, matchsize;
- unsigned char *p1, *p2;
- int matchcount = 0;
- Lisp_Object bestmatch, tem, elt, name;
- struct stat st;
- int directoryp;
- int passcount;
- int count = specpdl_ptr - specpdl;
- struct gcpro gcpro1, gcpro2, gcpro3;
-
-#ifdef VMS
- extern DIRENTRY * readdirver ();
-
- DIRENTRY *((* readfunc) ());
-
- /* Filename completion on VMS ignores case, since VMS filesys does. */
- specbind (Qcompletion_ignore_case, Qt);
-
- readfunc = readdir;
- if (ver_flag)
- readfunc = readdirver;
- file = Fupcase (file);
-#else /* not VMS */
- CHECK_STRING (file, 0);
-#endif /* not VMS */
-
-#ifdef FILE_SYSTEM_CASE
- file = FILE_SYSTEM_CASE (file);
-#endif
- bestmatch = Qnil;
- GCPRO3 (file, dirname, bestmatch);
- dirname = Fexpand_file_name (dirname, Qnil);
-
- /* With 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.** */
-
- for (passcount = !!all_flag; NILP (bestmatch) && passcount < 2; passcount++)
- {
- if (!(d = opendir (XSTRING (Fdirectory_file_name (dirname))->data)))
- report_file_error ("Opening directory", Fcons (dirname, Qnil));
-
- /* Loop reading blocks */
- /* (att3b compiler bug requires do a null comparison this way) */
- while (1)
- {
- DIRENTRY *dp;
- int len;
-
-#ifdef VMS
- dp = (*readfunc) (d);
-#else
- dp = readdir (d);
-#endif
- if (!dp) break;
-
- len = NAMLEN (dp);
-
- if (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
- goto quit;
- if (! DIRENTRY_NONEMPTY (dp)
- || len < XSTRING (file)->size
- || 0 <= scmp (dp->d_name, XSTRING (file)->data,
- XSTRING (file)->size))
- continue;
-
- if (file_name_completion_stat (dirname, dp, &st) < 0)
- continue;
-
- directoryp = ((st.st_mode & S_IFMT) == S_IFDIR);
- tem = Qnil;
- if (directoryp)
- {
-#ifndef TRIVIAL_DIRECTORY_ENTRY
-#define TRIVIAL_DIRECTORY_ENTRY(n) (!strcmp (n, ".") || !strcmp (n, ".."))
-#endif
- /* "." and ".." are never interesting as completions, but are
- actually in the way in a directory contains only one file. */
- if (!passcount && TRIVIAL_DIRECTORY_ENTRY (dp->d_name))
- continue;
- }
- else
- {
- /* Compare extensions-to-be-ignored against end of this file name */
- /* if name is not an exact match against specified string */
- if (!passcount && len > XSTRING (file)->size)
- /* and exit this for loop if a match is found */
- for (tem = Vcompletion_ignored_extensions;
- CONSP (tem); tem = XCONS (tem)->cdr)
- {
- elt = XCONS (tem)->car;
- if (!STRINGP (elt)) continue;
- skip = len - XSTRING (elt)->size;
- if (skip < 0) continue;
-
- if (0 <= scmp (dp->d_name + skip,
- XSTRING (elt)->data,
- XSTRING (elt)->size))
- continue;
- break;
- }
- }
-
- /* If an ignored-extensions match was found,
- don't process this name as a completion. */
- if (!passcount && CONSP (tem))
- continue;
-
- if (!passcount)
- {
- Lisp_Object regexps;
- Lisp_Object zero;
- XSETFASTINT (zero, 0);
-
- /* Ignore this element if it fails to match all the regexps. */
- for (regexps = Vcompletion_regexp_list; CONSP (regexps);
- regexps = XCONS (regexps)->cdr)
- {
- tem = Fstring_match (XCONS (regexps)->car, elt, zero);
- if (NILP (tem))
- break;
- }
- if (CONSP (regexps))
- continue;
- }
-
- /* Update computation of how much all possible completions match */
-
- matchcount++;
-
- if (all_flag || NILP (bestmatch))
- {
- /* This is a possible completion */
- if (directoryp)
- {
- /* This completion is a directory; make it end with '/' */
- name = Ffile_name_as_directory (make_string (dp->d_name, len));
- }
- else
- name = make_string (dp->d_name, len);
- if (all_flag)
- {
- bestmatch = Fcons (name, bestmatch);
- }
- else
- {
- bestmatch = name;
- bestmatchsize = XSTRING (name)->size;
- }
- }
- else
- {
- compare = min (bestmatchsize, len);
- p1 = XSTRING (bestmatch)->data;
- p2 = (unsigned char *) dp->d_name;
- 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. */
- /* This tests that the current file is an exact match
- but BESTMATCH is not (it is too long). */
- if ((matchsize == len
- && matchsize + !!directoryp
- < XSTRING (bestmatch)->size)
- ||
- /* If there is no exact match ignoring case,
- prefer a match that does not change the case
- of the input. */
- /* If there is more than one exact match aside from
- case, and one of them is exact including case,
- prefer that one. */
- /* This == checks that, of current file and BESTMATCH,
- either both or neither are exact. */
- (((matchsize == len)
- ==
- (matchsize + !!directoryp
- == XSTRING (bestmatch)->size))
- && !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
- && compare == matchsize
- && bestmatchsize > matchsize
- && IS_ANY_SEP (p1[matchsize]))
- matchsize++;
- bestmatchsize = matchsize;
- }
- }
- closedir (d);
- }
-
- UNGCPRO;
- bestmatch = unbind_to (count, bestmatch);
-
- if (all_flag || NILP (bestmatch))
- return bestmatch;
- if (matchcount == 1 && bestmatchsize == XSTRING (file)->size)
- return Qt;
- return Fsubstring (bestmatch, make_number (0), make_number (bestmatchsize));
- quit:
- if (d) closedir (d);
- Vquit_flag = Qnil;
- return Fsignal (Qquit, Qnil);
-}
-
-file_name_completion_stat (dirname, dp, st_addr)
- Lisp_Object dirname;
- DIRENTRY *dp;
- struct stat *st_addr;
-{
- int len = NAMLEN (dp);
- int pos = XSTRING (dirname)->size;
- int value;
- char *fullname = (char *) alloca (len + pos + 2);
-
-#ifdef MSDOS
-#if __DJGPP__ > 1
- /* Some fields of struct stat are *very* expensive to compute on MS-DOS,
- but aren't required here. Avoid computing the following fields:
- st_inode, st_size and st_nlink for directories, and the execute bits
- in st_mode for non-directory files with non-standard extensions. */
-
- unsigned short save_djstat_flags = _djstat_flags;
-
- _djstat_flags = _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
-#endif /* __DJGPP__ > 1 */
-#endif /* MSDOS */
-
- bcopy (XSTRING (dirname)->data, fullname, pos);
-#ifndef VMS
- if (!IS_DIRECTORY_SEP (fullname[pos - 1]))
- fullname[pos++] = DIRECTORY_SEP;
-#endif
-
- bcopy (dp->d_name, fullname + pos, len);
- fullname[pos + len] = 0;
-
-#ifdef S_IFLNK
- /* We want to return success if a link points to a nonexistent file,
- but we want to return the status for what the link points to,
- in case it is a directory. */
- value = lstat (fullname, st_addr);
- stat (fullname, st_addr);
- return value;
-#else
- value = stat (fullname, st_addr);
-#ifdef MSDOS
-#if __DJGPP__ > 1
- _djstat_flags = save_djstat_flags;
-#endif /* __DJGPP__ > 1 */
-#endif /* MSDOS */
- return value;
-#endif /* S_IFLNK */
-}
-
-#ifdef VMS
-
-DEFUN ("file-name-all-versions", Ffile_name_all_versions,
- Sfile_name_all_versions, 2, 2, 0,
- "Return a list of all versions of file name FILE in directory DIRECTORY.")
- (file, directory)
- Lisp_Object file, directory;
-{
- return file_name_completion (file, directory, 1, 1);
-}
-
-DEFUN ("file-version-limit", Ffile_version_limit, Sfile_version_limit, 1, 1, 0,
- "Return the maximum number of versions allowed for FILE.\n\
-Returns nil if the file cannot be opened or if there is no version limit.")
- (filename)
- Lisp_Object filename;
-{
- Lisp_Object retval;
- struct FAB fab;
- struct RAB rab;
- struct XABFHC xabfhc;
- int status;
-
- filename = Fexpand_file_name (filename, Qnil);
- fab = cc$rms_fab;
- xabfhc = cc$rms_xabfhc;
- fab.fab$l_fna = XSTRING (filename)->data;
- fab.fab$b_fns = strlen (fab.fab$l_fna);
- fab.fab$l_xab = (char *) &xabfhc;
- status = sys$open (&fab, 0, 0);
- if (status != RMS$_NORMAL) /* Probably non-existent file */
- return Qnil;
- sys$close (&fab, 0, 0);
- if (xabfhc.xab$w_verlimit == 32767)
- return Qnil; /* No version limit */
- else
- return make_number (xabfhc.xab$w_verlimit);
-}
-
-#endif /* VMS */
-
-Lisp_Object
-make_time (time)
- int time;
-{
- return Fcons (make_number (time >> 16),
- Fcons (make_number (time & 0177777), Qnil));
-}
-
-DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 1, 0,
- "Return a list of attributes of file FILENAME.\n\
-Value is nil if specified file cannot be opened.\n\
-Otherwise, list elements are:\n\
- 0. t for directory, string (name linked to) for symbolic link, or nil.\n\
- 1. Number of links to file.\n\
- 2. File uid.\n\
- 3. File gid.\n\
- 4. Last access time, as a list of two integers.\n\
- First integer has high-order 16 bits of time, second has low 16 bits.\n\
- 5. Last modification time, likewise.\n\
- 6. Last status change time, likewise.\n\
- 7. Size in bytes (-1, if number is out of range).\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 exist, returns nil.")
- (filename)
- Lisp_Object filename;
-{
- Lisp_Object values[12];
- Lisp_Object dirname;
- struct stat s;
- struct stat sdir;
- char modes[10];
- Lisp_Object handler;
-
- filename = Fexpand_file_name (filename, Qnil);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qfile_attributes);
- if (!NILP (handler))
- return call2 (handler, Qfile_attributes, filename);
-
- if (lstat (XSTRING (filename)->data, &s) < 0)
- return Qnil;
-
- switch (s.st_mode & S_IFMT)
- {
- default:
- values[0] = Qnil; break;
- case S_IFDIR:
- values[0] = Qt; break;
-#ifdef S_IFLNK
- case S_IFLNK:
- values[0] = Ffile_symlink_p (filename); break;
-#endif
- }
- values[1] = make_number (s.st_nlink);
- values[2] = make_number (s.st_uid);
- values[3] = make_number (s.st_gid);
- values[4] = make_time (s.st_atime);
- values[5] = make_time (s.st_mtime);
- values[6] = make_time (s.st_ctime);
- values[7] = make_number ((int) s.st_size);
- /* If the size is out of range, give back -1. */
- if (XINT (values[7]) != s.st_size)
- XSETINT (values[7], -1);
- filemodestring (&s, modes);
- values[8] = make_string (modes, 10);
-#ifdef BSD4_3 /* Gross kludge to avoid lack of "#if defined(...)" in VMS */
-#define BSD4_2 /* A new meaning to the term `backwards compatibility' */
-#endif
-#ifdef BSD4_2 /* file gid will be dir gid */
- dirname = Ffile_name_directory (filename);
- if (! NILP (dirname) && stat (XSTRING (dirname)->data, &sdir) == 0)
- values[9] = (sdir.st_gid != s.st_gid) ? Qt : Qnil;
- else /* if we can't tell, assume worst */
- values[9] = Qt;
-#else /* file gid will be egid */
- values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
-#endif /* BSD4_2 (or BSD4_3) */
-#ifdef BSD4_3
-#undef BSD4_2 /* ok, you can look again without throwing up */
-#endif
-#if 1
- /* To allow inode numbers larger than VALBITS, separate the bottom
- 16 bits. */
- values[10] = Fcons (make_number (s.st_ino >> 16),
- make_number (s.st_ino & 0xffff));
-#else
- values[10] = make_number (s.st_ino);
-#endif
- values[11] = make_number (s.st_dev);
- return Flist (sizeof(values) / sizeof(values[0]), values);
-}
-
-syms_of_dired ()
-{
- Qdirectory_files = intern ("directory-files");
- Qfile_name_completion = intern ("file-name-completion");
- Qfile_name_all_completions = intern ("file-name-all-completions");
- Qfile_attributes = intern ("file-attributes");
-
- staticpro (&Qdirectory_files);
- staticpro (&Qfile_name_completion);
- staticpro (&Qfile_name_all_completions);
- staticpro (&Qfile_attributes);
-
- defsubr (&Sdirectory_files);
- defsubr (&Sfile_name_completion);
-#ifdef VMS
- defsubr (&Sfile_name_all_versions);
- defsubr (&Sfile_version_limit);
-#endif /* VMS */
- defsubr (&Sfile_name_all_completions);
- defsubr (&Sfile_attributes);
-
-#ifdef VMS
- Qcompletion_ignore_case = intern ("completion-ignore-case");
- staticpro (&Qcompletion_ignore_case);
-#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.");
- Vcompletion_ignored_extensions = Qnil;
-}
diff --git a/src/dispextern.h b/src/dispextern.h
deleted file mode 100644
index 98bbb5e0650..00000000000
--- a/src/dispextern.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/* Interface definitions for display code.
- Copyright (C) 1985, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifndef _DISPEXTERN_H_
-#define _DISPEXTERN_H_
-
-/* Nonzero means last display completed and cursor is really at
- cursX, cursY. Zero means it was preempted. */
-extern int display_completed;
-
-#ifdef HAVE_X_WINDOWS
-#include <X11/Xlib.h>
-#endif
-
-#ifdef MSDOS
-#include "msdos.h"
-#endif
-
-#ifdef HAVE_NTGUI
-#include "win32.h"
-#endif
-
-#ifdef HAVE_FACES
-struct face
- {
- /* If this is non-zero, it is a GC we can use without modification
- to represent this face. */
- GC gc;
-
- /* Pixel value for foreground color. */
- EMACS_UINT foreground;
-
- /* Pixel value for background color. */
- EMACS_UINT background;
-
- /* Font used for this face. */
- XFontStruct *font;
-
- /* Background stipple or bitmap used for this face. */
- Pixmap stipple;
-
- /* Pixmap_depth. */
- unsigned int pixmap_w, pixmap_h;
-
- /* Whether or not to underline text in this face. */
- char underline;
- };
-
-/* Let's stop using this and get rid of it. */
-typedef struct face *FACE;
-
-#define NORMAL_FACE ((struct face *) 0)
-
-#define FACE_HAS_GC(f) ((f)->gc)
-#define FACE_GC(f) ((f)->gc)
-#define FACE_FOREGROUND(f) ((f)->foreground)
-#define FACE_BACKGROUND(f) ((f)->background)
-#define FACE_FONT(f) ((f)->font)
-#define FACE_STIPPLE(f) ((f)->stipple)
-#define FACE_UNDERLINE_P(f) ((f)->underline)
-
-#else /* not HAVE_FACES */
-
-typedef int FACE;
-
-#define NORMAL_FACE 0x0
-#define HIGHLIGHT_FACE 0x1
-#define UNDERLINE_FACE 0x2
-#define HIGHLIGHT_UNDERLINE_FACE 0x3
-
-#define FACE_HIGHLIGHT(f) ((f) & 0x1)
-#define FACE_UNDERLINE(f) ((f) & 0x2)
-
-#endif /* not HAVE_FACES */
-
-
-/* This structure is used for the actual display of text on a frame.
-
- There are two instantiations of it: the glyphs currently displayed,
- and the glyphs we desire to display. The latter object is generated
- from buffers being displayed. */
-
-struct frame_glyphs
- {
- struct frame *frame; /* Frame these glyphs belong to. */
- int height;
- int width;
-
- /* Contents of the frame.
- glyphs[V][H] is the glyph at position V, H.
- Note that glyphs[V][-1],
- glyphs[V][used[V]],
- and glyphs[V][frame_width] are always '\0'. */
- GLYPH **glyphs;
- /* long vector from which the strings in `glyphs' are taken. */
- GLYPH *total_contents;
-
- /* When representing a desired frame,
- enable[n] == 0 means that line n is same as current frame.
- Between updates, all lines should be disabled.
- When representing current frame contents,
- enable[n] == 0 means that line n is blank. */
- char *enable;
-
- /* Everything on line n after column used[n] is considered blank. */
- int *used;
-
- /* highlight[n] != 0 iff line n is highlighted. */
- char *highlight;
-
- /* Buffer offset of this line's first char.
- This is not really implemented, and cannot be,
- and should be deleted. */
- int *bufp;
-
-#ifdef HAVE_WINDOW_SYSTEM
- /* Pixel position of top left corner of line. */
- short *top_left_x;
- short *top_left_y;
-
- /* Pixel width of line. */
- short *pix_width;
-
- /* Pixel height of line. */
- short *pix_height;
-
- /* Largest font ascent on this line. */
- short *max_ascent;
-#endif /* HAVE_WINDOW_SYSTEM */
-
- /* Mapping of coordinate pairs to buffer positions.
- This field holds a vector indexed by row number.
- Its elements are vectors indexed by column number.
- Each element of these vectors is a buffer position, 0, or -1.
-
- For a column where the image of a text character starts,
- the element value is the buffer position of that character.
- When a window's screen line starts in mid character,
- the element for the line's first column (at the window's left margin)
- is that character's position.
- For successive columns within a multicolumn character,
- the element is -1.
- For the column just beyond the last glyph on a line,
- the element is the buffer position of the end of the line.
- For following columns within the same window, the element is 0.
- For rows past the end of the accessible buffer text,
- the window's first column has ZV and other columns have 0.
-
- Mode lines and vertical separator lines have 0.
-
- The column of a window's left margin
- always has a positive value (a buffer position), not 0 or -1,
- for each line in that window's interior. */
-
- int **charstarts;
-
- /* This holds all the space in the subvectors of the charstarts field. */
- int *total_charstarts;
- };
-
-extern void get_display_line ();
-extern Lisp_Object sit_for ();
-
-#endif /* not _DISPEXTERN_H_ */
diff --git a/src/dispnew.c b/src/dispnew.c
deleted file mode 100644
index 388bae255ac..00000000000
--- a/src/dispnew.c
+++ /dev/null
@@ -1,2619 +0,0 @@
-/* Updating of data structures for redisplay.
- Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <signal.h>
-
-#include <config.h>
-
-#include <stdio.h>
-#include <ctype.h>
-
-#include "lisp.h"
-#include "termchar.h"
-#include "termopts.h"
-#include "termhooks.h"
-/* cm.h must come after dispextern.h on Windows. */
-#include "dispextern.h"
-#include "cm.h"
-#include "buffer.h"
-#include "frame.h"
-#include "window.h"
-#include "commands.h"
-#include "disptab.h"
-#include "indent.h"
-#include "intervals.h"
-#include "blockinput.h"
-
-#include "systty.h"
-#include "syssignal.h"
-
-#ifdef HAVE_X_WINDOWS
-#include "xterm.h"
-#endif /* HAVE_X_WINDOWS */
-
-#ifdef HAVE_NTGUI
-#include "w32term.h"
-#endif /* HAVE_NTGUI */
-
-/* Include systime.h after xterm.h to avoid double inclusion of time.h. */
-#include "systime.h"
-
-#include <errno.h>
-
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
-/* 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__
-/* The s- file might have overridden the definition with one that works for
- the system's C library. But we are using the GNU C library, so this is
- the right definition for every system. */
-#ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
-#define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
-#else
-#undef PENDING_OUTPUT_COUNT
-#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
-#endif
-#else /* not __GNU_LIBRARY__ */
-#ifndef PENDING_OUTPUT_COUNT
-#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
-#endif
-#endif
-
-static void change_frame_size_1 ();
-
-/* Nonzero upon entry to redisplay means do not assume anything about
- current contents of actual terminal frame; clear and redraw it. */
-
-int frame_garbaged;
-
-/* Nonzero means last display completed. 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 frame, 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 X windows: 10, 11 or nil. */
-Lisp_Object Vwindow_system_version;
-
-/* Vector of glyph definitions. Indexed by glyph number,
- the contents are a string which is how to output the glyph.
-
- If Vglyph_table is nil, a glyph is output by using its low 8 bits
- as a character code. */
-
-Lisp_Object Vglyph_table;
-
-/* Display table to use for vectors that don't specify their own. */
-
-Lisp_Object Vstandard_display_table;
-
-/* Nonzero means reading single-character input with prompt
- so put cursor on minibuffer after the prompt.
- positive means at end of text in echo area;
- negative means at beginning of line. */
-int cursor_in_echo_area;
-
-Lisp_Object Qdisplay_table;
-
-/* The currently selected frame.
- In a single-frame version, this variable always holds the address of
- the_only_frame. */
-
-FRAME_PTR selected_frame;
-
-/* A frame which is not just a minibuffer, or 0 if there are no such
- frames. This is usually the most recent such frame that was
- selected. In a single-frame version, this variable always holds
- the address of the_only_frame. */
-FRAME_PTR last_nonminibuf_frame;
-
-/* This is a vector, made larger whenever it isn't large enough,
- which is used inside `update_frame' to hold the old contents
- of the FRAME_PHYS_LINES of the frame being updated. */
-struct frame_glyphs **ophys_lines;
-/* Length of vector currently allocated. */
-int ophys_lines_length;
-
-FILE *termscript; /* Stdio stream being used for copy of all output. */
-
-struct cm Wcm; /* Structure for info on cursor positioning */
-
-int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */
-
-DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
- "Clear frame FRAME and output again what is supposed to appear on it.")
- (frame)
- Lisp_Object frame;
-{
- FRAME_PTR f;
-
- CHECK_LIVE_FRAME (frame, 0);
- f = XFRAME (frame);
- update_begin (f);
- if (FRAME_MSDOS_P (f))
- set_terminal_modes ();
- clear_frame ();
- clear_frame_records (f);
- update_end (f);
- fflush (stdout);
- windows_or_buffers_changed++;
- /* Mark all windows as INaccurate,
- so that every window will have its redisplay done. */
- mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
- f->garbaged = 0;
- return Qnil;
-}
-
-redraw_frame (f)
- FRAME_PTR f;
-{
- Lisp_Object frame;
- XSETFRAME (frame, f);
- Fredraw_frame (frame);
-}
-
-DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
- "Clear and redisplay all visible frames.")
- ()
-{
- Lisp_Object tail, frame;
-
- FOR_EACH_FRAME (tail, frame)
- if (FRAME_VISIBLE_P (XFRAME (frame)))
- Fredraw_frame (frame);
-
- return Qnil;
-}
-
-/* This is used when frame_garbaged is set.
- Redraw the individual frames marked as garbaged. */
-
-void
-redraw_garbaged_frames ()
-{
- Lisp_Object tail, frame;
-
- FOR_EACH_FRAME (tail, frame)
- if (FRAME_VISIBLE_P (XFRAME (frame))
- && FRAME_GARBAGED_P (XFRAME (frame)))
- Fredraw_frame (frame);
-}
-
-
-static struct frame_glyphs *
-make_frame_glyphs (frame, empty)
- register FRAME_PTR frame;
- int empty;
-{
- register int i;
- register width = FRAME_WINDOW_WIDTH (frame);
- register height = FRAME_HEIGHT (frame);
- register struct frame_glyphs *new
- = (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
-
- SET_GLYPHS_FRAME (new, frame);
- new->height = height;
- new->width = width;
- new->used = (int *) xmalloc (height * sizeof (int));
- new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
- new->charstarts = (int **) xmalloc (height * sizeof (int *));
- new->highlight = (char *) xmalloc (height * sizeof (char));
- new->enable = (char *) xmalloc (height * sizeof (char));
- bzero (new->enable, height * sizeof (char));
- new->bufp = (int *) xmalloc (height * sizeof (int));
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (frame))
- {
- new->top_left_x = (short *) xmalloc (height * sizeof (short));
- new->top_left_y = (short *) xmalloc (height * sizeof (short));
- new->pix_width = (short *) xmalloc (height * sizeof (short));
- new->pix_height = (short *) xmalloc (height * sizeof (short));
- new->max_ascent = (short *) xmalloc (height * sizeof (short));
- }
-#endif /* HAVE_WINDOW_SYSTEM */
-
- if (empty)
- {
- /* Make the buffer used by decode_mode_spec. This buffer is also
- used as temporary storage when updating the frame. See scroll.c. */
- unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
- unsigned int total_charstarts = (width + 2) * sizeof (int);
-
- new->total_contents = (GLYPH *) xmalloc (total_glyphs);
- bzero (new->total_contents, total_glyphs);
-
- new->total_charstarts = (int *) xmalloc (total_charstarts);
- bzero (new->total_charstarts, total_charstarts);
- }
- else
- {
- unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
-
- new->total_contents = (GLYPH *) xmalloc (total_glyphs);
- bzero (new->total_contents, total_glyphs);
- for (i = 0; i < height; i++)
- new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
-
- if (!FRAME_TERMCAP_P (frame))
- {
- unsigned int total_charstarts = height * (width + 2) * sizeof (int);
-
- new->total_charstarts = (int *) xmalloc (total_charstarts);
- bzero (new->total_charstarts, total_charstarts);
- for (i = 0; i < height; i++)
- new->charstarts[i] = new->total_charstarts + i * (width + 2) + 1;
- }
- else
- {
- /* Without a window system, we don't really need charstarts.
- So use a small amount of space to make enough data structure
- to prevent crashes in display_text_line. */
- new->total_charstarts = (int *) xmalloc ((width + 2) * sizeof (int));
- for (i = 0; i < height; i++)
- new->charstarts[i] = new->total_charstarts;
- }
- }
-
- return new;
-}
-
-void
-free_frame_glyphs (frame, glyphs)
- FRAME_PTR frame;
- struct frame_glyphs *glyphs;
-{
- if (glyphs->total_contents)
- xfree (glyphs->total_contents);
- if (glyphs->total_charstarts)
- xfree (glyphs->total_charstarts);
-
- xfree (glyphs->used);
- xfree (glyphs->glyphs);
- xfree (glyphs->highlight);
- xfree (glyphs->enable);
- xfree (glyphs->bufp);
- if (glyphs->charstarts)
- xfree (glyphs->charstarts);
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (frame))
- {
- xfree (glyphs->top_left_x);
- xfree (glyphs->top_left_y);
- xfree (glyphs->pix_width);
- xfree (glyphs->pix_height);
- xfree (glyphs->max_ascent);
- }
-#endif /* HAVE_WINDOW_SYSTEM */
-
- xfree (glyphs);
-}
-
-void
-remake_frame_glyphs (frame)
- FRAME_PTR frame;
-{
- if (FRAME_CURRENT_GLYPHS (frame))
- free_frame_glyphs (frame, FRAME_CURRENT_GLYPHS (frame));
- if (FRAME_DESIRED_GLYPHS (frame))
- free_frame_glyphs (frame, FRAME_DESIRED_GLYPHS (frame));
- if (FRAME_TEMP_GLYPHS (frame))
- free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame));
-
- if (FRAME_MESSAGE_BUF (frame))
- {
- /* Reallocate the frame's message buffer; remember that
- echo_area_glyphs may be pointing here. */
- char *old_message_buf = FRAME_MESSAGE_BUF (frame);
-
- FRAME_MESSAGE_BUF (frame)
- = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
- FRAME_WIDTH (frame) + 1);
-
- if (echo_area_glyphs == old_message_buf)
- echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
- if (previous_echo_glyphs == old_message_buf)
- previous_echo_glyphs = FRAME_MESSAGE_BUF (frame);
- }
- else
- FRAME_MESSAGE_BUF (frame)
- = (char *) xmalloc (FRAME_WIDTH (frame) + 1);
-
- FRAME_CURRENT_GLYPHS (frame) = make_frame_glyphs (frame, 0);
- FRAME_DESIRED_GLYPHS (frame) = make_frame_glyphs (frame, 0);
- FRAME_TEMP_GLYPHS (frame) = make_frame_glyphs (frame, 1);
- if (FRAME_WINDOW_P (frame) || frame == selected_frame)
- SET_FRAME_GARBAGED (frame);
-}
-
-/* Return the hash code of contents of line VPOS in frame-matrix M. */
-
-static int
-line_hash_code (m, vpos)
- register struct frame_glyphs *m;
- int vpos;
-{
- register GLYPH *body, *end;
- register int h = 0;
-
- if (!m->enable[vpos])
- return 0;
-
- /* Give all highlighted lines the same hash code
- so as to encourage scrolling to leave them in place. */
- if (m->highlight[vpos])
- return -1;
-
- body = m->glyphs[vpos];
-
- if (must_write_spaces)
- while (1)
- {
- GLYPH g = *body++;
-
- if (g == 0)
- break;
- h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH;
- }
- else
- while (1)
- {
- GLYPH g = *body++;
-
- if (g == 0)
- break;
- h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g;
- }
-
- 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. */
-
-static unsigned int
-line_draw_cost (m, vpos)
- struct frame_glyphs *m;
- int vpos;
-{
- register GLYPH *beg = m->glyphs[vpos];
- register GLYPH *end = m->glyphs[vpos] + m->used[vpos];
- register int i;
- register int tlen = GLYPH_TABLE_LENGTH;
- register Lisp_Object *tbase = GLYPH_TABLE_BASE;
-
- /* Ignore trailing and leading spaces if we can. */
- if (!must_write_spaces)
- {
- while ((end != beg) && (*end == SPACEGLYPH))
- --end;
- if (end == beg)
- return (0); /* All blank line. */
-
- while (*beg == SPACEGLYPH)
- ++beg;
- }
-
- /* If we don't have a glyph-table, each glyph is one character,
- so return the number of glyphs. */
- if (tbase == 0)
- return end - beg;
-
- /* Otherwise, scan the glyphs and accumulate their total size in I. */
- i = 0;
- while ((beg <= end) && *beg)
- {
- register GLYPH g = *beg++;
-
- if (GLYPH_SIMPLE_P (tbase, tlen, g))
- i += 1;
- else
- i += GLYPH_LENGTH (tbase, g);
- }
- return i;
-}
-
-/* The functions on this page are the interface from xdisp.c to redisplay.
-
- The only other interface into redisplay is through setting
- FRAME_CURSOR_X (frame) and FRAME_CURSOR_Y (frame)
- and SET_FRAME_GARBAGED (frame). */
-
-/* cancel_line eliminates any request to display a line at position `vpos' */
-
-cancel_line (vpos, frame)
- int vpos;
- register FRAME_PTR frame;
-{
- FRAME_DESIRED_GLYPHS (frame)->enable[vpos] = 0;
-}
-
-clear_frame_records (frame)
- register FRAME_PTR frame;
-{
- bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame));
-}
-
-/* Clear out all display lines for a coming redisplay. */
-
-void
-init_desired_glyphs (frame)
- register FRAME_PTR frame;
-{
- register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
- int vpos;
- int height = FRAME_HEIGHT (frame);
-
- for (vpos = 0; vpos < height; vpos++)
- desired_glyphs->enable[vpos] = 0;
-}
-
-/* Prepare to display on line VPOS starting at HPOS within it. */
-
-void
-get_display_line (frame, vpos, hpos)
- register FRAME_PTR frame;
- int vpos;
- register int hpos;
-{
- register struct frame_glyphs *glyphs;
- register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
- register GLYPH *p;
-
- if (vpos < 0)
- abort ();
-
- if (! desired_glyphs->enable[vpos])
- {
- desired_glyphs->used[vpos] = 0;
- desired_glyphs->highlight[vpos] = 0;
- desired_glyphs->enable[vpos] = 1;
- }
-
- if (hpos > desired_glyphs->used[vpos])
- {
- GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos];
- GLYPH *end = desired_glyphs->glyphs[vpos] + hpos;
-
- desired_glyphs->used[vpos] = hpos;
- while (g != end)
- *g++ = SPACEGLYPH;
- }
-}
-
-/* Like bcopy except never gets confused by overlap. */
-
-void
-safe_bcopy (from, to, size)
- char *from, *to;
- int size;
-{
- if (size <= 0 || from == to)
- return;
-
- /* If the source and destination don't overlap, then bcopy can
- handle it. If they do overlap, but the destination is lower in
- memory than the source, we'll assume bcopy can handle that. */
- if (to < from || from + size <= to)
- bcopy (from, to, size);
-
- /* Otherwise, we'll copy from the end. */
- else
- {
- register char *endf = from + size;
- register char *endt = to + size;
-
- /* If TO - FROM is large, then we should break the copy into
- nonoverlapping chunks of TO - FROM bytes each. However, if
- TO - FROM is small, then the bcopy function call overhead
- makes this not worth it. The crossover point could be about
- anywhere. Since I don't think the obvious copy loop is too
- bad, I'm trying to err in its favor. */
- if (to - from < 64)
- {
- do
- *--endt = *--endf;
- while (endf != from);
- }
- else
- {
- for (;;)
- {
- endt -= (to - from);
- endf -= (to - from);
-
- if (endt < to)
- break;
-
- bcopy (endf, endt, to - from);
- }
-
- /* If SIZE wasn't a multiple of TO - FROM, there will be a
- little left over. The amount left over is
- (endt + (to - from)) - to, which is endt - from. */
- bcopy (from, to, endt - from);
- }
- }
-}
-
-/* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
- DISTANCE may be negative. */
-
-static void
-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);
-}
-
-/* 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_frame_lines (frame, from, end, amount, newpos)
- register FRAME_PTR frame;
- int from, end, amount, newpos;
-{
- register int i;
- register struct frame_glyphs *current_frame
- = FRAME_CURRENT_GLYPHS (frame);
- int pos_adjust;
- int width = FRAME_WINDOW_WIDTH (frame);
-
- if (!line_ins_del_ok)
- return 0;
-
- if (amount == 0)
- return 1;
-
- if (amount > 0)
- {
- update_begin (frame);
- 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_frame->glyphs + from,
- sizeof (GLYPH *) * (end + amount - from),
- amount * sizeof (GLYPH *));
-
- rotate_vector (current_frame->charstarts + from,
- sizeof (int *) * (end + amount - from),
- amount * sizeof (int *));
-
- safe_bcopy (current_frame->used + from,
- current_frame->used + from + amount,
- (end - from) * sizeof current_frame->used[0]);
-
- safe_bcopy (current_frame->highlight + from,
- current_frame->highlight + from + amount,
- (end - from) * sizeof current_frame->highlight[0]);
-
- safe_bcopy (current_frame->enable + from,
- current_frame->enable + from + amount,
- (end - from) * sizeof current_frame->enable[0]);
-
- /* Adjust the lines by an amount
- that puts the first of them at NEWPOS. */
- pos_adjust = newpos - current_frame->charstarts[from + amount][0];
-
- /* Offset each char position in the charstarts lines we moved
- by pos_adjust. */
- for (i = from + amount; i < end + amount; i++)
- {
- int *line = current_frame->charstarts[i];
- int col;
- for (col = 0; col < width; col++)
- if (line[col] > 0)
- line[col] += pos_adjust;
- }
- for (i = from; i < from + amount; i++)
- {
- int *line = current_frame->charstarts[i];
- int col;
- line[0] = -1;
- for (col = 0; col < width; col++)
- line[col] = 0;
- }
-
- /* Mark the lines made empty by scrolling as enabled, empty and
- normal video. */
- bzero (current_frame->used + from,
- amount * sizeof current_frame->used[0]);
- bzero (current_frame->highlight + from,
- amount * sizeof current_frame->highlight[0]);
- for (i = from; i < from + amount; i++)
- {
- current_frame->glyphs[i][0] = '\0';
- current_frame->charstarts[i][0] = -1;
- current_frame->enable[i] = 1;
- }
-
- safe_bcopy (current_frame->bufp + from,
- current_frame->bufp + from + amount,
- (end - from) * sizeof current_frame->bufp[0]);
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (frame))
- {
- safe_bcopy (current_frame->top_left_x + from,
- current_frame->top_left_x + from + amount,
- (end - from) * sizeof current_frame->top_left_x[0]);
-
- safe_bcopy (current_frame->top_left_y + from,
- current_frame->top_left_y + from + amount,
- (end - from) * sizeof current_frame->top_left_y[0]);
-
- safe_bcopy (current_frame->pix_width + from,
- current_frame->pix_width + from + amount,
- (end - from) * sizeof current_frame->pix_width[0]);
-
- safe_bcopy (current_frame->pix_height + from,
- current_frame->pix_height + from + amount,
- (end - from) * sizeof current_frame->pix_height[0]);
-
- safe_bcopy (current_frame->max_ascent + from,
- current_frame->max_ascent + from + amount,
- (end - from) * sizeof current_frame->max_ascent[0]);
- }
-#endif /* HAVE_WINDOW_SYSTEM */
-
- update_end (frame);
- }
- if (amount < 0)
- {
- update_begin (frame);
- 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_frame->glyphs + from + amount,
- sizeof (GLYPH *) * (end - from - amount),
- amount * sizeof (GLYPH *));
-
- rotate_vector (current_frame->charstarts + from + amount,
- sizeof (int *) * (end - from - amount),
- amount * sizeof (int *));
-
- safe_bcopy (current_frame->used + from,
- current_frame->used + from + amount,
- (end - from) * sizeof current_frame->used[0]);
-
- safe_bcopy (current_frame->highlight + from,
- current_frame->highlight + from + amount,
- (end - from) * sizeof current_frame->highlight[0]);
-
- safe_bcopy (current_frame->enable + from,
- current_frame->enable + from + amount,
- (end - from) * sizeof current_frame->enable[0]);
-
- /* Adjust the lines by an amount
- that puts the first of them at NEWPOS. */
- pos_adjust = newpos - current_frame->charstarts[from + amount][0];
-
- /* Offset each char position in the charstarts lines we moved
- by pos_adjust. */
- for (i = from + amount; i < end + amount; i++)
- {
- int *line = current_frame->charstarts[i];
- int col;
- for (col = 0; col < width; col++)
- if (line[col] > 0)
- line[col] += pos_adjust;
- }
- for (i = end + amount; i < end; i++)
- {
- int *line = current_frame->charstarts[i];
- int col;
- line[0] = -1;
- for (col = 0; col < width; col++)
- line[col] = 0;
- }
-
- /* Mark the lines made empty by scrolling as enabled, empty and
- normal video. */
- bzero (current_frame->used + end + amount,
- - amount * sizeof current_frame->used[0]);
- bzero (current_frame->highlight + end + amount,
- - amount * sizeof current_frame->highlight[0]);
- for (i = end + amount; i < end; i++)
- {
- current_frame->glyphs[i][0] = '\0';
- current_frame->charstarts[i][0] = 0;
- current_frame->enable[i] = 1;
- }
-
- safe_bcopy (current_frame->bufp + from,
- current_frame->bufp + from + amount,
- (end - from) * sizeof current_frame->bufp[0]);
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (frame))
- {
- safe_bcopy (current_frame->top_left_x + from,
- current_frame->top_left_x + from + amount,
- (end - from) * sizeof current_frame->top_left_x[0]);
-
- safe_bcopy (current_frame->top_left_y + from,
- current_frame->top_left_y + from + amount,
- (end - from) * sizeof current_frame->top_left_y[0]);
-
- safe_bcopy (current_frame->pix_width + from,
- current_frame->pix_width + from + amount,
- (end - from) * sizeof current_frame->pix_width[0]);
-
- safe_bcopy (current_frame->pix_height + from,
- current_frame->pix_height + from + amount,
- (end - from) * sizeof current_frame->pix_height[0]);
-
- safe_bcopy (current_frame->max_ascent + from,
- current_frame->max_ascent + from + amount,
- (end - from) * sizeof current_frame->max_ascent[0]);
- }
-#endif /* HAVE_WINDOW_SYSTEM */
-
- update_end (frame);
- }
- return 1;
-}
-
-/* After updating a window W that isn't the full frame wide,
- copy all the columns that W does not occupy
- into the FRAME_DESIRED_GLYPHS (frame) from the FRAME_PHYS_GLYPHS (frame)
- so that update_frame will not change those columns. */
-
-preserve_other_columns (w)
- struct window *w;
-{
- register int vpos;
- register struct frame_glyphs *current_frame, *desired_frame;
- register FRAME_PTR frame = XFRAME (w->frame);
- int start = WINDOW_LEFT_MARGIN (w);
- int end = WINDOW_RIGHT_EDGE (w);
- int bot = XFASTINT (w->top) + XFASTINT (w->height);
-
- current_frame = FRAME_CURRENT_GLYPHS (frame);
- desired_frame = FRAME_DESIRED_GLYPHS (frame);
-
- for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
- {
- if (current_frame->enable[vpos] && desired_frame->enable[vpos])
- {
- if (start > 0)
- {
- int len;
-
- bcopy (current_frame->glyphs[vpos],
- desired_frame->glyphs[vpos],
- start * sizeof (current_frame->glyphs[vpos][0]));
- bcopy (current_frame->charstarts[vpos],
- desired_frame->charstarts[vpos],
- start * sizeof (current_frame->charstarts[vpos][0]));
- len = min (start, current_frame->used[vpos]);
- if (desired_frame->used[vpos] < len)
- desired_frame->used[vpos] = len;
- }
- if (current_frame->used[vpos] > end
- && desired_frame->used[vpos] < current_frame->used[vpos])
- {
- while (desired_frame->used[vpos] < end)
- {
- int used = desired_frame->used[vpos]++;
- desired_frame->glyphs[vpos][used] = SPACEGLYPH;
- desired_frame->glyphs[vpos][used] = 0;
- }
- bcopy (current_frame->glyphs[vpos] + end,
- desired_frame->glyphs[vpos] + end,
- ((current_frame->used[vpos] - end)
- * sizeof (current_frame->glyphs[vpos][0])));
- bcopy (current_frame->charstarts[vpos] + end,
- desired_frame->charstarts[vpos] + end,
- ((current_frame->used[vpos] - end)
- * sizeof (current_frame->charstarts[vpos][0])));
- desired_frame->used[vpos] = current_frame->used[vpos];
- }
- }
- }
-}
-
-#if 0
-
-/* If window w does not need to be updated and isn't the full frame wide,
- copy all the columns that w does occupy
- into the FRAME_DESIRED_LINES (frame) from the FRAME_PHYS_LINES (frame)
- so that update_frame will not change those columns.
-
- Have not been able to figure out how to use this correctly. */
-
-preserve_my_columns (w)
- struct window *w;
-{
- register int vpos, fin;
- register struct frame_glyphs *l1, *l2;
- register FRAME_PTR frame = XFRAME (w->frame);
- int start = WINDOW_LEFT_MARGIN (w);
- int end = WINDOW_RIGHT_EDGE (w);
- int bot = XFASTINT (w->top) + XFASTINT (w->height);
-
- for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
- {
- if ((l1 = FRAME_DESIRED_GLYPHS (frame)->glyphs[vpos + 1])
- && (l2 = FRAME_PHYS_GLYPHS (frame)->glyphs[vpos + 1]))
- {
- if (l2->length > start && l1->length < l2->length)
- {
- fin = l2->length;
- if (fin > end) fin = end;
- while (l1->length < start)
- l1->body[l1->length++] = ' ';
- bcopy (l2->body + start, l1->body + start, fin - start);
- l1->length = fin;
- }
- }
- }
-}
-
-#endif
-
-/* Adjust by ADJUST the charstart values in window W
- after vpos VPOS, which counts relative to the frame
- (not relative to W itself). */
-
-void
-adjust_window_charstarts (w, vpos, adjust)
- struct window *w;
- int vpos;
- int adjust;
-{
- int left = WINDOW_LEFT_MARGIN (w);
- int top = XFASTINT (w->top);
- int right = left + window_internal_width (w);
- int bottom = top + window_internal_height (w);
- int i;
-
- for (i = vpos + 1; i < bottom; i++)
- {
- int *charstart
- = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
- int j;
- for (j = left; j < right; j++)
- if (charstart[j] > 0)
- charstart[j] += adjust;
- }
-}
-
-/* Check the charstarts values in the area of window W
- for internal consistency. We cannot check that they are "right";
- we can only look for something nonsensical. */
-
-verify_charstarts (w)
- struct window *w;
-{
- FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
- int i;
- int top = XFASTINT (w->top);
- int bottom = top + window_internal_height (w);
- int left = WINDOW_LEFT_MARGIN (w);
- int right = left + window_internal_width (w);
- int next_line;
- int truncate = (XINT (w->hscroll)
- || (truncate_partial_width_windows
- && !WINDOW_FULL_WIDTH_P (w))
- || !NILP (XBUFFER (w->buffer)->truncate_lines));
-
- for (i = top; i < bottom; i++)
- {
- int j;
- int last;
- int *charstart = FRAME_CURRENT_GLYPHS (f)->charstarts[i];
-
- if (i != top)
- {
- if (truncate)
- {
- /* If we are truncating lines, allow a jump
- in charstarts from one line to the next. */
- if (charstart[left] < next_line)
- abort ();
- }
- else
- {
- if (charstart[left] != next_line)
- abort ();
- }
- }
-
- for (j = left; j < right; j++)
- if (charstart[j] > 0)
- last = charstart[j];
- /* Record where the next line should start. */
- next_line = last;
- if (BUF_ZV (XBUFFER (w->buffer)) != last)
- {
- /* If there's a newline between the two lines, count that. */
- int endchar = *BUF_CHAR_ADDRESS (XBUFFER (w->buffer), last);
- if (endchar == '\n')
- next_line++;
- }
- }
-}
-
-/* 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 struct frame_glyphs *desired_glyphs
- = FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
- register int start = WINDOW_LEFT_MARGIN (w);
- register int bot = XFASTINT (w->top) + XFASTINT (w->height);
-
- for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
- if (desired_glyphs->enable[vpos]
- && desired_glyphs->used[vpos] >= start)
- desired_glyphs->used[vpos] = start;
-}
-
-/* These functions try to perform directly and immediately on the frame
- 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 frame 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 (g)
- int g;
-{
- register FRAME_PTR frame = selected_frame;
- register struct frame_glyphs *current_frame
- = FRAME_CURRENT_GLYPHS (frame);
-
-#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 = FRAME_CURSOR_X (frame);
-#ifndef COMPILER_REGISTER_BUG
- register
-#endif /* COMPILER_REGISTER_BUG */
- int vpos = FRAME_CURSOR_Y (frame);
-
- /* Give up if about to continue line. */
- if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1
-
- /* Avoid losing if cursor is in invisible text off left margin */
- || (XINT (w->hscroll) && hpos == WINDOW_LEFT_MARGIN (w))
-
- /* Give up if cursor outside window (in minibuf, probably) */
- || cursor_in_echo_area
- || FRAME_CURSOR_Y (frame) < XFASTINT (w->top)
- || FRAME_CURSOR_Y (frame) >= XFASTINT (w->top) + XFASTINT (w->height)
-
- /* Give up if cursor not really at FRAME_CURSOR_X, FRAME_CURSOR_Y */
- || !display_completed
-
- /* Give up if buffer appears in two places. */
- || buffer_shared > 1
-
-#ifdef USE_TEXT_PROPERTIES
- /* Intervals have already been adjusted, point is after the
- character that was just inserted. */
- /* Give up if character is invisible. */
- /* Give up if character has a face property.
- At the moment we only lose at end of line or end of buffer
- and only with faces that have some background */
- /* Instead of wasting time, give up if character has any text properties */
- || ! NILP (Ftext_properties_at (make_number (PT - 1), Qnil))
-#endif
-
- /* Give up if w is minibuffer and a message is being displayed there */
- || (MINI_WINDOW_P (w) && echo_area_glyphs))
- return 0;
-
- {
- int face = 0;
-#ifdef HAVE_FACES
- int dummy;
-
- if (FRAME_WINDOW_P (frame) || FRAME_MSDOS_P (frame))
- face = compute_char_face (frame, w, PT - 1, -1, -1, &dummy, PT, 0);
-#endif
- current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
- current_frame->charstarts[vpos][hpos] = PT - 1;
- /* Record the entry for after the newly inserted character. */
- current_frame->charstarts[vpos][hpos + 1] = PT;
- adjust_window_charstarts (w, vpos, 1);
- }
- unchanged_modified = MODIFF;
- beg_unchanged = GPT - BEG;
- XSETFASTINT (w->last_point, PT);
- XSETFASTINT (w->last_point_x, hpos);
- XSETFASTINT (w->last_modified, MODIFF);
- XSETFASTINT (w->last_overlay_modified, OVERLAY_MODIFF);
-
- reassert_line_highlight (0, vpos);
- write_glyphs (&current_frame->glyphs[vpos][hpos], 1);
- fflush (stdout);
- ++FRAME_CURSOR_X (frame);
- if (hpos == current_frame->used[vpos])
- {
- current_frame->used[vpos] = hpos + 1;
- current_frame->glyphs[vpos][hpos + 1] = 0;
- }
-
- return 1;
-}
-
-int
-direct_output_forward_char (n)
- int n;
-{
- register FRAME_PTR frame = selected_frame;
- register struct window *w = XWINDOW (selected_window);
- Lisp_Object position;
- int hpos = FRAME_CURSOR_X (frame);
-
- /* Give up if in truncated text at end of line. */
- if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1)
- return 0;
-
- /* Avoid losing if cursor is in invisible text off left margin
- or about to go off either side of window. */
- if ((FRAME_CURSOR_X (frame) == WINDOW_LEFT_MARGIN (w)
- && (XINT (w->hscroll) || n < 0))
- || (n > 0
- && (FRAME_CURSOR_X (frame) + 1 >= window_internal_width (w) - 1))
- || cursor_in_echo_area)
- return 0;
-
- /* Can't use direct output if highlighting a region. */
- if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
- return 0;
-
- /* Can't use direct output at an overlay boundary; it might have
- before-string or after-string properties. */
- if (overlay_touches_p (PT) || overlay_touches_p (PT - n))
- return 0;
-
-#ifdef USE_TEXT_PROPERTIES
- /* Don't use direct output next to an invisible character
- since we might need to do something special. */
-
- XSETFASTINT (position, PT);
- if (XFASTINT (position) < ZV
- && ! NILP (Fget_char_property (position,
- Qinvisible,
- selected_window)))
- return 0;
-
- XSETFASTINT (position, PT - 1);
- if (XFASTINT (position) >= BEGV
- && ! NILP (Fget_char_property (position,
- Qinvisible,
- selected_window)))
- return 0;
-#endif
-
- FRAME_CURSOR_X (frame) += n;
- XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (frame));
- XSETFASTINT (w->last_point, PT);
- cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
- fflush (stdout);
-
- return 1;
-}
-
-static void update_line ();
-
-/* Update frame F based on the data in FRAME_DESIRED_GLYPHS.
- Value is nonzero if redisplay stopped due to pending input.
- FORCE nonzero means do not stop for pending input. */
-
-int
-update_frame (f, force, inhibit_hairy_id)
- FRAME_PTR f;
- int force;
- int inhibit_hairy_id;
-{
- register struct frame_glyphs *current_frame;
- register struct frame_glyphs *desired_frame = 0;
- register int i;
- int pause;
- int preempt_count = baud_rate / 2400 + 1;
- extern input_pending;
-#ifdef HAVE_WINDOW_SYSTEM
- register int downto, leftmost;
-#endif
-
- if (baud_rate != FRAME_COST_BAUD_RATE (f))
- calculate_costs (f);
-
- if (preempt_count <= 0)
- preempt_count = 1;
-
- if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
-
- detect_input_pending ();
- if (input_pending && !force)
- {
- pause = 1;
- goto do_pause;
- }
-
- update_begin (f);
-
- if (!line_ins_del_ok)
- inhibit_hairy_id = 1;
-
- /* These are separate to avoid a possible bug in the AIX C compiler. */
- current_frame = FRAME_CURRENT_GLYPHS (f);
- desired_frame = FRAME_DESIRED_GLYPHS (f);
-
- /* See if any of the desired lines are enabled; don't compute for
- i/d line if just want cursor motion. */
- for (i = 0; i < FRAME_HEIGHT (f); i++)
- if (desired_frame->enable[i])
- break;
-
- /* Try doing i/d line, if not yet inhibited. */
- if (!inhibit_hairy_id && i < FRAME_HEIGHT (f))
- force |= scrolling (f);
-
- /* Update the individual lines as needed. Do bottom line first. */
-
- if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
- update_line (f, FRAME_HEIGHT (f) - 1);
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- {
- leftmost = downto = FRAME_INTERNAL_BORDER_WIDTH (f);
- if (desired_frame->enable[0])
- {
- current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
- current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
- = PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f)
- - current_frame->pix_height[FRAME_HEIGHT (f) - 1];
- current_frame->top_left_x[0] = leftmost;
- current_frame->top_left_y[0] = downto;
- }
- }
-#endif /* HAVE_WINDOW_SYSTEM */
-
- /* Now update the rest of the lines. */
- for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
- {
- if (desired_frame->enable[i])
- {
- if (FRAME_TERMCAP_P (f))
- {
- /* Flush out every so many lines.
- Also flush out if likely to have more than 1k buffered
- otherwise. I'm told that some 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 EMACS_OUTQSIZE
- if (EMACS_OUTQSIZE (0, &outq) < 0)
- /* Probably not a tty. Ignore the error and reset
- * the outq count. */
- outq = PENDING_OUTPUT_COUNT (stdout);
-#endif
- outq *= 10;
- if (baud_rate <= outq && baud_rate > 0)
- sleep (outq / baud_rate);
- }
- }
- }
-
- if ((i - 1) % preempt_count == 0)
- detect_input_pending ();
-
- update_line (f, i);
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- {
- current_frame->top_left_y[i] = downto;
- current_frame->top_left_x[i] = leftmost;
- }
-#endif /* HAVE_WINDOW_SYSTEM */
- }
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- downto += current_frame->pix_height[i];
-#endif /* HAVE_WINDOW_SYSTEM */
- }
- pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
-
- /* Now just clean up termcap drivers and set cursor, etc. */
- if (!pause)
- {
- if ((cursor_in_echo_area
- /* If we are showing a message instead of the minibuffer,
- show the cursor for the message instead of for the
- (now hidden) minibuffer contents. */
- || (EQ (minibuf_window, selected_window)
- && EQ (minibuf_window, echo_area_window)
- && echo_area_glyphs != 0))
- /* These cases apply only to the frame that contains
- the active minibuffer window. */
- && FRAME_HAS_MINIBUF_P (f)
- && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
- {
- int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
- int row, col;
-
- if (cursor_in_echo_area < 0)
- {
- row = top;
- col = 0;
- }
- else
- {
- /* If the minibuffer is several lines high, find the last
- line that has any text on it. */
- row = FRAME_HEIGHT (f);
- do
- {
- row--;
- if (current_frame->enable[row])
- col = current_frame->used[row];
- else
- col = 0;
- }
- while (row > top && col == 0);
-
- if (col >= FRAME_WINDOW_WIDTH (f))
- {
- col = 0;
- if (row < FRAME_HEIGHT (f) - 1)
- row++;
- }
- }
-
- cursor_to (row, col);
- }
- else
- cursor_to (FRAME_CURSOR_Y (f),
- max (min (FRAME_CURSOR_X (f),
- FRAME_WINDOW_WIDTH (f) - 1), 0));
- }
-
- update_end (f);
-
- if (termscript)
- fflush (termscript);
- fflush (stdout);
-
- /* Here if output is preempted because input is detected. */
- do_pause:
-
- if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
- display_completed = !pause;
-
- bzero (FRAME_DESIRED_GLYPHS (f)->enable, FRAME_HEIGHT (f));
- return pause;
-}
-
-/* Called when about to quit, to check for doing so
- at an improper time. */
-
-void
-quit_error_check ()
-{
-#if 0
- if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
- return;
- if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
- abort ();
- if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
- abort ();
-#endif
-}
-
-/* Decide what insert/delete line to do, and do it */
-
-extern void scrolling_1 ();
-
-scrolling (frame)
- FRAME_PTR frame;
-{
- int unchanged_at_top, unchanged_at_bottom;
- int window_size;
- int changed_lines;
- int *old_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
- int *new_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
- int *draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
- int *old_draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
- register int i;
- int free_at_end_vpos = FRAME_HEIGHT (frame);
- register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame);
- register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (frame);
-
- /* 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 = FRAME_HEIGHT (frame);
- for (i = 0; i < FRAME_HEIGHT (frame); i++)
- {
- /* Give up on this scrolling if some old lines are not enabled. */
- if (!current_frame->enable[i])
- return 0;
- old_hash[i] = line_hash_code (current_frame, i);
- if (! desired_frame->enable[i])
- new_hash[i] = old_hash[i];
- else
- new_hash[i] = line_hash_code (desired_frame, i);
-
- if (old_hash[i] != new_hash[i])
- {
- changed_lines++;
- unchanged_at_bottom = FRAME_HEIGHT (frame) - i - 1;
- }
- else if (i == unchanged_at_top)
- unchanged_at_top++;
- draw_cost[i] = line_draw_cost (desired_frame, i);
- old_draw_cost[i] = line_draw_cost (current_frame, i);
- }
-
- /* If changed lines are few, don't allow preemption, don't scroll. */
- if (!scroll_region_ok && changed_lines < baud_rate / 2400
- || unchanged_at_bottom == FRAME_HEIGHT (frame))
- return 1;
-
- window_size = (FRAME_HEIGHT (frame) - unchanged_at_top
- - unchanged_at_bottom);
-
- if (scroll_region_ok)
- free_at_end_vpos -= unchanged_at_bottom;
- else if (memory_below_frame)
- free_at_end_vpos = -1;
-
- /* If large window, fast terminal and few lines in common between
- current frame and desired frame, don't bother with i/d calc. */
- if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400
- && (window_size >=
- 10 * scrolling_max_lines_saved (unchanged_at_top,
- FRAME_HEIGHT (frame) - unchanged_at_bottom,
- old_hash, new_hash, draw_cost)))
- return 0;
-
- scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
- draw_cost + unchanged_at_top - 1,
- old_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;
-}
-
-/* Return the offset in its buffer of the character at location col, line
- in the given window. */
-int
-buffer_posn_from_coords (window, col, line)
- struct window *window;
- int col, line;
-{
- int hscroll = XINT (window->hscroll);
- int window_left = WINDOW_LEFT_MARGIN (window);
-
- /* The actual width of the window is window->width less one for the
- DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
- window. */
- int window_width = window_internal_width (window) - 1;
-
- int startp = marker_position (window->start);
-
- /* Since compute_motion will only operate on the current buffer,
- we need to save the old one and restore it when we're done. */
- struct buffer *old_current_buffer = current_buffer;
- struct position *posn;
-
- current_buffer = XBUFFER (window->buffer);
-
- /* We can't get a correct result in this case,
- but at least prevent compute_motion from crashing. */
- if (startp < BEGV)
- startp = BEGV;
-
- /* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME
- (window->frame))->bufp to avoid scanning from the very top of
- the window, but it isn't maintained correctly, and I'm not even
- sure I will keep it. */
- posn = compute_motion (startp, 0,
- ((window == XWINDOW (minibuf_window) && startp == BEG
- ? minibuf_prompt_width : 0)
- + (hscroll ? 1 - hscroll : 0)),
- 0,
- ZV, line, col,
- window_width, hscroll, 0, window);
-
- current_buffer = old_current_buffer;
-
- /* compute_motion considers frame points past the end of a line
- to be *after* the newline, i.e. at the start of the next line.
- This is reasonable, but not really what we want. So if the
- result is on a line below LINE, back it up one character. */
- if (posn->vpos > line)
- return posn->bufpos - 1;
- else
- return posn->bufpos;
-}
-
-static int
-count_blanks (r)
- register GLYPH *r;
-{
- register GLYPH *p = r;
- while (*p++ == SPACEGLYPH);
- return p - r - 1;
-}
-
-static int
-count_match (str1, str2)
- GLYPH *str1, *str2;
-{
- register GLYPH *p1 = str1;
- register GLYPH *p2 = str2;
- while (*p1++ == *p2++);
- return p1 - str1 - 1;
-}
-
-/* Char insertion/deletion cost vector, from term.c */
-extern int *char_ins_del_vector;
-
-#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WINDOW_WIDTH((f))])
-
-static void
-update_line (frame, vpos)
- register FRAME_PTR frame;
- int vpos;
-{
- register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
- int *temp1;
- int tem;
- int osp, nsp, begmatch, endmatch, olen, nlen;
- int save;
- register struct frame_glyphs *current_frame
- = FRAME_CURRENT_GLYPHS (frame);
- register struct frame_glyphs *desired_frame
- = FRAME_DESIRED_GLYPHS (frame);
-
- if (desired_frame->highlight[vpos]
- != (current_frame->enable[vpos] && current_frame->highlight[vpos]))
- {
- change_line_highlight (desired_frame->highlight[vpos], vpos,
- (current_frame->enable[vpos] ?
- current_frame->used[vpos] : 0));
- current_frame->enable[vpos] = 0;
- }
- else
- reassert_line_highlight (desired_frame->highlight[vpos], vpos);
-
- if (! current_frame->enable[vpos])
- {
- olen = 0;
- }
- else
- {
- obody = current_frame->glyphs[vpos];
- olen = current_frame->used[vpos];
- if (! current_frame->highlight[vpos])
- {
- if (!must_write_spaces)
- while (olen > 0 && obody[olen - 1] == SPACEGLYPH)
- olen--;
- }
- else
- {
- /* For an inverse-video line, remember we gave it
- spaces all the way to the frame edge
- so that the reverse video extends all the way across. */
-
- while (olen < FRAME_WINDOW_WIDTH (frame) - 1)
- obody[olen++] = SPACEGLYPH;
- }
- }
-
- /* One way or another, this will enable the line being updated. */
- current_frame->enable[vpos] = 1;
- current_frame->used[vpos] = desired_frame->used[vpos];
- current_frame->highlight[vpos] = desired_frame->highlight[vpos];
- current_frame->bufp[vpos] = desired_frame->bufp[vpos];
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (frame))
- {
- current_frame->pix_width[vpos]
- = current_frame->used[vpos]
- * FONT_WIDTH (FRAME_FONT (frame));
- current_frame->pix_height[vpos]
- = FRAME_LINE_HEIGHT (frame);
- }
-#endif /* HAVE_WINDOW_SYSTEM */
-
- if (!desired_frame->enable[vpos])
- {
- nlen = 0;
- goto just_erase;
- }
-
- nbody = desired_frame->glyphs[vpos];
- nlen = desired_frame->used[vpos];
-
- /* Pretend trailing spaces are not there at all,
- unless for one reason or another we must write all spaces. */
- if (! desired_frame->highlight[vpos])
- {
- if (!must_write_spaces)
- /* We know that the previous character byte contains 0. */
- while (nbody[nlen - 1] == SPACEGLYPH)
- nlen--;
- }
- else
- {
- /* For an inverse-video line, give it extra trailing spaces
- all the way to the frame edge
- so that the reverse video extends all the way across. */
-
- while (nlen < FRAME_WINDOW_WIDTH (frame) - 1)
- nbody[nlen++] = SPACEGLYPH;
- }
-
- /* If there's no i/d char, quickly do the best we can without it. */
- if (!char_ins_del_ok)
- {
- int i,j;
-
-#if 0
- if (FRAME_X_P (frame))
- {
- /* Under X, erase everything we are going to rewrite,
- and rewrite everything from the first char that's changed.
- This is part of supporting fonts like Courier
- whose chars can overlap outside the char width. */
- for (i = 0; i < nlen; i++)
- if (i >= olen || nbody[i] != obody[i])
- break;
-
- cursor_to (vpos, i);
- if (i != olen)
- clear_end_of_line (olen);
- write_glyphs (nbody + i, nlen - i);
- }
- else
- {}
-#endif /* 0 */
- for (i = 0; i < nlen; i++)
- {
- if (i >= olen || nbody[i] != obody[i]) /* A non-matching char. */
- {
- cursor_to (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. */
- write_glyphs (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)
- {
- cursor_to (vpos, nlen);
- clear_end_of_line (olen);
- }
-
- /* Exchange contents between current_frame and new_frame. */
- temp = desired_frame->glyphs[vpos];
- desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
- current_frame->glyphs[vpos] = temp;
-
- /* Exchange charstarts between current_frame and new_frame. */
- temp1 = desired_frame->charstarts[vpos];
- desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
- current_frame->charstarts[vpos] = temp1;
-
- return;
- }
-
- if (!olen)
- {
- nsp = (must_write_spaces || desired_frame->highlight[vpos])
- ? 0 : count_blanks (nbody);
- if (nlen > nsp)
- {
- cursor_to (vpos, nsp);
- write_glyphs (nbody + nsp, nlen - nsp);
- }
-
- /* Exchange contents between current_frame and new_frame. */
- temp = desired_frame->glyphs[vpos];
- desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
- current_frame->glyphs[vpos] = temp;
-
- /* Exchange charstarts between current_frame and new_frame. */
- temp1 = desired_frame->charstarts[vpos];
- desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
- current_frame->charstarts[vpos] = temp1;
-
- 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 (!desired_frame->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] == SPACEGLYPH)
- 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.
- If this screws up the zero at the end of the line, re-establish it. */
- nbody[nlen] = save;
- 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
- && (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem]))
- endmatch = 0;
-
- /* nsp - osp is the distance to insert or delete.
- If that is nonzero, begmatch is known to be nonzero also.
- begmatch + endmatch is how much we save by doing the ins/del.
- Is it worth it? */
-
- if (nsp != osp
- && (!char_ins_del_ok
- || begmatch + endmatch <= char_ins_del_cost (frame)[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)
- {
- cursor_to (vpos, nsp);
- delete_glyphs (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)
- {
- cursor_to (vpos, nlen - endmatch + osp - nsp);
- delete_glyphs (olen + nsp - osp - nlen);
- olen = nlen - (nsp - osp);
- }
- cursor_to (vpos, osp);
- insert_glyphs ((char *)0, nsp - osp);
- }
- olen += nsp - osp;
-
- tem = nsp + begmatch + endmatch;
- if (nlen != tem || olen != tem)
- {
- cursor_to (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 == FRAME_WINDOW_WIDTH (frame))
- olen = 0;
- write_glyphs (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 == FRAME_WINDOW_WIDTH (frame) && fast_clear_end_of_line && olen > nlen)
- {
- /* endmatch must be zero, and tem must equal nsp + begmatch */
- write_glyphs (nbody + tem, nlen - tem - 1);
- clear_end_of_line (olen);
- olen = 0; /* Don't let it be cleared again later */
- write_glyphs (nbody + nlen - 1, 1);
- }
- else
- write_glyphs (nbody + nsp + begmatch, nlen - tem);
-#endif /* OBSOLETE */
-
- }
- else if (nlen > olen)
- {
- write_glyphs (nbody + nsp + begmatch, olen - tem);
- insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
- olen = nlen;
- }
- else if (olen > nlen)
- {
- write_glyphs (nbody + nsp + begmatch, nlen - tem);
- delete_glyphs (olen - nlen);
- olen = nlen;
- }
- }
-
- just_erase:
- /* If any unerased characters remain after the new line, erase them. */
- if (olen > nlen)
- {
- cursor_to (vpos, nlen);
- clear_end_of_line (olen);
- }
-
- /* Exchange contents between current_frame and new_frame. */
- temp = desired_frame->glyphs[vpos];
- desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
- current_frame->glyphs[vpos] = temp;
-
- /* Exchange charstarts between current_frame and new_frame. */
- temp1 = desired_frame->charstarts[vpos];
- desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
- current_frame->charstarts[vpos] = temp1;
-}
-
-/* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the
- session's frames, frame names, buffers, buffer-read-only flags, and
- buffer-modified-flags, and a trailing sentinel (so we don't need to
- add length checks). */
-static Lisp_Object frame_and_buffer_state;
-
-DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
- Sframe_or_buffer_changed_p, 0, 0, 0,
- "Return non-nil if the frame and buffer state appears to have changed.\n\
-The state variable is an internal vector containing all frames and buffers,\n\
-aside from buffers whose names start with space,\n\
-along with the buffers' read-only and modified flags, which allows a fast\n\
-check to see whether the menu bars might need to be recomputed.\n\
-If this function returns non-nil, it updates the internal vector to reflect\n\
-the current state.\n")
- ()
-{
- Lisp_Object tail, frame, buf;
- Lisp_Object *vecp;
- int n;
-
- vecp = XVECTOR (frame_and_buffer_state)->contents;
- FOR_EACH_FRAME (tail, frame)
- {
- if (!EQ (*vecp++, frame))
- goto changed;
- if (!EQ (*vecp++, XFRAME (frame)->name))
- goto changed;
- }
- /* Check that the buffer info matches.
- No need to test for the end of the vector
- because the last element of the vector is lambda
- and that will always cause a mismatch. */
- for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- buf = XCONS (XCONS (tail)->car)->cdr;
- /* Ignore buffers that aren't included in buffer lists. */
- if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
- continue;
- if (!EQ (*vecp++, buf))
- goto changed;
- if (!EQ (*vecp++, XBUFFER (buf)->read_only))
- goto changed;
- if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
- goto changed;
- }
- /* Detect deletion of a buffer at the end of the list. */
- if (*vecp == Qlambda)
- return Qnil;
- changed:
- /* Start with 1 so there is room for at least one lambda at the end. */
- n = 1;
- FOR_EACH_FRAME (tail, frame)
- n += 2;
- for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
- n += 3;
- /* Reallocate the vector if it's grown, or if it's shrunk a lot. */
- if (n > XVECTOR (frame_and_buffer_state)->size
- || n + 20 < XVECTOR (frame_and_buffer_state)->size / 2)
- /* Add 20 extra so we grow it less often. */
- frame_and_buffer_state = Fmake_vector (make_number (n + 20), Qlambda);
- vecp = XVECTOR (frame_and_buffer_state)->contents;
- FOR_EACH_FRAME (tail, frame)
- {
- *vecp++ = frame;
- *vecp++ = XFRAME (frame)->name;
- }
- for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- buf = XCONS (XCONS (tail)->car)->cdr;
- /* Ignore buffers that aren't included in buffer lists. */
- if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
- continue;
- *vecp++ = buf;
- *vecp++ = XBUFFER (buf)->read_only;
- *vecp++ = Fbuffer_modified_p (buf);
- }
- /* Fill up the vector with lambdas (always at least one). */
- *vecp++ = Qlambda;
- while (vecp - XVECTOR (frame_and_buffer_state)->contents
- < XVECTOR (frame_and_buffer_state)->size)
- *vecp++ = Qlambda;
- /* Make sure we didn't overflow the vector. */
- if (vecp - XVECTOR (frame_and_buffer_state)->contents
- > XVECTOR (frame_and_buffer_state)->size)
- abort ();
- return Qt;
-}
-
-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 (! NILP (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;
-}
-
-
-#ifdef SIGWINCH
-SIGTYPE
-window_change_signal (signalnum) /* If we don't have an argument, */
- int signalnum; /* some compilers complain in signal calls. */
-{
- int width, height;
- extern int errno;
- int old_errno = errno;
-
- get_frame_size (&width, &height);
-
- /* The frame size change obviously applies to a termcap-controlled
- frame. Find such a frame in the list, and assume it's the only
- one (since the redisplay code always writes to stdout, not a
- FILE * specified in the frame structure). Record the new size,
- but don't reallocate the data structures now. Let that be done
- later outside of the signal handler. */
-
- {
- Lisp_Object tail, frame;
-
- FOR_EACH_FRAME (tail, frame)
- {
- if (FRAME_TERMCAP_P (XFRAME (frame)))
- {
- change_frame_size (XFRAME (frame), height, width, 0, 1);
- break;
- }
- }
- }
-
- signal (SIGWINCH, window_change_signal);
- errno = old_errno;
-}
-#endif /* SIGWINCH */
-
-
-/* Do any change in frame size that was requested by a signal. */
-
-do_pending_window_change ()
-{
- /* If window_change_signal should have run before, run it now. */
- while (delayed_size_change)
- {
- Lisp_Object tail, frame;
-
- delayed_size_change = 0;
-
- FOR_EACH_FRAME (tail, frame)
- {
- FRAME_PTR f = XFRAME (frame);
-
- int height = FRAME_NEW_HEIGHT (f);
- int width = FRAME_NEW_WIDTH (f);
-
- if (height != 0 || width != 0)
- change_frame_size (f, height, width, 0, 0);
- }
- }
-}
-
-
-/* Change the frame height and/or width. Values may be given as zero to
- indicate no change is to take place.
-
- If DELAY is non-zero, then assume we're being called from a signal
- handler, and queue the change for later - perhaps the next
- redisplay. Since this tries to resize windows, we can't call it
- from a signal handler. */
-
-change_frame_size (f, newheight, newwidth, pretend, delay)
- register FRAME_PTR f;
- int newheight, newwidth, pretend;
-{
- Lisp_Object tail, frame;
- if (! FRAME_WINDOW_P (f))
- {
- /* When using termcap, or on MS-DOS, all frames use
- the same screen, so a change in size affects all frames. */
- FOR_EACH_FRAME (tail, frame)
- if (! FRAME_WINDOW_P (XFRAME (frame)))
- change_frame_size_1 (XFRAME (frame), newheight, newwidth,
- pretend, delay);
- }
- else
- change_frame_size_1 (f, newheight, newwidth, pretend, delay);
-}
-
-static void
-change_frame_size_1 (frame, newheight, newwidth, pretend, delay)
- register FRAME_PTR frame;
- int newheight, newwidth, pretend, delay;
-{
- int new_frame_window_width;
- /* If we can't deal with the change now, queue it for later. */
- if (delay)
- {
- FRAME_NEW_HEIGHT (frame) = newheight;
- FRAME_NEW_WIDTH (frame) = newwidth;
- delayed_size_change = 1;
- return;
- }
-
- /* This size-change overrides any pending one for this frame. */
- FRAME_NEW_HEIGHT (frame) = 0;
- FRAME_NEW_WIDTH (frame) = 0;
-
- /* If an argument is zero, set it to the current value. */
- if (newheight == 0)
- newheight = FRAME_HEIGHT (frame);
- if (newwidth == 0)
- newwidth = FRAME_WIDTH (frame);
- new_frame_window_width = FRAME_WINDOW_WIDTH_ARG (frame, newwidth);
-
- /* Round up to the smallest acceptable size. */
- check_frame_size (frame, &newheight, &newwidth);
-
- /* If we're not changing the frame size, quit now. */
- if (newheight == FRAME_HEIGHT (frame)
- && new_frame_window_width == FRAME_WINDOW_WIDTH (frame))
- return;
-
- BLOCK_INPUT;
-
-#ifdef MSDOS
- /* We only can set screen dimensions to certain values supported
- by our video hardware. Try to find the smallest size greater
- or equal to the requested dimensions. */
- dos_set_window_size (&newheight, &newwidth);
-#endif
-
- if (newheight != FRAME_HEIGHT (frame))
- {
- if (FRAME_HAS_MINIBUF_P (frame)
- && ! FRAME_MINIBUF_ONLY_P (frame))
- {
- /* Frame has both root and minibuffer. */
- set_window_height (FRAME_ROOT_WINDOW (frame),
- newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
- XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top,
- newheight - 1);
- set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
- }
- else
- /* Frame has just one top-level window. */
- set_window_height (FRAME_ROOT_WINDOW (frame),
- newheight - FRAME_MENU_BAR_LINES (frame), 0);
-
- if (FRAME_TERMCAP_P (frame) && !pretend)
- FrameRows = newheight;
-
-#if 0
- if (frame->output_method == output_termcap)
- {
- frame_height = newheight;
- if (!pretend)
- FrameRows = newheight;
- }
-#endif
- }
-
- if (new_frame_window_width != FRAME_WINDOW_WIDTH (frame))
- {
- set_window_width (FRAME_ROOT_WINDOW (frame), new_frame_window_width, 0);
- if (FRAME_HAS_MINIBUF_P (frame))
- set_window_width (FRAME_MINIBUF_WINDOW (frame), new_frame_window_width, 0);
-
- if (FRAME_TERMCAP_P (frame) && !pretend)
- FrameCols = newwidth;
-#if 0
- if (frame->output_method == output_termcap)
- {
- frame_width = newwidth;
- if (!pretend)
- FrameCols = newwidth;
- }
-#endif
- }
-
- FRAME_HEIGHT (frame) = newheight;
- SET_FRAME_WIDTH (frame, newwidth);
-
- if (FRAME_CURSOR_X (frame) >= FRAME_WINDOW_WIDTH (frame))
- FRAME_CURSOR_X (frame) = FRAME_WINDOW_WIDTH (frame) - 1;
- if (FRAME_CURSOR_Y (frame) >= FRAME_HEIGHT (frame))
- FRAME_CURSOR_Y (frame) = FRAME_HEIGHT (frame) - 1;
-
- remake_frame_glyphs (frame);
- calculate_costs (frame);
-
- UNBLOCK_INPUT;
-}
-
-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.")
- (string)
- Lisp_Object string;
-{
- CHECK_STRING (string, 0);
- fwrite (XSTRING (string)->data, 1, XSTRING (string)->size, stdout);
- fflush (stdout);
- if (termscript)
- {
- fwrite (XSTRING (string)->data, 1, XSTRING (string)->size, termscript);
- fflush (termscript);
- }
- return Qnil;
-}
-
-DEFUN ("ding", Fding, Sding, 0, 1, 0,
- "Beep, or flash the screen.\n\
-Also, unless an argument is given,\n\
-terminate any keyboard macro currently executing.")
- (arg)
- Lisp_Object arg;
-{
- if (!NILP (arg))
- {
- if (noninteractive)
- putchar (07);
- else
- ring_bell ();
- fflush (stdout);
- }
- else
- bitch_at_user ();
-
- return Qnil;
-}
-
-bitch_at_user ()
-{
- if (noninteractive)
- putchar (07);
- else if (!INTERACTIVE) /* 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, 2, 0,
- "Pause, without updating display, for SECONDS seconds.\n\
-SECONDS may be a floating-point value, meaning that you can wait for a\n\
-fraction of a second. Optional second arg MILLISECONDS specifies an\n\
-additional wait period, in milliseconds; this may be useful if your\n\
-Emacs was built without floating point support.\n\
-\(Not all operating systems support waiting for a fraction of a second.)")
- (seconds, milliseconds)
- Lisp_Object seconds, milliseconds;
-{
- int sec, usec;
-
- if (NILP (milliseconds))
- XSETINT (milliseconds, 0);
- else
- CHECK_NUMBER (milliseconds, 1);
- usec = XINT (milliseconds) * 1000;
-
-#ifdef LISP_FLOAT_TYPE
- {
- double duration = extract_float (seconds);
- sec = (int) duration;
- usec += (duration - sec) * 1000000;
- }
-#else
- CHECK_NUMBER (seconds, 0);
- sec = XINT (seconds);
-#endif
-
-#ifndef EMACS_HAS_USECS
- if (sec == 0 && usec != 0)
- error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
-#endif
-
- /* Assure that 0 <= usec < 1000000. */
- if (usec < 0)
- {
- /* We can't rely on the rounding being correct if user is negative. */
- if (-1000000 < usec)
- sec--, usec += 1000000;
- else
- sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
- }
- else
- sec += usec / 1000000, usec %= 1000000;
-
- if (sec < 0 || (sec == 0 && usec == 0))
- return Qnil;
-
- {
- Lisp_Object zero;
-
- XSETFASTINT (zero, 0);
- wait_reading_process_input (sec, usec, zero, 0);
- }
-
- /* We should always have wait_reading_process_input; we have a dummy
- implementation for systems which don't support subprocesses. */
-#if 0
- /* No wait_reading_process_input */
- immediate_quit = 1;
- QUIT;
-
-#ifdef VMS
- sys_sleep (sec);
-#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
- EMACS_GET_TIME (end_time);
- EMACS_SET_SECS_USECS (timeout, sec, usec);
- EMACS_ADD_TIME (end_time, end_time, timeout);
-
- while (1)
- {
- EMACS_GET_TIME (timeout);
- EMACS_SUB_TIME (timeout, end_time, timeout);
- if (EMACS_TIME_NEG_P (timeout)
- || !select (1, 0, 0, 0, &timeout))
- break;
- }
-#else /* not HAVE_SELECT */
- sleep (sec);
-#endif /* HAVE_SELECT */
-#endif /* not VMS */
-
- immediate_quit = 0;
-#endif /* no subprocesses */
-
- return Qnil;
-}
-
-/* This is just like wait_reading_process_input, except that
- it does the redisplay.
-
- It's also much like Fsit_for, except that it can be used for
- waiting for input as well. */
-
-Lisp_Object
-sit_for (sec, usec, reading, display)
- int sec, usec, reading, display;
-{
- Lisp_Object read_kbd;
-
- swallow_events (display);
-
- if (detect_input_pending_run_timers (display))
- return Qnil;
-
- if (display)
- redisplay_preserve_echo_area ();
-
- if (sec == 0 && usec == 0)
- return Qt;
-
-#ifdef SIGIO
- gobble_input (0);
-#endif
-
- XSETINT (read_kbd, reading ? -1 : 1);
- wait_reading_process_input (sec, usec, read_kbd, display);
-
-
- /* wait_reading_process_input should always be available now; it is
- simulated in a simple way on systems that don't support
- subprocesses. */
-#if 0
- /* No wait_reading_process_input available. */
- immediate_quit = 1;
- QUIT;
-
- waitchannels = 1;
-#ifdef VMS
- input_wait_timeout (XINT (arg));
-#else /* not VMS */
-#ifndef HAVE_TIMEVAL
- timeout_sec = sec;
- select (1, &waitchannels, 0, 0, &timeout_sec);
-#else /* HAVE_TIMEVAL */
- timeout.tv_sec = sec;
- timeout.tv_usec = usec;
- select (1, &waitchannels, 0, 0, &timeout);
-#endif /* HAVE_TIMEVAL */
-#endif /* not VMS */
-
- immediate_quit = 0;
-#endif
-
- return detect_input_pending () ? Qnil : Qt;
-}
-
-DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
- "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
-SECONDS may be a floating-point value, meaning that you can wait for a\n\
-fraction of a second. Optional second arg MILLISECONDS specifies an\n\
-additional wait period, in milliseconds; this may be useful if your\n\
-Emacs was built without floating point support.\n\
-\(Not all operating systems support waiting for a fraction of a second.)\n\
-Optional third arg NODISP non-nil means don't redisplay, just wait for input.\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.")
- (seconds, milliseconds, nodisp)
- Lisp_Object seconds, milliseconds, nodisp;
-{
- int sec, usec;
-
- if (NILP (milliseconds))
- XSETINT (milliseconds, 0);
- else
- CHECK_NUMBER (milliseconds, 1);
- usec = XINT (milliseconds) * 1000;
-
-#ifdef LISP_FLOAT_TYPE
- {
- double duration = extract_float (seconds);
- sec = (int) duration;
- usec += (duration - sec) * 1000000;
- }
-#else
- CHECK_NUMBER (seconds, 0);
- sec = XINT (seconds);
-#endif
-
-#ifndef EMACS_HAS_USECS
- if (usec != 0 && sec == 0)
- error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
-#endif
-
- return sit_for (sec, usec, 0, NILP (nodisp));
-}
-
-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 int display_arg;
-#endif
-
- meta_key = 0;
- inverse_video = 0;
- cursor_in_echo_area = 0;
- terminal_type = (char *) 0;
-
- /* Now is the time to initialize this; it's used by init_sys_modes
- during startup. */
- Vwindow_system = Qnil;
-
- /* If the user wants to use a window system, we shouldn't bother
- initializing the terminal. This is especially important when the
- terminal is so dumb that emacs gives up before and doesn't bother
- using the window system.
-
- If the DISPLAY environment variable is set and nonempty,
- try to use X, and die with an error message if that doesn't work. */
-
-#ifdef HAVE_X_WINDOWS
- if (! display_arg)
- {
- char *display;
-#ifdef VMS
- display = getenv ("DECW$DISPLAY");
-#else
- display = getenv ("DISPLAY");
-#endif
-
- display_arg = (display != 0 && *display != 0);
- }
-
- if (!inhibit_window_system && display_arg && initialized)
- {
- Vwindow_system = intern ("x");
-#ifdef HAVE_X11
- Vwindow_system_version = make_number (11);
-#else
- Vwindow_system_version = make_number (10);
-#endif
-#if defined (LINUX) && defined (HAVE_LIBNCURSES)
- /* In some versions of ncurses,
- tputs crashes if we have not called tgetent.
- So call tgetent. */
- { char b[2044]; tgetent (b, "xterm");}
-#endif
- return;
- }
-#endif /* HAVE_X_WINDOWS */
-
-#ifdef HAVE_NTGUI
- if (!inhibit_window_system)
- {
- Vwindow_system = intern ("w32");
- Vwindow_system_version = make_number (1);
- return;
- }
-#endif /* HAVE_NTGUI */
-
- /* If no window system has been specified, try to use the terminal. */
- if (! isatty (0))
- {
- fprintf (stderr, "emacs: standard input is not a tty\n");
- exit (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);
- }
-
-#ifdef VMS
- /* VMS DCL tends to upcase things, so downcase term type.
- Hardly any uppercase letters in terminal types; should be none. */
- {
- char *new = (char *) xmalloc (strlen (terminal_type) + 1);
- char *p;
-
- strcpy (new, terminal_type);
-
- for (p = new; *p; p++)
- if (isupper (*p))
- *p = tolower (*p);
-
- terminal_type = new;
- }
-#endif
-
- term_init (terminal_type);
-
- remake_frame_glyphs (selected_frame);
- calculate_costs (selected_frame);
-
- /* X and Y coordinates of the cursor between updates. */
- FRAME_CURSOR_X (selected_frame) = 0;
- FRAME_CURSOR_Y (selected_frame) = 0;
-
-#ifdef SIGWINCH
-#ifndef CANNOT_DUMP
- if (initialized)
-#endif /* CANNOT_DUMP */
- signal (SIGWINCH, window_change_signal);
-#endif /* SIGWINCH */
-}
-
-syms_of_display ()
-{
- defsubr (&Sredraw_frame);
- defsubr (&Sredraw_display);
- defsubr (&Sframe_or_buffer_changed_p);
- defsubr (&Sopen_termscript);
- defsubr (&Sding);
- defsubr (&Ssit_for);
- defsubr (&Ssleep_for);
- defsubr (&Ssend_string_to_terminal);
-
- frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
- staticpro (&frame_and_buffer_state);
-
- Qdisplay_table = intern ("display-table");
- staticpro (&Qdisplay_table);
-
- DEFVAR_INT ("baud-rate", &baud_rate,
- "*The output baud rate of the terminal.\n\
-On most systems, changing this value will affect the amount of padding\n\
-and the other strategic decisions made during redisplay.");
- DEFVAR_BOOL ("inverse-video", &inverse_video,
- "*Non-nil means invert the entire frame display.\n\
-This means everything is in inverse video which otherwise would not be.");
- DEFVAR_BOOL ("visible-bell", &visible_bell,
- "*Non-nil means try to flash the frame to represent a bell.");
- DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
- "*Non-nil means no need to redraw entire frame after suspending.\n\
-A non-nil value is useful if the terminal can automatically preserve\n\
-Emacs's frame display when you reenter Emacs.\n\
-It is up to you to set this variable if your terminal can do that.");
- 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,
- "The version number of the window system in use.\n\
-For X windows, this is 10 or 11.");
- DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
- "Non-nil means put cursor in minibuffer, at end of any message there.");
- DEFVAR_LISP ("glyph-table", &Vglyph_table,
- "Table defining how to output a glyph code to the frame.\n\
-If not nil, this is a vector indexed by glyph code to define the glyph.\n\
-Each element can be:\n\
- integer: a glyph code which this glyph is an alias for.\n\
- string: output this glyph using that string (not impl. in X windows).\n\
- nil: this glyph mod 256 is char code to output,\n\
- and this glyph / 256 is face code for X windows (see `face-id').");
- Vglyph_table = Qnil;
-
- DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
- "Display table to use for buffers that specify none.\n\
-See `buffer-display-table' for more information.");
- Vstandard_display_table = Qnil;
-
- /* Initialize `window-system', unless init_display already decided it. */
-#ifdef CANNOT_DUMP
- if (noninteractive)
-#endif
- {
- Vwindow_system = Qnil;
- Vwindow_system_version = Qnil;
- }
-}
diff --git a/src/disptab.h b/src/disptab.h
deleted file mode 100644
index 71f36b6353a..00000000000
--- a/src/disptab.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Things for GLYPHS and glyph tables.
- Copyright (C) 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Access the slots of a display-table, according to their purpose. */
-
-#define DISP_TABLE_P(obj) \
- (CHAR_TABLE_P (obj) \
- && XCHAR_TABLE (obj)->purpose == Qdisplay_table \
- && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (obj)) == DISP_TABLE_EXTRA_SLOTS)
-
-#define DISP_TABLE_EXTRA_SLOTS 6
-#define DISP_TRUNC_GLYPH(dp) ((dp)->extras[0])
-#define DISP_CONTINUE_GLYPH(dp) ((dp)->extras[1])
-#define DISP_ESCAPE_GLYPH(dp) ((dp)->extras[2])
-#define DISP_CTRL_GLYPH(dp) ((dp)->extras[3])
-#define DISP_INVIS_VECTOR(dp) ((dp)->extras[4])
-#define DISP_BORDER_GLYPH(dp) ((dp)->extras[5])
-
-#define DISP_CHAR_VECTOR(dp, c) ((dp)->contents[c])
-
-/* Defined in window.c. */
-extern struct Lisp_Char_Table *window_display_table ();
-
-/* Defined in indent.c. */
-extern struct Lisp_Char_Table *buffer_display_table ();
-
-/* Display table to use for vectors that don't specify their own. */
-extern Lisp_Object Vstandard_display_table;
-
-/* This is the `purpose' slot of a display table. */
-extern Lisp_Object Qdisplay_table;
-
-/* Vector of GLYPH definitions. Indexed by GLYPH number,
- the contents are a string which is how to output the GLYPH. */
-extern Lisp_Object Vglyph_table;
-
-/* Return the current length of the GLYPH table,
- or 0 if the table isn't currently valid. */
-#define GLYPH_TABLE_LENGTH \
- ((VECTORP (Vglyph_table)) ? XVECTOR (Vglyph_table)->size : 0)
-
-/* Return the current base (for indexing) of the GLYPH table,
- or 0 if the table isn't currently valid. */
-#define GLYPH_TABLE_BASE \
- ((VECTORP (Vglyph_table)) ? XVECTOR (Vglyph_table)->contents : 0)
-
-/* Given BASE and LEN returned by the two previous macros,
- return nonzero if the GLYPH code G should be output as a single
- character with code G. Return zero if G has a string in the table. */
-#define GLYPH_SIMPLE_P(base,len,g) ((g) >= (len) || !STRINGP (base[g]))
-
-/* Given BASE and LEN returned by the two previous macros,
- return nonzero if GLYPH code G is aliased to a different code. */
-#define GLYPH_ALIAS_P(base,len,g) ((g) < (len) && INTEGERP (base[g]))
-
-/* Assuming that GLYPH_SIMPLE_P (BASE, LEN, G) is 1,
- return the alias for G. */
-#define GLYPH_ALIAS(base, g) XINT (base[g])
-
-/* Follow all aliases for G in the glyph table given by (BASE,
- LENGTH), and set G to the final glyph. */
-#define GLYPH_FOLLOW_ALIASES(base, length, g) \
- while (GLYPH_ALIAS_P ((base), (length), (g))) \
- (g) = GLYPH_ALIAS ((base), (g));
-
-/* Assuming that GLYPH_SIMPLE_P (BASE, LEN, G) is 0,
- return the length and the address of the character-sequence
- used for outputting GLYPH G. */
-#define GLYPH_LENGTH(base,g) XSTRING (base[g])->size
-#define GLYPH_STRING(base,g) XSTRING (base[g])->data
-
-/* GLYPH for a space character. */
-
-#define SPACEGLYPH 040
-#define NULL_GLYPH 00
-
-#define GLYPH_FROM_CHAR(c) (c)
-
-extern int glyphlen ();
-extern void str_to_glyph_cpy ();
-extern void str_to_glyph_ncpy ();
-extern void glyph_to_str_cpy ();
diff --git a/src/doc.c b/src/doc.c
deleted file mode 100644
index 5c26e6c6a33..00000000000
--- a/src/doc.c
+++ /dev/null
@@ -1,702 +0,0 @@
-/* Record indices of function doc strings stored in a file.
- Copyright (C) 1985, 1986, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.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
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifndef O_RDONLY
-#define O_RDONLY 0
-#endif
-
-#include "lisp.h"
-#include "buffer.h"
-#include "keyboard.h"
-
-Lisp_Object Vdoc_file_name;
-
-extern char *index ();
-
-extern Lisp_Object Voverriding_local_map;
-
-/* For VMS versions with limited file name syntax,
- convert the name to something VMS will allow. */
-static void
-munge_doc_file_name (name)
- char *name;
-{
-#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 */
-}
-
-/* Buffer used for reading from documentation file. */
-static char *get_doc_string_buffer;
-static int get_doc_string_buffer_size;
-
-/* Extract a doc string from a file. FILEPOS says where to get it.
- If it is an integer, use that position in the standard DOC-... file.
- If it is (FILE . INTEGER), use FILE as the file name
- and INTEGER as the position in that file.
- But if INTEGER is negative, make it positive.
- (A negative integer is used for user variables, so we can distinguish
- them without actually fetching the doc string.) */
-
-static Lisp_Object
-get_doc_string (filepos)
- Lisp_Object filepos;
-{
- char *from, *to;
- register int fd;
- register char *name;
- register char *p, *p1;
- int minsize;
- int offset, position;
- Lisp_Object file, tem;
-
- if (INTEGERP (filepos))
- {
- file = Vdoc_file_name;
- position = XINT (filepos);
- }
- else if (CONSP (filepos))
- {
- file = XCONS (filepos)->car;
- position = XINT (XCONS (filepos)->cdr);
- if (position < 0)
- position = - position;
- }
- else
- return Qnil;
-
- if (!STRINGP (Vdoc_directory))
- return Qnil;
-
- if (!STRINGP (file))
- return Qnil;
-
- /* Put the file name in NAME as a C string.
- If it is relative, combine it with Vdoc_directory. */
-
- tem = Ffile_name_absolute_p (file);
- if (NILP (tem))
- {
- minsize = XSTRING (Vdoc_directory)->size;
- /* sizeof ("../etc/") == 8 */
- if (minsize < 8)
- minsize = 8;
- name = (char *) alloca (minsize + XSTRING (file)->size + 8);
- strcpy (name, XSTRING (Vdoc_directory)->data);
- strcat (name, XSTRING (file)->data);
- munge_doc_file_name (name);
- }
- else
- {
- name = (char *) XSTRING (file)->data;
- }
-
- fd = open (name, O_RDONLY, 0);
- if (fd < 0)
- {
-#ifndef CANNOT_DUMP
- if (!NILP (Vpurify_flag))
- {
- /* Preparing to dump; DOC file is probably not installed.
- So check in ../etc. */
- strcpy (name, "../etc/");
- strcat (name, XSTRING (file)->data);
- munge_doc_file_name (name);
-
- fd = open (name, O_RDONLY, 0);
- }
-#endif
- if (fd < 0)
- error ("Cannot open doc string file \"%s\"", name);
- }
-
- /* Seek only to beginning of disk block. */
- offset = position % (8 * 1024);
- if (0 > lseek (fd, position - offset, 0))
- {
- close (fd);
- error ("Position %ld out of range in doc string file \"%s\"",
- position, name);
- }
-
- /* Read the doc string into get_doc_string_buffer.
- P points beyond the data just read. */
-
- p = get_doc_string_buffer;
- while (1)
- {
- int space_left = (get_doc_string_buffer_size
- - (p - get_doc_string_buffer));
- int nread;
-
- /* Allocate or grow the buffer if we need to. */
- if (space_left == 0)
- {
- int in_buffer = p - get_doc_string_buffer;
- get_doc_string_buffer_size += 16 * 1024;
- get_doc_string_buffer
- = (char *) xrealloc (get_doc_string_buffer,
- get_doc_string_buffer_size + 1);
- p = get_doc_string_buffer + in_buffer;
- space_left = (get_doc_string_buffer_size
- - (p - get_doc_string_buffer));
- }
-
- /* Read a disk block at a time.
- If we read the same block last time, maybe skip this? */
- if (space_left > 1024 * 8)
- space_left = 1024 * 8;
- nread = read (fd, p, space_left);
- if (nread < 0)
- {
- close (fd);
- error ("Read error on documentation file");
- }
- p[nread] = 0;
- if (!nread)
- break;
- if (p == get_doc_string_buffer)
- p1 = index (p + offset, '\037');
- else
- p1 = index (p, '\037');
- if (p1)
- {
- *p1 = 0;
- p = p1;
- break;
- }
- p += nread;
- }
- close (fd);
-
- /* Scan the text and perform quoting with ^A (char code 1).
- ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_. */
- from = get_doc_string_buffer + offset;
- to = get_doc_string_buffer + offset;
- while (from != p)
- {
- if (*from == 1)
- {
- int c;
-
- from++;
- c = *from++;
- if (c == 1)
- *to++ = c;
- else if (c == '0')
- *to++ = 0;
- else if (c == '_')
- *to++ = 037;
- else
- error ("Invalid data in documentation file -- ^A followed by code 0%o", c);
- }
- else
- *to++ = *from++;
- }
-
- return make_string (get_doc_string_buffer + offset,
- to - (get_doc_string_buffer + offset));
-}
-
-/* Get a string from position FILEPOS and pass it through the Lisp reader.
- We use this for fetching the bytecode string and constants vector
- of a compiled function from the .elc file. */
-
-Lisp_Object
-read_doc_string (filepos)
- Lisp_Object filepos;
-{
- return Fread (get_doc_string (filepos));
-}
-
-DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 2, 0,
- "Return the documentation string of FUNCTION.\n\
-Unless a non-nil second argument RAW is given, the\n\
-string is passed through `substitute-command-keys'.")
- (function, raw)
- Lisp_Object function, raw;
-{
- Lisp_Object fun;
- Lisp_Object funcar;
- Lisp_Object tem, doc;
-
- fun = Findirect_function (function);
-
- if (SUBRP (fun))
- {
- if (XSUBR (fun)->doc == 0) return Qnil;
- if ((EMACS_INT) XSUBR (fun)->doc >= 0)
- doc = build_string (XSUBR (fun)->doc);
- else
- doc = get_doc_string (make_number (- (EMACS_INT) XSUBR (fun)->doc));
- }
- else if (COMPILEDP (fun))
- {
- if ((XVECTOR (fun)->size & PSEUDOVECTOR_SIZE_MASK) <= COMPILED_DOC_STRING)
- return Qnil;
- tem = XVECTOR (fun)->contents[COMPILED_DOC_STRING];
- if (STRINGP (tem))
- doc = tem;
- else if (NATNUMP (tem) || CONSP (tem))
- doc = get_doc_string (tem);
- else
- return Qnil;
- }
- else if (STRINGP (fun) || VECTORP (fun))
- {
- return build_string ("Keyboard macro.");
- }
- else if (CONSP (fun))
- {
- funcar = Fcar (fun);
- if (!SYMBOLP (funcar))
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
- else if (EQ (funcar, Qkeymap))
- return build_string ("Prefix command (definition is a keymap associating keystrokes with\n\
-subcommands.)");
- else if (EQ (funcar, Qlambda)
- || EQ (funcar, Qautoload))
- {
- Lisp_Object tem1;
- tem1 = Fcdr (Fcdr (fun));
- tem = Fcar (tem1);
- if (STRINGP (tem))
- doc = tem;
- /* Handle a doc reference--but these never come last
- in the function body, so reject them if they are last. */
- else if ((NATNUMP (tem) || CONSP (tem))
- && ! NILP (XCONS (tem1)->cdr))
- doc = get_doc_string (tem);
- else
- return Qnil;
- }
- else if (EQ (funcar, Qmocklisp))
- return Qnil;
- else if (EQ (funcar, Qmacro))
- return Fdocumentation (Fcdr (fun), raw);
- else
- goto oops;
- }
- else
- {
- oops:
- Fsignal (Qinvalid_function, Fcons (fun, Qnil));
- }
-
- if (NILP (raw))
- {
- struct gcpro gcpro1;
-
- GCPRO1 (doc);
- doc = Fsubstitute_command_keys (doc);
- UNGCPRO;
- }
- return doc;
-}
-
-DEFUN ("documentation-property", Fdocumentation_property, Sdocumentation_property, 2, 3, 0,
- "Return the documentation string that is SYMBOL's PROP property.\n\
-This is like `get', but it can refer to strings stored in the\n\
-`etc/DOC' file; and if the value is a string, it is passed through\n\
-`substitute-command-keys'. A non-nil third argument RAW avoids this\n\
-translation.")
- (symbol, prop, raw)
- Lisp_Object symbol, prop, raw;
-{
- register Lisp_Object tem;
-
- tem = Fget (symbol, prop);
- if (INTEGERP (tem))
- tem = get_doc_string (XINT (tem) > 0 ? tem : make_number (- XINT (tem)));
- else if (CONSP (tem))
- tem = get_doc_string (tem);
- if (NILP (raw) && STRINGP (tem))
- return Fsubstitute_command_keys (tem);
- return tem;
-}
-
-/* Scanning the DOC files and placing docstring offsets into functions. */
-
-static void
-store_function_docstring (fun, offset)
- Lisp_Object fun;
- /* Use EMACS_INT because we get this from pointer subtraction. */
- EMACS_INT offset;
-{
- fun = indirect_function (fun);
-
- /* The type determines where the docstring is stored. */
-
- /* Lisp_Subrs have a slot for it. */
- if (SUBRP (fun))
- XSUBR (fun)->doc = (char *) - offset;
-
- /* If it's a lisp form, stick it in the form. */
- else if (CONSP (fun))
- {
- Lisp_Object tem;
-
- tem = XCONS (fun)->car;
- if (EQ (tem, Qlambda) || EQ (tem, Qautoload))
- {
- tem = Fcdr (Fcdr (fun));
- if (CONSP (tem) && INTEGERP (XCONS (tem)->car))
- XSETFASTINT (XCONS (tem)->car, offset);
- }
- else if (EQ (tem, Qmacro))
- store_function_docstring (XCONS (fun)->cdr, offset);
- }
-
- /* Bytecode objects sometimes have slots for it. */
- else if (COMPILEDP (fun))
- {
- /* This bytecode object must have a slot for the
- docstring, since we've found a docstring for it. */
- if ((XVECTOR (fun)->size & PSEUDOVECTOR_SIZE_MASK) > COMPILED_DOC_STRING)
- XSETFASTINT (XVECTOR (fun)->contents[COMPILED_DOC_STRING], offset);
- }
-}
-
-
-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 `data-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 ();
-
-#ifndef CANNOT_DUMP
- if (NILP (Vpurify_flag))
- error ("Snarf-documentation can only be called in an undumped Emacs");
-#endif
-
- CHECK_STRING (filename, 0);
-
-#ifndef CANNOT_DUMP
- name = (char *) alloca (XSTRING (filename)->size + 14);
- strcpy (name, "../etc/");
-#else /* CANNOT_DUMP */
- CHECK_STRING (Vdoc_directory, 0);
- name = (char *) alloca (XSTRING (filename)->size +
- XSTRING (Vdoc_directory)->size + 1);
- strcpy (name, XSTRING (Vdoc_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 (SYMBOLP (sym))
- {
- /* Attach a docstring to a variable? */
- 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)));
- }
-
- /* Attach a docstring to a function? */
- else if (p[1] == 'F')
- store_function_docstring (sym, 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,
- "Substitute key descriptions for command names in STRING.\n\
-Return a new string which is 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.")
- (string)
- Lisp_Object string;
-{
- unsigned char *buf;
- int changed = 0;
- register unsigned char *strp;
- register unsigned char *bufp;
- int idx;
- int bsize;
- unsigned char *new;
- Lisp_Object tem;
- Lisp_Object keymap;
- unsigned char *start;
- int length;
- Lisp_Object name;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- if (NILP (string))
- return Qnil;
-
- CHECK_STRING (string, 0);
- tem = Qnil;
- keymap = Qnil;
- name = Qnil;
- GCPRO4 (string, tem, keymap, name);
-
- /* KEYMAP is either nil (which means search all the active keymaps)
- or a specified local map (which means search just that and the
- global map). If non-nil, it might come from Voverriding_local_map,
- or from a \\<mapname> construct in STRING itself.. */
- keymap = current_kboard->Voverriding_terminal_local_map;
- if (NILP (keymap))
- keymap = Voverriding_local_map;
-
- bsize = XSTRING (string)->size;
- bufp = buf = (unsigned char *) xmalloc (bsize);
-
- strp = (unsigned char *) XSTRING (string)->data;
- while (strp < (unsigned char *) XSTRING (string)->data + XSTRING (string)->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] == '[')
- {
- Lisp_Object firstkey;
-
- changed = 1;
- strp += 2; /* skip \[ */
- start = strp;
-
- while ((strp - (unsigned char *) XSTRING (string)->data
- < XSTRING (string)->size)
- && *strp != ']')
- strp++;
- length = strp - start;
- strp++; /* skip ] */
-
- /* Save STRP in IDX. */
- idx = strp - (unsigned char *) XSTRING (string)->data;
- tem = Fintern (make_string (start, length), Qnil);
- tem = Fwhere_is_internal (tem, keymap, Qt, Qnil);
-
- /* Disregard menu bar bindings; it is positively annoying to
- mention them when there's no menu bar, and it isn't terribly
- useful even when there is a menu bar. */
- if (!NILP (tem))
- {
- firstkey = Faref (tem, make_number (0));
- if (EQ (firstkey, Qmenu_bar))
- tem = Qnil;
- }
-
- if (NILP (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 (symbol-value foo).
- \<foo> just sets the keymap used for \[cmd]. */
- else if (strp[0] == '\\' && (strp[1] == '{' || strp[1] == '<'))
- {
- struct buffer *oldbuf;
-
- changed = 1;
- strp += 2; /* skip \{ or \< */
- start = strp;
-
- while ((strp - (unsigned char *) XSTRING (string)->data
- < XSTRING (string)->size)
- && *strp != '}' && *strp != '>')
- strp++;
- length = strp - start;
- strp++; /* skip } or > */
-
- /* Save STRP in IDX. */
- idx = strp - (unsigned char *) XSTRING (string)->data;
-
- /* Get the value of the keymap in TEM, or nil if undefined.
- Do this while still in the user's current buffer
- in case it is a local variable. */
- name = Fintern (make_string (start, length), Qnil);
- tem = Fboundp (name);
- if (! NILP (tem))
- {
- tem = Fsymbol_value (name);
- if (! NILP (tem))
- tem = get_keymap_1 (tem, 0, 1);
- }
-
- /* Now switch to a temp buffer. */
- oldbuf = current_buffer;
- set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
-
- if (NILP (tem))
- {
- name = Fsymbol_name (name);
- insert_string ("\nUses keymap \"");
- insert_from_string (name, 0, XSTRING (name)->size, 1);
- insert_string ("\", which is not currently defined.\n");
- if (start[-1] == '<') keymap = Qnil;
- }
- else if (start[-1] == '<')
- keymap = tem;
- else
- describe_map_tree (tem, 1, Qnil, Qnil, (char *)0, 1, 0);
- 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 STRING again in case gc relocated it. */
- strp = (unsigned char *) XSTRING (string)->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 = string;
- xfree (buf);
- RETURN_UNGCPRO (tem);
-}
-
-syms_of_doc ()
-{
- DEFVAR_LISP ("internal-doc-file-name", &Vdoc_file_name,
- "Name of file containing documentation strings of built-in symbols.");
- 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
deleted file mode 100644
index d9b6566b1bc..00000000000
--- a/src/doprnt.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/* Output like sprintf to a buffer of specified size.
- Also takes args differently: pass one pointer to an array of strings
- in addition to the format string which is separate.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include <stdio.h>
-#include <ctype.h>
-#include "lisp.h"
-
-extern long *xmalloc (), *xrealloc ();
-
-static int doprnt1 ();
-
-/* 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.
- String arguments are passed as C strings.
- Integers are passed as C integers. */
-
-doprnt (buffer, bufsize, format, format_end, nargs, args)
- char *buffer;
- register int bufsize;
- char *format;
- char *format_end;
- int nargs;
- char **args;
-{
- return doprnt1 (0, buffer, bufsize, format, format_end, nargs, args);
-}
-
-/* Like doprnt except that strings in ARGS are passed
- as Lisp_Object. */
-
-doprnt_lisp (buffer, bufsize, format, format_end, nargs, args)
- char *buffer;
- register int bufsize;
- char *format;
- char *format_end;
- int nargs;
- char **args;
-{
- return doprnt1 (1, buffer, bufsize, format, format_end, nargs, args);
-}
-
-static int
-doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
- int lispstrings;
- 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;
-
- register int tem;
- char *string;
- char fixed_buffer[20]; /* Default buffer for small formatting. */
- char *fmtcpy;
- int minlen;
- int size; /* Field width factor; e.g., %90d */
- char charbuf[2]; /* Used for %c. */
-
- if (format_end == 0)
- format_end = format + strlen (format);
-
- if ((format_end - format + 1) < sizeof (fixed_buffer))
- fmtcpy = fixed_buffer;
- else
- fmtcpy = (char *) alloca (format_end - format + 1);
-
- bufsize--;
-
- /* Loop until end of format string or buffer full. */
- while (fmt != format_end && bufsize > 0)
- {
- if (*fmt == '%') /* Check for a '%' character */
- {
- int size_bound;
-
- fmt++;
- /* Copy this one %-spec into fmtcpy. */
- string = fmtcpy;
- *string++ = '%';
- while (1)
- {
- *string++ = *fmt;
- if (! (*fmt >= '0' && *fmt <= '9')
- && *fmt != '-' && *fmt != ' '&& *fmt != '.')
- break;
- fmt++;
- }
- *string = 0;
- /* Get an idea of how much space we might need. */
- size_bound = atoi (&fmtcpy[1]);
-
- /* Avoid pitfall of negative "size" parameter ("%-200d"). */
- if (size_bound < 0)
- size_bound = -size_bound;
- size_bound += 50;
-
- if (size_bound > (((unsigned) 1) << (BITS_PER_INT - 1)))
- error ("Format padding too large");
-
- /* 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 'd':
- case 'o':
- case 'x':
- if (cnt == nargs)
- error ("Not enough arguments for format string");
- if (sizeof (int) == sizeof (EMACS_INT))
- ;
- else if (sizeof (long) == sizeof (EMACS_INT))
- /* Insert an `l' the right place. */
- string[1] = string[0],
- string[0] = string[-1],
- string[-1] = 'l',
- string++;
- else
- abort ();
- sprintf (sprintf_buffer, fmtcpy, args[cnt++]);
- /* Now copy into final output, truncating as nec. */
- string = sprintf_buffer;
- goto doit;
-
- case 'f':
- case 'e':
- case 'g':
- {
- union { double d; char *half[2]; } u;
- if (cnt + 1 == nargs)
- error ("not enough arguments for format string");
- 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 ("not enough arguments for format string");
- if (fmtcpy[1] != 's')
- minlen = atoi (&fmtcpy[1]);
- if (lispstrings)
- {
- string = (char *) ((struct Lisp_String *)args[cnt])->data;
- tem = ((struct Lisp_String *)args[cnt])->size;
- cnt++;
- }
- else
- {
- string = args[cnt++];
- tem = strlen (string);
- }
- goto doit1;
-
- /* Copy string into final output, truncating if no room. */
- doit:
- tem = strlen (string);
- doit1:
- if (minlen > 0)
- {
- while (minlen > tem && bufsize > 0)
- {
- *bufptr++ = ' ';
- bufsize--;
- minlen--;
- }
- minlen = 0;
- }
- if (tem > bufsize)
- tem = bufsize;
- bcopy (string, bufptr, tem);
- bufptr += tem;
- bufsize -= tem;
- if (minlen < 0)
- {
- while (minlen < - tem && bufsize > 0)
- {
- *bufptr++ = ' ';
- bufsize--;
- minlen++;
- }
- minlen = 0;
- }
- continue;
-
- case 'c':
- if (cnt == nargs)
- error ("not enough arguments for format string");
- *charbuf = (EMACS_INT) args[cnt++];
- string = charbuf;
- tem = 1;
- if (fmtcpy[1] != 'c')
- minlen = atoi (&fmtcpy[1]);
- goto doit1;
-
- case '%':
- fmt--; /* Drop thru and this % will be treated as normal */
- }
- }
- *bufptr++ = *fmt++; /* Just some characters; Copy 'em */
- bufsize--;
- };
-
- /* If we had to malloc something, free it. */
- if (big_buffer)
- xfree (big_buffer);
-
- *bufptr = 0; /* Make sure our string end with a '\0' */
- return bufptr - buffer;
-}
diff --git a/src/dosfns.c b/src/dosfns.c
deleted file mode 100644
index 69254ef7089..00000000000
--- a/src/dosfns.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/* MS-DOS specific Lisp utilities. Coded by Manabu Higashida, 1991.
- Major changes May-July 1993 Morten Welinder (only 10% original code left)
- Copyright (C) 1991, 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-
-#ifdef MSDOS
-/* The entire file is within this conditional */
-
-#include <stdio.h>
-#include <dos.h>
-#include "lisp.h"
-#include "buffer.h"
-#include "termchar.h"
-#include "termhooks.h"
-#include "frame.h"
-#include "dosfns.h"
-#include "msdos.h"
-#include <go32.h>
-#include <dirent.h>
-
-DEFUN ("int86", Fint86, Sint86, 2, 2, 0,
- "Call specific MSDOS interrupt number INTERRUPT with REGISTERS.\n\
-Return the updated REGISTER vector.\n\
-\n\
-INTERRUPT should be an integer in the range 0 to 255.\n\
-REGISTERS should be a vector produced by `make-register' and\n\
-`set-register-value'.")
- (interrupt, registers)
- Lisp_Object interrupt, registers;
-{
- register int i;
- int no;
- union REGS inregs, outregs;
- Lisp_Object val;
-
- CHECK_NUMBER (interrupt, 0);
- no = (unsigned long) XINT (interrupt);
- CHECK_VECTOR (registers, 1);
- if (no < 0 || no > 0xff || XVECTOR (registers)-> size != 8)
- return Qnil;
- for (i = 0; i < 8; i++)
- CHECK_NUMBER (XVECTOR (registers)->contents[i], 1);
-
- inregs.x.ax = (unsigned long) XFASTINT (XVECTOR (registers)->contents[0]);
- inregs.x.bx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[1]);
- inregs.x.cx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[2]);
- inregs.x.dx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[3]);
- inregs.x.si = (unsigned long) XFASTINT (XVECTOR (registers)->contents[4]);
- inregs.x.di = (unsigned long) XFASTINT (XVECTOR (registers)->contents[5]);
- inregs.x.cflag = (unsigned long) XFASTINT (XVECTOR (registers)->contents[6]);
- inregs.x.flags = (unsigned long) XFASTINT (XVECTOR (registers)->contents[7]);
-
- int86 (no, &inregs, &outregs);
-
- XVECTOR (registers)->contents[0] = make_number (outregs.x.ax);
- XVECTOR (registers)->contents[1] = make_number (outregs.x.bx);
- XVECTOR (registers)->contents[2] = make_number (outregs.x.cx);
- XVECTOR (registers)->contents[3] = make_number (outregs.x.dx);
- XVECTOR (registers)->contents[4] = make_number (outregs.x.si);
- XVECTOR (registers)->contents[5] = make_number (outregs.x.di);
- XVECTOR (registers)->contents[6] = make_number (outregs.x.cflag);
- XVECTOR (registers)->contents[7] = make_number (outregs.x.flags);
-
- return registers;
-}
-
-DEFUN ("msdos-memget", Fdos_memget, Sdos_memget, 2, 2, 0,
- "Read DOS memory at offset ADDRESS into VECTOR.\n\
-Return the updated VECTOR.")
- (address, vector)
- Lisp_Object address, vector;
-{
- register int i;
- int offs, len;
- char *buf;
- Lisp_Object val;
-
- CHECK_NUMBER (address, 0);
- offs = (unsigned long) XINT (address);
- CHECK_VECTOR (vector, 1);
- len = XVECTOR (vector)-> size;
- if (len < 1 || len > 2048 || address < 0 || address > 0xfffff - len)
- return Qnil;
- buf = alloca (len);
- dosmemget (offs, len, buf);
-
- for (i = 0; i < len; i++)
- XVECTOR (vector)->contents[i] = make_number (buf[i]);
-
- return vector;
-}
-
-DEFUN ("msdos-memput", Fdos_memput, Sdos_memput, 2, 2, 0,
- "Write DOS memory at offset ADDRESS from VECTOR.")
- (address, vector)
- Lisp_Object address, vector;
-{
- register int i;
- int offs, len;
- char *buf;
- Lisp_Object val;
-
- CHECK_NUMBER (address, 0);
- offs = (unsigned long) XINT (address);
- CHECK_VECTOR (vector, 1);
- len = XVECTOR (vector)-> size;
- if (len < 1 || len > 2048 || address < 0 || address > 0xfffff - len)
- return Qnil;
- buf = alloca (len);
-
- for (i = 0; i < len; i++)
- {
- CHECK_NUMBER (XVECTOR (vector)->contents[i], 1);
- buf[i] = (unsigned char) XFASTINT (XVECTOR (vector)->contents[i]) & 0xFF;
- }
-
- dosmemput (buf, len, offs);
- return Qt;
-}
-
-DEFUN ("msdos-set-keyboard", Fmsdos_set_keyboard, Smsdos_set_keyboard, 1, 2, 0,
- "Set keyboard layout according to COUNTRY-CODE.\n\
-If the optional argument ALLKEYS is non-nil, the keyboard is mapped for\n\
-all keys; otherwise it is only used when the ALT key is pressed.\n\
-The current keyboard layout is available in dos-keyboard-code.")
- (country_code, allkeys)
- Lisp_Object country_code;
-{
- CHECK_NUMBER (country_code, 0);
- if (!dos_set_keyboard (XINT (country_code), !NILP (allkeys)))
- return Qnil;
- return Qt;
-}
-
-#ifndef HAVE_X_WINDOWS
-/* Later we might want to control the mouse interface with this function,
- e.g., with respect to non-80 column screen modes. */
-
-DEFUN ("msdos-mouse-p", Fmsdos_mouse_p, Smsdos_mouse_p, 0, 0, 0, "\
-Report whether a mouse is present.")
- ()
-{
- if (have_mouse)
- return Qt;
- else
- return Qnil;
-}
-
-/* Function to translate colour names to integers. See lisp/term/pc-win.el
- for its definition. */
-
-Lisp_Object Qmsdos_color_translate;
-#endif
-
-
-DEFUN ("msdos-mouse-init", Fmsdos_mouse_init, Smsdos_mouse_init, 0, 0, "",
- "Initialize and enable mouse if available.")
- ()
-{
- if (have_mouse)
- {
- have_mouse = 1;
- mouse_init ();
- return Qt;
- }
- return Qnil;
-}
-
-DEFUN ("msdos-mouse-enable", Fmsdos_mouse_enable, Smsdos_mouse_enable, 0, 0, "",
- "Enable mouse if available.")
- ()
-{
- if (have_mouse)
- {
- have_mouse = 1;
- mouse_on ();
- }
- return have_mouse ? Qt : Qnil;
-}
-
-DEFUN ("msdos-mouse-disable", Fmsdos_mouse_disable, Smsdos_mouse_disable, 0, 0, "",
- "Disable mouse if available.")
- ()
-{
- mouse_off ();
- if (have_mouse) have_mouse = -1;
- return Qnil;
-}
-
-DEFUN ("insert-startup-screen", Finsert_startup_screen, Sinsert_startup_screen, 0, 0, "", "\
-Insert copy of screen contents prior to starting emacs.\n\
-Return nil if startup screen is not available.")
- ()
-{
- char *s;
- int rows, cols;
- int i, j;
-
- if (!dos_get_saved_screen (&s, &rows, &cols))
- return Qnil;
-
- for (i = 0; i < rows; i++)
- {
- for (j = 0; j < cols; j++)
- {
- insert_char (*s, 1);
- s += 2;
- }
- insert_char ('\n', 1);
- }
-
- return Qt;
-}
-
-/* country info */
-int dos_country_code;
-int dos_codepage;
-int dos_timezone_offset;
-int dos_decimal_point;
-int dos_keyboard_layout;
-unsigned char dos_country_info[DOS_COUNTRY_INFO];
-
-int dos_hyper_key;
-int dos_super_key;
-int dos_keypad_mode;
-
-Lisp_Object Vdos_version;
-Lisp_Object Vdos_display_scancodes;
-
-void
-init_dosfns ()
-{
- union REGS regs;
- _go32_dpmi_seginfo info;
- _go32_dpmi_registers dpmiregs;
-
-#ifndef SYSTEM_MALLOC
- get_lim_data (); /* why the hell isn't this called elsewhere? */
-#endif
-
- regs.x.ax = 0x3000;
- intdos (&regs, &regs);
- Vdos_version = Fcons (make_number (regs.h.al), make_number (regs.h.ah));
-
- /* Obtain the country code by calling Dos via Dpmi. Don't rely on GO32. */
- info.size = (sizeof(dos_country_info) + 15) / 16;
- if (_go32_dpmi_allocate_dos_memory (&info))
- dos_country_code = 1;
- else
- {
- dpmiregs.x.ax = 0x3800;
- dpmiregs.x.ds = info.rm_segment;
- dpmiregs.x.dx = 0;
- dpmiregs.x.ss = dpmiregs.x.sp = 0;
- _go32_dpmi_simulate_int (0x21, &dpmiregs);
- dos_country_code = dpmiregs.x.bx;
- dosmemget (info.rm_segment * 16, DOS_COUNTRY_INFO, dos_country_info);
- _go32_dpmi_free_dos_memory (&info);
- }
- dos_set_keyboard (dos_country_code, 0);
-
- regs.x.ax = 0x6601;
- intdos (&regs, &regs);
- if (regs.x.cflag)
- /* Estimate code page from country code */
- switch (dos_country_code)
- {
- case 45: /* Denmark */
- case 47: /* Norway */
- dos_codepage = 865;
- break;
- default:
- /* US */
- dos_codepage = 437;
- }
- else
- dos_codepage = regs.x.bx & 0xffff;
-
-#if __DJGPP__ >= 2
-
- /* Without this, we never see hidden files.
- Don't OR it with the previous value, so the value recorded at dump
- time, possibly with `preserve-case' flags set, won't get through. */
- __opendir_flags = __OPENDIR_FIND_HIDDEN;
-
-#if __DJGPP_MINOR__ == 0
- /* Under LFN, preserve the case of files as recorded in the directory
- (in DJGPP 2.01 and later this is automagically done by the library). */
- if (!NILP (Fmsdos_long_file_names ()))
- __opendir_flags |= __OPENDIR_PRESERVE_CASE;
-#endif /* __DJGPP_MINOR__ == 0 */
-#endif /* __DJGPP__ >= 2 */
-}
-
-/*
- * Define everything
- */
-syms_of_dosfns ()
-{
- defsubr (&Sint86);
- defsubr (&Sdos_memget);
- defsubr (&Sdos_memput);
- defsubr (&Smsdos_mouse_init);
- defsubr (&Smsdos_mouse_enable);
- defsubr (&Smsdos_set_keyboard);
- defsubr (&Sinsert_startup_screen);
- defsubr (&Smsdos_mouse_disable);
-#ifndef HAVE_X_WINDOWS
- defsubr (&Smsdos_mouse_p);
- Qmsdos_color_translate = intern ("msdos-color-translate");
- staticpro (&Qmsdos_color_translate);
-#endif
-
- DEFVAR_INT ("dos-country-code", &dos_country_code,
- "The country code returned by Dos when Emacs was started.\n\
-Usually this is the international telephone prefix.");
-
- DEFVAR_INT ("dos-codepage", &dos_codepage,
- "The codepage active when Emacs was started.\n\
-The following are known:\n\
- 437 United States\n\
- 850 Multilingual (Latin I)\n\
- 852 Slavic (Latin II)\n\
- 857 Turkish\n\
- 860 Portugal\n\
- 861 Iceland\n\
- 863 Canada (French)\n\
- 865 Norway/Denmark");
-
- DEFVAR_INT ("dos-timezone-offset", &dos_timezone_offset,
- "The current timezone offset to UTC in minutes.
-Implicitly modified when the TZ variable is changed.");
-
- DEFVAR_LISP ("dos-version", &Vdos_version,
- "The (MAJOR . MINOR) Dos version (subject to modification with setver).");
-
- DEFVAR_LISP ("dos-display-scancodes", &Vdos_display_scancodes,
- "*When non-nil, the keyboard scan-codes are displayed at the bottom right\n\
-corner of the display (typically at the end of the mode line).\n\
-The output format is: scan code:char code*modifiers.");
- Vdos_display_scancodes = Qnil;
-
- DEFVAR_INT ("dos-hyper-key", &dos_hyper_key,
- "*If set to 1, use right ALT key as hyper key.\n\
-If set to 2, use right CTRL key as hyper key.");
- dos_hyper_key = 0;
-
- DEFVAR_INT ("dos-super-key", &dos_super_key,
- "*If set to 1, use right ALT key as super key.\n\
-If set to 2, use right CTRL key as super key.");
- dos_super_key = 0;
-
- DEFVAR_INT ("dos-keypad-mode", &dos_keypad_mode,
- "*Controls what key code is returned by a key in the numeric keypad.\n\
-The `numlock ON' action is only taken if no modifier keys are pressed.\n\
-The value is an integer constructed by adding the following bits together:\n\
- \n\
- 0x00 Digit key returns digit (if numlock ON)\n\
- 0x01 Digit key returns kp-digit (if numlock ON)\n\
- 0x02 Digit key returns M-digit (if numlock ON)\n\
- 0x03 Digit key returns edit key (if numlock ON)\n\
- \n\
- 0x00 Grey key returns char (if numlock ON)\n\
- 0x04 Grey key returns kp-key (if numlock ON)\n\
- \n\
- 0x00 Digit key returns digit (if numlock OFF)\n\
- 0x10 Digit key returns kp-digit (if numlock OFF)\n\
- 0x20 Digit key returns M-digit (if numlock OFF)\n\
- 0x30 Digit key returns edit key (if numlock OFF)\n\
- \n\
- 0x00 Grey key returns char (if numlock OFF)\n\
- 0x40 Grey key returns kp-key (if numlock OFF)\n\
- \n\
- 0x200 ALT-0..ALT-9 in top-row produces shifted codes.");
- dos_keypad_mode = 0x75;
-
- DEFVAR_INT ("dos-keyboard-layout", &dos_keyboard_layout,
- "Contains the country code for the current keyboard layout.\n\
-Use msdos-set-keyboard to select another keyboard layout.");
- dos_keyboard_layout = 1; /* US */
-
- DEFVAR_INT ("dos-decimal-point", &dos_decimal_point,
- "If non-zero, it contains the character to be returned when the\n\
-decimal point key in the numeric keypad is pressed when Num Lock is on.\n\
-If zero, the decimal point key returns the country code specific value.");
- dos_decimal_point = 0;
-}
-#endif /* MSDOS */
diff --git a/src/dosfns.h b/src/dosfns.h
deleted file mode 100644
index 0858e5cf096..00000000000
--- a/src/dosfns.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* MS-DOS specific Lisp utilities interface.
- Coded by Manabu Higashida, 1991.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-extern int dos_hyper_key;
-extern int dos_super_key;
-extern int dos_decimal_point;
-extern int dos_keypad_mode;
-
-extern int dos_keyboard_layout;
-extern int dos_country_code;
-extern int dos_codepage;
-extern int dos_timezone_offset;
-
-#define DOS_COUNTRY_INFO 34 /* no of bytes returned by dos int 38h */
-extern unsigned char dos_country_info[DOS_COUNTRY_INFO];
-
-extern Lisp_Object Vdos_version;
-#ifndef HAVE_X_WINDOWS
-extern Lisp_Object Vdos_display_scancodes;
-extern Lisp_Object Qmsdos_color_translate;
-#endif
diff --git a/src/editfns.c b/src/editfns.c
deleted file mode 100644
index 9ff24cba8f3..00000000000
--- a/src/editfns.c
+++ /dev/null
@@ -1,2653 +0,0 @@
-/* Lisp functions pertaining to editing.
- Copyright (C) 1985,86,87,89,93,94,95,96 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <sys/types.h>
-
-#include <config.h>
-
-#ifdef VMS
-#include "vms-pwd.h"
-#else
-#include <pwd.h>
-#endif
-
-#include "lisp.h"
-#include "intervals.h"
-#include "buffer.h"
-#include "window.h"
-
-#include "systime.h"
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) > (b) ? (a) : (b))
-
-extern char **environ;
-extern Lisp_Object make_time ();
-extern void insert_from_buffer ();
-static int tm_diff ();
-static void update_buffer_properties ();
-void set_time_zone_rule ();
-
-Lisp_Object Vbuffer_access_fontify_functions;
-Lisp_Object Qbuffer_access_fontify_functions;
-Lisp_Object Vbuffer_access_fontified_property;
-
-/* Some static data, and a function to initialize it for each run */
-
-Lisp_Object Vsystem_name;
-Lisp_Object Vuser_real_login_name; /* login name of current user ID */
-Lisp_Object Vuser_full_name; /* full name of current user */
-Lisp_Object Vuser_login_name; /* user name from LOGNAME or USER */
-
-void
-init_editfns ()
-{
- char *user_name;
- register unsigned char *p, *q, *r;
- struct passwd *pw; /* password entry for the current user */
- Lisp_Object tem;
-
- /* Set up system_name even when dumping. */
- init_system_name ();
-
-#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 ());
-#ifdef MSDOS
- /* We let the real user name default to "root" because that's quite
- accurate on MSDOG and because it lets Emacs find the init file.
- (The DVX libraries override the Djgpp libraries here.) */
- Vuser_real_login_name = build_string (pw ? pw->pw_name : "root");
-#else
- Vuser_real_login_name = build_string (pw ? pw->pw_name : "unknown");
-#endif
-
- /* Get the effective user name, by consulting environment variables,
- or the effective uid if those are unset. */
- user_name = (char *) getenv ("LOGNAME");
- if (!user_name)
-#ifdef WINDOWSNT
- user_name = (char *) getenv ("USERNAME"); /* it's USERNAME on NT */
-#else /* WINDOWSNT */
- user_name = (char *) getenv ("USER");
-#endif /* WINDOWSNT */
- if (!user_name)
- {
- pw = (struct passwd *) getpwuid (geteuid ());
- user_name = (char *) (pw ? pw->pw_name : "unknown");
- }
- Vuser_login_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_login_name, Vuser_real_login_name);
- Vuser_full_name = Fuser_full_name (NILP (tem)? make_number (geteuid())
- : Vuser_login_name);
-
- p = (unsigned char *) getenv ("NAME");
- if (p)
- Vuser_full_name = build_string (p);
- else if (NILP (Vuser_full_name))
- Vuser_full_name = build_string ("unknown");
-}
-
-DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0,
- "Convert arg CHARACTER to a one-character string containing that character.")
- (character)
- Lisp_Object character;
-{
- char c;
- CHECK_NUMBER (character, 0);
-
- c = XINT (character);
- 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.")
- (string)
- register Lisp_Object string;
-{
- register Lisp_Object val;
- register struct Lisp_String *p;
- CHECK_STRING (string, 0);
-
- p = XSTRING (string);
- if (p->size)
- XSETFASTINT (val, ((unsigned char *) p->data)[0]);
- else
- XSETFASTINT (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;
- XSETFASTINT (temp, PT);
- return temp;
-}
-
-DEFUN ("point-marker", Fpoint_marker, Spoint_marker, 0, 0, 0,
- "Return value of point, as a marker object.")
- ()
-{
- return buildmark (PT);
-}
-
-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: ",
- "Set point to POSITION, a number or marker.\n\
-Beginning of buffer is position (point-min), end is (point-max).")
- (position)
- register Lisp_Object position;
-{
- CHECK_NUMBER_COERCE_MARKER (position, 0);
-
- SET_PT (clip_to_bounds (BEGV, XINT (position), ZV));
- return position;
-}
-
-static Lisp_Object
-region_limit (beginningp)
- int beginningp;
-{
- extern Lisp_Object Vmark_even_if_inactive; /* Defined in callint.c. */
- register Lisp_Object m;
- if (!NILP (Vtransient_mark_mode) && NILP (Vmark_even_if_inactive)
- && NILP (current_buffer->mark_active))
- Fsignal (Qmark_inactive, Qnil);
- m = Fmarker_position (current_buffer->mark);
- if (NILP (m)) error ("There is no region now");
- if ((PT < XFASTINT (m)) == beginningp)
- return (make_number (PT));
- 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));
-}
-
-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\
-If you set the marker not to point anywhere, the buffer will have no mark.")
- ()
-{
- return current_buffer->mark;
-}
-
-DEFUN ("line-beginning-position", Fline_beginning_position, Sline_beginning_position,
- 0, 1, 0,
- "Return the character position of the first character on the current line.\n\
-With argument N not nil or 1, move forward N - 1 lines first.\n\
-If scan reaches end of buffer, return that position.\n\
-This function does not move point.")
- (n)
- Lisp_Object n;
-{
- register int orig, end;
-
- if (NILP (n))
- XSETFASTINT (n, 1);
- else
- CHECK_NUMBER (n, 0);
-
- orig = PT;
- Fforward_line (make_number (XINT (n) - 1));
- end = PT;
- SET_PT (orig);
-
- return make_number (end);
-}
-
-DEFUN ("line-end-position", Fline_end_position, Sline_end_position,
- 0, 1, 0,
- "Return the character position of the last character on the current line.\n\
-With argument N not nil or 1, move forward N - 1 lines first.\n\
-If scan reaches end of buffer, return that position.\n\
-This function does not move point.")
- (n)
- Lisp_Object n;
-{
- if (NILP (n))
- XSETFASTINT (n, 1);
- else
- CHECK_NUMBER (n, 0);
-
- return make_number (find_before_next_newline
- (PT, 0, XINT (n) - (XINT (n) <= 0)));
-}
-
-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, Qnil),
- Fcons (visible ? Qt : Qnil,
- current_buffer->mark_active)));
-}
-
-Lisp_Object
-save_excursion_restore (info)
- Lisp_Object info;
-{
- Lisp_Object tem, tem1, omark, nmark;
- struct gcpro gcpro1, gcpro2, gcpro3;
-
- 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 (NILP (tem))
- return Qnil;
-
- omark = nmark = Qnil;
- GCPRO3 (info, omark, nmark);
-
- Fset_buffer (tem);
- tem = Fcar (info);
- Fgoto_char (tem);
- unchain_marker (tem);
- tem = Fcar (Fcdr (info));
- omark = Fmarker_position (current_buffer->mark);
- Fset_marker (current_buffer->mark, tem, Fcurrent_buffer ());
- nmark = Fmarker_position (tem);
- unchain_marker (tem);
- tem = Fcdr (Fcdr (info));
-#if 0 /* We used to make the current buffer visible in the selected window
- if that was true previously. That avoids some anomalies.
- But it creates others, and it wasn't documented, and it is simpler
- and cleaner never to alter the window/buffer connections. */
- tem1 = Fcar (tem);
- if (!NILP (tem1)
- && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
- Fswitch_to_buffer (Fcurrent_buffer (), Qnil);
-#endif /* 0 */
-
- tem1 = current_buffer->mark_active;
- current_buffer->mark_active = Fcdr (tem);
- if (!NILP (Vrun_hooks))
- {
- /* If mark is active now, and either was not active
- or was at a different place, run the activate hook. */
- if (! NILP (current_buffer->mark_active))
- {
- if (! EQ (omark, nmark))
- call1 (Vrun_hooks, intern ("activate-mark-hook"));
- }
- /* If mark has ceased to be active, run deactivate hook. */
- else if (! NILP (tem1))
- call1 (Vrun_hooks, intern ("deactivate-mark-hook"));
- }
- UNGCPRO;
- return Qnil;
-}
-
-DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0,
- "Save point, mark, and current buffer; execute BODY; restore those things.\n\
-Executes BODY just like `progn'.\n\
-The values of point, mark and the current buffer are restored\n\
-even in case of abnormal exit (throw or error).\n\
-The state of activation of the mark is also restored.")
- (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);
- return unbind_to (count, val);
-}
-
-DEFUN ("save-current-buffer", Fsave_current_buffer, Ssave_current_buffer, 0, UNEVALLED, 0,
- "Save the current buffer; execute BODY; restore the current buffer.\n\
-Executes BODY just like `progn'.")
- (args)
- Lisp_Object args;
-{
- register Lisp_Object val;
- int count = specpdl_ptr - specpdl;
-
- record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
-
- val = Fprogn (args);
- return unbind_to (count, val);
-}
-
-DEFUN ("buffer-size", Fbufsize, Sbufsize, 0, 0, 0,
- "Return the number of characters in the current buffer.")
- ()
-{
- Lisp_Object temp;
- XSETFASTINT (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 narrowing (a buffer restriction) is in effect.")
- ()
-{
- Lisp_Object temp;
- XSETFASTINT (temp, BEGV);
- return temp;
-}
-
-DEFUN ("point-min-marker", Fpoint_min_marker, Spoint_min_marker, 0, 0, 0,
- "Return a marker to the minimum permissible value of point in this buffer.\n\
-This is the beginning, unless narrowing (a buffer 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 narrowing (a buffer restriction)\n\
-is in effect, in which case it is less.")
- ()
-{
- Lisp_Object temp;
- XSETFASTINT (temp, ZV);
- return temp;
-}
-
-DEFUN ("point-max-marker", Fpoint_max_marker, Spoint_max_marker, 0, 0, 0,
- "Return a marker to the maximum permissible value of point in this buffer.\n\
-This is (1+ (buffer-size)), unless narrowing (a buffer restriction)\n\
-is in effect, in which case it is less.")
- ()
-{
- return buildmark (ZV);
-}
-
-DEFUN ("following-char", Ffollowing_char, Sfollowing_char, 0, 0, 0,
- "Return the character following point, as a number.\n\
-At the end of the buffer or accessible region, return 0.")
- ()
-{
- Lisp_Object temp;
- if (PT >= ZV)
- XSETFASTINT (temp, 0);
- else
- XSETFASTINT (temp, FETCH_CHAR (PT));
- return temp;
-}
-
-DEFUN ("preceding-char", Fprevious_char, Sprevious_char, 0, 0, 0,
- "Return the character preceding point, as a number.\n\
-At the beginning of the buffer or accessible region, return 0.")
- ()
-{
- Lisp_Object temp;
- if (PT <= BEGV)
- XSETFASTINT (temp, 0);
- else
- XSETFASTINT (temp, FETCH_CHAR (PT - 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 (PT == 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 (PT == ZV)
- return Qt;
- return Qnil;
-}
-
-DEFUN ("bolp", Fbolp, Sbolp, 0, 0, 0,
- "Return T if point is at the beginning of a line.")
- ()
-{
- if (PT == BEGV || FETCH_CHAR (PT - 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 (PT == ZV || FETCH_CHAR (PT) == '\n')
- return Qt;
- return Qnil;
-}
-
-DEFUN ("char-after", Fchar_after, Schar_after, 1, 1, 0,
- "Return character in current buffer at position POS.\n\
-POS is an integer or a buffer pointer.\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;
-
- XSETFASTINT (val, FETCH_CHAR (n));
- return val;
-}
-
-DEFUN ("user-login-name", Fuser_login_name, Suser_login_name, 0, 1, 0,
- "Return the name under which the user logged in, as a string.\n\
-This is based on the effective uid, not the real uid.\n\
-Also, if the environment variable LOGNAME or USER is set,\n\
-that determines the value of this function.\n\n\
-If optional argument UID is an integer, return the login name of the user\n\
-with that uid, or nil if there is no such user.")
- (uid)
- Lisp_Object uid;
-{
- struct passwd *pw;
-
- /* Set up the user name info if we didn't do it before.
- (That can happen if Emacs is dumpable
- but you decide to run `temacs -l loadup' and not dump. */
- if (INTEGERP (Vuser_login_name))
- init_editfns ();
-
- if (NILP (uid))
- return Vuser_login_name;
-
- CHECK_NUMBER (uid, 0);
- pw = (struct passwd *) getpwuid (XINT (uid));
- return (pw ? build_string (pw->pw_name) : Qnil);
-}
-
-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\
-This ignores the environment variables LOGNAME and USER, so it differs from\n\
-`user-login-name' when running under `su'.")
- ()
-{
- /* Set up the user name info if we didn't do it before.
- (That can happen if Emacs is dumpable
- but you decide to run `temacs -l loadup' and not dump. */
- if (INTEGERP (Vuser_login_name))
- init_editfns ();
- return Vuser_real_login_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, 1, 0,
- "Return the full name of the user logged in, as a string.\n\
-If optional argument UID is an integer, return the full name of the user\n\
-with that uid, or \"unknown\" if there is no such user.
-If UID is a string, return the full name of the user with that login\n\
-name, or \"unknown\" if no such user could be found.")
- (uid)
- Lisp_Object uid;
-{
- struct passwd *pw;
- register char *p, *q;
- extern char *index ();
- Lisp_Object full;
-
- if (NILP (uid))
- return Vuser_full_name;
- else if (NUMBERP (uid))
- pw = (struct passwd *) getpwuid (XINT (uid));
- else if (STRINGP (uid))
- pw = (struct passwd *) getpwnam (XSTRING (uid)->data);
- else
- error ("Invalid UID specification");
-
- if (!pw)
- return Qnil;
-
- p = (unsigned char *) USER_FULL_NAME;
- /* Chop off everything after the first comma. */
- q = (unsigned char *) index (p, ',');
- full = make_string (p, q ? q - p : strlen (p));
-
-#ifdef AMPERSAND_FULL_NAME
- p = XSTRING (full)->data;
- q = (unsigned char *) index (p, '&');
- /* Substitute the login name for the &, upcasing the first character. */
- if (q)
- {
- register char *r;
- Lisp_Object login;
-
- login = Fuser_login_name (make_number (pw->pw_uid));
- r = (unsigned char *) alloca (strlen (p) + XSTRING (login)->size + 1);
- bcopy (p, r, q - p);
- r[q - p] = 0;
- strcat (r, XSTRING (login)->data);
- r[q - p] = UPCASE (r[q - p]);
- strcat (r, q + 1);
- full = build_string (r);
- }
-#endif /* AMPERSAND_FULL_NAME */
-
- return full;
-}
-
-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;
-}
-
-/* For the benefit of callers who don't want to include lisp.h */
-char *
-get_system_name ()
-{
- return (char *) XSTRING (Vsystem_name)->data;
-}
-
-DEFUN ("emacs-pid", Femacs_pid, Semacs_pid, 0, 0, 0,
- "Return the process ID of Emacs, as an integer.")
- ()
-{
- return make_number (getpid ());
-}
-
-DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0,
- "Return the current time, as the number of seconds since 1970-01-01 00:00:00.\n\
-The time is returned as a list of three integers. The first has the\n\
-most significant 16 bits of the seconds, while the second has the\n\
-least significant 16 bits. The third integer gives the microsecond\n\
-count.\n\
-\n\
-The microsecond count is zero on systems that do not provide\n\
-resolution finer than a second.")
- ()
-{
- EMACS_TIME t;
- Lisp_Object result[3];
-
- EMACS_GET_TIME (t);
- XSETINT (result[0], (EMACS_SECS (t) >> 16) & 0xffff);
- XSETINT (result[1], (EMACS_SECS (t) >> 0) & 0xffff);
- XSETINT (result[2], EMACS_USECS (t));
-
- return Flist (3, result);
-}
-
-
-static int
-lisp_time_argument (specified_time, result)
- Lisp_Object specified_time;
- time_t *result;
-{
- if (NILP (specified_time))
- return time (result) != -1;
- else
- {
- Lisp_Object high, low;
- high = Fcar (specified_time);
- CHECK_NUMBER (high, 0);
- low = Fcdr (specified_time);
- if (CONSP (low))
- low = Fcar (low);
- CHECK_NUMBER (low, 0);
- *result = (XINT (high) << 16) + (XINT (low) & 0xffff);
- return *result >> 16 == XINT (high);
- }
-}
-
-DEFUN ("format-time-string", Fformat_time_string, Sformat_time_string, 1, 2, 0,
- "Use FORMAT-STRING to format the time TIME.\n\
-TIME is specified as (HIGH LOW . IGNORED) or (HIGH . LOW), as from\n\
-`current-time' and `file-attributes'.\n\
-FORMAT-STRING may contain %-sequences to substitute parts of the time.\n\
-%a is replaced by the abbreviated name of the day of week.\n\
-%A is replaced by the full name of the day of week.\n\
-%b is replaced by the abbreviated name of the month.\n\
-%B is replaced by the full name of the month.\n\
-%c stands for the preferred date/time format of the C locale.\n\
-%d is replaced by the day of month, zero-padded.\n\
-%D is a synonym for \"%m/%d/%y\".\n\
-%e is replaced by the day of month, blank-padded.\n\
-%h is a synonym for \"%b\".\n\
-%H is replaced by the hour (00-23).\n\
-%I is replaced by the hour (00-12).\n\
-%j is replaced by the day of the year (001-366).\n\
-%k is replaced by the hour (0-23), blank padded.\n\
-%l is replaced by the hour (1-12), blank padded.\n\
-%m is replaced by the month (01-12).\n\
-%M is replaced by the minute (00-59).\n\
-%n is a synonym for \"\\n\".\n\
-%p is replaced by AM or PM, as appropriate.\n\
-%r is a synonym for \"%I:%M:%S %p\".\n\
-%R is a synonym for \"%H:%M\".\n\
-%S is replaced by the second (00-60).\n\
-%t is a synonym for \"\\t\".\n\
-%T is a synonym for \"%H:%M:%S\".\n\
-%U is replaced by the week of the year (00-53), first day of week is Sunday.\n\
-%w is replaced by the day of week (0-6), Sunday is day 0.\n\
-%W is replaced by the week of the year (00-53), first day of week is Monday.\n\
-%x is a locale-specific synonym, which defaults to \"%D\" in the C locale.\n\
-%X is a locale-specific synonym, which defaults to \"%T\" in the C locale.\n\
-%y is replaced by the year without century (00-99).\n\
-%Y is replaced by the year with century.\n\
-%Z is replaced by the time zone abbreviation.\n\
-\n\
-The number of options reflects the `strftime' function.")
- (format_string, time)
- Lisp_Object format_string, time;
-{
- time_t value;
- int size;
-
- CHECK_STRING (format_string, 1);
-
- if (! lisp_time_argument (time, &value))
- error ("Invalid time specification");
-
- /* This is probably enough. */
- size = XSTRING (format_string)->size * 6 + 50;
-
- while (1)
- {
- char *buf = (char *) alloca (size);
- *buf = 1;
- if (emacs_strftime (buf, size, XSTRING (format_string)->data,
- localtime (&value))
- || !*buf)
- return build_string (buf);
- /* If buffer was too small, make it bigger. */
- size *= 2;
- }
-}
-
-DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 1, 0,
- "Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST ZONE).\n\
-The optional SPECIFIED-TIME should be a list of (HIGH LOW . IGNORED)\n\
-or (HIGH . LOW), as from `current-time' and `file-attributes', or `nil'\n\
-to use the current time. The list has the following nine members:\n\
-SEC is an integer between 0 and 60; SEC is 60 for a leap second, which\n\
-only some operating systems support. MINUTE is an integer between 0 and 59.\n\
-HOUR is an integer between 0 and 23. DAY is an integer between 1 and 31.\n\
-MONTH is an integer between 1 and 12. YEAR is an integer indicating the\n\
-four-digit year. DOW is the day of week, an integer between 0 and 6, where\n\
-0 is Sunday. DST is t if daylight savings time is effect, otherwise nil.\n\
-ZONE is an integer indicating the number of seconds east of Greenwich.\n\
-\(Note that Common Lisp has different meanings for DOW and ZONE.)")
- (specified_time)
- Lisp_Object specified_time;
-{
- time_t time_spec;
- struct tm save_tm;
- struct tm *decoded_time;
- Lisp_Object list_args[9];
-
- if (! lisp_time_argument (specified_time, &time_spec))
- error ("Invalid time specification");
-
- decoded_time = localtime (&time_spec);
- XSETFASTINT (list_args[0], decoded_time->tm_sec);
- XSETFASTINT (list_args[1], decoded_time->tm_min);
- XSETFASTINT (list_args[2], decoded_time->tm_hour);
- XSETFASTINT (list_args[3], decoded_time->tm_mday);
- XSETFASTINT (list_args[4], decoded_time->tm_mon + 1);
- XSETINT (list_args[5], decoded_time->tm_year + 1900);
- XSETFASTINT (list_args[6], decoded_time->tm_wday);
- list_args[7] = (decoded_time->tm_isdst)? Qt : Qnil;
-
- /* Make a copy, in case gmtime modifies the struct. */
- save_tm = *decoded_time;
- decoded_time = gmtime (&time_spec);
- if (decoded_time == 0)
- list_args[8] = Qnil;
- else
- XSETINT (list_args[8], tm_diff (&save_tm, decoded_time));
- return Flist (9, list_args);
-}
-
-DEFUN ("encode-time", Fencode_time, Sencode_time, 6, MANY, 0,
- "Convert SECOND, MINUTE, HOUR, DAY, MONTH, YEAR and ZONE to internal time.\n\
-This is the reverse operation of `decode-time', which see.\n\
-ZONE defaults to the current time zone rule. This can\n\
-be a string or t (as from `set-time-zone-rule'), or it can be a list\n\
-\(as from `current-time-zone') or an integer (as from `decode-time')\n\
-applied without consideration for daylight savings time.\n\
-\n\
-You can pass more than 7 arguments; then the first six arguments\n\
-are used as SECOND through YEAR, and the *last* argument is used as ZONE.\n\
-The intervening arguments are ignored.\n\
-This feature lets (apply 'encode-time (decode-time ...)) work.\n\
-\n\
-Out-of-range values for SEC, MINUTE, HOUR, DAY, or MONTH are allowed;\n\
-for example, a DAY of 0 means the day preceding the given month.\n\
-Year numbers less than 100 are treated just like other year numbers.\n\
-If you want them to stand for years in this century, you must do that yourself.")
- (nargs, args)
- int nargs;
- register Lisp_Object *args;
-{
- time_t time;
- struct tm tm;
- Lisp_Object zone = (nargs > 6)? args[nargs - 1] : Qnil;
-
- CHECK_NUMBER (args[0], 0); /* second */
- CHECK_NUMBER (args[1], 1); /* minute */
- CHECK_NUMBER (args[2], 2); /* hour */
- CHECK_NUMBER (args[3], 3); /* day */
- CHECK_NUMBER (args[4], 4); /* month */
- CHECK_NUMBER (args[5], 5); /* year */
-
- tm.tm_sec = XINT (args[0]);
- tm.tm_min = XINT (args[1]);
- tm.tm_hour = XINT (args[2]);
- tm.tm_mday = XINT (args[3]);
- tm.tm_mon = XINT (args[4]) - 1;
- tm.tm_year = XINT (args[5]) - 1900;
- tm.tm_isdst = -1;
-
- if (CONSP (zone))
- zone = Fcar (zone);
- if (NILP (zone))
- time = mktime (&tm);
- else
- {
- char tzbuf[100];
- char *tzstring;
- char **oldenv = environ, **newenv;
-
- if (zone == Qt)
- tzstring = "UTC0";
- else if (STRINGP (zone))
- tzstring = (char *) XSTRING (zone)->data;
- else if (INTEGERP (zone))
- {
- int abszone = abs (XINT (zone));
- sprintf (tzbuf, "XXX%s%d:%02d:%02d", "-" + (XINT (zone) < 0),
- abszone / (60*60), (abszone/60) % 60, abszone % 60);
- tzstring = tzbuf;
- }
- else
- error ("Invalid time zone specification");
-
- /* Set TZ before calling mktime; merely adjusting mktime's returned
- value doesn't suffice, since that would mishandle leap seconds. */
- set_time_zone_rule (tzstring);
-
- time = mktime (&tm);
-
- /* Restore TZ to previous value. */
- newenv = environ;
- environ = oldenv;
- xfree (newenv);
-#ifdef LOCALTIME_CACHE
- tzset ();
-#endif
- }
-
- if (time == (time_t) -1)
- error ("Specified time is not representable");
-
- return make_time (time);
-}
-
-DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0,
- "Return the current time, as a human-readable string.\n\
-Programs can use this function to decode a time,\n\
-since the number of columns in each field is fixed.\n\
-The format is `Sun Sep 16 01:03:52 1973'.\n\
-If an argument is given, it specifies a time to format\n\
-instead of the current time. The argument should have the form:\n\
- (HIGH . LOW)\n\
-or the form:\n\
- (HIGH LOW . IGNORED).\n\
-Thus, you can use times obtained from `current-time'\n\
-and from `file-attributes'.")
- (specified_time)
- Lisp_Object specified_time;
-{
- time_t value;
- char buf[30];
- register char *tem;
-
- if (! lisp_time_argument (specified_time, &value))
- value = -1;
- tem = (char *) ctime (&value);
-
- strncpy (buf, tem, 24);
- buf[24] = 0;
-
- return build_string (buf);
-}
-
-#define TM_YEAR_BASE 1900
-
-/* Yield A - B, measured in seconds.
- This function is copied from the GNU C Library. */
-static int
-tm_diff (a, b)
- struct tm *a, *b;
-{
- /* Compute intervening leap days correctly even if year is negative.
- Take care to avoid int overflow in leap day calculations,
- but it's OK to assume that A and B are close to each other. */
- int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
- int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
- int a100 = a4 / 25 - (a4 % 25 < 0);
- int b100 = b4 / 25 - (b4 % 25 < 0);
- int a400 = a100 >> 2;
- int b400 = b100 >> 2;
- int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
- int years = a->tm_year - b->tm_year;
- int days = (365 * years + intervening_leap_days
- + (a->tm_yday - b->tm_yday));
- return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
- + (a->tm_min - b->tm_min))
- + (a->tm_sec - b->tm_sec));
-}
-
-DEFUN ("current-time-zone", Fcurrent_time_zone, Scurrent_time_zone, 0, 1, 0,
- "Return the offset and name for the local time zone.\n\
-This returns a list of the form (OFFSET NAME).\n\
-OFFSET is an integer number of seconds ahead of UTC (east of Greenwich).\n\
- A negative value means west of Greenwich.\n\
-NAME is a string giving the name of the time zone.\n\
-If an argument is given, it specifies when the time zone offset is determined\n\
-instead of using the current time. The argument should have the form:\n\
- (HIGH . LOW)\n\
-or the form:\n\
- (HIGH LOW . IGNORED).\n\
-Thus, you can use times obtained from `current-time'\n\
-and from `file-attributes'.\n\
-\n\
-Some operating systems cannot provide all this information to Emacs;\n\
-in this case, `current-time-zone' returns a list containing nil for\n\
-the data it can't find.")
- (specified_time)
- Lisp_Object specified_time;
-{
- time_t value;
- struct tm *t;
-
- if (lisp_time_argument (specified_time, &value)
- && (t = gmtime (&value)) != 0)
- {
- struct tm gmt;
- int offset;
- char *s, buf[6];
-
- gmt = *t; /* Make a copy, in case localtime modifies *t. */
- t = localtime (&value);
- offset = tm_diff (t, &gmt);
- s = 0;
-#ifdef HAVE_TM_ZONE
- if (t->tm_zone)
- s = (char *)t->tm_zone;
-#else /* not HAVE_TM_ZONE */
-#ifdef HAVE_TZNAME
- if (t->tm_isdst == 0 || t->tm_isdst == 1)
- s = tzname[t->tm_isdst];
-#endif
-#endif /* not HAVE_TM_ZONE */
- if (!s)
- {
- /* No local time zone name is available; use "+-NNNN" instead. */
- int am = (offset < 0 ? -offset : offset) / 60;
- sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60);
- s = buf;
- }
- return Fcons (make_number (offset), Fcons (build_string (s), Qnil));
- }
- else
- return Fmake_list (2, Qnil);
-}
-
-/* This holds the value of `environ' produced by the previous
- call to Fset_time_zone_rule, or 0 if Fset_time_zone_rule
- has never been called. */
-static char **environbuf;
-
-DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0,
- "Set the local time zone using TZ, a string specifying a time zone rule.\n\
-If TZ is nil, use implementation-defined default time zone information.\n\
-If TZ is t, use Universal Time.")
- (tz)
- Lisp_Object tz;
-{
- char *tzstring;
-
- if (NILP (tz))
- tzstring = 0;
- else if (tz == Qt)
- tzstring = "UTC0";
- else
- {
- CHECK_STRING (tz, 0);
- tzstring = (char *) XSTRING (tz)->data;
- }
-
- set_time_zone_rule (tzstring);
- if (environbuf)
- free (environbuf);
- environbuf = environ;
-
- return Qnil;
-}
-
-/* These two values are known to load tz files in buggy implementations.
- Their values shouldn't matter in non-buggy implementations.
- We don't use string literals for these strings,
- since if a string in the environment is in readonly
- storage, it runs afoul of bugs in SVR4 and Solaris 2.3.
- See Sun bugs 1113095 and 1114114, ``Timezone routines
- improperly modify environment''. */
-
-static char set_time_zone_rule_tz1[] = "TZ=GMT0";
-static char set_time_zone_rule_tz2[] = "TZ=GMT1";
-
-/* Set the local time zone rule to TZSTRING.
- This allocates memory into `environ', which it is the caller's
- responsibility to free. */
-void
-set_time_zone_rule (tzstring)
- char *tzstring;
-{
- int envptrs;
- char **from, **to, **newenv;
-
- /* Make the ENVIRON vector longer with room for TZSTRING. */
- for (from = environ; *from; from++)
- continue;
- envptrs = from - environ + 2;
- newenv = to = (char **) xmalloc (envptrs * sizeof (char *)
- + (tzstring ? strlen (tzstring) + 4 : 0));
-
- /* Add TZSTRING to the end of environ, as a value for TZ. */
- if (tzstring)
- {
- char *t = (char *) (to + envptrs);
- strcpy (t, "TZ=");
- strcat (t, tzstring);
- *to++ = t;
- }
-
- /* Copy the old environ vector elements into NEWENV,
- but don't copy the TZ variable.
- So we have only one definition of TZ, which came from TZSTRING. */
- for (from = environ; *from; from++)
- if (strncmp (*from, "TZ=", 3) != 0)
- *to++ = *from;
- *to = 0;
-
- environ = newenv;
-
- /* If we do have a TZSTRING, NEWENV points to the vector slot where
- the TZ variable is stored. If we do not have a TZSTRING,
- TO points to the vector slot which has the terminating null. */
-
-#ifdef LOCALTIME_CACHE
- {
- /* In SunOS 4.1.3_U1 and 4.1.4, if TZ has a value like
- "US/Pacific" that loads a tz file, then changes to a value like
- "XXX0" that does not load a tz file, and then changes back to
- its original value, the last change is (incorrectly) ignored.
- Also, if TZ changes twice in succession to values that do
- not load a tz file, tzset can dump core (see Sun bug#1225179).
- The following code works around these bugs. */
-
- if (tzstring)
- {
- /* Temporarily set TZ to a value that loads a tz file
- and that differs from tzstring. */
- char *tz = *newenv;
- *newenv = (strcmp (tzstring, set_time_zone_rule_tz1 + 3) == 0
- ? set_time_zone_rule_tz2 : set_time_zone_rule_tz1);
- tzset ();
- *newenv = tz;
- }
- else
- {
- /* The implied tzstring is unknown, so temporarily set TZ to
- two different values that each load a tz file. */
- *to = set_time_zone_rule_tz1;
- to[1] = 0;
- tzset ();
- *to = set_time_zone_rule_tz2;
- tzset ();
- *to = 0;
- }
-
- /* Now TZ has the desired value, and tzset can be invoked safely. */
- }
-
- tzset ();
-#endif
-}
-
-void
-insert1 (arg)
- Lisp_Object arg;
-{
- Finsert (1, &arg);
-}
-
-
-/* Callers passing one argument to Finsert need not gcpro the
- argument "array", since the only element of the array will
- not be used after calling insert or insert_from_string, so
- we don't care if it gets trashed. */
-
-DEFUN ("insert", Finsert, Sinsert, 0, MANY, 0,
- "Insert the arguments, either strings or characters, at point.\n\
-Point moves forward so that it ends up after the inserted text.\n\
-Any other markers at the point of insertion remain before the 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 (INTEGERP (tem))
- {
- str[0] = XINT (tem);
- insert (str, 1);
- }
- else if (STRINGP (tem))
- {
- insert_from_string (tem, 0, XSTRING (tem)->size, 0);
- }
- else
- {
- tem = wrong_type_argument (Qchar_or_string_p, tem);
- goto retry;
- }
- }
-
- return Qnil;
-}
-
-DEFUN ("insert-and-inherit", Finsert_and_inherit, Sinsert_and_inherit,
- 0, MANY, 0,
- "Insert the arguments at point, inheriting properties from adjoining text.\n\
-Point moves forward so that it ends up after the inserted text.\n\
-Any other markers at the point of insertion remain before the 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 (INTEGERP (tem))
- {
- str[0] = XINT (tem);
- insert_and_inherit (str, 1);
- }
- else if (STRINGP (tem))
- {
- insert_from_string (tem, 0, XSTRING (tem)->size, 1);
- }
- 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,
- "Insert strings or characters at point, relocating markers after the text.\n\
-Point moves forward so that it ends up after the inserted text.\n\
-Any other markers at the point of insertion also end up after the 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 (INTEGERP (tem))
- {
- str[0] = XINT (tem);
- insert_before_markers (str, 1);
- }
- else if (STRINGP (tem))
- {
- insert_from_string_before_markers (tem, 0, XSTRING (tem)->size, 0);
- }
- else
- {
- tem = wrong_type_argument (Qchar_or_string_p, tem);
- goto retry;
- }
- }
-
- return Qnil;
-}
-
-DEFUN ("insert-before-markers-and-inherit", Finsert_and_inherit_before_markers,
- Sinsert_and_inherit_before_markers, 0, MANY, 0,
- "Insert text at point, relocating markers and inheriting properties.\n\
-Point moves forward so that it ends up after the inserted text.\n\
-Any other markers at the point of insertion also end up after the 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 (INTEGERP (tem))
- {
- str[0] = XINT (tem);
- insert_before_markers_and_inherit (str, 1);
- }
- else if (STRINGP (tem))
- {
- insert_from_string_before_markers (tem, 0, XSTRING (tem)->size, 1);
- }
- else
- {
- tem = wrong_type_argument (Qchar_or_string_p, tem);
- goto retry;
- }
- }
-
- return Qnil;
-}
-
-DEFUN ("insert-char", Finsert_char, Sinsert_char, 2, 3, 0,
- "Insert COUNT (second arg) copies of CHARACTER (first arg).\n\
-Point and all markers are affected as in the function `insert'.\n\
-Both arguments are required.\n\
-The optional third arg INHERIT, if non-nil, says to inherit text properties\n\
-from adjoining text, if those properties are sticky.")
- (character, count, inherit)
- Lisp_Object character, count, inherit;
-{
- register unsigned char *string;
- register int strlen;
- register int i, n;
-
- CHECK_NUMBER (character, 0);
- CHECK_NUMBER (count, 1);
-
- n = XINT (count);
- if (n <= 0)
- return Qnil;
- strlen = min (n, 256);
- string = (unsigned char *) alloca (strlen);
- for (i = 0; i < strlen; i++)
- string[i] = XFASTINT (character);
- while (n >= strlen)
- {
- if (!NILP (inherit))
- insert_and_inherit (string, strlen);
- else
- insert (string, strlen);
- n -= strlen;
- }
- if (n > 0)
- {
- if (!NILP (inherit))
- insert_and_inherit (string, n);
- else
- insert (string, n);
- }
- return Qnil;
-}
-
-
-/* Making strings from buffer contents. */
-
-/* Return a Lisp_String containing the text of the current buffer from
- START to END. If text properties are in use and the current buffer
- has properties in the range specified, the resulting string will also
- have them, if PROPS is nonzero.
-
- We don't want to use plain old make_string here, because it calls
- make_uninit_string, which can cause the buffer arena to be
- compacted. make_string has no way of knowing that the data has
- been moved, and thus copies the wrong data into the string. This
- doesn't effect most of the other users of make_string, so it should
- be left as is. But we should use this function when conjuring
- buffer substrings. */
-
-Lisp_Object
-make_buffer_string (start, end, props)
- int start, end;
- int props;
-{
- Lisp_Object result, tem, tem1;
-
- if (start < GPT && GPT < end)
- move_gap (start);
-
- result = make_uninit_string (end - start);
- bcopy (&FETCH_CHAR (start), XSTRING (result)->data, end - start);
-
- /* If desired, update and copy the text properties. */
-#ifdef USE_TEXT_PROPERTIES
- if (props)
- {
- update_buffer_properties (start, end);
-
- tem = Fnext_property_change (make_number (start), Qnil, make_number (end));
- tem1 = Ftext_properties_at (make_number (start), Qnil);
-
- if (XINT (tem) != end || !NILP (tem1))
- copy_intervals_to_string (result, current_buffer, start, end - start);
- }
-#endif
-
- return result;
-}
-
-/* Call Vbuffer_access_fontify_functions for the range START ... END
- in the current buffer, if necessary. */
-
-static void
-update_buffer_properties (start, end)
- int start, end;
-{
-#ifdef USE_TEXT_PROPERTIES
- /* If this buffer has some access functions,
- call them, specifying the range of the buffer being accessed. */
- if (!NILP (Vbuffer_access_fontify_functions))
- {
- Lisp_Object args[3];
- Lisp_Object tem;
-
- args[0] = Qbuffer_access_fontify_functions;
- XSETINT (args[1], start);
- XSETINT (args[2], end);
-
- /* But don't call them if we can tell that the work
- has already been done. */
- if (!NILP (Vbuffer_access_fontified_property))
- {
- tem = Ftext_property_any (args[1], args[2],
- Vbuffer_access_fontified_property,
- Qnil, Qnil);
- if (! NILP (tem))
- Frun_hook_with_args (3, args);
- }
- else
- Frun_hook_with_args (3, args);
- }
-#endif
-}
-
-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 START and END are character positions;\n\
-they can be in either order.")
- (start, end)
- Lisp_Object start, end;
-{
- register int b, e;
-
- validate_region (&start, &end);
- b = XINT (start);
- e = XINT (end);
-
- return make_buffer_string (b, e, 1);
-}
-
-DEFUN ("buffer-substring-no-properties", Fbuffer_substring_no_properties,
- Sbuffer_substring_no_properties, 2, 2, 0,
- "Return the characters of part of the buffer, without the text properties.\n\
-The two arguments START and END are character positions;\n\
-they can be in either order.")
- (start, end)
- Lisp_Object start, end;
-{
- register int b, e;
-
- validate_region (&start, &end);
- b = XINT (start);
- e = XINT (end);
-
- return make_buffer_string (b, e, 0);
-}
-
-DEFUN ("buffer-string", Fbuffer_string, Sbuffer_string, 0, 0, 0,
- "Return the contents of the current buffer as a string.\n\
-If narrowing is in effect, this function returns only the visible part\n\
-of the buffer.")
- ()
-{
- return make_buffer_string (BEGV, ZV, 1);
-}
-
-DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring,
- 1, 3, 0,
- "Insert before point a substring of the contents of 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, start, end)
- Lisp_Object buf, start, end;
-{
- register int b, e, temp;
- register struct buffer *bp, *obuf;
- Lisp_Object buffer;
-
- buffer = Fget_buffer (buf);
- if (NILP (buffer))
- nsberror (buf);
- bp = XBUFFER (buffer);
- if (NILP (bp->name))
- error ("Selecting deleted buffer");
-
- if (NILP (start))
- b = BUF_BEGV (bp);
- else
- {
- CHECK_NUMBER_COERCE_MARKER (start, 0);
- b = XINT (start);
- }
- if (NILP (end))
- e = BUF_ZV (bp);
- else
- {
- CHECK_NUMBER_COERCE_MARKER (end, 1);
- e = XINT (end);
- }
-
- if (b > e)
- temp = b, b = e, e = temp;
-
- if (!(BUF_BEGV (bp) <= b && e <= BUF_ZV (bp)))
- args_out_of_range (start, end);
-
- obuf = current_buffer;
- set_buffer_internal_1 (bp);
- update_buffer_properties (b, e);
- set_buffer_internal_1 (obuf);
-
- insert_from_buffer (bp, b, e - b, 0);
- return Qnil;
-}
-
-DEFUN ("compare-buffer-substrings", Fcompare_buffer_substrings, Scompare_buffer_substrings,
- 6, 6, 0,
- "Compare two substrings of two buffers; return result as number.\n\
-the value is -N if first string is less after N-1 chars,\n\
-+N if first string is greater after N-1 chars, or 0 if strings match.\n\
-Each substring is represented as three arguments: BUFFER, START and END.\n\
-That makes six args in all, three for each substring.\n\n\
-The value of `case-fold-search' in the current buffer\n\
-determines whether case is significant or ignored.")
- (buffer1, start1, end1, buffer2, start2, end2)
- Lisp_Object buffer1, start1, end1, buffer2, start2, end2;
-{
- register int begp1, endp1, begp2, endp2, temp, len1, len2, length, i;
- register struct buffer *bp1, *bp2;
- register Lisp_Object *trt
- = (!NILP (current_buffer->case_fold_search)
- ? XCHAR_TABLE (current_buffer->case_canon_table)->contents : 0);
-
- /* Find the first buffer and its substring. */
-
- if (NILP (buffer1))
- bp1 = current_buffer;
- else
- {
- Lisp_Object buf1;
- buf1 = Fget_buffer (buffer1);
- if (NILP (buf1))
- nsberror (buffer1);
- bp1 = XBUFFER (buf1);
- if (NILP (bp1->name))
- error ("Selecting deleted buffer");
- }
-
- if (NILP (start1))
- begp1 = BUF_BEGV (bp1);
- else
- {
- CHECK_NUMBER_COERCE_MARKER (start1, 1);
- begp1 = XINT (start1);
- }
- if (NILP (end1))
- endp1 = BUF_ZV (bp1);
- else
- {
- CHECK_NUMBER_COERCE_MARKER (end1, 2);
- endp1 = XINT (end1);
- }
-
- if (begp1 > endp1)
- temp = begp1, begp1 = endp1, endp1 = temp;
-
- if (!(BUF_BEGV (bp1) <= begp1
- && begp1 <= endp1
- && endp1 <= BUF_ZV (bp1)))
- args_out_of_range (start1, end1);
-
- /* Likewise for second substring. */
-
- if (NILP (buffer2))
- bp2 = current_buffer;
- else
- {
- Lisp_Object buf2;
- buf2 = Fget_buffer (buffer2);
- if (NILP (buf2))
- nsberror (buffer2);
- bp2 = XBUFFER (buf2);
- if (NILP (bp2->name))
- error ("Selecting deleted buffer");
- }
-
- if (NILP (start2))
- begp2 = BUF_BEGV (bp2);
- else
- {
- CHECK_NUMBER_COERCE_MARKER (start2, 4);
- begp2 = XINT (start2);
- }
- if (NILP (end2))
- endp2 = BUF_ZV (bp2);
- else
- {
- CHECK_NUMBER_COERCE_MARKER (end2, 5);
- endp2 = XINT (end2);
- }
-
- if (begp2 > endp2)
- temp = begp2, begp2 = endp2, endp2 = temp;
-
- if (!(BUF_BEGV (bp2) <= begp2
- && begp2 <= endp2
- && endp2 <= BUF_ZV (bp2)))
- args_out_of_range (start2, end2);
-
- len1 = endp1 - begp1;
- len2 = endp2 - begp2;
- length = len1;
- if (len2 < length)
- length = len2;
-
- for (i = 0; i < length; i++)
- {
- int c1 = *BUF_CHAR_ADDRESS (bp1, begp1 + i);
- int c2 = *BUF_CHAR_ADDRESS (bp2, begp2 + i);
- if (trt)
- {
- c1 = trt[c1];
- c2 = trt[c2];
- }
- if (c1 < c2)
- return make_number (- 1 - i);
- if (c1 > c2)
- return make_number (i + 1);
- }
-
- /* The strings match as far as they go.
- If one is shorter, that one is less. */
- if (length < len1)
- return make_number (length + 1);
- else if (length < len2)
- return make_number (- length - 1);
-
- /* Same length too => they are equal. */
- return make_number (0);
-}
-
-static Lisp_Object
-subst_char_in_region_unwind (arg)
- Lisp_Object arg;
-{
- return current_buffer->undo_list = arg;
-}
-
-static Lisp_Object
-subst_char_in_region_unwind_1 (arg)
- Lisp_Object arg;
-{
- return current_buffer->filename = arg;
-}
-
-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;
- int changed = 0;
- int count = specpdl_ptr - specpdl;
-
- validate_region (&start, &end);
- CHECK_NUMBER (fromchar, 2);
- CHECK_NUMBER (tochar, 3);
-
- pos = XINT (start);
- stop = XINT (end);
- look = XINT (fromchar);
-
- /* If we don't want undo, turn off putting stuff on the list.
- That's faster than getting rid of things,
- and it prevents even the entry for a first change.
- Also inhibit locking the file. */
- if (!NILP (noundo))
- {
- record_unwind_protect (subst_char_in_region_unwind,
- current_buffer->undo_list);
- current_buffer->undo_list = Qt;
- /* Don't do file-locking. */
- record_unwind_protect (subst_char_in_region_unwind_1,
- current_buffer->filename);
- current_buffer->filename = Qnil;
- }
-
- while (pos < stop)
- {
- if (FETCH_CHAR (pos) == look)
- {
- if (! changed)
- {
- modify_region (current_buffer, XINT (start), stop);
-
- if (! NILP (noundo))
- {
- if (MODIFF - 1 == SAVE_MODIFF)
- SAVE_MODIFF++;
- if (MODIFF - 1 == current_buffer->auto_save_modified)
- current_buffer->auto_save_modified++;
- }
-
- changed = 1;
- }
-
- if (NILP (noundo))
- record_change (pos, 1);
- FETCH_CHAR (pos) = XINT (tochar);
- }
- pos++;
- }
-
- if (changed)
- signal_after_change (XINT (start),
- stop - XINT (start), stop - XINT (start));
-
- unbind_to (count, Qnil);
- return Qnil;
-}
-
-DEFUN ("translate-region", Ftranslate_region, Stranslate_region, 3, 3, 0,
- "From START to END, translate characters according to TABLE.\n\
-TABLE is a string; the Nth character in it is the mapping\n\
-for the character with code N. Returns the number of characters changed.")
- (start, end, table)
- Lisp_Object start;
- Lisp_Object end;
- register Lisp_Object table;
-{
- register int pos, stop; /* Limits of the region. */
- register unsigned char *tt; /* Trans table. */
- register int oc; /* Old character. */
- register int nc; /* New character. */
- int cnt; /* Number of changes made. */
- Lisp_Object z; /* Return. */
- int size; /* Size of translate table. */
-
- validate_region (&start, &end);
- CHECK_STRING (table, 2);
-
- size = XSTRING (table)->size;
- tt = XSTRING (table)->data;
-
- pos = XINT (start);
- stop = XINT (end);
- modify_region (current_buffer, pos, stop);
-
- cnt = 0;
- for (; pos < stop; ++pos)
- {
- oc = FETCH_CHAR (pos);
- if (oc < size)
- {
- nc = tt[oc];
- if (nc != oc)
- {
- record_change (pos, 1);
- FETCH_CHAR (pos) = nc;
- signal_after_change (pos, 1, 1);
- ++cnt;
- }
- }
- }
-
- XSETFASTINT (z, cnt);
- return (z);
-}
-
-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\
-positions (integers or markers) specifying the stretch to be deleted.")
- (start, end)
- Lisp_Object start, end;
-{
- validate_region (&start, &end);
- del_range (XINT (start), XINT (end));
- return Qnil;
-}
-
-DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
- "Remove restrictions (narrowing) from current buffer.\n\
-This allows the buffer's full text to be seen and edited.")
- ()
-{
- BEGV = BEG;
- SET_BUF_ZV (current_buffer, Z);
- current_buffer->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\
-See also `save-restriction'.\n\
-\n\
-When calling from a program, pass two arguments; positions (integers\n\
-or markers) bounding the text that should remain visible.")
- (start, end)
- register Lisp_Object start, end;
-{
- CHECK_NUMBER_COERCE_MARKER (start, 0);
- CHECK_NUMBER_COERCE_MARKER (end, 1);
-
- if (XINT (start) > XINT (end))
- {
- Lisp_Object tem;
- tem = start; start = end; end = tem;
- }
-
- if (!(BEG <= XINT (start) && XINT (start) <= XINT (end) && XINT (end) <= Z))
- args_out_of_range (start, end);
-
- BEGV = XFASTINT (start);
- SET_BUF_ZV (current_buffer, XFASTINT (end));
- if (PT < XFASTINT (start))
- SET_PT (XFASTINT (start));
- if (PT > XFASTINT (end))
- SET_PT (XFASTINT (end));
- current_buffer->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 mh and is considered "outside" the saved region. */
- XSETFASTINT (bottom, BEGV - BEG);
- XSETFASTINT (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);
- current_buffer->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 BODY, saving and restoring current buffer's restrictions.\n\
-The buffer's restrictions make parts of the beginning and end invisible.\n\
-\(They are set up with `narrow-to-region' and eliminated with `widen'.)\n\
-This special form, `save-restriction', saves the current buffer's restrictions\n\
-when it is entered, and restores them when it is exited.\n\
-So any `narrow-to-region' within BODY lasts only until the end of the form.\n\
-The old restrictions settings are restored\n\
-even in case of abnormal exit (throw or error).\n\
-\n\
-The value returned is the value of the last form in BODY.\n\
-\n\
-`save-restriction' can get 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:\n\
- (save-excursion (save-restriction ...))")
- (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);
- return unbind_to (count, val);
-}
-
-/* Buffer for the most recent text displayed by Fmessage. */
-static char *message_text;
-
-/* Allocated length of that buffer. */
-static int message_length;
-
-DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
- "Print a one-line message at the bottom of the screen.\n\
-The first argument is a format control string, and the rest are data\n\
-to be formatted under control of the string. See `format' for details.\n\
-\n\
-If the first argument is nil, clear any existing message; let the\n\
-minibuffer contents show.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
- if (NILP (args[0]))
- {
- message (0);
- return Qnil;
- }
- else
- {
- register Lisp_Object val;
- val = Fformat (nargs, args);
- /* Copy the data so that it won't move when we GC. */
- if (! message_text)
- {
- message_text = (char *)xmalloc (80);
- message_length = 80;
- }
- if (XSTRING (val)->size > message_length)
- {
- message_length = XSTRING (val)->size;
- message_text = (char *)xrealloc (message_text, message_length);
- }
- bcopy (XSTRING (val)->data, message_text, XSTRING (val)->size);
- message2 (message_text, XSTRING (val)->size);
- return val;
- }
-}
-
-DEFUN ("message-box", Fmessage_box, Smessage_box, 1, MANY, 0,
- "Display a message, in a dialog box if possible.\n\
-If a dialog box is not available, use the echo area.\n\
-The first argument is a format control string, and the rest are data\n\
-to be formatted under control of the string. See `format' for details.\n\
-\n\
-If the first argument is nil, clear any existing message; let the\n\
-minibuffer contents show.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
- if (NILP (args[0]))
- {
- message (0);
- return Qnil;
- }
- else
- {
- register Lisp_Object val;
- val = Fformat (nargs, args);
-#ifdef HAVE_MENUS
- {
- Lisp_Object pane, menu, obj;
- struct gcpro gcpro1;
- pane = Fcons (Fcons (build_string ("OK"), Qt), Qnil);
- GCPRO1 (pane);
- menu = Fcons (val, pane);
- obj = Fx_popup_dialog (Qt, menu);
- UNGCPRO;
- return val;
- }
-#else /* not HAVE_MENUS */
- /* Copy the data so that it won't move when we GC. */
- if (! message_text)
- {
- message_text = (char *)xmalloc (80);
- message_length = 80;
- }
- if (XSTRING (val)->size > message_length)
- {
- message_length = XSTRING (val)->size;
- message_text = (char *)xrealloc (message_text, message_length);
- }
- bcopy (XSTRING (val)->data, message_text, XSTRING (val)->size);
- message2 (message_text, XSTRING (val)->size);
- return val;
-#endif /* not HAVE_MENUS */
- }
-}
-#ifdef HAVE_MENUS
-extern Lisp_Object last_nonmenu_event;
-#endif
-
-DEFUN ("message-or-box", Fmessage_or_box, Smessage_or_box, 1, MANY, 0,
- "Display a message in a dialog box or in the echo area.\n\
-If this command was invoked with the mouse, use a dialog box.\n\
-Otherwise, use the echo area.\n\
-The first argument is a format control string, and the rest are data\n\
-to be formatted under control of the string. See `format' for details.\n\
-\n\
-If the first argument is nil, clear any existing message; let the\n\
-minibuffer contents show.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
-#ifdef HAVE_MENUS
- if (NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
- return Fmessage_box (nargs, args);
-#endif
- return Fmessage (nargs, args);
-}
-
-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\
-The other arguments are substituted into it to make the result, a string.\n\
-It may contain %-sequences meaning to substitute the next argument.\n\
-%s means print a string argument. Actually, prints any object, with `princ'.\n\
-%d means print as number in decimal (%o octal, %x hex).\n\
-%e means print a number in exponential notation.\n\
-%f means print a number in decimal-point notation.\n\
-%g means print a number in exponential notation\n\
- or decimal-point notation, whichever uses fewer characters.\n\
-%c means print a number as a single character.\n\
-%S means print any object as an s-expression (using prin1).\n\
- The argument used for %d, %o, %x, %e, %f, %g or %c must be a number.\n\
-Use %% to put a single % into the output.")
- (nargs, args)
- int nargs;
- register Lisp_Object *args;
-{
- register int n; /* The number of the next arg to substitute */
- register int total = 5; /* An estimate of the final length */
- char *buf;
- register unsigned char *format, *end;
- int length;
- 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;
- end = format + XSTRING (args[0])->size;
-
- n = 0;
- while (format != end)
- if (*format++ == '%')
- {
- int minlen;
-
- /* Process a numeric arg and skip it. */
- minlen = atoi (format);
- if (minlen < 0)
- minlen = - minlen;
-
- while ((*format >= '0' && *format <= '9')
- || *format == '-' || *format == ' ' || *format == '.')
- format++;
-
- if (*format == '%')
- format++;
- else if (++n >= nargs)
- error ("Not enough arguments for format string");
- else if (*format == 'S')
- {
- /* For `S', prin1 the argument and then treat like a string. */
- register Lisp_Object tem;
- tem = Fprin1_to_string (args[n], Qnil);
- args[n] = tem;
- goto string;
- }
- else if (SYMBOLP (args[n]))
- {
- XSETSTRING (args[n], XSYMBOL (args[n])->name);
- goto string;
- }
- else if (STRINGP (args[n]))
- {
- string:
- if (*format != 's' && *format != 'S')
- error ("format specifier doesn't match argument type");
- total += XSTRING (args[n])->size;
- /* We have to put an arbitrary limit on minlen
- since otherwise it could make alloca fail. */
- if (minlen < XSTRING (args[n])->size + 1000)
- total += minlen;
- }
- /* Would get MPV otherwise, since Lisp_Int's `point' to low memory. */
- else if (INTEGERP (args[n]) && *format != 's')
- {
-#ifdef LISP_FLOAT_TYPE
- /* The following loop assumes the Lisp type indicates
- the proper way to pass the argument.
- So make sure we have a flonum if the argument should
- be a double. */
- if (*format == 'e' || *format == 'f' || *format == 'g')
- args[n] = Ffloat (args[n]);
-#endif
- total += 30;
- /* We have to put an arbitrary limit on minlen
- since otherwise it could make alloca fail. */
- if (minlen < 1000)
- total += minlen;
- }
-#ifdef LISP_FLOAT_TYPE
- else if (FLOATP (args[n]) && *format != 's')
- {
- if (! (*format == 'e' || *format == 'f' || *format == 'g'))
- args[n] = Ftruncate (args[n]);
- total += 30;
- /* We have to put an arbitrary limit on minlen
- since otherwise it could make alloca fail. */
- if (minlen < 1000)
- total += minlen;
- }
-#endif
- else
- {
- /* Anything but a string, convert to a string using princ. */
- register Lisp_Object tem;
- tem = Fprin1_to_string (args[n], Qt);
- args[n] = tem;
- goto string;
- }
- }
-
- {
- register int nstrings = n + 1;
-
- /* Allocate twice as many strings as we have %-escapes; floats occupy
- two slots, and we're not sure how many of those we have. */
- register unsigned char **strings
- = (unsigned char **) alloca (2 * nstrings * sizeof (unsigned char *));
- int i;
-
- i = 0;
- for (n = 0; n < nstrings; n++)
- {
- if (n >= nargs)
- strings[i++] = (unsigned char *) "";
- else if (INTEGERP (args[n]))
- /* We checked above that the corresponding format effector
- isn't %s, which would cause MPV. */
- strings[i++] = (unsigned char *) XINT (args[n]);
-#ifdef LISP_FLOAT_TYPE
- else if (FLOATP (args[n]))
- {
- union { double d; char *half[2]; } u;
-
- u.d = XFLOAT (args[n])->data;
- strings[i++] = (unsigned char *) u.half[0];
- strings[i++] = (unsigned char *) u.half[1];
- }
-#endif
- else if (i == 0)
- /* The first string is treated differently
- because it is the format string. */
- strings[i++] = XSTRING (args[n])->data;
- else
- strings[i++] = (unsigned char *) XSTRING (args[n]);
- }
-
- /* Make room in result for all the non-%-codes in the control string. */
- total += XSTRING (args[0])->size;
-
- /* Format it in bigger and bigger buf's until it all fits. */
- while (1)
- {
- buf = (char *) alloca (total + 1);
- buf[total - 1] = 0;
-
- length = doprnt_lisp (buf, total + 1, strings[0],
- end, i-1, strings + 1);
- if (buf[total - 1] == 0)
- break;
-
- total *= 2;
- }
- }
-
- /* UNGCPRO; */
- return make_string (buf, length);
-}
-
-/* VARARGS 1 */
-Lisp_Object
-#ifdef NO_ARG_ARRAY
-format1 (string1, arg0, arg1, arg2, arg3, arg4)
- EMACS_INT arg0, arg1, arg2, arg3, arg4;
-#else
-format1 (string1)
-#endif
- char *string1;
-{
- char buf[100];
-#ifdef NO_ARG_ARRAY
- EMACS_INT args[5];
- args[0] = arg0;
- args[1] = arg1;
- args[2] = arg2;
- args[3] = arg3;
- args[4] = arg4;
- doprnt (buf, sizeof buf, string1, (char *)0, 5, args);
-#else
- doprnt (buf, sizeof buf, string1, (char *)0, 5, &string1 + 1);
-#endif
- return build_string (buf);
-}
-
-DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0,
- "Return t if two characters match, optionally ignoring case.\n\
-Both arguments must be characters (i.e. integers).\n\
-Case is ignored if `case-fold-search' is non-nil in the current buffer.")
- (c1, c2)
- register Lisp_Object c1, c2;
-{
- Lisp_Object *downcase = DOWNCASE_TABLE;
- CHECK_NUMBER (c1, 0);
- CHECK_NUMBER (c2, 1);
-
- if (!NILP (current_buffer->case_fold_search)
- ? ((XINT (downcase[0xff & XFASTINT (c1)])
- == XINT (downcase[0xff & XFASTINT (c2)]))
- && (XFASTINT (c1) & ~0xff) == (XFASTINT (c2) & ~0xff))
- : XINT (c1) == XINT (c2))
- return Qt;
- return Qnil;
-}
-
-/* Transpose the markers in two regions of the current buffer, and
- adjust the ones between them if necessary (i.e.: if the regions
- differ in size).
-
- Traverses the entire marker list of the buffer to do so, adding an
- appropriate amount to some, subtracting from some, and leaving the
- rest untouched. Most of this is copied from adjust_markers in insdel.c.
-
- It's the caller's job to see that (start1 <= end1 <= start2 <= end2). */
-
-void
-transpose_markers (start1, end1, start2, end2)
- register int start1, end1, start2, end2;
-{
- register int amt1, amt2, diff, mpos;
- register Lisp_Object marker;
-
- /* Update point as if it were a marker. */
- if (PT < start1)
- ;
- else if (PT < end1)
- TEMP_SET_PT (PT + (end2 - end1));
- else if (PT < start2)
- TEMP_SET_PT (PT + (end2 - start2) - (end1 - start1));
- else if (PT < end2)
- TEMP_SET_PT (PT - (start2 - start1));
-
- /* We used to adjust the endpoints here to account for the gap, but that
- isn't good enough. Even if we assume the caller has tried to move the
- gap out of our way, it might still be at start1 exactly, for example;
- and that places it `inside' the interval, for our purposes. The amount
- of adjustment is nontrivial if there's a `denormalized' marker whose
- position is between GPT and GPT + GAP_SIZE, so it's simpler to leave
- the dirty work to Fmarker_position, below. */
-
- /* The difference between the region's lengths */
- diff = (end2 - start2) - (end1 - start1);
-
- /* For shifting each marker in a region by the length of the other
- * region plus the distance between the regions.
- */
- amt1 = (end2 - start2) + (start2 - end1);
- amt2 = (end1 - start1) + (start2 - end1);
-
- for (marker = BUF_MARKERS (current_buffer); !NILP (marker);
- marker = XMARKER (marker)->chain)
- {
- mpos = Fmarker_position (marker);
- if (mpos >= start1 && mpos < end2)
- {
- if (mpos < end1)
- mpos += amt1;
- else if (mpos < start2)
- mpos += diff;
- else
- mpos -= amt2;
- if (mpos > GPT) mpos += GAP_SIZE;
- XMARKER (marker)->bufpos = mpos;
- }
- }
-}
-
-DEFUN ("transpose-regions", Ftranspose_regions, Stranspose_regions, 4, 5, 0,
- "Transpose region START1 to END1 with START2 to END2.\n\
-The regions may not be overlapping, because the size of the buffer is\n\
-never changed in a transposition.\n\
-\n\
-Optional fifth arg LEAVE_MARKERS, if non-nil, means don't transpose\n\
-any markers that happen to be located in the regions.\n\
-\n\
-Transposing beyond buffer boundaries is an error.")
- (startr1, endr1, startr2, endr2, leave_markers)
- Lisp_Object startr1, endr1, startr2, endr2, leave_markers;
-{
- register int start1, end1, start2, end2,
- gap, len1, len_mid, len2;
- unsigned char *start1_addr, *start2_addr, *temp;
-
-#ifdef USE_TEXT_PROPERTIES
- INTERVAL cur_intv, tmp_interval1, tmp_interval_mid, tmp_interval2;
- cur_intv = BUF_INTERVALS (current_buffer);
-#endif /* USE_TEXT_PROPERTIES */
-
- validate_region (&startr1, &endr1);
- validate_region (&startr2, &endr2);
-
- start1 = XFASTINT (startr1);
- end1 = XFASTINT (endr1);
- start2 = XFASTINT (startr2);
- end2 = XFASTINT (endr2);
- gap = GPT;
-
- /* Swap the regions if they're reversed. */
- if (start2 < end1)
- {
- register int glumph = start1;
- start1 = start2;
- start2 = glumph;
- glumph = end1;
- end1 = end2;
- end2 = glumph;
- }
-
- len1 = end1 - start1;
- len2 = end2 - start2;
-
- if (start2 < end1)
- error ("transposed regions not properly ordered");
- else if (start1 == end1 || start2 == end2)
- error ("transposed region may not be of length 0");
-
- /* The possibilities are:
- 1. Adjacent (contiguous) regions, or separate but equal regions
- (no, really equal, in this case!), or
- 2. Separate regions of unequal size.
-
- The worst case is usually No. 2. It means that (aside from
- potential need for getting the gap out of the way), there also
- needs to be a shifting of the text between the two regions. So
- if they are spread far apart, we are that much slower... sigh. */
-
- /* It must be pointed out that the really studly thing to do would
- be not to move the gap at all, but to leave it in place and work
- around it if necessary. This would be extremely efficient,
- especially considering that people are likely to do
- transpositions near where they are working interactively, which
- is exactly where the gap would be found. However, such code
- would be much harder to write and to read. So, if you are
- reading this comment and are feeling squirrely, by all means have
- a go! I just didn't feel like doing it, so I will simply move
- the gap the minimum distance to get it out of the way, and then
- deal with an unbroken array. */
-
- /* Make sure the gap won't interfere, by moving it out of the text
- we will operate on. */
- if (start1 < gap && gap < end2)
- {
- if (gap - start1 < end2 - gap)
- move_gap (start1);
- else
- move_gap (end2);
- }
-
- /* Hmmm... how about checking to see if the gap is large
- enough to use as the temporary storage? That would avoid an
- allocation... interesting. Later, don't fool with it now. */
-
- /* Working without memmove, for portability (sigh), so must be
- careful of overlapping subsections of the array... */
-
- if (end1 == start2) /* adjacent regions */
- {
- modify_region (current_buffer, start1, end2);
- record_change (start1, len1 + len2);
-
-#ifdef USE_TEXT_PROPERTIES
- tmp_interval1 = copy_intervals (cur_intv, start1, len1);
- tmp_interval2 = copy_intervals (cur_intv, start2, len2);
- Fset_text_properties (start1, end2, Qnil, Qnil);
-#endif /* USE_TEXT_PROPERTIES */
-
- /* First region smaller than second. */
- if (len1 < len2)
- {
- /* We use alloca only if it is small,
- because we want to avoid stack overflow. */
- if (len2 > 20000)
- temp = (unsigned char *) xmalloc (len2);
- else
- temp = (unsigned char *) alloca (len2);
-
- /* Don't precompute these addresses. We have to compute them
- at the last minute, because the relocating allocator might
- have moved the buffer around during the xmalloc. */
- start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
- start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
-
- bcopy (start2_addr, temp, len2);
- bcopy (start1_addr, start1_addr + len2, len1);
- bcopy (temp, start1_addr, len2);
- if (len2 > 20000)
- free (temp);
- }
- else
- /* First region not smaller than second. */
- {
- if (len1 > 20000)
- temp = (unsigned char *) xmalloc (len1);
- else
- temp = (unsigned char *) alloca (len1);
- start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
- start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
- bcopy (start1_addr, temp, len1);
- bcopy (start2_addr, start1_addr, len2);
- bcopy (temp, start1_addr + len2, len1);
- if (len1 > 20000)
- free (temp);
- }
-#ifdef USE_TEXT_PROPERTIES
- graft_intervals_into_buffer (tmp_interval1, start1 + len2,
- len1, current_buffer, 0);
- graft_intervals_into_buffer (tmp_interval2, start1,
- len2, current_buffer, 0);
-#endif /* USE_TEXT_PROPERTIES */
- }
- /* Non-adjacent regions, because end1 != start2, bleagh... */
- else
- {
- if (len1 == len2)
- /* Regions are same size, though, how nice. */
- {
- modify_region (current_buffer, start1, end1);
- modify_region (current_buffer, start2, end2);
- record_change (start1, len1);
- record_change (start2, len2);
-#ifdef USE_TEXT_PROPERTIES
- tmp_interval1 = copy_intervals (cur_intv, start1, len1);
- tmp_interval2 = copy_intervals (cur_intv, start2, len2);
- Fset_text_properties (start1, end1, Qnil, Qnil);
- Fset_text_properties (start2, end2, Qnil, Qnil);
-#endif /* USE_TEXT_PROPERTIES */
-
- if (len1 > 20000)
- temp = (unsigned char *) xmalloc (len1);
- else
- temp = (unsigned char *) alloca (len1);
- start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
- start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
- bcopy (start1_addr, temp, len1);
- bcopy (start2_addr, start1_addr, len2);
- bcopy (temp, start2_addr, len1);
- if (len1 > 20000)
- free (temp);
-#ifdef USE_TEXT_PROPERTIES
- graft_intervals_into_buffer (tmp_interval1, start2,
- len1, current_buffer, 0);
- graft_intervals_into_buffer (tmp_interval2, start1,
- len2, current_buffer, 0);
-#endif /* USE_TEXT_PROPERTIES */
- }
-
- else if (len1 < len2) /* Second region larger than first */
- /* Non-adjacent & unequal size, area between must also be shifted. */
- {
- len_mid = start2 - end1;
- modify_region (current_buffer, start1, end2);
- record_change (start1, (end2 - start1));
-#ifdef USE_TEXT_PROPERTIES
- tmp_interval1 = copy_intervals (cur_intv, start1, len1);
- tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
- tmp_interval2 = copy_intervals (cur_intv, start2, len2);
- Fset_text_properties (start1, end2, Qnil, Qnil);
-#endif /* USE_TEXT_PROPERTIES */
-
- /* holds region 2 */
- if (len2 > 20000)
- temp = (unsigned char *) xmalloc (len2);
- else
- temp = (unsigned char *) alloca (len2);
- start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
- start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
- bcopy (start2_addr, temp, len2);
- bcopy (start1_addr, start1_addr + len_mid + len2, len1);
- safe_bcopy (start1_addr + len1, start1_addr + len2, len_mid);
- bcopy (temp, start1_addr, len2);
- if (len2 > 20000)
- free (temp);
-#ifdef USE_TEXT_PROPERTIES
- graft_intervals_into_buffer (tmp_interval1, end2 - len1,
- len1, current_buffer, 0);
- graft_intervals_into_buffer (tmp_interval_mid, start1 + len2,
- len_mid, current_buffer, 0);
- graft_intervals_into_buffer (tmp_interval2, start1,
- len2, current_buffer, 0);
-#endif /* USE_TEXT_PROPERTIES */
- }
- else
- /* Second region smaller than first. */
- {
- len_mid = start2 - end1;
- record_change (start1, (end2 - start1));
- modify_region (current_buffer, start1, end2);
-
-#ifdef USE_TEXT_PROPERTIES
- tmp_interval1 = copy_intervals (cur_intv, start1, len1);
- tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
- tmp_interval2 = copy_intervals (cur_intv, start2, len2);
- Fset_text_properties (start1, end2, Qnil, Qnil);
-#endif /* USE_TEXT_PROPERTIES */
-
- /* holds region 1 */
- if (len1 > 20000)
- temp = (unsigned char *) xmalloc (len1);
- else
- temp = (unsigned char *) alloca (len1);
- start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
- start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
- bcopy (start1_addr, temp, len1);
- bcopy (start2_addr, start1_addr, len2);
- bcopy (start1_addr + len1, start1_addr + len2, len_mid);
- bcopy (temp, start1_addr + len2 + len_mid, len1);
- if (len1 > 20000)
- free (temp);
-#ifdef USE_TEXT_PROPERTIES
- graft_intervals_into_buffer (tmp_interval1, end2 - len1,
- len1, current_buffer, 0);
- graft_intervals_into_buffer (tmp_interval_mid, start1 + len2,
- len_mid, current_buffer, 0);
- graft_intervals_into_buffer (tmp_interval2, start1,
- len2, current_buffer, 0);
-#endif /* USE_TEXT_PROPERTIES */
- }
- }
-
- /* todo: this will be slow, because for every transposition, we
- traverse the whole friggin marker list. Possible solutions:
- somehow get a list of *all* the markers across multiple
- transpositions and do it all in one swell phoop. Or maybe modify
- Emacs' marker code to keep an ordered list or tree. This might
- be nicer, and more beneficial in the long run, but would be a
- bunch of work. Plus the way they're arranged now is nice. */
- if (NILP (leave_markers))
- {
- transpose_markers (start1, end1, start2, end2);
- fix_overlays_in_range (start1, end2);
- }
-
- return Qnil;
-}
-
-
-void
-syms_of_editfns ()
-{
- environbuf = 0;
-
- Qbuffer_access_fontify_functions
- = intern ("buffer-access-fontify-functions");
- staticpro (&Qbuffer_access_fontify_functions);
-
- DEFVAR_LISP ("buffer-access-fontify-functions",
- &Vbuffer_access_fontify_functions,
- "List of functions called by `buffer-substring' to fontify if necessary.\n\
-Each function is called with two arguments which specify the range\n\
-of the buffer being accessed.");
- Vbuffer_access_fontify_functions = Qnil;
-
- {
- Lisp_Object obuf;
- extern Lisp_Object Vprin1_to_string_buffer;
- obuf = Fcurrent_buffer ();
- /* Do this here, because init_buffer_once is too early--it won't work. */
- Fset_buffer (Vprin1_to_string_buffer);
- /* Make sure buffer-access-fontify-functions is nil in this buffer. */
- Fset (Fmake_local_variable (intern ("buffer-access-fontify-functions")),
- Qnil);
- Fset_buffer (obuf);
- }
-
- DEFVAR_LISP ("buffer-access-fontified-property",
- &Vbuffer_access_fontified_property,
- "Property which (if non-nil) indicates text has been fontified.\n\
-`buffer-substring' need not call the `buffer-access-fontify-functions'\n\
-functions if all the text being accessed has this property.");
- Vbuffer_access_fontified_property = Qnil;
-
- DEFVAR_LISP ("system-name", &Vsystem_name,
- "The name of the machine Emacs is running on.");
-
- DEFVAR_LISP ("user-full-name", &Vuser_full_name,
- "The full name of the user logged in.");
-
- DEFVAR_LISP ("user-login-name", &Vuser_login_name,
- "The user's name, taken from environment variables if possible.");
-
- DEFVAR_LISP ("user-real-login-name", &Vuser_real_login_name,
- "The user's name, based upon the real uid only.");
-
- defsubr (&Schar_equal);
- defsubr (&Sgoto_char);
- defsubr (&Sstring_to_char);
- defsubr (&Schar_to_string);
- defsubr (&Sbuffer_substring);
- defsubr (&Sbuffer_substring_no_properties);
- 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 (&Ssave_current_buffer);
-
- defsubr (&Sbufsize);
- defsubr (&Spoint_max);
- defsubr (&Spoint_min);
- defsubr (&Spoint_min_marker);
- defsubr (&Spoint_max_marker);
-
- defsubr (&Sline_beginning_position);
- defsubr (&Sline_end_position);
-
- defsubr (&Sbobp);
- defsubr (&Seobp);
- defsubr (&Sbolp);
- defsubr (&Seolp);
- defsubr (&Sfollowing_char);
- defsubr (&Sprevious_char);
- defsubr (&Schar_after);
- defsubr (&Sinsert);
- defsubr (&Sinsert_before_markers);
- defsubr (&Sinsert_and_inherit);
- defsubr (&Sinsert_and_inherit_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 (&Semacs_pid);
- defsubr (&Scurrent_time);
- defsubr (&Sformat_time_string);
- defsubr (&Sdecode_time);
- defsubr (&Sencode_time);
- defsubr (&Scurrent_time_string);
- defsubr (&Scurrent_time_zone);
- defsubr (&Sset_time_zone_rule);
- defsubr (&Ssystem_name);
- defsubr (&Smessage);
- defsubr (&Smessage_box);
- defsubr (&Smessage_or_box);
- defsubr (&Sformat);
-
- defsubr (&Sinsert_buffer_substring);
- defsubr (&Scompare_buffer_substrings);
- defsubr (&Ssubst_char_in_region);
- defsubr (&Stranslate_region);
- defsubr (&Sdelete_region);
- defsubr (&Swiden);
- defsubr (&Snarrow_to_region);
- defsubr (&Ssave_restriction);
- defsubr (&Stranspose_regions);
-}
diff --git a/src/emacs.c b/src/emacs.c
deleted file mode 100644
index fca9faf100e..00000000000
--- a/src/emacs.c
+++ /dev/null
@@ -1,1600 +0,0 @@
-/* Fully extensible Emacs, running on Unix, intended for GNU.
- Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <signal.h>
-#include <errno.h>
-
-#include <config.h>
-#include <stdio.h>
-
-#include <sys/types.h>
-#include <sys/file.h>
-
-#ifdef VMS
-#include <ssdef.h>
-#endif
-
-#ifdef BSD_SYSTEM
-#include <sys/ioctl.h>
-#endif
-
-#include "lisp.h"
-#include "commands.h"
-#include "intervals.h"
-
-#include "systty.h"
-#include "blockinput.h"
-#include "syssignal.h"
-#include "process.h"
-
-#ifdef HAVE_SETRLIMIT
-#include <sys/time.h>
-#include <sys/resource.h>
-#endif
-
-#ifndef O_RDWR
-#define O_RDWR 2
-#endif
-
-extern void malloc_warning ();
-extern void set_time_zone_rule ();
-extern char *index ();
-extern char *strerror ();
-
-/* Command line args from shell, as list of strings */
-Lisp_Object Vcommand_line_args;
-
-/* The name under which Emacs was invoked, with any leading directory
- names discarded. */
-Lisp_Object Vinvocation_name;
-
-/* The directory name from which Emacs was invoked. */
-Lisp_Object Vinvocation_directory;
-
-/* The directory name in which to find subdirs such as lisp and etc.
- nil means get them only from PATH_LOADSEARCH. */
-Lisp_Object Vinstallation_directory;
-
-/* 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;
-
-/* Variable whose value is string giving configuration built for. */
-Lisp_Object Vsystem_configuration;
-
-/* Variable whose value is string giving configuration options,
- for use when reporting bugs. */
-Lisp_Object Vsystem_configuration_options;
-
-Lisp_Object Qfile_name_handler_alist;
-
-/* 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;
-
-/* If nonzero, set Emacs to run at this priority. This is also used
- in child_setup and sys_suspend to make sure subshells run at normal
- priority; Those functions have their own extern declaration. */
-int emacs_priority;
-
-/* If non-zero a filter or a sentinel is running. Tested to save the match
- data on the first attempt to change it inside asynchronous code. */
-int running_asynch_code;
-
-#ifdef BSD_PGRPS
-/* See sysdep.c. */
-extern int inherited_pgroup;
-#endif
-
-#ifdef HAVE_X_WINDOWS
-/* If non-zero, -d was specified, meaning we're using some window system. */
-int display_arg;
-#endif
-
-/* An address near the bottom of the stack.
- Tells GC how to save a copy of the stack. */
-char *stack_bottom;
-
-#ifdef HAVE_WINDOW_SYSTEM
-extern Lisp_Object Vwindow_system;
-#endif /* HAVE_WINDOW_SYSTEM */
-
-extern Lisp_Object Vauto_save_list_file_name;
-
-#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;
-
-/* Save argv and argc. */
-char **initial_argv;
-int initial_argc;
-
-static void sort_args ();
-
-/* 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. */
-SIGTYPE
-fatal_error_signal (sig)
- int sig;
-{
- fatal_error_code = sig;
- signal (sig, SIG_DFL);
-
- TOTALLY_UNBLOCK_INPUT;
-
- /* If fatal error occurs in code below, avoid infinite recursion. */
- if (! fatal_error_in_progress)
- {
- fatal_error_in_progress = 1;
-
- shut_down_emacs (sig, 0, Qnil);
- }
-
-#ifdef VMS
- LIB$STOP (SS$_ABORT);
-#else
- /* Signal the same code; this time it will really be fatal.
- Remember that since we're in a signal handler, the signal we're
- going to send is probably blocked, so we have to unblock it if we
- want to really receive it. */
-#ifndef MSDOS
- sigunblock (sigmask (fatal_error_code));
-#endif
- kill (getpid (), fatal_error_code);
-#endif /* not VMS */
-}
-
-#ifdef SIGDANGER
-
-/* Handler for SIGDANGER. */
-SIGTYPE
-memory_warning_signal (sig)
- int sig;
-{
- signal (sig, memory_warning_signal);
-
- malloc_warning ("Operating system warns that virtual memory is running low.\n");
-
- /* It might be unsafe to call do_auto_save now. */
- force_auto_save_soon ();
-}
-#endif
-
-/* 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;
- Lisp_Object name, dir, tem;
- int count = specpdl_ptr - specpdl;
- Lisp_Object raw_name;
-
- initial_argv = argv;
- initial_argc = argc;
-
- raw_name = build_string (argv[0]);
-
- /* Add /: to the front of the name
- if it would otherwise be treated as magic. */
- tem = Ffind_file_name_handler (raw_name, Qt);
- if (! NILP (tem))
- raw_name = concat2 (build_string ("/:"), raw_name);
-
- Vinvocation_name = Ffile_name_nondirectory (raw_name);
- Vinvocation_directory = Ffile_name_directory (raw_name);
-
- /* If we got no directory in argv[0], search PATH to find where
- Emacs actually came from. */
- if (NILP (Vinvocation_directory))
- {
- Lisp_Object found;
- int yes = openp (Vexec_path, Vinvocation_name,
- EXEC_SUFFIXES, &found, 1);
- if (yes == 1)
- {
- /* Add /: to the front of the name
- if it would otherwise be treated as magic. */
- tem = Ffind_file_name_handler (found, Qt);
- if (! NILP (tem))
- found = concat2 (build_string ("/:"), found);
- Vinvocation_directory = Ffile_name_directory (found);
- }
- }
-
- if (!NILP (Vinvocation_directory)
- && NILP (Ffile_name_absolute_p (Vinvocation_directory)))
- /* Emacs was started with relative path, like ./emacs.
- Make it absolute. */
- Vinvocation_directory = Fexpand_file_name (Vinvocation_directory, Qnil);
-
- Vinstallation_directory = Qnil;
-
- if (!NILP (Vinvocation_directory))
- {
- dir = Vinvocation_directory;
- name = Fexpand_file_name (Vinvocation_name, dir);
- while (1)
- {
- Lisp_Object tem, lib_src_exists;
- Lisp_Object etc_exists, info_exists;
-
- /* See if dir contains subdirs for use by Emacs.
- Check for the ones that would exist in a build directory,
- not including lisp and info. */
- tem = Fexpand_file_name (build_string ("lib-src"), dir);
- lib_src_exists = Ffile_exists_p (tem);
- if (!NILP (lib_src_exists))
- {
- tem = Fexpand_file_name (build_string ("etc"), dir);
- etc_exists = Ffile_exists_p (tem);
- if (!NILP (etc_exists))
- {
- Vinstallation_directory
- = Ffile_name_as_directory (dir);
- break;
- }
- }
-
- /* See if dir's parent contains those subdirs. */
- tem = Fexpand_file_name (build_string ("../lib-src"), dir);
- lib_src_exists = Ffile_exists_p (tem);
- if (!NILP (lib_src_exists))
- {
- tem = Fexpand_file_name (build_string ("../etc"), dir);
- etc_exists = Ffile_exists_p (tem);
- if (!NILP (etc_exists))
- {
- tem = Fexpand_file_name (build_string (".."), dir);
- Vinstallation_directory
- = Ffile_name_as_directory (tem);
- break;
- }
- }
-
- /* If the Emacs executable is actually a link,
- next try the dir that the link points into. */
- tem = Ffile_symlink_p (name);
- if (!NILP (tem))
- {
- name = Fexpand_file_name (tem, dir);
- dir = Ffile_name_directory (name);
- }
- else
- break;
- }
- }
-
- 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);
- }
-
- unbind_to (count, Qnil);
-}
-
-DEFUN ("invocation-name", Finvocation_name, Sinvocation_name, 0, 0, 0,
- "Return the program name that was used to run Emacs.\n\
-Any directory names are omitted.")
- ()
-{
- return Fcopy_sequence (Vinvocation_name);
-}
-
-DEFUN ("invocation-directory", Finvocation_directory, Sinvocation_directory,
- 0, 0, 0,
- "Return the directory name in which the Emacs executable was located")
- ()
-{
- return Fcopy_sequence (Vinvocation_directory);
-}
-
-
-#ifdef VMS
-#ifdef LINK_CRTL_SHARE
-#ifdef SHARABLE_LIB_BUG
-extern noshare char **environ;
-#endif /* SHARABLE_LIB_BUG */
-#endif /* LINK_CRTL_SHARE */
-#endif /* VMS */
-
-#ifdef HAVE_TZSET
-/* A valid but unlikely value for the TZ environment value.
- It is OK (though a bit slower) if the user actually chooses this value. */
-static char dump_tz[] = "UtC0";
-#endif
-
-#ifndef ORDINARY_LINK
-/* 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 GCC_CTORS_IN_LIBC
-__do_global_ctors ()
-{}
-__do_global_ctors_aux ()
-{}
-__do_global_dtors ()
-{}
-/* Linux has a bug in its library; avoid an error. */
-#ifndef LINUX
-char * __CTOR_LIST__[2] = { (char *) (-1), 0 };
-#endif
-char * __DTOR_LIST__[2] = { (char *) (-1), 0 };
-#endif /* GCC_CTORS_IN_LIBC */
-__main ()
-{}
-#endif /* __GNUC__ */
-#endif /* ORDINARY_LINK */
-
-/* Test whether the next argument in ARGV matches SSTR or a prefix of
- LSTR (at least MINLEN characters). If so, then if VALPTR is non-null
- (the argument is supposed to have a value) store in *VALPTR either
- the next argument or the portion of this one after the equal sign.
- ARGV is read starting at position *SKIPPTR; this index is advanced
- by the number of arguments used.
-
- Too bad we can't just use getopt for all of this, but we don't have
- enough information to do it right. */
-
-static int
-argmatch (argv, argc, sstr, lstr, minlen, valptr, skipptr)
- char **argv;
- int argc;
- char *sstr;
- char *lstr;
- int minlen;
- char **valptr;
- int *skipptr;
-{
- char *p;
- int arglen;
- char *arg;
-
- /* Don't access argv[argc]; give up in advance. */
- if (argc <= *skipptr + 1)
- return 0;
-
- arg = argv[*skipptr+1];
- if (arg == NULL)
- return 0;
- if (strcmp (arg, sstr) == 0)
- {
- if (valptr != NULL)
- {
- *valptr = argv[*skipptr+2];
- *skipptr += 2;
- }
- else
- *skipptr += 1;
- return 1;
- }
- arglen = (valptr != NULL && (p = index (arg, '=')) != NULL
- ? p - arg : strlen (arg));
- if (lstr == 0 || arglen < minlen || strncmp (arg, lstr, arglen) != 0)
- return 0;
- else if (valptr == NULL)
- {
- *skipptr += 1;
- return 1;
- }
- else if (p != NULL)
- {
- *valptr = p+1;
- *skipptr += 1;
- return 1;
- }
- else if (argv[*skipptr+2] != NULL)
- {
- *valptr = argv[*skipptr+2];
- *skipptr += 2;
- return 1;
- }
- else
- {
- return 0;
- }
-}
-
-/* ARGSUSED */
-main (argc, argv, envp)
- int argc;
- char **argv;
- char **envp;
-{
- char stack_bottom_variable;
- int skip_args = 0;
- extern int errno;
- extern sys_nerr;
-#ifdef HAVE_SETRLIMIT
- struct rlimit rlim;
-#endif
-
-#ifdef LINUX_SBRK_BUG
- __sbrk (1);
-#endif
-
- sort_args (argc, argv);
-
- if (argmatch (argv, argc, "-version", "--version", 3, NULL, &skip_args))
- {
- Lisp_Object tem;
- tem = Fsymbol_value (intern ("emacs-version"));
- if (!STRINGP (tem))
- {
- fprintf (stderr, "Invalid value of `emacs-version'\n");
- exit (1);
- }
- else
- {
- printf ("GNU Emacs %s\n", XSTRING (tem)->data);
- printf ("Copyright (C) 1996 Free Software Foundation, Inc.\n");
- printf ("GNU Emacs comes with ABSOLUTELY NO WARRANTY.\n");
- printf ("You may redistribute copies of Emacs\n");
- printf ("under the terms of the GNU General Public License.\n");
- printf ("For more information about these matters, ");
- printf ("see the files named COPYING.\n");
- exit (0);
- }
- }
-
-/* Map in shared memory, if we are using that. */
-#ifdef HAVE_SHM
- if (argmatch (argv, argc, "-nl", "--no-shared-memory", 6, NULL, &skip_args))
- {
- 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 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 */
-
-#ifdef VMS
- /* If -map specified, map the data file in */
- {
- char *file;
- if (argmatch (argv, argc, "-map", "--map-data", 3, &mapin_file, &skip_args))
- mapin_data (file);
- }
-
-#ifdef LINK_CRTL_SHARE
-#ifdef SHARABLE_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 /* SHARABLE_LIB_BUG */
-#endif /* LINK_CRTL_SHARE */
-#endif /* VMS */
-
-#ifdef HAVE_SETRLIMIT
- /* Extend the stack space available. */
- if (!getrlimit (RLIMIT_STACK, &rlim))
- {
- rlim.rlim_cur = rlim.rlim_max;
- setrlimit (RLIMIT_STACK, &rlim);
- }
-#endif
-
- /* Record (approximately) where the stack begins. */
- stack_bottom = &stack_bottom_variable;
-
-#ifdef RUN_TIME_REMAP
- if (initialized)
- run_time_remap (argv[0]);
-#endif
-
-#ifdef USG_SHARED_LIBRARIES
- if (bss_end)
- brk ((void *)bss_end);
-#endif
-
- clearerr (stdin);
-
-#ifndef SYSTEM_MALLOC
- if (! initialized)
- {
- /* Arrange to get warning messages as memory fills up. */
- memory_warnings (0, malloc_warning);
-
- /* Arrange to disable interrupt input while malloc and friends are
- running. */
- uninterrupt_malloc ();
- }
-#endif /* not SYSTEM_MALLOC */
-
-#ifdef MSDOS
- /* We do all file input/output as binary files. When we need to translate
- newlines, we do that manually. */
- _fmode = O_BINARY;
-
-#if __DJGPP__ >= 2
- if (!isatty (fileno (stdin)))
- setmode (fileno (stdin), O_BINARY);
- if (!isatty (fileno (stdout)))
- {
- fflush (stdout);
- setmode (fileno (stdout), O_BINARY);
- }
-#else /* not __DJGPP__ >= 2 */
- (stdin)->_flag &= ~_IOTEXT;
- (stdout)->_flag &= ~_IOTEXT;
- (stderr)->_flag &= ~_IOTEXT;
-#endif /* not __DJGPP__ >= 2 */
-#endif /* MSDOS */
-
-#ifdef SET_EMACS_PRIORITY
- if (emacs_priority)
- nice (emacs_priority);
- setuid (getuid ());
-#endif /* SET_EMACS_PRIORITY */
-
-#ifdef EXTRA_INITIALIZE
- EXTRA_INITIALIZE;
-#endif
-
- inhibit_window_system = 0;
-
- /* Handle the -t switch, which specifies filename to use as terminal */
- {
- char *term;
- if (argmatch (argv, argc, "-t", "--terminal", 4, &term, &skip_args))
- {
- int result;
- close (0);
- close (1);
- result = open (term, O_RDWR, 2 );
- if (result < 0)
- {
- char *errstring = strerror (errno);
- fprintf (stderr, "emacs: %s: %s\n", term, errstring);
- exit (1);
- }
- dup (0);
- if (! isatty (0))
- {
- fprintf (stderr, "emacs: %s: not a tty\n", term);
- exit (1);
- }
- fprintf (stderr, "Using %s\n", term);
-#ifdef HAVE_WINDOW_SYSTEM
- inhibit_window_system = 1; /* -t => -nw */
-#endif
- }
- }
- if (argmatch (argv, argc, "-nw", "--no-windows", 6, NULL, &skip_args))
- inhibit_window_system = 1;
-
- /* Handle the -batch switch, which means don't do interactive display. */
- noninteractive = 0;
- if (argmatch (argv, argc, "-batch", "--batch", 5, NULL, &skip_args))
- noninteractive = 1;
-
- /* Handle the --help option, which gives a usage message.. */
- if (argmatch (argv, argc, "-help", "--help", 3, NULL, &skip_args))
- {
- printf ("\
-Usage: %s [-t term] [--terminal term] [-nw] [--no-windows] [--batch]\n\
- [-q] [--no-init-file] [-u user] [--user user] [--debug-init]\n\
- [--version] [--no-site-file]\n\
- [-f func] [--funcall func] [-l file] [--load file] [--insert file]\n\
- [+linenum] file-to-visit [--kill]\n\
-Report bugs to bug-gnu-emacs@prep.ai.mit.edu. First, please see\n\
-the Bugs section of the Emacs manual or the file BUGS.", argv[0]);
- exit (0);
- }
-
-#ifdef HAVE_X_WINDOWS
- /* Stupid kludge to catch command-line display spec. We can't
- handle this argument entirely in window system dependent code
- because we don't even know which window system dependent code
- to run until we've recognized this argument. */
- {
- char *displayname = 0;
- int i;
- int count_before = skip_args;
-
- if (argmatch (argv, argc, "-d", "--display", 3, &displayname, &skip_args))
- display_arg = 1;
- else if (argmatch (argv, argc, "-display", 0, 3, &displayname, &skip_args))
- display_arg = 1;
-
- /* If we have the form --display=NAME,
- convert it into -d name.
- This requires inserting a new element into argv. */
- if (displayname != 0 && skip_args - count_before == 1)
- {
- char **new = (char **) xmalloc (sizeof (char *) * (argc + 2));
- int j;
-
- for (j = 0; j < count_before + 1; j++)
- new[j] = argv[j];
- new[count_before + 1] = "-d";
- new[count_before + 2] = displayname;
- for (j = count_before + 2; j <argc; j++)
- new[j + 1] = argv[j];
- argv = new;
- argc++;
- }
- /* Change --display to -d, when its arg is separate. */
- else if (displayname != 0 && skip_args > count_before
- && argv[count_before + 1][1] == '-')
- argv[count_before + 1] = "-d";
-
- /* Don't actually discard this arg. */
- skip_args = count_before;
- }
-#endif
-
- if (! noninteractive)
- {
-#ifdef BSD_PGRPS
- if (initialized)
- {
- inherited_pgroup = EMACS_GETPGRP (0);
- setpgrp (0, getpid ());
- }
-#else
-#if defined (USG5) && defined (INTERRUPT_INPUT)
- setpgrp ();
-#endif
-#endif
- }
-
-#ifdef POSIX_SIGNALS
- init_signals ();
-#endif
-
- /* Don't catch SIGHUP if dumping. */
- if (1
-#ifndef CANNOT_DUMP
- && initialized
-#endif
- )
- {
- sigblock (sigmask (SIGHUP));
- /* In --batch mode, don't catch SIGHUP if already ignored.
- That makes nohup work. */
- if (! noninteractive
- || signal (SIGHUP, SIG_IGN) != SIG_IGN)
- signal (SIGHUP, fatal_error_signal);
- sigunblock (sigmask (SIGHUP));
- }
-
- if (
-#ifndef CANNOT_DUMP
- ! noninteractive || initialized
-#else
- 1
-#endif
- )
- {
- /* Don't catch these signals in batch mode if dumping.
- On some machines, this sets static data that would make
- signal fail to work right when the dumped Emacs is run. */
- signal (SIGQUIT, fatal_error_signal);
- signal (SIGILL, fatal_error_signal);
- signal (SIGTRAP, fatal_error_signal);
-#ifdef SIGABRT
- signal (SIGABRT, fatal_error_signal);
-#endif
-#ifdef SIGHWE
- signal (SIGHWE, fatal_error_signal);
-#endif
-#ifdef SIGPRE
- signal (SIGPRE, fatal_error_signal);
-#endif
-#ifdef SIGORE
- signal (SIGORE, fatal_error_signal);
-#endif
-#ifdef SIGUME
- signal (SIGUME, fatal_error_signal);
-#endif
-#ifdef SIGDLK
- signal (SIGDLK, fatal_error_signal);
-#endif
-#ifdef SIGCPULIM
- signal (SIGCPULIM, fatal_error_signal);
-#endif
-#ifdef SIGIOT
- /* This is missing on some systems - OS/2, for example. */
- signal (SIGIOT, fatal_error_signal);
-#endif
-#ifdef SIGEMT
- signal (SIGEMT, fatal_error_signal);
-#endif
- signal (SIGFPE, fatal_error_signal);
-#ifdef SIGBUS
- signal (SIGBUS, fatal_error_signal);
-#endif
- signal (SIGSEGV, fatal_error_signal);
-#ifdef SIGSYS
- signal (SIGSYS, fatal_error_signal);
-#endif
- signal (SIGTERM, fatal_error_signal);
-#ifdef SIGXCPU
- signal (SIGXCPU, fatal_error_signal);
-#endif
-#ifdef SIGXFSZ
- signal (SIGXFSZ, fatal_error_signal);
-#endif /* SIGXFSZ */
-
-#ifdef SIGDANGER
- /* This just means available memory is getting low. */
- signal (SIGDANGER, memory_warning_signal);
-#endif
-
-#ifdef AIX
-/* 20 is SIGCHLD, 21 is SIGTTIN, 22 is SIGTTOU. */
- signal (SIGXCPU, fatal_error_signal);
-#ifndef _I386
- signal (SIGIOINT, 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_casetab_once ();
- 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 ();
- init_eval ();
- init_data ();
- running_asynch_code = 0;
-
-#ifdef MSDOS
- /* Call early 'cause init_environment needs it. */
- init_dosfns ();
- /* Set defaults for several environment variables. */
- if (initialized)
- init_environment (argc, argv, skip_args);
- else
- tzset ();
-#endif /* MSDOS */
-
-#ifdef WINDOWSNT
- /* Initialize environment from registry settings. */
- init_environment ();
- init_ntproc (); /* must precede init_editfns */
-#endif
-
- /* egetenv is a pretty low-level facility, which may get called in
- many circumstances; it seems flimsy to put off initializing it
- until calling init_callproc. */
- set_process_environment ();
- /* AIX crashes are reported in system versions 3.2.3 and 3.2.4
- if this is not done. Do it after set_process_environment so that we
- don't pollute Vprocess_environment. */
-#ifdef AIX
- putenv ("LANG=C");
-#endif
-
- init_buffer (); /* Init default directory of main buffer */
-
- init_callproc_1 (); /* Must precede init_cmdargs and init_sys_modes. */
- init_cmdargs (argc, argv, skip_args); /* Must precede init_lread. */
-
- if (initialized)
- {
- /* Erase any pre-dump messages in the message log, to avoid confusion */
- Lisp_Object old_log_max;
- old_log_max = Vmessage_log_max;
- XSETFASTINT (Vmessage_log_max, 0);
- message_dolog ("", 0, 1);
- Vmessage_log_max = old_log_max;
- }
-
- init_callproc (); /* Must follow init_cmdargs but not init_sys_modes. */
- init_lread ();
-
- if (!noninteractive)
- {
-#ifdef VMS
- init_vms_input ();/* init_display calls get_frame_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 */
-#ifdef VMS
- init_vmsproc (); /* And this too. */
-#endif /* VMS */
- init_sys_modes (); /* Init system terminal modes (RAW or CBREAK, etc.) */
- init_xdisp ();
- init_macros ();
- init_editfns ();
-#ifdef LISP_FLOAT_TYPE
- init_floatfns ();
-#endif
-#ifdef VMS
- init_vmsfns ();
-#endif /* VMS */
- init_process ();
-#ifdef CLASH_DETECTION
- init_filelock ();
-#endif /* CLASH_DETECTION */
-
-/* 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 ();
- syms_of_lread ();
- syms_of_print ();
- syms_of_eval ();
- syms_of_fns ();
- syms_of_floatfns ();
-
- syms_of_abbrev ();
- syms_of_buffer ();
- syms_of_bytecode ();
- syms_of_callint ();
- syms_of_casefiddle ();
- syms_of_casetab ();
- 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_insdel ();
- syms_of_keyboard ();
- syms_of_keymap ();
- syms_of_macros ();
- syms_of_marker ();
- syms_of_minibuf ();
- syms_of_mocklisp ();
- syms_of_process ();
- syms_of_search ();
- syms_of_frame ();
- syms_of_syntax ();
- syms_of_term ();
- syms_of_undo ();
-
- /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
- syms_of_textprop ();
-#ifdef VMS
- syms_of_vmsproc ();
-#endif /* VMS */
-#ifdef WINDOWSNT
- syms_of_ntproc ();
-#endif /* WINDOWSNT */
- syms_of_window ();
- syms_of_xdisp ();
-#ifdef HAVE_X_WINDOWS
- syms_of_xterm ();
- syms_of_xfns ();
- syms_of_xfaces ();
-#ifdef HAVE_X11
- syms_of_xselect ();
-#endif
-#endif /* HAVE_X_WINDOWS */
-
-#if defined (MSDOS) && !defined (HAVE_X_WINDOWS)
- syms_of_xfaces ();
-#endif
-
-#ifndef HAVE_NTGUI
- syms_of_xmenu ();
-#endif
-
-#ifdef HAVE_NTGUI
- syms_of_w32term ();
- syms_of_w32fns ();
- syms_of_w32faces ();
- syms_of_w32select ();
- syms_of_w32menu ();
-#endif /* HAVE_NTGUI */
-
-#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 ();
- keys_of_frame ();
- }
-
- if (!initialized)
- {
- char *file;
- /* Handle -l loadup-and-dump, args passed by Makefile. */
- if (argmatch (argv, argc, "-l", "--load", 3, &file, &skip_args))
- Vtop_level = Fcons (intern ("load"),
- Fcons (build_string (file), Qnil));
-#ifdef CANNOT_DUMP
- /* Unless next switch is -nl, load "loadup.el" first thing. */
- if (!argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args))
- Vtop_level = Fcons (intern ("load"),
- Fcons (build_string ("loadup.el"), Qnil));
-#endif /* CANNOT_DUMP */
- }
-
- if (initialized)
- {
-#ifdef HAVE_TZSET
- {
- /* If the execution TZ happens to be the same as the dump TZ,
- change it to some other value and then change it back,
- to force the underlying implementation to reload the TZ info.
- This is needed on implementations that load TZ info from files,
- since the TZ file contents may differ between dump and execution. */
- char *tz = getenv ("TZ");
- if (tz && !strcmp (tz, dump_tz))
- {
- ++*tz;
- tzset ();
- --*tz;
- }
- }
-#endif
- }
-
- initialized = 1;
-
-#ifdef LOCALTIME_CACHE
- /* Some versions of localtime have a bug. They cache the value of the time
- zone rather than looking it up every time. Since localtime() is
- called to bolt the undumping time into the undumped emacs, this
- results in localtime ignoring the TZ environment variable.
- This flushes the new TZ value into localtime. */
- tzset ();
-#endif /* defined (LOCALTIME_CACHE) */
-
- /* Enter editor command loop. This never returns. */
- Frecursive_edit ();
- /* NOTREACHED */
-}
-
-/* Sort the args so we can find the most important ones
- at the beginning of argv. */
-
-/* First, here's a table of all the standard options. */
-
-struct standard_args
-{
- char *name;
- char *longname;
- int priority;
- int nargs;
-};
-
-struct standard_args standard_args[] =
-{
- { "-version", "--version", 110, 0 },
- { "-help", "--help", 110, 0 },
- { "-nl", "--no-shared-memory", 100, 0 },
-#ifdef VMS
- { "-map", "--map-data", 100, 0 },
-#endif
- { "-t", "--terminal", 90, 1 },
- { "-d", "--display", 80, 1 },
- { "-display", 0, 80, 1 },
- { "-nw", "--no-windows", 70, 0 },
- { "-batch", "--batch", 60, 0 },
- { "-q", "--no-init-file", 50, 0 },
- { "-no-init-file", 0, 50, 0 },
- { "-no-site-file", "--no-site-file", 40, 0 },
- { "-u", "--user", 30, 1 },
- { "-user", 0, 30, 1 },
- { "-debug-init", "--debug-init", 20, 0 },
- { "-i", "--icon-type", 15, 0 },
- { "-itype", 0, 15, 0 },
- { "-iconic", "--iconic", 15, 0 },
- { "-bg", "--background-color", 10, 1 },
- { "-background", 0, 10, 1 },
- { "-fg", "--foreground-color", 10, 1 },
- { "-foreground", 0, 10, 1 },
- { "-bd", "--border-color", 10, 1 },
- { "-bw", "--border-width", 10, 1 },
- { "-ib", "--internal-border", 10, 1 },
- { "-ms", "--mouse-color", 10, 1 },
- { "-cr", "--cursor-color", 10, 1 },
- { "-fn", "--font", 10, 1 },
- { "-font", 0, 10, 1 },
- { "-g", "--geometry", 10, 1 },
- { "-geometry", 0, 10, 1 },
- { "-T", "--title", 10, 1 },
- { "-title", 0, 10, 1 },
- { "-name", "--name", 10, 1 },
- { "-xrm", "--xrm", 10, 1 },
- { "-r", "--reverse-video", 5, 0 },
- { "-rv", 0, 5, 0 },
- { "-reverse", 0, 5, 0 },
- { "-hb", "--horizontal-scroll-bars", 5, 0 },
- { "-vb", "--vertical-scroll-bars", 5, 0 },
- /* These have the same priority as ordinary file name args,
- so they are not reordered with respect to those. */
- { "-L", "--directory", 0, 1 },
- { "-directory", 0, 0, 1 },
- { "-l", "--load", 0, 1 },
- { "-load", 0, 0, 1 },
- { "-f", "--funcall", 0, 1 },
- { "-funcall", 0, 0, 1 },
- { "-eval", "--eval", 0, 1 },
- { "-find-file", "--find-file", 0, 1 },
- { "-visit", "--visit", 0, 1 },
- { "-insert", "--insert", 0, 1 },
- /* This should be processed after ordinary file name args and the like. */
- { "-kill", "--kill", -10, 0 },
-};
-
-/* Reorder the elements of ARGV (assumed to have ARGC elements)
- so that the highest priority ones come first.
- Do not change the order of elements of equal priority.
- If an option takes an argument, keep it and its argument together. */
-
-static void
-sort_args (argc, argv)
- int argc;
- char **argv;
-{
- char **new = (char **) xmalloc (sizeof (char *) * argc);
- /* For each element of argv,
- the corresponding element of options is:
- 0 for an option that takes no arguments,
- 1 for an option that takes one argument, etc.
- -1 for an ordinary non-option argument. */
- int *options = (int *) xmalloc (sizeof (int) * argc);
- int *priority = (int *) xmalloc (sizeof (int) * argc);
- int to = 1;
- int from;
- int i;
- int end_of_options = argc;
-
- /* Categorize all the options,
- and figure out which argv elts are option arguments. */
- for (from = 1; from < argc; from++)
- {
- options[from] = -1;
- priority[from] = 0;
- if (argv[from][0] == '-')
- {
- int match, thislen;
- char *equals;
-
- /* If we have found "--", don't consider
- any more arguments as options. */
- if (argv[from][1] == '-')
- {
- /* Leave the "--", and everything following it, at the end. */
- for (; from < argc; from++)
- {
- priority[from] = -100;
- options[from] = -1;
- }
- break;
- }
-
- /* Look for a match with a known old-fashioned option. */
- for (i = 0; i < sizeof (standard_args) / sizeof (standard_args[0]); i++)
- if (!strcmp (argv[from], standard_args[i].name))
- {
- options[from] = standard_args[i].nargs;
- priority[from] = standard_args[i].priority;
- if (from + standard_args[i].nargs >= argc)
- fatal ("Option `%s' requires an argument\n", argv[from]);
- from += standard_args[i].nargs;
- goto done;
- }
-
- /* Look for a match with a known long option.
- MATCH is -1 if no match so far, -2 if two or more matches so far,
- >= 0 (the table index of the match) if just one match so far. */
- if (argv[from][1] == '-')
- {
- match = -1;
- thislen = strlen (argv[from]);
- equals = index (argv[from], '=');
- if (equals != 0)
- thislen = equals - argv[from];
-
- for (i = 0;
- i < sizeof (standard_args) / sizeof (standard_args[0]); i++)
- if (standard_args[i].longname
- && !strncmp (argv[from], standard_args[i].longname,
- thislen))
- {
- if (match == -1)
- match = i;
- else
- match = -2;
- }
-
- /* If we found exactly one match, use that. */
- if (match >= 0)
- {
- options[from] = standard_args[match].nargs;
- priority[from] = standard_args[match].priority;
- /* If --OPTION=VALUE syntax is used,
- this option uses just one argv element. */
- if (equals != 0)
- options[from] = 0;
- if (from + options[from] >= argc)
- fatal ("Option `%s' requires an argument\n", argv[from]);
- from += options[from];
- }
- }
- done: ;
- }
- }
-
- /* Copy the arguments, in order of decreasing priority, to NEW. */
- new[0] = argv[0];
- while (to < argc)
- {
- int best = -1;
- int best_priority = -9999;
-
- /* Find the highest priority remaining option.
- If several have equal priority, take the first of them. */
- for (from = 1; from < argc; from++)
- {
- if (argv[from] != 0 && priority[from] > best_priority)
- {
- best_priority = priority[from];
- best = from;
- }
- /* Skip option arguments--they are tied to the options. */
- if (options[from] > 0)
- from += options[from];
- }
-
- if (best < 0)
- abort ();
-
- /* Copy the highest priority remaining option, with its args, to NEW. */
- new[to++] = argv[best];
- for (i = 0; i < options[best]; i++)
- new[to++] = argv[best + i + 1];
-
- /* Clear out this option in ARGV. */
- argv[best] = 0;
- for (i = 0; i < options[best]; i++)
- argv[best + i + 1] = 0;
- }
-
- bcopy (new, argv, sizeof (char *) * argc);
-}
-
-DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P",
- "Exit the Emacs job and kill it.\n\
-If ARG is an integer, return ARG as the exit program code.\n\
-If ARG is a string, stuff it as keyboard input.\n\n\
-The value of `kill-emacs-hook', if not void,\n\
-is a list of functions (of no args),\n\
-all of which are called before Emacs is actually killed.")
- (arg)
- Lisp_Object arg;
-{
- Lisp_Object hook, hook1;
- int i;
- struct gcpro gcpro1;
-
- GCPRO1 (arg);
-
- if (feof (stdin))
- arg = Qt;
-
- if (!NILP (Vrun_hooks) && !noninteractive)
- call1 (Vrun_hooks, intern ("kill-emacs-hook"));
-
- UNGCPRO;
-
-/* Is it really necessary to do this deassign
- when we are going to exit anyway? */
-/* #ifdef VMS
- stop_vms_input ();
- #endif */
-
- shut_down_emacs (0, 0, STRINGP (arg) ? arg : Qnil);
-
- /* If we have an auto-save list file,
- kill it because we are exiting Emacs deliberately (not crashing).
- Do it after shut_down_emacs, which does an auto-save. */
- if (STRINGP (Vauto_save_list_file_name))
- unlink (XSTRING (Vauto_save_list_file_name)->data);
-
- exit (INTEGERP (arg) ? XINT (arg)
-#ifdef VMS
- : 1
-#else
- : 0
-#endif
- );
- /* NOTREACHED */
-}
-
-
-/* Perform an orderly shutdown of Emacs. Autosave any modified
- buffers, kill any child processes, clean up the terminal modes (if
- we're in the foreground), and other stuff like that. Don't perform
- any redisplay; this may be called when Emacs is shutting down in
- the background, or after its X connection has died.
-
- If SIG is a signal number, print a message for it.
-
- This is called by fatal signal handlers, X protocol error handlers,
- and Fkill_emacs. */
-
-void
-shut_down_emacs (sig, no_x, stuff)
- int sig, no_x;
- Lisp_Object stuff;
-{
- /* Prevent running of hooks from now on. */
- Vrun_hooks = Qnil;
-
- /* If we are controlling the terminal, reset terminal modes */
-#ifdef EMACS_HAVE_TTY_PGRP
- {
- int pgrp = EMACS_GETPGRP (0);
-
- int tpgrp;
- if (EMACS_GET_TTY_PGRP (0, &tpgrp) != -1
- && tpgrp == pgrp)
- {
- fflush (stdout);
- reset_sys_modes ();
- if (sig && sig != SIGTERM)
- fprintf (stderr, "Fatal error (%d).", sig);
- }
- }
-#else
- fflush (stdout);
- reset_sys_modes ();
-#endif
-
- stuff_buffered_input (stuff);
-
- kill_buffer_processes (Qnil);
- Fdo_auto_save (Qt, Qnil);
-
-#ifdef CLASH_DETECTION
- unlock_all_files ();
-#endif
-
-#ifdef VMS
- kill_vms_processes ();
-#endif
-
-#if 0 /* This triggers a bug in XCloseDisplay and is not needed. */
-#ifdef HAVE_X_WINDOWS
- /* It's not safe to call intern here. Maybe we are crashing. */
- if (!noninteractive && SYMBOLP (Vwindow_system)
- && XSYMBOL (Vwindow_system)->name->size == 1
- && XSYMBOL (Vwindow_system)->name->data[0] == 'x'
- && ! no_x)
- Fx_close_current_connection ();
-#endif /* HAVE_X_WINDOWS */
-#endif
-
-#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
-
-#ifdef WINDOWSNT
- term_ntproc ();
-#endif
-}
-
-
-
-#ifndef CANNOT_DUMP
-
-#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.")
- (filename)
- Lisp_Object filename;
-{
- extern char my_edata[];
- Lisp_Object tem;
-
- CHECK_STRING (filename, 0);
- filename = Fexpand_file_name (filename, 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
- memory_warnings (my_edata, malloc_warning);
-#endif
- map_out_data (XSTRING (filename)->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).\n\
-This is used in the file `loadup.el' when building Emacs.\n\
-\n\
-Bind `command-line-processed' to nil before dumping,\n\
-if you want the dumped Emacs to process its command line\n\
-and announce itself normally when it is run.")
- (filename, symfile)
- Lisp_Object filename, symfile;
-{
- extern char my_edata[];
- Lisp_Object tem;
-
- CHECK_STRING (filename, 0);
- filename = Fexpand_file_name (filename, Qnil);
- if (!NILP (symfile))
- {
- CHECK_STRING (symfile, 0);
- if (XSTRING (symfile)->size)
- symfile = Fexpand_file_name (symfile, Qnil);
- }
-
- tem = Vpurify_flag;
- Vpurify_flag = Qnil;
-
-#ifdef HAVE_TZSET
- set_time_zone_rule (dump_tz);
-#ifndef LOCALTIME_CACHE
- /* Force a tz reload, since set_time_zone_rule doesn't. */
- tzset ();
-#endif
-#endif
-
- fflush (stdout);
-#ifdef VMS
- mapout_data (XSTRING (filename)->data);
-#else
- /* Tell malloc where start of impure now is */
- /* Also arrange for warnings when nearly out of space. */
-#ifndef SYSTEM_MALLOC
-#ifndef WINDOWSNT
- /* On Windows, this was done before dumping, and that once suffices.
- Meanwhile, my_edata is not valid on Windows. */
- memory_warnings (my_edata, malloc_warning);
-#endif /* not WINDOWSNT */
-#endif
- unexec (XSTRING (filename)->data,
- !NILP (symfile) ? XSTRING (symfile)->data : 0, my_edata, 0, 0);
-#endif /* not VMS */
-
- Vpurify_flag = tem;
-
- return Qnil;
-}
-
-#endif /* not HAVE_SHM */
-
-#endif /* not CANNOT_DUMP */
-
-#ifndef SEPCHAR
-#define SEPCHAR ':'
-#endif
-
-Lisp_Object
-decode_env_path (evarname, defalt)
- char *evarname, *defalt;
-{
- register char *path, *p;
- Lisp_Object lpath, element, tem;
-
- /* It's okay to use getenv here, because this function is only used
- to initialize variables when Emacs starts up, and isn't called
- after that. */
- if (evarname != 0)
- path = (char *) getenv (evarname);
- else
- path = 0;
- if (!path)
- path = defalt;
- lpath = Qnil;
- while (1)
- {
- p = index (path, SEPCHAR);
- if (!p) p = path + strlen (path);
- element = (p - path ? make_string (path, p - path)
- : build_string ("."));
-
- /* Add /: to the front of the name
- if it would otherwise be treated as magic. */
- tem = Ffind_file_name_handler (element, Qt);
- if (! NILP (tem))
- element = concat2 (build_string ("/:"), element);
-
- lpath = Fcons (element, lpath);
- if (*p)
- path = p + 1;
- else
- break;
- }
- return Fnreverse (lpath);
-}
-
-syms_of_emacs ()
-{
- Qfile_name_handler_alist = intern ("file-name-handler-alist");
- staticpro (&Qfile_name_handler_alist);
-
-#ifndef CANNOT_DUMP
-#ifdef HAVE_SHM
- defsubr (&Sdump_emacs_data);
-#else
- defsubr (&Sdump_emacs);
-#endif
-#endif
-
- defsubr (&Skill_emacs);
-
- defsubr (&Sinvocation_name);
- defsubr (&Sinvocation_directory);
-
- 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,
- "Value is symbol indicating type of operating system you are using.");
- Vsystem_type = intern (SYSTEM_TYPE);
-
- DEFVAR_LISP ("system-configuration", &Vsystem_configuration,
- "Value is string indicating configuration Emacs was built for.");
- Vsystem_configuration = build_string (EMACS_CONFIGURATION);
-
- DEFVAR_LISP ("system-configuration-options", &Vsystem_configuration_options,
- "String containing the configuration options Emacs was built with.");
- Vsystem_configuration_options = build_string (EMACS_CONFIG_OPTIONS);
-
- DEFVAR_BOOL ("noninteractive", &noninteractive1,
- "Non-nil means Emacs is running without interactive terminal.");
-
- DEFVAR_LISP ("kill-emacs-hook", &Vkill_emacs_hook,
- "Hook to be run whenever kill-emacs is called.\n\
-Since kill-emacs may be invoked when the terminal is disconnected (or\n\
-in other similar situations), functions placed on this hook should not\n\
-expect to be able to interact with the user. To ask for confirmation,\n\
-see `kill-emacs-query-functions' instead.");
- Vkill_emacs_hook = Qnil;
-
- DEFVAR_INT ("emacs-priority", &emacs_priority,
- "Priority for Emacs to run at.\n\
-This value is effective only if set before Emacs is dumped,\n\
-and only if the Emacs executable is installed with setuid to permit\n\
-it to change priority. (Emacs sets its uid back to the real uid.)\n\
-Currently, you need to define SET_EMACS_PRIORITY in `config.h'\n\
-before you compile Emacs, to enable the code for this feature.");
- emacs_priority = 0;
-
- DEFVAR_LISP ("invocation-name", &Vinvocation_name,
- "The program name that was used to run Emacs.\n\
-Any directory names are omitted.");
-
- DEFVAR_LISP ("invocation-directory", &Vinvocation_directory,
- "The directory in which the Emacs executable was found, to run it.\n\
-The value is nil if that directory's name is not known.");
-
- DEFVAR_LISP ("installation-directory", &Vinstallation_directory,
- "A directory within which to look for the `lib-src' and `etc' directories.\n\
-This is non-nil when we can't find those directories in their standard\n\
-installed locations, but we can find them\n\
-near where the Emacs executable was found.");
- Vinstallation_directory = Qnil;
-}
diff --git a/src/epaths.in b/src/epaths.in
deleted file mode 100644
index 34d6c98290a..00000000000
--- a/src/epaths.in
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Hey Emacs, this is -*- C -*- code! */
-
-/* The default search path for Lisp function "load".
- This sets load-path. */
-#define PATH_LOADSEARCH "/usr/local/lib/emacs/lisp"
-
-/* Like PATH_LOADSEARCH, but used only when Emacs is dumping. This
- path is usually identical to PATH_LOADSEARCH except that the entry
- for the directory containing the installed lisp files has been
- replaced with ../lisp. */
-#define PATH_DUMPLOADSEARCH "../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 name in it sets the Lisp
- variable exec-directory. exec-directory is used for finding
- executables and other architecture-dependent files. */
-#define PATH_EXEC "/usr/local/lib/emacs/etc"
-
-/* Where Emacs should look for its architecture-independent data
- files, like the NEWS file. The lisp variable data-directory
- is set to this value. */
-#define PATH_DATA "/usr/local/lib/emacs/data"
-
-/* Where Emacs should look for X bitmap files.
- The lisp variable x-bitmap-file-path is set based on this value. */
-#define PATH_BITMAPS "/usr/include/X11/bitmaps"
-
-/* Where Emacs should look for its docstring file. The lisp variable
- doc-directory is set to this value. */
-#define PATH_DOC "/usr/local/lib/emacs/data"
-
-/* 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/lib/emacs/lock/"
-
-/* Where the configuration process believes the info tree lives. The
- lisp variable configure-info-directory gets its value from this
- macro, and is then used to set the Info-default-directory-list. */
-#define PATH_INFO "/usr/local/info"
diff --git a/src/eval.c b/src/eval.c
deleted file mode 100644
index bf1eaacedd1..00000000000
--- a/src/eval.c
+++ /dev/null
@@ -1,3008 +0,0 @@
-/* Evaluator for GNU Emacs Lisp interpreter.
- Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include "lisp.h"
-#include "blockinput.h"
-
-#ifndef standalone
-#include "commands.h"
-#include "keyboard.h"
-#else
-#define INTERACTIVE 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;
-
-/* This structure helps implement the `catch' and `throw' control
- structure. A struct catchtag contains all the information needed
- to restore the state of the interpreter after a non-local jump.
-
- Handlers for error conditions (represented by `struct handler'
- structures) just point to a catch tag to do the cleanup required
- for their jumps.
-
- catchtag structures are chained together in the C calling stack;
- the `next' member points to the next outer catchtag.
-
- A call like (throw TAG VAL) searches for a catchtag whose `tag'
- member is TAG, and then unbinds to it. The `val' member is used to
- hold VAL while the stack is unwound; `val' is returned as the value
- of the catch form.
-
- All the other members are concerned with restoring the interpreter
- state. */
-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 Qinhibit_quit, Vinhibit_quit, Vquit_flag;
-Lisp_Object Qmocklisp_arguments, Vmocklisp_arguments, Qmocklisp;
-Lisp_Object Qand_rest, Qand_optional;
-Lisp_Object Qdebug_on_error;
-
-/* This holds either the symbol `run-hooks' or nil.
- It is nil at an early stage of startup, and when Emacs
- is shutting down. */
-Lisp_Object Vrun_hooks;
-
-/* 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;
-
-/* List of conditions (non-nil atom means all) which cause a backtrace
- if an error is handled by the command loop's error handler. */
-Lisp_Object Vstack_trace_on_error;
-
-/* List of conditions (non-nil atom means all) which enter the debugger
- if an error is handled by the command loop's error handler. */
-Lisp_Object Vdebug_on_error;
-
-/* List of conditions and regexps specifying error messages which
- do not enter the debugger even if Vdebug_on_errors says they should. */
-Lisp_Object Vdebug_ignored_errors;
-
-/* Non-nil means call the debugger even if the error will be handled. */
-Lisp_Object Vdebug_on_signal;
-
-/* Hook for edebug to use. */
-Lisp_Object Vsignal_hook_function;
-
-/* Nonzero means enter debugger if a quit signal
- is handled by the command loop's error handler. */
-int debug_on_quit;
-
-/* The value of num_nonmacro_input_chars as of the last time we
- started to enter the debugger. If we decide to enter the debugger
- again when this is still equal to num_nonmacro_input_chars, then we
- know that the debugger itself has an error, and we should just
- signal the error instead of entering an infinite loop of debugger
- invocations. */
-int when_entered_debugger;
-
-Lisp_Object Vdebugger;
-
-void specbind (), record_unwind_protect ();
-
-Lisp_Object run_hook_with_args ();
-
-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 *) xmalloc (specpdl_size * sizeof (struct specbinding));
- specpdl_ptr = specpdl;
- max_specpdl_size = 600;
- max_lisp_eval_depth = 200;
-
- Vrun_hooks = Qnil;
-}
-
-init_eval ()
-{
- specpdl_ptr = specpdl;
- catchlist = 0;
- handlerlist = 0;
- backtrace_list = 0;
- Vquit_flag = Qnil;
- debug_on_next_call = 0;
- lisp_eval_depth = 0;
- /* This is less than the initial value of num_nonmacro_input_chars. */
- when_entered_debugger = -1;
-}
-
-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;
- when_entered_debugger = num_nonmacro_input_chars;
- 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 (NILP(args))
- return Qnil;
-
- args_left = args;
- GCPRO1 (args_left);
-
- do
- {
- val = Feval (Fcar (args_left));
- if (!NILP (val))
- break;
- args_left = Fcdr (args_left);
- }
- while (!NILP(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 (NILP(args))
- return Qt;
-
- args_left = args;
- GCPRO1 (args_left);
-
- do
- {
- val = Feval (Fcar (args_left));
- if (NILP (val))
- break;
- args_left = Fcdr (args_left);
- }
- while (!NILP(args_left));
-
- UNGCPRO;
- return val;
-}
-
-DEFUN ("if", Fif, Sif, 2, UNEVALLED, 0,
- "(if COND THEN ELSE...): if COND yields non-nil, do THEN, else do ELSE...\n\
-Returns the value of THEN or the value of the last of the ELSE's.\n\
-THEN must be one expression, but ELSE... can be zero or more expressions.\n\
-If COND yields nil, and there are no ELSE's, the value is nil.")
- (args)
- Lisp_Object args;
-{
- register Lisp_Object cond;
- struct gcpro gcpro1;
-
- GCPRO1 (args);
- cond = Feval (Fcar (args));
- UNGCPRO;
-
- if (!NILP (cond))
- return Feval (Fcar (Fcdr (args)));
- return Fprogn (Fcdr (Fcdr (args)));
-}
-
-DEFUN ("cond", Fcond, Scond, 0, UNEVALLED, 0,
- "(cond CLAUSES...): try each clause until one succeeds.\n\
-Each clause looks like (CONDITION BODY...). CONDITION 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-form.\n\
-If no clause succeeds, cond returns nil.\n\
-If a clause has one element, as in (CONDITION),\n\
-CONDITION's value if non-nil is returned from the cond-form.")
- (args)
- Lisp_Object args;
-{
- register Lisp_Object clause, val;
- struct gcpro gcpro1;
-
- val = Qnil;
- GCPRO1 (args);
- while (!NILP (args))
- {
- clause = Fcar (args);
- val = Feval (Fcar (clause));
- if (!NILP (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,
- "(progn BODY...): eval BODY forms sequentially and return value of 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 (!NILP (args) && (tem = Fcar (args), SYMBOLP (tem)))
- {
- QUIT;
- specbind (tem, val), args = Fcdr (args);
- }
- }
-
- if (NILP(args))
- return Qnil;
-
- args_left = args;
- GCPRO1 (args_left);
-
- do
- {
- val = Feval (Fcar (args_left));
- args_left = Fcdr (args_left);
- }
- while (!NILP(args_left));
-
- UNGCPRO;
- return val;
-}
-
-DEFUN ("prog1", Fprog1, Sprog1, 1, UNEVALLED, 0,
- "(prog1 FIRST BODY...): eval FIRST and BODY sequentially; value from FIRST.\n\
-The value of FIRST 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 (NILP(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 (!NILP(args_left));
-
- UNGCPRO;
- return val;
-}
-
-DEFUN ("prog2", Fprog2, Sprog2, 2, UNEVALLED, 0,
- "(prog2 X Y BODY...): eval X, Y and BODY sequentially; value from Y.\n\
-The value of Y 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 (NILP (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 (!NILP (args_left));
-
- UNGCPRO;
- return val;
-}
-
-DEFUN ("setq", Fsetq, Ssetq, 0, UNEVALLED, 0,
- "(setq SYM VAL SYM VAL ...): set each SYM to the value of its VAL.\n\
-The symbols SYM are variables; they are literal (not evaluated).\n\
-The values VAL are expressions; they are evaluated.\n\
-Thus, (setq x (1+ y)) sets `x' to the value of `(1+ y)'.\n\
-The second VAL is not computed until after the first SYM is set, and so on;\n\
-each VAL can use the new value of variables set earlier in the `setq'.\n\
-The return value of the `setq' form is the value of the last VAL.")
- (args)
- Lisp_Object args;
-{
- register Lisp_Object args_left;
- register Lisp_Object val, sym;
- struct gcpro gcpro1;
-
- if (NILP(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 (!NILP(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,
- "Like `quote', but preferred for objects which are functions.\n\
-In byte compilation, `function' causes its argument to be compiled.\n\
-`quote' cannot do that.")
- (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 (!INTERACTIVE)
- return Qnil;
-
- btp = backtrace_list;
-
- /* If this isn't a byte-compiled function, there may be a frame at
- the top for Finteractive_p itself. If so, skip it. */
- fun = Findirect_function (*btp->function);
- if (SUBRP (fun) && XSUBR (fun) == &Sinteractive_p)
- btp = btp->next;
-
- /* If we're running an Emacs 18-style byte-compiled function, there
- may be a frame for Fbytecode. Now, given the strictest
- definition, this function isn't really being called
- interactively, but because that's the way Emacs 18 always builds
- byte-compiled functions, we'll accept it for now. */
- if (EQ (*btp->function, Qbytecode))
- btp = btp->next;
-
- /* If this isn't a byte-compiled function, then we may now be
- looking at several frames for special forms. Skip past them. */
- while (btp &&
- btp->nargs == UNEVALLED)
- btp = btp->next;
-
- /* btp now points at the frame of the innermost function that isn't
- a special form, ignoring frames for Finteractive_p and/or
- Fbytecode at the top. If this frame is for a built-in function
- (such as load or eval-region) return nil. */
- fun = Findirect_function (*btp->function);
- if (SUBRP (fun))
- 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...): define 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 (!NILP (Vpurify_flag))
- defn = Fpurecopy (defn);
- Ffset (fn_name, defn);
- LOADHIST_ATTACH (fn_name);
- return fn_name;
-}
-
-DEFUN ("defmacro", Fdefmacro, Sdefmacro, 2, UNEVALLED, 0,
- "(defmacro NAME ARGLIST [DOCSTRING] BODY...): define 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 (!NILP (Vpurify_flag))
- defn = Fpurecopy (defn);
- Ffset (fn_name, defn);
- LOADHIST_ATTACH (fn_name);
- return fn_name;
-}
-
-DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0,
- "(defvar SYMBOL INITVALUE DOCSTRING): define SYMBOL as a variable.\n\
-You are not required to define a variable in order to use it,\n\
-but the definition can supply documentation and an initial value\n\
-in a way that tags can recognize.\n\n\
-INITVALUE is evaluated, and used to set SYMBOL, only if SYMBOL's value is void.\n\
-If SYMBOL is buffer-local, its default value is what is set;\n\
- buffer-local values are not affected.\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, tail;
-
- sym = Fcar (args);
- tail = Fcdr (args);
- if (!NILP (Fcdr (Fcdr (tail))))
- error ("too many arguments");
-
- if (!NILP (tail))
- {
- tem = Fdefault_boundp (sym);
- if (NILP (tem))
- Fset_default (sym, Feval (Fcar (Fcdr (args))));
- }
- tail = Fcdr (Fcdr (args));
- if (!NILP (Fcar (tail)))
- {
- tem = Fcar (tail);
- if (!NILP (Vpurify_flag))
- tem = Fpurecopy (tem);
- Fput (sym, Qvariable_documentation, tem);
- }
- LOADHIST_ATTACH (sym);
- return sym;
-}
-
-DEFUN ("defconst", Fdefconst, Sdefconst, 2, UNEVALLED, 0,
- "(defconst SYMBOL INITVALUE DOCSTRING): define 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\
-If SYMBOL is buffer-local, its default value is what is set;\n\
- buffer-local values are not affected.\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.\n\n\
-Note: do not use `defconst' for user options in libraries that are not\n\
-normally loaded, since it is useful for users to be able to specify\n\
-their own values for such variables before loading the library.\n\
-Since `defconst' unconditionally assigns the variable,\n\
-it would override the user's choice.")
- (args)
- Lisp_Object args;
-{
- register Lisp_Object sym, tem;
-
- sym = Fcar (args);
- if (!NILP (Fcdr (Fcdr (Fcdr (args)))))
- error ("too many arguments");
-
- Fset_default (sym, Feval (Fcar (Fcdr (args))));
- tem = Fcar (Fcdr (Fcdr (args)));
- if (!NILP (tem))
- {
- if (!NILP (Vpurify_flag))
- tem = Fpurecopy (tem);
- Fput (sym, Qvariable_documentation, tem);
- }
- LOADHIST_ATTACH (sym);
- 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\
-\(The alternative is a variable used internally in a Lisp program.)\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 (INTEGERP (documentation) && XINT (documentation) < 0)
- return Qt;
- if (STRINGP (documentation)
- && ((unsigned char) XSTRING (documentation)->data[0] == '*'))
- return Qt;
- /* If it is (STRING . INTEGER), a negative integer means a user variable. */
- if (CONSP (documentation)
- && STRINGP (XCONS (documentation)->car)
- && INTEGERP (XCONS (documentation)->cdr)
- && XINT (XCONS (documentation)->cdr) < 0)
- return Qt;
- return Qnil;
-}
-
-DEFUN ("let*", FletX, SletX, 1, UNEVALLED, 0,
- "(let* VARLIST BODY...): bind variables according to VARLIST then eval 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 (!NILP (varlist))
- {
- QUIT;
- elt = Fcar (varlist);
- if (SYMBOLP (elt))
- specbind (elt, Qnil);
- else if (! NILP (Fcdr (Fcdr (elt))))
- Fsignal (Qerror,
- Fcons (build_string ("`let' bindings can have only one value-form"),
- elt));
- else
- {
- val = Feval (Fcar (Fcdr (elt)));
- specbind (Fcar (elt), val);
- }
- varlist = Fcdr (varlist);
- }
- UNGCPRO;
- val = Fprogn (Fcdr (args));
- return unbind_to (count, val);
-}
-
-DEFUN ("let", Flet, Slet, 1, UNEVALLED, 0,
- "(let VARLIST BODY...): bind variables according to VARLIST then eval 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; !NILP (varlist); varlist = Fcdr (varlist))
- {
- QUIT;
- elt = Fcar (varlist);
- if (SYMBOLP (elt))
- temps [argnum++] = Qnil;
- else if (! NILP (Fcdr (Fcdr (elt))))
- Fsignal (Qerror,
- Fcons (build_string ("`let' bindings can have only one value-form"),
- elt));
- else
- temps [argnum++] = Feval (Fcar (Fcdr (elt)));
- gcpro2.nvars = argnum;
- }
- UNGCPRO;
-
- varlist = Fcar (args);
- for (argnum = 0; !NILP (varlist); varlist = Fcdr (varlist))
- {
- elt = Fcar (varlist);
- tem = temps[argnum++];
- if (SYMBOLP (elt))
- specbind (elt, tem);
- else
- specbind (Fcar (elt), tem);
- }
-
- elt = Fprogn (Fcdr (args));
- return unbind_to (count, elt);
-}
-
-DEFUN ("while", Fwhile, Swhile, 1, UNEVALLED, 0,
- "(while TEST BODY...): if TEST yields non-nil, eval BODY... and repeat.\n\
-The order of execution is thus TEST, BODY, TEST, BODY and so on\n\
-until TEST returns nil.")
- (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),
- (!EQ (Vmocklisp_arguments, Qt) ? XINT (tem) : !NILP (tem)))
- {
- QUIT;
- Fprogn (body);
- }
-
- UNGCPRO;
- return Qnil;
-}
-
-DEFUN ("macroexpand", Fmacroexpand, Smacroexpand, 1, 2, 0,
- "Return result of expanding macros at top level of FORM.\n\
-If FORM is not a macro call, it is returned unchanged.\n\
-Otherwise, the macro is expanded and the expansion is considered\n\
-in place of FORM. When a non-macro-call results, it is returned.\n\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, environment)
- Lisp_Object form;
- Lisp_Object environment;
-{
- /* With cleanups from Hallvard Furuseth. */
- 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 (!CONSP (form))
- break;
- /* Set SYM, give DEF and TEM right values in case SYM is not a symbol. */
- def = sym = XCONS (form)->car;
- tem = Qnil;
- /* Trace symbols aliases to other symbols
- until we get a symbol that is not an alias. */
- while (SYMBOLP (def))
- {
- QUIT;
- sym = def;
- tem = Fassq (sym, environment);
- if (NILP (tem))
- {
- def = XSYMBOL (sym)->function;
- if (!EQ (def, Qunbound))
- continue;
- }
- break;
- }
- /* Right now TEM is the result from SYM in ENVIRONMENT,
- and if TEM is nil then DEF is SYM's function definition. */
- if (NILP (tem))
- {
- /* SYM is not mentioned in ENVIRONMENT.
- Look at its function definition. */
- if (EQ (def, Qunbound) || !CONSP (def))
- /* Not defined or definition not suitable */
- break;
- if (EQ (XCONS (def)->car, Qautoload))
- {
- /* Autoloading function: will it be a macro when loaded? */
- tem = Fnth (make_number (4), def);
- if (EQ (tem, Qt) || EQ (tem, Qmacro))
- /* Yes, load it and try again. */
- {
- struct gcpro gcpro1;
- GCPRO1 (form);
- do_autoload (def, sym);
- UNGCPRO;
- continue;
- }
- else
- break;
- }
- else if (!EQ (XCONS (def)->car, Qmacro))
- break;
- else expander = XCONS (def)->cdr;
- }
- else
- {
- expander = XCONS (tem)->cdr;
- if (NILP (expander))
- break;
- }
- form = apply1 (expander, XCONS (form)->cdr);
- }
- return form;
-}
-
-DEFUN ("catch", Fcatch, Scatch, 1, UNEVALLED, 0,
- "(catch TAG BODY...): eval BODY allowing nonlocal exits using `throw'.\n\
-TAG is evalled to get the tag to use. Then the BODY is executed.\n\
-Within BODY, (throw TAG) with same tag exits BODY and exits this `catch'.\n\
-If no throw happens, `catch' returns the value of the last BODY form.\n\
-If a throw happens, it specifies the value to 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.pdlcount = specpdl_ptr - specpdl;
- c.poll_suppress_count = poll_suppress_count;
- 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;
-}
-
-/* Unwind the specbind, catch, and handler stacks back to CATCH, and
- jump to that CATCH, returning VALUE as the value of that catch.
-
- This is the guts Fthrow and Fsignal; they differ only in the way
- they choose the catch tag to throw to. A catch tag for a
- condition-case form has a TAG of Qnil.
-
- Before each catch is discarded, unbind all special bindings and
- execute all unwind-protect clauses made above that catch. Unwind
- the handler stack as we go, so that the proper handlers are in
- effect for each unwind-protect clause we run. At the end, restore
- some static info saved in CATCH, and longjmp to the location
- specified in the
-
- This is used for correct unwinding in Fthrow and Fsignal. */
-
-static void
-unwind_to_catch (catch, value)
- struct catchtag *catch;
- Lisp_Object value;
-{
- register int last_time;
-
- /* Save the value in the tag. */
- catch->val = value;
-
- /* Restore the polling-suppression count. */
- set_poll_suppress_count (catch->poll_suppress_count);
-
- do
- {
- last_time = catchlist == catch;
-
- /* Unwind the specpdl stack, and then restore the proper set of
- handlers. */
- unbind_to (catchlist->pdlcount, Qnil);
- handlerlist = catchlist->handlerlist;
- catchlist = catchlist->next;
- }
- while (! last_time);
-
- gcprolist = catch->gcpro;
- backtrace_list = catch->backlist;
- lisp_eval_depth = catch->lisp_eval_depth;
-
- _longjmp (catch->jmp, 1);
-}
-
-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, value)
- register Lisp_Object tag, value;
-{
- register struct catchtag *c;
-
- while (1)
- {
- if (!NILP (tag))
- for (c = catchlist; c; c = c->next)
- {
- if (EQ (c->tag, tag))
- unwind_to_catch (c, value);
- }
- tag = Fsignal (Qno_catch, Fcons (tag, Fcons (value, 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;
-
- record_unwind_protect (0, Fcdr (args));
- val = Feval (Fcar (args));
- return unbind_to (count, 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\
-Usage looks like (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\n\
-A handler is applicable to an error\n\
-if CONDITION-NAME is one of the error's condition names.\n\
-If an error happens, the first applicable handler is run.\n\
-\n\
-The car of a handler may be a list of condition names\n\
-instead of a single condition name.\n\
-\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\
-VAR may be nil; then you do not get access to the signal information.\n\
-\n\
-The value of the last BODY form is returned from the condition-case.\n\
-See also the function `signal' for more info.")
- (args)
- Lisp_Object args;
-{
- Lisp_Object val;
- struct catchtag c;
- struct handler h;
- register Lisp_Object var, bodyform, handlers;
-
- var = Fcar (args);
- bodyform = Fcar (Fcdr (args));
- handlers = Fcdr (Fcdr (args));
- CHECK_SYMBOL (var, 0);
-
- for (val = handlers; ! NILP (val); val = Fcdr (val))
- {
- Lisp_Object tem;
- tem = Fcar (val);
- if (! (NILP (tem)
- || (CONSP (tem)
- && (SYMBOLP (XCONS (tem)->car)
- || CONSP (XCONS (tem)->car)))))
- error ("Invalid condition handler", tem);
- }
-
- c.tag = Qnil;
- c.val = Qnil;
- c.backlist = backtrace_list;
- c.handlerlist = handlerlist;
- c.lisp_eval_depth = lisp_eval_depth;
- c.pdlcount = specpdl_ptr - specpdl;
- c.poll_suppress_count = poll_suppress_count;
- c.gcpro = gcprolist;
- if (_setjmp (c.jmp))
- {
- if (!NILP (h.var))
- specbind (h.var, c.val);
- val = Fprogn (Fcdr (h.chosen_clause));
-
- /* Note that this just undoes the binding of h.var; whoever
- longjumped to us unwound the stack to c.pdlcount before
- throwing. */
- unbind_to (c.pdlcount, Qnil);
- return val;
- }
- c.next = catchlist;
- catchlist = &c;
-
- h.var = var;
- h.handler = handlers;
- h.next = handlerlist;
- h.tag = &c;
- handlerlist = &h;
-
- val = Feval (bodyform);
- catchlist = c.next;
- handlerlist = h.next;
- return val;
-}
-
-/* Call the function BFUN with no arguments, catching errors within it
- according to HANDLERS. If there is an error, call HFUN with
- one argument which is the data that describes the error:
- (SIGNALNAME . DATA)
-
- HANDLERS can be a list of conditions to catch.
- If HANDLERS is Qt, catch all errors.
- If HANDLERS is Qerror, catch all errors
- but allow the debugger to run if that is enabled. */
-
-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;
-
- /* Since Fsignal resets this to 0, it had better be 0 now
- or else we have a potential bug. */
- if (interrupt_input_blocked != 0)
- abort ();
-
- c.tag = Qnil;
- c.val = Qnil;
- c.backlist = backtrace_list;
- c.handlerlist = handlerlist;
- c.lisp_eval_depth = lisp_eval_depth;
- c.pdlcount = specpdl_ptr - specpdl;
- c.poll_suppress_count = poll_suppress_count;
- c.gcpro = gcprolist;
- if (_setjmp (c.jmp))
- {
- return (*hfun) (c.val);
- }
- c.next = catchlist;
- catchlist = &c;
- h.handler = handlers;
- h.var = Qnil;
- h.next = handlerlist;
- h.tag = &c;
- handlerlist = &h;
-
- val = (*bfun) ();
- catchlist = c.next;
- handlerlist = h.next;
- return val;
-}
-
-/* Like internal_condition_case but call HFUN with ARG as its argument. */
-
-Lisp_Object
-internal_condition_case_1 (bfun, arg, handlers, hfun)
- Lisp_Object (*bfun) ();
- Lisp_Object arg;
- 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.pdlcount = specpdl_ptr - specpdl;
- c.poll_suppress_count = poll_suppress_count;
- c.gcpro = gcprolist;
- if (_setjmp (c.jmp))
- {
- return (*hfun) (c.val);
- }
- c.next = catchlist;
- catchlist = &c;
- h.handler = handlers;
- h.var = Qnil;
- h.next = handlerlist;
- h.tag = &c;
- handlerlist = &h;
-
- val = (*bfun) (arg);
- 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 ERROR-SYMBOL and associated DATA.\n\
-This function does not return.\n\n\
-An error symbol 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 normally 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 also the function `condition-case'.")
- (error_symbol, data)
- Lisp_Object error_symbol, 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 ();
-
-#ifdef HAVE_WINDOW_SYSTEM
- TOTALLY_UNBLOCK_INPUT;
-#endif
-
- /* This hook is used by edebug. */
- if (! NILP (Vsignal_hook_function))
- Ffuncall (Vsignal_hook_function, error_symbol, data);
-
- conditions = Fget (error_symbol, Qerror_conditions);
-
- for (; handlerlist; handlerlist = handlerlist->next)
- {
- register Lisp_Object clause;
- clause = find_handler_clause (handlerlist->handler, conditions,
- error_symbol, data, &debugger_value);
-
-#if 0 /* Most callers are not prepared to handle gc if this returns.
- So, since this feature is not very useful, take it out. */
- /* If have called debugger and user wants to continue,
- just return nil. */
- if (EQ (clause, Qlambda))
- return debugger_value;
-#else
- if (EQ (clause, Qlambda))
- {
- /* We can't return values to code which signaled an error, but we
- can continue code which has signaled a quit. */
- if (EQ (error_symbol, Qquit))
- return Qnil;
- else
- error ("Cannot return from the debugger in an error");
- }
-#endif
-
- if (!NILP (clause))
- {
- Lisp_Object unwind_data;
- struct handler *h = handlerlist;
-
- handlerlist = allhandlers;
- if (EQ (data, memory_signal_data))
- unwind_data = memory_signal_data;
- else
- unwind_data = Fcons (error_symbol, data);
- h->chosen_clause = clause;
- unwind_to_catch (h->tag, unwind_data);
- }
- }
-
- 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, error_symbol, data, &debugger_value);
- Fthrow (Qtop_level, Qt);
-}
-
-/* Return nonzero iff LIST is a non-nil atom or
- a list containing one of CONDITIONS. */
-
-static int
-wants_debugger (list, conditions)
- Lisp_Object list, conditions;
-{
- if (NILP (list))
- return 0;
- if (! CONSP (list))
- return 1;
-
- while (CONSP (conditions))
- {
- Lisp_Object this, tail;
- this = XCONS (conditions)->car;
- for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
- if (EQ (XCONS (tail)->car, this))
- return 1;
- conditions = XCONS (conditions)->cdr;
- }
- return 0;
-}
-
-/* Return 1 if an error with condition-symbols CONDITIONS,
- and described by SIGNAL-DATA, should skip the debugger
- according to debugger-ignore-errors. */
-
-static int
-skip_debugger (conditions, data)
- Lisp_Object conditions, data;
-{
- Lisp_Object tail;
- int first_string = 1;
- Lisp_Object error_message;
-
- for (tail = Vdebug_ignored_errors; CONSP (tail);
- tail = XCONS (tail)->cdr)
- {
- if (STRINGP (XCONS (tail)->car))
- {
- if (first_string)
- {
- error_message = Ferror_message_string (data);
- first_string = 0;
- }
- if (fast_string_match (XCONS (tail)->car, error_message) >= 0)
- return 1;
- }
- else
- {
- Lisp_Object contail;
-
- for (contail = conditions; CONSP (contail);
- contail = XCONS (contail)->cdr)
- if (EQ (XCONS (tail)->car, XCONS (contail)->car))
- return 1;
- }
- }
-
- return 0;
-}
-
-/* Value of Qlambda means we have called debugger and user has continued.
- Store value returned from debugger 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;
-
- if (EQ (handlers, Qt)) /* t is used by handlers for all conditions, set up by C code. */
- return Qt;
- /* error is used similarly, but means print an error message
- and run the debugger if that is enabled. */
- if (EQ (handlers, Qerror)
- || !NILP (Vdebug_on_signal)) /* This says call debugger even if
- there is a handler. */
- {
- int count = specpdl_ptr - specpdl;
- int debugger_called = 0;
-
- if (wants_debugger (Vstack_trace_on_error, conditions))
- internal_with_output_to_temp_buffer ("*Backtrace*", Fbacktrace, Qnil);
- if ((EQ (sig, Qquit)
- ? debug_on_quit
- : wants_debugger (Vdebug_on_error, conditions))
- && ! skip_debugger (conditions, Fcons (sig, data))
- && when_entered_debugger < num_nonmacro_input_chars)
- {
- specbind (Qdebug_on_error, Qnil);
- *debugger_value_ptr
- = call_debugger (Fcons (Qerror,
- Fcons (Fcons (sig, data),
- Qnil)));
- debugger_called = 1;
- }
- /* If there is no handler, return saying whether we ran the debugger. */
- if (EQ (handlers, Qerror))
- {
- if (debugger_called)
- return unbind_to (count, Qlambda);
- return Qt;
- }
- }
- for (h = handlers; CONSP (h); h = Fcdr (h))
- {
- Lisp_Object handler, condit;
-
- handler = Fcar (h);
- if (!CONSP (handler))
- continue;
- condit = Fcar (handler);
- /* Handle a single condition name in handler HANDLER. */
- if (SYMBOLP (condit))
- {
- tem = Fmemq (Fcar (handler), conditions);
- if (!NILP (tem))
- return handler;
- }
- /* Handle a list of condition names in handler HANDLER. */
- else if (CONSP (condit))
- {
- while (CONSP (condit))
- {
- tem = Fmemq (Fcar (condit), conditions);
- if (!NILP (tem))
- return handler;
- condit = XCONS (condit)->cdr;
- }
- }
- }
- return Qnil;
-}
-
-/* dump an error message; called like printf */
-
-/* VARARGS 1 */
-void
-error (m, a1, a2, a3)
- char *m;
- char *a1, *a2, *a3;
-{
- char buf[200];
- int size = 200;
- int mlen;
- char *buffer = buf;
- char *args[3];
- int allocated = 0;
- Lisp_Object string;
-
- args[0] = a1;
- args[1] = a2;
- args[2] = a3;
-
- mlen = strlen (m);
-
- while (1)
- {
- int used = doprnt (buf, size, m, m + mlen, 3, args);
- if (used < size)
- break;
- size *= 2;
- if (allocated)
- buffer = (char *) xrealloc (buffer, size);
- else
- {
- buffer = (char *) xmalloc (size);
- allocated = 1;
- }
- }
-
- string = build_string (buf);
- if (allocated)
- free (buffer);
-
- Fsignal (Qerror, Fcons (string, 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\n\
-definition.\n\
-\n\
-Interactively callable functions include strings and vectors (treated\n\
-as keyboard macros), lambda-expressions that contain a top-level call\n\
-to `interactive', autoload definitions made by `autoload' with non-nil\n\
-fourth argument, and some of the built-in functions of Lisp.\n\
-\n\
-Also, a symbol satisfies `commandp' if its function definition does so.")
- (function)
- Lisp_Object function;
-{
- register Lisp_Object fun;
- register Lisp_Object funcar;
- register Lisp_Object tem;
- register int i = 0;
-
- fun = function;
-
- fun = indirect_function (fun);
- if (EQ (fun, Qunbound))
- return Qnil;
-
- /* Emacs primitives are interactive if their DEFUN specifies an
- interactive spec. */
- if (SUBRP (fun))
- {
- if (XSUBR (fun)->prompt)
- return Qt;
- else
- return Qnil;
- }
-
- /* Bytecode objects are interactive if they are long enough to
- have an element whose index is COMPILED_INTERACTIVE, which is
- where the interactive spec is stored. */
- else if (COMPILEDP (fun))
- return ((XVECTOR (fun)->size & PSEUDOVECTOR_SIZE_MASK) > COMPILED_INTERACTIVE
- ? Qt : Qnil);
-
- /* Strings and vectors are keyboard macros. */
- if (STRINGP (fun) || VECTORP (fun))
- return Qt;
-
- /* Lists may represent commands. */
- if (!CONSP (fun))
- return Qnil;
- funcar = Fcar (fun);
- if (!SYMBOLP (funcar))
- 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 INTERACTIVE if non-nil says function can be called interactively.\n\
-Fifth arg TYPE indicates the type of the object:\n\
- nil or omitted says FUNCTION is a function,\n\
- `keymap' says FUNCTION is really a keymap, and\n\
- `macro' or t says 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, type)
- Lisp_Object function, file, docstring, interactive, type;
-{
-#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)
- && !(CONSP (XSYMBOL (function)->function)
- && EQ (XCONS (XSYMBOL (function)->function)->car, Qautoload)))
- return Qnil;
-
-#ifdef NO_ARG_ARRAY
- args[0] = file;
- args[1] = docstring;
- args[2] = interactive;
- args[3] = type;
-
- 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;
-}
-
-/* Load an autoloaded function.
- FUNNAME is the symbol which is the function's name.
- FUNDEF is the autoload definition (a list). */
-
-do_autoload (fundef, funname)
- Lisp_Object fundef, funname;
-{
- int count = specpdl_ptr - specpdl;
- Lisp_Object fun, val, queue, first, second;
- struct gcpro gcpro1, gcpro2, gcpro3;
-
- fun = funname;
- CHECK_SYMBOL (funname, 0);
- GCPRO3 (fun, funname, fundef);
-
- /* 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);
-
- /* Save the old autoloads, in case we ever do an unload. */
- queue = Vautoload_queue;
- while (CONSP (queue))
- {
- first = Fcar (queue);
- second = Fcdr (first);
- first = Fcar (first);
-
- /* Note: This test is subtle. The cdr of an autoload-queue entry
- may be an atom if the autoload entry was generated by a defalias
- or fset. */
- if (CONSP (second))
- Fput (first, Qautoload, (Fcdr (second)));
-
- queue = Fcdr (queue);
- }
-
- /* Once loading finishes, don't undo it. */
- Vautoload_queue = Qt;
- unbind_to (count, Qnil);
-
- fun = Findirect_function (fun);
-
- if (!NILP (Fequal (fun, fundef)))
- error ("Autoloading failed to define function %s",
- XSYMBOL (funname)->name->data);
- UNGCPRO;
-}
-
-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 (SYMBOLP (form))
- {
- if (EQ (Vmocklisp_arguments, Qt))
- return Fsymbol_value (form);
- val = Fsymbol_value (form);
- if (NILP (val))
- XSETFASTINT (val, 0);
- else if (EQ (val, Qt))
- XSETFASTINT (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 = Findirect_function (original_fun);
-
- if (SUBRP (fun))
- {
- Lisp_Object numargs;
- Lisp_Object argvals[7];
- 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)))
- return Fsignal (Qwrong_number_of_arguments, Fcons (fun, Fcons (numargs, Qnil)));
-
- 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 (!NILP (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;
- case 6:
- val = (*XSUBR (fun)->function) (argvals[0], argvals[1], argvals[2],
- argvals[3], argvals[4], argvals[5]);
- goto done;
- case 7:
- val = (*XSUBR (fun)->function) (argvals[0], argvals[1], argvals[2],
- argvals[3], argvals[4], argvals[5],
- argvals[6]);
- goto done;
-
- default:
- /* Someone has created a subr that takes more arguments than
- is supported by this code. We need to either rewrite the
- subr to use a different argument protocol, or add more
- cases to this switch. */
- abort ();
- }
- }
- if (COMPILEDP (fun))
- val = apply_lambda (fun, original_args, 1);
- else
- {
- if (!CONSP (fun))
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
- funcar = Fcar (fun);
- if (!SYMBOLP (funcar))
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
- if (EQ (funcar, Qautoload))
- {
- do_autoload (fun, original_fun);
- goto retry;
- }
- 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
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
- }
- done:
- if (!EQ (Vmocklisp_arguments, Qt))
- {
- if (NILP (val))
- XSETFASTINT (val, 0);
- else if (EQ (val, Qt))
- XSETFASTINT (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 with our remaining args, using our last arg as list of args.\n\
-Then return the value FUNCTION returns.\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;
- 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;
-
- fun = indirect_function (fun);
- if (EQ (fun, Qunbound))
- {
- /* Let funcall get the error */
- fun = args[0];
- goto funcall;
- }
-
- if (SUBRP (fun))
- {
- 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 (!NILP (spread_arg))
- {
- funcall_args [i++] = XCONS (spread_arg)->car;
- spread_arg = XCONS (spread_arg)->cdr;
- }
-
- RETURN_UNGCPRO (Ffuncall (gcpro1.nvars, funcall_args));
-}
-
-/* Run hook variables in various ways. */
-
-enum run_hooks_condition {to_completion, until_success, until_failure};
-
-DEFUN ("run-hooks", Frun_hooks, Srun_hooks, 1, MANY, 0,
- "Run each hook in HOOKS. Major mode functions use this.\n\
-Each argument should be a symbol, a hook variable.\n\
-These symbols are processed in the order specified.\n\
-If a hook symbol has a non-nil value, that value may be a function\n\
-or a list of functions to be called to run the hook.\n\
-If the value is a function, it is called with no arguments.\n\
-If it is a list, the elements are called, in order, with no arguments.\n\
-\n\
-To make a hook variable buffer-local, use `make-local-hook',\n\
-not `make-local-variable'.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
- Lisp_Object hook[1];
- register int i;
-
- for (i = 0; i < nargs; i++)
- {
- hook[0] = args[i];
- run_hook_with_args (1, hook, to_completion);
- }
-
- return Qnil;
-}
-
-DEFUN ("run-hook-with-args", Frun_hook_with_args,
- Srun_hook_with_args, 1, MANY, 0,
- "Run HOOK with the specified arguments ARGS.\n\
-HOOK should be a symbol, a hook variable. If HOOK has a non-nil\n\
-value, that value may be a function or a list of functions to be\n\
-called to run the hook. If the value is a function, it is called with\n\
-the given arguments and its return value is returned. If it is a list\n\
-of functions, those functions are called, in order,\n\
-with the given arguments ARGS.\n\
-It is best not to depend on the value return by `run-hook-with-args',\n\
-as that may change.\n\
-\n\
-To make a hook variable buffer-local, use `make-local-hook',\n\
-not `make-local-variable'.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
- return run_hook_with_args (nargs, args, to_completion);
-}
-
-DEFUN ("run-hook-with-args-until-success", Frun_hook_with_args_until_success,
- Srun_hook_with_args_until_success, 1, MANY, 0,
- "Run HOOK with the specified arguments ARGS.\n\
-HOOK should be a symbol, a hook variable. Its value should\n\
-be a list of functions. We call those functions, one by one,\n\
-passing arguments ARGS to each of them, until one of them\n\
-returns a non-nil value. Then we return that value.\n\
-If all the functions return nil, we return nil.\n\
-\n\
-To make a hook variable buffer-local, use `make-local-hook',\n\
-not `make-local-variable'.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
- return run_hook_with_args (nargs, args, until_success);
-}
-
-DEFUN ("run-hook-with-args-until-failure", Frun_hook_with_args_until_failure,
- Srun_hook_with_args_until_failure, 1, MANY, 0,
- "Run HOOK with the specified arguments ARGS.\n\
-HOOK should be a symbol, a hook variable. Its value should\n\
-be a list of functions. We call those functions, one by one,\n\
-passing arguments ARGS to each of them, until one of them\n\
-returns nil. Then we return nil.\n\
-If all the functions return non-nil, we return non-nil.\n\
-\n\
-To make a hook variable buffer-local, use `make-local-hook',\n\
-not `make-local-variable'.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
- return run_hook_with_args (nargs, args, until_failure);
-}
-
-/* ARGS[0] should be a hook symbol.
- Call each of the functions in the hook value, passing each of them
- as arguments all the rest of ARGS (all NARGS - 1 elements).
- COND specifies a condition to test after each call
- to decide whether to stop.
- The caller (or its caller, etc) must gcpro all of ARGS,
- except that it isn't necessary to gcpro ARGS[0]. */
-
-Lisp_Object
-run_hook_with_args (nargs, args, cond)
- int nargs;
- Lisp_Object *args;
- enum run_hooks_condition cond;
-{
- Lisp_Object sym, val, ret;
- struct gcpro gcpro1, gcpro2;
-
- /* If we are dying or still initializing,
- don't do anything--it would probably crash if we tried. */
- if (NILP (Vrun_hooks))
- return;
-
- sym = args[0];
- val = find_symbol_value (sym);
- ret = (cond == until_failure ? Qt : Qnil);
-
- if (EQ (val, Qunbound) || NILP (val))
- return ret;
- else if (!CONSP (val) || EQ (XCONS (val)->car, Qlambda))
- {
- args[0] = val;
- return Ffuncall (nargs, args);
- }
- else
- {
- GCPRO2 (sym, val);
-
- for (;
- CONSP (val) && ((cond == to_completion)
- || (cond == until_success ? NILP (ret)
- : !NILP (ret)));
- val = XCONS (val)->cdr)
- {
- if (EQ (XCONS (val)->car, Qt))
- {
- /* t indicates this hook has a local binding;
- it means to run the global binding too. */
- Lisp_Object globals;
-
- for (globals = Fdefault_value (sym);
- CONSP (globals) && ((cond == to_completion)
- || (cond == until_success ? NILP (ret)
- : !NILP (ret)));
- globals = XCONS (globals)->cdr)
- {
- args[0] = XCONS (globals)->car;
- /* In a global value, t should not occur. If it does, we
- must ignore it to avoid an endless loop. */
- if (!EQ (args[0], Qt))
- ret = Ffuncall (nargs, args);
- }
- }
- else
- {
- args[0] = XCONS (val)->car;
- ret = Ffuncall (nargs, args);
- }
- }
-
- UNGCPRO;
- return ret;
- }
-}
-
-/* Run a hook symbol ARGS[0], but use FUNLIST instead of the actual
- present value of that symbol.
- Call each element of FUNLIST,
- passing each of them the rest of ARGS.
- The caller (or its caller, etc) must gcpro all of ARGS,
- except that it isn't necessary to gcpro ARGS[0]. */
-
-Lisp_Object
-run_hook_list_with_args (funlist, nargs, args)
- Lisp_Object funlist;
- int nargs;
- Lisp_Object *args;
-{
- Lisp_Object sym;
- Lisp_Object val;
- struct gcpro gcpro1, gcpro2;
-
- sym = args[0];
- GCPRO2 (sym, val);
-
- for (val = funlist; CONSP (val); val = XCONS (val)->cdr)
- {
- if (EQ (XCONS (val)->car, Qt))
- {
- /* t indicates this hook has a local binding;
- it means to run the global binding too. */
- Lisp_Object globals;
-
- for (globals = Fdefault_value (sym);
- CONSP (globals);
- globals = XCONS (globals)->cdr)
- {
- args[0] = XCONS (globals)->car;
- /* In a global value, t should not occur. If it does, we
- must ignore it to avoid an endless loop. */
- if (!EQ (args[0], Qt))
- Ffuncall (nargs, args);
- }
- }
- else
- {
- args[0] = XCONS (val)->car;
- Ffuncall (nargs, args);
- }
- }
- UNGCPRO;
- return Qnil;
-}
-
-/* Run the hook HOOK, giving each function the two args ARG1 and ARG2. */
-
-void
-run_hook_with_args_2 (hook, arg1, arg2)
- Lisp_Object hook, arg1, arg2;
-{
- Lisp_Object temp[3];
- temp[0] = hook;
- temp[1] = arg1;
- temp[2] = arg2;
-
- Frun_hook_with_args (3, temp);
-}
-
-/* Apply fn to arg */
-Lisp_Object
-apply1 (fn, arg)
- Lisp_Object fn, arg;
-{
- struct gcpro gcpro1;
-
- GCPRO1 (fn);
- if (NILP (arg))
- RETURN_UNGCPRO (Ffuncall (1, &fn));
- gcpro1.nvars = 2;
-#ifdef NO_ARG_ARRAY
- {
- Lisp_Object args[2];
- args[0] = fn;
- args[1] = arg;
- gcpro1.var = args;
- RETURN_UNGCPRO (Fapply (2, args));
- }
-#else /* not NO_ARG_ARRAY */
- RETURN_UNGCPRO (Fapply (2, &fn));
-#endif /* not NO_ARG_ARRAY */
-}
-
-/* Call function fn on no arguments */
-Lisp_Object
-call0 (fn)
- Lisp_Object fn;
-{
- struct gcpro gcpro1;
-
- GCPRO1 (fn);
- RETURN_UNGCPRO (Ffuncall (1, &fn));
-}
-
-/* Call function fn with 1 argument arg1 */
-/* ARGSUSED */
-Lisp_Object
-call1 (fn, arg1)
- Lisp_Object fn, arg1;
-{
- struct gcpro gcpro1;
-#ifdef NO_ARG_ARRAY
- Lisp_Object args[2];
-
- args[0] = fn;
- args[1] = arg1;
- GCPRO1 (args[0]);
- gcpro1.nvars = 2;
- RETURN_UNGCPRO (Ffuncall (2, args));
-#else /* not NO_ARG_ARRAY */
- GCPRO1 (fn);
- gcpro1.nvars = 2;
- RETURN_UNGCPRO (Ffuncall (2, &fn));
-#endif /* not NO_ARG_ARRAY */
-}
-
-/* Call function fn with 2 arguments arg1, arg2 */
-/* ARGSUSED */
-Lisp_Object
-call2 (fn, arg1, arg2)
- Lisp_Object fn, arg1, arg2;
-{
- struct gcpro gcpro1;
-#ifdef NO_ARG_ARRAY
- Lisp_Object args[3];
- args[0] = fn;
- args[1] = arg1;
- args[2] = arg2;
- GCPRO1 (args[0]);
- gcpro1.nvars = 3;
- RETURN_UNGCPRO (Ffuncall (3, args));
-#else /* not NO_ARG_ARRAY */
- GCPRO1 (fn);
- gcpro1.nvars = 3;
- RETURN_UNGCPRO (Ffuncall (3, &fn));
-#endif /* not NO_ARG_ARRAY */
-}
-
-/* Call function fn with 3 arguments arg1, arg2, arg3 */
-/* ARGSUSED */
-Lisp_Object
-call3 (fn, arg1, arg2, arg3)
- Lisp_Object fn, arg1, arg2, arg3;
-{
- struct gcpro gcpro1;
-#ifdef NO_ARG_ARRAY
- Lisp_Object args[4];
- args[0] = fn;
- args[1] = arg1;
- args[2] = arg2;
- args[3] = arg3;
- GCPRO1 (args[0]);
- gcpro1.nvars = 4;
- RETURN_UNGCPRO (Ffuncall (4, args));
-#else /* not NO_ARG_ARRAY */
- GCPRO1 (fn);
- gcpro1.nvars = 4;
- RETURN_UNGCPRO (Ffuncall (4, &fn));
-#endif /* not NO_ARG_ARRAY */
-}
-
-/* Call function fn with 4 arguments arg1, arg2, arg3, arg4 */
-/* ARGSUSED */
-Lisp_Object
-call4 (fn, arg1, arg2, arg3, arg4)
- Lisp_Object fn, arg1, arg2, arg3, arg4;
-{
- struct gcpro gcpro1;
-#ifdef NO_ARG_ARRAY
- Lisp_Object args[5];
- args[0] = fn;
- args[1] = arg1;
- args[2] = arg2;
- args[3] = arg3;
- args[4] = arg4;
- GCPRO1 (args[0]);
- gcpro1.nvars = 5;
- RETURN_UNGCPRO (Ffuncall (5, args));
-#else /* not NO_ARG_ARRAY */
- GCPRO1 (fn);
- gcpro1.nvars = 5;
- RETURN_UNGCPRO (Ffuncall (5, &fn));
-#endif /* not NO_ARG_ARRAY */
-}
-
-/* Call function fn with 5 arguments arg1, arg2, arg3, arg4, arg5 */
-/* ARGSUSED */
-Lisp_Object
-call5 (fn, arg1, arg2, arg3, arg4, arg5)
- Lisp_Object fn, arg1, arg2, arg3, arg4, arg5;
-{
- struct gcpro gcpro1;
-#ifdef NO_ARG_ARRAY
- Lisp_Object args[6];
- args[0] = fn;
- args[1] = arg1;
- args[2] = arg2;
- args[3] = arg3;
- args[4] = arg4;
- args[5] = arg5;
- GCPRO1 (args[0]);
- gcpro1.nvars = 6;
- RETURN_UNGCPRO (Ffuncall (6, args));
-#else /* not NO_ARG_ARRAY */
- GCPRO1 (fn);
- gcpro1.nvars = 6;
- RETURN_UNGCPRO (Ffuncall (6, &fn));
-#endif /* not NO_ARG_ARRAY */
-}
-
-/* Call function fn with 6 arguments arg1, arg2, arg3, arg4, arg5, arg6 */
-/* ARGSUSED */
-Lisp_Object
-call6 (fn, arg1, arg2, arg3, arg4, arg5, arg6)
- Lisp_Object fn, arg1, arg2, arg3, arg4, arg5, arg6;
-{
- struct gcpro gcpro1;
-#ifdef NO_ARG_ARRAY
- Lisp_Object args[7];
- args[0] = fn;
- args[1] = arg1;
- args[2] = arg2;
- args[3] = arg3;
- args[4] = arg4;
- args[5] = arg5;
- args[6] = arg6;
- GCPRO1 (args[0]);
- gcpro1.nvars = 7;
- RETURN_UNGCPRO (Ffuncall (7, args));
-#else /* not NO_ARG_ARRAY */
- GCPRO1 (fn);
- gcpro1.nvars = 7;
- RETURN_UNGCPRO (Ffuncall (7, &fn));
-#endif /* not NO_ARG_ARRAY */
-}
-
-DEFUN ("funcall", Ffuncall, Sfuncall, 1, MANY, 0,
- "Call first argument as a function, passing remaining arguments to it.\n\
-Return the value that function returns.\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];
-
- fun = Findirect_function (fun);
-
- if (SUBRP (fun))
- {
- if (numargs < XSUBR (fun)->min_args
- || (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < numargs))
- {
- XSETFASTINT (lisp_numargs, numargs);
- return Fsignal (Qwrong_number_of_arguments, Fcons (fun, Fcons (lisp_numargs, Qnil)));
- }
-
- if (XSUBR (fun)->max_args == UNEVALLED)
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
-
- 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;
- case 6:
- val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],
- internal_args[2], internal_args[3],
- internal_args[4], internal_args[5]);
- goto done;
- case 7:
- val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],
- internal_args[2], internal_args[3],
- internal_args[4], internal_args[5],
- internal_args[6]);
- goto done;
-
- default:
-
- /* If a subr takes more than 6 arguments without using MANY
- or UNEVALLED, we need to extend this function to support it.
- Until this is done, there is no way to call the function. */
- abort ();
- }
- }
- if (COMPILEDP (fun))
- val = funcall_lambda (fun, numargs, args + 1);
- else
- {
- if (!CONSP (fun))
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
- funcar = Fcar (fun);
- if (!SYMBOLP (funcar))
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
- 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
- return 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;
-}
-
-/* Apply a Lisp function FUN to the NARGS evaluated arguments in ARG_VECTOR
- and return the result of evaluation.
- FUN must be either a lambda-expression or a compiled-code object. */
-
-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! */
-
- XSETFASTINT (numargs, nargs);
-
- if (CONSP (fun))
- syms_left = Fcar (Fcdr (fun));
- else if (COMPILEDP (fun))
- syms_left = XVECTOR (fun)->contents[COMPILED_ARGLIST];
- else abort ();
-
- i = 0;
- for (; !NILP (syms_left); syms_left = Fcdr (syms_left))
- {
- QUIT;
- next = Fcar (syms_left);
- while (!SYMBOLP (next))
- 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)));
-
- if (CONSP (fun))
- val = Fprogn (Fcdr (Fcdr (fun)));
- else
- {
- /* If we have not actually read the bytecode string
- and constants vector yet, fetch them from the file. */
- if (CONSP (XVECTOR (fun)->contents[COMPILED_BYTECODE]))
- Ffetch_bytecode (fun);
- val = Fbyte_code (XVECTOR (fun)->contents[COMPILED_BYTECODE],
- XVECTOR (fun)->contents[COMPILED_CONSTANTS],
- XVECTOR (fun)->contents[COMPILED_STACK_DEPTH]);
- }
- return unbind_to (count, val);
-}
-
-DEFUN ("fetch-bytecode", Ffetch_bytecode, Sfetch_bytecode,
- 1, 1, 0,
- "If byte-compiled OBJECT is lazy-loaded, fetch it now.")
- (object)
- Lisp_Object object;
-{
- Lisp_Object tem;
-
- if (COMPILEDP (object)
- && CONSP (XVECTOR (object)->contents[COMPILED_BYTECODE]))
- {
- tem = read_doc_string (XVECTOR (object)->contents[COMPILED_BYTECODE]);
- if (!CONSP (tem))
- error ("invalid byte code");
- XVECTOR (object)->contents[COMPILED_BYTECODE] = XCONS (tem)->car;
- XVECTOR (object)->contents[COMPILED_CONSTANTS] = XCONS (tem)->cdr;
- }
- return object;
-}
-
-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)
- {
- if (!NILP (Vdebug_on_error))
- /* Leave room for some specpdl in the debugger. */
- max_specpdl_size = specpdl_size + 100;
- Fsignal (Qerror,
- Fcons (build_string ("Variable binding depth exceeds max-specpdl-size"), Qnil));
- }
- }
- 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;
-{
- Lisp_Object ovalue;
-
- CHECK_SYMBOL (symbol, 0);
-
- if (specpdl_ptr == specpdl + specpdl_size)
- grow_specpdl ();
- specpdl_ptr->symbol = symbol;
- specpdl_ptr->func = 0;
- specpdl_ptr->old_value = ovalue = find_symbol_value (symbol);
- specpdl_ptr++;
- if (BUFFER_OBJFWDP (ovalue) || KBOARD_OBJFWDP (ovalue))
- 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++;
-}
-
-Lisp_Object
-unbind_to (count, value)
- int count;
- Lisp_Object value;
-{
- int quitf = !NILP (Vquit_flag);
- struct gcpro gcpro1;
-
- GCPRO1 (value);
-
- 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 (NILP (specpdl_ptr->symbol))
- Fprogn (specpdl_ptr->old_value);
- else
- Fset (specpdl_ptr->symbol, specpdl_ptr->old_value);
- }
- if (NILP (Vquit_flag) && quitf) Vquit_flag = Qt;
-
- UNGCPRO;
-
- return value;
-}
-
-#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 = !NILP (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;
- extern Lisp_Object Vprint_level;
- struct gcpro gcpro1;
-
- XSETFASTINT (Vprint_level, 3);
-
- tail = Qnil;
- GCPRO1 (tail);
-
- while (backlist)
- {
- write_string (backlist->debug_on_exit ? "* " : " ", 2);
- if (backlist->nargs == UNEVALLED)
- {
- Fprin1 (Fcons (*backlist->function, *backlist->args), Qnil);
- write_string ("\n", -1);
- }
- else
- {
- tem = *backlist->function;
- Fprin1 (tem, Qnil); /* This can QUIT */
- write_string ("(", -1);
- if (backlist->nargs == MANY)
- {
- for (tail = *backlist->args, i = 0;
- !NILP (tail);
- tail = Fcdr (tail), i++)
- {
- if (i) write_string (" ", -1);
- Fprin1 (Fcar (tail), Qnil);
- }
- }
- else
- {
- for (i = 0; i < backlist->nargs; i++)
- {
- if (i) write_string (" ", -1);
- Fprin1 (backlist->args[i], Qnil);
- }
- }
- write_string (")\n", -1);
- }
- backlist = backlist->next;
- }
-
- Vprint_level = Qnil;
- UNGCPRO;
- return Qnil;
-}
-
-DEFUN ("backtrace-frame", Fbacktrace_frame, Sbacktrace_frame, 1, 1, "",
- "Return the function and arguments NFRAMES up from current execution point.\n\
-If that frame has not evaluated the arguments yet (or is a special form),\n\
-the value is (nil FUNCTION ARG-FORMS...).\n\
-If that frame has evaluated its arguments and called its function already,\n\
-the value is (t FUNCTION ARG-VALUES...).\n\
-A &rest arg is represented as the tail of the list ARG-VALUES.\n\
-FUNCTION is whatever was supplied as car of evaluated list,\n\
-or a lambda expression for macro calls.\n\
-If NFRAMES is more than the number of frames, the value is nil.")
- (nframes)
- Lisp_Object nframes;
-{
- register struct backtrace *backlist = backtrace_list;
- register int i;
- Lisp_Object tem;
-
- CHECK_NATNUM (nframes, 0);
-
- /* Find the frame requested. */
- for (i = 0; backlist && i < XFASTINT (nframes); i++)
- backlist = backlist->next;
-
- if (!backlist)
- return Qnil;
- if (backlist->nargs == UNEVALLED)
- return Fcons (Qnil, Fcons (*backlist->function, *backlist->args));
- else
- {
- if (backlist->nargs == MANY)
- tem = *backlist->args;
- else
- tem = Flist (backlist->nargs, backlist->args);
-
- return Fcons (Qt, Fcons (*backlist->function, tem));
- }
-}
-
-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.\n\
-This limit is to catch infinite recursions for you before they cause\n\
-actual stack overflow in C, which would be fatal for Emacs.\n\
-You can safely make it considerably larger than its default value,\n\
-if that proves inconveniently small.");
-
- 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;
-
- 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 signaled 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;
-
- Qinhibit_quit = intern ("inhibit-quit");
- staticpro (&Qinhibit_quit);
-
- Qautoload = intern ("autoload");
- staticpro (&Qautoload);
-
- Qdebug_on_error = intern ("debug-on-error");
- staticpro (&Qdebug_on_error);
-
- 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_LISP ("stack-trace-on-error", &Vstack_trace_on_error,
- "*Non-nil means automatically display a backtrace buffer\n\
-after any error that is handled by the editor command loop.\n\
-If the value is a list, an error only means to display a backtrace\n\
-if one of its condition symbols appears in the list.");
- Vstack_trace_on_error = Qnil;
-
- DEFVAR_LISP ("debug-on-error", &Vdebug_on_error,
- "*Non-nil means enter debugger if an error is signaled.\n\
-Does not apply to errors handled by `condition-case'.\n\
-If the value is a list, an error only means to enter the debugger\n\
-if one of its condition symbols appears in the list.\n\
-See also variable `debug-on-quit'.");
- Vdebug_on_error = Qnil;
-
- DEFVAR_LISP ("debug-ignored-errors", &Vdebug_ignored_errors,
- "*List of errors for which the debugger should not be called.\n\
-Each element may be a condition-name or a regexp that matches error messages.\n\
-If any element applies to a given error, that error skips the debugger\n\
-and just returns to top level.\n\
-This overrides the variable `debug-on-error'.\n\
-It does not apply to errors handled by `condition-case'.");
- Vdebug_ignored_errors = Qnil;
-
- 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 the value being returned;\n\
- this function's value will be returned instead of that.\n\
-If due to error, args are `error' and a list of the args to `signal'.\n\
-If due to `apply' or `funcall' entry, one arg, `lambda'.\n\
-If due to `eval' entry, one arg, t.");
- Vdebugger = Qnil;
-
- DEFVAR_LISP ("signal-hook-function", &Vsignal_hook_function,
- "If non-nil, this is a function for `signal' to call.\n\
-It receives the same arguments that `signal' was given.\n\
-The Edebug package uses this to regain control.");
- Vsignal_hook_function = 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;
-
- DEFVAR_LISP ("debug-on-signal", &Vdebug_on_signal,
- "*Non-nil means call the debugger regardless of condition handlers.\n\
-Note that `debug-on-error', `debug-on-quit' and friends\n\
-still determine whether to handle the particular condition.");
- Vdebug_on_signal = Qnil;
-
- Vrun_hooks = intern ("run-hooks");
- staticpro (&Vrun_hooks);
-
- 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 (&Srun_hooks);
- defsubr (&Srun_hook_with_args);
- defsubr (&Srun_hook_with_args_until_success);
- defsubr (&Srun_hook_with_args_until_failure);
- defsubr (&Sfetch_bytecode);
- defsubr (&Sbacktrace_debug);
- defsubr (&Sbacktrace);
- defsubr (&Sbacktrace_frame);
-}
diff --git a/src/fileio.c b/src/fileio.c
deleted file mode 100644
index 9d7fa4aadd4..00000000000
--- a/src/fileio.c
+++ /dev/null
@@ -1,4774 +0,0 @@
-/* File IO for GNU Emacs.
- Copyright (C) 1985,86,87,88,93,94,95,96 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include <config.h>
-
-#if defined (USG5) || defined (BSD_SYSTEM) || defined (LINUX)
-#include <fcntl.h>
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#if !defined (S_ISLNK) && defined (S_IFLNK)
-# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
-#endif
-
-#if !defined (S_ISFIFO) && defined (S_IFIFO)
-# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
-#endif
-
-#if !defined (S_ISREG) && defined (S_IFREG)
-# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#endif
-
-#ifdef VMS
-#include "vms-pwd.h"
-#else
-#include <pwd.h>
-#endif
-
-#ifdef MSDOS
-#include "msdos.h"
-#include <sys/param.h>
-#if __DJGPP__ >= 2
-#include <fcntl.h>
-#include <string.h>
-#endif
-#endif
-
-#include <ctype.h>
-
-#ifdef VMS
-#include "vmsdir.h"
-#include <perror.h>
-#include <stddef.h>
-#include <string.h>
-#endif
-
-#include <errno.h>
-
-#ifndef vax11c
-extern int errno;
-#endif
-
-extern char *strerror ();
-
-#ifdef APOLLO
-#include <sys/time.h>
-#endif
-
-#ifndef USG
-#ifndef VMS
-#ifndef BSD4_1
-#ifndef WINDOWSNT
-#define HAVE_FSYNC
-#endif
-#endif
-#endif
-#endif
-
-#include "lisp.h"
-#include "intervals.h"
-#include "buffer.h"
-#include "window.h"
-
-#ifdef WINDOWSNT
-#define NOMINMAX 1
-#include <windows.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#endif /* not WINDOWSNT */
-
-#ifdef DOS_NT
-#define CORRECT_DIR_SEPS(s) \
- do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
- else unixtodos_filename (s); \
- } while (0)
-/* On Windows, drive letters must be alphabetic - on DOS, the Netware
- redirector allows the six letters between 'Z' and 'a' as well. */
-#ifdef MSDOS
-#define IS_DRIVE(x) ((x) >= 'A' && (x) <= 'z')
-#endif
-#ifdef WINDOWSNT
-#define IS_DRIVE(x) isalpha (x)
-#endif
-/* Need to lower-case the drive letter, or else expanded
- filenames will sometimes compare inequal, because
- `expand-file-name' doesn't always down-case the drive letter. */
-#define DRIVE_LETTER(x) (tolower (x))
-#endif
-
-#ifdef VMS
-#include <file.h>
-#include <rmsdef.h>
-#include <fab.h>
-#include <nam.h>
-#endif
-
-#include "systime.h"
-
-#ifdef HPUX
-#include <netio.h>
-#ifndef HPUX8
-#ifndef HPUX9
-#include <errnet.h>
-#endif
-#endif
-#endif
-
-#ifndef O_WRONLY
-#define O_WRONLY 1
-#endif
-
-#ifndef O_RDONLY
-#define O_RDONLY 0
-#endif
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) > (b) ? (a) : (b))
-
-/* 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;
-
-/* Alist of elements (REGEXP . HANDLER) for file names
- whose I/O is done with a special handler. */
-Lisp_Object Vfile_name_handler_alist;
-
-/* Format for auto-save files */
-Lisp_Object Vauto_save_file_format;
-
-/* Lisp functions for translating file formats */
-Lisp_Object Qformat_decode, Qformat_annotate_function;
-
-/* Functions to be called to process text properties in inserted file. */
-Lisp_Object Vafter_insert_file_functions;
-
-/* Functions to be called to create text property annotations for file. */
-Lisp_Object Vwrite_region_annotate_functions;
-
-/* During build_annotations, each time an annotation function is called,
- this holds the annotations made by the previous functions. */
-Lisp_Object Vwrite_region_annotations_so_far;
-
-/* File name in which we write a list of all our auto save files. */
-Lisp_Object Vauto_save_list_file_name;
-
-/* Nonzero means, when reading a filename in the minibuffer,
- start out by inserting the default directory into the minibuffer. */
-int insert_default_directory;
-
-/* On VMS, nonzero means write new files with record format stmlf.
- Zero means use var format. */
-int vms_stmlf_recfm;
-
-/* On NT, specifies the directory separator character, used (eg.) when
- expanding file names. This can be bound to / or \. */
-Lisp_Object Vdirectory_sep_char;
-
-extern Lisp_Object Vuser_login_name;
-
-extern int minibuf_level;
-
-/* These variables describe handlers that have "already" had a chance
- to handle the current operation.
-
- Vinhibit_file_name_handlers is a list of file name handlers.
- Vinhibit_file_name_operation is the operation being handled.
- If we try to handle that operation, we ignore those handlers. */
-
-static Lisp_Object Vinhibit_file_name_handlers;
-static Lisp_Object Vinhibit_file_name_operation;
-
-Lisp_Object Qfile_error, Qfile_already_exists;
-
-Lisp_Object Qfile_name_history;
-
-Lisp_Object Qcar_less_than_car;
-
-report_file_error (string, data)
- char *string;
- Lisp_Object data;
-{
- Lisp_Object errstring;
-
- errstring = build_string (strerror (errno));
-
- /* System error messages are capitalized. Downcase the initial
- unless it is followed by a slash. */
- if (XSTRING (errstring)->data[1] != '/')
- XSTRING (errstring)->data[0] = DOWNCASE (XSTRING (errstring)->data[0]);
-
- while (1)
- Fsignal (Qfile_error,
- Fcons (build_string (string), Fcons (errstring, data)));
-}
-
-close_file_unwind (fd)
- Lisp_Object fd;
-{
- close (XFASTINT (fd));
-}
-
-/* Restore point, having saved it as a marker. */
-
-restore_point_unwind (location)
- Lisp_Object location;
-{
- SET_PT (marker_position (location));
- Fset_marker (location, Qnil, Qnil);
-}
-
-Lisp_Object Qexpand_file_name;
-Lisp_Object Qsubstitute_in_file_name;
-Lisp_Object Qdirectory_file_name;
-Lisp_Object Qfile_name_directory;
-Lisp_Object Qfile_name_nondirectory;
-Lisp_Object Qunhandled_file_name_directory;
-Lisp_Object Qfile_name_as_directory;
-Lisp_Object Qcopy_file;
-Lisp_Object Qmake_directory_internal;
-Lisp_Object Qdelete_directory;
-Lisp_Object Qdelete_file;
-Lisp_Object Qrename_file;
-Lisp_Object Qadd_name_to_file;
-Lisp_Object Qmake_symbolic_link;
-Lisp_Object Qfile_exists_p;
-Lisp_Object Qfile_executable_p;
-Lisp_Object Qfile_readable_p;
-Lisp_Object Qfile_writable_p;
-Lisp_Object Qfile_symlink_p;
-Lisp_Object Qaccess_file;
-Lisp_Object Qfile_directory_p;
-Lisp_Object Qfile_regular_p;
-Lisp_Object Qfile_accessible_directory_p;
-Lisp_Object Qfile_modes;
-Lisp_Object Qset_file_modes;
-Lisp_Object Qfile_newer_than_file_p;
-Lisp_Object Qinsert_file_contents;
-Lisp_Object Qwrite_region;
-Lisp_Object Qverify_visited_file_modtime;
-Lisp_Object Qset_visited_file_modtime;
-
-DEFUN ("find-file-name-handler", Ffind_file_name_handler, Sfind_file_name_handler, 2, 2, 0,
- "Return FILENAME's handler function for OPERATION, if it has one.\n\
-Otherwise, return nil.\n\
-A file name is handled if one of the regular expressions in\n\
-`file-name-handler-alist' matches it.\n\n\
-If OPERATION equals `inhibit-file-name-operation', then we ignore\n\
-any handlers that are members of `inhibit-file-name-handlers',\n\
-but we still do run any other handlers. This lets handlers\n\
-use the standard functions without calling themselves recursively.")
- (filename, operation)
- Lisp_Object filename, operation;
-{
- /* This function must not munge the match data. */
- Lisp_Object chain, inhibited_handlers;
-
- CHECK_STRING (filename, 0);
-
- if (EQ (operation, Vinhibit_file_name_operation))
- inhibited_handlers = Vinhibit_file_name_handlers;
- else
- inhibited_handlers = Qnil;
-
- for (chain = Vfile_name_handler_alist; CONSP (chain);
- chain = XCONS (chain)->cdr)
- {
- Lisp_Object elt;
- elt = XCONS (chain)->car;
- if (CONSP (elt))
- {
- Lisp_Object string;
- string = XCONS (elt)->car;
- if (STRINGP (string) && fast_string_match (string, filename) >= 0)
- {
- Lisp_Object handler, tem;
-
- handler = XCONS (elt)->cdr;
- tem = Fmemq (handler, inhibited_handlers);
- if (NILP (tem))
- return handler;
- }
- }
-
- QUIT;
- }
- return Qnil;
-}
-
-DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,
- 1, 1, 0,
- "Return the directory component in file name FILENAME.\n\
-Return nil if FILENAME does not include a directory.\n\
-Otherwise return 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 `>'.")
- (filename)
- Lisp_Object filename;
-{
- register unsigned char *beg;
- register unsigned char *p;
- Lisp_Object handler;
-
- CHECK_STRING (filename, 0);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qfile_name_directory);
- if (!NILP (handler))
- return call2 (handler, Qfile_name_directory, filename);
-
-#ifdef FILE_SYSTEM_CASE
- filename = FILE_SYSTEM_CASE (filename);
-#endif
- beg = XSTRING (filename)->data;
-#ifdef DOS_NT
- beg = strcpy (alloca (strlen (beg) + 1), beg);
-#endif
- p = beg + XSTRING (filename)->size;
-
- while (p != beg && !IS_DIRECTORY_SEP (p[-1])
-#ifdef VMS
- && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
-#endif /* VMS */
-#ifdef DOS_NT
- /* only recognise drive specifier at beginning */
- && !(p[-1] == ':' && p == beg + 2)
-#endif
- ) p--;
-
- if (p == beg)
- return Qnil;
-#ifdef DOS_NT
- /* Expansion of "c:" to drive and default directory. */
- if (p == beg + 2 && beg[1] == ':')
- {
- /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */
- unsigned char *res = alloca (MAXPATHLEN + 1);
- if (getdefdir (toupper (*beg) - 'A' + 1, res))
- {
- if (!IS_DIRECTORY_SEP (res[strlen (res) - 1]))
- strcat (res, "/");
- beg = res;
- p = beg + strlen (beg);
- }
- }
- CORRECT_DIR_SEPS (beg);
-#endif /* DOS_NT */
- return make_string (beg, p - beg);
-}
-
-DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, Sfile_name_nondirectory,
- 1, 1, 0,
- "Return file name FILENAME sans its directory.\n\
-For example, in a Unix-syntax file name,\n\
-this is everything after the last slash,\n\
-or the entire name if it contains no slash.")
- (filename)
- Lisp_Object filename;
-{
- register unsigned char *beg, *p, *end;
- Lisp_Object handler;
-
- CHECK_STRING (filename, 0);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qfile_name_nondirectory);
- if (!NILP (handler))
- return call2 (handler, Qfile_name_nondirectory, filename);
-
- beg = XSTRING (filename)->data;
- end = p = beg + XSTRING (filename)->size;
-
- while (p != beg && !IS_DIRECTORY_SEP (p[-1])
-#ifdef VMS
- && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
-#endif /* VMS */
-#ifdef DOS_NT
- /* only recognise drive specifier at beginning */
- && !(p[-1] == ':' && p == beg + 2)
-#endif
- ) p--;
-
- return make_string (p, end - p);
-}
-
-DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, Sunhandled_file_name_directory, 1, 1, 0,
- "Return a directly usable directory name somehow associated with FILENAME.\n\
-A `directly usable' directory name is one that may be used without the\n\
-intervention of any file handler.\n\
-If FILENAME is a directly usable file itself, return\n\
-(file-name-directory FILENAME).\n\
-The `call-process' and `start-process' functions use this function to\n\
-get a current directory to run processes in.")
- (filename)
- Lisp_Object filename;
-{
- Lisp_Object handler;
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qunhandled_file_name_directory);
- if (!NILP (handler))
- return call2 (handler, Qunhandled_file_name_directory, filename);
-
- return Ffile_name_directory (filename);
-}
-
-
-char *
-file_name_as_directory (out, in)
- char *out, *in;
-{
- int size = strlen (in) - 1;
-
- strcpy (out, in);
-
-#ifdef VMS
- /* Is it already a directory string? */
- if (in[size] == ':' || in[size] == ']' || in[size] == '>')
- return out;
- /* Is it a VMS directory file name? If so, hack VMS syntax. */
- else if (! index (in, '/')
- && ((size > 3 && ! strcmp (&in[size - 3], ".DIR"))
- || (size > 3 && ! strcmp (&in[size - 3], ".dir"))
- || (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4)
- || ! strncmp (&in[size - 5], ".dir", 4))
- && (in[size - 1] == '.' || in[size - 1] == ';')
- && in[size] == '1')))
- {
- register char *p, *dot;
- char brack;
-
- /* x.dir -> [.x]
- dir:x.dir --> dir:[x]
- dir:[x]y.dir --> dir:[x.y] */
- p = in + size;
- while (p != in && *p != ':' && *p != '>' && *p != ']') p--;
- if (p != in)
- {
- strncpy (out, in, p - in);
- out[p - in] = '\0';
- if (*p == ':')
- {
- brack = ']';
- strcat (out, ":[");
- }
- else
- {
- brack = *p;
- strcat (out, ".");
- }
- p++;
- }
- else
- {
- brack = ']';
- strcpy (out, "[.");
- }
- dot = index (p, '.');
- if (dot)
- {
- /* blindly remove any extension */
- size = strlen (out) + (dot - p);
- strncat (out, p, dot - p);
- }
- else
- {
- strcat (out, p);
- size = strlen (out);
- }
- out[size++] = brack;
- out[size] = '\0';
- }
-#else /* not VMS */
- /* For Unix syntax, Append a slash if necessary */
- if (!IS_DIRECTORY_SEP (out[size]))
- {
- out[size + 1] = DIRECTORY_SEP;
- out[size + 2] = '\0';
- }
-#ifdef DOS_NT
- CORRECT_DIR_SEPS (out);
-#endif
-#endif /* not VMS */
- return out;
-}
-
-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\
-For a Unix-syntax file name, just appends a slash.\n\
-On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
- (file)
- Lisp_Object file;
-{
- char *buf;
- Lisp_Object handler;
-
- CHECK_STRING (file, 0);
- if (NILP (file))
- return Qnil;
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (file, Qfile_name_as_directory);
- if (!NILP (handler))
- return call2 (handler, Qfile_name_as_directory, file);
-
- buf = (char *) alloca (XSTRING (file)->size + 10);
- return build_string (file_name_as_directory (buf, XSTRING (file)->data));
-}
-
-/*
- * Convert from directory name to filename.
- * On VMS:
- * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
- * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
- * On UNIX, it's simple: just make sure there isn't a terminating /
-
- * Value is nonzero if the string output is different from the input.
- */
-
-directory_file_name (src, dst)
- char *src, *dst;
-{
- long slen;
-#ifdef VMS
- long rlen;
- char * ptr, * rptr;
- char bracket;
- struct FAB fab = cc$rms_fab;
- struct NAM nam = cc$rms_nam;
- char esa[NAM$C_MAXRSS];
-#endif /* VMS */
-
- slen = strlen (src);
-#ifdef VMS
- if (! index (src, '/')
- && (src[slen - 1] == ']'
- || src[slen - 1] == ':'
- || src[slen - 1] == '>'))
- {
- /* 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$l_nam = &nam;
- fab.fab$l_fop = FAB$M_NAM;
-
- nam.nam$l_esa = esa;
- nam.nam$b_ess = sizeof esa;
- nam.nam$b_nop |= NAM$M_SYNCHK;
-
- /* 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 -= 2;
- esa[slen] = '\0';
- src = esa;
- }
- if (src[slen - 1] != ']' && src[slen - 1] != '>')
- {
- /* what about when we have logical_name:???? */
- if (src[slen - 1] == ':')
- { /* Xlate logical name and see what we get */
- ptr = strcpy (dst, src); /* upper case for getenv */
- while (*ptr)
- {
- if ('a' <= *ptr && *ptr <= 'z')
- *ptr -= 040;
- ptr++;
- }
- dst[slen - 1] = 0; /* remove colon */
- if (!(src = egetenv (dst)))
- return 0;
- /* should we jump to the beginning of this procedure?
- Good points: allows us to use logical names that xlate
- to Unix names,
- Bad points: can be a problem if we just translated to a device
- 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] != '>')
- { /* no recursion here! */
- strcpy (dst, src);
- return 0;
- }
- }
- else
- { /* not a directory spec */
- strcpy (dst, src);
- return 0;
- }
- }
- bracket = src[slen - 1];
-
- /* If bracket is ']' or '>', bracket - 2 is the corresponding
- opening bracket. */
- ptr = index (src, bracket - 2);
- if (ptr == 0)
- { /* no opening bracket */
- strcpy (dst, src);
- return 0;
- }
- if (!(rptr = rindex (src, '.')))
- rptr = ptr;
- slen = rptr - src;
- strncpy (dst, src, slen);
- dst[slen] = '\0';
- if (*rptr == '.')
- {
- dst[slen++] = bracket;
- dst[slen] = '\0';
- }
- else
- {
- /* If we have the top-level of a rooted directory (i.e. xx:[000000]),
- then translate the device and recurse. */
- if (dst[slen - 1] == ':'
- && dst[slen - 2] != ':' /* skip decnet nodes */
- && strcmp (src + slen, "[000000]") == 0)
- {
- dst[slen - 1] = '\0';
- if ((ptr = egetenv (dst))
- && (rlen = strlen (ptr) - 1) > 0
- && (ptr[rlen] == ']' || ptr[rlen] == '>')
- && ptr[rlen - 1] == '.')
- {
- 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] = ':';
- }
- strcat (dst, "[000000]");
- slen += 8;
- }
- rptr++;
- rlen = strlen (rptr) - 1;
- strncat (dst, rptr, rlen);
- dst[slen + rlen] = '\0';
- strcat (dst, ".DIR.1");
- return 1;
- }
-#endif /* VMS */
- /* Process as Unix format: just remove any final slash.
- But leave "/" unchanged; do not change it to "". */
- strcpy (dst, src);
-#ifdef APOLLO
- /* Handle // as root for apollo's. */
- if ((slen > 2 && dst[slen - 1] == '/')
- || (slen > 1 && dst[0] != '/' && dst[slen - 1] == '/'))
- dst[slen - 1] = 0;
-#else
- if (slen > 1
- && IS_DIRECTORY_SEP (dst[slen - 1])
-#ifdef DOS_NT
- && !IS_ANY_SEP (dst[slen - 2])
-#endif
- )
- dst[slen - 1] = 0;
-#endif
-#ifdef DOS_NT
- CORRECT_DIR_SEPS (dst);
-#endif
- return 1;
-}
-
-DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name,
- 1, 1, 0,
- "Returns the file name of the directory named DIRECTORY.\n\
-This is the name of the file that holds the data for the directory 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\
-In Unix-syntax, this function 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\".")
- (directory)
- Lisp_Object directory;
-{
- char *buf;
- Lisp_Object handler;
-
- CHECK_STRING (directory, 0);
-
- if (NILP (directory))
- return Qnil;
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (directory, Qdirectory_file_name);
- if (!NILP (handler))
- return call2 (handler, Qdirectory_file_name, directory);
-
-#ifdef VMS
- /* 20 extra chars is insufficient for VMS, since we might perform a
- logical name translation. an equivalence string can be up to 255
- chars long, so grab that much extra space... - sss */
- buf = (char *) alloca (XSTRING (directory)->size + 20 + 255);
-#else
- buf = (char *) alloca (XSTRING (directory)->size + 20);
-#endif
- directory_file_name (XSTRING (directory)->data, buf);
- return build_string (buf);
-}
-
-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.")
- (prefix)
- Lisp_Object prefix;
-{
- Lisp_Object val;
-#ifdef MSDOS
- /* Don't use too many characters of the restricted 8+3 DOS
- filename space. */
- val = concat2 (prefix, build_string ("a.XXX"));
-#else
- val = concat2 (prefix, build_string ("XXXXXX"));
-#endif
- mktemp (XSTRING (val)->data);
-#ifdef DOS_NT
- CORRECT_DIR_SEPS (XSTRING (val)->data);
-#endif
- return val;
-}
-
-DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
- "Convert filename NAME to absolute, and canonicalize it.\n\
-Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative\n\
- (does not start with slash); if DEFAULT-DIRECTORY is nil or missing,\n\
-the current buffer's value of default-directory is used.\n\
-File name components that are `.' are removed, and \n\
-so are file name components followed by `..', along with the `..' itself;\n\
-note that these simplifications are done without checking the resulting\n\
-file names in the file system.\n\
-An initial `~/' expands to your home directory.\n\
-An initial `~USER/' expands to USER's home directory.\n\
-See also the function `substitute-in-file-name'.")
- (name, default_directory)
- Lisp_Object name, default_directory;
-{
- unsigned char *nm;
-
- register unsigned char *newdir, *p, *o;
- int tlen;
- unsigned char *target;
- struct passwd *pw;
-#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;
-#endif /* VMS */
-#ifdef DOS_NT
- int drive = 0;
- int collapse_newdir = 1;
-#endif /* DOS_NT */
- int length;
- Lisp_Object handler;
-
- CHECK_STRING (name, 0);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (name, Qexpand_file_name);
- if (!NILP (handler))
- return call3 (handler, Qexpand_file_name, name, default_directory);
-
- /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */
- if (NILP (default_directory))
- default_directory = current_buffer->directory;
- CHECK_STRING (default_directory, 1);
-
- if (!NILP (default_directory))
- {
- handler = Ffind_file_name_handler (default_directory, Qexpand_file_name);
- if (!NILP (handler))
- return call3 (handler, Qexpand_file_name, name, default_directory);
- }
-
- o = XSTRING (default_directory)->data;
-
- /* Make sure DEFAULT_DIRECTORY is properly expanded.
- It would be better to do this down below where we actually use
- default_directory. Unfortunately, calling Fexpand_file_name recursively
- could invoke GC, and the strings might be relocated. This would
- be annoying because we have pointers into strings lying around
- that would need adjusting, and people would add new pointers to
- the code and forget to adjust them, resulting in intermittent bugs.
- Putting this call here avoids all that crud.
-
- The EQ test avoids infinite recursion. */
- if (! NILP (default_directory) && !EQ (default_directory, name)
- /* Save time in some common cases - as long as default_directory
- is not relative, it can be canonicalized with name below (if it
- is needed at all) without requiring it to be expanded now. */
-#ifdef DOS_NT
- /* Detect MSDOS file names with drive specifiers. */
- && ! (IS_DRIVE (o[0]) && (IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2])))
-#ifdef WINDOWSNT
- /* Detect Windows file names in UNC format. */
- && ! (IS_DIRECTORY_SEP (o[0]) && IS_DIRECTORY_SEP (o[1]))
-#endif
-#else /* not DOS_NT */
- /* Detect Unix absolute file names (/... alone is not absolute on
- DOS or Windows). */
- && ! (IS_DIRECTORY_SEP (o[0]))
-#endif /* not DOS_NT */
- )
- {
- struct gcpro gcpro1;
-
- GCPRO1 (name);
- default_directory = Fexpand_file_name (default_directory, Qnil);
- UNGCPRO;
- }
-
-#ifdef VMS
- /* Filenames on VMS are always upper case. */
- name = Fupcase (name);
-#endif
-#ifdef FILE_SYSTEM_CASE
- name = FILE_SYSTEM_CASE (name);
-#endif
-
- nm = XSTRING (name)->data;
-
-#ifdef DOS_NT
- /* We will force directory separators to be either all \ or /, so make
- a local copy to modify, even if there ends up being no change. */
- nm = strcpy (alloca (strlen (nm) + 1), nm);
-
- /* Find and remove drive specifier if present; this makes nm absolute
- even if the rest of the name appears to be relative. */
- {
- unsigned char *colon = rindex (nm, ':');
-
- if (colon)
- /* Only recognize colon as part of drive specifier if there is a
- single alphabetic character preceeding the colon (and if the
- character before the drive letter, if present, is a directory
- separator); this is to support the remote system syntax used by
- ange-ftp, and the "po:username" syntax for POP mailboxes. */
- look_again:
- if (nm == colon)
- nm++;
- else if (IS_DRIVE (colon[-1])
- && (colon == nm + 1 || IS_DIRECTORY_SEP (colon[-2])))
- {
- drive = colon[-1];
- nm = colon + 1;
- }
- else
- {
- while (--colon >= nm)
- if (colon[0] == ':')
- goto look_again;
- }
- }
-#endif /* DOS_NT */
-
-#ifdef WINDOWSNT
- /* Discard any previous drive specifier if nm is now in UNC format. */
- if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
- {
- drive = 0;
- }
-#endif
-
- /* If nm is absolute, look for /./ or /../ sequences; if none are
- found, we can probably return right away. We will avoid allocating
- a new string if name is already fully expanded. */
- if (
- IS_DIRECTORY_SEP (nm[0])
-#ifdef MSDOS
- && drive
-#endif
-#ifdef WINDOWSNT
- && (drive || IS_DIRECTORY_SEP (nm[1]))
-#endif
-#ifdef VMS
- || index (nm, ':')
-#endif /* VMS */
- )
- {
- /* If it turns out that the filename we want to return is just a
- suffix of FILENAME, we don't need to go through and edit
- things; we just need to construct a new string using data
- starting at the middle of FILENAME. If we set lose to a
- non-zero value, that means we've discovered that we can't do
- that cool trick. */
- int lose = 0;
-
- p = nm;
- while (*p)
- {
- /* Since we know the name is absolute, we can assume that each
- element starts with a "/". */
-
- /* "." and ".." are hairy. */
- if (IS_DIRECTORY_SEP (p[0])
- && p[1] == '.'
- && (IS_DIRECTORY_SEP (p[2])
- || p[2] == 0
- || (p[2] == '.' && (IS_DIRECTORY_SEP (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 /name/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 */
-#ifdef DOS_NT
- /* Make sure directories are all separated with / or \ as
- desired, but avoid allocation of a new string when not
- required. */
- CORRECT_DIR_SEPS (nm);
-#ifdef WINDOWSNT
- if (IS_DIRECTORY_SEP (nm[1]))
- {
- if (strcmp (nm, XSTRING (name)->data) != 0)
- name = build_string (nm);
- }
- else
-#endif
- /* drive must be set, so this is okay */
- if (strcmp (nm - 2, XSTRING (name)->data) != 0)
- {
- name = make_string (nm - 2, p - nm + 2);
- XSTRING (name)->data[0] = DRIVE_LETTER (drive);
- XSTRING (name)->data[1] = ':';
- }
- return name;
-#else /* not DOS_NT */
- if (nm == XSTRING (name)->data)
- return name;
- return build_string (nm);
-#endif /* not DOS_NT */
- }
- }
-
- /* At this point, nm might or might not be an absolute file name. We
- need to expand ~ or ~user if present, otherwise prefix nm with
- default_directory if nm is not absolute, and finally collapse /./
- and /foo/../ sequences.
-
- We set newdir to be the appropriate prefix if one is needed:
- - the relevant user directory if nm starts with ~ or ~user
- - the specified drive's working dir (DOS/NT only) if nm does not
- start with /
- - the value of default_directory.
-
- Note that these prefixes are not guaranteed to be absolute (except
- for the working dir of a drive). Therefore, to ensure we always
- return an absolute name, if the final prefix is not absolute we
- append it to the current working directory. */
-
- newdir = 0;
-
- if (nm[0] == '~') /* prefix ~ */
- {
- if (IS_DIRECTORY_SEP (nm[1])
-#ifdef VMS
- || nm[1] == ':'
-#endif /* VMS */
- || nm[1] == 0) /* ~ by itself */
- {
- if (!(newdir = (unsigned char *) egetenv ("HOME")))
- newdir = (unsigned char *) "";
- nm++;
-#ifdef DOS_NT
- collapse_newdir = 0;
-#endif
-#ifdef VMS
- nm++; /* Don't leave the slash in nm. */
-#endif /* VMS */
- }
- else /* ~user/filename */
- {
- for (p = nm; *p && (!IS_DIRECTORY_SEP (*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)
- {
- newdir = (unsigned char *) pw -> pw_dir;
-#ifdef VMS
- nm = p + 1; /* skip the terminator */
-#else
- nm = p;
-#ifdef DOS_NT
- collapse_newdir = 0;
-#endif
-#endif /* VMS */
- }
-
- /* If we don't find a user of that name, leave the name
- unchanged; don't move nm forward to p. */
- }
- }
-
-#ifdef DOS_NT
- /* On DOS and Windows, nm is absolute if a drive name was specified;
- use the drive's current directory as the prefix if needed. */
- if (!newdir && drive)
- {
- /* Get default directory if needed to make nm absolute. */
- if (!IS_DIRECTORY_SEP (nm[0]))
- {
- newdir = alloca (MAXPATHLEN + 1);
- if (!getdefdir (toupper (drive) - 'A' + 1, newdir))
- newdir = NULL;
- }
- if (!newdir)
- {
- /* Either nm starts with /, or drive isn't mounted. */
- newdir = alloca (4);
- newdir[0] = DRIVE_LETTER (drive);
- newdir[1] = ':';
- newdir[2] = '/';
- newdir[3] = 0;
- }
- }
-#endif /* DOS_NT */
-
- /* Finally, if no prefix has been specified and nm is not absolute,
- then it must be expanded relative to default_directory. */
-
- if (1
-#ifndef DOS_NT
- /* /... alone is not absolute on DOS and Windows. */
- && !IS_DIRECTORY_SEP (nm[0])
-#endif
-#ifdef WINDOWSNT
- && !(IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
-#endif
-#ifdef VMS
- && !index (nm, ':')
-#endif
- && !newdir)
- {
- newdir = XSTRING (default_directory)->data;
- }
-
-#ifdef DOS_NT
- if (newdir)
- {
- /* First ensure newdir is an absolute name. */
- if (
- /* Detect MSDOS file names with drive specifiers. */
- ! (IS_DRIVE (newdir[0])
- && IS_DEVICE_SEP (newdir[1]) && IS_DIRECTORY_SEP (newdir[2]))
-#ifdef WINDOWSNT
- /* Detect Windows file names in UNC format. */
- && ! (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
-#endif
- )
- {
- /* Effectively, let newdir be (expand-file-name newdir cwd).
- Because of the admonition against calling expand-file-name
- when we have pointers into lisp strings, we accomplish this
- indirectly by prepending newdir to nm if necessary, and using
- cwd (or the wd of newdir's drive) as the new newdir. */
-
- if (IS_DRIVE (newdir[0]) && newdir[1] == ':')
- {
- drive = newdir[0];
- newdir += 2;
- }
- if (!IS_DIRECTORY_SEP (nm[0]))
- {
- char * tmp = alloca (strlen (newdir) + strlen (nm) + 2);
- file_name_as_directory (tmp, newdir);
- strcat (tmp, nm);
- nm = tmp;
- }
- newdir = alloca (MAXPATHLEN + 1);
- if (drive)
- {
- if (!getdefdir (toupper (drive) - 'A' + 1, newdir))
- newdir = "/";
- }
- else
- getwd (newdir);
- }
-
- /* Strip off drive name from prefix, if present. */
- if (IS_DRIVE (newdir[0]) && newdir[1] == ':')
- {
- drive = newdir[0];
- newdir += 2;
- }
-
- /* Keep only a prefix from newdir if nm starts with slash
- (//server/share for UNC, nothing otherwise). */
- if (IS_DIRECTORY_SEP (nm[0]) && collapse_newdir)
- {
-#ifdef WINDOWSNT
- if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
- {
- newdir = strcpy (alloca (strlen (newdir) + 1), newdir);
- p = newdir + 2;
- while (*p && !IS_DIRECTORY_SEP (*p)) p++;
- p++;
- while (*p && !IS_DIRECTORY_SEP (*p)) p++;
- *p = 0;
- }
- else
-#endif
- newdir = "";
- }
- }
-#endif /* DOS_NT */
-
- if (newdir)
- {
- /* Get rid of any slash at the end of newdir, unless newdir is
- just // (an incomplete UNC name). */
- length = strlen (newdir);
- if (IS_DIRECTORY_SEP (newdir[length - 1])
-#ifdef WINDOWSNT
- && !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
-#endif
- )
- {
- 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 += strlen (nm) + 1;
-#ifdef DOS_NT
- /* Add reserved space for drive name. (The Microsoft x86 compiler
- produces incorrect code if the following two lines are combined.) */
- target = (unsigned char *) alloca (tlen + 2);
- target += 2;
-#else /* not DOS_NT */
- target = (unsigned char *) alloca (tlen);
-#endif /* not DOS_NT */
- *target = 0;
-
- if (newdir)
- {
-#ifndef VMS
- if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0]))
- strcpy (target, newdir);
- else
-#endif
- file_name_as_directory (target, newdir);
- }
-
- strcat (target, nm);
-#ifdef VMS
- if (index (target, '/'))
- strcpy (target, sys_translate_unix (target));
-#endif /* VMS */
-
- /* ASSERT (IS_DIRECTORY_SEP (target[0])) if not VMS */
-
- /* Now canonicalize by removing /. and /foo/.. if they appear. */
-
- p = target;
- o = target;
-
- while (*p)
- {
-#ifdef VMS
- if (*p != ']' && *p != '>' && *p != '-')
- {
- 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.-] ==> [-] */
- }
- 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 (!IS_DIRECTORY_SEP (*p))
- {
- *o++ = *p++;
- }
- else if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1])
-#if defined (APOLLO) || defined (WINDOWSNT)
- /* // at start of filename is meaningful in Apollo
- and WindowsNT systems */
- && o != target
-#endif /* APOLLO || WINDOWSNT */
- )
- {
- o = target;
- p++;
- }
- else if (IS_DIRECTORY_SEP (p[0])
- && p[1] == '.'
- && (IS_DIRECTORY_SEP (p[2])
- || p[2] == 0))
- {
- /* If "/." is the entire filename, keep the "/". Otherwise,
- just delete the whole "/.". */
- if (o == target && p[2] == '\0')
- *o++ = *p;
- p += 2;
- }
- else if (IS_DIRECTORY_SEP (p[0]) && p[1] == '.' && p[2] == '.'
- /* `/../' is the "superroot" on certain file systems. */
- && o != target
- && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0))
- {
- while (o != target && (--o) && !IS_DIRECTORY_SEP (*o))
- ;
- if (o == target && IS_ANY_SEP (*o))
- ++o;
- p += 3;
- }
- else
- {
- *o++ = *p++;
- }
-#endif /* not VMS */
- }
-
-#ifdef DOS_NT
- /* At last, set drive name. */
-#ifdef WINDOWSNT
- /* Except for network file name. */
- if (!(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])))
-#endif /* WINDOWSNT */
- {
- if (!drive) abort ();
- target -= 2;
- target[0] = DRIVE_LETTER (drive);
- target[1] = ':';
- }
- CORRECT_DIR_SEPS (target);
-#endif /* DOS_NT */
-
- return make_string (target, o - target);
-}
-
-#if 0
-/* Changed this DEFUN to a DEAFUN, so as not to confuse `make-docfile'. */
-DEAFUN ("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;
-#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;
-#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 /name/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);
- }
- }
-
- /* 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 */
- {
- /* 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 (nm[0] != '/'
-#ifdef VMS
- && !index (nm, ':')
-#endif /* not VMS */
- && !newdir)
- {
- if (NILP (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)
- {
-#ifndef VMS
- if (nm[0] == 0 || nm[0] == '/')
- strcpy (target, newdir);
- else
-#endif
- file_name_as_directory (target, newdir);
- }
-
- strcat (target, nm);
-#ifdef VMS
- if (index (target, '/'))
- strcpy (target, sys_translate_unix (target));
-#endif /* VMS */
-
- /* Now canonicalize by removing /. and /foo/.. if they appear */
-
- p = target;
- o = target;
-
- while (*p)
- {
-#ifdef VMS
- if (*p != ']' && *p != '>' && *p != '-')
- {
- 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.-] ==> [-] */
- }
- 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);
-}
-#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.")
- (filename)
- Lisp_Object filename;
-{
- unsigned char *nm;
-
- register unsigned char *s, *p, *o, *x, *endp;
- unsigned char *target;
- int total = 0;
- int substituted = 0;
- unsigned char *xnm;
- Lisp_Object handler;
-
- CHECK_STRING (filename, 0);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qsubstitute_in_file_name);
- if (!NILP (handler))
- return call2 (handler, Qsubstitute_in_file_name, filename);
-
- nm = XSTRING (filename)->data;
-#ifdef DOS_NT
- nm = strcpy (alloca (strlen (nm) + 1), nm);
- CORRECT_DIR_SEPS (nm);
- substituted = (strcmp (nm, XSTRING (filename)->data) != 0);
-#endif
- endp = nm + XSTRING (filename)->size;
-
- /* If /~ or // appears, discard everything through first slash. */
-
- for (p = nm; p != endp; p++)
- {
- if ((p[0] == '~'
-#if defined (APOLLO) || defined (WINDOWSNT)
- /* // at start of file name is meaningful in Apollo and
- WindowsNT systems */
- || (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm)
-#else /* not (APOLLO || WINDOWSNT) */
- || IS_DIRECTORY_SEP (p[0])
-#endif /* not (APOLLO || WINDOWSNT) */
- )
- && p != nm
- && (0
-#ifdef VMS
- || p[-1] == ':' || p[-1] == ']' || p[-1] == '>'
-#endif /* VMS */
- || IS_DIRECTORY_SEP (p[-1])))
- {
- nm = p;
- substituted = 1;
- }
-#ifdef DOS_NT
- /* see comment in expand-file-name about drive specifiers */
- else if (IS_DRIVE (p[0]) && p[1] == ':'
- && p > nm && IS_DIRECTORY_SEP (p[-1]))
- {
- nm = p;
- substituted = 1;
- }
-#endif /* DOS_NT */
- }
-
-#ifdef VMS
- return build_string (nm);
-#else
-
- /* See if any variables are substituted into the string
- and find the total length of their values in `total' */
-
- for (p = nm; p != endp;)
- if (*p != '$')
- p++;
- else
- {
- p++;
- if (p == endp)
- goto badsubst;
- else if (*p == '$')
- {
- /* "$$" means a single "$" */
- p++;
- total -= 1;
- substituted = 1;
- continue;
- }
- else if (*p == '{')
- {
- o = ++p;
- while (p != endp && *p != '}') p++;
- if (*p != '}') goto missingclose;
- s = p;
- }
- else
- {
- o = p;
- while (p != endp && (isalnum (*p) || *p == '_')) p++;
- s = p;
- }
-
- /* Copy out the variable name */
- target = (unsigned char *) alloca (s - o + 1);
- strncpy (target, o, s - o);
- target[s - o] = 0;
-#ifdef DOS_NT
- strupr (target); /* $home == $HOME etc. */
-#endif /* DOS_NT */
-
- /* Get variable value */
- o = (unsigned char *) egetenv (target);
- if (!o) goto badvar;
- total += strlen (o);
- substituted = 1;
- }
-
- if (!substituted)
- return filename;
-
- /* If substitution required, recopy the string and do it */
- /* Make space in stack frame for the new copy */
- xnm = (unsigned char *) alloca (XSTRING (filename)->size + total + 1);
- x = xnm;
-
- /* Copy the rest of the name through, replacing $ constructs with values */
- for (p = nm; *p;)
- if (*p != '$')
- *x++ = *p++;
- else
- {
- p++;
- if (p == endp)
- goto badsubst;
- else if (*p == '$')
- {
- *x++ = *p++;
- continue;
- }
- else if (*p == '{')
- {
- o = ++p;
- while (p != endp && *p != '}') p++;
- if (*p != '}') goto missingclose;
- s = p++;
- }
- else
- {
- o = p;
- while (p != endp && (isalnum (*p) || *p == '_')) p++;
- s = p;
- }
-
- /* Copy out the variable name */
- target = (unsigned char *) alloca (s - o + 1);
- strncpy (target, o, s - o);
- target[s - o] = 0;
-#ifdef DOS_NT
- strupr (target); /* $home == $HOME etc. */
-#endif /* DOS_NT */
-
- /* Get variable value */
- o = (unsigned char *) egetenv (target);
- if (!o)
- goto badvar;
-
- strcpy (x, o);
- x += strlen (o);
- }
-
- *x = 0;
-
- /* If /~ or // appears, discard everything through first slash. */
-
- for (p = xnm; p != x; p++)
- if ((p[0] == '~'
-#if defined (APOLLO) || defined (WINDOWSNT)
- || (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm)
-#else /* not (APOLLO || WINDOWSNT) */
- || IS_DIRECTORY_SEP (p[0])
-#endif /* not (APOLLO || WINDOWSNT) */
- )
- && p != nm && IS_DIRECTORY_SEP (p[-1]))
- xnm = p;
-#ifdef DOS_NT
- else if (IS_DRIVE (p[0]) && p[1] == ':'
- && p > nm && IS_DIRECTORY_SEP (p[-1]))
- xnm = p;
-#endif
-
- return make_string (xnm, x - xnm);
-
- badsubst:
- error ("Bad format environment-variable substitution");
- missingclose:
- error ("Missing \"}\" in environment-variable substitution");
- badvar:
- error ("Substituting nonexistent environment variable \"%s\"", target);
-
- /* NOTREACHED */
-#endif /* not VMS */
-}
-
-/* A slightly faster and more convenient way to get
- (directory-file-name (expand-file-name FOO)). */
-
-Lisp_Object
-expand_and_dir_to_file (filename, defdir)
- Lisp_Object filename, defdir;
-{
- register Lisp_Object absname;
-
- absname = Fexpand_file_name (filename, defdir);
-#ifdef VMS
- {
- register int c = XSTRING (absname)->data[XSTRING (absname)->size - 1];
- if (c == ':' || c == ']' || c == '>')
- absname = Fdirectory_file_name (absname);
- }
-#else
- /* Remove final slash, if any (unless this is the root dir).
- stat behaves differently depending! */
- if (XSTRING (absname)->size > 1
- && IS_DIRECTORY_SEP (XSTRING (absname)->data[XSTRING (absname)->size - 1])
- && !IS_DEVICE_SEP (XSTRING (absname)->data[XSTRING (absname)->size-2]))
- /* We cannot take shortcuts; they might be wrong for magic file names. */
- absname = Fdirectory_file_name (absname);
-#endif
- return absname;
-}
-
-/* Signal an error if the file ABSNAME already exists.
- If INTERACTIVE is nonzero, ask the user whether to proceed,
- and bypass the error if the user says to go ahead.
- QUERYSTRING is a name for the action that is being considered
- to alter the file.
- *STATPTR is used to store the stat information if the file exists.
- If the file does not exist, STATPTR->st_mode is set to 0. */
-
-void
-barf_or_query_if_file_exists (absname, querystring, interactive, statptr)
- Lisp_Object absname;
- unsigned char *querystring;
- int interactive;
- struct stat *statptr;
-{
- register Lisp_Object tem;
- struct stat statbuf;
- struct gcpro gcpro1;
-
- /* stat is a good way to tell whether the file exists,
- regardless of what access permissions it has. */
- if (stat (XSTRING (absname)->data, &statbuf) >= 0)
- {
- if (! interactive)
- Fsignal (Qfile_already_exists,
- 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));
- UNGCPRO;
- if (NILP (tem))
- Fsignal (Qfile_already_exists,
- Fcons (build_string ("File already exists"),
- Fcons (absname, Qnil)));
- if (statptr)
- *statptr = statbuf;
- }
- else
- {
- if (statptr)
- statptr->st_mode = 0;
- }
- return;
-}
-
-DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 4,
- "fCopy file: \nFCopy %s to file: \np\nP",
- "Copy FILE to NEWNAME. Both args must be strings.\n\
-Signals a `file-already-exists' error if file 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\
-Fourth arg KEEP-TIME non-nil means give the new file the same\n\
-last-modified time as the old one. (This works on only some systems.)\n\
-A prefix arg makes KEEP-TIME non-nil.")
- (file, newname, ok_if_already_exists, keep_date)
- Lisp_Object file, newname, ok_if_already_exists, keep_date;
-{
- int ifd, ofd, n;
- char buf[16 * 1024];
- struct stat st, out_st;
- Lisp_Object handler;
- struct gcpro gcpro1, gcpro2;
- int count = specpdl_ptr - specpdl;
- int input_file_statable_p;
-
- GCPRO2 (file, newname);
- CHECK_STRING (file, 0);
- CHECK_STRING (newname, 1);
- file = Fexpand_file_name (file, Qnil);
- newname = Fexpand_file_name (newname, Qnil);
-
- /* If the input file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (file, Qcopy_file);
- /* Likewise for output file name. */
- if (NILP (handler))
- handler = Ffind_file_name_handler (newname, Qcopy_file);
- if (!NILP (handler))
- RETURN_UNGCPRO (call5 (handler, Qcopy_file, file, newname,
- ok_if_already_exists, keep_date));
-
- if (NILP (ok_if_already_exists)
- || INTEGERP (ok_if_already_exists))
- barf_or_query_if_file_exists (newname, "copy to it",
- INTEGERP (ok_if_already_exists), &out_st);
- else if (stat (XSTRING (newname)->data, &out_st) < 0)
- out_st.st_mode = 0;
-
- ifd = open (XSTRING (file)->data, O_RDONLY);
- if (ifd < 0)
- report_file_error ("Opening input file", Fcons (file, Qnil));
-
- record_unwind_protect (close_file_unwind, make_number (ifd));
-
- /* We can only copy regular files and symbolic links. Other files are not
- copyable by us. */
- input_file_statable_p = (fstat (ifd, &st) >= 0);
-
-#if !defined (MSDOS) || __DJGPP__ > 1
- if (out_st.st_mode != 0
- && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
- {
- errno = 0;
- report_file_error ("Input and output files are the same",
- Fcons (file, Fcons (newname, Qnil)));
- }
-#endif
-
-#if defined (S_ISREG) && defined (S_ISLNK)
- if (input_file_statable_p)
- {
- if (!(S_ISREG (st.st_mode)) && !(S_ISLNK (st.st_mode)))
- {
-#if defined (EISDIR)
- /* Get a better looking error message. */
- errno = EISDIR;
-#endif /* EISDIR */
- report_file_error ("Non-regular file", Fcons (file, Qnil));
- }
- }
-#endif /* S_ISREG && S_ISLNK */
-
-#ifdef VMS
- /* Create the copy file with the same record format as the input file */
- ofd = sys_creat (XSTRING (newname)->data, 0666, ifd);
-#else
-#ifdef MSDOS
- /* System's default file type was set to binary by _fmode in emacs.c. */
- ofd = creat (XSTRING (newname)->data, S_IREAD | S_IWRITE);
-#else /* not MSDOS */
- ofd = creat (XSTRING (newname)->data, 0666);
-#endif /* not MSDOS */
-#endif /* VMS */
- if (ofd < 0)
- report_file_error ("Opening output file", Fcons (newname, Qnil));
-
- record_unwind_protect (close_file_unwind, make_number (ofd));
-
- immediate_quit = 1;
- QUIT;
- while ((n = read (ifd, buf, sizeof buf)) > 0)
- if (write (ofd, buf, n) != n)
- report_file_error ("I/O error", Fcons (newname, Qnil));
- immediate_quit = 0;
-
- /* Closing the output clobbers the file times on some systems. */
- if (close (ofd) < 0)
- report_file_error ("I/O error", Fcons (newname, Qnil));
-
- if (input_file_statable_p)
- {
- if (!NILP (keep_date))
- {
- EMACS_TIME atime, mtime;
- EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
- EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
- if (set_file_times (XSTRING (newname)->data, atime, mtime))
- report_file_error ("I/O error", Fcons (newname, Qnil));
- }
-#ifndef MSDOS
- chmod (XSTRING (newname)->data, st.st_mode & 07777);
-#else /* MSDOS */
-#if defined (__DJGPP__) && __DJGPP__ > 1
- /* In DJGPP v2.0 and later, fstat usually returns true file mode bits,
- and if it can't, it tells so. Otherwise, under MSDOS we usually
- get only the READ bit, which will make the copied file read-only,
- so it's better not to chmod at all. */
- if ((_djstat_flags & _STFAIL_WRITEBIT) == 0)
- chmod (XSTRING (newname)->data, st.st_mode & 07777);
-#endif /* DJGPP version 2 or newer */
-#endif /* MSDOS */
- }
-
- close (ifd);
-
- /* Discard the unwind protects. */
- specpdl_ptr = specpdl + count;
-
- UNGCPRO;
- return Qnil;
-}
-
-DEFUN ("make-directory-internal", Fmake_directory_internal,
- Smake_directory_internal, 1, 1, 0,
- "Create a new directory named DIRECTORY.")
- (directory)
- Lisp_Object directory;
-{
- unsigned char *dir;
- Lisp_Object handler;
-
- CHECK_STRING (directory, 0);
- directory = Fexpand_file_name (directory, Qnil);
-
- handler = Ffind_file_name_handler (directory, Qmake_directory_internal);
- if (!NILP (handler))
- return call2 (handler, Qmake_directory_internal, directory);
-
- dir = XSTRING (directory)->data;
-
-#ifdef WINDOWSNT
- if (mkdir (dir) != 0)
-#else
- if (mkdir (dir, 0777) != 0)
-#endif
- report_file_error ("Creating directory", Flist (1, &directory));
-
- return Qnil;
-}
-
-DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete directory: ",
- "Delete the directory named DIRECTORY.")
- (directory)
- Lisp_Object directory;
-{
- unsigned char *dir;
- Lisp_Object handler;
-
- CHECK_STRING (directory, 0);
- directory = Fdirectory_file_name (Fexpand_file_name (directory, Qnil));
- dir = XSTRING (directory)->data;
-
- handler = Ffind_file_name_handler (directory, Qdelete_directory);
- if (!NILP (handler))
- return call2 (handler, Qdelete_directory, directory);
-
- if (rmdir (dir) != 0)
- report_file_error ("Removing directory", Flist (1, &directory));
-
- return Qnil;
-}
-
-DEFUN ("delete-file", Fdelete_file, Sdelete_file, 1, 1, "fDelete file: ",
- "Delete file named FILENAME.\n\
-If file has multiple names, it continues to exist with the other names.")
- (filename)
- Lisp_Object filename;
-{
- Lisp_Object handler;
- CHECK_STRING (filename, 0);
- filename = Fexpand_file_name (filename, Qnil);
-
- handler = Ffind_file_name_handler (filename, Qdelete_file);
- if (!NILP (handler))
- return call2 (handler, Qdelete_file, filename);
-
- if (0 > unlink (XSTRING (filename)->data))
- report_file_error ("Removing old name", Flist (1, &filename));
- return Qnil;
-}
-
-static Lisp_Object
-internal_delete_file_1 (ignore)
- Lisp_Object ignore;
-{
- return Qt;
-}
-
-/* Delete file FILENAME, returning 1 if successful and 0 if failed. */
-
-int
-internal_delete_file (filename)
- Lisp_Object filename;
-{
- return NILP (internal_condition_case_1 (Fdelete_file, filename,
- Qt, internal_delete_file_1));
-}
-
-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\
-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.")
- (file, newname, ok_if_already_exists)
- Lisp_Object file, newname, ok_if_already_exists;
-{
-#ifdef NO_ARG_ARRAY
- Lisp_Object args[2];
-#endif
- Lisp_Object handler;
- struct gcpro gcpro1, gcpro2;
-
- GCPRO2 (file, newname);
- CHECK_STRING (file, 0);
- CHECK_STRING (newname, 1);
- file = Fexpand_file_name (file, Qnil);
- newname = Fexpand_file_name (newname, Qnil);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (file, Qrename_file);
- if (NILP (handler))
- handler = Ffind_file_name_handler (newname, Qrename_file);
- if (!NILP (handler))
- RETURN_UNGCPRO (call4 (handler, Qrename_file,
- file, newname, ok_if_already_exists));
-
- if (NILP (ok_if_already_exists)
- || INTEGERP (ok_if_already_exists))
- barf_or_query_if_file_exists (newname, "rename to it",
- INTEGERP (ok_if_already_exists), 0);
-#ifndef BSD4_1
- if (0 > rename (XSTRING (file)->data, XSTRING (newname)->data))
-#else
- if (0 > link (XSTRING (file)->data, XSTRING (newname)->data)
- || 0 > unlink (XSTRING (file)->data))
-#endif
- {
- if (errno == EXDEV)
- {
- Fcopy_file (file, newname,
- /* We have already prompted if it was an integer,
- so don't have copy-file prompt again. */
- NILP (ok_if_already_exists) ? Qnil : Qt, Qt);
- Fdelete_file (file);
- }
- else
-#ifdef NO_ARG_ARRAY
- {
- args[0] = file;
- args[1] = newname;
- report_file_error ("Renaming", Flist (2, args));
- }
-#else
- report_file_error ("Renaming", Flist (2, &file));
-#endif
- }
- UNGCPRO;
- return Qnil;
-}
-
-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\
-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.")
- (file, newname, ok_if_already_exists)
- Lisp_Object file, newname, ok_if_already_exists;
-{
-#ifdef NO_ARG_ARRAY
- Lisp_Object args[2];
-#endif
- Lisp_Object handler;
- struct gcpro gcpro1, gcpro2;
-
- GCPRO2 (file, newname);
- CHECK_STRING (file, 0);
- CHECK_STRING (newname, 1);
- file = Fexpand_file_name (file, Qnil);
- newname = Fexpand_file_name (newname, Qnil);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (file, Qadd_name_to_file);
- if (!NILP (handler))
- RETURN_UNGCPRO (call4 (handler, Qadd_name_to_file, file,
- newname, ok_if_already_exists));
-
- /* If the new name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (newname, Qadd_name_to_file);
- if (!NILP (handler))
- RETURN_UNGCPRO (call4 (handler, Qadd_name_to_file, file,
- newname, ok_if_already_exists));
-
- if (NILP (ok_if_already_exists)
- || INTEGERP (ok_if_already_exists))
- barf_or_query_if_file_exists (newname, "make it a new name",
- INTEGERP (ok_if_already_exists), 0);
-#ifdef WINDOWSNT
- /* Windows does not support this operation. */
- report_file_error ("Adding new name", Flist (2, &file));
-#else /* not WINDOWSNT */
-
- unlink (XSTRING (newname)->data);
- if (0 > link (XSTRING (file)->data, XSTRING (newname)->data))
- {
-#ifdef NO_ARG_ARRAY
- args[0] = file;
- args[1] = newname;
- report_file_error ("Adding new name", Flist (2, args));
-#else
- report_file_error ("Adding new name", Flist (2, &file));
-#endif
- }
-#endif /* not WINDOWSNT */
-
- UNGCPRO;
- return Qnil;
-}
-
-#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 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 LINKNAME already exists.\n\
-This happens for interactive use with M-x.")
- (filename, linkname, ok_if_already_exists)
- Lisp_Object filename, linkname, ok_if_already_exists;
-{
-#ifdef NO_ARG_ARRAY
- Lisp_Object args[2];
-#endif
- Lisp_Object handler;
- struct gcpro gcpro1, gcpro2;
-
- GCPRO2 (filename, linkname);
- CHECK_STRING (filename, 0);
- CHECK_STRING (linkname, 1);
- /* If the link target has a ~, we must expand it to get
- a truly valid file name. Otherwise, do not expand;
- we want to permit links to relative file names. */
- if (XSTRING (filename)->data[0] == '~')
- filename = Fexpand_file_name (filename, Qnil);
- linkname = Fexpand_file_name (linkname, Qnil);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qmake_symbolic_link);
- if (!NILP (handler))
- RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
- linkname, ok_if_already_exists));
-
- /* If the new link name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (linkname, Qmake_symbolic_link);
- if (!NILP (handler))
- RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
- linkname, ok_if_already_exists));
-
- if (NILP (ok_if_already_exists)
- || INTEGERP (ok_if_already_exists))
- barf_or_query_if_file_exists (linkname, "make it a link",
- INTEGERP (ok_if_already_exists), 0);
- if (0 > symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
- {
- /* If we didn't complain already, silently delete existing file. */
- if (errno == EEXIST)
- {
- unlink (XSTRING (linkname)->data);
- if (0 <= symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
- {
- UNGCPRO;
- return Qnil;
- }
- }
-
-#ifdef NO_ARG_ARRAY
- args[0] = filename;
- args[1] = linkname;
- report_file_error ("Making symbolic link", Flist (2, args));
-#else
- report_file_error ("Making symbolic link", Flist (2, &filename));
-#endif
- }
- UNGCPRO;
- return Qnil;
-}
-#endif /* S_IFLNK */
-
-#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\
-If STRING is nil or a null string, the logical name NAME is deleted.")
- (name, string)
- Lisp_Object name;
- Lisp_Object string;
-{
- CHECK_STRING (name, 0);
- if (NILP (string))
- delete_logical_name (XSTRING (name)->data);
- else
- {
- CHECK_STRING (string, 1);
-
- if (XSTRING (string)->size == 0)
- delete_logical_name (XSTRING (name)->data);
- else
- define_logical_name (XSTRING (name)->data, XSTRING (string)->data);
- }
-
- return string;
-}
-#endif /* VMS */
-
-#ifdef HPUX_NET
-
-DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
- "Open a network connection to PATH using LOGIN as the login string.")
- (path, login)
- Lisp_Object path, login;
-{
- int netresult;
-
- CHECK_STRING (path, 0);
- CHECK_STRING (login, 0);
-
- netresult = netunam (XSTRING (path)->data, XSTRING (login)->data);
-
- if (netresult == -1)
- return Qnil;
- else
- return Qt;
-}
-#endif /* HPUX_NET */
-
-DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p,
- 1, 1, 0,
- "Return t if file FILENAME specifies an absolute file name.\n\
-On Unix, this is a name starting with a `/' or a `~'.")
- (filename)
- Lisp_Object filename;
-{
- unsigned char *ptr;
-
- CHECK_STRING (filename, 0);
- ptr = XSTRING (filename)->data;
- if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~'
-#ifdef VMS
-/* ??? This criterion is probably wrong for '<'. */
- || index (ptr, ':') || index (ptr, '<')
- || (*ptr == '[' && (ptr[1] != '-' || (ptr[2] != '.' && ptr[2] != ']'))
- && ptr[1] != '.')
-#endif /* VMS */
-#ifdef DOS_NT
- || (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2]))
-#endif
- )
- return Qt;
- else
- return Qnil;
-}
-
-/* Return nonzero if file FILENAME exists and can be executed. */
-
-static int
-check_executable (filename)
- char *filename;
-{
-#ifdef DOS_NT
- int len = strlen (filename);
- char *suffix;
- struct stat st;
- if (stat (filename, &st) < 0)
- return 0;
-#if defined (WINDOWSNT) || (defined (MSDOS) && __DJGPP__ > 1)
- return ((st.st_mode & S_IEXEC) != 0);
-#else
- return (S_ISREG (st.st_mode)
- && len >= 5
- && (stricmp ((suffix = filename + len-4), ".com") == 0
- || stricmp (suffix, ".exe") == 0
- || stricmp (suffix, ".bat") == 0)
- || (st.st_mode & S_IFMT) == S_IFDIR);
-#endif /* not WINDOWSNT */
-#else /* not DOS_NT */
-#ifdef HAVE_EUIDACCESS
- return (euidaccess (filename, 1) >= 0);
-#else
- /* Access isn't quite right because it uses the real uid
- and we really want to test with the effective uid.
- But Unix doesn't give us a right way to do it. */
- return (access (filename, 1) >= 0);
-#endif
-#endif /* not DOS_NT */
-}
-
-/* Return nonzero if file FILENAME exists and can be written. */
-
-static int
-check_writable (filename)
- char *filename;
-{
-#ifdef MSDOS
- struct stat st;
- if (stat (filename, &st) < 0)
- return 0;
- return (st.st_mode & S_IWRITE || (st.st_mode & S_IFMT) == S_IFDIR);
-#else /* not MSDOS */
-#ifdef HAVE_EUIDACCESS
- return (euidaccess (filename, 2) >= 0);
-#else
- /* Access isn't quite right because it uses the real uid
- and we really want to test with the effective uid.
- But Unix doesn't give us a right way to do it.
- Opening with O_WRONLY could work for an ordinary file,
- but would lose for directories. */
- return (access (filename, 2) >= 0);
-#endif
-#endif /* not MSDOS */
-}
-
-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'.")
- (filename)
- Lisp_Object filename;
-{
- Lisp_Object absname;
- Lisp_Object handler;
- struct stat statbuf;
-
- CHECK_STRING (filename, 0);
- absname = Fexpand_file_name (filename, Qnil);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (absname, Qfile_exists_p);
- if (!NILP (handler))
- return call2 (handler, Qfile_exists_p, absname);
-
- return (stat (XSTRING (absname)->data, &statbuf) >= 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 a directory, this means you can access files in that directory.")
- (filename)
- Lisp_Object filename;
-
-{
- Lisp_Object absname;
- Lisp_Object handler;
-
- CHECK_STRING (filename, 0);
- absname = Fexpand_file_name (filename, Qnil);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (absname, Qfile_executable_p);
- if (!NILP (handler))
- return call2 (handler, Qfile_executable_p, absname);
-
- return (check_executable (XSTRING (absname)->data) ? Qt : Qnil);
-}
-
-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'.")
- (filename)
- Lisp_Object filename;
-{
- Lisp_Object absname;
- Lisp_Object handler;
- int desc;
- int flags;
- struct stat statbuf;
-
- CHECK_STRING (filename, 0);
- absname = Fexpand_file_name (filename, Qnil);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (absname, Qfile_readable_p);
- if (!NILP (handler))
- return call2 (handler, Qfile_readable_p, absname);
-
-#ifdef DOS_NT
- /* Under MS-DOS and Windows, open does not work for directories. */
- if (access (XSTRING (absname)->data, 0) == 0)
- return Qt;
- return Qnil;
-#else /* not DOS_NT */
- flags = O_RDONLY;
-#if defined (S_ISFIFO) && defined (O_NONBLOCK)
- /* Opening a fifo without O_NONBLOCK can wait.
- We don't want to wait. But we don't want to mess wth O_NONBLOCK
- except in the case of a fifo, on a system which handles it. */
- desc = stat (XSTRING (absname)->data, &statbuf);
- if (desc < 0)
- return Qnil;
- if (S_ISFIFO (statbuf.st_mode))
- flags |= O_NONBLOCK;
-#endif
- desc = open (XSTRING (absname)->data, flags);
- if (desc < 0)
- return Qnil;
- close (desc);
- return Qt;
-#endif /* not DOS_NT */
-}
-
-/* Having this before file-symlink-p mysteriously caused it to be forgotten
- on the RT/PC. */
-DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
- "Return t if file FILENAME can be written or created by you.")
- (filename)
- Lisp_Object filename;
-{
- Lisp_Object absname, dir;
- Lisp_Object handler;
- struct stat statbuf;
-
- CHECK_STRING (filename, 0);
- absname = Fexpand_file_name (filename, Qnil);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (absname, Qfile_writable_p);
- if (!NILP (handler))
- return call2 (handler, Qfile_writable_p, absname);
-
- if (stat (XSTRING (absname)->data, &statbuf) >= 0)
- return (check_writable (XSTRING (absname)->data)
- ? Qt : Qnil);
- dir = Ffile_name_directory (absname);
-#ifdef VMS
- if (!NILP (dir))
- dir = Fdirectory_file_name (dir);
-#endif /* VMS */
-#ifdef MSDOS
- if (!NILP (dir))
- dir = Fdirectory_file_name (dir);
-#endif /* MSDOS */
- return (check_writable (!NILP (dir) ? (char *) XSTRING (dir)->data : "")
- ? Qt : Qnil);
-}
-
-DEFUN ("access-file", Faccess_file, Saccess_file, 2, 2, 0,
- "Access file FILENAME, and get an error if that does not work.\n\
-The second argument STRING is used in the error message.\n\
-If there is no error, we return nil.")
- (filename, string)
- Lisp_Object filename, string;
-{
- Lisp_Object handler;
- int fd;
-
- CHECK_STRING (filename, 0);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qaccess_file);
- if (!NILP (handler))
- return call3 (handler, Qaccess_file, filename, string);
-
- fd = open (XSTRING (filename)->data, O_RDONLY);
- if (fd < 0)
- report_file_error (XSTRING (string)->data, Fcons (filename, Qnil));
- close (fd);
-
- return Qnil;
-}
-
-DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
- "Return non-nil if file FILENAME is the name of a symbolic link.\n\
-The value is the name of the file to which it is linked.\n\
-Otherwise returns nil.")
- (filename)
- Lisp_Object filename;
-{
-#ifdef S_IFLNK
- char *buf;
- int bufsize;
- int valsize;
- Lisp_Object val;
- Lisp_Object handler;
-
- CHECK_STRING (filename, 0);
- filename = Fexpand_file_name (filename, Qnil);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qfile_symlink_p);
- if (!NILP (handler))
- return call2 (handler, Qfile_symlink_p, filename);
-
- bufsize = 100;
- while (1)
- {
- buf = (char *) xmalloc (bufsize);
- bzero (buf, bufsize);
- valsize = readlink (XSTRING (filename)->data, buf, bufsize);
- if (valsize < bufsize) break;
- /* Buffer was not long enough */
- xfree (buf);
- bufsize *= 2;
- }
- if (valsize == -1)
- {
- xfree (buf);
- return Qnil;
- }
- val = make_string (buf, valsize);
- xfree (buf);
- return val;
-#else /* not S_IFLNK */
- return Qnil;
-#endif /* not S_IFLNK */
-}
-
-DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
- "Return t if file FILENAME is the name of a directory as a file.\n\
-A directory name spec may be given instead; then the value is t\n\
-if the directory so specified exists and really is a directory.")
- (filename)
- Lisp_Object filename;
-{
- register Lisp_Object absname;
- struct stat st;
- Lisp_Object handler;
-
- absname = expand_and_dir_to_file (filename, current_buffer->directory);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (absname, Qfile_directory_p);
- if (!NILP (handler))
- return call2 (handler, Qfile_directory_p, absname);
-
- if (stat (XSTRING (absname)->data, &st) < 0)
- return Qnil;
- return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
-}
-
-DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, Sfile_accessible_directory_p, 1, 1, 0,
- "Return t if file FILENAME is the name of a directory as a file,\n\
-and files in that directory can be opened by you. In order to use a\n\
-directory as a buffer's current directory, this predicate must return true.\n\
-A directory name spec may be given instead; then the value is t\n\
-if the directory so specified exists and really is a readable and\n\
-searchable directory.")
- (filename)
- Lisp_Object filename;
-{
- Lisp_Object handler;
- int tem;
- struct gcpro gcpro1;
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p);
- if (!NILP (handler))
- return call2 (handler, Qfile_accessible_directory_p, filename);
-
- /* It's an unlikely combination, but yes we really do need to gcpro:
- Suppose that file-accessible-directory-p has no handler, but
- file-directory-p does have a handler; this handler causes a GC which
- relocates the string in `filename'; and finally file-directory-p
- returns non-nil. Then we would end up passing a garbaged string
- to file-executable-p. */
- GCPRO1 (filename);
- tem = (NILP (Ffile_directory_p (filename))
- || NILP (Ffile_executable_p (filename)));
- UNGCPRO;
- return tem ? Qnil : Qt;
-}
-
-DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
- "Return t if file FILENAME is the name of a regular file.\n\
-This is the sort of file that holds an ordinary stream of data bytes.")
- (filename)
- Lisp_Object filename;
-{
- register Lisp_Object absname;
- struct stat st;
- Lisp_Object handler;
-
- absname = expand_and_dir_to_file (filename, current_buffer->directory);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (absname, Qfile_regular_p);
- if (!NILP (handler))
- return call2 (handler, Qfile_regular_p, absname);
-
- if (stat (XSTRING (absname)->data, &st) < 0)
- return Qnil;
- return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
-}
-
-DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
- "Return mode bits of file named FILENAME, as an integer.")
- (filename)
- Lisp_Object filename;
-{
- Lisp_Object absname;
- struct stat st;
- Lisp_Object handler;
-
- absname = expand_and_dir_to_file (filename, current_buffer->directory);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (absname, Qfile_modes);
- if (!NILP (handler))
- return call2 (handler, Qfile_modes, absname);
-
- if (stat (XSTRING (absname)->data, &st) < 0)
- return Qnil;
-#if defined (MSDOS) && __DJGPP__ < 2
- if (check_executable (XSTRING (absname)->data))
- st.st_mode |= S_IEXEC;
-#endif /* MSDOS && __DJGPP__ < 2 */
-
- return make_number (st.st_mode & 07777);
-}
-
-DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 2, 0,
- "Set mode bits of file named FILENAME to MODE (an integer).\n\
-Only the 12 low bits of MODE are used.")
- (filename, mode)
- Lisp_Object filename, mode;
-{
- Lisp_Object absname;
- Lisp_Object handler;
-
- absname = Fexpand_file_name (filename, current_buffer->directory);
- CHECK_NUMBER (mode, 1);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (absname, Qset_file_modes);
- if (!NILP (handler))
- return call3 (handler, Qset_file_modes, absname, mode);
-
- if (chmod (XSTRING (absname)->data, XINT (mode)) < 0)
- report_file_error ("Doing chmod", Fcons (absname, Qnil));
-
- return Qnil;
-}
-
-DEFUN ("set-default-file-modes", Fset_default_file_modes, Sset_default_file_modes, 1, 1, 0,
- "Set the file permission bits for newly created files.\n\
-The argument MODE should be an integer; only the low 9 bits are used.\n\
-This setting is inherited by subprocesses.")
- (mode)
- Lisp_Object mode;
-{
- CHECK_NUMBER (mode, 0);
-
- umask ((~ XINT (mode)) & 0777);
-
- return Qnil;
-}
-
-DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
- "Return the default file protection for created files.\n\
-The value is an integer.")
- ()
-{
- int realmask;
- Lisp_Object value;
-
- realmask = umask (0);
- umask (realmask);
-
- XSETINT (value, (~ realmask) & 0777);
- return value;
-}
-
-#ifdef unix
-
-DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
- "Tell Unix to finish all pending disk updates.")
- ()
-{
- sync ();
- return Qnil;
-}
-
-#endif /* unix */
-
-DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p, Sfile_newer_than_file_p, 2, 2, 0,
- "Return t if file FILE1 is newer than file FILE2.\n\
-If FILE1 does not exist, the answer is nil;\n\
-otherwise, if FILE2 does not exist, the answer is t.")
- (file1, file2)
- Lisp_Object file1, file2;
-{
- Lisp_Object absname1, absname2;
- struct stat st;
- int mtime1;
- Lisp_Object handler;
- struct gcpro gcpro1, gcpro2;
-
- CHECK_STRING (file1, 0);
- CHECK_STRING (file2, 0);
-
- absname1 = Qnil;
- GCPRO2 (absname1, file2);
- absname1 = expand_and_dir_to_file (file1, current_buffer->directory);
- absname2 = expand_and_dir_to_file (file2, current_buffer->directory);
- UNGCPRO;
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (absname1, Qfile_newer_than_file_p);
- if (NILP (handler))
- handler = Ffind_file_name_handler (absname2, Qfile_newer_than_file_p);
- if (!NILP (handler))
- return call3 (handler, Qfile_newer_than_file_p, absname1, absname2);
-
- if (stat (XSTRING (absname1)->data, &st) < 0)
- return Qnil;
-
- mtime1 = st.st_mtime;
-
- if (stat (XSTRING (absname2)->data, &st) < 0)
- return Qt;
-
- return (mtime1 > st.st_mtime) ? Qt : Qnil;
-}
-
-#ifdef DOS_NT
-Lisp_Object Qfind_buffer_file_type;
-#endif /* DOS_NT */
-
-DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
- 1, 5, 0,
- "Insert contents of file FILENAME after point.\n\
-Returns list of absolute file name and length of data inserted.\n\
-If second argument VISIT is non-nil, the buffer's visited filename\n\
-and last save file modtime are set, and it is marked unmodified.\n\
-If visiting and the file does not exist, visiting is completed\n\
-before the error is signaled.\n\n\
-The optional third and fourth arguments BEG and END\n\
-specify what portion of the file to insert.\n\
-If VISIT is non-nil, BEG and END must be nil.\n\
-\n\
-If optional fifth argument REPLACE is non-nil,\n\
-it means replace the current buffer contents (in the accessible portion)\n\
-with the file contents. This is better than simply deleting and inserting\n\
-the whole thing because (1) it preserves some marker positions\n\
-and (2) it puts less data in the undo list.\n\
-When REPLACE is non-nil, the value is the number of characters actually read,\n\
-which is often less than the number of characters to be read.")
- (filename, visit, beg, end, replace)
- Lisp_Object filename, visit, beg, end, replace;
-{
- struct stat st;
- register int fd;
- register int inserted = 0;
- register int how_much;
- int count = specpdl_ptr - specpdl;
- struct gcpro gcpro1, gcpro2, gcpro3;
- Lisp_Object handler, val, insval;
- Lisp_Object p;
- int total;
- int not_regular = 0;
-
- if (current_buffer->base_buffer && ! NILP (visit))
- error ("Cannot do file visiting in an indirect buffer");
-
- if (!NILP (current_buffer->read_only))
- Fbarf_if_buffer_read_only ();
-
- val = Qnil;
- p = Qnil;
-
- GCPRO3 (filename, val, p);
-
- CHECK_STRING (filename, 0);
- filename = Fexpand_file_name (filename, Qnil);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qinsert_file_contents);
- if (!NILP (handler))
- {
- val = call6 (handler, Qinsert_file_contents, filename,
- visit, beg, end, replace);
- goto handled;
- }
-
- fd = -1;
-
-#ifndef APOLLO
- if (stat (XSTRING (filename)->data, &st) < 0)
-#else
- if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0
- || fstat (fd, &st) < 0)
-#endif /* not APOLLO */
- {
- if (fd >= 0) close (fd);
- badopen:
- if (NILP (visit))
- report_file_error ("Opening input file", Fcons (filename, Qnil));
- st.st_mtime = -1;
- how_much = 0;
- goto notfound;
- }
-
-#ifdef S_IFREG
- /* This code will need to be changed in order to work on named
- pipes, and it's probably just not worth it. So we should at
- least signal an error. */
- if (!S_ISREG (st.st_mode))
- {
- if (NILP (visit))
- Fsignal (Qfile_error,
- Fcons (build_string ("not a regular file"),
- Fcons (filename, Qnil)));
-
- not_regular = 1;
- goto notfound;
- }
-#endif
-
- if (fd < 0)
- if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0)
- goto badopen;
-
- /* Replacement should preserve point as it preserves markers. */
- if (!NILP (replace))
- record_unwind_protect (restore_point_unwind, Fpoint_marker ());
-
- record_unwind_protect (close_file_unwind, make_number (fd));
-
- /* Supposedly happens on VMS. */
- if (st.st_size < 0)
- error ("File size is negative");
-
- if (!NILP (beg) || !NILP (end))
- if (!NILP (visit))
- error ("Attempt to visit less than an entire file");
-
- if (!NILP (beg))
- CHECK_NUMBER (beg, 0);
- else
- XSETFASTINT (beg, 0);
-
- if (!NILP (end))
- CHECK_NUMBER (end, 0);
- else
- {
- XSETINT (end, st.st_size);
- if (XINT (end) != st.st_size)
- error ("maximum buffer size exceeded");
- }
-
- /* If requested, replace the accessible part of the buffer
- with the file contents. Avoid replacing text at the
- beginning or end of the buffer that matches the file contents;
- that preserves markers pointing to the unchanged parts. */
-#ifdef DOS_NT
- /* On MSDOS, replace mode doesn't really work, except for binary files,
- and it's not worth supporting just for them. */
- if (!NILP (replace))
- {
- replace = Qnil;
- del_range_1 (BEGV, ZV, 0);
- }
-#else /* not DOS_NT */
- if (!NILP (replace))
- {
- unsigned char buffer[1 << 14];
- int same_at_start = BEGV;
- int same_at_end = ZV;
- int overlap;
-
- if (XINT (beg) != 0)
- {
- if (lseek (fd, XINT (beg), 0) < 0)
- report_file_error ("Setting file position",
- Fcons (filename, Qnil));
- }
-
- immediate_quit = 1;
- QUIT;
- /* Count how many chars at the start of the file
- match the text at the beginning of the buffer. */
- while (1)
- {
- int nread, bufpos;
-
- nread = read (fd, buffer, sizeof buffer);
- if (nread < 0)
- error ("IO error reading %s: %s",
- XSTRING (filename)->data, strerror (errno));
- else if (nread == 0)
- break;
- bufpos = 0;
- while (bufpos < nread && same_at_start < ZV
- && FETCH_CHAR (same_at_start) == buffer[bufpos])
- same_at_start++, bufpos++;
- /* If we found a discrepancy, stop the scan.
- Otherwise loop around and scan the next bufferful. */
- if (bufpos != nread)
- break;
- }
- immediate_quit = 0;
- /* If the file matches the buffer completely,
- there's no need to replace anything. */
- if (same_at_start - BEGV == XINT (end))
- {
- close (fd);
- specpdl_ptr--;
- /* Truncate the buffer to the size of the file. */
- del_range_1 (same_at_start, same_at_end, 0);
- goto handled;
- }
- immediate_quit = 1;
- QUIT;
- /* Count how many chars at the end of the file
- match the text at the end of the buffer. */
- while (1)
- {
- int total_read, nread, bufpos, curpos, trial;
-
- /* At what file position are we now scanning? */
- curpos = XINT (end) - (ZV - same_at_end);
- /* If the entire file matches the buffer tail, stop the scan. */
- if (curpos == 0)
- break;
- /* How much can we scan in the next step? */
- trial = min (curpos, sizeof buffer);
- if (lseek (fd, curpos - trial, 0) < 0)
- report_file_error ("Setting file position",
- Fcons (filename, Qnil));
-
- total_read = 0;
- while (total_read < trial)
- {
- nread = read (fd, buffer + total_read, trial - total_read);
- if (nread <= 0)
- error ("IO error reading %s: %s",
- XSTRING (filename)->data, strerror (errno));
- total_read += nread;
- }
- /* Scan this bufferful from the end, comparing with
- the Emacs buffer. */
- bufpos = total_read;
- /* Compare with same_at_start to avoid counting some buffer text
- as matching both at the file's beginning and at the end. */
- while (bufpos > 0 && same_at_end > same_at_start
- && FETCH_CHAR (same_at_end - 1) == buffer[bufpos - 1])
- same_at_end--, bufpos--;
- /* If we found a discrepancy, stop the scan.
- Otherwise loop around and scan the preceding bufferful. */
- if (bufpos != 0)
- break;
- /* If display current starts at beginning of line,
- keep it that way. */
- if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
- XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
- }
- immediate_quit = 0;
-
- /* Don't try to reuse the same piece of text twice. */
- overlap = same_at_start - BEGV - (same_at_end + st.st_size - ZV);
- if (overlap > 0)
- same_at_end += overlap;
-
- /* Arrange to read only the nonmatching middle part of the file. */
- XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV));
- XSETFASTINT (end, XINT (end) - (ZV - same_at_end));
-
- del_range_1 (same_at_start, same_at_end, 0);
- /* Insert from the file at the proper position. */
- SET_PT (same_at_start);
- }
-#endif /* not DOS_NT */
-
- total = XINT (end) - XINT (beg);
-
- {
- register Lisp_Object temp;
-
- /* Make sure point-max won't overflow after this insertion. */
- XSETINT (temp, total);
- if (total != XINT (temp))
- error ("maximum buffer size exceeded");
- }
-
- if (NILP (visit) && total > 0)
- prepare_to_modify_buffer (PT, PT);
-
- move_gap (PT);
- if (GAP_SIZE < total)
- make_gap (total - GAP_SIZE);
-
- if (XINT (beg) != 0 || !NILP (replace))
- {
- if (lseek (fd, XINT (beg), 0) < 0)
- report_file_error ("Setting file position", Fcons (filename, Qnil));
- }
-
- how_much = 0;
- while (inserted < total)
- {
- /* try is reserved in some compilers (Microsoft C) */
- int trytry = min (total - inserted, 64 << 10);
- int this;
-
- /* Allow quitting out of the actual I/O. */
- immediate_quit = 1;
- QUIT;
- this = read (fd, &FETCH_CHAR (PT + inserted - 1) + 1, trytry);
- immediate_quit = 0;
-
- if (this <= 0)
- {
- how_much = this;
- break;
- }
-
- GPT += this;
- GAP_SIZE -= this;
- ZV += this;
- Z += this;
- inserted += this;
- }
-
-#ifdef DOS_NT
- /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */
- /* Determine file type from name and remove LFs from CR-LFs if the file
- is deemed to be a text file. */
- {
- current_buffer->buffer_file_type
- = call1 (Qfind_buffer_file_type, filename);
- if (NILP (current_buffer->buffer_file_type))
- {
- int reduced_size
- = inserted - crlf_to_lf (inserted, &FETCH_CHAR (PT - 1) + 1);
- ZV -= reduced_size;
- Z -= reduced_size;
- GPT -= reduced_size;
- GAP_SIZE += reduced_size;
- inserted -= reduced_size;
- }
- }
-#endif /* DOS_NT */
-
- if (inserted > 0)
- {
- record_insert (PT, inserted);
-
- /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
- offset_intervals (current_buffer, PT, inserted);
- MODIFF++;
- }
-
- close (fd);
-
- /* Discard the unwind protect for closing the file. */
- specpdl_ptr--;
-
- if (how_much < 0)
- error ("IO error reading %s: %s",
- XSTRING (filename)->data, strerror (errno));
-
- notfound:
- handled:
-
- if (!NILP (visit))
- {
- if (!EQ (current_buffer->undo_list, Qt))
- current_buffer->undo_list = Qnil;
-#ifdef APOLLO
- stat (XSTRING (filename)->data, &st);
-#endif
-
- if (NILP (handler))
- {
- current_buffer->modtime = st.st_mtime;
- current_buffer->filename = filename;
- }
-
- SAVE_MODIFF = MODIFF;
- current_buffer->auto_save_modified = MODIFF;
- XSETFASTINT (current_buffer->save_length, Z - BEG);
-#ifdef CLASH_DETECTION
- if (NILP (handler))
- {
- if (!NILP (current_buffer->file_truename))
- unlock_file (current_buffer->file_truename);
- unlock_file (filename);
- }
-#endif /* CLASH_DETECTION */
- if (not_regular)
- Fsignal (Qfile_error,
- Fcons (build_string ("not a regular file"),
- Fcons (filename, Qnil)));
-
- /* If visiting nonexistent file, return nil. */
- if (current_buffer->modtime == -1)
- report_file_error ("Opening input file", Fcons (filename, Qnil));
- }
-
- /* Decode file format */
- if (inserted > 0)
- {
- insval = call3 (Qformat_decode,
- Qnil, make_number (inserted), visit);
- CHECK_NUMBER (insval, 0);
- inserted = XFASTINT (insval);
- }
-
- if (inserted > 0 && NILP (visit) && total > 0)
- signal_after_change (PT, 0, inserted);
-
- if (inserted > 0)
- {
- p = Vafter_insert_file_functions;
- while (!NILP (p))
- {
- insval = call1 (Fcar (p), make_number (inserted));
- if (!NILP (insval))
- {
- CHECK_NUMBER (insval, 0);
- inserted = XFASTINT (insval);
- }
- QUIT;
- p = Fcdr (p);
- }
- }
-
- if (NILP (val))
- val = Fcons (filename,
- Fcons (make_number (inserted),
- Qnil));
-
- RETURN_UNGCPRO (unbind_to (count, val));
-}
-
-static Lisp_Object build_annotations ();
-
-/* If build_annotations switched buffers, switch back to BUF.
- Kill the temporary buffer that was selected in the meantime. */
-
-static Lisp_Object
-build_annotations_unwind (buf)
- Lisp_Object buf;
-{
- Lisp_Object tembuf;
-
- if (XBUFFER (buf) == current_buffer)
- return Qnil;
- tembuf = Fcurrent_buffer ();
- Fset_buffer (buf);
- Fkill_buffer (tembuf);
- return Qnil;
-}
-
-DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 6,
- "r\nFWrite region to file: ",
- "Write current region into specified file.\n\
-When called from a program, takes three arguments:\n\
-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\
- and mark buffer not modified.\n\
-If VISIT is a string, it is a second file name;\n\
- the output goes to FILENAME, but the buffer is marked as visiting VISIT.\n\
- VISIT is also the file name to lock and unlock for clash detection.\n\
-If VISIT is neither t nor nil nor a string,\n\
- that means do not print the \"Wrote file\" message.\n\
-The optional sixth arg LOCKNAME, if non-nil, specifies the name to\n\
- use for locking and unlocking, overriding FILENAME and VISIT.\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.")
- (start, end, filename, append, visit, lockname)
- Lisp_Object start, end, filename, append, visit, lockname;
-{
- register int desc;
- int failure;
- int save_errno;
- unsigned char *fn;
- struct stat st;
- int tem;
- int count = specpdl_ptr - specpdl;
- int count1;
-#ifdef VMS
- unsigned char *fname = 0; /* If non-0, original filename (must rename) */
-#endif /* VMS */
- Lisp_Object handler;
- Lisp_Object visit_file;
- Lisp_Object annotations;
- int visiting, quietly;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
- struct buffer *given_buffer;
-#ifdef DOS_NT
- int buffer_file_type
- = NILP (current_buffer->buffer_file_type) ? O_TEXT : O_BINARY;
-#endif /* DOS_NT */
-
- if (current_buffer->base_buffer && ! NILP (visit))
- error ("Cannot do file visiting in an indirect buffer");
-
- if (!NILP (start) && !STRINGP (start))
- validate_region (&start, &end);
-
- GCPRO3 (filename, visit, lockname);
- filename = Fexpand_file_name (filename, Qnil);
- if (STRINGP (visit))
- visit_file = Fexpand_file_name (visit, Qnil);
- else
- visit_file = filename;
- UNGCPRO;
-
- visiting = (EQ (visit, Qt) || STRINGP (visit));
- quietly = !NILP (visit);
-
- annotations = Qnil;
-
- if (NILP (lockname))
- lockname = visit_file;
-
- GCPRO5 (start, filename, annotations, visit_file, lockname);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qwrite_region);
- /* If FILENAME has no handler, see if VISIT has one. */
- if (NILP (handler) && STRINGP (visit))
- handler = Ffind_file_name_handler (visit, Qwrite_region);
-
- if (!NILP (handler))
- {
- Lisp_Object val;
- val = call6 (handler, Qwrite_region, start, end,
- filename, append, visit);
-
- if (visiting)
- {
- SAVE_MODIFF = MODIFF;
- XSETFASTINT (current_buffer->save_length, Z - BEG);
- current_buffer->filename = visit_file;
- }
- UNGCPRO;
- return val;
- }
-
- /* Special kludge to simplify auto-saving. */
- if (NILP (start))
- {
- XSETFASTINT (start, BEG);
- XSETFASTINT (end, Z);
- }
-
- record_unwind_protect (build_annotations_unwind, Fcurrent_buffer ());
- count1 = specpdl_ptr - specpdl;
-
- given_buffer = current_buffer;
- annotations = build_annotations (start, end);
- if (current_buffer != given_buffer)
- {
- start = BEGV;
- end = ZV;
- }
-
-#ifdef CLASH_DETECTION
- if (!auto_saving)
- {
- /* If we've locked this file for some other buffer,
- query before proceeding. */
- if (!visiting && EQ (Ffile_locked_p (lockname), Qt))
- call2 (intern ("ask-user-about-lock"), fn, Vuser_login_name);
-
- lock_file (lockname);
- }
-#endif /* CLASH_DETECTION */
-
- fn = XSTRING (filename)->data;
- desc = -1;
- if (!NILP (append))
-#ifdef DOS_NT
- desc = open (fn, O_WRONLY | buffer_file_type);
-#else /* not DOS_NT */
- desc = open (fn, O_WRONLY);
-#endif /* not DOS_NT */
-
- if (desc < 0 && (NILP (append) || errno == ENOENT) )
-#ifdef VMS
- if (auto_saving) /* Overwrite any previous version of autosave file */
- {
- vms_truncate (fn); /* if fn exists, truncate to zero length */
- desc = open (fn, O_RDWR);
- if (desc < 0)
- desc = creat_copy_attrs (STRINGP (current_buffer->filename)
- ? XSTRING (current_buffer->filename)->data : 0,
- fn);
- }
- else /* Write to temporary name and rename if no errors */
- {
- Lisp_Object temp_name;
- temp_name = Ffile_name_directory (filename);
-
- if (!NILP (temp_name))
- {
- temp_name = Fmake_temp_name (concat2 (temp_name,
- build_string ("$$SAVE$$")));
- fname = XSTRING (filename)->data;
- fn = XSTRING (temp_name)->data;
- desc = creat_copy_attrs (fname, fn);
- if (desc < 0)
- {
- /* If we can't open the temporary file, try creating a new
- version of the original file. VMS "creat" creates a
- new version rather than truncating an existing file. */
- 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 (desc < 0)
- {
- /* We can't make a new version;
- try to truncate and rewrite existing version if any. */
- vms_truncate (fn);
- desc = open (fn, O_RDWR);
- }
-#endif
- }
- }
- else
- desc = creat (fn, 0666);
- }
-#else /* not VMS */
-#ifdef DOS_NT
- desc = open (fn,
- O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type,
- S_IREAD | S_IWRITE);
-#else /* not DOS_NT */
- desc = creat (fn, auto_saving ? auto_save_mode_bits : 0666);
-#endif /* not DOS_NT */
-#endif /* not VMS */
-
- UNGCPRO;
-
- if (desc < 0)
- {
-#ifdef CLASH_DETECTION
- save_errno = errno;
- if (!auto_saving) unlock_file (lockname);
- errno = save_errno;
-#endif /* CLASH_DETECTION */
- report_file_error ("Opening output file", Fcons (filename, Qnil));
- }
-
- record_unwind_protect (close_file_unwind, make_number (desc));
-
- if (!NILP (append))
- if (lseek (desc, 0, 2) < 0)
- {
-#ifdef CLASH_DETECTION
- if (!auto_saving) unlock_file (lockname);
-#endif /* CLASH_DETECTION */
- report_file_error ("Lseek error", Fcons (filename, Qnil));
- }
-
-#ifdef VMS
-/*
- * Kludge Warning: The VMS C RTL likes to insert carriage returns
- * if we do writes that don't end with a carriage return. Furthermore
- * it cannot handle writes of more then 16K. The modified
- * version of "sys_write" in SYSDEP.C (see comment there) copes with
- * this EXCEPT for the last record (iff it doesn't end with a carriage
- * return). This implies that if your buffer doesn't end with a carriage
- * return, you get one free... tough. However it also means that if
- * we make two calls to sys_write (a la the following code) you can
- * get one at the gap as well. The easiest way to fix this (honest)
- * is to move the gap to the next newline (or the end of the buffer).
- * Thus this change.
- *
- * Yech!
- */
- if (GPT > BEG && GPT_ADDR[-1] != '\n')
- move_gap (find_next_newline (GPT, 1));
-#endif
-
- failure = 0;
- immediate_quit = 1;
-
- if (STRINGP (start))
- {
- failure = 0 > a_write (desc, XSTRING (start)->data,
- XSTRING (start)->size, 0, &annotations);
- save_errno = errno;
- }
- else if (XINT (start) != XINT (end))
- {
- int nwritten = 0;
- if (XINT (start) < GPT)
- {
- register int end1 = XINT (end);
- tem = XINT (start);
- failure = 0 > a_write (desc, &FETCH_CHAR (tem),
- min (GPT, end1) - tem, tem, &annotations);
- nwritten += min (GPT, end1) - tem;
- save_errno = errno;
- }
-
- if (XINT (end) > GPT && !failure)
- {
- tem = XINT (start);
- tem = max (tem, GPT);
- failure = 0 > a_write (desc, &FETCH_CHAR (tem), XINT (end) - tem,
- tem, &annotations);
- nwritten += XINT (end) - tem;
- save_errno = errno;
- }
- }
- else
- {
- /* If file was empty, still need to write the annotations */
- failure = 0 > a_write (desc, "", 0, XINT (start), &annotations);
- save_errno = errno;
- }
-
- immediate_quit = 0;
-
-#ifdef HAVE_FSYNC
- /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
- Disk full in NFS may be reported here. */
- /* mib says that closing the file will try to write as fast as NFS can do
- it, and that means the fsync here is not crucial for autosave files. */
- if (!auto_saving && fsync (desc) < 0)
- {
- /* If fsync fails with EINTR, don't treat that as serious. */
- if (errno != EINTR)
- failure = 1, save_errno = errno;
- }
-#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
-
- /* On VMS and APOLLO, must do the stat after the close
- since closing changes the modtime. */
-#ifndef VMS
-#ifndef APOLLO
- /* Recall that #if defined does not work on VMS. */
-#define FOO
- fstat (desc, &st);
-#endif
-#endif
-#endif
-
- /* NFS can report a write failure now. */
- if (close (desc) < 0)
- failure = 1, save_errno = errno;
-
-#ifdef VMS
- /* If we wrote to a temporary name and had no errors, rename to real name. */
- if (fname)
- {
- if (!failure)
- failure = (rename (fn, fname) != 0), save_errno = errno;
- fn = fname;
- }
-#endif /* VMS */
-
-#ifndef FOO
- stat (fn, &st);
-#endif
- /* Discard the unwind protect for close_file_unwind. */
- specpdl_ptr = specpdl + count1;
- /* Restore the original current buffer. */
- visit_file = unbind_to (count, visit_file);
-
-#ifdef CLASH_DETECTION
- if (!auto_saving)
- unlock_file (lockname);
-#endif /* CLASH_DETECTION */
-
- /* Do this before reporting IO error
- to avoid a "file has changed on disk" warning on
- next attempt to save. */
- if (visiting)
- current_buffer->modtime = st.st_mtime;
-
- if (failure)
- error ("IO error writing %s: %s", fn, strerror (save_errno));
-
- if (visiting)
- {
- SAVE_MODIFF = MODIFF;
- XSETFASTINT (current_buffer->save_length, Z - BEG);
- current_buffer->filename = visit_file;
- update_mode_lines++;
- }
- else if (quietly)
- return Qnil;
-
- if (!auto_saving)
- message ("Wrote %s", XSTRING (visit_file)->data);
-
- return Qnil;
-}
-
-Lisp_Object merge ();
-
-DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
- "Return t if (car A) is numerically less than (car B).")
- (a, b)
- Lisp_Object a, b;
-{
- return Flss (Fcar (a), Fcar (b));
-}
-
-/* Build the complete list of annotations appropriate for writing out
- the text between START and END, by calling all the functions in
- write-region-annotate-functions and merging the lists they return.
- If one of these functions switches to a different buffer, we assume
- that buffer contains altered text. Therefore, the caller must
- make sure to restore the current buffer in all cases,
- as save-excursion would do. */
-
-static Lisp_Object
-build_annotations (start, end)
- Lisp_Object start, end;
-{
- Lisp_Object annotations;
- Lisp_Object p, res;
- struct gcpro gcpro1, gcpro2;
- Lisp_Object original_buffer;
-
- XSETBUFFER (original_buffer, current_buffer);
-
- annotations = Qnil;
- p = Vwrite_region_annotate_functions;
- GCPRO2 (annotations, p);
- while (!NILP (p))
- {
- struct buffer *given_buffer = current_buffer;
- Vwrite_region_annotations_so_far = annotations;
- res = call2 (Fcar (p), start, end);
- /* If the function makes a different buffer current,
- assume that means this buffer contains altered text to be output.
- Reset START and END from the buffer bounds
- and discard all previous annotations because they should have
- been dealt with by this function. */
- if (current_buffer != given_buffer)
- {
- start = BEGV;
- end = ZV;
- annotations = Qnil;
- }
- Flength (res); /* Check basic validity of return value */
- annotations = merge (annotations, res, Qcar_less_than_car);
- p = Fcdr (p);
- }
-
- /* Now do the same for annotation functions implied by the file-format */
- if (auto_saving && (!EQ (Vauto_save_file_format, Qt)))
- p = Vauto_save_file_format;
- else
- p = current_buffer->file_format;
- while (!NILP (p))
- {
- struct buffer *given_buffer = current_buffer;
- Vwrite_region_annotations_so_far = annotations;
- res = call4 (Qformat_annotate_function, Fcar (p), start, end,
- original_buffer);
- if (current_buffer != given_buffer)
- {
- start = BEGV;
- end = ZV;
- annotations = Qnil;
- }
- Flength (res);
- annotations = merge (annotations, res, Qcar_less_than_car);
- p = Fcdr (p);
- }
- UNGCPRO;
- return annotations;
-}
-
-/* Write to descriptor DESC the LEN characters starting at ADDR,
- assuming they start at position POS in the buffer.
- Intersperse with them the annotations from *ANNOT
- (those which fall within the range of positions POS to POS + LEN),
- each at its appropriate position.
-
- Modify *ANNOT by discarding elements as we output them.
- The return value is negative in case of system call failure. */
-
-int
-a_write (desc, addr, len, pos, annot)
- int desc;
- register char *addr;
- register int len;
- int pos;
- Lisp_Object *annot;
-{
- Lisp_Object tem;
- int nextpos;
- int lastpos = pos + len;
-
- while (NILP (*annot) || CONSP (*annot))
- {
- tem = Fcar_safe (Fcar (*annot));
- if (INTEGERP (tem) && XINT (tem) >= pos && XFASTINT (tem) <= lastpos)
- nextpos = XFASTINT (tem);
- else
- return e_write (desc, addr, lastpos - pos);
- if (nextpos > pos)
- {
- if (0 > e_write (desc, addr, nextpos - pos))
- return -1;
- addr += nextpos - pos;
- pos = nextpos;
- }
- tem = Fcdr (Fcar (*annot));
- if (STRINGP (tem))
- {
- if (0 > e_write (desc, XSTRING (tem)->data, XSTRING (tem)->size))
- return -1;
- }
- *annot = Fcdr (*annot);
- }
-}
-
-int
-e_write (desc, addr, len)
- int desc;
- register char *addr;
- register int len;
-{
- char buf[16 * 1024];
- register char *p, *end;
-
- if (!EQ (current_buffer->selective_display, Qt))
- return write (desc, addr, len) - len;
- else
- {
- p = buf;
- end = p + sizeof buf;
- while (len--)
- {
- if (p == end)
- {
- if (write (desc, buf, sizeof buf) != sizeof buf)
- return -1;
- p = buf;
- }
- *p = *addr++;
- if (*p++ == '\015')
- p[-1] = '\n';
- }
- if (p != buf)
- if (write (desc, buf, p - buf) != p - buf)
- return -1;
- }
- return 0;
-}
-
-DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
- Sverify_visited_file_modtime, 1, 1, 0,
- "Return t if last mod time of BUF's visited file matches what BUF records.\n\
-This means that the file has not been changed since it was visited or saved.")
- (buf)
- Lisp_Object buf;
-{
- struct buffer *b;
- struct stat st;
- Lisp_Object handler;
-
- CHECK_BUFFER (buf, 0);
- b = XBUFFER (buf);
-
- if (!STRINGP (b->filename)) return Qt;
- if (b->modtime == 0) return Qt;
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (b->filename,
- Qverify_visited_file_modtime);
- if (!NILP (handler))
- return call2 (handler, Qverify_visited_file_modtime, buf);
-
- if (stat (XSTRING (b->filename)->data, &st) < 0)
- {
- /* If the file doesn't exist now and didn't exist before,
- we say that it isn't modified, provided the error is a tame one. */
- if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)
- st.st_mtime = -1;
- else
- st.st_mtime = 0;
- }
- if (st.st_mtime == b->modtime
- /* If both are positive, accept them if they are off by one second. */
- || (st.st_mtime > 0 && b->modtime > 0
- && (st.st_mtime == b->modtime + 1
- || st.st_mtime == b->modtime - 1)))
- return Qt;
- return Qnil;
-}
-
-DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
- Sclear_visited_file_modtime, 0, 0, 0,
- "Clear out records of last mod time of visited file.\n\
-Next attempt to save will certainly not complain of a discrepancy.")
- ()
-{
- current_buffer->modtime = 0;
- return Qnil;
-}
-
-DEFUN ("visited-file-modtime", Fvisited_file_modtime,
- Svisited_file_modtime, 0, 0, 0,
- "Return the current buffer's recorded visited file modification time.\n\
-The value is a list of the form (HIGH . LOW), like the time values\n\
-that `file-attributes' returns.")
- ()
-{
- return long_to_cons ((unsigned long) current_buffer->modtime);
-}
-
-DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
- Sset_visited_file_modtime, 0, 1, 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.\n\
-An argument specifies the modification time value to use\n\
-\(instead of that of the visited file), in the form of a list\n\
-\(HIGH . LOW) or (HIGH LOW).")
- (time_list)
- Lisp_Object time_list;
-{
- if (!NILP (time_list))
- current_buffer->modtime = cons_to_long (time_list);
- else
- {
- register Lisp_Object filename;
- struct stat st;
- Lisp_Object handler;
-
- filename = Fexpand_file_name (current_buffer->filename, Qnil);
-
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qset_visited_file_modtime);
- if (!NILP (handler))
- /* The handler can find the file name the same way we did. */
- return call2 (handler, Qset_visited_file_modtime, Qnil);
- else if (stat (XSTRING (filename)->data, &st) >= 0)
- current_buffer->modtime = st.st_mtime;
- }
-
- return Qnil;
-}
-
-Lisp_Object
-auto_save_error ()
-{
- ring_bell ();
- message ("Autosaving...error for %s", XSTRING (current_buffer->name)->data);
- Fsleep_for (make_number (1), Qnil);
- message ("Autosaving...error!for %s", XSTRING (current_buffer->name)->data);
- Fsleep_for (make_number (1), Qnil);
- message ("Autosaving...error for %s", XSTRING (current_buffer->name)->data);
- Fsleep_for (make_number (1), Qnil);
- return Qnil;
-}
-
-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, Qnil);
-}
-
-static Lisp_Object
-do_auto_save_unwind (desc) /* used as unwind-protect function */
- Lisp_Object desc;
-{
- auto_saving = 0;
- if (XINT (desc) >= 0)
- close (XINT (desc));
- return Qnil;
-}
-
-DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
- "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\
-Normally we run the normal hook `auto-save-hook' before saving.\n\n\
-A non-nil NO-MESSAGE argument means do not print any message if successful.\n\
-A non-nil CURRENT-ONLY argument means save only current buffer.")
- (no_message, current_only)
- Lisp_Object no_message, current_only;
-{
- struct buffer *old = current_buffer, *b;
- Lisp_Object tail, buf;
- int auto_saved = 0;
- char *omessage = echo_area_glyphs;
- int omessage_length = echo_area_glyphs_length;
- int do_handled_files;
- Lisp_Object oquit;
- int listdesc;
- int count = specpdl_ptr - specpdl;
- int *ptr;
-
- /* Ordinarily don't quit within this function,
- but don't make it impossible to quit (in case we get hung in I/O). */
- oquit = Vquit_flag;
- Vquit_flag = Qnil;
-
- /* No GCPRO needed, because (when it matters) all Lisp_Object variables
- point to non-strings reached from Vbuffer_alist. */
-
- if (minibuf_level)
- no_message = Qt;
-
- if (!NILP (Vrun_hooks))
- call1 (Vrun_hooks, intern ("auto-save-hook"));
-
- if (STRINGP (Vauto_save_list_file_name))
- {
- Lisp_Object listfile;
- listfile = Fexpand_file_name (Vauto_save_list_file_name, Qnil);
-#ifdef DOS_NT
- listdesc = open (XSTRING (listfile)->data,
- O_WRONLY | O_TRUNC | O_CREAT | O_TEXT,
- S_IREAD | S_IWRITE);
-#else /* not DOS_NT */
- listdesc = creat (XSTRING (listfile)->data, 0666);
-#endif /* not DOS_NT */
- }
- else
- listdesc = -1;
-
- /* Arrange to close that file whether or not we get an error.
- Also reset auto_saving to 0. */
- record_unwind_protect (do_auto_save_unwind, make_number (listdesc));
-
- auto_saving = 1;
-
- /* First, save all files which don't have handlers. If Emacs is
- crashing, the handlers may tweak what is causing Emacs to crash
- in the first place, and it would be a shame if Emacs failed to
- autosave perfectly ordinary files because it couldn't handle some
- ange-ftp'd file. */
- for (do_handled_files = 0; do_handled_files < 2; do_handled_files++)
- for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCONS (tail)->cdr)
- {
- buf = XCONS (XCONS (tail)->car)->cdr;
- b = XBUFFER (buf);
-
- /* Record all the buffers that have auto save mode
- in the special file that lists them. For each of these buffers,
- Record visited name (if any) and auto save name. */
- if (STRINGP (b->auto_save_file_name)
- && listdesc >= 0 && do_handled_files == 0)
- {
- if (!NILP (b->filename))
- {
- write (listdesc, XSTRING (b->filename)->data,
- XSTRING (b->filename)->size);
- }
- write (listdesc, "\n", 1);
- write (listdesc, XSTRING (b->auto_save_file_name)->data,
- XSTRING (b->auto_save_file_name)->size);
- write (listdesc, "\n", 1);
- }
-
- if (!NILP (current_only)
- && b != current_buffer)
- continue;
-
- /* Don't auto-save indirect buffers.
- The base buffer takes care of it. */
- if (b->base_buffer)
- continue;
-
- /* Check for auto save enabled
- and file changed since last auto save
- and file changed since last real save. */
- if (STRINGP (b->auto_save_file_name)
- && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)
- && b->auto_save_modified < BUF_MODIFF (b)
- /* -1 means we've turned off autosaving for a while--see below. */
- && XINT (b->save_length) >= 0
- && (do_handled_files
- || NILP (Ffind_file_name_handler (b->auto_save_file_name,
- Qwrite_region))))
- {
- EMACS_TIME before_time, after_time;
-
- EMACS_GET_TIME (before_time);
-
- /* If we had a failure, don't try again for 20 minutes. */
- if (b->auto_save_failure_time >= 0
- && EMACS_SECS (before_time) - b->auto_save_failure_time < 1200)
- continue;
-
- if ((XFASTINT (b->save_length) * 10
- > (BUF_Z (b) - BUF_BEG (b)) * 13)
- /* A short file is likely to change a large fraction;
- spare the user annoying messages. */
- && XFASTINT (b->save_length) > 5000
- /* These messages are frequent and annoying for `*mail*'. */
- && !EQ (b->filename, Qnil)
- && NILP (no_message))
- {
- /* It has shrunk too much; turn off auto-saving here. */
- message ("Buffer %s has shrunk a lot; auto save turned off there",
- XSTRING (b->name)->data);
- /* Turn off auto-saving until there's a real save,
- and prevent any more warnings. */
- XSETINT (b->save_length, -1);
- Fsleep_for (make_number (1), Qnil);
- continue;
- }
- set_buffer_internal (b);
- if (!auto_saved && NILP (no_message))
- message1 ("Auto-saving...");
- internal_condition_case (auto_save_1, Qt, auto_save_error);
- auto_saved++;
- b->auto_save_modified = BUF_MODIFF (b);
- XSETFASTINT (current_buffer->save_length, Z - BEG);
- set_buffer_internal (old);
-
- EMACS_GET_TIME (after_time);
-
- /* If auto-save took more than 60 seconds,
- assume it was an NFS failure that got a timeout. */
- if (EMACS_SECS (after_time) - EMACS_SECS (before_time) > 60)
- b->auto_save_failure_time = EMACS_SECS (after_time);
- }
- }
-
- /* Prevent another auto save till enough input events come in. */
- record_auto_save ();
-
- if (auto_saved && NILP (no_message))
- {
- if (omessage)
- {
- sit_for (1, 0, 0, 0);
- message2 (omessage, omessage_length);
- }
- else
- message1 ("Auto-saving...done");
- }
-
- Vquit_flag = oquit;
-
- unbind_to (count, Qnil);
- return Qnil;
-}
-
-DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved,
- Sset_buffer_auto_saved, 0, 0, 0,
- "Mark current buffer as auto-saved with its current text.\n\
-No auto-save file will be written until the buffer changes again.")
- ()
-{
- current_buffer->auto_save_modified = MODIFF;
- XSETFASTINT (current_buffer->save_length, Z - BEG);
- current_buffer->auto_save_failure_time = -1;
- return Qnil;
-}
-
-DEFUN ("clear-buffer-auto-save-failure", Fclear_buffer_auto_save_failure,
- Sclear_buffer_auto_save_failure, 0, 0, 0,
- "Clear any record of a recent auto-save failure in the current buffer.")
- ()
-{
- current_buffer->auto_save_failure_time = -1;
- return Qnil;
-}
-
-DEFUN ("recent-auto-save-p", Frecent_auto_save_p, Srecent_auto_save_p,
- 0, 0, 0,
- "Return t if buffer has been auto-saved since last read in or saved.")
- ()
-{
- return (SAVE_MODIFF < current_buffer->auto_save_modified) ? Qt : Qnil;
-}
-
-/* Reading and completing file names */
-extern Lisp_Object Ffile_name_completion (), Ffile_name_all_completions ();
-
-/* In the string VAL, change each $ to $$ and return the result. */
-
-static Lisp_Object
-double_dollars (val)
- Lisp_Object val;
-{
- register unsigned char *old, *new;
- register int n;
- int osize, count;
-
- osize = XSTRING (val)->size;
- /* Quote "$" as "$$" to get it past substitute-in-file-name */
- for (n = osize, count = 0, old = XSTRING (val)->data; n > 0; n--)
- if (*old++ == '$') count++;
- if (count > 0)
- {
- old = XSTRING (val)->data;
- val = Fmake_string (make_number (osize + count), make_number (0));
- new = XSTRING (val)->data;
- for (n = osize; n > 0; n--)
- if (*old != '$')
- *new++ = *old++;
- else
- {
- *new++ = '$';
- *new++ = '$';
- old++;
- }
- }
- return val;
-}
-
-DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,
- 3, 3, 0,
- "Internal subroutine for read-file-name. Do not call this.")
- (string, dir, action)
- Lisp_Object string, dir, action;
- /* action is nil for complete, t for return list of completions,
- lambda for verify final value */
-{
- Lisp_Object name, specdir, realdir, val, orig_string;
- int changed;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
-
- CHECK_STRING (string, 0);
-
- realdir = dir;
- name = string;
- orig_string = Qnil;
- specdir = Qnil;
- changed = 0;
- /* No need to protect ACTION--we only compare it with t and nil. */
- GCPRO5 (string, realdir, name, specdir, orig_string);
-
- if (XSTRING (string)->size == 0)
- {
- if (EQ (action, Qlambda))
- {
- UNGCPRO;
- return Qnil;
- }
- }
- else
- {
- orig_string = string;
- string = Fsubstitute_in_file_name (string);
- changed = NILP (Fstring_equal (string, orig_string));
- name = Ffile_name_nondirectory (string);
- val = Ffile_name_directory (string);
- if (! NILP (val))
- realdir = Fexpand_file_name (val, realdir);
- }
-
- if (NILP (action))
- {
- specdir = Ffile_name_directory (string);
- val = Ffile_name_completion (name, realdir);
- UNGCPRO;
- if (!STRINGP (val))
- {
- if (changed)
- return double_dollars (string);
- return val;
- }
-
- if (!NILP (specdir))
- val = concat2 (specdir, val);
-#ifndef VMS
- return double_dollars (val);
-#else /* not VMS */
- return val;
-#endif /* not VMS */
- }
- UNGCPRO;
-
- if (EQ (action, Qt))
- return Ffile_name_all_completions (name, realdir);
- /* Only other case actually used is ACTION = lambda */
-#ifdef VMS
- /* Supposedly this helps commands such as `cd' that read directory names,
- but can someone explain how it helps them? -- RMS */
- if (XSTRING (name)->size == 0)
- return Qt;
-#endif /* VMS */
- 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-FILENAME if user enters a null string.\n\
- (If DEFAULT-FILENAME is omitted, the visited file name is used,\n\
- except that if INITIAL is specified, that combined with DIR 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, default_filename, mustmatch, initial)
- Lisp_Object prompt, dir, default_filename, mustmatch, initial;
-{
- Lisp_Object val, insdef, insdef1, tem;
- struct gcpro gcpro1, gcpro2;
- register char *homedir;
- int count;
-
- if (NILP (dir))
- dir = current_buffer->directory;
- if (NILP (default_filename))
- {
- if (! NILP (initial))
- default_filename = Fexpand_file_name (initial, dir);
- else
- default_filename = current_buffer->filename;
- }
-
- /* If dir starts with user's homedir, change that to ~. */
- homedir = (char *) egetenv ("HOME");
-#ifdef DOS_NT
- homedir = strcpy (alloca (strlen (homedir) + 1), homedir);
- CORRECT_DIR_SEPS (homedir);
-#endif
- if (homedir != 0
- && STRINGP (dir)
- && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
- && IS_DIRECTORY_SEP (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 && STRINGP (dir))
- {
- insdef = dir;
- if (!NILP (initial))
- {
- Lisp_Object args[2], pos;
-
- args[0] = insdef;
- args[1] = initial;
- insdef = Fconcat (2, args);
- pos = make_number (XSTRING (double_dollars (dir))->size);
- insdef1 = Fcons (double_dollars (insdef), pos);
- }
- else
- insdef1 = double_dollars (insdef);
- }
- else if (STRINGP (initial))
- {
- insdef = initial;
- insdef1 = Fcons (double_dollars (insdef), 0);
- }
- else
- insdef = Qnil, insdef1 = Qnil;
-
-#ifdef VMS
- count = specpdl_ptr - specpdl;
- specbind (intern ("completion-ignore-case"), Qt);
-#endif
-
- GCPRO2 (insdef, default_filename);
- val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
- dir, mustmatch, insdef1,
- Qfile_name_history);
-
-#ifdef VMS
- unbind_to (count, Qnil);
-#endif
-
- UNGCPRO;
- if (NILP (val))
- error ("No file name specified");
- tem = Fstring_equal (val, insdef);
- if (!NILP (tem) && !NILP (default_filename))
- return default_filename;
- if (XSTRING (val)->size == 0 && NILP (insdef))
- {
- if (!NILP (default_filename))
- return default_filename;
- else
- error ("No default file name");
- }
- return Fsubstitute_in_file_name (val);
-}
-
-#if 0 /* Old version */
-DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
- /* Don't confuse make-docfile by having two doc strings for this function.
- make-docfile does not pay attention to #if, for good reason! */
- 0)
- (prompt, dir, defalt, mustmatch, initial)
- Lisp_Object prompt, dir, defalt, mustmatch, initial;
-{
- Lisp_Object val, insdef, tem;
- struct gcpro gcpro1, gcpro2;
- register char *homedir;
- int count;
-
- if (NILP (dir))
- dir = current_buffer->directory;
- if (NILP (defalt))
- defalt = current_buffer->filename;
-
- /* If dir starts with user's homedir, change that to ~. */
- homedir = (char *) egetenv ("HOME");
- if (homedir != 0
- && STRINGP (dir)
- && !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 (!NILP (initial))
- insdef = initial;
- else if (insert_default_directory)
- insdef = dir;
- else
- insdef = build_string ("");
-
-#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,
- Qfile_name_history);
-
-#ifdef VMS
- unbind_to (count, Qnil);
-#endif
-
- UNGCPRO;
- if (NILP (val))
- error ("No file name specified");
- tem = Fstring_equal (val, insdef);
- if (!NILP (tem) && !NILP (defalt))
- return defalt;
- return Fsubstitute_in_file_name (val);
-}
-#endif /* Old version */
-
-syms_of_fileio ()
-{
- Qexpand_file_name = intern ("expand-file-name");
- Qsubstitute_in_file_name = intern ("substitute-in-file-name");
- Qdirectory_file_name = intern ("directory-file-name");
- Qfile_name_directory = intern ("file-name-directory");
- Qfile_name_nondirectory = intern ("file-name-nondirectory");
- Qunhandled_file_name_directory = intern ("unhandled-file-name-directory");
- Qfile_name_as_directory = intern ("file-name-as-directory");
- Qcopy_file = intern ("copy-file");
- Qmake_directory_internal = intern ("make-directory-internal");
- Qdelete_directory = intern ("delete-directory");
- Qdelete_file = intern ("delete-file");
- Qrename_file = intern ("rename-file");
- Qadd_name_to_file = intern ("add-name-to-file");
- Qmake_symbolic_link = intern ("make-symbolic-link");
- Qfile_exists_p = intern ("file-exists-p");
- Qfile_executable_p = intern ("file-executable-p");
- Qfile_readable_p = intern ("file-readable-p");
- Qfile_writable_p = intern ("file-writable-p");
- Qfile_symlink_p = intern ("file-symlink-p");
- Qaccess_file = intern ("access-file");
- Qfile_directory_p = intern ("file-directory-p");
- Qfile_regular_p = intern ("file-regular-p");
- Qfile_accessible_directory_p = intern ("file-accessible-directory-p");
- Qfile_modes = intern ("file-modes");
- Qset_file_modes = intern ("set-file-modes");
- Qfile_newer_than_file_p = intern ("file-newer-than-file-p");
- Qinsert_file_contents = intern ("insert-file-contents");
- Qwrite_region = intern ("write-region");
- Qverify_visited_file_modtime = intern ("verify-visited-file-modtime");
- Qset_visited_file_modtime = intern ("set-visited-file-modtime");
-
- staticpro (&Qexpand_file_name);
- staticpro (&Qsubstitute_in_file_name);
- staticpro (&Qdirectory_file_name);
- staticpro (&Qfile_name_directory);
- staticpro (&Qfile_name_nondirectory);
- staticpro (&Qunhandled_file_name_directory);
- staticpro (&Qfile_name_as_directory);
- staticpro (&Qcopy_file);
- staticpro (&Qmake_directory_internal);
- staticpro (&Qdelete_directory);
- staticpro (&Qdelete_file);
- staticpro (&Qrename_file);
- staticpro (&Qadd_name_to_file);
- staticpro (&Qmake_symbolic_link);
- staticpro (&Qfile_exists_p);
- staticpro (&Qfile_executable_p);
- staticpro (&Qfile_readable_p);
- staticpro (&Qfile_writable_p);
- staticpro (&Qaccess_file);
- staticpro (&Qfile_symlink_p);
- staticpro (&Qfile_directory_p);
- staticpro (&Qfile_regular_p);
- staticpro (&Qfile_accessible_directory_p);
- staticpro (&Qfile_modes);
- staticpro (&Qset_file_modes);
- staticpro (&Qfile_newer_than_file_p);
- staticpro (&Qinsert_file_contents);
- staticpro (&Qwrite_region);
- staticpro (&Qverify_visited_file_modtime);
- staticpro (&Qset_visited_file_modtime);
-
- Qfile_name_history = intern ("file-name-history");
- Fset (Qfile_name_history, Qnil);
- staticpro (&Qfile_name_history);
-
- Qfile_error = intern ("file-error");
- staticpro (&Qfile_error);
- Qfile_already_exists = intern ("file-already-exists");
- staticpro (&Qfile_already_exists);
-
-#ifdef DOS_NT
- Qfind_buffer_file_type = intern ("find-buffer-file-type");
- staticpro (&Qfind_buffer_file_type);
-#endif /* DOS_NT */
-
- DEFVAR_LISP ("auto-save-file-format", &Vauto_save_file_format,
- "*Format in which to write auto-save files.\n\
-Should be a list of symbols naming formats that are defined in `format-alist'.\n\
-If it is t, which is the default, auto-save files are written in the\n\
-same format as a regular save would use.");
- Vauto_save_file_format = Qt;
-
- Qformat_decode = intern ("format-decode");
- staticpro (&Qformat_decode);
- Qformat_annotate_function = intern ("format-annotate-function");
- staticpro (&Qformat_annotate_function);
-
- Qcar_less_than_car = intern ("car-less-than-car");
- staticpro (&Qcar_less_than_car);
-
- Fput (Qfile_error, Qerror_conditions,
- Fcons (Qfile_error, Fcons (Qerror, Qnil)));
- Fput (Qfile_error, Qerror_message,
- build_string ("File error"));
-
- Fput (Qfile_already_exists, Qerror_conditions,
- Fcons (Qfile_already_exists,
- Fcons (Qfile_error, Fcons (Qerror, Qnil))));
- Fput (Qfile_already_exists, Qerror_message,
- build_string ("File already exists"));
-
- DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,
- "*Non-nil means when reading a filename start with default dir in minibuffer.");
- insert_default_directory = 1;
-
- DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,
- "*Non-nil means write new files with record format `stmlf'.\n\
-nil means use format `var'. This variable is meaningful only on VMS.");
- vms_stmlf_recfm = 0;
-
- DEFVAR_LISP ("directory-sep-char", &Vdirectory_sep_char,
- "Directory separator character for built-in functions that return file names.\n\
-The value should be either ?/ or ?\\ (any other value is treated as ?\\).\n\
-This variable affects the built-in functions only on Windows,\n\
-on other platforms, it is initialized so that Lisp code can find out\n\
-what the normal separator is.");
- Vdirectory_sep_char = '/';
-
- DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
- "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
-If a file name matches REGEXP, then all I/O on that file is done by calling\n\
-HANDLER.\n\
-\n\
-The first argument given to HANDLER is the name of the I/O primitive\n\
-to be handled; the remaining arguments are the arguments that were\n\
-passed to that primitive. For example, if you do\n\
- (file-exists-p FILENAME)\n\
-and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
- (funcall HANDLER 'file-exists-p FILENAME)\n\
-The function `find-file-name-handler' checks this list for a handler\n\
-for its argument.");
- Vfile_name_handler_alist = Qnil;
-
- DEFVAR_LISP ("after-insert-file-functions", &Vafter_insert_file_functions,
- "A list of functions to be called at the end of `insert-file-contents'.\n\
-Each is passed one argument, the number of bytes inserted. It should return\n\
-the new byte count, and leave point the same. If `insert-file-contents' is\n\
-intercepted by a handler from `file-name-handler-alist', that handler is\n\
-responsible for calling the after-insert-file-functions if appropriate.");
- Vafter_insert_file_functions = Qnil;
-
- DEFVAR_LISP ("write-region-annotate-functions", &Vwrite_region_annotate_functions,
- "A list of functions to be called at the start of `write-region'.\n\
-Each is passed two arguments, START and END as for `write-region'.\n\
-These are usually two numbers but not always; see the documentation\n\
-for `write-region'. The function should return a list of pairs\n\
-of the form (POSITION . STRING), consisting of strings to be effectively\n\
-inserted at the specified positions of the file being written (1 means to\n\
-insert before the first byte written). The POSITIONs must be sorted into\n\
-increasing order. If there are several functions in the list, the several\n\
-lists are merged destructively.");
- Vwrite_region_annotate_functions = Qnil;
-
- DEFVAR_LISP ("write-region-annotations-so-far",
- &Vwrite_region_annotations_so_far,
- "When an annotation function is called, this holds the previous annotations.\n\
-These are the annotations made by other annotation functions\n\
-that were already called. See also `write-region-annotate-functions'.");
- Vwrite_region_annotations_so_far = Qnil;
-
- DEFVAR_LISP ("inhibit-file-name-handlers", &Vinhibit_file_name_handlers,
- "A list of file name handlers that temporarily should not be used.\n\
-This applies only to the operation `inhibit-file-name-operation'.");
- Vinhibit_file_name_handlers = Qnil;
-
- DEFVAR_LISP ("inhibit-file-name-operation", &Vinhibit_file_name_operation,
- "The operation for which `inhibit-file-name-handlers' is applicable.");
- Vinhibit_file_name_operation = Qnil;
-
- DEFVAR_LISP ("auto-save-list-file-name", &Vauto_save_list_file_name,
- "File name in which we write a list of all auto save file names.\n\
-This variable is initialized automatically from `auto-save-list-file-prefix'\n\
-shortly after Emacs reads your `.emacs' file, if you have not yet given it\n\
-a non-nil value.");
- Vauto_save_list_file_name = Qnil;
-
- defsubr (&Sfind_file_name_handler);
- defsubr (&Sfile_name_directory);
- defsubr (&Sfile_name_nondirectory);
- defsubr (&Sunhandled_file_name_directory);
- defsubr (&Sfile_name_as_directory);
- defsubr (&Sdirectory_file_name);
- defsubr (&Smake_temp_name);
- defsubr (&Sexpand_file_name);
- defsubr (&Ssubstitute_in_file_name);
- defsubr (&Scopy_file);
- defsubr (&Smake_directory_internal);
- defsubr (&Sdelete_directory);
- defsubr (&Sdelete_file);
- defsubr (&Srename_file);
- defsubr (&Sadd_name_to_file);
-#ifdef S_IFLNK
- defsubr (&Smake_symbolic_link);
-#endif /* S_IFLNK */
-#ifdef VMS
- defsubr (&Sdefine_logical_name);
-#endif /* VMS */
-#ifdef HPUX_NET
- defsubr (&Ssysnetunam);
-#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 (&Saccess_file);
- defsubr (&Sfile_symlink_p);
- defsubr (&Sfile_directory_p);
- defsubr (&Sfile_accessible_directory_p);
- defsubr (&Sfile_regular_p);
- defsubr (&Sfile_modes);
- defsubr (&Sset_file_modes);
- defsubr (&Sset_default_file_modes);
- defsubr (&Sdefault_file_modes);
- defsubr (&Sfile_newer_than_file_p);
- defsubr (&Sinsert_file_contents);
- defsubr (&Swrite_region);
- defsubr (&Scar_less_than_car);
- defsubr (&Sverify_visited_file_modtime);
- defsubr (&Sclear_visited_file_modtime);
- defsubr (&Svisited_file_modtime);
- defsubr (&Sset_visited_file_modtime);
- defsubr (&Sdo_auto_save);
- defsubr (&Sset_buffer_auto_saved);
- defsubr (&Sclear_buffer_auto_save_failure);
- defsubr (&Srecent_auto_save_p);
-
- defsubr (&Sread_file_name_internal);
- defsubr (&Sread_file_name);
-
-#ifdef unix
- defsubr (&Sunix_sync);
-#endif
-}
diff --git a/src/filelock.c b/src/filelock.c
deleted file mode 100644
index 25ab59eb25b..00000000000
--- a/src/filelock.c
+++ /dev/null
@@ -1,488 +0,0 @@
-/* Copyright (C) 1985, 86, 87, 93, 94, 96 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <config.h>
-
-#ifdef VMS
-#include "vms-pwd.h"
-#else
-#include <pwd.h>
-#endif /* not VMS */
-
-#include <sys/file.h>
-#ifdef USG
-#include <fcntl.h>
-#include <string.h>
-#endif /* USG */
-
-#include "lisp.h"
-#include "buffer.h"
-
-#include <errno.h>
-#ifndef errno
-extern int errno;
-#endif
-
-#ifdef CLASH_DETECTION
-
-/* The strategy: to lock a file FN, create a symlink .#FN in FN's
- directory, with link data `user@host.pid'. This avoids a single
- mount (== failure) point for lock files.
-
- When the host in the lock data is the current host, we can check if
- the pid is valid with kill.
-
- Otherwise, we could look at a separate file that maps hostnames to
- reboot times to see if the remote pid can possibly be valid, since we
- don't want Emacs to have to communicate via pipes or sockets or
- whatever to other processes, either locally or remotely; rms says
- that's too unreliable. Hence the separate file, which could
- theoretically be updated by daemons running separately -- but this
- whole idea is unimplemented; in practice, at least in our
- environment, it seems such stale locks arise fiarly infrequently, and
- Emacs' standard methods of dealing with clashes suffice.
-
- We use symlinks instead of normal files because (1) they can be
- stored more efficiently on the filesystem, since the kernel knows
- they will be small, and (2) all the info about the lock can be read
- in a single system call (readlink). Although we could use regular
- files to be useful on old systems lacking symlinks, noawdays
- virtually all such systems are probably single-user anyway, so it
- didn't seem worth the complication.
-
- Similarly, we don't worry about a possible 14-character limit on
- file names, because those are all the same systems that don't have
- symlinks.
-
- This is compatible with the locking scheme used by Interleaf (which
- has contributed this implementation for Emacs), and was designed by
- Ethan Jacobson, Kimbo Mundy, and others.
-
- --karl@cs.umb.edu/karl@hq.ileaf.com. */
-
-
-/* Here is the structure that stores information about a lock. */
-
-typedef struct
-{
- char *user;
- char *host;
- unsigned long pid;
-} lock_info_type;
-
-/* When we read the info back, we might need this much more. */
-#define LOCK_PID_MAX 21 /* enough for signed 64 bits plus null */
-
-/* Free the two dynamically-allocated pieces in PTR. */
-#define FREE_LOCK_INFO(i) do { xfree ((i).user); xfree ((i).host); } while (0)
-
-
-/* Write the name of the lock file for FN into LFNAME. Length will be
- that of FN plus two more for the leading `.#' plus one for the null. */
-#define MAKE_LOCK_NAME(lock, file) \
- (lock = (char *) alloca (XSTRING (file)->size + 2 + 1), \
- fill_in_lock_file_name (lock, (file)))
-
-static void
-fill_in_lock_file_name (lockfile, fn)
- register char *lockfile;
- register Lisp_Object fn;
-{
- register char *p;
-
- strcpy (lockfile, XSTRING (fn)->data);
-
- /* Shift the nondirectory part of the file name (including the null)
- right two characters. Here is one of the places where we'd have to
- do something to support 14-character-max file names. */
- for (p = lockfile + strlen (lockfile); p != lockfile && *p != '/'; p--)
- p[2] = *p;
-
- /* Insert the `.#'. */
- p[1] = '.';
- p[2] = '#';
-}
-
-/* Lock the lock file named LFNAME.
- If FORCE is nonzero, we do so even if it is already locked.
- Return 1 if successful, 0 if not. */
-
-static int
-lock_file_1 (lfname, force)
- char *lfname;
- int force;
-{
- register int err;
- char *user_name = XSTRING (Fuser_login_name (Qnil))->data;
- char *host_name = XSTRING (Fsystem_name ())->data;
- char *lock_info_str = alloca (strlen (user_name) + strlen (host_name) + 21);
-
- sprintf (lock_info_str, "%s@%s.%lu", user_name, host_name,
- (unsigned long) getpid ());
-
- err = symlink (lock_info_str, lfname);
- if (errno == EEXIST && force)
- {
- unlink (lfname);
- err = symlink (lock_info_str, lfname);
- }
-
- return err == 0;
-}
-
-
-
-/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete,
- 1 if another process owns it (and set OWNER (if non-null) to info),
- 2 if the current process owns it,
- or -1 if something is wrong with the locking mechanism. */
-
-static int
-current_lock_owner (owner, lfname)
- lock_info_type *owner;
- char *lfname;
-{
-#ifndef index
- extern char *rindex (), *index ();
-#endif
- int o, p, len, ret;
- int local_owner = 0;
- char *at, *dot;
- char *lfinfo = 0;
- int bufsize = 50;
- /* Read arbitrarily-long contents of symlink. Similar code in
- file-symlink-p in fileio.c. */
- do
- {
- bufsize *= 2;
- lfinfo = (char *) xrealloc (lfinfo, bufsize);
- len = readlink (lfname, lfinfo, bufsize);
- }
- while (len >= bufsize);
-
- /* If nonexistent lock file, all is well; otherwise, got strange error. */
- if (len == -1)
- {
- xfree (lfinfo);
- return errno == ENOENT ? 0 : -1;
- }
-
- /* Link info exists, so `len' is its length. Null terminate. */
- lfinfo[len] = 0;
-
- /* Even if the caller doesn't want the owner info, we still have to
- read it to determine return value, so allocate it. */
- if (!owner)
- {
- owner = alloca (sizeof (lock_info_type));
- local_owner = 1;
- }
-
- /* Parse USER@HOST.PID. If can't parse, return -1. */
- /* The USER is everything before the first @. */
- at = index (lfinfo, '@');
- dot = rindex (lfinfo, '.');
- if (!at || !dot) {
- xfree (lfinfo);
- return -1;
- }
- len = at - lfinfo;
- owner->user = (char *) xmalloc (len + 1);
- strncpy (owner->user, lfinfo, len);
- owner->user[len] = 0;
-
- /* The PID is everything after the last `.'. */
- owner->pid = atoi (dot + 1);
-
- /* The host is everything in between. */
- len = dot - at - 1;
- owner->host = (char *) xmalloc (len + 1);
- strncpy (owner->host, at + 1, len);
- owner->host[len] = 0;
-
- /* We're done looking at the link info. */
- xfree (lfinfo);
-
- /* On current host? */
- if (strcmp (owner->host, XSTRING (Fsystem_name ())->data) == 0)
- {
- if (owner->pid == getpid ())
- ret = 2; /* We own it. */
-
- if (owner->pid > 0
- && (kill (owner->pid, 0) >= 0 || errno == EPERM))
- ret = 1; /* An existing process on this machine owns it. */
-
- /* The owner process is dead or has a strange pid (<=0), so try to
- zap the lockfile. */
- if (unlink (lfname) < 0)
- ret = -1;
-
- ret = 0;
- }
- else
- { /* If we wanted to support the check for stale locks on remote machines,
- here's where we'd do it. */
- ret = 1;
- }
-
- /* Avoid garbage. */
- if (local_owner || ret <= 0)
- {
- FREE_LOCK_INFO (*owner);
- }
- return ret;
-}
-
-
-/* Lock the lock named LFNAME if possible.
- Return 0 in that case.
- Return positive if some other process owns the lock, and info about
- that process in CLASHER.
- Return -1 if cannot lock for any other reason. */
-
-static int
-lock_if_free (clasher, lfname)
- lock_info_type *clasher;
- register char *lfname;
-{
- while (lock_file_1 (lfname, 0) == 0)
- {
- int locker;
-
- if (errno != EEXIST)
- return -1;
-
- locker = current_lock_owner (clasher, lfname);
- if (locker == 2)
- {
- FREE_LOCK_INFO (*clasher);
- return 0; /* We ourselves locked it. */
- }
- else if (locker == 1)
- return 1; /* Someone else has it. */
- else if (locker == -1)
- return -1; /* Something's wrong. */
-
- /* If some other error, or no such lock, try to lock again. */
- /* Is there a case where we loop forever? */
- }
- return 0;
-}
-
-/* lock_file locks file FN,
- meaning it serves notice on the world that you intend to edit that file.
- This should be done only when about to modify a file-visiting
- buffer previously unmodified.
- Do not (normally) call this for a buffer already modified,
- as either the file is already locked, or the user has already
- decided to go ahead without locking.
-
- When this returns, either the lock is locked for us,
- or the user has said to go ahead without locking.
-
- If the file is locked by someone else, this calls
- ask-user-about-lock (a Lisp function) with two arguments,
- the file name and info about the user who did the locking.
- This function can signal an error, or return t meaning
- take away the lock, or return nil meaning ignore the lock. */
-
-void
-lock_file (fn)
- register Lisp_Object fn;
-{
- register Lisp_Object attack, orig_fn;
- register char *lfname, *locker;
- lock_info_type lock_info;
-
- orig_fn = fn;
- fn = Fexpand_file_name (fn, Qnil);
-
- /* Create the name of the lock-file for file fn */
- MAKE_LOCK_NAME (lfname, fn);
-
- /* See if this file is visited and has changed on disk since it was
- visited. */
- {
- register Lisp_Object subject_buf;
- subject_buf = get_truename_buffer (orig_fn);
- if (!NILP (subject_buf)
- && NILP (Fverify_visited_file_modtime (subject_buf))
- && !NILP (Ffile_exists_p (fn)))
- call1 (intern ("ask-user-about-supersession-threat"), fn);
- }
-
- /* Try to lock the lock. */
- if (lock_if_free (&lock_info, lfname) <= 0)
- /* Return now if we have locked it, or if lock creation failed */
- return;
-
- /* Else consider breaking the lock */
- locker = alloca (strlen (lock_info.user) + strlen (lock_info.host)
- + LOCK_PID_MAX + 9);
- sprintf (locker, "%s@%s (pid %d)", lock_info.user, lock_info.host,
- lock_info.pid);
- FREE_LOCK_INFO (lock_info);
-
- attack = call2 (intern ("ask-user-about-lock"), fn, build_string (locker));
- if (!NILP (attack))
- /* User says take the lock */
- {
- lock_file_1 (lfname, 1);
- return;
- }
- /* User says ignore the lock */
-}
-
-void
-unlock_file (fn)
- register Lisp_Object fn;
-{
- register char *lfname;
-
- fn = Fexpand_file_name (fn, Qnil);
-
- MAKE_LOCK_NAME (lfname, fn);
-
- if (current_lock_owner (0, lfname) == 2)
- unlink (lfname);
-}
-
-void
-unlock_all_files ()
-{
- register Lisp_Object tail;
- register struct buffer *b;
-
- for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCONS (tail)->cdr)
- {
- b = XBUFFER (XCONS (XCONS (tail)->car)->cdr);
- if (STRINGP (b->file_truename) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b))
- unlock_file (b->file_truename);
- }
-}
-
-DEFUN ("lock-buffer", Flock_buffer, Slock_buffer,
- 0, 1, 0,
- "Lock 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.")
- (file)
- Lisp_Object file;
-{
- if (NILP (file))
- file = current_buffer->file_truename;
- else
- CHECK_STRING (file, 0);
- if (SAVE_MODIFF < MODIFF
- && !NILP (file))
- lock_file (file);
- return Qnil;
-}
-
-DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,
- 0, 0, 0,
- "Unlock the file visited in the current buffer,\n\
-if it should normally be locked.")
- ()
-{
- if (SAVE_MODIFF < MODIFF
- && STRINGP (current_buffer->file_truename))
- unlock_file (current_buffer->file_truename);
- return Qnil;
-}
-
-/* Unlock the file visited in buffer BUFFER. */
-
-unlock_buffer (buffer)
- struct buffer *buffer;
-{
- if (BUF_SAVE_MODIFF (buffer) < BUF_MODIFF (buffer)
- && STRINGP (buffer->file_truename))
- unlock_file (buffer->file_truename);
-}
-
-DEFUN ("file-locked-p", Ffile_locked_p, Sfile_locked_p, 0, 1, 0,
- "Return nil if the FILENAME is not locked,\n\
-t if it is locked by you, else a string of the name of the locker.")
- (filename)
- Lisp_Object filename;
-{
- Lisp_Object ret;
- register char *lfname;
- int owner;
- lock_info_type locker;
-
- filename = Fexpand_file_name (filename, Qnil);
-
- MAKE_LOCK_NAME (lfname, filename);
-
- owner = current_lock_owner (&locker, lfname);
- if (owner <= 0)
- ret = Qnil;
- else if (owner == 2)
- ret = Qt;
- else
- ret = build_string (locker.user);
-
- if (owner > 0)
- FREE_LOCK_INFO (locker);
-
- return ret;
-}
-
-
-/* Initialization functions. */
-
-init_filelock ()
-{
-#if 0
- char *new_name;
-
- lock_dir = egetenv ("EMACSLOCKDIR");
- if (! lock_dir)
- lock_dir = PATH_LOCK;
-
- /* Copy the name in case egetenv got it from a Lisp string. */
- new_name = (char *) xmalloc (strlen (lock_dir) + 2);
- strcpy (new_name, lock_dir);
- lock_dir = new_name;
-
- /* Make sure it ends with a slash. */
- if (lock_dir[strlen (lock_dir) - 1] != '/')
- strcat (lock_dir, "/");
-
- superlock_file = (char *) xmalloc ((strlen (lock_dir)
- + sizeof (SUPERLOCK_NAME)));
- strcpy (superlock_file, lock_dir);
- strcat (superlock_file, SUPERLOCK_NAME);
-#endif
-}
-
-syms_of_filelock ()
-{
- defsubr (&Sunlock_buffer);
- defsubr (&Slock_buffer);
- defsubr (&Sfile_locked_p);
-}
-
-#endif /* CLASH_DETECTION */
diff --git a/src/floatfns.c b/src/floatfns.c
deleted file mode 100644
index 452bdc2ea54..00000000000
--- a/src/floatfns.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/* Primitive operations on floating point for GNU Emacs Lisp interpreter.
- Copyright (C) 1988, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* ANSI C requires only these float functions:
- acos, asin, atan, atan2, ceil, cos, cosh, exp, fabs, floor, fmod,
- frexp, ldexp, log, log10, modf, pow, sin, sinh, sqrt, tan, tanh.
-
- Define HAVE_INVERSE_HYPERBOLIC if you have acosh, asinh, and atanh.
- Define HAVE_CBRT if you have cbrt.
- Define HAVE_RINT if you have rint.
- If you don't define these, then the appropriate routines will be simulated.
-
- Define HAVE_MATHERR if on a system supporting the SysV matherr callback.
- (This should happen automatically.)
-
- Define FLOAT_CHECK_ERRNO if the float library routines set errno.
- This has no effect if HAVE_MATHERR is defined.
-
- Define FLOAT_CATCH_SIGILL if the float library routines signal SIGILL.
- (What systems actually do this? Please let us know.)
-
- Define FLOAT_CHECK_DOMAIN if the float library doesn't handle errors by
- either setting errno, or signaling SIGFPE/SIGILL. Otherwise, domain and
- range checking will happen before calling the float routines. This has
- no effect if HAVE_MATHERR is defined (since matherr will be called when
- a domain error occurs.)
- */
-
-#include <signal.h>
-
-#include <config.h>
-#include "lisp.h"
-#include "syssignal.h"
-
-#ifdef LISP_FLOAT_TYPE
-
-#if STDC_HEADERS
-#include <float.h>
-#endif
-
-/* If IEEE_FLOATING_POINT isn't defined, default it from FLT_*. */
-#ifndef IEEE_FLOATING_POINT
-#if (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
- && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
-#define IEEE_FLOATING_POINT 1
-#else
-#define IEEE_FLOATING_POINT 0
-#endif
-#endif
-
-/* Work around a problem that happens because math.h on hpux 7
- defines two static variables--which, in Emacs, are not really static,
- because `static' is defined as nothing. The problem is that they are
- defined both here and in lread.c.
- These macros prevent the name conflict. */
-#if defined (HPUX) && !defined (HPUX8)
-#define _MAXLDBL floatfns_maxldbl
-#define _NMAXLDBL floatfns_nmaxldbl
-#endif
-
-#include <math.h>
-
-/* This declaration is omitted on some systems, like Ultrix. */
-#if !defined (HPUX) && defined (HAVE_LOGB) && !defined (logb)
-extern double logb ();
-#endif /* not HPUX and HAVE_LOGB and no logb macro */
-
-#if defined(DOMAIN) && defined(SING) && defined(OVERFLOW)
- /* If those are defined, then this is probably a `matherr' machine. */
-# ifndef HAVE_MATHERR
-# define HAVE_MATHERR
-# endif
-#endif
-
-#ifdef NO_MATHERR
-#undef HAVE_MATHERR
-#endif
-
-#ifdef HAVE_MATHERR
-# ifdef FLOAT_CHECK_ERRNO
-# undef FLOAT_CHECK_ERRNO
-# endif
-# ifdef FLOAT_CHECK_DOMAIN
-# undef FLOAT_CHECK_DOMAIN
-# endif
-#endif
-
-#ifndef NO_FLOAT_CHECK_ERRNO
-#define FLOAT_CHECK_ERRNO
-#endif
-
-#ifdef FLOAT_CHECK_ERRNO
-# include <errno.h>
-
-extern int errno;
-#endif
-
-/* Avoid traps on VMS from sinh and cosh.
- All the other functions set errno instead. */
-
-#ifdef VMS
-#undef cosh
-#undef sinh
-#define cosh(x) ((exp(x)+exp(-x))*0.5)
-#define sinh(x) ((exp(x)-exp(-x))*0.5)
-#endif /* VMS */
-
-#ifndef HAVE_RINT
-#define rint(x) (floor((x)+0.5))
-#endif
-
-static SIGTYPE float_error ();
-
-/* 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,
- here is the actual argument value to use in the error message.
- These variables are used only across the floating point library call
- so there is no need to staticpro them. */
-
-static Lisp_Object float_error_arg, float_error_arg2;
-
-static char *float_error_fn_name;
-
-/* Evaluate the floating point expression D, recording NUM
- as the original argument for error messages.
- D is normally an assignment expression.
- Handle errors which may result in signals or may set errno.
-
- Note that float_error may be declared to return void, so you can't
- just cast the zero after the colon to (SIGTYPE) to make the types
- check properly. */
-
-#ifdef FLOAT_CHECK_ERRNO
-#define IN_FLOAT(d, name, num) \
- do { \
- float_error_arg = num; \
- float_error_fn_name = name; \
- in_float = 1; errno = 0; (d); in_float = 0; \
- switch (errno) { \
- case 0: break; \
- case EDOM: domain_error (float_error_fn_name, float_error_arg); \
- case ERANGE: range_error (float_error_fn_name, float_error_arg); \
- default: arith_error (float_error_fn_name, float_error_arg); \
- } \
- } while (0)
-#define IN_FLOAT2(d, name, num, num2) \
- do { \
- float_error_arg = num; \
- float_error_arg2 = num2; \
- float_error_fn_name = name; \
- in_float = 1; errno = 0; (d); in_float = 0; \
- switch (errno) { \
- case 0: break; \
- case EDOM: domain_error (float_error_fn_name, float_error_arg); \
- case ERANGE: range_error (float_error_fn_name, float_error_arg); \
- default: arith_error (float_error_fn_name, float_error_arg); \
- } \
- } while (0)
-#else
-#define IN_FLOAT(d, name, num) (in_float = 1, (d), in_float = 0)
-#define IN_FLOAT2(d, name, num, num2) (in_float = 1, (d), in_float = 0)
-#endif
-
-/* Convert float to Lisp_Int if it fits, else signal a range error
- using the given arguments. */
-#define FLOAT_TO_INT(x, i, name, num) \
- do \
- { \
- if ((x) >= (((EMACS_INT) 1) << (VALBITS-1)) || \
- (x) <= - (((EMACS_INT) 1) << (VALBITS-1)) - 1) \
- range_error (name, num); \
- XSETINT (i, (EMACS_INT)(x)); \
- } \
- while (0)
-#define FLOAT_TO_INT2(x, i, name, num1, num2) \
- do \
- { \
- if ((x) >= (((EMACS_INT) 1) << (VALBITS-1)) || \
- (x) <= - (((EMACS_INT) 1) << (VALBITS-1)) - 1) \
- range_error2 (name, num1, num2); \
- XSETINT (i, (EMACS_INT)(x)); \
- } \
- while (0)
-
-#define arith_error(op,arg) \
- Fsignal (Qarith_error, Fcons (build_string ((op)), Fcons ((arg), Qnil)))
-#define range_error(op,arg) \
- Fsignal (Qrange_error, Fcons (build_string ((op)), Fcons ((arg), Qnil)))
-#define range_error2(op,a1,a2) \
- Fsignal (Qrange_error, Fcons (build_string ((op)), \
- Fcons ((a1), Fcons ((a2), Qnil))))
-#define domain_error(op,arg) \
- Fsignal (Qdomain_error, Fcons (build_string ((op)), Fcons ((arg), Qnil)))
-#define domain_error2(op,a1,a2) \
- Fsignal (Qdomain_error, Fcons (build_string ((op)), \
- Fcons ((a1), Fcons ((a2), Qnil))))
-
-/* 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 (FLOATP (num))
- return XFLOAT (num)->data;
- return (double) XINT (num);
-}
-
-/* Trig functions. */
-
-DEFUN ("acos", Facos, Sacos, 1, 1, 0,
- "Return the inverse cosine of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d > 1.0 || d < -1.0)
- domain_error ("acos", arg);
-#endif
- IN_FLOAT (d = acos (d), "acos", arg);
- return make_float (d);
-}
-
-DEFUN ("asin", Fasin, Sasin, 1, 1, 0,
- "Return the inverse sine of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d > 1.0 || d < -1.0)
- domain_error ("asin", arg);
-#endif
- IN_FLOAT (d = asin (d), "asin", arg);
- return make_float (d);
-}
-
-DEFUN ("atan", Fatan, Satan, 1, 1, 0,
- "Return the inverse tangent of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = atan (d), "atan", arg);
- return make_float (d);
-}
-
-DEFUN ("cos", Fcos, Scos, 1, 1, 0,
- "Return the cosine of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = cos (d), "cos", arg);
- return make_float (d);
-}
-
-DEFUN ("sin", Fsin, Ssin, 1, 1, 0,
- "Return the sine of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = sin (d), "sin", arg);
- return make_float (d);
-}
-
-DEFUN ("tan", Ftan, Stan, 1, 1, 0,
- "Return the tangent of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- double c = cos (d);
-#ifdef FLOAT_CHECK_DOMAIN
- if (c == 0.0)
- domain_error ("tan", arg);
-#endif
- IN_FLOAT (d = sin (d) / c, "tan", arg);
- return make_float (d);
-}
-
-#if 0 /* Leave these out unless we find there's a reason for them. */
-
-DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0,
- "Return the bessel function j0 of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = j0 (d), "bessel-j0", arg);
- return make_float (d);
-}
-
-DEFUN ("bessel-j1", Fbessel_j1, Sbessel_j1, 1, 1, 0,
- "Return the bessel function j1 of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = j1 (d), "bessel-j1", arg);
- 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.")
- (n, arg)
- register Lisp_Object n, arg;
-{
- int i1 = extract_float (n);
- double f2 = extract_float (arg);
-
- IN_FLOAT (f2 = jn (i1, f2), "bessel-jn", n);
- return make_float (f2);
-}
-
-DEFUN ("bessel-y0", Fbessel_y0, Sbessel_y0, 1, 1, 0,
- "Return the bessel function y0 of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = y0 (d), "bessel-y0", arg);
- return make_float (d);
-}
-
-DEFUN ("bessel-y1", Fbessel_y1, Sbessel_y1, 1, 1, 0,
- "Return the bessel function y1 of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = y1 (d), "bessel-y0", arg);
- 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.")
- (n, arg)
- register Lisp_Object n, arg;
-{
- int i1 = extract_float (n);
- double f2 = extract_float (arg);
-
- IN_FLOAT (f2 = yn (i1, f2), "bessel-yn", n);
- return make_float (f2);
-}
-
-#endif
-
-#if 0 /* Leave these out unless we see they are worth having. */
-
-DEFUN ("erf", Ferf, Serf, 1, 1, 0,
- "Return the mathematical error function of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = erf (d), "erf", arg);
- return make_float (d);
-}
-
-DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0,
- "Return the complementary error function of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = erfc (d), "erfc", arg);
- return make_float (d);
-}
-
-DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0,
- "Return the log gamma of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = lgamma (d), "log-gamma", arg);
- return make_float (d);
-}
-
-DEFUN ("cube-root", Fcube_root, Scube_root, 1, 1, 0,
- "Return the cube root of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
-#ifdef HAVE_CBRT
- IN_FLOAT (d = cbrt (d), "cube-root", arg);
-#else
- if (d >= 0.0)
- IN_FLOAT (d = pow (d, 1.0/3.0), "cube-root", arg);
- else
- IN_FLOAT (d = -pow (-d, 1.0/3.0), "cube-root", arg);
-#endif
- return make_float (d);
-}
-
-#endif
-
-DEFUN ("exp", Fexp, Sexp, 1, 1, 0,
- "Return the exponential base e of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d > 709.7827) /* Assume IEEE doubles here */
- range_error ("exp", arg);
- else if (d < -709.0)
- return make_float (0.0);
- else
-#endif
- IN_FLOAT (d = exp (d), "exp", arg);
- return make_float (d);
-}
-
-DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
- "Return the exponential ARG1 ** ARG2.")
- (arg1, arg2)
- register Lisp_Object arg1, arg2;
-{
- double f1, f2;
-
- CHECK_NUMBER_OR_FLOAT (arg1, 0);
- CHECK_NUMBER_OR_FLOAT (arg2, 0);
- if (INTEGERP (arg1) /* common lisp spec */
- && INTEGERP (arg2)) /* don't promote, if both are ints */
- { /* this can be improved by pre-calculating */
- EMACS_INT acc, x, y; /* some binary powers of x then accumulating */
- Lisp_Object val;
-
- x = XINT (arg1);
- y = XINT (arg2);
- acc = 1;
-
- if (y < 0)
- {
- if (x == 1)
- acc = 1;
- else if (x == -1)
- acc = (y & 1) ? -1 : 1;
- else
- acc = 0;
- }
- else
- {
- while (y > 0)
- {
- if (y & 1)
- acc *= x;
- x *= x;
- y = (unsigned)y >> 1;
- }
- }
- XSETINT (val, acc);
- return val;
- }
- f1 = FLOATP (arg1) ? XFLOAT (arg1)->data : XINT (arg1);
- f2 = FLOATP (arg2) ? XFLOAT (arg2)->data : XINT (arg2);
- /* Really should check for overflow, too */
- if (f1 == 0.0 && f2 == 0.0)
- f1 = 1.0;
-#ifdef FLOAT_CHECK_DOMAIN
- else if ((f1 == 0.0 && f2 < 0.0) || (f1 < 0 && f2 != floor(f2)))
- domain_error2 ("expt", arg1, arg2);
-#endif
- IN_FLOAT2 (f1 = pow (f1, f2), "expt", arg1, arg2);
- return make_float (f1);
-}
-
-DEFUN ("log", Flog, Slog, 1, 2, 0,
- "Return the natural logarithm of ARG.\n\
-If second optional argument BASE is given, return log ARG using that base.")
- (arg, base)
- register Lisp_Object arg, base;
-{
- double d = extract_float (arg);
-
-#ifdef FLOAT_CHECK_DOMAIN
- if (d <= 0.0)
- domain_error2 ("log", arg, base);
-#endif
- if (NILP (base))
- IN_FLOAT (d = log (d), "log", arg);
- else
- {
- double b = extract_float (base);
-
-#ifdef FLOAT_CHECK_DOMAIN
- if (b <= 0.0 || b == 1.0)
- domain_error2 ("log", arg, base);
-#endif
- if (b == 10.0)
- IN_FLOAT2 (d = log10 (d), "log", arg, base);
- else
- IN_FLOAT2 (d = log (d) / log (b), "log", arg, base);
- }
- return make_float (d);
-}
-
-DEFUN ("log10", Flog10, Slog10, 1, 1, 0,
- "Return the logarithm base 10 of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d <= 0.0)
- domain_error ("log10", arg);
-#endif
- IN_FLOAT (d = log10 (d), "log10", arg);
- return make_float (d);
-}
-
-DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0,
- "Return the square root of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d < 0.0)
- domain_error ("sqrt", arg);
-#endif
- IN_FLOAT (d = sqrt (d), "sqrt", arg);
- return make_float (d);
-}
-
-#if 0 /* Not clearly worth adding. */
-
-DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0,
- "Return the inverse hyperbolic cosine of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d < 1.0)
- domain_error ("acosh", arg);
-#endif
-#ifdef HAVE_INVERSE_HYPERBOLIC
- IN_FLOAT (d = acosh (d), "acosh", arg);
-#else
- IN_FLOAT (d = log (d + sqrt (d*d - 1.0)), "acosh", arg);
-#endif
- return make_float (d);
-}
-
-DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0,
- "Return the inverse hyperbolic sine of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
-#ifdef HAVE_INVERSE_HYPERBOLIC
- IN_FLOAT (d = asinh (d), "asinh", arg);
-#else
- IN_FLOAT (d = log (d + sqrt (d*d + 1.0)), "asinh", arg);
-#endif
- return make_float (d);
-}
-
-DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0,
- "Return the inverse hyperbolic tangent of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d >= 1.0 || d <= -1.0)
- domain_error ("atanh", arg);
-#endif
-#ifdef HAVE_INVERSE_HYPERBOLIC
- IN_FLOAT (d = atanh (d), "atanh", arg);
-#else
- IN_FLOAT (d = 0.5 * log ((1.0 + d) / (1.0 - d)), "atanh", arg);
-#endif
- return make_float (d);
-}
-
-DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0,
- "Return the hyperbolic cosine of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d > 710.0 || d < -710.0)
- range_error ("cosh", arg);
-#endif
- IN_FLOAT (d = cosh (d), "cosh", arg);
- return make_float (d);
-}
-
-DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0,
- "Return the hyperbolic sine of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d > 710.0 || d < -710.0)
- range_error ("sinh", arg);
-#endif
- IN_FLOAT (d = sinh (d), "sinh", arg);
- return make_float (d);
-}
-
-DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0,
- "Return the hyperbolic tangent of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = tanh (d), "tanh", arg);
- return make_float (d);
-}
-#endif
-
-DEFUN ("abs", Fabs, Sabs, 1, 1, 0,
- "Return the absolute value of ARG.")
- (arg)
- register Lisp_Object arg;
-{
- CHECK_NUMBER_OR_FLOAT (arg, 0);
-
- if (FLOATP (arg))
- IN_FLOAT (arg = make_float (fabs (XFLOAT (arg)->data)), "abs", arg);
- else if (XINT (arg) < 0)
- XSETINT (arg, - XINT (arg));
-
- return arg;
-}
-
-DEFUN ("float", Ffloat, Sfloat, 1, 1, 0,
- "Return the floating point number equal to ARG.")
- (arg)
- register Lisp_Object arg;
-{
- CHECK_NUMBER_OR_FLOAT (arg, 0);
-
- if (INTEGERP (arg))
- return make_float ((double) XINT (arg));
- else /* give 'em the same float back */
- return arg;
-}
-
-DEFUN ("logb", Flogb, Slogb, 1, 1, 0,
- "Returns largest integer <= the base 2 log of the magnitude of ARG.\n\
-This is the same as the exponent of a float.")
- (arg)
- Lisp_Object arg;
-{
- Lisp_Object val;
- EMACS_INT value;
- double f = extract_float (arg);
-
- if (f == 0.0)
- value = -(VALMASK >> 1);
- else
- {
-#ifdef HAVE_LOGB
- IN_FLOAT (value = logb (f), "logb", arg);
-#else
-#ifdef HAVE_FREXP
- int ivalue;
- IN_FLOAT (frexp (f, &ivalue), "logb", arg);
- value = ivalue - 1;
-#else
- int i;
- double d;
- if (f < 0.0)
- f = -f;
- value = -1;
- while (f < 0.5)
- {
- for (i = 1, d = 0.5; d * d >= f; i += i)
- d *= d;
- f /= d;
- value -= i;
- }
- while (f >= 1.0)
- {
- for (i = 1, d = 2.0; d * d <= f; i += i)
- d *= d;
- f /= d;
- value += i;
- }
-#endif
-#endif
- }
- XSETINT (val, value);
- return val;
-}
-
-/* the rounding functions */
-
-DEFUN ("ceiling", Fceiling, Sceiling, 1, 1, 0,
- "Return the smallest integer no less than ARG. (Round toward +inf.)")
- (arg)
- register Lisp_Object arg;
-{
- CHECK_NUMBER_OR_FLOAT (arg, 0);
-
- if (FLOATP (arg))
- {
- double d;
-
- IN_FLOAT (d = ceil (XFLOAT (arg)->data), "ceiling", arg);
- FLOAT_TO_INT (d, arg, "ceiling", arg);
- }
-
- return arg;
-}
-
-#endif /* LISP_FLOAT_TYPE */
-
-
-DEFUN ("floor", Ffloor, Sfloor, 1, 2, 0,
- "Return the largest integer no greater than ARG. (Round towards -inf.)\n\
-With optional DIVISOR, return the largest integer no greater than ARG/DIVISOR.")
- (arg, divisor)
- register Lisp_Object arg, divisor;
-{
- CHECK_NUMBER_OR_FLOAT (arg, 0);
-
- if (! NILP (divisor))
- {
- EMACS_INT i1, i2;
-
- CHECK_NUMBER_OR_FLOAT (divisor, 1);
-
-#ifdef LISP_FLOAT_TYPE
- if (FLOATP (arg) || FLOATP (divisor))
- {
- double f1, f2;
-
- f1 = FLOATP (arg) ? XFLOAT (arg)->data : XINT (arg);
- f2 = (FLOATP (divisor) ? XFLOAT (divisor)->data : XINT (divisor));
- if (! IEEE_FLOATING_POINT && f2 == 0)
- Fsignal (Qarith_error, Qnil);
-
- IN_FLOAT2 (f1 = floor (f1 / f2), "floor", arg, divisor);
- FLOAT_TO_INT2 (f1, arg, "floor", arg, divisor);
- return arg;
- }
-#endif
-
- i1 = XINT (arg);
- i2 = XINT (divisor);
-
- if (i2 == 0)
- Fsignal (Qarith_error, Qnil);
-
- /* With C's /, the result is implementation-defined if either operand
- is negative, so use only nonnegative operands. */
- i1 = (i2 < 0
- ? (i1 <= 0 ? -i1 / -i2 : -1 - ((i1 - 1) / -i2))
- : (i1 < 0 ? -1 - ((-1 - i1) / i2) : i1 / i2));
-
- XSETINT (arg, i1);
- return arg;
- }
-
-#ifdef LISP_FLOAT_TYPE
- if (FLOATP (arg))
- {
- double d;
- IN_FLOAT (d = floor (XFLOAT (arg)->data), "floor", arg);
- FLOAT_TO_INT (d, arg, "floor", arg);
- }
-#endif
-
- return arg;
-}
-
-#ifdef LISP_FLOAT_TYPE
-
-Lisp_Object
-fmod_float (x, y)
- register Lisp_Object x, y;
-{
- double f1, f2;
-
- f1 = FLOATP (x) ? XFLOAT (x)->data : XINT (x);
- f2 = FLOATP (y) ? XFLOAT (y)->data : XINT (y);
-
- if (! IEEE_FLOATING_POINT && f2 == 0)
- Fsignal (Qarith_error, Qnil);
-
- /* If the "remainder" comes out with the wrong sign, fix it. */
- IN_FLOAT2 ((f1 = fmod (f1, f2),
- f1 = (f2 < 0 ? f1 > 0 : f1 < 0) ? f1 + f2 : f1),
- "mod", x, y);
- return make_float (f1);
-}
-
-DEFUN ("round", Fround, Sround, 1, 1, 0,
- "Return the nearest integer to ARG.")
- (arg)
- register Lisp_Object arg;
-{
- CHECK_NUMBER_OR_FLOAT (arg, 0);
-
- if (FLOATP (arg))
- {
- double d;
-
- /* Screw the prevailing rounding mode. */
- IN_FLOAT (d = rint (XFLOAT (arg)->data), "round", arg);
- FLOAT_TO_INT (d, arg, "round", arg);
- }
-
- return arg;
-}
-
-DEFUN ("truncate", Ftruncate, Struncate, 1, 1, 0,
- "Truncate a floating point number to an int.\n\
-Rounds the value toward zero.")
- (arg)
- register Lisp_Object arg;
-{
- CHECK_NUMBER_OR_FLOAT (arg, 0);
-
- if (FLOATP (arg))
- {
- double d;
-
- d = XFLOAT (arg)->data;
- FLOAT_TO_INT (d, arg, "truncate", arg);
- }
-
- return arg;
-}
-
-/* It's not clear these are worth adding. */
-
-DEFUN ("fceiling", Ffceiling, Sfceiling, 1, 1, 0,
- "Return the smallest integer no less than ARG, as a float.\n\
-\(Round toward +inf.\)")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = ceil (d), "fceiling", arg);
- return make_float (d);
-}
-
-DEFUN ("ffloor", Fffloor, Sffloor, 1, 1, 0,
- "Return the largest integer no greater than ARG, as a float.\n\
-\(Round towards -inf.\)")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = floor (d), "ffloor", arg);
- return make_float (d);
-}
-
-DEFUN ("fround", Ffround, Sfround, 1, 1, 0,
- "Return the nearest integer to ARG, as a float.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- IN_FLOAT (d = rint (d), "fround", arg);
- return make_float (d);
-}
-
-DEFUN ("ftruncate", Fftruncate, Sftruncate, 1, 1, 0,
- "Truncate a floating point number to an integral float value.\n\
-Rounds the value toward zero.")
- (arg)
- register Lisp_Object arg;
-{
- double d = extract_float (arg);
- if (d >= 0.0)
- IN_FLOAT (d = floor (d), "ftruncate", arg);
- else
- IN_FLOAT (d = ceil (d), "ftruncate", arg);
- return make_float (d);
-}
-
-#ifdef FLOAT_CATCH_SIGILL
-static SIGTYPE
-float_error (signo)
- int signo;
-{
- if (! in_float)
- fatal_error_signal (signo);
-
-#ifdef BSD_SYSTEM
-#ifdef BSD4_1
- sigrelse (SIGILL);
-#else /* not BSD4_1 */
- sigsetmask (SIGEMPTYMASK);
-#endif /* not BSD4_1 */
-#else
- /* Must reestablish handler each time it is called. */
- signal (SIGILL, float_error);
-#endif /* BSD_SYSTEM */
-
- 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 /* FLOAT_CATCH_SIGILL */
-
-#ifdef HAVE_MATHERR
-int
-matherr (x)
- struct exception *x;
-{
- Lisp_Object args;
- if (! in_float)
- /* Not called from emacs-lisp float routines; do the default thing. */
- return 0;
- if (!strcmp (x->name, "pow"))
- x->name = "expt";
-
- args
- = Fcons (build_string (x->name),
- Fcons (make_float (x->arg1),
- ((!strcmp (x->name, "log") || !strcmp (x->name, "pow"))
- ? Fcons (make_float (x->arg2), Qnil)
- : Qnil)));
- switch (x->type)
- {
- case DOMAIN: Fsignal (Qdomain_error, args); break;
- case SING: Fsignal (Qsingularity_error, args); break;
- case OVERFLOW: Fsignal (Qoverflow_error, args); break;
- case UNDERFLOW: Fsignal (Qunderflow_error, args); break;
- default: Fsignal (Qarith_error, args); break;
- }
- return (1); /* don't set errno or print a message */
-}
-#endif /* HAVE_MATHERR */
-
-init_floatfns ()
-{
-#ifdef FLOAT_CATCH_SIGILL
- signal (SIGILL, float_error);
-#endif
- in_float = 0;
-}
-
-#else /* not LISP_FLOAT_TYPE */
-
-init_floatfns ()
-{}
-
-#endif /* not LISP_FLOAT_TYPE */
-
-syms_of_floatfns ()
-{
-#ifdef LISP_FLOAT_TYPE
- defsubr (&Sacos);
- defsubr (&Sasin);
- defsubr (&Satan);
- defsubr (&Scos);
- defsubr (&Ssin);
- defsubr (&Stan);
-#if 0
- defsubr (&Sacosh);
- defsubr (&Sasinh);
- defsubr (&Satanh);
- defsubr (&Scosh);
- defsubr (&Ssinh);
- defsubr (&Stanh);
- defsubr (&Sbessel_y0);
- defsubr (&Sbessel_y1);
- defsubr (&Sbessel_yn);
- defsubr (&Sbessel_j0);
- defsubr (&Sbessel_j1);
- defsubr (&Sbessel_jn);
- defsubr (&Serf);
- defsubr (&Serfc);
- defsubr (&Slog_gamma);
- defsubr (&Scube_root);
-#endif
- defsubr (&Sfceiling);
- defsubr (&Sffloor);
- defsubr (&Sfround);
- defsubr (&Sftruncate);
- defsubr (&Sexp);
- defsubr (&Sexpt);
- defsubr (&Slog);
- defsubr (&Slog10);
- defsubr (&Ssqrt);
-
- defsubr (&Sabs);
- defsubr (&Sfloat);
- defsubr (&Slogb);
- defsubr (&Sceiling);
- defsubr (&Sround);
- defsubr (&Struncate);
-#endif /* LISP_FLOAT_TYPE */
- defsubr (&Sfloor);
-}
diff --git a/src/fns.c b/src/fns.c
deleted file mode 100644
index 1c7a98cae46..00000000000
--- a/src/fns.c
+++ /dev/null
@@ -1,1923 +0,0 @@
-/* Random utility Lisp functions.
- Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-
-/* Note on some machines this defines `vector' as a typedef,
- so make sure we don't use that name in this file. */
-#undef vector
-#define vector *****
-
-#include "lisp.h"
-#include "commands.h"
-
-#include "buffer.h"
-#include "keyboard.h"
-#include "intervals.h"
-#include "frame.h"
-#include "window.h"
-
-#ifndef NULL
-#define NULL (void *)0
-#endif
-
-extern Lisp_Object Flookup_key ();
-
-extern int minibuffer_auto_raise;
-extern Lisp_Object minibuf_window;
-
-Lisp_Object Qstring_lessp, Qprovide, Qrequire;
-Lisp_Object Qyes_or_no_p_history;
-Lisp_Object Qcursor_in_echo_area;
-
-static int internal_equal ();
-
-DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
- "Return the argument unchanged.")
- (arg)
- Lisp_Object arg;
-{
- return arg;
-}
-
-extern long get_random ();
-extern void seed_random ();
-extern long time ();
-
-DEFUN ("random", Frandom, Srandom, 0, 1, 0,
- "Return a pseudo-random number.\n\
-All integers representable in Lisp are equally likely.\n\
- On most systems, this is 28 bits' worth.\n\
-With positive integer argument N, return random number in interval [0,N).\n\
-With argument t, set the random number seed from the current time and pid.")
- (n)
- Lisp_Object n;
-{
- EMACS_INT val;
- Lisp_Object lispy_val;
- unsigned long denominator;
-
- if (EQ (n, Qt))
- seed_random (getpid () + time (NULL));
- if (NATNUMP (n) && XFASTINT (n) != 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. We do this by using the
- quotient rather than the remainder. At the high end of the RNG
- it's possible to get a quotient larger than n; discarding
- these values eliminates the bias that would otherwise appear
- when using a large n. */
- denominator = ((unsigned long)1 << VALBITS) / XFASTINT (n);
- do
- val = get_random () / denominator;
- while (val >= XFASTINT (n));
- }
- else
- val = get_random ();
- XSETINT (lispy_val, val);
- return lispy_val;
-}
-
-/* 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.")
- (sequence)
- register Lisp_Object sequence;
-{
- register Lisp_Object tail, val;
- register int i;
-
- retry:
- if (STRINGP (sequence))
- XSETFASTINT (val, XSTRING (sequence)->size);
- else if (VECTORP (sequence))
- XSETFASTINT (val, XVECTOR (sequence)->size);
- else if (CHAR_TABLE_P (sequence))
- XSETFASTINT (val, CHAR_TABLE_ORDINARY_SLOTS);
- else if (BOOL_VECTOR_P (sequence))
- XSETFASTINT (val, XBOOL_VECTOR (sequence)->size);
- else if (COMPILEDP (sequence))
- XSETFASTINT (val, XVECTOR (sequence)->size & PSEUDOVECTOR_SIZE_MASK);
- else if (CONSP (sequence))
- {
- for (i = 0, tail = sequence; !NILP (tail); i++)
- {
- QUIT;
- tail = Fcdr (tail);
- }
-
- XSETFASTINT (val, i);
- }
- else if (NILP (sequence))
- XSETFASTINT (val, 0);
- else
- {
- sequence = wrong_type_argument (Qsequencep, sequence);
- goto retry;
- }
- return val;
-}
-
-/* This does not check for quits. That is safe
- since it must terminate. */
-
-DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0,
- "Return the length of a list, but avoid error or infinite loop.\n\
-This function never gets an error. If LIST is not really a list,\n\
-it returns 0. If LIST is circular, it returns a finite value\n\
-which is at least the number of distinct elements.")
- (list)
- Lisp_Object list;
-{
- Lisp_Object tail, halftail, length;
- int len = 0;
-
- /* halftail is used to detect circular lists. */
- halftail = list;
- for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- if (EQ (tail, halftail) && len != 0)
- break;
- len++;
- if ((len & 1) == 0)
- halftail = XCONS (halftail)->cdr;
- }
-
- XSETINT (length, len);
- return length;
-}
-
-DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0,
- "T if two strings have identical contents.\n\
-Case is significant, but text properties are ignored.\n\
-Symbols are also allowed; their print names are used instead.")
- (s1, s2)
- register Lisp_Object s1, s2;
-{
- if (SYMBOLP (s1))
- XSETSTRING (s1, XSYMBOL (s1)->name);
- if (SYMBOLP (s2))
- XSETSTRING (s2, XSYMBOL (s2)->name);
- CHECK_STRING (s1, 0);
- CHECK_STRING (s2, 1);
-
- if (XSTRING (s1)->size != XSTRING (s2)->size ||
- bcmp (XSTRING (s1)->data, XSTRING (s2)->data, XSTRING (s1)->size))
- return Qnil;
- return Qt;
-}
-
-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;
-{
- register int i;
- register unsigned char *p1, *p2;
- register int end;
-
- if (SYMBOLP (s1))
- XSETSTRING (s1, XSYMBOL (s1)->name);
- if (SYMBOLP (s2))
- XSETSTRING (s2, XSYMBOL (s2)->name);
- CHECK_STRING (s1, 0);
- CHECK_STRING (s2, 1);
-
- p1 = XSTRING (s1)->data;
- p2 = XSTRING (s2)->data;
- end = XSTRING (s1)->size;
- if (end > XSTRING (s2)->size)
- end = XSTRING (s2)->size;
-
- for (i = 0; i < end; i++)
- {
- if (p1[i] != p2[i])
- return p1[i] < p2[i] ? Qt : Qnil;
- }
- return i < XSTRING (s2)->size ? Qt : Qnil;
-}
-
-static Lisp_Object concat ();
-
-/* ARGSUSED */
-Lisp_Object
-concat2 (s1, s2)
- Lisp_Object s1, s2;
-{
-#ifdef NO_ARG_ARRAY
- Lisp_Object args[2];
- args[0] = s1;
- args[1] = s2;
- return concat (2, args, Lisp_String, 0);
-#else
- return concat (2, &s1, Lisp_String, 0);
-#endif /* NO_ARG_ARRAY */
-}
-
-/* ARGSUSED */
-Lisp_Object
-concat3 (s1, s2, s3)
- Lisp_Object s1, s2, s3;
-{
-#ifdef NO_ARG_ARRAY
- Lisp_Object args[3];
- args[0] = s1;
- args[1] = s2;
- args[2] = s3;
- return concat (3, args, Lisp_String, 0);
-#else
- return concat (3, &s1, Lisp_String, 0);
-#endif /* NO_ARG_ARRAY */
-}
-
-DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
- "Concatenate all the 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, just used as the tail of the new list.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
- return concat (nargs, args, Lisp_Cons, 1);
-}
-
-DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0,
- "Concatenate all the 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 or a list or vector of characters (integers).\n\
-\n\
-Do not use individual integers as arguments!\n\
-The behavior of `concat' in that case will be changed later!\n\
-If your program passes an integer as an argument to `concat',\n\
-you should change it right away not to do so.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
- return concat (nargs, args, Lisp_String, 0);
-}
-
-DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0,
- "Concatenate all the 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)
- int nargs;
- Lisp_Object *args;
-{
- return concat (nargs, args, Lisp_Vectorlike, 0);
-}
-
-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.")
- (arg)
- Lisp_Object arg;
-{
- if (NILP (arg)) return arg;
-
- if (CHAR_TABLE_P (arg))
- {
- int i, size;
- Lisp_Object copy;
-
- /* Calculate the number of extra slots. */
- size = CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (arg));
- copy = Fmake_char_table (XCHAR_TABLE (arg)->purpose, Qnil);
- /* Copy all the slots, including the extra ones. */
- bcopy (XCHAR_TABLE (arg)->contents, XCHAR_TABLE (copy)->contents,
- (XCHAR_TABLE (arg)->size & PSEUDOVECTOR_SIZE_MASK) * sizeof (Lisp_Object));
-
- /* Recursively copy any char-tables in the ordinary slots. */
- for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
- if (CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
- XCHAR_TABLE (copy)->contents[i]
- = Fcopy_sequence (XCHAR_TABLE (copy)->contents[i]);
-
- return copy;
- }
-
- if (BOOL_VECTOR_P (arg))
- {
- Lisp_Object val;
- int size_in_chars
- = (XBOOL_VECTOR (arg)->size + BITS_PER_CHAR) / BITS_PER_CHAR;
-
- val = Fmake_bool_vector (Flength (arg), Qnil);
- bcopy (XBOOL_VECTOR (arg)->data, XBOOL_VECTOR (val)->data,
- size_in_chars);
- return val;
- }
-
- if (!CONSP (arg) && !VECTORP (arg) && !STRINGP (arg))
- arg = wrong_type_argument (Qsequencep, arg);
- return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0);
-}
-
-static Lisp_Object
-concat (nargs, args, target_type, last_special)
- int nargs;
- Lisp_Object *args;
- enum Lisp_Type target_type;
- int last_special;
-{
- Lisp_Object val;
- Lisp_Object len;
- register Lisp_Object tail;
- register Lisp_Object this;
- int toindex;
- register int leni;
- register int argnum;
- Lisp_Object last_tail;
- Lisp_Object prev;
-
- /* In append, the last arg isn't treated like the others */
- if (last_special && nargs > 0)
- {
- nargs--;
- last_tail = args[nargs];
- }
- else
- last_tail = Qnil;
-
- for (argnum = 0; argnum < nargs; argnum++)
- {
- this = args[argnum];
- if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this)
- || COMPILEDP (this) || BOOL_VECTOR_P (this)))
- {
- if (INTEGERP (this))
- args[argnum] = Fnumber_to_string (this);
- else
- args[argnum] = wrong_type_argument (Qsequencep, this);
- }
- }
-
- for (argnum = 0, leni = 0; argnum < nargs; argnum++)
- {
- this = args[argnum];
- len = Flength (this);
- leni += XFASTINT (len);
- }
-
- XSETFASTINT (len, leni);
-
- if (target_type == Lisp_Cons)
- val = Fmake_list (len, Qnil);
- else if (target_type == Lisp_Vectorlike)
- val = Fmake_vector (len, Qnil);
- else
- val = Fmake_string (len, len);
-
- /* In append, if all but last arg are nil, return last arg */
- if (target_type == Lisp_Cons && EQ (val, Qnil))
- return last_tail;
-
- if (CONSP (val))
- tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */
- else
- toindex = 0;
-
- prev = Qnil;
-
- for (argnum = 0; argnum < nargs; argnum++)
- {
- Lisp_Object thislen;
- int thisleni;
- register int thisindex = 0;
-
- this = args[argnum];
- if (!CONSP (this))
- thislen = Flength (this), thisleni = XINT (thislen);
-
- if (STRINGP (this) && STRINGP (val)
- && ! NULL_INTERVAL_P (XSTRING (this)->intervals))
- {
- copy_text_properties (make_number (0), thislen, this,
- make_number (toindex), val, Qnil);
- }
-
- while (1)
- {
- register Lisp_Object elt;
-
- /* Fetch next element of `this' arg into `elt', or break if
- `this' is exhausted. */
- if (NILP (this)) break;
- if (CONSP (this))
- elt = Fcar (this), this = Fcdr (this);
- else
- {
- if (thisindex >= thisleni) break;
- if (STRINGP (this))
- XSETFASTINT (elt, XSTRING (this)->data[thisindex++]);
- else if (BOOL_VECTOR_P (this))
- {
- int size_in_chars
- = ((XBOOL_VECTOR (this)->size + BITS_PER_CHAR)
- / BITS_PER_CHAR);
- int byte;
- byte = XBOOL_VECTOR (val)->data[thisindex / BITS_PER_CHAR];
- if (byte & (1 << thisindex))
- elt = Qt;
- else
- elt = Qnil;
- }
- else
- elt = XVECTOR (this)->contents[thisindex++];
- }
-
- /* Store into result */
- if (toindex < 0)
- {
- XCONS (tail)->car = elt;
- prev = tail;
- tail = XCONS (tail)->cdr;
- }
- else if (VECTORP (val))
- XVECTOR (val)->contents[toindex++] = elt;
- else
- {
- while (!INTEGERP (elt))
- elt = wrong_type_argument (Qintegerp, elt);
- {
-#ifdef MASSC_REGISTER_BUG
- /* Even removing all "register"s doesn't disable this bug!
- Nothing simpler than this seems to work. */
- unsigned char *p = & XSTRING (val)->data[toindex++];
- *p = XINT (elt);
-#else
- XSTRING (val)->data[toindex++] = XINT (elt);
-#endif
- }
- }
- }
- }
- if (!NILP (prev))
- XCONS (prev)->cdr = last_tail;
-
- return val;
-}
-
-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\
-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.")
- (alist)
- Lisp_Object alist;
-{
- register Lisp_Object tem;
-
- CHECK_LIST (alist, 0);
- if (NILP (alist))
- return alist;
- alist = concat (1, &alist, Lisp_Cons, 0);
- for (tem = alist; CONSP (tem); tem = XCONS (tem)->cdr)
- {
- register Lisp_Object car;
- car = XCONS (tem)->car;
-
- if (CONSP (car))
- XCONS (tem)->car = Fcons (XCONS (car)->car, XCONS (car)->cdr);
- }
- return alist;
-}
-
-DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0,
- "Return a substring of STRING, starting at index FROM and ending before TO.\n\
-TO may be nil or omitted; then the substring runs to the end of STRING.\n\
-If FROM or TO is negative, it counts from the end.\n\
-\n\
-This function allows vectors as well as strings.")
- (string, from, to)
- Lisp_Object string;
- register Lisp_Object from, to;
-{
- Lisp_Object res;
- int size;
-
- if (! (STRINGP (string) || VECTORP (string)))
- wrong_type_argument (Qarrayp, string);
-
- CHECK_NUMBER (from, 1);
-
- if (STRINGP (string))
- size = XSTRING (string)->size;
- else
- size = XVECTOR (string)->size;
-
- if (NILP (to))
- to = size;
- else
- CHECK_NUMBER (to, 2);
-
- if (XINT (from) < 0)
- XSETINT (from, XINT (from) + size);
- if (XINT (to) < 0)
- XSETINT (to, XINT (to) + size);
- if (!(0 <= XINT (from) && XINT (from) <= XINT (to)
- && XINT (to) <= size))
- args_out_of_range_3 (string, from, to);
-
- if (STRINGP (string))
- {
- res = make_string (XSTRING (string)->data + XINT (from),
- XINT (to) - XINT (from));
- copy_text_properties (from, to, string, make_number (0), res, Qnil);
- }
- else
- res = Fvector (XINT (to) - XINT (from),
- XVECTOR (string)->contents + XINT (from));
-
- return res;
-}
-
-DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
- "Take cdr N times on LIST, returns the result.")
- (n, list)
- Lisp_Object n;
- register Lisp_Object list;
-{
- register int i, num;
- CHECK_NUMBER (n, 0);
- num = XINT (n);
- for (i = 0; i < num && !NILP (list); i++)
- {
- QUIT;
- list = Fcdr (list);
- }
- return list;
-}
-
-DEFUN ("nth", Fnth, Snth, 2, 2, 0,
- "Return 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;
-{
- return Fcar (Fnthcdr (n, list));
-}
-
-DEFUN ("elt", Felt, Selt, 2, 2, 0,
- "Return element of SEQUENCE at index N.")
- (sequence, n)
- register Lisp_Object sequence, n;
-{
- CHECK_NUMBER (n, 0);
- while (1)
- {
- if (CONSP (sequence) || NILP (sequence))
- return Fcar (Fnthcdr (n, sequence));
- else if (STRINGP (sequence) || VECTORP (sequence)
- || BOOL_VECTOR_P (sequence) || CHAR_TABLE_P (sequence))
- return Faref (sequence, n);
- else
- sequence = wrong_type_argument (Qsequencep, sequence);
- }
-}
-
-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; !NILP (tail); tail = Fcdr (tail))
- {
- register Lisp_Object tem;
- tem = Fcar (tail);
- if (! NILP (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\
-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; !NILP (tail); tail = Fcdr (tail))
- {
- register Lisp_Object tem;
- tem = Fcar (tail);
- if (EQ (elt, tem)) return tail;
- QUIT;
- }
- return Qnil;
-}
-
-DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
- "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
-The value is actually the element of LIST whose car is KEY.\n\
-Elements of LIST that are not conses are ignored.")
- (key, list)
- register Lisp_Object key;
- Lisp_Object list;
-{
- register Lisp_Object tail;
- for (tail = list; !NILP (tail); tail = Fcdr (tail))
- {
- register Lisp_Object elt, tem;
- elt = Fcar (tail);
- if (!CONSP (elt)) continue;
- tem = Fcar (elt);
- if (EQ (key, tem)) return elt;
- QUIT;
- }
- return Qnil;
-}
-
-/* Like Fassq but never report an error and do not allow quits.
- Use only on lists known never to be circular. */
-
-Lisp_Object
-assq_no_quit (key, list)
- register Lisp_Object key;
- Lisp_Object list;
-{
- register Lisp_Object tail;
- for (tail = list; CONSP (tail); tail = Fcdr (tail))
- {
- register Lisp_Object elt, tem;
- elt = Fcar (tail);
- if (!CONSP (elt)) continue;
- tem = Fcar (elt);
- if (EQ (key, tem)) return elt;
- }
- return Qnil;
-}
-
-DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
- "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
-The value is actually the element of LIST whose car equals KEY.")
- (key, list)
- register Lisp_Object key;
- Lisp_Object list;
-{
- register Lisp_Object tail;
- for (tail = list; !NILP (tail); tail = Fcdr (tail))
- {
- register Lisp_Object elt, tem;
- elt = Fcar (tail);
- if (!CONSP (elt)) continue;
- tem = Fequal (Fcar (elt), key);
- if (!NILP (tem)) return elt;
- QUIT;
- }
- return Qnil;
-}
-
-DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
- "Return non-nil if ELT is `eq' to the cdr of an element of LIST.\n\
-The value is actually the element of LIST whose cdr is ELT.")
- (key, list)
- register Lisp_Object key;
- Lisp_Object list;
-{
- register Lisp_Object tail;
- for (tail = list; !NILP (tail); tail = Fcdr (tail))
- {
- register Lisp_Object elt, tem;
- elt = Fcar (tail);
- if (!CONSP (elt)) continue;
- tem = Fcdr (elt);
- if (EQ (key, tem)) return elt;
- QUIT;
- }
- return Qnil;
-}
-
-DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
- "Return non-nil if KEY is `equal' to the cdr of an element of LIST.\n\
-The value is actually the element of LIST whose cdr equals KEY.")
- (key, list)
- register Lisp_Object key;
- Lisp_Object list;
-{
- register Lisp_Object tail;
- for (tail = list; !NILP (tail); tail = Fcdr (tail))
- {
- register Lisp_Object elt, tem;
- elt = Fcar (tail);
- if (!CONSP (elt)) continue;
- tem = Fequal (Fcdr (elt), key);
- if (!NILP (tem)) return elt;
- QUIT;
- }
- return Qnil;
-}
-
-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\
-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'.")
- (elt, list)
- register Lisp_Object elt;
- Lisp_Object list;
-{
- register Lisp_Object tail, prev;
- register Lisp_Object tem;
-
- tail = list;
- prev = Qnil;
- while (!NILP (tail))
- {
- tem = Fcar (tail);
- if (EQ (elt, tem))
- {
- if (NILP (prev))
- list = Fcdr (tail);
- else
- Fsetcdr (prev, Fcdr (tail));
- }
- else
- prev = tail;
- tail = Fcdr (tail);
- QUIT;
- }
- return list;
-}
-
-DEFUN ("delete", Fdelete, Sdelete, 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 `equal'.\n\
-If the first member of LIST is ELT, deleting it is not a side effect;\n\
-it is simply using a different list.\n\
-Therefore, write `(setq foo (delete element foo))'\n\
-to be sure of changing the value of `foo'.")
- (elt, list)
- register Lisp_Object elt;
- Lisp_Object list;
-{
- register Lisp_Object tail, prev;
- register Lisp_Object tem;
-
- tail = list;
- prev = Qnil;
- while (!NILP (tail))
- {
- tem = Fcar (tail);
- if (! NILP (Fequal (elt, tem)))
- {
- if (NILP (prev))
- list = Fcdr (tail);
- else
- Fsetcdr (prev, Fcdr (tail));
- }
- else
- prev = tail;
- tail = Fcdr (tail);
- QUIT;
- }
- return list;
-}
-
-DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
- "Reverse LIST by modifying cdr pointers.\n\
-Returns the beginning of the reversed list.")
- (list)
- Lisp_Object list;
-{
- register Lisp_Object prev, tail, next;
-
- if (NILP (list)) return list;
- prev = Qnil;
- tail = list;
- while (!NILP (tail))
- {
- QUIT;
- next = Fcdr (tail);
- Fsetcdr (tail, prev);
- prev = tail;
- tail = next;
- }
- return prev;
-}
-
-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.")
- (list)
- Lisp_Object list;
-{
- Lisp_Object length;
- register Lisp_Object *vec;
- register Lisp_Object tail;
- register int i;
-
- length = Flength (list);
- vec = (Lisp_Object *) alloca (XINT (length) * sizeof (Lisp_Object));
- for (i = XINT (length) - 1, tail = list; i >= 0; i--, tail = Fcdr (tail))
- vec[i] = Fcar (tail);
-
- return Flist (XINT (length), vec);
-}
-
-Lisp_Object merge ();
-
-DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
- "Sort LIST, stably, comparing elements using PREDICATE.\n\
-Returns the sorted list. LIST is modified by side effects.\n\
-PREDICATE is called with two elements of LIST, and should return T\n\
-if the first element is \"less\" than the second.")
- (list, predicate)
- Lisp_Object list, predicate;
-{
- Lisp_Object front, back;
- register Lisp_Object len, tem;
- struct gcpro gcpro1, gcpro2;
- register int length;
-
- front = list;
- len = Flength (list);
- length = XINT (len);
- if (length < 2)
- return list;
-
- XSETINT (len, (length / 2) - 1);
- tem = Fnthcdr (len, list);
- back = Fcdr (tem);
- Fsetcdr (tem, Qnil);
-
- GCPRO2 (front, back);
- front = Fsort (front, predicate);
- back = Fsort (back, predicate);
- UNGCPRO;
- return merge (front, back, predicate);
-}
-
-Lisp_Object
-merge (org_l1, org_l2, pred)
- Lisp_Object org_l1, org_l2;
- Lisp_Object pred;
-{
- Lisp_Object value;
- register Lisp_Object tail;
- Lisp_Object tem;
- register Lisp_Object l1, l2;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- l1 = org_l1;
- l2 = org_l2;
- tail = Qnil;
- value = Qnil;
-
- /* It is sufficient to protect org_l1 and org_l2.
- When l1 and l2 are updated, we copy the new values
- back into the org_ vars. */
- GCPRO4 (org_l1, org_l2, pred, value);
-
- while (1)
- {
- if (NILP (l1))
- {
- UNGCPRO;
- if (NILP (tail))
- return l2;
- Fsetcdr (tail, l2);
- return value;
- }
- if (NILP (l2))
- {
- UNGCPRO;
- if (NILP (tail))
- return l1;
- Fsetcdr (tail, l1);
- return value;
- }
- tem = call2 (pred, Fcar (l2), Fcar (l1));
- if (NILP (tem))
- {
- tem = l1;
- l1 = Fcdr (l1);
- org_l1 = l1;
- }
- else
- {
- tem = l2;
- l2 = Fcdr (l2);
- org_l2 = l2;
- }
- if (NILP (tail))
- value = tem;
- else
- Fsetcdr (tail, tem);
- tail = tem;
- }
-}
-
-
-DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
- "Extract a value from a property list.\n\
-PLIST is a property list, which is a list of the form\n\
-\(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value\n\
-corresponding to the given PROP, or nil if PROP is not\n\
-one of the properties on the list.")
- (plist, prop)
- Lisp_Object plist;
- register Lisp_Object prop;
-{
- register Lisp_Object tail;
- for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
- {
- register Lisp_Object tem;
- tem = Fcar (tail);
- if (EQ (prop, tem))
- return Fcar (Fcdr (tail));
- }
- return Qnil;
-}
-
-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)'.")
- (symbol, propname)
- Lisp_Object symbol, propname;
-{
- CHECK_SYMBOL (symbol, 0);
- return Fplist_get (XSYMBOL (symbol)->plist, propname);
-}
-
-DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0,
- "Change value in PLIST of PROP to VAL.\n\
-PLIST is a property list, which is a list of the form\n\
-\(PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol and VAL is any object.\n\
-If PROP is already a property on the list, its value is set to VAL,\n\
-otherwise the new PROP VAL pair is added. The new plist is returned;\n\
-use `(setq x (plist-put x prop val))' to be sure to use the new value.\n\
-The PLIST is modified by side effects.")
- (plist, prop, val)
- Lisp_Object plist;
- register Lisp_Object prop;
- Lisp_Object val;
-{
- register Lisp_Object tail, prev;
- Lisp_Object newcell;
- prev = Qnil;
- for (tail = plist; CONSP (tail) && CONSP (XCONS (tail)->cdr);
- tail = XCONS (XCONS (tail)->cdr)->cdr)
- {
- if (EQ (prop, XCONS (tail)->car))
- {
- Fsetcar (XCONS (tail)->cdr, val);
- return plist;
- }
- prev = tail;
- }
- newcell = Fcons (prop, Fcons (val, Qnil));
- if (NILP (prev))
- return newcell;
- else
- Fsetcdr (XCONS (prev)->cdr, newcell);
- return plist;
-}
-
-DEFUN ("put", Fput, Sput, 3, 3, 0,
- "Store SYMBOL's PROPNAME property with value VALUE.\n\
-It can be retrieved with `(get SYMBOL PROPNAME)'.")
- (symbol, propname, value)
- Lisp_Object symbol, propname, value;
-{
- CHECK_SYMBOL (symbol, 0);
- XSYMBOL (symbol)->plist
- = Fplist_put (XSYMBOL (symbol)->plist, propname, value);
- return value;
-}
-
-DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
- "T if two Lisp objects have similar structure and contents.\n\
-They must have the same data type.\n\
-Conses are compared by comparing the cars and the cdrs.\n\
-Vectors and strings are compared element by element.\n\
-Numbers are compared by value, but integers cannot equal floats.\n\
- (Use `=' if you want integers and floats to be able to be equal.)\n\
-Symbols must match exactly.")
- (o1, o2)
- register Lisp_Object o1, o2;
-{
- return internal_equal (o1, o2, 0) ? Qt : Qnil;
-}
-
-static int
-internal_equal (o1, o2, depth)
- register Lisp_Object o1, o2;
- int depth;
-{
- if (depth > 200)
- error ("Stack overflow in equal");
-
- tail_recurse:
- QUIT;
- if (EQ (o1, o2))
- return 1;
- if (XTYPE (o1) != XTYPE (o2))
- return 0;
-
- switch (XTYPE (o1))
- {
-#ifdef LISP_FLOAT_TYPE
- case Lisp_Float:
- return (extract_float (o1) == extract_float (o2));
-#endif
-
- case Lisp_Cons:
- if (!internal_equal (XCONS (o1)->car, XCONS (o2)->car, depth + 1))
- return 0;
- o1 = XCONS (o1)->cdr;
- o2 = XCONS (o2)->cdr;
- goto tail_recurse;
-
- case Lisp_Misc:
- if (XMISCTYPE (o1) != XMISCTYPE (o2))
- return 0;
- if (OVERLAYP (o1))
- {
- if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o1),
- depth + 1)
- || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o1),
- depth + 1))
- return 0;
- o1 = XOVERLAY (o1)->plist;
- o2 = XOVERLAY (o2)->plist;
- goto tail_recurse;
- }
- if (MARKERP (o1))
- {
- return (XMARKER (o1)->buffer == XMARKER (o2)->buffer
- && (XMARKER (o1)->buffer == 0
- || XMARKER (o1)->bufpos == XMARKER (o2)->bufpos));
- }
- break;
-
- case Lisp_Vectorlike:
- {
- register int i, size;
- size = XVECTOR (o1)->size;
- /* Pseudovectors have the type encoded in the size field, so this test
- actually checks that the objects have the same type as well as the
- same size. */
- if (XVECTOR (o2)->size != size)
- return 0;
- /* Boolvectors are compared much like strings. */
- if (BOOL_VECTOR_P (o1))
- {
- int size_in_chars
- = (XBOOL_VECTOR (o1)->size + BITS_PER_CHAR) / BITS_PER_CHAR;
-
- if (XBOOL_VECTOR (o1)->size != XBOOL_VECTOR (o2)->size)
- return 0;
- if (bcmp (XBOOL_VECTOR (o1)->data, XBOOL_VECTOR (o2)->data,
- size_in_chars))
- return 0;
- return 1;
- }
-
- /* Aside from them, only true vectors, char-tables, and compiled
- functions are sensible to compare, so eliminate the others now. */
- if (size & PSEUDOVECTOR_FLAG)
- {
- if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE)))
- return 0;
- size &= PSEUDOVECTOR_SIZE_MASK;
- }
- for (i = 0; i < size; i++)
- {
- Lisp_Object v1, v2;
- v1 = XVECTOR (o1)->contents [i];
- v2 = XVECTOR (o2)->contents [i];
- if (!internal_equal (v1, v2, depth + 1))
- return 0;
- }
- return 1;
- }
- break;
-
- case Lisp_String:
- if (XSTRING (o1)->size != XSTRING (o2)->size)
- return 0;
- if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data,
- XSTRING (o1)->size))
- return 0;
-#ifdef USE_TEXT_PROPERTIES
- /* If the strings have intervals, verify they match;
- if not, they are unequal. */
- if ((XSTRING (o1)->intervals != 0 || XSTRING (o2)->intervals != 0)
- && ! compare_string_intervals (o1, o2))
- return 0;
-#endif
- return 1;
- }
- return 0;
-}
-
-DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0,
- "Store each element of ARRAY with ITEM.\n\
-ARRAY is a vector, string, char-table, or bool-vector.")
- (array, item)
- Lisp_Object array, item;
-{
- register int size, index, charval;
- retry:
- if (VECTORP (array))
- {
- register Lisp_Object *p = XVECTOR (array)->contents;
- size = XVECTOR (array)->size;
- for (index = 0; index < size; index++)
- p[index] = item;
- }
- else if (CHAR_TABLE_P (array))
- {
- register Lisp_Object *p = XCHAR_TABLE (array)->contents;
- size = CHAR_TABLE_ORDINARY_SLOTS;
- for (index = 0; index < size; index++)
- p[index] = item;
- XCHAR_TABLE (array)->defalt = Qnil;
- }
- else if (STRINGP (array))
- {
- register unsigned char *p = XSTRING (array)->data;
- CHECK_NUMBER (item, 1);
- charval = XINT (item);
- size = XSTRING (array)->size;
- for (index = 0; index < size; index++)
- p[index] = charval;
- }
- else if (BOOL_VECTOR_P (array))
- {
- register unsigned char *p = XBOOL_VECTOR (array)->data;
- int size_in_chars
- = (XBOOL_VECTOR (array)->size + BITS_PER_CHAR) / BITS_PER_CHAR;
-
- charval = (! NILP (item) ? -1 : 0);
- for (index = 0; index < size_in_chars; index++)
- p[index] = charval;
- }
- else
- {
- array = wrong_type_argument (Qarrayp, array);
- goto retry;
- }
- return array;
-}
-
-DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
- 1, 1, 0,
- "Return the subtype of char-table CHAR-TABLE. The value is a symbol.")
- (char_table)
- Lisp_Object char_table;
-{
- CHECK_CHAR_TABLE (char_table, 0);
-
- return XCHAR_TABLE (char_table)->purpose;
-}
-
-DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
- 1, 1, 0,
- "Return the parent char-table of CHAR-TABLE.\n\
-The value is either nil or another char-table.\n\
-If CHAR-TABLE holds nil for a given character,\n\
-then the actual applicable value is inherited from the parent char-table\n\
-\(or from its parents, if necessary).")
- (char_table)
- Lisp_Object char_table;
-{
- CHECK_CHAR_TABLE (char_table, 0);
-
- return XCHAR_TABLE (char_table)->parent;
-}
-
-DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
- 2, 2, 0,
- "Set the parent char-table of CHAR-TABLE to PARENT.\n\
-PARENT must be either nil or another char-table.")
- (char_table, parent)
- Lisp_Object char_table, parent;
-{
- Lisp_Object temp;
-
- CHECK_CHAR_TABLE (char_table, 0);
-
- if (!NILP (parent))
- {
- CHECK_CHAR_TABLE (parent, 0);
-
- for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
- if (EQ (temp, char_table))
- error ("Attempt to make a chartable be its own parent");
- }
-
- XCHAR_TABLE (char_table)->parent = parent;
-
- return parent;
-}
-
-DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
- 2, 2, 0,
- "Return the value in extra-slot number N of char-table CHAR-TABLE.")
- (char_table, n)
- Lisp_Object char_table, n;
-{
- CHECK_CHAR_TABLE (char_table, 1);
- CHECK_NUMBER (n, 2);
- if (XINT (n) < 0
- || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
- args_out_of_range (char_table, n);
-
- return XCHAR_TABLE (char_table)->extras[XINT (n)];
-}
-
-DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
- Sset_char_table_extra_slot,
- 3, 3, 0,
- "Set extra-slot number N of CHAR-TABLE to VALUE.")
- (char_table, n, value)
- Lisp_Object char_table, n, value;
-{
- CHECK_CHAR_TABLE (char_table, 1);
- CHECK_NUMBER (n, 2);
- if (XINT (n) < 0
- || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
- args_out_of_range (char_table, n);
-
- return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
-}
-
-DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
- 2, 2, 0,
- "Return the value in CHAR-TABLE for a range of characters RANGE.\n\
-RANGE should be t (for all characters), nil (for the default value)\n\
-a vector which identifies a character set or a row of a character set,\n\
-or a character code.")
- (char_table, range)
- Lisp_Object char_table, range;
-{
- int i;
-
- CHECK_CHAR_TABLE (char_table, 0);
-
- if (EQ (range, Qnil))
- return XCHAR_TABLE (char_table)->defalt;
- else if (INTEGERP (range))
- return Faref (char_table, range);
- else if (VECTORP (range))
- {
- for (i = 0; i < XVECTOR (range)->size - 1; i++)
- char_table = Faref (char_table, XVECTOR (range)->contents[i]);
-
- if (EQ (XVECTOR (range)->contents[i], Qnil))
- return XCHAR_TABLE (char_table)->defalt;
- else
- return Faref (char_table, XVECTOR (range)->contents[i]);
- }
- else
- error ("Invalid RANGE argument to `char-table-range'");
-}
-
-DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
- 3, 3, 0,
- "Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.\n\
-RANGE should be t (for all characters), nil (for the default value)\n\
-a vector which identifies a character set or a row of a character set,\n\
-or a character code.")
- (char_table, range, value)
- Lisp_Object char_table, range, value;
-{
- int i;
-
- CHECK_CHAR_TABLE (char_table, 0);
-
- if (EQ (range, Qt))
- for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
- XCHAR_TABLE (char_table)->contents[i] = value;
- else if (EQ (range, Qnil))
- XCHAR_TABLE (char_table)->defalt = value;
- else if (INTEGERP (range))
- Faset (char_table, range, value);
- else if (VECTORP (range))
- {
- for (i = 0; i < XVECTOR (range)->size - 1; i++)
- char_table = Faref (char_table, XVECTOR (range)->contents[i]);
-
- if (EQ (XVECTOR (range)->contents[i], Qnil))
- XCHAR_TABLE (char_table)->defalt = value;
- else
- Faset (char_table, XVECTOR (range)->contents[i], value);
- }
- else
- error ("Invalid RANGE argument to `set-char-table-range'");
-
- return value;
-}
-
-/* Map C_FUNCTION or FUNCTION over CHARTABLE, calling it for each
- character or group of characters that share a value.
- DEPTH is the current depth in the originally specified
- chartable, and INDICES contains the vector indices
- for the levels our callers have descended. */
-
-void
-map_char_table (c_function, function, chartable, depth, indices)
- Lisp_Object (*c_function) (), function, chartable, *indices;
- int depth;
-{
- int i;
- int size = CHAR_TABLE_ORDINARY_SLOTS;
-
- /* Make INDICES longer if we are about to fill it up. */
- if ((depth % 10) == 9)
- {
- Lisp_Object *new_indices
- = (Lisp_Object *) alloca ((depth += 10) * sizeof (Lisp_Object));
- bcopy (indices, new_indices, depth * sizeof (Lisp_Object));
- indices = new_indices;
- }
-
- for (i = 0; i < size; i++)
- {
- Lisp_Object elt;
- indices[depth] = i;
- elt = XCHAR_TABLE (chartable)->contents[i];
- if (CHAR_TABLE_P (elt))
- map_char_table (c_function, function, chartable, depth + 1, indices);
- else if (c_function)
- (*c_function) (depth + 1, indices, elt);
- /* Here we should handle all cases where the range is a single character
- by passing that character as a number. Currently, that is
- all the time, but with the MULE code this will have to be changed. */
- else if (depth == 0)
- call2 (function, make_number (i), elt);
- else
- call2 (function, Fvector (depth + 1, indices), elt);
- }
-}
-
-DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
- 2, 2, 0,
- "Call FUNCTION for each range of like characters in CHAR-TABLE.\n\
-FUNCTION is called with two arguments--a key and a value.\n\
-The key is always a possible RANGE argument to `set-char-table-range'.")
- (function, char_table)
- Lisp_Object function, char_table;
-{
- Lisp_Object keyvec;
- Lisp_Object *indices = (Lisp_Object *) alloca (10 * sizeof (Lisp_Object));
-
- map_char_table (NULL, function, char_table, 0, indices);
- return Qnil;
-}
-
-/* ARGSUSED */
-Lisp_Object
-nconc2 (s1, s2)
- Lisp_Object s1, s2;
-{
-#ifdef NO_ARG_ARRAY
- Lisp_Object args[2];
- args[0] = s1;
- args[1] = s2;
- return Fnconc (2, args);
-#else
- return Fnconc (2, &s1);
-#endif /* NO_ARG_ARRAY */
-}
-
-DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
- "Concatenate any number of lists by altering them.\n\
-Only the last argument is not altered, and need not be a list.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
- register int argnum;
- register Lisp_Object tail, tem, val;
-
- val = Qnil;
-
- for (argnum = 0; argnum < nargs; argnum++)
- {
- tem = args[argnum];
- if (NILP (tem)) continue;
-
- if (NILP (val))
- val = tem;
-
- if (argnum + 1 == nargs) break;
-
- if (!CONSP (tem))
- tem = wrong_type_argument (Qlistp, tem);
-
- while (CONSP (tem))
- {
- tail = tem;
- tem = Fcdr (tail);
- QUIT;
- }
-
- tem = args[argnum + 1];
- Fsetcdr (tail, tem);
- if (NILP (tem))
- args[argnum + 1] = tail;
- }
-
- return val;
-}
-
-/* This is the guts of all mapping functions.
- Apply fn to each element of seq, one by one,
- storing the results into elements of vals, a C vector of Lisp_Objects.
- leni is the length of vals, which should also be the length of seq. */
-
-static void
-mapcar1 (leni, vals, fn, seq)
- int leni;
- Lisp_Object *vals;
- Lisp_Object fn, seq;
-{
- register Lisp_Object tail;
- Lisp_Object dummy;
- register int i;
- struct gcpro gcpro1, gcpro2, gcpro3;
-
- /* Don't let vals contain any garbage when GC happens. */
- for (i = 0; i < leni; i++)
- vals[i] = Qnil;
-
- GCPRO3 (dummy, fn, seq);
- gcpro1.var = vals;
- gcpro1.nvars = leni;
- /* We need not explicitly protect `tail' because it is used only on lists, and
- 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
-
- if (VECTORP (seq))
- {
- for (i = 0; i < leni; i++)
- {
- dummy = XVECTOR (seq)->contents[i];
- vals[i] = call1 (fn, dummy);
- }
- }
- else if (STRINGP (seq))
- {
- for (i = 0; i < leni; i++)
- {
- XSETFASTINT (dummy, XSTRING (seq)->data[i]);
- vals[i] = call1 (fn, dummy);
- }
- }
- else /* Must be a list, since Flength did not get an error */
- {
- tail = seq;
- for (i = 0; i < leni; i++)
- {
- vals[i] = call1 (fn, Fcar (tail));
- tail = Fcdr (tail);
- }
- }
-
- UNGCPRO;
-}
-
-DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
- "Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.\n\
-In between each pair of results, stick in SEPARATOR. Thus, \" \" as\n\
-SEPARATOR results in spaces between the values returned by FUNCTION.")
- (function, sequence, separator)
- Lisp_Object function, sequence, separator;
-{
- Lisp_Object len;
- register int leni;
- int nargs;
- register Lisp_Object *args;
- register int i;
- struct gcpro gcpro1;
-
- len = Flength (sequence);
- leni = XINT (len);
- nargs = leni + leni - 1;
- if (nargs < 0) return build_string ("");
-
- args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
-
- GCPRO1 (separator);
- mapcar1 (leni, args, function, sequence);
- UNGCPRO;
-
- for (i = leni - 1; i >= 0; i--)
- args[i + i] = args[i];
-
- for (i = 1; i < nargs; i += 2)
- args[i] = separator;
-
- return Fconcat (nargs, args);
-}
-
-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.")
- (function, sequence)
- Lisp_Object function, sequence;
-{
- register Lisp_Object len;
- register int leni;
- register Lisp_Object *args;
-
- len = Flength (sequence);
- leni = XFASTINT (len);
- args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
-
- mapcar1 (leni, args, function, sequence);
-
- return Flist (leni, args);
-}
-
-/* Anything that calls this function must protect from GC! */
-
-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, key, def, answer_string, map;
- register int answer;
- Lisp_Object xprompt;
- Lisp_Object args[2];
- struct gcpro gcpro1, gcpro2;
- int count = specpdl_ptr - specpdl;
-
- specbind (Qcursor_in_echo_area, Qt);
-
- map = Fsymbol_value (intern ("query-replace-map"));
-
- CHECK_STRING (prompt, 0);
- xprompt = prompt;
- GCPRO2 (prompt, xprompt);
-
- while (1)
- {
-
-
-#ifdef HAVE_MENUS
- if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
- && have_menus_p ())
- {
- Lisp_Object pane, menu;
- redisplay_preserve_echo_area ();
- pane = Fcons (Fcons (build_string ("Yes"), Qt),
- Fcons (Fcons (build_string ("No"), Qnil),
- Qnil));
- menu = Fcons (prompt, pane);
- obj = Fx_popup_dialog (Qt, menu);
- answer = !NILP (obj);
- break;
- }
-#endif /* HAVE_MENUS */
- cursor_in_echo_area = 1;
- choose_minibuf_frame ();
- message_nolog ("%s(y or n) ", XSTRING (xprompt)->data);
-
- if (minibuffer_auto_raise)
- {
- Lisp_Object mini_frame;
-
- mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
-
- Fraise_frame (mini_frame);
- }
-
- obj = read_filtered_event (1, 0, 0);
- cursor_in_echo_area = 0;
- /* If we need to quit, quit with cursor_in_echo_area = 0. */
- QUIT;
-
- key = Fmake_vector (make_number (1), obj);
- def = Flookup_key (map, key, Qt);
- answer_string = Fsingle_key_description (obj);
-
- if (EQ (def, intern ("skip")))
- {
- answer = 0;
- break;
- }
- else if (EQ (def, intern ("act")))
- {
- answer = 1;
- break;
- }
- else if (EQ (def, intern ("recenter")))
- {
- Frecenter (Qnil);
- xprompt = prompt;
- continue;
- }
- else if (EQ (def, intern ("quit")))
- Vquit_flag = Qt;
- /* We want to exit this command for exit-prefix,
- and this is the only way to do it. */
- else if (EQ (def, intern ("exit-prefix")))
- Vquit_flag = Qt;
-
- QUIT;
-
- /* If we don't clear this, then the next call to read_char will
- return quit_char again, and we'll enter an infinite loop. */
- Vquit_flag = Qnil;
-
- Fding (Qnil);
- Fdiscard_input ();
- if (EQ (xprompt, prompt))
- {
- args[0] = build_string ("Please answer y or n. ");
- args[1] = prompt;
- xprompt = Fconcat (2, args);
- }
- }
- UNGCPRO;
-
- if (! noninteractive)
- {
- cursor_in_echo_area = -1;
- message_nolog ("%s(y or n) %c",
- XSTRING (xprompt)->data, answer ? 'y' : 'n');
- }
-
- unbind_to (count, Qnil);
- return answer ? 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\
-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 has been confirmed.")
- (prompt)
- Lisp_Object prompt;
-{
- register Lisp_Object ans;
- Lisp_Object args[2];
- struct gcpro gcpro1;
- Lisp_Object menu;
-
- CHECK_STRING (prompt, 0);
-
-#ifdef HAVE_MENUS
- if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
- && have_menus_p ())
- {
- Lisp_Object pane, menu, obj;
- redisplay_preserve_echo_area ();
- pane = Fcons (Fcons (build_string ("Yes"), Qt),
- Fcons (Fcons (build_string ("No"), Qnil),
- Qnil));
- GCPRO1 (pane);
- menu = Fcons (prompt, pane);
- obj = Fx_popup_dialog (Qt, menu);
- UNGCPRO;
- return obj;
- }
-#endif /* HAVE_MENUS */
-
- args[0] = prompt;
- args[1] = build_string ("(yes or no) ");
- prompt = Fconcat (2, args);
-
- GCPRO1 (prompt);
-
- while (1)
- {
- ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
- Qyes_or_no_p_history));
- if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
- {
- UNGCPRO;
- return Qt;
- }
- if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
- {
- UNGCPRO;
- return Qnil;
- }
-
- Fding (Qnil);
- Fdiscard_input ();
- message ("Please answer yes or no.");
- Fsleep_for (make_number (2), Qnil);
- }
-}
-
-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.\n\
-If the 5-minute or 15-minute load averages are not available, return a\n\
-shortened list, containing only those averages which are available.")
- ()
-{
- double load_ave[3];
- int loads = getloadavg (load_ave, 3);
- Lisp_Object ret;
-
- if (loads < 0)
- error ("load-average not implemented for this operating system");
-
- ret = Qnil;
- while (loads > 0)
- ret = Fcons (make_number ((int) (load_ave[--loads] * 100.0)), ret);
-
- return ret;
-}
-
-Lisp_Object Vfeatures;
-
-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'.")
- (feature)
- Lisp_Object feature;
-{
- register Lisp_Object tem;
- CHECK_SYMBOL (feature, 0);
- tem = Fmemq (feature, Vfeatures);
- return (NILP (tem)) ? Qnil : Qt;
-}
-
-DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
- "Announce that FEATURE is a feature of the current Emacs.")
- (feature)
- Lisp_Object feature;
-{
- register Lisp_Object tem;
- CHECK_SYMBOL (feature, 0);
- if (!NILP (Vautoload_queue))
- Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
- tem = Fmemq (feature, Vfeatures);
- if (NILP (tem))
- Vfeatures = Fcons (feature, Vfeatures);
- LOADHIST_ATTACH (Fcons (Qprovide, feature));
- return feature;
-}
-
-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.")
- (feature, file_name)
- Lisp_Object feature, file_name;
-{
- register Lisp_Object tem;
- CHECK_SYMBOL (feature, 0);
- tem = Fmemq (feature, Vfeatures);
- LOADHIST_ATTACH (Fcons (Qrequire, feature));
- if (NILP (tem))
- {
- int count = specpdl_ptr - specpdl;
-
- /* Value saved here is to be restored into Vautoload_queue */
- record_unwind_protect (un_autoload, Vautoload_queue);
- Vautoload_queue = Qt;
-
- Fload (NILP (file_name) ? Fsymbol_name (feature) : file_name,
- Qnil, Qt, Qnil);
-
- tem = Fmemq (feature, Vfeatures);
- if (NILP (tem))
- error ("Required feature %s was not provided",
- XSYMBOL (feature)->name->data );
-
- /* Once loading finishes, don't undo it. */
- Vautoload_queue = Qt;
- feature = unbind_to (count, feature);
- }
- return feature;
-}
-
-syms_of_fns ()
-{
- Qstring_lessp = intern ("string-lessp");
- staticpro (&Qstring_lessp);
- Qprovide = intern ("provide");
- staticpro (&Qprovide);
- Qrequire = intern ("require");
- staticpro (&Qrequire);
- Qyes_or_no_p_history = intern ("yes-or-no-p-history");
- staticpro (&Qyes_or_no_p_history);
- Qcursor_in_echo_area = intern ("cursor-in-echo-area");
- staticpro (&Qcursor_in_echo_area);
-
- Fset (Qyes_or_no_p_history, Qnil);
-
- 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'.");
- Vfeatures = Qnil;
-
- defsubr (&Sidentity);
- defsubr (&Srandom);
- defsubr (&Slength);
- defsubr (&Ssafe_length);
- defsubr (&Sstring_equal);
- defsubr (&Sstring_lessp);
- defsubr (&Sappend);
- defsubr (&Sconcat);
- defsubr (&Svconcat);
- defsubr (&Scopy_sequence);
- defsubr (&Scopy_alist);
- defsubr (&Ssubstring);
- defsubr (&Snthcdr);
- defsubr (&Snth);
- defsubr (&Selt);
- defsubr (&Smember);
- defsubr (&Smemq);
- defsubr (&Sassq);
- defsubr (&Sassoc);
- defsubr (&Srassq);
- defsubr (&Srassoc);
- defsubr (&Sdelq);
- defsubr (&Sdelete);
- defsubr (&Snreverse);
- defsubr (&Sreverse);
- defsubr (&Ssort);
- defsubr (&Splist_get);
- defsubr (&Sget);
- defsubr (&Splist_put);
- defsubr (&Sput);
- defsubr (&Sequal);
- defsubr (&Sfillarray);
- defsubr (&Schar_table_subtype);
- defsubr (&Schar_table_parent);
- defsubr (&Sset_char_table_parent);
- defsubr (&Schar_table_extra_slot);
- defsubr (&Sset_char_table_extra_slot);
- defsubr (&Schar_table_range);
- defsubr (&Sset_char_table_range);
- defsubr (&Smap_char_table);
- defsubr (&Snconc);
- defsubr (&Smapcar);
- defsubr (&Smapconcat);
- defsubr (&Sy_or_n_p);
- defsubr (&Syes_or_no_p);
- defsubr (&Sload_average);
- defsubr (&Sfeaturep);
- defsubr (&Srequire);
- defsubr (&Sprovide);
-}
diff --git a/src/frame.c b/src/frame.c
deleted file mode 100644
index 937336c4873..00000000000
--- a/src/frame.c
+++ /dev/null
@@ -1,2153 +0,0 @@
-/* Generic frame functions.
- Copyright (C) 1993, 1994, 1995 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include <config.h>
-
-#include <stdio.h>
-#include "lisp.h"
-#include "frame.h"
-#include "termhooks.h"
-#include "window.h"
-#ifdef MSDOS
-#include "msdos.h"
-#endif
-
-/* Evaluate this expression to rebuild the section of syms_of_frame
- that initializes and staticpros the symbols declared below. Note
- that Emacs 18 has a bug that keeps C-x C-e from being able to
- evaluate this expression.
-
-(progn
- ;; Accumulate a list of the symbols we want to initialize from the
- ;; declarations at the top of the file.
- (goto-char (point-min))
- (search-forward "/\*&&& symbols declared here &&&*\/\n")
- (let (symbol-list)
- (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
- (setq symbol-list
- (cons (buffer-substring (match-beginning 1) (match-end 1))
- symbol-list))
- (forward-line 1))
- (setq symbol-list (nreverse symbol-list))
- ;; Delete the section of syms_of_... where we initialize the symbols.
- (search-forward "\n /\*&&& init symbols here &&&*\/\n")
- (let ((start (point)))
- (while (looking-at "^ Q")
- (forward-line 2))
- (kill-region start (point)))
- ;; Write a new symbol initialization section.
- (while symbol-list
- (insert (format " %s = intern (\"" (car symbol-list)))
- (let ((start (point)))
- (insert (substring (car symbol-list) 1))
- (subst-char-in-region start (point) ?_ ?-))
- (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
- (setq symbol-list (cdr symbol-list)))))
- */
-
-/*&&& symbols declared here &&&*/
-Lisp_Object Qframep;
-Lisp_Object Qframe_live_p;
-Lisp_Object Qheight;
-Lisp_Object Qicon;
-Lisp_Object Qminibuffer;
-Lisp_Object Qmodeline;
-Lisp_Object Qname;
-Lisp_Object Qonly;
-Lisp_Object Qunsplittable;
-Lisp_Object Qmenu_bar_lines;
-Lisp_Object Qwidth;
-Lisp_Object Qx;
-Lisp_Object Qw32;
-Lisp_Object Qpc;
-Lisp_Object Qvisible;
-Lisp_Object Qbuffer_predicate;
-Lisp_Object Qtitle;
-
-Lisp_Object Vterminal_frame;
-Lisp_Object Vdefault_frame_alist;
-
-static void
-syms_of_frame_1 ()
-{
- /*&&& init symbols here &&&*/
- Qframep = intern ("framep");
- staticpro (&Qframep);
- Qframe_live_p = intern ("frame-live-p");
- staticpro (&Qframe_live_p);
- Qheight = intern ("height");
- staticpro (&Qheight);
- Qicon = intern ("icon");
- staticpro (&Qicon);
- Qminibuffer = intern ("minibuffer");
- staticpro (&Qminibuffer);
- Qmodeline = intern ("modeline");
- staticpro (&Qmodeline);
- Qname = intern ("name");
- staticpro (&Qname);
- Qonly = intern ("only");
- staticpro (&Qonly);
- Qunsplittable = intern ("unsplittable");
- staticpro (&Qunsplittable);
- Qmenu_bar_lines = intern ("menu-bar-lines");
- staticpro (&Qmenu_bar_lines);
- Qwidth = intern ("width");
- staticpro (&Qwidth);
- Qx = intern ("x");
- staticpro (&Qx);
- Qw32 = intern ("w32");
- staticpro (&Qw32);
- Qpc = intern ("pc");
- staticpro (&Qpc);
- Qvisible = intern ("visible");
- staticpro (&Qvisible);
- Qbuffer_predicate = intern ("buffer-predicate");
- staticpro (&Qbuffer_predicate);
- Qtitle = intern ("title");
- staticpro (&Qtitle);
-
- DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
- "Alist of default values for frame creation.\n\
-These may be set in your init file, like this:\n\
- (setq default-frame-alist '((width . 80) (height . 55) (menu-bar-lines . 1))\n\
-These override values given in window system configuration data,\n\
- including X Windows' defaults database.\n\
-For values specific to the first Emacs frame, see `initial-frame-alist'.\n\
-For values specific to the separate minibuffer frame, see\n\
- `minibuffer-frame-alist'.\n\
-The `menu-bar-lines' element of the list controls whether new frames\n\
- have menu bars; `menu-bar-mode' works by altering this element.");
- Vdefault_frame_alist = Qnil;
-}
-
-static void
-set_menu_bar_lines_1 (window, n)
- Lisp_Object window;
- int n;
-{
- struct window *w = XWINDOW (window);
-
- XSETFASTINT (w->last_modified, 0);
- XSETFASTINT (w->top, XFASTINT (w->top) + n);
- XSETFASTINT (w->height, XFASTINT (w->height) - n);
-
- /* Handle just the top child in a vertical split. */
- if (!NILP (w->vchild))
- set_menu_bar_lines_1 (w->vchild, n);
-
- /* Adjust all children in a horizontal split. */
- for (window = w->hchild; !NILP (window); window = w->next)
- {
- w = XWINDOW (window);
- set_menu_bar_lines_1 (window, n);
- }
-}
-
-static void
-set_menu_bar_lines (f, value, oldval)
- struct frame *f;
- Lisp_Object value, oldval;
-{
- int nlines;
- int olines = FRAME_MENU_BAR_LINES (f);
-
- /* Right now, menu bars don't work properly in minibuf-only frames;
- most of the commands try to apply themselves to the minibuffer
- frame itself, and get an error because you can't switch buffers
- in or split the minibuffer window. */
- if (FRAME_MINIBUF_ONLY_P (f))
- return;
-
- if (INTEGERP (value))
- nlines = XINT (value);
- else
- nlines = 0;
-
- if (nlines != olines)
- {
- windows_or_buffers_changed++;
- FRAME_WINDOW_SIZES_CHANGED (f) = 1;
- FRAME_MENU_BAR_LINES (f) = nlines;
- set_menu_bar_lines_1 (f->root_window, nlines - olines);
- }
-}
-
-#include "buffer.h"
-
-/* These help us bind and responding to switch-frame events. */
-#include "commands.h"
-#include "keyboard.h"
-
-Lisp_Object Vemacs_iconified;
-Lisp_Object Vframe_list;
-
-extern Lisp_Object Vminibuffer_list;
-extern Lisp_Object get_minibuffer ();
-extern Lisp_Object Fhandle_switch_frame ();
-extern Lisp_Object Fredirect_frame_focus ();
-extern Lisp_Object x_get_focus_frame ();
-
-DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
- "Return non-nil if OBJECT is a frame.\n\
-Value is t for a termcap frame (a character-only terminal),\n\
-`x' for an Emacs frame that is really an X window,\n\
-`pc' for a direct-write MS-DOS frame.\n\
-See also `frame-live-p'.")
- (object)
- Lisp_Object object;
-{
- if (!FRAMEP (object))
- return Qnil;
- switch (XFRAME (object)->output_method)
- {
- case output_termcap:
- return Qt;
- case output_x_window:
- return Qx;
- case output_w32:
- return Qw32;
- case output_msdos_raw:
- return Qpc;
- default:
- abort ();
- }
-}
-
-DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
- "Return non-nil if OBJECT is a frame which has not been deleted.\n\
-Value is nil if OBJECT is not a live frame. If object is a live\n\
-frame, the return value indicates what sort of output device it is\n\
-displayed on. Value is t for a termcap frame (a character-only\n\
-terminal), `x' for an Emacs frame being displayed in an X window.")
- (object)
- Lisp_Object object;
-{
- return ((FRAMEP (object)
- && FRAME_LIVE_P (XFRAME (object)))
- ? Fframep (object)
- : Qnil);
-}
-
-struct frame *
-make_frame (mini_p)
- int mini_p;
-{
- Lisp_Object frame;
- register struct frame *f;
- register Lisp_Object root_window;
- register Lisp_Object mini_window;
- register struct Lisp_Vector *vec;
- int i;
-
- vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct frame));
- for (i = 0; i < VECSIZE (struct frame); i++)
- XSETFASTINT (vec->contents[i], 0);
- vec->size = VECSIZE (struct frame);
- f = (struct frame *)vec;
- XSETFRAME (frame, f);
-
- f->cursor_x = 0;
- f->cursor_y = 0;
- f->current_glyphs = 0;
- f->desired_glyphs = 0;
- f->visible = 0;
- f->async_visible = 0;
- f->output_data.nothing = 0;
- f->iconified = 0;
- f->async_iconified = 0;
- f->wants_modeline = 1;
- f->auto_raise = 0;
- f->auto_lower = 0;
- f->no_split = 0;
- f->garbaged = 0;
- f->has_minibuffer = mini_p;
- f->focus_frame = Qnil;
- f->explicit_name = 0;
- f->can_have_scroll_bars = 0;
- f->vertical_scroll_bar_type = vertical_scroll_bar_none;
- f->param_alist = Qnil;
- f->scroll_bars = Qnil;
- f->condemned_scroll_bars = Qnil;
- f->face_alist = Qnil;
- f->menu_bar_items = Qnil;
- f->menu_bar_vector = Qnil;
- f->menu_bar_items_used = 0;
- f->buffer_predicate = Qnil;
-#ifdef MULTI_KBOARD
- f->kboard = initial_kboard;
-#endif
- f->namebuf = 0;
- f->title = Qnil;
-
- root_window = make_window ();
- if (mini_p)
- {
- mini_window = make_window ();
- XWINDOW (root_window)->next = mini_window;
- XWINDOW (mini_window)->prev = root_window;
- XWINDOW (mini_window)->mini_p = Qt;
- XWINDOW (mini_window)->frame = frame;
- f->minibuffer_window = mini_window;
- }
- else
- {
- mini_window = Qnil;
- XWINDOW (root_window)->next = Qnil;
- f->minibuffer_window = Qnil;
- }
-
- XWINDOW (root_window)->frame = frame;
-
- /* 10 is arbitrary,
- just so that there is "something there."
- Correct size will be set up later with change_frame_size. */
-
- SET_FRAME_WIDTH (f, 10);
- f->height = 10;
-
- XSETFASTINT (XWINDOW (root_window)->width, 10);
- XSETFASTINT (XWINDOW (root_window)->height, (mini_p ? 9 : 10));
-
- if (mini_p)
- {
- XSETFASTINT (XWINDOW (mini_window)->width, 10);
- XSETFASTINT (XWINDOW (mini_window)->top, 9);
- XSETFASTINT (XWINDOW (mini_window)->height, 1);
- }
-
- /* Choose a buffer for the frame's root window. */
- {
- Lisp_Object buf;
-
- XWINDOW (root_window)->buffer = Qt;
- buf = Fcurrent_buffer ();
- /* If buf is a 'hidden' buffer (i.e. one whose name starts with
- a space), try to find another one. */
- if (XSTRING (Fbuffer_name (buf))->data[0] == ' ')
- buf = Fother_buffer (buf, Qnil);
- Fset_window_buffer (root_window, buf);
- }
-
- if (mini_p)
- {
- XWINDOW (mini_window)->buffer = Qt;
- Fset_window_buffer (mini_window,
- (NILP (Vminibuffer_list)
- ? get_minibuffer (0)
- : Fcar (Vminibuffer_list)));
- }
-
- f->root_window = root_window;
- f->selected_window = root_window;
- /* Make sure this window seems more recently used than
- a newly-created, never-selected window. */
- XSETFASTINT (XWINDOW (f->selected_window)->use_time, ++window_select_count);
-
- return f;
-}
-
-/* Make a frame using a separate minibuffer window on another frame.
- MINI_WINDOW is the minibuffer window to use. nil means use the
- default (the global minibuffer). */
-
-struct frame *
-make_frame_without_minibuffer (mini_window, kb, display)
- register Lisp_Object mini_window;
- KBOARD *kb;
- Lisp_Object display;
-{
- register struct frame *f;
- struct gcpro gcpro1;
-
- if (!NILP (mini_window))
- CHECK_LIVE_WINDOW (mini_window, 0);
-
-#ifdef MULTI_KBOARD
- if (!NILP (mini_window)
- && XFRAME (XWINDOW (mini_window)->frame)->kboard != kb)
- error ("frame and minibuffer must be on the same display");
-#endif
-
- /* Make a frame containing just a root window. */
- f = make_frame (0);
-
- if (NILP (mini_window))
- {
- /* Use default-minibuffer-frame if possible. */
- if (!FRAMEP (kb->Vdefault_minibuffer_frame)
- || ! FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame)))
- {
- Lisp_Object frame_dummy;
-
- XSETFRAME (frame_dummy, f);
- GCPRO1 (frame_dummy);
- /* If there's no minibuffer frame to use, create one. */
- kb->Vdefault_minibuffer_frame =
- call1 (intern ("make-initial-minibuffer-frame"), display);
- UNGCPRO;
- }
-
- mini_window = XFRAME (kb->Vdefault_minibuffer_frame)->minibuffer_window;
- }
-
- f->minibuffer_window = mini_window;
-
- /* Make the chosen minibuffer window display the proper minibuffer,
- unless it is already showing a minibuffer. */
- if (NILP (Fmemq (XWINDOW (mini_window)->buffer, Vminibuffer_list)))
- Fset_window_buffer (mini_window,
- (NILP (Vminibuffer_list)
- ? get_minibuffer (0)
- : Fcar (Vminibuffer_list)));
- return f;
-}
-
-/* Make a frame containing only a minibuffer window. */
-
-struct frame *
-make_minibuffer_frame ()
-{
- /* First make a frame containing just a root window, no minibuffer. */
-
- register struct frame *f = make_frame (0);
- register Lisp_Object mini_window;
- register Lisp_Object frame;
-
- XSETFRAME (frame, f);
-
- f->auto_raise = 0;
- f->auto_lower = 0;
- f->no_split = 1;
- f->wants_modeline = 0;
- f->has_minibuffer = 1;
-
- /* Now label the root window as also being the minibuffer.
- Avoid infinite looping on the window chain by marking next pointer
- as nil. */
-
- mini_window = f->minibuffer_window = f->root_window;
- XWINDOW (mini_window)->mini_p = Qt;
- XWINDOW (mini_window)->next = Qnil;
- XWINDOW (mini_window)->prev = Qnil;
- XWINDOW (mini_window)->frame = frame;
-
- /* Put the proper buffer in that window. */
-
- Fset_window_buffer (mini_window,
- (NILP (Vminibuffer_list)
- ? get_minibuffer (0)
- : Fcar (Vminibuffer_list)));
- return f;
-}
-
-/* Construct a frame that refers to the terminal (stdin and stdout). */
-
-static int terminal_frame_count;
-
-struct frame *
-make_terminal_frame ()
-{
- register struct frame *f;
- Lisp_Object frame;
- char name[20];
-
-#ifdef MULTI_KBOARD
- if (!initial_kboard)
- {
- initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
- init_kboard (initial_kboard);
- initial_kboard->next_kboard = all_kboards;
- all_kboards = initial_kboard;
- }
-#endif
-
- /* The first call must initialize Vframe_list. */
- if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
- Vframe_list = Qnil;
-
- f = make_frame (1);
-
- XSETFRAME (frame, f);
- Vframe_list = Fcons (frame, Vframe_list);
-
- terminal_frame_count++;
- if (terminal_frame_count == 1)
- {
- f->name = build_string ("Emacs");
- }
- else
- {
- sprintf (name, "Emacs-%d", terminal_frame_count);
- f->name = build_string (name);
- }
-
- f->visible = 1; /* FRAME_SET_VISIBLE wd set frame_garbaged. */
- f->async_visible = 1; /* Don't let visible be cleared later. */
-#ifdef MSDOS
- f->output_data.x = &the_only_x_display;
- f->output_method = output_msdos_raw;
- init_frame_faces (f);
-#else /* not MSDOS */
- f->output_data.nothing = 1; /* Nonzero means frame isn't deleted. */
-#endif
- return f;
-}
-
-DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
- 1, 1, 0, "Create an additional terminal frame.\n\
-You can create multiple frames on a text-only terminal in this way.\n\
-Only the selected terminal frame is actually displayed.\n\
-This function takes one argument, an alist specifying frame parameters.\n\
-In practice, generally you don't need to specify any parameters.\n\
-Note that changing the size of one terminal frame automatically affects all.")
- (parms)
- Lisp_Object parms;
-{
- struct frame *f;
- Lisp_Object frame;
-
-#ifdef MSDOS
- if (selected_frame->output_method != output_msdos_raw)
- abort ();
-#else
- if (selected_frame->output_method != output_termcap)
- error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
-#endif
-
- f = make_terminal_frame ();
- change_frame_size (f, FRAME_HEIGHT (selected_frame),
- FRAME_WIDTH (selected_frame), 0, 0);
- remake_frame_glyphs (f);
- calculate_costs (f);
- XSETFRAME (frame, f);
- Fmodify_frame_parameters (frame, Vdefault_frame_alist);
- Fmodify_frame_parameters (frame, parms);
- f->face_alist = selected_frame->face_alist;
- return frame;
-}
-
-Lisp_Object
-do_switch_frame (frame, no_enter, track)
- Lisp_Object frame, no_enter;
- int track;
-{
- /* If FRAME is a switch-frame event, extract the frame we should
- switch to. */
- if (CONSP (frame)
- && EQ (XCONS (frame)->car, Qswitch_frame)
- && CONSP (XCONS (frame)->cdr))
- frame = XCONS (XCONS (frame)->cdr)->car;
-
- /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
- a switch-frame event to arrive after a frame is no longer live,
- especially when deleting the initial frame during startup. */
- CHECK_FRAME (frame, 0);
- if (! FRAME_LIVE_P (XFRAME (frame)))
- return Qnil;
-
- if (selected_frame == XFRAME (frame))
- return frame;
-
- /* This is too greedy; it causes inappropriate focus redirection
- that's hard to get rid of. */
-#if 0
- /* If a frame's focus has been redirected toward the currently
- selected frame, we should change the redirection to point to the
- newly selected frame. This means that if the focus is redirected
- from a minibufferless frame to a surrogate minibuffer frame, we
- can use `other-window' to switch between all the frames using
- that minibuffer frame, and the focus redirection will follow us
- around. */
- if (track)
- {
- Lisp_Object tail;
-
- for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- Lisp_Object focus;
-
- if (!FRAMEP (XCONS (tail)->car))
- abort ();
-
- focus = FRAME_FOCUS_FRAME (XFRAME (XCONS (tail)->car));
-
- if (FRAMEP (focus) && XFRAME (focus) == selected_frame)
- Fredirect_frame_focus (XCONS (tail)->car, frame);
- }
- }
-#else /* ! 0 */
- /* Instead, apply it only to the frame we're pointing to. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (track && (FRAME_WINDOW_P (XFRAME (frame))))
- {
- Lisp_Object focus, xfocus;
-
- xfocus = x_get_focus_frame (XFRAME (frame));
- if (FRAMEP (xfocus))
- {
- focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
- if (FRAMEP (focus) && XFRAME (focus) == selected_frame)
- Fredirect_frame_focus (xfocus, frame);
- }
- }
-#endif /* HAVE_X_WINDOWS */
-#endif /* ! 0 */
-
- selected_frame = XFRAME (frame);
- if (! FRAME_MINIBUF_ONLY_P (selected_frame))
- last_nonminibuf_frame = selected_frame;
-
- Fselect_window (XFRAME (frame)->selected_window);
-
- /* We want to make sure that the next event generates a frame-switch
- event to the appropriate frame. This seems kludgy to me, but
- before you take it out, make sure that evaluating something like
- (select-window (frame-root-window (new-frame))) doesn't end up
- with your typing being interpreted in the new frame instead of
- the one you're actually typing in. */
- internal_last_event_frame = Qnil;
-
- return frame;
-}
-
-DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
- "Select the frame FRAME.\n\
-Subsequent editing commands apply to its selected window.\n\
-The selection of FRAME lasts until the next time the user does\n\
-something to select a different frame, or until the next time this\n\
-function is called.")
- (frame, no_enter)
- Lisp_Object frame, no_enter;
-{
- return do_switch_frame (frame, no_enter, 1);
-}
-
-
-DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 2, "e",
- "Handle a switch-frame event EVENT.\n\
-Switch-frame events are usually bound to this function.\n\
-A switch-frame event tells Emacs that the window manager has requested\n\
-that the user's events be directed to the frame mentioned in the event.\n\
-This function selects the selected window of the frame of EVENT.\n\
-\n\
-If EVENT is frame object, handle it as if it were a switch-frame event\n\
-to that frame.")
- (event, no_enter)
- Lisp_Object event, no_enter;
-{
- /* Preserve prefix arg that the command loop just cleared. */
- current_kboard->Vprefix_arg = Vcurrent_prefix_arg;
- call1 (Vrun_hooks, Qmouse_leave_buffer_hook);
- return do_switch_frame (event, no_enter, 0);
-}
-
-DEFUN ("ignore-event", Fignore_event, Signore_event, 0, 0, "",
- "Do nothing, but preserve any prefix argument already specified.\n\
-This is a suitable binding for iconify-frame and make-frame-visible.")
- ()
-{
- current_kboard->Vprefix_arg = Vcurrent_prefix_arg;
- return Qnil;
-}
-
-DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
- "Return the frame that is now selected.")
- ()
-{
- Lisp_Object tem;
- XSETFRAME (tem, selected_frame);
- return tem;
-}
-
-DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
- "Return the frame object that window WINDOW is on.")
- (window)
- Lisp_Object window;
-{
- CHECK_LIVE_WINDOW (window, 0);
- return XWINDOW (window)->frame;
-}
-
-DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
- "Returns the topmost, leftmost window of FRAME.\n\
-If omitted, FRAME defaults to the currently selected frame.")
- (frame)
- Lisp_Object frame;
-{
- Lisp_Object w;
-
- if (NILP (frame))
- w = selected_frame->root_window;
- else
- {
- CHECK_LIVE_FRAME (frame, 0);
- w = XFRAME (frame)->root_window;
- }
- while (NILP (XWINDOW (w)->buffer))
- {
- if (! NILP (XWINDOW (w)->hchild))
- w = XWINDOW (w)->hchild;
- else if (! NILP (XWINDOW (w)->vchild))
- w = XWINDOW (w)->vchild;
- else
- abort ();
- }
- return w;
-}
-
-DEFUN ("active-minibuffer-window", Factive_minibuffer_window,
- Sactive_minibuffer_window, 0, 0, 0,
- "Return the currently active minibuffer window, or nil if none.")
- ()
-{
- return minibuf_level ? minibuf_window : Qnil;
-}
-
-DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
- "Returns the root-window of FRAME.\n\
-If omitted, FRAME defaults to the currently selected frame.")
- (frame)
- Lisp_Object frame;
-{
- if (NILP (frame))
- XSETFRAME (frame, selected_frame);
- else
- CHECK_LIVE_FRAME (frame, 0);
-
- return XFRAME (frame)->root_window;
-}
-
-DEFUN ("frame-selected-window", Fframe_selected_window,
- Sframe_selected_window, 0, 1, 0,
- "Return the selected window of frame object FRAME.\n\
-If omitted, FRAME defaults to the currently selected frame.")
- (frame)
- Lisp_Object frame;
-{
- if (NILP (frame))
- XSETFRAME (frame, selected_frame);
- else
- CHECK_LIVE_FRAME (frame, 0);
-
- return XFRAME (frame)->selected_window;
-}
-
-DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
- Sset_frame_selected_window, 2, 2, 0,
- "Set the selected window of frame object FRAME to WINDOW.\n\
-If FRAME is nil, the selected frame is used.\n\
-If FRAME is the selected frame, this makes WINDOW the selected window.")
- (frame, window)
- Lisp_Object frame, window;
-{
- if (NILP (frame))
- XSETFRAME (frame, selected_frame);
- else
- CHECK_LIVE_FRAME (frame, 0);
-
- CHECK_LIVE_WINDOW (window, 1);
-
- if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
- error ("In `set-frame-selected-window', WINDOW is not on FRAME");
-
- if (XFRAME (frame) == selected_frame)
- return Fselect_window (window);
-
- return XFRAME (frame)->selected_window = window;
-}
-
-DEFUN ("frame-list", Fframe_list, Sframe_list,
- 0, 0, 0,
- "Return a list of all frames.")
- ()
-{
- return Fcopy_sequence (Vframe_list);
-}
-
-/* Return the next frame in the frame list after FRAME.
- If MINIBUF is nil, exclude minibuffer-only frames.
- If MINIBUF is a window, include only its own frame
- and any frame now using that window as the minibuffer.
- If MINIBUF is `visible', include all visible frames.
- If MINIBUF is 0, include all visible and iconified frames.
- Otherwise, include all frames. */
-
-Lisp_Object
-next_frame (frame, minibuf)
- Lisp_Object frame;
- Lisp_Object minibuf;
-{
- Lisp_Object tail;
- int passed = 0;
-
- /* There must always be at least one frame in Vframe_list. */
- if (! CONSP (Vframe_list))
- abort ();
-
- /* If this frame is dead, it won't be in Vframe_list, and we'll loop
- forever. Forestall that. */
- CHECK_LIVE_FRAME (frame, 0);
-
- while (1)
- for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- Lisp_Object f;
-
- f = XCONS (tail)->car;
-
- if (passed
- && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
- {
- /* Decide whether this frame is eligible to be returned. */
-
- /* If we've looped all the way around without finding any
- eligible frames, return the original frame. */
- if (EQ (f, frame))
- return f;
-
- /* Let minibuf decide if this frame is acceptable. */
- if (NILP (minibuf))
- {
- if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
- return f;
- }
- else if (EQ (minibuf, Qvisible))
- {
- FRAME_SAMPLE_VISIBILITY (XFRAME (f));
- if (FRAME_VISIBLE_P (XFRAME (f)))
- return f;
- }
- else if (XFASTINT (minibuf) == 0)
- {
- FRAME_SAMPLE_VISIBILITY (XFRAME (f));
- if (FRAME_VISIBLE_P (XFRAME (f))
- || FRAME_ICONIFIED_P (XFRAME (f)))
- return f;
- }
- else if (WINDOWP (minibuf))
- {
- if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
- /* Check that F either is, or has forwarded its focus to,
- MINIBUF's frame. */
- && (EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
- || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
- FRAME_FOCUS_FRAME (XFRAME (f)))))
- return f;
- }
- else
- return f;
- }
-
- if (EQ (frame, f))
- passed++;
- }
-}
-
-/* Return the previous frame in the frame list before FRAME.
- If MINIBUF is nil, exclude minibuffer-only frames.
- If MINIBUF is a window, include only its own frame
- and any frame now using that window as the minibuffer.
- If MINIBUF is `visible', include all visible frames.
- If MINIBUF is 0, include all visible and iconified frames.
- Otherwise, include all frames. */
-
-Lisp_Object
-prev_frame (frame, minibuf)
- Lisp_Object frame;
- Lisp_Object minibuf;
-{
- Lisp_Object tail;
- Lisp_Object prev;
-
- /* There must always be at least one frame in Vframe_list. */
- if (! CONSP (Vframe_list))
- abort ();
-
- prev = Qnil;
- for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- Lisp_Object f;
-
- f = XCONS (tail)->car;
- if (!FRAMEP (f))
- abort ();
-
- if (EQ (frame, f) && !NILP (prev))
- return prev;
-
- if (FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
- {
- /* Decide whether this frame is eligible to be returned,
- according to minibuf. */
- if (NILP (minibuf))
- {
- if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
- prev = f;
- }
- else if (WINDOWP (minibuf))
- {
- if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
- /* Check that F either is, or has forwarded its focus to,
- MINIBUF's frame. */
- && (EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
- || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
- FRAME_FOCUS_FRAME (XFRAME (f)))))
- prev = f;
- }
- else if (EQ (minibuf, Qvisible))
- {
- FRAME_SAMPLE_VISIBILITY (XFRAME (f));
- if (FRAME_VISIBLE_P (XFRAME (f)))
- prev = f;
- }
- else if (XFASTINT (minibuf) == 0)
- {
- FRAME_SAMPLE_VISIBILITY (XFRAME (f));
- if (FRAME_VISIBLE_P (XFRAME (f))
- || FRAME_ICONIFIED_P (XFRAME (f)))
- prev = f;
- }
- else
- prev = f;
- }
- }
-
- /* We've scanned the entire list. */
- if (NILP (prev))
- /* We went through the whole frame list without finding a single
- acceptable frame. Return the original frame. */
- return frame;
- else
- /* There were no acceptable frames in the list before FRAME; otherwise,
- we would have returned directly from the loop. Since PREV is the last
- acceptable frame in the list, return it. */
- return prev;
-}
-
-
-DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
- "Return the next frame in the frame list after FRAME.\n\
-It considers only frames on the same terminal as FRAME.\n\
-By default, skip minibuffer-only frames.\n\
-If omitted, FRAME defaults to the selected frame.\n\
-If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
-If MINIFRAME is a window, include only its own frame\n\
-and any frame now using that window as the minibuffer.\n\
-If MINIFRAME is `visible', include all visible frames.\n\
-If MINIFRAME is 0, include all visible and iconified frames.\n\
-Otherwise, include all frames.")
- (frame, miniframe)
- Lisp_Object frame, miniframe;
-{
- Lisp_Object tail;
-
- if (NILP (frame))
- XSETFRAME (frame, selected_frame);
- else
- CHECK_LIVE_FRAME (frame, 0);
-
- return next_frame (frame, miniframe);
-}
-
-DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
- "Return the previous frame in the frame list before FRAME.\n\
-It considers only frames on the same terminal as FRAME.\n\
-By default, skip minibuffer-only frames.\n\
-If omitted, FRAME defaults to the selected frame.\n\
-If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
-If MINIFRAME is a window, include only its own frame\n\
-and any frame now using that window as the minibuffer.\n\
-If MINIFRAME is `visible', include all visible frames.\n\
-If MINIFRAME is 0, include all visible and iconified frames.\n\
-Otherwise, include all frames.")
- (frame, miniframe)
- Lisp_Object frame, miniframe;
-{
- Lisp_Object tail;
-
- if (NILP (frame))
- XSETFRAME (frame, selected_frame);
- else
- CHECK_LIVE_FRAME (frame, 0);
-
- return prev_frame (frame, miniframe);
-}
-
-/* Return 1 if it is ok to delete frame F;
- 0 if all frames aside from F are invisible.
- (Exception: if F is the terminal frame, and we are using X, return 1.) */
-
-int
-other_visible_frames (f)
- FRAME_PTR f;
-{
- /* We know the selected frame is visible,
- so if F is some other frame, it can't be the sole visible one. */
- if (f == selected_frame)
- {
- Lisp_Object frames;
- int count = 0;
-
- for (frames = Vframe_list;
- CONSP (frames);
- frames = XCONS (frames)->cdr)
- {
- Lisp_Object this;
-
- this = XCONS (frames)->car;
- /* Verify that the frame's window still exists
- and we can still talk to it. And note any recent change
- in visibility. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (XFRAME (this)))
- {
- x_sync (XFRAME (this));
- FRAME_SAMPLE_VISIBILITY (XFRAME (this));
- }
-#endif
-
- if (FRAME_VISIBLE_P (XFRAME (this))
- || FRAME_ICONIFIED_P (XFRAME (this))
- /* Allow deleting the terminal frame when at least
- one X frame exists! */
- || (FRAME_WINDOW_P (XFRAME (this)) && !FRAME_WINDOW_P (f)))
- count++;
- }
- return count > 1;
- }
- return 1;
-}
-
-DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
- "Delete FRAME, permanently eliminating it from use.\n\
-If omitted, FRAME defaults to the selected frame.\n\
-A frame may not be deleted if its minibuffer is used by other frames.\n\
-Normally, you may not delete a frame if all other frames are invisible,\n\
-but if the second optional argument FORCE is non-nil, you may do so.")
- (frame, force)
- Lisp_Object frame, force;
-{
- struct frame *f;
- int minibuffer_selected;
-
- if (EQ (frame, Qnil))
- {
- f = selected_frame;
- XSETFRAME (frame, f);
- }
- else
- {
- CHECK_FRAME (frame, 0);
- f = XFRAME (frame);
- }
-
- if (! FRAME_LIVE_P (f))
- return Qnil;
-
- if (NILP (force) && !other_visible_frames (f))
- error ("Attempt to delete the sole visible or iconified frame");
-
- /* Does this frame have a minibuffer, and is it the surrogate
- minibuffer for any other frame? */
- if (FRAME_HAS_MINIBUF_P (XFRAME (frame)))
- {
- Lisp_Object frames;
-
- for (frames = Vframe_list;
- CONSP (frames);
- frames = XCONS (frames)->cdr)
- {
- Lisp_Object this;
- this = XCONS (frames)->car;
-
- if (! EQ (this, frame)
- && EQ (frame,
- WINDOW_FRAME (XWINDOW
- (FRAME_MINIBUF_WINDOW (XFRAME (this))))))
- error ("Attempt to delete a surrogate minibuffer frame");
- }
- }
-
- minibuffer_selected = EQ (minibuf_window, selected_window);
-
- /* Don't let the frame remain selected. */
- if (f == selected_frame)
- {
- Lisp_Object tail, frame1;
-
- /* Look for another visible frame on the same terminal. */
- frame1 = next_frame (frame, Qvisible);
-
- /* If there is none, find *some* other frame. */
- if (NILP (frame1) || EQ (frame1, frame))
- {
- FOR_EACH_FRAME (tail, frame1)
- {
- if (! EQ (frame, frame1))
- break;
- }
- }
-
- do_switch_frame (frame1, Qnil, 0);
- }
-
- /* Don't allow minibuf_window to remain on a deleted frame. */
- if (EQ (f->minibuffer_window, minibuf_window))
- {
- Fset_window_buffer (selected_frame->minibuffer_window,
- XWINDOW (minibuf_window)->buffer);
- minibuf_window = selected_frame->minibuffer_window;
-
- /* If the dying minibuffer window was selected,
- select the new one. */
- if (minibuffer_selected)
- Fselect_window (minibuf_window);
- }
-
- /* Clear any X selections for this frame. */
-#ifdef HAVE_X_WINDOWS
- if (FRAME_X_P (f))
- x_clear_frame_selections (f);
-#endif
-
- /* Mark all the windows that used to be on FRAME as deleted, and then
- remove the reference to them. */
- delete_all_subwindows (XWINDOW (f->root_window));
- f->root_window = Qnil;
-
- Vframe_list = Fdelq (frame, Vframe_list);
- FRAME_SET_VISIBLE (f, 0);
-
- if (f->namebuf)
- free (f->namebuf);
- if (FRAME_CURRENT_GLYPHS (f))
- free_frame_glyphs (f, FRAME_CURRENT_GLYPHS (f));
- if (FRAME_DESIRED_GLYPHS (f))
- free_frame_glyphs (f, FRAME_DESIRED_GLYPHS (f));
- if (FRAME_TEMP_GLYPHS (f))
- free_frame_glyphs (f, FRAME_TEMP_GLYPHS (f));
- if (FRAME_INSERT_COST (f))
- free (FRAME_INSERT_COST (f));
- if (FRAME_DELETEN_COST (f))
- free (FRAME_DELETEN_COST (f));
- if (FRAME_INSERTN_COST (f))
- free (FRAME_INSERTN_COST (f));
- if (FRAME_DELETE_COST (f))
- free (FRAME_DELETE_COST (f));
-
- /* Since some events are handled at the interrupt level, we may get
- an event for f at any time; if we zero out the frame's display
- now, then we may trip up the event-handling code. Instead, we'll
- promise that the display of the frame must be valid until we have
- called the window-system-dependent frame destruction routine. */
-
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- x_destroy_window (f);
-#endif
-
- f->output_data.nothing = 0;
-
- /* If we've deleted the last_nonminibuf_frame, then try to find
- another one. */
- if (f == last_nonminibuf_frame)
- {
- Lisp_Object frames;
-
- last_nonminibuf_frame = 0;
-
- for (frames = Vframe_list;
- CONSP (frames);
- frames = XCONS (frames)->cdr)
- {
- f = XFRAME (XCONS (frames)->car);
- if (!FRAME_MINIBUF_ONLY_P (f))
- {
- last_nonminibuf_frame = f;
- break;
- }
- }
- }
-
- /* If we've deleted this keyboard's default_minibuffer_frame, try to
- find another one. Prefer minibuffer-only frames, but also notice
- frames with other windows. */
- if (EQ (frame, FRAME_KBOARD (f)->Vdefault_minibuffer_frame))
- {
- Lisp_Object frames;
-
- /* The last frame we saw with a minibuffer, minibuffer-only or not. */
- Lisp_Object frame_with_minibuf;
- /* Some frame we found on the same kboard, or nil if there are none. */
- Lisp_Object frame_on_same_kboard;
-
- frame_on_same_kboard = Qnil;
- frame_with_minibuf = Qnil;
-
- for (frames = Vframe_list;
- CONSP (frames);
- frames = XCONS (frames)->cdr)
- {
- Lisp_Object this;
- struct frame *f1;
-
- this = XCONS (frames)->car;
- if (!FRAMEP (this))
- abort ();
- f1 = XFRAME (this);
-
- /* Consider only frames on the same kboard
- and only those with minibuffers. */
- if (FRAME_KBOARD (f) == FRAME_KBOARD (f1)
- && FRAME_HAS_MINIBUF_P (f1))
- {
- frame_with_minibuf = this;
- if (FRAME_MINIBUF_ONLY_P (f1))
- break;
- }
-
- if (FRAME_KBOARD (f) == FRAME_KBOARD (f1))
- frame_on_same_kboard = this;
- }
-
- if (!NILP (frame_on_same_kboard))
- {
- /* We know that there must be some frame with a minibuffer out
- there. If this were not true, all of the frames present
- would have to be minibufferless, which implies that at some
- point their minibuffer frames must have been deleted, but
- that is prohibited at the top; you can't delete surrogate
- minibuffer frames. */
- if (NILP (frame_with_minibuf))
- abort ();
-
- FRAME_KBOARD (f)->Vdefault_minibuffer_frame = frame_with_minibuf;
- }
- else
- /* No frames left on this kboard--say no minibuffer either. */
- FRAME_KBOARD (f)->Vdefault_minibuffer_frame = Qnil;
- }
-
- /* Cause frame titles to update--necessary if we now have just one frame. */
- update_mode_lines = 1;
-
- return Qnil;
-}
-
-/* Return mouse position in character cell units. */
-
-DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
- "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
-The position is given in character cells, where (0, 0) is the\n\
-upper-left corner.\n\
-If Emacs is running on a mouseless terminal or hasn't been programmed\n\
-to read the mouse position, it returns the selected frame for FRAME\n\
-and nil for X and Y.")
- ()
-{
- FRAME_PTR f;
- Lisp_Object lispy_dummy;
- enum scroll_bar_part party_dummy;
- Lisp_Object x, y;
- int col, row;
- unsigned long long_dummy;
-
- f = selected_frame;
- x = y = Qnil;
-
-#ifdef HAVE_MOUSE
- /* It's okay for the hook to refrain from storing anything. */
- if (mouse_position_hook)
- (*mouse_position_hook) (&f, 0,
- &lispy_dummy, &party_dummy,
- &x, &y,
- &long_dummy);
- if (! NILP (x))
- {
- col = XINT (x);
- row = XINT (y);
- pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
- XSETINT (x, col);
- XSETINT (y, row);
- }
-#endif
- XSETFRAME (lispy_dummy, f);
- return Fcons (lispy_dummy, Fcons (x, y));
-}
-
-DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
- Smouse_pixel_position, 0, 0, 0,
- "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
-The position is given in pixel units, where (0, 0) is the\n\
-upper-left corner.\n\
-If Emacs is running on a mouseless terminal or hasn't been programmed\n\
-to read the mouse position, it returns the selected frame for FRAME\n\
-and nil for X and Y.")
- ()
-{
- FRAME_PTR f;
- Lisp_Object lispy_dummy;
- enum scroll_bar_part party_dummy;
- Lisp_Object x, y;
- int col, row;
- unsigned long long_dummy;
-
- f = selected_frame;
- x = y = Qnil;
-
-#ifdef HAVE_MOUSE
- /* It's okay for the hook to refrain from storing anything. */
- if (mouse_position_hook)
- (*mouse_position_hook) (&f, 0,
- &lispy_dummy, &party_dummy,
- &x, &y,
- &long_dummy);
-#endif
- XSETFRAME (lispy_dummy, f);
- return Fcons (lispy_dummy, Fcons (x, y));
-}
-
-DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
- "Move the mouse pointer to the center of character cell (X,Y) in FRAME.\n\
-Note, this is a no-op for an X frame that is not visible.\n\
-If you have just created a frame, you must wait for it to become visible\n\
-before calling this function on it, like this.\n\
- (while (not (frame-visible-p frame)) (sleep-for .5))")
- (frame, x, y)
- Lisp_Object frame, x, y;
-{
- CHECK_LIVE_FRAME (frame, 0);
- CHECK_NUMBER (x, 2);
- CHECK_NUMBER (y, 1);
-
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (XFRAME (frame)))
- /* Warping the mouse will cause enternotify and focus events. */
- x_set_mouse_position (XFRAME (frame), x, y);
-#else
-#if defined (MSDOS) && defined (HAVE_MOUSE)
- if (FRAME_MSDOS_P (XFRAME (frame)))
- {
- Fselect_frame (frame, Qnil);
- mouse_moveto (XINT (x), XINT (y));
- }
-#endif
-#endif
-
- return Qnil;
-}
-
-DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
- Sset_mouse_pixel_position, 3, 3, 0,
- "Move the mouse pointer to pixel position (X,Y) in FRAME.\n\
-Note, this is a no-op for an X frame that is not visible.\n\
-If you have just created a frame, you must wait for it to become visible\n\
-before calling this function on it, like this.\n\
- (while (not (frame-visible-p frame)) (sleep-for .5))")
- (frame, x, y)
- Lisp_Object frame, x, y;
-{
- CHECK_LIVE_FRAME (frame, 0);
- CHECK_NUMBER (x, 2);
- CHECK_NUMBER (y, 1);
-
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (XFRAME (frame)))
- /* Warping the mouse will cause enternotify and focus events. */
- x_set_mouse_pixel_position (XFRAME (frame), x, y);
-#else
-#if defined (MSDOS) && defined (HAVE_MOUSE)
- if (FRAME_MSDOS_P (XFRAME (frame)))
- {
- Fselect_frame (frame, Qnil);
- mouse_moveto (XINT (x), XINT (y));
- }
-#endif
-#endif
-
- return Qnil;
-}
-
-DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
- 0, 1, "",
- "Make the frame FRAME visible (assuming it is an X-window).\n\
-If omitted, FRAME defaults to the currently selected frame.")
- (frame)
- Lisp_Object frame;
-{
- if (NILP (frame))
- XSETFRAME (frame, selected_frame);
-
- CHECK_LIVE_FRAME (frame, 0);
-
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (XFRAME (frame)))
- {
- FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
- x_make_frame_visible (XFRAME (frame));
- }
-#endif
-
- /* Make menu bar update for the Buffers and Frams menus. */
- windows_or_buffers_changed++;
-
- return frame;
-}
-
-DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
- 0, 2, "",
- "Make the frame FRAME invisible (assuming it is an X-window).\n\
-If omitted, FRAME defaults to the currently selected frame.\n\
-Normally you may not make FRAME invisible if all other frames are invisible,\n\
-but if the second optional argument FORCE is non-nil, you may do so.")
- (frame, force)
- Lisp_Object frame, force;
-{
- if (NILP (frame))
- XSETFRAME (frame, selected_frame);
-
- CHECK_LIVE_FRAME (frame, 0);
-
- if (NILP (force) && !other_visible_frames (XFRAME (frame)))
- error ("Attempt to make invisible the sole visible or iconified frame");
-
-#if 0 /* This isn't logically necessary, and it can do GC. */
- /* Don't let the frame remain selected. */
- if (XFRAME (frame) == selected_frame)
- do_switch_frame (next_frame (frame, Qt), Qnil, 0)
-#endif
-
- /* Don't allow minibuf_window to remain on a deleted frame. */
- if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
- {
- Fset_window_buffer (selected_frame->minibuffer_window,
- XWINDOW (minibuf_window)->buffer);
- minibuf_window = selected_frame->minibuffer_window;
- }
-
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (XFRAME (frame)))
- x_make_frame_invisible (XFRAME (frame));
-#endif
-
- /* Make menu bar update for the Buffers and Frams menus. */
- windows_or_buffers_changed++;
-
- return Qnil;
-}
-
-DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
- 0, 1, "",
- "Make the frame FRAME into an icon.\n\
-If omitted, FRAME defaults to the currently selected frame.")
- (frame)
- Lisp_Object frame;
-{
- if (NILP (frame))
- XSETFRAME (frame, selected_frame);
-
- CHECK_LIVE_FRAME (frame, 0);
-
-#if 0 /* This isn't logically necessary, and it can do GC. */
- /* Don't let the frame remain selected. */
- if (XFRAME (frame) == selected_frame)
- Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
-#endif
-
- /* Don't allow minibuf_window to remain on a deleted frame. */
- if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
- {
- Fset_window_buffer (selected_frame->minibuffer_window,
- XWINDOW (minibuf_window)->buffer);
- minibuf_window = selected_frame->minibuffer_window;
- }
-
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (XFRAME (frame)))
- x_iconify_frame (XFRAME (frame));
-#endif
-
- /* Make menu bar update for the Buffers and Frams menus. */
- windows_or_buffers_changed++;
-
- return Qnil;
-}
-
-DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
- 1, 1, 0,
- "Return t if FRAME is now \"visible\" (actually in use for display).\n\
-A frame that is not \"visible\" is not updated and, if it works through\n\
-a window system, it may not show at all.\n\
-Return the symbol `icon' if frame is visible only as an icon.")
- (frame)
- Lisp_Object frame;
-{
- CHECK_LIVE_FRAME (frame, 0);
-
- FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
-
- if (FRAME_VISIBLE_P (XFRAME (frame)))
- return Qt;
- if (FRAME_ICONIFIED_P (XFRAME (frame)))
- return Qicon;
- return Qnil;
-}
-
-DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
- 0, 0, 0,
- "Return a list of all frames now \"visible\" (being updated).")
- ()
-{
- Lisp_Object tail, frame;
- struct frame *f;
- Lisp_Object value;
-
- value = Qnil;
- for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- frame = XCONS (tail)->car;
- if (!FRAMEP (frame))
- continue;
- f = XFRAME (frame);
- if (FRAME_VISIBLE_P (f))
- value = Fcons (frame, value);
- }
- return value;
-}
-
-
-DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
- "Bring FRAME to the front, so it occludes any frames it overlaps.\n\
-If FRAME is invisible, make it visible.\n\
-If you don't specify a frame, the selected frame is used.\n\
-If Emacs is displaying on an ordinary terminal or some other device which\n\
-doesn't support multiple overlapping frames, this function does nothing.")
- (frame)
- Lisp_Object frame;
-{
- if (NILP (frame))
- XSETFRAME (frame, selected_frame);
-
- CHECK_LIVE_FRAME (frame, 0);
-
- /* Do like the documentation says. */
- Fmake_frame_visible (frame);
-
- if (frame_raise_lower_hook)
- (*frame_raise_lower_hook) (XFRAME (frame), 1);
-
- return Qnil;
-}
-
-/* Should we have a corresponding function called Flower_Power? */
-DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
- "Send FRAME to the back, so it is occluded by any frames that overlap it.\n\
-If you don't specify a frame, the selected frame is used.\n\
-If Emacs is displaying on an ordinary terminal or some other device which\n\
-doesn't support multiple overlapping frames, this function does nothing.")
- (frame)
- Lisp_Object frame;
-{
- if (NILP (frame))
- XSETFRAME (frame, selected_frame);
-
- CHECK_LIVE_FRAME (frame, 0);
-
- if (frame_raise_lower_hook)
- (*frame_raise_lower_hook) (XFRAME (frame), 0);
-
- return Qnil;
-}
-
-
-DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
- 1, 2, 0,
- "Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.\n\
-In other words, switch-frame events caused by events in FRAME will\n\
-request a switch to FOCUS-FRAME, and `last-event-frame' will be\n\
-FOCUS-FRAME after reading an event typed at FRAME.\n\
-\n\
-If FOCUS-FRAME is omitted or nil, any existing redirection is\n\
-cancelled, and the frame again receives its own keystrokes.\n\
-\n\
-Focus redirection is useful for temporarily redirecting keystrokes to\n\
-a surrogate minibuffer frame when a frame doesn't have its own\n\
-minibuffer window.\n\
-\n\
-A frame's focus redirection can be changed by select-frame. If frame\n\
-FOO is selected, and then a different frame BAR is selected, any\n\
-frames redirecting their focus to FOO are shifted to redirect their\n\
-focus to BAR. This allows focus redirection to work properly when the\n\
-user switches from one frame to another using `select-window'.\n\
-\n\
-This means that a frame whose focus is redirected to itself is treated\n\
-differently from a frame whose focus is redirected to nil; the former\n\
-is affected by select-frame, while the latter is not.\n\
-\n\
-The redirection lasts until `redirect-frame-focus' is called to change it.")
- (frame, focus_frame)
- Lisp_Object frame, focus_frame;
-{
- /* Note that we don't check for a live frame here. It's reasonable
- to redirect the focus of a frame you're about to delete, if you
- know what other frame should receive those keystrokes. */
- CHECK_FRAME (frame, 0);
-
- if (! NILP (focus_frame))
- CHECK_LIVE_FRAME (focus_frame, 1);
-
- XFRAME (frame)->focus_frame = focus_frame;
-
- if (frame_rehighlight_hook)
- (*frame_rehighlight_hook) (XFRAME (frame));
-
- return Qnil;
-}
-
-
-DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 1, 1, 0,
- "Return the frame to which FRAME's keystrokes are currently being sent.\n\
-This returns nil if FRAME's focus is not redirected.\n\
-See `redirect-frame-focus'.")
- (frame)
- Lisp_Object frame;
-{
- CHECK_LIVE_FRAME (frame, 0);
-
- return FRAME_FOCUS_FRAME (XFRAME (frame));
-}
-
-
-
-/* Return the value of frame parameter PROP in frame FRAME. */
-
-Lisp_Object
-get_frame_param (frame, prop)
- register struct frame *frame;
- Lisp_Object prop;
-{
- register Lisp_Object tem;
-
- tem = Fassq (prop, frame->param_alist);
- if (EQ (tem, Qnil))
- return tem;
- return Fcdr (tem);
-}
-
-/* Return the buffer-predicate of the selected frame. */
-
-Lisp_Object
-frame_buffer_predicate ()
-{
- return selected_frame->buffer_predicate;
-}
-
-/* Modify the alist in *ALISTPTR to associate PROP with VAL.
- If the alist already has an element for PROP, we change it. */
-
-void
-store_in_alist (alistptr, prop, val)
- Lisp_Object *alistptr, val;
- Lisp_Object prop;
-{
- register Lisp_Object tem;
-
- tem = Fassq (prop, *alistptr);
- if (EQ (tem, Qnil))
- *alistptr = Fcons (Fcons (prop, val), *alistptr);
- else
- Fsetcdr (tem, val);
-}
-
-void
-store_frame_param (f, prop, val)
- struct frame *f;
- Lisp_Object prop, val;
-{
- register Lisp_Object tem;
-
- tem = Fassq (prop, f->param_alist);
- if (EQ (tem, Qnil))
- f->param_alist = Fcons (Fcons (prop, val), f->param_alist);
- else
- Fsetcdr (tem, val);
-
- if (EQ (prop, Qbuffer_predicate))
- f->buffer_predicate = val;
-
- if (! FRAME_WINDOW_P (f))
- if (EQ (prop, Qmenu_bar_lines))
- set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
-
- if (EQ (prop, Qminibuffer) && WINDOWP (val))
- {
- if (! MINI_WINDOW_P (XWINDOW (val)))
- error ("Surrogate minibuffer windows must be minibuffer windows.");
-
- if (FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f)
- && !EQ (val, f->minibuffer_window))
- error ("Can't change the surrogate minibuffer of a frame with its own minibuffer");
-
- /* Install the chosen minibuffer window, with proper buffer. */
- f->minibuffer_window = val;
- }
-}
-
-DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
- "Return the parameters-alist of frame FRAME.\n\
-It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.\n\
-The meaningful PARMs depend on the kind of frame.\n\
-If FRAME is omitted, return information on the currently selected frame.")
- (frame)
- Lisp_Object frame;
-{
- Lisp_Object alist;
- FRAME_PTR f;
- int height, width;
-
- if (EQ (frame, Qnil))
- f = selected_frame;
- else
- {
- CHECK_FRAME (frame, 0);
- f = XFRAME (frame);
- }
-
- if (!FRAME_LIVE_P (f))
- return Qnil;
-
- alist = Fcopy_alist (f->param_alist);
-#ifdef MSDOS
- if (FRAME_MSDOS_P (f))
- {
- static char *colornames[16] =
- {
- "black", "blue", "green", "cyan", "red", "magenta", "brown",
- "lightgray", "darkgray", "lightblue", "lightgreen", "lightcyan",
- "lightred", "lightmagenta", "yellow", "white"
- };
- store_in_alist (&alist, intern ("foreground-color"),
- build_string (colornames[FRAME_FOREGROUND_PIXEL (f)]));
- store_in_alist (&alist, intern ("background-color"),
- build_string (colornames[FRAME_BACKGROUND_PIXEL (f)]));
- }
- store_in_alist (&alist, intern ("font"), build_string ("default"));
-#endif
- store_in_alist (&alist, Qname, f->name);
- height = (FRAME_NEW_HEIGHT (f) ? FRAME_NEW_HEIGHT (f) : FRAME_HEIGHT (f));
- store_in_alist (&alist, Qheight, make_number (height));
- width = (FRAME_NEW_WIDTH (f) ? FRAME_NEW_WIDTH (f) : FRAME_WIDTH (f));
- store_in_alist (&alist, Qwidth, make_number (width));
- store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
- store_in_alist (&alist, Qminibuffer,
- (! FRAME_HAS_MINIBUF_P (f) ? Qnil
- : FRAME_MINIBUF_ONLY_P (f) ? Qonly
- : FRAME_MINIBUF_WINDOW (f)));
- store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
-
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- x_report_frame_params (f, &alist);
- else
-#endif
- {
- /* This ought to be correct in f->param_alist for an X frame. */
- Lisp_Object lines;
- XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
- store_in_alist (&alist, Qmenu_bar_lines, lines);
- }
- return alist;
-}
-
-DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
- Smodify_frame_parameters, 2, 2, 0,
- "Modify the parameters of frame FRAME according to ALIST.\n\
-ALIST is an alist of parameters to change and their new values.\n\
-Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
-The meaningful PARMs depend on the kind of frame.\n\
-Undefined PARMs are ignored, but stored in the frame's parameter list\n\
-so that `frame-parameters' will return them.")
- (frame, alist)
- Lisp_Object frame, alist;
-{
- FRAME_PTR f;
- register Lisp_Object tail, elt, prop, val;
-
- if (EQ (frame, Qnil))
- f = selected_frame;
- else
- {
- CHECK_LIVE_FRAME (frame, 0);
- f = XFRAME (frame);
- }
-
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- x_set_frame_parameters (f, alist);
- else
-#endif
-#ifdef MSDOS
- if (FRAME_MSDOS_P (f))
- IT_set_frame_parameters (f, alist);
- else
-#endif
- {
- int length = XINT (Flength (alist));
- int i;
- Lisp_Object *parms
- = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
- Lisp_Object *values
- = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
-
- /* Extract parm names and values into those vectors. */
-
- i = 0;
- for (tail = alist; CONSP (tail); tail = Fcdr (tail))
- {
- Lisp_Object elt, prop, val;
-
- elt = Fcar (tail);
- parms[i] = Fcar (elt);
- values[i] = Fcdr (elt);
- i++;
- }
-
- /* Now process them in reverse of specified order. */
- for (i--; i >= 0; i--)
- {
- prop = parms[i];
- val = values[i];
- store_frame_param (f, prop, val);
- }
- }
-
- return Qnil;
-}
-
-DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
- 0, 1, 0,
- "Height in pixels of a line in the font in frame FRAME.\n\
-If FRAME is omitted, the selected frame is used.\n\
-For a terminal frame, the value is always 1.")
- (frame)
- Lisp_Object frame;
-{
- struct frame *f;
-
- if (NILP (frame))
- f = selected_frame;
- else
- {
- CHECK_FRAME (frame, 0);
- f = XFRAME (frame);
- }
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- return make_number (x_char_height (f));
- else
-#endif
- return make_number (1);
-}
-
-
-DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
- 0, 1, 0,
- "Width in pixels of characters in the font in frame FRAME.\n\
-If FRAME is omitted, the selected frame is used.\n\
-The width is the same for all characters, because\n\
-currently Emacs supports only fixed-width fonts.\n\
-For a terminal screen, the value is always 1.")
- (frame)
- Lisp_Object frame;
-{
- struct frame *f;
-
- if (NILP (frame))
- f = selected_frame;
- else
- {
- CHECK_FRAME (frame, 0);
- f = XFRAME (frame);
- }
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- return make_number (x_char_width (f));
- else
-#endif
- return make_number (1);
-}
-
-DEFUN ("frame-pixel-height", Fframe_pixel_height,
- Sframe_pixel_height, 0, 1, 0,
- "Return a FRAME's height in pixels.\n\
-For a terminal frame, the result really gives the height in characters.\n\
-If FRAME is omitted, the selected frame is used.")
- (frame)
- Lisp_Object frame;
-{
- struct frame *f;
-
- if (NILP (frame))
- f = selected_frame;
- else
- {
- CHECK_FRAME (frame, 0);
- f = XFRAME (frame);
- }
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- return make_number (x_pixel_height (f));
- else
-#endif
- return make_number (FRAME_HEIGHT (f));
-}
-
-DEFUN ("frame-pixel-width", Fframe_pixel_width,
- Sframe_pixel_width, 0, 1, 0,
- "Return FRAME's width in pixels.\n\
-For a terminal frame, the result really gives the width in characters.\n\
-If FRAME is omitted, the selected frame is used.")
- (frame)
- Lisp_Object frame;
-{
- struct frame *f;
-
- if (NILP (frame))
- f = selected_frame;
- else
- {
- CHECK_FRAME (frame, 0);
- f = XFRAME (frame);
- }
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- return make_number (x_pixel_width (f));
- else
-#endif
- return make_number (FRAME_WIDTH (f));
-}
-
-DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
- "Specify that the frame FRAME has LINES lines.\n\
-Optional third arg non-nil means that redisplay should use LINES lines\n\
-but that the idea of the actual height of the frame should not be changed.")
- (frame, lines, pretend)
- Lisp_Object frame, lines, pretend;
-{
- register struct frame *f;
-
- CHECK_NUMBER (lines, 0);
- if (NILP (frame))
- f = selected_frame;
- else
- {
- CHECK_LIVE_FRAME (frame, 0);
- f = XFRAME (frame);
- }
-
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- {
- if (XINT (lines) != f->height)
- x_set_window_size (f, 1, f->width, XINT (lines));
- }
- else
-#endif
- change_frame_size (f, XINT (lines), 0, !NILP (pretend), 0);
- return Qnil;
-}
-
-DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
- "Specify that the frame FRAME has COLS columns.\n\
-Optional third arg non-nil means that redisplay should use COLS columns\n\
-but that the idea of the actual width of the frame should not be changed.")
- (frame, cols, pretend)
- Lisp_Object frame, cols, pretend;
-{
- register struct frame *f;
- CHECK_NUMBER (cols, 0);
- if (NILP (frame))
- f = selected_frame;
- else
- {
- CHECK_LIVE_FRAME (frame, 0);
- f = XFRAME (frame);
- }
-
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- {
- if (XINT (cols) != f->width)
- x_set_window_size (f, 1, XINT (cols), f->height);
- }
- else
-#endif
- change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0);
- return Qnil;
-}
-
-DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
- "Sets size of FRAME to COLS by ROWS, measured in characters.")
- (frame, cols, rows)
- Lisp_Object frame, cols, rows;
-{
- register struct frame *f;
- int mask;
-
- CHECK_LIVE_FRAME (frame, 0);
- CHECK_NUMBER (cols, 2);
- CHECK_NUMBER (rows, 1);
- f = XFRAME (frame);
-
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- {
- if (XINT (rows) != f->height || XINT (cols) != f->width
- || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
- x_set_window_size (f, 1, XINT (cols), XINT (rows));
- }
- else
-#endif
- change_frame_size (f, XINT (rows), XINT (cols), 0, 0);
-
- return Qnil;
-}
-
-DEFUN ("set-frame-position", Fset_frame_position,
- Sset_frame_position, 3, 3, 0,
- "Sets position of FRAME in pixels to XOFFSET by YOFFSET.\n\
-This is actually the position of the upper left corner of the frame.\n\
-Negative values for XOFFSET or YOFFSET are interpreted relative to\n\
-the rightmost or bottommost possible position (that stays within the screen).")
- (frame, xoffset, yoffset)
- Lisp_Object frame, xoffset, yoffset;
-{
- register struct frame *f;
- int mask;
-
- CHECK_LIVE_FRAME (frame, 0);
- CHECK_NUMBER (xoffset, 1);
- CHECK_NUMBER (yoffset, 2);
- f = XFRAME (frame);
-
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
-#endif
-
- return Qt;
-}
-
-
-syms_of_frame ()
-{
- syms_of_frame_1 ();
-
- staticpro (&Vframe_list);
-
- DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
- "The initial frame-object, which represents Emacs's stdout.");
-
- DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
- "Non-nil if all of emacs is iconified and frame updates are not needed.");
- Vemacs_iconified = Qnil;
-
- DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
- "Minibufferless frames use this frame's minibuffer.\n\
-\n\
-Emacs cannot create minibufferless frames unless this is set to an\n\
-appropriate surrogate.\n\
-\n\
-Emacs consults this variable only when creating minibufferless\n\
-frames; once the frame is created, it sticks with its assigned\n\
-minibuffer, no matter what this variable is set to. This means that\n\
-this variable doesn't necessarily say anything meaningful about the\n\
-current set of frames, or where the minibuffer is currently being\n\
-displayed.");
-
- defsubr (&Sactive_minibuffer_window);
- defsubr (&Sframep);
- defsubr (&Sframe_live_p);
- defsubr (&Smake_terminal_frame);
- defsubr (&Shandle_switch_frame);
- defsubr (&Signore_event);
- defsubr (&Sselect_frame);
- defsubr (&Sselected_frame);
- defsubr (&Swindow_frame);
- defsubr (&Sframe_root_window);
- defsubr (&Sframe_first_window);
- defsubr (&Sframe_selected_window);
- defsubr (&Sset_frame_selected_window);
- defsubr (&Sframe_list);
- defsubr (&Snext_frame);
- defsubr (&Sprevious_frame);
- defsubr (&Sdelete_frame);
- defsubr (&Smouse_position);
- defsubr (&Smouse_pixel_position);
- defsubr (&Sset_mouse_position);
- defsubr (&Sset_mouse_pixel_position);
-#if 0
- defsubr (&Sframe_configuration);
- defsubr (&Srestore_frame_configuration);
-#endif
- defsubr (&Smake_frame_visible);
- defsubr (&Smake_frame_invisible);
- defsubr (&Siconify_frame);
- defsubr (&Sframe_visible_p);
- defsubr (&Svisible_frame_list);
- defsubr (&Sraise_frame);
- defsubr (&Slower_frame);
- defsubr (&Sredirect_frame_focus);
- defsubr (&Sframe_focus);
- defsubr (&Sframe_parameters);
- defsubr (&Smodify_frame_parameters);
- defsubr (&Sframe_char_height);
- defsubr (&Sframe_char_width);
- defsubr (&Sframe_pixel_height);
- defsubr (&Sframe_pixel_width);
- defsubr (&Sset_frame_height);
- defsubr (&Sset_frame_width);
- defsubr (&Sset_frame_size);
- defsubr (&Sset_frame_position);
-}
-
-keys_of_frame ()
-{
- initial_define_lispy_key (global_map, "switch-frame", "handle-switch-frame");
- initial_define_lispy_key (global_map, "delete-frame", "handle-delete-frame");
- initial_define_lispy_key (global_map, "iconify-frame", "ignore-event");
- initial_define_lispy_key (global_map, "make-frame-visible", "ignore-event");
-}
diff --git a/src/frame.h b/src/frame.h
deleted file mode 100644
index 404dfcdfb04..00000000000
--- a/src/frame.h
+++ /dev/null
@@ -1,485 +0,0 @@
-/* Define frame-object for GNU Emacs.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Miscellanea. */
-
-/* Nonzero means don't assume anything about current
- contents of actual terminal frame */
-extern int frame_garbaged;
-
-/* Nonzero means FRAME_MESSAGE_BUF (selected_frame) is being used by
- print. */
-extern int message_buf_print;
-
-
-/* The structure representing a frame. */
-
-enum output_method
-{ output_termcap, output_x_window, output_msdos_raw, output_w32 };
-
-enum vertical_scroll_bar_type
-{ vertical_scroll_bar_none, vertical_scroll_bar_left, vertical_scroll_bar_right };
-
-struct frame
-{
- EMACS_INT size;
- struct Lisp_Vector *next;
-
- /* All Lisp_Object components must come first.
- Only EMACS_INT values can be intermixed with them.
- That ensures they are all aligned normally. */
-
- /* Name of this frame: a Lisp string. It is used for looking up resources,
- as well as for the title in some cases. */
- Lisp_Object name;
-
- /* The name to use for the icon, the last time
- it was refreshed. nil means not explicitly specified. */
- Lisp_Object icon_name;
-
- /* This is the frame title specified explicitly, if any.
- Usually it is nil. */
- Lisp_Object title;
-
- /* The frame which should receive keystrokes that occur in this
- frame, or nil if they should go to the frame itself. This is
- usually nil, but if the frame is minibufferless, we can use this
- to redirect keystrokes to a surrogate minibuffer frame when
- needed.
-
- Note that a value of nil is different than having the field point
- to the frame itself. Whenever the Fselect_frame function is used
- to shift from one frame to the other, any redirections to the
- original frame are shifted to the newly selected frame; if
- focus_frame is nil, Fselect_frame will leave it alone. */
- Lisp_Object focus_frame;
-
- /* This frame's root window. Every frame has one.
- If the frame has only a minibuffer window, this is it.
- Otherwise, if the frame has a minibuffer window, this is its sibling. */
- Lisp_Object root_window;
-
- /* This frame's selected window.
- Each frame has its own window hierarchy
- and one of the windows in it is selected within the frame.
- The selected window of the selected frame is Emacs's selected window. */
- Lisp_Object selected_window;
-
- /* This frame's minibuffer window.
- Most frames have their own minibuffer windows,
- but only the selected frame's minibuffer window
- can actually appear to exist. */
- Lisp_Object minibuffer_window;
-
- /* Parameter alist of this frame.
- These are the parameters specified when creating the frame
- or modified with modify-frame-parameters. */
- Lisp_Object param_alist;
-
- /* List of scroll bars on this frame.
- Actually, we don't specify exactly what is stored here at all; the
- scroll bar implementation code can use it to store anything it likes.
- This field is marked by the garbage collector. It is here
- instead of in the `display' structure so that the garbage
- collector doesn't need to look inside the window-system-dependent
- structure. */
- Lisp_Object scroll_bars;
- Lisp_Object condemned_scroll_bars;
-
- /* Vector describing the items to display in the menu bar.
- Each item has four elements in this vector.
- They are KEY, STRING, SUBMAP, and HPOS.
- (HPOS is not used in when the X toolkit is in use.)
- There are four additional elements of nil at the end, to terminate. */
- Lisp_Object menu_bar_items;
-
- /* Alist of elements (FACE-NAME . FACE-VECTOR-DATA). */
- Lisp_Object face_alist;
-
- /* A vector that records the entire structure of this frame's menu bar.
- For the format of the data, see extensive comments in xmenu.c.
- Only the X toolkit version uses this. */
- Lisp_Object menu_bar_vector;
- /* Number of elements in the vector that have meaningful data. */
- EMACS_INT menu_bar_items_used;
-
- /* Predicate for selecting buffers for other-buffer. */
- Lisp_Object buffer_predicate;
-
- /* Beyond here, there should be no more Lisp_Object components. */
-
-
- /* A buffer to hold the frame's name. We can't use the Lisp string's
- pointer (`name', above) because it might get relocated. */
- char *namebuf;
-
- /* glyphs as they appear on the frame */
- struct frame_glyphs *current_glyphs;
-
- /* glyphs we'd like to appear on the frame */
- struct frame_glyphs *desired_glyphs;
-
- /* See do_line_insertion_deletion_costs for info on these arrays. */
- /* Cost of inserting 1 line on this frame */
- int *insert_line_cost;
- /* Cost of deleting 1 line on this frame */
- int *delete_line_cost;
- /* Cost of inserting n lines on this frame */
- int *insert_n_lines_cost;
- /* Cost of deleting n lines on this frame */
- int *delete_n_lines_cost;
-
- /* glyphs for the mode line */
- struct frame_glyphs *temp_glyphs;
-
- /* Intended cursor position of this frame.
- Measured in characters, counting from upper left corner
- within the frame. */
- int cursor_x;
- int cursor_y;
-
- /* Actual cursor position of this frame, and the character under it.
- (Not used for terminal frames.) */
- int phys_cursor_x;
- int phys_cursor_y;
- /* This is handy for undrawing the cursor, because current_glyphs is
- not always accurate when in do_scrolling. */
- GLYPH phys_cursor_glyph;
- /* Nonzero means the cursor is displayed. */
- int phys_cursor_on;
-
- /* Size of this frame, in units of characters. */
- EMACS_INT height;
- EMACS_INT width;
- EMACS_INT window_width;
-
- /* New height and width for pending size change. 0 if no change pending. */
- int new_height, new_width;
-
- /* The output method says how the contents of this frame
- are displayed. It could be using termcap, or using an X window. */
- enum output_method output_method;
-
- /* A structure of auxiliary data used for displaying the contents.
- struct x_output is used for X window frames;
- it is defined in xterm.h.
- struct w32_output is used for W32 window frames;
- it is defined in w32term.h. */
- union output_data { struct x_output *x; struct w32_output *w32; int nothing; } output_data;
-
-#ifdef MULTI_KBOARD
- /* A pointer to the kboard structure associated with this frame.
- For termcap frames, this points to initial_kboard. For X frames,
- it will be the same as display.x->display_info->kboard. */
- struct kboard *kboard;
-#endif
-
- /* Number of lines of menu bar. */
- int menu_bar_lines;
-
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
- /* Nonzero means using a menu bar that comes from the X toolkit. */
- int external_menu_bar;
-#endif
-
- /* Nonzero if last attempt at redisplay on this frame was preempted. */
- char display_preempted;
-
- /* visible is nonzero if the frame is currently displayed; we check
- it to see if we should bother updating the frame's contents.
- DON'T SET IT DIRECTLY; instead, use FRAME_SET_VISIBLE.
-
- Note that, since invisible frames aren't updated, whenever a
- frame becomes visible again, it must be marked as garbaged. The
- FRAME_SAMPLE_VISIBILITY macro takes care of this.
-
- iconified is nonzero if the frame is currently iconified.
-
- Asynchronous input handlers should NOT change these directly;
- instead, they should change async_visible or async_iconified, and
- let the FRAME_SAMPLE_VISIBILITY macro set visible and iconified
- at the next redisplay.
-
- These should probably be considered read-only by everyone except
- FRAME_SAMPLE_VISIBILITY.
-
- These two are mutually exclusive. They might both be zero, if the
- frame has been made invisible without an icon. */
- char visible, iconified;
-
- /* Asynchronous input handlers change these, and
- FRAME_SAMPLE_VISIBILITY copies them into visible and iconified.
- See FRAME_SAMPLE_VISIBILITY, below. */
-#ifdef __STDC__
- volatile
-#endif
- char async_visible, async_iconified;
-
- /* Nonzero if this frame should be redrawn. */
-#ifdef __STDC__
- volatile
-#endif
- char garbaged;
-
- /* True if frame actually has a minibuffer window on it.
- 0 if using a minibuffer window that isn't on this frame. */
- char has_minibuffer;
-
- /* 0 means, if this frame has just one window,
- show no modeline for that window. */
- char wants_modeline;
-
- /* Non-zero if the hardware device this frame is displaying on can
- support scroll bars. */
- char can_have_scroll_bars;
-
- /* If can_have_scroll_bars is non-zero, this is non-zero if we should
- actually display them on this frame. */
- enum vertical_scroll_bar_type vertical_scroll_bar_type;
-
- /* Non-0 means raise this frame to the top of the heap when selected. */
- char auto_raise;
-
- /* Non-0 means lower this frame to the bottom of the stack when left. */
- char auto_lower;
-
- /* True if frame's root window can't be split. */
- char no_split;
-
- /* If this is set, then Emacs won't change the frame name to indicate
- the current buffer, etcetera. If the user explicitly sets the frame
- name, this gets set. If the user sets the name to Qnil, this is
- cleared. */
- char explicit_name;
-
- /* Nonzero if size of some window on this frame has changed. */
- char window_sizes_changed;
-
- /* Storage for messages to this frame. */
- char *message_buf;
-
- /* Nonnegative if current redisplay should not do scroll computation
- for lines beyond a certain vpos. This is the vpos. */
- int scroll_bottom_vpos;
-
- /* Width of the scroll bar, in pixels and in characters.
- scroll_bar_cols tracks scroll_bar_pixel_width if the latter is positive;
- a zero value in scroll_bar_pixel_width means to compute the actual width
- on the fly, using scroll_bar_cols and the current font width. */
- int scroll_bar_pixel_width;
- int scroll_bar_cols;
-
- /* The baud rate that was used to calculate costs for this frame. */
- int cost_calculation_baud_rate;
-
- /* Nonzero if the mouse has moved on this display
- since the last time we checked. */
- char mouse_moved;
-};
-
-#ifdef MULTI_KBOARD
-#define FRAME_KBOARD(f) ((f)->kboard)
-#else
-#define FRAME_KBOARD(f) (&the_only_kboard)
-#endif
-
-typedef struct frame *FRAME_PTR;
-
-#define XFRAME(p) ((struct frame *) XPNTR (p))
-#define XSETFRAME(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_FRAME))
-
-#define WINDOW_FRAME(w) (w)->frame
-
-#define FRAME_X_P(f) ((f)->output_method == output_x_window)
-#define FRAME_W32_P(f) ((f)->output_method == output_w32)
-#define FRAME_MSDOS_P(f) ((f)->output_method == output_msdos_raw)
-
-/* FRAME_WINDOW_P tests whether the frame is a window, and is
- defined to be the predicate for the window system being used. */
-#ifdef HAVE_X_WINDOWS
-#define FRAME_WINDOW_P(f) FRAME_X_P (f)
-#endif
-#ifdef HAVE_NTGUI
-#define FRAME_WINDOW_P(f) FRAME_W32_P (f)
-#endif
-#ifndef FRAME_WINDOW_P
-#define FRAME_WINDOW_P(f) (0)
-#endif
-
-#define FRAME_LIVE_P(f) ((f)->output_data.nothing != 0)
-#define FRAME_TERMCAP_P(f) ((f)->output_method == output_termcap)
-#define FRAME_MINIBUF_ONLY_P(f) \
- EQ (FRAME_ROOT_WINDOW (f), FRAME_MINIBUF_WINDOW (f))
-#define FRAME_HAS_MINIBUF_P(f) ((f)->has_minibuffer)
-#define FRAME_CURRENT_GLYPHS(f) (f)->current_glyphs
-#define FRAME_DESIRED_GLYPHS(f) (f)->desired_glyphs
-#define FRAME_TEMP_GLYPHS(f) (f)->temp_glyphs
-#define FRAME_HEIGHT(f) (f)->height
-#define FRAME_WIDTH(f) (f)->width
-#define FRAME_NEW_HEIGHT(f) (f)->new_height
-#define FRAME_NEW_WIDTH(f) (f)->new_width
-#define FRAME_MENU_BAR_LINES(f) (f)->menu_bar_lines
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
-#define FRAME_EXTERNAL_MENU_BAR(f) (f)->external_menu_bar
-#else
-#define FRAME_EXTERNAL_MENU_BAR(f) 0
-#endif
-#define FRAME_CURSOR_X(f) (f)->cursor_x
-#define FRAME_CURSOR_Y(f) (f)->cursor_y
-#define FRAME_VISIBLE_P(f) ((f)->visible != 0)
-#define FRAME_SET_VISIBLE(f,p) \
- ((f)->async_visible = (p), FRAME_SAMPLE_VISIBILITY (f))
-#define SET_FRAME_GARBAGED(f) (frame_garbaged = 1, f->garbaged = 1)
-#define FRAME_GARBAGED_P(f) (f)->garbaged
-#define FRAME_NO_SPLIT_P(f) (f)->no_split
-#define FRAME_WANTS_MODELINE_P(f) (f)->wants_modeline
-#define FRAME_ICONIFIED_P(f) (f)->iconified
-#define FRAME_WINDOW_SIZES_CHANGED(f) (f)->window_sizes_changed
-#define FRAME_MINIBUF_WINDOW(f) (f)->minibuffer_window
-#define FRAME_ROOT_WINDOW(f) (f)->root_window
-#define FRAME_SELECTED_WINDOW(f) (f)->selected_window
-#define SET_GLYPHS_FRAME(glyphs,frame) ((glyphs)->frame = (frame))
-#define FRAME_INSERT_COST(f) (f)->insert_line_cost
-#define FRAME_DELETE_COST(f) (f)->delete_line_cost
-#define FRAME_INSERTN_COST(f) (f)->insert_n_lines_cost
-#define FRAME_DELETEN_COST(f) (f)->delete_n_lines_cost
-#define FRAME_MESSAGE_BUF(f) (f)->message_buf
-#define FRAME_SCROLL_BOTTOM_VPOS(f) (f)->scroll_bottom_vpos
-#define FRAME_FOCUS_FRAME(f) (f)->focus_frame
-#define FRAME_CAN_HAVE_SCROLL_BARS(f) ((f)->can_have_scroll_bars)
-#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((f)->vertical_scroll_bar_type)
-#define FRAME_HAS_VERTICAL_SCROLL_BARS(f) \
- ((f)->vertical_scroll_bar_type != vertical_scroll_bar_none)
-#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT(f) \
- ((f)->vertical_scroll_bar_type == vertical_scroll_bar_left)
-#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) \
- ((f)->vertical_scroll_bar_type == vertical_scroll_bar_right)
-#define FRAME_SCROLL_BAR_PIXEL_WIDTH(f) ((f)->scroll_bar_pixel_width)
-#define FRAME_SCROLL_BAR_COLS(f) ((f)->scroll_bar_cols)
-#define FRAME_LEFT_SCROLL_BAR_WIDTH(f) \
- (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f) \
- ? FRAME_SCROLL_BAR_COLS (f) \
- : 0)
-#define FRAME_SCROLL_BAR_WIDTH(f) \
- (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \
- ? FRAME_SCROLL_BAR_COLS (f) \
- : 0)
-#define FRAME_WINDOW_WIDTH_ARG(f, width) \
- ((width) + FRAME_SCROLL_BAR_WIDTH (f))
-#define FRAME_WINDOW_WIDTH(f) ((f)->window_width)
-#define SET_FRAME_WIDTH(f,val) ((f)->width = (val), (f)->window_width = FRAME_WINDOW_WIDTH_ARG (f, (f)->width))
-#define FRAME_SCROLL_BARS(f) ((f)->scroll_bars)
-#define FRAME_CONDEMNED_SCROLL_BARS(f) ((f)->condemned_scroll_bars)
-#define FRAME_MENU_BAR_ITEMS(f) ((f)->menu_bar_items)
-#define FRAME_COST_BAUD_RATE(f) ((f)->cost_calculation_baud_rate)
-
-/* Emacs's redisplay code could become confused if a frame's
- visibility changes at arbitrary times. For example, if a frame is
- visible while the desired glyphs are being built, but becomes
- invisible before they are updated, then some rows of the
- desired_glyphs will be left marked as enabled after redisplay is
- complete, which should never happen. The next time the frame
- becomes visible, redisplay will probably barf.
-
- Currently, there are no similar situations involving iconified, but
- the principle is the same.
-
- So instead of having asynchronous input handlers directly set and
- clear the frame's visibility and iconification flags, they just set
- the async_visible and async_iconified flags; the redisplay code
- calls the FRAME_SAMPLE_VISIBILITY macro before doing any redisplay,
- which sets visible and iconified from their asynchronous
- counterparts.
-
- Synchronous code must use the FRAME_SET_VISIBLE macro.
-
- Also, if a frame used to be invisible, but has just become visible,
- it must be marked as garbaged, since redisplay hasn't been keeping
- up its contents. */
-#define FRAME_SAMPLE_VISIBILITY(f) \
- (((f)->async_visible && ! (f)->visible) ? SET_FRAME_GARBAGED (f) : 0, \
- (f)->visible = (f)->async_visible, \
- (f)->iconified = (f)->async_iconified)
-
-#define CHECK_FRAME(x, i) \
- { \
- if (! FRAMEP (x)) \
- x = wrong_type_argument (Qframep, (x)); \
- }
-
-#define CHECK_LIVE_FRAME(x, i) \
- { \
- if (! FRAMEP (x) \
- || ! FRAME_LIVE_P (XFRAME (x))) \
- x = wrong_type_argument (Qframe_live_p, (x)); \
- }
-
-/* FOR_EACH_FRAME (LIST_VAR, FRAME_VAR) followed by a statement is a
- `for' loop which iterates over the elements of Vframe_list. The
- loop will set FRAME_VAR, a Lisp_Object, to each frame in
- Vframe_list in succession and execute the statement. LIST_VAR
- should be a Lisp_Object too; it is used to iterate through the
- Vframe_list.
-
- This macro is a holdover from a time when multiple frames weren't always
- supported. An alternate definition of the macro would expand to
- something which executes the statement once. */
-#define FOR_EACH_FRAME(list_var, frame_var) \
- for ((list_var) = Vframe_list; \
- (CONSP (list_var) \
- && (frame_var = XCONS (list_var)->car, 1)); \
- list_var = XCONS (list_var)->cdr)
-
-
-extern Lisp_Object Qframep, Qframe_live_p, Qicon;
-
-extern struct frame *selected_frame;
-extern struct frame *last_nonminibuf_frame;
-
-extern struct frame *make_terminal_frame ();
-extern struct frame *make_frame ();
-extern struct frame *make_minibuffer_frame ();
-extern struct frame *make_frame_without_minibuffer ();
-
-extern Lisp_Object Vframe_list;
-extern Lisp_Object Vdefault_frame_alist;
-
-extern Lisp_Object Vterminal_frame;
-
-/* Device-independent scroll bar stuff. */
-
-/* Return the starting column (zero-based) of the vertical scroll bar
- for window W. The column before this one is the last column we can
- use for text. If the window touches the right edge of the frame,
- we have extra space allocated for it. Otherwise, the scroll bar
- takes over the window's rightmost columns. */
-#define WINDOW_VERTICAL_SCROLL_BAR_COLUMN(w) \
- (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (XFRAME (WINDOW_FRAME (w))) ? \
- (((XINT ((w)->left) + XINT ((w)->width)) \
- < FRAME_WIDTH (XFRAME (WINDOW_FRAME (w)))) \
- ? (XINT ((w)->left) + XINT ((w)->width) \
- - FRAME_SCROLL_BAR_COLS (XFRAME (WINDOW_FRAME (w)))) \
- : FRAME_WIDTH (XFRAME (WINDOW_FRAME (w)))) \
- : XINT ((w)->left))
-
-/* Return the height in lines of the vertical scroll bar in w. If the
- window has a mode line, don't make the scroll bar extend that far. */
-#define WINDOW_VERTICAL_SCROLL_BAR_HEIGHT(w) (window_internal_height (w))
diff --git a/src/getloadavg.c b/src/getloadavg.c
deleted file mode 100644
index 6209fef76f9..00000000000
--- a/src/getloadavg.c
+++ /dev/null
@@ -1,1022 +0,0 @@
-/* Get the system load averages.
- Copyright (C) 1985, 86, 87, 88, 89, 91, 92, 93, 1994, 1995
- 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 2, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- USA. */
-
-/* Compile-time symbols that this file uses:
-
- FIXUP_KERNEL_SYMBOL_ADDR() Adjust address in returned struct nlist.
- KERNEL_FILE Pathname of the kernel to nlist.
- LDAV_CVT() Scale the load average from the kernel.
- Returns a double.
- LDAV_SYMBOL Name of kernel symbol giving load average.
- LOAD_AVE_TYPE Type of the load average array in the kernel.
- Must be defined unless one of
- apollo, DGUX, NeXT, or UMAX is defined;
- otherwise, no load average is available.
- NLIST_STRUCT Include nlist.h, not a.out.h, and
- the nlist n_name element is a pointer,
- not an array.
- NLIST_NAME_UNION struct nlist has an n_un member, not n_name.
- LINUX_LDAV_FILE [__linux__]: File containing load averages.
-
- Specific system predefines this file uses, aside from setting
- default values if not emacs:
-
- apollo
- BSD Real BSD, not just BSD-like.
- convex
- DGUX
- eunice UNIX emulator under VMS.
- hpux
- MSDOS No-op for MSDOS.
- NeXT
- sgi
- sequent Sequent Dynix 3.x.x (BSD)
- _SEQUENT_ Sequent DYNIX/ptx 1.x.x (SYSV)
- sony_news NEWS-OS (works at least for 4.1C)
- UMAX
- UMAX4_3
- VMS
- WIN32 No-op for Windows95/NT.
- __linux__ Linux: assumes /proc filesystem mounted.
- Support from Michael K. Johnson.
- __NetBSD__ NetBSD: assumes /kern filesystem mounted.
-
- In addition, to avoid nesting many #ifdefs, we internally set
- LDAV_DONE to indicate that the load average has been computed.
-
- We also #define LDAV_PRIVILEGED if a program will require
- special installation to be able to call getloadavg. */
-
-/* This should always be first. */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sys/types.h>
-
-/* Both the Emacs and non-Emacs sections want this. Some
- configuration files' definitions for the LOAD_AVE_CVT macro (like
- sparc.h's) use macros like FSCALE, defined here. */
-#ifdef unix
-#include <sys/param.h>
-#endif
-
-
-/* Exclude all the code except the test program at the end
- if the system has its own `getloadavg' function.
-
- The declaration of `errno' is needed by the test program
- as well as the function itself, so it comes first. */
-
-#include <errno.h>
-
-#ifndef errno
-extern int errno;
-#endif
-
-#ifndef HAVE_GETLOADAVG
-
-
-/* The existing Emacs configuration files define a macro called
- LOAD_AVE_CVT, which accepts a value of type LOAD_AVE_TYPE, and
- returns the load average multiplied by 100. What we actually want
- is a macro called LDAV_CVT, which returns the load average as an
- unmultiplied double.
-
- For backwards compatibility, we'll define LDAV_CVT in terms of
- LOAD_AVE_CVT, but future machine config files should just define
- LDAV_CVT directly. */
-
-#if !defined(LDAV_CVT) && defined(LOAD_AVE_CVT)
-#define LDAV_CVT(n) (LOAD_AVE_CVT (n) / 100.0)
-#endif
-
-#if !defined (BSD) && defined (ultrix)
-/* Ultrix behaves like BSD on Vaxen. */
-#define BSD
-#endif
-
-#ifdef NeXT
-/* NeXT in the 2.{0,1,2} releases defines BSD in <sys/param.h>, which
- conflicts with the definition understood in this file, that this
- really is BSD. */
-#undef BSD
-
-/* NeXT defines FSCALE in <sys/param.h>. However, we take FSCALE being
- defined to mean that the nlist method should be used, which is not true. */
-#undef FSCALE
-#endif
-
-/* Set values that are different from the defaults, which are
- set a little farther down with #ifndef. */
-
-
-/* Some shorthands. */
-
-#if defined (HPUX) && !defined (hpux)
-#define hpux
-#endif
-
-#if defined (__hpux) && !defined (hpux)
-#define hpux
-#endif
-
-#if defined (__sun) && !defined (sun)
-#define sun
-#endif
-
-#if defined(hp300) && !defined(hpux)
-#define MORE_BSD
-#endif
-
-#if defined(ultrix) && defined(mips)
-#define decstation
-#endif
-
-#if (defined(sun) && defined(SVR4)) || defined (SOLARIS2)
-#define SUNOS_5
-#endif
-
-#if defined (__osf__) && (defined (__alpha) || defined (__alpha__))
-#define OSF_ALPHA
-#include <sys/table.h>
-#endif
-
-#if defined (__osf__) && (defined (mips) || defined (__mips__))
-#define OSF_MIPS
-#include <sys/table.h>
-#endif
-
-/* UTek's /bin/cc on the 4300 has no architecture specific cpp define by
- default, but _MACH_IND_SYS_TYPES is defined in <sys/types.h>. Combine
- that with a couple of other things and we'll have a unique match. */
-#if !defined (tek4300) && defined (unix) && defined (m68k) && defined (mc68000) && defined (mc68020) && defined (_MACH_IND_SYS_TYPES)
-#define tek4300 /* Define by emacs, but not by other users. */
-#endif
-
-
-/* VAX C can't handle multi-line #ifs, or lines longer than 256 chars. */
-#ifndef LOAD_AVE_TYPE
-
-#ifdef MORE_BSD
-#define LOAD_AVE_TYPE long
-#endif
-
-#ifdef sun
-#define LOAD_AVE_TYPE long
-#endif
-
-#ifdef decstation
-#define LOAD_AVE_TYPE long
-#endif
-
-#ifdef _SEQUENT_
-#define LOAD_AVE_TYPE long
-#endif
-
-#ifdef sgi
-#define LOAD_AVE_TYPE long
-#endif
-
-#ifdef SVR4
-#define LOAD_AVE_TYPE long
-#endif
-
-#ifdef sony_news
-#define LOAD_AVE_TYPE long
-#endif
-
-#ifdef sequent
-#define LOAD_AVE_TYPE long
-#endif
-
-#ifdef OSF_ALPHA
-#define LOAD_AVE_TYPE long
-#endif
-
-#if defined (ardent) && defined (titan)
-#define LOAD_AVE_TYPE long
-#endif
-
-#ifdef tek4300
-#define LOAD_AVE_TYPE long
-#endif
-
-#if defined(alliant) && defined(i860) /* Alliant FX/2800 */
-#define LOAD_AVE_TYPE long
-#endif
-
-#ifdef _AIX
-#define LOAD_AVE_TYPE long
-#endif
-
-#ifdef convex
-#define LOAD_AVE_TYPE double
-#ifndef LDAV_CVT
-#define LDAV_CVT(n) (n)
-#endif
-#endif
-
-#endif /* No LOAD_AVE_TYPE. */
-
-#ifdef OSF_ALPHA
-/* <sys/param.h> defines an incorrect value for FSCALE on Alpha OSF/1,
- according to ghazi@noc.rutgers.edu. */
-#undef FSCALE
-#define FSCALE 1024.0
-#endif
-
-#if defined(alliant) && defined(i860) /* Alliant FX/2800 */
-/* <sys/param.h> defines an incorrect value for FSCALE on an
- Alliant FX/2800 Concentrix 2.2, according to ghazi@noc.rutgers.edu. */
-#undef FSCALE
-#define FSCALE 100.0
-#endif
-
-
-#ifndef FSCALE
-
-/* SunOS and some others define FSCALE in sys/param.h. */
-
-#ifdef MORE_BSD
-#define FSCALE 2048.0
-#endif
-
-#if defined(MIPS) || defined(SVR4) || defined(decstation)
-#define FSCALE 256
-#endif
-
-#if defined (sgi) || defined (sequent)
-/* Sometimes both MIPS and sgi are defined, so FSCALE was just defined
- above under #ifdef MIPS. But we want the sgi value. */
-#undef FSCALE
-#define FSCALE 1000.0
-#endif
-
-#if defined (ardent) && defined (titan)
-#define FSCALE 65536.0
-#endif
-
-#ifdef tek4300
-#define FSCALE 100.0
-#endif
-
-#ifdef _AIX
-#define FSCALE 65536.0
-#endif
-
-#endif /* Not FSCALE. */
-
-#if !defined (LDAV_CVT) && defined (FSCALE)
-#define LDAV_CVT(n) (((double) (n)) / FSCALE)
-#endif
-
-/* VAX C can't handle multi-line #ifs, or lines longer that 256 characters. */
-#ifndef NLIST_STRUCT
-
-#ifdef MORE_BSD
-#define NLIST_STRUCT
-#endif
-
-#ifdef sun
-#define NLIST_STRUCT
-#endif
-
-#ifdef decstation
-#define NLIST_STRUCT
-#endif
-
-#ifdef hpux
-#define NLIST_STRUCT
-#endif
-
-#if defined (_SEQUENT_) || defined (sequent)
-#define NLIST_STRUCT
-#endif
-
-#ifdef sgi
-#define NLIST_STRUCT
-#endif
-
-#ifdef SVR4
-#define NLIST_STRUCT
-#endif
-
-#ifdef sony_news
-#define NLIST_STRUCT
-#endif
-
-#ifdef OSF_ALPHA
-#define NLIST_STRUCT
-#endif
-
-#if defined (ardent) && defined (titan)
-#define NLIST_STRUCT
-#endif
-
-#ifdef tek4300
-#define NLIST_STRUCT
-#endif
-
-#ifdef butterfly
-#define NLIST_STRUCT
-#endif
-
-#if defined(alliant) && defined(i860) /* Alliant FX/2800 */
-#define NLIST_STRUCT
-#endif
-
-#ifdef _AIX
-#define NLIST_STRUCT
-#endif
-
-#endif /* defined (NLIST_STRUCT) */
-
-
-#if defined(sgi) || (defined(mips) && !defined(BSD))
-#define FIXUP_KERNEL_SYMBOL_ADDR(nl) ((nl)[0].n_value &= ~(1 << 31))
-#endif
-
-
-#if !defined (KERNEL_FILE) && defined (sequent)
-#define KERNEL_FILE "/dynix"
-#endif
-
-#if !defined (KERNEL_FILE) && defined (hpux)
-#define KERNEL_FILE "/hp-ux"
-#endif
-
-#if !defined(KERNEL_FILE) && (defined(_SEQUENT_) || defined(MIPS) || defined(SVR4) || defined(ISC) || defined (sgi) || defined(SVR4) || (defined (ardent) && defined (titan)))
-#define KERNEL_FILE "/unix"
-#endif
-
-
-#if !defined (LDAV_SYMBOL) && defined (alliant)
-#define LDAV_SYMBOL "_Loadavg"
-#endif
-
-#if !defined(LDAV_SYMBOL) && ((defined(hpux) && !defined(hp9000s300)) || defined(_SEQUENT_) || defined(SVR4) || defined(ISC) || defined(sgi) || (defined (ardent) && defined (titan)) || defined (_AIX))
-#define LDAV_SYMBOL "avenrun"
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <stdio.h>
-
-/* LOAD_AVE_TYPE should only get defined if we're going to use the
- nlist method. */
-#if !defined(LOAD_AVE_TYPE) && (defined(BSD) || defined(LDAV_CVT) || defined(KERNEL_FILE) || defined(LDAV_SYMBOL))
-#define LOAD_AVE_TYPE double
-#endif
-
-#ifdef LOAD_AVE_TYPE
-
-#ifndef VMS
-#ifndef NLIST_STRUCT
-#include <a.out.h>
-#else /* NLIST_STRUCT */
-#include <nlist.h>
-#endif /* NLIST_STRUCT */
-
-#ifdef SUNOS_5
-#include <fcntl.h>
-#include <kvm.h>
-#include <kstat.h>
-#endif
-
-#ifndef KERNEL_FILE
-#define KERNEL_FILE "/vmunix"
-#endif /* KERNEL_FILE */
-
-#ifndef LDAV_SYMBOL
-#define LDAV_SYMBOL "_avenrun"
-#endif /* LDAV_SYMBOL */
-
-#else /* VMS */
-
-#ifndef eunice
-#include <iodef.h>
-#include <descrip.h>
-#else /* eunice */
-#include <vms/iodef.h>
-#endif /* eunice */
-#endif /* VMS */
-
-#ifndef LDAV_CVT
-#define LDAV_CVT(n) ((double) (n))
-#endif /* !LDAV_CVT */
-
-#endif /* LOAD_AVE_TYPE */
-
-#ifdef NeXT
-#ifdef HAVE_MACH_MACH_H
-#include <mach/mach.h>
-#else
-#include <mach.h>
-#endif
-#endif /* NeXT */
-
-#ifdef sgi
-#include <sys/sysmp.h>
-#endif /* sgi */
-
-#ifdef UMAX
-#include <stdio.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <sys/syscall.h>
-
-#ifdef UMAX_43
-#include <machine/cpu.h>
-#include <inq_stats/statistics.h>
-#include <inq_stats/sysstats.h>
-#include <inq_stats/cpustats.h>
-#include <inq_stats/procstats.h>
-#else /* Not UMAX_43. */
-#include <sys/sysdefs.h>
-#include <sys/statistics.h>
-#include <sys/sysstats.h>
-#include <sys/cpudefs.h>
-#include <sys/cpustats.h>
-#include <sys/procstats.h>
-#endif /* Not UMAX_43. */
-#endif /* UMAX */
-
-#ifdef DGUX
-#include <sys/dg_sys_info.h>
-#endif
-
-#if defined(HAVE_FCNTL_H) || defined(_POSIX_VERSION)
-#include <fcntl.h>
-#else
-#include <sys/file.h>
-#endif
-
-/* Avoid static vars inside a function since in HPUX they dump as pure. */
-
-#ifdef NeXT
-static processor_set_t default_set;
-static int getloadavg_initialized;
-#endif /* NeXT */
-
-#ifdef UMAX
-static unsigned int cpus = 0;
-static unsigned int samples;
-#endif /* UMAX */
-
-#ifdef DGUX
-static struct dg_sys_info_load_info load_info; /* what-a-mouthful! */
-#endif /* DGUX */
-
-#ifdef LOAD_AVE_TYPE
-/* File descriptor open to /dev/kmem or VMS load ave driver. */
-static int channel;
-/* Nonzero iff channel is valid. */
-static int getloadavg_initialized;
-/* Offset in kmem to seek to read load average, or 0 means invalid. */
-static long offset;
-
-#if !defined(VMS) && !defined(sgi)
-static struct nlist nl[2];
-#endif /* Not VMS or sgi */
-
-#ifdef SUNOS_5
-static kvm_t *kd;
-#endif /* SUNOS_5 */
-
-#endif /* LOAD_AVE_TYPE */
-
-/* Put the 1 minute, 5 minute and 15 minute load averages
- into the first NELEM elements of LOADAVG.
- Return the number written (never more than 3, but may be less than NELEM),
- or -1 if an error occurred. */
-
-int
-getloadavg (loadavg, nelem)
- double loadavg[];
- int nelem;
-{
- int elem = 0; /* Return value. */
-
-#ifdef NO_GET_LOAD_AVG
-#define LDAV_DONE
- /* Set errno to zero to indicate that there was no particular error;
- this function just can't work at all on this system. */
- errno = 0;
- elem = -1;
-#endif
-
-#if !defined (LDAV_DONE) && defined (SUNOS_5)
-/* Use libkstat because we don't have to be root. */
-#define LDAV_DONE
- kstat_ctl_t *kc;
- kstat_t *ksp;
- kstat_named_t *kn;
-
- kc = kstat_open ();
- if (kc == 0) return -1;
- ksp = kstat_lookup (kc, "unix", 0, "system_misc");
- if (ksp == 0 ) return -1;
- if (kstat_read (kc, ksp, 0) == -1) return -1;
-
-
- kn = kstat_data_lookup (ksp, "avenrun_1min");
- if (kn == 0)
- {
- /* Return -1 if no load average information is available. */
- nelem = 0;
- elem = -1;
- }
-
- if (nelem >= 1)
- loadavg[elem++] = (double) kn->value.ul/FSCALE;
-
- if (nelem >= 2)
- {
- kn = kstat_data_lookup (ksp, "avenrun_5min");
- if (kn != 0)
- {
- loadavg[elem++] = (double) kn->value.ul/FSCALE;
-
- if (nelem >= 3)
- {
- kn = kstat_data_lookup (ksp, "avenrun_15min");
- if (kn != 0)
- loadavg[elem++] = (double) kn->value.ul/FSCALE;
- }
- }
- }
-
- kstat_close (kc);
-#endif /* SUNOS_5 */
-
-#if !defined (LDAV_DONE) && defined (__linux__)
-#define LDAV_DONE
-#undef LOAD_AVE_TYPE
-
-#ifndef LINUX_LDAV_FILE
-#define LINUX_LDAV_FILE "/proc/loadavg"
-#endif
-
- char ldavgbuf[40];
- double load_ave[3];
- int fd, count;
-
- fd = open (LINUX_LDAV_FILE, O_RDONLY);
- if (fd == -1)
- return -1;
- count = read (fd, ldavgbuf, 40);
- (void) close (fd);
- if (count <= 0)
- return -1;
-
- count = sscanf (ldavgbuf, "%lf %lf %lf",
- &load_ave[0], &load_ave[1], &load_ave[2]);
- if (count < 1)
- return -1;
-
- for (elem = 0; elem < nelem && elem < count; elem++)
- loadavg[elem] = load_ave[elem];
-
- return elem;
-
-#endif /* __linux__ */
-
-#if !defined (LDAV_DONE) && defined (__NetBSD__)
-#define LDAV_DONE
-#undef LOAD_AVE_TYPE
-
-#ifndef NETBSD_LDAV_FILE
-#define NETBSD_LDAV_FILE "/kern/loadavg"
-#endif
-
- unsigned long int load_ave[3], scale;
- int count;
- FILE *fp;
-
- fp = fopen (NETBSD_LDAV_FILE, "r");
- if (fp == NULL)
- return -1;
- count = fscanf (fp, "%lu %lu %lu %lu\n",
- &load_ave[0], &load_ave[1], &load_ave[2],
- &scale);
- (void) fclose (fp);
- if (count != 4)
- return -1;
-
- for (elem = 0; elem < nelem; elem++)
- loadavg[elem] = (double) load_ave[elem] / (double) scale;
-
- return elem;
-
-#endif /* __NetBSD__ */
-
-#if !defined (LDAV_DONE) && defined (NeXT)
-#define LDAV_DONE
- /* The NeXT code was adapted from iscreen 3.2. */
-
- host_t host;
- struct processor_set_basic_info info;
- unsigned info_count;
-
- /* We only know how to get the 1-minute average for this system,
- so even if the caller asks for more than 1, we only return 1. */
-
- if (!getloadavg_initialized)
- {
- if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS)
- getloadavg_initialized = 1;
- }
-
- if (getloadavg_initialized)
- {
- info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
- if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host,
- (processor_set_info_t) &info, &info_count)
- != KERN_SUCCESS)
- getloadavg_initialized = 0;
- else
- {
- if (nelem > 0)
- loadavg[elem++] = (double) info.load_average / LOAD_SCALE;
- }
- }
-
- if (!getloadavg_initialized)
- return -1;
-#endif /* NeXT */
-
-#if !defined (LDAV_DONE) && defined (UMAX)
-#define LDAV_DONE
-/* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not
- have a /dev/kmem. Information about the workings of the running kernel
- can be gathered with inq_stats system calls.
- We only know how to get the 1-minute average for this system. */
-
- struct proc_summary proc_sum_data;
- struct stat_descr proc_info;
- double load;
- register unsigned int i, j;
-
- if (cpus == 0)
- {
- register unsigned int c, i;
- struct cpu_config conf;
- struct stat_descr desc;
-
- desc.sd_next = 0;
- desc.sd_subsys = SUBSYS_CPU;
- desc.sd_type = CPUTYPE_CONFIG;
- desc.sd_addr = (char *) &conf;
- desc.sd_size = sizeof conf;
-
- if (inq_stats (1, &desc))
- return -1;
-
- c = 0;
- for (i = 0; i < conf.config_maxclass; ++i)
- {
- struct class_stats stats;
- bzero ((char *) &stats, sizeof stats);
-
- desc.sd_type = CPUTYPE_CLASS;
- desc.sd_objid = i;
- desc.sd_addr = (char *) &stats;
- desc.sd_size = sizeof stats;
-
- if (inq_stats (1, &desc))
- return -1;
-
- c += stats.class_numcpus;
- }
- cpus = c;
- samples = cpus < 2 ? 3 : (2 * cpus / 3);
- }
-
- proc_info.sd_next = 0;
- proc_info.sd_subsys = SUBSYS_PROC;
- proc_info.sd_type = PROCTYPE_SUMMARY;
- proc_info.sd_addr = (char *) &proc_sum_data;
- proc_info.sd_size = sizeof (struct proc_summary);
- proc_info.sd_sizeused = 0;
-
- if (inq_stats (1, &proc_info) != 0)
- return -1;
-
- load = proc_sum_data.ps_nrunnable;
- j = 0;
- for (i = samples - 1; i > 0; --i)
- {
- load += proc_sum_data.ps_nrun[j];
- if (j++ == PS_NRUNSIZE)
- j = 0;
- }
-
- if (nelem > 0)
- loadavg[elem++] = load / samples / cpus;
-#endif /* UMAX */
-
-#if !defined (LDAV_DONE) && defined (DGUX)
-#define LDAV_DONE
- /* This call can return -1 for an error, but with good args
- it's not supposed to fail. The first argument is for no
- apparent reason of type `long int *'. */
- dg_sys_info ((long int *) &load_info,
- DG_SYS_INFO_LOAD_INFO_TYPE,
- DG_SYS_INFO_LOAD_VERSION_0);
-
- if (nelem > 0)
- loadavg[elem++] = load_info.one_minute;
- if (nelem > 1)
- loadavg[elem++] = load_info.five_minute;
- if (nelem > 2)
- loadavg[elem++] = load_info.fifteen_minute;
-#endif /* DGUX */
-
-#if !defined (LDAV_DONE) && defined (apollo)
-#define LDAV_DONE
-/* Apollo code from lisch@mentorg.com (Ray Lischner).
-
- This system call is not documented. The load average is obtained as
- three long integers, for the load average over the past minute,
- five minutes, and fifteen minutes. Each value is a scaled integer,
- with 16 bits of integer part and 16 bits of fraction part.
-
- I'm not sure which operating system first supported this system call,
- but I know that SR10.2 supports it. */
-
- extern void proc1_$get_loadav ();
- unsigned long load_ave[3];
-
- proc1_$get_loadav (load_ave);
-
- if (nelem > 0)
- loadavg[elem++] = load_ave[0] / 65536.0;
- if (nelem > 1)
- loadavg[elem++] = load_ave[1] / 65536.0;
- if (nelem > 2)
- loadavg[elem++] = load_ave[2] / 65536.0;
-#endif /* apollo */
-
-#if !defined (LDAV_DONE) && defined (OSF_MIPS)
-#define LDAV_DONE
-
- struct tbl_loadavg load_ave;
- table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
- loadavg[elem++]
- = (load_ave.tl_lscale == 0
- ? load_ave.tl_avenrun.d[0]
- : (load_ave.tl_avenrun.l[0] / (double) load_ave.tl_lscale));
-#endif /* OSF_MIPS */
-
-#if !defined (LDAV_DONE) && (defined (MSDOS) || defined (WIN32))
-#define LDAV_DONE
-
- /* A faithful emulation is going to have to be saved for a rainy day. */
- for ( ; elem < nelem; elem++)
- {
- loadavg[elem] = 0.0;
- }
-#endif /* MSDOS */
-
-#if !defined (LDAV_DONE) && defined (OSF_ALPHA)
-#define LDAV_DONE
-
- struct tbl_loadavg load_ave;
- table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
- for (elem = 0; elem < nelem; elem++)
- loadavg[elem]
- = (load_ave.tl_lscale == 0
- ? load_ave.tl_avenrun.d[elem]
- : (load_ave.tl_avenrun.l[elem] / (double) load_ave.tl_lscale));
-#endif /* OSF_ALPHA */
-
-#if !defined (LDAV_DONE) && defined (VMS)
- /* VMS specific code -- read from the Load Ave driver. */
-
- LOAD_AVE_TYPE load_ave[3];
- static int getloadavg_initialized = 0;
-#ifdef eunice
- struct
- {
- int dsc$w_length;
- char *dsc$a_pointer;
- } descriptor;
-#endif
-
- /* Ensure that there is a channel open to the load ave device. */
- if (!getloadavg_initialized)
- {
- /* Attempt to open the channel. */
-#ifdef eunice
- descriptor.dsc$w_length = 18;
- descriptor.dsc$a_pointer = "$$VMS_LOAD_AVERAGE";
-#else
- $DESCRIPTOR (descriptor, "LAV0:");
-#endif
- if (sys$assign (&descriptor, &channel, 0, 0) & 1)
- getloadavg_initialized = 1;
- }
-
- /* Read the load average vector. */
- if (getloadavg_initialized
- && !(sys$qiow (0, channel, IO$_READVBLK, 0, 0, 0,
- load_ave, 12, 0, 0, 0, 0) & 1))
- {
- sys$dassgn (channel);
- getloadavg_initialized = 0;
- }
-
- if (!getloadavg_initialized)
- return -1;
-#endif /* VMS */
-
-#if !defined (LDAV_DONE) && defined(LOAD_AVE_TYPE) && !defined(VMS)
-
- /* UNIX-specific code -- read the average from /dev/kmem. */
-
-#define LDAV_PRIVILEGED /* This code requires special installation. */
-
- LOAD_AVE_TYPE load_ave[3];
-
- /* Get the address of LDAV_SYMBOL. */
- if (offset == 0)
- {
-#ifndef sgi
-#ifndef NLIST_STRUCT
- strcpy (nl[0].n_name, LDAV_SYMBOL);
- strcpy (nl[1].n_name, "");
-#else /* NLIST_STRUCT */
-#ifdef NLIST_NAME_UNION
- nl[0].n_un.n_name = LDAV_SYMBOL;
- nl[1].n_un.n_name = 0;
-#else /* not NLIST_NAME_UNION */
- nl[0].n_name = LDAV_SYMBOL;
- nl[1].n_name = 0;
-#endif /* not NLIST_NAME_UNION */
-#endif /* NLIST_STRUCT */
-
-#ifndef SUNOS_5
- if (
-#if !(defined (_AIX) && !defined (ps2))
- nlist (KERNEL_FILE, nl)
-#else /* _AIX */
- knlist (nl, 1, sizeof (nl[0]))
-#endif
- >= 0)
- /* Omit "&& nl[0].n_type != 0 " -- it breaks on Sun386i. */
- {
-#ifdef FIXUP_KERNEL_SYMBOL_ADDR
- FIXUP_KERNEL_SYMBOL_ADDR (nl);
-#endif
- offset = nl[0].n_value;
- }
-#endif /* !SUNOS_5 */
-#else /* sgi */
- int ldav_off;
-
- ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN);
- if (ldav_off != -1)
- offset = (long) ldav_off & 0x7fffffff;
-#endif /* sgi */
- }
-
- /* Make sure we have /dev/kmem open. */
- if (!getloadavg_initialized)
- {
-#ifndef SUNOS_5
- channel = open ("/dev/kmem", 0);
- if (channel >= 0)
- {
- /* Set the channel to close on exec, so it does not
- litter any child's descriptor table. */
-#ifdef FD_SETFD
-#ifndef FD_CLOEXEC
-#define FD_CLOEXEC 1
-#endif
- (void) fcntl (channel, F_SETFD, FD_CLOEXEC);
-#endif
- getloadavg_initialized = 1;
- }
-#else /* SUNOS_5 */
- /* We pass 0 for the kernel, corefile, and swapfile names
- to use the currently running kernel. */
- kd = kvm_open (0, 0, 0, O_RDONLY, 0);
- if (kd != 0)
- {
- /* nlist the currently running kernel. */
- kvm_nlist (kd, nl);
- offset = nl[0].n_value;
- getloadavg_initialized = 1;
- }
-#endif /* SUNOS_5 */
- }
-
- /* If we can, get the load average values. */
- if (offset && getloadavg_initialized)
- {
- /* Try to read the load. */
-#ifndef SUNOS_5
- if (lseek (channel, offset, 0) == -1L
- || read (channel, (char *) load_ave, sizeof (load_ave))
- != sizeof (load_ave))
- {
- close (channel);
- getloadavg_initialized = 0;
- }
-#else /* SUNOS_5 */
- if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave))
- != sizeof (load_ave))
- {
- kvm_close (kd);
- getloadavg_initialized = 0;
- }
-#endif /* SUNOS_5 */
- }
-
- if (offset == 0 || !getloadavg_initialized)
- return -1;
-#endif /* LOAD_AVE_TYPE and not VMS */
-
-#if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE) /* Including VMS. */
- if (nelem > 0)
- loadavg[elem++] = LDAV_CVT (load_ave[0]);
- if (nelem > 1)
- loadavg[elem++] = LDAV_CVT (load_ave[1]);
- if (nelem > 2)
- loadavg[elem++] = LDAV_CVT (load_ave[2]);
-
-#define LDAV_DONE
-#endif /* !LDAV_DONE && LOAD_AVE_TYPE */
-
-#ifdef LDAV_DONE
- return elem;
-#else
- /* Set errno to zero to indicate that there was no particular error;
- this function just can't work at all on this system. */
- errno = 0;
- return -1;
-#endif
-}
-
-#endif /* ! HAVE_GETLOADAVG */
-
-#ifdef TEST
-void
-main (argc, argv)
- int argc;
- char **argv;
-{
- int naptime = 0;
-
- if (argc > 1)
- naptime = atoi (argv[1]);
-
- while (1)
- {
- double avg[3];
- int loads;
-
- errno = 0; /* Don't be misled if it doesn't set errno. */
- loads = getloadavg (avg, 3);
- if (loads == -1)
- {
- perror ("Error getting load average");
- exit (1);
- }
- if (loads > 0)
- printf ("1-minute: %f ", avg[0]);
- if (loads > 1)
- printf ("5-minute: %f ", avg[1]);
- if (loads > 2)
- printf ("15-minute: %f ", avg[2]);
- if (loads > 0)
- putchar ('\n');
-
- if (naptime == 0)
- break;
- sleep (naptime);
- }
-
- exit (0);
-}
-#endif /* TEST */
diff --git a/src/getpagesize.h b/src/getpagesize.h
deleted file mode 100644
index a064973d15f..00000000000
--- a/src/getpagesize.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Emulate getpagesize on systems that lack it. */
-
-#ifndef HAVE_GETPAGESIZE
-
-# ifdef VMS
-# define getpagesize() 512
-# endif
-
-# ifdef HAVE_UNISTD_H
-# include <unistd.h>
-# endif
-
-# ifdef _SC_PAGESIZE
-# define getpagesize() sysconf(_SC_PAGESIZE)
-# else /* no _SC_PAGESIZE */
-# ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-# 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 */
-# ifdef NBPC
-# define getpagesize() NBPC
-# else /* no NBPC */
-# ifdef PAGESIZE
-# define getpagesize() PAGESIZE
-# endif /* PAGESIZE */
-# endif /* no NBPC */
-# endif /* no NBPG */
-# endif /* no EXEC_PAGESIZE */
-# else /* no HAVE_SYS_PARAM_H */
-# define getpagesize() 8192 /* punt totally */
-# endif /* no HAVE_SYS_PARAM_H */
-# endif /* no _SC_PAGESIZE */
-
-#endif /* no HAVE_GETPAGESIZE */
diff --git a/src/gnu.h b/src/gnu.h
deleted file mode 100644
index b5cf7261f7d..00000000000
--- a/src/gnu.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#define gnu_width 50
-#define gnu_height 50
-static unsigned char gnu_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0e,
- 0x00, 0x00, 0x0c, 0x00, 0x70, 0x00, 0x1e, 0x00, 0x00, 0x06, 0xc0, 0xdd,
- 0x01, 0x34, 0x00, 0x00, 0x07, 0x3c, 0x07, 0x03, 0x34, 0x00, 0x80, 0x03,
- 0x1f, 0x06, 0x06, 0x24, 0x00, 0x80, 0x03, 0x0f, 0x04, 0x0c, 0x26, 0x00,
- 0xc0, 0x81, 0x07, 0x00, 0x08, 0x33, 0x00, 0x60, 0xc1, 0xe3, 0x80, 0xbb,
- 0x31, 0x00, 0x30, 0xe1, 0x33, 0xfe, 0xff, 0x18, 0x00, 0x10, 0xf1, 0x31,
- 0xc7, 0xe3, 0x1f, 0x00, 0x10, 0xf1, 0xd8, 0x01, 0x05, 0x3c, 0x00, 0x10,
- 0x83, 0x6c, 0x00, 0x1a, 0x40, 0x00, 0x10, 0x66, 0x36, 0x54, 0xd5, 0xff,
- 0x00, 0x30, 0x3c, 0xdb, 0xab, 0x3a, 0x2a, 0x00, 0x60, 0x80, 0xe9, 0x54,
- 0x35, 0x00, 0x00, 0xe0, 0xe0, 0x6c, 0xb9, 0x6a, 0x00, 0x00, 0x80, 0x37,
- 0xb6, 0x66, 0x75, 0x00, 0x00, 0x00, 0x0f, 0xb6, 0xb4, 0x6a, 0x00, 0x00,
- 0x00, 0x06, 0xb3, 0x77, 0x75, 0x00, 0x00, 0x00, 0xe1, 0x19, 0xa7, 0x6a,
- 0x00, 0x00, 0xc0, 0xff, 0x19, 0x48, 0xf5, 0x00, 0x00, 0x40, 0x75, 0x15,
- 0xaf, 0xea, 0x00, 0x00, 0x00, 0x70, 0x35, 0x66, 0xd5, 0x00, 0x00, 0x00,
- 0x58, 0x6a, 0x80, 0xea, 0x00, 0x00, 0x00, 0xdc, 0xaa, 0x80, 0xd5, 0x01,
- 0x00, 0x00, 0x9c, 0x27, 0x03, 0xeb, 0x01, 0x00, 0x00, 0xbc, 0x65, 0x04,
- 0xd4, 0x01, 0x00, 0x00, 0x3c, 0x55, 0xed, 0x6b, 0x03, 0x00, 0x00, 0x3e,
- 0xcd, 0x2a, 0x3e, 0x02, 0x00, 0x00, 0x7e, 0xb9, 0x2a, 0xb8, 0x03, 0x00,
- 0x00, 0x7c, 0x93, 0x3d, 0x91, 0x03, 0x00, 0x00, 0x7c, 0x76, 0x77, 0x96,
- 0x01, 0x00, 0x00, 0xf8, 0x6d, 0xf6, 0xc4, 0x01, 0x00, 0x00, 0xf8, 0xdd,
- 0xfe, 0xc3, 0x01, 0x00, 0x00, 0xf0, 0xb1, 0xfd, 0xfc, 0x01, 0x00, 0x00,
- 0xd0, 0x2f, 0xe7, 0xc1, 0x00, 0x00, 0x00, 0xc0, 0x4f, 0xe6, 0x61, 0x00,
- 0x00, 0x00, 0x80, 0xff, 0xf6, 0x7f, 0x00, 0x00, 0x00, 0x80, 0xfe, 0x1c,
- 0x3e, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00};
diff --git a/src/hftctl.c b/src/hftctl.c
deleted file mode 100644
index 5fe816abbb5..00000000000
--- a/src/hftctl.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/* IBM has disclaimed copyright on this module. */
-
-/***************************************************************/
-/* */
-/* Function: hftctl */
-/* */
-/* Syntax: */
-/* #include <sys/ioctl.h> */
-/* #include <sys/hft.h> */
-/* */
-/* int hftctl(fildes, request, arg ) */
-/* int fildes, request; */
-/* char *arg; */
-/* */
-/* Description: */
-/* */
-/* Does the following: */
-/* 1. determines if fildes is pty */
-/* does normal ioctl it is not */
-/* 2. places fildes into raw mode */
-/* 3. converts ioctl arguments to datastream */
-/* 4. waits for 2 secs for acknowledgement before */
-/* timing out. */
-/* 5. places response in callers buffer ( just like */
-/* ioctl. */
-/* 6. returns fildes to its original mode */
-/* */
-/* User of this program should review steps 1,4, and 3. */
-/* hftctl makes no check on the request type. It must be */
-/* a HFT ioctl that is supported remotely. */
-/* This program will use the SIGALRM and alarm(2). Any */
-/* Previous alarms are lost. */
-/* */
-/* Users of this program are free to modify it any way */
-/* they want. */
-/* */
-/* Return Value: */
-/* */
-/* If ioctl fails, a value of -1 is returned and errno */
-/* is set to indicate the error. */
-/* */
-/***************************************************************/
-
-#include <sys/signal.h>
-#include <errno.h>
-
-#include <config.h>
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <setjmp.h>
-#include <sys/ioctl.h>
-#include <sys/devinfo.h>
-#include <termios.h>
-#include <termio.h>
-#include <sys/hft.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";
-
-/*************** LOCAL DEFINES **********************************/
-
-#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 ********************/
-
-static int hfqry();
-static int hfskbd();
- char *xmalloc();
-
-extern int errno;
-static jmp_buf hftenv;
-static int is_ack_vtd;
-static SIGTYPE (*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(); */
-
-/*************** 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])
-
- /* 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; }
-
-/*************** 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 void hft_alrm(int sig);
-#else
-static GT_ACK ();
-static WR_REQ ();
-static void hft_alrm ();
-#endif
-
-/*************** HFTCTL FUNCTION *******************************/
-
-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 */
-}
-
-/*************** HFSKBD FUNCTION ******************************/
-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));
-}
-
-/*************** HFQUERY FUNCTION ******************************/
-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));
-}
-
-
-/*************** GT_ACK FUNCTION ******************************/
-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;
-
- 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 */
-}
-
-/*************** HFT_ALRM FUNCTION ******************************/
-static void
-hft_alrm (sig) /* Function hft_alrm - handle */
- int sig; /* alarm signal */
-{
- signal (SIGALRM, sav_alrm); /* reset to previous */
-
- if (is_ack_vtd) /* has ack vtd arrived ? */
- return; /* yes, then continue */
- else /* no, then return with error */
- longjmp (hftenv, -1);
-
-}
-
-/*********************************************************************/
-/*** ***/
-/*** NOTE: Both the HFCTLREQ and the arg structure should be ***/
-/*** sent in one io write operation. If terminal ***/
-/*** emulators are in NODELAY mode then multiple writes ***/
-/*** may cause bogus information to be read by the emulator ***/
-/*** depending on the timing. ***/
-/*** ***/
-/*********************************************************************/
-
-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 = xmalloc(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 */
- xfree (p.c);
- return (0);
-
-}
diff --git a/src/indent.c b/src/indent.c
deleted file mode 100644
index 3ada091d45f..00000000000
--- a/src/indent.c
+++ /dev/null
@@ -1,1431 +0,0 @@
-/* Indentation functions.
- Copyright (C) 1985,86,87,88,93,94,95 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include "lisp.h"
-#include "buffer.h"
-#include "indent.h"
-#include "frame.h"
-#include "window.h"
-#include "termchar.h"
-#include "termopts.h"
-#include "disptab.h"
-#include "intervals.h"
-#include "region-cache.h"
-
-/* Indentation can insert tabs if this is non-zero;
- otherwise always uses spaces */
-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 */
-/* Last value returned by current_column */
-int last_known_column;
-/* Value of point when current_column was called */
-int last_known_column_point;
-/* Value of MODIFF when current_column was called */
-int last_known_column_modified;
-
-static int current_column_1 ();
-
-/* Get the display table to use for the current buffer. */
-
-struct Lisp_Char_Table *
-buffer_display_table ()
-{
- Lisp_Object thisbuf;
-
- thisbuf = current_buffer->display_table;
- if (DISP_TABLE_P (thisbuf))
- return XCHAR_TABLE (thisbuf);
- if (DISP_TABLE_P (Vstandard_display_table))
- return XCHAR_TABLE (Vstandard_display_table);
- return 0;
-}
-
-/* Width run cache considerations. */
-
-/* Return the width of character C under display table DP. */
-
-static int
-character_width (c, dp)
- int c;
- struct Lisp_Char_Table *dp;
-{
- Lisp_Object elt;
-
- /* These width computations were determined by examining the cases
- in display_text_line. */
-
- /* Everything can be handled by the display table, if it's
- present and the element is right. */
- if (dp && (elt = DISP_CHAR_VECTOR (dp, c), VECTORP (elt)))
- return XVECTOR (elt)->size;
-
- /* Some characters are special. */
- if (c == '\n' || c == '\t' || c == '\015')
- return 0;
-
- /* Printing characters have width 1. */
- else if (c >= 040 && c < 0177)
- return 1;
-
- /* Everybody else (control characters, metacharacters) has other
- widths. We could return their actual widths here, but they
- depend on things like ctl_arrow and crud like that, and they're
- not very common at all. So we'll just claim we don't know their
- widths. */
- else
- return 0;
-}
-
-/* Return true iff the display table DISPTAB specifies the same widths
- for characters as WIDTHTAB. We use this to decide when to
- invalidate the buffer's width_run_cache. */
-int
-disptab_matches_widthtab (disptab, widthtab)
- struct Lisp_Char_Table *disptab;
- struct Lisp_Vector *widthtab;
-{
- int i;
-
- if (widthtab->size != 256)
- abort ();
-
- for (i = 0; i < 256; i++)
- if (character_width (i, disptab)
- != XFASTINT (widthtab->contents[i]))
- return 0;
-
- return 1;
-}
-
-/* Recompute BUF's width table, using the display table DISPTAB. */
-void
-recompute_width_table (buf, disptab)
- struct buffer *buf;
- struct Lisp_Char_Table *disptab;
-{
- int i;
- struct Lisp_Vector *widthtab;
-
- if (!VECTORP (buf->width_table))
- buf->width_table = Fmake_vector (make_number (256), make_number (0));
- widthtab = XVECTOR (buf->width_table);
- if (widthtab->size != 256)
- abort ();
-
- for (i = 0; i < 256; i++)
- XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
-}
-
-/* Allocate or free the width run cache, as requested by the current
- state of current_buffer's cache_long_line_scans variable. */
-static void
-width_run_cache_on_off ()
-{
- if (NILP (current_buffer->cache_long_line_scans))
- {
- /* It should be off. */
- if (current_buffer->width_run_cache)
- {
- free_region_cache (current_buffer->width_run_cache);
- current_buffer->width_run_cache = 0;
- current_buffer->width_table = Qnil;
- }
- }
- else
- {
- /* It should be on. */
- if (current_buffer->width_run_cache == 0)
- {
- current_buffer->width_run_cache = new_region_cache ();
- recompute_width_table (current_buffer, buffer_display_table ());
- }
- }
-}
-
-
-/* Skip some invisible characters starting from POS.
- This includes characters invisible because of text properties
- and characters invisible because of overlays.
-
- If position POS is followed by invisible characters,
- skip some of them and return the position after them.
- Otherwise return POS itself.
-
- Set *NEXT_BOUNDARY_P to the next position at which
- it will be necessary to call this function again.
-
- Don't scan past TO, and don't set *NEXT_BOUNDARY_P
- to a value greater than TO.
-
- If WINDOW is non-nil, and this buffer is displayed in WINDOW,
- take account of overlays that apply only in WINDOW.
-
- We don't necessarily skip all the invisible characters after POS
- because that could take a long time. We skip a reasonable number
- which can be skipped quickly. If there might be more invisible
- characters immediately following, then *NEXT_BOUNDARY_P
- will equal the return value. */
-
-static int
-skip_invisible (pos, next_boundary_p, to, window)
- int pos;
- int *next_boundary_p;
- int to;
- Lisp_Object window;
-{
- Lisp_Object prop, position, end, overlay_limit, proplimit;
- Lisp_Object buffer;
-
- XSETFASTINT (position, pos);
- XSETBUFFER (buffer, current_buffer);
-
- /* Give faster response for overlay lookup near POS. */
- recenter_overlay_lists (current_buffer, pos);
-
- /* We must not advance farther than the next overlay change.
- The overlay change might change the invisible property;
- or there might be overlay strings to be displayed there. */
- overlay_limit = Fnext_overlay_change (position);
- /* As for text properties, this gives a lower bound
- for where the invisible text property could change. */
- proplimit = Fnext_property_change (position, buffer, Qt);
- if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
- proplimit = overlay_limit;
- /* PROPLIMIT is now a lower bound for the next change
- in invisible status. If that is plenty far away,
- use that lower bound. */
- if (XFASTINT (proplimit) > pos + 100 || XFASTINT (proplimit) >= to)
- *next_boundary_p = XFASTINT (proplimit);
- /* Otherwise, scan for the next `invisible' property change. */
- else
- {
- /* Don't scan terribly far. */
- XSETFASTINT (proplimit, min (pos + 100, to));
- /* No matter what. don't go past next overlay change. */
- if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
- proplimit = overlay_limit;
- end = Fnext_single_property_change (position, Qinvisible,
- buffer, proplimit);
- *next_boundary_p = XFASTINT (end);
- }
- /* if the `invisible' property is set, we can skip to
- the next property change */
- if (!NILP (window) && EQ (XWINDOW (window)->buffer, buffer))
- prop = Fget_char_property (position, Qinvisible, window);
- else
- prop = Fget_char_property (position, Qinvisible, buffer);
- if (TEXT_PROP_MEANS_INVISIBLE (prop))
- return *next_boundary_p;
- return pos;
-}
-
-DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0,
- "Return the horizontal position of point. Beginning of line is column 0.\n\
-This 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 frame, which means that this function may return\n\
-values greater than (frame-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.")
- ()
-{
- Lisp_Object temp;
- XSETFASTINT (temp, current_column ());
- 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 int tab_seen;
- int post_tab;
- register int c;
- register int tab_width = XINT (current_buffer->tab_width);
- int ctl_arrow = !NILP (current_buffer->ctl_arrow);
- register struct Lisp_Char_Table *dp = buffer_display_table ();
- int stopchar;
-
- if (PT == last_known_column_point
- && MODIFF == last_known_column_modified)
- return last_known_column;
-
- /* If the buffer has overlays or text properties,
- use a more general algorithm. */
- if (BUF_INTERVALS (current_buffer)
- || !NILP (current_buffer->overlays_before)
- || !NILP (current_buffer->overlays_after))
- return current_column_1 (PT);
-
- /* Scan backwards from point to the previous newline,
- counting width. Tab characters are the only complicated case. */
-
- /* Make a pointer for decrementing through the chars before point. */
- ptr = &FETCH_CHAR (PT - 1) + 1;
- /* Make a pointer to where consecutive chars leave off,
- going backwards from point. */
- if (PT == BEGV)
- stop = ptr;
- else if (PT <= GPT || BEGV > GPT)
- stop = BEGV_ADDR;
- else
- stop = GAP_END_ADDR;
-
- if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
-
- col = 0, tab_seen = 0, post_tab = 0;
-
- while (1)
- {
- if (ptr == stop)
- {
- /* We stopped either for the beginning of the buffer
- or for the gap. */
- if (ptr == BEGV_ADDR)
- break;
- /* It was the gap. Jump back over it. */
- stop = BEGV_ADDR;
- ptr = GPT_ADDR;
- /* Check whether that brings us to beginning of buffer. */
- if (BEGV >= GPT) break;
- }
-
- c = *--ptr;
- if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
- col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
- else if (c >= 040 && c < 0177)
- col++;
- else if (c == '\n')
- break;
- else if (c == '\r' && EQ (current_buffer->selective_display, Qt))
- break;
- else if (c == '\t')
- {
- if (tab_seen)
- col = ((col + tab_width) / tab_width) * tab_width;
-
- post_tab += col;
- col = 0;
- tab_seen = 1;
- }
- else
- col += (ctl_arrow && c < 0200) ? 2 : 4;
- }
-
- if (tab_seen)
- {
- col = ((col + tab_width) / tab_width) * tab_width;
- col += post_tab;
- }
-
- last_known_column = col;
- last_known_column_point = PT;
- last_known_column_modified = MODIFF;
-
- return col;
-}
-
-/* Return the column number of position POS
- by scanning forward from the beginning of the line.
- This function handles characters that are invisible
- due to text properties or overlays. */
-
-static int
-current_column_1 (pos)
- int pos;
-{
- register int tab_width = XINT (current_buffer->tab_width);
- register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
- register struct Lisp_Char_Table *dp = buffer_display_table ();
-
- /* Start the scan at the beginning of this line with column number 0. */
- register int col = 0;
- int scan = find_next_newline (pos, -1);
- int next_boundary = scan;
-
- if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
-
- /* Scan forward to the target position. */
- while (scan < pos)
- {
- int c;
-
- /* Occasionally we may need to skip invisible text. */
- while (scan == next_boundary)
- {
- /* This updates NEXT_BOUNDARY to the next place
- where we might need to skip more invisible text. */
- scan = skip_invisible (scan, &next_boundary, pos, Qnil);
- if (scan >= pos)
- goto endloop;
- }
-
- c = FETCH_CHAR (scan);
- if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
- {
- col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
- scan++;
- continue;
- }
- if (c == '\n')
- break;
- if (c == '\r' && EQ (current_buffer->selective_display, Qt))
- break;
- scan++;
- if (c == '\t')
- {
- int prev_col = col;
- col += tab_width;
- col = col / tab_width * tab_width;
- }
- else if (ctl_arrow && (c < 040 || c == 0177))
- col += 2;
- else if (c < 040 || c >= 0177)
- col += 4;
- else
- col++;
- }
- endloop:
-
- last_known_column = col;
- last_known_column_point = PT;
- last_known_column_modified = MODIFF;
-
- return col;
-}
-
-/* Return the width in columns of the part of STRING from BEG to END.
- If BEG is nil, that stands for the beginning of STRING.
- If END is nil, that stands for the end of STRING. */
-
-static int
-string_display_width (string, beg, end)
- Lisp_Object string, beg, end;
-{
- register int col;
- register unsigned char *ptr, *stop;
- register int tab_seen;
- int post_tab;
- register int c;
- register int tab_width = XINT (current_buffer->tab_width);
- int ctl_arrow = !NILP (current_buffer->ctl_arrow);
- register struct Lisp_Char_Table *dp = buffer_display_table ();
- int b, e;
-
- if (NILP (end))
- e = XSTRING (string)->size;
- else
- {
- CHECK_NUMBER (end, 0);
- e = XINT (end);
- }
-
- if (NILP (beg))
- b = 0;
- else
- {
- CHECK_NUMBER (beg, 0);
- b = XINT (beg);
- }
-
- /* Make a pointer for decrementing through the chars before point. */
- ptr = XSTRING (string)->data + e;
- /* Make a pointer to where consecutive chars leave off,
- going backwards from point. */
- stop = XSTRING (string)->data + b;
-
- if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
-
- col = 0, tab_seen = 0, post_tab = 0;
-
- while (1)
- {
- if (ptr == stop)
- break;
-
- c = *--ptr;
- if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
- col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
- else if (c >= 040 && c < 0177)
- col++;
- else if (c == '\n')
- break;
- else if (c == '\t')
- {
- if (tab_seen)
- col = ((col + tab_width) / tab_width) * tab_width;
-
- post_tab += col;
- col = 0;
- tab_seen = 1;
- }
- else
- col += (ctl_arrow && c < 0200) ? 2 : 4;
- }
-
- if (tab_seen)
- {
- col = ((col + tab_width) / tab_width) * tab_width;
- col += post_tab;
- }
-
- return col;
-}
-
-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 MININUM says always do at least MININUM spaces\n\
-even if that goes past COLUMN; by default, MININUM is zero.")
- (column, minimum)
- Lisp_Object column, minimum;
-{
- int mincol;
- register int fromcol;
- register int tab_width = XINT (current_buffer->tab_width);
-
- CHECK_NUMBER (column, 0);
- if (NILP (minimum))
- XSETFASTINT (minimum, 0);
- CHECK_NUMBER (minimum, 1);
-
- fromcol = current_column ();
- mincol = fromcol + XINT (minimum);
- if (mincol < XINT (column)) mincol = XINT (column);
-
- if (fromcol == mincol)
- return make_number (mincol);
-
- if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
-
- if (indent_tabs_mode)
- {
- Lisp_Object n;
- XSETFASTINT (n, mincol / tab_width - fromcol / tab_width);
- if (XFASTINT (n) != 0)
- {
- Finsert_char (make_number ('\t'), n, Qt);
-
- fromcol = (mincol / tab_width) * tab_width;
- }
- }
-
- XSETFASTINT (column, mincol - fromcol);
- Finsert_char (make_number (' '), column, Qt);
-
- last_known_column = mincol;
- last_known_column_point = PT;
- last_known_column_modified = MODIFF;
-
- XSETINT (column, mincol);
- return column;
-}
-
-
-DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation,
- 0, 0, 0,
- "Return the indentation of the current line.\n\
-This is the horizontal position of the character\n\
-following any initial whitespace.")
- ()
-{
- Lisp_Object val;
-
- XSETFASTINT (val, position_indentation (find_next_newline (PT, -1)));
- return val;
-}
-
-position_indentation (pos)
- register int pos;
-{
- register int column = 0;
- register int tab_width = XINT (current_buffer->tab_width);
- register unsigned char *p;
- register unsigned char *stop;
- unsigned char *start;
- int next_boundary = pos;
- int ceiling = pos;
-
- if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
-
- p = &FETCH_CHAR (pos);
- /* STOP records the value of P at which we will need
- to think about the gap, or about invisible text,
- or about the end of the buffer. */
- stop = p;
- /* START records the starting value of P. */
- start = p;
- while (1)
- {
- while (p == stop)
- {
- int stop_pos;
-
- /* If we have updated P, set POS to match.
- The first time we enter the loop, POS is already right. */
- if (p != start)
- pos = PTR_CHAR_POS (p);
- /* Consider the various reasons STOP might have been set here. */
- if (pos == ZV)
- return column;
- if (pos == next_boundary)
- pos = skip_invisible (pos, &next_boundary, ZV, Qnil);
- if (pos >= ceiling)
- ceiling = BUFFER_CEILING_OF (pos) + 1;
- /* Compute the next place we need to stop and think,
- and set STOP accordingly. */
- stop_pos = min (ceiling, next_boundary);
- /* The -1 and +1 arrange to point at the first byte of gap
- (if STOP_POS is the position of the gap)
- rather than at the data after the gap. */
-
- stop = &FETCH_CHAR (stop_pos - 1) + 1;
- p = &FETCH_CHAR (pos);
- }
- switch (*p++)
- {
- case ' ':
- column++;
- break;
- case '\t':
- column += tab_width - column % tab_width;
- break;
- default:
- return column;
- }
- }
-}
-
-/* Test whether the line beginning at POS is indented beyond COLUMN.
- Blank lines are treated as if they had the same indentation as the
- preceding line. */
-int
-indented_beyond_p (pos, column)
- int pos, column;
-{
- while (pos > BEGV && FETCH_CHAR (pos) == '\n')
- pos = find_next_newline_no_quit (pos - 1, -1);
- return (position_indentation (pos) >= column);
-}
-
-DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, "p",
- "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.\n\
-\n\
-The return value is the current column.")
- (column, force)
- Lisp_Object column, force;
-{
- register int pos;
- register int col = current_column ();
- register int goal;
- register int end;
- register int tab_width = XINT (current_buffer->tab_width);
- register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
- register struct Lisp_Char_Table *dp = buffer_display_table ();
-
- Lisp_Object val;
- int prev_col;
- int c;
-
- int next_boundary;
-
- if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
- CHECK_NATNUM (column, 0);
- goal = XINT (column);
-
- pos = PT;
- end = ZV;
- next_boundary = pos;
-
- /* If we're starting past the desired column,
- back up to beginning of line and scan from there. */
- if (col > goal)
- {
- end = pos;
- pos = find_next_newline (pos, -1);
- col = 0;
- }
-
- while (pos < end)
- {
- while (pos == next_boundary)
- {
- pos = skip_invisible (pos, &next_boundary, end, Qnil);
- if (pos >= end)
- goto endloop;
- }
-
- /* Test reaching the goal column. We do this after skipping
- invisible characters, so that we put point before the
- character on which the cursor will appear. */
- if (col >= goal)
- break;
-
- c = FETCH_CHAR (pos);
- if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
- {
- col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
- pos++;
- continue;
- }
- if (c == '\n')
- break;
- if (c == '\r' && EQ (current_buffer->selective_display, Qt))
- break;
- pos++;
- if (c == '\t')
- {
- prev_col = col;
- col += tab_width;
- col = col / tab_width * tab_width;
- }
- else if (ctl_arrow && (c < 040 || c == 0177))
- col += 2;
- else if (c < 040 || c >= 0177)
- col += 4;
- else
- col++;
- }
- endloop:
-
- SET_PT (pos);
-
- /* If a tab char made us overshoot, change it to spaces
- and scan through it again. */
- if (!NILP (force) && col > goal && c == '\t' && prev_col < goal)
- {
- int old_point;
-
- del_range (PT - 1, PT);
- Findent_to (make_number (goal), Qnil);
- old_point = PT;
- Findent_to (make_number (col), Qnil);
- SET_PT (old_point);
- /* Set the last_known... vars consistently. */
- col = goal;
- }
-
- /* If line ends prematurely, add space to the end. */
- if (col < goal && !NILP (force))
- Findent_to (make_number (col = goal), Qnil);
-
- last_known_column = col;
- last_known_column_point = PT;
- last_known_column_modified = MODIFF;
-
- XSETFASTINT (val, col);
- return val;
-}
-
-/* compute_motion: compute buffer posn given screen posn and vice versa */
-
-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. If we
- can't hit the requested column exactly (because of a tab or other
- multi-column character), overshoot.
-
- DID_MOTION is 1 if FROMHPOS has already accounted for overlay strings
- at FROM. This is the case if FROMVPOS and FROMVPOS came from an
- earlier call to compute_motion. The other common case is that FROMHPOS
- is zero and FROM is a position that "belongs" at column zero, but might
- be shifted by overlay strings; in this case DID_MOTION should be 0.
-
- 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 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. prevhpos is the column at
- which the character before bufpos started, and contin is non-zero
- if we reached the current line by continuing the previous.
-
- Note that FROMHPOS and TOHPOS should be expressed in real screen
- columns, taking HSCROLL and the truncation glyph at the left margin
- into account. That is, beginning-of-line moves you to the hpos
- -HSCROLL + (HSCROLL > 0).
-
- 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
- - (has_vertical_scroll_bars
- ? FRAME_SCROLL_BAR_COLS (XFRAME (window->frame))
- : (window_width + window_left != frame_width))
-
- where
- window_width is XFASTINT (w->width),
- window_left is XFASTINT (w->left),
- has_vertical_scroll_bars is
- FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (WINDOW_FRAME (window)))
- and frame_width = FRAME_WIDTH (XFRAME (window->frame))
-
- Or you can let window_internal_width do this all for you, and write:
- window_internal_width (w) - 1
-
- The `-1' accounts for the continuation-line backslashes; the rest
- accounts for window borders if the window is split horizontally, and
- the scroll bars if they are turned on. */
-
-struct position *
-compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, hscroll, tab_offset, win)
- int from, fromvpos, fromhpos, to, tovpos, tohpos;
- int did_motion;
- register int width;
- int hscroll, tab_offset;
- struct window *win;
-{
- 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 = !NILP (current_buffer->ctl_arrow);
- register struct Lisp_Char_Table *dp = window_display_table (win);
- int selective
- = (INTEGERP (current_buffer->selective_display)
- ? XINT (current_buffer->selective_display)
- : !NILP (current_buffer->selective_display) ? -1 : 0);
- int prev_vpos = vpos, prev_hpos = 0;
- int selective_rlen
- = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp))
- ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : 0);
- /* The next location where the `invisible' property changes, or an
- overlay starts or ends. */
- int next_boundary = from;
-
- /* For computing runs of characters with similar widths.
- Invariant: width_run_width is zero, or all the characters
- from width_run_start to width_run_end have a fixed width of
- width_run_width. */
- int width_run_start = from;
- int width_run_end = from;
- int width_run_width = 0;
- Lisp_Object *width_table;
- Lisp_Object buffer;
-
- /* The next buffer pos where we should consult the width run cache. */
- int next_width_run = from;
- Lisp_Object window;
-
- XSETBUFFER (buffer, current_buffer);
- XSETWINDOW (window, win);
-
- width_run_cache_on_off ();
- if (dp == buffer_display_table ())
- width_table = (VECTORP (current_buffer->width_table)
- ? XVECTOR (current_buffer->width_table)->contents
- : 0);
- else
- /* If the window has its own display table, we can't use the width
- run cache, because that's based on the buffer's display table. */
- width_table = 0;
-
- if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
-
- pos = from;
- while (1)
- {
- while (pos == next_boundary)
- {
- /* If the caller says that the screen position came from an earlier
- call to compute_motion, then we've already accounted for the
- overlay strings at point. This is only true the first time
- through, so clear the flag after testing it. */
- if (!did_motion)
- /* We need to skip past the overlay strings. Currently those
- strings must contain single-column printing characters;
- if we want to relax that restriction, something will have
- to be changed here. */
- hpos += overlay_strings (pos, win, (char **)0);
- did_motion = 0;
-
- if (pos >= to)
- break;
-
- /* Advance POS past invisible characters
- (but not necessarily all that there are here),
- and store in next_boundary the next position where
- we need to call skip_invisible. */
- pos = skip_invisible (pos, &next_boundary, to, window);
- }
-
- /* Handle right margin. */
- if (hpos >= width
- && (hpos > width
- || (pos < ZV && FETCH_CHAR (pos) != '\n')))
- {
- if (hscroll
- || (truncate_partial_width_windows
- && width + 1 < FRAME_WIDTH (XFRAME (WINDOW_FRAME (win))))
- || !NILP (current_buffer->truncate_lines))
- {
- /* Truncating: skip to newline. */
- pos = find_before_next_newline (pos, to, 1);
- hpos = width;
- /* If we just skipped next_boundary,
- loop around in the main while
- and handle it. */
- if (pos >= next_boundary)
- next_boundary = pos + 1;
- }
- else
- {
- /* Continuing. */
- vpos += hpos / width;
- tab_offset += hpos - hpos % width;
- hpos %= width;
- }
- }
-
- /* Stop if past the target buffer position or screen position. */
- if (pos >= to)
- break;
- if (vpos > tovpos || (vpos == tovpos && hpos >= tohpos))
- break;
-
- prev_vpos = vpos;
- prev_hpos = hpos;
-
- /* Consult the width run cache to see if we can avoid inspecting
- the text character-by-character. */
- if (current_buffer->width_run_cache && pos >= next_width_run)
- {
- int run_end;
- int common_width
- = region_cache_forward (current_buffer,
- current_buffer->width_run_cache,
- pos, &run_end);
-
- /* A width of zero means the character's width varies (like
- a tab), is meaningless (like a newline), or we just don't
- want to skip over it for some other reason. */
- if (common_width != 0)
- {
- int run_end_hpos;
-
- /* Don't go past the final buffer posn the user
- requested. */
- if (run_end > to)
- run_end = to;
-
- run_end_hpos = hpos + (run_end - pos) * common_width;
-
- /* Don't go past the final horizontal position the user
- requested. */
- if (vpos == tovpos && run_end_hpos > tohpos)
- {
- run_end = pos + (tohpos - hpos) / common_width;
- run_end_hpos = hpos + (run_end - pos) * common_width;
- }
-
- /* Don't go past the margin. */
- if (run_end_hpos >= width)
- {
- run_end = pos + (width - hpos) / common_width;
- run_end_hpos = hpos + (run_end - pos) * common_width;
- }
-
- hpos = run_end_hpos;
- if (run_end > pos)
- prev_hpos = hpos - common_width;
- pos = run_end;
- }
-
- next_width_run = run_end + 1;
- }
-
- /* We have to scan the text character-by-character. */
- else
- {
- c = FETCH_CHAR (pos);
- pos++;
-
- /* Perhaps add some info to the width_run_cache. */
- if (current_buffer->width_run_cache)
- {
- /* Is this character part of the current run? If so, extend
- the run. */
- if (pos - 1 == width_run_end
- && width_table[c] == width_run_width)
- width_run_end = pos;
-
- /* The previous run is over, since this is a character at a
- different position, or a different width. */
- else
- {
- /* Have we accumulated a run to put in the cache?
- (Currently, we only cache runs of width == 1). */
- if (width_run_start < width_run_end
- && width_run_width == 1)
- know_region_cache (current_buffer,
- current_buffer->width_run_cache,
- width_run_start, width_run_end);
-
- /* Start recording a new width run. */
- width_run_width = width_table[c];
- width_run_start = pos - 1;
- width_run_end = pos;
- }
- }
-
- if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
- hpos += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
- else if (c >= 040 && c < 0177)
- hpos++;
- else if (c == '\t')
- {
- int tem = (hpos + tab_offset + hscroll - (hscroll > 0)) % tab_width;
- if (tem < 0)
- tem += tab_width;
- hpos += tab_width - tem;
- }
- else if (c == '\n')
- {
- if (selective > 0 && indented_beyond_p (pos, selective))
- {
- /* Skip any number of invisible lines all at once */
- do
- pos = find_before_next_newline (pos, to, 1) + 1;
- while (pos < to
- && indented_beyond_p (pos, selective));
- /* Allow for the " ..." that is displayed for them. */
- if (selective_rlen)
- {
- hpos += selective_rlen;
- if (hpos >= width)
- hpos = width;
- }
- --pos;
- /* We have skipped the invis text, but not the
- newline after. */
- }
- else
- {
- /* A visible line. */
- vpos++;
- hpos = 0;
- hpos -= hscroll;
- /* Count the truncation glyph on column 0 */
- if (hscroll > 0)
- hpos++;
- 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.
- Stop *before* the real newline. */
- pos = find_before_next_newline (pos, to, 1);
- /* If we just skipped next_boundary,
- loop around in the main while
- and handle it. */
- if (pos > next_boundary)
- next_boundary = pos;
- /* Allow for the " ..." that is displayed for them. */
- if (selective_rlen)
- {
- hpos += selective_rlen;
- if (hpos >= width)
- hpos = width;
- }
- }
- else
- hpos += (ctl_arrow && c < 0200) ? 2 : 4;
- }
- }
-
- /* Remember any final width run in the cache. */
- if (current_buffer->width_run_cache
- && width_run_width == 1
- && width_run_start < width_run_end)
- know_region_cache (current_buffer, current_buffer->width_run_cache,
- width_run_start, width_run_end);
-
- val_compute_motion.bufpos = pos;
- val_compute_motion.hpos = hpos;
- val_compute_motion.vpos = vpos;
- val_compute_motion.prevhpos = prev_hpos;
- /* We alalways handle all of them here; none of them remain to do. */
- val_compute_motion.ovstring_chars_done = 0;
-
- /* Nonzero if have just continued a line */
- val_compute_motion.contin
- = (pos != from
- && (val_compute_motion.vpos != prev_vpos)
- && c != '\n');
-
- return &val_compute_motion;
-}
-
-#if 0 /* The doc string is too long for some compilers,
- but make-docfile can find it in this comment. */
-DEFUN ("compute-motion", Ffoo, Sfoo, 7, 7, 0,
- "Scan through the current buffer, calculating screen position.\n\
-Scan the current buffer forward from offset FROM,\n\
-assuming it is at position FROMPOS--a cons of the form (HPOS . VPOS)--\n\
-to position TO or position TOPOS--another cons of the form (HPOS . VPOS)--\n\
-and return the ending buffer position and screen location.\n\
-\n\
-There are three additional arguments:\n\
-\n\
-WIDTH is the number of columns available to display text;\n\
-this affects handling of continuation lines.\n\
-This is usually the value returned by `window-width', less one (to allow\n\
-for the continuation glyph).\n\
-\n\
-OFFSETS is either nil or a cons cell (HSCROLL . TAB-OFFSET).\n\
-HSCROLL is the number of columns not being displayed at the left\n\
-margin; this is usually taken from a window's hscroll member.\n\
-TAB-OFFSET is the number of columns of the first tab that aren't\n\
-being displayed, perhaps because the line was continued within it.\n\
-If OFFSETS is nil, HSCROLL and TAB-OFFSET are assumed to be zero.\n\
-\n\
-WINDOW is the window to operate on. It is used to choose the display table;\n\
-if it is showing the current buffer, it is used also for\n\
-deciding which overlay properties apply.\n\
-Note that `compute-motion' always operates on the current buffer.\n\
-\n\
-The value is a list of five elements:\n\
- (POS HPOS VPOS PREVHPOS CONTIN)\n\
-POS is the buffer position where the scan stopped.\n\
-VPOS is the vertical position where the scan stopped.\n\
-HPOS is the horizontal position where the scan stopped.\n\
-\n\
-PREVHPOS is the horizontal position one character back from POS.\n\
-CONTIN is t if a line was continued after (or within) the previous character.\n\
-\n\
-For example, to find the buffer position of column COL of line LINE\n\
-of a certain window, pass the window's starting location as FROM\n\
-and the window's upper-left coordinates as FROMPOS.\n\
-Pass the buffer's (point-max) as TO, to limit the scan to the end of the\n\
-visible section of the buffer, and pass LINE and COL as TOPOS.")
- (from, frompos, to, topos, width, offsets, window)
-#endif
-
-DEFUN ("compute-motion", Fcompute_motion, Scompute_motion, 7, 7, 0,
- 0)
- (from, frompos, to, topos, width, offsets, window)
- Lisp_Object from, frompos, to, topos;
- Lisp_Object width, offsets, window;
-{
- Lisp_Object bufpos, hpos, vpos, prevhpos, contin;
- struct position *pos;
- int hscroll, tab_offset;
-
- CHECK_NUMBER_COERCE_MARKER (from, 0);
- CHECK_CONS (frompos, 0);
- CHECK_NUMBER (XCONS (frompos)->car, 0);
- CHECK_NUMBER (XCONS (frompos)->cdr, 0);
- CHECK_NUMBER_COERCE_MARKER (to, 0);
- CHECK_CONS (topos, 0);
- CHECK_NUMBER (XCONS (topos)->car, 0);
- CHECK_NUMBER (XCONS (topos)->cdr, 0);
- CHECK_NUMBER (width, 0);
- if (!NILP (offsets))
- {
- CHECK_CONS (offsets, 0);
- CHECK_NUMBER (XCONS (offsets)->car, 0);
- CHECK_NUMBER (XCONS (offsets)->cdr, 0);
- hscroll = XINT (XCONS (offsets)->car);
- tab_offset = XINT (XCONS (offsets)->cdr);
- }
- else
- hscroll = tab_offset = 0;
-
- if (NILP (window))
- window = Fselected_window ();
- else
- CHECK_LIVE_WINDOW (window, 0);
-
- pos = compute_motion (XINT (from), XINT (XCONS (frompos)->cdr),
- XINT (XCONS (frompos)->car), 0,
- XINT (to), XINT (XCONS (topos)->cdr),
- XINT (XCONS (topos)->car),
- XINT (width), hscroll, tab_offset,
- XWINDOW (window));
-
- XSETFASTINT (bufpos, pos->bufpos);
- XSETINT (hpos, pos->hpos);
- XSETINT (vpos, pos->vpos);
- XSETINT (prevhpos, pos->prevhpos);
-
- return Fcons (bufpos,
- Fcons (hpos,
- Fcons (vpos,
- Fcons (prevhpos,
- Fcons (pos->contin ? Qt : Qnil, Qnil)))));
-
-}
-
-/* Return the column of position POS in window W's buffer.
- The result is 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 = PT;
- int col;
- int width = window_internal_width (w) - 1;
-
- if (pos == BEGV || FETCH_CHAR (pos - 1) == '\n')
- return 0;
- TEMP_SET_PT (pos);
- col = current_column ();
- TEMP_SET_PT (opoint);
- return col - (col % width);
-}
-
-
-/* Fvertical_motion and vmotion */
-struct position val_vmotion;
-
-struct position *
-vmotion (from, vtarget, w)
- register int from, vtarget;
- struct window *w;
-{
- int width = window_internal_width (w) - 1;
- int hscroll = XINT (w->hscroll);
- struct position pos;
- /* vpos is cumulative vertical position, changed as from is changed */
- register int vpos = 0;
- Lisp_Object prevline;
- register int first;
- int lmargin = hscroll > 0 ? 1 - hscroll : 0;
- int selective
- = (INTEGERP (current_buffer->selective_display)
- ? XINT (current_buffer->selective_display)
- : !NILP (current_buffer->selective_display) ? -1 : 0);
- Lisp_Object window;
- int start_hpos = 0;
- int did_motion;
-
- XSETWINDOW (window, w);
-
- /* The omission of the clause
- && marker_position (w->start) == BEG
- here is deliberate; I think we want to measure from the prompt
- position even if the minibuffer window has scrolled. */
- if (EQ (window, minibuf_window))
- {
- if (minibuf_prompt_width == 0 && STRINGP (minibuf_prompt))
- minibuf_prompt_width
- = string_display_width (minibuf_prompt, Qnil, Qnil);
-
- start_hpos = minibuf_prompt_width;
- }
-
- if (vpos >= vtarget)
- {
- /* To move upward, go a line at a time until
- we have gone at least far enough */
-
- first = 1;
-
- while ((vpos > vtarget || first) && from > BEGV)
- {
- Lisp_Object propval;
-
- XSETFASTINT (prevline, find_next_newline_no_quit (from - 1, -1));
- while (XFASTINT (prevline) > BEGV
- && ((selective > 0
- && indented_beyond_p (XFASTINT (prevline), selective))
-#ifdef USE_TEXT_PROPERTIES
- /* watch out for newlines with `invisible' property */
- || (propval = Fget_char_property (prevline,
- Qinvisible,
- window),
- TEXT_PROP_MEANS_INVISIBLE (propval))
-#endif
- ))
- XSETFASTINT (prevline,
- find_next_newline_no_quit (XFASTINT (prevline) - 1,
- -1));
- pos = *compute_motion (XFASTINT (prevline), 0,
- lmargin + (XFASTINT (prevline) == BEG
- ? start_hpos : 0),
- 0,
- from, 1 << (BITS_PER_INT - 2), 0,
- width, hscroll, 0, w);
- vpos -= pos.vpos;
- first = 0;
- from = XFASTINT (prevline);
- }
-
- /* If we made exactly the desired vertical distance,
- or if we hit beginning of buffer,
- return point found */
- if (vpos >= vtarget)
- {
- val_vmotion.bufpos = from;
- val_vmotion.vpos = vpos;
- val_vmotion.hpos = lmargin;
- val_vmotion.contin = 0;
- val_vmotion.prevhpos = 0;
- val_vmotion.ovstring_chars_done = 0;
- return &val_vmotion;
- }
-
- /* Otherwise find the correct spot by moving down */
- }
- /* Moving downward is simple, but must calculate from beg of line
- to determine hpos of starting point */
- if (from > BEGV && FETCH_CHAR (from - 1) != '\n')
- {
- Lisp_Object propval;
-
- XSETFASTINT (prevline, find_next_newline_no_quit (from, -1));
- while (XFASTINT (prevline) > BEGV
- && ((selective > 0
- && indented_beyond_p (XFASTINT (prevline), selective))
-#ifdef USE_TEXT_PROPERTIES
- /* watch out for newlines with `invisible' property */
- || (propval = Fget_char_property (prevline, Qinvisible,
- window),
- TEXT_PROP_MEANS_INVISIBLE (propval))
-#endif
- ))
- XSETFASTINT (prevline,
- find_next_newline_no_quit (XFASTINT (prevline) - 1,
- -1));
- pos = *compute_motion (XFASTINT (prevline), 0,
- lmargin + (XFASTINT (prevline) == BEG
- ? start_hpos : 0),
- 0,
- from, 1 << (BITS_PER_INT - 2), 0,
- width, hscroll, 0, w);
- did_motion = 1;
- }
- else
- {
- pos.hpos = lmargin + (from == BEG ? start_hpos : 0);
- pos.vpos = 0;
- did_motion = 0;
- }
- return compute_motion (from, vpos, pos.hpos, did_motion,
- ZV, vtarget, - (1 << (BITS_PER_INT - 2)),
- width, hscroll, pos.vpos * width, w);
-}
-
-DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0,
- "Move point to start of the screen line LINES lines down.\n\
-If LINES is negative, this means moving up.\n\
-\n\
-This function is an ordinary cursor motion function\n\
-which calculates the new position based on how text would be displayed.\n\
-The new position may be the start of a line,\n\
-or just the start of a continuation line.\n\
-The function returns number of screen lines moved over;\n\
-that usually equals LINES, but may be closer to zero\n\
-if beginning or end of buffer was reached.\n\
-\n\
-The optional second argument WINDOW specifies the window to use for\n\
-parameters such as width, horizontal scrolling, and so on.\n\
-The default is to use the selected window's parameters.\n\
-\n\
-`vertical-motion' always uses the current buffer,\n\
-regardless of which buffer is displayed in WINDOW.\n\
-This is consistent with other cursor motion functions\n\
-and makes it possible to use `vertical-motion' in any buffer,\n\
-whether or not it is currently displayed in some window.")
- (lines, window)
- Lisp_Object lines, window;
-{
- struct position pos;
-
- CHECK_NUMBER (lines, 0);
- if (! NILP (window))
- CHECK_WINDOW (window, 0);
- else
- window = selected_window;
-
- pos = *vmotion (PT, (int) XINT (lines), XWINDOW (window));
-
- SET_PT (pos.bufpos);
- return make_number (pos.vpos);
-}
-
-/* file's initialization. */
-
-syms_of_indent ()
-{
- DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode,
- "*Indentation can insert tabs if this is non-nil.\n\
-Setting this variable automatically makes it local to the current buffer.");
- indent_tabs_mode = 1;
-
- defsubr (&Scurrent_indentation);
- defsubr (&Sindent_to);
- defsubr (&Scurrent_column);
- defsubr (&Smove_to_column);
- defsubr (&Svertical_motion);
- defsubr (&Scompute_motion);
-}
diff --git a/src/indent.h b/src/indent.h
deleted file mode 100644
index 91d8f44c1ac..00000000000
--- a/src/indent.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Definitions for interface to indent.c
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-struct position
- {
- int bufpos;
- int hpos;
- int vpos;
- int prevhpos;
- int contin;
- /* Number of characters we have already handled
- from the before and after strings at this position. */
- int ovstring_chars_done;
- };
-
-struct position *compute_motion ();
-struct position *vmotion ();
-
-/* Value of point when current_column was called */
-extern int last_known_column_point;
-
-/* Functions for dealing with the column cache. */
-
-/* Return true iff the display table DISPTAB specifies the same widths
- for characters as WIDTHTAB. We use this to decide when to
- invalidate the buffer's column_cache. */
-extern int disptab_matches_widthtab ( /* struct Lisp_Vector *disptab,
- struct Lisp_Vector *widthtab */ );
-
-/* Recompute BUF's width table, using the display table DISPTAB. */
-extern void recompute_width_table ( /* struct buffer *buf,
- struct Lisp_Vector *disptab */ );
diff --git a/src/insdel.c b/src/insdel.c
deleted file mode 100644
index b3bc81467fd..00000000000
--- a/src/insdel.c
+++ /dev/null
@@ -1,1044 +0,0 @@
-/* Buffer insertion/deletion and gap motion for GNU Emacs.
- Copyright (C) 1985, 1986, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include "lisp.h"
-#include "intervals.h"
-#include "buffer.h"
-#include "window.h"
-#include "blockinput.h"
-
-#define min(x, y) ((x) < (y) ? (x) : (y))
-
-static void insert_from_string_1 ();
-static void insert_from_buffer_1 ();
-static void gap_left ();
-static void gap_right ();
-static void adjust_markers ();
-static void adjust_point ();
-
-Lisp_Object Fcombine_after_change_execute ();
-
-/* Non-nil means don't call the after-change-functions right away,
- just record an element in Vcombine_after_change_calls_list. */
-Lisp_Object Vcombine_after_change_calls;
-
-/* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
- describing changes which happened while combine_after_change_calls
- was nonzero. We use this to decide how to call them
- once the deferral ends.
-
- In each element.
- BEG-UNCHANGED is the number of chars before the changed range.
- END-UNCHANGED is the number of chars after the changed range,
- and CHANGE-AMOUNT is the number of characters inserted by the change
- (negative for a deletion). */
-Lisp_Object combine_after_change_list;
-
-/* Buffer which combine_after_change_list is about. */
-Lisp_Object combine_after_change_buffer;
-
-/* Move gap to position `pos'.
- Note that this can quit! */
-
-void
-move_gap (pos)
- int pos;
-{
- if (pos < GPT)
- gap_left (pos, 0);
- else if (pos > GPT)
- gap_right (pos);
-}
-
-/* Move the gap to POS, which is less than the current GPT.
- If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
-
-static void
-gap_left (pos, newgap)
- register int pos;
- int newgap;
-{
- register unsigned char *to, *from;
- register int i;
- int new_s1;
-
- pos--;
-
- if (!newgap)
- {
- if (unchanged_modified == MODIFF
- && overlay_unchanged_modified == OVERLAY_MODIFF)
- {
- beg_unchanged = pos;
- end_unchanged = Z - pos - 1;
- }
- else
- {
- if (Z - GPT < end_unchanged)
- end_unchanged = Z - GPT;
- if (pos < beg_unchanged)
- beg_unchanged = pos;
- }
- }
-
- i = GPT;
- to = GAP_END_ADDR;
- from = GPT_ADDR;
- new_s1 = GPT - BEG;
-
- /* Now copy the characters. To move the gap down,
- copy characters up. */
-
- while (1)
- {
- /* I gets number of characters left to copy. */
- i = new_s1 - pos;
- if (i == 0)
- break;
- /* If a quit is requested, stop copying now.
- Change POS to be where we have actually moved the gap to. */
- if (QUITP)
- {
- pos = new_s1;
- break;
- }
- /* 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;
- }
- }
-
- /* Adjust markers, and buffer data structure, to put the gap at POS.
- POS is where the loop above stopped, which may be what was specified
- or may be where a quit was detected. */
- adjust_markers (pos + 1, GPT, GAP_SIZE);
- GPT = pos + 1;
- QUIT;
-}
-
-static void
-gap_right (pos)
- register int pos;
-{
- register unsigned char *to, *from;
- register int i;
- int new_s1;
-
- pos--;
-
- if (unchanged_modified == MODIFF
- && overlay_unchanged_modified == OVERLAY_MODIFF)
-
- {
- beg_unchanged = pos;
- end_unchanged = Z - pos - 1;
- }
- else
- {
- if (Z - pos - 1 < end_unchanged)
- end_unchanged = Z - pos - 1;
- if (GPT - BEG < beg_unchanged)
- beg_unchanged = GPT - BEG;
- }
-
- i = GPT;
- from = GAP_END_ADDR;
- to = GPT_ADDR;
- new_s1 = GPT - 1;
-
- /* Now copy the characters. To move the gap up,
- copy characters down. */
-
- while (1)
- {
- /* I gets number of characters left to copy. */
- i = pos - new_s1;
- if (i == 0)
- break;
- /* If a quit is requested, stop copying now.
- Change POS to be where we have actually moved the gap to. */
- if (QUITP)
- {
- pos = new_s1;
- break;
- }
- /* 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++;
- }
- }
-
- adjust_markers (GPT + GAP_SIZE, pos + 1 + GAP_SIZE, - GAP_SIZE);
- GPT = pos + 1;
- QUIT;
-}
-
-/* Add AMOUNT to the position of every marker in the current buffer
- whose current position is between FROM (exclusive) and TO (inclusive).
-
- Also, any markers past the outside of that interval, in the direction
- of adjustment, are first moved back to the near end of the interval
- and then adjusted by AMOUNT.
-
- When the latter adjustment is done, if AMOUNT is negative,
- we record the adjustment for undo. (This case happens only for
- deletion.) */
-
-static void
-adjust_markers (from, to, amount)
- register int from, to, amount;
-{
- Lisp_Object marker;
- register struct Lisp_Marker *m;
- register int mpos;
-
- marker = BUF_MARKERS (current_buffer);
-
- while (!NILP (marker))
- {
- m = XMARKER (marker);
- mpos = m->bufpos;
- if (amount > 0)
- {
- if (mpos > to && mpos < to + amount)
- mpos = to + amount;
- }
- else
- {
- /* Here's the case where a marker is inside text being deleted.
- AMOUNT can be negative for gap motion, too,
- but then this range contains no markers. */
- if (mpos > from + amount && mpos <= from)
- {
- record_marker_adjustment (marker, from + amount - mpos);
- mpos = from + amount;
- }
- }
- if (mpos > from && mpos <= to)
- mpos += amount;
- m->bufpos = mpos;
- marker = m->chain;
- }
-}
-
-/* Adjust markers whose insertion-type is t
- for an insertion of AMOUNT characters at POS. */
-
-static void
-adjust_markers_for_insert (pos, amount)
- register int pos, amount;
-{
- Lisp_Object marker;
-
- marker = BUF_MARKERS (current_buffer);
-
- while (!NILP (marker))
- {
- register struct Lisp_Marker *m = XMARKER (marker);
- if (m->insertion_type && m->bufpos == pos)
- m->bufpos += amount;
- marker = m->chain;
- }
-}
-
-/* Add the specified amount to point. This is used only when the value
- of point changes due to an insert or delete; it does not represent
- a conceptual change in point as a marker. In particular, point is
- not crossing any interval boundaries, so there's no need to use the
- usual SET_PT macro. In fact it would be incorrect to do so, because
- either the old or the new value of point is out of sync with the
- current set of intervals. */
-static void
-adjust_point (amount)
- int amount;
-{
- BUF_PT (current_buffer) += amount;
-}
-
-/* Make the gap INCREMENT characters longer. */
-
-void
-make_gap (increment)
- int increment;
-{
- unsigned char *result;
- Lisp_Object tem;
- int real_gap_loc;
- int old_gap_size;
-
- /* If we have to get more space, get enough to last a while. */
- increment += 2000;
-
- /* Don't allow a buffer size that won't fit in an int
- even if it will fit in a Lisp integer.
- That won't work because so many places use `int'. */
-
- if (Z - BEG + GAP_SIZE + increment
- >= ((unsigned) 1 << (min (BITS_PER_INT, VALBITS) - 1)))
- error ("Buffer exceeds maximum size");
-
- BLOCK_INPUT;
- result = BUFFER_REALLOC (BEG_ADDR, (Z - BEG + GAP_SIZE + increment));
-
- if (result == 0)
- {
- UNBLOCK_INPUT;
- memory_full ();
- }
-
- /* We can't unblock until the new address is properly stored. */
- BEG_ADDR = result;
- UNBLOCK_INPUT;
-
- /* Prevent quitting in move_gap. */
- tem = Vinhibit_quit;
- Vinhibit_quit = Qt;
-
- 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;
-
- Vinhibit_quit = tem;
-}
-
-/* Insert a string of specified length before point.
- DO NOT use this for the contents of a Lisp string or a Lisp buffer!
- prepare_to_modify_buffer could relocate the text. */
-
-void
-insert (string, length)
- register unsigned char *string;
- register length;
-{
- if (length > 0)
- {
- insert_1 (string, length, 0, 1);
- signal_after_change (PT-length, 0, length);
- }
-}
-
-void
-insert_and_inherit (string, length)
- register unsigned char *string;
- register length;
-{
- if (length > 0)
- {
- insert_1 (string, length, 1, 1);
- signal_after_change (PT-length, 0, length);
- }
-}
-
-void
-insert_1 (string, length, inherit, prepare)
- register unsigned char *string;
- register int length;
- int inherit, prepare;
-{
- register Lisp_Object temp;
-
- if (prepare)
- prepare_to_modify_buffer (PT, PT);
-
- if (PT != GPT)
- move_gap (PT);
- if (GAP_SIZE < length)
- make_gap (length - GAP_SIZE);
-
- record_insert (PT, length);
- MODIFF++;
-
- bcopy (string, GPT_ADDR, length);
-
-#ifdef USE_TEXT_PROPERTIES
- if (BUF_INTERVALS (current_buffer) != 0)
- /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
- offset_intervals (current_buffer, PT, length);
-#endif
-
- GAP_SIZE -= length;
- GPT += length;
- ZV += length;
- Z += length;
- adjust_overlays_for_insert (PT, length);
- adjust_markers_for_insert (PT, length);
- adjust_point (length);
-
-#ifdef USE_TEXT_PROPERTIES
- if (!inherit && BUF_INTERVALS (current_buffer) != 0)
- Fset_text_properties (make_number (PT - length), make_number (PT),
- Qnil, Qnil);
-#endif
-}
-
-/* Insert the part of the text of STRING, a Lisp object assumed to be
- of type string, consisting of the LENGTH characters starting at
- position POS. If the text of STRING has properties, they are absorbed
- into the buffer.
-
- It does not work to use `insert' for this, because a GC could happen
- before we bcopy the stuff into the buffer, and relocate the string
- without insert noticing. */
-
-void
-insert_from_string (string, pos, length, inherit)
- Lisp_Object string;
- register int pos, length;
- int inherit;
-{
- if (length > 0)
- {
- insert_from_string_1 (string, pos, length, inherit);
- signal_after_change (PT-length, 0, length);
- }
-}
-
-static void
-insert_from_string_1 (string, pos, length, inherit)
- Lisp_Object string;
- register int pos, length;
- int inherit;
-{
- register Lisp_Object temp;
- struct gcpro gcpro1;
-
- /* Make sure point-max won't overflow after this insertion. */
- XSETINT (temp, length + Z);
- if (length + Z != XINT (temp))
- error ("maximum buffer size exceeded");
-
- GCPRO1 (string);
- prepare_to_modify_buffer (PT, PT);
-
- if (PT != GPT)
- move_gap (PT);
- if (GAP_SIZE < length)
- make_gap (length - GAP_SIZE);
-
- record_insert (PT, length);
- MODIFF++;
- UNGCPRO;
-
- bcopy (XSTRING (string)->data, GPT_ADDR, length);
-
- /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
- offset_intervals (current_buffer, PT, length);
-
- GAP_SIZE -= length;
- GPT += length;
- ZV += length;
- Z += length;
- adjust_overlays_for_insert (PT, length);
- adjust_markers_for_insert (PT, length);
-
- /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
- graft_intervals_into_buffer (XSTRING (string)->intervals, PT, length,
- current_buffer, inherit);
-
- adjust_point (length);
-}
-
-/* Insert text from BUF, starting at POS and having length LENGTH, into the
- current buffer. If the text in BUF has properties, they are absorbed
- into the current buffer.
-
- It does not work to use `insert' for this, because a malloc could happen
- and relocate BUF's text before the bcopy happens. */
-
-void
-insert_from_buffer (buf, pos, length, inherit)
- struct buffer *buf;
- int pos, length;
- int inherit;
-{
- if (length > 0)
- {
- insert_from_buffer_1 (buf, pos, length, inherit);
- signal_after_change (PT-length, 0, length);
- }
-}
-
-static void
-insert_from_buffer_1 (buf, pos, length, inherit)
- struct buffer *buf;
- int pos, length;
- int inherit;
-{
- register Lisp_Object temp;
- int chunk;
-
- /* Make sure point-max won't overflow after this insertion. */
- XSETINT (temp, length + Z);
- if (length + Z != XINT (temp))
- error ("maximum buffer size exceeded");
-
- prepare_to_modify_buffer (PT, PT);
-
- if (PT != GPT)
- move_gap (PT);
- if (GAP_SIZE < length)
- make_gap (length - GAP_SIZE);
-
- record_insert (PT, length);
- MODIFF++;
-
- if (pos < BUF_GPT (buf))
- {
- chunk = BUF_GPT (buf) - pos;
- if (chunk > length)
- chunk = length;
- bcopy (BUF_CHAR_ADDRESS (buf, pos), GPT_ADDR, chunk);
- }
- else
- chunk = 0;
- if (chunk < length)
- bcopy (BUF_CHAR_ADDRESS (buf, pos + chunk),
- GPT_ADDR + chunk, length - chunk);
-
-#ifdef USE_TEXT_PROPERTIES
- if (BUF_INTERVALS (current_buffer) != 0)
- offset_intervals (current_buffer, PT, length);
-#endif
-
- GAP_SIZE -= length;
- GPT += length;
- ZV += length;
- Z += length;
- adjust_overlays_for_insert (PT, length);
- adjust_markers_for_insert (PT, length);
- adjust_point (length);
-
- /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
- graft_intervals_into_buffer (copy_intervals (BUF_INTERVALS (buf),
- pos, length),
- PT - length, length, current_buffer, inherit);
-}
-
-/* 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
- the insertion happens are adjusted to point after it.
- Don't use this function to insert part of a Lisp string,
- since gc could happen and relocate it. */
-
-void
-insert_before_markers (string, length)
- unsigned char *string;
- register int length;
-{
- if (length > 0)
- {
- register int opoint = PT;
- insert_1 (string, length, 0, 1);
- adjust_markers (opoint - 1, opoint, length);
- signal_after_change (PT-length, 0, length);
- }
-}
-
-void
-insert_before_markers_and_inherit (string, length)
- unsigned char *string;
- register int length;
-{
- if (length > 0)
- {
- register int opoint = PT;
- insert_1 (string, length, 1, 1);
- adjust_markers (opoint - 1, opoint, length);
- signal_after_change (PT-length, 0, length);
- }
-}
-
-/* Insert part of a Lisp string, relocating markers after. */
-
-void
-insert_from_string_before_markers (string, pos, length, inherit)
- Lisp_Object string;
- register int pos, length;
- int inherit;
-{
- if (length > 0)
- {
- register int opoint = PT;
- insert_from_string_1 (string, pos, length, inherit);
- adjust_markers (opoint - 1, opoint, length);
- signal_after_change (PT-length, 0, length);
- }
-}
-
-/* Delete characters in current buffer
- from FROM up to (but not including) TO. */
-
-void
-del_range (from, to)
- register int from, to;
-{
- del_range_1 (from, to, 1);
-}
-
-/* Like del_range; PREPARE says whether to call prepare_to_modify_buffer. */
-
-void
-del_range_1 (from, to, prepare)
- register int from, to, prepare;
-{
- register int numdel;
-
- /* Make args be valid */
- if (from < BEGV)
- from = BEGV;
- if (to > ZV)
- to = ZV;
-
- if ((numdel = to - from) <= 0)
- return;
-
- /* 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);
-
- if (prepare)
- prepare_to_modify_buffer (from, to);
-
- /* Relocate all markers pointing into the new, larger gap
- to point at the end of the text before the gap.
- This has to be done before recording the deletion,
- so undo handles this after reinserting the text. */
- adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE);
-
- record_delete (from, numdel);
- MODIFF++;
-
- /* Relocate point as if it were a marker. */
- if (from < PT)
- adjust_point (from - (PT < to ? PT : to));
-
- /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
- offset_intervals (current_buffer, from, - numdel);
-
- /* Adjust the overlay center as needed. This must be done after
- adjusting the markers that bound the overlays. */
- adjust_overlays_for_delete (from, numdel);
-
- GAP_SIZE += numdel;
- ZV -= numdel;
- Z -= numdel;
- GPT = from;
-
- if (GPT - BEG < beg_unchanged)
- beg_unchanged = GPT - BEG;
- if (Z - GPT < end_unchanged)
- end_unchanged = Z - GPT;
-
- evaporate_overlays (from);
- signal_after_change (from, numdel, 0);
-}
-
-/* Call this if you're about to change the region of BUFFER from START
- to END. This checks the read-only properties of the region, calls
- the necessary modification hooks, and warns the next redisplay that
- it should pay attention to that area. */
-void
-modify_region (buffer, start, end)
- struct buffer *buffer;
- int start, end;
-{
- struct buffer *old_buffer = current_buffer;
-
- if (buffer != old_buffer)
- set_buffer_internal (buffer);
-
- prepare_to_modify_buffer (start, end);
-
- if (start - 1 < beg_unchanged
- || (unchanged_modified == MODIFF
- && overlay_unchanged_modified == OVERLAY_MODIFF))
- beg_unchanged = start - 1;
- if (Z - end < end_unchanged
- || (unchanged_modified == MODIFF
- && overlay_unchanged_modified == OVERLAY_MODIFF))
- end_unchanged = Z - end;
-
- if (MODIFF <= SAVE_MODIFF)
- record_first_change ();
- MODIFF++;
-
- buffer->point_before_scroll = Qnil;
-
- if (buffer != old_buffer)
- set_buffer_internal (old_buffer);
-}
-
-/* Check that it is okay to modify the buffer between START and END.
- Run the before-change-function, if any. If intervals are in use,
- verify that the text to be modified is not read-only, and call
- any modification properties the text may have. */
-
-void
-prepare_to_modify_buffer (start, end)
- int start, end;
-{
- if (!NILP (current_buffer->read_only))
- Fbarf_if_buffer_read_only ();
-
- /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
- if (BUF_INTERVALS (current_buffer) != 0)
- verify_interval_modification (current_buffer, start, end);
-
-#ifdef CLASH_DETECTION
- if (!NILP (current_buffer->file_truename)
- /* Make binding buffer-file-name to nil effective. */
- && !NILP (current_buffer->filename)
- && SAVE_MODIFF >= MODIFF)
- lock_file (current_buffer->file_truename);
-#else
- /* At least warn if this file has changed on disk since it was visited. */
- if (!NILP (current_buffer->filename)
- && SAVE_MODIFF >= MODIFF
- && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
- && !NILP (Ffile_exists_p (current_buffer->filename)))
- call1 (intern ("ask-user-about-supersession-threat"),
- current_buffer->filename);
-#endif /* not CLASH_DETECTION */
-
- signal_before_change (start, end);
-
- if (current_buffer->newline_cache)
- invalidate_region_cache (current_buffer,
- current_buffer->newline_cache,
- start - BEG, Z - end);
- if (current_buffer->width_run_cache)
- invalidate_region_cache (current_buffer,
- current_buffer->width_run_cache,
- start - BEG, Z - end);
-
- Vdeactivate_mark = Qt;
-}
-
-/* Signal a change to the buffer immediately before it happens.
- START_INT and END_INT are the bounds of the text to be changed. */
-
-void
-signal_before_change (start_int, end_int)
- int start_int, end_int;
-{
- Lisp_Object start, end;
-
- start = make_number (start_int);
- end = make_number (end_int);
-
- /* If buffer is unmodified, run a special hook for that case. */
- if (SAVE_MODIFF >= MODIFF
- && !NILP (Vfirst_change_hook)
- && !NILP (Vrun_hooks))
- call1 (Vrun_hooks, Qfirst_change_hook);
-
- /* Run the before-change-function if any.
- We don't bother "binding" this variable to nil
- because it is obsolete anyway and new code should not use it. */
- if (!NILP (Vbefore_change_function))
- call2 (Vbefore_change_function, start, end);
-
- /* Now run the before-change-functions if any. */
- if (!NILP (Vbefore_change_functions))
- {
- Lisp_Object args[3];
- Lisp_Object before_change_functions;
- Lisp_Object after_change_functions;
- struct gcpro gcpro1, gcpro2;
-
- /* "Bind" before-change-functions and after-change-functions
- to nil--but in a way that errors don't know about.
- That way, if there's an error in them, they will stay nil. */
- before_change_functions = Vbefore_change_functions;
- after_change_functions = Vafter_change_functions;
- Vbefore_change_functions = Qnil;
- Vafter_change_functions = Qnil;
- GCPRO2 (before_change_functions, after_change_functions);
-
- /* Actually run the hook functions. */
- args[0] = Qbefore_change_functions;
- args[1] = start;
- args[2] = end;
- run_hook_list_with_args (before_change_functions, 3, args);
-
- /* "Unbind" the variables we "bound" to nil. */
- Vbefore_change_functions = before_change_functions;
- Vafter_change_functions = after_change_functions;
- UNGCPRO;
- }
-
- if (!NILP (current_buffer->overlays_before)
- || !NILP (current_buffer->overlays_after))
- report_overlay_modification (start, end, 0, start, end, Qnil);
-}
-
-/* Signal a change immediately 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 that part of the text
- after the change. */
-
-void
-signal_after_change (pos, lendel, lenins)
- int pos, lendel, lenins;
-{
- /* If we are deferring calls to the after-change functions
- and there are no before-change functions,
- just record the args that we were going to use. */
- if (! NILP (Vcombine_after_change_calls)
- && NILP (Vbefore_change_function) && NILP (Vbefore_change_functions)
- && NILP (current_buffer->overlays_before)
- && NILP (current_buffer->overlays_after))
- {
- Lisp_Object elt;
-
- if (!NILP (combine_after_change_list)
- && current_buffer != XBUFFER (combine_after_change_buffer))
- Fcombine_after_change_execute ();
-
- elt = Fcons (make_number (pos - BEG),
- Fcons (make_number (Z - (pos - lendel + lenins)),
- Fcons (make_number (lenins - lendel), Qnil)));
- combine_after_change_list
- = Fcons (elt, combine_after_change_list);
- combine_after_change_buffer = Fcurrent_buffer ();
-
- return;
- }
-
- if (!NILP (combine_after_change_list))
- Fcombine_after_change_execute ();
-
- /* Run the after-change-function if any.
- We don't bother "binding" this variable to nil
- because it is obsolete anyway and new code should not use it. */
- if (!NILP (Vafter_change_function))
- call3 (Vafter_change_function,
- make_number (pos), make_number (pos + lenins),
- make_number (lendel));
-
- if (!NILP (Vafter_change_functions))
- {
- Lisp_Object args[4];
- Lisp_Object before_change_functions;
- Lisp_Object after_change_functions;
- struct gcpro gcpro1, gcpro2;
-
- /* "Bind" before-change-functions and after-change-functions
- to nil--but in a way that errors don't know about.
- That way, if there's an error in them, they will stay nil. */
- before_change_functions = Vbefore_change_functions;
- after_change_functions = Vafter_change_functions;
- Vbefore_change_functions = Qnil;
- Vafter_change_functions = Qnil;
- GCPRO2 (before_change_functions, after_change_functions);
-
- /* Actually run the hook functions. */
- args[0] = Qafter_change_functions;
- XSETFASTINT (args[1], pos);
- XSETFASTINT (args[2], pos + lenins);
- XSETFASTINT (args[3], lendel);
- run_hook_list_with_args (after_change_functions,
- 4, args);
-
- /* "Unbind" the variables we "bound" to nil. */
- Vbefore_change_functions = before_change_functions;
- Vafter_change_functions = after_change_functions;
- UNGCPRO;
- }
-
- if (!NILP (current_buffer->overlays_before)
- || !NILP (current_buffer->overlays_after))
- report_overlay_modification (make_number (pos),
- make_number (pos + lenins),
- 1,
- make_number (pos), make_number (pos + lenins),
- make_number (lendel));
-
- /* After an insertion, call the text properties
- insert-behind-hooks or insert-in-front-hooks. */
- if (lendel == 0)
- report_interval_modification (pos, pos + lenins);
-}
-
-Lisp_Object
-Fcombine_after_change_execute_1 (val)
- Lisp_Object val;
-{
- Vcombine_after_change_calls = val;
- return val;
-}
-
-DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
- Scombine_after_change_execute, 0, 0, 0,
- "This function is for use internally in `combine-after-change-calls'.")
- ()
-{
- register Lisp_Object val;
- int count = specpdl_ptr - specpdl;
- int beg, end, change;
- int begpos, endpos;
- Lisp_Object tail;
-
- record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
-
- Fset_buffer (combine_after_change_buffer);
-
- /* # chars unchanged at beginning of buffer. */
- beg = Z - BEG;
- /* # chars unchanged at end of buffer. */
- end = beg;
- /* Total amount of insertion (negative for deletion). */
- change = 0;
-
- /* Scan the various individual changes,
- accumulating the range info in BEG, END and CHANGE. */
- for (tail = combine_after_change_list; CONSP (tail);
- tail = XCONS (tail)->cdr)
- {
- Lisp_Object elt, thisbeg, thisend, thischange;
-
- /* Extract the info from the next element. */
- elt = XCONS (tail)->car;
- if (! CONSP (elt))
- continue;
- thisbeg = XINT (XCONS (elt)->car);
-
- elt = XCONS (elt)->cdr;
- if (! CONSP (elt))
- continue;
- thisend = XINT (XCONS (elt)->car);
-
- elt = XCONS (elt)->cdr;
- if (! CONSP (elt))
- continue;
- thischange = XINT (XCONS (elt)->car);
-
- /* Merge this range into the accumulated range. */
- change += thischange;
- if (thisbeg < beg)
- beg = thisbeg;
- if (thisend < end)
- end = thisend;
- }
-
- /* Get the current start and end positions of the range
- that was changed. */
- begpos = BEG + beg;
- endpos = Z - end;
-
- /* We are about to handle these, so discard them. */
- combine_after_change_list = Qnil;
-
- /* Now run the after-change functions for real.
- Turn off the flag that defers them. */
- record_unwind_protect (Fcombine_after_change_execute_1,
- Vcombine_after_change_calls);
- signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
-
- return unbind_to (count, val);
-}
-
-syms_of_insdel ()
-{
- staticpro (&combine_after_change_list);
- combine_after_change_list = Qnil;
-
- DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls,
- "Used internally by the `combine-after-change-calls' macro.");
- Vcombine_after_change_calls = Qnil;
-
- defsubr (&Scombine_after_change_execute);
-}
diff --git a/src/intervals.c b/src/intervals.c
deleted file mode 100644
index cff718d1f8e..00000000000
--- a/src/intervals.c
+++ /dev/null
@@ -1,1961 +0,0 @@
-/* Code for doing intervals.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* NOTES:
-
- Have to ensure that we can't put symbol nil on a plist, or some
- functions may work incorrectly.
-
- An idea: Have the owner of the tree keep count of splits and/or
- insertion lengths (in intervals), and balance after every N.
-
- Need to call *_left_hook when buffer is killed.
-
- Scan for zero-length, or 0-length to see notes about handling
- zero length interval-markers.
-
- There are comments around about freeing intervals. It might be
- faster to explicitly free them (put them on the free list) than
- to GC them.
-
-*/
-
-
-#include <config.h>
-#include "lisp.h"
-#include "intervals.h"
-#include "buffer.h"
-#include "puresize.h"
-#include "keyboard.h"
-
-/* The rest of the file is within this conditional. */
-#ifdef USE_TEXT_PROPERTIES
-
-/* Test for membership, allowing for t (actually any non-cons) to mean the
- universal set. */
-
-#define TMEM(sym, set) (CONSP (set) ? ! NILP (Fmemq (sym, set)) : ! NILP (set))
-
-#define min(x, y) ((x) < (y) ? (x) : (y))
-
-Lisp_Object merge_properties_sticky ();
-
-/* Utility functions for intervals. */
-
-
-/* Create the root interval of some object, a buffer or string. */
-
-INTERVAL
-create_root_interval (parent)
- Lisp_Object parent;
-{
- INTERVAL new;
-
- CHECK_IMPURE (parent);
-
- new = make_interval ();
-
- if (BUFFERP (parent))
- {
- new->total_length = (BUF_Z (XBUFFER (parent))
- - BUF_BEG (XBUFFER (parent)));
- BUF_INTERVALS (XBUFFER (parent)) = new;
- }
- else if (STRINGP (parent))
- {
- new->total_length = XSTRING (parent)->size;
- XSTRING (parent)->intervals = new;
- }
-
- new->parent = (INTERVAL) parent;
- new->position = 1;
-
- return new;
-}
-
-/* Make the interval TARGET have exactly the properties of SOURCE */
-
-void
-copy_properties (source, target)
- register INTERVAL source, target;
-{
- if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target))
- return;
-
- COPY_INTERVAL_CACHE (source, target);
- target->plist = Fcopy_sequence (source->plist);
-}
-
-/* Merge the properties of interval SOURCE into the properties
- of interval TARGET. That is to say, each property in SOURCE
- is added to TARGET if TARGET has no such property as yet. */
-
-static void
-merge_properties (source, target)
- register INTERVAL source, target;
-{
- register Lisp_Object o, sym, val;
-
- if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target))
- return;
-
- MERGE_INTERVAL_CACHE (source, target);
-
- o = source->plist;
- while (! EQ (o, Qnil))
- {
- sym = Fcar (o);
- val = Fmemq (sym, target->plist);
-
- if (NILP (val))
- {
- o = Fcdr (o);
- val = Fcar (o);
- target->plist = Fcons (sym, Fcons (val, target->plist));
- o = Fcdr (o);
- }
- else
- o = Fcdr (Fcdr (o));
- }
-}
-
-/* Return 1 if the two intervals have the same properties,
- 0 otherwise. */
-
-int
-intervals_equal (i0, i1)
- INTERVAL i0, i1;
-{
- register Lisp_Object i0_cdr, i0_sym, i1_val;
- register i1_len;
-
- if (DEFAULT_INTERVAL_P (i0) && DEFAULT_INTERVAL_P (i1))
- return 1;
-
- if (DEFAULT_INTERVAL_P (i0) || DEFAULT_INTERVAL_P (i1))
- return 0;
-
- i1_len = XFASTINT (Flength (i1->plist));
- if (i1_len & 0x1) /* Paranoia -- plists are always even */
- abort ();
- i1_len /= 2;
- i0_cdr = i0->plist;
- while (!NILP (i0_cdr))
- {
- /* Lengths of the two plists were unequal. */
- if (i1_len == 0)
- return 0;
-
- i0_sym = Fcar (i0_cdr);
- i1_val = Fmemq (i0_sym, i1->plist);
-
- /* i0 has something i1 doesn't. */
- if (EQ (i1_val, Qnil))
- return 0;
-
- /* i0 and i1 both have sym, but it has different values in each. */
- i0_cdr = Fcdr (i0_cdr);
- if (! EQ (Fcar (Fcdr (i1_val)), Fcar (i0_cdr)))
- return 0;
-
- i0_cdr = Fcdr (i0_cdr);
- i1_len--;
- }
-
- /* Lengths of the two plists were unequal. */
- if (i1_len > 0)
- return 0;
-
- return 1;
-}
-
-static int icount;
-static int idepth;
-static int zero_length;
-
-/* Traverse an interval tree TREE, performing FUNCTION on each node.
- Pass FUNCTION two args: an interval, and ARG. */
-
-void
-traverse_intervals (tree, position, depth, function, arg)
- INTERVAL tree;
- int position, depth;
- void (* function) ();
- Lisp_Object arg;
-{
- if (NULL_INTERVAL_P (tree))
- return;
-
- traverse_intervals (tree->left, position, depth + 1, function, arg);
- position += LEFT_TOTAL_LENGTH (tree);
- tree->position = position;
- (*function) (tree, arg);
- position += LENGTH (tree);
- traverse_intervals (tree->right, position, depth + 1, function, arg);
-}
-
-#if 0
-/* These functions are temporary, for debugging purposes only. */
-
-INTERVAL search_interval, found_interval;
-
-void
-check_for_interval (i)
- register INTERVAL i;
-{
- if (i == search_interval)
- {
- found_interval = i;
- icount++;
- }
-}
-
-INTERVAL
-search_for_interval (i, tree)
- register INTERVAL i, tree;
-{
- icount = 0;
- search_interval = i;
- found_interval = NULL_INTERVAL;
- traverse_intervals (tree, 1, 0, &check_for_interval, Qnil);
- return found_interval;
-}
-
-static void
-inc_interval_count (i)
- INTERVAL i;
-{
- icount++;
- if (LENGTH (i) == 0)
- zero_length++;
- if (depth > idepth)
- idepth = depth;
-}
-
-int
-count_intervals (i)
- register INTERVAL i;
-{
- icount = 0;
- idepth = 0;
- zero_length = 0;
- traverse_intervals (i, 1, 0, &inc_interval_count, Qnil);
-
- return icount;
-}
-
-static INTERVAL
-root_interval (interval)
- INTERVAL interval;
-{
- register INTERVAL i = interval;
-
- while (! ROOT_INTERVAL_P (i))
- i = i->parent;
-
- return i;
-}
-#endif
-
-/* Assuming that a left child exists, perform the following operation:
-
- A B
- / \ / \
- B => A
- / \ / \
- c c
-*/
-
-static INTERVAL
-rotate_right (interval)
- INTERVAL interval;
-{
- INTERVAL i;
- INTERVAL B = interval->left;
- int old_total = interval->total_length;
-
- /* Deal with any Parent of A; make it point to B. */
- if (! ROOT_INTERVAL_P (interval))
- if (AM_LEFT_CHILD (interval))
- interval->parent->left = B;
- else
- interval->parent->right = B;
- B->parent = interval->parent;
-
- /* Make B the parent of A */
- i = B->right;
- B->right = interval;
- interval->parent = B;
-
- /* Make A point to c */
- interval->left = i;
- if (! NULL_INTERVAL_P (i))
- i->parent = interval;
-
- /* A's total length is decreased by the length of B and its left child. */
- interval->total_length -= B->total_length - LEFT_TOTAL_LENGTH (interval);
-
- /* B must have the same total length of A. */
- B->total_length = old_total;
-
- return B;
-}
-
-/* Assuming that a right child exists, perform the following operation:
-
- A B
- / \ / \
- B => A
- / \ / \
- c c
-*/
-
-static INTERVAL
-rotate_left (interval)
- INTERVAL interval;
-{
- INTERVAL i;
- INTERVAL B = interval->right;
- int old_total = interval->total_length;
-
- /* Deal with any parent of A; make it point to B. */
- if (! ROOT_INTERVAL_P (interval))
- if (AM_LEFT_CHILD (interval))
- interval->parent->left = B;
- else
- interval->parent->right = B;
- B->parent = interval->parent;
-
- /* Make B the parent of A */
- i = B->left;
- B->left = interval;
- interval->parent = B;
-
- /* Make A point to c */
- interval->right = i;
- if (! NULL_INTERVAL_P (i))
- i->parent = interval;
-
- /* A's total length is decreased by the length of B and its right child. */
- interval->total_length -= B->total_length - RIGHT_TOTAL_LENGTH (interval);
-
- /* B must have the same total length of A. */
- B->total_length = old_total;
-
- return B;
-}
-
-/* Balance an interval tree with the assumption that the subtrees
- themselves are already balanced. */
-
-static INTERVAL
-balance_an_interval (i)
- INTERVAL i;
-{
- register int old_diff, new_diff;
-
- while (1)
- {
- old_diff = LEFT_TOTAL_LENGTH (i) - RIGHT_TOTAL_LENGTH (i);
- if (old_diff > 0)
- {
- new_diff = i->total_length - i->left->total_length
- + RIGHT_TOTAL_LENGTH (i->left) - LEFT_TOTAL_LENGTH (i->left);
- if (abs (new_diff) >= old_diff)
- break;
- i = rotate_right (i);
- balance_an_interval (i->right);
- }
- else if (old_diff < 0)
- {
- new_diff = i->total_length - i->right->total_length
- + LEFT_TOTAL_LENGTH (i->right) - RIGHT_TOTAL_LENGTH (i->right);
- if (abs (new_diff) >= -old_diff)
- break;
- i = rotate_left (i);
- balance_an_interval (i->left);
- }
- else
- break;
- }
- return i;
-}
-
-/* Balance INTERVAL, potentially stuffing it back into its parent
- Lisp Object. */
-
-static INLINE INTERVAL
-balance_possible_root_interval (interval)
- register INTERVAL interval;
-{
- Lisp_Object parent;
-
- if (interval->parent == NULL_INTERVAL)
- return interval;
-
- parent = (Lisp_Object) (interval->parent);
- interval = balance_an_interval (interval);
-
- if (BUFFERP (parent))
- BUF_INTERVALS (XBUFFER (parent)) = interval;
- else if (STRINGP (parent))
- XSTRING (parent)->intervals = interval;
-
- return interval;
-}
-
-/* Balance the interval tree TREE. Balancing is by weight
- (the amount of text). */
-
-static INTERVAL
-balance_intervals_internal (tree)
- register INTERVAL tree;
-{
- /* Balance within each side. */
- if (tree->left)
- balance_intervals_internal (tree->left);
- if (tree->right)
- balance_intervals_internal (tree->right);
- return balance_an_interval (tree);
-}
-
-/* Advertised interface to balance intervals. */
-
-INTERVAL
-balance_intervals (tree)
- INTERVAL tree;
-{
- if (tree == NULL_INTERVAL)
- return NULL_INTERVAL;
-
- return balance_intervals_internal (tree);
-}
-
-/* Split INTERVAL into two pieces, starting the second piece at
- character position OFFSET (counting from 0), relative to INTERVAL.
- INTERVAL becomes the left-hand piece, and the right-hand piece
- (second, lexicographically) is returned.
-
- The size and position fields of the two intervals are set based upon
- those of the original interval. The property list of the new interval
- is reset, thus it is up to the caller to do the right thing with the
- result.
-
- Note that this does not change the position of INTERVAL; if it is a root,
- it is still a root after this operation. */
-
-INTERVAL
-split_interval_right (interval, offset)
- INTERVAL interval;
- int offset;
-{
- INTERVAL new = make_interval ();
- int position = interval->position;
- int new_length = LENGTH (interval) - offset;
-
- new->position = position + offset;
- new->parent = interval;
-
- if (NULL_RIGHT_CHILD (interval))
- {
- interval->right = new;
- new->total_length = new_length;
-
- return new;
- }
-
- /* Insert the new node between INTERVAL and its right child. */
- new->right = interval->right;
- interval->right->parent = new;
- interval->right = new;
- new->total_length = new_length + new->right->total_length;
-
- balance_an_interval (new);
- balance_possible_root_interval (interval);
-
- return new;
-}
-
-/* Split INTERVAL into two pieces, starting the second piece at
- character position OFFSET (counting from 0), relative to INTERVAL.
- INTERVAL becomes the right-hand piece, and the left-hand piece
- (first, lexicographically) is returned.
-
- The size and position fields of the two intervals are set based upon
- those of the original interval. The property list of the new interval
- is reset, thus it is up to the caller to do the right thing with the
- result.
-
- Note that this does not change the position of INTERVAL; if it is a root,
- it is still a root after this operation. */
-
-INTERVAL
-split_interval_left (interval, offset)
- INTERVAL interval;
- int offset;
-{
- INTERVAL new = make_interval ();
- int position = interval->position;
- int new_length = offset;
-
- new->position = interval->position;
- interval->position = interval->position + offset;
- new->parent = interval;
-
- if (NULL_LEFT_CHILD (interval))
- {
- interval->left = new;
- new->total_length = new_length;
-
- return new;
- }
-
- /* Insert the new node between INTERVAL and its left child. */
- new->left = interval->left;
- new->left->parent = new;
- interval->left = new;
- new->total_length = new_length + new->left->total_length;
-
- balance_an_interval (new);
- balance_possible_root_interval (interval);
-
- return new;
-}
-
-/* Find the interval containing text position POSITION in the text
- represented by the interval tree TREE. POSITION is a buffer
- position; the earliest position is 1. If POSITION is at the end of
- the buffer, return the interval containing the last character.
-
- The `position' field, which is a cache of an interval's position,
- is updated in the interval found. Other functions (e.g., next_interval)
- will update this cache based on the result of find_interval. */
-
-INLINE INTERVAL
-find_interval (tree, position)
- register INTERVAL tree;
- register int position;
-{
- /* The distance from the left edge of the subtree at TREE
- to POSITION. */
- register int relative_position = position - BEG;
-
- if (NULL_INTERVAL_P (tree))
- return NULL_INTERVAL;
-
- if (relative_position > TOTAL_LENGTH (tree))
- abort (); /* Paranoia */
-
- tree = balance_possible_root_interval (tree);
-
- while (1)
- {
- if (relative_position < LEFT_TOTAL_LENGTH (tree))
- {
- tree = tree->left;
- }
- else if (! NULL_RIGHT_CHILD (tree)
- && relative_position >= (TOTAL_LENGTH (tree)
- - RIGHT_TOTAL_LENGTH (tree)))
- {
- relative_position -= (TOTAL_LENGTH (tree)
- - RIGHT_TOTAL_LENGTH (tree));
- tree = tree->right;
- }
- else
- {
- tree->position =
- (position - relative_position /* the left edge of *tree */
- + LEFT_TOTAL_LENGTH (tree)); /* the left edge of this interval */
-
- return tree;
- }
- }
-}
-
-/* Find the succeeding interval (lexicographically) to INTERVAL.
- Sets the `position' field based on that of INTERVAL (see
- find_interval). */
-
-INTERVAL
-next_interval (interval)
- register INTERVAL interval;
-{
- register INTERVAL i = interval;
- register int next_position;
-
- if (NULL_INTERVAL_P (i))
- return NULL_INTERVAL;
- next_position = interval->position + LENGTH (interval);
-
- if (! NULL_RIGHT_CHILD (i))
- {
- i = i->right;
- while (! NULL_LEFT_CHILD (i))
- i = i->left;
-
- i->position = next_position;
- return i;
- }
-
- while (! NULL_PARENT (i))
- {
- if (AM_LEFT_CHILD (i))
- {
- i = i->parent;
- i->position = next_position;
- return i;
- }
-
- i = i->parent;
- }
-
- return NULL_INTERVAL;
-}
-
-/* Find the preceding interval (lexicographically) to INTERVAL.
- Sets the `position' field based on that of INTERVAL (see
- find_interval). */
-
-INTERVAL
-previous_interval (interval)
- register INTERVAL interval;
-{
- register INTERVAL i;
- register position_of_previous;
-
- if (NULL_INTERVAL_P (interval))
- return NULL_INTERVAL;
-
- if (! NULL_LEFT_CHILD (interval))
- {
- i = interval->left;
- while (! NULL_RIGHT_CHILD (i))
- i = i->right;
-
- i->position = interval->position - LENGTH (i);
- return i;
- }
-
- i = interval;
- while (! NULL_PARENT (i))
- {
- if (AM_RIGHT_CHILD (i))
- {
- i = i->parent;
-
- i->position = interval->position - LENGTH (i);
- return i;
- }
- i = i->parent;
- }
-
- return NULL_INTERVAL;
-}
-
-#if 0
-/* Traverse a path down the interval tree TREE to the interval
- containing POSITION, adjusting all nodes on the path for
- an addition of LENGTH characters. Insertion between two intervals
- (i.e., point == i->position, where i is second interval) means
- text goes into second interval.
-
- Modifications are needed to handle the hungry bits -- after simply
- finding the interval at position (don't add length going down),
- if it's the beginning of the interval, get the previous interval
- and check the hungry bits of both. Then add the length going back up
- to the root. */
-
-static INTERVAL
-adjust_intervals_for_insertion (tree, position, length)
- INTERVAL tree;
- int position, length;
-{
- register int relative_position;
- register INTERVAL this;
-
- if (TOTAL_LENGTH (tree) == 0) /* Paranoia */
- abort ();
-
- /* If inserting at point-max of a buffer, that position
- will be out of range */
- if (position > TOTAL_LENGTH (tree))
- position = TOTAL_LENGTH (tree);
- relative_position = position;
- this = tree;
-
- while (1)
- {
- if (relative_position <= LEFT_TOTAL_LENGTH (this))
- {
- this->total_length += length;
- this = this->left;
- }
- else if (relative_position > (TOTAL_LENGTH (this)
- - RIGHT_TOTAL_LENGTH (this)))
- {
- relative_position -= (TOTAL_LENGTH (this)
- - RIGHT_TOTAL_LENGTH (this));
- this->total_length += length;
- this = this->right;
- }
- else
- {
- /* If we are to use zero-length intervals as buffer pointers,
- then this code will have to change. */
- this->total_length += length;
- this->position = LEFT_TOTAL_LENGTH (this)
- + position - relative_position + 1;
- return tree;
- }
- }
-}
-#endif
-
-/* Effect an adjustment corresponding to the addition of LENGTH characters
- of text. Do this by finding the interval containing POSITION in the
- interval tree TREE, and then adjusting all of its ancestors by adding
- LENGTH to them.
-
- If POSITION is the first character of an interval, meaning that point
- is actually between the two intervals, make the new text belong to
- the interval which is "sticky".
-
- If both intervals are "sticky", then make them belong to the left-most
- interval. Another possibility would be to create a new interval for
- this text, and make it have the merged properties of both ends. */
-
-static INTERVAL
-adjust_intervals_for_insertion (tree, position, length)
- INTERVAL tree;
- int position, length;
-{
- register INTERVAL i;
- register INTERVAL temp;
- int eobp = 0;
-
- if (TOTAL_LENGTH (tree) == 0) /* Paranoia */
- abort ();
-
- /* If inserting at point-max of a buffer, that position will be out
- of range. Remember that buffer positions are 1-based. */
- if (position >= BEG + TOTAL_LENGTH (tree)){
- position = BEG + TOTAL_LENGTH (tree);
- eobp = 1;
- }
-
- i = find_interval (tree, position);
-
- /* If in middle of an interval which is not sticky either way,
- we must not just give its properties to the insertion.
- So split this interval at the insertion point. */
- if (! (position == i->position || eobp)
- && END_NONSTICKY_P (i)
- && FRONT_NONSTICKY_P (i))
- {
- Lisp_Object tail;
- Lisp_Object front, rear;
-
- front = textget (i->plist, Qfront_sticky);
- rear = textget (i->plist, Qrear_nonsticky);
-
- /* Does any actual property pose an actual problem? */
- for (tail = i->plist; ! NILP (tail); tail = Fcdr (Fcdr (tail)))
- {
- Lisp_Object prop;
- prop = XCONS (tail)->car;
-
- /* Is this particular property rear-sticky?
- Note, if REAR isn't a cons, it must be non-nil,
- which means that all properties are rear-nonsticky. */
- if (CONSP (rear) && NILP (Fmemq (prop, rear)))
- continue;
-
- /* Is this particular property front-sticky?
- Note, if FRONT isn't a cons, it must be nil,
- which means that all properties are front-nonsticky. */
- if (CONSP (front) && ! NILP (Fmemq (prop, front)))
- continue;
-
- /* PROP isn't sticky on either side => it is a real problem. */
- break;
- }
-
- /* If any property is a real problem, split the interval. */
- if (! NILP (tail))
- {
- temp = split_interval_right (i, position - i->position);
- copy_properties (i, temp);
- i = temp;
- }
- }
-
- /* If we are positioned between intervals, check the stickiness of
- both of them. We have to do this too, if we are at BEG or Z. */
- if (position == i->position || eobp)
- {
- register INTERVAL prev;
-
- if (position == BEG)
- prev = 0;
- else if (eobp)
- {
- prev = i;
- i = 0;
- }
- else
- prev = previous_interval (i);
-
- /* Even if we are positioned between intervals, we default
- to the left one if it exists. We extend it now and split
- off a part later, if stickiness demands it. */
- for (temp = prev ? prev : i;! NULL_INTERVAL_P (temp); temp = temp->parent)
- {
- temp->total_length += length;
- temp = balance_possible_root_interval (temp);
- }
-
- /* If at least one interval has sticky properties,
- we check the stickiness property by property. */
- if (END_NONSTICKY_P (prev) || FRONT_STICKY_P (i))
- {
- Lisp_Object pleft, pright;
- struct interval newi;
-
- pleft = NULL_INTERVAL_P (prev) ? Qnil : prev->plist;
- pright = NULL_INTERVAL_P (i) ? Qnil : i->plist;
- newi.plist = merge_properties_sticky (pleft, pright);
-
- if(! prev) /* i.e. position == BEG */
- {
- if (! intervals_equal (i, &newi))
- {
- i = split_interval_left (i, length);
- i->plist = newi.plist;
- }
- }
- else if (! intervals_equal (prev, &newi))
- {
- prev = split_interval_right (prev,
- position - prev->position);
- prev->plist = newi.plist;
- if (! NULL_INTERVAL_P (i)
- && intervals_equal (prev, i))
- merge_interval_right (prev);
- }
-
- /* We will need to update the cache here later. */
- }
- else if (! prev && ! NILP (i->plist))
- {
- /* Just split off a new interval at the left.
- Since I wasn't front-sticky, the empty plist is ok. */
- i = split_interval_left (i, length);
- }
- }
-
- /* Otherwise just extend the interval. */
- else
- {
- for (temp = i; ! NULL_INTERVAL_P (temp); temp = temp->parent)
- {
- temp->total_length += length;
- temp = balance_possible_root_interval (temp);
- }
- }
-
- return tree;
-}
-
-/* Any property might be front-sticky on the left, rear-sticky on the left,
- front-sticky on the right, or rear-sticky on the right; the 16 combinations
- can be arranged in a matrix with rows denoting the left conditions and
- columns denoting the right conditions:
- _ __ _
-_ FR FR FR FR
-FR__ 0 1 2 3
- _FR 4 5 6 7
-FR 8 9 A B
- FR C D E F
-
- left-props = '(front-sticky (p8 p9 pa pb pc pd pe pf)
- rear-nonsticky (p4 p5 p6 p7 p8 p9 pa pb)
- p0 L p1 L p2 L p3 L p4 L p5 L p6 L p7 L
- p8 L p9 L pa L pb L pc L pd L pe L pf L)
- right-props = '(front-sticky (p2 p3 p6 p7 pa pb pe pf)
- rear-nonsticky (p1 p2 p5 p6 p9 pa pd pe)
- p0 R p1 R p2 R p3 R p4 R p5 R p6 R p7 R
- p8 R p9 R pa R pb R pc R pd R pe R pf R)
-
- We inherit from whoever has a sticky side facing us. If both sides
- do (cases 2, 3, E, and F), then we inherit from whichever side has a
- non-nil value for the current property. If both sides do, then we take
- from the left.
-
- When we inherit a property, we get its stickiness as well as its value.
- So, when we merge the above two lists, we expect to get this:
-
- result = '(front-sticky (p6 p7 pa pb pc pd pe pf)
- rear-nonsticky (p6 pa)
- p0 L p1 L p2 L p3 L p6 R p7 R
- pa R pb R pc L pd L pe L pf L)
-
- The optimizable special cases are:
- left rear-nonsticky = nil, right front-sticky = nil (inherit left)
- left rear-nonsticky = t, right front-sticky = t (inherit right)
- left rear-nonsticky = t, right front-sticky = nil (inherit none)
-*/
-
-Lisp_Object
-merge_properties_sticky (pleft, pright)
- Lisp_Object pleft, pright;
-{
- register Lisp_Object props, front, rear;
- Lisp_Object lfront, lrear, rfront, rrear;
- register Lisp_Object tail1, tail2, sym, lval, rval, cat;
- int use_left, use_right;
- int lpresent;
-
- props = Qnil;
- front = Qnil;
- rear = Qnil;
- lfront = textget (pleft, Qfront_sticky);
- lrear = textget (pleft, Qrear_nonsticky);
- rfront = textget (pright, Qfront_sticky);
- rrear = textget (pright, Qrear_nonsticky);
-
- /* Go through each element of PRIGHT. */
- for (tail1 = pright; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1)))
- {
- sym = Fcar (tail1);
-
- /* Sticky properties get special treatment. */
- if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky))
- continue;
-
- rval = Fcar (Fcdr (tail1));
- for (tail2 = pleft; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2)))
- if (EQ (sym, Fcar (tail2)))
- break;
-
- /* Indicate whether the property is explicitly defined on the left.
- (We know it is defined explicitly on the right
- because otherwise we don't get here.) */
- lpresent = ! NILP (tail2);
- lval = (NILP (tail2) ? Qnil : Fcar (Fcdr (tail2)));
-
- use_left = ! TMEM (sym, lrear) && lpresent;
- use_right = TMEM (sym, rfront);
- if (use_left && use_right)
- {
- if (NILP (lval))
- use_left = 0;
- else if (NILP (rval))
- use_right = 0;
- }
- if (use_left)
- {
- /* We build props as (value sym ...) rather than (sym value ...)
- because we plan to nreverse it when we're done. */
- props = Fcons (lval, Fcons (sym, props));
- if (TMEM (sym, lfront))
- front = Fcons (sym, front);
- if (TMEM (sym, lrear))
- rear = Fcons (sym, rear);
- }
- else if (use_right)
- {
- props = Fcons (rval, Fcons (sym, props));
- if (TMEM (sym, rfront))
- front = Fcons (sym, front);
- if (TMEM (sym, rrear))
- rear = Fcons (sym, rear);
- }
- }
-
- /* Now go through each element of PLEFT. */
- for (tail2 = pleft; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2)))
- {
- sym = Fcar (tail2);
-
- /* Sticky properties get special treatment. */
- if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky))
- continue;
-
- /* If sym is in PRIGHT, we've already considered it. */
- for (tail1 = pright; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1)))
- if (EQ (sym, Fcar (tail1)))
- break;
- if (! NILP (tail1))
- continue;
-
- lval = Fcar (Fcdr (tail2));
-
- /* Since rval is known to be nil in this loop, the test simplifies. */
- if (! TMEM (sym, lrear))
- {
- props = Fcons (lval, Fcons (sym, props));
- if (TMEM (sym, lfront))
- front = Fcons (sym, front);
- }
- else if (TMEM (sym, rfront))
- {
- /* The value is nil, but we still inherit the stickiness
- from the right. */
- front = Fcons (sym, front);
- if (TMEM (sym, rrear))
- rear = Fcons (sym, rear);
- }
- }
- props = Fnreverse (props);
- if (! NILP (rear))
- props = Fcons (Qrear_nonsticky, Fcons (Fnreverse (rear), props));
-
- cat = textget (props, Qcategory);
- if (! NILP (front)
- &&
- /* If we have inherited a front-stick category property that is t,
- we don't need to set up a detailed one. */
- ! (! NILP (cat) && SYMBOLP (cat)
- && EQ (Fget (cat, Qfront_sticky), Qt)))
- props = Fcons (Qfront_sticky, Fcons (Fnreverse (front), props));
- return props;
-}
-
-
-/* Delete an node I from its interval tree by merging its subtrees
- into one subtree which is then returned. Caller is responsible for
- storing the resulting subtree into its parent. */
-
-static INTERVAL
-delete_node (i)
- register INTERVAL i;
-{
- register INTERVAL migrate, this;
- register int migrate_amt;
-
- if (NULL_INTERVAL_P (i->left))
- return i->right;
- if (NULL_INTERVAL_P (i->right))
- return i->left;
-
- migrate = i->left;
- migrate_amt = i->left->total_length;
- this = i->right;
- this->total_length += migrate_amt;
- while (! NULL_INTERVAL_P (this->left))
- {
- this = this->left;
- this->total_length += migrate_amt;
- }
- this->left = migrate;
- migrate->parent = this;
-
- return i->right;
-}
-
-/* Delete interval I from its tree by calling `delete_node'
- and properly connecting the resultant subtree.
-
- I is presumed to be empty; that is, no adjustments are made
- for the length of I. */
-
-void
-delete_interval (i)
- register INTERVAL i;
-{
- register INTERVAL parent;
- int amt = LENGTH (i);
-
- if (amt > 0) /* Only used on zero-length intervals now. */
- abort ();
-
- if (ROOT_INTERVAL_P (i))
- {
- Lisp_Object owner;
- owner = (Lisp_Object) i->parent;
- parent = delete_node (i);
- if (! NULL_INTERVAL_P (parent))
- parent->parent = (INTERVAL) owner;
-
- if (BUFFERP (owner))
- BUF_INTERVALS (XBUFFER (owner)) = parent;
- else if (STRINGP (owner))
- XSTRING (owner)->intervals = parent;
- else
- abort ();
-
- return;
- }
-
- parent = i->parent;
- if (AM_LEFT_CHILD (i))
- {
- parent->left = delete_node (i);
- if (! NULL_INTERVAL_P (parent->left))
- parent->left->parent = parent;
- }
- else
- {
- parent->right = delete_node (i);
- if (! NULL_INTERVAL_P (parent->right))
- parent->right->parent = parent;
- }
-}
-
-/* Find the interval in TREE corresponding to the relative position
- FROM and delete as much as possible of AMOUNT from that interval.
- Return the amount actually deleted, and if the interval was
- zeroed-out, delete that interval node from the tree.
-
- Note that FROM is actually origin zero, aka relative to the
- leftmost edge of tree. This is appropriate since we call ourselves
- recursively on subtrees.
-
- Do this by recursing down TREE to the interval in question, and
- deleting the appropriate amount of text. */
-
-static int
-interval_deletion_adjustment (tree, from, amount)
- register INTERVAL tree;
- register int from, amount;
-{
- register int relative_position = from;
-
- if (NULL_INTERVAL_P (tree))
- return 0;
-
- /* Left branch */
- if (relative_position < LEFT_TOTAL_LENGTH (tree))
- {
- int subtract = interval_deletion_adjustment (tree->left,
- relative_position,
- amount);
- tree->total_length -= subtract;
- return subtract;
- }
- /* Right branch */
- else if (relative_position >= (TOTAL_LENGTH (tree)
- - RIGHT_TOTAL_LENGTH (tree)))
- {
- int subtract;
-
- relative_position -= (tree->total_length
- - RIGHT_TOTAL_LENGTH (tree));
- subtract = interval_deletion_adjustment (tree->right,
- relative_position,
- amount);
- tree->total_length -= subtract;
- return subtract;
- }
- /* Here -- this node. */
- else
- {
- /* How much can we delete from this interval? */
- int my_amount = ((tree->total_length
- - RIGHT_TOTAL_LENGTH (tree))
- - relative_position);
-
- if (amount > my_amount)
- amount = my_amount;
-
- tree->total_length -= amount;
- if (LENGTH (tree) == 0)
- delete_interval (tree);
-
- return amount;
- }
-
- /* Never reach here. */
-}
-
-/* Effect the adjustments necessary to the interval tree of BUFFER to
- correspond to the deletion of LENGTH characters from that buffer
- text. The deletion is effected at position START (which is a
- buffer position, i.e. origin 1). */
-
-static void
-adjust_intervals_for_deletion (buffer, start, length)
- struct buffer *buffer;
- int start, length;
-{
- register int left_to_delete = length;
- register INTERVAL tree = BUF_INTERVALS (buffer);
- register int deleted;
-
- if (NULL_INTERVAL_P (tree))
- return;
-
- if (start > BEG + TOTAL_LENGTH (tree)
- || start + length > BEG + TOTAL_LENGTH (tree))
- abort ();
-
- if (length == TOTAL_LENGTH (tree))
- {
- BUF_INTERVALS (buffer) = NULL_INTERVAL;
- return;
- }
-
- if (ONLY_INTERVAL_P (tree))
- {
- tree->total_length -= length;
- return;
- }
-
- if (start > BEG + TOTAL_LENGTH (tree))
- start = BEG + TOTAL_LENGTH (tree);
- while (left_to_delete > 0)
- {
- left_to_delete -= interval_deletion_adjustment (tree, start - 1,
- left_to_delete);
- tree = BUF_INTERVALS (buffer);
- if (left_to_delete == tree->total_length)
- {
- BUF_INTERVALS (buffer) = NULL_INTERVAL;
- return;
- }
- }
-}
-
-/* Make the adjustments necessary to the interval tree of BUFFER to
- represent an addition or deletion of LENGTH characters starting
- at position START. Addition or deletion is indicated by the sign
- of LENGTH. */
-
-INLINE void
-offset_intervals (buffer, start, length)
- struct buffer *buffer;
- int start, length;
-{
- if (NULL_INTERVAL_P (BUF_INTERVALS (buffer)) || length == 0)
- return;
-
- if (length > 0)
- adjust_intervals_for_insertion (BUF_INTERVALS (buffer), start, length);
- else
- adjust_intervals_for_deletion (buffer, start, -length);
-}
-
-/* Merge interval I with its lexicographic successor. The resulting
- interval is returned, and has the properties of the original
- successor. The properties of I are lost. I is removed from the
- interval tree.
-
- IMPORTANT:
- The caller must verify that this is not the last (rightmost)
- interval. */
-
-INTERVAL
-merge_interval_right (i)
- register INTERVAL i;
-{
- register int absorb = LENGTH (i);
- register INTERVAL successor;
-
- /* Zero out this interval. */
- i->total_length -= absorb;
-
- /* Find the succeeding interval. */
- if (! NULL_RIGHT_CHILD (i)) /* It's below us. Add absorb
- as we descend. */
- {
- successor = i->right;
- while (! NULL_LEFT_CHILD (successor))
- {
- successor->total_length += absorb;
- successor = successor->left;
- }
-
- successor->total_length += absorb;
- delete_interval (i);
- return successor;
- }
-
- successor = i;
- while (! NULL_PARENT (successor)) /* It's above us. Subtract as
- we ascend. */
- {
- if (AM_LEFT_CHILD (successor))
- {
- successor = successor->parent;
- delete_interval (i);
- return successor;
- }
-
- successor = successor->parent;
- successor->total_length -= absorb;
- }
-
- /* This must be the rightmost or last interval and cannot
- be merged right. The caller should have known. */
- abort ();
-}
-
-/* Merge interval I with its lexicographic predecessor. The resulting
- interval is returned, and has the properties of the original predecessor.
- The properties of I are lost. Interval node I is removed from the tree.
-
- IMPORTANT:
- The caller must verify that this is not the first (leftmost) interval. */
-
-INTERVAL
-merge_interval_left (i)
- register INTERVAL i;
-{
- register int absorb = LENGTH (i);
- register INTERVAL predecessor;
-
- /* Zero out this interval. */
- i->total_length -= absorb;
-
- /* Find the preceding interval. */
- if (! NULL_LEFT_CHILD (i)) /* It's below us. Go down,
- adding ABSORB as we go. */
- {
- predecessor = i->left;
- while (! NULL_RIGHT_CHILD (predecessor))
- {
- predecessor->total_length += absorb;
- predecessor = predecessor->right;
- }
-
- predecessor->total_length += absorb;
- delete_interval (i);
- return predecessor;
- }
-
- predecessor = i;
- while (! NULL_PARENT (predecessor)) /* It's above us. Go up,
- subtracting ABSORB. */
- {
- if (AM_RIGHT_CHILD (predecessor))
- {
- predecessor = predecessor->parent;
- delete_interval (i);
- return predecessor;
- }
-
- predecessor = predecessor->parent;
- predecessor->total_length -= absorb;
- }
-
- /* This must be the leftmost or first interval and cannot
- be merged left. The caller should have known. */
- abort ();
-}
-
-/* Make an exact copy of interval tree SOURCE which descends from
- PARENT. This is done by recursing through SOURCE, copying
- the current interval and its properties, and then adjusting
- the pointers of the copy. */
-
-static INTERVAL
-reproduce_tree (source, parent)
- INTERVAL source, parent;
-{
- register INTERVAL t = make_interval ();
-
- bcopy (source, t, INTERVAL_SIZE);
- copy_properties (source, t);
- t->parent = parent;
- if (! NULL_LEFT_CHILD (source))
- t->left = reproduce_tree (source->left, t);
- if (! NULL_RIGHT_CHILD (source))
- t->right = reproduce_tree (source->right, t);
-
- return t;
-}
-
-#if 0
-/* Nobody calls this. Perhaps it's a vestige of an earlier design. */
-
-/* Make a new interval of length LENGTH starting at START in the
- group of intervals INTERVALS, which is actually an interval tree.
- Returns the new interval.
-
- Generate an error if the new positions would overlap an existing
- interval. */
-
-static INTERVAL
-make_new_interval (intervals, start, length)
- INTERVAL intervals;
- int start, length;
-{
- INTERVAL slot;
-
- slot = find_interval (intervals, start);
- if (start + length > slot->position + LENGTH (slot))
- error ("Interval would overlap");
-
- if (start == slot->position && length == LENGTH (slot))
- return slot;
-
- if (slot->position == start)
- {
- /* New right node. */
- split_interval_right (slot, length);
- return slot;
- }
-
- if (slot->position + LENGTH (slot) == start + length)
- {
- /* New left node. */
- split_interval_left (slot, LENGTH (slot) - length);
- return slot;
- }
-
- /* Convert interval SLOT into three intervals. */
- split_interval_left (slot, start - slot->position);
- split_interval_right (slot, length);
- return slot;
-}
-#endif
-
-/* Insert the intervals of SOURCE into BUFFER at POSITION.
- LENGTH is the length of the text in SOURCE.
-
- This is used in insdel.c when inserting Lisp_Strings into the
- buffer. The text corresponding to SOURCE is already in the buffer
- when this is called. The intervals of new tree are a copy of those
- belonging to the string being inserted; intervals are never
- shared.
-
- If the inserted text had no intervals associated, and we don't
- want to inherit the surrounding text's properties, this function
- simply returns -- offset_intervals should handle placing the
- text in the correct interval, depending on the sticky bits.
-
- If the inserted text had properties (intervals), then there are two
- cases -- either insertion happened in the middle of some interval,
- or between two intervals.
-
- If the text goes into the middle of an interval, then new
- intervals are created in the middle with only the properties of
- the new text, *unless* the macro MERGE_INSERTIONS is true, in
- which case the new text has the union of its properties and those
- of the text into which it was inserted.
-
- If the text goes between two intervals, then if neither interval
- had its appropriate sticky property set (front_sticky, rear_sticky),
- the new text has only its properties. If one of the sticky properties
- is set, then the new text "sticks" to that region and its properties
- depend on merging as above. If both the preceding and succeeding
- intervals to the new text are "sticky", then the new text retains
- only its properties, as if neither sticky property were set. Perhaps
- we should consider merging all three sets of properties onto the new
- text... */
-
-void
-graft_intervals_into_buffer (source, position, length, buffer, inherit)
- INTERVAL source;
- int position, length;
- struct buffer *buffer;
- int inherit;
-{
- register INTERVAL under, over, this, prev;
- register INTERVAL tree;
- int middle;
-
- tree = BUF_INTERVALS (buffer);
-
- /* If the new text has no properties, it becomes part of whatever
- interval it was inserted into. */
- if (NULL_INTERVAL_P (source))
- {
- Lisp_Object buf;
- if (!inherit && ! NULL_INTERVAL_P (tree))
- {
- XSETBUFFER (buf, buffer);
- Fset_text_properties (make_number (position),
- make_number (position + length),
- Qnil, buf);
- }
- if (! NULL_INTERVAL_P (BUF_INTERVALS (buffer)))
- BUF_INTERVALS (buffer) = balance_an_interval (BUF_INTERVALS (buffer));
- return;
- }
-
- if (NULL_INTERVAL_P (tree))
- {
- /* The inserted text constitutes the whole buffer, so
- simply copy over the interval structure. */
- if ((BUF_Z (buffer) - BUF_BEG (buffer)) == TOTAL_LENGTH (source))
- {
- Lisp_Object buf;
- XSETBUFFER (buf, buffer);
- BUF_INTERVALS (buffer) = reproduce_tree (source, buf);
- /* Explicitly free the old tree here. */
-
- return;
- }
-
- /* Create an interval tree in which to place a copy
- of the intervals of the inserted string. */
- {
- Lisp_Object buf;
- XSETBUFFER (buf, buffer);
- tree = create_root_interval (buf);
- }
- }
- else if (TOTAL_LENGTH (tree) == TOTAL_LENGTH (source))
- /* If the buffer contains only the new string, but
- there was already some interval tree there, then it may be
- some zero length intervals. Eventually, do something clever
- about inserting properly. For now, just waste the old intervals. */
- {
- BUF_INTERVALS (buffer) = reproduce_tree (source, tree->parent);
- /* Explicitly free the old tree here. */
-
- return;
- }
- /* Paranoia -- the text has already been added, so this buffer
- should be of non-zero length. */
- else if (TOTAL_LENGTH (tree) == 0)
- abort ();
-
- this = under = find_interval (tree, position);
- if (NULL_INTERVAL_P (under)) /* Paranoia */
- abort ();
- over = find_interval (source, 1);
-
- /* Here for insertion in the middle of an interval.
- Split off an equivalent interval to the right,
- then don't bother with it any more. */
-
- if (position > under->position)
- {
- INTERVAL end_unchanged
- = split_interval_left (this, position - under->position);
- copy_properties (under, end_unchanged);
- under->position = position;
- prev = 0;
- middle = 1;
- }
- else
- {
- prev = previous_interval (under);
- if (prev && !END_NONSTICKY_P (prev))
- prev = 0;
- }
-
- /* Insertion is now at beginning of UNDER. */
-
- /* The inserted text "sticks" to the interval `under',
- which means it gets those properties.
- The properties of under are the result of
- adjust_intervals_for_insertion, so stickiness has
- already been taken care of. */
-
- while (! NULL_INTERVAL_P (over))
- {
- if (LENGTH (over) < LENGTH (under))
- {
- this = split_interval_left (under, LENGTH (over));
- copy_properties (under, this);
- }
- else
- this = under;
- copy_properties (over, this);
- if (inherit)
- merge_properties (over, this);
- else
- copy_properties (over, this);
- over = next_interval (over);
- }
-
- if (! NULL_INTERVAL_P (BUF_INTERVALS (buffer)))
- BUF_INTERVALS (buffer) = balance_an_interval (BUF_INTERVALS (buffer));
- return;
-}
-
-/* Get the value of property PROP from PLIST,
- which is the plist of an interval.
- We check for direct properties, for categories with property PROP,
- and for PROP appearing on the default-text-properties list. */
-
-Lisp_Object
-textget (plist, prop)
- Lisp_Object plist;
- register Lisp_Object prop;
-{
- register Lisp_Object tail, fallback;
- fallback = Qnil;
-
- for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
- {
- register Lisp_Object tem;
- tem = Fcar (tail);
- if (EQ (prop, tem))
- return Fcar (Fcdr (tail));
- if (EQ (tem, Qcategory))
- {
- tem = Fcar (Fcdr (tail));
- if (SYMBOLP (tem))
- fallback = Fget (tem, prop);
- }
- }
-
- if (! NILP (fallback))
- return fallback;
- if (CONSP (Vdefault_text_properties))
- return Fplist_get (Vdefault_text_properties, prop);
- return Qnil;
-}
-
-
-/* Set point in BUFFER to POSITION. If the target position is
- before an intangible character, move to an ok place. */
-
-void
-set_point (position, buffer)
- register int position;
- register struct buffer *buffer;
-{
- register INTERVAL to, from, toprev, fromprev, target;
- int buffer_point;
- register Lisp_Object obj;
- int old_position = BUF_PT (buffer);
- int backwards = (position < old_position ? 1 : 0);
- int have_overlays;
- int original_position;
-
- buffer->point_before_scroll = Qnil;
-
- if (position == BUF_PT (buffer))
- return;
-
- /* Check this now, before checking if the buffer has any intervals.
- That way, we can catch conditions which break this sanity check
- whether or not there are intervals in the buffer. */
- if (position > BUF_ZV (buffer) || position < BUF_BEGV (buffer))
- abort ();
-
- have_overlays = (! NILP (buffer->overlays_before)
- || ! NILP (buffer->overlays_after));
-
- /* If we have no text properties and overlays,
- then we can do it quickly. */
- if (NULL_INTERVAL_P (BUF_INTERVALS (buffer)) && ! have_overlays)
- {
- BUF_PT (buffer) = position;
- return;
- }
-
- /* Set TO to the interval containing the char after POSITION,
- and TOPREV to the interval containing the char before POSITION.
- Either one may be null. They may be equal. */
- to = find_interval (BUF_INTERVALS (buffer), position);
- if (position == BUF_BEGV (buffer))
- toprev = 0;
- else if (to && to->position == position)
- toprev = previous_interval (to);
- else
- toprev = to;
-
- buffer_point = (BUF_PT (buffer) == BUF_ZV (buffer)
- ? BUF_ZV (buffer) - 1
- : BUF_PT (buffer));
-
- /* Set FROM to the interval containing the char after PT,
- and FROMPREV to the interval containing the char before PT.
- Either one may be null. They may be equal. */
- /* We could cache this and save time. */
- from = find_interval (BUF_INTERVALS (buffer), buffer_point);
- if (buffer_point == BUF_BEGV (buffer))
- fromprev = 0;
- else if (from && from->position == BUF_PT (buffer))
- fromprev = previous_interval (from);
- else if (buffer_point != BUF_PT (buffer))
- fromprev = from, from = 0;
- else
- fromprev = from;
-
- /* Moving within an interval. */
- if (to == from && toprev == fromprev && INTERVAL_VISIBLE_P (to)
- && ! have_overlays)
- {
- BUF_PT (buffer) = position;
- return;
- }
-
- original_position = position;
-
- /* If the new position is between two intangible characters
- with the same intangible property value,
- move forward or backward until a change in that property. */
- if (NILP (Vinhibit_point_motion_hooks)
- && ((! NULL_INTERVAL_P (to) && ! NULL_INTERVAL_P (toprev))
- || have_overlays)
- /* Intangibility never stops us from positioning at the beginning
- or end of the buffer, so don't bother checking in that case. */
- && position != BEGV && position != ZV)
- {
- Lisp_Object intangible_propval;
- Lisp_Object pos;
-
- XSETINT (pos, position);
-
- if (backwards)
- {
- intangible_propval = Fget_char_property (make_number (position),
- Qintangible, Qnil);
-
- /* If following char is intangible,
- skip back over all chars with matching intangible property. */
- if (! NILP (intangible_propval))
- while (XINT (pos) > BUF_BEGV (buffer)
- && EQ (Fget_char_property (make_number (XINT (pos) - 1),
- Qintangible, Qnil),
- intangible_propval))
- pos = Fprevious_char_property_change (pos, Qnil);
- }
- else
- {
- intangible_propval = Fget_char_property (make_number (position - 1),
- Qintangible, Qnil);
-
- /* If following char is intangible,
- skip back over all chars with matching intangible property. */
- if (! NILP (intangible_propval))
- while (XINT (pos) < BUF_ZV (buffer)
- && EQ (Fget_char_property (pos, Qintangible, Qnil),
- intangible_propval))
- pos = Fnext_char_property_change (pos, Qnil);
-
- }
-
- position = XINT (pos);
- }
-
- if (position != original_position)
- {
- /* Set TO to the interval containing the char after POSITION,
- and TOPREV to the interval containing the char before POSITION.
- Either one may be null. They may be equal. */
- to = find_interval (BUF_INTERVALS (buffer), position);
- if (position == BUF_BEGV (buffer))
- toprev = 0;
- else if (to && to->position == position)
- toprev = previous_interval (to);
- else
- toprev = to;
- }
-
- /* Here TO is the interval after the stopping point
- and TOPREV is the interval before the stopping point.
- One or the other may be null. */
-
- BUF_PT (buffer) = position;
-
- /* We run point-left and point-entered hooks here, iff the
- two intervals are not equivalent. These hooks take
- (old_point, new_point) as arguments. */
- if (NILP (Vinhibit_point_motion_hooks)
- && (! intervals_equal (from, to)
- || ! intervals_equal (fromprev, toprev)))
- {
- Lisp_Object leave_after, leave_before, enter_after, enter_before;
-
- if (fromprev)
- leave_after = textget (fromprev->plist, Qpoint_left);
- else
- leave_after = Qnil;
- if (from)
- leave_before = textget (from->plist, Qpoint_left);
- else
- leave_before = Qnil;
-
- if (toprev)
- enter_after = textget (toprev->plist, Qpoint_entered);
- else
- enter_after = Qnil;
- if (to)
- enter_before = textget (to->plist, Qpoint_entered);
- else
- enter_before = Qnil;
-
- if (! EQ (leave_before, enter_before) && !NILP (leave_before))
- call2 (leave_before, old_position, position);
- if (! EQ (leave_after, enter_after) && !NILP (leave_after))
- call2 (leave_after, old_position, position);
-
- if (! EQ (enter_before, leave_before) && !NILP (enter_before))
- call2 (enter_before, old_position, position);
- if (! EQ (enter_after, leave_after) && !NILP (enter_after))
- call2 (enter_after, old_position, position);
- }
-}
-
-/* Set point temporarily, without checking any text properties. */
-
-INLINE void
-temp_set_point (position, buffer)
- int position;
- struct buffer *buffer;
-{
- BUF_PT (buffer) = position;
-}
-
-/* Return the proper local map for position POSITION in BUFFER.
- Use the map specified by the local-map property, if any.
- Otherwise, use BUFFER's local map. */
-
-Lisp_Object
-get_local_map (position, buffer)
- register int position;
- register struct buffer *buffer;
-{
- Lisp_Object prop, tem, lispy_position, lispy_buffer;
- int old_begv, old_zv;
-
- /* Perhaps we should just change `position' to the limit. */
- if (position > BUF_Z (buffer) || position < BUF_BEG (buffer))
- abort ();
-
- /* Ignore narrowing, so that a local map continues to be valid even if
- the visible region contains no characters and hence no properties. */
- old_begv = BUF_BEGV (buffer);
- old_zv = BUF_ZV (buffer);
- BUF_BEGV (buffer) = BUF_BEG (buffer);
- BUF_ZV (buffer) = BUF_Z (buffer);
-
- /* There are no properties at the end of the buffer, so in that case
- check for a local map on the last character of the buffer instead. */
- if (position == BUF_Z (buffer) && BUF_Z (buffer) > BUF_BEG (buffer))
- --position;
- XSETFASTINT (lispy_position, position);
- XSETBUFFER (lispy_buffer, buffer);
- prop = Fget_char_property (lispy_position, Qlocal_map, lispy_buffer);
-
- BUF_BEGV (buffer) = old_begv;
- BUF_ZV (buffer) = old_zv;
-
- /* Use the local map only if it is valid. */
- /* Do allow symbols that are defined as keymaps. */
- if (SYMBOLP (prop) && !NILP (prop))
- prop = Findirect_function (prop);
- if (!NILP (prop)
- && (tem = Fkeymapp (prop), !NILP (tem)))
- return prop;
-
- return buffer->keymap;
-}
-
-/* Produce an interval tree reflecting the intervals in
- TREE from START to START + LENGTH. */
-
-INTERVAL
-copy_intervals (tree, start, length)
- INTERVAL tree;
- int start, length;
-{
- register INTERVAL i, new, t;
- register int got, prevlen;
-
- if (NULL_INTERVAL_P (tree) || length <= 0)
- return NULL_INTERVAL;
-
- i = find_interval (tree, start);
- if (NULL_INTERVAL_P (i) || LENGTH (i) == 0)
- abort ();
-
- /* If there is only one interval and it's the default, return nil. */
- if ((start - i->position + 1 + length) < LENGTH (i)
- && DEFAULT_INTERVAL_P (i))
- return NULL_INTERVAL;
-
- new = make_interval ();
- new->position = 1;
- got = (LENGTH (i) - (start - i->position));
- new->total_length = length;
- copy_properties (i, new);
-
- t = new;
- prevlen = got;
- while (got < length)
- {
- i = next_interval (i);
- t = split_interval_right (t, prevlen);
- copy_properties (i, t);
- prevlen = LENGTH (i);
- got += prevlen;
- }
-
- return balance_an_interval (new);
-}
-
-/* Give STRING the properties of BUFFER from POSITION to LENGTH. */
-
-INLINE void
-copy_intervals_to_string (string, buffer, position, length)
- Lisp_Object string;
- struct buffer *buffer;
- int position, length;
-{
- INTERVAL interval_copy = copy_intervals (BUF_INTERVALS (buffer),
- position, length);
- if (NULL_INTERVAL_P (interval_copy))
- return;
-
- interval_copy->parent = (INTERVAL) string;
- XSTRING (string)->intervals = interval_copy;
-}
-
-/* Return 1 if string S1 and S2 have identical properties; 0 otherwise.
- Assume they have identical characters. */
-
-int
-compare_string_intervals (s1, s2)
- Lisp_Object s1, s2;
-{
- INTERVAL i1, i2;
- int pos = 1;
- int end = XSTRING (s1)->size + 1;
-
- /* We specify 1 as position because the interval functions
- always use positions starting at 1. */
- i1 = find_interval (XSTRING (s1)->intervals, 1);
- i2 = find_interval (XSTRING (s2)->intervals, 1);
-
- while (pos < end)
- {
- /* Determine how far we can go before we reach the end of I1 or I2. */
- int len1 = (i1 != 0 ? INTERVAL_LAST_POS (i1) : end) - pos;
- int len2 = (i2 != 0 ? INTERVAL_LAST_POS (i2) : end) - pos;
- int distance = min (len1, len2);
-
- /* If we ever find a mismatch between the strings,
- they differ. */
- if (! intervals_equal (i1, i2))
- return 0;
-
- /* Advance POS till the end of the shorter interval,
- and advance one or both interval pointers for the new position. */
- pos += distance;
- if (len1 == distance)
- i1 = next_interval (i1);
- if (len2 == distance)
- i2 = next_interval (i2);
- }
- return 1;
-}
-
-#endif /* USE_TEXT_PROPERTIES */
diff --git a/src/intervals.h b/src/intervals.h
deleted file mode 100644
index 8ad333e2a67..00000000000
--- a/src/intervals.h
+++ /dev/null
@@ -1,255 +0,0 @@
-/* Definitions and global variables for intervals.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifdef USE_TEXT_PROPERTIES
-#ifndef NORMAL_FACE
-#include "dispextern.h"
-#endif
-
-#define NULL_INTERVAL 0
-#define INTERVAL_DEFAULT NULL_INTERVAL
-
-/* These are macros for dealing with the interval tree. */
-
-/* Size of the structure used to represent an interval */
-#define INTERVAL_SIZE (sizeof (struct interval))
-
-/* Size of a pointer to an interval structure */
-#define INTERVAL_PTR_SIZE (sizeof (struct interval *))
-
-/* True if an interval pointer is null, or is a Lisp_Buffer or
- Lisp_String pointer (meaning it points to the owner of this
- interval tree). */
-#define NULL_INTERVAL_P(i) ((i) == NULL_INTERVAL \
- || BUFFERP ((Lisp_Object)(i)) \
- || STRINGP ((Lisp_Object)(i)))
-
-/* True if this interval has no right child. */
-#define NULL_RIGHT_CHILD(i) ((i)->right == NULL_INTERVAL)
-
-/* True if this interval has no left child. */
-#define NULL_LEFT_CHILD(i) ((i)->left == NULL_INTERVAL)
-
-/* True if this interval has no parent. */
-#define NULL_PARENT(i) (NULL_INTERVAL_P ((i)->parent))
-
-/* True if this interval is the left child of some other interval. */
-#define AM_LEFT_CHILD(i) (! NULL_INTERVAL_P ((i)->parent) \
- && (i)->parent->left == (i))
-
-/* True if this interval is the right child of some other interval. */
-#define AM_RIGHT_CHILD(i) (! NULL_INTERVAL_P ((i)->parent) \
- && (i)->parent->right == (i))
-
-/* True if this interval has no children. */
-#define LEAF_INTERVAL_P(i) ((i)->left == NULL_INTERVAL \
- && (i)->right == NULL_INTERVAL)
-
-/* True if this interval has no parent and is therefore the root. */
-#define ROOT_INTERVAL_P(i) (NULL_PARENT (i))
-
-/* True if this interval is the only interval in the interval tree. */
-#define ONLY_INTERVAL_P(i) (ROOT_INTERVAL_P ((i)) && LEAF_INTERVAL_P ((i)))
-
-/* True if this interval has both left and right children. */
-#define BOTH_KIDS_P(i) ((i)->left != NULL_INTERVAL \
- && (i)->right != NULL_INTERVAL)
-
-/* The total size of all text represented by this interval and all its
- children in the tree. This is zero if the interval is null. */
-#define TOTAL_LENGTH(i) ((i) == NULL_INTERVAL ? 0 : (i)->total_length)
-
-/* The size of text represented by this interval alone. */
-#define LENGTH(i) ((i) == NULL_INTERVAL ? 0 : (TOTAL_LENGTH ((i)) \
- - TOTAL_LENGTH ((i)->right) \
- - TOTAL_LENGTH ((i)->left)))
-
-/* The position of the character just past the end of I. Note that
- the position cache i->position must be valid for this to work. */
-#define INTERVAL_LAST_POS(i) ((i)->position + LENGTH ((i)))
-
-/* The total size of the left subtree of this interval. */
-#define LEFT_TOTAL_LENGTH(i) ((i)->left ? (i)->left->total_length : 0)
-
-/* The total size of the right subtree of this interval. */
-#define RIGHT_TOTAL_LENGTH(i) ((i)->right ? (i)->right->total_length : 0)
-
-
-/* These macros are for dealing with the interval properties. */
-
-/* True if this is a default interval, which is the same as being null
- or having no properties. */
-#define DEFAULT_INTERVAL_P(i) (NULL_INTERVAL_P (i) || EQ ((i)->plist, Qnil))
-
-/* Reset this interval to its vanilla, or no-property state. */
-#define RESET_INTERVAL(i) \
-{ \
- (i)->total_length = (i)->position = 0; \
- (i)->left = (i)->right = NULL_INTERVAL; \
- (i)->parent = NULL_INTERVAL; \
- (i)->write_protect = 0; \
- (i)->visible = 0; \
- (i)->front_sticky = (i)->rear_sticky = 0; \
- (i)->plist = Qnil; \
-}
-
-/* Copy the cached property values of interval FROM to interval TO. */
-#define COPY_INTERVAL_CACHE(from,to) \
-{ \
- (to)->write_protect = (from)->write_protect; \
- (to)->visible = (from)->visible; \
- (to)->front_sticky = (from)->front_sticky; \
- (to)->rear_sticky = (from)->rear_sticky; \
-}
-
-/* Copy only the set bits of FROM's cache. */
-#define MERGE_INTERVAL_CACHE(from,to) \
-{ \
- if ((from)->write_protect) (to)->write_protect = 1; \
- if ((from)->visible) (to)->visible = 1; \
- if ((from)->front_sticky) (to)->front_sticky = 1; \
- if ((from)->rear_sticky) (to)->rear_sticky = 1; \
-}
-
-/* Macro determining whether the properties of an interval being
- inserted should be merged with the properties of the text where
- they are being inserted. */
-#define MERGE_INSERTIONS(i) 1
-
-/* Macro determining if an invisible interval should be displayed
- as a special glyph, or not at all. */
-#define DISPLAY_INVISIBLE_GLYPH(i) 0
-
-/* Is this interval visible? Replace later with cache access */
-#define INTERVAL_VISIBLE_P(i) \
- (! NULL_INTERVAL_P (i) && NILP (textget ((i)->plist, Qinvisible)))
-
-/* Is this interval writable? Replace later with cache access */
-#define INTERVAL_WRITABLE_P(i) \
- (! NULL_INTERVAL_P (i) \
- && (NILP (textget ((i)->plist, Qread_only)) \
- || ((CONSP (Vinhibit_read_only) \
- ? !NILP (Fmemq (textget ((i)->plist, Qread_only), \
- Vinhibit_read_only)) \
- : !NILP (Vinhibit_read_only))))) \
-
-/* Macros to tell whether insertions before or after this interval
- should stick to it. */
-/* Replace later with cache access */
-/*#define FRONT_STICKY_P(i) ((i)->front_sticky != 0)
- #define END_STICKY_P(i) ((i)->rear_sticky != 0)*/
-#define FRONT_STICKY_P(i) \
- (! NULL_INTERVAL_P (i) && ! NILP (textget ((i)->plist, Qfront_sticky)))
-#define END_NONSTICKY_P(i) \
- (! NULL_INTERVAL_P (i) && ! NILP (textget ((i)->plist, Qrear_nonsticky)))
-#define FRONT_NONSTICKY_P(i) \
- (! NULL_INTERVAL_P (i) && ! EQ (Qt, textget ((i)->plist, Qfront_sticky)))
-
-
-/* If PROP is the `invisible' property of a character,
- this is 1 if the character should be treated as invisible. */
-
-#define TEXT_PROP_MEANS_INVISIBLE(prop) \
- (EQ (current_buffer->invisibility_spec, Qt) \
- ? ! NILP (prop) \
- : invisible_p (prop, current_buffer->invisibility_spec))
-
-/* If PROP is the `invisible' property of a character,
- this is 1 if the character should be treated as invisible
- and should have an ellipsis. */
-
-#define TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS(prop) \
- (EQ (current_buffer->invisibility_spec, Qt) \
- ? 0 \
- : invisible_ellipsis_p (prop, current_buffer->invisibility_spec))
-
-/* Declared in alloc.c */
-
-extern INTERVAL make_interval ();
-
-/* Declared in intervals.c */
-
-extern INTERVAL create_root_interval ();
-extern void copy_properties ();
-extern int intervals_equal ();
-extern void traverse_intervals ();
-extern INTERVAL split_interval_right (), split_interval_left ();
-extern INLINE INTERVAL find_interval ();
-extern INTERVAL next_interval (), previous_interval ();
-extern INTERVAL merge_interval_left (), merge_interval_right ();
-extern void delete_interval ();
-extern INLINE void offset_intervals ();
-extern void graft_intervals_into_buffer ();
-extern void set_point ();
-extern INLINE void temp_set_point ();
-extern void verify_interval_modification ();
-extern INTERVAL balance_intervals ();
-extern INLINE void copy_intervals_to_string ();
-extern INTERVAL copy_intervals ();
-extern Lisp_Object textget ();
-extern Lisp_Object get_local_map ();
-
-/* Declared in textprop.c */
-
-/* Types of hooks. */
-extern Lisp_Object Qmouse_left;
-extern Lisp_Object Qmouse_entered;
-extern Lisp_Object Qpoint_left;
-extern Lisp_Object Qpoint_entered;
-extern Lisp_Object Qmodification_hooks;
-extern Lisp_Object Qcategory;
-extern Lisp_Object Qlocal_map;
-
-/* Visual properties text (including strings) may have. */
-extern Lisp_Object Qforeground, Qbackground, Qfont, Qunderline, Qstipple;
-extern Lisp_Object Qinvisible, Qintangible, Qread_only;
-
-extern Lisp_Object Vinhibit_point_motion_hooks;
-extern Lisp_Object Vdefault_text_properties;
-
-/* Sticky properties */
-extern Lisp_Object Qfront_sticky, Qrear_nonsticky;
-
-extern Lisp_Object Fget_char_property (), Fget_text_property ();
-extern Lisp_Object Ftext_properties_at ();
-extern Lisp_Object Fnext_property_change (), Fprevious_property_change ();
-extern Lisp_Object Fadd_text_properties (), Fset_text_properties ();
-extern Lisp_Object Fremove_text_properties (), Ferase_text_properties ();
-extern Lisp_Object Ftext_property_any (), Ftext_property_not_all ();
-extern Lisp_Object copy_text_properties ();
-
-extern void syms_of_textprop ();
-
-#else /* don't support text properties */
-
-#define NULL_INTERVAL_P(i) 1
-#define INTERVAL_SIZE 0
-#define INTERVAL_PTR_SIZE 0
-
-#define copy_intervals_to_string(string,buffer,position,length)
-#define verify_interval_modification(buffer,start,end)
-#define insert_interval_copy(source,position,end,sink,at)
-#define graft_intervals_into_buffer(tree,position,bufferptr)
-#define offset_intervals(buffer,position,length)
-#define copy_intervals(tree,start,length)
-
-#define syms_of_textprop()
-
-#endif /* don't support text properties */
diff --git a/src/ioctl.h b/src/ioctl.h
deleted file mode 100644
index 0366f6d6bd5..00000000000
--- a/src/ioctl.h
+++ /dev/null
@@ -1 +0,0 @@
-/* Emacs ioctl emulation for VMS */
diff --git a/src/keyboard.c b/src/keyboard.c
deleted file mode 100644
index ebe32821a28..00000000000
--- a/src/keyboard.c
+++ /dev/null
@@ -1,8294 +0,0 @@
-/* Keyboard and mouse input; editor command loop.
- Copyright (C) 1985,86,87,88,89,93,94,95,96 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Allow config.h to undefine symbols found here. */
-#include <signal.h>
-
-#include <config.h>
-#include <stdio.h>
-#include "termchar.h"
-#include "termopts.h"
-#include "lisp.h"
-#include "termhooks.h"
-#include "macros.h"
-#include "frame.h"
-#include "window.h"
-#include "commands.h"
-#include "buffer.h"
-#include "disptab.h"
-#include "dispextern.h"
-#include "keyboard.h"
-#include "intervals.h"
-#include "blockinput.h"
-#include <setjmp.h>
-#include <errno.h>
-
-#ifdef MSDOS
-#include "msdos.h"
-#include <time.h>
-#else /* not MSDOS */
-#ifndef VMS
-#include <sys/ioctl.h>
-#endif
-#endif /* not MSDOS */
-
-#include "syssignal.h"
-#include "systty.h"
-
-/* This is to get the definitions of the XK_ symbols. */
-#ifdef HAVE_X_WINDOWS
-#include "xterm.h"
-#endif
-
-#ifdef HAVE_NTGUI
-#include "w32term.h"
-#endif /* HAVE_NTGUI */
-
-/* Include systime.h after xterm.h to avoid double inclusion of time.h. */
-#include "systime.h"
-
-extern int errno;
-
-/* Variables for blockinput.h: */
-
-/* Non-zero if interrupt input is blocked right now. */
-int interrupt_input_blocked;
-
-/* Nonzero means an input interrupt has arrived
- during the current critical section. */
-int interrupt_input_pending;
-
-
-/* File descriptor to use for input. */
-extern int input_fd;
-
-#ifdef HAVE_WINDOW_SYSTEM
-/* Make all keyboard buffers much bigger when using X windows. */
-#define KBD_BUFFER_SIZE 4096
-#else /* No X-windows, character input */
-#define KBD_BUFFER_SIZE 256
-#endif /* No X-windows */
-
-/* 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;
- };
-
-#ifdef MULTI_KBOARD
-KBOARD *initial_kboard;
-KBOARD *current_kboard;
-KBOARD *all_kboards;
-int single_kboard;
-#else
-KBOARD the_only_kboard;
-#endif
-
-/* Non-nil disable property on a command means
- do not execute it; call disabled-command-hook's value instead. */
-Lisp_Object Qdisabled, Qdisabled_command_hook;
-
-#define NUM_RECENT_KEYS (100)
-int recent_keys_index; /* Index for storing next element into recent_keys */
-int total_keys; /* Total number of elements stored into recent_keys */
-Lisp_Object recent_keys; /* A vector, holding the last 100 keystrokes */
-
-/* Vector holding the key sequence that invoked the current command.
- It is reused for each command, and it may be longer than the current
- sequence; this_command_key_count indicates how many elements
- actually mean something.
- It's easier to staticpro a single Lisp_Object than an array. */
-Lisp_Object this_command_keys;
-int this_command_key_count;
-
-/* Number of elements of this_command_keys
- that precede this key sequence. */
-int this_single_command_key_start;
-
-/* Record values of this_command_key_count and echo_length ()
- before this command was read. */
-static int before_command_key_count;
-static int before_command_echo_length;
-/* Values of before_command_key_count and before_command_echo_length
- saved by reset-this-command-lengths. */
-static int before_command_key_count_1;
-static int before_command_echo_length_1;
-/* Flag set by reset-this-command-lengths,
- saying to reset the lengths when add_command_key is called. */
-static int before_command_restore_flag;
-
-extern int minbuf_level;
-
-extern struct backtrace *backtrace_list;
-
-/* Nonzero means do menu prompting. */
-static int menu_prompting;
-
-/* Character to see next line of menu prompt. */
-static Lisp_Object menu_prompt_more_char;
-
-/* For longjmp to where kbd input is being done. */
-static jmp_buf getcjmp;
-
-/* True while doing kbd input. */
-int waiting_for_input;
-
-/* True while displaying for echoing. Delays C-g throwing. */
-static int echoing;
-
-/* True means we can start echoing at the next input pause
- even though there is something in the echo area. */
-static char *ok_to_echo_at_next_pause;
-
-/* Nonzero means disregard local maps for the menu bar. */
-static int inhibit_local_menu_bar_menus;
-
-/* Nonzero means C-g should cause immediate error-signal. */
-int immediate_quit;
-
-/* Character to recognize as the help char. */
-Lisp_Object Vhelp_char;
-
-/* List of other event types to recognize as meaning "help". */
-Lisp_Object Vhelp_event_list;
-
-/* Form to execute when help char is typed. */
-Lisp_Object Vhelp_form;
-
-/* Command to run when the help character follows a prefix key. */
-Lisp_Object Vprefix_help_command;
-
-/* List of items that should move to the end of the menu bar. */
-Lisp_Object Vmenu_bar_final_items;
-
-/* Non-nil means show the equivalent key-binding for
- any M-x command that has one.
- The value can be a length of time to show the message for.
- If the value is non-nil and not a number, we wait 2 seconds. */
-Lisp_Object Vsuggest_key_bindings;
-
-/* Character that causes a quit. Normally C-g.
-
- If we are running on an ordinary terminal, this must be an ordinary
- ASCII char, since we want to make it our interrupt character.
-
- If we are not running on an ordinary terminal, it still needs to be
- an ordinary ASCII char. This character needs to be recognized in
- the input interrupt handler. At this point, the keystroke is
- represented as a struct input_event, while the desired quit
- character is specified as a lispy event. The mapping from struct
- input_events to lispy events cannot run in an interrupt handler,
- and the reverse mapping is difficult for anything but ASCII
- keystrokes.
-
- FOR THESE ELABORATE AND UNSATISFYING REASONS, quit_char must be an
- ASCII character. */
-int quit_char;
-
-extern Lisp_Object current_global_map;
-extern int minibuf_level;
-
-/* If non-nil, this is a map that overrides all other local maps. */
-Lisp_Object Voverriding_local_map;
-
-/* If non-nil, Voverriding_local_map applies to the menu bar. */
-Lisp_Object Voverriding_local_map_menu_flag;
-
-/* Keymap that defines special misc events that should
- be processed immediately at a low level. */
-Lisp_Object Vspecial_event_map;
-
-/* Current depth in recursive edits. */
-int command_loop_level;
-
-/* Total number of times command_loop has read a key sequence. */
-int num_input_keys;
-
-/* Last input character read as a command. */
-Lisp_Object last_command_char;
-
-/* Last input character read as a command, not counting menus
- reached by the mouse. */
-Lisp_Object last_nonmenu_event;
-
-/* Last input character read for any purpose. */
-Lisp_Object last_input_char;
-
-/* If not Qnil, a list of objects to be read as subsequent command input. */
-Lisp_Object Vunread_command_events;
-
-/* If not -1, an event to be read as subsequent command input. */
-int unread_command_char;
-
-/* If not Qnil, this is a switch-frame event which we decided to put
- off until the end of a key sequence. This should be read as the
- next command input, after any unread_command_events.
-
- read_key_sequence uses this to delay switch-frame events until the
- end of the key sequence; Fread_char uses it to put off switch-frame
- events until a non-ASCII event is acceptable as input. */
-Lisp_Object unread_switch_frame;
-
-/* A mask of extra modifier bits to put into every keyboard char. */
-int extra_keyboard_modifiers;
-
-/* 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. */
-
-Lisp_Object meta_prefix_char;
-
-/* Last size recorded for a current buffer which is not a minibuffer. */
-static int last_non_minibuf_size;
-
-/* Number of idle seconds before an auto-save and garbage collection. */
-static Lisp_Object Vauto_save_timeout;
-
-/* Total number of times read_char has returned. */
-int num_input_chars;
-
-/* Total number of times read_char has returned, outside of macros. */
-int num_nonmacro_input_chars;
-
-/* Auto-save automatically when this many characters have been typed
- since the last time. */
-
-static int auto_save_interval;
-
-/* Value of num_nonmacro_input_chars as of last auto save. */
-
-int last_auto_save;
-
-/* The command being executed by the command loop.
- Commands may set this, and the value set will be copied into
- current_kboard->Vlast_command instead of the actual command. */
-Lisp_Object this_command;
-
-/* The value of point when the last command was executed. */
-int last_point_position;
-
-/* The buffer that was current when the last command was started. */
-Lisp_Object last_point_position_buffer;
-
-/* The frame in which the last input event occurred, or Qmacro if the
- last event came from a macro. We use this to determine when to
- generate switch-frame events. This may be cleared by functions
- like Fselect_frame, to make sure that a switch-frame event is
- generated by the next character. */
-Lisp_Object internal_last_event_frame;
-
-/* A user-visible version of the above, intended to allow users to
- figure out where the last event came from, if the event doesn't
- carry that information itself (i.e. if it was a character). */
-Lisp_Object Vlast_event_frame;
-
-/* The timestamp of the last input event we received from the X server.
- X Windows wants this for selection ownership. */
-unsigned long last_event_timestamp;
-
-Lisp_Object Qself_insert_command;
-Lisp_Object Qforward_char;
-Lisp_Object Qbackward_char;
-Lisp_Object Qundefined;
-
-/* 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;
-
-/* Keymap mapping ASCII function key sequences onto their preferred forms. */
-extern Lisp_Object Vfunction_key_map;
-
-/* Another keymap that maps key sequences into key sequences.
- This one takes precedence over ordinary definitions. */
-extern Lisp_Object Vkey_translation_map;
-
-/* Non-nil means deactivate the mark at end of this command. */
-Lisp_Object Vdeactivate_mark;
-
-/* Menu bar specified in Lucid Emacs fashion. */
-
-Lisp_Object Vlucid_menu_bar_dirty_flag;
-Lisp_Object Qrecompute_lucid_menubar, Qactivate_menubar_hook;
-
-Lisp_Object Qecho_area_clear_hook;
-
-/* Hooks to run before and after each command. */
-Lisp_Object Qpre_command_hook, Vpre_command_hook;
-Lisp_Object Qpost_command_hook, Vpost_command_hook;
-Lisp_Object Qcommand_hook_internal, Vcommand_hook_internal;
-/* Hook run after a command if there's no more input soon. */
-Lisp_Object Qpost_command_idle_hook, Vpost_command_idle_hook;
-
-/* Delay time in microseconds before running post-command-idle-hook. */
-int post_command_idle_delay;
-
-/* List of deferred actions to be performed at a later time.
- The precise format isn't relevant here; we just check whether it is nil. */
-Lisp_Object Vdeferred_action_list;
-
-/* Function to call to handle deferred actions, when there are any. */
-Lisp_Object Vdeferred_action_function;
-Lisp_Object Qdeferred_action_function;
-
-/* File in which we write all commands we read. */
-FILE *dribble;
-
-/* Nonzero if input is available. */
-int input_pending;
-
-/* 1 if should obey 0200 bit in input chars as "Meta", 2 if should
- keep 0200 bit in input chars. 0 to ignore the 0200 bit. */
-
-int meta_key;
-
-extern char *pending_malloc_warning;
-
-/* Circular buffer for pre-read keyboard input. */
-static struct input_event kbd_buffer[KBD_BUFFER_SIZE];
-
-/* Vector to GCPRO the frames and windows mentioned in kbd_buffer.
-
- The interrupt-level event handlers will never enqueue an event on a
- frame which is not in Vframe_list, and once an event is dequeued,
- internal_last_event_frame or the event itself points to the frame.
- So that's all fine.
-
- But while the event is sitting in the queue, it's completely
- unprotected. Suppose the user types one command which will run for
- a while and then delete a frame, and then types another event at
- the frame that will be deleted, before the command gets around to
- it. Suppose there are no references to this frame elsewhere in
- Emacs, and a GC occurs before the second event is dequeued. Now we
- have an event referring to a freed frame, which will crash Emacs
- when it is dequeued.
-
- Similar things happen when an event on a scroll bar is enqueued; the
- window may be deleted while the event is in the queue.
-
- So, we use this vector to protect the frame_or_window field in the
- event queue. That way, they'll be dequeued as dead frames or
- windows, but still valid lisp objects.
-
- If kbd_buffer[i].kind != no_event, then
- (XVECTOR (kbd_buffer_frame_or_window)->contents[i]
- == kbd_buffer[i].frame_or_window. */
-static Lisp_Object kbd_buffer_frame_or_window;
-
-/* Pointer to next available character in kbd_buffer.
- If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty.
- This may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the the
- next available char is in kbd_buffer[0]. */
-static struct input_event *kbd_fetch_ptr;
-
-/* Pointer to next place to store character in kbd_buffer. This
- may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the next
- character should go in kbd_buffer[0]. */
-static volatile struct input_event *kbd_store_ptr;
-
-/* The above pair of variables forms a "queue empty" flag. When we
- enqueue a non-hook event, we increment kbd_store_ptr. When we
- dequeue a non-hook event, we increment kbd_fetch_ptr. We say that
- there is input available iff the two pointers are not equal.
-
- Why not just have a flag set and cleared by the enqueuing and
- dequeuing functions? Such a flag could be screwed up by interrupts
- at inopportune times. */
-
-/* If this flag is non-nil, we check mouse_moved to see when the
- mouse moves, and motion events will appear in the input stream.
- Otherwise, mouse motion is ignored. */
-static Lisp_Object do_mouse_tracking;
-
-/* Symbols to head events. */
-Lisp_Object Qmouse_movement;
-Lisp_Object Qscroll_bar_movement;
-Lisp_Object Qswitch_frame;
-Lisp_Object Qdelete_frame;
-Lisp_Object Qiconify_frame;
-Lisp_Object Qmake_frame_visible;
-
-/* Symbols to denote kinds of events. */
-Lisp_Object Qfunction_key;
-Lisp_Object Qmouse_click;
-Lisp_Object Qtimer_event;
-/* Lisp_Object Qmouse_movement; - also an event header */
-
-/* Properties of event headers. */
-Lisp_Object Qevent_kind;
-Lisp_Object Qevent_symbol_elements;
-
-Lisp_Object Qmenu_enable;
-
-/* An event header symbol HEAD may have a property named
- Qevent_symbol_element_mask, which is of the form (BASE MODIFIERS);
- BASE is the base, unmodified version of HEAD, and MODIFIERS is the
- mask of modifiers applied to it. If present, this is used to help
- speed up parse_modifiers. */
-Lisp_Object Qevent_symbol_element_mask;
-
-/* An unmodified event header BASE may have a property named
- Qmodifier_cache, which is an alist mapping modifier masks onto
- modified versions of BASE. If present, this helps speed up
- apply_modifiers. */
-Lisp_Object Qmodifier_cache;
-
-/* Symbols to use for parts of windows. */
-Lisp_Object Qmode_line;
-Lisp_Object Qvertical_line;
-Lisp_Object Qvertical_scroll_bar;
-Lisp_Object Qmenu_bar;
-
-extern Lisp_Object Qmenu_enable;
-
-Lisp_Object recursive_edit_unwind (), command_loop ();
-Lisp_Object Fthis_command_keys ();
-Lisp_Object Qextended_command_history;
-EMACS_TIME timer_check ();
-
-extern char *x_get_keysym_name ();
-
-static void record_menu_key ();
-
-Lisp_Object Qpolling_period;
-
-/* List of absolute timers. Appears in order of next scheduled event. */
-Lisp_Object Vtimer_list;
-
-/* List of idle time timers. Appears in order of next scheduled event. */
-Lisp_Object Vtimer_idle_list;
-
-/* Incremented whenever a timer is run. */
-int timers_run;
-
-extern Lisp_Object Vprint_level, Vprint_length;
-
-/* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt
- happens. */
-EMACS_TIME *input_available_clear_time;
-
-/* 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;
-
-/* 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
-
-/* If we support a window system, turn on the code to poll periodically
- to detect C-g. It isn't actually used when doing interrupt input. */
-#ifdef HAVE_WINDOW_SYSTEM
-#define POLL_FOR_INPUT
-#endif
-
-/* Global variable declarations. */
-
-/* Function for init_keyboard to call with no args (if nonzero). */
-void (*keyboard_init_hook) ();
-
-static int read_avail_input ();
-static void get_input_pending ();
-static int readable_events ();
-static Lisp_Object read_char_x_menu_prompt ();
-static Lisp_Object read_char_minibuf_menu_prompt ();
-static Lisp_Object make_lispy_event ();
-#ifdef HAVE_MOUSE
-static Lisp_Object make_lispy_movement ();
-#endif
-static Lisp_Object modify_event_symbol ();
-static Lisp_Object make_lispy_switch_frame ();
-static int parse_solitary_modifier ();
-
-/* > 0 if we are to echo keystrokes. */
-static int echo_keystrokes;
-
-/* Nonzero means don't try to suspend even if the operating system seems
- to support it. */
-static int cannot_suspend;
-
-#define min(a,b) ((a)<(b)?(a):(b))
-#define max(a,b) ((a)>(b)?(a):(b))
-
-/* 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 > ECHOBUFSIZE - 4)
- len = ECHOBUFSIZE - 4;
- bcopy (str, current_kboard->echobuf, len);
- current_kboard->echoptr = current_kboard->echobuf + len;
- *current_kboard->echoptr = '\0';
-
- current_kboard->echo_after_prompt = len;
-
- echo_now ();
-}
-
-/* Add C to the echo string, if echoing is going on.
- C can be a character, which is printed prettily ("M-C-x" and all that
- jazz), or a symbol, whose name is printed. */
-
-echo_char (c)
- Lisp_Object c;
-{
- extern char *push_key_description ();
-
- if (current_kboard->immediate_echo)
- {
- char *ptr = current_kboard->echoptr;
-
- if (ptr != current_kboard->echobuf)
- *ptr++ = ' ';
-
- /* If someone has passed us a composite event, use its head symbol. */
- c = EVENT_HEAD (c);
-
- if (INTEGERP (c))
- {
- if (ptr - current_kboard->echobuf > ECHOBUFSIZE - 6)
- return;
-
- ptr = push_key_description (XINT (c), ptr);
- }
- else if (SYMBOLP (c))
- {
- struct Lisp_String *name = XSYMBOL (c)->name;
- if ((ptr - current_kboard->echobuf) + name->size + 4 > ECHOBUFSIZE)
- return;
- bcopy (name->data, ptr, name->size);
- ptr += name->size;
- }
-
- if (current_kboard->echoptr == current_kboard->echobuf
- && help_char_p (c))
- {
- strcpy (ptr, " (Type ? for further options)");
- ptr += strlen (ptr);
- }
-
- *ptr = 0;
- current_kboard->echoptr = ptr;
-
- echo_now ();
- }
-}
-
-/* Temporarily add a dash to the end of the echo string if it's not
- empty, so that it serves as a mini-prompt for the very next character. */
-
-echo_dash ()
-{
- if (!current_kboard->immediate_echo
- && current_kboard->echoptr == current_kboard->echobuf)
- return;
- /* Do nothing if we just printed a prompt. */
- if (current_kboard->echo_after_prompt
- == current_kboard->echoptr - current_kboard->echobuf)
- return;
- /* Do nothing if not echoing at all. */
- if (current_kboard->echoptr == 0)
- return;
-
- /* Put a dash at the end of the buffer temporarily,
- but make it go away when the next character is added. */
- current_kboard->echoptr[0] = '-';
- current_kboard->echoptr[1] = 0;
-
- echo_now ();
-}
-
-/* Display the current echo string, and begin echoing if not already
- doing so. */
-
-echo_now ()
-{
- if (!current_kboard->immediate_echo)
- {
- int i;
- current_kboard->immediate_echo = 1;
-
- for (i = 0; i < this_command_key_count; i++)
- {
- Lisp_Object c;
- c = XVECTOR (this_command_keys)->contents[i];
- if (! (EVENT_HAS_PARAMETERS (c)
- && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
- echo_char (c);
- }
- echo_dash ();
- }
-
- echoing = 1;
- message1_nolog (current_kboard->echobuf);
- echoing = 0;
-
- if (waiting_for_input && !NILP (Vquit_flag))
- quit_throw_to_read_char ();
-}
-
-/* Turn off echoing, for the start of a new command. */
-
-cancel_echoing ()
-{
- current_kboard->immediate_echo = 0;
- current_kboard->echoptr = current_kboard->echobuf;
- current_kboard->echo_after_prompt = -1;
- ok_to_echo_at_next_pause = 0;
-}
-
-/* Return the length of the current echo string. */
-
-static int
-echo_length ()
-{
- return current_kboard->echoptr - current_kboard->echobuf;
-}
-
-/* Truncate the current echo message to its first LEN chars.
- This and echo_char get used by read_key_sequence when the user
- switches frames while entering a key sequence. */
-
-static void
-echo_truncate (len)
- int len;
-{
- current_kboard->echobuf[len] = '\0';
- current_kboard->echoptr = current_kboard->echobuf + len;
- truncate_echo_area (len);
-}
-
-
-/* Functions for manipulating this_command_keys. */
-static void
-add_command_key (key)
- Lisp_Object key;
-{
- int size = XVECTOR (this_command_keys)->size;
-
- /* If reset-this-command-length was called recently, obey it now.
- See the doc string of that function for an explanation of why. */
- if (before_command_restore_flag)
- {
- this_command_key_count = before_command_key_count_1;
- if (this_command_key_count < this_single_command_key_start)
- this_single_command_key_start = this_command_key_count;
- echo_truncate (before_command_echo_length_1);
- before_command_restore_flag = 0;
- }
-
- if (this_command_key_count >= size)
- {
- Lisp_Object new_keys;
-
- new_keys = Fmake_vector (make_number (size * 2), Qnil);
- bcopy (XVECTOR (this_command_keys)->contents,
- XVECTOR (new_keys)->contents,
- size * sizeof (Lisp_Object));
-
- this_command_keys = new_keys;
- }
-
- XVECTOR (this_command_keys)->contents[this_command_key_count++] = key;
-}
-
-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);
- /* Handle throw from read_minibuf when using minibuffer
- while it's active but we're in another window. */
- if (STRINGP (val))
- Fsignal (Qerror, Fcons (val, Qnil));
-
- return unbind_to (count, Qnil);
-}
-
-/* When an auto-save happens, record the "time", and don't do again soon. */
-
-record_auto_save ()
-{
- last_auto_save = num_nonmacro_input_chars;
-}
-
-/* Make an auto save happen as soon as possible at command level. */
-
-force_auto_save_soon ()
-{
- last_auto_save = - auto_save_interval - 1;
-
- record_asynch_buffer_change ();
-}
-
-DEFUN ("recursive-edit", Frecursive_edit, Srecursive_edit, 0, 0, "",
- "Invoke the editor command loop recursively.\n\
-To get out of the recursive edit, a command can do `(throw 'exit nil)';\n\
-that tells this function to return.\n\
-Alternately, `(throw 'exit t)' makes this function signal an error.\n\
-This function is called by the editor initialization to begin editing.")
- ()
-{
- int count = specpdl_ptr - specpdl;
- Lisp_Object val;
-
- command_loop_level++;
- update_mode_lines = 1;
-
- record_unwind_protect (recursive_edit_unwind,
- (command_loop_level
- && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
- ? Fcurrent_buffer ()
- : Qnil);
- recursive_edit_1 ();
- return unbind_to (count, Qnil);
-}
-
-Lisp_Object
-recursive_edit_unwind (buffer)
- Lisp_Object buffer;
-{
- if (!NILP (buffer))
- Fset_buffer (buffer);
-
- command_loop_level--;
- update_mode_lines = 1;
- return Qnil;
-}
-
-static void
-any_kboard_state ()
-{
-#ifdef MULTI_KBOARD
-#if 0 /* Theory: if there's anything in Vunread_command_events,
- it will right away be read by read_key_sequence,
- and then if we do switch KBOARDS, it will go into the side
- queue then. So we don't need to do anything special here -- rms. */
- if (CONSP (Vunread_command_events))
- {
- current_kboard->kbd_queue
- = nconc2 (Vunread_command_events, current_kboard->kbd_queue);
- current_kboard->kbd_queue_has_data = 1;
- }
- Vunread_command_events = Qnil;
-#endif
- single_kboard = 0;
-#endif
-}
-
-/* Switch to the single-kboard state, making current_kboard
- the only KBOARD from which further input is accepted. */
-
-void
-single_kboard_state ()
-{
-#ifdef MULTI_KBOARD
- single_kboard = 1;
-#endif
-}
-
-/* Maintain a stack of kboards, so other parts of Emacs
- can switch temporarily to the kboard of a given frame
- and then revert to the previous status. */
-
-struct kboard_stack
-{
- KBOARD *kboard;
- struct kboard_stack *next;
-};
-
-static struct kboard_stack *kboard_stack;
-
-void
-push_frame_kboard (f)
- FRAME_PTR f;
-{
-#ifdef MULTI_KBOARD
- struct kboard_stack *p
- = (struct kboard_stack *) xmalloc (sizeof (struct kboard_stack));
-
- p->next = kboard_stack;
- p->kboard = current_kboard;
- kboard_stack = p;
-
- current_kboard = FRAME_KBOARD (f);
-#endif
-}
-
-void
-pop_frame_kboard ()
-{
-#ifdef MULTI_KBOARD
- struct kboard_stack *p = kboard_stack;
- current_kboard = p->kboard;
- kboard_stack = p->next;
- xfree (p);
-#endif
-}
-
-/* Handle errors that are not handled at inner levels
- by printing an error message and returning to the editor command loop. */
-
-Lisp_Object
-cmd_error (data)
- Lisp_Object data;
-{
- Lisp_Object old_level, old_length;
- char macroerror[50];
-
- if (!NILP (executing_macro))
- {
- if (executing_macro_iterations == 1)
- sprintf (macroerror, "After 1 kbd macro iteration: ");
- else
- sprintf (macroerror, "After %d kbd macro iterations: ",
- executing_macro_iterations);
- }
- else
- *macroerror = 0;
-
- Vstandard_output = Qt;
- Vstandard_input = Qt;
- Vexecuting_macro = Qnil;
- executing_macro = Qnil;
- current_kboard->Vprefix_arg = Qnil;
- cancel_echoing ();
-
- /* Avoid unquittable loop if data contains a circular list. */
- old_level = Vprint_level;
- old_length = Vprint_length;
- XSETFASTINT (Vprint_level, 10);
- XSETFASTINT (Vprint_length, 10);
- cmd_error_internal (data, macroerror);
- Vprint_level = old_level;
- Vprint_length = old_length;
-
- Vquit_flag = Qnil;
-
- Vinhibit_quit = Qnil;
-#ifdef MULTI_KBOARD
- any_kboard_state ();
-#endif
-
- return make_number (0);
-}
-
-cmd_error_internal (data, context)
- Lisp_Object data;
- char *context;
-{
- Lisp_Object stream;
-
- Vquit_flag = Qnil;
- Vinhibit_quit = Qt;
- echo_area_glyphs = 0;
-
- /* If the window system or terminal frame hasn't been initialized
- yet, or we're not interactive, it's best to dump this message out
- to stderr and exit. */
- if (! FRAME_MESSAGE_BUF (selected_frame)
- || noninteractive)
- stream = Qexternal_debugging_output;
- else
- {
- Fdiscard_input ();
- bitch_at_user ();
- stream = Qt;
- }
-
- if (context != 0)
- write_string_1 (context, -1, stream);
-
- print_error_message (data, stream);
-
- /* If the window system or terminal frame hasn't been initialized
- yet, or we're in -batch mode, this error should cause Emacs to exit. */
- if (! FRAME_MESSAGE_BUF (selected_frame)
- || noninteractive)
- {
- Fterpri (stream);
- Fkill_emacs (make_number (-1));
- }
-}
-
-Lisp_Object command_loop_1 ();
-Lisp_Object command_loop_2 ();
-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 (!NILP (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 (!NILP (Vtop_level))
- internal_condition_case (top_level_2, Qerror, cmd_error);
- else if (!NILP (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 ();
-static int read_key_sequence ();
-void safe_run_hooks ();
-
-Lisp_Object
-command_loop_1 ()
-{
- Lisp_Object cmd, tem;
- int lose;
- int nonundocount;
- Lisp_Object keybuf[30];
- int i;
- int no_redisplay;
- int no_direct;
- int prev_modiff;
- struct buffer *prev_buffer;
-#ifdef MULTI_KBOARD
- int was_locked = single_kboard;
-#endif
-
- current_kboard->Vprefix_arg = Qnil;
- Vdeactivate_mark = Qnil;
- waiting_for_input = 0;
- cancel_echoing ();
-
- nonundocount = 0;
- no_redisplay = 0;
- this_command_key_count = 0;
- this_single_command_key_start = 0;
-
- /* Make sure this hook runs after commands that get errors and
- throw to top level. */
- /* Note that the value cell will never directly contain nil
- if the symbol is a local variable. */
- if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
- safe_run_hooks (Qpost_command_hook);
-
- if (!NILP (Vdeferred_action_list))
- call0 (Vdeferred_action_function);
-
- if (!NILP (Vpost_command_idle_hook) && !NILP (Vrun_hooks))
- {
- if (NILP (Vunread_command_events)
- && NILP (Vexecuting_macro)
- && !NILP (sit_for (0, post_command_idle_delay, 0, 1)))
- safe_run_hooks (Qpost_command_idle_hook);
- }
-
- /* Do this after running Vpost_command_hook, for consistency. */
- current_kboard->Vlast_command = this_command;
-
- while (1)
- {
- /* Make sure the 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;
-
- Vdeactivate_mark = Qnil;
-
- /* If minibuffer on and echo area in use,
- wait 2 sec and redraw minibuffer. */
-
- if (minibuf_level && echo_area_glyphs
- && EQ (minibuf_window, echo_area_window))
- {
- /* Bind inhibit-quit to t so that C-g gets read in
- rather than quitting back to the minibuffer. */
- int count = specpdl_ptr - specpdl;
- specbind (Qinhibit_quit, Qt);
-
- Fsit_for (make_number (2), Qnil, Qnil);
- /* Clear the echo area. */
- message2 (0);
- safe_run_hooks (Qecho_area_clear_hook);
-
- unbind_to (count, Qnil);
-
- /* If a C-g came in before, treat it as input now. */
- if (!NILP (Vquit_flag))
- {
- Vquit_flag = Qnil;
- Vunread_command_events = Fcons (make_number (quit_char), Qnil);
- }
- }
-
-#ifdef C_ALLOCA
- alloca (0); /* Cause a garbage collection now */
- /* Since we can free the most stuff here. */
-#endif /* C_ALLOCA */
-
-#if 0
- /* Select the frame that the last event came from. Usually,
- switch-frame events will take care of this, but if some lisp
- code swallows a switch-frame event, we'll fix things up here.
- Is this a good idea? */
- if (FRAMEP (internal_last_event_frame)
- && XFRAME (internal_last_event_frame) != selected_frame)
- Fselect_frame (internal_last_event_frame, Qnil);
-#endif
- /* If it has changed current-menubar from previous value,
- really recompute the menubar from the value. */
- if (! NILP (Vlucid_menu_bar_dirty_flag)
- && !NILP (Ffboundp (Qrecompute_lucid_menubar)))
- call0 (Qrecompute_lucid_menubar);
-
- before_command_key_count = this_command_key_count;
- before_command_echo_length = echo_length ();
-
- this_command = Qnil;
-
- /* Read next key sequence; i gets its length. */
- i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
- Qnil, 0, 1);
-
- /* A filter may have run while we were reading the input. */
- if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
- set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
-
- ++num_input_keys;
-
- /* 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. */
- /* -1 means read_key_sequence got a menu that was rejected.
- Just loop around and read another command. */
- if (i == -1)
- {
- cancel_echoing ();
- this_command_key_count = 0;
- this_single_command_key_start = 0;
- goto finalize;
- }
-
- last_command_char = keybuf[i - 1];
-
- /* If the previous command tried to force a specific window-start,
- forget about that, in case this command moves point far away
- from that position. But also throw away beg_unchanged and
- end_unchanged information in that case, so that redisplay will
- update the whole window properly. */
- if (!NILP (XWINDOW (selected_window)->force_start))
- {
- XWINDOW (selected_window)->force_start = Qnil;
- beg_unchanged = end_unchanged = 0;
- }
-
- cmd = read_key_sequence_cmd;
- if (!NILP (Vexecuting_macro))
- {
- if (!NILP (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.
- (actually, there's currently no way to prevent the redisplay,
- and no_redisplay is ignored.
- Perhaps someday we will really implement it.) */
- no_redisplay = 0;
-
- prev_buffer = current_buffer;
- prev_modiff = MODIFF;
- last_point_position = PT;
- XSETBUFFER (last_point_position_buffer, prev_buffer);
-
- /* Execute the command. */
-
- this_command = cmd;
- /* Note that the value cell will never directly contain nil
- if the symbol is a local variable. */
- if (!NILP (Vpre_command_hook) && !NILP (Vrun_hooks))
- safe_run_hooks (Qpre_command_hook);
-
- if (NILP (this_command))
- {
- /* nil means key is undefined. */
- bitch_at_user ();
- current_kboard->defining_kbd_macro = Qnil;
- update_mode_lines = 1;
- current_kboard->Vprefix_arg = Qnil;
- }
- else
- {
- if (NILP (current_kboard->Vprefix_arg) && ! no_direct)
- {
- /* Recognize some common commands in common situations and
- do them directly. */
- if (EQ (this_command, Qforward_char) && PT < ZV)
- {
- struct Lisp_Char_Table *dp
- = window_display_table (XWINDOW (selected_window));
- lose = FETCH_CHAR (PT);
- SET_PT (PT + 1);
- if ((dp
- ? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
- ? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1
- : (NILP (DISP_CHAR_VECTOR (dp, lose))
- && (lose >= 0x20 && lose < 0x7f)))
- : (lose >= 0x20 && lose < 0x7f))
- && (XFASTINT (XWINDOW (selected_window)->last_modified)
- >= MODIFF)
- && (XFASTINT (XWINDOW (selected_window)->last_overlay_modified)
- >= OVERLAY_MODIFF)
- && (XFASTINT (XWINDOW (selected_window)->last_point)
- == PT - 1)
- && !windows_or_buffers_changed
- && EQ (current_buffer->selective_display, Qnil)
- && !detect_input_pending ()
- && NILP (XWINDOW (selected_window)->column_number_displayed)
- && NILP (Vexecuting_macro))
- no_redisplay = direct_output_forward_char (1);
- goto directly_done;
- }
- else if (EQ (this_command, Qbackward_char) && PT > BEGV)
- {
- struct Lisp_Char_Table *dp
- = window_display_table (XWINDOW (selected_window));
- SET_PT (PT - 1);
- lose = FETCH_CHAR (PT);
- if ((dp
- ? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
- ? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1
- : (NILP (DISP_CHAR_VECTOR (dp, lose))
- && (lose >= 0x20 && lose < 0x7f)))
- : (lose >= 0x20 && lose < 0x7f))
- && (XFASTINT (XWINDOW (selected_window)->last_modified)
- >= MODIFF)
- && (XFASTINT (XWINDOW (selected_window)->last_overlay_modified)
- >= OVERLAY_MODIFF)
- && (XFASTINT (XWINDOW (selected_window)->last_point)
- == PT + 1)
- && !windows_or_buffers_changed
- && EQ (current_buffer->selective_display, Qnil)
- && !detect_input_pending ()
- && NILP (XWINDOW (selected_window)->column_number_displayed)
- && NILP (Vexecuting_macro))
- no_redisplay = direct_output_forward_char (-1);
- goto directly_done;
- }
- else if (EQ (this_command, Qself_insert_command)
- /* Try this optimization only on ascii keystrokes. */
- && INTEGERP (last_command_char))
- {
- unsigned char c = XINT (last_command_char);
- int value;
-
- if (NILP (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_overlay_modified)
- < OVERLAY_MODIFF)
- || (XFASTINT (XWINDOW (selected_window)->last_point)
- != PT)
- || MODIFF <= SAVE_MODIFF
- || windows_or_buffers_changed
- || !EQ (current_buffer->selective_display, Qnil)
- || detect_input_pending ()
- || !NILP (XWINDOW (selected_window)->column_number_displayed)
- || !NILP (Vexecuting_macro));
- value = internal_self_insert (c, 0);
- if (value)
- lose = 1;
- if (value == 2)
- nonundocount = 0;
-
- if (!lose
- && (PT == ZV || FETCH_CHAR (PT) == '\n'))
- {
- struct Lisp_Char_Table *dp
- = window_display_table (XWINDOW (selected_window));
- int lose = c;
-
- if (dp)
- {
- Lisp_Object obj;
-
- obj = DISP_CHAR_VECTOR (dp, lose);
- if (NILP (obj))
- {
- /* Do it only for char codes
- that by default display as themselves. */
- if (lose >= 0x20 && lose <= 0x7e)
- no_redisplay = direct_output_for_insert (lose);
- }
- else if (VECTORP (obj)
- && XVECTOR (obj)->size == 1
- && (obj = XVECTOR (obj)->contents[0],
- INTEGERP (obj))
- /* Insist face not specified in glyph. */
- && (XINT (obj) & ((-1) << 8)) == 0)
- no_redisplay
- = direct_output_for_insert (XINT (obj));
- }
- else
- {
- if (lose >= 0x20 && lose <= 0x7e)
- no_redisplay = direct_output_for_insert (lose);
- }
- }
- goto directly_done;
- }
- }
-
- /* Here for a command that isn't executed directly */
-
- nonundocount = 0;
- if (NILP (current_kboard->Vprefix_arg))
- Fundo_boundary ();
- Fcommand_execute (this_command, Qnil, Qnil, Qnil);
-
- }
- directly_done: ;
-
- /* If there is a prefix argument,
- 1) We don't want Vlast_command to be ``universal-argument''
- (that would be dumb), so don't set Vlast_command,
- 2) we want to leave echoing on so that the prefix will be
- echoed as part of this key sequence, so don't call
- cancel_echoing, and
- 3) we want to leave this_command_key_count non-zero, so that
- read_char will realize that it is re-reading a character, and
- not echo it a second time.
-
- If the command didn't actually create a prefix arg,
- but is merely a frame event that is transparent to prefix args,
- then the above doesn't apply. */
- if (NILP (current_kboard->Vprefix_arg) || CONSP (last_command_char))
- {
- current_kboard->Vlast_command = this_command;
- cancel_echoing ();
- this_command_key_count = 0;
- this_single_command_key_start = 0;
- }
-
- /* Note that the value cell will never directly contain nil
- if the symbol is a local variable. */
- if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
- safe_run_hooks (Qpost_command_hook);
-
- if (!NILP (Vdeferred_action_list))
- safe_run_hooks (Qdeferred_action_function);
-
- if (!NILP (Vpost_command_idle_hook) && !NILP (Vrun_hooks))
- {
- if (NILP (Vunread_command_events)
- && NILP (Vexecuting_macro)
- && !NILP (sit_for (0, post_command_idle_delay, 0, 1)))
- safe_run_hooks (Qpost_command_idle_hook);
- }
-
- if (!NILP (current_buffer->mark_active) && !NILP (Vrun_hooks))
- {
- if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode))
- {
- current_buffer->mark_active = Qnil;
- call1 (Vrun_hooks, intern ("deactivate-mark-hook"));
- }
- else if (current_buffer != prev_buffer || MODIFF != prev_modiff)
- call1 (Vrun_hooks, intern ("activate-mark-hook"));
- }
-
- finalize:
- /* Install chars successfully executed in kbd macro. */
-
- if (!NILP (current_kboard->defining_kbd_macro)
- && NILP (current_kboard->Vprefix_arg))
- finalize_kbd_macro_chars ();
-
-#ifdef MULTI_KBOARD
- if (!was_locked)
- any_kboard_state ();
-#endif
- }
-}
-
-/* Subroutine for safe_run_hooks: run the hook HOOK. */
-
-static Lisp_Object
-safe_run_hooks_1 (hook)
- Lisp_Object hook;
-{
- return call1 (Vrun_hooks, Vinhibit_quit);
-}
-
-/* Subroutine for safe_run_hooks: handle an error by clearing out the hook. */
-
-static Lisp_Object
-safe_run_hooks_error (data)
- Lisp_Object data;
-{
- Fset (Vinhibit_quit, Qnil);
-}
-
-/* If we get an error while running the hook, cause the hook variable
- to be nil. Also inhibit quits, so that C-g won't cause the hook
- to mysteriously evaporate. */
-
-void
-safe_run_hooks (hook)
- Lisp_Object hook;
-{
- Lisp_Object value;
- int count = specpdl_ptr - specpdl;
- specbind (Qinhibit_quit, hook);
-
- internal_condition_case (safe_run_hooks_1, Qt, safe_run_hooks_error);
-
- unbind_to (count, Qnil);
-}
-
-/* Number of seconds between polling for input. */
-int polling_period;
-
-/* Nonzero means polling for input is temporarily suppressed. */
-int poll_suppress_count;
-
-/* Nonzero if polling_for_input is actually being used. */
-int polling_for_input;
-
-#ifdef POLL_FOR_INPUT
-
-/* Handle an alarm once each second and read pending input
- so as to handle a C-g if it comces in. */
-
-SIGTYPE
-input_poll_signal (signalnum) /* If we don't have an argument, */
- int signalnum; /* some compilers complain in signal calls. */
-{
- /* This causes the call to start_polling at the end
- to do its job. It also arranges for a quit or error
- from within read_avail_input to resume polling. */
- poll_suppress_count++;
- if (interrupt_input_blocked == 0
- && !waiting_for_input)
- read_avail_input (0);
- /* Turn on the SIGALRM handler and request another alarm. */
- start_polling ();
-}
-
-#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 && !interrupt_input)
- {
- poll_suppress_count--;
- if (poll_suppress_count == 0)
- {
- signal (SIGALRM, input_poll_signal);
- polling_for_input = 1;
- alarm (polling_period);
- }
- }
-#endif
-}
-
-/* Nonzero if we are using polling to handle input asynchronously. */
-
-int
-input_polling_used ()
-{
-#ifdef POLL_FOR_INPUT
- return read_socket_hook && !interrupt_input;
-#else
- return 0;
-#endif
-}
-
-/* Turn off polling. */
-
-stop_polling ()
-{
-#ifdef POLL_FOR_INPUT
- if (read_socket_hook && !interrupt_input)
- {
- if (poll_suppress_count == 0)
- {
- polling_for_input = 0;
- alarm (0);
- }
- poll_suppress_count++;
- }
-#endif
-}
-
-/* Set the value of poll_suppress_count to COUNT
- and start or stop polling accordingly. */
-
-void
-set_poll_suppress_count (count)
- int count;
-{
-#ifdef POLL_FOR_INPUT
- if (count == 0 && poll_suppress_count != 0)
- {
- poll_suppress_count = 1;
- start_polling ();
- }
- else if (count != 0 && poll_suppress_count == 0)
- {
- stop_polling ();
- }
- poll_suppress_count = count;
-#endif
-}
-
-/* Bind polling_period to a value at least N.
- But don't decrease it. */
-
-bind_polling_period (n)
- int n;
-{
-#ifdef POLL_FOR_INPUT
- int new = polling_period;
-
- if (n > new)
- new = n;
-
- stop_polling ();
- specbind (Qpolling_period, make_number (new));
- /* Start a new alarm with the new period. */
- start_polling ();
-#endif
-}
-
-/* Apply the control modifier to CHARACTER. */
-
-int
-make_ctrl_char (c)
- int c;
-{
- /* Save the upper bits here. */
- int upper = c & ~0177;
-
- c &= 0177;
-
- /* Everything in the columns containing the upper-case letters
- denotes a control character. */
- if (c >= 0100 && c < 0140)
- {
- int oc = c;
- c &= ~0140;
- /* Set the shift modifier for a control char
- made from a shifted letter. But only for letters! */
- if (oc >= 'A' && oc <= 'Z')
- c |= shift_modifier;
- }
-
- /* The lower-case letters denote control characters too. */
- else if (c >= 'a' && c <= 'z')
- c &= ~0140;
-
- /* Include the bits for control and shift
- only if the basic ASCII code can't indicate them. */
- else if (c >= ' ')
- c |= ctrl_modifier;
-
- /* Replace the high bits. */
- c |= (upper & ~ctrl_modifier);
-
- return c;
-}
-
-
-
-/* Input of single characters from keyboard */
-
-Lisp_Object print_help ();
-static Lisp_Object kbd_buffer_get_event ();
-static void record_char ();
-
-#ifdef MULTI_KBOARD
-static jmp_buf wrong_kboard_jmpbuf;
-#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. */
-
-/* The arguments MAPS and NMAPS are for menu prompting.
- MAPS is an array of keymaps; NMAPS is the length of MAPS.
-
- PREV_EVENT is the previous input event, or nil if we are reading
- the first event of a key sequence.
-
- If USED_MOUSE_MENU is non-null, then we set *USED_MOUSE_MENU to 1
- if we used a mouse menu to read the input, or zero otherwise. If
- USED_MOUSE_MENU is null, we don't dereference it.
-
- Value is t if we showed a menu and the user rejected it. */
-
-Lisp_Object
-read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
- int commandflag;
- int nmaps;
- Lisp_Object *maps;
- Lisp_Object prev_event;
- int *used_mouse_menu;
-{
- register Lisp_Object c;
- int count;
- jmp_buf local_getcjmp;
- jmp_buf save_jump;
- int key_already_recorded = 0;
- Lisp_Object tem, save;
- Lisp_Object also_record;
- also_record = Qnil;
-
- before_command_key_count = this_command_key_count;
- before_command_echo_length = echo_length ();
-
- retry:
-
- if (CONSP (Vunread_command_events))
- {
- c = XCONS (Vunread_command_events)->car;
- Vunread_command_events = XCONS (Vunread_command_events)->cdr;
-
- /* Undo what read_char_x_menu_prompt did when it unread
- additional keys returned by Fx_popup_menu. */
- if (CONSP (c)
- && (SYMBOLP (XCONS (c)->car) || INTEGERP (XCONS (c)->car))
- && NILP (XCONS (c)->cdr))
- c = XCONS (c)->car;
-
- if (this_command_key_count == 0)
- goto reread_first;
- else
- goto reread;
- }
-
- if (unread_command_char != -1)
- {
- XSETINT (c, unread_command_char);
- unread_command_char = -1;
-
- if (this_command_key_count == 0)
- goto reread_first;
- else
- goto reread;
- }
-
- /* If there is no function key translated before
- reset-this-command-lengths takes effect, forget about it. */
- before_command_restore_flag = 0;
-
- if (!NILP (Vexecuting_macro))
- {
- /* We set this to Qmacro; since that's not a frame, nobody will
- try to switch frames on us, and the selected window will
- remain unchanged.
-
- Since this event came from a macro, it would be misleading to
- leave internal_last_event_frame set to wherever the last
- real event came from. Normally, a switch-frame event selects
- internal_last_event_frame after each command is read, but
- events read from a macro should never cause a new frame to be
- selected. */
- Vlast_event_frame = internal_last_event_frame = Qmacro;
-
- /* Exit the macro if we are at the end.
- Also, some things replace the macro with t
- to force an early exit. */
- if (EQ (Vexecuting_macro, Qt)
- || executing_macro_index >= XFASTINT (Flength (Vexecuting_macro)))
- {
- XSETINT (c, -1);
- return c;
- }
-
- c = Faref (Vexecuting_macro, make_number (executing_macro_index));
- if (STRINGP (Vexecuting_macro)
- && (XINT (c) & 0x80))
- XSETFASTINT (c, CHAR_META | (XINT (c) & ~0x80));
-
- executing_macro_index++;
-
- goto from_macro;
- }
-
- if (!NILP (unread_switch_frame))
- {
- c = unread_switch_frame;
- unread_switch_frame = Qnil;
-
- /* This event should make it into this_command_keys, and get echoed
- again, so we go to reread_first, rather than reread. */
- goto reread_first;
- }
-
- if (commandflag >= 0 && !input_pending
- && !detect_input_pending_run_timers (0))
- redisplay ();
-
- /* Message turns off echoing unless more keystrokes turn it on again. */
- if (echo_area_glyphs && *echo_area_glyphs
- && echo_area_glyphs != current_kboard->echobuf
- && ok_to_echo_at_next_pause != echo_area_glyphs)
- cancel_echoing ();
- else
- /* If already echoing, continue. */
- echo_dash ();
-
- /* Try reading a character via menu prompting in the minibuf.
- Try this before the sit-for, because the sit-for
- would do the wrong thing if we are supposed to do
- menu prompting. If EVENT_HAS_PARAMETERS then we are reading
- after a mouse event so don't try a minibuf menu. */
- c = Qnil;
- if (nmaps > 0 && INTERACTIVE
- && !NILP (prev_event) && ! EVENT_HAS_PARAMETERS (prev_event)
- /* Don't bring up a menu if we already have another event. */
- && NILP (Vunread_command_events)
- && unread_command_char < 0
- && !detect_input_pending_run_timers (0))
- {
- c = read_char_minibuf_menu_prompt (commandflag, nmaps, maps);
- if (! NILP (c))
- {
- key_already_recorded = 1;
- goto non_reread_1;
- }
- }
-
- /* Make a longjmp point for quits to use, but don't alter getcjmp just yet.
- We will do that below, temporarily for short sections of code,
- when appropriate. local_getcjmp must be in effect
- around any call to sit_for or kbd_buffer_get_event;
- it *must not* be in effect when we call redisplay. */
-
- if (_setjmp (local_getcjmp))
- {
- XSETINT (c, quit_char);
- XSETFRAME (internal_last_event_frame, selected_frame);
- Vlast_event_frame = internal_last_event_frame;
- /* If we report the quit char as an event,
- don't do so more than once. */
- if (!NILP (Vinhibit_quit))
- Vquit_flag = Qnil;
-
-#ifdef MULTI_KBOARD
- {
- KBOARD *kb = FRAME_KBOARD (selected_frame);
- if (kb != current_kboard)
- {
- Lisp_Object *tailp = &kb->kbd_queue;
- /* We shouldn't get here if we were in single-kboard mode! */
- if (single_kboard)
- abort ();
- while (CONSP (*tailp))
- tailp = &XCONS (*tailp)->cdr;
- if (!NILP (*tailp))
- abort ();
- *tailp = Fcons (c, Qnil);
- kb->kbd_queue_has_data = 1;
- current_kboard = kb;
- longjmp (wrong_kboard_jmpbuf, 1);
- }
- }
-#endif
- goto non_reread;
- }
-
- timer_start_idle ();
-
- /* If in middle of key sequence and minibuffer not active,
- start echoing if enough time elapses. */
-
- if (minibuf_level == 0 && !current_kboard->immediate_echo
- && this_command_key_count > 0
- && ! noninteractive
- && echo_keystrokes > 0
- && (echo_area_glyphs == 0 || *echo_area_glyphs == 0
- || ok_to_echo_at_next_pause == echo_area_glyphs))
- {
- Lisp_Object tem0;
-
- /* After a mouse event, start echoing right away.
- This is because we are probably about to display a menu,
- and we don't want to delay before doing so. */
- if (EVENT_HAS_PARAMETERS (prev_event))
- echo_now ();
- else
- {
- save_getcjmp (save_jump);
- restore_getcjmp (local_getcjmp);
- tem0 = sit_for (echo_keystrokes, 0, 1, 1);
- restore_getcjmp (save_jump);
- if (EQ (tem0, Qt))
- echo_now ();
- }
- }
-
- /* Maybe auto save due to number of keystrokes. */
-
- if (commandflag != 0
- && auto_save_interval > 0
- && num_nonmacro_input_chars - last_auto_save > max (auto_save_interval, 20)
- && !detect_input_pending_run_timers (0))
- {
- Fdo_auto_save (Qnil, Qnil);
- /* Hooks can actually change some buffers in auto save. */
- redisplay ();
- }
-
- /* Try reading using an X menu.
- This is never confused with reading using the minibuf
- because the recursive call of read_char in read_char_minibuf_menu_prompt
- does not pass on any keymaps. */
-
- if (nmaps > 0 && INTERACTIVE
- && !NILP (prev_event)
- && EVENT_HAS_PARAMETERS (prev_event)
- && !EQ (XCONS (prev_event)->car, Qmenu_bar)
- /* Don't bring up a menu if we already have another event. */
- && NILP (Vunread_command_events)
- && unread_command_char < 0)
- {
- c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu);
-
- /* Now that we have read an event, Emacs is not idle. */
- timer_stop_idle ();
-
- return c;
- }
-
- /* Maybe autosave and/or garbage collect due to idleness. */
-
- if (INTERACTIVE && NILP (c))
- {
- int delay_level, buffer_size;
-
- /* Slow down auto saves logarithmically in size of current buffer,
- and garbage collect while we're at it. */
- if (! MINI_WINDOW_P (XWINDOW (selected_window)))
- last_non_minibuf_size = Z - BEG;
- buffer_size = (last_non_minibuf_size >> 8) + 1;
- delay_level = 0;
- while (buffer_size > 64)
- delay_level++, buffer_size -= buffer_size >> 2;
- if (delay_level < 4) delay_level = 4;
- /* delay_level is 4 for files under around 50k, 7 at 100k,
- 9 at 200k, 11 at 300k, and 12 at 500k. It is 15 at 1 meg. */
-
- /* Auto save if enough time goes by without input. */
- if (commandflag != 0
- && num_nonmacro_input_chars > last_auto_save
- && INTEGERP (Vauto_save_timeout)
- && XINT (Vauto_save_timeout) > 0)
- {
- Lisp_Object tem0;
-
- save_getcjmp (save_jump);
- restore_getcjmp (local_getcjmp);
- tem0 = sit_for (delay_level * XFASTINT (Vauto_save_timeout) / 4,
- 0, 1, 1);
- restore_getcjmp (save_jump);
-
- if (EQ (tem0, Qt))
- {
- Fdo_auto_save (Qnil, Qnil);
-
- /* If we have auto-saved and there is still no input
- available, garbage collect if there has been enough
- consing going on to make it worthwhile. */
- if (!detect_input_pending_run_timers (0)
- && consing_since_gc > gc_cons_threshold / 2)
- Fgarbage_collect ();
-
- redisplay ();
- }
- }
- }
-
- /* Read something from current KBOARD's side queue, if possible. */
-
- if (NILP (c))
- {
- if (current_kboard->kbd_queue_has_data)
- {
- if (!CONSP (current_kboard->kbd_queue))
- abort ();
- c = XCONS (current_kboard->kbd_queue)->car;
- current_kboard->kbd_queue
- = XCONS (current_kboard->kbd_queue)->cdr;
- if (NILP (current_kboard->kbd_queue))
- current_kboard->kbd_queue_has_data = 0;
- input_pending = readable_events (0);
- if (EVENT_HAS_PARAMETERS (c)
- && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qswitch_frame))
- internal_last_event_frame = XCONS (XCONS (c)->cdr)->car;
- Vlast_event_frame = internal_last_event_frame;
- }
- }
-
-#ifdef MULTI_KBOARD
- /* If current_kboard's side queue is empty check the other kboards.
- If one of them has data that we have not yet seen here,
- switch to it and process the data waiting for it.
-
- Note: if the events queued up for another kboard
- have already been seen here, and therefore are not a complete command,
- the kbd_queue_has_data field is 0, so we skip that kboard here.
- That's to avoid an infinite loop switching between kboards here. */
- if (NILP (c) && !single_kboard)
- {
- KBOARD *kb;
- for (kb = all_kboards; kb; kb = kb->next_kboard)
- if (kb->kbd_queue_has_data)
- {
- current_kboard = kb;
- longjmp (wrong_kboard_jmpbuf, 1);
- }
- }
-#endif
-
- wrong_kboard:
-
- stop_polling ();
-
- /* Finally, we read from the main queue,
- and if that gives us something we can't use yet, we put it on the
- appropriate side queue and try again. */
-
- if (NILP (c))
- {
- KBOARD *kb;
-
- /* Actually read a character, waiting if necessary. */
- save_getcjmp (save_jump);
- restore_getcjmp (local_getcjmp);
- c = kbd_buffer_get_event (&kb, used_mouse_menu);
- restore_getcjmp (save_jump);
-
-#ifdef MULTI_KBOARD
- if (! NILP (c) && (kb != current_kboard))
- {
- Lisp_Object *tailp = &kb->kbd_queue;
- while (CONSP (*tailp))
- tailp = &XCONS (*tailp)->cdr;
- if (!NILP (*tailp))
- abort ();
- *tailp = Fcons (c, Qnil);
- kb->kbd_queue_has_data = 1;
- c = Qnil;
- if (single_kboard)
- goto wrong_kboard;
- current_kboard = kb;
- longjmp (wrong_kboard_jmpbuf, 1);
- }
-#endif
- }
-
- /* Terminate Emacs in batch mode if at eof. */
- if (noninteractive && INTEGERP (c) && XINT (c) < 0)
- Fkill_emacs (make_number (1));
-
- if (INTEGERP (c))
- {
- /* Add in any extra modifiers, where appropriate. */
- if ((extra_keyboard_modifiers & CHAR_CTL)
- || ((extra_keyboard_modifiers & 0177) < ' '
- && (extra_keyboard_modifiers & 0177) != 0))
- XSETINT (c, make_ctrl_char (XINT (c)));
-
- /* Transfer any other modifier bits directly from
- extra_keyboard_modifiers to c. Ignore the actual character code
- in the low 16 bits of extra_keyboard_modifiers. */
- XSETINT (c, XINT (c) | (extra_keyboard_modifiers & ~0xff7f & ~CHAR_CTL));
- }
-
- non_reread:
-
- /* Now that we have read an event, Emacs is not idle--
- unless the event was a timer event (not used now). */
- if (! (CONSP (c) && EQ (XCONS (c)->car, Qtimer_event)))
- timer_stop_idle ();
-
- start_polling ();
-
- if (NILP (c))
- {
- if (commandflag >= 0
- && !input_pending && !detect_input_pending_run_timers (0))
- redisplay ();
-
- goto wrong_kboard;
- }
-
- non_reread_1:
-
- /* Buffer switch events are only for internal wakeups
- so don't show them to the user. */
- if (BUFFERP (c))
- return c;
-
- if (key_already_recorded)
- return c;
-
- /* Process special events within read_char
- and loop around to read another event. */
- save = Vquit_flag;
- Vquit_flag = Qnil;
- tem = get_keyelt (access_keymap (get_keymap_1 (Vspecial_event_map, 0, 0),
- c, 0, 0), 1);
- Vquit_flag = save;
-
- if (!NILP (tem))
- {
- int was_locked = single_kboard;
-
- last_input_char = c;
- Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt);
-
- /* Resume allowing input from any kboard, if that was true before. */
- if (!was_locked)
- any_kboard_state ();
-
- goto retry;
- }
-
- /* Wipe the echo area. */
- if (echo_area_glyphs)
- safe_run_hooks (Qecho_area_clear_hook);
- echo_area_glyphs = 0;
-
- /* Handle things that only apply to characters. */
- if (INTEGERP (c))
- {
- /* If kbd_buffer_get_event gave us an EOF, return that. */
- if (XINT (c) == -1)
- return c;
-
- if (STRINGP (Vkeyboard_translate_table)
- && XSTRING (Vkeyboard_translate_table)->size > (unsigned) XFASTINT (c))
- XSETINT (c, XSTRING (Vkeyboard_translate_table)->data[XFASTINT (c)]);
- else if ((VECTORP (Vkeyboard_translate_table)
- && XVECTOR (Vkeyboard_translate_table)->size > (unsigned) XFASTINT (c))
- || (CHAR_TABLE_P (Vkeyboard_translate_table)
- && CHAR_TABLE_ORDINARY_SLOTS > (unsigned) XFASTINT (c)))
- {
- Lisp_Object d;
- d = Faref (Vkeyboard_translate_table, c);
- /* nil in keyboard-translate-table means no translation. */
- if (!NILP (d))
- c = d;
- }
- }
-
- /* If this event is a mouse click in the menu bar,
- return just menu-bar for now. Modify the mouse click event
- so we won't do this twice, then queue it up. */
- if (EVENT_HAS_PARAMETERS (c)
- && CONSP (XCONS (c)->cdr)
- && CONSP (EVENT_START (c))
- && CONSP (XCONS (EVENT_START (c))->cdr))
- {
- Lisp_Object posn;
-
- posn = POSN_BUFFER_POSN (EVENT_START (c));
- /* Handle menu-bar events:
- insert the dummy prefix event `menu-bar'. */
- if (EQ (posn, Qmenu_bar))
- {
- /* Change menu-bar to (menu-bar) as the event "position". */
- POSN_BUFFER_POSN (EVENT_START (c)) = Fcons (posn, Qnil);
-
- also_record = c;
- Vunread_command_events = Fcons (c, Vunread_command_events);
- c = posn;
- }
- }
-
- record_char (c);
- if (! NILP (also_record))
- record_char (also_record);
-
- from_macro:
- reread_first:
- before_command_key_count = this_command_key_count;
- before_command_echo_length = echo_length ();
-
- /* Don't echo mouse motion events. */
- if (echo_keystrokes
- && ! (EVENT_HAS_PARAMETERS (c)
- && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
- {
- echo_char (c);
- if (! NILP (also_record))
- echo_char (also_record);
- /* Once we reread a character, echoing can happen
- the next time we pause to read a new one. */
- ok_to_echo_at_next_pause = echo_area_glyphs;
- }
-
- /* Record this character as part of the current key. */
- add_command_key (c);
- if (! NILP (also_record))
- add_command_key (also_record);
-
- /* Re-reading in the middle of a command */
- reread:
- last_input_char = c;
- num_input_chars++;
-
- /* Process the help character specially if enabled */
- if (!NILP (Vhelp_form) && help_char_p (c))
- {
- Lisp_Object tem0;
- count = specpdl_ptr - specpdl;
-
- record_unwind_protect (Fset_window_configuration,
- Fcurrent_window_configuration (Qnil));
-
- tem0 = Feval (Vhelp_form);
- if (STRINGP (tem0))
- internal_with_output_to_temp_buffer ("*Help*", print_help, tem0);
-
- cancel_echoing ();
- do
- c = read_char (0, 0, 0, Qnil, 0);
- while (BUFFERP (c));
- /* Remove the help from the frame */
- unbind_to (count, Qnil);
-
- redisplay ();
- if (EQ (c, make_number (040)))
- {
- cancel_echoing ();
- do
- c = read_char (0, 0, 0, Qnil, 0);
- while (BUFFERP (c));
- }
- }
-
- return c;
-}
-
-/* Record a key that came from a mouse menu.
- Record it for echoing, for this-command-keys, and so on. */
-
-static void
-record_menu_key (c)
- Lisp_Object c;
-{
- /* Wipe the echo area. */
- echo_area_glyphs = 0;
-
- record_char (c);
-
- before_command_key_count = this_command_key_count;
- before_command_echo_length = echo_length ();
-
- /* Don't echo mouse motion events. */
- if (echo_keystrokes)
- {
- echo_char (c);
-
- /* Once we reread a character, echoing can happen
- the next time we pause to read a new one. */
- ok_to_echo_at_next_pause = 0;
- }
-
- /* Record this character as part of the current key. */
- add_command_key (c);
-
- /* Re-reading in the middle of a command */
- last_input_char = c;
- num_input_chars++;
-}
-
-/* Return 1 if should recognize C as "the help character". */
-
-int
-help_char_p (c)
- Lisp_Object c;
-{
- Lisp_Object tail;
-
- if (EQ (c, Vhelp_char))
- return 1;
- for (tail = Vhelp_event_list; CONSP (tail); tail = XCONS (tail)->cdr)
- if (EQ (c, XCONS (tail)->car))
- return 1;
- return 0;
-}
-
-/* Record the input event C in various ways. */
-
-static void
-record_char (c)
- Lisp_Object c;
-{
- total_keys++;
- XVECTOR (recent_keys)->contents[recent_keys_index] = c;
- if (++recent_keys_index >= NUM_RECENT_KEYS)
- recent_keys_index = 0;
-
- /* Write c to the dribble file. If c is a lispy event, write
- the event's symbol to the dribble file, in <brackets>. Bleaugh.
- If you, dear reader, have a better idea, you've got the source. :-) */
- if (dribble)
- {
- if (INTEGERP (c))
- {
- if (XUINT (c) < 0x100)
- putc (XINT (c), dribble);
- else
- fprintf (dribble, " 0x%x", (int) XUINT (c));
- }
- else
- {
- Lisp_Object dribblee;
-
- /* If it's a structured event, take the event header. */
- dribblee = EVENT_HEAD (c);
-
- if (SYMBOLP (dribblee))
- {
- putc ('<', dribble);
- fwrite (XSYMBOL (dribblee)->name->data, sizeof (char),
- XSYMBOL (dribblee)->name->size,
- dribble);
- putc ('>', dribble);
- }
- }
-
- fflush (dribble);
- }
-
- store_kbd_macro_char (c);
-
- num_nonmacro_input_chars++;
-}
-
-Lisp_Object
-print_help (object)
- Lisp_Object object;
-{
- struct buffer *old = current_buffer;
- Fprinc (object, Qnil);
- set_buffer_internal (XBUFFER (Vstandard_output));
- call0 (intern ("help-mode"));
- set_buffer_internal (old);
- return Qnil;
-}
-
-/* Copy out or in the info on where C-g should throw to.
- This is used when running Lisp code from within get_char,
- in case get_char is called recursively.
- See read_process_output. */
-
-save_getcjmp (temp)
- jmp_buf temp;
-{
- bcopy (getcjmp, temp, sizeof getcjmp);
-}
-
-restore_getcjmp (temp)
- jmp_buf temp;
-{
- bcopy (temp, getcjmp, sizeof getcjmp);
-}
-
-#ifdef HAVE_MOUSE
-
-/* Restore mouse tracking enablement. See Ftrack_mouse for the only use
- of this function. */
-
-static Lisp_Object
-tracking_off (old_value)
- Lisp_Object old_value;
-{
- do_mouse_tracking = old_value;
- if (NILP (old_value))
- {
- /* Redisplay may have been preempted because there was input
- available, and it assumes it will be called again after the
- input has been processed. If the only input available was
- the sort that we have just disabled, then we need to call
- redisplay. */
- if (!readable_events (1))
- {
- redisplay_preserve_echo_area ();
- get_input_pending (&input_pending, 1);
- }
- }
-}
-
-DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0,
- "Evaluate BODY with mouse movement events enabled.\n\
-Within a `track-mouse' form, mouse motion generates input events that\n\
-you can read with `read-event'.\n\
-Normally, mouse motion is ignored.")
- (args)
- Lisp_Object args;
-{
- int count = specpdl_ptr - specpdl;
- Lisp_Object val;
-
- record_unwind_protect (tracking_off, do_mouse_tracking);
-
- do_mouse_tracking = Qt;
-
- val = Fprogn (args);
- return unbind_to (count, val);
-}
-
-/* If mouse has moved on some frame, return one of those frames.
- Return 0 otherwise. */
-
-static FRAME_PTR
-some_mouse_moved ()
-{
- Lisp_Object tail, frame;
-
- FOR_EACH_FRAME (tail, frame)
- {
- if (XFRAME (frame)->mouse_moved)
- return XFRAME (frame);
- }
-
- return 0;
-}
-
-#endif /* HAVE_MOUSE */
-
-/* Low level keyboard/mouse input.
- kbd_buffer_store_event places events in kbd_buffer, and
- kbd_buffer_get_event retrieves them. */
-
-/* Return true iff there are any events in the queue that read-char
- would return. If this returns false, a read-char would block. */
-static int
-readable_events (do_timers_now)
- int do_timers_now;
-{
- if (do_timers_now)
- timer_check (do_timers_now);
-
- if (kbd_fetch_ptr != kbd_store_ptr)
- return 1;
-#ifdef HAVE_MOUSE
- if (!NILP (do_mouse_tracking) && some_mouse_moved ())
- return 1;
-#endif
- if (single_kboard)
- {
- if (current_kboard->kbd_queue_has_data)
- return 1;
- }
- else
- {
- KBOARD *kb;
- for (kb = all_kboards; kb; kb = kb->next_kboard)
- if (kb->kbd_queue_has_data)
- return 1;
- }
- return 0;
-}
-
-/* Set this for debugging, to have a way to get out */
-int stop_character;
-
-#ifdef MULTI_KBOARD
-static KBOARD *
-event_to_kboard (event)
- struct input_event *event;
-{
- Lisp_Object frame;
- frame = event->frame_or_window;
- if (CONSP (frame))
- frame = XCONS (frame)->car;
- else if (WINDOWP (frame))
- frame = WINDOW_FRAME (XWINDOW (frame));
-
- /* There are still some events that don't set this field.
- For now, just ignore the problem.
- Also ignore dead frames here. */
- if (!FRAMEP (frame) || !FRAME_LIVE_P (XFRAME (frame)))
- return 0;
- else
- return FRAME_KBOARD (XFRAME (frame));
-}
-#endif
-
-/* Store an event obtained at interrupt level into kbd_buffer, fifo */
-
-void
-kbd_buffer_store_event (event)
- register struct input_event *event;
-{
- if (event->kind == no_event)
- abort ();
-
- if (event->kind == ascii_keystroke)
- {
- register int c = event->code & 0377;
-
- if (event->modifiers & ctrl_modifier)
- c = make_ctrl_char (c);
-
- c |= (event->modifiers
- & (meta_modifier | alt_modifier
- | hyper_modifier | super_modifier));
-
- if (c == quit_char)
- {
- extern SIGTYPE interrupt_signal ();
-#ifdef MULTI_KBOARD
- KBOARD *kb;
- struct input_event *sp;
-
- if (single_kboard
- && (kb = FRAME_KBOARD (XFRAME (event->frame_or_window)),
- kb != current_kboard))
- {
- kb->kbd_queue
- = Fcons (make_lispy_switch_frame (event->frame_or_window),
- Fcons (make_number (c), Qnil));
- kb->kbd_queue_has_data = 1;
- for (sp = kbd_fetch_ptr; sp != kbd_store_ptr; sp++)
- {
- if (sp == kbd_buffer + KBD_BUFFER_SIZE)
- sp = kbd_buffer;
-
- if (event_to_kboard (sp) == kb)
- {
- sp->kind = no_event;
- sp->frame_or_window = Qnil;
- }
- }
- return;
- }
-#endif
-
- /* If this results in a quit_char being returned to Emacs as
- input, set Vlast_event_frame properly. If this doesn't
- get returned to Emacs as an event, the next event read
- will set Vlast_event_frame again, so this is safe to do. */
- {
- Lisp_Object focus;
-
- focus = FRAME_FOCUS_FRAME (XFRAME (event->frame_or_window));
- if (NILP (focus))
- focus = event->frame_or_window;
- internal_last_event_frame = focus;
- Vlast_event_frame = focus;
- }
-
- last_event_timestamp = event->timestamp;
- interrupt_signal ();
- return;
- }
-
- if (c && c == stop_character)
- {
- sys_suspend ();
- return;
- }
- }
- /* Don't insert two buffer_switch_event's in a row.
- Just ignore the second one. */
- else if (event->kind == buffer_switch_event
- && kbd_fetch_ptr != kbd_store_ptr
- && kbd_store_ptr->kind == buffer_switch_event)
- return;
-
- if (kbd_store_ptr - kbd_buffer == KBD_BUFFER_SIZE)
- kbd_store_ptr = kbd_buffer;
-
- /* Don't let the very last slot in the buffer become full,
- since that would make the two pointers equal,
- and that is indistinguishable from an empty buffer.
- Discard the event if it would fill the last slot. */
- if (kbd_fetch_ptr - 1 != kbd_store_ptr)
- {
- volatile struct input_event *sp = kbd_store_ptr;
- sp->kind = event->kind;
- if (event->kind == selection_request_event)
- {
- /* We must not use the ordinary copying code for this case,
- since `part' is an enum and copying it might not copy enough
- in this case. */
- bcopy (event, (char *) sp, sizeof (*event));
- }
- else
- {
- sp->code = event->code;
- sp->part = event->part;
- sp->frame_or_window = event->frame_or_window;
- sp->modifiers = event->modifiers;
- sp->x = event->x;
- sp->y = event->y;
- sp->timestamp = event->timestamp;
- }
- (XVECTOR (kbd_buffer_frame_or_window)->contents[kbd_store_ptr
- - kbd_buffer]
- = event->frame_or_window);
-
- kbd_store_ptr++;
- }
-}
-
-/* Read one event from the event buffer, waiting if necessary.
- The value is a Lisp object representing the event.
- The value is nil for an event that should be ignored,
- or that was handled here.
- We always read and discard one event. */
-
-static Lisp_Object
-kbd_buffer_get_event (kbp, used_mouse_menu)
- KBOARD **kbp;
- int *used_mouse_menu;
-{
- register int c;
- Lisp_Object obj;
- EMACS_TIME next_timer_delay;
-
- if (noninteractive)
- {
- c = getchar ();
- XSETINT (obj, c);
- *kbp = current_kboard;
- return obj;
- }
-
- /* Wait until there is input available. */
- for (;;)
- {
- if (kbd_fetch_ptr != kbd_store_ptr)
- break;
-#ifdef HAVE_MOUSE
- if (!NILP (do_mouse_tracking) && some_mouse_moved ())
- break;
-#endif
-
- /* If the quit flag is set, then read_char will return
- quit_char, so that counts as "available input." */
- if (!NILP (Vquit_flag))
- quit_throw_to_read_char ();
-
- /* One way or another, wait until input is available; then, if
- interrupt handlers have not read it, read it now. */
-
-#ifdef OLDVMS
- wait_for_kbd_input ();
-#else
-/* Note SIGIO has been undef'd if FIONREAD is missing. */
-#ifdef SIGIO
- gobble_input (0);
-#endif /* SIGIO */
- if (kbd_fetch_ptr != kbd_store_ptr)
- break;
-#ifdef HAVE_MOUSE
- if (!NILP (do_mouse_tracking) && some_mouse_moved ())
- break;
-#endif
- {
- Lisp_Object minus_one;
-
- XSETINT (minus_one, -1);
- wait_reading_process_input (0, 0, minus_one, 1);
-
- if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
- /* Pass 1 for EXPECT since we just waited to have input. */
- read_avail_input (1);
- }
-#endif /* not VMS */
- }
-
- /* At this point, we know that there is a readable event available
- somewhere. If the event queue is empty, then there must be a
- mouse movement enabled and available. */
- if (kbd_fetch_ptr != kbd_store_ptr)
- {
- struct input_event *event;
-
- event = ((kbd_fetch_ptr < kbd_buffer + KBD_BUFFER_SIZE)
- ? kbd_fetch_ptr
- : kbd_buffer);
-
- last_event_timestamp = event->timestamp;
-
-#ifdef MULTI_KBOARD
- *kbp = event_to_kboard (event);
- if (*kbp == 0)
- *kbp = current_kboard; /* Better than returning null ptr? */
-#else
- *kbp = &the_only_kboard;
-#endif
-
- obj = Qnil;
-
- /* These two kinds of events get special handling
- and don't actually appear to the command loop.
- We return nil for them. */
- if (event->kind == selection_request_event)
- {
-#ifdef HAVE_X11
- struct input_event copy;
-
- /* Remove it from the buffer before processing it,
- since otherwise swallow_events will see it
- and process it again. */
- copy = *event;
- kbd_fetch_ptr = event + 1;
- input_pending = readable_events (0);
- x_handle_selection_request (&copy);
-#else
- /* We're getting selection request events, but we don't have
- a window system. */
- abort ();
-#endif
- }
-
- else if (event->kind == selection_clear_event)
- {
-#ifdef HAVE_X11
- struct input_event copy;
-
- /* Remove it from the buffer before processing it. */
- copy = *event;
- kbd_fetch_ptr = event + 1;
- input_pending = readable_events (0);
- x_handle_selection_clear (&copy);
-#else
- /* We're getting selection request events, but we don't have
- a window system. */
- abort ();
-#endif
- }
-#if defined (HAVE_X11) || defined (HAVE_NTGUI)
- else if (event->kind == delete_window_event)
- {
- /* Make an event (delete-frame (FRAME)). */
- obj = Fcons (event->frame_or_window, Qnil);
- obj = Fcons (Qdelete_frame, Fcons (obj, Qnil));
- kbd_fetch_ptr = event + 1;
- }
- else if (event->kind == iconify_event)
- {
- /* Make an event (iconify-frame (FRAME)). */
- obj = Fcons (event->frame_or_window, Qnil);
- obj = Fcons (Qiconify_frame, Fcons (obj, Qnil));
- kbd_fetch_ptr = event + 1;
- }
- else if (event->kind == deiconify_event)
- {
- /* Make an event (make-frame-visible (FRAME)). */
- obj = Fcons (event->frame_or_window, Qnil);
- obj = Fcons (Qmake_frame_visible, Fcons (obj, Qnil));
- kbd_fetch_ptr = event + 1;
- }
-#endif
- else if (event->kind == buffer_switch_event)
- {
- /* The value doesn't matter here; only the type is tested. */
- XSETBUFFER (obj, current_buffer);
- kbd_fetch_ptr = event + 1;
- }
-#ifdef USE_X_TOOLKIT
- else if (event->kind == menu_bar_activate_event)
- {
- kbd_fetch_ptr = event + 1;
- input_pending = readable_events (0);
- if (FRAME_LIVE_P (XFRAME (event->frame_or_window)))
- x_activate_menubar (XFRAME (event->frame_or_window));
- }
-#endif
- /* Just discard these, by returning nil.
- With MULTI_KBOARD, these events are used as placeholders
- when we need to randomly delete events from the queue.
- (They shouldn't otherwise be found in the buffer,
- but on some machines it appears they do show up
- even without MULTI_KBOARD.) */
- else if (event->kind == no_event)
- kbd_fetch_ptr = event + 1;
-
- /* If this event is on a different frame, return a switch-frame this
- time, and leave the event in the queue for next time. */
- else
- {
- Lisp_Object frame;
- Lisp_Object focus;
-
- frame = event->frame_or_window;
- if (CONSP (frame))
- frame = XCONS (frame)->car;
- else if (WINDOWP (frame))
- frame = WINDOW_FRAME (XWINDOW (frame));
-
- focus = FRAME_FOCUS_FRAME (XFRAME (frame));
- if (! NILP (focus))
- frame = focus;
-
- if (! EQ (frame, internal_last_event_frame)
- && XFRAME (frame) != selected_frame)
- obj = make_lispy_switch_frame (frame);
- internal_last_event_frame = frame;
-
- /* If we didn't decide to make a switch-frame event, go ahead
- and build a real event from the queue entry. */
-
- if (NILP (obj))
- {
- obj = make_lispy_event (event);
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
- /* If this was a menu selection, then set the flag to inhibit
- writing to last_nonmenu_event. Don't do this if the event
- we're returning is (menu-bar), though; that indicates the
- beginning of the menu sequence, and we might as well leave
- that as the `event with parameters' for this selection. */
- if (event->kind == menu_bar_event
- && !(CONSP (obj) && EQ (XCONS (obj)->car, Qmenu_bar))
- && used_mouse_menu)
- *used_mouse_menu = 1;
-#endif
-
- /* Wipe out this event, to catch bugs. */
- event->kind = no_event;
- XVECTOR (kbd_buffer_frame_or_window)->contents[event - kbd_buffer] = Qnil;
-
- kbd_fetch_ptr = event + 1;
- }
- }
- }
-#ifdef HAVE_MOUSE
- /* Try generating a mouse motion event. */
- else if (!NILP (do_mouse_tracking) && some_mouse_moved ())
- {
- FRAME_PTR f = some_mouse_moved ();
- Lisp_Object bar_window;
- enum scroll_bar_part part;
- Lisp_Object x, y;
- unsigned long time;
-
- *kbp = current_kboard;
- /* Note that this uses F to determine which display to look at.
- If there is no valid info, it does not store anything
- so x remains nil. */
- x = Qnil;
- (*mouse_position_hook) (&f, 0, &bar_window, &part, &x, &y, &time);
-
- obj = Qnil;
-
- /* Decide if we should generate a switch-frame event. Don't
- generate switch-frame events for motion outside of all Emacs
- frames. */
- if (!NILP (x) && f)
- {
- Lisp_Object frame;
-
- frame = FRAME_FOCUS_FRAME (f);
- if (NILP (frame))
- XSETFRAME (frame, f);
-
- if (! EQ (frame, internal_last_event_frame)
- && XFRAME (frame) != selected_frame)
- obj = make_lispy_switch_frame (frame);
- internal_last_event_frame = frame;
- }
-
- /* If we didn't decide to make a switch-frame event, go ahead and
- return a mouse-motion event. */
- if (!NILP (x) && NILP (obj))
- obj = make_lispy_movement (f, bar_window, part, x, y, time);
- }
-#endif /* HAVE_MOUSE */
- else
- /* We were promised by the above while loop that there was
- something for us to read! */
- abort ();
-
- input_pending = readable_events (0);
-
- Vlast_event_frame = internal_last_event_frame;
-
- return (obj);
-}
-
-/* Process any events that are not user-visible,
- then return, without reading any user-visible events. */
-
-void
-swallow_events (do_display)
- int do_display;
-{
- int old_timers_run;
-
- while (kbd_fetch_ptr != kbd_store_ptr)
- {
- struct input_event *event;
-
- event = ((kbd_fetch_ptr < kbd_buffer + KBD_BUFFER_SIZE)
- ? kbd_fetch_ptr
- : kbd_buffer);
-
- last_event_timestamp = event->timestamp;
-
- /* These two kinds of events get special handling
- and don't actually appear to the command loop. */
- if (event->kind == selection_request_event)
- {
-#ifdef HAVE_X11
- struct input_event copy;
-
- /* Remove it from the buffer before processing it,
- since otherwise swallow_events called recursively could see it
- and process it again. */
- copy = *event;
- kbd_fetch_ptr = event + 1;
- input_pending = readable_events (0);
- x_handle_selection_request (&copy);
-#else
- /* We're getting selection request events, but we don't have
- a window system. */
- abort ();
-#endif
- }
-
- else if (event->kind == selection_clear_event)
- {
-#ifdef HAVE_X11
- struct input_event copy;
-
- /* Remove it from the buffer before processing it, */
- copy = *event;
-
- kbd_fetch_ptr = event + 1;
- input_pending = readable_events (0);
- x_handle_selection_clear (&copy);
-#else
- /* We're getting selection request events, but we don't have
- a window system. */
- abort ();
-#endif
- }
- /* Note that timer_event is currently never used. */
- else if (event->kind == timer_event)
- {
- Lisp_Object tem, lisp_event;
- int was_locked = single_kboard;
-
- tem = get_keymap_1 (Vspecial_event_map, 0, 0);
- tem = get_keyelt (access_keymap (tem, Qtimer_event, 0, 0),
- 1);
- lisp_event = Fcons (Qtimer_event,
- Fcons (Fcdr (event->frame_or_window), Qnil));
- kbd_fetch_ptr = event + 1;
- if (kbd_fetch_ptr == kbd_store_ptr)
- input_pending = 0;
- Fcommand_execute (tem, Qnil, Fvector (1, &lisp_event), Qt);
- timers_run++;
- if (do_display)
- redisplay_preserve_echo_area ();
-
- /* Resume allowing input from any kboard, if that was true before. */
- if (!was_locked)
- any_kboard_state ();
- }
- else
- break;
- }
-
- old_timers_run = timers_run;
- get_input_pending (&input_pending, 1);
-
- if (timers_run != old_timers_run && do_display)
- redisplay_preserve_echo_area ();
-}
-
-static EMACS_TIME timer_idleness_start_time;
-
-/* Record the start of when Emacs is idle,
- for the sake of running idle-time timers. */
-
-timer_start_idle ()
-{
- Lisp_Object timers;
-
- /* If we are already in the idle state, do nothing. */
- if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
- return;
-
- EMACS_GET_TIME (timer_idleness_start_time);
-
- /* Mark all idle-time timers as once again candidates for running. */
- for (timers = Vtimer_idle_list; CONSP (timers); timers = XCONS (timers)->cdr)
- {
- Lisp_Object timer;
-
- timer = XCONS (timers)->car;
-
- if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
- continue;
- XVECTOR (timer)->contents[0] = Qnil;
- }
-}
-
-/* Record that Emacs is no longer idle, so stop running idle-time timers. */
-
-timer_stop_idle ()
-{
- EMACS_SET_SECS_USECS (timer_idleness_start_time, -1, -1);
-}
-
-/* This is only for debugging. */
-struct input_event last_timer_event;
-
-/* Check whether a timer has fired. To prevent larger problems we simply
- disregard elements that are not proper timers. Do not make a circular
- timer list for the time being.
-
- Returns the number of seconds to wait until the next timer fires. If a
- timer is triggering now, return zero seconds.
- If no timer is active, return -1 seconds.
-
- If a timer is ripe, we run it, with quitting turned off.
-
- DO_IT_NOW is now ignored. It used to mean that we should
- run the timer directly instead of queueing a timer-event.
- Now we always run timers directly. */
-
-EMACS_TIME
-timer_check (do_it_now)
- int do_it_now;
-{
- EMACS_TIME nexttime;
- EMACS_TIME now, idleness_now;
- Lisp_Object timers, idle_timers, chosen_timer;
- /* Nonzero if we generate some events. */
- int events_generated = 0;
- struct gcpro gcpro1, gcpro2, gcpro3;
-
- EMACS_SET_SECS (nexttime, -1);
- EMACS_SET_USECS (nexttime, -1);
-
- /* Always consider the ordinary timers. */
- timers = Vtimer_list;
- /* Consider the idle timers only if Emacs is idle. */
- if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
- idle_timers = Vtimer_idle_list;
- else
- idle_timers = Qnil;
- chosen_timer = Qnil;
- GCPRO3 (timers, idle_timers, chosen_timer);
-
- if (CONSP (timers) || CONSP (idle_timers))
- {
- EMACS_GET_TIME (now);
- if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
- EMACS_SUB_TIME (idleness_now, now, timer_idleness_start_time);
- }
-
- while (CONSP (timers) || CONSP (idle_timers))
- {
- int triggertime = EMACS_SECS (now);
- Lisp_Object *vector;
- Lisp_Object timer, idle_timer;
- EMACS_TIME timer_time, idle_timer_time;
- EMACS_TIME difference, timer_difference, idle_timer_difference;
-
- /* Skip past invalid timers and timers already handled. */
- if (!NILP (timers))
- {
- timer = XCONS (timers)->car;
- if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
- {
- timers = XCONS (timers)->cdr;
- continue;
- }
- vector = XVECTOR (timer)->contents;
-
- if (!INTEGERP (vector[1]) || !INTEGERP (vector[2])
- || !INTEGERP (vector[3])
- || ! NILP (vector[0]))
- {
- timers = XCONS (timers)->cdr;
- continue;
- }
- }
- if (!NILP (idle_timers))
- {
- timer = XCONS (idle_timers)->car;
- if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
- {
- idle_timers = XCONS (idle_timers)->cdr;
- continue;
- }
- vector = XVECTOR (timer)->contents;
-
- if (!INTEGERP (vector[1]) || !INTEGERP (vector[2])
- || !INTEGERP (vector[3])
- || ! NILP (vector[0]))
- {
- idle_timers = XCONS (idle_timers)->cdr;
- continue;
- }
- }
-
- /* Set TIMER, TIMER_TIME and TIMER_DIFFERENCE
- based on the next ordinary timer.
- TIMER_DIFFERENCE is the distance in time from NOW to when
- this timer becomes ripe (negative if it's already ripe). */
- if (!NILP (timers))
- {
- timer = XCONS (timers)->car;
- vector = XVECTOR (timer)->contents;
- EMACS_SET_SECS (timer_time,
- (XINT (vector[1]) << 16) | (XINT (vector[2])));
- EMACS_SET_USECS (timer_time, XINT (vector[3]));
- EMACS_SUB_TIME (timer_difference, timer_time, now);
- }
-
- /* Set IDLE_TIMER, IDLE_TIMER_TIME and IDLE_TIMER_DIFFERENCE
- based on the next idle timer. */
- if (!NILP (idle_timers))
- {
- idle_timer = XCONS (idle_timers)->car;
- vector = XVECTOR (idle_timer)->contents;
- EMACS_SET_SECS (idle_timer_time,
- (XINT (vector[1]) << 16) | (XINT (vector[2])));
- EMACS_SET_USECS (idle_timer_time, XINT (vector[3]));
- EMACS_SUB_TIME (idle_timer_difference, idle_timer_time, idleness_now);
- }
-
- /* Decide which timer is the next timer,
- and set CHOSEN_TIMER, VECTOR and DIFFERENCE accordingly.
- Also step down the list where we found that timer. */
-
- if (! NILP (timers) && ! NILP (idle_timers))
- {
- EMACS_TIME temp;
- EMACS_SUB_TIME (temp, timer_difference, idle_timer_difference);
- if (EMACS_TIME_NEG_P (temp))
- {
- chosen_timer = timer;
- timers = XCONS (timers)->cdr;
- difference = timer_difference;
- }
- else
- {
- chosen_timer = idle_timer;
- idle_timers = XCONS (idle_timers)->cdr;
- difference = idle_timer_difference;
- }
- }
- else if (! NILP (timers))
- {
- chosen_timer = timer;
- timers = XCONS (timers)->cdr;
- difference = timer_difference;
- }
- else
- {
- chosen_timer = idle_timer;
- idle_timers = XCONS (idle_timers)->cdr;
- difference = idle_timer_difference;
- }
- vector = XVECTOR (chosen_timer)->contents;
-
- /* If timer is rupe, run it if it hasn't been run. */
- if (EMACS_TIME_NEG_P (difference)
- || (EMACS_SECS (difference) == 0
- && EMACS_USECS (difference) == 0))
- {
- if (NILP (vector[0]))
- {
- /* Mark the timer as triggered to prevent problems if the lisp
- code fails to reschedule it right. */
- vector[0] = Qt;
-
- /* Run the timer or queue a timer event. */
- if (1)
- {
- Lisp_Object tem, event;
- int was_locked = single_kboard;
- int count = specpdl_ptr - specpdl;
-
- specbind (Qinhibit_quit, Qt);
-
- tem = get_keymap_1 (Vspecial_event_map, 0, 0);
- tem = get_keyelt (access_keymap (tem, Qtimer_event, 0, 0),
- 1);
- event = Fcons (Qtimer_event, Fcons (chosen_timer, Qnil));
- Fcommand_execute (tem, Qnil, Fvector (1, &event), Qt);
- timers_run++;
-
- unbind_to (count, Qnil);
-
- /* Resume allowing input from any kboard, if that was true before. */
- if (!was_locked)
- any_kboard_state ();
-
- /* Since we have handled the event,
- we don't need to tell the caller to wake up and do it. */
- }
-#if 0
- else
- {
- /* Generate a timer event so the caller will handle it. */
- struct input_event event;
-
- event.kind = timer_event;
- event.modifiers = 0;
- event.x = event.y = Qnil;
- event.timestamp = triggertime;
- /* Store the timer in the frame slot. */
- event.frame_or_window
- = Fcons (Fselected_frame (), chosen_timer);
- kbd_buffer_store_event (&event);
-
- last_timer_event = event;
-
- /* Tell caller to handle this event right away. */
- events_generated = 1;
- EMACS_SET_SECS (nexttime, 0);
- EMACS_SET_USECS (nexttime, 0);
-
- /* Don't queue more than one event at once.
- When Emacs is ready for another, it will
- queue the next one. */
- UNGCPRO;
- return nexttime;
- }
-#endif /* 0 */
- }
- }
- else
- /* When we encounter a timer that is still waiting,
- return the amount of time to wait before it is ripe. */
- {
- UNGCPRO;
- /* But if we generated an event,
- tell the caller to handle it now. */
- if (events_generated)
- return nexttime;
- return difference;
- }
- }
-
- /* No timers are pending in the future. */
- /* Return 0 if we generated an event, and -1 if not. */
- UNGCPRO;
- return nexttime;
-}
-
-/* Caches for modify_event_symbol. */
-static Lisp_Object accent_key_syms;
-static Lisp_Object func_key_syms;
-static Lisp_Object mouse_syms;
-
-/* This is a list of keysym codes for special "accent" characters.
- It parallels lispy_accent_keys. */
-
-static int lispy_accent_codes[] =
-{
-#ifdef XK_dead_circumflex
- XK_dead_circumflex,
-#else
- 0,
-#endif
-#ifdef XK_dead_grave
- XK_dead_grave,
-#else
- 0,
-#endif
-#ifdef XK_dead_tilde
- XK_dead_tilde,
-#else
- 0,
-#endif
-#ifdef XK_dead_diaeresis
- XK_dead_diaeresis,
-#else
- 0,
-#endif
-#ifdef XK_dead_macron
- XK_dead_macron,
-#else
- 0,
-#endif
-#ifdef XK_dead_degree
- XK_dead_degree,
-#else
- 0,
-#endif
-#ifdef XK_dead_acute
- XK_dead_acute,
-#else
- 0,
-#endif
-#ifdef XK_dead_cedilla
- XK_dead_cedilla,
-#else
- 0,
-#endif
-#ifdef XK_dead_breve
- XK_dead_breve,
-#else
- 0,
-#endif
-#ifdef XK_dead_ogonek
- XK_dead_ogonek,
-#else
- 0,
-#endif
-#ifdef XK_dead_caron
- XK_dead_caron,
-#else
- 0,
-#endif
-#ifdef XK_dead_doubleacute
- XK_dead_doubleacute,
-#else
- 0,
-#endif
-#ifdef XK_dead_abovedot
- XK_dead_abovedot,
-#else
- 0,
-#endif
-};
-
-/* This is a list of Lisp names for special "accent" characters.
- It parallels lispy_accent_codes. */
-
-static char *lispy_accent_keys[] =
-{
- "dead-circumflex",
- "dead-grave",
- "dead-tilde",
- "dead-diaeresis",
- "dead-macron",
- "dead-degree",
- "dead-acute",
- "dead-cedilla",
- "dead-breve",
- "dead-ogonek",
- "dead-caron",
- "dead-doubleacute",
- "dead-abovedot",
-};
-
-#ifdef HAVE_NTGUI
-#define FUNCTION_KEY_OFFSET 0x0
-
-char *lispy_function_keys[] =
- {
- 0, /* 0 */
-
- 0, /* VK_LBUTTON 0x01 */
- 0, /* VK_RBUTTON 0x02 */
- "cancel", /* VK_CANCEL 0x03 */
- 0, /* VK_MBUTTON 0x04 */
-
- 0, 0, 0, /* 0x05 .. 0x07 */
-
- "backspace", /* VK_BACK 0x08 */
- "tab", /* VK_TAB 0x09 */
-
- 0, 0, /* 0x0A .. 0x0B */
-
- "clear", /* VK_CLEAR 0x0C */
- "return", /* VK_RETURN 0x0D */
-
- 0, 0, /* 0x0E .. 0x0F */
-
- "shift", /* VK_SHIFT 0x10 */
- "control", /* VK_CONTROL 0x11 */
- "menu", /* VK_MENU 0x12 */
- "pause", /* VK_PAUSE 0x13 */
- "capital", /* VK_CAPITAL 0x14 */
-
- 0, 0, 0, 0, 0, 0, /* 0x15 .. 0x1A */
-
- 0, /* VK_ESCAPE 0x1B */
-
- 0, 0, 0, 0, /* 0x1C .. 0x1F */
-
- 0, /* VK_SPACE 0x20 */
- "prior", /* VK_PRIOR 0x21 */
- "next", /* VK_NEXT 0x22 */
- "end", /* VK_END 0x23 */
- "home", /* VK_HOME 0x24 */
- "left", /* VK_LEFT 0x25 */
- "up", /* VK_UP 0x26 */
- "right", /* VK_RIGHT 0x27 */
- "down", /* VK_DOWN 0x28 */
- "select", /* VK_SELECT 0x29 */
- "print", /* VK_PRINT 0x2A */
- "execute", /* VK_EXECUTE 0x2B */
- "snapshot", /* VK_SNAPSHOT 0x2C */
- "insert", /* VK_INSERT 0x2D */
- "delete", /* VK_DELETE 0x2E */
- "help", /* VK_HELP 0x2F */
-
- /* VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
- 0, 0, 0, 0, 0, 0, 0, /* 0x3A .. 0x40 */
-
- /* VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-
- "lwindow", /* VK_LWIN 0x5B */
- "rwindow", /* VK_RWIN 0x5C */
- "apps", /* VK_APPS 0x5D */
-
- 0, 0, /* 0x5E .. 0x5F */
-
- "kp-0", /* VK_NUMPAD0 0x60 */
- "kp-1", /* VK_NUMPAD1 0x61 */
- "kp-2", /* VK_NUMPAD2 0x62 */
- "kp-3", /* VK_NUMPAD3 0x63 */
- "kp-4", /* VK_NUMPAD4 0x64 */
- "kp-5", /* VK_NUMPAD5 0x65 */
- "kp-6", /* VK_NUMPAD6 0x66 */
- "kp-7", /* VK_NUMPAD7 0x67 */
- "kp-8", /* VK_NUMPAD8 0x68 */
- "kp-9", /* VK_NUMPAD9 0x69 */
- "kp-multiply", /* VK_MULTIPLY 0x6A */
- "kp-add", /* VK_ADD 0x6B */
- "kp-separator", /* VK_SEPARATOR 0x6C */
- "kp-subtract", /* VK_SUBTRACT 0x6D */
- "kp-decimal", /* VK_DECIMAL 0x6E */
- "kp-divide", /* VK_DIVIDE 0x6F */
- "f1", /* VK_F1 0x70 */
- "f2", /* VK_F2 0x71 */
- "f3", /* VK_F3 0x72 */
- "f4", /* VK_F4 0x73 */
- "f5", /* VK_F5 0x74 */
- "f6", /* VK_F6 0x75 */
- "f7", /* VK_F7 0x76 */
- "f8", /* VK_F8 0x77 */
- "f9", /* VK_F9 0x78 */
- "f10", /* VK_F10 0x79 */
- "f11", /* VK_F11 0x7A */
- "f12", /* VK_F12 0x7B */
- "f13", /* VK_F13 0x7C */
- "f14", /* VK_F14 0x7D */
- "f15", /* VK_F15 0x7E */
- "f16", /* VK_F16 0x7F */
- "f17", /* VK_F17 0x80 */
- "f18", /* VK_F18 0x81 */
- "f19", /* VK_F19 0x82 */
- "f20", /* VK_F20 0x83 */
- "f21", /* VK_F21 0x84 */
- "f22", /* VK_F22 0x85 */
- "f23", /* VK_F23 0x86 */
- "f24", /* VK_F24 0x87 */
-
- 0, 0, 0, 0, /* 0x88 .. 0x8B */
- 0, 0, 0, 0, /* 0x8C .. 0x8F */
-
- "kp-numlock", /* VK_NUMLOCK 0x90 */
- "scroll", /* VK_SCROLL 0x91 */
-
- "kp-space", /* VK_NUMPAD_CLEAR 0x92 */
- "kp-enter", /* VK_NUMPAD_ENTER 0x93 */
- "kp-prior", /* VK_NUMPAD_PRIOR 0x94 */
- "kp-next", /* VK_NUMPAD_NEXT 0x95 */
- "kp-end", /* VK_NUMPAD_END 0x96 */
- "kp-home", /* VK_NUMPAD_HOME 0x97 */
- "kp-left", /* VK_NUMPAD_LEFT 0x98 */
- "kp-up", /* VK_NUMPAD_UP 0x99 */
- "kp-right", /* VK_NUMPAD_RIGHT 0x9A */
- "kp-down", /* VK_NUMPAD_DOWN 0x9B */
- "kp-insert", /* VK_NUMPAD_INSERT 0x9C */
- "kp-delete", /* VK_NUMPAD_DELETE 0x9D */
-
- 0, 0, /* 0x9E .. 0x9F */
-
- /*
- * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.
- * Used only as parameters to GetAsyncKeyState() and GetKeyState().
- * No other API or message will distinguish left and right keys this way.
- */
- /* 0xA0 .. 0xEF */
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
- /* 0xF0 .. 0xF5 */
-
- 0, 0, 0, 0, 0, 0,
-
- "attn", /* VK_ATTN 0xF6 */
- "crsel", /* VK_CRSEL 0xF7 */
- "exsel", /* VK_EXSEL 0xF8 */
- "ereof", /* VK_EREOF 0xF9 */
- "play", /* VK_PLAY 0xFA */
- "zoom", /* VK_ZOOM 0xFB */
- "noname", /* VK_NONAME 0xFC */
- "pa1", /* VK_PA1 0xFD */
- "oem_clear", /* VK_OEM_CLEAR 0xFE */
- };
-
-#else
-
-#define FUNCTION_KEY_OFFSET 0xff00
-
-/* You'll notice that this table is arranged to be conveniently
- indexed by X Windows keysym values. */
-static char *lispy_function_keys[] =
- {
- /* X Keysym value */
-
- 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff00 */
- "backspace",
- "tab",
- "linefeed",
- "clear",
- 0,
- "return",
- 0, 0,
- 0, 0, 0, /* 0xff10 */
- "pause",
- 0, 0, 0, 0, 0, 0, 0,
- "escape",
- 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff20...2f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff30...3f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff40...4f */
-
- "home", /* 0xff50 */ /* IsCursorKey */
- "left",
- "up",
- "right",
- "down",
- "prior",
- "next",
- "end",
- "begin",
- 0, /* 0xff59 */
- 0, 0, 0, 0, 0, 0,
- "select", /* 0xff60 */ /* IsMiscFunctionKey */
- "print",
- "execute",
- "insert",
- 0, /* 0xff64 */
- "undo",
- "redo",
- "menu",
- "find",
- "cancel",
- "help",
- "break", /* 0xff6b */
-
- 0, 0, 0, 0, 0, 0, 0, 0, "backtab", 0,
- 0, /* 0xff76 */
- 0, 0, 0, 0, 0, 0, 0, 0, "kp-numlock", /* 0xff7f */
- "kp-space", /* 0xff80 */ /* IsKeypadKey */
- 0, 0, 0, 0, 0, 0, 0, 0,
- "kp-tab", /* 0xff89 */
- 0, 0, 0,
- "kp-enter", /* 0xff8d */
- 0, 0, 0,
- "kp-f1", /* 0xff91 */
- "kp-f2",
- "kp-f3",
- "kp-f4",
- "kp-home", /* 0xff95 */
- "kp-left",
- "kp-up",
- "kp-right",
- "kp-down",
- "kp-prior", /* kp-page-up */
- "kp-next", /* kp-page-down */
- "kp-end",
- "kp-begin",
- "kp-insert",
- "kp-delete",
- 0, /* 0xffa0 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
- "kp-multiply", /* 0xffaa */
- "kp-add",
- "kp-separator",
- "kp-subtract",
- "kp-decimal",
- "kp-divide", /* 0xffaf */
- "kp-0", /* 0xffb0 */
- "kp-1", "kp-2", "kp-3", "kp-4", "kp-5", "kp-6", "kp-7", "kp-8", "kp-9",
- 0, /* 0xffba */
- 0, 0,
- "kp-equal", /* 0xffbd */
- "f1", /* 0xffbe */ /* IsFunctionKey */
- "f2",
- "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", /* 0xffc0 */
- "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18",
- "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", /* 0xffd0 */
- "f27", "f28", "f29", "f30", "f31", "f32", "f33", "f34",
- "f35", 0, 0, 0, 0, 0, 0, 0, /* 0xffe0 */
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, /* 0xfff0 */
- 0, 0, 0, 0, 0, 0, 0, "delete"
- };
-
-#endif /* HAVE_NTGUI */
-
-static char *lispy_mouse_names[] =
-{
- "mouse-1", "mouse-2", "mouse-3", "mouse-4", "mouse-5"
-};
-
-/* Scroll bar parts. */
-Lisp_Object Qabove_handle, Qhandle, Qbelow_handle;
-Lisp_Object Qup, Qdown;
-
-/* An array of scroll bar parts, indexed by an enum scroll_bar_part value. */
-Lisp_Object *scroll_bar_parts[] = {
- &Qabove_handle, &Qhandle, &Qbelow_handle,
- &Qup, &Qdown,
-};
-
-
-/* A vector, indexed by button number, giving the down-going location
- of currently depressed buttons, both scroll bar and non-scroll bar.
-
- The elements have the form
- (BUTTON-NUMBER MODIFIER-MASK . REST)
- where REST is the cdr of a position as it would be reported in the event.
-
- The make_lispy_event function stores positions here to tell the
- difference between click and drag events, and to store the starting
- location to be included in drag events. */
-
-static Lisp_Object button_down_location;
-
-/* Information about the most recent up-going button event: Which
- button, what location, and what time. */
-
-static int last_mouse_button;
-static int last_mouse_x;
-static int last_mouse_y;
-static unsigned long button_down_time;
-
-/* The maximum time between clicks to make a double-click,
- or Qnil to disable double-click detection,
- or Qt for no time limit. */
-Lisp_Object Vdouble_click_time;
-
-/* The number of clicks in this multiple-click. */
-
-int double_click_count;
-
-/* Given a struct input_event, build the lisp event which represents
- it. If EVENT is 0, build a mouse movement event from the mouse
- movement buffer, which should have a movement event in it.
-
- Note that events must be passed to this function in the order they
- are received; this function stores the location of button presses
- in order to build drag events when the button is released. */
-
-static Lisp_Object
-make_lispy_event (event)
- struct input_event *event;
-{
- int i;
-
- switch (SWITCH_ENUM_CAST (event->kind))
- {
- /* A simple keystroke. */
- case ascii_keystroke:
- {
- Lisp_Object lispy_c;
- int c = event->code & 0377;
- /* Turn ASCII characters into control characters
- when proper. */
- if (event->modifiers & ctrl_modifier)
- c = make_ctrl_char (c);
-
- /* Add in the other modifier bits. We took care of ctrl_modifier
- just above, and the shift key was taken care of by the X code,
- and applied to control characters by make_ctrl_char. */
- c |= (event->modifiers
- & (meta_modifier | alt_modifier
- | hyper_modifier | super_modifier));
- button_down_time = 0;
- XSETFASTINT (lispy_c, c);
- return lispy_c;
- }
-
- /* A function key. The symbol may need to have modifier prefixes
- tacked onto it. */
- case non_ascii_keystroke:
- button_down_time = 0;
-
- for (i = 0; i < sizeof (lispy_accent_codes) / sizeof (int); i++)
- if (event->code == lispy_accent_codes[i])
- return modify_event_symbol (i,
- event->modifiers,
- Qfunction_key, Qnil,
- lispy_accent_keys, &accent_key_syms,
- (sizeof (lispy_accent_keys)
- / sizeof (lispy_accent_keys[0])));
-
- /* Handle system-specific keysyms. */
- if (event->code & (1 << 28))
- {
- /* We need to use an alist rather than a vector as the cache
- since we can't make a vector long enuf. */
- if (NILP (current_kboard->system_key_syms))
- current_kboard->system_key_syms = Fcons (Qnil, Qnil);
- return modify_event_symbol (event->code,
- event->modifiers,
- Qfunction_key,
- current_kboard->Vsystem_key_alist,
- 0, &current_kboard->system_key_syms,
- (unsigned)-1);
- }
-
- return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET,
- event->modifiers,
- Qfunction_key, Qnil,
- lispy_function_keys, &func_key_syms,
- (sizeof (lispy_function_keys)
- / sizeof (lispy_function_keys[0])));
- break;
-
- /* Note that timer_event is currently never used. */
- case timer_event:
- return Fcons (Qtimer_event, Fcons (Fcdr (event->frame_or_window), Qnil));
-
-#ifdef HAVE_MOUSE
- /* A mouse click. Figure out where it is, decide whether it's
- a press, click or drag, and build the appropriate structure. */
- case mouse_click:
- case scroll_bar_click:
- {
- int button = event->code;
- int is_double;
- Lisp_Object position;
- Lisp_Object *start_pos_ptr;
- Lisp_Object start_pos;
-
- if (button < 0 || button >= NUM_MOUSE_BUTTONS)
- abort ();
-
- /* Build the position as appropriate for this mouse click. */
- if (event->kind == mouse_click)
- {
- int part;
- FRAME_PTR f = XFRAME (event->frame_or_window);
- Lisp_Object window;
- Lisp_Object posn;
- int row, column;
-
- /* Ignore mouse events that were made on frame that
- have been deleted. */
- if (! FRAME_LIVE_P (f))
- return Qnil;
-
- pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
- &column, &row, NULL, 1);
-
-#ifndef USE_X_TOOLKIT
- /* In the non-toolkit version, clicks on the menu bar
- are ordinary button events in the event buffer.
- Distinguish them, and invoke the menu.
-
- (In the toolkit version, the toolkit handles the menu bar
- and Emacs doesn't know about it until after the user
- makes a selection.) */
- if (row >= 0 && row < FRAME_MENU_BAR_LINES (f)
- && (event->modifiers & down_modifier))
- {
- Lisp_Object items, item;
- int hpos;
- int i;
-
-#if 0
- /* Activate the menu bar on the down event. If the
- up event comes in before the menu code can deal with it,
- just ignore it. */
- if (! (event->modifiers & down_modifier))
- return Qnil;
-#endif
-
- item = Qnil;
- items = FRAME_MENU_BAR_ITEMS (f);
- for (i = 0; i < XVECTOR (items)->size; i += 4)
- {
- Lisp_Object pos, string;
- string = XVECTOR (items)->contents[i + 1];
- pos = XVECTOR (items)->contents[i + 3];
- if (NILP (string))
- break;
- if (column >= XINT (pos)
- && column < XINT (pos) + XSTRING (string)->size)
- {
- item = XVECTOR (items)->contents[i];
- break;
- }
- }
-
- position
- = Fcons (event->frame_or_window,
- Fcons (Qmenu_bar,
- Fcons (Fcons (event->x, event->y),
- Fcons (make_number (event->timestamp),
- Qnil))));
-
- return Fcons (item, Fcons (position, Qnil));
- }
-#endif /* not USE_X_TOOLKIT */
-
- window = window_from_coordinates (f, column, row, &part);
-
- if (!WINDOWP (window))
- {
- window = event->frame_or_window;
- posn = Qnil;
- }
- else
- {
- int pixcolumn, pixrow;
- column -= WINDOW_LEFT_MARGIN (XWINDOW (window));
- row -= XINT (XWINDOW (window)->top);
- glyph_to_pixel_coords (f, column, row, &pixcolumn, &pixrow);
- XSETINT (event->x, pixcolumn);
- XSETINT (event->y, pixrow);
-
- if (part == 1)
- posn = Qmode_line;
- else if (part == 2)
- posn = Qvertical_line;
- else
- XSETINT (posn,
- buffer_posn_from_coords (XWINDOW (window),
- column, row));
- }
-
- position
- = Fcons (window,
- Fcons (posn,
- Fcons (Fcons (event->x, event->y),
- Fcons (make_number (event->timestamp),
- Qnil))));
- }
- else
- {
- Lisp_Object window;
- Lisp_Object portion_whole;
- Lisp_Object part;
-
- window = event->frame_or_window;
- portion_whole = Fcons (event->x, event->y);
- part = *scroll_bar_parts[(int) event->part];
-
- position
- = Fcons (window,
- Fcons (Qvertical_scroll_bar,
- Fcons (portion_whole,
- Fcons (make_number (event->timestamp),
- Fcons (part, Qnil)))));
- }
-
- start_pos_ptr = &XVECTOR (button_down_location)->contents[button];
-
- start_pos = *start_pos_ptr;
- *start_pos_ptr = Qnil;
-
- is_double = (button == last_mouse_button
- && XINT (event->x) == last_mouse_x
- && XINT (event->y) == last_mouse_y
- && button_down_time != 0
- && (EQ (Vdouble_click_time, Qt)
- || (INTEGERP (Vdouble_click_time)
- && ((int)(event->timestamp - button_down_time)
- < XINT (Vdouble_click_time)))));
- last_mouse_button = button;
- last_mouse_x = XINT (event->x);
- last_mouse_y = XINT (event->y);
-
- /* If this is a button press, squirrel away the location, so
- we can decide later whether it was a click or a drag. */
- if (event->modifiers & down_modifier)
- {
- if (is_double)
- {
- double_click_count++;
- event->modifiers |= ((double_click_count > 2)
- ? triple_modifier
- : double_modifier);
- }
- else
- double_click_count = 1;
- button_down_time = event->timestamp;
- *start_pos_ptr = Fcopy_alist (position);
- }
-
- /* Now we're releasing a button - check the co-ordinates to
- see if this was a click or a drag. */
- else if (event->modifiers & up_modifier)
- {
- /* If we did not see a down before this up,
- ignore the up. Probably this happened because
- the down event chose a menu item.
- It would be an annoyance to treat the release
- of the button that chose the menu item
- as a separate event. */
-
- if (!CONSP (start_pos))
- return Qnil;
-
- event->modifiers &= ~up_modifier;
-#if 0 /* Formerly we treated an up with no down as a click event. */
- if (!CONSP (start_pos))
- event->modifiers |= click_modifier;
- else
-#endif
- {
- /* The third element of every position should be the (x,y)
- pair. */
- Lisp_Object down;
-
- down = Fnth (make_number (2), start_pos);
- if (EQ (event->x, XCONS (down)->car)
- && EQ (event->y, XCONS (down)->cdr))
- {
- event->modifiers |= click_modifier;
- }
- else
- {
- button_down_time = 0;
- event->modifiers |= drag_modifier;
- }
- /* Don't check is_double; treat this as multiple
- if the down-event was multiple. */
- if (double_click_count > 1)
- event->modifiers |= ((double_click_count > 2)
- ? triple_modifier
- : double_modifier);
- }
- }
- else
- /* Every mouse event should either have the down_modifier or
- the up_modifier set. */
- abort ();
-
- {
- /* Get the symbol we should use for the mouse click. */
- Lisp_Object head;
-
- head = modify_event_symbol (button,
- event->modifiers,
- Qmouse_click, Qnil,
- lispy_mouse_names, &mouse_syms,
- (sizeof (lispy_mouse_names)
- / sizeof (lispy_mouse_names[0])));
- if (event->modifiers & drag_modifier)
- return Fcons (head,
- Fcons (start_pos,
- Fcons (position,
- Qnil)));
- else if (event->modifiers & (double_modifier | triple_modifier))
- return Fcons (head,
- Fcons (position,
- Fcons (make_number (double_click_count),
- Qnil)));
- else
- return Fcons (head,
- Fcons (position,
- Qnil));
- }
- }
-
-#ifdef WINDOWSNT
- case w32_scroll_bar_click:
- {
- int button = event->code;
- int is_double;
- Lisp_Object position;
- Lisp_Object *start_pos_ptr;
- Lisp_Object start_pos;
-
- if (button < 0 || button >= NUM_MOUSE_BUTTONS)
- abort ();
-
- {
- Lisp_Object window;
- Lisp_Object portion_whole;
- Lisp_Object part;
-
- window = event->frame_or_window;
- portion_whole = Fcons (event->x, event->y);
- part = *scroll_bar_parts[(int) event->part];
-
- position =
- Fcons (window,
- Fcons (Qvertical_scroll_bar,
- Fcons (portion_whole,
- Fcons (make_number (event->timestamp),
- Fcons (part, Qnil)))));
- }
-
- /* Always treat W32 scroll bar events as clicks. */
- event->modifiers |= click_modifier;
-
- {
- /* Get the symbol we should use for the mouse click. */
- Lisp_Object head;
-
- head = modify_event_symbol (button,
- event->modifiers,
- Qmouse_click, Qnil,
- lispy_mouse_names, &mouse_syms,
- (sizeof (lispy_mouse_names)
- / sizeof (lispy_mouse_names[0])));
- return Fcons (head,
- Fcons (position,
- Qnil));
- }
- }
-#endif
-
-#endif /* HAVE_MOUSE */
-
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
- case menu_bar_event:
- /* The event value is in the cdr of the frame_or_window slot. */
- if (!CONSP (event->frame_or_window))
- abort ();
- return XCONS (event->frame_or_window)->cdr;
-#endif
-
- /* The 'kind' field of the event is something we don't recognize. */
- default:
- abort ();
- }
-}
-
-#ifdef HAVE_MOUSE
-
-static Lisp_Object
-make_lispy_movement (frame, bar_window, part, x, y, time)
- FRAME_PTR frame;
- Lisp_Object bar_window;
- enum scroll_bar_part part;
- Lisp_Object x, y;
- unsigned long time;
-{
- /* Is it a scroll bar movement? */
- if (frame && ! NILP (bar_window))
- {
- Lisp_Object part_sym;
-
- part_sym = *scroll_bar_parts[(int) part];
- return Fcons (Qscroll_bar_movement,
- (Fcons (Fcons (bar_window,
- Fcons (Qvertical_scroll_bar,
- Fcons (Fcons (x, y),
- Fcons (make_number (time),
- Fcons (part_sym,
- Qnil))))),
- Qnil)));
- }
-
- /* Or is it an ordinary mouse movement? */
- else
- {
- int area;
- Lisp_Object window;
- Lisp_Object posn;
- int column, row;
-
- if (frame)
- {
- /* It's in a frame; which window on that frame? */
- pixel_to_glyph_coords (frame, XINT (x), XINT (y), &column, &row,
- NULL, 1);
- window = window_from_coordinates (frame, column, row, &area);
- }
- else
- window = Qnil;
-
- if (WINDOWP (window))
- {
- int pixcolumn, pixrow;
- column -= WINDOW_LEFT_MARGIN (XWINDOW (window));
- row -= XINT (XWINDOW (window)->top);
- glyph_to_pixel_coords (frame, column, row, &pixcolumn, &pixrow);
- XSETINT (x, pixcolumn);
- XSETINT (y, pixrow);
-
- if (area == 1)
- posn = Qmode_line;
- else if (area == 2)
- posn = Qvertical_line;
- else
- XSETINT (posn,
- buffer_posn_from_coords (XWINDOW (window), column, row));
- }
- else if (frame != 0)
- {
- XSETFRAME (window, frame);
- posn = Qnil;
- }
- else
- {
- window = Qnil;
- posn = Qnil;
- XSETFASTINT (x, 0);
- XSETFASTINT (y, 0);
- }
-
- return Fcons (Qmouse_movement,
- Fcons (Fcons (window,
- Fcons (posn,
- Fcons (Fcons (x, y),
- Fcons (make_number (time),
- Qnil)))),
- Qnil));
- }
-}
-
-#endif /* HAVE_MOUSE */
-
-/* Construct a switch frame event. */
-static Lisp_Object
-make_lispy_switch_frame (frame)
- Lisp_Object frame;
-{
- return Fcons (Qswitch_frame, Fcons (frame, Qnil));
-}
-
-/* Manipulating modifiers. */
-
-/* Parse the name of SYMBOL, and return the set of modifiers it contains.
-
- If MODIFIER_END is non-zero, set *MODIFIER_END to the position in
- SYMBOL's name of the end of the modifiers; the string from this
- position is the unmodified symbol name.
-
- This doesn't use any caches. */
-
-static int
-parse_modifiers_uncached (symbol, modifier_end)
- Lisp_Object symbol;
- int *modifier_end;
-{
- struct Lisp_String *name;
- int i;
- int modifiers;
-
- CHECK_SYMBOL (symbol, 1);
-
- modifiers = 0;
- name = XSYMBOL (symbol)->name;
-
- for (i = 0; i+2 <= name->size; )
- {
- int this_mod_end = 0;
- int this_mod = 0;
-
- /* See if the name continues with a modifier word.
- Check that the word appears, but don't check what follows it.
- Set this_mod and this_mod_end to record what we find. */
-
- switch (name->data[i])
- {
-#define SINGLE_LETTER_MOD(BIT) \
- (this_mod_end = i + 1, this_mod = BIT)
-
- case 'A':
- SINGLE_LETTER_MOD (alt_modifier);
- break;
-
- case 'C':
- SINGLE_LETTER_MOD (ctrl_modifier);
- break;
-
- case 'H':
- SINGLE_LETTER_MOD (hyper_modifier);
- break;
-
- case 'M':
- SINGLE_LETTER_MOD (meta_modifier);
- break;
-
- case 'S':
- SINGLE_LETTER_MOD (shift_modifier);
- break;
-
- case 's':
- SINGLE_LETTER_MOD (super_modifier);
- break;
-
-#undef SINGLE_LETTER_MOD
- }
-
- /* If we found no modifier, stop looking for them. */
- if (this_mod_end == 0)
- break;
-
- /* Check there is a dash after the modifier, so that it
- really is a modifier. */
- if (this_mod_end >= name->size || name->data[this_mod_end] != '-')
- break;
-
- /* This modifier is real; look for another. */
- modifiers |= this_mod;
- i = this_mod_end + 1;
- }
-
- /* Should we include the `click' modifier? */
- if (! (modifiers & (down_modifier | drag_modifier
- | double_modifier | triple_modifier))
- && i + 7 == name->size
- && strncmp (name->data + i, "mouse-", 6) == 0
- && ('0' <= name->data[i + 6] && name->data[i + 6] <= '9'))
- modifiers |= click_modifier;
-
- if (modifier_end)
- *modifier_end = i;
-
- return modifiers;
-}
-
-/* Return a symbol whose name is the modifier prefixes for MODIFIERS
- prepended to the string BASE[0..BASE_LEN-1].
- This doesn't use any caches. */
-static Lisp_Object
-apply_modifiers_uncached (modifiers, base, base_len)
- int modifiers;
- char *base;
- int base_len;
-{
- /* Since BASE could contain nulls, we can't use intern here; we have
- to use Fintern, which expects a genuine Lisp_String, and keeps a
- reference to it. */
- char *new_mods =
- (char *) alloca (sizeof ("A-C-H-M-S-s-down-drag-double-triple-"));
- int mod_len;
-
- {
- char *p = new_mods;
-
- /* Only the event queue may use the `up' modifier; it should always
- be turned into a click or drag event before presented to lisp code. */
- if (modifiers & up_modifier)
- abort ();
-
- if (modifiers & alt_modifier) { *p++ = 'A'; *p++ = '-'; }
- if (modifiers & ctrl_modifier) { *p++ = 'C'; *p++ = '-'; }
- if (modifiers & hyper_modifier) { *p++ = 'H'; *p++ = '-'; }
- if (modifiers & meta_modifier) { *p++ = 'M'; *p++ = '-'; }
- if (modifiers & shift_modifier) { *p++ = 'S'; *p++ = '-'; }
- if (modifiers & super_modifier) { *p++ = 's'; *p++ = '-'; }
- if (modifiers & double_modifier) { strcpy (p, "double-"); p += 7; }
- if (modifiers & triple_modifier) { strcpy (p, "triple-"); p += 7; }
- if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; }
- if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; }
- /* The click modifier is denoted by the absence of other modifiers. */
-
- *p = '\0';
-
- mod_len = p - new_mods;
- }
-
- {
- Lisp_Object new_name;
-
- new_name = make_uninit_string (mod_len + base_len);
- bcopy (new_mods, XSTRING (new_name)->data, mod_len);
- bcopy (base, XSTRING (new_name)->data + mod_len, base_len);
-
- return Fintern (new_name, Qnil);
- }
-}
-
-
-static char *modifier_names[] =
-{
- "up", "down", "drag", "click", "double", "triple", 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, "alt", "super", "hyper", "shift", "control", "meta"
-};
-#define NUM_MOD_NAMES (sizeof (modifier_names) / sizeof (modifier_names[0]))
-
-static Lisp_Object modifier_symbols;
-
-/* Return the list of modifier symbols corresponding to the mask MODIFIERS. */
-static Lisp_Object
-lispy_modifier_list (modifiers)
- int modifiers;
-{
- Lisp_Object modifier_list;
- int i;
-
- modifier_list = Qnil;
- for (i = 0; (1<<i) <= modifiers && i < NUM_MOD_NAMES; i++)
- if (modifiers & (1<<i))
- modifier_list = Fcons (XVECTOR (modifier_symbols)->contents[i],
- modifier_list);
-
- return modifier_list;
-}
-
-
-/* Parse the modifiers on SYMBOL, and return a list like (UNMODIFIED MASK),
- where UNMODIFIED is the unmodified form of SYMBOL,
- MASK is the set of modifiers present in SYMBOL's name.
- This is similar to parse_modifiers_uncached, but uses the cache in
- SYMBOL's Qevent_symbol_element_mask property, and maintains the
- Qevent_symbol_elements property. */
-
-static Lisp_Object
-parse_modifiers (symbol)
- Lisp_Object symbol;
-{
- Lisp_Object elements;
-
- elements = Fget (symbol, Qevent_symbol_element_mask);
- if (CONSP (elements))
- return elements;
- else
- {
- int end;
- int modifiers = parse_modifiers_uncached (symbol, &end);
- Lisp_Object unmodified;
- Lisp_Object mask;
-
- unmodified = Fintern (make_string (XSYMBOL (symbol)->name->data + end,
- XSYMBOL (symbol)->name->size - end),
- Qnil);
-
- if (modifiers & ~(((EMACS_INT)1 << VALBITS) - 1))
- abort ();
- XSETFASTINT (mask, modifiers);
- elements = Fcons (unmodified, Fcons (mask, Qnil));
-
- /* Cache the parsing results on SYMBOL. */
- Fput (symbol, Qevent_symbol_element_mask,
- elements);
- Fput (symbol, Qevent_symbol_elements,
- Fcons (unmodified, lispy_modifier_list (modifiers)));
-
- /* Since we know that SYMBOL is modifiers applied to unmodified,
- it would be nice to put that in unmodified's cache.
- But we can't, since we're not sure that parse_modifiers is
- canonical. */
-
- return elements;
- }
-}
-
-/* Apply the modifiers MODIFIERS to the symbol BASE.
- BASE must be unmodified.
-
- This is like apply_modifiers_uncached, but uses BASE's
- Qmodifier_cache property, if present. It also builds
- Qevent_symbol_elements properties, since it has that info anyway.
-
- apply_modifiers copies the value of BASE's Qevent_kind property to
- the modified symbol. */
-static Lisp_Object
-apply_modifiers (modifiers, base)
- int modifiers;
- Lisp_Object base;
-{
- Lisp_Object cache, index, entry, new_symbol;
-
- /* Mask out upper bits. We don't know where this value's been. */
- modifiers &= ((EMACS_INT)1 << VALBITS) - 1;
-
- /* The click modifier never figures into cache indices. */
- cache = Fget (base, Qmodifier_cache);
- XSETFASTINT (index, (modifiers & ~click_modifier));
- entry = assq_no_quit (index, cache);
-
- if (CONSP (entry))
- new_symbol = XCONS (entry)->cdr;
- else
- {
- /* We have to create the symbol ourselves. */
- new_symbol = apply_modifiers_uncached (modifiers,
- XSYMBOL (base)->name->data,
- XSYMBOL (base)->name->size);
-
- /* Add the new symbol to the base's cache. */
- entry = Fcons (index, new_symbol);
- Fput (base, Qmodifier_cache, Fcons (entry, cache));
-
- /* We have the parsing info now for free, so add it to the caches. */
- XSETFASTINT (index, modifiers);
- Fput (new_symbol, Qevent_symbol_element_mask,
- Fcons (base, Fcons (index, Qnil)));
- Fput (new_symbol, Qevent_symbol_elements,
- Fcons (base, lispy_modifier_list (modifiers)));
- }
-
- /* Make sure this symbol is of the same kind as BASE.
-
- You'd think we could just set this once and for all when we
- intern the symbol above, but reorder_modifiers may call us when
- BASE's property isn't set right; we can't assume that just
- because it has a Qmodifier_cache property it must have its
- Qevent_kind set right as well. */
- if (NILP (Fget (new_symbol, Qevent_kind)))
- {
- Lisp_Object kind;
-
- kind = Fget (base, Qevent_kind);
- if (! NILP (kind))
- Fput (new_symbol, Qevent_kind, kind);
- }
-
- return new_symbol;
-}
-
-
-/* Given a symbol whose name begins with modifiers ("C-", "M-", etc),
- return a symbol with the modifiers placed in the canonical order.
- Canonical order is alphabetical, except for down and drag, which
- always come last. The 'click' modifier is never written out.
-
- Fdefine_key calls this to make sure that (for example) C-M-foo
- and M-C-foo end up being equivalent in the keymap. */
-
-Lisp_Object
-reorder_modifiers (symbol)
- Lisp_Object symbol;
-{
- /* It's hopefully okay to write the code this way, since everything
- will soon be in caches, and no consing will be done at all. */
- Lisp_Object parsed;
-
- parsed = parse_modifiers (symbol);
- return apply_modifiers ((int) XINT (XCONS (XCONS (parsed)->cdr)->car),
- XCONS (parsed)->car);
-}
-
-
-/* For handling events, we often want to produce a symbol whose name
- is a series of modifier key prefixes ("M-", "C-", etcetera) attached
- to some base, like the name of a function key or mouse button.
- modify_event_symbol produces symbols of this sort.
-
- NAME_TABLE should point to an array of strings, such that NAME_TABLE[i]
- is the name of the i'th symbol. TABLE_SIZE is the number of elements
- in the table.
-
- Alternatively, NAME_ALIST is an alist mapping codes into symbol names.
- NAME_ALIST is used if it is non-nil; otherwise NAME_TABLE is used.
-
- SYMBOL_TABLE should be a pointer to a Lisp_Object whose value will
- persist between calls to modify_event_symbol that it can use to
- store a cache of the symbols it's generated for this NAME_TABLE
- before. The object stored there may be a vector or an alist.
-
- SYMBOL_NUM is the number of the base name we want from NAME_TABLE.
-
- MODIFIERS is a set of modifier bits (as given in struct input_events)
- whose prefixes should be applied to the symbol name.
-
- SYMBOL_KIND is the value to be placed in the event_kind property of
- the returned symbol.
-
- The symbols we create are supposed to have an
- `event-symbol-elements' property, which lists the modifiers present
- in the symbol's name. */
-
-static Lisp_Object
-modify_event_symbol (symbol_num, modifiers, symbol_kind, name_alist,
- name_table, symbol_table, table_size)
- int symbol_num;
- unsigned modifiers;
- Lisp_Object symbol_kind;
- Lisp_Object name_alist;
- char **name_table;
- Lisp_Object *symbol_table;
- unsigned int table_size;
-{
- Lisp_Object value;
- Lisp_Object symbol_int;
-
- /* Get rid of the "vendor-specific" bit here. */
- XSETINT (symbol_int, symbol_num & 0xffffff);
-
- /* Is this a request for a valid symbol? */
- if (symbol_num < 0 || symbol_num >= table_size)
- return Qnil;
-
- if (CONSP (*symbol_table))
- value = Fcdr (assq_no_quit (symbol_int, *symbol_table));
-
- /* If *symbol_table doesn't seem to be initialized properly, fix that.
- *symbol_table should be a lisp vector TABLE_SIZE elements long,
- where the Nth element is the symbol for NAME_TABLE[N], or nil if
- we've never used that symbol before. */
- else
- {
- if (! VECTORP (*symbol_table)
- || XVECTOR (*symbol_table)->size != table_size)
- {
- Lisp_Object size;
-
- XSETFASTINT (size, table_size);
- *symbol_table = Fmake_vector (size, Qnil);
- }
-
- value = XVECTOR (*symbol_table)->contents[symbol_num];
- }
-
- /* Have we already used this symbol before? */
- if (NILP (value))
- {
- /* No; let's create it. */
- if (!NILP (name_alist))
- value = Fcdr_safe (Fassq (symbol_int, name_alist));
- else if (name_table != 0 && name_table[symbol_num])
- value = intern (name_table[symbol_num]);
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (NILP (value))
- {
- char *name = x_get_keysym_name (symbol_num);
- if (name)
- value = intern (name);
- }
-#endif
-
- if (NILP (value))
- {
- char buf[20];
- sprintf (buf, "key-%d", symbol_num);
- value = intern (buf);
- }
-
- if (CONSP (*symbol_table))
- *symbol_table = Fcons (Fcons (symbol_int, value), *symbol_table);
- else
- XVECTOR (*symbol_table)->contents[symbol_num] = value;
-
- /* Fill in the cache entries for this symbol; this also
- builds the Qevent_symbol_elements property, which the user
- cares about. */
- apply_modifiers (modifiers & click_modifier, value);
- Fput (value, Qevent_kind, symbol_kind);
- }
-
- /* Apply modifiers to that symbol. */
- return apply_modifiers (modifiers, value);
-}
-
-/* Convert a list that represents an event type,
- such as (ctrl meta backspace), into the usual representation of that
- event type as a number or a symbol. */
-
-DEFUN ("event-convert-list", Fevent_convert_list, Sevent_convert_list, 1, 1, 0,
- "Convert the event description list EVENT-DESC to an event type.\n\
-EVENT-DESC should contain one base event type (a character or symbol)\n\
-and zero or more modifier names (control, meta, hyper, super, shift, alt,\n\
-drag, down, double or triple). The base must be last.\n\
-The return value is an event type (a character or symbol) which\n\
-has the same base event type and all the specified modifiers.")
- (event_desc)
- Lisp_Object event_desc;
-{
- Lisp_Object base;
- int modifiers = 0;
- Lisp_Object rest;
-
- base = Qnil;
- rest = event_desc;
- while (CONSP (rest))
- {
- Lisp_Object elt;
- int this = 0;
-
- elt = XCONS (rest)->car;
- rest = XCONS (rest)->cdr;
-
- /* Given a symbol, see if it is a modifier name. */
- if (SYMBOLP (elt) && CONSP (rest))
- this = parse_solitary_modifier (elt);
-
- if (this != 0)
- modifiers |= this;
- else if (!NILP (base))
- error ("Two bases given in one event");
- else
- base = elt;
-
- }
-
- /* Let the symbol A refer to the character A. */
- if (SYMBOLP (base) && XSYMBOL (base)->name->size == 1)
- XSETINT (base, XSYMBOL (base)->name->data[0]);
-
- if (INTEGERP (base))
- {
- /* Turn (shift a) into A. */
- if ((modifiers & shift_modifier) != 0
- && (XINT (base) >= 'a' && XINT (base) <= 'z'))
- {
- XSETINT (base, XINT (base) - ('a' - 'A'));
- modifiers &= ~shift_modifier;
- }
-
- /* Turn (control a) into C-a. */
- if (modifiers & ctrl_modifier)
- return make_number ((modifiers & ~ctrl_modifier)
- | make_ctrl_char (XINT (base)));
- else
- return make_number (modifiers | XINT (base));
- }
- else if (SYMBOLP (base))
- return apply_modifiers (modifiers, base);
- else
- error ("Invalid base event");
-}
-
-/* Try to recognize SYMBOL as a modifier name.
- Return the modifier flag bit, or 0 if not recognized. */
-
-static int
-parse_solitary_modifier (symbol)
- Lisp_Object symbol;
-{
- struct Lisp_String *name = XSYMBOL (symbol)->name;
-
- switch (name->data[0])
- {
-#define SINGLE_LETTER_MOD(BIT) \
- if (name->size == 1) \
- return BIT;
-
-#define MULTI_LETTER_MOD(BIT, NAME, LEN) \
- if (LEN == name->size \
- && ! strncmp (name->data, NAME, LEN)) \
- return BIT;
-
- case 'A':
- SINGLE_LETTER_MOD (alt_modifier);
- break;
-
- case 'a':
- MULTI_LETTER_MOD (alt_modifier, "alt", 3);
- break;
-
- case 'C':
- SINGLE_LETTER_MOD (ctrl_modifier);
- break;
-
- case 'c':
- MULTI_LETTER_MOD (ctrl_modifier, "ctrl", 4);
- MULTI_LETTER_MOD (ctrl_modifier, "control", 7);
- break;
-
- case 'H':
- SINGLE_LETTER_MOD (hyper_modifier);
- break;
-
- case 'h':
- MULTI_LETTER_MOD (hyper_modifier, "hyper", 5);
- break;
-
- case 'M':
- SINGLE_LETTER_MOD (meta_modifier);
- break;
-
- case 'm':
- MULTI_LETTER_MOD (meta_modifier, "meta", 4);
- break;
-
- case 'S':
- SINGLE_LETTER_MOD (shift_modifier);
- break;
-
- case 's':
- MULTI_LETTER_MOD (shift_modifier, "shift", 5);
- MULTI_LETTER_MOD (super_modifier, "super", 5);
- SINGLE_LETTER_MOD (super_modifier);
- break;
-
- case 'd':
- MULTI_LETTER_MOD (drag_modifier, "drag", 4);
- MULTI_LETTER_MOD (down_modifier, "down", 4);
- MULTI_LETTER_MOD (double_modifier, "double", 6);
- break;
-
- case 't':
- MULTI_LETTER_MOD (triple_modifier, "triple", 6);
- break;
-
-#undef SINGLE_LETTER_MOD
-#undef MULTI_LETTER_MOD
- }
-
- return 0;
-}
-
-/* Return 1 if EVENT is a list whose elements are all integers or symbols.
- Such a list is not valid as an event,
- but it can be a Lucid-style event type list. */
-
-int
-lucid_event_type_list_p (object)
- Lisp_Object object;
-{
- Lisp_Object tail;
-
- if (! CONSP (object))
- return 0;
-
- for (tail = object; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- Lisp_Object elt;
- elt = XCONS (tail)->car;
- if (! (INTEGERP (elt) || SYMBOLP (elt)))
- return 0;
- }
-
- return NILP (tail);
-}
-
-/* Store into *addr a value nonzero if terminal input chars are available.
- Serves the purpose of ioctl (0, FIONREAD, addr)
- but works even if FIONREAD does not exist.
- (In fact, this may actually read some input.)
-
- If DO_TIMERS_NOW is nonzero, actually run timer events that are ripe. */
-
-static void
-get_input_pending (addr, do_timers_now)
- int *addr;
- int do_timers_now;
-{
- /* First of all, have we already counted some input? */
- *addr = !NILP (Vquit_flag) || readable_events (do_timers_now);
-
- /* If input is being read as it arrives, and we have none, there is none. */
- if (*addr > 0 || (interrupt_input && ! interrupts_deferred))
- return;
-
- /* Try to read some input and see how much we get. */
- gobble_input (0);
- *addr = !NILP (Vquit_flag) || readable_events (do_timers_now);
-}
-
-/* Interface to read_avail_input, blocking SIGIO or SIGALRM if necessary. */
-
-int
-gobble_input (expected)
- int expected;
-{
-#ifndef VMS
-#ifdef SIGIO
- if (interrupt_input)
- {
- SIGMASKTYPE mask;
- mask = sigblock (sigmask (SIGIO));
- read_avail_input (expected);
- sigsetmask (mask);
- }
- else
-#ifdef POLL_FOR_INPUT
- if (read_socket_hook && !interrupt_input && poll_suppress_count == 0)
- {
- SIGMASKTYPE mask;
- mask = sigblock (sigmask (SIGALRM));
- read_avail_input (expected);
- sigsetmask (mask);
- }
- else
-#endif
-#endif
- read_avail_input (expected);
-#endif
-}
-
-/* Put a buffer_switch_event in the buffer
- so that read_key_sequence will notice the new current buffer. */
-
-record_asynch_buffer_change ()
-{
- struct input_event event;
- Lisp_Object tem;
-
- event.kind = buffer_switch_event;
- event.frame_or_window = Qnil;
-
-#ifdef subprocesses
- /* We don't need a buffer-switch event unless Emacs is waiting for input.
- The purpose of the event is to make read_key_sequence look up the
- keymaps again. If we aren't in read_key_sequence, we don't need one,
- and the event could cause trouble by messing up (input-pending-p). */
- tem = Fwaiting_for_user_input_p ();
- if (NILP (tem))
- return;
-#else
- /* We never need these events if we have no asynchronous subprocesses. */
- return;
-#endif
-
- /* Make sure no interrupt happens while storing the event. */
-#ifdef SIGIO
- if (interrupt_input)
- {
- SIGMASKTYPE mask;
- mask = sigblock (sigmask (SIGIO));
- kbd_buffer_store_event (&event);
- sigsetmask (mask);
- }
- else
-#endif
- {
- stop_polling ();
- kbd_buffer_store_event (&event);
- start_polling ();
- }
-}
-
-#ifndef VMS
-
-/* Read any terminal input already buffered up by the system
- into the kbd_buffer, but do not wait.
-
- EXPECTED should be nonzero if the caller knows there is some input.
-
- Except on VMS, all input is read by this function.
- If interrupt_input is nonzero, this function MUST be called
- only when SIGIO is blocked.
-
- Returns the number of keyboard chars read, or -1 meaning
- this is a bad time to try to read input. */
-
-static int
-read_avail_input (expected)
- int expected;
-{
- struct input_event buf[KBD_BUFFER_SIZE];
- register int i;
- int nread;
-
- if (read_socket_hook)
- /* No need for FIONREAD or fcntl; just say don't wait. */
- nread = (*read_socket_hook) (input_fd, buf, KBD_BUFFER_SIZE, expected);
- else
- {
- /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
- the kbd_buffer can really hold. That may prevent loss
- of characters on some systems when input is stuffed at us. */
- unsigned char cbuf[KBD_BUFFER_SIZE - 1];
- int n_to_read;
-
- /* Determine how many characters we should *try* to read. */
-#ifdef WINDOWSNT
- return 0;
-#else /* not WINDOWSNT */
-#ifdef MSDOS
- n_to_read = dos_keysns ();
- if (n_to_read == 0)
- return 0;
-#else /* not MSDOS */
-#ifdef FIONREAD
- /* Find out how much input is available. */
- if (ioctl (input_fd, FIONREAD, &n_to_read) < 0)
- /* Formerly simply reported no input, but that sometimes led to
- a failure of Emacs to terminate.
- SIGHUP seems appropriate if we can't reach the terminal. */
- /* ??? Is it really right to send the signal just to this process
- rather than to the whole process group?
- Perhaps on systems with FIONREAD Emacs is alone in its group. */
- kill (getpid (), SIGHUP);
- if (n_to_read == 0)
- return 0;
- if (n_to_read > sizeof cbuf)
- n_to_read = sizeof cbuf;
-#else /* no FIONREAD */
-#if defined (USG) || defined (DGUX)
- /* Read some input if available, but don't wait. */
- n_to_read = sizeof cbuf;
- fcntl (input_fd, F_SETFL, O_NDELAY);
-#else
- you lose;
-#endif
-#endif
-#endif /* not MSDOS */
-#endif /* not WINDOWSNT */
-
- /* Now read; for one reason or another, this will not block.
- NREAD is set to the number of chars read. */
- do
- {
-#ifdef MSDOS
- cbuf[0] = dos_keyread ();
- nread = 1;
-#else
- nread = read (input_fd, cbuf, n_to_read);
-#endif
-#if defined (AIX) && (! defined (aix386) && defined (_BSD))
- /* 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 (0, SIGHUP);
-#endif
- }
- while (
- /* We used to retry the read if it was interrupted.
- But this does the wrong thing when O_NDELAY causes
- an EAGAIN error. Does anybody know of a situation
- where a retry is actually needed? */
-#if 0
- nread < 0 && (errno == EAGAIN
-#ifdef EFAULT
- || errno == EFAULT
-#endif
-#ifdef EBADSLT
- || errno == EBADSLT
-#endif
- )
-#else
- 0
-#endif
- );
-
-#ifndef FIONREAD
-#if defined (USG) || defined (DGUX)
- fcntl (input_fd, F_SETFL, 0);
-#endif /* USG or DGUX */
-#endif /* no FIONREAD */
- for (i = 0; i < nread; i++)
- {
- buf[i].kind = ascii_keystroke;
- buf[i].modifiers = 0;
- if (meta_key == 1 && (cbuf[i] & 0x80))
- buf[i].modifiers = meta_modifier;
- if (meta_key != 2)
- cbuf[i] &= ~0x80;
-
- buf[i].code = cbuf[i];
- XSETFRAME (buf[i].frame_or_window, selected_frame);
- }
- }
-
- /* Scan the chars for C-g and store them in kbd_buffer. */
- for (i = 0; i < nread; i++)
- {
- kbd_buffer_store_event (&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].kind == ascii_keystroke
- && buf[i].code == quit_char)
- break;
- }
-
- return nread;
-}
-#endif /* not VMS */
-
-#ifdef SIGIO /* for entire page */
-/* Note SIGIO has been undef'd if FIONREAD is missing. */
-
-SIGTYPE
-input_available_signal (signo)
- int signo;
-{
- /* Must preserve main program's value of errno. */
- int old_errno = errno;
-#ifdef BSD4_1
- extern int select_alarmed;
-#endif
-
-#if defined (USG) && !defined (POSIX_SIGNALS)
- /* 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_time)
- EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
-
- while (1)
- {
- int nread;
- nread = read_avail_input (1);
- /* -1 means it's not ok to read the input now.
- UNBLOCK_INPUT will read it later; now, avoid infinite loop.
- 0 means there was no keyboard input available. */
- if (nread <= 0)
- break;
-
-#ifdef BSD4_1
- select_alarmed = 1; /* Force the select emulator back to life */
-#endif
- }
-
-#ifdef BSD4_1
- sigfree ();
-#endif
- errno = old_errno;
-}
-#endif /* SIGIO */
-
-/* Send ourselves a SIGIO.
-
- This function exists so that the UNBLOCK_INPUT macro in
- blockinput.h can have some way to take care of input we put off
- dealing with, without assuming that every file which uses
- UNBLOCK_INPUT also has #included the files necessary to get SIGIO. */
-void
-reinvoke_input_signal ()
-{
-#ifdef SIGIO
- kill (getpid (), SIGIO);
-#endif
-}
-
-
-
-/* Return the prompt-string of a sparse keymap.
- This is the first element which is a string.
- Return nil if there is none. */
-
-Lisp_Object
-map_prompt (map)
- Lisp_Object map;
-{
- while (CONSP (map))
- {
- register Lisp_Object tem;
- tem = Fcar (map);
- if (STRINGP (tem))
- return tem;
- map = Fcdr (map);
- }
- return Qnil;
-}
-
-static void menu_bar_item ();
-static void menu_bar_one_keymap ();
-
-/* These variables hold the vector under construction within
- menu_bar_items and its subroutines, and the current index
- for storing into that vector. */
-static Lisp_Object menu_bar_items_vector;
-static int menu_bar_items_index;
-
-/* Return a vector of menu items for a menu bar, appropriate
- to the current buffer. Each item has three elements in the vector:
- KEY STRING MAPLIST.
-
- OLD is an old vector we can optionally reuse, or nil. */
-
-Lisp_Object
-menu_bar_items (old)
- Lisp_Object old;
-{
- /* The number of keymaps we're scanning right now, and the number of
- keymaps we have allocated space for. */
- int nmaps;
-
- /* maps[0..nmaps-1] are the prefix definitions of KEYBUF[0..t-1]
- in the current keymaps, or nil where it is not a prefix. */
- Lisp_Object *maps;
-
- Lisp_Object def, tem, tail;
-
- Lisp_Object result;
-
- int mapno;
- Lisp_Object oquit;
-
- int i;
-
- struct gcpro gcpro1;
-
- /* In order to build the menus, we need to call the keymap
- accessors. They all call QUIT. But this function is called
- during redisplay, during which a quit is fatal. So inhibit
- quitting while building the menus.
- We do this instead of specbind because (1) errors will clear it anyway
- and (2) this avoids risk of specpdl overflow. */
- oquit = Vinhibit_quit;
- Vinhibit_quit = Qt;
-
- if (!NILP (old))
- menu_bar_items_vector = old;
- else
- menu_bar_items_vector = Fmake_vector (make_number (24), Qnil);
- menu_bar_items_index = 0;
-
- GCPRO1 (menu_bar_items_vector);
-
- /* Build our list of keymaps.
- If we recognize a function key and replace its escape sequence in
- keybuf with its symbol, or if the sequence starts with a mouse
- click and we need to switch buffers, we jump back here to rebuild
- the initial keymaps from the current buffer. */
- {
- Lisp_Object *tmaps;
-
- /* Should overriding-terminal-local-map and overriding-local-map apply? */
- if (!NILP (Voverriding_local_map_menu_flag))
- {
- /* Yes, use them (if non-nil) as well as the global map. */
- maps = (Lisp_Object *) alloca (3 * sizeof (maps[0]));
- nmaps = 0;
- if (!NILP (current_kboard->Voverriding_terminal_local_map))
- maps[nmaps++] = current_kboard->Voverriding_terminal_local_map;
- if (!NILP (Voverriding_local_map))
- maps[nmaps++] = Voverriding_local_map;
- }
- else
- {
- /* No, so use major and minor mode keymaps. */
- nmaps = current_minor_maps (NULL, &tmaps);
- maps = (Lisp_Object *) alloca ((nmaps + 2) * sizeof (maps[0]));
- bcopy (tmaps, maps, nmaps * sizeof (maps[0]));
-#ifdef USE_TEXT_PROPERTIES
- maps[nmaps++] = get_local_map (PT, current_buffer);
-#else
- maps[nmaps++] = current_buffer->keymap;
-#endif
- }
- maps[nmaps++] = current_global_map;
- }
-
- /* Look up in each map the dummy prefix key `menu-bar'. */
-
- result = Qnil;
-
- for (mapno = nmaps - 1; mapno >= 0; mapno--)
- {
- if (! NILP (maps[mapno]))
- def = get_keyelt (access_keymap (maps[mapno], Qmenu_bar, 1, 0));
- else
- def = Qnil;
-
- tem = Fkeymapp (def);
- if (!NILP (tem))
- menu_bar_one_keymap (def);
- }
-
- /* Move to the end those items that should be at the end. */
-
- for (tail = Vmenu_bar_final_items; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- int i;
- int end = menu_bar_items_index;
-
- for (i = 0; i < end; i += 4)
- if (EQ (XCONS (tail)->car, XVECTOR (menu_bar_items_vector)->contents[i]))
- {
- Lisp_Object tem0, tem1, tem2, tem3;
- /* Move the item at index I to the end,
- shifting all the others forward. */
- tem0 = XVECTOR (menu_bar_items_vector)->contents[i + 0];
- tem1 = XVECTOR (menu_bar_items_vector)->contents[i + 1];
- tem2 = XVECTOR (menu_bar_items_vector)->contents[i + 2];
- tem3 = XVECTOR (menu_bar_items_vector)->contents[i + 3];
- if (end > i + 4)
- bcopy (&XVECTOR (menu_bar_items_vector)->contents[i + 4],
- &XVECTOR (menu_bar_items_vector)->contents[i],
- (end - i - 4) * sizeof (Lisp_Object));
- XVECTOR (menu_bar_items_vector)->contents[end - 4] = tem0;
- XVECTOR (menu_bar_items_vector)->contents[end - 3] = tem1;
- XVECTOR (menu_bar_items_vector)->contents[end - 2] = tem2;
- XVECTOR (menu_bar_items_vector)->contents[end - 1] = tem3;
- break;
- }
- }
-
- /* Add nil, nil, nil, nil at the end. */
- i = menu_bar_items_index;
- if (i + 4 > XVECTOR (menu_bar_items_vector)->size)
- {
- Lisp_Object tem;
- int newsize = 2 * i;
- tem = Fmake_vector (make_number (2 * i), Qnil);
- bcopy (XVECTOR (menu_bar_items_vector)->contents,
- XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
- menu_bar_items_vector = tem;
- }
- /* Add this item. */
- XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
- XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
- XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
- XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
- menu_bar_items_index = i;
-
- Vinhibit_quit = oquit;
- UNGCPRO;
- return menu_bar_items_vector;
-}
-
-/* Scan one map KEYMAP, accumulating any menu items it defines
- in menu_bar_items_vector. */
-
-static void
-menu_bar_one_keymap (keymap)
- Lisp_Object keymap;
-{
- Lisp_Object tail, item, key, binding, item_string, table;
-
- /* Loop over all keymap entries that have menu strings. */
- for (tail = keymap; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- item = XCONS (tail)->car;
- if (CONSP (item))
- {
- key = XCONS (item)->car;
- binding = XCONS (item)->cdr;
- if (CONSP (binding))
- {
- item_string = XCONS (binding)->car;
- if (STRINGP (item_string))
- menu_bar_item (key, item_string, Fcdr (binding));
- }
- else if (EQ (binding, Qundefined))
- menu_bar_item (key, Qnil, binding);
- }
- else if (VECTORP (item))
- {
- /* Loop over the char values represented in the vector. */
- int len = XVECTOR (item)->size;
- int c;
- for (c = 0; c < len; c++)
- {
- Lisp_Object character;
- XSETFASTINT (character, c);
- binding = XVECTOR (item)->contents[c];
- if (CONSP (binding))
- {
- item_string = XCONS (binding)->car;
- if (STRINGP (item_string))
- menu_bar_item (key, item_string, Fcdr (binding));
- }
- else if (EQ (binding, Qundefined))
- menu_bar_item (key, Qnil, binding);
- }
- }
- }
-}
-
-/* This is used as the handler when calling internal_condition_case_1. */
-
-static Lisp_Object
-menu_bar_item_1 (arg)
- Lisp_Object arg;
-{
- return Qnil;
-}
-
-/* Add one item to menu_bar_items_vector, for KEY, ITEM_STRING and DEF.
- If there's already an item for KEY, add this DEF to it. */
-
-static void
-menu_bar_item (key, item_string, def)
- Lisp_Object key, item_string, def;
-{
- Lisp_Object tem;
- Lisp_Object enabled;
- int i;
-
- /* Skip menu-bar equiv keys data. */
- if (CONSP (def) && CONSP (XCONS (def)->car))
- def = XCONS (def)->cdr;
-
- if (EQ (def, Qundefined))
- {
- /* If a map has an explicit `undefined' as definition,
- discard any previously made menu bar item. */
-
- for (i = 0; i < menu_bar_items_index; i += 4)
- if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i]))
- {
- if (menu_bar_items_index > i + 4)
- bcopy (&XVECTOR (menu_bar_items_vector)->contents[i + 4],
- &XVECTOR (menu_bar_items_vector)->contents[i],
- (menu_bar_items_index - i - 4) * sizeof (Lisp_Object));
- menu_bar_items_index -= 4;
- return;
- }
-
- /* If there's no definition for this key yet,
- just ignore `undefined'. */
- return;
- }
-
- /* See if this entry is enabled. */
- enabled = Qt;
-
- if (SYMBOLP (def))
- {
- /* No property, or nil, means enable.
- Otherwise, enable if value is not nil. */
- tem = Fget (def, Qmenu_enable);
- if (!NILP (tem))
- /* (condition-case nil (eval tem)
- (error nil)) */
- enabled = internal_condition_case_1 (Feval, tem, Qerror,
- menu_bar_item_1);
- }
-
- /* Ignore this item if it's not enabled. */
- if (NILP (enabled))
- return;
-
- /* Find any existing item for this KEY. */
- for (i = 0; i < menu_bar_items_index; i += 4)
- if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i]))
- break;
-
- /* If we did not find this KEY, add it at the end. */
- if (i == menu_bar_items_index)
- {
- /* If vector is too small, get a bigger one. */
- if (i + 4 > XVECTOR (menu_bar_items_vector)->size)
- {
- Lisp_Object tem;
- int newsize = 2 * i;
- tem = Fmake_vector (make_number (2 * i), Qnil);
- bcopy (XVECTOR (menu_bar_items_vector)->contents,
- XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
- menu_bar_items_vector = tem;
- }
- /* Add this item. */
- XVECTOR (menu_bar_items_vector)->contents[i++] = key;
- XVECTOR (menu_bar_items_vector)->contents[i++] = item_string;
- XVECTOR (menu_bar_items_vector)->contents[i++] = Fcons (def, Qnil);
- XVECTOR (menu_bar_items_vector)->contents[i++] = make_number (0);
- menu_bar_items_index = i;
- }
- /* We did find an item for this KEY. Add DEF to its list of maps. */
- else
- {
- Lisp_Object old;
- old = XVECTOR (menu_bar_items_vector)->contents[i + 2];
- XVECTOR (menu_bar_items_vector)->contents[i + 2] = Fcons (def, old);
- }
-}
-
-/* Read a character using menus based on maps in the array MAPS.
- NMAPS is the length of MAPS. Return nil if there are no menus in the maps.
- Return t if we displayed a menu but the user rejected it.
-
- PREV_EVENT is the previous input event, or nil if we are reading
- the first event of a key sequence.
-
- If USED_MOUSE_MENU is non-null, then we set *USED_MOUSE_MENU to 1
- if we used a mouse menu to read the input, or zero otherwise. If
- USED_MOUSE_MENU is null, we don't dereference it.
-
- The prompting is done based on the prompt-string of the map
- and the strings associated with various map elements.
-
- This can be done with X menus or with menus put in the minibuf.
- These are done in different ways, depending on how the input will be read.
- Menus using X are done after auto-saving in read-char, getting the input
- event from Fx_popup_menu; menus using the minibuf use read_char recursively
- and do auto-saving in the inner call of read_char. */
-
-static Lisp_Object
-read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
- int nmaps;
- Lisp_Object *maps;
- Lisp_Object prev_event;
- int *used_mouse_menu;
-{
- int mapno;
- register Lisp_Object name;
- Lisp_Object rest, vector;
-
- if (used_mouse_menu)
- *used_mouse_menu = 0;
-
- /* Use local over global Menu maps */
-
- if (! menu_prompting)
- return Qnil;
-
- /* Optionally disregard all but the global map. */
- if (inhibit_local_menu_bar_menus)
- {
- maps += (nmaps - 1);
- nmaps = 1;
- }
-
- /* Get the menu name from the first map that has one (a prompt string). */
- for (mapno = 0; mapno < nmaps; mapno++)
- {
- name = map_prompt (maps[mapno]);
- if (!NILP (name))
- break;
- }
-
- /* If we don't have any menus, just read a character normally. */
- if (mapno >= nmaps)
- return Qnil;
-
-#ifdef HAVE_MENUS
- /* If we got to this point via a mouse click,
- use a real menu for mouse selection. */
- if (EVENT_HAS_PARAMETERS (prev_event)
- && !EQ (XCONS (prev_event)->car, Qmenu_bar))
- {
- /* Display the menu and get the selection. */
- Lisp_Object *realmaps
- = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
- Lisp_Object value;
- int nmaps1 = 0;
-
- /* Use the maps that are not nil. */
- for (mapno = 0; mapno < nmaps; mapno++)
- if (!NILP (maps[mapno]))
- realmaps[nmaps1++] = maps[mapno];
-
- value = Fx_popup_menu (prev_event, Flist (nmaps1, realmaps));
- if (CONSP (value))
- {
- Lisp_Object tem;
-
- record_menu_key (XCONS (value)->car);
-
- /* If we got multiple events, unread all but
- the first.
- There is no way to prevent those unread events
- from showing up later in last_nonmenu_event.
- So turn symbol and integer events into lists,
- to indicate that they came from a mouse menu,
- so that when present in last_nonmenu_event
- they won't confuse things. */
- for (tem = XCONS (value)->cdr; !NILP (tem);
- tem = XCONS (tem)->cdr)
- {
- record_menu_key (XCONS (tem)->car);
- if (SYMBOLP (XCONS (tem)->car)
- || INTEGERP (XCONS (tem)->car))
- XCONS (tem)->car
- = Fcons (XCONS (tem)->car, Qnil);
- }
-
- /* If we got more than one event, put all but the first
- onto this list to be read later.
- Return just the first event now. */
- Vunread_command_events
- = nconc2 (XCONS (value)->cdr, Vunread_command_events);
- value = XCONS (value)->car;
- }
- else if (NILP (value))
- value = Qt;
- if (used_mouse_menu)
- *used_mouse_menu = 1;
- return value;
- }
-#endif /* HAVE_MENUS */
- return Qnil ;
-}
-
-/* Buffer in use so far for the minibuf prompts for menu keymaps.
- We make this bigger when necessary, and never free it. */
-static char *read_char_minibuf_menu_text;
-/* Size of that buffer. */
-static int read_char_minibuf_menu_width;
-
-static Lisp_Object
-read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
- int commandflag ;
- int nmaps;
- Lisp_Object *maps;
-{
- int mapno;
- register Lisp_Object name;
- int nlength;
- int width = FRAME_WIDTH (selected_frame) - 4;
- int idx = -1;
- int nobindings = 1;
- Lisp_Object rest, vector;
- char *menu;
-
- if (! menu_prompting)
- return Qnil;
-
- /* Make sure we have a big enough buffer for the menu text. */
- if (read_char_minibuf_menu_text == 0)
- {
- read_char_minibuf_menu_width = width + 4;
- read_char_minibuf_menu_text = (char *) xmalloc (width + 4);
- }
- else if (width + 4 > read_char_minibuf_menu_width)
- {
- read_char_minibuf_menu_width = width + 4;
- read_char_minibuf_menu_text
- = (char *) xrealloc (read_char_minibuf_menu_text, width + 4);
- }
- menu = read_char_minibuf_menu_text;
-
- /* Get the menu name from the first map that has one (a prompt string). */
- for (mapno = 0; mapno < nmaps; mapno++)
- {
- name = map_prompt (maps[mapno]);
- if (!NILP (name))
- break;
- }
-
- /* If we don't have any menus, just read a character normally. */
- if (mapno >= nmaps)
- return Qnil;
-
- /* Prompt string always starts with map's prompt, and a space. */
- strcpy (menu, XSTRING (name)->data);
- nlength = XSTRING (name)->size;
- menu[nlength++] = ':';
- menu[nlength++] = ' ';
- menu[nlength] = 0;
-
- /* Start prompting at start of first map. */
- mapno = 0;
- rest = maps[mapno];
-
- /* Present the documented bindings, a line at a time. */
- while (1)
- {
- int notfirst = 0;
- int i = nlength;
- Lisp_Object obj;
- int ch;
- Lisp_Object orig_defn_macro;
-
- /* Loop over elements of map. */
- while (i < width)
- {
- Lisp_Object s, elt;
-
- /* If reached end of map, start at beginning of next map. */
- if (NILP (rest))
- {
- mapno++;
- /* At end of last map, wrap around to first map if just starting,
- or end this line if already have something on it. */
- if (mapno == nmaps)
- {
- mapno = 0;
- if (notfirst || nobindings) break;
- }
- rest = maps[mapno];
- }
-
- /* Look at the next element of the map. */
- if (idx >= 0)
- elt = XVECTOR (vector)->contents[idx];
- else
- elt = Fcar_safe (rest);
-
- if (idx < 0 && VECTORP (elt))
- {
- /* If we found a dense table in the keymap,
- advanced past it, but start scanning its contents. */
- rest = Fcdr_safe (rest);
- vector = elt;
- idx = 0;
- }
- else
- {
- /* An ordinary element. */
- Lisp_Object event;
-
- if (idx < 0)
- {
- s = Fcar_safe (Fcdr_safe (elt)); /* alist */
- event = Fcar_safe (elt);
- }
- else
- {
- s = Fcar_safe (elt); /* vector */
- XSETINT (event, idx);
- }
-
- /* Ignore the element if it has no prompt string. */
- if (STRINGP (s) && INTEGERP (event))
- {
- /* 1 if the char to type matches the string. */
- int char_matches;
- Lisp_Object upcased_event, downcased_event;
- Lisp_Object desc;
-
- upcased_event = Fupcase (event);
- downcased_event = Fdowncase (event);
- char_matches = (XINT (upcased_event) == XSTRING (s)->data[0]
- || XINT (downcased_event) == XSTRING (s)->data[0]);
- if (! char_matches)
- desc = Fsingle_key_description (event);
-
- /* If we have room for the prompt string, add it to this line.
- If this is the first on the line, always add it. */
- if ((XSTRING (s)->size + i + 2
- + (char_matches ? 0 : XSTRING (desc)->size + 3))
- < width
- || !notfirst)
- {
- int thiswidth;
-
- /* Punctuate between strings. */
- if (notfirst)
- {
- strcpy (menu + i, ", ");
- i += 2;
- }
- notfirst = 1;
- nobindings = 0 ;
-
- /* If the char to type doesn't match the string's
- first char, explicitly show what char to type. */
- if (! char_matches)
- {
- /* Add as much of string as fits. */
- thiswidth = XSTRING (desc)->size;
- if (thiswidth + i > width)
- thiswidth = width - i;
- bcopy (XSTRING (desc)->data, menu + i, thiswidth);
- i += thiswidth;
- strcpy (menu + i, " = ");
- i += 3;
- }
-
- /* Add as much of string as fits. */
- thiswidth = XSTRING (s)->size;
- if (thiswidth + i > width)
- thiswidth = width - i;
- bcopy (XSTRING (s)->data, menu + i, thiswidth);
- i += thiswidth;
- menu[i] = 0;
- }
- else
- {
- /* If this element does not fit, end the line now,
- and save the element for the next line. */
- strcpy (menu + i, "...");
- break;
- }
- }
-
- /* Move past this element. */
- if (idx >= 0 && idx + 1 >= XVECTOR (vector)->size)
- /* Handle reaching end of dense table. */
- idx = -1;
- if (idx >= 0)
- idx++;
- else
- rest = Fcdr_safe (rest);
- }
- }
-
- /* Prompt with that and read response. */
- message1 (menu);
-
- /* Make believe its not a keyboard macro in case the help char
- is pressed. Help characters are not recorded because menu prompting
- is not used on replay.
- */
- orig_defn_macro = current_kboard->defining_kbd_macro;
- current_kboard->defining_kbd_macro = Qnil;
- do
- obj = read_char (commandflag, 0, 0, Qnil, 0);
- while (BUFFERP (obj));
- current_kboard->defining_kbd_macro = orig_defn_macro;
-
- if (!INTEGERP (obj))
- return obj;
- else
- ch = XINT (obj);
-
- if (! EQ (obj, menu_prompt_more_char)
- && (!INTEGERP (menu_prompt_more_char)
- || ! EQ (obj, make_number (Ctl (XINT (menu_prompt_more_char))))))
- {
- if (!NILP (current_kboard->defining_kbd_macro))
- store_kbd_macro_char (obj);
- return obj;
- }
- /* Help char - go round again */
- }
-}
-
-/* Reading key sequences. */
-
-/* Follow KEY in the maps in CURRENT[0..NMAPS-1], placing its bindings
- in DEFS[0..NMAPS-1]. Set NEXT[i] to DEFS[i] if DEFS[i] is a
- keymap, or nil otherwise. Return the index of the first keymap in
- which KEY has any binding, or NMAPS if no map has a binding.
-
- If KEY is a meta ASCII character, treat it like meta-prefix-char
- followed by the corresponding non-meta character. Keymaps in
- CURRENT with non-prefix bindings for meta-prefix-char become nil in
- NEXT.
-
- If KEY has no bindings in any of the CURRENT maps, NEXT is left
- unmodified.
-
- NEXT may be the same array as CURRENT. */
-
-static int
-follow_key (key, nmaps, current, defs, next)
- Lisp_Object key;
- Lisp_Object *current, *defs, *next;
- int nmaps;
-{
- int i, first_binding;
- int did_meta = 0;
-
- /* If KEY is a meta ASCII character, treat it like meta-prefix-char
- followed by the corresponding non-meta character.
- Put the results into DEFS, since we are going to alter that anyway.
- Do not alter CURRENT or NEXT. */
- if (INTEGERP (key) && (XINT (key) & CHAR_META))
- {
- for (i = 0; i < nmaps; i++)
- if (! NILP (current[i]))
- {
- Lisp_Object def;
- def = get_keyelt (access_keymap (current[i],
- meta_prefix_char, 1, 0));
-
- /* Note that since we pass the resulting bindings through
- get_keymap_1, non-prefix bindings for meta-prefix-char
- disappear. */
- defs[i] = get_keymap_1 (def, 0, 1);
- }
- else
- defs[i] = Qnil;
-
- did_meta = 1;
- XSETINT (key, XFASTINT (key) & ~CHAR_META);
- }
-
- first_binding = nmaps;
- for (i = nmaps - 1; i >= 0; i--)
- {
- if (! NILP (current[i]))
- {
- Lisp_Object map;
- if (did_meta)
- map = defs[i];
- else
- map = current[i];
-
- defs[i] = get_keyelt (access_keymap (map, key, 1, 0));
- if (! NILP (defs[i]))
- first_binding = i;
- }
- else
- defs[i] = Qnil;
- }
-
- /* Given the set of bindings we've found, produce the next set of maps. */
- if (first_binding < nmaps)
- for (i = 0; i < nmaps; i++)
- next[i] = NILP (defs[i]) ? Qnil : get_keymap_1 (defs[i], 0, 1);
-
- return first_binding;
-}
-
-/* Read a sequence of keys that ends with a non prefix character,
- storing it in KEYBUF, a buffer of size BUFSIZE.
- Prompt with PROMPT.
- Return the length of the key sequence stored.
- Return -1 if the user rejected a command menu.
-
- Echo starting immediately unless `prompt' is 0.
-
- Where a key sequence ends depends on the currently active keymaps.
- These include any minor mode keymaps active in the current buffer,
- the current buffer's local map, and the global map.
-
- If a key sequence has no other bindings, we check Vfunction_key_map
- to see if some trailing subsequence might be the beginning of a
- function key's sequence. If so, we try to read the whole function
- key, and substitute its symbolic name into the key sequence.
-
- We ignore unbound `down-' mouse clicks. We turn unbound `drag-' and
- `double-' events into similar click events, if that would make them
- bound. We try to turn `triple-' events first into `double-' events,
- then into clicks.
-
- If we get a mouse click in a mode line, vertical divider, or other
- non-text area, we treat the click as if it were prefixed by the
- symbol denoting that area - `mode-line', `vertical-line', or
- whatever.
-
- If the sequence starts with a mouse click, we read the key sequence
- with respect to the buffer clicked on, not the current buffer.
-
- If the user switches frames in the midst of a key sequence, we put
- off the switch-frame event until later; the next call to
- read_char will return it. */
-
-static int
-read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
- can_return_switch_frame)
- Lisp_Object *keybuf;
- int bufsize;
- Lisp_Object prompt;
- int dont_downcase_last;
- int can_return_switch_frame;
-{
- int count = specpdl_ptr - specpdl;
-
- /* How many keys there are in the current key sequence. */
- int t;
-
- /* The length of the echo buffer when we started reading, and
- the length of this_command_keys when we started reading. */
- int echo_start;
- int keys_start;
-
- /* The number of keymaps we're scanning right now, and the number of
- keymaps we have allocated space for. */
- int nmaps;
- int nmaps_allocated = 0;
-
- /* defs[0..nmaps-1] are the definitions of KEYBUF[0..t-1] in
- the current keymaps. */
- Lisp_Object *defs;
-
- /* submaps[0..nmaps-1] are the prefix definitions of KEYBUF[0..t-1]
- in the current keymaps, or nil where it is not a prefix. */
- Lisp_Object *submaps;
-
- /* The local map to start out with at start of key sequence. */
- Lisp_Object orig_local_map;
-
- /* 1 if we have already considered switching to the local-map property
- of the place where a mouse click occurred. */
- int localized_local_map = 0;
-
- /* The index in defs[] of the first keymap that has a binding for
- this key sequence. In other words, the lowest i such that
- defs[i] is non-nil. */
- int first_binding;
-
- /* If t < mock_input, then KEYBUF[t] should be read as the next
- input key.
-
- We use this to recover after recognizing a function key. Once we
- realize that a suffix of the current key sequence is actually a
- function key's escape sequence, we replace the suffix with the
- function key's binding from Vfunction_key_map. Now keybuf
- contains a new and different key sequence, so the echo area,
- this_command_keys, and the submaps and defs arrays are wrong. In
- this situation, we set mock_input to t, set t to 0, and jump to
- restart_sequence; the loop will read keys from keybuf up until
- mock_input, thus rebuilding the state; and then it will resume
- reading characters from the keyboard. */
- int mock_input = 0;
-
- /* If the sequence is unbound in submaps[], then
- keybuf[fkey_start..fkey_end-1] is a prefix in Vfunction_key_map,
- and fkey_map is its binding.
-
- These might be > t, indicating that all function key scanning
- should hold off until t reaches them. We do this when we've just
- recognized a function key, to avoid searching for the function
- key's again in Vfunction_key_map. */
- int fkey_start = 0, fkey_end = 0;
- Lisp_Object fkey_map;
-
- /* Likewise, for key_translation_map. */
- int keytran_start = 0, keytran_end = 0;
- Lisp_Object keytran_map;
-
- /* If we receive a ``switch-frame'' event in the middle of a key sequence,
- we put it off for later. While we're reading, we keep the event here. */
- Lisp_Object delayed_switch_frame;
-
- /* See the comment below... */
-#if defined (GOBBLE_FIRST_EVENT)
- Lisp_Object first_event;
-#endif
-
- Lisp_Object original_uppercase;
- int original_uppercase_position = -1;
-
- /* Gets around Microsoft compiler limitations. */
- int dummyflag = 0;
-
- struct buffer *starting_buffer;
-
- /* Nonzero if we seem to have got the beginning of a binding
- in function_key_map. */
- int function_key_possible = 0;
- int key_translation_possible = 0;
-
- /* Save the status of key translation before each step,
- so that we can restore this after downcasing. */
- Lisp_Object prev_fkey_map;
- Lisp_Object prev_fkey_start;
- Lisp_Object prev_fkey_end;
-
- Lisp_Object prev_keytran_map;
- Lisp_Object prev_keytran_start;
- Lisp_Object prev_keytran_end;
-
- int junk;
-
- last_nonmenu_event = Qnil;
-
- delayed_switch_frame = Qnil;
- fkey_map = Vfunction_key_map;
- keytran_map = Vkey_translation_map;
-
- /* If there is no function-key-map, turn off function key scanning. */
- if (NILP (Fkeymapp (Vfunction_key_map)))
- fkey_start = fkey_end = bufsize + 1;
-
- /* If there is no key-translation-map, turn off scanning. */
- if (NILP (Fkeymapp (Vkey_translation_map)))
- keytran_start = keytran_end = bufsize + 1;
-
- if (INTERACTIVE)
- {
- if (!NILP (prompt))
- echo_prompt (XSTRING (prompt)->data);
- else if (cursor_in_echo_area && echo_keystrokes)
- /* This doesn't put in a dash if the echo buffer is empty, so
- you don't always see a dash hanging out in the minibuffer. */
- echo_dash ();
- }
-
- /* Record the initial state of the echo area and this_command_keys;
- we will need to restore them if we replay a key sequence. */
- if (INTERACTIVE)
- echo_start = echo_length ();
- keys_start = this_command_key_count;
- this_single_command_key_start = keys_start;
-
-#if defined (GOBBLE_FIRST_EVENT)
- /* This doesn't quite work, because some of the things that read_char
- does cannot safely be bypassed. It seems too risky to try to make
- this work right. */
-
- /* Read the first char of the sequence specially, before setting
- up any keymaps, in case a filter runs and switches buffers on us. */
- first_event = read_char (NILP (prompt), 0, submaps, last_nonmenu_event,
- &junk);
-#endif /* GOBBLE_FIRST_EVENT */
-
- orig_local_map = get_local_map (PT, current_buffer);
-
- /* We jump here when the key sequence has been thoroughly changed, and
- we need to rescan it starting from the beginning. When we jump here,
- keybuf[0..mock_input] holds the sequence we should reread. */
- replay_sequence:
-
- starting_buffer = current_buffer;
- function_key_possible = 0;
- key_translation_possible = 0;
-
- /* Build our list of keymaps.
- If we recognize a function key and replace its escape sequence in
- keybuf with its symbol, or if the sequence starts with a mouse
- click and we need to switch buffers, we jump back here to rebuild
- the initial keymaps from the current buffer. */
- {
- Lisp_Object *maps;
-
- if (!NILP (current_kboard->Voverriding_terminal_local_map)
- || !NILP (Voverriding_local_map))
- {
- if (3 > nmaps_allocated)
- {
- submaps = (Lisp_Object *) alloca (3 * sizeof (submaps[0]));
- defs = (Lisp_Object *) alloca (3 * sizeof (defs[0]));
- nmaps_allocated = 3;
- }
- nmaps = 0;
- if (!NILP (current_kboard->Voverriding_terminal_local_map))
- submaps[nmaps++] = current_kboard->Voverriding_terminal_local_map;
- if (!NILP (Voverriding_local_map))
- submaps[nmaps++] = Voverriding_local_map;
- }
- else
- {
- nmaps = current_minor_maps (0, &maps);
- if (nmaps + 2 > nmaps_allocated)
- {
- submaps = (Lisp_Object *) alloca ((nmaps+2) * sizeof (submaps[0]));
- defs = (Lisp_Object *) alloca ((nmaps+2) * sizeof (defs[0]));
- nmaps_allocated = nmaps + 2;
- }
- bcopy (maps, submaps, nmaps * sizeof (submaps[0]));
-#ifdef USE_TEXT_PROPERTIES
- submaps[nmaps++] = orig_local_map;
-#else
- submaps[nmaps++] = current_buffer->keymap;
-#endif
- }
- submaps[nmaps++] = current_global_map;
- }
-
- /* Find an accurate initial value for first_binding. */
- for (first_binding = 0; first_binding < nmaps; first_binding++)
- if (! NILP (submaps[first_binding]))
- break;
-
- /* Start from the beginning in keybuf. */
- t = 0;
-
- /* These are no-ops the first time through, but if we restart, they
- revert the echo area and this_command_keys to their original state. */
- this_command_key_count = keys_start;
- if (INTERACTIVE && t < mock_input)
- echo_truncate (echo_start);
-
- /* If the best binding for the current key sequence is a keymap, or
- we may be looking at a function key's escape sequence, keep on
- reading. */
- while ((first_binding < nmaps && ! NILP (submaps[first_binding]))
- || (first_binding >= nmaps
- && fkey_start < t
- /* mock input is never part of a function key's sequence. */
- && mock_input <= fkey_start)
- || (first_binding >= nmaps
- && keytran_start < t && key_translation_possible)
- /* Don't return in the middle of a possible function key sequence,
- if the only bindings we found were via case conversion.
- Thus, if ESC O a has a function-key-map translation
- and ESC o has a binding, don't return after ESC O,
- so that we can translate ESC O plus the next character. */
- )
- {
- Lisp_Object key;
- int used_mouse_menu = 0;
-
- /* Where the last real key started. If we need to throw away a
- key that has expanded into more than one element of keybuf
- (say, a mouse click on the mode line which is being treated
- as [mode-line (mouse-...)], then we backtrack to this point
- of keybuf. */
- int last_real_key_start;
-
- /* These variables are analogous to echo_start and keys_start;
- while those allow us to restart the entire key sequence,
- echo_local_start and keys_local_start allow us to throw away
- just one key. */
- int echo_local_start, keys_local_start, local_first_binding;
-
- if (t >= bufsize)
- error ("Key sequence too long");
-
- if (INTERACTIVE)
- echo_local_start = echo_length ();
- keys_local_start = this_command_key_count;
- local_first_binding = first_binding;
-
- replay_key:
- /* These are no-ops, unless we throw away a keystroke below and
- jumped back up to replay_key; in that case, these restore the
- variables to their original state, allowing us to replay the
- loop. */
- if (INTERACTIVE && t < mock_input)
- echo_truncate (echo_local_start);
- this_command_key_count = keys_local_start;
- first_binding = local_first_binding;
-
- /* By default, assume each event is "real". */
- last_real_key_start = t;
-
- /* Does mock_input indicate that we are re-reading a key sequence? */
- if (t < mock_input)
- {
- key = keybuf[t];
- add_command_key (key);
- if (echo_keystrokes)
- echo_char (key);
- }
-
- /* If not, we should actually read a character. */
- else
- {
- struct buffer *buf = current_buffer;
-
- {
-#ifdef MULTI_KBOARD
- KBOARD *interrupted_kboard = current_kboard;
- struct frame *interrupted_frame = selected_frame;
- if (setjmp (wrong_kboard_jmpbuf))
- {
- if (!NILP (delayed_switch_frame))
- {
- interrupted_kboard->kbd_queue
- = Fcons (delayed_switch_frame,
- interrupted_kboard->kbd_queue);
- delayed_switch_frame = Qnil;
- }
- while (t > 0)
- interrupted_kboard->kbd_queue
- = Fcons (keybuf[--t], interrupted_kboard->kbd_queue);
-
- /* If the side queue is non-empty, ensure it begins with a
- switch-frame, so we'll replay it in the right context. */
- if (CONSP (interrupted_kboard->kbd_queue)
- && (key = XCONS (interrupted_kboard->kbd_queue)->car,
- !(EVENT_HAS_PARAMETERS (key)
- && EQ (EVENT_HEAD_KIND (EVENT_HEAD (key)),
- Qswitch_frame))))
- {
- Lisp_Object frame;
- XSETFRAME (frame, interrupted_frame);
- interrupted_kboard->kbd_queue
- = Fcons (make_lispy_switch_frame (frame),
- interrupted_kboard->kbd_queue);
- }
- mock_input = 0;
- orig_local_map = get_local_map (PT, current_buffer);
- goto replay_sequence;
- }
-#endif
- key = read_char (NILP (prompt), nmaps, submaps, last_nonmenu_event,
- &used_mouse_menu);
- }
-
- /* read_char returns t when it shows a menu and the user rejects it.
- Just return -1. */
- if (EQ (key, Qt))
- return -1;
-
- /* read_char returns -1 at the end of a macro.
- Emacs 18 handles this by returning immediately with a
- zero, so that's what we'll do. */
- if (INTEGERP (key) && XINT (key) == -1)
- {
- t = 0;
- /* The Microsoft C compiler can't handle the goto that
- would go here. */
- dummyflag = 1;
- break;
- }
-
- /* If the current buffer has been changed from under us, the
- keymap may have changed, so replay the sequence. */
- if (BUFFERP (key))
- {
- mock_input = t;
- orig_local_map = get_local_map (PT, current_buffer);
- goto replay_sequence;
- }
-
- /* If we have a quit that was typed in another frame, and
- quit_throw_to_read_char switched buffers,
- replay to get the right keymap. */
- if (XINT (key) == quit_char && current_buffer != starting_buffer)
- {
- keybuf[t++] = key;
- mock_input = t;
- Vquit_flag = Qnil;
- orig_local_map = get_local_map (PT, current_buffer);
- goto replay_sequence;
- }
-
- Vquit_flag = Qnil;
- }
-
- /* Clicks in non-text areas get prefixed by the symbol
- in their CHAR-ADDRESS field. For example, a click on
- the mode line is prefixed by the symbol `mode-line'.
-
- Furthermore, key sequences beginning with mouse clicks
- are read using the keymaps of the buffer clicked on, not
- the current buffer. So we may have to switch the buffer
- here.
-
- When we turn one event into two events, we must make sure
- that neither of the two looks like the original--so that,
- if we replay the events, they won't be expanded again.
- If not for this, such reexpansion could happen either here
- or when user programs play with this-command-keys. */
- if (EVENT_HAS_PARAMETERS (key))
- {
- Lisp_Object kind;
-
- kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
- if (EQ (kind, Qmouse_click))
- {
- Lisp_Object window, posn;
-
- window = POSN_WINDOW (EVENT_START (key));
- posn = POSN_BUFFER_POSN (EVENT_START (key));
- if (CONSP (posn))
- {
- /* We're looking at the second event of a
- sequence which we expanded before. Set
- last_real_key_start appropriately. */
- if (t > 0)
- last_real_key_start = t - 1;
- }
-
- /* Key sequences beginning with mouse clicks are
- read using the keymaps in the buffer clicked on,
- not the current buffer. If we're at the
- beginning of a key sequence, switch buffers. */
- if (last_real_key_start == 0
- && WINDOWP (window)
- && BUFFERP (XWINDOW (window)->buffer)
- && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
- {
- keybuf[t] = key;
- mock_input = t + 1;
-
- /* Arrange to go back to the original buffer once we're
- done reading the key sequence. Note that we can't
- use save_excursion_{save,restore} here, because they
- save point as well as the current buffer; we don't
- want to save point, because redisplay may change it,
- to accommodate a Fset_window_start or something. We
- don't want to do this at the top of the function,
- because we may get input from a subprocess which
- wants to change the selected window and stuff (say,
- emacsclient). */
- record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
-
- set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
- orig_local_map = get_local_map (PT, current_buffer);
- goto replay_sequence;
- }
- /* For a mouse click, get the local text-property keymap
- of the place clicked on, rather than point. */
- if (last_real_key_start == 0 && CONSP (XCONS (key)->cdr)
- && ! localized_local_map)
- {
- Lisp_Object map_here, start, pos;
-
- localized_local_map = 1;
- start = EVENT_START (key);
- if (CONSP (start) && CONSP (XCONS (start)->cdr))
- {
- pos = POSN_BUFFER_POSN (start);
- if (INTEGERP (pos)
- && XINT (pos) >= BEG && XINT (pos) <= Z)
- {
- map_here = get_local_map (XINT (pos), current_buffer);
- if (!EQ (map_here, orig_local_map))
- {
- orig_local_map = map_here;
- keybuf[t] = key;
- mock_input = t + 1;
-
- goto replay_sequence;
- }
- }
- }
- }
-
- /* Expand mode-line and scroll-bar events into two events:
- use posn as a fake prefix key. */
- if (SYMBOLP (posn))
- {
- if (t + 1 >= bufsize)
- error ("Key sequence too long");
- keybuf[t] = posn;
- keybuf[t+1] = key;
- mock_input = t + 2;
-
- /* Zap the position in key, so we know that we've
- expanded it, and don't try to do so again. */
- POSN_BUFFER_POSN (EVENT_START (key))
- = Fcons (posn, Qnil);
- goto replay_key;
- }
- }
- else if (EQ (kind, Qswitch_frame))
- {
- /* If we're at the beginning of a key sequence, and the caller
- says it's okay, go ahead and return this event. If we're
- in the midst of a key sequence, delay it until the end. */
- if (t > 0 || !can_return_switch_frame)
- {
- delayed_switch_frame = key;
- goto replay_key;
- }
- }
- else if (CONSP (XCONS (key)->cdr)
- && CONSP (EVENT_START (key))
- && CONSP (XCONS (EVENT_START (key))->cdr))
- {
- Lisp_Object posn;
-
- posn = POSN_BUFFER_POSN (EVENT_START (key));
- /* Handle menu-bar events:
- insert the dummy prefix event `menu-bar'. */
- if (EQ (posn, Qmenu_bar))
- {
- if (t + 1 >= bufsize)
- error ("Key sequence too long");
- keybuf[t] = posn;
- keybuf[t+1] = key;
-
- /* Zap the position in key, so we know that we've
- expanded it, and don't try to do so again. */
- POSN_BUFFER_POSN (EVENT_START (key))
- = Fcons (posn, Qnil);
-
- mock_input = t + 2;
- goto replay_sequence;
- }
- else if (CONSP (posn))
- {
- /* We're looking at the second event of a
- sequence which we expanded before. Set
- last_real_key_start appropriately. */
- if (last_real_key_start == t && t > 0)
- last_real_key_start = t - 1;
- }
- }
- }
-
- /* We have finally decided that KEY is something we might want
- to look up. */
- first_binding = (follow_key (key,
- nmaps - first_binding,
- submaps + first_binding,
- defs + first_binding,
- submaps + first_binding)
- + first_binding);
-
- /* If KEY wasn't bound, we'll try some fallbacks. */
- if (first_binding >= nmaps)
- {
- Lisp_Object head;
-
- head = EVENT_HEAD (key);
- if (help_char_p (head) && t > 0)
- {
- read_key_sequence_cmd = Vprefix_help_command;
- keybuf[t++] = key;
- last_nonmenu_event = key;
- /* The Microsoft C compiler can't handle the goto that
- would go here. */
- dummyflag = 1;
- break;
- }
-
- if (SYMBOLP (head))
- {
- Lisp_Object breakdown;
- int modifiers;
-
- breakdown = parse_modifiers (head);
- modifiers = XINT (XCONS (XCONS (breakdown)->cdr)->car);
- /* Attempt to reduce an unbound mouse event to a simpler
- event that is bound:
- Drags reduce to clicks.
- Double-clicks reduce to clicks.
- Triple-clicks reduce to double-clicks, then to clicks.
- Down-clicks are eliminated.
- Double-downs reduce to downs, then are eliminated.
- Triple-downs reduce to double-downs, then to downs,
- then are eliminated. */
- if (modifiers & (down_modifier | drag_modifier
- | double_modifier | triple_modifier))
- {
- while (modifiers & (down_modifier | drag_modifier
- | double_modifier | triple_modifier))
- {
- Lisp_Object new_head, new_click;
- if (modifiers & triple_modifier)
- modifiers ^= (double_modifier | triple_modifier);
- else if (modifiers & double_modifier)
- modifiers &= ~double_modifier;
- else if (modifiers & drag_modifier)
- modifiers &= ~drag_modifier;
- else
- {
- /* Dispose of this `down' event by simply jumping
- back to replay_key, to get another event.
-
- Note that if this event came from mock input,
- then just jumping back to replay_key will just
- hand it to us again. So we have to wipe out any
- mock input.
-
- We could delete keybuf[t] and shift everything
- after that to the left by one spot, but we'd also
- have to fix up any variable that points into
- keybuf, and shifting isn't really necessary
- anyway.
-
- Adding prefixes for non-textual mouse clicks
- creates two characters of mock input, and both
- must be thrown away. If we're only looking at
- the prefix now, we can just jump back to
- replay_key. On the other hand, if we've already
- processed the prefix, and now the actual click
- itself is giving us trouble, then we've lost the
- state of the keymaps we want to backtrack to, and
- we need to replay the whole sequence to rebuild
- it.
-
- Beyond that, only function key expansion could
- create more than two keys, but that should never
- generate mouse events, so it's okay to zero
- mock_input in that case too.
-
- Isn't this just the most wonderful code ever? */
- if (t == last_real_key_start)
- {
- mock_input = 0;
- goto replay_key;
- }
- else
- {
- mock_input = last_real_key_start;
- goto replay_sequence;
- }
- }
-
- new_head
- = apply_modifiers (modifiers, XCONS (breakdown)->car);
- new_click
- = Fcons (new_head, Fcons (EVENT_START (key), Qnil));
-
- /* Look for a binding for this new key. follow_key
- promises that it didn't munge submaps the
- last time we called it, since key was unbound. */
- first_binding
- = (follow_key (new_click,
- nmaps - local_first_binding,
- submaps + local_first_binding,
- defs + local_first_binding,
- submaps + local_first_binding)
- + local_first_binding);
-
- /* If that click is bound, go for it. */
- if (first_binding < nmaps)
- {
- key = new_click;
- break;
- }
- /* Otherwise, we'll leave key set to the drag event. */
- }
- }
- }
- }
-
- keybuf[t++] = key;
- /* Normally, last_nonmenu_event gets the previous key we read.
- But when a mouse popup menu is being used,
- we don't update last_nonmenu_event; it continues to hold the mouse
- event that preceded the first level of menu. */
- if (!used_mouse_menu)
- last_nonmenu_event = key;
-
- /* Record what part of this_command_keys is the current key sequence. */
- this_single_command_key_start = this_command_key_count - t;
-
- prev_fkey_map = fkey_map;
- prev_fkey_start = fkey_start;
- prev_fkey_end = fkey_end;
-
- prev_keytran_map = keytran_map;
- prev_keytran_start = keytran_start;
- prev_keytran_end = keytran_end;
-
- /* If the sequence is unbound, see if we can hang a function key
- off the end of it. We only want to scan real keyboard input
- for function key sequences, so if mock_input says that we're
- re-reading old events, don't examine it. */
- if (first_binding >= nmaps
- && t >= mock_input)
- {
- Lisp_Object fkey_next;
-
- /* Continue scan from fkey_end until we find a bound suffix.
- If we fail, increment fkey_start
- and start fkey_end from there. */
- while (fkey_end < t)
- {
- Lisp_Object key;
-
- key = keybuf[fkey_end++];
- /* Look up meta-characters by prefixing them
- with meta_prefix_char. I hate this. */
- if (INTEGERP (key) && XINT (key) & meta_modifier)
- {
- fkey_next
- = get_keymap_1
- (get_keyelt
- (access_keymap (fkey_map, meta_prefix_char, 1, 0)),
- 0, 1);
- XSETFASTINT (key, XFASTINT (key) & ~meta_modifier);
- }
- else
- fkey_next = fkey_map;
-
- fkey_next
- = get_keyelt (access_keymap (fkey_next, key, 1, 0));
-
-#if 0 /* I didn't turn this on, because it might cause trouble
- for the mapping of return into C-m and tab into C-i. */
- /* Optionally don't map function keys into other things.
- This enables the user to redefine kp- keys easily. */
- if (SYMBOLP (key) && !NILP (Vinhibit_function_key_mapping))
- fkey_next = Qnil;
-#endif
-
- /* If the function key map gives a function, not an
- array, then call the function with no args and use
- its value instead. */
- if (SYMBOLP (fkey_next) && ! NILP (Ffboundp (fkey_next))
- && fkey_end == t)
- {
- struct gcpro gcpro1, gcpro2, gcpro3;
- Lisp_Object tem;
- tem = fkey_next;
-
- GCPRO3 (fkey_map, keytran_map, delayed_switch_frame);
- fkey_next = call1 (fkey_next, prompt);
- UNGCPRO;
- /* If the function returned something invalid,
- barf--don't ignore it.
- (To ignore it safely, we would need to gcpro a bunch of
- other variables.) */
- if (! (VECTORP (fkey_next) || STRINGP (fkey_next)))
- error ("Function in key-translation-map returns invalid key sequence");
- }
-
- function_key_possible = ! NILP (fkey_next);
-
- /* If keybuf[fkey_start..fkey_end] is bound in the
- function key map and it's a suffix of the current
- sequence (i.e. fkey_end == t), replace it with
- the binding and restart with fkey_start at the end. */
- if ((VECTORP (fkey_next) || STRINGP (fkey_next))
- && fkey_end == t)
- {
- int len = XFASTINT (Flength (fkey_next));
-
- t = fkey_start + len;
- if (t >= bufsize)
- error ("Key sequence too long");
-
- if (VECTORP (fkey_next))
- bcopy (XVECTOR (fkey_next)->contents,
- keybuf + fkey_start,
- (t - fkey_start) * sizeof (keybuf[0]));
- else if (STRINGP (fkey_next))
- {
- int i;
-
- for (i = 0; i < len; i++)
- XSETFASTINT (keybuf[fkey_start + i],
- XSTRING (fkey_next)->data[i]);
- }
-
- mock_input = t;
- fkey_start = fkey_end = t;
- fkey_map = Vfunction_key_map;
-
- /* Do pass the results through key-translation-map. */
- keytran_start = keytran_end = 0;
- keytran_map = Vkey_translation_map;
-
- goto replay_sequence;
- }
-
- fkey_map = get_keymap_1 (fkey_next, 0, 1);
-
- /* If we no longer have a bound suffix, try a new positions for
- fkey_start. */
- if (NILP (fkey_map))
- {
- fkey_end = ++fkey_start;
- fkey_map = Vfunction_key_map;
- function_key_possible = 0;
- }
- }
- }
-
- /* Look for this sequence in key-translation-map. */
- {
- Lisp_Object keytran_next;
-
- /* Scan from keytran_end until we find a bound suffix. */
- while (keytran_end < t)
- {
- Lisp_Object key;
-
- key = keybuf[keytran_end++];
- /* Look up meta-characters by prefixing them
- with meta_prefix_char. I hate this. */
- if (INTEGERP (key) && XINT (key) & meta_modifier)
- {
- keytran_next
- = get_keymap_1
- (get_keyelt
- (access_keymap (keytran_map, meta_prefix_char, 1, 0)),
- 0, 1);
- XSETFASTINT (key, XFASTINT (key) & ~meta_modifier);
- }
- else
- keytran_next = keytran_map;
-
- keytran_next
- = get_keyelt (access_keymap (keytran_next, key, 1, 0));
-
- /* If the key translation map gives a function, not an
- array, then call the function with no args and use
- its value instead. */
- if (SYMBOLP (keytran_next) && ! NILP (Ffboundp (keytran_next))
- && keytran_end == t)
- {
- struct gcpro gcpro1, gcpro2, gcpro3;
- Lisp_Object tem;
- tem = keytran_next;
-
- GCPRO3 (fkey_map, keytran_map, delayed_switch_frame);
- keytran_next = call1 (keytran_next, prompt);
- UNGCPRO;
- /* If the function returned something invalid,
- barf--don't ignore it.
- (To ignore it safely, we would need to gcpro a bunch of
- other variables.) */
- if (! (VECTORP (keytran_next) || STRINGP (keytran_next)))
- error ("Function in key-translation-map returns invalid key sequence");
- }
-
- key_translation_possible = ! NILP (keytran_next);
-
- /* If keybuf[keytran_start..keytran_end] is bound in the
- key translation map and it's a suffix of the current
- sequence (i.e. keytran_end == t), replace it with
- the binding and restart with keytran_start at the end. */
- if ((VECTORP (keytran_next) || STRINGP (keytran_next))
- && keytran_end == t)
- {
- int len = XFASTINT (Flength (keytran_next));
-
- t = keytran_start + len;
- if (t >= bufsize)
- error ("Key sequence too long");
-
- if (VECTORP (keytran_next))
- bcopy (XVECTOR (keytran_next)->contents,
- keybuf + keytran_start,
- (t - keytran_start) * sizeof (keybuf[0]));
- else if (STRINGP (keytran_next))
- {
- int i;
-
- for (i = 0; i < len; i++)
- XSETFASTINT (keybuf[keytran_start + i],
- XSTRING (keytran_next)->data[i]);
- }
-
- mock_input = t;
- keytran_start = keytran_end = t;
- keytran_map = Vkey_translation_map;
-
- /* Don't pass the results of key-translation-map
- through function-key-map. */
- fkey_start = fkey_end = t;
- fkey_map = Vkey_translation_map;
-
- goto replay_sequence;
- }
-
- keytran_map = get_keymap_1 (keytran_next, 0, 1);
-
- /* If we no longer have a bound suffix, try a new positions for
- keytran_start. */
- if (NILP (keytran_map))
- {
- keytran_end = ++keytran_start;
- keytran_map = Vkey_translation_map;
- key_translation_possible = 0;
- }
- }
- }
-
- /* If KEY is not defined in any of the keymaps,
- and cannot be part of a function key or translation,
- and is an upper case letter
- use the corresponding lower-case letter instead. */
- if (first_binding == nmaps && ! function_key_possible
- && ! key_translation_possible
- && INTEGERP (key)
- && ((((XINT (key) & 0x3ffff)
- < XSTRING (current_buffer->downcase_table)->size)
- && UPPERCASEP (XINT (key) & 0x3ffff))
- || (XINT (key) & shift_modifier)))
- {
- Lisp_Object new_key;
-
- original_uppercase = key;
- original_uppercase_position = t - 1;
-
- if (XINT (key) & shift_modifier)
- XSETINT (new_key, XINT (key) & ~shift_modifier);
- else
- XSETINT (new_key, (DOWNCASE (XINT (key) & 0x3ffff)
- | (XINT (key) & ~0x3ffff)));
-
- /* We have to do this unconditionally, regardless of whether
- the lower-case char is defined in the keymaps, because they
- might get translated through function-key-map. */
- keybuf[t - 1] = new_key;
- mock_input = t;
-
- fkey_map = prev_fkey_map;
- fkey_start = prev_fkey_start;
- fkey_end = prev_fkey_end;
-
- keytran_map = prev_keytran_map;
- keytran_start = prev_keytran_start;
- keytran_end = prev_keytran_end;
-
- goto replay_sequence;
- }
- /* If KEY is not defined in any of the keymaps,
- and cannot be part of a function key or translation,
- and is a shifted function key,
- use the corresponding unshifted function key instead. */
- if (first_binding == nmaps && ! function_key_possible
- && ! key_translation_possible
- && SYMBOLP (key))
- {
- Lisp_Object breakdown;
- int modifiers;
-
- breakdown = parse_modifiers (key);
- modifiers = XINT (XCONS (XCONS (breakdown)->cdr)->car);
- if (modifiers & shift_modifier)
- {
- Lisp_Object new_key;
-
- original_uppercase = key;
- original_uppercase_position = t - 1;
-
- modifiers &= ~shift_modifier;
- new_key = apply_modifiers (modifiers,
- XCONS (breakdown)->car);
-
- keybuf[t - 1] = new_key;
- mock_input = t;
-
- fkey_map = prev_fkey_map;
- fkey_start = prev_fkey_start;
- fkey_end = prev_fkey_end;
-
- keytran_map = prev_keytran_map;
- keytran_start = prev_keytran_start;
- keytran_end = prev_keytran_end;
-
- goto replay_sequence;
- }
- }
- }
-
- if (!dummyflag)
- read_key_sequence_cmd = (first_binding < nmaps
- ? defs[first_binding]
- : Qnil);
-
- unread_switch_frame = delayed_switch_frame;
- unbind_to (count, Qnil);
-
- /* Don't downcase the last character if the caller says don't.
- Don't downcase it if the result is undefined, either. */
- if ((dont_downcase_last || first_binding >= nmaps)
- && t - 1 == original_uppercase_position)
- keybuf[t - 1] = original_uppercase;
-
- /* Occasionally we fabricate events, perhaps by expanding something
- according to function-key-map, or by adding a prefix symbol to a
- mouse click in the scroll bar or modeline. In this cases, return
- the entire generated key sequence, even if we hit an unbound
- prefix or a definition before the end. This means that you will
- be able to push back the event properly, and also means that
- read-key-sequence will always return a logical unit.
-
- Better ideas? */
- for (; t < mock_input; t++)
- {
- if (echo_keystrokes)
- echo_char (keybuf[t]);
- add_command_key (keybuf[t]);
- }
-
- return t;
-}
-
-#if 0 /* This doc string is too long for some compilers.
- This commented-out definition serves for DOC. */
-DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 4, 0,
- "Read a sequence of keystrokes and return as a string or vector.\n\
-The sequence is sufficient to specify a non-prefix command in the\n\
-current local and global maps.\n\
-\n\
-First arg PROMPT is a prompt string. If nil, do not prompt specially.\n\
-Second (optional) arg CONTINUE-ECHO, if non-nil, means this key echos\n\
-as a continuation of the previous key.\n\
-\n\
-The third (optional) arg DONT-DOWNCASE-LAST, if non-nil, means do not\n\
-convert the last event to lower case. (Normally any upper case event\n\
-is converted to lower case if the original event is undefined and the lower\n\
-case equivalent is defined.) A non-nil value is appropriate for reading\n\
-a key sequence to be defined.\n\
-\n\
-A C-g typed while in this function is treated like any other character,\n\
-and `quit-flag' is not set.\n\
-\n\
-If the key sequence starts with a mouse click, then the sequence is read\n\
-using the keymaps of the buffer of the window clicked in, not the buffer\n\
-of the selected window as normal.\n\
-""\n\
-`read-key-sequence' drops unbound button-down events, since you normally\n\
-only care about the click or drag events which follow them. If a drag\n\
-or multi-click event is unbound, but the corresponding click event would\n\
-be bound, `read-key-sequence' turns the event into a click event at the\n\
-drag's starting position. This means that you don't have to distinguish\n\
-between click and drag, double, or triple events unless you want to.\n\
-\n\
-`read-key-sequence' prefixes mouse events on mode lines, the vertical\n\
-lines separating windows, and scroll bars with imaginary keys\n\
-`mode-line', `vertical-line', and `vertical-scroll-bar'.\n\
-\n\
-Optional fourth argument CAN-RETURN-SWITCH-FRAME non-nil means that this\n\
-function will process a switch-frame event if the user switches frames\n\
-before typing anything. If the user switches frames in the middle of a\n\
-key sequence, or at the start of the sequence but CAN-RETURN-SWITCH-FRAME\n\
-is nil, then the event will be put off until after the current key sequence.\n\
-\n\
-`read-key-sequence' checks `function-key-map' for function key\n\
-sequences, where they wouldn't conflict with ordinary bindings. See\n\
-`function-key-map' for more details.")
- (prompt, continue_echo, dont_downcase_last, can_return_switch_frame)
-#endif
-
-DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 4, 0,
- 0)
- (prompt, continue_echo, dont_downcase_last, can_return_switch_frame)
- Lisp_Object prompt, continue_echo, dont_downcase_last;
- Lisp_Object can_return_switch_frame;
-{
- Lisp_Object keybuf[30];
- register int i;
- struct gcpro gcpro1, gcpro2;
-
- if (!NILP (prompt))
- CHECK_STRING (prompt, 0);
- QUIT;
-
- bzero (keybuf, sizeof keybuf);
- GCPRO1 (keybuf[0]);
- gcpro1.nvars = (sizeof keybuf/sizeof (keybuf[0]));
-
- if (NILP (continue_echo))
- {
- this_command_key_count = 0;
- this_single_command_key_start = 0;
- }
-
- i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])),
- prompt, ! NILP (dont_downcase_last),
- ! NILP (can_return_switch_frame));
-
- if (i == -1)
- {
- Vquit_flag = Qt;
- QUIT;
- }
- UNGCPRO;
- return make_event_array (i, keybuf);
-}
-
-DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 4, 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 `command-history'.\n\
-Otherwise, that is done only if an arg is read using the minibuffer.\n\
-The argument KEYS specifies the value to use instead of (this-command-keys)\n\
-when reading the arguments; if it is nil, (this-command-keys) is used.\n\
-The argument SPECIAL, if non-nil, means that this command is executing\n\
-a special event, so ignore the prefix argument and don't clear it.")
- (cmd, record_flag, keys, special)
- Lisp_Object cmd, record_flag, keys, special;
-{
- register Lisp_Object final;
- register Lisp_Object tem;
- Lisp_Object prefixarg;
- struct backtrace backtrace;
- extern int debug_on_next_call;
-
- debug_on_next_call = 0;
-
- if (NILP (special))
- {
- prefixarg = current_kboard->Vprefix_arg;
- Vcurrent_prefix_arg = prefixarg;
- current_kboard->Vprefix_arg = Qnil;
- }
- else
- prefixarg = Qnil;
-
- if (SYMBOLP (cmd))
- {
- tem = Fget (cmd, Qdisabled);
- if (!NILP (tem) && !NILP (Vrun_hooks))
- {
- tem = Fsymbol_value (Qdisabled_command_hook);
- if (!NILP (tem))
- return call1 (Vrun_hooks, Qdisabled_command_hook);
- }
- }
-
- while (1)
- {
- final = Findirect_function (cmd);
-
- if (CONSP (final) && (tem = Fcar (final), EQ (tem, Qautoload)))
- {
- struct gcpro gcpro1, gcpro2;
-
- GCPRO2 (cmd, prefixarg);
- do_autoload (final, cmd);
- UNGCPRO;
- }
- else
- break;
- }
-
- if (STRINGP (final) || VECTORP (final))
- {
- /* If requested, place the macro in the command history. For
- other sorts of commands, call-interactively takes care of
- this. */
- if (!NILP (record_flag))
- Vcommand_history
- = Fcons (Fcons (Qexecute_kbd_macro,
- Fcons (final, Fcons (prefixarg, Qnil))),
- Vcommand_history);
-
- return Fexecute_kbd_macro (final, prefixarg);
- }
- if (CONSP (final) || SUBRP (final) || COMPILEDP (final))
- {
- 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_flag, keys);
-
- backtrace_list = backtrace.next;
- return tem;
- }
- 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;
- Lisp_Object bindings, value;
- struct gcpro gcpro1, gcpro2;
-
- saved_keys = Fvector (this_command_key_count,
- XVECTOR (this_command_keys)->contents);
- buf[0] = 0;
- GCPRO2 (saved_keys, prefixarg);
-
- if (EQ (prefixarg, Qminus))
- strcpy (buf, "- ");
- else if (CONSP (prefixarg) && XINT (XCONS (prefixarg)->car) == 4)
- strcpy (buf, "C-u ");
- else if (CONSP (prefixarg) && INTEGERP (XCONS (prefixarg)->car))
- {
- if (sizeof (int) == sizeof (EMACS_INT))
- sprintf (buf, "%d ", XINT (XCONS (prefixarg)->car));
- else if (sizeof (long) == sizeof (EMACS_INT))
- sprintf (buf, "%ld ", XINT (XCONS (prefixarg)->car));
- else
- abort ();
- }
- else if (INTEGERP (prefixarg))
- {
- if (sizeof (int) == sizeof (EMACS_INT))
- sprintf (buf, "%d ", XINT (prefixarg));
- else if (sizeof (long) == sizeof (EMACS_INT))
- sprintf (buf, "%ld ", XINT (prefixarg));
- else
- abort ();
- }
-
- /* This isn't strictly correct if execute-extended-command
- is bound to anything else. Perhaps it should use
- this_command_keys? */
- strcat (buf, "M-x ");
-
- /* Prompt with buf, and then read a string, completing from and
- restricting to the set of all defined commands. Don't provide
- any initial input. Save the command read on the extended-command
- history list. */
- function = Fcompleting_read (build_string (buf),
- Vobarray, Qcommandp,
- Qt, Qnil, Qextended_command_history);
-
- if (STRINGP (function) && XSTRING (function)->size == 0)
- error ("No command name given");
-
- /* Set this_command_keys to the concatenation of saved_keys and
- function, followed by a RET. */
- {
- struct Lisp_String *str;
- Lisp_Object *keys;
- int i;
- Lisp_Object tem;
-
- this_command_key_count = 0;
- this_single_command_key_start = 0;
-
- keys = XVECTOR (saved_keys)->contents;
- for (i = 0; i < XVECTOR (saved_keys)->size; i++)
- add_command_key (keys[i]);
-
- str = XSTRING (function);
- for (i = 0; i < str->size; i++)
- {
- XSETFASTINT (tem, str->data[i]);
- add_command_key (tem);
- }
-
- XSETFASTINT (tem, '\015');
- add_command_key (tem);
- }
-
- UNGCPRO;
-
- function = Fintern (function, Qnil);
- current_kboard->Vprefix_arg = prefixarg;
- this_command = function;
-
- /* If enabled, show which key runs this command. */
- if (!NILP (Vsuggest_key_bindings)
- && NILP (Vexecuting_macro)
- && SYMBOLP (function))
- bindings = Fwhere_is_internal (function, Voverriding_local_map,
- Qt, Qnil);
- else
- bindings = Qnil;
-
- value = Qnil;
- GCPRO2 (bindings, value);
- value = Fcommand_execute (function, Qt, Qnil, Qnil);
-
- /* If the command has a key binding, print it now. */
- if (!NILP (bindings))
- {
- /* But first wait, and skip the message if there is input. */
- if (!NILP (Fsit_for ((NUMBERP (Vsuggest_key_bindings)
- ? Vsuggest_key_bindings : make_number (2)),
- Qnil, Qnil)))
- {
- Lisp_Object binding;
- char *newmessage;
- char *oldmessage = echo_area_glyphs;
- int oldmessage_len = echo_area_glyphs_length;
-
- binding = Fkey_description (bindings);
-
- newmessage
- = (char *) alloca (XSYMBOL (function)->name->size
- + XSTRING (binding)->size
- + 100);
- sprintf (newmessage, "You can run the command `%s' by typing %s",
- XSYMBOL (function)->name->data,
- XSTRING (binding)->data);
- message1_nolog (newmessage);
- if (!NILP (Fsit_for ((NUMBERP (Vsuggest_key_bindings)
- ? Vsuggest_key_bindings : make_number (2)),
- Qnil, Qnil)))
- message2_nolog (oldmessage, oldmessage_len);
- }
- }
-
- RETURN_UNGCPRO (value);
-}
-
-/* Find the set of keymaps now active.
- Store into *MAPS_P a vector holding the various maps
- and return the number of them. The vector was malloc'd
- and the caller should free it. */
-
-int
-current_active_maps (maps_p)
- Lisp_Object **maps_p;
-{
- Lisp_Object *tmaps, *maps;
- int nmaps;
-
- /* Should overriding-terminal-local-map and overriding-local-map apply? */
- if (!NILP (Voverriding_local_map_menu_flag))
- {
- /* Yes, use them (if non-nil) as well as the global map. */
- maps = (Lisp_Object *) xmalloc (3 * sizeof (maps[0]));
- nmaps = 0;
- if (!NILP (current_kboard->Voverriding_terminal_local_map))
- maps[nmaps++] = current_kboard->Voverriding_terminal_local_map;
- if (!NILP (Voverriding_local_map))
- maps[nmaps++] = Voverriding_local_map;
- }
- else
- {
- /* No, so use major and minor mode keymaps. */
- nmaps = current_minor_maps (NULL, &tmaps);
- maps = (Lisp_Object *) xmalloc ((nmaps + 2) * sizeof (maps[0]));
- bcopy (tmaps, maps, nmaps * sizeof (maps[0]));
-#ifdef USE_TEXT_PROPERTIES
- maps[nmaps++] = get_local_map (PT, current_buffer);
-#else
- maps[nmaps++] = current_buffer->keymap;
-#endif
- }
- maps[nmaps++] = current_global_map;
-
- *maps_p = maps;
- return nmaps;
-}
-
-/* Return nonzero if input events are pending. */
-
-detect_input_pending ()
-{
- if (!input_pending)
- get_input_pending (&input_pending, 0);
-
- return input_pending;
-}
-
-/* Return nonzero if input events are pending, and run any pending timers. */
-
-detect_input_pending_run_timers (do_display)
- int do_display;
-{
- int old_timers_run = timers_run;
-
- if (!input_pending)
- get_input_pending (&input_pending, 1);
-
- if (old_timers_run != timers_run && do_display)
- redisplay_preserve_echo_area ();
-
- 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;
-}
-
-/* Return nonzero if there are pending requeued events.
- This isn't used yet. The hope is to make wait_reading_process_input
- call it, and return return if it runs Lisp code that unreads something.
- The problem is, kbd_buffer_get_event needs to be fixed to know what
- to do in that case. It isn't trivial. */
-
-requeued_events_pending_p ()
-{
- return (!NILP (Vunread_command_events) || unread_command_char != -1);
-}
-
-
-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 (!NILP (Vunread_command_events) || unread_command_char != -1)
- return (Qt);
-
- get_input_pending (&input_pending, 1);
- return input_pending > 0 ? Qt : Qnil;
-}
-
-DEFUN ("recent-keys", Frecent_keys, Srecent_keys, 0, 0, 0,
- "Return vector of last 100 events, not counting those from keyboard macros.")
- ()
-{
- Lisp_Object *keys = XVECTOR (recent_keys)->contents;
- Lisp_Object val;
-
- if (total_keys < NUM_RECENT_KEYS)
- return Fvector (total_keys, keys);
- else
- {
- val = Fvector (NUM_RECENT_KEYS, keys);
- bcopy (keys + recent_keys_index,
- XVECTOR (val)->contents,
- (NUM_RECENT_KEYS - recent_keys_index) * sizeof (Lisp_Object));
- bcopy (keys,
- XVECTOR (val)->contents + NUM_RECENT_KEYS - recent_keys_index,
- recent_keys_index * sizeof (Lisp_Object));
- return val;
- }
-}
-
-DEFUN ("this-command-keys", Fthis_command_keys, Sthis_command_keys, 0, 0, 0,
- "Return the key sequence that invoked this command.\n\
-The value is a string or a vector.")
- ()
-{
- return make_event_array (this_command_key_count,
- XVECTOR (this_command_keys)->contents);
-}
-
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,
- Sthis_single_command_keys, 0, 0, 0,
- "Return the key sequence that invoked this command.\n\
-Unlike `this-command-keys', this function's value\n\
-does not include prefix arguments.\n\
-The value is a string or a vector.")
- ()
-{
- return make_event_array (this_command_key_count
- - this_single_command_key_start,
- (XVECTOR (this_command_keys)->contents
- + this_single_command_key_start));
-}
-
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,
- Sreset_this_command_lengths, 0, 0, 0,
- "Used for complicated reasons in `universal-argument-other-key'.\n\
-\n\
-`universal-argument-other-key' rereads the event just typed.\n\
-It then gets translated through `function-key-map'.\n\
-The translated event gets included in the echo area and in\n\
-the value of `this-command-keys' in addition to the raw original event.\n\
-That is not right.\n\
-\n\
-Calling this function directs the translated event to replace\n\
-the original event, so that only one version of the event actually\n\
-appears in the echo area and in the value of `this-command-keys.'.")
- ()
-{
- before_command_restore_flag = 1;
- before_command_key_count_1 = before_command_key_count;
- before_command_echo_length_1 = before_command_echo_length;
-}
-
-DEFUN ("recursion-depth", Frecursion_depth, Srecursion_depth, 0, 0, 0,
- "Return the current depth in recursive edits.")
- ()
-{
- Lisp_Object temp;
- XSETFASTINT (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 a dribble file called FILE.\n\
-If FILE is nil, close any open dribble file.")
- (file)
- Lisp_Object file;
-{
- if (dribble)
- {
- fclose (dribble);
- dribble = 0;
- }
- if (!NILP (file))
- {
- file = Fexpand_file_name (file, Qnil);
- dribble = fopen (XSTRING (file)->data, "w");
- if (dribble == 0)
- report_file_error ("Opening dribble", Fcons (file, Qnil));
- }
- return Qnil;
-}
-
-DEFUN ("discard-input", Fdiscard_input, Sdiscard_input, 0, 0, 0,
- "Discard the contents of the terminal input buffer.\n\
-Also cancel any kbd macro being defined.")
- ()
-{
- current_kboard->defining_kbd_macro = Qnil;
- update_mode_lines++;
-
- Vunread_command_events = Qnil;
- unread_command_char = -1;
-
- discard_tty_input ();
-
- /* Without the cast, GCC complains that this assignment loses the
- volatile qualifier of kbd_store_ptr. Is there anything wrong
- with that? */
- kbd_fetch_ptr = (struct input_event *) kbd_store_ptr;
- Ffillarray (kbd_buffer_frame_or_window, Qnil);
- input_pending = 0;
-
- return Qnil;
-}
-
-DEFUN ("suspend-emacs", Fsuspend_emacs, Ssuspend_emacs, 0, 1, "",
- "Stop Emacs and return to superior process. You can resume later.\n\
-If `cannot-suspend' is non-nil, or if the system doesn't support job\n\
-control, run a subshell instead.\n\n\
-If optional arg STUFFSTRING is non-nil, its characters are stuffed\n\
-to be read as terminal input by Emacs's parent, after suspension.\n\
-\n\
-Before suspending, run the normal hook `suspend-hook'.\n\
-After resumption run the normal hook `suspend-resume-hook'.\n\
-\n\
-Some operating systems cannot stop the Emacs process and resume it later.\n\
-On such systems, Emacs starts a subshell instead of suspending.")
- (stuffstring)
- Lisp_Object stuffstring;
-{
- Lisp_Object tem;
- int count = specpdl_ptr - specpdl;
- int old_height, old_width;
- int width, height;
- struct gcpro gcpro1, gcpro2;
- extern init_sys_modes ();
-
- if (!NILP (stuffstring))
- CHECK_STRING (stuffstring, 0);
-
- /* Run the functions in suspend-hook. */
- if (!NILP (Vrun_hooks))
- call1 (Vrun_hooks, intern ("suspend-hook"));
-
- GCPRO1 (stuffstring);
- get_frame_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);
- if (cannot_suspend)
- sys_subshell ();
- else
- sys_suspend ();
- unbind_to (count, Qnil);
-
- /* 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_frame_size (&width, &height);
- if (width != old_width || height != old_height)
- change_frame_size (selected_frame, height, width, 0, 0);
-
- /* Run suspend-resume-hook. */
- if (!NILP (Vrun_hooks))
- call1 (Vrun_hooks, intern ("suspend-resume-hook"));
-
- UNGCPRO;
- return Qnil;
-}
-
-/* If STUFFSTRING is a string, stuff its contents as pending terminal input.
- Then in any case stuff anything Emacs has read ahead and not used. */
-
-stuff_buffered_input (stuffstring)
- Lisp_Object stuffstring;
-{
-/* stuff_char works only in BSD, versions 4.2 and up. */
-#ifdef BSD_SYSTEM
-#ifndef BSD4_1
- register unsigned char *p;
-
- if (STRINGP (stuffstring))
- {
- 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. */
- /* ?? What should this do when we have multiple keyboards??
- Should we ignore anything that was typed in at the "wrong" kboard? */
- for (; kbd_fetch_ptr != kbd_store_ptr; kbd_fetch_ptr++)
- {
- if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE)
- kbd_fetch_ptr = kbd_buffer;
- if (kbd_fetch_ptr->kind == ascii_keystroke)
- stuff_char (kbd_fetch_ptr->code);
- kbd_fetch_ptr->kind = no_event;
- (XVECTOR (kbd_buffer_frame_or_window)->contents[kbd_fetch_ptr
- - kbd_buffer]
- = Qnil);
- }
- input_pending = 0;
-#endif
-#endif /* BSD_SYSTEM and not BSD4_1 */
-}
-
-set_waiting_for_input (time_to_clear)
- EMACS_TIME *time_to_clear;
-{
- input_available_clear_time = time_to_clear;
-
- /* Tell interrupt_signal to throw back to read_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 (!NILP (Vquit_flag))
- quit_throw_to_read_char ();
-}
-
-clear_waiting_for_input ()
-{
- /* Tell interrupt_signal not to throw back to read_char, */
- waiting_for_input = 0;
- input_available_clear_time = 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_event,
- in handling SIGIO or SIGTINT.
-
- If `waiting_for_input' is non zero, then unless `echoing' is nonzero,
- immediately throw back to read_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. */
-
-SIGTYPE
-interrupt_signal (signalnum) /* If we don't have an argument, */
- int signalnum; /* some compilers complain in signal calls. */
-{
- char c;
- /* Must preserve main program's value of errno. */
- int old_errno = errno;
-
-#if defined (USG) && !defined (POSIX_SIGNALS)
- if (!read_socket_hook && NILP (Vwindow_system))
- {
- /* 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 (!NILP (Vquit_flag) && FRAME_TERMCAP_P (selected_frame))
- {
- 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 */
-#ifdef MSDOS
- /* We must remain inside the screen area when the internal terminal
- is used. Note that [Enter] is not echoed by dos. */
- cursor_to (0, 0);
-#endif
- /* It doesn't work to autosave while GC is in progress;
- the code used for auto-saving doesn't cope with the mark bit. */
- if (!gc_in_progress)
- {
- printf ("Auto-save? (y or n) ");
- fflush (stdout);
- if (((c = getchar ()) & ~040) == 'Y')
- {
- Fdo_auto_save (Qt, Qnil);
-#ifdef MSDOS
- printf ("\r\nAuto-save done");
-#else /* not MSDOS */
- printf ("Auto-save done\n");
-#endif /* not MSDOS */
- }
- while (c != '\n') c = getchar ();
- }
- else
- {
- /* During GC, it must be safe to reenable quitting again. */
- Vinhibit_quit = Qnil;
-#ifdef MSDOS
- printf ("\r\n");
-#endif /* not MSDOS */
- printf ("Garbage collection in progress; cannot auto-save now\r\n");
- printf ("but will instead do a real quit after garbage collection ends\r\n");
- fflush (stdout);
- }
-
-#ifdef MSDOS
- printf ("\r\nAbort? (y or n) ");
-#else /* not MSDOS */
-#ifdef VMS
- printf ("Abort (and enter debugger)? (y or n) ");
-#else /* not VMS */
- printf ("Abort (and dump core)? (y or n) ");
-#endif /* not VMS */
-#endif /* not MSDOS */
- fflush (stdout);
- if (((c = getchar ()) & ~040) == 'Y')
- abort ();
- while (c != '\n') c = getchar ();
-#ifdef MSDOS
- printf ("\r\nContinuing...\r\n");
-#else /* not MSDOS */
- printf ("Continuing...\n");
-#endif /* not MSDOS */
- 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 && NILP (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_char ();
-
- errno = old_errno;
-}
-
-/* Handle a C-g by making read_char return C-g. */
-
-quit_throw_to_read_char ()
-{
- quit_error_check ();
- sigfree ();
- /* Prevent another signal from doing this before we finish. */
- clear_waiting_for_input ();
- input_pending = 0;
-
- Vunread_command_events = Qnil;
- unread_command_char = -1;
-
-#if 0 /* Currently, sit_for is called from read_char without turning
- off polling. And that can call set_waiting_for_input.
- It seems to be harmless. */
-#ifdef POLL_FOR_INPUT
- /* May be > 1 if in recursive minibuffer. */
- if (poll_suppress_count == 0)
- abort ();
-#endif
-#endif
- if (FRAMEP (internal_last_event_frame)
- && XFRAME (internal_last_event_frame) != selected_frame)
- do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
- Qnil, 0);
-
- _longjmp (getcjmp, 1);
-}
-
-DEFUN ("set-input-mode", Fset_input_mode, Sset_input_mode, 3, 4, 0,
- "Set mode of reading keyboard input.\n\
-First arg INTERRUPT non-nil means use input interrupts;\n\
- nil means use CBREAK mode.\n\
-Second arg FLOW non-nil means use ^S/^Q flow control for output to terminal\n\
- (no effect except in CBREAK mode).\n\
-Third arg META t means accept 8-bit input (for a Meta key).\n\
- META nil means ignore the top bit, on the assumption it is parity.\n\
- Otherwise, accept 8-bit input and don't use the top bit for Meta.\n\
-Optional fourth arg QUIT if non-nil specifies character to use for quitting.\n\
-See also `current-input-mode'.")
- (interrupt, flow, meta, quit)
- Lisp_Object interrupt, flow, meta, quit;
-{
- if (!NILP (quit)
- && (!INTEGERP (quit) || XINT (quit) < 0 || XINT (quit) > 0400))
- error ("set-input-mode: QUIT must be an ASCII character");
-
-#ifdef POLL_FOR_INPUT
- stop_polling ();
-#endif
-
-#ifndef MSDOS
- /* this causes startup screen to be restored and messes with the mouse */
- reset_sys_modes ();
-#endif
-
-#ifdef SIGIO
-/* Note SIGIO has been undef'd if FIONREAD is missing. */
- if (read_socket_hook)
- {
- /* When using X, don't give the user a real choice,
- because we haven't implemented the mechanisms to support it. */
-#ifdef NO_SOCK_SIGIO
- interrupt_input = 0;
-#else /* not NO_SOCK_SIGIO */
- interrupt_input = 1;
-#endif /* NO_SOCK_SIGIO */
- }
- else
- interrupt_input = !NILP (interrupt);
-#else /* not SIGIO */
- interrupt_input = 0;
-#endif /* not SIGIO */
-
-/* Our VMS input only works by interrupts, as of now. */
-#ifdef VMS
- interrupt_input = 1;
-#endif
-
- flow_control = !NILP (flow);
- if (NILP (meta))
- meta_key = 0;
- else if (EQ (meta, Qt))
- meta_key = 1;
- else
- meta_key = 2;
- if (!NILP (quit))
- /* Don't let this value be out of range. */
- quit_char = XINT (quit) & (meta_key ? 0377 : 0177);
-
-#ifndef MSDOS
- init_sys_modes ();
-#endif
-
-#ifdef POLL_FOR_INPUT
- poll_suppress_count = 1;
- start_polling ();
-#endif
- return Qnil;
-}
-
-DEFUN ("current-input-mode", Fcurrent_input_mode, Scurrent_input_mode, 0, 0, 0,
- "Return information about the way Emacs currently reads keyboard input.\n\
-The value is a list of the form (INTERRUPT FLOW META QUIT), where\n\
- INTERRUPT is non-nil if Emacs is using interrupt-driven input; if\n\
- nil, Emacs is using CBREAK mode.\n\
- FLOW is non-nil if Emacs uses ^S/^Q flow control for output to the\n\
- terminal; this does not apply if Emacs uses interrupt-driven input.\n\
- META is t if accepting 8-bit input with 8th bit as Meta flag.\n\
- META nil means ignoring the top bit, on the assumption it is parity.\n\
- META is neither t nor nil if accepting 8-bit input and using\n\
- all 8 bits as the character code.\n\
- QUIT is the character Emacs currently uses to quit.\n\
-The elements of this list correspond to the arguments of\n\
-`set-input-mode'.")
- ()
-{
- Lisp_Object val[4];
-
- val[0] = interrupt_input ? Qt : Qnil;
- val[1] = flow_control ? Qt : Qnil;
- val[2] = meta_key == 2 ? make_number (0) : meta_key == 1 ? Qt : Qnil;
- XSETFASTINT (val[3], quit_char);
-
- return Flist (sizeof (val) / sizeof (val[0]), val);
-}
-
-
-/*
- * Set up a new kboard object with reasonable initial values.
- */
-void
-init_kboard (kb)
- KBOARD *kb;
-{
- kb->Voverriding_terminal_local_map = Qnil;
- kb->Vlast_command = Qnil;
- kb->Vprefix_arg = Qnil;
- kb->kbd_queue = Qnil;
- kb->kbd_queue_has_data = 0;
- kb->immediate_echo = 0;
- kb->echoptr = kb->echobuf;
- kb->echo_after_prompt = -1;
- kb->kbd_macro_buffer = 0;
- kb->kbd_macro_bufsize = 0;
- kb->defining_kbd_macro = Qnil;
- kb->Vlast_kbd_macro = Qnil;
- kb->reference_count = 0;
- kb->Vsystem_key_alist = Qnil;
- kb->system_key_syms = Qnil;
- kb->Vdefault_minibuffer_frame = Qnil;
-}
-
-/*
- * Destroy the contents of a kboard object, but not the object itself.
- * We use this just before deleting it, or if we're going to initialize
- * it a second time.
- */
-static void
-wipe_kboard (kb)
- KBOARD *kb;
-{
- if (kb->kbd_macro_buffer)
- xfree (kb->kbd_macro_buffer);
-}
-
-#ifdef MULTI_KBOARD
-void
-delete_kboard (kb)
- KBOARD *kb;
-{
- KBOARD **kbp;
- for (kbp = &all_kboards; *kbp != kb; kbp = &(*kbp)->next_kboard)
- if (*kbp == NULL)
- abort ();
- *kbp = kb->next_kboard;
- wipe_kboard (kb);
- xfree (kb);
-}
-#endif
-
-init_keyboard ()
-{
- /* This is correct before outermost invocation of the editor loop */
- command_loop_level = -1;
- immediate_quit = 0;
- quit_char = Ctl ('g');
- Vunread_command_events = Qnil;
- unread_command_char = -1;
- EMACS_SET_SECS_USECS (timer_idleness_start_time, -1, -1);
- total_keys = 0;
- recent_keys_index = 0;
- kbd_fetch_ptr = kbd_buffer;
- kbd_store_ptr = kbd_buffer;
- kbd_buffer_frame_or_window
- = Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil);
-#ifdef HAVE_MOUSE
- do_mouse_tracking = Qnil;
-#endif
- input_pending = 0;
-
- /* This means that command_loop_1 won't try to select anything the first
- time through. */
- internal_last_event_frame = Qnil;
- Vlast_event_frame = internal_last_event_frame;
-
-#ifdef MULTI_KBOARD
- current_kboard = initial_kboard;
-#endif
- wipe_kboard (current_kboard);
- init_kboard (current_kboard);
-
- if (initialized)
- Ffillarray (kbd_buffer_frame_or_window, Qnil);
-
- kbd_buffer_frame_or_window
- = Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil);
- if (!noninteractive && !read_socket_hook && NILP (Vwindow_system))
- {
- signal (SIGINT, interrupt_signal);
-#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
- /* For systems with SysV 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
- if (!noninteractive)
- 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
-
-/* Our VMS input only works by interrupts, as of now. */
-#ifdef VMS
- interrupt_input = 1;
-#endif
-
- sigfree ();
- dribble = 0;
-
- if (keyboard_init_hook)
- (*keyboard_init_hook) ();
-
-#ifdef POLL_FOR_INPUT
- poll_suppress_count = 1;
- start_polling ();
-#endif
-}
-
-/* This type's only use is in syms_of_keyboard, to initialize the
- event header symbols and put properties on them. */
-struct event_head {
- Lisp_Object *var;
- char *name;
- Lisp_Object *kind;
-};
-
-struct event_head head_table[] = {
- &Qmouse_movement, "mouse-movement", &Qmouse_movement,
- &Qscroll_bar_movement, "scroll-bar-movement", &Qmouse_movement,
- &Qswitch_frame, "switch-frame", &Qswitch_frame,
- &Qdelete_frame, "delete-frame", &Qdelete_frame,
- &Qiconify_frame, "iconify-frame", &Qiconify_frame,
- &Qmake_frame_visible, "make-frame-visible", &Qmake_frame_visible,
-};
-
-syms_of_keyboard ()
-{
- Qdisabled_command_hook = intern ("disabled-command-hook");
- staticpro (&Qdisabled_command_hook);
-
- 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);
-
- Qundefined = intern ("undefined");
- staticpro (&Qundefined);
-
- Qpre_command_hook = intern ("pre-command-hook");
- staticpro (&Qpre_command_hook);
-
- Qpost_command_hook = intern ("post-command-hook");
- staticpro (&Qpost_command_hook);
-
- Qpost_command_idle_hook = intern ("post-command-idle-hook");
- staticpro (&Qpost_command_idle_hook);
-
- Qdeferred_action_function = intern ("deferred-action-function");
- staticpro (&Qdeferred_action_function);
-
- Qcommand_hook_internal = intern ("command-hook-internal");
- staticpro (&Qcommand_hook_internal);
-
- Qfunction_key = intern ("function-key");
- staticpro (&Qfunction_key);
- Qmouse_click = intern ("mouse-click");
- staticpro (&Qmouse_click);
- Qtimer_event = intern ("timer-event");
- staticpro (&Qtimer_event);
-
- Qmenu_enable = intern ("menu-enable");
- staticpro (&Qmenu_enable);
-
- Qmode_line = intern ("mode-line");
- staticpro (&Qmode_line);
- Qvertical_line = intern ("vertical-line");
- staticpro (&Qvertical_line);
- Qvertical_scroll_bar = intern ("vertical-scroll-bar");
- staticpro (&Qvertical_scroll_bar);
- Qmenu_bar = intern ("menu-bar");
- staticpro (&Qmenu_bar);
-
- Qabove_handle = intern ("above-handle");
- staticpro (&Qabove_handle);
- Qhandle = intern ("handle");
- staticpro (&Qhandle);
- Qbelow_handle = intern ("below-handle");
- staticpro (&Qbelow_handle);
- Qup = intern ("up");
- staticpro (&Qup);
- Qdown = intern ("down");
- staticpro (&Qdown);
-
- Qevent_kind = intern ("event-kind");
- staticpro (&Qevent_kind);
- Qevent_symbol_elements = intern ("event-symbol-elements");
- staticpro (&Qevent_symbol_elements);
- Qevent_symbol_element_mask = intern ("event-symbol-element-mask");
- staticpro (&Qevent_symbol_element_mask);
- Qmodifier_cache = intern ("modifier-cache");
- staticpro (&Qmodifier_cache);
-
- Qrecompute_lucid_menubar = intern ("recompute-lucid-menubar");
- staticpro (&Qrecompute_lucid_menubar);
- Qactivate_menubar_hook = intern ("activate-menubar-hook");
- staticpro (&Qactivate_menubar_hook);
-
- Qpolling_period = intern ("polling-period");
- staticpro (&Qpolling_period);
-
- {
- struct event_head *p;
-
- for (p = head_table;
- p < head_table + (sizeof (head_table) / sizeof (head_table[0]));
- p++)
- {
- *p->var = intern (p->name);
- staticpro (p->var);
- Fput (*p->var, Qevent_kind, *p->kind);
- Fput (*p->var, Qevent_symbol_elements, Fcons (*p->var, Qnil));
- }
- }
-
- button_down_location = Fmake_vector (make_number (NUM_MOUSE_BUTTONS), Qnil);
- staticpro (&button_down_location);
-
- {
- int i;
- int len = sizeof (modifier_names) / sizeof (modifier_names[0]);
-
- modifier_symbols = Fmake_vector (make_number (len), Qnil);
- for (i = 0; i < len; i++)
- if (modifier_names[i])
- XVECTOR (modifier_symbols)->contents[i] = intern (modifier_names[i]);
- staticpro (&modifier_symbols);
- }
-
- recent_keys = Fmake_vector (make_number (NUM_RECENT_KEYS), Qnil);
- staticpro (&recent_keys);
-
- this_command_keys = Fmake_vector (make_number (40), Qnil);
- staticpro (&this_command_keys);
-
- Qextended_command_history = intern ("extended-command-history");
- Fset (Qextended_command_history, Qnil);
- staticpro (&Qextended_command_history);
-
- kbd_buffer_frame_or_window
- = Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil);
- staticpro (&kbd_buffer_frame_or_window);
-
- accent_key_syms = Qnil;
- staticpro (&accent_key_syms);
-
- func_key_syms = Qnil;
- staticpro (&func_key_syms);
-
- mouse_syms = Qnil;
- staticpro (&mouse_syms);
-
- unread_switch_frame = Qnil;
- staticpro (&unread_switch_frame);
-
- internal_last_event_frame = Qnil;
- staticpro (&internal_last_event_frame);
-
- read_key_sequence_cmd = Qnil;
- staticpro (&read_key_sequence_cmd);
-
- defsubr (&Sevent_convert_list);
- defsubr (&Sread_key_sequence);
- defsubr (&Srecursive_edit);
-#ifdef HAVE_MOUSE
- defsubr (&Strack_mouse);
-#endif
- defsubr (&Sinput_pending_p);
- defsubr (&Scommand_execute);
- defsubr (&Srecent_keys);
- defsubr (&Sthis_command_keys);
- defsubr (&Sthis_single_command_keys);
- defsubr (&Sreset_this_command_lengths);
- 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 (&Scurrent_input_mode);
- defsubr (&Sexecute_extended_command);
-
- DEFVAR_LISP ("last-command-char", &last_command_char,
- "Last input event that was part of a command.");
-
- DEFVAR_LISP_NOPRO ("last-command-event", &last_command_char,
- "Last input event that was part of a command.");
-
- DEFVAR_LISP ("last-nonmenu-event", &last_nonmenu_event,
- "Last input event in a command, except for mouse menu events.\n\
-Mouse menus give back keys that don't look like mouse events;\n\
-this variable holds the actual mouse event that led to the menu,\n\
-so that you can determine whether the command was run by mouse or not.");
-
- DEFVAR_LISP ("last-input-char", &last_input_char,
- "Last input event.");
-
- DEFVAR_LISP_NOPRO ("last-input-event", &last_input_char,
- "Last input event.");
-
- DEFVAR_LISP ("unread-command-events", &Vunread_command_events,
- "List of objects to be read as next command input events.");
-
- DEFVAR_INT ("unread-command-char", &unread_command_char,
- "If not -1, an object to be read as next command input event.");
-
- DEFVAR_LISP ("meta-prefix-char", &meta_prefix_char,
- "Meta-prefix character code. Meta-foo as command input\n\
-turns into this character followed by foo.");
- XSETINT (meta_prefix_char, 033);
-
- DEFVAR_KBOARD ("last-command", Vlast_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.\n\
-\n\
-The value `mode-exit' is special; it means that the previous command\n\
-read an event that told it to exit, and it did so and unread that event.\n\
-In other words, the present command is the event that made the previous\n\
-command exit.\n\
-\n\
-The value `kill-region' is special; it means that the previous command\n\
-was a kill command.");
-
- 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 due to number of characters typed.");
- auto_save_interval = 300;
-
- DEFVAR_LISP ("auto-save-timeout", &Vauto_save_timeout,
- "*Number of seconds idle time before auto-save.\n\
-Zero or nil means disable auto-saving due to idleness.\n\
-After auto-saving due to this many seconds of idle time,\n\
-Emacs also does a garbage collection if that seems to be warranted.");
- XSETFASTINT (Vauto_save_timeout, 30);
-
- 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_LISP ("double-click-time", &Vdouble_click_time,
- "*Maximum time between mouse clicks to make a double-click.\n\
-Measured in milliseconds. nil means disable double-click recognition;\n\
-t means double-clicks have no time limit and are detected\n\
-by position only.");
- Vdouble_click_time = make_number (500);
-
- DEFVAR_BOOL ("inhibit-local-menu-bar-menus", &inhibit_local_menu_bar_menus,
- "*Non-nil means inhibit local map menu bar menus.");
- inhibit_local_menu_bar_menus = 0;
-
- DEFVAR_INT ("num-input-keys", &num_input_keys,
- "Number of complete key sequences read from the keyboard so far.\n\
-This includes key sequences read from keyboard macros.\n\
-The number is effectively the number of interactive command invocations.");
- num_input_keys = 0;
-
- DEFVAR_LISP ("last-event-frame", &Vlast_event_frame,
- "The frame in which the most recently read event occurred.\n\
-If the last event came from a keyboard macro, this is set to `macro'.");
- Vlast_event_frame = Qnil;
-
- DEFVAR_LISP ("help-char", &Vhelp_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 the value of `help-form' is nil, this char can be read normally.");
- XSETINT (Vhelp_char, Ctl ('H'));
-
- DEFVAR_LISP ("help-event-list", &Vhelp_event_list,
- "List of input events to recognize as meaning Help.\n\
-These work just like the value of `help-char' (see that).");
- Vhelp_event_list = Qnil;
-
- 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 ("prefix-help-command", &Vprefix_help_command,
- "Command to run when `help-char' character follows a prefix key.\n\
-This command is used only when there is no actual binding\n\
-for that character after that prefix key.");
- Vprefix_help_command = 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,
- "Translate table for keyboard input, or nil.\n\
-Each character is looked up in this string and the contents used instead.\n\
-The value may be a string, a vector, or a char-table.\n\
-If it is a string or vector of length N,\n\
-character codes N and up are untranslated.\n\
-In a vector or a char-table, an element which is nil means \"no translation\".");
- Vkeyboard_translate_table = Qnil;
-
- DEFVAR_BOOL ("cannot-suspend", &cannot_suspend,
- "Non-nil means to always spawn a subshell instead of suspending,\n\
-even if the operating system has support for stopping a process.");
- cannot_suspend = 0;
-
- DEFVAR_BOOL ("menu-prompting", &menu_prompting,
- "Non-nil means prompt with menus when appropriate.\n\
-This is done when reading from a keymap that has a prompt string,\n\
-for elements that have prompt strings.\n\
-The menu is displayed on the screen\n\
-if X menus were enabled at configuration\n\
-time and the previous event was a mouse click prefix key.\n\
-Otherwise, menu prompting uses the echo area.");
- menu_prompting = 1;
-
- DEFVAR_LISP ("menu-prompt-more-char", &menu_prompt_more_char,
- "Character to see next line of menu prompt.\n\
-Type this character while in a menu prompt to rotate around the lines of it.");
- XSETINT (menu_prompt_more_char, ' ');
-
- DEFVAR_INT ("extra-keyboard-modifiers", &extra_keyboard_modifiers,
- "A mask of additional modifier keys to use with every keyboard character.\n\
-Emacs applies the modifiers of the character stored here to each keyboard\n\
-character it reads. For example, after evaluating the expression\n\
- (setq extra-keyboard-modifiers ?\\C-x)\n\
-all input characters will have the control modifier applied to them.\n\
-\n\
-Note that the character ?\\C-@, equivalent to the integer zero, does\n\
-not count as a control character; rather, it counts as a character\n\
-with no modifiers; thus, setting `extra-keyboard-modifiers' to zero\n\
-cancels any modification.");
- extra_keyboard_modifiers = 0;
-
- DEFVAR_LISP ("deactivate-mark", &Vdeactivate_mark,
- "If an editing command sets this to t, deactivate the mark afterward.\n\
-The command loop sets this to nil before each command,\n\
-and tests the value when the command returns.\n\
-Buffer modification stores t in this variable.");
- Vdeactivate_mark = Qnil;
-
- DEFVAR_LISP ("command-hook-internal", &Vcommand_hook_internal,
- "Temporary storage of pre-command-hook or post-command-hook.");
- Vcommand_hook_internal = Qnil;
-
- DEFVAR_LISP ("pre-command-hook", &Vpre_command_hook,
- "Normal hook run before each command is executed.\n\
-Errors running the hook are caught and ignored.");
- Vpre_command_hook = Qnil;
-
- DEFVAR_LISP ("post-command-hook", &Vpost_command_hook,
- "Normal hook run after each command is executed.\n\
-Errors running the hook are caught and ignored.");
- Vpost_command_hook = Qnil;
-
- DEFVAR_LISP ("post-command-idle-hook", &Vpost_command_idle_hook,
- "Normal hook run after each command is executed, if idle.\n\
-Errors running the hook are caught and ignored.\n\
-This feature is obsolete; use idle timers instead. See `etc/NEWS'.");
- Vpost_command_idle_hook = Qnil;
-
- DEFVAR_INT ("post-command-idle-delay", &post_command_idle_delay,
- "Delay time before running `post-command-idle-hook'.\n\
-This is measured in microseconds.");
- post_command_idle_delay = 100000;
-
-#if 0
- DEFVAR_LISP ("echo-area-clear-hook", ...,
- "Normal hook run when clearing the echo area.");
-#endif
- Qecho_area_clear_hook = intern ("echo-area-clear-hook");
- XSYMBOL (Qecho_area_clear_hook)->value = Qnil;
-
- DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag,
- "t means menu bar, specified Lucid style, needs to be recomputed.");
- Vlucid_menu_bar_dirty_flag = Qnil;
-
- DEFVAR_LISP ("menu-bar-final-items", &Vmenu_bar_final_items,
- "List of menu bar items to move to the end of the menu bar.\n\
-The elements of the list are event types that may have menu bar bindings.");
- Vmenu_bar_final_items = Qnil;
-
- DEFVAR_KBOARD ("overriding-terminal-local-map",
- Voverriding_terminal_local_map,
- "Keymap that overrides all other local keymaps.\n\
-If this variable is non-nil, it is used as a keymap instead of the\n\
-buffer's local map, and the minor mode keymaps and text property keymaps.");
-
- DEFVAR_LISP ("overriding-local-map", &Voverriding_local_map,
- "Keymap that overrides all other local keymaps.\n\
-If this variable is non-nil, it is used as a keymap instead of the\n\
-buffer's local map, and the minor mode keymaps and text property keymaps.");
- Voverriding_local_map = Qnil;
-
- DEFVAR_LISP ("overriding-local-map-menu-flag", &Voverriding_local_map_menu_flag,
- "Non-nil means `overriding-local-map' applies to the menu bar.\n\
-Otherwise, the menu bar continues to reflect the buffer's local map\n\
-and the minor mode maps regardless of `overriding-local-map'.");
- Voverriding_local_map_menu_flag = Qnil;
-
- DEFVAR_LISP ("special-event-map", &Vspecial_event_map,
- "Keymap defining bindings for special events to execute at low level.");
- Vspecial_event_map = Fcons (intern ("keymap"), Qnil);
-
- DEFVAR_LISP ("track-mouse", &do_mouse_tracking,
- "*Non-nil means generate motion events for mouse motion.");
-
- DEFVAR_KBOARD ("system-key-alist", Vsystem_key_alist,
- "Alist of system-specific X windows key symbols.\n\
-Each element should have the form (N . SYMBOL) where N is the\n\
-numeric keysym code (sans the \"system-specific\" bit 1<<28)\n\
-and SYMBOL is its name.");
-
- DEFVAR_LISP ("deferred-action-list", &Vdeferred_action_list,
- "List of deferred actions to be performed at a later time.\n\
-The precise format isn't relevant here; we just check whether it is nil.");
- Vdeferred_action_list = Qnil;
-
- DEFVAR_LISP ("deferred-action-function", &Vdeferred_action_function,
- "Function to call to handle deferred actions, after each command.\n\
-This function is called with no arguments after each command\n\
-whenever `deferred-action-list' is non-nil.");
- Vdeferred_action_function = Qnil;
-
- DEFVAR_LISP ("suggest-key-bindings", &Vsuggest_key_bindings,
- "Non-nil means show the equivalent key-binding when M-x command has one.\n\
-The value can be a length of time to show the message for.\n\
-If the value is non-nil and not a number, we wait 2 seconds.");
- Vsuggest_key_bindings = Qt;
-
- DEFVAR_LISP ("timer-list", &Vtimer_list,
- "List of active absolute time timers in order of increasing time");
- Vtimer_list = Qnil;
-
- DEFVAR_LISP ("timer-idle-list", &Vtimer_idle_list,
- "List of active idle-time timers in order of increasing time");
- Vtimer_idle_list = Qnil;
-}
-
-keys_of_keyboard ()
-{
- initial_define_key (global_map, Ctl ('Z'), "suspend-emacs");
- initial_define_key (control_x_map, Ctl ('Z'), "suspend-emacs");
- initial_define_key (meta_map, Ctl ('C'), "exit-recursive-edit");
- initial_define_key (global_map, Ctl (']'), "abort-recursive-edit");
- initial_define_key (meta_map, 'x', "execute-extended-command");
-
- initial_define_lispy_key (Vspecial_event_map, "delete-frame",
- "handle-delete-frame");
- initial_define_lispy_key (Vspecial_event_map, "iconify-frame",
- "ignore-event");
- initial_define_lispy_key (Vspecial_event_map, "make-frame-visible",
- "ignore-event");
-}
diff --git a/src/keyboard.h b/src/keyboard.h
deleted file mode 100644
index 1c36e11d1b8..00000000000
--- a/src/keyboard.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/* Declarations useful when processing input.
- Copyright (C) 1985, 1986, 1987, 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Length of echobuf field in each KBOARD. */
-
-#define ECHOBUFSIZE 300
-
-/* Each KBOARD represents one logical input stream from which Emacs gets input.
- If we are using an ordinary terminal, it has one KBOARD object.
- Usually each X display screen has its own KBOARD,
- but when two of them are on the same X server,
- we assume they share a keyboard and give them one KBOARD in common.
-
- Some Lisp variables are per-kboard; they are stored in the KBOARD structure
- and accessed indirectly via a Lisp_Misc_Kboard_Objfwd object.
-
- So that definition of keyboard macros, and reading of prefix arguments,
- can happen in parallel on various KBOARDs at once,
- the state information for those activities is stored in the KBOARD.
-
- Emacs has two states for reading input:
-
- ** Any kboard. Emacs can accept input from any KBOARD,
- and as soon as any of them provides a complete command, Emacs can run it.
-
- ** Single kboard. Then Emacs is running a command for one KBOARD
- and can only read input from that KBOARD.
-
- All input, from all KBOARDs, goes together in a single event queue
- at interrupt level. read_char sees the events sequentially,
- but deals with them in accord with the current input state.
-
- In the any-kboard state, read_key_sequence processes input from any KBOARD
- immediately. When a new event comes in from a particular KBOARD,
- read_key_sequence switches to that KBOARD. As a result,
- as soon as a complete key arrives from some KBOARD or other,
- Emacs starts executing that key's binding. It switches to the
- single-kboard state for the execution of that command,
- so that that command can get input only from its own KBOARD.
-
- While in the single-kboard state, read_char can consider input only
- from the current KBOARD. If events come from other KBOARDs, they
- are put aside for later in the KBOARDs' kbd_queue lists.
- The flag kbd_queue_has_data in a KBOARD is 1 if this has happened.
- When Emacs goes back to the any-kboard state, it looks at all the KBOARDS
- to find those; and it tries processing their input right away. */
-
-typedef struct kboard KBOARD;
-struct kboard
- {
- KBOARD *next_kboard;
-
- /* If non-nil, a keymap that overrides all others but applies only to
- this KBOARD. Lisp code that uses this instead of calling read-char
- can effectively wait for input in the any-kboard state, and hence
- avoid blocking out the other KBOARDs. See universal-argument in
- lisp/simple.el for an example. */
- Lisp_Object Voverriding_terminal_local_map;
-
- /* Last command executed by the editor command loop, not counting
- commands that set the prefix argument. */
- Lisp_Object Vlast_command;
-
- /* The prefix argument for the next command, in raw form. */
- Lisp_Object Vprefix_arg;
-
- /* Unread events specific to this kboard. */
- Lisp_Object kbd_queue;
-
- /* Non-nil while a kbd macro is being defined. */
- Lisp_Object defining_kbd_macro;
-
- /* The start of storage for the current keyboard macro. */
- Lisp_Object *kbd_macro_buffer;
-
- /* Where to store the next keystroke of the macro. */
- Lisp_Object *kbd_macro_ptr;
-
- /* The finalized section of the macro starts at kbd_macro_buffer and
- ends before this. This is not the same as kbd_macro_ptr, because
- we advance this to kbd_macro_ptr when a key's command is complete.
- This way, the keystrokes for "end-kbd-macro" are not included in the
- macro. */
- Lisp_Object *kbd_macro_end;
-
- /* Allocated size of kbd_macro_buffer. */
- int kbd_macro_bufsize;
-
- /* Last anonymous kbd macro defined. */
- Lisp_Object Vlast_kbd_macro;
-
- /* Alist of system-specific X windows key symbols. */
- Lisp_Object Vsystem_key_alist;
-
- /* Cache for modify_event_symbol. */
- Lisp_Object system_key_syms;
-
- /* Minibufferless frames on this display use this frame's minibuffer. */
- Lisp_Object Vdefault_minibuffer_frame;
-
- /* Number of displays using this KBOARD. Normally 1, but can be
- larger when you have multiple screens on a single X display. */
- int reference_count;
-
- /* Where to append more text to echobuf if we want to. */
- char *echoptr;
-
- /* The text we're echoing in the modeline - partial key sequences,
- usually. '\0'-terminated. This really shouldn't have a fixed size. */
- char echobuf[ECHOBUFSIZE];
-
- /* This flag indicates that events were put into kbd_queue
- while Emacs was running for some other KBOARD.
- The flag means that, when Emacs goes into the any-kboard state again,
- it should check this KBOARD to see if there is a complete command
- waiting.
-
- Note that the kbd_queue field can be non-nil even when
- kbd_queue_has_data is 0. When we push back an incomplete
- command, then this flag is 0, meaning we don't want to try
- reading from this KBOARD again until more input arrives. */
- char kbd_queue_has_data;
-
- /* Nonzero means echo each character as typed. */
- char immediate_echo;
-
- /* If we have echoed a prompt string specified by the user,
- this is its length. Otherwise this is -1. */
- char echo_after_prompt;
- };
-
-#ifdef MULTI_KBOARD
-/* Temporarily used before a frame has been opened, and for termcap frames */
-extern KBOARD *initial_kboard;
-
-/* In the single-kboard state, this is the kboard
- from which input is accepted.
-
- In the any-kboard state, this is the kboard from which we are
- right now considering input. We can consider input from another
- kboard, but doing so requires throwing to wrong_kboard_jmpbuf. */
-extern KBOARD *current_kboard;
-
-/* A list of all kboard objects, linked through next_kboard. */
-extern KBOARD *all_kboards;
-
-/* Nonzero in the single-kboard state, 0 in the any-kboard state. */
-extern int single_kboard;
-#else
-extern KBOARD the_only_kboard;
-#define current_kboard (&the_only_kboard)
-#define all_kboards (&the_only_kboard)
-#define single_kboard 1
-#endif
-
-extern Lisp_Object Vlucid_menu_bar_dirty_flag;
-extern Lisp_Object Qrecompute_lucid_menubar, Qactivate_menubar_hook;
-
-/* Total number of times read_char has returned. */
-extern int num_input_chars;
-
-/* Total number of times read_char has returned, outside of macros. */
-extern int num_nonmacro_input_chars;
-
-/* Nonzero means polling for input is temporarily suppressed. */
-extern int poll_suppress_count;
-
-/* Nonzero if polling_for_input is actually being used. */
-extern int polling_for_input;
-
-/* Keymap mapping ASCII function key sequences onto their preferred forms.
- Initialized by the terminal-specific lisp files. */
-extern Lisp_Object Vfunction_key_map;
-
-/* Vector holding the key sequence that invoked the current command.
- It is reused for each command, and it may be longer than the current
- sequence; this_command_key_count indicates how many elements
- actually mean something. */
-extern Lisp_Object this_command_keys;
-extern int this_command_key_count;
-
-/* The frame in which the last input event occurred, or Qmacro if the
- last event came from a macro. We use this to determine when to
- generate switch-frame events. This may be cleared by functions
- like Fselect_frame, to make sure that a switch-frame event is
- generated by the next character. */
-extern Lisp_Object internal_last_event_frame;
-
-/* Macros for dealing with lispy events. */
-
-/* True iff EVENT has data fields describing it (i.e. a mouse click). */
-#define EVENT_HAS_PARAMETERS(event) (CONSP (event))
-
-/* Extract the head from an event.
- This works on composite and simple events. */
-#define EVENT_HEAD(event) \
- (EVENT_HAS_PARAMETERS (event) ? XCONS (event)->car : (event))
-
-/* Extract the starting and ending positions from a composite event. */
-#define EVENT_START(event) (XCONS (XCONS (event)->cdr)->car)
-#define EVENT_END(event) (XCONS (XCONS (XCONS (event)->cdr)->cdr)->car)
-
-/* Extract the click count from a multi-click event. */
-#define EVENT_CLICK_COUNT(event) (Fnth ((event), make_number (2)))
-
-/* Extract the fields of a position. */
-#define POSN_WINDOW(posn) (XCONS (posn)->car)
-#define POSN_BUFFER_POSN(posn) (XCONS (XCONS (posn)->cdr)->car)
-#define POSN_WINDOW_POSN(posn) (XCONS (XCONS (XCONS (posn)->cdr)->cdr)->car)
-#define POSN_TIMESTAMP(posn) \
- (XCONS (XCONS (XCONS (XCONS (posn)->cdr)->cdr)->cdr)->car)
-#define POSN_SCROLLBAR_PART(posn) (Fnth ((posn), make_number (4)))
-
-/* Some of the event heads. */
-extern Lisp_Object Qswitch_frame;
-
-/* Properties on event heads. */
-extern Lisp_Object Qevent_kind, Qevent_symbol_elements;
-
-/* Getting an unmodified version of an event head. */
-#define EVENT_HEAD_UNMODIFIED(event_head) \
- (Fcar (Fget ((event_head), Qevent_symbol_elements)))
-
-/* The values of Qevent_kind properties. */
-extern Lisp_Object Qfunction_key, Qmouse_click, Qmouse_movement;
-extern Lisp_Object Qscroll_bar_movement;
-
-/* Getting the kind of an event head. */
-#define EVENT_HEAD_KIND(event_head) \
- (Fget ((event_head), Qevent_kind))
-
-/* Symbols to use for non-text mouse positions. */
-extern Lisp_Object Qmode_line, Qvertical_line;
-
-extern Lisp_Object get_keymap_1 ();
-extern Lisp_Object Fkeymapp ();
-extern Lisp_Object reorder_modifiers ();
-extern Lisp_Object read_char ();
-/* User-supplied string to translate input characters through. */
-extern Lisp_Object Vkeyboard_translate_table;
-
-extern Lisp_Object map_prompt ();
diff --git a/src/keymap.c b/src/keymap.c
deleted file mode 100644
index 3443b71ef51..00000000000
--- a/src/keymap.c
+++ /dev/null
@@ -1,2838 +0,0 @@
-/* Manipulation of keymaps
- Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include <stdio.h>
-#undef NULL
-#include "lisp.h"
-#include "commands.h"
-#include "buffer.h"
-#include "keyboard.h"
-#include "termhooks.h"
-#include "blockinput.h"
-#include "puresize.h"
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
-/* The number of elements in keymap vectors. */
-#define DENSE_TABLE_SIZE (0200)
-
-/* Actually allocate storage for these variables */
-
-Lisp_Object current_global_map; /* Current global keymap */
-
-Lisp_Object global_map; /* default global key bindings */
-
-Lisp_Object meta_map; /* The keymap used for globally bound
- ESC-prefixed default commands */
-
-Lisp_Object control_x_map; /* The keymap used for globally bound
- C-x-prefixed default commands */
-
-/* was MinibufLocalMap */
-Lisp_Object Vminibuffer_local_map;
- /* The keymap used by the minibuf for local
- bindings when spaces are allowed in the
- minibuf */
-
-/* was MinibufLocalNSMap */
-Lisp_Object Vminibuffer_local_ns_map;
- /* The keymap used by the minibuf for local
- bindings when spaces are not encouraged
- in the minibuf */
-
-/* keymap used for minibuffers when doing completion */
-/* was MinibufLocalCompletionMap */
-Lisp_Object Vminibuffer_local_completion_map;
-
-/* keymap used for minibuffers when doing completion and require a match */
-/* was MinibufLocalMustMatchMap */
-Lisp_Object Vminibuffer_local_must_match_map;
-
-/* Alist of minor mode variables and keymaps. */
-Lisp_Object Vminor_mode_map_alist;
-
-/* Keymap mapping ASCII function key sequences onto their preferred forms.
- Initialized by the terminal-specific lisp files. See DEFVAR for more
- documentation. */
-Lisp_Object Vfunction_key_map;
-
-/* Keymap mapping ASCII function key sequences onto their preferred forms. */
-Lisp_Object Vkey_translation_map;
-
-/* A list of all commands given new bindings since a certain time
- when nil was stored here.
- This is used to speed up recomputation of menu key equivalents
- when Emacs starts up. t means don't record anything here. */
-Lisp_Object Vdefine_key_rebound_commands;
-
-Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii;
-
-/* A char with the CHAR_META bit set in a vector or the 0200 bit set
- in a string key sequence is equivalent to prefixing with this
- character. */
-extern Lisp_Object meta_prefix_char;
-
-extern Lisp_Object Voverriding_local_map;
-
-static Lisp_Object define_as_prefix ();
-static Lisp_Object describe_buffer_bindings ();
-static void describe_command (), describe_translation ();
-static void describe_map ();
-
-/* Keymap object support - constructors and predicates. */
-
-DEFUN ("make-keymap", Fmake_keymap, Smake_keymap, 0, 1, 0,
- "Construct and return a new keymap, of the form (keymap VECTOR . ALIST).\n\
-VECTOR is a vector which holds the bindings for the ASCII\n\
-characters. ALIST is an assoc-list which holds bindings for function keys,\n\
-mouse events, and any other things that appear in the input stream.\n\
-All entries in it are initially nil, meaning \"command undefined\".\n\n\
-The optional arg STRING supplies a menu name for the keymap\n\
-in case you use it as a menu with `x-popup-menu'.")
- (string)
- Lisp_Object string;
-{
- Lisp_Object tail;
- if (!NILP (string))
- tail = Fcons (string, Qnil);
- else
- tail = Qnil;
- return Fcons (Qkeymap,
- Fcons (Fmake_vector (make_number (DENSE_TABLE_SIZE), Qnil),
- tail));
-}
-
-DEFUN ("make-sparse-keymap", Fmake_sparse_keymap, Smake_sparse_keymap, 0, 1, 0,
- "Construct and return a new sparse-keymap list.\n\
-Its car is `keymap' and its cdr is an alist of (CHAR . DEFINITION),\n\
-which binds the character CHAR to DEFINITION, or (SYMBOL . DEFINITION),\n\
-which binds the function key or mouse event SYMBOL to DEFINITION.\n\
-Initially the alist is nil.\n\n\
-The optional arg STRING supplies a menu name for the keymap\n\
-in case you use it as a menu with `x-popup-menu'.")
- (string)
- Lisp_Object string;
-{
- if (!NILP (string))
- return Fcons (Qkeymap, Fcons (string, Qnil));
- return Fcons (Qkeymap, Qnil);
-}
-
-/* This function is used for installing the standard key bindings
- at initialization time.
-
- For example:
-
- initial_define_key (control_x_map, Ctl('X'), "exchange-point-and-mark"); */
-
-void
-initial_define_key (keymap, key, defname)
- Lisp_Object keymap;
- int key;
- char *defname;
-{
- store_in_keymap (keymap, make_number (key), intern (defname));
-}
-
-void
-initial_define_lispy_key (keymap, keyname, defname)
- Lisp_Object keymap;
- char *keyname;
- char *defname;
-{
- store_in_keymap (keymap, intern (keyname), 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. */
-
-#if 0
-void
-synkey (frommap, fromchar, tomap, tochar)
- struct Lisp_Vector *frommap, *tomap;
- int fromchar, tochar;
-{
- Lisp_Object v, c;
- XSETVECTOR (v, tomap);
- XSETFASTINT (c, tochar);
- frommap->contents[fromchar] = Fcons (v, c);
-}
-#endif /* 0 */
-
-DEFUN ("keymapp", Fkeymapp, Skeymapp, 1, 1, 0,
- "Return t if OBJECT is a keymap.\n\
-\n\
-A keymap is a list (keymap . ALIST),\n\
-or a symbol whose function definition is itself a keymap.\n\
-ALIST elements look like (CHAR . DEFN) or (SYMBOL . DEFN);\n\
-a vector of densely packed bindings for small character codes\n\
-is also allowed as an element.")
- (object)
- Lisp_Object object;
-{
- return (NILP (get_keymap_1 (object, 0, 0)) ? Qnil : Qt);
-}
-
-/* Check that OBJECT is a keymap (after dereferencing through any
- symbols). If it is, return it.
-
- If AUTOLOAD is non-zero and OBJECT is a symbol whose function value
- is an autoload form, do the autoload and try again.
- If AUTOLOAD is nonzero, callers must assume GC is possible.
-
- ERROR controls how we respond if OBJECT isn't a keymap.
- If ERROR is non-zero, signal an error; otherwise, just return Qnil.
-
- Note that most of the time, we don't want to pursue autoloads.
- Functions like Faccessible_keymaps which scan entire keymap trees
- shouldn't load every autoloaded keymap. I'm not sure about this,
- but it seems to me that only read_key_sequence, Flookup_key, and
- Fdefine_key should cause keymaps to be autoloaded. */
-
-Lisp_Object
-get_keymap_1 (object, error, autoload)
- Lisp_Object object;
- int error, autoload;
-{
- Lisp_Object tem;
-
- autoload_retry:
- tem = indirect_function (object);
- if (CONSP (tem) && EQ (XCONS (tem)->car, Qkeymap))
- return tem;
-
- /* Should we do an autoload? Autoload forms for keymaps have
- Qkeymap as their fifth element. */
- if (autoload
- && SYMBOLP (object)
- && CONSP (tem)
- && EQ (XCONS (tem)->car, Qautoload))
- {
- Lisp_Object tail;
-
- tail = Fnth (make_number (4), tem);
- if (EQ (tail, Qkeymap))
- {
- struct gcpro gcpro1, gcpro2;
-
- GCPRO2 (tem, object);
- do_autoload (tem, object);
- UNGCPRO;
-
- goto autoload_retry;
- }
- }
-
- if (error)
- wrong_type_argument (Qkeymapp, object);
- else
- return Qnil;
-}
-
-
-/* Follow any symbol chaining, and return the keymap denoted by OBJECT.
- If OBJECT doesn't denote a keymap at all, signal an error. */
-Lisp_Object
-get_keymap (object)
- Lisp_Object object;
-{
- return get_keymap_1 (object, 1, 0);
-}
-
-/* Return the parent map of the keymap MAP, or nil if it has none.
- We assume that MAP is a valid keymap. */
-
-DEFUN ("keymap-parent", Fkeymap_parent, Skeymap_parent, 1, 1, 0,
- "Return the parent keymap of KEYMAP.")
- (keymap)
- Lisp_Object keymap;
-{
- Lisp_Object list;
-
- keymap = get_keymap_1 (keymap, 1, 1);
-
- /* Skip past the initial element `keymap'. */
- list = XCONS (keymap)->cdr;
- for (; CONSP (list); list = XCONS (list)->cdr)
- {
- /* See if there is another `keymap'. */
- if (EQ (Qkeymap, XCONS (list)->car))
- return list;
- }
-
- return Qnil;
-}
-
-/* Set the parent keymap of MAP to PARENT. */
-
-DEFUN ("set-keymap-parent", Fset_keymap_parent, Sset_keymap_parent, 2, 2, 0,
- "Modify KEYMAP to set its parent map to PARENT.\n\
-PARENT should be nil or another keymap.")
- (keymap, parent)
- Lisp_Object keymap, parent;
-{
- Lisp_Object list, prev;
- int i;
-
- keymap = get_keymap_1 (keymap, 1, 1);
- if (!NILP (parent))
- parent = get_keymap_1 (parent, 1, 1);
-
- /* Skip past the initial element `keymap'. */
- prev = keymap;
- while (1)
- {
- list = XCONS (prev)->cdr;
- /* If there is a parent keymap here, replace it.
- If we came to the end, add the parent in PREV. */
- if (! CONSP (list) || EQ (Qkeymap, XCONS (list)->car))
- {
- /* If we already have the right parent, return now
- so that we avoid the loops below. */
- if (EQ (XCONS (prev)->cdr, parent))
- return parent;
-
- XCONS (prev)->cdr = parent;
- break;
- }
- prev = list;
- }
-
- /* Scan through for submaps, and set their parents too. */
-
- for (list = XCONS (keymap)->cdr; CONSP (list); list = XCONS (list)->cdr)
- {
- /* Stop the scan when we come to the parent. */
- if (EQ (XCONS (list)->car, Qkeymap))
- break;
-
- /* If this element holds a prefix map, deal with it. */
- if (CONSP (XCONS (list)->car)
- && CONSP (XCONS (XCONS (list)->car)->cdr))
- fix_submap_inheritance (keymap, XCONS (XCONS (list)->car)->car,
- XCONS (XCONS (list)->car)->cdr);
-
- if (VECTORP (XCONS (list)->car))
- for (i = 0; i < XVECTOR (XCONS (list)->car)->size; i++)
- if (CONSP (XVECTOR (XCONS (list)->car)->contents[i]))
- fix_submap_inheritance (keymap, make_number (i),
- XVECTOR (XCONS (list)->car)->contents[i]);
- }
-
- return parent;
-}
-
-/* EVENT is defined in MAP as a prefix, and SUBMAP is its definition.
- if EVENT is also a prefix in MAP's parent,
- make sure that SUBMAP inherits that definition as its own parent. */
-
-fix_submap_inheritance (map, event, submap)
- Lisp_Object map, event, submap;
-{
- Lisp_Object map_parent, parent_entry;
-
- /* SUBMAP is a cons that we found as a key binding.
- Discard the other things found in a menu key binding. */
-
- if (CONSP (submap)
- && STRINGP (XCONS (submap)->car))
- {
- submap = XCONS (submap)->cdr;
- /* Also remove a menu help string, if any,
- following the menu item name. */
- if (CONSP (submap) && STRINGP (XCONS (submap)->car))
- submap = XCONS (submap)->cdr;
- /* Also remove the sublist that caches key equivalences, if any. */
- if (CONSP (submap)
- && CONSP (XCONS (submap)->car))
- {
- Lisp_Object carcar;
- carcar = XCONS (XCONS (submap)->car)->car;
- if (NILP (carcar) || VECTORP (carcar))
- submap = XCONS (submap)->cdr;
- }
- }
-
- /* If it isn't a keymap now, there's no work to do. */
- if (! CONSP (submap)
- || ! EQ (XCONS (submap)->car, Qkeymap))
- return;
-
- map_parent = Fkeymap_parent (map);
- if (! NILP (map_parent))
- parent_entry = access_keymap (map_parent, event, 0, 0);
- else
- parent_entry = Qnil;
-
- /* If MAP's parent has something other than a keymap,
- our own submap shadows it completely, so use nil as SUBMAP's parent. */
- if (! (CONSP (parent_entry) && EQ (XCONS (parent_entry)->car, Qkeymap)))
- parent_entry = Qnil;
-
- if (! EQ (parent_entry, submap))
- Fset_keymap_parent (submap, parent_entry);
-}
-
-/* Look up IDX in MAP. IDX may be any sort of event.
- Note that this does only one level of lookup; IDX must be a single
- event, not a sequence.
-
- If T_OK is non-zero, bindings for Qt are treated as default
- bindings; any key left unmentioned by other tables and bindings is
- given the binding of Qt.
-
- If T_OK is zero, bindings for Qt are not treated specially.
-
- If NOINHERIT, don't accept a subkeymap found in an inherited keymap. */
-
-Lisp_Object
-access_keymap (map, idx, t_ok, noinherit)
- Lisp_Object map;
- Lisp_Object idx;
- int t_ok;
- int noinherit;
-{
- int noprefix = 0;
- Lisp_Object val;
-
- /* If idx is a list (some sort of mouse click, perhaps?),
- the index we want to use is the car of the list, which
- ought to be a symbol. */
- idx = EVENT_HEAD (idx);
-
- /* If idx is a symbol, it might have modifiers, which need to
- be put in the canonical order. */
- if (SYMBOLP (idx))
- idx = reorder_modifiers (idx);
- else if (INTEGERP (idx))
- /* Clobber the high bits that can be present on a machine
- with more than 24 bits of integer. */
- XSETFASTINT (idx, XINT (idx) & (CHAR_META | (CHAR_META - 1)));
-
- {
- Lisp_Object tail;
- Lisp_Object t_binding;
-
- t_binding = Qnil;
- for (tail = map; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- Lisp_Object binding;
-
- binding = XCONS (tail)->car;
- if (SYMBOLP (binding))
- {
- /* If NOINHERIT, stop finding prefix definitions
- after we pass a second occurrence of the `keymap' symbol. */
- if (noinherit && EQ (binding, Qkeymap) && ! EQ (tail, map))
- noprefix = 1;
- }
- else if (CONSP (binding))
- {
- if (EQ (XCONS (binding)->car, idx))
- {
- val = XCONS (binding)->cdr;
- if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap))
- return Qnil;
- if (CONSP (val))
- fix_submap_inheritance (map, idx, val);
- return val;
- }
- if (t_ok && EQ (XCONS (binding)->car, Qt))
- t_binding = XCONS (binding)->cdr;
- }
- else if (VECTORP (binding))
- {
- if (NATNUMP (idx) && XFASTINT (idx) < XVECTOR (binding)->size)
- {
- val = XVECTOR (binding)->contents[XFASTINT (idx)];
- if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap))
- return Qnil;
- if (CONSP (val))
- fix_submap_inheritance (map, idx, val);
- return val;
- }
- }
-
- QUIT;
- }
-
- return t_binding;
- }
-}
-
-/* Given OBJECT which was found in a slot in a keymap,
- trace indirect definitions to get the actual definition of that slot.
- An indirect definition is a list of the form
- (KEYMAP . INDEX), where KEYMAP is a keymap or a symbol defined as one
- and INDEX is the object to look up in KEYMAP to yield the definition.
-
- Also if OBJECT has a menu string as the first element,
- remove that. Also remove a menu help string as second element.
-
- If AUTOLOAD is nonzero, load autoloadable keymaps
- that are referred to with indirection. */
-
-Lisp_Object
-get_keyelt (object, autoload)
- register Lisp_Object object;
- int autoload;
-{
- while (1)
- {
- register Lisp_Object map, tem;
-
- /* If the contents are (KEYMAP . ELEMENT), go indirect. */
- map = get_keymap_1 (Fcar_safe (object), 0, autoload);
- tem = Fkeymapp (map);
- if (!NILP (tem))
- object = access_keymap (map, Fcdr (object), 0, 0);
-
- /* If the keymap contents looks like (STRING . DEFN),
- use DEFN.
- Keymap alist elements like (CHAR MENUSTRING . DEFN)
- will be used by HierarKey menus. */
- else if (CONSP (object)
- && STRINGP (XCONS (object)->car))
- {
- object = XCONS (object)->cdr;
- /* Also remove a menu help string, if any,
- following the menu item name. */
- if (CONSP (object) && STRINGP (XCONS (object)->car))
- object = XCONS (object)->cdr;
- /* Also remove the sublist that caches key equivalences, if any. */
- if (CONSP (object)
- && CONSP (XCONS (object)->car))
- {
- Lisp_Object carcar;
- carcar = XCONS (XCONS (object)->car)->car;
- if (NILP (carcar) || VECTORP (carcar))
- object = XCONS (object)->cdr;
- }
- }
-
- else
- /* Anything else is really the value. */
- return object;
- }
-}
-
-Lisp_Object
-store_in_keymap (keymap, idx, def)
- Lisp_Object keymap;
- register Lisp_Object idx;
- register Lisp_Object def;
-{
- /* If we are preparing to dump, and DEF is a menu element
- with a menu item string, copy it to ensure it is not pure. */
- if (CONSP (def) && PURE_P (def) && STRINGP (XCONS (def)->car))
- def = Fcons (XCONS (def)->car, XCONS (def)->cdr);
-
- if (!CONSP (keymap) || ! EQ (XCONS (keymap)->car, Qkeymap))
- error ("attempt to define a key in a non-keymap");
-
- /* If idx is a list (some sort of mouse click, perhaps?),
- the index we want to use is the car of the list, which
- ought to be a symbol. */
- idx = EVENT_HEAD (idx);
-
- /* If idx is a symbol, it might have modifiers, which need to
- be put in the canonical order. */
- if (SYMBOLP (idx))
- idx = reorder_modifiers (idx);
- else if (INTEGERP (idx))
- /* Clobber the high bits that can be present on a machine
- with more than 24 bits of integer. */
- XSETFASTINT (idx, XINT (idx) & (CHAR_META | (CHAR_META - 1)));
-
- /* Scan the keymap for a binding of idx. */
- {
- Lisp_Object tail;
-
- /* The cons after which we should insert new bindings. If the
- keymap has a table element, we record its position here, so new
- bindings will go after it; this way, the table will stay
- towards the front of the alist and character lookups in dense
- keymaps will remain fast. Otherwise, this just points at the
- front of the keymap. */
- Lisp_Object insertion_point;
-
- insertion_point = keymap;
- for (tail = XCONS (keymap)->cdr; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- Lisp_Object elt;
-
- elt = XCONS (tail)->car;
- if (VECTORP (elt))
- {
- if (NATNUMP (idx) && XFASTINT (idx) < XVECTOR (elt)->size)
- {
- XVECTOR (elt)->contents[XFASTINT (idx)] = def;
- return def;
- }
- insertion_point = tail;
- }
- else if (CONSP (elt))
- {
- if (EQ (idx, XCONS (elt)->car))
- {
- XCONS (elt)->cdr = def;
- return def;
- }
- }
- else if (SYMBOLP (elt))
- {
- /* If we find a 'keymap' symbol in the spine of KEYMAP,
- then we must have found the start of a second keymap
- being used as the tail of KEYMAP, and a binding for IDX
- should be inserted before it. */
- if (EQ (elt, Qkeymap))
- goto keymap_end;
- }
-
- QUIT;
- }
-
- keymap_end:
- /* We have scanned the entire keymap, and not found a binding for
- IDX. Let's add one. */
- XCONS (insertion_point)->cdr
- = Fcons (Fcons (idx, def), XCONS (insertion_point)->cdr);
- }
-
- 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, tail;
-
- copy = Fcopy_alist (get_keymap (keymap));
-
- for (tail = copy; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- Lisp_Object elt;
-
- elt = XCONS (tail)->car;
- if (VECTORP (elt))
- {
- int i;
-
- elt = Fcopy_sequence (elt);
- XCONS (tail)->car = elt;
-
- for (i = 0; i < XVECTOR (elt)->size; i++)
- if (!SYMBOLP (XVECTOR (elt)->contents[i])
- && ! NILP (Fkeymapp (XVECTOR (elt)->contents[i])))
- XVECTOR (elt)->contents[i] =
- Fcopy_keymap (XVECTOR (elt)->contents[i]);
- }
- else if (CONSP (elt))
- {
- /* Skip the optional menu string. */
- if (CONSP (XCONS (elt)->cdr)
- && STRINGP (XCONS (XCONS (elt)->cdr)->car))
- {
- Lisp_Object tem;
-
- /* Copy the cell, since copy-alist didn't go this deep. */
- XCONS (elt)->cdr = Fcons (XCONS (XCONS (elt)->cdr)->car,
- XCONS (XCONS (elt)->cdr)->cdr);
- elt = XCONS (elt)->cdr;
-
- /* Also skip the optional menu help string. */
- if (CONSP (XCONS (elt)->cdr)
- && STRINGP (XCONS (XCONS (elt)->cdr)->car))
- {
- XCONS (elt)->cdr = Fcons (XCONS (XCONS (elt)->cdr)->car,
- XCONS (XCONS (elt)->cdr)->cdr);
- elt = XCONS (elt)->cdr;
- }
- /* There may also be a list that caches key equivalences.
- Just delete it for the new keymap. */
- if (CONSP (XCONS (elt)->cdr)
- && CONSP (XCONS (XCONS (elt)->cdr)->car)
- && (NILP (tem = XCONS (XCONS (XCONS (elt)->cdr)->car)->car)
- || VECTORP (tem)))
- XCONS (elt)->cdr = XCONS (XCONS (elt)->cdr)->cdr;
- }
- if (CONSP (elt)
- && ! SYMBOLP (XCONS (elt)->cdr)
- && ! NILP (Fkeymapp (XCONS (elt)->cdr)))
- XCONS (elt)->cdr = Fcopy_keymap (XCONS (elt)->cdr);
- }
- }
-
- return copy;
-}
-
-/* Simple Keymap mutators and accessors. */
-
-/* GC is possible in this function if it autoloads a keymap. */
-
-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 or a vector of symbols and characters\n\
-meaning a sequence of keystrokes and events.\n\
-Non-ASCII characters with codes above 127 (such as ISO Latin-1)\n\
-can be included if you use a vector.\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 symbol. When the key is looked up, the symbol will stand for its\n\
- function definition, which should at that time be one of the above,\n\
- or another symbol whose function definition is used, etc.\n\
- a cons (STRING . DEFN), meaning that DEFN is the definition\n\
- (DEFN should be a valid definition in its own right),\n\
- or a cons (KEYMAP . CHAR), meaning use definition of CHAR in map KEYMAP.\n\
-\n\
-If KEYMAP is a sparse keymap, the pair binding KEY to DEF is added at\n\
-the front of KEYMAP.")
- (keymap, key, def)
- Lisp_Object keymap;
- Lisp_Object key;
- Lisp_Object def;
-{
- register int idx;
- register Lisp_Object c;
- register Lisp_Object tem;
- register Lisp_Object cmd;
- int metized = 0;
- int meta_bit;
- int length;
- struct gcpro gcpro1, gcpro2, gcpro3;
-
- keymap = get_keymap_1 (keymap, 1, 1);
-
- if (!VECTORP (key) && !STRINGP (key))
- key = wrong_type_argument (Qarrayp, key);
-
- length = XFASTINT (Flength (key));
- if (length == 0)
- return Qnil;
-
- if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt))
- Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands);
-
- GCPRO3 (keymap, key, def);
-
- if (VECTORP (key))
- meta_bit = meta_modifier;
- else
- meta_bit = 0x80;
-
- idx = 0;
- while (1)
- {
- c = Faref (key, make_number (idx));
-
- if (CONSP (c) && lucid_event_type_list_p (c))
- c = Fevent_convert_list (c);
-
- if (INTEGERP (c)
- && (XINT (c) & meta_bit)
- && !metized)
- {
- c = meta_prefix_char;
- metized = 1;
- }
- else
- {
- if (INTEGERP (c))
- XSETINT (c, XINT (c) & ~meta_bit);
-
- metized = 0;
- idx++;
- }
-
- if (! INTEGERP (c) && ! SYMBOLP (c) && ! CONSP (c))
- error ("Key sequence contains invalid events");
-
- if (idx == length)
- RETURN_UNGCPRO (store_in_keymap (keymap, c, def));
-
- cmd = get_keyelt (access_keymap (keymap, c, 0, 1), 1);
-
- /* If this key is undefined, make it a prefix. */
- if (NILP (cmd))
- cmd = define_as_prefix (keymap, c);
-
- keymap = get_keymap_1 (cmd, 0, 1);
- if (NILP (keymap))
- /* We must use Fkey_description rather than just passing key to
- error; key might be a vector, not a string. */
- error ("Key sequence %s uses invalid prefix characters",
- XSTRING (Fkey_description (key))->data);
- }
-}
-
-/* Value is number if KEY is too long; NIL if valid but has no definition. */
-/* GC is possible in this function if it autoloads a keymap. */
-
-DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 3, 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\
-\n\
-A number as value means KEY is \"too long\";\n\
-that is, characters or symbols 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.\n\
-\n\
-Normally, `lookup-key' ignores bindings for t, which act as default\n\
-bindings, used when nothing else in the keymap applies; this makes it\n\
-usable as a general function for probing keymaps. However, if the\n\
-third optional argument ACCEPT-DEFAULT is non-nil, `lookup-key' will\n\
-recognize the default bindings, just as `read-key-sequence' does.")
- (keymap, key, accept_default)
- register Lisp_Object keymap;
- Lisp_Object key;
- Lisp_Object accept_default;
-{
- register int idx;
- register Lisp_Object tem;
- register Lisp_Object cmd;
- register Lisp_Object c;
- int metized = 0;
- int length;
- int t_ok = ! NILP (accept_default);
- int meta_bit;
- struct gcpro gcpro1;
-
- keymap = get_keymap_1 (keymap, 1, 1);
-
- if (!VECTORP (key) && !STRINGP (key))
- key = wrong_type_argument (Qarrayp, key);
-
- length = XFASTINT (Flength (key));
- if (length == 0)
- return keymap;
-
- if (VECTORP (key))
- meta_bit = meta_modifier;
- else
- meta_bit = 0x80;
-
- GCPRO1 (key);
-
- idx = 0;
- while (1)
- {
- c = Faref (key, make_number (idx));
-
- if (CONSP (c) && lucid_event_type_list_p (c))
- c = Fevent_convert_list (c);
-
- if (INTEGERP (c)
- && (XINT (c) & meta_bit)
- && !metized)
- {
- c = meta_prefix_char;
- metized = 1;
- }
- else
- {
- if (INTEGERP (c))
- XSETINT (c, XINT (c) & ~meta_bit);
-
- metized = 0;
- idx++;
- }
-
- cmd = get_keyelt (access_keymap (keymap, c, t_ok, 0), 1);
- if (idx == length)
- RETURN_UNGCPRO (cmd);
-
- keymap = get_keymap_1 (cmd, 0, 1);
- if (NILP (keymap))
- RETURN_UNGCPRO (make_number (idx));
-
- QUIT;
- }
-}
-
-/* Make KEYMAP define event C as a keymap (i.e., as a prefix).
- Assume that currently it does not define C at all.
- Return the keymap. */
-
-static Lisp_Object
-define_as_prefix (keymap, c)
- Lisp_Object keymap, c;
-{
- Lisp_Object inherit, cmd;
-
- cmd = Fmake_sparse_keymap (Qnil);
- /* If this key is defined as a prefix in an inherited keymap,
- make it a prefix in this map, and make its definition
- inherit the other prefix definition. */
- inherit = access_keymap (keymap, c, 0, 0);
-#if 0
- /* This code is needed to do the right thing in the following case:
- keymap A inherits from B,
- you define KEY as a prefix in A,
- then later you define KEY as a prefix in B.
- We want the old prefix definition in A to inherit from that in B.
- It is hard to do that retroactively, so this code
- creates the prefix in B right away.
-
- But it turns out that this code causes problems immediately
- when the prefix in A is defined: it causes B to define KEY
- as a prefix with no subcommands.
-
- So I took out this code. */
- if (NILP (inherit))
- {
- /* If there's an inherited keymap
- and it doesn't define this key,
- make it define this key. */
- Lisp_Object tail;
-
- for (tail = Fcdr (keymap); CONSP (tail); tail = XCONS (tail)->cdr)
- if (EQ (XCONS (tail)->car, Qkeymap))
- break;
-
- if (!NILP (tail))
- inherit = define_as_prefix (tail, c);
- }
-#endif
-
- cmd = nconc2 (cmd, inherit);
- store_in_keymap (keymap, c, cmd);
-
- return cmd;
-}
-
-/* Append a key to the end of a key sequence. We always make a vector. */
-
-Lisp_Object
-append_key (key_sequence, key)
- Lisp_Object key_sequence, key;
-{
- Lisp_Object args[2];
-
- args[0] = key_sequence;
-
- args[1] = Fcons (key, Qnil);
- return Fvconcat (2, args);
-}
-
-
-/* Global, local, and minor mode keymap stuff. */
-
-/* We can't put these variables inside current_minor_maps, since under
- some systems, static gets macro-defined to be the empty string.
- Ickypoo. */
-static Lisp_Object *cmm_modes, *cmm_maps;
-static int cmm_size;
-
-/* Error handler used in current_minor_maps. */
-static Lisp_Object
-current_minor_maps_error ()
-{
- return Qnil;
-}
-
-/* Store a pointer to an array of the keymaps of the currently active
- minor modes in *buf, and return the number of maps it contains.
-
- This function always returns a pointer to the same buffer, and may
- free or reallocate it, so if you want to keep it for a long time or
- hand it out to lisp code, copy it. This procedure will be called
- for every key sequence read, so the nice lispy approach (return a
- new assoclist, list, what have you) for each invocation would
- result in a lot of consing over time.
-
- If we used xrealloc/xmalloc and ran out of memory, they would throw
- back to the command loop, which would try to read a key sequence,
- which would call this function again, resulting in an infinite
- loop. Instead, we'll use realloc/malloc and silently truncate the
- list, let the key sequence be read, and hope some other piece of
- code signals the error. */
-int
-current_minor_maps (modeptr, mapptr)
- Lisp_Object **modeptr, **mapptr;
-{
- int i = 0;
- Lisp_Object alist, assoc, var, val;
-
- for (alist = Vminor_mode_map_alist;
- CONSP (alist);
- alist = XCONS (alist)->cdr)
- if ((assoc = XCONS (alist)->car, CONSP (assoc))
- && (var = XCONS (assoc)->car, SYMBOLP (var))
- && (val = find_symbol_value (var), ! EQ (val, Qunbound))
- && ! NILP (val))
- {
- Lisp_Object temp;
-
- if (i >= cmm_size)
- {
- Lisp_Object *newmodes, *newmaps;
-
- if (cmm_maps)
- {
- BLOCK_INPUT;
- cmm_size *= 2;
- newmodes
- = (Lisp_Object *) realloc (cmm_modes,
- cmm_size * sizeof (Lisp_Object));
- newmaps
- = (Lisp_Object *) realloc (cmm_maps,
- cmm_size * sizeof (Lisp_Object));
- UNBLOCK_INPUT;
- }
- else
- {
- BLOCK_INPUT;
- cmm_size = 30;
- newmodes
- = (Lisp_Object *) malloc (cmm_size * sizeof (Lisp_Object));
- newmaps
- = (Lisp_Object *) malloc (cmm_size * sizeof (Lisp_Object));
- UNBLOCK_INPUT;
- }
-
- if (newmaps && newmodes)
- {
- cmm_modes = newmodes;
- cmm_maps = newmaps;
- }
- else
- break;
- }
-
- /* Get the keymap definition--or nil if it is not defined. */
- temp = internal_condition_case_1 (Findirect_function,
- XCONS (assoc)->cdr,
- Qerror, current_minor_maps_error);
- if (!NILP (temp))
- {
- cmm_modes[i] = var;
- cmm_maps [i] = temp;
- i++;
- }
- }
-
- if (modeptr) *modeptr = cmm_modes;
- if (mapptr) *mapptr = cmm_maps;
- return i;
-}
-
-/* GC is possible in this function if it autoloads a keymap. */
-
-DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 2, 0,
- "Return the binding for command KEY in current keymaps.\n\
-KEY is a string or vector, a sequence of keystrokes.\n\
-The binding is probably a symbol with a function definition.\n\
-\n\
-Normally, `key-binding' ignores bindings for t, which act as default\n\
-bindings, used when nothing else in the keymap applies; this makes it\n\
-usable as a general function for probing keymaps. However, if the\n\
-optional second argument ACCEPT-DEFAULT is non-nil, `key-binding' does\n\
-recognize the default bindings, just as `read-key-sequence' does.")
- (key, accept_default)
- Lisp_Object key, accept_default;
-{
- Lisp_Object *maps, value;
- int nmaps, i;
- struct gcpro gcpro1;
-
- GCPRO1 (key);
-
- if (!NILP (current_kboard->Voverriding_terminal_local_map))
- {
- value = Flookup_key (current_kboard->Voverriding_terminal_local_map,
- key, accept_default);
- if (! NILP (value) && !INTEGERP (value))
- RETURN_UNGCPRO (value);
- }
- else if (!NILP (Voverriding_local_map))
- {
- value = Flookup_key (Voverriding_local_map, key, accept_default);
- if (! NILP (value) && !INTEGERP (value))
- RETURN_UNGCPRO (value);
- }
- else
- {
- Lisp_Object local;
-
- nmaps = current_minor_maps (0, &maps);
- /* Note that all these maps are GCPRO'd
- in the places where we found them. */
-
- for (i = 0; i < nmaps; i++)
- if (! NILP (maps[i]))
- {
- value = Flookup_key (maps[i], key, accept_default);
- if (! NILP (value) && !INTEGERP (value))
- RETURN_UNGCPRO (value);
- }
-
- local = get_local_map (PT, current_buffer);
-
- if (! NILP (local))
- {
- value = Flookup_key (local, key, accept_default);
- if (! NILP (value) && !INTEGERP (value))
- RETURN_UNGCPRO (value);
- }
- }
-
- value = Flookup_key (current_global_map, key, accept_default);
- UNGCPRO;
- if (! NILP (value) && !INTEGERP (value))
- return value;
-
- return Qnil;
-}
-
-/* GC is possible in this function if it autoloads a keymap. */
-
-DEFUN ("local-key-binding", Flocal_key_binding, Slocal_key_binding, 1, 2, 0,
- "Return the binding for command KEYS in current local keymap only.\n\
-KEYS is a string, a sequence of keystrokes.\n\
-The binding is probably a symbol with a function definition.\n\
-\n\
-If optional argument ACCEPT-DEFAULT is non-nil, recognize default\n\
-bindings; see the description of `lookup-key' for more details about this.")
- (keys, accept_default)
- Lisp_Object keys, accept_default;
-{
- register Lisp_Object map;
- map = current_buffer->keymap;
- if (NILP (map))
- return Qnil;
- return Flookup_key (map, keys, accept_default);
-}
-
-/* GC is possible in this function if it autoloads a keymap. */
-
-DEFUN ("global-key-binding", Fglobal_key_binding, Sglobal_key_binding, 1, 2, 0,
- "Return the binding for command KEYS in current global keymap only.\n\
-KEYS is a string, a sequence of keystrokes.\n\
-The binding is probably a symbol with a function definition.\n\
-This function's return values are the same as those of lookup-key\n\
-\(which see).\n\
-\n\
-If optional argument ACCEPT-DEFAULT is non-nil, recognize default\n\
-bindings; see the description of `lookup-key' for more details about this.")
- (keys, accept_default)
- Lisp_Object keys, accept_default;
-{
- return Flookup_key (current_global_map, keys, accept_default);
-}
-
-/* GC is possible in this function if it autoloads a keymap. */
-
-DEFUN ("minor-mode-key-binding", Fminor_mode_key_binding, Sminor_mode_key_binding, 1, 2, 0,
- "Find the visible minor mode bindings of KEY.\n\
-Return an alist of pairs (MODENAME . BINDING), where MODENAME is the\n\
-the symbol which names the minor mode binding KEY, and BINDING is\n\
-KEY's definition in that mode. In particular, if KEY has no\n\
-minor-mode bindings, return nil. If the first binding is a\n\
-non-prefix, all subsequent bindings will be omitted, since they would\n\
-be ignored. Similarly, the list doesn't include non-prefix bindings\n\
-that come after prefix bindings.\n\
-\n\
-If optional argument ACCEPT-DEFAULT is non-nil, recognize default\n\
-bindings; see the description of `lookup-key' for more details about this.")
- (key, accept_default)
- Lisp_Object key, accept_default;
-{
- Lisp_Object *modes, *maps;
- int nmaps;
- Lisp_Object binding;
- int i, j;
- struct gcpro gcpro1, gcpro2;
-
- nmaps = current_minor_maps (&modes, &maps);
- /* Note that all these maps are GCPRO'd
- in the places where we found them. */
-
- binding = Qnil;
- GCPRO2 (key, binding);
-
- for (i = j = 0; i < nmaps; i++)
- if (! NILP (maps[i])
- && ! NILP (binding = Flookup_key (maps[i], key, accept_default))
- && !INTEGERP (binding))
- {
- if (! NILP (get_keymap (binding)))
- maps[j++] = Fcons (modes[i], binding);
- else if (j == 0)
- RETURN_UNGCPRO (Fcons (Fcons (modes[i], binding), Qnil));
- }
-
- UNGCPRO;
- return Flist (j, maps);
-}
-
-DEFUN ("define-prefix-command", Fdefine_prefix_command, Sdefine_prefix_command, 1, 2, 0,
- "Define COMMAND as a prefix command. COMMAND should be a symbol.\n\
-A new sparse keymap is stored as COMMAND's function definition and its value.\n\
-If a second optional argument MAPVAR is given, the map is stored as\n\
-its value instead of as COMMAND's value; but COMMAND is still defined\n\
-as a function.")
- (command, mapvar)
- Lisp_Object command, mapvar;
-{
- Lisp_Object map;
- map = Fmake_sparse_keymap (Qnil);
- Ffset (command, map);
- if (!NILP (mapvar))
- Fset (mapvar, map);
- else
- Fset (command, map);
- return command;
-}
-
-DEFUN ("use-global-map", Fuse_global_map, Suse_global_map, 1, 1, 0,
- "Select KEYMAP as the global keymap.")
- (keymap)
- Lisp_Object keymap;
-{
- keymap = get_keymap (keymap);
- current_global_map = keymap;
-
- return Qnil;
-}
-
-DEFUN ("use-local-map", Fuse_local_map, Suse_local_map, 1, 1, 0,
- "Select KEYMAP as the local keymap.\n\
-If KEYMAP is nil, that means no local keymap.")
- (keymap)
- Lisp_Object keymap;
-{
- if (!NILP (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 current_global_map;
-}
-
-DEFUN ("current-minor-mode-maps", Fcurrent_minor_mode_maps, Scurrent_minor_mode_maps, 0, 0, 0,
- "Return a list of keymaps for the minor modes of the current buffer.")
- ()
-{
- Lisp_Object *maps;
- int nmaps = current_minor_maps (0, &maps);
-
- return Flist (nmaps, maps);
-}
-
-/* Help functions for describing and documenting keymaps. */
-
-/* This function cannot GC. */
-
-DEFUN ("accessible-keymaps", Faccessible_keymaps, Saccessible_keymaps,
- 1, 2, 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).\n\
-An optional argument PREFIX, if non-nil, should be a key sequence;\n\
-then the value includes only maps for prefixes that start with PREFIX.")
- (keymap, prefix)
- Lisp_Object keymap, prefix;
-{
- Lisp_Object maps, good_maps, tail;
- int prefixlen = 0;
-
- /* no need for gcpro because we don't autoload any keymaps. */
-
- if (!NILP (prefix))
- prefixlen = XINT (Flength (prefix));
-
- if (!NILP (prefix))
- {
- /* If a prefix was specified, start with the keymap (if any) for
- that prefix, so we don't waste time considering other prefixes. */
- Lisp_Object tem;
- tem = Flookup_key (keymap, prefix, Qt);
- /* Flookup_key may give us nil, or a number,
- if the prefix is not defined in this particular map.
- It might even give us a list that isn't a keymap. */
- tem = get_keymap_1 (tem, 0, 0);
- if (!NILP (tem))
- maps = Fcons (Fcons (prefix, tem), Qnil);
- else
- return Qnil;
- }
- else
- maps = Fcons (Fcons (Fmake_vector (make_number (0), Qnil),
- get_keymap (keymap)),
- Qnil);
-
- /* 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.
-
- This is a breadth-first traversal, where tail is the queue of
- nodes, and maps accumulates a list of all nodes visited. */
-
- for (tail = maps; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- register Lisp_Object thisseq, thismap;
- Lisp_Object last;
- /* Does the current sequence end in the meta-prefix-char? */
- int is_metized;
-
- thisseq = Fcar (Fcar (tail));
- thismap = Fcdr (Fcar (tail));
- last = make_number (XINT (Flength (thisseq)) - 1);
- is_metized = (XINT (last) >= 0
- && EQ (Faref (thisseq, last), meta_prefix_char));
-
- for (; CONSP (thismap); thismap = XCONS (thismap)->cdr)
- {
- Lisp_Object elt;
-
- elt = XCONS (thismap)->car;
-
- QUIT;
-
- if (VECTORP (elt))
- {
- register int i;
-
- /* Vector keymap. Scan all the elements. */
- for (i = 0; i < XVECTOR (elt)->size; i++)
- {
- register Lisp_Object tem;
- register Lisp_Object cmd;
-
- cmd = get_keyelt (XVECTOR (elt)->contents[i], 0);
- if (NILP (cmd)) continue;
- tem = Fkeymapp (cmd);
- if (!NILP (tem))
- {
- cmd = get_keymap (cmd);
- /* Ignore keymaps that are already added to maps. */
- tem = Frassq (cmd, maps);
- if (NILP (tem))
- {
- /* If the last key in thisseq is meta-prefix-char,
- turn it into a meta-ized keystroke. We know
- that the event we're about to append is an
- ascii keystroke since we're processing a
- keymap table. */
- if (is_metized)
- {
- int meta_bit = meta_modifier;
- tem = Fcopy_sequence (thisseq);
-
- Faset (tem, last, make_number (i | meta_bit));
-
- /* This new sequence is the same length as
- thisseq, so stick it in the list right
- after this one. */
- XCONS (tail)->cdr
- = Fcons (Fcons (tem, cmd), XCONS (tail)->cdr);
- }
- else
- {
- tem = append_key (thisseq, make_number (i));
- nconc2 (tail, Fcons (Fcons (tem, cmd), Qnil));
- }
- }
- }
- }
- }
- else if (CONSP (elt))
- {
- register Lisp_Object cmd, tem, filter;
-
- cmd = get_keyelt (XCONS (elt)->cdr, 0);
- /* Ignore definitions that aren't keymaps themselves. */
- tem = Fkeymapp (cmd);
- if (!NILP (tem))
- {
- /* Ignore keymaps that have been seen already. */
- cmd = get_keymap (cmd);
- tem = Frassq (cmd, maps);
- if (NILP (tem))
- {
- /* Let elt be the event defined by this map entry. */
- elt = XCONS (elt)->car;
-
- /* If the last key in thisseq is meta-prefix-char, and
- this entry is a binding for an ascii keystroke,
- turn it into a meta-ized keystroke. */
- if (is_metized && INTEGERP (elt))
- {
- tem = Fcopy_sequence (thisseq);
- Faset (tem, last,
- make_number (XINT (elt) | meta_modifier));
-
- /* This new sequence is the same length as
- thisseq, so stick it in the list right
- after this one. */
- XCONS (tail)->cdr
- = Fcons (Fcons (tem, cmd), XCONS (tail)->cdr);
- }
- else
- nconc2 (tail,
- Fcons (Fcons (append_key (thisseq, elt), cmd),
- Qnil));
- }
- }
- }
- }
- }
-
- if (NILP (prefix))
- return maps;
-
- /* Now find just the maps whose access prefixes start with PREFIX. */
-
- good_maps = Qnil;
- for (; CONSP (maps); maps = XCONS (maps)->cdr)
- {
- Lisp_Object elt, thisseq;
- elt = XCONS (maps)->car;
- thisseq = XCONS (elt)->car;
- /* The access prefix must be at least as long as PREFIX,
- and the first elements must match those of PREFIX. */
- if (XINT (Flength (thisseq)) >= prefixlen)
- {
- int i;
- for (i = 0; i < prefixlen; i++)
- {
- Lisp_Object i1;
- XSETFASTINT (i1, i);
- if (!EQ (Faref (thisseq, i1), Faref (prefix, i1)))
- break;
- }
- if (i == prefixlen)
- good_maps = Fcons (elt, good_maps);
- }
- }
-
- return Fnreverse (good_maps);
-}
-
-Lisp_Object Qsingle_key_description, Qkey_description;
-
-/* This function cannot GC. */
-
-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;
-{
- int len;
- int i;
- Lisp_Object sep;
- Lisp_Object *args;
-
- if (STRINGP (keys))
- {
- Lisp_Object vector;
- vector = Fmake_vector (Flength (keys), Qnil);
- for (i = 0; i < XSTRING (keys)->size; i++)
- {
- if (XSTRING (keys)->data[i] & 0x80)
- XSETFASTINT (XVECTOR (vector)->contents[i],
- meta_modifier | (XSTRING (keys)->data[i] & ~0x80));
- else
- XSETFASTINT (XVECTOR (vector)->contents[i],
- XSTRING (keys)->data[i]);
- }
- keys = vector;
- }
- else if (!VECTORP (keys))
- keys = wrong_type_argument (Qarrayp, keys);
-
- /* In effect, this computes
- (mapconcat 'single-key-description keys " ")
- but we shouldn't use mapconcat because it can do GC. */
-
- len = XVECTOR (keys)->size;
- sep = build_string (" ");
- /* This has one extra element at the end that we don't pass to Fconcat. */
- args = (Lisp_Object *) alloca (len * 2 * sizeof (Lisp_Object));
-
- for (i = 0; i < len; i++)
- {
- args[i * 2] = Fsingle_key_description (XVECTOR (keys)->contents[i]);
- args[i * 2 + 1] = sep;
- }
-
- return Fconcat (len * 2 - 1, args);
-}
-
-char *
-push_key_description (c, p)
- register unsigned int c;
- register char *p;
-{
- /* Clear all the meaningless bits above the meta bit. */
- c &= meta_modifier | ~ - meta_modifier;
-
- if (c & alt_modifier)
- {
- *p++ = 'A';
- *p++ = '-';
- c -= alt_modifier;
- }
- if (c & ctrl_modifier)
- {
- *p++ = 'C';
- *p++ = '-';
- c -= ctrl_modifier;
- }
- if (c & hyper_modifier)
- {
- *p++ = 'H';
- *p++ = '-';
- c -= hyper_modifier;
- }
- if (c & meta_modifier)
- {
- *p++ = 'M';
- *p++ = '-';
- c -= meta_modifier;
- }
- if (c & shift_modifier)
- {
- *p++ = 'S';
- *p++ = '-';
- c -= shift_modifier;
- }
- if (c & super_modifier)
- {
- *p++ = 's';
- *p++ = '-';
- c -= super_modifier;
- }
- if (c < 040)
- {
- if (c == 033)
- {
- *p++ = 'E';
- *p++ = 'S';
- *p++ = 'C';
- }
- else if (c == '\t')
- {
- *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 if (c < 256)
- *p++ = c;
- else
- {
- *p++ = '\\';
- *p++ = (7 & (c >> 15)) + '0';
- *p++ = (7 & (c >> 12)) + '0';
- *p++ = (7 & (c >> 9)) + '0';
- *p++ = (7 & (c >> 6)) + '0';
- *p++ = (7 & (c >> 3)) + '0';
- *p++ = (7 & (c >> 0)) + '0';
- }
-
- return p;
-}
-
-/* This function cannot GC. */
-
-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;
-{
- char tem[20];
-
- key = EVENT_HEAD (key);
-
- if (INTEGERP (key)) /* Normal character */
- {
- *push_key_description (XUINT (key), tem) = 0;
- return build_string (tem);
- }
- else if (SYMBOLP (key)) /* Function key or event-symbol */
- return Fsymbol_name (key);
- else if (STRINGP (key)) /* Buffer names in the menubar. */
- return Fcopy_sequence (key);
- else
- error ("KEY must be an integer, cons, symbol, or string");
-}
-
-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;
-}
-
-/* This function cannot GC. */
-
-DEFUN ("text-char-description", Ftext_char_description, Stext_char_description, 1, 1, 0,
- "Return a pretty description of file-character CHARACTER.\n\
-Control characters turn into \"^char\", etc.")
- (character)
- Lisp_Object character;
-{
- char tem[6];
-
- CHECK_NUMBER (character, 0);
-
- *push_text_char_description (XINT (character) & 0377, tem) = 0;
-
- return build_string (tem);
-}
-
-/* Return non-zero if SEQ contains only ASCII characters, perhaps with
- a meta bit. */
-static int
-ascii_sequence_p (seq)
- Lisp_Object seq;
-{
- int i;
- int len = XINT (Flength (seq));
-
- for (i = 0; i < len; i++)
- {
- Lisp_Object ii, elt;
-
- XSETFASTINT (ii, i);
- elt = Faref (seq, ii);
-
- if (!INTEGERP (elt)
- || (XUINT (elt) & ~CHAR_META) >= 0x80)
- return 0;
- }
-
- return 1;
-}
-
-
-/* where-is - finding a command in a set of keymaps. */
-
-/* This function can GC if Flookup_key autoloads any keymaps. */
-
-DEFUN ("where-is-internal", Fwhere_is_internal, Swhere_is_internal, 1, 4, 0,
- "Return list of keys that invoke DEFINITION.\n\
-If KEYMAP is non-nil, search only KEYMAP and the global keymap.\n\
-If KEYMAP is nil, search all the currently active keymaps.\n\
-\n\
-If optional 3rd arg FIRSTONLY is non-nil, return the first key sequence found,\n\
-rather than a list of all possible key sequences.\n\
-If FIRSTONLY is the symbol `non-ascii', return the first binding found,\n\
-no matter what it is.\n\
-If FIRSTONLY has another non-nil value, prefer sequences of ASCII characters,\n\
-and entirely reject menu bindings.\n\
-\n\
-If optional 4th arg NOINDIRECT is non-nil, don't follow indirections\n\
-to other keymaps or slots. This makes it possible to search for an\n\
-indirect definition itself.")
- (definition, keymap, firstonly, noindirect)
- Lisp_Object definition, keymap;
- Lisp_Object firstonly, noindirect;
-{
- Lisp_Object maps;
- Lisp_Object found, sequence;
- int keymap_specified = !NILP (keymap);
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
- /* 1 means ignore all menu bindings entirely. */
- int nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii);
-
- if (! keymap_specified)
- {
-#ifdef USE_TEXT_PROPERTIES
- keymap = get_local_map (PT, current_buffer);
-#else
- keymap = current_buffer->keymap;
-#endif
- }
-
- if (!NILP (keymap))
- maps = nconc2 (Faccessible_keymaps (get_keymap (keymap), Qnil),
- Faccessible_keymaps (get_keymap (current_global_map),
- Qnil));
- else
- maps = Faccessible_keymaps (get_keymap (current_global_map), Qnil);
-
- /* Put the minor mode keymaps on the front. */
- if (! keymap_specified)
- {
- Lisp_Object minors;
- minors = Fnreverse (Fcurrent_minor_mode_maps ());
- while (!NILP (minors))
- {
- maps = nconc2 (Faccessible_keymaps (get_keymap (XCONS (minors)->car),
- Qnil),
- maps);
- minors = XCONS (minors)->cdr;
- }
- }
-
- GCPRO5 (definition, keymap, maps, found, sequence);
- found = Qnil;
- sequence = Qnil;
-
- for (; !NILP (maps); maps = Fcdr (maps))
- {
- /* Key sequence to reach map, and the map that it reaches */
- register Lisp_Object this, map;
-
- /* If Fcar (map) is a VECTOR, the current element within that vector. */
- int i = 0;
-
- /* In order to fold [META-PREFIX-CHAR CHAR] sequences into
- [M-CHAR] sequences, check if last character of the sequence
- is the meta-prefix char. */
- Lisp_Object last;
- int last_is_meta;
-
- this = Fcar (Fcar (maps));
- map = Fcdr (Fcar (maps));
- last = make_number (XINT (Flength (this)) - 1);
- last_is_meta = (XINT (last) >= 0
- && EQ (Faref (this, last), meta_prefix_char));
-
- QUIT;
-
- while (CONSP (map))
- {
- /* Because the code we want to run on each binding is rather
- large, we don't want to have two separate loop bodies for
- sparse keymap bindings and tables; we want to iterate one
- loop body over both keymap and vector bindings.
-
- For this reason, if Fcar (map) is a vector, we don't
- advance map to the next element until i indicates that we
- have finished off the vector. */
-
- Lisp_Object elt, key, binding;
- elt = XCONS (map)->car;
-
- QUIT;
-
- /* Set key and binding to the current key and binding, and
- advance map and i to the next binding. */
- if (VECTORP (elt))
- {
- /* In a vector, look at each element. */
- binding = XVECTOR (elt)->contents[i];
- XSETFASTINT (key, i);
- i++;
-
- /* If we've just finished scanning a vector, advance map
- to the next element, and reset i in anticipation of the
- next vector we may find. */
- if (i >= XVECTOR (elt)->size)
- {
- map = XCONS (map)->cdr;
- i = 0;
- }
- }
- else if (CONSP (elt))
- {
- key = Fcar (Fcar (map));
- binding = Fcdr (Fcar (map));
-
- map = XCONS (map)->cdr;
- }
- else
- /* We want to ignore keymap elements that are neither
- vectors nor conses. */
- {
- map = XCONS (map)->cdr;
- continue;
- }
-
- /* Search through indirections unless that's not wanted. */
- if (NILP (noindirect))
- {
- if (nomenus)
- {
- while (1)
- {
- Lisp_Object map, tem;
- /* If the contents are (KEYMAP . ELEMENT), go indirect. */
- map = get_keymap_1 (Fcar_safe (definition), 0, 0);
- tem = Fkeymapp (map);
- if (!NILP (tem))
- definition = access_keymap (map, Fcdr (definition), 0, 0);
- else
- break;
- }
- /* If the contents are (STRING ...), reject. */
- if (CONSP (definition)
- && STRINGP (XCONS (definition)->car))
- continue;
- }
- else
- binding = get_keyelt (binding, 0);
- }
-
- /* End this iteration if this element does not match
- the target. */
-
- if (CONSP (definition))
- {
- Lisp_Object tem;
- tem = Fequal (binding, definition);
- if (NILP (tem))
- continue;
- }
- else
- if (!EQ (binding, definition))
- continue;
-
- /* We have found a match.
- Construct the key sequence where we found it. */
- if (INTEGERP (key) && last_is_meta)
- {
- sequence = Fcopy_sequence (this);
- Faset (sequence, last, make_number (XINT (key) | meta_modifier));
- }
- else
- sequence = append_key (this, key);
-
- /* Verify that this key binding is not shadowed by another
- binding for the same key, before we say it exists.
-
- 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 (keymap_specified)
- {
- binding = Flookup_key (keymap, sequence, Qnil);
- if (!NILP (binding) && !INTEGERP (binding))
- {
- if (CONSP (definition))
- {
- Lisp_Object tem;
- tem = Fequal (binding, definition);
- if (NILP (tem))
- continue;
- }
- else
- if (!EQ (binding, definition))
- continue;
- }
- }
- else
- {
- binding = Fkey_binding (sequence, Qnil);
- if (!EQ (binding, definition))
- continue;
- }
-
- /* It is a true unshadowed match. Record it, unless it's already
- been seen (as could happen when inheriting keymaps). */
- if (NILP (Fmember (sequence, found)))
- found = Fcons (sequence, found);
-
- /* If firstonly is Qnon_ascii, then we can return the first
- binding we find. If firstonly is not Qnon_ascii but not
- nil, then we should return the first ascii-only binding
- we find. */
- if (EQ (firstonly, Qnon_ascii))
- RETURN_UNGCPRO (sequence);
- else if (! NILP (firstonly) && ascii_sequence_p (sequence))
- RETURN_UNGCPRO (sequence);
- }
- }
-
- UNGCPRO;
-
- found = Fnreverse (found);
-
- /* firstonly may have been t, but we may have gone all the way through
- the keymaps without finding an all-ASCII key sequence. So just
- return the best we could find. */
- if (! NILP (firstonly))
- return Fcar (found);
-
- return found;
-}
-
-/* describe-bindings - summarizing all the bindings in a set of keymaps. */
-
-DEFUN ("describe-bindings", Fdescribe_bindings, Sdescribe_bindings, 0, 1, "",
- "Show a list of all defined keys, and their definitions.\n\
-The list is put in a buffer, which is displayed.\n\
-An optional argument PREFIX, if non-nil, should be a key sequence;\n\
-then we display only bindings that start with that prefix.")
- (prefix)
- Lisp_Object prefix;
-{
- register Lisp_Object thisbuf;
- XSETBUFFER (thisbuf, current_buffer);
- internal_with_output_to_temp_buffer ("*Help*",
- describe_buffer_bindings,
- Fcons (thisbuf, prefix));
- return Qnil;
-}
-
-/* ARG is (BUFFER . PREFIX). */
-
-static Lisp_Object
-describe_buffer_bindings (arg)
- Lisp_Object arg;
-{
- Lisp_Object descbuf, prefix, shadow;
- register Lisp_Object start1;
- struct gcpro gcpro1;
-
- char *alternate_heading
- = "\
-Alternate Characters (use anywhere the nominal character is listed):\n\
-nominal alternate\n\
-------- ---------\n";
-
- descbuf = XCONS (arg)->car;
- prefix = XCONS (arg)->cdr;
- shadow = Qnil;
- GCPRO1 (shadow);
-
- Fset_buffer (Vstandard_output);
-
- /* Report on alternates for keys. */
- if (STRINGP (Vkeyboard_translate_table) && !NILP (prefix))
- {
- int c;
- unsigned char *translate = XSTRING (Vkeyboard_translate_table)->data;
- int translate_len = XSTRING (Vkeyboard_translate_table)->size;
-
- for (c = 0; c < translate_len; c++)
- if (translate[c] != c)
- {
- char buf[20];
- char *bufend;
-
- if (alternate_heading)
- {
- insert_string (alternate_heading);
- alternate_heading = 0;
- }
-
- bufend = push_key_description (translate[c], buf);
- insert (buf, bufend - buf);
- Findent_to (make_number (16), make_number (1));
- bufend = push_key_description (c, buf);
- insert (buf, bufend - buf);
-
- insert ("\n", 1);
- }
-
- insert ("\n", 1);
- }
-
- if (!NILP (Vkey_translation_map))
- describe_map_tree (Vkey_translation_map, 0, Qnil, prefix,
- "Key translations", 0, 1, 0);
-
- {
- int i, nmaps;
- Lisp_Object *modes, *maps;
-
- /* Temporarily switch to descbuf, so that we can get that buffer's
- minor modes correctly. */
- Fset_buffer (descbuf);
-
- if (!NILP (current_kboard->Voverriding_terminal_local_map)
- || !NILP (Voverriding_local_map))
- nmaps = 0;
- else
- nmaps = current_minor_maps (&modes, &maps);
- Fset_buffer (Vstandard_output);
-
- /* Print the minor mode maps. */
- for (i = 0; i < nmaps; i++)
- {
- /* The title for a minor mode keymap
- is constructed at run time.
- We let describe_map_tree do the actual insertion
- because it takes care of other features when doing so. */
- char *title, *p;
-
- if (!SYMBOLP (modes[i]))
- abort();
-
- p = title = (char *) alloca (40 + XSYMBOL (modes[i])->name->size);
- *p++ = '`';
- bcopy (XSYMBOL (modes[i])->name->data, p,
- XSYMBOL (modes[i])->name->size);
- p += XSYMBOL (modes[i])->name->size;
- *p++ = '\'';
- bcopy (" Minor Mode Bindings", p, sizeof (" Minor Mode Bindings") - 1);
- p += sizeof (" Minor Mode Bindings") - 1;
- *p = 0;
-
- describe_map_tree (maps[i], 1, shadow, prefix, title, 0, 0, 0);
- shadow = Fcons (maps[i], shadow);
- }
- }
-
- /* Print the (major mode) local map. */
- if (!NILP (current_kboard->Voverriding_terminal_local_map))
- start1 = current_kboard->Voverriding_terminal_local_map;
- else if (!NILP (Voverriding_local_map))
- start1 = Voverriding_local_map;
- else
- start1 = XBUFFER (descbuf)->keymap;
-
- if (!NILP (start1))
- {
- describe_map_tree (start1, 1, shadow, prefix,
- "Major Mode Bindings", 0, 0, 0);
- shadow = Fcons (start1, shadow);
- }
-
- describe_map_tree (current_global_map, 1, shadow, prefix,
- "Global Bindings", 0, 0, 1);
-
- /* Print the function-key-map translations under this prefix. */
- if (!NILP (Vfunction_key_map))
- describe_map_tree (Vfunction_key_map, 0, Qnil, prefix,
- "Function key map translations", 0, 1, 0);
-
- call0 (intern ("help-mode"));
- Fset_buffer (descbuf);
- UNGCPRO;
- return Qnil;
-}
-
-/* Insert a description 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, it is a list of maps;
- don't mention keys which would be shadowed by any of them.
- PREFIX, if non-nil, says mention only keys that start with PREFIX.
- TITLE, if not 0, is a string to insert at the beginning.
- TITLE should not end with a colon or a newline; we supply that.
- If NOMENU is not 0, then omit menu-bar commands.
-
- If TRANSL is nonzero, the definitions are actually key translations
- so print strings and vectors differently.
-
- If ALWAYS_TITLE is nonzero, print the title even if there are no maps
- to look through. */
-
-void
-describe_map_tree (startmap, partial, shadow, prefix, title, nomenu, transl,
- always_title)
- Lisp_Object startmap, shadow, prefix;
- int partial;
- char *title;
- int nomenu;
- int transl;
- int always_title;
-{
- Lisp_Object maps, seen, sub_shadows;
- struct gcpro gcpro1, gcpro2, gcpro3;
- int something = 0;
- char *key_heading
- = "\
-key binding\n\
---- -------\n";
-
- maps = Faccessible_keymaps (startmap, prefix);
- seen = Qnil;
- sub_shadows = Qnil;
- GCPRO3 (maps, seen, sub_shadows);
-
- if (nomenu)
- {
- Lisp_Object list;
-
- /* Delete from MAPS each element that is for the menu bar. */
- for (list = maps; !NILP (list); list = XCONS (list)->cdr)
- {
- Lisp_Object elt, prefix, tem;
-
- elt = Fcar (list);
- prefix = Fcar (elt);
- if (XVECTOR (prefix)->size >= 1)
- {
- tem = Faref (prefix, make_number (0));
- if (EQ (tem, Qmenu_bar))
- maps = Fdelq (elt, maps);
- }
- }
- }
-
- if (!NILP (maps) || always_title)
- {
- if (title)
- {
- insert_string (title);
- if (!NILP (prefix))
- {
- insert_string (" Starting With ");
- insert1 (Fkey_description (prefix));
- }
- insert_string (":\n");
- }
- insert_string (key_heading);
- something = 1;
- }
-
- for (; !NILP (maps); maps = Fcdr (maps))
- {
- register Lisp_Object elt, prefix, tail;
-
- elt = Fcar (maps);
- prefix = Fcar (elt);
-
- sub_shadows = Qnil;
-
- for (tail = shadow; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- Lisp_Object shmap;
-
- shmap = XCONS (tail)->car;
-
- /* If the sequence by which we reach this keymap is zero-length,
- then the shadow map for this keymap is just SHADOW. */
- if ((STRINGP (prefix) && XSTRING (prefix)->size == 0)
- || (VECTORP (prefix) && XVECTOR (prefix)->size == 0))
- ;
- /* If the sequence by which we reach this keymap actually has
- some elements, then the sequence's definition in SHADOW is
- what we should use. */
- else
- {
- shmap = Flookup_key (shmap, Fcar (elt), Qt);
- if (INTEGERP (shmap))
- shmap = Qnil;
- }
-
- /* If shmap is not nil and not a keymap,
- it completely shadows this map, so don't
- describe this map at all. */
- if (!NILP (shmap) && NILP (Fkeymapp (shmap)))
- goto skip;
-
- if (!NILP (shmap))
- sub_shadows = Fcons (shmap, sub_shadows);
- }
-
- describe_map (Fcdr (elt), Fcar (elt),
- transl ? describe_translation : describe_command,
- partial, sub_shadows, &seen, nomenu);
-
- skip: ;
- }
-
- if (something)
- insert_string ("\n");
-
- UNGCPRO;
-}
-
-static int previous_description_column;
-
-static void
-describe_command (definition)
- Lisp_Object definition;
-{
- register Lisp_Object tem1;
- int column = current_column ();
- int description_column;
-
- /* If column 16 is no good, go to col 32;
- but don't push beyond that--go to next line instead. */
- if (column > 30)
- {
- insert_char ('\n');
- description_column = 32;
- }
- else if (column > 14 || (column > 10 && previous_description_column == 32))
- description_column = 32;
- else
- description_column = 16;
-
- Findent_to (make_number (description_column), make_number (1));
- previous_description_column = description_column;
-
- if (SYMBOLP (definition))
- {
- XSETSTRING (tem1, XSYMBOL (definition)->name);
- insert1 (tem1);
- insert_string ("\n");
- }
- else if (STRINGP (definition) || VECTORP (definition))
- insert_string ("Keyboard Macro\n");
- else
- {
- tem1 = Fkeymapp (definition);
- if (!NILP (tem1))
- insert_string ("Prefix Command\n");
- else
- insert_string ("??\n");
- }
-}
-
-static void
-describe_translation (definition)
- Lisp_Object definition;
-{
- register Lisp_Object tem1;
-
- Findent_to (make_number (16), make_number (1));
-
- if (SYMBOLP (definition))
- {
- XSETSTRING (tem1, XSYMBOL (definition)->name);
- insert1 (tem1);
- insert_string ("\n");
- }
- else if (STRINGP (definition) || VECTORP (definition))
- {
- insert1 (Fkey_description (definition));
- insert_string ("\n");
- }
- else
- {
- tem1 = Fkeymapp (definition);
- if (!NILP (tem1))
- insert_string ("Prefix Command\n");
- else
- insert_string ("??\n");
- }
-}
-
-/* Like Flookup_key, but uses a list of keymaps SHADOW instead of a single map.
- Returns the first non-nil binding found in any of those maps. */
-
-static Lisp_Object
-shadow_lookup (shadow, key, flag)
- Lisp_Object shadow, key, flag;
-{
- Lisp_Object tail, value;
-
- for (tail = shadow; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- value = Flookup_key (XCONS (tail)->car, key, flag);
- if (!NILP (value))
- return value;
- }
- return Qnil;
-}
-
-/* Describe the contents of map MAP, assuming that this map itself is
- reached by the sequence of prefix keys KEYS (a string or vector).
- PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above. */
-
-static void
-describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu)
- register Lisp_Object map;
- Lisp_Object keys;
- int (*elt_describer) ();
- int partial;
- Lisp_Object shadow;
- Lisp_Object *seen;
- int nomenu;
-{
- Lisp_Object elt_prefix;
- Lisp_Object tail, definition, event;
- Lisp_Object tem;
- Lisp_Object suppress;
- Lisp_Object kludge;
- int first = 1;
- struct gcpro gcpro1, gcpro2, gcpro3;
-
- if (!NILP (keys) && XFASTINT (Flength (keys)) > 0)
- {
- /* Call Fkey_description first, to avoid GC bug for the other string. */
- tem = Fkey_description (keys);
- elt_prefix = concat2 (tem, build_string (" "));
- }
- else
- elt_prefix = Qnil;
-
- if (partial)
- suppress = intern ("suppress-keymap");
-
- /* This vector gets used to present single keys to Flookup_key. Since
- that is done once per keymap element, we don't want to cons up a
- fresh vector every time. */
- kludge = Fmake_vector (make_number (1), Qnil);
- definition = Qnil;
-
- GCPRO3 (elt_prefix, definition, kludge);
-
- for (tail = map; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- QUIT;
-
- if (VECTORP (XCONS (tail)->car))
- describe_vector (XCONS (tail)->car,
- elt_prefix, elt_describer, partial, shadow, map);
- else if (CONSP (XCONS (tail)->car))
- {
- event = XCONS (XCONS (tail)->car)->car;
-
- /* Ignore bindings whose "keys" are not really valid events.
- (We get these in the frames and buffers menu.) */
- if (! (SYMBOLP (event) || INTEGERP (event)))
- continue;
-
- if (nomenu && EQ (event, Qmenu_bar))
- continue;
-
- definition = get_keyelt (XCONS (XCONS (tail)->car)->cdr, 0);
-
- /* Don't show undefined commands or suppressed commands. */
- if (NILP (definition)) continue;
- if (SYMBOLP (definition) && partial)
- {
- tem = Fget (definition, suppress);
- if (!NILP (tem))
- continue;
- }
-
- /* Don't show a command that isn't really visible
- because a local definition of the same key shadows it. */
-
- XVECTOR (kludge)->contents[0] = event;
- if (!NILP (shadow))
- {
- tem = shadow_lookup (shadow, kludge, Qt);
- if (!NILP (tem)) continue;
- }
-
- tem = Flookup_key (map, kludge, Qt);
- if (! EQ (tem, definition)) continue;
-
- if (first)
- {
- previous_description_column = 0;
- insert ("\n", 1);
- first = 0;
- }
-
- if (!NILP (elt_prefix))
- insert1 (elt_prefix);
-
- /* THIS gets the string to describe the character EVENT. */
- insert1 (Fsingle_key_description (event));
-
- /* Print a description of the definition of this character.
- elt_describer will take care of spacing out far enough
- for alignment purposes. */
- (*elt_describer) (definition);
- }
- else if (EQ (XCONS (tail)->car, Qkeymap))
- {
- /* The same keymap might be in the structure twice, if we're
- using an inherited keymap. So skip anything we've already
- encountered. */
- tem = Fassq (tail, *seen);
- if (CONSP (tem) && !NILP (Fequal (XCONS (tem)->car, keys)))
- break;
- *seen = Fcons (Fcons (tail, keys), *seen);
- }
- }
-
- UNGCPRO;
-}
-
-static int
-describe_vector_princ (elt)
- Lisp_Object elt;
-{
- Findent_to (make_number (16), make_number (1));
- Fprinc (elt, Qnil);
- Fterpri (Qnil);
-}
-
-DEFUN ("describe-vector", Fdescribe_vector, Sdescribe_vector, 1, 1, 0,
- "Insert a description of contents of VECTOR.\n\
-This is text showing the elements of vector matched against indices.")
- (vector)
- Lisp_Object vector;
-{
- int count = specpdl_ptr - specpdl;
-
- specbind (Qstandard_output, Fcurrent_buffer ());
- CHECK_VECTOR_OR_CHAR_TABLE (vector, 0);
- describe_vector (vector, Qnil, describe_vector_princ, 0, Qnil, Qnil);
-
- return unbind_to (count, Qnil);
-}
-
-/* Insert in the current buffer a description of the contents of VECTOR.
- We call ELT_DESCRIBER to insert the description of one value found
- in VECTOR.
-
- ELT_PREFIX describes what "comes before" the keys or indices defined
- by this vector.
-
- If the vector is in a keymap, ELT_PREFIX is a prefix key which
- leads to this keymap.
-
- If the vector is a chartable, ELT_PREFIX is the vector
- of bytes that lead to the character set or portion of a character
- set described by this chartable.
-
- If PARTIAL is nonzero, it means do not mention suppressed commands
- (that assumes the vector is in a keymap).
-
- SHADOW is a list of keymaps that shadow this map.
- If it is non-nil, then we look up the key in those maps
- and we don't mention it now if it is defined by any of them.
-
- ENTIRE_MAP is the keymap in which this vector appears.
- If the definition in effect in the whole map does not match
- the one in this vector, we ignore this one. */
-
-describe_vector (vector, elt_prefix, elt_describer,
- partial, shadow, entire_map)
- register Lisp_Object vector;
- Lisp_Object elt_prefix;
- int (*elt_describer) ();
- int partial;
- Lisp_Object shadow;
- Lisp_Object entire_map;
-{
- Lisp_Object this;
- Lisp_Object dummy;
- Lisp_Object definition;
- Lisp_Object tem2;
- register int i;
- Lisp_Object suppress;
- Lisp_Object kludge;
- Lisp_Object chartable_kludge;
- int first = 1;
- int size;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- definition = Qnil;
- chartable_kludge = Qnil;
-
- /* This vector gets used to present single keys to Flookup_key. Since
- that is done once per vector element, we don't want to cons up a
- fresh vector every time. */
- kludge = Fmake_vector (make_number (1), Qnil);
- GCPRO4 (elt_prefix, definition, kludge, chartable_kludge);
-
- if (partial)
- suppress = intern ("suppress-keymap");
-
- /* This does the right thing for char-tables as well as ordinary vectors. */
- size = XFASTINT (Flength (vector));
-
- for (i = 0; i < size; i++)
- {
- QUIT;
- definition = get_keyelt (XVECTOR (vector)->contents[i], 0);
-
- if (NILP (definition)) continue;
-
- /* Don't mention suppressed commands. */
- if (SYMBOLP (definition) && partial)
- {
- this = Fget (definition, suppress);
- if (!NILP (this))
- continue;
- }
-
- /* If this binding is shadowed by some other map, ignore it. */
- if (!NILP (shadow))
- {
- Lisp_Object tem;
-
- XVECTOR (kludge)->contents[0] = make_number (i);
- tem = shadow_lookup (shadow, kludge, Qt);
-
- if (!NILP (tem)) continue;
- }
-
- /* Ignore this definition if it is shadowed by an earlier
- one in the same keymap. */
- if (!NILP (entire_map))
- {
- Lisp_Object tem;
-
- XVECTOR (kludge)->contents[0] = make_number (i);
- tem = Flookup_key (entire_map, kludge, Qt);
-
- if (! EQ (tem, definition))
- continue;
- }
-
- /* If we find a char-table within a char-table,
- scan it recursively; it defines the details for
- a character set or a portion of a character set. */
- if (CHAR_TABLE_P (vector) && CHAR_TABLE_P (definition))
- {
- int outer_level
- = !NILP (elt_prefix) ? XVECTOR (elt_prefix)->size : 0;
- if (NILP (chartable_kludge))
- {
- chartable_kludge
- = Fmake_vector (make_number (outer_level + 1), Qnil);
- if (outer_level != 0)
- bcopy (XVECTOR (elt_prefix)->contents,
- XVECTOR (chartable_kludge)->contents,
- outer_level * sizeof (Lisp_Object));
- }
- XVECTOR (chartable_kludge)->contents[outer_level]
- = make_number (i);
- describe_vector (definition, chartable_kludge, elt_describer,
- partial, shadow, entire_map);
- continue;
- }
-
- if (first)
- {
- insert ("\n", 1);
- first = 0;
- }
-
- if (CHAR_TABLE_P (vector))
- {
- if (!NILP (elt_prefix))
- {
- /* Must combine elt_prefix with i to produce a character
- code, then insert that character's description. */
- }
- else
- {
- /* Get the string to describe the character I, and print it. */
- XSETFASTINT (dummy, i);
-
- /* THIS gets the string to describe the character DUMMY. */
- this = Fsingle_key_description (dummy);
- insert1 (this);
- }
- }
- else
- {
- /* Output the prefix that applies to every entry in this map. */
- if (!NILP (elt_prefix))
- insert1 (elt_prefix);
-
- /* Get the string to describe the character I, and print it. */
- XSETFASTINT (dummy, i);
-
- /* THIS gets the string to describe the character DUMMY. */
- this = Fsingle_key_description (dummy);
- insert1 (this);
- }
-
- /* Find all consecutive characters that have the same definition. */
- while (i + 1 < XVECTOR (vector)->size
- && (tem2 = get_keyelt (XVECTOR (vector)->contents[i+1], 0),
- EQ (tem2, definition)))
- i++;
-
- /* If we have a range of more than one character,
- print where the range reaches to. */
-
- if (i != XINT (dummy))
- {
- insert (" .. ", 4);
- if (CHAR_TABLE_P (vector))
- {
- if (!NILP (elt_prefix))
- {
- /* Must combine elt_prefix with i to produce a character
- code, then insert that character's description. */
- }
- else
- {
- XSETFASTINT (dummy, i);
-
- this = Fsingle_key_description (dummy);
- insert1 (this);
- }
- }
- else
- {
- if (!NILP (elt_prefix))
- insert1 (elt_prefix);
-
- XSETFASTINT (dummy, i);
- insert1 (Fsingle_key_description (dummy));
- }
- }
-
- /* Print a description of the definition of this character.
- elt_describer will take care of spacing out far enough
- for alignment purposes. */
- (*elt_describer) (definition);
- }
-
- UNGCPRO;
-}
-
-/* Apropos - finding all symbols whose names match a regexp. */
-Lisp_Object apropos_predicate;
-Lisp_Object apropos_accumulate;
-
-static void
-apropos_accum (symbol, string)
- Lisp_Object symbol, string;
-{
- register Lisp_Object tem;
-
- tem = Fstring_match (string, Fsymbol_name (symbol), Qnil);
- if (!NILP (tem) && !NILP (apropos_predicate))
- tem = call1 (apropos_predicate, symbol);
- if (!NILP (tem))
- apropos_accumulate = Fcons (symbol, apropos_accumulate);
-}
-
-DEFUN ("apropos-internal", Fapropos_internal, Sapropos_internal, 1, 2, 0,
- "Show all symbols whose names contain match for REGEXP.\n\
-If optional 2nd arg PREDICATE is non-nil, (funcall PREDICATE SYMBOL) is done\n\
-for each symbol and a symbol is mentioned only if that returns non-nil.\n\
-Return list of symbols found.")
- (regexp, predicate)
- Lisp_Object regexp, predicate;
-{
- struct gcpro gcpro1, gcpro2;
- CHECK_STRING (regexp, 0);
- apropos_predicate = predicate;
- GCPRO2 (apropos_predicate, apropos_accumulate);
- apropos_accumulate = Qnil;
- map_obarray (Vobarray, apropos_accum, regexp);
- apropos_accumulate = Fsort (apropos_accumulate, Qstring_lessp);
- 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 */
-
- global_map = Fcons (Qkeymap,
- Fcons (Fmake_vector (make_number (0400), Qnil), Qnil));
- Fset (intern ("global-map"), global_map);
-
- current_global_map = global_map;
- staticpro (&global_map);
- staticpro (&current_global_map);
-
- meta_map = Fmake_keymap (Qnil);
- Fset (intern ("esc-map"), meta_map);
- Ffset (intern ("ESC-prefix"), meta_map);
-
- control_x_map = Fmake_keymap (Qnil);
- Fset (intern ("ctl-x-map"), control_x_map);
- Ffset (intern ("Control-X-prefix"), control_x_map);
-
- DEFVAR_LISP ("define-key-rebound-commands", &Vdefine_key_rebound_commands,
- "List of commands given new key bindings recently.\n\
-This is used for internal purposes during Emacs startup;\n\
-don't alter it yourself.");
- Vdefine_key_rebound_commands = Qt;
-
- DEFVAR_LISP ("minibuffer-local-map", &Vminibuffer_local_map,
- "Default keymap to use when reading from the minibuffer.");
- Vminibuffer_local_map = Fmake_sparse_keymap (Qnil);
-
- DEFVAR_LISP ("minibuffer-local-ns-map", &Vminibuffer_local_ns_map,
- "Local keymap for the minibuffer when spaces are not allowed.");
- Vminibuffer_local_ns_map = Fmake_sparse_keymap (Qnil);
-
- DEFVAR_LISP ("minibuffer-local-completion-map", &Vminibuffer_local_completion_map,
- "Local keymap for minibuffer input with completion.");
- Vminibuffer_local_completion_map = Fmake_sparse_keymap (Qnil);
-
- DEFVAR_LISP ("minibuffer-local-must-match-map", &Vminibuffer_local_must_match_map,
- "Local keymap for minibuffer input with completion, for exact match.");
- Vminibuffer_local_must_match_map = Fmake_sparse_keymap (Qnil);
-
- DEFVAR_LISP ("minor-mode-map-alist", &Vminor_mode_map_alist,
- "Alist of keymaps to use for minor modes.\n\
-Each element looks like (VARIABLE . KEYMAP); KEYMAP is used to read\n\
-key sequences and look up bindings iff VARIABLE's value is non-nil.\n\
-If two active keymaps bind the same key, the keymap appearing earlier\n\
-in the list takes precedence.");
- Vminor_mode_map_alist = Qnil;
-
- DEFVAR_LISP ("function-key-map", &Vfunction_key_map,
- "Keymap mapping ASCII function key sequences onto their preferred forms.\n\
-This allows Emacs to recognize function keys sent from ASCII\n\
-terminals at any point in a key sequence.\n\
-\n\
-The `read-key-sequence' function replaces any subsequence bound by\n\
-`function-key-map' with its binding. More precisely, when the active\n\
-keymaps have no binding for the current key sequence but\n\
-`function-key-map' binds a suffix of the sequence to a vector or string,\n\
-`read-key-sequence' replaces the matching suffix with its binding, and\n\
-continues with the new sequence.\n\
-\n\
-The events that come from bindings in `function-key-map' are not\n\
-themselves looked up in `function-key-map'.\n\
-\n\
-For example, suppose `function-key-map' binds `ESC O P' to [f1].\n\
-Typing `ESC O P' to `read-key-sequence' would return [f1]. Typing\n\
-`C-x ESC O P' would return [?\\C-x f1]. If [f1] were a prefix\n\
-key, typing `ESC O P x' would return [f1 x].");
- Vfunction_key_map = Fmake_sparse_keymap (Qnil);
-
- DEFVAR_LISP ("key-translation-map", &Vkey_translation_map,
- "Keymap of key translations that can override keymaps.\n\
-This keymap works like `function-key-map', but comes after that,\n\
-and applies even for keys that have ordinary bindings.");
- Vkey_translation_map = Qnil;
-
- Qsingle_key_description = intern ("single-key-description");
- staticpro (&Qsingle_key_description);
-
- Qkey_description = intern ("key-description");
- staticpro (&Qkey_description);
-
- Qkeymapp = intern ("keymapp");
- staticpro (&Qkeymapp);
-
- Qnon_ascii = intern ("non-ascii");
- staticpro (&Qnon_ascii);
-
- defsubr (&Skeymapp);
- defsubr (&Skeymap_parent);
- defsubr (&Sset_keymap_parent);
- defsubr (&Smake_keymap);
- defsubr (&Smake_sparse_keymap);
- defsubr (&Scopy_keymap);
- defsubr (&Skey_binding);
- defsubr (&Slocal_key_binding);
- defsubr (&Sglobal_key_binding);
- defsubr (&Sminor_mode_key_binding);
- defsubr (&Sdefine_key);
- defsubr (&Slookup_key);
- defsubr (&Sdefine_prefix_command);
- defsubr (&Suse_global_map);
- defsubr (&Suse_local_map);
- defsubr (&Scurrent_local_map);
- defsubr (&Scurrent_global_map);
- defsubr (&Scurrent_minor_mode_maps);
- defsubr (&Saccessible_keymaps);
- defsubr (&Skey_description);
- defsubr (&Sdescribe_vector);
- defsubr (&Ssingle_key_description);
- defsubr (&Stext_char_description);
- defsubr (&Swhere_is_internal);
- defsubr (&Sdescribe_bindings);
- defsubr (&Sapropos_internal);
-}
-
-keys_of_keymap ()
-{
- Lisp_Object tem;
-
- initial_define_key (global_map, 033, "ESC-prefix");
- initial_define_key (global_map, Ctl('X'), "Control-X-prefix");
-}
diff --git a/src/lastfile.c b/src/lastfile.c
deleted file mode 100644
index 0efb03dac8f..00000000000
--- a/src/lastfile.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* 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.
-*/
-
-char my_edata[] = "End of Emacs initialized data";
-
diff --git a/src/line.h b/src/line.h
deleted file mode 100644
index e3441aaaa93..00000000000
--- a/src/line.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#define line_width 30
-#define line_height 10
-static char line_bits[] = {
- 0xf0, 0xff, 0xff, 0x03, 0x08, 0x00, 0x00, 0x04, 0x44, 0x48, 0xf4, 0x08,
- 0x42, 0xc8, 0x14, 0x10, 0x41, 0x48, 0x75, 0x20, 0x41, 0x48, 0x15, 0x20,
- 0x42, 0x48, 0x16, 0x10, 0xc4, 0x4b, 0xf4, 0x08, 0x08, 0x00, 0x00, 0x04,
- 0xf0, 0xff, 0xff, 0x03};
diff --git a/src/lisp.h b/src/lisp.h
deleted file mode 100644
index f478539f2cb..00000000000
--- a/src/lisp.h
+++ /dev/null
@@ -1,1857 +0,0 @@
-/* Fundamental definitions for GNU Emacs Lisp interpreter.
- Copyright (C) 1985,86,87,93,94,95 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* These are default choices for the types to use. */
-#ifndef EMACS_INT
-#define EMACS_INT int
-#define BITS_PER_EMACS_INT BITS_PER_INT
-#endif
-#ifndef EMACS_UINT
-#define EMACS_UINT unsigned int
-#endif
-
-/* Define the fundamental Lisp data structures. */
-
-/* This is the set of Lisp data types. */
-
-enum Lisp_Type
- {
- /* Integer. XINT (obj) is the integer value. */
- Lisp_Int,
-
- /* Symbol. XSYMBOL (object) points to a struct Lisp_Symbol. */
- Lisp_Symbol,
-
- /* Miscellaneous. XMISC (object) points to a union Lisp_Misc,
- whose first member indicates the subtype. */
- Lisp_Misc,
-
- /* String. XSTRING (object) points to a struct Lisp_String.
- The length of the string, and its contents, are stored therein. */
- Lisp_String,
-
- /* Vector of Lisp objects, or something resembling it.
- XVECTOR (object) points to a struct Lisp_Vector, which contains
- the size and contents. The size field also contains the type
- information, if it's not a real vector object. */
- Lisp_Vectorlike,
-
- /* Cons. XCONS (object) points to a struct Lisp_Cons. */
- Lisp_Cons,
-
-#ifdef LISP_FLOAT_TYPE
- Lisp_Float,
-#endif /* LISP_FLOAT_TYPE */
-
- /* This is not a type code. It is for range checking. */
- Lisp_Type_Limit
- };
-
-/* This is the set of datatypes that share a common structure.
- The first member of the structure is a type code from this set.
- The enum values are arbitrary, but we'll use large numbers to make it
- more likely that we'll spot the error if a random word in memory is
- mistakenly interpreted as a Lisp_Misc. */
-enum Lisp_Misc_Type
- {
- Lisp_Misc_Free = 0x5eab,
- Lisp_Misc_Marker,
- Lisp_Misc_Intfwd,
- Lisp_Misc_Boolfwd,
- Lisp_Misc_Objfwd,
- Lisp_Misc_Buffer_Objfwd,
- Lisp_Misc_Buffer_Local_Value,
- Lisp_Misc_Some_Buffer_Local_Value,
- Lisp_Misc_Overlay,
- Lisp_Misc_Kboard_Objfwd,
- /* Currently floats are not a misc type,
- but let's define this in case we want to change that. */
- Lisp_Misc_Float,
- /* This is not a type code. It is for range checking. */
- Lisp_Misc_Limit
- };
-
-/* These values are overridden by the m- file on some machines. */
-#ifndef VALBITS
-#define VALBITS 28
-#endif
-
-#ifndef GCTYPEBITS
-#define GCTYPEBITS 3
-#endif
-
-/* Make these values available in GDB, which sees enums but not macros. */
-
-enum gdb_lisp_params
-{
- gdb_valbits = VALBITS,
- gdb_gctypebits = GCTYPEBITS,
- gdb_emacs_intbits = sizeof (EMACS_INT) * BITS_PER_CHAR,
-#ifdef DATA_SEG_BITS
- gdb_data_seg_bits = DATA_SEG_BITS
-#else
- gdb_data_seg_bits = 0
-#endif
-};
-
-#ifndef NO_UNION_TYPE
-
-#ifndef WORDS_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: VALBITS;
- int type: GCTYPEBITS+1;
- } s;
- struct
- {
- unsigned int val: VALBITS;
- int type: GCTYPEBITS+1;
- } u;
- struct
- {
- unsigned int val: VALBITS;
- enum Lisp_Type type: GCTYPEBITS;
- /* 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 WORDS_BIG_ENDIAN */
-
-typedef
-union Lisp_Object
- {
- /* Used for comparing two Lisp_Objects;
- also, positive integers can be accessed fast this way. */
- int i;
-
- struct
- {
- int type: GCTYPEBITS+1;
- int val: VALBITS;
- } s;
- struct
- {
- int type: GCTYPEBITS+1;
- unsigned int val: VALBITS;
- } 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: GCTYPEBITS;
- unsigned int val: VALBITS;
- } gu;
- }
-Lisp_Object;
-
-#endif /* WORDS_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 EMACS_INT
-
-#ifndef VALMASK
-#define VALMASK ((((EMACS_INT) 1)<<VALBITS) - 1)
-#endif
-#define GCTYPEMASK ((((EMACS_INT) 1)<<GCTYPEBITS) - 1)
-
-/* Two flags that are set during GC. On some machines, these flags
- are defined differently by the m- file. */
-
-/* This is set in the car of a cons and in the plist slot of a symbol
- to indicate it is marked. Likewise in the plist slot of an interval,
- the chain slot of a marker, the type slot of a float, and the name
- slot of a buffer.
-
- In strings, this bit in the size field indicates that the string
- is a "large" one, one which was separately malloc'd
- rather than being part of a string block. */
-
-#ifndef MARKBIT
-#define MARKBIT ((int) ((unsigned int) 1 << (VALBITS + GCTYPEBITS)))
-#endif /*MARKBIT */
-
-/* In the size word of a vector, this bit means the vector has been marked.
- In the size word of a large string, likewise. */
-
-#ifndef ARRAY_MARK_FLAG
-#define ARRAY_MARK_FLAG ((MARKBIT >> 1) & ~MARKBIT)
-#endif /* no ARRAY_MARK_FLAG */
-
-/* In the size word of a struct Lisp_Vector, this bit means it's really
- some other vector-like object. */
-#ifndef PSEUDOVECTOR_FLAG
-#define PSEUDOVECTOR_FLAG ((ARRAY_MARK_FLAG >> 1) & ~ARRAY_MARK_FLAG)
-#endif
-
-/* In a pseudovector, the size field actually contains a word with one
- PSEUDOVECTOR_FLAG bit set, and exactly one of the following bits to
- indicate the actual type. */
-enum pvec_type
-{
- PVEC_NORMAL_VECTOR = 0,
- PVEC_PROCESS = 0x200,
- PVEC_FRAME = 0x400,
- PVEC_COMPILED = 0x800,
- PVEC_WINDOW = 0x1000,
- PVEC_WINDOW_CONFIGURATION = 0x2000,
- PVEC_SUBR = 0x4000,
- PVEC_CHAR_TABLE = 0x8000,
- PVEC_BOOL_VECTOR = 0x10000,
- PVEC_BUFFER = 0x20000,
- PVEC_TYPE_MASK = 0x3fe00,
- PVEC_FLAG = PSEUDOVECTOR_FLAG
-};
-
-/* For convenience, we also store the number of elements in these bits. */
-#define PSEUDOVECTOR_SIZE_MASK 0x1ff
-
-#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) | ((EMACS_INT)(b) << VALBITS))
-#endif
-
-/* For integers known to be positive, XFASTINT provides fast retrieval
- and XSETFASTINT provides fast storage. This takes advantage of the
- fact that Lisp_Int is 0. */
-#define XFASTINT(a) ((a) + 0)
-#define XSETFASTINT(a, b) ((a) = (b))
-
-/* Extract the value of a Lisp_Object as a signed integer. */
-
-#ifndef XINT /* Some machines need to do this differently. */
-#define XINT(a) (((a) << (BITS_PER_INT-VALBITS)) >> (BITS_PER_INT-VALBITS))
-#endif
-
-/* Extract the value as an unsigned integer. This is a basis
- for extracting it as a pointer to a structure in storage. */
-
-#ifndef XUINT
-#define XUINT(a) ((a) & VALMASK)
-#endif
-
-#ifndef XPNTR
-#ifdef HAVE_SHM
-/* In this representation, data is found in two widely separated segments. */
-extern int pure_size;
-#define XPNTR(a) \
- (XUINT (a) | (XUINT (a) > pure_size ? 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
-#define XPNTR(a) XUINT (a)
-#endif
-#endif /* not HAVE_SHM */
-#endif /* no XPNTR */
-
-#ifndef XSET
-#define XSET(var, type, ptr) \
- ((var) = ((EMACS_INT)(type) << VALBITS) + ((EMACS_INT) (ptr) & VALMASK))
-#endif
-
-/* Convert a C integer into a Lisp_Object integer. */
-
-#define make_number(N) \
- ((((EMACS_INT) (N)) & VALMASK) | ((EMACS_INT) Lisp_Int) << VALBITS)
-
-/* During garbage collection, XGCTYPE must be used for extracting types
- so that the mark bit is ignored. XMARKBIT accesses 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
-
-#if VALBITS + GCTYPEBITS == BITS_PER_EMACS_INT - 1
-/* Make XMARKBIT faster if mark bit is sign bit. */
-#ifndef XMARKBIT
-#define XMARKBIT(a) ((a) < 0)
-#endif
-#endif /* markbit is sign bit */
-
-#ifndef XMARKBIT
-#define XMARKBIT(a) ((a) & MARKBIT)
-#endif
-
-#ifndef XSETMARKBIT
-#define XSETMARKBIT(a,b) ((a) = ((a) & ~MARKBIT) | ((b) ? MARKBIT : 0))
-#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))
-
-/* For integers known to be positive, XFASTINT provides fast retrieval
- and XSETFASTINT provides fast storage. This takes advantage of the
- fact that Lisp_Int is 0. */
-#define XFASTINT(a) ((a).i + 0)
-#define XSETFASTINT(a, b) ((a).i = (b))
-
-#ifdef EXPLICIT_SIGN_EXTEND
-/* Make sure we sign-extend; compilers have been known to fail to do so. */
-#define XINT(a) (((a).i << (BITS_PER_INT-VALBITS)) >> (BITS_PER_INT-VALBITS))
-#else
-#define XINT(a) ((a).s.val)
-#endif /* EXPLICIT_SIGN_EXTEND */
-
-#define XUINT(a) ((a).u.val)
-#define XPNTR(a) ((a).u.val)
-
-#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 */
-
-/* Extract a value or address from a Lisp_Object. */
-
-#define XCONS(a) ((struct Lisp_Cons *) XPNTR(a))
-#define XVECTOR(a) ((struct Lisp_Vector *) XPNTR(a))
-#define XSTRING(a) ((struct Lisp_String *) XPNTR(a))
-#define XSYMBOL(a) ((struct Lisp_Symbol *) XPNTR(a))
-#define XFLOAT(a) ((struct Lisp_Float *) XPNTR(a))
-
-/* Misc types. */
-#define XMISC(a) ((union Lisp_Misc *) XPNTR(a))
-#define XMISCTYPE(a) (XMARKER (a)->type)
-#define XMARKER(a) (&(XMISC(a)->u_marker))
-#define XINTFWD(a) (&(XMISC(a)->u_intfwd))
-#define XBOOLFWD(a) (&(XMISC(a)->u_boolfwd))
-#define XOBJFWD(a) (&(XMISC(a)->u_objfwd))
-#define XBUFFER_OBJFWD(a) (&(XMISC(a)->u_buffer_objfwd))
-#define XBUFFER_LOCAL_VALUE(a) (&(XMISC(a)->u_buffer_local_value))
-#define XOVERLAY(a) (&(XMISC(a)->u_overlay))
-#define XKBOARD_OBJFWD(a) (&(XMISC(a)->u_kboard_objfwd))
-
-/* Pseudovector types. */
-#define XPROCESS(a) ((struct Lisp_Process *) XPNTR(a))
-#define XWINDOW(a) ((struct window *) XPNTR(a))
-#define XSUBR(a) ((struct Lisp_Subr *) XPNTR(a))
-#define XBUFFER(a) ((struct buffer *) XPNTR(a))
-#define XCHAR_TABLE(a) ((struct Lisp_Char_Table *) XPNTR(a))
-#define XBOOL_VECTOR(a) ((struct Lisp_Bool_Vector *) XPNTR(a))
-
-
-/* Construct a Lisp_Object from a value or address. */
-
-#define XSETINT(a, b) XSET (a, Lisp_Int, b)
-#define XSETCONS(a, b) XSET (a, Lisp_Cons, b)
-#define XSETVECTOR(a, b) XSET (a, Lisp_Vectorlike, b)
-#define XSETSTRING(a, b) XSET (a, Lisp_String, b)
-#define XSETSYMBOL(a, b) XSET (a, Lisp_Symbol, b)
-#define XSETFLOAT(a, b) XSET (a, Lisp_Float, b)
-
-/* Misc types. */
-#define XSETMISC(a, b) XSET (a, Lisp_Misc, b)
-#define XSETMARKER(a, b) (XSETMISC (a, b), XMISCTYPE (a) = Lisp_Misc_Marker)
-
-/* Pseudovector types. */
-#define XSETPSEUDOVECTOR(a, b, code) \
- (XSETVECTOR (a, b), XVECTOR (a)->size |= PSEUDOVECTOR_FLAG | (code))
-#define XSETWINDOW_CONFIGURATION(a, b) \
- (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION))
-#define XSETPROCESS(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_PROCESS))
-#define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW))
-#define XSETSUBR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUBR))
-#define XSETCOMPILED(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_COMPILED))
-#define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER))
-#define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE))
-#define XSETBOOL_VECTOR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BOOL_VECTOR))
-
-#ifdef USE_TEXT_PROPERTIES
-/* Basic data type for use of intervals. See the macros in intervals.h. */
-
-struct interval
-{
- /* The first group of entries deal with the tree structure. */
-
- unsigned int total_length; /* Length of myself and both children. */
- unsigned int position; /* Cache of interval's character position. */
- struct interval *left; /* Intervals which precede me. */
- struct interval *right; /* Intervals which succeed me. */
-
- /* Parent in the tree, or the Lisp_Object containing this interval tree.
-
- The mark bit on the root interval of an interval tree says
- whether we have started (and possibly finished) marking the
- tree. If GC comes across an interval tree whose root's parent
- field has its markbit set, it leaves the tree alone.
-
- You'd think we could store this information in the parent object
- somewhere (after all, that should be visited once and then
- ignored too, right?), but strings are GC'd strangely. */
- struct interval *parent;
-
- /* The remaining components are `properties' of the interval.
- The first four are duplicates for things which can be on the list,
- for purposes of speed. */
-
- unsigned char write_protect; /* Non-zero means can't modify. */
- unsigned char visible; /* Zero means don't display. */
- unsigned char front_sticky; /* Non-zero means text inserted just
- before this interval goes into it. */
- unsigned char rear_sticky; /* Likewise for just after it. */
-
- /* Properties of this interval.
- The mark bit on this field says whether this particular interval
- tree node has been visited. Since intervals should never be
- shared, GC aborts if it seems to have visited an interval twice. */
- Lisp_Object plist;
-};
-
-typedef struct interval *INTERVAL;
-
-/* Complain if object is not string or buffer type */
-#define CHECK_STRING_OR_BUFFER(x, i) \
- { if (!STRINGP ((x)) && !BUFFERP ((x))) \
- x = wrong_type_argument (Qbuffer_or_string_p, (x)); }
-
-/* Macro used to conditionally compile intervals into certain data
- structures. See, e.g., struct Lisp_String below. */
-#define DECLARE_INTERVALS INTERVAL intervals;
-
-/* Macro used to conditionally compile interval initialization into
- certain code. See, e.g., alloc.c. */
-#define INITIALIZE_INTERVAL(ptr,val) ptr->intervals = val
-
-#else /* No text properties */
-
-/* If no intervals are used, make the above definitions go away. */
-
-#define CHECK_STRING_OR_BUFFER(x, i)
-
-#define INTERVAL
-#define DECLARE_INTERVALS
-#define INITIALIZE_INTERVAL(ptr,val)
-
-#endif /* USE_TEXT_PROPERTIES */
-
-/* In a cons, the markbit of the car is the gc mark bit */
-
-struct Lisp_Cons
- {
- Lisp_Object car, cdr;
- };
-
-/* Take the car or cdr of something known to be a cons cell. */
-#define XCAR(c) (XCONS ((c))->car)
-#define XCDR(c) (XCONS ((c))->cdr)
-
-/* Take the car or cdr of something whose type is not known. */
-#define CAR(c) \
- (CONSP ((c)) ? XCAR ((c)) \
- : NILP ((c)) ? Qnil \
- : wrong_type_argument (Qlistp, (c)))
-
-#define CDR(c) \
- (CONSP ((c)) ? XCDR ((c)) \
- : NILP ((c)) ? Qnil \
- : wrong_type_argument (Qlistp, (c)))
-
-/* 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
- {
- EMACS_INT size;
- DECLARE_INTERVALS /* `data' field must be last. */
- unsigned char data[1];
- };
-
-/* If a struct is made to look like a vector, this macro returns the length
- of the shortest vector that would hold that struct. */
-#define VECSIZE(type) ((sizeof (type) - (sizeof (struct Lisp_Vector) \
- - sizeof (Lisp_Object)) \
- + sizeof(Lisp_Object) - 1) /* round up */ \
- / sizeof (Lisp_Object))
-
-struct Lisp_Vector
- {
- EMACS_INT size;
- struct Lisp_Vector *next;
- Lisp_Object contents[1];
- };
-
-/* A char table is a kind of vectorlike, with contents are like a vector
- but with a few other slots. For some purposes, it makes sense
- to handle a chartable with type struct Lisp_Vector. */
-
-/* This is the number of slots that apply to characters
- or character sets. */
-#define CHAR_TABLE_ORDINARY_SLOTS 256
-
-/* This is the number of slots that every char table must have.
- This counts the ordinary slots and the parent and defalt slots. */
-#define CHAR_TABLE_STANDARD_SLOTS (256+3)
-
-/* Return the number of "extra" slots in the char table CT. */
-
-#define CHAR_TABLE_EXTRA_SLOTS(CT) \
- (((CT)->size & PSEUDOVECTOR_SIZE_MASK) - CHAR_TABLE_STANDARD_SLOTS)
-
-struct Lisp_Char_Table
- {
- /* This is the vector's size field, which also holds the
- pseudovector type information. It holds the size, too.
- The size counts the defalt and parent slots. */
- EMACS_INT size;
- struct Lisp_Vector *next;
- Lisp_Object contents[CHAR_TABLE_ORDINARY_SLOTS];
- /* This holds a default value,
- which is used whenever the value for a specific character is nil. */
- Lisp_Object defalt;
- /* This points to another char table, which we inherit from
- when the value for a specific character is nil.
- The `defalt' slot takes precedence over this. */
- Lisp_Object parent;
- /* This should be a symbol which says what kind of use
- this char-table is meant for.
- Typically now the values can be `syntax-table' and `display-table'. */
- Lisp_Object purpose;
- /* These hold additional data. */
- Lisp_Object extras[1];
- };
-
-/* A boolvector is a kind of vectorlike, with contents are like a string. */
-struct Lisp_Bool_Vector
- {
- /* This is the vector's size field. It doesn't have the real size,
- just the subtype information. */
- EMACS_INT vector_size;
- struct Lisp_Vector *next;
- /* This is the size in bits. */
- EMACS_INT size;
- /* This contains the actual bits, packed into bytes. */
- unsigned char data[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;
- Lisp_Object obarray;
- struct Lisp_Symbol *next; /* -> next symbol in this obarray bucket */
- };
-
-/* This structure describes a built-in function.
- It is generated by the DEFUN macro only.
- defsubr makes it into a Lisp object.
-
- This type is treated in most respects as a pseudovector,
- but since we never dynamically allocate or free them,
- we don't need a next-vector field. */
-
-struct Lisp_Subr
- {
- EMACS_INT size;
- Lisp_Object (*function) ();
- short min_args, max_args;
- char *symbol_name;
- char *prompt;
- char *doc;
- };
-
-/* These structures are used for various misc types. */
-
-/* A miscellaneous object, when it's on the free list. */
-struct Lisp_Free
- {
- int type : 16; /* = Lisp_Misc_Free */
- int spacer : 16;
- union Lisp_Misc *chain;
- };
-
-/* In a marker, the markbit of the chain field is used as the gc mark bit. */
-struct Lisp_Marker
-{
- int type : 16; /* = Lisp_Misc_Marker */
- int spacer : 15;
- /* 1 means normal insertion at the marker's position
- leaves the marker after the inserted text. */
- unsigned int insertion_type : 1;
- struct buffer *buffer;
- Lisp_Object chain;
- int bufpos;
-};
-
-/* 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. */
-struct Lisp_Intfwd
- {
- int type : 16; /* = Lisp_Misc_Intfwd */
- int spacer : 16;
- int *intvar;
- };
-
-/* 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. */
-struct Lisp_Boolfwd
- {
- int type : 16; /* = Lisp_Misc_Boolfwd */
- int spacer : 16;
- int *boolvar;
- };
-
-/* 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. */
-struct Lisp_Objfwd
- {
- int type : 16; /* = Lisp_Misc_Objfwd */
- int spacer : 16;
- Lisp_Object *objvar;
- };
-
-/* Like Lisp_Objfwd except that value lives in a slot in the
- current buffer. Value is byte index of slot within buffer. */
-struct Lisp_Buffer_Objfwd
- {
- int type : 16; /* = Lisp_Misc_Buffer_Objfwd */
- int spacer : 16;
- int offset;
- };
-
-/* Used in a symbol value cell when the symbol's value is per-buffer.
- The actual contents resemble a cons cell which starts a list like this:
- (REALVALUE BUFFER CURRENT-ALIST-ELEMENT . DEFAULT-VALUE).
-
- The cons-like structure is for historical reasons; it might be better
- to just put these elements into the struct, now.
-
- 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
- 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. Each time we
- switch buffers, buffer-local variables which forward into C
- variables are swapped immediately, so the C code can assume
- that they are always up to date.
-
- Lisp_Misc_Buffer_Local_Value and Lisp_Misc_Some_Buffer_Local_Value
- use the same substructure. The difference is that with the latter,
- 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. */
-struct Lisp_Buffer_Local_Value
- {
- int type : 16; /* = Lisp_Misc_Buffer_Local_Value
- or Lisp_Misc_Some_Buffer_Local_Value */
- int spacer : 16;
- Lisp_Object car, cdr;
- };
-
-/* In an overlay object, the mark bit of the plist is used as the GC mark.
- START and END are markers in the overlay's buffer, and
- PLIST is the overlay's property list. */
-struct Lisp_Overlay
- {
- int type : 16; /* = Lisp_Misc_Overlay */
- int spacer : 16;
- Lisp_Object start, end, plist;
- };
-
-/* Like Lisp_Objfwd except that value lives in a slot in the
- current kboard. */
-struct Lisp_Kboard_Objfwd
- {
- int type : 16; /* = Lisp_Misc_Kboard_Objfwd */
- int spacer : 16;
- int offset;
- };
-
-
-/* To get the type field of a union Lisp_Misc, use XMISCTYPE.
- It uses one of these struct subtypes to get the type field. */
-
-union Lisp_Misc
- {
- struct Lisp_Free u_free;
- struct Lisp_Marker u_marker;
- struct Lisp_Intfwd u_intfwd;
- struct Lisp_Boolfwd u_boolfwd;
- struct Lisp_Objfwd u_objfwd;
- struct Lisp_Buffer_Objfwd u_buffer_objfwd;
- struct Lisp_Buffer_Local_Value u_buffer_local_value;
- struct Lisp_Overlay u_overlay;
- struct Lisp_Kboard_Objfwd u_kboard_objfwd;
- };
-
-#ifdef LISP_FLOAT_TYPE
-/* Optional Lisp floating point type */
-struct Lisp_Float
- {
- Lisp_Object type; /* essentially used for mark-bit
- and chaining when on free-list */
- double data;
- };
-#endif /* LISP_FLOAT_TYPE */
-
-/* A character, declared with the following typedef, is a member
- of some character set associated with the current buffer. */
-#ifndef _UCHAR_T /* Protect against something in ctab.h on AIX. */
-#define _UCHAR_T
-typedef unsigned char UCHAR;
-#endif
-
-/* Meanings of slots in a Lisp_Compiled: */
-
-#define COMPILED_ARGLIST 0
-#define COMPILED_BYTECODE 1
-#define COMPILED_CONSTANTS 2
-#define COMPILED_STACK_DEPTH 3
-#define COMPILED_DOC_STRING 4
-#define COMPILED_INTERACTIVE 5
-
-/* Flag bits in a character. These also get used in termhooks.h.
- Richard Stallman <rms@gnu.ai.mit.edu> thinks that MULE
- (MUlti-Lingual Emacs) might need 22 bits for the character value
- itself, so we probably shouldn't use any bits lower than 0x0400000. */
-#define CHAR_ALT (0x0400000)
-#define CHAR_SUPER (0x0800000)
-#define CHAR_HYPER (0x1000000)
-#define CHAR_SHIFT (0x2000000)
-#define CHAR_CTL (0x4000000)
-#define CHAR_META (0x8000000)
-
-#ifdef USE_X_TOOLKIT
-#ifdef NO_UNION_TYPE
-/* Use this for turning a (void *) into a Lisp_Object, as when the
- Lisp_Object is passed into a toolkit callback function. */
-#define VOID_TO_LISP(larg,varg) \
- do { ((larg) = ((Lisp_Object) (varg))); } while (0)
-#define CVOID_TO_LISP VOID_TO_LISP
-
-/* Use this for turning a Lisp_Object into a (void *), as when the
- Lisp_Object is passed into a toolkit callback function. */
-#define LISP_TO_VOID(larg) ((void *) (larg))
-#define LISP_TO_CVOID(varg) ((const void *) (larg))
-
-#else /* not NO_UNION_TYPE */
-/* Use this for turning a (void *) into a Lisp_Object, as when the
- Lisp_Object is passed into a toolkit callback function. */
-#define VOID_TO_LISP(larg,varg) \
- do { ((larg).v = (void *) (varg)); } while (0)
-#define CVOID_TO_LISP(larg,varg) \
- do { ((larg).cv = (const void *) (varg)); } while (0)
-
-/* Use this for turning a Lisp_Object into a (void *), as when the
- Lisp_Object is passed into a toolkit callback function. */
-#define LISP_TO_VOID(larg) ((larg).v)
-#define LISP_TO_CVOID(larg) ((larg).cv)
-#endif /* not NO_UNION_TYPE */
-#endif /* USE_X_TOOLKIT */
-
-
-/* The glyph datatype, used to represent characters on the display. */
-
-/* The low eight bits are the character code, and the bits above them
- are the numeric face ID. If FID is the face ID of a glyph on a
- frame F, then F->display.x->faces[FID] contains the description of
- that face. This is an int instead of a short, so we can support a
- good bunch of face ID's; given that we have no mechanism for
- tossing unused frame face ID's yet, we'll probably run out of 255
- pretty quickly. */
-#define GLYPH unsigned int
-
-#ifdef HAVE_FACES
-/* The FAST macros assume that we already know we're in an X window. */
-
-/* Given a character code and a face ID, return the appropriate glyph. */
-#define FAST_MAKE_GLYPH(char, face) ((char) | ((face) << 8))
-
-/* Return a glyph's character code. */
-#define FAST_GLYPH_CHAR(glyph) ((glyph) & 0xff)
-
-/* Return a glyph's face ID. */
-#define FAST_GLYPH_FACE(glyph) (((glyph) >> 8) & ((1 << 24) - 1))
-
-/* Slower versions that test the frame type first. */
-#define MAKE_GLYPH(f, char, face) (FRAME_TERMCAP_P (f) ? (char) \
- : FAST_MAKE_GLYPH (char, face))
-#define GLYPH_CHAR(f, g) (FRAME_TERMCAP_P (f) ? (g) : FAST_GLYPH_CHAR (g))
-#define GLYPH_FACE(f, g) (FRAME_TERMCAP_P (f) ? (0) : FAST_GLYPH_FACE (g))
-#else /* not HAVE_FACES */
-#define MAKE_GLYPH(f, char, face) (char)
-#define GLYPH_CHAR(f, g) (g)
-#define GLYPH_FACE(f, g) (g)
-#endif /* not HAVE_FACES */
-
-/* The ID of the mode line highlighting face. */
-#define GLYPH_MODE_LINE_FACE 1
-
-/* Data type checking */
-
-#define NILP(x) (XFASTINT (x) == XFASTINT (Qnil))
-#define GC_NILP(x) GC_EQ (x, Qnil)
-
-#ifdef LISP_FLOAT_TYPE
-#define NUMBERP(x) (INTEGERP (x) || FLOATP (x))
-#define GC_NUMBERP(x) (GC_INTEGERP (x) || GC_FLOATP (x))
-#else
-#define NUMBERP(x) (INTEGERP (x))
-#define GC_NUMBERP(x) (GC_INTEGERP (x))
-#endif
-#define NATNUMP(x) (INTEGERP (x) && XINT (x) >= 0)
-#define GC_NATNUMP(x) (GC_INTEGERP (x) && XINT (x) >= 0)
-
-#define INTEGERP(x) (XTYPE ((x)) == Lisp_Int)
-#define GC_INTEGERP(x) (XGCTYPE ((x)) == Lisp_Int)
-#define SYMBOLP(x) (XTYPE ((x)) == Lisp_Symbol)
-#define GC_SYMBOLP(x) (XGCTYPE ((x)) == Lisp_Symbol)
-#define MISCP(x) (XTYPE ((x)) == Lisp_Misc)
-#define GC_MISCP(x) (XGCTYPE ((x)) == Lisp_Misc)
-#define VECTORLIKEP(x) (XTYPE ((x)) == Lisp_Vectorlike)
-#define GC_VECTORLIKEP(x) (XGCTYPE ((x)) == Lisp_Vectorlike)
-#define STRINGP(x) (XTYPE ((x)) == Lisp_String)
-#define GC_STRINGP(x) (XGCTYPE ((x)) == Lisp_String)
-#define CONSP(x) (XTYPE ((x)) == Lisp_Cons)
-#define GC_CONSP(x) (XGCTYPE ((x)) == Lisp_Cons)
-
-#ifdef LISP_FLOAT_TYPE
-#define FLOATP(x) (XTYPE ((x)) == Lisp_Float)
-#define GC_FLOATP(x) (XGCTYPE ((x)) == Lisp_Float)
-#else
-#define FLOATP(x) (0)
-#define GC_FLOATP(x) (0)
-#endif
-#define VECTORP(x) (VECTORLIKEP (x) && !(XVECTOR (x)->size & PSEUDOVECTOR_FLAG))
-#define GC_VECTORP(x) (GC_VECTORLIKEP (x) && !(XVECTOR (x)->size & PSEUDOVECTOR_FLAG))
-#define OVERLAYP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay)
-#define GC_OVERLAYP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay)
-#define MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
-#define GC_MARKERP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
-#define INTFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Intfwd)
-#define GC_INTFWDP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Intfwd)
-#define BOOLFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Boolfwd)
-#define GC_BOOLFWDP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Boolfwd)
-#define OBJFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Objfwd)
-#define GC_OBJFWDP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Objfwd)
-#define BUFFER_OBJFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Buffer_Objfwd)
-#define GC_BUFFER_OBJFWDP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Buffer_Objfwd)
-#define BUFFER_LOCAL_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Buffer_Local_Value)
-#define GC_BUFFER_LOCAL_VALUEP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Buffer_Local_Value)
-#define SOME_BUFFER_LOCAL_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Some_Buffer_Local_Value)
-#define GC_SOME_BUFFER_LOCAL_VALUEP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Some_Buffer_Local_Value)
-#define KBOARD_OBJFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Kboard_Objfwd)
-#define GC_KBOARD_OBJFWDP(x) (GC_MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Kboard_Objfwd)
-
-
-/* True if object X is a pseudovector whose code is CODE. */
-#define PSEUDOVECTORP(x, code) \
- (VECTORLIKEP (x) \
- && (((XVECTOR (x)->size & (PSEUDOVECTOR_FLAG | (code)))) \
- == (PSEUDOVECTOR_FLAG | (code))))
-
-/* True if object X is a pseudovector whose code is CODE.
- This one works during GC. */
-#define GC_PSEUDOVECTORP(x, code) \
- (GC_VECTORLIKEP (x) \
- && (((XVECTOR (x)->size & (PSEUDOVECTOR_FLAG | (code)))) \
- == (PSEUDOVECTOR_FLAG | (code))))
-
-/* Test for specific pseudovector types. */
-#define WINDOW_CONFIGURATIONP(x) PSEUDOVECTORP (x, PVEC_WINDOW_CONFIGURATION)
-#define GC_WINDOW_CONFIGURATIONP(x) GC_PSEUDOVECTORP (x, PVEC_WINDOW_CONFIGURATION)
-#define PROCESSP(x) PSEUDOVECTORP (x, PVEC_PROCESS)
-#define GC_PROCESSP(x) GC_PSEUDOVECTORP (x, PVEC_PROCESS)
-#define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW)
-#define GC_WINDOWP(x) GC_PSEUDOVECTORP (x, PVEC_WINDOW)
-#define SUBRP(x) PSEUDOVECTORP (x, PVEC_SUBR)
-#define GC_SUBRP(x) GC_PSEUDOVECTORP (x, PVEC_SUBR)
-#define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED)
-#define GC_COMPILEDP(x) GC_PSEUDOVECTORP (x, PVEC_COMPILED)
-#define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER)
-#define GC_BUFFERP(x) GC_PSEUDOVECTORP (x, PVEC_BUFFER)
-#define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE)
-#define GC_CHAR_TABLE_P(x) GC_PSEUDOVECTORP (x, PVEC_CHAR_TABLE)
-#define BOOL_VECTOR_P(x) PSEUDOVECTORP (x, PVEC_BOOL_VECTOR)
-#define GC_BOOL_VECTOR_P(x) GC_PSEUDOVECTORP (x, PVEC_BOOL_VECTOR)
-#define FRAMEP(x) PSEUDOVECTORP (x, PVEC_FRAME)
-#define GC_FRAMEP(x) GC_PSEUDOVECTORP (x, PVEC_FRAME)
-
-#define EQ(x, y) (XFASTINT (x) == XFASTINT (y))
-#define GC_EQ(x, y) (XGCTYPE (x) == XGCTYPE (y) && XPNTR (x) == XPNTR (y))
-
-#define CHECK_LIST(x, i) \
- do { if (!CONSP ((x)) && !NILP (x)) x = wrong_type_argument (Qlistp, (x)); } while (0)
-
-#define CHECK_STRING(x, i) \
- do { if (!STRINGP ((x))) x = wrong_type_argument (Qstringp, (x)); } while (0)
-
-#define CHECK_CONS(x, i) \
- do { if (!CONSP ((x))) x = wrong_type_argument (Qconsp, (x)); } while (0)
-
-#define CHECK_SYMBOL(x, i) \
- do { if (!SYMBOLP ((x))) x = wrong_type_argument (Qsymbolp, (x)); } while (0)
-
-#define CHECK_CHAR_TABLE(x, i) \
- do { if (!CHAR_TABLE_P ((x))) \
- x = wrong_type_argument (Qchar_table_p, (x)); } while (0)
-
-#define CHECK_VECTOR(x, i) \
- do { if (!VECTORP ((x))) x = wrong_type_argument (Qvectorp, (x)); } while (0)
-
-#define CHECK_VECTOR_OR_CHAR_TABLE(x, i) \
- do { if (!VECTORP ((x)) && !CHAR_TABLE_P ((x))) \
- x = wrong_type_argument (Qvector_or_char_table_p, (x)); \
- } while (0)
-
-#define CHECK_BUFFER(x, i) \
- do { if (!BUFFERP ((x))) x = wrong_type_argument (Qbufferp, (x)); } while (0)
-
-#define CHECK_WINDOW(x, i) \
- do { if (!WINDOWP ((x))) x = wrong_type_argument (Qwindowp, (x)); } while (0)
-
-/* This macro rejects windows on the interior of the window tree as
- "dead", which is what we want; this is an argument-checking macro, and
- the user should never get access to interior windows.
-
- A window of any sort, leaf or interior, is dead iff the buffer,
- vchild, and hchild members are all nil. */
-
-#define CHECK_LIVE_WINDOW(x, i) \
- do { \
- if (!WINDOWP ((x)) \
- || NILP (XWINDOW ((x))->buffer)) \
- x = wrong_type_argument (Qwindow_live_p, (x)); \
- } while (0)
-
-#define CHECK_PROCESS(x, i) \
- do { if (!PROCESSP ((x))) x = wrong_type_argument (Qprocessp, (x)); } while (0)
-
-#define CHECK_NUMBER(x, i) \
- do { if (!INTEGERP ((x))) x = wrong_type_argument (Qintegerp, (x)); } while (0)
-
-#define CHECK_NATNUM(x, i) \
- do { if (!NATNUMP (x)) x = wrong_type_argument (Qwholenump, (x)); } while (0)
-
-#define CHECK_MARKER(x, i) \
- do { if (!MARKERP ((x))) x = wrong_type_argument (Qmarkerp, (x)); } while (0)
-
-#define CHECK_NUMBER_COERCE_MARKER(x, i) \
- do { if (MARKERP ((x))) XSETFASTINT (x, marker_position (x)); \
- else if (!INTEGERP ((x))) x = wrong_type_argument (Qinteger_or_marker_p, (x)); } while (0)
-
-#ifdef LISP_FLOAT_TYPE
-
-#ifndef DBL_DIG
-#define DBL_DIG 20
-#endif
-
-#define XFLOATINT(n) extract_float((n))
-
-#define CHECK_FLOAT(x, i) \
- do { if (!FLOATP (x)) \
- x = wrong_type_argument (Qfloatp, (x)); } while (0)
-
-#define CHECK_NUMBER_OR_FLOAT(x, i) \
- do { if (!FLOATP (x) && !INTEGERP (x)) \
- x = wrong_type_argument (Qnumberp, (x)); } while (0)
-
-#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(x, i) \
- do { if (MARKERP (x)) XSETFASTINT (x, marker_position (x)); \
- else if (!INTEGERP (x) && !FLOATP (x)) \
- x = wrong_type_argument (Qnumber_or_marker_p, (x)); } while (0)
-
-#else /* Not LISP_FLOAT_TYPE */
-
-#define CHECK_NUMBER_OR_FLOAT CHECK_NUMBER
-
-#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER CHECK_NUMBER_COERCE_MARKER
-
-#define XFLOATINT(n) XINT((n))
-#endif /* LISP_FLOAT_TYPE */
-
-#define CHECK_OVERLAY(x, i) \
- do { if (!OVERLAYP ((x))) x = wrong_type_argument (Qoverlayp, (x));} while (0)
-
-/* 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.
- See the doc string for `interactive'.
- A null string means call interactively with no arguments.
- `doc' is documentation for the user. */
-
-#if !defined (__STDC__) || defined (USE_NONANSI_DEFUN)
-#define DEFUN(lname, fnname, sname, minargs, maxargs, prompt, doc) \
- Lisp_Object fnname (); \
- struct Lisp_Subr sname = \
- { PVEC_SUBR | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)), \
- fnname, minargs, maxargs, lname, prompt, 0}; \
- Lisp_Object fnname
-
-#else
-
-/* This version of DEFUN declares a function prototype with the right
- arguments, so we can catch errors with maxargs at compile-time. */
-#define DEFUN(lname, fnname, sname, minargs, maxargs, prompt, doc) \
- Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \
- struct Lisp_Subr sname = \
- { PVEC_SUBR | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)), \
- fnname, minargs, maxargs, lname, prompt, 0}; \
- Lisp_Object fnname
-
-/* Note that the weird token-substitution semantics of ANSI C makes
- this work for MANY and UNEVALLED. */
-#define DEFUN_ARGS_MANY (int, Lisp_Object *)
-#define DEFUN_ARGS_UNEVALLED (Lisp_Object)
-#define DEFUN_ARGS_0 (void)
-#define DEFUN_ARGS_1 (Lisp_Object)
-#define DEFUN_ARGS_2 (Lisp_Object, Lisp_Object)
-#define DEFUN_ARGS_3 (Lisp_Object, Lisp_Object, Lisp_Object)
-#define DEFUN_ARGS_4 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)
-#define DEFUN_ARGS_5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
- Lisp_Object)
-#define DEFUN_ARGS_6 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
- Lisp_Object, Lisp_Object)
-#define DEFUN_ARGS_7 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
- Lisp_Object, Lisp_Object, Lisp_Object)
-#endif
-
-/* defsubr (Sname);
- is how we define the symbol for function `name' at start-up time. */
-extern void defsubr ();
-
-#define MANY -2
-#define UNEVALLED -1
-
-extern void defvar_lisp ();
-extern void defvar_bool ();
-extern void defvar_int ();
-extern void defvar_kboard ();
-
-/* Macros we use to define forwarded Lisp variables.
- These are used in the syms_of_FILENAME functions. */
-
-#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, type, doc) \
- defvar_per_buffer (lname, vname, type, 0)
-#define DEFVAR_KBOARD(lname, vname, doc) \
- defvar_kboard (lname, \
- (int)((char *)(&current_kboard->vname) \
- - (char *)current_kboard))
-
-/* Structure for recording Lisp call stack for backtrace purposes. */
-
-/* The special binding stack holds the outer values of variables while
- they are bound by a function application or a let form, stores the
- code to be executed for Lisp unwind-protect forms, and stores the C
- functions to be called for record_unwind_protect.
-
- If func is non-zero, undoing this binding applies func to old_value;
- This implements record_unwind_protect.
- If func is zero and symbol is nil, undoing this binding evaluates
- the list of forms in old_value; this implements Lisp's unwind-protect
- form.
- Otherwise, undoing this binding stores old_value as symbol's value; this
- undoes the bindings made by a let form or function call. */
-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;
-
-/* Everything needed to describe an active condition case. */
-struct handler
- {
- /* The handler clauses and variable from the condition-case form. */
- Lisp_Object handler;
- Lisp_Object var;
- /* Fsignal stores here the condition-case clause that applies,
- and Fcondition_case thus knows which clause to run. */
- Lisp_Object chosen_clause;
-
- /* Used to effect the longjump out to the handler. */
- struct catchtag *tag;
-
- /* The next enclosing handler. */
- struct handler *next;
- };
-
-extern struct handler *handlerlist;
-
-extern struct catchtag *catchlist;
-extern struct backtrace *backtrace_list;
-
-extern Lisp_Object memory_signal_data;
-
-/* An address near the bottom of the stack.
- Tells GC how to save a copy of the stack. */
-extern char *stack_bottom;
-
-/* Check quit-flag and quit if it is non-nil. */
-
-#define QUIT \
- if (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) \
- { Vquit_flag = Qnil; Fsignal (Qquit, Qnil); }
-
-/* Nonzero if ought to quit now. */
-
-#define QUITP (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
-
-/* 1 if CH is upper case. */
-
-#define UPPERCASEP(CH) \
- (XCHAR_TABLE (current_buffer->downcase_table)->contents[CH] != (CH))
-
-/* 1 if CH is lower case. */
-
-#define LOWERCASEP(CH) \
- (!UPPERCASEP (CH) \
- && XCHAR_TABLE (current_buffer->upcase_table)->contents[CH] != (CH))
-
-/* 1 if CH is neither upper nor lower case. */
-
-#define NOCASEP(CH) \
- (XCHAR_TABLE (current_buffer->upcase_table)->contents[CH] == (CH))
-
-/* Upcase a character, or make no change if that cannot be done. */
-
-#define UPCASE(CH) \
- (XCHAR_TABLE (current_buffer->downcase_table)->contents[CH] == (CH) \
- ? UPCASE1 (CH) : (CH))
-
-/* Upcase a character known to be not upper case. */
-
-#define UPCASE1(CH) (XCHAR_TABLE (current_buffer->upcase_table)->contents[CH])
-
-/* Downcase a character, or make no change if that cannot be done. */
-
-#define DOWNCASE(CH) \
- (XCHAR_TABLE (current_buffer->downcase_table)->contents[CH])
-
-/* Current buffer's map from characters to lower-case characters. */
-
-#define DOWNCASE_TABLE XCHAR_TABLE (current_buffer->downcase_table)->contents
-
-extern Lisp_Object Vascii_downcase_table;
-
-/* Number of bytes of structure consed since last GC. */
-
-extern int consing_since_gc;
-
-/* Threshold for doing another gc. */
-
-extern int gc_cons_threshold;
-
-/* 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; }
-
-#define GCPRO5(varname1, varname2, varname3, varname4, varname5) \
- {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; \
- gcpro5.next = &gcpro4; gcpro5.var = &varname5; gcpro5.nvars = 1; \
- gcprolist = &gcpro5; }
-
-/* Call staticpro (&var) to protect static variable `var'. */
-
-void staticpro();
-
-#define UNGCPRO (gcprolist = gcpro1.next)
-
-/* Evaluate expr, UNGCPRO, and then return the value of expr. */
-#define RETURN_UNGCPRO(expr) \
-if (1) \
- { \
- Lisp_Object ret_ungc_val; \
- ret_ungc_val = (expr); \
- UNGCPRO; \
- return ret_ungc_val; \
- } \
-else
-
-/* 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 Qmark_inactive;
-
-extern Lisp_Object Qrange_error, Qdomain_error, Qsingularity_error;
-extern Lisp_Object Qoverflow_error, Qunderflow_error;
-
-extern Lisp_Object Qintegerp, Qnumberp, Qnatnump, Qwholenump;
-extern Lisp_Object 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, Qnumber_or_marker_p;
-extern Lisp_Object Qchar_table_p, Qvector_or_char_table_p;
-extern Lisp_Object Qboundp, Qfboundp;
-extern Lisp_Object Qbuffer_or_string_p;
-extern Lisp_Object Qcdr;
-
-#ifdef LISP_FLOAT_TYPE
-extern Lisp_Object Qfloatp, Qinteger_or_floatp, Qinteger_or_float_or_marker_p;
-#endif /* LISP_FLOAT_TYPE */
-
-extern Lisp_Object Qframep;
-
-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 ();
-#ifdef LISP_FLOAT_TYPE
-extern Lisp_Object Ffloatp(), Finteger_or_floatp();
-extern Lisp_Object Finteger_or_float_or_marker_p(), Ftruncate();
-#endif /* LISP_FLOAT_TYPE */
-
-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 indirect_function (), Findirect_function ();
-extern Lisp_Object Ffset (), Fsetplist ();
-extern Lisp_Object Fsymbol_value (), find_symbol_value (), Fset ();
-extern Lisp_Object Fdefault_value (), Fset_default (), Fdefault_boundp ();
-extern Lisp_Object Fmake_local_variable ();
-
-extern Lisp_Object Faref (), Faset ();
-
-extern Lisp_Object Fstring_to_number (), Fnumber_to_string ();
-extern Lisp_Object Feqlsign (), Fgtr (), Flss (), Fgeq (), Fleq ();
-extern Lisp_Object Fneq (), Fzerop ();
-extern Lisp_Object Fplus (), Fminus (), Ftimes (), Fquo (), Frem ();
-extern Lisp_Object Fmax (), Fmin ();
-extern Lisp_Object Flogand (), Flogior (), Flogxor (), Flognot ();
-extern Lisp_Object Flsh (), Fash ();
-
-extern Lisp_Object Fadd1 (), Fsub1 ();
-
-extern Lisp_Object long_to_cons ();
-extern unsigned long cons_to_long ();
-extern void args_out_of_range ();
-extern void args_out_of_range_3 ();
-extern Lisp_Object wrong_type_argument ();
-extern void store_symval_forwarding ();
-extern Lisp_Object do_symval_forwarding ();
-#ifdef LISP_FLOAT_TYPE
-extern Lisp_Object Ffloat_to_int(), Fint_to_float();
-extern double extract_float();
-extern Lisp_Object make_float ();
-extern Lisp_Object Ffloat ();
-#endif /* LISP_FLOAT_TYPE */
-
-/* Defined in cmds.c */
-extern Lisp_Object Fend_of_line (), Fforward_char (), Fforward_line ();
-
-/* Defined in syntax.c */
-extern Lisp_Object Fforward_word ();
-
-/* Defined in fns.c */
-extern Lisp_Object Qstring_lessp;
-extern Lisp_Object Vfeatures;
-extern Lisp_Object Fidentity (), Frandom ();
-extern Lisp_Object Flength (), Fsafe_length ();
-extern Lisp_Object Fappend (), Fconcat (), Fvconcat (), Fcopy_sequence ();
-extern Lisp_Object Fsubstring ();
-extern Lisp_Object Fnth (), Fnthcdr (), Fmemq (), Fassq (), Fassoc ();
-extern Lisp_Object Felt (), Fmember (), 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 (), do_yes_or_no_p ();
-extern Lisp_Object Ffeaturep (), Frequire () , Fprovide ();
-extern Lisp_Object concat2 (), nconc2 ();
-extern Lisp_Object assq_no_quit ();
-extern Lisp_Object Fcopy_alist ();
-extern Lisp_Object Fplist_get ();
-extern Lisp_Object Fset_char_table_parent ();
-
-/* Defined in insdel.c */
-extern void move_gap ();
-extern void make_gap ();
-extern void insert ();
-extern void insert_and_inherit ();
-extern void insert_1 ();
-extern void insert_from_string ();
-extern void insert_from_buffer ();
-extern void insert_char ();
-extern void insert_string ();
-extern void insert_before_markers ();
-extern void insert_before_markers_and_inherit ();
-extern void insert_from_string_before_markers ();
-extern void del_range ();
-extern void del_range_1 ();
-extern void modify_region ();
-extern void prepare_to_modify_buffer ();
-extern void signal_before_change ();
-extern void signal_after_change ();
-
-/* Defined in dispnew.c */
-extern Lisp_Object Fding (), Fredraw_display ();
-extern Lisp_Object Fsleep_for ();
-
-/* Defined in xdisp.c */
-extern Lisp_Object Vmessage_log_max;
-extern void message ();
-extern void message_nolog ();
-extern void message1 ();
-extern void message1_nolog ();
-extern void message2 ();
-extern void message2_nolog ();
-extern void message_dolog ();
-extern void message_log_maybe_newline ();
-
-/* Defined in alloc.c */
-extern Lisp_Object Vpurify_flag;
-extern Lisp_Object Fcons (), Flist(), Fmake_list (), allocate_misc ();
-extern Lisp_Object Fmake_vector (), Fvector (), Fmake_symbol (), Fmake_marker ();
-extern Lisp_Object Fmake_string (), build_string (), make_string ();
-extern Lisp_Object make_event_array (), make_uninit_string ();
-extern Lisp_Object Fpurecopy (), make_pure_string ();
-extern Lisp_Object pure_cons (), make_pure_vector ();
-extern Lisp_Object Fgarbage_collect ();
-extern Lisp_Object Fmake_byte_code ();
-extern Lisp_Object Fmake_bool_vector (), Fmake_char_table ();
-extern Lisp_Object Qchar_table_extra_slots;
-extern struct Lisp_Vector *allocate_vectorlike ();
-extern int gc_in_progress;
-
-/* 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 Ferror_message_string ();
-extern Lisp_Object Vstandard_output, Qstandard_output;
-extern Lisp_Object Qexternal_debugging_output;
-extern void temp_output_buffer_setup (), temp_output_buffer_show ();
-extern int print_level, print_escape_newlines;
-extern Lisp_Object Qprint_escape_newlines;
-
-/* 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 read_filtered_event ();
-extern Lisp_Object Feval_current_buffer (), Feval_region ();
-extern Lisp_Object intern (), make_symbol (), oblookup ();
-#define LOADHIST_ATTACH(x) \
- if (initialized) Vcurrent_load_list = Fcons (x, Vcurrent_load_list)
-extern Lisp_Object Vcurrent_load_list;
-extern Lisp_Object Vload_history;
-
-/* Defined in eval.c */
-extern Lisp_Object Qautoload, Qexit, Qinteractive, Qcommandp, Qdefun, Qmacro;
-extern Lisp_Object Vinhibit_quit, Qinhibit_quit, Vquit_flag;
-extern Lisp_Object Vmocklisp_arguments, Qmocklisp, Qmocklisp_arguments;
-extern Lisp_Object Vautoload_queue;
-extern Lisp_Object Vdebug_on_error;
-/* To run a normal hook, use the appropriate function from the list below.
- The calling convention:
-
- if (!NILP (Vrun_hooks))
- call1 (Vrun_hooks, Qmy_funny_hook);
-
- should no longer be used. */
-extern Lisp_Object Vrun_hooks;
-extern Lisp_Object Frun_hooks (), Frun_hook_with_args ();
-extern Lisp_Object Frun_hook_with_args_until_success ();
-extern Lisp_Object Frun_hook_with_args_until_failure ();
-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 call4 (), call5 (), call6 ();
-extern Lisp_Object Fkill_emacs (), Fkey_binding (), Fsit_for ();
-extern Lisp_Object Fdo_auto_save (), Fset_marker ();
-extern Lisp_Object apply_lambda ();
-extern Lisp_Object internal_catch ();
-extern Lisp_Object internal_condition_case ();
-extern Lisp_Object internal_condition_case_1 ();
-extern Lisp_Object unbind_to ();
-extern void error ();
-extern Lisp_Object un_autoload ();
-extern Lisp_Object Ffetch_bytecode ();
-
-/* Defined in editfns.c */
-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 Fline_beginning_position (), Fline_end_position ();
-extern Lisp_Object Ffollowing_char (), Fprevious_char (), Fchar_after ();
-extern Lisp_Object Finsert (), Finsert_and_inherit ();
-extern Lisp_Object Finsert_before_markers ();
-extern Lisp_Object Finsert_buffer_substring ();
-extern Lisp_Object Finsert_char ();
-extern Lisp_Object Feolp (), Feobp (), Fbolp (), Fbobp ();
-extern Lisp_Object Fformat (), format1 ();
-extern Lisp_Object make_buffer_string (), Fbuffer_substring ();
-extern Lisp_Object 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 ();
-extern Lisp_Object Fdelete_region (), Fnarrow_to_region (), Fwiden ();
-
-/* defined in buffer.c */
-extern Lisp_Object Foverlay_start (), Foverlay_end ();
-extern void adjust_overlays_for_insert ();
-extern void adjust_overlays_for_delete ();
-extern void fix_overlays_in_range ();
-extern int overlay_touches_p ();
-extern Lisp_Object Vbuffer_alist, Vinhibit_read_only;
-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 Lisp_Object Foverlay_get ();
-extern Lisp_Object Fbuffer_modified_p (), Fset_buffer_modified_p ();
-extern Lisp_Object Fkill_buffer (), Fkill_all_local_variables ();
-extern Lisp_Object Fbuffer_disable_undo (), Fbuffer_enable_undo ();
-extern Lisp_Object Ferase_buffer ();
-extern Lisp_Object Qoverlayp;
-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 Ffind_file_name_handler ();
-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 ();
-extern Lisp_Object Fverify_visited_file_modtime ();
-extern Lisp_Object Ffile_exists_p ();
-extern Lisp_Object Ffile_name_absolute_p ();
-extern Lisp_Object Fdirectory_file_name ();
-extern Lisp_Object Ffile_name_directory ();
-extern Lisp_Object expand_and_dir_to_file ();
-extern Lisp_Object Ffile_accessible_directory_p ();
-extern Lisp_Object Funhandled_file_name_directory ();
-extern Lisp_Object Ffile_directory_p ();
-extern Lisp_Object Fwrite_region ();
-
-/* Defined in abbrev.c */
-
-extern Lisp_Object Vfundamental_mode_abbrev_table;
-
-/* defined in search.c */
-extern Lisp_Object Fstring_match ();
-extern Lisp_Object Fscan_buffer ();
-extern void restore_match_data ();
-extern Lisp_Object Fmatch_data (), Fstore_match_data ();
-extern Lisp_Object Fmatch_beginning (), Fmatch_end ();
-extern Lisp_Object Fskip_chars_forward (), Fskip_chars_backward ();
-
-/* defined in minibuf.c */
-
-extern Lisp_Object last_minibuf_string;
-extern Lisp_Object read_minibuf (), Fcompleting_read ();
-extern Lisp_Object Fread_from_minibuffer ();
-extern Lisp_Object Fread_variable (), Fread_buffer (), Fread_key_sequence ();
-extern Lisp_Object Fread_minibuffer (), Feval_minibuffer ();
-extern Lisp_Object Fread_string (), Fread_file_name ();
-extern Lisp_Object Fread_no_blanks_input ();
-extern Lisp_Object get_minibuffer ();
-
-/* Defined in callint.c */
-
-extern Lisp_Object Qminus, Qplus, Vcurrent_prefix_arg;
-extern Lisp_Object Vcommand_history;
-extern Lisp_Object Qcall_interactively, Qmouse_leave_buffer_hook;
-extern Lisp_Object Fcall_interactively ();
-extern Lisp_Object Fprefix_numeric_value ();
-
-/* defined in casefiddle.c */
-
-extern Lisp_Object Fdowncase (), Fupcase (), Fcapitalize ();
-extern Lisp_Object Fupcase_region ();
-extern Lisp_Object Fupcase_initials (), Fupcase_initials_region ();
-
-/* defined in casetab.c */
-
-extern Lisp_Object Fset_case_table ();
-extern Lisp_Object Fset_standard_case_table ();
-
-/* defined in keyboard.c */
-
-extern Lisp_Object Qdisabled;
-extern Lisp_Object Vhelp_form, Vtop_level;
-extern Lisp_Object Fdiscard_input (), Frecursive_edit ();
-extern Lisp_Object Fcommand_execute (), Finput_pending_p ();
-extern Lisp_Object menu_bar_items ();
-extern Lisp_Object Qvertical_scroll_bar;
-extern Lisp_Object Fevent_convert_list ();
-#ifdef MULTI_KBOARD
-extern void delete_kboard ();
-#endif
-
-/* defined in keymap.c */
-
-extern Lisp_Object Qkeymap, Qmenu_bar;
-extern Lisp_Object current_global_map;
-extern Lisp_Object Fdefine_key ();
-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 (), get_keymap_1 ();
-extern void describe_map_tree ();
-
-/* defined in indent.c */
-extern Lisp_Object Fvertical_motion (), Findent_to (), Fcurrent_column ();
-
-/* defined in window.c */
-extern Lisp_Object Qwindowp, Qwindow_live_p;
-extern Lisp_Object Fselected_window ();
-extern Lisp_Object Fget_buffer_window ();
-extern Lisp_Object Fsave_window_excursion ();
-extern Lisp_Object Fset_window_configuration (), Fcurrent_window_configuration ();
-extern Lisp_Object Fcoordinates_in_window_p ();
-extern Lisp_Object Fwindow_at ();
-extern Lisp_Object Fpos_visible_in_window_p ();
-extern int window_internal_height (), window_internal_width ();
-extern Lisp_Object Frecenter ();
-extern Lisp_Object Fscroll_other_window ();
-extern Lisp_Object Fset_window_start ();
-
-/* defined in frame.c */
-extern Lisp_Object Qvisible;
-extern void store_frame_param (), store_in_alist ();
-extern Lisp_Object do_switch_frame ();
-extern Lisp_Object get_frame_param();
-extern Lisp_Object frame_buffer_predicate ();
-extern Lisp_Object Fframep ();
-extern Lisp_Object Fselect_frame ();
-extern Lisp_Object Fselected_frame ();
-extern Lisp_Object Fwindow_frame ();
-extern Lisp_Object Fframe_root_window ();
-extern Lisp_Object Fframe_first_window ();
-extern Lisp_Object Fframe_selected_window ();
-extern Lisp_Object Fframe_list ();
-extern Lisp_Object Fnext_frame ();
-extern Lisp_Object Fdelete_frame ();
-extern Lisp_Object Fread_mouse_position ();
-extern Lisp_Object Fset_mouse_position ();
-extern Lisp_Object Fmake_frame_visible ();
-extern Lisp_Object Fmake_frame_invisible ();
-extern Lisp_Object Ficonify_frame ();
-extern Lisp_Object Fdeiconify_frame ();
-extern Lisp_Object Fframe_visible_p ();
-extern Lisp_Object Fvisible_frame_list ();
-extern Lisp_Object Fframe_parameters ();
-extern Lisp_Object Fmodify_frame_parameters ();
-extern Lisp_Object Fframe_pixel_size ();
-extern Lisp_Object Fframe_height ();
-extern Lisp_Object Fframe_width ();
-extern Lisp_Object Fset_frame_height ();
-extern Lisp_Object Fset_frame_width ();
-extern Lisp_Object Fset_frame_size ();
-extern Lisp_Object Fset_frame_position ();
-extern Lisp_Object Fraise_frame ();
-extern Lisp_Object Fredirect_frame_focus ();
-
-/* defined in emacs.c */
-extern Lisp_Object decode_env_path ();
-extern Lisp_Object Vinvocation_name, Vinvocation_directory;
-extern Lisp_Object Vinstallation_directory;
-void shut_down_emacs ( /* int signal, int no_x, Lisp_Object stuff */ );
-/* 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;
-/* Nonzero means that a filter or a sentinel is running. */
-extern int running_asynch_code;
-
-/* defined in process.c */
-extern Lisp_Object Fget_process (), Fget_buffer_process (), Fprocessp ();
-extern Lisp_Object Fprocess_status (), Fkill_process ();
-extern Lisp_Object Fprocess_send_eof ();
-extern Lisp_Object Fwaiting_for_user_input_p ();
-extern Lisp_Object Qprocessp;
-
-/* defined in callproc.c */
-extern Lisp_Object Vexec_path, Vexec_directory, Vdata_directory;
-extern Lisp_Object Vdoc_directory;
-
-/* defined in doc.c */
-extern Lisp_Object Vdoc_file_name;
-extern Lisp_Object Fsubstitute_command_keys ();
-extern Lisp_Object Fdocumentation (), Fdocumentation_property ();
-extern Lisp_Object read_doc_string ();
-
-/* defined in bytecode.c */
-extern Lisp_Object Qbytecode;
-extern Lisp_Object Fbyte_code ();
-
-/* defined in macros.c */
-extern Lisp_Object Qexecute_kbd_macro;
-extern Lisp_Object Fexecute_kbd_macro ();
-
-/* defined in undo.c */
-extern Lisp_Object Qinhibit_read_only;
-extern Lisp_Object Fundo_boundary ();
-extern Lisp_Object truncate_undo_list ();
-
-/* defined in textprop.c */
-extern Lisp_Object Qmodification_hooks;
-extern Lisp_Object Qrear_nonsticky, Qfont;
-extern Lisp_Object Qinsert_in_front_hooks, Qinsert_behind_hooks;
-extern Lisp_Object Fnext_property_change ();
-extern Lisp_Object Fnext_single_property_change ();
-extern Lisp_Object Fprevious_single_property_change ();
-extern Lisp_Object Fget_text_property (), Fput_text_property ();
-extern Lisp_Object Fset_text_properties ();
-extern Lisp_Object Ftext_property_not_all ();
-
-/* defined in intervals.c */
-extern Lisp_Object get_local_map ();
-
-/* defined in xmenu.c */
-extern Lisp_Object Fx_popup_menu (), Fx_popup_dialog ();
-
-/* 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 *getenv (), *ctime (), *getwd ();
-extern long *xmalloc (), *xrealloc ();
-extern void xfree ();
-
-extern char *egetenv ();
-
-/* Set up the name of the machine we're running on. */
-extern void init_system_name ();
-
-/* Some systems (e.g., NT) use a different path separator than Unix,
- in addition to a device separator. Default the path separator
- to '/', and don't test for a device separator in IS_ANY_SEP. */
-
-#ifdef WINDOWSNT
-extern Lisp_Object Vdirectory_sep_char;
-#endif
-
-#ifndef DIRECTORY_SEP
-#define DIRECTORY_SEP '/'
-#endif
-#ifndef IS_DIRECTORY_SEP
-#define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
-#endif
-#ifndef IS_DEVICE_SEP
-#ifndef DEVICE_SEP
-#define IS_DEVICE_SEP(_c_) 0
-#else
-#define IS_DEVICE_SEP(_c_) ((_c_) == DEVICE_SEP)
-#endif
-#endif
-#ifndef IS_ANY_SEP
-#define IS_ANY_SEP(_c_) (IS_DIRECTORY_SEP (_c_))
-#endif
-
-#ifdef SWITCH_ENUM_BUG
-#define SWITCH_ENUM_CAST(x) ((int)(x))
-#else
-#define SWITCH_ENUM_CAST(x) (x)
-#endif
diff --git a/src/lread.c b/src/lread.c
deleted file mode 100644
index 647735c8555..00000000000
--- a/src/lread.c
+++ /dev/null
@@ -1,2604 +0,0 @@
-/* Lisp parsing and input streams.
- Copyright (C) 1985, 1986, 1987, 1988, 1989,
- 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <errno.h>
-#include "lisp.h"
-
-#ifndef standalone
-#include "buffer.h"
-#include <paths.h>
-#include "commands.h"
-#include "keyboard.h"
-#include "termhooks.h"
-#endif
-
-#ifdef lint
-#include <sys/inode.h>
-#endif /* lint */
-
-#ifdef MSDOS
-#if __DJGPP__ < 2
-#include <unistd.h> /* to get X_OK */
-#endif
-#include "msdos.h"
-#endif
-
-#ifndef X_OK
-#define X_OK 01
-#endif
-
-#ifdef LISP_FLOAT_TYPE
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#endif
-
-#include <math.h>
-#endif /* LISP_FLOAT_TYPE */
-
-#ifdef HAVE_SETLOCALE
-#include <locale.h>
-#endif /* HAVE_SETLOCALE */
-
-#ifndef O_RDONLY
-#define O_RDONLY 0
-#endif
-
-extern int errno;
-
-Lisp_Object Qread_char, Qget_file_char, Qstandard_input, Qcurrent_load_list;
-Lisp_Object Qvariable_documentation, Vvalues, Vstandard_input, Vafter_load_alist;
-Lisp_Object Qascii_character, Qload, Qload_file_name;
-Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
-
-extern Lisp_Object Qevent_symbol_element_mask;
-
-/* non-zero if inside `load' */
-int load_in_progress;
-
-/* Directory in which the sources were found. */
-Lisp_Object Vsource_directory;
-
-/* Search path for files to be loaded. */
-Lisp_Object Vload_path;
-
-/* This is the user-visible association list that maps features to
- lists of defs in their load files. */
-Lisp_Object Vload_history;
-
-/* This is used to build the load history. */
-Lisp_Object Vcurrent_load_list;
-
-/* Name of file actually being read by `load'. */
-Lisp_Object Vload_file_name;
-
-/* Function to use for reading, in `load' and friends. */
-Lisp_Object Vload_read_function;
-
-/* The association list of objects read with the #n=object form.
- Each member of the list has the form (n . object), and is used to
- look up the object for the corresponding #n# construct.
- It must be set to nil before all top-level calls to read0. */
-Lisp_Object read_objects;
-
-/* Nonzero means load should forcibly load all dynamic doc strings. */
-static int load_force_doc_strings;
-
-/* List of descriptors now open for Fload. */
-static Lisp_Object load_descriptor_list;
-
-/* 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;
-
-/* This contains the last string skipped with #@. */
-static char *saved_doc_string;
-/* Length of buffer allocated in saved_doc_string. */
-static int saved_doc_string_size;
-/* Length of actual data in saved_doc_string. */
-static int saved_doc_string_length;
-/* This is the file position that string came from. */
-static int saved_doc_string_position;
-
-/* Nonzero means inside a new-style backquote
- with no surrounding parentheses.
- Fread initializes this to zero, so we need not specbind it
- or worry about what happens to it when there is an error. */
-static int new_backquote_flag;
-
-/* Handle unreading and rereading of characters.
- Write READCHAR to read a character,
- UNREAD(c) to unread c to be read again. */
-
-#define READCHAR readchar (readcharfun)
-#define UNREAD(c) unreadchar (readcharfun, c)
-
-static int
-readchar (readcharfun)
- Lisp_Object readcharfun;
-{
- Lisp_Object tem;
- register struct buffer *inbuffer;
- register int c, mpos;
-
- if (BUFFERP (readcharfun))
- {
- 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 (MARKERP (readcharfun))
- {
- 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))
- {
- c = getc (instream);
-#ifdef EINTR
- /* Interrupted reads have been observed while reading over the network */
- while (c == EOF && ferror (instream) && errno == EINTR)
- {
- clearerr (instream);
- c = getc (instream);
- }
-#endif
- return c;
- }
-
- if (STRINGP (readcharfun))
- {
- 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 (NILP (tem))
- return -1;
- return XINT (tem);
-}
-
-/* Unread the character C in the way appropriate for the stream READCHARFUN.
- If the stream is a user function, call it with the char as argument. */
-
-static void
-unreadchar (readcharfun, c)
- Lisp_Object readcharfun;
- int c;
-{
- if (c == -1)
- /* Don't back up the pointer if we're unreading the end-of-input mark,
- since readchar didn't advance it when we read it. */
- ;
- else if (BUFFERP (readcharfun))
- {
- if (XBUFFER (readcharfun) == current_buffer)
- SET_PT (PT - 1);
- else
- SET_BUF_PT (XBUFFER (readcharfun), BUF_PT (XBUFFER (readcharfun)) - 1);
- }
- else if (MARKERP (readcharfun))
- XMARKER (readcharfun)->bufpos--;
- else if (STRINGP (readcharfun))
- read_from_string_index--;
- else if (EQ (readcharfun, Qget_file_char))
- ungetc (c, instream);
- else
- call1 (readcharfun, make_number (c));
-}
-
-static Lisp_Object read0 (), read1 (), read_list (), read_vector ();
-
-/* get a character from the tty */
-
-extern Lisp_Object read_char ();
-
-/* Read input events until we get one that's acceptable for our purposes.
-
- If NO_SWITCH_FRAME is non-zero, switch-frame events are stashed
- until we get a character we like, and then stuffed into
- unread_switch_frame.
-
- If ASCII_REQUIRED is non-zero, we check function key events to see
- if the unmodified version of the symbol has a Qascii_character
- property, and use that character, if present.
-
- If ERROR_NONASCII is non-zero, we signal an error if the input we
- get isn't an ASCII character with modifiers. If it's zero but
- ASCII_REQUIRED is non-zero, we just re-read until we get an ASCII
- character. */
-
-Lisp_Object
-read_filtered_event (no_switch_frame, ascii_required, error_nonascii)
- int no_switch_frame, ascii_required, error_nonascii;
-{
-#ifdef standalone
- return make_number (getchar ());
-#else
- register Lisp_Object val, delayed_switch_frame;
-
- delayed_switch_frame = Qnil;
-
- /* Read until we get an acceptable event. */
- retry:
- val = read_char (0, 0, 0, Qnil, 0);
-
- if (BUFFERP (val))
- goto retry;
-
- /* switch-frame events are put off until after the next ASCII
- character. This is better than signaling an error just because
- the last characters were typed to a separate minibuffer frame,
- for example. Eventually, some code which can deal with
- switch-frame events will read it and process it. */
- if (no_switch_frame
- && EVENT_HAS_PARAMETERS (val)
- && EQ (EVENT_HEAD (val), Qswitch_frame))
- {
- delayed_switch_frame = val;
- goto retry;
- }
-
- if (ascii_required)
- {
- /* Convert certain symbols to their ASCII equivalents. */
- if (SYMBOLP (val))
- {
- Lisp_Object tem, tem1, tem2;
- tem = Fget (val, Qevent_symbol_element_mask);
- if (!NILP (tem))
- {
- tem1 = Fget (Fcar (tem), Qascii_character);
- /* Merge this symbol's modifier bits
- with the ASCII equivalent of its basic code. */
- if (!NILP (tem1))
- XSETFASTINT (val, XINT (tem1) | XINT (Fcar (Fcdr (tem))));
- }
- }
-
- /* If we don't have a character now, deal with it appropriately. */
- if (!INTEGERP (val))
- {
- if (error_nonascii)
- {
- Vunread_command_events = Fcons (val, Qnil);
- error ("Non-character input-event");
- }
- else
- goto retry;
- }
- }
-
- if (! NILP (delayed_switch_frame))
- unread_switch_frame = delayed_switch_frame;
-
- return val;
-#endif
-}
-
-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.\n\
-If the user generates an event which is not a character (i.e. a mouse\n\
-click or function key event), `read-char' signals an error. As an\n\
-exception, switch-frame events are put off until non-ASCII events can\n\
-be read.\n\
-If you want to read non-character events, or ignore them, call\n\
-`read-event' or `read-char-exclusive' instead.")
- ()
-{
- return read_filtered_event (1, 1, 1);
-}
-
-DEFUN ("read-event", Fread_event, Sread_event, 0, 0, 0,
- "Read an event object from the input stream.")
- ()
-{
- return read_filtered_event (0, 0, 0);
-}
-
-DEFUN ("read-char-exclusive", Fread_char_exclusive, Sread_char_exclusive, 0, 0, 0,
- "Read a character from the command input (keyboard or macro).\n\
-It is returned as a number. Non-character events are ignored.")
- ()
-{
- return read_filtered_event (1, 1, 0);
-}
-
-DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0,
- "Don't use this yourself.")
- ()
-{
- register Lisp_Object val;
- XSETINT (val, getc (instream));
- return val;
-}
-
-static void readevalloop ();
-static Lisp_Object load_unwind ();
-static Lisp_Object load_descriptor_unwind ();
-
-DEFUN ("load", Fload, Sload, 1, 4, 0,
- "Execute a file of Lisp code named FILE.\n\
-First try FILE with `.elc' appended, then try with `.el',\n\
- then try FILE unmodified.\n\
-This function searches the 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.")
- (file, noerror, nomessage, nosuffix)
- Lisp_Object file, noerror, nomessage, nosuffix;
-{
- register FILE *stream;
- register int fd = -1;
- register Lisp_Object lispstream;
- int count = specpdl_ptr - specpdl;
- Lisp_Object temp;
- struct gcpro gcpro1;
- Lisp_Object found;
- /* 1 means we printed the ".el is newer" message. */
- int newer = 0;
- /* 1 means we are loading a compiled file. */
- int compiled = 0;
- Lisp_Object handler;
-#ifdef DOS_NT
- char *dosmode = "rt";
-#endif /* DOS_NT */
-
- CHECK_STRING (file, 0);
-
- /* If file name is magic, call the handler. */
- handler = Ffind_file_name_handler (file, Qload);
- if (!NILP (handler))
- return call5 (handler, Qload, file, noerror, nomessage, nosuffix);
-
- /* Do this after the handler to avoid
- the need to gcpro noerror, nomessage and nosuffix.
- (Below here, we care only whether they are nil or not.) */
- file = Fsubstitute_in_file_name (file);
-
- /* Avoid weird lossage with null string as arg,
- since it would try to load a directory as a Lisp file */
- if (XSTRING (file)->size > 0)
- {
- GCPRO1 (file);
- fd = openp (Vload_path, file, !NILP (nosuffix) ? "" : ".elc:.el:",
- &found, 0);
- UNGCPRO;
- }
-
- if (fd < 0)
- {
- if (NILP (noerror))
- while (1)
- Fsignal (Qfile_error, Fcons (build_string ("Cannot open load file"),
- Fcons (file, Qnil)));
- else
- return Qnil;
- }
-
- if (!bcmp (&(XSTRING (found)->data[XSTRING (found)->size - 4]),
- ".elc", 4))
- {
- struct stat s1, s2;
- int result;
-
- compiled = 1;
-
-#ifdef DOS_NT
- dosmode = "rb";
-#endif /* DOS_NT */
- stat ((char *)XSTRING (found)->data, &s1);
- XSTRING (found)->data[XSTRING (found)->size - 1] = 0;
- result = stat ((char *)XSTRING (found)->data, &s2);
- if (result >= 0 && (unsigned) s1.st_mtime < (unsigned) s2.st_mtime)
- {
- /* Make the progress messages mention that source is newer. */
- newer = 1;
-
- /* If we won't print another message, mention this anyway. */
- if (! NILP (nomessage))
- message ("Source file `%s' newer than byte-compiled file",
- XSTRING (found)->data);
- }
- XSTRING (found)->data[XSTRING (found)->size - 1] = 'c';
- }
-
-#ifdef DOS_NT
- close (fd);
- stream = fopen ((char *) XSTRING (found)->data, dosmode);
-#else /* not DOS_NT */
- stream = fdopen (fd, "r");
-#endif /* not DOS_NT */
- if (stream == 0)
- {
- close (fd);
- error ("Failure to create stdio stream for %s", XSTRING (file)->data);
- }
-
- if (NILP (nomessage))
- {
- if (newer)
- message ("Loading %s (compiled; note, source file is newer)...",
- XSTRING (file)->data);
- else if (compiled)
- message ("Loading %s (compiled)...", XSTRING (file)->data);
- else
- message ("Loading %s...", XSTRING (file)->data);
- }
-
- GCPRO1 (file);
- lispstream = Fcons (Qnil, Qnil);
- XSETFASTINT (XCONS (lispstream)->car, (EMACS_UINT)stream >> 16);
- XSETFASTINT (XCONS (lispstream)->cdr, (EMACS_UINT)stream & 0xffff);
- record_unwind_protect (load_unwind, lispstream);
- record_unwind_protect (load_descriptor_unwind, load_descriptor_list);
- specbind (Qload_file_name, found);
- load_descriptor_list
- = Fcons (make_number (fileno (stream)), load_descriptor_list);
- load_in_progress++;
- readevalloop (Qget_file_char, stream, file, Feval, 0);
- unbind_to (count, Qnil);
-
- /* Run any load-hooks for this file. */
- temp = Fassoc (file, Vafter_load_alist);
- if (!NILP (temp))
- Fprogn (Fcdr (temp));
- UNGCPRO;
-
- if (saved_doc_string)
- free (saved_doc_string);
- saved_doc_string = 0;
- saved_doc_string_size = 0;
-
- if (!noninteractive && NILP (nomessage))
- {
- if (newer)
- message ("Loading %s (compiled; note, source file is newer)...done",
- XSTRING (file)->data);
- else if (compiled)
- message ("Loading %s (compiled)...done", XSTRING (file)->data);
- else
- message ("Loading %s...done", XSTRING (file)->data);
- }
- return Qt;
-}
-
-static Lisp_Object
-load_unwind (stream) /* used as unwind-protect function in load */
- Lisp_Object stream;
-{
- fclose ((FILE *) (XFASTINT (XCONS (stream)->car) << 16
- | XFASTINT (XCONS (stream)->cdr)));
- if (--load_in_progress < 0) load_in_progress = 0;
- return Qnil;
-}
-
-static Lisp_Object
-load_descriptor_unwind (oldlist)
- Lisp_Object oldlist;
-{
- load_descriptor_list = oldlist;
- return Qnil;
-}
-
-/* Close all descriptors in use for Floads.
- This is used when starting a subprocess. */
-
-void
-close_load_descs ()
-{
-#ifndef WINDOWSNT
- Lisp_Object tail;
- for (tail = load_descriptor_list; !NILP (tail); tail = XCONS (tail)->cdr)
- close (XFASTINT (XCONS (tail)->car));
-#endif
-}
-
-static int
-complete_filename_p (pathname)
- Lisp_Object pathname;
-{
- register unsigned char *s = XSTRING (pathname)->data;
- return (IS_DIRECTORY_SEP (s[0])
- || (XSTRING (pathname)->size > 2
- && IS_DEVICE_SEP (s[1]) && IS_DIRECTORY_SEP (s[2]))
-#ifdef ALTOS
- || *s == '@'
-#endif
-#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;
- struct gcpro gcpro1;
-
- GCPRO1 (str);
- if (storeptr)
- *storeptr = Qnil;
-
- if (complete_filename_p (str))
- absolute = 1;
-
- for (; !NILP (path); path = Fcdr (path))
- {
- char *nsuffix;
-
- filename = Fexpand_file_name (str, Fcar (path));
- if (!complete_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 (!complete_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.
- If the directory starts with /:, remove that. */
- if (XSTRING (filename)->size > 2
- && XSTRING (filename)->data[0] == '/'
- && XSTRING (filename)->data[1] == ':')
- {
- strncpy (fn, XSTRING (filename)->data + 2,
- XSTRING (filename)->size - 2);
- fn[XSTRING (filename)->size - 2] = 0;
- }
- else
- {
- 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) == 0) ? 1 : -1;
- else
- fd = open (fn, O_RDONLY, 0);
-
- if (fd >= 0)
- {
- /* We succeeded; return this descriptor and filename. */
- if (storeptr)
- *storeptr = build_string (fn);
- UNGCPRO;
- return fd;
- }
- }
-
- /* Advance to next suffix. */
- if (esuffix == 0)
- break;
- nsuffix += lsuffix + 1;
- }
- if (absolute)
- break;
- }
-
- UNGCPRO;
- return -1;
-}
-
-
-/* Merge the list we've accumulated of globals from the current input source
- into the load_history variable. The details depend on whether
- the source has an associated file name or not. */
-
-static void
-build_load_history (stream, source)
- FILE *stream;
- Lisp_Object source;
-{
- register Lisp_Object tail, prev, newelt;
- register Lisp_Object tem, tem2;
- register int foundit, loading;
-
- /* Don't bother recording anything for preloaded files. */
- if (!NILP (Vpurify_flag))
- return;
-
- loading = stream || !NARROWED;
-
- tail = Vload_history;
- prev = Qnil;
- foundit = 0;
- while (!NILP (tail))
- {
- tem = Fcar (tail);
-
- /* Find the feature's previous assoc list... */
- if (!NILP (Fequal (source, Fcar (tem))))
- {
- foundit = 1;
-
- /* If we're loading, remove it. */
- if (loading)
- {
- if (NILP (prev))
- Vload_history = Fcdr (tail);
- else
- Fsetcdr (prev, Fcdr (tail));
- }
-
- /* Otherwise, cons on new symbols that are not already members. */
- else
- {
- tem2 = Vcurrent_load_list;
-
- while (CONSP (tem2))
- {
- newelt = Fcar (tem2);
-
- if (NILP (Fmemq (newelt, tem)))
- Fsetcar (tail, Fcons (Fcar (tem),
- Fcons (newelt, Fcdr (tem))));
-
- tem2 = Fcdr (tem2);
- QUIT;
- }
- }
- }
- else
- prev = tail;
- tail = Fcdr (tail);
- QUIT;
- }
-
- /* If we're loading, cons the new assoc onto the front of load-history,
- the most-recently-loaded position. Also do this if we didn't find
- an existing member for the current source. */
- if (loading || !foundit)
- Vload_history = Fcons (Fnreverse (Vcurrent_load_list),
- Vload_history);
-}
-
-Lisp_Object
-unreadpure () /* Used as unwind-protect function in readevalloop */
-{
- read_pure = 0;
- return Qnil;
-}
-
-static void
-readevalloop (readcharfun, stream, sourcename, evalfun, printflag)
- Lisp_Object readcharfun;
- FILE *stream;
- Lisp_Object sourcename;
- Lisp_Object (*evalfun) ();
- int printflag;
-{
- register int c;
- register Lisp_Object val;
- int count = specpdl_ptr - specpdl;
- struct gcpro gcpro1;
- struct buffer *b = 0;
-
- if (BUFFERP (readcharfun))
- b = XBUFFER (readcharfun);
- else if (MARKERP (readcharfun))
- b = XMARKER (readcharfun)->buffer;
-
- specbind (Qstandard_input, readcharfun);
- specbind (Qcurrent_load_list, Qnil);
-
- GCPRO1 (sourcename);
-
- LOADHIST_ATTACH (sourcename);
-
- while (1)
- {
- if (b != 0 && NILP (b->name))
- error ("Reading from killed buffer");
-
- instream = stream;
- c = READCHAR;
- if (c == ';')
- {
- while ((c = READCHAR) != '\n' && c != -1);
- continue;
- }
- if (c < 0) break;
-
- /* Ignore whitespace here, so we can detect eof. */
- if (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r')
- continue;
-
- if (!NILP (Vpurify_flag) && c == '(')
- {
- int count1 = specpdl_ptr - specpdl;
- record_unwind_protect (unreadpure, Qnil);
- val = read_list (-1, readcharfun);
- unbind_to (count1, Qnil);
- }
- else
- {
- UNREAD (c);
- read_objects = Qnil;
- if (NILP (Vload_read_function))
- val = read0 (readcharfun);
- else
- val = call1 (Vload_read_function, readcharfun);
- }
-
- val = (*evalfun) (val);
- if (printflag)
- {
- Vvalues = Fcons (val, Vvalues);
- if (EQ (Vstandard_output, Qt))
- Fprin1 (val, Qnil);
- else
- Fprint (val, Qnil);
- }
- }
-
- build_load_history (stream, sourcename);
- UNGCPRO;
-
- unbind_to (count, Qnil);
-}
-
-#ifndef standalone
-
-DEFUN ("eval-buffer", Feval_buffer, Seval_buffer, 0, 2, "",
- "Execute the current buffer as Lisp code.\n\
-Programs can pass two arguments, BUFFER and PRINTFLAG.\n\
-BUFFER is the buffer to evaluate (nil means use current buffer).\n\
-PRINTFLAG controls printing of output:\n\
-nil means discard it; anything else is stream for print.\n\
-\n\
-If there is no error, point does not move. If there is an error,\n\
-point remains at the end of the last character read from the buffer.")
- (buffer, printflag)
- Lisp_Object buffer, printflag;
-{
- int count = specpdl_ptr - specpdl;
- Lisp_Object tem, buf;
-
- if (NILP (buffer))
- buf = Fcurrent_buffer ();
- else
- buf = Fget_buffer (buffer);
- if (NILP (buf))
- error ("No such buffer.");
-
- if (NILP (printflag))
- tem = Qsymbolp;
- else
- tem = printflag;
- specbind (Qstandard_output, tem);
- record_unwind_protect (save_excursion_restore, save_excursion_save ());
- BUF_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf)));
- readevalloop (buf, 0, XBUFFER (buf)->filename, Feval, !NILP (printflag));
- unbind_to (count, Qnil);
-
- return Qnil;
-}
-
-#if 0
-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.\n\
-\n\
-If there is no error, point does not move. If there is an error,\n\
-point remains at the end of the last character read from the buffer.")
- (printflag)
- Lisp_Object printflag;
-{
- int count = specpdl_ptr - specpdl;
- Lisp_Object tem, cbuf;
-
- cbuf = Fcurrent_buffer ()
-
- if (NILP (printflag))
- tem = Qsymbolp;
- else
- tem = printflag;
- specbind (Qstandard_output, tem);
- record_unwind_protect (save_excursion_restore, save_excursion_save ());
- SET_PT (BEGV);
- readevalloop (cbuf, 0, XBUFFER (cbuf)->filename, Feval, !NILP (printflag));
- return unbind_to (count, Qnil);
-}
-#endif
-
-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 output:\n\
-nil means discard it; anything else is stream for printing it.\n\
-\n\
-If there is no error, point does not move. If there is an error,\n\
-point remains at the end of the last character read from the buffer.")
- (start, end, printflag)
- Lisp_Object start, end, printflag;
-{
- int count = specpdl_ptr - specpdl;
- Lisp_Object tem, cbuf;
-
- cbuf = Fcurrent_buffer ();
-
- if (NILP (printflag))
- tem = Qsymbolp;
- else
- tem = printflag;
- specbind (Qstandard_output, tem);
-
- if (NILP (printflag))
- record_unwind_protect (save_excursion_restore, save_excursion_save ());
- record_unwind_protect (save_restriction_restore, save_restriction_save ());
-
- /* This both uses start and checks its type. */
- Fgoto_char (start);
- Fnarrow_to_region (make_number (BEGV), end);
- readevalloop (cbuf, 0, XBUFFER (cbuf)->filename, Feval, !NILP (printflag));
-
- return unbind_to (count, 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 the value of `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\
- call it with a char as argument to push a char back)\n\
- a string (takes text from string, starting at the beginning)\n\
- t (read text line using minibuffer and use it).")
- (stream)
- Lisp_Object stream;
-{
- extern Lisp_Object Fread_minibuffer ();
-
- if (NILP (stream))
- stream = Vstandard_input;
- if (EQ (stream, Qt))
- stream = Qread_char;
-
- new_backquote_flag = 0;
- read_objects = Qnil;
-
-#ifndef standalone
- if (EQ (stream, Qread_char))
- return Fread_minibuffer (build_string ("Lisp expression: "), Qnil);
-#endif
-
- if (STRINGP (stream))
- return Fcar (Fread_from_string (stream, Qnil, Qnil));
-
- return read0 (stream);
-}
-
-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 (NILP (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 (NILP (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;
-
- new_backquote_flag = 0;
- read_objects = Qnil;
-
- 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, &c, 0);
- if (c)
- Fsignal (Qinvalid_read_syntax, Fcons (make_string (&c, 1), Qnil));
-
- return val;
-}
-
-static int read_buffer_size;
-static char *read_buffer;
-
-static int
-read_escape (readcharfun)
- Lisp_Object readcharfun;
-{
- register int c = READCHAR;
- switch (c)
- {
- case -1:
- error ("End of file");
-
- case 'a':
- return '\007';
- case 'b':
- return '\b';
- case 'd':
- return 0177;
- 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 | meta_modifier;
-
- case 'S':
- c = READCHAR;
- if (c != '-')
- error ("Invalid escape character syntax");
- c = READCHAR;
- if (c == '\\')
- c = read_escape (readcharfun);
- return c | shift_modifier;
-
- case 'H':
- c = READCHAR;
- if (c != '-')
- error ("Invalid escape character syntax");
- c = READCHAR;
- if (c == '\\')
- c = read_escape (readcharfun);
- return c | hyper_modifier;
-
- case 'A':
- c = READCHAR;
- if (c != '-')
- error ("Invalid escape character syntax");
- c = READCHAR;
- if (c == '\\')
- c = read_escape (readcharfun);
- return c | alt_modifier;
-
- case 's':
- c = READCHAR;
- if (c != '-')
- error ("Invalid escape character syntax");
- c = READCHAR;
- if (c == '\\')
- c = read_escape (readcharfun);
- return c | super_modifier;
-
- case 'C':
- c = READCHAR;
- if (c != '-')
- error ("Invalid escape character syntax");
- case '^':
- c = READCHAR;
- if (c == '\\')
- c = read_escape (readcharfun);
- if ((c & 0177) == '?')
- return 0177 | c;
- /* ASCII control chars are made from letters (both cases),
- as well as the non-letters within 0100...0137. */
- else if ((c & 0137) >= 0101 && (c & 0137) <= 0132)
- return (c & (037 | ~0177));
- else if ((c & 0177) >= 0100 && (c & 0177) <= 0137)
- return (c & (037 | ~0177));
- else
- return c | ctrl_modifier;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- /* An octal escape, as in ANSI C. */
- {
- 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;
- }
-
- case 'x':
- /* A hex escape, as in ANSI C. */
- {
- int i = 0;
- while (1)
- {
- c = READCHAR;
- if (c >= '0' && c <= '9')
- {
- i *= 16;
- i += c - '0';
- }
- else if ((c >= 'a' && c <= 'f')
- || (c >= 'A' && c <= 'F'))
- {
- i *= 16;
- if (c >= 'a' && c <= 'f')
- i += c - 'a' + 10;
- else
- i += c - 'A' + 10;
- }
- else
- {
- UNREAD (c);
- break;
- }
- }
- return i;
- }
-
- default:
- return c;
- }
-}
-
-/* If the next token is ')' or ']' or '.', we store that character
- in *PCH and the return value is not interesting. Else, we store
- zero in *PCH and we read and return one lisp object.
-
- FIRST_IN_LIST is nonzero if this is the first element of a list. */
-
-static Lisp_Object
-read1 (readcharfun, pch, first_in_list)
- register Lisp_Object readcharfun;
- char *pch;
- int first_in_list;
-{
- register int c;
- int uninterned_symbol = 0;
-
- *pch = 0;
-
- 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 ']':
- {
- *pch = c;
- return Qnil;
- }
-
- case '#':
- c = READCHAR;
- if (c == '^')
- {
- c = READCHAR;
- if (c == '[')
- {
- Lisp_Object tmp;
- tmp = read_vector (readcharfun);
- if (XVECTOR (tmp)->size < CHAR_TABLE_STANDARD_SLOTS
- || XVECTOR (tmp)->size > CHAR_TABLE_STANDARD_SLOTS + 10)
- error ("Invalid size char-table");
- XSETCHAR_TABLE (tmp, XCHAR_TABLE (tmp));
- return tmp;
- }
- Fsignal (Qinvalid_read_syntax, Fcons (make_string ("#^", 2), Qnil));
- }
- if (c == '&')
- {
- Lisp_Object length;
- length = read1 (readcharfun, pch, first_in_list);
- c = READCHAR;
- if (c == '"')
- {
- Lisp_Object tmp, val;
- int size_in_chars = ((XFASTINT (length) + BITS_PER_CHAR)
- / BITS_PER_CHAR);
-
- UNREAD (c);
- tmp = read1 (readcharfun, pch, first_in_list);
- if (size_in_chars != XSTRING (tmp)->size)
- Fsignal (Qinvalid_read_syntax,
- Fcons (make_string ("#&", 2), Qnil));
-
- val = Fmake_bool_vector (length, Qnil);
- bcopy (XSTRING (tmp)->data, XBOOL_VECTOR (val)->data,
- size_in_chars);
- return val;
- }
- Fsignal (Qinvalid_read_syntax, Fcons (make_string ("#&", 2), Qnil));
- }
- if (c == '[')
- {
- /* Accept compiled functions at read-time so that we don't have to
- build them using function calls. */
- Lisp_Object tmp;
- tmp = read_vector (readcharfun);
- return Fmake_byte_code (XVECTOR (tmp)->size,
- XVECTOR (tmp)->contents);
- }
-#ifdef USE_TEXT_PROPERTIES
- if (c == '(')
- {
- Lisp_Object tmp;
- struct gcpro gcpro1;
- char ch;
-
- /* Read the string itself. */
- tmp = read1 (readcharfun, &ch, 0);
- if (ch != 0 || !STRINGP (tmp))
- Fsignal (Qinvalid_read_syntax, Fcons (make_string ("#", 1), Qnil));
- GCPRO1 (tmp);
- /* Read the intervals and their properties. */
- while (1)
- {
- Lisp_Object beg, end, plist;
-
- beg = read1 (readcharfun, &ch, 0);
- if (ch == ')')
- break;
- if (ch == 0)
- end = read1 (readcharfun, &ch, 0);
- if (ch == 0)
- plist = read1 (readcharfun, &ch, 0);
- if (ch)
- Fsignal (Qinvalid_read_syntax,
- Fcons (build_string ("invalid string property list"),
- Qnil));
- Fset_text_properties (beg, end, plist, tmp);
- }
- UNGCPRO;
- return tmp;
- }
-#endif
- /* #@NUMBER is used to skip NUMBER following characters.
- That's used in .elc files to skip over doc strings
- and function definitions. */
- if (c == '@')
- {
- int i, nskip = 0;
-
- /* Read a decimal integer. */
- while ((c = READCHAR) >= 0
- && c >= '0' && c <= '9')
- {
- nskip *= 10;
- nskip += c - '0';
- }
- if (c >= 0)
- UNREAD (c);
-
-#ifndef DOS_NT /* I don't know if filepos works right on MSDOS and Windoze. */
- if (load_force_doc_strings && EQ (readcharfun, Qget_file_char))
- {
- /* If we are supposed to force doc strings into core right now,
- record the last string that we skipped,
- and record where in the file it comes from. */
- if (saved_doc_string_size == 0)
- {
- saved_doc_string_size = nskip + 100;
- saved_doc_string = (char *) xmalloc (saved_doc_string_size);
- }
- if (nskip > saved_doc_string_size)
- {
- saved_doc_string_size = nskip + 100;
- saved_doc_string = (char *) xrealloc (saved_doc_string,
- saved_doc_string_size);
- }
-
- saved_doc_string_position = ftell (instream);
-
- /* Copy that many characters into saved_doc_string. */
- for (i = 0; i < nskip && c >= 0; i++)
- saved_doc_string[i] = c = READCHAR;
-
- saved_doc_string_length = i;
- }
- else
-#endif /* not DOS_NT */
- {
- /* Skip that many characters. */
- for (i = 0; i < nskip && c >= 0; i++)
- c = READCHAR;
- }
- goto retry;
- }
- if (c == '$')
- return Vload_file_name;
- if (c == '\'')
- return Fcons (Qfunction, Fcons (read0 (readcharfun), Qnil));
- /* #:foo is the uninterned symbol named foo. */
- if (c == ':')
- {
- uninterned_symbol = 1;
- c = READCHAR;
- goto default_label;
- }
- /* Reader forms that can reuse previously read objects. */
- if (c >= '0' && c <= '9')
- {
- int n = 0;
- Lisp_Object tem;
-
- /* Read a non-negative integer. */
- while (c >= '0' && c <= '9')
- {
- n *= 10;
- n += c - '0';
- c = READCHAR;
- }
- /* #n=object returns object, but associates it with n for #n#. */
- if (c == '=')
- {
- tem = read0 (readcharfun);
- read_objects = Fcons (Fcons (make_number (n), tem), read_objects);
- return tem;
- }
- /* #n# returns a previously read object. */
- if (c == '#')
- {
- tem = Fassq (make_number (n), read_objects);
- if (CONSP (tem))
- return XCDR (tem);
- /* Fall through to error message. */
- }
- /* Fall through to error message. */
- }
-
- UNREAD (c);
- 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 '`':
- if (first_in_list)
- goto default_label;
- else
- {
- Lisp_Object value;
-
- new_backquote_flag = 1;
- value = read0 (readcharfun);
- new_backquote_flag = 0;
-
- return Fcons (Qbackquote, Fcons (value, Qnil));
- }
-
- case ',':
- if (new_backquote_flag)
- {
- Lisp_Object comma_type = Qnil;
- Lisp_Object value;
- int ch = READCHAR;
-
- if (ch == '@')
- comma_type = Qcomma_at;
- else if (ch == '.')
- comma_type = Qcomma_dot;
- else
- {
- if (ch >= 0) UNREAD (ch);
- comma_type = Qcomma;
- }
-
- new_backquote_flag = 0;
- value = read0 (readcharfun);
- new_backquote_flag = 1;
- return Fcons (comma_type, Fcons (value, Qnil));
- }
- else
- goto default_label;
-
- case '?':
- {
- register Lisp_Object val;
-
- c = READCHAR;
- if (c < 0) return Fsignal (Qend_of_file, Qnil);
-
- if (c == '\\')
- XSETINT (val, read_escape (readcharfun));
- else
- XSETINT (val, c);
-
- 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 != '\"')
- {
- 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 == -1)
- {
- if (p == read_buffer)
- cancel = 1;
- }
- else
- {
- /* Allow `\C- ' and `\C-?'. */
- if (c == (CHAR_CTL | ' '))
- c = 0;
- else if (c == (CHAR_CTL | '?'))
- c = 127;
-
- if (c & CHAR_META)
- /* Move the meta bit to the right place for a string. */
- c = (c & ~CHAR_META) | 0x80;
- if (c & ~0xff)
- error ("Invalid modifier in string");
- *p++ = c;
- }
- }
- if (c < 0) return Fsignal (Qend_of_file, Qnil);
-
- /* 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 (!NILP (Vpurify_flag) && NILP (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);
- }
-
- case '.':
- {
-#ifdef LISP_FLOAT_TYPE
- /* If a period is followed by a number, then we should read it
- as a floating point number. Otherwise, it denotes a dotted
- pair. */
- int next_char = READCHAR;
- UNREAD (next_char);
-
- if (! (next_char >= '0' && next_char <= '9'))
-#endif
- {
- *pch = c;
- return Qnil;
- }
-
- /* Otherwise, we fall through! Note that the atom-reading loop
- below will now loop at least once, assuring that we will not
- try to UNREAD two characters in a row. */
- }
- default:
- default_label:
- if (c <= 040) goto retry;
- {
- register char *p = read_buffer;
- int quoted = 0;
-
- {
- register char *end = read_buffer + read_buffer_size;
-
- while (c > 040 &&
- !(c == '\"' || c == '\'' || c == ';' || c == '?'
- || c == '(' || c == ')'
-#ifndef LISP_FLOAT_TYPE
- /* If we have floating-point support, then we need
- to allow <digits><dot><digits>. */
- || c =='.'
-#endif /* not LISP_FLOAT_TYPE */
- || 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 == '\\')
- {
- c = READCHAR;
- quoted = 1;
- }
- *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;
- if (c >= 0)
- UNREAD (c);
- }
-
- if (!quoted && !uninterned_symbol)
- {
- register char *p1;
- register Lisp_Object val;
- p1 = read_buffer;
- if (*p1 == '+' || *p1 == '-') p1++;
- /* Is it an integer? */
- if (p1 != p)
- {
- while (p1 != p && (c = *p1) >= '0' && c <= '9') p1++;
-#ifdef LISP_FLOAT_TYPE
- /* Integers can have trailing decimal points. */
- if (p1 > read_buffer && p1 < p && *p1 == '.') p1++;
-#endif
- if (p1 == p)
- /* It is an integer. */
- {
-#ifdef LISP_FLOAT_TYPE
- if (p1[-1] == '.')
- p1[-1] = '\0';
-#endif
- if (sizeof (int) == sizeof (EMACS_INT))
- XSETINT (val, atoi (read_buffer));
- else if (sizeof (long) == sizeof (EMACS_INT))
- XSETINT (val, atol (read_buffer));
- else
- abort ();
- return val;
- }
- }
-#ifdef LISP_FLOAT_TYPE
- if (isfloat_string (read_buffer))
- return make_float (atof (read_buffer));
-#endif
- }
-
- if (uninterned_symbol)
- return make_symbol (read_buffer);
- else
- return intern (read_buffer);
- }
- }
-}
-
-#ifdef LISP_FLOAT_TYPE
-
-#define LEAD_INT 1
-#define DOT_CHAR 2
-#define TRAIL_INT 4
-#define E_CHAR 8
-#define EXP_INT 16
-
-int
-isfloat_string (cp)
- register char *cp;
-{
- register state;
-
- state = 0;
- if (*cp == '+' || *cp == '-')
- cp++;
-
- if (*cp >= '0' && *cp <= '9')
- {
- state |= LEAD_INT;
- while (*cp >= '0' && *cp <= '9')
- cp++;
- }
- if (*cp == '.')
- {
- state |= DOT_CHAR;
- cp++;
- }
- if (*cp >= '0' && *cp <= '9')
- {
- state |= TRAIL_INT;
- while (*cp >= '0' && *cp <= '9')
- cp++;
- }
- if (*cp == 'e' || *cp == 'E')
- {
- state |= E_CHAR;
- cp++;
- if (*cp == '+' || *cp == '-')
- cp++;
- }
-
- if (*cp >= '0' && *cp <= '9')
- {
- state |= EXP_INT;
- while (*cp >= '0' && *cp <= '9')
- cp++;
- }
- return (((*cp == 0) || (*cp == ' ') || (*cp == '\t') || (*cp == '\n') || (*cp == '\r') || (*cp == '\f'))
- && (state == (LEAD_INT|DOT_CHAR|TRAIL_INT)
- || state == (DOT_CHAR|TRAIL_INT)
- || state == (LEAD_INT|E_CHAR|EXP_INT)
- || state == (LEAD_INT|DOT_CHAR|TRAIL_INT|E_CHAR|EXP_INT)
- || state == (DOT_CHAR|TRAIL_INT|E_CHAR|EXP_INT)));
-}
-#endif /* LISP_FLOAT_TYPE */
-
-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;
- /* 0 is the normal case.
- 1 means this list is a doc reference; replace it with the number 0.
- 2 means this list is a doc reference; replace it with the doc string. */
- int doc_reference = 0;
-
- /* Initialize this to 1 if we are reading a list. */
- int first_in_list = flag <= 0;
-
- val = Qnil;
- tail = Qnil;
-
- while (1)
- {
- char ch;
- GCPRO2 (val, tail);
- elt = read1 (readcharfun, &ch, first_in_list);
- UNGCPRO;
-
- first_in_list = 0;
-
- /* While building, if the list starts with #$, treat it specially. */
- if (EQ (elt, Vload_file_name)
- && !NILP (Vpurify_flag))
- {
- if (NILP (Vdoc_file_name))
- /* We have not yet called Snarf-documentation, so assume
- this file is described in the DOC-MM.NN file
- and Snarf-documentation will fill in the right value later.
- For now, replace the whole list with 0. */
- doc_reference = 1;
- else
- /* We have already called Snarf-documentation, so make a relative
- file name for this file, so it can be found properly
- in the installed Lisp directory.
- We don't use Fexpand_file_name because that would make
- the directory absolute now. */
- elt = concat2 (build_string ("../lisp/"),
- Ffile_name_nondirectory (elt));
- }
- else if (EQ (elt, Vload_file_name)
- && load_force_doc_strings)
- doc_reference = 2;
-
- if (ch)
- {
- if (flag > 0)
- {
- if (ch == ']')
- return val;
- Fsignal (Qinvalid_read_syntax,
- Fcons (make_string (") or . in a vector", 18), Qnil));
- }
- if (ch == ')')
- return val;
- if (ch == '.')
- {
- GCPRO2 (val, tail);
- if (!NILP (tail))
- XCONS (tail)->cdr = read0 (readcharfun);
- else
- val = read0 (readcharfun);
- read1 (readcharfun, &ch, 0);
- UNGCPRO;
- if (ch == ')')
- {
- if (doc_reference == 1)
- return make_number (0);
- if (doc_reference == 2)
- {
- /* Get a doc string from the file we are loading.
- If it's in saved_doc_string, get it from there. */
- int pos = XINT (XCONS (val)->cdr);
- if (pos >= saved_doc_string_position
- && pos < (saved_doc_string_position
- + saved_doc_string_length))
- {
- int start = pos - saved_doc_string_position;
- int from, to;
-
- /* Process quoting with ^A,
- and find the end of the string,
- which is marked with ^_ (037). */
- for (from = start, to = start;
- saved_doc_string[from] != 037;)
- {
- int c = saved_doc_string[from++];
- if (c == 1)
- {
- c = saved_doc_string[from++];
- if (c == 1)
- saved_doc_string[to++] = c;
- else if (c == '0')
- saved_doc_string[to++] = 0;
- else if (c == '_')
- saved_doc_string[to++] = 037;
- }
- else
- saved_doc_string[to++] = c;
- }
-
- return make_string (saved_doc_string + start,
- to - start);
- }
- else
- return read_doc_string (val);
- }
-
- 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 (!NILP (tail))
- XCONS (tail)->cdr = tem;
- else
- val = tem;
- tail = tem;
- if (defunflag < 0)
- defunflag = EQ (elt, Qdefun);
- else if (defunflag > 0)
- read_pure = 1;
- }
-}
-
-Lisp_Object Vobarray;
-Lisp_Object initial_obarray;
-
-/* oblookup stores the bucket number here, for the sake of Funintern. */
-
-int oblookup_last_bucket_number;
-
-static int hash_string ();
-Lisp_Object oblookup ();
-
-/* Get an error if OBARRAY is not an obarray.
- If it is one, return it. */
-
-Lisp_Object
-check_obarray (obarray)
- Lisp_Object obarray;
-{
- while (!VECTORP (obarray) || 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;
-}
-
-/* Intern the C string STR: return a symbol with that name,
- interned in the current obarray. */
-
-Lisp_Object
-intern (str)
- char *str;
-{
- Lisp_Object tem;
- int len = strlen (str);
- Lisp_Object obarray;
-
- obarray = Vobarray;
- if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
- obarray = check_obarray (obarray);
- tem = oblookup (obarray, str, len);
- if (SYMBOLP (tem))
- return tem;
- return Fintern ((!NILP (Vpurify_flag)
- ? make_pure_string (str, len)
- : make_string (str, len)),
- obarray);
-}
-
-/* Create an uninterned symbol with name STR. */
-
-Lisp_Object
-make_symbol (str)
- char *str;
-{
- int len = strlen (str);
-
- return Fmake_symbol ((!NILP (Vpurify_flag)
- ? make_pure_string (str, len)
- : make_string (str, len)));
-}
-
-DEFUN ("intern", Fintern, Sintern, 1, 2, 0,
- "Return the canonical symbol whose name is STRING.\n\
-If there is none, one is created by this function and returned.\n\
-A second optional argument specifies the obarray to use;\n\
-it defaults to the value of `obarray'.")
- (string, obarray)
- Lisp_Object string, obarray;
-{
- register Lisp_Object tem, sym, *ptr;
-
- if (NILP (obarray)) obarray = Vobarray;
- obarray = check_obarray (obarray);
-
- CHECK_STRING (string, 0);
-
- tem = oblookup (obarray, XSTRING (string)->data, XSTRING (string)->size);
- if (!INTEGERP (tem))
- return tem;
-
- if (!NILP (Vpurify_flag))
- string = Fpurecopy (string);
- sym = Fmake_symbol (string);
- XSYMBOL (sym)->obarray = obarray;
-
- ptr = &XVECTOR (obarray)->contents[XINT (tem)];
- if (SYMBOLP (*ptr))
- 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 canonical symbol whose name is STRING, or nil if none exists.\n\
-A second optional argument specifies the obarray to use;\n\
-it defaults to the value of `obarray'.")
- (string, obarray)
- Lisp_Object string, obarray;
-{
- register Lisp_Object tem;
-
- if (NILP (obarray)) obarray = Vobarray;
- obarray = check_obarray (obarray);
-
- CHECK_STRING (string, 0);
-
- tem = oblookup (obarray, XSTRING (string)->data, XSTRING (string)->size);
- if (!INTEGERP (tem))
- return tem;
- return Qnil;
-}
-
-DEFUN ("unintern", Funintern, Sunintern, 1, 2, 0,
- "Delete the symbol named NAME, if any, from OBARRAY.\n\
-The value is t if a symbol was found and deleted, nil otherwise.\n\
-NAME may be a string or a symbol. If it is a symbol, that symbol\n\
-is deleted, if it belongs to OBARRAY--no other symbol is deleted.\n\
-OBARRAY defaults to the value of the variable `obarray'.")
- (name, obarray)
- Lisp_Object name, obarray;
-{
- register Lisp_Object string, tem;
- int hash;
-
- if (NILP (obarray)) obarray = Vobarray;
- obarray = check_obarray (obarray);
-
- if (SYMBOLP (name))
- XSETSTRING (string, XSYMBOL (name)->name);
- else
- {
- CHECK_STRING (name, 0);
- string = name;
- }
-
- tem = oblookup (obarray, XSTRING (string)->data, XSTRING (string)->size);
- if (INTEGERP (tem))
- return Qnil;
- /* If arg was a symbol, don't delete anything but that symbol itself. */
- if (SYMBOLP (name) && !EQ (name, tem))
- return Qnil;
-
- hash = oblookup_last_bucket_number;
-
- if (EQ (XVECTOR (obarray)->contents[hash], tem))
- {
- if (XSYMBOL (tem)->next)
- XSETSYMBOL (XVECTOR (obarray)->contents[hash], XSYMBOL (tem)->next);
- else
- XSETINT (XVECTOR (obarray)->contents[hash], 0);
- }
- else
- {
- Lisp_Object tail, following;
-
- for (tail = XVECTOR (obarray)->contents[hash];
- XSYMBOL (tail)->next;
- tail = following)
- {
- XSETSYMBOL (following, XSYMBOL (tail)->next);
- if (EQ (following, tem))
- {
- XSYMBOL (tail)->next = XSYMBOL (following)->next;
- break;
- }
- }
- }
-
- return Qt;
-}
-
-/* Return the symbol in OBARRAY whose names matches the string
- of SIZE characters at PTR. If there is no such symbol in OBARRAY,
- return nil.
-
- Also store the bucket number in oblookup_last_bucket_number. */
-
-Lisp_Object
-oblookup (obarray, ptr, size)
- Lisp_Object obarray;
- register char *ptr;
- register int size;
-{
- int hash;
- int obsize;
- register Lisp_Object tail;
- Lisp_Object bucket, tem;
-
- if (!VECTORP (obarray)
- || (obsize = XVECTOR (obarray)->size) == 0)
- {
- obarray = check_obarray (obarray);
- obsize = XVECTOR (obarray)->size;
- }
- /* This is sometimes needed in the middle of GC. */
- obsize &= ~ARRAY_MARK_FLAG;
- /* Combining next two lines breaks VMS C 2.3. */
- hash = hash_string (ptr, size);
- hash %= obsize;
- bucket = XVECTOR (obarray)->contents[hash];
- oblookup_last_bucket_number = hash;
- if (XFASTINT (bucket) == 0)
- ;
- else if (!SYMBOLP (bucket))
- error ("Bad data in guts of obarray"); /* Like CADR error message */
- else
- for (tail = bucket; ; XSETSYMBOL (tail, 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;
- }
- XSETINT (tem, 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)
- while (1)
- {
- (*fn) (tail, arg);
- if (XSYMBOL (tail)->next == 0)
- break;
- XSETSYMBOL (tail, 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 (NILP (obarray)) obarray = Vobarray;
- obarray = check_obarray (obarray);
-
- map_obarray (obarray, mapatoms_1, function);
- return Qnil;
-}
-
-#define OBARRAY_SIZE 1511
-
-void
-init_obarray ()
-{
- Lisp_Object oblength;
- int hash;
- Lisp_Object *tem;
-
- XSETFASTINT (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 */
- XSYMBOL (Qnil)->obarray = Vobarray;
- /* 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");
- staticpro (&Qvariable_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);
- XSETSUBR (XSYMBOL (sym)->function, 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);
- XSETSUBR (XSYMBOL (sym)->function, sname);
-}
-#endif /* NOTDEF */
-
-/* Define an "integer variable"; a symbol whose value is forwarded
- to a C variable of type int. Sample call: */
- /* DEFVAR_INT ("indent-tabs-mode", &indent_tabs_mode, "Documentation"); */
-void
-defvar_int (namestring, address)
- char *namestring;
- int *address;
-{
- Lisp_Object sym, val;
- sym = intern (namestring);
- val = allocate_misc ();
- XMISCTYPE (val) = Lisp_Misc_Intfwd;
- XINTFWD (val)->intvar = address;
- XSYMBOL (sym)->value = val;
-}
-
-/* Similar but define a variable whose value is T if address contains 1,
- NIL if address contains 0 */
-void
-defvar_bool (namestring, address)
- char *namestring;
- int *address;
-{
- Lisp_Object sym, val;
- sym = intern (namestring);
- val = allocate_misc ();
- XMISCTYPE (val) = Lisp_Misc_Boolfwd;
- XBOOLFWD (val)->boolvar = address;
- XSYMBOL (sym)->value = val;
-}
-
-/* Similar but define a variable whose value is the Lisp Object stored
- at address. Two versions: with and without gc-marking of the C
- variable. The nopro version is 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)
- char *namestring;
- Lisp_Object *address;
-{
- Lisp_Object sym, val;
- sym = intern (namestring);
- val = allocate_misc ();
- XMISCTYPE (val) = Lisp_Misc_Objfwd;
- XOBJFWD (val)->objvar = address;
- XSYMBOL (sym)->value = val;
-}
-
-void
-defvar_lisp (namestring, address)
- char *namestring;
- Lisp_Object *address;
-{
- defvar_lisp_nopro (namestring, address);
- staticpro (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, type, doc)
- char *namestring;
- Lisp_Object *address;
- Lisp_Object type;
- char *doc;
-{
- Lisp_Object sym, val;
- int offset;
- extern struct buffer buffer_local_symbols;
-
- sym = intern (namestring);
- val = allocate_misc ();
- offset = (char *)address - (char *)current_buffer;
-
- XMISCTYPE (val) = Lisp_Misc_Buffer_Objfwd;
- XBUFFER_OBJFWD (val)->offset = offset;
- XSYMBOL (sym)->value = val;
- *(Lisp_Object *)(offset + (char *)&buffer_local_symbols) = sym;
- *(Lisp_Object *)(offset + (char *)&buffer_local_types) = type;
- if (XINT (*(Lisp_Object *)(offset + (char *)&buffer_local_flags)) == 0)
- /* Did a DEFVAR_PER_BUFFER without initializing the corresponding
- slot of buffer_local_flags */
- abort ();
-}
-
-#endif /* standalone */
-
-/* Similar but define a variable whose value is the Lisp Object stored
- at a particular offset in the current kboard object. */
-
-void
-defvar_kboard (namestring, offset)
- char *namestring;
- int offset;
-{
- Lisp_Object sym, val;
- sym = intern (namestring);
- val = allocate_misc ();
- XMISCTYPE (val) = Lisp_Misc_Kboard_Objfwd;
- XKBOARD_OBJFWD (val)->offset = offset;
- XSYMBOL (sym)->value = val;
-}
-
-/* Record the value of load-path used at the start of dumping
- so we can see if the site changed it later during dumping. */
-static Lisp_Object dump_path;
-
-init_lread ()
-{
- char *normal;
- int turn_off_warning = 0;
-
-#ifdef HAVE_SETLOCALE
- /* Make sure numbers are parsed as we expect. */
- setlocale (LC_NUMERIC, "C");
-#endif /* HAVE_SETLOCALE */
-
- /* Compute the default load-path. */
-#ifdef CANNOT_DUMP
- normal = PATH_LOADSEARCH;
- Vload_path = decode_env_path (0, normal);
-#else
- if (NILP (Vpurify_flag))
- normal = PATH_LOADSEARCH;
- else
- normal = PATH_DUMPLOADSEARCH;
-
- /* In a dumped Emacs, we normally have to reset the value of
- Vload_path from PATH_LOADSEARCH, since the value that was dumped
- uses ../lisp, instead of the path of the installed elisp
- libraries. However, if it appears that Vload_path was changed
- from the default before dumping, don't override that value. */
- if (initialized)
- {
- if (! NILP (Fequal (dump_path, Vload_path)))
- {
- Vload_path = decode_env_path (0, normal);
- if (!NILP (Vinstallation_directory))
- {
- /* Add to the path the lisp subdir of the
- installation dir, if it exists. */
- Lisp_Object tem, tem1;
- tem = Fexpand_file_name (build_string ("lisp"),
- Vinstallation_directory);
- tem1 = Ffile_exists_p (tem);
- if (!NILP (tem1))
- {
- if (NILP (Fmember (tem, Vload_path)))
- {
- turn_off_warning = 1;
- Vload_path = nconc2 (Vload_path, Fcons (tem, Qnil));
- }
- }
- else
- /* That dir doesn't exist, so add the build-time
- Lisp dirs instead. */
- Vload_path = nconc2 (Vload_path, dump_path);
-
- /* Add site-list under the installation dir, if it exists. */
- tem = Fexpand_file_name (build_string ("site-lisp"),
- Vinstallation_directory);
- tem1 = Ffile_exists_p (tem);
- if (!NILP (tem1))
- {
- if (NILP (Fmember (tem, Vload_path)))
- Vload_path = nconc2 (Vload_path, Fcons (tem, Qnil));
- }
- }
- }
- }
- else
- {
- /* ../lisp refers to the build directory.
- NORMAL refers to the lisp dir in the source directory. */
- Vload_path = Fcons (build_string ("../lisp"),
- decode_env_path (0, normal));
- dump_path = Vload_path;
- }
-#endif
-
-#ifndef WINDOWSNT
- /* When Emacs is invoked over network shares on NT, PATH_LOADSEARCH is
- almost never correct, thereby causing a warning to be printed out that
- confuses users. Since PATH_LOADSEARCH is always overridden by the
- EMACSLOADPATH environment variable below, disable the warning on NT. */
-
- /* Warn if dirs in the *standard* path don't exist. */
- if (!turn_off_warning)
- {
- Lisp_Object path_tail;
-
- for (path_tail = Vload_path;
- !NILP (path_tail);
- path_tail = XCONS (path_tail)->cdr)
- {
- Lisp_Object dirfile;
- dirfile = Fcar (path_tail);
- if (STRINGP (dirfile))
- {
- dirfile = Fdirectory_file_name (dirfile);
- if (access (XSTRING (dirfile)->data, 0) < 0)
- dir_warning ("Warning: Lisp directory `%s' does not exist.\n",
- XCONS (path_tail)->car);
- }
- }
- }
-#endif /* WINDOWSNT */
-
- /* If the EMACSLOADPATH environment variable is set, use its value.
- This doesn't apply if we're dumping. */
-#ifndef CANNOT_DUMP
- if (NILP (Vpurify_flag)
- && egetenv ("EMACSLOADPATH"))
-#endif
- Vload_path = decode_env_path ("EMACSLOADPATH", normal);
-
- Vvalues = Qnil;
-
- load_in_progress = 0;
- Vload_file_name = Qnil;
-
- load_descriptor_list = Qnil;
-}
-
-/* Print a warning, using format string FORMAT, that directory DIRNAME
- does not exist. Print it on stderr and put it in *Message*. */
-
-dir_warning (format, dirname)
- char *format;
- Lisp_Object dirname;
-{
- char *buffer
- = (char *) alloca (XSTRING (dirname)->size + strlen (format) + 5);
-
- fprintf (stderr, format, XSTRING (dirname)->data);
- sprintf (buffer, format, XSTRING (dirname)->data);
- message_dolog (buffer, strlen (buffer), 0);
-}
-
-void
-syms_of_lread ()
-{
- defsubr (&Sread);
- defsubr (&Sread_from_string);
- defsubr (&Sintern);
- defsubr (&Sintern_soft);
- defsubr (&Sunintern);
- defsubr (&Sload);
- defsubr (&Seval_buffer);
- defsubr (&Seval_region);
- defsubr (&Sread_char);
- defsubr (&Sread_char_exclusive);
- defsubr (&Sread_event);
- 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\
-The vector's contents don't make sense if examined from Lisp programs;\n\
-to find all the symbols in an obarray, use `mapatoms'.");
-
- 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 by file `paths.h' when Emacs was built.");
-
- DEFVAR_BOOL ("load-in-progress", &load_in_progress,
- "Non-nil iff inside of `load'.");
-
- DEFVAR_LISP ("after-load-alist", &Vafter_load_alist,
- "An alist of expressions to be evalled when particular files are loaded.\n\
-Each element looks like (FILENAME FORMS...).\n\
-When `load' is run and the file-name argument is FILENAME,\n\
-the FORMS in the corresponding element are executed at the end of loading.\n\n\
-FILENAME must match exactly! Normally FILENAME is the name of a library,\n\
-with no directory specified, since that is how `load' is normally called.\n\
-An error in FORMS does not undo the load,\n\
-but does prevent execution of the rest of the FORMS.");
- Vafter_load_alist = Qnil;
-
- DEFVAR_LISP ("load-history", &Vload_history,
- "Alist mapping source file names to symbols and features.\n\
-Each alist element is a list that starts with a file name,\n\
-except for one element (optional) that starts with nil and describes\n\
-definitions evaluated from buffers not visiting files.\n\
-The remaining elements of each list are symbols defined as functions\n\
-or variables, and cons cells `(provide . FEATURE)' and `(require . FEATURE)'.");
- Vload_history = Qnil;
-
- DEFVAR_LISP ("load-file-name", &Vload_file_name,
- "Full name of file being loaded by `load'.");
- Vload_file_name = Qnil;
-
- DEFVAR_LISP ("current-load-list", &Vcurrent_load_list,
- "Used for internal purposes by `load'.");
- Vcurrent_load_list = Qnil;
-
- DEFVAR_LISP ("load-read-function", &Vload_read_function,
- "Function used by `load' and `eval-region' for reading expressions.\n\
-The default is nil, which means use the function `read'.");
- Vload_read_function = Qnil;
-
- DEFVAR_BOOL ("load-force-doc-strings", &load_force_doc_strings,
- "Non-nil means `load' should force-load all dynamic doc strings.\n\
-This is useful when the file being loaded is a temporary copy.");
- load_force_doc_strings = 0;
-
- DEFVAR_LISP ("source-directory", &Vsource_directory,
- "Directory in which Emacs sources were found when Emacs was built.\n\
-You cannot count on them to still be there!");
- Vsource_directory
- = Fexpand_file_name (build_string ("../"),
- Fcar (decode_env_path (0, PATH_DUMPLOADSEARCH)));
-
- /* Vsource_directory was initialized in init_lread. */
-
- load_descriptor_list = Qnil;
- staticpro (&load_descriptor_list);
-
- Qcurrent_load_list = intern ("current-load-list");
- staticpro (&Qcurrent_load_list);
-
- 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);
-
- Qbackquote = intern ("`");
- staticpro (&Qbackquote);
- Qcomma = intern (",");
- staticpro (&Qcomma);
- Qcomma_at = intern (",@");
- staticpro (&Qcomma_at);
- Qcomma_dot = intern (",.");
- staticpro (&Qcomma_dot);
-
- Qascii_character = intern ("ascii-character");
- staticpro (&Qascii_character);
-
- Qfunction = intern ("function");
- staticpro (&Qfunction);
-
- Qload = intern ("load");
- staticpro (&Qload);
-
- Qload_file_name = intern ("load-file-name");
- staticpro (&Qload_file_name);
-
- staticpro (&dump_path);
-
- staticpro (&read_objects);
- read_objects = Qnil;
-}
diff --git a/src/m/7300.h b/src/m/7300.h
deleted file mode 100644
index b090d8dd3ee..00000000000
--- a/src/m/7300.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2-2" */
-
-/* Supposedly now these machines have flexnames.
-
-/* # define SHORTNAMES */
-
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* XINT must explicitly sign-extend */
-
-#define EXPLICIT_SIGN_EXTEND
-
-/* 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) */
-
-#ifdef __GNUC__
-
-#define HAVE_ALLOCA
-
-#else
-
-#define SWITCH_ENUM_BUG
-#define C_ALLOCA
-#define STACK_DIRECTION -1
-
-#endif
-
-/* If you have the PD pty driver installed, uncomment the following line. */
-/* #define HAVE_PTYS */
-
-#define HAVE_SYSVIPC
-
-/* We don't have memmove. */
-#define memmove(d, s, n) safe_bcopy (s, d, n)
-
-/* 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
-
-/* Insist on using cc when compiling this. GCC may have been
- configured to use GAS syntax, which causes problems. */
-#define CRT0_COMPILE cc -c -O -Demacs
diff --git a/src/m/=dos386.h b/src/m/=dos386.h
deleted file mode 100644
index 1fb38da656f..00000000000
--- a/src/m/=dos386.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Machine description file for MS-DOS
-
- Copyright (C) 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* Note: lots of stuff here was taken from m-dos386.h in demacs. */
-
-
-/* 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 INTEL386
-
-/* 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 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
-
-/* We need a little extra space, see ../../lisp/loadup.el */
-#define PURESIZE 240000
-
-/* We have (the code to control) a mouse. */
-#define HAVE_MOUSE
diff --git a/src/m/acorn.h b/src/m/acorn.h
deleted file mode 100644
index ad7cfeb4ba2..00000000000
--- a/src/m/acorn.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/* Machine description file for Acorn RISCiX machines.
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. We can't
- * do this on the arm with gcc, since the first 4 args are in registers. */
-
-#ifdef __GNUC__
-#define NO_ARG_ARRAY
-#else
-#undef 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. */
-
-/* ARM note - The RISCiX Norcroft C Compiler has ALL
- non-32-bit types as unsigned */
-
-#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:
- Ones defined so far include vax, m68000, ns16000, pyramid,
- orion, tahoe, APOLLO and many others */
-
-/* ARM note - this is done by the Norcroft compiler - symbol is `__arm' */
-
-/* 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
-
-#ifdef LDAV_SYMBOL
-#undef LDAV_SYMBOL
-#endif
-
-#define LDAV_SYMBOL "_iavenrun"
-
-
-/* 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 */
-
-/*
- * Scale factor for scaled integers used to count
- * %cpu time and load averages.
- */
-
-/* FSHIFT and FSCALE are defined in param.h, but are required by
- LOAD_AVE_CVT, so they need to be defined here. */
-
-#ifndef FSHIFT
-#define FSHIFT 8 /* bits to right of fixed binary point */
-#endif
-
-#ifndef FSCALE
-#define FSCALE (1<<FSHIFT)
-#endif
-
-#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. */
-
-#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
-
-/* This prevents Emacs dumping an unsqueezed binary with the
- SQUEEZE bit set in the magic number. */
-
-#define ADJUST_EXEC_HEADER {hdr.a_magic &= ~MF_SQUEEZED;}
-
-/* Define C_ALLOCA if this machine does not support a true alloca
- and the one written in C should be used instead.
- Define HAVE_ALLOCA to say that the system provides a properly
- working alloca function and it should be used.
- Define neither one if an assembler-language alloca
- in the file alloca.s should be used. */
-
-#ifdef __GNUC__
-
-/* Use builtin alloca. Also be sure that no other ones are tried out. */
-#define alloca __builtin_alloca
-#define HAVE_ALLOCA
-
-/* Keep gcc/RISCiX happy - it uses __gccmain where other versions of
- gcc use __main, because of a library routine name clash. */
-#define __main __gccmain
-
-#else
-#define C_ALLOCA
-#undef HAVE_ALLOCA
-#endif /* __GNUC__ */
-
-/* Define NO_REMAP if memory segmentation makes it not work well
- 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
-
-
-#ifndef NOT_C_CODE
-#define TEXT_START 0x8000
-#define DATA_END &_edata
-extern int _edata;
-#define etext _etext
-#endif
-
-/* Avoid debugging library */
-#define LIBS_DEBUG
-
-/* Avoid sharing libc */
-#define LIB_STANDARD -lc_n
-
-/* Avoid sharing libX11 */
-#define LIB_X11_LIB -lX11_n
-
-/* All kinds of symbol definitions, so as to avoid multiply defined symbol
- errors from the RISCiX linker. */
-
-#ifdef __GNUC__
-#define C_DEBUG_SWITCH
-
-#define C_OPTIMIZE_SWITCH -O1 -fomit-frame-pointer -w -g -Dgetopt=gnu_getopt -Dopterr=gnu_opterr -Doptind=gnu_optind -Doptarg=gnu_optarg -Dcfree=gnu_cfree -D___type=
-
-#else
-#define C_DEBUG_SWITCH -O -w -g -Dgetopt=gnu_getopt -Dopterr=gnu_opterr -Doptind=gnu_optind -Doptarg=gnu_optarg -Dcfree=gnu_cfree
-#endif
-
-/* Turn this on to avoid the emacs malloc and use standard one */
-
-#undef SYSTEM_MALLOC
-
-/* Use <dirent.h>. */
-#define SYSV_SYSTEM_DIR
-
-/* For the portable alloca */
-#define STACK_DIRECTION -1
-
-#ifdef NO_REMAP
-/* CRT0_O is defined in s/riscix1-1.h or s/riscix1-2.h, as appropriate. */
-#define START_FILES pre-crt0.o CRT0_O
-#else
-Cannot
-do
-this
-yet
-#endif
diff --git a/src/m/alliant-2800.h b/src/m/alliant-2800.h
deleted file mode 100644
index 5cf7e393433..00000000000
--- a/src/m/alliant-2800.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* 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 free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-3" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-#undef WORD_MACHINE
-
-/* 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. */
-
-/* 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 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
-
-/* Use the K&R version of the DEFUN macro. */
-#define USE_NONANSI_DEFUN
diff --git a/src/m/alliant.h b/src/m/alliant.h
deleted file mode 100644
index bf8909fb3ef..00000000000
--- a/src/m/alliant.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* 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 alliant1.h instead of this file.
- Use 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#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
-
-/* 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
deleted file mode 100644
index 95f56cf1804..00000000000
--- a/src/m/alliant1.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* config.h should include this file for version 1 of Alliant's
- operating system. */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-2" */
-
-#define ALLIANT_1
-#include "alliant.h"
diff --git a/src/m/alliant4.h b/src/m/alliant4.h
deleted file mode 100644
index ade3dbbaae5..00000000000
--- a/src/m/alliant4.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* machine description file for Alliant Concentrix 4.0 or later.
- Use alliant.h for versions 2 and 3. */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-2" */
-
-#include "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/alpha.h b/src/m/alpha.h
deleted file mode 100644
index 9c33475ebbf..00000000000
--- a/src/m/alpha.h
+++ /dev/null
@@ -1,309 +0,0 @@
-/* machine description file For the alpha chip.
- Copyright (C) 1994 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, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Use -opsystem=osf1
-NOTE-END
-
-*/
-
-#define BITS_PER_LONG 64
-#define BITS_PER_EMACS_INT 64
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- Ones defined so far include vax, m68000, ns16000, pyramid,
- orion, tahoe, APOLLO and many others */
-
-/* __alpha defined automatically */
-
-
-/* Use type EMACS_INT rather than a union, to represent Lisp_Object */
-/* This is desirable for most machines. */
-
-#define NO_UNION_TYPE
-
-/* Define the type to use. */
-#define EMACS_INT long
-#define EMACS_UINT unsigned long
-#define SPECIAL_EMACS_INT
-
-/* 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 HAVE_ALLOCA
-
-/* GNU malloc and the relocating allocator do not work together
- with X. [Who wrote that?] */
-
-/* May 1995: reportedly [Rainer Schoepf <schoepf@uni-mainz.de>] both the
- system and the gnu malloc system work with "alpha-dec-osf3.0" and
- "alpha-dec-osf3.2". */
-
-/* May 1995: it seems to me [Morten Welinder <terra@diku.dk>] that both
- mallocs work with "alpha-dec-osf2.0", but I daren't break anything
- right now. Feel free to play if you want. */
-
-/* #define SYSTEM_MALLOC */
-
-/* Define NO_REMAP if memory segmentation makes it not work well
- to change the boundary between the text section and data section
- when Emacs is dumped. If you define this, the preloaded Lisp
- code will not be sharable; but that's better than failing completely. */
-
-#define NO_REMAP
-
-/* Some really obscure 4.2-based systems (like Sequent DYNIX)
- * do not support asynchronous I/O (using SIGIO) on sockets,
- * even though it works fine on tty's. If you have one of
- * these systems, define the following, and then use it in
- * config.h (or elsewhere) to decide when (not) to use SIGIO.
- *
- * You'd think this would go in an operating-system description file,
- * but since it only occurs on some, but not all, BSD systems, the
- * reasonable place to select for it is in the machine description
- * file.
- */
-
-/* #define NO_SOCK_SIGIO */
-
-
-#ifdef __ELF__
-/* With ELF, make sure that all common symbols get allocated to in the
- data section. Otherwise, the dump of temacs may miss variables in
- the shared library that have been initialized. For example, with
- GNU libc, __malloc_initialized would normally be resolved to the
- shared library's .bss section, which is fatal. */
-# ifdef __GNUC__
-# define C_SWITCH_MACHINE -fno-common
-# else
-# error What gives? Fix me if DEC Unix supports ELF now.
-# endif
-#endif
-
-#ifdef __ELF__
-#undef UNEXEC
-#define UNEXEC unexelf.o
-#endif
-
-#ifndef __ELF__
-
-/* Describe layout of the address space in an executing process. */
-
-#define TEXT_START 0x120000000
-#define DATA_START 0x140000000
-
-/* This is necessary for mem-limits.h, so that start_of_data gives
- the correct value */
-
-#define DATA_SEG_BITS 0x140000000
-
-/* The program to be used for unexec. */
-
-#define UNEXEC unexalpha.o
-
-#endif /* notdef __ELF__ */
-
-#ifdef OSF1
-#define ORDINARY_LINK
-
-/* Some systems seem to have this, others don't. */
-#ifdef HAVE_LIBDNET
-#define LIBS_MACHINE -ldnet
-#else
-#define LIBS_MACHINE -ldnet_stub
-#endif
-#endif /* OSF1 */
-
-#if 0 /* Rainer Schoepf <schoepf@uni-mainz.de> says this loses with X11R6
- since it has only shared libraries. */
-#ifndef __GNUC__
-/* This apparently is for the system ld as opposed to Gnu ld. */
-#ifdef OSF1
-#define LD_SWITCH_MACHINE -non_shared
-#endif
-#endif
-#endif /* 0 */
-
-#ifdef OSF1
-#define LIBS_DEBUG
-#define START_FILES pre-crt0.o
-#endif
-
-#if defined (LINUX) && __GNU_LIBRARY__ - 0 < 6
-/* This controls a conditional in main. */
-#define LINUX_SBRK_BUG
-#endif
-
-
-#define PNTR_COMPARISON_TYPE unsigned long
-
-/* On the 64 bit architecture, we can use 60 bits for addresses */
-
-#define VALBITS 60
-
-
-/* This definition of MARKBIT is necessary because of the comparison of
- ARRAY_MARK_FLAG and MARKBIT in an #if in lisp.h, which cpp doesn't like. */
-
-#define MARKBIT 0x8000000000000000L
-
-
-/* Define XINT and XUINT so that they can take arguments of type int */
-
-#define XINT(a) (((long) (a) << (BITS_PER_LONG - VALBITS)) >> (BITS_PER_LONG - VALBITS))
-#define XUINT(a) ((long) (a) & VALMASK)
-
-/* Define XPNTR to avoid or'ing with DATA_SEG_BITS */
-
-#define XPNTR(a) XUINT (a)
-
-/* Declare malloc and realloc in a way that is clean.
- But not in makefiles! */
-
-#ifndef NOT_C_CODE
-/* We need these because pointers are larger than the default ints. */
-#include <alloca.h>
-
-/* Hack alert! For reasons unknown to mankind the string.h file insists
- on defining bcopy etc. as taking char pointers as arguments. With
- Emacs this produces an endless amount of warning which are harmless,
- but tends to flood the real errors. This hack works around this problem
- by not prototyping. */
-#define bcopy string_h_bcopy
-#define bzero string_h_bzero
-#define bcmp string_h_bcmp
-#include <string.h>
-#undef bcopy
-#undef bzero
-#undef bcmp
-
-/* We need to prototype these for the lib-src programs even if we don't
- use the system malloc for the Emacs proper. */
-#ifdef _MALLOC_INTERNAL
-/* These declarations are designed to match the ones in gmalloc.c. */
-#if defined (__STDC__) && __STDC__
-extern void *malloc (), *realloc (), *calloc ();
-#else
-extern char *malloc (), *realloc (), *calloc ();
-#endif
-#else /* not _MALLOC_INTERNAL */
-extern void *malloc (), *realloc (), *calloc ();
-#endif /* not _MALLOC_INTERNAL */
-
-
-extern long *xmalloc (), *xrealloc ();
-
-#ifdef REL_ALLOC
-#ifndef _MALLOC_INTERNAL
-/* "char *" because ralloc.c defines it that way. gmalloc.c thinks it
- is allowed to prototype these as "void *" so we don't prototype in
- that case. You're right: it stinks! */
-extern char *r_alloc (), *r_re_alloc ();
-extern void r_alloc_free ();
-#endif /* not _MALLOC_INTERNAL */
-#endif /* REL_ALLOC */
-
-#endif /* not NOT_C_CODE */
-
-#ifdef OSF1
-#define PTY_ITERATION for (i = 0; i < 1; i++) /* ick */
-#define PTY_NAME_SPRINTF /* none */
-#define PTY_TTY_NAME_SPRINTF /* none */
-#define PTY_OPEN \
- do \
- { \
- int dummy; \
- SIGMASKTYPE mask; \
- mask = sigblockx (SIGCHLD); \
- if (-1 == openpty (&fd, &dummy, pty_name, 0, 0)) \
- fd = -1; \
- sigsetmask (mask); \
- close (dummy); \
- } \
- while (0)
-#endif
-
-/* On the Alpha it's best to avoid including TERMIO since struct
- termio and struct termios are mutually incompatible. */
-#define NO_TERMIO
-
-#ifdef LINUX
-# define TEXT_END ({ extern int _etext; &_etext; })
-# ifndef __ELF__
-# define COFF
-# define DATA_END ({ extern int _EDATA; &_EDATA; })
-# endif /* notdef __ELF__ */
-#endif
diff --git a/src/m/altos.h b/src/m/altos.h
deleted file mode 100644
index 264d65745d1..00000000000
--- a/src/m/altos.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* altos machine description file 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-#define EXPLICIT_SIGN_EXTEND
-
-/* Use type int rather than a union, to represent Lisp_Object */
-
-#define NO_UNION_TYPE
-
-#define LIB_STANDARD -lc
-
-#ifdef __GNUC__
-#define alloca __builtin_alloca
-#define HAVE_ALLOCA
-#else
-#define C_ALLOCA /* we have -lPW and alloca but it's broken!
- <vsedev!ron> */
-#endif
-
-#define SWITCH_ENUM_BUG
-
-#define NO_REMAP
-#define STACK_DIRECTION -1
-
-#undef TERMINFO
-
-#undef CANNOT_DUMP
-#undef SHORTNAMES
-#define TERMCAP
-
-#define LIBS_TERMCAP -ltermlib
-#define PURESIZE 220000
-#define ALTOS
-
-#ifdef __GNUC__
-#define COFF_ENCAPSULATE
-#endif
diff --git a/src/m/amdahl.h b/src/m/amdahl.h
deleted file mode 100644
index 08887b49410..00000000000
--- a/src/m/amdahl.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/* amdahl machine description file
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/*
-This file for amdahl_uts created by modifying the template.h
-by Jishnu Mukerji 3/1/87
-
-The following line tells the configuration script what sort of
-operating system this machine is likely to run.
-USUAL-OPSYS="usg5-2-2"
-
-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.
-*/
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#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! */
-
-/* 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. */
-
-#define C_OPTIMIZE_SWITCH
-
-/* 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
diff --git a/src/m/apollo.h b/src/m/apollo.h
deleted file mode 100644
index f8424be88b0..00000000000
--- a/src/m/apollo.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* machine description file for Apollo machine.
- Copyright (C) 1985, 1986, 1994, Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-3" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* 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 */
-
-/* Undefine VIRT_ADDR_VARIES because the virtual addresses of
- pure and impure space as loaded do not vary. */
-
-#undef VIRT_ADDR_VARIES
-
-/* Define HAVE_ALLOCA because we use the system's version of alloca. */
-
-#define HAVE_ALLOCA
-
-/* Prevent -lg from being used for debugging. Not needed. */
-
-#define LIBS_DEBUG
-
-/* Can't use the system's termcap. It has compressed data sections that
- interfere with dumping. That means we won't automatically get a vt100
- when we start up emacs in a dm pad (a dubious feature at best anyway). */
-
-#undef LIBS_TERMCAP
-
-/* Must use the system's malloc and alloca. */
-
-#define SYSTEM_MALLOC
-
-/* Define the file we use for UNEXEC. */
-
-#define UNEXEC unexapollo.o
-
-/* The Apollo linker does not recognize the -X switch, so we remove it here. */
-
-#define LD_SWITCH_SYSTEM
-
-/* Define C_SWITCH_MACHINE to compile for 68020/68030 or PRISM.
- Define LD_SWITCH_MACHINE to save space by stripping symbols
- and use X11 libraries. */
-
-#if _ISP__A88K
-#define C_SWITCH_MACHINE -W0,-ncompress -W0,-opt,2 -A cpu,a88k -A sys,any -A run,bsd4.3
-#define LD_SWITCH_MACHINE -A cpu,a88k -A sys,any -A run,bsd4.3
-#else
-#define C_SWITCH_MACHINE -W0,-ncompress -W0,-opt,2 -A cpu,3000 -A sys,any -A run,bsd4.3
-#define LD_SWITCH_MACHINE -A cpu,m68k -A sys,any -A run,bsd4.3
-#endif
-
-#define OLDXMENU_OPTIONS ${C_SWITCH_MACHINE}
-
-/* In SR10.4, unistd.h has bad prototype for getpgrp, so we don't include it. */
-#undef HAVE_UNISTD_H
diff --git a/src/m/att3b.h b/src/m/att3b.h
deleted file mode 100644
index 394f3db959f..00000000000
--- a/src/m/att3b.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/* Machine-dependent configuration for GNU Emacs for AT&T 3b machines.
- Copyright (C) 1986 Free Software Foundation, Inc.
-
- Modified by David Robinson (daver@csvax.caltech.edu) 6/6/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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically */
-#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 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 making xmakefile! */
-extern int sign_extend_temp;
-#endif
-
-#if u3b2 || u3b5 || u3b15
-
-/* On 3b2/5/15, data space has high order bit on. */
-#define VALBITS 27
-#define VALMASK (((1<<VALBITS) - 1) | (1 << 31))
-#define XTYPE(a) ((enum Lisp_Type) (((a) >> VALBITS) & GCTYPEMASK))
-
-#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 */
-
-/* 3b2 does not have memmove, I'm told. */
-/* It is safe to have no parens around the args in the safe_bcopy call,
- and parens would screw up the prototype decl for memmove. */
-#define memmove(d, s, n) safe_bcopy (s, d, n)
-
-/* This affects filemode.c. */
-#define NO_MODE_T
diff --git a/src/m/aviion.h b/src/m/aviion.h
deleted file mode 100644
index 62802d7a615..00000000000
--- a/src/m/aviion.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-#define WORD_MACHINE
-
-/* 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 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
-
-/* 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/celerity.h b/src/m/celerity.h
deleted file mode 100644
index 6e378e84fcc..00000000000
--- a/src/m/celerity.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* XINT must explicitly sign extend */
-
-#define EXPLICIT_SIGN_EXTEND
-
-/* 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/clipper.h b/src/m/clipper.h
deleted file mode 100644
index 7dc5e84b07d..00000000000
--- a/src/m/clipper.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* machine description file for clipper
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically */
-
-#define clipper 1
-
-/* Use type int rather than a union, to represent Lisp_Object */
-
-#define NO_UNION_TYPE
-
-/* 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 */
-
-/* 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))
-
-/* 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. */
-
-#define C_ALLOCA
-
-/* Define NO_REMAP if memory segmentation makes it not work well
- to change the boundary between the text section and data section
- when Emacs is dumped. If you define this, the preloaded Lisp
- code will not be sharable; but that's better than failing completely. */
-
-/* #define NO_REMAP */
-
-#ifdef USG
-#define TEXT_START 0
-#endif /* USG */
-
-#define LD_TEXT_START_ADDR 8000
diff --git a/src/m/cnvrgnt.h b/src/m/cnvrgnt.h
deleted file mode 100644
index c6008083291..00000000000
--- a/src/m/cnvrgnt.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* machine description file for convergent S series.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically. */
-
-#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.
- These are commented out since it is not supported by this machine. */
-
-#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. */
-
-#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
-
-/* 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
-
-/* Change some things to avoid bugs in compiler. */
-
-#define SWITCH_ENUM_BUG
-
-/* fork(2) and vfork() are the same here. */
-
-#define HAVE_VFORK
-
-/* grows towards lower addresses. */
-
-#define STACK_DIRECTION -1
-
-/* some errno.h's don't actually allocate the variable itself.
- Cause crt0.c to define errno. */
-
-#define NEED_ERRNO
diff --git a/src/m/convex.h b/src/m/convex.h
deleted file mode 100644
index bd5125a2435..00000000000
--- a/src/m/convex.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/* machine description file for Convex (all models).
- Copyright (C) 1987, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-3" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments.
- * Maybe it would be better to simply correct the code. */
-
-#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. */
-#ifndef convex /* The compiler doesn't always do this. */
-#define convex
-#endif
-
-/* Use type int rather than a union, to represent Lisp_Object */
-/* This is desirable for most machines. */
-
-#define NO_UNION_TYPE
-
-#ifndef __GNUC__ /* David M. Cooke <dcooke@haven.larc.nasa.gov>
- and Ralph Sobek <Ralph.Sobek@cerfacs.fr> agree
- must ignore one arg when compiled with convex compiler. */
-#define CRT0_DUMMIES ignore,
-#else
-#define CRT0_DUMMIES
-#endif
-
-/* 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
-
-/* Must use the system's termcap. It does special things. */
-
-#define LIBS_TERMCAP -ltermcap
-
-/* 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 (1 << (BITS_PER_INT-1))
-
-/* Right shift is logical shift.
- And the usual way of handling such machines, which involves
- copying the number into sign_extend_temp, does not work
- for reasons as yet unknown. */
-
-#define XINT(a) sign_extend_lisp_int (a)
-
-/* 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 LD_SWITCH_MACHINE \
- -e__start -L /usr/lib \
- '-A__iob=___ap$$iob' '-A_use_libc_sema=___ap$$use_libc_sema'
-
-/* Use <dirent.h>. */
-#define SYSV_SYSTEM_DIR
-
-#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
-
-/* Avoid error in xrdb.c - d.m.cooke@larc.nasa.gov. */
-#define DECLARE_GETPWUID_WITH_UID_T
-
-/* Call getpgrp properly. */
-#define GETPGRP_NO_ARG
-
-/* Tested for both Convex C and GNUC by d.m.cooke@larc.nasa.gov. */
-#define LIBS_MACHINE -lC2
-
-/* Avoid error in getloadavg.c. */
-#define NLIST_NAME_UNION 1
-
-#if 0 /* This is supposed to be an improvement.
- It would be good for people to try enabling this code
- and report the results. */
-/* gcc -nostdlib prevents some math symbols from being included.
- So we have to use -nostartfiles instead. */
-#define LINKER $(CC) -nostartfiles
-
-#define ORDINARY_LINK
-
-#undef LD_SWITCH_MACHINE
-#define LD_SWITCH_MACHINE \
- -L /usr/lib \
- '-A__iob=___ap$$iob' '-A_use_libc_sema=___ap$$use_libc_sema'
-#endif
diff --git a/src/m/cydra5.h b/src/m/cydra5.h
deleted file mode 100644
index fe224f28fd9..00000000000
--- a/src/m/cydra5.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-3" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#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
-
-/* 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 (ptyname, "/dev/pty%03x", i);
-#define PTY_TTY_NAME_SPRINTF sprintf (ptyname, "/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
deleted file mode 100644
index ee883656c30..00000000000
--- a/src/m/delta.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/* Machine description file for the Motorola Delta.
- Tested on mvme147 board using R3V7 without X. Tested with gcc.
- Tested on mvme167 board using R3V7 without X. Tested with cc, gnucc, gcc.
- Copyright (C) 1986, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-3" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- Ones defined so far include vax, m68000, ns16000, pyramid,
- orion, tahoe, APOLLO and many others */
-
-#define m68000
-#define MOTOROLA_DELTA
-
-/* 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 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 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
-
-/* Some really obscure 4.2-based systems (like Sequent DYNIX)
- * do not support asynchronous I/O (using SIGIO) on sockets,
- * even though it works fine on tty's. If you have one of
- * these systems, define the following, and then use it in
- * config.h (or elsewhere) to decide when (not) to use SIGIO.
- *
- * You'd think this would go in an operating-system description file,
- * but since it only occurs on some, but not all, BSD systems, the
- * reasonable place to select for it is in the machine description
- * file.
- */
-
-/* #define NO_SOCK_SIGIO */
-
-
-/* Undefine this if you don't want the machine slow down when a buffer
- is modified. */
-
-#define CLASH_DETECTION
-
-/* Machine specific stuff */
-#define HAVE_PTYS
-#define SYSV_PTYS
-#ifdef HAVE_INET_SOCKETS /* this comes from autoconf */
-# define HAVE_SOCKETS /* NSE may or may not have been installed */
-#endif
-#define SIGNALS_VIA_CHARACTERS
-#define BROKEN_CLOSEDIR /* builtin closedir is interruptible */
-#undef HAVE_BCOPY /* b* functions are just stubs to mem* ones */
-#define bcopy(from,to,bytes) memcpy(to,from,bytes)
-#define bzero(to,bytes) memset(to,0,bytes)
-#define bcmp memcmp
-#define memmove(t,f,s) safe_bcopy(f,t,s) /* for overlapping copies */
-#undef KERNEL_FILE
-#define KERNEL_FILE "/sysv68"
-#undef LDAV_SYMBOL
-#ifdef SIGIO
- /* R3V7 has SIGIO, but interrupt input does not work yet.
- Let's go on with cbreak code. */
-/* # define INTERRUPT_INPUT */
-#endif
-
-/* The standard C library is -lc881, not -lc.
- -lbsd brings sigblock and sigsetmask.
- DO NOT USE -lPW. That version of alloca is broken in versions R3V5,
- R3V6, R3V7. -riku@field.fi -pot@cnuce.cnr.it. */
-
-#define LIB_STANDARD -lc881
-#define LIB_MATH -lm881
-#define LIBS_TERMCAP -lcurses
-#define LIBS_SYSTEM -lbsd
-#undef sigsetmask
-
-#ifdef HAVE_X_WINDOWS
-# define HAVE_RANDOM
-# define BROKEN_FIONREAD /* pearce@ll.mit.edu says this is needed. */
-# define HAVE_XSCREENNUMBEROFSCREEN
-# undef LIB_X11_LIB /* no shared libraries */
-# define LIB_X11_LIB -lX11
-# undef USG_SHARED_LIBRARIES /* once again, no shared libs */
-# undef LIBX11_SYSTEM /* no -lpt as usg5-3.h expects */
-# define LIBX11_SYSTEM -lnls -lnsl_s
-#endif /* HAVE_X_WINDOWS */
-
-#ifdef __GNUC__
- /* Use builtin alloca. Also be sure that no other ones are tried out. */
-# define alloca __builtin_alloca
-# define HAVE_ALLOCA
- /* Union lisp objects do not yet work as of 19.15. */
-/* # undef NO_UNION_TYPE */
-
- /* We are assuming here that the `true' GNU gcc has not been
- installed, and we are using the gnucc provided by Motorola. No
- support exists for compiling with GNU gcc, as I do not have it on
- my machine to try it out. -pot@cnuce.cnr.it
- If __STDC__ is defined gnucc has been called without the -traditional
- option, that is, we are inside configure. If THIS_IS_CONFIGURE is
- not defined, then configure is trying to figure out what the right
- option for real compilation are.
- Let us set -traditional, because gmalloc.c includes <stddef.h>, and
- we don't have that (as of SYSV68 R3V7). */
-# define C_SWITCH_MACHINE -mfp0ret -traditional -Dconst= -fdelayed-branch -fstrength-reduce -fno-inline -fcaller-saves
-# define LIB_GCC /lib/gnulib881
-
-#else
- /* Not __GNUC__, use the alloca in alloca.s. */
-
- /* Try to guess if we are using the Green Hills Compiler */
-# if defined mc68000 && defined MC68000
- /* 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 -O
-# define GAP_USE_BCOPY /* *++to = *++from is inefficient */
-# define BCOPY_UPWARD_SAFE 0
-# define BCOPY_DOWNWARD_SAFE 1 /* bcopy does: mov.b (%a1)+,(%a0)+ */
-# else
- /* We are using the standard AT&T Portable C Compiler */
-# define SWITCH_ENUM_BUG
-# endif
-
-#endif /* not __GNUC__ */
diff --git a/src/m/delta88k.h b/src/m/delta88k.h
deleted file mode 100644
index 10bb6c911a5..00000000000
--- a/src/m/delta88k.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/* Machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-3" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- Ones defined so far include vax, m68000, ns16000, pyramid,
- orion, tahoe, APOLLO and many others */
-
-#ifndef m88000 /* Some 88k C compilers already define this */
-#define m88000
-#endif
-
-/* 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. */
-
-#ifdef __GNUC__
-#define HAVE_ALLOCA /* ... and be sure that no other ones are tried out. */
-#undef C_ALLOCA
-#else /* not __GNUC__ */
-#undef HAVE_ALLOCA
-#define C_ALLOCA /* Use the alloca() supplied in alloca.c. */
-#define STACK_DIRECTION -1 /* The stack grows towards lower addresses. */
-#endif /* __GNUC__ */
-
-/* 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
- */
-#ifdef USG5_4
-/* rms: not needed; LIB_X11_LIB deals with this. */
-/* #define LIBX11_SYSTEM -lX11 */
-#else
-#undef LIB_X11_LIB /* We don't have the shared libs as assumed in usg5-3.h. */
-#undef LIBX11_SYSTEM
-#define LIBX11_SYSTEM -lnsl -lbsd
-#endif /* USG5_4 */
-
-#define BROKEN_FIONREAD
-
-/* previously defined in usg5-4, if we choose to use that. */
-#ifndef LIBS_SYSTEM
-#ifdef USG5_4
-#define LIBS_SYSTEM -lsocket -lnsl
-#else
-#define LIBS_SYSTEM -lbsd -lg
-#endif /* USG5_4 */
-#endif
-
-#define HAVE_TERMIOS
-#undef HAVE_TERMIO
-#define NO_TERMIO
-#undef sigsetmask
-
-#define NO_SIOCTL_H
-
-#ifdef USG5_4
-#ifdef HAVE_X_WINDOWS
-#else
-#undef BSTRING
-#endif /* HAVE_X_WINDOWS */
-#endif /* USG5_4 */
-
-#define NO_PTY_H
-
-#define USE_GETOBAUD
diff --git a/src/m/dpx2.h b/src/m/dpx2.h
deleted file mode 100644
index 978b2fc88fd..00000000000
--- a/src/m/dpx2.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/* machine description for Bull DPX/2 range
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-3" */
-
-/*
- * 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 ?) */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE /**/
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- Ones defined so far include vax, m68000, ns16000, pyramid,
- orion, tahoe, APOLLO and many others */
-
-/* /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)
- */
-#ifndef DPX2
-#define DPX2
-#endif
-
-/* Disable support for shared libraries in unexec. */
-
-#undef USG_SHARED_LIBRARIES
-
-/*
- * if we use X11, libX11.a has these...
- */
-# undef LIB_X11_LIB
-# define LIB_X11_LIB -lX11
-# undef LIBX11_SYSTEM
-# define LIBX11_SYSTEM -lmalloc -lnsl
-# define BSTRING
-# define HAVE_GETWD
-
-/*
- * we must have INET loaded so we have sockets
- */
-# define HAVE_SOCKETS
-
-/*
- * useful if you have INET loaded
- */
-# define LIBS_MACHINE -linet
-
-
-#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 */
-
-
-#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
-
-/*
- * but we have that
-*/
-#define GETPGRP_NO_ARG
-
-/* select also needs this header file--but not in ymakefile. */
-#ifndef NOT_C_CODE
-#include <sys/types.h>
-#include <sys/select.h>
-#endif
-
-#define TEXT_START 0
-
-/*
- * Define the direction of stack growth.
- */
-
-#define STACK_DIRECTION -1
-
-/* we have termios */
-#undef HAVE_TERMIO
-#define HAVE_TERMIOS
-#define HAVE_TCATTR
-
-/* we also have this */
-#define HAVE_PTYS
-#define SYSV_PTYS
-
-/* It doesn't seem we have sigpause */
-#undef HAVE_SYSV_SIGPAUSE
-
-#define POSIX_SIGNALS
-
-/* We don't need the definition from usg5-3.h with POSIX_SIGNALS. */
-#undef sigsetmask
-
-
-/* on bos2.00.45 there is a bug that makes the F_SETOWN fcntl() call
- enters in an infinite loop. Avoid calling it */
-#define F_SETOWN_BUG
-
-/* system closedir sometimes complains about wrong descriptor
- for no apparent reasons. Use the provided closedir in sysdep.c instead */
-#ifdef HAVE_CLOSEDIR
-#undef HAVE_CLOSEDIR
-#endif
-
-/* Send signals to subprocesses by "typing" signal chars at them. */
-#define SIGNALS_VIA_CHARACTERS
-
-/* This is to prevent memory clobbering on the DPX/2 200. */
-#define LD_SWITCH_MACHINE -N -T32
-
- /* end of dpx2.h */
-
-
diff --git a/src/m/dual.h b/src/m/dual.h
deleted file mode 100644
index a2c022f08ed..00000000000
--- a/src/m/dual.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Dual running System V (-machine=dual -opsystem=usg5-2)
-
- As of 17.46, this works except for a few changes
- needed in unexec.c.
-
-Dual running Uniplus (-machine=dual -opsystem=unipl5-2)
-
- Works, as of 17.51.
-NOTE-END */
-
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* XINT must explicitly sign-extend */
-
-#define EXPLICIT_SIGN_EXTEND
-
-/* 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
deleted file mode 100644
index dc27d25bad7..00000000000
--- a/src/m/elxsi.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/* machine description file for Elxsi machine (running enix).
- Copyright (C) 1986, 1992 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2" */
-
-/* This file was modified by Matt Crawford <matt@tank.uchicago.edu>
- to work under Elxsi's 12.0 release of BSD unix. */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/*#define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/*#define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- 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
-
-
-/* Name of kernel load average variable */
-
-#undef LDAV_SYMBOL
-#define LDAV_SYMBOL "avenrun"
-
-/* 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.
-
- Earlier versions couldn't dump.
- Changes for 12.0 release are in 19.1.
- Dumping should work now. */
-
-/* #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
-
-/* Elxsi uses COFF under both Sys V and BSD environments */
-
-#define COFF
-
-#define ADJUST_EXEC_HEADER {\
-extern int _init_brk;\
-_init_brk = bss_start;\
-}
diff --git a/src/m/gec63.h b/src/m/gec63.h
deleted file mode 100644
index c0ca4280911..00000000000
--- a/src/m/gec63.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* 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 NO_REMAP
-
-/* The rest of the file certainly needs updating for Emacs 19.29! */
-
-/* Define sizes of portions of a Lisp_Object. */
-#define VALBITS 24
-
-#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 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)
diff --git a/src/m/gould-np1.h b/src/m/gould-np1.h
deleted file mode 100644
index 014fa68fb53..00000000000
--- a/src/m/gould-np1.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* machine description file for Gould NP1 with UTX/32 3.0 (first release for NP1). */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-3" */
-
-/* If your system uses COFF (Common Object File Format) then define the
- preprocessor symbol "COFF". */
-/* UTX 3.0 uses a cross between COFF and a.out format, but closer to COFF. */
-/* at least currently, already defined by cpp, but make sure */
-#ifndef COFF
-#define COFF
-#endif COFF
-
-#include "gould.h"
-
-/* undefine what gould.h defined */
-#undef ADJUST_EXEC_HEADER
-
-/* If your system uses COFF (Common Object File Format) then define the
- preprocessor symbol "COFF". */
-/* UTX 3.0 uses a cross between COFF and a.out format, but closer to COFF. */
-#ifndef COFF /* at least currently, already defined by cpp */
-#define COFF
-#endif COFF
-
-/* make Gould NP1 and PN COFF look like USG COFF */
-/* NP1 COFF */
-#undef aouthdr /* Since gould.h already defined these */
-#undef a_dtbase
-
-#ifdef IN_UNEXEC
-#define aouthdr exec
-#define ADJUST_TEXT_SCNHDR_SIZE
-
-/* Gould COFF - these are already defined in gould.h */
-/*
- * #define COFF_WITH_BSD_SYMTAB
- * #define HEADER_INCL_IN_TEXT
- * #define magic a_magic
- * #define tsize a_text
- * #define dsize a_data
- * #define bsize a_bss
- * #define entry a_entry
- * #define text_start a_txbase
- * #define data_start a_dtbase
-*/
-/* End Gould COFF */
-#endif /* IN_UNEXEC */
-
-/* NP1 supports a slightly different set than PowerNode */
-#define BAUD_CONVERT { 0, 50, 75, 110, 134, 150, 300, 450, 600, 1200, \
- 1800, 2000, 2400, 3600, 4800, 7200, 9600, \
- 19200, 38400 }
-
-#define LD_SWITCH_SYSTEM -BS -e start
-
-/* Undef C_DEBUG_SWITCH because it may have been set in gould.h */
-/* It will compile and load and works with dbx. Runs under an incomplete
- port of gdb, but gdb doesn't always find things correctly. */
-#undef C_DEBUG_SWITCH
-#define C_DEBUG_SWITCH -g
-#define LIBS_DEBUG -lg
-
-
-/* The data segment in this machine always starts at address 0x1000000 = 16M.
- 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 0x1000000
-#define DATA_START 0x1000000
-
-/* The text segment always starts at 0.
- This way we don't need to have a label _start defined. */
-#define TEXT_START 0
-
-/* Data isn't right next to text on an NP1 */
-#define NO_REMAP
-
-/* The bcopy bug has reappeared */
-#undef BSTRING
-
-#ifndef GOULD_NP1
-#define GOULD_NP1
-#endif
-
-
diff --git a/src/m/gould.h b/src/m/gould.h
deleted file mode 100644
index e208b9ea996..00000000000
--- a/src/m/gould.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/* machine description file for Gould PowerNodes with UTX/32 2.0 and 2.1.
- (See MACHINES for older versions.)
-
-* NOTE: If you are running a pre-release of UTX/32 2.1 you should #define
-* RELEASE2_1 in config.h. This may also be necessary with un-updated
-* official releases of 2.1
-
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Gould Power Node (-machine=gould -opsystem=bsd4-2 or bsd4-3)
-(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.
-
- On UTX/32 2.0, use -opsystem=bsd4-3
-
- On UTX/32 1.2 and UTX/32S 1.0, use -opsystem=bsd4-2 and note that compiling
- lib-src/sorted-doc tickles a compiler bug: remove the -g flag to cc in the
- makefile.
-
- UTX/32 1.3 has a bug in the bcopy library routine. Fix it by
- #undef BSTRING in 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.
-NOTE-END */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically */
-
-#ifndef GOULD
-#define GOULD
-#endif
-
-/* sel is an old preprocessor name on gould machines
- - it is no longer needed and interferes with a variable in xmenu.c */
-#undef sel
-
-/* 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. */
-
-/* If this is a 2.1 system, COFF will be predefined by cpp. If it's */
-/* pre-2.1 COFF won't be defined, which is as it should be. */
-
-#ifdef COFF
-
-#define HEADER_INCL_IN_TEXT
-#define COFF_BSD_SYMBOLS
-
-/* Seems to be necessary with coff */
-#define NO_REMAP
-
-#ifndef GOULD_NP1
-/* gould-np1.h includes this file */
-/* keep the old value - don't skip over the headers */
-#define KEEP_OLD_TEXT_SCNPTR
-#define KEEP_OLD_PADDR
-#ifndef RELEASE2_1
-#define ADJUST_TEXTBASE
-#endif /*RELEASE2_1*/
-#endif /* GOULD_NP1 */
-
-#ifdef IN_UNEXEC
-/* make Gould NP and PN COFF look like USG COFF */
-/* PN COFF */
-#define aouthdr old_exec
-/* PN COFF doesn't have a data_start or a_dtbase field in its */
-/* optional header, so substitute a junk field */
-#define a_dtbase a_ccvers
-/* Gould COFF */
-#define magic a_magic
-#define tsize a_text
-#define dsize a_data
-#define bsize a_bss
-#define entry a_entry
-#define text_start a_txbase
-#define data_start a_dtbase
-#endif /* IN_UNEXEC */
-
-/* Define how to search all pty names.
- * This is for UTX 2.1 and greater on PN and all NP versions. It is only
- * accident that this happens to correspond to the same versions of UTX
- * as COFF does, but we'll take advantage of that here.
- */
-
-/*#define USE_PTY_PAIR*/
-
-#endif /* COFF */
-
-/* -g is sometimes 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. */
-
-#ifndef COFF
-#define ADJUST_EXEC_HEADER \
- unexec_text_start = hdr.a_txbase + sizeof (hdr);
-#endif
-
-/* 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/hp800.h b/src/m/hp800.h
deleted file mode 100644
index 3f2d9f7f5e6..00000000000
--- a/src/m/hp800.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="hpux" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-#undef 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 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 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
-
-/* The standard definitions of these macros would work ok,
- but these are faster because the constants are short. */
-
-
-#define XUINT(a) (((unsigned)(a) << BITS_PER_INT-VALBITS) >> BITS_PER_INT-VALBITS)
-
-#define XSET(var, type, ptr) \
- ((var) = ((int)(type) << VALBITS) + (((unsigned) (ptr) << BITS_PER_INT-VALBITS) >> BITS_PER_INT-VALBITS))
-
-#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) << BITS_PER_INT-GCTYPEBITS-VALBITS) >> BITS_PER_INT-GCTYPEBITS-VALBITS))
-#endif
-
-/* Define the BSTRING functions in terms of the sysV functions. */
-/* On HPUX 8.05, including types.h can include strings.h
- which declares these as functions. Hence the #ifndef. */
-
-#ifndef HAVE_BCOPY
-#define bcopy(a,b,s) memcpy (b,a,s)
-#define bzero(a,s) memset (a,0,s)
-#define bcmp memcmp
-#endif
-
-#ifdef __hpux
-/* 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
-
-/* 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 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
-
-/* Include the file bsdtty.h, since this machine has job control. */
-#define NEED_BSDTTY
-
-/* 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 machine description file.
-*/
-
-/* no underscore please */
-#define LDAV_SYMBOL "avenrun"
-
-#if 0 /* Supposedly no longer true. */
-/* 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
-
-/* On USG systems these have different names. */
-
-#define index strchr
-#define rindex strrchr
-
-#endif /* __hpux */
diff --git a/src/m/hp9000s300.h b/src/m/hp9000s300.h
deleted file mode 100644
index e4db86a959a..00000000000
--- a/src/m/hp9000s300.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/* machine description file for hp9000 series 200 or 300 on either HPUX or BSD.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-HP 9000 series 200 or 300 (-machine=hp9000s300)
-
- These machines are 68000-series CPUs running HP-UX
- (a derivative of sysV with some BSD features) or BSD 4.3 ported by Utah.
-
- If you're running HP-UX, specify `-opsystem=hpux'.
- If you're running BSD, specify `-opsystem=bsd4-3'.
-NOTE-END */
-
-/* I don't understand why we have to do this at all! -JimB */
-#if 0
-
-/* Do this here at the top of the file; including sys/wait.h may
- include <endian.h>, which defines BIG_ENDIAN, which will conflict
- with our definition of BIG_ENDIAN if we do this at the bottom. */
-#ifndef NOT_C_CODE
-#ifndef NO_SHORTNAMES
-#include <sys/wait.h>
-#define WAITTYPE int
-#endif
-#define WRETCODE(w) (((w) >> 8) & 0377)
-#endif
-
-#endif
-
-/* 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 */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically. */
-
-#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
-
-/* 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 implementation 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 m68000
-
-#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"
-
-/* 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))
-
-#ifdef __GNUC__
-#define HAVE_ALLOCA
-#endif
-
-/* 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
-
-/* Need a TEXT_START. On the HP9000/s300 that is 0. */
-#ifdef __GNUC__
-#define TEXT_START 0
-#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/i860.h b/src/m/i860.h
deleted file mode 100644
index f1ce0c04fb1..00000000000
--- a/src/m/i860.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* machine description file for i860.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="<name of system .h file here, without the s- or .h>" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- Ones defined so far include vax, m68000, ns16000, pyramid,
- orion, tahoe, APOLLO and many others */
-
-#define INTEL860
-
-/* 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
-
-/* The X11 include files for i860-sysv4 need the macro SVR4 defined.
- --Kaveh Ghazi (ghazi@noc.rutgers.edu) 8/9/94. */
-#ifdef USG5_4
-#ifndef SVR4
-#define SVR4
-#endif
-#endif
diff --git a/src/m/ibm370aix.h b/src/m/ibm370aix.h
deleted file mode 100644
index 57b5ff67b9d..00000000000
--- a/src/m/ibm370aix.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* m/ file for IBM 370 running AIX. */
-
-#include "ibmps2-aix.h"
-
-#define AIX
-
-/* Include unistd.h, even though we don't define POSIX. */
-#define NEED_UNISTD_H
-
-/* these were defined in "ibmps2-aix.h" */
-#undef INTEL386
-#undef aix386
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-#undef TEXT_START
-#undef SEGMENT_MASK
-#undef DATA_SECTION_ALIGNMENT
-
-#define TEXT_START 0
-#define SEGMENT_MASK 0
-#define DATA_SECTION_ALIGNMENT 0x00001000
-
-#undef LOAD_AVE_CVT
-#undef LOAD_AVE_TYPE
-/* Data type of load average, as read out of kmem. */
-#define LOAD_AVE_CVT(x) (int)(((double) (x)) * 100.0 / 1.0)
-#define LOAD_AVE_TYPE double
-
-#undef LIBS_MACHINE
-#define LIBS_MACHINE
-#undef HAVE_VFORK
-
-#undef LD_SWITCH_MACHINE
-#define LD_SWITCH_MACHINE -xa
diff --git a/src/m/ibmps2-aix.h b/src/m/ibmps2-aix.h
deleted file mode 100644
index 72587ae31ae..00000000000
--- a/src/m/ibmps2-aix.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
- Use -opsystem=usg5-3 on AIX 1.2.
- -opsystem=usg5-2-2 should work on either AIX 1.1 or 1.2, but may not
- work with certain new X window managers, and may be suboptimal.
-NOTE-END */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- Ones defined so far include vax, m68000, ns16000, pyramid,
- orion, tahoe, APOLLO and many others */
-
-#define INTEL386
-#define aix386
-
-#define IBMAIX
-
-/* 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_VFORK
-#undef HAVE_TERMIO
-#define HAVE_TERMIOS
-
-/* Send signals to subprocesses by "typing" special chars at them. */
-
-#define SIGNALS_VIA_CHARACTERS
-
-/*
- * 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 NONSYSTEM_DIR_LIBRARY to make Emacs emulate
- * The 4.2 opendir, etc., library functions.
- */
-#undef NONSYSTEM_DIR_LIBRARY
-
-/* AIX utimes allegedly causes SIGSEGV. */
-#undef HAVE_UTIMES /* override configuration decision */
-
-/* AIX defines FIONREAD, but it does not work. */
-#define BROKEN_FIONREAD
-
-/* 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)
-
-/* 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
-
-/* sioctl.h should not be included, says bytheway@cs.utah.edu. */
-#undef NEED_SIOCTL
-/* I'm guessing that that means it doesn't want ptem.h either. */
-#undef NEED_PTEM_H
-
-/* aix has `union wait' */
-#define HAVE_UNION_WAIT
-
-/* Here override various assumptions in ymakefile */
-
-/* Define C_ALLOCA if this machine does not support a true alloca
- and the one written in C should be used instead.
- Define HAVE_ALLOCA to say that the system provides a properly
- working alloca function and it should be used.
- Define neither one if an assembler-language alloca
- in the file alloca.s should be used. */
-
-#ifdef __GNUC__
-#define HAVE_ALLOCA
-#define alloca(n) __builtin_alloca(n)
-#if __GNUC__ < 2
-#define LIB_STANDARD /usr/local/lib/gcc-gnulib -lbsd -lrts -lc
-#endif
-/* -g fails to work, so it is omitted. */
-/* tranle says that -fstrength-reduce does not help. */
-#define C_DEBUG_SWITCH
-#else
-#define C_ALLOCA
-#define STACK_DIRECTION -1 /* tell alloca.c which way it grows */
-#define LIBS_MACHINE -lbsd -lrts
-#endif
-
-#define OBJECTS_MACHINE hftctl.o
-#define LD_SWITCH_MACHINE -T0x00400000 -K -e start
-#define LIBS_DEBUG /* no -lg on aix ps/2 */
-
-#ifdef USG5_3
-#define XICCC
-#define HAVE_GETWD
-#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 BROKEN_TIOCGWINSZ
-#undef LIBX10_SYSTEM
-#undef LIBX11_SYSTEM
-#undef LIB_X11_LIB
-#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. */
-#define USG_SHARED_LIBRARIES /* Assume that by 19's release everyone has this. */
-
-#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
deleted file mode 100644
index 13ea5324955..00000000000
--- a/src/m/ibmrs6000.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="aix3-1" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#ifdef USG5_4
-#undef WORDS_BIG_ENDIAN
-#else
-#define WORDS_BIG_ENDIAN
-#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
-
-/* 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. */
-#ifdef USG5_4
-#define CANNOT_DUMP
-#endif
-
-#ifndef UNEXEC
-#define UNEXEC unexaix.o
-#endif
-
-/* Define addresses, macros, change some setup for dump */
-
-#define NO_REMAP
-
-#ifndef USG5_4
-#define TEXT_START 0x10000000
-#define TEXT_END 0
-#define DATA_START 0x20000000
-#define DATA_END 0
-#endif
-
-/* 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. */
-
-#ifndef USG5_4
-#define DATA_SEG_BITS 0x20000000
-#else
-#define DATA_SEG_BITS 0
-#endif
-
-#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. */
-
-/* Note: aix3-2.h defines HAVE_ALLOCA; aix3-1.h doesn't. */
-#ifndef HAVE_ALLOCA
-#define C_ALLOCA
-#define STACK_DIRECTION -1 /* tell alloca.c which way it grows */
-#endif
-
-/* Specify the font for X to use.
- This used to be Rom14.500; that's nice on the X server shipped with
- the RS/6000, but it's not available on other servers. */
-#define X_DEFAULT_FONT "fixed"
-
-/* Here override various assumptions in ymakefile */
-
-#ifdef AIXHFT
-#define OBJECTS_MACHINE hftctl.o
-#endif
-
-#ifndef USG5_4
-#define C_SWITCH_MACHINE -D_BSD
-#endif
-
-#ifdef AIX3_2
-/* -lpthreads seems to be necessary for Xlib in X11R6, and should be harmless
- on older versions of X where it happens to exist. */
-#ifdef HAVE_LIBPTHREADS
-#define LIBS_MACHINE -lrts -lIM -liconv -lpthreads
-#else
-/* IBM's X11R5 use -lIM and -liconv in AIX 3.2.2. */
-#define LIBS_MACHINE -lrts -lIM -liconv
-#endif
-#else
-#ifdef USG5_4
-#define LIBS_MACHINE
-#else
-#define LIBS_MACHINE -lIM
-#endif
-#endif
-
-#define START_FILES
-#define HAVE_SYSVIPC
-#define HAVE_GETWD
-/*** BUILD 9008 - FIONREAD problem still exists in X-Windows. ***/
-#define BROKEN_FIONREAD
-
-/* Don't try to include sioctl.h or ptem.h. */
-#undef NEED_SIOCTL
-#undef NEED_PTEM_H
-
-#define ORDINARY_LINK
-
-#ifndef USG5_4
-/* sfreed@unm.edu says add -bI:/usr/lpp/X11/bin/smt.exp for AIX 3.2.4. */
-/* marc@sti.com (Marc Pawliger) says ibmrs6000.inp is needed to avoid
- linker error for updated X11R5 libraries, which references pthread library
- which most machines don't have. We use the name .inp instead of .imp
- because .inp is a better convention to use in make-dist for naming
- random input files. */
-#ifdef AIX4
-#define LD_SWITCH_MACHINE -Wl,-bnodelcsect
-#else /* not AIX4 */
-#ifdef HAVE_AIX_SMT_EXP
-#define LD_SWITCH_MACHINE -Wl,-bnso,-bnodelcsect,-bI:/lib/syscalls.exp,-bI:$(srcdir)/m/ibmrs6000.inp,-bI:/usr/lpp/X11/bin/smt.exp
-#else
-#define LD_SWITCH_MACHINE -Wl,-bnso,-bnodelcsect,-bI:/lib/syscalls.exp,-bI:$(srcdir)/m/ibmrs6000.inp
-#endif
-#endif /* not AIX4 */
-
-/* Avoid gcc 2.7.x collect2 bug by using /bin/ld instead. */
-#if __GNUC__ == 2 && __GNUC_MINOR__ == 7
-#define LD_SWITCH_SITE -B/bin/
-#endif
-
-/* AIX supposedly doesn't use this interface, but on the RS/6000
- it apparently does. */
-#define NLIST_STRUCT
-#endif /* USG5_4 */
diff --git a/src/m/ibmrt-aix.h b/src/m/ibmrt-aix.h
deleted file mode 100644
index 6c655ea67fc..00000000000
--- a/src/m/ibmrt-aix.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically. */
-
-#ifndef IBMAIX
-#define IBMAIX
-#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))
-
-/* This is the offset of the executable's text, from the start of the file. */
-
-#define A_TEXT_SEEK(HDR) (N_TXTOFF (hdr) + sizeof (hdr))
-
-/* Define C_ALLOCA if this machine does not support a true alloca
- and the one written in C should be used instead.
- Define HAVE_ALLOCA to say that the system provides a properly
- working alloca function and it should be used.
- Define neither one if an assembler-language alloca
- in the file alloca.s should be used. */
-
-#define C_ALLOCA
-#define STACK_DIRECTION -1 /* tell alloca.c which way it grows */
-
-/* AIX has PTYs, so define here, along with macros needed to make them work. */
-
-#define HAVE_PTYS
-#define PTY_ITERATION for (i=0; i<256; i++)
-#define PTY_NAME_SPRINTF sprintf (ptyname, "/dev/ptc%d", i);
-
-#define PTY_TTY_NAME_SPRINTF \
-{ /* Check that server side not already open */ \
- if ((ioctl (*ptyv, PTYSTATUS, 0) & 0xFFFF) != 0) \
- { \
- close (*ptyv); \
- continue; \
- } \
- /* And finally to be sure we can open it later */ \
- sprintf (ptyname, "/dev/pts%d", i); \
- signal (SIGHUP,SIG_IGN); \
-} /* ignore hangup at process end */
-
-/* TIOCNOTTY doesn't occur on AIX, but the rest
- of the conditionalized code in process.c does
- the right thing if we fake this out. */
-#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_SYSTEM 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 -lX -lrts
-*/
-
-#define C_SWITCH_MACHINE -I/usr/include -I/usr/include/bsd -Nn2000
-#define LIBS_MACHINE -lXMenu -lX -lsock -lbsd -lrts
-
-#define OBJECTS_MACHINE hftctl.o
-#define START_FILES /lib/crt0.o
-/* -lXMenu, -lX must precede -lsock, -lbsd */
-#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 */
-
-#include </usr/include/bsd/BSDtoAIX.h>
-#define BSTRING
-#define HAVE_GETTIMEOFDAY
-#define HAVE_VFORK
-
-/* AIX utimes allegedly causes SIGSEGV. */
-#undef HAVE_UTIMES /* override configuration decision */
-
-/* AIX defines FIONREAD, but it does not work. */
-#define BROKEN_FIONREAD
-
-/* rocky@watson.ibm.com says this is needed. */
-#define HAVE_FTIME
diff --git a/src/m/ibmrt.h b/src/m/ibmrt.h
deleted file mode 100644
index e9404d125c1..00000000000
--- a/src/m/ibmrt.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-#define WORD_MACHINE
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically. */
-
-#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 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
-
-/* 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. */
-
-#ifndef __GNUC__
-#define C_SWITCH_MACHINE -Dalloca=_Alloca
-#endif
-
-/* 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
-
-/* Use the bitmap files that come with Emacs. */
-#define EMACS_BITMAP_FILES
diff --git a/src/m/intel386.h b/src/m/intel386.h
deleted file mode 100644
index fd2aac37376..00000000000
--- a/src/m/intel386.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/* Machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Intel 386 (-machine=intel386 or -machine=is386.h)
-
- The possibilities for -opsystem are: bsd4-2, usg5-2-2, usg5-3,
- isc2-2, 386-ix, esix, linux, sco3.2v4, and xenix.
-
- 18.58 should support a wide variety of operating systems.
- Use isc2-2 for Interactive 386/ix version 2.2.
- Use 386ix for prior versions.
- Use esix for Esix.
- Use linux for Linux.
- It isn't clear what to do on an SCO system.
-
- -machine=is386 is used for an Integrated Solutions 386 machine.
- It may also be correct for Microport systems.
-
-Cubix QBx/386 (-machine=intel386 -opsystem=usg5-3)
-
- Changes merged in 19.1. Systems before 2/A/0 may fail to compile etags.c
- due to a compiler bug.
-
-Prime EXL (-machine=intel386 -opsystem=usg5-3)
-
- Minor changes merged in 19.1.
-NOTE-END */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- Ones defined so far include vax, m68000, ns16000, pyramid,
- orion, tahoe, APOLLO and many others */
-
-#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 SOLARIS2
-/* 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))
-
-/* J.W.Hawtin@lut.ac.uk say Solaris 2.4 as well as Solaris 2.1 on X86
- requires -lkvm as well */
-#define LIBS_MACHINE -lkvm
-
-#ifndef SOLARIS2_4
-/* J.W.hawtin@lut.ac.uk says Solaris 2.1 on the X86 has FSCALE defined in a
- system header. */
-
-#define HAVE_VFORK
-
-#else /* SOLARIS2_4 */
-#ifndef __GNUC__
-#if 0 /* wisner@gryphon.com says this screws up cpp */
-#define C_SWITCH_MACHINE -Xa
-#endif
-#ifndef NOT_C_CODE
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif /* HAVE_ALLOCA_H */
-#endif /* not NOT_C_CODE */
-#endif /* not __GNUC__ */
-#endif /* SOLARIS2_4 */
-
-/* configure thinks solaris X86 has gethostname, but it does not work,
- so undefine it. */
-#undef HAVE_GETHOSTNAME
-
-#else /* not SOLARIS2 */
-#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
-#endif /* not SOLARIS2 */
-
-/* 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 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 */
-
-/* this brings in alloca() if we're using cc */
-#ifdef USG
-#ifndef LIB_STANDARD
-#ifdef USG5_4
-#define LIB_STANDARD -lc
-#else /* not USG5_4 */
-#define LIB_STANDARD -lPW -lc
-#endif /* not USG5_4 */
-#endif /* LIB_STANDARD */
-
-#define HAVE_ALLOCA
-#define NO_REMAP
-#define TEXT_START 0
-#endif /* USG */
-#endif /* not XENIX */
-
-#ifdef BSD_SYSTEM
-#define HAVE_ALLOCA
-#endif /* BSD_SYSTEM */
-
-/* If compiling with GCC, let GCC implement alloca. */
-#if defined(__GNUC__) && !defined(alloca)
-#define alloca(n) __builtin_alloca(n)
-#define HAVE_ALLOCA
-#endif
-
-#ifdef USG5_4
-#define DATA_SEG_BITS 0x08000000
-#endif
-
-#ifdef MSDOS
-#define NO_REMAP
-#endif
-
-#ifdef WINDOWSNT
-#define VIRT_ADDR_VARIES
-#define DATA_END get_data_end ()
-#define DATA_START get_data_start ()
-#define HAVE_ALLOCA
-#define NO_ARG_ARRAY
-#endif
-
-#ifdef linux
-/* libc-linux/sysdeps/linux/i386/ulimit.c says that due to shared library, */
-/* we cannot get the maximum address for brk */
-#define ULIMIT_BREAK_VALUE (32*1024*1024)
-
-#define SEGMENT_MASK ((SEGMENT_SIZE)-1)
-#endif
diff --git a/src/m/iris4d.h b/src/m/iris4d.h
deleted file mode 100644
index 129206d0e80..00000000000
--- a/src/m/iris4d.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/* machine description file for Iris-4D machines. Use with s/irix*.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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-#undef 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 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 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
-
-/* jg@genmagic.genmagic.com (John Giannandrea) says this is unnecessary. */
-#if 0
-/* 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)
-
-/* s-iris3-6.h uses /vmunix */
-
-#undef KERNEL_FILE
-#define KERNEL_FILE "/unix"
-#endif
-
-/* 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 */ /* Sjoerd.Mullender@cwi.nl says no need. */
-/* #define HAVE_ALLOCA */
-
-/* Define NO_REMAP if memory segmentation makes it not work well
- to change the boundary between the text section and data section
- when Emacs is dumped. If you define this, the preloaded Lisp
- 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. */
-
-#ifdef USG5_4
-#undef UNEXEC
-#define UNEXEC unexsgi.o
-#else
-#define UNEXEC unexmips.o
-#endif
-
-#define TEXT_START 0x400000
-
-/*
- * DATA_SEG_BITS forces extra bits to be or'd in with any pointers which
- * were stored in a Lisp_Object (as Emacs uses fewer than 32 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. */
-#if defined(__GNUC__) && defined(_ABIN32)
-#define LIBS_MACHINE
-#else
-#define LIBS_MACHINE -lmld
-#endif
-#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
-
-#ifndef USG5_4
-#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 -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 -lc
-#endif
-#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 */
-
-#undef STACK_DIRECTION
-#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) << BITS_PER_INT-VALBITS) >> BITS_PER_INT-VALBITS)
-
-#define XSET(var, type, ptr) \
- ((var) = ((int)(type) << VALBITS) + (((unsigned) (ptr) << BITS_PER_INT-VALBITS) >> BITS_PER_INT-VALBITS))
-
-#define XMARKBIT(a) ((a) < 0)
-#define XSETMARKBIT(a,b) ((a) = ((a) & ~MARKBIT) | ((b) ? MARKBIT : 0))
-#define XUNMARK(a) ((a) = (((unsigned)(a) << BITS_PER_INT-GCTYPEBITS-VALBITS) >> BITS_PER_INT-GCTYPEBITS-VALBITS))
-
-#ifndef __GNUC__
-/* Turn off some "helpful" error checks for type mismatches
- that we can't fix without breaking other machines. */
-#ifdef IRIX_FORCE_32_BITS
-#ifdef THIS_IS_MAKEFILE
-#define C_SWITCH_MACHINE -32
-#endif
-#endif
-
-#endif /* not __GNUC__ */
diff --git a/src/m/iris5d.h b/src/m/iris5d.h
deleted file mode 100644
index 9614d53bd5d..00000000000
--- a/src/m/iris5d.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/* machine description file for Iris-5D machines. Use with s-iris3-6.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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="irix3-3" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-#undef 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 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 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)
-
-/* s-iris3-6.h uses /vmunix */
-
-#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. */
-
-#ifdef UNEXEC
-#undef UNEXEC
-#endif
-#define UNEXEC unexsgi.o
-
-#define TEXT_START 0x400000
-
-/*
- * DATA_SEG_BITS forces extra bits to be or'd in with any pointers which
- * were stored in a Lisp_Object (as Emacs uses fewer than 32 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. */
-#if defined(__GNUC__) && defined(_ABIN32)
-#define LIBS_MACHINE -lsun
-#else
-#define LIBS_MACHINE -lsun -lmld
-#endif
-
-#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
-
-/* sioctl.h should be included where appropriate. */
-
-#define NEED_SIOCTL
-
-/* 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) << BITS_PER_INT-VALBITS) >> BITS_PER_INT-VALBITS)
-
-#define XSET(var, type, ptr) \
- ((var) = ((int)(type) << VALBITS) + (((unsigned) (ptr) << BITS_PER_INT-VALBITS) >> BITS_PER_INT-VALBITS))
-
-#define XMARKBIT(a) ((a) < 0)
-#define XSETMARKBIT(a,b) ((a) = ((a) & ~MARKBIT) | ((b) ? MARKBIT : 0))
-#define XUNMARK(a) ((a) = (((unsigned)(a) << BITS_PER_INT-GCTYPEBITS-VALBITS) >> BITS_PER_INT-GCTYPEBITS-VALBITS))
-
-#ifndef __GNUC__
-/* 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
deleted file mode 100644
index 9de72155458..00000000000
--- a/src/m/irist.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-NOTE-START
-Version 18 said to work; use -opsystem=irist3-5 for system version 2.5
-and -opsystem=iris3-6 for system versions 3.6 and up.
-NOTE-END */
-
-#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 */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- Ones defined so far include vax, m68000, ns16000, pyramid,
- orion, tahoe, APOLLO and many others */
-
-#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
deleted file mode 100644
index 45f9273e910..00000000000
--- a/src/m/is386.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* machine description file for Integrated Solutions 386 machine. */
-
-#include "intel386.h"
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Intel 386 (-machine=intel386 or -machine=is386.h)
-
- The possibilities for -opsystem are: bsd4-2, usg5-2-2, usg5-3,
- isc2-2, 386-ix, esix, or xenix.
-
- 18.58 should support a wide variety of operating systems.
- Use isc2-2 for Interactive 386/ix version 2.2.
- Use 386ix for prior versions.
- Use esix for Esix. It isn't clear what to do on an SCO system.
-
- -machine=is386 is used for an Integrated Solutions 386 machine.
- It may also be correct for Microport systems.
-NOTE-END */
-
-#define LIBX10_MACHINE -lnsl_s
-#define LIBX11_MACHINE -lnsl_s
-
-#define LIBS_DEBUG -lg
diff --git a/src/m/isi-ov.h b/src/m/isi-ov.h
deleted file mode 100644
index beb3fdd122a..00000000000
--- a/src/m/isi-ov.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Use `-opsystem=bsd4-2' or `-opsystem=bsd4-3'.
-NOTE-END */
-
-#define ISI68K
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* 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/m68k.h b/src/m/m68k.h
deleted file mode 100644
index d2a1ebff743..00000000000
--- a/src/m/m68k.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* Machine description file for generic Motorola 68k.
- Copyright (C) 1985, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following three symbols give information on
- the size of various data types. */
-
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically. */
-
-#ifndef m68k
-#define m68k
-#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
-
-/* 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 linux
-#ifdef __ELF__
-#define DATA_SEG_BITS 0x80000000
-#endif
-
-#define NO_REMAP
-#define TEXT_START 0
-#endif
-
-/* If compiling with GCC, let GCC implement alloca. */
-#if defined(__GNUC__) && !defined(alloca)
-#define alloca(n) __builtin_alloca(n)
-#define HAVE_ALLOCA
-#endif
diff --git a/src/m/masscomp.h b/src/m/masscomp.h
deleted file mode 100644
index 5f9aa6ae50b..00000000000
--- a/src/m/masscomp.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="rtu" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#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
-
-/* 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
deleted file mode 100644
index b67e3573293..00000000000
--- a/src/m/mega68.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* XINT must explicitly sign-extend */
-
-#define EXPLICIT_SIGN_EXTEND
-
-/* 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
deleted file mode 100644
index 13e4dbeb8bf..00000000000
--- a/src/m/mg1.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-We are in the dark about what operating system runs on the Whitechapel
-systems. Consult share-lib/MACHINES for information on which
-operating systems Emacs has already been ported to; one of them might
-work. If you find an existing system name that works or write your
-own configuration files, please let the Free Software Foundation in on
-your work; we'd like to distribute this information.
-NOTE-END */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-/* 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
-
-/* 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 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 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 sequent.h */
diff --git a/src/m/mips-siemens.h b/src/m/mips-siemens.h
deleted file mode 100644
index eb30cf88c68..00000000000
--- a/src/m/mips-siemens.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/* m- file for Mips machines.
- Copyright (C) 1987, 1992, 1993, 1995 Free Software Foundation, Inc.
-
- This file contains some changes for our SVR4 based SINIX-Mips 5.4.
- I hope this is helpful to port the emacs to our RM?00 series and
- maybe to the DC/OSx (Mips-based) machines of Pyramid Inc.
- (Marco.Walther@mch.sni.de)
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Use m-mips4.h for RISCOS version 4; use s-bsd4-3.h with the BSD world.
-Note that the proper m- file for the Decstation is m-pmax.h.
-This is the m- file for SNI RM*00 machines. Use s- sinix5-4.h file!
-With this the file mips-siemens.h is obsolete.
-NOTE-END */
-
-/* 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)
-
-/* CDC EP/IX 1.4.3 uses /unix */
-
-#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. */
-
-#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
-
-/* Describe layout of the address space in an executing process. */
-/* MARCO ???
-*/
-#define TEXT_START 0x400000
-/*
-#define DATA_START 0x10000000
-#define DATA_SEG_BITS 0x10000000
-*/
-#ifdef UNEXEC
-#undef UNEXEC
-#endif
-#define UNEXEC unexsni.o
-
-#undef ORDINARY_LINK
-
-#undef LIBS_DEBUG
-
-/* Alter some of the options used when linking. */
-
-#define LIBS_MACHINE -lmld
-#define START_FILES pre-crt0.o /usr/ccs/lib/crt1.o /usr/ccs/lib/crti.o /usr/ccs/lib/values-Xt.o
-
-#ifdef LIB_STANDARD
-#undef LIB_STANDARD
-#endif
-#define LIB_STANDARD -lc /usr/ccs/lib/crtn.o
-
-#ifdef __GNUC__
-#define C_DEBUG_SWITCH
-#define C_OPTIMIZE_SWITCH -O
-#define LD_SWITCH_MACHINE
-#else
-#define C_DEBUG_SWITCH -DSYSV
-#define C_OPTIMIZE_SWITCH -DSYSV
-#define LD_SWITCH_MACHINE
-#endif
-
-#if defined(HAVE_X_WINDOWS) && defined(HAVE_X11)
-#define HAVE_VFORK /* Graciously provided by libX.a */
-#endif
-
-
-/* The standard definitions of these macros would work ok,
- but these are faster because the constants are short. */
-
-#define XUINT(a) (((unsigned)(a) << (BITS_PER_INT-VALBITS)) >> (BITS_PER_INT-VALBITS))
-
-#define XSET(var, type, ptr) \
- ((var) = \
- ((int)(type) << VALBITS) \
- + (((unsigned) (ptr) << (BITS_PER_INT-VALBITS)) >> (BITS_PER_INT-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) << (BITS_PER_INT-GCTYPEBITS-VALBITS)) \
- >> (BITS_PER_INT-GCTYPEBITS-VALBITS)))
-
diff --git a/src/m/mips.h b/src/m/mips.h
deleted file mode 100644
index b51581791fd..00000000000
--- a/src/m/mips.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/* m- file for Mips machines.
- Copyright (C) 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Use m-mips4.h for RISCOS version 4; use s-bsd4-3.h with the BSD world.
-Note that the proper m- file for the Decstation is m-pmax.h.
-NOTE-END */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-#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)
-
-/* CDC EP/IX 1.4.3 uses /unix */
-
-#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. */
-
-#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. */
-
-#undef UNEXEC
-#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. */
-
-#ifndef NEWSOS5
-#ifdef BSD_SYSTEM
-
-/* DECstations don'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_SYSTEM */
-
-#if defined(__GNUC__) && defined(_ABIN32)
-#define LIBS_MACHINE
-#else
-#define LIBS_MACHINE -lmld
-#endif
-
-#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 BSD_SYSTEM */
-#endif /* not NEWSOS5 */
-
-/* The standard definitions of these macros would work ok,
- but these are faster because the constants are short. */
-
-#define XUINT(a) (((unsigned)(a) << (BITS_PER_INT-VALBITS)) >> (BITS_PER_INT-VALBITS))
-
-#define XSET(var, type, ptr) \
- ((var) = \
- ((int)(type) << VALBITS) \
- + (((unsigned) (ptr) << (BITS_PER_INT-VALBITS)) >> (BITS_PER_INT-VALBITS)))
-
-#define XUNMARK(a) \
- ((a) = \
- (((unsigned)(a) << (BITS_PER_INT-GCTYPEBITS-VALBITS)) \
- >> (BITS_PER_INT-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
-
-#if defined(emacs) && !defined(INHIBIT_BSD_TIME)
-#include <bsd/sys/time.h>
-#endif
-
-/* The `select' in the system won't work for pipes, so don't use it. */
-#undef HAVE_SELECT /* override configuration decision */
-
-#define HAVE_GETWD
-#define HAVE_GETTIMEOFDAY
-
-#define HAVE_PTYS
-#define HAVE_SOCKETS
-
-#undef NOMULTIPLEJOBS
-
-/* ??? */
-#define IRIS
-
-#endif /* USG */
-
-#ifdef BSD_SYSTEM
-#define COFF
-#define TERMINFO
-#undef MAIL_USE_FLOCK /* Someone should check this. */
-#undef HAVE_UNION_WAIT
-#endif /* BSD_SYSTEM */
-
-#endif /* not NEWSOS5 */
diff --git a/src/m/mips4.h b/src/m/mips4.h
deleted file mode 100644
index 33905072ac0..00000000000
--- a/src/m/mips4.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* machine description file for Mips running RISCOS version 4. */
-
-#include "mips.h"
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Use -opsystem=usg5-2-2 normally, or -opsystem=bsd4-3 with the BSD
-world.
-NOTE-END */
-
-#if 0
-/* Define MIPS2 if you have an R6000 or R4000. */
-#define MIPS2
-#endif
-
-#ifdef __GNUC__
-#define C_DEBUG_SWITCH -g -O
-#else
-/* We used to have -systype bsd43, but a configure change
- now takes care of that option. */
-#ifdef MIPS2
-#define C_DEBUG_SWITCH -DMips -g3 -Wf,-XNd4000 -O -Olimit 2000 -mips2
-#else
-#define C_DEBUG_SWITCH -DMips -g3 -Wf,-XNd4000 -O -Olimit 2000
-#endif
-#endif
-
-#ifdef TERMINFO
-#undef TERMINFO
-#endif
-
-#define START_FILES pre-crt0.o /lib/crt1.o
-/* Used to have -lisode, but jlp@math.byu.edu says remove it
- (for RISCOS 4.52). */
-/* ethanb@ptolemy.astro.washington.edu says crtn.o uses _ctype
- and therefore we must search libc again after crtn.o.
- The -L is used to force second -lc to find the sysv version
- of libc.a, which is needed because the BSD libc.a
- doesn't have _ctype. */
-#define LIB_STANDARD -lmld -lc /lib/crtn.o -L/usr/lib -lc
-
-
-#define COFF
-#undef LD_SWITCH_MACHINE
-#define LD_SWITCH_MACHINE -systype bsd43 -g3 -D 800000
-
-#define NO_MODE_T
-
-/* These are needed on Riscos 4.0.
- It appears that's the only system which uses mips4.h and defines BSD. */
-#ifdef BSD_SYSTEM
-#undef HAVE_STRERROR
-#undef HAVE_XRMSETDATABASE
-#undef HAVE_XSCREENRESOURCESTRING
-#undef HAVE_SETSID
-#endif
diff --git a/src/m/ncr386.h b/src/m/ncr386.h
deleted file mode 100644
index 2599456a873..00000000000
--- a/src/m/ncr386.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#include "intel386.h"
-
-#ifndef __GNUC__
-/* Allow emacs to link with "bcopy()" unresolved. Works around a
- problem where /usr/lib/libX11.so provides bcopy, but
- /usr/ccs/lib/libX11.so does not. */
-#define LD_SWITCH_X_DEFAULT -Wl,-z,nodefs
-#else /* __GNUC__ */
-
-/* Assuming we are using GNU ld, pass a -R option to it
- so that shared libraries will be found at execution time
- just as they are found at link time. */
-#define LD_SWITCH_X_DEFAULT -Xlinker LD_SWITCH_X_SITE_AUX
-
-#endif /* __GNUC__ */
diff --git a/src/m/news-risc.h b/src/m/news-risc.h
deleted file mode 100644
index 268d1796ddf..00000000000
--- a/src/m/news-risc.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* news-risc.h is for the "RISC News". */
-
-#include "mips.h"
-
-#ifdef NEWSOS5
-
-/* NEWS-OS 5.0.2 */
-
-#define LIBS_MACHINE -lmld
-
-#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 -non_shared
-#endif
-
-#else /* not NEWSOS5 */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-3" */
-
-#define COFF
-#undef LD_SWITCH_MACHINE
-#define LD_SWITCH_MACHINE -x -D 800000
-
-/* #define C_OPTIMIZE_SWITCH -O2 */
-#define C_OPTIMIZE_SWITCH -O
-
-#ifndef __GNUC__
-#define C_DEBUG_SWITCH -g3
-#endif
-
-#undef TERMINFO
-
-/* We have no mode_t. */
-#define NO_MODE_T
-
-/* Don't use the definitions in m/mips.h. */
-#undef LINKER
-#undef LIBS_MACHINE
-#define LIBS_MACHINE -lmld
-
-#undef KERNEL_FILE
-#define KERNEL_FILE "/vmunix"
-
-#endif /* not NEWSOS5 */
diff --git a/src/m/news.h b/src/m/news.h
deleted file mode 100644
index 8b4c5a8275e..00000000000
--- a/src/m/news.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Use -opsystem=bsd4-2, or -opsystem=bsd4-3 for system release 3.
-NOTE-END */
-
-/* Say this machine is a 68000 */
-
-#ifndef m68000
-#define m68000
-#endif
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* One CRT0 Dummy variable */
-
-#if 0 /* larry@mitra.com says Sony's as doesn't like this. */
-#define CRT0_DUMMIES one_dummy,
-#endif
-
-/* 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
deleted file mode 100644
index 0c3a2466fae..00000000000
--- a/src/m/next.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* Configuration file for the 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Say this machine is a next if not previously defined */
-
-#ifndef NeXT
-#define NeXT
-#endif
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-/* Let the compiler tell us. */
-#ifdef __BIG_ENDIAN__
-#define WORDS_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)
-
-/* 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
-
-/* This avoids a problem in Xos.h when using co-Xist 3.01. */
-#define X_NOT_POSIX
-
-/* 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 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
-
-#if 0 /* ohl@chico.harvard.edu says to do this. */
-/* Compile "strict bsd" to avoid warnings from include files */
-
-#define C_SWITCH_MACHINE -bsd
-#endif
-
-/* Link this program just by running cc. */
-#define ORDINARY_LINK
-
-/* 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
-
-#define LD_SWITCH_MACHINE -X -noseglinkedit
-
-#define environ _environ
-
-#if 0 /* This is ok for NeXT system version 3.0 or above. */
-/* Where to find the kernel, for load average. */
-#define KERNEL_FILE "/mach"
-#endif
-
-/* This should be true for recent NeXT systems. At least since 3.2. */
-#define HAVE_MACH_MACH_H
diff --git a/src/m/nh3000.h b/src/m/nh3000.h
deleted file mode 100644
index c124e1bf6c7..00000000000
--- a/src/m/nh3000.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* machine description for Harris Night Hawk Series 1200 and Series 3000
- MC68030-based systems (FPP on these is custom). These systems are
- also known as "ecx" and "gcx".
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* This file manually constructed for Harris Night Hawk 4000 (and 5000)
- * series Motorola 88100 and 88110 based machines.
- */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="<name of system .h file here, without the s- or .h>" */
-
-/* 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 gcx
-#define gcx
-#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 NO_REMAP if memory segmentation makes it not work well
- to change the boundary between the text section and data section
- when Emacs is dumped. If you define this, the preloaded Lisp
- code will not be sharable; but that's better than failing completely. */
-
-#define NO_REMAP
-
-/* Some really obscure 4.2-based systems (like Sequent DYNIX)
- * do not support asynchronous I/O (using SIGIO) on sockets,
- * even though it works fine on tty's. If you have one of
- * these systems, define the following, and then use it in
- * config.h (or elsewhere) to decide when (not) to use SIGIO.
- *
- * You'd think this would go in an operating-system description file,
- * but since it only occurs on some, but not all, BSD systems, the
- * reasonable place to select for it is in the machine description
- * file.
- */
-
-/* #define NO_SOCK_SIGIO */
diff --git a/src/m/nh4000.h b/src/m/nh4000.h
deleted file mode 100644
index df8c80901b0..00000000000
--- a/src/m/nh4000.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* machine description for Harris NightHawk 88k based machines
- (includes nh4000 and nh5000 machines).
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* This file manually constructed for Harris Night Hawk 4000 (and 5000)
- * series Motorola 88100 and 88110 based machines.
- */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="<name of system .h file here, without the s- or .h>" */
-
-/* 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
-#define m88000
-#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 bit field into an int. In other words, if bit fields
- are always unsigned.
-
- If you use NO_UNION_TYPE, this flag does not matter. */
-
-/* #define EXPLICIT_SIGN_EXTEND */
-
-/* Data type of load average, as read out of kmem. */
-
-#define LOAD_AVE_TYPE long
-
-/* Convert that into an integer that is 100 for a load average of 1.0 */
-
-#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
-
-/* Define CANNOT_DUMP on machines where unexec does not work.
- Then the function dump-emacs will not be defined
- and temacs will do (load "loadup") automatically unless told otherwise. */
-
-/* #define CANNOT_DUMP */
-
-/* Define VIRT_ADDR_VARIES if the virtual addresses of
- pure and impure space as loaded can vary, and even their
- relative order cannot be relied on.
-
- Otherwise Emacs assumes that text space precedes data space,
- numerically. */
-
-/* #define VIRT_ADDR_VARIES */
-
-/* Define C_ALLOCA if this machine does not support a true alloca
- and the one written in C should be used instead.
- Define HAVE_ALLOCA to say that the system provides a properly
- working alloca function and it should be used.
- Define neither one if an assembler-language alloca
- in the file alloca.s should be used. */
-
-/* #define C_ALLOCA */
-#define HAVE_ALLOCA
-
-/* Define NO_REMAP if memory segmentation makes it not work well
- to change the boundary between the text section and data section
- when Emacs is dumped. If you define this, the preloaded Lisp
- code will not be sharable; but that's better than failing completely. */
-
-#define NO_REMAP
-
-/* Some really obscure 4.2-based systems (like Sequent DYNIX)
- * do not support asynchronous I/O (using SIGIO) on sockets,
- * even though it works fine on tty's. If you have one of
- * these systems, define the following, and then use it in
- * config.h (or elsewhere) to decide when (not) to use SIGIO.
- *
- * You'd think this would go in an operating-system description file,
- * but since it only occurs on some, but not all, BSD systems, the
- * reasonable place to select for it is in the machine description
- * file.
- */
-
-/* #define NO_SOCK_SIGIO */
diff --git a/src/m/ns16000.h b/src/m/ns16000.h
deleted file mode 100644
index c9cf4005263..00000000000
--- a/src/m/ns16000.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-For the Encore, use `-opsystem=umax'.
-For a Tektronix 16000 box (a 6130, perhaps?), use `-opsystem=bsd4-2'.
-Use `-machine=ns16000' for both.
-NOTE-END */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* 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. */
-
-#ifndef USG
-#define LOAD_AVE_TYPE double
-#endif
-
-/* Convert that into an integer that is 100 for a load average of 1.0 */
-
-#ifndef USG
-#define LOAD_AVE_CVT(x) ((int) ((x) * 100.0))
-#endif
-
-#ifdef USG
-
-/* Control assembler syntax used in alloca.s. */
-#define NS5
-
-/* On early NS systems ulimit was buggy. If set emacs uses this value
- * for the maximum sbrk value instead of getting it from ulimit.
- */
-#define ULIMIT_BREAK_VALUE 0x7E0000
-
-/* Early NS compilers have this bug. I believe it has been fixed in later
- * releases.
- */
-#define SHORT_CAST_BUG
-
-#define SEGMENT_MASK (NBPS - 1)
-
-/* Variables to get crt0.c to come out correctly */
-#define CRT0_DUMMIES bogus_fp,
-#define DOT_GLOBAL_START
-
-/* Control how emacsclient communicates. */
-#define HAVE_SYSVIPC
-
-/* Set this to /bin/mail unless you have a better mail posting program */
-#define MAIL_PROGRAM_NAME "/usr/local/bin/remail"
-
-/* Tell sysdep.c not to define bzero, etc. */
-#undef BSTRING
-#define BSTRING
-
-/* Macro definitions to emulate BSD functions with SysV ones */
-#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
-
-/* This avoids problems with uninitialized static variables going in .data. */
-#define static
-
-#endif /* USG */
diff --git a/src/m/ns32000.h b/src/m/ns32000.h
deleted file mode 100644
index 9fe59767089..00000000000
--- a/src/m/ns32000.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* machine description file for National 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- Ones defined so far include vax, m68000, ns16000, pyramid,
- orion, tahoe, APOLLO and many others */
-
-/* Use type int rather than a union, to represent Lisp_Object */
-/* This is desirable for most machines. */
-
-#define NO_UNION_TYPE
-
-/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
- the 24-bit bit field into an int. In other words, if bit fields
- are always unsigned.
-
- If you use NO_UNION_TYPE, this flag does not matter. */
-
-#define EXPLICIT_SIGN_EXTEND
-
-/* Data type of load average, as read out of kmem. */
-
-/* #define LOAD_AVE_TYPE long */
-
-/* Convert that into an integer that is 100 for a load average of 1.0 */
-
-/* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */
-
-/* Define CANNOT_DUMP on machines where unexec does not work.
- Then the function dump-emacs will not be defined
- and temacs will do (load "loadup") automatically unless told otherwise. */
-
-/* #define CANNOT_DUMP */
-
-/* Define VIRT_ADDR_VARIES if the virtual addresses of
- pure and impure space as loaded can vary, and even their
- relative order cannot be relied on.
-
- Otherwise Emacs assumes that text space precedes data space,
- numerically. */
-
-/* #define VIRT_ADDR_VARIES */
-
-/* Define C_ALLOCA if this machine does not support a true alloca
- and the one written in C should be used instead.
- Define HAVE_ALLOCA to say that the system provides a properly
- working alloca function and it should be used.
- Define neither one if an assembler-language alloca
- in the file alloca.s should be used. */
-
-/* #define C_ALLOCA */
-#ifdef __NetBSD__
-#define HAVE_ALLOCA
-#endif
-
-/* Define NO_REMAP if memory segmentation makes it not work well
- to change the boundary between the text section and data section
- when Emacs is dumped. If you define this, the preloaded Lisp
- code will not be sharable; but that's better than failing completely. */
-
-/* #define NO_REMAP */
-
-#define TEXT_START 0
-
-#define STACK_DIRECTION -1
-
-#ifndef __NetBSD__
-#define EXEC_MAGIC 0410
-
-#define PURESIZE 140000
-
-#define START_FILES pre-crt0.o /lib/crt0.o
-#endif
diff --git a/src/m/nu.h b/src/m/nu.h
deleted file mode 100644
index ec9ad5f2976..00000000000
--- a/src/m/nu.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* XINT must explicitly sign-extend */
-
-#define EXPLICIT_SIGN_EXTEND
-
-/* 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
deleted file mode 100644
index bfb85cdb6fc..00000000000
--- a/src/m/orion.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_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
-
-/* 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
deleted file mode 100644
index c9f8991ddf3..00000000000
--- a/src/m/orion105.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* 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/paragon.h b/src/m/paragon.h
deleted file mode 100644
index 5c00f7d8d92..00000000000
--- a/src/m/paragon.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* m/ file for Paragon i860 machine. */
-
-#include "i860.h"
-#define COFF
-#define SYSTEM_MALLOC
-#define TEXT_START 0x10000
-#define LIB_STANDARD -lc -lic -lmach
-#define KEEP_OLD_TEXT_SCNPTR
-#define KEEP_OLD_PADDR
-#define drem fmod
diff --git a/src/m/pfa50.h b/src/m/pfa50.h
deleted file mode 100644
index 561ba15bb20..00000000000
--- a/src/m/pfa50.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* Machine description file for PFU A-series.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* 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 needs it.
- */
-
-#define LD_SWITCH_MACHINE -e __start
-
-#if pfa50 || pfa70
-
-/* On A-50/60/70/80, data space has high order byte use. */
-#define VALBITS 26
-#define VALMASK (((1<<VALBITS) - 1) | 0x60000000)
-#define XTYPE(a) ((enum Lisp_Type) (((a) >> VALBITS) & GCTYPEMASK))
-
-#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_PTYS
-#define HAVE_SOCKETS
-
-/* SX/A use SystemV style getdents/readdir. */
-
-/* SX/A does not have sigblock(2) */
-#define sigblock(mask) (0)
-
-#define NO_SIOCTL_H
-
-#undef SIGIO
diff --git a/src/m/plexus.h b/src/m/plexus.h
deleted file mode 100644
index b42c93c285a..00000000000
--- a/src/m/plexus.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#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
-
-/* 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
deleted file mode 100644
index 4ddb857b8e8..00000000000
--- a/src/m/pmax.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* Machine description file for DEC MIPS machines. */
-
-#include "mips.h"
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-The operating system would be either osf1, ultrix, or NetBSD.
-NOTE-END */
-
-#undef WORDS_BIG_ENDIAN
-#undef LIB_STANDARD
-#undef START_FILES
-#undef COFF
-#undef TERMINFO
-#define MAIL_USE_FLOCK
-#define HAVE_UNION_WAIT
-
-
-#ifdef MACH
-#define START_FILES pre-crt0.o /usr/lib/crt0.o
-#else
-/* 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
-#endif
-
-#ifdef __NetBSD__
-#undef START_FILES
-#undef RUN_TIME_REMAP
-#define START_FILES pre-crt0.o /usr/lib/crt0.o
-#define CANNOT_DUMP
-#undef UNEXEC
-#endif /* NetBSD */
-
-/* Supposedly the following will overcome a kernel bug. */
-#undef LD_SWITCH_MACHINE
-#undef DATA_START
-#define DATA_START 0x10000000
-#define DATA_SEG_BITS 0x10000000
-
-#if 0
-/* I don't see any such conflict in Ultrix 4.2, 4.2a, or 4.3. And
- the relocating allocator is a real win. -JimB */
-
-/* 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
-#endif
-
-/* Override what mips.h says about this. */
-#undef LINKER
-
-#ifdef ultrix
-/* 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
-#endif
-
-#if defined (OSF1) || defined (MACH)
-#undef C_ALLOCA
-#define HAVE_ALLOCA
-#endif
-
-#ifndef __NetBSD__
-/* mcc@timessqr.gc.cuny.edu says this makes Emacs work with DECnet. */
-#ifdef HAVE_LIBDNET
-#define LIBS_MACHINE -ldnet
-#endif
-
-/* mcc@timessqr.gc.cuny.edu says it is /vmunix on Ultrix 4.2a. */
-#undef KERNEL_FILE
-#define KERNEL_FILE "/vmunix"
-#endif
-
-#ifdef ultrix
-/* Jim Wilson writes:
- [...] The X11 include files that Dec distributes with Ultrix
- are bogus.
-
- When __STDC__ is defined (which is true with gcc), the X11 include files
- try to define prototypes. The prototypes however use types which haven't
- been defined yet, and thus we get syntax/parse errors.
-
- You can not fix this by changing the include files, because the prototypes
- create circular dependencies, in particular Xutil.h depends on types defined
- in Xlib.h, and Xlib.h depends on types defined in Xutil.h. So, no matter
- which order you try to include them in, it will still fail.
-
- Compiling with -DNeedFunctionPrototypes=0 will solve the problem by
- directly inhibiting the bad prototypes. This could perhaps just be put in
- an a Ultrix configuration file.
-
- Using the MIT X11 distribution instead of the one provided by Dec will
- also solve the problem, but I doubt you can convince everyone to do this. */
-/* Addendum: the MIT X11 distribution neglects to define certain symbols
- when NeedFunctionPrototypes is 0, but still tries to use them when
- NeedVarargsPrototypes is 1 (which is its default value). So if we're
- going to disable non-variadic prototypes, we also need to disable
- variadic prototypes. --kwzh@gnu.ai.mit.edu */
-#define C_SWITCH_X_MACHINE -DNeedFunctionPrototypes=0 -DNeedVarargsPrototypes=0
-#endif
-
-/* Enable a fix in process.c. */
-#define SET_CHILD_PTY_PGRP
diff --git a/src/m/pyramid.h b/src/m/pyramid.h
deleted file mode 100644
index ace92e51ba3..00000000000
--- a/src/m/pyramid.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#ifdef __GNUC__
-#define NO_ARG_ARRAY
-#endif
-
-/* XINT must explicitly sign extend */
-
-#define EXPLICIT_SIGN_EXTEND
-
-/* 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/sequent-ptx.h b/src/m/sequent-ptx.h
deleted file mode 100644
index 112638dbbf1..00000000000
--- a/src/m/sequent-ptx.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/* machine description file for SEQUENT machines running DYNIX/ptx
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="ptx" */
-
-#include "intel386.h"
-
-/* Define how to take a char and sign-extend into an int.
- On machines where char is signed, this is a no-op. */
-/* CHECK THIS */
-#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. */
-
-/* BTW: ptx defines _SEQUENT_, i386 */
-
-/* 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. */
-/* Already defined. Assume prior definition works for PTX. */
-#if 0
-#undef CRT0_DUMMIES
-#define CRT0_DUMMIES dummy1, dummy2, dummy3,
-#endif
-
-/* 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
-#define LOAD_AVE_TYPE unsigned long
-
-/* Convert that into an integer that is 100 for a load average of 1.0 */
-
-#undef FSCALE
-#define FSCALE 1000.0
-#undef LOAD_AVE_CVT
-#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. */
-
-#ifndef __GNUC__
-#define C_ALLOCA
-#undef HAVE_ALLOCA
-#endif
-
-/* Define NO_REMAP if memory segmentation makes it not work well
- to change the boundary between the text section and data section
- when Emacs is dumped. If you define this, the preloaded Lisp
- code will not be sharable; but that's better than failing completely. */
-/* On PTX, can't seem to get a valid executable unless NO_REMAP is
- defined. This did work in the Sequent patched Emacs 18.57. */
-#ifndef NO_REMAP
-#define NO_REMAP
-#endif
-/* #undef NO_REMAP */
-
-/* If a valid PTX executable could be dumped without NO_REMAP defined,
- here's a guess at some defines to make it work. */
-#ifndef NO_REMAP
-
-/* PTX has getpagesize() but it returns 296. Using the default method of
- including getpagesize.h in unexec.c returns 4096 which seems more
- reasonable. */
-#undef HAVE_GETPAGESIZE
-
-/* Override magic number for a.out header. */
-#define EXEC_MAGIC 0411 /* from a.out.h: separated I&D */
-
-#define ADJUST_TEXT_SCNHDR_SIZE
-#define ADJUST_TEXTBASE
-
-/* The file sections in the Symmetry a.out must be on 4K boundaries. */
-/* #define DATA_SECTION_ALIGNMENT (4096-1) */
-
-#endif /* ifndef NO_REMAP */
-
-/* Avoids a compiler bug. */
-#define TAHOE_REGISTER_BUG
-
-/* (short) negative-int doesn't sign-extend correctly. */
-#define SHORT_CAST_BUG
-
-/* Cause compilations to be done in parallel in ymakefile. */
-#define MAKE_PARALLEL $&
-
-/* Use terminfo library. */
-#define LIBS_TERMCAP -ltermlib
-
diff --git a/src/m/sequent.h b/src/m/sequent.h
deleted file mode 100644
index 50b585bc75e..00000000000
--- a/src/m/sequent.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Use -opsystem=bsd4-2, or -opsystem=bsd4-3 on newer systems.
-NOTE-END */
-
-/* NOTE: this file works for DYNIX release 2.0
- (not tested on 1.3) on NS32000's */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- 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))
-
-/* This is the offset of the executable's text, from the start of the file. */
-
-#define A_TEXT_SEEK(HDR) (N_TXTOFF (hdr) + sizeof (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 (ptyname, "/dev/pty%c%c", PTY_MAJOR[ma], PTY_MINOR[mi]);
-#define PTY_TTY_NAME_SPRINTF \
- sprintf (ptyname, "/dev/tty%c%c", PTY_MAJOR[ma], PTY_MINOR[mi]);
diff --git a/src/m/sgi3000.h b/src/m/sgi3000.h
deleted file mode 100644
index 79249b61911..00000000000
--- a/src/m/sgi3000.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "irist.h"
diff --git a/src/m/sparc.h b/src/m/sparc.h
deleted file mode 100644
index 9b3ccf362a5..00000000000
--- a/src/m/sparc.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Use -opsystem=sunos4 for operating system version 4, and
--opsystem=bsd4-2 for earlier versions.
-NOTE-END */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Say this machine is a sparc */
-
-#ifndef sparc
-#define sparc
-#endif
-
-#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
-#ifndef NOT_C_CODE
-#if __GNUC__ < 2 /* Modern versions of GCC handle alloca directly. */
-#include <alloca.h>
-#endif
-#endif
-
-/* Must use the system's termcap, if we use any termcap.
- It does special things. */
-
-#ifndef TERMINFO
-#define LIBS_TERMCAP -ltermcap
-#endif
-
-/* 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 130000
-#endif
-
-#ifndef __NetBSD__
-#ifndef __linux__
-/* This really belongs in s/sun.h. */
-
-/* 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)
-
-/* This is the offset of the executable's text, from the start of the file. */
-
-#define A_TEXT_SEEK(HDR) (N_TXTOFF (hdr) + sizeof (hdr))
-
-#endif /* __linux__ */
-#endif /* __NetBSD__ */
diff --git a/src/m/sps7.h b/src/m/sps7.h
deleted file mode 100644
index 40f67c8b895..00000000000
--- a/src/m/sps7.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* machine description file for Bull SPS-7.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Say this machine is a 68000 */
-
-#ifndef m68000
-#define m68000
-#endif
-
-#define sps7
-
-/* 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. */
-/* Suspect there is something weird about this machine, so turn it off. */
-
-/* #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 SMX
-#define V3x
-
-/*
- * 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
-
-/* Have the socketpair call
-*/
-
-#define SKTPAIR
-
-/* 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
-
-/* Use Berkeley style interface to nlist */
-
-#define NLIST_STRUCT
-
-/* Define this to cause -N to be passed to ld. This is needed
- * in uniplus because of its funny memory space layout.
- * SMX--If you are using 32 bit (COFF) use "-N", else don't use anything.
- */
-
-#define LD_SWITCH_MACHINE -N -T32 -e __start
-
-/* If you are compiling for a 68020, then use -lc32 else use -lc */
-
-#define LIB_STANDARD -lc32
-
-/* Fore 16 bit, -linet, for 32 bit -linet32 (be sure you have it!). */
-
-#define LIBS_MACHINE -linet32
-
-/* Use -T32 for 68020, -T16 otherwise */
-
-#define C_SWITCH_MACHINE -T32
-
-/*
- Here we assume that signal.h is included before config.h
- so that we can override it here. */
-
-#undef SIGIO
-
-/* Other than 68020 use ld16, as32, or undefine (defaults ld and as). */
-
-#define ASS as32
-
-#ifdef V3x
-#define EXEC_MAGIC 0x10b
-#define SEGMENT_MASK (NBPS-1)
-#define ADJUST_EXEC_HEADER f_hdr.f_magic = SMROMAGIC;\
- f_ohdr.stsize = 0;
-#endif
diff --git a/src/m/sr2k.h b/src/m/sr2k.h
deleted file mode 100644
index e735668679a..00000000000
--- a/src/m/sr2k.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/* machine description file for Hitachi SR2001/SR2201 machines.
- Copyright (C) 1996 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="hpux" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-#undef 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 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 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
-
-/* The standard definitions of these macros would work ok,
- but these are faster because the constants are short. */
-
-
-#define XUINT(a) (((unsigned)(a) << BITS_PER_INT-VALBITS) >> BITS_PER_INT-VALBITS)
-
-#define XSET(var, type, ptr) \
- ((var) = ((int)(type) << VALBITS) + (((unsigned) (ptr) << BITS_PER_INT-VALBITS) >> BITS_PER_INT-VALBITS))
-
-#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) << BITS_PER_INT-GCTYPEBITS-VALBITS) >> BITS_PER_INT-GCTYPEBITS-VALBITS))
-#endif
-
-/* Define the BSTRING functions in terms of the sysV functions. */
-/* On HPUX 8.05, including types.h can include strings.h
- which declares these as functions. Hence the #ifndef. */
-
-#ifndef HAVE_BCOPY
-#define bcopy(a,b,s) memcpy (b,a,s)
-#define bzero(a,s) memset (a,0,s)
-#define bcmp memcmp
-#endif
-
-/* #ifdef __hpux */
-/* 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
-
-
-/* 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 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
-
-/* Include the file bsdtty.h, since this machine has job control. */
-/* #define NEED_BSDTTY */
-
-/* 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 machine description file.
-*/
-
-/* no underscore please */
-#define LDAV_SYMBOL "avenrun"
-
-#if 0 /* Supposedly no longer true. */
-/* 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
-
-/* On USG systems these have different names. */
-
-#define index strchr
-#define rindex strrchr
-
-/* #endif */
diff --git a/src/m/stride.h b/src/m/stride.h
deleted file mode 100644
index 3e031ebe859..00000000000
--- a/src/m/stride.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#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
-
-/* 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_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 "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
-
-/* Define this macro if system defines a type `union wait'. */
-
-#define HAVE_UNION_WAIT
diff --git a/src/m/sun1.h b/src/m/sun1.h
deleted file mode 100644
index 68a113747e8..00000000000
--- a/src/m/sun1.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Sun 1, 2 and 3 (-machine=sun1, -machine=sun2, -machine=sun3;
- -opsystem=bsd4-2 or -opsystem=sunos4)
-
- Whether you should use sun1, sun2 or sun3 depends on the
- VERSION OF THE OPERATING SYSTEM
- you have. There are three machine types for different versions of
- SunOS. All are derived from Berkeley 4.2, meaning that you should
- use -opsystem=bsd4-2. Emacs 17 has run on all of them. You will
- need to use sun3 on Sun 2's running SunOS release 3.
-
- For SunOS release 4 on a Sun 3, use -machine=sun3 and
- -opsystem=sunos4. See the file share-lib/SUNBUG for how to solve
- problems caused by bugs in the "export" version of SunOS 4.
-NOTE-END */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* 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 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)
-
-/* 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
deleted file mode 100644
index e9267df0967..00000000000
--- a/src/m/sun2.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/* machine description file for Sun 68000's OPERATING SYSTEM version 2.
- Note that "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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Sun 1, 2 and 3 (-machine=sun1, -machine=sun2, -machine=sun3;
- -opsystem=bsd4-2 or -opsystem=sunos4)
-
- Whether you should use sun1, sun2 or sun3 depends on the
- VERSION OF THE OPERATING SYSTEM
- you have. There are three machine types for different versions of
- SunOS. All are derived from Berkeley 4.2, meaning that you should
- use -opsystem=bsd4-2. Emacs 17 has run on all of them. You will
- need to use sun3 on Sun 2's running SunOS release 3.
-
- For SunOS release 4 on a Sun 3, use -machine=sun3 and
- -opsystem=sunos4. See the file share-lib/SUNBUG for how to solve
- problems caused by bugs in the "export" version of SunOS 4.
-NOTE-END */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* 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 ${libsrc}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-68881.h b/src/m/sun3-68881.h
deleted file mode 100644
index b74758fa4fc..00000000000
--- a/src/m/sun3-68881.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* sun3-68881.h, for a Sun 3, using the 68881. */
-
-#include "sun3.h"
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Sun with 68881 co-processor (-machine=sun3-68881;
- -opsystem=bsd4-2 or -opsystem=sunos4)
-
- Versions 1, 2, and 3 of the operating system are derived from
- Berkeley 4.2, meaning that you should use -opsystem=bsd4-2.
-
- For SunOS release 4 on a Sun 3 with a 68881, use -machine=sun3-68881
- and -opsystem=sunos4. See the file share-lib/SUNBUG for how to
- solve problems caused by bugs in the "export" version of SunOS 4.
-NOTE-END */
-
-/* In case we are using floating point, work together with crt0.c. */
-
-#ifndef __GNUC__
-#define C_SWITCH_MACHINE -f68881
-#endif
-
-#define sun_68881
-#define START_FILES crt0.o /usr/lib/Mcrt1.o
diff --git a/src/m/sun3-fpa.h b/src/m/sun3-fpa.h
deleted file mode 100644
index da959cac361..00000000000
--- a/src/m/sun3-fpa.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* sun3-fpa.h, for a Sun 3, using the Sun fpa. */
-
-#include "sun3.h"
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Sun with FPA co-processor (-machine=sun3-fpa;
- -opsystem=bsd4-2 or -opsystem=sunos4)
-
- Versions 1, 2, and 3 of the operating system are derived from
- Berkeley 4.2, meaning that you should use -opsystem=bsd4-2.
-
- For SunOS release 4 on a Sun 3 with an FPA, use -machine=sun3-fpa
- and -opsystem=sunos4. See the file share-lib/SUNBUG for how to
- solve problems caused by bugs in the "export" version of SunOS 4.
-NOTE-END */
-
-/* In case we are using floating point, work together with crt0.c. */
-
-#ifndef __GNUC__
-#define C_SWITCH_MACHINE -ffpa
-#endif
-
-#define sun_fpa
-#define START_FILES crt0.o /usr/lib/Wcrt1.o
diff --git a/src/m/sun3-soft.h b/src/m/sun3-soft.h
deleted file mode 100644
index 05a1e9e7f49..00000000000
--- a/src/m/sun3-soft.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* sun3-soft.h, for a Sun 3, using the Sun with software floating point. */
-
-#include "sun3.h"
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Sun with software floating point (-machine=sun3-soft;
- -opsystem=bsd4-2 or -opsystem=sunos4)
-
- Versions 1, 2, and 3 of the operating system are derived from
- Berkeley 4.2, meaning that you should use -opsystem=bsd4-2.
-
- If you want to use software floating point on SunOS release 4 on a
- Sun 3, use -machine=sun3-68881 and -opsystem=sunos4. See the file
- share-lib/SUNBUG for how to solve problems caused by bugs in the
- "export" version of SunOS 4.
-NOTE-END */
-
-/* In case we are using floating point, work together with crt0.c. */
-
-#ifndef __GNUC__
-#define C_SWITCH_MACHINE -fsoft
-#endif
-
-#define sun_soft
-#define START_FILES crt0.o /usr/lib/Fcrt1.o
diff --git a/src/m/sun3.h b/src/m/sun3.h
deleted file mode 100644
index b20889c25b8..00000000000
--- a/src/m/sun3.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* machine description file for Sun 68000's OPERATING SYSTEM version 3
- (for either 68000 or 68020 systems). */
-
-#include "sun2.h"
-#undef sun2
-#ifndef sun3
-#define sun3
-#endif
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Sun 1, 2 and 3 (-machine=sun1, -machine=sun2, -machine=sun3;
- -opsystem=bsd4-2 or -opsystem=sunos4)
-
- Whether you should use sun1, sun2 or sun3 depends on the
- VERSION OF THE OPERATING SYSTEM
- you have. There are three machine types for different versions of
- SunOS. All are derived from Berkeley 4.2, meaning that you should
- use -opsystem=bsd4-2. Emacs 17 has run on all of them. You will
- need to use sun3 on Sun 2's running SunOS release 3.
-
- For SunOS release 4 on a Sun 3, use -machine=sun3 and
- -opsystem=sunos4. See the file share-lib/SUNBUG for how to solve
- problems caused by bugs in the "export" version of SunOS 4.
-NOTE-END */
-
-/* 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)
-
-/* This is the offset of the executable's text, from the start of the file. */
-
-#define A_TEXT_SEEK(HDR) (N_TXTOFF (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
deleted file mode 100644
index cf9537ea100..00000000000
--- a/src/m/sun386.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* machine description file for Sun's 386-based RoadRunner. This file borrows heavily from
- "sun2.h", but since that file is heavily cpu-specific, it was easier
- not to include it.
-
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
- Use s-sunos4-0.h for operating system version 4.0, and s-sunos4-1.h
- for later versions. See the file share-lib/SUNBUG for how to solve
- problems caused by bugs in the "export" version of SunOS 4.
-NOTE-END */
-
-/* Say this machine is a bird */
-#ifndef roadrunner
-#define roadrunner
-#endif
-
-/* Actual cpu-specific defs */
-#include "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
-
-#ifdef USG
-/* USG detects Solaris. j.w.hawtin@lut.ac.uk says Solaris 2.1
- on the 386 needs this. */
-#define LIBS_MACHINE -lkvm
-#endif
diff --git a/src/m/symmetry.h b/src/m/symmetry.h
deleted file mode 100644
index 2cbb820b2d8..00000000000
--- a/src/m/symmetry.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* machine description file for SEQUENT SYMMETRY 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* CHANGE: [Eric H. Herrin II; eric@ms.uky.edu - 15 Sept 1988]
- * Modified the sequent.h file for the Sequent Symmetry machine.
- * Biggest change was to align the sections in the a.out to 4K
- * boundaries (this is the page size).
- */
-
-
-/* NOTICE: this file works for DYNIX release 3.0.12 on Sequent Symmetry
- * (Intel 80386) machines. Hasn't been tested on anything else.
- */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-3" */
-
-#include "intel386.h"
-
-/* 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 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))
-
-/* This is the offset of the executable's text, from the start of the file. */
-
-#define A_TEXT_SEEK(HDR) (N_TXTOFF (hdr) + sizeof (hdr))
-
-/* The file sections in the Symmetry a.out must be on 4K boundaries.
- */
-#define SEGSIZ 4096
-#define SECTION_ALIGNMENT (SEGSIZ-1)
-
-/* (short) negative-int doesn't sign-extend correctly */
-#define SHORT_CAST_BUG
-
-/* Cause compilations to be done in parallel in ymakefile. */
-#define MAKE_PARALLEL &
-
-/* 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/tad68k.h b/src/m/tad68k.h
deleted file mode 100644
index eddf1456a9a..00000000000
--- a/src/m/tad68k.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-3" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically */
-
-/* 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 (2048-1) /* 2k boundaries required in unexec */
-#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 */
diff --git a/src/m/tahoe.h b/src/m/tahoe.h
deleted file mode 100644
index fdb89244dbe..00000000000
--- a/src/m/tahoe.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-Use -opsystem=bsd4-2 or -opsystem=bsd4-3, depending on the version of
-Berkeley you are running.
-NOTE-END */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* XINT must explicitly sign-extend */
-
-#define EXPLICIT_SIGN_EXTEND
-
-/* 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
diff --git a/src/m/tandem-s2.h b/src/m/tandem-s2.h
deleted file mode 100644
index 405af5c844a..00000000000
--- a/src/m/tandem-s2.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* machine description file for the Tandem Integrity S2. */
-
-#include "mips.h"
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-3" */
-
-/* This overrides some of the usual support for the mips and system V.3. */
-
-/* The operating system apparently defines TIOCGETC
- but it doesn't work. */
-#undef BROKEN_TIOCGETC
-
-/* rs@ai.mit.edu said this was necessary for it to work. However, some
- user of this machine ought to try to get subprocesses to work. */
-#undef subprocesses
-
-/* Correct some library file names. */
-#define START_FILES pre-crt0.o /usr/lib/crt1.o1.31
-#define LIB_STANDARD -lbsd -lc /usr/lib/crtn.o1.31
diff --git a/src/m/targon31.h b/src/m/targon31.h
deleted file mode 100644
index 16f29cac10b..00000000000
--- a/src/m/targon31.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* targon31 machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-#define WORD_MACHINE
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- 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 */
-
-/* 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 */
-/* Supposedly NO_REMAP is not needed with the following change. */
-#define SEGMENT_MASK 0xffff
-
-#define SWITCH_ENUM_BUG 1
diff --git a/src/m/tek4300.h b/src/m/tek4300.h
deleted file mode 100644
index 30ebbc7d36d..00000000000
--- a/src/m/tek4300.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="bsd4-3" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#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
-
-/* 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
-
-/* Use the system's malloc calls, gmalloc.c won't work for us. */
-
-#define SYSTEM_MALLOC
-
-/* In building xmakefile, "cc -E -g" forcibly reads from stdin. Since we
- can't remove the CFLAGS from that "cc -E" invocation, make sure we
- never pass -g. If you want to debug, remove the following, and fix
- src/Makefile.in so it doesn't pass ${CFLAGS} when creating xmakefile. */
-
-#define C_DEBUG_SWITCH
-
-/* eirik@elf.ithaca.ny.us said this was needed in 19.22. */
-#define NO_MODE_T
-
-/* Process groups work in the traditional BSD manner. */
-
-#define BSD_PGRPS
diff --git a/src/m/tekxd88.h b/src/m/tekxd88.h
deleted file mode 100644
index dbda4cb181f..00000000000
--- a/src/m/tekxd88.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* Configuration file for the Tektronix XD88 running UTekV 3.2e,
- contributed by Kaveh Ghazi (ghazi@caip.rutgers.edu) 1/15/93.
- You probably need to use gnu make (version 3.63 or higher.)
- Copyright (C) 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- Ones defined so far include vax, m68000, ns16000, pyramid,
- orion, tahoe, APOLLO and many others */
-#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)
-
-/* 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 */ /* No load average on XD88. */
-/* 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. */
-#ifdef __GNUC__
-# define alloca __builtin_alloca /* Use the gcc builtin alloca() ... */
-# define HAVE_ALLOCA /* ... and be sure that no other ones are tried out. */
-# undef C_ALLOCA
-# define C_OPTIMIZE_SWITCH -O2
-#else /* not __GNUC__ */
-# undef HAVE_ALLOCA
-# define C_ALLOCA /* Use the alloca() supplied in alloca.c. */
-# define STACK_DIRECTION -1 /* The stack grows towards lower addresses. */
-# define C_OPTIMIZE_SWITCH -O
-#endif /* __GNUC__ */
-
-#undef NOMULTIPLEJOBS /* we have job control */
-#define HAVE_SOCKETS /* sockets are available */
-#define BROKEN_FIONREAD /* is this needed ? */
-#define BSTRING /* its in libc but not declared in any header file. */
-#undef sigsetmask /* XD88 has sigsetmask() */
-
-#undef LIB_X11_LIB /* Don't use shared libraries defined in usg5-3.h */
-#undef LIBX11_SYSTEM
-
-#define HAVE_TERMIOS /* We have termios. */
-#undef HAVE_TERMIO /* Make sure termios ifdef code is used, not termio. */
-#define NO_TERMIO /* Don't include both termios.h and termio.h */
-#define HAVE_PTYS /* XD88 SysV has PTYs. */
-#define SYSV_PTYS /* Requires <termios.h> */
-
-#ifdef ghs /* Stands for "Green Hills Software", defined only in /bin/cc */
-/* -X18 means do not allocate programmer-defined local variables to a
- register unless they are declared register. (Copied from perl-4.036
- Green Hills C hints file. Might be needed for setjmp, I don't know.) */
-# define C_SWITCH_MACHINE -X18
-/* We need /lib/default.ld so that /bin/ld can read its link directives. */
-# define LD_SWITCH_SYSTEM /lib/default.ld
-#endif /* ghs */
-
-/* We need this to get dumping to work */
-#define KEEP_OLD_TEXT_SCNPTR
diff --git a/src/m/template.h b/src/m/template.h
deleted file mode 100644
index b6a31d2e18a..00000000000
--- a/src/m/template.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="<name of system .h file here, without the s- or .h>" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#define NO_ARG_ARRAY
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-#define WORD_MACHINE
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- Ones defined so far include vax, m68000, ns16000, pyramid,
- orion, tahoe, APOLLO and many others */
-
-/* Use type int rather than a union, to represent Lisp_Object */
-/* This is desirable for most machines. */
-
-#define NO_UNION_TYPE
-
-/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
- the 24-bit bit field into an int. In other words, if bit fields
- are always unsigned.
-
- If you use NO_UNION_TYPE, this flag does not matter. */
-
-#define EXPLICIT_SIGN_EXTEND
-
-/* Data type of load average, as read out of kmem. */
-
-#define LOAD_AVE_TYPE long
-
-/* Convert that into an integer that is 100 for a load average of 1.0 */
-
-#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
-
-/* Define CANNOT_DUMP on machines where unexec does not work.
- Then the function dump-emacs will not be defined
- and temacs will do (load "loadup") automatically unless told otherwise. */
-
-#define CANNOT_DUMP
-
-/* Define VIRT_ADDR_VARIES if the virtual addresses of
- pure and impure space as loaded can vary, and even their
- relative order cannot be relied on.
-
- Otherwise Emacs assumes that text space precedes data space,
- numerically. */
-
-#define VIRT_ADDR_VARIES
-
-/* Define C_ALLOCA if this machine does not support a true alloca
- and the one written in C should be used instead.
- Define HAVE_ALLOCA to say that the system provides a properly
- working alloca function and it should be used.
- Define neither one if an assembler-language alloca
- in the file alloca.s should be used. */
-
-#define C_ALLOCA
-#define HAVE_ALLOCA
-
-/* Define NO_REMAP if memory segmentation makes it not work well
- to change the boundary between the text section and data section
- when Emacs is dumped. If you define this, the preloaded Lisp
- code will not be sharable; but that's better than failing completely. */
-
-#define NO_REMAP
-
-/* Some really obscure 4.2-based systems (like Sequent DYNIX)
- * do not support asynchronous I/O (using SIGIO) on sockets,
- * even though it works fine on tty's. If you have one of
- * these systems, define the following, and then use it in
- * config.h (or elsewhere) to decide when (not) to use SIGIO.
- *
- * You'd think this would go in an operating-system description file,
- * but since it only occurs on some, but not all, BSD systems, the
- * reasonable place to select for it is in the machine description
- * file.
- */
-
-#define NO_SOCK_SIGIO
-
-
-/* After adding support for a new system, modify the large case
- statement in the `configure' script to recognize reasonable
- configuration names, and add a description of the system to
- `etc/MACHINES'.
-
- If you've just fixed a problem in an existing configuration file,
- you should also check `etc/MACHINES' to make sure its descriptions
- of known problems in that configuration should be updated. */
diff --git a/src/m/tower32.h b/src/m/tower32.h
deleted file mode 100644
index 31ed5c0da52..00000000000
--- a/src/m/tower32.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- 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 writable 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
deleted file mode 100644
index d85d631b1bb..00000000000
--- a/src/m/tower32v3.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-3" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- 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 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
-
-/* 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/ustation.h b/src/m/ustation.h
deleted file mode 100644
index b73ff291d12..00000000000
--- a/src/m/ustation.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/* machine description file for U-station (Nihon Unisys, SS5E; Sumitomo Denkoh, U-Station E30).
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-3" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#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
-
-/* 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 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. */
-
-/* On return from a subroutine, the 68020 compiler restores old contents of
- register variables relative to sp, so alloca() screws up such routines.
- The following definitions should work on all Masscomps. On the MC-5500
- (a 68000) one can #undef C_ALLOCA and #define HAVE_ALLOCA. */
-
-#define C_ALLOCA
-#undef HAVE_ALLOCA
-
-/* Define NO_REMAP if memory segmentation makes it not work well
- to change the boundary between the text section and data section
- when Emacs is dumped. If you define this, the preloaded Lisp
- code will not be sharable; but that's better than failing completely. */
-
-#undef NO_REMAP
-
-/* 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
-
-/* -lnet is not standard library */
-
-#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 SIGIO
-#undef SIGTSTP
diff --git a/src/m/vax.h b/src/m/vax.h
deleted file mode 100644
index 99d06d1c0d9..00000000000
--- a/src/m/vax.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="note"
-
-NOTE-START
-The vax (-machine=vax) runs zillions of different operating systems.
-
-Vax running Berkeley Unix (-opsystem=bsd4-1, -opsystem=bsd4-2 or
- -opsystem=bsd4-3)
-
- Works.
-
-Vax running Ultrix (-opsystem=bsd4-2)
-
- Works. See under Ultrix in share-lib/MACHINES for problems using X
- windows on Ultrix.
-
-Vax running System V rel 2 (-opsystem=usg5-2)
-
- 18.27 Works.
-
-Vax running System V rel 0 (-opsystem=usg5-0)
-
- Works as of 18.36.
-
-Vax running VMS (-opsystem=vms)
-
- 18.36 believed to work. Addition of features is necessary to make
- this Emacs version more usable.
-
-NOTE-END */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#undef WORDS_BIG_ENDIAN
-
-/* #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_SYSTEM
-/* 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_SYSTEM */
-
-#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_SYSTEM
-#define HAVE_ALLOCA
-#endif /* BSD_SYSTEM */
-
-#ifdef VMS
-#define C_ALLOCA
-#endif
-
-#ifdef BSD4_2
-#define HAVE_FTIME
-#endif
diff --git a/src/m/wicat.h b/src/m/wicat.h
deleted file mode 100644
index 395ebe2e255..00000000000
--- a/src/m/wicat.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/* machine description 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-#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
-
-/* 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/windowsnt.h b/src/m/windowsnt.h
deleted file mode 100644
index 64206889251..00000000000
--- a/src/m/windowsnt.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Machine description file for Windows NT.
-
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="<name of system .h file here, without the s- or .h>" */
-
-/* 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 */
-
-/* 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 1
-#define CANNOT_UNEXEC 1
- */
-
-/* Start and end of text and data. */
-#define DATA_END get_data_end ()
-#define DATA_START get_data_start ()
-
-/* 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. */
-
-/* Text does precede data space, but this is never a safe assumption. */
-#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 */
-#include <malloc.h>
-#define HAVE_ALLOCA
-
-/* Define NO_REMAP if memory segmentation makes it not work well
- to change the boundary between the text section and data section
- when Emacs is dumped. If you define this, the preloaded Lisp
- code will not be sharable; but that's better than failing completely. */
-
-/* #define NO_REMAP */
-
-/* Some really obscure 4.2-based systems (like Sequent DYNIX)
- * do not support asynchronous I/O (using SIGIO) on sockets,
- * even though it works fine on tty's. If you have one of
- * these systems, define the following, and then use it in
- * config.h (or elsewhere) to decide when (not) to use SIGIO.
- *
- * You'd think this would go in an operating-system description file,
- * but since it only occurs on some, but not all, BSD systems, the
- * reasonable place to select for it is in the machine description
- * file.
- */
-
-/* #define NO_SOCK_SIGIO */
-
-/* After adding support for a new system, modify the large case
- statement in the `configure' script to recognize reasonable
- configuration names, and add a description of the system to
- `etc/MACHINES'.
-
- If you've just fixed a problem in an existing configuration file,
- you should also check `etc/MACHINES' to make sure its descriptions
- of known problems in that configuration should be updated. */
diff --git a/src/m/xps100.h b/src/m/xps100.h
deleted file mode 100644
index e712d154030..00000000000
--- a/src/m/xps100.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* xps100.h for the Honeywell XPS100 running UNIX System V.2
- Mark J. Hewitt (mjh@uk.co.kernel)
-
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* The following line tells the configuration script what sort of
- operating system this machine is likely to run.
- USUAL-OPSYS="usg5-2" */
-
-/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
- is the most significant byte. */
-
-#define WORDS_BIG_ENDIAN
-
-/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
- * group of arguments and treat it as an array of the arguments. */
-
-/* #define NO_ARG_ARRAY */
-
-/* Define WORD_MACHINE if addresses and such have
- * to be corrected before they can be used as byte counts. */
-
-/* #define WORD_MACHINE */
-
-/* Now define a symbol for the cpu type, if your compiler
- does not define it automatically:
- Ones defined so far include vax, m68000, ns16000, pyramid,
- orion, tahoe, APOLLO and many others */
-
-/* Use type int rather than a union, to represent Lisp_Object */
-/* This is desirable for most machines. */
-
-#define NO_UNION_TYPE
-
-/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
- the 24-bit bit field into an int. In other words, if bit fields
- are always unsigned.
-
- If you use NO_UNION_TYPE, this flag does not matter. */
-
-#define EXPLICIT_SIGN_EXTEND
-
-/* Data type of load average, as read out of kmem. */
-
-/* #define LOAD_AVE_TYPE long */
-
-/* Convert that into an integer that is 100 for a load average of 1.0 */
-
-/* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */
-
-/* Define CANNOT_DUMP on machines where unexec does not work.
- Then the function dump-emacs will not be defined
- and temacs will do (load "loadup") automatically unless told otherwise. */
-
-/* #define CANNOT_DUMP */
-
-/* Define VIRT_ADDR_VARIES if the virtual addresses of
- pure and impure space as loaded can vary, and even their
- relative order cannot be relied on.
-
- Otherwise Emacs assumes that text space precedes data space,
- numerically. */
-
-/* #define VIRT_ADDR_VARIES */
-
-/* Define C_ALLOCA if this machine does not support a true alloca
- and the one written in C should be used instead.
- Define HAVE_ALLOCA to say that the system provides a properly
- working alloca function and it should be used.
- Define neither one if an assembler-language alloca
- in the file alloca.s should be used. */
-
-#define C_ALLOCA
-/* #define HAVE_ALLOCA */
-
-/* Define NO_REMAP if memory segmentation makes it not work well
- to change the boundary between the text section and data section
- when Emacs is dumped. If you define this, the preloaded Lisp
- code will not be sharable; but that's better than failing completely. */
-
-#define NO_REMAP
-#define STACK_DIRECTION -1
-#define TERMINFO
-#define SWITCH_ENUM_BUG
-#define LIB_STANDARD -lc
-#define LD_SWITCH_MACHINE -X
-#define SECTION_ALIGNMENT (0x3ff)
diff --git a/src/macros.c b/src/macros.c
deleted file mode 100644
index 9054fb5bfea..00000000000
--- a/src/macros.c
+++ /dev/null
@@ -1,327 +0,0 @@
-/* Keyboard macros.
- Copyright (C) 1985, 1986, 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include "lisp.h"
-#include "macros.h"
-#include "commands.h"
-#include "buffer.h"
-#include "window.h"
-#include "keyboard.h"
-
-Lisp_Object Qexecute_kbd_macro;
-
-/* Kbd macro currently being executed (a string or vector). */
-
-Lisp_Object Vexecuting_macro;
-
-/* Index of next character to fetch from that macro. */
-
-int executing_macro_index;
-
-/* Number of successful iterations so far
- for innermost keyboard macro.
- This is not bound at each level,
- so after an error, it describes the innermost interrupted macro. */
-
-int executing_macro_iterations;
-
-/* This is the macro that was executing.
- This is not bound at each level,
- so after an error, it describes the innermost interrupted macro.
- We use it only as a kind of flag, so no need to protect it. */
-
-Lisp_Object executing_macro;
-
-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 (!NILP (current_kboard->defining_kbd_macro))
- error ("Already defining kbd macro");
-
- if (!current_kboard->kbd_macro_buffer)
- {
- current_kboard->kbd_macro_bufsize = 30;
- current_kboard->kbd_macro_buffer
- = (Lisp_Object *)xmalloc (30 * sizeof (Lisp_Object));
- }
- update_mode_lines++;
- if (NILP (append))
- {
- if (current_kboard->kbd_macro_bufsize > 200)
- {
- current_kboard->kbd_macro_bufsize = 30;
- current_kboard->kbd_macro_buffer
- = (Lisp_Object *)xrealloc (current_kboard->kbd_macro_buffer,
- 30 * sizeof (Lisp_Object));
- }
- current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_buffer;
- current_kboard->kbd_macro_end = current_kboard->kbd_macro_buffer;
- message ("Defining kbd macro...");
- }
- else
- {
- message ("Appending to kbd macro...");
- current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_end;
- Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro,
- make_number (1));
- }
- current_kboard->defining_kbd_macro = Qt;
-
- 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\
-\n\
-With numeric arg, repeat macro now that many times,\n\
-counting the definition just completed as the first repetition.\n\
-An argument of zero means repeat until error.")
- (repeat)
- Lisp_Object repeat;
-{
- if (NILP (current_kboard->defining_kbd_macro))
- error ("Not defining kbd macro.");
-
- if (NILP (repeat))
- XSETFASTINT (repeat, 1);
- else
- CHECK_NUMBER (repeat, 0);
-
- if (!NILP (current_kboard->defining_kbd_macro))
- {
- current_kboard->defining_kbd_macro = Qnil;
- update_mode_lines++;
- current_kboard->Vlast_kbd_macro
- = make_event_array ((current_kboard->kbd_macro_end
- - current_kboard->kbd_macro_buffer),
- current_kboard->kbd_macro_buffer);
- message ("Keyboard macro defined");
- }
-
- if (XFASTINT (repeat) == 0)
- Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, repeat);
- else
- {
- XSETINT (repeat, XINT (repeat)-1);
- if (XINT (repeat) > 0)
- Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, repeat);
- }
- return Qnil;
-}
-
-/* Store character c into kbd macro being defined */
-
-store_kbd_macro_char (c)
- Lisp_Object c;
-{
- if (!NILP (current_kboard->defining_kbd_macro))
- {
- if ((current_kboard->kbd_macro_ptr
- - current_kboard->kbd_macro_buffer)
- == current_kboard->kbd_macro_bufsize)
- {
- register Lisp_Object *new;
- current_kboard->kbd_macro_bufsize *= 2;
- new = (Lisp_Object *)xrealloc (current_kboard->kbd_macro_buffer,
- (current_kboard->kbd_macro_bufsize
- * sizeof (Lisp_Object)));
- current_kboard->kbd_macro_ptr
- += new - current_kboard->kbd_macro_buffer;
- current_kboard->kbd_macro_end
- += new - current_kboard->kbd_macro_buffer;
- current_kboard->kbd_macro_buffer = new;
- }
- *current_kboard->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 ()
-{
- current_kboard->kbd_macro_end = current_kboard->kbd_macro_ptr;
-}
-
-DEFUN ("cancel-kbd-macro-events", Fcancel_kbd_macro_events,
- Scancel_kbd_macro_events, 0, 0, 0,
- "Cancel the events added to a keyboard macro for this command.")
- ()
-{
- current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_end;
-}
-
-DEFUN ("store-kbd-macro-event", Fstore_kbd_macro_event,
- Sstore_kbd_macro_event, 1, 1, 0,
- "Store EVENT into the keyboard macro being defined.")
- (event)
- Lisp_Object event;
-{
- store_kbd_macro_char (event);
- return Qnil;
-}
-
-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\
-\n\
-A prefix argument serves as a repeat count. Zero means repeat until error.\n\
-\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;
-{
- /* Don't interfere with recognition of the previous command
- from before this macro started. */
- this_command = current_kboard->Vlast_command;
-
- if (! NILP (current_kboard->defining_kbd_macro))
- error ("Can't execute anonymous macro while defining one");
- else if (NILP (current_kboard->Vlast_kbd_macro))
- error ("No kbd macro has been defined");
- else
- Fexecute_kbd_macro (current_kboard->Vlast_kbd_macro, prefix);
-
- /* command_loop_1 sets this to nil before it returns;
- get back the last command within the macro
- so that it can be last, again, after we return. */
- this_command = current_kboard->Vlast_command;
-
- return Qnil;
-}
-
-/* Restore Vexecuting_macro and executing_macro_index - called when
- the unwind-protect in Fexecute_kbd_macro gets invoked. */
-
-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, count)
- Lisp_Object macro, count;
-{
- Lisp_Object final;
- Lisp_Object tem;
- int pdlcount = specpdl_ptr - specpdl;
- int repeat = 1;
- struct gcpro gcpro1;
- int success_count = 0;
-
- if (!NILP (count))
- {
- count = Fprefix_numeric_value (count);
- repeat = XINT (count);
- }
-
- final = indirect_function (macro);
- if (!STRINGP (final) && !VECTORP (final))
- error ("Keyboard macros must be strings or vectors.");
-
- XSETFASTINT (tem, executing_macro_index);
- tem = Fcons (Vexecuting_macro, tem);
- record_unwind_protect (pop_kbd_macro, tem);
-
- GCPRO1 (final);
- do
- {
- Vexecuting_macro = final;
- executing_macro = final;
- executing_macro_index = 0;
-
- current_kboard->Vprefix_arg = Qnil;
- command_loop_1 ();
-
- executing_macro_iterations = ++success_count;
-
- QUIT;
- }
- while (--repeat
- && (STRINGP (Vexecuting_macro) || VECTORP (Vexecuting_macro)));
-
- executing_macro = Qnil;
-
- UNGCPRO;
- return unbind_to (pdlcount, Qnil);
-}
-
-init_macros ()
-{
- Vexecuting_macro = Qnil;
- executing_macro = Qnil;
-}
-
-syms_of_macros ()
-{
- Qexecute_kbd_macro = intern ("execute-kbd-macro");
- staticpro (&Qexecute_kbd_macro);
-
- defsubr (&Sstart_kbd_macro);
- defsubr (&Send_kbd_macro);
- defsubr (&Scall_last_kbd_macro);
- defsubr (&Sexecute_kbd_macro);
- defsubr (&Scancel_kbd_macro_events);
- defsubr (&Sstore_kbd_macro_event);
-
- DEFVAR_KBOARD ("defining-kbd-macro", defining_kbd_macro,
- "Non-nil while a keyboard macro is being defined. Don't set this!");
-
- DEFVAR_LISP ("executing-macro", &Vexecuting_macro,
- "Currently executing keyboard macro (string or vector); nil if none executing.");
-
- DEFVAR_LISP_NOPRO ("executing-kbd-macro", &Vexecuting_macro,
- "Currently executing keyboard macro (string or vector); nil if none executing.");
-
- DEFVAR_KBOARD ("last-kbd-macro", Vlast_kbd_macro,
- "Last kbd macro defined, as a string or vector; nil if none defined.");
-}
-
-keys_of_macros ()
-{
- initial_define_key (control_x_map, ('e'), "call-last-kbd-macro");
- initial_define_key (control_x_map, ('('), "start-kbd-macro");
- initial_define_key (control_x_map, (')'), "end-kbd-macro");
-}
diff --git a/src/macros.h b/src/macros.h
deleted file mode 100644
index 2396514ea23..00000000000
--- a/src/macros.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Kbd macro currently being executed (a string or vector). */
-
-extern Lisp_Object Vexecuting_macro;
-
-/* Index of next character to fetch from that macro. */
-
-extern int executing_macro_index;
-
-/* Number of successful iterations so far
- for innermost keyboard macro.
- This is not bound at each level,
- so after an error, it describes the innermost interrupted macro. */
-
-extern int executing_macro_iterations;
-
-/* This is the macro that was executing.
- This is not bound at each level,
- so after an error, it describes the innermost interrupted macro. */
-
-extern Lisp_Object executing_macro;
diff --git a/src/makefile.nt b/src/makefile.nt
deleted file mode 100644
index b3768704c46..00000000000
--- a/src/makefile.nt
+++ /dev/null
@@ -1,1127 +0,0 @@
-# Makefile for GNU Emacs on Windows NT
-# Copyright (c) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-# Tim Fleehart (apollo@online.com) 17-Apr-92
-# Geoff Voelker (voelker@cs.washington.edu) 11-20-93
-#
-# This file is part of GNU Emacs.
-#
-# GNU Emacs is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# GNU Emacs is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Emacs; see the file COPYING. If not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-
-#
-# Sets up the system dependent macros.
-#
-!include ..\nt\makefile.def
-
-SUBSYSTEM=console
-
-#
-# HAVE_CONFIG_H is required by some generic gnu sources stuck into
-# the emacs source tree.
-#
-LOCAL_FLAGS = -Demacs=1 -DWINDOWSNT -DDOS_NT -DHAVE_CONFIG_H -I..\nt\inc
-
-EMACS = $(BLD)\emacs.exe
-TEMACS = $(BLD)\temacs.exe
-TLIB1 = $(BLD)\temacs1.lib
-TLIB2 = $(BLD)\temacs2.lib
-!IFDEF NTGUI
-TLIBW32 = $(BLD)\temacw32.lib
-!ELSE
-TLIBW32 =
-!ENDIF
-TOBJ = $(BLD)\emacs.obj
-!if $(MSVCNT11)
-TRES = $(BLD)\emacs.res
-!else
-TRES = $(BLD)\emacs.rbj
-!endif
-TLASTLIB = $(BLD)\lastfile.lib
-
-# see comments in allocate_heap in w32heap.c before changing any of the
-# -stack, -heap, or -base settings.
-LINK_FLAGS = $(ARCH_LDFLAGS) -stack:0x00800000 -heap:0x00100000 -base:0x01000000 -debug:full -debugtype:cv -machine:$(ARCH) -subsystem:$(SUBSYSTEM) -entry:_start -map:$(BLD)\temacs.map
-
-#
-# Split up the objects into two sets so that we don't run out of
-# command line space when we link them into a library.
-#
-OBJ1 = $(BLD)\abbrev.obj \
- $(BLD)\alloc.obj \
- $(BLD)\alloca.obj \
- $(BLD)\buffer.obj \
- $(BLD)\bytecode.obj \
- $(BLD)\callint.obj \
- $(BLD)\callproc.obj \
- $(BLD)\casefiddle.obj \
- $(BLD)\cm.obj \
- $(BLD)\cmds.obj \
- $(BLD)\data.obj \
- $(BLD)\dired.obj \
- $(BLD)\dispnew.obj \
- $(BLD)\doc.obj \
- $(BLD)\doprnt.obj \
- $(BLD)\editfns.obj \
- $(BLD)\eval.obj \
- $(BLD)\fileio.obj \
- $(BLD)\filelock.obj \
- $(BLD)\filemode.obj \
- $(BLD)\fns.obj \
- $(BLD)\indent.obj \
- $(BLD)\insdel.obj \
- $(BLD)\keyboard.obj \
- $(BLD)\keymap.obj \
- $(BLD)\lread.obj \
- $(BLD)\macros.obj \
- $(BLD)\marker.obj \
- $(BLD)\minibuf.obj \
- $(BLD)\mocklisp.obj
-
-OBJ2 = $(BLD)\w32.obj \
- $(BLD)\w32heap.obj \
- $(BLD)\w32inevt.obj \
- $(BLD)\w32proc.obj \
- $(BLD)\w32console.obj \
- $(BLD)\print.obj \
- $(BLD)\process.obj \
- $(BLD)\regex.obj \
- $(BLD)\scroll.obj \
- $(BLD)\search.obj \
- $(BLD)\syntax.obj \
- $(BLD)\sysdep.obj \
- $(BLD)\term.obj \
- $(BLD)\termcap.obj \
- $(BLD)\tparam.obj \
- $(BLD)\undo.obj \
- $(BLD)\unexw32.obj \
- $(BLD)\window.obj \
- $(BLD)\xdisp.obj \
- $(BLD)\casetab.obj \
- $(BLD)\floatfns.obj \
- $(BLD)\frame.obj \
- $(BLD)\gmalloc.obj \
- $(BLD)\intervals.obj \
- $(BLD)\ralloc.obj \
- $(BLD)\textprop.obj \
- $(BLD)\vm-limit.obj \
- $(BLD)\region-cache.obj \
- $(BLD)\strftime.obj
-
-WIN32OBJ = $(BLD)\w32term.obj \
- $(BLD)\w32xfns.obj \
- $(BLD)\w32fns.obj \
- $(BLD)\w32faces.obj \
- $(BLD)\w32select.obj \
- $(BLD)\w32menu.obj \
- $(BLD)\w32reg.obj
-
-LIBS = $(TLIB1) \
- $(TLIB2) \
-!IFDEF NTGUI
- $(TLIBW32) \
-!ENDIF
- $(TLASTLIB) \
-!IFDEF NTGUI
- gdi32.lib \
- comdlg32.lib \
-!ENDIF
-# libcmt.lib \
- $(BASE_LIBS) \
- $(ADVAPI32) \
- user32.lib \
- mpr.lib
-
-#
-# Build the executable and dump it.
-#
-all: $(BLD) $(EMACS)
-
-#
-# Headers we would preprocess if we could.
-#
-PREPARED_HEADERS = config.h paths.h
-config.h: ..\nt\$(CONFIG_H)
- $(CP) $** $@
-paths.h: ..\nt\paths.h
- $(CP) $** $@
-
-#
-# Make sure we have the DOC file in the right place.
-#
-DOC = $(OBJDIR)\etc\DOC-X
-$(DOC):; cd ..\lib-src
- - $(DEL) DOC-X
- $(MAKE) -f makefile.nt all
- cd ..\src
-
-#
-# The dumped executable
-#
-emacs: $(EMACS)
-$(EMACS): $(PREPARED_HEADERS) $(DOC) $(TEMACS)
- cd $(BLD)
- temacs.exe -batch -l loadup dump
- cd ..\..
-
-#
-# The undumped executable
-#
-temacs: $(BLD) $(TEMACS)
-$(TEMACS): $(TLIB1) $(TLIB2) $(TLIBW32) $(TLASTLIB) $(TOBJ) $(TRES)
- $(LINK) -out:$(TEMACS) $(LINK_FLAGS) $(TOBJ) $(TRES) $(LIBS)
-
-#
-# The resource file. NT 3.10 requires the use of cvtres; even though
-# it is not necessary on later versions, it is still ok to use it.
-#
-$(TRES): ..\nt\emacs.rc
- $(RC) -i..\nt -Fo$(BLD)\emacs.res $**
-!if !$(MSVCNT11)
- $(CVTRES) -r -$(ARCH) -o $@ $(BLD)\emacs.res
-!endif
-
-#
-# Build the library. Split up the build into two phases...otherwise we
-# run out of command line space.
-#
-$(TLIB1): $(OBJ1)
- @- $(AR) -out:$@ $**
-$(TLIB2): $(OBJ2)
- @- $(AR) -out:$@ $**
-!IFDEF NTGUI
-$(TLIBW32): $(WIN32OBJ)
- @- $(AR) -out:$@ $**
-!ENDIF
-
-#
-# Place lastfile.obj in its own library so that it can be loaded after
-# the source libraries but before any system libraries. Doing so defines
-# the end of Emacs' data section portably across compilers and systems.
-#
-$(TLASTLIB): $(BLD)\lastfile.obj
- @- $(AR) -out:$@ $**
-
-#
-# Object files.
-#
-.c{$(BLD)}.obj:
- $(CC) $(CFLAGS) -Fo$@ $<
-
-#
-# Assuming INSTALL_DIR is defined, build and install emacs in it.
-#
-install: all
- - mkdir $(INSTALL_DIR)\bin
- $(CP) $(EMACS) $(INSTALL_DIR)\bin
-
-#
-# Maintenance
-#
-clean:; - $(DEL) *~ *.pdb config.h paths.h
- - $(DEL_TREE) deleted
- - $(DEL_TREE) $(OBJDIR)
-
-#
-# These files are the ones that compile conditionally on CANNOT_DUMP...
-# this target is mostly used for debugging.
-#
-cleandump:; cd $(BLD)
- - $(DEL) callproc.obj data.obj dispnew.obj doc.obj editfns.obj emacs.obj lread.obj process.obj sysdep.obj term.obj w32heap.obj unexw32.obj
- cd ..\..
-
-
-### DEPENDENCIES ###
-
-EMACS_ROOT = ..
-SRC = .
-
-$(BLD)\abbrev.obj : \
- $(SRC)\abbrev.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\commands.h \
- $(SRC)\buffer.h \
- $(SRC)\window.h
-
-$(BLD)\alloc.obj : \
- $(SRC)\alloc.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h \
- $(SRC)\puresize.h \
- $(SRC)\buffer.h \
- $(SRC)\window.h \
- $(SRC)\frame.h \
- $(SRC)\blockinput.h \
- $(SRC)\syssignal.h
-
-$(BLD)\alloca.obj : \
- $(SRC)\alloca.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\s\ms-w32.h \
- $(SRC)\m\intel386.h \
- $(SRC)\config.h \
- $(SRC)\blockinput.h
-
-$(BLD)\buffer.obj : \
- $(SRC)\buffer.c \
- $(EMACS_ROOT)\nt\inc\sys\param.h \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h \
- $(SRC)\window.h \
- $(SRC)\commands.h \
- $(SRC)\buffer.h \
- $(SRC)\indent.h \
- $(SRC)\blockinput.h \
- $(SRC)\region-cache.h
-
-$(BLD)\bytecode.obj : \
- $(SRC)\bytecode.c \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h \
- $(SRC)\syntax.h
-
-$(BLD)\callint.obj : \
- $(SRC)\callint.c \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h \
- $(SRC)\commands.h \
- $(SRC)\keyboard.h \
- $(SRC)\window.h \
- $(SRC)\mocklisp.h
-
-$(BLD)\callproc.obj : \
- $(SRC)\callproc.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\msdos.h \
- $(EMACS_ROOT)\nt\inc\sys\param.h \
- $(SRC)\lisp.h \
- $(SRC)\commands.h \
- $(SRC)\buffer.h \
- $(SRC)\process.h \
- $(SRC)\syssignal.h \
- $(EMACS_ROOT)\nt\inc\sys\ioctl.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h \
- $(SRC)\systty.h
-
-$(BLD)\casefiddle.obj : \
- $(SRC)\casefiddle.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h \
- $(SRC)\commands.h \
- $(SRC)\syntax.h
- $(CC) $(CFLAGS) -Fo$@ casefiddle.c
-
-$(BLD)\casetab.obj : \
- $(SRC)\casetab.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h
-
-$(BLD)\cm.obj : \
- $(SRC)\cm.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\cm.h \
- $(SRC)\termhooks.h
-
-$(BLD)\cmds.obj : \
- $(SRC)\cmds.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\commands.h \
- $(SRC)\buffer.h \
- $(SRC)\syntax.h
-
-$(BLD)\data.obj : \
- $(SRC)\data.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\puresize.h \
- $(SRC)\buffer.h \
- $(SRC)\syssignal.h
-
-$(BLD)\dired.obj : \
- $(SRC)\dired.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\vmsdir.h \
- $(SRC)\ndir.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h \
- $(SRC)\commands.h \
- $(SRC)\regex.h
-
-$(BLD)\dispnew.obj : \
- $(SRC)\dispnew.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\termchar.h \
- $(SRC)\termopts.h \
- $(SRC)\termhooks.h \
- $(SRC)\cm.h \
- $(SRC)\buffer.h \
- $(SRC)\frame.h \
- $(SRC)\window.h \
- $(SRC)\commands.h \
- $(SRC)\disptab.h \
- $(SRC)\indent.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h \
- $(EMACS_ROOT)\nt\inc\sys\ioctl.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h \
- $(SRC)\systty.h \
- $(SRC)\w32term.h \
- $(SRC)\xterm.h \
- $(SRC)\vmstime.h \
- $(SRC)\systime.h
-
-$(BLD)\doc.obj : \
- $(SRC)\doc.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h \
- $(SRC)\keyboard.h
-
-$(BLD)\doprnt.obj : \
- $(SRC)\doprnt.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h
-
-$(BLD)\dosfns.obj : \
- $(SRC)\dosfns.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h \
- $(SRC)\termchar.h \
- $(SRC)\termhooks.h \
- $(SRC)\frame.h \
- $(SRC)\dosfns.h \
- $(SRC)\msdos.h
-
-$(BLD)\editfns.obj : \
- $(SRC)\editfns.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\uaf.h \
- $(SRC)\vms-pwd.h \
- $(EMACS_ROOT)\nt\inc\pwd.h \
- $(SRC)\lisp.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h \
- $(SRC)\buffer.h \
- $(SRC)\window.h \
- $(SRC)\vmstime.h \
- $(SRC)\systime.h
-
-$(BLD)\emacs.obj : \
- $(SRC)\emacs.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\commands.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h \
- $(EMACS_ROOT)\nt\inc\sys\ioctl.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h \
- $(SRC)\systty.h \
- $(SRC)\syssignal.h \
- $(SRC)\process.h
-
-$(BLD)\eval.obj : \
- $(SRC)\eval.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\blockinput.h \
- $(SRC)\commands.h \
- $(SRC)\keyboard.h
-
-$(BLD)\fileio.obj : \
- $(SRC)\fileio.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\uaf.h \
- $(SRC)\vms-pwd.h \
- $(EMACS_ROOT)\nt\inc\pwd.h \
- $(SRC)\msdos.h \
- $(EMACS_ROOT)\nt\inc\sys\param.h \
- $(SRC)\vmsdir.h \
- $(SRC)\lisp.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h \
- $(SRC)\buffer.h \
- $(SRC)\window.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h \
- $(SRC)\vmstime.h \
- $(SRC)\systime.h
-
-$(BLD)\filelock.obj : \
- $(SRC)\filelock.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\uaf.h \
- $(SRC)\vms-pwd.h \
- $(EMACS_ROOT)\nt\inc\pwd.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h \
- $(SRC)\lisp.h \
- $(EMACS_ROOT)\src\paths.h \
- $(SRC)\buffer.h \
- $(SRC)\vmsdir.h \
- $(SRC)\ndir.h
-
-$(BLD)\filemode.obj : \
- $(SRC)\filemode.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\s\ms-w32.h \
- $(SRC)\m\intel386.h \
- $(SRC)\config.h
-
-$(BLD)\floatfns.obj : \
- $(SRC)\floatfns.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\syssignal.h
-
-$(BLD)\fns.obj : \
- $(SRC)\fns.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\commands.h \
- $(SRC)\buffer.h \
- $(SRC)\keyboard.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h
-
-$(BLD)\frame.obj : \
- $(SRC)\frame.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\frame.h \
- $(SRC)\termhooks.h \
- $(SRC)\window.h \
- $(SRC)\buffer.h \
- $(SRC)\commands.h \
- $(SRC)\keyboard.h
-
-$(BLD)\getloadavg.obj : \
- $(SRC)\getloadavg.c \
- $(EMACS_ROOT)\nt\inc\sys\param.h \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\s\ms-w32.h \
- $(SRC)\m\intel386.h \
- $(SRC)\config.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h
-
-$(BLD)\gmalloc.obj : \
- $(SRC)\gmalloc.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(EMACS_ROOT)\nt\inc\sys\param.h \
- $(SRC)\getpagesize.h
- $(CC) $(CFLAGS) -D__STDC__ -Fo$@ gmalloc.c
-
-$(BLD)\hftctl.obj : \
- $(SRC)\hftctl.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(EMACS_ROOT)\nt\inc\sys\ioctl.h
-
-$(BLD)\indent.obj : \
- $(SRC)\indent.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h \
- $(SRC)\indent.h \
- $(SRC)\frame.h \
- $(SRC)\window.h \
- $(SRC)\termchar.h \
- $(SRC)\termopts.h \
- $(SRC)\disptab.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h \
- $(SRC)\region-cache.h
-
-$(BLD)\insdel.obj : \
- $(SRC)\insdel.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h \
- $(SRC)\buffer.h \
- $(SRC)\window.h \
- $(SRC)\blockinput.h
-
-$(BLD)\intervals.obj : \
- $(SRC)\intervals.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h \
- $(SRC)\buffer.h \
- $(SRC)\puresize.h
- $(CC) $(CFLAGS) -Fo$@ intervals.c
-
-$(BLD)\keyboard.obj : \
- $(SRC)\keyboard.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\termchar.h \
- $(SRC)\termopts.h \
- $(SRC)\lisp.h \
- $(SRC)\termhooks.h \
- $(SRC)\macros.h \
- $(SRC)\frame.h \
- $(SRC)\window.h \
- $(SRC)\commands.h \
- $(SRC)\buffer.h \
- $(SRC)\disptab.h \
- $(SRC)\keyboard.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h \
- $(SRC)\blockinput.h \
- $(SRC)\msdos.h \
- $(SRC)\syssignal.h \
- $(EMACS_ROOT)\nt\inc\sys\ioctl.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h \
- $(SRC)\systty.h \
- $(SRC)\w32term.h \
- $(SRC)\xterm.h \
- $(SRC)\vmstime.h \
- $(SRC)\systime.h
-
-$(BLD)\keymap.obj : \
- $(SRC)\keymap.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\commands.h \
- $(SRC)\buffer.h \
- $(SRC)\keyboard.h \
- $(SRC)\termhooks.h \
- $(SRC)\blockinput.h
-
-$(BLD)\lastfile.obj : \
- $(SRC)\lastfile.c
-
-$(BLD)\lread.obj : \
- $(SRC)\lread.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h \
- $(EMACS_ROOT)\src\paths.h \
- $(SRC)\commands.h \
- $(SRC)\keyboard.h \
- $(SRC)\termhooks.h \
- $(SRC)\msdos.h
-
-$(BLD)\macros.obj : \
- $(SRC)\macros.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\macros.h \
- $(SRC)\commands.h \
- $(SRC)\buffer.h \
- $(SRC)\window.h
-
-$(BLD)\marker.obj : \
- $(SRC)\marker.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h
-
-$(BLD)\minibuf.obj : \
- $(SRC)\minibuf.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\commands.h \
- $(SRC)\buffer.h \
- $(SRC)\dispextern.h \
- $(SRC)\frame.h \
- $(SRC)\window.h \
- $(SRC)\syntax.h
-
-$(BLD)\mocklisp.obj : \
- $(SRC)\mocklisp.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h
-
-$(BLD)\w32.obj : \
- $(SRC)\w32.c \
- $(SRC)\w32.h \
- $(SRC)\s\ms-w32.h \
- $(SRC)\m\intel386.h \
- $(SRC)\config.h \
- $(SRC)\lisp.h \
- $(EMACS_ROOT)\nt\inc\pwd.h \
- $(SRC)\w32heap.h
-
-$(BLD)\w32heap.obj : \
- $(SRC)\w32heap.c \
- $(SRC)\w32heap.h
-
-$(BLD)\w32inevt.obj : \
- $(SRC)\w32inevt.c \
- $(SRC)\s\ms-w32.h \
- $(SRC)\m\intel386.h \
- $(SRC)\config.h \
- $(SRC)\lisp.h \
- $(SRC)\frame.h \
- $(SRC)\blockinput.h \
- $(SRC)\termhooks.h
-
-$(BLD)\w32proc.obj : \
- $(SRC)\w32proc.c \
- $(SRC)\s\ms-w32.h \
- $(SRC)\m\intel386.h \
- $(SRC)\config.h \
- $(SRC)\lisp.h \
- $(SRC)\w32.h \
- $(SRC)\vmstime.h \
- $(SRC)\systime.h
-
-$(BLD)\w32console.obj : \
- $(SRC)\w32console.c \
- $(SRC)\s\ms-w32.h \
- $(SRC)\m\intel386.h \
- $(SRC)\config.h \
- $(SRC)\lisp.h \
- $(SRC)\frame.h \
- $(SRC)\disptab.h \
- $(SRC)\termhooks.h \
- $(SRC)\w32inevt.h
-
-$(BLD)\prefix-args.obj : \
- $(SRC)\prefix-args.c
-
-$(BLD)\print.obj : \
- $(SRC)\print.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h \
- $(SRC)\frame.h \
- $(SRC)\window.h \
- $(SRC)\process.h \
- $(SRC)\termchar.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h
-
-$(BLD)\process.obj : \
- $(SRC)\process.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(EMACS_ROOT)\nt\inc\sys\ioctl.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h \
- $(SRC)\systty.h \
- $(SRC)\window.h \
- $(SRC)\buffer.h \
- $(SRC)\process.h \
- $(SRC)\termhooks.h \
- $(SRC)\commands.h \
- $(SRC)\frame.h \
- $(SRC)\syssignal.h \
- $(SRC)\vmsproc.h \
- $(SRC)\syswait.h \
- $(SRC)\lisp.h \
- $(SRC)\vmstime.h \
- $(SRC)\systime.h \
- $(SRC)\termopts.h
-
-$(BLD)\ralloc.obj : \
- $(SRC)\ralloc.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\s\ms-w32.h \
- $(SRC)\m\intel386.h \
- $(SRC)\config.h \
- $(EMACS_ROOT)\nt\inc\sys\param.h \
- $(SRC)\getpagesize.h
-
-$(BLD)\regex.obj : \
- $(SRC)\regex.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\s\ms-w32.h \
- $(SRC)\m\intel386.h \
- $(SRC)\config.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h \
- $(SRC)\syntax.h \
- $(SRC)\regex.h
-
-$(BLD)\region-cache.obj : \
- $(SRC)\region-cache.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h \
- $(SRC)\region-cache.h
-
-$(BLD)\scroll.obj : \
- $(SRC)\scroll.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\termchar.h \
- $(SRC)\lisp.h \
- $(SRC)\dispextern.h \
- $(SRC)\frame.h
-
-$(BLD)\search.obj : \
- $(SRC)\search.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\syntax.h \
- $(SRC)\buffer.h \
- $(SRC)\commands.h \
- $(SRC)\blockinput.h \
- $(SRC)\regex.h \
- $(SRC)\region-cache.h
-
-$(BLD)\strftime.obj : \
- $(SRC)\strftime.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h
- $(CC) $(CFLAGS) -Dstrftime=emacs_strftime -Fo$@ strftime.c
-
-$(BLD)\sunfns.obj : \
- $(SRC)\sunfns.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\window.h \
- $(SRC)\buffer.h \
- $(SRC)\termhooks.h
-
-$(BLD)\syntax.obj : \
- $(SRC)\syntax.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\commands.h \
- $(SRC)\buffer.h \
- $(SRC)\syntax.h
-
-$(BLD)\sysdep.obj : \
- $(SRC)\sysdep.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\blockinput.h \
- $(SRC)\dosfns.h \
- $(SRC)\msdos.h \
- $(EMACS_ROOT)\nt\inc\sys\param.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h \
- $(EMACS_ROOT)\nt\inc\sys\ioctl.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h \
- $(SRC)\systty.h \
- $(SRC)\vmsproc.h \
- $(SRC)\syswait.h \
- $(SRC)\frame.h \
- $(SRC)\window.h \
- $(SRC)\termhooks.h \
- $(SRC)\termchar.h \
- $(SRC)\termopts.h \
- $(SRC)\dispextern.h \
- $(SRC)\process.h \
- $(SRC)\vmsdir.h \
- $(SRC)\ndir.h \
- $(SRC)\syssignal.h \
- $(SRC)\vmstime.h \
- $(SRC)\systime.h \
- $(SRC)\uaf.h \
- $(SRC)\vms-pwd.h \
- $(EMACS_ROOT)\src\acldef.h \
- $(EMACS_ROOT)\src\chpdef.h
-
-$(BLD)\term.obj : \
- $(SRC)\term.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\termchar.h \
- $(SRC)\termopts.h \
- $(SRC)\cm.h \
- $(SRC)\lisp.h \
- $(SRC)\frame.h \
- $(SRC)\disptab.h \
- $(SRC)\termhooks.h \
- $(SRC)\keyboard.h
-
-$(BLD)\termcap.obj : \
- $(SRC)\termcap.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(EMACS_ROOT)\nt\inc\sys\file.h
-
-$(BLD)\terminfo.obj : \
- $(SRC)\terminfo.c
-
-$(BLD)\textprop.obj : \
- $(SRC)\textprop.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h \
- $(SRC)\buffer.h \
- $(SRC)\window.h
-
-$(BLD)\tparam.obj : \
- $(SRC)\tparam.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h
-
-$(BLD)\undo.obj : \
- $(SRC)\undo.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h \
- $(SRC)\commands.h
-
-$(BLD)\unexw32.obj : \
- $(SRC)\unexw32.c \
- $(SRC)\w32heap.h
-
-$(BLD)\vm-limit.obj : \
- $(SRC)\vm-limit.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\mem-limits.h
-
-$(BLD)\widget.obj : \
- $(SRC)\widget.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\xterm.h \
- $(SRC)\frame.h \
- $(SRC)\dispextern.h \
- $(SRC)\widget.h \
- $(SRC)\widgetprv.h
-
-$(BLD)\window.obj : \
- $(SRC)\window.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\buffer.h \
- $(SRC)\frame.h \
- $(SRC)\window.h \
- $(SRC)\commands.h \
- $(SRC)\indent.h \
- $(SRC)\termchar.h \
- $(SRC)\disptab.h \
- $(SRC)\keyboard.h
-
-$(BLD)\xdisp.obj : \
- $(SRC)\xdisp.c \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\lisp.h \
- $(SRC)\frame.h \
- $(SRC)\window.h \
- $(SRC)\termchar.h \
- $(SRC)\buffer.h \
- $(SRC)\indent.h \
- $(SRC)\commands.h \
- $(SRC)\macros.h \
- $(SRC)\disptab.h \
- $(SRC)\termhooks.h \
- $(SRC)\dispextern.h \
- $(SRC)\intervals.h
-
-$(BLD)\w32faces.obj: \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\w32faces.c \
- $(SRC)\lisp.h \
- $(SRC)\w32term.h \
- $(SRC)\win32.h \
- $(SRC)\buffer.h \
- $(SRC)\dispextern.h \
- $(SRC)\frame.h \
- $(SRC)\blockinput.h \
- $(SRC)\window.h \
- $(SRC)\intervals.h
-
-$(BLD)\w32fns.obj: \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\w32fns.c \
- $(SRC)\lisp.h \
- $(SRC)\w32term.h \
- $(SRC)\win32.h \
- $(SRC)\frame.h \
- $(SRC)\window.h \
- $(SRC)\buffer.h \
- $(SRC)\dispextern.h \
- $(SRC)\keyboard.h \
- $(SRC)\blockinput.h \
- $(SRC)\paths.h \
- $(SRC)\w32heap.h \
- $(SRC)\termhooks.h
-
-$(BLD)\w32menu.obj: \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\w32menu.c \
- $(SRC)\lisp.h \
- $(SRC)\termhooks.h \
- $(SRC)\frame.h \
- $(SRC)\window.h \
- $(SRC)\keyboard.h \
- $(SRC)\blockinput.h \
- $(SRC)\buffer.h
-
-$(BLD)\w32term.obj: \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\w32term.c \
- $(SRC)\lisp.h \
- $(SRC)\blockinput.h \
- $(SRC)\w32term.h \
- $(SRC)\win32.h \
- $(SRC)\systty.h \
- $(SRC)\systime.h \
- $(SRC)\frame.h \
- $(SRC)\dispextern.h \
- $(SRC)\termhooks.h \
- $(SRC)\termopts.h \
- $(SRC)\termchar.h \
- $(SRC)\gnu.h \
- $(SRC)\disptab.h \
- $(SRC)\buffer.h \
- $(SRC)\window.h \
- $(SRC)\keyboard.h \
- $(SRC)\intervals.h
-
-$(BLD)\w32select.obj: \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\w32select.c \
- $(SRC)\lisp.h \
- $(SRC)\w32term.h \
- $(SRC)\win32.h \
- $(SRC)\dispextern.h \
- $(SRC)\frame.h \
- $(SRC)\blockinput.h
-
-$(BLD)\w32reg.obj: \
- $(EMACS_ROOT)\src\s\ms-w32.h \
- $(EMACS_ROOT)\src\m\intel386.h \
- $(EMACS_ROOT)\src\config.h \
- $(SRC)\w32reg.c \
- $(SRC)\lisp.h \
- $(SRC)\w32term.h \
- $(SRC)\win32.h \
- $(SRC)\blockinput.h
diff --git a/src/marker.c b/src/marker.c
deleted file mode 100644
index a11068d69df..00000000000
--- a/src/marker.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/* Markers: examining, setting and killing.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include "lisp.h"
-#include "buffer.h"
-
-/* Operations on markers. */
-
-DEFUN ("marker-buffer", Fmarker_buffer, Smarker_buffer, 1, 1, 0,
- "Return the buffer that MARKER points into, or nil if none.\n\
-Returns nil if MARKER points into a dead buffer.")
- (marker)
- register Lisp_Object marker;
-{
- register Lisp_Object buf;
- CHECK_MARKER (marker, 0);
- if (XMARKER (marker)->buffer)
- {
- XSETBUFFER (buf, XMARKER (marker)->buffer);
- /* Return marker's buffer only if it is not dead. */
- if (!NILP (XBUFFER (buf)->name))
- return buf;
- }
- return Qnil;
-}
-
-DEFUN ("marker-position", Fmarker_position, Smarker_position, 1, 1, 0,
- "Return the position MARKER points at, as a character number.")
- (marker)
- Lisp_Object marker;
-{
- register Lisp_Object pos;
- register int i;
- register struct buffer *buf;
-
- CHECK_MARKER (marker, 0);
- if (XMARKER (marker)->buffer)
- {
- buf = XMARKER (marker)->buffer;
- i = XMARKER (marker)->bufpos;
-
- if (i > BUF_GPT (buf) + BUF_GAP_SIZE (buf))
- i -= BUF_GAP_SIZE (buf);
- else if (i > BUF_GPT (buf))
- i = BUF_GPT (buf);
-
- if (i < BUF_BEG (buf) || i > BUF_Z (buf))
- abort ();
-
- XSETFASTINT (pos, i);
- return pos;
- }
- return Qnil;
-}
-
-DEFUN ("set-marker", Fset_marker, Sset_marker, 2, 3, 0,
- "Position MARKER before character number POSITION in BUFFER.\n\
-BUFFER defaults to the current buffer.\n\
-If POSITION is nil, makes marker point nowhere.\n\
-Then it no longer slows down editing in any buffer.\n\
-Returns MARKER.")
- (marker, position, buffer)
- Lisp_Object marker, position, buffer;
-{
- register int charno;
- register struct buffer *b;
- register struct Lisp_Marker *m;
-
- CHECK_MARKER (marker, 0);
- /* If position is nil or a marker that points nowhere,
- make this marker point nowhere. */
- if (NILP (position)
- || (MARKERP (position) && !XMARKER (position)->buffer))
- {
- unchain_marker (marker);
- return marker;
- }
-
- CHECK_NUMBER_COERCE_MARKER (position, 1);
- if (NILP (buffer))
- b = current_buffer;
- else
- {
- CHECK_BUFFER (buffer, 1);
- b = XBUFFER (buffer);
- /* If buffer is dead, set marker to point nowhere. */
- if (EQ (b->name, Qnil))
- {
- unchain_marker (marker);
- return marker;
- }
- }
-
- charno = XINT (position);
- m = XMARKER (marker);
-
- if (charno < BUF_BEG (b))
- charno = BUF_BEG (b);
- if (charno > BUF_Z (b))
- charno = BUF_Z (b);
- if (charno > BUF_GPT (b)) charno += BUF_GAP_SIZE (b);
- m->bufpos = charno;
-
- if (m->buffer != b)
- {
- unchain_marker (marker);
- m->buffer = b;
- m->chain = BUF_MARKERS (b);
- BUF_MARKERS (b) = marker;
- }
-
- return marker;
-}
-
-/* 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;
-{
- register int charno;
- register struct buffer *b;
- register struct Lisp_Marker *m;
-
- CHECK_MARKER (marker, 0);
- /* If position is nil or a marker that points nowhere,
- make this marker point nowhere. */
- if (NILP (pos) ||
- (MARKERP (pos) && !XMARKER (pos)->buffer))
- {
- unchain_marker (marker);
- return marker;
- }
-
- CHECK_NUMBER_COERCE_MARKER (pos, 1);
- if (NILP (buffer))
- b = current_buffer;
- else
- {
- CHECK_BUFFER (buffer, 1);
- b = XBUFFER (buffer);
- /* If buffer is dead, set marker to point nowhere. */
- if (EQ (b->name, Qnil))
- {
- unchain_marker (marker);
- return marker;
- }
- }
-
- charno = XINT (pos);
- m = XMARKER (marker);
-
- if (charno < BUF_BEGV (b))
- charno = BUF_BEGV (b);
- if (charno > BUF_ZV (b))
- charno = BUF_ZV (b);
- if (charno > BUF_GPT (b))
- charno += BUF_GAP_SIZE (b);
- m->bufpos = charno;
-
- if (m->buffer != b)
- {
- unchain_marker (marker);
- m->buffer = b;
- m->chain = BUF_MARKERS (b);
- BUF_MARKERS (b) = marker;
- }
-
- return marker;
-}
-
-/* This is called during garbage collection,
- 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;
-{
- register Lisp_Object tail, prev, next;
- register EMACS_INT omark;
- register struct buffer *b;
-
- b = XMARKER (marker)->buffer;
- if (b == 0)
- return;
-
- if (EQ (b->name, Qnil))
- abort ();
-
- tail = BUF_MARKERS (b);
- prev = Qnil;
- while (XSYMBOL (tail) != XSYMBOL (Qnil))
- {
- next = XMARKER (tail)->chain;
- XUNMARK (next);
-
- if (XMARKER (marker) == XMARKER (tail))
- {
- if (NILP (prev))
- {
- BUF_MARKERS (b) = next;
- /* Deleting first marker from the buffer's chain. Crash
- if new first marker in chain does not say it belongs
- to the same buffer, or at least that they have the same
- base buffer. */
- if (!NILP (next) && b->text != XMARKER (next)->buffer->text)
- abort ();
- }
- else
- {
- omark = XMARKBIT (XMARKER (prev)->chain);
- XMARKER (prev)->chain = next;
- XSETMARKBIT (XMARKER (prev)->chain, omark);
- }
- break;
- }
- else
- prev = tail;
- tail = next;
- }
- XMARKER (marker)->buffer = 0;
-}
-
-/* Return the buffer position of marker MARKER, as a C integer. */
-
-int
-marker_position (marker)
- Lisp_Object marker;
-{
- register struct Lisp_Marker *m = XMARKER (marker);
- register struct buffer *buf = m->buffer;
- register int i = m->bufpos;
-
- if (!buf)
- error ("Marker does not point anywhere");
-
- if (i > BUF_GPT (buf) + BUF_GAP_SIZE (buf))
- i -= BUF_GAP_SIZE (buf);
- else if (i > BUF_GPT (buf))
- i = BUF_GPT (buf);
-
- if (i < BUF_BEG (buf) || i > BUF_Z (buf))
- abort ();
-
- return i;
-}
-
-DEFUN ("copy-marker", Fcopy_marker, Scopy_marker, 1, 2, 0,
- "Return a new marker pointing at the same place as MARKER.\n\
-If argument is a number, makes a new marker pointing\n\
-at that position in the current buffer.\n\
-The optional argument TYPE specifies the insertion type of the new marker;\n\
-see `marker-insertion-type'.")
- (marker, type)
- register Lisp_Object marker, type;
-{
- register Lisp_Object new;
-
- if (INTEGERP (marker) || MARKERP (marker))
- {
- new = Fmake_marker ();
- Fset_marker (new, marker,
- (MARKERP (marker) ? Fmarker_buffer (marker) : Qnil));
- XMARKER (new)->insertion_type = !NILP (type);
- return new;
- }
- else
- marker = wrong_type_argument (Qinteger_or_marker_p, marker);
-}
-
-DEFUN ("marker-insertion-type", Fmarker_insertion_type,
- Smarker_insertion_type, 1, 1, 0,
- "Return insertion type of MARKER: t if it stays after inserted text.\n\
-nil means the marker stays before text inserted there.")
- (marker)
- register Lisp_Object marker;
-{
- register Lisp_Object buf;
- CHECK_MARKER (marker, 0);
- return XMARKER (marker)->insertion_type ? Qt : Qnil;
-}
-
-DEFUN ("set-marker-insertion-type", Fset_marker_insertion_type,
- Sset_marker_insertion_type, 2, 2, 0,
- "Set the insertion-type of MARKER to TYPE.\n\
-If TYPE is t, it means the marker advances when you insert text at it.\n\
-If TYPE is nil, it means the marker stays behind when you insert text at it.")
- (marker, type)
- Lisp_Object marker, type;
-{
- CHECK_MARKER (marker, 0);
-
- XMARKER (marker)->insertion_type = ! NILP (type);
- return type;
-}
-
-DEFUN ("buffer-has-markers-at", Fbuffer_has_markers_at, Sbuffer_has_markers_at,
- 1, 1, 0,
- "Return t if there are markers pointing at POSITION in the currentbuffer.")
- (position)
- Lisp_Object position;
-{
- register Lisp_Object tail;
- register int charno;
-
- charno = XINT (position);
-
- if (charno < BEG)
- charno = BEG;
- if (charno > Z)
- charno = Z;
- if (charno > GPT) charno += GAP_SIZE;
-
- for (tail = BUF_MARKERS (current_buffer);
- XSYMBOL (tail) != XSYMBOL (Qnil);
- tail = XMARKER (tail)->chain)
- if (XMARKER (tail)->bufpos == charno)
- return Qt;
-
- return Qnil;
-}
-
-syms_of_marker ()
-{
- defsubr (&Smarker_position);
- defsubr (&Smarker_buffer);
- defsubr (&Sset_marker);
- defsubr (&Scopy_marker);
- defsubr (&Smarker_insertion_type);
- defsubr (&Sset_marker_insertion_type);
- defsubr (&Sbuffer_has_markers_at);
-}
diff --git a/src/mem-limits.h b/src/mem-limits.h
deleted file mode 100644
index 333642f0c82..00000000000
--- a/src/mem-limits.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/* Includes for memory limit warnings.
- Copyright (C) 1990, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifdef MSDOS
-#include <dpmi.h>
-#endif
-
-/* Some systems need this before <sys/resource.h>. */
-#include <sys/types.h>
-
-#ifdef _LIBC
-
-#include <sys/resource.h>
-#define BSD4_2 /* Tell code below to use getrlimit. */
-
-/* Old Linux startup code won't define __data_start. */
-extern int etext, __data_start; weak_extern (__data_start)
-#define start_of_data() (&__data_start ?: &etext)
-
-#else /* not _LIBC */
-
-#if defined (__osf__) && (defined (__mips) || defined (mips) || defined(__alpha))
-#include <sys/time.h>
-#include <sys/resource.h>
-#endif
-
-#ifdef __bsdi__
-#define BSD4_2
-#endif
-
-#ifndef BSD4_2
-#ifndef USG
-#ifndef MSDOS
-#ifndef WINDOWSNT
-#include <sys/vlimit.h>
-#endif /* not WINDOWSNT */
-#endif /* not MSDOS */
-#endif /* not USG */
-#else /* if BSD4_2 */
-#include <sys/time.h>
-#include <sys/resource.h>
-#endif /* BSD4_2 */
-
-#ifdef emacs
-/* The important properties of this type are that 1) it's a pointer, and
- 2) arithmetic on it should work as if the size of the object pointed
- to has a size of 1. */
-#ifdef __STDC__
-typedef void *POINTER;
-#else
-typedef char *POINTER;
-#endif
-
-typedef unsigned long SIZE;
-
-#ifdef NULL
-#undef NULL
-#endif
-#define NULL ((POINTER) 0)
-
-extern POINTER start_of_data ();
-#ifdef DATA_SEG_BITS
-#define EXCEEDS_LISP_PTR(ptr) \
- (((EMACS_UINT) (ptr) & ~DATA_SEG_BITS) >> VALBITS)
-#else
-#define EXCEEDS_LISP_PTR(ptr) ((EMACS_UINT) (ptr) >> VALBITS)
-#endif
-
-#ifdef BSD_SYSTEM
-#ifndef DATA_SEG_BITS
-extern char etext;
-#define start_of_data() &etext
-#endif
-#endif
-
-#else /* not emacs */
-extern char etext;
-#define start_of_data() &etext
-#endif /* not emacs */
-
-#endif /* not _LIBC */
-
-
-/* start of data space; can be changed by calling malloc_init */
-static POINTER data_space_start;
-
-/* Number of bytes of writable memory we can expect to be able to get */
-static unsigned long lim_data;
-
-#ifdef NO_LIM_DATA
-static void
-get_lim_data ()
-{
- lim_data = -1;
-}
-#else /* not NO_LIM_DATA */
-
-#ifdef USG
-
-static void
-get_lim_data ()
-{
- extern long ulimit ();
-
- lim_data = -1;
-
- /* Use the ulimit call, if we seem to have it. */
-#if !defined (ULIMIT_BREAK_VALUE) || defined (LINUX)
- lim_data = ulimit (3, 0);
-#endif
-
- /* If that didn't work, just use the macro's value. */
-#ifdef ULIMIT_BREAK_VALUE
- if (lim_data == -1)
- lim_data = ULIMIT_BREAK_VALUE;
-#endif
-
- lim_data -= (long) data_space_start;
-}
-
-#else /* not USG */
-#ifdef WINDOWSNT
-
-static void
-get_lim_data ()
-{
- extern unsigned long data_region_size;
- lim_data = data_region_size;
-}
-
-#else
-#if !defined (BSD4_2) && !defined (__osf__)
-
-#ifdef MSDOS
-void
-get_lim_data ()
-{
- _go32_dpmi_meminfo info;
-
- _go32_dpmi_get_free_memory_information (&info);
- lim_data = info.available_memory;
-}
-#else /* not MSDOS */
-static void
-get_lim_data ()
-{
- lim_data = vlimit (LIM_DATA, -1);
-}
-#endif /* not MSDOS */
-
-#else /* BSD4_2 */
-
-static void
-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 /* BSD4_2 */
-#endif /* not WINDOWSNT */
-#endif /* not USG */
-#endif /* not NO_LIM_DATA */
diff --git a/src/minibuf.c b/src/minibuf.c
deleted file mode 100644
index e7f8a88e306..00000000000
--- a/src/minibuf.c
+++ /dev/null
@@ -1,2002 +0,0 @@
-/* Minibuffer input and completion.
- Copyright (C) 1985, 1986, 93, 94, 95, 1996 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include "lisp.h"
-#include "commands.h"
-#include "buffer.h"
-#include "dispextern.h"
-#include "frame.h"
-#include "window.h"
-#include "syntax.h"
-#include "keyboard.h"
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
-extern int quit_char;
-
-/* 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 deeper
- minibuffer recursions are encountered. */
-Lisp_Object Vminibuffer_list;
-
-/* Data to remember during recursive minibuffer invocations */
-Lisp_Object minibuf_save_list;
-
-/* Depth in minibuffer invocations. */
-int minibuf_level;
-
-/* Nonzero means display completion help for invalid input. */
-int auto_help;
-
-/* The maximum length of a minibuffer history. */
-Lisp_Object Qhistory_length, Vhistory_length;
-
-/* Fread_minibuffer leaves the input here as a string. */
-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;
-
-/* Variable which is the history list to add minibuffer values to. */
-
-Lisp_Object Vminibuffer_history_variable;
-
-/* Current position in the history list (adjusted by M-n and M-p). */
-
-Lisp_Object Vminibuffer_history_position;
-
-Lisp_Object Qminibuffer_history;
-
-Lisp_Object Qread_file_name_internal;
-
-/* Normal hooks for entry to and exit from minibuffer. */
-
-Lisp_Object Qminibuffer_setup_hook, Vminibuffer_setup_hook;
-Lisp_Object Qminibuffer_exit_hook, Vminibuffer_exit_hook;
-
-/* Nonzero means completion ignores case. */
-
-int completion_ignore_case;
-
-/* List of regexps that should restrict possible completions. */
-
-Lisp_Object Vcompletion_regexp_list;
-
-/* Nonzero means raise the minibuffer frame when the minibuffer
- is entered. */
-
-int minibuffer_auto_raise;
-
-/* If last completion attempt reported "Complete but not unique"
- then this is the string completed then; otherwise this is nil. */
-
-static Lisp_Object last_exact_completion;
-
-Lisp_Object Quser_variable_p;
-
-/* Non-nil means it is the window for C-M-v to scroll
- when the minibuffer is selected. */
-extern Lisp_Object Vminibuf_scroll_window;
-
-extern Lisp_Object Voverriding_local_map;
-
-/* Put minibuf on currently selected frame's minibuffer.
- We do this whenever the user starts a new minibuffer
- or when a minibuffer exits. */
-
-void
-choose_minibuf_frame ()
-{
- if (selected_frame != 0
- && !EQ (minibuf_window, selected_frame->minibuffer_window))
- {
- /* I don't think that any frames may validly have a null minibuffer
- window anymore. */
- if (NILP (selected_frame->minibuffer_window))
- abort ();
-
- Fset_window_buffer (selected_frame->minibuffer_window,
- XWINDOW (minibuf_window)->buffer);
- minibuf_window = selected_frame->minibuffer_window;
- }
-
- /* Make sure no other frame has a minibuffer as its selected window,
- because the text would not be displayed in it, and that would be
- confusing. Only allow the selected frame to do this,
- and that only if the minibuffer is active. */
- {
- Lisp_Object tail, frame;
-
- FOR_EACH_FRAME (tail, frame)
- if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (XFRAME (frame))))
- && !(XFRAME (frame) == selected_frame
- && minibuf_level > 0))
- Fset_frame_selected_window (frame, Fframe_first_window (frame));
- }
-}
-
-DEFUN ("set-minibuffer-window", Fset_minibuffer_window,
- Sset_minibuffer_window, 1, 1, 0,
- "Specify which minibuffer window to use for the minibuffer.\n\
-This effects where the minibuffer is displayed if you put text in it\n\
-without invoking the usual minibuffer commands.")
- (window)
- Lisp_Object window;
-{
- CHECK_WINDOW (window, 1);
- if (! MINI_WINDOW_P (XWINDOW (window)))
- error ("Window is not a minibuffer window");
-
- minibuf_window = window;
-
- return window;
-}
-
-
-/* Actual minibuffer invocation. */
-
-void read_minibuf_unwind ();
-Lisp_Object get_minibuffer ();
-Lisp_Object read_minibuf ();
-
-/* Read from the minibuffer using keymap MAP, initial contents INITIAL
- (a string), putting point minus BACKUP_N chars from the end of INITIAL,
- prompting with PROMPT (a string), using history list HISTVAR
- with initial position HISTPOS. (BACKUP_N should be <= 0.)
-
- Normally return the result as a string (the text that was read),
- but if EXPFLAG is nonzero, read it and return the object read.
- If HISTVAR is given, save the value read on that history only if it doesn't
- match the front of that history list exactly. The value is pushed onto
- the list as the string that was read. */
-
-Lisp_Object
-read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
- Lisp_Object map;
- Lisp_Object initial;
- Lisp_Object prompt;
- Lisp_Object backup_n;
- int expflag;
- Lisp_Object histvar;
- Lisp_Object histpos;
-{
- Lisp_Object val;
- int count = specpdl_ptr - specpdl;
- Lisp_Object mini_frame, ambient_dir;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- single_kboard_state ();
-
- val = Qnil;
- ambient_dir = current_buffer->directory;
-
- /* Don't need to protect PROMPT, HISTVAR, and HISTPOS because we
- store them away before we can GC. Don't need to protect
- BACKUP_N because we use the value only if it is an integer. */
- GCPRO4 (map, initial, val, ambient_dir);
-
- if (!STRINGP (prompt))
- prompt = build_string ("");
-
- if (!enable_recursive_minibuffers
- && minibuf_level > 0)
- {
- if (EQ (selected_window, minibuf_window))
- error ("Command attempted to use minibuffer while in minibuffer");
- else
- /* If we're in another window, cancel the minibuffer that's active. */
- Fthrow (Qexit,
- build_string ("Command attempted to use minibuffer while in minibuffer"));
- }
-
- /* Choose the minibuffer window and frame, and take action on them. */
-
- choose_minibuf_frame ();
-
- record_unwind_protect (Fset_window_configuration,
- Fcurrent_window_configuration (Qnil));
-
- /* If the minibuffer window is on a different frame, save that
- frame's configuration too. */
- mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
- if (XFRAME (mini_frame) != selected_frame)
- record_unwind_protect (Fset_window_configuration,
- Fcurrent_window_configuration (mini_frame));
-
- /* If the minibuffer is on an iconified or invisible frame,
- make it visible now. */
- Fmake_frame_visible (mini_frame);
-
- if (minibuffer_auto_raise)
- Fraise_frame (mini_frame);
-
- /* We have to do this after saving the window configuration
- since that is what restores the current buffer. */
-
- /* Arrange to restore a number of minibuffer-related variables.
- We could bind each variable separately, but that would use lots of
- specpdl slots. */
- minibuf_save_list
- = Fcons (Voverriding_local_map,
- Fcons (minibuf_window, minibuf_save_list));
- minibuf_save_list
- = Fcons (minibuf_prompt,
- Fcons (make_number (minibuf_prompt_width),
- Fcons (Vhelp_form,
- Fcons (Vcurrent_prefix_arg,
- Fcons (Vminibuffer_history_position,
- Fcons (Vminibuffer_history_variable,
- minibuf_save_list))))));
-
- record_unwind_protect (read_minibuf_unwind, Qnil);
- minibuf_level++;
-
- /* Now that we can restore all those variables, start changing them. */
-
- minibuf_prompt_width = 0; /* xdisp.c puts in the right value. */
- minibuf_prompt = Fcopy_sequence (prompt);
- Vminibuffer_history_position = histpos;
- Vminibuffer_history_variable = histvar;
- Vhelp_form = Vminibuffer_help_form;
-
- /* Switch to the minibuffer. */
-
- Fset_buffer (get_minibuffer (minibuf_level));
-
- /* The current buffer's default directory is usually the right thing
- for our minibuffer here. However, if you're typing a command at
- a minibuffer-only frame when minibuf_level is zero, then buf IS
- the current_buffer, so reset_buffer leaves buf's default
- directory unchanged. This is a bummer when you've just started
- up Emacs and buf's default directory is Qnil. Here's a hack; can
- you think of something better to do? Find another buffer with a
- better directory, and use that one instead. */
- if (STRINGP (ambient_dir))
- current_buffer->directory = ambient_dir;
- else
- {
- Lisp_Object buf_list;
-
- for (buf_list = Vbuffer_alist;
- CONSP (buf_list);
- buf_list = XCONS (buf_list)->cdr)
- {
- Lisp_Object other_buf;
-
- other_buf = XCONS (XCONS (buf_list)->car)->cdr;
- if (STRINGP (XBUFFER (other_buf)->directory))
- {
- current_buffer->directory = XBUFFER (other_buf)->directory;
- break;
- }
- }
- }
-
- if (XFRAME (mini_frame) != selected_frame)
- Fredirect_frame_focus (Fselected_frame (), mini_frame);
-
- Vminibuf_scroll_window = selected_window;
- Fset_window_buffer (minibuf_window, Fcurrent_buffer ());
- Fselect_window (minibuf_window);
- XSETFASTINT (XWINDOW (minibuf_window)->hscroll, 0);
-
- Fmake_local_variable (Qprint_escape_newlines);
- print_escape_newlines = 1;
-
- /* Erase the buffer. */
- {
- int count1 = specpdl_ptr - specpdl;
- specbind (Qinhibit_read_only, Qt);
- Ferase_buffer ();
- unbind_to (count1, Qnil);
- }
-
- /* Put in the initial input. */
- if (!NILP (initial))
- {
- Finsert (1, &initial);
- if (!NILP (backup_n) && INTEGERP (backup_n))
- Fforward_char (backup_n);
- }
-
- echo_area_glyphs = 0;
- /* This is in case the minibuffer-setup-hook calls Fsit_for. */
- previous_echo_glyphs = 0;
-
- current_buffer->keymap = map;
-
- /* Run our hook, but not if it is empty.
- (run-hooks would do nothing if it is empty,
- but it's important to save time here in the usual case). */
- if (!NILP (Vminibuffer_setup_hook) && !EQ (Vminibuffer_setup_hook, Qunbound)
- && !NILP (Vrun_hooks))
- call1 (Vrun_hooks, Qminibuffer_setup_hook);
-
-/* ??? MCC did redraw_screen here if switching screens. */
- recursive_edit_1 ();
-
- /* If cursor is on the minibuffer line,
- show the user we have exited by putting it in column 0. */
- if ((FRAME_CURSOR_Y (selected_frame)
- >= XFASTINT (XWINDOW (minibuf_window)->top))
- && !noninteractive)
- {
- FRAME_CURSOR_X (selected_frame)
- = FRAME_LEFT_SCROLL_BAR_WIDTH (selected_frame);
- update_frame (selected_frame, 1, 1);
- }
-
- /* Make minibuffer contents into a string */
- val = make_buffer_string (1, Z, 1);
-#if 0 /* make_buffer_string should handle the gap. */
- bcopy (GAP_END_ADDR, XSTRING (val)->data + GPT - BEG, Z - GPT);
-#endif
-
- /* VAL is the string of minibuffer text. */
- last_minibuf_string = val;
-
- /* Add the value to the appropriate history list unless it is empty. */
- if (XSTRING (val)->size != 0
- && SYMBOLP (Vminibuffer_history_variable)
- && ! EQ (XSYMBOL (Vminibuffer_history_variable)->value, Qunbound))
- {
- /* If the caller wanted to save the value read on a history list,
- then do so if the value is not already the front of the list. */
- Lisp_Object histval;
- histval = Fsymbol_value (Vminibuffer_history_variable);
-
- /* The value of the history variable must be a cons or nil. Other
- values are unacceptable. We silently ignore these values. */
- if (NILP (histval)
- || (CONSP (histval)
- && NILP (Fequal (last_minibuf_string, Fcar (histval)))))
- {
- Lisp_Object length;
-
- histval = Fcons (last_minibuf_string, histval);
- Fset (Vminibuffer_history_variable, histval);
-
- /* Truncate if requested. */
- length = Fget (Vminibuffer_history_variable, Qhistory_length);
- if (NILP (length)) length = Vhistory_length;
- if (INTEGERP (length)) {
- if (XINT (length) <= 0)
- Fset (Vminibuffer_history_variable, Qnil);
- else
- {
- Lisp_Object temp;
-
- temp = Fnthcdr (Fsub1 (length), histval);
- if (CONSP (temp)) Fsetcdr (temp, Qnil);
- }
- }
- }
- }
-
- /* If Lisp form desired instead of string, parse it. */
- if (expflag)
- {
- Lisp_Object expr_and_pos;
- unsigned char *p;
-
- expr_and_pos = Fread_from_string (val, Qnil, Qnil);
- /* Ignore trailing whitespace; any other trailing junk is an error. */
- for (p = XSTRING (val)->data + XINT (Fcdr (expr_and_pos)); *p; p++)
- if (*p != ' ' && *p != '\t' && *p != '\n')
- error ("Trailing garbage following expression");
- val = Fcar (expr_and_pos);
- }
-
- /* The appropriate frame will get selected
- in set-window-configuration. */
- RETURN_UNGCPRO (unbind_to (count, 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[24];
- extern Lisp_Object nconc2 ();
-
- XSETFASTINT (num, depth);
- tail = Fnthcdr (num, Vminibuffer_list);
- if (NILP (tail))
- {
- tail = Fcons (Qnil, Qnil);
- Vminibuffer_list = nconc2 (Vminibuffer_list, tail);
- }
- buf = Fcar (tail);
- if (NILP (buf) || NILP (XBUFFER (buf)->name))
- {
- sprintf (name, " *Minibuf-%d*", depth);
- buf = Fget_buffer_create (build_string (name));
-
- /* Although the buffer's name starts with a space, undo should be
- enabled in it. */
- Fbuffer_enable_undo (buf);
-
- XCONS (tail)->car = buf;
- }
- else
- {
- int count = specpdl_ptr - specpdl;
-
- reset_buffer (XBUFFER (buf));
- record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
- Fset_buffer (buf);
- Fkill_all_local_variables ();
- unbind_to (count, Qnil);
- }
-
- 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 (data)
- Lisp_Object data;
-{
- Lisp_Object old_deactivate_mark;
- Lisp_Object window;
-
- /* We are exiting the minibuffer one way or the other,
- so run the hook. */
- if (!NILP (Vminibuffer_exit_hook) && !EQ (Vminibuffer_exit_hook, Qunbound)
- && !NILP (Vrun_hooks))
- safe_run_hooks (Qminibuffer_exit_hook);
-
- /* If this was a recursive minibuffer,
- tie the minibuffer window back to the outer level minibuffer buffer. */
- minibuf_level--;
-
- window = minibuf_window;
- /* To keep things predictable, in case it matters, let's be in the minibuffer
- when we reset the relevant variables. */
- Fset_buffer (XWINDOW (window)->buffer);
-
- /* Restore prompt, etc, from outer minibuffer level. */
- minibuf_prompt = Fcar (minibuf_save_list);
- minibuf_save_list = Fcdr (minibuf_save_list);
- minibuf_prompt_width = XFASTINT (Fcar (minibuf_save_list));
- minibuf_save_list = Fcdr (minibuf_save_list);
- Vhelp_form = Fcar (minibuf_save_list);
- minibuf_save_list = Fcdr (minibuf_save_list);
- Vcurrent_prefix_arg = Fcar (minibuf_save_list);
- minibuf_save_list = Fcdr (minibuf_save_list);
- Vminibuffer_history_position = Fcar (minibuf_save_list);
- minibuf_save_list = Fcdr (minibuf_save_list);
- Vminibuffer_history_variable = Fcar (minibuf_save_list);
- minibuf_save_list = Fcdr (minibuf_save_list);
- Voverriding_local_map = Fcar (minibuf_save_list);
- minibuf_save_list = Fcdr (minibuf_save_list);
-#if 0
- temp = Fcar (minibuf_save_list);
- if (FRAME_LIVE_P (XFRAME (WINDOW_FRAME (XWINDOW (temp)))))
- minibuf_window = temp;
-#endif
- minibuf_save_list = Fcdr (minibuf_save_list);
-
- /* Erase the minibuffer we were using at this level. */
- {
- int count = specpdl_ptr - specpdl;
- /* Prevent error in erase-buffer. */
- specbind (Qinhibit_read_only, Qt);
- old_deactivate_mark = Vdeactivate_mark;
- Ferase_buffer ();
- Vdeactivate_mark = old_deactivate_mark;
- unbind_to (count, Qnil);
- }
-
- /* Make the minibuffer follow the selected frame
- (in case we are exiting a recursive minibuffer). */
- choose_minibuf_frame ();
-
- /* Make sure minibuffer window is erased, not ignored. */
- windows_or_buffers_changed++;
- XSETFASTINT (XWINDOW (window)->last_modified, 0);
- XSETFASTINT (XWINDOW (window)->last_overlay_modified, 0);
-}
-
-
-/* This comment supplies the doc string for read-from-minibuffer,
- for make-docfile to see. We cannot put this in the real DEFUN
- due to limits in the Unix cpp.
-
-DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1, 5, 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\
- If INITIAL-CONTENTS is (STRING . POSITION), the initial input\n\
- is STRING, but point is placed at position POSITION in the minibuffer.\n\
-Third arg KEYMAP is a keymap to use whilst reading;\n\
- if omitted or nil, the default is `minibuffer-local-map'.\n\
-If fourth arg READ is non-nil, then interpret the result as a lisp object\n\
- and return that object:\n\
- in other words, do `(car (read-from-string INPUT-STRING))'\n\
-Fifth arg HIST, if non-nil, specifies a history list\n\
- and optionally the initial position in the list.\n\
- It can be a symbol, which is the history list variable to use,\n\
- or it can be a cons cell (HISTVAR . HISTPOS).\n\
- In that case, HISTVAR is the history list variable to use,\n\
- and HISTPOS is the initial position (the position in the list\n\
- which INITIAL-CONTENTS corresponds to).\n\
- Positions are counted starting from 1 at the beginning of the list."
-*/
-
-DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1, 5, 0,
- 0 /* See immediately above */)
- (prompt, initial_contents, keymap, read, hist)
- Lisp_Object prompt, initial_contents, keymap, read, hist;
-{
- int pos = 0;
- Lisp_Object histvar, histpos, position;
- position = Qnil;
-
- CHECK_STRING (prompt, 0);
- if (!NILP (initial_contents))
- {
- if (CONSP (initial_contents))
- {
- position = Fcdr (initial_contents);
- initial_contents = Fcar (initial_contents);
- }
- CHECK_STRING (initial_contents, 1);
- if (!NILP (position))
- {
- CHECK_NUMBER (position, 0);
- /* Convert to distance from end of input. */
- if (XINT (position) < 1)
- /* A number too small means the beginning of the string. */
- pos = - XSTRING (initial_contents)->size;
- else
- pos = XINT (position) - 1 - XSTRING (initial_contents)->size;
- }
- }
-
- if (NILP (keymap))
- keymap = Vminibuffer_local_map;
- else
- keymap = get_keymap (keymap,2);
-
- if (SYMBOLP (hist))
- {
- histvar = hist;
- histpos = Qnil;
- }
- else
- {
- histvar = Fcar_safe (hist);
- histpos = Fcdr_safe (hist);
- }
- if (NILP (histvar))
- histvar = Qminibuffer_history;
- if (NILP (histpos))
- XSETFASTINT (histpos, 0);
-
- return read_minibuf (keymap, initial_contents, prompt,
- make_number (pos), !NILP (read), histvar, histpos);
-}
-
-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 (!NILP (initial_contents))
- CHECK_STRING (initial_contents, 1);
- return read_minibuf (Vminibuffer_local_map, initial_contents,
- prompt, Qnil, 1, Qminibuffer_history, make_number (0));
-}
-
-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, 3, 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.\n\
-The third arg HISTORY, if non-nil, specifies a history list\n\
- and optionally the initial position in the list.\n\
-See `read-from-minibuffer' for details of HISTORY argument.")
- (prompt, initial_input, history)
- Lisp_Object prompt, initial_input, history;
-{
- return Fread_from_minibuffer (prompt, initial_input, Qnil, Qnil, history);
-}
-
-DEFUN ("read-no-blanks-input", Fread_no_blanks_input, Sread_no_blanks_input, 1, 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);
- if (! NILP (init))
- CHECK_STRING (init, 1);
-
- return read_minibuf (Vminibuffer_local_ns_map, init, prompt, Qnil, 0,
- Qminibuffer_history, make_number (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),
- 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),
- 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),
- 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 (BUFFERP (def))
- def = XBUFFER (def)->name;
- if (!NILP (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, 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\
-ALIST can also be a function to do the completion itself.\n\
-It receives three arguments: the values STRING, PREDICATE and nil.\n\
-Whatever it returns becomes the value of `try-completion'.\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\n\
-or the symbol from the obarray.")
- (string, alist, predicate)
- Lisp_Object string, alist, predicate;
-{
- Lisp_Object bestmatch, tail, elt, eltstring;
- int bestmatchsize;
- int compare, matchsize;
- int list = CONSP (alist) || NILP (alist);
- int index, obsize;
- int matchcount = 0;
- Lisp_Object bucket, zero, end, tem;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- CHECK_STRING (string, 0);
- if (!list && !VECTORP (alist))
- return call3 (alist, string, predicate, Qnil);
-
- bestmatch = 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 (NILP (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
- XSETFASTINT (bucket, 0);
- }
- else if (++index >= obsize)
- break;
- else
- {
- bucket = XVECTOR (alist)->contents[index];
- continue;
- }
- }
-
- /* Is this element a possible completion? */
-
- if (STRINGP (eltstring)
- && XSTRING (string)->size <= XSTRING (eltstring)->size
- && 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
- XSTRING (string)->size))
- {
- /* Yes. */
- Lisp_Object regexps;
- Lisp_Object zero;
- XSETFASTINT (zero, 0);
-
- /* Ignore this element if it fails to match all the regexps. */
- for (regexps = Vcompletion_regexp_list; CONSP (regexps);
- regexps = XCONS (regexps)->cdr)
- {
- tem = Fstring_match (XCONS (regexps)->car, eltstring, zero);
- if (NILP (tem))
- break;
- }
- if (CONSP (regexps))
- continue;
-
- /* Ignore this element if there is a predicate
- and the predicate doesn't like it. */
-
- if (!NILP (predicate))
- {
- if (EQ (predicate, Qcommandp))
- tem = Fcommandp (elt);
- else
- {
- GCPRO4 (tail, string, eltstring, bestmatch);
- tem = call1 (predicate, elt);
- UNGCPRO;
- }
- if (NILP (tem)) continue;
- }
-
- /* Update computation of how much all possible completions match */
-
- matchcount++;
- if (NILP (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 more than one exact match ignoring case,
- and one of them is exact including case,
- prefer that one. */
- /* 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)
- && !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 (NILP (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;
-
- XSETFASTINT (zero, 0); /* Else extract the part in which */
- XSETFASTINT (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. */
-
-int
-scmp (s1, s2, len)
- register unsigned char *s1, *s2;
- int len;
-{
- register int l = len;
-
- if (completion_ignore_case)
- {
- while (l && DOWNCASE (*s1++) == DOWNCASE (*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, 4, 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\
-\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\
-ALIST can also be a function to do the completion itself.\n\
-It receives three arguments: the values STRING, PREDICATE and t.\n\
-Whatever it returns becomes the value of `all-completion'.\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\n\
-or the symbol from the obarray.\n\
-\n\
-If the optional fourth argument HIDE-SPACES is non-nil,\n\
-strings in ALIST that start with a space\n\
-are ignored unless STRING itself starts with a space.")
- (string, alist, predicate, hide_spaces)
- Lisp_Object string, alist, predicate, hide_spaces;
-{
- Lisp_Object tail, elt, eltstring;
- Lisp_Object allmatches;
- int list = CONSP (alist) || NILP (alist);
- int index, obsize;
- Lisp_Object bucket, tem;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- CHECK_STRING (string, 0);
- if (!list && !VECTORP (alist))
- {
- return call3 (alist, string, predicate, 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 (NILP (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
- XSETFASTINT (bucket, 0);
- }
- else if (++index >= obsize)
- break;
- else
- {
- bucket = XVECTOR (alist)->contents[index];
- continue;
- }
- }
-
- /* Is this element a possible completion? */
-
- if (STRINGP (eltstring)
- && XSTRING (string)->size <= XSTRING (eltstring)->size
- /* If HIDE_SPACES, reject alternatives that start with space
- unless the input starts with space. */
- && ((XSTRING (string)->size > 0 && XSTRING (string)->data[0] == ' ')
- || XSTRING (eltstring)->data[0] != ' '
- || NILP (hide_spaces))
- && 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
- XSTRING (string)->size))
- {
- /* Yes. */
- Lisp_Object regexps;
- Lisp_Object zero;
- XSETFASTINT (zero, 0);
-
- /* Ignore this element if it fails to match all the regexps. */
- for (regexps = Vcompletion_regexp_list; CONSP (regexps);
- regexps = XCONS (regexps)->cdr)
- {
- tem = Fstring_match (XCONS (regexps)->car, eltstring, zero);
- if (NILP (tem))
- break;
- }
- if (CONSP (regexps))
- continue;
-
- /* Ignore this element if there is a predicate
- and the predicate doesn't like it. */
-
- if (!NILP (predicate))
- {
- if (EQ (predicate, Qcommandp))
- tem = Fcommandp (elt);
- else
- {
- GCPRO4 (tail, eltstring, allmatches, string);
- tem = call1 (predicate, elt);
- UNGCPRO;
- }
- if (NILP (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;
-
-/* This comment supplies the doc string for completing-read,
- for make-docfile to see. We cannot put this in the real DEFUN
- due to limits in the Unix cpp.
-
-DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 6, 0,
- "Read a string in the minibuffer, with completion.\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.\n\
-PREDICATE limits completion to a subset of TABLE.\n\
-See `try-completion' and `all-completions' for more details
- on completion, TABLE, and PREDICATE.\n\
-\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 or is null.\n\
- If it is also not t, Return does not exit if it does non-null completion.\n\
-If the input is null, `completing-read' returns an empty string,\n\
- regardless of the value of REQUIRE-MATCH.\n\
-\n\
-If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.\n\
- If it is (STRING . POSITION), the initial input\n\
- is STRING, but point is placed POSITION characters into the string.\n\
-HIST, if non-nil, specifies a history list\n\
- and optionally the initial position in the list.\n\
- It can be a symbol, which is the history list variable to use,\n\
- or it can be a cons cell (HISTVAR . HISTPOS).\n\
- In that case, HISTVAR is the history list variable to use,\n\
- and HISTPOS is the initial position (the position in the list\n\
- which INITIAL-CONTENTS corresponds to).\n\
- Positions are counted starting from 1 at the beginning of the list.\n\
-Completion ignores case if the ambient value of\n\
- `completion-ignore-case' is non-nil."
-*/
-DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 6, 0,
- 0 /* See immediately above */)
- (prompt, table, predicate, require_match, init, hist)
- Lisp_Object prompt, table, predicate, require_match, init, hist;
-{
- Lisp_Object val, histvar, histpos, position;
- int pos = 0;
- int count = specpdl_ptr - specpdl;
- specbind (Qminibuffer_completion_table, table);
- specbind (Qminibuffer_completion_predicate, predicate);
- specbind (Qminibuffer_completion_confirm,
- EQ (require_match, Qt) ? Qnil : Qt);
- last_exact_completion = Qnil;
-
- position = Qnil;
- if (!NILP (init))
- {
- if (CONSP (init))
- {
- position = Fcdr (init);
- init = Fcar (init);
- }
- CHECK_STRING (init, 0);
- if (!NILP (position))
- {
- CHECK_NUMBER (position, 0);
- /* Convert to distance from end of input. */
- pos = XINT (position) - XSTRING (init)->size;
- }
- }
-
- if (SYMBOLP (hist))
- {
- histvar = hist;
- histpos = Qnil;
- }
- else
- {
- histvar = Fcar_safe (hist);
- histpos = Fcdr_safe (hist);
- }
- if (NILP (histvar))
- histvar = Qminibuffer_history;
- if (NILP (histpos))
- XSETFASTINT (histpos, 0);
-
- val = read_minibuf (NILP (require_match)
- ? Vminibuffer_local_completion_map
- : Vminibuffer_local_must_match_map,
- init, prompt, make_number (pos), 0,
- histvar, histpos);
- return unbind_to (count, val);
-}
-
-/* Temporarily display the string M at the end of the current
- minibuffer contents. This is used to display things like
- "[No Match]" when the user requests a completion for a prefix
- that has no possible completions, and other quick, unobtrusive
- messages. */
-
-temp_echo_area_glyphs (m)
- char *m;
-{
- int osize = ZV;
- int opoint = PT;
- Lisp_Object oinhibit;
- oinhibit = Vinhibit_quit;
-
- /* Clear out any old echo-area message to make way for our new thing. */
- message (0);
-
- SET_PT (osize);
- insert_string (m);
- SET_PT (opoint);
- Vinhibit_quit = Qt;
- Fsit_for (make_number (2), Qnil, Qnil);
- del_range (osize, ZV);
- SET_PT (opoint);
- if (!NILP (Vquit_flag))
- {
- Vquit_flag = Qnil;
- Vunread_command_events = Fcons (make_number (quit_char), Qnil);
- }
- Vinhibit_quit = oinhibit;
-}
-
-Lisp_Object Fminibuffer_completion_help ();
-Lisp_Object assoc_for_completion ();
-/* A subroutine of Fintern_soft. */
-extern Lisp_Object oblookup ();
-
-
-/* Test whether TXT is an exact completion. */
-Lisp_Object
-test_completion (txt)
- Lisp_Object txt;
-{
- Lisp_Object tem;
-
- if (CONSP (Vminibuffer_completion_table)
- || NILP (Vminibuffer_completion_table))
- return assoc_for_completion (txt, Vminibuffer_completion_table);
- else if (VECTORP (Vminibuffer_completion_table))
- {
- /* Bypass intern-soft as that loses for nil */
- tem = oblookup (Vminibuffer_completion_table,
- XSTRING (txt)->data, XSTRING (txt)->size);
- if (!SYMBOLP (tem))
- return Qnil;
- else if (!NILP (Vminibuffer_completion_predicate))
- return call1 (Vminibuffer_completion_predicate, tem);
- else
- return Qt;
- }
- else
- return call3 (Vminibuffer_completion_table, txt,
- Vminibuffer_completion_predicate, Qlambda);
-}
-
-/* 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;
- Lisp_Object last;
- struct gcpro gcpro1, gcpro2;
-
- completion = Ftry_completion (Fbuffer_string (), Vminibuffer_completion_table,
- Vminibuffer_completion_predicate);
- last = last_exact_completion;
- last_exact_completion = Qnil;
-
- GCPRO2 (completion, last);
-
- if (NILP (completion))
- {
- bitch_at_user ();
- temp_echo_area_glyphs (" [No match]");
- UNGCPRO;
- return 0;
- }
-
- if (EQ (completion, Qt)) /* exact and unique match */
- {
- UNGCPRO;
- return 1;
- }
-
- /* compiler bug */
- tem = Fstring_equal (completion, Fbuffer_string());
- if (completedp = NILP (tem))
- {
- Ferase_buffer (); /* Some completion happened */
- Finsert (1, &completion);
- }
-
- /* It did find a match. Do we match some possibility exactly now? */
- tem = test_completion (Fbuffer_string ());
- if (NILP (tem))
- {
- /* not an exact match */
- UNGCPRO;
- if (completedp)
- return 5;
- else if (auto_help)
- Fminibuffer_completion_help ();
- else
- temp_echo_area_glyphs (" [Next char not unique]");
- return 6;
- }
- else if (completedp)
- {
- UNGCPRO;
- return 4;
- }
- /* If the last exact completion and this one were the same,
- it means we've already given a "Complete but not unique"
- message and the user's hit TAB again, so now we give him help. */
- last_exact_completion = completion;
- if (!NILP (last))
- {
- tem = Fbuffer_string ();
- if (!NILP (Fequal (tem, last)))
- Fminibuffer_completion_help ();
- }
- UNGCPRO;
- return 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; !NILP (tail); tail = Fcdr (tail))
- {
- register Lisp_Object elt, tem, thiscar;
- elt = Fcar (tail);
- if (!CONSP (elt)) continue;
- thiscar = Fcar (elt);
- if (!STRINGP (thiscar))
- continue;
- if (completion_ignore_case)
- thiscar = Fupcase (thiscar);
- tem = Fequal (thiscar, key);
- if (!NILP (tem)) return elt;
- QUIT;
- }
- return Qnil;
-}
-
-DEFUN ("minibuffer-complete", Fminibuffer_complete, Sminibuffer_complete, 0, 0, "",
- "Complete the minibuffer contents as far as possible.\n\
-Return nil if there is no valid completion, else t.\n\
-If no characters can be completed, display a list of possible completions.\n\
-If you repeat this command after it displayed such a list,\n\
-scroll the window of possible completions.")
- ()
-{
- register int i;
- Lisp_Object window, tem;
-
- /* If the previous command was not this, then mark the completion
- buffer obsolete. */
- if (! EQ (current_kboard->Vlast_command, this_command))
- Vminibuf_scroll_window = Qnil;
-
- window = Vminibuf_scroll_window;
- /* If there's a fresh completion window with a live buffer,
- and this command is repeated, scroll that window. */
- if (! NILP (window) && ! NILP (XWINDOW (window)->buffer)
- && !NILP (XBUFFER (XWINDOW (window)->buffer)->name))
- {
- struct buffer *obuf = current_buffer;
-
- Fset_buffer (XWINDOW (window)->buffer);
- tem = Fpos_visible_in_window_p (make_number (ZV), window);
- if (! NILP (tem))
- /* If end is in view, scroll up to the beginning. */
- Fset_window_start (window, BEGV, Qnil);
- else
- /* Else scroll down one screen. */
- Fscroll_other_window (Qnil);
-
- set_buffer_internal (obuf);
- return Qnil;
- }
-
- i = do_completion ();
- switch (i)
- {
- case 0:
- return Qnil;
-
- case 1:
- temp_echo_area_glyphs (" [Sole completion]");
- break;
-
- case 3:
- temp_echo_area_glyphs (" [Complete, but not unique]");
- break;
- }
-
- return Qt;
-}
-
-/* Subroutines of Fminibuffer_complete_and_exit. */
-
-/* This one is called by internal_condition_case to do the real work. */
-
-Lisp_Object
-complete_and_exit_1 ()
-{
- return make_number (do_completion ());
-}
-
-/* This one is called by internal_condition_case if an error happens.
- Pretend the current value is an exact match. */
-
-Lisp_Object
-complete_and_exit_2 (ignore)
- Lisp_Object ignore;
-{
- return make_number (1);
-}
-
-DEFUN ("minibuffer-complete-and-exit", Fminibuffer_complete_and_exit,
- Sminibuffer_complete_and_exit, 0, 0, "",
- "If the minibuffer contents is a valid completion then exit.\n\
-Otherwise try to complete it. If completion leads to a valid completion,\n\
-a repetition of this command will exit.")
- ()
-{
- register int i;
- Lisp_Object val;
-
- /* Allow user to specify null string */
- if (BEGV == ZV)
- goto exit;
-
- if (!NILP (test_completion (Fbuffer_string ())))
- goto exit;
-
- /* Call do_completion, but ignore errors. */
- val = internal_condition_case (complete_and_exit_1, Qerror,
- complete_and_exit_2);
-
- i = XFASTINT (val);
- switch (i)
- {
- case 1:
- case 3:
- goto exit;
-
- case 4:
- if (!NILP (Vminibuffer_completion_confirm))
- {
- temp_echo_area_glyphs (" [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.\n\
-After one word is completed as much as possible, a space or hyphen\n\
-is added, provided that matches some possible completion.\n\
-Return nil if there is no valid completion, else t.")
- ()
-{
- Lisp_Object completion, tem;
- register int i;
- register unsigned char *completion_string;
- struct gcpro gcpro1, gcpro2;
-
- /* 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 (NILP (completion))
- {
- bitch_at_user ();
- temp_echo_area_glyphs (" [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;
-
- CHECK_STRING (completion, 0);
- tem = Fbuffer_string ();
- GCPRO2 (completion, tem);
- /* If reading a file name,
- expand any $ENVVAR refs in the buffer and in TEM. */
- if (EQ (Vminibuffer_completion_table, Qread_file_name_internal))
- {
- Lisp_Object substituted;
- substituted = Fsubstitute_in_file_name (tem);
- if (! EQ (substituted, tem))
- {
- tem = substituted;
- Ferase_buffer ();
- insert_from_string (tem, 0, XSTRING (tem)->size, 0);
- }
- }
- 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);
- }
- UNGCPRO;
- }
-#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)
- {
- GCPRO1 (completion);
- tem = Ftry_completion (concat2 (Fbuffer_string (), build_string (" ")),
- Vminibuffer_completion_table,
- Vminibuffer_completion_predicate);
- UNGCPRO;
-
- if (STRINGP (tem))
- completion = tem;
- else
- {
- GCPRO1 (completion);
- tem =
- Ftry_completion (concat2 (Fbuffer_string (), build_string ("-")),
- Vminibuffer_completion_table,
- Vminibuffer_completion_predicate);
- UNGCPRO;
-
- if (STRINGP (tem))
- 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 (auto_help)
- Fminibuffer_completion_help ();
- return Qnil;
- }
-
- /* Otherwise insert in minibuffer the chars we got */
-
- Ferase_buffer ();
- insert_from_string (completion, 0, i, 1);
- return Qt;
-}
-
-DEFUN ("display-completion-list", Fdisplay_completion_list, Sdisplay_completion_list,
- 1, 1, 0,
- "Display the list of completions, COMPLETIONS, using `standard-output'.\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.\n\
-`standard-output' must be a buffer.\n\
-At the end, run the normal hook `completion-setup-hook'.\n\
-It can find the completion buffer in `standard-output'.")
- (completions)
- Lisp_Object completions;
-{
- Lisp_Object tail, elt;
- register int i;
- int column = 0;
- struct gcpro gcpro1, gcpro2;
- struct buffer *old = current_buffer;
- int first = 1;
-
- /* Note that (when it matters) every variable
- points to a non-string that is pointed to by COMPLETIONS,
- except for ELT. ELT can be pointing to a string
- when terpri or Findent_to calls a change hook. */
- elt = Qnil;
- GCPRO2 (completions, elt);
-
- if (BUFFERP (Vstandard_output))
- set_buffer_internal (XBUFFER (Vstandard_output));
-
- if (NILP (completions))
- write_string ("There are no possible completions of what you have typed.",
- -1);
- else
- {
- write_string ("Possible completions are:", -1);
- for (tail = completions, i = 0; !NILP (tail); tail = Fcdr (tail), i++)
- {
- Lisp_Object tem;
- int length;
- Lisp_Object startpos, endpos;
-
- elt = Fcar (tail);
- /* Compute the length of this element. */
- if (CONSP (elt))
- {
- tem = Fcar (elt);
- CHECK_STRING (tem, 0);
- length = XINT (XSTRING (tem)->size);
-
- tem = Fcar (Fcdr (elt));
- CHECK_STRING (tem, 0);
- length += XINT (XSTRING (tem)->size);
- }
- else
- {
- CHECK_STRING (elt, 0);
- length = XINT (XSTRING (elt)->size);
- }
-
- /* This does a bad job for narrower than usual windows.
- Sadly, the window it will appear in is not known
- until after the text has been made. */
-
- if (BUFFERP (Vstandard_output))
- XSETINT (startpos, BUF_PT (XBUFFER (Vstandard_output)));
-
- /* If the previous completion was very wide,
- or we have two on this line already,
- don't put another on the same line. */
- if (column > 33 || first
- /* If this is really wide, don't put it second on a line. */
- || column > 0 && length > 45)
- {
- Fterpri (Qnil);
- column = 0;
- }
- /* Otherwise advance to column 35. */
- else
- {
- if (BUFFERP (Vstandard_output))
- {
- tem = Findent_to (make_number (35), make_number (2));
-
- column = XINT (tem);
- }
- else
- {
- do
- {
- write_string (" ", -1);
- column++;
- }
- while (column < 35);
- }
- }
-
- if (BUFFERP (Vstandard_output))
- {
- XSETINT (endpos, BUF_PT (XBUFFER (Vstandard_output)));
- Fset_text_properties (startpos, endpos,
- Qnil, Vstandard_output);
- }
-
- /* Output this element and update COLUMN. */
- if (CONSP (elt))
- {
- Fprinc (Fcar (elt), Qnil);
- Fprinc (Fcar (Fcdr (elt)), Qnil);
- }
- else
- Fprinc (elt, Qnil);
-
- column += length;
-
- /* If output is to a buffer, recompute COLUMN in a way
- that takes account of character widths. */
- if (BUFFERP (Vstandard_output))
- {
- tem = Fcurrent_column ();
- column = XINT (tem);
- }
-
- first = 0;
- }
- }
-
- UNGCPRO;
-
- if (BUFFERP (Vstandard_output))
- set_buffer_internal (old);
-
- if (!NILP (Vrun_hooks))
- call1 (Vrun_hooks, intern ("completion-setup-hook"));
-
- 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,
- Qt);
- echo_area_glyphs = 0;
-
- if (NILP (completions))
- {
- bitch_at_user ();
- temp_echo_area_glyphs (" [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.")
- ()
-{
- if (INTEGERP (last_command_char))
- internal_self_insert (last_command_char, 0);
- else
- bitch_at_user ();
-
- 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);
-}
-
-DEFUN ("minibuffer-prompt", Fminibuffer_prompt, Sminibuffer_prompt, 0, 0, 0,
- "Return the prompt string of the currently-active minibuffer.\n\
-If no minibuffer is active, return nil.")
- ()
-{
- return Fcopy_sequence (minibuf_prompt);
-}
-
-DEFUN ("minibuffer-prompt-width", Fminibuffer_prompt_width,
- Sminibuffer_prompt_width, 0, 0, 0,
- "Return the display width of the minibuffer prompt.")
- ()
-{
- Lisp_Object width;
- XSETFASTINT (width, minibuf_prompt_width);
- return width;
-}
-
-init_minibuf_once ()
-{
- Vminibuffer_list = Qnil;
- staticpro (&Vminibuffer_list);
-}
-
-syms_of_minibuf ()
-{
- minibuf_level = 0;
- minibuf_prompt = Qnil;
- staticpro (&minibuf_prompt);
-
- minibuf_save_list = Qnil;
- staticpro (&minibuf_save_list);
-
- Qread_file_name_internal = intern ("read-file-name-internal");
- staticpro (&Qread_file_name_internal);
-
- 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_exact_completion);
- last_exact_completion = Qnil;
-
- staticpro (&last_minibuf_string);
- last_minibuf_string = Qnil;
-
- Quser_variable_p = intern ("user-variable-p");
- staticpro (&Quser_variable_p);
-
- Qminibuffer_history = intern ("minibuffer-history");
- staticpro (&Qminibuffer_history);
-
- Qminibuffer_setup_hook = intern ("minibuffer-setup-hook");
- staticpro (&Qminibuffer_setup_hook);
-
- Qminibuffer_exit_hook = intern ("minibuffer-exit-hook");
- staticpro (&Qminibuffer_exit_hook);
-
- Qhistory_length = intern ("history-length");
- staticpro (&Qhistory_length);
-
- DEFVAR_LISP ("minibuffer-setup-hook", &Vminibuffer_setup_hook,
- "Normal hook run just after entry to minibuffer.");
- Vminibuffer_setup_hook = Qnil;
-
- DEFVAR_LISP ("minibuffer-exit-hook", &Vminibuffer_exit_hook,
- "Normal hook run just after exit from minibuffer.");
- Vminibuffer_exit_hook = Qnil;
-
- DEFVAR_LISP ("history-length", &Vhistory_length,
- "*Maximum length for history lists before truncation takes place.\n\
-A number means that length; t means infinite. Truncation takes place\n\
-just after a new element is inserted. Setting the history-length\n\
-property of a history variable overrides this default.");
- XSETFASTINT (Vhistory_length, 30);
-
- DEFVAR_BOOL ("completion-auto-help", &auto_help,
- "*Non-nil means automatically provide help for invalid completion input.");
- 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 minibuffer commands while in the minibuffer.\n\
-More precisely, this variable makes a difference when the minibuffer window\n\
-is the selected window. If you are in some other window, minibuffer commands\n\
-are allowed even if a minibuffer is active.");
- enable_recursive_minibuffers = 0;
-
- DEFVAR_LISP ("minibuffer-completion-table", &Vminibuffer_completion_table,
- "Alist or obarray used for completion in the minibuffer.\n\
-This becomes the ALIST argument to `try-completion' and `all-completion'.\n\
-\n\
-The value may alternatively be a function, which is given three arguments:\n\
- STRING, the current buffer contents;\n\
- PREDICATE, the predicate for filtering possible matches;\n\
- CODE, which says what kind of things to do.\n\
-CODE can be nil, t or `lambda'.\n\
-nil means to return the best completion of STRING, or nil if there is none.\n\
-t means to return a list of all possible completions of STRING.\n\
-`lambda' means to return t if STRING is a valid completion as it stands.");
- Vminibuffer_completion_table = Qnil;
-
- DEFVAR_LISP ("minibuffer-completion-predicate", &Vminibuffer_completion_predicate,
- "Within call to `completing-read', this holds the PREDICATE argument.");
- 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;
-
- DEFVAR_LISP ("minibuffer-history-variable", &Vminibuffer_history_variable,
- "History list symbol to add minibuffer values to.\n\
-Each string of minibuffer input, as it appears on exit from the minibuffer,\n\
-is added with\n\
- (set minibuffer-history-variable\n\
- (cons STRING (symbol-value minibuffer-history-variable)))");
- XSETFASTINT (Vminibuffer_history_variable, 0);
-
- DEFVAR_LISP ("minibuffer-history-position", &Vminibuffer_history_position,
- "Current position of redoing in the history list.");
- Vminibuffer_history_position = Qnil;
-
- DEFVAR_BOOL ("minibuffer-auto-raise", &minibuffer_auto_raise,
- "*Non-nil means entering the minibuffer raises the minibuffer's frame.\n\
-Some uses of the echo area also raise that frame (since they use it too).");
- minibuffer_auto_raise = 0;
-
- DEFVAR_LISP ("completion-regexp-list", &Vcompletion_regexp_list,
- "List of regexps that should restrict possible completions.");
- Vcompletion_regexp_list = Qnil;
-
- defsubr (&Sset_minibuffer_window);
- 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 (&Sminibuffer_prompt);
- defsubr (&Sminibuffer_prompt_width);
-
- 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 ()
-{
- initial_define_key (Vminibuffer_local_map, Ctl ('g'),
- "abort-recursive-edit");
- initial_define_key (Vminibuffer_local_map, Ctl ('m'),
- "exit-minibuffer");
- initial_define_key (Vminibuffer_local_map, Ctl ('j'),
- "exit-minibuffer");
-
- initial_define_key (Vminibuffer_local_ns_map, Ctl ('g'),
- "abort-recursive-edit");
- initial_define_key (Vminibuffer_local_ns_map, Ctl ('m'),
- "exit-minibuffer");
- initial_define_key (Vminibuffer_local_ns_map, Ctl ('j'),
- "exit-minibuffer");
-
- initial_define_key (Vminibuffer_local_ns_map, ' ',
- "exit-minibuffer");
- initial_define_key (Vminibuffer_local_ns_map, '\t',
- "exit-minibuffer");
- initial_define_key (Vminibuffer_local_ns_map, '?',
- "self-insert-and-exit");
-
- initial_define_key (Vminibuffer_local_completion_map, Ctl ('g'),
- "abort-recursive-edit");
- initial_define_key (Vminibuffer_local_completion_map, Ctl ('m'),
- "exit-minibuffer");
- initial_define_key (Vminibuffer_local_completion_map, Ctl ('j'),
- "exit-minibuffer");
-
- initial_define_key (Vminibuffer_local_completion_map, '\t',
- "minibuffer-complete");
- initial_define_key (Vminibuffer_local_completion_map, ' ',
- "minibuffer-complete-word");
- initial_define_key (Vminibuffer_local_completion_map, '?',
- "minibuffer-completion-help");
-
- initial_define_key (Vminibuffer_local_must_match_map, Ctl ('g'),
- "abort-recursive-edit");
- initial_define_key (Vminibuffer_local_must_match_map, Ctl ('m'),
- "minibuffer-complete-and-exit");
- initial_define_key (Vminibuffer_local_must_match_map, Ctl ('j'),
- "minibuffer-complete-and-exit");
- initial_define_key (Vminibuffer_local_must_match_map, '\t',
- "minibuffer-complete");
- initial_define_key (Vminibuffer_local_must_match_map, ' ',
- "minibuffer-complete-word");
- initial_define_key (Vminibuffer_local_must_match_map, '?',
- "minibuffer-completion-help");
-}
diff --git a/src/mocklisp.c b/src/mocklisp.c
deleted file mode 100644
index ad6ae9908c7..00000000000
--- a/src/mocklisp.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/* Mocklisp compatibility functions for GNU Emacs Lisp interpreter.
- Copyright (C) 1985, 1986, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Compatibility for mocklisp */
-
-#include <config.h>
-#include "lisp.h"
-#include "buffer.h"
-
-/* Now in lisp code ("macrocode...")
-* DEFUN ("ml-defun", Fml_defun, Sml_defun, 0, UNEVALLED, 0,
-* "Define mocklisp functions")
-* (args)
-* Lisp_Object args;
-* {
-* Lisp_Object elt;
-*
-* while (!NILP (args))
-* {
-* elt = Fcar (args);
-* Ffset (Fcar (elt), Fcons (Qmocklisp, Fcdr (elt)));
-* args = Fcdr (args);
-* }
-* return Qnil;
-* }
-*/
-
-DEFUN ("ml-if", Fml_if, Sml_if, 0, UNEVALLED, 0, "Mocklisp version of `if'.")
- (args)
- Lisp_Object args;
-{
- register Lisp_Object val;
- struct gcpro gcpro1;
-
- GCPRO1 (args);
- while (!NILP (args))
- {
- val = Feval (Fcar (args));
- args = Fcdr (args);
- if (NILP (args)) break;
- if (XINT (val))
- {
- val = Feval (Fcar (args));
- break;
- }
- args = Fcdr (args);
- }
- UNGCPRO;
- return val;
-}
-
-/* Now converted to regular "while" by hairier conversion code.
-* DEFUN ("ml-while", Fml_while, Sml_while, 1, UNEVALLED, 0, "while for mocklisp programs")
-* (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), XINT (tem))
-* {
-* QUIT;
-* Fprogn (body);
-* }
-*
-* UNGCPRO;
-* return Qnil;
-*}
-
-/* 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 */
-
-Lisp_Object
-ml_apply (function, args)
- Lisp_Object function, args;
-{
- register int count = specpdl_ptr - specpdl;
- register Lisp_Object val;
-
- specbind (Qmocklisp_arguments, args);
- val = Fprogn (Fcdr (function));
- return unbind_to (count, val);
-}
-
-DEFUN ("ml-nargs", Fml_nargs, Sml_nargs, 0, 0, 0,
- "Number of arguments to currently executing mocklisp function.")
- ()
-{
- if (EQ (Vmocklisp_arguments, Qinteractive))
- return make_number (0);
- return Flength (Vmocklisp_arguments);
-}
-
-DEFUN ("ml-arg", Fml_arg, Sml_arg, 1, 2, 0,
- "Argument number N to currently executing mocklisp function.")
- (n, prompt)
- Lisp_Object n, prompt;
-{
- if (EQ (Vmocklisp_arguments, Qinteractive))
- return Fread_string (prompt, Qnil);
- CHECK_NUMBER (n, 0);
- XSETINT (n, XINT (n) - 1); /* Mocklisp likes to be origin-1 */
- return Fcar (Fnthcdr (n, Vmocklisp_arguments));
-}
-
-DEFUN ("ml-interactive", Fml_interactive, Sml_interactive, 0, 0, 0,
- "True if currently executing mocklisp function was called interactively.")
- ()
-{
- return (EQ (Vmocklisp_arguments, Qinteractive)) ? Qt : Qnil;
-}
-
-DEFUN ("ml-provide-prefix-argument", Fml_provide_prefix_argument, Sml_provide_prefix_argument,
- 2, UNEVALLED, 0,
- "Evaluate second argument, using first argument as prefix arg value.")
- (args)
- Lisp_Object args;
-{
- struct gcpro gcpro1;
- GCPRO1 (args);
- Vcurrent_prefix_arg = Feval (Fcar (args));
- UNGCPRO;
- return Feval (Fcar (Fcdr (args)));
-}
-
-DEFUN ("ml-prefix-argument-loop", Fml_prefix_argument_loop, Sml_prefix_argument_loop,
- 0, UNEVALLED, 0,
- "")
- (args)
- Lisp_Object args;
-{
- register Lisp_Object tem;
- register int i;
- struct gcpro gcpro1;
-
- /* Set `arg' in case we call a built-in function that looks at it. Still are a few. */
- if (NILP (Vcurrent_prefix_arg))
- i = 1;
- else
- {
- tem = Vcurrent_prefix_arg;
- if (CONSP (tem))
- tem = Fcar (tem);
- if (EQ (tem, Qminus))
- i = -1;
- else i = XINT (tem);
- }
-
- GCPRO1 (args);
- while (i-- > 0)
- Fprogn (args);
- UNGCPRO;
- return Qnil;
-}
-
-#if 0 /* 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\
-If either FROM or LENGTH is negative, the length of STRING is added to it.")
- (string, from, to)
- Lisp_Object string, from, to;
-{
- CHECK_STRING (string, 0);
- CHECK_NUMBER (from, 1);
- CHECK_NUMBER (to, 2);
-
- if (XINT (from) < 0)
- XSETINT (from, XINT (from) + XSTRING (string)->size);
- if (XINT (to) < 0)
- XSETINT (to, XINT (to) + XSTRING (string)->size);
- XSETINT (to, XINT (to) + XINT (from));
- return Fsubstring (string, from, to);
-}
-#endif /* 0 */
-DEFUN ("insert-string", Finsert_string, Sinsert_string, 0, MANY, 0,
- "Mocklisp-compatibility insert function.\n\
-Like the function `insert' except that any argument that is a number\n\
-is converted into a string by expressing it in decimal.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
-{
- register int argnum;
- register Lisp_Object tem;
-
- for (argnum = 0; argnum < nargs; argnum++)
- {
- tem = args[argnum];
- retry:
- if (INTEGERP (tem))
- tem = Fnumber_to_string (tem);
- if (STRINGP (tem))
- insert1 (tem);
- else
- {
- tem = wrong_type_argument (Qstringp, tem);
- goto retry;
- }
- }
-
- return Qnil;
-}
-
-
-syms_of_mocklisp ()
-{
- Qmocklisp = intern ("mocklisp");
- staticpro (&Qmocklisp);
-
-/*defsubr (&Sml_defun);*/
- defsubr (&Sml_if);
-/*defsubr (&Sml_while);*/
- defsubr (&Sml_arg);
- defsubr (&Sml_nargs);
- defsubr (&Sml_interactive);
- defsubr (&Sml_provide_prefix_argument);
- defsubr (&Sml_prefix_argument_loop);
-/*defsubr (&Sml_substr);*/
- defsubr (&Sinsert_string);
-}
diff --git a/src/mocklisp.h b/src/mocklisp.h
deleted file mode 100644
index 1ec7756ac13..00000000000
--- a/src/mocklisp.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Fundamental definitions for emulating mocklisp.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* 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 Finsert_string ();
diff --git a/src/msdos.c b/src/msdos.c
deleted file mode 100644
index d809fffd46a..00000000000
--- a/src/msdos.c
+++ /dev/null
@@ -1,3334 +0,0 @@
-/* MS-DOS specific C utilities.
- Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Contributed by Morten Welinder */
-/* New display, keyboard, and mouse control by Kim F. Storm */
-
-/* Note: some of the stuff here was taken from end of sysdep.c in demacs. */
-
-#include <config.h>
-
-#ifdef MSDOS
-#include "lisp.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <dos.h>
-#include <errno.h>
-#include <sys/stat.h> /* for _fixpath */
-#if __DJGPP__ >= 2
-#include <fcntl.h>
-#include <dpmi.h> /* for __dpmi_xxx stuff */
-#include <sys/farptr.h> /* for _farsetsel, _farnspokeb */
-#include <libc/dosio.h> /* for _USE_LFN */
-#endif
-
-#include "dosfns.h"
-#include "msdos.h"
-#include "systime.h"
-#include "termhooks.h"
-#include "dispextern.h"
-#include "termopts.h"
-#include "frame.h"
-#include "window.h"
-#include "buffer.h"
-#include "commands.h"
-#include <go32.h>
-#include <pc.h>
-#include <ctype.h>
-/* #include <process.h> */
-/* Damn that local process.h! Instead we can define P_WAIT ourselves. */
-#define P_WAIT 1
-
-#ifndef _USE_LFN
-#define _USE_LFN 0
-#endif
-
-#ifndef _dos_ds
-#define _dos_ds _go32_info_block.selector_for_linear_memory
-#endif
-
-#if __DJGPP__ > 1
-
-#include <signal.h>
-
-#ifndef SYSTEM_MALLOC
-
-#ifdef GNU_MALLOC
-
-/* If other `malloc' than ours is used, force our `sbrk' behave like
- Unix programs expect (resize memory blocks to keep them contiguous).
- If `sbrk' from `ralloc.c' is NOT used, also zero-out sbrk'ed memory,
- because that's what `gmalloc' expects to get. */
-#include <crt0.h>
-
-#ifdef REL_ALLOC
-int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK;
-#else /* not REL_ALLOC */
-int _crt0_startup_flags = (_CRT0_FLAG_UNIX_SBRK | _CRT0_FLAG_FILL_SBRK_MEMORY);
-#endif /* not REL_ALLOC */
-#endif /* GNU_MALLOC */
-
-#endif /* not SYSTEM_MALLOC */
-#endif /* __DJGPP__ > 1 */
-
-static unsigned long
-event_timestamp ()
-{
- struct time t;
- unsigned long s;
-
- gettime (&t);
- s = t.ti_min;
- s *= 60;
- s += t.ti_sec;
- s *= 1000;
- s += t.ti_hund * 10;
-
- return s;
-}
-
-
-/* ------------------------ Mouse control ---------------------------
- *
- * Coordinates are in screen positions and zero based.
- * Mouse buttons are numbered from left to right and also zero based.
- */
-
-int have_mouse; /* 0: no, 1: enabled, -1: disabled */
-static int mouse_visible;
-
-static int mouse_last_x;
-static int mouse_last_y;
-
-static int mouse_button_translate[NUM_MOUSE_BUTTONS];
-static int mouse_button_count;
-
-void
-mouse_on ()
-{
- union REGS regs;
-
- if (have_mouse > 0 && !mouse_visible)
- {
- if (termscript)
- fprintf (termscript, "<M_ON>");
- regs.x.ax = 0x0001;
- int86 (0x33, &regs, &regs);
- mouse_visible = 1;
- }
-}
-
-void
-mouse_off ()
-{
- union REGS regs;
-
- if (have_mouse > 0 && mouse_visible)
- {
- if (termscript)
- fprintf (termscript, "<M_OFF>");
- regs.x.ax = 0x0002;
- int86 (0x33, &regs, &regs);
- mouse_visible = 0;
- }
-}
-
-void
-mouse_moveto (x, y)
- int x, y;
-{
- union REGS regs;
-
- if (termscript)
- fprintf (termscript, "<M_XY=%dx%d>", x, y);
- regs.x.ax = 0x0004;
- mouse_last_x = regs.x.cx = x * 8;
- mouse_last_y = regs.x.dx = y * 8;
- int86 (0x33, &regs, &regs);
-}
-
-static int
-mouse_pressed (b, xp, yp)
- int b, *xp, *yp;
-{
- union REGS regs;
-
- if (b >= mouse_button_count)
- return 0;
- regs.x.ax = 0x0005;
- regs.x.bx = mouse_button_translate[b];
- int86 (0x33, &regs, &regs);
- if (regs.x.bx)
- *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
- return (regs.x.bx != 0);
-}
-
-static int
-mouse_released (b, xp, yp)
- int b, *xp, *yp;
-{
- union REGS regs;
-
- if (b >= mouse_button_count)
- return 0;
- regs.x.ax = 0x0006;
- regs.x.bx = mouse_button_translate[b];
- int86 (0x33, &regs, &regs);
- if (regs.x.bx)
- *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
- return (regs.x.bx != 0);
-}
-
-static void
-mouse_get_xy (int *x, int *y)
-{
- union REGS regs;
-
- regs.x.ax = 0x0003;
- int86 (0x33, &regs, &regs);
- *x = regs.x.cx / 8;
- *y = regs.x.dx / 8;
-}
-
-void
-mouse_get_pos (f, insist, bar_window, part, x, y, time)
- FRAME_PTR *f;
- int insist;
- Lisp_Object *bar_window, *x, *y;
- enum scroll_bar_part *part;
- unsigned long *time;
-{
- int ix, iy;
- union REGS regs;
-
- regs.x.ax = 0x0003;
- int86 (0x33, &regs, &regs);
- *f = selected_frame;
- *bar_window = Qnil;
- mouse_get_xy (&ix, &iy);
- selected_frame->mouse_moved = 0;
- *x = make_number (ix);
- *y = make_number (iy);
- *time = event_timestamp ();
-}
-
-static void
-mouse_check_moved ()
-{
- int x, y;
-
- mouse_get_xy (&x, &y);
- selected_frame->mouse_moved |= (x != mouse_last_x || y != mouse_last_y);
- mouse_last_x = x;
- mouse_last_y = y;
-}
-
-void
-mouse_init ()
-{
- union REGS regs;
-
- if (termscript)
- fprintf (termscript, "<M_INIT>");
-
- regs.x.ax = 0x0021;
- int86 (0x33, &regs, &regs);
-
- regs.x.ax = 0x0007;
- regs.x.cx = 0;
- regs.x.dx = 8 * (ScreenCols () - 1);
- int86 (0x33, &regs, &regs);
-
- regs.x.ax = 0x0008;
- regs.x.cx = 0;
- regs.x.dx = 8 * (ScreenRows () - 1);
- int86 (0x33, &regs, &regs);
-
- mouse_moveto (0, 0);
- mouse_visible = 0;
-}
-
-/* ------------------------- Screen control ----------------------
- *
- */
-
-static int internal_terminal = 0;
-
-#ifndef HAVE_X_WINDOWS
-extern unsigned char ScreenAttrib;
-static int screen_face;
-static int highlight;
-
-static int screen_size_X;
-static int screen_size_Y;
-static int screen_size;
-
-static int current_pos_X;
-static int current_pos_Y;
-static int new_pos_X;
-static int new_pos_Y;
-
-static void *startup_screen_buffer;
-static int startup_screen_size_X;
-static int startup_screen_size_Y;
-static int startup_pos_X;
-static int startup_pos_Y;
-static unsigned char startup_screen_attrib;
-
-static int term_setup_done;
-
-/* Similar to the_only_frame. */
-struct x_output the_only_x_display;
-
-/* This is never dereferenced. */
-Display *x_current_display;
-
-static
-dos_direct_output (y, x, buf, len)
- int y;
- int x;
- char *buf;
- int len;
-{
- int t = (int) ScreenPrimary + 2 * (x + y * screen_size_X);
-
-#if (__DJGPP__ < 2)
- while (--len >= 0) {
- dosmemput (buf++, 1, t);
- t += 2;
- }
-#else
- /* This is faster. */
- for (_farsetsel (_dos_ds); --len >= 0; t += 2, buf++)
- _farnspokeb (t, *buf);
-#endif
-}
-#endif
-
-/* Flash the screen as a substitute for BEEPs. */
-
-#if (__DJGPP__ < 2)
-static void
-do_visible_bell (xorattr)
- unsigned char xorattr;
-{
- asm volatile
- (" movb $1,%%dl
-visible_bell_0:
- movl _ScreenPrimary,%%eax
- call dosmemsetup
- movl %%eax,%%ebx
- movl %1,%%ecx
- movb %0,%%al
- incl %%ebx
-visible_bell_1:
- xorb %%al,%%gs:(%%ebx)
- addl $2,%%ebx
- decl %%ecx
- jne visible_bell_1
- decb %%dl
- jne visible_bell_3
-visible_bell_2:
- movzwl %%ax,%%eax
- movzwl %%ax,%%eax
- movzwl %%ax,%%eax
- movzwl %%ax,%%eax
- decw %%cx
- jne visible_bell_2
- jmp visible_bell_0
-visible_bell_3:"
- : /* no output */
- : "m" (xorattr), "g" (screen_size)
- : "%eax", "%ebx", /* "%gs",*/ "%ecx", "%edx");
-}
-
-static void
-ScreenVisualBell (void)
-{
- /* This creates an xor-mask that will swap the default fore- and
- background colors. */
- do_visible_bell (((the_only_x_display.foreground_pixel
- ^ the_only_x_display.background_pixel)
- * 0x11) & 0x7f);
-}
-#endif
-
-#ifndef HAVE_X_WINDOWS
-
-static int blink_bit = -1; /* the state of the blink bit at startup */
-
-/* Enable bright background colors. */
-static void
-bright_bg (void)
-{
- union REGS regs;
-
- /* Remember the original state of the blink/bright-background bit.
- It is stored at 0040:0065h in the BIOS data area. */
- if (blink_bit == -1)
- blink_bit = (_farpeekb (_dos_ds, 0x465) & 0x20) == 0x20;
-
- regs.h.bl = 0;
- regs.x.ax = 0x1003;
- int86 (0x10, &regs, &regs);
-}
-
-/* Disable bright background colors (and enable blinking) if we found
- the video system in that state at startup. */
-static void
-maybe_enable_blinking (void)
-{
- if (blink_bit == 1)
- {
- union REGS regs;
-
- regs.h.bl = 1;
- regs.x.ax = 0x1003;
- int86 (0x10, &regs, &regs);
- }
-}
-
-/* Set the screen dimensions so that it can show no less than
- ROWS x COLS frame. */
-
-void
-dos_set_window_size (rows, cols)
- int *rows, *cols;
-{
- char video_name[30];
- Lisp_Object video_mode;
- int video_mode_value;
- int have_vga = 0;
- union REGS regs;
- int current_rows = ScreenRows (), current_cols = ScreenCols ();
-
- if (*rows == current_rows && *cols == current_cols)
- return;
-
- /* Do we have a VGA? */
- regs.x.ax = 0x1a00;
- int86 (0x10, &regs, &regs);
- if (regs.h.al == 0x1a && regs.h.bl > 5 && regs.h.bl < 13)
- have_vga = 1;
-
- mouse_off ();
-
- /* If the user specified a special video mode for these dimensions,
- use that mode. */
- sprintf (video_name, "screen-dimensions-%dx%d", *rows, *cols);
- video_mode = XSYMBOL (Fintern_soft (build_string (video_name),
- Qnil))-> value;
-
- if (INTEGERP (video_mode)
- && (video_mode_value = XINT (video_mode)) > 0)
- {
- regs.x.ax = video_mode_value;
- int86 (0x10, &regs, &regs);
-
- if (have_mouse)
- {
- /* Must hardware-reset the mouse, or else it won't update
- its notion of screen dimensions for some non-standard
- video modes. This is *painfully* slow... */
- regs.x.ax = 0;
- int86 (0x33, &regs, &regs);
- }
- }
-
- /* Find one of the dimensions supported by standard EGA/VGA
- which gives us at least the required dimensions. */
-
-#if __DJGPP__ > 1
-
- else
- {
- static struct {
- int rows;
- int need_vga;
- } std_dimension[] = {
- {25, 0},
- {28, 1},
- {35, 0},
- {40, 1},
- {43, 0},
- {50, 1}
- };
- int i = 0;
-
- while (i < sizeof (std_dimension) / sizeof (std_dimension[0]))
- {
- if (std_dimension[i].need_vga <= have_vga
- && std_dimension[i].rows >= *rows)
- {
- if (std_dimension[i].rows != current_rows
- || *cols != current_cols)
- _set_screen_lines (std_dimension[i].rows);
- break;
- }
- i++;
- }
- }
-
-#else /* not __DJGPP__ > 1 */
-
- else if (*rows <= 25)
- {
- if (current_rows != 25 || current_cols != 80)
- {
- regs.x.ax = 3;
- int86 (0x10, &regs, &regs);
- regs.x.ax = 0x1101;
- regs.h.bl = 0;
- int86 (0x10, &regs, &regs);
- regs.x.ax = 0x1200;
- regs.h.bl = 32;
- int86 (0x10, &regs, &regs);
- regs.x.ax = 3;
- int86 (0x10, &regs, &regs);
- }
- }
- else if (*rows <= 50)
- if (have_vga && (current_rows != 50 || current_cols != 80)
- || *rows <= 43 && (current_rows != 43 || current_cols != 80))
- {
- regs.x.ax = 3;
- int86 (0x10, &regs, &regs);
- regs.x.ax = 0x1112;
- regs.h.bl = 0;
- int86 (0x10, &regs, &regs);
- regs.x.ax = 0x1200;
- regs.h.bl = 32;
- int86 (0x10, &regs, &regs);
- regs.x.ax = 0x0100;
- regs.x.cx = 7;
- int86 (0x10, &regs, &regs);
- }
-#endif /* not __DJGPP__ > 1 */
-
- if (have_mouse)
- {
- mouse_init ();
- mouse_on ();
- }
-
- /* Tell the caller what dimensions have been REALLY set. */
- *rows = ScreenRows ();
- *cols = ScreenCols ();
-
- /* Enable bright background colors. */
- bright_bg ();
-}
-
-/* If we write a character in the position where the mouse is,
- the mouse cursor may need to be refreshed. */
-
-static void
-mouse_off_maybe ()
-{
- int x, y;
-
- if (!mouse_visible)
- return;
-
- mouse_get_xy (&x, &y);
- if (y != new_pos_Y || x < new_pos_X)
- return;
-
- mouse_off ();
-}
-
-static
-IT_ring_bell ()
-{
- if (visible_bell)
- {
- mouse_off ();
- ScreenVisualBell ();
- }
- else
- {
- union REGS inregs, outregs;
- inregs.h.ah = 2;
- inregs.h.dl = 7;
- intdos (&inregs, &outregs);
- }
-}
-
-static void
-IT_set_face (int face)
-{
- struct face *fp;
- extern struct face *intern_face (/* FRAME_PTR, struct face * */);
-
- if (face == 1 || (face == 0 && highlight))
- fp = FRAME_MODE_LINE_FACE (foo);
- else if (face <= 0 || face >= FRAME_N_COMPUTED_FACES (foo))
- fp = FRAME_DEFAULT_FACE (foo);
- else
- fp = intern_face (selected_frame, FRAME_COMPUTED_FACES (foo)[face]);
- if (termscript)
- fprintf (termscript, "<FACE:%d:%d>", FACE_FOREGROUND (fp), FACE_BACKGROUND (fp));
- screen_face = face;
- ScreenAttrib = (FACE_BACKGROUND (fp) << 4) | FACE_FOREGROUND (fp);
-}
-
-static
-IT_write_glyphs (GLYPH *str, int len)
-{
- int newface;
- int ch, l = len;
- unsigned char *buf, *bp;
-
- if (len == 0) return;
-
- buf = bp = alloca (len * 2);
-
- while (--l >= 0)
- {
- newface = FAST_GLYPH_FACE (*str);
- if (newface != screen_face)
- IT_set_face (newface);
- ch = FAST_GLYPH_CHAR (*str);
- *bp++ = (unsigned char)ch;
- *bp++ = ScreenAttrib;
-
- if (termscript)
- fputc (ch, termscript);
- str++;
- }
-
- mouse_off_maybe ();
- dosmemput (buf, 2 * len,
- (int)ScreenPrimary + 2 * (new_pos_X + screen_size_X * new_pos_Y));
- new_pos_X += len;
-}
-
-static
-IT_clear_end_of_line (first_unused)
-{
- char *spaces, *sp;
- int i, j;
-
- IT_set_face (0);
- if (termscript)
- fprintf (termscript, "<CLR:EOL>");
- i = (j = screen_size_X - new_pos_X) * 2;
- spaces = sp = alloca (i);
-
- while (--j >= 0)
- {
- *sp++ = ' ';
- *sp++ = ScreenAttrib;
- }
-
- mouse_off_maybe ();
- dosmemput (spaces, i,
- (int)ScreenPrimary + 2 * (new_pos_X + screen_size_X * new_pos_Y));
-}
-
-static
-IT_clear_screen (void)
-{
- if (termscript)
- fprintf (termscript, "<CLR:SCR>");
- IT_set_face (0);
- mouse_off ();
- ScreenClear ();
- new_pos_X = new_pos_Y = 0;
-}
-
-static
-IT_clear_to_end (void)
-{
- if (termscript)
- fprintf (termscript, "<CLR:EOS>");
-
- while (new_pos_Y < screen_size_Y) {
- new_pos_X = 0;
- IT_clear_end_of_line (0);
- new_pos_Y++;
- }
-}
-
-static
-IT_cursor_to (int y, int x)
-{
- if (termscript)
- fprintf (termscript, "\n<XY=%dx%d>", x, y);
- new_pos_X = x;
- new_pos_Y = y;
-}
-
-static int cursor_cleared;
-
-static
-IT_display_cursor (int on)
-{
- if (on && cursor_cleared)
- {
- ScreenSetCursor (current_pos_Y, current_pos_X);
- cursor_cleared = 0;
- }
- else if (!on && !cursor_cleared)
- {
- ScreenSetCursor (-1, -1);
- cursor_cleared = 1;
- }
-}
-
-/* Emacs calls cursor-movement functions a lot when it updates the
- display (probably a legacy of old terminals where you cannot
- update a screen line without first moving the cursor there).
- However, cursor movement is expensive on MSDOS (it calls a slow
- BIOS function and requires 2 mode switches), while actual screen
- updates access the video memory directly and don't depend on
- cursor position. To avoid slowing down the redisplay, we cheat:
- all functions that move the cursor only set internal variables
- which record the cursor position, whereas the cursor is only
- moved to its final position whenever screen update is complete.
-
- `IT_cmgoto' is called from the keyboard reading loop and when the
- frame update is complete. This means that we are ready for user
- input, so we update the cursor position to show where the point is,
- and also make the mouse pointer visible.
-
- Special treatment is required when the cursor is in the echo area,
- to put the cursor at the end of the text displayed there. */
-
-static
-IT_cmgoto (f)
- FRAME_PTR f;
-{
- /* Only set the cursor to where it should be if the display is
- already in sync with the window contents. */
- int update_cursor_pos = MODIFF == unchanged_modified;
-
- /* If we are in the echo area, put the cursor at the end of text. */
- if (!update_cursor_pos
- && XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top) <= new_pos_Y)
- {
- new_pos_X = FRAME_DESIRED_GLYPHS (f)->used[new_pos_Y];
- update_cursor_pos = 1;
- }
-
- if (update_cursor_pos
- && (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y))
- {
- ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X);
- if (termscript)
- fprintf (termscript, "\n<CURSOR:%dx%d>", current_pos_X, current_pos_Y);
- }
-
- /* Maybe cursor is invisible, so make it visible. */
- IT_display_cursor (1);
-
- /* Mouse pointer should be always visible if we are waiting for
- keyboard input. */
- if (!mouse_visible)
- mouse_on ();
-}
-
-static
-IT_reassert_line_highlight (new, vpos)
- int new, vpos;
-{
- highlight = new;
- IT_set_face (0); /* To possibly clear the highlighting. */
-}
-
-static
-IT_change_line_highlight (new_highlight, vpos, first_unused_hpos)
-{
- highlight = new_highlight;
- IT_set_face (0); /* To possibly clear the highlighting. */
- IT_cursor_to (vpos, 0);
- IT_clear_end_of_line (first_unused_hpos);
-}
-
-static
-IT_update_begin ()
-{
- highlight = 0;
- IT_set_face (0); /* To possibly clear the highlighting. */
- screen_face = -1;
-}
-
-static
-IT_update_end ()
-{
-}
-
-/* This was more or less copied from xterm.c
-
- Nowadays, the corresponding function under X is `x_set_menu_bar_lines_1'
- on xfns.c */
-
-static void
-IT_set_menu_bar_lines (window, n)
- Lisp_Object window;
- int n;
-{
- struct window *w = XWINDOW (window);
-
- XSETFASTINT (w->last_modified, 0);
- XSETFASTINT (w->last_overlay_modified, 0);
- XSETFASTINT (w->top, XFASTINT (w->top) + n);
- XSETFASTINT (w->height, XFASTINT (w->height) - n);
-
- /* Handle just the top child in a vertical split. */
- if (!NILP (w->vchild))
- IT_set_menu_bar_lines (w->vchild, n);
-
- /* Adjust all children in a horizontal split. */
- for (window = w->hchild; !NILP (window); window = w->next)
- {
- w = XWINDOW (window);
- IT_set_menu_bar_lines (window, n);
- }
-}
-
-/* This was copied from xfns.c */
-
-void
-x_set_menu_bar_lines (f, value, oldval)
- struct frame *f;
- Lisp_Object value, oldval;
-{
- int nlines;
- int olines = FRAME_MENU_BAR_LINES (f);
-
- /* Right now, menu bars don't work properly in minibuf-only frames;
- most of the commands try to apply themselves to the minibuffer
- frame itslef, and get an error because you can't switch buffers
- in or split the minibuffer window. */
- if (FRAME_MINIBUF_ONLY_P (f))
- return;
-
- if (INTEGERP (value))
- nlines = XINT (value);
- else
- nlines = 0;
-
- FRAME_MENU_BAR_LINES (f) = nlines;
- IT_set_menu_bar_lines (f->root_window, nlines - olines);
-}
-
-/* IT_set_terminal_modes is called when emacs is started,
- resumed, and whenever the screen is redrawn! */
-
-static
-IT_set_terminal_modes (void)
-{
- char *colors;
- FRAME_PTR f;
- struct face *fp;
-
- if (termscript)
- fprintf (termscript, "\n<SET_TERM>");
- highlight = 0;
-
- screen_size_X = ScreenCols ();
- screen_size_Y = ScreenRows ();
- screen_size = screen_size_X * screen_size_Y;
-
- new_pos_X = new_pos_Y = 0;
- current_pos_X = current_pos_Y = -1;
-
- if (term_setup_done)
- return;
- term_setup_done = 1;
-
- startup_screen_size_X = screen_size_X;
- startup_screen_size_Y = screen_size_Y;
- startup_screen_attrib = ScreenAttrib;
-
- ScreenGetCursor (&startup_pos_Y, &startup_pos_X);
- ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2));
-
- if (termscript)
- fprintf (termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n",
- screen_size_X, screen_size_Y);
-
- bright_bg ();
-}
-
-/* IT_reset_terminal_modes is called when emacs is
- suspended or killed. */
-
-static
-IT_reset_terminal_modes (void)
-{
- int display_row_start = (int) ScreenPrimary;
- int saved_row_len = startup_screen_size_X * 2;
- int update_row_len = ScreenCols () * 2;
- int current_rows = ScreenRows ();
- int to_next_row = update_row_len;
- unsigned char *saved_row = startup_screen_buffer;
- int cursor_pos_X = ScreenCols () - 1;
- int cursor_pos_Y = ScreenRows () - 1;
-
- if (termscript)
- fprintf (termscript, "\n<RESET_TERM>");
-
- highlight = 0;
-
- if (!term_setup_done)
- return;
-
- mouse_off ();
-
- /* Leave the video system in the same state as we found it,
- as far as the blink/bright-background bit is concerned. */
- maybe_enable_blinking ();
-
- /* We have a situation here.
- We cannot just do ScreenUpdate(startup_screen_buffer) because
- the luser could have changed screen dimensions inside Emacs
- and failed (or didn't want) to restore them before killing
- Emacs. ScreenUpdate() uses the *current* screen dimensions and
- thus will happily use memory outside what was allocated for
- `startup_screen_buffer'.
- Thus we only restore as much as the current screen dimensions
- can hold, and clear the rest (if the saved screen is smaller than
- the current) with the color attribute saved at startup. The cursor
- is also restored within the visible dimensions. */
-
- ScreenAttrib = startup_screen_attrib;
- ScreenClear ();
-
- if (update_row_len > saved_row_len)
- update_row_len = saved_row_len;
- if (current_rows > startup_screen_size_Y)
- current_rows = startup_screen_size_Y;
-
- if (termscript)
- fprintf (termscript, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
- update_row_len / 2, current_rows);
-
- while (current_rows--)
- {
- dosmemput (saved_row, update_row_len, display_row_start);
- saved_row += saved_row_len;
- display_row_start += to_next_row;
- }
- if (startup_pos_X < cursor_pos_X)
- cursor_pos_X = startup_pos_X;
- if (startup_pos_Y < cursor_pos_Y)
- cursor_pos_Y = startup_pos_Y;
-
- ScreenSetCursor (cursor_pos_Y, cursor_pos_X);
- xfree (startup_screen_buffer);
-
- term_setup_done = 0;
-}
-
-static
-IT_set_terminal_window (void)
-{
-}
-
-void
-IT_set_frame_parameters (f, alist)
- FRAME_PTR f;
- Lisp_Object alist;
-{
- Lisp_Object tail;
- int redraw;
- extern unsigned long load_color ();
-
- redraw = 0;
- for (tail = alist; CONSP (tail); tail = Fcdr (tail))
- {
- Lisp_Object elt, prop, val;
-
- elt = Fcar (tail);
- prop = Fcar (elt);
- val = Fcdr (elt);
- CHECK_SYMBOL (prop, 1);
-
- if (EQ (prop, intern ("foreground-color")))
- {
- unsigned long new_color = load_color (f, val);
- if (new_color != ~0)
- {
- FRAME_FOREGROUND_PIXEL (f) = new_color;
- redraw = 1;
- if (termscript)
- fprintf (termscript, "<FGCOLOR %d>\n", new_color);
- }
- }
- else if (EQ (prop, intern ("background-color")))
- {
- unsigned long new_color = load_color (f, val);
- if (new_color != ~0)
- {
- FRAME_BACKGROUND_PIXEL (f) = new_color;
- redraw = 1;
- if (termscript)
- fprintf (termscript, "<BGCOLOR %d>\n", new_color);
- }
- }
- else if (EQ (prop, intern ("menu-bar-lines")))
- x_set_menu_bar_lines (f, val, 0);
- }
-
- if (redraw)
- {
- recompute_basic_faces (f);
- if (f == selected_frame)
- redraw_frame (f);
- }
-}
-
-#endif /* !HAVE_X_WINDOWS */
-
-
-/* Do we need the internal terminal? */
-
-void
-internal_terminal_init ()
-{
- char *term = getenv ("TERM");
- char *colors;
-
-#ifdef HAVE_X_WINDOWS
- if (!inhibit_window_system)
- return;
-#endif
-
- internal_terminal
- = (!noninteractive) && term && !strcmp (term, "internal");
-
- if (getenv ("EMACSTEST"))
- termscript = fopen (getenv ("EMACSTEST"), "wt");
-
-#ifndef HAVE_X_WINDOWS
- if (!internal_terminal || inhibit_window_system)
- {
- selected_frame->output_method = output_termcap;
- return;
- }
-
- Vwindow_system = intern ("pc");
- Vwindow_system_version = make_number (1);
-
- bzero (&the_only_x_display, sizeof the_only_x_display);
- the_only_x_display.background_pixel = 7; /* White */
- the_only_x_display.foreground_pixel = 0; /* Black */
- bright_bg ();
- colors = getenv ("EMACSCOLORS");
- if (colors && strlen (colors) >= 2)
- {
- /* The colors use 4 bits each (we enable bright background). */
- if (isdigit (colors[0]))
- colors[0] -= '0';
- else if (isxdigit (colors[0]))
- colors[0] -= (isupper (colors[0]) ? 'A' : 'a') - 10;
- if (colors[0] >= 0 && colors[0] < 16)
- the_only_x_display.foreground_pixel = colors[0];
- if (isdigit (colors[1]))
- colors[1] -= '0';
- else if (isxdigit (colors[1]))
- colors[1] -= (isupper (colors[1]) ? 'A' : 'a') - 10;
- if (colors[1] >= 0 && colors[1] < 16)
- the_only_x_display.background_pixel = colors[1];
- }
- the_only_x_display.line_height = 1;
- the_only_x_display.font = (XFontStruct *)1; /* must *not* be zero */
-
- init_frame_faces (selected_frame);
-
- ring_bell_hook = IT_ring_bell;
- write_glyphs_hook = IT_write_glyphs;
- cursor_to_hook = raw_cursor_to_hook = IT_cursor_to;
- clear_to_end_hook = IT_clear_to_end;
- clear_end_of_line_hook = IT_clear_end_of_line;
- clear_frame_hook = IT_clear_screen;
- change_line_highlight_hook = IT_change_line_highlight;
- update_begin_hook = IT_update_begin;
- update_end_hook = IT_update_end;
- reassert_line_highlight_hook = IT_reassert_line_highlight;
- frame_up_to_date_hook = IT_cmgoto; /* position cursor when update is done */
-
- /* These hooks are called by term.c without being checked. */
- set_terminal_modes_hook = IT_set_terminal_modes;
- reset_terminal_modes_hook = IT_reset_terminal_modes;
- set_terminal_window_hook = IT_set_terminal_window;
-#endif
-}
-
-dos_get_saved_screen (screen, rows, cols)
- char **screen;
- int *rows;
- int *cols;
-{
-#ifndef HAVE_X_WINDOWS
- *screen = startup_screen_buffer;
- *cols = startup_screen_size_X;
- *rows = startup_screen_size_Y;
- return 1;
-#else
- return 0;
-#endif
-}
-
-#ifndef HAVE_X_WINDOWS
-
-/* We are not X, but we can emulate it well enough for our needs... */
-void
-check_x (void)
-{
- if (! FRAME_MSDOS_P (selected_frame))
- error ("Not running under a windows system");
-}
-
-#endif
-
-
-/* ----------------------- Keyboard control ----------------------
- *
- * Keymaps reflect the following keyboard layout:
- *
- * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS
- * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41)
- * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET
- * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT
- * SPACE
- */
-
-static int extended_kbd; /* 101 (102) keyboard present. */
-
-struct dos_keyboard_map
-{
- char *unshifted;
- char *shifted;
- char *alt_gr;
-};
-
-
-static struct dos_keyboard_map us_keyboard = {
-/* 0 1 2 3 4 5 */
-/* 01234567890123456789012345678901234567890 12345678901234 */
- "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ",
-/* 0123456789012345678901234567890123456789 012345678901234 */
- "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ",
- 0 /* no Alt-Gr key */
-};
-
-static struct dos_keyboard_map fr_keyboard = {
-/* 0 1 2 3 4 5 */
-/* 012 3456789012345678901234567890123456789012345678901234 */
- "ý&‚\",(-Š_€…)= azertyuiop^$ qsdfghjklm—* wxcvbnm;:! ",
-/* 0123456789012345678901234567890123456789012345678901234 */
- " 1234567890ø+ AZERTYUIOPùœ QSDFGHJKLM%æ WXCVBN?./õ ",
-/* 01234567 89012345678901234567890123456789012345678901234 */
- " ~#{[|`\\^@]} Ï "
-};
-
-static struct dos_keyboard_map dk_keyboard = {
-/* 0 1 2 3 4 5 */
-/* 0123456789012345678901234567890123456789012345678901234 */
- "«1234567890+| qwertyuiop†~ asdfghjkl‘›' zxcvbnm,.- ",
-/* 01 23456789012345678901234567890123456789012345678901234 */
- "õ!\"#$%&/()=?` QWERTYUIOP^ ASDFGHJKL’* ZXCVBNM;:_ ",
-/* 0123456789012345678901234567890123456789012345678901234 */
- " @œ$ {[]} | "
-};
-
-static struct keyboard_layout_list
-{
- int country_code;
- struct dos_keyboard_map *keyboard_map;
-} keyboard_layout_list[] =
-{
- 1, &us_keyboard,
- 33, &fr_keyboard,
- 45, &dk_keyboard
-};
-
-static struct dos_keyboard_map *keyboard;
-static int keyboard_map_all;
-static int international_keyboard;
-
-int
-dos_set_keyboard (code, always)
- int code;
- int always;
-{
- int i;
- union REGS regs;
-
- /* See if Keyb.Com is installed (for international keyboard support). */
- regs.x.ax = 0xad80;
- int86 (0x2f, &regs, &regs);
- if (regs.h.al == 0xff)
- international_keyboard = 1;
-
- /* Initialize to US settings, for countries that don't have their own. */
- keyboard = keyboard_layout_list[0].keyboard_map;
- keyboard_map_all = always;
- dos_keyboard_layout = 1;
-
- for (i = 0; i < (sizeof (keyboard_layout_list)/sizeof (struct keyboard_layout_list)); i++)
- if (code == keyboard_layout_list[i].country_code)
- {
- keyboard = keyboard_layout_list[i].keyboard_map;
- keyboard_map_all = always;
- dos_keyboard_layout = code;
- return 1;
- }
- return 0;
-}
-
-#define Ignore 0x0000
-#define Normal 0x0000 /* normal key - alt changes scan-code */
-#define FctKey 0x1000 /* func key if c == 0, else c */
-#define Special 0x2000 /* func key even if c != 0 */
-#define ModFct 0x3000 /* special if mod-keys, else 'c' */
-#define Map 0x4000 /* alt scan-code, map to unshift/shift key */
-#define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */
-#define Grey 0x6000 /* Grey keypad key */
-
-#define Alt 0x0100 /* alt scan-code */
-#define Ctrl 0x0200 /* ctrl scan-code */
-#define Shift 0x0400 /* shift scan-code */
-
-static struct
-{
- unsigned char char_code; /* normal code */
- unsigned char meta_code; /* M- code */
- unsigned char keypad_code; /* keypad code */
- unsigned char editkey_code; /* edit key */
-} keypad_translate_map[] = {
- '0', '0', 0xb0, /* kp-0 */ 0x63, /* insert */
- '1', '1', 0xb1, /* kp-1 */ 0x57, /* end */
- '2', '2', 0xb2, /* kp-2 */ 0x54, /* down */
- '3', '3', 0xb3, /* kp-3 */ 0x56, /* next */
- '4', '4', 0xb4, /* kp-4 */ 0x51, /* left */
- '5', '5', 0xb5, /* kp-5 */ 0xb5, /* kp-5 */
- '6', '6', 0xb6, /* kp-6 */ 0x53, /* right */
- '7', '7', 0xb7, /* kp-7 */ 0x50, /* home */
- '8', '8', 0xb8, /* kp-8 */ 0x52, /* up */
- '9', '9', 0xb9, /* kp-9 */ 0x55, /* prior */
- '.', '-', 0xae, /* kp-decimal */ 0xff /* delete */
-};
-
-static struct
-{
- unsigned char char_code; /* normal code */
- unsigned char keypad_code; /* keypad code */
-} grey_key_translate_map[] = {
- '/', 0xaf, /* kp-decimal */
- '*', 0xaa, /* kp-multiply */
- '-', 0xad, /* kp-subtract */
- '+', 0xab, /* kp-add */
- '\r', 0x8d /* kp-enter */
-};
-
-static unsigned short
-ibmpc_translate_map[] =
-{
- /* --------------- 00 to 0f --------------- */
- Normal | 0xff, /* Ctrl Break + Alt-NNN */
- Alt | ModFct | 0x1b, /* Escape */
- Normal | 1, /* '1' */
- Normal | 2, /* '2' */
- Normal | 3, /* '3' */
- Normal | 4, /* '4' */
- Normal | 5, /* '5' */
- Normal | 6, /* '6' */
- Normal | 7, /* '7' */
- Normal | 8, /* '8' */
- Normal | 9, /* '9' */
- Normal | 10, /* '0' */
- Normal | 11, /* '-' */
- Normal | 12, /* '=' */
- Special | 0x08, /* Backspace */
- ModFct | 0x74, /* Tab/Backtab */
-
- /* --------------- 10 to 1f --------------- */
- Map | 15, /* 'q' */
- Map | 16, /* 'w' */
- Map | 17, /* 'e' */
- Map | 18, /* 'r' */
- Map | 19, /* 't' */
- Map | 20, /* 'y' */
- Map | 21, /* 'u' */
- Map | 22, /* 'i' */
- Map | 23, /* 'o' */
- Map | 24, /* 'p' */
- Map | 25, /* '[' */
- Map | 26, /* ']' */
- ModFct | 0x0d, /* Return */
- Ignore, /* Ctrl */
- Map | 30, /* 'a' */
- Map | 31, /* 's' */
-
- /* --------------- 20 to 2f --------------- */
- Map | 32, /* 'd' */
- Map | 33, /* 'f' */
- Map | 34, /* 'g' */
- Map | 35, /* 'h' */
- Map | 36, /* 'j' */
- Map | 37, /* 'k' */
- Map | 38, /* 'l' */
- Map | 39, /* ';' */
- Map | 40, /* '\'' */
- Map | 0, /* '`' */
- Ignore, /* Left shift */
- Map | 41, /* '\\' */
- Map | 45, /* 'z' */
- Map | 46, /* 'x' */
- Map | 47, /* 'c' */
- Map | 48, /* 'v' */
-
- /* --------------- 30 to 3f --------------- */
- Map | 49, /* 'b' */
- Map | 50, /* 'n' */
- Map | 51, /* 'm' */
- Map | 52, /* ',' */
- Map | 53, /* '.' */
- Map | 54, /* '/' */
- Ignore, /* Right shift */
- Grey | 1, /* Grey * */
- Ignore, /* Alt */
- Normal | ' ', /* ' ' */
- Ignore, /* Caps Lock */
- FctKey | 0xbe, /* F1 */
- FctKey | 0xbf, /* F2 */
- FctKey | 0xc0, /* F3 */
- FctKey | 0xc1, /* F4 */
- FctKey | 0xc2, /* F5 */
-
- /* --------------- 40 to 4f --------------- */
- FctKey | 0xc3, /* F6 */
- FctKey | 0xc4, /* F7 */
- FctKey | 0xc5, /* F8 */
- FctKey | 0xc6, /* F9 */
- FctKey | 0xc7, /* F10 */
- Ignore, /* Num Lock */
- Ignore, /* Scroll Lock */
- KeyPad | 7, /* Home */
- KeyPad | 8, /* Up */
- KeyPad | 9, /* Page Up */
- Grey | 2, /* Grey - */
- KeyPad | 4, /* Left */
- KeyPad | 5, /* Keypad 5 */
- KeyPad | 6, /* Right */
- Grey | 3, /* Grey + */
- KeyPad | 1, /* End */
-
- /* --------------- 50 to 5f --------------- */
- KeyPad | 2, /* Down */
- KeyPad | 3, /* Page Down */
- KeyPad | 0, /* Insert */
- KeyPad | 10, /* Delete */
- Shift | FctKey | 0xbe, /* (Shift) F1 */
- Shift | FctKey | 0xbf, /* (Shift) F2 */
- Shift | FctKey | 0xc0, /* (Shift) F3 */
- Shift | FctKey | 0xc1, /* (Shift) F4 */
- Shift | FctKey | 0xc2, /* (Shift) F5 */
- Shift | FctKey | 0xc3, /* (Shift) F6 */
- Shift | FctKey | 0xc4, /* (Shift) F7 */
- Shift | FctKey | 0xc5, /* (Shift) F8 */
- Shift | FctKey | 0xc6, /* (Shift) F9 */
- Shift | FctKey | 0xc7, /* (Shift) F10 */
- Ctrl | FctKey | 0xbe, /* (Ctrl) F1 */
- Ctrl | FctKey | 0xbf, /* (Ctrl) F2 */
-
- /* --------------- 60 to 6f --------------- */
- Ctrl | FctKey | 0xc0, /* (Ctrl) F3 */
- Ctrl | FctKey | 0xc1, /* (Ctrl) F4 */
- Ctrl | FctKey | 0xc2, /* (Ctrl) F5 */
- Ctrl | FctKey | 0xc3, /* (Ctrl) F6 */
- Ctrl | FctKey | 0xc4, /* (Ctrl) F7 */
- Ctrl | FctKey | 0xc5, /* (Ctrl) F8 */
- Ctrl | FctKey | 0xc6, /* (Ctrl) F9 */
- Ctrl | FctKey | 0xc7, /* (Ctrl) F10 */
- Alt | FctKey | 0xbe, /* (Alt) F1 */
- Alt | FctKey | 0xbf, /* (Alt) F2 */
- Alt | FctKey | 0xc0, /* (Alt) F3 */
- Alt | FctKey | 0xc1, /* (Alt) F4 */
- Alt | FctKey | 0xc2, /* (Alt) F5 */
- Alt | FctKey | 0xc3, /* (Alt) F6 */
- Alt | FctKey | 0xc4, /* (Alt) F7 */
- Alt | FctKey | 0xc5, /* (Alt) F8 */
-
- /* --------------- 70 to 7f --------------- */
- Alt | FctKey | 0xc6, /* (Alt) F9 */
- Alt | FctKey | 0xc7, /* (Alt) F10 */
- Ctrl | FctKey | 0x6d, /* (Ctrl) Sys Rq */
- Ctrl | KeyPad | 4, /* (Ctrl) Left */
- Ctrl | KeyPad | 6, /* (Ctrl) Right */
- Ctrl | KeyPad | 1, /* (Ctrl) End */
- Ctrl | KeyPad | 3, /* (Ctrl) Page Down */
- Ctrl | KeyPad | 7, /* (Ctrl) Home */
- Alt | Map | 1, /* '1' */
- Alt | Map | 2, /* '2' */
- Alt | Map | 3, /* '3' */
- Alt | Map | 4, /* '4' */
- Alt | Map | 5, /* '5' */
- Alt | Map | 6, /* '6' */
- Alt | Map | 7, /* '7' */
- Alt | Map | 8, /* '8' */
-
- /* --------------- 80 to 8f --------------- */
- Alt | Map | 9, /* '9' */
- Alt | Map | 10, /* '0' */
- Alt | Map | 11, /* '-' */
- Alt | Map | 12, /* '=' */
- Ctrl | KeyPad | 9, /* (Ctrl) Page Up */
- FctKey | 0xc8, /* F11 */
- FctKey | 0xc9, /* F12 */
- Shift | FctKey | 0xc8, /* (Shift) F11 */
- Shift | FctKey | 0xc9, /* (Shift) F12 */
- Ctrl | FctKey | 0xc8, /* (Ctrl) F11 */
- Ctrl | FctKey | 0xc9, /* (Ctrl) F12 */
- Alt | FctKey | 0xc8, /* (Alt) F11 */
- Alt | FctKey | 0xc9, /* (Alt) F12 */
- Ctrl | KeyPad | 8, /* (Ctrl) Up */
- Ctrl | Grey | 2, /* (Ctrl) Grey - */
- Ctrl | KeyPad | 5, /* (Ctrl) Keypad 5 */
-
- /* --------------- 90 to 9f --------------- */
- Ctrl | Grey | 3, /* (Ctrl) Grey + */
- Ctrl | KeyPad | 2, /* (Ctrl) Down */
- Ctrl | KeyPad | 0, /* (Ctrl) Insert */
- Ctrl | KeyPad | 10, /* (Ctrl) Delete */
- Ctrl | FctKey | 0x09, /* (Ctrl) Tab */
- Ctrl | Grey | 0, /* (Ctrl) Grey / */
- Ctrl | Grey | 1, /* (Ctrl) Grey * */
- Alt | FctKey | 0x50, /* (Alt) Home */
- Alt | FctKey | 0x52, /* (Alt) Up */
- Alt | FctKey | 0x55, /* (Alt) Page Up */
- Ignore, /* NO KEY */
- Alt | FctKey | 0x51, /* (Alt) Left */
- Ignore, /* NO KEY */
- Alt | FctKey | 0x53, /* (Alt) Right */
- Ignore, /* NO KEY */
- Alt | FctKey | 0x57, /* (Alt) End */
-
- /* --------------- a0 to af --------------- */
- Alt | KeyPad | 2, /* (Alt) Down */
- Alt | KeyPad | 3, /* (Alt) Page Down */
- Alt | KeyPad | 0, /* (Alt) Insert */
- Alt | KeyPad | 10, /* (Alt) Delete */
- Alt | Grey | 0, /* (Alt) Grey / */
- Alt | FctKey | 0x09, /* (Alt) Tab */
- Alt | Grey | 4 /* (Alt) Keypad Enter */
-};
-
-/* These bit-positions corresponds to values returned by BIOS */
-#define SHIFT_P 0x0003 /* two bits! */
-#define CTRL_P 0x0004
-#define ALT_P 0x0008
-#define SCRLOCK_P 0x0010
-#define NUMLOCK_P 0x0020
-#define CAPSLOCK_P 0x0040
-#define ALT_GR_P 0x0800
-#define SUPER_P 0x4000 /* pseudo */
-#define HYPER_P 0x8000 /* pseudo */
-
-static int
-dos_get_modifiers (keymask)
- int *keymask;
-{
- union REGS regs;
- int mask;
- int modifiers = 0;
-
- /* Calculate modifier bits */
- regs.h.ah = extended_kbd ? 0x12 : 0x02;
- int86 (0x16, &regs, &regs);
-
- if (!extended_kbd)
- {
- mask = regs.h.al & (SHIFT_P | CTRL_P | ALT_P |
- SCRLOCK_P | NUMLOCK_P | CAPSLOCK_P);
- }
- else
- {
- mask = regs.h.al & (SHIFT_P |
- SCRLOCK_P | NUMLOCK_P | CAPSLOCK_P);
-
- /* Do not break international keyboard support. */
- /* When Keyb.Com is loaded, the right Alt key is */
- /* used for accessing characters like { and } */
- if (regs.h.ah & 2) /* Left ALT pressed ? */
- mask |= ALT_P;
-
- if ((regs.h.ah & 8) != 0) /* Right ALT pressed ? */
- {
- mask |= ALT_GR_P;
- if (dos_hyper_key == 1)
- {
- mask |= HYPER_P;
- modifiers |= hyper_modifier;
- }
- else if (dos_super_key == 1)
- {
- mask |= SUPER_P;
- modifiers |= super_modifier;
- }
- else if (!international_keyboard)
- {
- /* If Keyb.Com is NOT installed, let Right Alt behave
- like the Left Alt. */
- mask &= ~ALT_GR_P;
- mask |= ALT_P;
- }
- }
-
- if (regs.h.ah & 1) /* Left CTRL pressed ? */
- mask |= CTRL_P;
-
- if (regs.h.ah & 4) /* Right CTRL pressed ? */
- {
- if (dos_hyper_key == 2)
- {
- mask |= HYPER_P;
- modifiers |= hyper_modifier;
- }
- else if (dos_super_key == 2)
- {
- mask |= SUPER_P;
- modifiers |= super_modifier;
- }
- else
- mask |= CTRL_P;
- }
- }
-
- if (mask & SHIFT_P)
- modifiers |= shift_modifier;
- if (mask & CTRL_P)
- modifiers |= ctrl_modifier;
- if (mask & ALT_P)
- modifiers |= meta_modifier;
-
- if (keymask)
- *keymask = mask;
- return modifiers;
-}
-
-#define NUM_RECENT_DOSKEYS (100)
-int recent_doskeys_index; /* Index for storing next element into recent_doskeys */
-int total_doskeys; /* Total number of elements stored into recent_doskeys */
-Lisp_Object recent_doskeys; /* A vector, holding the last 100 keystrokes */
-
-DEFUN ("recent-doskeys", Frecent_doskeys, Srecent_doskeys, 0, 0, 0,
- "Return vector of last 100 keyboard input values seen in dos_rawgetc.\n\
-Each input key receives two values in this vector: first the ASCII code,\n\
-and then the scan code.")
- ()
-{
- Lisp_Object *keys = XVECTOR (recent_doskeys)->contents;
- Lisp_Object val;
-
- if (total_doskeys < NUM_RECENT_DOSKEYS)
- return Fvector (total_doskeys, keys);
- else
- {
- val = Fvector (NUM_RECENT_DOSKEYS, keys);
- bcopy (keys + recent_doskeys_index,
- XVECTOR (val)->contents,
- (NUM_RECENT_DOSKEYS - recent_doskeys_index) * sizeof (Lisp_Object));
- bcopy (keys,
- XVECTOR (val)->contents + NUM_RECENT_DOSKEYS - recent_doskeys_index,
- recent_doskeys_index * sizeof (Lisp_Object));
- return val;
- }
-}
-
-/* Get a char from keyboard. Function keys are put into the event queue. */
-
-static int
-dos_rawgetc ()
-{
- struct input_event event;
- union REGS regs;
-
-#ifndef HAVE_X_WINDOWS
- /* Maybe put the cursor where it should be. */
- IT_cmgoto (selected_frame);
-#endif
-
- /* The following condition is equivalent to `kbhit ()', except that
- it uses the bios to do its job. This pleases DESQview/X. */
- while ((regs.h.ah = extended_kbd ? 0x11 : 0x01),
- int86 (0x16, &regs, &regs),
- (regs.x.flags & 0x40) == 0)
- {
- union REGS regs;
- register unsigned char c;
- int sc, code, mask, kp_mode;
- int modifiers;
-
- regs.h.ah = extended_kbd ? 0x10 : 0x00;
- int86 (0x16, &regs, &regs);
- c = regs.h.al;
- sc = regs.h.ah;
-
- total_doskeys += 2;
- XVECTOR (recent_doskeys)->contents[recent_doskeys_index++]
- = make_number (c);
- if (recent_doskeys_index == NUM_RECENT_DOSKEYS)
- recent_doskeys_index = 0;
- XVECTOR (recent_doskeys)->contents[recent_doskeys_index++]
- = make_number (sc);
- if (recent_doskeys_index == NUM_RECENT_DOSKEYS)
- recent_doskeys_index = 0;
-
- modifiers = dos_get_modifiers (&mask);
-
-#ifndef HAVE_X_WINDOWS
- if (!NILP (Vdos_display_scancodes))
- {
- char buf[11];
- sprintf (buf, "%02x:%02x*%04x",
- (unsigned) (sc&0xff), (unsigned) c, mask);
- dos_direct_output (screen_size_Y - 2, screen_size_X - 12, buf, 10);
- }
-#endif
-
- if (sc == 0xe0)
- {
- switch (c)
- {
- case 10: /* Ctrl Grey Enter */
- code = Ctrl | Grey | 4;
- break;
- case 13: /* Grey Enter */
- code = Grey | 4;
- break;
- case '/': /* Grey / */
- code = Grey | 0;
- break;
- default:
- continue;
- };
- c = 0;
- }
- else
- {
- if (sc >= (sizeof (ibmpc_translate_map) / sizeof (short)))
- continue;
- if ((code = ibmpc_translate_map[sc]) == Ignore)
- continue;
- }
-
- if (c == 0)
- {
- if (code & Alt)
- modifiers |= meta_modifier;
- if (code & Ctrl)
- modifiers |= ctrl_modifier;
- if (code & Shift)
- modifiers |= shift_modifier;
- }
-
- switch (code & 0xf000)
- {
- case ModFct:
- if (c && !(mask & (SHIFT_P | ALT_P | CTRL_P | HYPER_P | SUPER_P)))
- return c;
- c = 0; /* Special */
-
- case FctKey:
- if (c != 0)
- return c;
-
- case Special:
- code |= 0xff00;
- break;
-
- case Normal:
- if (sc == 0)
- {
- if (c == 0) /* ctrl-break */
- continue;
- return c; /* ALT-nnn */
- }
- if (!keyboard_map_all)
- {
- if (c != ' ')
- return c;
- code = c;
- break;
- }
-
- case Map:
- if (c && !(mask & ALT_P) && !((mask & SHIFT_P) && (mask & CTRL_P)))
- if (!keyboard_map_all)
- return c;
-
- code &= 0xff;
- if (mask & ALT_P && code <= 10 && code > 0 && dos_keypad_mode & 0x200)
- mask |= SHIFT_P; /* ALT-1 => M-! etc. */
-
- if (mask & SHIFT_P)
- {
- code = keyboard->shifted[code];
- mask -= SHIFT_P;
- modifiers &= ~shift_modifier;
- }
- else
- if ((mask & ALT_GR_P) && keyboard->alt_gr && keyboard->alt_gr[code] != ' ')
- code = keyboard->alt_gr[code];
- else
- code = keyboard->unshifted[code];
- break;
-
- case KeyPad:
- code &= 0xff;
- if (c == 0xe0) /* edit key */
- kp_mode = 3;
- else
- if ((mask & (NUMLOCK_P|CTRL_P|SHIFT_P|ALT_P)) == NUMLOCK_P) /* numlock on */
- kp_mode = dos_keypad_mode & 0x03;
- else
- kp_mode = (dos_keypad_mode >> 4) & 0x03;
-
- switch (kp_mode)
- {
- case 0:
- if (code == 10 && dos_decimal_point)
- return dos_decimal_point;
- return keypad_translate_map[code].char_code;
-
- case 1:
- code = 0xff00 | keypad_translate_map[code].keypad_code;
- break;
-
- case 2:
- code = keypad_translate_map[code].meta_code;
- modifiers = meta_modifier;
- break;
-
- case 3:
- code = 0xff00 | keypad_translate_map[code].editkey_code;
- break;
- }
- break;
-
- case Grey:
- code &= 0xff;
- kp_mode = ((mask & (NUMLOCK_P|CTRL_P|SHIFT_P|ALT_P)) == NUMLOCK_P) ? 0x04 : 0x40;
- if (dos_keypad_mode & kp_mode)
- code = 0xff00 | grey_key_translate_map[code].keypad_code;
- else
- code = grey_key_translate_map[code].char_code;
- break;
- }
-
- make_event:
- if (code == 0)
- continue;
-
- if (code >= 0x100)
- event.kind = non_ascii_keystroke;
- else
- event.kind = ascii_keystroke;
- event.code = code;
- event.modifiers = modifiers;
- XSETFRAME (event.frame_or_window, selected_frame);
- event.timestamp = event_timestamp ();
- kbd_buffer_store_event (&event);
- }
-
- if (have_mouse > 0)
- {
- int but, press, x, y, ok;
-
- /* Check for mouse movement *before* buttons. */
- mouse_check_moved ();
-
- for (but = 0; but < NUM_MOUSE_BUTTONS; but++)
- for (press = 0; press < 2; press++)
- {
- int button_num = but;
-
- if (press)
- ok = mouse_pressed (but, &x, &y);
- else
- ok = mouse_released (but, &x, &y);
- if (ok)
- {
- /* Allow a simultaneous press/release of Mouse-1 and
- Mouse-2 to simulate Mouse-3 on two-button mice. */
- if (mouse_button_count == 2 && but < 2)
- {
- int x2, y2; /* don't clobber original coordinates */
-
- /* If only one button is pressed, wait 100 msec and
- check again. This way, Speedy Gonzales isn't
- punished, while the slow get their chance. */
- if (press && mouse_pressed (1-but, &x2, &y2)
- || !press && mouse_released (1-but, &x2, &y2))
- button_num = 2;
- else
- {
- delay (100);
- if (press && mouse_pressed (1-but, &x2, &y2)
- || !press && mouse_released (1-but, &x2, &y2))
- button_num = 2;
- }
- }
-
- event.kind = mouse_click;
- event.code = button_num;
- event.modifiers = dos_get_modifiers (0)
- | (press ? down_modifier : up_modifier);
- event.x = x;
- event.y = y;
- XSETFRAME (event.frame_or_window, selected_frame);
- event.timestamp = event_timestamp ();
- kbd_buffer_store_event (&event);
- }
- }
- }
-
- return -1;
-}
-
-static int prev_get_char = -1;
-
-/* Return 1 if a key is ready to be read without suspending execution. */
-
-dos_keysns ()
-{
- if (prev_get_char != -1)
- return 1;
- else
- return ((prev_get_char = dos_rawgetc ()) != -1);
-}
-
-/* Read a key. Return -1 if no key is ready. */
-
-dos_keyread ()
-{
- if (prev_get_char != -1)
- {
- int c = prev_get_char;
- prev_get_char = -1;
- return c;
- }
- else
- return dos_rawgetc ();
-}
-
-#ifndef HAVE_X_WINDOWS
-/* See xterm.c for more info. */
-void
-pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
- FRAME_PTR f;
- register int pix_x, pix_y;
- register int *x, *y;
- void /* XRectangle */ *bounds;
- int noclip;
-{
- if (bounds) abort ();
-
- /* Ignore clipping. */
-
- *x = pix_x;
- *y = pix_y;
-}
-
-void
-glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
- FRAME_PTR f;
- register int x, y;
- register int *pix_x, *pix_y;
-{
- *pix_x = x;
- *pix_y = y;
-}
-
-/* Simulation of X's menus. Nothing too fancy here -- just make it work
- for now.
-
- Actually, I don't know the meaning of all the parameters of the functions
- here -- I only know how they are called by xmenu.c. I could of course
- grab the nearest Xlib manual (down the hall, second-to-last door on the
- left), but I don't think it's worth the effort. */
-
-static XMenu *
-IT_menu_create ()
-{
- XMenu *menu;
-
- menu = (XMenu *) xmalloc (sizeof (XMenu));
- menu->allocated = menu->count = menu->panecount = menu->width = 0;
- return menu;
-}
-
-/* Allocate some (more) memory for MENU ensuring that there is room for one
- for item. */
-
-static void
-IT_menu_make_room (XMenu *menu)
-{
- if (menu->allocated == 0)
- {
- int count = menu->allocated = 10;
- menu->text = (char **) xmalloc (count * sizeof (char *));
- menu->submenu = (XMenu **) xmalloc (count * sizeof (XMenu *));
- menu->panenumber = (int *) xmalloc (count * sizeof (int));
- }
- else if (menu->allocated == menu->count)
- {
- int count = menu->allocated = menu->allocated + 10;
- menu->text
- = (char **) xrealloc (menu->text, count * sizeof (char *));
- menu->submenu
- = (XMenu **) xrealloc (menu->submenu, count * sizeof (XMenu *));
- menu->panenumber
- = (int *) xrealloc (menu->panenumber, count * sizeof (int));
- }
-}
-
-/* Search the given menu structure for a given pane number. */
-
-static XMenu *
-IT_menu_search_pane (XMenu *menu, int pane)
-{
- int i;
- XMenu *try;
-
- for (i = 0; i < menu->count; i++)
- if (menu->submenu[i])
- {
- if (pane == menu->panenumber[i])
- return menu->submenu[i];
- if ((try = IT_menu_search_pane (menu->submenu[i], pane)))
- return try;
- }
- return (XMenu *) 0;
-}
-
-/* Determine how much screen space a given menu needs. */
-
-static void
-IT_menu_calc_size (XMenu *menu, int *width, int *height)
-{
- int i, h2, w2, maxsubwidth, maxheight;
-
- maxsubwidth = 0;
- maxheight = menu->count;
- for (i = 0; i < menu->count; i++)
- {
- if (menu->submenu[i])
- {
- IT_menu_calc_size (menu->submenu[i], &w2, &h2);
- if (w2 > maxsubwidth) maxsubwidth = w2;
- if (i + h2 > maxheight) maxheight = i + h2;
- }
- }
- *width = menu->width + maxsubwidth;
- *height = maxheight;
-}
-
-/* Display MENU at (X,Y) using FACES. */
-
-static void
-IT_menu_display (XMenu *menu, int y, int x, int *faces)
-{
- int i, j, face, width;
- GLYPH *text, *p;
- char *q;
- int mx, my;
- int enabled, mousehere;
- int row, col;
-
- width = menu->width;
- text = (GLYPH *) xmalloc ((width + 2) * sizeof (GLYPH));
- ScreenGetCursor (&row, &col);
- mouse_get_xy (&mx, &my);
- IT_update_begin ();
- for (i = 0; i < menu->count; i++)
- {
- IT_cursor_to (y + i, x);
- enabled
- = (!menu->submenu[i] && menu->panenumber[i]) || (menu->submenu[i]);
- mousehere = (y + i == my && x <= mx && mx < x + width + 2);
- face = faces[enabled + mousehere * 2];
- p = text;
- *p++ = FAST_MAKE_GLYPH (' ', face);
- for (j = 0, q = menu->text[i]; *q; j++)
- {
- if (*q > 26)
- *p++ = FAST_MAKE_GLYPH (*q++, face);
- else /* make '^x' */
- {
- *p++ = FAST_MAKE_GLYPH ('^', face);
- j++;
- *p++ = FAST_MAKE_GLYPH (*q++ + 64, face);
- }
- }
-
- for (; j < width; j++)
- *p++ = FAST_MAKE_GLYPH (' ', face);
- *p++ = FAST_MAKE_GLYPH (menu->submenu[i] ? 16 : ' ', face);
- IT_write_glyphs (text, width + 2);
- }
- IT_update_end ();
- IT_cursor_to (row, col);
- xfree (text);
-}
-
-/* --------------------------- X Menu emulation ---------------------- */
-
-/* Report availability of menus. */
-
-int
-have_menus_p ()
-{
- return 1;
-}
-
-/* Create a brand new menu structure. */
-
-XMenu *
-XMenuCreate (Display *foo1, Window foo2, char *foo3)
-{
- return IT_menu_create ();
-}
-
-/* Create a new pane and place it on the outer-most level. It is not
- clear that it should be placed out there, but I don't know what else
- to do. */
-
-int
-XMenuAddPane (Display *foo, XMenu *menu, char *txt, int enable)
-{
- int len;
- char *p;
-
- if (!enable)
- abort ();
-
- IT_menu_make_room (menu);
- menu->submenu[menu->count] = IT_menu_create ();
- menu->text[menu->count] = txt;
- menu->panenumber[menu->count] = ++menu->panecount;
- menu->count++;
-
- /* Adjust length for possible control characters (which will
- be written as ^x). */
- for (len = strlen (txt), p = txt; *p; p++)
- if (*p < 27)
- len++;
-
- if (len > menu->width)
- menu->width = len;
-
- return menu->panecount;
-}
-
-/* Create a new item in a menu pane. */
-
-int
-XMenuAddSelection (Display *bar, XMenu *menu, int pane,
- int foo, char *txt, int enable)
-{
- int len;
- char *p;
-
- if (pane)
- if (!(menu = IT_menu_search_pane (menu, pane)))
- return XM_FAILURE;
- IT_menu_make_room (menu);
- menu->submenu[menu->count] = (XMenu *) 0;
- menu->text[menu->count] = txt;
- menu->panenumber[menu->count] = enable;
- menu->count++;
-
- /* Adjust length for possible control characters (which will
- be written as ^x). */
- for (len = strlen (txt), p = txt; *p; p++)
- if (*p < 27)
- len++;
-
- if (len > menu->width)
- menu->width = len;
-
- return XM_SUCCESS;
-}
-
-/* Decide where the menu would be placed if requested at (X,Y). */
-
-void
-XMenuLocate (Display *foo0, XMenu *menu, int foo1, int foo2, int x, int y,
- int *ulx, int *uly, int *width, int *height)
-{
- IT_menu_calc_size (menu, width, height);
- *ulx = x + 1;
- *uly = y;
- *width += 2;
-}
-
-struct IT_menu_state
-{
- void *screen_behind;
- XMenu *menu;
- int pane;
- int x, y;
-};
-
-
-/* Display menu, wait for user's response, and return that response. */
-
-int
-XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
- int x0, int y0, unsigned ButtonMask, char **txt)
-{
- struct IT_menu_state *state;
- int statecount;
- int x, y, i, b;
- int screensize;
- int faces[4], selectface;
- int leave, result, onepane;
- int title_faces[4]; /* face to display the menu title */
- int buffers_num_deleted = 0;
-
- /* Just in case we got here without a mouse present... */
- if (have_mouse <= 0)
- return XM_IA_SELECT;
-
- state = alloca (menu->panecount * sizeof (struct IT_menu_state));
- screensize = screen_size * 2;
- faces[0]
- = compute_glyph_face (selected_frame,
- face_name_id_number
- (selected_frame,
- intern ("msdos-menu-passive-face")),
- 0);
- faces[1]
- = compute_glyph_face (selected_frame,
- face_name_id_number
- (selected_frame,
- intern ("msdos-menu-active-face")),
- 0);
- selectface
- = face_name_id_number (selected_frame, intern ("msdos-menu-select-face"));
- faces[2] = compute_glyph_face (selected_frame, selectface, faces[0]);
- faces[3] = compute_glyph_face (selected_frame, selectface, faces[1]);
-
- /* Make sure the menu title is always displayed with
- `msdos-menu-active-face', no matter where the mouse pointer is. */
- for (i = 0; i < 4; i++)
- title_faces[i] = faces[3];
-
- statecount = 1;
-
- /* Don't let the title for the "Buffers" popup menu include a
- digit (which is ugly).
-
- This is a terrible kludge, but I think the "Buffers" case is
- the only one where the title includes a number, so it doesn't
- seem to be necessary to make this more general. */
- if (strncmp (menu->text[0], "Buffers 1", 9) == 0)
- {
- menu->text[0][7] = '\0';
- buffers_num_deleted = 1;
- }
- state[0].menu = menu;
- mouse_off ();
- ScreenRetrieve (state[0].screen_behind = xmalloc (screensize));
-
- /* Turn off the cursor. Otherwise it shows through the menu
- panes, which is ugly. */
- IT_display_cursor (0);
-
- IT_menu_display (menu, y0 - 1, x0 - 1, title_faces); /* display menu title */
- if (buffers_num_deleted)
- menu->text[0][7] = ' ';
- if ((onepane = menu->count == 1 && menu->submenu[0]))
- {
- menu->width = menu->submenu[0]->width;
- state[0].menu = menu->submenu[0];
- }
- else
- {
- state[0].menu = menu;
- }
- state[0].x = x0 - 1;
- state[0].y = y0;
- state[0].pane = onepane;
-
- mouse_last_x = -1; /* A hack that forces display. */
- leave = 0;
- while (!leave)
- {
- if (!mouse_visible) mouse_on ();
- mouse_check_moved ();
- if (selected_frame->mouse_moved)
- {
- selected_frame->mouse_moved = 0;
- result = XM_IA_SELECT;
- mouse_get_xy (&x, &y);
- for (i = 0; i < statecount; i++)
- if (state[i].x <= x && x < state[i].x + state[i].menu->width + 2)
- {
- int dy = y - state[i].y;
- if (0 <= dy && dy < state[i].menu->count)
- {
- if (!state[i].menu->submenu[dy])
- if (state[i].menu->panenumber[dy])
- result = XM_SUCCESS;
- else
- result = XM_IA_SELECT;
- *pane = state[i].pane - 1;
- *selidx = dy;
- /* We hit some part of a menu, so drop extra menus that
- have been opened. That does not include an open and
- active submenu. */
- if (i != statecount - 2
- || state[i].menu->submenu[dy] != state[i+1].menu)
- while (i != statecount - 1)
- {
- statecount--;
- mouse_off ();
- ScreenUpdate (state[statecount].screen_behind);
- xfree (state[statecount].screen_behind);
- }
- if (i == statecount - 1 && state[i].menu->submenu[dy])
- {
- IT_menu_display (state[i].menu,
- state[i].y,
- state[i].x,
- faces);
- state[statecount].menu = state[i].menu->submenu[dy];
- state[statecount].pane = state[i].menu->panenumber[dy];
- mouse_off ();
- ScreenRetrieve (state[statecount].screen_behind
- = xmalloc (screensize));
- state[statecount].x
- = state[i].x + state[i].menu->width + 2;
- state[statecount].y = y;
- statecount++;
- }
- }
- }
- IT_menu_display (state[statecount - 1].menu,
- state[statecount - 1].y,
- state[statecount - 1].x,
- faces);
- }
- for (b = 0; b < mouse_button_count; b++)
- {
- (void) mouse_pressed (b, &x, &y);
- if (mouse_released (b, &x, &y))
- leave = 1;
- }
- }
-
- mouse_off ();
- ScreenUpdate (state[0].screen_behind);
- while (statecount--)
- xfree (state[statecount].screen_behind);
- IT_display_cursor (1); /* turn cursor back on */
- return result;
-}
-
-/* Dispose of a menu. */
-
-void
-XMenuDestroy (Display *foo, XMenu *menu)
-{
- int i;
- if (menu->allocated)
- {
- for (i = 0; i < menu->count; i++)
- if (menu->submenu[i])
- XMenuDestroy (foo, menu->submenu[i]);
- xfree (menu->text);
- xfree (menu->submenu);
- xfree (menu->panenumber);
- }
- xfree (menu);
-}
-
-int
-x_pixel_width (struct frame *f)
-{
- return FRAME_WIDTH (f);
-}
-
-int
-x_pixel_height (struct frame *f)
-{
- return FRAME_HEIGHT (f);
-}
-#endif /* !HAVE_X_WINDOWS */
-
-/* ----------------------- DOS / UNIX conversion --------------------- */
-
-void msdos_downcase_filename (unsigned char *);
-
-/* Destructively turn backslashes into slashes. */
-
-void
-dostounix_filename (p)
- register char *p;
-{
- msdos_downcase_filename (p);
-
- while (*p)
- {
- if (*p == '\\')
- *p = '/';
- p++;
- }
-}
-
-/* Destructively turn slashes into backslashes. */
-
-void
-unixtodos_filename (p)
- register char *p;
-{
- if (p[1] == ':' && *p >= 'A' && *p <= 'Z')
- {
- *p += 'a' - 'A';
- p += 2;
- }
-
- while (*p)
- {
- if (*p == '/')
- *p = '\\';
- p++;
- }
-}
-
-/* Get the default directory for a given drive. 0=def, 1=A, 2=B, ... */
-
-int
-getdefdir (drive, dst)
- int drive;
- char *dst;
-{
- char in_path[4], *p = in_path;
- int e = errno;
-
- /* Generate "X:." (when drive is X) or "." (when drive is 0). */
- if (drive != 0)
- {
- *p++ = drive + 'A' - 1;
- *p++ = ':';
- }
-
- *p++ = '.';
- *p = '\0';
- errno = 0;
- _fixpath (in_path, dst);
- if (errno)
- return 0;
-
- msdos_downcase_filename (dst);
-
- errno = e;
- return 1;
-}
-
-/* Remove all CR's that are followed by a LF. */
-
-int
-crlf_to_lf (n, buf)
- register int n;
- register unsigned char *buf;
-{
- unsigned char *np = buf;
- unsigned char *startp = buf;
- unsigned char *endp = buf + n;
- unsigned char c;
-
- if (n == 0)
- return n;
- while (buf < endp - 1)
- {
- if (*buf == 0x0d)
- {
- if (*(++buf) != 0x0a)
- *np++ = 0x0d;
- }
- else
- *np++ = *buf++;
- }
- if (buf < endp)
- *np++ = *buf++;
- return np - startp;
-}
-
-#if defined(__DJGPP__) && __DJGPP__ == 2 && __DJGPP_MINOR__ == 0
-
-/* In DJGPP v2.0, library `write' can call `malloc', which might
- cause relocation of the buffer whose address we get in ADDR.
- Here is a version of `write' that avoids calling `malloc',
- to serve us until such time as the library is fixed.
- Actually, what we define here is called `__write', because
- `write' is a stub that just jmp's to `__write' (to be
- POSIXLY-correct with respect to the global name-space). */
-
-#include <io.h> /* for _write */
-#include <libc/dosio.h> /* for __file_handle_modes[] */
-
-static char xbuf[64 * 1024]; /* DOS cannot write more in one chunk */
-
-#define XBUF_END (xbuf + sizeof (xbuf) - 1)
-
-int
-__write (int handle, const void *buffer, size_t count)
-{
- if (count == 0)
- return 0;
-
- if(__file_handle_modes[handle] & O_BINARY)
- return _write (handle, buffer, count);
- else
- {
- char *xbp = xbuf;
- const char *bp = buffer;
- int total_written = 0;
- int nmoved = 0, ncr = 0;
-
- while (count)
- {
- /* The next test makes sure there's space for at least 2 more
- characters in xbuf[], so both CR and LF can be put there. */
- if (xbp < XBUF_END)
- {
- if (*bp == '\n')
- {
- ncr++;
- *xbp++ = '\r';
- }
- *xbp++ = *bp++;
- nmoved++;
- count--;
- }
- if (xbp >= XBUF_END || !count)
- {
- size_t to_write = nmoved + ncr;
- int written = _write (handle, xbuf, to_write);
-
- if (written == -1)
- return -1;
- else
- total_written += nmoved; /* CRs aren't counted in ret value */
-
- /* If some, but not all were written (disk full?), return
- an estimate of the total written bytes not counting CRs. */
- if (written < to_write)
- return total_written - (to_write - written) * nmoved/to_write;
-
- nmoved = 0;
- ncr = 0;
- xbp = xbuf;
- }
- }
- return total_written;
- }
-}
-
-/* A low-level file-renaming function which works around Windows 95 bug.
- This is pulled directly out of DJGPP v2.01 library sources, and only
- used when you compile with DJGPP v2.0. */
-
-#include <io.h>
-
-int _rename(const char *old, const char *new)
-{
- __dpmi_regs r;
- int olen = strlen(old) + 1;
- int i;
- int use_lfn = _USE_LFN;
- char tempfile[FILENAME_MAX];
- const char *orig = old;
- int lfn_fd = -1;
-
- r.x.dx = __tb_offset;
- r.x.di = __tb_offset + olen;
- r.x.ds = r.x.es = __tb_segment;
-
- if (use_lfn)
- {
- /* Windows 95 bug: for some filenames, when you rename
- file -> file~ (as in Emacs, to leave a backup), the
- short 8+3 alias doesn't change, which effectively
- makes OLD and NEW the same file. We must rename
- through a temporary file to work around this. */
-
- char *pbase = 0, *p;
- static char try_char[] = "abcdefghijklmnopqrstuvwxyz012345789";
- int idx = sizeof(try_char) - 1;
-
- /* Generate a temporary name. Can't use `tmpnam', since $TMPDIR
- might point to another drive, which will fail the DOS call. */
- strcpy(tempfile, old);
- for (p = tempfile; *p; p++) /* ensure temporary is on the same drive */
- if (*p == '/' || *p == '\\' || *p == ':')
- pbase = p;
- if (pbase)
- pbase++;
- else
- pbase = tempfile;
- strcpy(pbase, "X$$djren$$.$$temp$$");
-
- do
- {
- if (idx <= 0)
- return -1;
- *pbase = try_char[--idx];
- } while (_chmod(tempfile, 0) != -1);
-
- r.x.ax = 0x7156;
- _put_path2(tempfile, olen);
- _put_path(old);
- __dpmi_int(0x21, &r);
- if (r.x.flags & 1)
- {
- errno = __doserr_to_errno(r.x.ax);
- return -1;
- }
-
- /* Now create a file with the original name. This will
- ensure that NEW will always have a 8+3 alias
- different from that of OLD. (Seems to be required
- when NameNumericTail in the Registry is set to 0.) */
- lfn_fd = _creat(old, 0);
-
- olen = strlen(tempfile) + 1;
- old = tempfile;
- r.x.di = __tb_offset + olen;
- }
-
- for (i=0; i<2; i++)
- {
- if(use_lfn)
- r.x.ax = 0x7156;
- else
- r.h.ah = 0x56;
- _put_path2(new, olen);
- _put_path(old);
- __dpmi_int(0x21, &r);
- if(r.x.flags & 1)
- {
- if (r.x.ax == 5 && i == 0) /* access denied */
- remove(new); /* and try again */
- else
- {
- errno = __doserr_to_errno(r.x.ax);
-
- /* Restore to original name if we renamed it to temporary. */
- if (use_lfn)
- {
- if (lfn_fd != -1)
- {
- _close (lfn_fd);
- remove (orig);
- }
- _put_path2(orig, olen);
- _put_path(tempfile);
- r.x.ax = 0x7156;
- __dpmi_int(0x21, &r);
- }
- return -1;
- }
- }
- else
- break;
- }
-
- /* Success. Delete the file possibly created to work
- around the Windows 95 bug. */
- if (lfn_fd != -1)
- return (_close (lfn_fd) == 0) ? remove (orig) : -1;
- return 0;
-}
-
-#endif /* __DJGPP__ == 2 && __DJGPP_MINOR__ == 0 */
-
-DEFUN ("msdos-long-file-names", Fmsdos_long_file_names, Smsdos_long_file_names,
- 0, 0, 0,
- "Return non-nil if long file names are supported on MSDOS.")
- ()
-{
- return (_USE_LFN ? Qt : Qnil);
-}
-
-/* Convert alphabetic characters in a filename to lower-case. */
-
-void
-msdos_downcase_filename (p)
- register unsigned char *p;
-{
- /* Always lower-case drive letters a-z, even if the filesystem
- preserves case in filenames.
- This is so MSDOS filenames could be compared by string comparison
- functions that are case-sensitive. Even case-preserving filesystems
- do not distinguish case in drive letters. */
- if (p[1] == ':' && *p >= 'A' && *p <= 'Z')
- {
- *p += 'a' - 'A';
- p += 2;
- }
-
- /* Under LFN we expect to get pathnames in their true case. */
- if (NILP (Fmsdos_long_file_names ()))
- for ( ; *p; p++)
- if (*p >= 'A' && *p <= 'Z')
- *p += 'a' - 'A';
-}
-
-DEFUN ("msdos-downcase-filename", Fmsdos_downcase_filename, Smsdos_downcase_filename,
- 1, 1, 0,
- "Convert alphabetic characters in FILENAME to lower case and return that.\n\
-When long filenames are supported, doesn't change FILENAME.\n\
-If FILENAME is not a string, returns nil.\n\
-The argument object is never altered--the value is a copy.")
- (filename)
- Lisp_Object filename;
-{
- char *fname;
- Lisp_Object tem;
-
- if (! STRINGP (filename))
- return Qnil;
-
- tem = Fcopy_sequence (filename);
- msdos_downcase_filename (XSTRING (tem)->data);
- return tem;
-}
-
-/* The Emacs root directory as determined by init_environment. */
-
-static char emacsroot[MAXPATHLEN];
-
-char *
-rootrelativepath (rel)
- char *rel;
-{
- static char result[MAXPATHLEN + 10];
-
- strcpy (result, emacsroot);
- strcat (result, "/");
- strcat (result, rel);
- return result;
-}
-
-/* Define a lot of environment variables if not already defined. Don't
- remove anything unless you know what you're doing -- lots of code will
- break if one or more of these are missing. */
-
-void
-init_environment (argc, argv, skip_args)
- int argc;
- char **argv;
- int skip_args;
-{
- char *s, *t, *root;
- int len;
-
- /* Find our root from argv[0]. Assuming argv[0] is, say,
- "c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */
- root = alloca (MAXPATHLEN + 20);
- _fixpath (argv[0], root);
- msdos_downcase_filename (root);
- len = strlen (root);
- while (len > 0 && root[len] != '/' && root[len] != ':')
- len--;
- root[len] = '\0';
- if (len > 4 && strcmp (root + len - 4, "/bin") == 0)
- root[len - 4] = '\0';
- else
- strcpy (root, "c:/emacs"); /* Only under debuggers, I think. */
- len = strlen (root);
- strcpy (emacsroot, root);
-
- /* We default HOME to our root. */
- setenv ("HOME", root, 0);
-
- /* We default EMACSPATH to root + "/bin". */
- strcpy (root + len, "/bin");
- setenv ("EMACSPATH", root, 0);
-
- /* I don't expect anybody to ever use other terminals so the internal
- terminal is the default. */
- setenv ("TERM", "internal", 0);
-
-#ifdef HAVE_X_WINDOWS
- /* Emacs expects DISPLAY to be set. */
- setenv ("DISPLAY", "unix:0.0", 0);
-#endif
-
- /* SHELL is a bit tricky -- COMSPEC is the closest we come, but we must
- downcase it and mirror the backslashes. */
- s = getenv ("COMSPEC");
- if (!s) s = "c:/command.com";
- t = alloca (strlen (s) + 1);
- strcpy (t, s);
- dostounix_filename (t);
- setenv ("SHELL", t, 0);
-
- /* PATH is also downcased and backslashes mirrored. */
- s = getenv ("PATH");
- if (!s) s = "";
- t = alloca (strlen (s) + 3);
- /* Current directory is always considered part of MsDos's path but it is
- not normally mentioned. Now it is. */
- strcat (strcpy (t, ".;"), s);
- dostounix_filename (t); /* Not a single file name, but this should work. */
- setenv ("PATH", t, 1);
-
- /* In some sense all dos users have root privileges, so... */
- setenv ("USER", "root", 0);
- setenv ("NAME", getenv ("USER"), 0);
-
- /* Time zone determined from country code. To make this possible, the
- country code may not span more than one time zone. In other words,
- in the USA, you lose. */
- if (!getenv ("TZ"))
- switch (dos_country_code)
- {
- case 31: /* Belgium */
- case 32: /* The Netherlands */
- case 33: /* France */
- case 34: /* Spain */
- case 36: /* Hungary */
- case 38: /* Yugoslavia (or what's left of it?) */
- case 39: /* Italy */
- case 41: /* Switzerland */
- case 42: /* Tjekia */
- case 45: /* Denmark */
- case 46: /* Sweden */
- case 47: /* Norway */
- case 48: /* Poland */
- case 49: /* Germany */
- /* Daylight saving from last Sunday in March to last Sunday in
- September, both at 2AM. */
- setenv ("TZ", "MET-01METDST-02,M3.5.0/02:00,M9.5.0/02:00", 0);
- break;
- case 44: /* United Kingdom */
- case 351: /* Portugal */
- case 354: /* Iceland */
- setenv ("TZ", "GMT+00", 0);
- break;
- case 81: /* Japan */
- case 82: /* Korea */
- setenv ("TZ", "JST-09", 0);
- break;
- case 90: /* Turkey */
- case 358: /* Finland */
- setenv ("TZ", "EET-02", 0);
- break;
- case 972: /* Israel */
- /* This is an approximation. (For exact rules, use the
- `zoneinfo/israel' file which comes with DJGPP, but you need
- to install it in `/usr/share/zoneinfo/' directory first.) */
- setenv ("TZ", "IST-02IDT-03,M4.1.6/00:00,M9.5.6/01:00", 0);
- break;
- }
- tzset ();
-}
-
-
-
-static int break_stat; /* BREAK check mode status. */
-static int stdin_stat; /* stdin IOCTL status. */
-
-#if __DJGPP__ < 2
-
-/* These must be global. */
-static _go32_dpmi_seginfo ctrl_break_vector;
-static _go32_dpmi_registers ctrl_break_regs;
-static int ctrlbreakinstalled = 0;
-
-/* Interrupt level detection of Ctrl-Break. Don't do anything fancy here! */
-
-void
-ctrl_break_func (regs)
- _go32_dpmi_registers *regs;
-{
- Vquit_flag = Qt;
-}
-
-void
-install_ctrl_break_check ()
-{
- if (!ctrlbreakinstalled)
- {
- /* Don't press Ctrl-Break if you don't have either DPMI or Emacs
- was compiler with Djgpp 1.11 maintenance level 5 or later! */
- ctrlbreakinstalled = 1;
- ctrl_break_vector.pm_offset = (int) ctrl_break_func;
- _go32_dpmi_allocate_real_mode_callback_iret (&ctrl_break_vector,
- &ctrl_break_regs);
- _go32_dpmi_set_real_mode_interrupt_vector (0x1b, &ctrl_break_vector);
- }
-}
-
-#endif /* __DJGPP__ < 2 */
-
-/* Turn off Dos' Ctrl-C checking and inhibit interpretation of
- control chars by DOS. Determine the keyboard type. */
-
-int
-dos_ttraw ()
-{
- union REGS inregs, outregs;
- static int first_time = 1;
-
- break_stat = getcbrk ();
- setcbrk (0);
-#if __DJGPP__ < 2
- install_ctrl_break_check ();
-#endif
-
- if (first_time)
- {
- inregs.h.ah = 0xc0;
- int86 (0x15, &inregs, &outregs);
- extended_kbd = (!outregs.x.cflag) && (outregs.h.ah == 0);
-
- have_mouse = 0;
-
- if (internal_terminal
-#ifdef HAVE_X_WINDOWS
- && inhibit_window_system
-#endif
- )
- {
- inregs.x.ax = 0x0021;
- int86 (0x33, &inregs, &outregs);
- have_mouse = (outregs.x.ax & 0xffff) == 0xffff;
- if (!have_mouse)
- {
- /* Reportedly, the above doesn't work for some mouse drivers. There
- is an additional detection method that should work, but might be
- a little slower. Use that as an alternative. */
- inregs.x.ax = 0x0000;
- int86 (0x33, &inregs, &outregs);
- have_mouse = (outregs.x.ax & 0xffff) == 0xffff;
- }
-
- if (have_mouse)
- {
- have_mouse = 1; /* enable mouse */
- mouse_visible = 0;
-
- if (outregs.x.bx == 3)
- {
- mouse_button_count = 3;
- mouse_button_translate[0] = 0; /* Left */
- mouse_button_translate[1] = 2; /* Middle */
- mouse_button_translate[2] = 1; /* Right */
- }
- else
- {
- mouse_button_count = 2;
- mouse_button_translate[0] = 0;
- mouse_button_translate[1] = 1;
- }
- mouse_position_hook = &mouse_get_pos;
- mouse_init ();
- }
- }
-
- first_time = 0;
-
-#if __DJGPP__ >= 2
-
- stdin_stat = setmode (fileno (stdin), O_BINARY);
- return (stdin_stat != -1);
- }
- else
- return (setmode (fileno (stdin), O_BINARY) != -1);
-
-#else /* __DJGPP__ < 2 */
-
- }
-
- /* I think it is wrong to overwrite `stdin_stat' every time
- but the first one this function is called, but I don't
- want to change the way it used to work in v1.x.--EZ */
-
- inregs.x.ax = 0x4400; /* Get IOCTL status. */
- inregs.x.bx = 0x00; /* 0 = stdin. */
- intdos (&inregs, &outregs);
- stdin_stat = outregs.h.dl;
-
- inregs.x.dx = stdin_stat | 0x0020; /* raw mode */
- inregs.x.ax = 0x4401; /* Set IOCTL status */
- intdos (&inregs, &outregs);
- return !outregs.x.cflag;
-
-#endif /* __DJGPP__ < 2 */
-}
-
-/* Restore status of standard input and Ctrl-C checking. */
-
-int
-dos_ttcooked ()
-{
- union REGS inregs, outregs;
-
- setcbrk (break_stat);
- mouse_off ();
-
-#if __DJGPP__ >= 2
-
- return (setmode (fileno (stdin), stdin_stat) != -1);
-
-#else /* not __DJGPP__ >= 2 */
-
- inregs.x.ax = 0x4401; /* Set IOCTL status. */
- inregs.x.bx = 0x00; /* 0 = stdin. */
- inregs.x.dx = stdin_stat;
- intdos (&inregs, &outregs);
- return !outregs.x.cflag;
-
-#endif /* not __DJGPP__ >= 2 */
-}
-
-
-/* Run command as specified by ARGV in directory DIR.
- The command is run with input from TEMPIN, output to
- file TEMPOUT and stderr to TEMPERR. */
-
-int
-run_msdos_command (argv, dir, tempin, tempout, temperr)
- unsigned char **argv;
- Lisp_Object dir;
- int tempin, tempout, temperr;
-{
- char *saveargv1, *saveargv2, **envv, *lowcase_argv0, *pa, *pl;
- char oldwd[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */
- int msshell, result = -1;
- int in, out, inbak, outbak, errbak;
- int x, y;
- Lisp_Object cmd;
-
- /* Get current directory as MSDOS cwd is not per-process. */
- getwd (oldwd);
-
- /* If argv[0] is the shell, it might come in any lettercase.
- Since `Fmember' is case-sensitive, we need to downcase
- argv[0], even if we are on case-preserving filesystems. */
- lowcase_argv0 = alloca (strlen (argv[0]) + 1);
- for (pa = argv[0], pl = lowcase_argv0; *pa; pl++)
- {
- *pl = *pa++;
- if (*pl >= 'A' && *pl <= 'Z')
- *pl += 'a' - 'A';
- }
- *pl = '\0';
-
- cmd = Ffile_name_nondirectory (build_string (lowcase_argv0));
- msshell = !NILP (Fmember (cmd, Fsymbol_value (intern ("msdos-shells"))))
- && !strcmp ("-c", argv[1]);
- if (msshell)
- {
- saveargv1 = argv[1];
- saveargv2 = argv[2];
- argv[1] = "/c";
- if (argv[2])
- {
- char *p = alloca (strlen (argv[2]) + 1);
-
- strcpy (argv[2] = p, saveargv2);
- while (*p && isspace (*p))
- p++;
- while (*p && !isspace (*p))
- if (*p == '/')
- *p++ = '\\';
- else
- p++;
- }
- }
-
- /* Build the environment array. */
- {
- extern Lisp_Object Vprocess_environment;
- Lisp_Object tmp, lst;
- int i, len;
-
- lst = Vprocess_environment;
- len = XFASTINT (Flength (lst));
-
- envv = alloca ((len + 1) * sizeof (char *));
- for (i = 0; i < len; i++)
- {
- tmp = Fcar (lst);
- lst = Fcdr (lst);
- CHECK_STRING (tmp, 0);
- envv[i] = alloca (XSTRING (tmp)->size + 1);
- strcpy (envv[i], XSTRING (tmp)->data);
- }
- envv[len] = (char *) 0;
- }
-
- if (STRINGP (dir))
- chdir (XSTRING (dir)->data);
- inbak = dup (0);
- outbak = dup (1);
- errbak = dup (2);
- if (inbak < 0 || outbak < 0 || errbak < 0)
- goto done; /* Allocation might fail due to lack of descriptors. */
-
- if (have_mouse > 0)
- mouse_get_xy (&x, &y);
-
- dos_ttcooked (); /* do it here while 0 = stdin */
-
- dup2 (tempin, 0);
- dup2 (tempout, 1);
- dup2 (temperr, 2);
-
-#if __DJGPP__ > 1
-
- if (msshell && !argv[3])
- {
- /* MS-DOS native shells are too restrictive. For starters, they
- cannot grok commands longer than 126 characters. In DJGPP v2
- and later, `system' is much smarter, so we'll call it instead. */
-
- extern char **environ;
- environ = envv;
-
- /* A shell gets a single argument--its full command
- line--whose original was saved in `saveargv2'. */
- result = system (saveargv2);
- }
- else
-
-#endif /* __DJGPP__ > 1 */
-
- result = spawnve (P_WAIT, argv[0], argv, envv);
-
- dup2 (inbak, 0);
- dup2 (outbak, 1);
- dup2 (errbak, 2);
- close (inbak);
- close (outbak);
- close (errbak);
-
- dos_ttraw ();
- if (have_mouse > 0)
- {
- mouse_init ();
- mouse_moveto (x, y);
- }
-
- /* Some programs might change the meaning of the highest bit of the
- text attribute byte, so we get blinking characters instead of the
- bright background colors. Restore that. */
- bright_bg ();
-
- done:
- chdir (oldwd);
- if (msshell)
- {
- argv[1] = saveargv1;
- argv[2] = saveargv2;
- }
- return result;
-}
-
-croak (badfunc)
- char *badfunc;
-{
- fprintf (stderr, "%s not yet implemented\r\n", badfunc);
- reset_sys_modes ();
- exit (1);
-}
-
-#if __DJGPP__ < 2
-
-/* ------------------------- Compatibility functions -------------------
- * gethostname
- * gettimeofday
- */
-
-/* Hostnames for a pc are not really funny,
- but they are used in change log so we emulate the best we can. */
-
-gethostname (p, size)
- char *p;
- int size;
-{
- char *q = egetenv ("HOSTNAME");
-
- if (!q) q = "pc";
- strcpy (p, q);
- return 0;
-}
-
-/* When time zones are set from Ms-Dos too many C-libraries are playing
- tricks with time values. We solve this by defining our own version
- of `gettimeofday' bypassing GO32. Our version needs to be initialized
- once and after each call to `tzset' with TZ changed. That is
- accomplished by aliasing tzset to init_gettimeofday. */
-
-static struct tm time_rec;
-
-int
-gettimeofday (struct timeval *tp, struct timezone *tzp)
-{
- if (tp)
- {
- struct time t;
- struct tm tm;
-
- gettime (&t);
- if (t.ti_hour < time_rec.tm_hour) /* midnight wrap */
- {
- struct date d;
- getdate (&d);
- time_rec.tm_year = d.da_year - 1900;
- time_rec.tm_mon = d.da_mon - 1;
- time_rec.tm_mday = d.da_day;
- }
-
- time_rec.tm_hour = t.ti_hour;
- time_rec.tm_min = t.ti_min;
- time_rec.tm_sec = t.ti_sec;
-
- tm = time_rec;
- tm.tm_gmtoff = dos_timezone_offset;
-
- tp->tv_sec = mktime (&tm); /* may modify tm */
- tp->tv_usec = t.ti_hund * (1000000 / 100);
- }
- /* Ignore tzp; it's obsolescent. */
- return 0;
-}
-
-#endif /* __DJGPP__ < 2 */
-
-/*
- * A list of unimplemented functions that we silently ignore.
- */
-
-#if __DJGPP__ < 2
-unsigned alarm (s) unsigned s; {}
-fork () { return 0; }
-int kill (x, y) int x, y; { return -1; }
-nice (p) int p; {}
-void volatile pause () {}
-sigsetmask (x) int x; { return 0; }
-#endif
-
-request_sigio () {}
-setpgrp () {return 0; }
-setpriority (x,y,z) int x,y,z; { return 0; }
-sigblock (mask) int mask; { return 0; }
-unrequest_sigio () {}
-
-#ifndef HAVE_SELECT
-#include "sysselect.h"
-
-#ifndef EMACS_TIME_ZERO_OR_NEG_P
-#define EMACS_TIME_ZERO_OR_NEG_P(time) \
- ((long)(time).tv_sec < 0 \
- || ((time).tv_sec == 0 \
- && (long)(time).tv_usec <= 0))
-#endif
-
-
-/* Only event queue is checked. */
-/* We don't have to call timer_check here
- because wait_reading_process_input takes care of that. */
-int
-sys_select (nfds, rfds, wfds, efds, timeout)
- int nfds;
- SELECT_TYPE *rfds, *wfds, *efds;
- EMACS_TIME *timeout;
-{
- int check_input;
- struct time t;
-
- check_input = 0;
- if (rfds)
- {
- check_input = FD_ISSET (0, rfds);
- FD_ZERO (rfds);
- }
- if (wfds)
- FD_ZERO (wfds);
- if (efds)
- FD_ZERO (efds);
-
- if (nfds != 1)
- abort ();
-
- /* If we are looking only for the terminal, with no timeout,
- just read it and wait -- that's more efficient. */
- if (!timeout)
- {
- while (!detect_input_pending ())
- {
-#if __DJGPP__ >= 2
- __dpmi_yield ();
-#endif
- }
- }
- else
- {
- EMACS_TIME clnow, cllast, cldiff;
-
- gettime (&t);
- EMACS_SET_SECS_USECS (cllast, t.ti_sec, t.ti_hund * 10000L);
-
- while (!check_input || !detect_input_pending ())
- {
- gettime (&t);
- EMACS_SET_SECS_USECS (clnow, t.ti_sec, t.ti_hund * 10000L);
- EMACS_SUB_TIME (cldiff, clnow, cllast);
-
- /* When seconds wrap around, we assume that no more than
- 1 minute passed since last `gettime'. */
- if (EMACS_TIME_NEG_P (cldiff))
- EMACS_SET_SECS (cldiff, EMACS_SECS (cldiff) + 60);
- EMACS_SUB_TIME (*timeout, *timeout, cldiff);
-
- /* Stop when timeout value crosses zero. */
- if (EMACS_TIME_ZERO_OR_NEG_P (*timeout))
- return 0;
- cllast = clnow;
-#if __DJGPP__ >= 2
- __dpmi_yield ();
-#endif
- }
- }
-
- FD_SET (0, rfds);
- return 1;
-}
-#endif
-
-/*
- * Define overlaid functions:
- *
- * chdir -> sys_chdir
- * tzset -> init_gettimeofday
- * abort -> dos_abort
- */
-
-#ifdef chdir
-#undef chdir
-extern int chdir ();
-
-int
-sys_chdir (path)
- const char* path;
-{
- int len = strlen (path);
- char *tmp = (char *)path;
-
- if (*tmp && tmp[1] == ':')
- {
- if (getdisk () != tolower (tmp[0]) - 'a')
- setdisk (tolower (tmp[0]) - 'a');
- tmp += 2; /* strip drive: KFS 1995-07-06 */
- len -= 2;
- }
-
- if (len > 1 && (tmp[len - 1] == '/'))
- {
- char *tmp1 = (char *) alloca (len + 1);
- strcpy (tmp1, tmp);
- tmp1[len - 1] = 0;
- tmp = tmp1;
- }
- return chdir (tmp);
-}
-#endif
-
-#ifdef tzset
-#undef tzset
-extern void tzset (void);
-
-void
-init_gettimeofday ()
-{
- time_t ltm, gtm;
- struct tm *lstm;
-
- tzset ();
- ltm = gtm = time (NULL);
- ltm = mktime (lstm = localtime (&ltm));
- gtm = mktime (gmtime (&gtm));
- time_rec.tm_hour = 99; /* force gettimeofday to get date */
- time_rec.tm_isdst = lstm->tm_isdst;
- dos_timezone_offset = time_rec.tm_gmtoff = (int)(gtm - ltm) / 60;
-}
-#endif
-
-#ifdef abort
-#undef abort
-void
-dos_abort (file, line)
- char *file;
- int line;
-{
- char buffer1[200], buffer2[400];
- int i, j;
-
- sprintf (buffer1, "<EMACS FATAL ERROR IN %s LINE %d>", file, line);
- for (i = j = 0; buffer1[i]; i++) {
- buffer2[j++] = buffer1[i];
- buffer2[j++] = 0x70;
- }
- dosmemput (buffer2, j, (int)ScreenPrimary);
- ScreenSetCursor (2, 0);
- abort ();
-}
-#else
-void
-abort ()
-{
- dos_ttcooked ();
- ScreenSetCursor (10, 0);
- cputs ("\r\n\nEmacs aborted!\r\n");
-#if __DJGPP__ > 1
- /* Generate traceback, so we could tell whodunit. */
- signal (SIGINT, SIG_DFL);
- __asm__ __volatile__ ("movb $0x1b,%al;call ___djgpp_hw_exception");
-#endif
- exit (2);
-}
-#endif
-
-syms_of_msdos ()
-{
- recent_doskeys = Fmake_vector (make_number (NUM_RECENT_DOSKEYS), Qnil);
- staticpro (&recent_doskeys);
-
- defsubr (&Srecent_doskeys);
- defsubr (&Smsdos_long_file_names);
- defsubr (&Smsdos_downcase_filename);
-}
-
-#endif /* MSDOS */
diff --git a/src/msdos.h b/src/msdos.h
deleted file mode 100644
index 3e3c6ec0695..00000000000
--- a/src/msdos.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* MS-DOS specific C utilities, interface.
- Copyright (C) 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifndef _MSDOS_H_
-#define _MSDOS_H_
-
-#include <dpmi.h>
-
-int dos_ttraw ();
-int dos_ttcooked ();
-int dos_get_saved_screen (char **, int *, int *);
-int dos_set_keyboard (int, int);
-void dos_set_window_size (int *, int *);
-
-int getdefdir (int, char*);
-void unixtodos_filename (char *);
-void dostounix_filename (char *);
-char *rootrelativepath (char *);
-void init_environment ();
-void internal_terminal_init ();
-void ctrl_break_func (_go32_dpmi_registers *);
-void install_ctrl_break_check ();
-
-extern int have_mouse;
-void mouse_init ();
-void mouse_on ();
-void mouse_off ();
-void mouse_moveto (int, int);
-
-#ifndef HAVE_X_WINDOWS
-/* Dummy types. */
-typedef int XFontStruct;
-typedef int GC;
-typedef int Pixmap;
-typedef int Display;
-typedef int Window;
-#define PIX_TYPE int
-#define XDISPLAY
-
-/* This is a cut-down version of the one in xterm.h, which see. */
-struct x_output
-{
- int left_pos;
- int top_pos;
- int line_height;
- PIX_TYPE background_pixel;
- PIX_TYPE foreground_pixel;
- XFontStruct *font;
- struct face **param_faces;
- int n_param_faces;
- struct face **computed_faces;
- int n_computed_faces;
- int size_computed_faces;
-};
-
-extern struct x_output the_only_x_display;
-extern Display *x_current_display;
-
-#define FRAME_PARAM_FACES(f) (the_only_x_display.param_faces)
-#define FRAME_N_PARAM_FACES(f) (the_only_x_display.n_param_faces)
-#define FRAME_DEFAULT_PARAM_FACE(f) (FRAME_PARAM_FACES (f)[0])
-#define FRAME_MODE_LINE_PARAM_FACE(f) (FRAME_PARAM_FACES (f)[1])
-#define FRAME_COMPUTED_FACES(f) (the_only_x_display.computed_faces)
-#define FRAME_N_COMPUTED_FACES(f) (the_only_x_display.n_computed_faces)
-#define FRAME_SIZE_COMPUTED_FACES(f) (the_only_x_display.size_computed_faces)
-#define FRAME_DEFAULT_FACE(f) (the_only_x_display.computed_faces[0])
-#define FRAME_MODE_LINE_FACE(f) (the_only_x_display.computed_faces[1])
-#define FRAME_X_DISPLAY(f) ((Display *) 0)
-#define FRAME_FOREGROUND_PIXEL(f) (the_only_x_display.foreground_pixel)
-#define FRAME_BACKGROUND_PIXEL(f) (the_only_x_display.background_pixel)
-#define FRAME_FONT(f) (the_only_x_display.font)
-
-#define XFreeGC (void)
-#define same_size_fonts(foo,bar) (1)
-#define unload_font(p1,p2)
-#define unload_color(p1,p2)
-#define x_destroy_bitmap(p1,p2)
-#define load_pixmap(p1,p2,p3,p4) (0)
-#define XGetGeometry(p1,p2,p3,p4,p5,p6,p7,p8,p9)
-#define DisplayWidth(p1,p2) (selected_frame->width)
-#define DisplayHeight(p1,p2) (selected_frame->height)
-#define XMenuSetAEQ (void)
-#define XMenuSetFreeze (void)
-#define XMenuRecompute (void)
-#define FONT_WIDTH(foo) 1
-#define XM_FAILURE -1
-#define XM_SUCCESS 1
-#define XM_NO_SELECT 2
-#define XM_IA_SELECT 3
-#define ButtonReleaseMask 0
-
-typedef struct x_menu_struct
-{
- int count;
- char **text;
- struct x_menu_struct **submenu;
- int *panenumber; /* Also used as enable. */
- int allocated;
- int panecount;
- int width;
-} XMenu;
-
-XMenu *XMenuCreate (Display *, Window, char *);
-int XMenuAddPane (Display *, XMenu *, char *, int);
-int XMenuAddSelection (Display *, XMenu *, int, int, char *, int);
-void XMenuLocate (Display *, XMenu *, int, int, int, int,
- int *, int *, int *, int *);
-int XMenuActivate (Display *, XMenu *, int *, int *, int, int, unsigned, char **);
-void XMenuDestroy (Display *, XMenu *);
-
-#endif /* not HAVE_X_WINDOWS */
-
-#endif /* not _MSDOS_H_ */
diff --git a/src/ndir.h b/src/ndir.h
deleted file mode 100644
index f02dfbd6703..00000000000
--- a/src/ndir.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- <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 "vmsdir.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
-#ifdef WINDOWSNT
-#define MAXNAMLEN 255
-#else /* not WINDOWSNT */
-#define MAXNAMLEN 15 /* maximum filename length */
-#endif /* not WINDOWSNT */
-#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/param.h b/src/param.h
deleted file mode 100644
index 1b27b50a276..00000000000
--- a/src/param.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* This is so that Emacs can run on VMS... */
-#define EXEC_PAGESIZE 512
diff --git a/src/point.h b/src/point.h
deleted file mode 100644
index 7bae693f2d4..00000000000
--- a/src/point.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#define point_width 5
-#define point_height 19
-static char point_bits[] = {
- 0x1f, 0x0e, 0x0e, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x04, 0x04, 0x0e, 0x0e, 0x1f};
diff --git a/src/pre-crt0.c b/src/pre-crt0.c
deleted file mode 100644
index 67fd31cd6ac..00000000000
--- a/src/pre-crt0.c
+++ /dev/null
@@ -1,9 +0,0 @@
-/* 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/print.c b/src/print.c
deleted file mode 100644
index db0b4cba965..00000000000
--- a/src/print.c
+++ /dev/null
@@ -1,1491 +0,0 @@
-/* Lisp object printing and output streams.
- Copyright (C) 1985, 86, 88, 93, 94, 95 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include <stdio.h>
-#include "lisp.h"
-
-#ifndef standalone
-#include "buffer.h"
-#include "frame.h"
-#include "window.h"
-#include "process.h"
-#include "dispextern.h"
-#include "termchar.h"
-#include "keyboard.h"
-#endif /* not standalone */
-
-#ifdef USE_TEXT_PROPERTIES
-#include "intervals.h"
-#endif
-
-Lisp_Object Vstandard_output, Qstandard_output;
-
-/* These are used to print like we read. */
-extern Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
-
-#ifdef LISP_FLOAT_TYPE
-Lisp_Object Vfloat_output_format, Qfloat_output_format;
-#endif /* LISP_FLOAT_TYPE */
-
-/* Avoid actual stack overflow in print. */
-int print_depth;
-
-/* Detect most circularities to print finite output. */
-#define PRINT_CIRCLE 200
-Lisp_Object being_printed[PRINT_CIRCLE];
-
-/* When printing into a buffer, first we put the text in this
- block, then insert it all at once. */
-char *print_buffer;
-
-/* Size allocated in print_buffer. */
-int print_buffer_size;
-/* Size used in print_buffer. */
-int print_buffer_pos;
-
-/* Maximum length of list to print in full; noninteger means
- effectively infinity */
-
-Lisp_Object Vprint_length;
-
-/* Maximum depth of list to print in full; noninteger means
- effectively infinity. */
-
-Lisp_Object Vprint_level;
-
-/* Nonzero means print newlines in strings as \n. */
-
-int print_escape_newlines;
-
-Lisp_Object Qprint_escape_newlines;
-
-/* Nonzero means print (quote foo) forms as 'foo, etc. */
-
-int print_quoted;
-
-/* Nonzero means print #: before uninterned symbols. */
-
-int print_gensym;
-
-/* Association list of certain objects that are `eq' in the form being
- printed and which should be `eq' when read back in, using the #n=object
- and #n# reader forms. Each element has the form (object . n). */
-
-Lisp_Object printed_gensyms;
-
-/* Nonzero means print newline to stdout 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 */
-
-void print_interval ();
-
-#if 0
-/* Convert between chars and GLYPHs */
-
-int
-glyphlen (glyphs)
- register GLYPH *glyphs;
-{
- register int i = 0;
-
- while (glyphs[i])
- i++;
- return i;
-}
-
-void
-str_to_glyph_cpy (str, glyphs)
- char *str;
- GLYPH *glyphs;
-{
- register GLYPH *gp = glyphs;
- register char *cp = str;
-
- while (*cp)
- *gp++ = *cp++;
-}
-
-void
-str_to_glyph_ncpy (str, glyphs, n)
- char *str;
- GLYPH *glyphs;
- register int n;
-{
- register GLYPH *gp = glyphs;
- register char *cp = str;
-
- while (n-- > 0)
- *gp++ = *cp++;
-}
-
-void
-glyph_to_str_cpy (glyphs, str)
- GLYPH *glyphs;
- char *str;
-{
- register GLYPH *gp = glyphs;
- register char *cp = str;
-
- while (*gp)
- *str++ = *gp++ & 0377;
-}
-#endif
-
-/* Low level output routines for characters and strings */
-
-/* Lisp functions to do output using a stream
- must have the stream in a variable called printcharfun
- and must start with PRINTPREPARE, end with PRINTFINISH,
- and use PRINTDECLARE to declare common variables.
- Use PRINTCHAR to output one character,
- or call strout to output a block of characters.
-*/
-
-#define PRINTDECLARE \
- struct buffer *old = current_buffer; \
- int old_point = -1, start_point; \
- int specpdl_count = specpdl_ptr - specpdl; \
- int free_print_buffer = 0; \
- Lisp_Object original
-
-#define PRINTPREPARE \
- original = printcharfun; \
- if (NILP (printcharfun)) printcharfun = Qt; \
- if (BUFFERP (printcharfun)) \
- { \
- if (XBUFFER (printcharfun) != current_buffer) \
- Fset_buffer (printcharfun); \
- printcharfun = Qnil; \
- } \
- if (MARKERP (printcharfun)) \
- { \
- if (!(XMARKER (original)->buffer)) \
- error ("Marker does not point anywhere"); \
- if (XMARKER (original)->buffer != current_buffer) \
- set_buffer_internal (XMARKER (original)->buffer); \
- old_point = PT; \
- SET_PT (marker_position (printcharfun)); \
- start_point = PT; \
- printcharfun = Qnil; \
- } \
- if (NILP (printcharfun)) \
- { \
- if (print_buffer != 0) \
- record_unwind_protect (print_unwind, \
- make_string (print_buffer, \
- print_buffer_pos)); \
- else \
- { \
- print_buffer_size = 1000; \
- print_buffer = (char *) xmalloc (print_buffer_size); \
- free_print_buffer = 1; \
- } \
- print_buffer_pos = 0; \
- } \
- printed_gensyms = Qnil
-
-#define PRINTFINISH \
- if (NILP (printcharfun)) \
- insert (print_buffer, print_buffer_pos); \
- if (free_print_buffer) \
- { \
- xfree (print_buffer); \
- print_buffer = 0; \
- } \
- unbind_to (specpdl_count, Qnil); \
- if (MARKERP (original)) \
- Fset_marker (original, make_number (PT), Qnil); \
- if (old_point >= 0) \
- SET_PT (old_point + (old_point >= start_point \
- ? PT - start_point : 0)); \
- if (old != current_buffer) \
- set_buffer_internal (old); \
- printed_gensyms = Qnil
-
-#define PRINTCHAR(ch) printchar (ch, printcharfun)
-
-/* Nonzero if there is no room to print any more characters
- so print might as well return right away. */
-
-#define PRINTFULLP() \
- (EQ (printcharfun, Qt) && !noninteractive \
- && printbufidx >= FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)))))
-
-/* This is used to restore the saved contents of print_buffer
- when there is a recursive call to print. */
-static Lisp_Object
-print_unwind (saved_text)
- Lisp_Object saved_text;
-{
- bcopy (XSTRING (saved_text)->data, print_buffer, XSTRING (saved_text)->size);
-}
-
-/* Index of first unused element of FRAME_MESSAGE_BUF (mini_frame). */
-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;
- if (print_buffer_pos == print_buffer_size)
- print_buffer = (char *) xrealloc (print_buffer,
- print_buffer_size *= 2);
- print_buffer[print_buffer_pos++] = ch;
- return;
- }
-
- if (EQ (fun, Qt))
- {
- FRAME_PTR mini_frame
- = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)));
-
- QUIT;
-
- if (noninteractive)
- {
- putchar (ch);
- noninteractive_need_newline = 1;
- return;
- }
-
- if (echo_area_glyphs != FRAME_MESSAGE_BUF (mini_frame)
- || !message_buf_print)
- {
- message_log_maybe_newline ();
- echo_area_glyphs = FRAME_MESSAGE_BUF (mini_frame);
- printbufidx = 0;
- echo_area_glyphs_length = 0;
- message_buf_print = 1;
- }
-
- message_dolog (&ch, 1, 0);
- if (printbufidx < FRAME_WIDTH (mini_frame) - 1)
- FRAME_MESSAGE_BUF (mini_frame)[printbufidx++] = ch;
- FRAME_MESSAGE_BUF (mini_frame)[printbufidx] = 0;
- echo_area_glyphs_length = printbufidx;
-
- return;
- }
-#endif /* not standalone */
-
- XSETFASTINT (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))
- {
- if (size < 0)
- size = strlen (ptr);
-
- if (print_buffer_pos + size > print_buffer_size)
- {
- print_buffer_size = print_buffer_size * 2 + size;
- print_buffer = (char *) xrealloc (print_buffer,
- print_buffer_size);
- }
- bcopy (ptr, print_buffer + print_buffer_pos, size);
- print_buffer_pos += size;
-
-#ifdef MAX_PRINT_CHARS
- if (max_print)
- print_chars += size;
-#endif /* MAX_PRINT_CHARS */
- return;
- }
- if (EQ (printcharfun, Qt))
- {
- FRAME_PTR mini_frame
- = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)));
-
- QUIT;
-
- 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_glyphs != FRAME_MESSAGE_BUF (mini_frame)
- || !message_buf_print)
- {
- message_log_maybe_newline ();
- echo_area_glyphs = FRAME_MESSAGE_BUF (mini_frame);
- printbufidx = 0;
- echo_area_glyphs_length = 0;
- message_buf_print = 1;
- }
-
- message_dolog (ptr, i, 0);
- if (i > FRAME_WIDTH (mini_frame) - printbufidx - 1)
- i = FRAME_WIDTH (mini_frame) - printbufidx - 1;
- bcopy (ptr, &FRAME_MESSAGE_BUF (mini_frame) [printbufidx], i);
- printbufidx += i;
- echo_area_glyphs_length = printbufidx;
- FRAME_MESSAGE_BUF (mini_frame) [printbufidx] = 0;
-
- return;
- }
-
- if (size >= 0)
- while (i < size)
- PRINTCHAR (ptr[i++]);
- else
- while (ptr[i])
- PRINTCHAR (ptr[i++]);
-}
-
-/* Print the contents of a string STRING using PRINTCHARFUN.
- It isn't safe to use strout in many cases,
- because printing one char can relocate. */
-
-print_string (string, printcharfun)
- Lisp_Object string;
- Lisp_Object printcharfun;
-{
- if (EQ (printcharfun, Qt) || NILP (printcharfun))
- /* strout is safe for output to a frame (echo area) or to print_buffer. */
- strout (XSTRING (string)->data, XSTRING (string)->size, printcharfun);
- else
- {
- /* Otherwise, fetch the string address for each character. */
- int i;
- int size = XSTRING (string)->size;
- struct gcpro gcpro1;
- GCPRO1 (string);
- for (i = 0; i < size; i++)
- PRINTCHAR (XSTRING (string)->data[i]);
- UNGCPRO;
- }
-}
-
-DEFUN ("write-char", Fwrite_char, Swrite_char, 1, 2, 0,
- "Output character CHARACTER to stream PRINTCHARFUN.\n\
-PRINTCHARFUN defaults to the value of `standard-output' (which see).")
- (character, printcharfun)
- Lisp_Object character, printcharfun;
-{
- PRINTDECLARE;
-
- if (NILP (printcharfun))
- printcharfun = Vstandard_output;
- CHECK_NUMBER (character, 0);
- PRINTPREPARE;
- PRINTCHAR (XINT (character));
- PRINTFINISH;
- return character;
-}
-
-/* Used from outside of print.c to print a block of SIZE chars at DATA
- on the default output stream.
- Do not use this on the contents of a Lisp string. */
-
-write_string (data, size)
- char *data;
- int size;
-{
- PRINTDECLARE;
- Lisp_Object printcharfun;
-
- printcharfun = Vstandard_output;
-
- PRINTPREPARE;
- strout (data, size, printcharfun);
- PRINTFINISH;
-}
-
-/* Used from outside of print.c to print a block of SIZE chars at DATA
- on a specified stream PRINTCHARFUN.
- Do not use this on the contents of a Lisp string. */
-
-write_string_1 (data, size, printcharfun)
- char *data;
- int size;
- Lisp_Object printcharfun;
-{
- PRINTDECLARE;
-
- PRINTPREPARE;
- strout (data, size, printcharfun);
- PRINTFINISH;
-}
-
-
-#ifndef standalone
-
-void
-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->directory = old->directory;
- current_buffer->read_only = Qnil;
- Ferase_buffer ();
-
- XSETBUFFER (buf, 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;
- struct gcpro gcpro1;
-
- GCPRO1 (args);
- record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
- temp_output_buffer_setup (bufname);
- buf = Vstandard_output;
- UNGCPRO;
-
- val = (*function) (args);
-
- GCPRO1 (val);
- temp_output_buffer_show (buf);
- UNGCPRO;
-
- return unbind_to (count, val);
-}
-
-DEFUN ("with-output-to-temp-buffer", Fwith_output_to_temp_buffer, Swith_output_to_temp_buffer,
- 1, UNEVALLED, 0,
- "Bind `standard-output' to buffer BUFNAME, eval BODY, then show 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\
-The buffer is displayed in another window, but not selected.\n\
-The value of the last form in BODY is returned.\n\
-If BODY does not finish normally, the buffer BUFNAME is not displayed.\n\n\
-If variable `temp-buffer-show-function' 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);
-
- return unbind_to (count, val);
-}
-#endif /* not standalone */
-
-static void print ();
-
-DEFUN ("terpri", Fterpri, Sterpri, 0, 1, 0,
- "Output a newline to stream PRINTCHARFUN.\n\
-If PRINTCHARFUN is omitted or nil, the value of `standard-output' is used.")
- (printcharfun)
- Lisp_Object printcharfun;
-{
- PRINTDECLARE;
-
- if (NILP (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 PRINTCHARFUN, or value of `standard-output' (which see).")
- (object, printcharfun)
- Lisp_Object object, printcharfun;
-{
- PRINTDECLARE;
-
-#ifdef MAX_PRINT_CHARS
- max_print = 0;
-#endif /* MAX_PRINT_CHARS */
- if (NILP (printcharfun))
- printcharfun = Vstandard_output;
- PRINTPREPARE;
- print_depth = 0;
- print (object, printcharfun, 1);
- PRINTFINISH;
- return object;
-}
-
-/* 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, 2, 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, unless the optional\n\
-second argument NOESCAPE is non-nil.")
- (object, noescape)
- Lisp_Object object, noescape;
-{
- PRINTDECLARE;
- Lisp_Object printcharfun;
- struct gcpro gcpro1, gcpro2;
- Lisp_Object tem;
-
- /* Save and restore this--we are altering a buffer
- but we don't want to deactivate the mark just for that.
- No need for specbind, since errors deactivate the mark. */
- tem = Vdeactivate_mark;
- GCPRO2 (object, tem);
-
- printcharfun = Vprin1_to_string_buffer;
- PRINTPREPARE;
- print_depth = 0;
- print (object, printcharfun, NILP (noescape));
- /* Make Vprin1_to_string_buffer be the default buffer after PRINTFINSH */
- PRINTFINISH;
- set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
- object = Fbuffer_string ();
-
- Ferase_buffer ();
- set_buffer_internal (old);
-
- Vdeactivate_mark = tem;
- UNGCPRO;
-
- return object;
-}
-
-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 PRINTCHARFUN, or value of standard-output (which see).")
- (object, printcharfun)
- Lisp_Object object, printcharfun;
-{
- PRINTDECLARE;
-
- if (NILP (printcharfun))
- printcharfun = Vstandard_output;
- PRINTPREPARE;
- print_depth = 0;
- print (object, printcharfun, 0);
- PRINTFINISH;
- return object;
-}
-
-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 PRINTCHARFUN, or value of `standard-output' (which see).")
- (object, printcharfun)
- Lisp_Object object, printcharfun;
-{
- PRINTDECLARE;
- struct gcpro gcpro1;
-
-#ifdef MAX_PRINT_CHARS
- print_chars = 0;
- max_print = MAX_PRINT_CHARS;
-#endif /* MAX_PRINT_CHARS */
- if (NILP (printcharfun))
- printcharfun = Vstandard_output;
- GCPRO1 (object);
- PRINTPREPARE;
- print_depth = 0;
- PRINTCHAR ('\n');
- print (object, printcharfun, 1);
- PRINTCHAR ('\n');
- PRINTFINISH;
-#ifdef MAX_PRINT_CHARS
- max_print = 0;
- print_chars = 0;
-#endif /* MAX_PRINT_CHARS */
- UNGCPRO;
- return object;
-}
-
-/* The subroutine object for external-debugging-output is kept here
- for the convenience of the debugger. */
-Lisp_Object Qexternal_debugging_output;
-
-DEFUN ("external-debugging-output", Fexternal_debugging_output, Sexternal_debugging_output, 1, 1, 0,
- "Write CHARACTER to stderr.\n\
-You can call print while debugging emacs, and pass it this function\n\
-to make it write to the debugging output.\n")
- (character)
- Lisp_Object character;
-{
- CHECK_NUMBER (character, 0);
- putc (XINT (character), stderr);
-
- return character;
-}
-
-/* This is the interface for debugging printing. */
-
-void
-debug_print (arg)
- Lisp_Object arg;
-{
- Fprin1 (arg, Qexternal_debugging_output);
- fprintf (stderr, "\r\n");
-}
-
-DEFUN ("error-message-string", Ferror_message_string, Serror_message_string,
- 1, 1, 0,
- "Convert an error value (ERROR-SYMBOL . DATA) to an error message.")
- (obj)
- Lisp_Object obj;
-{
- struct buffer *old = current_buffer;
- Lisp_Object original, printcharfun, value;
- struct gcpro gcpro1;
-
- print_error_message (obj, Vprin1_to_string_buffer, NULL);
-
- set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
- value = Fbuffer_string ();
-
- GCPRO1 (value);
- Ferase_buffer ();
- set_buffer_internal (old);
- UNGCPRO;
-
- return value;
-}
-
-/* Print an error message for the error DATA
- onto Lisp output stream STREAM (suitable for the print functions). */
-
-print_error_message (data, stream)
- Lisp_Object data, stream;
-{
- Lisp_Object errname, errmsg, file_error, tail;
- struct gcpro gcpro1;
- int i;
-
- 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. */
-
- tail = Fcdr_safe (data);
- GCPRO1 (tail);
-
- /* For file-error, make error message by concatenating
- all the data items. They are all strings. */
- if (!NILP (file_error) && !NILP (tail))
- errmsg = XCONS (tail)->car, tail = XCONS (tail)->cdr;
-
- if (STRINGP (errmsg))
- Fprinc (errmsg, stream);
- else
- write_string_1 ("peculiar error", -1, stream);
-
- for (i = 0; CONSP (tail); tail = Fcdr (tail), i++)
- {
- write_string_1 (i ? ", " : ": ", 2, stream);
- if (!NILP (file_error))
- Fprinc (Fcar (tail), stream);
- else
- Fprin1 (Fcar (tail), stream);
- }
- UNGCPRO;
-}
-
-#ifdef LISP_FLOAT_TYPE
-
-/*
- * The buffer should be at least as large as the max string size of the
- * largest float, printed in the biggest notation. This is undoubtedly
- * 20d float_output_format, with the negative of the C-constant "HUGE"
- * from <math.h>.
- *
- * On the vax the worst case is -1e38 in 20d format which takes 61 bytes.
- *
- * I assume that IEEE-754 format numbers can take 329 bytes for the worst
- * case of -1e307 in 20d float_output_format. What is one to do (short of
- * re-writing _doprnt to be more sane)?
- * -wsr
- */
-
-void
-float_to_string (buf, data)
- unsigned char *buf;
- double data;
-{
- unsigned char *cp;
- int width;
-
- if (NILP (Vfloat_output_format)
- || !STRINGP (Vfloat_output_format))
- lose:
- {
- sprintf (buf, "%.17g", data);
- width = -1;
- }
- else /* oink oink */
- {
- /* Check that the spec we have is fully valid.
- This means not only valid for printf,
- but meant for floats, and reasonable. */
- cp = XSTRING (Vfloat_output_format)->data;
-
- if (cp[0] != '%')
- goto lose;
- if (cp[1] != '.')
- goto lose;
-
- cp += 2;
-
- /* Check the width specification. */
- width = -1;
- if ('0' <= *cp && *cp <= '9')
- {
- width = 0;
- do
- width = (width * 10) + (*cp++ - '0');
- while (*cp >= '0' && *cp <= '9');
-
- /* A precision of zero is valid only for %f. */
- if (width > DBL_DIG
- || (width == 0 && *cp != 'f'))
- goto lose;
- }
-
- if (*cp != 'e' && *cp != 'f' && *cp != 'g')
- goto lose;
-
- if (cp[1] != 0)
- goto lose;
-
- sprintf (buf, XSTRING (Vfloat_output_format)->data, data);
- }
-
- /* Make sure there is a decimal point with digit after, or an
- exponent, so that the value is readable as a float. But don't do
- this with "%.0f"; it's valid for that not to produce a decimal
- point. Note that width can be 0 only for %.0f. */
- if (width != 0)
- {
- for (cp = buf; *cp; cp++)
- if ((*cp < '0' || *cp > '9') && *cp != '-')
- break;
-
- if (*cp == '.' && cp[1] == 0)
- {
- cp[1] = '0';
- cp[2] = 0;
- }
-
- if (*cp == 0)
- {
- *cp++ = '.';
- *cp++ = '0';
- *cp++ = 0;
- }
- }
-}
-#endif /* LISP_FLOAT_TYPE */
-
-static void
-print (obj, printcharfun, escapeflag)
- Lisp_Object obj;
- register Lisp_Object printcharfun;
- int escapeflag;
-{
- char buf[30];
-
- QUIT;
-
-#if 1 /* I'm not sure this is really worth doing. */
- /* Detect circularities and truncate them.
- No need to offer any alternative--this is better than an error. */
- if (CONSP (obj) || VECTORP (obj) || COMPILEDP (obj))
- {
- int i;
- for (i = 0; i < print_depth; i++)
- if (EQ (obj, being_printed[i]))
- {
- sprintf (buf, "#%d", i);
- strout (buf, -1, printcharfun);
- return;
- }
- }
-#endif
-
- being_printed[print_depth] = obj;
- print_depth++;
-
- if (print_depth > PRINT_CIRCLE)
- 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 */
-
- switch (XGCTYPE (obj))
- {
- case Lisp_Int:
- if (sizeof (int) == sizeof (EMACS_INT))
- sprintf (buf, "%d", XINT (obj));
- else if (sizeof (long) == sizeof (EMACS_INT))
- sprintf (buf, "%ld", XINT (obj));
- else
- abort ();
- strout (buf, -1, printcharfun);
- break;
-
-#ifdef LISP_FLOAT_TYPE
- case Lisp_Float:
- {
- char pigbuf[350]; /* see comments in float_to_string */
-
- float_to_string (pigbuf, XFLOAT(obj)->data);
- strout (pigbuf, -1, printcharfun);
- }
- break;
-#endif
-
- case Lisp_String:
- if (!escapeflag)
- print_string (obj, printcharfun);
- else
- {
- register int i;
- register unsigned char c;
- struct gcpro gcpro1;
-
- GCPRO1 (obj);
-
-#ifdef USE_TEXT_PROPERTIES
- if (!NULL_INTERVAL_P (XSTRING (obj)->intervals))
- {
- PRINTCHAR ('#');
- PRINTCHAR ('(');
- }
-#endif
-
- PRINTCHAR ('\"');
- for (i = 0; i < XSTRING (obj)->size; i++)
- {
- QUIT;
- c = XSTRING (obj)->data[i];
- if (c == '\n' && print_escape_newlines)
- {
- PRINTCHAR ('\\');
- PRINTCHAR ('n');
- }
- else if (c == '\f' && print_escape_newlines)
- {
- PRINTCHAR ('\\');
- PRINTCHAR ('f');
- }
- else
- {
- if (c == '\"' || c == '\\')
- PRINTCHAR ('\\');
- PRINTCHAR (c);
- }
- }
- PRINTCHAR ('\"');
-
-#ifdef USE_TEXT_PROPERTIES
- if (!NULL_INTERVAL_P (XSTRING (obj)->intervals))
- {
- traverse_intervals (XSTRING (obj)->intervals,
- 0, 0, print_interval, printcharfun);
- PRINTCHAR (')');
- }
-#endif
-
- UNGCPRO;
- }
- 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;
- int i;
-
- if (p != end && (*p == '-' || *p == '+')) p++;
- if (p == end)
- confusing = 0;
- else
- {
- while (p != end && *p >= '0' && *p <= '9')
- p++;
- confusing = (end == p);
- }
-
- /* If we print an uninterned symbol as part of a complex object and
- the flag print-gensym is non-nil, prefix it with #n= to read the
- object back with the #n# reader syntax later if needed. */
- if (print_gensym && NILP (XSYMBOL (obj)->obarray))
- {
- if (print_depth > 1)
- {
- Lisp_Object tem;
- tem = Fassq (obj, printed_gensyms);
- if (CONSP (tem))
- {
- PRINTCHAR ('#');
- print (XCDR (tem), printcharfun, escapeflag);
- PRINTCHAR ('#');
- break;
- }
- else
- {
- if (CONSP (printed_gensyms))
- XSETFASTINT (tem, XCDR (XCAR (printed_gensyms)) + 1);
- else
- XSETFASTINT (tem, 1);
- printed_gensyms = Fcons (Fcons (obj, tem), printed_gensyms);
-
- PRINTCHAR ('#');
- print (tem, printcharfun, escapeflag);
- PRINTCHAR ('=');
- }
- }
- PRINTCHAR ('#');
- PRINTCHAR (':');
- }
-
- for (i = 0; i < XSYMBOL (obj)->name->size; i++)
- {
- QUIT;
- c = XSYMBOL (obj)->name->data[i];
-
- 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:
- /* If deeper than spec'd depth, print placeholder. */
- if (INTEGERP (Vprint_level)
- && print_depth > XINT (Vprint_level))
- strout ("...", -1, printcharfun);
- else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj)))
- && (EQ (XCAR (obj), Qquote)))
- {
- PRINTCHAR ('\'');
- print (XCAR (XCDR (obj)), printcharfun, escapeflag);
- }
- else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj)))
- && (EQ (XCAR (obj), Qfunction)))
- {
- PRINTCHAR ('#');
- PRINTCHAR ('\'');
- print (XCAR (XCDR (obj)), printcharfun, escapeflag);
- }
- else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj)))
- && ((EQ (XCAR (obj), Qbackquote)
- || EQ (XCAR (obj), Qcomma)
- || EQ (XCAR (obj), Qcomma_at)
- || EQ (XCAR (obj), Qcomma_dot))))
- {
- print (XCAR (obj), printcharfun, 0);
- print (XCAR (XCDR (obj)), printcharfun, escapeflag);
- }
- else
- {
- PRINTCHAR ('(');
- {
- register int i = 0;
- register int max = 0;
-
- if (INTEGERP (Vprint_length))
- max = XINT (Vprint_length);
- /* Could recognize circularities in cdrs here,
- but that would make printing of long lists quadratic.
- It's not worth doing. */
- while (CONSP (obj))
- {
- if (i++)
- PRINTCHAR (' ');
- if (max && i > max)
- {
- strout ("...", 3, printcharfun);
- break;
- }
- print (XCAR (obj), printcharfun, escapeflag);
- obj = XCDR (obj);
- }
- }
- if (!NILP (obj))
- {
- strout (" . ", 3, printcharfun);
- print (obj, printcharfun, escapeflag);
- }
- PRINTCHAR (')');
- }
- break;
-
- case Lisp_Vectorlike:
- if (PROCESSP (obj))
- {
- if (escapeflag)
- {
- strout ("#<process ", -1, printcharfun);
- print_string (XPROCESS (obj)->name, printcharfun);
- PRINTCHAR ('>');
- }
- else
- print_string (XPROCESS (obj)->name, printcharfun);
- }
- else if (BOOL_VECTOR_P (obj))
- {
- register int i;
- register unsigned char c;
- struct gcpro gcpro1;
- int size_in_chars
- = (XBOOL_VECTOR (obj)->size + BITS_PER_CHAR) / BITS_PER_CHAR;
-
- GCPRO1 (obj);
-
- PRINTCHAR ('#');
- PRINTCHAR ('&');
- sprintf (buf, "%d", XBOOL_VECTOR (obj)->size);
- strout (buf, -1, printcharfun);
- PRINTCHAR ('\"');
-
- /* Don't print more characters than the specified maximum. */
- if (INTEGERP (Vprint_length)
- && XINT (Vprint_length) < size_in_chars)
- size_in_chars = XINT (Vprint_length);
-
- for (i = 0; i < size_in_chars; i++)
- {
- QUIT;
- c = XBOOL_VECTOR (obj)->data[i];
- if (c == '\n' && print_escape_newlines)
- {
- PRINTCHAR ('\\');
- PRINTCHAR ('n');
- }
- else if (c == '\f' && print_escape_newlines)
- {
- PRINTCHAR ('\\');
- PRINTCHAR ('f');
- }
- else
- {
- if (c == '\"' || c == '\\')
- PRINTCHAR ('\\');
- PRINTCHAR (c);
- }
- }
- PRINTCHAR ('\"');
-
- UNGCPRO;
- }
- else if (SUBRP (obj))
- {
- strout ("#<subr ", -1, printcharfun);
- strout (XSUBR (obj)->symbol_name, -1, printcharfun);
- PRINTCHAR ('>');
- }
-#ifndef standalone
- else if (WINDOWP (obj))
- {
- strout ("#<window ", -1, printcharfun);
- sprintf (buf, "%d", XFASTINT (XWINDOW (obj)->sequence_number));
- strout (buf, -1, printcharfun);
- if (!NILP (XWINDOW (obj)->buffer))
- {
- strout (" on ", -1, printcharfun);
- print_string (XBUFFER (XWINDOW (obj)->buffer)->name, printcharfun);
- }
- PRINTCHAR ('>');
- }
- else if (BUFFERP (obj))
- {
- if (NILP (XBUFFER (obj)->name))
- strout ("#<killed buffer>", -1, printcharfun);
- else if (escapeflag)
- {
- strout ("#<buffer ", -1, printcharfun);
- print_string (XBUFFER (obj)->name, printcharfun);
- PRINTCHAR ('>');
- }
- else
- print_string (XBUFFER (obj)->name, printcharfun);
- }
- else if (WINDOW_CONFIGURATIONP (obj))
- {
- strout ("#<window-configuration>", -1, printcharfun);
- }
- else if (FRAMEP (obj))
- {
- strout ((FRAME_LIVE_P (XFRAME (obj))
- ? "#<frame " : "#<dead frame "),
- -1, printcharfun);
- print_string (XFRAME (obj)->name, printcharfun);
- sprintf (buf, " 0x%lx", (unsigned long) (XFRAME (obj)));
- strout (buf, -1, printcharfun);
- PRINTCHAR ('>');
- }
-#endif /* not standalone */
- else
- {
- int size = XVECTOR (obj)->size;
- if (COMPILEDP (obj))
- {
- PRINTCHAR ('#');
- size &= PSEUDOVECTOR_SIZE_MASK;
- }
- if (CHAR_TABLE_P (obj))
- {
- /* We print a char-table as if it were a vector,
- lumping the parent and default slots in with the
- character slots. But we add #^ as a prefix. */
- PRINTCHAR ('#');
- PRINTCHAR ('^');
- size &= PSEUDOVECTOR_SIZE_MASK;
- }
- if (size & PSEUDOVECTOR_FLAG)
- goto badtype;
-
- PRINTCHAR ('[');
- {
- register int i;
- register Lisp_Object tem;
-
- /* Don't print more elements than the specified maximum. */
- if (INTEGERP (Vprint_length)
- && XINT (Vprint_length) < size)
- size = XINT (Vprint_length);
-
- for (i = 0; i < size; i++)
- {
- if (i) PRINTCHAR (' ');
- tem = XVECTOR (obj)->contents[i];
- print (tem, printcharfun, escapeflag);
- }
- }
- PRINTCHAR (']');
- }
- break;
-
-#ifndef standalone
- case Lisp_Misc:
- switch (XMISCTYPE (obj))
- {
- case Lisp_Misc_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);
- print_string (XMARKER (obj)->buffer->name, printcharfun);
- }
- PRINTCHAR ('>');
- break;
-
- case Lisp_Misc_Overlay:
- strout ("#<overlay ", -1, printcharfun);
- if (!(XMARKER (OVERLAY_START (obj))->buffer))
- strout ("in no buffer", -1, printcharfun);
- else
- {
- sprintf (buf, "from %d to %d in ",
- marker_position (OVERLAY_START (obj)),
- marker_position (OVERLAY_END (obj)));
- strout (buf, -1, printcharfun);
- print_string (XMARKER (OVERLAY_START (obj))->buffer->name,
- printcharfun);
- }
- PRINTCHAR ('>');
- break;
-
- /* Remaining cases shouldn't happen in normal usage, but let's print
- them anyway for the benefit of the debugger. */
- case Lisp_Misc_Free:
- strout ("#<misc free cell>", -1, printcharfun);
- break;
-
- case Lisp_Misc_Intfwd:
- sprintf (buf, "#<intfwd to %d>", *XINTFWD (obj)->intvar);
- strout (buf, -1, printcharfun);
- break;
-
- case Lisp_Misc_Boolfwd:
- sprintf (buf, "#<boolfwd to %s>",
- (*XBOOLFWD (obj)->boolvar ? "t" : "nil"));
- strout (buf, -1, printcharfun);
- break;
-
- case Lisp_Misc_Objfwd:
- strout ("#<objfwd to ", -1, printcharfun);
- print (*XOBJFWD (obj)->objvar, printcharfun, escapeflag);
- PRINTCHAR ('>');
- break;
-
- case Lisp_Misc_Buffer_Objfwd:
- strout ("#<buffer_objfwd to ", -1, printcharfun);
- print (*(Lisp_Object *)((char *)current_buffer
- + XBUFFER_OBJFWD (obj)->offset),
- printcharfun, escapeflag);
- PRINTCHAR ('>');
- break;
-
- case Lisp_Misc_Kboard_Objfwd:
- strout ("#<kboard_objfwd to ", -1, printcharfun);
- print (*(Lisp_Object *)((char *) current_kboard
- + XKBOARD_OBJFWD (obj)->offset),
- printcharfun, escapeflag);
- PRINTCHAR ('>');
- break;
-
- case Lisp_Misc_Buffer_Local_Value:
- strout ("#<buffer_local_value ", -1, printcharfun);
- goto do_buffer_local;
- case Lisp_Misc_Some_Buffer_Local_Value:
- strout ("#<some_buffer_local_value ", -1, printcharfun);
- do_buffer_local:
- strout ("[realvalue] ", -1, printcharfun);
- print (XBUFFER_LOCAL_VALUE (obj)->car, printcharfun, escapeflag);
- strout ("[buffer] ", -1, printcharfun);
- print (XCONS (XBUFFER_LOCAL_VALUE (obj)->cdr)->car,
- printcharfun, escapeflag);
- strout ("[alist-elt] ", -1, printcharfun);
- print (XCONS (XCONS (XBUFFER_LOCAL_VALUE (obj)->cdr)->cdr)->car,
- printcharfun, escapeflag);
- strout ("[default-value] ", -1, printcharfun);
- print (XCONS (XCONS (XBUFFER_LOCAL_VALUE (obj)->cdr)->cdr)->cdr,
- printcharfun, escapeflag);
- PRINTCHAR ('>');
- break;
-
- default:
- goto badtype;
- }
- break;
-#endif /* standalone */
-
- default:
- badtype:
- {
- /* We're in trouble if this happens!
- Probably should just abort () */
- strout ("#<EMACS BUG: INVALID DATATYPE ", -1, printcharfun);
- if (MISCP (obj))
- sprintf (buf, "(MISC 0x%04x)", (int) XMISCTYPE (obj));
- else if (VECTORLIKEP (obj))
- sprintf (buf, "(PVEC 0x%08x)", (int) XVECTOR (obj)->size);
- else
- sprintf (buf, "(0x%02x)", (int) XTYPE (obj));
- strout (buf, -1, printcharfun);
- strout (" Save your buffers immediately and please report this bug>",
- -1, printcharfun);
- }
- }
-
- print_depth--;
-}
-
-#ifdef USE_TEXT_PROPERTIES
-
-/* Print a description of INTERVAL using PRINTCHARFUN.
- This is part of printing a string that has text properties. */
-
-void
-print_interval (interval, printcharfun)
- INTERVAL interval;
- Lisp_Object printcharfun;
-{
- PRINTCHAR (' ');
- print (make_number (interval->position), printcharfun, 1);
- PRINTCHAR (' ');
- print (make_number (interval->position + LENGTH (interval)),
- printcharfun, 1);
- PRINTCHAR (' ');
- print (interval->plist, printcharfun, 1);
-}
-
-#endif /* USE_TEXT_PROPERTIES */
-
-void
-syms_of_print ()
-{
- DEFVAR_LISP ("standard-output", &Vstandard_output,
- "Output stream `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 echo area).");
- Vstandard_output = Qt;
- Qstandard_output = intern ("standard-output");
- staticpro (&Qstandard_output);
-
-#ifdef LISP_FLOAT_TYPE
- DEFVAR_LISP ("float-output-format", &Vfloat_output_format,
- "The format descriptor string used to print floats.\n\
-This is a %-spec like those accepted by `printf' in C,\n\
-but with some restrictions. It must start with the two characters `%.'.\n\
-After that comes an integer precision specification,\n\
-and then a letter which controls the format.\n\
-The letters allowed are `e', `f' and `g'.\n\
-Use `e' for exponential notation \"DIG.DIGITSeEXPT\"\n\
-Use `f' for decimal point notation \"DIGITS.DIGITS\".\n\
-Use `g' to choose the shorter of those two formats for the number at hand.\n\
-The precision in any of these cases is the number of digits following\n\
-the decimal point. With `f', a precision of 0 means to omit the\n\
-decimal point. 0 is not allowed with `e' or `g'.\n\n\
-A value of nil means to use `%.17g'.");
- Vfloat_output_format = Qnil;
- Qfloat_output_format = intern ("float-output-format");
- staticpro (&Qfloat_output_format);
-#endif /* LISP_FLOAT_TYPE */
-
- DEFVAR_LISP ("print-length", &Vprint_length,
- "Maximum length of list to print before abbreviating.\n\
-A value of nil means no limit.");
- Vprint_length = Qnil;
-
- DEFVAR_LISP ("print-level", &Vprint_level,
- "Maximum depth of list nesting to print before abbreviating.\n\
-A value of nil means no limit.");
- Vprint_level = Qnil;
-
- DEFVAR_BOOL ("print-escape-newlines", &print_escape_newlines,
- "Non-nil means print newlines in strings as backslash-n.\n\
-Also print formfeeds as backslash-f.");
- print_escape_newlines = 0;
-
- DEFVAR_BOOL ("print-quoted", &print_quoted,
- "Non-nil means print quoted forms with reader syntax.\n\
-I.e., (quote foo) prints as 'foo, (function foo) as #'foo, and, backquoted\n\
-forms print in the new syntax.");
- print_quoted = 0;
-
- DEFVAR_BOOL ("print-gensym", &print_gensym,
- "Non-nil means print uninterned symbols so they will read as uninterned.\n\
-I.e., the value of (make-symbol "foobar") prints as #:foobar.");
- print_gensym = 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 (&Serror_message_string);
- defsubr (&Sprinc);
- defsubr (&Sprint);
- defsubr (&Sterpri);
- defsubr (&Swrite_char);
- defsubr (&Sexternal_debugging_output);
-
- Qexternal_debugging_output = intern ("external-debugging-output");
- staticpro (&Qexternal_debugging_output);
-
- Qprint_escape_newlines = intern ("print-escape-newlines");
- staticpro (&Qprint_escape_newlines);
-
- staticpro (&printed_gensyms);
- printed_gensyms = Qnil;
-
-#ifndef standalone
- defsubr (&Swith_output_to_temp_buffer);
-#endif /* not standalone */
-}
diff --git a/src/process.c b/src/process.c
deleted file mode 100644
index 830e559f188..00000000000
--- a/src/process.c
+++ /dev/null
@@ -1,4141 +0,0 @@
-/* Asynchronous subprocess control for GNU Emacs.
- Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 1996
- Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <signal.h>
-
-#include <config.h>
-
-/* This file is split into two parts by the following preprocessor
- conditional. The 'then' clause contains all of the support for
- asynchronous subprocesses. The 'else' clause contains stub
- versions of some of the asynchronous subprocess routines that are
- often called elsewhere in Emacs, so we don't have to #ifdef the
- sections that call them. */
-
-
-#ifdef subprocesses
-
-#include <stdio.h>
-#include <errno.h>
-#include <setjmp.h>
-#include <sys/types.h> /* some typedefs are used in sys/file.h */
-#include <sys/file.h>
-#include <sys/stat.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef WINDOWSNT
-#include <stdlib.h>
-#include <fcntl.h>
-#endif /* not WINDOWSNT */
-
-#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#ifdef NEED_NET_ERRNO_H
-#include <net/errno.h>
-#endif /* NEED_NET_ERRNO_H */
-#endif /* HAVE_SOCKETS */
-
-/* TERM is a poor-man's SLIP, used on Linux. */
-#ifdef TERM
-#include <client.h>
-#endif
-
-/* On some systems, e.g. DGUX, inet_addr returns a 'struct in_addr'. */
-#ifdef HAVE_BROKEN_INET_ADDR
-#define IN_ADDR struct in_addr
-#define NUMERIC_ADDR_ERROR (numeric_addr.s_addr == -1)
-#else
-#define IN_ADDR unsigned long
-#define NUMERIC_ADDR_ERROR (numeric_addr == -1)
-#endif
-
-#if defined(BSD_SYSTEM) || defined(STRIDE)
-#include <sys/ioctl.h>
-#if !defined (O_NDELAY) && defined (HAVE_PTYS) && !defined(USG5)
-#include <fcntl.h>
-#endif /* HAVE_PTYS and no O_NDELAY */
-#endif /* BSD_SYSTEM || STRIDE */
-
-#ifdef BROKEN_O_NONBLOCK
-#undef O_NONBLOCK
-#endif /* BROKEN_O_NONBLOCK */
-
-#ifdef NEED_BSDTTY
-#include <bsdtty.h>
-#endif
-
-#ifdef IRIS
-#include <sys/sysmacros.h> /* for "minor" */
-#endif /* not IRIS */
-
-#include "systime.h"
-#include "systty.h"
-
-#include "lisp.h"
-#include "window.h"
-#include "buffer.h"
-#include "process.h"
-#include "termhooks.h"
-#include "termopts.h"
-#include "commands.h"
-#include "frame.h"
-#include "blockinput.h"
-
-Lisp_Object Qprocessp;
-Lisp_Object Qrun, Qstop, Qsignal, Qopen, Qclosed;
-Lisp_Object Qlast_nonmenu_event;
-/* Qexit is declared and initialized in eval.c. */
-
-/* a process object is a network connection when its childp field is neither
- Qt nor Qnil but is instead a cons cell (HOSTNAME PORTNUM). */
-
-#ifdef HAVE_SOCKETS
-#define NETCONN_P(p) (GC_CONSP (XPROCESS (p)->childp))
-#else
-#define NETCONN_P(p) 0
-#endif /* HAVE_SOCKETS */
-
-/* Define first descriptor number available for subprocesses. */
-#ifdef VMS
-#define FIRST_PROC_DESC 1
-#else /* Not VMS */
-#define FIRST_PROC_DESC 3
-#endif
-
-/* Define SIGCHLD as an alias for SIGCLD. There are many conditionals
- testing SIGCHLD. */
-
-#if !defined (SIGCHLD) && defined (SIGCLD)
-#define SIGCHLD SIGCLD
-#endif /* SIGCLD */
-
-#include "syssignal.h"
-
-#include "syswait.h"
-
-extern int errno;
-extern char *strerror ();
-#ifdef VMS
-extern char *sys_errlist[];
-#endif
-
-#ifndef HAVE_H_ERRNO
-extern int h_errno;
-#endif
-
-#ifndef SYS_SIGLIST_DECLARED
-#ifndef VMS
-#ifndef BSD4_1
-#ifndef WINDOWSNT
-#ifndef LINUX
-extern char *sys_siglist[];
-#endif /* not LINUX */
-#else /* BSD4_1 */
-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 /* not WINDOWSNT */
-#endif
-#endif /* VMS */
-#endif /* ! SYS_SIGLIST_DECLARED */
-
-/* t means use pty, nil means use a pipe,
- maybe other values to come. */
-static Lisp_Object Vprocess_connection_type;
-
-#ifdef SKTPAIR
-#ifndef HAVE_SOCKETS
-#include <sys/socket.h>
-#endif
-#endif /* SKTPAIR */
-
-/* These next two vars are non-static since sysdep.c uses them in the
- emulation of `select'. */
-/* 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;
-
-#include "sysselect.h"
-
-/* If we support a window system, turn on the code to poll periodically
- to detect C-g. It isn't actually used when doing interrupt input. */
-#ifdef HAVE_WINDOW_SYSTEM
-#define POLL_FOR_INPUT
-#endif
-
-/* Mask of bits indicating the descriptors that we wait for input on. */
-
-static SELECT_TYPE input_wait_mask;
-
-/* Mask that excludes keyboard input descriptor (s). */
-
-static SELECT_TYPE non_keyboard_wait_mask;
-
-/* The largest descriptor currently in use for a process object. */
-static int max_process_desc;
-
-/* The largest descriptor currently in use for keyboard input. */
-static int max_keyboard_desc;
-
-/* Nonzero means delete a process right away if it exits. */
-static int delete_exited_processes;
-
-/* 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;
-
-/* 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. */
-
-/* Don't make static; need to access externally. */
-int proc_buffered_char[MAXDESC];
-
-static Lisp_Object get_process ();
-
-extern EMACS_TIME timer_check ();
-extern int timers_run;
-
-/* Maximum number of bytes to send to a pty without an eof. */
-static int pty_max_bytes;
-
-#ifdef HAVE_PTYS
-/* The file name of the pty opened by allocate_pty. */
-
-static char pty_name[24];
-#endif
-
-/* Compute the Lisp form of the process status, p->status, from
- the numeric status that was returned by `wait'. */
-
-Lisp_Object status_convert ();
-
-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 (SYMBOLP (l))
- {
- *symbol = l;
- *code = 0;
- *coredump = 0;
- }
- else
- {
- *symbol = XCONS (l)->car;
- tem = XCONS (l)->cdr;
- *code = XFASTINT (XCONS (tem)->car);
- tem = XCONS (tem)->cdr;
- *coredump = !NILP (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))
- {
- char *signame = 0;
- if (code < NSIG)
- {
-#ifndef VMS
- /* Cast to suppress warning if the table has const char *. */
- signame = (char *) sys_siglist[code];
-#else
- signame = sys_errlist[code];
-#endif
- }
- if (signame == 0)
- signame = "unknown";
- string = build_string (signame);
- 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 = Fnumber_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. */
-
-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
- sprintf (pty_name, "/dev/pty%c%x", c, i);
-#endif /* no PTY_NAME_SPRINTF */
-
-#ifdef PTY_OPEN
- PTY_OPEN;
-#else /* no PTY_OPEN */
-#ifdef IRIS
- /* Unusual IRIS code */
- *ptyv = open ("/dev/ptc", O_RDWR | O_NDELAY, 0);
- if (fd < 0)
- return -1;
- if (fstat (fd, &stb) < 0)
- return -1;
-#else /* not 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
-#endif /* not 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
- sprintf (pty_name, "/dev/tty%c%x", c, i);
-#endif /* no PTY_TTY_NAME_SPRINTF */
-#ifndef UNIPLUS
- if (access (pty_name, 6) != 0)
- {
- close (fd);
-#if !defined(IRIS) && !defined(__sgi)
- 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;
-{
- struct Lisp_Vector *vec;
- register Lisp_Object val, tem, name1;
- register struct Lisp_Process *p;
- char suffix[10];
- register int i;
-
- vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct Lisp_Process));
- for (i = 0; i < VECSIZE (struct Lisp_Process); i++)
- vec->contents[i] = Qnil;
- vec->size = VECSIZE (struct Lisp_Process);
- p = (struct Lisp_Process *)vec;
-
- XSETINT (p->infd, -1);
- XSETINT (p->outfd, -1);
- XSETFASTINT (p->pid, 0);
- XSETFASTINT (p->tick, 0);
- XSETFASTINT (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 (NILP (tem)) break;
- sprintf (suffix, "<%d>", i);
- name1 = concat2 (name, build_string (suffix));
- }
- name = name1;
- p->name = name;
- XSETPROCESS (val, p);
- 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);
-
- deactivate_process (proc);
-}
-
-DEFUN ("processp", Fprocessp, Sprocessp, 1, 1, 0,
- "Return t if OBJECT is a process.")
- (object)
- Lisp_Object object;
-{
- return PROCESSP (object) ? 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 (PROCESSP (name))
- 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.")
- (buffer)
- register Lisp_Object buffer;
-{
- register Lisp_Object buf, tail, proc;
-
- if (NILP (buffer)) return Qnil;
- buf = Fget_buffer (buffer);
- if (NILP (buf)) return Qnil;
-
- for (tail = Vprocess_alist; !NILP (tail); tail = Fcdr (tail))
- {
- proc = Fcdr (Fcar (tail));
- if (PROCESSP (proc) && EQ (XPROCESS (proc)->buffer, buf))
- return proc;
- }
- return Qnil;
-}
-
-/* This is how commands for the user decode process arguments. It
- accepts a process, a process name, a buffer, a buffer name, or nil.
- Buffers denote the first process in the buffer, and nil denotes the
- current buffer. */
-
-static Lisp_Object
-get_process (name)
- register Lisp_Object name;
-{
- register Lisp_Object proc, obj;
- if (STRINGP (name))
- {
- obj = Fget_process (name);
- if (NILP (obj))
- obj = Fget_buffer (name);
- if (NILP (obj))
- error ("Process %s does not exist", XSTRING (name)->data);
- }
- else if (NILP (name))
- obj = Fcurrent_buffer ();
- else
- obj = name;
-
- /* Now obj should be either a buffer object or a process object.
- */
- if (BUFFERP (obj))
- {
- proc = Fget_buffer_process (obj);
- if (NILP (proc))
- error ("Buffer %s has no process", XSTRING (XBUFFER (obj)->name)->data);
- }
- else
- {
- CHECK_PROCESS (obj, 0);
- proc = obj;
- }
- return proc;
-}
-
-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, a buffer, the name of a process or buffer, or\n\
-nil, indicating the current buffer's process.")
- (process)
- register Lisp_Object process;
-{
- process = get_process (process);
- XPROCESS (process)->raw_status_low = Qnil;
- XPROCESS (process)->raw_status_high = Qnil;
- if (NETCONN_P (process))
- {
- XPROCESS (process)->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
- XSETINT (XPROCESS (process)->tick, ++process_tick);
- }
- else if (XINT (XPROCESS (process)->infd) >= 0)
- {
- Fkill_process (process, Qnil);
- /* Do this now, since remove_process will make sigchld_handler do nothing. */
- XPROCESS (process)->status
- = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
- XSETINT (XPROCESS (process)->tick, ++process_tick);
- status_notify ();
- }
- remove_process (process);
- 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.\n\
-PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
-nil, indicating the current buffer's process.")
- (process)
- register Lisp_Object process;
-{
- register struct Lisp_Process *p;
- register Lisp_Object status;
-
- if (STRINGP (process))
- process = Fget_process (process);
- else
- process = get_process (process);
-
- if (NILP (process))
- return process;
-
- p = XPROCESS (process);
- if (!NILP (p->raw_status_low))
- update_status (p);
- status = p->status;
- if (CONSP (status))
- status = XCONS (status)->car;
- if (NETCONN_P (process))
- {
- 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.")
- (process)
- register Lisp_Object process;
-{
- CHECK_PROCESS (process, 0);
- if (!NILP (XPROCESS (process)->raw_status_low))
- update_status (XPROCESS (process));
- if (CONSP (XPROCESS (process)->status))
- return XCONS (XCONS (XPROCESS (process)->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.")
- (process)
- register Lisp_Object process;
-{
- CHECK_PROCESS (process, 0);
- return XPROCESS (process)->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.")
- (process)
- register Lisp_Object process;
-{
- CHECK_PROCESS (process, 0);
- return XPROCESS (process)->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.")
- (process)
- register Lisp_Object process;
-{
- CHECK_PROCESS (process, 0);
- return XPROCESS (process)->command;
-}
-
-DEFUN ("process-tty-name", Fprocess_tty_name, Sprocess_tty_name, 1, 1, 0,
- "Return the name of the terminal PROCESS uses, or nil if none.\n\
-This is the terminal that the process itself reads and writes on,\n\
-not the name of the pty that Emacs uses to talk with that terminal.")
- (process)
- register Lisp_Object process;
-{
- CHECK_PROCESS (process, 0);
- return XPROCESS (process)->tty_name;
-}
-
-DEFUN ("set-process-buffer", Fset_process_buffer, Sset_process_buffer,
- 2, 2, 0,
- "Set buffer associated with PROCESS to BUFFER (a buffer, or nil).")
- (process, buffer)
- register Lisp_Object process, buffer;
-{
- CHECK_PROCESS (process, 0);
- if (!NILP (buffer))
- CHECK_BUFFER (buffer, 1);
- XPROCESS (process)->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.")
- (process)
- register Lisp_Object process;
-{
- CHECK_PROCESS (process, 0);
- return XPROCESS (process)->buffer;
-}
-
-DEFUN ("process-mark", Fprocess_mark, Sprocess_mark,
- 1, 1, 0,
- "Return the marker for the end of the last output from PROCESS.")
- (process)
- register Lisp_Object process;
-{
- CHECK_PROCESS (process, 0);
- return XPROCESS (process)->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\
-t means stop accepting output from the process.\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.")
- (process, filter)
- register Lisp_Object process, filter;
-{
- CHECK_PROCESS (process, 0);
- if (EQ (filter, Qt))
- {
- FD_CLR (XINT (XPROCESS (process)->infd), &input_wait_mask);
- FD_CLR (XINT (XPROCESS (process)->infd), &non_keyboard_wait_mask);
- }
- else if (EQ (XPROCESS (process)->filter, Qt))
- {
- FD_SET (XINT (XPROCESS (process)->infd), &input_wait_mask);
- FD_SET (XINT (XPROCESS (process)->infd), &non_keyboard_wait_mask);
- }
- XPROCESS (process)->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.")
- (process)
- register Lisp_Object process;
-{
- CHECK_PROCESS (process, 0);
- return XPROCESS (process)->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.")
- (process, sentinel)
- register Lisp_Object process, sentinel;
-{
- CHECK_PROCESS (process, 0);
- XPROCESS (process)->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.")
- (process)
- register Lisp_Object process;
-{
- CHECK_PROCESS (process, 0);
- return XPROCESS (process)->sentinel;
-}
-
-DEFUN ("set-process-window-size", Fset_process_window_size,
- Sset_process_window_size, 3, 3, 0,
- "Tell PROCESS that it has logical window size HEIGHT and WIDTH.")
- (process, height, width)
- register Lisp_Object process, height, width;
-{
- CHECK_PROCESS (process, 0);
- CHECK_NATNUM (height, 0);
- CHECK_NATNUM (width, 0);
- if (set_window_size (XINT (XPROCESS (process)->infd),
- XINT (height), XINT(width)) <= 0)
- return Qnil;
- else
- return Qt;
-}
-
-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.")
- (process, value)
- register Lisp_Object process, value;
-{
- Lisp_Object tem;
-
- CHECK_PROCESS (process, 0);
- tem = XPROCESS (process)->kill_without_query;
- XPROCESS (process)->kill_without_query = Fnull (value);
-
- return Fnull (tem);
-}
-
-DEFUN ("process-contact", Fprocess_contact, Sprocess_contact,
- 1, 1, 0,
- "Return the contact info of PROCESS; t for a real child.\n\
-For a net connection, the value is a cons cell of the form (HOST SERVICE).")
- (process)
- register Lisp_Object process;
-{
- CHECK_PROCESS (process, 0);
- return XPROCESS (process)->childp;
-}
-
-#if 0 /* Turned off because we don't currently record this info
- in the process. Perhaps add it. */
-DEFUN ("process-connection", Fprocess_connection, Sprocess_connection, 1, 1, 0,
- "Return the connection type of `PROCESS'.\n\
-The value is `nil' for a pipe,\n\
-`t' or `pty' for a pty, or `stream' for a socket connection.")
- (process)
- Lisp_Object process;
-{
- return XPROCESS (process)->type;
-}
-#endif
-
-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];
-
- XSETFASTINT (minspace, 1);
-
- set_buffer_internal (XBUFFER (Vstandard_output));
- Fbuffer_disable_undo (Vstandard_output);
-
- current_buffer->truncate_lines = Qt;
-
- write_string ("\
-Proc Status Buffer Tty Command\n\
----- ------ ------ --- -------\n", -1);
-
- for (tail = Vprocess_alist; !NILP (tail); tail = Fcdr (tail))
- {
- Lisp_Object symbol;
-
- proc = Fcdr (Fcar (tail));
- p = XPROCESS (proc);
- if (NILP (p->childp))
- continue;
-
- Finsert (1, &p->name);
- Findent_to (make_number (13), minspace);
-
- if (!NILP (p->raw_status_low))
- update_status (p);
- symbol = p->status;
- if (CONSP (p->status))
- symbol = XCONS (p->status)->car;
-
-
- if (EQ (symbol, Qsignal))
- {
- Lisp_Object tem;
- tem = Fcar (Fcdr (p->status));
-#ifdef VMS
- if (XINT (tem) < NSIG)
- write_string (sys_errlist [XINT (tem)], -1);
- else
-#endif
- 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", (int) XFASTINT (tem));
- write_string (tembuf, -1);
- }
- }
-
- if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
- remove_process (proc);
-
- Findent_to (make_number (22), minspace);
- if (NILP (p->buffer))
- insert_string ("(none)");
- else if (NILP (XBUFFER (p->buffer)->name))
- insert_string ("(Killed)");
- else
- Finsert (1, &XBUFFER (p->buffer)->name);
-
- Findent_to (make_number (37), minspace);
-
- if (STRINGP (p->tty_name))
- Finsert (1, &p->tty_name);
- else
- insert_string ("(none)");
-
- Findent_to (make_number (49), minspace);
-
- if (NETCONN_P (proc))
- {
- sprintf (tembuf, "(network stream connection to %s)\n",
- XSTRING (XCONS (p->childp)->car)->data);
- insert_string (tembuf);
- }
- else
- {
- tem = p->command;
- while (1)
- {
- tem1 = Fcar (tem);
- Finsert (1, &tem1);
- tem = Fcdr (tem);
- if (NILP (tem))
- break;
- insert_string (" ");
- }
- insert_string ("\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);
-}
-
-/* Starting asynchronous inferior processes. */
-
-static Lisp_Object start_process_unwind ();
-
-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, current_dir, tem;
-#ifdef VMS
- register unsigned char *new_argv;
- int len;
-#else
- register unsigned char **new_argv;
-#endif
- register int i;
- int count = specpdl_ptr - specpdl;
-
- buffer = args[1];
- if (!NILP (buffer))
- buffer = Fget_buffer_create (buffer);
-
- /* Make sure that the child will be able to chdir to the current
- buffer's current directory, or its unhandled equivalent. We
- can't just have the child check for an error when it does the
- chdir, since it's in a vfork.
-
- We have to GCPRO around this because Fexpand_file_name and
- Funhandled_file_name_directory might call a file name handling
- function. The argument list is protected by the caller, so all
- we really have to worry about is buffer. */
- {
- struct gcpro gcpro1, gcpro2;
-
- current_dir = current_buffer->directory;
-
- GCPRO2 (buffer, current_dir);
-
- current_dir
- = expand_and_dir_to_file (Funhandled_file_name_directory (current_dir),
- Qnil);
- if (NILP (Ffile_accessible_directory_p (current_dir)))
- report_file_error ("Setting current directory",
- Fcons (current_buffer->directory, Qnil));
-
- UNGCPRO;
- }
-
- name = args[0];
- CHECK_STRING (name, 0);
-
- program = args[2];
-
- CHECK_STRING (program, 2);
-
-#ifdef VMS
- /* Make a one member argv with all args concatenated
- together separated by a blank. */
- len = XSTRING (program)->size + 2;
- for (i = 3; i < nargs; i++)
- {
- tem = args[i];
- CHECK_STRING (tem, i);
- len += XSTRING (tem)->size + 1; /* count the blank */
- }
- new_argv = (unsigned char *) alloca (len);
- strcpy (new_argv, XSTRING (program)->data);
- for (i = 3; i < nargs; i++)
- {
- tem = args[i];
- CHECK_STRING (tem, i);
- strcat (new_argv, " ");
- strcat (new_argv, XSTRING (tem)->data);
- }
- /* Need to add code here to check for program existence on VMS */
-
-#else /* not VMS */
- new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
-
- /* If program file name is not absolute, search our path for it */
- if (!IS_DIRECTORY_SEP (XSTRING (program)->data[0])
- && !(XSTRING (program)->size > 1
- && IS_DEVICE_SEP (XSTRING (program)->data[1])))
- {
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- tem = Qnil;
- GCPRO4 (name, program, buffer, current_dir);
- openp (Vexec_path, program, EXEC_SUFFIXES, &tem, 1);
- UNGCPRO;
- if (NILP (tem))
- report_file_error ("Searching for program", Fcons (program, Qnil));
- tem = Fexpand_file_name (tem, Qnil);
- new_argv[0] = XSTRING (tem)->data;
- }
- else
- {
- if (!NILP (Ffile_directory_p (program)))
- error ("Specified program for new process is a directory");
-
- new_argv[0] = XSTRING (program)->data;
- }
-
- 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;
-#endif /* not VMS */
-
- proc = make_process (name);
- /* If an error occurs and we can't start the process, we want to
- remove it from the process list. This means that each error
- check in create_process doesn't need to call remove_process
- itself; it's all taken care of here. */
- record_unwind_protect (start_process_unwind, proc);
-
- 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);
-
- /* Make the process marker point into the process buffer (if any). */
- if (!NILP (buffer))
- Fset_marker (XPROCESS (proc)->mark,
- make_number (BUF_ZV (XBUFFER (buffer))), buffer);
-
- create_process (proc, new_argv, current_dir);
-
- return unbind_to (count, proc);
-}
-
-/* This function is the unwind_protect form for Fstart_process. If
- PROC doesn't have its pid set, then we know someone has signaled
- an error and the process wasn't started successfully, so we should
- remove it from the process list. */
-static Lisp_Object
-start_process_unwind (proc)
- Lisp_Object proc;
-{
- if (!PROCESSP (proc))
- abort ();
-
- /* Was PROC started successfully? */
- if (XINT (XPROCESS (proc)->pid) <= 0)
- remove_process (proc);
-
- return Qnil;
-}
-
-
-SIGTYPE
-create_process_1 (signo)
- int signo;
-{
-#if defined (USG) && !defined (POSIX_SIGNALS)
- /* 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;
-
-SIGTYPE
-create_process_sigchld ()
-{
- signal (SIGCHLD, create_process_sigchld);
-
- sigchld_deferred = 1;
-}
-#endif
-#endif
-#endif
-
-#ifndef VMS /* VMS version of this function is in vmsproc.c. */
-create_process (process, new_argv, current_dir)
- Lisp_Object process;
- char **new_argv;
- Lisp_Object current_dir;
-{
- int pid, inchannel, outchannel;
- int sv[2];
-#ifdef POSIX_SIGNALS
- sigset_t procmask;
- sigset_t blocked;
- struct sigaction sigint_action;
- struct sigaction sigquit_action;
-#ifdef AIX
- struct sigaction sighup_action;
-#endif
-#else /* !POSIX_SIGNALS */
-#ifdef SIGCHLD
- SIGTYPE (*sigchld)();
-#endif
-#endif /* !POSIX_SIGNALS */
- /* Use volatile to protect variables from being clobbered by longjmp. */
- volatile int forkin, forkout;
- volatile int pty_flag = 0;
- extern char **environ;
-
- inchannel = outchannel = -1;
-
-#ifdef HAVE_PTYS
- if (!NILP (Vprocess_connection_type))
- 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 /* not USG */
- 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 */
- {
- pipe (sv);
- inchannel = sv[0];
- forkout = sv[1];
- pipe (sv);
- 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);
- fcntl (outchannel, F_SETFL, O_NONBLOCK);
-#else
-#ifdef O_NDELAY
- fcntl (inchannel, F_SETFL, O_NDELAY);
- fcntl (outchannel, F_SETFL, O_NDELAY);
-#endif
-#endif
-
- /* 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;
- XSETINT (XPROCESS (process)->infd, inchannel);
- XSETINT (XPROCESS (process)->outfd, outchannel);
- /* Record the tty descriptor used in the subprocess. */
- if (forkin < 0)
- XPROCESS (process)->subtty = Qnil;
- else
- XSETFASTINT (XPROCESS (process)->subtty, forkin);
- XPROCESS (process)->pty_flag = (pty_flag ? Qt : Qnil);
- XPROCESS (process)->status = Qrun;
-
- /* Delay interrupts until we have a chance to store
- the new fork's pid in its process structure */
-#ifdef POSIX_SIGNALS
- sigemptyset (&blocked);
-#ifdef SIGCHLD
- sigaddset (&blocked, SIGCHLD);
-#endif
-#ifdef HAVE_VFORK
- /* On many hosts (e.g. Solaris 2.4), if a vforked child calls `signal',
- this sets the parent's signal handlers as well as the child's.
- So delay all interrupts whose handlers the child might munge,
- and record the current handlers so they can be restored later. */
- sigaddset (&blocked, SIGINT ); sigaction (SIGINT , 0, &sigint_action );
- sigaddset (&blocked, SIGQUIT); sigaction (SIGQUIT, 0, &sigquit_action);
-#ifdef AIX
- sigaddset (&blocked, SIGHUP ); sigaction (SIGHUP , 0, &sighup_action );
-#endif
-#endif /* HAVE_VFORK */
- sigprocmask (SIG_BLOCK, &blocked, &procmask);
-#else /* !POSIX_SIGNALS */
-#ifdef SIGCHLD
-#ifdef BSD4_1
- sighold (SIGCHLD);
-#else /* not BSD4_1 */
-#if defined (BSD_SYSTEM) || defined (UNIPLUS) || defined (HPUX)
- sigsetmask (sigmask (SIGCHLD));
-#else /* ordinary USG */
-#if 0
- sigchld_deferred = 0;
- sigchld = signal (SIGCHLD, create_process_sigchld);
-#endif
-#endif /* ordinary USG */
-#endif /* not BSD4_1 */
-#endif /* SIGCHLD */
-#endif /* !POSIX_SIGNALS */
-
- FD_SET (inchannel, &input_wait_mask);
- FD_SET (inchannel, &non_keyboard_wait_mask);
- if (inchannel > max_process_desc)
- max_process_desc = inchannel;
-
- /* Until we store the proper pid, enable sigchld_handler
- to recognize an unknown pid as standing for this process.
- It is very important not to let this `marker' value stay
- in the table after this function has returned; if it does
- it might cause call-process to hang and subsequent asynchronous
- processes to get their return values scrambled. */
- XSETINT (XPROCESS (process)->pid, -1);
-
- BLOCK_INPUT;
-
- {
- /* child_setup must clobber environ on systems with true vfork.
- Protect it from permanent change. */
- char **save_environ = environ;
-
-#ifndef WINDOWSNT
- pid = vfork ();
- if (pid == 0)
-#endif /* not WINDOWSNT */
- {
- 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 sure SIGCHLD is not blocked 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
- /* We tried doing setsid only if pty_flag, but it caused
- process_set_signal to fail on SGI when using a pipe. */
- setsid ();
- /* Make the pty's terminal the controlling terminal. */
- if (pty_flag)
- {
-#ifdef TIOCSCTTY
- /* We ignore the return value
- because faith@cs.unc.edu says that is necessary on Linux. */
- ioctl (xforkin, TIOCSCTTY, 0);
-#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 */
-#if defined (HAVE_TERMIOS) && defined (LDISC1)
- if (pty_flag && xforkin >= 0)
- {
- struct termios t;
- tcgetattr (xforkin, &t);
- t.c_lflag = LDISC1;
- if (tcsetattr (xforkin, TCSANOW, &t) < 0)
- write (1, "create_process/tcsetattr LDISC1 failed\n", 39);
- }
-#else
-#if defined (NTTYDISC) && defined (TIOCSETD)
- if (pty_flag && xforkin >= 0)
- {
- /* Use new line discipline. */
- int ldisc = NTTYDISC;
- ioctl (xforkin, TIOCSETD, &ldisc);
- }
-#endif
-#endif
-#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. */
-#ifdef HAVE_SETPGID
- setpgid (0, 0);
-#else
- setpgrp (0, 0);
-#endif
-#endif
- }
-#endif /* TIOCNOTTY */
-
-#if !defined (RTU) && !defined (UNIPLUS) && !defined (DONT_REOPEN_PTY)
-/*** There is a suggestion that this ought to be a
- conditional on TIOCSPGRP,
- or !(defined (HAVE_SETSID) && defined (TIOCSCTTY)).
- Trying the latter gave the wrong results on Debian GNU/Linux 1.1;
- that system does seem to need this code, even though
- both HAVE_SETSID and TIOCSCTTY are defined. */
- /* 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)
- {
-#ifdef SET_CHILD_PTY_PGRP
- int pgrp = getpid ();
-#endif
-
- /* 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)
- {
- write (1, "Couldn't open the pty terminal ", 31);
- write (1, pty_name, strlen (pty_name));
- write (1, "\n", 1);
- _exit (1);
- }
-
-#ifdef SET_CHILD_PTY_PGRP
- ioctl (xforkin, TIOCSPGRP, &pgrp);
- ioctl (xforkout, TIOCSPGRP, &pgrp);
-#endif
- }
-#endif /* not UNIPLUS and not RTU and not DONT_REOPEN_PTY */
-
-#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 */
-
- signal (SIGINT, SIG_DFL);
- signal (SIGQUIT, SIG_DFL);
-
- /* Stop blocking signals in the child. */
-#ifdef POSIX_SIGNALS
- sigprocmask (SIG_SETMASK, &procmask, 0);
-#else /* !POSIX_SIGNALS */
-#ifdef SIGCHLD
-#ifdef BSD4_1
- sigrelse (SIGCHLD);
-#else /* not BSD4_1 */
-#if defined (BSD_SYSTEM) || defined (UNIPLUS) || defined (HPUX)
- sigsetmask (SIGEMPTYMASK);
-#else /* ordinary USG */
-#if 0
- signal (SIGCHLD, sigchld);
-#endif
-#endif /* ordinary USG */
-#endif /* not BSD4_1 */
-#endif /* SIGCHLD */
-#endif /* !POSIX_SIGNALS */
-
- if (pty_flag)
- child_setup_tty (xforkout);
-#ifdef WINDOWSNT
- pid = child_setup (xforkin, xforkout, xforkout,
- new_argv, 1, current_dir);
-#else /* not WINDOWSNT */
- child_setup (xforkin, xforkout, xforkout,
- new_argv, 1, current_dir);
-#endif /* not WINDOWSNT */
- }
- environ = save_environ;
- }
-
- UNBLOCK_INPUT;
-
- /* This runs in the Emacs process. */
- if (pid < 0)
- {
- if (forkin >= 0)
- close (forkin);
- if (forkin != forkout && forkout >= 0)
- close (forkout);
- }
- else
- {
- /* vfork succeeded. */
- XSETFASTINT (XPROCESS (process)->pid, pid);
-
-#ifdef WINDOWSNT
- register_child (pid, inchannel);
-#endif /* WINDOWSNT */
-
- /* 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);
- XPROCESS (process)->subtty = Qnil;
- if (forkin >= 0)
- close (forkin);
- alarm (0);
- start_polling ();
- if (forkin != forkout && forkout >= 0)
- close (forkout);
-
-#ifdef HAVE_PTYS
- if (pty_flag)
- XPROCESS (process)->tty_name = build_string (pty_name);
- else
-#endif
- XPROCESS (process)->tty_name = Qnil;
- }
-
- /* Restore the signal state whether vfork succeeded or not.
- (We will signal an error, below, if it failed.) */
-#ifdef POSIX_SIGNALS
-#ifdef HAVE_VFORK
- /* Restore the parent's signal handlers. */
- sigaction (SIGINT, &sigint_action, 0);
- sigaction (SIGQUIT, &sigquit_action, 0);
-#ifdef AIX
- sigaction (SIGHUP, &sighup_action, 0);
-#endif
-#endif /* HAVE_VFORK */
- /* Stop blocking signals in the parent. */
- sigprocmask (SIG_SETMASK, &procmask, 0);
-#else /* !POSIX_SIGNALS */
-#ifdef SIGCHLD
-#ifdef BSD4_1
- sigrelse (SIGCHLD);
-#else /* not BSD4_1 */
-#if defined (BSD_SYSTEM) || 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 */
-#endif /* !POSIX_SIGNALS */
-
- /* Now generate the error if vfork failed. */
- if (pid < 0)
- report_file_error ("Doing vfork", Qnil);
-}
-#endif /* not VMS */
-
-#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, or its IP address.\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_ptr, host_info;
- char *(addr_list[2]);
- IN_ADDR numeric_addr;
- int s, outch, inch;
- char errstring[80];
- int port;
- struct hostent host_info_fixed;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
- int retry = 0;
- int count = specpdl_ptr - specpdl;
-
-#ifdef WINDOWSNT
- /* Ensure socket support is loaded if available. */
- init_winsock (TRUE);
-#endif
-
- GCPRO4 (name, buffer, host, service);
- CHECK_STRING (name, 0);
- CHECK_STRING (host, 0);
- if (INTEGERP (service))
- 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;
- }
-
- /* Slow down polling to every ten seconds.
- Some kernels have a bug which causes retrying connect to fail
- after a connect. Polling can interfere with gethostbyname too. */
-#ifdef POLL_FOR_INPUT
- bind_polling_period (10);
-#endif
-
-#ifndef TERM
- while (1)
- {
-#ifdef TRY_AGAIN
- h_errno = 0;
-#endif
- immediate_quit = 1;
- QUIT;
- host_info_ptr = gethostbyname (XSTRING (host)->data);
- immediate_quit = 0;
-#ifdef TRY_AGAIN
- if (! (host_info_ptr == 0 && h_errno == TRY_AGAIN))
-#endif
- break;
- Fsleep_for (make_number (1), Qnil);
- }
- if (host_info_ptr == 0)
- /* Attempt to interpret host as numeric inet address */
- {
- numeric_addr = inet_addr ((char *) XSTRING (host)->data);
- if (NUMERIC_ADDR_ERROR)
- error ("Unknown host \"%s\"", XSTRING (host)->data);
-
- host_info_ptr = &host_info;
- host_info.h_name = 0;
- host_info.h_aliases = 0;
- host_info.h_addrtype = AF_INET;
-#ifdef h_addr
- /* Older machines have only one address slot called h_addr.
- Newer machines have h_addr_list, but #define h_addr to
- be its first element. */
- host_info.h_addr_list = &(addr_list[0]);
-#endif
- host_info.h_addr = (char*)(&numeric_addr);
- addr_list[1] = 0;
- /* numeric_addr isn't null-terminated; it has fixed length. */
- host_info.h_length = sizeof (numeric_addr);
- }
-
- bzero (&address, sizeof address);
- bcopy (host_info_ptr->h_addr, (char *) &address.sin_addr,
- host_info_ptr->h_length);
- address.sin_family = host_info_ptr->h_addrtype;
- address.sin_port = port;
-
- s = socket (host_info_ptr->h_addrtype, 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.
- Note we do not turn off polling, because polling is only used
- when not interrupt_input, and thus not normally used on the systems
- which have this bug. On systems which use polling, there's no way
- to quit if polling is turned off. */
- if (interrupt_input)
- unrequest_sigio ();
-
- loop:
-
- immediate_quit = 1;
- QUIT;
-
- if (connect (s, (struct sockaddr *) &address, sizeof address) == -1
- && errno != EISCONN)
- {
- int xerrno = errno;
-
- immediate_quit = 0;
-
- if (errno == EINTR)
- goto loop;
- if (errno == EADDRINUSE && retry < 20)
- {
- /* A delay here is needed on some FreeBSD systems,
- and it is harmless, since this retrying takes time anyway
- and should be infrequent. */
- Fsleep_for (make_number (1), Qnil);
- retry++;
- goto loop;
- }
-
- close (s);
-
- if (interrupt_input)
- request_sigio ();
-
- errno = xerrno;
- report_file_error ("connection failed",
- Fcons (host, Fcons (name, Qnil)));
- }
-
- immediate_quit = 0;
-
-#ifdef POLL_FOR_INPUT
- unbind_to (count, Qnil);
-#endif
-
- if (interrupt_input)
- request_sigio ();
-
-#else /* TERM */
- s = connect_server (0);
- if (s < 0)
- report_file_error ("error creating socket", Fcons (name, Qnil));
- send_command (s, C_PORT, 0, "%s:%d", XSTRING (host)->data, ntohs (port));
- send_command (s, C_DUMB, 1, 0);
-#endif /* TERM */
-
- inch = s;
- outch = dup (s);
- if (outch < 0)
- report_file_error ("error duplicating socket", Fcons (name, Qnil));
-
- if (!NILP (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 = Fcons (host, Fcons (service, Qnil));
- 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;
- XSETINT (XPROCESS (proc)->infd, inch);
- XSETINT (XPROCESS (proc)->outfd, outch);
- XPROCESS (proc)->status = Qrun;
- FD_SET (inch, &input_wait_mask);
- FD_SET (inch, &non_keyboard_wait_mask);
- if (inch > max_process_desc)
- max_process_desc = inch;
-
- UNGCPRO;
- return proc;
-}
-#endif /* HAVE_SOCKETS */
-
-deactivate_process (proc)
- Lisp_Object proc;
-{
- register int inchannel, outchannel;
- register struct Lisp_Process *p = XPROCESS (proc);
-
- inchannel = XINT (p->infd);
- outchannel = XINT (p->outfd);
-
- if (inchannel >= 0)
- {
- /* Beware SIGCHLD hereabouts. */
- flush_pending_output (inchannel);
-#ifdef VMS
- {
- VMS_PROC_STUFF *get_vms_process_pointer (), *vs;
- sys$dassgn (outchannel);
- vs = get_vms_process_pointer (p->pid);
- if (vs)
- give_back_vms_process_stuff (vs);
- }
-#else
- close (inchannel);
- if (outchannel >= 0 && outchannel != inchannel)
- close (outchannel);
-#endif
-
- XSETINT (p->infd, -1);
- XSETINT (p->outfd, -1);
- chan_process[inchannel] = Qnil;
- FD_CLR (inchannel, &input_wait_mask);
- FD_CLR (inchannel, &non_keyboard_wait_mask);
- if (inchannel == max_process_desc)
- {
- int i;
- /* We just closed the highest-numbered process input descriptor,
- so recompute the highest-numbered one now. */
- max_process_desc = 0;
- for (i = 0; i < MAXDESC; i++)
- if (!NILP (chan_process[i]))
- max_process_desc = i;
- }
- }
-}
-
-/* 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 ()
-{
-#ifndef WINDOWSNT
- int i;
- for (i = 0; i < MAXDESC; i++)
- {
- Lisp_Object process;
- process = chan_process[i];
- if (!NILP (process))
- {
- int in = XINT (XPROCESS (process)->infd);
- int out = XINT (XPROCESS (process)->outfd);
- if (in >= 0)
- close (in);
- if (out >= 0 && in != out)
- close (out);
- }
- }
-#endif
-}
-
-DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output,
- 0, 3, 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.\n\
-Non-nil second arg TIMEOUT and third arg TIMEOUT-MSECS are number of\n\
-seconds and microseconds to wait; return after that much time whether\n\
-or not there is input.\n\
-Return non-nil iff we received any output before the timeout expired.")
- (process, timeout, timeout_msecs)
- register Lisp_Object process, timeout, timeout_msecs;
-{
- int seconds;
- int useconds;
-
- if (! NILP (timeout_msecs))
- {
- CHECK_NUMBER (timeout_msecs, 2);
- useconds = XINT (timeout_msecs);
- if (!INTEGERP (timeout))
- XSETINT (timeout, 0);
-
- {
- int carry = useconds / 1000000;
-
- XSETINT (timeout, XINT (timeout) + carry);
- useconds -= carry * 1000000;
-
- /* I think this clause is necessary because C doesn't
- guarantee a particular rounding direction for negative
- integers. */
- if (useconds < 0)
- {
- XSETINT (timeout, XINT (timeout) - 1);
- useconds += 1000000;
- }
- }
- }
- else
- useconds = 0;
-
- if (! NILP (timeout))
- {
- CHECK_NUMBER (timeout, 1);
- seconds = XINT (timeout);
- if (seconds < 0 || (seconds == 0 && useconds == 0))
- seconds = -1;
- }
- else
- {
- if (NILP (process))
- seconds = -1;
- else
- seconds = 0;
- }
-
- if (NILP (process))
- XSETFASTINT (process, 0);
-
- return
- (wait_reading_process_input (seconds, useconds, process, 0)
- ? Qt : 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.
- This is also used in record_asynch_buffer_change.
- For that purpose, this must be 0
- when not inside wait_reading_process_input. */
-static int waiting_for_user_input_p;
-
-/* This is here so breakpoints can be put on it. */
-static
-wait_reading_process_input_1 ()
-{
-}
-
-/* Read and dispose of subprocess output while waiting for timeout to
- elapse and/or keyboard input to be available.
-
- TIME_LIMIT is:
- timeout in seconds, or
- zero for no limit, or
- -1 means gobble data immediately available but don't wait for any.
-
- MICROSECS is:
- an additional duration to wait, measured in microseconds.
- If this is nonzero and time_limit is 0, then the timeout
- consists of MICROSECS only.
-
- READ_KBD is a lisp value:
- 0 to ignore keyboard input, or
- 1 to return when input is available, or
- -1 meaning caller will actually read the input, so don't throw to
- the quit handler, or
- a cons cell, meaning wait until its car is non-nil
- (and gobble terminal input into the buffer if any arrives), or
- a process object, meaning wait until something arrives from that
- process. The return value is true iff we read some input from
- that process.
-
- DO_DISPLAY != 0 means redisplay should be done to show subprocess
- output that arrives.
-
- If READ_KBD is a pointer to a struct Lisp_Process, then the
- function returns true iff we received input from that process
- before the timeout elapsed.
- Otherwise, return true iff we received input from any process. */
-
-wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
- int time_limit, microsecs;
- Lisp_Object read_kbd;
- int do_display;
-{
- register int channel, nfds, m;
- static SELECT_TYPE Available;
- int xerrno;
- Lisp_Object proc;
- EMACS_TIME timeout, end_time, garbage;
- SELECT_TYPE Atemp;
- int wait_channel = -1;
- struct Lisp_Process *wait_proc = 0;
- int got_some_input = 0;
- Lisp_Object *wait_for_cell = 0;
-
- FD_ZERO (&Available);
-
- /* If read_kbd is a process to watch, set wait_proc and wait_channel
- accordingly. */
- if (PROCESSP (read_kbd))
- {
- wait_proc = XPROCESS (read_kbd);
- wait_channel = XINT (wait_proc->infd);
- XSETFASTINT (read_kbd, 0);
- }
-
- /* If waiting for non-nil in a cell, record where. */
- if (CONSP (read_kbd))
- {
- wait_for_cell = &XCONS (read_kbd)->car;
- XSETFASTINT (read_kbd, 0);
- }
-
- waiting_for_user_input_p = XINT (read_kbd);
-
- /* Since we may need to wait several times,
- compute the absolute time to return at. */
- if (time_limit || microsecs)
- {
- EMACS_GET_TIME (end_time);
- EMACS_SET_SECS_USECS (timeout, time_limit, microsecs);
- EMACS_ADD_TIME (end_time, end_time, timeout);
- }
-#ifdef hpux
- /* AlainF 5-Jul-1996
- HP-UX 10.10 seem to have problems with signals coming in
- Causes "poll: interrupted system call" messages when Emacs is run
- in an X window
- Turn off periodic alarms (in case they are in use) */
- stop_polling ();
-#endif
-
- while (1)
- {
- int timeout_reduced_for_timers = 0;
-
- /* 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 (XINT (read_kbd) >= 0)
- QUIT;
-
- /* Exit now if the cell we're waiting for became non-nil. */
- if (wait_for_cell && ! NILP (*wait_for_cell))
- break;
-
- /* 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. */
-
- EMACS_SET_SECS_USECS (timeout, 0, 0);
- }
- else if (time_limit || microsecs)
- {
- EMACS_GET_TIME (timeout);
- EMACS_SUB_TIME (timeout, end_time, timeout);
- if (EMACS_TIME_NEG_P (timeout))
- break;
- }
- else
- {
- EMACS_SET_SECS_USECS (timeout, 100000, 0);
- }
-
- /* Normally we run timers here.
- But not if wait_for_cell; in those cases,
- the wait is supposed to be short,
- and those callers cannot handle running arbitrary Lisp code here. */
- if (! wait_for_cell)
- {
- EMACS_TIME timer_delay;
- int old_timers_run;
-
- retry:
- old_timers_run = timers_run;
- timer_delay = timer_check (1);
- if (timers_run != old_timers_run && do_display)
- {
- redisplay_preserve_echo_area ();
- /* We must retry, since a timer may have requeued itself
- and that could alter the time_delay. */
- goto retry;
- }
-
- if (! EMACS_TIME_NEG_P (timer_delay) && time_limit != -1)
- {
- EMACS_TIME difference;
- EMACS_SUB_TIME (difference, timer_delay, timeout);
- if (EMACS_TIME_NEG_P (difference))
- {
- timeout = timer_delay;
- timeout_reduced_for_timers = 1;
- }
- }
- /* If time_limit is -1, we are not going to wait at all. */
- else if (time_limit != -1)
- {
- /* This is so a breakpoint can be put here. */
- wait_reading_process_input_1 ();
- }
- }
-
- /* Cause C-g and alarm signals to take immediate action,
- and cause input available signals to zero out timeout.
-
- It is important that we do this before checking for process
- activity. If we get a SIGCHLD after the explicit checks for
- process activity, timeout is the only way we will know. */
- if (XINT (read_kbd) < 0)
- set_waiting_for_input (&timeout);
-
- /* If status of something has changed, and no input is
- available, notify the user of the change right away. After
- this explicit check, we'll let the SIGCHLD handler zap
- timeout to get our attention. */
- if (update_tick != process_tick && do_display)
- {
- Atemp = input_wait_mask;
- EMACS_SET_SECS_USECS (timeout, 0, 0);
- if ((select (MAXDESC, &Atemp, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
- &timeout)
- <= 0))
- {
- /* It's okay for us to do this and then continue with
- the loop, since timeout has already been zeroed out. */
- clear_waiting_for_input ();
- status_notify ();
- }
- }
-
- /* Don't wait for output from a non-running process. */
- if (wait_proc != 0 && !NILP (wait_proc->raw_status_low))
- update_status (wait_proc);
- if (wait_proc != 0
- && ! EQ (wait_proc->status, Qrun))
- {
- clear_waiting_for_input ();
- break;
- }
-
- /* Wait till there is something to do */
-
- if (! XINT (read_kbd) && wait_for_cell == 0)
- Available = non_keyboard_wait_mask;
- else
- Available = input_wait_mask;
-
- /* If frame size has changed or the window is newly mapped,
- redisplay now, before we start to wait. There is a race
- condition here; if a SIGIO arrives between now and the select
- and indicates that a frame is trashed, the select may block
- displaying a trashed screen. */
- if (frame_garbaged && do_display)
- {
- clear_waiting_for_input ();
- redisplay_preserve_echo_area ();
- if (XINT (read_kbd) < 0)
- set_waiting_for_input (&timeout);
- }
-
- if (XINT (read_kbd) && detect_input_pending ())
- {
- nfds = 0;
- FD_ZERO (&Available);
- }
- else
- nfds = select (MAXDESC, &Available, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
- &timeout);
-
- xerrno = errno;
-
- /* Make C-g and alarm signals set flags again */
- clear_waiting_for_input ();
-
- /* If we woke up due to SIGWINCH, actually change size now. */
- do_pending_window_change ();
-
- if (time_limit && nfds == 0 && ! timeout_reduced_for_timers)
- /* We wanted the full specified time, so return now. */
- break;
- if (nfds < 0)
- {
- if (xerrno == EINTR)
- FD_ZERO (&Available);
-#ifdef ultrix
- /* Ultrix select seems to return ENOMEM when it is
- interrupted. Treat it just like EINTR. Bleah. Note
- that we want to test for the "ultrix" CPP symbol, not
- "__ultrix__"; the latter is only defined under GCC, but
- not by DEC's bundled CC. -JimB */
- else if (xerrno == ENOMEM)
- FD_ZERO (&Available);
-#endif
-#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 doesn't handle PTY closure the same way BSD does. On AIX,
- the child's closure of the pts gives the parent a SIGHUP, and
- the ptc file descriptor is automatically closed,
- yielding EBADF here or at select() call above.
- So, SIGHUP is ignored (see def of PTY_TTY_NAME_SPRINTF
- in m/ibmrt-aix.h), and here we just ignore the select error.
- Cleanup occurs c/o status_notify after SIGCLD. */
- FD_ZERO (&Available); /* Cannot depend on values returned */
-#else
- abort ();
-#endif
- }
- else
- error ("select error: %s", strerror (xerrno));
- }
-#if defined(sun) && !defined(USG5_4)
- else if (nfds > 0 && keyboard_bit_set (&Available)
- && interrupt_input)
- /* System sometimes fails to deliver SIGIO.
-
- David J. Mackenzie says that Emacs doesn't compile under
- Solaris if this code is enabled, thus the USG5_4 in the CPP
- conditional. "I haven't noticed any ill effects so far.
- If you find a Solaris expert somewhere, they might know
- better." */
- kill (getpid (), SIGIO);
-#endif
-
- /* Check for keyboard input */
- /* If there is any, return immediately
- to give it higher priority than subprocesses */
-
- if ((XINT (read_kbd) != 0)
- && detect_input_pending_run_timers (do_display))
- {
- swallow_events (do_display);
- if (detect_input_pending_run_timers (do_display))
- break;
- }
-
- /* If wait_for_cell. check for keyboard input
- but don't run any timers.
- ??? (It seems wrong to me to check for keyboard
- input at all when wait_for_cell, but the code
- has been this way since July 1994.
- Try changing this after version 19.31.) */
- if (wait_for_cell
- && detect_input_pending ())
- {
- swallow_events (do_display);
- if (detect_input_pending ())
- break;
- }
-
- /* Exit now if the cell we're waiting for became non-nil. */
- if (wait_for_cell && ! NILP (*wait_for_cell))
- break;
-
-#ifdef SIGIO
- /* If we think we have keyboard input waiting, but didn't get SIGIO
- go read it. This can happen with X on BSD after logging out.
- In that case, there really is no input and no SIGIO,
- but select says there is input. */
-
- if (XINT (read_kbd) && interrupt_input
- && (keyboard_bit_set (&Available)))
- kill (getpid (), SIGIO);
-#endif
-
- if (! wait_proc)
- got_some_input |= nfds > 0;
-
- /* If checking input just got us a size-change event from X,
- obey it now if we should. */
- if (XINT (read_kbd) || wait_for_cell)
- do_pending_window_change ();
-
- /* Check for data from a process. */
- /* Really FIRST_PROC_DESC should be 0 on Unix,
- but this is safer in the short run. */
- for (channel = 0; channel <= max_process_desc; channel++)
- {
- if (FD_ISSET (channel, &Available)
- && FD_ISSET (channel, &non_keyboard_wait_mask))
- {
- int nread;
-
- /* 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 = -1;
- time_limit = -1;
- got_some_input = 1;
- }
- proc = chan_process[channel];
- if (NILP (proc))
- continue;
-
- /* 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)
- ;
-#endif
- /* ISC 4.1 defines both EWOULDBLOCK and O_NONBLOCK,
- and Emacs uses O_NONBLOCK, so what we get is EAGAIN. */
-#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 */
-#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)
- ;
-#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 (!NILP (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 each file descriptor */
- } /* end while exit conditions not met */
-
- waiting_for_user_input_p = 0;
-
- /* 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 (XINT (read_kbd) >= 0)
- {
- /* Prevent input_pending from remaining set if we quit. */
- clear_input_pending ();
- QUIT;
- }
-#ifdef hpux
- /* AlainF 5-Jul-1996
- HP-UX 10.10 seems to have problems with signals coming in
- Causes "poll: interrupted system call" messages when Emacs is run
- in an X window
- Turn periodic alarms back on */
- start_polling();
-#endif
-
- return got_some_input;
-}
-
-/* Given a list (FUNCTION ARGS...), apply FUNCTION to the ARGS. */
-
-static Lisp_Object
-read_process_output_call (fun_and_args)
- Lisp_Object fun_and_args;
-{
- return apply1 (XCONS (fun_and_args)->car, XCONS (fun_and_args)->cdr);
-}
-
-static Lisp_Object
-read_process_output_error_handler (error)
- Lisp_Object error;
-{
- cmd_error_internal (error, "error in process filter: ");
- Vinhibit_quit = Qt;
- update_echo_area ();
- Fsleep_for (make_number (2), Qnil);
-}
-
-/* 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;
-#ifdef VMS
- char *chars;
-#else
- char chars[1024];
-#endif
- register Lisp_Object outstream;
- register struct buffer *old = current_buffer;
- register struct Lisp_Process *p = XPROCESS (proc);
- register int opoint;
-
-#ifdef VMS
- VMS_PROC_STUFF *vs, *get_vms_process_pointer();
-
- vs = get_vms_process_pointer (p->pid);
- if (vs)
- {
- if (!vs->iosb[0])
- return(0); /* Really weird if it does this */
- if (!(vs->iosb[0] & 1))
- return -1; /* I/O error */
- }
- else
- error ("Could not get VMS process pointer");
- chars = vs->inputBuffer;
- nchars = clean_vms_buffer (chars, vs->iosb[1]);
- if (nchars <= 0)
- {
- start_vms_process_read (vs); /* Crank up the next read on the process */
- return 1; /* Nothing worth printing, say we got 1 */
- }
-#else /* not VMS */
-
- 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;
- }
-#endif /* not VMS */
-
- if (nchars <= 0) return nchars;
-
- outstream = p->filter;
- if (!NILP (outstream))
- {
- /* We inhibit quit here instead of just catching it so that
- hitting ^G when a filter happens to be running won't screw
- it up. */
- int count = specpdl_ptr - specpdl;
- Lisp_Object odeactivate;
- Lisp_Object obuffer, okeymap;
- int outer_running_asynch_code = running_asynch_code;
-
- /* No need to gcpro these, because all we do with them later
- is test them for EQness, and none of them should be a string. */
- odeactivate = Vdeactivate_mark;
- XSETBUFFER (obuffer, current_buffer);
- okeymap = current_buffer->keymap;
-
- specbind (Qinhibit_quit, Qt);
- specbind (Qlast_nonmenu_event, Qt);
-
- /* In case we get recursively called,
- and we already saved the match data nonrecursively,
- save the same match data in safely recursive fashion. */
- if (outer_running_asynch_code)
- {
- Lisp_Object tem;
- /* Don't clobber the CURRENT match data, either! */
- tem = Fmatch_data (Qnil, Qnil);
- restore_match_data ();
- record_unwind_protect (Fstore_match_data, Fmatch_data (Qnil, Qnil));
- Fstore_match_data (tem);
- }
-
- /* For speed, if a search happens within this code,
- save the match data in a special nonrecursive fashion. */
- running_asynch_code = 1;
-
- /* Read and dispose of the process output. */
- internal_condition_case_1 (read_process_output_call,
- Fcons (outstream,
- Fcons (proc,
- Fcons (make_string (chars,
- nchars),
- Qnil))),
- !NILP (Vdebug_on_error) ? Qnil : Qerror,
- read_process_output_error_handler);
-
- /* If we saved the match data nonrecursively, restore it now. */
- restore_match_data ();
- running_asynch_code = outer_running_asynch_code;
-
- /* Handling the process output should not deactivate the mark. */
- Vdeactivate_mark = odeactivate;
-
-#if 0 /* Call record_asynch_buffer_change unconditionally,
- because we might have changed minor modes or other things
- that affect key bindings. */
- if (! EQ (Fcurrent_buffer (), obuffer)
- || ! EQ (current_buffer->keymap, okeymap))
-#endif
- /* But do it only if the caller is actually going to read events.
- Otherwise there's no need to make him wake up, and it could
- cause trouble (for example it would make Fsit_for return). */
- if (waiting_for_user_input_p == -1)
- record_asynch_buffer_change ();
-
-#ifdef VMS
- start_vms_process_read (vs);
-#endif
- unbind_to (count, Qnil);
- return nchars;
- }
-
- /* If no filter, write into buffer if it isn't dead. */
- if (!NILP (p->buffer) && !NILP (XBUFFER (p->buffer)->name))
- {
- Lisp_Object old_read_only;
- Lisp_Object old_begv, old_zv;
- Lisp_Object odeactivate;
-
- odeactivate = Vdeactivate_mark;
-
- Fset_buffer (p->buffer);
- opoint = PT;
- old_read_only = current_buffer->read_only;
- XSETFASTINT (old_begv, BEGV);
- XSETFASTINT (old_zv, ZV);
-
- current_buffer->read_only = Qnil;
-
- /* 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 (clip_to_bounds (BEGV, marker_position (p->mark), ZV));
- else
- SET_PT (ZV);
-
- /* If the output marker is outside of the visible region, save
- the restriction and widen. */
- if (! (BEGV <= PT && PT <= ZV))
- Fwiden ();
-
- /* Make sure opoint floats ahead of any new text, just as point
- would. */
- if (PT <= opoint)
- opoint += nchars;
-
- /* Insert after old_begv, but before old_zv. */
- if (PT < XFASTINT (old_begv))
- XSETFASTINT (old_begv, XFASTINT (old_begv) + nchars);
- if (PT <= XFASTINT (old_zv))
- XSETFASTINT (old_zv, XFASTINT (old_zv) + nchars);
-
- /* Insert before markers in case we are inserting where
- the buffer's mark is, and the user's next command is Meta-y. */
- insert_before_markers (chars, nchars);
- Fset_marker (p->mark, make_number (PT), p->buffer);
-
- update_mode_lines++;
-
- /* If the restriction isn't what it should be, set it. */
- if (XFASTINT (old_begv) != BEGV || XFASTINT (old_zv) != ZV)
- Fnarrow_to_region (old_begv, old_zv);
-
- /* Handling the process output should not deactivate the mark. */
- Vdeactivate_mark = odeactivate;
-
- current_buffer->read_only = old_read_only;
- SET_PT (opoint);
- set_buffer_internal (old);
- }
-#ifdef VMS
- start_vms_process_read (vs);
-#endif
- 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;
-
-SIGTYPE
-send_process_trap ()
-{
-#ifdef BSD4_1
- sigrelse (SIGPIPE);
- sigrelse (SIGALRM);
-#endif /* BSD4_1 */
- longjmp (send_process_frame, 1);
-}
-
-/* Send some data to process PROC.
- BUF is the beginning of the data; LEN is the number of characters.
- OBJECT is the Lisp object that the data comes from. */
-
-send_process (proc, buf, len, object)
- volatile Lisp_Object proc;
- char *buf;
- int len;
- Lisp_Object object;
-{
- /* Use volatile to protect variables from being clobbered by longjmp. */
- int rv;
- volatile unsigned char *procname = XSTRING (XPROCESS (proc)->name)->data;
- struct gcpro gcpro1;
-
- GCPRO1 (object);
-
-#ifdef VMS
- struct Lisp_Process *p = XPROCESS (proc);
- VMS_PROC_STUFF *vs, *get_vms_process_pointer();
-#endif /* VMS */
-
- if (! NILP (XPROCESS (proc)->raw_status_low))
- update_status (XPROCESS (proc));
- if (! EQ (XPROCESS (proc)->status, Qrun))
- error ("Process %s not running", procname);
-
-#ifdef VMS
- vs = get_vms_process_pointer (p->pid);
- if (vs == 0)
- error ("Could not find this process: %x", p->pid);
- else if (write_to_vms_process (vs, buf, len))
- ;
-#else
-
- if (pty_max_bytes == 0)
- {
-#if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON)
- pty_max_bytes = fpathconf (XFASTINT (XPROCESS (proc)->outfd),
- _PC_MAX_CANON);
- if (pty_max_bytes < 0)
- pty_max_bytes = 250;
-#else
- pty_max_bytes = 250;
-#endif
- /* Deduct one, to leave space for the eof. */
- pty_max_bytes--;
- }
-
- if (!setjmp (send_process_frame))
- while (len > 0)
- {
- int this = len;
- SIGTYPE (*old_sigpipe)();
- int flush_pty = 0;
-
- /* Decide how much data we can send in one batch.
- Long lines need to be split into multiple batches. */
- if (!NILP (XPROCESS (proc)->pty_flag))
- {
- /* Starting this at zero is always correct when not the first iteration
- because the previous iteration ended by sending C-d.
- It may not be correct for the first iteration
- if a partial line was sent in a separate send_process call.
- If that proves worth handling, we need to save linepos
- in the process object. */
- int linepos = 0;
- char *ptr = buf;
- char *end = buf + len;
-
- /* Scan through this text for a line that is too long. */
- while (ptr != end && linepos < pty_max_bytes)
- {
- if (*ptr == '\n')
- linepos = 0;
- else
- linepos++;
- ptr++;
- }
- /* If we found one, break the line there
- and put in a C-d to force the buffer through. */
- this = ptr - buf;
- }
-
- /* Send this batch, using one or more write calls. */
- while (this > 0)
- {
- old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
- rv = write (XINT (XPROCESS (proc)->outfd), buf, this);
- signal (SIGPIPE, old_sigpipe);
-
- if (rv < 0)
- {
- if (0
-#ifdef EWOULDBLOCK
- || errno == EWOULDBLOCK
-#endif
-#ifdef EAGAIN
- || errno == EAGAIN
-#endif
- )
- /* Buffer is full. Wait, accepting input;
- that may allow the program
- to finish doing output and read more. */
- {
- Lisp_Object zero;
- int offset;
-
- /* Running filters might relocate buffers or strings.
- Arrange to relocate BUF. */
- if (BUFFERP (object))
- offset = BUF_PTR_CHAR_POS (XBUFFER (object),
- (unsigned char *) buf);
- else if (STRINGP (object))
- offset = buf - (char *) XSTRING (object)->data;
-
- XSETFASTINT (zero, 0);
-#ifdef EMACS_HAS_USECS
- wait_reading_process_input (0, 20000, zero, 0);
-#else
- wait_reading_process_input (1, 0, zero, 0);
-#endif
-
- if (BUFFERP (object))
- buf = (char *) BUF_CHAR_ADDRESS (XBUFFER (object), offset);
- else if (STRINGP (object))
- buf = offset + (char *) XSTRING (object)->data;
-
- rv = 0;
- }
- else
- /* This is a real error. */
- report_file_error ("writing to process", Fcons (proc, Qnil));
- }
- buf += rv;
- len -= rv;
- this -= rv;
- }
-
- /* If we sent just part of the string, put in an EOF
- to force it through, before we send the rest. */
- if (len > 0)
- Fprocess_send_eof (proc);
- }
-#endif
- 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);
-#ifdef VMS
- error ("Error writing to process %s; closed it", procname);
-#else
- error ("SIGPIPE raised on process %s; closed it", procname);
-#endif
- }
-
- UNGCPRO;
-}
-
-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, a buffer, the name of a process or buffer, or\n\
-nil, indicating the current buffer's process.\n\
-Called from program, takes three arguments, PROCESS, START and END.\n\
-If the region is more than 500 characters long,\n\
-it is sent in several bunches. This may happen even for shorter regions.\n\
-Output from processes can arrive in between bunches.")
- (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),
- Fcurrent_buffer ());
-
- 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, a buffer, the name of a process or buffer, or\n\
-nil, indicating the current buffer's process.\n\
-If STRING is more than 500 characters long,\n\
-it is sent in several bunches. This may happen even for shorter strings.\n\
-Output from processes can arrive in between bunches.")
- (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, string);
- 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.
-
- If we can, we try to signal PROCESS by sending control characters
- down the pty. This allows us to signal inferiors who have changed
- their uid, for which killpg would return an EPERM error. */
-
-static void
-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 (XINT (p->infd) < 0)
- error ("Process %s is not active",
- XSTRING (p->name)->data);
-
- if (NILP (p->pty_flag))
- current_group = Qnil;
-
- /* If we are using pgrps, get a pgrp number and make it negative. */
- if (!NILP (current_group))
- {
-#ifdef SIGNALS_VIA_CHARACTERS
- /* If possible, send signals to the entire pgrp
- by sending an input character to it. */
-
- /* TERMIOS is the latest and bestest, and seems most likely to
- work. If the system has it, use it. */
-#ifdef HAVE_TERMIOS
- struct termios t;
-
- switch (signo)
- {
- case SIGINT:
- tcgetattr (XINT (p->infd), &t);
- send_process (proc, &t.c_cc[VINTR], 1, Qnil);
- return;
-
- case SIGQUIT:
- tcgetattr (XINT (p->infd), &t);
- send_process (proc, &t.c_cc[VQUIT], 1, Qnil);
- return;
-
- case SIGTSTP:
- tcgetattr (XINT (p->infd), &t);
-#if defined (VSWTCH) && !defined (PREFER_VSUSP)
- send_process (proc, &t.c_cc[VSWTCH], 1, Qnil);
-#else
- send_process (proc, &t.c_cc[VSUSP], 1, Qnil);
-#endif
- return;
- }
-
-#else /* ! HAVE_TERMIOS */
-
- /* On Berkeley descendants, the following IOCTL's retrieve the
- current control characters. */
-#if defined (TIOCGLTC) && defined (TIOCGETC)
-
- struct tchars c;
- struct ltchars lc;
-
- switch (signo)
- {
- case SIGINT:
- ioctl (XINT (p->infd), TIOCGETC, &c);
- send_process (proc, &c.t_intrc, 1, Qnil);
- return;
- case SIGQUIT:
- ioctl (XINT (p->infd), TIOCGETC, &c);
- send_process (proc, &c.t_quitc, 1, Qnil);
- return;
-#ifdef SIGTSTP
- case SIGTSTP:
- ioctl (XINT (p->infd), TIOCGLTC, &lc);
- send_process (proc, &lc.t_suspc, 1, Qnil);
- return;
-#endif /* ! defined (SIGTSTP) */
- }
-
-#else /* ! defined (TIOCGLTC) && defined (TIOCGETC) */
-
- /* On SYSV descendants, the TCGETA ioctl retrieves the current control
- characters. */
-#ifdef TCGETA
- struct termio t;
- switch (signo)
- {
- case SIGINT:
- ioctl (XINT (p->infd), TCGETA, &t);
- send_process (proc, &t.c_cc[VINTR], 1, Qnil);
- return;
- case SIGQUIT:
- ioctl (XINT (p->infd), TCGETA, &t);
- send_process (proc, &t.c_cc[VQUIT], 1, Qnil);
- return;
-#ifdef SIGTSTP
- case SIGTSTP:
- ioctl (XINT (p->infd), TCGETA, &t);
- send_process (proc, &t.c_cc[VSWTCH], 1, Qnil);
- return;
-#endif /* ! defined (SIGTSTP) */
- }
-#else /* ! defined (TCGETA) */
- Your configuration files are messed up.
- /* If your system configuration files define SIGNALS_VIA_CHARACTERS,
- you'd better be using one of the alternatives above! */
-#endif /* ! defined (TCGETA) */
-#endif /* ! defined (TIOCGLTC) && defined (TIOCGETC) */
-#endif /* ! defined HAVE_TERMIOS */
-#endif /* ! defined (SIGNALS_VIA_CHARACTERS) */
-
-#ifdef TIOCGPGRP
- /* Get the pgrp using the tty itself, if we have that.
- Otherwise, use the pty to get the pgrp.
- On pfa systems, saka@pfu.fujitsu.co.JP writes:
- "TIOCGPGRP symbol defined in sys/ioctl.h at E50.
- But, TIOCGPGRP does not work on E50 ;-P works fine on E60"
- His patch indicates that if TIOCGPGRP returns an error, then
- we should just assume that p->pid is also the process group id. */
- {
- int err;
-
- if (!NILP (p->subtty))
- err = ioctl (XFASTINT (p->subtty), TIOCGPGRP, &gid);
- else
- err = ioctl (XINT (p->infd), TIOCGPGRP, &gid);
-
-#ifdef pfa
- if (err == -1)
- gid = - XFASTINT (p->pid);
-#endif /* ! defined (pfa) */
- }
- if (gid == -1)
- no_pgrp = 1;
- else
- gid = - gid;
-#else /* ! defined (TIOCGPGRP ) */
- /* Can't select pgrps on this system, so we know that
- the child itself heads the pgrp. */
- gid = - XFASTINT (p->pid);
-#endif /* ! defined (TIOCGPGRP ) */
- }
- else
- gid = - XFASTINT (p->pid);
-
- 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 /* ! defined (SIGCONT) */
- case SIGINT:
-#ifdef VMS
- send_process (proc, "\003", 1, Qnil); /* ^C */
- goto whoosh;
-#endif
- case SIGQUIT:
-#ifdef VMS
- send_process (proc, "\031", 1, Qnil); /* ^Y */
- goto whoosh;
-#endif
- case SIGKILL:
-#ifdef VMS
- sys$forcex (&(XFASTINT (p->pid)), 0, 1);
- whoosh:
-#endif
- flush_pending_output (XINT (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 (!NILP (current_group))
- ioctl (XINT (p->infd), TIOCSIGSEND, signo);
- else
- {
- gid = - XFASTINT (p->pid);
- kill (gid, signo);
- }
-#else /* ! defined (TIOCSIGSEND) */
- EMACS_KILLPG (-gid, signo);
-#endif /* ! defined (TIOCSIGSEND) */
-}
-
-DEFUN ("interrupt-process", Finterrupt_process, Sinterrupt_process, 0, 2, 0,
- "Interrupt process PROCESS. May be process or name of one.\n\
-PROCESS may be a process, a buffer, or the name of a process or buffer.\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 ("signal-process", Fsignal_process, Ssignal_process,
- 2, 2, "nProcess number: \nnSignal code: ",
- "Send the process with process id PID the signal with code SIGCODE.\n\
-PID must be an integer. The process need not be a child of this Emacs.\n\
-SIGCODE may be an integer, or a symbol whose name is a signal name.")
- (pid, sigcode)
- Lisp_Object pid, sigcode;
-{
- CHECK_NUMBER (pid, 0);
-
-#define handle_signal(NAME, VALUE) \
- else if (!strcmp (name, NAME)) \
- XSETINT (sigcode, VALUE)
-
- if (INTEGERP (sigcode))
- ;
- else
- {
- unsigned char *name;
-
- CHECK_SYMBOL (sigcode, 1);
- name = XSYMBOL (sigcode)->name->data;
-
- if (0)
- ;
-#ifdef SIGHUP
- handle_signal ("SIGHUP", SIGHUP);
-#endif
-#ifdef SIGINT
- handle_signal ("SIGINT", SIGINT);
-#endif
-#ifdef SIGQUIT
- handle_signal ("SIGQUIT", SIGQUIT);
-#endif
-#ifdef SIGILL
- handle_signal ("SIGILL", SIGILL);
-#endif
-#ifdef SIGABRT
- handle_signal ("SIGABRT", SIGABRT);
-#endif
-#ifdef SIGEMT
- handle_signal ("SIGEMT", SIGEMT);
-#endif
-#ifdef SIGKILL
- handle_signal ("SIGKILL", SIGKILL);
-#endif
-#ifdef SIGFPE
- handle_signal ("SIGFPE", SIGFPE);
-#endif
-#ifdef SIGBUS
- handle_signal ("SIGBUS", SIGBUS);
-#endif
-#ifdef SIGSEGV
- handle_signal ("SIGSEGV", SIGSEGV);
-#endif
-#ifdef SIGSYS
- handle_signal ("SIGSYS", SIGSYS);
-#endif
-#ifdef SIGPIPE
- handle_signal ("SIGPIPE", SIGPIPE);
-#endif
-#ifdef SIGALRM
- handle_signal ("SIGALRM", SIGALRM);
-#endif
-#ifdef SIGTERM
- handle_signal ("SIGTERM", SIGTERM);
-#endif
-#ifdef SIGURG
- handle_signal ("SIGURG", SIGURG);
-#endif
-#ifdef SIGSTOP
- handle_signal ("SIGSTOP", SIGSTOP);
-#endif
-#ifdef SIGTSTP
- handle_signal ("SIGTSTP", SIGTSTP);
-#endif
-#ifdef SIGCONT
- handle_signal ("SIGCONT", SIGCONT);
-#endif
-#ifdef SIGCHLD
- handle_signal ("SIGCHLD", SIGCHLD);
-#endif
-#ifdef SIGTTIN
- handle_signal ("SIGTTIN", SIGTTIN);
-#endif
-#ifdef SIGTTOU
- handle_signal ("SIGTTOU", SIGTTOU);
-#endif
-#ifdef SIGIO
- handle_signal ("SIGIO", SIGIO);
-#endif
-#ifdef SIGXCPU
- handle_signal ("SIGXCPU", SIGXCPU);
-#endif
-#ifdef SIGXFSZ
- handle_signal ("SIGXFSZ", SIGXFSZ);
-#endif
-#ifdef SIGVTALRM
- handle_signal ("SIGVTALRM", SIGVTALRM);
-#endif
-#ifdef SIGPROF
- handle_signal ("SIGPROF", SIGPROF);
-#endif
-#ifdef SIGWINCH
- handle_signal ("SIGWINCH", SIGWINCH);
-#endif
-#ifdef SIGINFO
- handle_signal ("SIGINFO", SIGINFO);
-#endif
-#ifdef SIGUSR1
- handle_signal ("SIGUSR1", SIGUSR1);
-#endif
-#ifdef SIGUSR2
- handle_signal ("SIGUSR2", SIGUSR2);
-#endif
- else
- error ("Undefined signal name %s", name);
- }
-
-#undef handle_signal
-
- return make_number (kill (XINT (pid), XINT (sigcode)));
-}
-
-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\
-PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
-nil, indicating the current buffer's process.\n\
-If PROCESS is a network connection, or is a process communicating\n\
-through a pipe (as opposed to a pty), then you cannot send any more\n\
-text to PROCESS after you call this function.")
- (process)
- Lisp_Object process;
-{
- Lisp_Object proc;
-
- proc = get_process (process);
-
- /* Make sure the process is really alive. */
- if (! NILP (XPROCESS (proc)->raw_status_low))
- update_status (XPROCESS (proc));
- if (! EQ (XPROCESS (proc)->status, Qrun))
- error ("Process %s not running", XSTRING (XPROCESS (proc)->name)->data);
-
-#ifdef VMS
- send_process (proc, "\032", 1, Qnil); /* ^z */
-#else
- if (!NILP (XPROCESS (proc)->pty_flag))
- send_process (proc, "\004", 1, Qnil);
- else
- {
- close (XINT (XPROCESS (proc)->outfd));
- XSETINT (XPROCESS (proc)->outfd, open (NULL_DEVICE, O_WRONLY));
- }
-#endif /* VMS */
- 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; GC_CONSP (tail); tail = XCONS (tail)->cdr)
- {
- proc = XCONS (XCONS (tail)->car)->cdr;
- if (GC_PROCESSP (proc)
- && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer)))
- {
- if (NETCONN_P (proc))
- Fdelete_process (proc);
- else if (XINT (XPROCESS (proc)->infd) >= 0)
- 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. */
-
-SIGTYPE
-sigchld_handler (signo)
- int signo;
-{
- int old_errno = errno;
- Lisp_Object proc;
- register struct Lisp_Process *p;
- extern EMACS_TIME *input_available_clear_time;
-
-#ifdef BSD4_1
- 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 */
-#if defined (USG) && !defined (POSIX_SIGNALS)
- 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 */
-
- /* Find the process that signaled us, and record its status. */
-
- p = 0;
- for (tail = Vprocess_alist; CONSP (tail); 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;
- }
-
- /* Look for an asynchronous process whose pid hasn't been filled
- in yet. */
- if (p == 0)
- for (tail = Vprocess_alist; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- proc = XCONS (XCONS (tail)->car)->cdr;
- p = XPROCESS (proc);
- if (INTEGERP (p->pid) && 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;
- int clear_desc_flag = 0;
-
- XSETINT (p->tick, ++process_tick);
- u.wt = w;
- XSETINT (p->raw_status_low, u.i & 0xffff);
- XSETINT (p->raw_status_high, u.i >> 16);
-
- /* If process has terminated, stop waiting for its output. */
- if ((WIFSIGNALED (w) || WIFEXITED (w))
- && XINT (p->infd) >= 0)
- clear_desc_flag = 1;
-
- /* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */
- if (clear_desc_flag)
- {
- FD_CLR (XINT (p->infd), &input_wait_mask);
- FD_CLR (XINT (p->infd), &non_keyboard_wait_mask);
- }
-
- /* Tell wait_reading_process_input that it needs to wake up and
- look around. */
- if (input_available_clear_time)
- EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
- }
-
- /* There was no asynchronous process found for that id. Check
- if we have a synchronous process. */
- else
- {
- synch_process_alive = 0;
-
- /* Report the status of the synchronous process. */
- if (WIFEXITED (w))
- synch_process_retcode = WRETCODE (w);
- else if (WIFSIGNALED (w))
- {
- int code = WTERMSIG (w);
- char *signame = 0;
-
- if (code < NSIG)
- {
-#ifndef VMS
- /* Suppress warning if the table has const char *. */
- signame = (char *) sys_siglist[code];
-#else
- signame = sys_errlist[code];
-#endif
- }
- if (signame == 0)
- signame = "unknown";
-
- synch_process_death = signame;
- }
-
- /* Tell wait_reading_process_input that it needs to wake up and
- look around. */
- if (input_available_clear_time)
- EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
- }
-
- /* 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)) || defined (WINDOWSNT)
-#if defined (USG) && ! defined (POSIX_SIGNALS)
- signal (signo, sigchld_handler);
-#endif
- errno = old_errno;
- return;
-#endif /* USG, but not HPUX with WNOHANG */
- }
-}
-
-
-static Lisp_Object
-exec_sentinel_unwind (data)
- Lisp_Object data;
-{
- XPROCESS (XCONS (data)->car)->sentinel = XCONS (data)->cdr;
- return Qnil;
-}
-
-static Lisp_Object
-exec_sentinel_error_handler (error)
- Lisp_Object error;
-{
- cmd_error_internal (error, "error in process sentinel: ");
- Vinhibit_quit = Qt;
- update_echo_area ();
- Fsleep_for (make_number (2), Qnil);
-}
-
-static void
-exec_sentinel (proc, reason)
- Lisp_Object proc, reason;
-{
- Lisp_Object sentinel, obuffer, odeactivate, okeymap;
- register struct Lisp_Process *p = XPROCESS (proc);
- int count = specpdl_ptr - specpdl;
- int outer_running_asynch_code = running_asynch_code;
-
- /* No need to gcpro these, because all we do with them later
- is test them for EQness, and none of them should be a string. */
- odeactivate = Vdeactivate_mark;
- XSETBUFFER (obuffer, current_buffer);
- okeymap = current_buffer->keymap;
-
- sentinel = p->sentinel;
- if (NILP (sentinel))
- return;
-
- /* Zilch the sentinel while it's running, to avoid recursive invocations;
- assure that it gets restored no matter how the sentinel exits. */
- p->sentinel = Qnil;
- record_unwind_protect (exec_sentinel_unwind, Fcons (proc, sentinel));
- /* Inhibit quit so that random quits don't screw up a running filter. */
- specbind (Qinhibit_quit, Qt);
- specbind (Qlast_nonmenu_event, Qt);
-
- /* In case we get recursively called,
- and we already saved the match data nonrecursively,
- save the same match data in safely recursive fashion. */
- if (outer_running_asynch_code)
- {
- Lisp_Object tem;
- tem = Fmatch_data (Qnil, Qnil);
- restore_match_data ();
- record_unwind_protect (Fstore_match_data, Fmatch_data (Qnil, Qnil));
- Fstore_match_data (tem);
- }
-
- /* For speed, if a search happens within this code,
- save the match data in a special nonrecursive fashion. */
- running_asynch_code = 1;
-
- internal_condition_case_1 (read_process_output_call,
- Fcons (sentinel,
- Fcons (proc, Fcons (reason, Qnil))),
- !NILP (Vdebug_on_error) ? Qnil : Qerror,
- exec_sentinel_error_handler);
-
- /* If we saved the match data nonrecursively, restore it now. */
- restore_match_data ();
- running_asynch_code = outer_running_asynch_code;
-
- Vdeactivate_mark = odeactivate;
-#if 0
- if (! EQ (Fcurrent_buffer (), obuffer)
- || ! EQ (current_buffer->keymap, okeymap))
-#endif
- /* But do it only if the caller is actually going to read events.
- Otherwise there's no need to make him wake up, and it could
- cause trouble (for example it would make Fsit_for return). */
- if (waiting_for_user_input_p == -1)
- record_asynch_buffer_change ();
-
- unbind_to (count, Qnil);
-}
-
-/* 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, msg;
- struct gcpro gcpro1, gcpro2;
-
- tail = Qnil;
- msg = Qnil;
- /* 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, and then causes a GC, tail is an unprotected
- reference. */
- GCPRO2 (tail, msg);
-
- /* Set this now, so that if new processes are created by sentinels
- that we run, we get called again to handle their status changes. */
- update_tick = process_tick;
-
- for (tail = Vprocess_alist; !NILP (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. */
- while (! EQ (p->filter, Qt)
- && XINT (p->infd) >= 0
- && read_process_output (proc, XINT (p->infd)) > 0);
-
- buffer = p->buffer;
-
- /* Get the text to use for the message. */
- if (!NILP (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 (CONSP (p->status))
- 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);
- }
-
- /* The actions above may have further incremented p->tick.
- So set p->update_tick again
- so that an error in the sentinel will not cause
- this code to be run again. */
- XSETINT (p->update_tick, XINT (p->tick));
- /* Now output the message suitably. */
- if (!NILP (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) && !NILP (buffer))
- {
- Lisp_Object ro, tem;
- struct buffer *old = current_buffer;
- int opoint;
-
- ro = XBUFFER (buffer)->read_only;
-
- /* Avoid error if buffer is deleted
- (probably that's why the process is dead, too) */
- if (NILP (XBUFFER (buffer)->name))
- continue;
- Fset_buffer (buffer);
- opoint = PT;
- /* 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 (PT <= opoint)
- opoint += XSTRING (msg)->size + XSTRING (p->name)->size + 10;
-
- tem = current_buffer->read_only;
- current_buffer->read_only = Qnil;
- insert_string ("\nProcess ");
- Finsert (1, &p->name);
- insert_string (" ");
- Finsert (1, &msg);
- current_buffer->read_only = tem;
- Fset_marker (p->mark, make_number (PT), 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 ();
-
- UNGCPRO;
-}
-
-/* The first time this is called, assume keyboard input comes from DESC
- instead of from where we used to expect it.
- Subsequent calls mean assume input keyboard can come from DESC
- in addition to other places. */
-
-static int add_keyboard_wait_descriptor_called_flag;
-
-void
-add_keyboard_wait_descriptor (desc)
- int desc;
-{
- if (! add_keyboard_wait_descriptor_called_flag)
- FD_CLR (0, &input_wait_mask);
- add_keyboard_wait_descriptor_called_flag = 1;
- FD_SET (desc, &input_wait_mask);
- if (desc > max_keyboard_desc)
- max_keyboard_desc = desc;
-}
-
-/* From now on, do not expect DESC to give keyboard input. */
-
-void
-delete_keyboard_wait_descriptor (desc)
- int desc;
-{
- int fd;
- int lim = max_keyboard_desc;
-
- FD_CLR (desc, &input_wait_mask);
-
- if (desc == max_keyboard_desc)
- for (fd = 0; fd < lim; fd++)
- if (FD_ISSET (fd, &input_wait_mask)
- && !FD_ISSET (fd, &non_keyboard_wait_mask))
- max_keyboard_desc = fd;
-}
-
-/* Return nonzero if *MASK has a bit set
- that corresponds to one of the keyboard input descriptors. */
-
-int
-keyboard_bit_set (mask)
- SELECT_TYPE *mask;
-{
- int fd;
-
- for (fd = 0; fd <= max_keyboard_desc; fd++)
- if (FD_ISSET (fd, mask) && FD_ISSET (fd, &input_wait_mask)
- && !FD_ISSET (fd, &non_keyboard_wait_mask))
- return 1;
-
- return 0;
-}
-
-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_ZERO (&non_keyboard_wait_mask);
- max_process_desc = 0;
-
- 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);
-
- Qlast_nonmenu_event = intern ("last-nonmenu-event");
- staticpro (&Qlast_nonmenu_event);
-
- 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, or t or `pty' to use a pty.\n\
-The value has no effect if the system has no ptys or if all ptys are busy:\n\
-then a pipe is used in any case.\n\
-The 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_tty_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 (&Sset_process_window_size);
- defsubr (&Sprocess_kill_without_query);
- defsubr (&Sprocess_contact);
- 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 (&Ssignal_process);
- defsubr (&Swaiting_for_user_input_p);
-/* defsubr (&Sprocess_connection); */
-}
-
-
-#else /* not subprocesses */
-
-#include <sys/types.h>
-#include <errno.h>
-
-#include "lisp.h"
-#include "systime.h"
-#include "termopts.h"
-#include "sysselect.h"
-
-extern int frame_garbaged;
-
-extern EMACS_TIME timer_check ();
-extern int timers_run;
-
-/* As described above, except assuming that there are no subprocesses:
-
- Wait for timeout to elapse and/or keyboard input to be available.
-
- time_limit is:
- timeout in seconds, or
- zero for no limit, or
- -1 means gobble data immediately available but don't wait for any.
-
- read_kbd is a Lisp_Object:
- 0 to ignore keyboard input, or
- 1 to return when input is available, or
- -1 means caller will actually read the input, so don't throw to
- the quit handler.
- a cons cell, meaning wait until its car is non-nil
- (and gobble terminal input into the buffer if any arrives), or
- We know that read_kbd will never be a Lisp_Process, since
- `subprocesses' isn't defined.
-
- do_display != 0 means redisplay should be done to show subprocess
- output that arrives.
-
- Return true iff we received input from any process. */
-
-int
-wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
- int time_limit, microsecs;
- Lisp_Object read_kbd;
- int do_display;
-{
- EMACS_TIME end_time, timeout;
- SELECT_TYPE waitchannels;
- int xerrno;
- Lisp_Object *wait_for_cell = 0;
-
- /* If waiting for non-nil in a cell, record where. */
- if (CONSP (read_kbd))
- {
- wait_for_cell = &XCONS (read_kbd)->car;
- XSETFASTINT (read_kbd, 0);
- }
-
- /* What does time_limit really mean? */
- if (time_limit || microsecs)
- {
- if (time_limit == -1)
- /* In fact, it's zero. */
- EMACS_SET_SECS_USECS (timeout, 0, 0);
- else
- EMACS_SET_SECS_USECS (timeout, time_limit, microsecs);
-
- /* How far in the future is that? */
- EMACS_GET_TIME (end_time);
- EMACS_ADD_TIME (end_time, end_time, timeout);
- }
- else
- /* It's infinite. */
- EMACS_SET_SECS_USECS (timeout, 100000, 0);
-
- /* Turn off periodic alarms (in case they are in use)
- because the select emulator uses alarms. */
- stop_polling ();
-
- for (;;)
- {
- int nfds;
- int timeout_reduced_for_timers = 0;
-
- /* 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 (XINT (read_kbd) >= 0)
- QUIT;
-
- /* Exit now if the cell we're waiting for became non-nil. */
- if (wait_for_cell && ! NILP (*wait_for_cell))
- break;
-
- /* Compute time from now till when time limit is up */
- /* Exit if already run out */
- if (time_limit > 0 || microsecs)
- {
- EMACS_GET_TIME (timeout);
- EMACS_SUB_TIME (timeout, end_time, timeout);
- if (EMACS_TIME_NEG_P (timeout))
- break;
- }
-
- /* If our caller will not immediately handle keyboard events,
- run timer events directly.
- (Callers that will immediately read keyboard events
- call timer_delay on their own.) */
- if (! wait_for_cell)
- {
- EMACS_TIME timer_delay;
- int old_timers_run;
-
- retry:
- old_timers_run = timers_run;
- timer_delay = timer_check (1);
- if (timers_run != old_timers_run && do_display)
- {
- redisplay_preserve_echo_area ();
- /* We must retry, since a timer may have requeued itself
- and that could alter the time delay. */
- goto retry;
- }
-
- if (! EMACS_TIME_NEG_P (timer_delay) && time_limit != -1)
- {
- EMACS_TIME difference;
- EMACS_SUB_TIME (difference, timer_delay, timeout);
- if (EMACS_TIME_NEG_P (difference))
- {
- timeout = timer_delay;
- timeout_reduced_for_timers = 1;
- }
- }
- }
-
- /* Cause C-g and alarm signals to take immediate action,
- and cause input available signals to zero out timeout. */
- if (XINT (read_kbd) < 0)
- set_waiting_for_input (&timeout);
-
- /* Wait till there is something to do. */
-
- if (! XINT (read_kbd) && wait_for_cell == 0)
- FD_ZERO (&waitchannels);
- else
- FD_SET (0, &waitchannels);
-
- /* If a frame has been newly mapped and needs updating,
- reprocess its display stuff. */
- if (frame_garbaged && do_display)
- {
- clear_waiting_for_input ();
- redisplay_preserve_echo_area ();
- if (XINT (read_kbd) < 0)
- set_waiting_for_input (&timeout);
- }
-
- if (XINT (read_kbd) && detect_input_pending ())
- {
- nfds = 0;
- FD_ZERO (&waitchannels);
- }
- else
- nfds = select (1, &waitchannels, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
- &timeout);
-
- xerrno = errno;
-
- /* Make C-g and alarm signals set flags again */
- clear_waiting_for_input ();
-
- /* If we woke up due to SIGWINCH, actually change size now. */
- do_pending_window_change ();
-
- if (time_limit && nfds == 0 && ! timeout_reduced_for_timers)
- /* We waited the full specified time, so return now. */
- break;
-
- if (nfds == -1)
- {
- /* If the system call was interrupted, then go around the
- loop again. */
- if (xerrno == EINTR)
- FD_ZERO (&waitchannels);
- else
- error ("select error: %s", strerror (xerrno));
- }
-#ifdef sun
- else if (nfds > 0 && (waitchannels & 1) && interrupt_input)
- /* System sometimes fails to deliver SIGIO. */
- kill (getpid (), SIGIO);
-#endif
-#ifdef SIGIO
- if (XINT (read_kbd) && interrupt_input && (waitchannels & 1))
- kill (getpid (), SIGIO);
-#endif
-
- /* Check for keyboard input */
-
- if ((XINT (read_kbd) != 0)
- && detect_input_pending_run_timers (do_display))
- {
- swallow_events (do_display);
- if (detect_input_pending_run_timers (do_display))
- break;
- }
-
- /* If wait_for_cell. check for keyboard input
- but don't run any timers.
- ??? (It seems wrong to me to check for keyboard
- input at all when wait_for_cell, but the code
- has been this way since July 1994.
- Try changing this after version 19.31.) */
- if (wait_for_cell
- && detect_input_pending ())
- {
- swallow_events (do_display);
- if (detect_input_pending ())
- break;
- }
-
- /* Exit now if the cell we're waiting for became non-nil. */
- if (wait_for_cell && ! NILP (*wait_for_cell))
- break;
- }
-
- start_polling ();
-
- return 0;
-}
-
-
-DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
- /* Don't confuse make-docfile by having two doc strings for this function.
- make-docfile does not pay attention to #if, for good reason! */
- 0)
- (name)
- register Lisp_Object name;
-{
- return Qnil;
-}
-
-/* Kill all processes associated with `buffer'.
- If `buffer' is nil, kill all processes.
- Since we have no subprocesses, this does nothing. */
-
-kill_buffer_processes (buffer)
- Lisp_Object buffer;
-{
-}
-
-init_process ()
-{
-}
-
-syms_of_process ()
-{
- defsubr (&Sget_buffer_process);
-}
-
-
-#endif /* not subprocesses */
diff --git a/src/process.h b/src/process.h
deleted file mode 100644
index ab7e410523b..00000000000
--- a/src/process.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Definitions for asynchronous process control in GNU Emacs.
- Copyright (C) 1985, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Structure records pertinent information about open channels.
- * There is one channel associated with each process.
- */
-
-struct Lisp_Process
- {
- EMACS_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 subprocess terminal. */
- Lisp_Object tty_name;
- /* 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;
- /* t if this is a real child process.
- For a net connection, it is (HOST SERVICE). */
- 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))
-
-/* Indexed by descriptor, gives the process (if any) for that descriptor. */
-extern Lisp_Object chan_process[];
-
-/* Alist of elements (NAME . PROCESS). */
-extern Lisp_Object Vprocess_alist;
-
-/* True iff we are about to fork off a synchronous process or if we
- are waiting for it. */
-extern int synch_process_alive;
-
-/* Communicate exit status of sync process to from sigchld_handler
- to Fcall_process. */
-
-/* Nonzero => this is a string explaining death of synchronous subprocess. */
-extern char *synch_process_death;
-
-/* If synch_process_death is zero,
- this is exit code of synchronous subprocess. */
-extern int synch_process_retcode;
-
-/* The name of the file open to get a null file, or a data sink.
- VMS, MS-DOS, and OS/2 redefine this. */
-#ifndef NULL_DEVICE
-#define NULL_DEVICE "/dev/null"
-#endif
-
-/* A string listing the possible suffixes used for executable files,
- separated by colons. VMS, MS-DOS, and OS/2 redefine this. */
-#ifndef EXEC_SUFFIXES
-#define EXEC_SUFFIXES ""
-#endif
diff --git a/src/puresize.h b/src/puresize.h
deleted file mode 100644
index 5ce857203ec..00000000000
--- a/src/puresize.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/* How much read-only Lisp storage a dumped Emacs needs.
- Copyright (C) 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Define PURESIZE, the number of bytes of pure Lisp code to leave space for.
-
- At one point, this was defined in config.h, meaning that changing
- PURESIZE would make Make recompile all of Emacs. But only a few
- files actually use PURESIZE, so we split it out to its own .h file.
-
- Make sure to include this file after config.h, since that tells us
- whether we are running X windows, which tells us how much pure
- storage to allocate. */
-
-/* First define a measure of the amount of data we have. */
-
-/* A system configuration file may set this to request a certain extra
- amount of storage. This is a lot more update-robust that defining
- BASE_PURESIZE or even PURESIZE directly. */
-#ifndef SYSTEM_PURESIZE_EXTRA
-#define SYSTEM_PURESIZE_EXTRA 0
-#endif
-
-#ifndef SITELOAD_PURESIZE_EXTRA
-#define SITELOAD_PURESIZE_EXTRA 0
-#endif
-
-#ifndef BASE_PURESIZE
-#define BASE_PURESIZE (350000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA)
-#endif
-
-/* Increase BASE_PURESIZE by a ratio depending on the machine's word size. */
-#ifndef PURESIZE_RATIO
-#if VALBITS + GCTYPEBITS + 1 > 32
-#define PURESIZE_RATIO 8/5 /* Don't surround with `()'. */
-#else
-#define PURESIZE_RATIO 1
-#endif
-#endif
-
-/* This is the actual size in bytes to allocate. */
-#ifndef PURESIZE
-#define PURESIZE (BASE_PURESIZE * PURESIZE_RATIO)
-#endif
-
-/* Signal an error if OBJ is pure. */
-#define CHECK_IMPURE(obj) \
- { if (PURE_P (obj)) \
- pure_write_error (); }
-
-/* Define PURE_P. */
-
-#ifdef VIRT_ADDR_VARIES
-/* For machines like APOLLO where text and data can go anywhere
- in virtual memory. */
-
-extern EMACS_INT pure[];
-
-#define PURE_P(obj) \
- ((PNTR_COMPARISON_TYPE) XPNTR (obj) < (PNTR_COMPARISON_TYPE) ((char *) pure + PURESIZE) \
- && (PNTR_COMPARISON_TYPE) XPNTR (obj) >= (PNTR_COMPARISON_TYPE) pure)
-
-#else /* not VIRT_ADDR_VARIES */
-#ifdef PNTR_COMPARISON_TYPE
-/* When PNTR_COMPARISON_TYPE is not the default (unsigned int). */
-
-extern char my_edata[];
-
-#define PURE_P(obj) \
- ((PNTR_COMPARISON_TYPE) XPNTR (obj) < (PNTR_COMPARISON_TYPE) my_edata)
-
-#else /* not VIRT_ADDRESS_VARIES, not PNTR_COMPARISON_TYPE */
-
-extern char my_edata[];
-
-#define PURE_P(obj) \
- (XPNTR (obj) < (unsigned int) my_edata)
-
-#endif /* PNTR_COMPARISON_TYPE */
-#endif /* VIRT_ADDRESS_VARIES */
-
diff --git a/src/ralloc.c b/src/ralloc.c
deleted file mode 100644
index 179fd314928..00000000000
--- a/src/ralloc.c
+++ /dev/null
@@ -1,1234 +0,0 @@
-/* Block-relocating memory allocator.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* NOTES:
-
- Only relocate the blocs necessary 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. */
-
-#ifdef emacs
-
-#include <config.h>
-#include "lisp.h" /* Needed for VALBITS. */
-
-#undef NULL
-
-/* The important properties of this type are that 1) it's a pointer, and
- 2) arithmetic on it should work as if the size of the object pointed
- to has a size of 1. */
-#if 0 /* Arithmetic on void* is a GCC extension. */
-#ifdef __STDC__
-typedef void *POINTER;
-#else
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-typedef char *POINTER;
-
-#endif
-#endif /* 0 */
-
-/* Unconditionally use char * for this. */
-typedef char *POINTER;
-
-typedef unsigned long SIZE;
-
-/* Declared in dispnew.c, this version doesn't screw up if regions
- overlap. */
-extern void safe_bcopy ();
-
-extern int __malloc_extra_blocks;
-
-#else /* not emacs */
-
-#include <stddef.h>
-
-typedef size_t SIZE;
-typedef void *POINTER;
-
-#include <unistd.h>
-#include <malloc.h>
-#include <string.h>
-
-#define safe_bcopy(x, y, z) memmove (y, x, z)
-#define bzero(x, len) memset (x, 0, len)
-
-#endif /* not emacs */
-
-#include "getpagesize.h"
-
-#define NIL ((POINTER) 0)
-
-/* A flag to indicate whether we have initialized ralloc yet. For
- Emacs's sake, please do not make this local to malloc_init; on some
- machines, the dumping procedure makes all static variables
- read-only. On these machines, the word static is #defined to be
- the empty string, meaning that r_alloc_initialized becomes an
- automatic variable, and loses its value each time Emacs is started up. */
-static int r_alloc_initialized = 0;
-
-static void r_alloc_init ();
-
-/* Declarations for working with the malloc, ralloc, and system breaks. */
-
-/* Function to set the real break value. */
-static POINTER (*real_morecore) ();
-
-/* The break value, as seen by malloc. */
-static POINTER virtual_break_value;
-
-/* The address of the end of the last data in use by ralloc,
- including relocatable blocs as well as malloc data. */
-static POINTER break_value;
-
-/* This is the size of a page. We round memory requests to this boundary. */
-static int page_size;
-
-/* Whenever we get memory from the system, get this many extra bytes. This
- must be a multiple of page_size. */
-static int extra_bytes;
-
-/* Macros for rounding. Note that rounding to any value is possible
- by changing the definition of PAGE. */
-#define PAGE (getpagesize ())
-#define ALIGNED(addr) (((unsigned long int) (addr) & (page_size - 1)) == 0)
-#define ROUNDUP(size) (((unsigned long int) (size) + page_size - 1) \
- & ~(page_size - 1))
-#define ROUND_TO_PAGE(addr) (addr & (~(page_size - 1)))
-
-#define MEM_ALIGN sizeof(double)
-#define MEM_ROUNDUP(addr) (((unsigned long int)(addr) + MEM_ALIGN - 1) \
- & ~(MEM_ALIGN - 1))
-
-/* Data structures of heaps and blocs. */
-
-/* The relocatable objects, or blocs, and the malloc data
- both reside within one or more heaps.
- Each heap contains malloc data, running from `start' to `bloc_start',
- and relocatable objects, running from `bloc_start' to `free'.
-
- Relocatable objects may relocate within the same heap
- or may move into another heap; the heaps themselves may grow
- but they never move.
-
- We try to make just one heap and make it larger as necessary.
- But sometimes we can't do that, because we can't get contiguous
- space to add onto the heap. When that happens, we start a new heap. */
-
-typedef struct heap
-{
- struct heap *next;
- struct heap *prev;
- /* Start of memory range of this heap. */
- POINTER start;
- /* End of memory range of this heap. */
- POINTER end;
- /* Start of relocatable data in this heap. */
- POINTER bloc_start;
- /* Start of unused space in this heap. */
- POINTER free;
- /* First bloc in this heap. */
- struct bp *first_bloc;
- /* Last bloc in this heap. */
- struct bp *last_bloc;
-} *heap_ptr;
-
-#define NIL_HEAP ((heap_ptr) 0)
-#define HEAP_PTR_SIZE (sizeof (struct heap))
-
-/* This is the first heap object.
- If we need additional heap objects, each one resides at the beginning of
- the space it covers. */
-static struct heap heap_base;
-
-/* Head and tail of the list of heaps. */
-static heap_ptr first_heap, last_heap;
-
-/* These structures are allocated in the malloc arena.
- The linked list is kept in order of increasing '.data' members.
- The data blocks abut each other; if b->next is non-nil, then
- b->data + b->size == b->next->data.
-
- An element with variable==NIL denotes a freed block, which has not yet
- been collected. They may only appear while r_alloc_freeze > 0, and will be
- freed when the arena is thawed. Currently, these blocs are not reusable,
- while the arena is frozen. Very inefficient. */
-
-typedef struct bp
-{
- struct bp *next;
- struct bp *prev;
- POINTER *variable;
- POINTER data;
- SIZE size;
- POINTER new_data; /* temporarily used for relocation */
- struct heap *heap; /* Heap this bloc is in. */
-} *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;
-
-static int use_relocatable_buffers;
-
-/* If >0, no relocation whatsoever takes place. */
-static int r_alloc_freeze_level;
-
-
-/* Functions to get and return memory from the system. */
-
-/* Find the heap that ADDRESS falls within. */
-
-static heap_ptr
-find_heap (address)
- POINTER address;
-{
- heap_ptr heap;
-
- for (heap = last_heap; heap; heap = heap->prev)
- {
- if (heap->start <= address && address <= heap->end)
- return heap;
- }
-
- return NIL_HEAP;
-}
-
-/* Find SIZE bytes of space in a heap.
- Try to get them at ADDRESS (which must fall within some heap's range)
- if we can get that many within one heap.
-
- If enough space is not presently available in our reserve, this means
- getting more page-aligned space from the system. If the returned space
- is not contiguous to the last heap, allocate a new heap, and append it
-
- obtain does not try to keep track of whether space is in use
- or not in use. It just returns the address of SIZE bytes that
- fall within a single heap. If you call obtain twice in a row
- with the same arguments, you typically get the same value.
- to the heap list. It's the caller's responsibility to keep
- track of what space is in use.
-
- Return the address of the space if all went well, or zero if we couldn't
- allocate the memory. */
-
-static POINTER
-obtain (address, size)
- POINTER address;
- SIZE size;
-{
- heap_ptr heap;
- SIZE already_available;
-
- /* Find the heap that ADDRESS falls within. */
- for (heap = last_heap; heap; heap = heap->prev)
- {
- if (heap->start <= address && address <= heap->end)
- break;
- }
-
- if (! heap)
- abort ();
-
- /* If we can't fit SIZE bytes in that heap,
- try successive later heaps. */
- while (heap && address + size > heap->end)
- {
- heap = heap->next;
- if (heap == NIL_HEAP)
- break;
- address = heap->bloc_start;
- }
-
- /* If we can't fit them within any existing heap,
- get more space. */
- if (heap == NIL_HEAP)
- {
- POINTER new = (*real_morecore)(0);
- SIZE get;
-
- already_available = (char *)last_heap->end - (char *)address;
-
- if (new != last_heap->end)
- {
- /* Someone else called sbrk. Make a new heap. */
-
- heap_ptr new_heap = (heap_ptr) MEM_ROUNDUP (new);
- POINTER bloc_start = (POINTER) MEM_ROUNDUP ((POINTER)(new_heap + 1));
-
- if ((*real_morecore) (bloc_start - new) != new)
- return 0;
-
- new_heap->start = new;
- new_heap->end = bloc_start;
- new_heap->bloc_start = bloc_start;
- new_heap->free = bloc_start;
- new_heap->next = NIL_HEAP;
- new_heap->prev = last_heap;
- new_heap->first_bloc = NIL_BLOC;
- new_heap->last_bloc = NIL_BLOC;
- last_heap->next = new_heap;
- last_heap = new_heap;
-
- address = bloc_start;
- already_available = 0;
- }
-
- /* Add space to the last heap (which we may have just created).
- Get some extra, so we can come here less often. */
-
- get = size + extra_bytes - already_available;
- get = (char *) ROUNDUP ((char *)last_heap->end + get)
- - (char *) last_heap->end;
-
- if ((*real_morecore) (get) != last_heap->end)
- return 0;
-
- last_heap->end += get;
- }
-
- return address;
-}
-
-/* Return unused heap space to the system
- if there is a lot of unused space now.
- This can make the last heap smaller;
- it can also eliminate the last heap entirely. */
-
-static void
-relinquish ()
-{
- register heap_ptr h;
- int excess = 0;
-
- /* Add the amount of space beyond break_value
- in all heaps which have extend beyond break_value at all. */
-
- for (h = last_heap; h && break_value < h->end; h = h->prev)
- {
- excess += (char *) h->end - (char *) ((break_value < h->bloc_start)
- ? h->bloc_start : break_value);
- }
-
- if (excess > extra_bytes * 2 && (*real_morecore) (0) == last_heap->end)
- {
- /* Keep extra_bytes worth of empty space.
- And don't free anything unless we can free at least extra_bytes. */
- excess -= extra_bytes;
-
- if ((char *)last_heap->end - (char *)last_heap->bloc_start <= excess)
- {
- /* This heap should have no blocs in it. */
- if (last_heap->first_bloc != NIL_BLOC
- || last_heap->last_bloc != NIL_BLOC)
- abort ();
-
- /* Return the last heap, with its header, to the system. */
- excess = (char *)last_heap->end - (char *)last_heap->start;
- last_heap = last_heap->prev;
- last_heap->next = NIL_HEAP;
- }
- else
- {
- excess = (char *) last_heap->end
- - (char *) ROUNDUP ((char *)last_heap->end - excess);
- last_heap->end -= excess;
- }
-
- if ((*real_morecore) (- excess) == 0)
- abort ();
- }
-}
-
-/* Return the total size in use by relocating allocator,
- above where malloc gets space. */
-
-long
-r_alloc_size_in_use ()
-{
- return break_value - virtual_break_value;
-}
-
-/* The meat - allocating, freeing, and relocating blocs. */
-
-/* Find the bloc referenced 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, or zero if we couldn't allocate
- memory for the new block. */
-
-static bloc_ptr
-get_bloc (size)
- SIZE size;
-{
- register bloc_ptr new_bloc;
- register heap_ptr heap;
-
- if (! (new_bloc = (bloc_ptr) malloc (BLOC_PTR_SIZE))
- || ! (new_bloc->data = obtain (break_value, size)))
- {
- if (new_bloc)
- free (new_bloc);
-
- return 0;
- }
-
- break_value = new_bloc->data + size;
-
- new_bloc->size = size;
- new_bloc->next = NIL_BLOC;
- new_bloc->variable = (POINTER *) NIL;
- new_bloc->new_data = 0;
-
- /* Record in the heap that this space is in use. */
- heap = find_heap (new_bloc->data);
- heap->free = break_value;
-
- /* Maintain the correspondence between heaps and blocs. */
- new_bloc->heap = heap;
- heap->last_bloc = new_bloc;
- if (heap->first_bloc == NIL_BLOC)
- heap->first_bloc = new_bloc;
-
- /* Put this bloc on the doubly-linked list of blocs. */
- 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;
-}
-
-/* Calculate new locations of blocs in the list beginning with BLOC,
- relocating it to start at ADDRESS, in heap HEAP. If enough space is
- not presently available in our reserve, call obtain for
- more space.
-
- Store the new location of each bloc in its new_data field.
- Do not touch the contents of blocs or break_value. */
-
-static int
-relocate_blocs (bloc, heap, address)
- bloc_ptr bloc;
- heap_ptr heap;
- POINTER address;
-{
- register bloc_ptr b = bloc;
-
- /* No need to ever call this if arena is frozen, bug somewhere! */
- if (r_alloc_freeze_level)
- abort();
-
- while (b)
- {
- /* If bloc B won't fit within HEAP,
- move to the next heap and try again. */
- while (heap && address + b->size > heap->end)
- {
- heap = heap->next;
- if (heap == NIL_HEAP)
- break;
- address = heap->bloc_start;
- }
-
- /* If BLOC won't fit in any heap,
- get enough new space to hold BLOC and all following blocs. */
- if (heap == NIL_HEAP)
- {
- register bloc_ptr tb = b;
- register SIZE s = 0;
-
- /* Add up the size of all the following blocs. */
- while (tb != NIL_BLOC)
- {
- if (tb->variable)
- s += tb->size;
-
- tb = tb->next;
- }
-
- /* Get that space. */
- address = obtain (address, s);
- if (address == 0)
- return 0;
-
- heap = last_heap;
- }
-
- /* Record the new address of this bloc
- and update where the next bloc can start. */
- b->new_data = address;
- if (b->variable)
- address += b->size;
- b = b->next;
- }
-
- return 1;
-}
-
-/* Reorder the bloc BLOC to go before bloc BEFORE in the doubly linked list.
- This is necessary if we put the memory of space of BLOC
- before that of BEFORE. */
-
-static void
-reorder_bloc (bloc, before)
- bloc_ptr bloc, before;
-{
- bloc_ptr prev, next;
-
- /* Splice BLOC out from where it is. */
- prev = bloc->prev;
- next = bloc->next;
-
- if (prev)
- prev->next = next;
- if (next)
- next->prev = prev;
-
- /* Splice it in before BEFORE. */
- prev = before->prev;
-
- if (prev)
- prev->next = bloc;
- bloc->prev = prev;
-
- before->prev = bloc;
- bloc->next = before;
-}
-
-/* Update the records of which heaps contain which blocs, starting
- with heap HEAP and bloc BLOC. */
-
-static void
-update_heap_bloc_correspondence (bloc, heap)
- bloc_ptr bloc;
- heap_ptr heap;
-{
- register bloc_ptr b;
-
- /* Initialize HEAP's status to reflect blocs before BLOC. */
- if (bloc != NIL_BLOC && bloc->prev != NIL_BLOC && bloc->prev->heap == heap)
- {
- /* The previous bloc is in HEAP. */
- heap->last_bloc = bloc->prev;
- heap->free = bloc->prev->data + bloc->prev->size;
- }
- else
- {
- /* HEAP contains no blocs before BLOC. */
- heap->first_bloc = NIL_BLOC;
- heap->last_bloc = NIL_BLOC;
- heap->free = heap->bloc_start;
- }
-
- /* Advance through blocs one by one. */
- for (b = bloc; b != NIL_BLOC; b = b->next)
- {
- /* Advance through heaps, marking them empty,
- till we get to the one that B is in. */
- while (heap)
- {
- if (heap->bloc_start <= b->data && b->data <= heap->end)
- break;
- heap = heap->next;
- /* We know HEAP is not null now,
- because there has to be space for bloc B. */
- heap->first_bloc = NIL_BLOC;
- heap->last_bloc = NIL_BLOC;
- heap->free = heap->bloc_start;
- }
-
- /* Update HEAP's status for bloc B. */
- heap->free = b->data + b->size;
- heap->last_bloc = b;
- if (heap->first_bloc == NIL_BLOC)
- heap->first_bloc = b;
-
- /* Record that B is in HEAP. */
- b->heap = heap;
- }
-
- /* If there are any remaining heaps and no blocs left,
- mark those heaps as empty. */
- heap = heap->next;
- while (heap)
- {
- heap->first_bloc = NIL_BLOC;
- heap->last_bloc = NIL_BLOC;
- heap->free = heap->bloc_start;
- heap = heap->next;
- }
-}
-
-/* Resize BLOC to SIZE bytes. This relocates the blocs
- that come after BLOC in memory. */
-
-static int
-resize_bloc (bloc, size)
- bloc_ptr bloc;
- SIZE size;
-{
- register bloc_ptr b;
- heap_ptr heap;
- POINTER address;
- SIZE old_size;
-
- /* No need to ever call this if arena is frozen, bug somewhere! */
- if (r_alloc_freeze_level)
- abort();
-
- if (bloc == NIL_BLOC || size == bloc->size)
- return 1;
-
- for (heap = first_heap; heap != NIL_HEAP; heap = heap->next)
- {
- if (heap->bloc_start <= bloc->data && bloc->data <= heap->end)
- break;
- }
-
- if (heap == NIL_HEAP)
- abort ();
-
- old_size = bloc->size;
- bloc->size = size;
-
- /* Note that bloc could be moved into the previous heap. */
- address = (bloc->prev ? bloc->prev->data + bloc->prev->size
- : first_heap->bloc_start);
- while (heap)
- {
- if (heap->bloc_start <= address && address <= heap->end)
- break;
- heap = heap->prev;
- }
-
- if (! relocate_blocs (bloc, heap, address))
- {
- bloc->size = old_size;
- return 0;
- }
-
- if (size > old_size)
- {
- for (b = last_bloc; b != bloc; b = b->prev)
- {
- if (!b->variable)
- {
- b->size = 0;
- b->data = b->new_data;
- }
- else
- {
- safe_bcopy (b->data, b->new_data, b->size);
- *b->variable = b->data = b->new_data;
- }
- }
- if (!bloc->variable)
- {
- bloc->size = 0;
- bloc->data = bloc->new_data;
- }
- else
- {
- safe_bcopy (bloc->data, bloc->new_data, old_size);
- bzero (bloc->new_data + old_size, size - old_size);
- *bloc->variable = bloc->data = bloc->new_data;
- }
- }
- else
- {
- for (b = bloc; b != NIL_BLOC; b = b->next)
- {
- if (!b->variable)
- {
- b->size = 0;
- b->data = b->new_data;
- }
- else
- {
- safe_bcopy (b->data, b->new_data, b->size);
- *b->variable = b->data = b->new_data;
- }
- }
- }
-
- update_heap_bloc_correspondence (bloc, heap);
-
- break_value = (last_bloc ? last_bloc->data + last_bloc->size
- : first_heap->bloc_start);
- return 1;
-}
-
-/* Free BLOC from the chain of blocs, relocating any blocs above it.
- This may return space to the system. */
-
-static void
-free_bloc (bloc)
- bloc_ptr bloc;
-{
- heap_ptr heap = bloc->heap;
-
- if (r_alloc_freeze_level)
- {
- bloc->variable = (POINTER *) NIL;
- return;
- }
-
- resize_bloc (bloc, 0);
-
- 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;
- }
- else
- {
- bloc->next->prev = bloc->prev;
- bloc->prev->next = bloc->next;
- }
-
- /* Update the records of which blocs are in HEAP. */
- if (heap->first_bloc == bloc)
- {
- if (bloc->next != 0 && bloc->next->heap == heap)
- heap->first_bloc = bloc->next;
- else
- heap->first_bloc = heap->last_bloc = NIL_BLOC;
- }
- if (heap->last_bloc == bloc)
- {
- if (bloc->prev != 0 && bloc->prev->heap == heap)
- heap->last_bloc = bloc->prev;
- else
- heap->first_bloc = heap->last_bloc = NIL_BLOC;
- }
-
- relinquish ();
- free (bloc);
-}
-
-/* Interface routines. */
-
-/* Obtain SIZE bytes of storage from the free pool, or the system, as
- necessary. If relocatable blocs are in use, this means relocating
- them. This function gets plugged into the GNU malloc's __morecore
- hook.
-
- We provide hysteresis, never relocating by less than extra_bytes.
-
- If we're out of memory, we should return zero, to imitate the other
- __morecore hook values - in particular, __default_morecore in the
- GNU malloc package. */
-
-POINTER
-r_alloc_sbrk (size)
- long size;
-{
- register bloc_ptr b;
- POINTER address;
-
- if (! r_alloc_initialized)
- r_alloc_init ();
-
- if (! use_relocatable_buffers)
- return (*real_morecore) (size);
-
- if (size == 0)
- return virtual_break_value;
-
- if (size > 0)
- {
- /* Allocate a page-aligned space. GNU malloc would reclaim an
- extra space if we passed an unaligned one. But we could
- not always find a space which is contiguous to the previous. */
- POINTER new_bloc_start;
- heap_ptr h = first_heap;
- SIZE get = ROUNDUP (size);
-
- address = (POINTER) ROUNDUP (virtual_break_value);
-
- /* Search the list upward for a heap which is large enough. */
- while ((char *) h->end < (char *) MEM_ROUNDUP ((char *)address + get))
- {
- h = h->next;
- if (h == NIL_HEAP)
- break;
- address = (POINTER) ROUNDUP (h->start);
- }
-
- /* If not found, obtain more space. */
- if (h == NIL_HEAP)
- {
- get += extra_bytes + page_size;
-
- if (! obtain (address, get))
- return 0;
-
- if (first_heap == last_heap)
- address = (POINTER) ROUNDUP (virtual_break_value);
- else
- address = (POINTER) ROUNDUP (last_heap->start);
- h = last_heap;
- }
-
- new_bloc_start = (POINTER) MEM_ROUNDUP ((char *)address + get);
-
- if (first_heap->bloc_start < new_bloc_start)
- {
- /* This is no clean solution - no idea how to do it better. */
- if (r_alloc_freeze_level)
- return NIL;
-
- /* There is a bug here: if the above obtain call succeeded, but the
- relocate_blocs call below does not succeed, we need to free
- the memory that we got with obtain. */
-
- /* Move all blocs upward. */
- if (! relocate_blocs (first_bloc, h, new_bloc_start))
- return 0;
-
- /* Note that (POINTER)(h+1) <= new_bloc_start since
- get >= page_size, so the following does not destroy the heap
- header. */
- for (b = last_bloc; b != NIL_BLOC; b = b->prev)
- {
- safe_bcopy (b->data, b->new_data, b->size);
- *b->variable = b->data = b->new_data;
- }
-
- h->bloc_start = new_bloc_start;
-
- update_heap_bloc_correspondence (first_bloc, h);
- }
- if (h != first_heap)
- {
- /* Give up managing heaps below the one the new
- virtual_break_value points to. */
- first_heap->prev = NIL_HEAP;
- first_heap->next = h->next;
- first_heap->start = h->start;
- first_heap->end = h->end;
- first_heap->free = h->free;
- first_heap->first_bloc = h->first_bloc;
- first_heap->last_bloc = h->last_bloc;
- first_heap->bloc_start = h->bloc_start;
-
- if (first_heap->next)
- first_heap->next->prev = first_heap;
- else
- last_heap = first_heap;
- }
-
- bzero (address, size);
- }
- else /* size < 0 */
- {
- SIZE excess = (char *)first_heap->bloc_start
- - ((char *)virtual_break_value + size);
-
- address = virtual_break_value;
-
- if (r_alloc_freeze_level == 0 && excess > 2 * extra_bytes)
- {
- excess -= extra_bytes;
- first_heap->bloc_start
- = (POINTER) MEM_ROUNDUP ((char *)first_heap->bloc_start - excess);
-
- relocate_blocs (first_bloc, first_heap, first_heap->bloc_start);
-
- for (b = first_bloc; b != NIL_BLOC; b = b->next)
- {
- safe_bcopy (b->data, b->new_data, b->size);
- *b->variable = b->data = b->new_data;
- }
- }
-
- if ((char *)virtual_break_value + size < (char *)first_heap->start)
- {
- /* We found an additional space below the first heap */
- first_heap->start = (POINTER) ((char *)virtual_break_value + size);
- }
- }
-
- virtual_break_value = (POINTER) ((char *)address + size);
- break_value = (last_bloc
- ? last_bloc->data + last_bloc->size
- : first_heap->bloc_start);
- if (size < 0)
- relinquish ();
-
- return address;
-}
-
-/* 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.
-
- The allocation of 0 bytes is valid.
- In case r_alloc_freeze is set, a best fit of unused blocs could be done
- before allocating a new area. Not yet done.
-
- If we can't allocate the necessary memory, set *PTR to zero, and
- return zero. */
-
-POINTER
-r_alloc (ptr, size)
- POINTER *ptr;
- SIZE size;
-{
- register bloc_ptr new_bloc;
-
- if (! r_alloc_initialized)
- r_alloc_init ();
-
- new_bloc = get_bloc (MEM_ROUNDUP (size));
- if (new_bloc)
- {
- new_bloc->variable = ptr;
- *ptr = new_bloc->data;
- }
- else
- *ptr = 0;
-
- return *ptr;
-}
-
-/* Free a bloc of relocatable storage whose data is pointed to by PTR.
- Store 0 in *PTR to show there's no block allocated. */
-
-void
-r_alloc_free (ptr)
- register POINTER *ptr;
-{
- register bloc_ptr dead_bloc;
-
- if (! r_alloc_initialized)
- r_alloc_init ();
-
- dead_bloc = find_bloc (ptr);
- if (dead_bloc == NIL_BLOC)
- abort ();
-
- free_bloc (dead_bloc);
- *ptr = 0;
-
-#ifdef emacs
- refill_memory_reserve ();
-#endif
-}
-
-/* Given a pointer at address PTR to relocatable data, resize it to SIZE.
- Do this by shifting all blocks above this one up in memory, unless
- SIZE is less than or equal to the current bloc size, in which case
- do nothing.
-
- In case r_alloc_freeze is set, a new bloc is allocated, and the
- memory copied to it. Not very efficient. We could traverse the
- bloc_list for a best fit of free blocs first.
-
- Change *PTR to reflect the new bloc, and return this value.
-
- If more memory cannot be allocated, then leave *PTR unchanged, and
- return zero. */
-
-POINTER
-r_re_alloc (ptr, size)
- POINTER *ptr;
- SIZE size;
-{
- register bloc_ptr bloc;
-
- if (! r_alloc_initialized)
- r_alloc_init ();
-
- if (!*ptr)
- return r_alloc (ptr, size);
- if (!size)
- {
- r_alloc_free (ptr);
- return r_alloc (ptr, 0);
- }
-
- bloc = find_bloc (ptr);
- if (bloc == NIL_BLOC)
- abort ();
-
- if (size < bloc->size)
- {
- /* Wouldn't it be useful to actually resize the bloc here? */
- /* I think so too, but not if it's too expensive... */
- if ((bloc->size - MEM_ROUNDUP (size) >= page_size)
- && r_alloc_freeze_level == 0)
- {
- resize_bloc (bloc, MEM_ROUNDUP (size));
- /* Never mind if this fails, just do nothing... */
- /* It *should* be infallible! */
- }
- }
- else if (size > bloc->size)
- {
- if (r_alloc_freeze_level)
- {
- bloc_ptr new_bloc;
- new_bloc = get_bloc (MEM_ROUNDUP (size));
- if (new_bloc)
- {
- new_bloc->variable = ptr;
- *ptr = new_bloc->data;
- bloc->variable = (POINTER *) NIL;
- }
- else
- return NIL;
- }
- else
- {
- if (! resize_bloc (bloc, MEM_ROUNDUP (size)))
- return NIL;
- }
- }
- return *ptr;
-}
-
-/* Disable relocations, after making room for at least SIZE bytes
- of non-relocatable heap if possible. The relocatable blocs are
- guaranteed to hold still until thawed, even if this means that
- malloc must return a null pointer. */
-
-void
-r_alloc_freeze (size)
- long size;
-{
- if (! r_alloc_initialized)
- r_alloc_init ();
-
- /* If already frozen, we can't make any more room, so don't try. */
- if (r_alloc_freeze_level > 0)
- size = 0;
- /* If we can't get the amount requested, half is better than nothing. */
- while (size > 0 && r_alloc_sbrk (size) == 0)
- size /= 2;
- ++r_alloc_freeze_level;
- if (size > 0)
- r_alloc_sbrk (-size);
-}
-
-void
-r_alloc_thaw ()
-{
-
- if (! r_alloc_initialized)
- r_alloc_init ();
-
- if (--r_alloc_freeze_level < 0)
- abort ();
-
- /* This frees all unused blocs. It is not too inefficient, as the resize
- and bcopy is done only once. Afterwards, all unreferenced blocs are
- already shrunk to zero size. */
- if (!r_alloc_freeze_level)
- {
- bloc_ptr *b = &first_bloc;
- while (*b)
- if (!(*b)->variable)
- free_bloc (*b);
- else
- b = &(*b)->next;
- }
-}
-
-
-/* The hook `malloc' uses for the function which gets more space
- from the system. */
-extern POINTER (*__morecore) ();
-
-/* Initialize various things for memory allocation. */
-
-static void
-r_alloc_init ()
-{
- if (r_alloc_initialized)
- return;
-
- r_alloc_initialized = 1;
- real_morecore = __morecore;
- __morecore = r_alloc_sbrk;
-
- first_heap = last_heap = &heap_base;
- first_heap->next = first_heap->prev = NIL_HEAP;
- first_heap->start = first_heap->bloc_start
- = virtual_break_value = break_value = (*real_morecore) (0);
- if (break_value == NIL)
- abort ();
-
- page_size = PAGE;
- extra_bytes = ROUNDUP (50000);
-
- /* Give GNU malloc's morecore some hysteresis
- so that we move all the relocatable blocks much less often. */
- __malloc_extra_blocks = 64;
-
- first_heap->end = (POINTER) ROUNDUP (first_heap->start);
-
- /* The extra call to real_morecore guarantees that the end of the
- address space is a multiple of page_size, even if page_size is
- not really the page size of the system running the binary in
- which page_size is stored. This allows a binary to be built on a
- system with one page size and run on a system with a smaller page
- size. */
- (*real_morecore) (first_heap->end - first_heap->start);
-
- /* Clear the rest of the last page; this memory is in our address space
- even though it is after the sbrk value. */
- /* Doubly true, with the additional call that explicitly adds the
- rest of that page to the address space. */
- bzero (first_heap->start, first_heap->end - first_heap->start);
- virtual_break_value = break_value = first_heap->bloc_start = first_heap->end;
- use_relocatable_buffers = 1;
-}
-#ifdef DEBUG
-#include <assert.h>
-
-void
-r_alloc_check ()
-{
- int found = 0;
- heap_ptr h, ph = 0;
- bloc_ptr b, pb = 0;
-
- if (!r_alloc_initialized)
- return;
-
- assert (first_heap);
- assert (last_heap->end <= (POINTER) sbrk (0));
- assert ((POINTER) first_heap < first_heap->start);
- assert (first_heap->start <= virtual_break_value);
- assert (virtual_break_value <= first_heap->end);
-
- for (h = first_heap; h; h = h->next)
- {
- assert (h->prev == ph);
- assert ((POINTER) ROUNDUP (h->end) == h->end);
-#if 0 /* ??? The code in ralloc.c does not really try to ensure
- the heap start has any sort of alignment.
- Perhaps it should. */
- assert ((POINTER) MEM_ROUNDUP (h->start) == h->start);
-#endif
- assert ((POINTER) MEM_ROUNDUP (h->bloc_start) == h->bloc_start);
- assert (h->start <= h->bloc_start && h->bloc_start <= h->end);
-
- if (ph)
- {
- assert (ph->end < h->start);
- assert (h->start <= (POINTER)h && (POINTER)(h+1) <= h->bloc_start);
- }
-
- if (h->bloc_start <= break_value && break_value <= h->end)
- found = 1;
-
- ph = h;
- }
-
- assert (found);
- assert (last_heap == ph);
-
- for (b = first_bloc; b; b = b->next)
- {
- assert (b->prev == pb);
- assert ((POINTER) MEM_ROUNDUP (b->data) == b->data);
- assert ((SIZE) MEM_ROUNDUP (b->size) == b->size);
-
- ph = 0;
- for (h = first_heap; h; h = h->next)
- {
- if (h->bloc_start <= b->data && b->data + b->size <= h->end)
- break;
- ph = h;
- }
-
- assert (h);
-
- if (pb && pb->data + pb->size != b->data)
- {
- assert (ph && b->data == h->bloc_start);
- while (ph)
- {
- if (ph->bloc_start <= pb->data
- && pb->data + pb->size <= ph->end)
- {
- assert (pb->data + pb->size + b->size > ph->end);
- break;
- }
- else
- {
- assert (ph->bloc_start + b->size > ph->end);
- }
- ph = ph->prev;
- }
- }
- pb = b;
- }
-
- assert (last_bloc == pb);
-
- if (last_bloc)
- assert (last_bloc->data + last_bloc->size == break_value);
- else
- assert (first_heap->bloc_start == break_value);
-}
-#endif /* DEBUG */
diff --git a/src/regex.c b/src/regex.c
deleted file mode 100644
index e26641bfcd9..00000000000
--- a/src/regex.c
+++ /dev/null
@@ -1,5512 +0,0 @@
-/* Extended regular expression matching and search library, version
- 0.12. (Implements POSIX draft P10003.2/D11.2, except for
- internationalization features.)
-
- Copyright (C) 1993, 1994, 1995, 1996 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 2, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- USA. */
-
-/* AIX requires this to be the first thing in the file. */
-#if defined (_AIX) && !defined (REGEX_MALLOC)
- #pragma alloca
-#endif
-
-#undef _GNU_SOURCE
-#define _GNU_SOURCE
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-/* We need this for `regex.h', and perhaps for the Emacs include files. */
-#include <sys/types.h>
-
-/* This is for other GNU distributions with internationalized messages. */
-#if HAVE_LIBINTL_H || defined (_LIBC)
-# include <libintl.h>
-#else
-# define gettext(msgid) (msgid)
-#endif
-
-#ifndef gettext_noop
-/* This define is so xgettext can find the internationalizable
- strings. */
-#define gettext_noop(String) String
-#endif
-
-/* The `emacs' switch turns on certain matching commands
- that make sense only in Emacs. */
-#ifdef emacs
-
-#include "lisp.h"
-#include "buffer.h"
-#include "syntax.h"
-
-#define malloc xmalloc
-#define free xfree
-
-#else /* not emacs */
-
-/* If we are not linking with Emacs proper,
- we can't use the relocating allocator
- even if config.h says that we can. */
-#undef REL_ALLOC
-
-#if defined (STDC_HEADERS) || defined (_LIBC)
-#include <stdlib.h>
-#else
-char *malloc ();
-char *realloc ();
-#endif
-
-/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow.
- If nothing else has been done, use the method below. */
-#ifdef INHIBIT_STRING_HEADER
-#if !(defined (HAVE_BZERO) && defined (HAVE_BCOPY))
-#if !defined (bzero) && !defined (bcopy)
-#undef INHIBIT_STRING_HEADER
-#endif
-#endif
-#endif
-
-/* This is the normal way of making sure we have a bcopy and a bzero.
- This is used in most programs--a few other programs avoid this
- by defining INHIBIT_STRING_HEADER. */
-#ifndef INHIBIT_STRING_HEADER
-#if defined (HAVE_STRING_H) || defined (STDC_HEADERS) || defined (_LIBC)
-#include <string.h>
-#ifndef bcmp
-#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
-#endif
-#ifndef bcopy
-#define bcopy(s, d, n) memcpy ((d), (s), (n))
-#endif
-#ifndef bzero
-#define bzero(s, n) memset ((s), 0, (n))
-#endif
-#else
-#include <strings.h>
-#endif
-#endif
-
-/* Define the syntax stuff for \<, \>, etc. */
-
-/* This must be nonzero for the wordchar and notwordchar pattern
- commands in re_match_2. */
-#ifndef Sword
-#define Sword 1
-#endif
-
-#ifdef SWITCH_ENUM_BUG
-#define SWITCH_ENUM_CAST(x) ((int)(x))
-#else
-#define SWITCH_ENUM_CAST(x) (x)
-#endif
-
-#ifdef SYNTAX_TABLE
-
-extern char *re_syntax_table;
-
-#else /* not SYNTAX_TABLE */
-
-/* How many characters in the character set. */
-#define CHAR_SET_SIZE 256
-
-static char re_syntax_table[CHAR_SET_SIZE];
-
-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;
-
- re_syntax_table['_'] = Sword;
-
- done = 1;
-}
-
-#endif /* not SYNTAX_TABLE */
-
-#define SYNTAX(c) re_syntax_table[c]
-
-#endif /* not emacs */
-
-/* Get the interface, including the syntax bits. */
-#include "regex.h"
-
-/* isalpha etc. are used for the character classes. */
-#include <ctype.h>
-
-/* Jim Meyering writes:
-
- "... Some ctype macros are valid only for character codes that
- isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when
- using /bin/cc or gcc but without giving an ansi option). So, all
- ctype uses should be through macros like ISPRINT... If
- STDC_HEADERS is defined, then autoconf has verified that the ctype
- macros don't need to be guarded with references to isascii. ...
- Defining isascii to 1 should let any compiler worth its salt
- eliminate the && through constant folding." */
-
-#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
-#define ISASCII(c) 1
-#else
-#define ISASCII(c) isascii(c)
-#endif
-
-#ifdef isblank
-#define ISBLANK(c) (ISASCII (c) && isblank (c))
-#else
-#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
-#endif
-#ifdef isgraph
-#define ISGRAPH(c) (ISASCII (c) && isgraph (c))
-#else
-#define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
-#endif
-
-#define ISPRINT(c) (ISASCII (c) && isprint (c))
-#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
-#define ISALNUM(c) (ISASCII (c) && isalnum (c))
-#define ISALPHA(c) (ISASCII (c) && isalpha (c))
-#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
-#define ISLOWER(c) (ISASCII (c) && islower (c))
-#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
-#define ISSPACE(c) (ISASCII (c) && isspace (c))
-#define ISUPPER(c) (ISASCII (c) && isupper (c))
-#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
-
-#ifndef NULL
-#define NULL (void *)0
-#endif
-
-/* We remove any previous definition of `SIGN_EXTEND_CHAR',
- since ours (we hope) works properly with all combinations of
- machines, compilers, `char' and `unsigned char' argument types.
- (Per Bothner suggested the basic approach.) */
-#undef SIGN_EXTEND_CHAR
-#if __STDC__
-#define SIGN_EXTEND_CHAR(c) ((signed char) (c))
-#else /* not __STDC__ */
-/* As in Harbison and Steele. */
-#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
-#endif
-
-/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we
- use `alloca' instead of `malloc'. This is because using malloc in
- re_search* or re_match* could cause memory leaks when C-g is used in
- Emacs; also, malloc is slower and causes storage fragmentation. On
- the other hand, malloc is more portable, and easier to debug.
-
- Because we sometimes use alloca, some routines have to be macros,
- not functions -- `alloca'-allocated space disappears at the end of the
- function it is called in. */
-
-#ifdef REGEX_MALLOC
-
-#define REGEX_ALLOCATE malloc
-#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
-#define REGEX_FREE free
-
-#else /* not REGEX_MALLOC */
-
-/* Emacs already defines alloca, sometimes. */
-#ifndef alloca
-
-/* Make alloca work the best possible way. */
-#ifdef __GNUC__
-#define alloca __builtin_alloca
-#else /* not __GNUC__ */
-#if HAVE_ALLOCA_H
-#include <alloca.h>
-#else /* not __GNUC__ or HAVE_ALLOCA_H */
-#if 0 /* It is a bad idea to declare alloca. We always cast the result. */
-#ifndef _AIX /* Already did AIX, up at the top. */
-char *alloca ();
-#endif /* not _AIX */
-#endif
-#endif /* not HAVE_ALLOCA_H */
-#endif /* not __GNUC__ */
-
-#endif /* not alloca */
-
-#define REGEX_ALLOCATE alloca
-
-/* Assumes a `char *destination' variable. */
-#define REGEX_REALLOCATE(source, osize, nsize) \
- (destination = (char *) alloca (nsize), \
- bcopy (source, destination, osize), \
- destination)
-
-/* No need to do anything to free, after alloca. */
-#define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */
-
-#endif /* not REGEX_MALLOC */
-
-/* Define how to allocate the failure stack. */
-
-#if defined (REL_ALLOC) && defined (REGEX_MALLOC)
-
-#define REGEX_ALLOCATE_STACK(size) \
- r_alloc (&failure_stack_ptr, (size))
-#define REGEX_REALLOCATE_STACK(source, osize, nsize) \
- r_re_alloc (&failure_stack_ptr, (nsize))
-#define REGEX_FREE_STACK(ptr) \
- r_alloc_free (&failure_stack_ptr)
-
-#else /* not using relocating allocator */
-
-#ifdef REGEX_MALLOC
-
-#define REGEX_ALLOCATE_STACK malloc
-#define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
-#define REGEX_FREE_STACK free
-
-#else /* not REGEX_MALLOC */
-
-#define REGEX_ALLOCATE_STACK alloca
-
-#define REGEX_REALLOCATE_STACK(source, osize, nsize) \
- REGEX_REALLOCATE (source, osize, nsize)
-/* No need to explicitly free anything. */
-#define REGEX_FREE_STACK(arg)
-
-#endif /* not REGEX_MALLOC */
-#endif /* not using relocating allocator */
-
-
-/* True if `size1' is non-NULL and PTR is pointing anywhere inside
- `string1' or just past its end. This works if PTR is NULL, which is
- a good thing. */
-#define FIRST_STRING_P(ptr) \
- (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
-
-/* (Re)Allocate N items of type T using malloc, or fail. */
-#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
-#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
-#define RETALLOC_IF(addr, n, t) \
- if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t)
-#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
-
-#define BYTEWIDTH 8 /* In bits. */
-
-#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
-
-#undef MAX
-#undef MIN
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-
-typedef char boolean;
-#define false 0
-#define true 1
-
-static int re_match_2_internal ();
-
-/* These are the command codes that appear in compiled regular
- expressions. Some opcodes are followed by argument bytes. A
- command code can specify any interpretation whatsoever for its
- arguments. Zero bytes may appear in the compiled regular expression. */
-
-typedef enum
-{
- no_op = 0,
-
- /* Succeed right away--no more backtracking. */
- succeed,
-
- /* Followed by one byte giving n, then by n literal bytes. */
- exactn,
-
- /* Matches any (more or less) character. */
- anychar,
-
- /* Matches any one char belonging to specified set. First
- following byte is number of bitmap bytes. Then come bytes
- for a bitmap 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,
-
- /* Same parameters as charset, but match any character that is
- not one of those specified. */
- charset_not,
-
- /* Start remembering the text that is matched, for storing in a
- register. Followed by one byte with the register number, in
- the range 0 to one less than the pattern buffer's re_nsub
- field. Then followed by one byte with the number of groups
- inner to this one. (This last has to be part of the
- start_memory only because we need it in the on_failure_jump
- of re_match_2.) */
- start_memory,
-
- /* Stop remembering the text that is matched and store it in a
- memory register. Followed by one byte with the register
- number, in the range 0 to one less than `re_nsub' in the
- pattern buffer, and one byte with the number of inner groups,
- just like `start_memory'. (We need the number of inner
- groups here because we don't have any easy way of finding the
- corresponding start_memory when we're at a stop_memory.) */
- stop_memory,
-
- /* Match a duplicate of something remembered. Followed by one
- byte containing the register number. */
- duplicate,
-
- /* Fail unless at beginning of line. */
- begline,
-
- /* Fail unless at end of line. */
- endline,
-
- /* Succeeds if at beginning of buffer (if emacs) or at beginning
- of string to be matched (if not). */
- begbuf,
-
- /* Analogously, for end of buffer/string. */
- endbuf,
-
- /* Followed by two byte relative address to which to jump. */
- jump,
-
- /* Same as jump, but marks the end of an alternative. */
- jump_past_alt,
-
- /* Followed by two-byte relative address of place to resume at
- in case of failure. */
- on_failure_jump,
-
- /* Like on_failure_jump, but pushes a placeholder instead of the
- current string position when executed. */
- on_failure_keep_string_jump,
-
- /* Throw away latest failure point and then jump to following
- two-byte relative address. */
- pop_failure_jump,
-
- /* Change to pop_failure_jump if know won't have to backtrack to
- match; otherwise change to jump. This is used to jump
- back to the beginning of a repeat. If what follows this jump
- clearly won't match what the repeat does, such that we can be
- sure that there is no use backtracking out of repetitions
- already matched, then we change it to a pop_failure_jump.
- Followed by two-byte address. */
- maybe_pop_jump,
-
- /* Jump to following two-byte address, 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. Also used as an intermediary kind
- of jump when compiling an alternative. */
- dummy_failure_jump,
-
- /* Push a dummy failure point and continue. Used at the end of
- alternatives. */
- push_dummy_failure,
-
- /* Followed by two-byte relative address and two-byte number n.
- After matching N times, jump to the address upon failure. */
- succeed_n,
-
- /* Followed by two-byte relative address, and two-byte number n.
- Jump to the address N times, then fail. */
- jump_n,
-
- /* Set the following two-byte relative address to the
- subsequent two-byte number. The address *includes* the two
- bytes of number. */
- set_number_at,
-
- 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. */
-
-#ifdef emacs
- ,before_dot, /* Succeeds if before point. */
- at_dot, /* Succeeds if at point. */
- after_dot, /* Succeeds if after point. */
-
- /* Matches any character whose syntax is specified. Followed by
- a byte which contains a syntax code, e.g., Sword. */
- syntaxspec,
-
- /* Matches any character whose syntax is not that specified. */
- notsyntaxspec
-#endif /* emacs */
-} re_opcode_t;
-
-/* Common operations on the compiled pattern. */
-
-/* Store NUMBER in two contiguous bytes starting at DESTINATION. */
-
-#define STORE_NUMBER(destination, number) \
- do { \
- (destination)[0] = (number) & 0377; \
- (destination)[1] = (number) >> 8; \
- } while (0)
-
-/* Same as STORE_NUMBER, except increment DESTINATION to
- the byte after where the number is stored. Therefore, DESTINATION
- must be an lvalue. */
-
-#define STORE_NUMBER_AND_INCR(destination, number) \
- do { \
- STORE_NUMBER (destination, number); \
- (destination) += 2; \
- } while (0)
-
-/* Put into DESTINATION a number stored in two contiguous bytes starting
- at SOURCE. */
-
-#define EXTRACT_NUMBER(destination, source) \
- do { \
- (destination) = *(source) & 0377; \
- (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \
- } while (0)
-
-#ifdef DEBUG
-static void
-extract_number (dest, source)
- int *dest;
- unsigned char *source;
-{
- int temp = SIGN_EXTEND_CHAR (*(source + 1));
- *dest = *source & 0377;
- *dest += temp << 8;
-}
-
-#ifndef EXTRACT_MACROS /* To debug the macros. */
-#undef EXTRACT_NUMBER
-#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
-#endif /* not EXTRACT_MACROS */
-
-#endif /* DEBUG */
-
-/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
- SOURCE must be an lvalue. */
-
-#define EXTRACT_NUMBER_AND_INCR(destination, source) \
- do { \
- EXTRACT_NUMBER (destination, source); \
- (source) += 2; \
- } while (0)
-
-#ifdef DEBUG
-static void
-extract_number_and_incr (destination, source)
- int *destination;
- unsigned char **source;
-{
- extract_number (destination, *source);
- *source += 2;
-}
-
-#ifndef EXTRACT_MACROS
-#undef EXTRACT_NUMBER_AND_INCR
-#define EXTRACT_NUMBER_AND_INCR(dest, src) \
- extract_number_and_incr (&dest, &src)
-#endif /* not EXTRACT_MACROS */
-
-#endif /* DEBUG */
-
-/* If DEBUG is defined, Regex prints many voluminous messages about what
- it is doing (if the variable `debug' is nonzero). If linked with the
- main program in `iregex.c', you can enter patterns and strings
- interactively. And if linked with the main program in `main.c' and
- the other test files, you can run the already-written tests. */
-
-#ifdef DEBUG
-
-/* We use standard I/O for debugging. */
-#include <stdio.h>
-
-/* It is useful to test things that ``must'' be true when debugging. */
-#include <assert.h>
-
-static int debug = 0;
-
-#define DEBUG_STATEMENT(e) e
-#define DEBUG_PRINT1(x) if (debug) printf (x)
-#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
-#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
-#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
-#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
- if (debug) print_partial_compiled_pattern (s, e)
-#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
- if (debug) print_double_string (w, s1, sz1, s2, sz2)
-
-
-/* Print the fastmap in human-readable form. */
-
-void
-print_fastmap (fastmap)
- char *fastmap;
-{
- unsigned was_a_range = 0;
- unsigned i = 0;
-
- while (i < (1 << BYTEWIDTH))
- {
- if (fastmap[i++])
- {
- was_a_range = 0;
- putchar (i - 1);
- while (i < (1 << BYTEWIDTH) && fastmap[i])
- {
- was_a_range = 1;
- i++;
- }
- if (was_a_range)
- {
- printf ("-");
- putchar (i - 1);
- }
- }
- }
- putchar ('\n');
-}
-
-
-/* Print a compiled pattern string in human-readable form, starting at
- the START pointer into it and ending just before the pointer END. */
-
-void
-print_partial_compiled_pattern (start, end)
- unsigned char *start;
- unsigned char *end;
-{
- int mcnt, mcnt2;
- unsigned char *p = start;
- unsigned char *pend = end;
-
- if (start == NULL)
- {
- printf ("(null)\n");
- return;
- }
-
- /* Loop over pattern commands. */
- while (p < pend)
- {
- printf ("%d:\t", p - start);
-
- switch ((re_opcode_t) *p++)
- {
- case no_op:
- printf ("/no_op");
- break;
-
- case exactn:
- mcnt = *p++;
- printf ("/exactn/%d", mcnt);
- do
- {
- putchar ('/');
- putchar (*p++);
- }
- while (--mcnt);
- break;
-
- case start_memory:
- mcnt = *p++;
- printf ("/start_memory/%d/%d", mcnt, *p++);
- break;
-
- case stop_memory:
- mcnt = *p++;
- printf ("/stop_memory/%d/%d", mcnt, *p++);
- break;
-
- case duplicate:
- printf ("/duplicate/%d", *p++);
- break;
-
- case anychar:
- printf ("/anychar");
- break;
-
- case charset:
- case charset_not:
- {
- register int c, last = -100;
- register int in_range = 0;
-
- printf ("/charset [%s",
- (re_opcode_t) *(p - 1) == charset_not ? "^" : "");
-
- assert (p + *p < pend);
-
- for (c = 0; c < 256; c++)
- if (c / 8 < *p
- && (p[1 + (c/8)] & (1 << (c % 8))))
- {
- /* Are we starting a range? */
- if (last + 1 == c && ! in_range)
- {
- putchar ('-');
- in_range = 1;
- }
- /* Have we broken a range? */
- else if (last + 1 != c && in_range)
- {
- putchar (last);
- in_range = 0;
- }
-
- if (! in_range)
- putchar (c);
-
- last = c;
- }
-
- if (in_range)
- putchar (last);
-
- putchar (']');
-
- p += 1 + *p;
- }
- break;
-
- case begline:
- printf ("/begline");
- break;
-
- case endline:
- printf ("/endline");
- break;
-
- case on_failure_jump:
- extract_number_and_incr (&mcnt, &p);
- printf ("/on_failure_jump to %d", p + mcnt - start);
- break;
-
- case on_failure_keep_string_jump:
- extract_number_and_incr (&mcnt, &p);
- printf ("/on_failure_keep_string_jump to %d", p + mcnt - start);
- break;
-
- case dummy_failure_jump:
- extract_number_and_incr (&mcnt, &p);
- printf ("/dummy_failure_jump to %d", p + mcnt - start);
- break;
-
- case push_dummy_failure:
- printf ("/push_dummy_failure");
- break;
-
- case maybe_pop_jump:
- extract_number_and_incr (&mcnt, &p);
- printf ("/maybe_pop_jump to %d", p + mcnt - start);
- break;
-
- case pop_failure_jump:
- extract_number_and_incr (&mcnt, &p);
- printf ("/pop_failure_jump to %d", p + mcnt - start);
- break;
-
- case jump_past_alt:
- extract_number_and_incr (&mcnt, &p);
- printf ("/jump_past_alt to %d", p + mcnt - start);
- break;
-
- case jump:
- extract_number_and_incr (&mcnt, &p);
- printf ("/jump to %d", p + mcnt - start);
- break;
-
- case succeed_n:
- extract_number_and_incr (&mcnt, &p);
- extract_number_and_incr (&mcnt2, &p);
- printf ("/succeed_n to %d, %d times", p + mcnt - start, mcnt2);
- break;
-
- case jump_n:
- extract_number_and_incr (&mcnt, &p);
- extract_number_and_incr (&mcnt2, &p);
- printf ("/jump_n to %d, %d times", p + mcnt - start, mcnt2);
- break;
-
- case set_number_at:
- extract_number_and_incr (&mcnt, &p);
- extract_number_and_incr (&mcnt2, &p);
- printf ("/set_number_at location %d to %d", p + mcnt - start, mcnt2);
- break;
-
- case wordbound:
- printf ("/wordbound");
- break;
-
- case notwordbound:
- printf ("/notwordbound");
- break;
-
- case wordbeg:
- printf ("/wordbeg");
- break;
-
- case wordend:
- printf ("/wordend");
-
-#ifdef emacs
- case before_dot:
- printf ("/before_dot");
- break;
-
- case at_dot:
- printf ("/at_dot");
- break;
-
- case after_dot:
- printf ("/after_dot");
- break;
-
- case syntaxspec:
- printf ("/syntaxspec");
- mcnt = *p++;
- printf ("/%d", mcnt);
- break;
-
- case notsyntaxspec:
- printf ("/notsyntaxspec");
- mcnt = *p++;
- printf ("/%d", mcnt);
- break;
-#endif /* emacs */
-
- case wordchar:
- printf ("/wordchar");
- break;
-
- case notwordchar:
- printf ("/notwordchar");
- break;
-
- case begbuf:
- printf ("/begbuf");
- break;
-
- case endbuf:
- printf ("/endbuf");
- break;
-
- default:
- printf ("?%d", *(p-1));
- }
-
- putchar ('\n');
- }
-
- printf ("%d:\tend of pattern.\n", p - start);
-}
-
-
-void
-print_compiled_pattern (bufp)
- struct re_pattern_buffer *bufp;
-{
- unsigned char *buffer = bufp->buffer;
-
- print_partial_compiled_pattern (buffer, buffer + bufp->used);
- printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated);
-
- if (bufp->fastmap_accurate && bufp->fastmap)
- {
- printf ("fastmap: ");
- print_fastmap (bufp->fastmap);
- }
-
- printf ("re_nsub: %d\t", bufp->re_nsub);
- printf ("regs_alloc: %d\t", bufp->regs_allocated);
- printf ("can_be_null: %d\t", bufp->can_be_null);
- printf ("newline_anchor: %d\n", bufp->newline_anchor);
- printf ("no_sub: %d\t", bufp->no_sub);
- printf ("not_bol: %d\t", bufp->not_bol);
- printf ("not_eol: %d\t", bufp->not_eol);
- printf ("syntax: %d\n", bufp->syntax);
- /* Perhaps we should print the translate table? */
-}
-
-
-void
-print_double_string (where, string1, size1, string2, size2)
- const char *where;
- const char *string1;
- const char *string2;
- int size1;
- int size2;
-{
- unsigned this_char;
-
- if (where == NULL)
- printf ("(null)");
- else
- {
- if (FIRST_STRING_P (where))
- {
- for (this_char = where - string1; this_char < size1; this_char++)
- putchar (string1[this_char]);
-
- where = string2;
- }
-
- for (this_char = where - string2; this_char < size2; this_char++)
- putchar (string2[this_char]);
- }
-}
-
-#else /* not DEBUG */
-
-#undef assert
-#define assert(e)
-
-#define DEBUG_STATEMENT(e)
-#define DEBUG_PRINT1(x)
-#define DEBUG_PRINT2(x1, x2)
-#define DEBUG_PRINT3(x1, x2, x3)
-#define DEBUG_PRINT4(x1, x2, x3, x4)
-#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
-#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
-
-#endif /* not DEBUG */
-
-/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can
- also be assigned to arbitrarily: each pattern buffer stores its own
- syntax, so it can be changed between regex compilations. */
-/* This has no initializer because initialized variables in Emacs
- become read-only after dumping. */
-reg_syntax_t re_syntax_options;
-
-
-/* Specify the precise syntax of regexps for compilation. This provides
- for compatibility for various utilities which historically have
- different, incompatible syntaxes.
-
- The argument SYNTAX is a bit mask comprised of the various bits
- defined in regex.h. We return the old syntax. */
-
-reg_syntax_t
-re_set_syntax (syntax)
- reg_syntax_t syntax;
-{
- reg_syntax_t ret = re_syntax_options;
-
- re_syntax_options = syntax;
- return ret;
-}
-
-/* This table gives an error message for each of the error codes listed
- in regex.h. Obviously the order here has to be same as there.
- POSIX doesn't require that we do anything for REG_NOERROR,
- but why not be nice? */
-
-static const char *re_error_msgid[] =
- {
- gettext_noop ("Success"), /* REG_NOERROR */
- gettext_noop ("No match"), /* REG_NOMATCH */
- gettext_noop ("Invalid regular expression"), /* REG_BADPAT */
- gettext_noop ("Invalid collation character"), /* REG_ECOLLATE */
- gettext_noop ("Invalid character class name"), /* REG_ECTYPE */
- gettext_noop ("Trailing backslash"), /* REG_EESCAPE */
- gettext_noop ("Invalid back reference"), /* REG_ESUBREG */
- gettext_noop ("Unmatched [ or [^"), /* REG_EBRACK */
- gettext_noop ("Unmatched ( or \\("), /* REG_EPAREN */
- gettext_noop ("Unmatched \\{"), /* REG_EBRACE */
- gettext_noop ("Invalid content of \\{\\}"), /* REG_BADBR */
- gettext_noop ("Invalid range end"), /* REG_ERANGE */
- gettext_noop ("Memory exhausted"), /* REG_ESPACE */
- gettext_noop ("Invalid preceding regular expression"), /* REG_BADRPT */
- gettext_noop ("Premature end of regular expression"), /* REG_EEND */
- gettext_noop ("Regular expression too big"), /* REG_ESIZE */
- gettext_noop ("Unmatched ) or \\)"), /* REG_ERPAREN */
- };
-
-/* Avoiding alloca during matching, to placate r_alloc. */
-
-/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the
- searching and matching functions should not call alloca. On some
- systems, alloca is implemented in terms of malloc, and if we're
- using the relocating allocator routines, then malloc could cause a
- relocation, which might (if the strings being searched are in the
- ralloc heap) shift the data out from underneath the regexp
- routines.
-
- Here's another reason to avoid allocation: Emacs
- processes input from X in a signal handler; processing X input may
- call malloc; if input arrives while a matching routine is calling
- malloc, then we're scrod. But Emacs can't just block input while
- calling matching routines; then we don't notice interrupts when
- they come in. So, Emacs blocks input around all regexp calls
- except the matching calls, which it leaves unprotected, in the
- faith that they will not malloc. */
-
-/* Normally, this is fine. */
-#define MATCH_MAY_ALLOCATE
-
-/* When using GNU C, we are not REALLY using the C alloca, no matter
- what config.h may say. So don't take precautions for it. */
-#ifdef __GNUC__
-#undef C_ALLOCA
-#endif
-
-/* The match routines may not allocate if (1) they would do it with malloc
- and (2) it's not safe for them to use malloc.
- Note that if REL_ALLOC is defined, matching would not use malloc for the
- failure stack, but we would still use it for the register vectors;
- so REL_ALLOC should not affect this. */
-#if (defined (C_ALLOCA) || defined (REGEX_MALLOC)) && defined (emacs)
-#undef MATCH_MAY_ALLOCATE
-#endif
-
-
-/* Failure stack declarations and macros; both re_compile_fastmap and
- re_match_2 use a failure stack. These have to be macros because of
- REGEX_ALLOCATE_STACK. */
-
-
-/* Number of failure points for which to initially allocate space
- when matching. If this number is exceeded, we allocate more
- space, so it is not a hard limit. */
-#ifndef INIT_FAILURE_ALLOC
-#define INIT_FAILURE_ALLOC 5
-#endif
-
-/* Roughly the maximum number of failure points on the stack. Would be
- exactly that if always used MAX_FAILURE_ITEMS items each time we failed.
- This is a variable only so users of regex can assign to it; we never
- change it ourselves. */
-#if defined (MATCH_MAY_ALLOCATE)
-/* 4400 was enough to cause a crash on Alpha OSF/1,
- whose default stack limit is 2mb. */
-int re_max_failures = 20000;
-#else
-int re_max_failures = 2000;
-#endif
-
-union fail_stack_elt
-{
- unsigned char *pointer;
- int integer;
-};
-
-typedef union fail_stack_elt fail_stack_elt_t;
-
-typedef struct
-{
- fail_stack_elt_t *stack;
- unsigned size;
- unsigned avail; /* Offset of next open position. */
-} fail_stack_type;
-
-#define FAIL_STACK_EMPTY() (fail_stack.avail == 0)
-#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
-#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size)
-
-
-/* Define macros to initialize and free the failure stack.
- Do `return -2' if the alloc fails. */
-
-#ifdef MATCH_MAY_ALLOCATE
-#define INIT_FAIL_STACK() \
- do { \
- fail_stack.stack = (fail_stack_elt_t *) \
- REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \
- \
- if (fail_stack.stack == NULL) \
- return -2; \
- \
- fail_stack.size = INIT_FAILURE_ALLOC; \
- fail_stack.avail = 0; \
- } while (0)
-
-#define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack)
-#else
-#define INIT_FAIL_STACK() \
- do { \
- fail_stack.avail = 0; \
- } while (0)
-
-#define RESET_FAIL_STACK()
-#endif
-
-
-/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
-
- Return 1 if succeeds, and 0 if either ran out of memory
- allocating space for it or it was already too large.
-
- REGEX_REALLOCATE_STACK requires `destination' be declared. */
-
-#define DOUBLE_FAIL_STACK(fail_stack) \
- ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \
- ? 0 \
- : ((fail_stack).stack = (fail_stack_elt_t *) \
- REGEX_REALLOCATE_STACK ((fail_stack).stack, \
- (fail_stack).size * sizeof (fail_stack_elt_t), \
- ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \
- \
- (fail_stack).stack == NULL \
- ? 0 \
- : ((fail_stack).size <<= 1, \
- 1)))
-
-
-/* Push pointer POINTER on FAIL_STACK.
- Return 1 if was able to do so and 0 if ran out of memory allocating
- space to do so. */
-#define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \
- ((FAIL_STACK_FULL () \
- && !DOUBLE_FAIL_STACK (FAIL_STACK)) \
- ? 0 \
- : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \
- 1))
-
-/* Push a pointer value onto the failure stack.
- Assumes the variable `fail_stack'. Probably should only
- be called from within `PUSH_FAILURE_POINT'. */
-#define PUSH_FAILURE_POINTER(item) \
- fail_stack.stack[fail_stack.avail++].pointer = (unsigned char *) (item)
-
-/* This pushes an integer-valued item onto the failure stack.
- Assumes the variable `fail_stack'. Probably should only
- be called from within `PUSH_FAILURE_POINT'. */
-#define PUSH_FAILURE_INT(item) \
- fail_stack.stack[fail_stack.avail++].integer = (item)
-
-/* Push a fail_stack_elt_t value onto the failure stack.
- Assumes the variable `fail_stack'. Probably should only
- be called from within `PUSH_FAILURE_POINT'. */
-#define PUSH_FAILURE_ELT(item) \
- fail_stack.stack[fail_stack.avail++] = (item)
-
-/* These three POP... operations complement the three PUSH... operations.
- All assume that `fail_stack' is nonempty. */
-#define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer
-#define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer
-#define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail]
-
-/* Used to omit pushing failure point id's when we're not debugging. */
-#ifdef DEBUG
-#define DEBUG_PUSH PUSH_FAILURE_INT
-#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT ()
-#else
-#define DEBUG_PUSH(item)
-#define DEBUG_POP(item_addr)
-#endif
-
-
-/* Push the information about the state we will need
- if we ever fail back to it.
-
- Requires variables fail_stack, regstart, regend, reg_info, and
- num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be
- declared.
-
- Does `return FAILURE_CODE' if runs out of memory. */
-
-#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \
- do { \
- char *destination; \
- /* Must be int, so when we don't save any registers, the arithmetic \
- of 0 + -1 isn't done as unsigned. */ \
- int this_reg; \
- \
- DEBUG_STATEMENT (failure_id++); \
- DEBUG_STATEMENT (nfailure_points_pushed++); \
- DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \
- DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\
- DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\
- \
- DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \
- DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \
- \
- /* Ensure we have enough space allocated for what we will push. */ \
- while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \
- { \
- if (!DOUBLE_FAIL_STACK (fail_stack)) \
- return failure_code; \
- \
- DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \
- (fail_stack).size); \
- DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\
- } \
- \
- /* Push the info, starting with the registers. */ \
- DEBUG_PRINT1 ("\n"); \
- \
- if (1) \
- for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
- this_reg++) \
- { \
- DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \
- DEBUG_STATEMENT (num_regs_pushed++); \
- \
- DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \
- PUSH_FAILURE_POINTER (regstart[this_reg]); \
- \
- DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \
- PUSH_FAILURE_POINTER (regend[this_reg]); \
- \
- DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \
- DEBUG_PRINT2 (" match_null=%d", \
- REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \
- DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \
- DEBUG_PRINT2 (" matched_something=%d", \
- MATCHED_SOMETHING (reg_info[this_reg])); \
- DEBUG_PRINT2 (" ever_matched=%d", \
- EVER_MATCHED_SOMETHING (reg_info[this_reg])); \
- DEBUG_PRINT1 ("\n"); \
- PUSH_FAILURE_ELT (reg_info[this_reg].word); \
- } \
- \
- DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\
- PUSH_FAILURE_INT (lowest_active_reg); \
- \
- DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\
- PUSH_FAILURE_INT (highest_active_reg); \
- \
- DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \
- DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \
- PUSH_FAILURE_POINTER (pattern_place); \
- \
- DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \
- DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \
- size2); \
- DEBUG_PRINT1 ("'\n"); \
- PUSH_FAILURE_POINTER (string_place); \
- \
- DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \
- DEBUG_PUSH (failure_id); \
- } while (0)
-
-/* This is the number of items that are pushed and popped on the stack
- for each register. */
-#define NUM_REG_ITEMS 3
-
-/* Individual items aside from the registers. */
-#ifdef DEBUG
-#define NUM_NONREG_ITEMS 5 /* Includes failure point id. */
-#else
-#define NUM_NONREG_ITEMS 4
-#endif
-
-/* We push at most this many items on the stack. */
-/* We used to use (num_regs - 1), which is the number of registers
- this regexp will save; but that was changed to 5
- to avoid stack overflow for a regexp with lots of parens. */
-#define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
-
-/* We actually push this many items. */
-#define NUM_FAILURE_ITEMS \
- (((0 \
- ? 0 : highest_active_reg - lowest_active_reg + 1) \
- * NUM_REG_ITEMS) \
- + NUM_NONREG_ITEMS)
-
-/* How many items can still be added to the stack without overflowing it. */
-#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
-
-
-/* Pops what PUSH_FAIL_STACK pushes.
-
- We restore into the parameters, all of which should be lvalues:
- STR -- the saved data position.
- PAT -- the saved pattern position.
- LOW_REG, HIGH_REG -- the highest and lowest active registers.
- REGSTART, REGEND -- arrays of string positions.
- REG_INFO -- array of information about each subexpression.
-
- Also assumes the variables `fail_stack' and (if debugging), `bufp',
- `pend', `string1', `size1', `string2', and `size2'. */
-
-#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
-{ \
- DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \
- int this_reg; \
- const unsigned char *string_temp; \
- \
- assert (!FAIL_STACK_EMPTY ()); \
- \
- /* Remove failure points and point to how many regs pushed. */ \
- DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \
- DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \
- DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \
- \
- assert (fail_stack.avail >= NUM_NONREG_ITEMS); \
- \
- DEBUG_POP (&failure_id); \
- DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \
- \
- /* If the saved string location is NULL, it came from an \
- on_failure_keep_string_jump opcode, and we want to throw away the \
- saved NULL, thus retaining our current position in the string. */ \
- string_temp = POP_FAILURE_POINTER (); \
- if (string_temp != NULL) \
- str = (const char *) string_temp; \
- \
- DEBUG_PRINT2 (" Popping string 0x%x: `", str); \
- DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \
- DEBUG_PRINT1 ("'\n"); \
- \
- pat = (unsigned char *) POP_FAILURE_POINTER (); \
- DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \
- DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \
- \
- /* Restore register info. */ \
- high_reg = (unsigned) POP_FAILURE_INT (); \
- DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \
- \
- low_reg = (unsigned) POP_FAILURE_INT (); \
- DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \
- \
- if (1) \
- for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \
- { \
- DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \
- \
- reg_info[this_reg].word = POP_FAILURE_ELT (); \
- DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \
- \
- regend[this_reg] = (const char *) POP_FAILURE_POINTER (); \
- DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \
- \
- regstart[this_reg] = (const char *) POP_FAILURE_POINTER (); \
- DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \
- } \
- else \
- { \
- for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \
- { \
- reg_info[this_reg].word.integer = 0; \
- regend[this_reg] = 0; \
- regstart[this_reg] = 0; \
- } \
- highest_active_reg = high_reg; \
- } \
- \
- set_regs_matched_done = 0; \
- DEBUG_STATEMENT (nfailure_points_popped++); \
-} /* POP_FAILURE_POINT */
-
-
-
-/* Structure for per-register (a.k.a. per-group) information.
- Other register information, such as the
- starting and ending positions (which are addresses), and the list of
- inner groups (which is a bits list) are maintained in separate
- variables.
-
- We are making a (strictly speaking) nonportable assumption here: that
- the compiler will pack our bit fields into something that fits into
- the type of `word', i.e., is something that fits into one item on the
- failure stack. */
-
-typedef union
-{
- fail_stack_elt_t word;
- struct
- {
- /* This field is one if this group can match the empty string,
- zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */
-#define MATCH_NULL_UNSET_VALUE 3
- unsigned match_null_string_p : 2;
- unsigned is_active : 1;
- unsigned matched_something : 1;
- unsigned ever_matched_something : 1;
- } bits;
-} register_info_type;
-
-#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p)
-#define IS_ACTIVE(R) ((R).bits.is_active)
-#define MATCHED_SOMETHING(R) ((R).bits.matched_something)
-#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something)
-
-
-/* Call this when have matched a real character; it sets `matched' flags
- for the subexpressions which we are currently inside. Also records
- that those subexprs have matched. */
-#define SET_REGS_MATCHED() \
- do \
- { \
- if (!set_regs_matched_done) \
- { \
- unsigned r; \
- set_regs_matched_done = 1; \
- for (r = lowest_active_reg; r <= highest_active_reg; r++) \
- { \
- MATCHED_SOMETHING (reg_info[r]) \
- = EVER_MATCHED_SOMETHING (reg_info[r]) \
- = 1; \
- } \
- } \
- } \
- while (0)
-
-/* Registers are set to a sentinel when they haven't yet matched. */
-static char reg_unset_dummy;
-#define REG_UNSET_VALUE (&reg_unset_dummy)
-#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
-
-/* Subroutine declarations and macros for regex_compile. */
-
-static void store_op1 (), store_op2 ();
-static void insert_op1 (), insert_op2 ();
-static boolean at_begline_loc_p (), at_endline_loc_p ();
-static boolean group_in_compile_stack ();
-static reg_errcode_t compile_range ();
-
-/* Fetch the next character in the uncompiled pattern---translating it
- if necessary. Also cast from a signed character in the constant
- string passed to us by the user to an unsigned char that we can use
- as an array index (in, e.g., `translate'). */
-#ifndef PATFETCH
-#define PATFETCH(c) \
- do {if (p == pend) return REG_EEND; \
- c = (unsigned char) *p++; \
- if (translate) c = (unsigned char) translate[c]; \
- } while (0)
-#endif
-
-/* Fetch the next character in the uncompiled pattern, with no
- translation. */
-#define PATFETCH_RAW(c) \
- do {if (p == pend) return REG_EEND; \
- c = (unsigned char) *p++; \
- } while (0)
-
-/* Go backwards one character in the pattern. */
-#define PATUNFETCH p--
-
-
-/* If `translate' is non-null, return translate[D], else just D. We
- cast the subscript to translate because some data is declared as
- `char *', to avoid warnings when a string constant is passed. But
- when we use a character as a subscript we must make it unsigned. */
-#ifndef TRANSLATE
-#define TRANSLATE(d) \
- (translate ? (char) translate[(unsigned char) (d)] : (d))
-#endif
-
-
-/* Macros for outputting the compiled pattern into `buffer'. */
-
-/* If the buffer isn't allocated when it comes in, use this. */
-#define INIT_BUF_SIZE 32
-
-/* Make sure we have at least N more bytes of space in buffer. */
-#define GET_BUFFER_SPACE(n) \
- while (b - bufp->buffer + (n) > bufp->allocated) \
- EXTEND_BUFFER ()
-
-/* Make sure we have one more byte of buffer space and then add C to it. */
-#define BUF_PUSH(c) \
- do { \
- GET_BUFFER_SPACE (1); \
- *b++ = (unsigned char) (c); \
- } while (0)
-
-
-/* Ensure we have two more bytes of buffer space and then append C1 and C2. */
-#define BUF_PUSH_2(c1, c2) \
- do { \
- GET_BUFFER_SPACE (2); \
- *b++ = (unsigned char) (c1); \
- *b++ = (unsigned char) (c2); \
- } while (0)
-
-
-/* As with BUF_PUSH_2, except for three bytes. */
-#define BUF_PUSH_3(c1, c2, c3) \
- do { \
- GET_BUFFER_SPACE (3); \
- *b++ = (unsigned char) (c1); \
- *b++ = (unsigned char) (c2); \
- *b++ = (unsigned char) (c3); \
- } while (0)
-
-
-/* Store a jump with opcode OP at LOC to location TO. We store a
- relative address offset by the three bytes the jump itself occupies. */
-#define STORE_JUMP(op, loc, to) \
- store_op1 (op, loc, (to) - (loc) - 3)
-
-/* Likewise, for a two-argument jump. */
-#define STORE_JUMP2(op, loc, to, arg) \
- store_op2 (op, loc, (to) - (loc) - 3, arg)
-
-/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */
-#define INSERT_JUMP(op, loc, to) \
- insert_op1 (op, loc, (to) - (loc) - 3, b)
-
-/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */
-#define INSERT_JUMP2(op, loc, to, arg) \
- insert_op2 (op, loc, (to) - (loc) - 3, arg, b)
-
-
-/* This is not an arbitrary limit: the arguments which represent offsets
- into the pattern are two bytes long. So if 2^16 bytes turns out to
- be too small, many things would have to change. */
-#define MAX_BUF_SIZE (1L << 16)
-
-
-/* Extend the buffer by twice its current size via realloc and
- reset the pointers that pointed into the old block to point to the
- correct places in the new one. If extending the buffer results in it
- being larger than MAX_BUF_SIZE, then flag memory exhausted. */
-#define EXTEND_BUFFER() \
- do { \
- unsigned char *old_buffer = bufp->buffer; \
- if (bufp->allocated == MAX_BUF_SIZE) \
- return REG_ESIZE; \
- bufp->allocated <<= 1; \
- if (bufp->allocated > MAX_BUF_SIZE) \
- bufp->allocated = MAX_BUF_SIZE; \
- bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\
- if (bufp->buffer == NULL) \
- return REG_ESPACE; \
- /* If the buffer moved, move all the pointers into it. */ \
- if (old_buffer != bufp->buffer) \
- { \
- b = (b - old_buffer) + bufp->buffer; \
- begalt = (begalt - old_buffer) + bufp->buffer; \
- if (fixup_alt_jump) \
- fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\
- if (laststart) \
- laststart = (laststart - old_buffer) + bufp->buffer; \
- if (pending_exact) \
- pending_exact = (pending_exact - old_buffer) + bufp->buffer; \
- } \
- } while (0)
-
-
-/* Since we have one byte reserved for the register number argument to
- {start,stop}_memory, the maximum number of groups we can report
- things about is what fits in that byte. */
-#define MAX_REGNUM 255
-
-/* But patterns can have more than `MAX_REGNUM' registers. We just
- ignore the excess. */
-typedef unsigned regnum_t;
-
-
-/* Macros for the compile stack. */
-
-/* Since offsets can go either forwards or backwards, this type needs to
- be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */
-typedef int pattern_offset_t;
-
-typedef struct
-{
- pattern_offset_t begalt_offset;
- pattern_offset_t fixup_alt_jump;
- pattern_offset_t inner_group_offset;
- pattern_offset_t laststart_offset;
- regnum_t regnum;
-} compile_stack_elt_t;
-
-
-typedef struct
-{
- compile_stack_elt_t *stack;
- unsigned size;
- unsigned avail; /* Offset of next open position. */
-} compile_stack_type;
-
-
-#define INIT_COMPILE_STACK_SIZE 32
-
-#define COMPILE_STACK_EMPTY (compile_stack.avail == 0)
-#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size)
-
-/* The next available element. */
-#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
-
-
-/* Set the bit for character C in a list. */
-#define SET_LIST_BIT(c) \
- (b[((unsigned char) (c)) / BYTEWIDTH] \
- |= 1 << (((unsigned char) c) % BYTEWIDTH))
-
-
-/* Get the next unsigned number in the uncompiled pattern. */
-#define GET_UNSIGNED_NUMBER(num) \
- { if (p != pend) \
- { \
- PATFETCH (c); \
- while (ISDIGIT (c)) \
- { \
- if (num < 0) \
- num = 0; \
- num = num * 10 + c - '0'; \
- if (p == pend) \
- break; \
- PATFETCH (c); \
- } \
- } \
- }
-
-#define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
-
-#define IS_CHAR_CLASS(string) \
- (STREQ (string, "alpha") || STREQ (string, "upper") \
- || STREQ (string, "lower") || STREQ (string, "digit") \
- || STREQ (string, "alnum") || STREQ (string, "xdigit") \
- || STREQ (string, "space") || STREQ (string, "print") \
- || STREQ (string, "punct") || STREQ (string, "graph") \
- || STREQ (string, "cntrl") || STREQ (string, "blank"))
-
-#ifndef MATCH_MAY_ALLOCATE
-
-/* If we cannot allocate large objects within re_match_2_internal,
- we make the fail stack and register vectors global.
- The fail stack, we grow to the maximum size when a regexp
- is compiled.
- The register vectors, we adjust in size each time we
- compile a regexp, according to the number of registers it needs. */
-
-static fail_stack_type fail_stack;
-
-/* Size with which the following vectors are currently allocated.
- That is so we can make them bigger as needed,
- but never make them smaller. */
-static int regs_allocated_size;
-
-static const char ** regstart, ** regend;
-static const char ** old_regstart, ** old_regend;
-static const char **best_regstart, **best_regend;
-static register_info_type *reg_info;
-static const char **reg_dummy;
-static register_info_type *reg_info_dummy;
-
-/* Make the register vectors big enough for NUM_REGS registers,
- but don't make them smaller. */
-
-static
-regex_grow_registers (num_regs)
- int num_regs;
-{
- if (num_regs > regs_allocated_size)
- {
- RETALLOC_IF (regstart, num_regs, const char *);
- RETALLOC_IF (regend, num_regs, const char *);
- RETALLOC_IF (old_regstart, num_regs, const char *);
- RETALLOC_IF (old_regend, num_regs, const char *);
- RETALLOC_IF (best_regstart, num_regs, const char *);
- RETALLOC_IF (best_regend, num_regs, const char *);
- RETALLOC_IF (reg_info, num_regs, register_info_type);
- RETALLOC_IF (reg_dummy, num_regs, const char *);
- RETALLOC_IF (reg_info_dummy, num_regs, register_info_type);
-
- regs_allocated_size = num_regs;
- }
-}
-
-#endif /* not MATCH_MAY_ALLOCATE */
-
-/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
- Returns one of error codes defined in `regex.h', or zero for success.
-
- Assumes the `allocated' (and perhaps `buffer') and `translate'
- fields are set in BUFP on entry.
-
- If it succeeds, results are put in BUFP (if it returns an error, the
- contents of BUFP are undefined):
- `buffer' is the compiled pattern;
- `syntax' is set to SYNTAX;
- `used' is set to the length of the compiled pattern;
- `fastmap_accurate' is zero;
- `re_nsub' is the number of subexpressions in PATTERN;
- `not_bol' and `not_eol' are zero;
-
- The `fastmap' and `newline_anchor' fields are neither
- examined nor set. */
-
-/* Return, freeing storage we allocated. */
-#define FREE_STACK_RETURN(value) \
- return (free (compile_stack.stack), value)
-
-static reg_errcode_t
-regex_compile (pattern, size, syntax, bufp)
- const char *pattern;
- int size;
- reg_syntax_t syntax;
- struct re_pattern_buffer *bufp;
-{
- /* We fetch characters from PATTERN here. Even though PATTERN is
- `char *' (i.e., signed), we declare these variables as unsigned, so
- they can be reliably used as array indices. */
- register unsigned char c, c1;
-
- /* A random temporary spot in PATTERN. */
- const char *p1;
-
- /* Points to the end of the buffer, where we should append. */
- register unsigned char *b;
-
- /* Keeps track of unclosed groups. */
- compile_stack_type compile_stack;
-
- /* Points to the current (ending) position in the pattern. */
- const char *p = pattern;
- const char *pend = pattern + size;
-
- /* How to translate the characters in the pattern. */
- RE_TRANSLATE_TYPE translate = bufp->translate;
-
- /* Address of the count-byte of the most recently inserted `exactn'
- command. This makes it possible to tell if a new exact-match
- character can be added to that command or if the character requires
- a new `exactn' command. */
- unsigned char *pending_exact = 0;
-
- /* Address of start of the most recently finished expression.
- This tells, e.g., postfix * where to find the start of its
- operand. Reset at the beginning of groups and alternatives. */
- unsigned char *laststart = 0;
-
- /* Address of beginning of regexp, or inside of last group. */
- unsigned char *begalt;
-
- /* Place in the uncompiled pattern (i.e., the {) to
- which to go back if the interval is invalid. */
- const char *beg_interval;
-
- /* 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. */
- unsigned char *fixup_alt_jump = 0;
-
- /* Counts open-groups as they are encountered. Remembered for the
- matching close-group on the compile stack, so the same register
- number is put in the stop_memory as the start_memory. */
- regnum_t regnum = 0;
-
-#ifdef DEBUG
- DEBUG_PRINT1 ("\nCompiling pattern: ");
- if (debug)
- {
- unsigned debug_count;
-
- for (debug_count = 0; debug_count < size; debug_count++)
- putchar (pattern[debug_count]);
- putchar ('\n');
- }
-#endif /* DEBUG */
-
- /* Initialize the compile stack. */
- compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
- if (compile_stack.stack == NULL)
- return REG_ESPACE;
-
- compile_stack.size = INIT_COMPILE_STACK_SIZE;
- compile_stack.avail = 0;
-
- /* Initialize the pattern buffer. */
- bufp->syntax = syntax;
- bufp->fastmap_accurate = 0;
- bufp->not_bol = bufp->not_eol = 0;
-
- /* Set `used' to zero, so that if we return an error, the pattern
- printer (for debugging) will think there's no pattern. We reset it
- at the end. */
- bufp->used = 0;
-
- /* Always count groups, whether or not bufp->no_sub is set. */
- bufp->re_nsub = 0;
-
-#if !defined (emacs) && !defined (SYNTAX_TABLE)
- /* Initialize the syntax table. */
- init_syntax_once ();
-#endif
-
- if (bufp->allocated == 0)
- {
- if (bufp->buffer)
- { /* If zero allocated, but buffer is non-null, try to realloc
- enough space. This loses if buffer's address is bogus, but
- that is the user's responsibility. */
- RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char);
- }
- else
- { /* Caller did not allocate a buffer. Do it for them. */
- bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char);
- }
- if (!bufp->buffer) FREE_STACK_RETURN (REG_ESPACE);
-
- bufp->allocated = INIT_BUF_SIZE;
- }
-
- begalt = b = bufp->buffer;
-
- /* Loop through the uncompiled pattern until we're at the end. */
- while (p != pend)
- {
- PATFETCH (c);
-
- switch (c)
- {
- case '^':
- {
- if ( /* If at start of pattern, it's an operator. */
- p == pattern + 1
- /* If context independent, it's an operator. */
- || syntax & RE_CONTEXT_INDEP_ANCHORS
- /* Otherwise, depends on what's come before. */
- || at_begline_loc_p (pattern, p, syntax))
- BUF_PUSH (begline);
- else
- goto normal_char;
- }
- break;
-
-
- case '$':
- {
- if ( /* If at end of pattern, it's an operator. */
- p == pend
- /* If context independent, it's an operator. */
- || syntax & RE_CONTEXT_INDEP_ANCHORS
- /* Otherwise, depends on what's next. */
- || at_endline_loc_p (p, pend, syntax))
- BUF_PUSH (endline);
- else
- goto normal_char;
- }
- break;
-
-
- case '+':
- case '?':
- if ((syntax & RE_BK_PLUS_QM)
- || (syntax & RE_LIMITED_OPS))
- goto normal_char;
- handle_plus:
- case '*':
- /* If there is no previous pattern... */
- if (!laststart)
- {
- if (syntax & RE_CONTEXT_INVALID_OPS)
- FREE_STACK_RETURN (REG_BADRPT);
- else if (!(syntax & RE_CONTEXT_INDEP_OPS))
- goto normal_char;
- }
-
- {
- /* Are we optimizing this jump? */
- boolean keep_string_p = false;
-
- /* 1 means zero (many) matches is allowed. */
- char zero_times_ok = 0, many_times_ok = 0;
-
- /* If there is a sequence of repetition chars, collapse it
- down to just one (the right one). We can't combine
- interval operators with these because of, e.g., `a{2}*',
- which should only match an even number of `a's. */
-
- for (;;)
- {
- zero_times_ok |= c != '+';
- many_times_ok |= c != '?';
-
- if (p == pend)
- break;
-
- PATFETCH (c);
-
- if (c == '*'
- || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
- ;
-
- else if (syntax & RE_BK_PLUS_QM && c == '\\')
- {
- if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
-
- PATFETCH (c1);
- if (!(c1 == '+' || c1 == '?'))
- {
- PATUNFETCH;
- PATUNFETCH;
- break;
- }
-
- c = c1;
- }
- else
- {
- PATUNFETCH;
- break;
- }
-
- /* If we get here, we found another repeat character. */
- }
-
- /* Star, etc. applied to an empty pattern is equivalent
- to an empty pattern. */
- if (!laststart)
- break;
-
- /* Now we know whether or not zero matches is allowed
- and also whether or not two or more matches is allowed. */
- if (many_times_ok)
- { /* More than one repetition is allowed, so put in at the
- end a backward relative jump from `b' to before the next
- jump we're going to put in below (which jumps from
- laststart to after this jump).
-
- But if we are at the `*' in the exact sequence `.*\n',
- insert an unconditional jump backwards to the .,
- instead of the beginning of the loop. This way we only
- push a failure point once, instead of every time
- through the loop. */
- assert (p - 1 > pattern);
-
- /* Allocate the space for the jump. */
- GET_BUFFER_SPACE (3);
-
- /* We know we are not at the first character of the pattern,
- because laststart was nonzero. And we've already
- incremented `p', by the way, to be the character after
- the `*'. Do we have to do something analogous here
- for null bytes, because of RE_DOT_NOT_NULL? */
- if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
- && zero_times_ok
- && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
- && !(syntax & RE_DOT_NEWLINE))
- { /* We have .*\n. */
- STORE_JUMP (jump, b, laststart);
- keep_string_p = true;
- }
- else
- /* Anything else. */
- STORE_JUMP (maybe_pop_jump, b, laststart - 3);
-
- /* We've added more stuff to the buffer. */
- b += 3;
- }
-
- /* On failure, jump from laststart to b + 3, which will be the
- end of the buffer after this jump is inserted. */
- GET_BUFFER_SPACE (3);
- INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
- : on_failure_jump,
- laststart, b + 3);
- pending_exact = 0;
- b += 3;
-
- if (!zero_times_ok)
- {
- /* At least one repetition is required, so insert a
- `dummy_failure_jump' before the initial
- `on_failure_jump' instruction of the loop. This
- effects a skip over that instruction the first time
- we hit that loop. */
- GET_BUFFER_SPACE (3);
- INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6);
- b += 3;
- }
- }
- break;
-
-
- case '.':
- laststart = b;
- BUF_PUSH (anychar);
- break;
-
-
- case '[':
- {
- boolean had_char_class = false;
-
- if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
-
- /* Ensure that we have enough space to push a charset: the
- opcode, the length count, and the bitset; 34 bytes in all. */
- GET_BUFFER_SPACE (34);
-
- laststart = b;
-
- /* We test `*p == '^' twice, instead of using an if
- statement, so we only need one BUF_PUSH. */
- BUF_PUSH (*p == '^' ? charset_not : charset);
- if (*p == '^')
- p++;
-
- /* Remember the first position in the bracket expression. */
- p1 = p;
-
- /* Push the number of bytes in the bitmap. */
- BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
-
- /* Clear the whole map. */
- bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
-
- /* charset_not matches newline according to a syntax bit. */
- if ((re_opcode_t) b[-2] == charset_not
- && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
- SET_LIST_BIT ('\n');
-
- /* Read in characters and ranges, setting map bits. */
- for (;;)
- {
- if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
-
- PATFETCH (c);
-
- /* \ might escape characters inside [...] and [^...]. */
- if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
- {
- if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
-
- PATFETCH (c1);
- SET_LIST_BIT (c1);
- continue;
- }
-
- /* Could be the end of the bracket expression. If it's
- not (i.e., when the bracket expression is `[]' so
- far), the ']' character bit gets set way below. */
- if (c == ']' && p != p1 + 1)
- break;
-
- /* Look ahead to see if it's a range when the last thing
- was a character class. */
- if (had_char_class && c == '-' && *p != ']')
- FREE_STACK_RETURN (REG_ERANGE);
-
- /* Look ahead to see if it's a range when the last thing
- was a character: if this is a hyphen not at the
- beginning or the end of a list, then it's the range
- operator. */
- if (c == '-'
- && !(p - 2 >= pattern && p[-2] == '[')
- && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
- && *p != ']')
- {
- reg_errcode_t ret
- = compile_range (&p, pend, translate, syntax, b);
- if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
- }
-
- else if (p[0] == '-' && p[1] != ']')
- { /* This handles ranges made up of characters only. */
- reg_errcode_t ret;
-
- /* Move past the `-'. */
- PATFETCH (c1);
-
- ret = compile_range (&p, pend, translate, syntax, b);
- if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
- }
-
- /* See if we're at the beginning of a possible character
- class. */
-
- else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
- { /* Leave room for the null. */
- char str[CHAR_CLASS_MAX_LENGTH + 1];
-
- PATFETCH (c);
- c1 = 0;
-
- /* If pattern is `[[:'. */
- if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
-
- for (;;)
- {
- PATFETCH (c);
- if (c == ':' || c == ']' || p == pend
- || c1 == CHAR_CLASS_MAX_LENGTH)
- break;
- str[c1++] = c;
- }
- str[c1] = '\0';
-
- /* If isn't a word bracketed by `[:' and:`]':
- undo the ending character, the letters, and leave
- the leading `:' and `[' (but set bits for them). */
- if (c == ':' && *p == ']')
- {
- int ch;
- boolean is_alnum = STREQ (str, "alnum");
- boolean is_alpha = STREQ (str, "alpha");
- boolean is_blank = STREQ (str, "blank");
- boolean is_cntrl = STREQ (str, "cntrl");
- boolean is_digit = STREQ (str, "digit");
- boolean is_graph = STREQ (str, "graph");
- boolean is_lower = STREQ (str, "lower");
- boolean is_print = STREQ (str, "print");
- boolean is_punct = STREQ (str, "punct");
- boolean is_space = STREQ (str, "space");
- boolean is_upper = STREQ (str, "upper");
- boolean is_xdigit = STREQ (str, "xdigit");
-
- if (!IS_CHAR_CLASS (str))
- FREE_STACK_RETURN (REG_ECTYPE);
-
- /* Throw away the ] at the end of the character
- class. */
- PATFETCH (c);
-
- if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
-
- for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
- {
- int translated = TRANSLATE (ch);
- /* This was split into 3 if's to
- avoid an arbitrary limit in some compiler. */
- if ( (is_alnum && ISALNUM (ch))
- || (is_alpha && ISALPHA (ch))
- || (is_blank && ISBLANK (ch))
- || (is_cntrl && ISCNTRL (ch)))
- SET_LIST_BIT (translated);
- if ( (is_digit && ISDIGIT (ch))
- || (is_graph && ISGRAPH (ch))
- || (is_lower && ISLOWER (ch))
- || (is_print && ISPRINT (ch)))
- SET_LIST_BIT (translated);
- if ( (is_punct && ISPUNCT (ch))
- || (is_space && ISSPACE (ch))
- || (is_upper && ISUPPER (ch))
- || (is_xdigit && ISXDIGIT (ch)))
- SET_LIST_BIT (translated);
- }
- had_char_class = true;
- }
- else
- {
- c1++;
- while (c1--)
- PATUNFETCH;
- SET_LIST_BIT ('[');
- SET_LIST_BIT (':');
- had_char_class = false;
- }
- }
- else
- {
- had_char_class = false;
- SET_LIST_BIT (c);
- }
- }
-
- /* Discard any (non)matching list bytes that are all 0 at the
- end of the map. Decrease the map-length byte too. */
- while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
- b[-1]--;
- b += b[-1];
- }
- break;
-
-
- case '(':
- if (syntax & RE_NO_BK_PARENS)
- goto handle_open;
- else
- goto normal_char;
-
-
- case ')':
- if (syntax & RE_NO_BK_PARENS)
- goto handle_close;
- else
- goto normal_char;
-
-
- case '\n':
- if (syntax & RE_NEWLINE_ALT)
- goto handle_alt;
- else
- goto normal_char;
-
-
- case '|':
- if (syntax & RE_NO_BK_VBAR)
- goto handle_alt;
- else
- goto normal_char;
-
-
- case '{':
- if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
- goto handle_interval;
- else
- goto normal_char;
-
-
- case '\\':
- if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
-
- /* Do not translate the character after the \, so that we can
- distinguish, e.g., \B from \b, even if we normally would
- translate, e.g., B to b. */
- PATFETCH_RAW (c);
-
- switch (c)
- {
- case '(':
- if (syntax & RE_NO_BK_PARENS)
- goto normal_backslash;
-
- handle_open:
- bufp->re_nsub++;
- regnum++;
-
- if (COMPILE_STACK_FULL)
- {
- RETALLOC (compile_stack.stack, compile_stack.size << 1,
- compile_stack_elt_t);
- if (compile_stack.stack == NULL) return REG_ESPACE;
-
- compile_stack.size <<= 1;
- }
-
- /* These are the values to restore when we hit end of this
- group. They are all relative offsets, so that if the
- whole pattern moves because of realloc, they will still
- be valid. */
- COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer;
- COMPILE_STACK_TOP.fixup_alt_jump
- = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
- COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
- COMPILE_STACK_TOP.regnum = regnum;
-
- /* We will eventually replace the 0 with the number of
- groups inner to this one. But do not push a
- start_memory for groups beyond the last one we can
- represent in the compiled pattern. */
- if (regnum <= MAX_REGNUM)
- {
- COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2;
- BUF_PUSH_3 (start_memory, regnum, 0);
- }
-
- compile_stack.avail++;
-
- fixup_alt_jump = 0;
- laststart = 0;
- begalt = b;
- /* If we've reached MAX_REGNUM groups, then this open
- won't actually generate any code, so we'll have to
- clear pending_exact explicitly. */
- pending_exact = 0;
- break;
-
-
- case ')':
- if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
-
- if (COMPILE_STACK_EMPTY)
- if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
- goto normal_backslash;
- else
- FREE_STACK_RETURN (REG_ERPAREN);
-
- handle_close:
- if (fixup_alt_jump)
- { /* Push a dummy failure point at the end of the
- alternative for a possible future
- `pop_failure_jump' to pop. See comments at
- `push_dummy_failure' in `re_match_2'. */
- BUF_PUSH (push_dummy_failure);
-
- /* We allocated space for this jump when we assigned
- to `fixup_alt_jump', in the `handle_alt' case below. */
- STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
- }
-
- /* See similar code for backslashed left paren above. */
- if (COMPILE_STACK_EMPTY)
- if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
- goto normal_char;
- else
- FREE_STACK_RETURN (REG_ERPAREN);
-
- /* Since we just checked for an empty stack above, this
- ``can't happen''. */
- assert (compile_stack.avail != 0);
- {
- /* We don't just want to restore into `regnum', because
- later groups should continue to be numbered higher,
- as in `(ab)c(de)' -- the second group is #2. */
- regnum_t this_group_regnum;
-
- compile_stack.avail--;
- begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
- fixup_alt_jump
- = COMPILE_STACK_TOP.fixup_alt_jump
- ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1
- : 0;
- laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
- this_group_regnum = COMPILE_STACK_TOP.regnum;
- /* If we've reached MAX_REGNUM groups, then this open
- won't actually generate any code, so we'll have to
- clear pending_exact explicitly. */
- pending_exact = 0;
-
- /* We're at the end of the group, so now we know how many
- groups were inside this one. */
- if (this_group_regnum <= MAX_REGNUM)
- {
- unsigned char *inner_group_loc
- = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset;
-
- *inner_group_loc = regnum - this_group_regnum;
- BUF_PUSH_3 (stop_memory, this_group_regnum,
- regnum - this_group_regnum);
- }
- }
- break;
-
-
- case '|': /* `\|'. */
- if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
- goto normal_backslash;
- handle_alt:
- if (syntax & RE_LIMITED_OPS)
- goto normal_char;
-
- /* Insert before the previous alternative a jump which
- jumps to this alternative if the former fails. */
- GET_BUFFER_SPACE (3);
- INSERT_JUMP (on_failure_jump, begalt, b + 6);
- pending_exact = 0;
- b += 3;
-
- /* The alternative before this one has a jump after it
- which gets executed if it gets matched. Adjust that
- jump so it will jump to this alternative's analogous
- jump (put in below, which in turn will jump to the next
- (if any) alternative's such jump, etc.). The last such
- jump jumps to the correct final destination. A picture:
- _____ _____
- | | | |
- | v | v
- a | b | c
-
- If we are at `b', then fixup_alt_jump right now points to a
- three-byte space after `a'. We'll put in the jump, set
- fixup_alt_jump to right after `b', and leave behind three
- bytes which we'll fill in when we get to after `c'. */
-
- if (fixup_alt_jump)
- STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
-
- /* Mark and leave space for a jump after this alternative,
- to be filled in later either by next alternative or
- when know we're at the end of a series of alternatives. */
- fixup_alt_jump = b;
- GET_BUFFER_SPACE (3);
- b += 3;
-
- laststart = 0;
- begalt = b;
- break;
-
-
- case '{':
- /* If \{ is a literal. */
- if (!(syntax & RE_INTERVALS)
- /* If we're at `\{' and it's not the open-interval
- operator. */
- || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
- || (p - 2 == pattern && p == pend))
- goto normal_backslash;
-
- handle_interval:
- {
- /* If got here, then the syntax allows intervals. */
-
- /* At least (most) this many matches must be made. */
- int lower_bound = -1, upper_bound = -1;
-
- beg_interval = p - 1;
-
- if (p == pend)
- {
- if (syntax & RE_NO_BK_BRACES)
- goto unfetch_interval;
- else
- FREE_STACK_RETURN (REG_EBRACE);
- }
-
- GET_UNSIGNED_NUMBER (lower_bound);
-
- if (c == ',')
- {
- GET_UNSIGNED_NUMBER (upper_bound);
- if (upper_bound < 0) upper_bound = RE_DUP_MAX;
- }
- else
- /* Interval such as `{1}' => match exactly once. */
- upper_bound = lower_bound;
-
- if (lower_bound < 0 || upper_bound > RE_DUP_MAX
- || lower_bound > upper_bound)
- {
- if (syntax & RE_NO_BK_BRACES)
- goto unfetch_interval;
- else
- FREE_STACK_RETURN (REG_BADBR);
- }
-
- if (!(syntax & RE_NO_BK_BRACES))
- {
- if (c != '\\') FREE_STACK_RETURN (REG_EBRACE);
-
- PATFETCH (c);
- }
-
- if (c != '}')
- {
- if (syntax & RE_NO_BK_BRACES)
- goto unfetch_interval;
- else
- FREE_STACK_RETURN (REG_BADBR);
- }
-
- /* We just parsed a valid interval. */
-
- /* If it's invalid to have no preceding re. */
- if (!laststart)
- {
- if (syntax & RE_CONTEXT_INVALID_OPS)
- FREE_STACK_RETURN (REG_BADRPT);
- else if (syntax & RE_CONTEXT_INDEP_OPS)
- laststart = b;
- else
- goto unfetch_interval;
- }
-
- /* If the upper bound is zero, don't want to succeed at
- all; jump from `laststart' to `b + 3', which will be
- the end of the buffer after we insert the jump. */
- if (upper_bound == 0)
- {
- GET_BUFFER_SPACE (3);
- INSERT_JUMP (jump, laststart, b + 3);
- b += 3;
- }
-
- /* Otherwise, we have a nontrivial interval. When
- we're all done, the pattern will look like:
- set_number_at <jump count> <upper bound>
- set_number_at <succeed_n count> <lower bound>
- succeed_n <after jump addr> <succeed_n count>
- <body of loop>
- jump_n <succeed_n addr> <jump count>
- (The upper bound and `jump_n' are omitted if
- `upper_bound' is 1, though.) */
- else
- { /* If the upper bound is > 1, we need to insert
- more at the end of the loop. */
- unsigned nbytes = 10 + (upper_bound > 1) * 10;
-
- GET_BUFFER_SPACE (nbytes);
-
- /* Initialize lower bound of the `succeed_n', even
- though it will be set during matching by its
- attendant `set_number_at' (inserted next),
- because `re_compile_fastmap' needs to know.
- Jump to the `jump_n' we might insert below. */
- INSERT_JUMP2 (succeed_n, laststart,
- b + 5 + (upper_bound > 1) * 5,
- lower_bound);
- b += 5;
-
- /* Code to initialize the lower bound. Insert
- before the `succeed_n'. The `5' is the last two
- bytes of this `set_number_at', plus 3 bytes of
- the following `succeed_n'. */
- insert_op2 (set_number_at, laststart, 5, lower_bound, b);
- b += 5;
-
- if (upper_bound > 1)
- { /* More than one repetition is allowed, so
- append a backward jump to the `succeed_n'
- that starts this interval.
-
- When we've reached this during matching,
- we'll have matched the interval once, so
- jump back only `upper_bound - 1' times. */
- STORE_JUMP2 (jump_n, b, laststart + 5,
- upper_bound - 1);
- b += 5;
-
- /* The location we want to set is the second
- parameter of the `jump_n'; that is `b-2' as
- an absolute address. `laststart' will be
- the `set_number_at' we're about to insert;
- `laststart+3' the number to set, the source
- for the relative address. But we are
- inserting into the middle of the pattern --
- so everything is getting moved up by 5.
- Conclusion: (b - 2) - (laststart + 3) + 5,
- i.e., b - laststart.
-
- We insert this at the beginning of the loop
- so that if we fail during matching, we'll
- reinitialize the bounds. */
- insert_op2 (set_number_at, laststart, b - laststart,
- upper_bound - 1, b);
- b += 5;
- }
- }
- pending_exact = 0;
- beg_interval = NULL;
- }
- break;
-
- unfetch_interval:
- /* If an invalid interval, match the characters as literals. */
- assert (beg_interval);
- p = beg_interval;
- beg_interval = NULL;
-
- /* normal_char and normal_backslash need `c'. */
- PATFETCH (c);
-
- if (!(syntax & RE_NO_BK_BRACES))
- {
- if (p > pattern && p[-1] == '\\')
- goto normal_backslash;
- }
- goto normal_char;
-
-#ifdef emacs
- /* There is no way to specify the before_dot and after_dot
- operators. rms says this is ok. --karl */
- case '=':
- BUF_PUSH (at_dot);
- break;
-
- case 's':
- laststart = b;
- PATFETCH (c);
- BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
- break;
-
- case 'S':
- laststart = b;
- PATFETCH (c);
- BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
- break;
-#endif /* emacs */
-
-
- case 'w':
- laststart = b;
- BUF_PUSH (wordchar);
- break;
-
-
- case 'W':
- laststart = b;
- BUF_PUSH (notwordchar);
- break;
-
-
- case '<':
- BUF_PUSH (wordbeg);
- break;
-
- case '>':
- BUF_PUSH (wordend);
- break;
-
- case 'b':
- BUF_PUSH (wordbound);
- break;
-
- case 'B':
- BUF_PUSH (notwordbound);
- break;
-
- case '`':
- BUF_PUSH (begbuf);
- break;
-
- case '\'':
- BUF_PUSH (endbuf);
- break;
-
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- if (syntax & RE_NO_BK_REFS)
- goto normal_char;
-
- c1 = c - '0';
-
- if (c1 > regnum)
- FREE_STACK_RETURN (REG_ESUBREG);
-
- /* Can't back reference to a subexpression if inside of it. */
- if (group_in_compile_stack (compile_stack, c1))
- goto normal_char;
-
- laststart = b;
- BUF_PUSH_2 (duplicate, c1);
- break;
-
-
- case '+':
- case '?':
- if (syntax & RE_BK_PLUS_QM)
- goto handle_plus;
- else
- goto normal_backslash;
-
- default:
- normal_backslash:
- /* 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. */
- c = TRANSLATE (c);
- goto normal_char;
- }
- break;
-
-
- default:
- /* Expects the character in `c'. */
- normal_char:
- /* If no exactn currently being built. */
- if (!pending_exact
-
- /* If last exactn not at current position. */
- || pending_exact + *pending_exact + 1 != b
-
- /* We have only one byte following the exactn for the count. */
- || *pending_exact == (1 << BYTEWIDTH) - 1
-
- /* If followed by a repetition operator. */
- || *p == '*' || *p == '^'
- || ((syntax & RE_BK_PLUS_QM)
- ? *p == '\\' && (p[1] == '+' || p[1] == '?')
- : (*p == '+' || *p == '?'))
- || ((syntax & RE_INTERVALS)
- && ((syntax & RE_NO_BK_BRACES)
- ? *p == '{'
- : (p[0] == '\\' && p[1] == '{'))))
- {
- /* Start building a new exactn. */
-
- laststart = b;
-
- BUF_PUSH_2 (exactn, 0);
- pending_exact = b - 1;
- }
-
- BUF_PUSH (c);
- (*pending_exact)++;
- break;
- } /* switch (c) */
- } /* while p != pend */
-
-
- /* Through the pattern now. */
-
- if (fixup_alt_jump)
- STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
-
- if (!COMPILE_STACK_EMPTY)
- FREE_STACK_RETURN (REG_EPAREN);
-
- /* If we don't want backtracking, force success
- the first time we reach the end of the compiled pattern. */
- if (syntax & RE_NO_POSIX_BACKTRACKING)
- BUF_PUSH (succeed);
-
- free (compile_stack.stack);
-
- /* We have succeeded; set the length of the buffer. */
- bufp->used = b - bufp->buffer;
-
-#ifdef DEBUG
- if (debug)
- {
- DEBUG_PRINT1 ("\nCompiled pattern: \n");
- print_compiled_pattern (bufp);
- }
-#endif /* DEBUG */
-
-#ifndef MATCH_MAY_ALLOCATE
- /* Initialize the failure stack to the largest possible stack. This
- isn't necessary unless we're trying to avoid calling alloca in
- the search and match routines. */
- {
- int num_regs = bufp->re_nsub + 1;
-
- /* Since DOUBLE_FAIL_STACK refuses to double only if the current size
- is strictly greater than re_max_failures, the largest possible stack
- is 2 * re_max_failures failure points. */
- if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS))
- {
- fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS);
-
-#ifdef emacs
- if (! fail_stack.stack)
- fail_stack.stack
- = (fail_stack_elt_t *) xmalloc (fail_stack.size
- * sizeof (fail_stack_elt_t));
- else
- fail_stack.stack
- = (fail_stack_elt_t *) xrealloc (fail_stack.stack,
- (fail_stack.size
- * sizeof (fail_stack_elt_t)));
-#else /* not emacs */
- if (! fail_stack.stack)
- fail_stack.stack
- = (fail_stack_elt_t *) malloc (fail_stack.size
- * sizeof (fail_stack_elt_t));
- else
- fail_stack.stack
- = (fail_stack_elt_t *) realloc (fail_stack.stack,
- (fail_stack.size
- * sizeof (fail_stack_elt_t)));
-#endif /* not emacs */
- }
-
- regex_grow_registers (num_regs);
- }
-#endif /* not MATCH_MAY_ALLOCATE */
-
- return REG_NOERROR;
-} /* regex_compile */
-
-/* Subroutines for `regex_compile'. */
-
-/* Store OP at LOC followed by two-byte integer parameter ARG. */
-
-static void
-store_op1 (op, loc, arg)
- re_opcode_t op;
- unsigned char *loc;
- int arg;
-{
- *loc = (unsigned char) op;
- STORE_NUMBER (loc + 1, arg);
-}
-
-
-/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */
-
-static void
-store_op2 (op, loc, arg1, arg2)
- re_opcode_t op;
- unsigned char *loc;
- int arg1, arg2;
-{
- *loc = (unsigned char) op;
- STORE_NUMBER (loc + 1, arg1);
- STORE_NUMBER (loc + 3, arg2);
-}
-
-
-/* Copy the bytes from LOC to END to open up three bytes of space at LOC
- for OP followed by two-byte integer parameter ARG. */
-
-static void
-insert_op1 (op, loc, arg, end)
- re_opcode_t op;
- unsigned char *loc;
- int arg;
- unsigned char *end;
-{
- register unsigned char *pfrom = end;
- register unsigned char *pto = end + 3;
-
- while (pfrom != loc)
- *--pto = *--pfrom;
-
- store_op1 (op, loc, arg);
-}
-
-
-/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */
-
-static void
-insert_op2 (op, loc, arg1, arg2, end)
- re_opcode_t op;
- unsigned char *loc;
- int arg1, arg2;
- unsigned char *end;
-{
- register unsigned char *pfrom = end;
- register unsigned char *pto = end + 5;
-
- while (pfrom != loc)
- *--pto = *--pfrom;
-
- store_op2 (op, loc, arg1, arg2);
-}
-
-
-/* P points to just after a ^ in PATTERN. Return true if that ^ comes
- after an alternative or a begin-subexpression. We assume there is at
- least one character before the ^. */
-
-static boolean
-at_begline_loc_p (pattern, p, syntax)
- const char *pattern, *p;
- reg_syntax_t syntax;
-{
- const char *prev = p - 2;
- boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
-
- return
- /* After a subexpression? */
- (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
- /* After an alternative? */
- || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
-}
-
-
-/* The dual of at_begline_loc_p. This one is for $. We assume there is
- at least one character after the $, i.e., `P < PEND'. */
-
-static boolean
-at_endline_loc_p (p, pend, syntax)
- const char *p, *pend;
- int syntax;
-{
- const char *next = p;
- boolean next_backslash = *next == '\\';
- const char *next_next = p + 1 < pend ? p + 1 : 0;
-
- return
- /* Before a subexpression? */
- (syntax & RE_NO_BK_PARENS ? *next == ')'
- : next_backslash && next_next && *next_next == ')')
- /* Before an alternative? */
- || (syntax & RE_NO_BK_VBAR ? *next == '|'
- : next_backslash && next_next && *next_next == '|');
-}
-
-
-/* Returns true if REGNUM is in one of COMPILE_STACK's elements and
- false if it's not. */
-
-static boolean
-group_in_compile_stack (compile_stack, regnum)
- compile_stack_type compile_stack;
- regnum_t regnum;
-{
- int this_element;
-
- for (this_element = compile_stack.avail - 1;
- this_element >= 0;
- this_element--)
- if (compile_stack.stack[this_element].regnum == regnum)
- return true;
-
- return false;
-}
-
-
-/* Read the ending character of a range (in a bracket expression) from the
- uncompiled pattern *P_PTR (which ends at PEND). We assume the
- starting character is in `P[-2]'. (`P[-1]' is the character `-'.)
- Then we set the translation of all bits between the starting and
- ending characters (inclusive) in the compiled pattern B.
-
- Return an error code.
-
- We use these short variable names so we can use the same macros as
- `regex_compile' itself. */
-
-static reg_errcode_t
-compile_range (p_ptr, pend, translate, syntax, b)
- const char **p_ptr, *pend;
- RE_TRANSLATE_TYPE translate;
- reg_syntax_t syntax;
- unsigned char *b;
-{
- unsigned this_char;
-
- const char *p = *p_ptr;
- int range_start, range_end;
-
- if (p == pend)
- return REG_ERANGE;
-
- /* Even though the pattern is a signed `char *', we need to fetch
- with unsigned char *'s; if the high bit of the pattern character
- is set, the range endpoints will be negative if we fetch using a
- signed char *.
-
- We also want to fetch the endpoints without translating them; the
- appropriate translation is done in the bit-setting loop below. */
- /* The SVR4 compiler on the 3B2 had trouble with unsigned const char *. */
- range_start = ((const unsigned char *) p)[-2];
- range_end = ((const unsigned char *) p)[0];
-
- /* Have to increment the pointer into the pattern string, so the
- caller isn't still at the ending character. */
- (*p_ptr)++;
-
- /* If the start is after the end, the range is empty. */
- if (range_start > range_end)
- return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
-
- /* Here we see why `this_char' has to be larger than an `unsigned
- char' -- the range is inclusive, so if `range_end' == 0xff
- (assuming 8-bit characters), we would otherwise go into an infinite
- loop, since all characters <= 0xff. */
- for (this_char = range_start; this_char <= range_end; this_char++)
- {
- SET_LIST_BIT (TRANSLATE (this_char));
- }
-
- return REG_NOERROR;
-}
-
-/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
- BUFP. A 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 impossible starting points.
-
- The caller must supply the address of a (1 << BYTEWIDTH)-byte data
- area as BUFP->fastmap.
-
- We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
- the pattern buffer.
-
- Returns 0 if we succeed, -2 if an internal error. */
-
-int
-re_compile_fastmap (bufp)
- struct re_pattern_buffer *bufp;
-{
- int j, k;
-#ifdef MATCH_MAY_ALLOCATE
- fail_stack_type fail_stack;
-#endif
-#ifndef REGEX_MALLOC
- char *destination;
-#endif
- /* We don't push any register information onto the failure stack. */
- unsigned num_regs = 0;
-
- register char *fastmap = bufp->fastmap;
- unsigned char *pattern = bufp->buffer;
- unsigned long size = bufp->used;
- unsigned char *p = pattern;
- register unsigned char *pend = pattern + size;
-
- /* This holds the pointer to the failure stack, when
- it is allocated relocatably. */
- fail_stack_elt_t *failure_stack_ptr;
-
- /* Assume that each path through the pattern can be null until
- proven otherwise. We set this false at the bottom of switch
- statement, to which we get only if a particular path doesn't
- match the empty string. */
- boolean path_can_be_null = true;
-
- /* We aren't doing a `succeed_n' to begin with. */
- boolean succeed_n_p = false;
-
- assert (fastmap != NULL && p != NULL);
-
- INIT_FAIL_STACK ();
- bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */
- bufp->fastmap_accurate = 1; /* It will be when we're done. */
- bufp->can_be_null = 0;
-
- while (1)
- {
- if (p == pend || *p == succeed)
- {
- /* We have reached the (effective) end of pattern. */
- if (!FAIL_STACK_EMPTY ())
- {
- bufp->can_be_null |= path_can_be_null;
-
- /* Reset for next path. */
- path_can_be_null = true;
-
- p = fail_stack.stack[--fail_stack.avail].pointer;
-
- continue;
- }
- else
- break;
- }
-
- /* We should never be about to go beyond the end of the pattern. */
- assert (p < pend);
-
- switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
- {
-
- /* I guess the idea here is to simply not bother with a fastmap
- if a backreference is used, since it's too hard to figure out
- the fastmap for the corresponding group. Setting
- `can_be_null' stops `re_search_2' from using the fastmap, so
- that is all we do. */
- case duplicate:
- bufp->can_be_null = 1;
- goto done;
-
-
- /* Following are the cases which match a character. These end
- with `break'. */
-
- case exactn:
- fastmap[p[1]] = 1;
- break;
-
-
- case charset:
- for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
- if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
- fastmap[j] = 1;
- break;
-
-
- case charset_not:
- /* Chars beyond end of map must be allowed. */
- for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
- fastmap[j] = 1;
-
- for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
- if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
- fastmap[j] = 1;
- 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;
-
-
- case anychar:
- {
- int fastmap_newline = fastmap['\n'];
-
- /* `.' matches anything ... */
- for (j = 0; j < (1 << BYTEWIDTH); j++)
- fastmap[j] = 1;
-
- /* ... except perhaps newline. */
- if (!(bufp->syntax & RE_DOT_NEWLINE))
- fastmap['\n'] = fastmap_newline;
-
- /* Return if we have already set `can_be_null'; if we have,
- then the fastmap is irrelevant. Something's wrong here. */
- else if (bufp->can_be_null)
- goto done;
-
- /* Otherwise, have to check alternative paths. */
- 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;
-
-
- /* All cases after this match the empty string. These end with
- `continue'. */
-
-
- case before_dot:
- case at_dot:
- case after_dot:
- continue;
-#endif /* emacs */
-
-
- case no_op:
- case begline:
- case endline:
- case begbuf:
- case endbuf:
- case wordbound:
- case notwordbound:
- case wordbeg:
- case wordend:
- case push_dummy_failure:
- continue;
-
-
- case jump_n:
- case pop_failure_jump:
- case maybe_pop_jump:
- case jump:
- case jump_past_alt:
- case dummy_failure_jump:
- EXTRACT_NUMBER_AND_INCR (j, p);
- p += j;
- if (j > 0)
- continue;
-
- /* Jump backward implies we just went through the body of a
- loop and matched nothing. Opcode jumped to should be
- `on_failure_jump' or `succeed_n'. Just treat it like an
- ordinary jump. For a * loop, it has pushed its failure
- point already; if so, discard that as redundant. */
- if ((re_opcode_t) *p != on_failure_jump
- && (re_opcode_t) *p != succeed_n)
- continue;
-
- p++;
- EXTRACT_NUMBER_AND_INCR (j, p);
- p += j;
-
- /* If what's on the stack is where we are now, pop it. */
- if (!FAIL_STACK_EMPTY ()
- && fail_stack.stack[fail_stack.avail - 1].pointer == p)
- fail_stack.avail--;
-
- continue;
-
-
- case on_failure_jump:
- case on_failure_keep_string_jump:
- handle_on_failure_jump:
- EXTRACT_NUMBER_AND_INCR (j, p);
-
- /* For some patterns, e.g., `(a?)?', `p+j' here points to the
- end of the pattern. We don't want to push such a point,
- since when we restore it above, entering the switch will
- increment `p' past the end of the pattern. We don't need
- to push such a point since we obviously won't find any more
- fastmap entries beyond `pend'. Such a pattern can match
- the null string, though. */
- if (p + j < pend)
- {
- if (!PUSH_PATTERN_OP (p + j, fail_stack))
- {
- RESET_FAIL_STACK ();
- return -2;
- }
- }
- else
- bufp->can_be_null = 1;
-
- if (succeed_n_p)
- {
- EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */
- succeed_n_p = false;
- }
-
- continue;
-
-
- case succeed_n:
- /* Get to the number of times to succeed. */
- p += 2;
-
- /* Increment p past the n for when k != 0. */
- EXTRACT_NUMBER_AND_INCR (k, p);
- if (k == 0)
- {
- p -= 4;
- succeed_n_p = true; /* Spaghetti code alert. */
- goto handle_on_failure_jump;
- }
- continue;
-
-
- case set_number_at:
- p += 4;
- continue;
-
-
- case start_memory:
- case stop_memory:
- p += 2;
- continue;
-
-
- default:
- abort (); /* We have listed all the cases. */
- } /* switch *p++ */
-
- /* Getting here means we have found the possible starting
- characters for one path of the pattern -- and that the empty
- string does not match. We need not follow this path further.
- Instead, look at the next alternative (remembered on the
- stack), or quit if no more. The test at the top of the loop
- does these things. */
- path_can_be_null = false;
- p = pend;
- } /* while p */
-
- /* Set `can_be_null' for the last path (also the first path, if the
- pattern is empty). */
- bufp->can_be_null |= path_can_be_null;
-
- done:
- RESET_FAIL_STACK ();
- return 0;
-} /* re_compile_fastmap */
-
-/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
- ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use
- this memory for recording register information. STARTS and ENDS
- must be allocated using the malloc library routine, and must each
- be at least NUM_REGS * sizeof (regoff_t) bytes long.
-
- If NUM_REGS == 0, then subsequent matches should allocate their own
- register data.
-
- Unless this function is called, the first search or match using
- PATTERN_BUFFER will allocate its own register data, without
- freeing the old data. */
-
-void
-re_set_registers (bufp, regs, num_regs, starts, ends)
- struct re_pattern_buffer *bufp;
- struct re_registers *regs;
- unsigned num_regs;
- regoff_t *starts, *ends;
-{
- if (num_regs)
- {
- bufp->regs_allocated = REGS_REALLOCATE;
- regs->num_regs = num_regs;
- regs->start = starts;
- regs->end = ends;
- }
- else
- {
- bufp->regs_allocated = REGS_UNALLOCATED;
- regs->num_regs = 0;
- regs->start = regs->end = (regoff_t *) 0;
- }
-}
-
-/* Searching routines. */
-
-/* Like re_search_2, below, but only one string is specified, and
- doesn't let you say where to stop matching. */
-
-int
-re_search (bufp, string, size, startpos, range, regs)
- struct re_pattern_buffer *bufp;
- const char *string;
- int size, startpos, range;
- struct re_registers *regs;
-{
- return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
- regs, size);
-}
-
-
-/* Using the compiled pattern in BUFP->buffer, first tries to match the
- virtual concatenation of STRING1 and STRING2, starting first at index
- STARTPOS, then at STARTPOS + 1, and so on.
-
- STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
-
- RANGE is how far to scan while trying to match. RANGE = 0 means try
- only at STARTPOS; in general, the last start tried is STARTPOS +
- RANGE.
-
- In REGS, return the indices of the virtual concatenation of STRING1
- and STRING2 that matched the entire BUFP->buffer and its contained
- subexpressions.
-
- Do not consider matching one past the index STOP in the virtual
- concatenation of STRING1 and STRING2.
-
- We return either the position in the strings at which the match was
- found, -1 if no match, or -2 if error (such as failure
- stack overflow). */
-
-int
-re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
- struct re_pattern_buffer *bufp;
- const char *string1, *string2;
- int size1, size2;
- int startpos;
- int range;
- struct re_registers *regs;
- int stop;
-{
- int val;
- register char *fastmap = bufp->fastmap;
- register RE_TRANSLATE_TYPE translate = bufp->translate;
- int total_size = size1 + size2;
- int endpos = startpos + range;
- int anchored_start = 0;
-
- /* Check for out-of-range STARTPOS. */
- if (startpos < 0 || startpos > total_size)
- return -1;
-
- /* Fix up RANGE if it might eventually take us outside
- the virtual concatenation of STRING1 and STRING2.
- Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */
- if (endpos < 0)
- range = 0 - startpos;
- else if (endpos > total_size)
- range = total_size - startpos;
-
- /* If the search isn't to be a backwards one, don't waste time in a
- search for a pattern that must be anchored. */
- if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0)
- {
- if (startpos > 0)
- return -1;
- else
- range = 1;
- }
-
-#ifdef emacs
- /* In a forward search for something that starts with \=.
- don't keep searching past point. */
- if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0)
- {
- range = PT - startpos;
- if (range <= 0)
- return -1;
- }
-#endif /* emacs */
-
- /* Update the fastmap now if not correct already. */
- if (fastmap && !bufp->fastmap_accurate)
- if (re_compile_fastmap (bufp) == -2)
- return -2;
-
- /* See whether the pattern is anchored. */
- if (bufp->buffer[0] == begline)
- anchored_start = 1;
-
- /* Loop through the string, looking for a place to start matching. */
- for (;;)
- {
- /* If the pattern is anchored,
- skip quickly past places we cannot match.
- We don't bother to treat startpos == 0 specially
- because that case doesn't repeat. */
- if (anchored_start && startpos > 0)
- {
- if (! (bufp->newline_anchor
- && ((startpos <= size1 ? string1[startpos - 1]
- : string2[startpos - size1 - 1])
- == '\n')))
- goto advance;
- }
-
- /* If a fastmap is supplied, skip quickly over characters that
- cannot be the start of a match. If the pattern can match the
- null string, however, we don't need to skip characters; we want
- the first null string. */
- if (fastmap && startpos < total_size && !bufp->can_be_null)
- {
- if (range > 0) /* Searching forwards. */
- {
- register const char *d;
- register int lim = 0;
- int irange = range;
-
- if (startpos < size1 && startpos + range >= size1)
- lim = range - (size1 - startpos);
-
- d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
-
- /* Written out as an if-else to avoid testing `translate'
- inside the loop. */
- if (translate)
- while (range > lim
- && !fastmap[(unsigned char)
- translate[(unsigned char) *d++]])
- range--;
- else
- while (range > lim && !fastmap[(unsigned char) *d++])
- range--;
-
- startpos += irange - range;
- }
- else /* Searching backwards. */
- {
- register char c = (size1 == 0 || startpos >= size1
- ? string2[startpos - size1]
- : string1[startpos]);
-
- if (!fastmap[(unsigned char) TRANSLATE (c)])
- goto advance;
- }
- }
-
- /* If can't match the null string, and that's all we have left, fail. */
- if (range >= 0 && startpos == total_size && fastmap
- && !bufp->can_be_null)
- return -1;
-
- val = re_match_2_internal (bufp, string1, size1, string2, size2,
- startpos, regs, stop);
-#ifndef REGEX_MALLOC
-#ifdef C_ALLOCA
- alloca (0);
-#endif
-#endif
-
- if (val >= 0)
- return startpos;
-
- if (val == -2)
- return -2;
-
- advance:
- if (!range)
- break;
- else if (range > 0)
- {
- range--;
- startpos++;
- }
- else
- {
- range++;
- startpos--;
- }
- }
- return -1;
-} /* re_search_2 */
-
-/* Declarations and macros for re_match_2. */
-
-static int bcmp_translate ();
-static boolean alt_match_null_string_p (),
- common_op_match_null_string_p (),
- group_match_null_string_p ();
-
-/* This converts PTR, a pointer into one of the search strings `string1'
- and `string2' into an offset from the beginning of that string. */
-#define POINTER_TO_OFFSET(ptr) \
- (FIRST_STRING_P (ptr) \
- ? ((regoff_t) ((ptr) - string1)) \
- : ((regoff_t) ((ptr) - string2 + size1)))
-
-/* Macros for dealing with the split strings in re_match_2. */
-
-#define MATCHING_IN_FIRST_STRING (dend == end_match_1)
-
-/* Call before fetching a character with *d. This switches over to
- string2 if necessary. */
-#define PREFETCH() \
- while (d == dend) \
- { \
- /* End of string2 => fail. */ \
- if (dend == end_match_2) \
- goto fail; \
- /* End of string1 => advance to string2. */ \
- d = string2; \
- dend = end_match_2; \
- }
-
-
-/* Test if at very beginning or at very end of the virtual concatenation
- of `string1' and `string2'. If only one string, it's `string2'. */
-#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
-#define AT_STRINGS_END(d) ((d) == end2)
-
-
-/* Test if D points to a character which is word-constituent. We have
- two special cases to check for: if past the end of string1, look at
- the first character in string2; and if before the beginning of
- string2, look at the last character in string1. */
-#define WORDCHAR_P(d) \
- (SYNTAX ((d) == end1 ? *string2 \
- : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \
- == Sword)
-
-/* Disabled due to a compiler bug -- see comment at case wordbound */
-#if 0
-/* Test if the character before D and the one at D differ with respect
- to being word-constituent. */
-#define AT_WORD_BOUNDARY(d) \
- (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \
- || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
-#endif
-
-/* Free everything we malloc. */
-#ifdef MATCH_MAY_ALLOCATE
-#define FREE_VAR(var) if (var) { REGEX_FREE (var); var = NULL; } else
-#define FREE_VARIABLES() \
- do { \
- REGEX_FREE_STACK (fail_stack.stack); \
- FREE_VAR (regstart); \
- FREE_VAR (regend); \
- FREE_VAR (old_regstart); \
- FREE_VAR (old_regend); \
- FREE_VAR (best_regstart); \
- FREE_VAR (best_regend); \
- FREE_VAR (reg_info); \
- FREE_VAR (reg_dummy); \
- FREE_VAR (reg_info_dummy); \
- } while (0)
-#else
-#define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */
-#endif /* not MATCH_MAY_ALLOCATE */
-
-/* These values must meet several constraints. They must not be valid
- register values; since we have a limit of 255 registers (because
- we use only one byte in the pattern for the register number), we can
- use numbers larger than 255. They must differ by 1, because of
- NUM_FAILURE_ITEMS above. And the value for the lowest register must
- be larger than the value for the highest register, so we do not try
- to actually save any registers when none are active. */
-#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
-#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
-
-/* Matching routines. */
-
-#ifndef emacs /* Emacs never uses this. */
-/* re_match is like re_match_2 except it takes only a single string. */
-
-int
-re_match (bufp, string, size, pos, regs)
- struct re_pattern_buffer *bufp;
- const char *string;
- int size, pos;
- struct re_registers *regs;
-{
- int result = re_match_2_internal (bufp, NULL, 0, string, size,
- pos, regs, size);
- alloca (0);
- return result;
-}
-#endif /* not emacs */
-
-
-/* re_match_2 matches the compiled pattern in BUFP against the
- the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
- and SIZE2, respectively). We start matching at POS, and stop
- matching at STOP.
-
- If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
- store offsets for the substring each group matched in REGS. See the
- documentation for exactly how many groups we fill.
-
- We return -1 if no match, -2 if an internal error (such as the
- failure stack overflowing). Otherwise, we return the length of the
- matched substring. */
-
-int
-re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
- struct re_pattern_buffer *bufp;
- const char *string1, *string2;
- int size1, size2;
- int pos;
- struct re_registers *regs;
- int stop;
-{
- int result = re_match_2_internal (bufp, string1, size1, string2, size2,
- pos, regs, stop);
- alloca (0);
- return result;
-}
-
-/* This is a separate function so that we can force an alloca cleanup
- afterwards. */
-static int
-re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
- struct re_pattern_buffer *bufp;
- const char *string1, *string2;
- int size1, size2;
- int pos;
- struct re_registers *regs;
- int stop;
-{
- /* General temporaries. */
- int mcnt;
- unsigned char *p1;
-
- /* Just past the end of the corresponding string. */
- const char *end1, *end2;
-
- /* Pointers into string1 and string2, just past the last characters in
- each to consider matching. */
- const char *end_match_1, *end_match_2;
-
- /* Where we are in the data, and the end of the current string. */
- const char *d, *dend;
-
- /* Where we are in the pattern, and the end of the pattern. */
- unsigned char *p = bufp->buffer;
- register unsigned char *pend = p + bufp->used;
-
- /* Mark the opcode just after a start_memory, so we can test for an
- empty subpattern when we get to the stop_memory. */
- unsigned char *just_past_start_mem = 0;
-
- /* We use this to map every character in the string. */
- RE_TRANSLATE_TYPE translate = bufp->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
- restart, regend, and reg_info for all registers corresponding to
- the subexpressions we're currently inside, plus the number of such
- registers, and, finally, two char *'s. The first char * is where
- to resume scanning the pattern; the second one is where to resume
- scanning the strings. If the latter is zero, the failure point is
- a ``dummy''; if a failure happens and the failure point is a dummy,
- it gets discarded and the next next one is tried. */
-#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */
- fail_stack_type fail_stack;
-#endif
-#ifdef DEBUG
- static unsigned failure_id = 0;
- unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
-#endif
-
- /* This holds the pointer to the failure stack, when
- it is allocated relocatably. */
- fail_stack_elt_t *failure_stack_ptr;
-
- /* We fill all the registers internally, independent of what we
- return, for use in backreferences. The number here includes
- an element for register zero. */
- unsigned num_regs = bufp->re_nsub + 1;
-
- /* The currently active registers. */
- unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG;
- unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG;
-
- /* Information on the contents of registers. These are pointers into
- the input strings; they record just what was matched (on this
- attempt) by a subexpression part of the pattern, that is, the
- regnum-th regstart pointer points to where in the pattern we began
- matching and the regnum-th regend points to right after where we
- stopped matching the regnum-th subexpression. (The zeroth register
- keeps track of what the whole pattern matches.) */
-#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
- const char **regstart, **regend;
-#endif
-
- /* If a group that's operated upon by a repetition operator fails to
- match anything, then the register for its start will need to be
- restored because it will have been set to wherever in the string we
- are when we last see its open-group operator. Similarly for a
- register's end. */
-#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
- const char **old_regstart, **old_regend;
-#endif
-
- /* The is_active field of reg_info helps us keep track of which (possibly
- nested) subexpressions we are currently in. The matched_something
- field of reg_info[reg_num] helps us tell whether or not we have
- matched any of the pattern so far this time through the reg_num-th
- subexpression. These two fields get reset each time through any
- loop their register is in. */
-#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */
- register_info_type *reg_info;
-#endif
-
- /* The following record the register info as found in the above
- variables when we find a match better than any we've seen before.
- This happens as we backtrack through the failure points, which in
- turn happens only if we have not yet matched the entire string. */
- unsigned best_regs_set = false;
-#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
- const char **best_regstart, **best_regend;
-#endif
-
- /* Logically, this is `best_regend[0]'. But we don't want to have to
- allocate space for that if we're not allocating space for anything
- else (see below). Also, we never need info about register 0 for
- any of the other register vectors, and it seems rather a kludge to
- treat `best_regend' differently than the rest. So we keep track of
- the end of the best match so far in a separate variable. We
- initialize this to NULL so that when we backtrack the first time
- and need to test it, it's not garbage. */
- const char *match_end = NULL;
-
- /* This helps SET_REGS_MATCHED avoid doing redundant work. */
- int set_regs_matched_done = 0;
-
- /* Used when we pop values we don't care about. */
-#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
- const char **reg_dummy;
- register_info_type *reg_info_dummy;
-#endif
-
-#ifdef DEBUG
- /* Counts the total number of registers pushed. */
- unsigned num_regs_pushed = 0;
-#endif
-
- DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
-
- INIT_FAIL_STACK ();
-
-#ifdef MATCH_MAY_ALLOCATE
- /* Do not bother to initialize all the register variables if there are
- no groups in the pattern, as it takes a fair amount of time. If
- there are groups, we include space for register 0 (the whole
- pattern), even though we never use it, since it simplifies the
- array indexing. We should fix this. */
- if (bufp->re_nsub)
- {
- regstart = REGEX_TALLOC (num_regs, const char *);
- regend = REGEX_TALLOC (num_regs, const char *);
- old_regstart = REGEX_TALLOC (num_regs, const char *);
- old_regend = REGEX_TALLOC (num_regs, const char *);
- best_regstart = REGEX_TALLOC (num_regs, const char *);
- best_regend = REGEX_TALLOC (num_regs, const char *);
- reg_info = REGEX_TALLOC (num_regs, register_info_type);
- reg_dummy = REGEX_TALLOC (num_regs, const char *);
- reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type);
-
- if (!(regstart && regend && old_regstart && old_regend && reg_info
- && best_regstart && best_regend && reg_dummy && reg_info_dummy))
- {
- FREE_VARIABLES ();
- return -2;
- }
- }
- else
- {
- /* We must initialize all our variables to NULL, so that
- `FREE_VARIABLES' doesn't try to free them. */
- regstart = regend = old_regstart = old_regend = best_regstart
- = best_regend = reg_dummy = NULL;
- reg_info = reg_info_dummy = (register_info_type *) NULL;
- }
-#endif /* MATCH_MAY_ALLOCATE */
-
- /* The starting position is bogus. */
- if (pos < 0 || pos > size1 + size2)
- {
- FREE_VARIABLES ();
- return -1;
- }
-
- /* Initialize subexpression text positions to -1 to mark ones that no
- start_memory/stop_memory has been seen for. Also initialize the
- register information struct. */
- for (mcnt = 1; mcnt < num_regs; mcnt++)
- {
- regstart[mcnt] = regend[mcnt]
- = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
-
- REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
- IS_ACTIVE (reg_info[mcnt]) = 0;
- MATCHED_SOMETHING (reg_info[mcnt]) = 0;
- EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
- }
-
- /* We move `string1' into `string2' if the latter's empty -- but not if
- `string1' is null. */
- if (size2 == 0 && string1 != NULL)
- {
- string2 = string1;
- size2 = size1;
- string1 = 0;
- size1 = 0;
- }
- end1 = string1 + size1;
- end2 = string2 + size2;
-
- /* Compute where to stop matching, within the two strings. */
- if (stop <= size1)
- {
- end_match_1 = string1 + stop;
- end_match_2 = string2;
- }
- else
- {
- end_match_1 = end1;
- end_match_2 = string2 + stop - size1;
- }
-
- /* `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 (size1 > 0 && pos <= size1)
- {
- d = string1 + pos;
- dend = end_match_1;
- }
- else
- {
- d = string2 + pos - size1;
- dend = end_match_2;
- }
-
- DEBUG_PRINT1 ("The compiled pattern is: ");
- DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
- DEBUG_PRINT1 ("The string to match is: `");
- DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
- DEBUG_PRINT1 ("'\n");
-
- /* This loops over pattern commands. It exits by returning from the
- function if the match is complete, or it drops through if the match
- fails at this starting point in the input data. */
- for (;;)
- {
- DEBUG_PRINT2 ("\n0x%x: ", p);
-
- if (p == pend)
- { /* End of pattern means we might have succeeded. */
- DEBUG_PRINT1 ("end of pattern ... ");
-
- /* If we haven't matched the entire string, and we want the
- longest match, try backtracking. */
- if (d != end_match_2)
- {
- /* 1 if this match ends in the same string (string1 or string2)
- as the best previous match. */
- boolean same_str_p = (FIRST_STRING_P (match_end)
- == MATCHING_IN_FIRST_STRING);
- /* 1 if this match is the best seen so far. */
- boolean best_match_p;
-
- /* AIX compiler got confused when this was combined
- with the previous declaration. */
- if (same_str_p)
- best_match_p = d > match_end;
- else
- best_match_p = !MATCHING_IN_FIRST_STRING;
-
- DEBUG_PRINT1 ("backtracking.\n");
-
- if (!FAIL_STACK_EMPTY ())
- { /* More failure points to try. */
-
- /* If exceeds best match so far, save it. */
- if (!best_regs_set || best_match_p)
- {
- best_regs_set = true;
- match_end = d;
-
- DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
-
- for (mcnt = 1; mcnt < num_regs; mcnt++)
- {
- best_regstart[mcnt] = regstart[mcnt];
- best_regend[mcnt] = regend[mcnt];
- }
- }
- goto fail;
- }
-
- /* If no failure points, don't restore garbage. And if
- last match is real best match, don't restore second
- best one. */
- else if (best_regs_set && !best_match_p)
- {
- restore_best_regs:
- /* Restore best match. It may happen that `dend ==
- end_match_1' while the restored d is in string2.
- For example, the pattern `x.*y.*z' against the
- strings `x-' and `y-z-', if the two strings are
- not consecutive in memory. */
- DEBUG_PRINT1 ("Restoring best registers.\n");
-
- d = match_end;
- dend = ((d >= string1 && d <= end1)
- ? end_match_1 : end_match_2);
-
- for (mcnt = 1; mcnt < num_regs; mcnt++)
- {
- regstart[mcnt] = best_regstart[mcnt];
- regend[mcnt] = best_regend[mcnt];
- }
- }
- } /* d != end_match_2 */
-
- succeed_label:
- DEBUG_PRINT1 ("Accepting match.\n");
-
- /* If caller wants register contents data back, do it. */
- if (regs && !bufp->no_sub)
- {
- /* Have the register data arrays been allocated? */
- if (bufp->regs_allocated == REGS_UNALLOCATED)
- { /* No. So allocate them with malloc. We need one
- extra element beyond `num_regs' for the `-1' marker
- GNU code uses. */
- regs->num_regs = MAX (RE_NREGS, num_regs + 1);
- regs->start = TALLOC (regs->num_regs, regoff_t);
- regs->end = TALLOC (regs->num_regs, regoff_t);
- if (regs->start == NULL || regs->end == NULL)
- {
- FREE_VARIABLES ();
- return -2;
- }
- bufp->regs_allocated = REGS_REALLOCATE;
- }
- else if (bufp->regs_allocated == REGS_REALLOCATE)
- { /* Yes. If we need more elements than were already
- allocated, reallocate them. If we need fewer, just
- leave it alone. */
- if (regs->num_regs < num_regs + 1)
- {
- regs->num_regs = num_regs + 1;
- RETALLOC (regs->start, regs->num_regs, regoff_t);
- RETALLOC (regs->end, regs->num_regs, regoff_t);
- if (regs->start == NULL || regs->end == NULL)
- {
- FREE_VARIABLES ();
- return -2;
- }
- }
- }
- else
- {
- /* These braces fend off a "empty body in an else-statement"
- warning under GCC when assert expands to nothing. */
- assert (bufp->regs_allocated == REGS_FIXED);
- }
-
- /* Convert the pointer data in `regstart' and `regend' to
- indices. Register zero has to be set differently,
- since we haven't kept track of any info for it. */
- if (regs->num_regs > 0)
- {
- regs->start[0] = pos;
- regs->end[0] = (MATCHING_IN_FIRST_STRING
- ? ((regoff_t) (d - string1))
- : ((regoff_t) (d - string2 + size1)));
- }
-
- /* Go through the first `min (num_regs, regs->num_regs)'
- registers, since that is all we initialized. */
- for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++)
- {
- if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
- regs->start[mcnt] = regs->end[mcnt] = -1;
- else
- {
- regs->start[mcnt]
- = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]);
- regs->end[mcnt]
- = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]);
- }
- }
-
- /* If the regs structure we return has more elements than
- were in the pattern, set the extra elements to -1. If
- we (re)allocated the registers, this is the case,
- because we always allocate enough to have at least one
- -1 at the end. */
- for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++)
- regs->start[mcnt] = regs->end[mcnt] = -1;
- } /* regs && !bufp->no_sub */
-
- DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
- nfailure_points_pushed, nfailure_points_popped,
- nfailure_points_pushed - nfailure_points_popped);
- DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
-
- mcnt = d - pos - (MATCHING_IN_FIRST_STRING
- ? string1
- : string2 - size1);
-
- DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
-
- FREE_VARIABLES ();
- return mcnt;
- }
-
- /* Otherwise match next pattern command. */
- switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
- {
- /* Ignore these. Used to ignore the n of succeed_n's which
- currently have n == 0. */
- case no_op:
- DEBUG_PRINT1 ("EXECUTING no_op.\n");
- break;
-
- case succeed:
- DEBUG_PRINT1 ("EXECUTING succeed.\n");
- goto succeed_label;
-
- /* Match the next n pattern characters exactly. The following
- byte in the pattern defines n, and the n bytes after that
- are the characters to match. */
- case exactn:
- mcnt = *p++;
- DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
-
- /* This is written out as an if-else so we don't waste time
- testing `translate' inside the loop. */
- if (translate)
- {
- do
- {
- PREFETCH ();
- if ((unsigned char) translate[(unsigned char) *d++]
- != (unsigned char) *p++)
- goto fail;
- }
- while (--mcnt);
- }
- else
- {
- do
- {
- PREFETCH ();
- if (*d++ != (char) *p++) goto fail;
- }
- while (--mcnt);
- }
- SET_REGS_MATCHED ();
- break;
-
-
- /* Match any character except possibly a newline or a null. */
- case anychar:
- DEBUG_PRINT1 ("EXECUTING anychar.\n");
-
- PREFETCH ();
-
- if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
- || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
- goto fail;
-
- SET_REGS_MATCHED ();
- DEBUG_PRINT2 (" Matched `%d'.\n", *d);
- d++;
- break;
-
-
- case charset:
- case charset_not:
- {
- register unsigned char c;
- boolean not = (re_opcode_t) *(p - 1) == charset_not;
-
- DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : "");
-
- PREFETCH ();
- c = TRANSLATE (*d); /* The character to match. */
-
- /* Cast to `unsigned' instead of `unsigned char' in case the
- bit list is a full 32 bytes long. */
- if (c < (unsigned) (*p * BYTEWIDTH)
- && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
- not = !not;
-
- p += 1 + *p;
-
- if (!not) goto fail;
-
- SET_REGS_MATCHED ();
- d++;
- break;
- }
-
-
- /* The beginning of a group is represented by start_memory.
- The arguments are the register number in the next byte, and the
- number of groups inner to this one in the next. The text
- matched within the group is recorded (in the internal
- registers data structure) under the register number. */
- case start_memory:
- DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]);
-
- /* Find out if this group can match the empty string. */
- p1 = p; /* To send to group_match_null_string_p. */
-
- if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
- REG_MATCH_NULL_STRING_P (reg_info[*p])
- = group_match_null_string_p (&p1, pend, reg_info);
-
- /* Save the position in the string where we were the last time
- we were at this open-group operator in case the group is
- operated upon by a repetition operator, e.g., with `(a*)*b'
- against `ab'; then we want to ignore where we are now in
- the string in case this attempt to match fails. */
- old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
- ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
- : regstart[*p];
- DEBUG_PRINT2 (" old_regstart: %d\n",
- POINTER_TO_OFFSET (old_regstart[*p]));
-
- regstart[*p] = d;
- DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
-
- IS_ACTIVE (reg_info[*p]) = 1;
- MATCHED_SOMETHING (reg_info[*p]) = 0;
-
- /* Clear this whenever we change the register activity status. */
- set_regs_matched_done = 0;
-
- /* This is the new highest active register. */
- highest_active_reg = *p;
-
- /* If nothing was active before, this is the new lowest active
- register. */
- if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
- lowest_active_reg = *p;
-
- /* Move past the register number and inner group count. */
- p += 2;
- just_past_start_mem = p;
-
- break;
-
-
- /* The stop_memory opcode represents the end of a group. Its
- arguments are the same as start_memory's: the register
- number, and the number of inner groups. */
- case stop_memory:
- DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]);
-
- /* We need to save the string position the last time we were at
- this close-group operator in case the group is operated
- upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
- against `aba'; then we want to ignore where we are now in
- the string in case this attempt to match fails. */
- old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
- ? REG_UNSET (regend[*p]) ? d : regend[*p]
- : regend[*p];
- DEBUG_PRINT2 (" old_regend: %d\n",
- POINTER_TO_OFFSET (old_regend[*p]));
-
- regend[*p] = d;
- DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
-
- /* This register isn't active anymore. */
- IS_ACTIVE (reg_info[*p]) = 0;
-
- /* Clear this whenever we change the register activity status. */
- set_regs_matched_done = 0;
-
- /* If this was the only register active, nothing is active
- anymore. */
- if (lowest_active_reg == highest_active_reg)
- {
- lowest_active_reg = NO_LOWEST_ACTIVE_REG;
- highest_active_reg = NO_HIGHEST_ACTIVE_REG;
- }
- else
- { /* We must scan for the new highest active register, since
- it isn't necessarily one less than now: consider
- (a(b)c(d(e)f)g). When group 3 ends, after the f), the
- new highest active register is 1. */
- unsigned char r = *p - 1;
- while (r > 0 && !IS_ACTIVE (reg_info[r]))
- r--;
-
- /* If we end up at register zero, that means that we saved
- the registers as the result of an `on_failure_jump', not
- a `start_memory', and we jumped to past the innermost
- `stop_memory'. For example, in ((.)*) we save
- registers 1 and 2 as a result of the *, but when we pop
- back to the second ), we are at the stop_memory 1.
- Thus, nothing is active. */
- if (r == 0)
- {
- lowest_active_reg = NO_LOWEST_ACTIVE_REG;
- highest_active_reg = NO_HIGHEST_ACTIVE_REG;
- }
- else
- highest_active_reg = r;
- }
-
- /* If just failed to match something this time around with a
- group that's operated on by a repetition operator, try to
- force exit from the ``loop'', and restore the register
- information for this group that we had before trying this
- last match. */
- if ((!MATCHED_SOMETHING (reg_info[*p])
- || just_past_start_mem == p - 1)
- && (p + 2) < pend)
- {
- boolean is_a_jump_n = false;
-
- p1 = p + 2;
- mcnt = 0;
- switch ((re_opcode_t) *p1++)
- {
- case jump_n:
- is_a_jump_n = true;
- case pop_failure_jump:
- case maybe_pop_jump:
- case jump:
- case dummy_failure_jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- if (is_a_jump_n)
- p1 += 2;
- break;
-
- default:
- /* do nothing */ ;
- }
- p1 += mcnt;
-
- /* If the next operation is a jump backwards in the pattern
- to an on_failure_jump right before the start_memory
- corresponding to this stop_memory, exit from the loop
- by forcing a failure after pushing on the stack the
- on_failure_jump's jump in the pattern, and d. */
- if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
- && (re_opcode_t) p1[3] == start_memory && p1[4] == *p)
- {
- /* If this group ever matched anything, then restore
- what its registers were before trying this last
- failed match, e.g., with `(a*)*b' against `ab' for
- regstart[1], and, e.g., with `((a*)*(b*)*)*'
- against `aba' for regend[3].
-
- Also restore the registers for inner groups for,
- e.g., `((a*)(b*))*' against `aba' (register 3 would
- otherwise get trashed). */
-
- if (EVER_MATCHED_SOMETHING (reg_info[*p]))
- {
- unsigned r;
-
- EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
-
- /* Restore this and inner groups' (if any) registers. */
- for (r = *p; r < *p + *(p + 1); r++)
- {
- regstart[r] = old_regstart[r];
-
- /* xx why this test? */
- if (old_regend[r] >= regstart[r])
- regend[r] = old_regend[r];
- }
- }
- p1++;
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
-
- goto fail;
- }
- }
-
- /* Move past the register number and the inner group count. */
- p += 2;
- break;
-
-
- /* \<digit> has been turned into a `duplicate' command which is
- followed by the numeric value of <digit> as the register number. */
- case duplicate:
- {
- register const char *d2, *dend2;
- int regno = *p++; /* Get which register to match against. */
- DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
-
- /* Can't back reference a group which we've never matched. */
- if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
- goto fail;
-
- /* Where in input to try to start matching. */
- d2 = regstart[regno];
-
- /* Where to stop matching; if both the place to start and
- the place to stop matching are in the same string, then
- set to the place to stop, otherwise, for now have to use
- the end of the first string. */
-
- dend2 = ((FIRST_STRING_P (regstart[regno])
- == FIRST_STRING_P (regend[regno]))
- ? regend[regno] : end_match_1);
- for (;;)
- {
- /* If necessary, advance to next segment in register
- contents. */
- while (d2 == dend2)
- {
- if (dend2 == end_match_2) break;
- if (dend2 == regend[regno]) break;
-
- /* End of string1 => advance to string2. */
- d2 = string2;
- dend2 = regend[regno];
- }
- /* At end of register contents => success */
- if (d2 == dend2) break;
-
- /* If necessary, advance to next segment in data. */
- PREFETCH ();
-
- /* How many characters left in this segment to match. */
- mcnt = dend - d;
-
- /* Want how many consecutive characters we can match in
- one shot, so, if necessary, adjust the count. */
- if (mcnt > dend2 - d2)
- mcnt = dend2 - d2;
-
- /* Compare that many; failure if mismatch, else move
- past them. */
- if (translate
- ? bcmp_translate (d, d2, mcnt, translate)
- : bcmp (d, d2, mcnt))
- goto fail;
- d += mcnt, d2 += mcnt;
-
- /* Do this because we've match some characters. */
- SET_REGS_MATCHED ();
- }
- }
- break;
-
-
- /* begline matches the empty string at the beginning of the string
- (unless `not_bol' is set in `bufp'), and, if
- `newline_anchor' is set, after newlines. */
- case begline:
- DEBUG_PRINT1 ("EXECUTING begline.\n");
-
- if (AT_STRINGS_BEG (d))
- {
- if (!bufp->not_bol) break;
- }
- else if (d[-1] == '\n' && bufp->newline_anchor)
- {
- break;
- }
- /* In all other cases, we fail. */
- goto fail;
-
-
- /* endline is the dual of begline. */
- case endline:
- DEBUG_PRINT1 ("EXECUTING endline.\n");
-
- if (AT_STRINGS_END (d))
- {
- if (!bufp->not_eol) break;
- }
-
- /* We have to ``prefetch'' the next character. */
- else if ((d == end1 ? *string2 : *d) == '\n'
- && bufp->newline_anchor)
- {
- break;
- }
- goto fail;
-
-
- /* Match at the very beginning of the data. */
- case begbuf:
- DEBUG_PRINT1 ("EXECUTING begbuf.\n");
- if (AT_STRINGS_BEG (d))
- break;
- goto fail;
-
-
- /* Match at the very end of the data. */
- case endbuf:
- DEBUG_PRINT1 ("EXECUTING endbuf.\n");
- if (AT_STRINGS_END (d))
- break;
- goto fail;
-
-
- /* on_failure_keep_string_jump is used to optimize `.*\n'. It
- pushes NULL as the value for the string on the stack. Then
- `pop_failure_point' will keep the current value for the
- string, instead of restoring it. To see why, consider
- matching `foo\nbar' against `.*\n'. The .* matches the foo;
- then the . fails against the \n. But the next thing we want
- to do is match the \n against the \n; if we restored the
- string value, we would be back at the foo.
-
- Because this is used only in specific cases, we don't need to
- check all the things that `on_failure_jump' does, to make
- sure the right things get saved on the stack. Hence we don't
- share its code. The only reason to push anything on the
- stack at all is that otherwise we would have to change
- `anychar's code to do something besides goto fail in this
- case; that seems worse than this. */
- case on_failure_keep_string_jump:
- DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
-
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
-
- PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
- break;
-
-
- /* Uses of on_failure_jump:
-
- Each alternative starts with an on_failure_jump that points
- to the beginning of the next alternative. Each alternative
- except the last ends with a jump that in effect jumps past
- the rest of the alternatives. (They really jump to the
- ending jump of the following alternative, because tensioning
- these jumps is a hassle.)
-
- Repeats start with an on_failure_jump that points past both
- the repetition text and either the following jump or
- pop_failure_jump back to this on_failure_jump. */
- case on_failure_jump:
- on_failure:
- DEBUG_PRINT1 ("EXECUTING on_failure_jump");
-
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
-
- /* If this on_failure_jump comes right before a group (i.e.,
- the original * applied to a group), save the information
- for that group and all inner ones, so that if we fail back
- to this point, the group's information will be correct.
- For example, in \(a*\)*\1, we need the preceding group,
- and in \(zz\(a*\)b*\)\2, we need the inner group. */
-
- /* We can't use `p' to check ahead because we push
- a failure point to `p + mcnt' after we do this. */
- p1 = p;
-
- /* We need to skip no_op's before we look for the
- start_memory in case this on_failure_jump is happening as
- the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
- against aba. */
- while (p1 < pend && (re_opcode_t) *p1 == no_op)
- p1++;
-
- if (p1 < pend && (re_opcode_t) *p1 == start_memory)
- {
- /* We have a new highest active register now. This will
- get reset at the start_memory we are about to get to,
- but we will have saved all the registers relevant to
- this repetition op, as described above. */
- highest_active_reg = *(p1 + 1) + *(p1 + 2);
- if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
- lowest_active_reg = *(p1 + 1);
- }
-
- DEBUG_PRINT1 (":\n");
- PUSH_FAILURE_POINT (p + mcnt, d, -2);
- break;
-
-
- /* A smart repeat ends with `maybe_pop_jump'.
- We change it to either `pop_failure_jump' or `jump'. */
- case maybe_pop_jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
- {
- register unsigned char *p2 = p;
-
- /* Compare the beginning of the repeat with what in the
- pattern follows its end. If we can establish that there
- is nothing that they would both match, i.e., that we
- would have to backtrack because of (as in, e.g., `a*a')
- then we can change to pop_failure_jump, because we'll
- never have to backtrack.
-
- This is not true in the case of alternatives: in
- `(a|ab)*' we do need to backtrack to the `ab' alternative
- (e.g., if the string was `ab'). But instead of trying to
- detect that here, the alternative has put on a dummy
- failure point which is what we will end up popping. */
-
- /* Skip over open/close-group commands.
- If what follows this loop is a ...+ construct,
- look at what begins its body, since we will have to
- match at least one of that. */
- while (1)
- {
- if (p2 + 2 < pend
- && ((re_opcode_t) *p2 == stop_memory
- || (re_opcode_t) *p2 == start_memory))
- p2 += 3;
- else if (p2 + 6 < pend
- && (re_opcode_t) *p2 == dummy_failure_jump)
- p2 += 6;
- else
- break;
- }
-
- p1 = p + mcnt;
- /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
- to the `maybe_finalize_jump' of this case. Examine what
- follows. */
-
- /* If we're at the end of the pattern, we can change. */
- if (p2 == pend)
- {
- /* Consider what happens when matching ":\(.*\)"
- against ":/". I don't really understand this code
- yet. */
- p[-3] = (unsigned char) pop_failure_jump;
- DEBUG_PRINT1
- (" End of pattern: change to `pop_failure_jump'.\n");
- }
-
- else if ((re_opcode_t) *p2 == exactn
- || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
- {
- register unsigned char c
- = *p2 == (unsigned char) endline ? '\n' : p2[2];
-
- if ((re_opcode_t) p1[3] == exactn && p1[5] != c)
- {
- p[-3] = (unsigned char) pop_failure_jump;
- DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n",
- c, p1[5]);
- }
-
- else if ((re_opcode_t) p1[3] == charset
- || (re_opcode_t) p1[3] == charset_not)
- {
- int not = (re_opcode_t) p1[3] == charset_not;
-
- if (c < (unsigned char) (p1[4] * BYTEWIDTH)
- && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
- not = !not;
-
- /* `not' is equal to 1 if c would match, which means
- that we can't change to pop_failure_jump. */
- if (!not)
- {
- p[-3] = (unsigned char) pop_failure_jump;
- DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
- }
- }
- }
- else if ((re_opcode_t) *p2 == charset)
- {
-#ifdef DEBUG
- register unsigned char c
- = *p2 == (unsigned char) endline ? '\n' : p2[2];
-#endif
-
- if ((re_opcode_t) p1[3] == exactn
- && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5]
- && (p2[2 + p1[5] / BYTEWIDTH]
- & (1 << (p1[5] % BYTEWIDTH)))))
- {
- p[-3] = (unsigned char) pop_failure_jump;
- DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n",
- c, p1[5]);
- }
-
- else if ((re_opcode_t) p1[3] == charset_not)
- {
- int idx;
- /* We win if the charset_not inside the loop
- lists every character listed in the charset after. */
- for (idx = 0; idx < (int) p2[1]; idx++)
- if (! (p2[2 + idx] == 0
- || (idx < (int) p1[4]
- && ((p2[2 + idx] & ~ p1[5 + idx]) == 0))))
- break;
-
- if (idx == p2[1])
- {
- p[-3] = (unsigned char) pop_failure_jump;
- DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
- }
- }
- else if ((re_opcode_t) p1[3] == charset)
- {
- int idx;
- /* We win if the charset inside the loop
- has no overlap with the one after the loop. */
- for (idx = 0;
- idx < (int) p2[1] && idx < (int) p1[4];
- idx++)
- if ((p2[2 + idx] & p1[5 + idx]) != 0)
- break;
-
- if (idx == p2[1] || idx == p1[4])
- {
- p[-3] = (unsigned char) pop_failure_jump;
- DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
- }
- }
- }
- }
- p -= 2; /* Point at relative address again. */
- if ((re_opcode_t) p[-1] != pop_failure_jump)
- {
- p[-1] = (unsigned char) jump;
- DEBUG_PRINT1 (" Match => jump.\n");
- goto unconditional_jump;
- }
- /* Note fall through. */
-
-
- /* The end of a simple repeat has a pop_failure_jump back to
- its matching on_failure_jump, where the latter will push a
- failure point. The pop_failure_jump takes off failure
- points put on by this pop_failure_jump's matching
- on_failure_jump; we got through the pattern to here from the
- matching on_failure_jump, so didn't fail. */
- case pop_failure_jump:
- {
- /* We need to pass separate storage for the lowest and
- highest registers, even though we don't care about the
- actual values. Otherwise, we will restore only one
- register from the stack, since lowest will == highest in
- `pop_failure_point'. */
- unsigned dummy_low_reg, dummy_high_reg;
- unsigned char *pdummy;
- const char *sdummy;
-
- DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
- POP_FAILURE_POINT (sdummy, pdummy,
- dummy_low_reg, dummy_high_reg,
- reg_dummy, reg_dummy, reg_info_dummy);
- }
- /* Note fall through. */
-
-
- /* Unconditionally jump (without popping any failure points). */
- case jump:
- unconditional_jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */
- DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
- p += mcnt; /* Do the jump. */
- DEBUG_PRINT2 ("(to 0x%x).\n", p);
- break;
-
-
- /* We need this opcode so we can detect where alternatives end
- in `group_match_null_string_p' et al. */
- case jump_past_alt:
- DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
- goto unconditional_jump;
-
-
- /* Normally, the on_failure_jump pushes a failure point, which
- then gets popped at pop_failure_jump. We will end up at
- pop_failure_jump, also, and with a pattern of, say, `a+', we
- are skipping over the on_failure_jump, so we have to push
- something meaningless for pop_failure_jump to pop. */
- case dummy_failure_jump:
- DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
- /* It doesn't matter what we push for the string here. What
- the code at `fail' tests is the value for the pattern. */
- PUSH_FAILURE_POINT (0, 0, -2);
- goto unconditional_jump;
-
-
- /* At the end of an alternative, we need to push a dummy failure
- point in case we are followed by a `pop_failure_jump', because
- we don't want the failure point for the alternative to be
- popped. For example, matching `(a|ab)*' against `aab'
- requires that we match the `ab' alternative. */
- case push_dummy_failure:
- DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
- /* See comments just above at `dummy_failure_jump' about the
- two zeroes. */
- PUSH_FAILURE_POINT (0, 0, -2);
- break;
-
- /* Have to succeed matching what follows at least n times.
- After that, handle like `on_failure_jump'. */
- case succeed_n:
- EXTRACT_NUMBER (mcnt, p + 2);
- DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
-
- assert (mcnt >= 0);
- /* Originally, this is how many times we HAVE to succeed. */
- if (mcnt > 0)
- {
- mcnt--;
- p += 2;
- STORE_NUMBER_AND_INCR (p, mcnt);
- DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p, mcnt);
- }
- else if (mcnt == 0)
- {
- DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2);
- p[2] = (unsigned char) no_op;
- p[3] = (unsigned char) no_op;
- goto on_failure;
- }
- break;
-
- case jump_n:
- EXTRACT_NUMBER (mcnt, p + 2);
- DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
-
- /* Originally, this is how many times we CAN jump. */
- if (mcnt)
- {
- mcnt--;
- STORE_NUMBER (p + 2, mcnt);
- goto unconditional_jump;
- }
- /* If don't have to jump any more, skip over the rest of command. */
- else
- p += 4;
- break;
-
- case set_number_at:
- {
- DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
-
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- p1 = p + mcnt;
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt);
- STORE_NUMBER (p1, mcnt);
- break;
- }
-
-#if 0
- /* The DEC Alpha C compiler 3.x generates incorrect code for the
- test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of
- AT_WORD_BOUNDARY, so this code is disabled. Expanding the
- macro and introducing temporary variables works around the bug. */
-
- case wordbound:
- DEBUG_PRINT1 ("EXECUTING wordbound.\n");
- if (AT_WORD_BOUNDARY (d))
- break;
- goto fail;
-
- case notwordbound:
- DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
- if (AT_WORD_BOUNDARY (d))
- goto fail;
- break;
-#else
- case wordbound:
- {
- boolean prevchar, thischar;
-
- DEBUG_PRINT1 ("EXECUTING wordbound.\n");
- if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
- break;
-
- prevchar = WORDCHAR_P (d - 1);
- thischar = WORDCHAR_P (d);
- if (prevchar != thischar)
- break;
- goto fail;
- }
-
- case notwordbound:
- {
- boolean prevchar, thischar;
-
- DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
- if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
- goto fail;
-
- prevchar = WORDCHAR_P (d - 1);
- thischar = WORDCHAR_P (d);
- if (prevchar != thischar)
- goto fail;
- break;
- }
-#endif
-
- case wordbeg:
- DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
- if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
- break;
- goto fail;
-
- case wordend:
- DEBUG_PRINT1 ("EXECUTING wordend.\n");
- if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
- && (!WORDCHAR_P (d) || AT_STRINGS_END (d)))
- break;
- goto fail;
-
-#ifdef emacs
- case before_dot:
- DEBUG_PRINT1 ("EXECUTING before_dot.\n");
- if (PTR_CHAR_POS ((unsigned char *) d) >= PT)
- goto fail;
- break;
-
- case at_dot:
- DEBUG_PRINT1 ("EXECUTING at_dot.\n");
- if (PTR_CHAR_POS ((unsigned char *) d) != PT)
- goto fail;
- break;
-
- case after_dot:
- DEBUG_PRINT1 ("EXECUTING after_dot.\n");
- if (PTR_CHAR_POS ((unsigned char *) d) <= PT)
- goto fail;
- break;
-
- case syntaxspec:
- DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
- mcnt = *p++;
- goto matchsyntax;
-
- case wordchar:
- DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
- mcnt = (int) Sword;
- matchsyntax:
- PREFETCH ();
- /* Can't use *d++ here; SYNTAX may be an unsafe macro. */
- d++;
- if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt)
- goto fail;
- SET_REGS_MATCHED ();
- break;
-
- case notsyntaxspec:
- DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
- mcnt = *p++;
- goto matchnotsyntax;
-
- case notwordchar:
- DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
- mcnt = (int) Sword;
- matchnotsyntax:
- PREFETCH ();
- /* Can't use *d++ here; SYNTAX may be an unsafe macro. */
- d++;
- if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt)
- goto fail;
- SET_REGS_MATCHED ();
- break;
-
-#else /* not emacs */
- case wordchar:
- DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
- PREFETCH ();
- if (!WORDCHAR_P (d))
- goto fail;
- SET_REGS_MATCHED ();
- d++;
- break;
-
- case notwordchar:
- DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
- PREFETCH ();
- if (WORDCHAR_P (d))
- goto fail;
- SET_REGS_MATCHED ();
- d++;
- break;
-#endif /* not emacs */
-
- default:
- abort ();
- }
- continue; /* Successfully executed one pattern command; keep going. */
-
-
- /* We goto here if a matching operation fails. */
- fail:
- if (!FAIL_STACK_EMPTY ())
- { /* A restart point is known. Restore to that state. */
- DEBUG_PRINT1 ("\nFAIL:\n");
- POP_FAILURE_POINT (d, p,
- lowest_active_reg, highest_active_reg,
- regstart, regend, reg_info);
-
- /* If this failure point is a dummy, try the next one. */
- if (!p)
- goto fail;
-
- /* If we failed to the end of the pattern, don't examine *p. */
- assert (p <= pend);
- if (p < pend)
- {
- boolean is_a_jump_n = false;
-
- /* If failed to a backwards jump that's part of a repetition
- loop, need to pop this failure point and use the next one. */
- switch ((re_opcode_t) *p)
- {
- case jump_n:
- is_a_jump_n = true;
- case maybe_pop_jump:
- case pop_failure_jump:
- case jump:
- p1 = p + 1;
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- p1 += mcnt;
-
- if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
- || (!is_a_jump_n
- && (re_opcode_t) *p1 == on_failure_jump))
- goto fail;
- break;
- default:
- /* do nothing */ ;
- }
- }
-
- if (d >= string1 && d <= end1)
- dend = end_match_1;
- }
- else
- break; /* Matching at this starting point really fails. */
- } /* for (;;) */
-
- if (best_regs_set)
- goto restore_best_regs;
-
- FREE_VARIABLES ();
-
- return -1; /* Failure to match. */
-} /* re_match_2 */
-
-/* Subroutine definitions for re_match_2. */
-
-
-/* We are passed P pointing to a register number after a start_memory.
-
- Return true if the pattern up to the corresponding stop_memory can
- match the empty string, and false otherwise.
-
- If we find the matching stop_memory, sets P to point to one past its number.
- Otherwise, sets P to an undefined byte less than or equal to END.
-
- We don't handle duplicates properly (yet). */
-
-static boolean
-group_match_null_string_p (p, end, reg_info)
- unsigned char **p, *end;
- register_info_type *reg_info;
-{
- int mcnt;
- /* Point to after the args to the start_memory. */
- unsigned char *p1 = *p + 2;
-
- while (p1 < end)
- {
- /* Skip over opcodes that can match nothing, and return true or
- false, as appropriate, when we get to one that can't, or to the
- matching stop_memory. */
-
- switch ((re_opcode_t) *p1)
- {
- /* Could be either a loop or a series of alternatives. */
- case on_failure_jump:
- p1++;
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-
- /* If the next operation is not a jump backwards in the
- pattern. */
-
- if (mcnt >= 0)
- {
- /* Go through the on_failure_jumps of the alternatives,
- seeing if any of the alternatives cannot match nothing.
- The last alternative starts with only a jump,
- whereas the rest start with on_failure_jump and end
- with a jump, e.g., here is the pattern for `a|b|c':
-
- /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
- /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
- /exactn/1/c
-
- So, we have to first go through the first (n-1)
- alternatives and then deal with the last one separately. */
-
-
- /* Deal with the first (n-1) alternatives, which start
- with an on_failure_jump (see above) that jumps to right
- past a jump_past_alt. */
-
- while ((re_opcode_t) p1[mcnt-3] == jump_past_alt)
- {
- /* `mcnt' holds how many bytes long the alternative
- is, including the ending `jump_past_alt' and
- its number. */
-
- if (!alt_match_null_string_p (p1, p1 + mcnt - 3,
- reg_info))
- return false;
-
- /* Move to right after this alternative, including the
- jump_past_alt. */
- p1 += mcnt;
-
- /* Break if it's the beginning of an n-th alternative
- that doesn't begin with an on_failure_jump. */
- if ((re_opcode_t) *p1 != on_failure_jump)
- break;
-
- /* Still have to check that it's not an n-th
- alternative that starts with an on_failure_jump. */
- p1++;
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- if ((re_opcode_t) p1[mcnt-3] != jump_past_alt)
- {
- /* Get to the beginning of the n-th alternative. */
- p1 -= 3;
- break;
- }
- }
-
- /* Deal with the last alternative: go back and get number
- of the `jump_past_alt' just before it. `mcnt' contains
- the length of the alternative. */
- EXTRACT_NUMBER (mcnt, p1 - 2);
-
- if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info))
- return false;
-
- p1 += mcnt; /* Get past the n-th alternative. */
- } /* if mcnt > 0 */
- break;
-
-
- case stop_memory:
- assert (p1[1] == **p);
- *p = p1 + 2;
- return true;
-
-
- default:
- if (!common_op_match_null_string_p (&p1, end, reg_info))
- return false;
- }
- } /* while p1 < end */
-
- return false;
-} /* group_match_null_string_p */
-
-
-/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
- It expects P to be the first byte of a single alternative and END one
- byte past the last. The alternative can contain groups. */
-
-static boolean
-alt_match_null_string_p (p, end, reg_info)
- unsigned char *p, *end;
- register_info_type *reg_info;
-{
- int mcnt;
- unsigned char *p1 = p;
-
- while (p1 < end)
- {
- /* Skip over opcodes that can match nothing, and break when we get
- to one that can't. */
-
- switch ((re_opcode_t) *p1)
- {
- /* It's a loop. */
- case on_failure_jump:
- p1++;
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- p1 += mcnt;
- break;
-
- default:
- if (!common_op_match_null_string_p (&p1, end, reg_info))
- return false;
- }
- } /* while p1 < end */
-
- return true;
-} /* alt_match_null_string_p */
-
-
-/* Deals with the ops common to group_match_null_string_p and
- alt_match_null_string_p.
-
- Sets P to one after the op and its arguments, if any. */
-
-static boolean
-common_op_match_null_string_p (p, end, reg_info)
- unsigned char **p, *end;
- register_info_type *reg_info;
-{
- int mcnt;
- boolean ret;
- int reg_no;
- unsigned char *p1 = *p;
-
- switch ((re_opcode_t) *p1++)
- {
- case no_op:
- case begline:
- case endline:
- case begbuf:
- case endbuf:
- case wordbeg:
- case wordend:
- case wordbound:
- case notwordbound:
-#ifdef emacs
- case before_dot:
- case at_dot:
- case after_dot:
-#endif
- break;
-
- case start_memory:
- reg_no = *p1;
- assert (reg_no > 0 && reg_no <= MAX_REGNUM);
- ret = group_match_null_string_p (&p1, end, reg_info);
-
- /* Have to set this here in case we're checking a group which
- contains a group and a back reference to it. */
-
- if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
- REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
-
- if (!ret)
- return false;
- break;
-
- /* If this is an optimized succeed_n for zero times, make the jump. */
- case jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- if (mcnt >= 0)
- p1 += mcnt;
- else
- return false;
- break;
-
- case succeed_n:
- /* Get to the number of times to succeed. */
- p1 += 2;
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-
- if (mcnt == 0)
- {
- p1 -= 4;
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- p1 += mcnt;
- }
- else
- return false;
- break;
-
- case duplicate:
- if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
- return false;
- break;
-
- case set_number_at:
- p1 += 4;
-
- default:
- /* All other opcodes mean we cannot match the empty string. */
- return false;
- }
-
- *p = p1;
- return true;
-} /* common_op_match_null_string_p */
-
-
-/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
- bytes; nonzero otherwise. */
-
-static int
-bcmp_translate (s1, s2, len, translate)
- unsigned char *s1, *s2;
- register int len;
- RE_TRANSLATE_TYPE translate;
-{
- register unsigned char *p1 = s1, *p2 = s2;
- while (len)
- {
- if (translate[*p1++] != translate[*p2++]) return 1;
- len--;
- }
- return 0;
-}
-
-/* Entry points for GNU code. */
-
-/* re_compile_pattern is the GNU regular expression compiler: it
- compiles PATTERN (of length SIZE) and puts the result in BUFP.
- Returns 0 if the pattern was valid, otherwise an error string.
-
- Assumes the `allocated' (and perhaps `buffer') and `translate' fields
- are set in BUFP on entry.
-
- We call regex_compile to do the actual compilation. */
-
-const char *
-re_compile_pattern (pattern, length, bufp)
- const char *pattern;
- int length;
- struct re_pattern_buffer *bufp;
-{
- reg_errcode_t ret;
-
- /* GNU code is written to assume at least RE_NREGS registers will be set
- (and at least one extra will be -1). */
- bufp->regs_allocated = REGS_UNALLOCATED;
-
- /* And GNU code determines whether or not to get register information
- by passing null for the REGS argument to re_match, etc., not by
- setting no_sub. */
- bufp->no_sub = 0;
-
- /* Match anchors at newline. */
- bufp->newline_anchor = 1;
-
- ret = regex_compile (pattern, length, re_syntax_options, bufp);
-
- if (!ret)
- return NULL;
- return gettext (re_error_msgid[(int) ret]);
-}
-
-/* Entry points compatible with 4.2 BSD regex library. We don't define
- them unless specifically requested. */
-
-#if defined (_REGEX_RE_COMP) || defined (_LIBC)
-
-/* BSD has one and only one pattern buffer. */
-static struct re_pattern_buffer re_comp_buf;
-
-char *
-#ifdef _LIBC
-/* Make these definitions weak in libc, so POSIX programs can redefine
- these names if they don't use our functions, and still use
- regcomp/regexec below without link errors. */
-weak_function
-#endif
-re_comp (s)
- const char *s;
-{
- reg_errcode_t ret;
-
- if (!s)
- {
- if (!re_comp_buf.buffer)
- return gettext ("No previous regular expression");
- return 0;
- }
-
- if (!re_comp_buf.buffer)
- {
- re_comp_buf.buffer = (unsigned char *) malloc (200);
- if (re_comp_buf.buffer == NULL)
- return gettext (re_error_msgid[(int) REG_ESPACE]);
- re_comp_buf.allocated = 200;
-
- re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
- if (re_comp_buf.fastmap == NULL)
- return gettext (re_error_msgid[(int) REG_ESPACE]);
- }
-
- /* Since `re_exec' always passes NULL for the `regs' argument, we
- don't need to initialize the pattern buffer fields which affect it. */
-
- /* Match anchors at newlines. */
- re_comp_buf.newline_anchor = 1;
-
- ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
-
- if (!ret)
- return NULL;
-
- /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */
- return (char *) gettext (re_error_msgid[(int) ret]);
-}
-
-
-int
-#ifdef _LIBC
-weak_function
-#endif
-re_exec (s)
- const char *s;
-{
- const int len = strlen (s);
- return
- 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
-}
-#endif /* _REGEX_RE_COMP */
-
-/* POSIX.2 functions. Don't define these for Emacs. */
-
-#ifndef emacs
-
-/* regcomp takes a regular expression as a string and compiles it.
-
- PREG is a regex_t *. We do not expect any fields to be initialized,
- since POSIX says we shouldn't. Thus, we set
-
- `buffer' to the compiled pattern;
- `used' to the length of the compiled pattern;
- `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
- REG_EXTENDED bit in CFLAGS is set; otherwise, to
- RE_SYNTAX_POSIX_BASIC;
- `newline_anchor' to REG_NEWLINE being set in CFLAGS;
- `fastmap' and `fastmap_accurate' to zero;
- `re_nsub' to the number of subexpressions in PATTERN.
-
- PATTERN is the address of the pattern string.
-
- CFLAGS is a series of bits which affect compilation.
-
- If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
- use POSIX basic syntax.
-
- If REG_NEWLINE is set, then . and [^...] don't match newline.
- Also, regexec will try a match beginning after every newline.
-
- If REG_ICASE is set, then we considers upper- and lowercase
- versions of letters to be equivalent when matching.
-
- If REG_NOSUB is set, then when PREG is passed to regexec, that
- routine will report only success or failure, and nothing about the
- registers.
-
- It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for
- the return codes and their meanings.) */
-
-int
-regcomp (preg, pattern, cflags)
- regex_t *preg;
- const char *pattern;
- int cflags;
-{
- reg_errcode_t ret;
- unsigned syntax
- = (cflags & REG_EXTENDED) ?
- RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
-
- /* regex_compile will allocate the space for the compiled pattern. */
- preg->buffer = 0;
- preg->allocated = 0;
- preg->used = 0;
-
- /* Don't bother to use a fastmap when searching. This simplifies the
- REG_NEWLINE case: if we used a fastmap, we'd have to put all the
- characters after newlines into the fastmap. This way, we just try
- every character. */
- preg->fastmap = 0;
-
- if (cflags & REG_ICASE)
- {
- unsigned i;
-
- preg->translate
- = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE
- * sizeof (*(RE_TRANSLATE_TYPE)0));
- if (preg->translate == NULL)
- return (int) REG_ESPACE;
-
- /* Map uppercase characters to corresponding lowercase ones. */
- for (i = 0; i < CHAR_SET_SIZE; i++)
- preg->translate[i] = ISUPPER (i) ? tolower (i) : i;
- }
- else
- preg->translate = NULL;
-
- /* If REG_NEWLINE is set, newlines are treated differently. */
- if (cflags & REG_NEWLINE)
- { /* REG_NEWLINE implies neither . nor [^...] match newline. */
- syntax &= ~RE_DOT_NEWLINE;
- syntax |= RE_HAT_LISTS_NOT_NEWLINE;
- /* It also changes the matching behavior. */
- preg->newline_anchor = 1;
- }
- else
- preg->newline_anchor = 0;
-
- preg->no_sub = !!(cflags & REG_NOSUB);
-
- /* POSIX says a null character in the pattern terminates it, so we
- can use strlen here in compiling the pattern. */
- ret = regex_compile (pattern, strlen (pattern), syntax, preg);
-
- /* POSIX doesn't distinguish between an unmatched open-group and an
- unmatched close-group: both are REG_EPAREN. */
- if (ret == REG_ERPAREN) ret = REG_EPAREN;
-
- return (int) ret;
-}
-
-
-/* regexec searches for a given pattern, specified by PREG, in the
- string STRING.
-
- If NMATCH is zero or REG_NOSUB was set in the cflags argument to
- `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
- least NMATCH elements, and we set them to the offsets of the
- corresponding matched substrings.
-
- EFLAGS specifies `execution flags' which affect matching: if
- REG_NOTBOL is set, then ^ does not match at the beginning of the
- string; if REG_NOTEOL is set, then $ does not match at the end.
-
- We return 0 if we find a match and REG_NOMATCH if not. */
-
-int
-regexec (preg, string, nmatch, pmatch, eflags)
- const regex_t *preg;
- const char *string;
- size_t nmatch;
- regmatch_t pmatch[];
- int eflags;
-{
- int ret;
- struct re_registers regs;
- regex_t private_preg;
- int len = strlen (string);
- boolean want_reg_info = !preg->no_sub && nmatch > 0;
-
- private_preg = *preg;
-
- private_preg.not_bol = !!(eflags & REG_NOTBOL);
- private_preg.not_eol = !!(eflags & REG_NOTEOL);
-
- /* The user has told us exactly how many registers to return
- information about, via `nmatch'. We have to pass that on to the
- matching routines. */
- private_preg.regs_allocated = REGS_FIXED;
-
- if (want_reg_info)
- {
- regs.num_regs = nmatch;
- regs.start = TALLOC (nmatch, regoff_t);
- regs.end = TALLOC (nmatch, regoff_t);
- if (regs.start == NULL || regs.end == NULL)
- return (int) REG_NOMATCH;
- }
-
- /* Perform the searching operation. */
- ret = re_search (&private_preg, string, len,
- /* start: */ 0, /* range: */ len,
- want_reg_info ? &regs : (struct re_registers *) 0);
-
- /* Copy the register information to the POSIX structure. */
- if (want_reg_info)
- {
- if (ret >= 0)
- {
- unsigned r;
-
- for (r = 0; r < nmatch; r++)
- {
- pmatch[r].rm_so = regs.start[r];
- pmatch[r].rm_eo = regs.end[r];
- }
- }
-
- /* If we needed the temporary register info, free the space now. */
- free (regs.start);
- free (regs.end);
- }
-
- /* We want zero return to mean success, unlike `re_search'. */
- return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
-}
-
-
-/* Returns a message corresponding to an error code, ERRCODE, returned
- from either regcomp or regexec. We don't use PREG here. */
-
-size_t
-regerror (errcode, preg, errbuf, errbuf_size)
- int errcode;
- const regex_t *preg;
- char *errbuf;
- size_t errbuf_size;
-{
- const char *msg;
- size_t msg_size;
-
- if (errcode < 0
- || errcode >= (sizeof (re_error_msgid) / sizeof (re_error_msgid[0])))
- /* Only error codes returned by the rest of the code should be passed
- to this routine. If we are given anything else, or if other regex
- code generates an invalid error code, then the program has a bug.
- Dump core so we can fix it. */
- abort ();
-
- msg = gettext (re_error_msgid[errcode]);
-
- msg_size = strlen (msg) + 1; /* Includes the null. */
-
- if (errbuf_size != 0)
- {
- if (msg_size > errbuf_size)
- {
- strncpy (errbuf, msg, errbuf_size - 1);
- errbuf[errbuf_size - 1] = 0;
- }
- else
- strcpy (errbuf, msg);
- }
-
- return msg_size;
-}
-
-
-/* Free dynamically allocated space used by PREG. */
-
-void
-regfree (preg)
- regex_t *preg;
-{
- if (preg->buffer != NULL)
- free (preg->buffer);
- preg->buffer = NULL;
-
- preg->allocated = 0;
- preg->used = 0;
-
- if (preg->fastmap != NULL)
- free (preg->fastmap);
- preg->fastmap = NULL;
- preg->fastmap_accurate = 0;
-
- if (preg->translate != NULL)
- free (preg->translate);
- preg->translate = NULL;
-}
-
-#endif /* not emacs */
diff --git a/src/regex.h b/src/regex.h
deleted file mode 100644
index 61bdd6e11a4..00000000000
--- a/src/regex.h
+++ /dev/null
@@ -1,496 +0,0 @@
-/* Definitions for data structures and routines for the regular
- expression library, version 0.12.
-
- Copyright (C) 1985, 89, 90, 91, 92, 93, 95 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 2, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- USA. */
-
-#ifndef __REGEXP_LIBRARY_H__
-#define __REGEXP_LIBRARY_H__
-
-/* POSIX says that <sys/types.h> must be included (by the caller) before
- <regex.h>. */
-
-#if !defined (_POSIX_C_SOURCE) && !defined (_POSIX_SOURCE) && defined (VMS)
-/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
- should be there. */
-#include <stddef.h>
-#endif
-
-
-/* The following bits are used to determine the regexp syntax we
- recognize. The set/not-set meanings are chosen so that Emacs syntax
- remains the value 0. The bits are given in alphabetical order, and
- the definitions shifted by one from the previous bit; thus, when we
- add or remove a bit, only one other definition need change. */
-typedef unsigned reg_syntax_t;
-
-/* If this bit is not set, then \ inside a bracket expression is literal.
- If set, then such a \ quotes the following character. */
-#define RE_BACKSLASH_ESCAPE_IN_LISTS (1)
-
-/* If this bit is not set, then + and ? are operators, and \+ and \? are
- literals.
- If set, then \+ and \? are operators and + and ? are literals. */
-#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
-
-/* If this bit is set, then character classes are supported. They are:
- [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
- [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
- If not set, then character classes are not supported. */
-#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
-
-/* If this bit is set, then ^ and $ are always anchors (outside bracket
- expressions, of course).
- If this bit is not set, then it depends:
- ^ is an anchor if it is at the beginning of a regular
- expression or after an open-group or an alternation operator;
- $ is an anchor if it is at the end of a regular expression, or
- before a close-group or an alternation operator.
-
- This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
- POSIX draft 11.2 says that * etc. in leading positions is undefined.
- We already implemented a previous draft which made those constructs
- invalid, though, so we haven't changed the code back. */
-#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
-
-/* If this bit is set, then special characters are always special
- regardless of where they are in the pattern.
- If this bit is not set, then special characters are special only in
- some contexts; otherwise they are ordinary. Specifically,
- * + ? and intervals are only special when not after the beginning,
- open-group, or alternation operator. */
-#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
-
-/* If this bit is set, then *, +, ?, and { cannot be first in an re or
- immediately after an alternation or begin-group operator. */
-#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
-
-/* If this bit is set, then . matches newline.
- If not set, then it doesn't. */
-#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
-
-/* If this bit is set, then . doesn't match NUL.
- If not set, then it does. */
-#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
-
-/* If this bit is set, nonmatching lists [^...] do not match newline.
- If not set, they do. */
-#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
-
-/* If this bit is set, either \{...\} or {...} defines an
- interval, depending on RE_NO_BK_BRACES.
- If not set, \{, \}, {, and } are literals. */
-#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
-
-/* If this bit is set, +, ? and | aren't recognized as operators.
- If not set, they are. */
-#define RE_LIMITED_OPS (RE_INTERVALS << 1)
-
-/* If this bit is set, newline is an alternation operator.
- If not set, newline is literal. */
-#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
-
-/* If this bit is set, then `{...}' defines an interval, and \{ and \}
- are literals.
- If not set, then `\{...\}' defines an interval. */
-#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
-
-/* If this bit is set, (...) defines a group, and \( and \) are literals.
- If not set, \(...\) defines a group, and ( and ) are literals. */
-#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
-
-/* If this bit is set, then \<digit> matches <digit>.
- If not set, then \<digit> is a back-reference. */
-#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
-
-/* If this bit is set, then | is an alternation operator, and \| is literal.
- If not set, then \| is an alternation operator, and | is literal. */
-#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
-
-/* If this bit is set, then an ending range point collating higher
- than the starting range point, as in [z-a], is invalid.
- If not set, then when ending range point collates higher than the
- starting range point, the range is ignored. */
-#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
-
-/* If this bit is set, then an unmatched ) is ordinary.
- If not set, then an unmatched ) is invalid. */
-#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
-
-/* If this bit is set, succeed as soon as we match the whole pattern,
- without further backtracking. */
-#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
-
-/* This global variable defines the particular regexp syntax to use (for
- some interfaces). When a regexp is compiled, the syntax used is
- stored in the pattern buffer, so changing this does not affect
- already-compiled regexps. */
-extern reg_syntax_t re_syntax_options;
-
-/* Define combinations of the above bits for the standard possibilities.
- (The [[[ comments delimit what gets put into the Texinfo file, so
- don't delete them!) */
-/* [[[begin syntaxes]]] */
-#define RE_SYNTAX_EMACS 0
-
-#define RE_SYNTAX_AWK \
- (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
- | RE_NO_BK_PARENS | RE_NO_BK_REFS \
- | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
- | RE_UNMATCHED_RIGHT_PAREN_ORD)
-
-#define RE_SYNTAX_POSIX_AWK \
- (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS)
-
-#define RE_SYNTAX_GREP \
- (RE_BK_PLUS_QM | RE_CHAR_CLASSES \
- | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
- | RE_NEWLINE_ALT)
-
-#define RE_SYNTAX_EGREP \
- (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
- | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
- | RE_NEWLINE_ALT | RE_NO_BK_PARENS \
- | RE_NO_BK_VBAR)
-
-#define RE_SYNTAX_POSIX_EGREP \
- (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
-
-/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
-#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
-
-#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
-
-/* Syntax bits common to both basic and extended POSIX regex syntax. */
-#define _RE_SYNTAX_POSIX_COMMON \
- (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
- | RE_INTERVALS | RE_NO_EMPTY_RANGES)
-
-#define RE_SYNTAX_POSIX_BASIC \
- (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
-
-/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
- RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
- isn't minimal, since other operators, such as \`, aren't disabled. */
-#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
- (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
-
-#define RE_SYNTAX_POSIX_EXTENDED \
- (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
- | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
- | RE_NO_BK_PARENS | RE_NO_BK_VBAR \
- | RE_UNMATCHED_RIGHT_PAREN_ORD)
-
-/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
- replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */
-#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
- (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
- | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
- | RE_NO_BK_PARENS | RE_NO_BK_REFS \
- | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
-/* [[[end syntaxes]]] */
-
-/* Maximum number of duplicates an interval can allow. Some systems
- (erroneously) define this in other header files, but we want our
- value, so remove any previous define. */
-#ifdef RE_DUP_MAX
-#undef RE_DUP_MAX
-#endif
-#define RE_DUP_MAX ((1 << 15) - 1)
-
-
-/* POSIX `cflags' bits (i.e., information for `regcomp'). */
-
-/* If this bit is set, then use extended regular expression syntax.
- If not set, then use basic regular expression syntax. */
-#define REG_EXTENDED 1
-
-/* If this bit is set, then ignore case when matching.
- If not set, then case is significant. */
-#define REG_ICASE (REG_EXTENDED << 1)
-
-/* If this bit is set, then anchors do not match at newline
- characters in the string.
- If not set, then anchors do match at newlines. */
-#define REG_NEWLINE (REG_ICASE << 1)
-
-/* If this bit is set, then report only success or fail in regexec.
- If not set, then returns differ between not matching and errors. */
-#define REG_NOSUB (REG_NEWLINE << 1)
-
-
-/* POSIX `eflags' bits (i.e., information for regexec). */
-
-/* If this bit is set, then the beginning-of-line operator doesn't match
- the beginning of the string (presumably because it's not the
- beginning of a line).
- If not set, then the beginning-of-line operator does match the
- beginning of the string. */
-#define REG_NOTBOL 1
-
-/* Like REG_NOTBOL, except for the end-of-line. */
-#define REG_NOTEOL (1 << 1)
-
-
-/* If any error codes are removed, changed, or added, update the
- `re_error_msg' table in regex.c. */
-typedef enum
-{
- REG_NOERROR = 0, /* Success. */
- REG_NOMATCH, /* Didn't find a match (for regexec). */
-
- /* POSIX regcomp return error codes. (In the order listed in the
- standard.) */
- REG_BADPAT, /* Invalid pattern. */
- REG_ECOLLATE, /* Not implemented. */
- REG_ECTYPE, /* Invalid character class name. */
- REG_EESCAPE, /* Trailing backslash. */
- REG_ESUBREG, /* Invalid back reference. */
- REG_EBRACK, /* Unmatched left bracket. */
- REG_EPAREN, /* Parenthesis imbalance. */
- REG_EBRACE, /* Unmatched \{. */
- REG_BADBR, /* Invalid contents of \{\}. */
- REG_ERANGE, /* Invalid range end. */
- REG_ESPACE, /* Ran out of memory. */
- REG_BADRPT, /* No preceding re for repetition op. */
-
- /* Error codes we've added. */
- REG_EEND, /* Premature end. */
- REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
- REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
-} reg_errcode_t;
-
-/* This data structure represents a compiled pattern. Before calling
- the pattern compiler, the fields `buffer', `allocated', `fastmap',
- `translate', and `no_sub' can be set. After the pattern has been
- compiled, the `re_nsub' field is available. All other fields are
- private to the regex routines. */
-
-#ifndef RE_TRANSLATE_TYPE
-#define RE_TRANSLATE_TYPE char *
-#endif
-
-struct re_pattern_buffer
-{
-/* [[[begin pattern_buffer]]] */
- /* Space that holds the compiled pattern. It is declared as
- `unsigned char *' because its elements are
- sometimes used as array indexes. */
- unsigned char *buffer;
-
- /* Number of bytes to which `buffer' points. */
- unsigned long allocated;
-
- /* Number of bytes actually used in `buffer'. */
- unsigned long used;
-
- /* Syntax setting with which the pattern was compiled. */
- reg_syntax_t syntax;
-
- /* Pointer to a fastmap, if any, otherwise zero. re_search uses
- the fastmap, if there is one, to skip over impossible
- starting points for matches. */
- char *fastmap;
-
- /* Either a translate table to apply to all characters before
- comparing them, or zero for no translation. The translation
- is applied to a pattern when it is compiled and to a string
- when it is matched. */
- RE_TRANSLATE_TYPE translate;
-
- /* Number of subexpressions found by the compiler. */
- size_t re_nsub;
-
- /* Zero if this pattern cannot match the empty string, one else.
- Well, in truth it's used only in `re_search_2', to see
- whether or not we should use the fastmap, so we don't set
- this absolutely perfectly; see `re_compile_fastmap' (the
- `duplicate' case). */
- unsigned can_be_null : 1;
-
- /* If REGS_UNALLOCATED, allocate space in the `regs' structure
- for `max (RE_NREGS, re_nsub + 1)' groups.
- If REGS_REALLOCATE, reallocate space if necessary.
- If REGS_FIXED, use what's there. */
-#define REGS_UNALLOCATED 0
-#define REGS_REALLOCATE 1
-#define REGS_FIXED 2
- unsigned regs_allocated : 2;
-
- /* Set to zero when `regex_compile' compiles a pattern; set to one
- by `re_compile_fastmap' if it updates the fastmap. */
- unsigned fastmap_accurate : 1;
-
- /* If set, `re_match_2' does not return information about
- subexpressions. */
- unsigned no_sub : 1;
-
- /* If set, a beginning-of-line anchor doesn't match at the
- beginning of the string. */
- unsigned not_bol : 1;
-
- /* Similarly for an end-of-line anchor. */
- unsigned not_eol : 1;
-
- /* If true, an anchor at a newline matches. */
- unsigned newline_anchor : 1;
-
-/* [[[end pattern_buffer]]] */
-};
-
-typedef struct re_pattern_buffer regex_t;
-
-/* Type for byte offsets within the string. POSIX mandates this. */
-typedef int regoff_t;
-
-
-/* This is the structure we store register match data in. See
- regex.texinfo for a full description of what registers match. */
-struct re_registers
-{
- unsigned num_regs;
- regoff_t *start;
- regoff_t *end;
-};
-
-
-/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
- `re_match_2' returns information about at least this many registers
- the first time a `regs' structure is passed. */
-#ifndef RE_NREGS
-#define RE_NREGS 30
-#endif
-
-
-/* POSIX specification for registers. Aside from the different names than
- `re_registers', POSIX uses an array of structures, instead of a
- structure of arrays. */
-typedef struct
-{
- regoff_t rm_so; /* Byte offset from string's start to substring's start. */
- regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
-} regmatch_t;
-
-/* Declarations for routines. */
-
-/* To avoid duplicating every routine declaration -- once with a
- prototype (if we are ANSI), and once without (if we aren't) -- we
- use the following macro to declare argument types. This
- unfortunately clutters up the declarations a bit, but I think it's
- worth it. */
-
-#if __STDC__
-
-#define _RE_ARGS(args) args
-
-#else /* not __STDC__ */
-
-#define _RE_ARGS(args) ()
-
-#endif /* not __STDC__ */
-
-/* Sets the current default syntax to SYNTAX, and return the old syntax.
- You can also simply assign to the `re_syntax_options' variable. */
-extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
-
-/* Compile the regular expression PATTERN, with length LENGTH
- and syntax given by the global `re_syntax_options', into the buffer
- BUFFER. Return NULL if successful, and an error string if not. */
-extern const char *re_compile_pattern
- _RE_ARGS ((const char *pattern, int length,
- struct re_pattern_buffer *buffer));
-
-
-/* Compile a fastmap for the compiled pattern in BUFFER; used to
- accelerate searches. Return 0 if successful and -2 if was an
- internal error. */
-extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
-
-
-/* Search in the string STRING (with length LENGTH) for the pattern
- compiled into BUFFER. Start searching at position START, for RANGE
- characters. Return the starting position of the match, -1 for no
- match, or -2 for an internal error. Also return register
- information in REGS (if REGS and BUFFER->no_sub are nonzero). */
-extern int re_search
- _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
- int length, int start, int range, struct re_registers *regs));
-
-
-/* Like `re_search', but search in the concatenation of STRING1 and
- STRING2. Also, stop searching at index START + STOP. */
-extern int re_search_2
- _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
- int length1, const char *string2, int length2,
- int start, int range, struct re_registers *regs, int stop));
-
-
-/* Like `re_search', but return how many characters in STRING the regexp
- in BUFFER matched, starting at position START. */
-extern int re_match
- _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
- int length, int start, struct re_registers *regs));
-
-
-/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
-extern int re_match_2
- _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
- int length1, const char *string2, int length2,
- int start, struct re_registers *regs, int stop));
-
-
-/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
- ENDS. Subsequent matches using BUFFER and REGS will use this memory
- for recording register information. STARTS and ENDS must be
- allocated with malloc, and must each be at least `NUM_REGS * sizeof
- (regoff_t)' bytes long.
-
- If NUM_REGS == 0, then subsequent matches should allocate their own
- register data.
-
- Unless this function is called, the first search or match using
- PATTERN_BUFFER will allocate its own register data, without
- freeing the old data. */
-extern void re_set_registers
- _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
- unsigned num_regs, regoff_t *starts, regoff_t *ends));
-
-#ifdef _REGEX_RE_COMP
-/* 4.2 bsd compatibility. */
-extern char *re_comp _RE_ARGS ((const char *));
-extern int re_exec _RE_ARGS ((const char *));
-#endif
-
-/* POSIX compatibility. */
-extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags));
-extern int regexec
- _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch,
- regmatch_t pmatch[], int eflags));
-extern size_t regerror
- _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf,
- size_t errbuf_size));
-extern void regfree _RE_ARGS ((regex_t *preg));
-
-#endif /* not __REGEXP_LIBRARY_H__ */
-
-/*
-Local variables:
-make-backup-files: t
-version-control: t
-trim-versions-without-asking: nil
-End:
-*/
diff --git a/src/region-cache.c b/src/region-cache.c
deleted file mode 100644
index 7f37fddc3c3..00000000000
--- a/src/region-cache.c
+++ /dev/null
@@ -1,834 +0,0 @@
-/* Caching facts about regions of the buffer, for optimization.
- Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1995
- Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include "lisp.h"
-#include "buffer.h"
-#include "region-cache.h"
-
-#include <stdio.h>
-
-
-/* Data structures. */
-
-/* The region cache.
-
- We want something that maps character positions in a buffer onto
- values. The representation should deal well with long runs of
- characters with the same value.
-
- The tricky part: the representation should be very cheap to
- maintain in the presence of many insertions and deletions. If the
- overhead of maintaining the cache is too high, the speedups it
- offers will be worthless.
-
-
- We represent the region cache as a sorted array of struct
- boundary's, each of which contains a buffer position and a value;
- the value applies to all the characters after the buffer position,
- until the position of the next boundary, or the end of the buffer.
-
- The cache always has a boundary whose position is BUF_BEG, so
- there's always a value associated with every character in the
- buffer. Since the cache is sorted, this is always the first
- element of the cache.
-
- To facilitate the insertion and deletion of boundaries in the
- cache, the cache has a gap, just like Emacs's text buffers do.
-
- To help boundary positions float along with insertions and
- deletions, all boundary positions before the cache gap are stored
- relative to BUF_BEG (buf) (thus they're >= 0), and all boundary
- positions after the gap are stored relative to BUF_Z (buf) (thus
- they're <= 0). Look at BOUNDARY_POS to see this in action. See
- revalidate_region_cache to see how this helps. */
-
-struct boundary {
- int pos;
- int value;
-};
-
-struct region_cache {
- /* A sorted array of locations where the known-ness of the buffer
- changes. */
- struct boundary *boundaries;
-
- /* boundaries[gap_start ... gap_start + gap_len - 1] is the gap. */
- int gap_start, gap_len;
-
- /* The number of elements allocated to boundaries, not including the
- gap. */
- int cache_len;
-
- /* The areas that haven't changed since the last time we cleaned out
- invalid entries from the cache. These overlap when the buffer is
- entirely unchanged. */
- int beg_unchanged, end_unchanged;
-
- /* The first and last positions in the buffer. Because boundaries
- store their positions relative to the start (BEG) and end (Z) of
- the buffer, knowing these positions allows us to accurately
- interpret positions without having to pass the buffer structure
- or its endpoints around all the time.
-
- Yes, buffer_beg is always 1. It's there for symmetry with
- buffer_end and the BEG and BUF_BEG macros. */
- int buffer_beg, buffer_end;
-};
-
-/* Return the position of boundary i in cache c. */
-#define BOUNDARY_POS(c, i) \
- ((i) < (c)->gap_start \
- ? (c)->buffer_beg + (c)->boundaries[(i)].pos \
- : (c)->buffer_end + (c)->boundaries[(c)->gap_len + (i)].pos)
-
-/* Return the value for text after boundary i in cache c. */
-#define BOUNDARY_VALUE(c, i) \
- ((i) < (c)->gap_start \
- ? (c)->boundaries[(i)].value \
- : (c)->boundaries[(c)->gap_len + (i)].value)
-
-/* Set the value for text after boundary i in cache c to v. */
-#define SET_BOUNDARY_VALUE(c, i, v) \
- ((i) < (c)->gap_start \
- ? ((c)->boundaries[(i)].value = (v))\
- : ((c)->boundaries[(c)->gap_len + (i)].value = (v)))
-
-
-/* How many elements to add to the gap when we resize the buffer. */
-#define NEW_CACHE_GAP (40)
-
-/* See invalidate_region_cache; if an invalidation would throw away
- information about this many characters, call
- revalidate_region_cache before doing the new invalidation, to
- preserve that information, instead of throwing it away. */
-#define PRESERVE_THRESHOLD (500)
-
-static void revalidate_region_cache ();
-
-
-/* Interface: Allocating, initializing, and disposing of region caches. */
-
-struct region_cache *
-new_region_cache ()
-{
- struct region_cache *c
- = (struct region_cache *) xmalloc (sizeof (struct region_cache));
-
- c->gap_start = 0;
- c->gap_len = NEW_CACHE_GAP;
- c->cache_len = 0;
- c->boundaries =
- (struct boundary *) xmalloc ((c->gap_len + c->cache_len)
- * sizeof (*c->boundaries));
-
- c->beg_unchanged = 0;
- c->end_unchanged = 0;
- c->buffer_beg = 1;
- c->buffer_end = 1;
-
- /* Insert the boundary for the buffer start. */
- c->cache_len++;
- c->gap_len--;
- c->gap_start++;
- c->boundaries[0].pos = 0; /* from buffer_beg */
- c->boundaries[0].value = 0;
-
- return c;
-}
-
-void
-free_region_cache (c)
- struct region_cache *c;
-{
- xfree (c->boundaries);
- xfree (c);
-}
-
-
-/* Finding positions in the cache. */
-
-/* Return the index of the last boundary in cache C at or before POS.
- In other words, return the boundary that specifies the value for
- the region POS..(POS + 1).
-
- This operation should be logarithmic in the number of cache
- entries. It would be nice if it took advantage of locality of
- reference, too, by searching entries near the last entry found. */
-static int
-find_cache_boundary (c, pos)
- struct region_cache *c;
- int pos;
-{
- int low = 0, high = c->cache_len;
-
- while (low + 1 < high)
- {
- /* mid is always a valid index, because low < high and ">> 1"
- rounds down. */
- int mid = (low + high) >> 1;
- int boundary = BOUNDARY_POS (c, mid);
-
- if (pos < boundary)
- high = mid;
- else
- low = mid;
- }
-
- /* Some testing. */
- if (BOUNDARY_POS (c, low) > pos
- || (low + 1 < c->cache_len
- && BOUNDARY_POS (c, low + 1) <= pos))
- abort ();
-
- return low;
-}
-
-
-
-/* Moving the cache gap around, inserting, and deleting. */
-
-
-/* Move the gap of cache C to index POS, and make sure it has space
- for at least MIN_SIZE boundaries. */
-static void
-move_cache_gap (c, pos, min_size)
- struct region_cache *c;
- int pos;
- int min_size;
-{
- /* Copy these out of the cache and into registers. */
- int gap_start = c->gap_start;
- int gap_len = c->gap_len;
- int buffer_beg = c->buffer_beg;
- int buffer_end = c->buffer_end;
-
- if (pos < 0
- || pos > c->cache_len)
- abort ();
-
- /* We mustn't ever try to put the gap before the dummy start
- boundary. That must always be start-relative. */
- if (pos == 0)
- abort ();
-
- /* Need we move the gap right? */
- while (gap_start < pos)
- {
- /* Copy one boundary from after to before the gap, and
- convert its position to start-relative. */
- c->boundaries[gap_start].pos
- = (buffer_end
- + c->boundaries[gap_start + gap_len].pos
- - buffer_beg);
- c->boundaries[gap_start].value
- = c->boundaries[gap_start + gap_len].value;
- gap_start++;
- }
-
- /* To enlarge the gap, we need to re-allocate the boundary array, and
- then shift the area after the gap to the new end. Since the cost
- is proportional to the amount of stuff after the gap, we do the
- enlargement here, after a right shift but before a left shift,
- when the portion after the gap is smallest. */
- if (gap_len < min_size)
- {
- int i;
-
- /* Always make at least NEW_CACHE_GAP elements, as long as we're
- expanding anyway. */
- if (min_size < NEW_CACHE_GAP)
- min_size = NEW_CACHE_GAP;
-
- c->boundaries =
- (struct boundary *) xrealloc (c->boundaries,
- ((min_size + c->cache_len)
- * sizeof (*c->boundaries)));
-
- /* Some systems don't provide a version of the copy routine that
- can be trusted to shift memory upward into an overlapping
- region. memmove isn't widely available. */
- min_size -= gap_len;
- for (i = c->cache_len - 1; i >= gap_start; i--)
- {
- c->boundaries[i + min_size].pos = c->boundaries[i + gap_len].pos;
- c->boundaries[i + min_size].value = c->boundaries[i + gap_len].value;
- }
-
- gap_len = min_size;
- }
-
- /* Need we move the gap left? */
- while (pos < gap_start)
- {
- gap_start--;
-
- /* Copy one region from before to after the gap, and
- convert its position to end-relative. */
- c->boundaries[gap_start + gap_len].pos
- = c->boundaries[gap_start].pos + buffer_beg - buffer_end;
- c->boundaries[gap_start + gap_len].value
- = c->boundaries[gap_start].value;
- }
-
- /* Assign these back into the cache. */
- c->gap_start = gap_start;
- c->gap_len = gap_len;
-}
-
-
-/* Insert a new boundary in cache C; it will have cache index INDEX,
- and have the specified POS and VALUE. */
-static void
-insert_cache_boundary (c, index, pos, value)
- struct region_cache *c;
- int index;
- int pos, value;
-{
- /* index must be a valid cache index. */
- if (index < 0 || index > c->cache_len)
- abort ();
-
- /* We must never want to insert something before the dummy first
- boundary. */
- if (index == 0)
- abort ();
-
- /* We must only be inserting things in order. */
- if (! (BOUNDARY_POS (c, index-1) < pos
- && (index == c->cache_len
- || pos < BOUNDARY_POS (c, index))))
- abort ();
-
- /* The value must be different from the ones around it. However, we
- temporarily create boundaries that establish the same value as
- the subsequent boundary, so we're not going to flag that case. */
- if (BOUNDARY_VALUE (c, index-1) == value)
- abort ();
-
- move_cache_gap (c, index, 1);
-
- c->boundaries[index].pos = pos - c->buffer_beg;
- c->boundaries[index].value = value;
- c->gap_start++;
- c->gap_len--;
- c->cache_len++;
-}
-
-
-/* Delete the i'th entry from cache C if START <= i < END. */
-
-static void
-delete_cache_boundaries (c, start, end)
- struct region_cache *c;
- int start, end;
-{
- int len = end - start;
-
- /* Gotta be in range. */
- if (start < 0
- || end > c->cache_len)
- abort ();
-
- /* Gotta be in order. */
- if (start > end)
- abort ();
-
- /* Can't delete the dummy entry. */
- if (start == 0
- && end >= 1)
- abort ();
-
- /* Minimize gap motion. If we're deleting nothing, do nothing. */
- if (len == 0)
- ;
- /* If the gap is before the region to delete, delete from the start
- forward. */
- else if (c->gap_start <= start)
- {
- move_cache_gap (c, start, 0);
- c->gap_len += len;
- }
- /* If the gap is after the region to delete, delete from the end
- backward. */
- else if (end <= c->gap_start)
- {
- move_cache_gap (c, end, 0);
- c->gap_start -= len;
- c->gap_len += len;
- }
- /* If the gap is in the region to delete, just expand it. */
- else
- {
- c->gap_start = start;
- c->gap_len += len;
- }
-
- c->cache_len -= len;
-}
-
-
-
-/* Set the value for a region. */
-
-/* Set the value in cache C for the region START..END to VALUE. */
-static void
-set_cache_region (c, start, end, value)
- struct region_cache *c;
- int start, end;
- int value;
-{
- if (start > end)
- abort ();
- if (start < c->buffer_beg
- || end > c->buffer_end)
- abort ();
-
- /* Eliminate this case; then we can assume that start and end-1 are
- both the locations of real characters in the buffer. */
- if (start == end)
- return;
-
- {
- /* We need to make sure that there are no boundaries in the area
- between start to end; the whole area will have the same value,
- so those boundaries will not be necessary.
-
- Let start_ix be the cache index of the boundary governing the
- first character of start..end, and let end_ix be the cache
- index of the earliest boundary after the last character in
- start..end. (This tortured terminology is intended to answer
- all the "< or <=?" sort of questions.) */
- int start_ix = find_cache_boundary (c, start);
- int end_ix = find_cache_boundary (c, end - 1) + 1;
-
- /* We must remember the value established by the last boundary
- before end; if that boundary's domain stretches beyond end,
- we'll need to create a new boundary at end, and that boundary
- must have that remembered value. */
- int value_at_end = BOUNDARY_VALUE (c, end_ix - 1);
-
- /* Delete all boundaries strictly within start..end; this means
- those whose indices are between start_ix (exclusive) and end_ix
- (exclusive). */
- delete_cache_boundaries (c, start_ix + 1, end_ix);
-
- /* Make sure we have the right value established going in to
- start..end from the left, and no unnecessary boundaries. */
- if (BOUNDARY_POS (c, start_ix) == start)
- {
- /* Is this boundary necessary? If no, remove it; if yes, set
- its value. */
- if (start_ix > 0
- && BOUNDARY_VALUE (c, start_ix - 1) == value)
- {
- delete_cache_boundaries (c, start_ix, start_ix + 1);
- start_ix--;
- }
- else
- SET_BOUNDARY_VALUE (c, start_ix, value);
- }
- else
- {
- /* Do we need to add a new boundary here? */
- if (BOUNDARY_VALUE (c, start_ix) != value)
- {
- insert_cache_boundary (c, start_ix + 1, start, value);
- start_ix++;
- }
- }
-
- /* This is equivalent to letting end_ix float (like a buffer
- marker does) with the insertions and deletions we may have
- done. */
- end_ix = start_ix + 1;
-
- /* Make sure we have the correct value established as we leave
- start..end to the right. */
- if (end == c->buffer_end)
- /* There is no text after start..end; nothing to do. */
- ;
- else if (end_ix >= c->cache_len
- || end < BOUNDARY_POS (c, end_ix))
- {
- /* There is no boundary at end, but we may need one. */
- if (value_at_end != value)
- insert_cache_boundary (c, end_ix, end, value_at_end);
- }
- else
- {
- /* There is a boundary at end; should it be there? */
- if (value == BOUNDARY_VALUE (c, end_ix))
- delete_cache_boundaries (c, end_ix, end_ix + 1);
- }
- }
-}
-
-
-
-/* Interface: Invalidating the cache. Private: Re-validating the cache. */
-
-/* Indicate that a section of BUF has changed, to invalidate CACHE.
- HEAD is the number of chars unchanged at the beginning of the buffer.
- TAIL is the number of chars unchanged at the end of the buffer.
- NOTE: this is *not* the same as the ending position of modified
- region.
- (This way of specifying regions makes more sense than absolute
- buffer positions in the presence of insertions and deletions; the
- args to pass are the same before and after such an operation.) */
-void
-invalidate_region_cache (buf, c, head, tail)
- struct buffer *buf;
- struct region_cache *c;
- int head, tail;
-{
- /* Let chead = c->beg_unchanged, and
- ctail = c->end_unchanged.
- If z-tail < beg+chead by a large amount, or
- z-ctail < beg+head by a large amount,
-
- then cutting back chead and ctail to head and tail would lose a
- lot of information that we could preserve by revalidating the
- cache before processing this invalidation. Losing that
- information may be more costly than revalidating the cache now.
- So go ahead and call revalidate_region_cache if it seems that it
- might be worthwhile. */
- if (((BUF_BEG (buf) + c->beg_unchanged) - (BUF_Z (buf) - tail)
- > PRESERVE_THRESHOLD)
- || ((BUF_BEG (buf) + head) - (BUF_Z (buf) - c->end_unchanged)
- > PRESERVE_THRESHOLD))
- revalidate_region_cache (buf, c);
-
-
- if (head < c->beg_unchanged)
- c->beg_unchanged = head;
- if (tail < c->end_unchanged)
- c->end_unchanged = tail;
-
- /* We now know nothing about the region between the unchanged head
- and the unchanged tail (call it the "modified region"), not even
- its length.
-
- If the modified region has shrunk in size (deletions do this),
- then the cache may now contain boundaries originally located in
- text that doesn't exist any more.
-
- If the modified region has increased in size (insertions do
- this), then there may now be boundaries in the modified region
- whose positions are wrong.
-
- Even calling BOUNDARY_POS on boundaries still in the unchanged
- head or tail may well give incorrect answers now, since
- c->buffer_beg and c->buffer_end may well be wrong now. (Well,
- okay, c->buffer_beg never changes, so boundaries in the unchanged
- head will still be okay. But it's the principle of the thing.)
-
- So things are generally a mess.
-
- But we don't clean up this mess here; that would be expensive,
- and this function gets called every time any buffer modification
- occurs. Rather, we can clean up everything in one swell foop,
- accounting for all the modifications at once, by calling
- revalidate_region_cache before we try to consult the cache the
- next time. */
-}
-
-
-/* Clean out any cache entries applying to the modified region, and
- make the positions of the remaining entries accurate again.
-
- After calling this function, the mess described in the comment in
- invalidate_region_cache is cleaned up.
-
- This function operates by simply throwing away everything it knows
- about the modified region. It doesn't care exactly which
- insertions and deletions took place; it just tosses it all.
-
- For example, if you insert a single character at the beginning of
- the buffer, and a single character at the end of the buffer (for
- example), without calling this function in between the two
- insertions, then the entire cache will be freed of useful
- information. On the other hand, if you do manage to call this
- function in between the two insertions, then the modified regions
- will be small in both cases, no information will be tossed, and the
- cache will know that it doesn't have knowledge of the first and
- last characters any more.
-
- Calling this function may be expensive; it does binary searches in
- the cache, and causes cache gap motion. */
-
-static void
-revalidate_region_cache (buf, c)
- struct buffer *buf;
- struct region_cache *c;
-{
- /* The boundaries now in the cache are expressed relative to the
- buffer_beg and buffer_end values stored in the cache. Now,
- buffer_beg and buffer_end may not be the same as BUF_BEG (buf)
- and BUF_Z (buf), so we have two different "bases" to deal with
- --- the cache's, and the buffer's. */
-
- /* If the entire buffer is still valid, don't waste time. Yes, this
- should be a >, not a >=; think about what beg_unchanged and
- end_unchanged get set to when the only change has been an
- insertion. */
- if (c->buffer_beg + c->beg_unchanged
- > c->buffer_end - c->end_unchanged)
- return;
-
- /* If all the text we knew about as of the last cache revalidation
- is still there, then all of the information in the cache is still
- valid. Because c->buffer_beg and c->buffer_end are out-of-date,
- the modified region appears from the cache's point of view to be
- a null region located someplace in the buffer.
-
- Now, invalidating that empty string will have no actual affect on
- the cache; instead, we need to update the cache's basis first
- (which will give the modified region the same size in the cache
- as it has in the buffer), and then invalidate the modified
- region. */
- if (c->buffer_beg + c->beg_unchanged
- == c->buffer_end - c->end_unchanged)
- {
- /* Move the gap so that all the boundaries in the unchanged head
- are expressed beg-relative, and all the boundaries in the
- unchanged tail are expressed end-relative. That done, we can
- plug in the new buffer beg and end, and all the positions
- will be accurate.
-
- The boundary which has jurisdiction over the modified region
- should be left before the gap. */
- move_cache_gap (c,
- (find_cache_boundary (c, (c->buffer_beg
- + c->beg_unchanged))
- + 1),
- 0);
-
- c->buffer_beg = BUF_BEG (buf);
- c->buffer_end = BUF_Z (buf);
-
- /* Now that the cache's basis has been changed, the modified
- region actually takes up some space in the cache, so we can
- invalidate it. */
- set_cache_region (c,
- c->buffer_beg + c->beg_unchanged,
- c->buffer_end - c->end_unchanged,
- 0);
- }
-
- /* Otherwise, there is a non-empty region in the cache which
- corresponds to the modified region of the buffer. */
- else
- {
- int modified_ix;
-
- /* These positions are correct, relative to both the cache basis
- and the buffer basis. */
- set_cache_region (c,
- c->buffer_beg + c->beg_unchanged,
- c->buffer_end - c->end_unchanged,
- 0);
-
- /* Now the cache contains only boundaries that are in the
- unchanged head and tail; we've disposed of any boundaries
- whose positions we can't be sure of given the information
- we've saved.
-
- If we put the cache gap between the unchanged head and the
- unchanged tail, we can adjust all the boundary positions at
- once, simply by setting buffer_beg and buffer_end.
-
- The boundary which has jurisdiction over the modified region
- should be left before the gap. */
- modified_ix =
- find_cache_boundary (c, (c->buffer_beg + c->beg_unchanged)) + 1;
- move_cache_gap (c, modified_ix, 0);
-
- c->buffer_beg = BUF_BEG (buf);
- c->buffer_end = BUF_Z (buf);
-
- /* Now, we may have shrunk the buffer when we changed the basis,
- and brought the boundaries we created for the start and end
- of the modified region together, giving them the same
- position. If that's the case, we should collapse them into
- one boundary. Or we may even delete them both, if the values
- before and after them are the same. */
- if (modified_ix < c->cache_len
- && (BOUNDARY_POS (c, modified_ix - 1)
- == BOUNDARY_POS (c, modified_ix)))
- {
- int value_after = BOUNDARY_VALUE (c, modified_ix);
-
- /* Should we remove both of the boundaries? Yes, if the
- latter boundary is now establishing the same value that
- the former boundary's predecessor does. */
- if (modified_ix - 1 > 0
- && value_after == BOUNDARY_VALUE (c, modified_ix - 2))
- delete_cache_boundaries (c, modified_ix - 1, modified_ix + 1);
- else
- {
- /* We do need a boundary here; collapse the two
- boundaries into one. */
- SET_BOUNDARY_VALUE (c, modified_ix - 1, value_after);
- delete_cache_boundaries (c, modified_ix, modified_ix + 1);
- }
- }
- }
-
- /* Now the entire cache is valid. */
- c->beg_unchanged
- = c->end_unchanged
- = c->buffer_end - c->buffer_beg;
-}
-
-
-/* Interface: Adding information to the cache. */
-
-/* Assert that the region of BUF between START and END (absolute
- buffer positions) is "known," for the purposes of CACHE (e.g. "has
- no newlines", in the case of the line cache). */
-void
-know_region_cache (buf, c, start, end)
- struct buffer *buf;
- struct region_cache *c;
- int start, end;
-{
- revalidate_region_cache (buf, c);
-
- set_cache_region (c, start, end, 1);
-}
-
-
-/* Interface: using the cache. */
-
-/* Return true if the text immediately after POS in BUF is known, for
- the purposes of CACHE. If NEXT is non-zero, set *NEXT to the nearest
- position after POS where the knownness changes. */
-int
-region_cache_forward (buf, c, pos, next)
- struct buffer *buf;
- struct region_cache *c;
- int pos;
- int *next;
-{
- revalidate_region_cache (buf, c);
-
- {
- int i = find_cache_boundary (c, pos);
- int i_value = BOUNDARY_VALUE (c, i);
- int j;
-
- /* Beyond the end of the buffer is unknown, by definition. */
- if (pos >= BUF_Z (buf))
- {
- if (next) *next = BUF_Z (buf);
- i_value = 0;
- }
- else if (next)
- {
- /* Scan forward from i to find the next differing position. */
- for (j = i + 1; j < c->cache_len; j++)
- if (BOUNDARY_VALUE (c, j) != i_value)
- break;
-
- if (j < c->cache_len)
- *next = BOUNDARY_POS (c, j);
- else
- *next = BUF_Z (buf);
- }
-
- return i_value;
- }
-}
-
-/* Return true if the text immediately before POS in BUF is known, for
- the purposes of CACHE. If NEXT is non-zero, set *NEXT to the nearest
- position before POS where the knownness changes. */
-int region_cache_backward (buf, c, pos, next)
- struct buffer *buf;
- struct region_cache *c;
- int pos;
- int *next;
-{
- revalidate_region_cache (buf, c);
-
- /* Before the beginning of the buffer is unknown, by
- definition. */
- if (pos <= BUF_BEG (buf))
- {
- if (next) *next = BUF_BEG (buf);
- return 0;
- }
-
- {
- int i = find_cache_boundary (c, pos - 1);
- int i_value = BOUNDARY_VALUE (c, i);
- int j;
-
- if (next)
- {
- /* Scan backward from i to find the next differing position. */
- for (j = i - 1; j >= 0; j--)
- if (BOUNDARY_VALUE (c, j) != i_value)
- break;
-
- if (j >= 0)
- *next = BOUNDARY_POS (c, j + 1);
- else
- *next = BUF_BEG (buf);
- }
-
- return i_value;
- }
-}
-
-
-/* Debugging: pretty-print a cache to the standard error output. */
-
-void
-pp_cache (c)
- struct region_cache *c;
-{
- int i;
- int beg_u = c->buffer_beg + c->beg_unchanged;
- int end_u = c->buffer_end - c->end_unchanged;
-
- fprintf (stderr,
- "basis: %d..%d modified: %d..%d\n",
- c->buffer_beg, c->buffer_end,
- beg_u, end_u);
-
- for (i = 0; i < c->cache_len; i++)
- {
- int pos = BOUNDARY_POS (c, i);
-
- putc (((pos < beg_u) ? 'v'
- : (pos == beg_u) ? '-'
- : ' '),
- stderr);
- putc (((pos > end_u) ? '^'
- : (pos == end_u) ? '-'
- : ' '),
- stderr);
- fprintf (stderr, "%d : %d\n", pos, BOUNDARY_VALUE (c, i));
- }
-}
diff --git a/src/region-cache.h b/src/region-cache.h
deleted file mode 100644
index e950bf05629..00000000000
--- a/src/region-cache.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Header file: Caching facts about regions of the buffer, for optimization.
- Copyright (C) 1985, 1986, 1993, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* This code was written by Jim Blandy <jimb@cs.oberlin.edu> to help
- GNU Emacs better support the gene editor written for the University
- of Illinois at Urbana-Champagne's Ribosome Database Project (RDP).
-
- Emacs implements line operations (finding the beginning/end of the
- line, vertical motion, all the redisplay stuff) by searching for
- newlines in the buffer. Usually, this is a good design; it's very
- clean to just represent the buffer as an unstructured string of
- characters, and the lines in most files are very short (less than
- eighty characters), meaning that scanning usually costs about the
- same as the overhead of maintaining some more complicated data
- structure.
-
- However, some applications, like gene editing, make use of very
- long lines --- on the order of tens of kilobytes. In such cases,
- it may well be worthwhile to try to avoid scanning, because the
- scans have become two orders of magnitude more expensive. It would
- be nice if this speedup could preserve the simplicity of the
- existing data structure, and disturb as little of the existing code
- as possible.
-
- So here's the tack. We add some caching to the scan_buffer
- function, so that when it searches for a newline, it notes that the
- region between the start and end of the search contained no
- newlines; then, the next time around, it consults this cache to see
- if there are regions of text it can skip over completely. The
- buffer modification primitives invalidate this cache.
-
- (Note: Since the redisplay code needs similar information on
- modified regions of the buffer, we can use the code that helps out
- redisplay as a guide to where we need to add our own code to
- invalidate our cache. prepare_to_modify_buffer seems to be the
- central spot.)
-
- Note that the cache code itself never mentions newlines
- specifically, so if you wanted to cache other properties of regions
- of the buffer, you could use this code pretty much unchanged. So
- this cache really holds "known/unknown" information --- "I know
- this region has property P" vs. "I don't know if this region has
- property P or not." */
-
-
-/* Allocate, initialize and return a new, empty region cache. */
-struct region_cache *new_region_cache ( /* void */ );
-
-/* Free a region cache. */
-void free_region_cache ( /* struct region_cache * */ );
-
-/* Assert that the region of BUF between START and END (absolute
- buffer positions) is "known," for the purposes of CACHE (e.g. "has
- no newlines", in the case of the line cache). */
-extern void know_region_cache ( /* struct buffer *BUF,
- struct region_cache *CACHE,
- int START, END */ );
-
-/* Indicate that a section of BUF has changed, to invalidate CACHE.
- HEAD is the number of chars unchanged at the beginning of the buffer.
- TAIL is the number of chars unchanged at the end of the buffer.
- NOTE: this is *not* the same as the ending position of modified
- region.
- (This way of specifying regions makes more sense than absolute
- buffer positions in the presence of insertions and deletions; the
- args to pass are the same before and after such an operation.) */
-extern void invalidate_region_cache ( /* struct buffer *BUF,
- struct region_cache *CACHE,
- int HEAD, TAIL */ );
-
-/* The scanning functions.
-
- Basically, if you're scanning forward/backward from position POS,
- and region_cache_forward/backward returns true, you can skip all
- the text between POS and *NEXT. And if the function returns false,
- you should examine all the text from POS to *NEXT, and call
- know_region_cache depending on what you find there; this way, you
- might be able to avoid scanning it again. */
-
-/* Return true if the text immediately after POS in BUF is known, for
- the purposes of CACHE. If NEXT is non-zero, set *NEXT to the nearest
- position after POS where the knownness changes. */
-extern int region_cache_forward ( /* struct buffer *BUF,
- struct region_cache *CACHE,
- int POS,
- int *NEXT */ );
-
-/* Return true if the text immediately before POS in BUF is known, for
- the purposes of CACHE. If NEXT is non-zero, set *NEXT to the nearest
- position before POS where the knownness changes. */
-extern int region_cache_backward ( /* struct buffer *BUF,
- struct region_cache *CACHE,
- int POS,
- int *NEXT */ );
diff --git a/src/s/3700.h b/src/s/3700.h
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/src/s/3700.h
+++ /dev/null
diff --git a/src/s/386-ix.h b/src/s/386-ix.h
deleted file mode 100644
index dc17281df01..00000000000
--- a/src/s/386-ix.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Interactive 386/ix. */
-
-#include "usg5-3.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
-*/
-
-/* 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/386bsd.h b/src/s/386bsd.h
deleted file mode 100644
index f9f4a6a5ff2..00000000000
--- a/src/s/386bsd.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* s/ file for 386bsd system. */
-
-/* Get most of the stuff from bsd4.3 */
-#include "bsd4-3.h"
-
-#undef LIB_STANDARD
-#define LIB_STANDARD -lc $(GNULIB_VAR)
-
-/* The following should be set to /netbsd if you are running netbsd > 0.8
- Or just link /netbsd -> /386bsd */
-#undef KERNEL_FILE
-#define KERNEL_FILE "/386bsd"
-
-#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_p - (FILE)->_bf._base)
-
-/* Need to use GNU make, as system make has problems */
-#define MAKE_COMMAND gmake
-#define LIBS_DEBUG
-
-/* For mem-limits.h. */
-#define BSD4_2
-
-/* This affects a declaration in xrdb.c. */
-#define DECLARE_GETPWUID_WITH_UID_T
diff --git a/src/s/aix3-1.h b/src/s/aix3-1.h
deleted file mode 100644
index 4ed32fbcfbe..00000000000
--- a/src/s/aix3-1.h
+++ /dev/null
@@ -1,229 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#define 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"
-
-
-/* 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_TERMIOS
-
-/*
- * 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 interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_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) */
-
-#ifndef __GNUC__
-#define LINKER cc
-#endif
-
-/* 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
-
-/* Include unistd.h, even though we don't define POSIX. */
-#define NEED_UNISTD_H
-
-/* AIX doesn't define this. */
-#define unix 1
-
-/* AIX 3.1 has the HFT features. */
-#define AIXHFT
diff --git a/src/s/aix3-2-5.h b/src/s/aix3-2-5.h
deleted file mode 100644
index 7490b27abd9..00000000000
--- a/src/s/aix3-2-5.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* s- file for building Emacs on AIX 3.2.5. */
-
-#include "aix3-2.h"
-
-/* For AIX, it turns out compiling emacs under AIX 3.2.4 REQUIRES "cc -g"
- because "cc -O" crashes. Under AIX 3.2.5, "cc -O" is required because
- "cc -g" crashes. Go figure. --floppy@merlin.mit.edu */
-#ifndef __GNUC__
-#undef C_DEBUG_SWITCH
-#undef C_OPTIMIZE_SWITCH
-#define C_DEBUG_SWITCH -O
-#define C_OPTIMIZE_SWITCH -O
-#endif
-
-/* Perry Smith <pedz@ddivt1.austin.ibm.com> says these are correct. */
-#define SIGNALS_VIA_CHARACTERS
-#define MAIL_USE_LOCKF
-#define CLASH_DETECTION
-
-/* Perry Smith <pedz@ddivt1.austin.ibm.com> says these are correct. */
-#define POSIX_SIGNALS
-#undef sigmask
-#undef sigsetmask
-#undef _setjmp
-#undef _longjmp
-
-/* Bill Woodward <wpwood@austin.ibm.com> says:
- libIM *must* precede libXm, to avoid getting aixLoadIM error messages. */
-#define LIB_MOTIF -lIM -lXm
diff --git a/src/s/aix3-2.h b/src/s/aix3-2.h
deleted file mode 100644
index 2073ccf928d..00000000000
--- a/src/s/aix3-2.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* s- file for building Emacs on AIX 3.2. */
-
-#include "aix3-1.h"
-
-#define AIX3_2
-
-/* No need to define this--the header files indicate X11R4,
- and that's supposedly what 3.2 will come with. */
-#undef SPECIFY_X11R4
-
-#ifndef __GNUC__
-/* Some programs in src produce warnings saying certain subprograms
- are to comples and need a MAXMEM value greater than 2000 for
- additional optimization. --nils@exp-math.uni-essen.de */
-#define C_SWITCH_SYSTEM -ma -qmaxmem=4000
-#endif
-
-#define HAVE_ALLOCA
-/* Adrian Colley <Adrian.Colley@three.serpentine.com> says this is needed. */
-#ifndef NOT_C_CODE
-#ifndef AIX4
- #pragma alloca
-#endif
-#endif
-
-#undef rindex
-#undef index
-
-#define HAVE_FSYNC
-
-/* With this defined, a gcc-compiled Emacs crashed in realloc under AIX
- 3.2, and a cc-compiled Emacs works with this undefined.
- --karl@cs.umb.edu. */
-#undef SYSTEM_MALLOC
-
-/* For AIX, it turns out compiling emacs under AIX 3.2.4 REQUIRES "cc -g"
- because "cc -O" crashes. Under AIX 3.2.5, "cc -O" is required because
- "cc -g" crashes. Go figure. --floppy@merlin.mit.edu */
-#ifndef __GNUC__
-#define C_SWITCH_DEBUG -g
-#define C_SWITCH_OPTIMIZE
-#endif
-
-/* The character-composition stuff is broken in X11R5.
- Even with XIMStatusNothing aliased to XIMStatusNone,
- tranle@intellicorp.com (Minh Tran-Le) reports that enabling
- the internationalization code causes the modifier keys C, M and Shift
- to beep after a mouse click. */
-#define X11R5_INHIBIT_I18N
diff --git a/src/s/aix4-1.h b/src/s/aix4-1.h
deleted file mode 100644
index f5053a45afd..00000000000
--- a/src/s/aix4-1.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#define AIX4_1
-
-#include "aix4.h"
-
-/* olson@mcs.anl.gov says -li18n is needed by -lXm. */
-#undef LIB_MOTIF
-#define LIB_MOTIF -lXm -li18n
-
-#ifdef __GNUC__
-#undef _NO_PROTO
-#endif
-
-/* For AIX, it turns out compiling emacs under AIX 3.2.4 REQUIRES "cc -g"
- because "cc -O" crashes. Under AIX 3.2.5, "cc -O" is required because
- "cc -g" crashes. Go figure. --floppy@merlin.mit.edu.
- 4.1 seems to need -g again. -- larry@vaquita.mitra.com. */
-/* David Edelsohn <dje@watson.ibm.com> says that this actually depends
- on the version of XLC, which can't be predicted from the system version.
- What a mess! */
-#ifndef __GNUC__
-#undef C_DEBUG_SWITCH
-#undef C_OPTIMIZE_SWITCH
-#define C_DEBUG_SWITCH -g
-#endif
-
-/* The X internationalization stuff is still broken in AIX 4.1, so
- don't #undef X11R5_INHIBIT_I18N
- It still causes shift, ctrl, and alt to resend the last character,
- if it was a control character like tab, enter, backspace, or ESC.
- Bill_Mann @ PraxisInt.com */
-/* #undef X11R5_INHIBIT_I18N */
diff --git a/src/s/aix4.h b/src/s/aix4.h
deleted file mode 100644
index ae55ae3b317..00000000000
--- a/src/s/aix4.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#define AIX4
-
-#include "aix3-2-5.h"
-
-/* AIX 4 does not have HFT any more. */
-#undef AIXHFT
diff --git a/src/s/alliant-2800.h b/src/s/alliant-2800.h
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/src/s/alliant-2800.h
+++ /dev/null
diff --git a/src/s/alliant.h b/src/s/alliant.h
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/src/s/alliant.h
+++ /dev/null
diff --git a/src/s/altos.h b/src/s/altos.h
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/src/s/altos.h
+++ /dev/null
diff --git a/src/s/amdahl.h b/src/s/amdahl.h
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/src/s/amdahl.h
+++ /dev/null
diff --git a/src/s/bsd386.h b/src/s/bsd386.h
deleted file mode 100644
index c170c1efdca..00000000000
--- a/src/s/bsd386.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* s/ file for bsd386 system. */
-
-#include "bsd4-3.h"
-
-#ifndef __bsdi__
-#define __bsdi__ 1
-#endif
-
-#define DECLARE_GETPWUID_WITH_UID_T
-
-#define SIGNALS_VIA_CHARACTERS
-
-#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_p - (FILE)->_bf._base)
-#define A_TEXT_OFFSET(x) (sizeof (struct exec))
-#define A_TEXT_SEEK(hdr) (N_TXTOFF(hdr) + A_TEXT_OFFSET(hdr))
-
-#define LIBS_DEBUG
-#define LIB_X11_LIB -L/usr/X11/lib -lX11
-#define LIBS_SYSTEM -lutil -lkvm -lcompat
-
-#define HAVE_GETLOADAVG
-
-#undef BSD_PGRPS
-
-/* System uses OXTABS instead of the expected TAB3.
- (Copied from netbsd.h.) */
-#define TABDLY OXTABS
-#define TAB3 OXTABS
-
-#define SYSV_SYSTEM_DIR
-
-#define HAVE_TERMIOS
-#define NO_TERMIO
-
-/* This silences a few compilation warnings. */
-#ifdef emacs
-#undef BSD_SYSTEM
-#include <sys/param.h> /* To get BSD defined consistently. */
-#endif
-
-#define WAITTYPE int
-/* get this since it won't be included if WAITTYPE is defined */
-#ifdef emacs
-#include <sys/wait.h>
-#endif
-#define WRETCODE(w) WEXITSTATUS(w)
-#ifndef WCOREDUMP
-#define WCOREDUMP(w) ((w) & 0200)
-#endif
-
-#define GETPGRP_NO_ARG 1
diff --git a/src/s/bsd4-1.h b/src/s/bsd4-1.h
deleted file mode 100644
index 9bca58f08b5..00000000000
--- a/src/s/bsd4-1.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#define BSD4_1
-
-#define BSD_SYSTEM
-
-/* 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_PTYS if the system supports pty devices.
- */
-
-/* #define HAVE_PTYS */
-
-/* Define this macro if system defines a type `union wait'. */
-
-#define HAVE_UNION_WAIT
-
-/* 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
deleted file mode 100644
index 51ca3b77a9f..00000000000
--- a/src/s/bsd4-2.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* Definitions file for GNU Emacs running on bsd 4.2
- Copyright (C) 1985, 1986, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#ifndef BSD4_2
-#define BSD4_2 1
-#endif /* BSD4_2 */
-
-#ifndef BSD_SYSTEM
-#define BSD_SYSTEM 42
-#endif /* BSD_SYSTEM */
-
-/* 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_PTYS if the system supports pty devices.
- */
-
-#define HAVE_PTYS
-
-/* Define this macro if system defines a type `union wait'. */
-
-#define HAVE_UNION_WAIT
-
-/* 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"
-
-/* Send signals to subprocesses by "typing" special chars at them. */
-
-#define SIGNALS_VIA_CHARACTERS
-
-/* We do have vfork. */
-
-#define HAVE_VFORK
-
-/* Process groups work in the traditional BSD manner. */
-
-#define BSD_PGRPS
diff --git a/src/s/bsd4-3.h b/src/s/bsd4-3.h
deleted file mode 100644
index 85671c37057..00000000000
--- a/src/s/bsd4-3.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-/* We give these symbols the numeric values found in <sys/param.h> to
- avoid warnings about redefined macros. */
-#ifndef BSD4_3
-#define BSD4_3 1
-#endif /* BSD4_3 */
-
-#ifndef BSD_SYSTEM
-#define BSD_SYSTEM 43
-#endif /* BSD_SYSTEM */
-
-/* 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_PTYS if the system supports pty devices.
- */
-
-#define HAVE_PTYS
-
-/* Define this macro if system defines a type `union wait'. */
-
-#define HAVE_UNION_WAIT
-
-/* 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"
-
-/* Send signals to subprocesses by "typing" special chars at them. */
-
-#define SIGNALS_VIA_CHARACTERS
-
-/* We do have vfork. */
-
-#define HAVE_VFORK
diff --git a/src/s/bsdos2-1.h b/src/s/bsdos2-1.h
deleted file mode 100644
index 7a8b6630d02..00000000000
--- a/src/s/bsdos2-1.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/* s/ file for BSDI BSD/OS 2.1 system. */
-
-#include "bsdos2.h"
-
-#undef LIB_X11_LIB
-#define LIB_X11_LIB -L/usr/X11/lib -lX11 -lipc
diff --git a/src/s/bsdos2.h b/src/s/bsdos2.h
deleted file mode 100644
index c3c477c4d98..00000000000
--- a/src/s/bsdos2.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* s/ file for BSDI BSD/OS 2.0 system. */
-
-#include "bsd386.h"
-
-#define TEXT_START 0x1020 /* for QMAGIC */
-#define START_FILES pre-crt0.o /usr/lib/crt0.o
-#define HAVE_TERMIOS
-#define NO_TERMIO
diff --git a/src/s/cxux.h b/src/s/cxux.h
deleted file mode 100644
index 0281e789717..00000000000
--- a/src/s/cxux.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/* Header file for Harris CXUX.
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-/* #define UNIPLUS */
-#define USG5
-#define USG
-/* #define HPUX */
-/* #define UMAX */
-/* #define BSD4_1 */
-/* #define BSD4_2 */
-/* #define BSD4_3 */
-/* #define BSD_SYSTEM */
-/* #define VMS */
-
-#ifndef _CX_UX
-#define _CX_UX 1
-#endif
-
-/* Define this symbol if you are running CX/UX 7.0 or later (7.0 introduced
- * support for ELF files, and while we still build emacs in COFF format, the
- * way it is linked is different for 7.0).
- */
-/* #define USING_CX_UX_7 */
-
-#ifdef USING_CX_UX_7
-#define LINKER /usr/sde/coff/usr/bin/ld
-#define LD_SWITCH_SYSTEM -L/usr/sde/coff/usr/lib -zzero_word
-#define START_FILES pre-crt0.o /usr/sde/coff/usr/lib/crt0.o /usr/sde/coff/usr/lib/m88100.o
-#else /* !USING_CX_UX_7 */
-#ifdef _M88K
-#define START_FILES pre-crt0.o /lib/crt0.o
-#else
-#define START_FILES cxux-crt0.o /lib/crt0.o
-#endif
-#endif /* USING_CX_UX_7 */
-
-/* SYSTEM_TYPE should indicate the kind of system you are using.
- It sets the Lisp variable system-type. */
-
-#define SYSTEM_TYPE "usg-unix-v"
-
-#define C_SWITCH_SYSTEM -Xa
-
-#define POSIX_SIGNALS
-
-/* With POSIX signals, also need to use sigaction rather than signal to
- * setup signal handlers
- */
-#define signal sys_signal
-
-/* NOMULTIPLEJOBS should be defined if your system's shell
- does not have "job control" (the ability to stop a program,
- run some other program, then continue the first one). */
-
-/* #define NOMULTIPLEJOBS */
-
-/* Emacs can read input using SIGIO and buffering characters itself,
- or using CBREAK mode and making C-g cause SIGINT.
- The choice is controlled by the variable interrupt_input.
-
- Define INTERRUPT_INPUT to make interrupt_input = 1 the default (use SIGIO)
-
- Emacs uses the presence or absence of the SIGIO macro to indicate
- whether or not signal-driven I/O is possible. It uses
- INTERRUPT_INPUT to decide whether to use it by default.
-
- SIGIO can be used only on systems that implement it (4.2 and 4.3).
- CBREAK mode has two disadvantages
- 1) At least in 4.2, it is impossible to handle the Meta key properly.
- I hear that in system V this problem does not exist.
- 2) Control-G causes output to be discarded.
- I do not know whether this can be fixed in system V.
-
- Another method of doing input is planned but not implemented.
- It would have Emacs fork off a separate process
- to read the input and send it to the true Emacs process
- through a pipe. */
-
-#define INTERRUPT_INPUT
-/* #define BROKEN_FIONREAD */
-
-/* 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 PTY_ITERATION for (c = 'A'; c <= 'P'; c++) for (i = 0; i < 16; i++)
-
-/*
- * Define HAVE_TERMIOS if the system provides POSIX-style
- * functions and macros for terminal control.
- *
- * Define HAVE_TERMIO if the system provides sysV-style ioctls
- * for terminal control.
- *
- * Do not define both. HAVE_TERMIOS is preferred, if it is
- * supported on your system.
- */
-
-#define HAVE_TERMIOS
-/* #define HAVE_TERMIO */
-#define NO_TERMIO
-
-/*
- * Define HAVE_PTYS if the system supports pty devices.
- */
-
-#define HAVE_PTYS
-
-/*
- * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
- * The 4.2 opendir, etc., library functions.
- */
-
-/* #define NONSYSTEM_DIR_LIBRARY */
-
-#define 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 generally OS dependent, and not supported
- under most USG systems. */
-
-#define subprocesses
-
-/* If your system uses COFF (Common Object File Format) then define the
- preprocessor symbol "COFF". */
-
-#define COFF
-
-/* define MAIL_USE_FLOCK if the mailer uses flock
- to interlock access to /usr/spool/mail/$USER.
- The alternative is that a lock file named
- /usr/spool/mail/$USER.lock. */
-
-#define MAIL_USE_FLOCK
-
-/* Define CLASH_DETECTION if you want lock files to be written
- so that Emacs can tell instantly when you try to modify
- a file that someone else has modified in his Emacs. */
-
-#define CLASH_DETECTION
-
-/* Define this if your operating system declares signal handlers to
- have a type other than the usual. `The usual' is `void' for ANSI C
- systems (i.e. when the __STDC__ macro is defined), and `int' for
- pre-ANSI systems. If you're using GCC on an older system, __STDC__
- will be defined, but the system's include files will still say that
- signal returns int or whatever; in situations like that, define
- this to be what the system's include files want. */
-/* #define SIGTYPE int */
-#define SIGTYPE void
-
-/* If the character used to separate elements of the executable path
- is not ':', #define this to be the appropriate character constant. */
-/* #define SEPCHAR ':' */
-
-/* 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). */
-
-/* Yes! The Night Hawk has sockets! */
-
-#define HAVE_SOCKETS
-
-/* 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"
-
-#define KERNEL_FILE "/unix"
-
-/* There are too many kludges required to redefine malloc - use the system
- one */
-#define SYSTEM_MALLOC
-
-#define _setjmp setjmp
-#define _longjmp longjmp
-
-/* const really does work, but I can't get configure to run the C compiler
- * with the right options so it figures that out.
- */
-#undef const
-
-#define HAVE_GETWD
-
-#ifdef sigmask
-#undef sigmask
-#endif
-
-/*
- * <pwd.h> already declares getpwuid, and with a uid_t argument in ANSI C
- * mode. Define this so xrdb.c will compile
- */
-#ifdef __STDC__
-#define DECLARE_GETPWUID_WITH_UID_T
-#endif
-
-/* 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/cxux7.h b/src/s/cxux7.h
deleted file mode 100644
index 83323a98642..00000000000
--- a/src/s/cxux7.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* Define this symbol if you are running CX/UX 7.0 or later (7.0 introduced
- * support for ELF files, and while we still build emacs in COFF format, the
- * way it is linked is different for 7.0).
- */
-#define USING_CX_UX_7
-
-#include "cxux.h"
diff --git a/src/s/dgux.h b/src/s/dgux.h
deleted file mode 100644
index 6206908e2e2..00000000000
--- a/src/s/dgux.h
+++ /dev/null
@@ -1,370 +0,0 @@
-/* Definitions file for GNU Emacs running on Data General's DG/UX
- version 4.32 upto and including 5.4.1.
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-/* #define UNIPLUS */
-/* #define USG5 */
-/* #define USG */
-/* #define HPUX */
-/* #define UMAX */
-/* #define BSD4_1 */
-#define BSD4_2
-#define BSD4_3
-#define BSD4_4
-#define BSD_SYSTEM
-
-/* SYSTEM_TYPE should indicate the kind of system you are using.
- It sets the Lisp variable system-type. */
-
-#define SYSTEM_TYPE "dgux"
-
-/* 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 disadvantages
- 1) At least in 4.2, it is impossible to handle the Meta key properly.
- I hear that in system V this problem does not exist.
- 2) Control-G causes output to be discarded.
- I do not know whether this can be fixed in system V.
-
- Another method of doing input is planned but not implemented.
- It would have Emacs fork off a separate process
- to read the input and send it to the true Emacs process
- through a pipe.
-
-*/
-
-#define INTERRUPT_INPUT
-
-/*
- * Define HAVE_SOCKETS if the system supports sockets.
- */
-
-#define HAVE_SOCKETS
-
-/*
- * Define HAVE_UNIX_DOMAIN if the system supports Unix
- * domain sockets.
- */
-
-#define HAVE_UNIX_DOMAIN
-
-/*
- * Define HAVE_PTYS if the system supports pty devices.
- */
-
-#define HAVE_PTYS
-
-/* (Assume) we do have vfork. */
-
-#define HAVE_VFORK
-
-/*
- * 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; the default is ELF.
- To compile for COFF (or BCS) use the TARGET_BINARY_INTERFACE
- environment variable. */
-
-#if defined(_DGUXCOFF_TARGET) || defined(_DGUXBCS_TARGET)
-#undef ELF
-#ifndef COFF
-#define COFF
-#endif /* COFF */
-#else /* defined(_DGUXCOFF_TARGET) || defined(_DGUXBCS_TARGET) */
-#undef COFF
-#ifndef ELF
-#define ELF
-#endif /* ELF */
-#endif /* defined(_DGUXCOFF_TARGET) || defined(_DGUXBCS_TARGET) */
-
-#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 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
-
-/*
- * Send signals to subprocesses using characters.
- *
- */
-
-#define SIGNALS_VIA_CHARACTERS
-
-/*
- * Define HAVE_TERMIOS since this is POSIX,
- * for terminal control. Prevent redundant inclusion of termio.h.
- */
-
-#define HAVE_TERMIOS
-#define NO_TERMIO
-
-/*
- * 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 SYSTEM_MALLOC */
-
-/* MAKING_MAKEFILE must be defined in "ymakefile" before including config.h */
-#ifndef NOT_C_CODE
-
-/* Make sure signal.h is included so macros below don't mess with it. */
-/* DG/UX include files prevent multiple inclusion. */
-
-#include <signal.h>
-
-/* but undefine the sigmask and sigpause macros since they will get
- #define'd later. */
-#undef sigmask
-#undef sigpause
-
-#define POSIX_SIGNALS
-
-/* Define this if you use System 5 Release 4 Streams */
-#define open sys_open
-#define close sys_close
-#define read sys_read
-#define write sys_write
-
-#define INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_CLOSE
-/* can't hurt to define these, even though read/write should auto restart */
-#define INTERRUPTIBLE_IO
-
-/* Can't use sys_signal because then etc/server.c would need sysdep.o. */
-extern struct sigaction act, oact;
-#define signal(SIG,FUNC) berk_signal(SIG,FUNC)
-
-#endif /* not NOT_C_CODE */
-
-#ifndef __GNUC__
-#error You must use GCC to compiler Emascs on DGUX
-#endif
-
-#define ORDINARY_LINK
-#define START_FILES pre-crt0.o
-#define LIB_GCC /usr/lib/gcc/libgcc.a
-
-#ifdef _M88KBCS_TARGET
-/* Karl Berry says: the environment
- recommended by gcc (88/open, a.k.a. m88kbcs) doesn't support some system
- functions, and gcc doesn't make it easy to switch environments. */
-#define NO_GET_LOAD_AVG
-#endif
-
-/* definitions for xmakefile production */
-#ifdef COFF
-
-/* Define the following to use all of the available pty's. */
-
-#define PTY_ITERATION \
- for (c = 'p'; c < 't'; c++) \
- for (i = 0; (((c == 'p') && (i < 64)) || ((c != 'p') && (i < 16))); i++)
-
-#define PTY_NAME_SPRINTF \
- if (c == 'p') \
- sprintf (pty_name, "/dev/pty%c%d", c, i); \
- else \
- sprintf (pty_name, "/dev/pty%c%x", c, i);
-
-#define PTY_TTY_NAME_SPRINTF \
- if (c == 'p') \
- sprintf (pty_name, "/dev/tty%c%d", c, i); \
- else \
- sprintf (pty_name, "/dev/tty%c%x", c, i);
-
-#define C_DEBUG_SWITCH -g
-
-#else /* not COFF */
-
-/* We are generating ELF object format. This makes the system more
- SVR4 like. */
-
-#define SVR4
-
-/* Pseudo-terminal support under SVR4 only loops to deal with errors. */
-
-#define PTY_ITERATION for (i = 0; i < 1; i++)
-
-/* 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; \
- \
- sigblock(sigmask(SIGCLD)); \
- if (grantpt(fd) == -1) \
- fatal("could not grant slave pty"); \
- sigunblock(sigmask(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);
-
-#ifdef __GNUC__
-#define C_DEBUG_SWITCH -g -V2 -mversion-03.00 -mstandard
-#endif
-
-#endif /* ELF */
-
-/* Extra stuff which probably should be someplace else but is here out
- of expediency. */
-
-#define LIB_X11_LIB -lX11
-#define LIB_MOTIF -lXm -lgen
-
-/* Process groups work in the traditional BSD manner. */
-
-#define BSD_PGRPS
diff --git a/src/s/dgux5-4-3.h b/src/s/dgux5-4-3.h
deleted file mode 100644
index cd6932ec856..00000000000
--- a/src/s/dgux5-4-3.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* Definitions file for GNU Emacs running on Data General's DG/UX
- version 5.4 Release 3.00 and above.
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* NOTE: DGUX5.4R3.00 will not build with the delivered gcc-2.4.5
- compiler. You must upgraded to at least gcc-2.5.8. If you are
- running DGUX 5.4R3.00 check on the system dg-rtp.dg.com:/pub/gnu
- for gcc-2.5.8 or later compiler.
- -pmr@pajato.com */
-
-#include "dgux5-4r2.h"
-
-/* DGUX 5.4R3.00 brought the definition of `struct inet_addr' into
- compliance with the majority of Unix systems. The workaround
- introduced in 5.4R2 is no longer necessary. */
-
-#ifdef HAVE_BROKEN_INET_ADDR
-#undef HAVE_BROKEN_INET_ADDR
-#endif
-
-/* The `stop on tty output' problem which occurs when using
- INTERRUPT_INPUT and when Emacs is invoked under X11 using a job
- control shell (csh, ksh, etc.) in the background has not been fixed in
- DGUX 5.4R3.00.
- -pmr@pajato.com */
-
-#if 0
-#ifdef BROKEN_FIONREAD
-#undef BROKEN_FIONREAD
-#endif
-#ifndef INTERRUPT_INPUT
-#define INTERRUPT_INPUT
-#endif
-#endif
-
-/* Under DGUX 5.4R3.00, getting a debuggable executable has been
- greatly simplified and applies to either COFF or ELF
- environments. */
-
-#ifdef C_DEBUG_SWITCH
-#undef C_DEBUG_SWITCH
-#define C_DEBUG_SWITCH -g
-#endif
diff --git a/src/s/dgux5-4R2.h b/src/s/dgux5-4R2.h
deleted file mode 100644
index e13d50be4b4..00000000000
--- a/src/s/dgux5-4R2.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Definitions file for GNU Emacs running on Data General's DG/UX
- 5.4 Release 2.xx systems.
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include "dgux.h"
-
-/* There is a known kernel bug in DGUX 5.4R2.xx when using
- INTERRUPT_INPUT and invoking Emacs with a job control shell (csh,
- ksh, etc.) in the background. This bug manifests itself by
- outputting `stop on tty output' and hanging. The workaround is to
- set BROKEN_FIONREAD.
- -pmr@pajato.com */
-
-#ifndef BROKEN_FIONREAD
-#define BROKEN_FIONREAD
-#endif
-#ifdef INTERRUPT_INPUT
-#undef INTERRUPT_INPUT
-#endif
-
-/* In DGUX 5.4R2.xx the function inet_addr() returns a `struct
- in_addr' instead of the more common `unsigned long'.
- -pmr@pajato.com */
-
-#define HAVE_BROKEN_INET_ADDR
-
-#if 0 /* Shawn M. Carey <smcarey@mailbox.syr.edu> found this
- caused trouble on DGUX 5.4.2. */
-#define LIBS_SYSTEM -ldgc
-#endif
diff --git a/src/s/dgux5-4R3.h b/src/s/dgux5-4R3.h
deleted file mode 100644
index e1c2bde4386..00000000000
--- a/src/s/dgux5-4R3.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Definitions file for GNU Emacs running on Data General's DG/UX
- version 5.4 Release 3.00 and above.
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* NOTE: DGUX5.4R3.00 will not build with the delivered gcc-2.4.5
- compiler. You must upgraded to at least gcc-2.5.8. If you are
- running DGUX 5.4R3.00 check on the system dg-rtp.dg.com:/pub/gnu
- for gcc-2.5.8 or later compiler.
- -pmr@pajato.com */
-
-#include "dgux5-4R2.h"
-
-/* DGUX 5.4R3.00 brought the definition of `struct inet_addr' into
- compliance wiht the majority of Unix systems. The workaround
- introduced in 5.4R2 is no longer necessary. */
-
-#ifdef HAVE_BROKEN_INET_ADDR
-#undef HAVE_BROKEN_INET_ADDR
-#endif
-
-/* The `stop on tty output' problem which occurs when using
- INTERRUPT_INPUT and when Emacs is invoked under X11 using a job
- control shell (csh, ksh, etc.) in the background has not been fixed in
- DGUX 5.4R3.00.
- -pmr@pajato.com */
-
-#if 0
-#ifdef BROKEN_FIONREAD
-#undef BROKEN_FIONREAD
-#endif
-#ifndef INTERRUPT_INPUT
-#define INTERRUPT_INPUT
-#endif
-#endif
-
-/* Under DGUX 5.4R3.00, getting a debuggable executable has been
- greatly simplified and applies to either COFF or ELF
- environments. */
-
-#ifdef C_DEBUG_SWITCH
-#undef C_DEBUG_SWITCH
-#define C_DEBUG_SWITCH -g
-#endif
diff --git a/src/s/dgux5-4r2.h b/src/s/dgux5-4r2.h
deleted file mode 100644
index 1eaeccdf269..00000000000
--- a/src/s/dgux5-4r2.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Definitions file for GNU Emacs running on Data General's DG/UX
- 5.4 Release 2.xx systems.
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include "dgux.h"
-
-/* There is a known kernel bug in DGUX 5.4R2.xx when using
- INTERRUPT_INPUT and invoking Emacs with a job control shell (csh,
- ksh, etc.) in the background. This bug manifests itself by
- outputting `stop on tty output' and hanging. The workaround is to
- set BROKEN_FIONREAD.
- -pmr@pajato.com */
-
-#ifndef BROKEN_FIONREAD
-#define BROKEN_FIONREAD
-#endif
-#ifdef INTERRUPT_INPUT
-#undef INTERRUPT_INPUT
-#endif
-
-/* In DGUX 5.4R2.xx the function inet_addr() returns a `struct
- in_addr' instead of the more common `unsigned long'.
- -pmr@pajato.com */
-
-#define HAVE_BROKEN_INET_ADDR
-
-#if 0 /* Shawn M. Carey <smcarey@mailbox.syr.edu> found this
- caused trouble on DGUX 5.4.2. */
-#define LIBS_SYSTEM -ldgc
-#endif
diff --git a/src/s/esix.h b/src/s/esix.h
deleted file mode 100644
index 64d0822bf5f..00000000000
--- a/src/s/esix.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Definitions for ESIX, a variant of v.5.3 for the 386. */
-/* These are based on reports for ESIX 5.3.2 D. */
-
-#include "usg5-3.h"
-
-/* 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 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 BROKEN_FIONREAD
diff --git a/src/s/esix5r4.h b/src/s/esix5r4.h
deleted file mode 100644
index d8cf0184f3a..00000000000
--- a/src/s/esix5r4.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Definitions for ESIX System V 4.0.4, a variant of V.4 for the 386. */
-/* Redone by zircon!joe@uunet.uu.net (Joe Kelsey). */
-
-#include "usg5-4.h"
-
-#define SYSTEM_MALLOC 1
-#if defined (HAVE_XFREE386)
-# undef LIB_STANDARD
-# define LIB_STANDARD -lc
-#else
-# define LIB_X11_LIB -lsocket -lc -lX11
-# undef LIB_STANDARD
-# ifdef ORDINARY_LINK
-# define LIB_STANDARD -lnsl -lns -lelf /usr/ucblib/libucb.a
-# else
-# define LIB_STANDARD -lnsl -lns -lelf /usr/ucblib/libucb.a /usr/ccs/lib/crtn.o
-# endif
-
-/* Resolve BSD string functions in X Window library from libucb.a. */
-# define BSTRING
-
-/* zircon!joe says this makes X windows work. */
-# define BROKEN_FIONREAD
-#endif
diff --git a/src/s/freebsd.h b/src/s/freebsd.h
deleted file mode 100644
index 9affb886231..00000000000
--- a/src/s/freebsd.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* s/ file for freebsd system. */
-
-/* '__FreeBSD__' is defined by the preprocessor on FreeBSD-1.1 and up.
- Earlier versions do not have shared libraries, so inhibit them.
- You can inhibit them on newer systems if you wish
- by defining NO_SHARED_LIBS. */
-#ifndef __FreeBSD__
-#define NO_SHARED_LIBS
-#endif
-
-
-#if 0 /* This much, alone, seemed sufficient as of 19.23.
- But it seems better to be independent of netbsd.h. */
-#include "netbsd.h"
-
-#undef LIB_GCC
-#define LIB_GCC -lgcc
-#undef NEED_ERRNO
-#endif /* 0 */
-
-
-/* Get most of the stuff from bsd4.3 */
-#include "bsd4-3.h"
-
-/* For mem-limits.h. */
-#define BSD4_2
-
-/* These aren't needed, since we have getloadavg. */
-#undef KERNEL_FILE
-#undef LDAV_SYMBOL
-
-#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_p - (FILE)->_bf._base)
-
-#define LIBS_DEBUG
-#define LIBS_SYSTEM -lutil
-#define LIBS_TERMCAP -ltermcap
-#define LIB_GCC -lgcc
-
-#define SYSV_SYSTEM_DIR
-
-/* freebsd has POSIX-style pgrp behavior. */
-#undef BSD_PGRPS
-#define GETPGRP_NO_ARG
-
-#ifndef NO_SHARED_LIBS
-#define LD_SWITCH_SYSTEM -e start -dc -dp
-#define HAVE_TEXT_START /* No need to define `start_of_text'. */
-#define START_FILES pre-crt0.o /usr/lib/crt0.o
-#define UNEXEC unexsunos4.o
-#define RUN_TIME_REMAP
-
-#ifndef N_TRELOFF
-#define N_PAGSIZ(x) __LDPGSZ
-#define N_BSSADDR(x) (N_ALIGN(x, N_DATADDR(x)+x.a_data))
-#define N_TRELOFF(x) N_RELOFF(x)
-#endif
-#else /* NO_SHARED_LIBS */
-#ifdef __FreeBSD__ /* shared libs are available, but the user prefers
- not to use them. */
-#define LD_SWITCH_SYSTEM -Bstatic
-#define A_TEXT_OFFSET(x) (sizeof (struct exec))
-#define A_TEXT_SEEK(hdr) (N_TXTOFF(hdr) + A_TEXT_OFFSET(hdr))
-#endif /* __FreeBSD__ */
-#endif /* NO_SHARED_LIBS */
-
-#define HAVE_WAIT_HEADER
-#define HAVE_GETLOADAVG
-/*#define HAVE_GETPAGESIZE /* configure now puts this in config.h */
-#define HAVE_TERMIOS
-#define NO_TERMIO
-#define DECLARE_GETPWUID_WITH_UID_T
-
-/* freebsd uses OXTABS instead of the expected TAB3. */
-#define TABDLY OXTABS
-#define TAB3 OXTABS
-
-/* this silences a few compilation warnings */
-#undef BSD_SYSTEM
-#if __FreeBSD__ == 1
-#define BSD_SYSTEM 199103
-#elif __FreeBSD__ == 2
-#define BSD_SYSTEM 199306
-#endif
-
-#define WAITTYPE int
-/* get this since it won't be included if WAITTYPE is defined */
-#ifdef emacs
-#include <sys/wait.h>
-#endif
-#define WRETCODE(w) (_W_INT(w) >> 8)
-
-/* Needed to avoid hanging when child process writes an error message
- and exits -- enami tsugutomo <enami@ba2.so-net.or.jp>. */
-#define vfork fork
-
-/* Don't close pty in process.c to make it as controlling terminal.
- It is already a controlling terminal of subprocess, because we did
- ioctl TIOCSCTTY. */
-#define DONT_REOPEN_PTY
diff --git a/src/s/gnu-linux.h b/src/s/gnu-linux.h
deleted file mode 100644
index ccce9cc84d2..00000000000
--- a/src/s/gnu-linux.h
+++ /dev/null
@@ -1,295 +0,0 @@
-/* This file is the configuration file for Linux-based GNU systems
- Copyright (C) 1985, 1986, 1992, 1994, 1996 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* This file was put together by Michael K. Johnson and Rik Faith. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-/* #define UNIPLUS */
-/* #define USG5 */
-#define USG
-/* #define BSD_SYSTEM */
-#define LINUX
-
-/* SYSTEM_TYPE should indicate the kind of system you are using.
- It sets the Lisp variable system-type. */
-
-#define SYSTEM_TYPE "gnu/linux" /* All the best software is free. */
-
-/* Check the version number of Linux--if it is at least 1.2.0,
- it is safe to use SIGIO. */
-#ifndef NOT_C_CODE
-#ifdef emacs
-#ifdef HAVE_LINUX_VERSION_H
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE > 0x10200
-#define LINUX_SIGIO_DOES_WORK
-#endif /* LINUX_VERSION_CODE > 0x10200 */
-#endif /* HAVE_LINUX_VERSION_H */
-#endif /* emacs */
-#endif /* NOT_C_CODE */
-
-/* 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_TERMIOS if the system provides POSIX-style
- * functions and macros for terminal control.
- */
-
-#define HAVE_TERMIOS
-
-/*
- * Define HAVE_PTYS if the system supports pty devices.
- */
-
-#define HAVE_PTYS
-
-/* Uncomment this later when other problems are dealt with -mkj */
-
-#define HAVE_SOCKETS
-
-/* 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
-
-/* 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. */
-
-/* On GNU/Linux systems, both methods are used by various mail
- programs. I assume that most people are using newer mailers that
- have heard of flock. Change this if you need to. */
-
-#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). */
-
-/* On POSIX systems the system calls are interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_CLOSE
-#define INTERRUPTIBLE_IO
-
-/* If you mount the proc file system somewhere other than /proc
- you will have to uncomment the following and make the proper
- changes */
-
-/* #define LINUX_LDAV_FILE "/proc/loadavg" */
-
-/* This is needed for dispnew.c:update_frame */
-
-#ifdef emacs
-#include <stdio.h> /* Get the definition of _IO_STDIO_H. */
-#if defined(_IO_STDIO_H) || defined(_STDIO_USES_IOSTREAM)
-/* new C libio names */
-#define GNU_LIBRARY_PENDING_OUTPUT_COUNT(FILE) \
- ((FILE)->_IO_write_ptr - (FILE)->_IO_write_base)
-#else /* !_IO_STDIO_H */
-/* old C++ iostream names */
-#define GNU_LIBRARY_PENDING_OUTPUT_COUNT(FILE) \
- ((FILE)->_pptr - (FILE)->_pbase)
-#endif /* !_IO_STDIO_H */
-#endif /* emacs */
-
-/* Ask GCC where to find libgcc.a. */
-#define LIB_GCC `$(CC) $(C_SWITCH_X_SITE) -print-libgcc-file-name`
-
-#ifndef __ELF__
-/* GNU/Linux usually has crt0.o in a non-standard place */
-#define START_FILES pre-crt0.o /usr/lib/crt0.o
-#else
-#define START_FILES pre-crt0.o /usr/lib/crt1.o /usr/lib/crti.o
-#endif
-
-#ifdef __ELF__
-/* Here is how to find X Windows. LD_SWITCH_X_SITE_AUX gives an -R option
- says where to find X windows at run time. */
-
-#define LD_SWITCH_SYSTEM LD_SWITCH_X_SITE_AUX
-#endif /* __ELF__ */
-
-/* As of version 1.1.51, Linux did not actually implement SIGIO.
- But it works in newer versions. */
-/* Here we assume that signal.h is already included. */
-#ifdef emacs
-#ifdef LINUX_SIGIO_DOES_WORK
-#define INTERRUPT_INPUT
-#else
-#undef SIGIO
-/* Some versions of Linux define SIGURG and SIGPOLL as aliases for SIGIO.
- This prevents lossage in process.c. */
-#undef SIGURG
-#undef SIGPOLL
-#endif
-#endif
-
-/* This is needed for sysdep.c */
-
-#define NO_SIOCTL_H /* don't have sioctl.h */
-
-#define HAVE_VFORK
-#define HAVE_SYS_SIGLIST
-#define HAVE_GETWD /* cure conflict with getcwd? */
-#define HAVE_WAIT_HEADER
-
-#define SYSV_SYSTEM_DIR /* use dirent.h */
-
-#define POSIX /* affects getpagesize.h and systty.h */
-#define POSIX_SIGNALS
-
-/* Best not to include -lg, unless it is last on the command line */
-#define LIBS_DEBUG
-#ifndef __ELF__
-#define LIB_STANDARD -lc /* avoid -lPW */
-#else
-#undef LIB_GCC
-#define LIB_GCC
-#define LIB_STANDARD -lgcc -lc -lgcc /usr/lib/crtn.o
-#endif
-
-/* Don't use -g in test compiles in configure.
- This is so we will use the same shared libs for that linking
- that are used when linking temacs. */
-#ifdef THIS_IS_CONFIGURE
-#define C_DEBUG_SWITCH
-#endif
-
-/* Let's try this out, just in case.
- Nah. Rik Faith <faith@cs.unc.edu> says it doesn't work well. */
-/* #define SIGNALS_VIA_CHARACTERS */
-
-/* Rob Malouf <malouf@csli.stanford.edu> says:
- SYSV IPC is standard a standard part of Linux since version 0.99pl10,
- and is a very common addition to previous versions. */
-
-#ifdef TERM
-#define LIBS_SYSTEM -lclient
-#define C_SWITCH_SYSTEM -D_BSD_SOURCE -I/usr/src/term
-#else
-/* alane@wozzle.linet.org says that -lipc is not a separate library,
- since libc-4.4.1. So -lipc was deleted. */
-#define LIBS_SYSTEM
-#define C_SWITCH_SYSTEM -D_BSD_SOURCE
-#endif
-
-/* Paul Abrahams <abrahams@equinox.shaysnet.com> says this is needed. */
-#define LIB_MOTIF -lXm -lXpm
-
-#ifdef HAVE_LIBNCURSES
-#define TERMINFO
-#define LIBS_TERMCAP -lncurses
-#endif
-
-#define HAVE_SYSVIPC
-
-#ifdef __ELF__
-#define UNEXEC unexelf.o
-#define UNEXEC_USE_MAP_PRIVATE
-#endif
-
-#ifdef LINUX_QMAGIC
-
-#define HAVE_TEXT_START
-#define UNEXEC unexsunos4.o
-#define N_PAGSIZ(x) PAGE_SIZE
-
-#else /* not LINUX_QMAGIC */
-
-#define A_TEXT_OFFSET(hdr) (N_MAGIC(hdr) == QMAGIC ? sizeof (struct exec) : 0)
-#define A_TEXT_SEEK(hdr) (N_TXTOFF(hdr) + A_TEXT_OFFSET(hdr))
-#define ADJUST_EXEC_HEADER \
- unexec_text_start = N_TXTADDR(ohdr) + A_TEXT_OFFSET(ohdr)
-
-#endif /* not LINUX_QMAGIC */
-
-#if 0
-/* In 19.23 and 19.24, configure sometimes fails to define these.
- It has to do with the fact that configure uses CFLAGS when linking
- while Makefile.in.in (erroneously) fails to do so when linking temacs. */
-#ifndef HAVE_GETTIMEOFDAY
-#define HAVE_GETTIMEOFDAY
-#endif
-#ifndef HAVE_MKDIR
-#define HAVE_MKDIR
-#endif
-#ifndef HAVE_RMDIR
-#define HAVE_RMDIR
-#endif
-#ifndef HAVE_XSCREENNUMBEROFSCREEN
-#define HAVE_XSCREENNUMBEROFSCREEN
-#endif
-#endif /* 0 */
-
-/* This is to work around mysterious gcc failures in some system versions.
- It is unlikely that Emacs changes will work around this problem;
- therefore, this should remain permanently. */
-#ifndef HAVE_XRMSETDATABASE
-#define HAVE_XRMSETDATABASE
-#endif
-
-/* The regex.o routines are a part of the GNU C-library used with Linux. */
-/* However, sometimes they disagree with the src/regex.h that comes with Emacs,
- and that can make trouble in etags.c because it gets the regex.h from Emacs
- and the function definitions in libc. So turn this off. */
-/* #define REGEXP_IN_LIBC */
-
-/* Use BSD process groups, but use setpgid() instead of setpgrp() to
- actually set a process group. */
-
-#define BSD_PGRPS
-#define setpgrp(pid,pgid) setpgid((pid),(pgid))
diff --git a/src/s/gnu.h b/src/s/gnu.h
deleted file mode 100644
index 67c818848e6..00000000000
--- a/src/s/gnu.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Definitions file for GNU Emacs running on the GNU Hurd.
- Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Get most of the stuff from bsd4.3 */
-#include "bsd4-3.h"
-
-/* For mem-limits.h. */
-#define BSD4_2
-
-#undef SYSTEM_TYPE
-#define SYSTEM_TYPE "gnu"
-
-/* XXX should getloadavg be in libc? Should we have a libutil?
-#define HAVE_GETLOADAVG */
-
-#define SIGNALS_VIA_CHARACTERS
-
-#define HAVE_TERMIOS
-#define NO_TERMIO
-
-#define LIBS_DEBUG
-
-/* XXX emacs should not expect TAB3 to be defined. */
-#define TABDLY OXTABS
-#define TAB3 OXTABS
-
-/* Tell Emacs that we are a terminfo based system; disable the use
- of local termcap. (GNU uses ncurses.) */
-#ifdef HAVE_LIBNCURSES
-#define TERMINFO
-#define LIBS_TERMCAP -lncurses
-#endif
-
-#define SYSV_SYSTEM_DIR
-
-/* GNU has POSIX-style pgrp behavior. */
-#undef BSD_PGRPS
-#define GETPGRP_NO_ARG
-
-#define HAVE_WAIT_HEADER
-#define WAIT_USE_INT
-#define HAVE_UNION_WAIT
-
-/* GNU needs its own crt0, and libc defines data_start. */
-#define ORDINARY_LINK
-#define DATA_START ({ extern int data_start; (char *) &data_start; })
-
-/* GNU now always uses the ELF format. */
-#define UNEXEC unexelf.o
-
-/* Some losing code fails to include this and then assumes
- that because it is braindead that O_RDONLY==0. */
-#ifndef NOT_C_CODE
-#include <fcntl.h>
-#endif
diff --git a/src/s/hiuxmpp.h b/src/s/hiuxmpp.h
deleted file mode 100644
index 022eb40562b..00000000000
--- a/src/s/hiuxmpp.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* System description file for HI-UX. */
-
-#define BSD 198911 /* system version (year & month) */
-#define DBL_DIG 15 /* same as the definition of <float.h> */
-#include "bsd4-3.h"
-
-/* Identify OSF1 for the m- files. */
-
-#define OSF1
-
-/* To avoid to include the non-existant header file <sys/vlimit.h>,
- we define BSD4_2.
- This definition does not mean that the OS is based on BSD 4.2. */
-#define BSD4_2
-
-/* Define _BSD to tell the include files we're running under
- the BSD universe and not the SYSV universe.
- Define HITACHI and OSF for Xt's Boolean type as int intead of char.
- (But for these defines, /usr/include/X11/Intrinsic.h defines
- Boolean as char, but libXt.a on HI-UX/MPP requires it as int.) */
-
-#define C_SWITCH_SYSTEM -D_BSD -DHITACHI -DOSF
-#define LIBS_SYSTEM -lbsd
-
-#define GETPGRP_NO_ARG
-
-#define read sys_read
-#define write sys_write
-#define open sys_open
-#define close sys_close
-
-#define INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_CLOSE
-#define INTERRUPTIBLE_IO
-
-#define SYSV_SYSTEM_DIR
-
-/* If your system uses COFF (Common Object File Format) then define the
- preprocessor symbol "COFF". */
-
-/* #define COFF */
-
-/* Here is how to find X Windows. LD_SWITCH_X_SITE_AUX gives an -R option
- says where to find X windows at run time. We convert it to a -rpath option
- which is what OSF1 uses. */
-#define LD_SWITCH_SYSTEM
-
-#undef KERNEL_FILE
-#define KERNEL_FILE "/mach_kernel"
-
-#undef LDAV_SYMBOL
-#define LDAV_SYMBOL "avenrun"
-
diff --git a/src/s/hpux.h b/src/s/hpux.h
deleted file mode 100644
index 5b1f42d1501..00000000000
--- a/src/s/hpux.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/* Definitions file for GNU Emacs running on HPUX release 7.0.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#define 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_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 equivalents
- * 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 interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_IO
-
-/* Use the system provided termcap(3) library */
-#define TERMINFO
-
-/* The 48-bit versions are more winning for Emacs;
- the ordinary ones don't give even 32 bits. */
-#define random lrand48
-#define srandom srand48
-
-/* In hpux, the symbol SIGIO is defined, but the feature
- doesn't work in the way Emacs needs it to.
-
- 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_VFORK
-#define HAVE_PERROR /* Delete this line for version 6. */
-
-/* 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
-
-/* This is how to get the device name of the tty end of a pty. */
-#define PTY_TTY_NAME_SPRINTF \
- sprintf (pty_name, "/dev/pty/tty%c%x", c, i);
-
-/* This is how to get the device name of the control end of a pty. */
-#define PTY_NAME_SPRINTF \
- sprintf (pty_name, "/dev/ptym/pty%c%x", c, i);
-
-/* This triggers a conditional in xfaces.c. */
-#define XOS_NEEDS_TIME_H
diff --git a/src/s/hpux10.h b/src/s/hpux10.h
deleted file mode 100644
index 32daf200a21..00000000000
--- a/src/s/hpux10.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "hpux9shr.h"
-
-#define HPUX10
-
-/* We have to go this route, rather than hpux9's approach of renaming the
- functions via macros. The system's stdlib.h has fully prototyped
- declarations, which yields a conflicting definition of srand48; it
- tries to redeclare what was once srandom to be srand48. So we go
- with HAVE_LRAND48 being defined. */
-#undef srandom
-#undef srand48
-#undef HAVE_RANDOM
-#define HPUX10
-#define FORCE_ALLOCA_H
-
-/* AlainF 20-Jul-1996 says this is right. */
-#undef KERNEL_FILE
-#define KERNEL_FILE "/stand/vmunix"
-
-#ifdef LIBS_SYSTEM
-#undef LIBS_SYSTEM
-#endif
-#ifdef HPUX_NET
-#define LIBS_SYSTEM -ln -l:libdld.sl
-#else
-#define LIBS_SYSTEM -l:libdld.sl
-#endif
-
-/* Make sure we get select from libc rather than from libcurses
- because libcurses on HPUX 10.10 has a broken version of select. */
-#define LIBS_TERMCAP -lc -lcurses
-
-#undef C_SWITCH_X_SYSTEM
-#undef LD_SWITCH_X_DEFAULT
-/* However, HPUX 10 puts Xaw and Xmu in a strange place
- (if you install them at all). So search that place. */
-#define C_SWITCH_X_SYSTEM -I/usr/include/X11R5 -I/usr/include/Motif1.2 -I/usr/contrib/X11R5/include
-#define LD_SWITCH_X_DEFAULT -L/usr/lib/X11R5 -L/usr/lib/Motif1.2 -L/usr/contrib/X11R5/lib
diff --git a/src/s/hpux8.h b/src/s/hpux8.h
deleted file mode 100644
index 86a04f77aea..00000000000
--- a/src/s/hpux8.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* system description 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 "hpux.h"
-
-#define HPUX8
-
-/* dob@inel.gov says HPUX 8.07 needs this. He was using X11R5, I think. */
-#define LIBX11_SYSTEM -lXext
-
-#define LIB_X11_LIB -L/usr/lib/X11R5 -L/usr/lib/X11R4 -lX11
-#define C_SWITCH_X_SYSTEM -I/usr/include/X11R5 -I/usr/include/X11R4
-#define LD_SWITCH_X_DEFAULT -L/usr/lib/X11R5 -L/usr/lib/X11R4
-
-/* Don't use shared libraries. unexec doesn't handle them.
- Note GCC automatically passes -a archive to ld, and it has its own
- conflicting -a. */
-#ifdef __GNUC__
-/* No need to specify roundabout way of linking temacs. */
-#define ORDINARY_LINK
-
-#ifdef HPUX_USE_SHLIBS
-#define LD_SWITCH_SYSTEM
-#else
-#define LD_SWITCH_SYSTEM -Xlinker -a -Xlinker archive
-#endif
-
-#else /* not __GNUC__ */
-#if (defined(hp9000s700) || defined(__hp9000s700))
-#ifdef HPUX_USE_SHLIBS
-#define LD_SWITCH_SYSTEM -L/lib/pa1.1
-#else
-#define LD_SWITCH_SYSTEM -a archive -L/lib/pa1.1
-#endif
-#else /* not (defined(hp9000s700) || defined(__hp9000s700)) */
-#ifdef HPUX_USE_SHLIBS
-#define LD_SWITCH_SYSTEM
-#else
-#define LD_SWITCH_SYSTEM -a archive
-#endif
-#endif /* not (defined(hp9000s700) || defined(__hp9000s700)) */
-#endif /* not __GNUC__ */
-
-/* Some hpux 8 machines seem to have TIOCGWINSZ,
- and none have sioctl.h, so might as well define this. */
-#define NO_SIOCTL_H
-
-#if 0 /* autoconf should be detecting the presence or absence of
- random and srandom now. */
-/* If you use X11R4 you must define this. If you use
- X11R5 you must comment this out */
-/* #define HAVE_RANDOM */
-#define random foo_random
-#define srandom foo_srandom
-#endif
-
-#if 0 /* This seems to be spurious. */
-/* "X11R5" on hpux8 doesn't have this function, which is supposed to exist
- in X11R5. Maybe things will work if we just don't call it. */
-#define NO_XRM_SET_DATABASE
-#endif
-
-/* Enable a special hack in XTread_socket. */
-#define X_IO_BUG
diff --git a/src/s/hpux9-x11r4.h b/src/s/hpux9-x11r4.h
deleted file mode 100644
index 7d321162eae..00000000000
--- a/src/s/hpux9-x11r4.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* System description file for hpux version 9 using X11R4. */
-
-#include "hpux9.h"
-
-#undef C_SWITCH_X_SYSTEM
-#define C_SWITCH_X_SYSTEM -I/usr/include/Motif1.1
-
-#undef LD_SWITCH_X_DEFAULT
-#define LD_SWITCH_X_DEFAULT -L/usr/lib/Motif1.1
-
diff --git a/src/s/hpux9.h b/src/s/hpux9.h
deleted file mode 100644
index 93ba380460b..00000000000
--- a/src/s/hpux9.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* System description file for hpux version 9. */
-
-#include "hpux8.h"
-
-#define HPUX9
-
-/* If Emacs doesn't seem to work when built to use GNU malloc, you
- probably need to get the latest patches to the HP/UX compiler.
- See `etc/MACHINES' for more information. */
-#if 0
-#define SYSTEM_MALLOC 1
-#undef GNU_MALLOC
-#undef REL_ALLOC
-#endif
-
-#ifndef __GNUC__
-/* Make room for enough symbols, so dispnew.c does not fail. */
-#define C_SWITCH_SYSTEM -Wp,-H200000 -D_BSD
-#else
-#define C_SWITCH_SYSTEM -D_BSD
-#endif
-
-#if 0 /* These definitions run into a bug in hpux
- whereby trying to disable the vdsusp character has no effect.
- supposedly there is no particular need for this. */
-/* neal@ctd.comsat.com */
-#undef HAVE_TERMIO
-#define HAVE_TERMIOS
-#define NO_TERMIO
-#endif
-
-/* According to ngorelic@speclab.cr.usgs.gov,
- references to the X11R4 directories in these variables
- (inherited from hpux8.h)
- cause the wrong libraries to be found,
- and the options to specify the X11R5 directories are unnecessary
- since the R5 files are found without them. */
-#undef LIB_X11_LIB
-#undef C_SWITCH_X_SYSTEM
-#undef LD_SWITCH_X_DEFAULT
-/* However, HPUX 9 has Motif includes in a strange place.
- So search that place. These definitions assume that X11R5 is being
- used -- if X11R4 is used, "s/hpux9-x11r4.h" gets loaded instead. */
-/* horst@tkm.physik.uni-karlsruhe.de says that the /usr/contrib/... dirs
- are needed to find the Xmu and Xaw libraries. */
-#define C_SWITCH_X_SYSTEM -I/usr/include/X11R5 -I/usr/contrib/X11R5/include -I/usr/include/Motif1.2
-#define LD_SWITCH_X_DEFAULT -L/usr/lib/X11R5 -L/usr/contrib/X11R5/lib -L/usr/lib/Motif1.2
-
-#ifndef HAVE_LIBXMU
-/* HP-UX doesn't supply Xmu. */
-#define LIBXMU
-
-/* Unfortunately without libXmu we cannot support EditRes. */
-#define NO_EDITRES
-#endif
-
-/* zoo@armadillo.com says we don't need -lXext in HPUX 9. */
-#undef LIBX11_SYSTEM
diff --git a/src/s/hpux9shr.h b/src/s/hpux9shr.h
deleted file mode 100644
index 41ef98741c0..00000000000
--- a/src/s/hpux9shr.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#define ORDINARY_LINK
-#define HPUX_USE_SHLIBS
-#define RUN_TIME_REMAP
-
-#include "hpux9.h"
-
-#if 0 /* No longer needed, since in current GCC -g no longer does that. */
-/* We must turn off -g since it forces -static. */
-#ifdef __GNUC__
-#undef C_DEBUG_SWITCH
-#define C_DEBUG_SWITCH
-#endif
-#endif
diff --git a/src/s/iris3-5.h b/src/s/iris3-5.h
deleted file mode 100644
index c3d576cfde2..00000000000
--- a/src/s/iris3-5.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#define 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 "irix"
-
-/* 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_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 interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_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
-
-/* This is how to get the device name of the tty end of a pty. */
-#define PTY_TTY_NAME_SPRINTF \
- sprintf (ptyname, "/dev/ttyq%d", minor (stb.st_rdev));
diff --git a/src/s/iris3-6.h b/src/s/iris3-6.h
deleted file mode 100644
index 8b5d7495424..00000000000
--- a/src/s/iris3-6.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#define 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 "irix"
-
-/* 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_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 interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_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
-
-/* This is how to get the device name of the tty end of a pty. */
-#define PTY_TTY_NAME_SPRINTF \
- sprintf (ptyname, "/dev/ttyq%d", minor (stb.st_rdev));
-
-/* The C library does have the getwd function. */
-#define HAVE_GETWD
diff --git a/src/s/irix3-3.h b/src/s/irix3-3.h
deleted file mode 100644
index e41b05d7069..00000000000
--- a/src/s/irix3-3.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#define 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 "irix"
-
-/* 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_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. */
-
-#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 interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_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 */
-
-/* This is how to get the device name of the tty end of a pty. */
-#define PTY_TTY_NAME_SPRINTF \
- sprintf (ptyname, "/dev/ttyq%d", minor (stb.st_rdev));
-
-
-/* getwd is defined. */
-
-#define HAVE_GETWD
-
-#define HAVE_SYSVIPC
-
-/* sioctl.h should be included where appropriate. */
-
-#define NEED_SIOCTL
-
-/* This affects child_setup. */
-
-#define SETPGRP_RELEASES_CTTY
-
-/* This was formerly in LIBS_MACHINE in iris4d.h,
- but it is not needed for newer system versions. */
-#define LIBS_SYSTEM -lsun
diff --git a/src/s/irix4-0.h b/src/s/irix4-0.h
deleted file mode 100644
index 722cac19650..00000000000
--- a/src/s/irix4-0.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#include "irix3-3.h"
-
-#define USG5_3
-#define IRIX4
-
-#define HAVE_ALLOCA
-#ifndef NOT_C_CODE
-#include <alloca.h>
-#endif
-
-#undef NEED_SIOCTL
-
-/* Include unistd.h, even though we don't define POSIX. */
-#define NEED_UNISTD_H
-
-/* Make process_send_signal work by "typing" a signal character on the pty. */
-#define SIGNALS_VIA_CHARACTERS
-
-/* use K&R C */
-#ifndef __GNUC__
-#define C_SWITCH_MACHINE -cckr
-#endif
-
-/* 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. */
-#undef PTY_TTY_NAME_SPRINTF
-#define PTY_TTY_NAME_SPRINTF
-/* No need to get the pty name at all. */
-#define PTY_NAME_SPRINTF
-/* 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); \
-}
-
-/* jpff@maths.bath.ac.uk reports `struct exception' is not defined
- on this system, so inhibit use of matherr. */
-#define NO_MATHERR
diff --git a/src/s/irix5-0.h b/src/s/irix5-0.h
deleted file mode 100644
index 477f85756d4..00000000000
--- a/src/s/irix5-0.h
+++ /dev/null
@@ -1,129 +0,0 @@
-#include "usg5-4.h"
-
-#define IRIX5
-
-#undef sigsetmask /* use sys_sigsetmask */
-#undef _longjmp /* use system versions, not conservative aliases */
-#undef _setjmp
-
-#define SETPGRP_RELEASES_CTTY
-
-#ifdef LIBS_SYSTEM
-#undef LIBS_SYSTEM
-#endif
-
-#ifdef LIB_STANDARD
-#undef LIB_STANDARD
-#endif
-
-#ifdef SYSTEM_TYPE
-#undef SYSTEM_TYPE
-#endif
-#define SYSTEM_TYPE "irix"
-
-#ifdef SETUP_SLAVE_PTY
-#undef SETUP_SLAVE_PTY
-#endif
-
-/* thomas@mathematik.uni-bremen.de says this is needed. */
-/* Make process_send_signal work by "typing" a signal character on the pty. */
-#define SIGNALS_VIA_CHARACTERS
-
-/* 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
-
-#ifndef NOT_C_CODE
-#ifndef __GNUC__
-#include <alloca.h>
-#endif
-#endif
-
-/* 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. */
-#ifdef PTY_TTY_NAME_SPRINTF
-#undef PTY_TTY_NAME_SPRINTF
-#endif
-#define PTY_TTY_NAME_SPRINTF
-/* No need to get the pty name at all. */
-#ifdef PTY_NAME_SPRINTF
-#undef PTY_NAME_SPRINTF
-#endif
-#define PTY_NAME_SPRINTF
-#ifdef emacs
-char *_getpty();
-#endif
-/* We need only try once to open a pty. */
-#define PTY_ITERATION
-/* Here is how to do it. */
-#define PTY_OPEN \
-{ \
- struct sigaction ocstat, cstat; \
- char * name; \
- sigemptyset(&cstat.sa_mask); \
- cstat.sa_handler = SIG_DFL; \
- cstat.sa_flags = 0; \
- sigaction(SIGCLD, &cstat, &ocstat); \
- name = _getpty (&fd, O_RDWR | O_NDELAY, 0600, 0); \
- sigaction(SIGCLD, &ocstat, (struct sigaction *)0); \
- if (name == 0) \
- return -1; \
- if (fd < 0) \
- return -1; \
- if (fstat (fd, &stb) < 0) \
- return -1; \
- strcpy (pty_name, name); \
-}
-
-/* Since we use POSIX constructs in PTY_OPEN, we must force POSIX
- throughout. */
-#define POSIX_SIGNALS
-
-/* jpff@maths.bath.ac.uk reports `struct exception' is not defined
- on this system, so inhibit use of matherr. */
-#define NO_MATHERR
-
-/* Info from simon@lia.di.epfl.ch (Simon Leinen) suggests this is needed. */
-#define GETPGRP_NO_ARG
-
-/* Ulimit(UL_GMEMLIM) is busted... */
-#define ULIMIT_BREAK_VALUE 0x14000000
-
-/* Tell process_send_signal to use VSUSP instead of VSWTCH. */
-#define PREFER_VSUSP
-
-/* Because unexsgi.c cannot handle a ".sbss" section yet, we must
- tell the linker to avoid making one. SGI's cc does this by
- default, but GCC (at least 2.5.8 and 2.6.0) doesn't. */
-#ifdef __GNUC__
-#define LD_SWITCH_SYSTEM -G 0
-#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
-
-/* use K&R C */
-#ifndef __GNUC__
-#define C_SWITCH_SYSTEM -cckr
-#endif
-
-/* -g does not work on Irix, and since gcc warns if you use it,
- turn off the warning. */
-#ifdef __GNUC__
-#define C_DEBUG_SWITCH
-#endif
-
-/* Prevent the variable ospeed from being defined by -lcurses
- because it defines it with too few bytes. */
-#define ospeed ospeed_
diff --git a/src/s/irix5-2.h b/src/s/irix5-2.h
deleted file mode 100644
index 2ab6765c95b..00000000000
--- a/src/s/irix5-2.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "irix5-0.h"
-
-/* as of version 5.2, irix no longer uses flock,
- according to jackr@wpd.sgi.com. */
-#undef MAIL_USE_FLOCK
-
-/* C-g in select is not handled properly with restartable
- system calls. So don't use them. */
-#undef SA_RESTART
-
-/* schoepf@goofy.zdv.Uni-Mainz.de reports he needed -lw with X11R6
- on Irix 5.3. I don't know which Irix version that need starts with. */
-#define NEED_LIBW
diff --git a/src/s/irix6-0.h b/src/s/irix6-0.h
deleted file mode 100644
index be50494c6d7..00000000000
--- a/src/s/irix6-0.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "irix5-0.h"
-
-/* Irix 6 tries to do 64 bits, but doesn't do it fully,
- so inhibit that. */
-#define IRIX_FORCE_32_BITS
-
-#ifndef __GNUC__
-#define LD_SWITCH_SYSTEM -32
-#endif
-
-/* This macro definition, which we inherited from irix5-0.h,
- is needed in configure on Irix 5, but gets in the way there
- on Irix 6. So get rid of it except in Makefile.in where we need it. */
-#ifndef THIS_IS_MAKEFILE
-#undef C_SWITCH_SYSTEM
-#endif
-
-/* The only supported configuration of GCC under IRIX6.x produces
- n32 MIPS ABI binaries and also supports -g. */
-#ifdef __GNUC__
-#undef C_DEBUG_SWITCH
-#define C_DEBUG_SWITCH -g
-#endif
-
-#undef SA_RESTART
-
-/* Canced the #define that is in irix5-0.h. */
-#undef ospeed
diff --git a/src/s/isc2-2.h b/src/s/isc2-2.h
deleted file mode 100644
index f669fc2c141..00000000000
--- a/src/s/isc2-2.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* system description file for Interactive (ISC) Unix version 2.2 on
- the 386. */
-
-#include "usg5-3.h"
-
-/* select (in -linet) works okay on X ptys, but not on the serial port.
- karl@cs.umb.edu says that with that select call, subprocesses made by
- (e.g.) M-x grep don't exit cleanly, they just hang. Similar problems
- have been observed in ISC 3.0. */
-#define BROKEN_SELECT_NON_X
-
-/* karl@cs.umb.edu says that ISC's socket support (in -linet) isn't
- what Emacs needs; it makes interrupt-shell-subjob and the like do
- nothing. But that appears to have been another manifestation of
- the broken select, so it should now be safe to define this again. */
-#define HAVE_SOCKETS
-
-#define NO_SOCKETS_IN_FILE_SYSTEM
-#define NEED_NET_ERRNO_H
-
-/* This keeps the .cdbx section that gcc puts out when generating
- stabs-in-coff output, so Emacs can be debugged. --karl@cs.umb.edu. */
-#define USG_SHARED_LIBRARIES
-
-/* We can support lock files. */
-#define CLASH_DETECTION
-#define NO_FCHMOD
-
-#define HAVE_PTYS
-#define MAXNAMLEN 512
-#define O_NDELAY O_NONBLOCK
-#define MEMORY_IN_STRING_H
-
-/* Tell gmalloc.c that we don't have memmove (system include files to the
- contrary!). */
-#define MEMMOVE_MISSING
-
-/* Send a signal to a subprocess by "typing" a signal character. */
-#define SIGNALS_VIA_CHARACTERS
-
-/* -lPW is only needed if not using Gcc. We used to include -lcposix here
- for the rename function, but some people say ISC's rename doesn't
- work correctly with Emacs so we use Emacs' emulation instead. */
-#if defined (__GNUC__)
-# define LIB_STANDARD_1 -lcposix
-#else /* !__GNUC__ */
-# define LIB_STANDARD_1 -lPW
-#endif /* !__GNUC__ */
-
-/* LIB_STANDARD_1 is used both here and in LIBS_SYSTEM
- (the latter for the sake of configure). */
-#define LIB_STANDARD LIB_STANDARD_1 -lc
-
-#define NO_X_DESTROY_DATABASE
-
-/* -linet may be needed to avoid undefined symbols such as gethostname,
- inet_addr, gethostbyname, socket, connect, ... */
-#define LIBS_SYSTEM -linet LIB_STANDARD_1
-
-/* This system has job control. */
-#undef NOMULTIPLEJOBS
-
-/* Inhibit asm code in netinet/in.h. Strictly speaking, only necessary
- when -traditional is being used, but it doesn't hurt to
- unconditionally define this. */
-#define NO_ASM
-
-/* -traditional is not necessary if the system header files are fixed to
- define getc and putc in the absence of _POSIX_SOURCE. GCC's from 2.4.4
- on do this. */
-#if !defined (__GNUC__) || __GNUC__ < 2
-# define C_SWITCH_SYSTEM -traditional
-#endif
-
-/* Some versions of ISC are said to define S_IFLNK even tho
- they don't really support symlinks. */
-#undef S_IFLNK
diff --git a/src/s/isc3-0.h b/src/s/isc3-0.h
deleted file mode 100644
index 737ce3c3297..00000000000
--- a/src/s/isc3-0.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* s- file for Interactive (ISC) Unix version 3.0 on the 386. */
-
-#include "isc2-2.h"
-
-/* This has been moved into isc2-2.h. */
-/* #define HAVE_SOCKETS */
-
-/* This appears on 3.0, presumably as part of what SunSoft call X2. */
-#undef NO_X_DESTROY_DATABASE
-
-#ifdef __GNUC__ /* Currently we use -lcposix only with gcc */
-#define POSIX_SIGNALS
-
-/* We don't need the definition from usg5-3.h with POSIX_SIGNALS. */
-#undef sigsetmask
-#undef HAVE_SYSV_SIGPAUSE
-#endif
-
-/* People say that using -traditional causes lossage with `const',
- so we might as well try getting rid of -traditional. */
-#undef C_SWITCH_SYSTEM
-
-/* We indirectly #include s/usg5-3.h, which says to use libX11_s and
- libc_s. Martin Tomes <mt00@controls.eurotherm.co.uk> says that ISC
- has no libX11_s, and that linking with libc_s causes sbrk not to work. */
-#undef LIB_X11_LIB
-#undef LIBX11_SYSTEM
-#define LIBX11_SYSTEM -lpt -lnls -lnsl_s
-
-/* TIOCGWINSZ isn't broken; you just have to know where to find it. */
-#undef BROKEN_TIOCGWINSZ
-#define NEED_SIOCTL
-
-/* We need either _XOPEN_SOURCE or _POSIX_SOURCE to import the posix
- signal symbols; might as well use _XOPEN_SOURCE. Defining _SYSV3
- ensures that we don't lose the traditional symbols as a side effect
- from this or __STDC__ being defined. */
-#define C_SWITCH_SYSTEM -D_XOPEN_SOURCE -D_SYSV3
-
-#ifdef __GNUC__ /* Currently we use -lcposix only with gcc */
-/* This works around a bug in ISC 4.0 and 3.0; it fails
- to clear the "POSIX process" flag on an exec.
- It won't be needed for 4.1. */
-#define EXTRA_INITIALIZE __setostype (0)
-#endif
diff --git a/src/s/isc4-0.h b/src/s/isc4-0.h
deleted file mode 100644
index 14eb692ba13..00000000000
--- a/src/s/isc4-0.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#include "isc3-0.h"
-
-#undef LIBS_SYSTEM
-#define LIBS_SYSTEM -linet -lcposix
-
-#define ISC4_0
-
-/* fmcphers@csugrad.cs.vt.edu reported this was necessary.
- He used GCC. I don't know what is needed with other compilers. */
-#ifdef __GNUC__
-#undef LIBX11_SYSTEM
-#define LIBX11_SYSTEM -lpt -lnls -lnsl_s -lcposix -lc
-#endif
-
-/* Tobias Herbert <herbert@clipper.ikp.physik.th-darmstadt.de>
- says this is needed. */
-
-#ifndef POSIX_SIGNALS
-#ifndef sigblock
-#ifndef SIG_BLOCK
-#define SIG_BLOCK 0
-#endif
-#define sigblock(sig) (sigprocmask (SIG_BLOCK, SIGEMPTYMASK | sig, NULL))
-#endif
-#endif /* not POSIX_SIGNALS */
diff --git a/src/s/isc4-1.h b/src/s/isc4-1.h
deleted file mode 100644
index dcb66b742b4..00000000000
--- a/src/s/isc4-1.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#include "isc3-0.h"
-
-/* ISC 4.1 has renamed __setostype, but also has fixed the bug
- for which we needed to call it; so just do nothing. uddeborg@carmen.se. */
-#undef EXTRA_INITIALIZE
-
-#define ISC4_1
-
-#undef LIBS_SYSTEM
-#define LIBS_SYSTEM -linet
-
-/* uddeborg@carmen.se recommends the rest of this file. */
-
-/* A special startup file is used when compiling with Posix. */
-#define START_FILES pre-crt0.o /lib/crtp1.o
-
-/* -lPW is only needed if not using Gcc. */
-#undef LIB_STANDARD
-#if defined (__GNUC__)
-# define LIB_STANDARD -lcposix -lc /lib/crtn.o
-#else /* !__GNUC__ */
-# define LIB_STANDARD -lPW -lcposix -lc /lib/crtn.o
-#endif /* !__GNUC__ */
-
-/* We have Posix termios. */
-#define HAVE_TERMIOS
-/* According to template.h HAVE_TERMIO and HAVE_TERMIOS shouldn't be */
-/* defined at the same time. */
-#undef HAVE_TERMIO
diff --git a/src/s/mach-bsd4-3.h b/src/s/mach-bsd4-3.h
deleted file mode 100644
index df4640b3fc5..00000000000
--- a/src/s/mach-bsd4-3.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/* I don't care if this doesn't do more than including bsd4-3.h;
- Mach is not bsd4-3 and the moment you forget it chances are that
- you're in deep shit. */
-
-#include "bsd4-3.h"
diff --git a/src/s/ms-w32.h b/src/s/ms-w32.h
deleted file mode 100644
index 041da1f5a16..00000000000
--- a/src/s/ms-w32.h
+++ /dev/null
@@ -1,374 +0,0 @@
-/* System description file for Windows NT.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-/* #define UNIPLUS */
-/* #define USG5 */
-/* #define USG */
-/* #define HPUX */
-/* #define UMAX */
-/* #define BSD4_1 */
-/* #define BSD4_2 */
-/* #define BSD4_3 */
-/* #define BSD_SYSTEM */
-/* #define VMS */
-#ifndef WINDOWSNT
-#define WINDOWSNT
-#endif
-#ifndef DOS_NT
-#define DOS_NT /* MSDOS or WINDOWSNT */
-#endif
-
-/* If you are compiling with a non-C calling convention but need to
- declare vararg routines differently, put it here */
-#define _VARARGS_ __cdecl
-
-/* If you are providing a function to something that will call the
- function back (like a signal handler and signal, or main) its calling
- convention must be whatever standard the libraries expect */
-#define _CALLBACK_ __cdecl
-
-/* SYSTEM_TYPE should indicate the kind of system you are using.
- It sets the Lisp variable system-type. */
-
-#define SYSTEM_TYPE "windows-nt"
-#define SYMS_SYSTEM syms_of_ntterm ()
-
-#define NO_MATHERR
-
-/* NOMULTIPLEJOBS should be defined if your system's shell
- does not have "job control" (the ability to stop a program,
- run some other program, then continue the first one). */
-
-/* #define NOMULTIPLEJOBS */
-
-/* Emacs can read input using SIGIO and buffering characters itself,
- or using CBREAK mode and making C-g cause SIGINT.
- The choice is controlled by the variable interrupt_input.
-
- Define INTERRUPT_INPUT to make interrupt_input = 1 the default (use SIGIO)
-
- Emacs uses the presence or absence of the SIGIO macro to indicate
- whether or not signal-driven I/O is possible. It uses
- INTERRUPT_INPUT to decide whether to use it by default.
-
- SIGIO can be used only on systems that implement it (4.2 and 4.3).
- CBREAK mode has two disadvantages
- 1) At least in 4.2, it is impossible to handle the Meta key properly.
- I hear that in system V this problem does not exist.
- 2) Control-G causes output to be discarded.
- I do not know whether this can be fixed in system V.
-
- Another method of doing input is planned but not implemented.
- It would have Emacs fork off a separate process
- to read the input and send it to the true Emacs process
- through a pipe. */
-
-#define INTERRUPT_INPUT
-
-/* Letter to use in finding device name of first pty,
- if system supports pty's. 'a' means it is /dev/ptya0 */
-
-#define FIRST_PTY_LETTER 'a'
-
-/*
- * Define HAVE_TERMIOS if the system provides POSIX-style
- * functions and macros for terminal control.
- *
- * Define HAVE_TERMIO if the system provides sysV-style ioctls
- * for terminal control.
- *
- * Do not define both. HAVE_TERMIOS is preferred, if it is
- * supported on your system.
- */
-
-/* #define HAVE_TERMIOS */
-/* #define HAVE_TERMIO */
-
-/*
- * Define 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 */
-
-/* NT supports Winsock which is close enough (with some hacks) */
-
-#define HAVE_SOCKETS
-
-/* Define this symbol if your system has the functions bcopy, etc. */
-
-#define BSTRING
-#define bzero(b, l) memset(b, 0, l)
-#define bcopy(s, d, l) memcpy(d, s, l)
-#define bcmp(a, b, l) memcmp(a, b, l)
-
-/* 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 MAIL_USE_POP
-#define MAIL_USE_SYSTEM_LOCK
-
-/* Define CLASH_DETECTION if you want lock files to be written
- so that Emacs can tell instantly when you try to modify
- a file that someone else has modified in his Emacs. */
-
-/* #define CLASH_DETECTION */
-
-/* Define this if your operating system declares signal handlers to
- have a type other than the usual. `The usual' is `void' for ANSI C
- systems (i.e. when the __STDC__ macro is defined), and `int' for
- pre-ANSI systems. If you're using GCC on an older system, __STDC__
- will be defined, but the system's include files will still say that
- signal returns int or whatever; in situations like that, define
- this to be what the system's include files want. */
-/* #define SIGTYPE int */
-
-/* If the character used to separate elements of the executable path
- is not ':', #define this to be the appropriate character constant. */
-#define SEPCHAR ';'
-
-/* ============================================================ */
-
-/* Here, add any special hacks needed
- to make Emacs work on this system. For example,
- you might define certain system call names that don't
- exist on your system, or that do different things on
- your system and must be used only through an encapsulation
- (Which you should place, by convention, in sysdep.c). */
-
-/* Define this to be the separator between path elements */
-#define DIRECTORY_SEP XINT (Vdirectory_sep_char)
-
-/* Define this to be the separator between devices and paths */
-#define DEVICE_SEP ':'
-
-/* We'll support either convention on NT. */
-#define IS_DIRECTORY_SEP(_c_) ((_c_) == '/' || (_c_) == '\\')
-#define IS_ANY_SEP(_c_) (IS_DIRECTORY_SEP (_c_) || IS_DEVICE_SEP (_c_))
-
-/* The null device on Windows NT. */
-#define NULL_DEVICE "NUL:"
-#define EXEC_SUFFIXES ".exe:.com:.bat:.cmd:"
-
-#ifndef MAXPATHLEN
-#define MAXPATHLEN _MAX_PATH
-#endif
-
-#define LISP_FLOAT_TYPE
-
-#define HAVE_SYS_TIMEB_H
-#define HAVE_SYS_TIME_H
-#define HAVE_UNISTD_H
-#define STDC_HEADERS
-#define TIME_WITH_SYS_TIME
-
-#define HAVE_GETTIMEOFDAY
-#define HAVE_GETHOSTNAME
-#define HAVE_DUP2
-#define HAVE_RENAME
-#define HAVE_CLOSEDIR
-
-#define HAVE_TZNAME
-
-#define HAVE_LONG_FILE_NAMES
-
-#define HAVE_MKDIR
-#define HAVE_RMDIR
-#define HAVE_RANDOM
-#define HAVE_BCOPY
-#define HAVE_BCMP
-#define HAVE_LOGB
-#define HAVE_FREXP
-#define HAVE_FMOD
-#define HAVE_FTIME
-#define HAVE_MKTIME
-
-#define HAVE_MOUSE
-#define HAVE_H_ERRNO
-
-#ifdef HAVE_NTGUI
-#define HAVE_WINDOW_SYSTEM
-#define HAVE_FACES
-#endif
-
-#define MODE_LINE_BINARY_TEXT(_b_) (NILP ((_b_)->buffer_file_type) ? "T" : "B")
-
-/* get some redefinitions in place */
-
-/* IO calls that are emulated or shadowed */
-#define access sys_access
-#define chdir sys_chdir
-#define chmod sys_chmod
-#define close sys_close
-#define creat sys_creat
-#define ctime sys_ctime
-#define dup sys_dup
-#define dup2 sys_dup2
-#define fopen sys_fopen
-#define link sys_link
-#define mkdir sys_mkdir
-#define mktemp sys_mktemp
-#define open sys_open
-#define pipe sys_pipe
-#define read sys_read
-#define rename sys_rename
-#define rmdir sys_rmdir
-#define select sys_select
-#define sleep sys_sleep
-#define unlink sys_unlink
-#define write sys_write
-
-/* this is hacky, but is necessary to avoid warnings about macro
- redefinitions using the SDK compilers */
-#ifndef __STDC__
-#define __STDC__ 1
-#define MUST_UNDEF__STDC__
-#endif
-#include <direct.h>
-#include <io.h>
-#include <stdio.h>
-#ifdef MUST_UNDEF__STDC__
-#undef __STDC__
-#undef MUST_UNDEF__STDC__
-#endif
-
-/* subprocess calls that are emulated */
-#define spawnve sys_spawnve
-#define wait sys_wait
-#define kill sys_kill
-#define signal sys_signal
-
-/* map to MSVC names */
-#define execlp _execlp
-#define execvp _execvp
-#define fcloseall _fcloseall
-#define fdopen _fdopen
-#define fgetchar _fgetchar
-#define fileno _fileno
-#define flushall _flushall
-#define fputchar _fputchar
-#define getw _getw
-#define getpid _getpid
-#define isatty _isatty
-#define logb _logb
-#define _longjmp longjmp
-#define lseek _lseek
-#define popen _popen
-#define pclose _pclose
-#define putw _putw
-#define umask _umask
-#define utime _utime
-#define index strchr
-#define rindex strrchr
-
-#ifdef HAVE_NTGUI
-#define abort w32_abort
-#endif
-
-/* Defines that we need that aren't in the standard signal.h */
-#define SIGHUP 1 /* Hang up */
-#define SIGQUIT 3 /* Quit process */
-#define SIGTRAP 5 /* Trace trap */
-#define SIGKILL 9 /* Die, die die */
-#define SIGPIPE 13 /* Write on pipe with no readers */
-#define SIGALRM 14 /* Alarm */
-#define SIGCHLD 18 /* Death of child */
-
-/* For integration with MSDOS support. */
-#define getdisk() (_getdrive () - 1)
-#define getdefdir(_drv, _buf) _getdcwd (_drv, _buf, MAXPATHLEN)
-
-#define EMACS_CONFIGURATION get_emacs_configuration ()
-#define EMACS_CONFIG_OPTIONS "NT" /* Not very meaningful yet. */
-
-/* Define this so that winsock.h definitions don't get included with
- windows.h. For this to have proper effect, config.h must always be
- included before windows.h. */
-#define _WINSOCKAPI_ 1
-
-/* Defines size_t and alloca (). */
-#include <malloc.h>
-
-#include <sys/stat.h>
-
-/* Define for those source files that do not include enough NT
- system files. */
-#ifndef NULL
-#ifdef __cplusplus
-#define NULL 0
-#else
-#define NULL ((void *)0)
-#endif
-#endif
-
-/* For proper declaration of environ. */
-#include <stdlib.h>
-#include <string.h>
-
-/* Emacs takes care of ensuring that these are defined. */
-#ifdef max
-#undef max
-#undef min
-#endif
-
-/* We need a little extra space, see ../../lisp/loadup.el */
-#define SYSTEM_PURESIZE_EXTRA 15000
-
-/* ============================================================ */
diff --git a/src/s/msdos.h b/src/s/msdos.h
deleted file mode 100644
index 8d4e70a91bf..00000000000
--- a/src/s/msdos.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/* System description file for MS-DOS
-
- Copyright (C) 1993, 1996 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Note: lots of stuff here was taken from s-msdos.h in demacs. */
-
-
-/*
- * 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_SYSTEM */
-/* #define VMS */
-#ifndef MSDOS
-#define MSDOS
-#endif
-
-#ifdef __GO32__
-#ifndef __DJGPP__
-#define __DJGPP__ 1 /* V2 defines __DJGPP__ == 2 */
-#endif
-#else
-You lose; /* Emacs for DOS must be compiled with DJGPP */
-#endif
-
-#define DOS_NT /* MSDOS or WINDOWSNT */
-#undef BSD_SYSTEM
-#undef VMS
-
-/* SYSTEM_TYPE should indicate the kind of system you are using.
- It sets the Lisp variable system-type. */
-
-#define SYSTEM_TYPE "ms-dos"
-
-#define SYMS_SYSTEM syms_of_dosfns();syms_of_msdos()
-
-/* 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 disadvantages
- 1) At least in 4.2, it is impossible to handle the Meta key properly.
- I hear that in system V this problem does not exist.
- 2) Control-G causes output to be discarded.
- I do not know whether this can be fixed in system V.
-
- Another method of doing input is planned but not implemented.
- It would have Emacs fork off a separate process
- to read the input and send it to the true Emacs process
- through a pipe.
-*/
-
-/* #define INTERRUPT_INPUT */
-
-/* Letter to use in finding device name of first pty,
- if system supports pty's. 'a' means it is /dev/ptya0 */
-
-/* #define FIRST_PTY_LETTER 'a' */
-
-/*
- * 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 SYSV_SYSTEM_DIR
-
-/* Define this symbol if your system has the functions bcopy, etc. */
-
-#define BSTRING
-
-/* Define this is the compiler understands `volatile'. */
-#define HAVE_VOLATILE
-
-
-/* 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. */
-
-#undef 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). */
-
-/* Avoid incompatibilities between gmalloc.c and system header files
- in how to declare valloc. */
-#define GMALLOC_INHIBIT_VALLOC
-
-/* setjmp and longjmp can safely replace _setjmp and _longjmp,
- but they will run slower. */
-
-#define _setjmp setjmp
-#define _longjmp longjmp
-
-#if __DJGPP__ < 2
-
-#define NO_MODE_T
-
-/* New chdir () routine.
- DJGPP v2.0 and later doesn't need it because its chdir() does
- set the drive itself. */
-#ifdef chdir
-#undef chdir
-#endif
-#define chdir sys_chdir
-
-#define LIBS_SYSTEM -lpc /* isn't required in DJGPP v2.0, either */
-
-#endif /* __DJGPP__ < 2 */
-
-#if __DJGPP__ > 1
-
-#define DATA_START (&etext + 1)
-#define TEXT_START &start
-#define TEXT_END &etext
-
-#define _NAIVE_DOS_REGS
-
-#else /* not __DJGPP__ > 1 */
-
-/* This somehow needs to be defined even though we use COFF. */
-#define TEXT_START -1
-
-#endif /* not __DJGPP__ > 1 */
-
-#define ORDINARY_LINK
-
-/* command.com does not understand `...` so we define this. */
-#define LIB_GCC -Lgcc
-#define DONT_NEED_ENVIRON
-#define SEPCHAR ';'
-
-#define NULL_DEVICE "nul"
-#define EXEC_SUFFIXES ".exe:.com:.bat:"
-
-#if __DJGPP__ < 2
-#define O_RDONLY 0x0001
-#define O_WRONLY 0x0002
-#define O_RDWR 0x0004
-#define O_CREAT 0x0100
-#define O_TRUNC 0x0200
-#define O_EXCL 0x0400
-#define O_APPEND 0x0800
-#define O_TEXT 0x4000
-#define O_BINARY 0x8000
-#define NO_MATHERR
-#endif
-
-#define HAVE_INVERSE_HYPERBOLIC
-#define FLOAT_CHECK_DOMAIN
-
-/* When $TERM is "internal" then this is substituted: */
-#define INTERNAL_TERMINAL "pc|bios|IBM PC with colour display:\
-:co#80:li#25:km:ms:cm=<CM>:cl=<CL>:ce=<CE>:"
-
-/* Define this to a function (Fdowncase, Fupcase) if your file system
- likes that */
-#define FILE_SYSTEM_CASE Fmsdos_downcase_filename
-
-/* Define this to be the separator between devices and paths */
-#define DEVICE_SEP ':'
-
-/* We'll support either convention on MSDOG. */
-#define IS_DIRECTORY_SEP(_c_) ((_c_) == '/' || (_c_) == '\\')
-#define IS_ANY_SEP(_c_) (IS_DIRECTORY_SEP (_c_) || IS_DEVICE_SEP (_c_))
-
-/* Call init_gettimeofday when TZ changes. */
-#if __DJGPP__ < 2
-#define LOCALTIME_CACHE
-#define tzset init_gettimeofday
-#endif
-
-/* bcopy under djgpp is quite safe */
-#define GAP_USE_BCOPY
-#define BCOPY_UPWARD_SAFE 1
-#define BCOPY_DOWNWARD_SAFE 1
-
-/* Mode line description of a buffer's type. */
-#define MODE_LINE_BINARY_TEXT(buf) (NILP(buf->buffer_file_type) ? "T" : "B")
-
-/* Do we have POSIX signals? */
-#if __DJGPP__ > 1
-#define POSIX_SIGNALS
-#endif
-
-/* We have (the code to control) a mouse. */
-#define HAVE_MOUSE
-
-/* We canuse mouse menus. */
-#define HAVE_MENUS
-
-/* We have support for faces. */
-#define HAVE_FACES
-
-/* Define one of these for easier conditionals. */
-#ifdef HAVE_X_WINDOWS
-/* We need a little extra space, see ../../lisp/loadup.el */
-#define SYSTEM_PURESIZE_EXTRA 15000
-#define HAVE_X11R5
-#define LIBX11_SYSTEM -lxext -lsys
-#else
-/* We need a little extra space, see ../../lisp/loadup.el */
-#define SYSTEM_PURESIZE_EXTRA 85000
-#endif
diff --git a/src/s/netbsd.h b/src/s/netbsd.h
deleted file mode 100644
index b6535665724..00000000000
--- a/src/s/netbsd.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* s/ file for netbsd system. */
-
-/* Get most of the stuff from bsd4.3 */
-#include "bsd4-3.h"
-
-/* For mem-limits.h. */
-#define BSD4_2
-
-#undef KERNEL_FILE
-#undef LDAV_SYMBOL
-#define HAVE_GETLOADAVG
-
-#define HAVE_UNION_WAIT
-
-#define SIGNALS_VIA_CHARACTERS
-
-#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_p - (FILE)->_bf._base)
-
-/* netbsd uses OXTABS instead of the expected TAB3. */
-#define TABDLY OXTABS
-#define TAB3 OXTABS
-
-#define A_TEXT_OFFSET(x) (sizeof (struct exec))
-#define A_TEXT_SEEK(hdr) (N_TXTOFF(hdr) + A_TEXT_OFFSET(hdr))
-
-#define HAVE_TERMIOS
-#define NO_TERMIO
-
-#define LIBS_DEBUG
-/* -lutil is not needed for NetBSD >0.9. */
-/* #define LIBS_SYSTEM -lutil */
-#define LIBS_TERMCAP -ltermcap
-
-#define NEED_ERRNO
-#define SYSV_SYSTEM_DIR
-
-/* Netbsd has POSIX-style pgrp behavior. */
-#undef BSD_PGRPS
-
-#define GETPGRP_NO_ARG
-
-#ifndef NO_SHARED_LIBS
-/* These definitions should work for either dynamic or static linking,
- whichever is the default for `cc -nostdlib'. */
-#define HAVE_TEXT_START /* No need to define `start_of_text'. */
-#define START_FILES pre-crt0.o /usr/lib/crt0.o
-#define UNEXEC unexsunos4.o
-#define RUN_TIME_REMAP
-
-/* Try to make this work for both 0.9 and >0.9. */
-#ifndef N_TRELOFF
-#define N_PAGSIZ(x) __LDPGSZ
-#define N_BSSADDR(x) (N_ALIGN(x, N_DATADDR(x)+x.a_data))
-#define N_TRELOFF(x) N_RELOFF(x)
-#endif
-#endif /* not NO_SHARED_LIBS */
-
-#define HAVE_WAIT_HEADER
-#define WAIT_USE_INT
-
-#define NO_MATHERR
-
-#define AMPERSAND_FULL_NAME
diff --git a/src/s/newsos5.h b/src/s/newsos5.h
deleted file mode 100644
index 7c782a40cd4..00000000000
--- a/src/s/newsos5.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Definitions file for GNU Emacs running on Sony's NEWS-OS 5.0.2
- Copyright (C) 1992, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Use the SysVr4 file for at least base configuration. */
-
-#include "usg5-4.h"
-
-#define NEWSOS5
-
-/* These will be defined by "m-mips.h". */
-#undef START_FILES
-#undef LIB_STANDARD
-
-#undef LIBS_SYSTEM
-#define LIBS_SYSTEM -lsocket -lnsl -lgen
-
-/* Disable use of "unexelf.c" and shared libraries, because
- "unexelf.c" doesn't work correctly on NEWS-OS. "unexmips.c" does
- work correctly if the program is linked statically without ELF. */
-#undef UNEXEC
-#undef USG_SHARED_LIBRARIES
-
-/* Use `ld' directly rather than ordinary link, because ordinary link
- can't produce a non-ELF executable. */
-#undef ORDINARY_LINK
-#define LINKER /usr/lib/cmplrs/cc/ld
-#define START_FILES pre-crt0.o /usr/ccs/lib/crt1.o
-#define LIB_STANDARD -lc /usr/ccs/lib/crtn.o /usr/ccs/lib/values-Xt.o
-
-#ifndef HAVE_SOCKETS
-#define HAVE_SOCKETS
-#endif
diff --git a/src/s/nextstep.h b/src/s/nextstep.h
deleted file mode 100644
index 893d62ba7a7..00000000000
--- a/src/s/nextstep.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Configuration file for the NeXTstep system.
- Copyright (C) 1990, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include "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"
-
-#ifndef NeXT
-#define NeXT
-#endif
-
-
-/* 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)
-
-/* Defining KERNEL_FILE causes lossage because sys/file.h
- stupidly gets confused by it. */
-#undef KERNEL_FILE
-
-#define HAVE_ALLOCA
-
-#define SYSTEM_MALLOC
-
-#define environ _environ
-
-/* This should be true for recent NeXT systems. At least since 3.2. */
-#define HAVE_MACH_MACH_H
-
-/* mktime wrongly ignores TZ. */
-#define BROKEN_MKTIME 1
-
-#if 0 /* I think these are never used--let's see. -- rms. */
-/* Mask for address bits within a memory segment */
-
-#define SEGSIZ 0x20000
-#define SEGMENT_MASK (SEGSIZ - 1)
-
-#define HAVE_UNIX_DOMAIN
-
-/* Conflicts in process.c between ioctl.h & tty.h use of t_foo fields */
-
-#define NO_T_CHARS_DEFINES
-
-/* This avoids a problem in Xos.h when using co-Xist 3.01. */
-#define X_NOT_POSIX
-#endif /* 0 */
-
-/* Definitions for how to link. */
-
-/* Link this program just by running cc. */
-#define ORDINARY_LINK
-
-#define LD_SWITCH_SYSTEM -X
-
-/* Don't use -lc on the NeXT. */
-#ifdef NS_TARGET /* We use the dynamic libraries under Openstep for Mach 4.0 */
-#define LIB_STANDARD
-#else
-#define LIB_STANDARD -lsys_s
-#endif
-
-#define LIB_MATH -lm
-
-#define START_FILES pre-crt0.o
-
-#define LIB_X11_LIB -L/usr/lib/X11 -lX11
-
-/* 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
-
-/* Definitions for how to dump. */
-
-#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 ()
diff --git a/src/s/osf1.h b/src/s/osf1.h
deleted file mode 100644
index 9503fb2ff53..00000000000
--- a/src/s/osf1.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "bsd4-3.h"
-
-/* Identify OSF1 for the m- files. */
-
-#define OSF1
-
-/* Define _BSD to tell the include files we're running under
- the BSD universe and not the SYSV universe. */
-
-#define C_SWITCH_SYSTEM -D_BSD
-#define LIBS_SYSTEM -lbsd
-
-#define GETPGRP_NO_ARG
-
-#define read sys_read
-#define write sys_write
-#define open sys_open
-#define close sys_close
-
-#define INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_CLOSE
-#define INTERRUPTIBLE_IO
-
-#define SYSV_SYSTEM_DIR
-
-/* If your system uses COFF (Common Object File Format) then define the
- preprocessor symbol "COFF". */
-
-#define COFF
-
-/* Here is how to find X Windows. LD_SWITCH_X_SITE_AUX gives an -R option
- says where to find X windows at run time. We convert it to a -rpath option
- which is what OSF1 uses. */
-#define LD_SWITCH_SYSTEM `echo LD_SWITCH_X_SITE_AUX | sed -e 's/-R/-Wl,-rpath,/'`
diff --git a/src/s/ptx.h b/src/s/ptx.h
deleted file mode 100644
index d9d223d1cc5..00000000000
--- a/src/s/ptx.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/* Definitions file for GNU Emacs running on Sequent DYNIX/ptx 1.x/2.x
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* This file was written by Bill Burton <billb@progress.com>. Parts were
- adapted from m-ptx1-2.h and process.c as distributed with the Emacs 18.57
- on the Sequent Public software tape. Other parts were adapted from
- usg5-4.h. */
-
-/* Use the SysVr3 file for base configuration even though much is changed. */
-#include "usg5-3.h"
-
-/* Undo these defines because they are incorrect or need to be changed. */
-#undef LIB_X11_LIB
-#undef LIBX10_SYSTEM
-#undef LIBX11_SYSTEM
-#undef USG_SHARED_LIBRARIES
-
-/* <sys/stat.h> *defines* stat as a static function. If "static"
- is blank, then many files will have a public definition for stat. */
-#undef static
-
-/* PTX supports job control. */
-#undef NOMULTIPLEJOBS
-
-/* PTX has System V streams. */
-#define SYSV_STREAMS
-
-/* Leave out -lPW since it conflicts with term.o and because we're not sure
- if the alloca found there by autoconf should be trusted on PTX. */
-#define LIB_STANDARD -lc
-
-/* Local define. If TCP/IP is not installed, comment this out. */
-#define TCPIP_INSTALLED
-
-#ifdef TCPIP_INSTALLED
-#define HAVE_SOCKETS
-#else
-#undef subprocesses
-#endif
-
-#ifdef HAVE_X_WINDOWS
-
-#define LIBX11_SYSTEM -lsocket -linet -lnsl
-/* This is also defined so that lib-src/profile can link. */
-#define LIBS_SYSTEM -lseq
-
-#else /* ! HAVE_X_WINDOWS */
-
-#ifdef HAVE_SOCKETS
-#define LIBS_SYSTEM -lsocket -linet -lnsl -lseq
-#else
-#define LIBS_SYSTEM -lseq
-#endif
-
-#endif /* ! HAVE_X_WINDOWS */
-
-/* No <sioctl.h> */
-#define NO_SIOCTL_H
-
-/* If we have X windows, configure should find gettimeofday in -lX11.
- Since we emulate gettimeofday below, we really have it anyway. */
-#ifndef HAVE_GETTIMEOFDAY
-#define HAVE_GETTIMEOFDAY
-#endif
-
-#ifdef emacs
-#include <sys/stropts.h> /* Support for pty's */
-#include <sys/conf.h>
-
-/*#undef SIGIO*/ /* SIGIO is already undef'd elsewhere. PTX
- has SIGIO, but it's just an alias for
- SIGPOLL. */
-
-/* Emulate gettimeofday() except for the time zone information which Emacs
- doesn't use anyway. Get_process_stats() is in -lseq. */
-#include <sys/procstats.h>
-#define gettimeofday(tp, tzp) get_process_stats (tp, PS_SELF, 0, 0)
-
-/* Define timezone since it's not in sys/time.h. Unfortunately, this causes
- trouble when building with X since this struct is defined in
- <X11/Xos.h>. */
-struct timezone
-{
- int tz_minuteswest;
- int tz_dsttime;
-};
-
-/* Unfortunately, this define is not checked in all files including
- <X11/Xos.h> so we can't use it. */
-/* #define XOS_NEEDS_TIME_H */
-
-/* In ptx/WINDOWS, this prevents problems with the timezone struct being
- redefined in <X11/Xos.h>. It seems the necessary include files are
- included via systime.h so leaving them out here is not a problem. This
- may not work in X11R5 or X11R6. */
-#define __TIMEVAL__
-
-#endif /* emacs */
-
-/* PTX doesn't have FIONREAD at all. */
-#undef INTERRUPT_INPUT
-#define BROKEN_FIONREAD
-
-/* We can support this */
-#define CLASH_DETECTION
-
-/* PTX has termios */
-#define HAVE_TERMIOS
-#undef HAVE_TERMIO
-#undef BROKEN_TIOCGWINSZ
-#undef BROKEN_TIOCGETC
-
-/* It is possible to receive SIGCHLD when there are no children
- waiting, because a previous waitsys cleaned up the carcass of child
- without clearing the SIGCHLD pending info. So, use a non-blocking
- wait3 instead, which maps to waitpid in SysVr4. */
-/* Not sure if this is used but PTX does support waitpid. */
-/*#define HAVE_WAIT_HEADER*/
-/*#define WAITTYPE int*/
-#define wait3(status, options, rusage) \
- waitpid ((pid_t) -1, (status), (options))
-/*#define WRETCODE(w) (w >> 8)*/
-
-/* PTX has pty's but not like System V */
-#define HAVE_PTYS
-#undef SYSV_PTYS
-
-/* Provide pty support which is defined into process.c:allocate_pty.
- Basic ideas for handling getpseudotty were lifted from process.c in
- Emacs 18.57 included on the Sequent Public Software tape. However, this
- implementation bears almost no resemblance to the original and does not
- require that process.c be patched. */
-#define PTY_ITERATION \
- char *mastername, *slavename; \
- while (1)
-
-#define PTY_OPEN \
- if (failed_count++ >= 5) break; \
- if ((fd = getpseudotty (&slavename, &mastername)) < 0) { \
- error("Out of ptys."); \
- continue; \
- } \
- strcpy (pty_name, slavename);
-
-/* Define these to prevent the default logic in process.c:allocate_pty
- from being used. */
-#define PTY_NAME_SPRINTF
-#define PTY_TTY_NAME_SPRINTF
-
-/* PTX doesn't seem to have memmove. */
-#define MEMMOVE_MISSING
-
-/* Kenneth Stailey <kstailey@eagle.dol-esa.gov> says this is needed. */
-#define POSIX_SIGNALS
diff --git a/src/s/ptx4.h b/src/s/ptx4.h
deleted file mode 100644
index 3042c0a8d82..00000000000
--- a/src/s/ptx4.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* s/ file for Sequent "ptx 4", which is a modified SVR5.4. */
-
-/* Tell usg5-4.h not to include filio.h. */
-#define NO_FILIO_H
-
-#include "usg5-4.h"
-
-/* Marcus Daniels <marcus@sysc.pdx.edu> says that SIGINFO is defined
- on ptx4 but it is not a signal. Prevent process.c from doing the
- wrong thing. */
-#undef SIGINFO
-
-/* Marcus Daniels <marcus@sysc.pdx.edu> says vfork does exist. */
-#define HAVE_VFORK
-
diff --git a/src/s/riscix1-1.h b/src/s/riscix1-1.h
deleted file mode 100644
index 605ed688bcd..00000000000
--- a/src/s/riscix1-1.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Definitions file for GNU Emacs running on RISCiX 1.1 (bsd 4.3)
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#define RISCiX_1_1 1
-#define RISCiX 11
-#define CRT0_O /lib/crt0.o
-#include "bsd4-3.h"
diff --git a/src/s/riscix12.h b/src/s/riscix12.h
deleted file mode 100644
index cbc78d58b95..00000000000
--- a/src/s/riscix12.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Definitions file for GNU Emacs running on RISCiX 1.2 (bsd 4.3)
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#define RISCiX_1_2 1
-#define RISCiX 12
-#define CRT0_O /usr/lib/crt0.o
-#include "bsd4-3.h"
diff --git a/src/s/riscos5.h b/src/s/riscos5.h
deleted file mode 100644
index c4b1919bf06..00000000000
--- a/src/s/riscos5.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "bsd4-3.h"
-
-/* This file has changes that Jost Krieger <x920031@rubb.rz.ruhr-uni-bochum.de>
- says are necessary. */
-
-/* No declaration in system header files. */
-extern double atof ();
-
-#define LD_SWITCH_SYSTEM -non_shared
-
-#define GETPGRP_NO_ARG
diff --git a/src/s/rtu.h b/src/s/rtu.h
deleted file mode 100644
index 45266f2716d..00000000000
--- a/src/s/rtu.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#define BSD4_2
-#define BSD_SYSTEM
-#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 disadvantages
- 1) At least in 4.2, it is impossible to handle the Meta key properly.
- I hear that in system V this problem does not exist.
- 2) Control-G causes output to be discarded.
- I do not know whether this can be fixed in system V.
-
- Another method of doing input is planned but not implemented.
- It would have Emacs fork off a separate process
- to read the input and send it to the true Emacs process
- through a pipe.
-*/
-
-#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_PTYS if the system supports pty devices.
- */
-
-#define HAVE_PTYS
-
-/* Define this macro if system defines a type `union wait'. */
-
-#define HAVE_UNION_WAIT
-
-/* 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 interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_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
-
-/* This is how to get the device name of the tty end of a pty. */
-#define PTY_TTY_NAME_SPRINTF \
- sprintf (pty_name, "/dev/ttyp%x", i);
-
-/* This is how to get the device name of the control end of a pty. */
-#define PTY_NAME_SPRINTF \
- sprintf (pty_name, "/dev/pty%x", i);
-
-/* (Assume) we do have vfork. */
-
-#define HAVE_VFORK
-
-/* Process groups work in the traditional BSD manner. */
-
-#define BSD_PGRPS
diff --git a/src/s/sco4.h b/src/s/sco4.h
deleted file mode 100644
index 2610dfbe0f0..00000000000
--- a/src/s/sco4.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/* System description file for SCO 3.2v4.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Contributed by Ian Lance Taylor, ian@cygnus.com. */
-
-/* SCO is sort of like SVR3. */
-#include "usg5-3.h"
-#define SCO_R4
-
-#if 0 /* Turned off rather than make the Lisp code check for this. -- rms.
- I am assuming that (at least most of) the tests for usg-unix-v
- do the right thing for sco3.2v4 also. Things that *might* be wrong
- as a result of turning off these lines include the values of
- ange-ftp-remote-shell-file-name (now remsh)
- dired-chown-program (now just chown)
- lpr-command (now lp)
- nntp-buggy-select (now t)
- rmail-spool-directory (now /usr/mail?)
- and the actions of the function print-region-1. */
-
-/* SYSTEM_TYPE should indicate the kind of system you are using. */
-#undef SYSTEM_TYPE
-#define SYSTEM_TYPE "SCO 3.2v4"
-#endif
-
-/* SCO supports job control. */
-#undef NOMULTIPLEJOBS
-
-/* SCO has termios. */
-#define HAVE_TERMIOS
-
-/* SCO has ptys with unusual names. */
-#define HAVE_PTYS
-
-#define PTY_ITERATION \
- for (i = 0; ; i++)
-#define PTY_NAME_SPRINTF \
- sprintf (pty_name, "/dev/ptyp%d", i);
-#define PTY_TTY_NAME_SPRINTF \
- sprintf (pty_name, "/dev/ttyp%d", i);
-
-/* Sockets are an option on SCO. If you have X, you have them.
- They also exist if you have TCP, but we don't know how to test
- for that. */
-#ifdef HAVE_X_WINDOWS
-#define HAVE_SOCKETS
-#endif
-
-/* Must use 'cc' to link when build with motif toolkit. */
-#ifndef __GNUC__
-#define LINKER cc
-#endif
-
-/* This is safe since we already assumed HAVE_SOCKET
- if using X windows. */
-#undef LIBX11_SYSTEM
-#define LIBX11_SYSTEM -lpt -lnls -lnsl_s -lc_s -lsocket
-
-#ifdef HAVE_INET_SOCKETS /* This comes from autoconf. */
-#define HAVE_SOCKETS
-#endif
-
-#ifdef HAVE_SOCKETS
-#define LIBS_SYSTEM -lsocket -lPW
-
-/* SCO has gettimeofday in socket library */
-/* Autoconf should determine this, but for now,
- play safe to avoid error rather than deleting this
- and risking the wrong result. */
-#ifndef HAVE_GETTIMEOFDAY
-#define HAVE_GETTIMEOFDAY
-#endif
-#endif
-
-/* This enables configure to tell that we have alloca. */
-#ifndef LIBS_SYSTEM
-#define LIBS_SYSTEM -lPW
-#endif
-
-#ifdef HAVE_X11R5
-/* configure can't get this right linking fails unless -lsocket is used. */
-#undef HAVE_XSCREENNUMBEROFSCREEN
-#define HAVE_XSCREENNUMBEROFSCREEN
-#endif
-
-/* We don't have -loldX, and we don't need it. */
-#define LIB_XMENU_LIB
-
-/* doug@zadall.com says SCO 3.2v4.2 mktime botches time arithmetic as used
- by display-time. */
-#define BROKEN_MKTIME 1
-
-/* SCO does have TIOCGWINSZ. */
-#undef BROKEN_TIOCGWINSZ
-#define NEED_PTEM_H
-
-/* We need to link with crt1.o and crtn.o. */
-#define START_FILES pre-crt0.o /lib/crt1.o
-#define LIB_STANDARD -lc /lib/crtn.o
-
-/* Send signals to subprocesses by "typing" signal chars at them. */
-#define SIGNALS_VIA_CHARACTERS
-
-/* Specify program for etc/fakemail to run. Define SMAIL if you are
- using smail, don't for MMDF. */
-
-#ifdef SMAIL
-#define MAIL_PROGRAM_NAME "/bin/smail -q0"
-#else
-#define MAIL_PROGRAM_NAME "/usr/lib/mail/execmail"
-#endif
-
-/* miano@acosta.enet.dec.com says these are needed. */
-#define bcopy(b1,b2,len) memmove (b2, b1, len)
-#define bzero(b,len) memset (b, 0, len)
-#define bcmp(b1,b2,len) memcmp (b1, b2, len)
-
-/* Tell process_send_signal to use VSUSP instead of VSWTCH. */
-#define PREFER_VSUSP
-
-/* wjs@wang.com (William Smith) says this is needed on 3.2.4.2. */
-#define POSIX_SIGNALS
-
-/* wjs@wiis.wang.com says SCO 3.2 v4.2 "has sockets",
- but only for network connections.
- It doesn't have the kind of sockets that emacsclient.c
- and emacsserver.c would use. */
-#define NO_SOCKETS_IN_FILE_SYSTEM
diff --git a/src/s/sco5.h b/src/s/sco5.h
deleted file mode 100644
index 1c914a37299..00000000000
--- a/src/s/sco5.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/* System description file for SCO 3.2v5.
- Copyright (C) 1996 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Contributed by Mark Diekhans <markd@grizzly.com>. */
-
-/* SCO is sort of like SVR3. */
-#include "usg5-3.h"
-#define SCO_R5
-
-#if 0 /* Turned off rather than make the Lisp code check for this. -- rms.
- I am assuming that (at least most of) the tests for usg-unix-v
- do the right thing for sco3.2v4 also. Things that *might* be wrong
- as a result of turning off these lines include the values of
- ange-ftp-remote-shell-file-name (now remsh)
- dired-chown-program (now just chown)
- lpr-command (now lp)
- nntp-buggy-select (now t)
- rmail-spool-directory (now /usr/mail?)
- and the actions of the function print-region-1. */
-
-/* SYSTEM_TYPE should indicate the kind of system you are using. */
-#undef SYSTEM_TYPE
-#define SYSTEM_TYPE "SCO 3.2v4"
-#endif
-
-/* SCO supports job control. */
-#undef NOMULTIPLEJOBS
-
-/* SCO has termios. */
-#define HAVE_TERMIOS
-
-/* SCO has ptys with unusual names. */
-#define HAVE_PTYS
-
-#define PTY_ITERATION \
- for (i = 0; ; i++)
-#define PTY_NAME_SPRINTF \
- sprintf (pty_name, "/dev/ptyp%d", i);
-#define PTY_TTY_NAME_SPRINTF \
- sprintf (pty_name, "/dev/ttyp%d", i);
-
-/* Sockets are an option on SCO. If you have X, you have them.
- They also exist if you have TCP, but we don't know how to test
- for that. */
-#ifdef HAVE_X_WINDOWS
-#define HAVE_SOCKETS
-#endif
-
-#ifndef __GNUC__
-#define LINKER ld
-#endif
-
-/* This is safe since we already assumed HAVE_SOCKET
- if using X windows. */
-#undef LIBX11_SYSTEM
-#define LIBX11_SYSTEM -lpt -lnls -lnsl -lc -lsocket
-
-#undef LIB_X11_LIB
-#define LIB_X11_LIB -lX11
-
-#ifdef HAVE_INET_SOCKETS /* This comes from autoconf. */
-#define HAVE_SOCKETS
-#endif
-
-#ifdef HAVE_SOCKETS
-#define LIBS_SYSTEM -lsocket -lPW
-#endif
-
-#ifndef HAVE_GETTIMEOFDAY
-#define HAVE_GETTIMEOFDAY
-#endif
-
-/* This enables configure to tell that we have alloca. */
-#ifndef LIBS_SYSTEM
-#define LIBS_SYSTEM -lPW
-#endif
-
-#ifdef HAVE_X11R5
-/* configure can't get this right linking fails unless -lsocket is used. */
-#undef HAVE_XSCREENNUMBEROFSCREEN
-#define HAVE_XSCREENNUMBEROFSCREEN
-#endif
-
-/* We don't have -loldX, and we don't need it. */
-#define LIB_XMENU_LIB
-
-/* SCO does have TIOCGWINSZ. */
-#undef BROKEN_TIOCGWINSZ
-#define NEED_PTEM_H
-
-/* We need to link with crt1.o and crtn.o. */
-#define START_FILES pre-crt0.o /lib/crt1.o
-#define LIB_STANDARD -lc /lib/crtn.o
-
-/* Send signals to subprocesses by "typing" signal chars at them. */
-#define SIGNALS_VIA_CHARACTERS
-
-/* Specify program for etc/fakemail to run. Define SMAIL if you are
- using smail, don't for MMDF. */
-
-#ifdef SMAIL
-#define MAIL_PROGRAM_NAME "/bin/smail -q0"
-#else
-#define MAIL_PROGRAM_NAME "/usr/lib/mail/execmail"
-#endif
-
-/* miano@acosta.enet.dec.com says these are needed. */
-#define bcopy(b1,b2,len) memmove (b2, b1, len)
-#define bzero(b,len) memset (b, 0, len)
-#define bcmp(b1,b2,len) memcmp (b1, b2, len)
-
-/* Tell process_send_signal to use VSUSP instead of VSWTCH. */
-#define PREFER_VSUSP
-
-/* SCO Unix has Posix signals, but in 3.2.5 something broken that causes
- * all keyboard-quit signals to be lost after the first one. */
-#undef POSIX_SIGNALS
-#define sigblock(sig) (sigprocmask (SIG_BLOCK, SIGEMPTYMASK | sig, NULL))
-
-#ifndef PENDING_OUTPUT_COUNT
-#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__ptr - (FILE)->__base)
-#endif
-
-#ifndef HAVE_VFORK
-#define HAVE_VFORK
-#endif
-
-/* Use ELF and get real shared libraries */
-
-#undef COFF
-#define ELF
-
-#define UNEXEC unexelf.o
-
-#ifndef __GNUC__
-#define C_SWITCH_SYSTEM -belf
-#define LD_SWITCH_SYSTEM -belf
-#endif
-
-/* SCO has a working alloca in libPW */
-#define HAVE_ALLOCA
-
-/* Don't disable static function, as SCO's header files have some.*/
-#undef static
-
-#undef START_FILES
-#define START_FILES pre-crt0.o /usr/ccs/lib/crt1.o /usr/ccs/lib/values-Xt.o
-#undef LIB_STANDARD
-#define LIB_STANDARD -lc /usr/ccs/lib/crtn.o
diff --git a/src/s/sol2-3.h b/src/s/sol2-3.h
deleted file mode 100644
index 9d9018aa0be..00000000000
--- a/src/s/sol2-3.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "sol2.h"
-
-/* Solaris 2.3 has a bug in XListFontsWithInfo. */
-#define BROKEN_XLISTFONTSWITHINFO
-
-/* Override LD_SWITCH_SYSTEM: add -L /usr/ccs/lib to the sol2.h value. */
-
-#undef LD_SWITCH_SYSTEM
-
-#ifndef __GNUC__
-#define LD_SWITCH_SYSTEM -L /usr/ccs/lib LD_SWITCH_X_SITE_AUX
-#else /* GCC */
-/* We use ./prefix-args because we don't know whether LD_SWITCH_X_SITE_AUX
- has anything in it. It can be empty.
- This works ok in src. Luckily lib-src does not use LD_SWITCH_SYSTEM. */
-#define LD_SWITCH_SYSTEM -L /usr/ccs/lib \
- `./prefix-args -Xlinker LD_SWITCH_X_SITE_AUX`
-#endif /* GCC */
-
-/* Info from fnf@cygnus.com suggests this is appropriate. */
-#define POSIX_SIGNALS
-
-/* We don't need the definition from usg5-3.h with POSIX_SIGNALS. */
-#undef sigsetmask
-
-/* This is the same definition as in usg5-4.h, but with sigblock/sigunblock
- rather than sighold/sigrelse, which appear to be BSD4.1 specific and won't
- work if POSIX_SIGNALS is defined. It may also be appropriate for SVR4.x
- (x<2) but I'm not sure. fnf@cygnus.com */
-/* 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). */
-
-#undef PTY_TTY_NAME_SPRINTF
-#define PTY_TTY_NAME_SPRINTF \
- { \
- char *ptsname (), *ptyname; \
- \
- sigblock (sigmask (SIGCLD)); \
- if (grantpt (fd) == -1) \
- { close (fd); return -1; } \
- sigunblock (sigmask (SIGCLD)); \
- if (unlockpt (fd) == -1) \
- { close (fd); return -1; } \
- if (!(ptyname = ptsname (fd))) \
- { close (fd); return -1; } \
- strncpy (pty_name, ptyname, sizeof (pty_name)); \
- pty_name[sizeof (pty_name) - 1] = 0; \
- }
diff --git a/src/s/sol2-4.h b/src/s/sol2-4.h
deleted file mode 100644
index 1e59b217d01..00000000000
--- a/src/s/sol2-4.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Handle Solaris 2.4. */
-
-#include "sol2-3.h"
-
-#define SOLARIS2_4
-
-/* Get rid of -traditional and let const really do its thing. */
-
-#ifdef __GNUC__
-#undef C_SWITCH_SYSTEM
-#undef const
-#endif /* __GNUC__ */
-
-#undef LD_SWITCH_SYSTEM
-#ifndef __GNUC__
-#define LD_SWITCH_SYSTEM -L/usr/ccs/lib LD_SWITCH_X_SITE_AUX -R/usr/dt/lib -L/usr/dt/lib
-#else /* GCC */
-/* We use ./prefix-args because we don't know whether LD_SWITCH_X_SITE_AUX
- has anything in it. It can be empty.
- This works ok in src. Luckily lib-src does not use LD_SWITCH_SYSTEM. */
-#define LD_SWITCH_SYSTEM -L/usr/ccs/lib \
- `./prefix-args -Xlinker LD_SWITCH_X_SITE_AUX` -R/usr/dt/lib -L/usr/dt/lib
-#endif /* GCC */
-
-/* Gregory Neil Shapiro <gshapiro@hhmi.org> reports the Motif header files
- are in this directory on Solaris 2.4. */
-#define C_SWITCH_X_SYSTEM -I/usr/dt/include
-
diff --git a/src/s/sol2-5.h b/src/s/sol2-5.h
deleted file mode 100644
index f4b45884e6c..00000000000
--- a/src/s/sol2-5.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Handle Solaris 2.5. */
-
-#include "sol2-4.h"
-
-/* -lgen is needed for the regex and regcmp functions
- which are used by Motif. In the future we can try changing
- regex.c to provide them in Emacs, but this is safer for now. */
-#define LIB_MOTIF -lXm -lgen
-
-#if 0 /* A recent patch in unexelf.c should eliminate the need for this. */
-/* Don't use the shared libraries for -lXt and -lXaw,
- to work around a linker bug in Solaris 2.5.
- (This also affects the other libraries used specifically for
- the X toolkit, which may not be necessary.) */
-#define LIBXT_STATIC
-
-#ifdef __GNUC__
-#define STATIC_OPTION -Xlinker -Bstatic
-#define DYNAMIC_OPTION -Xlinker -Bdynamic
-#else
-#define STATIC_OPTION -Bstatic
-#define DYNAMIC_OPTION -Bdynamic
-#endif
-
-#endif /* 0 */
diff --git a/src/s/sol2.h b/src/s/sol2.h
deleted file mode 100644
index f4e0891dd1c..00000000000
--- a/src/s/sol2.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "usg5-4.h"
-
-#define SOLARIS2
-
-/* eggert@twinsun.com said these work in Solaris.
- Perhaps they work in all kinds of SVR4, but this is more conservative. */
-#undef BROKEN_TIOCGETC
-#undef BROKEN_TIOCGWINSZ
-
-/* This triggers a conditional in xfaces.c. */
-#define XOS_NEEDS_TIME_H
-
-#define POSIX
-
-/* Here is how to find X Windows. LD_SWITCH_X_SITE_AUX gives an -R option
- says where to find X windows at run time. */
-#ifndef __GNUC__
-#define LD_SWITCH_SYSTEM LD_SWITCH_X_SITE_AUX
-#else /* GCC */
-/* We use ./prefix-args because we don't know whether LD_SWITCH_X_SITE_AUX
- has anything in it. It can be empty.
- This works ok in src. Luckily lib-src does not use LD_SWITCH_SYSTEM. */
-#define LD_SWITCH_SYSTEM `./prefix-args -Xlinker LD_SWITCH_X_SITE_AUX`
-#endif /* GCC */
-
-#undef LIBS_SYSTEM
-#define LIBS_SYSTEM -lsocket -lnsl -lkstat
-#define HAVE_VFORK
diff --git a/src/s/sunos4-0.h b/src/s/sunos4-0.h
deleted file mode 100644
index 02bdd1ea0c5..00000000000
--- a/src/s/sunos4-0.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "bsd4-2.h"
-
-#ifndef SUNOS4
-#define SUNOS4
-#endif
-
-#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
-
-/* We use the Sun syntax -Bstatic unconditionally, because even when we
- use GCC, these are passed through to the linker, not handled by GCC
- directly. */
-#define LD_SWITCH_SYSTEM -e __start -Bstatic
-
-/* In SunOS 4.1, a static function called by tzsetwall reportedly
- clears the byte just past an eight byte region it mallocs, corrupting
- GNU malloc's memory pool. But Sun's malloc doesn't seem to mind. */
-
-#define SYSTEM_MALLOC
-
-#ifdef __GNUC__
-/* We must define mkdir with this arg prototype
- to match GCC's fixed stat.h. */
-#define MKDIR_PROTOTYPE \
- int mkdir (const char *dpath, unsigned short dmode)
-#endif /* __GNUC__ */
diff --git a/src/s/sunos4-1.h b/src/s/sunos4-1.h
deleted file mode 100644
index 7aa0946d381..00000000000
--- a/src/s/sunos4-1.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "sunos4-0.h"
-
-/* 4.1.1 makes these system calls interruptible. */
-
-#define read sys_read
-#define write sys_write
-#define open sys_open
-#define close sys_close
-
-#define INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_CLOSE
-#define INTERRUPTIBLE_IO
-
-/* Cause the compilation of oldxmenu to use the right -I option. */
-#define OLDXMENU_OPTIONS CFLAGS=C_SWITCH_SYSTEM
-
-#if 0 /* This isn't right. Apparently some sites do have -lresolv
- but don't use that. On those systems, the code below loses.
- There's no way to win automatically unless someone
- figures out a way of determining automatically which way is right
- on any given system. */
-/* Some systems do not run the Network Information Service, but have
- modified the shared C library to include resolver support without
- also changing the C archive library (/usr/lib/libc.a). If we
- detect the presence of libresolv.a, use -lresolv to supplement libc.a.
-
- We used to have #ifdef HAVE_GETHOSTNAME is to prevent configure from
- setting libsrc_libs to -lresolv in lib-src/Makefile. But nowadays
- configure is smarter about computing libsrc_libs, and would not
- be fooled. Anyway, why not use -lresolv in lib-src? */
-/* #ifdef HAVE_GETHOSTNAME */
-#ifdef HAVE_LIBRESOLV
-#define LIBS_SYSTEM -lresolv
-#endif
-/* #endif */
-#endif
-
-#if 0 /* Not necessary, since SYSTEM_MALLOC is defined in sunos4-0.h. */
-/* Tell GNU malloc to compensate for a bug in localtime. */
-#define SUNOS_LOCALTIME_BUG
-#endif
-
-/* Define dlopen, dlclose, dlsym. */
-#define USE_DL_STUBS
diff --git a/src/s/sunos413.h b/src/s/sunos413.h
deleted file mode 100644
index 3caae6e7378..00000000000
--- a/src/s/sunos413.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "sunos4-1.h"
-
-/* jik@gza.com says this works now. */
-/* The bug that corrupts GNU malloc's memory pool is fixed in SunOS 4.1.3. */
-
-#undef SYSTEM_MALLOC
-
-/* barrie@calvin.demon.co.uk says memmove is missing. */
-#ifndef SYSTEM_MALLOC
-#define MEMMOVE_MISSING
-#endif
diff --git a/src/s/sunos4shr.h b/src/s/sunos4shr.h
deleted file mode 100644
index b95160fe016..00000000000
--- a/src/s/sunos4shr.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* This file permits building Emacs with a shared libc on Sunos 4.
- To make this work, you must completely replace your C shared library
- using one of the SunOS 4.1.x jumbo replacement patches from Sun.
- Here are the patch numbers for Sunos 4.1.3:
- 100890-10 SunOS 4.1.3: domestic libc jumbo patch
- 100891-10 SunOS 4.1.3: international libc jumbo patch */
-
-
-#include "sunos4-1.h"
-
-/* 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. */
-
-/* Misleading! Actually gets loaded after crt0.o */
-#define START_FILES pre-crt0.o
-
-/*
- * Kludge! can't get at symbol "start" in std crt0.o
- * Who the #$%&* decided to remove the __ characters!
- * Someone needs to fix this in sysdep.c with an #ifdef BROKEN_START in
- * sysdep.c. We do not use this address so any value should do really. Still
- * may need it in the future?
- */
-#define BROKEN_START
-#define TEXT_START 0x2020
-
-#define UNEXEC unexsunos4.o
-#define RUN_TIME_REMAP
-#define ORDINARY_LINK
-#define SUNOS4_SHARED_LIBRARIES
-
-#undef LD_SWITCH_SYSTEM
-
-#undef SYSTEM_MALLOC
-#ifndef GNU_MALLOC
-#define GNU_MALLOC
-#endif
-#ifndef REL_ALLOC
-#define REL_ALLOC
-#endif
-
-/* khera@cs.duke.edu says this is needed. */
-#define memmove(to, from, size) bcopy (from, to, size)
-
-#undef USE_DL_STUBS
-
-#ifndef HAVE_X11R6
-/* With X11R5 it was reported that linking -lXmu dynamically
- did not work. With X11R6, it does work; and since normally
- only the dynamic libraries are available, we should use them. */
-#ifdef __GNUC__
-#define LIBXMU -Xlinker -Bstatic -lXmu -Xlinker -Bdynamic
-#else
-#define LIBXMU -Bstatic -lXmu -Bdynamic
-#endif
-
-#endif /* not HAVE_X11R6 */
diff --git a/src/s/template.h b/src/s/template.h
deleted file mode 100644
index ee6da5cc57a..00000000000
--- a/src/s/template.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/* Template for system description header files.
- This file describes the parameters that system description files
- should define or not.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-/* #define UNIPLUS */
-/* #define USG5 */
-/* #define USG */
-/* #define HPUX */
-/* #define UMAX */
-/* #define BSD4_1 */
-/* #define BSD4_2 */
-/* #define BSD4_3 */
-/* #define BSD_SYSTEM */
-/* #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)
-
- Emacs uses the presence or absence of the SIGIO macro to indicate
- whether or not signal-driven I/O is possible. It uses
- INTERRUPT_INPUT to decide whether to use it by default.
-
- SIGIO can be used only on systems that implement it (4.2 and 4.3).
- CBREAK mode has two disadvantages
- 1) At least in 4.2, it is impossible to handle the Meta key properly.
- I hear that in system V this problem does not exist.
- 2) Control-G causes output to be discarded.
- I do not know whether this can be fixed in system V.
-
- Another method of doing input is planned but not implemented.
- It would have Emacs fork off a separate process
- to read the input and send it to the true Emacs process
- through a pipe. */
-
-#define INTERRUPT_INPUT
-
-/* Letter to use in finding device name of first pty,
- if system supports pty's. 'a' means it is /dev/ptya0 */
-
-#define FIRST_PTY_LETTER 'a'
-
-/*
- * Define HAVE_TERMIOS if the system provides POSIX-style
- * functions and macros for terminal control.
- *
- * Define HAVE_TERMIO if the system provides sysV-style ioctls
- * for terminal control.
- *
- * Do not define both. HAVE_TERMIOS is preferred, if it is
- * supported on your system.
- */
-
-#define HAVE_TERMIOS
-/* #define HAVE_TERMIO */
-
-/*
- * Define HAVE_PTYS if the system supports pty devices.
- */
-
-#define HAVE_PTYS
-
-/*
- * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
- * The 4.2 opendir, etc., library functions.
- */
-
-#define NONSYSTEM_DIR_LIBRARY
-
-/* Define this symbol if your system has the functions bcopy, etc. */
-
-#define BSTRING
-
-/* subprocesses should be defined if you want to
- have code for asynchronous subprocesses
- (as used in M-x compile and M-x shell).
- This is generally OS dependent, and not supported
- under most USG systems. */
-
-#define subprocesses
-
-/* If your system uses COFF (Common Object File Format) then define the
- preprocessor symbol "COFF". */
-
-/* #define COFF */
-
-/* define MAIL_USE_FLOCK if the mailer uses flock
- to interlock access to /usr/spool/mail/$USER.
- The alternative is that a lock file named
- /usr/spool/mail/$USER.lock. */
-
-#define MAIL_USE_FLOCK
-
-/* Define CLASH_DETECTION if you want lock files to be written
- so that Emacs can tell instantly when you try to modify
- a file that someone else has modified in his Emacs. */
-
-#define CLASH_DETECTION
-
-/* Define this if your operating system declares signal handlers to
- have a type other than the usual. `The usual' is `void' for ANSI C
- systems (i.e. when the __STDC__ macro is defined), and `int' for
- pre-ANSI systems. If you're using GCC on an older system, __STDC__
- will be defined, but the system's include files will still say that
- signal returns int or whatever; in situations like that, define
- this to be what the system's include files want. */
-/* #define SIGTYPE int */
-
-/* If the character used to separate elements of the executable path
- is not ':', #define this to be the appropriate character constant. */
-/* #define SEPCHAR ':' */
-
-/* ============================================================ */
-
-/* Here, add any special hacks needed
- to make Emacs work on this system. For example,
- you might define certain system call names that don't
- exist on your system, or that do different things on
- your system and must be used only through an encapsulation
- (Which you should place, by convention, in sysdep.c). */
-
-/* Some compilers tend to put everything declared static
- into the initialized data area, which becomes pure after dumping Emacs.
- On these systems, you must #define static as nothing to foil this.
- Note that emacs carefully avoids static vars inside functions. */
-
-/* #define static */
-
-/* ============================================================ */
-
-/* After adding support for a new system, modify the large case
- statement in the `configure' script to recognize reasonable
- configuration names, and add a description of the system to
- `etc/MACHINES'.
-
- If you've just fixed a problem in an existing configuration file,
- you should also check `etc/MACHINES' to make sure its descriptions
- of known problems in that configuration should be updated. */
diff --git a/src/s/ultrix4-3.h b/src/s/ultrix4-3.h
deleted file mode 100644
index 0ca4900ffaa..00000000000
--- a/src/s/ultrix4-3.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "bsd4-3.h"
-
-#define NEED_UNISTD_H
-#define HAVE_TERMIOS
-#define PREFER_VSUSP
-
-/* Must set the line discipline to this, to make termio work. */
-#define SET_LINE_DISCIPLINE TERMIODISC
diff --git a/src/s/umax.h b/src/s/umax.h
deleted file mode 100644
index de631f608c4..00000000000
--- a/src/s/umax.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-/* #define UNIPLUS */
-/* #define USG5 */
-/* #define USG */
-/* #define BSD4_1 */
-#define BSD4_2
-/* #define BSD4_3 */
-#define BSD_SYSTEM
-#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 disadvantages
- 1) At least in 4.2, it is impossible to handle the Meta key properly.
- I hear that in system V this problem does not exist.
- 2) Control-G causes output to be discarded.
- I do not know whether this can be fixed in system V.
-
- Another method of doing input is planned but not implemented.
- It would have Emacs fork off a separate process
- to read the input and send it to the true Emacs process
- through a pipe.
-*/
-
-#define INTERRUPT_INPUT
-
-/* Letter to use in finding device name of first pty,
- if system supports pty's. 'a' means it is /dev/ptya0 */
-
-#define FIRST_PTY_LETTER 'p'
-
-/*
- * Define HAVE_PTYS if the system supports pty devices.
- */
-
-#define HAVE_PTYS
-
-/* Define this macro if system defines a type `union wait'. */
-
-#define HAVE_UNION_WAIT
-
-/* 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
-*/
-
-/* (Assume) we do have vfork. */
-
-#define HAVE_VFORK
-
-/* Process groups work in the traditional BSD manner. */
-
-#define BSD_PGRPS
diff --git a/src/s/umips.h b/src/s/umips.h
deleted file mode 100644
index 07a4cd6bbb0..00000000000
--- a/src/s/umips.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Definitions file for GNU Emacs running on Mips operating system.
- That system can emulate either BSD or Sys V, in either case with changes.
- If BSD_SYSTEM is defined, we assume BSD is being emulated; otherwise,
- Sys V. */
-
-#ifdef BSD_SYSTEM
-#include "bsd4-3.h"
-
-#define C_SWITCH_SYSTEM -systype bsd43
-#define LD_SWITCH_SYSTEM -systype bsd43
-#define LIBS_SYSTEM -lmld
-#define LIBS_DEBUG
-#define START_FILES pre-crt0.o /lib/crt1.o
-#define LIB_STANDARD -lc /usr/lib/crtn.o
-
-#define COFF
-#define TERMINFO
-#undef MAIL_USE_FLOCK /* Someone should check this. */
-#undef HAVE_UNION_WAIT
-
-#else /* not BSD_SYSTEM */
-
-#include "usg5-2-2.h"
-
-#define LIBS_SYSTEM -lmld
-#define LIBS_DEBUG
-#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_SYSTEM -I/usr/include/bsd
-
-/* 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
-
-#if defined(emacs)
-#include <bsd/sys/time.h>
-#endif
-
-/* The `select' in the system won't work for pipes,
- so don't use it. */
-#define BROKEN_SELECT
-
-#define HAVE_DUP2
-#define HAVE_GETWD
-#define HAVE_GETTIMEOFDAY
-
-#define HAVE_PTYS
-#define HAVE_SOCKETS
-/* #define BSTRING Supposedly removed. */
-
-#undef NOMULTIPLEJOBS
-
-#define CLASH_DETECTION
-
-#if defined(HAVE_X_WINDOWS) && defined(HAVE_X11)
-#define HAVE_VFORK /* Graciously provided by libX.a */
-#endif
-
-#define utimes utime /* Someone should check this. */
-/* ??? */
-#define IRIS
-
-#endif /* not BSD_SYSTEM */
-
-/* High order bit must be stripped off nlist return values */
-#define FIXUP_KERNEL_SYMBOL_ADDR(NL) (NL)[0].n_value &= 0x7fffffff;
diff --git a/src/s/unipl5-0.h b/src/s/unipl5-0.h
deleted file mode 100644
index 465c654f370..00000000000
--- a/src/s/unipl5-0.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#define 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_PTYS if the system supports pty devices.
- */
-
-/* #define HAVE_PTYS */
-
-/* Define this macro if system defines a type `union wait'. */
-
-#define HAVE_UNION_WAIT
-
-/* 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 interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_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
deleted file mode 100644
index df505e48f16..00000000000
--- a/src/s/unipl5-2.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#define 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_PTYS if the system supports pty devices.
- */
-
-#define HAVE_PTYS
-
-/* Define this macro if system defines a type `union wait'. */
-
-#define HAVE_UNION_WAIT
-
-/* 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 interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_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
deleted file mode 100644
index cf31a3d1404..00000000000
--- a/src/s/usg5-0.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#define 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_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 interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_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
deleted file mode 100644
index 98698f2fefb..00000000000
--- a/src/s/usg5-2-2.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#define 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_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 interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_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
deleted file mode 100644
index 51b73bda462..00000000000
--- a/src/s/usg5-2.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#define 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_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 interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_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
deleted file mode 100644
index 01eea23c4b6..00000000000
--- a/src/s/usg5-3.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#define 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_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 interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_CLOSE
-#define INTERRUPTIBLE_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)
-
-/* Use terminfo instead of termcap. */
-
-#define TERMINFO
-
-/* Some variants have TIOCGETC, but the structures to go with it
- are not declared. */
-
-#define BROKEN_TIOCGETC
-
-/* AT&T SVr3 X wants to be linked with shared libraries */
-
-#define LIB_X11_LIB -lX11_s
-
-/* X needs to talk on the network, so search the network library. */
-
-#define LIBX10_SYSTEM -lnsl_s
-#define LIBX11_SYSTEM -lpt -lnls -lnsl_s -lc_s
-
-/* The docs for system V/386 suggest v.3 has sigpause,
- so let's give it a try. */
-#define HAVE_SYSV_SIGPAUSE
-
-/* Some variants have TIOCGWINSZ, but the structures to go with it
- are not declared. */
-
-#define BROKEN_TIOCGWINSZ
-
-/* If we're using the System V X port, BSD bstring functions will be handy */
-
-#ifdef HAVE_X_WINDOWS
-#define BSTRING
-#endif /* HAVE_X_WINDOWS */
-
-/* Enable support for shared libraries in unexec. */
-
-#define USG_SHARED_LIBRARIES
-
-/* On USG systems signal handlers return void */
-
-#define SIGTYPE void
diff --git a/src/s/usg5-4-2.h b/src/s/usg5-4-2.h
deleted file mode 100644
index 373ecb85f11..00000000000
--- a/src/s/usg5-4-2.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* s/ file for System V release 4.2. */
-
-#include "usg5-4.h"
-
-/* pcg@aber.ac.uk says this is useless since fork does copy-on-write
- #define HAVE_VFORK */
-/* fnf@cygnus.com says these exist. */
-#define HAVE_TCATTR
-#if 0 /* autoconf should take care of this. */
-#define HAVE_GETHOSTNAME
-#define HAVE_RANDOM
-#endif
-/* #define HAVE_GETWD (appears to be buggy on SVR4.2) */
-
-/* Info from fnf@cygnus.com suggests this is appropriate. */
-#define POSIX_SIGNALS
-
-/* We don't need the definition from usg5-3.h with POSIX_SIGNALS. */
-#undef sigsetmask
-#undef HAVE_SYSV_SIGPAUSE
-
-/* Motif needs -lgen. */
-#undef LIBS_SYSTEM
-#define LIBS_SYSTEM -lsocket -lnsl -lelf -lgen
-
-/* This is the same definition as in usg5-4.h, but with sigblock/sigunblock
- rather than sighold/sigrelse, which appear to be BSD4.1 specific and won't
- work if POSIX_SIGNALS is defined. It may also be appropriate for SVR4.x
- (x<2) but I'm not sure. fnf@cygnus.com */
-/* 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). */
-
-#undef PTY_TTY_NAME_SPRINTF
-#define PTY_TTY_NAME_SPRINTF \
- { \
- char *ptsname(), *ptyname; \
- \
- sigblock(sigmask(SIGCLD)); \
- if (grantpt(fd) == -1) \
- fatal("could not grant slave pty"); \
- sigunblock(sigmask(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; \
- }
-
-/* Use libw.a along with X11R6 Xt. */
-#define NEED_LIBW
-
-/* ryanr@ellingtn.ftc.nrcs.usda.gov (Richard Anthony Ryan) says -lXimp
- is needed in UNIX_SV ... 4.2 1.1.2. */
-#define LIB_MOTIF -lXm -lXimp
-
-#define VFORK_RETURN_TYPE pid_t
diff --git a/src/s/usg5-4-3.h b/src/s/usg5-4-3.h
deleted file mode 100644
index f7773cb0a13..00000000000
--- a/src/s/usg5-4-3.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* s/ file for System V release 4.3. */
-
-#include "usg5-4-2.h"
-
-/* Bill_Mann@PraxisInt.com: without this switch emacs generates this error
- on start up for an i486-ncr-sysv4.3 (running the X toolkit):
- _XipOpenIM() Unable to find Atom _XIM_INPUTMETHOD */
-#define X11R5_INHIBIT_I18N
diff --git a/src/s/usg5-4.h b/src/s/usg5-4.h
deleted file mode 100644
index ebb848199eb..00000000000
--- a/src/s/usg5-4.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* This file written by James Van Artsdalen of Dell Computer Corporation.
- * james@bigtex.cactus.org. Subsequently improved for Dell 2.2 by Eric
- * S. Raymond <esr@snark.thyrsus.com>.
- */
-
-/* Use the SysVr3 file for at least base configuration. */
-
-#include "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
-#ifdef ORDINARY_LINK
-#define LIB_STANDARD -lc /usr/ucblib/libucb.a
-#else
-#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
-#else
-
-#ifdef ORDINARY_LINK
-#define LIB_STANDARD
-#else
-#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/ccs/lib/crtn.o
-#endif
-#endif
-
-/* there are no -lg libraries on this system, and no libPW */
-
-#define LIBS_DEBUG
-/* This is turned off because nobody actually uses LIBS_STANDARD (Nov 1995).
- That name is a typo. The next step is to delete this entirely. */
-/* #define LIBS_STANDARD -lc */
-
-/* No <sioctl.h> */
-
-#define NO_SIOCTL_H
-
-/* Undump with ELF */
-
-#undef COFF
-
-#define UNEXEC unexelf.o
-
-/* <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
-
-/* 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.
- */
-
-#ifndef NOT_C_CODE
-#include <sys/wait.h>
-#endif
-
-#ifdef emacs
-#ifndef NO_FILIO_H
-#include <sys/filio.h>
-#endif
-#include <termio.h>
-#include <sys/ttold.h>
-#include <signal.h>
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/termios.h>
-#undef SIGIO
-#endif
-
-/* Some SVr4s don't define NSIG in sys/signal.h for ANSI environments;
- * instead, there's a system variable _sys_nsig. Unfortunately, we need the
- * constant to dimension an array. So wire in the appropriate value here.
- */
-
-#ifndef NSIG
-#define NSIG 32
-#endif
-
-/* 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_TERMIOS
-#undef BROKEN_TIOCGWINSZ
-#undef BROKEN_TIOCGETC
-
-/* 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) \
- { close (fd); return -1; } \
- sigrelse (SIGCLD); \
- if (unlockpt (fd) == -1) \
- { close (fd); return -1; } \
- if (!(ptyname = ptsname (fd))) \
- { close (fd); return -1; } \
- 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);
-
-/* Undo the SVr3 X11 library definition */
-#undef LIB_X11_LIB
-
-/* 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
-
-#define bcopy(src,dst,n) memmove (dst,src,n)
-#define bcmp(src,dst,n) memcmp (src,dst,n)
-#define bzero(s,n) memset (s,0,n)
diff --git a/src/s/vms.h b/src/s/vms.h
deleted file mode 100644
index e95212c5624..00000000000
--- a/src/s/vms.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/* system description header for VMS
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-#ifndef VMS /* Decus cpp doesn't define this but VAX C does */
-#define VMS
-#endif /* VMS */
-/* Note that this file is used indirectly via 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_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 sharable library bug? If you link with a sharable
- 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 sharable
- 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 sharable one) you don't need to define this. (This
- is NOT fixed in V4.4...) */
-
-#define SHARABLE_LIB_BUG
-
-/* Partially due to the above mentioned bug and also so that we don't need
- to require that people have a sharable 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
-
-#ifndef _GNUC_
-extern double mth$dmod(double, double);
-#define drem mth$dmod
-#endif
-
-/* Some time routines are missing in the VAX C RTL, or needs some
- extra bit of code */
-#define tzset sys_tzset
-#define localtime sys_localtime
-#define gmtime sys_gmtime
-
-/* 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
-
-#ifndef GNU_MALLOC
-/* Hide these names so that we don't get linker errors */
-#define malloc sys_malloc
-#define free sys_free
-#define realloc sys_realloc
-#define calloc sys_calloc
-
-/* Don't use the standard brk and sbrk */
-#define sbrk sys_sbrk
-#define brk sys_brk
-#endif
-
-/* 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
-
-/* 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
-
-/* variable length too long... maybe */
-#if 0
-#define do_line_insertion_deletion_costs do_line_insertion_deletion_cost
-#endif
-
-/* 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 oddities...)
- Here, we use $CHKPRO to really determine access. */
-#define access sys_access
-
-#define PAGESIZE 512
-
-#define _longjmp longjmp
-#define _setjmp setjmp
-
-globalref char sdata[];
-#define DATA_START (((int) sdata + 511) & ~511)
-#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 330000
-
-/* Stdio FILE type has extra indirect on VMS, so must alter this macro. */
-
-#define PENDING_OUTPUT_COUNT(FILE) ((*(FILE))->_ptr - (*(FILE))->_base)
-
-#define NULL_DEVICE "NLA0:"
-
-#define TERMCAP_NAME "emacs_library:[etc]termcap.dat"
-
-#define EXEC_SUFFIXES ".exe:.com"
-
-/* Case conflict with Xlib XFree () */
-#define xfree emacs_xfree
-
-/* What separator do we use in paths? */
-#define SEPCHAR ','
diff --git a/src/s/vms4-0.h b/src/s/vms4-0.h
deleted file mode 100644
index 3f11a3de30a..00000000000
--- a/src/s/vms4-0.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "vms.h"
-#define VMS4_0
diff --git a/src/s/vms4-2.h b/src/s/vms4-2.h
deleted file mode 100644
index e632b87e09f..00000000000
--- a/src/s/vms4-2.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "vms.h"
-#define VMS4_2
-
diff --git a/src/s/vms4-4.h b/src/s/vms4-4.h
deleted file mode 100644
index c0f60900d53..00000000000
--- a/src/s/vms4-4.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "vms.h"
-#define VMS4_4
-
diff --git a/src/s/vms5-5.h b/src/s/vms5-5.h
deleted file mode 100644
index e51fedf6317..00000000000
--- a/src/s/vms5-5.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "vms.h"
-#define VMS5_5
-#define VMS4_4
-
-/* The bug that SHARABLE_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 SHARABLE_LIB_BUG
diff --git a/src/s/windows95.h b/src/s/windows95.h
deleted file mode 100644
index 62340c3744e..00000000000
--- a/src/s/windows95.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/* System description file for Windows 95. */
-
-#include "windowsnt.h"
-
-#define WINDOWS95
diff --git a/src/s/xenix.h b/src/s/xenix.h
deleted file mode 100644
index 74c14f818d0..00000000000
--- a/src/s/xenix.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/*
- * Define symbols to identify the version of Unix this is.
- * Define all the symbols that apply correctly.
- */
-
-/* #define UNIPLUS */
-#define XENIX
-#define USG5
-#define USG
-/* #define HPUX */
-/* #define UMAX */
-/* #define BSD4_1 */
-/* #define BSD4_2 */
-/* #define BSD4_3 */
-/* #define BSD_SYSTEM */
-/* #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 disadvantages:
- 1) At least in 4.2, it is impossible to handle the Meta key properly.
- I hear that in system V this problem does not exist.
- 2) Control-G causes output to be discarded.
- I do not know whether this can be fixed in system V.
-
- Another method of doing input is planned but not implemented.
- It would have Emacs fork off a separate process
- to read the input and send it to the true Emacs process
- through a pipe.
-*/
-
-/* #define INTERRUPT_INPUT */
-
-/* Letter to use in finding device name of first pty,
- if system supports pty's. '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_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 interruptible 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 INTERRUPTIBLE_OPEN
-#define INTERRUPTIBLE_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
-
-/* Some variants have TIOCGETC, but the structures to go with it
- are not declared. */
-
-#define BROKEN_TIOCGETC
diff --git a/src/scroll.c b/src/scroll.c
deleted file mode 100644
index cbab971fd35..00000000000
--- a/src/scroll.c
+++ /dev/null
@@ -1,1058 +0,0 @@
-/* Calculate what line insertion or deletion to do, and do it,
- Copyright (C) 1985, 1986, 1990, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include "termchar.h"
-#include "lisp.h"
-#include "dispextern.h"
-#include "frame.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 frame, measured in characters.
- Let's hope this is never more than 1000000 characters. */
-
-#define INFINITY 1000000
-
-struct matrix_elt
- {
- /* Cost of outputting through this line
- if no insert/delete is done just above it. */
- int writecost;
- /* Cost of outputting through this line
- if an insert is done just above it. */
- int insertcost;
- /* Cost of outputting through this line
- if a delete is done just above it. */
- int deletecost;
- /* Number of inserts so far in this run of inserts,
- for the cost in insertcost. */
- unsigned char insertcount;
- /* Number of deletes so far in this run of deletes,
- for the cost in deletecost. */
- unsigned char deletecount;
- /* Number of writes so far since the last insert
- or delete for the cost in writecost. */
- unsigned char writecount;
- };
-
-
-/* Determine, in matrix[i,j], the cost of updating the first j old
- lines into the first i new lines using the general scrolling method.
- This involves using insert or delete somewhere if i != j.
- For each matrix elements, three kinds of costs are recorded:
- the smallest cost that ends with an insert, the smallest
- cost that ends with a delete, and the smallest cost that
- ends with neither one. These are kept separate because
- on some terminals the cost of doing an insert varies
- depending on whether one was just done, etc. */
-
-/* draw_cost[VPOS] is the cost of outputting new line at VPOS.
- old_hash[VPOS] is the hash code of the old line at VPOS.
- new_hash[VPOS] is the hash code of the new line at VPOS.
- Note that these are not true frame vpos's, but relative
- to the place at which the first mismatch between old and
- new contents appears. */
-
-static void
-calculate_scrolling (frame, matrix, window_size, lines_below,
- draw_cost, old_hash, new_hash,
- free_at_end)
- FRAME_PTR frame;
- /* matrix is of size window_size + 1 on each side. */
- struct matrix_elt *matrix;
- int window_size;
- int *draw_cost;
- int *old_hash;
- int *new_hash;
- int free_at_end;
-{
- register int i, j;
- int frame_height = FRAME_HEIGHT (frame);
- 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
- = &FRAME_INSERT_COST (frame)[frame_height - 1 - lines_moved];
- int *first_delete_cost
- = &FRAME_DELETE_COST (frame)[frame_height - 1 - lines_moved];
- int *next_insert_cost
- = &FRAME_INSERTN_COST (frame)[frame_height - 1 - lines_moved];
- int *next_delete_cost
- = &FRAME_DELETEN_COST (frame)[frame_height - 1 - lines_moved];
-
- /* Discourage long scrolls on fast lines.
- Don't scroll nearly a full frame height unless it saves
- at least 1/4 second. */
- int extra_cost = baud_rate / (10 * 4 * FRAME_HEIGHT (frame));
-
- if (baud_rate <= 0)
- extra_cost = 1;
-
- /* initialize the top left corner of the matrix */
- matrix->writecost = 0;
- matrix->insertcost = INFINITY;
- matrix->deletecost = INFINITY;
- matrix->insertcount = 0;
- matrix->deletecount = 0;
-
- /* initialize the left edge of the matrix */
- cost = first_insert_cost[1] - next_insert_cost[1];
- for (i = 1; i <= window_size; i++)
- {
- p = matrix + i * (window_size + 1);
- cost += draw_cost[i] + next_insert_cost[i] + extra_cost;
- p->insertcost = cost;
- p->writecost = INFINITY;
- p->deletecost = INFINITY;
- p->insertcount = i;
- p->deletecount = 0;
- }
-
- /* initialize the top edge of the matrix */
- cost = first_delete_cost[1] - next_delete_cost[1];
- for (j = 1; j <= window_size; j++)
- {
- cost += next_delete_cost[j];
- matrix[j].deletecost = cost;
- matrix[j].writecost = INFINITY;
- matrix[j].insertcost = INFINITY;
- matrix[j].deletecount = j;
- matrix[j].insertcount = 0;
- }
-
- /* `i' represents the vpos among new frame contents.
- `j' represents the vpos among the old frame contents. */
- p = matrix + window_size + 2; /* matrix [1, 1] */
- for (i = 1; i <= window_size; i++, p++)
- for (j = 1; j <= window_size; j++, p++)
- {
- /* p contains the address of matrix [i, j] */
-
- /* First calculate the cost assuming we do
- not insert or delete above this line.
- That is, if we update through line i-1
- based on old lines through j-1,
- and then just change old line j to new line i. */
- p1 = p - window_size - 2; /* matrix [i-1, j-1] */
- cost = p1->writecost;
- if (cost > p1->insertcost)
- cost = p1->insertcost;
- if (cost > p1->deletecost)
- cost = p1->deletecost;
- if (old_hash[j] != new_hash[i])
- cost += draw_cost[i];
- p->writecost = cost;
-
- /* Calculate the cost if we do an insert-line
- before outputting this line.
- That is, we update through line i-1
- based on old lines through j,
- do an insert-line on line i,
- and then output line i from scratch,
- leaving old lines starting from j for reuse below. */
- p1 = p - window_size - 1; /* matrix [i-1, j] */
- /* No need to think about doing a delete followed
- immediately by an insert. It cannot be as good
- as not doing either of them. */
- if (free_at_end == i)
- {
- cost = p1->writecost;
- cost1 = p1->insertcost;
- }
- else
- {
- cost = p1->writecost + first_insert_cost[i];
- if ((int) p1->insertcount > i)
- abort ();
- cost1 = p1->insertcost + next_insert_cost[i - p1->insertcount];
- }
- p->insertcost = min (cost, cost1) + draw_cost[i] + extra_cost;
- p->insertcount = (cost < cost1) ? 1 : p1->insertcount + 1;
- if ((int) p->insertcount > i)
- abort ();
-
- /* Calculate the cost if we do a delete line after
- outputting this line.
- That is, we update through line i
- based on old lines through j-1,
- and throw away old line j. */
- p1 = p - 1; /* matrix [i, j-1] */
- /* No need to think about doing an insert followed
- immediately by a delete. */
- if (free_at_end == i)
- {
- cost = p1->writecost;
- cost1 = p1->deletecost;
- }
- else
- {
- cost = p1->writecost + first_delete_cost[i];
- cost1 = p1->deletecost + next_delete_cost[i];
- }
- p->deletecost = min (cost, cost1);
- p->deletecount = (cost < cost1) ? 1 : p1->deletecount + 1;
- }
-}
-
-/* Perform insert-lines and delete-lines operations on FRAME according
- to the costs in MATRIX, using the general scrolling method.
- Update the frame's current_glyphs info to record what was done.
-
- WINDOW_SIZE is the number of lines being considered for scrolling
- and UNCHANGED_AT_TOP is the vpos of the first line being considered.
- These two arguments can specify any contiguous range of lines.
-
- We also shuffle the charstarts vectors for the lines
- along with the glyphs; but the results are not quite right,
- since we cannot offset them for changes in amount of text
- in this line or that line. Luckily it doesn't matter,
- since update_frame and update_line will copy in the proper
- new charstarts vectors from the frame's desired_glyphs. */
-
-static void
-do_scrolling (frame, matrix, window_size, unchanged_at_top)
- FRAME_PTR frame;
- struct matrix_elt *matrix;
- int window_size;
- int unchanged_at_top;
-{
- register struct matrix_elt *p;
- register int i, j;
- register struct frame_glyphs *current_frame;
- /* temp_frame->enable[i] means line i has been moved to current_frame. */
- register struct frame_glyphs *temp_frame;
- struct queue { int count, pos; } *queue;
- int offset = unchanged_at_top;
- int qi = 0;
- int window = 0;
- register int tem;
- int next;
-
- queue = (struct queue *) alloca (FRAME_HEIGHT (frame)
- * sizeof (struct queue));
-
- current_frame = FRAME_CURRENT_GLYPHS (frame);
- temp_frame = FRAME_TEMP_GLYPHS (frame);
-
- bcopy (current_frame->glyphs, temp_frame->glyphs,
- current_frame->height * sizeof (GLYPH *));
- bcopy (current_frame->charstarts, temp_frame->charstarts,
- current_frame->height * sizeof (GLYPH *));
- bcopy (current_frame->used, temp_frame->used,
- current_frame->height * sizeof (int));
- bcopy (current_frame->highlight, temp_frame->highlight,
- current_frame->height * sizeof (char));
- bzero (temp_frame->enable, temp_frame->height * sizeof (char));
- bcopy (current_frame->bufp, temp_frame->bufp,
- current_frame->height * sizeof (int));
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (frame))
- {
- bcopy (current_frame->top_left_x, temp_frame->top_left_x,
- current_frame->height * sizeof (short));
- bcopy (current_frame->top_left_y, temp_frame->top_left_y,
- current_frame->height * sizeof (short));
- bcopy (current_frame->pix_width, temp_frame->pix_width,
- current_frame->height * sizeof (short));
- bcopy (current_frame->pix_height, temp_frame->pix_height,
- current_frame->height * sizeof (short));
- bcopy (current_frame->max_ascent, temp_frame->max_ascent,
- current_frame->height * sizeof (short));
- }
-#endif
-
- i = j = window_size;
-
- while (i > 0 || j > 0)
- {
- p = matrix + i * (window_size + 1) + j;
- tem = p->insertcost;
- if (tem < p->writecost && tem < p->deletecost)
- {
- /* Insert should be done at vpos i-1, plus maybe some before */
- queue[qi].count = p->insertcount;
- i -= p->insertcount;
- queue[qi++].pos = i + unchanged_at_top;
- }
- else if (p->deletecost < p->writecost)
- {
- /* Old line at vpos j-1, and maybe some before it,
- should be deleted */
- j -= p->deletecount;
- if (!window)
- {
- set_terminal_window (window_size + unchanged_at_top);
- window = 1;
- }
- ins_del_lines (j + unchanged_at_top, - p->deletecount);
- }
- else
- {
- /* Best thing done here is no insert or delete */
- /* Old line at vpos j-1 ends up at vpos i-1 */
- current_frame->glyphs[i + offset - 1]
- = temp_frame->glyphs[j + offset - 1];
- current_frame->charstarts[i + offset - 1]
- = temp_frame->charstarts[j + offset - 1];
- current_frame->used[i + offset - 1]
- = temp_frame->used[j + offset - 1];
- current_frame->highlight[i + offset - 1]
- = temp_frame->highlight[j + offset - 1];
-
- temp_frame->enable[j + offset - 1] = 1;
- i--;
- j--;
- }
- }
-
- if (!window && qi)
- {
- set_terminal_window (window_size + unchanged_at_top);
- window = 1;
- }
-
- /* Now do all insertions */
-
- next = 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_frame->enable was not set. */
- tem = queue[i].pos;
- for (j = tem + queue[i].count - 1; j >= tem; j--)
- {
- current_frame->enable[j] = 0;
- while (temp_frame->enable[next])
- next++;
- current_frame->glyphs[j] = temp_frame->glyphs[next];
- current_frame->charstarts[j] = temp_frame->charstarts[next++];
- }
- }
-
- if (window)
- set_terminal_window (0);
-}
-
-/* Determine, in matrix[i,j], the cost of updating the first j
- old lines into the first i new lines using the direct
- scrolling method. When the old line and the new line have
- different hash codes, the calculated cost of updating old
- line j into new line i includes the cost of outputting new
- line i, and if i != j, the cost of outputting the old line j
- is also included, as a penalty for moving the line and then
- erasing it. In addition, the cost of updating a sequence of
- lines with constant i - j includes the cost of scrolling the
- old lines into their new positions, unless i == j. Scrolling
- is achieved by setting the screen window to avoid affecting
- other lines below, and inserting or deleting lines at the top
- of the scrolled region. The cost of scrolling a sequence of
- lines includes the fixed cost of specifying a scroll region,
- plus a variable cost which can depend upon the number of lines
- involved and the distance by which they are scrolled, and an
- extra cost to discourage long scrolls.
-
- As reflected in the matrix, an insert or delete does not
- correspond directly to the insertion or deletion which is
- used in scrolling lines. An insert means that the value of i
- has increased without a corresponding increase in the value
- of j. A delete means that the value of j has increased
- without a corresponding increase in the value of i. A write
- means that i and j are both increased by the same amount, and
- that the old lines will be moved to their new positions.
-
- An insert following a delete is allowed only if i > j.
- A delete following an insert is allowed only if i < j.
- These restrictions ensure that the new lines in an insert
- will always be blank as an effect of the neighboring writes.
- Thus the calculated cost of an insert is simply the cost of
- outputting the new line contents. The direct cost of a
- delete is zero. Inserts and deletes indirectly affect the
- total cost through their influence on subsequent writes. */
-
-/* The vectors draw_cost, old_hash, and new_hash have the same
- meanings here as in calculate_scrolling, and old_draw_cost
- is the equivalent of draw_cost for the old line contents */
-
-static void
-calculate_direct_scrolling (frame, matrix, window_size, lines_below,
- draw_cost, old_draw_cost, old_hash, new_hash,
- free_at_end)
- FRAME_PTR frame;
- /* matrix is of size window_size + 1 on each side. */
- struct matrix_elt *matrix;
- int window_size;
- int *draw_cost;
- int *old_draw_cost;
- int *old_hash;
- int *new_hash;
- int free_at_end;
-{
- register int i, j;
- int frame_height = FRAME_HEIGHT (frame);
- register struct matrix_elt *p, *p1;
- register int cost, cost1, delta;
-
- /* first_insert_cost[-I] is the cost of doing the first insert-line
- at a position I lines above the bottom line in the scroll window. */
- int *first_insert_cost
- = &FRAME_INSERT_COST (frame)[frame_height - 1];
- int *first_delete_cost
- = &FRAME_DELETE_COST (frame)[frame_height - 1];
- int *next_insert_cost
- = &FRAME_INSERTN_COST (frame)[frame_height - 1];
- int *next_delete_cost
- = &FRAME_DELETEN_COST (frame)[frame_height - 1];
-
- int scroll_overhead;
-
- /* Discourage long scrolls on fast lines.
- Don't scroll nearly a full frame height unless it saves
- at least 1/4 second. */
- int extra_cost = baud_rate / (10 * 4 * FRAME_HEIGHT (frame));
-
- if (baud_rate <= 0)
- extra_cost = 1;
-
- /* Overhead of setting the scroll window, plus the extra cost
- cost of scrolling by a distance of one. The extra cost is
- added once for consistency with the cost vectors */
- scroll_overhead = scroll_region_cost + extra_cost;
-
- /* initialize the top left corner of the matrix */
- matrix->writecost = 0;
- matrix->insertcost = INFINITY;
- matrix->deletecost = INFINITY;
- matrix->writecount = 0;
- matrix->insertcount = 0;
- matrix->deletecount = 0;
-
- /* initialize the left edge of the matrix */
- cost = 0;
- for (i = 1; i <= window_size; i++)
- {
- p = matrix + i * (window_size + 1);
- cost += draw_cost[i];
- p->insertcost = cost;
- p->writecost = INFINITY;
- p->deletecost = INFINITY;
- p->insertcount = i;
- p->writecount = 0;
- p->deletecount = 0;
- }
-
- /* initialize the top edge of the matrix */
- for (j = 1; j <= window_size; j++)
- {
- matrix[j].deletecost = 0;
- matrix[j].writecost = INFINITY;
- matrix[j].insertcost = INFINITY;
- matrix[j].deletecount = j;
- matrix[j].writecount = 0;
- matrix[j].insertcount = 0;
- }
-
- /* `i' represents the vpos among new frame contents.
- `j' represents the vpos among the old frame contents. */
- p = matrix + window_size + 2; /* matrix [1, 1] */
-
- for (i = 1; i <= window_size; i++, p++)
- for (j = 1; j <= window_size; j++, p++)
- {
- /* p contains the address of matrix [i, j] */
-
- /* First calculate the cost assuming we do
- not insert or delete above this line.
- That is, if we update through line i-1
- based on old lines through j-1,
- and then just change old line j to new line i.
-
- Depending on which choice gives the lower cost,
- this usually involves either scrolling a single line
- or extending a sequence of scrolled lines, but
- when i == j, no scrolling is required. */
- p1 = p - window_size - 2; /* matrix [i-1, j-1] */
- cost = p1->insertcost;
- if (cost > p1->deletecost)
- cost = p1->deletecost;
- cost1 = p1->writecost;
- if (i == j)
- {
- if (cost > cost1)
- {
- cost = cost1;
- p->writecount = p1->writecount + 1;
- }
- else
- p->writecount = 1;
- if (old_hash[j] != new_hash[i])
- {
- cost += draw_cost[i];
- }
- }
- else
- {
- if (i > j)
- {
- delta = i - j;
-
- /* The cost added here for scrolling the first line by
- a distance N includes the overhead of setting the
- scroll window, the cost of inserting N lines at a
- position N lines above the bottom line of the window,
- and an extra cost which is proportional to N. */
- cost += scroll_overhead + first_insert_cost[-delta] +
- (delta-1) * (next_insert_cost[-delta] + extra_cost);
-
- /* In the most general case, the insertion overhead and
- the multiply factor can grow linearly as the distance
- from the bottom of the window increases. The incremental
- cost of scrolling an additional line depends upon the
- rate of change of these two parameters. Each of these
- growth rates can be determined by a simple difference.
- To reduce the cumulative effects of rounding error, we
- vary the position at which the difference is computed. */
- cost1 += first_insert_cost[-j] - first_insert_cost[1-j] +
- (delta-1) * (next_insert_cost[-j] - next_insert_cost[1-j]);
- }
- else
- {
- delta = j - i;
- cost += scroll_overhead + first_delete_cost[-delta] +
- (delta-1) * (next_delete_cost[-delta] + extra_cost);
- cost1 += first_delete_cost[-i] - first_delete_cost[1-i] +
- (delta-1) * ( next_delete_cost[-i] - next_delete_cost[1-i]);
- }
- if (cost1 < cost)
- {
- cost = cost1;
- p->writecount = p1->writecount + 1;
- }
- else
- p->writecount = 1;
- if (old_hash[j] != new_hash[i])
- {
- cost += draw_cost[i] + old_draw_cost[j];
- }
- }
- p->writecost = cost;
-
- /* Calculate the cost if we do an insert-line
- before outputting this line.
- That is, we update through line i-1
- based on old lines through j,
- do an insert-line on line i,
- and then output line i from scratch,
- leaving old lines starting from j for reuse below. */
- p1 = p - window_size - 1; /* matrix [i-1, j] */
- cost = p1->writecost;
- /* If i > j, an insert is allowed after a delete. */
- if (i > j && p1->deletecost < cost)
- cost = p1->deletecost;
- if (p1->insertcost <= cost)
- {
- cost = p1->insertcost;
- p->insertcount = p1->insertcount + 1;
- }
- else
- p->insertcount = 1;
- cost += draw_cost[i];
- p->insertcost = cost;
-
- /* Calculate the cost if we do a delete line after
- outputting this line.
- That is, we update through line i
- based on old lines through j-1,
- and throw away old line j. */
- p1 = p - 1; /* matrix [i, j-1] */
- cost = p1->writecost;
- /* If i < j, a delete is allowed after an insert. */
- if (i < j && p1->insertcost < cost)
- cost = p1->insertcost;
- cost1 = p1->deletecost;
- if (p1->deletecost <= cost)
- {
- cost = p1->deletecost;
- p->deletecount = p1->deletecount + 1;
- }
- else
- p->deletecount = 1;
- p->deletecost = cost;
- }
-}
-
-/* Perform insert-lines and delete-lines operations on FRAME according
- to the costs in MATRIX, using the direct scrolling method.
- Update the frame's current_glyphs info to record what was done.
-
- WINDOW_SIZE is the number of lines being considered for scrolling
- and UNCHANGED_AT_TOP is the vpos of the first line being considered.
- These two arguments can specify any contiguous range of lines.
-
- We also shuffle the charstarts vectors for the lines
- along with the glyphs; but the results are not quite right,
- since we cannot offset them for changes in amount of text
- in this line or that line. Luckily it doesn't matter,
- since update_frame and update_line will copy in the proper
- new charstarts vectors from the frame's desired_glyphs.
-
- In the direct scrolling method, a new scroll window is selected
- before each insertion or deletion, so that groups of lines can be
- scrolled directly to their final vertical positions. This method
- is described in more detail in calculate_direct_scrolling,
- where the cost matrix for this approach is constructed. */
-
-static void
-do_direct_scrolling (frame, matrix, window_size, unchanged_at_top)
- FRAME_PTR frame;
- struct matrix_elt *matrix;
- int window_size;
- int unchanged_at_top;
-{
- register struct matrix_elt *p;
- register int i, j;
- register struct frame_glyphs *current_frame;
- /* temp_frame->enable[i] means line i has been moved to current_frame. */
- register struct frame_glyphs *temp_frame;
- struct alt_queue { int count, pos, window; } *queue;
- int offset = unchanged_at_top;
- int qi = 0;
- int window = 0;
- register int tem;
- int next;
-
- /* A nonzero value of write_follows indicates that a write has been
- selected, allowing either an insert or a delete to be selected next.
- When write_follows is zero, a delete cannot be selected unless j < i,
- and an insert cannot be selected unless i < j. This corresponds to
- a similar restriction (with the ordering reversed) in
- calculate_direct_scrolling, which is intended to ensure that lines
- marked as inserted will be blank. */
- int write_follows = 1;
-
- queue = (struct alt_queue *) alloca (FRAME_HEIGHT (frame)
- * sizeof (struct alt_queue));
-
- current_frame = FRAME_CURRENT_GLYPHS (frame);
- temp_frame = FRAME_TEMP_GLYPHS (frame);
-
- bcopy (current_frame->glyphs, temp_frame->glyphs,
- current_frame->height * sizeof (GLYPH *));
- bcopy (current_frame->charstarts, temp_frame->charstarts,
- current_frame->height * sizeof (GLYPH *));
- bcopy (current_frame->used, temp_frame->used,
- current_frame->height * sizeof (int));
- bcopy (current_frame->highlight, temp_frame->highlight,
- current_frame->height * sizeof (char));
- bzero (temp_frame->enable, temp_frame->height * sizeof (char));
- bcopy (current_frame->bufp, temp_frame->bufp,
- current_frame->height * sizeof (int));
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (frame))
- {
- bcopy (current_frame->top_left_x, temp_frame->top_left_x,
- current_frame->height * sizeof (short));
- bcopy (current_frame->top_left_y, temp_frame->top_left_y,
- current_frame->height * sizeof (short));
- bcopy (current_frame->pix_width, temp_frame->pix_width,
- current_frame->height * sizeof (short));
- bcopy (current_frame->pix_height, temp_frame->pix_height,
- current_frame->height * sizeof (short));
- bcopy (current_frame->max_ascent, temp_frame->max_ascent,
- current_frame->height * sizeof (short));
- }
-#endif
-
- i = j = window_size;
-
- while (i > 0 || j > 0)
- {
- p = matrix + i * (window_size + 1) + j;
- tem = p->insertcost;
- if (tem < p->writecost && tem < p->deletecost
- && (write_follows || i < j))
- {
- /* Insert should be done at vpos i-1, plus maybe some before.
- Setting count to 0 in the queue marks this as an insert. */
- write_follows = 0;
- queue[qi].window = i + unchanged_at_top;
- queue[qi].count = 0;
- i -= p->insertcount;
- queue[qi++].pos = i + unchanged_at_top;
- }
- else if (p->deletecost < p->writecost && (write_follows || i > j))
- {
- /* Delete should be done at vpos j-1, plus maybe some before. */
- write_follows = 0;
- j -= p->deletecount;
- }
- else
- {
- /* One or more lines should be retained. */
- write_follows = 1;
- tem = p->writecount;
- if (i > j)
- {
- /* Immediately scroll a group of lines downward */
- set_terminal_window (i + unchanged_at_top);
- window = 1;
- ins_del_lines (j - tem + unchanged_at_top, i - j);
- }
- else if (i < j)
- {
- /* Queue the upward scrolling of a group of lines */
- queue[qi].pos = i - tem + unchanged_at_top;
- queue[qi].window = j + unchanged_at_top;
- queue[qi++].count = i - j;
- }
-
- /* Now copy the line-contents strings */
- while (tem > 0)
- {
- i--;
- j--;
- tem--;
- current_frame->glyphs[i + offset]
- = temp_frame->glyphs[j + offset];
- current_frame->charstarts[i + offset]
- = temp_frame->charstarts[j + offset];
- current_frame->used[i + offset]
- = temp_frame->used[j + offset];
- current_frame->highlight[i + offset]
- = temp_frame->highlight[j + offset];
-
- temp_frame->enable[j + offset] = 1;
- }
- }
- }
-
- /* Now do all the upward scrolling, and copy the line-contents
- strings for the blank lines of the recorded inserts. */
-
- next = unchanged_at_top;
- for (i = qi - 1; i >= 0; i--)
- {
- if (queue[i].count)
- {
- set_terminal_window (queue[i].window);
- window = 1;
- ins_del_lines (queue[i].pos, queue[i].count);
- }
- else
- {
- /* 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_frame->enable was not set. */
- tem = queue[i].pos;
- for (j = queue[i].window - 1; j >= tem; j--)
- {
- current_frame->enable[j] = 0;
- while (temp_frame->enable[next])
- next++;
- current_frame->glyphs[j] = temp_frame->glyphs[next];
- current_frame->charstarts[j] = temp_frame->charstarts[next++];
- }
- }
- }
-
- if (window)
- set_terminal_window (0);
-}
-
-void
-scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
- draw_cost, old_draw_cost, old_hash, new_hash, free_at_end)
- FRAME_PTR frame;
- int window_size, unchanged_at_top, unchanged_at_bottom;
- int *draw_cost;
- int *old_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));
-
- if (scroll_region_ok)
- {
- calculate_direct_scrolling (frame, matrix, window_size,
- unchanged_at_bottom,
- draw_cost, old_draw_cost,
- old_hash, new_hash, free_at_end);
- do_direct_scrolling (frame, matrix, window_size, unchanged_at_top);
- }
- else
- {
- calculate_scrolling (frame, matrix, window_size, unchanged_at_bottom,
- draw_cost, old_hash, new_hash,
- free_at_end);
- do_scrolling (frame, matrix, window_size, unchanged_at_top);
- }
-}
-
-/* Return number of lines in common between current and desired frame 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
- avoiding redrawing such a line will have little weight. */
-
-int
-scrolling_max_lines_saved (start, end, oldhash, newhash, cost)
- int start, end;
- int *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. */
- for (i = start; i < end; i++)
- {
- if (cost[i] > threshold)
- {
- h = newhash[i] & 0777;
- lines[h].hash = newhash[i];
- lines[h].count++;
- }
- }
-
- /* Look up old line hash codes in the hash table.
- Count number of matches between old lines and new. */
-
- for (i = start; i < end; i++)
- {
- h = oldhash[i] & 0777;
- if (oldhash[i] == lines[h].hash)
- {
- matchcount++;
- if (--lines[h].count == 0)
- lines[h].hash = 0;
- }
- }
-
- return matchcount;
-}
-
-/* Return a measure of the cost of moving the lines
- starting with vpos FROM, up to but not including vpos TO,
- down by AMOUNT lines (AMOUNT may be negative).
- These are the same arguments that might be given to
- scroll_frame_lines to perform this scrolling. */
-
-scroll_cost (frame, from, to, amount)
- FRAME_PTR frame;
- int from, to, amount;
-{
- /* Compute how many lines, at bottom of frame,
- will not be involved in actual motion. */
- int limit = to;
- int offset;
- int height = FRAME_HEIGHT (frame);
-
- if (amount == 0)
- return 0;
-
- if (! scroll_region_ok)
- limit = height;
- else if (amount > 0)
- limit += amount;
-
- if (amount < 0)
- {
- int temp = to;
- to = from + amount;
- from = temp + amount;
- amount = - amount;
- }
-
- offset = height - limit;
-
- return
- (FRAME_INSERT_COST (frame)[offset + from]
- + (amount - 1) * FRAME_INSERTN_COST (frame)[offset + from]
- + FRAME_DELETE_COST (frame)[offset + to]
- + (amount - 1) * FRAME_DELETEN_COST (frame)[offset + to]);
-}
-
-/* Calculate the line insertion/deletion
- overhead and multiply factor values */
-
-static void
-line_ins_del (frame, ov1, pf1, ovn, pfn, ov, mf)
- FRAME_PTR frame;
- int ov1, ovn;
- int pf1, pfn;
- register int *ov, *mf;
-{
- register int i;
- register int frame_height = FRAME_HEIGHT (frame);
- register int insert_overhead = ov1 * 10;
- register int next_insert_cost = ovn * 10;
-
- for (i = frame_height-1; i >= 0; i--)
- {
- mf[i] = next_insert_cost / 10;
- next_insert_cost += pfn;
- ov[i] = (insert_overhead + next_insert_cost) / 10;
- insert_overhead += pf1;
- }
-}
-
-static void
-ins_del_costs (frame,
- one_line_string, multi_string,
- setup_string, cleanup_string,
- costvec, ncostvec, coefficient)
- FRAME_PTR frame;
- char *one_line_string, *multi_string;
- char *setup_string, *cleanup_string;
- int *costvec, *ncostvec;
- int coefficient;
-{
- if (multi_string)
- line_ins_del (frame,
- string_cost (multi_string) * coefficient,
- per_line_cost (multi_string) * coefficient,
- 0, 0, costvec, ncostvec);
- else if (one_line_string)
- line_ins_del (frame,
- 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 (frame,
- 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 frame 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
- costs: the "once-only" and the "repeated". This is to handle both
- those terminals that are able to insert N lines at a time (once-
- only) and those that must repeatedly insert one line.
-
- The cost to insert N lines at line L is
- [tt.t_ILov + (frame_height + 1 - L) * tt.t_ILpf] +
- N * [tt.t_ILnov + (frame_height + 1 - L) * tt.t_ILnpf]
-
- ILov represents the basic insert line overhead. ILpf is the padding
- required to allow the terminal time to move a line: insertion at line
- L changes (frame_height + 1 - L) lines.
-
- 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
- FRAME_INSERT_COST (frame) and the multiply factor in
- FRAME_INSERTN_COST (frame). Note however that any insertion
- must include at least one multiply factor. Rather than compute this
- as FRAME_INSERT_COST (frame)[line]+FRAME_INSERTN_COST (frame)[line],
- we add FRAME_INSERTN_COST (frame) into FRAME_INSERT_COST (frame).
- This is reasonable because of the particular algorithm used in calcM.
-
- Deletion is essentially the same as insertion.
- */
-
-do_line_insertion_deletion_costs (frame,
- ins_line_string, multi_ins_string,
- del_line_string, multi_del_string,
- setup_string, cleanup_string, coefficient)
- FRAME_PTR frame;
- char *ins_line_string, *multi_ins_string;
- char *del_line_string, *multi_del_string;
- char *setup_string, *cleanup_string;
- int coefficient;
-{
- if (FRAME_INSERT_COST (frame) != 0)
- {
- FRAME_INSERT_COST (frame) =
- (int *) xrealloc (FRAME_INSERT_COST (frame),
- FRAME_HEIGHT (frame) * sizeof (int));
- FRAME_DELETEN_COST (frame) =
- (int *) xrealloc (FRAME_DELETEN_COST (frame),
- FRAME_HEIGHT (frame) * sizeof (int));
- FRAME_INSERTN_COST (frame) =
- (int *) xrealloc (FRAME_INSERTN_COST (frame),
- FRAME_HEIGHT (frame) * sizeof (int));
- FRAME_DELETE_COST (frame) =
- (int *) xrealloc (FRAME_DELETE_COST (frame),
- FRAME_HEIGHT (frame) * sizeof (int));
- }
- else
- {
- FRAME_INSERT_COST (frame) =
- (int *) xmalloc (FRAME_HEIGHT (frame) * sizeof (int));
- FRAME_DELETEN_COST (frame) =
- (int *) xmalloc (FRAME_HEIGHT (frame) * sizeof (int));
- FRAME_INSERTN_COST (frame) =
- (int *) xmalloc (FRAME_HEIGHT (frame) * sizeof (int));
- FRAME_DELETE_COST (frame) =
- (int *) xmalloc (FRAME_HEIGHT (frame) * sizeof (int));
- }
-
- ins_del_costs (frame,
- ins_line_string, multi_ins_string,
- setup_string, cleanup_string,
- FRAME_INSERT_COST (frame), FRAME_INSERTN_COST (frame),
- coefficient);
- ins_del_costs (frame,
- del_line_string, multi_del_string,
- setup_string, cleanup_string,
- FRAME_DELETE_COST (frame), FRAME_DELETEN_COST (frame),
- coefficient);
-}
diff --git a/src/search.c b/src/search.c
deleted file mode 100644
index 45119e60617..00000000000
--- a/src/search.c
+++ /dev/null
@@ -1,2125 +0,0 @@
-/* String search routines for GNU Emacs.
- Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include "lisp.h"
-#include "syntax.h"
-#include "buffer.h"
-#include "region-cache.h"
-#include "commands.h"
-#include "blockinput.h"
-
-#include <sys/types.h>
-#include "regex.h"
-
-#define REGEXP_CACHE_SIZE 20
-
-/* If the regexp is non-nil, then the buffer contains the compiled form
- of that regexp, suitable for searching. */
-struct regexp_cache
-{
- struct regexp_cache *next;
- Lisp_Object regexp;
- struct re_pattern_buffer buf;
- char fastmap[0400];
- /* Nonzero means regexp was compiled to do full POSIX backtracking. */
- char posix;
-};
-
-/* The instances of that struct. */
-struct regexp_cache searchbufs[REGEXP_CACHE_SIZE];
-
-/* The head of the linked list; points to the most recently used buffer. */
-struct regexp_cache *searchbuf_head;
-
-
-/* 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).
-
- Since the registers are now dynamically allocated, we need to make
- sure not to refer to the Nth register before checking that it has
- been allocated by checking search_regs.num_regs.
-
- The regex code keeps track of whether it has allocated the search
- buffer using bits in the re_pattern_buffer. This means that whenever
- you compile a new pattern, it completely forgets whether it has
- allocated any registers, and will allocate new registers the next
- time you call a searching or matching function. Therefore, we need
- to call re_set_registers after compiling a new pattern or after
- setting the match registers, so that the regex functions will be
- able to free or re-allocate it properly. */
-static struct re_registers search_regs;
-
-/* The buffer in which the last search was performed, or
- Qt if the last search was done in a string;
- Qnil if no searching has been done yet. */
-static Lisp_Object last_thing_searched;
-
-/* error condition signaled when regexp compile_pattern fails */
-
-Lisp_Object Qinvalid_regexp;
-
-static void set_search_regs ();
-static void save_search_regs ();
-
-static int search_buffer ();
-
-static void
-matcher_overflow ()
-{
- error ("Stack overflow in regexp matcher");
-}
-
-#ifdef __STDC__
-#define CONST const
-#else
-#define CONST
-#endif
-
-/* Compile a regexp and signal a Lisp error if anything goes wrong.
- PATTERN is the pattern to compile.
- CP is the place to put the result.
- TRANSLATE is a translation table for ignoring case, or NULL for none.
- REGP is the structure that says where to store the "register"
- values that will result from matching this pattern.
- If it is 0, we should compile the pattern not to record any
- subexpression bounds.
- POSIX is nonzero if we want full backtracking (POSIX style)
- for this pattern. 0 means backtrack only enough to get a valid match. */
-
-static void
-compile_pattern_1 (cp, pattern, translate, regp, posix)
- struct regexp_cache *cp;
- Lisp_Object pattern;
- Lisp_Object *translate;
- struct re_registers *regp;
- int posix;
-{
- CONST char *val;
- reg_syntax_t old;
-
- cp->regexp = Qnil;
- cp->buf.translate = translate;
- cp->posix = posix;
- BLOCK_INPUT;
- old = re_set_syntax (RE_SYNTAX_EMACS
- | (posix ? 0 : RE_NO_POSIX_BACKTRACKING));
- val = (CONST char *) re_compile_pattern ((char *) XSTRING (pattern)->data,
- XSTRING (pattern)->size, &cp->buf);
- re_set_syntax (old);
- UNBLOCK_INPUT;
- if (val)
- Fsignal (Qinvalid_regexp, Fcons (build_string (val), Qnil));
-
- cp->regexp = Fcopy_sequence (pattern);
-}
-
-/* Compile a regexp if necessary, but first check to see if there's one in
- the cache.
- PATTERN is the pattern to compile.
- TRANSLATE is a translation table for ignoring case, or NULL for none.
- REGP is the structure that says where to store the "register"
- values that will result from matching this pattern.
- If it is 0, we should compile the pattern not to record any
- subexpression bounds.
- POSIX is nonzero if we want full backtracking (POSIX style)
- for this pattern. 0 means backtrack only enough to get a valid match. */
-
-struct re_pattern_buffer *
-compile_pattern (pattern, regp, translate, posix)
- Lisp_Object pattern;
- struct re_registers *regp;
- Lisp_Object *translate;
- int posix;
-{
- struct regexp_cache *cp, **cpp;
-
- for (cpp = &searchbuf_head; ; cpp = &cp->next)
- {
- cp = *cpp;
- if (XSTRING (cp->regexp)->size == XSTRING (pattern)->size
- && !NILP (Fstring_equal (cp->regexp, pattern))
- && cp->buf.translate == translate
- && cp->posix == posix)
- break;
-
- /* If we're at the end of the cache, compile into the last cell. */
- if (cp->next == 0)
- {
- compile_pattern_1 (cp, pattern, translate, regp, posix);
- break;
- }
- }
-
- /* When we get here, cp (aka *cpp) contains the compiled pattern,
- either because we found it in the cache or because we just compiled it.
- Move it to the front of the queue to mark it as most recently used. */
- *cpp = cp->next;
- cp->next = searchbuf_head;
- searchbuf_head = cp;
-
- /* Advise the searching functions about the space we have allocated
- for register data. */
- if (regp)
- re_set_registers (&cp->buf, regp, regp->num_regs, regp->start, regp->end);
-
- return &cp->buf;
-}
-
-/* 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;
-}
-
-static Lisp_Object
-looking_at_1 (string, posix)
- Lisp_Object string;
- int posix;
-{
- Lisp_Object val;
- unsigned char *p1, *p2;
- int s1, s2;
- register int i;
- struct re_pattern_buffer *bufp;
-
- if (running_asynch_code)
- save_search_regs ();
-
- CHECK_STRING (string, 0);
- bufp = compile_pattern (string, &search_regs,
- (!NILP (current_buffer->case_fold_search)
- ? DOWNCASE_TABLE : 0),
- posix);
-
- 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;
- }
-
- i = re_match_2 (bufp, (char *) p1, s1, (char *) p2, s2,
- PT - BEGV, &search_regs,
- ZV - BEGV);
- if (i == -2)
- matcher_overflow ();
-
- val = (0 <= i ? Qt : Qnil);
- for (i = 0; i < search_regs.num_regs; i++)
- if (search_regs.start[i] >= 0)
- {
- search_regs.start[i] += BEGV;
- search_regs.end[i] += BEGV;
- }
- XSETBUFFER (last_thing_searched, current_buffer);
- immediate_quit = 0;
- return val;
-}
-
-DEFUN ("looking-at", Flooking_at, Slooking_at, 1, 1, 0,
- "Return t if text after point matches regular expression REGEXP.\n\
-This function modifies the match data that `match-beginning',\n\
-`match-end' and `match-data' access; save and restore the match\n\
-data if you want to preserve them.")
- (regexp)
- Lisp_Object regexp;
-{
- return looking_at_1 (regexp, 0);
-}
-
-DEFUN ("posix-looking-at", Fposix_looking_at, Sposix_looking_at, 1, 1, 0,
- "Return t if text after point matches regular expression REGEXP.\n\
-Find the longest match, in accord with Posix regular expression rules.\n\
-This function modifies the match data that `match-beginning',\n\
-`match-end' and `match-data' access; save and restore the match\n\
-data if you want to preserve them.")
- (regexp)
- Lisp_Object regexp;
-{
- return looking_at_1 (regexp, 1);
-}
-
-static Lisp_Object
-string_match_1 (regexp, string, start, posix)
- Lisp_Object regexp, string, start;
- int posix;
-{
- int val;
- int s;
- struct re_pattern_buffer *bufp;
-
- if (running_asynch_code)
- save_search_regs ();
-
- CHECK_STRING (regexp, 0);
- CHECK_STRING (string, 1);
-
- if (NILP (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);
- }
-
- bufp = compile_pattern (regexp, &search_regs,
- (!NILP (current_buffer->case_fold_search)
- ? DOWNCASE_TABLE : 0),
- posix);
- immediate_quit = 1;
- val = re_search (bufp, (char *) XSTRING (string)->data,
- XSTRING (string)->size, s, XSTRING (string)->size - s,
- &search_regs);
- immediate_quit = 0;
- last_thing_searched = Qt;
- if (val == -2)
- matcher_overflow ();
- if (val < 0) return Qnil;
- return make_number (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;
-{
- return string_match_1 (regexp, string, start, 0);
-}
-
-DEFUN ("posix-string-match", Fposix_string_match, Sposix_string_match, 2, 3, 0,
- "Return index of start of first match for REGEXP in STRING, or nil.\n\
-Find the longest match, in accord with Posix regular expression rules.\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;
-{
- return string_match_1 (regexp, string, start, 1);
-}
-
-/* Match REGEXP against STRING, searching all of STRING,
- and return the index of the match, or negative on failure.
- This does not clobber the match data. */
-
-int
-fast_string_match (regexp, string)
- Lisp_Object regexp, string;
-{
- int val;
- struct re_pattern_buffer *bufp;
-
- bufp = compile_pattern (regexp, 0, 0, 0);
- immediate_quit = 1;
- val = re_search (bufp, (char *) XSTRING (string)->data,
- XSTRING (string)->size, 0, XSTRING (string)->size,
- 0);
- immediate_quit = 0;
- return val;
-}
-
-/* max and min. */
-
-static int
-max (a, b)
- int a, b;
-{
- return ((a > b) ? a : b);
-}
-
-static int
-min (a, b)
- int a, b;
-{
- return ((a < b) ? a : b);
-}
-
-
-/* The newline cache: remembering which sections of text have no newlines. */
-
-/* If the user has requested newline caching, make sure it's on.
- Otherwise, make sure it's off.
- This is our cheezy way of associating an action with the change of
- state of a buffer-local variable. */
-static void
-newline_cache_on_off (buf)
- struct buffer *buf;
-{
- if (NILP (buf->cache_long_line_scans))
- {
- /* It should be off. */
- if (buf->newline_cache)
- {
- free_region_cache (buf->newline_cache);
- buf->newline_cache = 0;
- }
- }
- else
- {
- /* It should be on. */
- if (buf->newline_cache == 0)
- buf->newline_cache = new_region_cache ();
- }
-}
-
-
-/* Search for COUNT instances of the character TARGET between START and END.
-
- If COUNT is positive, search forwards; END must be >= START.
- If COUNT is negative, search backwards for the -COUNTth instance;
- END must be <= START.
- If COUNT is zero, do anything you please; run rogue, for all I care.
-
- If END is zero, use BEGV or ZV instead, as appropriate for the
- direction indicated by COUNT.
-
- If we find COUNT instances, set *SHORTAGE to zero, and return the
- position after the COUNTth match. Note that for reverse motion
- this is not the same as the usual convention for Emacs motion commands.
-
- If we don't find COUNT instances before reaching END, set *SHORTAGE
- to the number of TARGETs left unfound, and return END.
-
- If ALLOW_QUIT is non-zero, set immediate_quit. That's good to do
- except when inside redisplay. */
-
-scan_buffer (target, start, end, count, shortage, allow_quit)
- register int target;
- int start, end;
- int count;
- int *shortage;
- int allow_quit;
-{
- struct region_cache *newline_cache;
- int direction;
-
- if (count > 0)
- {
- direction = 1;
- if (! end) end = ZV;
- }
- else
- {
- direction = -1;
- if (! end) end = BEGV;
- }
-
- newline_cache_on_off (current_buffer);
- newline_cache = current_buffer->newline_cache;
-
- if (shortage != 0)
- *shortage = 0;
-
- immediate_quit = allow_quit;
-
- if (count > 0)
- while (start != end)
- {
- /* Our innermost scanning loop is very simple; it doesn't know
- about gaps, buffer ends, or the newline cache. ceiling is
- the position of the last character before the next such
- obstacle --- the last character the dumb search loop should
- examine. */
- register int ceiling = end - 1;
-
- /* If we're looking for a newline, consult the newline cache
- to see where we can avoid some scanning. */
- if (target == '\n' && newline_cache)
- {
- int next_change;
- immediate_quit = 0;
- while (region_cache_forward
- (current_buffer, newline_cache, start, &next_change))
- start = next_change;
- immediate_quit = allow_quit;
-
- /* start should never be after end. */
- if (start >= end)
- start = end - 1;
-
- /* Now the text after start is an unknown region, and
- next_change is the position of the next known region. */
- ceiling = min (next_change - 1, ceiling);
- }
-
- /* The dumb loop can only scan text stored in contiguous
- bytes. BUFFER_CEILING_OF returns the last character
- position that is contiguous, so the ceiling is the
- position after that. */
- ceiling = min (BUFFER_CEILING_OF (start), ceiling);
-
- {
- /* The termination address of the dumb loop. */
- register unsigned char *ceiling_addr = &FETCH_CHAR (ceiling) + 1;
- register unsigned char *cursor = &FETCH_CHAR (start);
- unsigned char *base = cursor;
-
- while (cursor < ceiling_addr)
- {
- unsigned char *scan_start = cursor;
-
- /* The dumb loop. */
- while (*cursor != target && ++cursor < ceiling_addr)
- ;
-
- /* If we're looking for newlines, cache the fact that
- the region from start to cursor is free of them. */
- if (target == '\n' && newline_cache)
- know_region_cache (current_buffer, newline_cache,
- start + scan_start - base,
- start + cursor - base);
-
- /* Did we find the target character? */
- if (cursor < ceiling_addr)
- {
- if (--count == 0)
- {
- immediate_quit = 0;
- return (start + cursor - base + 1);
- }
- cursor++;
- }
- }
-
- start += cursor - base;
- }
- }
- else
- while (start > end)
- {
- /* The last character to check before the next obstacle. */
- register int ceiling = end;
-
- /* Consult the newline cache, if appropriate. */
- if (target == '\n' && newline_cache)
- {
- int next_change;
- immediate_quit = 0;
- while (region_cache_backward
- (current_buffer, newline_cache, start, &next_change))
- start = next_change;
- immediate_quit = allow_quit;
-
- /* Start should never be at or before end. */
- if (start <= end)
- start = end + 1;
-
- /* Now the text before start is an unknown region, and
- next_change is the position of the next known region. */
- ceiling = max (next_change, ceiling);
- }
-
- /* Stop scanning before the gap. */
- ceiling = max (BUFFER_FLOOR_OF (start - 1), ceiling);
-
- {
- /* The termination address of the dumb loop. */
- register unsigned char *ceiling_addr = &FETCH_CHAR (ceiling);
- register unsigned char *cursor = &FETCH_CHAR (start - 1);
- unsigned char *base = cursor;
-
- while (cursor >= ceiling_addr)
- {
- unsigned char *scan_start = cursor;
-
- while (*cursor != target && --cursor >= ceiling_addr)
- ;
-
- /* If we're looking for newlines, cache the fact that
- the region from after the cursor to start is free of them. */
- if (target == '\n' && newline_cache)
- know_region_cache (current_buffer, newline_cache,
- start + cursor - base,
- start + scan_start - base);
-
- /* Did we find the target character? */
- if (cursor >= ceiling_addr)
- {
- if (++count >= 0)
- {
- immediate_quit = 0;
- return (start + cursor - base);
- }
- cursor--;
- }
- }
-
- start += cursor - base;
- }
- }
-
- immediate_quit = 0;
- if (shortage != 0)
- *shortage = count * direction;
- return start;
-}
-
-int
-find_next_newline_no_quit (from, cnt)
- register int from, cnt;
-{
- return scan_buffer ('\n', from, 0, cnt, (int *) 0, 0);
-}
-
-int
-find_next_newline (from, cnt)
- register int from, cnt;
-{
- return scan_buffer ('\n', from, 0, cnt, (int *) 0, 1);
-}
-
-
-/* Like find_next_newline, but returns position before the newline,
- not after, and only search up to TO. This isn't just
- find_next_newline (...)-1, because you might hit TO. */
-int
-find_before_next_newline (from, to, cnt)
- int from, to, cnt;
-{
- int shortage;
- int pos = scan_buffer ('\n', from, to, cnt, &shortage, 1);
-
- if (shortage == 0)
- pos--;
-
- return pos;
-}
-
-Lisp_Object skip_chars ();
-
-DEFUN ("skip-chars-forward", Fskip_chars_forward, Sskip_chars_forward, 1, 2, 0,
- "Move point forward, stopping before a char not in STRING, or at pos LIM.\n\
-STRING 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.\n\
-Returns the distance traveled, either zero or positive.")
- (string, lim)
- Lisp_Object string, lim;
-{
- return skip_chars (1, 0, string, lim);
-}
-
-DEFUN ("skip-chars-backward", Fskip_chars_backward, Sskip_chars_backward, 1, 2, 0,
- "Move point backward, stopping after a char not in STRING, or at pos LIM.\n\
-See `skip-chars-forward' for details.\n\
-Returns the distance traveled, either zero or negative.")
- (string, lim)
- Lisp_Object string, lim;
-{
- return skip_chars (0, 0, string, lim);
-}
-
-DEFUN ("skip-syntax-forward", Fskip_syntax_forward, Sskip_syntax_forward, 1, 2, 0,
- "Move point forward across chars in specified syntax classes.\n\
-SYNTAX is a string of syntax code characters.\n\
-Stop before a char whose syntax is not in SYNTAX, or at position LIM.\n\
-If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\
-This function returns the distance traveled, either zero or positive.")
- (syntax, lim)
- Lisp_Object syntax, lim;
-{
- return skip_chars (1, 1, syntax, lim);
-}
-
-DEFUN ("skip-syntax-backward", Fskip_syntax_backward, Sskip_syntax_backward, 1, 2, 0,
- "Move point backward across chars in specified syntax classes.\n\
-SYNTAX is a string of syntax code characters.\n\
-Stop on reaching a char whose syntax is not in SYNTAX, or at position LIM.\n\
-If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\
-This function returns the distance traveled, either zero or negative.")
- (syntax, lim)
- Lisp_Object syntax, lim;
-{
- return skip_chars (0, 1, syntax, lim);
-}
-
-Lisp_Object
-skip_chars (forwardp, syntaxp, string, lim)
- int forwardp, syntaxp;
- 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 (NILP (lim))
- XSETINT (lim, forwardp ? ZV : BEGV);
- else
- CHECK_NUMBER_COERCE_MARKER (lim, 1);
-
- /* In any case, don't allow scan outside bounds of buffer. */
- /* jla turned this off, for no known reason.
- bfox turned the ZV part on, and rms turned the
- BEGV part back on. */
- if (XINT (lim) > ZV)
- XSETFASTINT (lim, ZV);
- if (XINT (lim) < BEGV)
- XSETFASTINT (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.
- If syntaxp, each character counts as itself.
- Otherwise, handle backslashes and ranges specially */
-
- while (p != pend)
- {
- c = *p++;
- if (syntaxp)
- fastmap[c] = 1;
- else
- {
- 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 (syntaxp && fastmap['-'] != 0)
- fastmap[' '] = 1;
-
- /* If ^ was the first character, complement the fastmap. */
-
- if (negate)
- for (i = 0; i < sizeof fastmap; i++)
- fastmap[i] ^= 1;
-
- {
- int start_point = PT;
-
- immediate_quit = 1;
- if (syntaxp)
- {
-
- if (forwardp)
- {
- while (PT < XINT (lim)
- && fastmap[(unsigned char) syntax_code_spec[(int) SYNTAX (FETCH_CHAR (PT))]])
- SET_PT (PT + 1);
- }
- else
- {
- while (PT > XINT (lim)
- && fastmap[(unsigned char) syntax_code_spec[(int) SYNTAX (FETCH_CHAR (PT - 1))]])
- SET_PT (PT - 1);
- }
- }
- else
- {
- if (forwardp)
- {
- while (PT < XINT (lim) && fastmap[FETCH_CHAR (PT)])
- SET_PT (PT + 1);
- }
- else
- {
- while (PT > XINT (lim) && fastmap[FETCH_CHAR (PT - 1)])
- SET_PT (PT - 1);
- }
- }
- immediate_quit = 0;
-
- return make_number (PT - start_point);
- }
-}
-
-/* Subroutines of Lisp buffer search functions. */
-
-static Lisp_Object
-search_command (string, bound, noerror, count, direction, RE, posix)
- Lisp_Object string, bound, noerror, count;
- int direction;
- int RE;
- int posix;
-{
- register int np;
- int lim;
- int n = direction;
-
- if (!NILP (count))
- {
- CHECK_NUMBER (count, 3);
- n *= XINT (count);
- }
-
- CHECK_STRING (string, 0);
- if (NILP (bound))
- lim = n > 0 ? ZV : BEGV;
- else
- {
- CHECK_NUMBER_COERCE_MARKER (bound, 1);
- lim = XINT (bound);
- if (n > 0 ? lim < PT : lim > PT)
- error ("Invalid search bound (wrong side of point)");
- if (lim > ZV)
- lim = ZV;
- if (lim < BEGV)
- lim = BEGV;
- }
-
- np = search_buffer (string, PT, lim, n, RE,
- (!NILP (current_buffer->case_fold_search)
- ? XCHAR_TABLE (current_buffer->case_canon_table)->contents
- : 0),
- (!NILP (current_buffer->case_fold_search)
- ? XCHAR_TABLE (current_buffer->case_eqv_table)->contents
- : 0),
- posix);
- if (np <= 0)
- {
- if (NILP (noerror))
- return signal_failure (string);
- if (!EQ (noerror, Qt))
- {
- if (lim < BEGV || lim > ZV)
- abort ();
- SET_PT (lim);
- return Qnil;
-#if 0 /* This would be clean, but maybe programs depend on
- a value of nil here. */
- np = lim;
-#endif
- }
- else
- return Qnil;
- }
-
- if (np < BEGV || np > ZV)
- abort ();
-
- SET_PT (np);
-
- return make_number (np);
-}
-
-static int
-trivial_regexp_p (regexp)
- Lisp_Object regexp;
-{
- int len = XSTRING (regexp)->size;
- unsigned char *s = XSTRING (regexp)->data;
- unsigned char c;
- while (--len >= 0)
- {
- switch (*s++)
- {
- case '.': case '*': case '+': case '?': case '[': case '^': case '$':
- return 0;
- case '\\':
- if (--len < 0)
- return 0;
- switch (*s++)
- {
- case '|': case '(': case ')': case '`': case '\'': case 'b':
- case 'B': case '<': case '>': case 'w': case 'W': case 's':
- case 'S': case '=':
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- return 0;
- }
- }
- }
- return 1;
-}
-
-/* Search for the n'th occurrence of STRING in the current buffer,
- starting at position POS and stopping at position LIM,
- treating STRING 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 POS.
- If N is negative, searching is backward and LIM must be less than POS.
-
- Returns -x if only N-x occurrences found (x > 0),
- or else the position at the beginning of the Nth occurrence
- (if searching backward) or the end (if searching forward).
-
- POSIX is nonzero if we want full backtracking (POSIX style)
- for this pattern. 0 means backtrack only enough to get a valid match. */
-
-static int
-search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
- Lisp_Object string;
- int pos;
- int lim;
- int n;
- int RE;
- Lisp_Object *trt;
- Lisp_Object *inverse_trt;
- int posix;
-{
- 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 (running_asynch_code)
- save_search_regs ();
-
- /* Null string is found at starting position. */
- if (len == 0)
- {
- set_search_regs (pos, 0);
- return pos;
- }
-
- /* Searching 0 times means don't move. */
- if (n == 0)
- return pos;
-
- if (RE && !trivial_regexp_p (string))
- {
- struct re_pattern_buffer *bufp;
-
- bufp = compile_pattern (string, &search_regs, trt, posix);
-
- 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 val;
- val = re_search_2 (bufp, (char *) p1, s1, (char *) p2, s2,
- pos - BEGV, lim - pos, &search_regs,
- /* Don't allow match past current point */
- pos - BEGV);
- if (val == -2)
- {
- matcher_overflow ();
- }
- if (val >= 0)
- {
- j = BEGV;
- for (i = 0; i < search_regs.num_regs; i++)
- if (search_regs.start[i] >= 0)
- {
- search_regs.start[i] += j;
- search_regs.end[i] += j;
- }
- XSETBUFFER (last_thing_searched, current_buffer);
- /* Set pos to the new position. */
- pos = search_regs.start[0];
- }
- else
- {
- immediate_quit = 0;
- return (n);
- }
- n++;
- }
- while (n > 0)
- {
- int val;
- val = re_search_2 (bufp, (char *) p1, s1, (char *) p2, s2,
- pos - BEGV, lim - pos, &search_regs,
- lim - BEGV);
- if (val == -2)
- {
- matcher_overflow ();
- }
- if (val >= 0)
- {
- j = BEGV;
- for (i = 0; i < search_regs.num_regs; i++)
- if (search_regs.start[i] >= 0)
- {
- search_regs.start[i] += j;
- search_regs.end[i] += j;
- }
- XSETBUFFER (last_thing_searched, current_buffer);
- 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
- {
- unsigned char *patbuf = (unsigned char *) alloca (len);
- pat = patbuf;
- while (--len >= 0)
- {
- /* If we got here and the RE flag is set, it's because we're
- dealing with a regexp known to be trivial, so the backslash
- just quotes the next character. */
- if (RE && *base_pat == '\\')
- {
- len--;
- base_pat++;
- }
- *pat++ = (trt ? trt[*base_pat++] : *base_pat++);
- }
- len = pat - patbuf;
- pat = base_pat = patbuf;
- }
- /* 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 (trt != 0)
- {
- k = (j = trt[j]);
- if (i == infinity)
- stride_for_teases = BM_tab[j];
- BM_tab[j] = dirlen - i;
- /* A translation table is accompanied by its inverse -- see */
- /* comment following downcase_table for details */
- while ((j = (unsigned char) inverse_trt[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)
- {
- /* It's been reported that some (broken) compiler thinks that
- Boolean expressions in an arithmetic context are unsigned.
- Using an explicit ?1:0 prevents this. */
- if ((lim - pos - ((direction > 0) ? 1 : 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)
- ? BUFFER_CEILING_OF (limit)
- : BUFFER_FLOOR_OF (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 ((EMACS_INT) (p_limit + infinity) > (EMACS_INT) p_limit)
- while ((EMACS_INT) cursor <= (EMACS_INT) p_limit)
- cursor += BM_tab[*cursor];
- else
- while ((EMACS_UINT) cursor <= (EMACS_UINT) p_limit)
- cursor += BM_tab[*cursor];
- }
- else
- {
- if ((EMACS_INT) (p_limit + infinity) < (EMACS_INT) p_limit)
- while ((EMACS_INT) cursor >= (EMACS_INT) p_limit)
- cursor += BM_tab[*cursor];
- else
- while ((EMACS_UINT) cursor >= (EMACS_UINT) 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 (trt != 0)
- {
- 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;
-
- set_search_regs (pos + cursor - p2 + ((direction > 0)
- ? 1 - len : 0),
- len);
-
- 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)
- ? BUFFER_CEILING_OF (pos - dirlen + 1)
- : BUFFER_FLOOR_OF (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 phony 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] != (trt != 0
- ? 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;
-
- set_search_regs (pos + ((direction > 0) ? 1 - len : 0),
- len);
-
- 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;
- }
-}
-
-/* Record beginning BEG and end BEG + LEN
- for a match just found in the current buffer. */
-
-static void
-set_search_regs (beg, len)
- int beg, len;
-{
- /* Make sure we have registers in which to store
- the match position. */
- if (search_regs.num_regs == 0)
- {
- search_regs.start = (regoff_t *) xmalloc (2 * sizeof (regoff_t));
- search_regs.end = (regoff_t *) xmalloc (2 * sizeof (regoff_t));
- search_regs.num_regs = 2;
- }
-
- search_regs.start[0] = beg;
- search_regs.end[0] = beg + len;
- XSETBUFFER (last_thing_searched, current_buffer);
-}
-
-/* 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 point.\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', `match-end' and `replace-match'.")
- (string, bound, noerror, count)
- Lisp_Object string, bound, noerror, count;
-{
- return search_command (string, bound, noerror, count, -1, 0, 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 point.\n\
-An optional second argument bounds the search; it is a buffer position.\n\
-The match found must not extend after that position. nil is equivalent\n\
- to (point-max).\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', `match-end' and `replace-match'.")
- (string, bound, noerror, count)
- Lisp_Object string, bound, noerror, count;
-{
- return search_command (string, bound, noerror, count, 1, 0, 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 point.\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, 0);
-}
-
-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 point.\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, 0);
-}
-
-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 point.\n\
-The match found is the one starting last in the buffer\n\
-and yet ending before 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', `match-end' and `replace-match'.")
- (regexp, bound, noerror, count)
- Lisp_Object regexp, bound, noerror, count;
-{
- return search_command (regexp, bound, noerror, count, -1, 1, 0);
-}
-
-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 point.\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', `match-end' and `replace-match'.")
- (regexp, bound, noerror, count)
- Lisp_Object regexp, bound, noerror, count;
-{
- return search_command (regexp, bound, noerror, count, 1, 1, 0);
-}
-
-DEFUN ("posix-search-backward", Fposix_search_backward, Sposix_search_backward, 1, 4,
- "sPosix search backward: ",
- "Search backward from point for match for regular expression REGEXP.\n\
-Find the longest match in accord with Posix regular expression rules.\n\
-Set point to the beginning of the match, and return point.\n\
-The match found is the one starting last in the buffer\n\
-and yet ending before 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', `match-end' and `replace-match'.")
- (regexp, bound, noerror, count)
- Lisp_Object regexp, bound, noerror, count;
-{
- return search_command (regexp, bound, noerror, count, -1, 1, 1);
-}
-
-DEFUN ("posix-search-forward", Fposix_search_forward, Sposix_search_forward, 1, 4,
- "sPosix search: ",
- "Search forward from point for regular expression REGEXP.\n\
-Find the longest match in accord with Posix regular expression rules.\n\
-Set point to the end of the occurrence found, and return point.\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', `match-end' and `replace-match'.")
- (regexp, bound, noerror, count)
- Lisp_Object regexp, bound, noerror, count;
-{
- return search_command (regexp, bound, noerror, count, 1, 1, 1);
-}
-
-DEFUN ("replace-match", Freplace_match, Sreplace_match, 1, 5, 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 maybe capitalize the whole text, or maybe just word initials,\n\
-based on the replaced text.\n\
-If the replaced text has only capital letters\n\
-and has at least one multiletter word, convert NEWTEXT to all caps.\n\
-If the replaced text has at least one word starting with a capital letter,\n\
-then capitalize each word in NEWTEXT.\n\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 what matched the Nth `\\(...\\)'.\n\
- If Nth parens didn't match, substitute nothing.\n\
- `\\\\' means insert one `\\'.\n\
-FIXEDCASE and LITERAL are optional arguments.\n\
-Leaves point at end of replacement text.\n\
-\n\
-The optional fourth argument STRING can be a string to modify.\n\
-In that case, this function creates and returns a new string\n\
-which is made by replacing the part of STRING that was matched.\n\
-\n\
-The optional fifth argument SUBEXP specifies a subexpression of the match.\n\
-It says to replace just that subexpression instead of the whole match.\n\
-This is useful only after a regular expression search or match\n\
-since only regular expressions have distinguished subexpressions.")
- (newtext, fixedcase, literal, string, subexp)
- Lisp_Object newtext, fixedcase, literal, string, subexp;
-{
- enum { nochange, all_caps, cap_initial } case_action;
- register int pos, last;
- int some_multiletter_word;
- int some_lowercase;
- int some_uppercase;
- int some_nonuppercase_initial;
- register int c, prevc;
- int inslen;
- int sub;
-
- CHECK_STRING (newtext, 0);
-
- if (! NILP (string))
- CHECK_STRING (string, 4);
-
- case_action = nochange; /* We tried an initialization */
- /* but some C compilers blew it */
-
- if (search_regs.num_regs <= 0)
- error ("replace-match called before any match found");
-
- if (NILP (subexp))
- sub = 0;
- else
- {
- CHECK_NUMBER (subexp, 3);
- sub = XINT (subexp);
- if (sub < 0 || sub >= search_regs.num_regs)
- args_out_of_range (subexp, make_number (search_regs.num_regs));
- }
-
- if (NILP (string))
- {
- if (search_regs.start[sub] < BEGV
- || search_regs.start[sub] > search_regs.end[sub]
- || search_regs.end[sub] > ZV)
- args_out_of_range (make_number (search_regs.start[sub]),
- make_number (search_regs.end[sub]));
- }
- else
- {
- if (search_regs.start[sub] < 0
- || search_regs.start[sub] > search_regs.end[sub]
- || search_regs.end[sub] > XSTRING (string)->size)
- args_out_of_range (make_number (search_regs.start[sub]),
- make_number (search_regs.end[sub]));
- }
-
- if (NILP (fixedcase))
- {
- /* Decide how to casify by examining the matched text. */
-
- last = search_regs.end[sub];
- 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;
- some_lowercase = 0;
- some_nonuppercase_initial = 0;
- some_uppercase = 0;
-
- for (pos = search_regs.start[sub]; pos < last; pos++)
- {
- if (NILP (string))
- c = FETCH_CHAR (pos);
- else
- c = XSTRING (string)->data[pos];
-
- if (LOWERCASEP (c))
- {
- /* Cannot be all caps if any original char is lower case */
-
- some_lowercase = 1;
- if (SYNTAX (prevc) != Sword)
- some_nonuppercase_initial = 1;
- else
- some_multiletter_word = 1;
- }
- else if (!NOCASEP (c))
- {
- some_uppercase = 1;
- if (SYNTAX (prevc) != Sword)
- ;
- else
- some_multiletter_word = 1;
- }
- else
- {
- /* If the initial is a caseless word constituent,
- treat that like a lowercase initial. */
- if (SYNTAX (prevc) != Sword)
- some_nonuppercase_initial = 1;
- }
-
- prevc = c;
- }
-
- /* Convert to all caps if the old text is all caps
- and has at least one multiletter word. */
- if (! some_lowercase && some_multiletter_word)
- case_action = all_caps;
- /* Capitalize each word, if the old text has all capitalized words. */
- else if (!some_nonuppercase_initial && some_multiletter_word)
- case_action = cap_initial;
- else if (!some_nonuppercase_initial && some_uppercase)
- /* Should x -> yz, operating on X, give Yz or YZ?
- We'll assume the latter. */
- case_action = all_caps;
- else
- case_action = nochange;
- }
-
- /* Do replacement in a string. */
- if (!NILP (string))
- {
- Lisp_Object before, after;
-
- before = Fsubstring (string, make_number (0),
- make_number (search_regs.start[sub]));
- after = Fsubstring (string, make_number (search_regs.end[sub]), Qnil);
-
- /* Do case substitution into NEWTEXT if desired. */
- if (NILP (literal))
- {
- int lastpos = -1;
- /* We build up the substituted string in ACCUM. */
- Lisp_Object accum;
- Lisp_Object middle;
-
- accum = Qnil;
-
- for (pos = 0; pos < XSTRING (newtext)->size; pos++)
- {
- int substart = -1;
- int subend;
- int delbackslash = 0;
-
- c = XSTRING (newtext)->data[pos];
- if (c == '\\')
- {
- c = XSTRING (newtext)->data[++pos];
- if (c == '&')
- {
- substart = search_regs.start[sub];
- subend = search_regs.end[sub];
- }
- else if (c >= '1' && c <= '9' && c <= search_regs.num_regs + '0')
- {
- if (search_regs.start[c - '0'] >= 0)
- {
- substart = search_regs.start[c - '0'];
- subend = search_regs.end[c - '0'];
- }
- }
- else if (c == '\\')
- delbackslash = 1;
- }
- if (substart >= 0)
- {
- if (pos - 1 != lastpos + 1)
- middle = Fsubstring (newtext,
- make_number (lastpos + 1),
- make_number (pos - 1));
- else
- middle = Qnil;
- accum = concat3 (accum, middle,
- Fsubstring (string, make_number (substart),
- make_number (subend)));
- lastpos = pos;
- }
- else if (delbackslash)
- {
- middle = Fsubstring (newtext, make_number (lastpos + 1),
- make_number (pos));
- accum = concat2 (accum, middle);
- lastpos = pos;
- }
- }
-
- if (pos != lastpos + 1)
- middle = Fsubstring (newtext, make_number (lastpos + 1),
- make_number (pos));
- else
- middle = Qnil;
-
- newtext = concat2 (accum, middle);
- }
-
- if (case_action == all_caps)
- newtext = Fupcase (newtext);
- else if (case_action == cap_initial)
- newtext = Fupcase_initials (newtext);
-
- return concat3 (before, newtext, after);
- }
-
- /* We insert the replacement text before the old text, and then
- delete the original text. This means that markers at the
- beginning or end of the original will float to the corresponding
- position in the replacement. */
- SET_PT (search_regs.start[sub]);
- if (!NILP (literal))
- Finsert_and_inherit (1, &newtext);
- else
- {
- struct gcpro gcpro1;
- GCPRO1 (newtext);
-
- for (pos = 0; pos < XSTRING (newtext)->size; pos++)
- {
- int offset = PT - search_regs.start[sub];
-
- c = XSTRING (newtext)->data[pos];
- if (c == '\\')
- {
- c = XSTRING (newtext)->data[++pos];
- if (c == '&')
- Finsert_buffer_substring
- (Fcurrent_buffer (),
- make_number (search_regs.start[sub] + offset),
- make_number (search_regs.end[sub] + offset));
- else if (c >= '1' && c <= '9' && c <= search_regs.num_regs + '0')
- {
- if (search_regs.start[c - '0'] >= 1)
- Finsert_buffer_substring
- (Fcurrent_buffer (),
- make_number (search_regs.start[c - '0'] + offset),
- make_number (search_regs.end[c - '0'] + offset));
- }
- else
- insert_char (c);
- }
- else
- insert_char (c);
- }
- UNGCPRO;
- }
-
- inslen = PT - (search_regs.start[sub]);
- del_range (search_regs.start[sub] + inslen, search_regs.end[sub] + inslen);
-
- if (case_action == all_caps)
- Fupcase_region (make_number (PT - inslen), make_number (PT));
- else if (case_action == cap_initial)
- Fupcase_initials_region (make_number (PT - inslen), make_number (PT));
- 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 >= search_regs.num_regs)
- args_out_of_range (num, make_number (search_regs.num_regs));
- if (search_regs.num_regs <= 0
- || 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 position of start of text matched by last search.\n\
-SUBEXP, a number, specifies which parenthesized expression in the last\n\
- regexp.\n\
-Value is nil if SUBEXPth pair didn't match, or there were less than\n\
- SUBEXP pairs.\n\
-Zero means the entire text matched by the whole regexp or whole string.")
- (subexp)
- Lisp_Object subexp;
-{
- return match_limit (subexp, 1);
-}
-
-DEFUN ("match-end", Fmatch_end, Smatch_end, 1, 1, 0,
- "Return position of end of text matched by last search.\n\
-SUBEXP, a number, specifies which parenthesized expression in the last\n\
- regexp.\n\
-Value is nil if SUBEXPth pair didn't match, or there were less than\n\
- SUBEXP pairs.\n\
-Zero means the entire text matched by the whole regexp or whole string.")
- (subexp)
- Lisp_Object subexp;
-{
- return match_limit (subexp, 0);
-}
-
-DEFUN ("match-data", Fmatch_data, Smatch_data, 0, 2, 0,
- "Return a 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 markers or nil (nil if the Nth pair didn't match)\n\
-if the last match was on a buffer; integers or nil if a string was matched.\n\
-Use `store-match-data' to reinstate the data in this list.\n\
-\n\
-If INTEGERS (the optional first argument) is non-nil, always use integers\n\
-\(rather than markers) to represent buffer positions.\n\
-If REUSE is a list, reuse it as part of the value. If REUSE is long enough\n\
-to hold all the values, and if INTEGERS is non-nil, no consing is done.")
- (integers, reuse)
- Lisp_Object integers, reuse;
-{
- Lisp_Object tail, prev;
- Lisp_Object *data;
- int i, len;
-
- if (NILP (last_thing_searched))
- return Qnil;
-
- data = (Lisp_Object *) alloca ((2 * search_regs.num_regs)
- * sizeof (Lisp_Object));
-
- len = -1;
- for (i = 0; i < search_regs.num_regs; i++)
- {
- int start = search_regs.start[i];
- if (start >= 0)
- {
- if (EQ (last_thing_searched, Qt)
- || ! NILP (integers))
- {
- XSETFASTINT (data[2 * i], start);
- XSETFASTINT (data[2 * i + 1], search_regs.end[i]);
- }
- else if (BUFFERP (last_thing_searched))
- {
- data[2 * i] = Fmake_marker ();
- Fset_marker (data[2 * i],
- make_number (start),
- last_thing_searched);
- data[2 * i + 1] = Fmake_marker ();
- Fset_marker (data[2 * i + 1],
- make_number (search_regs.end[i]),
- last_thing_searched);
- }
- else
- /* last_thing_searched must always be Qt, a buffer, or Qnil. */
- abort ();
-
- len = i;
- }
- else
- data[2 * i] = data [2 * i + 1] = Qnil;
- }
-
- /* If REUSE is not usable, cons up the values and return them. */
- if (! CONSP (reuse))
- return Flist (2 * len + 2, data);
-
- /* If REUSE is a list, store as many value elements as will fit
- into the elements of REUSE. */
- for (i = 0, tail = reuse; CONSP (tail);
- i++, tail = XCONS (tail)->cdr)
- {
- if (i < 2 * len + 2)
- XCONS (tail)->car = data[i];
- else
- XCONS (tail)->car = Qnil;
- prev = tail;
- }
-
- /* If we couldn't fit all value elements into REUSE,
- cons up the rest of them and add them to the end of REUSE. */
- if (i < 2 * len + 2)
- XCONS (prev)->cdr = Flist (2 * len + 2 - i, data + i);
-
- return reuse;
-}
-
-
-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 (running_asynch_code)
- save_search_regs ();
-
- if (!CONSP (list) && !NILP (list))
- list = wrong_type_argument (Qconsp, list);
-
- /* Unless we find a marker with a buffer in LIST, assume that this
- match data came from a string. */
- last_thing_searched = Qt;
-
- /* Allocate registers if they don't already exist. */
- {
- int length = XFASTINT (Flength (list)) / 2;
-
- if (length > search_regs.num_regs)
- {
- if (search_regs.num_regs == 0)
- {
- search_regs.start
- = (regoff_t *) xmalloc (length * sizeof (regoff_t));
- search_regs.end
- = (regoff_t *) xmalloc (length * sizeof (regoff_t));
- }
- else
- {
- search_regs.start
- = (regoff_t *) xrealloc (search_regs.start,
- length * sizeof (regoff_t));
- search_regs.end
- = (regoff_t *) xrealloc (search_regs.end,
- length * sizeof (regoff_t));
- }
-
- search_regs.num_regs = length;
- }
- }
-
- for (i = 0; i < search_regs.num_regs; i++)
- {
- marker = Fcar (list);
- if (NILP (marker))
- {
- search_regs.start[i] = -1;
- list = Fcdr (list);
- }
- else
- {
- if (MARKERP (marker))
- {
- if (XMARKER (marker)->buffer == 0)
- XSETFASTINT (marker, 0);
- else
- XSETBUFFER (last_thing_searched, XMARKER (marker)->buffer);
- }
-
- CHECK_NUMBER_COERCE_MARKER (marker, 0);
- search_regs.start[i] = XINT (marker);
- list = Fcdr (list);
-
- marker = Fcar (list);
- if (MARKERP (marker) && XMARKER (marker)->buffer == 0)
- XSETFASTINT (marker, 0);
-
- CHECK_NUMBER_COERCE_MARKER (marker, 0);
- search_regs.end[i] = XINT (marker);
- }
- list = Fcdr (list);
- }
-
- return Qnil;
-}
-
-/* If non-zero the match data have been saved in saved_search_regs
- during the execution of a sentinel or filter. */
-static int search_regs_saved;
-static struct re_registers saved_search_regs;
-
-/* Called from Flooking_at, Fstring_match, search_buffer, Fstore_match_data
- if asynchronous code (filter or sentinel) is running. */
-static void
-save_search_regs ()
-{
- if (!search_regs_saved)
- {
- saved_search_regs.num_regs = search_regs.num_regs;
- saved_search_regs.start = search_regs.start;
- saved_search_regs.end = search_regs.end;
- search_regs.num_regs = 0;
- search_regs.start = 0;
- search_regs.end = 0;
-
- search_regs_saved = 1;
- }
-}
-
-/* Called upon exit from filters and sentinels. */
-void
-restore_match_data ()
-{
- if (search_regs_saved)
- {
- if (search_regs.num_regs > 0)
- {
- xfree (search_regs.start);
- xfree (search_regs.end);
- }
- search_regs.num_regs = saved_search_regs.num_regs;
- search_regs.start = saved_search_regs.start;
- search_regs.end = saved_search_regs.end;
-
- search_regs_saved = 0;
- }
-}
-
-/* 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.")
- (string)
- Lisp_Object string;
-{
- register unsigned char *in, *out, *end;
- register unsigned char *temp;
-
- CHECK_STRING (string, 0);
-
- temp = (unsigned char *) alloca (XSTRING (string)->size * 2);
-
- /* Now copy the data into the new string, inserting escapes. */
-
- in = XSTRING (string)->data;
- end = in + XSTRING (string)->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);
-}
-
-syms_of_search ()
-{
- register int i;
-
- for (i = 0; i < REGEXP_CACHE_SIZE; ++i)
- {
- searchbufs[i].buf.allocated = 100;
- searchbufs[i].buf.buffer = (unsigned char *) malloc (100);
- searchbufs[i].buf.fastmap = searchbufs[i].fastmap;
- searchbufs[i].regexp = Qnil;
- staticpro (&searchbufs[i].regexp);
- searchbufs[i].next = (i == REGEXP_CACHE_SIZE-1 ? 0 : &searchbufs[i+1]);
- }
- searchbuf_head = &searchbufs[0];
-
- 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_thing_searched = Qnil;
- staticpro (&last_thing_searched);
-
- defsubr (&Slooking_at);
- defsubr (&Sposix_looking_at);
- defsubr (&Sstring_match);
- defsubr (&Sposix_string_match);
- defsubr (&Sskip_chars_forward);
- defsubr (&Sskip_chars_backward);
- defsubr (&Sskip_syntax_forward);
- defsubr (&Sskip_syntax_backward);
- defsubr (&Ssearch_forward);
- defsubr (&Ssearch_backward);
- defsubr (&Sword_search_forward);
- defsubr (&Sword_search_backward);
- defsubr (&Sre_search_forward);
- defsubr (&Sre_search_backward);
- defsubr (&Sposix_search_forward);
- defsubr (&Sposix_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
deleted file mode 100644
index 1eb6770c83f..00000000000
--- a/src/sink.h
+++ /dev/null
@@ -1,91 +0,0 @@
-#define sink_width 48
-#define sink_height 48
-#ifdef HAVE_X11
-static 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};
-#else
-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};
-#endif /* HAVE_X11 */
diff --git a/src/sink11.h b/src/sink11.h
deleted file mode 100644
index dec0280a72b..00000000000
--- a/src/sink11.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#define sink_width 48
-#define sink_height 48
-static 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
deleted file mode 100644
index b0a6e0c6f35..00000000000
--- a/src/sink11mask.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#define sink_mask_width 48
-#define sink_mask_height 48
-static 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
deleted file mode 100644
index 6453cfbd6f0..00000000000
--- a/src/sinkmask.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#define sinkmask_width 48
-#define sinkmask_height 48
-static char sinkmask_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x60,
- 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f,
- 0x00, 0x00, 0x00, 0x80, 0x01, 0x40, 0x00, 0x00, 0x00, 0x80, 0xfc, 0x5f,
- 0x00, 0x00, 0x00, 0x80, 0x02, 0x50, 0x00, 0x00, 0x00, 0xc0, 0x06, 0x50,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x03, 0x50,
- 0x00, 0x00, 0x00, 0x80, 0x07, 0x50, 0x00, 0x00, 0x00, 0x00, 0x03, 0x50,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x40, 0x08, 0x50,
- 0x00, 0x00, 0x00, 0xc0, 0x0c, 0x50, 0x00, 0x00, 0x00, 0x00, 0x03, 0x50,
- 0xc0, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x80, 0xff, 0xff, 0xff, 0xff, 0x1f,
- 0x20, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x30, 0x06, 0xf0, 0x00, 0x00, 0x18,
- 0x30, 0x06, 0x08, 0x00, 0x00, 0x18, 0x00, 0x06, 0x08, 0x9c, 0x04, 0x18,
- 0x00, 0x06, 0xc8, 0xa5, 0x04, 0x18, 0x30, 0x06, 0x08, 0xa5, 0x04, 0x18,
- 0x30, 0x06, 0x08, 0xa5, 0x06, 0x18, 0x10, 0x06, 0xf0, 0x24, 0x05, 0x18,
- 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x20, 0x06, 0x00, 0x00, 0x00, 0x18,
- 0x30, 0xe6, 0x03, 0x00, 0x00, 0x18, 0x30, 0x26, 0x00, 0x00, 0x00, 0x18,
- 0x00, 0x26, 0xb8, 0x31, 0x8c, 0x19, 0x00, 0xe6, 0x49, 0x4a, 0x52, 0x18,
- 0x30, 0x26, 0x48, 0x4a, 0x82, 0x19, 0x38, 0x26, 0x48, 0x4a, 0x12, 0x1a,
- 0x10, 0xe6, 0x4b, 0xb2, 0x8c, 0x19, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1c,
- 0x00, 0xfc, 0x7f, 0xfc, 0xff, 0x0f, 0x10, 0xf8, 0xff, 0xfe, 0xff, 0x07,
- 0x38, 0x00, 0xc0, 0x06, 0x00, 0x00, 0x18, 0x00, 0x80, 0x02, 0x1f, 0x00,
- 0x00, 0x00, 0x80, 0x82, 0x20, 0x00, 0x00, 0x00, 0x80, 0x42, 0x4e, 0x00,
- 0x00, 0x00, 0x80, 0x44, 0x51, 0x00, 0x10, 0x00, 0x00, 0x25, 0x51, 0x00,
- 0x38, 0x00, 0x00, 0x99, 0x50, 0x00, 0x18, 0x00, 0x00, 0x42, 0x50, 0x00,
- 0x00, 0x00, 0x00, 0x3c, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00};
diff --git a/src/sunfns.c b/src/sunfns.c
deleted file mode 100644
index 6bfa479321d..00000000000
--- a/src/sunfns.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/* Functions for Sun Windows menus and selection buffer.
- Copyright (C) 1987 Free Software Foundation, Inc.
-
-This file is probably totally obsolete. In any case, the FSF is
-unwilling to support it. We agreed to include it in our distribution
-only on the understanding that we would spend no time at all on it.
-
-If you have complaints about this file, send them to peck@sun.com.
-If no one at Sun wants to maintain this, then consider it not
-maintained at all. It would be a bad thing for the GNU project if
-this file took our effort away from higher-priority things.
-
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Author: Jeff Peck, Sun Microsystems, Inc. <peck@sun.com>
-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.
- */
-
-/*
- * Emacs Lisp-Callable functions for sunwindows
- */
-#include <config.h>
-
-#include <stdio.h>
-#include <errno.h>
-#include <signal.h>
-#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>
-
-#include <fcntl.h>
-#undef NULL /* We don't need sunview's idea of NULL */
-#include "lisp.h"
-#include "window.h"
-#include "buffer.h"
-#include "termhooks.h"
-
-/* conversion to/from character & frame coordinates */
-/* From Gosling Emacs SunWindow driver by Chris Torek */
-
-/* Chars to frame coords. Note that we speak in zero origin. */
-#define CtoSX(cx) ((cx) * Sun_Font_Xsize)
-#define CtoSY(cy) ((cy) * Sun_Font_Ysize)
-
-/* Frame coords to chars */
-#define StoCX(sx) ((sx) / Sun_Font_Xsize)
-#define StoCY(sy) ((sy) / Sun_Font_Ysize)
-
-#define CHECK_GFX(x) if((win_fd<0)&&(Fsun_window_init(),(win_fd<0)))return(x)
-int win_fd = -1;
-struct pixfont *Sun_Font; /* The font */
-int Sun_Font_Xsize; /* Width of font */
-int Sun_Font_Ysize; /* Height of font */
-
-#define Menu_Base_Kludge /* until menu_show_using_fd gets fixed */
-#ifdef Menu_Base_Kludge
-static Frame Menu_Base_Frame;
-static int Menu_Base_fd;
-static Lisp_Object sm_kludge_string;
-#endif
-struct cursor CurrentCursor; /* The current cursor */
-
-static short CursorData[16]; /* Build cursor here */
-static mpr_static(CursorMpr, 16, 16, 1, CursorData);
-static struct cursor NewCursor = {0, 0, PIX_SRC ^ PIX_DST, &CursorMpr};
-
-#define RIGHT_ARROW_CURSOR /* if you want the right arrow */
-#ifdef RIGHT_ARROW_CURSOR
-/* The default right-arrow cursor, with XOR drawing. */
-static short ArrowCursorData[16] = {
- 0x0001,0x0003,0x0007,0x000F,0x001F,0x003F,0x007F,0x000F,
- 0x001B,0x0019,0x0030,0x0030,0x0060,0x0060,0x00C0,0x00C0};
-static mpr_static(ArrowCursorMpr, 16, 16, 1, ArrowCursorData);
-struct cursor DefaultCursor = {15, 0, PIX_SRC ^ PIX_DST, &ArrowCursorMpr};
-
-#else
-/* The default left-arrow cursor, with XOR drawing. */
-static short ArrowCursorData[16] = {
- 0x8000,0xC000,0xE000,0xF000,0xF800,0xFC00,0xFE00,0xF000,
- 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
-
-/*
- * Initialize window
- */
-DEFUN ("sun-window-init", Fsun_window_init, Ssun_window_init, 0, 1, 0,
- "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.")
- (force)
- Lisp_Object force;
-{
- char *cp;
- static int already_initialized = 0;
-
- if ((! already_initialized) || (!NILP(force))) {
- cp = getenv("WINDOW_GFX");
- if (cp != 0) win_fd = open(cp, 2);
- if (win_fd > 0)
- {
- Sun_Font = pf_default();
- Sun_Font_Xsize = Sun_Font->pf_defaultsize.x;
- Sun_Font_Ysize = Sun_Font->pf_defaultsize.y;
- Fsun_change_cursor_icon (Qnil); /* set up the default cursor */
- already_initialized = 1;
-#ifdef Menu_Base_Kludge
-
- /* Make a frame to use for putting the menu on, and get its fd. */
- Menu_Base_Frame = window_create(0, FRAME,
- WIN_X, 0, WIN_Y, 0,
- WIN_ROWS, 1, WIN_COLUMNS, 1,
- WIN_SHOW, FALSE,
- FRAME_NO_CONFIRM, 1,
- 0);
- Menu_Base_fd = (int) window_get(Menu_Base_Frame, WIN_FD);
-#endif
- }
- }
- return(make_number(win_fd));
-}
-
-/*
- * 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,
- "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\
-Redisplay does not happen if input is available before it starts.")
- (n)
- Lisp_Object n;
-{
- struct timeval Timeout;
- int waitmask = 1;
-
- CHECK_NUMBER (n, 0);
- Timeout.tv_sec = XINT(n) / 1000;
- Timeout.tv_usec = (XINT(n) - (Timeout.tv_sec * 1000)) * 1000;
-
- if (detect_input_pending()) return(Qnil);
- redisplay_preserve_echo_area ();
- /*
- * Check for queued keyboard input/mouse hits again
- * (A bit screen update can take some time!)
- */
- if (detect_input_pending()) return(Qnil);
- select(1,&waitmask,0,0,&Timeout);
- if (detect_input_pending()) return(Qnil);
- return(Qt);
-}
-
-/*
- * Sun sleep-for (allows a shorter interval than the regular sleep-for)
- */
-DEFUN ("sleep-for-millisecs",
- Fsleep_for_millisecs,
- Ssleep_for_millisecs, 1, 1, 0,
- "Pause, without updating display, for ARG milliseconds.")
- (n)
- Lisp_Object n;
-{
- unsigned useconds;
-
- CHECK_NUMBER (n, 0);
- useconds = XINT(n) * 1000;
- usleep(useconds);
- return(Qt);
-}
-
-DEFUN ("update-display", Fupdate_display, Supdate_display, 0, 0, 0,
- "Perform redisplay.")
- ()
-{
- redisplay_preserve_echo_area ();
- return(Qt);
-}
-
-
-/*
- * Change the Sun mouse icon
- */
-DEFUN ("sun-change-cursor-icon",
- Fsun_change_cursor_icon,
- Ssun_change_cursor_icon, 1, 1, 0,
- "Change the Sun mouse cursor icon. ICON is a lisp vector whose 1st element\n\
-is the X offset of the cursor hot-point, whose 2nd element is the Y offset\n\
-of the cursor hot-point and whose 3rd element is the cursor pixel data\n\
-expressed as a string. If ICON is nil then the original arrow cursor is used")
- (Icon)
- Lisp_Object Icon;
-{
- register unsigned char *cp;
- register short *p;
- register int i;
- Lisp_Object X_Hot, Y_Hot, Data;
-
- CHECK_GFX (Qnil);
- /*
- * If the icon is null, we just restore the DefaultCursor
- */
- if (NILP(Icon))
- CurrentCursor = DefaultCursor;
- else {
- /*
- * extract the data from the vector
- */
- CHECK_VECTOR (Icon, 0);
- if (XVECTOR(Icon)->size < 3) return(Qnil);
- X_Hot = XVECTOR(Icon)->contents[0];
- Y_Hot = XVECTOR(Icon)->contents[1];
- Data = XVECTOR(Icon)->contents[2];
-
- CHECK_NUMBER (X_Hot, 0);
- CHECK_NUMBER (Y_Hot, 0);
- CHECK_STRING (Data, 0);
- if (XSTRING(Data)->size != 32) return(Qnil);
- /*
- * Setup the new cursor
- */
- NewCursor.cur_xhot = X_Hot;
- NewCursor.cur_yhot = Y_Hot;
- cp = XSTRING(Data)->data;
- p = CursorData;
- i = 16;
- while(--i >= 0)
- *p++ = (cp[0] << 8) | cp[1], cp += 2;
- CurrentCursor = NewCursor;
- }
- win_setcursor(win_fd, &CurrentCursor);
- return(Qt);
-}
-
-/*
- * Interface for sunwindows selection
- */
-static Lisp_Object Current_Selection;
-
-static
-sel_write (sel, file)
- struct selection *sel;
- FILE *file;
-{
- fwrite (XSTRING (Current_Selection)->data, sizeof (char),
- sel->sel_items, file);
-}
-
-static
-sel_clear (sel, windowfd)
- struct selection *sel;
- int windowfd;
-{
-}
-
-static
-sel_read (sel, file)
- struct selection *sel;
- FILE *file;
-{
- register int i, n;
- register char *cp;
-
- Current_Selection = make_string ("", 0);
- if (sel->sel_items <= 0)
- return (0);
- cp = (char *) malloc(sel->sel_items);
- if (cp == (char *)0) {
- error("malloc failed in sel_read");
- return(-1);
- }
- n = fread(cp, sizeof(char), sel->sel_items, file);
- if (n > sel->sel_items) {
- error("fread botch in sel_read");
- return(-1);
- } else if (n < 0) {
- error("Error reading selection.");
- return(-1);
- }
- /*
- * The shelltool select saves newlines as carriage returns,
- * but emacs wants newlines.
- */
- for (i = 0; i < n; i++)
- if (cp[i] == '\r') cp[i] = '\n';
-
- Current_Selection = make_string (cp, n);
- free (cp);
- return (0);
-}
-
-/*
- * Set the window system "selection" to be the arg STRING
- */
-DEFUN ("sun-set-selection", Fsun_set_selection, Ssun_set_selection, 1, 1,
- "sSet selection to: ",
- "Set the current sunwindow selection to STRING.")
- (str)
- Lisp_Object str;
-{
- struct selection selection;
-
- CHECK_STRING (str, 0);
- Current_Selection = str;
-
- CHECK_GFX (Qnil);
- selection.sel_type = SELTYPE_CHAR;
- selection.sel_items = XSTRING (str)->size;
- selection.sel_itembytes = 1;
- selection.sel_pubflags = 1;
- selection_set(&selection, sel_write, sel_clear, win_fd);
- return (Qt);
-}
-/*
- * Stuff the current window system selection into the current buffer
- */
-DEFUN ("sun-get-selection", Fsun_get_selection, Ssun_get_selection, 0, 0, 0,
- "Return the current sunwindows selection as a string.")
- ()
-{
- CHECK_GFX (Current_Selection);
- selection_get (sel_read, win_fd);
- return (Current_Selection);
-}
-
-Menu sun_menu_create();
-
-Menu_item
-sun_item_create (Pair)
- Lisp_Object Pair;
-{
- /* In here, we depend on Lisp supplying zero terminated strings in the data*/
- /* so we can just pass the pointers, and not recopy anything */
-
- Menu_item menu_item;
- Menu submenu;
- Lisp_Object String;
- Lisp_Object Value;
-
- if (!CONSP(Pair)) wrong_type_argument(Qlistp, Pair);
- String = Fcar(Pair);
- CHECK_STRING(String, 0);
- Value = Fcdr(Pair);
- if (SYMBOLP (Value))
- Value = XSYMBOL(Value)->value;
- if (VECTORP (Value)) {
- submenu = sun_menu_create (Value);
- menu_item = menu_create_item
- (MENU_RELEASE, MENU_PULLRIGHT_ITEM, XSTRING(String)->data, submenu, 0);
- } else {
- menu_item = menu_create_item
- (MENU_RELEASE, MENU_STRING_ITEM, XSTRING(String)->data, Value, 0);
- }
- return menu_item;
-}
-
-Menu
-sun_menu_create (Vector)
- Lisp_Object Vector;
-{
- Menu menu;
- int i;
- CHECK_VECTOR(Vector,0);
- menu=menu_create(0);
- for(i = 0; i < XVECTOR(Vector)->size; i++) {
- menu_set (menu, MENU_APPEND_ITEM,
- sun_item_create(XVECTOR(Vector)->contents[i]), 0);
- }
- return menu;
-}
-
-/*
- * If the first item of the menu has nil as its value, then make the
- * item look like a label by inverting it and making it unselectable.
- * Returns 1 if the label was made, 0 otherwise.
- */
-int
-make_menu_label (menu)
- Menu menu;
-{
- int made_label_p = 0;
-
- if (( menu_get(menu, MENU_NITEMS) > 0 ) && /* At least one item */
- ((Lisp_Object) menu_get(menu_get(menu, MENU_NTH_ITEM, 1),
- MENU_VALUE) == Qnil )) {
- menu_set(menu_get(menu, MENU_NTH_ITEM, 1),
- MENU_INVERT, TRUE,
- MENU_FEEDBACK, FALSE,
- 0);
- made_label_p = 1;
- }
- return made_label_p;
-}
-
-/*
- * Do a pop-up menu and return the selected value
- */
-DEFUN ("sun-menu-internal",
- Fsun_menu_internal,
- Ssun_menu_internal, 5, 5, 0,
- "Set up a SunView pop-up menu and return the user's choice.\n\
-Arguments WINDOW, X, Y, BUTTON, and MENU.\n\
-*** User code should generally use sun-menu-evaluate ***\n\
-\n\
-Arguments WINDOW, X, Y, BUTTON, and MENU.\n\
-Put MENU up in WINDOW at position X, Y.\n\
-The BUTTON argument specifies the button to be released that selects an item:\n\
- 1 = LEFT BUTTON\n\
- 2 = MIDDLE BUTTON\n\
- 4 = RIGHT BUTTON\n\
-The MENU argument is a vector containing (STRING . VALUE) pairs.\n\
-The VALUE of the selected item is returned.\n\
-If the VALUE of the first pair is nil, then the first STRING will be used\n\
-as a menu label.")
- (window, X_Position, Y_Position, Button, MEnu)
- Lisp_Object window, X_Position, Y_Position, Button, MEnu;
-{
- Menu menu;
- int button, xpos, ypos;
- Event event0;
- Event *event = &event0;
- Lisp_Object Value, Pair;
-
- CHECK_NUMBER(X_Position, 0);
- CHECK_NUMBER(Y_Position, 1);
- CHECK_LIVE_WINDOW(window, 2);
- CHECK_NUMBER(Button, 3);
- CHECK_VECTOR(MEnu, 4);
-
- CHECK_GFX (Qnil);
-
- xpos = CtoSX (WINDOW_LEFT_MARGIN (XWINDOW (window)) + XINT(X_Position));
- ypos = CtoSY (XWINDOW(window)->top + XINT(Y_Position));
-#ifdef Menu_Base_Kludge
- {static Lisp_Object symbol[2];
- symbol[0] = Fintern (sm_kludge_string, Qnil);
- Pair = Ffuncall (1, symbol);
- xpos += XINT (XCONS (Pair)->cdr);
- ypos += XINT (XCONS (Pair)->car);
- }
-#endif
-
- button = XINT(Button);
- if(button == 4) button = 3;
- event_set_id (event, BUT(button));
- event_set_down (event);
- event_set_x (event, xpos);
- event_set_y (event, ypos);
-
- menu = sun_menu_create(MEnu);
- make_menu_label(menu);
-
-#ifdef Menu_Base_Kludge
- Value = (Lisp_Object) menu_show(menu, Menu_Base_Frame, event, 0);
-#else
-/* This confuses the notifier or something: */
- Value = (Lisp_Object) menu_show_using_fd(menu, win_fd, event, 0);
-/*
- * 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
- menu_destroy (menu);
-
- return ((int)Value ? Value : Qnil);
-}
-
-
-/*
- * Define everything
- */
-syms_of_sunfns()
-{
-#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 */
-
- defsubr(&Ssun_window_init);
- defsubr(&Ssit_for_millisecs);
- defsubr(&Ssleep_for_millisecs);
- defsubr(&Supdate_display);
- defsubr(&Ssun_change_cursor_icon);
- defsubr(&Ssun_set_selection);
- defsubr(&Ssun_get_selection);
- defsubr(&Ssun_menu_internal);
-}
diff --git a/src/syntax.c b/src/syntax.c
deleted file mode 100644
index 22339930b2b..00000000000
--- a/src/syntax.c
+++ /dev/null
@@ -1,1823 +0,0 @@
-/* GNU Emacs routines to deal with syntax tables; also word and list parsing.
- Copyright (C) 1985, 1987, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include <ctype.h>
-#include "lisp.h"
-#include "commands.h"
-#include "buffer.h"
-#include "syntax.h"
-
-Lisp_Object Qsyntax_table_p, Qsyntax_table;
-
-static void scan_sexps_forward ();
-static int char_quoted ();
-
-int words_include_escapes;
-
-/* Used as a temporary in SYNTAX_ENTRY and other macros in syntax.h,
- if not compiled with GCC. No need to mark it, since it is used
- only very temporarily. */
-Lisp_Object syntax_temp;
-
-/* This is the internal form of the parse state used in parse-partial-sexp. */
-
-struct lisp_parse_state
- {
- int depth; /* Depth at end of parsing */
- int instring; /* -1 if not within string, else desired terminator. */
- int incomment; /* Nonzero if within a comment at end of parsing */
- int comstyle; /* comment style a=0, or b=1 */
- int quoted; /* Nonzero if just after an escape char at end of parsing */
- int thislevelstart; /* Char number of most recent start-of-expression at current level */
- int prevlevelstart; /* Char number of start of containing expression */
- int location; /* Char number at which parsing stopped. */
- int mindepth; /* Minimum depth seen while scanning. */
- int comstart; /* Position just after last comment starter. */
- };
-
-/* These variables are a cache for finding the start of a defun.
- find_start_pos is the place for which the defun start was found.
- find_start_value is the defun start position found for it.
- find_start_buffer is the buffer it was found in.
- find_start_begv is the BEGV value when it was found.
- find_start_modiff is the value of MODIFF when it was found. */
-
-static int find_start_pos;
-static int find_start_value;
-static struct buffer *find_start_buffer;
-static int find_start_begv;
-static int find_start_modiff;
-
-/* Find a defun-start that is the last one before POS (or nearly the last).
- We record what we find, so that another call in the same area
- can return the same value right away. */
-
-static int
-find_defun_start (pos)
- int pos;
-{
- int tem;
- int shortage;
-
- /* Use previous finding, if it's valid and applies to this inquiry. */
- if (current_buffer == find_start_buffer
- /* Reuse the defun-start even if POS is a little farther on.
- POS might be in the next defun, but that's ok.
- Our value may not be the best possible, but will still be usable. */
- && pos <= find_start_pos + 1000
- && pos >= find_start_value
- && BEGV == find_start_begv
- && MODIFF == find_start_modiff)
- return find_start_value;
-
- /* Back up to start of line. */
- tem = scan_buffer ('\n', pos, BEGV, -1, &shortage, 1);
-
- while (tem > BEGV)
- {
- /* Open-paren at start of line means we found our defun-start. */
- if (SYNTAX (FETCH_CHAR (tem)) == Sopen)
- break;
- /* Move to beg of previous line. */
- tem = scan_buffer ('\n', tem, BEGV, -2, &shortage, 1);
- }
-
- /* Record what we found, for the next try. */
- find_start_value = tem;
- find_start_buffer = current_buffer;
- find_start_modiff = MODIFF;
- find_start_begv = BEGV;
- find_start_pos = pos;
-
- return find_start_value;
-}
-
-DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0,
- "Return t if OBJECT is a syntax table.\n\
-Currently, any char-table counts as a syntax table.")
- (object)
- Lisp_Object object;
-{
- if (CHAR_TABLE_P (object)
- && XCHAR_TABLE (object)->purpose == Qsyntax_table)
- return Qt;
- return Qnil;
-}
-
-static void
-check_syntax_table (obj)
- Lisp_Object obj;
-{
- if (!(CHAR_TABLE_P (obj)
- && XCHAR_TABLE (obj)->purpose == Qsyntax_table))
- wrong_type_argument (Qsyntax_table_p, obj);
-}
-
-DEFUN ("syntax-table", Fsyntax_table, Ssyntax_table, 0, 0, 0,
- "Return the current syntax table.\n\
-This is the one specified by the current buffer.")
- ()
-{
- return current_buffer->syntax_table;
-}
-
-DEFUN ("standard-syntax-table", Fstandard_syntax_table,
- Sstandard_syntax_table, 0, 0, 0,
- "Return the standard syntax table.\n\
-This is the one used for new buffers.")
- ()
-{
- return Vstandard_syntax_table;
-}
-
-DEFUN ("copy-syntax-table", Fcopy_syntax_table, Scopy_syntax_table, 0, 1, 0,
- "Construct a new syntax table and return it.\n\
-It is a copy of the TABLE, which defaults to the standard syntax table.")
- (table)
- Lisp_Object table;
-{
- Lisp_Object copy;
-
- if (!NILP (table))
- check_syntax_table (table);
- else
- table = Vstandard_syntax_table;
-
- copy = Fcopy_sequence (table);
-
- /* Only the standard syntax table should have a default element.
- Other syntax tables should inherit from parents instead. */
- XCHAR_TABLE (copy)->defalt = Qnil;
-
- /* Copied syntax tables should all have parents.
- If we copied one with no parent, such as the standard syntax table,
- use the standard syntax table as the copy's parent. */
- if (NILP (XCHAR_TABLE (copy)->parent))
- Fset_char_table_parent (copy, Vstandard_syntax_table);
- return copy;
-}
-
-DEFUN ("set-syntax-table", Fset_syntax_table, Sset_syntax_table, 1, 1, 0,
- "Select a new syntax table for the current buffer.\n\
-One argument, a syntax table.")
- (table)
- Lisp_Object table;
-{
- check_syntax_table (table);
- current_buffer->syntax_table = table;
- /* Indicate that this buffer now has a specified syntax table. */
- current_buffer->local_var_flags
- |= XFASTINT (buffer_local_flags.syntax_table);
- return table;
-}
-
-/* Convert a letter which signifies a syntax code
- into the code it signifies.
- This is used by modify-syntax-entry, and other things. */
-
-unsigned char syntax_spec_code[0400] =
- { 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
- 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
- 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
- 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
- (char) Swhitespace, 0377, (char) Sstring, 0377,
- (char) Smath, 0377, 0377, (char) Squote,
- (char) Sopen, (char) Sclose, 0377, 0377,
- 0377, (char) Swhitespace, (char) Spunct, (char) Scharquote,
- 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
- 0377, 0377, 0377, 0377,
- (char) Scomment, 0377, (char) Sendcomment, 0377,
- (char) Sinherit, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* @, A ... */
- 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
- 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword,
- 0377, 0377, 0377, 0377, (char) Sescape, 0377, 0377, (char) Ssymbol,
- 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* `, a, ... */
- 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
- 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword,
- 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377
- };
-
-/* Indexed by syntax code, give the letter that describes it. */
-
-char syntax_code_spec[14] =
- {
- ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>', '@'
- };
-
-/* Look up the value for CHARACTER in syntax table TABLE's parent
- and its parents. SYNTAX_ENTRY calls this, when TABLE itself has nil
- for CHARACTER. It's actually used only when not compiled with GCC. */
-
-Lisp_Object
-syntax_parent_lookup (table, character)
- Lisp_Object table;
- int character;
-{
- Lisp_Object value;
-
- while (1)
- {
- table = XCHAR_TABLE (table)->parent;
- if (NILP (table))
- return Qnil;
-
- value = XCHAR_TABLE (table)->contents[character];
- if (!NILP (value))
- return value;
- }
-}
-
-DEFUN ("char-syntax", Fchar_syntax, Schar_syntax, 1, 1, 0,
- "Return the syntax code of CHARACTER, described by a character.\n\
-For example, if CHARACTER is a word constituent,\n\
-the character `w' is returned.\n\
-The characters that correspond to various syntax codes\n\
-are listed in the documentation of `modify-syntax-entry'.")
- (character)
- Lisp_Object character;
-{
- int char_int;
- CHECK_NUMBER (character, 0);
- char_int = XINT (character);
- return make_number (syntax_code_spec[(int) SYNTAX (char_int)]);
-}
-
-DEFUN ("matching-paren", Fmatching_paren, Smatching_paren, 1, 1, 0,
- "Return the matching parenthesis of CHARACTER, or nil if none.")
- (character)
- Lisp_Object character;
-{
- int char_int, code;
- CHECK_NUMBER (character, 0);
- char_int = XINT (character);
- code = SYNTAX (char_int);
- if (code == Sopen || code == Sclose)
- return make_number (SYNTAX_MATCH (char_int));
- return Qnil;
-}
-
-/* This comment supplies the doc string for modify-syntax-entry,
- for make-docfile to see. We cannot put this in the real DEFUN
- due to limits in the Unix cpp.
-
-DEFUN ("modify-syntax-entry", foo, bar, 2, 3, 0,
- "Set syntax for character CHAR according to string S.\n\
-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 or - whitespace syntax. w word constituent.\n\
- _ symbol constituent. . punctuation.\n\
- ( open-parenthesis. ) close-parenthesis.\n\
- \" string quote. \\ escape.\n\
- $ paired delimiter. ' expression quote or prefix operator.\n\
- < comment starter. > comment ender.\n\
- / character-quote. @ inherit from `standard-syntax-table'.\n\
-\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\
-Any additional characters are flags.\n\
-Defined flags are the characters 1, 2, 3, 4, b, and p.\n\
- 1 means CHAR is the start of a two-char comment start sequence.\n\
- 2 means CHAR is the second character of such a sequence.\n\
- 3 means CHAR is the start of a two-char comment end sequence.\n\
- 4 means CHAR is the second character of such a sequence.\n\
-\n\
-There can be up to two orthogonal comment sequences. This is to support\n\
-language modes such as C++. By default, all comment sequences are of style\n\
-a, but you can set the comment sequence style to b (on the second character\n\
-of a comment-start, or the first character of a comment-end sequence) using\n\
-this flag:\n\
- b means CHAR is part of comment sequence b.\n\
-\n\
- p means CHAR is a prefix character for `backward-prefix-chars';\n\
- such characters are treated as whitespace when they occur\n\
- between expressions.")
- (char, s, table)
-*/
-
-DEFUN ("modify-syntax-entry", Fmodify_syntax_entry, Smodify_syntax_entry, 2, 3,
- /* I really don't know why this is interactive
- help-form should at least be made useful whilst reading the second arg
- */
- "cSet syntax for character: \nsSet syntax for %s to: ",
- 0 /* See immediately above */)
- (c, newentry, syntax_table)
- Lisp_Object c, newentry, syntax_table;
-{
- register unsigned char *p;
- register enum syntaxcode code;
- int val;
- Lisp_Object match;
-
- CHECK_NUMBER (c, 0);
- CHECK_STRING (newentry, 1);
-
- if (NILP (syntax_table))
- syntax_table = current_buffer->syntax_table;
- else
- check_syntax_table (syntax_table);
-
- p = XSTRING (newentry)->data;
- code = (enum syntaxcode) syntax_spec_code[*p++];
- if (((int) code & 0377) == 0377)
- error ("invalid syntax description letter: %c", c);
-
- if (code == Sinherit)
- {
- SET_RAW_SYNTAX_ENTRY (syntax_table, c, Qnil);
- return Qnil;
- }
-
- if (*p)
- {
- XSETINT (match, *p++);
- if (XFASTINT (match) == ' ')
- match = Qnil;
- }
- else
- match = Qnil;
-
- val = (int) code;
- while (*p)
- switch (*p++)
- {
- case '1':
- val |= 1 << 16;
- break;
-
- case '2':
- val |= 1 << 17;
- break;
-
- case '3':
- val |= 1 << 18;
- break;
-
- case '4':
- val |= 1 << 19;
- break;
-
- case 'p':
- val |= 1 << 20;
- break;
-
- case 'b':
- val |= 1 << 21;
- break;
- }
-
- SET_RAW_SYNTAX_ENTRY (syntax_table, c,
- Fcons (make_number (val), match));
-
- return Qnil;
-}
-
-/* Dump syntax table to buffer in human-readable format */
-
-static void
-describe_syntax (value)
- Lisp_Object value;
-{
- register enum syntaxcode code;
- char desc, match, start1, start2, end1, end2, prefix, comstyle;
- char str[2];
- Lisp_Object first, match_lisp;
-
- Findent_to (make_number (16), make_number (1));
-
- if (NILP (value))
- {
- insert_string ("inherit");
- return;
- }
-
- if (!CONSP (value))
- {
- insert_string ("invalid");
- return;
- }
-
- first = XCONS (value)->car;
- match_lisp = XCONS (value)->cdr;
-
- if (!INTEGERP (first) || !(NILP (match_lisp) || INTEGERP (match_lisp)))
- {
- insert_string ("invalid");
- return;
- }
-
- code = (enum syntaxcode) (first & 0377);
- start1 = (XINT (first) >> 16) & 1;
- start2 = (XINT (first) >> 17) & 1;
- end1 = (XINT (first) >> 18) & 1;
- end2 = (XINT (first) >> 19) & 1;
- prefix = (XINT (first) >> 20) & 1;
- comstyle = (XINT (first) >> 21) & 1;
-
- if ((int) code < 0 || (int) code >= (int) Smax)
- {
- insert_string ("invalid");
- return;
- }
- desc = syntax_code_spec[(int) code];
-
- str[0] = desc, str[1] = 0;
- insert (str, 1);
-
- str[0] = !NILP (match_lisp) ? XINT (match_lisp) : ' ';
- insert (str, 1);
-
- if (start1)
- insert ("1", 1);
- if (start2)
- insert ("2", 1);
-
- if (end1)
- insert ("3", 1);
- if (end2)
- insert ("4", 1);
-
- if (prefix)
- insert ("p", 1);
- if (comstyle)
- insert ("b", 1);
-
- insert_string ("\twhich means: ");
-
- switch (SWITCH_ENUM_CAST (code))
- {
- case Swhitespace:
- insert_string ("whitespace"); break;
- case Spunct:
- insert_string ("punctuation"); break;
- case Sword:
- insert_string ("word"); break;
- case Ssymbol:
- insert_string ("symbol"); break;
- case Sopen:
- insert_string ("open"); break;
- case Sclose:
- insert_string ("close"); break;
- case Squote:
- insert_string ("quote"); break;
- case Sstring:
- insert_string ("string"); break;
- case Smath:
- insert_string ("math"); break;
- case Sescape:
- insert_string ("escape"); break;
- case Scharquote:
- insert_string ("charquote"); break;
- case Scomment:
- insert_string ("comment"); break;
- case Sendcomment:
- insert_string ("endcomment"); break;
- default:
- insert_string ("invalid");
- return;
- }
-
- if (!NILP (match_lisp))
- {
- insert_string (", matches ");
- insert_char (XINT (match_lisp));
- }
-
- if (start1)
- insert_string (",\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");
-
- if (end1)
- insert_string (",\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 (comstyle)
- insert_string (" (comment style b)");
-
- if (prefix)
- insert_string (",\n\t is a prefix character for `backward-prefix-chars'");
-
- insert_string ("\n");
-}
-
-static Lisp_Object
-describe_syntax_1 (vector)
- Lisp_Object vector;
-{
- struct buffer *old = current_buffer;
- set_buffer_internal (XBUFFER (Vstandard_output));
- describe_vector (vector, Qnil, describe_syntax, 0, Qnil, Qnil);
- call0 (intern ("help-mode"));
- 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.")
- ()
-{
- internal_with_output_to_temp_buffer
- ("*Help*", describe_syntax_1, current_buffer->syntax_table);
-
- return Qnil;
-}
-
-/* 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. */
-
-scan_words (from, count)
- register int from, count;
-{
- register int beg = BEGV;
- register int end = ZV;
- register int code;
- int charcode;
-
- immediate_quit = 1;
- QUIT;
-
- while (count > 0)
- {
- while (1)
- {
- if (from == end)
- {
- immediate_quit = 0;
- return 0;
- }
- charcode = FETCH_CHAR (from);
- code = SYNTAX (charcode);
- if (words_include_escapes
- && (code == Sescape || code == Scharquote))
- break;
- if (code == Sword)
- break;
- from++;
- }
- while (1)
- {
- if (from == end) break;
- charcode = FETCH_CHAR (from);
- code = SYNTAX (charcode);
- if (!(words_include_escapes
- && (code == Sescape || code == Scharquote)))
- if (code != Sword)
- break;
- from++;
- }
- count--;
- }
- while (count < 0)
- {
- while (1)
- {
- if (from == beg)
- {
- immediate_quit = 0;
- return 0;
- }
- charcode = FETCH_CHAR (from - 1);
- code = SYNTAX (charcode);
- if (words_include_escapes
- && (code == Sescape || code == Scharquote))
- break;
- if (code == Sword)
- break;
- from--;
- }
- while (1)
- {
- if (from == beg) break;
- charcode = FETCH_CHAR (from - 1);
- code = SYNTAX (charcode);
- if (!(words_include_escapes
- && (code == Sescape || code == Scharquote)))
- if (code != Sword)
- break;
- from--;
- }
- count++;
- }
-
- immediate_quit = 0;
-
- return from;
-}
-
-DEFUN ("forward-word", Fforward_word, Sforward_word, 1, 1, "p",
- "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.")
- (count)
- Lisp_Object count;
-{
- int val;
- CHECK_NUMBER (count, 0);
-
- if (!(val = scan_words (PT, XINT (count))))
- {
- SET_PT (XINT (count) > 0 ? ZV : BEGV);
- return Qnil;
- }
- SET_PT (val);
- return Qt;
-}
-
-DEFUN ("forward-comment", Fforward_comment, Sforward_comment, 1, 1, 0,
- "Move forward across up to N comments. If N is negative, move backward.\n\
-Stop scanning if we find something other than a comment or whitespace.\n\
-Set point to where scanning stops.\n\
-If N comments are found as expected, with nothing except whitespace\n\
-between them, return t; otherwise return nil.")
- (count)
- Lisp_Object count;
-{
- register int from;
- register int stop;
- register int c, c1;
- register enum syntaxcode code;
- int comstyle = 0; /* style of comment encountered */
- int found;
- int count1;
-
- CHECK_NUMBER (count, 0);
- count1 = XINT (count);
-
- immediate_quit = 1;
- QUIT;
-
- from = PT;
-
- while (count1 > 0)
- {
- stop = ZV;
- do
- {
- if (from == stop)
- {
- SET_PT (from);
- immediate_quit = 0;
- return Qnil;
- }
- c = FETCH_CHAR (from);
- code = SYNTAX (c);
- from++;
- comstyle = 0;
- if (from < stop && SYNTAX_COMSTART_FIRST (c)
- && (c1 = FETCH_CHAR (from),
- SYNTAX_COMSTART_SECOND (c1)))
- {
- /* We have encountered a comment start sequence and we
- are ignoring all text inside comments. We must record
- the comment style this sequence begins so that later,
- only a comment end of the same style actually ends
- the comment section. */
- code = Scomment;
- comstyle = SYNTAX_COMMENT_STYLE (c1);
- from++;
- }
- }
- while (code == Swhitespace || code == Sendcomment);
- if (code != Scomment)
- {
- immediate_quit = 0;
- SET_PT (from - 1);
- return Qnil;
- }
- /* We're at the start of a comment. */
- while (1)
- {
- if (from == stop)
- {
- immediate_quit = 0;
- SET_PT (from);
- return Qnil;
- }
- c = FETCH_CHAR (from);
- from++;
- if (SYNTAX (c) == Sendcomment
- && SYNTAX_COMMENT_STYLE (c) == comstyle)
- /* we have encountered a comment end of the same style
- as the comment sequence which began this comment
- section */
- break;
- if (from < stop && SYNTAX_COMEND_FIRST (c)
- && (c1 = FETCH_CHAR (from),
- SYNTAX_COMEND_SECOND (c1))
- && SYNTAX_COMMENT_STYLE (c) == comstyle)
- /* we have encountered a comment end of the same style
- as the comment sequence which began this comment
- section */
- { from++; break; }
- }
- /* We have skipped one comment. */
- count1--;
- }
-
- while (count1 < 0)
- {
- stop = BEGV;
- while (from > stop)
- {
- int quoted;
-
- from--;
- quoted = char_quoted (from);
- if (quoted)
- from--;
- c = FETCH_CHAR (from);
- code = SYNTAX (c);
- comstyle = 0;
- if (code == Sendcomment)
- comstyle = SYNTAX_COMMENT_STYLE (c);
- if (from > stop && SYNTAX_COMEND_SECOND (c)
- && (c1 = FETCH_CHAR (from - 1),
- SYNTAX_COMEND_FIRST (c1))
- && !char_quoted (from - 1))
- {
- /* We must record the comment style encountered so that
- later, we can match only the proper comment begin
- sequence of the same style. */
- code = Sendcomment;
- comstyle = SYNTAX_COMMENT_STYLE (c1);
- from--;
- }
-
- if (code == Sendcomment && !quoted)
- {
-#if 0
- if (code != SYNTAX (c))
- /* For a two-char comment ender, we can assume
- it does end a comment. So scan back in a simple way. */
- {
- if (from != stop) from--;
- while (1)
- {
- if ((c = FETCH_CHAR (from),
- SYNTAX (c) == Scomment)
- && SYNTAX_COMMENT_STYLE (c) == comstyle)
- break;
- if (from == stop)
- {
- immediate_quit = 0;
- SET_PT (from);
- return Qnil;
- }
- from--;
- if (SYNTAX_COMSTART_SECOND (c)
- && (c1 = FETCH_CHAR (from),
- SYNTAX_COMSTART_FIRST (c1))
- && SYNTAX_COMMENT_STYLE (c) == comstyle
- && !char_quoted (from))
- break;
- }
- break;
- }
-#endif /* 0 */
-
- /* 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 parity = 0;
- char my_stringend = 0;
- int string_lossage = 0;
- int comment_end = from;
- int comstart_pos = 0;
- int comstart_parity = 0;
- int scanstart = from - 1;
-
- /* 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--;
- c = FETCH_CHAR (from);
- }
-
- /* If this char starts a 2-char comment start sequence,
- treat it like a 1-char comment starter. */
- if (from < scanstart && SYNTAX_COMSTART_FIRST (c)
- && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from + 1))
- && comstyle == SYNTAX_COMMENT_STYLE (FETCH_CHAR (from + 1)))
- code = Scomment;
-
- /* Ignore escaped characters. */
- if (char_quoted (from))
- continue;
-
- /* Track parity of quotes. */
- if (code == Sstring)
- {
- parity ^= 1;
- if (my_stringend == 0)
- my_stringend = c;
- /* If we have two kinds of string delimiters.
- There's no way to grok this scanning backwards. */
- else if (my_stringend != c)
- string_lossage = 1;
- }
-
- /* Record comment-starters according to that
- quote-parity to the comment-end. */
- if (code == Scomment)
- {
- comstart_parity = parity;
- comstart_pos = from;
- }
-
- /* If we find another earlier comment-ender,
- any comment-starts earlier than that don't count
- (because they go with the earlier comment-ender). */
- if (code == Sendcomment
- && SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)) == comstyle)
- break;
-
- /* Assume a defun-start point is outside of strings. */
- if (code == Sopen
- && (from == stop || FETCH_CHAR (from - 1) == '\n'))
- break;
- }
-
- if (comstart_pos == 0)
- from = comment_end;
- /* If the earliest comment starter
- is followed by uniform paired string quotes or none,
- we know it can't be inside a string
- since if it were then the comment ender would be inside one.
- So it does start a comment. Skip back to it. */
- else if (comstart_parity == 0 && !string_lossage)
- from = comstart_pos;
- else
- {
- /* We had two kinds of string delimiters mixed up
- together. Decode this going forwards.
- Scan fwd from the previous comment ender
- to the one in question; this records where we
- last passed a comment starter. */
- struct lisp_parse_state state;
- scan_sexps_forward (&state, find_defun_start (comment_end),
- comment_end - 1, -10000, 0, Qnil, 0);
- if (state.incomment)
- from = state.comstart;
- else
- /* We can't grok this as a comment; scan it normally. */
- from = comment_end;
- }
- }
- /* We have skipped one comment. */
- break;
- }
- else if ((code != Swhitespace && code != Scomment) || quoted)
- {
- immediate_quit = 0;
- SET_PT (from + 1);
- return Qnil;
- }
- }
-
- count1++;
- }
-
- SET_PT (from);
- immediate_quit = 0;
- return Qt;
-}
-
-int parse_sexp_ignore_comments;
-
-Lisp_Object
-scan_lists (from, count, depth, sexpflag)
- register int from;
- int count, depth, sexpflag;
-{
- Lisp_Object val;
- register int stop;
- register int c;
- unsigned char stringterm;
- int quoted;
- int mathexit = 0;
- register enum syntaxcode code;
- int min_depth = depth; /* Err out if depth gets less than this. */
- int comstyle = 0; /* style of comment encountered */
-
- if (depth > 0) min_depth = 0;
-
- immediate_quit = 1;
- QUIT;
-
- while (count > 0)
- {
- stop = ZV;
- while (from < stop)
- {
- c = FETCH_CHAR (from);
- code = SYNTAX (c);
- from++;
- if (from < stop && SYNTAX_COMSTART_FIRST (c)
- && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from))
- && parse_sexp_ignore_comments)
- {
- /* we have encountered a comment start sequence and we
- are ignoring all text inside comments. we must record
- the comment style this sequence begins so that later,
- only a comment end of the same style actually ends
- the comment section */
- code = Scomment;
- comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from));
- from++;
- }
-
- if (SYNTAX_PREFIX (c))
- continue;
-
- switch (SWITCH_ENUM_CAST (code))
- {
- case Sescape:
- case Scharquote:
- if (from == stop) goto lose;
- from++;
- /* treat following character as a word constituent */
- case Sword:
- case Ssymbol:
- if (depth || !sexpflag) break;
- /* This word counts as a sexp; return at end of it. */
- while (from < stop)
- {
- switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from))))
- {
- case Scharquote:
- case Sescape:
- from++;
- if (from == stop) goto lose;
- break;
- case Sword:
- case Ssymbol:
- case Squote:
- break;
- default:
- goto done;
- }
- from++;
- }
- goto done;
-
- case Scomment:
- if (!parse_sexp_ignore_comments) break;
- while (1)
- {
- if (from == stop)
- {
- if (depth == 0)
- goto done;
- goto lose;
- }
- c = FETCH_CHAR (from);
- if (SYNTAX (c) == Sendcomment
- && SYNTAX_COMMENT_STYLE (c) == comstyle)
- /* we have encountered a comment end of the same style
- as the comment sequence which began this comment
- section */
- break;
- from++;
- if (from < stop && SYNTAX_COMEND_FIRST (c)
- && SYNTAX_COMEND_SECOND (FETCH_CHAR (from))
- && SYNTAX_COMMENT_STYLE (c) == comstyle)
- /* we have encountered a comment end of the same style
- as the comment sequence which began this comment
- section */
- { from++; break; }
- }
- break;
-
- case Smath:
- if (!sexpflag)
- break;
- if (from != stop && c == FETCH_CHAR (from))
- from++;
- if (mathexit)
- {
- mathexit = 0;
- goto close1;
- }
- mathexit = 1;
-
- case Sopen:
- if (!++depth) goto done;
- break;
-
- case Sclose:
- close1:
- if (!--depth) goto done;
- if (depth < min_depth)
- error ("Containing expression ends prematurely");
- break;
-
- case Sstring:
- stringterm = FETCH_CHAR (from - 1);
- while (1)
- {
- if (from >= stop) goto lose;
- if (FETCH_CHAR (from) == stringterm) break;
- switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from))))
- {
- case Scharquote:
- case Sescape:
- from++;
- }
- from++;
- }
- from++;
- if (!depth && sexpflag) goto done;
- break;
- }
- }
-
- /* Reached end of buffer. Error if within object, return nil if between */
- if (depth) goto lose;
-
- immediate_quit = 0;
- return Qnil;
-
- /* End of object reached */
- done:
- count--;
- }
-
- while (count < 0)
- {
- stop = BEGV;
- while (from > stop)
- {
- from--;
- if (quoted = char_quoted (from))
- from--;
- c = FETCH_CHAR (from);
- code = SYNTAX (c);
- comstyle = 0;
- if (code == Sendcomment)
- comstyle = SYNTAX_COMMENT_STYLE (c);
- if (from > stop && SYNTAX_COMEND_SECOND (c)
- && SYNTAX_COMEND_FIRST (FETCH_CHAR (from - 1))
- && !char_quoted (from - 1)
- && parse_sexp_ignore_comments)
- {
- /* we must record the comment style encountered so that
- later, we can match only the proper comment begin
- sequence of the same style */
- code = Sendcomment;
- comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from - 1));
- from--;
- }
-
- if (SYNTAX_PREFIX (c))
- continue;
-
- switch (SWITCH_ENUM_CAST (quoted ? Sword : code))
- {
- case Sword:
- case Ssymbol:
- if (depth || !sexpflag) break;
- /* This word counts as a sexp; count object finished after passing it. */
- while (from > stop)
- {
- quoted = char_quoted (from - 1);
- if (quoted)
- from--;
- if (! (quoted || SYNTAX (FETCH_CHAR (from - 1)) == Sword
- || SYNTAX (FETCH_CHAR (from - 1)) == Ssymbol
- || SYNTAX (FETCH_CHAR (from - 1)) == Squote))
- goto done2;
- from--;
- }
- goto done2;
-
- case Smath:
- if (!sexpflag)
- break;
- if (from != stop && c == FETCH_CHAR (from - 1))
- from--;
- if (mathexit)
- {
- mathexit = 0;
- goto open2;
- }
- mathexit = 1;
-
- case Sclose:
- if (!++depth) goto done2;
- break;
-
- case Sopen:
- open2:
- if (!--depth) goto done2;
- if (depth < min_depth)
- error ("Containing expression ends prematurely");
- break;
-
- case Sendcomment:
- if (!parse_sexp_ignore_comments)
- break;
-#if 0
- if (code != SYNTAX (c))
- /* For a two-char comment ender, we can assume
- it does end a comment. So scan back in a simple way. */
- {
- if (from != stop) from--;
- while (1)
- {
- if (SYNTAX (c = FETCH_CHAR (from)) == Scomment
- && SYNTAX_COMMENT_STYLE (c) == comstyle)
- break;
- if (from == stop)
- {
- if (depth == 0)
- goto done2;
- goto lose;
- }
- from--;
- if (SYNTAX_COMSTART_SECOND (c)
- && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from))
- && SYNTAX_COMMENT_STYLE (c) == comstyle
- && !char_quoted (from))
- break;
- }
- break;
- }
-#endif /* 0 */
-
- /* 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 parity = 0;
- char my_stringend = 0;
- int string_lossage = 0;
- int comment_end = from;
- int comstart_pos = 0;
- int comstart_parity = 0;
- int scanstart = from - 1;
-
- /* 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--;
- c = FETCH_CHAR (from);
- }
-
- /* If this char starts a 2-char comment start sequence,
- treat it like a 1-char comment starter. */
- if (from < scanstart && SYNTAX_COMSTART_FIRST (c)
- && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from + 1))
- && comstyle == SYNTAX_COMMENT_STYLE (FETCH_CHAR (from + 1)))
- code = Scomment;
-
- /* Ignore escaped characters. */
- if (char_quoted (from))
- continue;
-
- /* Track parity of quotes. */
- if (code == Sstring)
- {
- parity ^= 1;
- if (my_stringend == 0)
- my_stringend = c;
- /* If we have two kinds of string delimiters.
- There's no way to grok this scanning backwards. */
- else if (my_stringend != c)
- string_lossage = 1;
- }
-
- /* Record comment-starters according to that
- quote-parity to the comment-end. */
- if (code == Scomment)
- {
- comstart_parity = parity;
- comstart_pos = from;
- }
-
- /* If we find another earlier comment-ender,
- any comment-starts earlier than that don't count
- (because they go with the earlier comment-ender). */
- if (code == Sendcomment
- && SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)) == comstyle)
- break;
-
- /* Assume a defun-start point is outside of strings. */
- if (code == Sopen
- && (from == stop || FETCH_CHAR (from - 1) == '\n'))
- break;
- }
-
- if (comstart_pos == 0)
- from = comment_end;
- /* If the earliest comment starter
- is followed by uniform paired string quotes or none,
- we know it can't be inside a string
- since if it were then the comment ender would be inside one.
- So it does start a comment. Skip back to it. */
- else if (comstart_parity == 0 && !string_lossage)
- from = comstart_pos;
- else
- {
- /* We had two kinds of string delimiters mixed up
- together. Decode this going forwards.
- Scan fwd from the previous comment ender
- to the one in question; this records where we
- last passed a comment starter. */
- struct lisp_parse_state state;
- scan_sexps_forward (&state, find_defun_start (comment_end),
- comment_end - 1, -10000, 0, Qnil, 0);
- if (state.incomment)
- from = state.comstart;
- else
- /* We can't grok this as a comment; scan it normally. */
- from = comment_end;
- }
- }
- break;
-
- case Sstring:
- stringterm = FETCH_CHAR (from);
- while (1)
- {
- if (from == stop) goto lose;
- if (!char_quoted (from - 1)
- && stringterm == FETCH_CHAR (from - 1))
- break;
- from--;
- }
- from--;
- if (!depth && sexpflag) goto done2;
- break;
- }
- }
-
- /* Reached start of buffer. Error if within object, return nil if between */
- if (depth) goto lose;
-
- immediate_quit = 0;
- return Qnil;
-
- done2:
- count++;
- }
-
-
- immediate_quit = 0;
- XSETFASTINT (val, from);
- return val;
-
- lose:
- error ("Unbalanced parentheses");
- /* NOTREACHED */
-}
-
-static int
-char_quoted (pos)
- register int pos;
-{
- register enum syntaxcode code;
- register int beg = BEGV;
- register int quoted = 0;
-
- while (pos > beg
- && ((code = SYNTAX (FETCH_CHAR (pos - 1))) == Scharquote
- || code == Sescape))
- pos--, quoted = !quoted;
- return quoted;
-}
-
-DEFUN ("scan-lists", Fscan_lists, Sscan_lists, 3, 3, 0,
- "Scan from character number FROM by COUNT lists.\n\
-Returns the character number of the position thus found.\n\
-\n\
-If DEPTH is nonzero, paren depth begins counting from that value,\n\
-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\
-\n\
-If the beginning or end of (the accessible 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)
- Lisp_Object from, count, depth;
-{
- CHECK_NUMBER (from, 0);
- CHECK_NUMBER (count, 1);
- CHECK_NUMBER (depth, 2);
-
- return scan_lists (XINT (from), XINT (count), XINT (depth), 0);
-}
-
-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\
-\n\
-If the beginning or end of (the accessible 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.")
- (from, count)
- Lisp_Object from, count;
-{
- CHECK_NUMBER (from, 0);
- CHECK_NUMBER (count, 1);
-
- return scan_lists (XINT (from), XINT (count), 0, 1);
-}
-
-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).")
- ()
-{
- int beg = BEGV;
- int pos = PT;
-
- while (pos > beg && !char_quoted (pos - 1)
- && (SYNTAX (FETCH_CHAR (pos - 1)) == Squote
- || SYNTAX_PREFIX (FETCH_CHAR (pos - 1))))
- pos--;
-
- SET_PT (pos);
-
- return Qnil;
-}
-
-/* Parse forward from FROM to END,
- assuming that FROM has state OLDSTATE (nil means FROM is start of function),
- and return a description of the state of the parse at END.
- If STOPBEFORE is nonzero, stop at the start of an atom.
- If COMMENTSTOP is nonzero, stop at the start of a comment. */
-
-static void
-scan_sexps_forward (stateptr, from, end, targetdepth,
- stopbefore, oldstate, commentstop)
- struct lisp_parse_state *stateptr;
- register int from;
- int end, targetdepth, stopbefore;
- Lisp_Object oldstate;
- int commentstop;
-{
- struct lisp_parse_state state;
-
- register enum syntaxcode code;
- struct level { int last, prev; };
- struct level levelstart[100];
- register struct level *curlevel = levelstart;
- struct level *endlevel = levelstart + 100;
- char prev;
- register int depth; /* Paren depth of current scanning location.
- level - levelstart equals this except
- when the depth becomes negative. */
- int mindepth; /* Lowest DEPTH value seen. */
- int start_quoted = 0; /* Nonzero means starting after a char quote */
- Lisp_Object tem;
-
- immediate_quit = 1;
- QUIT;
-
- if (NILP (oldstate))
- {
- depth = 0;
- state.instring = -1;
- state.incomment = 0;
- state.comstyle = 0; /* comment style a by default */
- }
- else
- {
- tem = Fcar (oldstate);
- if (!NILP (tem))
- depth = XINT (tem);
- else
- depth = 0;
-
- oldstate = Fcdr (oldstate);
- oldstate = Fcdr (oldstate);
- oldstate = Fcdr (oldstate);
- tem = Fcar (oldstate);
- state.instring = !NILP (tem) ? XINT (tem) : -1;
-
- oldstate = Fcdr (oldstate);
- tem = Fcar (oldstate);
- state.incomment = !NILP (tem);
-
- oldstate = Fcdr (oldstate);
- tem = Fcar (oldstate);
- start_quoted = !NILP (tem);
-
- /* if the eight element of the list is nil, we are in comment
- style a. if it is non-nil, we are in comment style b */
- oldstate = Fcdr (oldstate);
- oldstate = Fcdr (oldstate);
- tem = Fcar (oldstate);
- state.comstyle = !NILP (tem);
- }
- state.quoted = 0;
- mindepth = depth;
-
- curlevel->prev = -1;
- curlevel->last = -1;
-
- /* Enter the loop at a place appropriate for initial state. */
-
- if (state.incomment) goto startincomment;
- if (state.instring >= 0)
- {
- if (start_quoted) goto startquotedinstring;
- goto startinstring;
- }
- if (start_quoted) goto startquoted;
-
- while (from < end)
- {
- code = SYNTAX (FETCH_CHAR (from));
- from++;
- if (code == Scomment)
- state.comstart = from-1;
-
- else if (from < end && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from - 1))
- && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from)))
- {
- /* Record the comment style we have entered so that only
- the comment-end sequence of the same style actually
- terminates the comment section. */
- code = Scomment;
- state.comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from));
- state.comstart = from-1;
- from++;
- }
-
- if (SYNTAX_PREFIX (FETCH_CHAR (from - 1)))
- continue;
- switch (SWITCH_ENUM_CAST (code))
- {
- case Sescape:
- case Scharquote:
- if (stopbefore) goto stop; /* this arg means stop at sexp start */
- curlevel->last = from - 1;
- startquoted:
- if (from == end) goto endquoted;
- from++;
- goto symstarted;
- /* treat following character as a word constituent */
- case Sword:
- case Ssymbol:
- if (stopbefore) goto stop; /* this arg means stop at sexp start */
- curlevel->last = from - 1;
- symstarted:
- while (from < end)
- {
- switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from))))
- {
- case Scharquote:
- case Sescape:
- from++;
- if (from == end) goto endquoted;
- break;
- case Sword:
- case Ssymbol:
- case Squote:
- break;
- default:
- goto symdone;
- }
- from++;
- }
- symdone:
- curlevel->prev = curlevel->last;
- break;
-
- startincomment:
- if (commentstop)
- goto done;
- if (from != BEGV)
- {
- /* Enter the loop in the middle so that we find
- a 2-char comment ender if we start in the middle of it. */
- prev = FETCH_CHAR (from - 1);
- goto startincomment_1;
- }
- /* At beginning of buffer, enter the loop the ordinary way. */
-
- case Scomment:
- state.incomment = 1;
- if (commentstop)
- goto done;
- while (1)
- {
- if (from == end) goto done;
- prev = FETCH_CHAR (from);
- if (SYNTAX (prev) == Sendcomment
- && SYNTAX_COMMENT_STYLE (prev) == state.comstyle)
- /* Only terminate the comment section if the endcomment
- of the same style as the start sequence has been
- encountered. */
- break;
- from++;
- startincomment_1:
- if (from < end && SYNTAX_COMEND_FIRST (prev)
- && SYNTAX_COMEND_SECOND (FETCH_CHAR (from))
- && SYNTAX_COMMENT_STYLE (prev) == state.comstyle)
- /* Only terminate the comment section if the end-comment
- sequence of the same style as the start sequence has
- been encountered. */
- { from++; break; }
- }
- state.incomment = 0;
- state.comstyle = 0; /* reset the comment style */
- break;
-
- case Sopen:
- if (stopbefore) goto stop; /* this arg means stop at sexp start */
- depth++;
- /* curlevel++->last ran into compiler bug on Apollo */
- curlevel->last = from - 1;
- if (++curlevel == endlevel)
- error ("Nesting too deep for parser");
- curlevel->prev = -1;
- curlevel->last = -1;
- if (targetdepth == depth) goto done;
- break;
-
- case Sclose:
- depth--;
- if (depth < mindepth)
- mindepth = depth;
- if (curlevel != levelstart)
- curlevel--;
- curlevel->prev = curlevel->last;
- if (targetdepth == depth) goto done;
- break;
-
- case Sstring:
- if (stopbefore) goto stop; /* this arg means stop at sexp start */
- curlevel->last = from - 1;
- state.instring = FETCH_CHAR (from - 1);
- startinstring:
- while (1)
- {
- if (from >= end) goto done;
- if (FETCH_CHAR (from) == state.instring) break;
- switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from))))
- {
- case Scharquote:
- case Sescape:
- from++;
- startquotedinstring:
- if (from >= end) goto endquoted;
- }
- from++;
- }
- state.instring = -1;
- curlevel->prev = curlevel->last;
- from++;
- break;
-
- case Smath:
- break;
- }
- }
- goto done;
-
- stop: /* Here if stopping before start of sexp. */
- from--; /* We have just fetched the char that starts it; */
- goto done; /* but return the position before it. */
-
- endquoted:
- state.quoted = 1;
- done:
- state.depth = depth;
- state.mindepth = mindepth;
- state.thislevelstart = curlevel->prev;
- state.prevlevelstart
- = (curlevel == levelstart) ? -1 : (curlevel - 1)->last;
- state.location = from;
- immediate_quit = 0;
-
- *stateptr = state;
-}
-
-/* This comment supplies the doc string for parse-partial-sexp,
- for make-docfile to see. We cannot put this in the real DEFUN
- due to limits in the Unix cpp.
-
-DEFUN ("parse-partial-sexp", Ffoo, Sfoo, 2, 6, 0,
- "Parse Lisp syntax starting at FROM until TO; return status of parse at TO.\n\
-Parsing stops at TO or when certain criteria are met;\n\
- point is set to where parsing stops.\n\
-If fifth arg STATE is omitted or nil,\n\
- parsing assumes that FROM is the beginning of a function.\n\
-Value is a list of eight elements describing final state of parsing:\n\
- 0. depth in parens.\n\
- 1. character address of start of innermost containing list; nil if none.\n\
- 2. character address of start of last complete sexp terminated.\n\
- 3. non-nil if inside a string.\n\
- (it is the character that will terminate the string.)\n\
- 4. t if inside a comment.\n\
- 5. t if following a quote character.\n\
- 6. the minimum paren-depth encountered during this scan.\n\
- 7. t if in a comment of style `b'.\n\
-If third arg TARGETDEPTH is non-nil, parsing stops if the depth\n\
-in parentheses becomes equal to TARGETDEPTH.\n\
-Fourth arg STOPBEFORE non-nil means stop when come to\n\
- any character that starts a sexp.\n\
-Fifth arg STATE is an eight-list like what this function returns.\n\
-It is used to initialize the state of the parse. Its second and third
-elements are ignored.
-Sixth args COMMENTSTOP non-nil means stop at the start of a comment.")
- (from, to, targetdepth, stopbefore, state, commentstop)
-*/
-
-DEFUN ("parse-partial-sexp", Fparse_partial_sexp, Sparse_partial_sexp, 2, 6, 0,
- 0 /* See immediately above */)
- (from, to, targetdepth, stopbefore, oldstate, commentstop)
- Lisp_Object from, to, targetdepth, stopbefore, oldstate, commentstop;
-{
- struct lisp_parse_state state;
- int target;
-
- if (!NILP (targetdepth))
- {
- CHECK_NUMBER (targetdepth, 3);
- target = XINT (targetdepth);
- }
- else
- target = -100000; /* We won't reach this depth */
-
- validate_region (&from, &to);
- scan_sexps_forward (&state, XINT (from), XINT (to),
- target, !NILP (stopbefore), oldstate,
- !NILP (commentstop));
-
- SET_PT (state.location);
-
- return Fcons (make_number (state.depth),
- Fcons (state.prevlevelstart < 0 ? Qnil : make_number (state.prevlevelstart),
- Fcons (state.thislevelstart < 0 ? Qnil : make_number (state.thislevelstart),
- Fcons (state.instring >= 0 ? make_number (state.instring) : Qnil,
- Fcons (state.incomment ? Qt : Qnil,
- Fcons (state.quoted ? Qt : Qnil,
- Fcons (make_number (state.mindepth),
- Fcons (state.comstyle ? Qt : Qnil,
- Qnil))))))));
-}
-
-init_syntax_once ()
-{
- register int i;
- Lisp_Object temp;
-
- /* This has to be done here, before we call Fmake_char_table. */
- Qsyntax_table = intern ("syntax-table");
- staticpro (&Qsyntax_table);
-
- /* Intern this now in case it isn't already done.
- Setting this variable twice is harmless.
- But don't staticpro it here--that is done in alloc.c. */
- Qchar_table_extra_slots = intern ("char-table-extra-slots");
-
- /* Now we are ready to set up this property, so we can
- create syntax tables. */
- Fput (Qsyntax_table, Qchar_table_extra_slots, make_number (0));
-
- temp = Fcons (make_number ((int) Swhitespace), Qnil);
-
- Vstandard_syntax_table = Fmake_char_table (Qsyntax_table, temp);
-
- temp = Fcons (make_number ((int) Sword), Qnil);
- for (i = 'a'; i <= 'z'; i++)
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, i, temp);
- for (i = 'A'; i <= 'Z'; i++)
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, i, temp);
- for (i = '0'; i <= '9'; i++)
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, i, temp);
-
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '$', temp);
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '%', temp);
-
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '(',
- Fcons (make_number (Sopen), make_number (')')));
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, ')',
- Fcons (make_number (Sclose), make_number ('(')));
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '[',
- Fcons (make_number (Sopen), make_number (']')));
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, ']',
- Fcons (make_number (Sclose), make_number ('[')));
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '{',
- Fcons (make_number (Sopen), make_number ('}')));
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '}',
- Fcons (make_number (Sclose), make_number ('{')));
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '"',
- Fcons (make_number ((int) Sstring), Qnil));
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '\\',
- Fcons (make_number ((int) Sescape), Qnil));
-
- temp = Fcons (make_number ((int) Ssymbol), Qnil);
- for (i = 0; i < 10; i++)
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, "_-+*/&|<>="[i], temp);
-
- temp = Fcons (make_number ((int) Spunct), Qnil);
- for (i = 0; i < 12; i++)
- SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, ".,;:?!#@~^'`"[i], temp);
-}
-
-syms_of_syntax ()
-{
- Qsyntax_table_p = intern ("syntax-table-p");
- 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.");
-
- defsubr (&Ssyntax_table_p);
- defsubr (&Ssyntax_table);
- defsubr (&Sstandard_syntax_table);
- defsubr (&Scopy_syntax_table);
- defsubr (&Sset_syntax_table);
- defsubr (&Schar_syntax);
- defsubr (&Smatching_paren);
- defsubr (&Smodify_syntax_entry);
- defsubr (&Sdescribe_syntax);
-
- defsubr (&Sforward_word);
-
- defsubr (&Sforward_comment);
- defsubr (&Sscan_lists);
- defsubr (&Sscan_sexps);
- defsubr (&Sbackward_prefix_chars);
- defsubr (&Sparse_partial_sexp);
-}
diff --git a/src/syntax.h b/src/syntax.h
deleted file mode 100644
index a4a8fb2a632..00000000000
--- a/src/syntax.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/* Declarations having to do with GNU Emacs syntax tables.
- Copyright (C) 1985, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-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 chartable whose elements are cons cells
- (CODE+FLAGS . MATCHING-CHAR). MATCHING-CHAR can be nil if the char
- is not a kind of parenthesis.
-
- The low 8 bits of CODE+FLAGS 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 */
- Sinherit, /* use the standard syntax table for this character */
- Smax /* Upper bound on codes that are meaningful */
- };
-
-/* Fetch the syntax entry for char C from table TABLE.
- This returns the whole entry (normally a cons cell)
- and does not do any kind of inheritance. */
-
-#if 1
-#define RAW_SYNTAX_ENTRY(table, c) \
- (XCHAR_TABLE (table)->contents[(unsigned char) (c)])
-
-#define SET_RAW_SYNTAX_ENTRY(table, c, val) \
- (XCHAR_TABLE (table)->contents[(unsigned char) (c)] = (val))
-#else
-#define RAW_SYNTAX_ENTRY(table, c) \
- ((c) >= 128 \
- ? raw_syntax_table_lookup (table, c) \
- : XCHAR_TABLE (table)->contents[(unsigned char) (c)])
-
-#define SET_RAW_SYNTAX_ENTRY(table, c, val) \
- ((c) >= 128 \
- ? set_raw_syntax_table_lookup (table, c, (val)) \
- : XCHAR_TABLE (table)->contents[(unsigned char) (c)] = (val))
-#endif
-
-/* Extract the information from the entry for character C
- in syntax table TABLE. Do inheritance. */
-
-#ifdef __GNUC__
-#define SYNTAX_ENTRY(c) \
- ({ Lisp_Object temp, table; \
- unsigned char cc = (c); \
- table = current_buffer->syntax_table; \
- while (!NILP (table)) \
- { \
- temp = RAW_SYNTAX_ENTRY (table, cc); \
- if (!NILP (temp)) \
- break; \
- table = XCHAR_TABLE (table)->parent; \
- } \
- temp; })
-
-#define SYNTAX(c) \
- ({ Lisp_Object temp; \
- temp = SYNTAX_ENTRY (c); \
- (CONSP (temp) \
- ? (enum syntaxcode) (XINT (XCONS (temp)->car) & 0xff) \
- : wrong_type_argument (Qconsp, temp)); })
-
-#define SYNTAX_WITH_FLAGS(c) \
- ({ Lisp_Object temp; \
- temp = SYNTAX_ENTRY (c); \
- (CONSP (temp) \
- ? XINT (XCONS (temp)->car) \
- : wrong_type_argument (Qconsp, temp)); })
-
-#define SYNTAX_MATCH(c) \
- ({ Lisp_Object temp; \
- temp = SYNTAX_ENTRY (c); \
- (CONSP (temp) \
- ? XINT (XCONS (temp)->cdr) \
- : wrong_type_argument (Qconsp, temp)); })
-#else
-extern Lisp_Object syntax_temp;
-extern Lisp_Object syntax_parent_lookup ();
-
-#define SYNTAX_ENTRY(c) \
- (syntax_temp \
- = RAW_SYNTAX_ENTRY (current_buffer->syntax_table, (c)), \
- (NILP (syntax_temp) \
- ? (syntax_temp \
- = syntax_parent_lookup (current_buffer->syntax_table, \
- (unsigned char) (c))) \
- : syntax_temp))
-
-#define SYNTAX(c) \
- (syntax_temp = SYNTAX_ENTRY ((c)), \
- (CONSP (syntax_temp) \
- ? (enum syntaxcode) (XINT (XCONS (syntax_temp)->car) & 0xff) \
- : wrong_type_argument (Qconsp, syntax_temp)))
-
-#define SYNTAX_WITH_FLAGS(c) \
- (syntax_temp = SYNTAX_ENTRY ((c)), \
- (CONSP (syntax_temp) \
- ? XINT (XCONS (syntax_temp)->car) \
- : wrong_type_argument (Qconsp, syntax_temp)))
-
-#define SYNTAX_MATCH(c) \
- (syntax_temp = SYNTAX_ENTRY ((c)), \
- (CONSP (syntax_temp) \
- ? XINT (XCONS (syntax_temp)->cdr) \
- : wrong_type_argument (Qconsp, syntax_temp)))
-#endif
-
-/* Then there are six 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.
- 5. This character is a prefix, for backward-prefix-chars.
- 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.
-
- bit 6 is used to discriminate between two different comment styles.
- Languages such as C++ allow two orthogonal syntax start/end pairs
- and bit 6 is used to determine whether a comment-end or Scommentend
- ends style a or b. Comment start sequences can start style a or b.
- Style a is always the default.
- */
-
-#define SYNTAX_COMSTART_FIRST(c) ((SYNTAX_WITH_FLAGS (c) >> 16) & 1)
-
-#define SYNTAX_COMSTART_SECOND(c) ((SYNTAX_WITH_FLAGS (c) >> 17) & 1)
-
-#define SYNTAX_COMEND_FIRST(c) ((SYNTAX_WITH_FLAGS (c) >> 18) & 1)
-
-#define SYNTAX_COMEND_SECOND(c) ((SYNTAX_WITH_FLAGS (c) >> 19) & 1)
-
-#define SYNTAX_PREFIX(c) ((SYNTAX_WITH_FLAGS (c) >> 20) & 1)
-
-/* extract the comment style bit from the syntax table entry */
-#define SYNTAX_COMMENT_STYLE(c) ((SYNTAX_WITH_FLAGS (c) >> 21) & 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];
-
-/* Indexed by syntax code, give the letter that describes it. */
-
-extern char syntax_code_spec[14];
diff --git a/src/sysdep.c b/src/sysdep.c
deleted file mode 100644
index 62a0194cdf1..00000000000
--- a/src/sysdep.c
+++ /dev/null
@@ -1,5143 +0,0 @@
-/* Interfaces to system-dependent kernel and library entries.
- Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <signal.h>
-#include <setjmp.h>
-
-#include <config.h>
-#include "lisp.h"
-#include "blockinput.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
-
-#ifdef WINDOWSNT
-#define read _read
-#define write _write
-#include <windows.h>
-extern int errno;
-#endif /* not WINDOWSNT */
-
-#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 */
-
-/* Does anyone other than VMS need this? */
-#ifndef fwrite
-#define sys_fwrite fwrite
-#else
-#undef fwrite
-#endif
-
-#ifndef HAVE_H_ERRNO
-extern int h_errno;
-#endif
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-/* Get _POSIX_VDISABLE, if it is available. */
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-/* Get SI_SRPC_DOMAIN, if it is available. */
-#ifdef HAVE_SYS_SYSTEMINFO_H
-#include <sys/systeminfo.h>
-#endif
-
-#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
-#include <dos.h>
-#include "dosfns.h"
-#include "msdos.h"
-#include <sys/param.h>
-
-#if __DJGPP__ > 1
-extern int etext;
-extern unsigned start __asm__ ("start");
-#endif
-#endif
-
-extern int errno;
-
-#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_SYSTEM /* avoid writing defined (BSD_SYSTEM) || defined (USG)
- because the vms compiler doesn't grok `defined' */
-#include <fcntl.h>
-#endif
-#ifdef USG
-#ifndef USG5
-#include <fcntl.h>
-#endif
-#endif
-#endif /* not 4.1 bsd */
-
-#ifndef MSDOS
-#include <sys/ioctl.h>
-#endif
-
-#include "systty.h"
-#include "syswait.h"
-
-#ifdef BROKEN_TIOCGWINSZ
-#undef TIOCGWINSZ
-#undef TIOCSWINSZ
-#endif
-
-#ifdef USG
-#include <sys/utsname.h>
-#include <string.h>
-#ifndef MEMORY_IN_STRING_H
-#include <memory.h>
-#endif
-#if defined (TIOCGWINSZ) || defined (ISC4_0)
-#ifdef NEED_SIOCTL
-#include <sys/sioctl.h>
-#endif
-#ifdef NEED_PTEM_H
-#include <sys/stream.h>
-#include <sys/ptem.h>
-#endif
-#endif /* TIOCGWINSZ or ISC4_0 */
-#endif /* USG */
-
-extern int quit_char;
-
-#include "frame.h"
-#include "window.h"
-#include "termhooks.h"
-#include "termchar.h"
-#include "termopts.h"
-#include "dispextern.h"
-#include "process.h"
-
-#ifdef WINDOWSNT
-#include <direct.h>
-/* In process.h which conflicts with the local copy. */
-#define _P_WAIT 0
-int _CRTAPI1 _spawnlp (int, const char *, const char *, ...);
-int _CRTAPI1 _getpid (void);
-#endif
-
-#ifdef NONSYSTEM_DIR_LIBRARY
-#include "ndir.h"
-#endif /* NONSYSTEM_DIR_LIBRARY */
-
-#include "syssignal.h"
-#include "systime.h"
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
-
-#ifndef HAVE_UTIMES
-#ifndef HAVE_STRUCT_UTIMBUF
-/* We want to use utime rather than utimes, but we couldn't find the
- structure declaration. We'll use the traditional one. */
-struct utimbuf {
- long actime;
- long modtime;
-};
-#endif
-#endif
-
-#ifndef VFORK_RETURN_TYPE
-#define VFORK_RETURN_TYPE int
-#endif
-
-/* 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
-
-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
-
-#ifdef HAVE_TERMIOS
-extern speed_t ospeed;
-#else
-extern short ospeed;
-#endif
-
-/* The file descriptor for Emacs's input terminal.
- Under Unix, this is normally zero except when using X;
- under VMS, we place the input channel number here. */
-int input_fd;
-
-/* Specify a different file descriptor for further input operations. */
-
-void
-change_input_fd (fd)
- int fd;
-{
- input_fd = fd;
-}
-
-/* Discard pending input on descriptor input_fd. */
-
-discard_tty_input ()
-{
-#ifndef WINDOWSNT
- struct emacs_tty 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_fd, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
- &buf.main, 0, 0, terminator_mask, 0, 0);
- queue_kbd_input ();
-#else /* not VMS */
-#ifdef APOLLO
- {
- int zero = 0;
- ioctl (input_fd, TIOCFLUSH, &zero);
- }
-#else /* not Apollo */
-#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
- while (dos_keyread () != -1)
- ;
-#else /* not MSDOS */
- EMACS_GET_TTY (input_fd, &buf);
- EMACS_SET_TTY (input_fd, &buf, 0);
-#endif /* not MSDOS */
-#endif /* not Apollo */
-#endif /* not VMS */
-#endif /* not WINDOWSNT */
-}
-
-#ifdef SIGTSTP
-
-/* Arrange for character C to be read as the next input from
- the terminal. */
-
-stuff_char (c)
- char c;
-{
- if (read_socket_hook)
- return;
-
-/* Should perhaps error if in batch mode */
-#ifdef TIOCSTI
- ioctl (input_fd, TIOCSTI, &c);
-#else /* no TIOCSTI */
- error ("Cannot stuff terminal input characters in this version of Unix");
-#endif /* no TIOCSTI */
-}
-
-#endif /* SIGTSTP */
-
-init_baud_rate ()
-{
- if (noninteractive)
- ospeed = 0;
- else
- {
-#ifdef DOS_NT
- ospeed = 15;
-#else /* not DOS_NT */
-#ifdef VMS
- struct sensemode sg;
-
- SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0,
- &sg.class, 12, 0, 0, 0, 0 );
- ospeed = sg.xmit_baud;
-#else /* not VMS */
-#ifdef HAVE_TERMIOS
- struct termios sg;
-
- sg.c_cflag = B9600;
- tcgetattr (input_fd, &sg);
- ospeed = cfgetospeed (&sg);
-#if defined (USE_GETOBAUD) && defined (getobaud)
- /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
- if (ospeed == 0)
- ospeed = getobaud (sg.c_cflag);
-#endif
-#else /* neither VMS nor TERMIOS */
-#ifdef HAVE_TERMIO
- struct termio sg;
-
- sg.c_cflag = B9600;
-#ifdef HAVE_TCATTR
- tcgetattr (input_fd, &sg);
-#else
- ioctl (input_fd, TCGETA, &sg);
-#endif
- ospeed = sg.c_cflag & CBAUD;
-#else /* neither VMS nor TERMIOS nor TERMIO */
- struct sgttyb sg;
-
- sg.sg_ospeed = B9600;
- if (ioctl (input_fd, TIOCGETP, &sg) < 0)
- abort ();
- ospeed = sg.sg_ospeed;
-#endif /* not HAVE_TERMIO */
-#endif /* not HAVE_TERMIOS */
-#endif /* not VMS */
-#endif /* not DOS_NT */
- }
-
- 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_SYSTEM
- wait3 (0, WNOHANG | WUNTRACED, 0);
-#else
- croak ("wait_without_blocking");
-#endif
- synch_process_alive = 0;
-}
-
-#endif /* not subprocesses */
-
-int wait_debugging; /* Set nonzero to make following function work under dbx
- (at least for bsd). */
-
-SIGTYPE
-wait_for_termination_signal ()
-{}
-
-/* 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
-#ifdef VMS
- int status;
-
- status = SYS$FORCEX (&pid, 0, 0);
- break;
-#else /* not VMS */
-#if defined (BSD_SYSTEM) || (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. */
- sigsetmask (sigmask (SIGCHLD));
- if (0 > kill (pid, 0))
- {
- sigsetmask (SIGEMPTYMASK);
- kill (getpid (), SIGCHLD);
- break;
- }
- if (wait_debugging)
- sleep (1);
- else
- sigpause (SIGEMPTYMASK);
-#else /* not BSD_SYSTEM, and not HPUX version >= 6 */
-#if defined (UNIPLUS)
- if (0 > kill (pid, 0))
- break;
- wait (0);
-#else /* neither BSD_SYSTEM nor UNIPLUS: random sysV */
-#ifdef POSIX_SIGNALS /* would this work for LINUX as well? */
- sigblock (sigmask (SIGCHLD));
- if (0 > kill (pid, 0))
- {
- sigunblock (sigmask (SIGCHLD));
- break;
- }
- sigpause (SIGEMPTYMASK);
-#else /* not POSIX_SIGNALS */
-#ifdef HAVE_SYSV_SIGPAUSE
- sighold (SIGCHLD);
- if (0 > kill (pid, 0))
- {
- sigrelse (SIGCHLD);
- break;
- }
- sigpause (SIGCHLD);
-#else /* not HAVE_SYSV_SIGPAUSE */
-#ifdef WINDOWSNT
- wait (0);
- break;
-#else /* not WINDOWSNT */
- 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 WINDOWSNT */
-#endif /* not HAVE_SYSV_SIGPAUSE */
-#endif /* not POSIX_SIGNALS */
-#endif /* not UNIPLUS */
-#endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
-#endif /* not VMS */
-#else /* not subprocesses */
-#if __DJGPP__ > 1
- break;
-#else /* not __DJGPP__ > 1 */
-#ifndef BSD4_1
- if (kill (pid, 0) < 0)
- break;
- wait (0);
-#else /* BSD4_1 */
- int status;
- status = wait (0);
- if (status == pid || status == -1)
- break;
-#endif /* BSD4_1 */
-#endif /* not __DJGPP__ > 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 HAVE_TERMIOS
- /* If we try this, we get hit with SIGTTIN, because
- the child's tty belongs to the child's pgrp. */
-#else
-#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
-#endif
-}
-
-#ifndef VMS
-/* 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;
-{
-#ifndef DOS_NT
- struct emacs_tty s;
-
- EMACS_GET_TTY (out, &s);
-
-#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
- s.main.c_oflag |= OPOST; /* Enable output postprocessing */
- s.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
-#ifdef NLDLY
- s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
- /* No output delays */
-#endif
- s.main.c_lflag &= ~ECHO; /* Disable echo */
- s.main.c_lflag |= ISIG; /* Enable signals */
-#ifdef IUCLC
- s.main.c_iflag &= ~IUCLC; /* Disable downcasing on input. */
-#endif
-#ifdef ISTRIP
- s.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
-#endif
-#ifdef OLCUC
- s.main.c_oflag &= ~OLCUC; /* Disable upcasing on output. */
-#endif
- s.main.c_oflag &= ~TAB3; /* Disable tab expansion */
- s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
-#if 0
- /* Said to be unnecessary: */
- s.main.c_cc[VMIN] = 1; /* minimum number of characters to accept */
- s.main.c_cc[VTIME] = 0; /* wait forever for at least 1 character */
-#endif
-
- s.main.c_lflag |= ICANON; /* Enable erase/kill and eof processing */
- s.main.c_cc[VEOF] = 04; /* insure that EOF is Control-D */
- s.main.c_cc[VERASE] = CDISABLE; /* disable erase processing */
- s.main.c_cc[VKILL] = CDISABLE; /* disable kill processing */
-
-#ifdef HPUX
- s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
-#endif /* HPUX */
-
-#ifdef AIX
-/* AIX enhanced edit loses NULs, so disable it */
-#ifndef IBMR2AIX
- s.main.c_line = 0;
- s.main.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.main.c_iflag &= ~IGNBRK;
- s.main.c_iflag &= ~BRKINT;
- /* QUIT and INTR work better as signals, so disable character forms */
- s.main.c_cc[VINTR] = 0377;
-#ifdef SIGNALS_VIA_CHARACTERS
- /* the QUIT and INTR character are used in process_send_signal
- so set them here to something useful. */
- if (s.main.c_cc[VQUIT] == 0377)
- s.main.c_cc[VQUIT] = '\\'&037; /* Control-\ */
- if (s.main.c_cc[VINTR] == 0377)
- s.main.c_cc[VINTR] = 'C'&037; /* Control-C */
-#else /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
- /* QUIT and INTR work better as signals, so disable character forms */
- s.main.c_cc[VQUIT] = 0377;
- s.main.c_cc[VINTR] = 0377;
- s.main.c_lflag &= ~ISIG;
-#endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
- s.main.c_cc[VEOL] = 0377;
- s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
-#endif /* AIX */
-
-#else /* not HAVE_TERMIO */
-
- s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
- | CBREAK | TANDEM);
- s.main.sg_flags |= LPASS8;
- s.main.sg_erase = 0377;
- s.main.sg_kill = 0377;
- s.lmode = LLITOUT | s.lmode; /* Don't strip 8th bit */
-
-#endif /* not HAVE_TERMIO */
-
- EMACS_SET_TTY (out, &s, 0);
-
-#ifdef BSD4_1
- if (interrupt_input)
- reset_sigio ();
-#endif /* BSD4_1 */
-#ifdef RTU
- {
- int zero = 0;
- ioctl (out, FIOASYNC, &zero);
- }
-#endif /* RTU */
-#endif /* not DOS_NT */
-}
-#endif /* not VMS */
-
-#endif /* subprocesses */
-
-/* Record a signal code and the handler for it. */
-struct save_signal
-{
- int code;
- SIGTYPE (*handler) ();
-};
-
-/* Suspend the Emacs process; give terminal to its superior. */
-
-sys_suspend ()
-{
-#ifdef VMS
- /* "Foster" parentage allows emacs to return to a subprocess that attached
- to the current emacs as a cheaper than starting a whole new process. This
- is set up by KEPTEDITOR.COM. */
- unsigned long parent_id, foster_parent_id;
- char *fpid_string;
-
- fpid_string = getenv ("EMACS_PARENT_PID");
- if (fpid_string != NULL)
- {
- sscanf (fpid_string, "%x", &foster_parent_id);
- if (foster_parent_id != 0)
- parent_id = foster_parent_id;
- else
- parent_id = getppid ();
- }
- else
- parent_id = getppid ();
-
- xfree (fpid_string); /* On VMS, this was malloc'd */
-
- if (parent_id && parent_id != 0xffffffff)
- {
- SIGTYPE (*oldsig)() = (int) signal (SIGINT, SIG_IGN);
- int status = LIB$ATTACH (&parent_id) & 1;
- signal (SIGINT, oldsig);
- return status;
- }
- else
- {
- struct {
- int l;
- char *a;
- } d_prompt;
- d_prompt.l = sizeof ("Emacs: "); /* Our special prompt */
- d_prompt.a = "Emacs: "; /* Just a reminder */
- LIB$SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt, 0);
- return 1;
- }
- return -1;
-#else
-#if defined(SIGTSTP) && !defined(MSDOS)
-
- {
- int pgrp = EMACS_GETPGRP (0);
- EMACS_KILLPG (pgrp, SIGTSTP);
- }
-
-#else /* No SIGTSTP */
-#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 /* No SIGTSTP or USG_JOBCTRL */
-
-/* On a system where suspending is not implemented,
- instead fork a subshell and let it talk directly to the terminal
- while we wait. */
- sys_subshell ();
-
-#endif /* no USG_JOBCTRL */
-#endif /* no SIGTSTP */
-#endif /* not VMS */
-}
-
-/* Fork a subshell. */
-
-sys_subshell ()
-{
-#ifndef VMS
-#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
- int st;
- char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS. */
-#endif
- int pid;
- struct save_signal saved_handlers[5];
- Lisp_Object dir;
- unsigned char *str = 0;
- int len;
-
- 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
-
- /* Mentioning current_buffer->buffer would mean including buffer.h,
- which somehow wedges the hp compiler. So instead... */
-
- dir = intern ("default-directory");
- if (NILP (Fboundp (dir)))
- goto xyzzy;
- dir = Fsymbol_value (dir);
- if (!STRINGP (dir))
- goto xyzzy;
-
- dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
- 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;
- xyzzy:
-
-#ifdef WINDOWSNT
- pid = -1;
-#else /* not WINDOWSNT */
-
-#ifdef MSDOS
- pid = 0;
-#if __DJGPP__ > 1
- save_signal_handlers (saved_handlers);
- synch_process_alive = 1;
-#endif /* __DJGPP__ > 1 */
-#else
- pid = vfork ();
- if (pid == -1)
- error ("Can't spawn subshell");
-#endif
-
- if (pid == 0)
-#endif /* not WINDOWSNT */
- {
- char *sh = 0;
-
-#ifdef MSDOS /* MW, Aug 1993 */
- getwd (oldwd);
- if (sh == 0)
- sh = (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
-#endif
- if (sh == 0)
- sh = (char *) egetenv ("SHELL");
- if (sh == 0)
- sh = "sh";
-
- /* Use our buffer's default directory for the subshell. */
- if (str)
- chdir (str);
-
-#ifdef subprocesses
- close_process_descs (); /* Close Emacs's pipes/ptys */
-#endif
-
-#ifdef SET_EMACS_PRIORITY
- {
- extern int emacs_priority;
-
- if (emacs_priority < 0)
- nice (-emacs_priority);
- }
-#endif
-
-#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
- st = system (sh);
- chdir (oldwd);
-#if 0 /* This is also reported if last command executed in subshell failed, KFS */
- if (st)
- report_file_error ("Can't execute subshell", Fcons (build_string (sh), Qnil));
-#endif
-#else /* not MSDOS */
-#ifdef WINDOWSNT
- /* Waits for process completion */
- pid = _spawnlp (_P_WAIT, sh, sh, NULL);
- if (pid == -1)
- write (1, "Can't execute subshell", 22);
-
- take_console ();
-#else /* not WINDOWSNT */
- execlp (sh, sh, 0);
- write (1, "Can't execute subshell", 22);
- _exit (1);
-#endif /* not WINDOWSNT */
-#endif /* not MSDOS */
- }
-
- /* Do this now if we did not do it before. */
-#if !defined (MSDOS) || __DJGPP__ == 1
- save_signal_handlers (saved_handlers);
- synch_process_alive = 1;
-#endif
-
-#ifndef MSDOS
- wait_for_termination (pid);
-#endif
- restore_signal_handlers (saved_handlers);
- synch_process_alive = 0;
-#endif /* !VMS */
-}
-
-save_signal_handlers (saved_handlers)
- struct save_signal *saved_handlers;
-{
- while (saved_handlers->code)
- {
- saved_handlers->handler
- = (SIGTYPE (*) ()) 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 (fd)
- int fd;
-{
-#ifdef FASYNC
- old_fcntl_flags = fcntl (fd, F_GETFL, 0) & ~FASYNC;
- fcntl (fd, F_SETFL, old_fcntl_flags | FASYNC);
-#endif
- interrupts_deferred = 0;
-}
-
-reset_sigio ()
-{
- unrequest_sigio ();
-}
-
-#ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
-
-request_sigio ()
-{
- if (read_socket_hook)
- return;
-
-#ifdef SIGWINCH
- sigunblock (sigmask (SIGWINCH));
-#endif
- fcntl (input_fd, F_SETFL, old_fcntl_flags | FASYNC);
-
- interrupts_deferred = 0;
-}
-
-unrequest_sigio ()
-{
- if (read_socket_hook)
- return;
-
-#ifdef SIGWINCH
- sigblock (sigmask (SIGWINCH));
-#endif
- fcntl (input_fd, 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;
-
- if (read_socket_hook)
- return;
-
- ioctl (input_fd, FIOASYNC, &on);
- interrupts_deferred = 0;
-}
-
-unrequest_sigio ()
-{
- int off = 0;
-
- if (read_socket_hook)
- return;
-
- ioctl (input_fd, FIOASYNC, &off);
- interrupts_deferred = 1;
-}
-
-#else /* not FASYNC, not STRIDE */
-
-#ifdef _CX_UX
-
-#include <termios.h>
-
-request_sigio ()
-{
- int on = 1;
- sigset_t st;
-
- if (read_socket_hook)
- return;
-
- sigemptyset(&st);
- sigaddset(&st, SIGIO);
- ioctl (input_fd, FIOASYNC, &on);
- interrupts_deferred = 0;
- sigprocmask(SIG_UNBLOCK, &st, (sigset_t *)0);
-}
-
-unrequest_sigio ()
-{
- int off = 0;
-
- if (read_socket_hook)
- return;
-
- ioctl (input_fd, FIOASYNC, &off);
- interrupts_deferred = 1;
-}
-
-#else /* ! _CX_UX */
-
-request_sigio ()
-{
- if (read_socket_hook)
- return;
-
- croak ("request_sigio");
-}
-
-unrequest_sigio ()
-{
- if (read_socket_hook)
- return;
-
- croak ("unrequest_sigio");
-}
-
-#endif /* _CX_UX */
-#endif /* STRIDE */
-#endif /* FASYNC */
-#endif /* F_SETFL */
-
-/* Saving and restoring the process group of Emacs's terminal. */
-
-#ifdef BSD_PGRPS
-
-/* The process group of which Emacs was a member when it initially
- started.
-
- If Emacs was in its own process group (i.e. inherited_pgroup ==
- getpid ()), then we know we're running under a shell with job
- control (Emacs would never be run as part of a pipeline).
- Everything is fine.
-
- If Emacs was not in its own process group, then we know we're
- running under a shell (or a caller) that doesn't know how to
- separate itself from Emacs (like sh). Emacs must be in its own
- process group in order to receive SIGIO correctly. In this
- situation, we put ourselves in our own pgroup, forcibly set the
- tty's pgroup to our pgroup, and make sure to restore and reinstate
- the tty's pgroup just like any other terminal setting. If
- inherited_group was not the tty's pgroup, then we'll get a
- SIGTTmumble when we try to change the tty's pgroup, and a CONT if
- it goes foreground in the future, which is what should happen. */
-int inherited_pgroup;
-
-/* Split off the foreground process group to Emacs alone.
- When we are in the foreground, but not started in our own process
- group, redirect the TTY to point to our own process group. We need
- to be in our own process group to receive SIGIO properly. */
-narrow_foreground_group ()
-{
- int me = getpid ();
-
- setpgrp (0, inherited_pgroup);
- if (inherited_pgroup != me)
- EMACS_SET_TTY_PGRP (input_fd, &me);
- setpgrp (0, me);
-}
-
-/* Set the tty to our original foreground group. */
-widen_foreground_group ()
-{
- if (inherited_pgroup != getpid ())
- EMACS_SET_TTY_PGRP (input_fd, &inherited_pgroup);
- setpgrp (0, inherited_pgroup);
-}
-
-#endif /* BSD_PGRPS */
-
-/* Getting and setting emacs_tty structures. */
-
-/* Set *TC to the parameters associated with the terminal FD.
- Return zero if all's well, or -1 if we ran into an error we
- couldn't deal with. */
-int
-emacs_get_tty (fd, settings)
- int fd;
- struct emacs_tty *settings;
-{
- /* Retrieve the primary parameters - baud rate, character size, etcetera. */
-#ifdef HAVE_TCATTR
- /* We have those nifty POSIX tcmumbleattr functions. */
- if (tcgetattr (fd, &settings->main) < 0)
- return -1;
-
-#else
-#ifdef HAVE_TERMIO
- /* The SYSV-style interface? */
- if (ioctl (fd, TCGETA, &settings->main) < 0)
- return -1;
-
-#else
-#ifdef VMS
- /* Vehemently Monstrous System? :-) */
- if (! (SYS$QIOW (0, fd, IO$_SENSEMODE, settings, 0, 0,
- &settings->main.class, 12, 0, 0, 0, 0)
- & 1))
- return -1;
-
-#else
-#ifndef DOS_NT
- /* I give up - I hope you have the BSD ioctls. */
- if (ioctl (fd, TIOCGETP, &settings->main) < 0)
- return -1;
-#endif /* not DOS_NT */
-#endif
-#endif
-#endif
-
- /* Suivant - Do we have to get struct ltchars data? */
-#ifdef HAVE_LTCHARS
- if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
- return -1;
-#endif
-
- /* How about a struct tchars and a wordful of lmode bits? */
-#ifdef HAVE_TCHARS
- if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
- || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
- return -1;
-#endif
-
- /* We have survived the tempest. */
- return 0;
-}
-
-
-/* Set the parameters of the tty on FD according to the contents of
- *SETTINGS. If FLUSHP is non-zero, we discard input.
- Return 0 if all went well, and -1 if anything failed. */
-
-int
-emacs_set_tty (fd, settings, flushp)
- int fd;
- struct emacs_tty *settings;
- int flushp;
-{
- /* Set the primary parameters - baud rate, character size, etcetera. */
-#ifdef HAVE_TCATTR
- int i;
- /* We have those nifty POSIX tcmumbleattr functions.
- William J. Smith <wjs@wiis.wang.com> writes:
- "POSIX 1003.1 defines tcsetattr() to return success if it was
- able to perform any of the requested actions, even if some
- of the requested actions could not be performed.
- We must read settings back to ensure tty setup properly.
- AIX requires this to keep tty from hanging occasionally." */
- /* This make sure that we don't loop indefinitely in here. */
- for (i = 0 ; i < 10 ; i++)
- if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
- {
- if (errno == EINTR)
- continue;
- else
- return -1;
- }
- else
- {
- struct termios new;
-
- /* Get the current settings, and see if they're what we asked for. */
- tcgetattr (fd, &new);
- /* We cannot use memcmp on the whole structure here because under
- * aix386 the termios structure has some reserved field that may
- * not be filled in.
- */
- if ( new.c_iflag == settings->main.c_iflag
- && new.c_oflag == settings->main.c_oflag
- && new.c_cflag == settings->main.c_cflag
- && new.c_lflag == settings->main.c_lflag
- && memcmp(new.c_cc, settings->main.c_cc, NCCS) == 0)
- break;
- else
- continue;
- }
-
-#else
-#ifdef HAVE_TERMIO
- /* The SYSV-style interface? */
- if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0)
- return -1;
-
-#else
-#ifdef VMS
- /* Vehemently Monstrous System? :-) */
- if (! (SYS$QIOW (0, fd, IO$_SETMODE, &input_iosb, 0, 0,
- &settings->main.class, 12, 0, 0, 0, 0)
- & 1))
- return -1;
-
-#else
-#ifndef DOS_NT
- /* I give up - I hope you have the BSD ioctls. */
- if (ioctl (fd, (flushp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
- return -1;
-#endif /* not DOS_NT */
-
-#endif
-#endif
-#endif
-
- /* Suivant - Do we have to get struct ltchars data? */
-#ifdef HAVE_LTCHARS
- if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
- return -1;
-#endif
-
- /* How about a struct tchars and a wordful of lmode bits? */
-#ifdef HAVE_TCHARS
- if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
- || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
- return -1;
-#endif
-
- /* We have survived the tempest. */
- return 0;
-}
-
-
-/* The initial tty mode bits */
-struct emacs_tty old_tty;
-
-/* 1 if we have been through init_sys_modes. */
-int term_initted;
-
-/* 1 if outer tty status has been recorded. */
-int old_tty_valid;
-
-#ifdef BSD4_1
-/* BSD 4.1 needs to keep track of the lmode bits in order to start
- sigio. */
-int lmode;
-#endif
-
-#ifndef F_SETOWN_BUG
-#ifdef F_SETOWN
-int old_fcntl_owner;
-#endif /* F_SETOWN */
-#endif /* F_SETOWN_BUG */
-
-/* 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 HAVE_LTCHARS
-static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
-#endif
-#ifdef HAVE_TCHARS
- static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
-#endif
-
-init_sys_modes ()
-{
- struct emacs_tty tty;
-
-#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)
- input_ef = get_kbd_event_flag ();
- /* LIB$GET_EF (&input_ef); */
- SYS$CLREF (input_ef);
- waiting_for_ast = 0;
- if (!timer_ef)
- timer_ef = get_timer_event_flag ();
- /* LIB$GET_EF (&timer_ef); */
- SYS$CLREF (timer_ef);
-#if 0
- 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.");
-#endif
- if (input_ef / 32 != timer_ef / 32)
- croak ("Input and timer event flags in different clusters.");
-#if 0
- input_eflist = ((unsigned) 1 << (input_ef % 32)) |
- ((unsigned) 1 << (process_ef % 32));
-#endif
- timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
- ((unsigned) 1 << (timer_ef % 32));
-#ifndef VMS4_4
- sys_access_reinit ();
-#endif
-#endif /* not VMS */
-
-#ifdef BSD_PGRPS
- if (! read_socket_hook && EQ (Vwindow_system, Qnil))
- narrow_foreground_group ();
-#endif
-
-#ifdef HAVE_WINDOW_SYSTEM
- /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
- needs the initialization code below. */
- if (!read_socket_hook && EQ (Vwindow_system, Qnil))
-#endif
- {
- EMACS_GET_TTY (input_fd, &old_tty);
-
- old_tty_valid = 1;
-
- tty = old_tty;
-
-#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
-#ifdef DGUX
- /* This allows meta to be sent on 8th bit. */
- tty.main.c_iflag &= ~INPCK; /* don't check input for parity */
-#endif
- tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */
- tty.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
-#ifdef INLCR /* I'm just being cautious,
- since I can't check how widespread INLCR is--rms. */
- tty.main.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */
-#endif
-#ifdef ISTRIP
- tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
-#endif
- tty.main.c_lflag &= ~ECHO; /* Disable echo */
- tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */
-#ifdef IEXTEN
- tty.main.c_lflag &= ~IEXTEN; /* Disable other editing characters. */
-#endif
- tty.main.c_lflag |= ISIG; /* Enable signals */
- if (flow_control)
- {
- tty.main.c_iflag |= IXON; /* Enable start/stop output control */
-#ifdef IXANY
- tty.main.c_iflag &= ~IXANY;
-#endif /* IXANY */
- }
- else
- tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */
- tty.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL
- on output */
- tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */
-#ifdef CS8
- if (meta_key)
- {
- tty.main.c_cflag |= CS8; /* allow 8th bit on input */
- tty.main.c_cflag &= ~PARENB;/* Don't check parity */
- }
-#endif
- tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
- /* Set up C-g 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.main.c_cc[VQUIT] = quit_char;
- tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
- tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */
-#ifdef VSWTCH
- tty.main.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use
- of C-z */
-#endif /* VSWTCH */
-#if defined (mips) || defined (HAVE_TCATTR)
-#ifdef VSUSP
- tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */
-#endif /* VSUSP */
-#ifdef V_DSUSP
- tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */
-#endif /* V_DSUSP */
-#ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
- tty.main.c_cc[VDSUSP] = CDISABLE;
-#endif /* VDSUSP */
-#ifdef VLNEXT
- tty.main.c_cc[VLNEXT] = CDISABLE;
-#endif /* VLNEXT */
-#ifdef VREPRINT
- tty.main.c_cc[VREPRINT] = CDISABLE;
-#endif /* VREPRINT */
-#ifdef VWERASE
- tty.main.c_cc[VWERASE] = CDISABLE;
-#endif /* VWERASE */
-#ifdef VDISCARD
- tty.main.c_cc[VDISCARD] = CDISABLE;
-#endif /* VDISCARD */
-#ifdef VSTART
- tty.main.c_cc[VSTART] = CDISABLE;
-#endif /* VSTART */
-#ifdef VSTOP
- tty.main.c_cc[VSTOP] = CDISABLE;
-#endif /* VSTOP */
-#endif /* mips or HAVE_TCATTR */
-#ifdef SET_LINE_DISCIPLINE
- /* Need to explicitly request TERMIODISC line discipline or
- Ultrix's termios does not work correctly. */
- tty.main.c_line = SET_LINE_DISCIPLINE;
-#endif
-#ifdef AIX
-#ifndef IBMR2AIX
- /* AIX enhanced edit loses NULs, so disable it. */
- tty.main.c_line = 0;
- tty.main.c_iflag &= ~ASCEDIT;
-#else
- tty.main.c_cc[VSTRT] = 255;
- tty.main.c_cc[VSTOP] = 255;
- tty.main.c_cc[VSUSP] = 255;
- tty.main.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.main.c_iflag &= ~IGNBRK;
- tty.main.c_iflag &= ~BRKINT;
-#endif
-#else /* if not HAVE_TERMIO */
-#ifdef VMS
- tty.main.tt_char |= TT$M_NOECHO;
- if (meta_key)
- tty.main.tt_char |= TT$M_EIGHTBIT;
- if (flow_control)
- tty.main.tt_char |= TT$M_TTSYNC;
- else
- tty.main.tt_char &= ~TT$M_TTSYNC;
- tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
-#else /* not VMS (BSD, that is) */
-#ifndef DOS_NT
- tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
- if (meta_key)
- tty.main.sg_flags |= ANYP;
- tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
-#endif /* not DOS_NT */
-#endif /* not VMS (BSD, that is) */
-#endif /* not HAVE_TERMIO */
-
- /* 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. */
-#ifndef HAVE_TERMIO
-#ifdef HAVE_TCHARS
- /* Note: if not using CBREAK mode, it makes no difference how we
- set this */
- tty.tchars = new_tchars;
- tty.tchars.t_intrc = quit_char;
- if (flow_control)
- {
- tty.tchars.t_startc = '\021';
- tty.tchars.t_stopc = '\023';
- }
-
- tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode;
-#ifdef ultrix
- /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
- anything, and leaving it in breaks the meta key. Go figure. */
- tty.lmode &= ~LLITOUT;
-#endif
-
-#ifdef BSD4_1
- lmode = tty.lmode;
-#endif
-
-#endif /* HAVE_TCHARS */
-#endif /* not HAVE_TERMIO */
-
-#ifdef HAVE_LTCHARS
- tty.ltchars = new_ltchars;
-#endif /* HAVE_LTCHARS */
-#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
- if (!term_initted)
- internal_terminal_init ();
- dos_ttraw ();
-#endif
-
- EMACS_SET_TTY (input_fd, &tty, 0);
-
- /* This code added to insure that, if flow-control is not to be used,
- we have an unlocked terminal at the start. */
-
-#ifdef TCXONC
- if (!flow_control) ioctl (input_fd, TCXONC, 1);
-#endif
-#ifndef APOLLO
-#ifdef TIOCSTART
- if (!flow_control) ioctl (input_fd, TIOCSTART, 0);
-#endif
-#endif
-
-#if defined (HAVE_TERMIOS) || defined (HPUX9)
-#ifdef TCOON
- if (!flow_control) tcflow (input_fd, TCOON);
-#endif
-#endif
-
-#ifdef AIXHFT
- 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 /* AIXHFT */
-
-#ifdef VMS
-/* Appears to do nothing when in PASTHRU mode.
- SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
- interrupt_signal, oob_chars, 0, 0, 0, 0);
-*/
- queue_kbd_input (0);
-#endif /* VMS */
- }
-
-#ifdef F_SETFL
-#ifndef F_SETOWN_BUG
-#ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
- if (interrupt_input
- && ! read_socket_hook && EQ (Vwindow_system, Qnil))
- {
- old_fcntl_owner = fcntl (input_fd, F_GETOWN, 0);
- fcntl (input_fd, F_SETOWN, getpid ());
- init_sigio (input_fd);
- }
-#endif /* F_GETOWN */
-#endif /* F_SETOWN_BUG */
-#endif /* F_SETFL */
-
-#ifdef BSD4_1
- if (interrupt_input)
- init_sigio (input_fd);
-#endif
-
-#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
-#ifdef HAVE_WINDOW_SYSTEM
- /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
- needs the initialization code below. */
- if (! read_socket_hook && EQ (Vwindow_system, Qnil))
-#endif
- set_terminal_modes ();
-
- if (term_initted && no_redraw_on_reenter)
- {
- if (display_completed)
- direct_output_forward_char (0);
- }
- else
- {
- frame_garbaged = 1;
- if (FRAMEP (Vterminal_frame))
- FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 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 ()
-{
- struct emacs_tty tty;
-
- EMACS_GET_TTY (input_fd, &tty);
- return EMACS_TTY_TABS_OK (&tty);
-}
-
-/* Get terminal size from system.
- Store number of lines into *HEIGHTP and width into *WIDTHP.
- We store 0 if there's no valid information. */
-
-get_frame_size (widthp, heightp)
- int *widthp, *heightp;
-{
-
-#ifdef TIOCGWINSZ
-
- /* BSD-style. */
- struct winsize size;
-
- if (ioctl (input_fd, TIOCGWINSZ, &size) == -1)
- *widthp = *heightp = 0;
- else
- {
- *widthp = size.ws_col;
- *heightp = size.ws_row;
- }
-
-#else
-#ifdef TIOCGSIZE
-
- /* SunOS - style. */
- struct ttysize size;
-
- if (ioctl (input_fd, TIOCGSIZE, &size) == -1)
- *widthp = *heightp = 0;
- else
- {
- *widthp = size.ts_cols;
- *heightp = size.ts_lines;
- }
-
-#else
-#ifdef VMS
-
- struct sensemode tty;
-
- SYS$QIOW (0, input_fd, IO$_SENSEMODE, &tty, 0, 0,
- &tty.class, 12, 0, 0, 0, 0);
- *widthp = tty.scr_wid;
- *heightp = tty.scr_len;
-
-#else
-#ifdef MSDOS
- *widthp = ScreenCols ();
- *heightp = ScreenRows ();
-#else /* system doesn't know size */
- *widthp = 0;
- *heightp = 0;
-#endif
-
-#endif /* not VMS */
-#endif /* not SunOS-style */
-#endif /* not BSD-style */
-}
-
-/* Set the logical window size associated with descriptor FD
- to HEIGHT and WIDTH. This is used mainly with ptys. */
-
-int
-set_window_size (fd, height, width)
- int fd, height, width;
-{
-#ifdef TIOCSWINSZ
-
- /* BSD-style. */
- struct winsize size;
- size.ws_row = height;
- size.ws_col = width;
-
- if (ioctl (fd, TIOCSWINSZ, &size) == -1)
- return 0; /* error */
- else
- return 1;
-
-#else
-#ifdef TIOCSSIZE
-
- /* SunOS - style. */
- struct ttysize size;
- size.ts_lines = height;
- size.ts_cols = width;
-
- if (ioctl (fd, TIOCGSIZE, &size) == -1)
- return 0;
- else
- return 1;
-#else
- return -1;
-#endif /* not SunOS-style */
-#endif /* not BSD-style */
-}
-
-
-/* Prepare the terminal for exiting Emacs; move the cursor to the
- bottom of the frame, turn off interrupt-driven I/O, etc. */
-reset_sys_modes ()
-{
- if (noninteractive)
- {
- fflush (stdout);
- return;
- }
- if (!term_initted)
- return;
-#ifdef HAVE_WINDOW_SYSTEM
- /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
- needs the clean-up code below. */
- if (read_socket_hook || !EQ (Vwindow_system, Qnil))
- return;
-#endif
- cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
- clear_end_of_line (FRAME_WIDTH (selected_frame));
- /* clear_end_of_line may move the cursor */
- cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
-#if defined (IBMR2AIX) && defined (AIXHFT)
- {
- /* 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_SYSTEM
-#ifndef BSD4_1
- /* Avoid possible loss of output when changing terminal modes. */
- fsync (fileno (stdout));
-#endif
-#endif
-
-#ifdef F_SETFL
-#ifndef F_SETOWN_BUG
-#ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
- if (interrupt_input)
- {
- reset_sigio ();
- fcntl (input_fd, F_SETOWN, old_fcntl_owner);
- }
-#endif /* F_SETOWN */
-#endif /* F_SETOWN_BUG */
-#ifdef O_NDELAY
- fcntl (input_fd, F_SETFL, fcntl (input_fd, F_GETFL, 0) & ~O_NDELAY);
-#endif
-#endif /* F_SETFL */
-#ifdef BSD4_1
- if (interrupt_input)
- reset_sigio ();
-#endif /* BSD4_1 */
-
- if (old_tty_valid)
- while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
- ;
-
-#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
- dos_ttcooked ();
-#endif
-
-#ifdef SET_LINE_DISCIPLINE
- /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
- A different old line discipline is therefore not restored, yet.
- Restore the old line discipline by hand. */
- ioctl (0, TIOCSETD, &old_tty.main.c_line);
-#endif
-
-#ifdef AIXHFT
- hft_reset ();
-#endif
-
-#ifdef BSD_PGRPS
- widen_foreground_group ();
-#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_fd == 0)
- {
- status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0);
- if (! (status & 1))
- LIB$STOP (status);
- }
-}
-
-/* Deassigning the input channel is done before exiting. */
-
-stop_vms_input ()
-{
- return SYS$DASSGN (input_fd);
-}
-
-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;
- extern kbd_input_ast ();
-
- waiting_for_ast = 0;
- stop_input = 0;
- status = SYS$QIO (0, input_fd, 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;
- extern EMACS_TIME *input_available_clear_time;
-
- 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)
- {
- struct input_event e;
- e.kind = ascii_keystroke;
- XSETINT (e.code, c);
- XSETFRAME (e.frame_or_window, selected_frame);
- kbd_buffer_store_event (&e);
- }
- if (input_available_clear_time)
- EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
- 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++;
- prepare_menu_bars ();
- 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_event! */
- {
- SYS$CANCEL (input_fd);
- 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_fd);
- 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 (fd)
- int fd;
-{
- 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 HAVE_TEXT_START
-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 HAVE_TEXT_START */
-
-/*
- * 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 boundary 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
-#ifdef ORDINARY_LINK
- /*
- * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
- * data_start isn't defined. We take the address of environ, which
- * is known to live at or near the start of the system crt0.c, and
- * we don't sweat the handful of bytes that might lose.
- */
- extern char **environ;
-
- return((char *) &environ);
-#else
- extern int data_start;
- return ((char *) &data_start);
-#endif /* ORDINARY_LINK */
-#endif /* DATA_START */
-}
-#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 */
-
-/* init_system_name sets up the string for the Lisp function
- system-name to return. */
-
-#ifdef BSD4_1
-#include <whoami.h>
-#endif
-
-extern Lisp_Object Vsystem_name;
-
-#ifndef BSD4_1
-#ifndef VMS
-#ifdef HAVE_SOCKETS
-#include <sys/socket.h>
-#include <netdb.h>
-#endif /* HAVE_SOCKETS */
-#endif /* not VMS */
-#endif /* not BSD4_1 */
-
-void
-init_system_name ()
-{
-#ifdef BSD4_1
- Vsystem_name = build_string (sysname);
-#else
-#ifdef VMS
- char *sp, *end;
- if ((sp = egetenv ("SYS$NODE")) == 0)
- Vsystem_name = build_string ("vax-vms");
- else if ((end = index (sp, ':')) == 0)
- Vsystem_name = build_string (sp);
- else
- Vsystem_name = make_string (sp, end - sp);
-#else
-#ifndef HAVE_GETHOSTNAME
- struct utsname uts;
- uname (&uts);
- Vsystem_name = build_string (uts.nodename);
-#else /* HAVE_GETHOSTNAME */
- unsigned int hostname_size = 256;
- char *hostname = (char *) alloca (hostname_size);
-
- /* Try to get the host name; if the buffer is too short, try
- again. Apparently, the only indication gethostname gives of
- whether the buffer was large enough is the presence or absence
- of a '\0' in the string. Eech. */
- for (;;)
- {
- gethostname (hostname, hostname_size - 1);
- hostname[hostname_size - 1] = '\0';
-
- /* Was the buffer large enough for the '\0'? */
- if (strlen (hostname) < hostname_size - 1)
- break;
-
- hostname_size <<= 1;
- hostname = (char *) alloca (hostname_size);
- }
-#ifdef HAVE_SOCKETS
- /* Turn the hostname into the official, fully-qualified hostname.
- Don't do this if we're going to dump; this can confuse system
- libraries on some machines and make the dumped emacs core dump. */
-#ifndef CANNOT_DUMP
- if (initialized)
-#endif /* not CANNOT_DUMP */
- {
- struct hostent *hp;
- int count;
- for (count = 0;; count++)
- {
-#ifdef TRY_AGAIN
- h_errno = 0;
-#endif
- hp = gethostbyname (hostname);
-#ifdef TRY_AGAIN
- if (! (hp == 0 && h_errno == TRY_AGAIN))
-#endif
- break;
- if (count >= 5)
- break;
- Fsleep_for (make_number (1), Qnil);
- }
- if (hp)
- {
- char *fqdn = (char *) hp->h_name;
- char *p;
-
- if (!index (fqdn, '.'))
- {
- /* We still don't have a fully qualified domain name.
- Try to find one in the list of alternate names */
- char **alias = hp->h_aliases;
- while (*alias && !index (*alias, '.'))
- alias++;
- if (*alias)
- fqdn = *alias;
- }
- hostname = fqdn;
-#if 0
- /* Convert the host name to lower case. */
- /* Using ctype.h here would introduce a possible locale
- dependence that is probably wrong for hostnames. */
- p = hostname;
- while (*p)
- {
- if (*p >= 'A' && *p <= 'Z')
- *p += 'a' - 'A';
- p++;
- }
-#endif
- }
- }
-#endif /* HAVE_SOCKETS */
-#if (HAVE_SYSINFO && defined (SI_SRPC_DOMAIN)) || HAVE_GETDOMAINNAME
- if (! index (hostname, '.'))
- {
- /* The hostname is not fully qualified. Append the domain name. */
-
- int hostlen = strlen (hostname);
- int domain_size = 256;
-
- for (;;)
- {
- char *fqdn = (char *) alloca (hostlen + 1 + domain_size);
- char *domain = fqdn + hostlen + 1;
-#if HAVE_SYSINFO && defined (SI_SRPC_DOMAIN)
- int sys_domain_size = sysinfo (SI_SRPC_DOMAIN, domain, domain_size);
- if (sys_domain_size <= 0)
- break;
- if (domain_size < sys_domain_size)
- {
- domain_size = sys_domain_size;
- continue;
- }
-#else /* HAVE_GETDOMAINNAME */
- if (getdomainname (domain, domain_size - 1) != 0 || ! *domain)
- break;
- domain[domain_size - 1] = '\0';
- if (strlen (domain) == domain_size - 1)
- {
- domain_size *= 2;
- continue;
- }
-#endif /* HAVE_GETDOMAINNAME */
- strcpy (fqdn, hostname);
- fqdn[hostlen] = '.';
- hostname = fqdn;
- break;
- }
- }
-#endif /*! ((HAVE_SYSINFO && defined (SI_SRPC_DOMAIN)) || HAVE_GETDOMAINNAME)*/
- Vsystem_name = build_string (hostname);
-#endif /* HAVE_GETHOSTNAME */
-#endif /* VMS */
-#endif /* BSD4_1 */
- {
- unsigned char *p;
- for (p = XSTRING (Vsystem_name)->data; *p; p++)
- if (*p == ' ' || *p == '\t')
- *p = '-';
- }
-}
-
-#ifndef MSDOS
-#ifndef VMS
-#if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
-
-#include "sysselect.h"
-#undef select
-
-#if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
-/* Cause explanatory error message at compile time,
- since the select emulation is not good enough for X. */
-int *x = &x_windows_lose_if_no_select_system_call;
-#endif
-
-/* 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;
-
-SIGTYPE
-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);
-}
-
-#ifndef WINDOWSNT
-/* Only rfds are checked. */
-int
-sys_select (nfds, rfds, wfds, efds, timeout)
- int nfds;
- SELECT_TYPE *rfds, *wfds, *efds;
- EMACS_TIME *timeout;
-{
- int ravail = 0, old_alarm;
- SELECT_TYPE orfds;
- int timeoutval;
- int *local_timeout;
- extern int proc_buffered_char[];
-#ifndef subprocesses
- int process_tick = 0, update_tick = 0;
-#else
- extern int process_tick, update_tick;
-#endif
- SIGTYPE (*old_trap) ();
- unsigned char buf;
-
-#if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
- /* If we're using X, then the native select will work; we only need the
- emulation for non-X usage. */
- if (!NILP (Vwindow_system))
- return select (nfds, rfds, wfds, efds, timeout);
-#endif
- timeoutval = timeout ? EMACS_SECS (*timeout) : 100000;
- local_timeout = &timeoutval;
- FD_ZERO (&orfds);
- if (rfds)
- {
- orfds = *rfds;
- FD_ZERO (rfds);
- }
- if (wfds)
- FD_ZERO (wfds);
- if (efds)
- FD_ZERO (efds);
-
- /* If we are looking only for the terminal, with no timeout,
- just read it and wait -- that's more efficient. */
- if (*local_timeout == 100000 && process_tick == update_tick
- && FD_ISSET (0, &orfds))
- {
- int fd;
- for (fd = 1; fd < nfds; ++fd)
- if (FD_ISSET (fd, &orfds))
- goto hardway;
- if (! detect_input_pending ())
- read_input_waiting ();
- FD_SET (0, rfds);
- return 1;
- }
-
- hardway:
- /* 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, fd;
-
- if (rfds)
- {
- for (to_check = nfds, fd = 0; --to_check >= 0; fd++)
- {
- if (FD_ISSET (fd, &orfds))
- {
- int avail = 0, status = 0;
-
- if (fd == 0)
- 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)
- {
- FD_SET (fd, rfds);
- ravail++;
- }
- }
- }
- }
- if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
- break;
- old_alarm = alarm (0);
- old_trap = 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 (FD_ISSET (0, &orfds))
- {
- read_input_waiting ();
- if (detect_input_pending ())
- 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;
-}
-#endif /* not WINDOWSNT */
-
-/* Read keyboard input into the standard buffer,
- waiting for at least one character. */
-
-/* Make all keyboard buffers much bigger when using a window system. */
-#ifdef HAVE_WINDOW_SYSTEM
-#define BUFFER_SIZE_FACTOR 16
-#else
-#define BUFFER_SIZE_FACTOR 1
-#endif
-
-read_input_waiting ()
-{
- struct input_event e;
- int nread, i;
- extern int quit_char;
-
- if (read_socket_hook)
- {
- struct input_event buf[256];
-
- read_alarm_should_throw = 0;
- if (! setjmp (read_alarm_throw))
- nread = (*read_socket_hook) (0, buf, 256, 1, 0);
- else
- nread = -1;
-
- /* Scan the chars for C-g and store them in kbd_buffer. */
- for (i = 0; i < nread; i++)
- {
- kbd_buffer_store_event (&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].kind == ascii_keystroke
- && buf[i].code == quit_char)
- break;
- }
- }
- else
- {
- char buf[3];
- nread = read (fileno (stdin), buf, 1);
-
- /* Scan the chars for C-g and store them in kbd_buffer. */
- e.kind = ascii_keystroke;
- XSETFRAME (e.frame_or_window, selected_frame);
- e.modifiers = 0;
- for (i = 0; i < nread; i++)
- {
- /* Convert chars > 0177 to meta events if desired.
- We do this under the same conditions that read_avail_input does. */
- if (read_socket_hook == 0)
- {
- /* If the user says she has a meta key, then believe her. */
- if (meta_key == 1 && (buf[i] & 0x80))
- e.modifiers = meta_modifier;
- if (meta_key != 2)
- buf[i] &= ~0x80;
- }
-
- XSETINT (e.code, buf[i]);
- kbd_buffer_store_event (&e);
- /* 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 HAVE_SELECT */
-#endif /* not VMS */
-#endif /* not MSDOS */
-
-#ifdef BSD4_1
-/*
- * 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 (fd)
- int fd;
-{
- if (noninteractive)
- return;
- lmode = LINTRUP | lmode;
- ioctl (fd, 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 old_mask, empty_mask, full_mask, temp_mask;
-static struct sigaction new_action, old_action;
-
-init_signals ()
-{
- sigemptyset (&empty_mask);
- sigfillset (&full_mask);
-}
-
-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;
-#ifdef SA_RESTART
- /* Emacs mostly works better with restartable system services. If this
- * flag exists, we probably want to turn it on here.
- */
- new_action.sa_flags = SA_RESTART;
-#else
- new_action.sa_flags = 0;
-#endif
- sigaction (signal_number, &new_action, &old_action);
- return (old_action.sa_handler);
-#endif /* DGUX */
-}
-
-#ifndef __GNUC__
-/* If we're compiling with GCC, we don't need this function, since it
- can be written as a macro. */
-sigset_t
-sys_sigmask (int sig)
-{
- sigset_t mask;
- sigemptyset (&mask);
- sigaddset (&mask, sig);
- return mask;
-}
-#endif
-
-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 HAVE_RANDOM
-#ifdef random
-#define HAVE_RANDOM
-#endif
-#endif
-
-/* Figure out how many bits the system's random number generator uses.
- `random' and `lrand48' are assumed to return 31 usable bits.
- BSD `rand' returns a 31 bit value but the low order bits are unusable;
- so we'll shift it and treat it like the 15-bit USG `rand'. */
-
-#ifndef RAND_BITS
-# ifdef HAVE_RANDOM
-# define RAND_BITS 31
-# else /* !HAVE_RANDOM */
-# ifdef HAVE_LRAND48
-# define RAND_BITS 31
-# define random lrand48
-# else /* !HAVE_LRAND48 */
-# define RAND_BITS 15
-# if RAND_MAX == 32767
-# define random rand
-# else /* RAND_MAX != 32767 */
-# if RAND_MAX == 2147483647
-# define random() (rand () >> 16)
-# else /* RAND_MAX != 2147483647 */
-# ifdef USG
-# define random rand
-# else
-# define random() (rand () >> 16)
-# endif /* !USG */
-# endif /* RAND_MAX != 2147483647 */
-# endif /* RAND_MAX != 32767 */
-# endif /* !HAVE_LRAND48 */
-# endif /* !HAVE_RANDOM */
-#endif /* !RAND_BITS */
-
-void
-seed_random (arg)
- long arg;
-{
-#ifdef HAVE_RANDOM
- srandom ((unsigned int)arg);
-#else
-# ifdef HAVE_LRAND48
- srand48 (arg);
-# else
- srand ((unsigned int)arg);
-# endif
-#endif
-}
-
-/*
- * Build a full Emacs-sized word out of whatever we've got.
- * This suffices even for a 64-bit architecture with a 15-bit rand.
- */
-long
-get_random ()
-{
- long val = random ();
-#if VALBITS > RAND_BITS
- val = (val << RAND_BITS) ^ random ();
-#if VALBITS > 2*RAND_BITS
- val = (val << RAND_BITS) ^ random ();
-#if VALBITS > 3*RAND_BITS
- val = (val << RAND_BITS) ^ random ();
-#if VALBITS > 4*RAND_BITS
- val = (val << RAND_BITS) ^ random ();
-#endif /* need at least 5 */
-#endif /* need at least 4 */
-#endif /* need at least 3 */
-#endif /* need at least 2 */
- return val & ((1L << VALBITS) - 1);
-}
-
-#ifdef WRONG_NAME_INSQUE
-
-insque (q,p)
- caddr_t q,p;
-{
- _insque (q,p);
-}
-
-#endif
-
-#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 SHARABLE_LIB_BUG
-/* Variables declared noshare and initialized in sharable 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 /* SHARABLE_LIB_BUG */
-#endif /* LINK_CRTL_SHARE */
-#endif /* VMS */
-
-#ifndef HAVE_STRERROR
-#ifndef WINDOWSNT
-char *
-strerror (errnum)
- int errnum;
-{
- extern char *sys_errlist[];
- extern int sys_nerr;
-
- if (errnum >= 0 && errnum < sys_nerr)
- return sys_errlist[errnum];
- return (char *) "Unknown error";
-}
-#endif /* not WINDOWSNT */
-#endif /* ! HAVE_STRERROR */
-
-#ifdef INTERRUPTIBLE_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 /* INTERRUPTIBLE_OPEN */
-
-#ifdef INTERRUPTIBLE_CLOSE
-
-sys_close (fd)
- int fd;
-{
- int did_retry = 0;
- register int rtnval;
-
- while ((rtnval = close (fd)) == -1
- && (errno == EINTR))
- did_retry = 1;
-
- /* If close is interrupted SunOS 4.1 may or may not have closed the
- file descriptor. If it did the second close will fail with
- errno = EBADF. That means we have succeeded. */
- if (rtnval == -1 && did_retry && errno == EBADF)
- return 0;
-
- return rtnval;
-}
-
-#endif /* INTERRUPTIBLE_CLOSE */
-
-#ifdef INTERRUPTIBLE_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, bytes_written;
-
- bytes_written = 0;
-
- while (nbyte > 0)
- {
- rtnval = write (fildes, buf, nbyte);
-
- if (rtnval == -1)
- {
- if (errno == EINTR)
- continue;
- else
- return (bytes_written ? bytes_written : -1);
- }
-
- buf += rtnval;
- nbyte -= rtnval;
- bytes_written += rtnval;
- }
- return (bytes_written);
-}
-
-#endif /* INTERRUPTIBLE_IO */
-
-#ifndef HAVE_VFORK
-#ifndef WINDOWSNT
-/*
- * Substitute fork for vfork on USG flavors.
- */
-
-VFORK_RETURN_TYPE
-vfork ()
-{
- return (fork ());
-}
-#endif /* not WINDOWSNT */
-#endif /* not HAVE_VFORK */
-
-#ifdef USG
-/*
- * All of the following are for USG.
- *
- * On USG systems the system calls are INTERRUPTIBLE 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 occurrence in the source. Sure, this
- * adds an extra level of function call overhead but it is almost
- * always negligible. Fred Fish, Unisoft Systems Inc.
- */
-
-#ifndef HAVE_SYS_SIGLIST
-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 */
-#ifdef AIXHFT
- "HFT grant", /* 28 SIGGRANT */
- "HFT retract", /* 29 SIGRETRACT */
- "HFT sound done", /* 30 SIGSOUND */
- "HFT input ready", /* 31 SIGMSG */
-#endif
-#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 */
-#ifdef sun
- "window size change", /* 20 SIGWINCH */
- "urgent socket condition", /* 21 SIGURG */
- "pollable event occurred", /* 22 SIGPOLL */
- "stop (cannot be caught or ignored)", /* 23 SIGSTOP */
- "user stop requested from tty", /* 24 SIGTSTP */
- "stopped process has been continued", /* 25 SIGCONT */
- "background tty read attempted", /* 26 SIGTTIN */
- "background tty write attempted", /* 27 SIGTTOU */
- "virtual timer expired", /* 28 SIGVTALRM */
- "profiling timer expired", /* 29 SIGPROF */
- "exceeded cpu limit", /* 30 SIGXCPU */
- "exceeded file size limit", /* 31 SIGXFSZ */
- "process's lwps are blocked", /* 32 SIGWAITING */
- "special signal used by thread library", /* 33 SIGLWP */
-#ifdef SIGFREEZE
- "Special Signal Used By CPR", /* 34 SIGFREEZE */
-#endif
-#ifdef SIGTHAW
- "Special Signal Used By CPR", /* 35 SIGTHAW */
-#endif
-#endif /* sun */
-#endif /* not AIX */
- 0
- };
-#endif /* HAVE_SYS_SIGLIST */
-
-/*
- * 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 ();
-
- BLOCK_INPUT; /* getcwd uses malloc */
- spath = npath = getcwd ((char *) 0, MAXPATHLEN);
- if (spath == 0)
- return spath;
- /* 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 */
- UNBLOCK_INPUT;
- return pathname;
-}
-
-#endif /* HAVE_GETWD */
-
-/*
- * 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).
- */
-
-#ifndef HAVE_RENAME
-
-rename (from, to)
- const char *from;
- const char *to;
-{
- if (access (from, 0) == 0)
- {
- unlink (to);
- if (link (from, to) == 0)
- if (unlink (from) == 0)
- return (0);
- }
- return (-1);
-}
-
-#endif
-
-
-#ifdef HPUX
-#ifndef HAVE_PERROR
-
-/* 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 /* not HAVE_PERROR */
-#endif /* HPUX */
-
-#ifndef HAVE_DUP2
-
-/*
- * Emulate BSD dup2. First close newd if it already exists.
- * Then, attempt to dup oldd. If not successful, call dup2 recursively
- * until we are, then close the unsuccessful ones.
- */
-
-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 ("can't dup2 (%i,%i) : %s", oldd, newd, strerror (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 VMS
-#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;
- if (tzp != 0)
- tzp->tz_minuteswest = -1;
-}
-
-#endif
-#endif
-#endif
-#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
-
-/*
- * 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 occurred", /* 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>
-
-#if defined(BROKEN_CLOSEDIR) || !defined(HAVE_CLOSEDIR)
-
-int
-closedir (dirp)
- register DIR *dirp; /* stream from opendir */
-{
- int rtnval;
-
- rtnval = sys_close (dirp->dd_fd);
-
- /* Some systems (like Solaris) allocate the buffer and the DIR all
- in one block. Why in the world are we freeing this ourselves
- anyway? */
-#if ! (defined (sun) && defined (USG5_4))
- xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
-#endif
- xfree ((char *) dirp);
-
- return rtnval;
-}
-#endif /* BROKEN_CLOSEDIR or 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;
-
- BLOCK_INPUT;
- if (fstat (fd, &sbuf) < 0
- || (sbuf.st_mode & S_IFMT) != S_IFDIR
- || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
- {
- sys_close (fd);
- UNBLOCK_INPUT;
- return 0; /* bad luck today */
- }
- UNBLOCK_INPUT;
-
- 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);
- xfree ((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 */
-
-
-int
-set_file_times (filename, atime, mtime)
- char *filename;
- EMACS_TIME atime, mtime;
-{
-#ifdef HAVE_UTIMES
- struct timeval tv[2];
- tv[0] = atime;
- tv[1] = mtime;
- return utimes (filename, tv);
-#else /* not HAVE_UTIMES */
- struct utimbuf utb;
- utb.actime = EMACS_SECS (atime);
- utb.modtime = EMACS_SECS (mtime);
- return utime (filename, &utb);
-#endif /* not HAVE_UTIMES */
-}
-
-/* mkdir and rmdir functions, for systems which don't have them. */
-
-#ifndef HAVE_MKDIR
-/*
- * Written by Robert Rother, Mariah Corporation, August 1985.
- *
- * If you want it, it's yours. All I ask in return is that if you
- * figure out how to do this in a Bourne Shell script you send me
- * a copy.
- * sdcsvax!rmr or rmr@uscd
- *
- * Severely hacked over by John Gilmore to make a 4.2BSD compatible
- * subroutine. 11Mar86; hoptoad!gnu
- *
- * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
- * subroutine didn't return EEXIST. It does now.
- */
-
-/*
- * Make a directory.
- */
-#ifdef MKDIR_PROTOTYPE
-MKDIR_PROTOTYPE
-#else
-int
-mkdir (dpath, dmode)
- char *dpath;
- int dmode;
-#endif
-{
- int cpid, status, fd;
- struct stat statbuf;
-
- if (stat (dpath, &statbuf) == 0)
- {
- errno = EEXIST; /* Stat worked, so it already exists */
- return -1;
- }
-
- /* If stat fails for a reason other than non-existence, return error */
- if (errno != ENOENT)
- return -1;
-
- synch_process_alive = 1;
- switch (cpid = fork ())
- {
-
- case -1: /* Error in fork */
- return (-1); /* Errno is set already */
-
- case 0: /* Child process */
- /*
- * Cheap hack to set mode of new directory. Since this
- * child process is going away anyway, we zap its umask.
- * FIXME, this won't suffice to set SUID, SGID, etc. on this
- * directory. Does anybody care?
- */
- status = umask (0); /* Get current umask */
- status = umask (status | (0777 & ~dmode)); /* Set for mkdir */
- fd = sys_open("/dev/null", 2);
- if (fd >= 0)
- {
- dup2 (fd, 0);
- dup2 (fd, 1);
- dup2 (fd, 2);
- }
- execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
- _exit (-1); /* Can't exec /bin/mkdir */
-
- default: /* Parent process */
- wait_for_termination (cpid);
- }
-
- if (synch_process_death != 0 || synch_process_retcode != 0)
- {
- errno = EIO; /* We don't know why, but */
- return -1; /* /bin/mkdir failed */
- }
-
- return 0;
-}
-#endif /* not HAVE_MKDIR */
-
-#ifndef HAVE_RMDIR
-int
-rmdir (dpath)
- char *dpath;
-{
- int cpid, status, fd;
- struct stat statbuf;
-
- if (stat (dpath, &statbuf) != 0)
- {
- /* Stat just set errno. We don't have to */
- return -1;
- }
-
- synch_process_alive = 1;
- switch (cpid = fork ())
- {
-
- case -1: /* Error in fork */
- return (-1); /* Errno is set already */
-
- case 0: /* Child process */
- fd = sys_open("/dev/null", 2);
- if (fd >= 0)
- {
- dup2 (fd, 0);
- dup2 (fd, 1);
- dup2 (fd, 2);
- }
- execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
- _exit (-1); /* Can't exec /bin/rmdir */
-
- default: /* Parent process */
- wait_for_termination (cpid);
- }
-
- if (synch_process_death != 0 || synch_process_retcode != 0)
- {
- errno = EIO; /* We don't know why, but */
- return -1; /* /bin/rmdir failed */
- }
-
- return 0;
-}
-#endif /* !HAVE_RMDIR */
-
-
-
-/* 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 buflen s.s_buflen
-#define code s.s_code
-#define bufadr s.s_bufadr
-#define retlenadr s.s_retlenadr
-
-#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;
- unsigned short int dummy;
- item itemlst[3];
- static int constant = ACL$C_FILE;
- DESCRIPTOR (path_desc, path);
- DESCRIPTOR (user_desc, user);
-
- flags = 0;
- acces = 0;
- if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
- return stat;
- if (mode & R_OK)
- acces |= CHP$M_READ;
- if (mode & W_OK)
- acces |= CHP$M_WRITE;
- itemlst[0].buflen = sizeof (int);
- itemlst[0].code = CHP$_FLAGS;
- itemlst[0].bufadr = (char *) &flags;
- itemlst[0].retlenadr = &dummy;
- itemlst[1].buflen = sizeof (int);
- itemlst[1].code = CHP$_ACCESS;
- itemlst[1].bufadr = (char *) &acces;
- itemlst[1].retlenadr = &dummy;
- itemlst[2].end = CHP$_END;
- stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, 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 WRITABLE(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) && WRITABLE (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 (WRITABLE (XAB$V_WLD)) /* World writable */
- return 0;
- if (WRITABLE (XAB$V_GRP) &&
- (unsigned short) (xab.xab$l_uic >> 16) == grpid)
- return 0; /* Group writable */
- if (WRITABLE (XAB$V_OWN) &&
- (xab.xab$l_uic & 0xFFFF) == memid)
- return 0; /* Owner writable */
-
- return -1; /* Not writable */
-}
-#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, *val;
- extern char *getcwd ();
-
-#define MAXPATHLEN 1024
-
- ptr = xmalloc (MAXPATHLEN);
- val = getcwd (ptr, MAXPATHLEN);
- if (val == 0)
- {
- xfree (ptr);
- return val;
- }
- strcpy (pathname, ptr);
- xfree (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_incrementer;
- 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_incrementer);
- name = va_arg (list_incrementer, char *);
- mode = va_arg (list_incrementer, int);
- if (count > 2)
- rfd = va_arg (list_incrementer, int);
- va_end (list_incrementer);
- 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 style, 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 = 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 ()
-{}
-
-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 separate
- 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 terminal*/
- 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 AIXHFT
-
-/* 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 /* AIXHFT */
-
-#ifdef USE_DL_STUBS
-
-/* These are included on Sunos 4.1 when we do not use shared libraries.
- X11 libraries may refer to these functions but (we hope) do not
- actually call them. */
-
-void *
-dlopen ()
-{
- return 0;
-}
-
-void *
-dlsym ()
-{
- return 0;
-}
-
-int
-dlclose ()
-{
- return -1;
-}
-
-#endif /* USE_DL_STUBS */
-
-#ifndef BSTRING
-
-#ifndef bzero
-
-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 */
-}
-
-#endif /* no bzero */
-#endif /* BSTRING */
-
-#if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
-#undef bcopy
-
-/* 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 (&length, b1, b2);
-#else
- while (length-- > 0)
- *b2++ = *b1++;
-#endif /* not VMS */
-}
-#endif /* (defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
-
-#ifndef BSTRING
-#ifndef bcmp
-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 /* no bcmp */
-#endif /* not BSTRING */
diff --git a/src/sysselect.h b/src/sysselect.h
deleted file mode 100644
index 5a392c381a7..00000000000
--- a/src/sysselect.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* sysselect.h - System-dependent definitions for the select function.
- Copyright (C) 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifdef HAVE_SYS_SELECT
-#include <sys/select.h>
-#endif
-
-#ifdef FD_SET
-#ifdef FD_SETSIZE
-#define MAXDESC FD_SETSIZE
-#else
-#define MAXDESC 64
-#endif
-#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 */
-
-#if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
-#define select sys_select
-#endif
diff --git a/src/syssignal.h b/src/syssignal.h
deleted file mode 100644
index b7e646a2787..00000000000
--- a/src/syssignal.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/* syssignal.h - System-dependent definitions for signals.
- Copyright (C) 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifdef POSIX_SIGNALS
-
-/* Don't #include <signal.h>. That header should always be #included
- before "config.h", because some configuration files (like s/hpux.h)
- indicate that SIGIO doesn't work by #undef-ing SIGIO. If this file
- #includes <signal.h>, then that will re-#define SIGIO and confuse
- things. */
-
-#define SIGMASKTYPE sigset_t
-
-#define SIGEMPTYMASK (empty_mask)
-#define SIGFULLMASK (full_mask)
-extern sigset_t empty_mask, full_mask, temp_mask;
-
-/* POSIX pretty much destroys any possibility of writing sigmask as a
- macro in standard C. */
-#ifndef sigmask
-#ifdef __GNUC__
-#define sigmask(SIG) \
- ({ \
- sigset_t _mask; \
- sigemptyset (&_mask); \
- sigaddset (&_mask, SIG); \
- _mask; \
- })
-#else /* ! defined (__GNUC__) */
-extern sigset_t sys_sigmask ();
-#define sigmask(SIG) (sys_sigmask (SIG))
-#endif /* ! defined (__GNUC__) */
-#endif
-
-#define sigpause(SIG) sys_sigpause (SIG)
-#define sigblock(SIG) sys_sigblock (SIG)
-#define sigunblock(SIG) sys_sigunblock (SIG)
-#ifndef sigsetmask
-#define sigsetmask(SIG) sys_sigsetmask (SIG)
-#endif
-#define sighold(SIG) ONLY_USED_IN_BSD_4_1
-#define sigrelse(SIG) ONLY_USED_IN_BSD_4_1
-#undef signal
-#define signal(SIG,ACT) sys_signal(SIG,ACT)
-
-/* Whether this is what all systems want or not, this is what
- appears to be assumed in the source, for example data.c:arith_error. */
-typedef RETSIGTYPE (*signal_handler_t) (/*int*/);
-
-signal_handler_t sys_signal (/*int signal_number, signal_handler_t 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)
-
-#else /* ! defined (POSIX_SIGNALS) */
-#ifdef USG5_4
-
-#ifndef sigblock
-#define sigblock(sig) (sigprocmask (SIG_BLOCK, SIGEMPTYMASK | sig, NULL))
-#endif
-
-#define sigunblock(sig) (sigprocmask (SIG_SETMASK, SIGFULLMASK & ~(sig), NULL))
-
-#else
-#ifdef USG
-
-#define sigunblock(sig)
-
-#else
-
-#define sigunblock(SIG) \
-{ SIGMASKTYPE omask = sigblock (SIGEMPTYMASK); sigsetmask (omask & ~SIG); }
-
-#endif /* ! defined (USG) */
-#endif /* ! defined (USG5_4) */
-#endif /* ! defined (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 BSD4_1
-#define sigfree() sigsetmask (SIGEMPTYMASK)
-#endif /* not BSD4_1 */
-
-#ifdef BSD4_1
-#define SIGIO SIGTINT
-/* sigfree is in sysdep.c */
-#endif /* BSD4_1 */
-
-/* On bsd, [man says] kill does not accept a negative number to kill a pgrp.
- Must do that using the killpg call. */
-#ifdef BSD_SYSTEM
-#define EMACS_KILLPG(gid, signo) (killpg ( (gid), (signo)))
-#else
-#ifdef WINDOWSNT
-#define EMACS_KILLPG(gid, signo) (kill (gid, signo))
-#else
-#define EMACS_KILLPG(gid, signo) (kill (-(gid), (signo)))
-#endif
-#endif
-
-/* Define SIGCHLD as an alias for SIGCLD. There are many conditionals
- testing SIGCHLD. */
-#ifndef VMS
-#ifdef SIGCLD
-#ifndef SIGCHLD
-#define SIGCHLD SIGCLD
-#endif /* SIGCHLD */
-#endif /* ! defined (SIGCLD) */
-#endif /* VMS */
diff --git a/src/systime.h b/src/systime.h
deleted file mode 100644
index 44c1f7d4de1..00000000000
--- a/src/systime.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/* systime.h - System-dependent definitions for time manipulations.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-
-#ifdef HAVE_TZNAME
-#ifndef tzname /* For SGI. */
-extern char *tzname[]; /* RS6000 and others want it this way. */
-#endif
-#endif
-
-/* SVr4 doesn't actually declare this in its #include files. */
-#ifdef USG5_4
-extern long timezone;
-#endif
-
-#ifdef VMS
-#ifdef VAXC
-#include "vmstime.h"
-#endif
-#endif
-
-/* On some configurations (hpux8.0, X11R4), sys/time.h and X11/Xos.h
- disagree about the name of the guard symbol. */
-#ifdef HPUX
-#ifdef _STRUCT_TIMEVAL
-#ifndef __TIMEVAL__
-#define __TIMEVAL__
-#endif
-#endif
-#endif
-
-/* EMACS_TIME is the type to use to represent temporal intervals -
- struct timeval on some systems, int on others. It can be passed as
- the timeout argument to the select system call.
-
- EMACS_SECS (TIME) is an rvalue for the seconds component of TIME.
- EMACS_SET_SECS (TIME, SECONDS) sets that to SECONDS.
-
- EMACS_HAS_USECS is defined iff EMACS_TIME has a usecs component.
- EMACS_USECS (TIME) is an rvalue for the microseconds component of TIME.
- This returns zero if EMACS_TIME doesn't have a microseconds component.
- EMACS_SET_USECS (TIME, MICROSECONDS) sets that to MICROSECONDS.
- This does nothing if EMACS_TIME doesn't have a microseconds component.
-
- EMACS_SET_SECS_USECS (TIME, SECS, USECS) sets both components of TIME.
-
- EMACS_GET_TIME (TIME) stores the current system time in TIME, which
- should be an lvalue.
-
- EMACS_ADD_TIME (DEST, SRC1, SRC2) adds SRC1 to SRC2 and stores the
- result in DEST. SRC should not be negative.
-
- EMACS_SUB_TIME (DEST, SRC1, SRC2) subtracts SRC2 from SRC1 and
- stores the result in DEST. SRC should not be negative.
- EMACS_TIME_NEG_P (TIME) is true iff TIME is negative.
-
-*/
-
-#ifdef HAVE_TIMEVAL
-
-#define EMACS_HAS_USECS
-
-#define EMACS_TIME struct timeval
-#define EMACS_SECS(time) ((time).tv_sec + 0)
-#define EMACS_USECS(time) ((time).tv_usec + 0)
-#define EMACS_SET_SECS(time, seconds) ((time).tv_sec = (seconds))
-#define EMACS_SET_USECS(time, microseconds) ((time).tv_usec = (microseconds))
-
-/* On SVR4, the compiler may complain if given this extra BSD arg. */
-#ifdef GETTIMEOFDAY_ONE_ARGUMENT
-#define EMACS_GET_TIME(time) \
-{ \
- gettimeofday (&(time)); \
-}
-#else /* not GETTIMEOFDAY_ONE_ARGUMENT */
-#define EMACS_GET_TIME(time) \
-{ \
- struct timezone dummy; \
- gettimeofday (&(time), &dummy); \
-}
-#endif /* not GETTIMEOFDAY_ONE_ARGUMENT */
-
-#define EMACS_ADD_TIME(dest, src1, src2) \
-{ \
- (dest).tv_sec = (src1).tv_sec + (src2).tv_sec; \
- (dest).tv_usec = (src1).tv_usec + (src2).tv_usec; \
- if ((dest).tv_usec > 1000000) \
- (dest).tv_usec -= 1000000, (dest).tv_sec++; \
-}
-
-#define EMACS_SUB_TIME(dest, src1, src2) \
-{ \
- (dest).tv_sec = (src1).tv_sec - (src2).tv_sec; \
- (dest).tv_usec = (src1).tv_usec - (src2).tv_usec; \
- if ((dest).tv_usec < 0) \
- (dest).tv_usec += 1000000, (dest).tv_sec--; \
-}
-
-#define EMACS_TIME_NEG_P(time) \
- ((long)(time).tv_sec < 0 \
- || ((time).tv_sec == 0 \
- && (long)(time).tv_usec < 0))
-
-#else /* ! defined (HAVE_TIMEVAL) */
-
-#define EMACS_TIME int
-#define EMACS_SECS(time) (time)
-#define EMACS_USECS(time) 0
-#define EMACS_SET_SECS(time, seconds) ((time) = (seconds))
-#define EMACS_SET_USECS(time, usecs) 0
-
-#define EMACS_GET_TIME(t) ((t) = time ((long *) 0))
-#define EMACS_ADD_TIME(dest, src1, src2) ((dest) = (src1) + (src2))
-#define EMACS_SUB_TIME(dest, src1, src2) ((dest) = (src1) - (src2))
-#define EMACS_TIME_NEG_P(t) ((t) < 0)
-
-#endif /* ! defined (HAVE_TIMEVAL) */
-
-#define EMACS_SET_SECS_USECS(time, secs, usecs) \
- (EMACS_SET_SECS (time, secs), EMACS_SET_USECS (time, usecs))
-
-extern int set_file_times ();
diff --git a/src/systty.h b/src/systty.h
deleted file mode 100644
index fda88d4c9da..00000000000
--- a/src/systty.h
+++ /dev/null
@@ -1,419 +0,0 @@
-/* systty.h - System-dependent definitions for terminals.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifdef HAVE_TERMIOS
-#define HAVE_TCATTR
-#endif
-
-/* If we defined these before and we are about to redefine them,
- prevent alarming warnings. */
-#ifdef BSD_TERMIOS
-#undef NL0
-#undef NL1
-#undef CR0
-#undef CR1
-#undef CR2
-#undef CR3
-#undef TAB0
-#undef TAB1
-#undef TAB2
-#undef XTABS
-#undef BS0
-#undef BS1
-#undef FF0
-#undef FF1
-#undef ECHO
-#undef NOFLSH
-#undef TOSTOP
-#undef FLUSHO
-#undef PENDIN
-#endif
-
-/* Include the proper files. */
-#ifdef HAVE_TERMIO
-#ifdef __DGUX
-#include <sys/ioctl.h>
-#endif
-#ifndef NO_TERMIO
-#include <termio.h>
-#endif /* not NO_TERMIO */
-#ifndef INCLUDED_FCNTL
-#define INCLUDED_FCNTL
-#include <fcntl.h>
-#endif
-#else /* not HAVE_TERMIO */
-#ifdef HAVE_TERMIOS
-#if defined(_AIX) && defined(_I386)
-#include <termios.h> /* termios.h needs to be before termio.h */
-#include <termio.h>
-#else /* not (_AIX && _I386) */
-#ifndef NO_TERMIO
-#include <termio.h>
-#endif
-#include <termios.h>
-#endif /* not (_AIX && _I386) */
-#define INCLUDED_FCNTL
-#include <fcntl.h>
-#else /* neither HAVE_TERMIO nor HAVE_TERMIOS */
-#ifndef VMS
-#ifndef DOS_NT
-#include <sgtty.h>
-#endif /* not DOS_NT */
-#else /* VMS */
-#include <descrip.h>
-static struct iosb
-{
- short status;
- short offset;
- short termlen;
- short term;
-} input_iosb;
-
-extern int waiting_for_ast;
-extern int stop_input;
-extern int input_ef;
-extern int timer_ef;
-extern int process_ef;
-extern int input_eflist;
-extern int timer_eflist;
-
-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;
-#endif /* VMS */
-#endif /* not HAVE_TERMIOS */
-#endif /* not HAVE_TERMIO */
-
-#ifdef __GNU_LIBRARY__
-#include <sys/ioctl.h>
-#include <termios.h>
-#endif
-
-#ifdef AIXHFT
-/* 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 NEED_BSDTTY
-#include <sys/bsdtty.h>
-#endif
-
-#if defined (HPUX) && defined (HAVE_PTYS)
-#include <sys/ptyio.h>
-#endif
-
-#ifdef AIX
-#include <sys/pty.h>
-#endif /* AIX */
-
-#if (defined (POSIX) || defined (NEED_UNISTD_H)) && defined (HAVE_UNISTD_H)
-#include <unistd.h>
-#endif
-
-#ifdef SYSV_PTYS
-#include <sys/types.h>
-#include <sys/tty.h>
-#ifdef titan
-#include <sys/ttyhw.h>
-#include <sys/stream.h>
-#endif
-#ifndef NO_PTY_H
-#include <sys/pty.h>
-#endif
-#endif
-
-/* saka@pfu.fujitsu.co.JP writes:
- 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
-
-
-/* Special cases - inhibiting the use of certain features. */
-
-#ifdef APOLLO
-#undef TIOCSTART
-#endif
-
-#ifdef XENIX
-#undef TIOCGETC /* Avoid confusing some conditionals that test this. */
-#endif
-
-#ifdef BROKEN_TIOCGETC
-#undef TIOCGETC /* Avoid confusing some conditionals that test this. */
-#endif
-
-/* UNIPLUS systems may have FIONREAD. */
-#ifdef UNIPLUS
-#include <sys.ioctl.h>
-#endif
-
-/* Allow m- file to inhibit use of FIONREAD. */
-#ifdef BROKEN_FIONREAD
-#undef FIONREAD
-#undef ASYNC
-#endif
-
-/* Interrupt input is not used if there is no FIONREAD. */
-#ifndef FIONREAD
-#undef SIGIO
-#endif
-
-/* On TERMIOS systems, the tcmumbleattr calls take care of these
- parameters, and it's a bad idea to use them (on AIX, it makes the
- tty hang for a long time). */
-#if defined (TIOCGLTC) && !defined (HAVE_TERMIOS)
-#define HAVE_LTCHARS
-#endif
-
-#if defined (TIOCGETC) && !defined (HAVE_TERMIOS)
-#define HAVE_TCHARS
-#endif
-
-
-/* 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
-#undef CDISABLE
-#define CDISABLE CDEL
-#else /* not CDEL */
-#define CDISABLE 255
-#endif /* not CDEL */
-#endif /* not _POSIX_VDISABLE */
-
-/* Get the number of characters queued for output. */
-
-/* EMACS_OUTQSIZE(FD, int *SIZE) stores the number of characters
- queued for output to the terminal FD in *SIZE, if FD is a tty.
- Returns -1 if there was an error (i.e. FD is not a tty), 0
- otherwise. */
-#ifdef TIOCOUTQ
-#define EMACS_OUTQSIZE(fd, size) (ioctl ((fd), TIOCOUTQ, (size)))
-#endif
-
-#ifdef HAVE_TERMIO
-#ifdef TCOUTQ
-#undef EMACS_OUTQSIZE
-#define EMACS_OUTQSIZE(fd, size) (ioctl ((fd), TCOUTQ, (size)))
-#endif
-#endif
-
-
-/* Manipulate a terminal's current process group. */
-
-/* EMACS_HAVE_TTY_PGRP is true if we can get and set the tty's current
- controlling process group.
-
- EMACS_GET_TTY_PGRP(int FD, int *PGID) sets *PGID the terminal FD's
- current process group. Return -1 if there is an error.
-
- EMACS_SET_TTY_PGRP(int FD, int *PGID) sets the terminal FD's
- current process group to *PGID. Return -1 if there is an error. */
-
-#ifdef HPUX
-/* HPUX tty process group stuff doesn't work, says the anonymous voice
- from the past. */
-#else
-#ifdef TIOCGPGRP
-#define EMACS_HAVE_TTY_PGRP
-#else
-#ifdef HAVE_TERMIOS
-#define EMACS_HAVE_TTY_PGRP
-#endif
-#endif
-#endif
-
-#ifdef EMACS_HAVE_TTY_PGRP
-
-#if defined (HAVE_TERMIOS) && ! defined (BSD_TERMIOS)
-
-#define EMACS_GET_TTY_PGRP(fd, pgid) (*(pgid) = tcgetpgrp ((fd)))
-#define EMACS_SET_TTY_PGRP(fd, pgid) (tcsetpgrp ((fd), *(pgid)))
-
-#else
-#ifdef TIOCSPGRP
-
-#define EMACS_GET_TTY_PGRP(fd, pgid) (ioctl ((fd), TIOCGPGRP, (pgid)))
-#define EMACS_SET_TTY_PGRP(fd, pgid) (ioctl ((fd), TIOCSPGRP, (pgid)))
-
-#endif
-#endif
-
-#else
-
-/* Just ignore this for now and hope for the best */
-#define EMACS_GET_TTY_PGRP(fd, pgid) 0
-#define EMACS_SET_TTY_PGRP(fd, pgif) 0
-
-#endif
-
-/* EMACS_GETPGRP (arg) returns the process group of the process. */
-
-#ifdef __GNU_LIBRARY__
-/* GNU libc by default defines getpgrp with no args on all systems. */
-#define GETPGRP_NO_ARG
-#else /* not __GNU_LIBRARY__ */
-#if defined (USG) && !defined (GETPGRP_NEEDS_ARG)
-# if !defined (GETPGRP_NO_ARG)
-# define GETPGRP_NO_ARG
-# endif
-#endif
-#endif /* not __GNU_LIBRARY__ */
-
-#if defined (GETPGRP_NO_ARG)
-# define EMACS_GETPGRP(x) getpgrp()
-#else
-# define EMACS_GETPGRP(x) getpgrp(x)
-#endif /* !GETPGRP_NO_ARG */
-
-/* Manipulate a TTY's input/output processing parameters. */
-
-/* struct emacs_tty is a structure used to hold the current tty
- parameters. If the terminal has several structures describing its
- state, for example a struct tchars, a struct sgttyb, a struct
- tchars, a struct ltchars, and a struct pagechars, struct
- emacs_tty should contain an element for each parameter struct
- that Emacs may change.
-
- EMACS_GET_TTY (int FD, struct emacs_tty *P) stores the parameters
- of the tty on FD in *P. Return zero if all's well, or -1 if we ran
- into an error we couldn't deal with.
-
- EMACS_SET_TTY (int FD, struct emacs_tty *P, int flushp)
- sets the parameters of the tty on FD according to the contents of
- *P. If flushp is non-zero, we discard queued input to be
- written before making the change.
- Return 0 if all went well, and -1 if anything failed.
-
- EMACS_TTY_TABS_OK (struct emacs_tty *P) is false iff the kernel
- expands tabs to spaces upon output; in that case, there is no
- advantage to using tabs over spaces. */
-
-
-/* For each tty parameter structure that Emacs might want to save and restore,
- - include an element for it in this structure, and
- - extend the emacs_{get,set}_tty functions in sysdep.c to deal with the
- new members. */
-
-struct emacs_tty {
-
-/* There is always one of the following elements, so there is no need
- for dummy get and set definitions. */
-#ifdef HAVE_TCATTR
- struct termios main;
-#else
-#ifdef HAVE_TERMIO
- struct termio main;
-#else
-#ifdef VMS
- struct sensemode main;
-#else
-#ifdef DOS_NT
- int main;
-#else /* not DOS_NT */
- struct sgttyb main;
-#endif /* not DOS_NT */
-#endif
-#endif
-#endif
-
-/* If we have TERMIOS, we don't need to do this - they're taken care of
- by the tc*attr calls. */
-#ifndef HAVE_TERMIOS
-#ifdef HAVE_LTCHARS
- struct ltchars ltchars;
-#endif
-
-#ifdef HAVE_TCHARS
- struct tchars tchars;
- int lmode;
-#endif
-#endif
-};
-
-/* Define EMACS_GET_TTY and EMACS_SET_TTY,
- the macros for reading and setting parts of `struct emacs_tty'.
-
- These got pretty unmanageable (huge macros are hard to debug), and
- finally needed some code which couldn't be done as part of an
- expression, so we moved them out to their own functions in sysdep.c. */
-#define EMACS_GET_TTY(fd, p) (emacs_get_tty ((fd), (p)))
-#define EMACS_SET_TTY(fd, p, waitp) (emacs_set_tty ((fd), (p), (waitp)))
-
-
-/* Define EMACS_TTY_TABS_OK. */
-
-#ifdef HAVE_TERMIOS
-
-#ifdef TABDLY
-#define EMACS_TTY_TABS_OK(p) (((p)->main.c_oflag & TABDLY) != TAB3)
-#else
-#define EMACS_TTY_TABS_OK(p) 1
-#endif
-
-#else /* not def HAVE_TERMIOS */
-#ifdef HAVE_TERMIO
-
-#define EMACS_TTY_TABS_OK(p) (((p)->main.c_oflag & TABDLY) != TAB3)
-
-#else /* neither HAVE_TERMIO nor HAVE_TERMIOS */
-#ifdef VMS
-
-#define EMACS_TTY_TABS_OK(p) (((p)->main.tt_char & TT$M_MECHTAB) != 0)
-
-#else
-
-#ifdef DOS_NT
-#define EMACS_TTY_TABS_OK(p) 0
-#else /* not DOS_NT */
-#define EMACS_TTY_TABS_OK(p) (((p)->main.sg_flags & XTABS) != XTABS)
-#endif /* not DOS_NT */
-
-#endif /* not def VMS */
-#endif /* not def HAVE_TERMIO */
-#endif /* not def HAVE_TERMIOS */
diff --git a/src/syswait.h b/src/syswait.h
deleted file mode 100644
index 1889c36a32e..00000000000
--- a/src/syswait.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Define wait system call interface for Emacs.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Define 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 VMS
-#ifndef WAITTYPE
-
-#ifdef WAIT_USE_INT
-/* Some systems have union wait in their header, but we should use
- int regardless of that. */
-#include <sys/wait.h>
-#define WAITTYPE int
-#define WRETCODE(w) WEXITSTATUS (w)
-
-#else /* not WAIT_USE_INT */
-
-#if (!defined (BSD_SYSTEM) && !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
-#undef WCOREDUMP /* Later BSDs define this name differently. */
-#define WCOREDUMP(w) w.w_coredump
-
-#if defined (HPUX) || defined (convex)
-/* HPUX version 7 has broken definitions of these. */
-/* pvogel@convex.com says the convex does too. */
-#undef WTERMSIG
-#undef WSTOPSIG
-#undef WIFSTOPPED
-#undef WIFSIGNALED
-#undef WIFEXITED
-#endif /* HPUX | convex */
-
-#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_SYSTEM || UNIPLUS || STRIDE || HPUX */
-#endif /* not WAIT_USE_INT */
-#endif /* no WAITTYPE */
-
-#else /* VMS */
-
-#define WAITTYPE int
-#define WIFSTOPPED(w) 0
-#define WIFSIGNALED(w) 0
-#define WIFEXITED(w) ((w) != -1)
-#define WRETCODE(w) (w)
-#define WSTOPSIG(w) (w)
-#define WCOREDUMP(w) 0
-#define WTERMSIG(w) (w)
-#include <ssdef.h>
-#include <iodef.h>
-#include <clidef.h>
-#include "vmsproc.h"
-
-#endif /* VMS */
diff --git a/src/term.c b/src/term.c
deleted file mode 100644
index 8519a49ee57..00000000000
--- a/src/term.c
+++ /dev/null
@@ -1,1817 +0,0 @@
-/* terminal control module for terminals described by TERMCAP
- Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include <stdio.h>
-#include <ctype.h>
-#include "termchar.h"
-#include "termopts.h"
-#include "cm.h"
-#undef NULL
-#include "lisp.h"
-#include "frame.h"
-#include "disptab.h"
-#include "termhooks.h"
-#include "keyboard.h"
-
-extern Lisp_Object Fmake_sparse_keymap ();
-
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
-#define OUTPUT(a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - 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, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc); }
-#define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); }
-
-/* Function to use to ring the bell. */
-Lisp_Object Vring_bell_function;
-
-/* Terminal characteristics that higher levels want to look at.
- These are all extern'd in termchar.h */
-
-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 scroll_region_cost; /* Cost of setting a scroll window,
- measured in characters */
-int memory_below_frame; /* Terminal remembers lines
- scrolled off bottom */
-int fast_clear_end_of_line; /* Terminal has a `ce' string */
-
-/* Nonzero means no need to redraw the entire frame 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;
-
-/* Hook functions that you can set to snap out the functions in this file.
- These are all extern'd in termhooks.h */
-
-int (*cursor_to_hook) ();
-int (*raw_cursor_to_hook) ();
-
-int (*clear_to_end_hook) ();
-int (*clear_frame_hook) ();
-int (*clear_end_of_line_hook) ();
-
-int (*ins_del_lines_hook) ();
-
-int (*change_line_highlight_hook) ();
-int (*reassert_line_highlight_hook) ();
-
-int (*insert_glyphs_hook) ();
-int (*write_glyphs_hook) ();
-int (*delete_glyphs_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 (*frame_up_to_date_hook) ();
-
-/* Return the current position of the mouse.
-
- Set *f to the frame the mouse is in, or zero if the mouse is in no
- Emacs frame. If it is set to zero, all the other arguments are
- garbage.
-
- If the motion started in a scroll bar, set *bar_window to the
- scroll bar's window, *part to the part the mouse is currently over,
- *x to the position of the mouse along the scroll bar, and *y to the
- overall length of the scroll bar.
-
- Otherwise, set *bar_window to Qnil, and *x and *y to the column and
- row of the character cell the mouse is over.
-
- Set *time to the time the mouse was at the returned position.
-
- This should clear mouse_moved until the next motion
- event arrives. */
-void (*mouse_position_hook) ( /* FRAME_PTR *f, int insist,
- Lisp_Object *bar_window,
- enum scroll_bar_part *part,
- Lisp_Object *x,
- Lisp_Object *y,
- unsigned long *time */ );
-
-/* When reading from a minibuffer in a different frame, Emacs wants
- to shift the highlight from the selected frame to the minibuffer's
- frame; under X, this means it lies about where the focus is.
- This hook tells the window system code to re-decide where to put
- the highlight. */
-void (*frame_rehighlight_hook) ( /* FRAME_PTR f */ );
-
-/* If we're displaying frames using a window system that can stack
- frames on top of each other, this hook allows you to bring a frame
- to the front, or bury it behind all the other windows. If this
- hook is zero, that means the device we're displaying on doesn't
- support overlapping frames, so there's no need to raise or lower
- anything.
-
- If RAISE is non-zero, F is brought to the front, before all other
- windows. If RAISE is zero, F is sent to the back, behind all other
- windows. */
-void (*frame_raise_lower_hook) ( /* FRAME_PTR f, int raise */ );
-
-/* Set the vertical scroll bar for WINDOW to have its upper left corner
- at (TOP, LEFT), and be LENGTH rows high. Set its handle to
- indicate that we are displaying PORTION characters out of a total
- of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
- have a scroll bar, create one for it. */
-void (*set_vertical_scroll_bar_hook)
- ( /* struct window *window,
- int portion, int whole, int position */ );
-
-
-/* The following three hooks are used when we're doing a thorough
- redisplay of the frame. We don't explicitly know which scroll bars
- are going to be deleted, because keeping track of when windows go
- away is a real pain - can you say set-window-configuration?
- Instead, we just assert at the beginning of redisplay that *all*
- scroll bars are to be removed, and then save scroll bars from the
- fiery pit when we actually redisplay their window. */
-
-/* Arrange for all scroll bars on FRAME to be removed at the next call
- to `*judge_scroll_bars_hook'. A scroll bar may be spared if
- `*redeem_scroll_bar_hook' is applied to its window before the judgement.
-
- This should be applied to each frame each time its window tree is
- redisplayed, even if it is not displaying scroll bars at the moment;
- if the HAS_SCROLL_BARS flag has just been turned off, only calling
- this and the judge_scroll_bars_hook will get rid of them.
-
- If non-zero, this hook should be safe to apply to any frame,
- whether or not it can support scroll bars, and whether or not it is
- currently displaying them. */
-void (*condemn_scroll_bars_hook)( /* FRAME_PTR *frame */ );
-
-/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
- Note that it's okay to redeem a scroll bar that is not condemned. */
-void (*redeem_scroll_bar_hook)( /* struct window *window */ );
-
-/* Remove all scroll bars on FRAME that haven't been saved since the
- last call to `*condemn_scroll_bars_hook'.
-
- This should be applied to each frame after each time its window
- tree is redisplayed, even if it is not displaying scroll bars at the
- moment; if the HAS_SCROLL_BARS flag has just been turned off, only
- calling this and condemn_scroll_bars_hook will get rid of them.
-
- If non-zero, this hook should be safe to apply to any frame,
- whether or not it can support scroll bars, and whether or not it is
- currently displaying them. */
-void (*judge_scroll_bars_hook)( /* FRAME_PTR *FRAME */ );
-
-
-/* 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_frame; /* "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 */
-
-/* The largest frame width in any call to calculate_costs. */
-int max_frame_width;
-/* The largest frame height in any call to calculate_costs. */
-int max_frame_height;
-
-/* Number of chars of space used for standout marker at beginning of line,
- or'd with 0100. Zero if no standout marker at all.
- The length of these vectors is max_frame_height.
-
- Used IFF TN_standout_width >= 0. */
-
-static 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, from the top of frame downwards,
- which can participate in insert-line/delete-line operations.
-
- Effectively it excludes the bottom frame_height - specified_window_size
- lines from those operations. */
-
-int specified_window;
-
-/* Frame currently being redisplayed; 0 if not currently redisplaying.
- (Direct output does not count). */
-
-FRAME_PTR updating_frame;
-
-/* Provided for lisp packages. */
-static int system_uses_terminfo;
-
-char *tparam ();
-
-extern char *tgetstr ();
-
-
-#ifdef WINDOWSNT
-/* We aren't X windows, but we aren't termcap either. This makes me
- uncertain as to what value to use for frame.output_method. For
- this file, we'll define FRAME_TERMCAP_P to be zero so that our
- output hooks get called instead of the termcap functions. Probably
- the best long-term solution is to define an output_windows_nt... */
-
-#undef FRAME_TERMCAP_P
-#define FRAME_TERMCAP_P(_f_) 0
-#endif /* WINDOWSNT */
-
-ring_bell ()
-{
- if (! NILP (Vring_bell_function))
- {
- Lisp_Object function;
-
- /* Temporarily set the global variable to nil
- so that if we get an error, it stays nil
- and we don't call it over and over.
-
- We don't specbind it, because that would carefully
- restore the bad value if there's an error
- and make the loop of errors happen anyway. */
- function = Vring_bell_function;
- Vring_bell_function = Qnil;
-
- call0 (function);
-
- Vring_bell_function = function;
- return;
- }
-
- if (! FRAME_TERMCAP_P (selected_frame))
- {
- (*ring_bell_hook) ();
- return;
- }
- OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
-}
-
-set_terminal_modes ()
-{
- if (! FRAME_TERMCAP_P (selected_frame))
- {
- (*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 (! FRAME_TERMCAP_P (selected_frame))
- {
- (*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);
- /* Output raw CR so kernel can track the cursor hpos. */
- /* But on magic-cookie terminals this can erase an end-standout marker and
- cause the rest of the frame to be in standout, so move down first. */
- if (TN_standout_width >= 0)
- cmputc ('\n');
- cmputc ('\r');
-}
-
-update_begin (f)
- FRAME_PTR f;
-{
- updating_frame = f;
- if (! FRAME_TERMCAP_P (updating_frame))
- (*update_begin_hook) (f);
-}
-
-update_end (f)
- FRAME_PTR f;
-{
- if (! FRAME_TERMCAP_P (updating_frame))
- {
- (*update_end_hook) (f);
- updating_frame = 0;
- return;
- }
- turn_off_insert ();
- background_highlight ();
- standout_requested = 0;
- updating_frame = 0;
-}
-
-set_terminal_window (size)
- int size;
-{
- if (! FRAME_TERMCAP_P (updating_frame))
- {
- (*set_terminal_window_hook) (size);
- return;
- }
- specified_window = size ? size : FRAME_HEIGHT (selected_frame);
- 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,
- FRAME_HEIGHT (selected_frame), start,
- FRAME_HEIGHT (selected_frame) - stop,
- FRAME_HEIGHT (selected_frame));
- }
- else
- {
- buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (selected_frame));
- }
- OUTPUT (buf);
- xfree (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 terminal's 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 (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
- {
- (*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 (! FRAME_TERMCAP_P (updating_frame))
- {
- (*change_line_highlight_hook) (new_highlight, vpos, first_unused_hpos);
- return;
- }
-
- cursor_to (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, FRAME_WIDTH (selected_frame) - 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 */
-
-cursor_to (row, col)
- int row, col;
-{
- if (! FRAME_TERMCAP_P ((updating_frame
- ? updating_frame
- : selected_frame))
- && cursor_to_hook)
- {
- (*cursor_to_hook) (row, col);
- return;
- }
-
- /* Detect the case where we are called from reset_sys_modes
- and the costs have never been calculated. Do nothing. */
- if (chars_wasted == 0)
- return;
-
- col += chars_wasted[row] & 077;
- 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_cursor_to (row, col)
- int row, col;
-{
- if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
- {
- (*raw_cursor_to_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 frame */
-clear_to_end ()
-{
- register int i;
-
- if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
- {
- (*clear_to_end_hook) ();
- return;
- }
- if (TS_clr_to_bottom)
- {
- background_highlight ();
- OUTPUT (TS_clr_to_bottom);
- bzero (chars_wasted + curY, FRAME_HEIGHT (selected_frame) - curY);
- }
- else
- {
- for (i = curY; i < FRAME_HEIGHT (selected_frame); i++)
- {
- cursor_to (i, 0);
- clear_end_of_line_raw (FRAME_WIDTH (selected_frame));
- }
- }
-}
-
-/* Clear entire frame */
-
-clear_frame ()
-{
- if (clear_frame_hook
- && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
- {
- (*clear_frame_hook) ();
- return;
- }
- if (TS_clr_frame)
- {
- background_highlight ();
- OUTPUT (TS_clr_frame);
- bzero (chars_wasted, FRAME_HEIGHT (selected_frame));
- cmat (0, 0);
- }
- else
- {
- cursor_to (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;
-{
- static GLYPH buf = SPACEGLYPH;
- if (FRAME_TERMCAP_P (selected_frame)
- && chars_wasted != 0
- && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
- write_glyphs (&buf, 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;
-
- if (clear_end_of_line_hook
- && ! FRAME_TERMCAP_P ((updating_frame
- ? updating_frame
- : selected_frame)))
- {
- (*clear_end_of_line_hook) (first_unused_hpos);
- return;
- }
-
- /* Detect the case where we are called from reset_sys_modes
- and the costs have never been calculated. Do nothing. */
- if (chars_wasted == 0)
- return;
-
- first_unused_hpos += chars_wasted[curY] & 077;
- 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 ();
-
- /* Do not write in last row last col with Autowrap on. */
- if (AutoWrap && curY == FRAME_HEIGHT (selected_frame) - 1
- && first_unused_hpos == FRAME_WIDTH (selected_frame))
- first_unused_hpos--;
-
- for (i = curX; i < first_unused_hpos; i++)
- {
- if (termscript)
- fputc (' ', termscript);
- putchar (' ');
- }
- cmplus (first_unused_hpos - curX);
- }
-}
-
-
-write_glyphs (string, len)
- register GLYPH *string;
- register int len;
-{
- register GLYPH g;
- register int tlen = GLYPH_TABLE_LENGTH;
- register Lisp_Object *tbase = GLYPH_TABLE_BASE;
-
- if (write_glyphs_hook
- && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
- {
- (*write_glyphs_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 frame on some terminals. */
-
- if (AutoWrap
- && curY + 1 == FRAME_HEIGHT (selected_frame)
- && (curX + len - (chars_wasted[curY] & 077)
- == FRAME_WIDTH (selected_frame)))
- len --;
-
- cmplus (len);
- while (--len >= 0)
- {
- g = *string++;
- /* Check quickly for G beyond length of table.
- That implies it isn't an alias and is simple. */
- if (g >= tlen)
- {
- simple:
- putc (g & 0xff, stdout);
- if (ferror (stdout))
- clearerr (stdout);
- if (termscript)
- putc (g & 0xff, termscript);
- }
- else
- {
- /* G has an entry in Vglyph_table,
- so process any alias and then test for simpleness. */
- while (GLYPH_ALIAS_P (tbase, tlen, g))
- g = GLYPH_ALIAS (tbase, g);
- if (GLYPH_SIMPLE_P (tbase, tlen, g))
- goto simple;
- else
- {
- /* Here if G (or its definition as an alias) is not simple. */
- fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
- stdout);
- if (ferror (stdout))
- clearerr (stdout);
- if (termscript)
- fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
- termscript);
- }
- }
- }
- cmcheckmagic ();
-}
-
-/* If start is zero, insert blanks instead of a string at start */
-
-insert_glyphs (start, len)
- register GLYPH *start;
- register int len;
-{
- char *buf;
- register GLYPH g;
- register int tlen = GLYPH_TABLE_LENGTH;
- register Lisp_Object *tbase = GLYPH_TABLE_BASE;
-
- if (insert_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
- {
- (*insert_glyphs_hook) (start, len);
- return;
- }
- highlight_if_desired ();
-
- if (TS_ins_multi_chars)
- {
- buf = tparam (TS_ins_multi_chars, 0, 0, len);
- OUTPUT1 (buf);
- xfree (buf);
- if (start)
- write_glyphs (start, len);
- return;
- }
-
- turn_on_insert ();
- cmplus (len);
- while (--len >= 0)
- {
- OUTPUT1_IF (TS_ins_char);
- if (!start)
- g = SPACEGLYPH;
- else
- g = *start++;
-
- if (GLYPH_SIMPLE_P (tbase, tlen, g))
- {
- putc (g & 0xff, stdout);
- if (ferror (stdout))
- clearerr (stdout);
- if (termscript)
- putc (g & 0xff, termscript);
- }
- else
- {
- fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g), stdout);
- if (ferror (stdout))
- clearerr (stdout);
- if (termscript)
- fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
- termscript);
- }
-
- OUTPUT1_IF (TS_pad_inserted_char);
- }
- cmcheckmagic ();
-}
-
-delete_glyphs (n)
- register int n;
-{
- char *buf;
- register int i;
-
- if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
- {
- (*delete_glyphs_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);
- xfree (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 && ! FRAME_TERMCAP_P (updating_frame))
- {
- (*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_frame && vpos + i >= FRAME_HEIGHT (selected_frame))
- return;
-
- if (multi)
- {
- raw_cursor_to (vpos, 0);
- background_highlight ();
- buf = tparam (multi, 0, 0, i);
- OUTPUT (buf);
- xfree (buf);
- }
- else if (single)
- {
- raw_cursor_to (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_cursor_to (specified_window - 1, 0);
- else
- raw_cursor_to (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
- : FRAME_HEIGHT (selected_frame));
-
- 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_frame && n < 0)
- {
- cursor_to (FRAME_HEIGHT (selected_frame) + n, 0);
- clear_to_end ();
- }
-}
-
-/* Compute cost of sending "str", in characters,
- not counting any line-dependent padding. */
-
-int
-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. */
-
-static int
-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. */
-
-int
-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;
-}
-
-#ifndef old
-/* char_ins_del_cost[n] is cost of inserting N characters.
- char_ins_del_cost[-n] is cost of deleting N characters.
- The length of this vector is based on max_frame_width. */
-
-int *char_ins_del_vector;
-
-#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
-#endif
-
-/* ARGSUSED */
-static void
-calculate_ins_del_char_costs (frame)
- FRAME_PTR frame;
-{
- 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 = &char_ins_del_cost (frame)[0];
- for (i = FRAME_WIDTH (frame); --i >= 0;)
- *--p = (del_startup_cost += del_cost_per_char);
-
- /* Doing nothing is free */
- p = &char_ins_del_cost (frame)[0];
- *p++ = 0;
-
- /* Insert costs are at positive offsets */
- for (i = FRAME_WIDTH (frame); --i >= 0;)
- *p++ = (ins_startup_cost += ins_cost_per_char);
-}
-
-extern do_line_insertion_deletion_costs ();
-
-calculate_costs (frame)
- FRAME_PTR frame;
-{
- register char *f = (TS_set_scroll_region
- ? TS_set_scroll_region
- : TS_set_scroll_region_1);
-
- FRAME_COST_BAUD_RATE (frame) = baud_rate;
-
- scroll_region_cost = string_cost (f);
-#ifdef HAVE_X_WINDOWS
- if (FRAME_X_P (frame))
- {
- do_line_insertion_deletion_costs (frame, 0, ".5*", 0, ".5*",
- 0, 0,
- x_screen_planes (frame));
- scroll_region_cost = 0;
- return;
- }
-#endif
-
- /* These variables are only used for terminal stuff. They are allocated
- once for the terminal frame of X-windows emacs, but not used afterwards.
-
- char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
- X turns off char_ins_del_ok.
-
- chars_wasted and copybuf are only used here in term.c in cases where
- the term hook isn't called. */
-
- max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame));
- max_frame_width = max (max_frame_width, FRAME_WIDTH (frame));
-
- if (chars_wasted != 0)
- chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height);
- else
- chars_wasted = (char *) xmalloc (max_frame_height);
-
- if (copybuf != 0)
- copybuf = (char *) xrealloc (copybuf, max_frame_height);
- else
- copybuf = (char *) xmalloc (max_frame_height);
-
- if (char_ins_del_vector != 0)
- char_ins_del_vector
- = (int *) xrealloc (char_ins_del_vector,
- (sizeof (int)
- + 2 * max_frame_width * sizeof (int)));
- else
- char_ins_del_vector
- = (int *) xmalloc (sizeof (int)
- + 2 * max_frame_width * sizeof (int));
-
- bzero (chars_wasted, max_frame_height);
- bzero (copybuf, max_frame_height);
- bzero (char_ins_del_vector, (sizeof (int)
- + 2 * max_frame_width * sizeof (int)));
-
- if (f && (!TS_ins_line && !TS_del_line))
- do_line_insertion_deletion_costs (frame,
- TS_rev_scroll, TS_ins_multi_lines,
- TS_fwd_scroll, TS_del_multi_lines,
- f, f, 1);
- else
- do_line_insertion_deletion_costs (frame,
- TS_ins_line, TS_ins_multi_lines,
- TS_del_line, TS_del_multi_lines,
- 0, 0, 1);
-
- calculate_ins_del_char_costs (frame);
-
- /* 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 = FRAME_WIDTH (frame) * 2;
-
- cmcostinit (); /* set up cursor motion costs */
-}
-
-struct fkey_table {
- char *cap, *name;
-};
-
- /* Termcap capability names that correspond directly to X keysyms.
- Some of these (marked "terminfo") aren't supplied by old-style
- (Berkeley) termcap entries. They're listed in X keysym order;
- except we put the keypad keys first, so that if they clash with
- other keys (as on the IBM PC keyboard) they get overridden.
- */
-
-static struct fkey_table keys[] = {
- "kh", "home", /* termcap */
- "kl", "left", /* termcap */
- "ku", "up", /* termcap */
- "kr", "right", /* termcap */
- "kd", "down", /* termcap */
- "%8", "prior", /* terminfo */
- "%5", "next", /* terminfo */
- "@7", "end", /* terminfo */
- "@1", "begin", /* terminfo */
- "*6", "select", /* terminfo */
- "%9", "print", /* terminfo */
- "@4", "execute", /* terminfo --- actually the `command' key */
- /*
- * "insert" --- see below
- */
- "&8", "undo", /* terminfo */
- "%0", "redo", /* terminfo */
- "%7", "menu", /* terminfo --- actually the `options' key */
- "@0", "find", /* terminfo */
- "@2", "cancel", /* terminfo */
- "%1", "help", /* terminfo */
- /*
- * "break" goes here, but can't be reliably intercepted with termcap
- */
- "&4", "reset", /* terminfo --- actually `restart' */
- /*
- * "system" and "user" --- no termcaps
- */
- "kE", "clearline", /* terminfo */
- "kA", "insertline", /* terminfo */
- "kL", "deleteline", /* terminfo */
- "kI", "insertchar", /* terminfo */
- "kD", "deletechar", /* terminfo */
- "kB", "backtab", /* terminfo */
- /*
- * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
- */
- "@8", "kp-enter", /* terminfo */
- /*
- * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
- * "kp-multiply", "kp-add", "kp-separator",
- * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
- * --- no termcaps for any of these.
- */
- "K4", "kp-1", /* terminfo */
- /*
- * "kp-2" --- no termcap
- */
- "K5", "kp-3", /* terminfo */
- /*
- * "kp-4" --- no termcap
- */
- "K2", "kp-5", /* terminfo */
- /*
- * "kp-6" --- no termcap
- */
- "K1", "kp-7", /* terminfo */
- /*
- * "kp-8" --- no termcap
- */
- "K3", "kp-9", /* terminfo */
- /*
- * "kp-equal" --- no termcap
- */
- "k1", "f1",
- "k2", "f2",
- "k3", "f3",
- "k4", "f4",
- "k5", "f5",
- "k6", "f6",
- "k7", "f7",
- "k8", "f8",
- "k9", "f9",
- };
-
-static char **term_get_fkeys_arg;
-static Lisp_Object term_get_fkeys_1 ();
-
-/* Find the escape codes sent by the function keys for Vfunction_key_map.
- This function scans the termcap function key sequence entries, and
- adds entries to Vfunction_key_map for each function key it finds. */
-
-void
-term_get_fkeys (address)
- char **address;
-{
- /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
- errors during the call. The only errors should be from Fdefine_key
- when given a key sequence containing an invalid prefix key. If the
- termcap defines function keys which use a prefix that is already bound
- to a command by the default bindings, we should silently ignore that
- function key specification, rather than giving the user an error and
- refusing to run at all on such a terminal. */
-
- extern Lisp_Object Fidentity ();
- term_get_fkeys_arg = address;
- internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
-}
-
-static Lisp_Object
-term_get_fkeys_1 ()
-{
- int i;
-
- char **address = term_get_fkeys_arg;
-
- /* This can happen if CANNOT_DUMP or with strange options. */
- if (!initialized)
- Vfunction_key_map = Fmake_sparse_keymap (Qnil);
-
- for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
- {
- char *sequence = tgetstr (keys[i].cap, address);
- if (sequence)
- Fdefine_key (Vfunction_key_map, build_string (sequence),
- Fmake_vector (make_number (1),
- intern (keys[i].name)));
- }
-
- /* The uses of the "k0" capability are inconsistent; sometimes it
- describes F10, whereas othertimes it describes F0 and "k;" describes F10.
- We will attempt to politely accommodate both systems by testing for
- "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
- */
- {
- char *k_semi = tgetstr ("k;", address);
- char *k0 = tgetstr ("k0", address);
- char *k0_name = "f10";
-
- if (k_semi)
- {
- Fdefine_key (Vfunction_key_map, build_string (k_semi),
- Fmake_vector (make_number (1), intern ("f10")));
- k0_name = "f0";
- }
-
- if (k0)
- Fdefine_key (Vfunction_key_map, build_string (k0),
- Fmake_vector (make_number (1), intern (k0_name)));
- }
-
- /* Set up cookies for numbered function keys above f10. */
- {
- char fcap[3], fkey[4];
-
- fcap[0] = 'F'; fcap[2] = '\0';
- for (i = 11; i < 64; i++)
- {
- if (i <= 19)
- fcap[1] = '1' + i - 11;
- else if (i <= 45)
- fcap[1] = 'A' + i - 20;
- else
- fcap[1] = 'a' + i - 46;
-
- {
- char *sequence = tgetstr (fcap, address);
- if (sequence)
- {
- sprintf (fkey, "f%d", i);
- Fdefine_key (Vfunction_key_map, build_string (sequence),
- Fmake_vector (make_number (1),
- intern (fkey)));
- }
- }
- }
- }
-
- /*
- * Various mappings to try and get a better fit.
- */
- {
-#define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
- if (!tgetstr (cap1, address)) \
- { \
- char *sequence = tgetstr (cap2, address); \
- if (sequence) \
- Fdefine_key (Vfunction_key_map, build_string (sequence), \
- Fmake_vector (make_number (1), \
- intern (sym))); \
- }
-
- /* if there's no key_next keycap, map key_npage to `next' keysym */
- CONDITIONAL_REASSIGN ("%5", "kN", "next");
- /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
- CONDITIONAL_REASSIGN ("%8", "kP", "prior");
- /* if there's no key_dc keycap, map key_ic to `insert' keysym */
- CONDITIONAL_REASSIGN ("kD", "kI", "insert");
-
- /* IBM has their own non-standard dialect of terminfo.
- If the standard name isn't found, try the IBM name. */
- CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
- CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
- CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
- CONDITIONAL_REASSIGN ("%7", "ki", "menu");
- CONDITIONAL_REASSIGN ("@7", "kw", "end");
- CONDITIONAL_REASSIGN ("F1", "k<", "f11");
- CONDITIONAL_REASSIGN ("F2", "k>", "f12");
- CONDITIONAL_REASSIGN ("%1", "kq", "help");
- CONDITIONAL_REASSIGN ("*6", "kU", "select");
-#undef CONDITIONAL_REASSIGN
- }
-}
-
-
-term_init (terminal_type)
- char *terminal_type;
-{
- char *area;
- char **address = &area;
- char buffer[2044];
- register char *p;
- int status;
-
-#ifdef WINDOWSNT
- initialize_win_nt_display ();
-
- Wcm_clear ();
-
- area = (char *) malloc (2044);
-
- if (area == 0)
- abort ();
-
- FrameRows = FRAME_HEIGHT (selected_frame);
- FrameCols = FRAME_WIDTH (selected_frame);
- specified_window = FRAME_HEIGHT (selected_frame);
-
- delete_in_insert_mode = 1;
-
- UseTabs = 0;
- scroll_region_ok = 0;
-
- /* Seems to insert lines when it's not supposed to, messing
- up the display. In doing a trace, it didn't seem to be
- called much, so I don't think we're losing anything by
- turning it off. */
-
- line_ins_del_ok = 0;
- char_ins_del_ok = 1;
-
- baud_rate = 19200;
-
- FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0;
- FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame) = vertical_scroll_bar_none;
-
- return;
-#endif /* WINDOWSNT */
-
- Wcm_clear ();
-
- status = tgetent (buffer, terminal_type);
- if (status < 0)
- {
-#ifdef TERMINFO
- fatal ("Cannot open terminfo database file.\n");
-#else
- fatal ("Cannot open termcap database file.\n");
-#endif
- }
- if (status == 0)
- {
-#ifdef TERMINFO
- fatal ("Terminal type %s is not defined.\n\
-If that is not the actual type of terminal you have,\n\
-use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
-`setenv TERM ...') to specify the correct type. It may be necessary\n\
-to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.\n",
- terminal_type);
-#else
- fatal ("Terminal type %s is not defined.\n\
-If that is not the actual type of terminal you have,\n\
-use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
-`setenv TERM ...') to specify the correct type. It may be necessary\n\
-to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n",
- terminal_type);
-#endif
- }
-#ifdef TERMINFO
- area = (char *) malloc (2044);
-#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);
- BackTab = tgetstr ("bt", address);
- TS_clr_to_bottom = tgetstr ("cd", address);
- TS_clr_line = tgetstr ("ce", address);
- TS_clr_frame = 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);
- MultiUp = tgetstr ("UP", address);
- MultiDown = tgetstr ("DO", address);
- MultiLeft = tgetstr ("LE", address);
- MultiRight = tgetstr ("RI", address);
-
- MagicWrap = tgetflag ("xn");
- /* Since we make MagicWrap terminals look like AutoWrap, we need to have
- the former flag imply the latter. */
- AutoWrap = MagicWrap || tgetflag ("am");
- memory_below_frame = 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");
- TF_xs = tgetflag ("xs");
- TF_teleray = tgetflag ("xt");
-
- term_get_fkeys (address);
-
- /* Get frame size from system, or else from termcap. */
- {
- int height, width;
- get_frame_size (&width, &height);
- FRAME_WIDTH (selected_frame) = width;
- FRAME_HEIGHT (selected_frame) = height;
- }
-
- if (FRAME_WIDTH (selected_frame) <= 0)
- SET_FRAME_WIDTH (selected_frame, tgetnum ("co"));
- else
- /* Keep width and external_width consistent */
- SET_FRAME_WIDTH (selected_frame, FRAME_WIDTH (selected_frame));
- if (FRAME_HEIGHT (selected_frame) <= 0)
- FRAME_HEIGHT (selected_frame) = tgetnum ("li");
-
- if (FRAME_HEIGHT (selected_frame) < 3
- || FRAME_WIDTH (selected_frame) < 3)
- fatal ("Screen size %dx%d is too small.\n",
- FRAME_HEIGHT (selected_frame), FRAME_WIDTH (selected_frame));
-
- 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 no `se' string, try using a `me' string instead.
- If that fails, we can't use standout mode at all. */
- if (TS_end_standout_mode == 0)
- {
- char *s = tgetstr ("me", address);
- if (s != 0)
- TS_end_standout_mode = s;
- else
- TS_standout_mode = 0;
- }
-
- 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_frame = 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 frame 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++;
- }
- }
-
- FrameRows = FRAME_HEIGHT (selected_frame);
- FrameCols = FRAME_WIDTH (selected_frame);
- specified_window = FRAME_HEIGHT (selected_frame);
-
- if (Wcm_init () == -1) /* 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 /* not VMS */
-# ifdef TERMINFO
- 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 Bourne shell command `TERM=... export TERM' (C-shell:\n\
-`setenv TERM ...') to specify the correct type. It may be necessary\n\
-to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.\n",
- terminal_type);
-# else /* TERMCAP */
- 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 Bourne shell command `TERM=... export TERM' (C-shell:\n\
-`setenv TERM ...') to specify the correct type. It may be necessary\n\
-to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n",
- terminal_type);
-# endif /* TERMINFO */
-#endif /*VMS */
- if (FRAME_HEIGHT (selected_frame) <= 0
- || FRAME_WIDTH (selected_frame) <= 0)
- fatal ("The frame size has not been specified.");
-
- 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)
- SET_FRAME_WIDTH (selected_frame,
- FRAME_WIDTH (selected_frame) - TN_standout_width);
-
- UseTabs = tabs_safe_p () && TabWidth == 8;
-
- scroll_region_ok
- = (Wcm.cm_abs
- && (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;
-
- FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0;
- FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame) = vertical_scroll_bar_none;
-}
-
-/* VARARGS 1 */
-fatal (str, arg1, arg2)
- char *str, *arg1, *arg2;
-{
- fprintf (stderr, "emacs: ");
- fprintf (stderr, str, arg1, arg2);
- fflush (stderr);
- exit (1);
-}
-
-syms_of_term ()
-{
- DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
- "Non-nil means the system uses terminfo rather than termcap.\n\
-This variable can be used by terminal emulator packages.");
-#ifdef TERMINFO
- system_uses_terminfo = 1;
-#else
- system_uses_terminfo = 0;
-#endif
-
- DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
- "Non-nil means call this function to ring the bell.\n\
-The function should accept no arguments.");
- Vring_bell_function = Qnil;
-}
diff --git a/src/termcap.c b/src/termcap.c
deleted file mode 100644
index f41f24f160d..00000000000
--- a/src/termcap.c
+++ /dev/null
@@ -1,784 +0,0 @@
-/* Work-alike for termcap, plus extra features.
- Copyright (C) 1985, 86, 93, 94, 95 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 2, 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, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Emacs config.h may rename various library functions such as malloc. */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef emacs
-
-/* Get the O_* definitions for open et al. */
-#include <sys/file.h>
-#ifdef USG5
-#include <fcntl.h>
-#endif
-
-#else /* not emacs */
-
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#include <string.h>
-#else
-char *getenv ();
-char *malloc ();
-char *realloc ();
-#endif
-
-/* Do this after the include, in case string.h prototypes bcopy. */
-#if (defined(HAVE_STRING_H) || defined(STDC_HEADERS)) && !defined(bcopy)
-#define bcopy(s, d, n) memcpy ((d), (s), (n))
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef _POSIX_VERSION
-#include <fcntl.h>
-#endif
-
-#endif /* not emacs */
-
-#ifndef NULL
-#define NULL (char *) 0
-#endif
-
-#ifndef O_RDONLY
-#define O_RDONLY 0
-#endif
-
-/* 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. */
-
-#ifndef BUFSIZE
-#ifdef DEBUG
-#define BUFSIZE bufsize
-
-int bufsize = 128;
-#else
-#define BUFSIZE 2048
-#endif
-#endif
-
-#ifndef TERMCAP_FILE
-#define TERMCAP_FILE "/etc/termcap"
-#endif
-
-#ifndef emacs
-static void
-memory_out ()
-{
- write (2, "virtual memory exhausted\n", 25);
- exit (1);
-}
-
-static char *
-xmalloc (size)
- unsigned size;
-{
- register char *tem = malloc (size);
-
- if (!tem)
- memory_out ();
- return tem;
-}
-
-static char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
-{
- register char *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 ();
-
-/* Search entry BP for capability CAP.
- Return a pointer to the capability (in BP) if found,
- 0 if not found. */
-
-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 NULL;
-}
-
-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 ptr && ptr[-1] == ':';
-}
-
-/* Look up a string-valued capability CAP.
- If AREA is non-null, 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 null, 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 NULL;
- 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 \
- ";
-
-/* PTR points to a string value inside a termcap entry.
- Copy that value, processing \ and ^ abbreviations,
- into the block that *AREA points to,
- or to newly allocated storage if AREA is NULL.
- Return the address to which we copied the value,
- or NULL if PTR is NULL. */
-
-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 NULL;
-
- /* `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++;
- if (c == '?')
- c = 0177;
- else
- c &= 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;
-/* If OSPEED is 0, we use this as the actual baud rate. */
-int tputs_baud_rate;
-char PC;
-
-/* Actual baud rate if positive;
- - baud rate / 100 if negative. */
-
-static int 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, -288, -384, -576, -1152
-#endif /* not VMS */
- };
-
-void
-tputs (str, nlines, outfun)
- register char *str;
- int nlines;
- register int (*outfun) ();
-{
- register int padcount = 0;
- register int speed;
-
-#ifdef emacs
- extern baud_rate;
- speed = baud_rate;
- /* For quite high speeds, convert to the smaller
- units to avoid overflow. */
- if (speed > 10000)
- speed = - speed / 100;
-#else
- if (ospeed == 0)
- speed = tputs_baud_rate;
- else if (ospeed > 0 && ospeed < (sizeof speeds / sizeof speeds[0]))
- speed = speeds[ospeed];
- else
- speed = 0;
-#endif
-
- if (!str)
- return;
-
- while (*str >= '0' && *str <= '9')
- {
- padcount += *str++ - '0';
- padcount *= 10;
- }
- if (*str == '.')
- {
- str++;
- padcount += *str++ - '0';
- }
- if (*str == '*')
- {
- str++;
- padcount *= nlines;
- }
- while (*str)
- (*outfun) (*str++);
-
- /* PADCOUNT is now in units of tenths of msec.
- SPEED is measured in characters per 10 seconds
- or in characters per .1 seconds (if negative).
- We use the smaller units for larger speeds to avoid overflow. */
- padcount *= speed;
- padcount += 500;
- padcount /= 1000;
- if (speed < 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
-valid_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;
-}
-
-#else /* !VMS */
-
-#ifdef MSDOS /* MW, May 1993 */
-static int
-valid_filename_p (fn)
- char *fn;
-{
- return *fn == '/' || fn[1] == ':';
-}
-#else
-#define valid_filename_p(fn) (*(fn) == '/')
-#endif
-
-#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 null, space is dynamically allocated.
-
- Return -1 if there is some difficulty accessing the data base
- of terminal types,
- 0 if the data base is accessible but the type NAME is not defined
- in it, and some other value otherwise. */
-
-int
-tgetent (bp, name)
- char *bp, *name;
-{
- register char *termcap_name;
- register int fd;
- struct buffer buf;
- register char *bp1;
- char *tc_search_point;
- char *term;
- int malloc_size = 0;
- register int c;
- char *tcenv; /* TERMCAP value, if it contains :tc=. */
- char *indirect = NULL; /* Terminal type in :tc= in TERMCAP value. */
- int filep;
-
-#ifdef INTERNAL_TERMINAL
- /* For the internal terminal we don't want to read any termcap file,
- so fake it. */
- if (!strcmp (name, "internal"))
- {
- term = INTERNAL_TERMINAL;
- if (!bp)
- {
- malloc_size = 1 + strlen (term);
- bp = (char *) xmalloc (malloc_size);
- }
- strcpy (bp, term);
- goto ret;
- }
-#endif /* INTERNAL_TERMINAL */
-
- /* For compatibility with programs like `less' that want to
- put data in the termcap buffer themselves as a fallback. */
- if (bp)
- term_entry = bp;
-
- termcap_name = getenv ("TERMCAP");
- if (termcap_name && *termcap_name == '\0')
- termcap_name = NULL;
-#if defined (MSDOS) && !defined (TEST)
- if (termcap_name && (*termcap_name == '\\'
- || *termcap_name == '/'
- || termcap_name[1] == ':'))
- dostounix_filename(termcap_name);
-#endif
-
- filep = termcap_name && valid_filename_p (termcap_name);
-
- /* If termcap_name 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 (termcap_name && !filep && !strcmp (name, getenv ("TERM")))
- {
- indirect = tgetst1 (find_capability (termcap_name, "tc"), (char **) 0);
- if (!indirect)
- {
- if (!bp)
- bp = termcap_name;
- else
- strcpy (bp, termcap_name);
- goto ret;
- }
- else
- { /* It has tc=. Need to read /etc/termcap. */
- tcenv = termcap_name;
- termcap_name = NULL;
- }
- }
-
- if (!termcap_name || !filep)
- termcap_name = TERMCAP_FILE;
-
- /* Here we know we must search a file and termcap_name has its name. */
-
-#ifdef MSDOS
- fd = open (termcap_name, O_RDONLY|O_TEXT, 0);
-#else
- fd = open (termcap_name, O_RDONLY, 0);
-#endif
- 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);
- }
- tc_search_point = bp1 = bp;
-
- if (indirect)
- /* Copy the data from the environment variable. */
- {
- strcpy (bp, tcenv);
- bp1 += strlen (tcenv);
- }
-
- while (term)
- {
- /* Scan the file, reading it via buf, till find start of main entry. */
- if (scan_file (term, fd, &buf) == 0)
- {
- close (fd);
- free (buf.beg);
- if (malloc_size)
- free (bp);
- 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;
- termcap_name = (char *) xrealloc (bp, malloc_size);
- bp1 += termcap_name - bp;
- tc_search_point += termcap_name - bp;
- bp = termcap_name;
- }
-
- /* Copy the line of the entry from buf into bp. */
- termcap_name = buf.ptr;
- while ((*bp1++ = c = *termcap_name++) && c != '\n')
- /* Drop out any \ newline sequence. */
- if (c == '\\' && *termcap_name == '\n')
- {
- bp1--;
- termcap_name++;
- }
- *bp1 = '\0';
-
- /* Does this entry refer to another terminal type's entry?
- If something is found, copy it into heap and null-terminate it. */
- tc_search_point = find_capability (tc_search_point, "tc");
- term = tgetst1 (tc_search_point, (char **) 0);
- }
-
- close (fd);
- free (buf.beg);
-
- if (malloc_size)
- bp = (char *) xrealloc (bp, bp1 - bp + 1);
-
- ret:
- term_entry = 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 STR.
- Return 1 if successful, with that line in BUFP,
- or 0 if no entry is found in the file. */
-
-static int
-scan_file (str, fd, bufp)
- char *str;
- int fd;
- register struct buffer *bufp;
-{
- 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 = NULL;
- 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, str))
- 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, we win. */
- return 0;
- 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.
-
- Return 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
- non-null, 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)
- 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
-
-#ifdef NULL
-#undef NULL
-#endif
-
-#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
deleted file mode 100644
index 1feb8772769..00000000000
--- a/src/termchar.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-extern int baud_rate; /* Output speed in baud */
-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 scroll_region_cost; /* Cost of setting the scroll window,
- measured in characters */
-extern int memory_below_frame; /* 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 frame 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;
diff --git a/src/termhooks.h b/src/termhooks.h
deleted file mode 100644
index 984c4284ec1..00000000000
--- a/src/termhooks.h
+++ /dev/null
@@ -1,361 +0,0 @@
-/* Hooks by which low level terminal operations
- can be made to call other routines.
- Copyright (C) 1985, 1986, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Miscellanea. */
-
-/* If nonzero, send all terminal output characters to this stream also. */
-extern FILE *termscript;
-
-
-/* Text display hooks. */
-
-extern int (*cursor_to_hook) ();
-extern int (*raw_cursor_to_hook) ();
-
-extern int (*clear_to_end_hook) ();
-extern int (*clear_frame_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_glyphs_hook) ();
-extern int (*write_glyphs_hook) ();
-extern int (*delete_glyphs_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) ();
-
-
-
-/* Multi-frame and mouse support hooks. */
-
-enum scroll_bar_part {
- scroll_bar_above_handle,
- scroll_bar_handle,
- scroll_bar_below_handle,
- scroll_bar_up_arrow,
- scroll_bar_down_arrow
-};
-
-/* Return the current position of the mouse.
-
- Set *f to the frame the mouse is in, or zero if the mouse is in no
- Emacs frame. If it is set to zero, all the other arguments are
- garbage.
-
- If the motion started in a scroll bar, set *bar_window to the
- scroll bar's window, *part to the part the mouse is currently over,
- *x to the position of the mouse along the scroll bar, and *y to the
- overall length of the scroll bar.
-
- Otherwise, set *bar_window to Qnil, and *x and *y to the column and
- row of the character cell the mouse is over.
-
- Set *time to the time the mouse was at the returned position.
-
- This should clear mouse_moved until the next motion
- event arrives. */
-extern void (*mouse_position_hook) ( /* FRAME_PTR *f,
- Lisp_Object *bar_window,
- enum scroll_bar_part *part,
- Lisp_Object *x,
- Lisp_Object *y,
- unsigned long *time */ );
-
-/* The window system handling code should set this if the mouse has
- moved since the last call to the mouse_position_hook. Calling that
- hook should clear this. */
-extern int mouse_moved;
-
-/* When a frame's focus redirection is changed, this hook tells the
- window system code to re-decide where to put the highlight. Under
- X, this means that Emacs lies about where the focus is. */
-extern void (*frame_rehighlight_hook) ( /* void */ );
-
-/* If we're displaying frames using a window system that can stack
- frames on top of each other, this hook allows you to bring a frame
- to the front, or bury it behind all the other windows. If this
- hook is zero, that means the device we're displaying on doesn't
- support overlapping frames, so there's no need to raise or lower
- anything.
-
- If RAISE is non-zero, F is brought to the front, before all other
- windows. If RAISE is zero, F is sent to the back, behind all other
- windows. */
-extern void (*frame_raise_lower_hook) ( /* FRAME_PTR f, int raise */ );
-
-
-/* Scroll bar hooks. */
-
-/* The representation of scroll bars is determined by the code which
- implements them, except for one thing: they must be represented by
- lisp objects. This allows us to place references to them in
- Lisp_Windows without worrying about those references becoming
- dangling references when the scroll bar is destroyed.
-
- The window-system-independent portion of Emacs just refers to
- scroll bars via their windows, and never looks inside the scroll bar
- representation; it always uses hook functions to do all the
- scroll bar manipulation it needs.
-
- The `vertical_scroll_bar' field of a Lisp_Window refers to that
- window's scroll bar, or is nil if the window doesn't have a
- scroll bar.
-
- The `scroll_bars' and `condemned_scroll_bars' fields of a Lisp_Frame
- are free for use by the scroll bar implementation in any way it sees
- fit. They are marked by the garbage collector. */
-
-
-/* Set the vertical scroll bar for WINDOW to have its upper left corner
- at (TOP, LEFT), and be LENGTH rows high. Set its handle to
- indicate that we are displaying PORTION characters out of a total
- of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
- have a scroll bar, create one for it. */
-extern void (*set_vertical_scroll_bar_hook)
- ( /* struct window *window,
- int portion, int whole, int position */ );
-
-
-/* The following three hooks are used when we're doing a thorough
- redisplay of the frame. We don't explicitly know which scroll bars
- are going to be deleted, because keeping track of when windows go
- away is a real pain - can you say set-window-configuration?
- Instead, we just assert at the beginning of redisplay that *all*
- scroll bars are to be removed, and then save scroll bars from the
- fiery pit when we actually redisplay their window. */
-
-/* Arrange for all scroll bars on FRAME to be removed at the next call
- to `*judge_scroll_bars_hook'. A scroll bar may be spared if
- `*redeem_scroll_bar_hook' is applied to its window before the judgement.
-
- This should be applied to each frame each time its window tree is
- redisplayed, even if it is not displaying scroll bars at the moment;
- if the HAS_SCROLL_BARS flag has just been turned off, only calling
- this and the judge_scroll_bars_hook will get rid of them.
-
- If non-zero, this hook should be safe to apply to any frame,
- whether or not it can support scroll bars, and whether or not it is
- currently displaying them. */
-extern void (*condemn_scroll_bars_hook)( /* FRAME_PTR *frame */ );
-
-/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
- Note that it's okay to redeem a scroll bar that is not condemned. */
-extern void (*redeem_scroll_bar_hook)( /* struct window *window */ );
-
-/* Remove all scroll bars on FRAME that haven't been saved since the
- last call to `*condemn_scroll_bars_hook'.
-
- This should be applied to each frame after each time its window
- tree is redisplayed, even if it is not displaying scroll bars at the
- moment; if the HAS_SCROLL_BARS flag has just been turned off, only
- calling this and condemn_scroll_bars_hook will get rid of them.
-
- If non-zero, this hook should be safe to apply to any frame,
- whether or not it can support scroll bars, and whether or not it is
- currently displaying them. */
-extern void (*judge_scroll_bars_hook)( /* FRAME_PTR *FRAME */ );
-
-
-/* Input queue declarations and hooks. */
-
-/* Called to read input events. */
-extern int (*read_socket_hook) ();
-
-/* Called when a frame's display becomes entirely up to date. */
-extern int (*frame_up_to_date_hook) ();
-
-/* Expedient hack: only provide the below definitions to files that
- are prepared to handle lispy things. CONSP is defined iff lisp.h
- has been included before this file. */
-#ifdef CONSP
-
-enum event_kind
-{
- no_event, /* nothing happened. This should never
- actually appear in the event queue. */
-
- ascii_keystroke, /* The ASCII code is in .code, perhaps
- with modifiers applied.
- .modifiers holds the state of the
- modifier keys.
- .frame_or_window is the frame in
- which the key was typed.
- .timestamp gives a timestamp (in
- milliseconds) for the keystroke. */
- non_ascii_keystroke, /* .code is a number identifying the
- function key. A code N represents
- a key whose name is
- function_key_names[N]; function_key_names
- is a table in keyboard.c to which you
- should feel free to add missing keys.
- .modifiers holds the state of the
- modifier keys.
- .frame_or_window is the frame in
- which the key was typed.
- .timestamp gives a timestamp (in
- milliseconds) for the keystroke. */
- timer_event, /* A timer fired. */
- mouse_click, /* The button number is in .code; it must
- be >= 0 and < NUM_MOUSE_BUTTONS, defined
- below.
- .modifiers holds the state of the
- modifier keys.
- .x and .y give the mouse position,
- in characters, within the window.
- .frame_or_window gives the frame
- the mouse click occurred in.
- .timestamp gives a timestamp (in
- milliseconds) for the click. */
- scroll_bar_click, /* .code gives the number of the mouse button
- that was clicked.
- .modifiers holds the state of the modifier
- keys.
- .part is a lisp symbol indicating which
- part of the scroll bar got clicked.
- .x gives the distance from the start of the
- scroll bar of the click; .y gives the total
- length of the scroll bar.
- .frame_or_window gives the window
- whose scroll bar was clicked in.
- .timestamp gives a timestamp (in
- milliseconds) for the click. */
-#ifdef WINDOWSNT
- w32_scroll_bar_click, /* as for scroll_bar_click, but only generated
- by MS-Windows scroll bar controls. */
-#endif
- selection_request_event, /* Another X client wants a selection from us.
- See `struct selection_event'. */
- selection_clear_event, /* Another X client cleared our selection. */
- buffer_switch_event, /* A process filter has switched buffers. */
- delete_window_event, /* An X client said "delete this window". */
- menu_bar_event, /* An event generated by the menu bar.
- The frame_or_window field's cdr holds the
- Lisp-level event value.
- (Only the toolkit version uses these.) */
- iconify_event, /* An X client iconified this window. */
- deiconify_event, /* An X client deiconified this window. */
- menu_bar_activate_event /* A button press in the menu bar
- (toolkit version only). */
-};
-
-/* If a struct input_event has a kind which is selection_request_event
- or selection_clear_event, then its contents are really described
- by `struct selection_event'; see xterm.h. */
-
-/* The keyboard input buffer is an array of these structures. Each one
- represents some sort of input event - a keystroke, a mouse click, or
- a window system event. These get turned into their lispy forms when
- they are removed from the event queue. */
-
-struct input_event
-{
-
- /* What kind of event was this? */
- int kind;
-
- /* For an ascii_keystroke, this is the character.
- For a non_ascii_keystroke, this is the keysym code.
- For a mouse event, this is the button number. */
- int code;
- enum scroll_bar_part part;
-
- int modifiers; /* See enum below for interpretation. */
-
- Lisp_Object x, y;
- unsigned long timestamp;
-
- /* This is padding just to put the frame_or_window field
- past the size of struct selection_event. */
- int *padding[2];
-
- /* This field is copied into a vector while the event is in the queue,
- so that garbage collections won't kill it. */
- /* In a menu_bar_event, this is a cons cell whose car is the frame
- and whose cdr is the Lisp object that is the event's value. */
- /* This field is last so that struct selection_input_event
- does not overlap with it. */
- Lisp_Object frame_or_window;
-};
-
-/* This is used in keyboard.c, to tell how many buttons we will need
- to track the positions of. */
-#define NUM_MOUSE_BUTTONS (5)
-
-/* Bits in the modifiers member of the input_event structure.
- Note that reorder_modifiers assumes that the bits are in canonical
- order.
-
- The modifiers applied to mouse clicks are rather ornate. The
- window-system-specific code should store mouse clicks with
- up_modifier or down_modifier set. Having an explicit down modifier
- simplifies some of window-system-independent code; without it, the
- code would have to recognize down events by checking if the event
- is a mouse click lacking the click and drag modifiers.
-
- The window-system independent code turns all up_modifier events
- bits into drag_modifier, click_modifier, double_modifier, or
- triple_modifier events. The click_modifier has no written
- representation in the names of the symbols used as event heads,
- but it does appear in the Qevent_symbol_components property of the
- event heads. */
-enum {
- up_modifier = 1, /* Only used on mouse buttons - always
- turned into a click or a drag modifier
- before lisp code sees the event. */
- down_modifier = 2, /* Only used on mouse buttons. */
- drag_modifier = 4, /* This is never used in the event
- queue; it's only used internally by
- the window-system-independent code. */
- click_modifier= 8, /* See drag_modifier. */
- double_modifier= 16, /* See drag_modifier. */
- triple_modifier= 32, /* See drag_modifier. */
-
- /* The next four modifier bits are used also in keyboard events at
- the Lisp level.
-
- It's probably not the greatest idea to use the 2^23 bit for any
- modifier. It may or may not be the sign bit, depending on
- VALBITS, so using it to represent a modifier key means that
- characters thus modified have different integer equivalents
- depending on the architecture they're running on. Oh, and
- applying XINT to a character whose 2^23 bit is set sign-extends
- it, so you get a bunch of bits in the mask you didn't want.
-
- The CHAR_ macros are defined in lisp.h. */
- alt_modifier = CHAR_ALT, /* Under X, the XK_Alt_[LR] keysyms. */
- super_modifier= CHAR_SUPER, /* Under X, the XK_Super_[LR] keysyms. */
- hyper_modifier= CHAR_HYPER, /* Under X, the XK_Hyper_[LR] keysyms. */
- shift_modifier= CHAR_SHIFT,
- ctrl_modifier = CHAR_CTL,
- meta_modifier = CHAR_META /* Under X, the XK_Meta_[LR] keysyms. */
-};
-
-#endif
diff --git a/src/terminfo.c b/src/terminfo.c
deleted file mode 100644
index ab6ab9e4ccb..00000000000
--- a/src/terminfo.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include <config.h>
-
-/* 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;
-
-#ifdef HAVE_TERMIOS_H
-#include <termios.h>
-speed_t ospeed;
-#else
-short ospeed;
-#endif
-
-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
deleted file mode 100644
index 0fd240bd005..00000000000
--- a/src/termopts.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Flags and parameters describing user options for handling the terminal.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* 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;
-
-/* Terminal has meta key */
-extern int meta_key;
-
-/* Nonzero means truncate lines in all windows less wide than the frame */
-extern int truncate_partial_width_windows;
diff --git a/src/textprop.c b/src/textprop.c
deleted file mode 100644
index 3e667825d4b..00000000000
--- a/src/textprop.c
+++ /dev/null
@@ -1,1790 +0,0 @@
-/* Interface code for dealing with text properties.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include <config.h>
-#include "lisp.h"
-#include "intervals.h"
-#include "buffer.h"
-#include "window.h"
-
-#ifndef NULL
-#define NULL (void *)0
-#endif
-
-/* Test for membership, allowing for t (actually any non-cons) to mean the
- universal set. */
-
-#define TMEM(sym, set) (CONSP (set) ? ! NILP (Fmemq (sym, set)) : ! NILP (set))
-
-
-/* NOTES: previous- and next- property change will have to skip
- zero-length intervals if they are implemented. This could be done
- inside next_interval and previous_interval.
-
- set_properties needs to deal with the interval property cache.
-
- It is assumed that for any interval plist, a property appears
- only once on the list. Although some code i.e., remove_properties,
- handles the more general case, the uniqueness of properties is
- necessary for the system to remain consistent. This requirement
- is enforced by the subrs installing properties onto the intervals. */
-
-/* The rest of the file is within this conditional */
-#ifdef USE_TEXT_PROPERTIES
-
-/* Types of hooks. */
-Lisp_Object Qmouse_left;
-Lisp_Object Qmouse_entered;
-Lisp_Object Qpoint_left;
-Lisp_Object Qpoint_entered;
-Lisp_Object Qcategory;
-Lisp_Object Qlocal_map;
-
-/* Visual properties text (including strings) may have. */
-Lisp_Object Qforeground, Qbackground, Qfont, Qunderline, Qstipple;
-Lisp_Object Qinvisible, Qread_only, Qintangible;
-
-/* Sticky properties */
-Lisp_Object Qfront_sticky, Qrear_nonsticky;
-
-/* If o1 is a cons whose cdr is a cons, return non-zero and set o2 to
- the o1's cdr. Otherwise, return zero. This is handy for
- traversing plists. */
-#define PLIST_ELT_P(o1, o2) (CONSP (o1) && ((o2)=XCONS (o1)->cdr, CONSP (o2)))
-
-Lisp_Object Vinhibit_point_motion_hooks;
-Lisp_Object Vdefault_text_properties;
-
-/* verify_interval_modification saves insertion hooks here
- to be run later by report_interval_modification. */
-Lisp_Object interval_insert_behind_hooks;
-Lisp_Object interval_insert_in_front_hooks;
-
-/* Extract the interval at the position pointed to by BEGIN from
- OBJECT, a string or buffer. Additionally, check that the positions
- pointed to by BEGIN and END are within the bounds of OBJECT, and
- reverse them if *BEGIN is greater than *END. The objects pointed
- to by BEGIN and END may be integers or markers; if the latter, they
- are coerced to integers.
-
- When OBJECT is a string, we increment *BEGIN and *END
- to make them origin-one.
-
- Note that buffer points don't correspond to interval indices.
- For example, point-max is 1 greater than the index of the last
- character. This difference is handled in the caller, which uses
- the validated points to determine a length, and operates on that.
- Exceptions are Ftext_properties_at, Fnext_property_change, and
- Fprevious_property_change which call this function with BEGIN == END.
- Handle this case specially.
-
- If FORCE is soft (0), it's OK to return NULL_INTERVAL. Otherwise,
- create an interval tree for OBJECT if one doesn't exist, provided
- the object actually contains text. In the current design, if there
- is no text, there can be no text properties. */
-
-#define soft 0
-#define hard 1
-
-static INTERVAL
-validate_interval_range (object, begin, end, force)
- Lisp_Object object, *begin, *end;
- int force;
-{
- register INTERVAL i;
- int searchpos;
-
- CHECK_STRING_OR_BUFFER (object, 0);
- CHECK_NUMBER_COERCE_MARKER (*begin, 0);
- CHECK_NUMBER_COERCE_MARKER (*end, 0);
-
- /* If we are asked for a point, but from a subr which operates
- on a range, then return nothing. */
- if (EQ (*begin, *end) && begin != end)
- return NULL_INTERVAL;
-
- if (XINT (*begin) > XINT (*end))
- {
- Lisp_Object n;
- n = *begin;
- *begin = *end;
- *end = n;
- }
-
- if (BUFFERP (object))
- {
- register struct buffer *b = XBUFFER (object);
-
- if (!(BUF_BEGV (b) <= XINT (*begin) && XINT (*begin) <= XINT (*end)
- && XINT (*end) <= BUF_ZV (b)))
- args_out_of_range (*begin, *end);
- i = BUF_INTERVALS (b);
-
- /* If there's no text, there are no properties. */
- if (BUF_BEGV (b) == BUF_ZV (b))
- return NULL_INTERVAL;
-
- searchpos = XINT (*begin);
- }
- else
- {
- register struct Lisp_String *s = XSTRING (object);
-
- if (! (0 <= XINT (*begin) && XINT (*begin) <= XINT (*end)
- && XINT (*end) <= s->size))
- args_out_of_range (*begin, *end);
- /* User-level Positions in strings start with 0,
- but the interval code always wants positions starting with 1. */
- XSETFASTINT (*begin, XFASTINT (*begin) + 1);
- if (begin != end)
- XSETFASTINT (*end, XFASTINT (*end) + 1);
- i = s->intervals;
-
- if (s->size == 0)
- return NULL_INTERVAL;
-
- searchpos = XINT (*begin);
- }
-
- if (NULL_INTERVAL_P (i))
- return (force ? create_root_interval (object) : i);
-
- return find_interval (i, searchpos);
-}
-
-/* Validate LIST as a property list. If LIST is not a list, then
- make one consisting of (LIST nil). Otherwise, verify that LIST
- is even numbered and thus suitable as a plist. */
-
-static Lisp_Object
-validate_plist (list)
- Lisp_Object list;
-{
- if (NILP (list))
- return Qnil;
-
- if (CONSP (list))
- {
- register int i;
- register Lisp_Object tail;
- for (i = 0, tail = list; !NILP (tail); i++)
- {
- tail = Fcdr (tail);
- QUIT;
- }
- if (i & 1)
- error ("Odd length text property list");
- return list;
- }
-
- return Fcons (list, Fcons (Qnil, Qnil));
-}
-
-/* Return nonzero if interval I has all the properties,
- with the same values, of list PLIST. */
-
-static int
-interval_has_all_properties (plist, i)
- Lisp_Object plist;
- INTERVAL i;
-{
- register Lisp_Object tail1, tail2, sym1, sym2;
- register int found;
-
- /* Go through each element of PLIST. */
- for (tail1 = plist; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1)))
- {
- sym1 = Fcar (tail1);
- found = 0;
-
- /* Go through I's plist, looking for sym1 */
- for (tail2 = i->plist; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2)))
- if (EQ (sym1, Fcar (tail2)))
- {
- /* Found the same property on both lists. If the
- values are unequal, return zero. */
- if (! EQ (Fcar (Fcdr (tail1)), Fcar (Fcdr (tail2))))
- return 0;
-
- /* Property has same value on both lists; go to next one. */
- found = 1;
- break;
- }
-
- if (! found)
- return 0;
- }
-
- return 1;
-}
-
-/* Return nonzero if the plist of interval I has any of the
- properties of PLIST, regardless of their values. */
-
-static INLINE int
-interval_has_some_properties (plist, i)
- Lisp_Object plist;
- INTERVAL i;
-{
- register Lisp_Object tail1, tail2, sym;
-
- /* Go through each element of PLIST. */
- for (tail1 = plist; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1)))
- {
- sym = Fcar (tail1);
-
- /* Go through i's plist, looking for tail1 */
- for (tail2 = i->plist; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2)))
- if (EQ (sym, Fcar (tail2)))
- return 1;
- }
-
- return 0;
-}
-
-/* Changing the plists of individual intervals. */
-
-/* Return the value of PROP in property-list PLIST, or Qunbound if it
- has none. */
-static Lisp_Object
-property_value (plist, prop)
- Lisp_Object plist, prop;
-{
- Lisp_Object value;
-
- while (PLIST_ELT_P (plist, value))
- if (EQ (XCONS (plist)->car, prop))
- return XCONS (value)->car;
- else
- plist = XCONS (value)->cdr;
-
- return Qunbound;
-}
-
-/* Set the properties of INTERVAL to PROPERTIES,
- and record undo info for the previous values.
- OBJECT is the string or buffer that INTERVAL belongs to. */
-
-static void
-set_properties (properties, interval, object)
- Lisp_Object properties, object;
- INTERVAL interval;
-{
- Lisp_Object sym, value;
-
- if (BUFFERP (object))
- {
- /* For each property in the old plist which is missing from PROPERTIES,
- or has a different value in PROPERTIES, make an undo record. */
- for (sym = interval->plist;
- PLIST_ELT_P (sym, value);
- sym = XCONS (value)->cdr)
- if (! EQ (property_value (properties, XCONS (sym)->car),
- XCONS (value)->car))
- {
- record_property_change (interval->position, LENGTH (interval),
- XCONS (sym)->car, XCONS (value)->car,
- object);
- }
-
- /* For each new property that has no value at all in the old plist,
- make an undo record binding it to nil, so it will be removed. */
- for (sym = properties;
- PLIST_ELT_P (sym, value);
- sym = XCONS (value)->cdr)
- if (EQ (property_value (interval->plist, XCONS (sym)->car), Qunbound))
- {
- record_property_change (interval->position, LENGTH (interval),
- XCONS (sym)->car, Qnil,
- object);
- }
- }
-
- /* Store new properties. */
- interval->plist = Fcopy_sequence (properties);
-}
-
-/* Add the properties of PLIST to the interval I, or set
- the value of I's property to the value of the property on PLIST
- if they are different.
-
- OBJECT should be the string or buffer the interval is in.
-
- Return nonzero if this changes I (i.e., if any members of PLIST
- are actually added to I's plist) */
-
-static int
-add_properties (plist, i, object)
- Lisp_Object plist;
- INTERVAL i;
- Lisp_Object object;
-{
- Lisp_Object tail1, tail2, sym1, val1;
- register int changed = 0;
- register int found;
- struct gcpro gcpro1, gcpro2, gcpro3;
-
- tail1 = plist;
- sym1 = Qnil;
- val1 = Qnil;
- /* No need to protect OBJECT, because we can GC only in the case
- where it is a buffer, and live buffers are always protected.
- I and its plist are also protected, via OBJECT. */
- GCPRO3 (tail1, sym1, val1);
-
- /* Go through each element of PLIST. */
- for (tail1 = plist; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1)))
- {
- sym1 = Fcar (tail1);
- val1 = Fcar (Fcdr (tail1));
- found = 0;
-
- /* Go through I's plist, looking for sym1 */
- for (tail2 = i->plist; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2)))
- if (EQ (sym1, Fcar (tail2)))
- {
- /* No need to gcpro, because tail2 protects this
- and it must be a cons cell (we get an error otherwise). */
- register Lisp_Object this_cdr;
-
- this_cdr = Fcdr (tail2);
- /* Found the property. Now check its value. */
- found = 1;
-
- /* The properties have the same value on both lists.
- Continue to the next property. */
- if (EQ (val1, Fcar (this_cdr)))
- break;
-
- /* Record this change in the buffer, for undo purposes. */
- if (BUFFERP (object))
- {
- record_property_change (i->position, LENGTH (i),
- sym1, Fcar (this_cdr), object);
- }
-
- /* I's property has a different value -- change it */
- Fsetcar (this_cdr, val1);
- changed++;
- break;
- }
-
- if (! found)
- {
- /* Record this change in the buffer, for undo purposes. */
- if (BUFFERP (object))
- {
- record_property_change (i->position, LENGTH (i),
- sym1, Qnil, object);
- }
- i->plist = Fcons (sym1, Fcons (val1, i->plist));
- changed++;
- }
- }
-
- UNGCPRO;
-
- return changed;
-}
-
-/* For any members of PLIST which are properties of I, remove them
- from I's plist.
- OBJECT is the string or buffer containing I. */
-
-static int
-remove_properties (plist, i, object)
- Lisp_Object plist;
- INTERVAL i;
- Lisp_Object object;
-{
- register Lisp_Object tail1, tail2, sym, current_plist;
- register int changed = 0;
-
- current_plist = i->plist;
- /* Go through each element of plist. */
- for (tail1 = plist; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1)))
- {
- sym = Fcar (tail1);
-
- /* First, remove the symbol if its at the head of the list */
- while (! NILP (current_plist) && EQ (sym, Fcar (current_plist)))
- {
- if (BUFFERP (object))
- {
- record_property_change (i->position, LENGTH (i),
- sym, Fcar (Fcdr (current_plist)),
- object);
- }
-
- current_plist = Fcdr (Fcdr (current_plist));
- changed++;
- }
-
- /* Go through i's plist, looking for sym */
- tail2 = current_plist;
- while (! NILP (tail2))
- {
- register Lisp_Object this;
- this = Fcdr (Fcdr (tail2));
- if (EQ (sym, Fcar (this)))
- {
- if (BUFFERP (object))
- {
- record_property_change (i->position, LENGTH (i),
- sym, Fcar (Fcdr (this)), object);
- }
-
- Fsetcdr (Fcdr (tail2), Fcdr (Fcdr (this)));
- changed++;
- }
- tail2 = this;
- }
- }
-
- if (changed)
- i->plist = current_plist;
- return changed;
-}
-
-#if 0
-/* Remove all properties from interval I. Return non-zero
- if this changes the interval. */
-
-static INLINE int
-erase_properties (i)
- INTERVAL i;
-{
- if (NILP (i->plist))
- return 0;
-
- i->plist = Qnil;
- return 1;
-}
-#endif
-
-DEFUN ("text-properties-at", Ftext_properties_at,
- Stext_properties_at, 1, 2, 0,
- "Return the list of properties held by the character at POSITION\n\
-in optional argument OBJECT, a string or buffer. If nil, OBJECT\n\
-defaults to the current buffer.\n\
-If POSITION is at the end of OBJECT, the value is nil.")
- (position, object)
- Lisp_Object position, object;
-{
- register INTERVAL i;
-
- if (NILP (object))
- XSETBUFFER (object, current_buffer);
-
- i = validate_interval_range (object, &position, &position, soft);
- if (NULL_INTERVAL_P (i))
- return Qnil;
- /* If POSITION is at the end of the interval,
- it means it's the end of OBJECT.
- There are no properties at the very end,
- since no character follows. */
- if (XINT (position) == LENGTH (i) + i->position)
- return Qnil;
-
- return i->plist;
-}
-
-DEFUN ("get-text-property", Fget_text_property, Sget_text_property, 2, 3, 0,
- "Return the value of POSITION's property PROP, in OBJECT.\n\
-OBJECT is optional and defaults to the current buffer.\n\
-If POSITION is at the end of OBJECT, the value is nil.")
- (position, prop, object)
- Lisp_Object position, object;
- Lisp_Object prop;
-{
- return textget (Ftext_properties_at (position, object), prop);
-}
-
-DEFUN ("get-char-property", Fget_char_property, Sget_char_property, 2, 3, 0,
- "Return the value of POSITION's property PROP, in OBJECT.\n\
-OBJECT is optional and defaults to the current buffer.\n\
-If POSITION is at the end of OBJECT, the value is nil.\n\
-If OBJECT is a buffer, then overlay properties are considered as well as\n\
-text properties.\n\
-If OBJECT is a window, then that window's buffer is used, but window-specific\n\
-overlays are considered only if they are associated with OBJECT.")
- (position, prop, object)
- Lisp_Object position, object;
- register Lisp_Object prop;
-{
- struct window *w = 0;
-
- CHECK_NUMBER_COERCE_MARKER (position, 0);
-
- if (NILP (object))
- XSETBUFFER (object, current_buffer);
-
- if (WINDOWP (object))
- {
- w = XWINDOW (object);
- object = w->buffer;
- }
- if (BUFFERP (object))
- {
- int posn = XINT (position);
- int noverlays;
- Lisp_Object *overlay_vec, tem;
- int next_overlay;
- int len;
- struct buffer *obuf = current_buffer;
-
- set_buffer_temp (XBUFFER (object));
-
- /* First try with room for 40 overlays. */
- len = 40;
- overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-
- noverlays = overlays_at (posn, 0, &overlay_vec, &len,
- &next_overlay, NULL);
-
- /* If there are more than 40,
- make enough space for all, and try again. */
- if (noverlays > len)
- {
- len = noverlays;
- overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- noverlays = overlays_at (posn, 0, &overlay_vec, &len,
- &next_overlay, NULL);
- }
- noverlays = sort_overlays (overlay_vec, noverlays, w);
-
- set_buffer_temp (obuf);
-
- /* Now check the overlays in order of decreasing priority. */
- while (--noverlays >= 0)
- {
- tem = Foverlay_get (overlay_vec[noverlays], prop);
- if (!NILP (tem))
- return (tem);
- }
- }
- /* Not a buffer, or no appropriate overlay, so fall through to the
- simpler case. */
- return (Fget_text_property (position, prop, object));
-}
-
-DEFUN ("next-char-property-change", Fnext_char_property_change,
- Snext_char_property_change, 1, 2, 0,
- "Return the position of next text property or overlay change.\n\
-This scans characters forward from POSITION in OBJECT till it finds\n\
-a change in some text property, or the beginning or end of an overlay,\n\
-and returns the position of that.\n\
-If none is found, the function returns (point-max).\n\
-\n\
-If the optional third argument LIMIT is non-nil, don't search\n\
-past position LIMIT; return LIMIT if nothing is found before LIMIT.")
- (position, limit)
- Lisp_Object position, limit;
-{
- Lisp_Object temp;
-
- temp = Fnext_overlay_change (position);
- if (! NILP (limit))
- {
- CHECK_NUMBER (limit, 2);
- if (XINT (limit) < XINT (temp))
- temp = limit;
- }
- return Fnext_property_change (position, Qnil, temp);
-}
-
-DEFUN ("previous-char-property-change", Fprevious_char_property_change,
- Sprevious_char_property_change, 1, 2, 0,
- "Return the position of previous text property or overlay change.\n\
-Scans characters backward from POSITION in OBJECT till it finds\n\
-a change in some text property, or the beginning or end of an overlay,\n\
-and returns the position of that.\n\
-If none is found, the function returns (point-max).\n\
-\n\
-If the optional third argument LIMIT is non-nil, don't search\n\
-past position LIMIT; return LIMIT if nothing is found before LIMIT.")
- (position, limit)
- Lisp_Object position, limit;
-{
- Lisp_Object temp;
-
- temp = Fprevious_overlay_change (position);
- if (! NILP (limit))
- {
- CHECK_NUMBER (limit, 2);
- if (XINT (limit) > XINT (temp))
- temp = limit;
- }
- return Fprevious_property_change (position, Qnil, temp);
-}
-
-DEFUN ("next-property-change", Fnext_property_change,
- Snext_property_change, 1, 3, 0,
- "Return the position of next property change.\n\
-Scans characters forward from POSITION in OBJECT till it finds\n\
-a change in some text property, then returns the position of the change.\n\
-The optional second argument OBJECT is the string or buffer to scan.\n\
-Return nil if the property is constant all the way to the end of OBJECT.\n\
-If the value is non-nil, it is a position greater than POSITION, never equal.\n\n\
-If the optional third argument LIMIT is non-nil, don't search\n\
-past position LIMIT; return LIMIT if nothing is found before LIMIT.")
- (position, object, limit)
- Lisp_Object position, object, limit;
-{
- register INTERVAL i, next;
-
- if (NILP (object))
- XSETBUFFER (object, current_buffer);
-
- if (! NILP (limit) && ! EQ (limit, Qt))
- CHECK_NUMBER_COERCE_MARKER (limit, 0);
-
- i = validate_interval_range (object, &position, &position, soft);
-
- /* If LIMIT is t, return start of next interval--don't
- bother checking further intervals. */
- if (EQ (limit, Qt))
- {
- if (NULL_INTERVAL_P (i))
- next = i;
- else
- next = next_interval (i);
-
- if (NULL_INTERVAL_P (next))
- XSETFASTINT (position, (STRINGP (object)
- ? XSTRING (object)->size
- : BUF_ZV (XBUFFER (object))));
- else
- XSETFASTINT (position, next->position - (STRINGP (object)));
- return position;
- }
-
- if (NULL_INTERVAL_P (i))
- return limit;
-
- next = next_interval (i);
-
- while (! NULL_INTERVAL_P (next) && intervals_equal (i, next)
- && (NILP (limit) || next->position < XFASTINT (limit)))
- next = next_interval (next);
-
- if (NULL_INTERVAL_P (next))
- return limit;
- if (! NILP (limit) && !(next->position < XFASTINT (limit)))
- return limit;
-
- XSETFASTINT (position, next->position - (STRINGP (object)));
- return position;
-}
-
-/* Return 1 if there's a change in some property between BEG and END. */
-
-int
-property_change_between_p (beg, end)
- int beg, end;
-{
- register INTERVAL i, next;
- Lisp_Object object, pos;
-
- XSETBUFFER (object, current_buffer);
- XSETFASTINT (pos, beg);
-
- i = validate_interval_range (object, &pos, &pos, soft);
- if (NULL_INTERVAL_P (i))
- return 0;
-
- next = next_interval (i);
- while (! NULL_INTERVAL_P (next) && intervals_equal (i, next))
- {
- next = next_interval (next);
- if (NULL_INTERVAL_P (next))
- return 0;
- if (next->position >= end)
- return 0;
- }
-
- if (NULL_INTERVAL_P (next))
- return 0;
-
- return 1;
-}
-
-DEFUN ("next-single-property-change", Fnext_single_property_change,
- Snext_single_property_change, 2, 4, 0,
- "Return the position of next property change for a specific property.\n\
-Scans characters forward from POSITION till it finds\n\
-a change in the PROP property, then returns the position of the change.\n\
-The optional third argument OBJECT is the string or buffer to scan.\n\
-The property values are compared with `eq'.\n\
-Return nil if the property is constant all the way to the end of OBJECT.\n\
-If the value is non-nil, it is a position greater than POSITION, never equal.\n\n\
-If the optional fourth argument LIMIT is non-nil, don't search\n\
-past position LIMIT; return LIMIT if nothing is found before LIMIT.")
- (position, prop, object, limit)
- Lisp_Object position, prop, object, limit;
-{
- register INTERVAL i, next;
- register Lisp_Object here_val;
-
- if (NILP (object))
- XSETBUFFER (object, current_buffer);
-
- if (!NILP (limit))
- CHECK_NUMBER_COERCE_MARKER (limit, 0);
-
- i = validate_interval_range (object, &position, &position, soft);
- if (NULL_INTERVAL_P (i))
- return limit;
-
- here_val = textget (i->plist, prop);
- next = next_interval (i);
- while (! NULL_INTERVAL_P (next)
- && EQ (here_val, textget (next->plist, prop))
- && (NILP (limit) || next->position < XFASTINT (limit)))
- next = next_interval (next);
-
- if (NULL_INTERVAL_P (next))
- return limit;
- if (! NILP (limit) && !(next->position < XFASTINT (limit)))
- return limit;
-
- XSETFASTINT (position, next->position - (STRINGP (object)));
- return position;
-}
-
-DEFUN ("previous-property-change", Fprevious_property_change,
- Sprevious_property_change, 1, 3, 0,
- "Return the position of previous property change.\n\
-Scans characters backwards from POSITION in OBJECT till it finds\n\
-a change in some text property, then returns the position of the change.\n\
-The optional second argument OBJECT is the string or buffer to scan.\n\
-Return nil if the property is constant all the way to the start of OBJECT.\n\
-If the value is non-nil, it is a position less than POSITION, never equal.\n\n\
-If the optional third argument LIMIT is non-nil, don't search\n\
-back past position LIMIT; return LIMIT if nothing is found until LIMIT.")
- (position, object, limit)
- Lisp_Object position, object, limit;
-{
- register INTERVAL i, previous;
-
- if (NILP (object))
- XSETBUFFER (object, current_buffer);
-
- if (!NILP (limit))
- CHECK_NUMBER_COERCE_MARKER (limit, 0);
-
- i = validate_interval_range (object, &position, &position, soft);
- if (NULL_INTERVAL_P (i))
- return limit;
-
- /* Start with the interval containing the char before point. */
- if (i->position == XFASTINT (position))
- i = previous_interval (i);
-
- previous = previous_interval (i);
- while (! NULL_INTERVAL_P (previous) && intervals_equal (previous, i)
- && (NILP (limit)
- || previous->position + LENGTH (previous) > XFASTINT (limit)))
- previous = previous_interval (previous);
- if (NULL_INTERVAL_P (previous))
- return limit;
- if (!NILP (limit)
- && !(previous->position + LENGTH (previous) > XFASTINT (limit)))
- return limit;
-
- XSETFASTINT (position, (previous->position + LENGTH (previous)
- - (STRINGP (object))));
- return position;
-}
-
-DEFUN ("previous-single-property-change", Fprevious_single_property_change,
- Sprevious_single_property_change, 2, 4, 0,
- "Return the position of previous property change for a specific property.\n\
-Scans characters backward from POSITION till it finds\n\
-a change in the PROP property, then returns the position of the change.\n\
-The optional third argument OBJECT is the string or buffer to scan.\n\
-The property values are compared with `eq'.\n\
-Return nil if the property is constant all the way to the start of OBJECT.\n\
-If the value is non-nil, it is a position less than POSITION, never equal.\n\n\
-If the optional fourth argument LIMIT is non-nil, don't search\n\
-back past position LIMIT; return LIMIT if nothing is found until LIMIT.")
- (position, prop, object, limit)
- Lisp_Object position, prop, object, limit;
-{
- register INTERVAL i, previous;
- register Lisp_Object here_val;
-
- if (NILP (object))
- XSETBUFFER (object, current_buffer);
-
- if (!NILP (limit))
- CHECK_NUMBER_COERCE_MARKER (limit, 0);
-
- i = validate_interval_range (object, &position, &position, soft);
-
- /* Start with the interval containing the char before point. */
- if (! NULL_INTERVAL_P (i) && i->position == XFASTINT (position))
- i = previous_interval (i);
-
- if (NULL_INTERVAL_P (i))
- return limit;
-
- here_val = textget (i->plist, prop);
- previous = previous_interval (i);
- while (! NULL_INTERVAL_P (previous)
- && EQ (here_val, textget (previous->plist, prop))
- && (NILP (limit)
- || previous->position + LENGTH (previous) > XFASTINT (limit)))
- previous = previous_interval (previous);
- if (NULL_INTERVAL_P (previous))
- return limit;
- if (!NILP (limit)
- && !(previous->position + LENGTH (previous) > XFASTINT (limit)))
- return limit;
-
- XSETFASTINT (position, (previous->position + LENGTH (previous)
- - (STRINGP (object))));
- return position;
-}
-
-/* Callers note, this can GC when OBJECT is a buffer (or nil). */
-
-DEFUN ("add-text-properties", Fadd_text_properties,
- Sadd_text_properties, 3, 4, 0,
- "Add properties to the text from START to END.\n\
-The third argument PROPERTIES is a property list\n\
-specifying the property values to add.\n\
-The optional fourth argument, OBJECT,\n\
-is the string or buffer containing the text.\n\
-Return t if any property value actually changed, nil otherwise.")
- (start, end, properties, object)
- Lisp_Object start, end, properties, object;
-{
- register INTERVAL i, unchanged;
- register int s, len, modified = 0;
- struct gcpro gcpro1;
-
- properties = validate_plist (properties);
- if (NILP (properties))
- return Qnil;
-
- if (NILP (object))
- XSETBUFFER (object, current_buffer);
-
- i = validate_interval_range (object, &start, &end, hard);
- if (NULL_INTERVAL_P (i))
- return Qnil;
-
- s = XINT (start);
- len = XINT (end) - s;
-
- /* No need to protect OBJECT, because we GC only if it's a buffer,
- and live buffers are always protected. */
- GCPRO1 (properties);
-
- /* If we're not starting on an interval boundary, we have to
- split this interval. */
- if (i->position != s)
- {
- /* If this interval already has the properties, we can
- skip it. */
- if (interval_has_all_properties (properties, i))
- {
- int got = (LENGTH (i) - (s - i->position));
- if (got >= len)
- RETURN_UNGCPRO (Qnil);
- len -= got;
- i = next_interval (i);
- }
- else
- {
- unchanged = i;
- i = split_interval_right (unchanged, s - unchanged->position);
- copy_properties (unchanged, i);
- }
- }
-
- if (BUFFERP (object))
- modify_region (XBUFFER (object), XINT (start), XINT (end));
-
- /* We are at the beginning of interval I, with LEN chars to scan. */
- for (;;)
- {
- if (i == 0)
- abort ();
-
- if (LENGTH (i) >= len)
- {
- /* We can UNGCPRO safely here, because there will be just
- one more chance to gc, in the next call to add_properties,
- and after that we will not need PROPERTIES or OBJECT again. */
- UNGCPRO;
-
- if (interval_has_all_properties (properties, i))
- {
- if (BUFFERP (object))
- signal_after_change (XINT (start), XINT (end) - XINT (start),
- XINT (end) - XINT (start));
-
- return modified ? Qt : Qnil;
- }
-
- if (LENGTH (i) == len)
- {
- add_properties (properties, i, object);
- if (BUFFERP (object))
- signal_after_change (XINT (start), XINT (end) - XINT (start),
- XINT (end) - XINT (start));
- return Qt;
- }
-
- /* i doesn't have the properties, and goes past the change limit */
- unchanged = i;
- i = split_interval_left (unchanged, len);
- copy_properties (unchanged, i);
- add_properties (properties, i, object);
- if (BUFFERP (object))
- signal_after_change (XINT (start), XINT (end) - XINT (start),
- XINT (end) - XINT (start));
- return Qt;
- }
-
- len -= LENGTH (i);
- modified += add_properties (properties, i, object);
- i = next_interval (i);
- }
-}
-
-/* Callers note, this can GC when OBJECT is a buffer (or nil). */
-
-DEFUN ("put-text-property", Fput_text_property,
- Sput_text_property, 4, 5, 0,
- "Set one property of the text from START to END.\n\
-The third and fourth arguments PROPERTY and VALUE\n\
-specify the property to add.\n\
-The optional fifth argument, OBJECT,\n\
-is the string or buffer containing the text.")
- (start, end, property, value, object)
- Lisp_Object start, end, property, value, object;
-{
- Fadd_text_properties (start, end,
- Fcons (property, Fcons (value, Qnil)),
- object);
- return Qnil;
-}
-
-DEFUN ("set-text-properties", Fset_text_properties,
- Sset_text_properties, 3, 4, 0,
- "Completely replace properties of text from START to END.\n\
-The third argument PROPERTIES is the new property list.\n\
-The optional fourth argument, OBJECT,\n\
-is the string or buffer containing the text.")
- (start, end, properties, object)
- Lisp_Object start, end, properties, object;
-{
- register INTERVAL i, unchanged;
- register INTERVAL prev_changed = NULL_INTERVAL;
- register int s, len;
- Lisp_Object ostart, oend;
- int have_modified = 0;
-
- ostart = start;
- oend = end;
-
- properties = validate_plist (properties);
-
- if (NILP (object))
- XSETBUFFER (object, current_buffer);
-
- /* If we want no properties for a whole string,
- get rid of its intervals. */
- if (NILP (properties) && STRINGP (object)
- && XFASTINT (start) == 0
- && XFASTINT (end) == XSTRING (object)->size)
- {
- if (! XSTRING (object)->intervals)
- return Qt;
-
- XSTRING (object)->intervals = 0;
- return Qt;
- }
-
- i = validate_interval_range (object, &start, &end, soft);
-
- if (NULL_INTERVAL_P (i))
- {
- /* If buffer has no properties, and we want none, return now. */
- if (NILP (properties))
- return Qnil;
-
- /* Restore the original START and END values
- because validate_interval_range increments them for strings. */
- start = ostart;
- end = oend;
-
- i = validate_interval_range (object, &start, &end, hard);
- /* This can return if start == end. */
- if (NULL_INTERVAL_P (i))
- return Qnil;
- }
-
- s = XINT (start);
- len = XINT (end) - s;
-
- if (BUFFERP (object))
- modify_region (XBUFFER (object), XINT (start), XINT (end));
-
- if (i->position != s)
- {
- unchanged = i;
- i = split_interval_right (unchanged, s - unchanged->position);
-
- if (LENGTH (i) > len)
- {
- copy_properties (unchanged, i);
- i = split_interval_left (i, len);
- set_properties (properties, i, object);
- if (BUFFERP (object))
- signal_after_change (XINT (start), XINT (end) - XINT (start),
- XINT (end) - XINT (start));
-
- return Qt;
- }
-
- set_properties (properties, i, object);
-
- if (LENGTH (i) == len)
- {
- if (BUFFERP (object))
- signal_after_change (XINT (start), XINT (end) - XINT (start),
- XINT (end) - XINT (start));
-
- return Qt;
- }
-
- prev_changed = i;
- len -= LENGTH (i);
- i = next_interval (i);
- }
-
- /* We are starting at the beginning of an interval, I */
- while (len > 0)
- {
- if (i == 0)
- abort ();
-
- if (LENGTH (i) >= len)
- {
- if (LENGTH (i) > len)
- i = split_interval_left (i, len);
-
- /* We have to call set_properties even if we are going to
- merge the intervals, so as to make the undo records
- and cause redisplay to happen. */
- set_properties (properties, i, object);
- if (!NULL_INTERVAL_P (prev_changed))
- merge_interval_left (i);
- if (BUFFERP (object))
- signal_after_change (XINT (start), XINT (end) - XINT (start),
- XINT (end) - XINT (start));
- return Qt;
- }
-
- len -= LENGTH (i);
-
- /* We have to call set_properties even if we are going to
- merge the intervals, so as to make the undo records
- and cause redisplay to happen. */
- set_properties (properties, i, object);
- if (NULL_INTERVAL_P (prev_changed))
- prev_changed = i;
- else
- prev_changed = i = merge_interval_left (i);
-
- i = next_interval (i);
- }
-
- if (BUFFERP (object))
- signal_after_change (XINT (start), XINT (end) - XINT (start),
- XINT (end) - XINT (start));
- return Qt;
-}
-
-DEFUN ("remove-text-properties", Fremove_text_properties,
- Sremove_text_properties, 3, 4, 0,
- "Remove some properties from text from START to END.\n\
-The third argument PROPERTIES is a property list\n\
-whose property names specify the properties to remove.\n\
-\(The values stored in PROPERTIES are ignored.)\n\
-The optional fourth argument, OBJECT,\n\
-is the string or buffer containing the text.\n\
-Return t if any property was actually removed, nil otherwise.")
- (start, end, properties, object)
- Lisp_Object start, end, properties, object;
-{
- register INTERVAL i, unchanged;
- register int s, len, modified = 0;
-
- if (NILP (object))
- XSETBUFFER (object, current_buffer);
-
- i = validate_interval_range (object, &start, &end, soft);
- if (NULL_INTERVAL_P (i))
- return Qnil;
-
- s = XINT (start);
- len = XINT (end) - s;
-
- if (i->position != s)
- {
- /* No properties on this first interval -- return if
- it covers the entire region. */
- if (! interval_has_some_properties (properties, i))
- {
- int got = (LENGTH (i) - (s - i->position));
- if (got >= len)
- return Qnil;
- len -= got;
- i = next_interval (i);
- }
- /* Split away the beginning of this interval; what we don't
- want to modify. */
- else
- {
- unchanged = i;
- i = split_interval_right (unchanged, s - unchanged->position);
- copy_properties (unchanged, i);
- }
- }
-
- if (BUFFERP (object))
- modify_region (XBUFFER (object), XINT (start), XINT (end));
-
- /* We are at the beginning of an interval, with len to scan */
- for (;;)
- {
- if (i == 0)
- abort ();
-
- if (LENGTH (i) >= len)
- {
- if (! interval_has_some_properties (properties, i))
- return modified ? Qt : Qnil;
-
- if (LENGTH (i) == len)
- {
- remove_properties (properties, i, object);
- if (BUFFERP (object))
- signal_after_change (XINT (start), XINT (end) - XINT (start),
- XINT (end) - XINT (start));
- return Qt;
- }
-
- /* i has the properties, and goes past the change limit */
- unchanged = i;
- i = split_interval_left (i, len);
- copy_properties (unchanged, i);
- remove_properties (properties, i, object);
- if (BUFFERP (object))
- signal_after_change (XINT (start), XINT (end) - XINT (start),
- XINT (end) - XINT (start));
- return Qt;
- }
-
- len -= LENGTH (i);
- modified += remove_properties (properties, i, object);
- i = next_interval (i);
- }
-}
-
-DEFUN ("text-property-any", Ftext_property_any,
- Stext_property_any, 4, 5, 0,
- "Check text from START to END for property PROPERTY equalling VALUE.\n\
-If so, return the position of the first character whose property PROPERTY\n\
-is `eq' to VALUE. Otherwise return nil.\n\
-The optional fifth argument, OBJECT, is the string or buffer\n\
-containing the text.")
- (start, end, property, value, object)
- Lisp_Object start, end, property, value, object;
-{
- register INTERVAL i;
- register int e, pos;
-
- if (NILP (object))
- XSETBUFFER (object, current_buffer);
- i = validate_interval_range (object, &start, &end, soft);
- if (NULL_INTERVAL_P (i))
- return (!NILP (value) || EQ (start, end) ? Qnil : start);
- e = XINT (end);
-
- while (! NULL_INTERVAL_P (i))
- {
- if (i->position >= e)
- break;
- if (EQ (textget (i->plist, property), value))
- {
- pos = i->position;
- if (pos < XINT (start))
- pos = XINT (start);
- return make_number (pos - (STRINGP (object)));
- }
- i = next_interval (i);
- }
- return Qnil;
-}
-
-DEFUN ("text-property-not-all", Ftext_property_not_all,
- Stext_property_not_all, 4, 5, 0,
- "Check text from START to END for property PROPERTY not equalling VALUE.\n\
-If so, return the position of the first character whose property PROPERTY\n\
-is not `eq' to VALUE. Otherwise, return nil.\n\
-The optional fifth argument, OBJECT, is the string or buffer\n\
-containing the text.")
- (start, end, property, value, object)
- Lisp_Object start, end, property, value, object;
-{
- register INTERVAL i;
- register int s, e;
-
- if (NILP (object))
- XSETBUFFER (object, current_buffer);
- i = validate_interval_range (object, &start, &end, soft);
- if (NULL_INTERVAL_P (i))
- return (NILP (value) || EQ (start, end)) ? Qnil : start;
- s = XINT (start);
- e = XINT (end);
-
- while (! NULL_INTERVAL_P (i))
- {
- if (i->position >= e)
- break;
- if (! EQ (textget (i->plist, property), value))
- {
- if (i->position > s)
- s = i->position;
- return make_number (s - (STRINGP (object)));
- }
- i = next_interval (i);
- }
- return Qnil;
-}
-
-#if 0 /* You can use set-text-properties for this. */
-
-DEFUN ("erase-text-properties", Ferase_text_properties,
- Serase_text_properties, 2, 3, 0,
- "Remove all properties from the text from START to END.\n\
-The optional third argument, OBJECT,\n\
-is the string or buffer containing the text.")
- (start, end, object)
- Lisp_Object start, end, object;
-{
- register INTERVAL i;
- register INTERVAL prev_changed = NULL_INTERVAL;
- register int s, len, modified;
-
- if (NILP (object))
- XSETBUFFER (object, current_buffer);
-
- i = validate_interval_range (object, &start, &end, soft);
- if (NULL_INTERVAL_P (i))
- return Qnil;
-
- s = XINT (start);
- len = XINT (end) - s;
-
- if (i->position != s)
- {
- register int got;
- register INTERVAL unchanged = i;
-
- /* If there are properties here, then this text will be modified. */
- if (! NILP (i->plist))
- {
- i = split_interval_right (unchanged, s - unchanged->position);
- i->plist = Qnil;
- modified++;
-
- if (LENGTH (i) > len)
- {
- i = split_interval_right (i, len);
- copy_properties (unchanged, i);
- return Qt;
- }
-
- if (LENGTH (i) == len)
- return Qt;
-
- got = LENGTH (i);
- }
- /* If the text of I is without any properties, and contains
- LEN or more characters, then we may return without changing
- anything.*/
- else if (LENGTH (i) - (s - i->position) <= len)
- return Qnil;
- /* The amount of text to change extends past I, so just note
- how much we've gotten. */
- else
- got = LENGTH (i) - (s - i->position);
-
- len -= got;
- prev_changed = i;
- i = next_interval (i);
- }
-
- /* We are starting at the beginning of an interval, I. */
- while (len > 0)
- {
- if (LENGTH (i) >= len)
- {
- /* If I has no properties, simply merge it if possible. */
- if (NILP (i->plist))
- {
- if (! NULL_INTERVAL_P (prev_changed))
- merge_interval_left (i);
-
- return modified ? Qt : Qnil;
- }
-
- if (LENGTH (i) > len)
- i = split_interval_left (i, len);
- if (! NULL_INTERVAL_P (prev_changed))
- merge_interval_left (i);
- else
- i->plist = Qnil;
-
- return Qt;
- }
-
- /* Here if we still need to erase past the end of I */
- len -= LENGTH (i);
- if (NULL_INTERVAL_P (prev_changed))
- {
- modified += erase_properties (i);
- prev_changed = i;
- }
- else
- {
- modified += ! NILP (i->plist);
- /* Merging I will give it the properties of PREV_CHANGED. */
- prev_changed = i = merge_interval_left (i);
- }
-
- i = next_interval (i);
- }
-
- return modified ? Qt : Qnil;
-}
-#endif /* 0 */
-
-/* I don't think this is the right interface to export; how often do you
- want to do something like this, other than when you're copying objects
- around?
-
- I think it would be better to have a pair of functions, one which
- returns the text properties of a region as a list of ranges and
- plists, and another which applies such a list to another object. */
-
-/* Add properties from SRC to SRC of SRC, starting at POS in DEST.
- SRC and DEST may each refer to strings or buffers.
- Optional sixth argument PROP causes only that property to be copied.
- Properties are copied to DEST as if by `add-text-properties'.
- Return t if any property value actually changed, nil otherwise. */
-
-/* Note this can GC when DEST is a buffer. */
-
-Lisp_Object
-copy_text_properties (start, end, src, pos, dest, prop)
- Lisp_Object start, end, src, pos, dest, prop;
-{
- INTERVAL i;
- Lisp_Object res;
- Lisp_Object stuff;
- Lisp_Object plist;
- int s, e, e2, p, len, modified = 0;
- struct gcpro gcpro1, gcpro2;
-
- i = validate_interval_range (src, &start, &end, soft);
- if (NULL_INTERVAL_P (i))
- return Qnil;
-
- CHECK_NUMBER_COERCE_MARKER (pos, 0);
- {
- Lisp_Object dest_start, dest_end;
-
- dest_start = pos;
- XSETFASTINT (dest_end, XINT (dest_start) + (XINT (end) - XINT (start)));
- /* Apply this to a copy of pos; it will try to increment its arguments,
- which we don't want. */
- validate_interval_range (dest, &dest_start, &dest_end, soft);
- }
-
- s = XINT (start);
- e = XINT (end);
- p = XINT (pos);
-
- stuff = Qnil;
-
- while (s < e)
- {
- e2 = i->position + LENGTH (i);
- if (e2 > e)
- e2 = e;
- len = e2 - s;
-
- plist = i->plist;
- if (! NILP (prop))
- while (! NILP (plist))
- {
- if (EQ (Fcar (plist), prop))
- {
- plist = Fcons (prop, Fcons (Fcar (Fcdr (plist)), Qnil));
- break;
- }
- plist = Fcdr (Fcdr (plist));
- }
- if (! NILP (plist))
- {
- /* Must defer modifications to the interval tree in case src
- and dest refer to the same string or buffer. */
- stuff = Fcons (Fcons (make_number (p),
- Fcons (make_number (p + len),
- Fcons (plist, Qnil))),
- stuff);
- }
-
- i = next_interval (i);
- if (NULL_INTERVAL_P (i))
- break;
-
- p += len;
- s = i->position;
- }
-
- GCPRO2 (stuff, dest);
-
- while (! NILP (stuff))
- {
- res = Fcar (stuff);
- res = Fadd_text_properties (Fcar (res), Fcar (Fcdr (res)),
- Fcar (Fcdr (Fcdr (res))), dest);
- if (! NILP (res))
- modified++;
- stuff = Fcdr (stuff);
- }
-
- UNGCPRO;
-
- return modified ? Qt : Qnil;
-}
-
-/* Call the modification hook functions in LIST, each with START and END. */
-
-static void
-call_mod_hooks (list, start, end)
- Lisp_Object list, start, end;
-{
- struct gcpro gcpro1;
- GCPRO1 (list);
- while (!NILP (list))
- {
- call2 (Fcar (list), start, end);
- list = Fcdr (list);
- }
- UNGCPRO;
-}
-
-/* Check for read-only intervals and signal an error if we find one.
- Then check for any modification hooks in the range START up to
- (but not including) END. Create a list of all these hooks in
- lexicographic order, eliminating consecutive extra copies of the
- same hook. Then call those hooks in order, with START and END - 1
- as arguments. */
-
-void
-verify_interval_modification (buf, start, end)
- struct buffer *buf;
- int start, end;
-{
- register INTERVAL intervals = BUF_INTERVALS (buf);
- register INTERVAL i, prev;
- Lisp_Object hooks;
- register Lisp_Object prev_mod_hooks;
- Lisp_Object mod_hooks;
- struct gcpro gcpro1;
-
- hooks = Qnil;
- prev_mod_hooks = Qnil;
- mod_hooks = Qnil;
-
- interval_insert_behind_hooks = Qnil;
- interval_insert_in_front_hooks = Qnil;
-
- if (NULL_INTERVAL_P (intervals))
- return;
-
- if (start > end)
- {
- int temp = start;
- start = end;
- end = temp;
- }
-
- /* For an insert operation, check the two chars around the position. */
- if (start == end)
- {
- INTERVAL prev;
- Lisp_Object before, after;
-
- /* Set I to the interval containing the char after START,
- and PREV to the interval containing the char before START.
- Either one may be null. They may be equal. */
- i = find_interval (intervals, start);
-
- if (start == BUF_BEGV (buf))
- prev = 0;
- else if (i->position == start)
- prev = previous_interval (i);
- else if (i->position < start)
- prev = i;
- if (start == BUF_ZV (buf))
- i = 0;
-
- /* If Vinhibit_read_only is set and is not a list, we can
- skip the read_only checks. */
- if (NILP (Vinhibit_read_only) || CONSP (Vinhibit_read_only))
- {
- /* If I and PREV differ we need to check for the read-only
- property together with its stickiness. If either I or
- PREV are 0, this check is all we need.
- We have to take special care, since read-only may be
- indirectly defined via the category property. */
- if (i != prev)
- {
- if (! NULL_INTERVAL_P (i))
- {
- after = textget (i->plist, Qread_only);
-
- /* If interval I is read-only and read-only is
- front-sticky, inhibit insertion.
- Check for read-only as well as category. */
- if (! NILP (after)
- && NILP (Fmemq (after, Vinhibit_read_only)))
- {
- Lisp_Object tem;
-
- tem = textget (i->plist, Qfront_sticky);
- if (TMEM (Qread_only, tem)
- || (NILP (Fplist_get (i->plist, Qread_only))
- && TMEM (Qcategory, tem)))
- error ("Attempt to insert within read-only text");
- }
- }
-
- if (! NULL_INTERVAL_P (prev))
- {
- before = textget (prev->plist, Qread_only);
-
- /* If interval PREV is read-only and read-only isn't
- rear-nonsticky, inhibit insertion.
- Check for read-only as well as category. */
- if (! NILP (before)
- && NILP (Fmemq (before, Vinhibit_read_only)))
- {
- Lisp_Object tem;
-
- tem = textget (prev->plist, Qrear_nonsticky);
- if (! TMEM (Qread_only, tem)
- && (! NILP (Fplist_get (prev->plist,Qread_only))
- || ! TMEM (Qcategory, tem)))
- error ("Attempt to insert within read-only text");
- }
- }
- }
- else if (! NULL_INTERVAL_P (i))
- {
- after = textget (i->plist, Qread_only);
-
- /* If interval I is read-only and read-only is
- front-sticky, inhibit insertion.
- Check for read-only as well as category. */
- if (! NILP (after) && NILP (Fmemq (after, Vinhibit_read_only)))
- {
- Lisp_Object tem;
-
- tem = textget (i->plist, Qfront_sticky);
- if (TMEM (Qread_only, tem)
- || (NILP (Fplist_get (i->plist, Qread_only))
- && TMEM (Qcategory, tem)))
- error ("Attempt to insert within read-only text");
-
- tem = textget (prev->plist, Qrear_nonsticky);
- if (! TMEM (Qread_only, tem)
- && (! NILP (Fplist_get (prev->plist, Qread_only))
- || ! TMEM (Qcategory, tem)))
- error ("Attempt to insert within read-only text");
- }
- }
- }
-
- /* Run both insert hooks (just once if they're the same). */
- if (!NULL_INTERVAL_P (prev))
- interval_insert_behind_hooks
- = textget (prev->plist, Qinsert_behind_hooks);
- if (!NULL_INTERVAL_P (i))
- interval_insert_in_front_hooks
- = textget (i->plist, Qinsert_in_front_hooks);
- }
- else
- {
- /* Loop over intervals on or next to START...END,
- collecting their hooks. */
-
- i = find_interval (intervals, start);
- do
- {
- if (! INTERVAL_WRITABLE_P (i))
- error ("Attempt to modify read-only text");
-
- mod_hooks = textget (i->plist, Qmodification_hooks);
- if (! NILP (mod_hooks) && ! EQ (mod_hooks, prev_mod_hooks))
- {
- hooks = Fcons (mod_hooks, hooks);
- prev_mod_hooks = mod_hooks;
- }
-
- i = next_interval (i);
- }
- /* Keep going thru the interval containing the char before END. */
- while (! NULL_INTERVAL_P (i) && i->position < end);
-
- GCPRO1 (hooks);
- hooks = Fnreverse (hooks);
- while (! EQ (hooks, Qnil))
- {
- call_mod_hooks (Fcar (hooks), make_number (start),
- make_number (end));
- hooks = Fcdr (hooks);
- }
- UNGCPRO;
- }
-}
-
-/* Run the interval hooks for an insertion.
- verify_interval_modification chose which hooks to run;
- this function is called after the insertion happens
- so it can indicate the range of inserted text. */
-
-void
-report_interval_modification (start, end)
- Lisp_Object start, end;
-{
- if (! NILP (interval_insert_behind_hooks))
- call_mod_hooks (interval_insert_behind_hooks,
- make_number (start), make_number (end));
- if (! NILP (interval_insert_in_front_hooks)
- && ! EQ (interval_insert_in_front_hooks,
- interval_insert_behind_hooks))
- call_mod_hooks (interval_insert_in_front_hooks,
- make_number (start), make_number (end));
-}
-
-void
-syms_of_textprop ()
-{
- DEFVAR_LISP ("default-text-properties", &Vdefault_text_properties,
- "Property-list used as default values.\n\
-The value of a property in this list is seen as the value for every\n\
-character that does not have its own value for that property.");
- Vdefault_text_properties = Qnil;
-
- DEFVAR_LISP ("inhibit-point-motion-hooks", &Vinhibit_point_motion_hooks,
- "If non-nil, don't run `point-left' and `point-entered' text properties.\n\
-This also inhibits the use of the `intangible' text property.");
- Vinhibit_point_motion_hooks = Qnil;
-
- staticpro (&interval_insert_behind_hooks);
- staticpro (&interval_insert_in_front_hooks);
- interval_insert_behind_hooks = Qnil;
- interval_insert_in_front_hooks = Qnil;
-
-
- /* Common attributes one might give text */
-
- staticpro (&Qforeground);
- Qforeground = intern ("foreground");
- staticpro (&Qbackground);
- Qbackground = intern ("background");
- staticpro (&Qfont);
- Qfont = intern ("font");
- staticpro (&Qstipple);
- Qstipple = intern ("stipple");
- staticpro (&Qunderline);
- Qunderline = intern ("underline");
- staticpro (&Qread_only);
- Qread_only = intern ("read-only");
- staticpro (&Qinvisible);
- Qinvisible = intern ("invisible");
- staticpro (&Qintangible);
- Qintangible = intern ("intangible");
- staticpro (&Qcategory);
- Qcategory = intern ("category");
- staticpro (&Qlocal_map);
- Qlocal_map = intern ("local-map");
- staticpro (&Qfront_sticky);
- Qfront_sticky = intern ("front-sticky");
- staticpro (&Qrear_nonsticky);
- Qrear_nonsticky = intern ("rear-nonsticky");
-
- /* Properties that text might use to specify certain actions */
-
- staticpro (&Qmouse_left);
- Qmouse_left = intern ("mouse-left");
- staticpro (&Qmouse_entered);
- Qmouse_entered = intern ("mouse-entered");
- staticpro (&Qpoint_left);
- Qpoint_left = intern ("point-left");
- staticpro (&Qpoint_entered);
- Qpoint_entered = intern ("point-entered");
-
- defsubr (&Stext_properties_at);
- defsubr (&Sget_text_property);
- defsubr (&Sget_char_property);
- defsubr (&Snext_char_property_change);
- defsubr (&Sprevious_char_property_change);
- defsubr (&Snext_property_change);
- defsubr (&Snext_single_property_change);
- defsubr (&Sprevious_property_change);
- defsubr (&Sprevious_single_property_change);
- defsubr (&Sadd_text_properties);
- defsubr (&Sput_text_property);
- defsubr (&Sset_text_properties);
- defsubr (&Sremove_text_properties);
- defsubr (&Stext_property_any);
- defsubr (&Stext_property_not_all);
-/* defsubr (&Serase_text_properties); */
-/* defsubr (&Scopy_text_properties); */
-}
-
-#else
-
-lose -- this shouldn't be compiled if USE_TEXT_PROPERTIES isn't defined
-
-#endif /* USE_TEXT_PROPERTIES */
diff --git a/src/tparam.c b/src/tparam.c
deleted file mode 100644
index ae12e72ac7b..00000000000
--- a/src/tparam.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/* Merge parameters into a termcap entry string.
- Copyright (C) 1985, 87, 93, 95 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 2, 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, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Emacs config.h may rename various library functions such as malloc. */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef emacs
-#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
-#define bcopy(s, d, n) memcpy ((d), (s), (n))
-#endif
-
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#include <string.h>
-#else
-char *malloc ();
-char *realloc ();
-#endif
-
-#endif /* not emacs */
-
-#ifndef NULL
-#define NULL (char *) 0
-#endif
-
-#ifndef emacs
-static void
-memory_out ()
-{
- write (2, "virtual memory exhausted\n", 25);
- exit (1);
-}
-
-static char *
-xmalloc (size)
- unsigned size;
-{
- register char *tem = malloc (size);
-
- if (!tem)
- memory_out ();
- return tem;
-}
-
-static char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
-{
- register char *tem = realloc (ptr, size);
-
- if (!tem)
- memory_out ();
- return tem;
-}
-#endif /* not emacs */
-
-/* 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;
-{
- int arg[4];
-
- arg[0] = arg0;
- arg[1] = arg1;
- arg[2] = arg2;
- arg[3] = arg3;
- return tparam1 (string, outstring, len, NULL, NULL, arg);
-}
-
-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 NULL;
- 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 *old_argp = 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)
- {
- outlen = len + 40;
- new = (char *) xmalloc (outlen);
- outend += 40;
- bcopy (outstring, new, op - outstring);
- }
- else
- {
- outend += outlen;
- outlen *= 2;
- new = (char *) xrealloc (outstring, outlen);
- }
- op += new - outstring;
- outend += new - outstring;
- outstring = new;
- }
- c = *p++;
- if (!c)
- 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 == old_argp)
- doup++, outend -= strlen (up);
- else
- doleft++, outend -= strlen (left);
- }
- }
- *op++ = tem ? 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;
- old_argp++;
- 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
deleted file mode 100644
index 57615ab4527..00000000000
--- a/src/uaf.h
+++ /dev/null
@@ -1,296 +0,0 @@
-/* GNU Emacs VMS UAF 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/*
- * User Authorization File record formats
- */
-#ifndef UAF$K_LENGTH
-
-struct UAF {
-#define UAF$C_USER_ID 1
-#define UAF$C_VERSION1 1
-#define UAF$C_KEYED_PART 52
-#define UAF$C_AD_II 0
-#define UAF$C_PURDY 1
-#define UAF$C_PURDY_V 2
-#define UAF$K_FIXED 644
-#define UAF$C_FIXED 644
-#define UAF$K_LENGTH 1412
-#define UAF$C_LENGTH 1412
-#define UAF$S_UAFDEF 1412
-#define UAF$B_RTYPE 0
- char uaf$b_rtype;
-#define UAF$B_VERSION 1
- char uaf$b_version;
-#define UAF$W_USRDATOFF 2
- short uaf$w_usrdatoff;
-#define UAF$S_USERNAME 32
-#define UAF$T_USERNAME 4
-#define UAF$T_USERNAME_TAG 35
- char uaf$t_username[UAF$S_USERNAME];
-#define UAF$L_UIC 36
-#define UAF$W_MEM 36
-#define UAF$W_GRP 38
- union {
- long uaf_l_uic;
-#define uaf$l_uic uaf_u_uic.uaf_l_uic
- struct {
- short uaf_w_mem;
- short uaf_w_grp;
-#define uaf$w_mem uaf_u_uic.uaf_u_mem_grp.uaf_w_mem
-#define uaf$w_grp uaf_u_uic.uaf_u_mem_grp.uaf_w_grp
- } uaf_u_mem_grp;
- } uaf_u_uic;
-#define UAF$L_SUB_ID 40
- long uaf$l_sub_id;
-#define UAF$S_PARENT_ID 8
-#define UAF$Q_PARENT_ID 44
- char uaf$q_parent_id[UAF$S_PARENT_ID];
-#define UAF$S_ACCOUNT 32
-#define UAF$T_ACCOUNT 52
- char uaf$t_account[UAF$S_ACCOUNT];
-#define UAF$S_OWNER 32
-#define UAF$T_OWNER 84
- char uaf$t_owner[UAF$S_OWNER];
-#define UAF$S_DEFDEV 32
-#define UAF$T_DEFDEV 116
- char uaf$t_defdev[UAF$S_DEFDEV];
-#define UAF$S_DEFDIR 64
-#define UAF$T_DEFDIR 148
- char uaf$t_defdir[UAF$S_DEFDIR];
-#define UAF$S_LGICMD 64
-#define UAF$T_LGICMD 212
- char uaf$t_lgicmd[UAF$S_LGICMD];
-#define UAF$S_DEFCLI 32
-#define UAF$T_DEFCLI 276
- char uaf$t_defcli[UAF$S_DEFCLI];
-#define UAF$S_CLITABLES 32
-#define UAF$T_CLITABLES 308
- char uaf$t_clitables[UAF$S_CLITABLES];
-#define UAF$S_PWD 8
-#define UAF$Q_PWD 340
-#define UAF$L_PWD 340
- char uaf$q_pwd[UAF$S_PWD];
-#define uaf$l_pwd uaf$q_pwd[0]
-#define UAF$S_PWD2 8
-#define UAF$Q_PWD2 348
- char uaf$q_pwd2[UAF$S_PWD2];
-#define UAF$W_LOGFAILS 356
- short uaf$w_logfails;
-#define UAF$W_SALT 358
- short uaf$w_salt;
-#define UAF$B_ENCRYPT 360
- char uaf$b_encrypt;
-#define UAF$B_ENCRYPT2 361
- char uaf$b_encrypt2;
-#define UAF$B_PWD_LENGTH 362
- char uaf$b_pwd_length;
-#define UAF$S_EXPIRATION 8
-#define UAF$Q_EXPIRATION 364
- char uaf$q_expiration[UAF$S_EXPIRATION];
-#define UAF$S_PWD_LIFETIME 8
-#define UAF$Q_PWD_LIFETIME 372
- char uaf$q_pwd_lifetime[UAF$S_PWD_LIFETIME];
-#define UAF$S_PWD_DATE 8
-#define UAF$Q_PWD_DATE 380
- char uaf$q_pwd_date[UAF$S_PWD_DATE];
-#define UAF$S_PWD2_DATE 8
-#define UAF$Q_PWD2_DATE 388
- char uaf$q_pwd2_date[UAF$S_PWD2_DATE];
-#define UAF$S_LASTLOGIN_I 8
-#define UAF$Q_LASTLOGIN_I 396
- char uaf$q_lastlogin_i[UAF$S_LASTLOGIN_I];
-#define UAF$S_LASTLOGIN_N 8
-#define UAF$Q_LASTLOGIN_N 404
- char uaf$q_lastlogin_n[UAF$S_LASTLOGIN_N];
-#define UAF$S_PRIV 8
-#define UAF$Q_PRIV 412
- char uaf$q_priv[UAF$S_PRIV];
-#define UAF$S_DEF_PRIV 8
-#define UAF$Q_DEF_PRIV 420
- char uaf$q_def_priv[UAF$S_DEF_PRIV];
-#define UAF$S_MIN_CLASS 20
-#define UAF$R_MIN_CLASS 428
- char uaf$r_min_class[UAF$S_MIN_CLASS];
-#define UAF$S_MAX_CLASS 20
-#define UAF$R_MAX_CLASS 448
- char uaf$r_max_class[UAF$S_MAX_CLASS];
-#define UAF$L_FLAGS 468
-#define UAF$V_DISCTLY 0
-#define UAF$V_DEFCLI 1
-#define UAF$V_LOCKPWD 2
-#define UAF$V_CAPTIVE 3
-#define UAF$V_DISACNT 4
-#define UAF$V_DISWELCOM 5
-#define UAF$V_DISMAIL 6
-#define UAF$V_NOMAIL 7
-#define UAF$V_GENPWD 8
-#define UAF$V_PWD_EXPIRED 9
-#define UAF$V_PWD2_EXPIRED 10
-#define UAF$V_AUDIT 11
-#define UAF$V_DISREPORT 12
-#define UAF$V_DISRECONNECT 13
- union {
- unsigned long uaf_l_flags;
-#define uaf$l_flags uaf_u_flags.uaf_l_flags
- struct {
- unsigned long
- uaf_v_disctly : 1,
-#define uaf$v_disctly uaf_u_flags.uaf_v_flags.uaf_v_disctly
- uaf_v_defcli : 1,
-#define uaf$v_defcli uaf_u_flags.uaf_v_flags.uaf_v_discli
- uaf_v_lockpwd : 1,
-#define uaf$v_lockpwd uaf_u_flags.uaf_v_flags.uaf_v_lockpwd
- uaf_v_captive : 1,
-#define uaf$v_captive uaf_u_flags.uaf_v_flags.uaf_v_captive
- uaf_v_disacnt : 1,
-#define uaf$v_disacnt uaf_u_flags.uaf_v_flags.uaf_v_disacnt
- uaf_v_diswelcom : 1,
-#define uaf$v_diswelcom uaf_u_flags.uaf_v_flags.uaf_v_diswelcom
- uaf_v_dismail : 1,
-#define uaf$v_dismail uaf_u_flags.uaf_v_flags.uaf_v_dismail
- uaf_v_nomail : 1,
-#define uaf$v_nomail uaf_u_flags.uaf_v_flags.uaf_v_nomail
- uaf_v_genpwd : 1,
-#define uaf$v_genpwd uaf_u_flags.uaf_v_flags.uaf_v_genpwd
- uaf_v_pwd_expired : 1,
-#define uaf$v_pwd_expired uaf_u_flags.uaf_v_flags.uaf_v_pwd_expired
- uaf_v_pwd2_expired : 1,
-#define uaf$v_pwd2_expired uaf_u_flags.uaf_v_flags.uaf_v_pwd2_expired
- uaf_v_audit : 1,
-#define uaf$v_audit uaf_u_flags.uaf_v_flags.uaf_v_audit
- uaf_v_disreport : 1,
-#define uaf$v_disreport uaf_u_flags.uaf_v_flags.uaf_v_disreport
- uaf_v_disreconnect : 1;
-#define uaf$v_disreconnect uaf_u_flags.uaf_v_flags.uaf_v_disreconnect
- } uaf_v_flags;
- } uaf_u_flags;
-#define UAF$S_NETWORK_ACCESS_P 3
-#define UAF$B_NETWORK_ACCESS_P 472
- char uaf$b_network_access_p[UAF$S_NETWORK_ACCESS_P];
-#define UAF$S_NETWORK_ACCESS_S 3
-#define UAF$B_NETWORK_ACCESS_S 475
- char uaf$b_network_access_s[UAF$S_NETWORK_ACCESS_S];
-#define UAF$S_BATCH_ACCESS_P 3
-#define UAF$B_BATCH_ACCESS_P 478
- char uaf$b_batch_access_p[UAF$S_BATCH_ACCESS_P];
-#define UAF$S_BATCH_ACCESS_S 3
-#define UAF$B_BATCH_ACCESS_S 481
- char uaf$b_batch_access_s[UAF$S_BATCH_ACCESS_S];
-#define UAF$S_LOCAL_ACCESS_P 3
-#define UAF$B_LOCAL_ACCESS_P 484
- char uaf$b_local_access_p[UAF$S_LOCAL_ACCESS_P];
-#define UAF$S_LOCAL_ACCESS_S 3
-#define UAF$B_LOCAL_ACCESS_S 487
- char uaf$b_local_access_s[UAF$S_LOCAL_ACCESS_S];
-#define UAF$S_DIALUP_ACCESS_P 3
-#define UAF$B_DIALUP_ACCESS_P 490
- char uaf$b_dialup_access_p[UAF$S_DIALUP_ACCESS_P];
-#define UAF$S_DIALUP_ACCESS_S 3
-#define UAF$B_DIALUP_ACCESS_S 493
- char uaf$b_dialup_access_s[UAF$S_DIALUP_ACCESS_S];
-#define UAF$S_REMOTE_ACCESS_P 3
-#define UAF$B_REMOTE_ACCESS_P 496
- char uaf$b_remote_access_p[UAF$S_REMOTE_ACCESS_P];
-#define UAF$S_REMOTE_ACCESS_S 3
-#define UAF$B_REMOTE_ACCESS_S 499
- char uaf$b_remote_access_s[UAF$S_REMOTE_ACCESS_S];
-#define UAF$B_PRIMEDAYS 514
-#define UAF$V_MONDAY 0
-#define UAF$V_TUESDAY 1
-#define UAF$V_WEDNESDAY 2
-#define UAF$V_THURSDAY 3
-#define UAF$V_FRIDAY 4
-#define UAF$V_SATURDAY 5
-#define UAF$V_SUNDAY 6
- union {
- unsigned char uaf_b_primedays;
-#define uaf$b_primedays uaf_u_primedays.uaf_b_primedays
- unsigned char
- uaf_v_monday : 1,
-#define uaf$v_monday uaf_u_primedays.uaf_v_monday
- uaf_v_tuesday : 1,
-#define uaf$v_tuesday uaf_u_primedays.uaf_v_tuesday
- uaf_v_wednesday : 1,
-#define uaf$v_wednesday uaf_u_primedays.uaf_v_wednesday
- uaf_v_thursday : 1,
-#define uaf$v_thursday uaf_u_primedays.uaf_v_thursday
- uaf_v_friday : 1,
-#define uaf$v_friday uaf_u_primedays.uaf_v_friday
- uaf_v_saturday : 1,
-#define uaf$v_saturday uaf_u_primedays.uaf_v_saturday
- uav_v_sunday : 1;
-#define uaf$v_sunday uaf_u_primedays.uaf_v_sunday
- } uaf_u_primedays;
-#define UAF$B_PRI 516
- char uaf$b_pri;
-#define UAF$B_QUEPRI 517
- char uaf$b_quepri;
-#define UAF$W_MAXJOBS 518
- short uaf$w_maxjobs;
-#define UAF$W_MAXACCTJOBS 520
- short uaf$w_maxacctjobs;
-#define UAF$W_MAXDETACH 522
- short uaf$w_maxdetach;
-#define UAF$W_PRCCNT 524
- short uaf$w_prccnt;
-#define UAF$W_BIOLM 526
- short uaf$w_biolm;
-#define UAF$W_DIOLM 528
- short uaf$w_diolm;
-#define UAF$W_TQCNT 530
- short uaf$w_twcnt;
-#define UAF$W_ASTLM 532
- short uaf$w_astlm;
-#define UAF$W_ENQLM 534
- short uaf$w_enqlm;
-#define UAF$W_FILLM 536
- short uaf$w_fillm;
-#define UAF$W_SHRFILLM 538
- short uaf$w_shrfillm;
-#define UAF$L_WSQUOTA 540
- long uaf$l_wsquota;
-#define UAF$L_DFWSCNT 544
- long uaf$l_dfwscnt;
-#define UAF$L_WSEXTENT 548
- long uaf$l_wsextent;
-#define UAF$L_PGFLQUOTA 552
- long uaf$l_pgflquota;
-#define UAF$L_CPUTIM 556
- long uaf$l_cputim;
-#define UAF$L_BYTLM 560
- long uaf$l_bytlm;
-#define UAF$L_PBYTLM 564
- long uaf$l_pbytlm;
-#define UAF$L_JTQUOTA 568
- long uaf$l_jtquota;
-#define UAF$W_PROXY_LIM 572
- short uaf$w_proxy_lim;
-#define UAF$W_PROXIES 574
- short uaf$w_proxies;
-#define UAF$W_ACCOUNT_LIM 576
- short uaf$w_account_lim;
-#define UAF$W_ACCOUNTS 578
- short uaf$w_accounts;
- char uaf$b_fixed[UAF$C_FIXED - UAF$W_ACCOUNTS + 2];
- char uaf$b_usrdata[UAF$C_LENGTH - UAF$C_FIXED];
-};
-
-#endif /* not UAF$K_LENGTH */
diff --git a/src/undo.c b/src/undo.c
deleted file mode 100644
index 9a139456927..00000000000
--- a/src/undo.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/* undo handling for GNU Emacs.
- Copyright (C) 1990, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include "lisp.h"
-#include "buffer.h"
-#include "commands.h"
-
-/* Last buffer for which undo information was recorded. */
-Lisp_Object last_undo_buffer;
-
-Lisp_Object Qinhibit_read_only;
-
-/* The first time a command records something for undo.
- it also allocates the undo-boundary object
- which will be added to the list at the end of the command.
- This ensures we can't run out of space while trying to make
- an undo-boundary. */
-Lisp_Object pending_boundary;
-
-/* Record an insertion that just happened or is about to happen,
- for LENGTH characters at position BEG.
- (It is possible to record an insertion before or after the fact
- because we don't need to record the contents.) */
-
-record_insert (beg, length)
- int beg, length;
-{
- Lisp_Object lbeg, lend;
-
- if (EQ (current_buffer->undo_list, Qt))
- return;
-
- /* Allocate a cons cell to be the undo boundary after this command. */
- if (NILP (pending_boundary))
- pending_boundary = Fcons (Qnil, Qnil);
-
- if (current_buffer != XBUFFER (last_undo_buffer))
- Fundo_boundary ();
- XSETBUFFER (last_undo_buffer, current_buffer);
-
- if (MODIFF <= SAVE_MODIFF)
- record_first_change ();
-
- /* If this is following another insertion and consecutive with it
- in the buffer, combine the two. */
- if (CONSP (current_buffer->undo_list))
- {
- Lisp_Object elt;
- elt = XCONS (current_buffer->undo_list)->car;
- if (CONSP (elt)
- && INTEGERP (XCONS (elt)->car)
- && INTEGERP (XCONS (elt)->cdr)
- && XINT (XCONS (elt)->cdr) == beg)
- {
- XSETINT (XCONS (elt)->cdr, beg + length);
- return;
- }
- }
-
- XSETFASTINT (lbeg, beg);
- XSETINT (lend, beg + length);
- current_buffer->undo_list = Fcons (Fcons (lbeg, lend),
- current_buffer->undo_list);
-}
-
-/* Record that a deletion is about to take place,
- for LENGTH characters at location BEG. */
-
-record_delete (beg, length)
- int beg, length;
-{
- Lisp_Object lbeg, lend, sbeg;
- int at_boundary;
-
- if (EQ (current_buffer->undo_list, Qt))
- return;
-
- /* Allocate a cons cell to be the undo boundary after this command. */
- if (NILP (pending_boundary))
- pending_boundary = Fcons (Qnil, Qnil);
-
- if (current_buffer != XBUFFER (last_undo_buffer))
- Fundo_boundary ();
- XSETBUFFER (last_undo_buffer, current_buffer);
-
- at_boundary = (CONSP (current_buffer->undo_list)
- && NILP (XCONS (current_buffer->undo_list)->car));
-
- if (MODIFF <= SAVE_MODIFF)
- record_first_change ();
-
- if (PT == beg + length)
- XSETINT (sbeg, -beg);
- else
- XSETFASTINT (sbeg, beg);
- XSETFASTINT (lbeg, beg);
- XSETFASTINT (lend, beg + length);
-
- /* If we are just after an undo boundary, and
- point wasn't at start of deleted range, record where it was. */
- if (at_boundary
- && last_point_position != XFASTINT (sbeg)
- && current_buffer == XBUFFER (last_point_position_buffer))
- current_buffer->undo_list
- = Fcons (make_number (last_point_position), current_buffer->undo_list);
-
- current_buffer->undo_list
- = Fcons (Fcons (Fbuffer_substring (lbeg, lend), sbeg),
- current_buffer->undo_list);
-}
-
-/* Record the fact that MARKER is about to be adjusted by ADJUSTMENT.
- This is done only when a marker points within text being deleted,
- because that's the only case where an automatic marker adjustment
- won't be inverted automatically by undoing the buffer modification. */
-
-record_marker_adjustment (marker, adjustment)
- Lisp_Object marker;
- int adjustment;
-{
- if (EQ (current_buffer->undo_list, Qt))
- return;
-
- /* Allocate a cons cell to be the undo boundary after this command. */
- if (NILP (pending_boundary))
- pending_boundary = Fcons (Qnil, Qnil);
-
- if (current_buffer != XBUFFER (last_undo_buffer))
- Fundo_boundary ();
- XSETBUFFER (last_undo_buffer, current_buffer);
-
- current_buffer->undo_list
- = Fcons (Fcons (marker, make_number (adjustment)),
- current_buffer->undo_list);
-}
-
-/* Record that a replacement is about to take place,
- for LENGTH characters at location BEG.
- The replacement does not change the number of characters. */
-
-record_change (beg, length)
- int beg, length;
-{
- record_delete (beg, length);
- record_insert (beg, length);
-}
-
-/* Record that an unmodified buffer is about to be changed.
- Record the file modification date so that when undoing this entry
- we can tell whether it is obsolete because the file was saved again. */
-
-record_first_change ()
-{
- Lisp_Object high, low;
- struct buffer *base_buffer = current_buffer;
-
- if (EQ (current_buffer->undo_list, Qt))
- return;
-
- if (current_buffer != XBUFFER (last_undo_buffer))
- Fundo_boundary ();
- XSETBUFFER (last_undo_buffer, current_buffer);
-
- if (base_buffer->base_buffer)
- base_buffer = base_buffer->base_buffer;
-
- XSETFASTINT (high, (base_buffer->modtime >> 16) & 0xffff);
- XSETFASTINT (low, base_buffer->modtime & 0xffff);
- current_buffer->undo_list = Fcons (Fcons (Qt, Fcons (high, low)), current_buffer->undo_list);
-}
-
-/* Record a change in property PROP (whose old value was VAL)
- for LENGTH characters starting at position BEG in BUFFER. */
-
-record_property_change (beg, length, prop, value, buffer)
- int beg, length;
- Lisp_Object prop, value, buffer;
-{
- Lisp_Object lbeg, lend, entry;
- struct buffer *obuf = current_buffer;
- int boundary = 0;
-
- if (EQ (XBUFFER (buffer)->undo_list, Qt))
- return;
-
- /* Allocate a cons cell to be the undo boundary after this command. */
- if (NILP (pending_boundary))
- pending_boundary = Fcons (Qnil, Qnil);
-
- if (!EQ (buffer, last_undo_buffer))
- boundary = 1;
- last_undo_buffer = buffer;
-
- /* Switch temporarily to the buffer that was changed. */
- current_buffer = XBUFFER (buffer);
-
- if (boundary)
- Fundo_boundary ();
-
- if (MODIFF <= SAVE_MODIFF)
- record_first_change ();
-
- XSETINT (lbeg, beg);
- XSETINT (lend, beg + length);
- entry = Fcons (Qnil, Fcons (prop, Fcons (value, Fcons (lbeg, lend))));
- current_buffer->undo_list = Fcons (entry, current_buffer->undo_list);
-
- current_buffer = obuf;
-}
-
-DEFUN ("undo-boundary", Fundo_boundary, Sundo_boundary, 0, 0, 0,
- "Mark a boundary between units of undo.\n\
-An undo command will stop at this point,\n\
-but another undo command will undo to the previous boundary.")
- ()
-{
- Lisp_Object tem;
- if (EQ (current_buffer->undo_list, Qt))
- return Qnil;
- tem = Fcar (current_buffer->undo_list);
- if (!NILP (tem))
- {
- /* One way or another, cons nil onto the front of the undo list. */
- if (!NILP (pending_boundary))
- {
- /* If we have preallocated the cons cell to use here,
- use that one. */
- XCONS (pending_boundary)->cdr = current_buffer->undo_list;
- current_buffer->undo_list = pending_boundary;
- pending_boundary = Qnil;
- }
- else
- current_buffer->undo_list = Fcons (Qnil, current_buffer->undo_list);
- }
- return Qnil;
-}
-
-/* At garbage collection time, make an undo list shorter at the end,
- returning the truncated list.
- MINSIZE and MAXSIZE are the limits on size allowed, as described below.
- In practice, these are the values of undo-limit and
- undo-strong-limit. */
-
-Lisp_Object
-truncate_undo_list (list, minsize, maxsize)
- Lisp_Object list;
- int minsize, maxsize;
-{
- Lisp_Object prev, next, last_boundary;
- 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.
-
- Skip, skip, skip the undo, skip, skip, skip the undo,
- Skip, skip, skip the undo, skip to the undo bound'ry.
- (Get it? "Skip to my Loo?") */
- if (CONSP (next) && NILP (XCONS (next)->car))
- {
- /* 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 (CONSP (next) && ! NILP (XCONS (next)->car))
- {
- 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 (CONSP (elt))
- {
- size_so_far += sizeof (struct Lisp_Cons);
- if (STRINGP (XCONS (elt)->car))
- size_so_far += (sizeof (struct Lisp_String) - 1
- + XSTRING (XCONS (elt)->car)->size);
- }
-
- /* Advance to next element. */
- prev = next;
- next = XCONS (next)->cdr;
- }
- if (CONSP (next))
- last_boundary = prev;
-
- while (CONSP (next))
- {
- Lisp_Object elt;
- elt = XCONS (next)->car;
-
- /* When we get to a boundary, decide whether to truncate
- either before or after it. The lower threshold, MINSIZE,
- tells us to truncate after it. If its size pushes past
- the higher threshold MAXSIZE as well, we truncate before it. */
- if (NILP (elt))
- {
- if (size_so_far > maxsize)
- break;
- last_boundary = 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);
- if (CONSP (elt))
- {
- size_so_far += sizeof (struct Lisp_Cons);
- if (STRINGP (XCONS (elt)->car))
- size_so_far += (sizeof (struct Lisp_String) - 1
- + XSTRING (XCONS (elt)->car)->size);
- }
-
- /* Advance to next element. */
- prev = next;
- next = XCONS (next)->cdr;
- }
-
- /* If we scanned the whole list, it is short enough; don't change it. */
- if (NILP (next))
- return list;
-
- /* Truncate at the boundary where we decided to truncate. */
- if (!NILP (last_boundary))
- {
- XCONS (last_boundary)->cdr = Qnil;
- return list;
- }
- else
- return Qnil;
-}
-
-DEFUN ("primitive-undo", Fprimitive_undo, Sprimitive_undo, 2, 2, 0,
- "Undo N records from the front of the list LIST.\n\
-Return what remains of the list.")
- (n, list)
- Lisp_Object n, list;
-{
- struct gcpro gcpro1, gcpro2;
- Lisp_Object next;
- int count = specpdl_ptr - specpdl;
- register int arg;
-#if 0 /* This is a good feature, but would make undo-start
- unable to do what is expected. */
- Lisp_Object tem;
-
- /* If the head of the list is a boundary, it is the boundary
- preceding this command. Get rid of it and don't count it. */
- tem = Fcar (list);
- if (NILP (tem))
- list = Fcdr (list);
-#endif
-
- CHECK_NUMBER (n, 0);
- arg = XINT (n);
- next = Qnil;
- GCPRO2 (next, list);
-
- /* Don't let read-only properties interfere with undo. */
- if (NILP (current_buffer->read_only))
- specbind (Qinhibit_read_only, Qt);
-
- while (arg > 0)
- {
- while (1)
- {
- next = Fcar (list);
- list = Fcdr (list);
- /* Exit inner loop at undo boundary. */
- if (NILP (next))
- break;
- /* Handle an integer by setting point to that value. */
- if (INTEGERP (next))
- SET_PT (clip_to_bounds (BEGV, XINT (next), ZV));
- else if (CONSP (next))
- {
- Lisp_Object car, cdr;
-
- car = Fcar (next);
- cdr = Fcdr (next);
- if (EQ (car, Qt))
- {
- /* Element (t high . low) records previous modtime. */
- Lisp_Object high, low;
- int mod_time;
- struct buffer *base_buffer = current_buffer;
-
- high = Fcar (cdr);
- low = Fcdr (cdr);
- mod_time = (XFASTINT (high) << 16) + XFASTINT (low);
-
- if (current_buffer->base_buffer)
- base_buffer = current_buffer->base_buffer;
-
- /* If this records an obsolete save
- (not matching the actual disk file)
- then don't mark unmodified. */
- if (mod_time != base_buffer->modtime)
- continue;
-#ifdef CLASH_DETECTION
- Funlock_buffer ();
-#endif /* CLASH_DETECTION */
- Fset_buffer_modified_p (Qnil);
- }
-#ifdef USE_TEXT_PROPERTIES
- else if (EQ (car, Qnil))
- {
- /* Element (nil prop val beg . end) is property change. */
- Lisp_Object beg, end, prop, val;
-
- prop = Fcar (cdr);
- cdr = Fcdr (cdr);
- val = Fcar (cdr);
- cdr = Fcdr (cdr);
- beg = Fcar (cdr);
- end = Fcdr (cdr);
-
- Fput_text_property (beg, end, prop, val, Qnil);
- }
-#endif /* USE_TEXT_PROPERTIES */
- else if (INTEGERP (car) && INTEGERP (cdr))
- {
- /* Element (BEG . END) means range was inserted. */
- Lisp_Object end;
-
- if (XINT (car) < BEGV
- || XINT (cdr) > ZV)
- error ("Changes to be undone are outside visible portion of buffer");
- /* Set point first thing, so that undoing this undo
- does not send point back to where it is now. */
- Fgoto_char (car);
- Fdelete_region (car, cdr);
- }
- else if (STRINGP (car) && INTEGERP (cdr))
- {
- /* Element (STRING . POS) means STRING was deleted. */
- Lisp_Object membuf;
- int pos = XINT (cdr);
-
- membuf = car;
- if (pos < 0)
- {
- if (-pos < BEGV || -pos > ZV)
- error ("Changes to be undone are outside visible portion of buffer");
- SET_PT (-pos);
- Finsert (1, &membuf);
- }
- else
- {
- if (pos < BEGV || pos > ZV)
- error ("Changes to be undone are outside visible portion of buffer");
- SET_PT (pos);
-
- /* Insert before markers so that if the mark is
- currently on the boundary of this deletion, it
- ends up on the other side of the now-undeleted
- text from point. Since undo doesn't even keep
- track of the mark, this isn't really necessary,
- but it may lead to better behavior in certain
- situations. */
- Finsert_before_markers (1, &membuf);
- SET_PT (pos);
- }
- }
- else if (MARKERP (car) && INTEGERP (cdr))
- {
- /* (MARKER . INTEGER) means a marker MARKER
- was adjusted by INTEGER. */
- if (XMARKER (car)->buffer)
- Fset_marker (car,
- make_number (marker_position (car) - XINT (cdr)),
- Fmarker_buffer (car));
- }
- }
- }
- arg--;
- }
-
- UNGCPRO;
- return unbind_to (count, list);
-}
-
-syms_of_undo ()
-{
- Qinhibit_read_only = intern ("inhibit-read-only");
- staticpro (&Qinhibit_read_only);
-
- pending_boundary = Qnil;
- staticpro (&pending_boundary);
-
- defsubr (&Sprimitive_undo);
- defsubr (&Sundo_boundary);
-}
diff --git a/src/unexaix.c b/src/unexaix.c
deleted file mode 100644
index 9fcdef808c8..00000000000
--- a/src/unexaix.c
+++ /dev/null
@@ -1,883 +0,0 @@
-/* Modified by Andrew.Vignaux@comp.vuw.ac.nz to get it to work :-) */
-
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
-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.
- *
- * Updated for AIX 4.1.3 by Bill_Mann @ PraxisInt.com, Feb 1996
- * As of AIX 4.1, text, data, and bss are pre-relocated by the binder in
- * such a way that the file can be mapped with code in one segment and
- * data/bss in another segment, without reading or copying the file, by
- * the AIX exec loader. Padding sections are omitted, nevertheless
- * small amounts of 'padding' still occurs between sections in the file.
- * As modified, this code handles both 3.2 and 4.1 conventions.
- *
- * 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.
-
-*/
-
-#define XCOFF
-#define COFF
-#define NO_REMAP
-
-#ifndef emacs
-#define PERROR(arg) perror (arg); return -1
-#else
-#include <config.h>
-#define PERROR(file) report_error (file, new)
-#endif
-
-#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"
-
-#ifndef makedev /* Try to detect types.h already loaded */
-#include <sys/types.h>
-#endif
-#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 */
-
-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 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 */
-
-static long text_scnptr;
-static long data_scnptr;
-#ifdef XCOFF
-#define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1))
-static long load_scnptr;
-static long orig_load_scnptr;
-static long orig_data_scnptr;
-#endif
-static ulong data_st; /* start of data area written out */
-
-#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
-#include "lisp.h"
-
-static
-report_error (file, fd)
- char *file;
- int fd;
-{
- if (fd)
- close (fd);
- report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil));
-}
-#endif /* emacs */
-
-#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);
-#ifdef emacs
- error (msg, a1, a2);
-#else
- fprintf (stderr, msg, a1, a2);
- fprintf (stderr, "\n");
-#endif
-}
-
-static int make_hdr ();
-static void mark_x ();
-static int copy_text_and_data ();
-static int copy_sym ();
-
-/* ****************************************************************
- * 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
-#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;
- }
-
- 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)
- {
- bss_start = (ADDR_CORRECT (bss_start) + pagemask);
- /* (Up) to page bdry. */
- bss_start &= ~ pagemask;
- if (bss_start > bss_end)
- {
- ERROR1 ("unexec: Specified bss_start (%u) 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 (%u) can't be greater than bss_start (%u)",
- data_start, bss_start);
- }
-
-#ifdef COFF
- /* Salvage as much info from the existing file as possible */
- 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)
- {
- if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
- {
- PERROR (a_name);
- }
- if (f_hdr.f_opthdr > 0)
- {
- if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
- {
- PERROR (a_name);
- }
- }
- 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);
- }
-
-#define CHECK_SCNHDR(ptr, name, flags) \
- if (strcmp(s->s_name, name) == 0) { \
- if (s->s_flags != flags) { \
- fprintf(stderr, "unexec: %lx flags where %x expected in %s section.\n", \
- (unsigned long)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);
- }
- }
- else
- {
- 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. */
-
- /* Indicate that the reloc information is no longer valid for ld (bind);
- we only update it enough to fake out the exec-time loader. */
- f_hdr.f_flags |= (F_RELFLG | F_EXEC);
-
-#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
- data_st = f_ohdr.data_start ? f_ohdr.data_start : (ulong) &_data;
- f_ohdr.dsize = bss_start - data_st;
- 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.data_start + f_ohdr.dsize;
- f_bhdr->s_vaddr = f_ohdr.data_start + f_ohdr.dsize;
-
- /* fix scnptr's */
- {
- ulong ptr = section[0].s_scnptr;
-
- bias = -1;
- for (scns = 0; scns < f_hdr.f_nscns; scns++)
- {
- struct scnhdr *s = &section[scns];
-
- if (s->s_flags & STYP_PAD) /* .pad sections omitted in AIX 4.1 */
- {
- /*
- * 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 - (ptr % 512);
- if (s->s_size == 512)
- s->s_size = 0;
- }
- s->s_scnptr = ptr;
- }
- else if (s->s_flags & STYP_DATA)
- s->s_scnptr = ptr;
- else if (!(s->s_flags & (STYP_TEXT | STYP_BSS)))
- {
- if (bias == -1) /* if first section after bss */
- bias = ptr - s->s_scnptr;
-
- s->s_scnptr += bias;
- ptr = s->s_scnptr;
- }
-
- ptr = ptr + s->s_size;
- }
- }
-
- /* 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)
- {
- f_hdr.f_symptr += bias;
- }
-
- text_scnptr = f_thdr->s_scnptr;
- data_scnptr = f_dhdr->s_scnptr;
- load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
-
-#ifdef ADJUST_EXEC_HEADER
- ADJUST_EXEC_HEADER
-#endif /* ADJUST_EXEC_HEADER */
-
- if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
- {
- PERROR (new_name);
- }
-
- if (f_hdr.f_opthdr > 0)
- {
- if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
- {
- PERROR (new_name);
- }
- }
-
- 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);
- }
- }
-
- return (0);
-
-#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_st;
- end = ptr + f_ohdr.dsize;
- write_segment (new, ptr, end);
-
- return 0;
-}
-
-#define UnexBlockSz (1<<12) /* read/write block size */
-write_segment (new, ptr, end)
- int new;
- register char *ptr, *end;
-{
- register int i, nwrite, ret;
- char buf[80];
- extern int errno;
- char zeros[UnexBlockSz];
-
- for (i = 0; ptr < end;)
- {
- /* distance to next block. */
- nwrite = (((int) ptr + UnexBlockSz) & -UnexBlockSz) - (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)
- {
- bzero (zeros, nwrite);
- write (new, zeros, nwrite);
- }
- else if (nwrite != ret)
- {
- sprintf (buf,
- "unexec write failure: addr 0x%lx, fileno %d, size 0x%x, wrote 0x%x, errno %d",
- (unsigned long)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[UnexBlockSz];
- int n;
-
- if (a_out < 0)
- return 0;
-
- if (orig_load_scnptr == 0L)
- return 0;
-
- if (lnnoptr && lnnoptr < orig_load_scnptr) /* if there is line number info */
- lseek (a_out, lnnoptr, 0); /* start copying from there */
- else
- lseek (a_out, orig_load_scnptr, 0); /* Position a.out to symtab. */
-
- 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 successfully building the new a.out, mark it executable
- */
-static void
-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);
-}
-
-/*
- * 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.
- *
- * I believe this is now fixed correctly. Bill Mann
- */
-
-#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 naux;
- 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;
- }
-
- lseek (new, f_hdr.f_symptr, 0);
- for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
- {
- read (new, &symentry, SYMESZ);
- if (symentry.n_sclass == C_BINCL || symentry.n_sclass == C_EINCL)
- {
- symentry.n_value += bias;
- lseek (new, -SYMESZ, 1);
- write (new, &symentry, SYMESZ);
- }
-
- for (naux = symentry.n_numaux; naux-- != 0; )
- {
- read (new, &auxentry, AUXESZ);
- nsyms++;
- if (naux != 0 /* skip csect auxentry (last entry) */
- && (symentry.n_sclass == C_EXT || symentry.n_sclass == C_HIDEXT))
- {
- auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
- lseek (new, -AUXESZ, 1);
- write (new, &auxentry, AUXESZ);
- }
- }
- }
- close (new);
-}
-
-#endif /* COFF */
-
-#ifdef XCOFF
-
-/* 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;
-{
- register int i;
- register int l;
- register LDREL *ldrel;
- LDHDR ldhdr;
- LDREL ldrel_buf [20];
- ulong t_reloc = (ulong) &_text - f_ohdr.text_start;
- ulong d_reloc = (ulong) &_data - ALIGN(f_ohdr.data_start, 2);
- int * p;
-
- 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;
- }
-
- /* move the BSS loader symbols to the DATA segment */
- if (ldrel->l_symndx == SYMNDX_BSS)
- {
- ldrel->l_symndx = SYMNDX_DATA;
-
- 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 - f_ohdr.data_start), 0);
-
- if (read (a_out, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int))
- {
- PERROR (a_name);
- }
-
- p = (int *) (ldrel->l_vaddr + d_reloc);
-
- switch (ldrel->l_symndx) {
- case SYMNDX_TEXT:
- orig_int = * p - t_reloc;
- break;
-
- case SYMNDX_DATA:
- case SYMNDX_BSS:
- orig_int = * p - d_reloc;
- break;
- }
-
- if (orig_int != * p)
- {
- lseek (new,
- data_scnptr + (ldrel->l_vaddr - f_ohdr.data_start), 0);
- if (write (new, (void *) &orig_int, sizeof (orig_int))
- != sizeof (orig_int))
- {
- PERROR (new_name);
- }
- }
- }
- }
-}
-#endif /* XCOFF */
diff --git a/src/unexalpha.c b/src/unexalpha.c
deleted file mode 100644
index 2adfd1fa57e..00000000000
--- a/src/unexalpha.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/* Unexec for DEC alpha. schoepf@sc.ZIB-Berlin.DE (Rainer Schoepf).
-
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include <sys/types.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <stdio.h>
-#include <varargs.h>
-#include <filehdr.h>
-#include <aouthdr.h>
-#include <scnhdr.h>
-#include <syms.h>
-#ifndef __linux__
-# include <reloc.h>
-# include <elf_abi.h>
-#endif
-
-static void fatal_unexec ();
-static void 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 char *strerror ();
-
-void *sbrk ();
-
-#define EEOF -1
-
-static struct scnhdr *text_section;
-static struct scnhdr *rel_dyn_section;
-static struct scnhdr *dynstr_section;
-static struct scnhdr *dynsym_section;
-static struct scnhdr *init_section;
-static struct scnhdr *finit_section;
-static struct scnhdr *rdata_section;
-static struct scnhdr *rconst_section;
-static struct scnhdr *data_section;
-static struct scnhdr *pdata_section;
-static struct scnhdr *xdata_section;
-static struct scnhdr *got_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;
-
-static struct scnhdr old_data_scnhdr;
-
-static unsigned long Brk;
-
-struct headers {
- struct filehdr fhdr;
- struct aouthdr aout;
- struct scnhdr section[_MIPS_NSCNS_MAX];
-};
-
-
-
-/* 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 long data_start, bss_start, entry_address;
-{
- int new, old;
- char * oldptr;
- struct headers ohdr, nhdr;
- struct stat stat;
- long pagesize, brk;
- long newsyms, symrel;
- int nread;
- int i;
- long vaddr, scnptr;
-#define BUFSIZE 8192
- char buffer[BUFSIZE];
-
- if ((old = open (a_name, O_RDONLY)) < 0)
- fatal_unexec ("opening %s", a_name);
-
- new = creat (new_name, 0666);
- if (new < 0) fatal_unexec ("creating %s", new_name);
-
- if ((fstat (old, &stat) == -1))
- fatal_unexec ("fstat %s", a_name);
-
- oldptr = (char *)mmap (0, stat.st_size, PROT_READ, MAP_FILE|MAP_SHARED, old, 0);
-
- if (oldptr == (char *)-1)
- fatal_unexec ("mmap %s", a_name);
-
- close (old);
-
- /* This is a copy of the a.out header of the original executable */
-
- ohdr = (*(struct headers *)oldptr);
-
- /* This is where we build the new header from the in-memory copy */
-
- nhdr = *((struct headers *)TEXT_START);
-
- /* First do some consistency checks */
-
- if (nhdr.fhdr.f_magic != ALPHAMAGIC
- && nhdr.fhdr.f_magic != ALPHAUMAGIC)
- {
- fprintf (stderr, "unexec: input file magic number is %x, not %x or %x.\n",
- nhdr.fhdr.f_magic, ALPHAMAGIC, ALPHAUMAGIC);
- exit (1);
- }
-
- if (nhdr.fhdr.f_opthdr != sizeof (nhdr.aout))
- {
- fprintf (stderr, "unexec: input a.out header is %d bytes, not %d.\n",
- nhdr.fhdr.f_opthdr, sizeof (nhdr.aout));
- exit (1);
- }
- if (nhdr.aout.magic != ZMAGIC)
- {
- fprintf (stderr, "unexec: input file a.out magic number is %o, not %o.\n",
- nhdr.aout.magic, ZMAGIC);
- exit (1);
- }
-
-
- /* Now check the existence of certain header section and grab
- their addresses. */
-
-#define CHECK_SCNHDR(ptr, name, flags) \
- ptr = NULL; \
- for (i = 0; i < nhdr.fhdr.f_nscns && !ptr; i++) \
- if (strncmp (nhdr.section[i].s_name, name, 8) == 0) \
- { \
- if (nhdr.section[i].s_flags != flags) \
- fprintf (stderr, "unexec: %x flags (%x expected) in %s section.\n", \
- nhdr.section[i].s_flags, flags, name); \
- ptr = nhdr.section + i; \
- } \
-
- CHECK_SCNHDR (text_section, _TEXT, STYP_TEXT);
- CHECK_SCNHDR (init_section, _INIT, STYP_INIT);
-#ifdef _REL_DYN
- CHECK_SCNHDR (rel_dyn_section, _REL_DYN, STYP_REL_DYN);
-#endif /* _REL_DYN */
-#ifdef _DYNSYM
- CHECK_SCNHDR (dynsym_section, _DYNSYM, STYP_DYNSYM);
-#endif /* _REL_DYN */
-#ifdef _DYNSTR
- CHECK_SCNHDR (dynstr_section, _DYNSTR, STYP_DYNSTR);
-#endif /* _REL_DYN */
-#ifdef _FINI
- CHECK_SCNHDR (finit_section, _FINI, STYP_FINI);
-#endif /* _FINI */
- CHECK_SCNHDR (rdata_section, _RDATA, STYP_RDATA);
-#ifdef _RCONST
- CHECK_SCNHDR (rconst_section, _RCONST, STYP_RCONST);
-#endif
-#ifdef _PDATA
- CHECK_SCNHDR (pdata_section, _PDATA, STYP_PDATA);
-#endif _PDATA
-#ifdef _GOT
- CHECK_SCNHDR (got_section, _GOT, STYP_GOT);
-#endif _GOT
- CHECK_SCNHDR (data_section, _DATA, STYP_DATA);
-#ifdef _XDATA
- CHECK_SCNHDR (xdata_section, _XDATA, STYP_XDATA);
-#endif /* _XDATA */
-#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);
-
-
- pagesize = getpagesize ();
- brk = (((long) (sbrk (0))) + pagesize - 1) & (-pagesize);
-
- /* Remember the current break */
-
- Brk = brk;
-
- bcopy (data_section, &old_data_scnhdr, sizeof (old_data_scnhdr));
-
- nhdr.aout.dsize = brk - DATA_START;
- nhdr.aout.bsize = 0;
- if (entry_address == 0)
- {
- extern DEFAULT_ENTRY_ADDRESS ();
- nhdr.aout.entry = (unsigned long)DEFAULT_ENTRY_ADDRESS;
- }
- else
- nhdr.aout.entry = entry_address;
-
- nhdr.aout.bss_start = nhdr.aout.data_start + nhdr.aout.dsize;
-
- if (rdata_section != NULL)
- {
- 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 + nhdr.aout.tsize;
- }
-
- data_section->s_vaddr = data_start;
- data_section->s_paddr = data_start;
- data_section->s_size = brk - data_start;
-
- if (rdata_section != NULL)
- {
- 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;
- }
-#ifdef _XDATA
- if (xdata_section != NULL)
- {
- xdata_section->s_vaddr = vaddr;
- xdata_section->s_paddr = vaddr;
- xdata_section->s_size = 0;
- xdata_section->s_scnptr = scnptr;
- }
-#endif
-#ifdef _GOT
- if (got_section != NULL)
- {
- bcopy (got_section, buffer, sizeof (struct scnhdr));
-
- got_section->s_vaddr = vaddr;
- got_section->s_paddr = vaddr;
- got_section->s_size = 0;
- got_section->s_scnptr = scnptr;
- }
-#endif /*_GOT */
- 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, (char *)TEXT_START, nhdr.aout.tsize,
- "writing text section to %s", new_name);
- WRITE (new, (char *)DATA_START, nhdr.aout.dsize,
- "writing data section to %s", new_name);
-
-#ifdef _GOT
-#define old_got_section ((struct scnhdr *)buffer)
-
- if (got_section != NULL)
- {
- SEEK (new, old_got_section->s_scnptr,
- "seeking to start of got_section in %s", new_name);
- WRITE (new, oldptr + old_got_section->s_scnptr, old_got_section->s_size,
- "writing new got_section of %s", new_name);
- SEEK (new, nhdr.aout.tsize + nhdr.aout.dsize,
- "seeking to end of data section of %s", new_name);
- }
-
-#undef old_got_section
-#endif
-
- /*
- * Construct new symbol table header
- */
-
- bcopy (oldptr + nhdr.fhdr.f_symptr, buffer, cbHDRR);
-
-#define symhdr ((pHDRR)buffer)
- newsyms = nhdr.aout.tsize + nhdr.aout.dsize;
- symrel = newsyms - nhdr.fhdr.f_symptr;
- nhdr.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;
-
- WRITE (new, buffer, cbHDRR, "writing symbol table header of %s", new_name);
-
- /*
- * Copy the symbol table and line numbers
- */
- WRITE (new, oldptr + ohdr.fhdr.f_symptr + cbHDRR,
- stat.st_size - ohdr.fhdr.f_symptr - cbHDRR,
- "writing symbol table of %s", new_name);
-
-#ifndef __linux__
- update_dynamic_symbols (oldptr, new_name, new, nhdr.aout);
-#endif
-
-#undef symhdr
-
- SEEK (new, 0, "seeking to start of header in %s", new_name);
- WRITE (new, &nhdr, sizeof (nhdr),
- "writing header of %s", new_name);
-
- close (old);
- close (new);
- mark_x (new_name);
-}
-
-
-
-
-#ifndef __linux__
-
-update_dynamic_symbols (old, new_name, new, aout)
- char *old; /* Pointer to old executable */
- char *new_name; /* Name of new executable */
- int new; /* File descriptor for new executable */
- struct aouthdr aout; /* a.out info from the file header */
-{
- typedef struct dynrel_info {
- char * addr;
- unsigned type:8;
- unsigned index:24;
- unsigned info:8;
- unsigned pad:8;
- } dr_info;
-
- int nsyms = rel_dyn_section->s_size / sizeof (struct dynrel_info);
- int i;
- dr_info * rd_base = (dr_info *) (old + rel_dyn_section->s_scnptr);
- Elf32_Sym * ds_base = (Elf32_Sym *) (old + dynsym_section->s_scnptr);
-
- for (i = 0; i < nsyms; i++) {
- register Elf32_Sym x;
-
- if (rd_base[i].index == 0)
- continue;
-
- x = ds_base[rd_base[i].index];
-
-#if 0
- fprintf (stderr, "Object inspected: %s, addr = %lx, shndx = %x",
- old + dynstr_section->s_scnptr + x.st_name, rd_base[i].addr, x.st_shndx);
-#endif
-
-
- if ((ELF32_ST_BIND (x.st_info) == STB_GLOBAL)
- && (x.st_shndx == 0)
- /* && (x.st_value == NULL) */
- ) {
- /* OK, this is probably a reference to an object in a shared
- library, so copy the old value. This is done in several steps:
- 1. reladdr is the address of the location in question relative to
- the start of the data section,
- 2. oldref is the addr is the mapped in temacs executable,
- 3. newref is the address of the location in question in the
- undumped executable,
- 4. len is the size of the object reference in bytes --
- currently only 4 (long) and 8 (quad) are supported.
- */
- register unsigned long reladdr = rd_base[i].addr - old_data_scnhdr.s_vaddr;
- char * oldref = old + old_data_scnhdr.s_scnptr + reladdr;
- unsigned long newref = aout.tsize + reladdr;
- int len;
-
-#if 0
- fprintf (stderr, "...relocated\n");
-#endif
-
- if (rd_base[i].type == R_REFLONG)
- len = 4;
- else if (rd_base[i].type == R_REFQUAD)
- len = 8;
- else
- fatal_unexec ("unrecognized relocation type in .dyn.rel section (symbol #%d)", i);
-
- SEEK (new, newref, "seeking to dynamic symbol in %s", new_name);
- WRITE (new, oldref, len, "writing old dynrel info in %s", new_name);
- }
-
-#if 0
- else
- fprintf (stderr, "...not relocated\n");
-#endif
-
- }
-
-}
-
-#endif /* !__linux__ */
-
-
-/*
- * mark_x
- *
- * After successfully building the new a.out, mark it executable
- */
-
-static void
-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, arg)
- char *s;
- char *arg;
-{
- if (errno == EEOF)
- fputs ("unexec: unexpected end of file, ", stderr);
- else
- fprintf (stderr, "unexec: %s, ", strerror (errno));
- fprintf (stderr, s, arg);
- fputs (".\n", stderr);
- exit (1);
-}
diff --git a/src/unexconvex.c b/src/unexconvex.c
deleted file mode 100644
index 3197e21a6ef..00000000000
--- a/src/unexconvex.c
+++ /dev/null
@@ -1,602 +0,0 @@
-/* Modified version of unexec for convex machines.
- 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.
-
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* modified 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 cheesy 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 successfully 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
deleted file mode 100644
index f7ff9ca6b02..00000000000
--- a/src/unexec.c
+++ /dev/null
@@ -1,1238 +0,0 @@
-/* Copyright (C) 1985,86,87,88,92,93,94 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- * 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
- *
- */
-
-/* Modified to support SysVr3 shared libraries by James Van Artsdalen
- * of Dell Computer Corporation. james@bigtex.cactus.org.
- */
-
-/* There are several compilation parameters affecting unexec:
-
-* COFF
-
-Define this if your system uses COFF for executables.
-
-* COFF_ENCAPSULATE
-
-Define this if you are using the GNU coff encapsulated a.out format.
-This is closer to a.out than COFF. You should *not* define COFF if
-you define COFF_ENCAPSULATE
-
-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.
-
-* 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.
-
-*/
-
-#ifndef emacs
-#define PERROR(arg) perror (arg); return -1
-#else
-#define IN_UNEXEC
-#include <config.h>
-#define PERROR(file) report_error (file, new)
-#endif
-
-#ifndef CANNOT_DUMP /* all rest of file! */
-
-#ifdef COFF_ENCAPSULATE
-int need_coff_header = 1;
-#include <coff-encap/a.out.encap.h> /* The location might be a poor assumption */
-#else
-#ifdef MSDOS
-#if __DJGPP__ > 1
-#include <fcntl.h> /* for O_RDONLY, O_RDWR */
-#include <crt0.h> /* for _crt0_startup_flags and its bits */
-static int save_djgpp_startup_flags;
-#endif
-#include <coff.h>
-#define filehdr external_filehdr
-#define scnhdr external_scnhdr
-#define syment external_syment
-#define auxent external_auxent
-#define n_numaux e_numaux
-#define n_type e_type
-struct aouthdr
-{
- unsigned short magic; /* type of file */
- unsigned short vstamp; /* version stamp */
- unsigned long tsize; /* text size in bytes, padded to FW bdry*/
- unsigned long dsize; /* initialized data " " */
- unsigned long bsize; /* uninitialized data " " */
- unsigned long entry; /* entry pt. */
- unsigned long text_start;/* base of text used for this file */
- unsigned long data_start;/* base of data used for this file */
-};
-
-
-#else /* not MSDOS */
-#include <a.out.h>
-#endif /* not MSDOS */
-#endif
-
-/* Define getpagesize if the system does not.
- Note that this may depend on symbols defined in a.out.h. */
-#include "getpagesize.h"
-
-#ifndef makedev /* Try to detect types.h already loaded */
-#include <sys/types.h>
-#endif /* makedev */
-#include <stdio.h>
-#include <sys/stat.h>
-#include <errno.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
-#ifndef O_RDWR
-#define O_RDWR 2
-#endif
-
-
-extern char *start_of_text (); /* Start of text */
-extern char *start_of_data (); /* Start of initialized data */
-
-#ifdef COFF
-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;
-
-#else /* not COFF */
-
-#ifdef HPUX
-extern void *sbrk ();
-#else
-#if 0
-/* Some systems with __STDC__ compilers still declare this `char *' in some
- header file, and our declaration conflicts. The return value is always
- cast, so it should be harmless to leave it undefined. Hopefully
- machines with different size pointers and ints declare sbrk in a header
- file. */
-#ifdef __STDC__
-extern void *sbrk ();
-#else
-extern char *sbrk ();
-#endif /* __STDC__ */
-#endif
-#endif /* HPUX */
-
-#define SYMS_START ((long) N_SYMOFF (ohdr))
-
-/* Some machines override the structure name for an a.out header. */
-#ifndef EXEC_HDR_TYPE
-#define EXEC_HDR_TYPE struct exec
-#endif
-
-#ifdef HPUX
-#ifdef HP9000S200_ID
-#define MY_ID HP9000S200_ID
-#else
-#include <model.h>
-#define MY_ID MYSYS
-#endif /* no HP9000S200_ID */
-static MAGIC OLDMAGIC = {MY_ID, SHARE_MAGIC};
-static MAGIC NEWMAGIC = {MY_ID, DEMAND_MAGIC};
-#define N_TXTOFF(x) TEXT_OFFSET(x)
-#define N_SYMOFF(x) LESYM_OFFSET(x)
-static EXEC_HDR_TYPE hdr, ohdr;
-
-#else /* not HPUX */
-
-#if defined (USG) && !defined (IBMAIX) && !defined (IRIS) && !defined (COFF_ENCAPSULATE) && !defined (LINUX)
-static struct bhdr hdr, ohdr;
-#define a_magic fmagic
-#define a_text tsize
-#define a_data dsize
-#define a_bss bsize
-#define a_syms ssize
-#define a_trsize rtsize
-#define a_drsize rdsize
-#define a_entry entry
-#define N_BADMAG(x) \
- (((x).fmagic)!=OMAGIC && ((x).fmagic)!=NMAGIC &&\
- ((x).fmagic)!=FMAGIC && ((x).fmagic)!=IMAGIC)
-#define NEWMAGIC FMAGIC
-#else /* IRIS or IBMAIX or not USG */
-static EXEC_HDR_TYPE hdr, ohdr;
-#define NEWMAGIC ZMAGIC
-#endif /* IRIS or IBMAIX not USG */
-#endif /* not HPUX */
-
-static int unexec_text_start;
-static int unexec_data_start;
-
-#ifdef COFF_ENCAPSULATE
-/* coffheader is defined in the GNU a.out.encap.h file. */
-struct coffheader coffheader;
-#endif
-
-#endif /* not 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
-
-#include "lisp.h"
-
-static
-report_error (file, fd)
- char *file;
- int fd;
-{
- if (fd)
- close (fd);
- report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil));
-}
-#endif /* emacs */
-
-#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);
-#ifdef emacs
- error (msg, a1, a2);
-#else
- fprintf (stderr, msg, a1, a2);
- fprintf (stderr, "\n");
-#endif
-}
-
-static int make_hdr ();
-static int copy_text_and_data ();
-static int copy_sym ();
-static void mark_x ();
-
-/* ****************************************************************
- * 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, O_RDONLY)) < 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, 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);
- /* unlink (new_name); /* Failed, unlink new a.out */
- 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.
- */
-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;
-{
- int tem;
-#ifdef COFF
- auto struct scnhdr f_thdr; /* Text section header */
- auto struct scnhdr f_dhdr; /* Data section header */
- auto struct scnhdr f_bhdr; /* Bss section header */
- auto struct scnhdr scntemp; /* Temporary section header */
- register int scns;
-#endif /* COFF */
-#ifdef USG_SHARED_LIBRARIES
- extern unsigned int bss_end;
-#else
- unsigned int bss_end;
-#endif
-
- pagemask = getpagesize () - 1;
-
- /* Adjust text/data boundary. */
-#ifdef NO_REMAP
- data_start = (int) start_of_data ();
-#else /* not NO_REMAP */
- if (!data_start)
- data_start = (int) start_of_data ();
-#endif /* not 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)
- {
- bss_start = (ADDR_CORRECT (bss_start) + pagemask);
- /* (Up) to page bdry. */
- bss_start &= ~ pagemask;
- if (bss_start > bss_end)
- {
- ERROR1 ("unexec: Specified bss_start (%u) 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 (%u) can't be greater than bss_start (%u)",
- data_start, bss_start);
- }
-
-#ifdef COFF
- /* Salvage as much info from the existing file as possible */
- if (a_out >= 0)
- {
- 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);
- }
- /* Loop through section headers, copying them in */
- lseek (a_out, sizeof (f_hdr) + f_hdr.f_opthdr, 0);
- for (scns = f_hdr.f_nscns; scns > 0; scns--) {
- if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
- {
- PERROR (a_name);
- }
- if (scntemp.s_scnptr > 0L)
- {
- if (block_copy_start < scntemp.s_scnptr + scntemp.s_size)
- block_copy_start = scntemp.s_scnptr + scntemp.s_size;
- }
- if (strcmp (scntemp.s_name, ".text") == 0)
- {
- f_thdr = scntemp;
- }
- else if (strcmp (scntemp.s_name, ".data") == 0)
- {
- f_dhdr = scntemp;
- }
- else if (strcmp (scntemp.s_name, ".bss") == 0)
- {
- f_bhdr = scntemp;
- }
- }
- }
- else
- {
- ERROR0 ("can't build a COFF file from scratch yet");
- }
-
- /* Now we alter the contents of all the f_*hdr variables
- to correspond to what we want to dump. */
-
-#ifdef USG_SHARED_LIBRARIES
-
- /* The amount of data we're adding to the file is distance from the
- * end of the original .data space to the current end of the .data
- * space.
- */
-
- bias = bss_start - (f_ohdr.data_start + f_dhdr.s_size);
-
-#endif
-
- f_hdr.f_flags |= (F_RELFLG | F_EXEC);
-#ifdef TPIX
- f_hdr.f_nscns = 3;
-#endif
-#ifdef EXEC_MAGIC
- f_ohdr.magic = EXEC_MAGIC;
-#endif
-#ifndef NO_REMAP
- f_ohdr.text_start = (long) start_of_text ();
- f_ohdr.tsize = data_start - f_ohdr.text_start;
- f_ohdr.data_start = data_start;
-#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
- of the sections in the file itself. */
- f_thdr.s_scnptr
- = (f_thdr.s_scnptr + SECTION_ALIGNMENT) & ~SECTION_ALIGNMENT;
-#endif /* SECTION_ALIGNMENT */
-#ifdef TPIX
- 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;
-#ifdef SECTION_ALIGNMENT
- /* Some systems require special alignment
- of the sections in the file itself. */
- f_dhdr.s_scnptr
- = (f_dhdr.s_scnptr + SECTION_ALIGNMENT) & ~SECTION_ALIGNMENT;
-#endif /* SECTION_ALIGNMENT */
-#ifdef DATA_SECTION_ALIGNMENT
- /* Some systems require special alignment
- of the data section only. */
- f_dhdr.s_scnptr
- = (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;
-#ifndef USG_SHARED_LIBRARIES
- bias = f_dhdr.s_scnptr + f_dhdr.s_size - block_copy_start;
-#endif
-
- if (f_hdr.f_symptr > 0L)
- {
- f_hdr.f_symptr += bias;
- }
-
- if (f_thdr.s_lnnoptr > 0L)
- {
- f_thdr.s_lnnoptr += bias;
- }
-
-#ifdef ADJUST_EXEC_HEADER
- ADJUST_EXEC_HEADER;
-#endif /* ADJUST_EXEC_HEADER */
-
- 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);
- }
-
-#ifndef USG_SHARED_LIBRARIES
-
- if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr))
- {
- PERROR (new_name);
- }
-
- if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr))
- {
- PERROR (new_name);
- }
-
- if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr))
- {
- PERROR (new_name);
- }
-
-#else /* USG_SHARED_LIBRARIES */
-
- /* The purpose of this code is to write out the new file's section
- * header table.
- *
- * Scan through the original file's sections. If the encountered
- * section is one we know (.text, .data or .bss), write out the
- * correct header. If it is a section we do not know (such as
- * .lib), adjust the address of where the section data is in the
- * file, and write out the header.
- *
- * If any section precedes .text or .data in the file, this code
- * will not adjust the file pointer for that section correctly.
- */
-
- /* This used to use sizeof (f_ohdr) instead of .f_opthdr.
- .f_opthdr is said to be right when there is no optional header. */
- lseek (a_out, sizeof (f_hdr) + f_hdr.f_opthdr, 0);
-
- for (scns = f_hdr.f_nscns; scns > 0; scns--)
- {
- if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
- PERROR (a_name);
-
- if (!strcmp (scntemp.s_name, f_thdr.s_name)) /* .text */
- {
- if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr))
- PERROR (new_name);
- }
- else if (!strcmp (scntemp.s_name, f_dhdr.s_name)) /* .data */
- {
- if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr))
- PERROR (new_name);
- }
- else if (!strcmp (scntemp.s_name, f_bhdr.s_name)) /* .bss */
- {
- if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr))
- PERROR (new_name);
- }
- else
- {
- if (scntemp.s_scnptr)
- scntemp.s_scnptr += bias;
- if (write (new, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
- PERROR (new_name);
- }
- }
-#endif /* USG_SHARED_LIBRARIES */
-
- return (0);
-
-#else /* if not COFF */
-
- /* Get symbol table info from header of a.out file if given one. */
- if (a_out >= 0)
- {
-#ifdef COFF_ENCAPSULATE
- if (read (a_out, &coffheader, sizeof coffheader) != sizeof coffheader)
- {
- PERROR(a_name);
- }
- if (coffheader.f_magic != COFF_MAGIC)
- {
- ERROR1("%s doesn't have legal coff magic number\n", a_name);
- }
-#endif
- if (read (a_out, &ohdr, sizeof hdr) != sizeof hdr)
- {
- PERROR (a_name);
- }
-
- if (N_BADMAG (ohdr))
- {
- ERROR1 ("invalid magic number in %s", a_name);
- }
- hdr = ohdr;
- }
- else
- {
-#ifdef COFF_ENCAPSULATE
- /* We probably could without too much trouble. The code is in gld
- * but I don't have that much time or incentive.
- */
- ERROR0 ("can't build a COFF file from scratch yet");
-#else
-#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
- bzero ((void *)&hdr, sizeof hdr);
-#else
- bzero (&hdr, sizeof hdr);
-#endif
-#endif
- }
-
- unexec_text_start = (long) start_of_text ();
- unexec_data_start = data_start;
-
- /* Machine-dependent fixup for header, or maybe for unexec_text_start */
-#ifdef ADJUST_EXEC_HEADER
- ADJUST_EXEC_HEADER;
-#endif /* ADJUST_EXEC_HEADER */
-
- hdr.a_trsize = 0;
- hdr.a_drsize = 0;
- if (entry_address != 0)
- hdr.a_entry = entry_address;
-
- hdr.a_bss = bss_end - bss_start;
- hdr.a_data = bss_start - data_start;
-#ifdef NO_REMAP
- hdr.a_text = ohdr.a_text;
-#else /* not NO_REMAP */
- hdr.a_text = data_start - unexec_text_start;
-
-#ifdef A_TEXT_OFFSET
- hdr.a_text += A_TEXT_OFFSET (ohdr);
-#endif
-
-#endif /* not NO_REMAP */
-
-#ifdef COFF_ENCAPSULATE
- /* We are encapsulating BSD format within COFF format. */
- {
- struct coffscn *tp, *dp, *bp;
- tp = &coffheader.scns[0];
- dp = &coffheader.scns[1];
- bp = &coffheader.scns[2];
- tp->s_size = hdr.a_text + sizeof(struct exec);
- dp->s_paddr = data_start;
- dp->s_vaddr = data_start;
- dp->s_size = hdr.a_data;
- bp->s_paddr = dp->s_vaddr + dp->s_size;
- bp->s_vaddr = bp->s_paddr;
- bp->s_size = hdr.a_bss;
- coffheader.tsize = tp->s_size;
- coffheader.dsize = dp->s_size;
- coffheader.bsize = bp->s_size;
- coffheader.text_start = tp->s_vaddr;
- coffheader.data_start = dp->s_vaddr;
- }
- if (write (new, &coffheader, sizeof coffheader) != sizeof coffheader)
- {
- PERROR(new_name);
- }
-#endif /* COFF_ENCAPSULATE */
-
- if (write (new, &hdr, sizeof hdr) != sizeof hdr)
- {
- PERROR (new_name);
- }
-
-#if 0 /* This #ifndef caused a bug on Linux when using QMAGIC. */
- /* This adjustment was done above only #ifndef NO_REMAP,
- so only undo it now #ifndef NO_REMAP. */
- /* #ifndef NO_REMAP */
-#endif
-#ifdef A_TEXT_OFFSET
- hdr.a_text -= A_TEXT_OFFSET (ohdr);
-#endif
-
- return 0;
-
-#endif /* not COFF */
-}
-
-/* ****************************************************************
- * copy_text_and_data
- *
- * Copy the text and data segments from memory to the new a.out
- */
-static int
-copy_text_and_data (new, a_out)
- int new, a_out;
-{
- register char *end;
- register char *ptr;
-
-#ifdef COFF
-
-#ifdef USG_SHARED_LIBRARIES
-
- int scns;
- struct scnhdr scntemp; /* Temporary section header */
-
- /* The purpose of this code is to write out the new file's section
- * contents.
- *
- * Step through the section table. If we know the section (.text,
- * .data) do the appropriate thing. Otherwise, if the section has
- * no allocated space in the file (.bss), do nothing. Otherwise,
- * the section has space allocated in the file, and is not a section
- * we know. So just copy it.
- */
-
- lseek (a_out, sizeof (struct filehdr) + sizeof (struct aouthdr), 0);
-
- for (scns = f_hdr.f_nscns; scns > 0; scns--)
- {
- if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
- PERROR ("temacs");
-
- if (!strcmp (scntemp.s_name, ".text"))
- {
- lseek (new, (long) text_scnptr, 0);
- ptr = (char *) f_ohdr.text_start;
- end = ptr + f_ohdr.tsize;
- write_segment (new, ptr, end);
- }
- else if (!strcmp (scntemp.s_name, ".data"))
- {
- lseek (new, (long) data_scnptr, 0);
- ptr = (char *) f_ohdr.data_start;
- end = ptr + f_ohdr.dsize;
- write_segment (new, ptr, end);
- }
- else if (!scntemp.s_scnptr)
- ; /* do nothing - no data for this section */
- else
- {
- char page[BUFSIZ];
- int size, n;
- long old_a_out_ptr = lseek (a_out, 0, 1);
-
- lseek (a_out, scntemp.s_scnptr, 0);
- for (size = scntemp.s_size; size > 0; size -= sizeof (page))
- {
- n = size > sizeof (page) ? sizeof (page) : size;
- if (read (a_out, page, n) != n || write (new, page, n) != n)
- PERROR ("emacs");
- }
- lseek (a_out, old_a_out_ptr, 0);
- }
- }
-
-#else /* COFF, but not USG_SHARED_LIBRARIES */
-
-#ifdef MSDOS
-#if __DJGPP__ >= 2
- /* Dump the original table of exception handlers, not the one
- where our exception hooks are registered. */
- __djgpp_exception_toggle ();
-
- /* Switch off startup flags that might have been set at runtime
- and which might change the way that dumped Emacs works. */
- save_djgpp_startup_flags = _crt0_startup_flags;
- _crt0_startup_flags &= ~(_CRT0_FLAG_NO_LFN | _CRT0_FLAG_NEARPTR);
-#endif
-#endif
-
- 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);
-
- lseek (new, (long) data_scnptr, 0);
- ptr = (char *) f_ohdr.data_start;
- end = ptr + f_ohdr.dsize;
- write_segment (new, ptr, end);
-
-#ifdef MSDOS
-#if __DJGPP__ >= 2
- /* Restore our exception hooks. */
- __djgpp_exception_toggle ();
-
- /* Restore the startup flags. */
- _crt0_startup_flags = save_djgpp_startup_flags;
-#endif
-#endif
-
-#endif /* USG_SHARED_LIBRARIES */
-
-#else /* if not COFF */
-
-/* Some machines count the header as part of the text segment.
- That is to say, the header appears in core
- just before the address that start_of_text returns.
- For them, N_TXTOFF is the place where the header goes.
- We must adjust the seek to the place after the header.
- Note that at this point hdr.a_text does *not* count
- the extra A_TEXT_OFFSET bytes, only the actual bytes of code. */
-
-#ifdef A_TEXT_SEEK
- lseek (new, (long) A_TEXT_SEEK (hdr), 0);
-#else
- lseek (new, (long) N_TXTOFF (hdr), 0);
-#endif /* no A_TEXT_SEEK */
-
-#ifdef RISCiX
-
- /* Acorn's RISC-iX has a wacky way of initialising the position of the heap.
- * There is a little table in crt0.o that is filled at link time with
- * the min and current brk positions, among other things. When start
- * runs, it copies the table to where these parameters live during
- * execution. This data is in text space, so it cannot be modified here
- * before saving the executable, so the data is written manually. In
- * addition, the table does not have a label, and the nearest accessible
- * label (mcount) is not prefixed with a '_', thus making it inaccessible
- * from within C programs. To overcome this, emacs's executable is passed
- * through the command 'nm %s | fgrep mcount' into a pipe, and the
- * resultant output is then used to find the address of 'mcount'. As far as
- * is possible to determine, in RISC-iX releases prior to 1.2, the negative
- * offset of the table from mcount is 0x2c, whereas from 1.2 onwards it is
- * 0x30. bss_end has been rounded up to page boundary. This solution is
- * based on suggestions made by Kevin Welton and Steve Hunt of Acorn, and
- * avoids the need for a custom version of crt0.o for emacs which has its
- * table in data space.
- */
-
- {
- char command[1024];
- char errbuf[1024];
- char address_text[32];
- int proforma[4];
- FILE *pfile;
- char *temp_ptr;
- char c;
- int mcount_address, mcount_offset, count;
- extern char *_execname;
-
-
- /* The use of _execname is incompatible with RISCiX 1.1 */
- sprintf (command, "nm %s | fgrep mcount", _execname);
-
- if ( (pfile = popen(command, "r")) == NULL)
- {
- sprintf (errbuf, "Could not open pipe");
- PERROR (errbuf);
- }
-
- count=0;
- while ( ((c=getc(pfile)) != EOF) && (c != ' ') && (count < 31))
- address_text[count++]=c;
- address_text[count]=0;
-
- if ((count == 0) || pclose(pfile) != NULL)
- {
- sprintf (errbuf, "Failed to execute the command '%s'\n", command);
- PERROR (errbuf);
- }
-
- sscanf(address_text, "%x", &mcount_address);
- ptr = (char *) unexec_text_start;
- mcount_offset = (char *)mcount_address - ptr;
-
-#ifdef RISCiX_1_1
-#define EDATA_OFFSET 0x2c
-#else
-#define EDATA_OFFSET 0x30
-#endif
-
- end = ptr + mcount_offset - EDATA_OFFSET;
-
- write_segment (new, ptr, end);
-
- proforma[0] = bss_end; /* becomes _edata */
- proforma[1] = bss_end; /* becomes _end */
- proforma[2] = bss_end; /* becomes _minbrk */
- proforma[3] = bss_end; /* becomes _curbrk */
-
- write (new, proforma, 16);
-
- temp_ptr = ptr;
- ptr = end + 16;
- end = temp_ptr + hdr.a_text;
-
- write_segment (new, ptr, end);
- }
-
-#else /* !RISCiX */
- ptr = (char *) unexec_text_start;
- end = ptr + hdr.a_text;
- write_segment (new, ptr, end);
-#endif /* RISCiX */
-
- ptr = (char *) unexec_data_start;
- end = ptr + hdr.a_data;
-/* This lseek is certainly incorrect when A_TEXT_OFFSET
- and I believe it is a no-op otherwise.
- Let's see if its absence ever fails. */
-/* lseek (new, (long) N_TXTOFF (hdr) + hdr.a_text, 0); */
- write_segment (new, ptr, end);
-
-#endif /* not COFF */
-
- return 0;
-}
-
-write_segment (new, ptr, end)
- int new;
- register char *ptr, *end;
-{
- register int i, nwrite, ret;
- char buf[80];
- extern int errno;
- /* This is the normal amount to write at once.
- It is the size of block that NFS uses. */
- int writesize = 1 << 13;
- int pagesize = getpagesize ();
- char zeros[1 << 13];
-
- bzero (zeros, sizeof (zeros));
-
- for (i = 0; ptr < end;)
- {
- /* Distance to next multiple of writesize. */
- nwrite = (((int) ptr + writesize) & -writesize) - (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
-#ifdef EFAULT
- && errno == EFAULT
-#endif
- )
- {
- /* Write only a page of zeros at once,
- so that we we don't overshoot the start
- of the valid memory in the old data segment. */
- if (nwrite > pagesize)
- nwrite = pagesize;
- write (new, zeros, nwrite);
- }
-#if 0 /* Now that we have can ask `write' to write more than a page,
- it is legit for write do less than the whole amount specified. */
- 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);
- }
-#endif
- 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;
-
-#ifdef COFF
- if (SYMS_START == 0L)
- return 0;
-#endif /* COFF */
-
-#ifdef COFF
- if (lnnoptr) /* if there is line number info */
- lseek (a_out, lnnoptr, 0); /* start copying from there */
- else
-#endif /* COFF */
- lseek (a_out, SYMS_START, 0); /* Position a.out to symtab. */
-
- 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 successfully building the new a.out, mark it executable
- */
-static void
-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);
-}
-
-#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
- * 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.
- */
-
-/* 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;
-#if defined (amdahl_uts) || defined (pfa)
- SYMENT symentry;
- AUXENT auxentry;
-#else
- struct syment symentry;
- union auxent auxentry;
-#endif
-
- if (!lnnoptr || !f_hdr.f_symptr)
- return 0;
-
-#ifdef MSDOS
- if ((new = writedesc) < 0)
-#else
- if ((new = open (new_name, O_RDWR)) < 0)
-#endif
- {
- PERROR (new_name);
- return -1;
- }
-
- 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) || symentry.n_type == 0x2400)
- {
- auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
- lseek (new, -AUXESZ, 1);
- write (new, &auxentry, AUXESZ);
- }
- }
- }
-#ifndef MSDOS
- close (new);
-#endif
- return 0;
-}
-
-#endif /* COFF_BSD_SYMBOLS */
-
-#endif /* COFF */
-
-#endif /* not CANNOT_DUMP */
diff --git a/src/unexelf.c b/src/unexelf.c
deleted file mode 100644
index a832755167e..00000000000
--- a/src/unexelf.c
+++ /dev/null
@@ -1,952 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
-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
-
-
- */
-
-/* Modified by wtien@urbana.mcd.mot.com of Motorola Inc.
- *
- * The above mechanism does not work if the unexeced ELF file is being
- * re-layout by other applications (such as `strip'). All the applications
- * that re-layout the internal of ELF will layout all sections in ascending
- * order of their file offsets. After the re-layout, the data2 section will
- * still be the LAST section in the section header vector, but its file offset
- * is now being pushed far away down, and causes part of it not to be mapped
- * in (ie. not covered by the load segment entry in PHDR vector), therefore
- * causes the new binary to fail.
- *
- * The solution is to modify the unexec algorithm to insert the new data2
- * section header right before the new bss section header, so their file
- * offsets will be in the ascending order. Since some of the section's (all
- * sections AFTER the bss section) indexes are now changed, we also need to
- * modify some fields to make them point to the right sections. This is done
- * by macro PATCH_INDEX. All the fields that need to be patched are:
- *
- * 1. ELF header e_shstrndx field.
- * 2. section header sh_link and sh_info field.
- * 3. symbol table entry st_shndx field.
- *
- * The above example now should look like:
-
- **** 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] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
- 0 0 0x4 0
-
-[17] 8 3 0x80c6800 0x7d800 0 .bss
- 0 0 0x4 0
-
-[18] 2 0 0 0x7d800 0x9b90 .symtab
- 19 371 0x4 0x10
-
-[19] 3 0 0 0x87390 0x8526 .strtab
- 0 0 0x1 0
-
-[20] 3 0 0 0x8f8b6 0x93 .shstrtab
- 0 0 0x1 0
-
-[21] 1 0 0 0x8f949 0x68b7 .comment
- 0 0 0x1 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>
-
-#ifdef __alpha__
-# include <sym.h> /* get COFF debugging symbol table declaration */
-#endif
-
-#if __GNU_LIBRARY__ - 0 >= 6
-# include <link.h> /* get ElfW etc */
-#endif
-
-#ifndef ElfW
-# ifdef __STDC__
-# define ElfW(type) Elf32_##type
-# else
-# define ElfW(type) Elf32_/**/type
-# endif
-#endif
-
-#ifndef emacs
-#define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1)
-#else
-#include <config.h>
-extern void fatal (char *, ...);
-#endif
-
-#ifndef ELF_BSS_SECTION_NAME
-#define ELF_BSS_SECTION_NAME ".bss"
-#endif
-
-/* Get the address of a particular section or program header entry,
- * accounting for the size of the entries.
- */
-/*
- On PPC Reference Platform running Solaris 2.5.1
- the plt section is also of type NOBI like the bss section.
- (not really stored) and therefore sections after the bss
- section start at the plt offset. The plt section is always
- the one just before the bss section.
- Thus, we modify the test from
- if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
- to
- if (NEW_SECTION_H (nn).sh_offset >=
- OLD_SECTION_H (old_bss_index-1).sh_offset)
- This is just a hack. We should put the new data section
- before the .plt section.
- And we should not have this routine at all but use
- the libelf library to read the old file and create the new
- file.
- The changed code is minimal and depends on prep set in m/prep.h
- Erik Deumens
- Quantum Theory Project
- University of Florida
- deumens@qtp.ufl.edu
- Apr 23, 1996
- */
-
-#define OLD_SECTION_H(n) \
- (*(ElfW(Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
-#define NEW_SECTION_H(n) \
- (*(ElfW(Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
-#define OLD_PROGRAM_H(n) \
- (*(ElfW(Phdr) *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
-#define NEW_PROGRAM_H(n) \
- (*(ElfW(Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
-
-#define PATCH_INDEX(n) \
- do { \
- if ((int) (n) >= old_bss_index) \
- (n)++; } while (0)
-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;
-{
- 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.
- */
- ElfW(Ehdr) *old_file_h, *new_file_h;
- ElfW(Phdr) *old_program_h, *new_program_h;
- ElfW(Shdr) *old_section_h, *new_section_h;
-
- /* Point to the section name table in the old file */
- char *old_section_names;
-
- ElfW(Addr) old_bss_addr, new_bss_addr;
- ElfW(Word) old_bss_size, new_data2_size;
- ElfW(Off) new_data2_offset;
- ElfW(Addr) new_data2_addr;
-
- int n, nn, 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 = (ElfW(Ehdr) *) old_base;
- old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
- old_section_h = (ElfW(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 < (int) 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,
- ELF_BSS_SECTION_NAME))
- 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)
- new_bss_addr = (ElfW(Addr)) sbrk (0);
-#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 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);
-
-#ifdef UNEXEC_USE_MAP_PRIVATE
- new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
- new_file, 0);
-#else
- new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
- new_file, 0);
-#endif
-
- if (new_base == (caddr_t) -1)
- fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
-
- new_file_h = (ElfW(Ehdr) *) new_base;
- new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
- new_section_h = (ElfW(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);
-
- /* Modify the e_shstrndx if necessary. */
- PATCH_INDEX (new_file_h->e_shstrndx);
-
- /* 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 (old_data_index = 1; old_data_index < (int) 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);
-
- /* Walk through all section headers, insert the new data2 section right
- before the new bss section. */
- for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++)
- {
- caddr_t src;
- /* If it is bss section, insert the new data2 section before it. */
- if (n == old_bss_index)
- {
- /* Steal the data section header for this data2 section. */
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
- new_file_h->e_shentsize);
-
- NEW_SECTION_H (nn).sh_addr = new_data2_addr;
- NEW_SECTION_H (nn).sh_offset = new_data2_offset;
- NEW_SECTION_H (nn).sh_size = new_data2_size;
- /* Use the bss section's alignment. This will assure that the
- new data2 section always be placed in the same spot as the old
- bss section by any other application. */
- NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign;
-
- /* Now copy over what we have in the memory now. */
- memcpy (NEW_SECTION_H (nn).sh_offset + new_base,
- (caddr_t) OLD_SECTION_H (n).sh_addr,
- new_data2_size);
- nn++;
- }
-
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
- old_file_h->e_shentsize);
-
- /* The new bss section's size is zero, and its file offset and virtual
- address should be off by NEW_DATA2_SIZE. */
- if (n == old_bss_index)
- {
- /* NN should be `old_bss_index + 1' at this point. */
- NEW_SECTION_H (nn).sh_offset += new_data2_size;
- NEW_SECTION_H (nn).sh_addr += new_data2_size;
- /* Let the new bss section address alignment be the same as the
- section address alignment followed the old bss section, so
- this section will be placed in exactly the same place. */
- NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
- NEW_SECTION_H (nn).sh_size = 0;
- }
- else
- {
- /* Any section that was original placed AFTER the bss
- section should now be off by NEW_DATA2_SIZE. */
-#ifdef SOLARIS_POWERPC
- /* On PPC Reference Platform running Solaris 2.5.1
- the plt section is also of type NOBI like the bss section.
- (not really stored) and therefore sections after the bss
- section start at the plt offset. The plt section is always
- the one just before the bss section.
- It would be better to put the new data section before
- the .plt section, or use libelf instead.
- Erik Deumens, deumens@qtp.ufl.edu. */
- if (NEW_SECTION_H (nn).sh_offset
- >= OLD_SECTION_H (old_bss_index-1).sh_offset)
- NEW_SECTION_H (nn).sh_offset += new_data2_size;
-#else
- if (round_up (NEW_SECTION_H (nn).sh_offset,
- OLD_SECTION_H (old_bss_index).sh_addralign)
- >= new_data2_offset)
- NEW_SECTION_H (nn).sh_offset += new_data2_size;
-#endif
- /* Any section that was originally placed after the section
- header table should now be off by the size of one section
- header table entry. */
- if (NEW_SECTION_H (nn).sh_offset > new_file_h->e_shoff)
- NEW_SECTION_H (nn).sh_offset += new_file_h->e_shentsize;
- }
-
- /* If any section hdr refers to the section after the new .data
- section, make it refer to next one because we have inserted
- a new section in between. */
-
- PATCH_INDEX (NEW_SECTION_H (nn).sh_link);
- /* For symbol tables, info is a symbol table index,
- so don't change it. */
- if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB
- && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM)
- PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
-
- /* Now, start to copy the content of sections. */
- if (NEW_SECTION_H (nn).sh_type == SHT_NULL
- || NEW_SECTION_H (nn).sh_type == SHT_NOBITS)
- continue;
-
- /* 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. */
- 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) OLD_SECTION_H (n).sh_addr;
- else
- src = old_base + OLD_SECTION_H (n).sh_offset;
-
- memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
- NEW_SECTION_H (nn).sh_size);
-
-#ifdef __alpha__
- /* Update Alpha COFF symbol table: */
- if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug")
- == 0)
- {
- pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base);
-
- symhdr->cbLineOffset += new_data2_size;
- symhdr->cbDnOffset += new_data2_size;
- symhdr->cbPdOffset += new_data2_size;
- symhdr->cbSymOffset += new_data2_size;
- symhdr->cbOptOffset += new_data2_size;
- symhdr->cbAuxOffset += new_data2_size;
- symhdr->cbSsOffset += new_data2_size;
- symhdr->cbSsExtOffset += new_data2_size;
- symhdr->cbFdOffset += new_data2_size;
- symhdr->cbRfdOffset += new_data2_size;
- symhdr->cbExtOffset += new_data2_size;
- }
-#endif /* __alpha__ */
-
- /* If it is the symbol table, its st_shndx field needs to be patched. */
- if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
- || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
- {
- ElfW(Shdr) *spt = &NEW_SECTION_H (nn);
- unsigned int num = spt->sh_size / spt->sh_entsize;
- ElfW(Sym) * sym = (ElfW(Sym) *) (NEW_SECTION_H (nn).sh_offset +
- new_base);
- for (; num--; sym++)
- {
- if ((sym->st_shndx == SHN_UNDEF)
- || (sym->st_shndx == SHN_ABS)
- || (sym->st_shndx == SHN_COMMON))
- continue;
-
- PATCH_INDEX (sym->st_shndx);
- }
- }
- }
-
- /* Update the symbol values of _edata and _end. */
- for (n = new_file_h->e_shnum - 1; n; n--)
- {
- byte *symnames;
- ElfW(Sym) *symp, *symendp;
-
- if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM
- && NEW_SECTION_H (n).sh_type != SHT_SYMTAB)
- continue;
-
- symnames = ((byte *) new_base
- + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset);
- symp = (ElfW(Sym) *) (NEW_SECTION_H (n).sh_offset + new_base);
- symendp = (ElfW(Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size);
-
- for (; symp < symendp; symp ++)
- if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
- || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0)
- memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
- }
-
- /* This loop seeks out relocation sections for the data section, so
- that it can undo relocations performed by the runtime linker. */
- for (n = new_file_h->e_shnum - 1; n; n--)
- {
- ElfW(Shdr) section = NEW_SECTION_H (n);
- switch (section.sh_type) {
- default:
- break;
- case SHT_REL:
- case SHT_RELA:
- /* This code handles two different size structs, but there should
- be no harm in that provided that r_offset is always the first
- member. */
- nn = section.sh_info;
- if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".data1"))
- {
- ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr -
- NEW_SECTION_H (nn).sh_offset;
- caddr_t reloc = old_base + section.sh_offset, end;
- for (end = reloc + section.sh_size; reloc < end;
- reloc += section.sh_entsize)
- {
- ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset;
-#ifdef __alpha__
- /* The Alpha ELF binutils currently have a bug that
- sometimes results in relocs that contain all
- zeroes. Work around this for now... */
- if (((ElfW(Rel) *) reloc)->r_offset == 0)
- continue;
-#endif
- memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr)));
- }
- }
- break;
- }
- }
-
-#ifdef UNEXEC_USE_MAP_PRIVATE
- if (lseek (new_file, 0, SEEK_SET) == -1)
- fatal ("Can't rewind (%s): errno %d\n", new_name, errno);
-
- if (write (new_file, new_base, new_file_size) != new_file_size)
- fatal ("Can't write (%s): errno %d\n", new_name, errno);
-#endif
-
- /* 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/unexencap.c b/src/unexencap.c
deleted file mode 100644
index 4ffc41145a9..00000000000
--- a/src/unexencap.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Waiting for papers! */
-
-/*
- * Do an unexec() for coff encapsulation. Uses the approach I took
- * for AKCL, so don't be surprised if it doesn't look too much like
- * the other unexec() routines. Assumes NO_REMAP. Should be easy to
- * adapt to the emacs style unexec() if that is desired, but this works
- * just fine for me with GCC/GAS/GLD under System V. - Jordan
- */
-
-#include <sys/types.h>
-#include <sys/fcntl.h>
-#include <sys/file.h>
-#include <stdio.h>
-#include "/usr/gnu/lib/gcc/gcc-include/a.out.h"
-
-filecpy(to, from, n)
-FILE *to, *from;
-register int n;
-{
- char buffer[BUFSIZ];
-
- for (;;)
- if (n > BUFSIZ) {
- fread(buffer, BUFSIZ, 1, from);
- fwrite(buffer, BUFSIZ, 1, to);
- n -= BUFSIZ;
- } else if (n > 0) {
- fread(buffer, 1, n, from);
- fwrite(buffer, 1, n, to);
- break;
- } else
- break;
-}
-/* ****************************************************************
- * 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;
-{
- struct coffheader header1;
- struct coffscn *tp, *dp, *bp;
- struct exec header;
- int stsize;
- char *original_file = a_name;
- char *save_file = new_name;
-
- char *data_begin, *data_end;
- int original_data;
- FILE *original, *save;
- register int n;
- register char *p;
- extern char *sbrk();
- char stdin_buf[BUFSIZ], stdout_buf[BUFSIZ];
-
-
- fclose(stdin);
- original = fopen(original_file, "r");
- if (stdin != original || original->_file != 0) {
- fprintf(stderr, "unexec: Can't open the original file.\n");
- exit(1);
- }
- setbuf(original, stdin_buf);
- fclose(stdout);
- unlink(save_file);
- n = open(save_file, O_CREAT|O_WRONLY, 0777);
- if (n != 1 || (save = fdopen(n, "w")) != stdout) {
- fprintf(stderr, "unexec: Can't open the save file.\n");
- exit(1);
- }
- setbuf(save, stdout_buf);
-
- fread(&header1, sizeof(header1), 1, original);
- tp = &header1.scns[0];
- dp = &header1.scns[1];
- bp = &header1.scns[2];
- fread(&header, sizeof(header), 1, original);
- data_begin=(char *)N_DATADDR(header);
- data_end = sbrk(0);
- original_data = header.a_data;
- header.a_data = data_end - data_begin;
- header.a_bss = 0;
- dp->s_size = header.a_data;
- bp->s_paddr = dp->s_vaddr + dp->s_size;
- bp->s_vaddr = bp->s_paddr;
- bp->s_size = 0;
- header1.tsize = tp->s_size;
- header1.dsize = dp->s_size;
- header1.bsize = bp->s_size;
- fwrite(&header1, sizeof(header1), 1, save);
- fwrite(&header, sizeof(header), 1, save);
-
- filecpy(save, original, header.a_text);
-
- for (n = header.a_data, p = data_begin; ; n -= BUFSIZ, p += BUFSIZ)
- if (n > BUFSIZ)
- fwrite(p, BUFSIZ, 1, save);
- else if (n > 0) {
- fwrite(p, 1, n, save);
- break;
- } else
- break;
-
- fseek(original, original_data, 1);
-
- filecpy(save, original, header.a_syms+header.a_trsize+header.a_drsize);
- fread(&stsize, sizeof(stsize), 1, original);
- fwrite(&stsize, sizeof(stsize), 1, save);
- filecpy(save, original, stsize - sizeof(stsize));
-
- fclose(original);
- fclose(save);
-}
diff --git a/src/unexenix.c b/src/unexenix.c
deleted file mode 100644
index 10413bd65a0..00000000000
--- a/src/unexenix.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/* Unexec for Xenix.
- 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.
-
- Copyright (C) 1988, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-
-/*
- 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 char *strerror ();
-#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 successfully 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
- fprintf (stderr, "unexec: %s, ", strerror (errno));
- va_start (ap);
- _doprnt (s, ap, stderr);
- fputs (".\n", stderr);
- exit (1);
-}
diff --git a/src/unexfx2800.c b/src/unexfx2800.c
deleted file mode 100644
index 89e14e678d8..00000000000
--- a/src/unexfx2800.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/* 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
deleted file mode 100644
index f33340c4d8c..00000000000
--- a/src/unexhp9k800.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/* Unexec for HP 9000 Series 800 machines.
- Bob Desinger <hpsemc!bd@hplabs.hp.com>
-
- Note that the GNU project considers support for HP 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.
-
-
- Unexec creates a copy of the old a.out file, and replaces the old data
- area with the current data area. When the new file is executed, the
- process will see the same data structures and data values that the
- original process had when unexec was called.
-
- Unlike other versions of unexec, this one copies symbol table and
- debug information to the new a.out file. Thus, the new a.out file
- may be debugged with symbolic debuggers.
-
- If you fix any bugs in this, I'd like to incorporate your fixes.
- Send them to uunet!hpda!hpsemc!jmorris or jmorris%hpsemc@hplabs.HP.COM.
-
- CAVEATS:
- This routine saves the current value of all static and external
- variables. This means that any data structure that needs to be
- initialized must be explicitly reset. Variables will not have their
- expected default values.
-
- Unfortunately, the HP-UX signal handler has internal initialization
- flags which are not explicitly reset. Thus, for signals to work in
- conjunction with this routine, the following code must executed when
- the new process starts up.
-
- void _sigreturn ();
- ...
- sigsetreturn (_sigreturn);
-*/
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <a.out.h>
-
-#ifdef emacs
-#include <config.h>
-#endif
-
-#ifdef HPUX_USE_SHLIBS
-#include <dl.h>
-#endif
-
-/* brk value to restore, stored as a global.
- This is really used only if we used shared libraries. */
-static long brk_on_dump = 0;
-
-/* Called from main, if we use shared libraries. */
-int
-run_time_remap (ignored)
- char *ignored;
-{
- brk ((char *) brk_on_dump);
-}
-
-#undef roundup
-#define roundup(x,n) (((x) + ((n) - 1)) & ~((n) - 1)) /* n is power of 2 */
-#define min(x,y) (((x) < (y)) ? (x) : (y))
-
-
-/* Create a new a.out file, same as old but with current data space */
-
-unexec (new_name, old_name, new_end_of_text, dummy1, dummy2)
- char new_name[]; /* name of the new a.out file to be created */
- char old_name[]; /* name of the old a.out file */
- char *new_end_of_text; /* ptr to new edata/etext; NOT USED YET */
- int dummy1, dummy2; /* not used by emacs */
-{
- int old, new;
- 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,
- rename the temp file to the new name.
- This way, a program could update its own a.out file even while
- it is still executing. If problems occur, everything is still
- intact. NOT implemented. */
-
- /* Open the input and output a.out files */
- old = open (old_name, O_RDONLY);
- if (old < 0)
- { perror (old_name); exit (1); }
- new = open (new_name, O_CREAT|O_RDWR|O_TRUNC, 0777);
- if (new < 0)
- { perror (new_name); exit (1); }
-
- /* Read the old headers */
- read_header (old, &hdr, &auxhdr);
-
- brk_on_dump = (long) sbrk (0);
-
- /* Decide how large the new and old data areas are */
- old_size = auxhdr.exec_dsize;
- /* I suspect these two statements are separate
- to avoid a compiler bug in hpux version 8. */
- i = (long) sbrk (0);
- new_size = i - auxhdr.exec_dmem;
-
- /* Copy the old file to the new, up to the data space */
- lseek (old, 0, 0);
- copy_file (old, new, auxhdr.exec_dfile);
-
- /* Skip the old data segment and write a new one */
- lseek (old, old_size, 1);
- save_data_space (new, &hdr, &auxhdr, new_size);
-
- /* Copy the rest of the file */
- copy_rest (old, new);
-
- /* Update file pointers since we probably changed size of data area */
- update_file_ptrs (new, &hdr, &auxhdr, auxhdr.exec_dfile, new_size-old_size);
-
- /* Save the modified header */
- write_header (new, &hdr, &auxhdr);
-
- /* Close the binary file */
- close (old);
- close (new);
- return 0;
-}
-
-/* Save current data space in the file, update header. */
-
-save_data_space (file, hdr, auxhdr, size)
- int file;
- struct header *hdr;
- struct som_exec_auxhdr *auxhdr;
- int size;
-{
- /* Write the entire data space out to the file */
- if (write (file, auxhdr->exec_dmem, size) != size)
- { perror ("Can't save new data space"); exit (1); }
-
- /* Update the header to reflect the new data size */
- auxhdr->exec_dsize = size;
- auxhdr->exec_bsize = 0;
-}
-
-/* Update the values of file pointers when something is inserted. */
-
-update_file_ptrs (file, hdr, auxhdr, location, offset)
- int file;
- struct header *hdr;
- struct som_exec_auxhdr *auxhdr;
- unsigned int location;
- int offset;
-{
- struct subspace_dictionary_record subspace;
- int i;
-
- /* Increase the overall size of the module */
- hdr->som_length += offset;
-
- /* Update the various file pointers in the header */
-#define update(ptr) if (ptr > location) ptr = ptr + offset
- update (hdr->aux_header_location);
- update (hdr->space_strings_location);
- update (hdr->init_array_location);
- update (hdr->compiler_location);
- update (hdr->symbol_location);
- update (hdr->fixup_request_location);
- update (hdr->symbol_strings_location);
- update (hdr->unloadable_sp_location);
- update (auxhdr->exec_tfile);
- update (auxhdr->exec_dfile);
-
- /* Do for each subspace dictionary entry */
- lseek (file, hdr->subspace_location, 0);
- for (i = 0; i < hdr->subspace_total; i++)
- {
- if (read (file, &subspace, sizeof (subspace)) != sizeof (subspace))
- { perror ("Can't read subspace record"); exit (1); }
-
- /* If subspace has a file location, update it */
- if (subspace.initialization_length > 0
- && subspace.file_loc_init_value > location)
- {
- subspace.file_loc_init_value += offset;
- lseek (file, -sizeof (subspace), 1);
- if (write (file, &subspace, sizeof (subspace)) != sizeof (subspace))
- { perror ("Can't update subspace record"); exit (1); }
- }
- }
-
- /* Do for each initialization pointer record */
- /* (I don't think it applies to executable files, only relocatables) */
-#undef update
-}
-
-/* Read in the header records from an a.out file. */
-
-read_header (file, hdr, auxhdr)
- int file;
- struct header *hdr;
- struct som_exec_auxhdr *auxhdr;
-{
-
- /* Read the header in */
- lseek (file, 0, 0);
- if (read (file, hdr, sizeof (*hdr)) != sizeof (*hdr))
- { perror ("Couldn't read header from a.out file"); exit (1); }
-
- if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC
- && hdr->a_magic != DEMAND_MAGIC)
- {
- fprintf (stderr, "a.out file doesn't have legal magic number\n");
- exit (1);
- }
-
- lseek (file, hdr->aux_header_location, 0);
- if (read (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr))
- {
- perror ("Couldn't read auxiliary header from a.out file");
- exit (1);
- }
-}
-
-/* Write out the header records into an a.out file. */
-
-write_header (file, hdr, auxhdr)
- int file;
- struct header *hdr;
- struct som_exec_auxhdr *auxhdr;
-{
- /* Update the checksum */
- hdr->checksum = calculate_checksum (hdr);
-
- /* Write the header back into the a.out file */
- lseek (file, 0, 0);
- if (write (file, hdr, sizeof (*hdr)) != sizeof (*hdr))
- { perror ("Couldn't write header to a.out file"); exit (1); }
- lseek (file, hdr->aux_header_location, 0);
- if (write (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr))
- { perror ("Couldn't write auxiliary header to a.out file"); exit (1); }
-}
-
-/* Calculate the checksum of a SOM header record. */
-
-calculate_checksum (hdr)
- struct header *hdr;
-{
- int checksum, i, *ptr;
-
- checksum = 0; ptr = (int *) hdr;
-
- for (i = 0; i < sizeof (*hdr) / sizeof (int) - 1; i++)
- checksum ^= ptr[i];
-
- return (checksum);
-}
-
-/* Copy size bytes from the old file to the new one. */
-
-copy_file (old, new, size)
- int new, old;
- int size;
-{
- int len;
- int buffer[8192]; /* word aligned will be faster */
-
- for (; size > 0; size -= len)
- {
- len = min (size, sizeof (buffer));
- if (read (old, buffer, len) != len)
- { perror ("Read failure on a.out file"); exit (1); }
- if (write (new, buffer, len) != len)
- { perror ("Write failure in a.out file"); exit (1); }
- }
-}
-
-/* Copy the rest of the file, up to EOF. */
-
-copy_rest (old, new)
- int new, old;
-{
- int buffer[4096];
- int len;
-
- /* Copy bytes until end of file or error */
- while ((len = read (old, buffer, sizeof (buffer))) > 0)
- if (write (new, buffer, len) != len) break;
-
- if (len != 0)
- { perror ("Unable to copy the rest of the file"); exit (1); }
-}
-
-#ifdef DEBUG
-display_header (hdr, auxhdr)
- struct header *hdr;
- struct som_exec_auxhdr *auxhdr;
-{
- /* Display the header information (debug) */
- printf ("\n\nFILE HEADER\n");
- printf ("magic number %d \n", hdr->a_magic);
- printf ("text loc %.8x size %d \n", auxhdr->exec_tmem, auxhdr->exec_tsize);
- printf ("data loc %.8x size %d \n", auxhdr->exec_dmem, auxhdr->exec_dsize);
- printf ("entry %x \n", auxhdr->exec_entry);
- printf ("Bss segment size %u\n", auxhdr->exec_bsize);
- printf ("\n");
- printf ("data file loc %d size %d\n",
- auxhdr->exec_dfile, auxhdr->exec_dsize);
- printf ("som_length %d\n", hdr->som_length);
- printf ("unloadable sploc %d size %d\n",
- hdr->unloadable_sp_location, hdr->unloadable_sp_size);
-}
-#endif /* DEBUG */
diff --git a/src/unexmips.c b/src/unexmips.c
deleted file mode 100644
index cad42a17897..00000000000
--- a/src/unexmips.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/* Unexec for MIPS (including IRIS4D).
- 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.
-
- Copyright (C) 1988, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include <sys/types.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <varargs.h>
-
-#ifdef MACH
-
-#include <a.out.h>
-
-/* I don't know why this isn't defined. */
-#ifndef STYP_INIT
-#define STYP_INIT 0x80000000
-#endif
-
-/* I don't know why this isn't defined. */
-#ifndef _RDATA
-#define _RDATA ".rdata"
-#define STYP_RDATA 0x00000100
-#endif
-
-/* Small ("near") data section. */
-#ifndef _SDATA
-#define _SDATA ".sdata"
-#define STYP_SDATA 0x00000200
-#endif
-
-/* Small ("near") bss section. */
-#ifndef _SBSS
-#define _SBSS ".sbss"
-#define STYP_SBSS 0x00000400
-#endif
-
-/* We don't seem to have a sym.h or syms.h anywhere, so we'll do it the
- hard way. This stinks. */
-typedef struct {
- short magic;
- short vstamp;
- long ilineMax;
- struct { long foo, offset; } offsets[11];
-} HDRR, *pHDRR;
-
-#else /* not MACH */
-
-#include <filehdr.h>
-#include <aouthdr.h>
-#include <scnhdr.h>
-#include <sym.h>
-
-#endif /* not MACH */
-
-#if defined (IRIS_4D) || defined (sony)
-#include "getpagesize.h"
-#include <fcntl.h>
-#endif
-
-static void fatal_unexec ();
-static void 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 char *strerror ();
-#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 (%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 ();
- /* Casting to int avoids compiler error on NEWS-OS 5.0.2. */
- brk = (((int) (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, (char *)TEXT_START, hdr.aout.tsize,
- "writing text section to %s", new_name);
- WRITE (new, (char *)DATA_START, hdr.aout.dsize,
- "writing data 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);
- newsyms = hdr.aout.tsize + hdr.aout.dsize;
- symrel = newsyms - hdr.fhdr.f_symptr;
- hdr.fhdr.f_symptr = newsyms;
-#define symhdr ((pHDRR)buffer)
-#ifdef MACH
- for (i = 0; i < 11; i++)
- symhdr->offsets[i].offset += symrel;
-#else
- 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;
-#endif
-#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 successfully building the new a.out, mark it executable
- */
-
-static void
-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
- fprintf (stderr, "unexec: %s, ", strerror (errno));
- va_start (ap);
- _doprnt (s, ap, stderr);
- fputs (".\n", stderr);
- exit (1);
-}
diff --git a/src/unexnext.c b/src/unexnext.c
deleted file mode 100644
index 66f52fa0352..00000000000
--- a/src/unexnext.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/* Dump Emacs in macho format.
- Copyright (C) 1990, 1993 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#undef __STRICT_BSD__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <mach/mach.h>
-#include <mach-o/loader.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);
- }
- 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);
- }
- 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;
- struct section *sect;
-
- sect = (struct section *) 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
- */
- if (lseek(infd, the_header.sizeofcmds + sizeof(the_header),
- L_SET) < 0) {
- fatal_unexec("cannot seek input file");
- return (0);
- }
- 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/unexsni.c b/src/unexsni.c
deleted file mode 100644
index f8a6f01ed1d..00000000000
--- a/src/unexsni.c
+++ /dev/null
@@ -1,836 +0,0 @@
-/* Unexec for Siemens machines running Sinix (modified SVR4).
- Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992, 1993, 1994, 1995
- Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
-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.
- */
-
-/* Modified by wtien@urbana.mcd.mot.com of Motorola Inc.
- *
- * The above mechanism does not work if the unexeced ELF file is being
- * re-layout by other applications (such as `strip'). All the applications
- * that re-layout the internal of ELF will layout all sections in ascending
- * order of their file offsets. After the re-layout, the data2 section will
- * still be the LAST section in the section header vector, but its file offset
- * is now being pushed far away down, and causes part of it not to be mapped
- * in (ie. not covered by the load segment entry in PHDR vector), therefore
- * causes the new binary to fail.
- *
- * The solution is to modify the unexec algorithm to insert the new data2
- * section header right before the new bss section header, so their file
- * offsets will be in the ascending order. Since some of the section's (all
- * sections AFTER the bss section) indexes are now changed, we also need to
- * modify some fields to make them point to the right sections. This is done
- * by macro PATCH_INDEX. All the fields that need to be patched are:
- *
- * 1. ELF header e_shstrndx field.
- * 2. section header sh_link and sh_info field.
- * 3. symbol table entry st_shndx field.
- */
-
-/*
- * New modifications for Siemens Nixdorf's MIPS-based machines.
- * Marco.Walther@mch.sni.de
- *
- * The problem: Before the bss segment we have a so called sbss segment
- * (small bss) and maybe an sdata segment. These segments
- * must also be handled correct.
- *
- * /home1/marco/emacs/emacs-19.22/src
- * dump -hv temacs
- *
- * temacs:
- *
- * **** SECTION HEADER TABLE ****
- * [No] Type Flags Addr Offset Size Name
- * Link Info Adralgn Entsize
- *
- * [1] PBIT -A-- 0x4000f4 0xf4 0x13 .interp
- * 0 0 0x1 0
- *
- * [2] REGI -A-- 0x400108 0x108 0x18 .reginfo
- * 0 0 0x4 0x18
- *
- * [3] DYNM -A-- 0x400120 0x120 0xb8 .dynamic
- * 6 0 0x4 0x8
- *
- * [4] HASH -A-- 0x4001d8 0x1d8 0x8a0 .hash
- * 5 0 0x4 0x4
- *
- * [5] DYNS -A-- 0x400a78 0xa78 0x11f0 .dynsym
- * 6 2 0x4 0x10
- *
- * [6] STRT -A-- 0x401c68 0x1c68 0xbf9 .dynstr
- * 0 0 0x1 0
- *
- * [7] REL -A-- 0x402864 0x2864 0x18 .rel.dyn
- * 5 14 0x4 0x8
- *
- * [8] PBIT -AI- 0x402880 0x2880 0x60 .init
- * 0 0 0x10 0x1
- *
- * [9] PBIT -AI- 0x4028e0 0x28e0 0x1234 .plt
- * 0 0 0x4 0x4
- *
- * [10] PBIT -AI- 0x403b20 0x3b20 0xee400 .text
- * 0 0 0x20 0x1
- *
- * [11] PBIT -AI- 0x4f1f20 0xf1f20 0x60 .fini
- * 0 0 0x10 0x1
- *
- * [12] PBIT -A-- 0x4f1f80 0xf1f80 0xd90 .rdata
- * 0 0 0x10 0x1
- *
- * [13] PBIT -A-- 0x4f2d10 0xf2d10 0x17e0 .rodata
- * 0 0 0x10 0x1
- *
- * [14] PBIT WA-- 0x5344f0 0xf44f0 0x4b3e4 .data <<<<<
- * 0 0 0x10 0x1
- *
- * [15] PBIT WA-G 0x57f8d4 0x13f8d4 0x2a84 .got
- * 0 0 0x4 0x4
- *
- * [16] PBIT WA-G 0x582360 0x142360 0x10 .sdata <<<<<
- * 0 0 0x10 0x1
- *
- * [17] NOBI WA-G 0x582370 0x142370 0xb84 .sbss <<<<<
- * 0 0 0x4 0
- *
- * [18] NOBI WA-- 0x582f00 0x142370 0x27ec0 .bss <<<<<
- * 0 0 0x10 0x1
- *
- * [19] SYMT ---- 0 0x142370 0x10e40 .symtab
- * 20 1108 0x4 0x10
- *
- * [20] STRT ---- 0 0x1531b0 0xed9e .strtab
- * 0 0 0x1 0
- *
- * [21] STRT ---- 0 0x161f4e 0xb5 .shstrtab
- * 0 0 0x1 0
- *
- * [22] PBIT ---- 0 0x162003 0x28e2a .comment
- * 0 0 0x1 0x1
- *
- * [23] PBIT ---- 0 0x18ae2d 0x592 .debug
- * 0 0 0x1 0
- *
- * [24] PBIT ---- 0 0x18b3bf 0x80 .line
- * 0 0 0x1 0
- *
- * [25] MDBG ---- 0 0x18b440 0x60 .mdebug
- * 0 0 0x4 0
- *
- *
- * dump -hv emacs
- *
- * emacs:
- *
- * **** SECTION HEADER TABLE ****
- * [No] Type Flags Addr Offset Size Name
- * Link Info Adralgn Entsize
- *
- * [1] PBIT -A-- 0x4000f4 0xf4 0x13 .interp
- * 0 0 0x1 0
- *
- * [2] REGI -A-- 0x400108 0x108 0x18 .reginfo
- * 0 0 0x4 0x18
- *
- * [3] DYNM -A-- 0x400120 0x120 0xb8 .dynamic
- * 6 0 0x4 0x8
- *
- * [4] HASH -A-- 0x4001d8 0x1d8 0x8a0 .hash
- * 5 0 0x4 0x4
- *
- * [5] DYNS -A-- 0x400a78 0xa78 0x11f0 .dynsym
- * 6 2 0x4 0x10
- *
- * [6] STRT -A-- 0x401c68 0x1c68 0xbf9 .dynstr
- * 0 0 0x1 0
- *
- * [7] REL -A-- 0x402864 0x2864 0x18 .rel.dyn
- * 5 14 0x4 0x8
- *
- * [8] PBIT -AI- 0x402880 0x2880 0x60 .init
- * 0 0 0x10 0x1
- *
- * [9] PBIT -AI- 0x4028e0 0x28e0 0x1234 .plt
- * 0 0 0x4 0x4
- *
- * [10] PBIT -AI- 0x403b20 0x3b20 0xee400 .text
- * 0 0 0x20 0x1
- *
- * [11] PBIT -AI- 0x4f1f20 0xf1f20 0x60 .fini
- * 0 0 0x10 0x1
- *
- * [12] PBIT -A-- 0x4f1f80 0xf1f80 0xd90 .rdata
- * 0 0 0x10 0x1
- *
- * [13] PBIT -A-- 0x4f2d10 0xf2d10 0x17e0 .rodata
- * 0 0 0x10 0x1
- *
- * [14] PBIT WA-- 0x5344f0 0xf44f0 0x4b3e4 .data <<<<<
- * 0 0 0x10 0x1
- *
- * [15] PBIT WA-G 0x57f8d4 0x13f8d4 0x2a84 .got
- * 0 0 0x4 0x4
- *
- * [16] PBIT WA-G 0x582360 0x142360 0xb94 .sdata <<<<<
- * 0 0 0x10 0x1
- *
- * [17] PBIT WA-- 0x582f00 0x142f00 0x94100 .data <<<<<
- * 0 0 0x10 0x1
- *
- * [18] NOBI WA-G 0x617000 0x1d7000 0 .sbss <<<<<
- * 0 0 0x4 0
- *
- * [19] NOBI WA-- 0x617000 0x1d7000 0 .bss <<<<<
- * 0 0 0x4 0x1
- *
- * [20] SYMT ---- 0 0x1d7000 0x10e40 .symtab
- * 21 1109 0x4 0x10
- *
- * [21] STRT ---- 0 0x1e7e40 0xed9e .strtab
- * 0 0 0x1 0
- *
- * [22] STRT ---- 0 0x1f6bde 0xb5 .shstrtab
- * 0 0 0x1 0
- *
- * [23] PBIT ---- 0 0x1f6c93 0x28e2a .comment
- * 0 0 0x1 0x1
- *
- * [24] PBIT ---- 0 0x21fabd 0x592 .debug
- * 0 0 0x1 0
- *
- * [25] PBIT ---- 0 0x22004f 0x80 .line
- * 0 0 0x1 0
- *
- * [26] MDBG ---- 0 0x2200d0 0x60 .mdebug
- * 0 0 0x4 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)))
-
-#define PATCH_INDEX(n) \
- do { \
- if ((n) >= old_sbss_index) \
- (n) += 1 + (old_sdata_index ? 0 : 1); } while (0)
-
-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_Addr old_sbss_addr;
- Elf32_Word old_bss_size, new_data2_size;
- Elf32_Word old_sbss_size, new_data3_size;
- Elf32_Off new_data2_offset;
- Elf32_Off new_data3_offset;
- Elf32_Addr new_data2_addr;
- Elf32_Addr new_data3_addr;
-
- Elf32_Word old_sdata_size, new_sdata_size;
- int old_sdata_index = 0;
-
- int n, nn, old_data_index, new_data2_align;
- int old_bss_index;
- int old_sbss_index;
- int old_bss_padding;
- 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 .sbss section.
- */
-
- for (old_sbss_index = 1; old_sbss_index < old_file_h->e_shnum;
- old_sbss_index++)
- {
-#ifdef DEBUG
- fprintf (stderr, "Looking for .sbss - found %s\n",
- old_section_names + OLD_SECTION_H(old_sbss_index).sh_name);
-#endif
- if (!strcmp (old_section_names + OLD_SECTION_H(old_sbss_index).sh_name,
- ".sbss"))
- break;
- }
- if (old_sbss_index == old_file_h->e_shnum)
- fatal ("Can't find .sbss in %s.\n", old_name, 0);
-
- if (!strcmp(old_section_names + OLD_SECTION_H(old_sbss_index - 1).sh_name,
- ".sdata"))
- {
- old_sdata_index = old_sbss_index - 1;
- }
-
-
- /* Find the old .bss section.
- */
-
- 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);
-
- if (old_sbss_index != (old_bss_index - 1))
- fatal (".sbss should come immediately before .bss in %s.\n", old_name, 0);
-
- /* Figure out parameters of the new data3 and data2 sections.
- * Change the sbss and bss sections.
- */
-
- old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr;
- old_bss_size = OLD_SECTION_H(old_bss_index).sh_size;
-
- old_sbss_addr = OLD_SECTION_H(old_sbss_index).sh_addr;
- old_sbss_size = OLD_SECTION_H(old_sbss_index).sh_size;
-
- if (old_sdata_index)
- {
- old_sdata_size = OLD_SECTION_H(old_sdata_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
- if (old_sdata_index)
- {
- new_sdata_size = OLD_SECTION_H(old_sbss_index).sh_offset -
- OLD_SECTION_H(old_sdata_index).sh_offset + old_sbss_size;
- }
-
- new_data3_addr = old_sbss_addr;
- new_data3_size = old_sbss_size;
- new_data3_offset = OLD_SECTION_H(old_sbss_index).sh_offset;
-
- new_data2_addr = old_bss_addr;
- new_data2_size = new_bss_addr - old_bss_addr;
- new_data2_align = (new_data3_offset + old_sbss_size) %
- OLD_SECTION_H(old_bss_index).sh_addralign;
- new_data2_align = new_data2_align ?
- OLD_SECTION_H(old_bss_index).sh_addralign - new_data2_align :
- 0;
- new_data2_offset = new_data3_offset + old_sbss_size + new_data2_align;
-
- old_bss_padding = OLD_SECTION_H(old_bss_index).sh_offset -
- OLD_SECTION_H(old_sbss_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);
- fprintf (stderr, "old_sbss_index %d\n", old_sbss_index);
- fprintf (stderr, "old_sbss_addr %x\n", old_sbss_addr);
- fprintf (stderr, "old_sbss_size %x\n", old_sbss_size);
- if (old_sdata_index)
- {
- fprintf (stderr, "old_sdata_size %x\n", old_sdata_size);
- fprintf (stderr, "new_sdata_size %x\n", new_sdata_size);
- }
- else
- {
- fprintf (stderr, "new_data3_addr %x\n", new_data3_addr);
- fprintf (stderr, "new_data3_size %x\n", new_data3_size);
- fprintf (stderr, "new_data3_offset %x\n", new_data3_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 +
- ((1 + (old_sdata_index ? 0 : 1)) * old_file_h->e_shentsize) +
- new_data2_size + new_data3_size + new_data2_align;
-
- 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 +
- new_data2_align +
- new_data3_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);
-
- /* Modify the e_shstrndx if necessary. */
- PATCH_INDEX (new_file_h->e_shstrndx);
-
- /* Fix up file header. We'll add one section. Section header is
- * further away now.
- */
-
- new_file_h->e_shoff += new_data2_size + new_data2_align + new_data3_size;
- new_file_h->e_shnum += 1 + (old_sdata_index ? 0 : 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 ((OLD_SECTION_H (old_sbss_index)).sh_addralign > alignment)
- alignment = OLD_SECTION_H (old_sbss_index).sh_addralign;
-
- /* Supposedly this condition is okay for the SGI. */
-#if 0
- 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);
-#endif
-
- 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_data2_align +
- new_data3_size;
- NEW_PROGRAM_H(n).p_memsz = NEW_PROGRAM_H(n).p_filesz;
-
-#if 1 /* 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_data3_addr)
- NEW_PROGRAM_H(n).p_vaddr += new_data2_size - old_bss_size +
- new_data3_size - old_sbss_size;
-
- if (NEW_PROGRAM_H(n).p_offset >= new_data3_offset)
- NEW_PROGRAM_H(n).p_offset += new_data2_size + new_data2_align +
- new_data3_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 (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);
-
- /* Walk through all section headers, insert the new data2 section right
- before the new bss section. */
- for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
- {
- caddr_t src;
-
- if (n == old_sbss_index)
-
- /* If it is sbss section, insert the new data3 section before it. */
- {
- /* Steal the data section header for this data3 section. */
- if (!old_sdata_index)
- {
- memcpy (&NEW_SECTION_H(nn), &OLD_SECTION_H(old_data_index),
- new_file_h->e_shentsize);
-
- NEW_SECTION_H(nn).sh_addr = new_data3_addr;
- NEW_SECTION_H(nn).sh_offset = new_data3_offset;
- NEW_SECTION_H(nn).sh_size = new_data3_size;
- NEW_SECTION_H(nn).sh_flags = OLD_SECTION_H(n).sh_flags;
- /* Use the sbss section's alignment. This will assure that the
- new data3 section always be placed in the same spot as the old
- sbss section by any other application. */
- NEW_SECTION_H(nn).sh_addralign = OLD_SECTION_H(n).sh_addralign;
-
- /* Now copy over what we have in the memory now. */
- memcpy (NEW_SECTION_H(nn).sh_offset + new_base,
- (caddr_t) OLD_SECTION_H(n).sh_addr,
- new_data3_size);
- /* the new .data2 section should also come before the
- * new .sbss section */
- nn += 2;
- }
- else
- {
- /* We always have a .sdata section: append the contents of the
- * old .sbss section.
- */
- memcpy (new_data3_offset + new_base,
- (caddr_t) OLD_SECTION_H(n).sh_addr,
- new_data3_size);
- nn ++;
- }
- }
- else if (n == old_bss_index)
-
- /* If it is bss section, insert the new data2 section before it. */
- {
- Elf32_Word tmp_align;
- Elf32_Addr tmp_addr;
-
- tmp_align = OLD_SECTION_H(n).sh_addralign;
- tmp_addr = OLD_SECTION_H(n).sh_addr;
-
- nn -= 2;
- /* Steal the data section header for this data2 section. */
- memcpy (&NEW_SECTION_H(nn), &OLD_SECTION_H(old_data_index),
- new_file_h->e_shentsize);
-
- NEW_SECTION_H(nn).sh_addr = new_data2_addr;
- NEW_SECTION_H(nn).sh_offset = new_data2_offset;
- NEW_SECTION_H(nn).sh_size = new_data2_size;
- /* Use the bss section's alignment. This will assure that the
- new data2 section always be placed in the same spot as the old
- bss section by any other application. */
- NEW_SECTION_H(nn).sh_addralign = tmp_align;
-
- /* Now copy over what we have in the memory now. */
- memcpy (NEW_SECTION_H(nn).sh_offset + new_base,
- (caddr_t) tmp_addr, new_data2_size);
- nn += 2;
- }
-
- memcpy (&NEW_SECTION_H(nn), &OLD_SECTION_H(n),
- old_file_h->e_shentsize);
-
- if (old_sdata_index && n == old_sdata_index)
- /* The old .sdata section has now a new size */
- NEW_SECTION_H(nn).sh_size = new_sdata_size;
-
- /* The new bss section's size is zero, and its file offset and virtual
- address should be off by NEW_DATA2_SIZE. */
- if (n == old_sbss_index)
- {
- /* NN should be `old_sbss_index + 2' at this point. */
- NEW_SECTION_H(nn).sh_offset += new_data2_size + new_data2_align +
- new_data3_size;
- NEW_SECTION_H(nn).sh_addr += new_data2_size + new_data2_align +
- new_data3_size;
- /* Let the new bss section address alignment be the same as the
- section address alignment followed the old bss section, so
- this section will be placed in exactly the same place. */
- NEW_SECTION_H(nn).sh_addralign =
- OLD_SECTION_H(nn + (old_sdata_index ? 1 : 0)).sh_addralign;
- NEW_SECTION_H(nn).sh_size = 0;
- }
- else if (n == old_bss_index)
- {
- /* NN should be `old_bss_index + 2' at this point. */
- NEW_SECTION_H(nn).sh_offset += new_data2_size + new_data2_align +
- new_data3_size - old_bss_padding;
- NEW_SECTION_H(nn).sh_addr += new_data2_size;
- /* Let the new bss section address alignment be the same as the
- section address alignment followed the old bss section, so
- this section will be placed in exactly the same place. */
- NEW_SECTION_H(nn).sh_addralign =
- OLD_SECTION_H((nn - (old_sdata_index ? 0 : 1))).sh_addralign;
- NEW_SECTION_H(nn).sh_size = 0;
- }
- /* Any section that was original placed AFTER the bss section should now
- be off by NEW_DATA2_SIZE. */
- else if (NEW_SECTION_H(nn).sh_offset >= new_data3_offset)
- NEW_SECTION_H(nn).sh_offset += new_data2_size +
- new_data2_align +
- new_data3_size -
- old_bss_padding;
-
- /* If any section hdr refers to the section after the new .data
- section, make it refer to next one because we have inserted
- a new section in between. */
-
- PATCH_INDEX(NEW_SECTION_H(nn).sh_link);
- PATCH_INDEX(NEW_SECTION_H(nn).sh_info);
-
- /* Now, start to copy the content of sections. */
- if (NEW_SECTION_H(nn).sh_type == SHT_NULL
- || NEW_SECTION_H(nn).sh_type == SHT_NOBITS)
- continue;
-
- /* Write out the sections. .data, .data1 and .sdata get copied from
- * the current process instead of the old file.
- */
- if (!strcmp (old_section_names + OLD_SECTION_H(n).sh_name, ".data") ||
- !strcmp (old_section_names + OLD_SECTION_H(n).sh_name, ".data1") ||
- (old_sdata_index && (n == old_sdata_index)))
- src = (caddr_t) OLD_SECTION_H(n).sh_addr;
- else
- src = old_base + OLD_SECTION_H(n).sh_offset;
-
- memcpy (NEW_SECTION_H(nn).sh_offset + new_base, src,
- ((n == old_sdata_index) ?
- old_sdata_size :
- NEW_SECTION_H(nn).sh_size));
-
- /* If it is the symbol table, its st_shndx field needs to be patched. */
- if (NEW_SECTION_H(nn).sh_type == SHT_SYMTAB
- || NEW_SECTION_H(nn).sh_type == SHT_DYNSYM)
- {
- Elf32_Shdr *spt = &NEW_SECTION_H(nn);
- unsigned int num = spt->sh_size / spt->sh_entsize;
- Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H(nn).sh_offset +
- new_base);
- for (; num--; sym++)
- {
- if ((sym->st_shndx == SHN_UNDEF)
- || (sym->st_shndx == SHN_ABS)
- || (sym->st_shndx == SHN_COMMON))
- continue;
-
- PATCH_INDEX(sym->st_shndx);
- }
- }
- }
-
- /* 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/unexsunos4.c b/src/unexsunos4.c
deleted file mode 100644
index bdc20336282..00000000000
--- a/src/unexsunos4.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/* Unexec for Sunos 4 using shared libraries.
- Copyright (C) 1990, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Contributed by Viktor Dukhovni. */
-/*
- * Unexec for Berkeley a.out format + SUNOS shared libraries
- * The unexeced executable contains the __DYNAMIC area from the
- * original text file, and then the rest of data + bss + malloced area of
- * the current process. (The __DYNAMIC area is at the top of the process
- * data segment, we use "data_start" defined externally to mark the start
- * of the "real" data segment.)
- *
- * For programs that want to remap some of the data segment read only
- * a run_time_remap is provided. This attempts to remap largest area starting
- * and ending on page boundaries between "data_start" and "bndry"
- * For this it to figure out where the text file is located. A path search
- * is attempted after trying argv[0] and if all fails we simply do not remap
- *
- * One feature of run_time_remap () is mandatory: reseting the break.
- *
- * Note that we can no longer map data into the text segment, as this causes
- * the __DYNAMIC struct to become read only, breaking the runtime loader.
- * Thus we no longer need to mess with a private crt0.c, the standard one
- * will do just fine, since environ can live in the writable area between
- * __DYNAMIC and data_start, just make sure that pre-crt0.o (the name
- * is somewhat abused here) is loaded first!
- *
- */
-#include <sys/param.h>
-#include <sys/mman.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <stdio.h>
-#include <a.out.h>
-
-/* Do this after the above #include's in case a configuration file wants
- to define things for this file based on what <a.out.h> defines. */
-#ifdef emacs
-#include <config.h>
-#endif
-
-#if defined (SUNOS4) || defined (__FreeBSD__) || defined (__NetBSD__)
-#define UNDO_RELOCATION
-#endif
-
-#ifdef UNDO_RELOCATION
-#include <link.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-/* NetBSD needs this bit, but SunOS does not have it. */
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif
-
-
-/*
- * for programs other than emacs
- * define data_start + initialized here, and make sure
- * this object is loaded first!
- * emacs will define these elsewhere, and load the object containing
- * data_start (pre-crt0.o or firstfile.o?) first!
- * The custom crt0.o *must not* be loaded!
- */
-#ifndef emacs
- static int data_start = 0;
- static int initialized = 0;
-#else
- extern int initialized;
- extern unsigned data_start;
- extern int pureptr;
-#endif
-
-extern char *getenv ();
-static unsigned brk_value;
-static struct exec nhdr;
-static int rd_only_len;
-static long cookie;
-
-
-unexec (new_name, a_name, bndry, bss_start, entry)
- char *new_name, *a_name;
- unsigned bndry, bss_start, entry;
-{
- int fd, new;
- char *old;
- struct exec ohdr; /* Allocate on the stack, not needed in the next life */
- struct stat stat;
-
- if ((fd = open (a_name, O_RDONLY)) < 0)
- {
- fprintf (stderr, "%s: open: ", a_name);
- perror (a_name);
- exit (1);
- }
- if ((new = open (new_name, O_WRONLY | O_CREAT, 0666)) == -1)
- {
- fprintf (stderr, "%s: open: ", a_name);
- perror (new_name);
- exit (1);
- }
-
- if ((fstat (fd, &stat) == -1))
- {
- fprintf (stderr, "%s: ", a_name);
- perror ("fstat");
- exit (1);
- }
-
- old = (char *)mmap (0, stat.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0);
- if (old == (char *)-1)
- {
- fprintf (stderr, "%s: ", a_name);
- perror ("mmap");
- exit (1);
- }
- close (fd);
-
- nhdr = ohdr = (*(struct exec *)old);
-
-
- /*
- * Remember a magic cookie so we know we've got the right binary
- * when remapping.
- */
- cookie = time (0);
-
- /* Save the break, it is reset to &_end (by ld.so?). */
- brk_value = (unsigned) sbrk (0);
-
- /*
- * Round up data start to a page boundary (Lose if not a 2 power!)
- */
- data_start = ((((int)&data_start) - 1) & ~(N_PAGSIZ (nhdr) - 1)) + N_PAGSIZ (nhdr);
-
- /*
- * Round down read only pages to a multiple of the page size
- */
- if (bndry)
- rd_only_len = ((int)bndry & ~(N_PAGSIZ (nhdr) - 1)) - data_start;
-
-#ifndef emacs
- /* Have to do this some time before dumping the data */
- initialized = 1;
-#endif
-
- /* Handle new data and bss sizes and optional new entry point.
- No one actually uses bss_start and entry, but tradition compels
- one to support them.
- Could complain if bss_start > brk_value,
- but the caller is *supposed* to know what she is doing. */
- nhdr.a_data = (bss_start ? bss_start : brk_value) - N_DATADDR (nhdr);
- nhdr.a_bss = bss_start ? brk_value - bss_start : 0;
- if (entry)
- nhdr.a_entry = entry;
-
- /*
- * Write out the text segment with new header
- * Dynamic executables are ZMAGIC with N_TXTOFF==0 and the header
- * part of the text segment, but no need to rely on this.
- * So write the TEXT first, then go back replace the header.
- * Doing it in the other order is less general!
- */
- lseek (new, N_TXTOFF (nhdr), L_SET);
- write (new, old + N_TXTOFF (ohdr), N_TXTOFF (ohdr) + ohdr.a_text);
- lseek (new, 0L, L_SET);
- write (new, &nhdr, sizeof (nhdr));
-
- /*
- * Write out the head of the old data segment from the file not
- * from core, this has the unresolved __DYNAMIC relocation data
- * we need to reload
- */
- lseek (new, N_DATOFF (nhdr), L_SET);
- write (new, old + N_DATOFF (ohdr), (int)&data_start - N_DATADDR (ohdr));
-
- /*
- * Copy the rest of the data from core
- */
- write (new, &data_start, N_BSSADDR (nhdr) - (int)&data_start);
-
- /*
- * Copy the symbol table and line numbers
- */
- lseek (new, N_TRELOFF (nhdr), L_SET);
- write (new, old + N_TRELOFF (ohdr), stat.st_size - N_TRELOFF (ohdr));
-
- /* Some other BSD systems use this file.
- We don't know whether this change is right for them. */
-#ifdef UNDO_RELOCATION
- /* Undo the relocations done at startup by ld.so.
- It will do these relocations again when we start the dumped Emacs.
- Doing them twice gives incorrect results. */
- {
- unsigned long daddr = N_DATADDR (ohdr);
- unsigned long rel, erel;
-#ifdef SUNOS4
-#ifdef SUNOS4_SHARED_LIBRARIES
- extern struct link_dynamic _DYNAMIC;
-
- /* SunOS4.x's ld_rel is relative to N_TXTADDR. */
- if (!ohdr.a_dynamic)
- /* This was statically linked. */
- rel = erel = 0;
- else if (_DYNAMIC.ld_version < 2)
- {
- rel = _DYNAMIC.ld_un.ld_1->ld_rel + N_TXTADDR (ohdr);
- erel = _DYNAMIC.ld_un.ld_1->ld_hash + N_TXTADDR (ohdr);
- }
- else
- {
- rel = _DYNAMIC.ld_un.ld_2->ld_rel + N_TXTADDR (ohdr);
- erel = _DYNAMIC.ld_un.ld_2->ld_hash + N_TXTADDR (ohdr);
- }
-#else /* not SUNOS4_SHARED_LIBRARIES */
- rel = erel = 0;
-#endif /* not SUNOS4_SHARED_LIBRARIES */
-#ifdef sparc
-#define REL_INFO_TYPE struct reloc_info_sparc
-#else
-#define REL_INFO_TYPE struct relocation_info
-#endif /* sparc */
-#define REL_TARGET_ADDRESS(r) (((REL_INFO_TYPE *)(r))->r_address)
-#endif /* SUNOS4 */
-#if defined (__FreeBSD__) || defined (__NetBSD__)
- extern struct _dynamic _DYNAMIC;
-
- /* FreeBSD's LD_REL is a virtual address itself. */
- rel = LD_REL (&_DYNAMIC);
- erel = rel + LD_RELSZ (&_DYNAMIC);
-#define REL_INFO_TYPE struct relocation_info
-#define REL_TARGET_ADDRESS(r) (((REL_INFO_TYPE *)(r))->r_address)
-#endif
-
- for (; rel < erel; rel += sizeof (REL_INFO_TYPE))
- {
- /* This is the virtual address where ld.so will do relocation. */
- unsigned long target = REL_TARGET_ADDRESS (rel);
- /* This is the offset in the data segment. */
- unsigned long segoffset = target - daddr;
-
- /* If it is located below data_start, we have to do nothing here,
- because the old data has been already written to the location. */
- if (target < (unsigned long)&data_start)
- continue;
-
- lseek (new, N_DATOFF (nhdr) + segoffset, L_SET);
- write (new, old + N_DATOFF (ohdr) + segoffset, sizeof (unsigned long));
- }
- }
-#endif /* UNDO_RELOCATION */
-
- fchmod (new, 0755);
-}
-
-void
-run_time_remap (progname)
- char *progname;
-{
- char aout[MAXPATHLEN];
- register char *path, *p;
-
- /* Just in case */
- if (!initialized)
- return;
-
- /* Restore the break */
- brk ((char *) brk_value);
-
- /* If nothing to remap: we are done! */
- if (rd_only_len == 0)
- return;
-
- /*
- * Attempt to find the executable
- * First try argv[0], will almost always succeed as shells tend to give
- * the full path from the hash list rather than using execvp ()
- */
- if (is_it (progname))
- return;
-
- /*
- * If argv[0] is a full path and does not exist, not much sense in
- * searching further
- */
- if (strchr (progname, '/'))
- return;
-
- /*
- * Try to search for argv[0] on the PATH
- */
- path = getenv ("PATH");
- if (path == NULL)
- return;
-
- while (*path)
- {
- /* copy through ':' or end */
- for (p = aout; *p = *path; ++p, ++path)
- if (*p == ':')
- {
- ++path; /* move past ':' */
- break;
- }
- *p++ = '/';
- strcpy (p, progname);
- /*
- * aout is a candidate full path name
- */
- if (is_it (aout))
- return;
- }
-}
-
-is_it (filename)
- char *filename;
-{
- int fd;
- long filenames_cookie;
- struct exec hdr;
-
- /*
- * Open an executable and check for a valid header!
- * Can't bcmp the header with what we had, it may have been stripped!
- * so we may save looking at non executables with the same name, mostly
- * directories.
- */
- fd = open (filename, O_RDONLY);
- if (fd != -1)
- {
- if (read (fd, &hdr, sizeof (hdr)) == sizeof (hdr)
- && !N_BADMAG (hdr) && N_DATOFF (hdr) == N_DATOFF (nhdr)
- && N_TRELOFF (hdr) == N_TRELOFF (nhdr))
- {
- /* compare cookies */
- lseek (fd, N_DATOFF (hdr) + (int)&cookie - N_DATADDR (hdr), L_SET);
- read (fd, &filenames_cookie, sizeof (filenames_cookie));
- if (filenames_cookie == cookie)
- { /* Eureka */
-
- /*
- * Do the mapping
- * The PROT_EXEC may not be needed, but it is safer this way.
- * should the shared library decide to indirect through
- * addresses in the data segment not part of __DYNAMIC
- */
- mmap ((char *) data_start, rd_only_len, PROT_READ | PROT_EXEC,
- MAP_FILE | MAP_SHARED | MAP_FIXED, fd,
- N_DATOFF (hdr) + data_start - N_DATADDR (hdr));
- close (fd);
- return 1;
- }
- }
- close (fd);
- }
- return 0;
-}
diff --git a/src/unexw32.c b/src/unexw32.c
deleted file mode 100644
index d449a79eaa0..00000000000
--- a/src/unexw32.c
+++ /dev/null
@@ -1,584 +0,0 @@
-/* unexec for GNU Emacs on Windows NT.
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
- Geoff Voelker (voelker@cs.washington.edu) 8-12-94
-*/
-
-#include <stdlib.h> /* _fmode */
-#include <stdio.h>
-#include <fcntl.h>
-#include <windows.h>
-
-extern BOOL ctrl_c_handler (unsigned long type);
-
-#include "w32heap.h"
-
-/* A convenient type for keeping all the info about a mapped file together. */
-typedef struct file_data {
- char *name;
- unsigned long size;
- HANDLE file;
- HANDLE file_mapping;
- unsigned char *file_base;
-} file_data;
-
-/* Basically, our "initialized" flag. */
-BOOL need_to_recreate_heap = FALSE;
-
-/* So we can find our heap in the file to recreate it. */
-unsigned long heap_index_in_executable = 0;
-
-void open_input_file (file_data *p_file, char *name);
-void open_output_file (file_data *p_file, char *name, unsigned long size);
-void close_file_data (file_data *p_file);
-
-void get_section_info (file_data *p_file);
-void copy_executable_and_dump_data_section (file_data *, file_data *);
-void dump_bss_and_heap (file_data *p_infile, file_data *p_outfile);
-
-/* Cached info about the .data section in the executable. */
-PUCHAR data_start_va = 0;
-DWORD data_start_file = 0;
-DWORD data_size = 0;
-
-/* Cached info about the .bss section in the executable. */
-PUCHAR bss_start = 0;
-DWORD bss_size = 0;
-
-#ifdef HAVE_NTGUI
-HINSTANCE hinst = NULL;
-HINSTANCE hprevinst = NULL;
-LPSTR lpCmdLine = "";
-int nCmdShow = 0;
-#endif /* HAVE_NTGUI */
-
-/* Startup code for running on NT. When we are running as the dumped
- version, we need to bootstrap our heap and .bss section into our
- address space before we can actually hand off control to the startup
- code supplied by NT (primarily because that code relies upon malloc ()). */
-void
-_start (void)
-{
- extern void mainCRTStartup (void);
-
- /* Cache system info, e.g., the NT page size. */
- cache_system_info ();
-
- /* If we're a dumped version of emacs then we need to recreate
- our heap and play tricks with our .bss section. Do this before
- start up. (WARNING: Do not put any code before this section
- that relies upon malloc () and runs in the dumped version. It
- won't work.) */
- if (need_to_recreate_heap)
- {
- char executable_path[MAX_PATH];
-
- if (GetModuleFileName (NULL, executable_path, MAX_PATH) == 0)
- {
- printf ("Failed to find path for executable.\n");
- exit (1);
- }
- recreate_heap (executable_path);
- need_to_recreate_heap = FALSE;
- }
-
- /* The default behavior is to treat files as binary and patch up
- text files appropriately, in accordance with the MSDOS code. */
- _fmode = O_BINARY;
-
- /* This prevents ctrl-c's in shells running while we're suspended from
- having us exit. */
- SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrl_c_handler, TRUE);
-
- /* Invoke the NT CRT startup routine now that our housecleaning
- is finished. */
-#ifdef HAVE_NTGUI
- /* determine WinMain args like crt0.c does */
- hinst = GetModuleHandle(NULL);
- lpCmdLine = GetCommandLine();
- nCmdShow = SW_SHOWDEFAULT;
-#endif
- mainCRTStartup ();
-}
-
-/* Dump out .data and .bss sections into a new executable. */
-void
-unexec (char *new_name, char *old_name, void *start_data, void *start_bss,
- void *entry_address)
-{
- file_data in_file, out_file;
- char out_filename[MAX_PATH], in_filename[MAX_PATH];
- unsigned long size;
- char *ptr;
-
- /* Make sure that the input and output filenames have the
- ".exe" extension...patch them up if they don't. */
- strcpy (in_filename, old_name);
- ptr = in_filename + strlen (in_filename) - 4;
- if (strcmp (ptr, ".exe"))
- strcat (in_filename, ".exe");
-
- strcpy (out_filename, new_name);
- ptr = out_filename + strlen (out_filename) - 4;
- if (strcmp (ptr, ".exe"))
- strcat (out_filename, ".exe");
-
- printf ("Dumping from %s\n", in_filename);
- printf (" to %s\n", out_filename);
-
- /* We need to round off our heap to NT's allocation unit (64KB). */
- round_heap (get_allocation_unit ());
-
- /* Open the undumped executable file. */
- open_input_file (&in_file, in_filename);
-
- /* Get the interesting section info, like start and size of .bss... */
- get_section_info (&in_file);
-
- /* The size of the dumped executable is the size of the original
- executable plus the size of the heap and the size of the .bss section. */
- heap_index_in_executable = (unsigned long)
- round_to_next ((unsigned char *) in_file.size, get_allocation_unit ());
- size = heap_index_in_executable + get_committed_heap_size () + bss_size;
- open_output_file (&out_file, out_filename, size);
-
- /* Set the flag (before dumping). */
- need_to_recreate_heap = TRUE;
-
- copy_executable_and_dump_data_section (&in_file, &out_file);
- dump_bss_and_heap (&in_file, &out_file);
-
- close_file_data (&in_file);
- close_file_data (&out_file);
-}
-
-
-/* File handling. */
-
-
-void
-open_input_file (file_data *p_file, char *filename)
-{
- HANDLE file;
- HANDLE file_mapping;
- void *file_base;
- unsigned long size, upper_size;
-
- file = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- if (file == INVALID_HANDLE_VALUE)
- {
- printf ("Failed to open %s (%d)...bailing.\n",
- filename, GetLastError ());
- exit (1);
- }
-
- size = GetFileSize (file, &upper_size);
- file_mapping = CreateFileMapping (file, NULL, PAGE_READONLY,
- 0, size, NULL);
- if (!file_mapping)
- {
- printf ("Failed to create file mapping of %s (%d)...bailing.\n",
- filename, GetLastError ());
- exit (1);
- }
-
- file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size);
- if (file_base == 0)
- {
- printf ("Failed to map view of file of %s (%d)...bailing.\n",
- filename, GetLastError ());
- exit (1);
- }
-
- p_file->name = filename;
- p_file->size = size;
- p_file->file = file;
- p_file->file_mapping = file_mapping;
- p_file->file_base = file_base;
-}
-
-void
-open_output_file (file_data *p_file, char *filename, unsigned long size)
-{
- HANDLE file;
- HANDLE file_mapping;
- void *file_base;
- int i;
-
- file = CreateFile (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
- CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
- if (file == INVALID_HANDLE_VALUE)
- {
- i = GetLastError ();
- printf ("open_output_file: Failed to open %s (%d).\n",
- filename, i);
- exit (1);
- }
-
- file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE,
- 0, size, NULL);
- if (!file_mapping)
- {
- i = GetLastError ();
- printf ("open_output_file: Failed to create file mapping of %s (%d).\n",
- filename, i);
- exit (1);
- }
-
- file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size);
- if (file_base == 0)
- {
- i = GetLastError ();
- printf ("open_output_file: Failed to map view of file of %s (%d).\n",
- filename, i);
- exit (1);
- }
-
- p_file->name = filename;
- p_file->size = size;
- p_file->file = file;
- p_file->file_mapping = file_mapping;
- p_file->file_base = file_base;
-}
-
-/* Close the system structures associated with the given file. */
-static void
-close_file_data (file_data *p_file)
-{
- UnmapViewOfFile (p_file->file_base);
- CloseHandle (p_file->file_mapping);
- CloseHandle (p_file->file);
-}
-
-
-/* Routines to manipulate NT executable file sections. */
-
-static void
-get_bss_info_from_map_file (file_data *p_infile, PUCHAR *p_bss_start,
- DWORD *p_bss_size)
-{
- int n, start, len;
- char map_filename[MAX_PATH];
- char buffer[256];
- FILE *map;
-
- /* Overwrite the .exe extension on the executable file name with
- the .map extension. */
- strcpy (map_filename, p_infile->name);
- n = strlen (map_filename) - 3;
- strcpy (&map_filename[n], "map");
-
- map = fopen (map_filename, "r");
- if (!map)
- {
- printf ("Failed to open map file %s, error %d...bailing out.\n",
- map_filename, GetLastError ());
- exit (-1);
- }
-
- while (fgets (buffer, sizeof (buffer), map))
- {
- if (!(strstr (buffer, ".bss") && strstr (buffer, "DATA")))
- continue;
- n = sscanf (buffer, " %*d:%x %x", &start, &len);
- if (n != 2)
- {
- printf ("Failed to scan the .bss section line:\n%s", buffer);
- exit (-1);
- }
- break;
- }
- *p_bss_start = (PUCHAR) start;
- *p_bss_size = (DWORD) len;
-}
-
-static unsigned long
-get_section_size (PIMAGE_SECTION_HEADER p_section)
-{
- /* The section size is in different locations in the different versions. */
- switch (get_w32_minor_version ())
- {
- case 10:
- return p_section->SizeOfRawData;
- default:
- return p_section->Misc.VirtualSize;
- }
-}
-
-/* Flip through the executable and cache the info necessary for dumping. */
-static void
-get_section_info (file_data *p_infile)
-{
- PIMAGE_DOS_HEADER dos_header;
- PIMAGE_NT_HEADERS nt_header;
- PIMAGE_SECTION_HEADER section, data_section;
- unsigned char *ptr;
- int i;
-
- dos_header = (PIMAGE_DOS_HEADER) p_infile->file_base;
- if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
- {
- printf ("Unknown EXE header in %s...bailing.\n", p_infile->name);
- exit (1);
- }
- nt_header = (PIMAGE_NT_HEADERS) (((unsigned long) dos_header) +
- dos_header->e_lfanew);
- if (nt_header == NULL)
- {
- printf ("Failed to find IMAGE_NT_HEADER in %s...bailing.\n",
- p_infile->name);
- exit (1);
- }
-
- /* Check the NT header signature ... */
- if (nt_header->Signature != IMAGE_NT_SIGNATURE)
- {
- printf ("Invalid IMAGE_NT_SIGNATURE 0x%x in %s...bailing.\n",
- nt_header->Signature, p_infile->name);
- }
-
- /* Flip through the sections for .data and .bss ... */
- section = (PIMAGE_SECTION_HEADER) IMAGE_FIRST_SECTION (nt_header);
- for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
- {
- if (!strcmp (section->Name, ".bss"))
- {
- /* The .bss section. */
- ptr = (char *) nt_header->OptionalHeader.ImageBase +
- section->VirtualAddress;
- bss_start = ptr;
- bss_size = get_section_size (section);
- }
- if (!strcmp (section->Name, ".data"))
- {
- /* From lastfile.c */
- extern char my_edata[];
-
- /* The .data section. */
- data_section = section;
- ptr = (char *) nt_header->OptionalHeader.ImageBase +
- section->VirtualAddress;
- data_start_va = ptr;
- data_start_file = section->PointerToRawData;
-
- /* We want to only write Emacs data back to the executable,
- not any of the library data (if library data is included,
- then a dumped Emacs won't run on system versions other
- than the one Emacs was dumped on). */
- data_size = my_edata - data_start_va;
- }
- section++;
- }
-
- if (!bss_start && !bss_size)
- {
- /* Starting with MSVC 4.0, the .bss section has been eliminated
- and appended virtually to the end of the .data section. Our
- only hint about where the .bss section starts in the address
- comes from the SizeOfRawData field in the .data section
- header. Unfortunately, this field is only approximate, as it
- is a rounded number and is typically rounded just beyond the
- start of the .bss section. To find the start and size of the
- .bss section exactly, we have to peek into the map file. */
- get_bss_info_from_map_file (p_infile, &ptr, &bss_size);
- bss_start = ptr + nt_header->OptionalHeader.ImageBase
- + data_section->VirtualAddress;
- }
-}
-
-
-/* The dump routines. */
-
-static void
-copy_executable_and_dump_data_section (file_data *p_infile,
- file_data *p_outfile)
-{
- unsigned char *data_file, *data_va;
- unsigned long size, index;
-
- /* Get a pointer to where the raw data should go in the executable file. */
- data_file = (char *) p_outfile->file_base + data_start_file;
-
- /* Get a pointer to the raw data in our address space. */
- data_va = data_start_va;
-
- size = (DWORD) data_file - (DWORD) p_outfile->file_base;
- printf ("Copying executable up to data section...\n");
- printf ("\t0x%08x Offset in input file.\n", 0);
- printf ("\t0x%08x Offset in output file.\n", 0);
- printf ("\t0x%08x Size in bytes.\n", size);
- memcpy (p_outfile->file_base, p_infile->file_base, size);
-
- size = data_size;
- printf ("Dumping .data section...\n");
- printf ("\t0x%08x Address in process.\n", data_va);
- printf ("\t0x%08x Offset in output file.\n",
- data_file - p_outfile->file_base);
- printf ("\t0x%08x Size in bytes.\n", size);
- memcpy (data_file, data_va, size);
-
- index = (DWORD) data_file + size - (DWORD) p_outfile->file_base;
- size = p_infile->size - index;
- printf ("Copying rest of executable...\n");
- printf ("\t0x%08x Offset in input file.\n", index);
- printf ("\t0x%08x Offset in output file.\n", index);
- printf ("\t0x%08x Size in bytes.\n", size);
- memcpy ((char *) p_outfile->file_base + index,
- (char *) p_infile->file_base + index, size);
-}
-
-static void
-dump_bss_and_heap (file_data *p_infile, file_data *p_outfile)
-{
- unsigned char *heap_data, *bss_data;
- unsigned long size, index;
-
- printf ("Dumping heap into executable...\n");
-
- index = heap_index_in_executable;
- size = get_committed_heap_size ();
- heap_data = get_heap_start ();
-
- printf ("\t0x%08x Heap start in process.\n", heap_data);
- printf ("\t0x%08x Heap offset in executable.\n", index);
- printf ("\t0x%08x Heap size in bytes.\n", size);
-
- memcpy ((PUCHAR) p_outfile->file_base + index, heap_data, size);
-
- printf ("Dumping .bss into executable...\n");
-
- index += size;
- size = bss_size;
- bss_data = bss_start;
-
- printf ("\t0x%08x BSS start in process.\n", bss_data);
- printf ("\t0x%08x BSS offset in executable.\n", index);
- printf ("\t0x%08x BSS size in bytes.\n", size);
- memcpy ((char *) p_outfile->file_base + index, bss_data, size);
-}
-
-
-/* Reload and remap routines. */
-
-
-/* Load the dumped .bss section into the .bss area of our address space. */
-void
-read_in_bss (char *filename)
-{
- HANDLE file;
- unsigned long size, index, n_read, total_read;
- char buffer[512], *bss;
- int i;
-
- file = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- if (file == INVALID_HANDLE_VALUE)
- {
- i = GetLastError ();
- exit (1);
- }
-
- /* Seek to where the .bss section is tucked away after the heap... */
- index = heap_index_in_executable + get_committed_heap_size ();
- if (SetFilePointer (file, index, NULL, FILE_BEGIN) == 0xFFFFFFFF)
- {
- i = GetLastError ();
- exit (1);
- }
-
-
- /* Ok, read in the saved .bss section and initialize all
- uninitialized variables. */
- if (!ReadFile (file, bss_start, bss_size, &n_read, NULL))
- {
- i = GetLastError ();
- exit (1);
- }
-
- CloseHandle (file);
-}
-
-/* Map the heap dumped into the executable file into our address space. */
-void
-map_in_heap (char *filename)
-{
- HANDLE file;
- HANDLE file_mapping;
- void *file_base;
- unsigned long size, upper_size, n_read;
- int i;
-
- file = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- if (file == INVALID_HANDLE_VALUE)
- {
- i = GetLastError ();
- exit (1);
- }
-
- size = GetFileSize (file, &upper_size);
- file_mapping = CreateFileMapping (file, NULL, PAGE_WRITECOPY,
- 0, size, NULL);
- if (!file_mapping)
- {
- i = GetLastError ();
- exit (1);
- }
-
- size = get_committed_heap_size ();
- file_base = MapViewOfFileEx (file_mapping, FILE_MAP_COPY, 0,
- heap_index_in_executable, size,
- get_heap_start ());
- if (file_base != 0)
- {
- return;
- }
-
- /* If we don't succeed with the mapping, then copy from the
- data into the heap. */
-
- CloseHandle (file_mapping);
-
- if (VirtualAlloc (get_heap_start (), get_committed_heap_size (),
- MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) == NULL)
- {
- i = GetLastError ();
- exit (1);
- }
-
- /* Seek to the location of the heap data in the executable. */
- i = heap_index_in_executable;
- if (SetFilePointer (file, i, NULL, FILE_BEGIN) == 0xFFFFFFFF)
- {
- i = GetLastError ();
- exit (1);
- }
-
- /* Read in the data. */
- if (!ReadFile (file, get_heap_start (),
- get_committed_heap_size (), &n_read, NULL))
- {
- i = GetLastError ();
- exit (1);
- }
-
- CloseHandle (file);
-}
diff --git a/src/vlimit.h b/src/vlimit.h
deleted file mode 100644
index c347dc74df6..00000000000
--- a/src/vlimit.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Dummy for Emacs so that we can run on VMS... */
-#define LIM_DATA 0
diff --git a/src/vm-limit.c b/src/vm-limit.c
deleted file mode 100644
index b23beeb26e7..00000000000
--- a/src/vm-limit.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/* Functions for memory limit warnings.
- Copyright (C) 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifdef emacs
-#include <config.h>
-#include "lisp.h"
-#endif
-
-#ifndef emacs
-#include <stddef.h>
-typedef size_t SIZE;
-typedef void *POINTER;
-#define EXCEEDS_LISP_PTR(x) 0
-#endif
-
-#include "mem-limits.h"
-
-/*
- Level number of warnings already issued.
- 0 -- no warnings issued.
- 1 -- 75% warning already issued.
- 2 -- 85% warning already issued.
- 3 -- 95% warning issued; keep warning frequently.
-*/
-static int warnlevel;
-
-/* Function to call to issue a warning;
- 0 means don't issue them. */
-static void (*warn_function) ();
-
-/* Get more memory space, complaining if we're near the end. */
-
-static void
-check_memory_limits ()
-{
- extern POINTER (*__morecore) ();
-
- register POINTER cp;
- unsigned long five_percent;
- unsigned long data_size;
-
- if (lim_data == 0)
- get_lim_data ();
- five_percent = lim_data / 20;
-
- /* Find current end of memory and issue warning if getting near max */
- cp = (char *) (*__morecore) (0);
- data_size = (char *) cp - (char *) data_space_start;
-
- if (warn_function)
- switch (warnlevel)
- {
- case 0:
- if (data_size > five_percent * 15)
- {
- warnlevel++;
- (*warn_function) ("Warning: past 75% of memory limit");
- }
- break;
-
- case 1:
- if (data_size > five_percent * 17)
- {
- warnlevel++;
- (*warn_function) ("Warning: past 85% of memory limit");
- }
- break;
-
- case 2:
- if (data_size > five_percent * 19)
- {
- warnlevel++;
- (*warn_function) ("Warning: past 95% of memory limit");
- }
- break;
-
- default:
- (*warn_function) ("Warning: past acceptable memory limits");
- break;
- }
-
- /* If we go down below 70% full, issue another 75% warning
- when we go up again. */
- if (data_size < five_percent * 14)
- warnlevel = 0;
- /* If we go down below 80% full, issue another 85% warning
- when we go up again. */
- else if (warnlevel > 1 && data_size < five_percent * 16)
- warnlevel = 1;
- /* If we go down below 90% full, issue another 95% warning
- when we go up again. */
- else if (warnlevel > 2 && data_size < five_percent * 18)
- warnlevel = 2;
-
- if (EXCEEDS_LISP_PTR (cp))
- (*warn_function) ("Warning: memory in use exceeds lisp pointer size");
-}
-
-/* Cause reinitialization based on job parameters;
- also declare where the end of pure storage is. */
-
-void
-memory_warnings (start, warnfun)
- POINTER start;
- void (*warnfun) ();
-{
- extern void (* __after_morecore_hook) (); /* From gmalloc.c */
-
- if (start)
- data_space_start = start;
- else
- data_space_start = start_of_data ();
-
- warn_function = warnfun;
- __after_morecore_hook = check_memory_limits;
-}
diff --git a/src/vms-pp.c b/src/vms-pp.c
deleted file mode 100644
index 9ac7a4966a9..00000000000
--- a/src/vms-pp.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/* vms_pp - preprocess emacs files in such a way that they can be
- * compiled on VMS without warnings.
- * 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
- *
- * Usage:
- * vms_pp infile outfile
- * implicit inputs:
- * The file "vms_pp.trans" has the names and their translations.
- * description:
- * Vms_pp takes the input file and scans it, replacing the long
- * names with shorter names according to the table read in from
- * vms_pp.trans. The line is then written to the output file.
- *
- * Additionally, the "#undef foo" construct is replaced with:
- * #ifdef foo
- * #undef foo
- * #endif
- *
- * The construct #if defined(foo) is replaced with
- * #ifdef foo
- * #define foo_VAL 1
- * #else
- * #define foo_VAL 0
- * #endif
- * #define defined(XX) XX_val
- * #if defined(foo)
- *
- * This last construction only works on single line #if's and takes
- * advantage of a questionable C pre-processor trick. If there are
- * comments within the #if, that contain "defined", then this will
- * bomb.
- */
-#include <stdio.h>
-
-#define Max_table 100
-#define Table_name "vms_pp.trans"
-#define Word_member \
-"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$"
-
-static FILE *in,*out; /* read from, write to */
-struct item { /* symbol table entries */
- char *name;
- char *value;
-};
-static struct item name_table[Max_table]; /* symbol table */
-static int defined_defined = 0; /* small optimization */
-
-main(argc,argv) int argc; char **argv; {
- char buffer[1024];
-
- if(argc != 3) { /* check argument count */
- fprintf(stderr,"usage: vms_pp infile outfile");
- exit();
- }
- init_table(); /* read in translation table */
-
-/* open input and output files
- */
- if((in = fopen(argv[1],"r")) == NULL) {
- fprintf(stderr,"vms_pp: unable to open file '%s'",argv[1]);
- exit();
- }
- if((out = fopen(argv[2],"w")) == NULL) {
- fprintf(stderr,"vms_pp: unable to create file '%s'",argv[2]);
- exit();
- }
-
- while(fgets(buffer,1023,in) != NULL) { /* loop through buffer until end */
- process_line(buffer); /* process the line */
- fputs(buffer,out); /* write out the line */
- }
-}
-
-/* buy - allocate and copy a string
- */
-static char *buy(str) char *str; {
- char *temp;
-
- if(!(temp = malloc(strlen(str)+1))) {
- fprintf(stderr,"vms_pp: can't allocate memory");
- exit();
- }
- strcpy(temp,str);
- return temp;
-}
-
-/* gather_word - return a buffer full of the next word
- */
-static char *gather_word(ptr,word) char *ptr, *word;{
- for(; strchr(Word_member,*ptr); ptr++,word++)
- *word = *ptr;
- *word = 0;
- return ptr;
-}
-
-/* skip_white - skip white space
- */
-static char *skip_white(ptr) char *ptr; {
- while(*ptr == ' ' || *ptr == '\t')
- ptr++;
- return ptr;
-}
-
-/* init_table - initialize translation table.
- */
-init_table() {
- char buf[256],*ptr,word[128];
- FILE *in;
- int i;
-
- if((in = fopen(Table_name,"r")) == NULL) { /* open file */
- fprintf(stderr,"vms_pp: can't open '%s'",Table_name);
- exit();
- }
- for(i = 0; fgets(buf,255,in) != NULL;) { /* loop through lines */
- ptr = skip_white(buf);
- if(*ptr == '!') /* skip comments */
- continue;
- ptr = gather_word(ptr,word); /* get long word */
- if(*word == 0) { /* bad entry */
- fprintf(stderr,"vms_pp: bad input line '%s'\n",buf);
- continue;
- }
- name_table[i].name = buy(word); /* set up the name */
- ptr = skip_white(ptr); /* skip white space */
- ptr = gather_word(ptr,word); /* get equivalent name */
- if(*word == 0) { /* bad entry */
- fprintf(stderr,"vms_pp: bad input line '%s'\n",buf);
- continue;
- }
- name_table[i].value = buy(word); /* and the equivalent name */
- i++; /* increment to next position */
- }
- for(; i < Max_table; i++) /* mark rest as unused */
- name_table[i].name = 0;
-}
-
-/* process_line - do actual line processing
- */
-process_line(buf) char *buf; {
- char *in_ptr,*out_ptr;
- char word[128],*ptr;
- int len;
-
- check_pp(buf); /* check for preprocessor lines */
-
- for(in_ptr = out_ptr = buf; *in_ptr;) {
- if(!strchr(Word_member,*in_ptr)) /* non alpha-numeric? just copy */
- *out_ptr++ = *in_ptr++;
- else {
- in_ptr = gather_word(in_ptr,word); /* get the 'word' */
- if(strlen(word) > 31) /* length is too long */
- replace_word(word); /* replace the word */
- for(ptr = word; *ptr; ptr++,out_ptr++) /* copy out the word */
- *out_ptr = *ptr;
- }
- }
- *out_ptr = 0;
-}
-
-/* check_pp - check for preprocessor lines
- */
-check_pp(buf) char *buf; {
- char *ptr,*p;
- char word[128];
-
- ptr = skip_white(buf); /* skip white space */
- if(*ptr != '#') /* is this a preprocessor line? */
- return; /* no, just return */
-
- ptr = skip_white(++ptr); /* skip white */
- ptr = gather_word(ptr,word); /* get command word */
- if(!strcmp("undef",word)) { /* undef? */
- ptr = skip_white(ptr);
- ptr = gather_word(ptr,word); /* get the symbol to undef */
- fprintf(out,"#ifdef %s\n",word);
- fputs(buf,out);
- strcpy(buf,"#endif");
- return;
- }
- if(!strcmp("if",word)) { /* check for if */
- for(;;) {
- ptr = strchr(ptr,'d'); /* look for d in defined */
- if(!ptr) /* are we done? */
- return;
- if(strchr(Word_member,*(ptr-1))){ /* at beginning of word? */
- ptr++; continue; /* no, continue looking */
- }
- ptr = gather_word(ptr,word); /* get the word */
- if(strcmp(word,"defined")) /* skip if not defined */
- continue;
- ptr = skip_white(ptr); /* skip white */
- if(*ptr != '(') /* look for open paren */
- continue; /* error, continue */
- ptr++; /* skip paren */
- ptr = skip_white(ptr); /* more white skipping */
- ptr = gather_word(ptr,word); /* get the thing to test */
- if(!*word) /* null word is bad */
- continue;
- fprintf(out,"#ifdef %s\n",word); /* generate the code */
- fprintf(out,"#define %s_VAL 1\n",word);
- fprintf(out,"#else\n");
- fprintf(out,"#define %s_VAL 0\n",word);
- fprintf(out,"#endif\n");
- if(!defined_defined) {
- fprintf(out,"#define defined(XXX) XXX/**/_VAL\n");
- defined_defined = 1;
- }
- }
- }
-}
-
-/* replace_word - look the word up in the table, and replace it
- * if a match is found.
- */
-replace_word(word) char *word; {
- int i;
-
- for(i = 0; i < Max_table && name_table[i].name; i++)
- if(!strcmp(word,name_table[i].name)) {
- strcpy(word,name_table[i].value);
- return;
- }
- fprintf(stderr,"couldn't find '%s'\n",word);
-}
diff --git a/src/vms-pwd.h b/src/vms-pwd.h
deleted file mode 100644
index d07fb1dcf59..00000000000
--- a/src/vms-pwd.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#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/vmsdir.h b/src/vmsdir.h
deleted file mode 100644
index 4b4f6e08068..00000000000
--- a/src/vmsdir.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/*
- * 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;
- char dir$t_name[];
-} 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 {
- char dir$t_linkname[];
-} dir$_dirdef2;
-
-#endif
diff --git a/src/vmsfns.c b/src/vmsfns.c
deleted file mode 100644
index 716ba21def7..00000000000
--- a/src/vmsfns.c
+++ /dev/null
@@ -1,962 +0,0 @@
-/* VMS subprocess and command interface.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Written by Mukesh Prasad. */
-
-/*
- * INTERFACE PROVIDED BY EMACS FOR VMS SUBPROCESSES:
- *
- * Emacs provides the following functions:
- *
- * "spawn-subprocess", which takes as arguments:
- *
- * (i) an integer to identify the spawned subprocess in future
- * operations,
- * (ii) A function to process input from the subprocess, and
- * (iii) A function to be called upon subprocess termination.
- *
- * First argument is required. If second argument is missing or nil,
- * the default action is to insert all received messages at the current
- * location in the current buffer. If third argument is missing or nil,
- * no action is taken upon subprocess termination.
- * The input-handler is called as
- * (input-handler num string)
- * where num is the identifying integer for the subprocess and string
- * is a string received from the subprocess. exit-handler is called
- * with the identifying integer as the argument.
- *
- * "send-command-to-subprocess" takes two arguments:
- *
- * (i) Subprocess identifying integer.
- * (ii) String to send as a message to the subprocess.
- *
- * "stop-subprocess" takes the subprocess identifying integer as
- * argument.
- *
- * Implementation is done by spawning an asynchronous subprocess, and
- * communicating to it via mailboxes.
- */
-
-#ifdef VMS
-
-#include <stdio.h>
-#include <ctype.h>
-#undef NULL
-
-#include <config.h>
-#include "lisp.h"
-#include <descrip.h>
-#include <dvidef.h>
-#include <prvdef.h>
-/* #include <clidef.h> */
-#include <iodef.h>
-#include <ssdef.h>
-#include <errno.h>
-
-#ifdef VMS4_4 /* I am being cautious; perhaps this exists in older versions */
-#include <jpidef.h>
-#endif
-
-/* #include <syidef.h> */
-
-#define CLI$M_NOWAIT 1 /* clidef.h is missing from C library */
-#define SYI$_VERSION 4096 /* syidef.h is missing from C library */
-#define JPI$_CLINAME 522 /* JPI$_CLINAME is missing from jpidef.h */
-#define JPI$_MASTER_PID 805 /* JPI$_MASTER_PID missing from jpidef.h */
-#define LIB$_NOSUCHSYM 1409892 /* libclidef.h missing */
-
-#define MSGSIZE 160 /* Maximum size for mailbox operations */
-
-#ifndef PRV$V_ACNT
-
-/* these defines added as hack for VMS 5.1-1. SJones, 8-17-89 */
-/* this is _really_ nasty and needs to be changed ASAP - should see about
- using the union defined in SYS$LIBRARY:PRVDEF.H under v5 */
-
-#define PRV$V_ACNT 0x09
-#define PRV$V_ALLSPOOL 0x04
-#define PRV$V_ALTPRI 0x0D
-#define PRV$V_BUGCHK 0x17
-#define PRV$V_BYPASS 0x1D
-#define PRV$V_CMEXEC 0x01
-#define PRV$V_CMKRNL 0x00
-#define PRV$V_DETACH 0x05
-#define PRV$V_DIAGNOSE 0x06
-#define PRV$V_DOWNGRADE 0x21
-#define PRV$V_EXQUOTA 0x13
-#define PRV$V_GROUP 0x08
-#define PRV$V_GRPNAM 0x03
-#define PRV$V_GRPPRV 0x22
-#define PRV$V_LOG_IO 0x07
-#define PRV$V_MOUNT 0x11
-#define PRV$V_NETMBX 0x14
-#define PRV$V_NOACNT 0x09
-#define PRV$V_OPER 0x12
-#define PRV$V_PFNMAP 0x1A
-#define PRV$V_PHY_IO 0x16
-#define PRV$V_PRMCEB 0x0A
-#define PRV$V_PRMGBL 0x18
-#define PRV$V_PRMJNL 0x25
-#define PRV$V_PRMMBX 0x0B
-#define PRV$V_PSWAPM 0x0C
-#define PRV$V_READALL 0x23
-#define PRV$V_SECURITY 0x26
-#define PRV$V_SETPRI 0x0D
-#define PRV$V_SETPRV 0x0E
-#define PRV$V_SHARE 0x1F
-#define PRV$V_SHMEM 0x1B
-#define PRV$V_SYSGBL 0x19
-#define PRV$V_SYSLCK 0x1E
-#define PRV$V_SYSNAM 0x02
-#define PRV$V_SYSPRV 0x1C
-#define PRV$V_TMPJNL 0x24
-#define PRV$V_TMPMBX 0x0F
-#define PRV$V_UPGRADE 0x20
-#define PRV$V_VOLPRO 0x15
-#define PRV$V_WORLD 0x10
-#endif
-
-/* IO status block for mailbox operations. */
-struct mbx_iosb
-{
- short status;
- short size;
- int pid;
-};
-
-/* Structure for maintaining linked list of subprocesses. */
-struct process_list
-{
- int name; /* Numeric identifier for subprocess */
- int process_id; /* VMS process address */
- int process_active; /* 1 iff process has not exited yet */
- int mbx_chan; /* Mailbox channel to write to process */
- struct mbx_iosb iosb; /* IO status block for write operations */
- Lisp_Object input_handler; /* Input handler for subprocess */
- Lisp_Object exit_handler; /* Exit handler for subprocess */
- struct process_list * next; /* Linked list chain */
-};
-
-/* Structure for privilege list. */
-struct privilege_list
-{
- char * name;
- int mask;
-};
-
-/* Structure for finding VMS related information. */
-struct vms_objlist
-{
- char * name; /* Name of object */
- Lisp_Object (* objfn)(); /* Function to retrieve VMS object */
-};
-
-static int exit_ast (); /* Called upon subprocess exit */
-static int create_mbx (); /* Creates mailbox */
-static void mbx_msg (); /* Writes null terminated string to mbx */
-static void write_to_mbx (); /* Writes message to string */
-static void start_mbx_input (); /* Queues I/O request to mailbox */
-
-static int input_mbx_chan = 0; /* Channel to read subprocess input on */
-static char input_mbx_name[20];
- /* Storage for mailbox device name */
-static struct dsc$descriptor_s input_mbx_dsc;
- /* Descriptor for mailbox device name */
-static struct process_list * process_list = 0;
- /* Linked list of subprocesses */
-static char mbx_buffer[MSGSIZE];
- /* Buffer to read from subprocesses */
-static struct mbx_iosb input_iosb;
- /* IO status block for mailbox reads */
-
-int have_process_input, /* Non-zero iff subprocess input pending */
- process_exited; /* Non-zero iff suprocess exit pending */
-
-/* List of privilege names and mask offsets */
-static struct privilege_list priv_list[] = {
-
- { "ACNT", PRV$V_ACNT },
- { "ALLSPOOL", PRV$V_ALLSPOOL },
- { "ALTPRI", PRV$V_ALTPRI },
- { "BUGCHK", PRV$V_BUGCHK },
- { "BYPASS", PRV$V_BYPASS },
- { "CMEXEC", PRV$V_CMEXEC },
- { "CMKRNL", PRV$V_CMKRNL },
- { "DETACH", PRV$V_DETACH },
- { "DIAGNOSE", PRV$V_DIAGNOSE },
- { "DOWNGRADE", PRV$V_DOWNGRADE }, /* Isn't VMS as low as you can go? */
- { "EXQUOTA", PRV$V_EXQUOTA },
- { "GRPPRV", PRV$V_GRPPRV },
- { "GROUP", PRV$V_GROUP },
- { "GRPNAM", PRV$V_GRPNAM },
- { "LOG_IO", PRV$V_LOG_IO },
- { "MOUNT", PRV$V_MOUNT },
- { "NETMBX", PRV$V_NETMBX },
- { "NOACNT", PRV$V_NOACNT },
- { "OPER", PRV$V_OPER },
- { "PFNMAP", PRV$V_PFNMAP },
- { "PHY_IO", PRV$V_PHY_IO },
- { "PRMCEB", PRV$V_PRMCEB },
- { "PRMGBL", PRV$V_PRMGBL },
- { "PRMJNL", PRV$V_PRMJNL },
- { "PRMMBX", PRV$V_PRMMBX },
- { "PSWAPM", PRV$V_PSWAPM },
- { "READALL", PRV$V_READALL },
- { "SECURITY", PRV$V_SECURITY },
- { "SETPRI", PRV$V_SETPRI },
- { "SETPRV", PRV$V_SETPRV },
- { "SHARE", PRV$V_SHARE },
- { "SHMEM", PRV$V_SHMEM },
- { "SYSGBL", PRV$V_SYSGBL },
- { "SYSLCK", PRV$V_SYSLCK },
- { "SYSNAM", PRV$V_SYSNAM },
- { "SYSPRV", PRV$V_SYSPRV },
- { "TMPJNL", PRV$V_TMPJNL },
- { "TMPMBX", PRV$V_TMPMBX },
- { "UPGRADE", PRV$V_UPGRADE },
- { "VOLPRO", PRV$V_VOLPRO },
- { "WORLD", PRV$V_WORLD },
-
- };
-
-static Lisp_Object
- vms_account(), vms_cliname(), vms_owner(), vms_grp(), vms_image(),
- vms_parent(), vms_pid(), vms_prcnam(), vms_terminal(), vms_uic_int(),
- vms_uic_str(), vms_username(), vms_version_fn(), vms_trnlog(),
- vms_symbol(), vms_proclist();
-
-/* Table of arguments to Fvms_object, and the handlers that get the data. */
-
-static struct vms_objlist vms_object [] = {
- { "ACCOUNT", vms_account }, /* Returns account name as a string */
- { "CLINAME", vms_cliname }, /* Returns CLI name (string) */
- { "OWNER", vms_owner }, /* Returns owner process's PID (int) */
- { "GRP", vms_grp }, /* Returns group number of UIC (int) */
- { "IMAGE", vms_image }, /* Returns executing image (string) */
- { "PARENT", vms_parent }, /* Returns parent proc's PID (int) */
- { "PID", vms_pid }, /* Returns process's PID (int) */
- { "PRCNAM", vms_prcnam }, /* Returns process's name (string) */
- { "TERMINAL", vms_terminal }, /* Returns terminal name (string) */
- { "UIC", vms_uic_int }, /* Returns UIC as integer */
- { "UICGRP", vms_uic_str }, /* Returns UIC as string */
- { "USERNAME", vms_username }, /* Returns username (string) */
- { "VERSION", vms_version_fn },/* Returns VMS version (string) */
- { "LOGICAL", vms_trnlog }, /* Translates VMS logical name */
- { "DCL-SYMBOL", vms_symbol }, /* Translates DCL symbol */
- { "PROCLIST", vms_proclist }, /* Returns list of all PIDs on system */
- };
-
-Lisp_Object Qdefault_subproc_input_handler;
-
-extern int process_ef; /* Event flag for subprocess operations */
-
-DEFUN ("default-subprocess-input-handler",
- Fdefault_subproc_input_handler, Sdefault_subproc_input_handler,
- 2, 2, 0,
- "Default input handler for input from spawned subprocesses.")
- (name, input)
- Lisp_Object name, input;
-{
- /* Just insert in current buffer */
- insert1 (input);
- insert ("\n", 1);
-}
-
-DEFUN ("spawn-subprocess", Fspawn_subprocess, Sspawn_subprocess, 1, 3, 0,
- "Spawn an asynchronous VMS suprocess for command processing.")
- (name, input_handler, exit_handler)
- Lisp_Object name, input_handler, exit_handler;
-{
- int status;
- char output_mbx_name[20];
- struct dsc$descriptor_s output_mbx_dsc;
- struct process_list *ptr, *p, *prev;
-
- CHECK_NUMBER (name, 0);
- if (! input_mbx_chan)
- {
- if (! create_mbx (&input_mbx_dsc, input_mbx_name, &input_mbx_chan, 1))
- return Qnil;
- start_mbx_input ();
- }
- ptr = 0;
- prev = 0;
- while (ptr)
- {
- struct process_list *next = ptr->next;
- if (ptr->name == XFASTINT (name))
- {
- if (ptr->process_active)
- return Qt;
-
- /* Delete this process and run its exit handler. */
- if (prev)
- prev->next = next;
- else
- process_list = next;
- if (! NILP (ptr->exit_handler))
- Feval (Fcons (ptr->exit_handler, Fcons (make_number (ptr->name),
- Qnil)));
- sys$dassgn (ptr->mbx_chan);
- break;
- }
- else
- prev = ptr;
- ptr = next;
- }
- if (! ptr)
- ptr = xmalloc (sizeof (struct process_list));
- if (! create_mbx (&output_mbx_dsc, output_mbx_name, &ptr->mbx_chan, 2))
- {
- free (ptr);
- return Qnil;
- }
- if (NILP (input_handler))
- input_handler = Qdefault_subproc_input_handler;
- 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,
- &ptr->process_id, 0, 0, exit_ast, &ptr->process_active);
- if (! (status & 1))
- {
- sys$dassgn (ptr->mbx_chan);
- free (ptr);
- error ("Unable to spawn subprocess");
- return Qnil;
- }
- ptr->name = XFASTINT (name);
- ptr->next = process_list;
- ptr->process_active = 1;
- process_list = ptr;
- message ("Creating subprocess...done");
- return Qt;
-}
-
-static void
-mbx_msg (ptr, msg)
- struct process_list *ptr;
- char *msg;
-{
- write_to_mbx (ptr, msg, strlen (msg));
-}
-
-DEFUN ("send-command-to-subprocess",
- Fsend_command_to_subprocess, Ssend_command_to_subprocess, 2, 2,
- "sSend command to subprocess: \nsSend subprocess %s command: ",
- "Send to VMS subprocess named NAME the string COMMAND.")
- (name, command)
- Lisp_Object name, command;
-{
- struct process_list * ptr;
-
- CHECK_NUMBER (name, 0);
- CHECK_STRING (command, 1);
- for (ptr = process_list; ptr; ptr = ptr->next)
- if (XFASTINT (name) == ptr->name)
- {
- write_to_mbx (ptr, XSTRING (command)->data,
- XSTRING (command)->size);
- return Qt;
- }
- return Qnil;
-}
-
-DEFUN ("stop-subprocess", Fstop_subprocess, Sstop_subprocess, 1, 1,
- "sStop subprocess: ", "Stop VMS subprocess named NAME.")
- (name)
- Lisp_Object name;
-{
- struct process_list * ptr;
-
- CHECK_NUMBER (name, 0);
- for (ptr = process_list; ptr; ptr = ptr->next)
- if (XFASTINT (name) == ptr->name)
- {
- ptr->exit_handler = Qnil;
- if (sys$delprc (&ptr->process_id, 0) & 1)
- ptr->process_active = 0;
- return Qt;
- }
- return Qnil;
-}
-
-static int
-exit_ast (active)
- int * active;
-{
- process_exited = 1;
- *active = 0;
- sys$setef (process_ef);
-}
-
-/* Process to handle input on the input mailbox.
- * Searches through the list of processes until the matching PID is found,
- * then calls its input handler.
- */
-
-process_command_input ()
-{
- struct process_list * ptr;
- char * msg;
- int msglen;
- Lisp_Object expr;
-
- msg = mbx_buffer;
- msglen = input_iosb.size;
- /* Hack around VMS oddity of sending extraneous CR/LF characters for
- * some of the commands (but not most).
- */
- if (msglen > 0 && *msg == '\r')
- {
- msg++;
- msglen--;
- }
- if (msglen > 0 && msg[msglen - 1] == '\n')
- msglen--;
- if (msglen > 0 && msg[msglen - 1] == '\r')
- msglen--;
- /* Search for the subprocess in the linked list.
- */
- expr = Qnil;
- for (ptr = process_list; ptr; ptr = ptr->next)
- if (ptr->process_id == input_iosb.pid)
- {
- expr = Fcons (ptr->input_handler,
- Fcons (make_number (ptr->name),
- Fcons (make_string (msg, msglen),
- Qnil)));
- break;
- }
- have_process_input = 0;
- start_mbx_input ();
- clear_waiting_for_input (); /* Otherwise Ctl-g will cause crash. JCB */
- if (! NILP (expr))
- Feval (expr);
-}
-
-/* Searches process list for any processes which have exited. Calls their
- * exit handlers and removes them from the process list.
- */
-
-process_exit ()
-{
- struct process_list * ptr, * prev, * next;
-
- process_exited = 0;
- prev = 0;
- ptr = process_list;
- while (ptr)
- {
- next = ptr->next;
- if (! ptr->process_active)
- {
- if (prev)
- prev->next = next;
- else
- process_list = next;
- if (! NILP (ptr->exit_handler))
- Feval (Fcons (ptr->exit_handler, Fcons (make_number (ptr->name),
- Qnil)));
- sys$dassgn (ptr->mbx_chan);
- free (ptr);
- }
- else
- prev = ptr;
- ptr = next;
- }
-}
-
-/* Called at emacs exit.
- */
-
-kill_vms_processes ()
-{
- struct process_list * ptr;
-
- for (ptr = process_list; ptr; ptr = ptr->next)
- if (ptr->process_active)
- {
- sys$dassgn (ptr->mbx_chan);
- sys$delprc (&ptr->process_id, 0);
- }
- sys$dassgn (input_mbx_chan);
- process_list = 0;
- input_mbx_chan = 0;
-}
-
-/* Creates a temporary mailbox and retrieves its device name in 'buf'.
- * Makes the descriptor pointed to by 'dsc' refer to this device.
- * 'buffer_factor' is used to allow sending messages asynchronously
- * till some point.
- */
-
-static int
-create_mbx (dsc, buf, chan, buffer_factor)
- struct dsc$descriptor_s *dsc;
- char *buf;
- int *chan;
- int buffer_factor;
-{
- int strval[2];
- int status;
-
- status = sys$crembx (0, chan, MSGSIZE, MSGSIZE * buffer_factor, 0, 0, 0);
- if (! (status & 1))
- {
- message ("Unable to create mailbox. Need TMPMBX privilege.");
- return 0;
- }
- strval[0] = 16;
- strval[1] = buf;
- status = lib$getdvi (&DVI$_DEVNAM, chan, 0, 0, strval,
- &dsc->dsc$w_length);
- if (! (status & 1))
- return 0;
- dsc->dsc$b_dtype = DSC$K_DTYPE_T;
- dsc->dsc$b_class = DSC$K_CLASS_S;
- dsc->dsc$a_pointer = buf;
- return 1;
-} /* create_mbx */
-
-/* AST routine to be called upon receiving mailbox input.
- * Sets flag telling keyboard routines that input is available.
- */
-
-static int
-mbx_input_ast ()
-{
- have_process_input = 1;
-}
-
-/* Issue a QIO request on the input mailbox.
- */
-static void
-start_mbx_input ()
-{
- sys$qio (process_ef, input_mbx_chan, IO$_READVBLK, &input_iosb,
- mbx_input_ast, 0, mbx_buffer, sizeof (mbx_buffer),
- 0, 0, 0, 0);
-}
-
-/* Send a message to the subprocess input mailbox, without blocking if
- * possible.
- */
-static void
-write_to_mbx (ptr, buf, len)
- struct process_list *ptr;
- char *buf;
- int len;
-{
- sys$qiow (0, ptr->mbx_chan, IO$_WRITEVBLK | IO$M_NOW, &ptr->iosb,
- 0, 0, buf, len, 0, 0, 0, 0);
-}
-
-DEFUN ("setprv", Fsetprv, Ssetprv, 1, 3, 0,
- "Set or reset a VMS privilege. First arg is privilege name.\n\
-Second arg is t or nil, indicating whether the privilege is to be\n\
-set or reset. Default is nil. Returns t if success, nil if not.\n\
-If third arg is non-nil, does not change privilege, but returns t\n\
-or nil depending upon whether the privilege is already enabled.")
- (priv, value, getprv)
- Lisp_Object priv, value, getprv;
-{
- int prvmask[2], prvlen, newmask[2];
- char * prvname;
- int found, i;
- struct privilege_list * ptr;
-
- CHECK_STRING (priv, 0);
- priv = Fupcase (priv);
- prvname = XSTRING (priv)->data;
- prvlen = XSTRING (priv)->size;
- found = 0;
- prvmask[0] = 0;
- prvmask[1] = 0;
- for (i = 0; i < sizeof (priv_list) / sizeof (priv_list[0]); i++)
- {
- ptr = &priv_list[i];
- if (prvlen == strlen (ptr->name) &&
- bcmp (prvname, ptr->name, prvlen) == 0)
- {
- if (ptr->mask >= 32)
- prvmask[1] = 1 << (ptr->mask % 32);
- else
- prvmask[0] = 1 << ptr->mask;
- found = 1;
- break;
- }
- }
- if (! found)
- error ("Unknown privilege name %s", XSTRING (priv)->data);
- if (NILP (getprv))
- {
- if (sys$setprv (NILP (value) ? 0 : 1, prvmask, 0, 0) == SS$_NORMAL)
- return Qt;
- return Qnil;
- }
- /* Get old priv value */
- if (sys$setprv (0, 0, 0, newmask) != SS$_NORMAL)
- return Qnil;
- if ((newmask[0] & prvmask[0])
- || (newmask[1] & prvmask[1]))
- return Qt;
- return Qnil;
-}
-
-/* Retrieves VMS system information. */
-
-#ifdef VMS4_4 /* I don't know whether these functions work in old versions */
-
-DEFUN ("vms-system-info", Fvms_system_info, Svms_system_info, 1, 3, 0,
- "Retrieve VMS process and system information.\n\
-The first argument (a string) specifies the type of information desired.\n\
-The other arguments depend on the type you select.\n\
-For information about a process, the second argument is a process ID\n\
-or a process name, with the current process as a default.\n\
-These are the possibilities for the first arg (upper or lower case ok):\n\
- account Returns account name\n\
- cliname Returns CLI name\n\
- owner Returns owner process's PID\n\
- grp Returns group number\n\
- parent Returns parent process's PID\n\
- pid Returns process's PID\n\
- prcnam Returns process's name\n\
- terminal Returns terminal name\n\
- uic Returns UIC number\n\
- uicgrp Returns formatted [UIC,GRP]\n\
- username Returns username\n\
- version Returns VMS version\n\
- logical Translates VMS logical name (second argument)\n\
- dcl-symbol Translates DCL symbol (second argument)\n\
- proclist Returns list of all PIDs on system (needs WORLD privilege)." )
- (type, arg1, arg2)
- Lisp_Object type, arg1, arg2;
-{
- int i, typelen;
- char * typename;
- struct vms_objlist * ptr;
-
- CHECK_STRING (type, 0);
- type = Fupcase (type);
- typename = XSTRING (type)->data;
- typelen = XSTRING (type)->size;
- for (i = 0; i < sizeof (vms_object) / sizeof (vms_object[0]); i++)
- {
- ptr = &vms_object[i];
- if (typelen == strlen (ptr->name)
- && bcmp (typename, ptr->name, typelen) == 0)
- return (* ptr->objfn)(arg1, arg2);
- }
- error ("Unknown object type %s", typename);
-}
-
-/* Given a reference to a VMS process, returns its process id. */
-
-static int
-translate_id (pid, owner)
- Lisp_Object pid;
- int owner; /* if pid is null/0, return owner. If this
- * flag is 0, return self. */
-{
- int status, code, id, i, numeric, size;
- char * p;
- int prcnam[2];
-
- if (NILP (pid)
- || STRINGP (pid) && XSTRING (pid)->size == 0
- || INTEGERP (pid) && XFASTINT (pid) == 0)
- {
- code = owner ? JPI$_OWNER : JPI$_PID;
- status = lib$getjpi (&code, 0, 0, &id);
- if (! (status & 1))
- error ("Cannot find %s: %s",
- owner ? "owner process" : "process id",
- vmserrstr (status));
- return (id);
- }
- if (INTEGERP (pid))
- return (XFASTINT (pid));
- CHECK_STRING (pid, 0);
- pid = Fupcase (pid);
- size = XSTRING (pid)->size;
- p = XSTRING (pid)->data;
- numeric = 1;
- id = 0;
- for (i = 0; i < size; i++, p++)
- if (isxdigit (*p))
- {
- id *= 16;
- if (*p >= '0' && *p <= '9')
- id += *p - '0';
- else
- id += *p - 'A' + 10;
- }
- else
- {
- numeric = 0;
- break;
- }
- if (numeric)
- return (id);
- prcnam[0] = XSTRING (pid)->size;
- prcnam[1] = XSTRING (pid)->data;
- status = lib$getjpi (&JPI$_PID, 0, prcnam, &id);
- if (! (status & 1))
- error ("Cannot find process id: %s",
- vmserrstr (status));
- return (id);
-} /* translate_id */
-
-/* VMS object retrieval functions. */
-
-static Lisp_Object
-getjpi (jpicode, arg, numeric)
- int jpicode; /* Type of GETJPI information */
- Lisp_Object arg;
- int numeric; /* 1 if numeric value expected */
-{
- int id, status, numval;
- char str[128];
- int strdsc[2] = { sizeof (str), str };
- short strlen;
-
- id = translate_id (arg, 0);
- status = lib$getjpi (&jpicode, &id, 0, &numval, strdsc, &strlen);
- if (! (status & 1))
- error ("Unable to retrieve information: %s",
- vmserrstr (status));
- if (numeric)
- return (make_number (numval));
- return (make_string (str, strlen));
-}
-
-static Lisp_Object
-vms_account (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- return getjpi (JPI$_ACCOUNT, arg1, 0);
-}
-
-static Lisp_Object
-vms_cliname (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- return getjpi (JPI$_CLINAME, arg1, 0);
-}
-
-static Lisp_Object
-vms_grp (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- return getjpi (JPI$_GRP, arg1, 1);
-}
-
-static Lisp_Object
-vms_image (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- return getjpi (JPI$_IMAGNAME, arg1, 0);
-}
-
-static Lisp_Object
-vms_owner (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- return getjpi (JPI$_OWNER, arg1, 1);
-}
-
-static Lisp_Object
-vms_parent (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- return getjpi (JPI$_MASTER_PID, arg1, 1);
-}
-
-static Lisp_Object
-vms_pid (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- return getjpi (JPI$_PID, arg1, 1);
-}
-
-static Lisp_Object
-vms_prcnam (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- return getjpi (JPI$_PRCNAM, arg1, 0);
-}
-
-static Lisp_Object
-vms_terminal (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- return getjpi (JPI$_TERMINAL, arg1, 0);
-}
-
-static Lisp_Object
-vms_uic_int (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- return getjpi (JPI$_UIC, arg1, 1);
-}
-
-static Lisp_Object
-vms_uic_str (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- return getjpi (JPI$_UIC, arg1, 0);
-}
-
-static Lisp_Object
-vms_username (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- return getjpi (JPI$_USERNAME, arg1, 0);
-}
-
-static Lisp_Object
-vms_version_fn (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- char str[40];
- int status;
- int strdsc[2] = { sizeof (str), str };
- short strlen;
-
- status = lib$getsyi (&SYI$_VERSION, 0, strdsc, &strlen, 0, 0);
- if (! (status & 1))
- error ("Unable to obtain version: %s", vmserrstr (status));
- return (make_string (str, strlen));
-}
-
-static Lisp_Object
-vms_trnlog (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- char str[256]; /* Max logical translation is 255 bytes. */
- int status, symdsc[2];
- int strdsc[2] = { sizeof (str), str };
- short length, level;
-
- CHECK_STRING (arg1, 0);
- symdsc[0] = XSTRING (arg1)->size;
- symdsc[1] = XSTRING (arg1)->data;
- status = lib$sys_trnlog (symdsc, &length, strdsc);
- if (! (status & 1))
- error ("Unable to translate logical name: %s", vmserrstr (status));
- if (status == SS$_NOTRAN)
- return (Qnil);
- return (make_string (str, length));
-}
-
-static Lisp_Object
-vms_symbol (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- char str[1025]; /* Max symbol translation is 1024 bytes. */
- int status, symdsc[2];
- int strdsc[2] = { sizeof (str), str };
- short length, level;
-
- CHECK_STRING (arg1, 0);
- symdsc[0] = XSTRING (arg1)->size;
- symdsc[1] = XSTRING (arg1)->data;
- status = lib$get_symbol (symdsc, strdsc, &length, &level);
- if (! (status & 1)) {
- if (status == LIB$_NOSUCHSYM)
- return (Qnil);
- else
- error ("Unable to translate symbol: %s", vmserrstr (status));
- }
- return (make_string (str, length));
-}
-
-static Lisp_Object
-vms_proclist (arg1, arg2)
- Lisp_Object arg1, arg2;
-{
- Lisp_Object retval;
- int id, status, pid;
-
- retval = Qnil;
- pid = -1;
- for (;;)
- {
- status = lib$getjpi (&JPI$_PID, &pid, 0, &id);
- if (status == SS$_NOMOREPROC)
- break;
- if (! (status & 1))
- error ("Unable to get process ID: %s", vmserrstr (status));
- retval = Fcons (make_number (id), retval);
- }
- return (Fsort (retval, intern ("<")));
-}
-
-DEFUN ("shrink-to-icon", Fshrink_to_icon, Sshrink_to_icon, 0, 0, 0,
- "If emacs is running in a workstation window, shrink to an icon.")
- ()
-{
- static char result[128];
- static $DESCRIPTOR (result_descriptor, result);
- static $DESCRIPTOR (tt_name, "TT:");
- static int chan = 0;
- static int buf = 0x9d + ('2'<<8) + ('2'<<16) + (0x9c<<24);
- int status;
- static int temp = JPI$_TERMINAL;
-
- status = lib$getjpi (&temp, 0, 0, 0, &result_descriptor, 0);
- if (status != SS$_NORMAL)
- error ("Unable to determine terminal type.");
- if (result[0] != 'W' || result[1] != 'T') /* see if workstation */
- error ("Can't shrink-to-icon on a non workstation terminal");
- if (!chan) /* assign channel if not assigned */
- if ((status = sys$assign (&tt_name, &chan, 0, 0)) != SS$_NORMAL)
- error ("Can't assign terminal, %d", status);
- status = sys$qiow (0, chan, IO$_WRITEVBLK+IO$M_BREAKTHRU, 0, 0, 0,
- &buf, 4, 0, 0, 0, 0);
- if (status != SS$_NORMAL)
- error ("Can't shrink-to-icon, %d", status);
-}
-
-#endif /* VMS4_4 */
-
-init_vmsfns ()
-{
- process_list = 0;
- input_mbx_chan = 0;
-}
-
-syms_of_vmsfns ()
-{
- defsubr (&Sdefault_subproc_input_handler);
- defsubr (&Sspawn_subprocess);
- defsubr (&Ssend_command_to_subprocess);
- defsubr (&Sstop_subprocess);
- defsubr (&Ssetprv);
-#ifdef VMS4_4
- defsubr (&Svms_system_info);
- defsubr (&Sshrink_to_icon);
-#endif /* VMS4_4 */
- Qdefault_subproc_input_handler = intern ("default-subprocess-input-handler");
- staticpro (&Qdefault_subproc_input_handler);
-}
-#endif /* VMS */
-
diff --git a/src/vmsgmalloc.c b/src/vmsgmalloc.c
deleted file mode 100644
index a3545f5eb01..00000000000
--- a/src/vmsgmalloc.c
+++ /dev/null
@@ -1,2012 +0,0 @@
-/* DO NOT EDIT THIS FILE -- it is automagically generated. -*- C -*- */
-
-#define _MALLOC_INTERNAL
-
-/* The malloc headers and source files from the C library follow here. */
-
-/* Declarations for `malloc' and friends.
- Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
- Written May 1989 by Mike Haertel.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
- The author may be reached (Email) at the address mike@ai.mit.edu,
- or (US mail) as Mike Haertel c/o Free Software Foundation. */
-
-#ifndef _MALLOC_H
-
-#define _MALLOC_H 1
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
-#undef __P
-#define __P(args) args
-#undef __const
-#define __const const
-#undef __ptr_t
-#define __ptr_t void *
-#else /* Not C++ or ANSI C. */
-#undef __P
-#define __P(args) ()
-#undef __const
-#define __const
-#undef __ptr_t
-#define __ptr_t char *
-#endif /* C++ or ANSI C. */
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifdef __STDC__
-#include <stddef.h>
-#else
-#ifdef VMS /* The following are defined in stdio.h, but we need it NOW!
- But do NOT do it with defines here, for then, VAX C is going
- to barf when it gets to stdio.h and the typedefs in there! */
-typedef unsigned int size_t;
-typedef int ptrdiff_t;
-#else /* not VMS */
-#undef size_t
-#define size_t unsigned int
-#undef ptrdiff_t
-#define ptrdiff_t int
-#endif /* VMS */
-#endif
-
-
-/* Allocate SIZE bytes of memory. */
-extern __ptr_t malloc __P ((size_t __size));
-/* Re-allocate the previously allocated block
- in __ptr_t, making the new block SIZE bytes long. */
-extern __ptr_t realloc __P ((__ptr_t __ptr, size_t __size));
-/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
-extern __ptr_t calloc __P ((size_t __nmemb, size_t __size));
-/* Free a block allocated by `malloc', `realloc' or `calloc'. */
-extern void free __P ((__ptr_t __ptr));
-
-/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
-extern __ptr_t memalign __P ((size_t __alignment, size_t __size));
-
-/* Allocate SIZE bytes on a page boundary. */
-extern __ptr_t valloc __P ((size_t __size));
-
-#ifdef VMS
-/* VMS hooks to deal with two heaps */
-/* Allocate SIZE bytes of memory. */
-extern __ptr_t __vms_malloc __P ((size_t __size));
-/* Re-allocate the previously allocated block
- in __ptr_t, making the new block SIZE bytes long. */
-extern __ptr_t __vms_realloc __P ((__ptr_t __ptr, size_t __size));
-/* Free a block allocated by `malloc', `realloc' or `calloc'. */
-extern void __vms_free __P ((__ptr_t __ptr));
-#endif
-
-#ifdef _MALLOC_INTERNAL
-
-#include <stdio.h> /* Harmless, gets __GNU_LIBRARY__ defined. */
-
-#if defined(HAVE_CONFIG_H) || defined(emacs)
-#include <config.h>
-#endif
-
-#if defined(__GNU_LIBRARY__) || defined(STDC_HEADERS) || defined(USG)
-#include <string.h>
-#else
-#ifndef memset
-#define memset(s, zero, n) bzero ((s), (n))
-#endif
-#ifndef memcpy
-#define memcpy(d, s, n) bcopy ((s), (d), (n))
-#endif
-#ifndef memmove
-#define memmove(d, s, n) bcopy ((s), (d), (n))
-#endif
-#endif
-
-
-#if defined(__GNU_LIBRARY__) || defined(__STDC__)
-#include <limits.h>
-#else
-#define CHAR_BIT 8
-#endif
-
-/* The allocator divides the heap into blocks of fixed size; large
- requests receive one or more whole blocks, and small requests
- receive a fragment of a block. Fragment sizes are powers of two,
- and all fragments of a block are the same size. When all the
- fragments in a block have been freed, the block itself is freed. */
-#define INT_BIT (CHAR_BIT * sizeof(int))
-#ifdef VMS
-#define BLOCKLOG 9
-#else
-#define BLOCKLOG (INT_BIT > 16 ? 12 : 9)
-#endif
-#define BLOCKSIZE (1 << BLOCKLOG)
-#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
-
-/* Determine the amount of memory spanned by the initial heap table
- (not an absolute limit). */
-#define HEAP (INT_BIT > 16 ? 4194304 : 65536)
-
-/* Number of contiguous free blocks allowed to build up at the end of
- memory before they will be returned to the system. */
-#define FINAL_FREE_BLOCKS 8
-
-/* Data structure giving per-block information. */
-typedef union
- {
- /* Heap information for a busy block. */
- struct
- {
- /* Zero for a large block, or positive giving the
- logarithm to the base two of the fragment size. */
- int type;
- union
- {
- struct
- {
- size_t nfree; /* Free fragments in a fragmented block. */
- size_t first; /* First free fragment of the block. */
- } frag;
- /* Size (in blocks) of a large cluster. */
- size_t size;
- } info;
- } busy;
- /* Heap information for a free block
- (that may be the first of a free cluster). */
- struct
- {
- size_t size; /* Size (in blocks) of a free cluster. */
- size_t next; /* Index of next free cluster. */
- size_t prev; /* Index of previous free cluster. */
- } free;
- } malloc_info;
-
-/* Pointer to first block of the heap. */
-extern char *_heapbase;
-
-/* Table indexed by block number giving per-block information. */
-extern malloc_info *_heapinfo;
-
-/* Address to block number and vice versa. */
-#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
-#define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))
-
-/* Current search index for the heap table. */
-extern size_t _heapindex;
-
-/* Limit of valid info table indices. */
-extern size_t _heaplimit;
-
-/* Doubly linked lists of free fragments. */
-struct list
- {
- struct list *next;
- struct list *prev;
- };
-
-/* Free list headers for each fragment size. */
-extern struct list _fraghead[];
-
-/* List of blocks allocated with `memalign' (or `valloc'). */
-struct alignlist
- {
- struct alignlist *next;
- __ptr_t aligned; /* The address that memaligned returned. */
- __ptr_t exact; /* The address that malloc returned. */
- };
-extern struct alignlist *_aligned_blocks;
-
-/* Instrumentation. */
-extern size_t _chunks_used;
-extern size_t _bytes_used;
-extern size_t _chunks_free;
-extern size_t _bytes_free;
-
-/* Internal version of `free' used in `morecore' (malloc.c). */
-extern void _free_internal __P ((__ptr_t __ptr));
-
-#endif /* _MALLOC_INTERNAL. */
-
-/* Underlying allocation function; successive calls should
- return contiguous pieces of memory. */
-/* It does NOT always return contiguous pieces of memory on VMS. */
-extern __ptr_t (*__morecore) __P ((ptrdiff_t __size));
-
-/* Underlying deallocation function. It accepts both a pointer and
- a size to back up. It is implementation dependent what is really
- used. */
-extern __ptr_t (*__lesscore) __P ((__ptr_t __ptr, ptrdiff_t __size));
-
-/* Default value of `__morecore'. */
-extern __ptr_t __default_morecore __P ((ptrdiff_t __size));
-
-/* Default value of `__lesscore'. */
-extern __ptr_t __default_lesscore __P ((__ptr_t __ptr, ptrdiff_t __size));
-
-#ifdef VMS
-/* Default value of `__morecore'. */
-extern __ptr_t __vms_morecore __P ((ptrdiff_t __size));
-
-/* Default value of `__lesscore'. */
-extern __ptr_t __vms_lesscore __P ((__ptr_t __ptr, ptrdiff_t __size));
-#endif
-
-/* If not NULL, this function is called after each time
- `__morecore' is called to increase the data size. */
-extern void (*__after_morecore_hook) __P ((void));
-
-/* If not NULL, this function is called after each time
- `__lesscore' is called to increase the data size. */
-extern void (*__after_lesscore_hook) __P ((void));
-
-/* Nonzero if `malloc' has been called and done its initialization. */
-extern int __malloc_initialized;
-
-/* Hooks for debugging versions. */
-extern void (*__free_hook) __P ((__ptr_t __ptr));
-extern __ptr_t (*__malloc_hook) __P ((size_t __size));
-extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
-
-/* Activate a standard collection of debugging hooks. */
-extern int mcheck __P ((void (*__func) __P ((void))));
-
-/* Activate a standard collection of tracing hooks. */
-extern void mtrace __P ((void));
-
-/* Statistics available to the user. */
-struct mstats
- {
- size_t bytes_total; /* Total size of the heap. */
- size_t chunks_used; /* Chunks allocated by the user. */
- size_t bytes_used; /* Byte total of user-allocated chunks. */
- size_t chunks_free; /* Chunks in the free list. */
- size_t bytes_free; /* Byte total of chunks in the free list. */
- };
-
-/* Pick up the current statistics. */
-extern struct mstats mstats __P ((void));
-
-/* Call WARNFUN with a warning message when memory usage is high. */
-extern void memory_warnings __P ((__ptr_t __start,
- void (*__warnfun) __P ((__const char *))));
-
-
-/* Relocating allocator. */
-
-/* Allocate SIZE bytes, and store the address in *HANDLEPTR. */
-extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, size_t __size));
-
-/* Free the storage allocated in HANDLEPTR. */
-extern void r_alloc_free __P ((__ptr_t *__handleptr));
-
-/* Adjust the block at HANDLEPTR to be SIZE bytes long. */
-extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, size_t __size));
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* malloc.h */
-/* Memory allocator `malloc'.
- Copyright 1990, 1991, 1992, 1993 Free Software Foundation
- Written May 1989 by Mike Haertel.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
-
- The author may be reached (Email) at the address mike@ai.mit.edu,
- or (US mail) as Mike Haertel c/o Free Software Foundation. */
-
-#ifndef _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
-
-#ifdef VMS
-/* How to really get more memory. */
-__ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __vms_morecore;
-#else
-/* How to really get more memory. */
-__ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore;
-#endif
-
-/* Debugging hook for `malloc'. */
-#ifdef VMS
-__ptr_t (*__malloc_hook) __P ((size_t __size)) = __vms_malloc;
-#else
-__ptr_t (*__malloc_hook) __P ((size_t __size));
-#endif
-
-/* Pointer to the base of the first block. */
-char *_heapbase;
-
-/* Block information table. Allocated with align/__free (not malloc/free). */
-malloc_info *_heapinfo;
-
-/* Number of info entries. */
-static size_t heapsize;
-
-/* Search index in the info table. */
-size_t _heapindex;
-
-/* Limit of valid info table indices. */
-size_t _heaplimit;
-
-/* Free lists for each fragment size. */
-struct list _fraghead[BLOCKLOG];
-
-/* Instrumentation. */
-size_t _chunks_used;
-size_t _bytes_used;
-size_t _chunks_free;
-size_t _bytes_free;
-
-/* Are you experienced? */
-int __malloc_initialized;
-
-void (*__after_morecore_hook) __P ((void));
-
-/* Aligned allocation. */
-static __ptr_t align __P ((size_t));
-static __ptr_t
-align (size)
- size_t size;
-{
- __ptr_t result;
- unsigned long int adj;
-
- result = (*__morecore) (size);
- adj = (unsigned long int) ((unsigned long int) ((char *) result -
- (char *) NULL)) % BLOCKSIZE;
- if (adj != 0)
- {
- adj = BLOCKSIZE - adj;
- (void) (*__morecore) (adj);
- result = (char *) result + adj;
- }
-
- if (__after_morecore_hook)
- (*__after_morecore_hook) ();
-
- return result;
-}
-
-/* Set everything up and remember that we have. */
-static int initialize __P ((void));
-static int
-initialize ()
-{
-#ifdef RL_DEBUG
- extern VMS_present_buffer();
- printf("__malloc_initialized = %d\n", __malloc_initialized);
- VMS_present_buffer();
-#endif
- heapsize = HEAP / BLOCKSIZE;
- _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info));
- if (_heapinfo == NULL)
- return 0;
- memset (_heapinfo, 0, heapsize * sizeof (malloc_info));
- _heapinfo[0].free.size = 0;
- _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
- _heapindex = 0;
- _heapbase = (char *) _heapinfo;
-#ifdef RL_DEBUG
-/* debug */
- printf("_heapbase = 0%o/0x%x/%d\n", _heapbase, _heapbase, _heapbase);
-/* end debug */
-#endif
- __malloc_initialized = 1;
- return 1;
-}
-
-/* Get neatly aligned memory, initializing or
- growing the heap info table as necessary. */
-static __ptr_t morecore __P ((size_t));
-static __ptr_t
-morecore (size)
- size_t size;
-{
- __ptr_t result;
- malloc_info *newinfo, *oldinfo;
- size_t newsize;
-
- result = align (size);
- if (result == NULL)
- return NULL;
-
- /* Check if we need to grow the info table. */
- if ((size_t) BLOCK ((char *) result + size) > heapsize)
- {
- newsize = heapsize;
- while ((size_t) BLOCK ((char *) result + size) > newsize)
- newsize *= 2;
- newinfo = (malloc_info *) align (newsize * sizeof (malloc_info));
- if (newinfo == NULL)
- {
- (*__lesscore) (result, size);
- return NULL;
- }
- memset (newinfo, 0, newsize * sizeof (malloc_info));
- memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info));
- oldinfo = _heapinfo;
- newinfo[BLOCK (oldinfo)].busy.type = 0;
- newinfo[BLOCK (oldinfo)].busy.info.size
- = BLOCKIFY (heapsize * sizeof (malloc_info));
- _heapinfo = newinfo;
- _free_internal (oldinfo);
- heapsize = newsize;
- }
-
- _heaplimit = BLOCK ((char *) result + size);
- return result;
-}
-
-/* Allocate memory from the heap. */
-__ptr_t
-malloc (size)
- size_t size;
-{
- __ptr_t result;
- size_t block, blocks, lastblocks, start;
- register size_t i;
- struct list *next;
-
- if (size == 0)
- return NULL;
-
- if (__malloc_hook != NULL)
- return (*__malloc_hook) (size);
-
- if (!__malloc_initialized)
- if (!initialize ())
- return NULL;
-
- if (size < sizeof (struct list))
- size = sizeof (struct list);
-
- /* Determine the allocation policy based on the request size. */
- if (size <= BLOCKSIZE / 2)
- {
- /* Small allocation to receive a fragment of a block.
- Determine the logarithm to base two of the fragment size. */
- register size_t log = 1;
- --size;
- while ((size /= 2) != 0)
- ++log;
-
- /* Look in the fragment lists for a
- free fragment of the desired size. */
- next = _fraghead[log].next;
- if (next != NULL)
- {
- /* There are free fragments of this size.
- Pop a fragment out of the fragment list and return it.
- Update the block's nfree and first counters. */
- result = (__ptr_t) next;
- next->prev->next = next->next;
- if (next->next != NULL)
- next->next->prev = next->prev;
- block = BLOCK (result);
- if (--_heapinfo[block].busy.info.frag.nfree != 0)
- _heapinfo[block].busy.info.frag.first = (unsigned long int)
- ((unsigned long int) ((char *) next->next - (char *) NULL)
- % BLOCKSIZE) >> log;
-
- /* Update the statistics. */
- ++_chunks_used;
- _bytes_used += 1 << log;
- --_chunks_free;
- _bytes_free -= 1 << log;
- }
- else
- {
- /* No free fragments of the desired size, so get a new block
- and break it into fragments, returning the first. */
- result = malloc (BLOCKSIZE);
- if (result == NULL)
- return NULL;
-
- /* Link all fragments but the first into the free list. */
- for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i)
- {
- next = (struct list *) ((char *) result + (i << log));
-#ifdef RL_DEBUG
- printf("DEBUG: malloc (%d): next = %p\n", size, next);
-#endif
- next->next = _fraghead[log].next;
- next->prev = &_fraghead[log];
- next->prev->next = next;
- if (next->next != NULL)
- next->next->prev = next;
- }
-
- /* Initialize the nfree and first counters for this block. */
- block = BLOCK (result);
- _heapinfo[block].busy.type = log;
- _heapinfo[block].busy.info.frag.nfree = i - 1;
- _heapinfo[block].busy.info.frag.first = i - 1;
-
- _chunks_free += (BLOCKSIZE >> log) - 1;
- _bytes_free += BLOCKSIZE - (1 << log);
- _bytes_used -= BLOCKSIZE - (1 << log);
- }
- }
- else
- {
- /* Large allocation to receive one or more blocks.
- Search the free list in a circle starting at the last place visited.
- If we loop completely around without finding a large enough
- space we will have to get more memory from the system. */
- blocks = BLOCKIFY (size);
- start = block = _heapindex;
- while (_heapinfo[block].free.size < blocks)
- {
- block = _heapinfo[block].free.next;
- if (block == start)
- {
- /* Need to get more from the system. Check to see if
- the new core will be contiguous with the final free
- block; if so we don't need to get as much. */
- block = _heapinfo[0].free.prev;
- lastblocks = _heapinfo[block].free.size;
- if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
- (*__morecore) (0) == ADDRESS (block + lastblocks) &&
- (morecore ((blocks - lastblocks) * BLOCKSIZE)) != NULL)
- {
- _heapinfo[block].free.size = blocks;
- _bytes_free += (blocks - lastblocks) * BLOCKSIZE;
- continue;
- }
- result = morecore (blocks * BLOCKSIZE);
- if (result == NULL)
- return NULL;
- block = BLOCK (result);
- _heapinfo[block].busy.type = 0;
- _heapinfo[block].busy.info.size = blocks;
- ++_chunks_used;
- _bytes_used += blocks * BLOCKSIZE;
- return result;
- }
- }
-
- /* At this point we have found a suitable free list entry.
- Figure out how to remove what we need from the list. */
- result = ADDRESS (block);
- if (_heapinfo[block].free.size > blocks)
- {
- /* The block we found has a bit left over,
- so relink the tail end back into the free list. */
- _heapinfo[block + blocks].free.size
- = _heapinfo[block].free.size - blocks;
- _heapinfo[block + blocks].free.next
- = _heapinfo[block].free.next;
- _heapinfo[block + blocks].free.prev
- = _heapinfo[block].free.prev;
- _heapinfo[_heapinfo[block].free.prev].free.next
- = _heapinfo[_heapinfo[block].free.next].free.prev
- = _heapindex = block + blocks;
- }
- else
- {
- /* The block exactly matches our requirements,
- so just remove it from the list. */
- _heapinfo[_heapinfo[block].free.next].free.prev
- = _heapinfo[block].free.prev;
- _heapinfo[_heapinfo[block].free.prev].free.next
- = _heapindex = _heapinfo[block].free.next;
- --_chunks_free;
- }
-
- _heapinfo[block].busy.type = 0;
- _heapinfo[block].busy.info.size = blocks;
- ++_chunks_used;
- _bytes_used += blocks * BLOCKSIZE;
- _bytes_free -= blocks * BLOCKSIZE;
- }
-
- return result;
-}
-/* Free a block of memory allocated by `malloc'.
- Copyright 1990, 1991, 1992 Free Software Foundation
- Written May 1989 by Mike Haertel.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
-
- The author may be reached (Email) at the address mike@ai.mit.edu,
- or (US mail) as Mike Haertel c/o Free Software Foundation. */
-
-#ifndef _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
-
-#ifdef VMS
-/* How to really get more memory. */
-__ptr_t (*__lesscore) __P ((__ptr_t __ptr,ptrdiff_t __size)) = __vms_lesscore;
-#else
-/* How to really get more memory. */
-__ptr_t (*__lesscore) __P ((__ptr_t __ptr,ptrdiff_t __size)) = __default_lesscore;
-#endif
-
-/* Debugging hook for free. */
-#ifdef VMS
-void (*__free_hook) __P ((__ptr_t __ptr)) = __vms_free;
-#else
-void (*__free_hook) __P ((__ptr_t __ptr));
-#endif
-
-/* List of blocks allocated by memalign. */
-struct alignlist *_aligned_blocks = NULL;
-
-/* Return memory to the heap.
- Like `free' but don't call a __free_hook if there is one. */
-void
-_free_internal (ptr)
- __ptr_t ptr;
-{
- int type;
- size_t block, blocks;
- register size_t i;
- struct list *prev, *next;
-
- block = BLOCK (ptr);
-
- type = _heapinfo[block].busy.type;
- switch (type)
- {
- case 0:
- /* Get as many statistics as early as we can. */
- --_chunks_used;
- _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
- _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
-
- /* Find the free cluster previous to this one in the free list.
- Start searching at the last block referenced; this may benefit
- programs with locality of allocation. */
- i = _heapindex;
- if (i > block)
- while (i > block)
- i = _heapinfo[i].free.prev;
- else
- {
- do
- i = _heapinfo[i].free.next;
- while (i > 0 && i < block);
- i = _heapinfo[i].free.prev;
- }
-
- /* Determine how to link this block into the free list. */
- if (block == i + _heapinfo[i].free.size)
- {
- /* Coalesce this block with its predecessor. */
- _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
- block = i;
- }
- else
- {
- /* Really link this block back into the free list. */
- _heapinfo[block].free.size = _heapinfo[block].busy.info.size;
- _heapinfo[block].free.next = _heapinfo[i].free.next;
- _heapinfo[block].free.prev = i;
- _heapinfo[i].free.next = block;
- _heapinfo[_heapinfo[block].free.next].free.prev = block;
- ++_chunks_free;
- }
-
- /* Now that the block is linked in, see if we can coalesce it
- with its successor (by deleting its successor from the list
- and adding in its size). */
- if (block + _heapinfo[block].free.size == _heapinfo[block].free.next)
- {
- _heapinfo[block].free.size
- += _heapinfo[_heapinfo[block].free.next].free.size;
- _heapinfo[block].free.next
- = _heapinfo[_heapinfo[block].free.next].free.next;
- _heapinfo[_heapinfo[block].free.next].free.prev = block;
- --_chunks_free;
- }
-
- /* Now see if we can return stuff to the system. */
- blocks = _heapinfo[block].free.size;
- if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
- && (*__morecore) (0) == ADDRESS (block + blocks))
- {
- register size_t bytes = blocks * BLOCKSIZE;
- _heaplimit -= blocks;
- (*__lesscore) (ADDRESS(block), bytes);
- _heapinfo[_heapinfo[block].free.prev].free.next
- = _heapinfo[block].free.next;
- _heapinfo[_heapinfo[block].free.next].free.prev
- = _heapinfo[block].free.prev;
- block = _heapinfo[block].free.prev;
- --_chunks_free;
- _bytes_free -= bytes;
- }
-
- /* Set the next search to begin at this block. */
- _heapindex = block;
- break;
-
- default:
- /* Do some of the statistics. */
- --_chunks_used;
- _bytes_used -= 1 << type;
- ++_chunks_free;
- _bytes_free += 1 << type;
-
- /* Get the address of the first free fragment in this block. */
- prev = (struct list *) ((char *) ADDRESS (block) +
- (_heapinfo[block].busy.info.frag.first << type));
-#ifdef RL_DEBUG
- printf("_free_internal(0%o/0x%x/%d) :\n", ptr, ptr, ptr);
- printf(" block = %d, type = %d, prev = 0%o/0x%x/%d\n",
- block, type, prev, prev, prev);
- printf(" _heapinfo[block=%d].busy.info.frag.nfree = %d\n",
- block,
- _heapinfo[block].busy.info.frag.nfree);
-#endif
-
- if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)
- {
- /* If all fragments of this block are free, remove them
- from the fragment list and free the whole block. */
- next = prev;
- for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
- next = next->next;
- prev->prev->next = next;
- if (next != NULL)
- next->prev = prev->prev;
- _heapinfo[block].busy.type = 0;
- _heapinfo[block].busy.info.size = 1;
-
- /* Keep the statistics accurate. */
- ++_chunks_used;
- _bytes_used += BLOCKSIZE;
- _chunks_free -= BLOCKSIZE >> type;
- _bytes_free -= BLOCKSIZE;
-
- free (ADDRESS (block));
- }
- else if (_heapinfo[block].busy.info.frag.nfree != 0)
- {
- /* If some fragments of this block are free, link this
- fragment into the fragment list after the first free
- fragment of this block. */
-#ifdef RL_DEBUG
- printf("There's a bug hiding here (%s:%d), so I will print some values\n", __FILE__, __LINE__);
-#endif
- next = (struct list *) ptr;
-#ifdef RL_DEBUG
- printf(" (struct list *)next (0%o / 0x%x / %d) ->\n", next, next, next);
- printf(" next = 0%o / 0x%x / %d\n", next->next,next->next,next->next);
- printf(" prev = 0%o / 0x%x / %d\n", next->prev,next->prev,next->prev);
- printf(" (struct list *)prev (0%o / 0x%x / %d)->\n", prev, prev, prev);
- printf(" next = 0%o / 0x%x / %d\n", prev->next,prev->next,prev->next);
- printf(" prev = 0%o / 0x%x / %d\n", prev->prev,prev->prev,prev->prev);
-#endif
- next->next = prev->next;
- next->prev = prev;
- prev->next = next;
- if (next->next != NULL)
- next->next->prev = next;
- ++_heapinfo[block].busy.info.frag.nfree;
- }
- else
- {
- /* No fragments of this block are free, so link this
- fragment into the fragment list and announce that
- it is the first free fragment of this block. */
- prev = (struct list *) ptr;
- _heapinfo[block].busy.info.frag.nfree = 1;
- _heapinfo[block].busy.info.frag.first = (unsigned long int)
- ((unsigned long int) ((char *) ptr - (char *) NULL)
- % BLOCKSIZE >> type);
- prev->next = _fraghead[type].next;
- prev->prev = &_fraghead[type];
- prev->prev->next = prev;
- if (prev->next != NULL)
- prev->next->prev = prev;
- }
- break;
- }
-}
-
-/* Return memory to the heap. */
-void
-free (ptr)
- __ptr_t ptr;
-{
- register struct alignlist *l;
-
- if (ptr == NULL)
- return;
-
- for (l = _aligned_blocks; l != NULL; l = l->next)
- if (l->aligned == ptr)
- {
- l->aligned = NULL; /* Mark the slot in the list as free. */
- ptr = l->exact;
- break;
- }
-
- if (__free_hook != NULL)
- (*__free_hook) (ptr);
- else
- _free_internal (ptr);
-}
-/* Change the size of a block allocated by `malloc'.
- Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
- Written May 1989 by Mike Haertel.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
-
- The author may be reached (Email) at the address mike@ai.mit.edu,
- or (US mail) as Mike Haertel c/o Free Software Foundation. */
-
-#ifndef _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
-
-#define min(A, B) ((A) < (B) ? (A) : (B))
-
-/* Debugging hook for realloc. */
-#ifdef VMS
-__ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size)) = __vms_realloc;
-#else
-__ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
-#endif
-
-/* Resize the given region to the new size, returning a pointer
- to the (possibly moved) region. This is optimized for speed;
- some benchmarks seem to indicate that greater compactness is
- achieved by unconditionally allocating and copying to a
- new region. This module has incestuous knowledge of the
- internals of both free and malloc. */
-__ptr_t
-realloc (ptr, size)
- __ptr_t ptr;
- size_t size;
-{
- __ptr_t result;
- int type;
- size_t block, blocks, oldlimit;
-
- if (size == 0)
- {
- free (ptr);
- return malloc (0);
- }
- else if (ptr == NULL)
- return malloc (size);
-
- if (__realloc_hook != NULL)
- return (*__realloc_hook) (ptr, size);
-
- block = BLOCK (ptr);
-
- type = _heapinfo[block].busy.type;
- switch (type)
- {
- case 0:
- /* Maybe reallocate a large block to a small fragment. */
- if (size <= BLOCKSIZE / 2)
- {
- result = malloc (size);
- if (result != NULL)
- {
- memcpy (result, ptr, size);
- free (ptr);
- return result;
- }
- }
-
- /* The new size is a large allocation as well;
- see if we can hold it in place. */
- blocks = BLOCKIFY (size);
- if (blocks < _heapinfo[block].busy.info.size)
- {
- /* The new size is smaller; return
- excess memory to the free list. */
- _heapinfo[block + blocks].busy.type = 0;
- _heapinfo[block + blocks].busy.info.size
- = _heapinfo[block].busy.info.size - blocks;
- _heapinfo[block].busy.info.size = blocks;
- free (ADDRESS (block + blocks));
- result = ptr;
- }
- else if (blocks == _heapinfo[block].busy.info.size)
- /* No size change necessary. */
- result = ptr;
- else
- {
- /* Won't fit, so allocate a new region that will.
- Free the old region first in case there is sufficient
- adjacent free space to grow without moving. */
- blocks = _heapinfo[block].busy.info.size;
- /* Prevent free from actually returning memory to the system. */
- oldlimit = _heaplimit;
- _heaplimit = 0;
- free (ptr);
- _heaplimit = oldlimit;
- result = malloc (size);
- if (result == NULL)
- {
- /* Now we're really in trouble. We have to unfree
- the thing we just freed. Unfortunately it might
- have been coalesced with its neighbors. */
- if (_heapindex == block)
- (void) malloc (blocks * BLOCKSIZE);
- else
- {
- __ptr_t previous = malloc ((block - _heapindex) * BLOCKSIZE);
- (void) malloc (blocks * BLOCKSIZE);
- free (previous);
- }
- return NULL;
- }
- if (ptr != result)
- memmove (result, ptr, blocks * BLOCKSIZE);
- }
- break;
-
- default:
- /* Old size is a fragment; type is logarithm
- to base two of the fragment size. */
- if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))
- /* The new size is the same kind of fragment. */
- result = ptr;
- else
- {
- /* The new size is different; allocate a new space,
- and copy the lesser of the new size and the old. */
- result = malloc (size);
- if (result == NULL)
- return NULL;
- memcpy (result, ptr, min (size, (size_t) 1 << type));
- free (ptr);
- }
- break;
- }
-
- return result;
-}
-/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
-
- The author may be reached (Email) at the address mike@ai.mit.edu,
- or (US mail) as Mike Haertel c/o Free Software Foundation. */
-
-#ifndef _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
-
-/* Allocate an array of NMEMB elements each SIZE bytes long.
- The entire array is initialized to zeros. */
-__ptr_t
-calloc (nmemb, size)
- register size_t nmemb;
- register size_t size;
-{
- register __ptr_t result = malloc (nmemb * size);
-
- if (result != NULL)
- (void) memset (result, 0, nmemb * size);
-
- return result;
-}
-/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-
-The GNU C Library is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with the GNU C Library; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#ifndef _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
-
-#ifndef __GNU_LIBRARY__
-#define __sbrk sbrk
-#ifdef VMS
-#define __brk brk
-#endif
-#endif
-
-extern __ptr_t __sbrk __P ((int increment));
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#if defined(emacs) && defined(VMS)
-/* Dumping of Emacs on VMS does not include the heap!
- So let's make a huge array from which initial data will be
- allocated.
-
- VMS_ALLOCATION_SIZE is the amount of memory we preallocate.
- We don't want it to be too large, because it only gives a larger
- dump file. The way to check how much is really used is to
- make VMS_ALLOCATION_SIZE very large, to link Emacs with the
- debugger, run Emacs, check how much was allocated. Then set
- VMS_ALLOCATION_SIZE to something suitable, recompile gmalloc,
- relink Emacs, and you should be off.
-
- N.B. This is experimental, but it worked quite fine on Emacs 18.
-*/
-#ifndef VMS_ALLOCATION_SIZE
-#define VMS_ALLOCATION_SIZE (512*(512+128))
-#endif
-
-int vms_out_initial = 0;
-char vms_initial_buffer[VMS_ALLOCATION_SIZE];
-char *vms_current_brk = vms_initial_buffer;
-char *vms_end_brk = &vms_initial_buffer[VMS_ALLOCATION_SIZE-1];
-
-__ptr_t
-__vms_initial_morecore (increment)
- ptrdiff_t increment;
-{
- __ptr_t result = NULL;
- __ptr_t temp;
-
- /* It's far easier to make the alignment here than to make a
- kludge in align () */
-#ifdef RL_DEBUG
- printf(">>>foo... %p...", vms_current_brk);
-#endif
- vms_current_brk += (BLOCKSIZE - ((unsigned long) vms_current_brk
- & (BLOCKSIZE - 1))) & (BLOCKSIZE - 1);
-#ifdef RL_DEBUG
- printf("bar... %p. (%d)\n", vms_current_brk, increment);
-#endif
- temp = vms_current_brk + (int) increment;
- if (temp <= vms_end_brk)
- {
- if (increment >= 0)
- result = vms_current_brk;
- else
- result = temp;
- vms_current_brk = temp;
- }
- return result;
-}
-
-__ptr_t
-__vms_initial_lesscore (ptr, size)
- __ptr_t ptr;
- ptrdiff_t size;
-{
- if (ptr >= vms_initial_buffer
- && ptr < vms_initial_buffer+VMS_ALLOCATION_SIZE)
- {
- vms_current_brk = ptr;
- return vms_current_brk;
- }
- return vms_current_brk;
-}
-
-VMS_present_buffer()
-{
- printf("Vms initial buffer starts at 0%o/0x%x/%d and ends at 0%o/0x%x/%d\n",
- vms_initial_buffer, vms_initial_buffer, vms_initial_buffer,
- vms_end_brk, vms_end_brk, vms_end_brk);
-}
-#endif /* defined(emacs) && defined(VMS) */
-
-#ifdef VMS
-/* Unfortunately, the VAX C sbrk() is buggy. For example, it returns
- memory in 512 byte chunks (not a bug, but there's more), AND it
- adds an extra 512 byte chunk if you ask for a multiple of 512
- bytes (you ask for 512 bytes, you get 1024 bytes...). And also,
- the VAX C sbrk does not handle negative increments...
- There's a similar problem with brk(). Even if you set the break
- to an even page boundary, it gives you one extra page... */
-
-static char vms_brk_info_fetched = -1; /* -1 if this is the first time, otherwise
- bit 0 set if 'increment' needs adjustment
- bit 1 set if the value to brk() needs adjustment */
-static char *vms_brk_start = 0;
-static char *vms_brk_end = 0;
-static char *vms_brk_current = 0;
-#endif
-
-/* Allocate INCREMENT more bytes of data space,
- and return the start of data space, or NULL on errors.
- If INCREMENT is negative, shrink data space. */
-__ptr_t
-__default_morecore (increment)
- ptrdiff_t increment;
-{
- __ptr_t result;
-#ifdef VMS
- __ptr_t temp;
-
-#ifdef RL_DEBUG
- printf("DEBUG: morecore: increment = %x\n", increment);
- printf(" @ start: vms_brk_info_fetched = %x\n", vms_brk_info_fetched);
- printf(" vms_brk_start = %p\n", vms_brk_start);
- printf(" vms_brk_current = %p\n", vms_brk_current);
- printf(" vms_brk_end = %p\n", vms_brk_end);
- printf(" @ end: ");
-#endif
-
- if (vms_brk_info_fetched < 0)
- {
- vms_brk_current = vms_brk_start = __sbrk (512);
- vms_brk_end = __sbrk (0);
- if (vms_brk_end - vms_brk_current == 1024)
- vms_brk_info_fetched = 1;
- else
- vms_brk_info_fetched = 0;
- vms_brk_end = brk(vms_brk_start);
- if (vms_brk_end != vms_brk_start)
- vms_brk_info_fetched |= 2;
-#ifdef RL_DEBUG
- printf("vms_brk_info_fetched = %x\n", vms_brk_info_fetched);
- printf(" vms_brk_start = %p\n", vms_brk_start);
- printf(" vms_brk_current = %p\n", vms_brk_current);
- printf(" vms_brk_end = %p\n", vms_brk_end);
- printf(" ");
-#endif
- }
-
- if (increment < 0)
- {
- printf("BZZZZZT! ERROR: __default_morecore does NOT take negative args\n");
- return NULL;
- }
-
- if (increment > 0)
- {
- result = vms_brk_current;
- temp = vms_brk_current + increment;
-
- if (temp > vms_brk_end)
- {
- __ptr_t foo;
-
- foo = __sbrk (0);
- if (foo == vms_brk_end)
- {
- increment = temp - vms_brk_end;
- if (increment > (vms_brk_info_fetched & 1))
- increment -= (vms_brk_info_fetched & 1);
- foo = __sbrk(increment);
-#ifdef RL_DEBUG
- printf("__sbrk(%d) --> %p\n", increment, foo);
-#endif
- if (foo == (__ptr_t) -1)
- return NULL;
-#ifdef RL_DEBUG
- printf(" ");
-#endif
- }
- else
- {
- result = __sbrk (increment);
-
- if (result == (__ptr_t) -1)
- return NULL;
-
- temp = result + increment;
- }
-
- vms_brk_end = __sbrk(0);
- }
- vms_brk_current = temp;
-#ifdef RL_DEBUG
- printf("vms_brk_current = %p\n", vms_brk_current);
- printf(" vms_brk_end = %p\n", vms_brk_end);
-#endif
- return result;
- }
-#ifdef RL_DEBUG
- printf(" nothing more...\n");
-#endif
-
- /* OK, so the user wanted to check where the heap limit is. Let's
- see if the system thinks it is where we think it is. */
- temp = __sbrk (0);
- if (temp != vms_brk_end)
- {
- /* the value has changed.
- Let's trust the system and modify our value */
- vms_brk_current = vms_brk_end = temp;
- }
- return vms_brk_current;
-
-#else /* not VMS */
- result = __sbrk ((int) increment);
- if (result == (__ptr_t) -1)
- return NULL;
- return result;
-#endif /* VMS */
-}
-
-__ptr_t
-__default_lesscore (ptr, size)
- __ptr_t ptr;
- ptrdiff_t size;
-{
-#ifdef VMS
- if (vms_brk_end != 0)
- {
- vms_brk_current = ptr;
- if (vms_brk_current < vms_brk_start)
- vms_brk_current = vms_brk_start;
- vms_brk_end = (char *) vms_brk_current -
- ((vms_brk_info_fetched >> 1) & 1);
-#ifdef RL_DEBUG
- printf("<<<bar... %p (%p (%p, %d))...",
- vms_brk_end, vms_brk_current, ptr, size);
-#endif
- vms_brk_end = __brk (vms_brk_end);
-#ifdef RL_DEBUG
- printf("foo... %p.\n", vms_brk_end);
-#endif
- }
-
- return vms_brk_current;
-#else /* not VMS */
- __default_morecore (-size);
-#endif
-}
-
-/* Allocate memory on a page boundary.
- Copyright (C) 1991, 1992 Free Software Foundation, Inc.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
-
- The author may be reached (Email) at the address mike@ai.mit.edu,
- or (US mail) as Mike Haertel c/o Free Software Foundation. */
-
-#ifndef _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
-
-#if defined (emacs) || defined (HAVE_CONFIG_H)
-#include "config.h"
-#endif
-
-#ifdef __GNU_LIBRARY__
-extern size_t __getpagesize __P ((void));
-#else
-#if !defined(USG) && !defined(VMS)
-extern size_t getpagesize __P ((void));
-#define __getpagesize() getpagesize()
-#else
-#include <sys/param.h>
-#ifdef EXEC_PAGESIZE
-#define __getpagesize() EXEC_PAGESIZE
-#else /* No EXEC_PAGESIZE. */
-#ifdef NBPG
-#ifndef CLSIZE
-#define CLSIZE 1
-#endif /* No CLSIZE. */
-#define __getpagesize() (NBPG * CLSIZE)
-#else /* No NBPG. */
-#define __getpagesize() NBPC
-#endif /* NBPG. */
-#endif /* EXEC_PAGESIZE. */
-#endif /* USG. */
-#endif
-
-static size_t pagesize;
-
-__ptr_t
-valloc (size)
- size_t size;
-{
- if (pagesize == 0)
- pagesize = __getpagesize ();
-
- return memalign (pagesize, size);
-}
-/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA. */
-
-#ifndef _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
-
-__ptr_t
-memalign (alignment, size)
- size_t alignment;
- size_t size;
-{
- __ptr_t result;
- unsigned long int adj;
-
- size = ((size + alignment - 1) / alignment) * alignment;
-
- result = malloc (size);
- if (result == NULL)
- return NULL;
- adj = (unsigned long int) ((unsigned long int) ((char *) result -
- (char *) NULL)) % alignment;
- if (adj != 0)
- {
- struct alignlist *l;
- for (l = _aligned_blocks; l != NULL; l = l->next)
- if (l->aligned == NULL)
- /* This slot is free. Use it. */
- break;
- if (l == NULL)
- {
- l = (struct alignlist *) malloc (sizeof (struct alignlist));
- if (l == NULL)
- {
- free (result);
- return NULL;
- }
- }
- l->exact = result;
- result = l->aligned = (char *) result + alignment - adj;
- l->next = _aligned_blocks;
- _aligned_blocks = l;
- }
-
- return result;
-}
-
-#ifdef VMS
-struct vms_malloc_data
-{
- int __malloc_initialized;
- char *_heapbase;
- malloc_info *_heapinfo;
- size_t heapsize;
- size_t _heapindex;
- size_t _heaplimit;
- size_t _chunks_used;
- size_t _bytes_used;
- size_t _chunks_free;
- size_t _bytes_free;
-} ____vms_malloc_data[] =
-{
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-};
-
-struct vms_core_routines
-{
- __ptr_t (*__morecore) __P ((ptrdiff_t increment));
- __ptr_t (*__lesscore) __P ((__ptr_t address, ptrdiff_t increment));
-} ____vms_core_routines[] =
-{
- { __vms_initial_morecore, __vms_initial_lesscore },
- { __default_morecore, __default_lesscore },
- { 0, 0 }
-};
-
-static int current_vms_data = -1;
-static int current_vms_core_routines = 0;
-
-static void use_vms_core_routines (int i)
-{
- current_vms_core_routines = i;
- current_vms_data = i;
-}
-
-static void use_vms_data (int i)
-{
- use_vms_core_routines (i);
- __malloc_initialized = ____vms_malloc_data[i].__malloc_initialized;
- _heapbase = ____vms_malloc_data[i]._heapbase;
- _heapinfo = ____vms_malloc_data[i]._heapinfo;
- heapsize = ____vms_malloc_data[i].heapsize;
- _heapindex = ____vms_malloc_data[i]._heapindex;
- _heaplimit = ____vms_malloc_data[i]._heaplimit;
- _chunks_used = ____vms_malloc_data[i]._chunks_used;
- _bytes_used = ____vms_malloc_data[i]._bytes_used;
- _chunks_free = ____vms_malloc_data[i]._chunks_free;
- _bytes_free = ____vms_malloc_data[i]._bytes_free;
-}
-
-static void store_vms_data (int i)
-{
- ____vms_malloc_data[i].__malloc_initialized = __malloc_initialized;
- ____vms_malloc_data[i]._heapbase = _heapbase;
- ____vms_malloc_data[i]._heapinfo = _heapinfo;
- ____vms_malloc_data[i].heapsize = heapsize;
- ____vms_malloc_data[i]._heapindex = _heapindex;
- ____vms_malloc_data[i]._heaplimit = _heaplimit;
- ____vms_malloc_data[i]._chunks_used = _chunks_used;
- ____vms_malloc_data[i]._bytes_used = _bytes_used;
- ____vms_malloc_data[i]._chunks_free = _chunks_free;
- ____vms_malloc_data[i]._bytes_free = _bytes_free;
-}
-
-static void store_current_vms_data ()
-{
- switch (current_vms_data)
- {
- case 0:
- case 1:
- store_vms_data (current_vms_data);
- break;
- }
-}
-
-__ptr_t __vms_morecore (increment)
- ptrdiff_t increment;
-{
- return
- (*____vms_core_routines[current_vms_core_routines].__morecore) (increment);
-}
-
-__ptr_t __vms_lesscore (ptr, increment)
- __ptr_t ptr;
- ptrdiff_t increment;
-{
- return
- (*____vms_core_routines[current_vms_core_routines].__lesscore) (ptr,increment);
-}
-
-__ptr_t __vms_malloc (size)
- size_t size;
-{
- __ptr_t result;
- int old_current_vms_data = current_vms_data;
-
- __malloc_hook = 0;
-
- store_current_vms_data ();
-
- if (____vms_malloc_data[0]._heapbase != 0)
- use_vms_data (0);
- else
- use_vms_core_routines (0);
- result = malloc (size);
- store_vms_data (0);
- if (result == NULL)
- {
- use_vms_data (1);
- result = malloc (size);
- store_vms_data (1);
- vms_out_initial = 1;
- }
- __malloc_hook = __vms_malloc;
- if (old_current_vms_data != -1)
- use_vms_data (current_vms_data);
- return result;
-}
-
-void __vms_free (ptr)
- __ptr_t ptr;
-{
- int old_current_vms_data = current_vms_data;
-
- __free_hook = 0;
-
- store_current_vms_data ();
-
- if (ptr >= vms_initial_buffer && ptr <= vms_end_brk)
- {
- use_vms_data (0);
- free (ptr);
- store_vms_data (0);
- }
- else
- {
- use_vms_data (1);
- free (ptr);
- store_vms_data (1);
- if (_chunks_free == 0 && _chunks_used == 0)
- vms_out_initial = 0;
- }
- __free_hook = __vms_free;
- if (old_current_vms_data != -1)
- use_vms_data (current_vms_data);
-}
-
-__ptr_t __vms_realloc (ptr, size)
- __ptr_t ptr;
- size_t size;
-{
- __ptr_t result;
- int old_current_vms_data = current_vms_data;
-
- __realloc_hook = 0;
-
- store_current_vms_data ();
-
- if (ptr >= vms_initial_buffer && ptr <= vms_end_brk)
- {
- use_vms_data (0);
- result = realloc (ptr, size);
- store_vms_data (0);
- }
- else
- {
- use_vms_data (1);
- result = realloc (ptr, size);
- store_vms_data (1);
- }
- __realloc_hook = __vms_realloc;
- if (old_current_vms_data != -1)
- use_vms_data (current_vms_data);
- return result;
-}
-#endif /* VMS */
-/* Standard debugging hooks for `malloc'.
- Copyright 1990, 1991, 1992 Free Software Foundation
- Written May 1989 by Mike Haertel.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
-
- The author may be reached (Email) at the address mike@ai.mit.edu,
- or (US mail) as Mike Haertel c/o Free Software Foundation. */
-
-#ifndef _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
-
-/* Old hook values. */
-static void (*old_free_hook) __P ((__ptr_t ptr));
-static __ptr_t (*old_malloc_hook) __P ((size_t size));
-static __ptr_t (*old_realloc_hook) __P ((__ptr_t ptr, size_t size));
-
-/* Function to call when something awful happens. */
-static void (*abortfunc) __P ((void));
-
-/* Arbitrary magical numbers. */
-#define MAGICWORD 0xfedabeeb
-#define MAGICBYTE ((char) 0xd7)
-
-struct hdr
- {
- size_t size; /* Exact size requested by user. */
- unsigned long int magic; /* Magic number to check header integrity. */
- };
-
-static void checkhdr __P ((__const struct hdr *));
-static void
-checkhdr (hdr)
- __const struct hdr *hdr;
-{
- if (hdr->magic != MAGICWORD || ((char *) &hdr[1])[hdr->size] != MAGICBYTE)
- (*abortfunc) ();
-}
-
-static void freehook __P ((__ptr_t));
-static void
-freehook (ptr)
- __ptr_t ptr;
-{
- struct hdr *hdr = ((struct hdr *) ptr) - 1;
- checkhdr (hdr);
- hdr->magic = 0;
- __free_hook = old_free_hook;
- free (hdr);
- __free_hook = freehook;
-}
-
-static __ptr_t mallochook __P ((size_t));
-static __ptr_t
-mallochook (size)
- size_t size;
-{
- struct hdr *hdr;
-
- __malloc_hook = old_malloc_hook;
- hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1);
- __malloc_hook = mallochook;
- if (hdr == NULL)
- return NULL;
-
- hdr->size = size;
- hdr->magic = MAGICWORD;
- ((char *) &hdr[1])[size] = MAGICBYTE;
- return (__ptr_t) (hdr + 1);
-}
-
-static __ptr_t reallochook __P ((__ptr_t, size_t));
-static __ptr_t
-reallochook (ptr, size)
- __ptr_t ptr;
- size_t size;
-{
- struct hdr *hdr = ((struct hdr *) ptr) - 1;
-
- checkhdr (hdr);
- __free_hook = old_free_hook;
- __malloc_hook = old_malloc_hook;
- __realloc_hook = old_realloc_hook;
- hdr = (struct hdr *) realloc ((__ptr_t) hdr, sizeof (struct hdr) + size + 1);
- __free_hook = freehook;
- __malloc_hook = mallochook;
- __realloc_hook = reallochook;
- if (hdr == NULL)
- return NULL;
-
- hdr->size = size;
- ((char *) &hdr[1])[size] = MAGICBYTE;
- return (__ptr_t) (hdr + 1);
-}
-
-int
-mcheck (func)
- void (*func) __P ((void));
-{
- extern void abort __P ((void));
- static int mcheck_used = 0;
-
- abortfunc = (func != NULL) ? func : abort;
-
- /* These hooks may not be safely inserted if malloc is already in use. */
- if (!__malloc_initialized && !mcheck_used)
- {
- old_free_hook = __free_hook;
- __free_hook = freehook;
- old_malloc_hook = __malloc_hook;
- __malloc_hook = mallochook;
- old_realloc_hook = __realloc_hook;
- __realloc_hook = reallochook;
- mcheck_used = 1;
- }
-
- return mcheck_used ? 0 : -1;
-}
-/* More debugging hooks for `malloc'.
- Copyright (C) 1991, 1992 Free Software Foundation, Inc.
- Written April 2, 1991 by John Gilmore of Cygnus Support.
- Based on mcheck.c by Mike Haertel.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
-
- The author may be reached (Email) at the address mike@ai.mit.edu,
- or (US mail) as Mike Haertel c/o Free Software Foundation. */
-
-#ifndef _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
-
-#include <stdio.h>
-
-#ifndef __GNU_LIBRARY__
-extern char *getenv ();
-#else
-#include <stdlib.h>
-#endif
-
-static FILE *mallstream;
-static char mallenv[]= "MALLOC_TRACE";
-static char mallbuf[BUFSIZ]; /* Buffer for the output. */
-
-/* Address to breakpoint on accesses to... */
-__ptr_t mallwatch;
-
-/* Old hook values. */
-static __ptr_t (*tr_old_morecore) __P ((ptrdiff_t increment));
-static __ptr_t (*tr_old_lesscore) __P ((__ptr_t ptr, ptrdiff_t increment));
-static void (*tr_old_free_hook) __P ((__ptr_t ptr));
-static __ptr_t (*tr_old_malloc_hook) __P ((size_t size));
-static __ptr_t (*tr_old_realloc_hook) __P ((__ptr_t ptr, size_t size));
-
-/* This function is called when the block being alloc'd, realloc'd, or
- freed has an address matching the variable "mallwatch". In a debugger,
- set "mallwatch" to the address of interest, then put a breakpoint on
- tr_break. */
-
-void tr_break __P ((void));
-void
-tr_break ()
-{
-}
-
-static void tr_freehook __P ((__ptr_t));
-static void
-tr_freehook (ptr)
- __ptr_t ptr;
-{
- fprintf (mallstream, "- %p\n", ptr); /* Be sure to print it first. */
- if (ptr == mallwatch)
- tr_break ();
- __free_hook = tr_old_free_hook;
- free (ptr);
- __free_hook = tr_freehook;
-}
-
-static __ptr_t tr_morecore __P ((ptrdiff_t));
-static __ptr_t
-tr_morecore (increment)
- ptrdiff_t increment;
-{
- __ptr_t p;
-
- __morecore = tr_old_morecore;
- p = (__ptr_t) (*__morecore) (increment);
- __morecore = tr_morecore;
-
- fprintf (mallstream, "$ %p %d\n", p, increment);
-
- return p;
-}
-
-static __ptr_t tr_lesscore __P ((__ptr_t, ptrdiff_t));
-static __ptr_t
-tr_lesscore (ptr, increment)
- __ptr_t ptr;
- ptrdiff_t increment;
-{
- __ptr_t p;
-
- __lesscore = tr_old_lesscore;
- p = (__ptr_t) (*__lesscore) (ptr, increment);
- __lesscore = tr_lesscore;
-
- fprintf (mallstream, "* %p (%p, %d)\n", p, ptr, increment);
-
- return p;
-}
-
-static __ptr_t tr_mallochook __P ((size_t));
-static __ptr_t
-tr_mallochook (size)
- size_t size;
-{
- __ptr_t hdr;
-
- __malloc_hook = tr_old_malloc_hook;
- hdr = (__ptr_t) malloc (size);
- __malloc_hook = tr_mallochook;
-
- /* We could be printing a NULL here; that's OK. */
- fprintf (mallstream, "+ %p %x\n", hdr, size);
-
- if (hdr == mallwatch)
- tr_break ();
-
- return hdr;
-}
-
-static __ptr_t tr_reallochook __P ((__ptr_t, size_t));
-static __ptr_t
-tr_reallochook (ptr, size)
- __ptr_t ptr;
- size_t size;
-{
- __ptr_t hdr;
-
- if (ptr == mallwatch)
- tr_break ();
-
- __free_hook = tr_old_free_hook;
- __malloc_hook = tr_old_malloc_hook;
- __realloc_hook = tr_old_realloc_hook;
- hdr = (__ptr_t) realloc (ptr, size);
- __free_hook = tr_freehook;
- __malloc_hook = tr_mallochook;
- __realloc_hook = tr_reallochook;
- if (hdr == NULL)
- /* Failed realloc. */
- fprintf (mallstream, "! %p %x\n", ptr, size);
- else
- fprintf (mallstream, "< %p\n> %p %x\n", ptr, hdr, size);
-
- if (hdr == mallwatch)
- tr_break ();
-
- return hdr;
-}
-
-/* We enable tracing if either the environment variable MALLOC_TRACE
- is set, or if the variable mallwatch has been patched to an address
- that the debugging user wants us to stop on. When patching mallwatch,
- don't forget to set a breakpoint on tr_break! */
-
-void
-mtrace ()
-{
- char *mallfile;
-
- mallfile = getenv (mallenv);
- if (mallfile != NULL || mallwatch != NULL)
- {
- mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w");
- if (mallstream != NULL)
- {
- /* Be sure it doesn't malloc its buffer! */
- setbuf (mallstream, mallbuf);
- fprintf (mallstream, "= Start\n");
-#if defined(emacs) && defined(VMS)
- fprintf (mallstream, "= Initial buffer spans %p -- %p\n",
- vms_initial_buffer, vms_end_brk + 1);
-#endif
- tr_old_morecore = __morecore;
- __morecore = tr_morecore;
- tr_old_lesscore = __lesscore;
- __lesscore = tr_lesscore;
- tr_old_free_hook = __free_hook;
- __free_hook = tr_freehook;
- tr_old_malloc_hook = __malloc_hook;
- __malloc_hook = tr_mallochook;
- tr_old_realloc_hook = __realloc_hook;
- __realloc_hook = tr_reallochook;
- }
- }
-}
-/* Access the statistics maintained by `malloc'.
- Copyright 1990, 1991, 1992 Free Software Foundation
- Written May 1989 by Mike Haertel.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
-
- The author may be reached (Email) at the address mike@ai.mit.edu,
- or (US mail) as Mike Haertel c/o Free Software Foundation. */
-
-#ifndef _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
-
-struct mstats
-mstats ()
-{
- struct mstats result;
-
- result.bytes_total = (char *) (*__morecore) (0) - _heapbase;
- result.chunks_used = _chunks_used;
- result.bytes_used = _bytes_used;
- result.chunks_free = _chunks_free;
- result.bytes_free = _bytes_free;
- return result;
-}
diff --git a/src/vmsmap.c b/src/vmsmap.c
deleted file mode 100644
index 7d05c4bd263..00000000000
--- a/src/vmsmap.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/* 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* 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. */
-
-globaldef {"$D$ATA"} char sdata[512]; /* Start of saved data area */
-globaldef {"__DATA"} char edata[512]; /* End of saved data area */
-
-/* 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 = &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] = map_data.sdata;
- inadr[1] = 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 = &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
deleted file mode 100644
index ae2d9ba4a5c..00000000000
--- a/src/vmspaths.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Hey Emacs, this is -*- C -*- code! */
-
-/* The default search path for Lisp function "load".
- This sets load-path. */
-#define PATH_LOADSEARCH "EMACS_LIBRARY:[LOCAL-LISP],EMACS_LIBRARY:[LISP]"
-
-/* Like PATH_LOADSEARCH, but used only when Emacs is dumping. This
- path is usually identical to PATH_LOADSEARCH except that the entry
- for the directory containing the installed lisp files has been
- replaced with ../lisp. */
-#define PATH_DUMPLOADSEARCH "[-.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 name in it sets the Lisp
- variable exec-directory. exec-directory is used for finding
- executables and other architecture-dependent files. */
-#define PATH_EXEC "EMACS_LIBRARY:[LIB-SRC]"
-
-/* Where Emacs should look for its architecture-independent data
- files, like the docstring file. The lisp variable data-directory
- is set to this value. */
-#define PATH_DATA "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 c229a914bd3..00000000000
--- a/src/vmsproc.c
+++ /dev/null
@@ -1,795 +0,0 @@
-/* Interfaces to subprocesses on VMS.
- Copyright (C) 1988, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/*
- 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 <config.h>
-#include <ssdef.h>
-#include <iodef.h>
-#include <dvidef.h>
-#include <clidef.h>
-#include "vmsproc.h"
-#include "lisp.h"
-#include "buffer.h"
-#include <file.h>
-#include "process.h"
-#include "commands.h"
-#include <errno.h>
-extern Lisp_Object call_process_cleanup ();
-
-
-#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 (STRINGP (current_buffer->directory))
- 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 || NILP (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 (INTEGERP (buffer))
- {
- 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 (!INTEGERP (buffer))
- {
- 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 (INTEGERP (buffer))
- {
-#ifndef subprocesses
- wait_without_blocking ();
-#endif subprocesses
- return Qnil;
- }
-
- if (!NILP (display) && INTERACTIVE)
- prepare_menu_bars ();
-
- record_unwind_protect (call_process_cleanup,
- Fcons (make_number (fd[0]), make_number (pid)));
-
-
- if (BUFFERP (buffer))
- Fset_buffer (buffer);
-
- immediate_quit = 1;
- QUIT;
-
- while (1)
- {
- sys$waitfr (vs->eventFlag);
- if (vs->iosb[0] & 1)
- {
- immediate_quit = 0;
- if (!NILP (buffer))
- {
- vs->iosb[1] = clean_vms_buffer (vs->inputBuffer, vs->iosb[1]);
- InsCStr (vs->inputBuffer, vs->iosb[1]);
- }
- if (!NILP (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 subtract 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;
- XSETFASTINT (XPROCESS (process)->infd, inchannel);
- XSETFASTINT (XPROCESS (process)->outfd, outchannel);
- XPROCESS (process)->status = Qrun
-
- /* 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));
-
- XSETFASTINT (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;
-
- p->status = Fcons (Qexit, Fcons (make_number (vs->exitStatus), Qnil))
-}
-
-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/vmsproc.h b/src/vmsproc.h
deleted file mode 100644
index f6faddf6a3e..00000000000
--- a/src/vmsproc.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- Structure for storing VMS specific information for an EMACS process
-
- We use the event flags 1-23 for processes, keyboard input and timer
-*/
-
-/*
- Same as MAXDESC in process.c
-*/
-#define MAX_EVENT_FLAGS 23
-
-typedef struct {
- char inputBuffer[1024];
- short inputChan;
- short outputChan;
- short busy;
- int pid;
- int eventFlag;
- int exitStatus;
- short iosb[4];
-} VMS_PROC_STUFF;
diff --git a/src/vmstime.c b/src/vmstime.c
deleted file mode 100644
index 4eec5d0a4de..00000000000
--- a/src/vmstime.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/* Time support for VMS.
- Copyright (C) 1993 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include <config.h>
-#include "vmstime.h"
-
-long timezone=0;
-int daylight=0;
-
-static char tzname_default[20]="";
-static char tzname_dst[20]="";
-
-char *tzname[2] = { tzname_default, tzname_dst };
-
-static long internal_daylight=0;
-static char daylight_set=0;
-
-static long read_time(const char *nptr, const char **endptr,
- int sign_allowed_p)
-{
- int t;
-
- *endptr = nptr;
-
- /* This routine trusts the user very much, and does no checks!
- The only exception is this: */
- if (!sign_allowed_p && (*nptr == '-' || *nptr == '+'))
- return 0;
-
- t = strtol(*endptr, endptr, 10) * 3600;
- if (**endptr != ':' || **endptr == '+' || **endptr == '-')
- return t;
- (*endptr)++;
-
- t = t + strtol(*endptr, endptr, 10) * 60;
- if (**endptr != ':' || **endptr == '+' || **endptr == '-')
- return t;
- (*endptr)++;
-
- return t + strtol(*endptr, endptr, 10);
-}
-
-static void read_dst_time(const char *nptr, const char **endptr,
- int *m, int *n, int *d,
- int *leap_p)
-{
- time_t bintim = time(0);
- struct tm *lc = localtime(&bintim);
-
- *leap_p = 1;
- *m = 0; /* When m and n are 0, a Julian */
- *n = 0; /* date has been inserted in d */
-
- switch(*nptr)
- {
- case 'M':
- {
- /* This routine counts on the user to have specified "Mm.n.d",
- where 1 <= n <= 5, 1 <= m <= 12, 0 <= d <= 6 */
-
- *m = strtol(++nptr, endptr, 10);
- (*endptr)++; /* Skip the dot */
- *n = strtol(*endptr, endptr, 10);
- (*endptr)++; /* Skip the dot */
- *d = strtol(*endptr, endptr, 10);
-
- return;
- }
- case 'J':
- *leap_p = 0; /* Never count with leap years */
- default: /* trust the user to have inserted a number! */
- *d = strtol(++nptr, endptr, 10);
- return;
- }
-}
-
-struct vms_vectim
-{
- short year, month, day, hour, minute, second, centi_second;
-};
-static void find_dst_time(int m, int n, long d,
- int hour, int minute, int second,
- int leap_p,
- long vms_internal_time[2])
-{
- long status = SYS$GETTIM(vms_internal_time);
- struct vms_vectim vms_vectime;
- status = SYS$NUMTIM(&vms_vectime, vms_internal_time);
-
- if (m == 0 && n == 0)
- {
- long tmp_vms_internal_time[2][2];
- long day_of_year;
- long tmp_operation = LIB$K_DAY_OF_YEAR;
-
- status = LIB$CVT_FROM_INTERNAL_TIME(&tmp_operation, &day_of_year,
- vms_internal_time);
-
- vms_vectime.month = 2;
- vms_vectime.day = 29;
- status = LIB$CVT_VECTIM(&vms_vectime, tmp_vms_internal_time[0]);
- if (status & 1) /* This is a leap year */
- {
- if (!leap_p && d > 59)
- d ++; /* If we don't count with 29th Feb,
- and this is a leap year, count up,
- to make day 60 really become the
- 1st March. */
- }
- /* 1st January, at midnight */
- vms_vectime.month = 1;
- vms_vectime.day = 1;
- vms_vectime.hour = hour;
- vms_vectime.minute = minute;
- vms_vectime.second = second;
- vms_vectime.centi_second = 0;
- status = LIB$CVT_VECTIM(&vms_vectime, tmp_vms_internal_time[0]);
- tmp_operation = LIB$K_DELTA_DAYS;
- status = LIB$CVT_TO_INTERNAL_TIME(&tmp_operation, &d,
- tmp_vms_internal_time[1]);
- /* now, tmp_vms_interval_time[0] contains 1st Jan, 00:00:00,
- and tmp_vms_interval_time[1] contains delta time +d days.
- Let's just add them together */
- status = LIB$ADD_TIMES(tmp_vms_internal_time[0],
- tmp_vms_internal_time[1],
- vms_internal_time);
- }
- else
- {
- long tmp_vms_internal_time[2];
- long day_of_week;
- long tmp_operation = LIB$K_DAY_OF_YEAR;
-
- if (d == 0) /* 0 is Sunday, which isn't compatible with VMS,
- where day_of_week is 1 -- 7, and 1 is Monday */
- {
- d = 7; /* So a simple conversion is required */
- }
- vms_vectime.month = m;
- vms_vectime.day = 1;
- vms_vectime.hour = hour;
- vms_vectime.minute = minute;
- vms_vectime.second = second;
- vms_vectime.centi_second = 0;
- status = LIB$CVT_VECTIM(&vms_vectime, tmp_vms_internal_time);
- tmp_operation = LIB$K_DAY_OF_WEEK;
- status = LIB$CVT_FROM_INTERNAL_TIME(&tmp_operation, &day_of_week,
- tmp_vms_internal_time);
- d -= day_of_week;
- if (d < 0)
- {
- d += 7;
- }
- vms_vectime.day += (n-1)*7 + d;
- status = LIB$CVT_VECTIM(&vms_vectime, vms_internal_time);
- if (!(status & 1))
- {
- vms_vectime.day -= 7; /* n was probably 5 */
- status = LIB$CVT_VECTIM(&vms_vectime, vms_internal_time);
- }
- }
-}
-
-static cmp_vms_internal_times(long vms_internal_time1[2],
- long vms_internal_time2[2])
-{
- if (vms_internal_time1[1] < vms_internal_time2[1])
- return -1;
- else
- if (vms_internal_time1[1] > vms_internal_time2[1])
- return 1;
-
- if (vms_internal_time1[0] < vms_internal_time2[0])
- return -1;
- else
- if (vms_internal_time1[0] > vms_internal_time2[0])
- return 1;
-
- return 0;
-}
-
-/* -------------------------- Global routines ------------------------------ */
-
-#ifdef tzset
-#undef tzset
-#endif
-void sys_tzset()
-{
- char *TZ;
- char *p, *q;
-
- if (daylight_set)
- return;
-
- daylight = 0;
-
- if ((TZ = getenv("TZ")) == 0)
- return;
-
- p = TZ;
- q = tzname[0];
-
- while(*p != '\0'
- && (*p <'0' || *p > '9') && *p != '-' && *p != '+' && *p != ',')
- *q++ = *p++;
- *q = '\0';
-
- /* This is special for VMS, so I don't care if it doesn't exist anywhere
- else */
-
- timezone = read_time(p, &p, 1);
-
- q = tzname[1];
-
- while(*p != '\0'
- && (*p <'0' || *p > '9') && *p != '-' && *p != '+' && *p != ',')
- *q++ = *p++;
- *q = '\0';
-
- if (*p != '-' && *p != '+' && !(*p >='0' && *p <= '9'))
- internal_daylight = timezone - 3600;
- else
- internal_daylight = read_time(p, &p, 1);
-
- if (*p == ',')
- {
- int start_m;
- int start_n;
- int start_d;
- int start_leap_p;
- int start_hour=2, start_minute=0, start_second=0;
-
- p++;
- read_dst_time(p, &p, &start_m, &start_n, &start_d, &start_leap_p);
- if (*p == '/')
- {
- long tmp = read_time (++p, &p, 0);
- start_hour = tmp / 3600;
- start_minute = (tmp % 3600) / 60;
- start_second = tmp % 60;
- }
- if (*p == ',')
- {
- int end_m;
- int end_n;
- int end_d;
- int end_leap_p;
- int end_hour=2, end_minute=0, end_second=0;
-
- p++;
- read_dst_time(p, &p, &end_m, &end_n, &end_d, &end_leap_p);
- if (*p == '/')
- {
- long tmp = read_time (++p, &p, 0);
- end_hour = tmp / 3600;
- end_minute = (tmp % 3600) / 60;
- end_second = tmp % 60;
- }
- {
- long vms_internal_time[3][2];
- find_dst_time(start_m, start_n, start_d,
- start_hour, start_minute, start_second,
- start_leap_p,
- vms_internal_time[0]);
- SYS$GETTIM(&vms_internal_time[1]);
- find_dst_time(end_m, end_n, end_d,
- end_hour, end_minute, end_second,
- end_leap_p,
- vms_internal_time[2]);
- if (cmp_vms_internal_times(vms_internal_time[0],
- vms_internal_time[1]) < 0
- && cmp_vms_internal_times(vms_internal_time[1],
- vms_internal_time[2]) < 0)
- daylight = 1;
- }
- }
- }
-}
-
-#ifdef localtime
-#undef localtime
-#endif
-struct tm *sys_localtime(time_t *clock)
-{
- struct tm *tmp = localtime(clock);
-
- sys_tzset();
- tmp->tm_isdst = daylight;
-
- return tmp;
-}
-
-#ifdef gmtime
-#undef gmtime
-#endif
-struct tm *sys_gmtime(time_t *clock)
-{
- static struct tm gmt;
- struct vms_vectim tmp_vectime;
- long vms_internal_time[3][2];
- long tmp_operation = LIB$K_DELTA_SECONDS;
- long status;
- long tmp_offset;
- char tmp_o_sign;
-
- sys_tzset();
-
- if (daylight)
- tmp_offset = internal_daylight;
- else
- tmp_offset = timezone;
-
- if (tmp_offset < 0)
- {
- tmp_o_sign = -1;
- tmp_offset = -tmp_offset;
- }
- else
- tmp_o_sign = 1;
-
- status = LIB$CVT_TO_INTERNAL_TIME(&tmp_operation, &tmp_offset,
- vms_internal_time[1]);
- status = SYS$GETTIM(vms_internal_time[0]);
- if (tmp_o_sign < 0)
- {
- status = LIB$SUB_TIMES(vms_internal_time[0],
- vms_internal_time[1],
- vms_internal_time[2]);
- }
- else
- {
- status = LIB$ADD_TIMES(vms_internal_time[0],
- vms_internal_time[1],
- vms_internal_time[2]);
- }
-
- status = SYS$NUMTIM(&tmp_vectime, vms_internal_time[2]);
- gmt.tm_sec = tmp_vectime.second;
- gmt.tm_min = tmp_vectime.minute;
- gmt.tm_hour = tmp_vectime.hour;
- gmt.tm_mday = tmp_vectime.day;
- gmt.tm_mon = tmp_vectime.month - 1;
- gmt.tm_year = tmp_vectime.year - 1900;
-
- tmp_operation = LIB$K_DAY_OF_WEEK;
- status = LIB$CVT_FROM_INTERNAL_TIME(&tmp_operation,
- &gmt.tm_wday,
- vms_internal_time[2]);
- if (gmt.tm_wday == 7) gmt.tm_wday = 0;
-
- tmp_operation = LIB$K_DAY_OF_YEAR;
- status = LIB$CVT_FROM_INTERNAL_TIME(&tmp_operation,
- &gmt.tm_yday,
- vms_internal_time[2]);
- gmt.tm_yday--;
- gmt.tm_isdst = daylight;
-
- return &gmt;
-}
-
diff --git a/src/vmstime.h b/src/vmstime.h
deleted file mode 100644
index c7198d755b9..00000000000
--- a/src/vmstime.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Interface to time support for VMS.
- Copyright (C) 1993 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifndef vmstime_h
-#define vmstime_h
-
-#include <time.h>
-#include <libdtdef.h>
-
-extern long timezone;
-extern int daylight;
-extern char *tzname[2];
-
-void sys_tzset();
-struct tm *sys_localtime(time_t *clock);
-struct tm *sys_gmtime(time_t *clock);
-
-#endif /* vmstime_h */
diff --git a/src/w32.c b/src/w32.c
deleted file mode 100644
index 79b3137363b..00000000000
--- a/src/w32.c
+++ /dev/null
@@ -1,2259 +0,0 @@
-/* Utility and Unix shadow routines for GNU Emacs on Windows NT.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
- Geoff Voelker (voelker@cs.washington.edu) 7-29-94
-*/
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <io.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <signal.h>
-#include <sys/time.h>
-
-/* must include CRT headers *before* config.h */
-#include "config.h"
-#undef access
-#undef chdir
-#undef chmod
-#undef creat
-#undef ctime
-#undef fopen
-#undef link
-#undef mkdir
-#undef mktemp
-#undef open
-#undef rename
-#undef rmdir
-#undef unlink
-
-#undef close
-#undef dup
-#undef dup2
-#undef pipe
-#undef read
-#undef write
-
-#define getwd _getwd
-#include "lisp.h"
-#undef getwd
-
-#include <pwd.h>
-
-#include <windows.h>
-
-#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
-#include <sys/socket.h>
-#undef socket
-#undef bind
-#undef connect
-#undef htons
-#undef ntohs
-#undef inet_addr
-#undef gethostname
-#undef gethostbyname
-#undef getservbyname
-#endif
-
-#include "w32.h"
-#include "ndir.h"
-#include "w32heap.h"
-
-/* Get the current working directory. */
-char *
-getwd (char *dir)
-{
- if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
- return dir;
- return NULL;
-}
-
-#ifndef HAVE_SOCKETS
-/* Emulate gethostname. */
-int
-gethostname (char *buffer, int size)
-{
- /* NT only allows small host names, so the buffer is
- certainly large enough. */
- return !GetComputerName (buffer, &size);
-}
-#endif /* HAVE_SOCKETS */
-
-/* Emulate getloadavg. */
-int
-getloadavg (double loadavg[], int nelem)
-{
- int i;
-
- /* A faithful emulation is going to have to be saved for a rainy day. */
- for (i = 0; i < nelem; i++)
- {
- loadavg[i] = 0.0;
- }
- return i;
-}
-
-/* Emulate the Unix directory procedures opendir, closedir,
- and readdir. We can't use the procedures supplied in sysdep.c,
- so we provide them here. */
-
-struct direct dir_static; /* simulated directory contents */
-static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
-static int dir_is_fat;
-static char dir_pathname[MAXPATHLEN+1];
-
-extern Lisp_Object Vw32_downcase_file_names;
-
-DIR *
-opendir (char *filename)
-{
- DIR *dirp;
-
- /* Opening is done by FindFirstFile. However, a read is inherent to
- this operation, so we defer the open until read time. */
-
- if (!(dirp = (DIR *) malloc (sizeof (DIR))))
- return NULL;
- if (dir_find_handle != INVALID_HANDLE_VALUE)
- return NULL;
-
- dirp->dd_fd = 0;
- dirp->dd_loc = 0;
- dirp->dd_size = 0;
-
- strncpy (dir_pathname, filename, MAXPATHLEN);
- dir_pathname[MAXPATHLEN] = '\0';
- dir_is_fat = is_fat_volume (filename, NULL);
-
- return dirp;
-}
-
-void
-closedir (DIR *dirp)
-{
- /* If we have a find-handle open, close it. */
- if (dir_find_handle != INVALID_HANDLE_VALUE)
- {
- FindClose (dir_find_handle);
- dir_find_handle = INVALID_HANDLE_VALUE;
- }
- xfree ((char *) dirp);
-}
-
-struct direct *
-readdir (DIR *dirp)
-{
- WIN32_FIND_DATA find_data;
-
- /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
- if (dir_find_handle == INVALID_HANDLE_VALUE)
- {
- char filename[MAXNAMLEN + 3];
- int ln;
-
- strcpy (filename, dir_pathname);
- ln = strlen (filename) - 1;
- if (!IS_DIRECTORY_SEP (filename[ln]))
- strcat (filename, "\\");
- strcat (filename, "*");
-
- dir_find_handle = FindFirstFile (filename, &find_data);
-
- if (dir_find_handle == INVALID_HANDLE_VALUE)
- return NULL;
- }
- else
- {
- if (!FindNextFile (dir_find_handle, &find_data))
- return NULL;
- }
-
- /* Emacs never uses this value, so don't bother making it match
- value returned by stat(). */
- dir_static.d_ino = 1;
-
- dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
- dir_static.d_namlen - dir_static.d_namlen % 4;
-
- dir_static.d_namlen = strlen (find_data.cFileName);
- strcpy (dir_static.d_name, find_data.cFileName);
- if (dir_is_fat)
- _strlwr (dir_static.d_name);
- else if (!NILP (Vw32_downcase_file_names))
- {
- register char *p;
- for (p = dir_static.d_name; *p; p++)
- if (*p >= 'a' && *p <= 'z')
- break;
- if (!*p)
- _strlwr (dir_static.d_name);
- }
-
- return &dir_static;
-}
-
-/* Emulate getpwuid, getpwnam and others. */
-
-#define PASSWD_FIELD_SIZE 256
-
-static char the_passwd_name[PASSWD_FIELD_SIZE];
-static char the_passwd_passwd[PASSWD_FIELD_SIZE];
-static char the_passwd_gecos[PASSWD_FIELD_SIZE];
-static char the_passwd_dir[PASSWD_FIELD_SIZE];
-static char the_passwd_shell[PASSWD_FIELD_SIZE];
-
-static struct passwd the_passwd =
-{
- the_passwd_name,
- the_passwd_passwd,
- 0,
- 0,
- 0,
- the_passwd_gecos,
- the_passwd_dir,
- the_passwd_shell,
-};
-
-int
-getuid ()
-{
- return the_passwd.pw_uid;
-}
-
-int
-geteuid ()
-{
- /* I could imagine arguing for checking to see whether the user is
- in the Administrators group and returning a UID of 0 for that
- case, but I don't know how wise that would be in the long run. */
- return getuid ();
-}
-
-int
-getgid ()
-{
- return the_passwd.pw_gid;
-}
-
-int
-getegid ()
-{
- return getgid ();
-}
-
-struct passwd *
-getpwuid (int uid)
-{
- if (uid == the_passwd.pw_uid)
- return &the_passwd;
- return NULL;
-}
-
-struct passwd *
-getpwnam (char *name)
-{
- struct passwd *pw;
-
- pw = getpwuid (getuid ());
- if (!pw)
- return pw;
-
- if (stricmp (name, pw->pw_name))
- return NULL;
-
- return pw;
-}
-
-void
-init_user_info ()
-{
- /* Find the user's real name by opening the process token and
- looking up the name associated with the user-sid in that token.
-
- Use the relative portion of the identifier authority value from
- the user-sid as the user id value (same for group id using the
- primary group sid from the process token). */
-
- char user_sid[256], name[256], domain[256];
- DWORD length = sizeof (name), dlength = sizeof (domain), trash;
- HANDLE token = NULL;
- SID_NAME_USE user_type;
-
- if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token)
- && GetTokenInformation (token, TokenUser,
- (PVOID) user_sid, sizeof (user_sid), &trash)
- && LookupAccountSid (NULL, *((PSID *) user_sid), name, &length,
- domain, &dlength, &user_type))
- {
- strcpy (the_passwd.pw_name, name);
- /* Determine a reasonable uid value. */
- if (stricmp ("administrator", name) == 0)
- {
- the_passwd.pw_uid = 0;
- the_passwd.pw_gid = 0;
- }
- else
- {
- SID_IDENTIFIER_AUTHORITY * pSIA;
-
- pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
- /* I believe the relative portion is the last 4 bytes (of 6)
- with msb first. */
- the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
- (pSIA->Value[3] << 16) +
- (pSIA->Value[4] << 8) +
- (pSIA->Value[5] << 0));
- /* restrict to conventional uid range for normal users */
- the_passwd.pw_uid = the_passwd.pw_uid % 60001;
-
- /* Get group id */
- if (GetTokenInformation (token, TokenPrimaryGroup,
- (PVOID) user_sid, sizeof (user_sid), &trash))
- {
- SID_IDENTIFIER_AUTHORITY * pSIA;
-
- pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
- the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
- (pSIA->Value[3] << 16) +
- (pSIA->Value[4] << 8) +
- (pSIA->Value[5] << 0));
- /* I don't know if this is necessary, but for safety... */
- the_passwd.pw_gid = the_passwd.pw_gid % 60001;
- }
- else
- the_passwd.pw_gid = the_passwd.pw_uid;
- }
- }
- /* If security calls are not supported (presumably because we
- are running under Windows 95), fallback to this. */
- else if (GetUserName (name, &length))
- {
- strcpy (the_passwd.pw_name, name);
- if (stricmp ("administrator", name) == 0)
- the_passwd.pw_uid = 0;
- else
- the_passwd.pw_uid = 123;
- the_passwd.pw_gid = the_passwd.pw_uid;
- }
- else
- {
- strcpy (the_passwd.pw_name, "unknown");
- the_passwd.pw_uid = 123;
- the_passwd.pw_gid = 123;
- }
-
- /* Ensure HOME and SHELL are defined. */
- if (getenv ("HOME") == NULL)
- putenv ("HOME=c:/");
- if (getenv ("SHELL") == NULL)
- putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
-
- /* Set dir and shell from environment variables. */
- strcpy (the_passwd.pw_dir, getenv ("HOME"));
- strcpy (the_passwd.pw_shell, getenv ("SHELL"));
-
- if (token)
- CloseHandle (token);
-}
-
-int
-random ()
-{
- /* rand () on NT gives us 15 random bits...hack together 30 bits. */
- return ((rand () << 15) | rand ());
-}
-
-void
-srandom (int seed)
-{
- srand (seed);
-}
-
-/* Normalize filename by converting all path separators to
- the specified separator. Also conditionally convert upper
- case path name components to lower case. */
-
-static void
-normalize_filename (fp, path_sep)
- register char *fp;
- char path_sep;
-{
- char sep;
- char *elem;
-
- /* Always lower-case drive letters a-z, even if the filesystem
- preserves case in filenames.
- This is so filenames can be compared by string comparison
- functions that are case-sensitive. Even case-preserving filesystems
- do not distinguish case in drive letters. */
- if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z')
- {
- *fp += 'a' - 'A';
- fp += 2;
- }
-
- if (NILP (Vw32_downcase_file_names))
- {
- while (*fp)
- {
- if (*fp == '/' || *fp == '\\')
- *fp = path_sep;
- fp++;
- }
- return;
- }
-
- sep = path_sep; /* convert to this path separator */
- elem = fp; /* start of current path element */
-
- do {
- if (*fp >= 'a' && *fp <= 'z')
- elem = 0; /* don't convert this element */
-
- if (*fp == 0 || *fp == ':')
- {
- sep = *fp; /* restore current separator (or 0) */
- *fp = '/'; /* after conversion of this element */
- }
-
- if (*fp == '/' || *fp == '\\')
- {
- if (elem && elem != fp)
- {
- *fp = 0; /* temporary end of string */
- _strlwr (elem); /* while we convert to lower case */
- }
- *fp = sep; /* convert (or restore) path separator */
- elem = fp + 1; /* next element starts after separator */
- sep = path_sep;
- }
- } while (*fp++);
-}
-
-/* Destructively turn backslashes into slashes. */
-void
-dostounix_filename (p)
- register char *p;
-{
- normalize_filename (p, '/');
-}
-
-/* Destructively turn slashes into backslashes. */
-void
-unixtodos_filename (p)
- register char *p;
-{
- normalize_filename (p, '\\');
-}
-
-/* Remove all CR's that are followed by a LF.
- (From msdos.c...probably should figure out a way to share it,
- although this code isn't going to ever change.) */
-int
-crlf_to_lf (n, buf)
- register int n;
- register unsigned char *buf;
-{
- unsigned char *np = buf;
- unsigned char *startp = buf;
- unsigned char *endp = buf + n;
-
- if (n == 0)
- return n;
- while (buf < endp - 1)
- {
- if (*buf == 0x0d)
- {
- if (*(++buf) != 0x0a)
- *np++ = 0x0d;
- }
- else
- *np++ = *buf++;
- }
- if (buf < endp)
- *np++ = *buf++;
- return np - startp;
-}
-
-/* Routines that are no-ops on NT but are defined to get Emacs to compile. */
-
-int
-sigsetmask (int signal_mask)
-{
- return 0;
-}
-
-int
-sigblock (int sig)
-{
- return 0;
-}
-
-int
-setpgrp (int pid, int gid)
-{
- return 0;
-}
-
-int
-alarm (int seconds)
-{
- return 0;
-}
-
-int
-unrequest_sigio (void)
-{
- return 0;
-}
-
-int
-request_sigio (void)
-{
- return 0;
-}
-
-#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
-
-LPBYTE
-w32_get_resource (key, lpdwtype)
- char *key;
- LPDWORD lpdwtype;
-{
- LPBYTE lpvalue;
- HKEY hrootkey = NULL;
- DWORD cbData;
- BOOL ok = FALSE;
-
- /* Check both the current user and the local machine to see if
- we have any resources. */
-
- if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
- {
- lpvalue = NULL;
-
- if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
- && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
- && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
- {
- return (lpvalue);
- }
-
- if (lpvalue) xfree (lpvalue);
-
- RegCloseKey (hrootkey);
- }
-
- if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
- {
- lpvalue = NULL;
-
- if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS &&
- (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL &&
- RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
- {
- return (lpvalue);
- }
-
- if (lpvalue) xfree (lpvalue);
-
- RegCloseKey (hrootkey);
- }
-
- return (NULL);
-}
-
-void
-init_environment ()
-{
- /* Check for environment variables and use registry if they don't exist */
- {
- int i;
- LPBYTE lpval;
- DWORD dwType;
-
- static char * env_vars[] =
- {
- "HOME",
- "PRELOAD_WINSOCK",
- "emacs_dir",
- "EMACSLOADPATH",
- "SHELL",
- "EMACSDATA",
- "EMACSPATH",
- "EMACSLOCKDIR",
- "INFOPATH",
- "EMACSDOC",
- "TERM",
- };
-
- for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
- {
- if (!getenv (env_vars[i]) &&
- (lpval = w32_get_resource (env_vars[i], &dwType)) != NULL)
- {
- if (dwType == REG_EXPAND_SZ)
- {
- char buf1[500], buf2[500];
-
- ExpandEnvironmentStrings ((LPSTR) lpval, buf1, 500);
- _snprintf (buf2, 499, "%s=%s", env_vars[i], buf1);
- putenv (strdup (buf2));
- }
- else if (dwType == REG_SZ)
- {
- char buf[500];
-
- _snprintf (buf, 499, "%s=%s", env_vars[i], lpval);
- putenv (strdup (buf));
- }
-
- xfree (lpval);
- }
- }
- }
-
- init_user_info ();
-}
-
-/* We don't have scripts to automatically determine the system configuration
- for Emacs before it's compiled, and we don't want to have to make the
- user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
- routine. */
-
-static char configuration_buffer[32];
-
-char *
-get_emacs_configuration (void)
-{
- char *arch, *oem, *os;
-
- /* Determine the processor type. */
- switch (get_processor_type ())
- {
-
-#ifdef PROCESSOR_INTEL_386
- case PROCESSOR_INTEL_386:
- case PROCESSOR_INTEL_486:
- case PROCESSOR_INTEL_PENTIUM:
- arch = "i386";
- break;
-#endif
-
-#ifdef PROCESSOR_INTEL_860
- case PROCESSOR_INTEL_860:
- arch = "i860";
- break;
-#endif
-
-#ifdef PROCESSOR_MIPS_R2000
- case PROCESSOR_MIPS_R2000:
- case PROCESSOR_MIPS_R3000:
- case PROCESSOR_MIPS_R4000:
- arch = "mips";
- break;
-#endif
-
-#ifdef PROCESSOR_ALPHA_21064
- case PROCESSOR_ALPHA_21064:
- arch = "alpha";
- break;
-#endif
-
- default:
- arch = "unknown";
- break;
- }
-
- /* Let oem be "*" until we figure out how to decode the OEM field. */
- oem = "*";
-
- os = (GetVersion () & 0x80000000) ? "win95" : "nt";
-
- sprintf (configuration_buffer, "%s-%s-%s%d.%d", arch, oem, os,
- get_w32_major_version (), get_w32_minor_version ());
- return configuration_buffer;
-}
-
-#include <sys/timeb.h>
-
-/* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
-void
-gettimeofday (struct timeval *tv, struct timezone *tz)
-{
- struct _timeb tb;
- _ftime (&tb);
-
- tv->tv_sec = tb.time;
- tv->tv_usec = tb.millitm * 1000L;
- if (tz)
- {
- tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
- tz->tz_dsttime = tb.dstflag; /* type of dst correction */
- }
-}
-
-/* ------------------------------------------------------------------------- */
-/* IO support and wrapper functions for W32 API. */
-/* ------------------------------------------------------------------------- */
-
-/* Place a wrapper around the MSVC version of ctime. It returns NULL
- on network directories, so we handle that case here.
- (Ulrich Leodolter, 1/11/95). */
-char *
-sys_ctime (const time_t *t)
-{
- char *str = (char *) ctime (t);
- return (str ? str : "Sun Jan 01 00:00:00 1970");
-}
-
-/* Emulate sleep...we could have done this with a define, but that
- would necessitate including windows.h in the files that used it.
- This is much easier. */
-void
-sys_sleep (int seconds)
-{
- Sleep (seconds * 1000);
-}
-
-/* Internal MSVC data and functions for low-level descriptor munging */
-#if (_MSC_VER == 900)
-extern char _osfile[];
-#endif
-extern int __cdecl _set_osfhnd (int fd, long h);
-extern int __cdecl _free_osfhnd (int fd);
-
-/* parallel array of private info on file handles */
-filedesc fd_info [ MAXDESC ];
-
-static struct {
- DWORD serialnum;
- DWORD maxcomp;
- DWORD flags;
- char name[32];
- char type[32];
-} volume_info;
-
-/* Get information on the volume where name is held; set path pointer to
- start of pathname in name (past UNC header\volume header if present). */
-int
-get_volume_info (const char * name, const char ** pPath)
-{
- char temp[MAX_PATH];
- char *rootname = NULL; /* default to current volume */
-
- if (name == NULL)
- return FALSE;
-
- /* find the root name of the volume if given */
- if (isalpha (name[0]) && name[1] == ':')
- {
- rootname = temp;
- temp[0] = *name++;
- temp[1] = *name++;
- temp[2] = '\\';
- temp[3] = 0;
- }
- else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
- {
- char *str = temp;
- int slashes = 4;
- rootname = temp;
- do
- {
- if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
- break;
- *str++ = *name++;
- }
- while ( *name );
-
- *str++ = '\\';
- *str = 0;
- }
-
- if (pPath)
- *pPath = name;
-
- if (GetVolumeInformation (rootname,
- volume_info.name, 32,
- &volume_info.serialnum,
- &volume_info.maxcomp,
- &volume_info.flags,
- volume_info.type, 32))
- {
- return TRUE;
- }
- return FALSE;
-}
-
-/* Determine if volume is FAT format (ie. only supports short 8.3
- names); also set path pointer to start of pathname in name. */
-int
-is_fat_volume (const char * name, const char ** pPath)
-{
- if (get_volume_info (name, pPath))
- return (volume_info.maxcomp == 12);
- return FALSE;
-}
-
-/* Map filename to a legal 8.3 name if necessary. */
-const char *
-map_w32_filename (const char * name, const char ** pPath)
-{
- static char shortname[MAX_PATH];
- char * str = shortname;
- char c;
- char * path;
-
- if (is_fat_volume (name, &path)) /* truncate to 8.3 */
- {
- register int left = 8; /* maximum number of chars in part */
- register int extn = 0; /* extension added? */
- register int dots = 2; /* maximum number of dots allowed */
-
- while (name < path)
- *str++ = *name++; /* skip past UNC header */
-
- while ((c = *name++))
- {
- switch ( c )
- {
- case '\\':
- case '/':
- *str++ = '\\';
- extn = 0; /* reset extension flags */
- dots = 2; /* max 2 dots */
- left = 8; /* max length 8 for main part */
- break;
- case ':':
- *str++ = ':';
- extn = 0; /* reset extension flags */
- dots = 2; /* max 2 dots */
- left = 8; /* max length 8 for main part */
- break;
- case '.':
- if ( dots )
- {
- /* Convert path components of the form .xxx to _xxx,
- but leave . and .. as they are. This allows .emacs
- to be read as _emacs, for example. */
-
- if (! *name ||
- *name == '.' ||
- IS_DIRECTORY_SEP (*name))
- {
- *str++ = '.';
- dots--;
- }
- else
- {
- *str++ = '_';
- left--;
- dots = 0;
- }
- }
- else if ( !extn )
- {
- *str++ = '.';
- extn = 1; /* we've got an extension */
- left = 3; /* 3 chars in extension */
- }
- else
- {
- /* any embedded dots after the first are converted to _ */
- *str++ = '_';
- }
- break;
- case '~':
- case '#': /* don't lose these, they're important */
- if ( ! left )
- str[-1] = c; /* replace last character of part */
- /* FALLTHRU */
- default:
- if ( left )
- {
- *str++ = tolower (c); /* map to lower case (looks nicer) */
- left--;
- dots = 0; /* started a path component */
- }
- break;
- }
- }
- *str = '\0';
- }
- else
- {
- strcpy (shortname, name);
- unixtodos_filename (shortname);
- }
-
- if (pPath)
- *pPath = shortname + (path - name);
-
- return shortname;
-}
-
-
-/* Shadow some MSVC runtime functions to map requests for long filenames
- to reasonable short names if necessary. This was originally added to
- permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
- long file names. */
-
-int
-sys_access (const char * path, int mode)
-{
- return _access (map_w32_filename (path, NULL), mode);
-}
-
-int
-sys_chdir (const char * path)
-{
- return _chdir (map_w32_filename (path, NULL));
-}
-
-int
-sys_chmod (const char * path, int mode)
-{
- return _chmod (map_w32_filename (path, NULL), mode);
-}
-
-int
-sys_creat (const char * path, int mode)
-{
- return _creat (map_w32_filename (path, NULL), mode);
-}
-
-FILE *
-sys_fopen(const char * path, const char * mode)
-{
- int fd;
- int oflag;
- const char * mode_save = mode;
-
- /* Force all file handles to be non-inheritable. This is necessary to
- ensure child processes don't unwittingly inherit handles that might
- prevent future file access. */
-
- if (mode[0] == 'r')
- oflag = O_RDONLY;
- else if (mode[0] == 'w' || mode[0] == 'a')
- oflag = O_WRONLY | O_CREAT | O_TRUNC;
- else
- return NULL;
-
- /* Only do simplistic option parsing. */
- while (*++mode)
- if (mode[0] == '+')
- {
- oflag &= ~(O_RDONLY | O_WRONLY);
- oflag |= O_RDWR;
- }
- else if (mode[0] == 'b')
- {
- oflag &= ~O_TEXT;
- oflag |= O_BINARY;
- }
- else if (mode[0] == 't')
- {
- oflag &= ~O_BINARY;
- oflag |= O_TEXT;
- }
- else break;
-
- fd = _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
- if (fd < 0)
- return NULL;
-
- return fdopen (fd, mode_save);
-}
-
-int
-sys_link (const char * path1, const char * path2)
-{
- errno = EINVAL;
- return -1;
-}
-
-int
-sys_mkdir (const char * path)
-{
- return _mkdir (map_w32_filename (path, NULL));
-}
-
-/* Because of long name mapping issues, we need to implement this
- ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
- a unique name, instead of setting the input template to an empty
- string.
-
- Standard algorithm seems to be use pid or tid with a letter on the
- front (in place of the 6 X's) and cycle through the letters to find a
- unique name. We extend that to allow any reasonable character as the
- first of the 6 X's. */
-char *
-sys_mktemp (char * template)
-{
- char * p;
- int i;
- unsigned uid = GetCurrentThreadId ();
- static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
-
- if (template == NULL)
- return NULL;
- p = template + strlen (template);
- i = 5;
- /* replace up to the last 5 X's with uid in decimal */
- while (--p >= template && p[0] == 'X' && --i >= 0)
- {
- p[0] = '0' + uid % 10;
- uid /= 10;
- }
-
- if (i < 0 && p[0] == 'X')
- {
- i = 0;
- do
- {
- int save_errno = errno;
- p[0] = first_char[i];
- if (sys_access (template, 0) < 0)
- {
- errno = save_errno;
- return template;
- }
- }
- while (++i < sizeof (first_char));
- }
-
- /* Template is badly formed or else we can't generate a unique name,
- so return empty string */
- template[0] = 0;
- return template;
-}
-
-int
-sys_open (const char * path, int oflag, int mode)
-{
- /* Force all file handles to be non-inheritable. */
- return _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, mode);
-}
-
-int
-sys_rename (const char * oldname, const char * newname)
-{
- char temp[MAX_PATH];
- DWORD attr;
-
- /* MoveFile on Win95 doesn't correctly change the short file name
- alias in a number of circumstances (it is not easy to predict when
- just by looking at oldname and newname, unfortunately). In these
- cases, renaming through a temporary name avoids the problem.
-
- A second problem on Win95 is that renaming through a temp name when
- newname is uppercase fails (the final long name ends up in
- lowercase, although the short alias might be uppercase) UNLESS the
- long temp name is not 8.3.
-
- So, on Win95 we always rename through a temp name, and we make sure
- the temp name has a long extension to ensure correct renaming. */
-
- strcpy (temp, map_w32_filename (oldname, NULL));
-
- if (GetVersion () & 0x80000000)
- {
- char * p;
-
- if (p = strrchr (temp, '\\'))
- p++;
- else
- p = temp;
- strcpy (p, "__XXXXXX");
- sys_mktemp (temp);
- /* Force temp name to require a manufactured 8.3 alias - this
- seems to make the second rename work properly. */
- strcat (temp, ".long");
- if (rename (map_w32_filename (oldname, NULL), temp) < 0)
- return -1;
- }
-
- /* Emulate Unix behaviour - newname is deleted if it already exists
- (at least if it is a file; don't do this for directories).
- However, don't do this if we are just changing the case of the file
- name - we will end up deleting the file we are trying to rename! */
- newname = map_w32_filename (newname, NULL);
- if (stricmp (newname, temp) != 0
- && (attr = GetFileAttributes (newname)) != -1
- && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0)
- {
- _chmod (newname, 0666);
- _unlink (newname);
- }
-
- return rename (temp, newname);
-}
-
-int
-sys_rmdir (const char * path)
-{
- return _rmdir (map_w32_filename (path, NULL));
-}
-
-int
-sys_unlink (const char * path)
-{
- return _unlink (map_w32_filename (path, NULL));
-}
-
-static FILETIME utc_base_ft;
-static long double utc_base;
-static int init = 0;
-
-static time_t
-convert_time (FILETIME ft)
-{
- long double ret;
-
- if (!init)
- {
- /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
- SYSTEMTIME st;
-
- st.wYear = 1970;
- st.wMonth = 1;
- st.wDay = 1;
- st.wHour = 0;
- st.wMinute = 0;
- st.wSecond = 0;
- st.wMilliseconds = 0;
-
- SystemTimeToFileTime (&st, &utc_base_ft);
- utc_base = (long double) utc_base_ft.dwHighDateTime
- * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
- init = 1;
- }
-
- if (CompareFileTime (&ft, &utc_base_ft) < 0)
- return 0;
-
- ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
- ret -= utc_base;
- return (time_t) (ret * 1e-7);
-}
-
-#if 0
-/* in case we ever have need of this */
-void
-convert_from_time_t (time_t time, FILETIME * pft)
-{
- long double tmp;
-
- if (!init)
- {
- /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
- SYSTEMTIME st;
-
- st.wYear = 1970;
- st.wMonth = 1;
- st.wDay = 1;
- st.wHour = 0;
- st.wMinute = 0;
- st.wSecond = 0;
- st.wMilliseconds = 0;
-
- SystemTimeToFileTime (&st, &utc_base_ft);
- utc_base = (long double) utc_base_ft.dwHighDateTime
- * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
- init = 1;
- }
-
- /* time in 100ns units since 1-Jan-1601 */
- tmp = (long double) time * 1e7 + utc_base;
- pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
- pft->dwLowDateTime = (DWORD) (tmp - pft->dwHighDateTime);
-}
-#endif
-
-/* "PJW" algorithm (see the "Dragon" compiler book). */
-static unsigned
-hashval (const char * str)
-{
- unsigned h = 0;
- unsigned g;
- while (*str)
- {
- h = (h << 4) + *str++;
- if ((g = h & 0xf0000000) != 0)
- h = (h ^ (g >> 24)) & 0x0fffffff;
- }
- return h;
-}
-
-/* Return the hash value of the canonical pathname, excluding the
- drive/UNC header, to get a hopefully unique inode number. */
-static _ino_t
-generate_inode_val (const char * name)
-{
- char fullname[ MAX_PATH ];
- char * p;
- unsigned hash;
-
- GetFullPathName (name, sizeof (fullname), fullname, &p);
- get_volume_info (fullname, &p);
- /* Normal W32 filesystems are still case insensitive. */
- _strlwr (p);
- hash = hashval (p);
- return (_ino_t) (hash ^ (hash >> 16));
-}
-
-/* MSVC stat function can't cope with UNC names and has other bugs, so
- replace it with our own. This also allows us to calculate consistent
- inode values without hacks in the main Emacs code. */
-int
-stat (const char * path, struct stat * buf)
-{
- char * name;
- WIN32_FIND_DATA wfd;
- HANDLE fh;
- int permission;
- int len;
- int rootdir = FALSE;
-
- if (path == NULL || buf == NULL)
- {
- errno = EFAULT;
- return -1;
- }
-
- name = (char *) map_w32_filename (path, &path);
- /* must be valid filename, no wild cards */
- if (strchr (name, '*') || strchr (name, '?'))
- {
- errno = ENOENT;
- return -1;
- }
-
- /* Remove trailing directory separator, unless name is the root
- directory of a drive or UNC volume in which case ensure there
- is a trailing separator. */
- len = strlen (name);
- rootdir = (path >= name + len - 1
- && (IS_DIRECTORY_SEP (*path) || *path == 0));
- name = strcpy (alloca (len + 2), name);
-
- if (rootdir)
- {
- if (!IS_DIRECTORY_SEP (name[len-1]))
- strcat (name, "\\");
- if (GetDriveType (name) < 2)
- {
- errno = ENOENT;
- return -1;
- }
- memset (&wfd, 0, sizeof (wfd));
- wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
- wfd.ftCreationTime = utc_base_ft;
- wfd.ftLastAccessTime = utc_base_ft;
- wfd.ftLastWriteTime = utc_base_ft;
- strcpy (wfd.cFileName, name);
- }
- else
- {
- if (IS_DIRECTORY_SEP (name[len-1]))
- name[len - 1] = 0;
- fh = FindFirstFile (name, &wfd);
- if (fh == INVALID_HANDLE_VALUE)
- {
- errno = ENOENT;
- return -1;
- }
- FindClose (fh);
- }
-
- if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- buf->st_mode = _S_IFDIR;
- buf->st_nlink = 2; /* doesn't really matter */
- }
- else
- {
-#if 0
- /* This is more accurate in terms of gettting the correct number
- of links, but is quite slow (it is noticable when Emacs is
- making a list of file name completions). */
- BY_HANDLE_FILE_INFORMATION info;
-
- fh = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
- if (GetFileInformationByHandle (fh, &info))
- {
- switch (GetFileType (fh))
- {
- case FILE_TYPE_DISK:
- buf->st_mode = _S_IFREG;
- break;
- case FILE_TYPE_PIPE:
- buf->st_mode = _S_IFIFO;
- break;
- case FILE_TYPE_CHAR:
- case FILE_TYPE_UNKNOWN:
- default:
- buf->st_mode = _S_IFCHR;
- }
- buf->st_nlink = info.nNumberOfLinks;
- /* Could use file index, but this is not guaranteed to be
- unique unless we keep a handle open all the time. */
- /* buf->st_ino = info.nFileIndexLow ^ info.nFileIndexHigh; */
- CloseHandle (fh);
- }
- else
- {
- errno = EACCES;
- return -1;
- }
-#else
- buf->st_mode = _S_IFREG;
- buf->st_nlink = 1;
-#endif
- }
-
- /* consider files to belong to current user */
- buf->st_uid = the_passwd.pw_uid;
- buf->st_gid = the_passwd.pw_gid;
-
- /* volume_info is set indirectly by map_w32_filename */
- buf->st_dev = volume_info.serialnum;
- buf->st_rdev = volume_info.serialnum;
-
- buf->st_ino = generate_inode_val (name);
-
- buf->st_size = wfd.nFileSizeLow;
-
- /* Convert timestamps to Unix format. */
- buf->st_mtime = convert_time (wfd.ftLastWriteTime);
- buf->st_atime = convert_time (wfd.ftLastAccessTime);
- if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
- buf->st_ctime = convert_time (wfd.ftCreationTime);
- if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
-
- /* determine rwx permissions */
- if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
- permission = _S_IREAD;
- else
- permission = _S_IREAD | _S_IWRITE;
-
- if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- permission |= _S_IEXEC;
- else
- {
- char * p = strrchr (name, '.');
- if (p != NULL &&
- (stricmp (p, ".exe") == 0 ||
- stricmp (p, ".com") == 0 ||
- stricmp (p, ".bat") == 0 ||
- stricmp (p, ".cmd") == 0))
- permission |= _S_IEXEC;
- }
-
- buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
-
- return 0;
-}
-
-#ifdef HAVE_SOCKETS
-
-/* Wrappers for winsock functions to map between our file descriptors
- and winsock's handles; also set h_errno for convenience.
-
- To allow Emacs to run on systems which don't have winsock support
- installed, we dynamically link to winsock on startup if present, and
- otherwise provide the minimum necessary functionality
- (eg. gethostname). */
-
-/* function pointers for relevant socket functions */
-int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
-void (PASCAL *pfn_WSASetLastError) (int iError);
-int (PASCAL *pfn_WSAGetLastError) (void);
-int (PASCAL *pfn_socket) (int af, int type, int protocol);
-int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
-int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
-int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
-int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
-int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
-int (PASCAL *pfn_closesocket) (SOCKET s);
-int (PASCAL *pfn_shutdown) (SOCKET s, int how);
-int (PASCAL *pfn_WSACleanup) (void);
-
-u_short (PASCAL *pfn_htons) (u_short hostshort);
-u_short (PASCAL *pfn_ntohs) (u_short netshort);
-unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
-int (PASCAL *pfn_gethostname) (char * name, int namelen);
-struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
-struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
-
-/* SetHandleInformation is only needed to make sockets non-inheritable. */
-BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
-#ifndef HANDLE_FLAG_INHERIT
-#define HANDLE_FLAG_INHERIT 1
-#endif
-
-HANDLE winsock_lib;
-static int winsock_inuse;
-
-BOOL
-term_winsock (void)
-{
- if (winsock_lib != NULL && winsock_inuse == 0)
- {
- /* Not sure what would cause WSAENETDOWN, or even if it can happen
- after WSAStartup returns successfully, but it seems reasonable
- to allow unloading winsock anyway in that case. */
- if (pfn_WSACleanup () == 0 ||
- pfn_WSAGetLastError () == WSAENETDOWN)
- {
- if (FreeLibrary (winsock_lib))
- winsock_lib = NULL;
- return TRUE;
- }
- }
- return FALSE;
-}
-
-BOOL
-init_winsock (int load_now)
-{
- WSADATA winsockData;
-
- if (winsock_lib != NULL)
- return TRUE;
-
- pfn_SetHandleInformation = NULL;
- pfn_SetHandleInformation
- = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
- "SetHandleInformation");
-
- winsock_lib = LoadLibrary ("wsock32.dll");
-
- if (winsock_lib != NULL)
- {
- /* dynamically link to socket functions */
-
-#define LOAD_PROC(fn) \
- if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
- goto fail;
-
- LOAD_PROC( WSAStartup );
- LOAD_PROC( WSASetLastError );
- LOAD_PROC( WSAGetLastError );
- LOAD_PROC( socket );
- LOAD_PROC( bind );
- LOAD_PROC( connect );
- LOAD_PROC( ioctlsocket );
- LOAD_PROC( recv );
- LOAD_PROC( send );
- LOAD_PROC( closesocket );
- LOAD_PROC( shutdown );
- LOAD_PROC( htons );
- LOAD_PROC( ntohs );
- LOAD_PROC( inet_addr );
- LOAD_PROC( gethostname );
- LOAD_PROC( gethostbyname );
- LOAD_PROC( getservbyname );
- LOAD_PROC( WSACleanup );
-
-#undef LOAD_PROC
-
- /* specify version 1.1 of winsock */
- if (pfn_WSAStartup (0x101, &winsockData) == 0)
- {
- if (winsockData.wVersion != 0x101)
- goto fail;
-
- if (!load_now)
- {
- /* Report that winsock exists and is usable, but leave
- socket functions disabled. I am assuming that calling
- WSAStartup does not require any network interaction,
- and in particular does not cause or require a dial-up
- connection to be established. */
-
- pfn_WSACleanup ();
- FreeLibrary (winsock_lib);
- winsock_lib = NULL;
- }
- winsock_inuse = 0;
- return TRUE;
- }
-
- fail:
- FreeLibrary (winsock_lib);
- winsock_lib = NULL;
- }
-
- return FALSE;
-}
-
-
-int h_errno = 0;
-
-/* function to set h_errno for compatability; map winsock error codes to
- normal system codes where they overlap (non-overlapping definitions
- are already in <sys/socket.h> */
-static void set_errno ()
-{
- if (winsock_lib == NULL)
- h_errno = EINVAL;
- else
- h_errno = pfn_WSAGetLastError ();
-
- switch (h_errno)
- {
- case WSAEACCES: h_errno = EACCES; break;
- case WSAEBADF: h_errno = EBADF; break;
- case WSAEFAULT: h_errno = EFAULT; break;
- case WSAEINTR: h_errno = EINTR; break;
- case WSAEINVAL: h_errno = EINVAL; break;
- case WSAEMFILE: h_errno = EMFILE; break;
- case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
- case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
- }
- errno = h_errno;
-}
-
-static void check_errno ()
-{
- if (h_errno == 0 && winsock_lib != NULL)
- pfn_WSASetLastError (0);
-}
-
-/* [andrewi 3-May-96] I've had conflicting results using both methods,
- but I believe the method of keeping the socket handle separate (and
- insuring it is not inheritable) is the correct one. */
-
-//#define SOCK_REPLACE_HANDLE
-
-#ifdef SOCK_REPLACE_HANDLE
-#define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
-#else
-#define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
-#endif
-
-int
-sys_socket(int af, int type, int protocol)
-{
- int fd;
- long s;
- child_process * cp;
-
- if (winsock_lib == NULL)
- {
- h_errno = ENETDOWN;
- return INVALID_SOCKET;
- }
-
- check_errno ();
-
- /* call the real socket function */
- s = (long) pfn_socket (af, type, protocol);
-
- if (s != INVALID_SOCKET)
- {
- /* Although under NT 3.5 _open_osfhandle will accept a socket
- handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
- that does not work under NT 3.1. However, we can get the same
- effect by using a backdoor function to replace an existing
- descriptor handle with the one we want. */
-
- /* allocate a file descriptor (with appropriate flags) */
- fd = _open ("NUL:", _O_RDWR);
- if (fd >= 0)
- {
-#ifdef SOCK_REPLACE_HANDLE
- /* now replace handle to NUL with our socket handle */
- CloseHandle ((HANDLE) _get_osfhandle (fd));
- _free_osfhnd (fd);
- _set_osfhnd (fd, s);
- /* setmode (fd, _O_BINARY); */
-#else
- /* Make a non-inheritable copy of the socket handle. */
- {
- HANDLE parent;
- HANDLE new_s = INVALID_HANDLE_VALUE;
-
- parent = GetCurrentProcess ();
-
- /* Apparently there is a bug in NT 3.51 with some service
- packs, which prevents using DuplicateHandle to make a
- socket handle non-inheritable (causes WSACleanup to
- hang). The work-around is to use SetHandleInformation
- instead if it is available and implemented. */
- if (!pfn_SetHandleInformation
- || !pfn_SetHandleInformation ((HANDLE) s,
- HANDLE_FLAG_INHERIT,
- HANDLE_FLAG_INHERIT))
- {
- DuplicateHandle (parent,
- (HANDLE) s,
- parent,
- &new_s,
- 0,
- FALSE,
- DUPLICATE_SAME_ACCESS);
- pfn_closesocket (s);
- s = (SOCKET) new_s;
- }
- fd_info[fd].hnd = (HANDLE) s;
- }
-#endif
-
- /* set our own internal flags */
- fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
-
- cp = new_child ();
- if (cp)
- {
- cp->fd = fd;
- cp->status = STATUS_READ_ACKNOWLEDGED;
-
- /* attach child_process to fd_info */
- if (fd_info[ fd ].cp != NULL)
- {
- DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
- abort ();
- }
-
- fd_info[ fd ].cp = cp;
-
- /* success! */
- winsock_inuse++; /* count open sockets */
- return fd;
- }
-
- /* clean up */
- _close (fd);
- }
- pfn_closesocket (s);
- h_errno = EMFILE;
- }
- set_errno ();
-
- return -1;
-}
-
-
-int
-sys_bind (int s, const struct sockaddr * addr, int namelen)
-{
- if (winsock_lib == NULL)
- {
- h_errno = ENOTSOCK;
- return SOCKET_ERROR;
- }
-
- check_errno ();
- if (fd_info[s].flags & FILE_SOCKET)
- {
- int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
- if (rc == SOCKET_ERROR)
- set_errno ();
- return rc;
- }
- h_errno = ENOTSOCK;
- return SOCKET_ERROR;
-}
-
-
-int
-sys_connect (int s, const struct sockaddr * name, int namelen)
-{
- if (winsock_lib == NULL)
- {
- h_errno = ENOTSOCK;
- return SOCKET_ERROR;
- }
-
- check_errno ();
- if (fd_info[s].flags & FILE_SOCKET)
- {
- int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
- if (rc == SOCKET_ERROR)
- set_errno ();
- return rc;
- }
- h_errno = ENOTSOCK;
- return SOCKET_ERROR;
-}
-
-u_short
-sys_htons (u_short hostshort)
-{
- return (winsock_lib != NULL) ?
- pfn_htons (hostshort) : hostshort;
-}
-
-u_short
-sys_ntohs (u_short netshort)
-{
- return (winsock_lib != NULL) ?
- pfn_ntohs (netshort) : netshort;
-}
-
-unsigned long
-sys_inet_addr (const char * cp)
-{
- return (winsock_lib != NULL) ?
- pfn_inet_addr (cp) : INADDR_NONE;
-}
-
-int
-sys_gethostname (char * name, int namelen)
-{
- if (winsock_lib != NULL)
- return pfn_gethostname (name, namelen);
-
- if (namelen > MAX_COMPUTERNAME_LENGTH)
- return !GetComputerName (name, &namelen);
-
- h_errno = EFAULT;
- return SOCKET_ERROR;
-}
-
-struct hostent *
-sys_gethostbyname(const char * name)
-{
- struct hostent * host;
-
- if (winsock_lib == NULL)
- {
- h_errno = ENETDOWN;
- return NULL;
- }
-
- check_errno ();
- host = pfn_gethostbyname (name);
- if (!host)
- set_errno ();
- return host;
-}
-
-struct servent *
-sys_getservbyname(const char * name, const char * proto)
-{
- struct servent * serv;
-
- if (winsock_lib == NULL)
- {
- h_errno = ENETDOWN;
- return NULL;
- }
-
- check_errno ();
- serv = pfn_getservbyname (name, proto);
- if (!serv)
- set_errno ();
- return serv;
-}
-
-#endif /* HAVE_SOCKETS */
-
-
-/* Shadow main io functions: we need to handle pipes and sockets more
- intelligently, and implement non-blocking mode as well. */
-
-int
-sys_close (int fd)
-{
- int rc;
-
- if (fd < 0 || fd >= MAXDESC)
- {
- errno = EBADF;
- return -1;
- }
-
- if (fd_info[fd].cp)
- {
- child_process * cp = fd_info[fd].cp;
-
- fd_info[fd].cp = NULL;
-
- if (CHILD_ACTIVE (cp))
- {
- /* if last descriptor to active child_process then cleanup */
- int i;
- for (i = 0; i < MAXDESC; i++)
- {
- if (i == fd)
- continue;
- if (fd_info[i].cp == cp)
- break;
- }
- if (i == MAXDESC)
- {
-#ifdef HAVE_SOCKETS
- if (fd_info[fd].flags & FILE_SOCKET)
- {
-#ifndef SOCK_REPLACE_HANDLE
- if (winsock_lib == NULL) abort ();
-
- pfn_shutdown (SOCK_HANDLE (fd), 2);
- rc = pfn_closesocket (SOCK_HANDLE (fd));
-#endif
- winsock_inuse--; /* count open sockets */
- }
-#endif
- delete_child (cp);
- }
- }
- }
-
- /* Note that sockets do not need special treatment here (at least on
- NT and Win95 using the standard tcp/ip stacks) - it appears that
- closesocket is equivalent to CloseHandle, which is to be expected
- because socket handles are fully fledged kernel handles. */
- rc = _close (fd);
-
- if (rc == 0)
- fd_info[fd].flags = 0;
-
- return rc;
-}
-
-int
-sys_dup (int fd)
-{
- int new_fd;
-
- new_fd = _dup (fd);
- if (new_fd >= 0)
- {
- /* duplicate our internal info as well */
- fd_info[new_fd] = fd_info[fd];
- }
- return new_fd;
-}
-
-
-int
-sys_dup2 (int src, int dst)
-{
- int rc;
-
- if (dst < 0 || dst >= MAXDESC)
- {
- errno = EBADF;
- return -1;
- }
-
- /* make sure we close the destination first if it's a pipe or socket */
- if (src != dst && fd_info[dst].flags != 0)
- sys_close (dst);
-
- rc = _dup2 (src, dst);
- if (rc == 0)
- {
- /* duplicate our internal info as well */
- fd_info[dst] = fd_info[src];
- }
- return rc;
-}
-
-/* From callproc.c */
-extern Lisp_Object Vbinary_process_input;
-extern Lisp_Object Vbinary_process_output;
-
-/* Unix pipe() has only one arg */
-int
-sys_pipe (int * phandles)
-{
- int rc;
- unsigned flags;
- child_process * cp;
-
- /* make pipe handles non-inheritable; when we spawn a child,
- we replace the relevant handle with an inheritable one. */
- rc = _pipe (phandles, 0, _O_NOINHERIT);
-
- if (rc == 0)
- {
- /* set internal flags, and put read and write handles into binary
- mode as necessary; if not in binary mode, set the MSVC internal
- FDEV (0x40) flag to prevent _read from treating ^Z as eof (this
- could otherwise allow Emacs to hang because it then waits
- indefinitely for the child process to exit, when it might not be
- finished). */
- flags = FILE_PIPE | FILE_READ;
- if (!NILP (Vbinary_process_output))
- {
- flags |= FILE_BINARY;
- setmode (phandles[0], _O_BINARY);
- }
-#if (_MSC_VER == 900)
- else
- _osfile[phandles[0]] |= 0x40;
-#endif
-
- fd_info[phandles[0]].flags = flags;
-
- flags = FILE_PIPE | FILE_WRITE;
- if (!NILP (Vbinary_process_input))
- {
- flags |= FILE_BINARY;
- setmode (phandles[1], _O_BINARY);
- }
-#if (_MSC_VER == 900)
- else
- _osfile[phandles[1]] |= 0x40;
-#endif
-
- fd_info[phandles[1]].flags = flags;
- }
-
- return rc;
-}
-
-/* From ntproc.c */
-extern Lisp_Object Vw32_pipe_read_delay;
-
-/* Function to do blocking read of one byte, needed to implement
- select. It is only allowed on sockets and pipes. */
-int
-_sys_read_ahead (int fd)
-{
- child_process * cp;
- int rc;
-
- if (fd < 0 || fd >= MAXDESC)
- return STATUS_READ_ERROR;
-
- cp = fd_info[fd].cp;
-
- if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
- return STATUS_READ_ERROR;
-
- if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
- || (fd_info[fd].flags & FILE_READ) == 0)
- {
- DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
- abort ();
- }
-
- cp->status = STATUS_READ_IN_PROGRESS;
-
- if (fd_info[fd].flags & FILE_PIPE)
- {
- /* Use read to get CRLF translation */
- rc = _read (fd, &cp->chr, sizeof (char));
-
- /* Give subprocess time to buffer some more output for us before
- reporting that input is available; we need this because Win95
- connects DOS programs to pipes by making the pipe appear to be
- the normal console stdout - as a result most DOS programs will
- write to stdout without buffering, ie. one character at a
- time. Even some W32 programs do this - "dir" in a command
- shell on NT is very slow if we don't do this. */
- if (rc > 0)
- {
- int wait = XINT (Vw32_pipe_read_delay);
-
- if (wait > 0)
- Sleep (wait);
- else if (wait < 0)
- while (++wait <= 0)
- /* Yield remainder of our time slice, effectively giving a
- temporary priority boost to the child process. */
- Sleep (0);
- }
- }
-#ifdef HAVE_SOCKETS
- else if (fd_info[fd].flags & FILE_SOCKET)
- rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
-#endif
-
- if (rc == sizeof (char))
- cp->status = STATUS_READ_SUCCEEDED;
- else
- cp->status = STATUS_READ_FAILED;
-
- return cp->status;
-}
-
-int
-sys_read (int fd, char * buffer, unsigned int count)
-{
- int nchars;
- int extra = 0;
- int to_read;
- DWORD waiting;
-
- if (fd < 0 || fd >= MAXDESC)
- {
- errno = EBADF;
- return -1;
- }
-
- if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
- {
- child_process *cp = fd_info[fd].cp;
-
- if ((fd_info[fd].flags & FILE_READ) == 0)
- {
- errno = EBADF;
- return -1;
- }
-
- /* presence of a child_process structure means we are operating in
- non-blocking mode - otherwise we just call _read directly.
- Note that the child_process structure might be missing because
- reap_subprocess has been called; in this case the pipe is
- already broken, so calling _read on it is okay. */
- if (cp)
- {
- int current_status = cp->status;
-
- switch (current_status)
- {
- case STATUS_READ_FAILED:
- case STATUS_READ_ERROR:
- /* report normal EOF */
- return 0;
-
- case STATUS_READ_READY:
- case STATUS_READ_IN_PROGRESS:
- DebPrint (("sys_read called when read is in progress\n"));
- errno = EWOULDBLOCK;
- return -1;
-
- case STATUS_READ_SUCCEEDED:
- /* consume read-ahead char */
- *buffer++ = cp->chr;
- count--;
- extra = 1;
- cp->status = STATUS_READ_ACKNOWLEDGED;
- ResetEvent (cp->char_avail);
-
- case STATUS_READ_ACKNOWLEDGED:
- break;
-
- default:
- DebPrint (("sys_read: bad status %d\n", current_status));
- errno = EBADF;
- return -1;
- }
-
- if (fd_info[fd].flags & FILE_PIPE)
- {
- PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
- to_read = min (waiting, (DWORD) count);
-
- /* Use read to get CRLF translation */
- nchars = _read (fd, buffer, to_read);
- }
-#ifdef HAVE_SOCKETS
- else /* FILE_SOCKET */
- {
- if (winsock_lib == NULL) abort ();
-
- /* do the equivalent of a non-blocking read */
- pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
- if (waiting == 0 && extra == 0)
- {
- h_errno = errno = EWOULDBLOCK;
- return -1;
- }
-
- nchars = 0;
- if (waiting)
- {
- /* always use binary mode for sockets */
- nchars = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
- if (nchars == SOCKET_ERROR)
- {
- DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
- pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
- if (extra == 0)
- {
- set_errno ();
- return -1;
- }
- nchars = 0;
- }
- }
- }
-#endif
- }
- else
- nchars = _read (fd, buffer, count);
- }
- else
- nchars = _read (fd, buffer, count);
-
- return nchars + extra;
-}
-
-/* For now, don't bother with a non-blocking mode */
-int
-sys_write (int fd, const void * buffer, unsigned int count)
-{
- int nchars;
-
- if (fd < 0 || fd >= MAXDESC)
- {
- errno = EBADF;
- return -1;
- }
-
- if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
- if ((fd_info[fd].flags & FILE_WRITE) == 0)
- {
- errno = EBADF;
- return -1;
- }
-#ifdef HAVE_SOCKETS
- if (fd_info[fd].flags & FILE_SOCKET)
- {
- if (winsock_lib == NULL) abort ();
- nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
- if (nchars == SOCKET_ERROR)
- {
- DebPrint(("sys_read.send failed with error %d on socket %ld\n",
- pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
- set_errno ();
- }
- }
- else
-#endif
- nchars = _write (fd, buffer, count);
-
- return nchars;
-}
-
-
-void
-term_ntproc ()
-{
-#ifdef HAVE_SOCKETS
- /* shutdown the socket interface if necessary */
- term_winsock ();
-#endif
-}
-
-extern BOOL dos_process_running;
-
-void
-init_ntproc ()
-{
-#ifdef HAVE_SOCKETS
- /* Initialise the socket interface now if available and requested by
- the user by defining PRELOAD_WINSOCK; otherwise loading will be
- delayed until open-network-stream is called (w32-has-winsock can
- also be used to dynamically load or reload winsock).
-
- Conveniently, init_environment is called before us, so
- PRELOAD_WINSOCK can be set in the registry. */
-
- /* Always initialize this correctly. */
- winsock_lib = NULL;
-
- if (getenv ("PRELOAD_WINSOCK") != NULL)
- init_winsock (TRUE);
-#endif
-
- /* Initial preparation for subprocess support: replace our standard
- handles with non-inheritable versions. */
- {
- HANDLE parent;
- HANDLE stdin_save = INVALID_HANDLE_VALUE;
- HANDLE stdout_save = INVALID_HANDLE_VALUE;
- HANDLE stderr_save = INVALID_HANDLE_VALUE;
-
- parent = GetCurrentProcess ();
-
- /* ignore errors when duplicating and closing; typically the
- handles will be invalid when running as a gui program. */
- DuplicateHandle (parent,
- GetStdHandle (STD_INPUT_HANDLE),
- parent,
- &stdin_save,
- 0,
- FALSE,
- DUPLICATE_SAME_ACCESS);
-
- DuplicateHandle (parent,
- GetStdHandle (STD_OUTPUT_HANDLE),
- parent,
- &stdout_save,
- 0,
- FALSE,
- DUPLICATE_SAME_ACCESS);
-
- DuplicateHandle (parent,
- GetStdHandle (STD_ERROR_HANDLE),
- parent,
- &stderr_save,
- 0,
- FALSE,
- DUPLICATE_SAME_ACCESS);
-
- fclose (stdin);
- fclose (stdout);
- fclose (stderr);
-
- if (stdin_save != INVALID_HANDLE_VALUE)
- _open_osfhandle ((long) stdin_save, O_TEXT);
- else
- open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
- fdopen (0, "r");
-
- if (stdout_save != INVALID_HANDLE_VALUE)
- _open_osfhandle ((long) stdout_save, O_TEXT);
- else
- open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
- fdopen (1, "w");
-
- if (stderr_save != INVALID_HANDLE_VALUE)
- _open_osfhandle ((long) stderr_save, O_TEXT);
- else
- open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
- fdopen (2, "w");
- }
-
- /* Restrict Emacs to running only one DOS program at a time (with any
- number of W32 programs). This is to prevent the user from
- running into problems with DOS programs being run in the same VDM
- under both Windows 95 and Windows NT.
-
- Note that it is possible for Emacs to run DOS programs in separate
- VDMs, but unfortunately the pipe implementation on Windows 95 then
- fails to report when the DOS process exits (which is supposed to
- break the pipe). Until this bug is fixed, or we can devise a
- work-around, we must try to avoid letting the user start more than
- one DOS program if possible. */
-
- dos_process_running = FALSE;
-
- /* unfortunately, atexit depends on implementation of malloc */
- /* atexit (term_ntproc); */
- signal (SIGABRT, term_ntproc);
-}
-
-/* end of nt.c */
diff --git a/src/w32.h b/src/w32.h
deleted file mode 100644
index 90ba7fbe015..00000000000
--- a/src/w32.h
+++ /dev/null
@@ -1,127 +0,0 @@
-#ifndef _NT_H_
-#define _NT_H_
-
-/* Support routines for the NT version of Emacs.
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* #define FULL_DEBUG */
-#define EMACSDEBUG
-
-#ifdef EMACSDEBUG
-#define DebPrint(stuff) _DebPrint stuff
-#else
-#define DebPrint(stuff)
-#endif
-
-/* File descriptor set emulation. */
-
-/* MSVC runtime library has limit of 64 descriptors by default */
-#define FD_SETSIZE 64
-typedef struct {
- unsigned int bits[FD_SETSIZE / 32];
-} fd_set;
-
-/* standard access macros */
-#define FD_SET(n, p) \
- do { \
- if ((n) < FD_SETSIZE) { \
- (p)->bits[(n)/32] |= (1 << (n)%32); \
- } \
- } while (0)
-#define FD_CLR(n, p) \
- do { \
- if ((n) < FD_SETSIZE) { \
- (p)->bits[(n)/32] &= ~(1 << (n)%32); \
- } \
- } while (0)
-#define FD_ISSET(n, p) ((n) < FD_SETSIZE ? ((p)->bits[(n)/32] & (1 << (n)%32)) : 0)
-#define FD_ZERO(p) memset((p), 0, sizeof(fd_set))
-
-#define SELECT_TYPE fd_set
-
-/* ------------------------------------------------------------------------- */
-
-/* child_process.status values */
-enum {
- STATUS_READ_ERROR = -1,
- STATUS_READ_READY,
- STATUS_READ_IN_PROGRESS,
- STATUS_READ_FAILED,
- STATUS_READ_SUCCEEDED,
- STATUS_READ_ACKNOWLEDGED
-};
-
-/* This structure is used for both pipes and sockets; for
- a socket, the process handle in pi is NULL. */
-typedef struct _child_process
-{
- int fd;
- int pid;
- int is_dos_process;
- HANDLE char_avail;
- HANDLE char_consumed;
- HANDLE thrd;
- PROCESS_INFORMATION procinfo;
- volatile int status;
- char chr;
-} child_process;
-
-#define MAXDESC FD_SETSIZE
-#define MAX_CHILDREN MAXDESC/2
-#define CHILD_ACTIVE(cp) ((cp)->char_avail != NULL)
-
-/* parallel array of private info on file handles */
-typedef struct
-{
- unsigned flags;
- HANDLE hnd;
- child_process * cp;
-} filedesc;
-
-extern filedesc fd_info [ MAXDESC ];
-
-/* fd_info flag definitions */
-#define FILE_READ 0x0001
-#define FILE_WRITE 0x0002
-#define FILE_BINARY 0x0010
-#define FILE_PIPE 0x0100
-#define FILE_SOCKET 0x0200
-
-extern child_process * new_child (void);
-extern void delete_child (child_process *cp);
-
-/* ------------------------------------------------------------------------- */
-
-
-/* Prepare our standard handles for proper inheritance by child processes. */
-extern void prepare_standard_handles (int in, int out,
- int err, HANDLE handles[4]);
-
-/* Reset our standard handles to their original state. */
-extern void reset_standard_handles (int in, int out,
- int err, HANDLE handles[4]);
-
-/* Return the string resource associated with KEY of type TYPE. */
-extern LPBYTE w32_get_resource (char * key, LPDWORD type);
-
-extern void init_ntproc ();
-extern void term_ntproc ();
-
-#endif /* _NT_H_ */
diff --git a/src/w32console.c b/src/w32console.c
deleted file mode 100644
index d80981b605a..00000000000
--- a/src/w32console.c
+++ /dev/null
@@ -1,635 +0,0 @@
-/* Terminal hooks for Windows NT port of GNU Emacs.
- 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
- Tim Fleehart (apollo@online.com) 1-17-92
- Geoff Voelker (voelker@cs.washington.edu) 9-12-93
-*/
-
-
-#include <config.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <windows.h>
-
-#include "lisp.h"
-#include "frame.h"
-#include "disptab.h"
-#include "termhooks.h"
-
-#include "w32inevt.h"
-
-/* from window.c */
-extern Lisp_Object Frecenter ();
-
-/* from keyboard.c */
-extern int detect_input_pending ();
-
-/* from sysdep.c */
-extern int read_input_pending ();
-
-extern FRAME_PTR updating_frame;
-extern int meta_key;
-
-static void move_cursor (int row, int col);
-static void clear_to_end (void);
-static void clear_frame (void);
-static void clear_end_of_line (int);
-static void ins_del_lines (int vpos, int n);
-static void change_line_highlight (int, int, int);
-static void reassert_line_highlight (int, int);
-static void insert_glyphs (GLYPH *start, int len);
-static void write_glyphs (GLYPH *string, int len);
-static void delete_glyphs (int n);
-void w32_sys_ring_bell (void);
-static void reset_terminal_modes (void);
-static void set_terminal_modes (void);
-static void set_terminal_window (int size);
-static void update_begin (FRAME_PTR f);
-static void update_end (FRAME_PTR f);
-static void reset_kbd (void);
-static void unset_kbd (void);
-static int hl_mode (int new_highlight);
-
-void
-DebPrint ()
-{
-}
-
-/* Init hook called in init_keyboard. */
-void (*keyboard_init_hook)(void) = reset_kbd;
-
-COORD cursor_coords;
-HANDLE prev_screen, cur_screen;
-UCHAR char_attr, char_attr_normal, char_attr_reverse;
-HANDLE keyboard_handle;
-DWORD prev_console_mode;
-
-
-/* Setting this as the ctrl handler prevents emacs from being killed when
- someone hits ^C in a 'suspended' session (child shell).
- Also ignore Ctrl-Break signals. */
-
-BOOL
-ctrl_c_handler (unsigned long type)
-{
- return (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT);
-}
-
-/* If we're updating a frame, use it as the current frame
- Otherwise, use the selected frame. */
-#define PICK_FRAME() (updating_frame ? updating_frame : selected_frame)
-
-/* Move the cursor to (row, col). */
-void
-move_cursor (int row, int col)
-{
- cursor_coords.X = col;
- cursor_coords.Y = row;
-
- if (updating_frame == (FRAME_PTR) NULL)
- {
- SetConsoleCursorPosition (cur_screen, cursor_coords);
- }
-}
-
-/* Clear from cursor to end of screen. */
-void
-clear_to_end (void)
-{
- FRAME_PTR f = PICK_FRAME ();
-
- clear_end_of_line (FRAME_WIDTH (f) - 1);
- ins_del_lines (cursor_coords.Y, FRAME_HEIGHT (f) - cursor_coords.Y - 1);
-}
-
-/* Clear the frame. */
-void
-clear_frame (void)
-{
- FRAME_PTR f = PICK_FRAME ();
- COORD dest;
- int n, r;
-
- hl_mode (0);
-
- n = FRAME_HEIGHT (f) * FRAME_WIDTH (f);
- dest.X = dest.Y = 0;
-
- FillConsoleOutputAttribute (cur_screen, char_attr, n, dest, &r);
- FillConsoleOutputCharacter (cur_screen, ' ', n, dest, &r);
-
- move_cursor (0, 0);
-}
-
-
-static GLYPH glyph_base[256];
-static BOOL ceol_initialized = FALSE;
-
-/* Clear from Cursor to end (what's "standout marker"?). */
-void
-clear_end_of_line (int end)
-{
- if (!ceol_initialized)
- {
- int i;
- for (i = 0; i < 256; i++)
- {
- glyph_base[i] = SPACEGLYPH; /* empty space */
- }
- ceol_initialized = TRUE;
- }
- write_glyphs (glyph_base, end - cursor_coords.X); /* fencepost ? */
-}
-
-/* Insert n lines at vpos. if n is negative delete -n lines. */
-void
-ins_del_lines (int vpos, int n)
-{
- int i, nb, save_highlight;
- SMALL_RECT scroll;
- COORD dest;
- CHAR_INFO fill;
- FRAME_PTR f = PICK_FRAME ();
-
- if (n < 0)
- {
- scroll.Top = vpos - n;
- scroll.Bottom = FRAME_HEIGHT (f);
- dest.Y = vpos;
- }
- else
- {
- scroll.Top = vpos;
- scroll.Bottom = FRAME_HEIGHT (f) - n;
- dest.Y = vpos + n;
- }
- scroll.Left = 0;
- scroll.Right = FRAME_WIDTH (f);
-
- dest.X = 0;
-
- save_highlight = hl_mode (0);
-
- fill.Char.AsciiChar = 0x20;
- fill.Attributes = char_attr;
-
- ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);
-
- /* Here we have to deal with a w32 console flake: If the scroll
- region looks like abc and we scroll c to a and fill with d we get
- cbd... if we scroll block c one line at a time to a, we get cdd...
- Emacs expects cdd consistently... So we have to deal with that
- here... (this also occurs scrolling the same way in the other
- direction. */
-
- if (n > 0)
- {
- if (scroll.Bottom < dest.Y)
- {
- for (i = scroll.Bottom; i < dest.Y; i++)
- {
- move_cursor (i, 0);
- clear_end_of_line (FRAME_WIDTH (f));
- }
- }
- }
- else
- {
- nb = dest.Y + (scroll.Bottom - scroll.Top) + 1;
-
- if (nb < scroll.Top)
- {
- for (i = nb; i < scroll.Top; i++)
- {
- move_cursor (i, 0);
- clear_end_of_line (FRAME_WIDTH (f));
- }
- }
- }
-
- cursor_coords.X = 0;
- cursor_coords.Y = vpos;
-
- hl_mode (save_highlight);
-}
-
-/* Changes attribute to use when drawing characters to control. */
-static int
-hl_mode (int new_highlight)
-{
- static int highlight = 0;
- int old_highlight;
-
- old_highlight = highlight;
- highlight = (new_highlight != 0);
- if (highlight)
- {
- char_attr = char_attr_reverse;
- }
- else
- {
- char_attr = char_attr_normal;
- }
- return old_highlight;
-}
-
-/* Call this when about to modify line at position VPOS and change whether it
- is highlighted. */
-void
-change_line_highlight (int new_highlight, int vpos, int first_unused_hpos)
-{
- hl_mode (new_highlight);
- move_cursor (vpos, 0);
- clear_end_of_line (first_unused_hpos);
-}
-
-/* External interface to control of standout mode. Call this when about to
- * modify line at position VPOS and not change whether it is highlighted. */
-void
-reassert_line_highlight (int highlight, int vpos)
-{
- hl_mode (highlight);
- vpos; /* pedantic compiler silencer */
-}
-
-#undef LEFT
-#undef RIGHT
-#define LEFT 1
-#define RIGHT 0
-
-void
-scroll_line (int dist, int direction)
-{
- /* The idea here is to implement a horizontal scroll in one line to
- implement delete and half of insert. */
- SMALL_RECT scroll;
- COORD dest;
- CHAR_INFO fill;
- FRAME_PTR f = PICK_FRAME ();
-
- scroll.Top = cursor_coords.Y;
- scroll.Bottom = cursor_coords.Y;
-
- if (direction == LEFT)
- {
- scroll.Left = cursor_coords.X + dist;
- scroll.Right = FRAME_WIDTH (f) - 1;
- }
- else
- {
- scroll.Left = cursor_coords.X;
- scroll.Right = FRAME_WIDTH (f) - dist - 1;
- }
-
- dest.X = cursor_coords.X;
- dest.Y = cursor_coords.Y;
-
- fill.Char.AsciiChar = 0x20;
- fill.Attributes = char_attr;
-
- ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);
-}
-
-
-/* If start is zero insert blanks instead of a string at start ?. */
-void
-insert_glyphs (register GLYPH *start, register int len)
-{
- scroll_line (len, RIGHT);
-
- /* Move len chars to the right starting at cursor_coords, fill with blanks */
- if (start)
- {
- /* Print the first len characters of start, cursor_coords.X adjusted
- by write_glyphs. */
-
- write_glyphs (start, len);
- }
- else
- {
- clear_end_of_line (cursor_coords.X + len);
- }
-}
-
-void
-write_glyphs (register GLYPH *string, register int len)
-{
- register unsigned int glyph_len = GLYPH_TABLE_LENGTH;
- Lisp_Object *glyph_table = GLYPH_TABLE_BASE;
- FRAME_PTR f = PICK_FRAME ();
- register char *ptr;
- GLYPH glyph;
- WORD *attrs;
- char *chars;
- int i;
-
- if (len <= 0)
- return;
-
- attrs = alloca (len * sizeof (*attrs));
- chars = alloca (len * sizeof (*chars));
- if (attrs == NULL || chars == NULL)
- {
- printf ("alloca failed in write_glyphs\n");
- return;
- }
-
- /* We have to deal with the glyph indirection...go over the glyph
- buffer and extract the characters. */
- ptr = chars;
- while (--len >= 0)
- {
- glyph = *string++;
-
- if (glyph > glyph_len)
- {
- *ptr++ = glyph & 0xFF;
- continue;
- }
- GLYPH_FOLLOW_ALIASES (glyph_table, glyph_len, glyph);
-#ifndef HAVE_NTGUI
- if (GLYPH_FACE (fixfix, glyph) != 0)
- printf ("Glyph face is %d\n", GLYPH_FACE (fixfix, glyph));
-#endif /* !HAVE_NTGUI */
- if (GLYPH_SIMPLE_P (glyph_table, glyph_len, glyph))
- {
- *ptr++ = glyph & 0xFF;
- continue;
- }
- for (i = 0; i < GLYPH_LENGTH (glyph_table, glyph); i++)
- {
- *ptr++ = (GLYPH_STRING (glyph_table, glyph))[i];
- }
- }
-
- /* Number of characters we have in the buffer. */
- len = ptr-chars;
-
- /* Fill in the attributes for these characters. */
- for (i = 0; i < len; i++)
- attrs[i] = char_attr;
-
- /* Write the attributes. */
- if (!WriteConsoleOutputAttribute (cur_screen, attrs, len, cursor_coords, &i))
- {
- printf ("Failed writing console attributes: %d\n", GetLastError ());
- fflush (stdout);
- }
-
- /* Write the characters. */
- if (!WriteConsoleOutputCharacter (cur_screen, chars, len, cursor_coords, &i))
- {
- printf ("Failed writing console characters: %d\n", GetLastError ());
- fflush (stdout);
- }
-
- cursor_coords.X += len;
- move_cursor (cursor_coords.Y, cursor_coords.X);
-}
-
-void
-delete_glyphs (int n)
-{
- /* delete chars means scroll chars from cursor_coords.X + n to
- cursor_coords.X, anything beyond the edge of the screen should
- come out empty... */
-
- scroll_line (n, LEFT);
-}
-
-static unsigned int sound_type = 0xFFFFFFFF;
-
-void
-w32_sys_ring_bell (void)
-{
- if (sound_type == 0xFFFFFFFF)
- Beep (666, 100);
- else
- MessageBeep (sound_type);
-}
-
-DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
- "Set the sound generated when the bell is rung.\n\
-SOUND is 'asterisk, 'exclamation, 'hand, 'question, or 'ok\n\
-to use the corresponding system sound for the bell.\n\
-SOUND is nil to use the normal beep.")
- (sound)
- Lisp_Object sound;
-{
- CHECK_SYMBOL (sound, 0);
-
- if (NILP (sound))
- sound_type = 0xFFFFFFFF;
- else if (EQ (sound, intern ("asterisk")))
- sound_type = MB_ICONASTERISK;
- else if (EQ (sound, intern ("exclamation")))
- sound_type = MB_ICONEXCLAMATION;
- else if (EQ (sound, intern ("hand")))
- sound_type = MB_ICONHAND;
- else if (EQ (sound, intern ("question")))
- sound_type = MB_ICONQUESTION;
- else if (EQ (sound, intern ("ok")))
- sound_type = MB_OK;
- else
- sound_type = 0xFFFFFFFF;
-
- return sound;
-}
-
-/* Put our console back up, for ending a suspended session. */
-void
-take_console (void)
-{
- reset_kbd ();
- SetConsoleActiveScreenBuffer (cur_screen);
-}
-
-void
-reset_terminal_modes (void)
-{
- unset_kbd ();
- SetConsoleActiveScreenBuffer (prev_screen);
-}
-
-void
-set_terminal_modes (void)
-{
- CONSOLE_CURSOR_INFO cci;
-
- if (cur_screen == NULL)
- {
- reset_kbd ();
- cur_screen = CreateConsoleScreenBuffer (GENERIC_READ | GENERIC_WRITE,
- 0, NULL,
- CONSOLE_TEXTMODE_BUFFER,
- NULL);
-
- if (cur_screen == INVALID_HANDLE_VALUE)
- {
- printf ("CreateConsoleScreenBuffer failed in ResetTerm\n");
- printf ("LastError = 0x%lx\n", GetLastError ());
- fflush (stdout);
- exit (0);
- }
-
- SetConsoleActiveScreenBuffer (cur_screen);
-
- /* make cursor big and visible (100 on Win95 makes it disappear) */
- cci.dwSize = 99;
- cci.bVisible = TRUE;
- (void) SetConsoleCursorInfo (cur_screen, &cci);
- }
-}
-
-/* hmmm... perhaps these let us bracket screen changes so that we can flush
- clumps rather than one-character-at-a-time...
-
- we'll start with not moving the cursor while an update is in progress. */
-void
-update_begin (FRAME_PTR f)
-{
-}
-
-void
-update_end (FRAME_PTR f)
-{
- SetConsoleCursorPosition (cur_screen, cursor_coords);
-}
-
-void
-set_terminal_window (int size)
-{
-}
-
-void
-unset_kbd (void)
-{
- SetConsoleMode (keyboard_handle, prev_console_mode);
-}
-
-void
-reset_kbd (void)
-{
- keyboard_handle = GetStdHandle (STD_INPUT_HANDLE);
- GetConsoleMode (keyboard_handle, &prev_console_mode);
- SetConsoleMode (keyboard_handle, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
-
- /* Try to use interrupt input; if we can't, then start polling. */
- Fset_input_mode (Qt, Qnil, Qt, Qnil);
-}
-
-typedef int (*term_hook) ();
-
-void
-initialize_win_nt_display (void)
-{
- CONSOLE_SCREEN_BUFFER_INFO info;
-
- cursor_to_hook = (term_hook) move_cursor;
- raw_cursor_to_hook = (term_hook) move_cursor;
- clear_to_end_hook = (term_hook) clear_to_end;
- clear_frame_hook = (term_hook) clear_frame;
- clear_end_of_line_hook = (term_hook) clear_end_of_line;
- ins_del_lines_hook = (term_hook) ins_del_lines;
- change_line_highlight_hook = (term_hook) change_line_highlight;
- reassert_line_highlight_hook = (term_hook) reassert_line_highlight;
- insert_glyphs_hook = (term_hook) insert_glyphs;
- write_glyphs_hook = (term_hook) write_glyphs;
- delete_glyphs_hook = (term_hook) delete_glyphs;
- ring_bell_hook = (term_hook) w32_sys_ring_bell;
- reset_terminal_modes_hook = (term_hook) reset_terminal_modes;
- set_terminal_modes_hook = (term_hook) set_terminal_modes;
- set_terminal_window_hook = (term_hook) set_terminal_window;
- update_begin_hook = (term_hook) update_begin;
- update_end_hook = (term_hook) update_end;
-
- read_socket_hook = w32_console_read_socket;
- mouse_position_hook = w32_mouse_position;
-
- prev_screen = GetStdHandle (STD_OUTPUT_HANDLE);
-
- set_terminal_modes ();
-
- GetConsoleScreenBufferInfo (cur_screen, &info);
-
- meta_key = 1;
- char_attr = info.wAttributes & 0xFF;
- char_attr_normal = char_attr;
- char_attr_reverse = ((char_attr & 0xf) << 4) + ((char_attr & 0xf0) >> 4);
-
- FRAME_HEIGHT (selected_frame) = info.dwSize.Y; /* lines per page */
- SET_FRAME_WIDTH (selected_frame, info.dwSize.X); /* characters per line */
-
- move_cursor (0, 0);
-
- clear_frame ();
-}
-
-DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
- "Set screen colors.")
- (foreground, background)
- Lisp_Object foreground;
- Lisp_Object background;
-{
- char_attr_normal = XFASTINT (foreground) + (XFASTINT (background) << 4);
- char_attr_reverse = XFASTINT (background) + (XFASTINT (foreground) << 4);
-
- Frecenter (Qnil);
- return Qt;
-}
-
-DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
- "Set cursor size.")
- (size)
- Lisp_Object size;
-{
- CONSOLE_CURSOR_INFO cci;
- cci.dwSize = XFASTINT (size);
- cci.bVisible = TRUE;
- (void) SetConsoleCursorInfo (cur_screen, &cci);
-
- return Qt;
-}
-
-#ifndef HAVE_NTGUI
-void
-pixel_to_glyph_coords (FRAME_PTR f, int pix_x, int pix_y, int *x, int *y,
- void *bounds, int noclip)
-{
- *x = pix_x;
- *y = pix_y;
-}
-
-void
-glyph_to_pixel_coords (FRAME_PTR f, int x, int y, int *pix_x, int *pix_y)
-{
- *pix_x = x;
- *pix_y = y;
-}
-#endif /* !HAVE_NTGUI */
-
-void
-syms_of_ntterm ()
-{
- defsubr (&Sset_screen_color);
- defsubr (&Sset_cursor_size);
- defsubr (&Sset_message_beep);
-}
diff --git a/src/w32faces.c b/src/w32faces.c
deleted file mode 100644
index 1328dd8cab5..00000000000
--- a/src/w32faces.c
+++ /dev/null
@@ -1,1047 +0,0 @@
-/* "Face" primitives under the Win32 API.
- Copyright (C) 1993, 1994, 1995 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Ported xfaces.c for w32 - Kevin Gallo */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <config.h>
-#include "lisp.h"
-
-#include "w32term.h"
-#include "buffer.h"
-#include "dispextern.h"
-#include "frame.h"
-#include "blockinput.h"
-#include "window.h"
-#include "intervals.h"
-
-
-/* An explanation of the face data structures. */
-
-/* ========================= Face Data Structures =========================
-
- Let FACE-NAME be a symbol naming a face.
-
- Let FACE-VECTOR be (assq FACE-NAME (frame-face-alist FRAME))
- FACE-VECTOR is either nil, or a vector of the form
- [face NAME ID FONT FOREGROUND BACKGROUND BACKGROUND-PIXMAP UNDERLINE-P]
- where
- face is the symbol `face',
- NAME is the symbol with which this vector is associated (a backpointer),
- ID is the face ID, an integer used internally by the C code to identify
- the face,
- FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors
- to use with the face,
- BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
- use right now, and
- UNDERLINE-P is non-nil if the face should be underlined.
- If any of these elements are nil, that parameter is considered
- unspecified; parameters from faces specified by lower-priority
- overlays or text properties, or the parameters of the frame itself,
- can show through. (lisp/faces.el maintains these lists.)
-
- (assq FACE-NAME global-face-data) returns a vector describing the
- global parameters for that face.
-
- Let PARAM-FACE be FRAME->display.x->param_faces[Faref (FACE-VECTOR, 2)].
- PARAM_FACE is a struct face whose members are the Xlib analogues of
- the parameters in FACE-VECTOR. If an element of FACE-VECTOR is
- nil, then the corresponding member of PARAM_FACE is FACE_DEFAULT.
- These faces are called "parameter faces", because they're the ones
- lisp manipulates to control what gets displayed. Elements 0 and 1
- of FRAME->display.x->param_faces are special - they describe the
- default and mode line faces. None of the faces in param_faces have
- GC's. (See src/dispextern.h for the definition of struct face.
- lisp/faces.el maintains the isomorphism between face_alist and
- param_faces.)
-
- The functions compute_char_face and compute_glyph_face find and
- combine the parameter faces associated with overlays and text
- properties. The resulting faces are called "computed faces"; none
- of their members are FACE_DEFAULT; they are completely specified.
- They then call intern_compute_face to search
- FRAME->display.x->computed_faces for a matching face, add one if
- none is found, and return the index into
- FRAME->display.x->computed_faces. FRAME's glyph matrices use these
- indices to record the faces of the matrix characters, and the X
- display hooks consult compute_faces to decide how to display these
- characters. Elements 0 and 1 of computed_faces always describe the
- default and mode-line faces.
-
- Each computed face belongs to a particular frame.
-
- Computed faces have graphics contexts some of the time.
- intern_face builds a GC for a specified computed face
- if it doesn't have one already.
- clear_face_cache clears out the GCs of all computed faces.
- This is done from time to time so that we don't hold on to
- lots of GCs that are no longer needed.
-
- Constraints:
-
- Symbols naming faces must have associations on all frames; for any
- FRAME, for all FACE-NAME, if (assq FACE-NAME (frame-face-alist
- FRAME)) is non-nil, it must be non-nil for all frames.
-
- Analogously, indices into param_faces must be valid on all frames;
- if param_faces[i] is a non-zero face pointer on one frame, then it
- must be filled in on all frames. Code assumes that face ID's can
- be used on any frame.
-
- Some subtleties:
-
- Why do we keep param_faces and computed_faces separate?
- computed_faces contains an element for every combination of facial
- parameters we have ever displayed. indices into param_faces have
- to be valid on all frames. If they were the same array, then that
- array would grow very large on all frames, because any facial
- combination displayed on any frame would need to be a valid entry
- on all frames. */
-
-/* Definitions and declarations. */
-
-/* The number of face-id's in use (same for all frames). */
-static int next_face_id;
-
-/* The number of the face to use to indicate the region. */
-static int region_face;
-
-/* This is what appears in a slot in a face to signify that the face
- does not specify that display aspect. */
-#define FACE_DEFAULT (~0)
-
-Lisp_Object Qface, Qmouse_face;
-Lisp_Object Qpixmap_spec_p;
-
-int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ );
-
-struct face *intern_face ( /* FRAME_PTR, struct face * */ );
-static int new_computed_face ( /* FRAME_PTR, struct face * */ );
-static int intern_computed_face ( /* FRAME_PTR, struct face * */ );
-static void ensure_face_ready ( /* FRAME_PTR, int id */ );
-void recompute_basic_faces ( /* FRAME_PTR f */ );
-
-/* Allocating, copying, and comparing struct faces. */
-
-/* Allocate a new face */
-static struct face *
-allocate_face ()
-{
- struct face *result = (struct face *) xmalloc (sizeof (struct face));
- bzero (result, sizeof (struct face));
- result->font = (XFontStruct *) FACE_DEFAULT;
- result->foreground = FACE_DEFAULT;
- result->background = FACE_DEFAULT;
- result->stipple = FACE_DEFAULT;
- return result;
-}
-
-/* Make a new face that's a copy of an existing one. */
-static struct face *
-copy_face (face)
- struct face *face;
-{
- struct face *result = allocate_face ();
-
- result->font = face->font;
- result->foreground = face->foreground;
- result->background = face->background;
- result->stipple = face->stipple;
- result->underline = face->underline;
- result->pixmap_h = face->pixmap_h;
- result->pixmap_w = face->pixmap_w;
-
- return result;
-}
-
-static int
-face_eql (face1, face2)
- struct face *face1, *face2;
-{
- return ( face1->font == face2->font
- && face1->foreground == face2->foreground
- && face1->background == face2->background
- && face1->stipple == face2->stipple
- && face1->underline == face2->underline);
-}
-
-/* Managing graphics contexts of faces. */
-
-/* Given a computed face, construct its graphics context if necessary. */
-
-struct face *
-intern_face (f, face)
- struct frame *f;
- struct face *face;
-{
- face->gc = NULL;
-
- return face;
-}
-
-/* Clear out all graphics contexts for all computed faces
- except for the default and mode line faces.
- This should be done from time to time just to avoid
- keeping too many graphics contexts that are no longer needed. */
-
-void
-clear_face_cache ()
-{
-/* Nothing extra */
-}
-
-/* Allocating, freeing, and duplicating fonts, colors, and pixmaps.
-
- These functions operate on param faces only.
- Computed faces get their fonts, colors and pixmaps
- by merging param faces. */
-
-static XFontStruct *
-load_font (f, name)
- struct frame *f;
- Lisp_Object name;
-{
- XFontStruct *font;
-
- if (NILP (name))
- return (XFontStruct *) FACE_DEFAULT;
-
- CHECK_STRING (name, 0);
- BLOCK_INPUT;
- font = w32_load_font (FRAME_W32_DISPLAY_INFO (f), (char *) XSTRING (name)->data);
- UNBLOCK_INPUT;
-
- if (! font)
- Fsignal (Qerror, Fcons (build_string ("undefined font"),
- Fcons (name, Qnil)));
- return font;
-}
-
-static void
-unload_font (f, font)
- struct frame *f;
- XFontStruct *font;
-{
- if (!font || font == ((XFontStruct *) FACE_DEFAULT))
- return;
-
- BLOCK_INPUT;
- w32_unload_font (FRAME_W32_DISPLAY_INFO (f), font);
- UNBLOCK_INPUT;
-}
-
-static unsigned long
-load_color (f, name)
- struct frame *f;
- Lisp_Object name;
-{
- COLORREF color;
- int result;
-
- if (NILP (name))
- return FACE_DEFAULT;
-
- CHECK_STRING (name, 0);
- /* if the colormap is full, defined_color will return a best match
- to the values in an an existing cell. */
- result = defined_color(f, (char *) XSTRING (name)->data, &color, 1);
- if (! result)
- Fsignal (Qerror, Fcons (build_string ("undefined color"),
- Fcons (name, Qnil)));
- return (unsigned long) color;
-}
-
-static void
-unload_color (f, pixel)
- struct frame *f;
- unsigned long pixel;
-{
-}
-
-DEFUN ("pixmap-spec-p", Fpixmap_spec_p, Spixmap_spec_p, 1, 1, 0,
- "Return t if ARG is a valid pixmap specification.")
- (arg)
- Lisp_Object arg;
-{
- Lisp_Object height, width;
-
- return ((STRINGP (arg)
- || (CONSP (arg)
- && CONSP (XCONS (arg)->cdr)
- && CONSP (XCONS (XCONS (arg)->cdr)->cdr)
- && NILP (XCONS (XCONS (XCONS (arg)->cdr)->cdr)->cdr)
- && (width = XCONS (arg)->car, INTEGERP (width))
- && (height = XCONS (XCONS (arg)->cdr)->car, INTEGERP (height))
- && STRINGP (XCONS (XCONS (XCONS (arg)->cdr)->cdr)->car)
- && XINT (width) > 0
- && XINT (height) > 0
- /* The string must have enough bits for width * height. */
- && ((XSTRING (XCONS (XCONS (XCONS (arg)->cdr)->cdr)->car)->size
- * (BITS_PER_INT / sizeof (int)))
- >= XFASTINT (width) * XFASTINT (height))))
- ? Qt : Qnil);
-}
-
-/* Load a bitmap according to NAME (which is either a file name
- or a pixmap spec). Return the bitmap_id (see xfns.c)
- or get an error if NAME is invalid.
-
- Store the bitmap width in *W_PTR and height in *H_PTR. */
-
-static long
-load_pixmap (f, name, w_ptr, h_ptr)
- FRAME_PTR f;
- Lisp_Object name;
- unsigned int *w_ptr, *h_ptr;
-{
- int bitmap_id;
- Lisp_Object tem;
-
- if (NILP (name))
- return FACE_DEFAULT;
-
- tem = Fpixmap_spec_p (name);
- if (NILP (tem))
- wrong_type_argument (Qpixmap_spec_p, name);
-
- BLOCK_INPUT;
-
- if (CONSP (name))
- {
- /* Decode a bitmap spec into a bitmap. */
-
- int h, w;
- Lisp_Object bits;
-
- w = XINT (Fcar (name));
- h = XINT (Fcar (Fcdr (name)));
- bits = Fcar (Fcdr (Fcdr (name)));
-
- bitmap_id = x_create_bitmap_from_data (f, XSTRING (bits)->data,
- w, h);
- }
- else
- {
- /* It must be a string -- a file name. */
- bitmap_id = x_create_bitmap_from_file (f, name);
- }
- UNBLOCK_INPUT;
-
- if (bitmap_id < 0)
- Fsignal (Qerror, Fcons (build_string ("invalid or undefined bitmap"),
- Fcons (name, Qnil)));
-
- *w_ptr = x_bitmap_width (f, bitmap_id);
- *h_ptr = x_bitmap_height (f, bitmap_id);
-
- return bitmap_id;
-}
-
-
-/* Managing parameter face arrays for frames. */
-
-void
-init_frame_faces (f)
- FRAME_PTR f;
-{
- ensure_face_ready (f, 0);
- ensure_face_ready (f, 1);
-
- FRAME_N_COMPUTED_FACES (f) = 0;
- FRAME_SIZE_COMPUTED_FACES (f) = 0;
-
- new_computed_face (f, FRAME_PARAM_FACES (f)[0]);
- new_computed_face (f, FRAME_PARAM_FACES (f)[1]);
- recompute_basic_faces (f);
-
- /* Find another frame. */
- {
- Lisp_Object tail, frame, result;
-
- result = Qnil;
- FOR_EACH_FRAME (tail, frame)
- if (FRAME_W32_P (XFRAME (frame))
- && XFRAME (frame) != f)
- {
- result = frame;
- break;
- }
-
- /* If we didn't find any X frames other than f, then we don't need
- any faces other than 0 and 1, so we're okay. Otherwise, make
- sure that all faces valid on the selected frame are also valid
- on this new frame. */
- if (FRAMEP (result))
- {
- int i;
- int n_faces = FRAME_N_PARAM_FACES (XFRAME (result));
- struct face **faces = FRAME_PARAM_FACES (XFRAME (result));
-
- for (i = 2; i < n_faces; i++)
- if (faces[i])
- ensure_face_ready (f, i);
- }
- }
-}
-
-
-/* Called from Fdelete_frame. */
-
-void
-free_frame_faces (f)
- struct frame *f;
-{
- int i;
-
- BLOCK_INPUT;
-
- for (i = 0; i < FRAME_N_PARAM_FACES (f); i++)
- {
- struct face *face = FRAME_PARAM_FACES (f) [i];
- if (face)
- {
- unload_font (f, face->font);
- unload_color (f, face->foreground);
- unload_color (f, face->background);
- x_destroy_bitmap (f, face->stipple);
- xfree (face);
- }
- }
- xfree (FRAME_PARAM_FACES (f));
- FRAME_PARAM_FACES (f) = 0;
- FRAME_N_PARAM_FACES (f) = 0;
-
- /* All faces in FRAME_COMPUTED_FACES use resources copied from
- FRAME_PARAM_FACES; we can free them without fuss.
- But we do free the GCs and the face objects themselves. */
- for (i = 0; i < FRAME_N_COMPUTED_FACES (f); i++)
- {
- struct face *face = FRAME_COMPUTED_FACES (f) [i];
- if (face)
- {
- xfree (face);
- }
- }
- xfree (FRAME_COMPUTED_FACES (f));
- FRAME_COMPUTED_FACES (f) = 0;
- FRAME_N_COMPUTED_FACES (f) = 0;
-
- UNBLOCK_INPUT;
-}
-
-/* Interning faces in a frame's face array. */
-
-static int
-new_computed_face (f, new_face)
- struct frame *f;
- struct face *new_face;
-{
- int i = FRAME_N_COMPUTED_FACES (f);
-
- if (i >= FRAME_SIZE_COMPUTED_FACES (f))
- {
- int new_size = i + 32;
-
- FRAME_COMPUTED_FACES (f)
- = (struct face **) (FRAME_SIZE_COMPUTED_FACES (f) == 0
- ? xmalloc (new_size * sizeof (struct face *))
- : xrealloc (FRAME_COMPUTED_FACES (f),
- new_size * sizeof (struct face *)));
- FRAME_SIZE_COMPUTED_FACES (f) = new_size;
- }
-
- i = FRAME_N_COMPUTED_FACES (f)++;
- FRAME_COMPUTED_FACES (f)[i] = copy_face (new_face);
- return i;
-}
-
-
-/* Find a match for NEW_FACE in a FRAME's computed face array, and add
- it if we don't find one. */
-static int
-intern_computed_face (f, new_face)
- struct frame *f;
- struct face *new_face;
-{
- int len = FRAME_N_COMPUTED_FACES (f);
- int i;
-
- /* Search for a computed face already on F equivalent to FACE. */
- for (i = 0; i < len; i++)
- {
- if (! FRAME_COMPUTED_FACES (f)[i])
- abort ();
- if (face_eql (new_face, FRAME_COMPUTED_FACES (f)[i]))
- return i;
- }
-
- /* We didn't find one; add a new one. */
- return new_computed_face (f, new_face);
-}
-
-/* Make parameter face id ID valid on frame F. */
-
-static void
-ensure_face_ready (f, id)
- struct frame *f;
- int id;
-{
- if (FRAME_N_PARAM_FACES (f) <= id)
- {
- int n = id + 10;
- int i;
- if (!FRAME_N_PARAM_FACES (f))
- FRAME_PARAM_FACES (f)
- = (struct face **) xmalloc (sizeof (struct face *) * n);
- else
- FRAME_PARAM_FACES (f)
- = (struct face **) xrealloc (FRAME_PARAM_FACES (f),
- sizeof (struct face *) * n);
-
- bzero (FRAME_PARAM_FACES (f) + FRAME_N_PARAM_FACES (f),
- (n - FRAME_N_PARAM_FACES (f)) * sizeof (struct face *));
- FRAME_N_PARAM_FACES (f) = n;
- }
-
- if (FRAME_PARAM_FACES (f) [id] == 0)
- FRAME_PARAM_FACES (f) [id] = allocate_face ();
-}
-
-/* Return non-zero if FONT1 and FONT2 have the same width.
- We do not check the height, because we can now deal with
- different heights.
- We assume that they're both character-cell fonts. */
-
-int
-same_size_fonts (font1, font2)
- XFontStruct *font1, *font2;
-{
- return (FONT_WIDTH(font1) == FONT_WIDTH(font2));
-}
-
-/* Update the line_height of frame F according to the biggest font in
- any face. Return nonzero if if line_height changes. */
-
-int
-frame_update_line_height (f)
- FRAME_PTR f;
-{
- int i;
- int biggest = FONT_HEIGHT (f->output_data.w32->font);
-
- for (i = 0; i < f->output_data.w32->n_param_faces; i++)
- if (f->output_data.w32->param_faces[i] != 0
- && f->output_data.w32->param_faces[i]->font != (XFontStruct *) FACE_DEFAULT)
- {
- int height = FONT_HEIGHT (f->output_data.w32->param_faces[i]->font);
- if (height > biggest)
- biggest = height;
- }
-
- if (biggest == f->output_data.w32->line_height)
- return 0;
-
- f->output_data.w32->line_height = biggest;
- return 1;
-}
-
-/* Modify face TO by copying from FROM all properties which have
- nondefault settings. */
-
-static void
-merge_faces (from, to)
- struct face *from, *to;
-{
- /* Only merge the font if it's the same width as the base font.
- Otherwise ignore it, since we can't handle it properly. */
- if (from->font != (XFontStruct *) FACE_DEFAULT
- && same_size_fonts (from->font, to->font))
- to->font = from->font;
- if (from->foreground != FACE_DEFAULT)
- to->foreground = from->foreground;
- if (from->background != FACE_DEFAULT)
- to->background = from->background;
- if (from->stipple != FACE_DEFAULT)
- {
- to->stipple = from->stipple;
- to->pixmap_h = from->pixmap_h;
- to->pixmap_w = from->pixmap_w;
- }
- if (from->underline)
- to->underline = from->underline;
-}
-
-/* Set up the basic set of facial parameters, based on the frame's
- data; all faces are deltas applied to this. */
-
-static void
-compute_base_face (f, face)
- FRAME_PTR f;
- struct face *face;
-{
- face->gc = 0;
- face->foreground = FRAME_FOREGROUND_PIXEL (f);
- face->background = FRAME_BACKGROUND_PIXEL (f);
- face->font = FRAME_FONT (f);
- face->stipple = 0;
- face->underline = 0;
-}
-
-/* Return the face ID to use to display a special glyph which selects
- FACE_CODE as the face ID, assuming that ordinarily the face would
- be CURRENT_FACE. F is the frame. */
-
-int
-compute_glyph_face (f, face_code, current_face)
- struct frame *f;
- int face_code, current_face;
-{
- struct face face;
-
- face = *FRAME_COMPUTED_FACES (f)[current_face];
-
- if (face_code >= 0 && face_code < FRAME_N_PARAM_FACES (f)
- && FRAME_PARAM_FACES (f) [face_code] != 0)
- merge_faces (FRAME_PARAM_FACES (f) [face_code], &face);
-
- return intern_computed_face (f, &face);
-}
-
-/* Return the face ID to use to display a special glyph which selects
- FACE_CODE as the face ID, assuming that ordinarily the face would
- be CURRENT_FACE. F is the frame. */
-
-int
-compute_glyph_face_1 (f, face_name, current_face)
- struct frame *f;
- Lisp_Object face_name;
- int current_face;
-{
- struct face face;
-
- face = *FRAME_COMPUTED_FACES (f)[current_face];
-
- if (!NILP (face_name))
- {
- int facecode = face_name_id_number (f, face_name);
- if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
- && FRAME_PARAM_FACES (f) [facecode] != 0)
- merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
- }
-
- return intern_computed_face (f, &face);
-}
-
-/* Return the face ID associated with a buffer position POS.
- Store into *ENDPTR the position at which a different face is needed.
- This does not take account of glyphs that specify their own face codes.
- F is the frame in use for display, and W is a window displaying
- the current buffer.
-
- REGION_BEG, REGION_END delimit the region, so it can be highlighted.
-
- LIMIT is a position not to scan beyond. That is to limit
- the time this function can take.
-
- If MOUSE is nonzero, use the character's mouse-face, not its face. */
-
-int
-compute_char_face (f, w, pos, region_beg, region_end, endptr, limit, mouse)
- struct frame *f;
- struct window *w;
- int pos;
- int region_beg, region_end;
- int *endptr;
- int limit;
- int mouse;
-{
- struct face face;
- Lisp_Object prop, position;
- int i, j, noverlays;
- int facecode;
- Lisp_Object *overlay_vec;
- Lisp_Object frame;
- int endpos;
- Lisp_Object propname;
-
- /* W must display the current buffer. We could write this function
- to use the frame and buffer of W, but right now it doesn't. */
- if (XBUFFER (w->buffer) != current_buffer)
- abort ();
-
- XSETFRAME (frame, f);
-
- endpos = ZV;
- if (pos < region_beg && region_beg < endpos)
- endpos = region_beg;
-
- XSETFASTINT (position, pos);
-
- if (mouse)
- propname = Qmouse_face;
- else
- propname = Qface;
-
- prop = Fget_text_property (position, propname, w->buffer);
-
- {
- Lisp_Object limit1, end;
-
- XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
- end = Fnext_single_property_change (position, propname, w->buffer, limit1);
- if (INTEGERP (end))
- endpos = XINT (end);
- }
-
- {
- int next_overlay;
- int len;
-
- /* First try with room for 40 overlays. */
- len = 40;
- overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-
- noverlays = overlays_at (pos, 0, &overlay_vec, &len,
- &next_overlay, (int *) 0);
-
- /* If there are more than 40,
- make enough space for all, and try again. */
- if (noverlays > len)
- {
- len = noverlays;
- overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- noverlays = overlays_at (pos, 0, &overlay_vec, &len,
- &next_overlay, (int *) 0);
- }
-
- if (next_overlay < endpos)
- endpos = next_overlay;
- }
-
- *endptr = endpos;
-
- /* Optimize the default case. */
- if (noverlays == 0 && NILP (prop)
- && !(pos >= region_beg && pos < region_end))
- return 0;
-
- compute_base_face (f, &face);
-
- if (CONSP (prop))
- {
- /* We have a list of faces, merge them in reverse order */
- Lisp_Object length = Flength (prop);
- int len = XINT (length);
- Lisp_Object *faces;
-
- /* Put them into an array */
- faces = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- for (j = 0; j < len; j++)
- {
- faces[j] = Fcar (prop);
- prop = Fcdr (prop);
- }
- /* So that we can merge them in the reverse order */
- for (j = len - 1; j >= 0; j--)
- {
- facecode = face_name_id_number (f, faces[j]);
- if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
- && FRAME_PARAM_FACES (f) [facecode] != 0)
- merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
- }
- }
- else if (!NILP (prop))
- {
- facecode = face_name_id_number (f, prop);
- if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
- && FRAME_PARAM_FACES (f) [facecode] != 0)
- merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
- }
-
- noverlays = sort_overlays (overlay_vec, noverlays, w);
-
- /* Now merge the overlay data in that order. */
- for (i = 0; i < noverlays; i++)
- {
- prop = Foverlay_get (overlay_vec[i], propname);
- if (CONSP (prop))
- {
- /* We have a list of faces, merge them in reverse order */
- Lisp_Object length = Flength (prop);
- int len = XINT (length);
- Lisp_Object *faces;
- int i;
-
- /* Put them into an array */
- faces = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- for (j = 0; j < len; j++)
- {
- faces[j] = Fcar (prop);
- prop = Fcdr (prop);
- }
- /* So that we can merge them in the reverse order */
- for (j = len - 1; j >= 0; j--)
- {
- facecode = face_name_id_number (f, faces[j]);
- if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
- && FRAME_PARAM_FACES (f) [facecode] != 0)
- merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
- }
- }
- else if (!NILP (prop))
- {
- Lisp_Object oend;
- int oendpos;
-
- facecode = face_name_id_number (f, prop);
- if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
- && FRAME_PARAM_FACES (f) [facecode] != 0)
- merge_faces (FRAME_PARAM_FACES (f)[facecode], &face);
-
- oend = OVERLAY_END (overlay_vec[i]);
- oendpos = OVERLAY_POSITION (oend);
- if (oendpos < endpos)
- endpos = oendpos;
- }
- }
-
- if (pos >= region_beg && pos < region_end)
- {
- if (region_end < endpos)
- endpos = region_end;
- if (region_face >= 0 && region_face < next_face_id)
- merge_faces (FRAME_PARAM_FACES (f)[region_face], &face);
- }
-
- *endptr = endpos;
-
- return intern_computed_face (f, &face);
-}
-
-/* Recompute the GC's for the default and modeline faces.
- We call this after changing frame parameters on which those GC's
- depend. */
-
-void
-recompute_basic_faces (f)
- FRAME_PTR f;
-{
- /* If the frame's faces haven't been initialized yet, don't worry about
- this stuff. */
- if (FRAME_N_PARAM_FACES (f) < 2)
- return;
-
- BLOCK_INPUT;
-
- compute_base_face (f, FRAME_DEFAULT_FACE (f));
- compute_base_face (f, FRAME_MODE_LINE_FACE (f));
-
- merge_faces (FRAME_DEFAULT_PARAM_FACE (f), FRAME_DEFAULT_FACE (f));
- merge_faces (FRAME_MODE_LINE_PARAM_FACE (f), FRAME_MODE_LINE_FACE (f));
-
- intern_face (f, FRAME_DEFAULT_FACE (f));
- intern_face (f, FRAME_MODE_LINE_FACE (f));
-
- UNBLOCK_INPUT;
-}
-
-
-
-/* Lisp interface. */
-
-DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
- "")
- (frame)
- Lisp_Object frame;
-{
- CHECK_FRAME (frame, 0);
- return XFRAME (frame)->face_alist;
-}
-
-DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
- 2, 2, 0, "")
- (frame, value)
- Lisp_Object frame, value;
-{
- CHECK_FRAME (frame, 0);
- XFRAME (frame)->face_alist = value;
- return value;
-}
-
-
-DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
- "Create face number FACE-ID on all frames.")
- (face_id)
- Lisp_Object face_id;
-{
- Lisp_Object rest, frame;
- int id = XINT (face_id);
-
- CHECK_NUMBER (face_id, 0);
- if (id < 0 || id >= next_face_id)
- error ("Face id out of range");
-
- FOR_EACH_FRAME (rest, frame)
- {
- if (FRAME_W32_P (XFRAME (frame)))
- ensure_face_ready (XFRAME (frame), id);
- }
- return Qnil;
-}
-
-
-DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
- Sset_face_attribute_internal, 4, 4, 0, "")
- (face_id, attr_name, attr_value, frame)
- Lisp_Object face_id, attr_name, attr_value, frame;
-{
- struct face *face;
- struct frame *f;
- int magic_p;
- int id;
- int garbaged = 0;
-
- CHECK_FRAME (frame, 0);
- CHECK_NUMBER (face_id, 0);
- CHECK_SYMBOL (attr_name, 0);
-
- f = XFRAME (frame);
- id = XINT (face_id);
- if (id < 0 || id >= next_face_id)
- error ("Face id out of range");
-
- if (! FRAME_W32_P (f))
- return Qnil;
-
- ensure_face_ready (f, id);
- face = FRAME_PARAM_FACES (f) [XFASTINT (face_id)];
-
- if (EQ (attr_name, intern ("font")))
- {
- XFontStruct *font = load_font (f, attr_value);
- if (face->font != f->output_data.w32->font)
- unload_font (f, face->font);
- face->font = font;
- if (frame_update_line_height (f))
- x_set_window_size (f, 0, f->width, f->height);
- /* Must clear cache, since it might contain the font
- we just got rid of. */
- garbaged = 1;
- }
- else if (EQ (attr_name, intern ("foreground")))
- {
- unsigned long new_color = load_color (f, attr_value);
- unload_color (f, face->foreground);
- face->foreground = new_color;
- garbaged = 1;
- }
- else if (EQ (attr_name, intern ("background")))
- {
- unsigned long new_color = load_color (f, attr_value);
- unload_color (f, face->background);
- face->background = new_color;
- garbaged = 1;
- }
- else if (EQ (attr_name, intern ("background-pixmap")))
- {
- unsigned int w, h;
- unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h);
- x_destroy_bitmap (f, face->stipple);
- face->stipple = (Pixmap) new_pixmap;
- face->pixmap_w = w;
- face->pixmap_h = h;
- garbaged = 1;
- }
- else if (EQ (attr_name, intern ("underline")))
- {
- int new = !NILP (attr_value);
- face->underline = new;
- }
- else
- error ("unknown face attribute");
-
- if (id == 0 || id == 1)
- recompute_basic_faces (f);
-
- /* We must redraw the frame whenever any face font or color changes,
- because it's possible that a merged (display) face
- contains the font or color we just replaced.
- And we must inhibit any Expose events until the redraw is done,
- since they would try to use the invalid display faces. */
- if (garbaged)
- SET_FRAME_GARBAGED (f);
-
- return Qnil;
-}
-
-DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
- 0, 0, 0, "")
- ()
-{
- return make_number (next_face_id++);
-}
-
-/* Return the face id for name NAME on frame FRAME.
- (It should be the same for all frames,
- but it's as easy to use the "right" frame to look it up
- as to use any other one.) */
-
-int
-face_name_id_number (f, name)
- FRAME_PTR f;
- Lisp_Object name;
-{
- Lisp_Object tem;
-
- tem = Fcdr (assq_no_quit (name, f->face_alist));
- if (NILP (tem))
- return 0;
- CHECK_VECTOR (tem, 0);
- tem = XVECTOR (tem)->contents[2];
- CHECK_NUMBER (tem, 0);
- return XINT (tem);
-}
-
-/* Emacs initialization. */
-
-void
-syms_of_w32faces ()
-{
- Qface = intern ("face");
- staticpro (&Qface);
- Qmouse_face = intern ("mouse-face");
- staticpro (&Qmouse_face);
- Qpixmap_spec_p = intern ("pixmap-spec-p");
- staticpro (&Qpixmap_spec_p);
-
- DEFVAR_INT ("region-face", &region_face,
- "Face number to use to highlight the region\n\
-The region is highlighted with this face\n\
-when Transient Mark mode is enabled and the mark is active.");
-
- defsubr (&Spixmap_spec_p);
- defsubr (&Sframe_face_alist);
- defsubr (&Sset_frame_face_alist);
- defsubr (&Smake_face_internal);
- defsubr (&Sset_face_attribute_internal);
- defsubr (&Sinternal_next_face_id);
-}
diff --git a/src/w32fns.c b/src/w32fns.c
deleted file mode 100644
index 6501e49b61e..00000000000
--- a/src/w32fns.c
+++ /dev/null
@@ -1,5165 +0,0 @@
-/* Functions for the MS Win32 window system API.
- Copyright (C) 1989, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Added by Kevin Gallo */
-
-#include <signal.h>
-#include <config.h>
-#include <stdio.h>
-
-#include "lisp.h"
-#include "w32term.h"
-#include "frame.h"
-#include "window.h"
-#include "buffer.h"
-#include "dispextern.h"
-#include "keyboard.h"
-#include "blockinput.h"
-#include "paths.h"
-#include "w32heap.h"
-#include "termhooks.h"
-
-#include <commdlg.h>
-
-extern void abort ();
-extern void free_frame_menubar ();
-extern struct scroll_bar *x_window_to_scroll_bar ();
-extern int quit_char;
-
-/* The colormap for converting color names to RGB values */
-Lisp_Object Vw32_color_map;
-
-/* Non nil if alt key presses are passed on to Windows. */
-Lisp_Object Vw32_pass_alt_to_system;
-
-/* Non nil if alt key is translated to meta_modifier, nil if it is translated
- to alt_modifier. */
-Lisp_Object Vw32_alt_is_meta;
-
-/* Non nil if left window, right window, and application key events
- are passed on to Windows. */
-Lisp_Object Vw32_pass_optional_keys_to_system;
-
-/* Switch to control whether we inhibit requests for italicised fonts (which
- are synthesized, look ugly, and are trashed by cursor movement under NT). */
-Lisp_Object Vw32_enable_italics;
-
-/* Enable palette management. */
-Lisp_Object Vw32_enable_palette;
-
-/* Control how close left/right button down events must be to
- be converted to a middle button down event. */
-Lisp_Object Vw32_mouse_button_tolerance;
-
-/* Minimum interval between mouse movement (and scroll bar drag)
- events that are passed on to the event loop. */
-Lisp_Object Vw32_mouse_move_interval;
-
-/* The name we're using in resource queries. */
-Lisp_Object Vx_resource_name;
-
-/* Non nil if no window manager is in use. */
-Lisp_Object Vx_no_window_manager;
-
-/* The background and shape of the mouse pointer, and shape when not
- over text or in the modeline. */
-Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
-/* The shape when over mouse-sensitive text. */
-Lisp_Object Vx_sensitive_text_pointer_shape;
-
-/* Color of chars displayed in cursor box. */
-Lisp_Object Vx_cursor_fore_pixel;
-
-/* Search path for bitmap files. */
-Lisp_Object Vx_bitmap_file_path;
-
-/* Evaluate this expression to rebuild the section of syms_of_w32fns
- that initializes and staticpros the symbols declared below. Note
- that Emacs 18 has a bug that keeps C-x C-e from being able to
- evaluate this expression.
-
-(progn
- ;; Accumulate a list of the symbols we want to initialize from the
- ;; declarations at the top of the file.
- (goto-char (point-min))
- (search-forward "/\*&&& symbols declared here &&&*\/\n")
- (let (symbol-list)
- (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
- (setq symbol-list
- (cons (buffer-substring (match-beginning 1) (match-end 1))
- symbol-list))
- (forward-line 1))
- (setq symbol-list (nreverse symbol-list))
- ;; Delete the section of syms_of_... where we initialize the symbols.
- (search-forward "\n /\*&&& init symbols here &&&*\/\n")
- (let ((start (point)))
- (while (looking-at "^ Q")
- (forward-line 2))
- (kill-region start (point)))
- ;; Write a new symbol initialization section.
- (while symbol-list
- (insert (format " %s = intern (\"" (car symbol-list)))
- (let ((start (point)))
- (insert (substring (car symbol-list) 1))
- (subst-char-in-region start (point) ?_ ?-))
- (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
- (setq symbol-list (cdr symbol-list)))))
-
- */
-
-/*&&& symbols declared here &&&*/
-Lisp_Object Qauto_raise;
-Lisp_Object Qauto_lower;
-Lisp_Object Qbackground_color;
-Lisp_Object Qbar;
-Lisp_Object Qborder_color;
-Lisp_Object Qborder_width;
-Lisp_Object Qbox;
-Lisp_Object Qcursor_color;
-Lisp_Object Qcursor_type;
-Lisp_Object Qforeground_color;
-Lisp_Object Qgeometry;
-Lisp_Object Qicon_left;
-Lisp_Object Qicon_top;
-Lisp_Object Qicon_type;
-Lisp_Object Qicon_name;
-Lisp_Object Qinternal_border_width;
-Lisp_Object Qleft;
-Lisp_Object Qright;
-Lisp_Object Qmouse_color;
-Lisp_Object Qnone;
-Lisp_Object Qparent_id;
-Lisp_Object Qscroll_bar_width;
-Lisp_Object Qsuppress_icon;
-Lisp_Object Qtop;
-Lisp_Object Qundefined_color;
-Lisp_Object Qvertical_scroll_bars;
-Lisp_Object Qvisibility;
-Lisp_Object Qwindow_id;
-Lisp_Object Qx_frame_parameter;
-Lisp_Object Qx_resource_name;
-Lisp_Object Quser_position;
-Lisp_Object Quser_size;
-Lisp_Object Qdisplay;
-
-/* State variables for emulating a three button mouse. */
-#define LMOUSE 1
-#define MMOUSE 2
-#define RMOUSE 4
-
-static int button_state = 0;
-static W32Msg saved_mouse_button_msg;
-static unsigned mouse_button_timer; /* non-zero when timer is active */
-static W32Msg saved_mouse_move_msg;
-static unsigned mouse_move_timer;
-
-#define MOUSE_BUTTON_ID 1
-#define MOUSE_MOVE_ID 2
-
-/* The below are defined in frame.c. */
-extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
-extern Lisp_Object Qunsplittable, Qmenu_bar_lines;
-
-extern Lisp_Object Vwindow_system_version;
-
-extern Lisp_Object last_mouse_scroll_bar;
-extern int last_mouse_scroll_bar_pos;
-
-/* From w32term.c. */
-extern Lisp_Object Vw32_num_mouse_buttons;
-
-Time last_mouse_movement_time;
-
-
-/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
- and checking validity for W32. */
-
-FRAME_PTR
-check_x_frame (frame)
- Lisp_Object frame;
-{
- FRAME_PTR f;
-
- if (NILP (frame))
- f = selected_frame;
- else
- {
- CHECK_LIVE_FRAME (frame, 0);
- f = XFRAME (frame);
- }
- if (! FRAME_W32_P (f))
- error ("non-w32 frame used");
- return f;
-}
-
-/* Let the user specify an display with a frame.
- nil stands for the selected frame--or, if that is not a w32 frame,
- the first display on the list. */
-
-static struct w32_display_info *
-check_x_display_info (frame)
- Lisp_Object frame;
-{
- if (NILP (frame))
- {
- if (FRAME_W32_P (selected_frame))
- return FRAME_W32_DISPLAY_INFO (selected_frame);
- else
- return &one_w32_display_info;
- }
- else if (STRINGP (frame))
- return x_display_info_for_name (frame);
- else
- {
- FRAME_PTR f;
-
- CHECK_LIVE_FRAME (frame, 0);
- f = XFRAME (frame);
- if (! FRAME_W32_P (f))
- error ("non-w32 frame used");
- return FRAME_W32_DISPLAY_INFO (f);
- }
-}
-
-/* Return the Emacs frame-object corresponding to an w32 window.
- It could be the frame's main window or an icon window. */
-
-/* This function can be called during GC, so use GC_xxx type test macros. */
-
-struct frame *
-x_window_to_frame (dpyinfo, wdesc)
- struct w32_display_info *dpyinfo;
- HWND wdesc;
-{
- Lisp_Object tail, frame;
- struct frame *f;
-
- for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
- {
- frame = XCONS (tail)->car;
- if (!GC_FRAMEP (frame))
- continue;
- f = XFRAME (frame);
- if (f->output_data.nothing == 1
- || FRAME_W32_DISPLAY_INFO (f) != dpyinfo)
- continue;
- if (FRAME_W32_WINDOW (f) == wdesc)
- return f;
- }
- return 0;
-}
-
-
-
-/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
- id, which is just an int that this section returns. Bitmaps are
- reference counted so they can be shared among frames.
-
- Bitmap indices are guaranteed to be > 0, so a negative number can
- be used to indicate no bitmap.
-
- If you use x_create_bitmap_from_data, then you must keep track of
- the bitmaps yourself. That is, creating a bitmap from the same
- data more than once will not be caught. */
-
-
-/* Functions to access the contents of a bitmap, given an id. */
-
-int
-x_bitmap_height (f, id)
- FRAME_PTR f;
- int id;
-{
- return FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].height;
-}
-
-int
-x_bitmap_width (f, id)
- FRAME_PTR f;
- int id;
-{
- return FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].width;
-}
-
-int
-x_bitmap_pixmap (f, id)
- FRAME_PTR f;
- int id;
-{
- return (int) FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
-}
-
-
-/* Allocate a new bitmap record. Returns index of new record. */
-
-static int
-x_allocate_bitmap_record (f)
- FRAME_PTR f;
-{
- struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
- int i;
-
- if (dpyinfo->bitmaps == NULL)
- {
- dpyinfo->bitmaps_size = 10;
- dpyinfo->bitmaps
- = (struct w32_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct w32_bitmap_record));
- dpyinfo->bitmaps_last = 1;
- return 1;
- }
-
- if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
- return ++dpyinfo->bitmaps_last;
-
- for (i = 0; i < dpyinfo->bitmaps_size; ++i)
- if (dpyinfo->bitmaps[i].refcount == 0)
- return i + 1;
-
- dpyinfo->bitmaps_size *= 2;
- dpyinfo->bitmaps
- = (struct w32_bitmap_record *) xrealloc (dpyinfo->bitmaps,
- dpyinfo->bitmaps_size * sizeof (struct w32_bitmap_record));
- return ++dpyinfo->bitmaps_last;
-}
-
-/* Add one reference to the reference count of the bitmap with id ID. */
-
-void
-x_reference_bitmap (f, id)
- FRAME_PTR f;
- int id;
-{
- ++FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
-}
-
-/* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
-
-int
-x_create_bitmap_from_data (f, bits, width, height)
- struct frame *f;
- char *bits;
- unsigned int width, height;
-{
- struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
- Pixmap bitmap;
- int id;
-
- bitmap = CreateBitmap (width, height,
- FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_planes,
- FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_cbits,
- bits);
-
- if (! bitmap)
- return -1;
-
- id = x_allocate_bitmap_record (f);
- dpyinfo->bitmaps[id - 1].pixmap = bitmap;
- dpyinfo->bitmaps[id - 1].file = NULL;
- dpyinfo->bitmaps[id - 1].hinst = NULL;
- dpyinfo->bitmaps[id - 1].refcount = 1;
- dpyinfo->bitmaps[id - 1].depth = 1;
- dpyinfo->bitmaps[id - 1].height = height;
- dpyinfo->bitmaps[id - 1].width = width;
-
- return id;
-}
-
-/* Create bitmap from file FILE for frame F. */
-
-int
-x_create_bitmap_from_file (f, file)
- struct frame *f;
- Lisp_Object file;
-{
- return -1;
-#if 0
- struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
- unsigned int width, height;
- Pixmap bitmap;
- int xhot, yhot, result, id;
- Lisp_Object found;
- int fd;
- char *filename;
- HINSTANCE hinst;
-
- /* Look for an existing bitmap with the same name. */
- for (id = 0; id < dpyinfo->bitmaps_last; ++id)
- {
- if (dpyinfo->bitmaps[id].refcount
- && dpyinfo->bitmaps[id].file
- && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
- {
- ++dpyinfo->bitmaps[id].refcount;
- return id + 1;
- }
- }
-
- /* Search bitmap-file-path for the file, if appropriate. */
- fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
- if (fd < 0)
- return -1;
- close (fd);
-
- filename = (char *) XSTRING (found)->data;
-
- hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
-
- if (hinst == NULL)
- return -1;
-
-
- result = XReadBitmapFile (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
- filename, &width, &height, &bitmap, &xhot, &yhot);
- if (result != BitmapSuccess)
- return -1;
-
- id = x_allocate_bitmap_record (f);
- dpyinfo->bitmaps[id - 1].pixmap = bitmap;
- dpyinfo->bitmaps[id - 1].refcount = 1;
- dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (XSTRING (file)->size + 1);
- dpyinfo->bitmaps[id - 1].depth = 1;
- dpyinfo->bitmaps[id - 1].height = height;
- dpyinfo->bitmaps[id - 1].width = width;
- strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
-
- return id;
-#endif
-}
-
-/* Remove reference to bitmap with id number ID. */
-
-int
-x_destroy_bitmap (f, id)
- FRAME_PTR f;
- int id;
-{
- struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
-
- if (id > 0)
- {
- --dpyinfo->bitmaps[id - 1].refcount;
- if (dpyinfo->bitmaps[id - 1].refcount == 0)
- {
- BLOCK_INPUT;
- DeleteObject (dpyinfo->bitmaps[id - 1].pixmap);
- if (dpyinfo->bitmaps[id - 1].file)
- {
- free (dpyinfo->bitmaps[id - 1].file);
- dpyinfo->bitmaps[id - 1].file = NULL;
- }
- UNBLOCK_INPUT;
- }
- }
-}
-
-/* Free all the bitmaps for the display specified by DPYINFO. */
-
-static void
-x_destroy_all_bitmaps (dpyinfo)
- struct w32_display_info *dpyinfo;
-{
- int i;
- for (i = 0; i < dpyinfo->bitmaps_last; i++)
- if (dpyinfo->bitmaps[i].refcount > 0)
- {
- DeleteObject (dpyinfo->bitmaps[i].pixmap);
- if (dpyinfo->bitmaps[i].file)
- free (dpyinfo->bitmaps[i].file);
- }
- dpyinfo->bitmaps_last = 0;
-}
-
-/* Connect the frame-parameter names for W32 frames
- to the ways of passing the parameter values to the window system.
-
- The name of a parameter, as a Lisp symbol,
- has an `x-frame-parameter' property which is an integer in Lisp
- but can be interpreted as an `enum x_frame_parm' in C. */
-
-enum x_frame_parm
-{
- X_PARM_FOREGROUND_COLOR,
- X_PARM_BACKGROUND_COLOR,
- X_PARM_MOUSE_COLOR,
- X_PARM_CURSOR_COLOR,
- X_PARM_BORDER_COLOR,
- X_PARM_ICON_TYPE,
- X_PARM_FONT,
- X_PARM_BORDER_WIDTH,
- X_PARM_INTERNAL_BORDER_WIDTH,
- X_PARM_NAME,
- X_PARM_AUTORAISE,
- X_PARM_AUTOLOWER,
- X_PARM_VERT_SCROLL_BAR,
- X_PARM_VISIBILITY,
- X_PARM_MENU_BAR_LINES
-};
-
-
-struct x_frame_parm_table
-{
- char *name;
- void (*setter)( /* struct frame *frame, Lisp_Object val, oldval */ );
-};
-
-void x_set_foreground_color ();
-void x_set_background_color ();
-void x_set_mouse_color ();
-void x_set_cursor_color ();
-void x_set_border_color ();
-void x_set_cursor_type ();
-void x_set_icon_type ();
-void x_set_icon_name ();
-void x_set_font ();
-void x_set_border_width ();
-void x_set_internal_border_width ();
-void x_explicitly_set_name ();
-void x_set_autoraise ();
-void x_set_autolower ();
-void x_set_vertical_scroll_bars ();
-void x_set_visibility ();
-void x_set_menu_bar_lines ();
-void x_set_scroll_bar_width ();
-void x_set_unsplittable ();
-
-static struct x_frame_parm_table x_frame_parms[] =
-{
- "foreground-color", x_set_foreground_color,
- "background-color", x_set_background_color,
- "mouse-color", x_set_mouse_color,
- "cursor-color", x_set_cursor_color,
- "border-color", x_set_border_color,
- "cursor-type", x_set_cursor_type,
- "icon-type", x_set_icon_type,
- "icon-name", x_set_icon_name,
- "font", x_set_font,
- "border-width", x_set_border_width,
- "internal-border-width", x_set_internal_border_width,
- "name", x_explicitly_set_name,
- "auto-raise", x_set_autoraise,
- "auto-lower", x_set_autolower,
- "vertical-scroll-bars", x_set_vertical_scroll_bars,
- "visibility", x_set_visibility,
- "menu-bar-lines", x_set_menu_bar_lines,
- "scroll-bar-width", x_set_scroll_bar_width,
- "unsplittable", x_set_unsplittable,
-};
-
-/* Attach the `x-frame-parameter' properties to
- the Lisp symbol names of parameters relevant to W32. */
-
-init_x_parm_symbols ()
-{
- int i;
-
- for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
- Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
- make_number (i));
-}
-
-/* Change the parameters of FRAME as specified by ALIST.
- If a parameter is not specially recognized, do nothing;
- otherwise call the `x_set_...' function for that parameter. */
-
-void
-x_set_frame_parameters (f, alist)
- FRAME_PTR f;
- Lisp_Object alist;
-{
- Lisp_Object tail;
-
- /* If both of these parameters are present, it's more efficient to
- set them both at once. So we wait until we've looked at the
- entire list before we set them. */
- int width, height;
-
- /* Same here. */
- Lisp_Object left, top;
-
- /* Same with these. */
- Lisp_Object icon_left, icon_top;
-
- /* Record in these vectors all the parms specified. */
- Lisp_Object *parms;
- Lisp_Object *values;
- int i;
- int left_no_change = 0, top_no_change = 0;
- int icon_left_no_change = 0, icon_top_no_change = 0;
-
- i = 0;
- for (tail = alist; CONSP (tail); tail = Fcdr (tail))
- i++;
-
- parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
- values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
-
- /* Extract parm names and values into those vectors. */
-
- i = 0;
- for (tail = alist; CONSP (tail); tail = Fcdr (tail))
- {
- Lisp_Object elt, prop, val;
-
- elt = Fcar (tail);
- parms[i] = Fcar (elt);
- values[i] = Fcdr (elt);
- i++;
- }
-
- top = left = Qunbound;
- icon_left = icon_top = Qunbound;
-
- /* Provide default values for HEIGHT and WIDTH. */
- width = FRAME_WIDTH (f);
- height = FRAME_HEIGHT (f);
-
- /* Now process them in reverse of specified order. */
- for (i--; i >= 0; i--)
- {
- Lisp_Object prop, val;
-
- prop = parms[i];
- val = values[i];
-
- if (EQ (prop, Qwidth) && NUMBERP (val))
- width = XFASTINT (val);
- else if (EQ (prop, Qheight) && NUMBERP (val))
- height = XFASTINT (val);
- else if (EQ (prop, Qtop))
- top = val;
- else if (EQ (prop, Qleft))
- left = val;
- else if (EQ (prop, Qicon_top))
- icon_top = val;
- else if (EQ (prop, Qicon_left))
- icon_left = val;
- else
- {
- register Lisp_Object param_index, old_value;
-
- param_index = Fget (prop, Qx_frame_parameter);
- old_value = get_frame_param (f, prop);
- store_frame_param (f, prop, val);
- if (NATNUMP (param_index)
- && (XFASTINT (param_index)
- < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
- (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
- }
- }
-
- /* Don't die if just one of these was set. */
- if (EQ (left, Qunbound))
- {
- left_no_change = 1;
- if (f->output_data.w32->left_pos < 0)
- left = Fcons (Qplus, Fcons (make_number (f->output_data.w32->left_pos), Qnil));
- else
- XSETINT (left, f->output_data.w32->left_pos);
- }
- if (EQ (top, Qunbound))
- {
- top_no_change = 1;
- if (f->output_data.w32->top_pos < 0)
- top = Fcons (Qplus, Fcons (make_number (f->output_data.w32->top_pos), Qnil));
- else
- XSETINT (top, f->output_data.w32->top_pos);
- }
-
- /* If one of the icon positions was not set, preserve or default it. */
- if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
- {
- icon_left_no_change = 1;
- icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
- if (NILP (icon_left))
- XSETINT (icon_left, 0);
- }
- if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
- {
- icon_top_no_change = 1;
- icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
- if (NILP (icon_top))
- XSETINT (icon_top, 0);
- }
-
- /* Don't set these parameters unless they've been explicitly
- specified. The window might be mapped or resized while we're in
- this function, and we don't want to override that unless the lisp
- code has asked for it.
-
- Don't set these parameters unless they actually differ from the
- window's current parameters; the window may not actually exist
- yet. */
- {
- Lisp_Object frame;
-
- check_frame_size (f, &height, &width);
-
- XSETFRAME (frame, f);
-
- if (XINT (width) != FRAME_WIDTH (f)
- || XINT (height) != FRAME_HEIGHT (f))
- Fset_frame_size (frame, make_number (width), make_number (height));
-
- if ((!NILP (left) || !NILP (top))
- && ! (left_no_change && top_no_change)
- && ! (NUMBERP (left) && XINT (left) == f->output_data.w32->left_pos
- && NUMBERP (top) && XINT (top) == f->output_data.w32->top_pos))
- {
- int leftpos = 0;
- int toppos = 0;
-
- /* Record the signs. */
- f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
- if (EQ (left, Qminus))
- f->output_data.w32->size_hint_flags |= XNegative;
- else if (INTEGERP (left))
- {
- leftpos = XINT (left);
- if (leftpos < 0)
- f->output_data.w32->size_hint_flags |= XNegative;
- }
- else if (CONSP (left) && EQ (XCONS (left)->car, Qminus)
- && CONSP (XCONS (left)->cdr)
- && INTEGERP (XCONS (XCONS (left)->cdr)->car))
- {
- leftpos = - XINT (XCONS (XCONS (left)->cdr)->car);
- f->output_data.w32->size_hint_flags |= XNegative;
- }
- else if (CONSP (left) && EQ (XCONS (left)->car, Qplus)
- && CONSP (XCONS (left)->cdr)
- && INTEGERP (XCONS (XCONS (left)->cdr)->car))
- {
- leftpos = XINT (XCONS (XCONS (left)->cdr)->car);
- }
-
- if (EQ (top, Qminus))
- f->output_data.w32->size_hint_flags |= YNegative;
- else if (INTEGERP (top))
- {
- toppos = XINT (top);
- if (toppos < 0)
- f->output_data.w32->size_hint_flags |= YNegative;
- }
- else if (CONSP (top) && EQ (XCONS (top)->car, Qminus)
- && CONSP (XCONS (top)->cdr)
- && INTEGERP (XCONS (XCONS (top)->cdr)->car))
- {
- toppos = - XINT (XCONS (XCONS (top)->cdr)->car);
- f->output_data.w32->size_hint_flags |= YNegative;
- }
- else if (CONSP (top) && EQ (XCONS (top)->car, Qplus)
- && CONSP (XCONS (top)->cdr)
- && INTEGERP (XCONS (XCONS (top)->cdr)->car))
- {
- toppos = XINT (XCONS (XCONS (top)->cdr)->car);
- }
-
-
- /* Store the numeric value of the position. */
- f->output_data.w32->top_pos = toppos;
- f->output_data.w32->left_pos = leftpos;
-
- f->output_data.w32->win_gravity = NorthWestGravity;
-
- /* Actually set that position, and convert to absolute. */
- x_set_offset (f, leftpos, toppos, -1);
- }
-
- if ((!NILP (icon_left) || !NILP (icon_top))
- && ! (icon_left_no_change && icon_top_no_change))
- x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
- }
-}
-
-/* Store the screen positions of frame F into XPTR and YPTR.
- These are the positions of the containing window manager window,
- not Emacs's own window. */
-
-void
-x_real_positions (f, xptr, yptr)
- FRAME_PTR f;
- int *xptr, *yptr;
-{
- POINT pt;
-
- {
- RECT rect;
-
- GetClientRect(FRAME_W32_WINDOW(f), &rect);
- AdjustWindowRect(&rect, f->output_data.w32->dwStyle, FRAME_EXTERNAL_MENU_BAR(f));
-
- pt.x = rect.left;
- pt.y = rect.top;
- }
-
- ClientToScreen (FRAME_W32_WINDOW(f), &pt);
-
- *xptr = pt.x;
- *yptr = pt.y;
-}
-
-/* Insert a description of internally-recorded parameters of frame X
- into the parameter alist *ALISTPTR that is to be given to the user.
- Only parameters that are specific to W32
- and whose values are not correctly recorded in the frame's
- param_alist need to be considered here. */
-
-x_report_frame_params (f, alistptr)
- struct frame *f;
- Lisp_Object *alistptr;
-{
- char buf[16];
- Lisp_Object tem;
-
- /* Represent negative positions (off the top or left screen edge)
- in a way that Fmodify_frame_parameters will understand correctly. */
- XSETINT (tem, f->output_data.w32->left_pos);
- if (f->output_data.w32->left_pos >= 0)
- store_in_alist (alistptr, Qleft, tem);
- else
- store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
-
- XSETINT (tem, f->output_data.w32->top_pos);
- if (f->output_data.w32->top_pos >= 0)
- store_in_alist (alistptr, Qtop, tem);
- else
- store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
-
- store_in_alist (alistptr, Qborder_width,
- make_number (f->output_data.w32->border_width));
- store_in_alist (alistptr, Qinternal_border_width,
- make_number (f->output_data.w32->internal_border_width));
- sprintf (buf, "%ld", (long) FRAME_W32_WINDOW (f));
- store_in_alist (alistptr, Qwindow_id,
- build_string (buf));
- store_in_alist (alistptr, Qicon_name, f->icon_name);
- FRAME_SAMPLE_VISIBILITY (f);
- store_in_alist (alistptr, Qvisibility,
- (FRAME_VISIBLE_P (f) ? Qt
- : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
- store_in_alist (alistptr, Qdisplay,
- XCONS (FRAME_W32_DISPLAY_INFO (f)->name_list_element)->car);
-}
-
-
-DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color, Sw32_define_rgb_color, 4, 4, 0,
- "Convert RGB numbers to a windows color reference and associate with NAME (a string).\n\
-This adds or updates a named color to w32-color-map, making it available for use.\n\
-The original entry's RGB ref is returned, or nil if the entry is new.")
- (red, green, blue, name)
- Lisp_Object red, green, blue, name;
-{
- Lisp_Object rgb;
- Lisp_Object oldrgb = Qnil;
- Lisp_Object entry;
-
- CHECK_NUMBER (red, 0);
- CHECK_NUMBER (green, 0);
- CHECK_NUMBER (blue, 0);
- CHECK_STRING (name, 0);
-
- XSET (rgb, Lisp_Int, RGB(XUINT (red), XUINT (green), XUINT (blue)));
-
- BLOCK_INPUT;
-
- /* replace existing entry in w32-color-map or add new entry. */
- entry = Fassoc (name, Vw32_color_map);
- if (NILP (entry))
- {
- entry = Fcons (name, rgb);
- Vw32_color_map = Fcons (entry, Vw32_color_map);
- }
- else
- {
- oldrgb = Fcdr (entry);
- Fsetcdr (entry, rgb);
- }
-
- UNBLOCK_INPUT;
-
- return (oldrgb);
-}
-
-DEFUN ("w32-load-color-file", Fw32_load_color_file, Sw32_load_color_file, 1, 1, 0,
- "Create an alist of color entries from an external file (ie. rgb.txt).\n\
-Assign this value to w32-color-map to replace the existing color map.\n\
-\
-The file should define one named RGB color per line like so:\
- R G B name\n\
-where R,G,B are numbers between 0 and 255 and name is an arbitrary string.")
- (filename)
- Lisp_Object filename;
-{
- FILE *fp;
- Lisp_Object cmap = Qnil;
- Lisp_Object abspath;
-
- CHECK_STRING (filename, 0);
- abspath = Fexpand_file_name (filename, Qnil);
-
- fp = fopen (XSTRING (filename)->data, "rt");
- if (fp)
- {
- char buf[512];
- int red, green, blue;
- int num;
-
- BLOCK_INPUT;
-
- while (fgets (buf, sizeof (buf), fp) != NULL) {
- if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
- {
- char *name = buf + num;
- num = strlen (name) - 1;
- if (name[num] == '\n')
- name[num] = 0;
- cmap = Fcons (Fcons (build_string (name),
- make_number (RGB (red, green, blue))),
- cmap);
- }
- }
- fclose (fp);
-
- UNBLOCK_INPUT;
- }
-
- return cmap;
-}
-
-/* The default colors for the w32 color map */
-typedef struct colormap_t
-{
- char *name;
- COLORREF colorref;
-} colormap_t;
-
-colormap_t w32_color_map[] =
-{
- {"snow" , PALETTERGB (255,250,250)},
- {"ghost white" , PALETTERGB (248,248,255)},
- {"GhostWhite" , PALETTERGB (248,248,255)},
- {"white smoke" , PALETTERGB (245,245,245)},
- {"WhiteSmoke" , PALETTERGB (245,245,245)},
- {"gainsboro" , PALETTERGB (220,220,220)},
- {"floral white" , PALETTERGB (255,250,240)},
- {"FloralWhite" , PALETTERGB (255,250,240)},
- {"old lace" , PALETTERGB (253,245,230)},
- {"OldLace" , PALETTERGB (253,245,230)},
- {"linen" , PALETTERGB (250,240,230)},
- {"antique white" , PALETTERGB (250,235,215)},
- {"AntiqueWhite" , PALETTERGB (250,235,215)},
- {"papaya whip" , PALETTERGB (255,239,213)},
- {"PapayaWhip" , PALETTERGB (255,239,213)},
- {"blanched almond" , PALETTERGB (255,235,205)},
- {"BlanchedAlmond" , PALETTERGB (255,235,205)},
- {"bisque" , PALETTERGB (255,228,196)},
- {"peach puff" , PALETTERGB (255,218,185)},
- {"PeachPuff" , PALETTERGB (255,218,185)},
- {"navajo white" , PALETTERGB (255,222,173)},
- {"NavajoWhite" , PALETTERGB (255,222,173)},
- {"moccasin" , PALETTERGB (255,228,181)},
- {"cornsilk" , PALETTERGB (255,248,220)},
- {"ivory" , PALETTERGB (255,255,240)},
- {"lemon chiffon" , PALETTERGB (255,250,205)},
- {"LemonChiffon" , PALETTERGB (255,250,205)},
- {"seashell" , PALETTERGB (255,245,238)},
- {"honeydew" , PALETTERGB (240,255,240)},
- {"mint cream" , PALETTERGB (245,255,250)},
- {"MintCream" , PALETTERGB (245,255,250)},
- {"azure" , PALETTERGB (240,255,255)},
- {"alice blue" , PALETTERGB (240,248,255)},
- {"AliceBlue" , PALETTERGB (240,248,255)},
- {"lavender" , PALETTERGB (230,230,250)},
- {"lavender blush" , PALETTERGB (255,240,245)},
- {"LavenderBlush" , PALETTERGB (255,240,245)},
- {"misty rose" , PALETTERGB (255,228,225)},
- {"MistyRose" , PALETTERGB (255,228,225)},
- {"white" , PALETTERGB (255,255,255)},
- {"black" , PALETTERGB ( 0, 0, 0)},
- {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
- {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
- {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
- {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
- {"dim gray" , PALETTERGB (105,105,105)},
- {"DimGray" , PALETTERGB (105,105,105)},
- {"dim grey" , PALETTERGB (105,105,105)},
- {"DimGrey" , PALETTERGB (105,105,105)},
- {"slate gray" , PALETTERGB (112,128,144)},
- {"SlateGray" , PALETTERGB (112,128,144)},
- {"slate grey" , PALETTERGB (112,128,144)},
- {"SlateGrey" , PALETTERGB (112,128,144)},
- {"light slate gray" , PALETTERGB (119,136,153)},
- {"LightSlateGray" , PALETTERGB (119,136,153)},
- {"light slate grey" , PALETTERGB (119,136,153)},
- {"LightSlateGrey" , PALETTERGB (119,136,153)},
- {"gray" , PALETTERGB (190,190,190)},
- {"grey" , PALETTERGB (190,190,190)},
- {"light grey" , PALETTERGB (211,211,211)},
- {"LightGrey" , PALETTERGB (211,211,211)},
- {"light gray" , PALETTERGB (211,211,211)},
- {"LightGray" , PALETTERGB (211,211,211)},
- {"midnight blue" , PALETTERGB ( 25, 25,112)},
- {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
- {"navy" , PALETTERGB ( 0, 0,128)},
- {"navy blue" , PALETTERGB ( 0, 0,128)},
- {"NavyBlue" , PALETTERGB ( 0, 0,128)},
- {"cornflower blue" , PALETTERGB (100,149,237)},
- {"CornflowerBlue" , PALETTERGB (100,149,237)},
- {"dark slate blue" , PALETTERGB ( 72, 61,139)},
- {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
- {"slate blue" , PALETTERGB (106, 90,205)},
- {"SlateBlue" , PALETTERGB (106, 90,205)},
- {"medium slate blue" , PALETTERGB (123,104,238)},
- {"MediumSlateBlue" , PALETTERGB (123,104,238)},
- {"light slate blue" , PALETTERGB (132,112,255)},
- {"LightSlateBlue" , PALETTERGB (132,112,255)},
- {"medium blue" , PALETTERGB ( 0, 0,205)},
- {"MediumBlue" , PALETTERGB ( 0, 0,205)},
- {"royal blue" , PALETTERGB ( 65,105,225)},
- {"RoyalBlue" , PALETTERGB ( 65,105,225)},
- {"blue" , PALETTERGB ( 0, 0,255)},
- {"dodger blue" , PALETTERGB ( 30,144,255)},
- {"DodgerBlue" , PALETTERGB ( 30,144,255)},
- {"deep sky blue" , PALETTERGB ( 0,191,255)},
- {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
- {"sky blue" , PALETTERGB (135,206,235)},
- {"SkyBlue" , PALETTERGB (135,206,235)},
- {"light sky blue" , PALETTERGB (135,206,250)},
- {"LightSkyBlue" , PALETTERGB (135,206,250)},
- {"steel blue" , PALETTERGB ( 70,130,180)},
- {"SteelBlue" , PALETTERGB ( 70,130,180)},
- {"light steel blue" , PALETTERGB (176,196,222)},
- {"LightSteelBlue" , PALETTERGB (176,196,222)},
- {"light blue" , PALETTERGB (173,216,230)},
- {"LightBlue" , PALETTERGB (173,216,230)},
- {"powder blue" , PALETTERGB (176,224,230)},
- {"PowderBlue" , PALETTERGB (176,224,230)},
- {"pale turquoise" , PALETTERGB (175,238,238)},
- {"PaleTurquoise" , PALETTERGB (175,238,238)},
- {"dark turquoise" , PALETTERGB ( 0,206,209)},
- {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
- {"medium turquoise" , PALETTERGB ( 72,209,204)},
- {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
- {"turquoise" , PALETTERGB ( 64,224,208)},
- {"cyan" , PALETTERGB ( 0,255,255)},
- {"light cyan" , PALETTERGB (224,255,255)},
- {"LightCyan" , PALETTERGB (224,255,255)},
- {"cadet blue" , PALETTERGB ( 95,158,160)},
- {"CadetBlue" , PALETTERGB ( 95,158,160)},
- {"medium aquamarine" , PALETTERGB (102,205,170)},
- {"MediumAquamarine" , PALETTERGB (102,205,170)},
- {"aquamarine" , PALETTERGB (127,255,212)},
- {"dark green" , PALETTERGB ( 0,100, 0)},
- {"DarkGreen" , PALETTERGB ( 0,100, 0)},
- {"dark olive green" , PALETTERGB ( 85,107, 47)},
- {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
- {"dark sea green" , PALETTERGB (143,188,143)},
- {"DarkSeaGreen" , PALETTERGB (143,188,143)},
- {"sea green" , PALETTERGB ( 46,139, 87)},
- {"SeaGreen" , PALETTERGB ( 46,139, 87)},
- {"medium sea green" , PALETTERGB ( 60,179,113)},
- {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
- {"light sea green" , PALETTERGB ( 32,178,170)},
- {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
- {"pale green" , PALETTERGB (152,251,152)},
- {"PaleGreen" , PALETTERGB (152,251,152)},
- {"spring green" , PALETTERGB ( 0,255,127)},
- {"SpringGreen" , PALETTERGB ( 0,255,127)},
- {"lawn green" , PALETTERGB (124,252, 0)},
- {"LawnGreen" , PALETTERGB (124,252, 0)},
- {"green" , PALETTERGB ( 0,255, 0)},
- {"chartreuse" , PALETTERGB (127,255, 0)},
- {"medium spring green" , PALETTERGB ( 0,250,154)},
- {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
- {"green yellow" , PALETTERGB (173,255, 47)},
- {"GreenYellow" , PALETTERGB (173,255, 47)},
- {"lime green" , PALETTERGB ( 50,205, 50)},
- {"LimeGreen" , PALETTERGB ( 50,205, 50)},
- {"yellow green" , PALETTERGB (154,205, 50)},
- {"YellowGreen" , PALETTERGB (154,205, 50)},
- {"forest green" , PALETTERGB ( 34,139, 34)},
- {"ForestGreen" , PALETTERGB ( 34,139, 34)},
- {"olive drab" , PALETTERGB (107,142, 35)},
- {"OliveDrab" , PALETTERGB (107,142, 35)},
- {"dark khaki" , PALETTERGB (189,183,107)},
- {"DarkKhaki" , PALETTERGB (189,183,107)},
- {"khaki" , PALETTERGB (240,230,140)},
- {"pale goldenrod" , PALETTERGB (238,232,170)},
- {"PaleGoldenrod" , PALETTERGB (238,232,170)},
- {"light goldenrod yellow" , PALETTERGB (250,250,210)},
- {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
- {"light yellow" , PALETTERGB (255,255,224)},
- {"LightYellow" , PALETTERGB (255,255,224)},
- {"yellow" , PALETTERGB (255,255, 0)},
- {"gold" , PALETTERGB (255,215, 0)},
- {"light goldenrod" , PALETTERGB (238,221,130)},
- {"LightGoldenrod" , PALETTERGB (238,221,130)},
- {"goldenrod" , PALETTERGB (218,165, 32)},
- {"dark goldenrod" , PALETTERGB (184,134, 11)},
- {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
- {"rosy brown" , PALETTERGB (188,143,143)},
- {"RosyBrown" , PALETTERGB (188,143,143)},
- {"indian red" , PALETTERGB (205, 92, 92)},
- {"IndianRed" , PALETTERGB (205, 92, 92)},
- {"saddle brown" , PALETTERGB (139, 69, 19)},
- {"SaddleBrown" , PALETTERGB (139, 69, 19)},
- {"sienna" , PALETTERGB (160, 82, 45)},
- {"peru" , PALETTERGB (205,133, 63)},
- {"burlywood" , PALETTERGB (222,184,135)},
- {"beige" , PALETTERGB (245,245,220)},
- {"wheat" , PALETTERGB (245,222,179)},
- {"sandy brown" , PALETTERGB (244,164, 96)},
- {"SandyBrown" , PALETTERGB (244,164, 96)},
- {"tan" , PALETTERGB (210,180,140)},
- {"chocolate" , PALETTERGB (210,105, 30)},
- {"firebrick" , PALETTERGB (178,34, 34)},
- {"brown" , PALETTERGB (165,42, 42)},
- {"dark salmon" , PALETTERGB (233,150,122)},
- {"DarkSalmon" , PALETTERGB (233,150,122)},
- {"salmon" , PALETTERGB (250,128,114)},
- {"light salmon" , PALETTERGB (255,160,122)},
- {"LightSalmon" , PALETTERGB (255,160,122)},
- {"orange" , PALETTERGB (255,165, 0)},
- {"dark orange" , PALETTERGB (255,140, 0)},
- {"DarkOrange" , PALETTERGB (255,140, 0)},
- {"coral" , PALETTERGB (255,127, 80)},
- {"light coral" , PALETTERGB (240,128,128)},
- {"LightCoral" , PALETTERGB (240,128,128)},
- {"tomato" , PALETTERGB (255, 99, 71)},
- {"orange red" , PALETTERGB (255, 69, 0)},
- {"OrangeRed" , PALETTERGB (255, 69, 0)},
- {"red" , PALETTERGB (255, 0, 0)},
- {"hot pink" , PALETTERGB (255,105,180)},
- {"HotPink" , PALETTERGB (255,105,180)},
- {"deep pink" , PALETTERGB (255, 20,147)},
- {"DeepPink" , PALETTERGB (255, 20,147)},
- {"pink" , PALETTERGB (255,192,203)},
- {"light pink" , PALETTERGB (255,182,193)},
- {"LightPink" , PALETTERGB (255,182,193)},
- {"pale violet red" , PALETTERGB (219,112,147)},
- {"PaleVioletRed" , PALETTERGB (219,112,147)},
- {"maroon" , PALETTERGB (176, 48, 96)},
- {"medium violet red" , PALETTERGB (199, 21,133)},
- {"MediumVioletRed" , PALETTERGB (199, 21,133)},
- {"violet red" , PALETTERGB (208, 32,144)},
- {"VioletRed" , PALETTERGB (208, 32,144)},
- {"magenta" , PALETTERGB (255, 0,255)},
- {"violet" , PALETTERGB (238,130,238)},
- {"plum" , PALETTERGB (221,160,221)},
- {"orchid" , PALETTERGB (218,112,214)},
- {"medium orchid" , PALETTERGB (186, 85,211)},
- {"MediumOrchid" , PALETTERGB (186, 85,211)},
- {"dark orchid" , PALETTERGB (153, 50,204)},
- {"DarkOrchid" , PALETTERGB (153, 50,204)},
- {"dark violet" , PALETTERGB (148, 0,211)},
- {"DarkViolet" , PALETTERGB (148, 0,211)},
- {"blue violet" , PALETTERGB (138, 43,226)},
- {"BlueViolet" , PALETTERGB (138, 43,226)},
- {"purple" , PALETTERGB (160, 32,240)},
- {"medium purple" , PALETTERGB (147,112,219)},
- {"MediumPurple" , PALETTERGB (147,112,219)},
- {"thistle" , PALETTERGB (216,191,216)},
- {"gray0" , PALETTERGB ( 0, 0, 0)},
- {"grey0" , PALETTERGB ( 0, 0, 0)},
- {"dark grey" , PALETTERGB (169,169,169)},
- {"DarkGrey" , PALETTERGB (169,169,169)},
- {"dark gray" , PALETTERGB (169,169,169)},
- {"DarkGray" , PALETTERGB (169,169,169)},
- {"dark blue" , PALETTERGB ( 0, 0,139)},
- {"DarkBlue" , PALETTERGB ( 0, 0,139)},
- {"dark cyan" , PALETTERGB ( 0,139,139)},
- {"DarkCyan" , PALETTERGB ( 0,139,139)},
- {"dark magenta" , PALETTERGB (139, 0,139)},
- {"DarkMagenta" , PALETTERGB (139, 0,139)},
- {"dark red" , PALETTERGB (139, 0, 0)},
- {"DarkRed" , PALETTERGB (139, 0, 0)},
- {"light green" , PALETTERGB (144,238,144)},
- {"LightGreen" , PALETTERGB (144,238,144)},
-};
-
-DEFUN ("w32-default-color-map", Fw32_default_color_map, Sw32_default_color_map,
- 0, 0, 0, "Return the default color map.")
- ()
-{
- int i;
- colormap_t *pc = w32_color_map;
- Lisp_Object cmap;
-
- BLOCK_INPUT;
-
- cmap = Qnil;
-
- for (i = 0; i < sizeof (w32_color_map) / sizeof (w32_color_map[0]);
- pc++, i++)
- cmap = Fcons (Fcons (build_string (pc->name),
- make_number (pc->colorref)),
- cmap);
-
- UNBLOCK_INPUT;
-
- return (cmap);
-}
-
-Lisp_Object
-w32_to_x_color (rgb)
- Lisp_Object rgb;
-{
- Lisp_Object color;
-
- CHECK_NUMBER (rgb, 0);
-
- BLOCK_INPUT;
-
- color = Frassq (rgb, Vw32_color_map);
-
- UNBLOCK_INPUT;
-
- if (!NILP (color))
- return (Fcar (color));
- else
- return Qnil;
-}
-
-COLORREF
-x_to_w32_color (colorname)
- char * colorname;
-{
- register Lisp_Object tail, ret = Qnil;
-
- BLOCK_INPUT;
-
- for (tail = Vw32_color_map; !NILP (tail); tail = Fcdr (tail))
- {
- register Lisp_Object elt, tem;
-
- elt = Fcar (tail);
- if (!CONSP (elt)) continue;
-
- tem = Fcar (elt);
-
- if (lstrcmpi (XSTRING (tem)->data, colorname) == 0)
- {
- ret = XUINT(Fcdr (elt));
- break;
- }
-
- QUIT;
- }
-
- UNBLOCK_INPUT;
-
- return ret;
-}
-
-
-void
-w32_regenerate_palette (FRAME_PTR f)
-{
- struct w32_palette_entry * list;
- LOGPALETTE * log_palette;
- HPALETTE new_palette;
- int i;
-
- /* don't bother trying to create palette if not supported */
- if (! FRAME_W32_DISPLAY_INFO (f)->has_palette)
- return;
-
- log_palette = (LOGPALETTE *)
- alloca (sizeof (LOGPALETTE) +
- FRAME_W32_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY));
- log_palette->palVersion = 0x300;
- log_palette->palNumEntries = FRAME_W32_DISPLAY_INFO (f)->num_colors;
-
- list = FRAME_W32_DISPLAY_INFO (f)->color_list;
- for (i = 0;
- i < FRAME_W32_DISPLAY_INFO (f)->num_colors;
- i++, list = list->next)
- log_palette->palPalEntry[i] = list->entry;
-
- new_palette = CreatePalette (log_palette);
-
- enter_crit ();
-
- if (FRAME_W32_DISPLAY_INFO (f)->palette)
- DeleteObject (FRAME_W32_DISPLAY_INFO (f)->palette);
- FRAME_W32_DISPLAY_INFO (f)->palette = new_palette;
-
- /* Realize display palette and garbage all frames. */
- release_frame_dc (f, get_frame_dc (f));
-
- leave_crit ();
-}
-
-#define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
-#define SET_W32_COLOR(pe, color) \
- do \
- { \
- pe.peRed = GetRValue (color); \
- pe.peGreen = GetGValue (color); \
- pe.peBlue = GetBValue (color); \
- pe.peFlags = 0; \
- } while (0)
-
-#if 0
-/* Keep these around in case we ever want to track color usage. */
-void
-w32_map_color (FRAME_PTR f, COLORREF color)
-{
- struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
-
- if (NILP (Vw32_enable_palette))
- return;
-
- /* check if color is already mapped */
- while (list)
- {
- if (W32_COLOR (list->entry) == color)
- {
- ++list->refcount;
- return;
- }
- list = list->next;
- }
-
- /* not already mapped, so add to list and recreate Windows palette */
- list = (struct w32_palette_entry *)
- xmalloc (sizeof (struct w32_palette_entry));
- SET_W32_COLOR (list->entry, color);
- list->refcount = 1;
- list->next = FRAME_W32_DISPLAY_INFO (f)->color_list;
- FRAME_W32_DISPLAY_INFO (f)->color_list = list;
- FRAME_W32_DISPLAY_INFO (f)->num_colors++;
-
- /* set flag that palette must be regenerated */
- FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
-}
-
-void
-w32_unmap_color (FRAME_PTR f, COLORREF color)
-{
- struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
- struct w32_palette_entry **prev = &FRAME_W32_DISPLAY_INFO (f)->color_list;
-
- if (NILP (Vw32_enable_palette))
- return;
-
- /* check if color is already mapped */
- while (list)
- {
- if (W32_COLOR (list->entry) == color)
- {
- if (--list->refcount == 0)
- {
- *prev = list->next;
- xfree (list);
- FRAME_W32_DISPLAY_INFO (f)->num_colors--;
- break;
- }
- else
- return;
- }
- prev = &list->next;
- list = list->next;
- }
-
- /* set flag that palette must be regenerated */
- FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
-}
-#endif
-
-/* Decide if color named COLOR is valid for the display associated with
- the selected frame; if so, return the rgb values in COLOR_DEF.
- If ALLOC is nonzero, allocate a new colormap cell. */
-
-int
-defined_color (f, color, color_def, alloc)
- FRAME_PTR f;
- char *color;
- COLORREF *color_def;
- int alloc;
-{
- register Lisp_Object tem;
-
- tem = x_to_w32_color (color);
-
- if (!NILP (tem))
- {
- if (!NILP (Vw32_enable_palette))
- {
- struct w32_palette_entry * entry =
- FRAME_W32_DISPLAY_INFO (f)->color_list;
- struct w32_palette_entry ** prev =
- &FRAME_W32_DISPLAY_INFO (f)->color_list;
-
- /* check if color is already mapped */
- while (entry)
- {
- if (W32_COLOR (entry->entry) == XUINT (tem))
- break;
- prev = &entry->next;
- entry = entry->next;
- }
-
- if (entry == NULL && alloc)
- {
- /* not already mapped, so add to list */
- entry = (struct w32_palette_entry *)
- xmalloc (sizeof (struct w32_palette_entry));
- SET_W32_COLOR (entry->entry, XUINT (tem));
- entry->next = NULL;
- *prev = entry;
- FRAME_W32_DISPLAY_INFO (f)->num_colors++;
-
- /* set flag that palette must be regenerated */
- FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
- }
- }
- /* Ensure COLORREF value is snapped to nearest color in (default)
- palette by simulating the PALETTERGB macro. This works whether
- or not the display device has a palette. */
- *color_def = XUINT (tem) | 0x2000000;
- return 1;
- }
- else
- {
- return 0;
- }
-}
-
-/* Given a string ARG naming a color, compute a pixel value from it
- suitable for screen F.
- If F is not a color screen, return DEF (default) regardless of what
- ARG says. */
-
-int
-x_decode_color (f, arg, def)
- FRAME_PTR f;
- Lisp_Object arg;
- int def;
-{
- COLORREF cdef;
-
- CHECK_STRING (arg, 0);
-
- if (strcmp (XSTRING (arg)->data, "black") == 0)
- return BLACK_PIX_DEFAULT (f);
- else if (strcmp (XSTRING (arg)->data, "white") == 0)
- return WHITE_PIX_DEFAULT (f);
-
- if ((FRAME_W32_DISPLAY_INFO (f)->n_planes * FRAME_W32_DISPLAY_INFO (f)->n_cbits) == 1)
- return def;
-
- /* defined_color is responsible for coping with failures
- by looking for a near-miss. */
- if (defined_color (f, XSTRING (arg)->data, &cdef, 1))
- return cdef;
-
- /* defined_color failed; return an ultimate default. */
- return def;
-}
-
-/* Functions called only from `x_set_frame_param'
- to set individual parameters.
-
- If FRAME_W32_WINDOW (f) is 0,
- the frame is being created and its window does not exist yet.
- In that case, just record the parameter's new value
- in the standard place; do not attempt to change the window. */
-
-void
-x_set_foreground_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- f->output_data.w32->foreground_pixel
- = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
-
- if (FRAME_W32_WINDOW (f) != 0)
- {
- recompute_basic_faces (f);
- if (FRAME_VISIBLE_P (f))
- redraw_frame (f);
- }
-}
-
-void
-x_set_background_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- Pixmap temp;
- int mask;
-
- f->output_data.w32->background_pixel
- = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
-
- if (FRAME_W32_WINDOW (f) != 0)
- {
- SetWindowLong (FRAME_W32_WINDOW (f), WND_BACKGROUND_INDEX, f->output_data.w32->background_pixel);
-
- recompute_basic_faces (f);
-
- if (FRAME_VISIBLE_P (f))
- redraw_frame (f);
- }
-}
-
-void
-x_set_mouse_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
-#if 0
- Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
-#endif
- int mask_color;
-
- if (!EQ (Qnil, arg))
- f->output_data.w32->mouse_pixel
- = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
- mask_color = f->output_data.w32->background_pixel;
- /* No invisible pointers. */
- if (mask_color == f->output_data.w32->mouse_pixel
- && mask_color == f->output_data.w32->background_pixel)
- f->output_data.w32->mouse_pixel = f->output_data.w32->foreground_pixel;
-
-#if 0
- BLOCK_INPUT;
-
- /* It's not okay to crash if the user selects a screwy cursor. */
- x_catch_errors (FRAME_W32_DISPLAY (f));
-
- if (!EQ (Qnil, Vx_pointer_shape))
- {
- CHECK_NUMBER (Vx_pointer_shape, 0);
- cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_pointer_shape));
- }
- else
- cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
- x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
-
- if (!EQ (Qnil, Vx_nontext_pointer_shape))
- {
- CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
- nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
- XINT (Vx_nontext_pointer_shape));
- }
- else
- nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
- x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
-
- if (!EQ (Qnil, Vx_mode_pointer_shape))
- {
- CHECK_NUMBER (Vx_mode_pointer_shape, 0);
- mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
- XINT (Vx_mode_pointer_shape));
- }
- else
- mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
- x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
-
- if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
- {
- CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
- cross_cursor
- = XCreateFontCursor (FRAME_W32_DISPLAY (f),
- XINT (Vx_sensitive_text_pointer_shape));
- }
- else
- cross_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
-
- /* Check and report errors with the above calls. */
- x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
- x_uncatch_errors (FRAME_W32_DISPLAY (f));
-
- {
- XColor fore_color, back_color;
-
- fore_color.pixel = f->output_data.w32->mouse_pixel;
- back_color.pixel = mask_color;
- XQueryColor (FRAME_W32_DISPLAY (f),
- DefaultColormap (FRAME_W32_DISPLAY (f),
- DefaultScreen (FRAME_W32_DISPLAY (f))),
- &fore_color);
- XQueryColor (FRAME_W32_DISPLAY (f),
- DefaultColormap (FRAME_W32_DISPLAY (f),
- DefaultScreen (FRAME_W32_DISPLAY (f))),
- &back_color);
- XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
- &fore_color, &back_color);
- XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
- &fore_color, &back_color);
- XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
- &fore_color, &back_color);
- XRecolorCursor (FRAME_W32_DISPLAY (f), cross_cursor,
- &fore_color, &back_color);
- }
-
- if (FRAME_W32_WINDOW (f) != 0)
- {
- XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
- }
-
- if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
- XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
- f->output_data.w32->text_cursor = cursor;
-
- if (nontext_cursor != f->output_data.w32->nontext_cursor
- && f->output_data.w32->nontext_cursor != 0)
- XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
- f->output_data.w32->nontext_cursor = nontext_cursor;
-
- if (mode_cursor != f->output_data.w32->modeline_cursor
- && f->output_data.w32->modeline_cursor != 0)
- XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
- f->output_data.w32->modeline_cursor = mode_cursor;
- if (cross_cursor != f->output_data.w32->cross_cursor
- && f->output_data.w32->cross_cursor != 0)
- XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->cross_cursor);
- f->output_data.w32->cross_cursor = cross_cursor;
-
- XFlush (FRAME_W32_DISPLAY (f));
- UNBLOCK_INPUT;
-#endif
-}
-
-void
-x_set_cursor_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- unsigned long fore_pixel;
-
- if (!EQ (Vx_cursor_fore_pixel, Qnil))
- fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
- WHITE_PIX_DEFAULT (f));
- else
- fore_pixel = f->output_data.w32->background_pixel;
- f->output_data.w32->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
-
- /* Make sure that the cursor color differs from the background color. */
- if (f->output_data.w32->cursor_pixel == f->output_data.w32->background_pixel)
- {
- f->output_data.w32->cursor_pixel = f->output_data.w32->mouse_pixel;
- if (f->output_data.w32->cursor_pixel == fore_pixel)
- fore_pixel = f->output_data.w32->background_pixel;
- }
- f->output_data.w32->cursor_foreground_pixel = fore_pixel;
-
- if (FRAME_W32_WINDOW (f) != 0)
- {
- if (FRAME_VISIBLE_P (f))
- {
- x_display_cursor (f, 0);
- x_display_cursor (f, 1);
- }
- }
-}
-
-/* Set the border-color of frame F to value described by ARG.
- ARG can be a string naming a color.
- The border-color is used for the border that is drawn by the server.
- Note that this does not fully take effect if done before
- F has a window; it must be redone when the window is created. */
-
-void
-x_set_border_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- unsigned char *str;
- int pix;
-
- CHECK_STRING (arg, 0);
- str = XSTRING (arg)->data;
-
- pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
-
- x_set_border_pixel (f, pix);
-}
-
-/* Set the border-color of frame F to pixel value PIX.
- Note that this does not fully take effect if done before
- F has an window. */
-
-x_set_border_pixel (f, pix)
- struct frame *f;
- int pix;
-{
- f->output_data.w32->border_pixel = pix;
-
- if (FRAME_W32_WINDOW (f) != 0 && f->output_data.w32->border_width > 0)
- {
- if (FRAME_VISIBLE_P (f))
- redraw_frame (f);
- }
-}
-
-void
-x_set_cursor_type (f, arg, oldval)
- FRAME_PTR f;
- Lisp_Object arg, oldval;
-{
- if (EQ (arg, Qbar))
- {
- FRAME_DESIRED_CURSOR (f) = bar_cursor;
- f->output_data.w32->cursor_width = 2;
- }
- else if (CONSP (arg) && EQ (XCONS (arg)->car, Qbar)
- && INTEGERP (XCONS (arg)->cdr))
- {
- FRAME_DESIRED_CURSOR (f) = bar_cursor;
- f->output_data.w32->cursor_width = XINT (XCONS (arg)->cdr);
- }
- else
- /* Treat anything unknown as "box cursor".
- It was bad to signal an error; people have trouble fixing
- .Xdefaults with Emacs, when it has something bad in it. */
- FRAME_DESIRED_CURSOR (f) = filled_box_cursor;
-
- /* Make sure the cursor gets redrawn. This is overkill, but how
- often do people change cursor types? */
- update_mode_lines++;
-}
-
-void
-x_set_icon_type (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
-#if 0
- Lisp_Object tem;
- int result;
-
- if (STRINGP (arg))
- {
- if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
- return;
- }
- else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
- return;
-
- BLOCK_INPUT;
- if (NILP (arg))
- result = x_text_icon (f,
- (char *) XSTRING ((!NILP (f->icon_name)
- ? f->icon_name
- : f->name))->data);
- else
- result = x_bitmap_icon (f, arg);
-
- if (result)
- {
- UNBLOCK_INPUT;
- error ("No icon window available");
- }
-
- /* If the window was unmapped (and its icon was mapped),
- the new icon is not mapped, so map the window in its stead. */
- if (FRAME_VISIBLE_P (f))
- {
-#ifdef USE_X_TOOLKIT
- XtPopup (f->output_data.w32->widget, XtGrabNone);
-#endif
- XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
- }
-
- XFlush (FRAME_W32_DISPLAY (f));
- UNBLOCK_INPUT;
-#endif
-}
-
-/* Return non-nil if frame F wants a bitmap icon. */
-
-Lisp_Object
-x_icon_type (f)
- FRAME_PTR f;
-{
- Lisp_Object tem;
-
- tem = assq_no_quit (Qicon_type, f->param_alist);
- if (CONSP (tem))
- return XCONS (tem)->cdr;
- else
- return Qnil;
-}
-
-void
-x_set_icon_name (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- Lisp_Object tem;
- int result;
-
- if (STRINGP (arg))
- {
- if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
- return;
- }
- else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
- return;
-
- f->icon_name = arg;
-
-#if 0
- if (f->output_data.w32->icon_bitmap != 0)
- return;
-
- BLOCK_INPUT;
-
- result = x_text_icon (f,
- (char *) XSTRING ((!NILP (f->icon_name)
- ? f->icon_name
- : f->name))->data);
-
- if (result)
- {
- UNBLOCK_INPUT;
- error ("No icon window available");
- }
-
- /* If the window was unmapped (and its icon was mapped),
- the new icon is not mapped, so map the window in its stead. */
- if (FRAME_VISIBLE_P (f))
- {
-#ifdef USE_X_TOOLKIT
- XtPopup (f->output_data.w32->widget, XtGrabNone);
-#endif
- XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
- }
-
- XFlush (FRAME_W32_DISPLAY (f));
- UNBLOCK_INPUT;
-#endif
-}
-
-extern Lisp_Object x_new_font ();
-
-void
-x_set_font (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- Lisp_Object result;
-
- CHECK_STRING (arg, 1);
-
- BLOCK_INPUT;
- result = x_new_font (f, XSTRING (arg)->data);
- UNBLOCK_INPUT;
-
- if (EQ (result, Qnil))
- error ("Font \"%s\" is not defined", XSTRING (arg)->data);
- else if (EQ (result, Qt))
- error ("the characters of the given font have varying widths");
- else if (STRINGP (result))
- {
- recompute_basic_faces (f);
- store_frame_param (f, Qfont, result);
- }
- else
- abort ();
-}
-
-void
-x_set_border_width (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- CHECK_NUMBER (arg, 0);
-
- if (XINT (arg) == f->output_data.w32->border_width)
- return;
-
- if (FRAME_W32_WINDOW (f) != 0)
- error ("Cannot change the border width of a window");
-
- f->output_data.w32->border_width = XINT (arg);
-}
-
-void
-x_set_internal_border_width (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- int mask;
- int old = f->output_data.w32->internal_border_width;
-
- CHECK_NUMBER (arg, 0);
- f->output_data.w32->internal_border_width = XINT (arg);
- if (f->output_data.w32->internal_border_width < 0)
- f->output_data.w32->internal_border_width = 0;
-
- if (f->output_data.w32->internal_border_width == old)
- return;
-
- if (FRAME_W32_WINDOW (f) != 0)
- {
- BLOCK_INPUT;
- x_set_window_size (f, 0, f->width, f->height);
- UNBLOCK_INPUT;
- SET_FRAME_GARBAGED (f);
- }
-}
-
-void
-x_set_visibility (f, value, oldval)
- struct frame *f;
- Lisp_Object value, oldval;
-{
- Lisp_Object frame;
- XSETFRAME (frame, f);
-
- if (NILP (value))
- Fmake_frame_invisible (frame, Qt);
- else if (EQ (value, Qicon))
- Ficonify_frame (frame);
- else
- Fmake_frame_visible (frame);
-}
-
-void
-x_set_menu_bar_lines (f, value, oldval)
- struct frame *f;
- Lisp_Object value, oldval;
-{
- int nlines;
- int olines = FRAME_MENU_BAR_LINES (f);
-
- /* Right now, menu bars don't work properly in minibuf-only frames;
- most of the commands try to apply themselves to the minibuffer
- frame itslef, and get an error because you can't switch buffers
- in or split the minibuffer window. */
- if (FRAME_MINIBUF_ONLY_P (f))
- return;
-
- if (INTEGERP (value))
- nlines = XINT (value);
- else
- nlines = 0;
-
- FRAME_MENU_BAR_LINES (f) = 0;
- if (nlines)
- FRAME_EXTERNAL_MENU_BAR (f) = 1;
- else
- {
- if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
- free_frame_menubar (f);
- FRAME_EXTERNAL_MENU_BAR (f) = 0;
- }
-}
-
-/* Change the name of frame F to NAME. If NAME is nil, set F's name to
- w32_id_name.
-
- If EXPLICIT is non-zero, that indicates that lisp code is setting the
- name; if NAME is a string, set F's name to NAME and set
- F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
-
- If EXPLICIT is zero, that indicates that Emacs redisplay code is
- suggesting a new name, which lisp code should override; if
- F->explicit_name is set, ignore the new name; otherwise, set it. */
-
-void
-x_set_name (f, name, explicit)
- struct frame *f;
- Lisp_Object name;
- int explicit;
-{
- /* Make sure that requests from lisp code override requests from
- Emacs redisplay code. */
- if (explicit)
- {
- /* If we're switching from explicit to implicit, we had better
- update the mode lines and thereby update the title. */
- if (f->explicit_name && NILP (name))
- update_mode_lines = 1;
-
- f->explicit_name = ! NILP (name);
- }
- else if (f->explicit_name)
- return;
-
- /* If NAME is nil, set the name to the w32_id_name. */
- if (NILP (name))
- {
- /* Check for no change needed in this very common case
- before we do any consing. */
- if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->w32_id_name,
- XSTRING (f->name)->data))
- return;
- name = build_string (FRAME_W32_DISPLAY_INFO (f)->w32_id_name);
- }
- else
- CHECK_STRING (name, 0);
-
- /* Don't change the name if it's already NAME. */
- if (! NILP (Fstring_equal (name, f->name)))
- return;
-
- if (FRAME_W32_WINDOW (f))
- {
- BLOCK_INPUT;
- SetWindowText(FRAME_W32_WINDOW (f), XSTRING (name)->data);
- UNBLOCK_INPUT;
- }
-
- f->name = name;
-}
-
-/* This function should be called when the user's lisp code has
- specified a name for the frame; the name will override any set by the
- redisplay code. */
-void
-x_explicitly_set_name (f, arg, oldval)
- FRAME_PTR f;
- Lisp_Object arg, oldval;
-{
- x_set_name (f, arg, 1);
-}
-
-/* This function should be called by Emacs redisplay code to set the
- name; names set this way will never override names set by the user's
- lisp code. */
-void
-x_implicitly_set_name (f, arg, oldval)
- FRAME_PTR f;
- Lisp_Object arg, oldval;
-{
- x_set_name (f, arg, 0);
-}
-
-void
-x_set_autoraise (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- f->auto_raise = !EQ (Qnil, arg);
-}
-
-void
-x_set_autolower (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- f->auto_lower = !EQ (Qnil, arg);
-}
-
-void
-x_set_unsplittable (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- f->no_split = !NILP (arg);
-}
-
-void
-x_set_vertical_scroll_bars (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
- || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
- || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
- {
- FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = NILP (arg) ?
- vertical_scroll_bar_none :
- EQ (Qright, arg)
- ? vertical_scroll_bar_right
- : vertical_scroll_bar_left;
-
- /* We set this parameter before creating the window for the
- frame, so we can get the geometry right from the start.
- However, if the window hasn't been created yet, we shouldn't
- call x_set_window_size. */
- if (FRAME_W32_WINDOW (f))
- x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
- }
-}
-
-void
-x_set_scroll_bar_width (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- if (NILP (arg))
- {
- FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
- FRAME_SCROLL_BAR_COLS (f) = 2;
- }
- else if (INTEGERP (arg) && XINT (arg) > 0
- && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
- {
- int wid = FONT_WIDTH (f->output_data.w32->font);
- FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
- FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
- if (FRAME_W32_WINDOW (f))
- x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
- }
-}
-
-/* Subroutines of creating an frame. */
-
-/* Make sure that Vx_resource_name is set to a reasonable value.
- Fix it up, or set it to `emacs' if it is too hopeless. */
-
-static void
-validate_x_resource_name ()
-{
- int len;
- /* Number of valid characters in the resource name. */
- int good_count = 0;
- /* Number of invalid characters in the resource name. */
- int bad_count = 0;
- Lisp_Object new;
- int i;
-
- if (STRINGP (Vx_resource_name))
- {
- unsigned char *p = XSTRING (Vx_resource_name)->data;
- int i;
-
- len = XSTRING (Vx_resource_name)->size;
-
- /* Only letters, digits, - and _ are valid in resource names.
- Count the valid characters and count the invalid ones. */
- for (i = 0; i < len; i++)
- {
- int c = p[i];
- if (! ((c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9')
- || c == '-' || c == '_'))
- bad_count++;
- else
- good_count++;
- }
- }
- else
- /* Not a string => completely invalid. */
- bad_count = 5, good_count = 0;
-
- /* If name is valid already, return. */
- if (bad_count == 0)
- return;
-
- /* If name is entirely invalid, or nearly so, use `emacs'. */
- if (good_count == 0
- || (good_count == 1 && bad_count > 0))
- {
- Vx_resource_name = build_string ("emacs");
- return;
- }
-
- /* Name is partly valid. Copy it and replace the invalid characters
- with underscores. */
-
- Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
-
- for (i = 0; i < len; i++)
- {
- int c = XSTRING (new)->data[i];
- if (! ((c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9')
- || c == '-' || c == '_'))
- XSTRING (new)->data[i] = '_';
- }
-}
-
-
-extern char *x_get_string_resource ();
-
-DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
- "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
-This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
-class, where INSTANCE is the name under which Emacs was invoked, or\n\
-the name specified by the `-name' or `-rn' command-line arguments.\n\
-\n\
-The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
-class, respectively. You must specify both of them or neither.\n\
-If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
-and the class is `Emacs.CLASS.SUBCLASS'.")
- (attribute, class, component, subclass)
- Lisp_Object attribute, class, component, subclass;
-{
- register char *value;
- char *name_key;
- char *class_key;
-
- CHECK_STRING (attribute, 0);
- CHECK_STRING (class, 0);
-
- if (!NILP (component))
- CHECK_STRING (component, 1);
- if (!NILP (subclass))
- CHECK_STRING (subclass, 2);
- if (NILP (component) != NILP (subclass))
- error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
-
- validate_x_resource_name ();
-
- /* Allocate space for the components, the dots which separate them,
- and the final '\0'. Make them big enough for the worst case. */
- name_key = (char *) alloca (XSTRING (Vx_resource_name)->size
- + (STRINGP (component)
- ? XSTRING (component)->size : 0)
- + XSTRING (attribute)->size
- + 3);
-
- class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
- + XSTRING (class)->size
- + (STRINGP (subclass)
- ? XSTRING (subclass)->size : 0)
- + 3);
-
- /* Start with emacs.FRAMENAME for the name (the specific one)
- and with `Emacs' for the class key (the general one). */
- strcpy (name_key, XSTRING (Vx_resource_name)->data);
- strcpy (class_key, EMACS_CLASS);
-
- strcat (class_key, ".");
- strcat (class_key, XSTRING (class)->data);
-
- if (!NILP (component))
- {
- strcat (class_key, ".");
- strcat (class_key, XSTRING (subclass)->data);
-
- strcat (name_key, ".");
- strcat (name_key, XSTRING (component)->data);
- }
-
- strcat (name_key, ".");
- strcat (name_key, XSTRING (attribute)->data);
-
- value = x_get_string_resource (Qnil,
- name_key, class_key);
-
- if (value != (char *) 0)
- return build_string (value);
- else
- return Qnil;
-}
-
-/* Used when C code wants a resource value. */
-
-char *
-x_get_resource_string (attribute, class)
- char *attribute, *class;
-{
- register char *value;
- char *name_key;
- char *class_key;
-
- /* Allocate space for the components, the dots which separate them,
- and the final '\0'. */
- name_key = (char *) alloca (XSTRING (Vinvocation_name)->size
- + strlen (attribute) + 2);
- class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
- + strlen (class) + 2);
-
- sprintf (name_key, "%s.%s",
- XSTRING (Vinvocation_name)->data,
- attribute);
- sprintf (class_key, "%s.%s", EMACS_CLASS, class);
-
- return x_get_string_resource (selected_frame,
- name_key, class_key);
-}
-
-/* Types we might convert a resource string into. */
-enum resource_types
- {
- number, boolean, string, symbol
- };
-
-/* Return the value of parameter PARAM.
-
- First search ALIST, then Vdefault_frame_alist, then the X defaults
- database, using ATTRIBUTE as the attribute name and CLASS as its class.
-
- Convert the resource to the type specified by desired_type.
-
- If no default is specified, return Qunbound. If you call
- x_get_arg, make sure you deal with Qunbound in a reasonable way,
- and don't let it get stored in any Lisp-visible variables! */
-
-static Lisp_Object
-x_get_arg (alist, param, attribute, class, type)
- Lisp_Object alist, param;
- char *attribute;
- char *class;
- enum resource_types type;
-{
- register Lisp_Object tem;
-
- tem = Fassq (param, alist);
- if (EQ (tem, Qnil))
- tem = Fassq (param, Vdefault_frame_alist);
- if (EQ (tem, Qnil))
- {
-
- if (attribute)
- {
- tem = Fx_get_resource (build_string (attribute),
- build_string (class),
- Qnil, Qnil);
-
- if (NILP (tem))
- return Qunbound;
-
- switch (type)
- {
- case number:
- return make_number (atoi (XSTRING (tem)->data));
-
- case boolean:
- tem = Fdowncase (tem);
- if (!strcmp (XSTRING (tem)->data, "on")
- || !strcmp (XSTRING (tem)->data, "true"))
- return Qt;
- else
- return Qnil;
-
- case string:
- return tem;
-
- case symbol:
- /* As a special case, we map the values `true' and `on'
- to Qt, and `false' and `off' to Qnil. */
- {
- Lisp_Object lower;
- lower = Fdowncase (tem);
- if (!strcmp (XSTRING (lower)->data, "on")
- || !strcmp (XSTRING (lower)->data, "true"))
- return Qt;
- else if (!strcmp (XSTRING (lower)->data, "off")
- || !strcmp (XSTRING (lower)->data, "false"))
- return Qnil;
- else
- return Fintern (tem, Qnil);
- }
-
- default:
- abort ();
- }
- }
- else
- return Qunbound;
- }
- return Fcdr (tem);
-}
-
-/* Record in frame F the specified or default value according to ALIST
- of the parameter named PARAM (a Lisp symbol).
- If no value is specified for PARAM, look for an X default for XPROP
- on the frame named NAME.
- If that is not found either, use the value DEFLT. */
-
-static Lisp_Object
-x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
- struct frame *f;
- Lisp_Object alist;
- Lisp_Object prop;
- Lisp_Object deflt;
- char *xprop;
- char *xclass;
- enum resource_types type;
-{
- Lisp_Object tem;
-
- tem = x_get_arg (alist, prop, xprop, xclass, type);
- if (EQ (tem, Qunbound))
- tem = deflt;
- x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
- return tem;
-}
-
-DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
- "Parse an X-style geometry string STRING.\n\
-Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
-The properties returned may include `top', `left', `height', and `width'.\n\
-The value of `left' or `top' may be an integer,\n\
-or a list (+ N) meaning N pixels relative to top/left corner,\n\
-or a list (- N) meaning -N pixels relative to bottom/right corner.")
- (string)
- Lisp_Object string;
-{
- int geometry, x, y;
- unsigned int width, height;
- Lisp_Object result;
-
- CHECK_STRING (string, 0);
-
- geometry = XParseGeometry ((char *) XSTRING (string)->data,
- &x, &y, &width, &height);
-
- result = Qnil;
- if (geometry & XValue)
- {
- Lisp_Object element;
-
- if (x >= 0 && (geometry & XNegative))
- element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
- else if (x < 0 && ! (geometry & XNegative))
- element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
- else
- element = Fcons (Qleft, make_number (x));
- result = Fcons (element, result);
- }
-
- if (geometry & YValue)
- {
- Lisp_Object element;
-
- if (y >= 0 && (geometry & YNegative))
- element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
- else if (y < 0 && ! (geometry & YNegative))
- element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
- else
- element = Fcons (Qtop, make_number (y));
- result = Fcons (element, result);
- }
-
- if (geometry & WidthValue)
- result = Fcons (Fcons (Qwidth, make_number (width)), result);
- if (geometry & HeightValue)
- result = Fcons (Fcons (Qheight, make_number (height)), result);
-
- return result;
-}
-
-/* Calculate the desired size and position of this window,
- and return the flags saying which aspects were specified.
-
- This function does not make the coordinates positive. */
-
-#define DEFAULT_ROWS 40
-#define DEFAULT_COLS 80
-
-static int
-x_figure_window_size (f, parms)
- struct frame *f;
- Lisp_Object parms;
-{
- register Lisp_Object tem0, tem1, tem2;
- int height, width, left, top;
- register int geometry;
- long window_prompting = 0;
-
- /* Default values if we fall through.
- Actually, if that happens we should get
- window manager prompting. */
- SET_FRAME_WIDTH (f, DEFAULT_COLS);
- f->height = DEFAULT_ROWS;
- /* Window managers expect that if program-specified
- positions are not (0,0), they're intentional, not defaults. */
- f->output_data.w32->top_pos = 0;
- f->output_data.w32->left_pos = 0;
-
- tem0 = x_get_arg (parms, Qheight, 0, 0, number);
- tem1 = x_get_arg (parms, Qwidth, 0, 0, number);
- tem2 = x_get_arg (parms, Quser_size, 0, 0, number);
- if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
- {
- if (!EQ (tem0, Qunbound))
- {
- CHECK_NUMBER (tem0, 0);
- f->height = XINT (tem0);
- }
- if (!EQ (tem1, Qunbound))
- {
- CHECK_NUMBER (tem1, 0);
- SET_FRAME_WIDTH (f, XINT (tem1));
- }
- if (!NILP (tem2) && !EQ (tem2, Qunbound))
- window_prompting |= USSize;
- else
- window_prompting |= PSize;
- }
-
- f->output_data.w32->vertical_scroll_bar_extra
- = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
- ? 0
- : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
- ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
- : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
- f->output_data.w32->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
- f->output_data.w32->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
-
- tem0 = x_get_arg (parms, Qtop, 0, 0, number);
- tem1 = x_get_arg (parms, Qleft, 0, 0, number);
- tem2 = x_get_arg (parms, Quser_position, 0, 0, number);
- if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
- {
- if (EQ (tem0, Qminus))
- {
- f->output_data.w32->top_pos = 0;
- window_prompting |= YNegative;
- }
- else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qminus)
- && CONSP (XCONS (tem0)->cdr)
- && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
- {
- f->output_data.w32->top_pos = - XINT (XCONS (XCONS (tem0)->cdr)->car);
- window_prompting |= YNegative;
- }
- else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qplus)
- && CONSP (XCONS (tem0)->cdr)
- && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
- {
- f->output_data.w32->top_pos = XINT (XCONS (XCONS (tem0)->cdr)->car);
- }
- else if (EQ (tem0, Qunbound))
- f->output_data.w32->top_pos = 0;
- else
- {
- CHECK_NUMBER (tem0, 0);
- f->output_data.w32->top_pos = XINT (tem0);
- if (f->output_data.w32->top_pos < 0)
- window_prompting |= YNegative;
- }
-
- if (EQ (tem1, Qminus))
- {
- f->output_data.w32->left_pos = 0;
- window_prompting |= XNegative;
- }
- else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qminus)
- && CONSP (XCONS (tem1)->cdr)
- && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
- {
- f->output_data.w32->left_pos = - XINT (XCONS (XCONS (tem1)->cdr)->car);
- window_prompting |= XNegative;
- }
- else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qplus)
- && CONSP (XCONS (tem1)->cdr)
- && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
- {
- f->output_data.w32->left_pos = XINT (XCONS (XCONS (tem1)->cdr)->car);
- }
- else if (EQ (tem1, Qunbound))
- f->output_data.w32->left_pos = 0;
- else
- {
- CHECK_NUMBER (tem1, 0);
- f->output_data.w32->left_pos = XINT (tem1);
- if (f->output_data.w32->left_pos < 0)
- window_prompting |= XNegative;
- }
-
- if (!NILP (tem2) && ! EQ (tem2, Qunbound))
- window_prompting |= USPosition;
- else
- window_prompting |= PPosition;
- }
-
- return window_prompting;
-}
-
-
-
-extern LRESULT CALLBACK w32_wnd_proc ();
-
-BOOL
-w32_init_class (hinst)
- HINSTANCE hinst;
-{
- WNDCLASS wc;
-
- wc.style = CS_HREDRAW | CS_VREDRAW;
- wc.lpfnWndProc = (WNDPROC) w32_wnd_proc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = WND_EXTRA_BYTES;
- wc.hInstance = hinst;
- wc.hIcon = LoadIcon (hinst, EMACS_CLASS);
- wc.hCursor = LoadCursor (NULL, IDC_ARROW);
- wc.hbrBackground = NULL; // GetStockObject (WHITE_BRUSH);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = EMACS_CLASS;
-
- return (RegisterClass (&wc));
-}
-
-HWND
-w32_createscrollbar (f, bar)
- struct frame *f;
- struct scroll_bar * bar;
-{
- return (CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
- /* Position and size of scroll bar. */
- XINT(bar->left), XINT(bar->top),
- XINT(bar->width), XINT(bar->height),
- FRAME_W32_WINDOW (f),
- NULL,
- hinst,
- NULL));
-}
-
-void
-w32_createwindow (f)
- struct frame *f;
-{
- HWND hwnd;
-
- /* Do first time app init */
-
- if (!hprevinst)
- {
- w32_init_class (hinst);
- }
-
- FRAME_W32_WINDOW (f) = hwnd = CreateWindow (EMACS_CLASS,
- f->namebuf,
- f->output_data.w32->dwStyle | WS_CLIPCHILDREN,
- f->output_data.w32->left_pos,
- f->output_data.w32->top_pos,
- PIXEL_WIDTH (f),
- PIXEL_HEIGHT (f),
- NULL,
- NULL,
- hinst,
- NULL);
-
- if (hwnd)
- {
- SetWindowLong (hwnd, WND_X_UNITS_INDEX, FONT_WIDTH (f->output_data.w32->font));
- SetWindowLong (hwnd, WND_Y_UNITS_INDEX, f->output_data.w32->line_height);
- SetWindowLong (hwnd, WND_BACKGROUND_INDEX, f->output_data.w32->background_pixel);
-
- /* Do this to discard the default setting specified by our parent. */
- ShowWindow (hwnd, SW_HIDE);
- }
-}
-
-/* Convert between the modifier bits W32 uses and the modifier bits
- Emacs uses. */
-unsigned int
-w32_get_modifiers ()
-{
- return (((GetKeyState (VK_SHIFT)&0x8000) ? shift_modifier : 0) |
- ((GetKeyState (VK_CONTROL)&0x8000) ? ctrl_modifier : 0) |
- ((GetKeyState (VK_MENU)&0x8000) ?
- ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0));
-}
-
-void
-my_post_msg (wmsg, hwnd, msg, wParam, lParam)
- W32Msg * wmsg;
- HWND hwnd;
- UINT msg;
- WPARAM wParam;
- LPARAM lParam;
-{
- wmsg->msg.hwnd = hwnd;
- wmsg->msg.message = msg;
- wmsg->msg.wParam = wParam;
- wmsg->msg.lParam = lParam;
- wmsg->msg.time = GetMessageTime ();
-
- post_msg (wmsg);
-}
-
-/* GetKeyState and MapVirtualKey on Win95 do not actually distinguish
- between left and right keys as advertised. We test for this
- support dynamically, and set a flag when the support is absent. If
- absent, we keep track of the left and right control and alt keys
- ourselves. This is particularly necessary on keyboards that rely
- upon the AltGr key, which is represented as having the left control
- and right alt keys pressed. For these keyboards, we need to know
- when the left alt key has been pressed in addition to the AltGr key
- so that we can properly support M-AltGr-key sequences (such as M-@
- on Swedish keyboards). */
-
-#define EMACS_LCONTROL 0
-#define EMACS_RCONTROL 1
-#define EMACS_LMENU 2
-#define EMACS_RMENU 3
-
-static int modifiers[4];
-static int modifiers_recorded;
-static int modifier_key_support_tested;
-
-static void
-test_modifier_support (unsigned int wparam)
-{
- unsigned int l, r;
-
- if (wparam != VK_CONTROL && wparam != VK_MENU)
- return;
- if (wparam == VK_CONTROL)
- {
- l = VK_LCONTROL;
- r = VK_RCONTROL;
- }
- else
- {
- l = VK_LMENU;
- r = VK_RMENU;
- }
- if (!(GetKeyState (l) & 0x8000) && !(GetKeyState (r) & 0x8000))
- modifiers_recorded = 1;
- else
- modifiers_recorded = 0;
- modifier_key_support_tested = 1;
-}
-
-static void
-record_keydown (unsigned int wparam, unsigned int lparam)
-{
- int i;
-
- if (!modifier_key_support_tested)
- test_modifier_support (wparam);
-
- if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
- return;
-
- if (wparam == VK_CONTROL)
- i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
- else
- i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
-
- modifiers[i] = 1;
-}
-
-static void
-record_keyup (unsigned int wparam, unsigned int lparam)
-{
- int i;
-
- if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
- return;
-
- if (wparam == VK_CONTROL)
- i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
- else
- i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
-
- modifiers[i] = 0;
-}
-
-/* Emacs can lose focus while a modifier key has been pressed. When
- it regains focus, be conservative and clear all modifiers since
- we cannot reconstruct the left and right modifier state. */
-static void
-reset_modifiers ()
-{
- SHORT ctrl, alt;
-
- if (!modifiers_recorded)
- return;
-
- ctrl = GetAsyncKeyState (VK_CONTROL);
- alt = GetAsyncKeyState (VK_MENU);
-
- if (ctrl == 0 || alt == 0)
- /* Emacs doesn't have keyboard focus. Do nothing. */
- return;
-
- if (!(ctrl & 0x08000))
- /* Clear any recorded control modifier state. */
- modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
-
- if (!(alt & 0x08000))
- /* Clear any recorded alt modifier state. */
- modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
-
- /* Otherwise, leave the modifier state as it was when Emacs lost
- keyboard focus. */
-}
-
-/* Synchronize modifier state with what is reported with the current
- keystroke. Even if we cannot distinguish between left and right
- modifier keys, we know that, if no modifiers are set, then neither
- the left or right modifier should be set. */
-static void
-sync_modifiers ()
-{
- if (!modifiers_recorded)
- return;
-
- if (!(GetKeyState (VK_CONTROL) & 0x8000))
- modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
-
- if (!(GetKeyState (VK_MENU) & 0x8000))
- modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
-}
-
-static int
-modifier_set (int vkey)
-{
- if (vkey == VK_CAPITAL)
- return (GetKeyState (vkey) & 0x1);
- if (!modifiers_recorded)
- return (GetKeyState (vkey) & 0x8000);
-
- switch (vkey)
- {
- case VK_LCONTROL:
- return modifiers[EMACS_LCONTROL];
- case VK_RCONTROL:
- return modifiers[EMACS_RCONTROL];
- case VK_LMENU:
- return modifiers[EMACS_LMENU];
- case VK_RMENU:
- return modifiers[EMACS_RMENU];
- default:
- break;
- }
- return (GetKeyState (vkey) & 0x8000);
-}
-
-/* We map the VK_* modifiers into console modifier constants
- so that we can use the same routines to handle both console
- and window input. */
-
-static int
-construct_modifiers (unsigned int wparam, unsigned int lparam)
-{
- int mods;
-
- if (wparam != VK_CONTROL && wparam != VK_MENU)
- mods = GetLastError ();
-
- mods = 0;
- mods |= (modifier_set (VK_SHIFT)) ? SHIFT_PRESSED : 0;
- mods |= (modifier_set (VK_CAPITAL)) ? CAPSLOCK_ON : 0;
- mods |= (modifier_set (VK_LCONTROL)) ? LEFT_CTRL_PRESSED : 0;
- mods |= (modifier_set (VK_RCONTROL)) ? RIGHT_CTRL_PRESSED : 0;
- mods |= (modifier_set (VK_LMENU)) ? LEFT_ALT_PRESSED : 0;
- mods |= (modifier_set (VK_RMENU)) ? RIGHT_ALT_PRESSED : 0;
-
- return mods;
-}
-
-static unsigned int
-map_keypad_keys (unsigned int wparam, unsigned int lparam)
-{
- unsigned int extended = (lparam & 0x1000000L);
-
- if (wparam < VK_CLEAR || wparam > VK_DELETE)
- return wparam;
-
- if (wparam == VK_RETURN)
- return (extended ? VK_NUMPAD_ENTER : VK_RETURN);
-
- if (wparam >= VK_PRIOR && wparam <= VK_DOWN)
- return (!extended ? (VK_NUMPAD_PRIOR + (wparam - VK_PRIOR)) : wparam);
-
- if (wparam == VK_INSERT || wparam == VK_DELETE)
- return (!extended ? (VK_NUMPAD_INSERT + (wparam - VK_INSERT)) : wparam);
-
- if (wparam == VK_CLEAR)
- return (!extended ? VK_NUMPAD_CLEAR : wparam);
-
- return wparam;
-}
-
-/* Main message dispatch loop. */
-
-DWORD
-win_msg_worker (dw)
- DWORD dw;
-{
- MSG msg;
-
- /* Ensure our message queue is created */
-
- PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
-
- PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0);
-
- while (GetMessage (&msg, NULL, 0, 0))
- {
- if (msg.hwnd == NULL)
- {
- switch (msg.message)
- {
- case WM_EMACS_CREATEWINDOW:
- w32_createwindow ((struct frame *) msg.wParam);
- PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0);
- break;
- case WM_EMACS_CREATESCROLLBAR:
- {
- HWND hwnd = w32_createscrollbar ((struct frame *) msg.wParam,
- (struct scroll_bar *) msg.lParam);
- PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, (WPARAM)hwnd, 0);
- }
- break;
- case WM_EMACS_KILL:
- return (0);
- }
- }
- else
- {
- DispatchMessage (&msg);
- }
- }
-
- return (0);
-}
-
-/* Main window procedure */
-
-extern char *lispy_function_keys[];
-
-LRESULT CALLBACK
-w32_wnd_proc (hwnd, msg, wParam, lParam)
- HWND hwnd;
- UINT msg;
- WPARAM wParam;
- LPARAM lParam;
-{
- struct frame *f;
- LRESULT ret = 1;
- struct w32_display_info *dpyinfo = &one_w32_display_info;
- W32Msg wmsg;
- int windows_translate;
-
- /* Note that it is okay to call x_window_to_frame, even though we are
- not running in the main lisp thread, because frame deletion
- requires the lisp thread to synchronize with this thread. Thus, if
- a frame struct is returned, it can be used without concern that the
- lisp thread might make it disappear while we are using it.
-
- NB. Walking the frame list in this thread is safe (as long as
- writes of Lisp_Object slots are atomic, which they are on Windows).
- Although delete-frame can destructively modify the frame list while
- we are walking it, a garbage collection cannot occur until after
- delete-frame has synchronized with this thread.
-
- It is also safe to use functions that make GDI calls, such as
- w32_clear_rect, because these functions must obtain a DC handle
- from the frame struct using get_frame_dc which is thread-aware. */
-
- switch (msg)
- {
- case WM_ERASEBKGND:
- f = x_window_to_frame (dpyinfo, hwnd);
- if (f)
- {
- GetUpdateRect (hwnd, &wmsg.rect, FALSE);
- w32_clear_rect (f, NULL, &wmsg.rect);
- }
- return 1;
- case WM_PALETTECHANGED:
- /* ignore our own changes */
- if ((HWND)wParam != hwnd)
- {
- f = x_window_to_frame (dpyinfo, hwnd);
- if (f)
- /* get_frame_dc will realize our palette and force all
- frames to be redrawn if needed. */
- release_frame_dc (f, get_frame_dc (f));
- }
- return 0;
- case WM_PAINT:
- {
- PAINTSTRUCT paintStruct;
-
- enter_crit ();
- BeginPaint (hwnd, &paintStruct);
- wmsg.rect = paintStruct.rcPaint;
- EndPaint (hwnd, &paintStruct);
- leave_crit ();
-
- my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
-
- return (0);
- }
-
- case WM_KEYUP:
- case WM_SYSKEYUP:
- record_keyup (wParam, lParam);
- goto dflt;
-
- case WM_KEYDOWN:
- case WM_SYSKEYDOWN:
- /* Synchronize modifiers with current keystroke. */
- sync_modifiers ();
-
- record_keydown (wParam, lParam);
-
- wParam = map_keypad_keys (wParam, lParam);
-
- windows_translate = 0;
- switch (wParam) {
- case VK_LWIN:
- case VK_RWIN:
- case VK_APPS:
- /* More support for these keys will likely be necessary. */
- if (!NILP (Vw32_pass_optional_keys_to_system))
- windows_translate = 1;
- break;
- case VK_MENU:
- if (NILP (Vw32_pass_alt_to_system))
- return 0;
- windows_translate = 1;
- break;
- case VK_CONTROL:
- case VK_CAPITAL:
- case VK_SHIFT:
- case VK_NUMLOCK:
- case VK_SCROLL:
- windows_translate = 1;
- break;
- default:
- /* If not defined as a function key, change it to a WM_CHAR message. */
- if (lispy_function_keys[wParam] == 0)
- msg = WM_CHAR;
- break;
- }
-
- if (windows_translate)
- {
- MSG winmsg = { hwnd, msg, wParam, lParam, 0, {0,0} };
-
- winmsg.time = GetMessageTime ();
- TranslateMessage (&winmsg);
- goto dflt;
- }
-
- /* Fall through */
-
- case WM_SYSCHAR:
- case WM_CHAR:
- wmsg.dwModifiers = construct_modifiers (wParam, lParam);
-
-#if 1
- /* Detect quit_char and set quit-flag directly. Note that we
- still need to post a message to ensure the main thread will be
- woken up if blocked in sys_select(), but we do NOT want to post
- the quit_char message itself (because it will usually be as if
- the user had typed quit_char twice). Instead, we post a dummy
- message that has no particular effect. */
- {
- int c = wParam;
- if (isalpha (c) && (wmsg.dwModifiers == LEFT_CTRL_PRESSED
- || wmsg.dwModifiers == RIGHT_CTRL_PRESSED))
- c = make_ctrl_char (c) & 0377;
- if (c == quit_char)
- {
- Vquit_flag = Qt;
-
- /* The choice of message is somewhat arbitrary, as long as
- the main thread handler just ignores it. */
- msg = WM_QUIT;
- }
- }
-#endif
-
- my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
-
- break;
-
- /* Simulate middle mouse button events when left and right buttons
- are used together, but only if user has two button mouse. */
- case WM_LBUTTONDOWN:
- case WM_RBUTTONDOWN:
- if (XINT (Vw32_num_mouse_buttons) == 3)
- goto handle_plain_button;
-
- {
- int this = (msg == WM_LBUTTONDOWN) ? LMOUSE : RMOUSE;
- int other = (msg == WM_LBUTTONDOWN) ? RMOUSE : LMOUSE;
-
- if (button_state & this)
- return 0;
-
- if (button_state == 0)
- SetCapture (hwnd);
-
- button_state |= this;
-
- if (button_state & other)
- {
- if (mouse_button_timer)
- {
- KillTimer (hwnd, mouse_button_timer);
- mouse_button_timer = 0;
-
- /* Generate middle mouse event instead. */
- msg = WM_MBUTTONDOWN;
- button_state |= MMOUSE;
- }
- else if (button_state & MMOUSE)
- {
- /* Ignore button event if we've already generated a
- middle mouse down event. This happens if the
- user releases and press one of the two buttons
- after we've faked a middle mouse event. */
- return 0;
- }
- else
- {
- /* Flush out saved message. */
- post_msg (&saved_mouse_button_msg);
- }
- wmsg.dwModifiers = w32_get_modifiers ();
- my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
-
- /* Clear message buffer. */
- saved_mouse_button_msg.msg.hwnd = 0;
- }
- else
- {
- /* Hold onto message for now. */
- mouse_button_timer =
- SetTimer (hwnd, MOUSE_BUTTON_ID, XINT (Vw32_mouse_button_tolerance), NULL);
- saved_mouse_button_msg.msg.hwnd = hwnd;
- saved_mouse_button_msg.msg.message = msg;
- saved_mouse_button_msg.msg.wParam = wParam;
- saved_mouse_button_msg.msg.lParam = lParam;
- saved_mouse_button_msg.msg.time = GetMessageTime ();
- saved_mouse_button_msg.dwModifiers = w32_get_modifiers ();
- }
- }
- return 0;
-
- case WM_LBUTTONUP:
- case WM_RBUTTONUP:
- if (XINT (Vw32_num_mouse_buttons) == 3)
- goto handle_plain_button;
-
- {
- int this = (msg == WM_LBUTTONUP) ? LMOUSE : RMOUSE;
- int other = (msg == WM_LBUTTONUP) ? RMOUSE : LMOUSE;
-
- if ((button_state & this) == 0)
- return 0;
-
- button_state &= ~this;
-
- if (button_state & MMOUSE)
- {
- /* Only generate event when second button is released. */
- if ((button_state & other) == 0)
- {
- msg = WM_MBUTTONUP;
- button_state &= ~MMOUSE;
-
- if (button_state) abort ();
- }
- else
- return 0;
- }
- else
- {
- /* Flush out saved message if necessary. */
- if (saved_mouse_button_msg.msg.hwnd)
- {
- post_msg (&saved_mouse_button_msg);
- }
- }
- wmsg.dwModifiers = w32_get_modifiers ();
- my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
-
- /* Always clear message buffer and cancel timer. */
- saved_mouse_button_msg.msg.hwnd = 0;
- KillTimer (hwnd, mouse_button_timer);
- mouse_button_timer = 0;
-
- if (button_state == 0)
- ReleaseCapture ();
- }
- return 0;
-
- case WM_MBUTTONDOWN:
- case WM_MBUTTONUP:
- handle_plain_button:
- {
- BOOL up;
-
- if (parse_button (msg, NULL, &up))
- {
- if (up) ReleaseCapture ();
- else SetCapture (hwnd);
- }
- }
-
- wmsg.dwModifiers = w32_get_modifiers ();
- my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
- return 0;
-
- case WM_VSCROLL:
- case WM_MOUSEMOVE:
- if (XINT (Vw32_mouse_move_interval) <= 0
- || (msg == WM_MOUSEMOVE && button_state == 0))
- {
- wmsg.dwModifiers = w32_get_modifiers ();
- my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
- return 0;
- }
-
- /* Hang onto mouse move and scroll messages for a bit, to avoid
- sending such events to Emacs faster than it can process them.
- If we get more events before the timer from the first message
- expires, we just replace the first message. */
-
- if (saved_mouse_move_msg.msg.hwnd == 0)
- mouse_move_timer =
- SetTimer (hwnd, MOUSE_MOVE_ID, XINT (Vw32_mouse_move_interval), NULL);
-
- /* Hold onto message for now. */
- saved_mouse_move_msg.msg.hwnd = hwnd;
- saved_mouse_move_msg.msg.message = msg;
- saved_mouse_move_msg.msg.wParam = wParam;
- saved_mouse_move_msg.msg.lParam = lParam;
- saved_mouse_move_msg.msg.time = GetMessageTime ();
- saved_mouse_move_msg.dwModifiers = w32_get_modifiers ();
-
- return 0;
-
- case WM_TIMER:
- /* Flush out saved messages if necessary. */
- if (wParam == mouse_button_timer)
- {
- if (saved_mouse_button_msg.msg.hwnd)
- {
- post_msg (&saved_mouse_button_msg);
- saved_mouse_button_msg.msg.hwnd = 0;
- }
- KillTimer (hwnd, mouse_button_timer);
- mouse_button_timer = 0;
- }
- else if (wParam == mouse_move_timer)
- {
- if (saved_mouse_move_msg.msg.hwnd)
- {
- post_msg (&saved_mouse_move_msg);
- saved_mouse_move_msg.msg.hwnd = 0;
- }
- KillTimer (hwnd, mouse_move_timer);
- mouse_move_timer = 0;
- }
- return 0;
-
- case WM_NCACTIVATE:
- /* Windows doesn't send us focus messages when putting up and
- taking down a system popup dialog as for Ctrl-Alt-Del on Win95.
- The only indication we get that something happened is receiving
- this message afterwards. So this is a good time to reset our
- keyboard modifiers' state. */
- reset_modifiers ();
- goto dflt;
-
- case WM_SETFOCUS:
- reset_modifiers ();
- case WM_KILLFOCUS:
- case WM_MOVE:
- case WM_SIZE:
- case WM_SYSCOMMAND:
- case WM_COMMAND:
- wmsg.dwModifiers = w32_get_modifiers ();
- my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
- goto dflt;
-
- case WM_CLOSE:
- wmsg.dwModifiers = w32_get_modifiers ();
- my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
- return 0;
-
- case WM_WINDOWPOSCHANGING:
- {
- WINDOWPLACEMENT wp;
- LPWINDOWPOS lppos = (WINDOWPOS *) lParam;
-
- GetWindowPlacement (hwnd, &wp);
-
- if (wp.showCmd != SW_SHOWMINIMIZED && ! (lppos->flags & SWP_NOSIZE))
- {
- RECT rect;
- int wdiff;
- int hdiff;
- DWORD dwXUnits;
- DWORD dwYUnits;
- RECT wr;
-
- wp.length = sizeof(wp);
- GetWindowRect (hwnd, &wr);
-
- enter_crit ();
-
- dwXUnits = GetWindowLong (hwnd, WND_X_UNITS_INDEX);
- dwYUnits = GetWindowLong (hwnd, WND_Y_UNITS_INDEX);
-
- leave_crit ();
-
- memset (&rect, 0, sizeof (rect));
- AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE),
- GetMenu (hwnd) != NULL);
-
- /* All windows have an extra pixel so subtract 1 */
-
- wdiff = (lppos->cx - (rect.right - rect.left) - 0) % dwXUnits;
- hdiff = (lppos->cy - (rect.bottom - rect.top) - 0) % dwYUnits;
-
- if (wdiff || hdiff)
- {
- /* For right/bottom sizing we can just fix the sizes.
- However for top/left sizing we will need to fix the X
- and Y positions as well. */
-
- lppos->cx -= wdiff;
- lppos->cy -= hdiff;
-
- if (wp.showCmd != SW_SHOWMAXIMIZED
- && ! (lppos->flags & SWP_NOMOVE))
- {
- if (lppos->x != wr.left || lppos->y != wr.top)
- {
- lppos->x += wdiff;
- lppos->y += hdiff;
- }
- else
- {
- lppos->flags |= SWP_NOMOVE;
- }
- }
-
- ret = 0;
- }
- }
- }
-
- if (ret == 0) return (0);
-
- goto dflt;
- case WM_EMACS_SHOWWINDOW:
- return ShowWindow (hwnd, wParam);
- case WM_EMACS_SETWINDOWPOS:
- {
- W32WindowPos * pos = (W32WindowPos *) wParam;
- return SetWindowPos (hwnd, pos->hwndAfter,
- pos->x, pos->y, pos->cx, pos->cy, pos->flags);
- }
- case WM_EMACS_DESTROYWINDOW:
- DestroyWindow ((HWND) wParam);
- break;
- default:
- dflt:
- return DefWindowProc (hwnd, msg, wParam, lParam);
- }
-
- return (1);
-}
-
-void
-my_create_window (f)
- struct frame * f;
-{
- MSG msg;
-
- PostThreadMessage (dwWinThreadId, WM_EMACS_CREATEWINDOW, (WPARAM)f, 0);
- GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
-}
-
-/* Create and set up the w32 window for frame F. */
-
-static void
-w32_window (f, window_prompting, minibuffer_only)
- struct frame *f;
- long window_prompting;
- int minibuffer_only;
-{
- BLOCK_INPUT;
-
- /* Use the resource name as the top-level window name
- for looking up resources. Make a non-Lisp copy
- for the window manager, so GC relocation won't bother it.
-
- Elsewhere we specify the window name for the window manager. */
-
- {
- char *str = (char *) XSTRING (Vx_resource_name)->data;
- f->namebuf = (char *) xmalloc (strlen (str) + 1);
- strcpy (f->namebuf, str);
- }
-
- my_create_window (f);
-
- validate_x_resource_name ();
-
- /* x_set_name normally ignores requests to set the name if the
- requested name is the same as the current name. This is the one
- place where that assumption isn't correct; f->name is set, but
- the server hasn't been told. */
- {
- Lisp_Object name;
- int explicit = f->explicit_name;
-
- f->explicit_name = 0;
- name = f->name;
- f->name = Qnil;
- x_set_name (f, name, explicit);
- }
-
- UNBLOCK_INPUT;
-
- if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
- initialize_frame_menubar (f);
-
- if (FRAME_W32_WINDOW (f) == 0)
- error ("Unable to create window");
-}
-
-/* Handle the icon stuff for this window. Perhaps later we might
- want an x_set_icon_position which can be called interactively as
- well. */
-
-static void
-x_icon (f, parms)
- struct frame *f;
- Lisp_Object parms;
-{
- Lisp_Object icon_x, icon_y;
-
- /* Set the position of the icon. Note that win95 groups all
- icons in the tray. */
- icon_x = x_get_arg (parms, Qicon_left, 0, 0, number);
- icon_y = x_get_arg (parms, Qicon_top, 0, 0, number);
- if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
- {
- CHECK_NUMBER (icon_x, 0);
- CHECK_NUMBER (icon_y, 0);
- }
- else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
- error ("Both left and top icon corners of icon must be specified");
-
- BLOCK_INPUT;
-
- if (! EQ (icon_x, Qunbound))
- x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
-
- UNBLOCK_INPUT;
-}
-
-DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
- 1, 1, 0,
- "Make a new window, which is called a \"frame\" in Emacs terms.\n\
-Returns an Emacs frame object.\n\
-ALIST is an alist of frame parameters.\n\
-If the parameters specify that the frame should not have a minibuffer,\n\
-and do not specify a specific minibuffer window to use,\n\
-then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
-be shared by the new frame.\n\
-\n\
-This function is an internal primitive--use `make-frame' instead.")
- (parms)
- Lisp_Object parms;
-{
- struct frame *f;
- Lisp_Object frame, tem;
- Lisp_Object name;
- int minibuffer_only = 0;
- long window_prompting = 0;
- int width, height;
- int count = specpdl_ptr - specpdl;
- struct gcpro gcpro1;
- Lisp_Object display;
- struct w32_display_info *dpyinfo;
- Lisp_Object parent;
- struct kboard *kb;
-
- /* Use this general default value to start with
- until we know if this frame has a specified name. */
- Vx_resource_name = Vinvocation_name;
-
- display = x_get_arg (parms, Qdisplay, 0, 0, string);
- if (EQ (display, Qunbound))
- display = Qnil;
- dpyinfo = check_x_display_info (display);
-#ifdef MULTI_KBOARD
- kb = dpyinfo->kboard;
-#else
- kb = &the_only_kboard;
-#endif
-
- name = x_get_arg (parms, Qname, "title", "Title", string);
- if (!STRINGP (name)
- && ! EQ (name, Qunbound)
- && ! NILP (name))
- error ("Invalid frame name--not a string or nil");
-
- if (STRINGP (name))
- Vx_resource_name = name;
-
- /* See if parent window is specified. */
- parent = x_get_arg (parms, Qparent_id, NULL, NULL, number);
- if (EQ (parent, Qunbound))
- parent = Qnil;
- if (! NILP (parent))
- CHECK_NUMBER (parent, 0);
-
- tem = x_get_arg (parms, Qminibuffer, 0, 0, symbol);
- if (EQ (tem, Qnone) || NILP (tem))
- f = make_frame_without_minibuffer (Qnil, kb, display);
- else if (EQ (tem, Qonly))
- {
- f = make_minibuffer_frame ();
- minibuffer_only = 1;
- }
- else if (WINDOWP (tem))
- f = make_frame_without_minibuffer (tem, kb, display);
- else
- f = make_frame (1);
-
- /* Note that Windows does support scroll bars. */
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
- /* By default, make scrollbars the system standard width. */
- f->scroll_bar_pixel_width = GetSystemMetrics (SM_CXVSCROLL);
-
- XSETFRAME (frame, f);
- GCPRO1 (frame);
-
- f->output_method = output_w32;
- f->output_data.w32 = (struct w32_output *) xmalloc (sizeof (struct w32_output));
- bzero (f->output_data.w32, sizeof (struct w32_output));
-
-/* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
-#ifdef MULTI_KBOARD
- FRAME_KBOARD (f) = kb;
-#endif
-
- /* Specify the parent under which to make this window. */
-
- if (!NILP (parent))
- {
- f->output_data.w32->parent_desc = (Window) parent;
- f->output_data.w32->explicit_parent = 1;
- }
- else
- {
- f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
- f->output_data.w32->explicit_parent = 0;
- }
-
- /* Note that the frame has no physical cursor right now. */
- f->phys_cursor_x = -1;
-
- /* Set the name; the functions to which we pass f expect the name to
- be set. */
- if (EQ (name, Qunbound) || NILP (name))
- {
- f->name = build_string (dpyinfo->w32_id_name);
- f->explicit_name = 0;
- }
- else
- {
- f->name = name;
- f->explicit_name = 1;
- /* use the frame's title when getting resources for this frame. */
- specbind (Qx_resource_name, name);
- }
-
- /* Extract the window parameters from the supplied values
- that are needed to determine window geometry. */
- {
- Lisp_Object font;
-
- font = x_get_arg (parms, Qfont, "font", "Font", string);
- BLOCK_INPUT;
- /* First, try whatever font the caller has specified. */
- if (STRINGP (font))
- font = x_new_font (f, XSTRING (font)->data);
-#if 0
- /* Try out a font which we hope has bold and italic variations. */
- if (!STRINGP (font))
- font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
- if (! STRINGP (font))
- font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
- if (! STRINGP (font))
- /* This was formerly the first thing tried, but it finds too many fonts
- and takes too long. */
- font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
- /* If those didn't work, look for something which will at least work. */
- if (! STRINGP (font))
- font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
- if (! STRINGP (font))
- font = x_new_font (f, "-*-system-medium-r-normal-*-*-200-*-*-c-120-*-*");
-#endif
- if (! STRINGP (font))
- font = x_new_font (f, "-*-Fixedsys-*-r-*-*-12-90-*-*-c-*-*-*");
- UNBLOCK_INPUT;
- if (! STRINGP (font))
- font = build_string ("-*-system");
-
- x_default_parameter (f, parms, Qfont, font,
- "font", "Font", string);
- }
-
- x_default_parameter (f, parms, Qborder_width, make_number (2),
- "borderwidth", "BorderWidth", number);
- /* This defaults to 2 in order to match xterm. We recognize either
- internalBorderWidth or internalBorder (which is what xterm calls
- it). */
- if (NILP (Fassq (Qinternal_border_width, parms)))
- {
- Lisp_Object value;
-
- value = x_get_arg (parms, Qinternal_border_width,
- "internalBorder", "BorderWidth", number);
- if (! EQ (value, Qunbound))
- parms = Fcons (Fcons (Qinternal_border_width, value),
- parms);
- }
- x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
- "internalBorderWidth", "BorderWidth", number);
- x_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
- "verticalScrollBars", "ScrollBars", boolean);
-
- /* Also do the stuff which must be set before the window exists. */
- x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
- "foreground", "Foreground", string);
- x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
- "background", "Background", string);
- x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
- "pointerColor", "Foreground", string);
- x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
- "cursorColor", "Foreground", string);
- x_default_parameter (f, parms, Qborder_color, build_string ("black"),
- "borderColor", "BorderColor", string);
-
- x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
- "menuBar", "MenuBar", number);
- x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
- "scrollBarWidth", "ScrollBarWidth", number);
-
- f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
- f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
- window_prompting = x_figure_window_size (f, parms);
-
- if (window_prompting & XNegative)
- {
- if (window_prompting & YNegative)
- f->output_data.w32->win_gravity = SouthEastGravity;
- else
- f->output_data.w32->win_gravity = NorthEastGravity;
- }
- else
- {
- if (window_prompting & YNegative)
- f->output_data.w32->win_gravity = SouthWestGravity;
- else
- f->output_data.w32->win_gravity = NorthWestGravity;
- }
-
- f->output_data.w32->size_hint_flags = window_prompting;
-
- w32_window (f, window_prompting, minibuffer_only);
- x_icon (f, parms);
- init_frame_faces (f);
-
- /* We need to do this after creating the window, so that the
- icon-creation functions can say whose icon they're describing. */
- x_default_parameter (f, parms, Qicon_type, Qnil,
- "bitmapIcon", "BitmapIcon", symbol);
-
- x_default_parameter (f, parms, Qauto_raise, Qnil,
- "autoRaise", "AutoRaiseLower", boolean);
- x_default_parameter (f, parms, Qauto_lower, Qnil,
- "autoLower", "AutoRaiseLower", boolean);
- x_default_parameter (f, parms, Qcursor_type, Qbox,
- "cursorType", "CursorType", symbol);
-
- /* Dimensions, especially f->height, must be done via change_frame_size.
- Change will not be effected unless different from the current
- f->height. */
- width = f->width;
- height = f->height;
- f->height = 0;
- SET_FRAME_WIDTH (f, 0);
- change_frame_size (f, height, width, 1, 0);
-
- /* Tell the server what size and position, etc, we want,
- and how badly we want them. */
- BLOCK_INPUT;
- x_wm_set_size_hint (f, window_prompting, 0);
- UNBLOCK_INPUT;
-
- tem = x_get_arg (parms, Qunsplittable, 0, 0, boolean);
- f->no_split = minibuffer_only || EQ (tem, Qt);
-
- UNGCPRO;
-
- /* It is now ok to make the frame official
- even if we get an error below.
- And the frame needs to be on Vframe_list
- or making it visible won't work. */
- Vframe_list = Fcons (frame, Vframe_list);
-
- /* Now that the frame is official, it counts as a reference to
- its display. */
- FRAME_W32_DISPLAY_INFO (f)->reference_count++;
-
- /* Make the window appear on the frame and enable display,
- unless the caller says not to. However, with explicit parent,
- Emacs cannot control visibility, so don't try. */
- if (! f->output_data.w32->explicit_parent)
- {
- Lisp_Object visibility;
-
- visibility = x_get_arg (parms, Qvisibility, 0, 0, symbol);
- if (EQ (visibility, Qunbound))
- visibility = Qt;
-
- if (EQ (visibility, Qicon))
- x_iconify_frame (f);
- else if (! NILP (visibility))
- x_make_frame_visible (f);
- else
- /* Must have been Qnil. */
- ;
- }
-
- return unbind_to (count, frame);
-}
-
-/* FRAME is used only to get a handle on the X display. We don't pass the
- display info directly because we're called from frame.c, which doesn't
- know about that structure. */
-Lisp_Object
-x_get_focus_frame (frame)
- struct frame *frame;
-{
- struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (frame);
- Lisp_Object xfocus;
- if (! dpyinfo->w32_focus_frame)
- return Qnil;
-
- XSETFRAME (xfocus, dpyinfo->w32_focus_frame);
- return xfocus;
-}
-
-XFontStruct *
-w32_load_font (dpyinfo,name)
-struct w32_display_info *dpyinfo;
-char * name;
-{
- XFontStruct * font = NULL;
- BOOL ok;
-
- {
- LOGFONT lf;
-
- if (!name || !x_to_w32_font (name, &lf))
- return (NULL);
-
- font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
-
- if (!font) return (NULL);
-
- BLOCK_INPUT;
-
- font->hfont = CreateFontIndirect (&lf);
- }
-
- if (font->hfont == NULL)
- {
- ok = FALSE;
- }
- else
- {
- HDC hdc;
- HANDLE oldobj;
-
- hdc = GetDC (dpyinfo->root_window);
- oldobj = SelectObject (hdc, font->hfont);
- ok = GetTextMetrics (hdc, &font->tm);
- SelectObject (hdc, oldobj);
- ReleaseDC (dpyinfo->root_window, hdc);
- }
-
- UNBLOCK_INPUT;
-
- if (ok) return (font);
-
- w32_unload_font (dpyinfo, font);
- return (NULL);
-}
-
-void
-w32_unload_font (dpyinfo, font)
- struct w32_display_info *dpyinfo;
- XFontStruct * font;
-{
- if (font)
- {
- if (font->hfont) DeleteObject(font->hfont);
- xfree (font);
- }
-}
-
-/* The font conversion stuff between x and w32 */
-
-/* X font string is as follows (from faces.el)
- * (let ((- "[-?]")
- * (foundry "[^-]+")
- * (family "[^-]+")
- * (weight "\\(bold\\|demibold\\|medium\\)") ; 1
- * (weight\? "\\([^-]*\\)") ; 1
- * (slant "\\([ior]\\)") ; 2
- * (slant\? "\\([^-]?\\)") ; 2
- * (swidth "\\([^-]*\\)") ; 3
- * (adstyle "[^-]*") ; 4
- * (pixelsize "[0-9]+")
- * (pointsize "[0-9][0-9]+")
- * (resx "[0-9][0-9]+")
- * (resy "[0-9][0-9]+")
- * (spacing "[cmp?*]")
- * (avgwidth "[0-9]+")
- * (registry "[^-]+")
- * (encoding "[^-]+")
- * )
- * (setq x-font-regexp
- * (concat "\\`\\*?[-?*]"
- * foundry - family - weight\? - slant\? - swidth - adstyle -
- * pixelsize - pointsize - resx - resy - spacing - registry -
- * encoding "[-?*]\\*?\\'"
- * ))
- * (setq x-font-regexp-head
- * (concat "\\`[-?*]" foundry - family - weight\? - slant\?
- * "\\([-*?]\\|\\'\\)"))
- * (setq x-font-regexp-slant (concat - slant -))
- * (setq x-font-regexp-weight (concat - weight -))
- * nil)
- */
-
-#define FONT_START "[-?]"
-#define FONT_FOUNDRY "[^-]+"
-#define FONT_FAMILY "\\([^-]+\\)" /* 1 */
-#define FONT_WEIGHT "\\(bold\\|demibold\\|medium\\)" /* 2 */
-#define FONT_WEIGHT_Q "\\([^-]*\\)" /* 2 */
-#define FONT_SLANT "\\([ior]\\)" /* 3 */
-#define FONT_SLANT_Q "\\([^-]?\\)" /* 3 */
-#define FONT_SWIDTH "\\([^-]*\\)" /* 4 */
-#define FONT_ADSTYLE "[^-]*"
-#define FONT_PIXELSIZE "[^-]*"
-#define FONT_POINTSIZE "\\([0-9][0-9]+\\|\\*\\)" /* 5 */
-#define FONT_RESX "[0-9][0-9]+"
-#define FONT_RESY "[0-9][0-9]+"
-#define FONT_SPACING "[cmp?*]"
-#define FONT_AVGWIDTH "[0-9]+"
-#define FONT_REGISTRY "[^-]+"
-#define FONT_ENCODING "[^-]+"
-
-#define FONT_REGEXP ("\\`\\*?[-?*]" \
- FONT_FOUNDRY "-" \
- FONT_FAMILY "-" \
- FONT_WEIGHT_Q "-" \
- FONT_SLANT_Q "-" \
- FONT_SWIDTH "-" \
- FONT_ADSTYLE "-" \
- FONT_PIXELSIZE "-" \
- FONT_POINTSIZE "-" \
- "[-?*]\\|\\'")
-
-#define FONT_REGEXP_HEAD ("\\`[-?*]" \
- FONT_FOUNDRY "-" \
- FONT_FAMILY "-" \
- FONT_WEIGHT_Q "-" \
- FONT_SLANT_Q \
- "\\([-*?]\\|\\'\\)")
-
-#define FONT_REGEXP_SLANT "-" FONT_SLANT "-"
-#define FONT_REGEXP_WEIGHT "-" FONT_WEIGHT "-"
-
-LONG
-x_to_w32_weight (lpw)
- char * lpw;
-{
- if (!lpw) return (FW_DONTCARE);
-
- if (stricmp (lpw,"heavy") == 0) return FW_HEAVY;
- else if (stricmp (lpw,"extrabold") == 0) return FW_EXTRABOLD;
- else if (stricmp (lpw,"bold") == 0) return FW_BOLD;
- else if (stricmp (lpw,"demibold") == 0) return FW_SEMIBOLD;
- else if (stricmp (lpw,"medium") == 0) return FW_MEDIUM;
- else if (stricmp (lpw,"normal") == 0) return FW_NORMAL;
- else if (stricmp (lpw,"light") == 0) return FW_LIGHT;
- else if (stricmp (lpw,"extralight") == 0) return FW_EXTRALIGHT;
- else if (stricmp (lpw,"thin") == 0) return FW_THIN;
- else
- return FW_DONTCARE;
-}
-
-
-char *
-w32_to_x_weight (fnweight)
- int fnweight;
-{
- if (fnweight >= FW_HEAVY) return "heavy";
- if (fnweight >= FW_EXTRABOLD) return "extrabold";
- if (fnweight >= FW_BOLD) return "bold";
- if (fnweight >= FW_SEMIBOLD) return "semibold";
- if (fnweight >= FW_MEDIUM) return "medium";
- if (fnweight >= FW_NORMAL) return "normal";
- if (fnweight >= FW_LIGHT) return "light";
- if (fnweight >= FW_EXTRALIGHT) return "extralight";
- if (fnweight >= FW_THIN) return "thin";
- else
- return "*";
-}
-
-LONG
-x_to_w32_charset (lpcs)
- char * lpcs;
-{
- if (!lpcs) return (0);
-
- if (stricmp (lpcs,"ansi") == 0) return ANSI_CHARSET;
- else if (stricmp (lpcs,"iso8859-1") == 0) return ANSI_CHARSET;
- else if (stricmp (lpcs,"iso8859") == 0) return ANSI_CHARSET;
- else if (stricmp (lpcs,"oem") == 0) return OEM_CHARSET;
-#ifdef UNICODE_CHARSET
- else if (stricmp (lpcs,"unicode") == 0) return UNICODE_CHARSET;
- else if (stricmp (lpcs,"iso10646") == 0) return UNICODE_CHARSET;
-#endif
- else
- return 0;
-}
-
-char *
-w32_to_x_charset (fncharset)
- int fncharset;
-{
- switch (fncharset)
- {
- case ANSI_CHARSET: return "ansi";
- case OEM_CHARSET: return "oem";
- case SYMBOL_CHARSET: return "symbol";
-#ifdef UNICODE_CHARSET
- case UNICODE_CHARSET: return "unicode";
-#endif
- }
- return "*";
-}
-
-BOOL
-w32_to_x_font (lplogfont, lpxstr, len)
- LOGFONT * lplogfont;
- char * lpxstr;
- int len;
-{
- char height_pixels[8];
- char height_dpi[8];
- char width_pixels[8];
-
- if (!lpxstr) abort ();
-
- if (!lplogfont)
- return FALSE;
-
- if (lplogfont->lfHeight)
- {
- sprintf (height_pixels, "%u", abs (lplogfont->lfHeight));
- sprintf (height_dpi, "%u",
- (abs (lplogfont->lfHeight) * 720) / one_w32_display_info.height_in);
- }
- else
- {
- strcpy (height_pixels, "*");
- strcpy (height_dpi, "*");
- }
- if (lplogfont->lfWidth)
- sprintf (width_pixels, "%u", lplogfont->lfWidth * 10);
- else
- strcpy (width_pixels, "*");
-
- _snprintf (lpxstr, len - 1,
- "-*-%s-%s-%c-*-*-%s-%s-*-*-%c-%s-*-%s-",
- lplogfont->lfFaceName,
- w32_to_x_weight (lplogfont->lfWeight),
- lplogfont->lfItalic?'i':'r',
- height_pixels,
- height_dpi,
- ((lplogfont->lfPitchAndFamily & 0x3) == VARIABLE_PITCH) ? 'p' : 'c',
- width_pixels,
- w32_to_x_charset (lplogfont->lfCharSet)
- );
-
- lpxstr[len - 1] = 0; /* just to be sure */
- return (TRUE);
-}
-
-BOOL
-x_to_w32_font (lpxstr, lplogfont)
- char * lpxstr;
- LOGFONT * lplogfont;
-{
- if (!lplogfont) return (FALSE);
-
- memset (lplogfont, 0, sizeof (*lplogfont));
-
-#if 1
- lplogfont->lfOutPrecision = OUT_DEFAULT_PRECIS;
- lplogfont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
- lplogfont->lfQuality = DEFAULT_QUALITY;
-#else
- /* go for maximum quality */
- lplogfont->lfOutPrecision = OUT_STROKE_PRECIS;
- lplogfont->lfClipPrecision = CLIP_STROKE_PRECIS;
- lplogfont->lfQuality = PROOF_QUALITY;
-#endif
-
- if (!lpxstr)
- return FALSE;
-
- /* Provide a simple escape mechanism for specifying Windows font names
- * directly -- if font spec does not beginning with '-', assume this
- * format:
- * "<font name>[:height in pixels[:width in pixels[:weight]]]"
- */
-
- if (*lpxstr == '-')
- {
- int fields;
- char name[50], weight[20], slant, pitch, pixels[10], height[10], width[10], remainder[20];
- char * encoding;
-
- fields = sscanf (lpxstr,
- "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%*[^-]-%c-%9[^-]-%19s",
- name, weight, &slant, pixels, height, &pitch, width, remainder);
-
- if (fields == EOF) return (FALSE);
-
- if (fields > 0 && name[0] != '*')
- {
- strncpy (lplogfont->lfFaceName,name, LF_FACESIZE);
- lplogfont->lfFaceName[LF_FACESIZE-1] = 0;
- }
- else
- {
- lplogfont->lfFaceName[0] = 0;
- }
-
- fields--;
-
- lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
-
- fields--;
-
- if (!NILP (Vw32_enable_italics))
- lplogfont->lfItalic = (fields > 0 && slant == 'i');
-
- fields--;
-
- if (fields > 0 && pixels[0] != '*')
- lplogfont->lfHeight = atoi (pixels);
-
- fields--;
-
- if (fields > 0 && lplogfont->lfHeight == 0 && height[0] != '*')
- lplogfont->lfHeight = (atoi (height)
- * one_w32_display_info.height_in) / 720;
-
- fields--;
-
- lplogfont->lfPitchAndFamily =
- (fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
-
- fields--;
-
- if (fields > 0 && width[0] != '*')
- lplogfont->lfWidth = atoi (width) / 10;
-
- fields--;
-
- /* Not all font specs include the registry field, so we allow for an
- optional registry field before the encoding when parsing
- remainder. Also we strip the trailing '-' if present. */
- {
- int len = strlen (remainder);
- if (len > 0 && remainder[len-1] == '-')
- remainder[len-1] = 0;
- }
- encoding = remainder;
- if (strncmp (encoding, "*-", 2) == 0)
- encoding += 2;
- lplogfont->lfCharSet = x_to_w32_charset (fields > 0 ? encoding : "");
- }
- else
- {
- int fields;
- char name[100], height[10], width[10], weight[20];
-
- fields = sscanf (lpxstr,
- "%99[^:]:%9[^:]:%9[^:]:%19s",
- name, height, width, weight);
-
- if (fields == EOF) return (FALSE);
-
- if (fields > 0)
- {
- strncpy (lplogfont->lfFaceName,name, LF_FACESIZE);
- lplogfont->lfFaceName[LF_FACESIZE-1] = 0;
- }
- else
- {
- lplogfont->lfFaceName[0] = 0;
- }
-
- fields--;
-
- if (fields > 0)
- lplogfont->lfHeight = atoi (height);
-
- fields--;
-
- if (fields > 0)
- lplogfont->lfWidth = atoi (width);
-
- fields--;
-
- lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
- }
-
- /* This makes TrueType fonts work better. */
- lplogfont->lfHeight = - abs (lplogfont->lfHeight);
-
- return (TRUE);
-}
-
-BOOL
-w32_font_match (lpszfont1, lpszfont2)
- char * lpszfont1;
- char * lpszfont2;
-{
- char * s1 = lpszfont1, *e1;
- char * s2 = lpszfont2, *e2;
-
- if (s1 == NULL || s2 == NULL) return (FALSE);
-
- if (*s1 == '-') s1++;
- if (*s2 == '-') s2++;
-
- while (1)
- {
- int len1, len2;
-
- e1 = strchr (s1, '-');
- e2 = strchr (s2, '-');
-
- if (e1 == NULL || e2 == NULL) return (TRUE);
-
- len1 = e1 - s1;
- len2 = e2 - s2;
-
- if (*s1 != '*' && *s2 != '*'
- && (len1 != len2 || strnicmp (s1, s2, len1) != 0))
- return (FALSE);
-
- s1 = e1 + 1;
- s2 = e2 + 1;
- }
-}
-
-typedef struct enumfont_t
-{
- HDC hdc;
- int numFonts;
- LOGFONT logfont;
- XFontStruct *size_ref;
- Lisp_Object *pattern;
- Lisp_Object *head;
- Lisp_Object *tail;
-} enumfont_t;
-
-int CALLBACK
-enum_font_cb2 (lplf, lptm, FontType, lpef)
- ENUMLOGFONT * lplf;
- NEWTEXTMETRIC * lptm;
- int FontType;
- enumfont_t * lpef;
-{
- if (lplf->elfLogFont.lfStrikeOut || lplf->elfLogFont.lfUnderline
- || (lplf->elfLogFont.lfCharSet != ANSI_CHARSET && lplf->elfLogFont.lfCharSet != OEM_CHARSET))
- return (1);
-
- /* if (!lpef->size_ref || lptm->tmMaxCharWidth == FONT_WIDTH (lpef->size_ref)) */
- {
- char buf[100];
-
- if (!NILP (*(lpef->pattern)) && FontType == TRUETYPE_FONTTYPE)
- {
- lplf->elfLogFont.lfHeight = lpef->logfont.lfHeight;
- lplf->elfLogFont.lfWidth = lpef->logfont.lfWidth;
- }
-
- if (!w32_to_x_font (lplf, buf, 100)) return (0);
-
- if (NILP (*(lpef->pattern)) || w32_font_match (buf, XSTRING (*(lpef->pattern))->data))
- {
- *lpef->tail = Fcons (build_string (buf), Qnil);
- lpef->tail = &XCONS (*lpef->tail)->cdr;
- lpef->numFonts++;
- }
- }
-
- return (1);
-}
-
-int CALLBACK
-enum_font_cb1 (lplf, lptm, FontType, lpef)
- ENUMLOGFONT * lplf;
- NEWTEXTMETRIC * lptm;
- int FontType;
- enumfont_t * lpef;
-{
- return EnumFontFamilies (lpef->hdc,
- lplf->elfLogFont.lfFaceName,
- (FONTENUMPROC) enum_font_cb2,
- (LPARAM) lpef);
-}
-
-
-DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 3, 0,
- "Return a list of the names of available fonts matching PATTERN.\n\
-If optional arguments FACE and FRAME are specified, return only fonts\n\
-the same size as FACE on FRAME.\n\
-\n\
-PATTERN is a string, perhaps with wildcard characters;\n\
- the * character matches any substring, and\n\
- the ? character matches any single character.\n\
- PATTERN is case-insensitive.\n\
-FACE is a face name--a symbol.\n\
-\n\
-The return value is a list of strings, suitable as arguments to\n\
-set-face-font.\n\
-\n\
-Fonts Emacs can't use (i.e. proportional fonts) may or may not be excluded\n\
-even if they match PATTERN and FACE.")
- (pattern, face, frame)
- Lisp_Object pattern, face, frame;
-{
- int num_fonts;
- char **names;
- XFontStruct *info;
- XFontStruct *size_ref;
- Lisp_Object namelist;
- Lisp_Object list;
- FRAME_PTR f;
- enumfont_t ef;
-
- CHECK_STRING (pattern, 0);
- if (!NILP (face))
- CHECK_SYMBOL (face, 1);
-
- f = check_x_frame (frame);
-
- /* Determine the width standard for comparison with the fonts we find. */
-
- if (NILP (face))
- size_ref = 0;
- else
- {
- int face_id;
-
- /* Don't die if we get called with a terminal frame. */
- if (! FRAME_W32_P (f))
- error ("non-w32 frame used in `x-list-fonts'");
-
- face_id = face_name_id_number (f, face);
-
- if (face_id < 0 || face_id >= FRAME_N_PARAM_FACES (f)
- || FRAME_PARAM_FACES (f) [face_id] == 0)
- size_ref = f->output_data.w32->font;
- else
- {
- size_ref = FRAME_PARAM_FACES (f) [face_id]->font;
- if (size_ref == (XFontStruct *) (~0))
- size_ref = f->output_data.w32->font;
- }
- }
-
- /* See if we cached the result for this particular query. */
- list = Fassoc (pattern,
- XCONS (FRAME_W32_DISPLAY_INFO (f)->name_list_element)->cdr);
-
- /* We have info in the cache for this PATTERN. */
- if (!NILP (list))
- {
- Lisp_Object tem, newlist;
-
- /* We have info about this pattern. */
- list = XCONS (list)->cdr;
-
- if (size_ref == 0)
- return list;
-
- BLOCK_INPUT;
-
- /* Filter the cached info and return just the fonts that match FACE. */
- newlist = Qnil;
- for (tem = list; CONSP (tem); tem = XCONS (tem)->cdr)
- {
- XFontStruct *thisinfo;
-
- thisinfo = w32_load_font (FRAME_W32_DISPLAY_INFO (f), XSTRING (XCONS (tem)->car)->data);
-
- if (thisinfo && same_size_fonts (thisinfo, size_ref))
- newlist = Fcons (XCONS (tem)->car, newlist);
-
- w32_unload_font (FRAME_W32_DISPLAY_INFO (f), thisinfo);
- }
-
- UNBLOCK_INPUT;
-
- return newlist;
- }
-
- BLOCK_INPUT;
-
- namelist = Qnil;
- ef.pattern = &pattern;
- ef.tail = ef.head = &namelist;
- ef.numFonts = 0;
- x_to_w32_font (STRINGP (pattern) ? XSTRING (pattern)->data : NULL, &ef.logfont);
-
- {
- ef.hdc = GetDC (FRAME_W32_WINDOW (f));
-
- EnumFontFamilies (ef.hdc, NULL, (FONTENUMPROC) enum_font_cb1, (LPARAM)&ef);
-
- ReleaseDC (FRAME_W32_WINDOW (f), ef.hdc);
- }
-
- UNBLOCK_INPUT;
-
- if (ef.numFonts)
- {
- int i;
- Lisp_Object cur;
-
- /* Make a list of all the fonts we got back.
- Store that in the font cache for the display. */
- XCONS (FRAME_W32_DISPLAY_INFO (f)->name_list_element)->cdr
- = Fcons (Fcons (pattern, namelist),
- XCONS (FRAME_W32_DISPLAY_INFO (f)->name_list_element)->cdr);
-
- /* Make a list of the fonts that have the right width. */
- list = Qnil;
- cur=namelist;
- for (i = 0; i < ef.numFonts; i++)
- {
- int keeper;
-
- if (!size_ref)
- keeper = 1;
- else
- {
- XFontStruct *thisinfo;
-
- BLOCK_INPUT;
- thisinfo = w32_load_font (FRAME_W32_DISPLAY_INFO (f), XSTRING (Fcar (cur))->data);
-
- keeper = thisinfo && same_size_fonts (thisinfo, size_ref);
-
- w32_unload_font (FRAME_W32_DISPLAY_INFO (f), thisinfo);
-
- UNBLOCK_INPUT;
- }
- if (keeper)
- list = Fcons (build_string (XSTRING (Fcar (cur))->data), list);
-
- cur = Fcdr (cur);
- }
- list = Fnreverse (list);
- }
-
- return list;
-}
-
-DEFUN ("x-color-defined-p", Fx_color_defined_p, Sx_color_defined_p, 1, 2, 0,
- "Return non-nil if color COLOR is supported on frame FRAME.\n\
-If FRAME is omitted or nil, use the selected frame.")
- (color, frame)
- Lisp_Object color, frame;
-{
- COLORREF foo;
- FRAME_PTR f = check_x_frame (frame);
-
- CHECK_STRING (color, 1);
-
- if (defined_color (f, XSTRING (color)->data, &foo, 0))
- return Qt;
- else
- return Qnil;
-}
-
-DEFUN ("x-color-values", Fx_color_values, Sx_color_values, 1, 2, 0,
- "Return a description of the color named COLOR on frame FRAME.\n\
-The value is a list of integer RGB values--(RED GREEN BLUE).\n\
-These values appear to range from 0 to 65280 or 65535, depending\n\
-on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
-If FRAME is omitted or nil, use the selected frame.")
- (color, frame)
- Lisp_Object color, frame;
-{
- COLORREF foo;
- FRAME_PTR f = check_x_frame (frame);
-
- CHECK_STRING (color, 1);
-
- if (defined_color (f, XSTRING (color)->data, &foo, 0))
- {
- Lisp_Object rgb[3];
-
- rgb[0] = make_number (GetRValue (foo));
- rgb[1] = make_number (GetGValue (foo));
- rgb[2] = make_number (GetBValue (foo));
- return Flist (3, rgb);
- }
- else
- return Qnil;
-}
-
-DEFUN ("x-display-color-p", Fx_display_color_p, Sx_display_color_p, 0, 1, 0,
- "Return t if the X display supports color.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
-
- if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
- return Qnil;
-
- return Qt;
-}
-
-DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
- 0, 1, 0,
- "Return t if the X display supports shades of gray.\n\
-Note that color displays do support shades of gray.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
-
- if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
- return Qnil;
-
- return Qt;
-}
-
-DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
- 0, 1, 0,
- "Returns the width in pixels of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (dpyinfo->width);
-}
-
-DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
- Sx_display_pixel_height, 0, 1, 0,
- "Returns the height in pixels of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (dpyinfo->height);
-}
-
-DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
- 0, 1, 0,
- "Returns the number of bitplanes of the display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
-}
-
-DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
- 0, 1, 0,
- "Returns the number of color cells of the display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
- HDC hdc;
- int cap;
-
- hdc = GetDC (dpyinfo->root_window);
- if (dpyinfo->has_palette)
- cap = GetDeviceCaps (hdc,SIZEPALETTE);
- else
- cap = GetDeviceCaps (hdc,NUMCOLORS);
-
- ReleaseDC (dpyinfo->root_window, hdc);
-
- return make_number (cap);
-}
-
-DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
- Sx_server_max_request_size,
- 0, 1, 0,
- "Returns the maximum request size of the server of display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (1);
-}
-
-DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
- "Returns the vendor ID string of the W32 system (Microsoft).\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
- char *vendor = "Microsoft Corp.";
-
- if (! vendor) vendor = "";
- return build_string (vendor);
-}
-
-DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
- "Returns the version numbers of the server of display DISPLAY.\n\
-The value is a list of three integers: the major and minor\n\
-version numbers, and the vendor-specific release\n\
-number. See also the function `x-server-vendor'.\n\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
-
- return Fcons (make_number (w32_major_version),
- Fcons (make_number (w32_minor_version), Qnil));
-}
-
-DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
- "Returns the number of screens on the server of display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (1);
-}
-
-DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
- "Returns the height in millimeters of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
- HDC hdc;
- int cap;
-
- hdc = GetDC (dpyinfo->root_window);
-
- cap = GetDeviceCaps (hdc, VERTSIZE);
-
- ReleaseDC (dpyinfo->root_window, hdc);
-
- return make_number (cap);
-}
-
-DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
- "Returns the width in millimeters of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
-
- HDC hdc;
- int cap;
-
- hdc = GetDC (dpyinfo->root_window);
-
- cap = GetDeviceCaps (hdc, HORZSIZE);
-
- ReleaseDC (dpyinfo->root_window, hdc);
-
- return make_number (cap);
-}
-
-DEFUN ("x-display-backing-store", Fx_display_backing_store,
- Sx_display_backing_store, 0, 1, 0,
- "Returns an indication of whether display DISPLAY does backing store.\n\
-The value may be `always', `when-mapped', or `not-useful'.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- return intern ("not-useful");
-}
-
-DEFUN ("x-display-visual-class", Fx_display_visual_class,
- Sx_display_visual_class, 0, 1, 0,
- "Returns the visual class of the display DISPLAY.\n\
-The value is one of the symbols `static-gray', `gray-scale',\n\
-`static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
-
-#if 0
- switch (dpyinfo->visual->class)
- {
- case StaticGray: return (intern ("static-gray"));
- case GrayScale: return (intern ("gray-scale"));
- case StaticColor: return (intern ("static-color"));
- case PseudoColor: return (intern ("pseudo-color"));
- case TrueColor: return (intern ("true-color"));
- case DirectColor: return (intern ("direct-color"));
- default:
- error ("Display has an unknown visual class");
- }
-#endif
-
- error ("Display has an unknown visual class");
-}
-
-DEFUN ("x-display-save-under", Fx_display_save_under,
- Sx_display_save_under, 0, 1, 0,
- "Returns t if the display DISPLAY supports the save-under feature.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
-
- return Qnil;
-}
-
-int
-x_pixel_width (f)
- register struct frame *f;
-{
- return PIXEL_WIDTH (f);
-}
-
-int
-x_pixel_height (f)
- register struct frame *f;
-{
- return PIXEL_HEIGHT (f);
-}
-
-int
-x_char_width (f)
- register struct frame *f;
-{
- return FONT_WIDTH (f->output_data.w32->font);
-}
-
-int
-x_char_height (f)
- register struct frame *f;
-{
- return f->output_data.w32->line_height;
-}
-
-int
-x_screen_planes (frame)
- Lisp_Object frame;
-{
- return (FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_planes *
- FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_cbits);
-}
-
-/* Return the display structure for the display named NAME.
- Open a new connection if necessary. */
-
-struct w32_display_info *
-x_display_info_for_name (name)
- Lisp_Object name;
-{
- Lisp_Object names;
- struct w32_display_info *dpyinfo;
-
- CHECK_STRING (name, 0);
-
- for (dpyinfo = &one_w32_display_info, names = w32_display_name_list;
- dpyinfo;
- dpyinfo = dpyinfo->next, names = XCONS (names)->cdr)
- {
- Lisp_Object tem;
- tem = Fstring_equal (XCONS (XCONS (names)->car)->car, name);
- if (!NILP (tem))
- return dpyinfo;
- }
-
- /* Use this general default value to start with. */
- Vx_resource_name = Vinvocation_name;
-
- validate_x_resource_name ();
-
- dpyinfo = w32_term_init (name, (unsigned char *)0,
- (char *) XSTRING (Vx_resource_name)->data);
-
- if (dpyinfo == 0)
- error ("Cannot connect to server %s", XSTRING (name)->data);
-
- XSETFASTINT (Vwindow_system_version, 3);
-
- return dpyinfo;
-}
-
-DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
- 1, 3, 0, "Open a connection to a server.\n\
-DISPLAY is the name of the display to connect to.\n\
-Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
-If the optional third arg MUST-SUCCEED is non-nil,\n\
-terminate Emacs if we can't open the connection.")
- (display, xrm_string, must_succeed)
- Lisp_Object display, xrm_string, must_succeed;
-{
- unsigned int n_planes;
- unsigned char *xrm_option;
- struct w32_display_info *dpyinfo;
-
- CHECK_STRING (display, 0);
- if (! NILP (xrm_string))
- CHECK_STRING (xrm_string, 1);
-
- /* Allow color mapping to be defined externally; first look in user's
- HOME directory, then in Emacs etc dir for a file called rgb.txt. */
- {
- Lisp_Object color_file;
- struct gcpro gcpro1;
-
- color_file = build_string("~/rgb.txt");
-
- GCPRO1 (color_file);
-
- if (NILP (Ffile_readable_p (color_file)))
- color_file =
- Fexpand_file_name (build_string ("rgb.txt"),
- Fsymbol_value (intern ("data-directory")));
-
- Vw32_color_map = Fw32_load_color_file (color_file);
-
- UNGCPRO;
- }
- if (NILP (Vw32_color_map))
- Vw32_color_map = Fw32_default_color_map ();
-
- if (! NILP (xrm_string))
- xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
- else
- xrm_option = (unsigned char *) 0;
-
- /* Use this general default value to start with. */
- /* First remove .exe suffix from invocation-name - it looks ugly. */
- {
- char basename[ MAX_PATH ], *str;
-
- strcpy (basename, XSTRING (Vinvocation_name)->data);
- str = strrchr (basename, '.');
- if (str) *str = 0;
- Vinvocation_name = build_string (basename);
- }
- Vx_resource_name = Vinvocation_name;
-
- validate_x_resource_name ();
-
- /* This is what opens the connection and sets x_current_display.
- This also initializes many symbols, such as those used for input. */
- dpyinfo = w32_term_init (display, xrm_option,
- (char *) XSTRING (Vx_resource_name)->data);
-
- if (dpyinfo == 0)
- {
- if (!NILP (must_succeed))
- fatal ("Cannot connect to server %s.\n",
- XSTRING (display)->data);
- else
- error ("Cannot connect to server %s", XSTRING (display)->data);
- }
-
- XSETFASTINT (Vwindow_system_version, 3);
- return Qnil;
-}
-
-DEFUN ("x-close-connection", Fx_close_connection,
- Sx_close_connection, 1, 1, 0,
- "Close the connection to DISPLAY's server.\n\
-For DISPLAY, specify either a frame or a display name (a string).\n\
-If DISPLAY is nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
- struct w32_display_info *tail;
- int i;
-
- if (dpyinfo->reference_count > 0)
- error ("Display still has frames on it");
-
- BLOCK_INPUT;
- /* Free the fonts in the font table. */
- for (i = 0; i < dpyinfo->n_fonts; i++)
- {
- if (dpyinfo->font_table[i].name)
- free (dpyinfo->font_table[i].name);
- /* Don't free the full_name string;
- it is always shared with something else. */
- w32_unload_font (dpyinfo, dpyinfo->font_table[i].font);
- }
- x_destroy_all_bitmaps (dpyinfo);
-
- x_delete_display (dpyinfo);
- UNBLOCK_INPUT;
-
- return Qnil;
-}
-
-DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
- "Return the list of display names that Emacs has connections to.")
- ()
-{
- Lisp_Object tail, result;
-
- result = Qnil;
- for (tail = w32_display_name_list; ! NILP (tail); tail = XCONS (tail)->cdr)
- result = Fcons (XCONS (XCONS (tail)->car)->car, result);
-
- return result;
-}
-
-DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
- "If ON is non-nil, report errors as soon as the erring request is made.\n\
-If ON is nil, allow buffering of requests.\n\
-This is a noop on W32 systems.\n\
-The optional second argument DISPLAY specifies which display to act on.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If DISPLAY is omitted or nil, that stands for the selected frame's display.")
- (on, display)
- Lisp_Object display, on;
-{
- struct w32_display_info *dpyinfo = check_x_display_info (display);
-
- return Qnil;
-}
-
-
-/* These are the w32 specialized functions */
-
-DEFUN ("w32-select-font", Fw32_select_font, Sw32_select_font, 0, 1, 0,
- "This will display the W32 font dialog and return an X font string corresponding to the selection.")
- (frame)
- Lisp_Object frame;
-{
- FRAME_PTR f = check_x_frame (frame);
- CHOOSEFONT cf;
- LOGFONT lf;
- char buf[100];
-
- bzero (&cf, sizeof (cf));
-
- cf.lStructSize = sizeof (cf);
- cf.hwndOwner = FRAME_W32_WINDOW (f);
- cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST | CF_SCREENFONTS;
- cf.lpLogFont = &lf;
-
- if (!ChooseFont (&cf) || !w32_to_x_font (&lf, buf, 100))
- return Qnil;
-
- return build_string (buf);
-}
-
-
-syms_of_w32fns ()
-{
- /* The section below is built by the lisp expression at the top of the file,
- just above where these variables are declared. */
- /*&&& init symbols here &&&*/
- Qauto_raise = intern ("auto-raise");
- staticpro (&Qauto_raise);
- Qauto_lower = intern ("auto-lower");
- staticpro (&Qauto_lower);
- Qbackground_color = intern ("background-color");
- staticpro (&Qbackground_color);
- Qbar = intern ("bar");
- staticpro (&Qbar);
- Qborder_color = intern ("border-color");
- staticpro (&Qborder_color);
- Qborder_width = intern ("border-width");
- staticpro (&Qborder_width);
- Qbox = intern ("box");
- staticpro (&Qbox);
- Qcursor_color = intern ("cursor-color");
- staticpro (&Qcursor_color);
- Qcursor_type = intern ("cursor-type");
- staticpro (&Qcursor_type);
- Qforeground_color = intern ("foreground-color");
- staticpro (&Qforeground_color);
- Qgeometry = intern ("geometry");
- staticpro (&Qgeometry);
- Qicon_left = intern ("icon-left");
- staticpro (&Qicon_left);
- Qicon_top = intern ("icon-top");
- staticpro (&Qicon_top);
- Qicon_type = intern ("icon-type");
- staticpro (&Qicon_type);
- Qicon_name = intern ("icon-name");
- staticpro (&Qicon_name);
- Qinternal_border_width = intern ("internal-border-width");
- staticpro (&Qinternal_border_width);
- Qleft = intern ("left");
- staticpro (&Qleft);
- Qright = intern ("right");
- staticpro (&Qright);
- Qmouse_color = intern ("mouse-color");
- staticpro (&Qmouse_color);
- Qnone = intern ("none");
- staticpro (&Qnone);
- Qparent_id = intern ("parent-id");
- staticpro (&Qparent_id);
- Qscroll_bar_width = intern ("scroll-bar-width");
- staticpro (&Qscroll_bar_width);
- Qsuppress_icon = intern ("suppress-icon");
- staticpro (&Qsuppress_icon);
- Qtop = intern ("top");
- staticpro (&Qtop);
- Qundefined_color = intern ("undefined-color");
- staticpro (&Qundefined_color);
- Qvertical_scroll_bars = intern ("vertical-scroll-bars");
- staticpro (&Qvertical_scroll_bars);
- Qvisibility = intern ("visibility");
- staticpro (&Qvisibility);
- Qwindow_id = intern ("window-id");
- staticpro (&Qwindow_id);
- Qx_frame_parameter = intern ("x-frame-parameter");
- staticpro (&Qx_frame_parameter);
- Qx_resource_name = intern ("x-resource-name");
- staticpro (&Qx_resource_name);
- Quser_position = intern ("user-position");
- staticpro (&Quser_position);
- Quser_size = intern ("user-size");
- staticpro (&Quser_size);
- Qdisplay = intern ("display");
- staticpro (&Qdisplay);
- /* This is the end of symbol initialization. */
-
- Fput (Qundefined_color, Qerror_conditions,
- Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
- Fput (Qundefined_color, Qerror_message,
- build_string ("Undefined color"));
-
- DEFVAR_LISP ("w32-color-map", &Vw32_color_map,
- "A array of color name mappings for windows.");
- Vw32_color_map = Qnil;
-
- DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system,
- "Non-nil if alt key presses are passed on to Windows.\n\
-When non-nil, for example, alt pressed and released and then space will\n\
-open the System menu. When nil, Emacs silently swallows alt key events.");
- Vw32_pass_alt_to_system = Qnil;
-
- DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta,
- "Non-nil if the alt key is to be considered the same as the meta key.\n\
-When nil, Emacs will translate the alt key to the Alt modifier, and not Meta.");
- Vw32_alt_is_meta = Qt;
-
- DEFVAR_LISP ("w32-pass-optional-keys-to-system",
- &Vw32_pass_optional_keys_to_system,
- "Non-nil if the 'optional' keys (left window, right window,\n\
-and application keys) are passed on to Windows.");
- Vw32_pass_optional_keys_to_system = Qnil;
-
- DEFVAR_LISP ("w32-enable-italics", &Vw32_enable_italics,
- "Non-nil enables selection of artificially italicized fonts.");
- Vw32_enable_italics = Qnil;
-
- DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette,
- "Non-nil enables Windows palette management to map colors exactly.");
- Vw32_enable_palette = Qt;
-
- DEFVAR_INT ("w32-mouse-button-tolerance",
- &Vw32_mouse_button_tolerance,
- "Analogue of double click interval for faking middle mouse events.\n\
-The value is the minimum time in milliseconds that must elapse between\n\
-left/right button down events before they are considered distinct events.\n\
-If both mouse buttons are depressed within this interval, a middle mouse\n\
-button down event is generated instead.");
- XSETINT (Vw32_mouse_button_tolerance, GetDoubleClickTime () / 2);
-
- DEFVAR_INT ("w32-mouse-move-interval",
- &Vw32_mouse_move_interval,
- "Minimum interval between mouse move events.\n\
-The value is the minimum time in milliseconds that must elapse between\n\
-successive mouse move (or scroll bar drag) events before they are\n\
-reported as lisp events.");
- XSETINT (Vw32_mouse_move_interval, 50);
-
- init_x_parm_symbols ();
-
- DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
- "List of directories to search for bitmap files for w32.");
- Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
-
- DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
- "The shape of the pointer when over text.\n\
-Changing the value does not affect existing frames\n\
-unless you set the mouse color.");
- Vx_pointer_shape = Qnil;
-
- DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
- "The name Emacs uses to look up resources; for internal use only.\n\
-`x-get-resource' uses this as the first component of the instance name\n\
-when requesting resource values.\n\
-Emacs initially sets `x-resource-name' to the name under which Emacs\n\
-was invoked, or to the value specified with the `-name' or `-rn'\n\
-switches, if present.");
- Vx_resource_name = Qnil;
-
- Vx_nontext_pointer_shape = Qnil;
-
- Vx_mode_pointer_shape = Qnil;
-
- DEFVAR_INT ("x-sensitive-text-pointer-shape",
- &Vx_sensitive_text_pointer_shape,
- "The shape of the pointer when over mouse-sensitive text.\n\
-This variable takes effect when you create a new frame\n\
-or when you set the mouse color.");
- Vx_sensitive_text_pointer_shape = Qnil;
-
- DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
- "A string indicating the foreground color of the cursor box.");
- Vx_cursor_fore_pixel = Qnil;
-
- DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
- "Non-nil if no window manager is in use.\n\
-Emacs doesn't try to figure this out; this is always nil\n\
-unless you set it to something else.");
- /* We don't have any way to find this out, so set it to nil
- and maybe the user would like to set it to t. */
- Vx_no_window_manager = Qnil;
-
- defsubr (&Sx_get_resource);
- defsubr (&Sx_list_fonts);
- defsubr (&Sx_display_color_p);
- defsubr (&Sx_display_grayscale_p);
- defsubr (&Sx_color_defined_p);
- defsubr (&Sx_color_values);
- defsubr (&Sx_server_max_request_size);
- defsubr (&Sx_server_vendor);
- defsubr (&Sx_server_version);
- defsubr (&Sx_display_pixel_width);
- defsubr (&Sx_display_pixel_height);
- defsubr (&Sx_display_mm_width);
- defsubr (&Sx_display_mm_height);
- defsubr (&Sx_display_screens);
- defsubr (&Sx_display_planes);
- defsubr (&Sx_display_color_cells);
- defsubr (&Sx_display_visual_class);
- defsubr (&Sx_display_backing_store);
- defsubr (&Sx_display_save_under);
- defsubr (&Sx_parse_geometry);
- defsubr (&Sx_create_frame);
- defsubr (&Sfocus_frame);
- defsubr (&Sunfocus_frame);
- defsubr (&Sx_open_connection);
- defsubr (&Sx_close_connection);
- defsubr (&Sx_display_list);
- defsubr (&Sx_synchronize);
-
- /* W32 specific functions */
-
- defsubr (&Sw32_select_font);
- defsubr (&Sw32_define_rgb_color);
- defsubr (&Sw32_default_color_map);
- defsubr (&Sw32_load_color_file);
-}
-
-#undef abort
-
-void
-w32_abort()
-{
- int button;
- button = MessageBox (NULL,
- "A fatal error has occurred!\n\n"
- "Select Abort to exit, Retry to debug, Ignore to continue",
- "Emacs Abort Dialog",
- MB_ICONEXCLAMATION | MB_TASKMODAL
- | MB_SETFOREGROUND | MB_ABORTRETRYIGNORE);
- switch (button)
- {
- case IDRETRY:
- DebugBreak ();
- break;
- case IDIGNORE:
- break;
- case IDABORT:
- default:
- abort ();
- break;
- }
-}
-
diff --git a/src/w32gui.h b/src/w32gui.h
deleted file mode 100644
index 00b3b331612..00000000000
--- a/src/w32gui.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Definitions and headers for communication with Win32 GUI.
- Copyright (C) 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifndef __WIN32_H__
-#define __WIN32_H__
-
-#include <windows.h>
-
-typedef struct W32FontStruct {
- TEXTMETRIC tm;
- HFONT hfont;
-} W32FontStruct;
-
-typedef HBITMAP Pixmap;
-typedef HBITMAP Bitmap;
-typedef struct W32FontStruct XFontStruct;
-typedef HDC GC;
-typedef COLORREF Color;
-typedef DWORD Time;
-typedef HWND Window;
-typedef HCURSOR Cursor;
-
-#define FACE_DEFAULT (~0)
-
-extern HINSTANCE hinst;
-extern HINSTANCE hprevinst;
-extern LPSTR lpCmdLine;
-extern int nCmdShow;
-
-/* Bit Gravity */
-
-#define ForgetGravity 0
-#define NorthWestGravity 1
-#define NorthGravity 2
-#define NorthEastGravity 3
-#define WestGravity 4
-#define CenterGravity 5
-#define EastGravity 6
-#define SouthWestGravity 7
-#define SouthGravity 8
-#define SouthEastGravity 9
-#define StaticGravity 10
-
-#define NoValue 0x0000
-#define XValue 0x0001
-#define YValue 0x0002
-#define WidthValue 0x0004
-#define HeightValue 0x0008
-#define AllValues 0x000F
-#define XNegative 0x0010
-#define YNegative 0x0020
-
-#define USPosition (1L << 0) /* user specified x, y */
-#define USSize (1L << 1) /* user specified width, height */
-
-#define PPosition (1L << 2) /* program specified position */
-#define PSize (1L << 3) /* program specified size */
-#define PMinSize (1L << 4) /* program specified minimum size */
-#define PMaxSize (1L << 5) /* program specified maximum size */
-#define PResizeInc (1L << 6) /* program specified resize increments */
-#define PAspect (1L << 7) /* program specified min and max aspect ratios */
-#define PBaseSize (1L << 8) /* program specified base for incrementing */
-#define PWinGravity (1L << 9) /* program specified window gravity */
-
-extern int XParseGeometry ();
-
-#endif
diff --git a/src/w32heap.c b/src/w32heap.c
deleted file mode 100644
index a16872e2d11..00000000000
--- a/src/w32heap.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/* Heap management routines for GNU Emacs on Windows NT.
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
- Geoff Voelker (voelker@cs.washington.edu) 7-29-94
-*/
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "w32heap.h"
-#include "lisp.h" /* for VALMASK */
-
-/* This gives us the page size and the size of the allocation unit on NT. */
-SYSTEM_INFO sysinfo_cache;
-unsigned long syspage_mask = 0;
-
-/* These are defined to get Emacs to compile, but are not used. */
-int edata;
-int etext;
-
-/* The major and minor versions of NT. */
-int w32_major_version;
-int w32_minor_version;
-
-/* Cache information describing the NT system for later use. */
-void
-cache_system_info (void)
-{
- union
- {
- struct info
- {
- char major;
- char minor;
- short platform;
- } info;
- DWORD data;
- } version;
-
- /* Cache the version of the operating system. */
- version.data = GetVersion ();
- w32_major_version = version.info.major;
- w32_minor_version = version.info.minor;
-
- /* Cache page size, allocation unit, processor type, etc. */
- GetSystemInfo (&sysinfo_cache);
- syspage_mask = sysinfo_cache.dwPageSize - 1;
-}
-
-/* Round ADDRESS up to be aligned with ALIGN. */
-unsigned char *
-round_to_next (unsigned char *address, unsigned long align)
-{
- unsigned long tmp;
-
- tmp = (unsigned long) address;
- tmp = (tmp + align - 1) / align;
-
- return (unsigned char *) (tmp * align);
-}
-
-/* Info for keeping track of our heap. */
-unsigned char *data_region_base = NULL;
-unsigned char *data_region_end = NULL;
-unsigned char *real_data_region_end = NULL;
-unsigned long data_region_size = 0;
-unsigned long reserved_heap_size = 0;
-
-/* The start of the data segment. */
-unsigned char *
-get_data_start (void)
-{
- return data_region_base;
-}
-
-/* The end of the data segment. */
-unsigned char *
-get_data_end (void)
-{
- return data_region_end;
-}
-
-static char *
-allocate_heap (void)
-{
- /* The base address for our GNU malloc heap is chosen in conjuction
- with the link settings for temacs.exe which control the stack size,
- the initial default process heap size and the executable image base
- address. The link settings and the malloc heap base below must all
- correspond; the relationship between these values depends on how NT
- and Win95 arrange the virtual address space for a process (and on
- the size of the code and data segments in temacs.exe).
-
- The most important thing is to make base address for the executable
- image high enough to leave enough room between it and the 4MB floor
- of the process address space on Win95 for the primary thread stack,
- the process default heap, and other assorted odds and ends
- (eg. environment strings, private system dll memory etc) that are
- allocated before temacs has a chance to grab its malloc arena. The
- malloc heap base can then be set several MB higher than the
- executable image base, leaving enough room for the code and data
- segments.
-
- Because some parts of Emacs can use rather a lot of stack space
- (for instance, the regular expression routines can potentially
- allocate several MB of stack space) we allow 8MB for the stack.
-
- Allowing 1MB for the default process heap, and 1MB for odds and
- ends, we can base the executable at 16MB and still have a generous
- safety margin. At the moment, the executable has about 810KB of
- code (for x86) and about 550KB of data - on RISC platforms the code
- size could be roughly double, so if we allow 4MB for the executable
- we will have plenty of room for expansion.
-
- Thus we would like to set the malloc heap base to 20MB. However,
- Win95 refuses to allocate the heap starting at this address, so we
- set the base to 27MB to make it happy. Since Emacs now leaves
- 28 bits available for pointers, this lets us use the remainder of
- the region below the 256MB line for our malloc arena - 229MB is
- still a pretty decent arena to play in! */
-
- unsigned long base = 0x01B00000; /* 27MB */
- unsigned long end = 1 << VALBITS; /* 256MB */
- void *ptr = NULL;
-
-#if NTHEAP_PROBE_BASE /* This is never normally defined */
- /* Try various addresses looking for one the kernel will let us have. */
- while (!ptr && (base < end))
- {
- reserved_heap_size = end - base;
- ptr = VirtualAlloc ((void *) base,
- get_reserved_heap_size (),
- MEM_RESERVE,
- PAGE_NOACCESS);
- base += 0x00100000; /* 1MB increment */
- }
-#else
- reserved_heap_size = end - base;
- ptr = VirtualAlloc ((void *) base,
- get_reserved_heap_size (),
- MEM_RESERVE,
- PAGE_NOACCESS);
-#endif
-
- return ptr;
-}
-
-
-/* Emulate Unix sbrk. */
-void *
-sbrk (unsigned long increment)
-{
- void *result;
- long size = (long) increment;
-
- /* Allocate our heap if we haven't done so already. */
- if (!data_region_base)
- {
- data_region_base = allocate_heap ();
- if (!data_region_base)
- return NULL;
-
- /* Ensure that the addresses don't use the upper tag bits since
- the Lisp type goes there. */
- if (((unsigned long) data_region_base & ~VALMASK) != 0)
- {
- printf ("Error: The heap was allocated in upper memory.\n");
- exit (1);
- }
-
- data_region_end = data_region_base;
- real_data_region_end = data_region_end;
- data_region_size = get_reserved_heap_size ();
- }
-
- result = data_region_end;
-
- /* If size is negative, shrink the heap by decommitting pages. */
- if (size < 0)
- {
- int new_size;
- unsigned char *new_data_region_end;
-
- size = -size;
-
- /* Sanity checks. */
- if ((data_region_end - size) < data_region_base)
- return NULL;
-
- /* We can only decommit full pages, so allow for
- partial deallocation [cga]. */
- new_data_region_end = (data_region_end - size);
- new_data_region_end = (unsigned char *)
- ((long) (new_data_region_end + syspage_mask) & ~syspage_mask);
- new_size = real_data_region_end - new_data_region_end;
- real_data_region_end = new_data_region_end;
- if (new_size > 0)
- {
- /* Decommit size bytes from the end of the heap. */
- if (!VirtualFree (real_data_region_end, new_size, MEM_DECOMMIT))
- return NULL;
- }
-
- data_region_end -= size;
- }
- /* If size is positive, grow the heap by committing reserved pages. */
- else if (size > 0)
- {
- /* Sanity checks. */
- if ((data_region_end + size) >
- (data_region_base + get_reserved_heap_size ()))
- return NULL;
-
- /* Commit more of our heap. */
- if (VirtualAlloc (data_region_end, size, MEM_COMMIT,
- PAGE_READWRITE) == NULL)
- return NULL;
- data_region_end += size;
-
- /* We really only commit full pages, so record where
- the real end of committed memory is [cga]. */
- real_data_region_end = (unsigned char *)
- ((long) (data_region_end + syspage_mask) & ~syspage_mask);
- }
-
- return result;
-}
-
-/* Recreate the heap from the data that was dumped to the executable.
- EXECUTABLE_PATH tells us where to find the executable. */
-void
-recreate_heap (char *executable_path)
-{
- unsigned char *tmp;
-
- /* First reserve the upper part of our heap. (We reserve first
- because there have been problems in the past where doing the
- mapping first has loaded DLLs into the VA space of our heap.) */
- tmp = VirtualAlloc ((void *) get_heap_end (),
- get_reserved_heap_size () - get_committed_heap_size (),
- MEM_RESERVE,
- PAGE_NOACCESS);
- if (!tmp)
- exit (1);
-
- /* We read in the data for the .bss section from the executable
- first and map in the heap from the executable second to prevent
- any funny interactions between file I/O and file mapping. */
- read_in_bss (executable_path);
- map_in_heap (executable_path);
-}
-
-/* Round the heap up to the given alignment. */
-void
-round_heap (unsigned long align)
-{
- unsigned long needs_to_be;
- unsigned long need_to_alloc;
-
- needs_to_be = (unsigned long) round_to_next (get_heap_end (), align);
- need_to_alloc = needs_to_be - (unsigned long) get_heap_end ();
-
- if (need_to_alloc)
- sbrk (need_to_alloc);
-}
diff --git a/src/w32heap.h b/src/w32heap.h
deleted file mode 100644
index 24ed080ff7f..00000000000
--- a/src/w32heap.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Heap management routines (including unexec) for GNU Emacs on Windows NT.
- Copyright (C) 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
- Geoff Voelker (voelker@cs.washington.edu) 7-29-94
-*/
-
-#ifndef NTHEAP_H_
-#define NTHEAP_H_
-
-#include <windows.h>
-
-/*
- * Heap related stuff.
- */
-#define get_reserved_heap_size() reserved_heap_size
-#define get_committed_heap_size() (get_data_end () - get_data_start ())
-#define get_heap_start() get_data_start ()
-#define get_heap_end() get_data_end ()
-#define get_page_size() sysinfo_cache.dwPageSize
-#define get_allocation_unit() sysinfo_cache.dwAllocationGranularity
-#define get_processor_type() sysinfo_cache.dwProcessorType
-#define get_w32_major_version() w32_major_version
-#define get_w32_minor_version() w32_minor_version
-
-extern unsigned char *get_data_start();
-extern unsigned char *get_data_end();
-extern unsigned long data_region_size;
-extern unsigned long reserved_heap_size;
-extern SYSTEM_INFO sysinfo_cache;
-extern BOOL need_to_recreate_heap;
-extern int w32_major_version;
-extern int w32_minor_version;
-
-/* Emulation of Unix sbrk(). */
-extern void *sbrk (unsigned long size);
-
-/* Recreate the heap created during dumping. */
-extern void recreate_heap (char *executable_path);
-
-/* Round the heap to this size. */
-extern void round_heap (unsigned long size);
-
-/* Load in the dumped .bss section. */
-extern void read_in_bss (char *name);
-
-/* Map in the dumped heap. */
-extern void map_in_heap (char *name);
-
-/* Cache system info, e.g., the NT page size. */
-extern void cache_system_info (void);
-
-/* Round ADDRESS up to be aligned with ALIGN. */
-extern unsigned char *round_to_next (unsigned char *address,
- unsigned long align);
-
-#endif /* NTHEAP_H_ */
diff --git a/src/w32inevt.c b/src/w32inevt.c
deleted file mode 100644
index 7e811bfe1df..00000000000
--- a/src/w32inevt.c
+++ /dev/null
@@ -1,580 +0,0 @@
-/* Input event support for Emacs under Win32 API.
- Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
- Drew Bliss 01-Oct-93
- Adapted from ntkbd.c by Tim Fleehart
-*/
-
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <windows.h>
-
-#include "lisp.h"
-#include "frame.h"
-#include "blockinput.h"
-#include "termhooks.h"
-
-/* stdin, from ntterm */
-extern HANDLE keyboard_handle;
-
-/* Info for last mouse motion */
-static COORD movement_pos;
-static DWORD movement_time;
-
-/* from keyboard.c */
-extern void reinvoke_input_signal (void);
-
-/* from dispnew.c */
-extern int change_frame_size (FRAME_PTR, int, int, int, int);
-
-/* from w32fns.c */
-extern Lisp_Object Vw32_alt_is_meta;
-
-/* Event queue */
-#define EVENT_QUEUE_SIZE 50
-static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
-static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
-
-static int
-fill_queue (BOOL block)
-{
- BOOL rc;
- DWORD events_waiting;
-
- if (queue_ptr < queue_end)
- return queue_end-queue_ptr;
-
- if (!block)
- {
- /* Check to see if there are some events to read before we try
- because we can't block. */
- if (!GetNumberOfConsoleInputEvents (keyboard_handle, &events_waiting))
- return -1;
- if (events_waiting == 0)
- return 0;
- }
-
- rc = ReadConsoleInput (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
- &events_waiting);
- if (!rc)
- return -1;
- queue_ptr = event_queue;
- queue_end = event_queue + events_waiting;
- return (int) events_waiting;
-}
-
-/* In a generic, multi-frame world this should take a console handle
- and return the frame for it
-
- Right now, there's only one frame so return it. */
-static FRAME_PTR
-get_frame (void)
-{
- return selected_frame;
-}
-
-/* Translate console modifiers to emacs modifiers.
- German keyboard support (Kai Morgan Zeise 2/18/95). */
-int
-w32_kbd_mods_to_emacs (DWORD mods)
-{
- int retval = 0;
-
- /* If AltGr has been pressed, remove it. */
- if ((mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
- == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
- mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED);
-
- if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
- retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier);
-
- if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
- {
- retval |= ctrl_modifier;
- if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
- == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
- retval |= meta_modifier;
- }
-
- if (((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) == SHIFT_PRESSED)
- || ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) == CAPSLOCK_ON))
- retval |= shift_modifier;
-
- return retval;
-}
-
-/* The return code indicates key code size. */
-int
-w32_kbd_patch_key (KEY_EVENT_RECORD *event)
-{
- unsigned int key_code = event->wVirtualKeyCode;
- unsigned int mods = event->dwControlKeyState;
- BYTE keystate[256];
- static BYTE ansi_code[4];
- static int isdead = 0;
-
- if (isdead == 2)
- {
- event->uChar.AsciiChar = ansi_code[2];
- isdead = 0;
- return 1;
- }
- if (event->uChar.AsciiChar != 0)
- return 1;
-
- memset (keystate, 0, sizeof (keystate));
- if (mods & SHIFT_PRESSED)
- keystate[VK_SHIFT] = 0x80;
- if (mods & CAPSLOCK_ON)
- keystate[VK_CAPITAL] = 1;
- if ((mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED))
- {
- keystate[VK_CONTROL] = 0x80;
- keystate[VK_LCONTROL] = 0x80;
- keystate[VK_MENU] = 0x80;
- keystate[VK_RMENU] = 0x80;
- }
-
- isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode,
- keystate, (LPWORD) ansi_code, 0);
- if (isdead == 0)
- return 0;
- event->uChar.AsciiChar = ansi_code[0];
- return isdead;
-}
-
-/* Map virtual key codes into:
- -1 - Ignore this key
- -2 - ASCII char
- Other - Map non-ASCII keys into X keysyms so that they are looked up
- correctly in keyboard.c
-
- Return, escape and tab are mapped to ASCII rather than coming back
- as non-ASCII to be more compatible with old-style keyboard support. */
-
-static int map_virt_key[256] =
-{
-#ifdef MULE
- -3,
-#else
- -1,
-#endif
- -1, /* VK_LBUTTON */
- -1, /* VK_RBUTTON */
- 0x69, /* VK_CANCEL */
- -1, /* VK_MBUTTON */
- -1, -1, -1,
- 8, /* VK_BACK */
- -2, /* VK_TAB */
- -1, -1,
- 11, /* VK_CLEAR */
- -2, /* VK_RETURN */
- -1, -1,
- -1, /* VK_SHIFT */
- -1, /* VK_CONTROL */
- -1, /* VK_MENU */
- 0x13, /* VK_PAUSE */
- -1, /* VK_CAPITAL */
- -1, -1, -1, -1, -1, -1,
- -2, /* VK_ESCAPE */
- -1, -1, -1, -1,
- -2, /* VK_SPACE */
- 0x55, /* VK_PRIOR */
- 0x56, /* VK_NEXT */
- 0x57, /* VK_END */
- 0x50, /* VK_HOME */
- 0x51, /* VK_LEFT */
- 0x52, /* VK_UP */
- 0x53, /* VK_RIGHT */
- 0x54, /* VK_DOWN */
- 0x60, /* VK_SELECT */
- 0x61, /* VK_PRINT */
- 0x62, /* VK_EXECUTE */
- -1, /* VK_SNAPSHOT */
- 0x63, /* VK_INSERT */
- 0xff, /* VK_DELETE */
- 0x6a, /* VK_HELP */
- -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, /* 0 - 9 */
- -1, -1, -1, -1, -1, -1, -1,
- -2, -2, -2, -2, -2, -2, -2, -2, /* A - Z */
- -2, -2, -2, -2, -2, -2, -2, -2,
- -2, -2, -2, -2, -2, -2, -2, -2,
- -2, -2,
- -1, -1, -1, -1, -1,
- 0xb0, /* VK_NUMPAD0 */
- 0xb1, /* VK_NUMPAD1 */
- 0xb2, /* VK_NUMPAD2 */
- 0xb3, /* VK_NUMPAD3 */
- 0xb4, /* VK_NUMPAD4 */
- 0xb5, /* VK_NUMPAD5 */
- 0xb6, /* VK_NUMPAD6 */
- 0xb7, /* VK_NUMPAD7 */
- 0xb8, /* VK_NUMPAD8 */
- 0xb9, /* VK_NUMPAD9 */
- 0xaa, /* VK_MULTIPLY */
- 0xab, /* VK_ADD */
- 0xac, /* VK_SEPARATOR */
- 0xad, /* VK_SUBTRACT */
- 0xae, /* VK_DECIMAL */
- 0xaf, /* VK_DIVIDE */
- 0xbe, /* VK_F1 */
- 0xbf, /* VK_F2 */
- 0xc0, /* VK_F3 */
- 0xc1, /* VK_F4 */
- 0xc2, /* VK_F5 */
- 0xc3, /* VK_F6 */
- 0xc4, /* VK_F7 */
- 0xc5, /* VK_F8 */
- 0xc6, /* VK_F9 */
- 0xc7, /* VK_F10 */
- 0xc8, /* VK_F11 */
- 0xc9, /* VK_F12 */
- 0xca, /* VK_F13 */
- 0xcb, /* VK_F14 */
- 0xcc, /* VK_F15 */
- 0xcd, /* VK_F16 */
- 0xce, /* VK_F17 */
- 0xcf, /* VK_F18 */
- 0xd0, /* VK_F19 */
- 0xd1, /* VK_F20 */
- 0xd2, /* VK_F21 */
- 0xd3, /* VK_F22 */
- 0xd4, /* VK_F23 */
- 0xd5, /* VK_F24 */
- -1, -1, -1, -1, -1, -1, -1, -1,
- 0x7f, /* VK_NUMLOCK */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xaf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb9 */
- -2, /* ; */
- -2, /* = */
- -2, /* , */
- -2, /* \ */
- -2, /* . */
- -2, /* / */
- -2, /* ` */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xcf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xda */
- -2, -2, -2, -2, -2, /* 0xdf */
- -2, -2, -2, -2, -2,
- -1, /* 0xe5 */
- -2, /* oxe6 */
- -1, -1, /* 0xe8 */
- -2, -2, -2, -2, -2, -2, -2, /* 0xef */
- -2, -2, -2, -2, -2, -2,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xff */
-};
-
-/* return code -1 means that event_queue_ptr won't be incremented.
- In other word, this event makes two key codes. (by himi) */
-int
-key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev)
-{
- int map;
- int key_flag = 0;
- static BOOL map_virt_key_init_done;
-
- /* Skip key-up events. */
- if (!event->bKeyDown)
- return 0;
-
- if (event->wVirtualKeyCode > 0xff)
- {
- printf ("Unknown key code %d\n", event->wVirtualKeyCode);
- return 0;
- }
-
- /* Patch needed for German keyboard. Ulrich Leodolter (1/11/95). */
- if (! map_virt_key_init_done)
- {
- short vk;
-
- if ((vk = VkKeyScan (0x3c)) >= 0 && vk < 256) map_virt_key[vk] = -2; /* less */
- if ((vk = VkKeyScan (0x3e)) >= 0 && vk < 256) map_virt_key[vk] = -2; /* greater */
-
- map_virt_key_init_done = TRUE;
- }
-
- /* BUGBUG - Ignores the repeat count
- It's questionable whether we want to obey the repeat count anyway
- since keys usually aren't repeated unless key events back up in
- the queue. If they're backing up then we don't generally want
- to honor them later since that leads to significant slop in
- cursor motion when the system is under heavy load. */
-
- map = map_virt_key[event->wVirtualKeyCode];
- if (map == -1)
- {
- return 0;
- }
- else if (map == -2)
- {
- /* ASCII */
- emacs_ev->kind = ascii_keystroke;
- key_flag = w32_kbd_patch_key (event); /* 95.7.25 by himi */
- if (key_flag == 0)
- return 0;
- XSETINT (emacs_ev->code, event->uChar.AsciiChar);
- }
-#ifdef MULE
- /* for IME */
- else if (map == -3)
- {
- if ((event->dwControlKeyState & NLS_IME_CONVERSION)
- && !(event->dwControlKeyState & RIGHT_ALT_PRESSED)
- && !(event->dwControlKeyState & LEFT_ALT_PRESSED)
- && !(event->dwControlKeyState & RIGHT_CTRL_PRESSED)
- && !(event->dwControlKeyState & LEFT_CTRL_PRESSED))
- {
- emacs_ev->kind = ascii_keystroke;
- XSETINT (emacs_ev->code, event->uChar.AsciiChar);
- }
- else
- return 0;
- }
-#endif
- else
- {
- /* non-ASCII */
- emacs_ev->kind = non_ascii_keystroke;
-#ifdef HAVE_NTGUI
- /* use Windows keysym map */
- XSETINT (emacs_ev->code, event->wVirtualKeyCode);
-#else
- /*
- * make_lispy_event () now requires non-ascii codes to have
- * the full X keysym values (2nd byte is 0xff). add it on.
- */
- map |= 0xff00;
- XSETINT (emacs_ev->code, map);
-#endif /* HAVE_NTGUI */
- }
-/* for Mule 2.2 (Based on Emacs 19.28) */
-#ifdef MULE
- XSET (emacs_ev->frame_or_window, Lisp_Frame, get_frame ());
-#else
- XSETFRAME (emacs_ev->frame_or_window, get_frame ());
-#endif
- emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState);
- emacs_ev->timestamp = GetTickCount ();
- if (key_flag == 2) return -1; /* 95.7.25 by himi */
- return 1;
-}
-
-/* Mouse position hook. */
-void
-w32_mouse_position (FRAME_PTR *f,
-#ifndef MULE
- int insist,
-#endif
- Lisp_Object *bar_window,
- enum scroll_bar_part *part,
- Lisp_Object *x,
- Lisp_Object *y,
- unsigned long *time)
-{
- BLOCK_INPUT;
-
-#ifndef MULE
- insist = insist;
-#endif
-
- *f = get_frame ();
- *bar_window = Qnil;
- *part = 0;
- selected_frame->mouse_moved = 0;
-
- *x = movement_pos.X;
- *y = movement_pos.Y;
- *time = movement_time;
-
- UNBLOCK_INPUT;
-}
-
-/* Remember mouse motion and notify emacs. */
-static void
-mouse_moved_to (int x, int y)
-{
- /* If we're in the same place, ignore it */
- if (x != movement_pos.X || y != movement_pos.Y)
- {
- selected_frame->mouse_moved = 1;
- movement_pos.X = x;
- movement_pos.Y = y;
- movement_time = GetTickCount ();
- }
-}
-
-/* Consoles return button bits in a strange order:
- least significant - Leftmost button
- next - Rightmost button
- next - Leftmost+1
- next - Leftmost+2...
-
- Assume emacs likes three button mice, so
- Left == 0
- Middle == 1
- Right == 2
- Others increase from there. */
-
-static int emacs_button_translation[NUM_MOUSE_BUTTONS] =
-{
- 0, 2, 1, 3, 4,
-};
-
-static int
-do_mouse_event (MOUSE_EVENT_RECORD *event,
- struct input_event *emacs_ev)
-{
- static DWORD button_state = 0;
- DWORD but_change, mask;
- int i;
-
- if (event->dwEventFlags == MOUSE_MOVED)
- {
- /* For movement events we just note that the mouse has moved
- so that emacs will generate drag events. */
- mouse_moved_to (event->dwMousePosition.X, event->dwMousePosition.Y);
- return 0;
- }
-
- /* It looks like the console code sends us a mouse event with
- dwButtonState == 0 when a window is activated. Ignore this case. */
- if (event->dwButtonState == button_state)
- return 0;
-
- emacs_ev->kind = mouse_click;
-
- /* Find out what button has changed state since the last button event. */
- but_change = button_state ^ event->dwButtonState;
- mask = 1;
- for (i = 0; i < NUM_MOUSE_BUTTONS; i++, mask <<= 1)
- if (but_change & mask)
- {
- XSETINT (emacs_ev->code, emacs_button_translation[i]);
- break;
- }
-
- /* If the changed button is out of emacs' range (highly unlikely)
- ignore this event. */
- if (i == NUM_MOUSE_BUTTONS)
- return 0;
-
- button_state = event->dwButtonState;
- emacs_ev->timestamp = GetTickCount ();
- emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState) |
- ((event->dwButtonState & mask) ? down_modifier : up_modifier);
-
- XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
- XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
-/* for Mule 2.2 (Based on Emacs 19.28 */
-#ifdef MULE
- XSET (emacs_ev->frame_or_window, Lisp_Frame, get_frame ());
-#else
- XSETFRAME (emacs_ev->frame_or_window, get_frame ());
-#endif
-
- return 1;
-}
-
-static void
-resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
-{
- FRAME_PTR f = get_frame ();
-
- change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1);
- SET_FRAME_GARBAGED (f);
-}
-
-int
-w32_console_read_socket (int sd, struct input_event *bufp, int numchars,
- int waitp, int expected)
-{
- BOOL no_events = TRUE;
- int nev, ret = 0, add;
-
- if (interrupt_input_blocked)
- {
- interrupt_input_pending = 1;
- return -1;
- }
-
- interrupt_input_pending = 0;
- BLOCK_INPUT;
-
- for (;;)
- {
- nev = fill_queue (0);
- if (nev <= 0)
- {
- /* If nev == -1, there was some kind of error
- If nev == 0 then waitp must be zero and no events were available
- so return. */
- UNBLOCK_INPUT;
- return nev;
- }
-
- while (nev > 0 && numchars > 0)
- {
- switch (queue_ptr->EventType)
- {
- case KEY_EVENT:
- add = key_event (&queue_ptr->Event.KeyEvent, bufp);
- if (add == -1) /* 95.7.25 by himi */
- {
- queue_ptr--;
- add = 1;
- }
- bufp += add;
- ret += add;
- numchars -= add;
- break;
-
- case MOUSE_EVENT:
- add = do_mouse_event (&queue_ptr->Event.MouseEvent, bufp);
- bufp += add;
- ret += add;
- numchars -= add;
- break;
-
- case WINDOW_BUFFER_SIZE_EVENT:
- resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
- break;
-
- case MENU_EVENT:
- case FOCUS_EVENT:
- /* Internal event types, ignored. */
- break;
- }
-
- queue_ptr++;
- nev--;
- }
-
- if (ret > 0 || expected == 0)
- break;
- }
-
- UNBLOCK_INPUT;
- return ret;
-}
diff --git a/src/w32inevt.h b/src/w32inevt.h
deleted file mode 100644
index f0a0a9c5ad9..00000000000
--- a/src/w32inevt.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Input routines for Emacs on Win32 API.
- Copyright (C) 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifndef __NTINEVT_H__
-#define __NTINEVT_H__
-
-int w32_console_read_socket (/* int sd, struct input_event *bufp, int numchars,
- int waitp, int expected */);
-void w32_mouse_position (/* FRAME_PTR *f,
- Lisp_Object *bar_window,
- enum scroll_bar_part *part,
- Lisp_Object *x,
- Lisp_Object *y,
- unsigned long *time */);
-
-#endif
diff --git a/src/w32menu.c b/src/w32menu.c
deleted file mode 100644
index a169e267e31..00000000000
--- a/src/w32menu.c
+++ /dev/null
@@ -1,1967 +0,0 @@
-/* X Communication module for terminals which understand the X protocol.
- Copyright (C) 1986, 1988, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Written by Kevin Gallo. */
-
-#include <signal.h>
-#include <config.h>
-
-#include <stdio.h>
-#include "lisp.h"
-#include "termhooks.h"
-#include "frame.h"
-#include "window.h"
-#include "keyboard.h"
-#include "blockinput.h"
-#include "buffer.h"
-
-/* This may include sys/types.h, and that somehow loses
- if this is not done before the other system files. */
-#include "w32term.h"
-
-/* Load sys/types.h if not already loaded.
- In some systems loading it twice is suicidal. */
-#ifndef makedev
-#include <sys/types.h>
-#endif
-
-#include "dispextern.h"
-
-#define min(x, y) (((x) < (y)) ? (x) : (y))
-#define max(x, y) (((x) > (y)) ? (x) : (y))
-
-typedef struct menu_map
-{
- Lisp_Object menu_items;
- int menu_items_allocated;
- int menu_items_used;
-} menu_map;
-
-Lisp_Object Qdebug_on_next_call;
-
-extern Lisp_Object Qmenu_enable;
-extern Lisp_Object Qmenu_bar;
-
-extern Lisp_Object Voverriding_local_map;
-extern Lisp_Object Voverriding_local_map_menu_flag;
-
-extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
-
-extern Lisp_Object Qmenu_bar_update_hook;
-
-static Lisp_Object w32_dialog_show ();
-static Lisp_Object w32menu_show ();
-
-static HMENU keymap_panes ();
-static HMENU single_keymap_panes ();
-static HMENU list_of_panes ();
-static HMENU list_of_items ();
-
-static HMENU create_menu_items ();
-
-/* Initialize the menu_items structure if we haven't already done so.
- Also mark it as currently empty. */
-
-static void
-init_menu_items (lpmm)
- menu_map * lpmm;
-{
- if (NILP (lpmm->menu_items))
- {
- lpmm->menu_items_allocated = 60;
- lpmm->menu_items = Fmake_vector (make_number (lpmm->menu_items_allocated),
- Qnil);
- }
-
- lpmm->menu_items_used = 0;
-}
-
-/* Call when finished using the data for the current menu
- in menu_items. */
-
-static void
-discard_menu_items (lpmm)
- menu_map * lpmm;
-{
- lpmm->menu_items = Qnil;
- lpmm->menu_items_allocated = lpmm->menu_items_used = 0;
-}
-
-/* Make the menu_items vector twice as large. */
-
-static void
-grow_menu_items (lpmm)
- menu_map * lpmm;
-{
- Lisp_Object new;
- int old_size = lpmm->menu_items_allocated;
-
- lpmm->menu_items_allocated *= 2;
- new = Fmake_vector (make_number (lpmm->menu_items_allocated), Qnil);
- bcopy (XVECTOR (lpmm->menu_items)->contents, XVECTOR (new)->contents,
- old_size * sizeof (Lisp_Object));
-
- lpmm->menu_items = new;
-}
-
-/* Indicate boundary between left and right. */
-
-static void
-add_left_right_boundary (hmenu)
- HMENU hmenu;
-{
- AppendMenu (hmenu, MF_MENUBARBREAK, 0, NULL);
-}
-
-/* Push one menu item into the current pane.
- NAME is the string to display. ENABLE if non-nil means
- this item can be selected. KEY is the key generated by
- choosing this item. EQUIV is the textual description
- of the keyboard equivalent for this item (or nil if none). */
-
-static void
-add_menu_item (lpmm, hmenu, name, enable, key)
- menu_map * lpmm;
- HMENU hmenu;
- Lisp_Object name;
- UINT enable;
- Lisp_Object key;
-{
- UINT fuFlags;
-
- if (NILP (name)
- || ((char *) XSTRING (name)->data)[0] == 0
- || strcmp ((char *) XSTRING (name)->data, "--") == 0)
- fuFlags = MF_SEPARATOR;
- else if (enable)
- fuFlags = MF_STRING;
- else
- fuFlags = MF_STRING | MF_GRAYED;
-
- AppendMenu (hmenu,
- fuFlags,
- lpmm->menu_items_used + 1,
- (fuFlags == MF_SEPARATOR)?NULL: (char *) XSTRING (name)->data);
-
- lpmm->menu_items_used++;
-#if 0
- if (lpmm->menu_items_used >= lpmm->menu_items_allocated)
- grow_menu_items (lpmm);
-
- XSET (XVECTOR (lpmm->menu_items)->contents[lpmm->menu_items_used++],
- Lisp_Cons,
- key);
-#endif
-}
-
-/* Figure out the current keyboard equivalent of a menu item ITEM1.
- The item string for menu display should be ITEM_STRING.
- Store the equivalent keyboard key sequence's
- textual description into *DESCRIP_PTR.
- Also cache them in the item itself.
- Return the real definition to execute. */
-
-static Lisp_Object
-menu_item_equiv_key (item_string, item1, descrip_ptr)
- Lisp_Object item_string;
- Lisp_Object item1;
- Lisp_Object *descrip_ptr;
-{
- /* This is the real definition--the function to run. */
- Lisp_Object def;
- /* This is the sublist that records cached equiv key data
- so we can save time. */
- Lisp_Object cachelist;
- /* These are the saved equivalent keyboard key sequence
- and its key-description. */
- Lisp_Object savedkey, descrip;
- Lisp_Object def1;
- int changed = 0;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- /* If a help string follows the item string, skip it. */
- if (CONSP (XCONS (item1)->cdr)
- && STRINGP (XCONS (XCONS (item1)->cdr)->car))
- item1 = XCONS (item1)->cdr;
-
- def = Fcdr (item1);
-
- /* Get out the saved equivalent-keyboard-key info. */
- cachelist = savedkey = descrip = Qnil;
- if (CONSP (def) && CONSP (XCONS (def)->car)
- && (NILP (XCONS (XCONS (def)->car)->car)
- || VECTORP (XCONS (XCONS (def)->car)->car)))
- {
- cachelist = XCONS (def)->car;
- def = XCONS (def)->cdr;
- savedkey = XCONS (cachelist)->car;
- descrip = XCONS (cachelist)->cdr;
- }
-
- GCPRO4 (def, def1, savedkey, descrip);
-
- /* Is it still valid? */
- def1 = Qnil;
- if (!NILP (savedkey))
- def1 = Fkey_binding (savedkey, Qnil);
- /* If not, update it. */
- if (! EQ (def1, def)
- /* If the command is an alias for another
- (such as easymenu.el and lmenu.el set it up),
- check if the original command matches the cached command. */
- && !(SYMBOLP (def) && SYMBOLP (XSYMBOL (def)->function)
- && EQ (def1, XSYMBOL (def)->function))
- /* If something had no key binding before, don't recheck it--
- doing that takes too much time and makes menus too slow. */
- && !(!NILP (cachelist) && NILP (savedkey)))
- {
- changed = 1;
- descrip = Qnil;
- savedkey = Fwhere_is_internal (def, Qnil, Qt, Qnil);
- /* If the command is an alias for another
- (such as easymenu.el and lmenu.el set it up),
- see if the original command name has equivalent keys. */
- if (SYMBOLP (def) && SYMBOLP (XSYMBOL (def)->function))
- savedkey = Fwhere_is_internal (XSYMBOL (def)->function,
- Qnil, Qt, Qnil);
-
- if (VECTORP (savedkey)
- && EQ (XVECTOR (savedkey)->contents[0], Qmenu_bar))
- savedkey = Qnil;
- if (!NILP (savedkey))
- {
- descrip = Fkey_description (savedkey);
- descrip = concat2 (make_string (" (", 3), descrip);
- descrip = concat2 (descrip, make_string (")", 1));
- }
- }
-
- /* Cache the data we just got in a sublist of the menu binding. */
- if (NILP (cachelist))
- XCONS (item1)->cdr = Fcons (Fcons (savedkey, descrip), def);
- else if (changed)
- {
- XCONS (cachelist)->car = savedkey;
- XCONS (cachelist)->cdr = descrip;
- }
-
- UNGCPRO;
- *descrip_ptr = descrip;
- return def;
-}
-
-/* This is used as the handler when calling internal_condition_case_1. */
-
-static Lisp_Object
-menu_item_enabled_p_1 (arg)
- Lisp_Object arg;
-{
- return Qnil;
-}
-
-/* Return non-nil if the command DEF is enabled when used as a menu item.
- This is based on looking for a menu-enable property.
- If NOTREAL is set, don't bother really computing this. */
-
-static Lisp_Object
-menu_item_enabled_p (def, notreal)
- Lisp_Object def;
-{
- Lisp_Object enabled, tem;
-
- enabled = Qt;
- if (notreal)
- return enabled;
- if (XTYPE (def) == Lisp_Symbol)
- {
- /* No property, or nil, means enable.
- Otherwise, enable if value is not nil. */
- tem = Fget (def, Qmenu_enable);
- if (!NILP (tem))
- /* (condition-case nil (eval tem)
- (error nil)) */
- enabled = internal_condition_case_1 (Feval, tem, Qerror,
- menu_item_enabled_p_1);
- }
- return enabled;
-}
-
-/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
- and generate menu panes for them in menu_items.
- If NOTREAL is nonzero,
- don't bother really computing whether an item is enabled. */
-
-static HMENU
-keymap_panes (lpmm, keymaps, nmaps, notreal)
- menu_map * lpmm;
- Lisp_Object *keymaps;
- int nmaps;
- int notreal;
-{
- int mapno;
-
- // init_menu_items (lpmm);
-
- if (nmaps > 1)
- {
- HMENU hmenu;
-
- if (!notreal)
- {
- hmenu = CreateMenu ();
-
- if (!hmenu) return (NULL);
- }
- else
- {
- hmenu = NULL;
- }
-
- /* Loop over the given keymaps, making a pane for each map.
- But don't make a pane that is empty--ignore that map instead.
- P is the number of panes we have made so far. */
- for (mapno = 0; mapno < nmaps; mapno++)
- {
- HMENU new_hmenu;
-
- new_hmenu = single_keymap_panes (lpmm, keymaps[mapno],
- Qnil, Qnil, notreal);
-
- if (!notreal && new_hmenu)
- {
- AppendMenu (hmenu, MF_POPUP, (UINT)new_hmenu, "");
- }
- }
-
- return (hmenu);
- }
- else
- {
- return (single_keymap_panes (lpmm, keymaps[0], Qnil, Qnil, notreal));
- }
-}
-
-/* This is a recursive subroutine of keymap_panes.
- It handles one keymap, KEYMAP.
- The other arguments are passed along
- or point to local variables of the previous function.
- If NOTREAL is nonzero,
- don't bother really computing whether an item is enabled. */
-
-HMENU
-single_keymap_panes (lpmm, keymap, pane_name, prefix, notreal)
- menu_map * lpmm;
- Lisp_Object keymap;
- Lisp_Object pane_name;
- Lisp_Object prefix;
- int notreal;
-{
- Lisp_Object pending_maps;
- Lisp_Object tail, item, item1, item_string, table;
- HMENU hmenu;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- if (!notreal)
- {
- hmenu = CreateMenu ();
- if (hmenu == NULL) return NULL;
- }
- else
- {
- hmenu = NULL;
- }
-
- pending_maps = Qnil;
-
- for (tail = keymap; XTYPE (tail) == Lisp_Cons; tail = XCONS (tail)->cdr)
- {
- /* Look at each key binding, and if it has a menu string,
- make a menu item from it. */
-
- item = XCONS (tail)->car;
-
- if (CONSP (item))
- {
- item1 = XCONS (item)->cdr;
-
- if (XTYPE (item1) == Lisp_Cons)
- {
- item_string = XCONS (item1)->car;
- if (XTYPE (item_string) == Lisp_String)
- {
- /* This is the real definition--the function to run. */
-
- Lisp_Object def;
-
- /* These are the saved equivalent keyboard key sequence
- and its key-description. */
-
- Lisp_Object descrip;
- Lisp_Object tem, enabled;
-
- /* GCPRO because ...enabled_p will call eval
- and ..._equiv_key may autoload something.
- Protecting KEYMAP preserves everything we use;
- aside from that, must protect whatever might be
- a string. Since there's no GCPRO5, we refetch
- item_string instead of protecting it. */
-
- descrip = def = Qnil;
- GCPRO4 (keymap, pending_maps, def, prefix);
-
- def = menu_item_equiv_key (item_string, item1, &descrip);
- enabled = menu_item_enabled_p (def, notreal);
-
- UNGCPRO;
-
- item_string = XCONS (item1)->car;
-
- tem = Fkeymapp (def);
- if (XSTRING (item_string)->data[0] == '@' && !NILP (tem))
- {
- pending_maps = Fcons (Fcons (def,
- Fcons (item_string,
- XCONS (item)->car)),
- pending_maps);
- }
- else
- {
- Lisp_Object submap;
-
- GCPRO4 (keymap, pending_maps, item, item_string);
-
- submap = get_keymap_1 (def, 0, 1);
-
- UNGCPRO;
-
- if (NILP (submap))
- {
- if (!notreal)
- {
- add_menu_item (lpmm,
- hmenu,
- item_string,
- !NILP (enabled),
- Fcons (XCONS (item)->car, prefix));
- }
- }
- else
- /* Display a submenu. */
- {
- HMENU new_hmenu = single_keymap_panes (lpmm,
- submap,
- item_string,
- XCONS (item)->car,
- notreal);
-
- if (!notreal)
- {
- AppendMenu (hmenu, MF_POPUP,
- (UINT)new_hmenu,
- (char *) XSTRING (item_string)->data);
- }
- }
- }
- }
- }
- }
- else if (VECTORP (item))
- {
- /* Loop over the char values represented in the vector. */
- int len = XVECTOR (item)->size;
- int c;
- for (c = 0; c < len; c++)
- {
- Lisp_Object character;
- XSETFASTINT (character, c);
- item1 = XVECTOR (item)->contents[c];
- if (CONSP (item1))
- {
- item_string = XCONS (item1)->car;
- if (STRINGP (item_string))
- {
- Lisp_Object def;
-
- /* These are the saved equivalent keyboard key sequence
- and its key-description. */
- Lisp_Object descrip;
- Lisp_Object tem, enabled;
-
- /* GCPRO because ...enabled_p will call eval
- and ..._equiv_key may autoload something.
- Protecting KEYMAP preserves everything we use;
- aside from that, must protect whatever might be
- a string. Since there's no GCPRO5, we refetch
- item_string instead of protecting it. */
- GCPRO4 (keymap, pending_maps, def, descrip);
- descrip = def = Qnil;
-
- def = menu_item_equiv_key (item_string, item1, &descrip);
- enabled = menu_item_enabled_p (def, notreal);
-
- UNGCPRO;
-
- item_string = XCONS (item1)->car;
-
- tem = Fkeymapp (def);
- if (XSTRING (item_string)->data[0] == '@' && !NILP (tem))
- pending_maps = Fcons (Fcons (def, Fcons (item_string, character)),
- pending_maps);
- else
- {
- Lisp_Object submap;
-
- GCPRO4 (keymap, pending_maps, descrip, item_string);
-
- submap = get_keymap_1 (def, 0, 1);
-
- UNGCPRO;
-
- if (NILP (submap))
- {
- if (!notreal)
- {
- add_menu_item (lpmm,
- hmenu,
- item_string,
- !NILP (enabled),
- character);
- }
- }
- else
- /* Display a submenu. */
- {
- HMENU new_hmenu = single_keymap_panes (lpmm,
- submap,
- Qnil,
- character,
- notreal);
-
- if (!notreal)
- {
- AppendMenu (hmenu,MF_POPUP,
- (UINT)new_hmenu,
- (char *)XSTRING (item_string)->data);
- }
- }
- }
- }
- }
- }
- }
- }
-
- /* Process now any submenus which want to be panes at this level. */
- while (!NILP (pending_maps))
- {
- Lisp_Object elt, eltcdr, string;
- elt = Fcar (pending_maps);
- eltcdr = XCONS (elt)->cdr;
- string = XCONS (eltcdr)->car;
- /* We no longer discard the @ from the beginning of the string here.
- Instead, we do this in w32menu_show. */
- {
- HMENU new_hmenu = single_keymap_panes (lpmm,
- Fcar (elt),
- string,
- XCONS (eltcdr)->cdr, notreal);
-
- if (!notreal)
- {
- AppendMenu (hmenu, MF_POPUP,
- (UINT)new_hmenu,
- (char *) XSTRING (string)->data);
- }
- }
-
- pending_maps = Fcdr (pending_maps);
- }
-
- return (hmenu);
-}
-
-/* Push all the panes and items of a menu described by the
- alist-of-alists MENU.
- This handles old-fashioned calls to x-popup-menu. */
-
-static HMENU
-list_of_panes (lpmm, menu)
- menu_map * lpmm;
- Lisp_Object menu;
-{
- Lisp_Object tail;
- HMENU hmenu;
-
- hmenu = CreateMenu ();
- if (hmenu == NULL) return NULL;
-
- // init_menu_items (lpmm);
-
- for (tail = menu; !NILP (tail); tail = Fcdr (tail))
- {
- Lisp_Object elt, pane_name, pane_data;
- HMENU new_hmenu;
-
- elt = Fcar (tail);
- pane_name = Fcar (elt);
- CHECK_STRING (pane_name, 0);
- pane_data = Fcdr (elt);
- CHECK_CONS (pane_data, 0);
-
- new_hmenu = list_of_items (lpmm, pane_data);
- if (new_hmenu == NULL) goto error;
-
- AppendMenu (hmenu, MF_POPUP, (UINT)new_hmenu,
- (char *) XSTRING (pane_name)->data);
- }
-
- return (hmenu);
-
- error:
- DestroyMenu (hmenu);
-
- return (NULL);
-}
-
-/* Push the items in a single pane defined by the alist PANE. */
-
-static HMENU
-list_of_items (lpmm, pane)
- menu_map * lpmm;
- Lisp_Object pane;
-{
- Lisp_Object tail, item, item1;
- HMENU hmenu;
-
- hmenu = CreateMenu ();
- if (hmenu == NULL) return NULL;
-
- for (tail = pane; !NILP (tail); tail = Fcdr (tail))
- {
- item = Fcar (tail);
- if (STRINGP (item))
- add_menu_item (lpmm, hmenu, item, Qnil, Qnil);
- else if (NILP (item))
- add_left_right_boundary ();
- else
- {
- CHECK_CONS (item, 0);
- item1 = Fcar (item);
- CHECK_STRING (item1, 1);
- add_menu_item (lpmm, hmenu, item1, Qt, Fcdr (item));
- }
- }
-
- return (hmenu);
-}
-
-
-HMENU
-create_menu_items (lpmm, menu, notreal)
- menu_map * lpmm;
- Lisp_Object menu;
- int notreal;
-{
- Lisp_Object title;
- Lisp_Object keymap, tem;
- HMENU hmenu;
-
- title = Qnil;
-
- /* Decode the menu items from what was specified. */
-
- keymap = Fkeymapp (menu);
- tem = Qnil;
- if (XTYPE (menu) == Lisp_Cons)
- tem = Fkeymapp (Fcar (menu));
-
- if (!NILP (keymap))
- {
- /* We were given a keymap. Extract menu info from the keymap. */
- Lisp_Object prompt;
- keymap = get_keymap (menu);
-
- /* Extract the detailed info to make one pane. */
- hmenu = keymap_panes (lpmm, &keymap, 1, notreal);
-
-#if 0
- /* Search for a string appearing directly as an element of the keymap.
- That string is the title of the menu. */
- prompt = map_prompt (keymap);
-
- /* Make that be the pane title of the first pane. */
- if (!NILP (prompt) && menu_items_n_panes >= 0)
- XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = prompt;
-#endif
- }
- else if (!NILP (tem))
- {
- /* We were given a list of keymaps. */
- int nmaps = XFASTINT (Flength (menu));
- Lisp_Object *maps
- = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
- int i;
-
- title = Qnil;
-
- /* The first keymap that has a prompt string
- supplies the menu title. */
- for (tem = menu, i = 0; XTYPE (tem) == Lisp_Cons; tem = Fcdr (tem))
- {
- Lisp_Object prompt;
-
- maps[i++] = keymap = get_keymap (Fcar (tem));
-#if 0
- prompt = map_prompt (keymap);
- if (NILP (title) && !NILP (prompt))
- title = prompt;
-#endif
- }
-
- /* Extract the detailed info to make one pane. */
- hmenu = keymap_panes (lpmm, maps, nmaps, notreal);
-
-#if 0
- /* Make the title be the pane title of the first pane. */
- if (!NILP (title) && menu_items_n_panes >= 0)
- XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title;
-#endif
- }
- else
- {
- /* We were given an old-fashioned menu. */
- title = Fcar (menu);
- CHECK_STRING (title, 1);
-
- hmenu = list_of_panes (lpmm, Fcdr (menu));
- }
-
- return (hmenu);
-}
-
-/* This is a recursive subroutine of keymap_panes.
- It handles one keymap, KEYMAP.
- The other arguments are passed along
- or point to local variables of the previous function.
- If NOTREAL is nonzero,
- don't bother really computing whether an item is enabled. */
-
-Lisp_Object
-get_single_keymap_event (keymap, lpnum)
- Lisp_Object keymap;
- int * lpnum;
-{
- Lisp_Object pending_maps;
- Lisp_Object tail, item, item1, item_string, table;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- pending_maps = Qnil;
-
- for (tail = keymap; XTYPE (tail) == Lisp_Cons; tail = XCONS (tail)->cdr)
- {
- /* Look at each key binding, and if it has a menu string,
- make a menu item from it. */
-
- item = XCONS (tail)->car;
-
- if (XTYPE (item) == Lisp_Cons)
- {
- item1 = XCONS (item)->cdr;
-
- if (CONSP (item1))
- {
- item_string = XCONS (item1)->car;
- if (XTYPE (item_string) == Lisp_String)
- {
- /* This is the real definition--the function to run. */
-
- Lisp_Object def;
-
- /* These are the saved equivalent keyboard key sequence
- and its key-description. */
-
- Lisp_Object descrip;
- Lisp_Object tem, enabled;
-
- /* GCPRO because ...enabled_p will call eval
- and ..._equiv_key may autoload something.
- Protecting KEYMAP preserves everything we use;
- aside from that, must protect whatever might be
- a string. Since there's no GCPRO5, we refetch
- item_string instead of protecting it. */
-
- descrip = def = Qnil;
- GCPRO3 (keymap, pending_maps, def);
-
- def = menu_item_equiv_key (item_string, item1, &descrip);
-
- UNGCPRO;
-
- item_string = XCONS (item1)->car;
-
- tem = Fkeymapp (def);
- if (XSTRING (item_string)->data[0] == '@' && !NILP (tem))
- {
- pending_maps = Fcons (Fcons (def,
- Fcons (item_string,
- XCONS (item)->car)),
- pending_maps);
- }
- else
- {
- Lisp_Object submap;
-
- GCPRO4 (keymap, pending_maps, item, item_string);
-
- submap = get_keymap_1 (def, 0, 1);
-
- UNGCPRO;
-
- if (NILP (submap))
- {
- if (--(*lpnum) == 0)
- {
- return (Fcons (XCONS (item)->car, Qnil));
- }
- }
- else
- /* Display a submenu. */
- {
- Lisp_Object event = get_single_keymap_event (submap,
- lpnum);
-
- if (*lpnum <= 0)
- {
- if (!NILP (XCONS (item)->car))
- event = Fcons (XCONS (item)->car, event);
-
- return (event);
- }
- }
- }
- }
- }
- }
- else if (VECTORP (item))
- {
- /* Loop over the char values represented in the vector. */
- int len = XVECTOR (item)->size;
- int c;
- for (c = 0; c < len; c++)
- {
- Lisp_Object character;
- XSETFASTINT (character, c);
- item1 = XVECTOR (item)->contents[c];
- if (XTYPE (item1) == Lisp_Cons)
- {
- item_string = XCONS (item1)->car;
- if (XTYPE (item_string) == Lisp_String)
- {
- Lisp_Object def;
-
- /* These are the saved equivalent keyboard key sequence
- and its key-description. */
- Lisp_Object descrip;
- Lisp_Object tem, enabled;
-
- /* GCPRO because ...enabled_p will call eval
- and ..._equiv_key may autoload something.
- Protecting KEYMAP preserves everything we use;
- aside from that, must protect whatever might be
- a string. Since there's no GCPRO5, we refetch
- item_string instead of protecting it. */
- GCPRO4 (keymap, pending_maps, def, descrip);
- descrip = def = Qnil;
-
- def = menu_item_equiv_key (item_string, item1, &descrip);
-
- UNGCPRO;
-
- item_string = XCONS (item1)->car;
-
- tem = Fkeymapp (def);
- if (XSTRING (item_string)->data[0] == '@' && !NILP (tem))
- pending_maps = Fcons (Fcons (def, Fcons (item_string, character)),
- pending_maps);
- else
- {
- Lisp_Object submap;
-
- GCPRO4 (keymap, pending_maps, descrip, item_string);
-
- submap = get_keymap_1 (def, 0, 1);
-
- UNGCPRO;
-
- if (NILP (submap))
- {
- if (--(*lpnum) == 0)
- {
- return (Fcons (character, Qnil));
- }
- }
- else
- /* Display a submenu. */
- {
- Lisp_Object event = get_single_keymap_event (submap,
- lpnum);
-
- if (*lpnum <= 0)
- {
- if (!NILP (character))
- event = Fcons (character, event);
-
- return (event);
- }
- }
- }
- }
- }
- }
- }
- }
-
- /* Process now any submenus which want to be panes at this level. */
- while (!NILP (pending_maps))
- {
- Lisp_Object elt, eltcdr, string;
- elt = Fcar (pending_maps);
- eltcdr = XCONS (elt)->cdr;
- string = XCONS (eltcdr)->car;
- /* We no longer discard the @ from the beginning of the string here.
- Instead, we do this in w32menu_show. */
- {
- Lisp_Object event = get_single_keymap_event (Fcar (elt), lpnum);
-
- if (*lpnum <= 0)
- {
- if (!NILP (XCONS (eltcdr)->cdr))
- event = Fcons (XCONS (eltcdr)->cdr, event);
-
- return (event);
- }
- }
-
- pending_maps = Fcdr (pending_maps);
- }
-
- return (Qnil);
-}
-
-/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
- and generate menu panes for them in menu_items.
- If NOTREAL is nonzero,
- don't bother really computing whether an item is enabled. */
-
-static Lisp_Object
-get_keymap_event (keymaps, nmaps, lpnum)
- Lisp_Object *keymaps;
- int nmaps;
- int * lpnum;
-{
- int mapno;
- Lisp_Object event = Qnil;
-
- /* Loop over the given keymaps, making a pane for each map.
- But don't make a pane that is empty--ignore that map instead.
- P is the number of panes we have made so far. */
- for (mapno = 0; mapno < nmaps; mapno++)
- {
- event = get_single_keymap_event (keymaps[mapno], lpnum);
-
- if (*lpnum <= 0) break;
- }
-
- return (event);
-}
-
-static Lisp_Object
-get_list_of_items_event (pane, lpnum)
- Lisp_Object pane;
- int * lpnum;
-{
- Lisp_Object tail, item, item1;
-
- for (tail = pane; !NILP (tail); tail = Fcdr (tail))
- {
- item = Fcar (tail);
- if (STRINGP (item))
- {
- if (-- (*lpnum) == 0)
- {
- return (Qnil);
- }
- }
- else if (!NILP (item))
- {
- if (--(*lpnum) == 0)
- {
- CHECK_CONS (item, 0);
- return (Fcdr (item));
- }
- }
- }
-
- return (Qnil);
-}
-
-/* Push all the panes and items of a menu described by the
- alist-of-alists MENU.
- This handles old-fashioned calls to x-popup-menu. */
-
-static Lisp_Object
-get_list_of_panes_event (menu, lpnum)
- Lisp_Object menu;
- int * lpnum;
-{
- Lisp_Object tail;
-
- for (tail = menu; !NILP (tail); tail = Fcdr (tail))
- {
- Lisp_Object elt, pane_name, pane_data;
- Lisp_Object event;
-
- elt = Fcar (tail);
- pane_data = Fcdr (elt);
- CHECK_CONS (pane_data, 0);
-
- event = get_list_of_items_event (pane_data, lpnum);
-
- if (*lpnum <= 0)
- {
- return (event);
- }
- }
-
- return (Qnil);
-}
-
-Lisp_Object
-get_menu_event (menu, lpnum)
- Lisp_Object menu;
- int * lpnum;
-{
- Lisp_Object keymap, tem;
- Lisp_Object event;
-
- /* Decode the menu items from what was specified. */
-
- keymap = Fkeymapp (menu);
- tem = Qnil;
- if (XTYPE (menu) == Lisp_Cons)
- tem = Fkeymapp (Fcar (menu));
-
- if (!NILP (keymap))
- {
- keymap = get_keymap (menu);
-
- event = get_keymap_event (menu, 1, lpnum);
- }
- else if (!NILP (tem))
- {
- /* We were given a list of keymaps. */
- int nmaps = XFASTINT (Flength (menu));
- Lisp_Object *maps
- = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
- int i;
-
- /* The first keymap that has a prompt string
- supplies the menu title. */
- for (tem = menu, i = 0; XTYPE (tem) == Lisp_Cons; tem = Fcdr (tem))
- {
- Lisp_Object prompt;
-
- maps[i++] = keymap = get_keymap (Fcar (tem));
- }
-
- event = get_keymap_event (maps, nmaps, lpnum);
- }
- else
- {
- /* We were given an old-fashioned menu. */
- event = get_list_of_panes_event (Fcdr (menu), lpnum);
- }
-
- return (event);
-}
-
-DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
- "Pop up a deck-of-cards menu and return user's selection.\n\
-POSITION is a position specification. This is either a mouse button event\n\
-or a list ((XOFFSET YOFFSET) WINDOW)\n\
-where XOFFSET and YOFFSET are positions in pixels from the top left\n\
-corner of WINDOW's frame. (WINDOW may be a frame object instead of a window.)\n\
-This controls the position of the center of the first line\n\
-in the first pane of the menu, not the top left of the menu as a whole.\n\
-If POSITION is t, it means to use the current mouse position.\n\
-\n\
-MENU is a specifier for a menu. For the simplest case, MENU is a keymap.\n\
-The menu items come from key bindings that have a menu string as well as\n\
-a definition; actually, the \"definition\" in such a key binding looks like\n\
-\(STRING . REAL-DEFINITION). To give the menu a title, put a string into\n\
-the keymap as a top-level element.\n\n\
-You can also use a list of keymaps as MENU.\n\
- Then each keymap makes a separate pane.\n\
-When MENU is a keymap or a list of keymaps, the return value\n\
-is a list of events.\n\n\
-Alternatively, you can specify a menu of multiple panes\n\
- with a list of the form (TITLE PANE1 PANE2...),\n\
-where each pane is a list of form (TITLE ITEM1 ITEM2...).\n\
-Each ITEM is normally a cons cell (STRING . VALUE);\n\
-but a string can appear as an item--that makes a nonselectable line\n\
-in the menu.\n\
-With this form of menu, the return value is VALUE from the chosen item.\n\
-\n\
-If POSITION is nil, don't display the menu at all, just precalculate the\n\
-cached information about equivalent key sequences.")
- (position, menu)
- Lisp_Object position, menu;
-{
- int number_of_panes, panes;
- Lisp_Object keymap, tem;
- int xpos, ypos;
- Lisp_Object title;
- char *error_name;
- Lisp_Object selection;
- int i, j;
- FRAME_PTR f;
- Lisp_Object x, y, window;
- int keymaps = 0;
- int menubarp = 0;
- struct gcpro gcpro1;
- HMENU hmenu;
- menu_map mm;
-
- if (! NILP (position))
- {
- /* Decode the first argument: find the window and the coordinates. */
- if (EQ (position, Qt))
- {
- /* Use the mouse's current position. */
- FRAME_PTR new_f = 0;
- Lisp_Object bar_window;
- int part;
- unsigned long time;
-
- if (mouse_position_hook)
- (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time);
- if (new_f != 0)
- XSETFRAME (window, new_f);
- else
- {
- window = selected_window;
- XSETFASTINT (x, 0);
- XSETFASTINT (y, 0);
- }
- }
- else
- {
- tem = Fcar (position);
- if (CONSP (tem))
- {
- window = Fcar (Fcdr (position));
- x = Fcar (tem);
- y = Fcar (Fcdr (tem));
- }
- else
- {
- tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
- window = Fcar (tem); /* POSN_WINDOW (tem) */
- tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
- x = Fcar (tem);
- y = Fcdr (tem);
-
- /* Determine whether this menu is handling a menu bar click. */
- tem = Fcar (Fcdr (Fcar (Fcdr (position))));
- if (CONSP (tem) && EQ (Fcar (tem), Qmenu_bar))
- menubarp = 1;
- }
- }
-
- CHECK_NUMBER (x, 0);
- CHECK_NUMBER (y, 0);
-
- /* Decode where to put the menu. */
-
- if (FRAMEP (window))
- {
- f = XFRAME (window);
-
- xpos = 0;
- ypos = 0;
- }
- else if (WINDOWP (window))
- {
- CHECK_LIVE_WINDOW (window, 0);
- f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
-
- xpos = (FONT_WIDTH (f->output_data.w32->font) * XWINDOW (window)->left);
- ypos = (f->output_data.w32->line_height * XWINDOW (window)->top);
- }
- else
- /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
- but I don't want to make one now. */
- CHECK_WINDOW (window, 0);
-
- xpos += XINT (x);
- ypos += XINT (y);
- }
-
- title = Qnil;
- GCPRO1 (title);
-
- discard_menu_items (&mm);
- hmenu = create_menu_items (&mm, menu, NILP (position));
-
- if (NILP (position))
- {
- discard_menu_items (&mm);
- UNGCPRO;
- return Qnil;
- }
-
- /* Display them in a menu. */
- BLOCK_INPUT;
-
- selection = w32menu_show (f, xpos, ypos, menu, &hmenu, &error_name);
-
- UNBLOCK_INPUT;
-
- discard_menu_items (&mm);
- DestroyMenu (hmenu);
-
- UNGCPRO;
-
- if (error_name) error (error_name);
- return selection;
-}
-
-DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 2, 0,
- "Pop up a dialog box and return user's selection.\n\
-POSITION specifies which frame to use.\n\
-This is normally a mouse button event or a window or frame.\n\
-If POSITION is t, it means to use the frame the mouse is on.\n\
-The dialog box appears in the middle of the specified frame.\n\
-\n\
-CONTENTS specifies the alternatives to display in the dialog box.\n\
-It is a list of the form (TITLE ITEM1 ITEM2...).\n\
-Each ITEM is a cons cell (STRING . VALUE).\n\
-The return value is VALUE from the chosen item.\n\n\
-An ITEM may also be just a string--that makes a nonselectable item.\n\
-An ITEM may also be nil--that means to put all preceding items\n\
-on the left of the dialog box and all following items on the right.\n\
-\(By default, approximately half appear on each side.)")
- (position, contents)
- Lisp_Object position, contents;
-{
- FRAME_PTR f;
- Lisp_Object window;
-
- /* Decode the first argument: find the window or frame to use. */
- if (EQ (position, Qt))
- {
- /* Decode the first argument: find the window and the coordinates. */
- if (EQ (position, Qt))
- window = selected_window;
- }
- else if (CONSP (position))
- {
- Lisp_Object tem;
- tem = Fcar (position);
- if (XTYPE (tem) == Lisp_Cons)
- window = Fcar (Fcdr (position));
- else
- {
- tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
- window = Fcar (tem); /* POSN_WINDOW (tem) */
- }
- }
- else if (WINDOWP (position) || FRAMEP (position))
- window = position;
-
- /* Decode where to put the menu. */
-
- if (FRAMEP (window))
- f = XFRAME (window);
- else if (WINDOWP (window))
- {
- CHECK_LIVE_WINDOW (window, 0);
- f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
- }
- else
- /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
- but I don't want to make one now. */
- CHECK_WINDOW (window, 0);
-
-#if 1
- /* Display a menu with these alternatives
- in the middle of frame F. */
- {
- Lisp_Object x, y, frame, newpos;
- XSETFRAME (frame, f);
- XSETINT (x, x_pixel_width (f) / 2);
- XSETINT (y, x_pixel_height (f) / 2);
- newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
-
- return Fx_popup_menu (newpos,
- Fcons (Fcar (contents), Fcons (contents, Qnil)));
- }
-#else
- {
- Lisp_Object title;
- char *error_name;
- Lisp_Object selection;
-
- /* Decode the dialog items from what was specified. */
- title = Fcar (contents);
- CHECK_STRING (title, 1);
-
- list_of_panes (Fcons (contents, Qnil));
-
- /* Display them in a dialog box. */
- BLOCK_INPUT;
- selection = w32_dialog_show (f, 0, 0, title, &error_name);
- UNBLOCK_INPUT;
-
- discard_menu_items ();
-
- if (error_name) error (error_name);
- return selection;
- }
-#endif
-}
-
-Lisp_Object
-get_frame_menubar_event (f, num)
- FRAME_PTR f;
- int num;
-{
- Lisp_Object tail, items;
- int i;
- struct gcpro gcpro1;
-
- BLOCK_INPUT;
-
- GCPRO1 (items);
-
- if (NILP (items = FRAME_MENU_BAR_ITEMS (f)))
- items = FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
-
- for (i = 0; i < XVECTOR (items)->size; i += 4)
- {
- Lisp_Object event;
-
- event = get_menu_event (XVECTOR (items)->contents[i + 2], &num);
-
- if (num <= 0)
- {
- UNGCPRO;
- UNBLOCK_INPUT;
- return (Fcons (XVECTOR (items)->contents[i], event));
- }
- }
-
- UNGCPRO;
- UNBLOCK_INPUT;
-
- return (Qnil);
-}
-
-void
-set_frame_menubar (f, first_time)
- FRAME_PTR f;
- int first_time;
-{
- Lisp_Object tail, items;
- HMENU hmenu;
- int i;
- struct gcpro gcpro1;
- menu_map mm;
- int count = specpdl_ptr - specpdl;
-
- struct buffer *prev = current_buffer;
- Lisp_Object buffer;
-
- buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
- specbind (Qinhibit_quit, Qt);
- /* Don't let the debugger step into this code
- because it is not reentrant. */
- specbind (Qdebug_on_next_call, Qnil);
-
- record_unwind_protect (Fstore_match_data, Fmatch_data (Qnil, Qnil));
- if (NILP (Voverriding_local_map_menu_flag))
- {
- specbind (Qoverriding_terminal_local_map, Qnil);
- specbind (Qoverriding_local_map, Qnil);
- }
-
- set_buffer_internal_1 (XBUFFER (buffer));
-
- /* Run the Lucid hook. */
- call1 (Vrun_hooks, Qactivate_menubar_hook);
- /* If it has changed current-menubar from previous value,
- really recompute the menubar from the value. */
- if (! NILP (Vlucid_menu_bar_dirty_flag))
- call0 (Qrecompute_lucid_menubar);
- safe_run_hooks (Qmenu_bar_update_hook);
-
- BLOCK_INPUT;
-
- GCPRO1 (items);
-
- items = FRAME_MENU_BAR_ITEMS (f);
- if (NILP (items))
- items = FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
-
- hmenu = CreateMenu ();
-
- if (!hmenu) goto error;
-
- discard_menu_items (&mm);
- UNBLOCK_INPUT;
-
- for (i = 0; i < XVECTOR (items)->size; i += 4)
- {
- Lisp_Object string;
- int keymaps;
- CHAR *error;
- HMENU new_hmenu;
-
- string = XVECTOR (items)->contents[i + 1];
- if (NILP (string))
- break;
-
- /* Input must not be blocked here
- because we call general Lisp code and internal_condition_case_1. */
- new_hmenu = create_menu_items (&mm,
- XVECTOR (items)->contents[i + 2],
- 0);
-
- if (!new_hmenu)
- continue;
-
- BLOCK_INPUT;
- AppendMenu (hmenu, MF_POPUP, (UINT)new_hmenu,
- (char *) XSTRING (string)->data);
- UNBLOCK_INPUT;
- }
-
- BLOCK_INPUT;
- {
- HMENU old = GetMenu (FRAME_W32_WINDOW (f));
- SetMenu (FRAME_W32_WINDOW (f), hmenu);
- DestroyMenu (old);
- }
-
- error:
- set_buffer_internal_1 (prev);
- UNGCPRO;
- UNBLOCK_INPUT;
- unbind_to (count, Qnil);
-}
-
-void
-free_frame_menubar (f)
- FRAME_PTR f;
-{
- BLOCK_INPUT;
-
- {
- HMENU old = GetMenu (FRAME_W32_WINDOW (f));
- SetMenu (FRAME_W32_WINDOW (f), NULL);
- DestroyMenu (old);
- }
-
- UNBLOCK_INPUT;
-}
-/* Called from Fw32_create_frame to create the initial menubar of a frame
- before it is mapped, so that the window is mapped with the menubar already
- there instead of us tacking it on later and thrashing the window after it
- is visible. */
-void
-initialize_frame_menubar (f)
- FRAME_PTR f;
-{
- set_frame_menubar (f, 1);
-}
-
-#if 0
-/* If the mouse has moved to another menu bar item,
- return 1 and unread a button press event for that item.
- Otherwise return 0. */
-
-static int
-check_mouse_other_menu_bar (f)
- FRAME_PTR f;
-{
- FRAME_PTR new_f;
- Lisp_Object bar_window;
- int part;
- Lisp_Object x, y;
- unsigned long time;
-
- (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time);
-
- if (f == new_f && other_menu_bar_item_p (f, x, y))
- {
- unread_menu_bar_button (f, x);
- return 1;
- }
-
- return 0;
-}
-#endif
-
-
-#if 0
-static HMENU
-create_menu (keymaps, error)
- int keymaps;
- char **error;
-{
- HMENU hmenu = NULL; /* the menu we are currently working on */
- HMENU first_hmenu = NULL;
-
- HMENU *submenu_stack = (HMENU *) alloca (menu_items_used * sizeof (HMENU));
- Lisp_Object *subprefix_stack = (Lisp_Object *) alloca (menu_items_used *
- sizeof (Lisp_Object));
- int submenu_depth = 0;
- int i;
-
- if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
- {
- *error = "Empty menu";
- return NULL;
- }
-
- i = 0;
-
- /* Loop over all panes and items, filling in the tree. */
-
- while (i < menu_items_used)
- {
- if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
- {
- submenu_stack[submenu_depth++] = hmenu;
- i++;
- }
- else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
- {
- hmenu = submenu_stack[--submenu_depth];
- i++;
- }
-#if 0
-else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
- && submenu_depth != 0)
- i += MENU_ITEMS_PANE_LENGTH;
-#endif
- /* Ignore a nil in the item list.
- It's meaningful only for dialog boxes. */
-else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
- i += 1;
-else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
- {
- /* Create a new pane. */
-
- Lisp_Object pane_name;
- char *pane_string;
-
- pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
- pane_string = (NILP (pane_name) ? "" : (char *) XSTRING (pane_name)->data);
-
- if (!hmenu || strcmp (pane_string, ""))
- {
- HMENU new_hmenu = CreateMenu ();
-
- if (!new_hmenu)
- {
- *error = "Could not create menu pane";
- goto error;
- }
-
- if (hmenu)
- {
- AppendMenu (hmenu, MF_POPUP, (UINT)new_hmenu, pane_string);
- }
-
- hmenu = new_hmenu;
-
- if (!first_hmenu) first_hmenu = hmenu;
- }
- i += MENU_ITEMS_PANE_LENGTH;
- }
-else
- {
- /* Create a new item within current pane. */
-
- Lisp_Object item_name, enable, descrip;
- UINT fuFlags;
-
- item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
- enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
- // descrip = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
-
- if (((char *) XSTRING (item_name)->data)[0] == 0
- || strcmp ((char *) XSTRING (item_name)->data, "--") == 0)
- fuFlags = MF_SEPARATOR;
- else if (NILP (enable) || !XUINT(enable))
- fuFlags = MF_STRING | MF_GRAYED;
- else
- fuFlags = MF_STRING;
-
- AppendMenu (hmenu,
- fuFlags,
- i,
- (char *) XSTRING (item_name)->data);
-
- // if (!NILP (descrip))
- // hmenu->key = (char *) XSTRING (descrip)->data;
-
- i += MENU_ITEMS_ITEM_LENGTH;
- }
-}
-
- return (first_hmenu);
-
- error:
- if (first_hmenu) DestroyMenu (first_hmenu);
- return (NULL);
-}
-
-#endif
-
-/* w32menu_show actually displays a menu using the panes and items in
- menu_items and returns the value selected from it.
- There are two versions of w32menu_show, one for Xt and one for Xlib.
- Both assume input is blocked by the caller. */
-
-/* F is the frame the menu is for.
- X and Y are the frame-relative specified position,
- relative to the inside upper left corner of the frame F.
- MENUBARP is 1 if the click that asked for this menu came from the menu bar.
- KEYMAPS is 1 if this menu was specified with keymaps;
- in that case, we return a list containing the chosen item's value
- and perhaps also the pane's prefix.
- TITLE is the specified menu title.
- ERROR is a place to store an error message string in case of failure.
- (We return nil on failure, but the value doesn't actually matter.) */
-
-
-static Lisp_Object
-w32menu_show (f, x, y, menu, hmenu, error)
- FRAME_PTR f;
- int x;
- int y;
- Lisp_Object menu;
- HMENU hmenu;
- char **error;
-{
- int i , menu_selection;
- POINT pos;
-
- *error = NULL;
-
- if (!hmenu)
- {
- *error = "Empty menu";
- return Qnil;
- }
-
- pos.x = x;
- pos.y = y;
-
- /* Offset the coordinates to root-relative. */
- ClientToScreen (FRAME_W32_WINDOW (f), &pos);
-
-#if 0
- /* If the mouse moves out of the menu before we show the menu,
- don't show it at all. */
- if (check_mouse_other_menu_bar (f))
- {
- DestroyMenu (hmenu);
- return Qnil;
- }
-#endif
-
- /* Display the menu. */
- menu_selection = TrackPopupMenu (hmenu,
- 0x10,
- pos.x, pos.y,
- 0,
- FRAME_W32_WINDOW (f),
- NULL);
- if (menu_selection == -1)
- {
- *error = "Invalid menu specification";
- return Qnil;
- }
-
- /* Find the selected item, and its pane, to return
- the proper value. */
-
-#if 1
- if (menu_selection > 0)
- {
- return get_menu_event (menu, menu_selection);
- }
-#else
- if (menu_selection > 0 && menu_selection <= lpmm->menu_items_used)
- {
- return (XVECTOR (lpmm->menu_items)->contents[menu_selection - 1]);
- }
-#endif
-
- return Qnil;
-}
-
-#if 0
-static char * button_names [] =
-{
- "button1", "button2", "button3", "button4", "button5",
- "button6", "button7", "button8", "button9", "button10"
-};
-
-static Lisp_Object
-w32_dialog_show (f, menubarp, keymaps, title, error)
- FRAME_PTR f;
- int menubarp;
- int keymaps;
- Lisp_Object title;
- char **error;
-{
- int i, nb_buttons=0;
- HMENU hmenu;
- char dialog_name[6];
-
- /* Number of elements seen so far, before boundary. */
- int left_count = 0;
- /* 1 means we've seen the boundary between left-hand elts and right-hand. */
- int boundary_seen = 0;
-
- *error = NULL;
-
- if (menu_items_n_panes > 1)
- {
- *error = "Multiple panes in dialog box";
- return Qnil;
- }
-
- /* Create a tree of widget_value objects
- representing the text label and buttons. */
- {
- Lisp_Object pane_name, prefix;
- char *pane_string;
- pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
- prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
- pane_string = (NILP (pane_name)
- ? "" : (char *) XSTRING (pane_name)->data);
- prev_wv = malloc_widget_value ();
- prev_wv->value = pane_string;
- if (keymaps && !NILP (prefix))
- prev_wv->name++;
- prev_wv->enabled = 1;
- prev_wv->name = "message";
- first_wv = prev_wv;
-
- /* Loop over all panes and items, filling in the tree. */
- i = MENU_ITEMS_PANE_LENGTH;
- while (i < menu_items_used)
- {
-
- /* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip;
- item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
- enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
- descrip
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
-
- if (NILP (item_name))
- {
- free_menubar_widget_value_tree (first_wv);
- *error = "Submenu in dialog items";
- return Qnil;
- }
- if (EQ (item_name, Qquote))
- {
- /* This is the boundary between left-side elts
- and right-side elts. Stop incrementing right_count. */
- boundary_seen = 1;
- i++;
- continue;
- }
- if (nb_buttons >= 10)
- {
- free_menubar_widget_value_tree (first_wv);
- *error = "Too many dialog items";
- return Qnil;
- }
-
- wv = malloc_widget_value ();
- prev_wv->next = wv;
- wv->name = (char *) button_names[nb_buttons];
- if (!NILP (descrip))
- wv->key = (char *) XSTRING (descrip)->data;
- wv->value = (char *) XSTRING (item_name)->data;
- wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
- wv->enabled = !NILP (enable);
- prev_wv = wv;
-
- if (! boundary_seen)
- left_count++;
-
- nb_buttons++;
- i += MENU_ITEMS_ITEM_LENGTH;
- }
-
- /* If the boundary was not specified,
- by default put half on the left and half on the right. */
- if (! boundary_seen)
- left_count = nb_buttons - nb_buttons / 2;
-
- wv = malloc_widget_value ();
- wv->name = dialog_name;
-
- /* Dialog boxes use a really stupid name encoding
- which specifies how many buttons to use
- and how many buttons are on the right.
- The Q means something also. */
- dialog_name[0] = 'Q';
- dialog_name[1] = '0' + nb_buttons;
- dialog_name[2] = 'B';
- dialog_name[3] = 'R';
- /* Number of buttons to put on the right. */
- dialog_name[4] = '0' + nb_buttons - left_count;
- dialog_name[5] = 0;
- wv->contents = first_wv;
- first_wv = wv;
- }
-
- /* Actually create the dialog. */
- dialog_id = ++popup_id_tick;
- menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
- f->output_data.w32->widget, 1, 0,
- dialog_selection_callback, 0);
-#if 0 /* This causes crashes, and seems to be redundant -- rms. */
- lw_modify_all_widgets (dialog_id, first_wv, True);
-#endif
- lw_modify_all_widgets (dialog_id, first_wv->contents, True);
- /* Free the widget_value objects we used to specify the contents. */
- free_menubar_widget_value_tree (first_wv);
-
- /* No selection has been chosen yet. */
- menu_item_selection = 0;
-
- /* Display the menu. */
- lw_pop_up_all_widgets (dialog_id);
-
- /* Process events that apply to the menu. */
- while (1)
- {
- XEvent event;
-
- XtAppNextEvent (Xt_app_con, &event);
- if (event.type == ButtonRelease)
- {
- XtDispatchEvent (&event);
- break;
- }
- else if (event.type == Expose)
- process_expose_from_menu (event);
- XtDispatchEvent (&event);
- if (XtWindowToWidget(XDISPLAY event.xany.window) != menu)
- {
- queue_tmp = (struct event_queue *) malloc (sizeof (struct event_queue));
-
- if (queue_tmp != NULL)
- {
- queue_tmp->event = event;
- queue_tmp->next = queue;
- queue = queue_tmp;
- }
- }
- }
- pop_down:
-
- /* State that no mouse buttons are now held.
- That is not necessarily true, but the fiction leads to reasonable
- results, and it is a pain to ask which are actually held now
- or track this in the loop above. */
- w32_mouse_grabbed = 0;
-
- /* Unread any events that we got but did not handle. */
- while (queue != NULL)
- {
- queue_tmp = queue;
- XPutBackEvent (XDISPLAY &queue_tmp->event);
- queue = queue_tmp->next;
- free ((char *)queue_tmp);
- /* Cause these events to get read as soon as we UNBLOCK_INPUT. */
- interrupt_input_pending = 1;
- }
-
- /* Find the selected item, and its pane, to return
- the proper value. */
- if (menu_item_selection != 0)
- {
- Lisp_Object prefix;
-
- prefix = Qnil;
- i = 0;
- while (i < menu_items_used)
- {
- Lisp_Object entry;
-
- if (EQ (XVECTOR (menu_items)->contents[i], Qt))
- {
- prefix
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
- i += MENU_ITEMS_PANE_LENGTH;
- }
- else
- {
- entry
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
- if (menu_item_selection == &XVECTOR (menu_items)->contents[i])
- {
- if (keymaps != 0)
- {
- entry = Fcons (entry, Qnil);
- if (!NILP (prefix))
- entry = Fcons (prefix, entry);
- }
- return entry;
- }
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
- }
-
- return Qnil;
-}
-#endif
-
-syms_of_w32menu ()
-{
- Qdebug_on_next_call = intern ("debug-on-next-call");
- staticpro (&Qdebug_on_next_call);
-
- defsubr (&Sx_popup_menu);
- defsubr (&Sx_popup_dialog);
-}
diff --git a/src/w32proc.c b/src/w32proc.c
deleted file mode 100644
index 755336299b4..00000000000
--- a/src/w32proc.c
+++ /dev/null
@@ -1,1326 +0,0 @@
-/* Process support for Windows NT port of GNU EMACS.
- Copyright (C) 1992, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-
- Drew Bliss Oct 14, 1993
- Adapted from alarm.c by Tim Fleehart
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <io.h>
-#include <fcntl.h>
-#include <signal.h>
-
-/* must include CRT headers *before* config.h */
-#include "config.h"
-#undef signal
-#undef wait
-#undef spawnve
-#undef select
-#undef kill
-
-#include <windows.h>
-
-#include "lisp.h"
-#include "w32.h"
-#include "systime.h"
-#include "syswait.h"
-#include "process.h"
-
-/* Control whether spawnve quotes arguments as necessary to ensure
- correct parsing by child process. Because not all uses of spawnve
- are careful about constructing argv arrays, we make this behaviour
- conditional (off by default). */
-Lisp_Object Vw32_quote_process_args;
-
-/* Control whether create_child causes the process' window to be
- hidden. The default is nil. */
-Lisp_Object Vw32_start_process_show_window;
-
-/* Time to sleep before reading from a subprocess output pipe - this
- avoids the inefficiency of frequently reading small amounts of data.
- This is primarily necessary for handling DOS processes on Windows 95,
- but is useful for W32 processes on both Win95 and NT as well. */
-Lisp_Object Vw32_pipe_read_delay;
-
-/* Control conversion of upper case file names to lower case.
- nil means no, t means yes. */
-Lisp_Object Vw32_downcase_file_names;
-
-/* Keep track of whether we have already started a DOS program. */
-BOOL dos_process_running;
-
-#ifndef SYS_SIGLIST_DECLARED
-extern char *sys_siglist[];
-#endif
-
-#ifdef EMACSDEBUG
-void _DebPrint (const char *fmt, ...)
-{
- char buf[1024];
- va_list args;
-
- va_start (args, fmt);
- vsprintf (buf, fmt, args);
- va_end (args);
- OutputDebugString (buf);
-}
-#endif
-
-typedef void (_CALLBACK_ *signal_handler)(int);
-
-/* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */
-static signal_handler sig_handlers[NSIG];
-
-/* Fake signal implementation to record the SIGCHLD handler. */
-signal_handler
-sys_signal (int sig, signal_handler handler)
-{
- signal_handler old;
-
- if (sig != SIGCHLD)
- {
- errno = EINVAL;
- return SIG_ERR;
- }
- old = sig_handlers[sig];
- sig_handlers[sig] = handler;
- return old;
-}
-
-/* Defined in <process.h> which conflicts with the local copy */
-#define _P_NOWAIT 1
-
-/* Child process management list. */
-int child_proc_count = 0;
-child_process child_procs[ MAX_CHILDREN ];
-child_process *dead_child = NULL;
-
-DWORD WINAPI reader_thread (void *arg);
-
-/* Find an unused process slot. */
-child_process *
-new_child (void)
-{
- child_process *cp;
- DWORD id;
-
- for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
- if (!CHILD_ACTIVE (cp))
- goto Initialise;
- if (child_proc_count == MAX_CHILDREN)
- return NULL;
- cp = &child_procs[child_proc_count++];
-
- Initialise:
- memset (cp, 0, sizeof(*cp));
- cp->fd = -1;
- cp->pid = -1;
- cp->procinfo.hProcess = NULL;
- cp->status = STATUS_READ_ERROR;
-
- /* use manual reset event so that select() will function properly */
- cp->char_avail = CreateEvent (NULL, TRUE, FALSE, NULL);
- if (cp->char_avail)
- {
- cp->char_consumed = CreateEvent (NULL, FALSE, FALSE, NULL);
- if (cp->char_consumed)
- {
- cp->thrd = CreateThread (NULL, 1024, reader_thread, cp, 0, &id);
- if (cp->thrd)
- return cp;
- }
- }
- delete_child (cp);
- return NULL;
-}
-
-void
-delete_child (child_process *cp)
-{
- int i;
-
- /* Should not be deleting a child that is still needed. */
- for (i = 0; i < MAXDESC; i++)
- if (fd_info[i].cp == cp)
- abort ();
-
- if (!CHILD_ACTIVE (cp))
- return;
-
- /* reap thread if necessary */
- if (cp->thrd)
- {
- DWORD rc;
-
- if (GetExitCodeThread (cp->thrd, &rc) && rc == STILL_ACTIVE)
- {
- /* let the thread exit cleanly if possible */
- cp->status = STATUS_READ_ERROR;
- SetEvent (cp->char_consumed);
- if (WaitForSingleObject (cp->thrd, 1000) != WAIT_OBJECT_0)
- {
- DebPrint (("delete_child.WaitForSingleObject (thread) failed "
- "with %lu for fd %ld\n", GetLastError (), cp->fd));
- TerminateThread (cp->thrd, 0);
- }
- }
- CloseHandle (cp->thrd);
- cp->thrd = NULL;
- }
- if (cp->char_avail)
- {
- CloseHandle (cp->char_avail);
- cp->char_avail = NULL;
- }
- if (cp->char_consumed)
- {
- CloseHandle (cp->char_consumed);
- cp->char_consumed = NULL;
- }
-
- /* update child_proc_count (highest numbered slot in use plus one) */
- if (cp == child_procs + child_proc_count - 1)
- {
- for (i = child_proc_count-1; i >= 0; i--)
- if (CHILD_ACTIVE (&child_procs[i]))
- {
- child_proc_count = i + 1;
- break;
- }
- }
- if (i < 0)
- child_proc_count = 0;
-}
-
-/* Find a child by pid. */
-static child_process *
-find_child_pid (DWORD pid)
-{
- child_process *cp;
-
- for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
- if (CHILD_ACTIVE (cp) && pid == cp->pid)
- return cp;
- return NULL;
-}
-
-
-/* Thread proc for child process and socket reader threads. Each thread
- is normally blocked until woken by select() to check for input by
- reading one char. When the read completes, char_avail is signalled
- to wake up the select emulator and the thread blocks itself again. */
-DWORD WINAPI
-reader_thread (void *arg)
-{
- child_process *cp;
-
- /* Our identity */
- cp = (child_process *)arg;
-
- /* We have to wait for the go-ahead before we can start */
- if (cp == NULL ||
- WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
- return 1;
-
- for (;;)
- {
- int rc;
-
- rc = _sys_read_ahead (cp->fd);
-
- /* The name char_avail is a misnomer - it really just means the
- read-ahead has completed, whether successfully or not. */
- if (!SetEvent (cp->char_avail))
- {
- DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n",
- GetLastError (), cp->fd));
- return 1;
- }
-
- if (rc == STATUS_READ_ERROR)
- return 1;
-
- /* If the read died, the child has died so let the thread die */
- if (rc == STATUS_READ_FAILED)
- break;
-
- /* Wait until our input is acknowledged before reading again */
- if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
- {
- DebPrint (("reader_thread.WaitForSingleObject failed with "
- "%lu for fd %ld\n", GetLastError (), cp->fd));
- break;
- }
- }
- return 0;
-}
-
-static BOOL
-create_child (char *exe, char *cmdline, char *env,
- int * pPid, child_process *cp)
-{
- STARTUPINFO start;
- SECURITY_ATTRIBUTES sec_attrs;
- SECURITY_DESCRIPTOR sec_desc;
-
- if (cp == NULL) abort ();
-
- memset (&start, 0, sizeof (start));
- start.cb = sizeof (start);
-
-#ifdef HAVE_NTGUI
- if (NILP (Vw32_start_process_show_window))
- start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
- else
- start.dwFlags = STARTF_USESTDHANDLES;
- start.wShowWindow = SW_HIDE;
-
- start.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
- start.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
- start.hStdError = GetStdHandle (STD_ERROR_HANDLE);
-#endif /* HAVE_NTGUI */
-
- /* Explicitly specify no security */
- if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION))
- goto EH_Fail;
- if (!SetSecurityDescriptorDacl (&sec_desc, TRUE, NULL, FALSE))
- goto EH_Fail;
- sec_attrs.nLength = sizeof (sec_attrs);
- sec_attrs.lpSecurityDescriptor = &sec_desc;
- sec_attrs.bInheritHandle = FALSE;
-
- if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE,
- CREATE_NEW_PROCESS_GROUP,
- env, NULL,
- &start, &cp->procinfo))
- goto EH_Fail;
-
- cp->pid = (int) cp->procinfo.dwProcessId;
-
- /* Hack for Windows 95, which assigns large (ie negative) pids */
- if (cp->pid < 0)
- cp->pid = -cp->pid;
-
- /* pid must fit in a Lisp_Int */
- cp->pid = (cp->pid & VALMASK);
-
-
- *pPid = cp->pid;
-
- return TRUE;
-
- EH_Fail:
- DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError()););
- return FALSE;
-}
-
-/* create_child doesn't know what emacs' file handle will be for waiting
- on output from the child, so we need to make this additional call
- to register the handle with the process
- This way the select emulator knows how to match file handles with
- entries in child_procs. */
-void
-register_child (int pid, int fd)
-{
- child_process *cp;
-
- cp = find_child_pid (pid);
- if (cp == NULL)
- {
- DebPrint (("register_child unable to find pid %lu\n", pid));
- return;
- }
-
-#ifdef FULL_DEBUG
- DebPrint (("register_child registered fd %d with pid %lu\n", fd, pid));
-#endif
-
- cp->fd = fd;
-
- /* thread is initially blocked until select is called; set status so
- that select will release thread */
- cp->status = STATUS_READ_ACKNOWLEDGED;
-
- /* attach child_process to fd_info */
- if (fd_info[fd].cp != NULL)
- {
- DebPrint (("register_child: fd_info[%d] apparently in use!\n", fd));
- abort ();
- }
-
- fd_info[fd].cp = cp;
-}
-
-/* When a process dies its pipe will break so the reader thread will
- signal failure to the select emulator.
- The select emulator then calls this routine to clean up.
- Since the thread signaled failure we can assume it is exiting. */
-static void
-reap_subprocess (child_process *cp)
-{
- if (cp->procinfo.hProcess)
- {
- /* Reap the process */
- if (WaitForSingleObject (cp->procinfo.hProcess, INFINITE) != WAIT_OBJECT_0)
- DebPrint (("reap_subprocess.WaitForSingleObject (process) failed "
- "with %lu for fd %ld\n", GetLastError (), cp->fd));
- CloseHandle (cp->procinfo.hProcess);
- cp->procinfo.hProcess = NULL;
- CloseHandle (cp->procinfo.hThread);
- cp->procinfo.hThread = NULL;
-
- /* If this was a DOS process, indicate that it is now safe to
- start a new one. */
- if (cp->is_dos_process)
- dos_process_running = FALSE;
- }
-
- /* For asynchronous children, the child_proc resources will be freed
- when the last pipe read descriptor is closed; for synchronous
- children, we must explicitly free the resources now because
- register_child has not been called. */
- if (cp->fd == -1)
- delete_child (cp);
-}
-
-/* Wait for any of our existing child processes to die
- When it does, close its handle
- Return the pid and fill in the status if non-NULL. */
-
-int
-sys_wait (int *status)
-{
- DWORD active, retval;
- int nh;
- int pid;
- child_process *cp, *cps[MAX_CHILDREN];
- HANDLE wait_hnd[MAX_CHILDREN];
-
- nh = 0;
- if (dead_child != NULL)
- {
- /* We want to wait for a specific child */
- wait_hnd[nh] = dead_child->procinfo.hProcess;
- cps[nh] = dead_child;
- if (!wait_hnd[nh]) abort ();
- nh++;
- }
- else
- {
- for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
- /* some child_procs might be sockets; ignore them */
- if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess)
- {
- wait_hnd[nh] = cp->procinfo.hProcess;
- cps[nh] = cp;
- if (!wait_hnd[nh]) abort ();
- nh++;
- }
- }
-
- if (nh == 0)
- {
- /* Nothing to wait on, so fail */
- errno = ECHILD;
- return -1;
- }
-
- active = WaitForMultipleObjects (nh, wait_hnd, FALSE, INFINITE);
- if (active == WAIT_FAILED)
- {
- errno = EBADF;
- return -1;
- }
- else if (active == WAIT_TIMEOUT)
- {
- /* Should never happen */
- errno = EINVAL;
- return -1;
- }
- else if (active >= WAIT_OBJECT_0 &&
- active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS)
- {
- active -= WAIT_OBJECT_0;
- }
- else if (active >= WAIT_ABANDONED_0 &&
- active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS)
- {
- active -= WAIT_ABANDONED_0;
- }
-
- if (!GetExitCodeProcess (wait_hnd[active], &retval))
- {
- DebPrint (("Wait.GetExitCodeProcess failed with %lu\n",
- GetLastError ()));
- retval = 1;
- }
- if (retval == STILL_ACTIVE)
- {
- /* Should never happen */
- DebPrint (("Wait.WaitForMultipleObjects returned an active process\n"));
- errno = EINVAL;
- return -1;
- }
-
- /* Massage the exit code from the process to match the format expected
- by the WIFSTOPPED et al macros in syswait.h. Only WIFSIGNALED and
- WIFEXITED are supported; WIFSTOPPED doesn't make sense under NT. */
-
- if (retval == STATUS_CONTROL_C_EXIT)
- retval = SIGINT;
- else
- retval <<= 8;
-
- cp = cps[active];
- pid = cp->pid;
-#ifdef FULL_DEBUG
- DebPrint (("Wait signaled with process pid %d\n", cp->pid));
-#endif
-
- if (status)
- {
- *status = retval;
- }
- else if (synch_process_alive)
- {
- synch_process_alive = 0;
-
- /* Report the status of the synchronous process. */
- if (WIFEXITED (retval))
- synch_process_retcode = WRETCODE (retval);
- else if (WIFSIGNALED (retval))
- {
- int code = WTERMSIG (retval);
- char *signame = 0;
-
- if (code < NSIG)
- {
- /* Suppress warning if the table has const char *. */
- signame = (char *) sys_siglist[code];
- }
- if (signame == 0)
- signame = "unknown";
-
- synch_process_death = signame;
- }
-
- reap_subprocess (cp);
- }
-
- return pid;
-}
-
-int
-w32_is_dos_binary (char * filename)
-{
- IMAGE_DOS_HEADER dos_header;
- DWORD signature;
- int fd;
- int is_dos_binary = FALSE;
-
- fd = open (filename, O_RDONLY | O_BINARY, 0);
- if (fd >= 0)
- {
- char * p = strrchr (filename, '.');
-
- /* We can only identify DOS .com programs from the extension. */
- if (p && stricmp (p, ".com") == 0)
- is_dos_binary = TRUE;
- else if (p && stricmp (p, ".bat") == 0)
- {
- /* A DOS shell script - it appears that CreateProcess is happy
- to accept this (somewhat surprisingly); presumably it looks
- at COMSPEC to determine what executable to actually invoke.
- Therefore, we have to do the same here as well. */
- p = getenv ("COMSPEC");
- if (p)
- is_dos_binary = w32_is_dos_binary (p);
- }
- else
- {
- /* Look for DOS .exe signature - if found, we must also check
- that it isn't really a 16- or 32-bit Windows exe, since
- both formats start with a DOS program stub. Note that
- 16-bit Windows executables use the OS/2 1.x format. */
- if (read (fd, &dos_header, sizeof (dos_header)) == sizeof (dos_header)
- && dos_header.e_magic == IMAGE_DOS_SIGNATURE
- && lseek (fd, dos_header.e_lfanew, SEEK_SET) != -1)
- {
- if (read (fd, &signature, sizeof (signature)) != sizeof (signature)
- || (signature != IMAGE_NT_SIGNATURE &&
- LOWORD (signature) != IMAGE_OS2_SIGNATURE))
- is_dos_binary = TRUE;
- }
- }
- close (fd);
- }
-
- return is_dos_binary;
-}
-
-int
-compare_env (const char **strp1, const char **strp2)
-{
- const char *str1 = *strp1, *str2 = *strp2;
-
- while (*str1 && *str2 && *str1 != '=' && *str2 != '=')
- {
- if (tolower (*str1) > tolower (*str2))
- return 1;
- else if (tolower (*str1) < tolower (*str2))
- return -1;
- str1++, str2++;
- }
-
- if (*str1 == '=' && *str2 == '=')
- return 0;
- else if (*str1 == '=')
- return -1;
- else
- return 1;
-}
-
-void
-merge_and_sort_env (char **envp1, char **envp2, char **new_envp)
-{
- char **optr, **nptr;
- int num;
-
- nptr = new_envp;
- optr = envp1;
- while (*optr)
- *nptr++ = *optr++;
- num = optr - envp1;
-
- optr = envp2;
- while (*optr)
- *nptr++ = *optr++;
- num += optr - envp2;
-
- qsort (new_envp, num, sizeof (char *), compare_env);
-
- *nptr = NULL;
-}
-
-/* When a new child process is created we need to register it in our list,
- so intercept spawn requests. */
-int
-sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
-{
- Lisp_Object program, full;
- char *cmdline, *env, *parg, **targ;
- int arglen, numenv;
- int pid;
- child_process *cp;
- int is_dos_binary;
- /* We pass our process ID to our children by setting up an environment
- variable in their environment. */
- char ppid_env_var_buffer[64];
- char *extra_env[] = {ppid_env_var_buffer, NULL};
-
- /* We don't care about the other modes */
- if (mode != _P_NOWAIT)
- {
- errno = EINVAL;
- return -1;
- }
-
- /* Handle executable names without an executable suffix. */
- program = make_string (cmdname, strlen (cmdname));
- if (NILP (Ffile_executable_p (program)))
- {
- struct gcpro gcpro1;
-
- full = Qnil;
- GCPRO1 (program);
- openp (Vexec_path, program, EXEC_SUFFIXES, &full, 1);
- UNGCPRO;
- if (NILP (full))
- {
- errno = EINVAL;
- return -1;
- }
- cmdname = XSTRING (full)->data;
- argv[0] = cmdname;
- }
-
- /* make sure cmdname is in DOS format */
- strcpy (cmdname = alloca (strlen (cmdname) + 1), argv[0]);
- unixtodos_filename (cmdname);
- argv[0] = cmdname;
-
- /* Check if program is a DOS executable, and if so whether we are
- allowed to start it. */
- is_dos_binary = w32_is_dos_binary (cmdname);
- if (is_dos_binary && dos_process_running)
- {
- errno = EAGAIN;
- return -1;
- }
-
- /* we have to do some conjuring here to put argv and envp into the
- form CreateProcess wants... argv needs to be a space separated/null
- terminated list of parameters, and envp is a null
- separated/double-null terminated list of parameters.
-
- Additionally, zero-length args and args containing whitespace need
- to be wrapped in double quotes. Args containing embedded double
- quotes (as opposed to enclosing quotes, which we leave alone) are
- usually illegal (most W32 programs do not implement escaping of
- double quotes - sad but true, at least for programs compiled with
- MSVC), but we will escape quotes anyway for those programs that can
- handle it. The W32 gcc library from Cygnus doubles quotes to
- escape them, so we will use that convention.
-
- Since I have no idea how large argv and envp are likely to be
- we figure out list lengths on the fly and allocate them. */
-
- /* do argv... */
- arglen = 0;
- targ = argv;
- while (*targ)
- {
- char * p = *targ;
- int add_quotes = 0;
-
- if (*p == 0)
- add_quotes = 1;
- while (*p)
- if (*p++ == '"')
- {
- /* allow for embedded quotes to be doubled - we won't
- actually double quotes that aren't embedded though */
- arglen++;
- add_quotes = 1;
- }
- else if (*p == ' ' || *p == '\t')
- add_quotes = 1;
- if (add_quotes)
- arglen += 2;
- arglen += strlen (*targ++) + 1;
- }
- cmdline = alloca (arglen);
- targ = argv;
- parg = cmdline;
- while (*targ)
- {
- char * p = *targ;
- int add_quotes = 0;
-
- if (*p == 0)
- add_quotes = 1;
-
- if (!NILP (Vw32_quote_process_args))
- {
- /* This is conditional because it sometimes causes more
- problems than it solves, since argv arrays are not always
- carefully constructed. M-x grep, for instance, passes the
- whole command line as one argument, so it becomes
- impossible to pass a regexp which contains spaces. */
- for ( ; *p; p++)
- if (*p == ' ' || *p == '\t' || *p == '"')
- add_quotes = 1;
- }
- if (add_quotes)
- {
- char * first;
- char * last;
-
- p = *targ;
- first = p;
- last = p + strlen (p) - 1;
- *parg++ = '"';
- while (*p)
- {
- if (*p == '"' && p > first && p < last)
- *parg++ = '"'; /* double up embedded quotes only */
- *parg++ = *p++;
- }
- *parg++ = '"';
- }
- else
- {
- strcpy (parg, *targ);
- parg += strlen (*targ);
- }
- *parg++ = ' ';
- targ++;
- }
- *--parg = '\0';
-
- /* and envp... */
- arglen = 1;
- targ = envp;
- numenv = 1; /* for end null */
- while (*targ)
- {
- arglen += strlen (*targ++) + 1;
- numenv++;
- }
- /* extra env vars... */
- sprintf (ppid_env_var_buffer, "__PARENT_PROCESS_ID=%d",
- GetCurrentProcessId ());
- arglen += strlen (ppid_env_var_buffer) + 1;
- numenv++;
-
- /* merge env passed in and extra env into one, and sort it. */
- targ = (char **) alloca (numenv * sizeof (char *));
- merge_and_sort_env (envp, extra_env, targ);
-
- /* concatenate env entries. */
- env = alloca (arglen);
- parg = env;
- while (*targ)
- {
- strcpy (parg, *targ);
- parg += strlen (*targ++);
- *parg++ = '\0';
- }
- *parg++ = '\0';
- *parg = '\0';
-
- cp = new_child ();
- if (cp == NULL)
- {
- errno = EAGAIN;
- return -1;
- }
-
- /* Now create the process. */
- if (!create_child (cmdname, cmdline, env, &pid, cp))
- {
- delete_child (cp);
- errno = ENOEXEC;
- return -1;
- }
-
- if (is_dos_binary)
- {
- cp->is_dos_process = TRUE;
- dos_process_running = TRUE;
- }
-
- return pid;
-}
-
-/* Emulate the select call
- Wait for available input on any of the given rfds, or timeout if
- a timeout is given and no input is detected
- wfds and efds are not supported and must be NULL. */
-
-/* From ntterm.c */
-extern HANDLE keyboard_handle;
-/* From process.c */
-extern int proc_buffered_char[];
-
-int
-sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
- EMACS_TIME *timeout)
-{
- SELECT_TYPE orfds;
- DWORD timeout_ms;
- int i, nh, nr;
- DWORD active;
- child_process *cp;
- HANDLE wait_hnd[MAXDESC];
- int fdindex[MAXDESC]; /* mapping from wait handles back to descriptors */
-
- /* If the descriptor sets are NULL but timeout isn't, then just Sleep. */
- if (rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL)
- {
- Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000);
- return 0;
- }
-
- /* Otherwise, we only handle rfds, so fail otherwise. */
- if (rfds == NULL || wfds != NULL || efds != NULL)
- {
- errno = EINVAL;
- return -1;
- }
-
- orfds = *rfds;
- FD_ZERO (rfds);
- nr = 0;
-
- /* Build a list of handles to wait on. */
- nh = 0;
- for (i = 0; i < nfds; i++)
- if (FD_ISSET (i, &orfds))
- {
- if (i == 0)
- {
- if (keyboard_handle)
- {
- /* Handle stdin specially */
- wait_hnd[nh] = keyboard_handle;
- fdindex[nh] = i;
- nh++;
- }
-
- /* Check for any emacs-generated input in the queue since
- it won't be detected in the wait */
- if (detect_input_pending ())
- {
- FD_SET (i, rfds);
- return 1;
- }
- }
- else
- {
- /* Child process and socket input */
- cp = fd_info[i].cp;
- if (cp)
- {
- int current_status = cp->status;
-
- if (current_status == STATUS_READ_ACKNOWLEDGED)
- {
- /* Tell reader thread which file handle to use. */
- cp->fd = i;
- /* Wake up the reader thread for this process */
- cp->status = STATUS_READ_READY;
- if (!SetEvent (cp->char_consumed))
- DebPrint (("nt_select.SetEvent failed with "
- "%lu for fd %ld\n", GetLastError (), i));
- }
-
-#ifdef CHECK_INTERLOCK
- /* slightly crude cross-checking of interlock between threads */
-
- current_status = cp->status;
- if (WaitForSingleObject (cp->char_avail, 0) == WAIT_OBJECT_0)
- {
- /* char_avail has been signalled, so status (which may
- have changed) should indicate read has completed
- but has not been acknowledged. */
- current_status = cp->status;
- if (current_status != STATUS_READ_SUCCEEDED &&
- current_status != STATUS_READ_FAILED)
- DebPrint (("char_avail set, but read not completed: status %d\n",
- current_status));
- }
- else
- {
- /* char_avail has not been signalled, so status should
- indicate that read is in progress; small possibility
- that read has completed but event wasn't yet signalled
- when we tested it (because a context switch occurred
- or if running on separate CPUs). */
- if (current_status != STATUS_READ_READY &&
- current_status != STATUS_READ_IN_PROGRESS &&
- current_status != STATUS_READ_SUCCEEDED &&
- current_status != STATUS_READ_FAILED)
- DebPrint (("char_avail reset, but read status is bad: %d\n",
- current_status));
- }
-#endif
- wait_hnd[nh] = cp->char_avail;
- fdindex[nh] = i;
- if (!wait_hnd[nh]) abort ();
- nh++;
-#ifdef FULL_DEBUG
- DebPrint (("select waiting on child %d fd %d\n",
- cp-child_procs, i));
-#endif
- }
- else
- {
- /* Unable to find something to wait on for this fd, skip */
- DebPrint (("sys_select: fd %ld is invalid! ignoring\n", i));
- abort ();
- }
- }
- }
-
- /* Nothing to look for, so we didn't find anything */
- if (nh == 0)
- {
- if (timeout)
- Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000);
- return 0;
- }
-
- /*
- Wait for input
- If a child process dies while this is waiting, its pipe will break
- so the reader thread will signal an error condition, thus, the wait
- will wake up
- */
- timeout_ms = timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFINITE;
-
- active = WaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms);
-
- if (active == WAIT_FAILED)
- {
- DebPrint (("select.WaitForMultipleObjects (%d, %lu) failed with %lu\n",
- nh, timeout_ms, GetLastError ()));
- /* don't return EBADF - this causes wait_reading_process_input to
- abort; WAIT_FAILED is returned when single-stepping under
- Windows 95 after switching thread focus in debugger, and
- possibly at other times. */
- errno = EINTR;
- return -1;
- }
- else if (active == WAIT_TIMEOUT)
- {
- return 0;
- }
- else if (active >= WAIT_OBJECT_0 &&
- active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS)
- {
- active -= WAIT_OBJECT_0;
- }
- else if (active >= WAIT_ABANDONED_0 &&
- active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS)
- {
- active -= WAIT_ABANDONED_0;
- }
-
- /* Loop over all handles after active (now officially documented as
- being the first signalled handle in the array). We do this to
- ensure fairness, so that all channels with data available will be
- processed - otherwise higher numbered channels could be starved. */
- do
- {
- if (fdindex[active] == 0)
- {
- /* Keyboard input available */
- FD_SET (0, rfds);
- nr++;
- }
- else
- {
- /* must be a socket or pipe */
- int current_status;
-
- cp = fd_info[ fdindex[active] ].cp;
-
- /* Read ahead should have completed, either succeeding or failing. */
- FD_SET (fdindex[active], rfds);
- nr++;
- current_status = cp->status;
- if (current_status != STATUS_READ_SUCCEEDED)
- {
- if (current_status != STATUS_READ_FAILED)
- DebPrint (("internal error: subprocess pipe signalled "
- "at the wrong time (status %d)\n!", current_status));
-
- /* The child_process entry for a socket or pipe will be
- freed when the last descriptor using it is closed; for
- pipes, we call the SIGCHLD handler. */
- if (fd_info[ fdindex[active] ].flags & FILE_PIPE)
- {
- /* The SIGCHLD handler will do a Wait so we know it won't
- return until the process is dead
- We force Wait to only wait for this process to avoid it
- picking up other children that happen to be dead but that
- we haven't noticed yet
- SIG_DFL for SIGCHLD is ignore? */
- if (sig_handlers[SIGCHLD] != SIG_DFL &&
- sig_handlers[SIGCHLD] != SIG_IGN)
- {
-#ifdef FULL_DEBUG
- DebPrint (("select calling SIGCHLD handler for pid %d\n",
- cp->pid));
-#endif
- dead_child = cp;
- sig_handlers[SIGCHLD] (SIGCHLD);
- dead_child = NULL;
- }
-
- /* Clean up the child process entry in the table */
- reap_subprocess (cp);
- }
- }
- }
-
- /* Test for input on remaining channels. */
- while (++active < nh)
- if (WaitForSingleObject (wait_hnd[active], 0) == WAIT_OBJECT_0)
- break;
- } while (active < nh);
-
- return nr;
-}
-
-/* Substitute for certain kill () operations */
-int
-sys_kill (int pid, int sig)
-{
- child_process *cp;
- HANDLE proc_hand;
- int need_to_free = 0;
- int rc = 0;
-
- /* Only handle signals that will result in the process dying */
- if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
- {
- errno = EINVAL;
- return -1;
- }
-
- cp = find_child_pid (pid);
- if (cp == NULL)
- {
- proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid);
- if (proc_hand == NULL)
- {
- errno = EPERM;
- return -1;
- }
- need_to_free = 1;
- }
- else
- {
- proc_hand = cp->procinfo.hProcess;
- pid = cp->procinfo.dwProcessId;
- }
-
- if (sig == SIGINT)
- {
- /* Ctrl-Break is NT equivalent of SIGINT. */
- if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid))
- {
- DebPrint (("sys_kill.GenerateConsoleCtrlEvent return %d "
- "for pid %lu\n", GetLastError (), pid));
- errno = EINVAL;
- rc = -1;
- }
- }
- else
- {
- /* Kill the process. On W32 this doesn't kill child processes
- so it doesn't work very well for shells which is why it's not
- used in every case. Also, don't try to terminate DOS processes
- (on Win95), because this will hang Emacs. */
- if (!(cp && cp->is_dos_process)
- && !TerminateProcess (proc_hand, 0xff))
- {
- DebPrint (("sys_kill.TerminateProcess returned %d "
- "for pid %lu\n", GetLastError (), pid));
- errno = EINVAL;
- rc = -1;
- }
- }
-
- if (need_to_free)
- CloseHandle (proc_hand);
-
- return rc;
-}
-
-extern int report_file_error (char *, Lisp_Object);
-
-/* The following two routines are used to manipulate stdin, stdout, and
- stderr of our child processes.
-
- Assuming that in, out, and err are *not* inheritable, we make them
- stdin, stdout, and stderr of the child as follows:
-
- - Save the parent's current standard handles.
- - Set the std handles to inheritable duplicates of the ones being passed in.
- (Note that _get_osfhandle() is an io.h procedure that retrieves the
- NT file handle for a crt file descriptor.)
- - Spawn the child, which inherits in, out, and err as stdin,
- stdout, and stderr. (see Spawnve)
- - Close the std handles passed to the child.
- - Reset the parent's standard handles to the saved handles.
- (see reset_standard_handles)
- We assume that the caller closes in, out, and err after calling us. */
-
-void
-prepare_standard_handles (int in, int out, int err, HANDLE handles[3])
-{
- HANDLE parent;
- HANDLE newstdin, newstdout, newstderr;
-
- parent = GetCurrentProcess ();
-
- handles[0] = GetStdHandle (STD_INPUT_HANDLE);
- handles[1] = GetStdHandle (STD_OUTPUT_HANDLE);
- handles[2] = GetStdHandle (STD_ERROR_HANDLE);
-
- /* make inheritable copies of the new handles */
- if (!DuplicateHandle (parent,
- (HANDLE) _get_osfhandle (in),
- parent,
- &newstdin,
- 0,
- TRUE,
- DUPLICATE_SAME_ACCESS))
- report_file_error ("Duplicating input handle for child", Qnil);
-
- if (!DuplicateHandle (parent,
- (HANDLE) _get_osfhandle (out),
- parent,
- &newstdout,
- 0,
- TRUE,
- DUPLICATE_SAME_ACCESS))
- report_file_error ("Duplicating output handle for child", Qnil);
-
- if (!DuplicateHandle (parent,
- (HANDLE) _get_osfhandle (err),
- parent,
- &newstderr,
- 0,
- TRUE,
- DUPLICATE_SAME_ACCESS))
- report_file_error ("Duplicating error handle for child", Qnil);
-
- /* and store them as our std handles */
- if (!SetStdHandle (STD_INPUT_HANDLE, newstdin))
- report_file_error ("Changing stdin handle", Qnil);
-
- if (!SetStdHandle (STD_OUTPUT_HANDLE, newstdout))
- report_file_error ("Changing stdout handle", Qnil);
-
- if (!SetStdHandle (STD_ERROR_HANDLE, newstderr))
- report_file_error ("Changing stderr handle", Qnil);
-}
-
-void
-reset_standard_handles (int in, int out, int err, HANDLE handles[3])
-{
- /* close the duplicated handles passed to the child */
- CloseHandle (GetStdHandle (STD_INPUT_HANDLE));
- CloseHandle (GetStdHandle (STD_OUTPUT_HANDLE));
- CloseHandle (GetStdHandle (STD_ERROR_HANDLE));
-
- /* now restore parent's saved std handles */
- SetStdHandle (STD_INPUT_HANDLE, handles[0]);
- SetStdHandle (STD_OUTPUT_HANDLE, handles[1]);
- SetStdHandle (STD_ERROR_HANDLE, handles[2]);
-}
-
-#ifdef HAVE_SOCKETS
-
-/* To avoid problems with winsock implementations that work over dial-up
- connections causing or requiring a connection to exist while Emacs is
- running, Emacs no longer automatically loads winsock on startup if it
- is present. Instead, it will be loaded when open-network-stream is
- first called.
-
- To allow full control over when winsock is loaded, we provide these
- two functions to dynamically load and unload winsock. This allows
- dial-up users to only be connected when they actually need to use
- socket services. */
-
-/* From nt.c */
-extern HANDLE winsock_lib;
-extern BOOL term_winsock (void);
-extern BOOL init_winsock (int load_now);
-
-extern Lisp_Object Vsystem_name;
-
-DEFUN ("w32-has-winsock", Fw32_has_winsock, Sw32_has_winsock, 0, 1, 0,
- "Test for presence of the Windows socket library `winsock'.\n\
-Returns non-nil if winsock support is present, nil otherwise.\n\
-\n\
-If the optional argument LOAD-NOW is non-nil, the winsock library is\n\
-also loaded immediately if not already loaded. If winsock is loaded,\n\
-the winsock local hostname is returned (since this may be different from\n\
-the value of `system-name' and should supplant it), otherwise t is\n\
-returned to indicate winsock support is present.")
- (load_now)
- Lisp_Object load_now;
-{
- int have_winsock;
-
- have_winsock = init_winsock (!NILP (load_now));
- if (have_winsock)
- {
- if (winsock_lib != NULL)
- {
- /* Return new value for system-name. The best way to do this
- is to call init_system_name, saving and restoring the
- original value to avoid side-effects. */
- Lisp_Object orig_hostname = Vsystem_name;
- Lisp_Object hostname;
-
- init_system_name ();
- hostname = Vsystem_name;
- Vsystem_name = orig_hostname;
- return hostname;
- }
- return Qt;
- }
- return Qnil;
-}
-
-DEFUN ("w32-unload-winsock", Fw32_unload_winsock, Sw32_unload_winsock,
- 0, 0, 0,
- "Unload the Windows socket library `winsock' if loaded.\n\
-This is provided to allow dial-up socket connections to be disconnected\n\
-when no longer needed. Returns nil without unloading winsock if any\n\
-socket connections still exist.")
- ()
-{
- return term_winsock () ? Qt : Qnil;
-}
-
-#endif /* HAVE_SOCKETS */
-
-
-syms_of_ntproc ()
-{
-#ifdef HAVE_SOCKETS
- defsubr (&Sw32_has_winsock);
- defsubr (&Sw32_unload_winsock);
-#endif
-
- DEFVAR_LISP ("w32-quote-process-args", &Vw32_quote_process_args,
- "Non-nil enables quoting of process arguments to ensure correct parsing.\n\
-Because Windows does not directly pass argv arrays to child processes,\n\
-programs have to reconstruct the argv array by parsing the command\n\
-line string. For an argument to contain a space, it must be enclosed\n\
-in double quotes or it will be parsed as multiple arguments.\n\
-\n\
-However, the argument list to call-process is not always correctly\n\
-constructed (or arguments have already been quoted), so enabling this\n\
-option may cause unexpected behavior.");
- Vw32_quote_process_args = Qnil;
-
- DEFVAR_LISP ("w32-start-process-show-window",
- &Vw32_start_process_show_window,
- "When nil, processes started via start-process hide their windows.\n\
-When non-nil, they show their window in the method of their choice.");
- Vw32_start_process_show_window = Qnil;
-
- DEFVAR_INT ("w32-pipe-read-delay", &Vw32_pipe_read_delay,
- "Forced delay before reading subprocess output.\n\
-This is done to improve the buffering of subprocess output, by\n\
-avoiding the inefficiency of frequently reading small amounts of data.\n\
-\n\
-If positive, the value is the number of milliseconds to sleep before\n\
-reading the subprocess output. If negative, the magnitude is the number\n\
-of time slices to wait (effectively boosting the priority of the child\n\
-process temporarily). A value of zero disables waiting entirely.");
- Vw32_pipe_read_delay = 50;
-
- DEFVAR_LISP ("w32-downcase-file-names", &Vw32_downcase_file_names,
- "Non-nil means convert all-upper case file names to lower case.\n\
-This applies when performing completions and file name expansion.");
- Vw32_downcase_file_names = Qnil;
-}
-/* end of ntproc.c */
diff --git a/src/w32reg.c b/src/w32reg.c
deleted file mode 100644
index d32032c76e2..00000000000
--- a/src/w32reg.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/* Emulate the X Resource Manager through the registry.
- Copyright (C) 1990, 1993, 1994 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Written by Kevin Gallo */
-
-#include <config.h>
-#include "lisp.h"
-#include "w32term.h"
-#include "blockinput.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
-
-LPBYTE
-w32_get_string_resource (name, class, dwexptype)
- char *name, *class;
- DWORD dwexptype;
-{
- LPBYTE lpvalue = NULL;
- HKEY hrootkey = NULL;
- DWORD dwType;
- DWORD cbData;
- BOOL ok = FALSE;
-
- BLOCK_INPUT;
-
- /* Check both the current user and the local machine to see if we have any resources */
-
- if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS
- || RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
- {
- char *keyname;
-
- if (RegQueryValueEx (hrootkey, name, NULL, &dwType, NULL, &cbData) == ERROR_SUCCESS
- && dwType == dwexptype)
- {
- keyname = name;
- }
- else if (RegQueryValueEx (hrootkey, class, NULL, &dwType, NULL, &cbData) == ERROR_SUCCESS
- && dwType == dwexptype)
- {
- keyname = class;
- }
- else
- {
- keyname = NULL;
- }
-
- ok = (keyname
- && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
- && RegQueryValueEx (hrootkey, keyname, NULL, NULL, lpvalue, &cbData) == ERROR_SUCCESS);
-
- RegCloseKey (hrootkey);
- }
-
- UNBLOCK_INPUT;
-
- if (!ok)
- {
- if (lpvalue) xfree (lpvalue);
- return (NULL);
- }
- else
- {
- return (lpvalue);
- }
-}
-
-/* Retrieve the string resource specified by NAME with CLASS from
- database RDB. */
-
-char *
-x_get_string_resource (rdb, name, class)
- int rdb;
- char *name, *class;
-{
- return (w32_get_string_resource (name, class, REG_SZ));
-}
diff --git a/src/w32select.c b/src/w32select.c
deleted file mode 100644
index 84d6e2b8dfe..00000000000
--- a/src/w32select.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/* Selection processing for Emacs using the Win32 API.
- Copyright (C) 1993, 1994 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Written by Kevin Gallo */
-
-#include <config.h>
-#include "lisp.h"
-#include "w32term.h" /* for all of the w32 includes */
-#include "dispextern.h" /* frame.h seems to want this */
-#include "frame.h" /* Need this to get the X window of selected_frame */
-#include "blockinput.h"
-
-Lisp_Object QCLIPBOARD;
-
-#if 0
-DEFUN ("w32-open-clipboard", Fw32_open_clipboard, Sw32_open_clipboard, 0, 1, 0,
- "This opens the clipboard with the given frame pointer.")
- (frame)
- Lisp_Object frame;
-{
- BOOL ok = FALSE;
-
- if (!NILP (frame))
- CHECK_LIVE_FRAME (frame, 0);
-
- BLOCK_INPUT;
-
- ok = OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL);
-
- UNBLOCK_INPUT;
-
- return (ok ? frame : Qnil);
-}
-
-DEFUN ("w32-empty-clipboard", Fw32_empty_clipboard, Sw32_empty_clipboard, 0, 0, 0,
- "This empties the clipboard and assigns ownership to the window which opened the clipboard.")
- ()
-{
- BOOL ok = FALSE;
-
- BLOCK_INPUT;
-
- ok = EmptyClipboard ();
-
- UNBLOCK_INPUT;
-
- return (ok ? Qt : Qnil);
-}
-
-DEFUN ("w32-close-clipboard", Fw32_close_clipboard, Sw32_close_clipboard, 0, 0, 0,
- "This closes the clipboard.")
- ()
-{
- BOOL ok = FALSE;
-
- BLOCK_INPUT;
-
- ok = CloseClipboard ();
-
- UNBLOCK_INPUT;
-
- return (ok ? Qt : Qnil);
-}
-
-#endif
-
-DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, Sw32_set_clipboard_data, 1, 2, 0,
- "This sets the clipboard data to the given text.")
- (string, frame)
- Lisp_Object string, frame;
-{
- BOOL ok = TRUE;
- HANDLE htext;
- int nbytes;
- int truelen;
- unsigned char *src;
- unsigned char *dst;
-
- CHECK_STRING (string, 0);
-
- if (!NILP (frame))
- CHECK_LIVE_FRAME (frame, 0);
-
- BLOCK_INPUT;
-
- nbytes = XSTRING (string)->size + 1;
- src = XSTRING (string)->data;
-
- /* need to know final size after '\r' chars are inserted (the
- standard CF_TEXT clipboard format uses CRLF line endings,
- while Emacs uses just LF internally) */
-
- truelen = nbytes;
- dst = src;
- /* avoid using strchr because it recomputes the length everytime */
- while ((dst = memchr (dst, '\n', nbytes - (dst - src))) != NULL)
- {
- truelen++;
- dst++;
- }
-
- if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, truelen)) == NULL)
- goto error;
-
- if ((dst = (unsigned char *) GlobalLock (htext)) == NULL)
- goto error;
-
- /* convert to CRLF line endings expected by clipboard */
- while (1)
- {
- unsigned char *next;
- /* copy next line or remaining bytes including '\0' */
- next = _memccpy (dst, src, '\n', nbytes);
- if (next)
- {
- /* copied one line ending with '\n' */
- int copied = next - dst;
- nbytes -= copied;
- src += copied;
- /* insert '\r' before '\n' */
- next[-1] = '\r';
- next[0] = '\n';
- dst = next + 1;
- }
- else
- /* copied remaining partial line -> now finished */
- break;
- }
-
- GlobalUnlock (htext);
-
- if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL))
- goto error;
-
- ok = EmptyClipboard () && SetClipboardData (CF_TEXT, htext);
-
- CloseClipboard ();
-
- if (ok) goto done;
-
- error:
-
- ok = FALSE;
- if (htext) GlobalFree (htext);
-
- done:
- UNBLOCK_INPUT;
-
- return (ok ? string : Qnil);
-}
-
-DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, Sw32_get_clipboard_data, 0, 1, 0,
- "This gets the clipboard data in text format.")
- (frame)
- Lisp_Object frame;
-{
- HANDLE htext;
- Lisp_Object ret = Qnil;
-
- if (!NILP (frame))
- CHECK_LIVE_FRAME (frame, 0);
-
- BLOCK_INPUT;
-
- if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL))
- goto done;
-
- if ((htext = GetClipboardData (CF_TEXT)) == NULL)
- goto closeclip;
-
- {
- unsigned char *src;
- unsigned char *dst;
- int nbytes;
- int truelen;
-
- if ((src = (unsigned char *) GlobalLock (htext)) == NULL)
- goto closeclip;
-
- nbytes = strlen (src);
-
- /* need to know final size after '\r' chars are removed because
- we can't change the string size manually, and doing an extra
- copy is silly */
-
- truelen = nbytes;
- dst = src;
- /* avoid using strchr because it recomputes the length everytime */
- while ((dst = memchr (dst, '\r', nbytes - (dst - src))) != NULL)
- {
- truelen--;
- dst++;
- }
-
- ret = make_uninit_string (truelen);
-
- /* convert CRLF line endings (the standard CF_TEXT clipboard
- format) to LF endings as used internally by Emacs */
-
- dst = XSTRING (ret)->data;
- while (1)
- {
- unsigned char *next;
- /* copy next line or remaining bytes excluding '\0' */
- next = _memccpy (dst, src, '\r', nbytes);
- if (next)
- {
- /* copied one line ending with '\r' */
- int copied = next - dst;
- nbytes -= copied;
- dst += copied - 1; /* overwrite '\r' */
- src += copied;
- }
- else
- /* copied remaining partial line -> now finished */
- break;
- }
-
- GlobalUnlock (htext);
- }
-
- closeclip:
- CloseClipboard ();
-
- done:
- UNBLOCK_INPUT;
-
- return (ret);
-}
-
-/* Support checking for a clipboard selection. */
-
-DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
- 0, 1, 0,
- "Whether there is an owner for the given X Selection.\n\
-The arg should be the name of the selection in question, typically one of\n\
-the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
-\(Those are literal upper-case symbol names, since that's what X expects.)\n\
-For convenience, the symbol nil is the same as `PRIMARY',\n\
-and t is the same as `SECONDARY'.")
- (selection)
- Lisp_Object selection;
-{
- CHECK_SYMBOL (selection, 0);
-
- /* Return nil for PRIMARY and SECONDARY selections; for CLIPBOARD, check
- if the clipboard currently has valid text format contents. */
-
- if (EQ (selection, QCLIPBOARD))
- {
- Lisp_Object val = Qnil;
-
- if (OpenClipboard (NULL))
- {
- int format = 0;
- while (format = EnumClipboardFormats (format))
- if (format == CF_TEXT)
- {
- val = Qt;
- break;
- }
- CloseClipboard ();
- }
- return val;
- }
- return Qnil;
-}
-
-void
-syms_of_w32select ()
-{
-#if 0
- defsubr (&Sw32_open_clipboard);
- defsubr (&Sw32_empty_clipboard);
- defsubr (&Sw32_close_clipboard);
-#endif
- defsubr (&Sw32_set_clipboard_data);
- defsubr (&Sw32_get_clipboard_data);
- defsubr (&Sx_selection_exists_p);
-
- QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
-}
diff --git a/src/w32term.c b/src/w32term.c
deleted file mode 100644
index 4706ac4fa43..00000000000
--- a/src/w32term.c
+++ /dev/null
@@ -1,3891 +0,0 @@
-/* Implementation of GUI terminal on the Win32 API.
- Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Added by Kevin Gallo */
-
-#include <signal.h>
-#include <config.h>
-#include <stdio.h>
-#include "lisp.h"
-#include "blockinput.h"
-
-#include <w32term.h>
-
-#include "systty.h"
-#include "systime.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <setjmp.h>
-#include <sys/stat.h>
-
-#include "frame.h"
-#include "dispextern.h"
-#include "termhooks.h"
-#include "termopts.h"
-#include "termchar.h"
-#include "gnu.h"
-#include "disptab.h"
-#include "buffer.h"
-#include "window.h"
-#include "keyboard.h"
-#include "intervals.h"
-
-extern void free_frame_menubar ();
-
-extern Lisp_Object Vwindow_system;
-
-#define x_any_window_to_frame x_window_to_frame
-#define x_top_window_to_frame x_window_to_frame
-
-
-/* This is display since w32 does not support multiple ones. */
-struct w32_display_info one_w32_display_info;
-
-/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
- one for each element of w32_display_list and in the same order.
- NAME is the name of the frame.
- FONT-LIST-CACHE records previous values returned by x-list-fonts. */
-Lisp_Object w32_display_name_list;
-
-/* Frame being updated by update_frame. This is declared in term.c.
- This is set by update_begin and looked at by all the
- w32 functions. It is zero while not inside an update.
- In that case, the w32 functions assume that `selected_frame'
- is the frame to apply to. */
-extern struct frame *updating_frame;
-
-/* This is a frame waiting to be autoraised, within w32_read_socket. */
-struct frame *pending_autoraise_frame;
-
-/* During an update, maximum vpos for ins/del line operations to affect. */
-
-static int flexlines;
-
-/* During an update, nonzero if chars output now should be highlighted. */
-
-static int highlight;
-
-/* Nominal cursor position -- where to draw output.
- During an update, these are different from the cursor-box position. */
-
-static int curs_x;
-static int curs_y;
-
-DWORD dwWinThreadId = 0;
-HANDLE hWinThread = NULL;
-DWORD dwMainThreadId = 0;
-HANDLE hMainThread = NULL;
-
-/* Mouse movement. */
-
-/* Where the mouse was last time we reported a mouse event. */
-static FRAME_PTR last_mouse_frame;
-static RECT last_mouse_glyph;
-
-Lisp_Object Vw32_num_mouse_buttons;
-
-Lisp_Object Vw32_swap_mouse_buttons;
-
-/* The scroll bar in which the last motion event occurred.
-
- If the last motion event occurred in a scroll bar, we set this
- so w32_mouse_position can know whether to report a scroll bar motion or
- an ordinary motion.
-
- If the last motion event didn't occur in a scroll bar, we set this
- to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
-Lisp_Object last_mouse_scroll_bar;
-int last_mouse_scroll_bar_pos;
-
-/* This is a hack. We would really prefer that w32_mouse_position would
- return the time associated with the position it returns, but there
- doesn't seem to be any way to wrest the timestamp from the server
- along with the position query. So, we just keep track of the time
- of the last movement we received, and return that in hopes that
- it's somewhat accurate. */
-Time last_mouse_movement_time;
-
-/* Incremented by w32_read_socket whenever it really tries to read events. */
-#ifdef __STDC__
-static int volatile input_signal_count;
-#else
-static int input_signal_count;
-#endif
-
-extern Lisp_Object Vcommand_line_args, Vsystem_name;
-
-extern Lisp_Object Qface, Qmouse_face;
-
-extern int errno;
-
-/* A mask of extra modifier bits to put into every keyboard char. */
-extern int extra_keyboard_modifiers;
-
-static Lisp_Object Qvendor_specific_keysyms;
-
-void w32_delete_display ();
-
-static void redraw_previous_char ();
-static void redraw_following_char ();
-static unsigned int w32_get_modifiers ();
-
-static int fast_find_position ();
-static void note_mouse_highlight ();
-static void clear_mouse_face ();
-static void show_mouse_face ();
-static void do_line_dance ();
-
-static int w32_cursor_to ();
-static int w32_clear_end_of_line ();
-
-#if 0
-/* This is a function useful for recording debugging information
- about the sequence of occurrences in this file. */
-
-struct record
-{
- char *locus;
- int type;
-};
-
-struct record event_record[100];
-
-int event_record_index;
-
-record_event (locus, type)
- char *locus;
- int type;
-{
- if (event_record_index == sizeof (event_record) / sizeof (struct record))
- event_record_index = 0;
-
- event_record[event_record_index].locus = locus;
- event_record[event_record_index].type = type;
- event_record_index++;
-}
-
-#endif /* 0 */
-
-/* Return the struct w32_display_info. */
-
-struct w32_display_info *
-w32_display_info_for_display ()
-{
- return (&one_w32_display_info);
-}
-
-void
-w32_fill_rect (f, _hdc, pix, lprect)
- FRAME_PTR f;
- HDC _hdc;
- COLORREF pix;
- RECT * lprect;
-{
- HDC hdc;
- HBRUSH hb;
- RECT rect;
-
- if (_hdc)
- hdc = _hdc;
- else
- {
- if (!f) return;
- hdc = get_frame_dc (f);
- }
-
- hb = CreateSolidBrush (pix);
- FillRect (hdc, lprect, hb);
- DeleteObject (hb);
-
- if (!_hdc)
- release_frame_dc (f, hdc);
-}
-
-void
-w32_clear_window (f)
- FRAME_PTR f;
-{
- RECT rect;
-
- GetClientRect (FRAME_W32_WINDOW (f), &rect);
- w32_clear_rect (f, NULL, &rect);
-}
-
-
-/* Starting and ending updates.
-
- These hooks are called by update_frame at the beginning and end
- of a frame update. We record in `updating_frame' the identity
- of the frame being updated, so that the w32_... functions do not
- need to take a frame as argument. Most of the w32_... functions
- should never be called except during an update, the only exceptions
- being w32_cursor_to, w32_write_glyphs and w32_reassert_line_highlight. */
-
-static
-w32_update_begin (f)
- struct frame *f;
-{
- if (f == 0)
- abort ();
-
- flexlines = f->height;
- highlight = 0;
-
- BLOCK_INPUT;
-
- /* Regenerate display palette before drawing if list of requested
- colors has changed. */
- if (FRAME_W32_DISPLAY_INFO (f)->regen_palette)
- {
- w32_regenerate_palette (f);
- FRAME_W32_DISPLAY_INFO (f)->regen_palette = FALSE;
- }
-
- if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
- {
- /* Don't do highlighting for mouse motion during the update. */
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 1;
-
- /* If the frame needs to be redrawn,
- simply forget about any prior mouse highlighting. */
- if (FRAME_GARBAGED_P (f))
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = Qnil;
-
- if (!NILP (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window))
- {
- int firstline, lastline, i;
- struct window *w = XWINDOW (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window);
-
- /* Find the first, and the last+1, lines affected by redisplay. */
- for (firstline = 0; firstline < f->height; firstline++)
- if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
- break;
-
- lastline = f->height;
- for (i = f->height - 1; i >= 0; i--)
- {
- if (FRAME_DESIRED_GLYPHS (f)->enable[i])
- break;
- else
- lastline = i;
- }
-
- /* Can we tell that this update does not affect the window
- where the mouse highlight is? If so, no need to turn off.
- Likewise, don't do anything if the frame is garbaged;
- in that case, the FRAME_CURRENT_GLYPHS that we would use
- are all wrong, and we will redisplay that line anyway. */
- if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
- || lastline < XFASTINT (w->top)))
- clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
- }
- }
-
- UNBLOCK_INPUT;
-}
-
-static
-w32_update_end (f)
- struct frame *f;
-{
- BLOCK_INPUT;
-
- do_line_dance ();
- x_display_cursor (f, 1);
-
- if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
-
- UNBLOCK_INPUT;
-}
-
-/* This is called after a redisplay on frame F. */
-
-static
-w32_frame_up_to_date (f)
- FRAME_PTR f;
-{
- if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc
- || f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
- {
- note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame,
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x,
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y);
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
- }
-}
-
-/* External interface to control of standout mode.
- Call this when about to modify line at position VPOS
- and not change whether it is highlighted. */
-
-w32_reassert_line_highlight (new, vpos)
- int new, vpos;
-{
- highlight = new;
-}
-
-/* Call this when about to modify line at position VPOS
- and change whether it is highlighted. */
-
-static
-w32_change_line_highlight (new_highlight, vpos, first_unused_hpos)
- int new_highlight, vpos, first_unused_hpos;
-{
- highlight = new_highlight;
- w32_cursor_to (vpos, 0);
- w32_clear_end_of_line (updating_frame->width);
-}
-
-/* This is used when starting Emacs and when restarting after suspend.
- When starting Emacs, no window is mapped. And nothing must be done
- to Emacs's own window if it is suspended (though that rarely happens). */
-
-static
-w32_set_terminal_modes ()
-{
-}
-
-/* This is called when exiting or suspending Emacs.
- Exiting will make the W32 windows go away, and suspending
- requires no action. */
-
-static
-w32_reset_terminal_modes ()
-{
-}
-
-/* Set the nominal cursor position of the frame.
- This is where display update commands will take effect.
- This does not affect the place where the cursor-box is displayed. */
-
-static int
-w32_cursor_to (row, col)
- register int row, col;
-{
- int orow = row;
-
- curs_x = col;
- curs_y = row;
-
- if (updating_frame == 0)
- {
- BLOCK_INPUT;
- x_display_cursor (selected_frame, 1);
- UNBLOCK_INPUT;
- }
-}
-
-/* Display a sequence of N glyphs found at GP.
- WINDOW is the window to output to. LEFT and TOP are starting coords.
- HL is 1 if this text is highlighted, 2 if the cursor is on it,
- 3 if should appear in its mouse-face.
- JUST_FOREGROUND if 1 means draw only the foreground;
- don't alter the background.
-
- FONT is the default font to use (for glyphs whose font-code is 0).
-
- Since the display generation code is responsible for calling
- compute_char_face and compute_glyph_face on everything it puts in
- the display structure, we can assume that the face code on each
- glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
- to which we can actually apply intern_face.
- Call this function with input blocked. */
-
-static void
-dumpglyphs (f, left, top, gp, n, hl, just_foreground)
- struct frame *f;
- int left, top;
- register GLYPH *gp; /* Points to first GLYPH. */
- register int n; /* Number of glyphs to display. */
- int hl;
- int just_foreground;
-{
- /* Holds characters to be displayed. */
- char *buf = (char *) alloca (f->width * sizeof (*buf));
- register char *cp; /* Steps through buf[]. */
- register int tlen = GLYPH_TABLE_LENGTH;
- register Lisp_Object *tbase = GLYPH_TABLE_BASE;
- Window window = FRAME_W32_WINDOW (f);
- int orig_left = left;
- HDC hdc;
-
- hdc = get_frame_dc (f);
-
- while (n > 0)
- {
- /* Get the face-code of the next GLYPH. */
- int cf, len;
- int g = *gp;
-
- GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
- cf = FAST_GLYPH_FACE (g);
-
- /* Find the run of consecutive glyphs with the same face-code.
- Extract their character codes into BUF. */
- cp = buf;
- while (n > 0)
- {
- g = *gp;
- GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
- if (FAST_GLYPH_FACE (g) != cf)
- break;
-
- *cp++ = FAST_GLYPH_CHAR (g);
- --n;
- ++gp;
- }
-
- /* LEN gets the length of the run. */
- len = cp - buf;
-
- /* Now output this run of chars, with the font and pixel values
- determined by the face code CF. */
- {
- struct face *face = FRAME_DEFAULT_FACE (f);
- XFontStruct *font = FACE_FONT (face);
- int stippled = 0;
- COLORREF fg;
- COLORREF bg;
-
- /* HL = 3 means use a mouse face previously chosen. */
- if (hl == 3)
- cf = FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id;
-
- /* First look at the face of the text itself. */
- if (cf != 0)
- {
- /* It's possible for the display table to specify
- a face code that is out of range. Use 0 in that case. */
- if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
- || FRAME_COMPUTED_FACES (f) [cf] == 0)
- cf = 0;
-
- if (cf == 1)
- face = FRAME_MODE_LINE_FACE (f);
- else
- face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
- font = FACE_FONT (face);
- if (FACE_STIPPLE (face))
- stippled = 1;
- }
-
- /* Then comes the distinction between modeline and normal text. */
- else if (hl == 0)
- ;
- else if (hl == 1)
- {
- face = FRAME_MODE_LINE_FACE (f);
- font = FACE_FONT (face);
- if (FACE_STIPPLE (face))
- stippled = 1;
- }
-
- fg = face->foreground;
- bg = face->background;
-
- /* Now override that if the cursor's on this character. */
- if (hl == 2)
- {
- /* The cursor overrides stippling. */
- stippled = 0;
-
- if ((!face->font
- || face->font == (XFontStruct *) FACE_DEFAULT
- || face->font == f->output_data.w32->font)
- && face->background == f->output_data.w32->background_pixel
- && face->foreground == f->output_data.w32->foreground_pixel)
- {
- bg = f->output_data.w32->cursor_pixel;
- fg = face->background;
- }
- /* Cursor on non-default face: must merge. */
- else
- {
- bg = f->output_data.w32->cursor_pixel;
- fg = face->background;
- /* If the glyph would be invisible,
- try a different foreground. */
- if (fg == bg)
- fg = face->foreground;
- if (fg == bg)
- fg = f->output_data.w32->cursor_foreground_pixel;
- if (fg == bg)
- fg = face->foreground;
- /* Make sure the cursor is distinct from text in this face. */
- if (bg == face->background
- && fg == face->foreground)
- {
- bg = face->foreground;
- fg = face->background;
- }
- }
- }
-
- if (font == (XFontStruct *) FACE_DEFAULT)
- font = f->output_data.w32->font;
-
- SetBkMode (hdc, just_foreground ? TRANSPARENT : OPAQUE);
-
- SetTextColor (hdc, fg);
- SetBkColor (hdc, bg);
-
- SelectObject (hdc, font->hfont);
-
- TextOut (hdc, left, top, buf, len);
-
- if (!just_foreground)
- {
- /* Clear the rest of the line's height. */
- if (f->output_data.w32->line_height != FONT_HEIGHT (font))
- w32_fill_area (f, hdc, bg,
- left,
- top + FONT_HEIGHT (font),
- FONT_WIDTH (font) * len,
- f->output_data.w32->line_height - FONT_HEIGHT (font));
- }
-
- {
- int underline_position = 1;
-
- if (font->tm.tmDescent <= underline_position)
- underline_position = font->tm.tmDescent - 1;
-
- if (face->underline)
- w32_fill_area (f, hdc, fg,
- left, (top
- + FONT_BASE (font)
- + underline_position),
- len * FONT_WIDTH (font), 1);
- }
-
- left += len * FONT_WIDTH (font);
- }
- }
-
- release_frame_dc (f, hdc);
-}
-
-
-/* Output some text at the nominal frame cursor position.
- Advance the cursor over the text.
- Output LEN glyphs at START.
-
- `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
- controls the pixel values used for foreground and background. */
-
-static
-w32_write_glyphs (start, len)
- register GLYPH *start;
- int len;
-{
- register int temp_length;
- struct frame *f;
-
- BLOCK_INPUT;
-
- do_line_dance ();
- f = updating_frame;
- if (f == 0)
- {
- f = selected_frame;
- /* If not within an update,
- output at the frame's visible cursor. */
- curs_x = f->cursor_x;
- curs_y = f->cursor_y;
- }
-
- dumpglyphs (f,
- CHAR_TO_PIXEL_COL (f, curs_x),
- CHAR_TO_PIXEL_ROW (f, curs_y),
- start, len, highlight, 0);
-
- /* If we drew on top of the cursor, note that it is turned off. */
- if (curs_y == f->phys_cursor_y
- && curs_x <= f->phys_cursor_x
- && curs_x + len > f->phys_cursor_x)
- f->phys_cursor_x = -1;
-
- if (updating_frame == 0)
- {
- f->cursor_x += len;
- x_display_cursor (f, 1);
- f->cursor_x -= len;
- }
- else
- curs_x += len;
-
- UNBLOCK_INPUT;
-}
-
-/* Clear to the end of the line.
- Erase the current text line from the nominal cursor position (inclusive)
- to column FIRST_UNUSED (exclusive). The idea is that everything
- from FIRST_UNUSED onward is already erased. */
-
-static
-w32_clear_end_of_line (first_unused)
- register int first_unused;
-{
- struct frame *f = updating_frame;
-
- if (f == 0)
- abort ();
-
- if (curs_y < 0 || curs_y >= f->height)
- return 1;
- if (first_unused <= 0)
- return 1;
-
- if (first_unused >= f->width)
- first_unused = f->width;
-
- BLOCK_INPUT;
-
- do_line_dance ();
-
- /* Notice if the cursor will be cleared by this operation. */
- if (curs_y == f->phys_cursor_y
- && curs_x <= f->phys_cursor_x
- && f->phys_cursor_x < first_unused)
- f->phys_cursor_x = -1;
-
- w32_clear_area (f, NULL,
- CHAR_TO_PIXEL_COL (f, curs_x),
- CHAR_TO_PIXEL_ROW (f, curs_y),
- FONT_WIDTH (f->output_data.w32->font) * (first_unused - curs_x),
- f->output_data.w32->line_height);
-
- UNBLOCK_INPUT;
-}
-
-static
-w32_clear_frame ()
-{
- struct frame *f = updating_frame;
-
- if (f == 0)
- f = selected_frame;
-
- f->phys_cursor_x = -1; /* Cursor not visible. */
- curs_x = 0; /* Nominal cursor position is top left. */
- curs_y = 0;
-
- BLOCK_INPUT;
-
- w32_clear_window (f);
-
- /* We have to clear the scroll bars, too. If we have changed
- colors or something like that, then they should be notified. */
- x_scroll_bar_clear (f);
-
- UNBLOCK_INPUT;
-}
-
-/* Make audible bell. */
-
-w32_ring_bell ()
-{
- BLOCK_INPUT;
-
- if (visible_bell)
- FlashWindow (FRAME_W32_WINDOW (selected_frame), FALSE);
- else
- w32_sys_ring_bell ();
-
- UNBLOCK_INPUT;
-
- return 1;
-}
-
-/* Insert and delete character.
- These are not supposed to be used because we are supposed to turn
- off the feature of using them. */
-
-static
-w32_insert_glyphs (start, len)
- register char *start;
- register int len;
-{
- abort ();
-}
-
-static
-w32_delete_glyphs (n)
- register int n;
-{
- abort ();
-}
-
-/* Specify how many text lines, from the top of the window,
- should be affected by insert-lines and delete-lines operations.
- This, and those operations, are used only within an update
- that is bounded by calls to w32_update_begin and w32_update_end. */
-
-static
-w32_set_terminal_window (n)
- register int n;
-{
- if (updating_frame == 0)
- abort ();
-
- if ((n <= 0) || (n > updating_frame->height))
- flexlines = updating_frame->height;
- else
- flexlines = n;
-}
-
-/* These variables need not be per frame
- because redisplay is done on a frame-by-frame basis
- and the line dance for one frame is finished before
- anything is done for another frame. */
-
-/* Array of line numbers from cached insert/delete operations.
- line_dance[i] is the old position of the line that we want
- to move to line i, or -1 if we want a blank line there. */
-static int *line_dance;
-
-/* Allocated length of that array. */
-static int line_dance_len;
-
-/* Flag indicating whether we've done any work. */
-static int line_dance_in_progress;
-
-/* Perform an insert-lines or delete-lines operation,
- inserting N lines or deleting -N lines at vertical position VPOS. */
-w32_ins_del_lines (vpos, n)
- int vpos, n;
-{
- register int fence, i;
-
- if (vpos >= flexlines)
- return 1;
-
- if (!line_dance_in_progress)
- {
- int ht = updating_frame->height;
- if (ht > line_dance_len)
- {
- line_dance = (int *)xrealloc (line_dance, ht * sizeof (int));
- line_dance_len = ht;
- }
- for (i = 0; i < ht; ++i) line_dance[i] = i;
- line_dance_in_progress = 1;
- }
- if (n >= 0)
- {
- if (n > flexlines - vpos)
- n = flexlines - vpos;
- fence = vpos + n;
- for (i = flexlines; --i >= fence;)
- line_dance[i] = line_dance[i-n];
- for (i = fence; --i >= vpos;)
- line_dance[i] = -1;
- }
- else
- {
- n = -n;
- if (n > flexlines - vpos)
- n = flexlines - vpos;
- fence = flexlines - n;
- for (i = vpos; i < fence; ++i)
- line_dance[i] = line_dance[i + n];
- for (i = fence; i < flexlines; ++i)
- line_dance[i] = -1;
- }
-}
-
-/* Here's where we actually move the pixels around.
- Must be called with input blocked. */
-static void
-do_line_dance ()
-{
- register int i, j, distance;
- register struct frame *f;
- int ht;
- int intborder;
- HDC hdc;
-
- /* Must check this flag first. If it's not set, then not only is the
- array uninitialized, but we might not even have a frame. */
- if (!line_dance_in_progress)
- return;
-
- f = updating_frame;
- if (f == 0)
- abort ();
-
- ht = f->height;
- intborder = f->output_data.w32->internal_border_width;
-
- x_display_cursor (updating_frame, 0);
-
- hdc = get_frame_dc (f);
-
- for (i = 0; i < ht; ++i)
- if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
- {
- for (j = i; (j < ht && line_dance[j] != -1
- && line_dance[j]-j == distance); ++j);
- /* Copy [i,j) upward from [i+distance, j+distance) */
- BitBlt (hdc,
- intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
- f->width * FONT_WIDTH (f->output_data.w32->font),
- (j-i) * f->output_data.w32->line_height,
- hdc,
- intborder, CHAR_TO_PIXEL_ROW (f, i),
- SRCCOPY);
- i = j-1;
- }
-
- for (i = ht; --i >=0; )
- if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0)
- {
- for (j = i; (--j >= 0 && line_dance[j] != -1
- && line_dance[j]-j == distance););
- /* Copy (j, i] downward from (j+distance, i+distance] */
- BitBlt (hdc,
- intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
- f->width * FONT_WIDTH (f->output_data.w32->font),
- (i-j) * f->output_data.w32->line_height,
- hdc,
- intborder, CHAR_TO_PIXEL_ROW (f, j+1),
- SRCCOPY);
- i = j+1;
- }
-
- release_frame_dc (f, hdc);
-
- for (i = 0; i < ht; ++i)
- if (line_dance[i] == -1)
- {
- for (j = i; j < ht && line_dance[j] == -1; ++j);
- /* Clear [i,j) */
- w32_clear_area (f, NULL,
- intborder,
- CHAR_TO_PIXEL_ROW (f, i),
- f->width * FONT_WIDTH (f->output_data.w32->font),
- (j-i) * f->output_data.w32->line_height);
- i = j-1;
- }
- line_dance_in_progress = 0;
-}
-
-/* Support routines for exposure events. */
-static void clear_cursor ();
-
-/* Output into a rectangle of a window (for frame F)
- the characters in f->phys_lines that overlap that rectangle.
- TOP and LEFT are the position of the upper left corner of the rectangle.
- ROWS and COLS are the size of the rectangle.
- Call this function with input blocked. */
-
-void
-dumprectangle (f, left, top, cols, rows)
- struct frame *f;
- register int left, top, cols, rows;
-{
- register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
- int cursor_cleared = 0;
- int bottom, right;
- register int y;
-
- if (FRAME_GARBAGED_P (f))
- return;
-
- /* Express rectangle as four edges, instead of position-and-size. */
- bottom = top + rows;
- right = left + cols;
-
- /* Convert rectangle edges in pixels to edges in chars.
- Round down for left and top, up for right and bottom. */
- top = PIXEL_TO_CHAR_ROW (f, top);
- left = PIXEL_TO_CHAR_COL (f, left);
- bottom += (f->output_data.w32->line_height - 1);
- right += (FONT_WIDTH (f->output_data.w32->font) - 1);
- bottom = PIXEL_TO_CHAR_ROW (f, bottom);
- right = PIXEL_TO_CHAR_COL (f, right);
-
- /* Clip the rectangle to what can be visible. */
- if (left < 0)
- left = 0;
- if (top < 0)
- top = 0;
- if (right > f->width)
- right = f->width;
- if (bottom > f->height)
- bottom = f->height;
-
- /* Get size in chars of the rectangle. */
- cols = right - left;
- rows = bottom - top;
-
- /* If rectangle has zero area, return. */
- if (rows <= 0) return;
- if (cols <= 0) return;
-
- /* Turn off the cursor if it is in the rectangle.
- We will turn it back on afterward. */
- if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
- && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
- {
- clear_cursor (f);
- cursor_cleared = 1;
- }
-
- /* Display the text in the rectangle, one text line at a time. */
-
- for (y = top; y < bottom; y++)
- {
- GLYPH *line = &active_frame->glyphs[y][left];
-
- if (! active_frame->enable[y] || left > active_frame->used[y])
- continue;
-
- dumpglyphs (f,
- CHAR_TO_PIXEL_COL (f, left),
- CHAR_TO_PIXEL_ROW (f, y),
- line, min (cols, active_frame->used[y] - left),
- active_frame->highlight[y], 0);
- }
-
- /* Turn the cursor on if we turned it off. */
-
- if (cursor_cleared)
- x_display_cursor (f, 1);
-}
-
-static void
-frame_highlight (f)
- struct frame *f;
-{
- x_display_cursor (f, 1);
-}
-
-static void
-frame_unhighlight (f)
- struct frame *f;
-{
- x_display_cursor (f, 1);
-}
-
-static void w32_frame_rehighlight ();
-static void x_frame_rehighlight ();
-
-/* The focus has changed. Update the frames as necessary to reflect
- the new situation. Note that we can't change the selected frame
- here, because the Lisp code we are interrupting might become confused.
- Each event gets marked with the frame in which it occurred, so the
- Lisp code can tell when the switch took place by examining the events. */
-
-void
-x_new_focus_frame (dpyinfo, frame)
- struct w32_display_info *dpyinfo;
- struct frame *frame;
-{
- struct frame *old_focus = dpyinfo->w32_focus_frame;
- int events_enqueued = 0;
-
- if (frame != dpyinfo->w32_focus_frame)
- {
- /* Set this before calling other routines, so that they see
- the correct value of w32_focus_frame. */
- dpyinfo->w32_focus_frame = frame;
-
- if (old_focus && old_focus->auto_lower)
- x_lower_frame (old_focus);
-
- if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
- pending_autoraise_frame = dpyinfo->w32_focus_frame;
- else
- pending_autoraise_frame = 0;
- }
-
- x_frame_rehighlight (dpyinfo);
-}
-
-/* Handle an event saying the mouse has moved out of an Emacs frame. */
-
-void
-x_mouse_leave (dpyinfo)
- struct w32_display_info *dpyinfo;
-{
- x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
-}
-
-/* The focus has changed, or we have redirected a frame's focus to
- another frame (this happens when a frame uses a surrogate
- minibuffer frame). Shift the highlight as appropriate.
-
- The FRAME argument doesn't necessarily have anything to do with which
- frame is being highlighted or unhighlighted; we only use it to find
- the appropriate display info. */
-static void
-w32_frame_rehighlight (frame)
- struct frame *frame;
-{
- x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
-}
-
-static void
-x_frame_rehighlight (dpyinfo)
- struct w32_display_info *dpyinfo;
-{
- struct frame *old_highlight = dpyinfo->w32_highlight_frame;
-
- if (dpyinfo->w32_focus_frame)
- {
- dpyinfo->w32_highlight_frame
- = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
- ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
- : dpyinfo->w32_focus_frame);
- if (! FRAME_LIVE_P (dpyinfo->w32_highlight_frame))
- {
- FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
- dpyinfo->w32_highlight_frame = dpyinfo->w32_focus_frame;
- }
- }
- else
- dpyinfo->w32_highlight_frame = 0;
-
- if (dpyinfo->w32_highlight_frame != old_highlight)
- {
- if (old_highlight)
- frame_unhighlight (old_highlight);
- if (dpyinfo->w32_highlight_frame)
- frame_highlight (dpyinfo->w32_highlight_frame);
- }
-}
-
-/* Keyboard processing - modifier keys, etc. */
-
-/* Convert a keysym to its name. */
-
-char *
-x_get_keysym_name (keysym)
- int keysym;
-{
- /* Make static so we can always return it */
- static char value[100];
-
- BLOCK_INPUT;
- GetKeyNameText(keysym, value, 100);
- UNBLOCK_INPUT;
-
- return value;
-}
-
-/* Mouse clicks and mouse movement. Rah. */
-
-/* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
- glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
- that the glyph at X, Y occupies, if BOUNDS != 0.
- If NOCLIP is nonzero, do not force the value into range. */
-
-void
-pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
- FRAME_PTR f;
- register int pix_x, pix_y;
- register int *x, *y;
- RECT *bounds;
- int noclip;
-{
- /* Support tty mode: if Vwindow_system is nil, behave correctly. */
- if (NILP (Vwindow_system))
- {
- *x = pix_x;
- *y = pix_y;
- return;
- }
-
- /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
- even for negative values. */
- if (pix_x < 0)
- pix_x -= FONT_WIDTH ((f)->output_data.w32->font) - 1;
- if (pix_y < 0)
- pix_y -= (f)->output_data.w32->line_height - 1;
-
- pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
- pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
-
- if (bounds)
- {
- bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
- bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
- bounds->right = bounds->left + FONT_WIDTH (f->output_data.w32->font) - 1;
- bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
- }
-
- if (!noclip)
- {
- if (pix_x < 0)
- pix_x = 0;
- else if (pix_x > f->width)
- pix_x = f->width;
-
- if (pix_y < 0)
- pix_y = 0;
- else if (pix_y > f->height)
- pix_y = f->height;
- }
-
- *x = pix_x;
- *y = pix_y;
-}
-
-void
-glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
- FRAME_PTR f;
- register int x, y;
- register int *pix_x, *pix_y;
-{
- /* Support tty mode: if Vwindow_system is nil, behave correctly. */
- if (NILP (Vwindow_system))
- {
- *pix_x = x;
- *pix_y = y;
- return;
- }
-
- *pix_x = CHAR_TO_PIXEL_COL (f, x);
- *pix_y = CHAR_TO_PIXEL_ROW (f, y);
-}
-
-BOOL
-parse_button (message, pbutton, pup)
- int message;
- int * pbutton;
- int * pup;
-{
- int button = 0;
- int up = 0;
-
- switch (message)
- {
- case WM_LBUTTONDOWN:
- button = 0;
- up = 0;
- break;
- case WM_LBUTTONUP:
- button = 0;
- up = 1;
- break;
- case WM_MBUTTONDOWN:
- if (NILP (Vw32_swap_mouse_buttons))
- button = 1;
- else
- button = 2;
- up = 0;
- break;
- case WM_MBUTTONUP:
- if (NILP (Vw32_swap_mouse_buttons))
- button = 1;
- else
- button = 2;
- up = 1;
- break;
- case WM_RBUTTONDOWN:
- if (NILP (Vw32_swap_mouse_buttons))
- button = 2;
- else
- button = 1;
- up = 0;
- break;
- case WM_RBUTTONUP:
- if (NILP (Vw32_swap_mouse_buttons))
- button = 2;
- else
- button = 1;
- up = 1;
- break;
- default:
- return (FALSE);
- }
-
- if (pup) *pup = up;
- if (pbutton) *pbutton = button;
-
- return (TRUE);
-}
-
-
-/* Prepare a mouse-event in *RESULT for placement in the input queue.
-
- If the event is a button press, then note that we have grabbed
- the mouse. */
-
-static void
-construct_mouse_click (result, msg, f)
- struct input_event *result;
- W32Msg *msg;
- struct frame *f;
-{
- int button;
- int up;
-
- parse_button (msg->msg.message, &button, &up);
-
- /* Make the event type no_event; we'll change that when we decide
- otherwise. */
- result->kind = mouse_click;
- result->code = button;
- result->timestamp = msg->msg.time;
- result->modifiers = (msg->dwModifiers
- | (up
- ? up_modifier
- : down_modifier));
-
- {
- int row, column;
-
- XSETINT (result->x, LOWORD (msg->msg.lParam));
- XSETINT (result->y, HIWORD (msg->msg.lParam));
- XSETFRAME (result->frame_or_window, f);
- }
-}
-
-
-/* Function to report a mouse movement to the mainstream Emacs code.
- The input handler calls this.
-
- We have received a mouse movement event, which is given in *event.
- If the mouse is over a different glyph than it was last time, tell
- the mainstream emacs code by setting mouse_moved. If not, ask for
- another motion event, so we can check again the next time it moves. */
-
-static void
-note_mouse_movement (frame, msg)
- FRAME_PTR frame;
- MSG *msg;
-{
- last_mouse_movement_time = msg->time;
-
- if (msg->hwnd != FRAME_W32_WINDOW (frame))
- {
- frame->mouse_moved = 1;
- last_mouse_scroll_bar = Qnil;
-
- note_mouse_highlight (frame, -1, -1);
- }
-
- /* Has the mouse moved off the glyph it was on at the last sighting? */
- else if (LOWORD (msg->lParam) < last_mouse_glyph.left
- || LOWORD (msg->lParam) > last_mouse_glyph.right
- || HIWORD (msg->lParam) < last_mouse_glyph.top
- || HIWORD (msg->lParam) > last_mouse_glyph.bottom)
- {
- frame->mouse_moved = 1;
- last_mouse_scroll_bar = Qnil;
-
- note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
- }
-}
-
-/* This is used for debugging, to turn off note_mouse_highlight. */
-static int disable_mouse_highlight;
-
-/* Take proper action when the mouse has moved to position X, Y on frame F
- as regards highlighting characters that have mouse-face properties.
- Also dehighlighting chars where the mouse was before.
- X and Y can be negative or out of range. */
-
-static void
-note_mouse_highlight (f, x, y)
- FRAME_PTR f;
- int x, y;
-{
- int row, column, portion;
- RECT new_glyph;
- Lisp_Object window;
- struct window *w;
-
- if (disable_mouse_highlight)
- return;
-
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
-
- if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer)
- return;
-
- if (gc_in_progress)
- {
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
- return;
- }
-
- /* Find out which glyph the mouse is on. */
- pixel_to_glyph_coords (f, x, y, &column, &row,
- &new_glyph, FRAME_W32_DISPLAY_INFO (f)->grabbed);
-
- /* Which window is that in? */
- window = window_from_coordinates (f, column, row, &portion);
- w = XWINDOW (window);
-
- /* If we were displaying active text in another window, clear that. */
- if (! EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window))
- clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
-
- /* Are we in a window whose display is up to date?
- And verify the buffer's text has not changed. */
- if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
- && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
- && EQ (w->window_end_valid, w->buffer)
- && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer))
- && w->last_overlay_modified == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))
- {
- int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
- int i, pos;
-
- /* Find which buffer position the mouse corresponds to. */
- for (i = column; i >= 0; i--)
- if (ptr[i] > 0)
- break;
- pos = ptr[i];
- /* Is it outside the displayed active region (if any)? */
- if (pos <= 0)
- clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
- else if (! (EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window)
- && row >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
- && row <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
- && (row > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
- || column >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col)
- && (row < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
- || column < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col
- || FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end)))
- {
- Lisp_Object mouse_face, overlay, position;
- Lisp_Object *overlay_vec;
- int len, noverlays, ignor1;
- struct buffer *obuf;
- int obegv, ozv;
-
- /* If we get an out-of-range value, return now; avoid an error. */
- if (pos > BUF_Z (XBUFFER (w->buffer)))
- return;
-
- /* Make the window's buffer temporarily current for
- overlays_at and compute_char_face. */
- obuf = current_buffer;
- current_buffer = XBUFFER (w->buffer);
- obegv = BEGV;
- ozv = ZV;
- BEGV = BEG;
- ZV = Z;
-
- /* Yes. Clear the display of the old active region, if any. */
- clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
-
- /* Is this char mouse-active? */
- XSETINT (position, pos);
-
- len = 10;
- overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
-
- /* Put all the overlays we want in a vector in overlay_vec.
- Store the length in len. */
- noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
- NULL, NULL);
- noverlays = sort_overlays (overlay_vec, noverlays, w);
-
- /* Find the highest priority overlay that has a mouse-face prop. */
- overlay = Qnil;
- for (i = 0; i < noverlays; i++)
- {
- mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
- if (!NILP (mouse_face))
- {
- overlay = overlay_vec[i];
- break;
- }
- }
- free (overlay_vec);
- /* If no overlay applies, get a text property. */
- if (NILP (overlay))
- mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
-
- /* Handle the overlay case. */
- if (! NILP (overlay))
- {
- /* Find the range of text around this char that
- should be active. */
- Lisp_Object before, after;
- int ignore;
-
- before = Foverlay_start (overlay);
- after = Foverlay_end (overlay);
- /* Record this as the current active region. */
- fast_find_position (window, before,
- &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
- &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
- = !fast_find_position (window, after,
- &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
- &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
- = compute_char_face (f, w, pos, 0, 0,
- &ignore, pos + 1, 1);
-
- /* Display it as active. */
- show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
- }
- /* Handle the text property case. */
- else if (! NILP (mouse_face))
- {
- /* Find the range of text around this char that
- should be active. */
- Lisp_Object before, after, beginning, end;
- int ignore;
-
- beginning = Fmarker_position (w->start);
- XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
- - XFASTINT (w->window_end_pos)));
- before
- = Fprevious_single_property_change (make_number (pos + 1),
- Qmouse_face,
- w->buffer, beginning);
- after
- = Fnext_single_property_change (position, Qmouse_face,
- w->buffer, end);
- /* Record this as the current active region. */
- fast_find_position (window, before,
- &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
- &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
- = !fast_find_position (window, after,
- &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
- &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
- FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
- = compute_char_face (f, w, pos, 0, 0,
- &ignore, pos + 1, 1);
-
- /* Display it as active. */
- show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
- }
- BEGV = obegv;
- ZV = ozv;
- current_buffer = obuf;
- }
- }
-}
-
-/* Find the row and column of position POS in window WINDOW.
- Store them in *COLUMNP and *ROWP.
- This assumes display in WINDOW is up to date.
- If POS is above start of WINDOW, return coords
- of start of first screen line.
- If POS is after end of WINDOW, return coords of end of last screen line.
-
- Value is 1 if POS is in range, 0 if it was off screen. */
-
-static int
-fast_find_position (window, pos, columnp, rowp)
- Lisp_Object window;
- int pos;
- int *columnp, *rowp;
-{
- struct window *w = XWINDOW (window);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
- int i;
- int row = 0;
- int left = WINDOW_LEFT_MARGIN (w);
- int top = w->top;
- int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
- int width = window_internal_width (w);
- int *charstarts;
- int lastcol;
- int maybe_next_line = 0;
-
- /* Find the right row. */
- for (i = 0;
- i < height;
- i++)
- {
- int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
- if (linestart > pos)
- break;
- /* If the position sought is the end of the buffer,
- don't include the blank lines at the bottom of the window. */
- if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer)))
- {
- maybe_next_line = 1;
- break;
- }
- if (linestart > 0)
- row = i;
- }
-
- /* Find the right column with in it. */
- charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
- lastcol = left;
- for (i = 0; i < width; i++)
- {
- if (charstarts[left + i] == pos)
- {
- *rowp = row + top;
- *columnp = i + left;
- return 1;
- }
- else if (charstarts[left + i] > pos)
- break;
- else if (charstarts[left + i] > 0)
- lastcol = left + i;
- }
-
- /* If we're looking for the end of the buffer,
- and we didn't find it in the line we scanned,
- use the start of the following line. */
- if (maybe_next_line)
- {
- row++;
- i = 0;
- }
-
- *rowp = row + top;
- *columnp = lastcol;
- return 0;
-}
-
-/* Display the active region described by mouse_face_*
- in its mouse-face if HL > 0, in its normal face if HL = 0. */
-
-static void
-show_mouse_face (dpyinfo, hl)
- struct w32_display_info *dpyinfo;
- int hl;
-{
- struct window *w = XWINDOW (dpyinfo->mouse_face_window);
- int width = window_internal_width (w);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
- int i;
- int cursor_off = 0;
- int old_curs_x = curs_x;
- int old_curs_y = curs_y;
-
- /* Set these variables temporarily
- so that if we have to turn the cursor off and on again
- we will put it back at the same place. */
- curs_x = f->phys_cursor_x;
- curs_y = f->phys_cursor_y;
-
- for (i = FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row;
- i <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row; i++)
- {
- int column = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
- ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col
- : WINDOW_LEFT_MARGIN (w));
- int endcolumn = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
- ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col
- : WINDOW_LEFT_MARGIN (w) + width);
- endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
-
- /* If the cursor's in the text we are about to rewrite,
- turn the cursor off. */
- if (i == curs_y
- && curs_x >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col - 1
- && curs_x <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col)
- {
- x_display_cursor (f, 0);
- cursor_off = 1;
- }
-
- dumpglyphs (f,
- CHAR_TO_PIXEL_COL (f, column),
- CHAR_TO_PIXEL_ROW (f, i),
- FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
- endcolumn - column,
- /* Highlight with mouse face if hl > 0. */
- hl > 0 ? 3 : 0, 0);
- }
-
- /* If we turned the cursor off, turn it back on. */
- if (cursor_off)
- x_display_cursor (f, 1);
-
- curs_x = old_curs_x;
- curs_y = old_curs_y;
-
- /* Change the mouse cursor according to the value of HL. */
- if (hl > 0)
- SetCursor (f->output_data.w32->cross_cursor);
- else
- SetCursor (f->output_data.w32->text_cursor);
-}
-
-/* Clear out the mouse-highlighted active region.
- Redraw it unhighlighted first. */
-
-static void
-clear_mouse_face (dpyinfo)
- struct w32_display_info *dpyinfo;
-{
- if (! NILP (dpyinfo->mouse_face_window))
- show_mouse_face (dpyinfo, 0);
-
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
-}
-
-struct scroll_bar *x_window_to_scroll_bar ();
-static void x_scroll_bar_report_motion ();
-
-/* Return the current position of the mouse.
- *fp should be a frame which indicates which display to ask about.
-
- If the mouse movement started in a scroll bar, set *fp, *bar_window,
- and *part to the frame, window, and scroll bar part that the mouse
- is over. Set *x and *y to the portion and whole of the mouse's
- position on the scroll bar.
-
- If the mouse movement started elsewhere, set *fp to the frame the
- mouse is on, *bar_window to nil, and *x and *y to the character cell
- the mouse is over.
-
- Set *time to the server timestamp for the time at which the mouse
- was at this position.
-
- Don't store anything if we don't have a valid set of values to report.
-
- This clears the mouse_moved flag, so we can wait for the next mouse
- movement. This also calls XQueryPointer, which will cause the
- server to give us another MotionNotify when the mouse moves
- again. */
-
-static void
-w32_mouse_position (fp, insist, bar_window, part, x, y, time)
- FRAME_PTR *fp;
- int insist;
- Lisp_Object *bar_window;
- enum scroll_bar_part *part;
- Lisp_Object *x, *y;
- unsigned long *time;
-{
- FRAME_PTR f1;
-
- BLOCK_INPUT;
-
- if (! NILP (last_mouse_scroll_bar))
- x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
- else
- {
- POINT pt;
-
- Lisp_Object frame, tail;
-
- /* Clear the mouse-moved flag for every frame on this display. */
- FOR_EACH_FRAME (tail, frame)
- XFRAME (frame)->mouse_moved = 0;
-
- last_mouse_scroll_bar = Qnil;
-
- GetCursorPos (&pt);
-
- /* Now we have a position on the root; find the innermost window
- containing the pointer. */
- {
- if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
- && FRAME_LIVE_P (last_mouse_frame))
- {
- f1 = last_mouse_frame;
- }
- else
- {
- /* Is win one of our frames? */
- f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
- }
-
- /* If not, is it one of our scroll bars? */
- if (! f1)
- {
- struct scroll_bar *bar = x_window_to_scroll_bar (WindowFromPoint(pt));
-
- if (bar)
- {
- f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
- }
- }
-
- if (f1 == 0 && insist)
- f1 = selected_frame;
-
- if (f1)
- {
- int ignore1, ignore2;
-
- ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
-
- /* Ok, we found a frame. Store all the values. */
-
- pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
- &last_mouse_glyph,
- FRAME_W32_DISPLAY_INFO (f1)->grabbed
- || insist);
-
- *bar_window = Qnil;
- *part = 0;
- *fp = f1;
- XSETINT (*x, pt.x);
- XSETINT (*y, pt.y);
- *time = last_mouse_movement_time;
- }
- }
- }
-
- UNBLOCK_INPUT;
-}
-
-/* Scroll bar support. */
-
-/* Given an window ID, find the struct scroll_bar which manages it.
- This can be called in GC, so we have to make sure to strip off mark
- bits. */
-struct scroll_bar *
-x_window_to_scroll_bar (window_id)
- Window window_id;
-{
- Lisp_Object tail, frame;
-
- for (tail = Vframe_list;
- XGCTYPE (tail) == Lisp_Cons;
- tail = XCONS (tail)->cdr)
- {
- Lisp_Object frame, bar, condemned;
-
- frame = XCONS (tail)->car;
- /* All elements of Vframe_list should be frames. */
- if (! GC_FRAMEP (frame))
- abort ();
-
- /* Scan this frame's scroll bar list for a scroll bar with the
- right window ID. */
- condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
- for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
- /* This trick allows us to search both the ordinary and
- condemned scroll bar lists with one loop. */
- ! GC_NILP (bar) || (bar = condemned,
- condemned = Qnil,
- ! GC_NILP (bar));
- bar = XSCROLL_BAR (bar)->next)
- if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
- return XSCROLL_BAR (bar);
- }
-
- return 0;
-}
-
-HWND
-my_create_scrollbar (f, bar)
- struct frame * f;
- struct scroll_bar * bar;
-{
- MSG msg;
-
- PostThreadMessage (dwWinThreadId, WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
- (LPARAM) bar);
- GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
-
- return ((HWND) msg.wParam);
-}
-
-//#define ATTACH_THREADS
-
-void
-my_show_window (HWND hwnd, int how)
-{
-#ifndef ATTACH_THREADS
- SendMessage (hwnd, WM_EMACS_SHOWWINDOW, (WPARAM) how, 0);
-#else
- ShowWindow (hwnd , how);
-#endif
-}
-
-void
-my_set_window_pos (HWND hwnd, HWND hwndAfter,
- int x, int y, int cx, int cy, int flags)
-{
-#ifndef ATTACH_THREADS
- W32WindowPos pos;
- pos.hwndAfter = hwndAfter;
- pos.x = x;
- pos.y = y;
- pos.cx = cx;
- pos.cy = cy;
- pos.flags = flags;
- SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
-#else
- SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
-#endif
-}
-
-void
-my_destroy_window (f, hwnd)
- struct frame * f;
- HWND hwnd;
-{
- SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
- (WPARAM) hwnd, 0);
-}
-
-/* Open a new window to serve as a scroll bar, and return the
- scroll bar vector for it. */
-static struct scroll_bar *
-x_scroll_bar_create (window, top, left, width, height)
- struct window *window;
- int top, left, width, height;
-{
- FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
- struct scroll_bar *bar
- = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
- HWND hwnd;
-
- BLOCK_INPUT;
-
- XSETWINDOW (bar->window, window);
- XSETINT (bar->top, top);
- XSETINT (bar->left, left);
- XSETINT (bar->width, width);
- XSETINT (bar->height, height);
- XSETINT (bar->start, 0);
- XSETINT (bar->end, 0);
- bar->dragging = Qnil;
-
- /* Requires geometry to be set before call to create the real window */
-
- hwnd = my_create_scrollbar (f, bar);
-
- SetScrollRange (hwnd, SB_CTL, 0, height, FALSE);
- SetScrollPos (hwnd, SB_CTL, 0, TRUE);
-
- SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
-
- /* Add bar to its frame's list of scroll bars. */
- bar->next = FRAME_SCROLL_BARS (f);
- bar->prev = Qnil;
- XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
- if (! NILP (bar->next))
- XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
-
- UNBLOCK_INPUT;
-
- return bar;
-}
-
-/* Draw BAR's handle in the proper position.
- If the handle is already drawn from START to END, don't bother
- redrawing it, unless REBUILD is non-zero; in that case, always
- redraw it. (REBUILD is handy for drawing the handle after expose
- events.)
-
- Normally, we want to constrain the start and end of the handle to
- fit inside its rectangle, but if the user is dragging the scroll bar
- handle, we want to let them drag it down all the way, so that the
- bar's top is as far down as it goes; otherwise, there's no way to
- move to the very end of the buffer. */
-static void
-x_scroll_bar_set_handle (bar, start, end, rebuild)
- struct scroll_bar *bar;
- int start, end;
- int rebuild;
-{
- int dragging = ! NILP (bar->dragging);
- Window w = SCROLL_BAR_W32_WINDOW (bar);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-
- /* If the display is already accurate, do nothing. */
- if (! rebuild
- && start == XINT (bar->start)
- && end == XINT (bar->end))
- return;
-
- BLOCK_INPUT;
-
- /* Store the adjusted setting in the scroll bar. */
- XSETINT (bar->start, start);
- XSETINT (bar->end, end);
-
- SetScrollPos (w, SB_CTL, start, TRUE);
-
- UNBLOCK_INPUT;
-}
-
-/* Move a scroll bar around on the screen, to accommodate changing
- window configurations. */
-static void
-x_scroll_bar_move (bar, top, left, width, height)
- struct scroll_bar *bar;
- int top, left, width, height;
-{
- Window w = SCROLL_BAR_W32_WINDOW (bar);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-
- BLOCK_INPUT;
-
- MoveWindow (w, left, top, width, height, TRUE);
- SetScrollRange (w, SB_CTL, 0, height, FALSE);
- InvalidateRect (w, NULL, FALSE);
- my_show_window (w, SW_NORMAL);
-
- XSETINT (bar->left, left);
- XSETINT (bar->top, top);
- XSETINT (bar->width, width);
- XSETINT (bar->height, height);
-
- UNBLOCK_INPUT;
-}
-
-/* Destroy the window for BAR, and set its Emacs window's scroll bar
- to nil. */
-static void
-x_scroll_bar_remove (bar)
- struct scroll_bar *bar;
-{
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-
- BLOCK_INPUT;
-
- /* Destroy the window. */
- my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
-
- /* Disassociate this scroll bar from its window. */
- XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
-
- UNBLOCK_INPUT;
-}
-
-/* Set the handle of the vertical scroll bar for WINDOW to indicate
- that we are displaying PORTION characters out of a total of WHOLE
- characters, starting at POSITION. If WINDOW has no scroll bar,
- create one. */
-static void
-w32_set_vertical_scroll_bar (window, portion, whole, position)
- struct window *window;
- int portion, whole, position;
-{
- FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
- int top = XINT (window->top);
- int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
- int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
-
- /* Where should this scroll bar be, pixelwise? */
- int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
- int pixel_left = CHAR_TO_PIXEL_COL (f, left);
- int pixel_width
- = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
- ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
- : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
- int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
-
- struct scroll_bar *bar;
-
- /* Does the scroll bar exist yet? */
- if (NILP (window->vertical_scroll_bar))
- bar = x_scroll_bar_create (window,
- pixel_top, pixel_left,
- pixel_width, pixel_height);
- else
- {
- /* It may just need to be moved and resized. */
- bar = XSCROLL_BAR (window->vertical_scroll_bar);
- x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
- }
-
- /* Set the scroll bar's current state, unless we're currently being
- dragged. */
- if (NILP (bar->dragging))
- {
- int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
-
- if (whole == 0)
- x_scroll_bar_set_handle (bar, 0, top_range, 0);
- else
- {
- int start = (int) (((double) position * top_range) / whole);
- int end = (int) (((double) (position + portion) * top_range) / whole);
-
- x_scroll_bar_set_handle (bar, start, end, 0);
- }
- }
-
- XSETVECTOR (window->vertical_scroll_bar, bar);
-}
-
-
-/* The following three hooks are used when we're doing a thorough
- redisplay of the frame. We don't explicitly know which scroll bars
- are going to be deleted, because keeping track of when windows go
- away is a real pain - "Can you say set-window-configuration, boys
- and girls?" Instead, we just assert at the beginning of redisplay
- that *all* scroll bars are to be removed, and then save a scroll bar
- from the fiery pit when we actually redisplay its window. */
-
-/* Arrange for all scroll bars on FRAME to be removed at the next call
- to `*judge_scroll_bars_hook'. A scroll bar may be spared if
- `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
-static void
-w32_condemn_scroll_bars (frame)
- FRAME_PTR frame;
-{
- /* The condemned list should be empty at this point; if it's not,
- then the rest of Emacs isn't using the condemn/redeem/judge
- protocol correctly. */
- if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
- abort ();
-
- /* Move them all to the "condemned" list. */
- FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
- FRAME_SCROLL_BARS (frame) = Qnil;
-}
-
-/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
- Note that WINDOW isn't necessarily condemned at all. */
-static void
-w32_redeem_scroll_bar (window)
- struct window *window;
-{
- struct scroll_bar *bar;
-
- /* We can't redeem this window's scroll bar if it doesn't have one. */
- if (NILP (window->vertical_scroll_bar))
- abort ();
-
- bar = XSCROLL_BAR (window->vertical_scroll_bar);
-
- /* Unlink it from the condemned list. */
- {
- FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
-
- if (NILP (bar->prev))
- {
- /* If the prev pointer is nil, it must be the first in one of
- the lists. */
- if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
- /* It's not condemned. Everything's fine. */
- return;
- else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
- window->vertical_scroll_bar))
- FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
- else
- /* If its prev pointer is nil, it must be at the front of
- one or the other! */
- abort ();
- }
- else
- XSCROLL_BAR (bar->prev)->next = bar->next;
-
- if (! NILP (bar->next))
- XSCROLL_BAR (bar->next)->prev = bar->prev;
-
- bar->next = FRAME_SCROLL_BARS (f);
- bar->prev = Qnil;
- XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
- if (! NILP (bar->next))
- XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
- }
-}
-
-/* Remove all scroll bars on FRAME that haven't been saved since the
- last call to `*condemn_scroll_bars_hook'. */
-static void
-w32_judge_scroll_bars (f)
- FRAME_PTR f;
-{
- Lisp_Object bar, next;
-
- bar = FRAME_CONDEMNED_SCROLL_BARS (f);
-
- /* Clear out the condemned list now so we won't try to process any
- more events on the hapless scroll bars. */
- FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
-
- for (; ! NILP (bar); bar = next)
- {
- struct scroll_bar *b = XSCROLL_BAR (bar);
-
- x_scroll_bar_remove (b);
-
- next = b->next;
- b->next = b->prev = Qnil;
- }
-
- /* Now there should be no references to the condemned scroll bars,
- and they should get garbage-collected. */
-}
-
-/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
- is set to something other than no_event, it is enqueued.
-
- This may be called from a signal handler, so we have to ignore GC
- mark bits. */
-
-static int
-x_scroll_bar_handle_click (bar, msg, emacs_event)
- struct scroll_bar *bar;
- W32Msg *msg;
- struct input_event *emacs_event;
-{
- if (! GC_WINDOWP (bar->window))
- abort ();
-
- emacs_event->kind = w32_scroll_bar_click;
- emacs_event->code = 0;
- /* not really meaningful to distinguish up/down */
- emacs_event->modifiers = msg->dwModifiers;
- emacs_event->frame_or_window = bar->window;
- emacs_event->timestamp = msg->msg.time;
-
- {
- int internal_height
- = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
- int top_range
- = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
- int y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
-
- switch (LOWORD (msg->msg.wParam))
- {
- case SB_THUMBTRACK:
- emacs_event->part = scroll_bar_handle;
- if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
- y = HIWORD (msg->msg.wParam);
- break;
- case SB_LINEDOWN:
- emacs_event->part = scroll_bar_down_arrow;
- break;
- case SB_LINEUP:
- emacs_event->part = scroll_bar_up_arrow;
- break;
- case SB_PAGEUP:
- emacs_event->part = scroll_bar_above_handle;
- break;
- case SB_PAGEDOWN:
- emacs_event->part = scroll_bar_below_handle;
- break;
- case SB_TOP:
- emacs_event->part = scroll_bar_handle;
- y = 0;
- break;
- case SB_BOTTOM:
- emacs_event->part = scroll_bar_handle;
- y = top_range;
- break;
- case SB_THUMBPOSITION:
- emacs_event->part = scroll_bar_handle;
- break;
- case SB_ENDSCROLL:
- default:
- SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
- return FALSE;
- }
-
- XSETINT (emacs_event->x, y);
- XSETINT (emacs_event->y, top_range);
-
- return TRUE;
- }
-}
-
-/* Return information to the user about the current position of the mouse
- on the scroll bar. */
-static void
-x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
- FRAME_PTR *fp;
- Lisp_Object *bar_window;
- enum scroll_bar_part *part;
- Lisp_Object *x, *y;
- unsigned long *time;
-{
- struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
- Window w = SCROLL_BAR_W32_WINDOW (bar);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
- int pos;
-
- BLOCK_INPUT;
-
- *fp = f;
- *bar_window = bar->window;
-
- pos = GetScrollPos (w, SB_CTL);
-
- switch (LOWORD (last_mouse_scroll_bar_pos))
- {
- case SB_THUMBPOSITION:
- case SB_THUMBTRACK:
- *part = scroll_bar_handle;
- if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
- pos = HIWORD (last_mouse_scroll_bar_pos);
- break;
- case SB_LINEDOWN:
- *part = scroll_bar_handle;
- pos++;
- break;
- default:
- *part = scroll_bar_handle;
- break;
- }
-
- XSETINT(*x, pos);
- XSETINT(*y, VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)));
-
- f->mouse_moved = 0;
- last_mouse_scroll_bar = Qnil;
-
- *time = last_mouse_movement_time;
-
- UNBLOCK_INPUT;
-}
-
-/* The screen has been cleared so we may have changed foreground or
- background colors, and the scroll bars may need to be redrawn.
- Clear out the scroll bars, and ask for expose events, so we can
- redraw them. */
-
-x_scroll_bar_clear (f)
- FRAME_PTR f;
-{
- Lisp_Object bar;
-
- for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
- bar = XSCROLL_BAR (bar)->next)
- {
- HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
- HDC hdc = GetDC (window);
- RECT rect;
-
- my_show_window (window, SW_HIDE);
- GetClientRect (window, &rect);
- select_palette (f, hdc);
- w32_clear_rect (f, hdc, &rect);
- deselect_palette (f, hdc);
- }
-}
-
-show_scroll_bars (f, how)
- FRAME_PTR f;
- int how;
-{
- Lisp_Object bar;
-
- for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
- bar = XSCROLL_BAR (bar)->next)
- {
- HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
- my_show_window (window, how);
- }
-}
-
-
-/* The main W32 event-reading loop - w32_read_socket. */
-
-/* Timestamp of enter window event. This is only used by w32_read_socket,
- but we have to put it out here, since static variables within functions
- sometimes don't work. */
-static Time enter_timestamp;
-
-/* Record the last 100 characters stored
- to help debug the loss-of-chars-during-GC problem. */
-int temp_index;
-short temp_buffer[100];
-
-extern int key_event (KEY_EVENT_RECORD *, struct input_event *);
-
-/* Map a W32 WM_CHAR message into a KEY_EVENT_RECORD so that
- we can use the same routines to handle input in both console
- and window modes. */
-
-static void
-convert_to_key_event (W32Msg *msgp, KEY_EVENT_RECORD *eventp)
-{
- eventp->bKeyDown = TRUE;
- eventp->wRepeatCount = 1;
- eventp->wVirtualKeyCode = msgp->msg.wParam;
- eventp->wVirtualScanCode = (msgp->msg.lParam & 0xFF0000) >> 16;
- eventp->uChar.AsciiChar = 0;
- eventp->dwControlKeyState = msgp->dwModifiers;
-}
-
-/* Return nonzero if the virtual key is a dead key. */
-
-static int
-is_dead_key (int wparam)
-{
- unsigned int code = MapVirtualKey (wparam, 2);
-
- /* Win95 returns 0x8000, NT returns 0x80000000. */
- if ((code & 0x8000) || (code & 0x80000000))
- return 1;
- else
- return 0;
-}
-
-/* Read events coming from the W32 shell.
- This routine is called by the SIGIO handler.
- We return as soon as there are no more events to be read.
-
- Events representing keys are stored in buffer BUFP,
- which can hold up to NUMCHARS characters.
- We return the number of characters stored into the buffer,
- thus pretending to be `read'.
-
- EXPECTED is nonzero if the caller knows input is available.
-
- Some of these messages are reposted back to the message queue since the
- system calls the winproc directly in a context where we cannot return the
- data nor can we guarantee the state we are in. So if we dispatch them
- we will get into an infinite loop. To prevent this from ever happening we
- will set a variable to indicate we are in the read_socket call and indicate
- which message we are processing since the winproc gets called recursively with different
- messages by the system.
-*/
-
-int
-w32_read_socket (sd, bufp, numchars, expected)
- register int sd;
- register struct input_event *bufp;
- register int numchars;
- int expected;
-{
- int count = 0;
- int nbytes = 0;
- int items_pending; /* How many items are in the X queue. */
- W32Msg msg;
- struct frame *f;
- int event_found = 0;
- int prefix;
- Lisp_Object part;
- struct w32_display_info *dpyinfo = &one_w32_display_info;
-
- if (interrupt_input_blocked)
- {
- interrupt_input_pending = 1;
- return -1;
- }
-
- interrupt_input_pending = 0;
- BLOCK_INPUT;
-
- /* So people can tell when we have read the available input. */
- input_signal_count++;
-
- if (numchars <= 0)
- abort (); /* Don't think this happens. */
-
- while (get_next_msg (&msg, FALSE))
- {
- switch (msg.msg.message)
- {
- case WM_PAINT:
- {
- f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- if (f)
- {
- if (f->async_visible == 0)
- {
- f->async_visible = 1;
- f->async_iconified = 0;
- SET_FRAME_GARBAGED (f);
- }
- else
- {
- /* Erase background again for safety. */
- w32_clear_rect (f, NULL, &msg.rect);
- dumprectangle (f,
- msg.rect.left,
- msg.rect.top,
- msg.rect.right-msg.rect.left+1,
- msg.rect.bottom-msg.rect.top+1);
- }
- }
- }
- break;
- case WM_KEYDOWN:
- case WM_SYSKEYDOWN:
- f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- if (f && !f->iconified)
- {
- if (temp_index == sizeof temp_buffer / sizeof (short))
- temp_index = 0;
- temp_buffer[temp_index++] = msg.msg.wParam;
- bufp->kind = non_ascii_keystroke;
- bufp->code = msg.msg.wParam;
- bufp->modifiers = w32_kbd_mods_to_emacs (msg.dwModifiers);
- XSETFRAME (bufp->frame_or_window, f);
- bufp->timestamp = msg.msg.time;
- bufp++;
- numchars--;
- count++;
- }
- break;
- case WM_SYSCHAR:
- case WM_CHAR:
- f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- if (f && !f->iconified)
- {
- if (numchars > 1)
- {
- int add;
- KEY_EVENT_RECORD key, *keyp = &key;
-
- if (temp_index == sizeof temp_buffer / sizeof (short))
- temp_index = 0;
-
- convert_to_key_event (&msg, keyp);
- add = key_event (keyp, bufp);
- XSETFRAME (bufp->frame_or_window, f);
- if (add == -1)
- {
- /* The key pressed generated two characters, most likely
- an accent character and a key that could not be
- combined with it. Prepend the message on the queue
- again to process the second character (which is
- being held internally in key_event), and process
- the first character now. */
- prepend_msg (&msg);
- add = 1;
- }
-
- /* Throw dead keys away. However, be sure not to
- throw away the dead key if it was produced using
- AltGr and there is a valid AltGr scan code for
- this key. */
- if (is_dead_key (msg.msg.wParam)
- && !((VkKeyScan ((char) bufp->code) & 0xff00) == 0x600))
- break;
-
- bufp += add;
- numchars -= add;
- count += add;
- }
- else
- {
- abort ();
- }
- }
- break;
- case WM_MOUSEMOVE:
- if (dpyinfo->grabbed && last_mouse_frame
- && FRAME_LIVE_P (last_mouse_frame))
- f = last_mouse_frame;
- else
- f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- if (f)
- note_mouse_movement (f, &msg.msg);
- else
- clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
-
- break;
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_MBUTTONDOWN:
- case WM_MBUTTONUP:
- case WM_RBUTTONDOWN:
- case WM_RBUTTONUP:
- {
- int button;
- int up;
-
- if (dpyinfo->grabbed && last_mouse_frame
- && FRAME_LIVE_P (last_mouse_frame))
- f = last_mouse_frame;
- else
- f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- if (f)
- {
- if ((!dpyinfo->w32_focus_frame || f == dpyinfo->w32_focus_frame)
- && (numchars >= 1))
- {
- construct_mouse_click (bufp, &msg, f);
- bufp++;
- count++;
- numchars--;
- }
- }
-
- parse_button (msg.msg.message, &button, &up);
-
- if (up)
- {
- dpyinfo->grabbed &= ~ (1 << button);
- }
- else
- {
- dpyinfo->grabbed |= (1 << button);
- last_mouse_frame = f;
- }
- }
-
- break;
- case WM_VSCROLL:
- {
- struct scroll_bar *bar = x_window_to_scroll_bar ((HWND)msg.msg.lParam);
-
- if (bar && numchars >= 1)
- {
- if (x_scroll_bar_handle_click (bar, &msg, bufp))
- {
- bufp++;
- count++;
- numchars--;
- }
- }
- }
-
- break;
- case WM_MOVE:
- f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- if (f && !f->async_iconified)
- {
- f->output_data.w32->left_pos = LOWORD (msg.msg.lParam);
- f->output_data.w32->top_pos = HIWORD (msg.msg.lParam);
- }
-
- break;
- case WM_SIZE:
- f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
- {
- RECT rect;
- int rows;
- int columns;
- int width;
- int height;
-
- GetClientRect(msg.msg.hwnd, &rect);
-
- height = rect.bottom - rect.top + 1;
- width = rect.right - rect.left + 1;
-
- rows = PIXEL_TO_CHAR_HEIGHT (f, height);
- columns = PIXEL_TO_CHAR_WIDTH (f, width);
-
- /* Even if the number of character rows and columns has
- not changed, the font size may have changed, so we need
- to check the pixel dimensions as well. */
-
- if (columns != f->width
- || rows != f->height
- || width != f->output_data.w32->pixel_width
- || height != f->output_data.w32->pixel_height)
- {
- /* I had set this to 0, 0 - I am not sure why?? */
-
- change_frame_size (f, rows, columns, 0, 1);
- SET_FRAME_GARBAGED (f);
-
- f->output_data.w32->pixel_width = width;
- f->output_data.w32->pixel_height = height;
- f->output_data.w32->win_gravity = NorthWestGravity;
- }
- }
-
- break;
- case WM_SETFOCUS:
- case WM_KILLFOCUS:
- f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- if (msg.msg.message == WM_SETFOCUS)
- {
- x_new_focus_frame (dpyinfo, f);
- }
- else if (f == dpyinfo->w32_focus_frame)
- x_new_focus_frame (dpyinfo, 0);
-
- break;
- case WM_SYSCOMMAND:
- switch (msg.msg.wParam & 0xfff0) /* Lower 4 bits used by Windows. */
- {
- case SC_CLOSE:
- f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- if (f)
- {
- if (numchars == 0)
- abort ();
-
- bufp->kind = delete_window_event;
- XSETFRAME (bufp->frame_or_window, f);
- bufp++;
- count++;
- numchars--;
- }
-
- break;
- case SC_MINIMIZE:
- f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- if (f)
- {
- f->async_visible = 1;
- f->async_iconified = 1;
-
- bufp->kind = iconify_event;
- XSETFRAME (bufp->frame_or_window, f);
- bufp++;
- count++;
- numchars--;
- }
-
- break;
- case SC_MAXIMIZE:
- case SC_RESTORE:
- f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- if (f)
- {
- f->async_visible = 1;
- f->async_iconified = 0;
-
- /* wait_reading_process_input will notice this and update
- the frame's display structures. */
- SET_FRAME_GARBAGED (f);
-
- if (f->iconified)
- {
- bufp->kind = deiconify_event;
- XSETFRAME (bufp->frame_or_window, f);
- bufp++;
- count++;
- numchars--;
- }
- else
- /* Force a redisplay sooner or later
- to update the frame titles
- in case this is the second frame. */
- record_asynch_buffer_change ();
- }
-
- break;
- }
-
- break;
- case WM_CLOSE:
- f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- if (f)
- {
- if (numchars == 0)
- abort ();
-
- bufp->kind = delete_window_event;
- XSETFRAME (bufp->frame_or_window, f);
- bufp++;
- count++;
- numchars--;
- }
-
- break;
- case WM_COMMAND:
- f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- if (f)
- {
- if (msg.msg.lParam == 0)
- {
- /* Came from window menu */
-
- extern Lisp_Object get_frame_menubar_event ();
- Lisp_Object event = get_frame_menubar_event (f, msg.msg.wParam);
- struct input_event buf;
- Lisp_Object frame;
-
- XSETFRAME (frame, f);
- buf.kind = menu_bar_event;
-
- /* Store initial menu bar event */
-
- if (!NILP (event))
- {
- buf.frame_or_window = Fcons (frame, Fcons (Qmenu_bar, Qnil));
- kbd_buffer_store_event (&buf);
- }
-
- /* Enqueue the events */
-
- while (!NILP (event))
- {
- buf.frame_or_window = Fcons (frame, XCONS (event)->car);
- kbd_buffer_store_event (&buf);
- event = XCONS (event)->cdr;
- }
- }
- else
- {
- /* Came from popup menu */
- }
- }
- break;
- }
- }
-
- /* If the focus was just given to an autoraising frame,
- raise it now. */
- /* ??? This ought to be able to handle more than one such frame. */
- if (pending_autoraise_frame)
- {
- x_raise_frame (pending_autoraise_frame);
- pending_autoraise_frame = 0;
- }
-
- UNBLOCK_INPUT;
- return count;
-}
-
-/* Drawing the cursor. */
-
-
-/* Draw a hollow box cursor. Don't change the inside of the box. */
-
-static void
-x_draw_box (f)
- struct frame *f;
-{
- RECT rect;
- HBRUSH hb;
- HDC hdc;
-
- hdc = get_frame_dc (f);
-
- hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
-
- rect.left = CHAR_TO_PIXEL_COL (f, curs_x);
- rect.top = CHAR_TO_PIXEL_ROW (f, curs_y);
- rect.right = rect.left + FONT_WIDTH (f->output_data.w32->font);
- rect.bottom = rect.top + f->output_data.w32->line_height;
-
- FrameRect (hdc, &rect, hb);
- DeleteObject (hb);
-
- release_frame_dc (f, hdc);
-}
-
-/* Clear the cursor of frame F to background color,
- and mark the cursor as not shown.
- This is used when the text where the cursor is
- is about to be rewritten. */
-
-static void
-clear_cursor (f)
- struct frame *f;
-{
- if (! FRAME_VISIBLE_P (f)
- || f->phys_cursor_x < 0)
- return;
-
- x_display_cursor (f, 0);
- f->phys_cursor_x = -1;
-}
-
-/* Redraw the glyph at ROW, COLUMN on frame F, in the style
- HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
- glyph drawn. */
-
-static void
-x_draw_single_glyph (f, row, column, glyph, highlight)
- struct frame *f;
- int row, column;
- GLYPH glyph;
- int highlight;
-{
- dumpglyphs (f,
- CHAR_TO_PIXEL_COL (f, column),
- CHAR_TO_PIXEL_ROW (f, row),
- &glyph, 1, highlight, 0);
-}
-
-static void
-x_display_bar_cursor (f, on)
- struct frame *f;
- int on;
-{
- struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
-
- /* This is pointless on invisible frames, and dangerous on garbaged
- frames; in the latter case, the frame may be in the midst of
- changing its size, and curs_x and curs_y may be off the frame. */
- if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
- return;
-
- if (! on && f->phys_cursor_x < 0)
- return;
-
- /* If we're not updating, then we want to use the current frame's
- cursor position, not our local idea of where the cursor ought to be. */
- if (f != updating_frame)
- {
- curs_x = FRAME_CURSOR_X (f);
- curs_y = FRAME_CURSOR_Y (f);
- }
-
- /* If there is anything wrong with the current cursor state, remove it. */
- if (f->phys_cursor_x >= 0
- && (!on
- || f->phys_cursor_x != curs_x
- || f->phys_cursor_y != curs_y
- || f->output_data.w32->current_cursor != bar_cursor))
- {
- /* Erase the cursor by redrawing the character underneath it. */
- x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
- f->phys_cursor_glyph,
- current_glyphs->highlight[f->phys_cursor_y]);
- f->phys_cursor_x = -1;
- }
-
- /* If we now need a cursor in the new place or in the new form, do it so. */
- if (on
- && (f->phys_cursor_x < 0
- || (f->output_data.w32->current_cursor != bar_cursor)))
- {
- f->phys_cursor_glyph
- = ((current_glyphs->enable[curs_y]
- && curs_x < current_glyphs->used[curs_y])
- ? current_glyphs->glyphs[curs_y][curs_x]
- : SPACEGLYPH);
- w32_fill_area (f, NULL, f->output_data.w32->cursor_pixel,
- CHAR_TO_PIXEL_COL (f, curs_x),
- CHAR_TO_PIXEL_ROW (f, curs_y),
- max (f->output_data.w32->cursor_width, 1),
- f->output_data.w32->line_height);
-
- f->phys_cursor_x = curs_x;
- f->phys_cursor_y = curs_y;
-
- f->output_data.w32->current_cursor = bar_cursor;
- }
-}
-
-
-/* Turn the displayed cursor of frame F on or off according to ON.
- If ON is nonzero, where to put the cursor is specified
- by F->cursor_x and F->cursor_y. */
-
-static void
-x_display_box_cursor (f, on)
- struct frame *f;
- int on;
-{
- struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
-
- /* This is pointless on invisible frames, and dangerous on garbaged
- frames; in the latter case, the frame may be in the midst of
- changing its size, and curs_x and curs_y may be off the frame. */
- if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
- return;
-
- /* If cursor is off and we want it off, return quickly. */
- if (!on && f->phys_cursor_x < 0)
- return;
-
- /* If we're not updating, then we want to use the current frame's
- cursor position, not our local idea of where the cursor ought to be. */
- if (f != updating_frame)
- {
- curs_x = FRAME_CURSOR_X (f);
- curs_y = FRAME_CURSOR_Y (f);
- }
-
- /* If cursor is currently being shown and we don't want it to be
- or it is in the wrong place,
- or we want a hollow box and it's not so, (pout!)
- erase it. */
- if (f->phys_cursor_x >= 0
- && (!on
- || f->phys_cursor_x != curs_x
- || f->phys_cursor_y != curs_y
- || (f->output_data.w32->current_cursor != hollow_box_cursor
- && (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame))))
- {
- int mouse_face_here = 0;
- struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
-
- /* If the cursor is in the mouse face area, redisplay that when
- we clear the cursor. */
- if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame
- &&
- (f->phys_cursor_y > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
- || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
- && f->phys_cursor_x >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col))
- &&
- (f->phys_cursor_y < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
- || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
- && f->phys_cursor_x < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col))
- /* Don't redraw the cursor's spot in mouse face
- if it is at the end of a line (on a newline).
- The cursor appears there, but mouse highlighting does not. */
- && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x)
- mouse_face_here = 1;
-
- /* If the font is not as tall as a whole line,
- we must explicitly clear the line's whole height. */
- if (FONT_HEIGHT (f->output_data.w32->font) != f->output_data.w32->line_height)
- w32_clear_area (f, NULL,
- CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
- CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
- FONT_WIDTH (f->output_data.w32->font),
- f->output_data.w32->line_height);
- /* Erase the cursor by redrawing the character underneath it. */
- x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
- f->phys_cursor_glyph,
- (mouse_face_here
- ? 3
- : current_glyphs->highlight[f->phys_cursor_y]));
- f->phys_cursor_x = -1;
- }
-
- /* If we want to show a cursor,
- or we want a box cursor and it's not so,
- write it in the right place. */
- if (on
- && (f->phys_cursor_x < 0
- || (f->output_data.w32->current_cursor != filled_box_cursor
- && f == FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)))
- {
- f->phys_cursor_glyph
- = ((current_glyphs->enable[curs_y]
- && curs_x < current_glyphs->used[curs_y])
- ? current_glyphs->glyphs[curs_y][curs_x]
- : SPACEGLYPH);
- if (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
- {
- x_draw_box (f);
- f->output_data.w32->current_cursor = hollow_box_cursor;
- }
- else
- {
- x_draw_single_glyph (f, curs_y, curs_x,
- f->phys_cursor_glyph, 2);
- f->output_data.w32->current_cursor = filled_box_cursor;
- }
-
- f->phys_cursor_x = curs_x;
- f->phys_cursor_y = curs_y;
- }
-}
-
-x_display_cursor (f, on)
- struct frame *f;
- int on;
-{
- BLOCK_INPUT;
-
- if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
- x_display_box_cursor (f, on);
- else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
- x_display_bar_cursor (f, on);
- else
- /* Those are the only two we have implemented! */
- abort ();
-
- UNBLOCK_INPUT;
-}
-
-/* Changing the font of the frame. */
-
-/* Give frame F the font named FONTNAME as its default font, and
- return the full name of that font. FONTNAME may be a wildcard
- pattern; in that case, we choose some font that fits the pattern.
- The return value shows which font we chose. */
-
-Lisp_Object
-x_new_font (f, fontname)
- struct frame *f;
- register char *fontname;
-{
- int already_loaded;
- int n_matching_fonts;
- XFontStruct *font_info;
- char new_font_name[101];
-
- /* Get a font which matches this name */
- {
- LOGFONT lf;
-
- if (!x_to_w32_font(fontname, &lf)
- || !w32_to_x_font(&lf, new_font_name, 100))
- {
- return Qnil;
- }
- }
-
- /* See if we've already loaded a matching font. */
- already_loaded = -1;
-
- {
- int i;
-
- for (i = 0; i < FRAME_W32_DISPLAY_INFO (f)->n_fonts; i++)
- if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->font_table[i].name, new_font_name))
- {
- already_loaded = i;
- fontname = FRAME_W32_DISPLAY_INFO (f)->font_table[i].name;
- break;
- }
- }
-
- /* If we have, just return it from the table. */
- if (already_loaded >= 0)
- f->output_data.w32->font = FRAME_W32_DISPLAY_INFO (f)->font_table[already_loaded].font;
- /* Otherwise, load the font and add it to the table. */
- else
- {
- XFontStruct *font;
- int n_fonts;
-
- font = w32_load_font(FRAME_W32_DISPLAY_INFO (f), fontname);
-
- if (! font)
- {
- return Qnil;
- }
-
- /* Do we need to create the table? */
- if (FRAME_W32_DISPLAY_INFO (f)->font_table_size == 0)
- {
- FRAME_W32_DISPLAY_INFO (f)->font_table_size = 16;
- FRAME_W32_DISPLAY_INFO (f)->font_table
- = (struct font_info *) xmalloc (FRAME_W32_DISPLAY_INFO (f)->font_table_size
- * sizeof (struct font_info));
- }
- /* Do we need to grow the table? */
- else if (FRAME_W32_DISPLAY_INFO (f)->n_fonts
- >= FRAME_W32_DISPLAY_INFO (f)->font_table_size)
- {
- FRAME_W32_DISPLAY_INFO (f)->font_table_size *= 2;
- FRAME_W32_DISPLAY_INFO (f)->font_table
- = (struct font_info *) xrealloc (FRAME_W32_DISPLAY_INFO (f)->font_table,
- (FRAME_W32_DISPLAY_INFO (f)->font_table_size
- * sizeof (struct font_info)));
- }
-
- n_fonts = FRAME_W32_DISPLAY_INFO (f)->n_fonts;
- FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
- bcopy (fontname, FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
- f->output_data.w32->font = FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
- FRAME_W32_DISPLAY_INFO (f)->n_fonts++;
- }
-
- /* Compute the scroll bar width in character columns. */
- if (f->scroll_bar_pixel_width > 0)
- {
- int wid = FONT_WIDTH (f->output_data.w32->font);
- f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
- }
- else
- f->scroll_bar_cols = 2;
-
- /* Now make the frame display the given font. */
- if (FRAME_W32_WINDOW (f) != 0)
- {
- frame_update_line_height (f);
- x_set_window_size (f, 0, f->width, f->height);
- }
- else
- /* If we are setting a new frame's font for the first time,
- there are no faces yet, so this font's height is the line height. */
- f->output_data.w32->line_height = FONT_HEIGHT (f->output_data.w32->font);
-
- {
- Lisp_Object lispy_name;
-
- lispy_name = build_string (fontname);
-
- return lispy_name;
- }
-}
-
-x_calc_absolute_position (f)
- struct frame *f;
-{
- Window win, child;
- POINT pt;
- int flags = f->output_data.w32->size_hint_flags;
-
- pt.x = pt.y = 0;
-
- /* Find the position of the outside upper-left corner of
- the inner window, with respect to the outer window. */
- if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
- {
- BLOCK_INPUT;
- MapWindowPoints (FRAME_W32_WINDOW (f),
- f->output_data.w32->parent_desc,
- &pt, 1);
- UNBLOCK_INPUT;
- }
-
- {
- RECT rt;
- rt.left = rt.right = rt.top = rt.bottom = 0;
-
- BLOCK_INPUT;
- AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
- FRAME_EXTERNAL_MENU_BAR (f));
- UNBLOCK_INPUT;
-
- pt.x += (rt.right - rt.left);
- pt.y += (rt.bottom - rt.top);
- }
-
- /* Treat negative positions as relative to the leftmost bottommost
- position that fits on the screen. */
- if (flags & XNegative)
- f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
- - 2 * f->output_data.w32->border_width - pt.x
- - PIXEL_WIDTH (f)
- + f->output_data.w32->left_pos);
-
- if (flags & YNegative)
- f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
- - 2 * f->output_data.w32->border_width - pt.y
- - PIXEL_HEIGHT (f)
- + f->output_data.w32->top_pos);
- /* The left_pos and top_pos
- are now relative to the top and left screen edges,
- so the flags should correspond. */
- f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
-}
-
-/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
- to really change the position, and 0 when calling from
- x_make_frame_visible (in that case, XOFF and YOFF are the current
- position values). It is -1 when calling from x_set_frame_parameters,
- which means, do adjust for borders but don't change the gravity. */
-
-x_set_offset (f, xoff, yoff, change_gravity)
- struct frame *f;
- register int xoff, yoff;
- int change_gravity;
-{
- int modified_top, modified_left;
-
- if (change_gravity > 0)
- {
- f->output_data.w32->top_pos = yoff;
- f->output_data.w32->left_pos = xoff;
- f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
- if (xoff < 0)
- f->output_data.w32->size_hint_flags |= XNegative;
- if (yoff < 0)
- f->output_data.w32->size_hint_flags |= YNegative;
- f->output_data.w32->win_gravity = NorthWestGravity;
- }
- x_calc_absolute_position (f);
-
- BLOCK_INPUT;
- x_wm_set_size_hint (f, (long) 0, 0);
-
- /* It is a mystery why we need to add the border_width here
- when the frame is already visible, but experiment says we do. */
- modified_left = f->output_data.w32->left_pos;
- modified_top = f->output_data.w32->top_pos;
- if (change_gravity != 0)
- {
- modified_left += f->output_data.w32->border_width;
- modified_top += f->output_data.w32->border_width;
- }
-
- my_set_window_pos (FRAME_W32_WINDOW (f),
- NULL,
- modified_left, modified_top,
- 0,0,
- SWP_NOZORDER | SWP_NOSIZE);
- UNBLOCK_INPUT;
-}
-
-/* Call this to change the size of frame F's x-window.
- If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
- for this size change and subsequent size changes.
- Otherwise we leave the window gravity unchanged. */
-
-x_set_window_size (f, change_gravity, cols, rows)
- struct frame *f;
- int change_gravity;
- int cols, rows;
-{
- int pixelwidth, pixelheight;
-
- BLOCK_INPUT;
-
- check_frame_size (f, &rows, &cols);
- f->output_data.w32->vertical_scroll_bar_extra
- = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
- ? 0
- : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
- ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
- : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
- pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
- pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
-
- f->output_data.w32->win_gravity = NorthWestGravity;
- x_wm_set_size_hint (f, (long) 0, 0);
-
- {
- RECT rect;
-
- rect.left = rect.top = 0;
- rect.right = pixelwidth;
- rect.bottom = pixelheight;
-
- AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
- FRAME_EXTERNAL_MENU_BAR (f));
-
- /* All windows have an extra pixel */
-
- my_set_window_pos (FRAME_W32_WINDOW (f),
- NULL,
- 0, 0,
- rect.right - rect.left + 1,
- rect.bottom - rect.top + 1,
- SWP_NOZORDER | SWP_NOMOVE);
- }
-
- /* Now, strictly speaking, we can't be sure that this is accurate,
- but the window manager will get around to dealing with the size
- change request eventually, and we'll hear how it went when the
- ConfigureNotify event gets here.
-
- We could just not bother storing any of this information here,
- and let the ConfigureNotify event set everything up, but that
- might be kind of confusing to the lisp code, since size changes
- wouldn't be reported in the frame parameters until some random
- point in the future when the ConfigureNotify event arrives. */
- change_frame_size (f, rows, cols, 0, 0);
- PIXEL_WIDTH (f) = pixelwidth;
- PIXEL_HEIGHT (f) = pixelheight;
-
- /* If cursor was outside the new size, mark it as off. */
- if (f->phys_cursor_y >= rows
- || f->phys_cursor_x >= cols)
- {
- f->phys_cursor_x = -1;
- f->phys_cursor_y = -1;
- }
-
- /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
- receive in the ConfigureNotify event; if we get what we asked
- for, then the event won't cause the screen to become garbaged, so
- we have to make sure to do it here. */
- SET_FRAME_GARBAGED (f);
-
- UNBLOCK_INPUT;
-}
-
-/* Mouse warping. */
-
-void
-x_set_mouse_pixel_position (f, pix_x, pix_y)
- struct frame *f;
- int pix_x, pix_y;
-{
- BLOCK_INPUT;
-
- pix_x += f->output_data.w32->left_pos;
- pix_y += f->output_data.w32->top_pos;
-
- SetCursorPos (pix_x, pix_y);
-
- UNBLOCK_INPUT;
-}
-
-void
-x_set_mouse_position (f, x, y)
- struct frame *f;
- int x, y;
-{
- int pix_x, pix_y;
-
- pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.w32->font) / 2;
- pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
-
- if (pix_x < 0) pix_x = 0;
- if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
-
- if (pix_y < 0) pix_y = 0;
- if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
-
- x_set_mouse_pixel_position (f, pix_x, pix_y);
-}
-
-/* focus shifting, raising and lowering. */
-
-x_focus_on_frame (f)
- struct frame *f;
-{
-}
-
-x_unfocus_frame (f)
- struct frame *f;
-{
-}
-
-/* Raise frame F. */
-
-x_raise_frame (f)
- struct frame *f;
-{
-// if (f->async_visible)
- {
- BLOCK_INPUT;
- my_set_window_pos (FRAME_W32_WINDOW (f),
- HWND_TOP,
- 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE);
- UNBLOCK_INPUT;
- }
-}
-
-/* Lower frame F. */
-
-x_lower_frame (f)
- struct frame *f;
-{
-// if (f->async_visible)
- {
- BLOCK_INPUT;
- my_set_window_pos (FRAME_W32_WINDOW (f),
- HWND_BOTTOM,
- 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE);
- UNBLOCK_INPUT;
- }
-}
-
-static void
-w32_frame_raise_lower (f, raise)
- FRAME_PTR f;
- int raise;
-{
- if (raise)
- x_raise_frame (f);
- else
- x_lower_frame (f);
-}
-
-/* Change of visibility. */
-
-/* This tries to wait until the frame is really visible.
- However, if the window manager asks the user where to position
- the frame, this will return before the user finishes doing that.
- The frame will not actually be visible at that time,
- but it will become visible later when the window manager
- finishes with it. */
-
-x_make_frame_visible (f)
- struct frame *f;
-{
- BLOCK_INPUT;
-
- if (! FRAME_VISIBLE_P (f))
- {
- /* We test FRAME_GARBAGED_P here to make sure we don't
- call x_set_offset a second time
- if we get to x_make_frame_visible a second time
- before the window gets really visible. */
- if (! FRAME_ICONIFIED_P (f)
- && ! f->output_data.w32->asked_for_visible)
- {
- x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
-// SetForegroundWindow (FRAME_W32_WINDOW (f));
- }
-
- f->output_data.w32->asked_for_visible = 1;
-
- my_show_window (FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
- }
-
- /* Synchronize to ensure Emacs knows the frame is visible
- before we do anything else. We do this loop with input not blocked
- so that incoming events are handled. */
- {
- Lisp_Object frame;
- int count = input_signal_count;
-
- /* This must come after we set COUNT. */
- UNBLOCK_INPUT;
-
- XSETFRAME (frame, f);
-
- while (1)
- {
- /* Once we have handled input events,
- we should have received the MapNotify if one is coming.
- So if we have not got it yet, stop looping.
- Some window managers make their own decisions
- about visibility. */
- if (input_signal_count != count)
- break;
- /* Machines that do polling rather than SIGIO have been observed
- to go into a busy-wait here. So we'll fake an alarm signal
- to let the handler know that there's something to be read.
- We used to raise a real alarm, but it seems that the handler
- isn't always enabled here. This is probably a bug. */
- if (input_polling_used ())
- {
- /* It could be confusing if a real alarm arrives while processing
- the fake one. Turn it off and let the handler reset it. */
- alarm (0);
- input_poll_signal ();
- }
- /* Once we have handled input events,
- we should have received the MapNotify if one is coming.
- So if we have not got it yet, stop looping.
- Some window managers make their own decisions
- about visibility. */
- if (input_signal_count != count)
- break;
- }
- FRAME_SAMPLE_VISIBILITY (f);
- }
-}
-
-/* Change from mapped state to withdrawn state. */
-
-/* Make the frame visible (mapped and not iconified). */
-
-x_make_frame_invisible (f)
- struct frame *f;
-{
- Window window;
-
- /* Don't keep the highlight on an invisible frame. */
- if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
- FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
-
- BLOCK_INPUT;
-
- my_show_window (FRAME_W32_WINDOW (f), SW_HIDE);
-
- /* We can't distinguish this from iconification
- just by the event that we get from the server.
- So we can't win using the usual strategy of letting
- FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
- and synchronize with the server to make sure we agree. */
- f->visible = 0;
- FRAME_ICONIFIED_P (f) = 0;
- f->async_visible = 0;
- f->async_iconified = 0;
-
- UNBLOCK_INPUT;
-}
-
-/* Change window state from mapped to iconified. */
-
-void
-x_iconify_frame (f)
- struct frame *f;
-{
- int result;
-
- /* Don't keep the highlight on an invisible frame. */
- if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
- FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
-
- if (f->async_iconified)
- return;
-
- BLOCK_INPUT;
-
- my_show_window (FRAME_W32_WINDOW (f), SW_SHOWMINIMIZED);
- /* The frame doesn't seem to be lowered automatically. */
- x_lower_frame (f);
-
- f->async_iconified = 1;
-
- UNBLOCK_INPUT;
-}
-
-/* Destroy the window of frame F. */
-
-x_destroy_window (f)
- struct frame *f;
-{
- struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
-
- BLOCK_INPUT;
-
- my_destroy_window (f, FRAME_W32_WINDOW (f));
- free_frame_menubar (f);
- free_frame_faces (f);
-
- xfree (f->output_data.w32);
- f->output_data.w32 = 0;
- if (f == dpyinfo->w32_focus_frame)
- dpyinfo->w32_focus_frame = 0;
- if (f == dpyinfo->w32_focus_event_frame)
- dpyinfo->w32_focus_event_frame = 0;
- if (f == dpyinfo->w32_highlight_frame)
- dpyinfo->w32_highlight_frame = 0;
-
- dpyinfo->reference_count--;
-
- if (f == dpyinfo->mouse_face_mouse_frame)
- {
- dpyinfo->mouse_face_beg_row
- = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row
- = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
- }
-
- UNBLOCK_INPUT;
-}
-
-/* Setting window manager hints. */
-
-/* Set the normal size hints for the window manager, for frame F.
- FLAGS is the flags word to use--or 0 meaning preserve the flags
- that the window now has.
- If USER_POSITION is nonzero, we set the USPosition
- flag (this is useful when FLAGS is 0). */
-
-x_wm_set_size_hint (f, flags, user_position)
- struct frame *f;
- long flags;
- int user_position;
-{
- Window window = FRAME_W32_WINDOW (f);
-
- flexlines = f->height;
-
- enter_crit ();
-
- SetWindowLong (window, WND_X_UNITS_INDEX, FONT_WIDTH (f->output_data.w32->font));
- SetWindowLong (window, WND_Y_UNITS_INDEX, f->output_data.w32->line_height);
-
- leave_crit ();
-}
-
-/* Window manager things */
-x_wm_set_icon_position (f, icon_x, icon_y)
- struct frame *f;
- int icon_x, icon_y;
-{
-#if 0
- Window window = FRAME_W32_WINDOW (f);
-
- f->display.x->wm_hints.flags |= IconPositionHint;
- f->display.x->wm_hints.icon_x = icon_x;
- f->display.x->wm_hints.icon_y = icon_y;
-
- XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
-#endif
-}
-
-
-/* Initialization. */
-
-#ifdef USE_X_TOOLKIT
-static XrmOptionDescRec emacs_options[] = {
- {"-geometry", ".geometry", XrmoptionSepArg, NULL},
- {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
-
- {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
- XrmoptionSepArg, NULL},
- {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
-
- {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
- {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
- {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
- {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
- {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
- {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
- {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
-};
-#endif /* USE_X_TOOLKIT */
-
-static int w32_initialized = 0;
-
-struct w32_display_info *
-w32_term_init (display_name, xrm_option, resource_name)
- Lisp_Object display_name;
- char *xrm_option;
- char *resource_name;
-{
- Lisp_Object frame;
- char *defaultvalue;
- struct w32_display_info *dpyinfo;
- HDC hdc;
-
- BLOCK_INPUT;
-
- if (!w32_initialized)
- {
- w32_initialize ();
- w32_initialized = 1;
- }
-
- {
- int argc = 0;
- char *argv[3];
-
- argv[0] = "";
- argc = 1;
- if (xrm_option)
- {
- argv[argc++] = "-xrm";
- argv[argc++] = xrm_option;
- }
- }
-
- dpyinfo = &one_w32_display_info;
-
- /* Put this display on the chain. */
- dpyinfo->next = NULL;
-
- /* Put it on w32_display_name_list as well, to keep them parallel. */
- w32_display_name_list = Fcons (Fcons (display_name, Qnil),
- w32_display_name_list);
- dpyinfo->name_list_element = XCONS (w32_display_name_list)->car;
-
- dpyinfo->w32_id_name
- = (char *) xmalloc (XSTRING (Vinvocation_name)->size
- + XSTRING (Vsystem_name)->size
- + 2);
- sprintf (dpyinfo->w32_id_name, "%s@%s",
- XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
-
-#if 0
- xrdb = x_load_resources (dpyinfo->display, xrm_option,
- resource_name, EMACS_CLASS);
-
- /* Put the rdb where we can find it in a way that works on
- all versions. */
- dpyinfo->xrdb = xrdb;
-#endif
- hdc = GetDC (GetDesktopWindow ());
-
- dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
- dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
- dpyinfo->root_window = GetDesktopWindow ();
- dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
- dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
- dpyinfo->height_in = GetDeviceCaps (hdc, LOGPIXELSX);
- dpyinfo->width_in = GetDeviceCaps (hdc, LOGPIXELSY);
- dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
- dpyinfo->grabbed = 0;
- dpyinfo->reference_count = 0;
- dpyinfo->n_fonts = 0;
- dpyinfo->font_table_size = 0;
- dpyinfo->bitmaps = 0;
- dpyinfo->bitmaps_size = 0;
- dpyinfo->bitmaps_last = 0;
- dpyinfo->mouse_face_mouse_frame = 0;
- dpyinfo->mouse_face_deferred_gc = 0;
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_face_id = 0;
- dpyinfo->mouse_face_window = Qnil;
- dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
- dpyinfo->mouse_face_defer = 0;
- dpyinfo->w32_focus_frame = 0;
- dpyinfo->w32_focus_event_frame = 0;
- dpyinfo->w32_highlight_frame = 0;
-
- ReleaseDC (GetDesktopWindow (), hdc);
-
- /* Determine if there is a middle mouse button, to allow parse_button
- to decide whether right mouse events should be mouse-2 or
- mouse-3. */
- XSETINT (Vw32_num_mouse_buttons, GetSystemMetrics (SM_CMOUSEBUTTONS));
-
- /* initialise palette with white and black */
- {
- COLORREF color;
- defined_color (0, "white", &color, 1);
- defined_color (0, "black", &color, 1);
- }
-
-#ifndef F_SETOWN_BUG
-#ifdef F_SETOWN
-#ifdef F_SETOWN_SOCK_NEG
- /* stdin is a socket here */
- fcntl (connection, F_SETOWN, -getpid ());
-#else /* ! defined (F_SETOWN_SOCK_NEG) */
- fcntl (connection, F_SETOWN, getpid ());
-#endif /* ! defined (F_SETOWN_SOCK_NEG) */
-#endif /* ! defined (F_SETOWN) */
-#endif /* F_SETOWN_BUG */
-
-#ifdef SIGIO
- if (interrupt_input)
- init_sigio (connection);
-#endif /* ! defined (SIGIO) */
-
- UNBLOCK_INPUT;
-
- return dpyinfo;
-}
-
-/* Get rid of display DPYINFO, assuming all frames are already gone. */
-
-void
-x_delete_display (dpyinfo)
- struct w32_display_info *dpyinfo;
-{
- /* Discard this display from w32_display_name_list and w32_display_list.
- We can't use Fdelq because that can quit. */
- if (! NILP (w32_display_name_list)
- && EQ (XCONS (w32_display_name_list)->car, dpyinfo->name_list_element))
- w32_display_name_list = XCONS (w32_display_name_list)->cdr;
- else
- {
- Lisp_Object tail;
-
- tail = w32_display_name_list;
- while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
- {
- if (EQ (XCONS (XCONS (tail)->cdr)->car,
- dpyinfo->name_list_element))
- {
- XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
- break;
- }
- tail = XCONS (tail)->cdr;
- }
- }
-
- /* free palette table */
- {
- struct w32_palette_entry * plist;
-
- plist = dpyinfo->color_list;
- while (plist)
- {
- struct w32_palette_entry * pentry = plist;
- plist = plist->next;
- xfree(pentry);
- }
- dpyinfo->color_list = NULL;
- if (dpyinfo->palette)
- DeleteObject(dpyinfo->palette);
- }
- xfree (dpyinfo->font_table);
- xfree (dpyinfo->w32_id_name);
-}
-
-/* Set up use of W32. */
-
-DWORD win_msg_worker ();
-
-w32_initialize ()
-{
- clear_frame_hook = w32_clear_frame;
- clear_end_of_line_hook = w32_clear_end_of_line;
- ins_del_lines_hook = w32_ins_del_lines;
- change_line_highlight_hook = w32_change_line_highlight;
- insert_glyphs_hook = w32_insert_glyphs;
- write_glyphs_hook = w32_write_glyphs;
- delete_glyphs_hook = w32_delete_glyphs;
- ring_bell_hook = w32_ring_bell;
- reset_terminal_modes_hook = w32_reset_terminal_modes;
- set_terminal_modes_hook = w32_set_terminal_modes;
- update_begin_hook = w32_update_begin;
- update_end_hook = w32_update_end;
- set_terminal_window_hook = w32_set_terminal_window;
- read_socket_hook = w32_read_socket;
- frame_up_to_date_hook = w32_frame_up_to_date;
- cursor_to_hook = w32_cursor_to;
- reassert_line_highlight_hook = w32_reassert_line_highlight;
- mouse_position_hook = w32_mouse_position;
- frame_rehighlight_hook = w32_frame_rehighlight;
- frame_raise_lower_hook = w32_frame_raise_lower;
- set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
- condemn_scroll_bars_hook = w32_condemn_scroll_bars;
- redeem_scroll_bar_hook = w32_redeem_scroll_bar;
- judge_scroll_bars_hook = w32_judge_scroll_bars;
-
- scroll_region_ok = 1; /* we'll scroll partial frames */
- char_ins_del_ok = 0; /* just as fast to write the line */
- line_ins_del_ok = 1; /* we'll just blt 'em */
- fast_clear_end_of_line = 1; /* X does this well */
- memory_below_frame = 0; /* we don't remember what scrolls
- off the bottom */
- baud_rate = 19200;
-
- /* Try to use interrupt input; if we can't, then start polling. */
- Fset_input_mode (Qt, Qnil, Qt, Qnil);
-
- /* Create the window thread - it will terminate itself or when the app terminates */
-
- init_crit ();
-
- dwMainThreadId = GetCurrentThreadId ();
- DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
- GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
-
- /* Wait for thread to start */
-
- {
- MSG msg;
-
- PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
-
- hWinThread = CreateThread (NULL, 0,
- (LPTHREAD_START_ROUTINE) win_msg_worker,
- 0, 0, &dwWinThreadId);
-
- GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
- }
-
- /* It is desirable that mainThread should have the same notion of
- focus window and active window as winThread. Unfortunately, the
- following call to AttachThreadInput, which should do precisely what
- we need, causes major problems when Emacs is linked as a console
- program. Unfortunately, we have good reasons for doing that, so
- instead we need to send messages to winThread to make some API
- calls for us (ones that affect, or depend on, the active/focus
- window state. */
-#ifdef ATTACH_THREADS
- AttachThreadInput (dwMainThreadId, dwWinThreadId, TRUE);
-#endif
-}
-
-void
-syms_of_w32term ()
-{
- staticpro (&w32_display_name_list);
- w32_display_name_list = Qnil;
-
- staticpro (&last_mouse_scroll_bar);
- last_mouse_scroll_bar = Qnil;
-
- staticpro (&Qvendor_specific_keysyms);
- Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
-
- DEFVAR_INT ("w32-num-mouse-buttons",
- &Vw32_num_mouse_buttons,
- "Number of physical mouse buttons.");
- Vw32_num_mouse_buttons = Qnil;
-
- DEFVAR_LISP ("w32-swap-mouse-buttons",
- &Vw32_swap_mouse_buttons,
- "Swap the mapping of middle and right mouse buttons.\n\
-When nil, middle button is mouse-2 and right button is mouse-3.");
- Vw32_swap_mouse_buttons = Qnil;
-}
diff --git a/src/w32term.h b/src/w32term.h
deleted file mode 100644
index c872730397d..00000000000
--- a/src/w32term.h
+++ /dev/null
@@ -1,658 +0,0 @@
-/* Definitions and headers for communication under the Win32 API.
- Copyright (C) 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Added by Kevin Gallo */
-
-#include <win32.h>
-
-/* The class of this X application. */
-#define EMACS_CLASS "Emacs"
-
-#define BLACK_PIX_DEFAULT(f) PALETTERGB(0,0,0)
-#define WHITE_PIX_DEFAULT(f) PALETTERGB(255,255,255)
-
-#define FONT_WIDTH(f) ((f)->tm.tmAveCharWidth)
-#define FONT_HEIGHT(f) ((f)->tm.tmHeight)
-#define FONT_BASE(f) ((f)->tm.tmAscent)
-
-#define CHECK_W32_FRAME(f, frame) \
- if (NILP (frame)) \
- f = selected_frame; \
- else \
- { \
- CHECK_LIVE_FRAME (frame, 0); \
- f = XFRAME (frame); \
- } \
- if (! FRAME_W32_P (f))
-
-/* Indicates whether we are in the readsocket call and the message we
- are processing in the current loop */
-
-extern MSG CurMsg;
-extern BOOL bUseDflt;
-
-extern struct frame *x_window_to_frame ();
-
-enum text_cursor_kinds {
- filled_box_cursor, hollow_box_cursor, bar_cursor
-};
-
-/* This data type is used for the font_table field
- of struct w32_display_info. */
-
-struct font_info
-{
- XFontStruct *font;
- char *name;
-};
-
-/* Structure recording bitmaps and reference count.
- If REFCOUNT is 0 then this record is free to be reused. */
-
-struct w32_bitmap_record
-{
- Pixmap pixmap;
- char *file;
- HINSTANCE hinst; /* Used to load the file */
- int refcount;
- /* Record some info about this pixmap. */
- int height, width, depth;
-};
-
-/* Palette book-keeping stuff for mapping requested colors into the
- system palette. Keep a ref-counted list of requested colors and
- regenerate the app palette whenever the requested list changes. */
-
-extern Lisp_Object Vw32_enable_palette;
-
-struct w32_palette_entry {
- struct w32_palette_entry * next;
- PALETTEENTRY entry;
-#if 0
- unsigned refcount;
-#endif
-};
-
-extern void w32_regenerate_palette(struct frame *f);
-
-
-/* For each display (currently only one on w32), we have a structure that
- records information about it. */
-
-struct w32_display_info
-{
- /* Chain of all w32_display_info structures. */
- struct w32_display_info *next;
- /* This is a cons cell of the form (NAME . FONT-LIST-CACHE).
- The same cons cell also appears in x_display_name_list. */
- Lisp_Object name_list_element;
- /* Number of frames that are on this display. */
- int reference_count;
- /* Number of planes on this screen. */
- int n_planes;
- /* Number of bits per pixel on this screen. */
- int n_cbits;
- /* Dimensions of this screen. */
- int height, width;
- int height_in,width_in;
- /* Mask of things that cause the mouse to be grabbed. */
- int grabbed;
- /* The root window of this screen. */
- Window root_window;
- /* The cursor to use for vertical scroll bars. */
- Cursor vertical_scroll_bar_cursor;
-
- /* color palette information */
- int has_palette;
- struct w32_palette_entry * color_list;
- unsigned num_colors;
- HPALETTE palette;
-
- /* deferred action flags checked when starting frame update */
- int regen_palette;
-
- /* A table of all the fonts we have already loaded. */
- struct font_info *font_table;
-
- /* The current capacity of x_font_table. */
- int font_table_size;
-
- /* These variables describe the range of text currently shown
- in its mouse-face, together with the window they apply to.
- As long as the mouse stays within this range, we need not
- redraw anything on its account. */
- int mouse_face_beg_row, mouse_face_beg_col;
- int mouse_face_end_row, mouse_face_end_col;
- int mouse_face_past_end;
- Lisp_Object mouse_face_window;
- int mouse_face_face_id;
-
- /* 1 if a mouse motion event came and we didn't handle it right away because
- gc was in progress. */
- int mouse_face_deferred_gc;
-
- /* FRAME and X, Y position of mouse when last checked for
- highlighting. X and Y can be negative or out of range for the frame. */
- struct frame *mouse_face_mouse_frame;
- int mouse_face_mouse_x, mouse_face_mouse_y;
-
- /* Nonzero means defer mouse-motion highlighting. */
- int mouse_face_defer;
-
- char *w32_id_name;
-
- /* The number of fonts actually stored in w32_font_table.
- font_table[n] is used and valid iff 0 <= n < n_fonts.
- 0 <= n_fonts <= font_table_size. */
- int n_fonts;
-
- /* Pointer to bitmap records. */
- struct w32_bitmap_record *bitmaps;
-
- /* Allocated size of bitmaps field. */
- int bitmaps_size;
-
- /* Last used bitmap index. */
- int bitmaps_last;
-
- /* The frame (if any) which has the window that has keyboard focus.
- Zero if none. This is examined by Ffocus_frame in w32fns.c. Note
- that a mere EnterNotify event can set this; if you need to know the
- last frame specified in a FocusIn or FocusOut event, use
- w32_focus_event_frame. */
- struct frame *w32_focus_frame;
-
- /* The last frame mentioned in a FocusIn or FocusOut event. This is
- separate from w32_focus_frame, because whether or not LeaveNotify
- events cause us to lose focus depends on whether or not we have
- received a FocusIn event for it. */
- struct frame *w32_focus_event_frame;
-
- /* The frame which currently has the visual highlight, and should get
- keyboard input (other sorts of input have the frame encoded in the
- event). It points to the focus frame's selected window's
- frame. It differs from w32_focus_frame when we're using a global
- minibuffer. */
- struct frame *w32_highlight_frame;
-};
-
-/* This is a chain of structures for all the displays currently in use. */
-extern struct w32_display_info one_w32_display_info;
-
-/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
- one for each element of w32_display_list and in the same order.
- NAME is the name of the frame.
- FONT-LIST-CACHE records previous values returned by x-list-fonts. */
-extern Lisp_Object w32_display_name_list;
-
-extern struct w32_display_info *x_display_info_for_display ();
-extern struct w32_display_info *x_display_info_for_name ();
-
-extern struct w32_display_info *w32_term_init ();
-
-/* Each W32 frame object points to its own struct w32_display object
- in the output_data.w32 field. The w32_display structure contains all
- the information that is specific to W32 windows. */
-
-struct w32_output
-{
- /* Original palette (used to deselect real palette after drawing) */
- HPALETTE old_palette;
-
- /* Position of the W32 window (x and y offsets in root window). */
- int left_pos;
- int top_pos;
-
- /* Border width of the W32 window as known by the window system. */
- int border_width;
-
- /* Size of the W32 window in pixels. */
- int pixel_height, pixel_width;
-
- /* Height of a line, in pixels. */
- int line_height;
-
- /* Width of the internal border. This is a line of background color
- just inside the window's border. When the frame is selected,
- a highlighting is displayed inside the internal border. */
- int internal_border_width;
-
- /* The window used for this frame.
- May be zero while the frame object is being created
- and the window has not yet been created. */
- Window window_desc;
-
- /* The window that is the parent of this window.
- Usually this is a window that was made by the window manager,
- but it can be the root window, and it can be explicitly specified
- (see the explicit_parent field, below). */
- Window parent_desc;
-
- XFontStruct *font;
-
- /* Pixel values used for various purposes.
- border_pixel may be -1 meaning use a gray tile. */
- unsigned long background_pixel;
- unsigned long foreground_pixel;
- unsigned long cursor_pixel;
- unsigned long border_pixel;
- unsigned long mouse_pixel;
- unsigned long cursor_foreground_pixel;
-
- /* Descriptor for the cursor in use for this window. */
- Cursor text_cursor;
- Cursor nontext_cursor;
- Cursor modeline_cursor;
- Cursor cross_cursor;
-
- /* Flag to set when the window needs to be completely repainted. */
- int needs_exposure;
-
- /* What kind of text cursor is drawn in this window right now?
- (If there is no cursor (phys_cursor_x < 0), then this means nothing.) */
- enum text_cursor_kinds current_cursor;
-
- /* What kind of text cursor should we draw in the future?
- This should always be filled_box_cursor or bar_cursor. */
- enum text_cursor_kinds desired_cursor;
-
- /* Width of bar cursor (if we are using that). */
- int cursor_width;
-
- DWORD dwStyle;
-
- /* The size of the extra width currently allotted for vertical
- scroll bars, in pixels. */
- int vertical_scroll_bar_extra;
-
- /* Table of parameter faces for this frame. Any resources (pixel
- values, fonts) referred to here have been allocated explicitly
- for this face, and should be freed if we change the face. */
- struct face **param_faces;
- int n_param_faces;
-
- /* Table of computed faces for this frame. These are the faces
- whose indexes go into the upper bits of a glyph, computed by
- combining the parameter faces specified by overlays, text
- properties, and what have you. The resources mentioned here
- are all shared with parameter faces. */
- struct face **computed_faces;
- int n_computed_faces; /* How many are valid */
- int size_computed_faces; /* How many are allocated */
-
- /* This is the gravity value for the specified window position. */
- int win_gravity;
-
- /* The geometry flags for this window. */
- int size_hint_flags;
-
- /* This is the Emacs structure for the display this frame is on. */
- /* struct w32_display_info *display_info; */
-
- /* Nonzero means our parent is another application's window
- and was explicitly specified. */
- char explicit_parent;
-
- /* Nonzero means tried already to make this frame visible. */
- char asked_for_visible;
-};
-
-/* Get at the computed faces of an X window frame. */
-#define FRAME_PARAM_FACES(f) ((f)->output_data.w32->param_faces)
-#define FRAME_N_PARAM_FACES(f) ((f)->output_data.w32->n_param_faces)
-#define FRAME_DEFAULT_PARAM_FACE(f) (FRAME_PARAM_FACES (f)[0])
-#define FRAME_MODE_LINE_PARAM_FACE(f) (FRAME_PARAM_FACES (f)[1])
-
-#define FRAME_COMPUTED_FACES(f) ((f)->output_data.w32->computed_faces)
-#define FRAME_N_COMPUTED_FACES(f) ((f)->output_data.w32->n_computed_faces)
-#define FRAME_SIZE_COMPUTED_FACES(f) ((f)->output_data.w32->size_computed_faces)
-#define FRAME_DEFAULT_FACE(f) ((f)->output_data.w32->computed_faces[0])
-#define FRAME_MODE_LINE_FACE(f) ((f)->output_data.w32->computed_faces[1])
-
-/* Return the window associated with the frame F. */
-#define FRAME_W32_WINDOW(f) ((f)->output_data.w32->window_desc)
-
-#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.w32->foreground_pixel)
-#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.w32->background_pixel)
-#define FRAME_FONT(f) ((f)->output_data.w32->font)
-#define FRAME_INTERNAL_BORDER_WIDTH(f) ((f)->output_data.w32->internal_border_width)
-
-/* This gives the w32_display_info structure for the display F is on. */
-#define FRAME_W32_DISPLAY_INFO(f) (&one_w32_display_info)
-
-/* These two really ought to be called FRAME_PIXEL_{WIDTH,HEIGHT}. */
-#define PIXEL_WIDTH(f) ((f)->output_data.w32->pixel_width)
-#define PIXEL_HEIGHT(f) ((f)->output_data.w32->pixel_height)
-#define FRAME_LINE_HEIGHT(f) ((f)->output_data.w32->line_height)
-
-#define FRAME_DESIRED_CURSOR(f) ((f)->output_data.w32->desired_cursor)
-
-
-/* W32-specific scroll bar stuff. */
-
-/* We represent scroll bars as lisp vectors. This allows us to place
- references to them in windows without worrying about whether we'll
- end up with windows referring to dead scroll bars; the garbage
- collector will free it when its time comes.
-
- We use struct scroll_bar as a template for accessing fields of the
- vector. */
-
-struct scroll_bar {
-
- /* These fields are shared by all vectors. */
- EMACS_INT size_from_Lisp_Vector_struct;
- struct Lisp_Vector *next_from_Lisp_Vector_struct;
-
- /* The window we're a scroll bar for. */
- Lisp_Object window;
-
- /* The next and previous in the chain of scroll bars in this frame. */
- Lisp_Object next, prev;
-
- /* The window representing this scroll bar. Since this is a full
- 32-bit quantity, we store it split into two 32-bit values. */
- Lisp_Object w32_window_low, w32_window_high;
-
- /* The position and size of the scroll bar in pixels, relative to the
- frame. */
- Lisp_Object top, left, width, height;
-
- /* The starting and ending positions of the handle, relative to the
- handle area (i.e. zero is the top position, not
- SCROLL_BAR_TOP_BORDER). If they're equal, that means the handle
- hasn't been drawn yet.
-
- These are not actually the locations where the beginning and end
- are drawn; in order to keep handles from becoming invisible when
- editing large files, we establish a minimum height by always
- drawing handle bottoms VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
- where they would be normally; the bottom and top are in a
- different co-ordinate system. */
- Lisp_Object start, end;
-
- /* If the scroll bar handle is currently being dragged by the user,
- this is the number of pixels from the top of the handle to the
- place where the user grabbed it. If the handle isn't currently
- being dragged, this is Qnil. */
- Lisp_Object dragging;
-};
-
-/* The number of elements a vector holding a struct scroll_bar needs. */
-#define SCROLL_BAR_VEC_SIZE \
- ((sizeof (struct scroll_bar) \
- - sizeof (EMACS_INT) - sizeof (struct Lisp_Vector *)) \
- / sizeof (Lisp_Object))
-
-/* Turning a lisp vector value into a pointer to a struct scroll_bar. */
-#define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec))
-
-
-/* Building a 32-bit C integer from two 16-bit lisp integers. */
-#define SCROLL_BAR_PACK(low, high) (XINT (high) << 16 | XINT (low))
-
-/* Setting two lisp integers to the low and high words of a 32-bit C int. */
-#define SCROLL_BAR_UNPACK(low, high, int32) \
- (XSETINT ((low), (int32) & 0xffff), \
- XSETINT ((high), ((int32) >> 16) & 0xffff))
-
-
-/* Extract the window id of the scroll bar from a struct scroll_bar. */
-#define SCROLL_BAR_W32_WINDOW(ptr) \
- ((Window) SCROLL_BAR_PACK ((ptr)->w32_window_low, (ptr)->w32_window_high))
-
-/* Store a window id in a struct scroll_bar. */
-#define SET_SCROLL_BAR_W32_WINDOW(ptr, id) \
- (SCROLL_BAR_UNPACK ((ptr)->w32_window_low, (ptr)->w32_window_high, (int) id))
-
-
-/* Return the outside pixel height for a vertical scroll bar HEIGHT
- rows high on frame F. */
-#define VERTICAL_SCROLL_BAR_PIXEL_HEIGHT(f, height) \
- ((height) * (f)->output_data.w32->line_height)
-
-/* Return the inside width of a vertical scroll bar, given the outside
- width. */
-#define VERTICAL_SCROLL_BAR_INSIDE_WIDTH(width) \
- ((width) - VERTICAL_SCROLL_BAR_LEFT_BORDER - VERTICAL_SCROLL_BAR_RIGHT_BORDER)
-
-/* Return the length of the rectangle within which the top of the
- handle must stay. This isn't equivalent to the inside height,
- because the scroll bar handle has a minimum height.
-
- This is the real range of motion for the scroll bar, so when we're
- scaling buffer positions to scroll bar positions, we use this, not
- VERTICAL_SCROLL_BAR_INSIDE_HEIGHT. */
-#define VERTICAL_SCROLL_BAR_TOP_RANGE(height) \
- (VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (height) - VERTICAL_SCROLL_BAR_MIN_HANDLE)
-
-/* Return the inside height of vertical scroll bar, given the outside
- height. See VERTICAL_SCROLL_BAR_TOP_RANGE too. */
-#define VERTICAL_SCROLL_BAR_INSIDE_HEIGHT(height) \
- ((height) - VERTICAL_SCROLL_BAR_TOP_BORDER - VERTICAL_SCROLL_BAR_BOTTOM_BORDER)
-
-
-/* Border widths for scroll bars.
-
- Scroll bar windows don't have any borders; their border width is
- set to zero, and we redraw borders ourselves. This makes the code
- a bit cleaner, since we don't have to convert between outside width
- (used when relating to the rest of the screen) and inside width
- (used when sizing and drawing the scroll bar window itself).
-
- The handle moves up and down/back and forth in a rectangle inset
- from the edges of the scroll bar. These are widths by which we
- inset the handle boundaries from the scroll bar edges. */
-#define VERTICAL_SCROLL_BAR_LEFT_BORDER (0)
-#define VERTICAL_SCROLL_BAR_RIGHT_BORDER (0)
-#define VERTICAL_SCROLL_BAR_TOP_BORDER (0)
-#define VERTICAL_SCROLL_BAR_BOTTOM_BORDER (0)
-
-/* Minimum lengths for scroll bar handles, in pixels. */
-#define VERTICAL_SCROLL_BAR_MIN_HANDLE (0)
-
-
-/* Manipulating pixel sizes and character sizes.
- Knowledge of which factors affect the overall size of the window should
- be hidden in these macros, if that's possible.
-
- Return the upper/left pixel position of the character cell on frame F
- at ROW/COL. */
-#define CHAR_TO_PIXEL_ROW(f, row) \
- ((f)->output_data.w32->internal_border_width \
- + (row) * (f)->output_data.w32->line_height)
-#define CHAR_TO_PIXEL_COL(f, col) \
- ((f)->output_data.w32->internal_border_width \
- + (col) * FONT_WIDTH ((f)->output_data.w32->font))
-
-/* Return the pixel width/height of frame F if it has
- WIDTH columns/HEIGHT rows. */
-#define CHAR_TO_PIXEL_WIDTH(f, width) \
- (CHAR_TO_PIXEL_COL (f, width) \
- + (f)->output_data.w32->vertical_scroll_bar_extra \
- + (f)->output_data.w32->internal_border_width)
-#define CHAR_TO_PIXEL_HEIGHT(f, height) \
- (CHAR_TO_PIXEL_ROW (f, height) \
- + (f)->output_data.w32->internal_border_width)
-
-
-/* Return the row/column (zero-based) of the character cell containing
- the pixel on FRAME at ROW/COL. */
-#define PIXEL_TO_CHAR_ROW(f, row) \
- (((row) - (f)->output_data.w32->internal_border_width) \
- / (f)->output_data.w32->line_height)
-#define PIXEL_TO_CHAR_COL(f, col) \
- (((col) - (f)->output_data.w32->internal_border_width) \
- / FONT_WIDTH ((f)->output_data.w32->font))
-
-/* How many columns/rows of text can we fit in WIDTH/HEIGHT pixels on
- frame F? */
-#define PIXEL_TO_CHAR_WIDTH(f, width) \
- (PIXEL_TO_CHAR_COL (f, ((width) \
- - (f)->output_data.w32->internal_border_width \
- - (f)->output_data.w32->vertical_scroll_bar_extra)))
-#define PIXEL_TO_CHAR_HEIGHT(f, height) \
- (PIXEL_TO_CHAR_ROW (f, ((height) \
- - (f)->output_data.w32->internal_border_width)))
-
-/* Interface to the face code functions. */
-
-/* Create the first two computed faces for a frame -- the ones that
- have GC's. */
-extern void init_frame_faces (/* FRAME_PTR */);
-
-/* Free the resources for the faces associated with a frame. */
-extern void free_frame_faces (/* FRAME_PTR */);
-
-/* Given a computed face, find or make an equivalent display face
- in face_vector, and return a pointer to it. */
-extern struct face *intern_face (/* FRAME_PTR, struct face * */);
-
-/* Given a frame and a face name, return the face's ID number, or
- zero if it isn't a recognized face name. */
-extern int face_name_id_number (/* FRAME_PTR, Lisp_Object */);
-
-/* Return non-zero if FONT1 and FONT2 have the same size bounding box.
- We assume that they're both character-cell fonts. */
-extern int same_size_fonts (/* XFontStruct *, XFontStruct * */);
-
-/* Recompute the GC's for the default and modeline faces.
- We call this after changing frame parameters on which those GC's
- depend. */
-extern void recompute_basic_faces (/* FRAME_PTR */);
-
-/* Return the face ID associated with a buffer position POS. Store
- into *ENDPTR the next position at which a different face is
- needed. This does not take account of glyphs that specify their
- own face codes. F is the frame in use for display, and W is a
- window displaying the current buffer.
-
- REGION_BEG, REGION_END delimit the region, so it can be highlighted. */
-extern int compute_char_face (/* FRAME_PTR frame,
- struct window *w,
- int pos,
- int region_beg, int region_end,
- int *endptr */);
-/* Return the face ID to use to display a special glyph which selects
- FACE_CODE as the face ID, assuming that ordinarily the face would
- be BASIC_FACE. F is the frame. */
-extern int compute_glyph_face (/* FRAME_PTR, int */);
-
-extern void w32_fill_rect ();
-extern void w32_clear_window ();
-
-#define w32_fill_area(f,hdc,pix,x,y,nx,ny) \
-{ \
- RECT rect; \
- rect.left = x; \
- rect.top = y; \
- rect.right = x + nx; \
- rect.bottom = y + ny; \
- w32_fill_rect (f,hdc,pix,&rect); \
-}
-
-#define w32_clear_rect(f,hdc,lprect) \
-w32_fill_rect (f,hdc,f->output_data.w32->background_pixel,lprect)
-
-#define w32_clear_area(f,hdc,x,y,nx,ny) \
-w32_fill_area (f,hdc,f->output_data.w32->background_pixel,x,y,nx,ny)
-
-extern XFontStruct *w32_load_font ();
-extern void w32_unload_font ();
-
-#define WM_EMACS_START (WM_USER + 1)
-#define WM_EMACS_KILL (WM_EMACS_START + 0x00)
-#define WM_EMACS_CREATEWINDOW (WM_EMACS_START + 0x01)
-#define WM_EMACS_DONE (WM_EMACS_START + 0x02)
-#define WM_EMACS_CREATESCROLLBAR (WM_EMACS_START + 0x03)
-#define WM_EMACS_SHOWWINDOW (WM_EMACS_START + 0x04)
-#define WM_EMACS_SETWINDOWPOS (WM_EMACS_START + 0x05)
-#define WM_EMACS_DESTROYWINDOW (WM_EMACS_START + 0x06)
-#define WM_EMACS_END (WM_EMACS_START + 0x10)
-
-typedef struct {
- HWND hwndAfter;
- int x;
- int y;
- int cx;
- int cy;
- int flags;
-} W32WindowPos;
-
-#define WND_X_UNITS_INDEX (0)
-#define WND_Y_UNITS_INDEX (4)
-#define WND_BACKGROUND_INDEX (8)
-
-#define WND_LAST_INDEX (16)
-#define WND_EXTRA_BYTES (WND_LAST_INDEX)
-
-extern DWORD dwWinThreadId;
-extern HANDLE hWinThread;
-extern DWORD dwMainThreadId;
-extern HANDLE hMainThread;
-
-typedef struct W32Msg {
- MSG msg;
- DWORD dwModifiers;
- RECT rect;
-} W32Msg;
-
-extern CRITICAL_SECTION critsect;
-
-extern void init_crit ();
-extern void delete_crit ();
-
-#define enter_crit() EnterCriticalSection (&critsect)
-#define leave_crit() LeaveCriticalSection (&critsect)
-
-extern void select_palette (struct frame * f, HDC hdc);
-extern void deselect_palette (struct frame * f, HDC hdc);
-extern HDC get_frame_dc (struct frame * f);
-extern int release_frame_dc (struct frame * f, HDC hDC);
-
-extern BOOL get_next_msg ();
-extern BOOL post_msg ();
-extern void wait_for_sync ();
-
-extern BOOL parse_button ();
-
-/* Keypad command key support. W32 doesn't have virtual keys defined
- for the function keys on the keypad (they are mapped to the standard
- fuction keys), so we define our own. */
-#define VK_NUMPAD_BEGIN 0x92
-#define VK_NUMPAD_CLEAR (VK_NUMPAD_BEGIN + 0)
-#define VK_NUMPAD_ENTER (VK_NUMPAD_BEGIN + 1)
-#define VK_NUMPAD_PRIOR (VK_NUMPAD_BEGIN + 2)
-#define VK_NUMPAD_NEXT (VK_NUMPAD_BEGIN + 3)
-#define VK_NUMPAD_END (VK_NUMPAD_BEGIN + 4)
-#define VK_NUMPAD_HOME (VK_NUMPAD_BEGIN + 5)
-#define VK_NUMPAD_LEFT (VK_NUMPAD_BEGIN + 6)
-#define VK_NUMPAD_UP (VK_NUMPAD_BEGIN + 7)
-#define VK_NUMPAD_RIGHT (VK_NUMPAD_BEGIN + 8)
-#define VK_NUMPAD_DOWN (VK_NUMPAD_BEGIN + 9)
-#define VK_NUMPAD_INSERT (VK_NUMPAD_BEGIN + 10)
-#define VK_NUMPAD_DELETE (VK_NUMPAD_BEGIN + 11)
-
-#ifndef VK_LWIN
-/* Older compiler environments don't have these defined. */
-#define VK_LWIN 0x5B
-#define VK_RWIN 0x5C
-#define VK_APPS 0x5D
-#endif
diff --git a/src/w32xfns.c b/src/w32xfns.c
deleted file mode 100644
index e2aa3b6abc3..00000000000
--- a/src/w32xfns.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/* Functions taken directly from X sources for use with the Win32 API.
- Copyright (C) 1989, 1992, 1993, 1994, 1995 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include <signal.h>
-#include <config.h>
-#include <stdio.h>
-#include "lisp.h"
-#include "frame.h"
-#include "blockinput.h"
-#include "w32term.h"
-#include "windowsx.h"
-
-#define myalloc(cb) GlobalAllocPtr (GPTR, cb)
-#define myfree(lp) GlobalFreePtr (lp)
-
-CRITICAL_SECTION critsect;
-extern HANDLE keyboard_handle;
-HANDLE input_available = NULL;
-
-void
-init_crit ()
-{
- InitializeCriticalSection (&critsect);
-
- /* For safety, input_available should only be reset by get_next_msg
- when the input queue is empty, so make it a manual reset event. */
- keyboard_handle = input_available = CreateEvent (NULL, TRUE, FALSE, NULL);
-}
-
-void
-delete_crit ()
-{
- DeleteCriticalSection (&critsect);
-
- if (input_available)
- {
- CloseHandle (input_available);
- input_available = NULL;
- }
-}
-
-void
-select_palette (FRAME_PTR f, HDC hdc)
-{
- if (!NILP (Vw32_enable_palette))
- f->output_data.w32->old_palette =
- SelectPalette (hdc, one_w32_display_info.palette, FALSE);
- else
- f->output_data.w32->old_palette = NULL;
-
- if (RealizePalette (hdc))
- {
- Lisp_Object frame, framelist;
- FOR_EACH_FRAME (framelist, frame)
- {
- SET_FRAME_GARBAGED (XFRAME (frame));
- }
- }
-}
-
-void
-deselect_palette (FRAME_PTR f, HDC hdc)
-{
- if (f->output_data.w32->old_palette)
- SelectPalette (hdc, f->output_data.w32->old_palette, FALSE);
-}
-
-/* Get a DC for frame and select palette for drawing; force an update of
- all frames if palette's mapping changes. */
-HDC
-get_frame_dc (FRAME_PTR f)
-{
- HDC hdc;
-
- enter_crit ();
-
- hdc = GetDC (f->output_data.w32->window_desc);
- select_palette (f, hdc);
-
- return hdc;
-}
-
-int
-release_frame_dc (FRAME_PTR f, HDC hdc)
-{
- int ret;
-
- deselect_palette (f, hdc);
- ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
-
- leave_crit ();
-
- return ret;
-}
-
-typedef struct int_msg
-{
- W32Msg w32msg;
- struct int_msg *lpNext;
-} int_msg;
-
-int_msg *lpHead = NULL;
-int_msg *lpTail = NULL;
-int nQueue = 0;
-
-BOOL
-get_next_msg (lpmsg, bWait)
- W32Msg * lpmsg;
- BOOL bWait;
-{
- BOOL bRet = FALSE;
-
- enter_crit ();
-
- /* The while loop takes care of multiple sets */
-
- while (!nQueue && bWait)
- {
- leave_crit ();
- WaitForSingleObject (input_available, INFINITE);
- enter_crit ();
- }
-
- if (nQueue)
- {
- bcopy (&(lpHead->w32msg), lpmsg, sizeof (W32Msg));
-
- {
- int_msg * lpCur = lpHead;
-
- lpHead = lpHead->lpNext;
-
- myfree (lpCur);
- }
-
- nQueue--;
-
- bRet = TRUE;
- }
-
- if (nQueue == 0)
- ResetEvent (input_available);
-
- leave_crit ();
-
- return (bRet);
-}
-
-BOOL
-post_msg (lpmsg)
- W32Msg * lpmsg;
-{
- int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
-
- if (!lpNew)
- return (FALSE);
-
- bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
- lpNew->lpNext = NULL;
-
- enter_crit ();
-
- if (nQueue++)
- {
- lpTail->lpNext = lpNew;
- }
- else
- {
- lpHead = lpNew;
- }
-
- lpTail = lpNew;
- SetEvent (input_available);
-
- leave_crit ();
-
- return (TRUE);
-}
-
-BOOL
-prepend_msg (W32Msg *lpmsg)
-{
- int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
-
- if (!lpNew)
- return (FALSE);
-
- bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
-
- enter_crit ();
-
- nQueue++;
- lpNew->lpNext = lpHead;
- lpHead = lpNew;
-
- leave_crit ();
-
- return (TRUE);
-}
-
-/*
- * XParseGeometry parses strings of the form
- * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
- * width, height, xoffset, and yoffset are unsigned integers.
- * Example: "=80x24+300-49"
- * The equal sign is optional.
- * It returns a bitmask that indicates which of the four values
- * were actually found in the string. For each value found,
- * the corresponding argument is updated; for each value
- * not found, the corresponding argument is left unchanged.
- */
-
-static int
-read_integer (string, NextString)
- register char *string;
- char **NextString;
-{
- register int Result = 0;
- int Sign = 1;
-
- if (*string == '+')
- string++;
- else if (*string == '-')
- {
- string++;
- Sign = -1;
- }
- for (; (*string >= '0') && (*string <= '9'); string++)
- {
- Result = (Result * 10) + (*string - '0');
- }
- *NextString = string;
- if (Sign >= 0)
- return (Result);
- else
- return (-Result);
-}
-
-int
-XParseGeometry (string, x, y, width, height)
- char *string;
- int *x, *y;
- unsigned int *width, *height; /* RETURN */
-{
- int mask = NoValue;
- register char *strind;
- unsigned int tempWidth, tempHeight;
- int tempX, tempY;
- char *nextCharacter;
-
- if ((string == NULL) || (*string == '\0')) return (mask);
- if (*string == '=')
- string++; /* ignore possible '=' at beg of geometry spec */
-
- strind = (char *)string;
- if (*strind != '+' && *strind != '-' && *strind != 'x')
- {
- tempWidth = read_integer (strind, &nextCharacter);
- if (strind == nextCharacter)
- return (0);
- strind = nextCharacter;
- mask |= WidthValue;
- }
-
- if (*strind == 'x' || *strind == 'X')
- {
- strind++;
- tempHeight = read_integer (strind, &nextCharacter);
- if (strind == nextCharacter)
- return (0);
- strind = nextCharacter;
- mask |= HeightValue;
- }
-
- if ((*strind == '+') || (*strind == '-'))
- {
- if (*strind == '-')
- {
- strind++;
- tempX = -read_integer (strind, &nextCharacter);
- if (strind == nextCharacter)
- return (0);
- strind = nextCharacter;
- mask |= XNegative;
-
- }
- else
- {
- strind++;
- tempX = read_integer (strind, &nextCharacter);
- if (strind == nextCharacter)
- return (0);
- strind = nextCharacter;
- }
- mask |= XValue;
- if ((*strind == '+') || (*strind == '-'))
- {
- if (*strind == '-')
- {
- strind++;
- tempY = -read_integer (strind, &nextCharacter);
- if (strind == nextCharacter)
- return (0);
- strind = nextCharacter;
- mask |= YNegative;
-
- }
- else
- {
- strind++;
- tempY = read_integer (strind, &nextCharacter);
- if (strind == nextCharacter)
- return (0);
- strind = nextCharacter;
- }
- mask |= YValue;
- }
- }
-
- /* If strind isn't at the end of the string the it's an invalid
- geometry specification. */
-
- if (*strind != '\0') return (0);
-
- if (mask & XValue)
- *x = tempX;
- if (mask & YValue)
- *y = tempY;
- if (mask & WidthValue)
- *width = tempWidth;
- if (mask & HeightValue)
- *height = tempHeight;
- return (mask);
-}
-
-/* We can use mouse menus when we wish. */
-int
-have_menus_p (void)
-{
- return 1;
-}
-
-/* x_sync is a no-op on W32. */
-void
-x_sync (f)
- void *f;
-{
-}
-
diff --git a/src/widget.c b/src/widget.c
deleted file mode 100644
index db524a59350..00000000000
--- a/src/widget.c
+++ /dev/null
@@ -1,978 +0,0 @@
-/* The emacs frame widget.
- Copyright (C) 1992, 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Emacs 19 face widget ported by Fred Pierresteguy */
-
-/* This file has been censored by the Communications Decency Act.
- That law was passed under the guise of a ban on pornography, but
- it bans far more than that. This file did not contain pornography,
- but it was censored nonetheless.
-
- For information on US government censorship of the Internet, and
- what you can do to bring back freedom of the press, see the web
- site http://www.vtw.org/
- */
-
-#include <config.h>
-#include <stdio.h>
-#include "lisp.h"
-#include "xterm.h"
-
-#include "frame.h"
-
-#include "dispextern.h"
-#include "blockinput.h"
-
-#include <X11/StringDefs.h>
-#include <X11/IntrinsicP.h>
-#include <X11/cursorfont.h>
-#include "widgetprv.h"
-#include <X11/ObjectP.h>
-#include <X11/Shell.h>
-#include <X11/ShellP.h>
-#include "../lwlib/lwlib.h"
-
-#define max(a, b) ((a) > (b) ? (a) : (b))
-
-/* This sucks: this is the first default that x-faces.el tries. This won't
- be used unless neither the "Emacs.EmacsFrame" resource nor the
- "Emacs.EmacsFrame" resource is set; the frame
- may have the wrong default size if this font doesn't exist, but some other
- font that x-faces.el does. The workaround is to specify some font in the
- resource database; I don't know a solution other than duplicating the font-
- searching code from x-faces.el in this file.
-
- This also means that if "Emacs.EmacsFrame" is specified as a non-
- existent font, then Xt is going to substitute "XtDefaultFont" for it,
- which is a different size than this one. The solution for this is to
- make x-faces.el try to use XtDefaultFont. The problem with that is that
- XtDefaultFont is almost certainly variable-width.
-
- #### Perhaps we could have this code explicitly set XtDefaultFont to this?
- */
-#define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
-
-
-static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
-static void EmacsFrameDestroy (/* Widget */);
-static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
-void EmacsFrameResize (/* Widget widget */);
-static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
- ArgList, Cardinal * */);
-static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
- XtWidgetGeometry* */);
-
-
-#undef XtOffset
-#define XtOffset(p_type,field) \
- ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
-#define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
-
-static XtResource resources[] = {
- {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
- offset (geometry), XtRString, (XtPointer) 0},
- {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
- offset (iconic), XtRImmediate, (XtPointer) False},
-
- {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
- offset (frame), XtRImmediate, 0},
-
- {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
- offset (minibuffer), XtRImmediate, (XtPointer)0},
- {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
- offset (unsplittable), XtRImmediate, (XtPointer)0},
- {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
- offset (internal_border_width), XtRImmediate, (XtPointer)4},
- {XtNinterline, XtCInterline, XtRInt, sizeof (int),
- offset (interline), XtRImmediate, (XtPointer)0},
- {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
- offset(font),XtRString, DEFAULT_FACE_FONT},
- {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
- offset(foreground_pixel), XtRString, "XtDefaultForeground"},
- {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
- offset(cursor_color), XtRString, "XtDefaultForeground"},
- {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
- offset (bar_cursor), XtRImmediate, (XtPointer)0},
- {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
- offset (visual_bell), XtRImmediate, (XtPointer)0},
- {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
- offset (bell_volume), XtRImmediate, (XtPointer)0},
-};
-
-#undef offset
-
-/*
-static XtActionsRec
-emacsFrameActionsTable [] = {
- {"keypress", key_press},
- {"focus_in", emacs_frame_focus_handler},
- {"focus_out", emacs_frame_focus_handler},
-};
-
-static char
-emacsFrameTranslations [] = "\
-<KeyPress>: keypress()\n\
-<FocusIn>: focus_in()\n\
-<FocusOut>: focus_out()\n\
-";
-*/
-
-EmacsFrameClassRec emacsFrameClassRec = {
- { /* core fields */
- /* superclass */ &widgetClassRec,
- /* class_name */ "EmacsFrame",
- /* widget_size */ sizeof(EmacsFrameRec),
- /* class_initialize */ 0,
- /* class_part_initialize */ 0,
- /* class_inited */ FALSE,
- /* initialize */ EmacsFrameInitialize,
- /* initialize_hook */ 0,
- /* realize */ EmacsFrameRealize,
- /* actions */ 0, /*emacsFrameActionsTable*/
- /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
- /* resources */ resources,
- /* resource_count */ XtNumber(resources),
- /* xrm_class */ NULLQUARK,
- /* compress_motion */ TRUE,
- /* compress_exposure */ TRUE,
- /* compress_enterleave */ TRUE,
- /* visible_interest */ FALSE,
- /* destroy */ EmacsFrameDestroy,
- /* resize */ EmacsFrameResize,
- /* expose */ XtInheritExpose,
- /* set_values */ EmacsFrameSetValues,
- /* set_values_hook */ 0,
- /* set_values_almost */ XtInheritSetValuesAlmost,
- /* get_values_hook */ 0,
- /* accept_focus */ XtInheritAcceptFocus,
- /* version */ XtVersion,
- /* callback_private */ 0,
- /* tm_table */ 0, /*emacsFrameTranslations*/
- /* query_geometry */ EmacsFrameQueryGeometry,
- /* display_accelerator */ XtInheritDisplayAccelerator,
- /* extension */ 0
- }
-};
-
-WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
-
-static void
-get_default_char_pixel_size (ew, pixel_width, pixel_height)
- EmacsFrame ew;
- int* pixel_width;
- int* pixel_height;
-{
- struct frame* f = ew->emacs_frame.frame;
- *pixel_width = FONT_WIDTH (f->output_data.x->font);
- *pixel_height = f->output_data.x->line_height;
-}
-
-static void
-pixel_to_char_size (ew, pixel_width, pixel_height, char_width, char_height)
- EmacsFrame ew;
- Dimension pixel_width;
- Dimension pixel_height;
- int* char_width;
- int* char_height;
-{
- struct frame* f = ew->emacs_frame.frame;
- *char_width = PIXEL_TO_CHAR_WIDTH (f, (int) pixel_width);
- *char_height = PIXEL_TO_CHAR_HEIGHT (f, (int) pixel_height);
-}
-
-static void
-char_to_pixel_size (ew, char_width, char_height, pixel_width, pixel_height)
- EmacsFrame ew;
- int char_width;
- int char_height;
- Dimension* pixel_width;
- Dimension* pixel_height;
-{
- struct frame* f = ew->emacs_frame.frame;
- *pixel_width = CHAR_TO_PIXEL_WIDTH (f, char_width);
- *pixel_height = CHAR_TO_PIXEL_HEIGHT (f, char_height);
-}
-
-static void
-round_size_to_char (ew, in_width, in_height, out_width, out_height)
- EmacsFrame ew;
- Dimension in_width;
- Dimension in_height;
- Dimension* out_width;
- Dimension* out_height;
-{
- int char_width;
- int char_height;
- pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
- char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
-}
-
-static Widget
-get_wm_shell (w)
- Widget w;
-{
- Widget wmshell;
-
- for (wmshell = XtParent (w);
- wmshell && !XtIsWMShell (wmshell);
- wmshell = XtParent (wmshell));
-
- return wmshell;
-}
-
-static void
-mark_shell_size_user_specified (wmshell)
- Widget wmshell;
-{
- if (! XtIsWMShell (wmshell)) abort ();
- /* This is kind of sleazy, but I can't see how else to tell it to make it
- mark the WM_SIZE_HINTS size as user specified when appropriate. */
- ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
-}
-
-
-/* Can't have static frame locals because of some broken compilers.
- Normally, initializing a variable like this doesn't work in emacs,
- but it's ok in this file because it must come after lastfile (and
- thus have its data not go into text space) because Xt needs to
- write to initialized data objects too.
- */
-static Boolean first_frame_p = True;
-
-static void
-set_frame_size (ew)
- EmacsFrame ew;
-{
- /* The widget hierarchy is
-
- argv[0] emacsShell pane Frame-NAME
- ApplicationShell EmacsShell Paned EmacsFrame
-
- We accept geometry specs in this order:
-
- *Frame-NAME.geometry
- *EmacsFrame.geometry
- Emacs.geometry
-
- Other possibilities for widget hierarchies might be
-
- argv[0] frame pane Frame-NAME
- ApplicationShell EmacsShell Paned EmacsFrame
- or
- argv[0] Frame-NAME pane Frame-NAME
- ApplicationShell EmacsShell Paned EmacsFrame
- or
- argv[0] Frame-NAME pane emacsTextPane
- ApplicationShell EmacsFrame Paned EmacsTextPane
-
- With the current setup, the text-display-area is the part which is
- an emacs "frame", since that's the only part managed by emacs proper
- (the menubar and the parent of the menubar and all that sort of thing
- are managed by lwlib.)
-
- The EmacsShell widget is simply a replacement for the Shell widget
- which is able to deal with using an externally-supplied window instead
- of always creating its own. It is not actually emacs specific, and
- should possibly have class "Shell" instead of "EmacsShell" to simplify
- the resources.
-
- */
-
- /* Geometry of the AppShell */
- int app_flags = 0;
- int app_x = 0;
- int app_y = 0;
- unsigned int app_w = 0;
- unsigned int app_h = 0;
-
- /* Geometry of the EmacsFrame */
- int frame_flags = 0;
- int frame_x = 0;
- int frame_y = 0;
- unsigned int frame_w = 0;
- unsigned int frame_h = 0;
-
- /* Hairily merged geometry */
- int x = 0;
- int y = 0;
- unsigned int w = ew->emacs_frame.frame->width;
- unsigned int h = ew->emacs_frame.frame->height;
- int flags = 0;
-
- Widget wmshell = get_wm_shell ((Widget) ew);
- /* Each Emacs shell is now independent and top-level. */
- Widget app_shell = wmshell;
-
- if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
-
- /* We don't need this for the moment. The geometry is computed in
- xfns.c. */
-#if 0
- /* If the EmacsFrame doesn't have a geometry but the shell does,
- treat that as the geometry of the frame. (Is this bogus?
- I'm not sure.) */
- if (ew->emacs_frame.geometry == 0)
- XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, 0);
-
- /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
- this bogus? I'm not sure.) */
- if (!ew->emacs_frame.iconic)
- XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, 0);
-
-
- {
- char *geom = 0;
- XtVaGetValues (app_shell, XtNgeometry, &geom, 0);
- if (geom)
- app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
- }
-
- if (ew->emacs_frame.geometry)
- frame_flags = XParseGeometry (ew->emacs_frame.geometry,
- &frame_x, &frame_y,
- &frame_w, &frame_h);
-
- if (first_frame_p)
- {
- /* If this is the first frame created:
- ====================================
-
- - Use the ApplicationShell's size/position, if specified.
- (This is "Emacs.geometry", or the "-geometry" command line arg.)
- - Else use the EmacsFrame's size/position.
- (This is "*Frame-NAME.geometry")
-
- - If the AppShell is iconic, the frame should be iconic.
-
- AppShell comes first so that -geometry always applies to the first
- frame created, even if there is an "every frame" entry in the
- resource database.
- */
- if (app_flags & (XValue | YValue))
- {
- x = app_x; y = app_y;
- flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
- }
- else if (frame_flags & (XValue | YValue))
- {
- x = frame_x; y = frame_y;
- flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
- }
-
- if (app_flags & (WidthValue | HeightValue))
- {
- w = app_w; h = app_h;
- flags |= (app_flags & (WidthValue | HeightValue));
- }
- else if (frame_flags & (WidthValue | HeightValue))
- {
- w = frame_w; h = frame_h;
- flags |= (frame_flags & (WidthValue | HeightValue));
- }
-
- /* If the AppShell is iconic, then the EmacsFrame is iconic. */
- if (!ew->emacs_frame.iconic)
- XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, 0);
-
- first_frame_p = False;
- }
- else
- {
- /* If this is not the first frame created:
- ========================================
-
- - use the EmacsFrame's size/position if specified
- - Otherwise, use the ApplicationShell's size, but not position.
-
- So that means that one can specify the position of the first frame
- with "Emacs.geometry" or `-geometry'; but can only specify the
- position of subsequent frames with "*Frame-NAME.geometry".
-
- AppShell comes second so that -geometry does not apply to subsequent
- frames when there is an "every frame" entry in the resource db,
- but does apply to the first frame.
- */
- if (frame_flags & (XValue | YValue))
- {
- x = frame_x; y = frame_y;
- flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
- }
-
- if (frame_flags & (WidthValue | HeightValue))
- {
- w = frame_w; h = frame_h;
- flags |= (frame_flags & (WidthValue | HeightValue));
- }
- else if (app_flags & (WidthValue | HeightValue))
- {
- w = app_w;
- h = app_h;
- flags |= (app_flags & (WidthValue | HeightValue));
- }
- }
-#endif /* 0 */
- {
- struct frame* frame = ew->emacs_frame.frame;
- Dimension pixel_width, pixel_height;
- char shell_position [32];
-
- /* Take into account the size of the scrollbar */
- frame->output_data.x->vertical_scroll_bar_extra
- = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
- ? 0
- : FRAME_SCROLL_BAR_PIXEL_WIDTH (frame) > 0
- ? FRAME_SCROLL_BAR_PIXEL_WIDTH (frame)
- : (FRAME_SCROLL_BAR_COLS (frame)
- * FONT_WIDTH (frame->output_data.x->font)));
-
- change_frame_size (frame, h, w, 1, 0);
- char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
- ew->core.width = pixel_width;
- ew->core.height = pixel_height;
-
-#if 0 /* xfns.c takes care of this now. */
- /* If a position was specified, assign it to the shell widget.
- (Else WM won't do anything with it.)
- */
- if (flags & (XValue | YValue))
- {
- /* the tricky things with the sign is to make sure that
- -0 is printed -0. */
- int len;
- char *tem;
- sprintf (shell_position, "=%c%d%c%d",
- flags & XNegative ? '-' : '+', x < 0 ? -x : x,
- flags & YNegative ? '-' : '+', y < 0 ? -y : y);
- len = strlen (shell_position) + 1;
- tem = (char *) xmalloc (len);
- strncpy (tem, shell_position, len);
- XtVaSetValues (wmshell, XtNgeometry, tem, 0);
- }
- else if (flags & (WidthValue | HeightValue))
- {
- int len;
- char *tem;
- sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
- len = strlen (shell_position) + 1;
- tem = (char *) xmalloc (len);
- strncpy (tem, shell_position, len);
- XtVaSetValues (wmshell, XtNgeometry, tem, 0);
- }
-
- /* If the geometry spec we're using has W/H components, mark the size
- in the WM_SIZE_HINTS as user specified. */
- if (flags & (WidthValue | HeightValue))
- mark_shell_size_user_specified (wmshell);
-
- /* Also assign the iconic status of the frame to the Shell, so that
- the WM sees it. */
- XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, 0);
-#endif /* 0 */
- }
-}
-
-/* Nonzero tells update_wm_hints not to do anything
- (the caller should call update_wm_hints explicitly later.) */
-int update_hints_inhibit;
-
-static void
-update_wm_hints (ew)
- EmacsFrame ew;
-{
- Widget wmshell = get_wm_shell ((Widget)ew);
- int cw;
- int ch;
- Dimension rounded_width;
- Dimension rounded_height;
- int char_width;
- int char_height;
- int base_width;
- int base_height;
- int min_rows = 0, min_cols = 0;
-
- if (update_hints_inhibit)
- return;
-
-#if 0
- check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
-#endif
-
- pixel_to_char_size (ew, ew->core.width, ew->core.height,
- &char_width, &char_height);
- char_to_pixel_size (ew, char_width, char_height,
- &rounded_width, &rounded_height);
- get_default_char_pixel_size (ew, &cw, &ch);
-
- base_width = (wmshell->core.width - ew->core.width
- + (rounded_width - (char_width * cw)));
- base_height = (wmshell->core.height - ew->core.height
- + (rounded_height - (char_height * ch)));
-
- /* This is kind of sleazy, but I can't see how else to tell it to
- make it mark the WM_SIZE_HINTS size as user specified.
- */
-/* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
-
- XtVaSetValues (wmshell,
- XtNbaseWidth, base_width,
- XtNbaseHeight, base_height,
- XtNwidthInc, cw,
- XtNheightInc, ch,
- XtNminWidth, base_width + min_cols * cw,
- XtNminHeight, base_height + min_rows * ch,
- 0);
-}
-
-static void
-create_frame_gcs (ew)
- EmacsFrame ew;
-{
- struct frame *s = ew->emacs_frame.frame;
-
- s->output_data.x->normal_gc
- = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
- (unsigned long)0, (XGCValues *)0);
- s->output_data.x->reverse_gc
- = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
- (unsigned long)0, (XGCValues *)0);
- s->output_data.x->cursor_gc
- = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
- (unsigned long)0, (XGCValues *)0);
-}
-
-static char setup_frame_cursor_bits[] =
-{
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static void
-setup_frame_gcs (ew)
- EmacsFrame ew;
-{
- XGCValues gc_values;
- struct frame* s = ew->emacs_frame.frame;
- Pixmap blank_stipple, blank_tile;
-
- /* We have to initialize all of our GCs to have a stipple/tile, otherwise
- XGetGCValues returns uninitialized data when we query the stipple
- (instead of None or something sensible) and it makes things hard.
-
- This should be fixed for real by not querying the GCs but instead having
- some GC-based cache instead of the current face-based cache which doesn't
- effectively cache all of the GC settings we need to use.
- */
-
- blank_stipple
- = XCreateBitmapFromData (XtDisplay (ew),
- RootWindowOfScreen (XtScreen (ew)),
- setup_frame_cursor_bits, 2, 2);
-
- /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
- never actually get used as a background tile!
- */
- blank_tile
- = XCreatePixmapFromBitmapData (XtDisplay(ew),
- RootWindowOfScreen (XtScreen (ew)),
- setup_frame_cursor_bits, 2, 2,
- (unsigned long)0, (unsigned long)1,
- ew->core.depth);
-
- /* Normal video */
- gc_values.font = ew->emacs_frame.font->fid;
- gc_values.foreground = ew->emacs_frame.foreground_pixel;
- gc_values.background = ew->core.background_pixel;
- gc_values.graphics_exposures = False;
- gc_values.stipple = blank_stipple;
- gc_values.tile = blank_tile;
- XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
- (GCFont | GCForeground | GCBackground | GCGraphicsExposures
- | GCStipple | GCTile),
- &gc_values);
-
- /* Reverse video style. */
- gc_values.font = ew->emacs_frame.font->fid;
- gc_values.foreground = ew->core.background_pixel;
- gc_values.background = ew->emacs_frame.foreground_pixel;
- gc_values.graphics_exposures = False;
- gc_values.stipple = blank_stipple;
- gc_values.tile = blank_tile;
- XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
- (GCFont | GCForeground | GCBackground | GCGraphicsExposures
- | GCStipple | GCTile),
- &gc_values);
-
- /* Cursor has to have an empty stipple. */
- gc_values.font = ew->emacs_frame.font->fid;
- gc_values.foreground = ew->core.background_pixel;
- gc_values.background = ew->emacs_frame.cursor_color;
- gc_values.graphics_exposures = False;
- gc_values.tile = blank_tile;
- gc_values.stipple
- = XCreateBitmapFromData (XtDisplay (ew),
- RootWindowOfScreen (XtScreen (ew)),
- setup_frame_cursor_bits, 16, 16);
- XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
- (GCFont | GCForeground | GCBackground | GCGraphicsExposures
- | GCStipple | GCTile),
- &gc_values);
-}
-
-static void
-update_various_frame_slots (ew)
- EmacsFrame ew;
-{
- struct x_output *x = ew->emacs_frame.frame->output_data.x;
- x->pixel_height = ew->core.height + x->menubar_height;
- x->pixel_width = ew->core.width;
- x->internal_border_width = ew->emacs_frame.internal_border_width;
-
-}
-
-static void
-update_from_various_frame_slots (ew)
- EmacsFrame ew;
-{
- struct x_output *x = ew->emacs_frame.frame->output_data.x;
- ew->core.height = x->pixel_height - x->menubar_height;
- ew->core.width = x->pixel_width;
- ew->core.background_pixel = x->background_pixel;
- ew->emacs_frame.internal_border_width = x->internal_border_width;
- ew->emacs_frame.font = x->font;
- ew->emacs_frame.foreground_pixel = x->foreground_pixel;
- ew->emacs_frame.cursor_color = x->cursor_pixel;
- ew->core.border_pixel = x->border_pixel;
-}
-
-static void
-EmacsFrameInitialize (request, new, dum1, dum2)
- Widget request;
- Widget new;
- ArgList dum1;
- Cardinal *dum2;
-{
- EmacsFrame ew = (EmacsFrame)new;
-
- if (!ew->emacs_frame.frame)
- {
- fprintf (stderr,
- "can't create an emacs frame widget without a frame\n");
- exit (1);
- }
-
-#if 0 /* done in xfns.c */
- /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
- resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
- It's unfortunate that we have to do this, but we need to know the font
- size for frame-sizing purposes before the faces get initialized. If
- the "default.attributeFont" isn't set, then we use the font of this
- EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
- the "default" face will use the frame's font if its own is not set,
- so everything stays in sync -- it's not possible for the frame's font
- and the default face's font to be different.
- */
- {
- XFontStruct *f = 0;
- XtResource face_res;
- face_res.resource_name = "attributeFont";
- face_res.resource_class = "AttributeFont";
- face_res.resource_type = XtRFontStruct;
- face_res.resource_size = sizeof (XFontStruct *);
- face_res.resource_offset = 0;
- face_res.default_type = XtRImmediate;
- face_res.default_addr = 0;
- XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
- &face_res, 1, NULL, 0);
-
- if (f)
- ew->emacs_frame.font = f;
- else if (! ew->emacs_frame.font)
- {
- fprintf (stderr, "emacs frame widget could not load a font\n");
- exit (1);
- }
- }
-
-/* Update the font field in frame */
- ew->emacs_frame.frame->output_data.x->font = ew->emacs_frame.font;
-#endif
-
- update_from_various_frame_slots (ew);
- set_frame_size (ew);
-/*create_frame_gcs (ew);
- setup_frame_gcs (ew);
- update_various_frame_slots (ew); */
-}
-
-
-static void
-EmacsFrameRealize (widget, mask, attrs)
- Widget widget;
- XtValueMask *mask;
- XSetWindowAttributes *attrs;
-{
- EmacsFrame ew = (EmacsFrame)widget;
-
- attrs->event_mask = (STANDARD_EVENT_SET | PropertyChangeMask
- | SubstructureNotifyMask | SubstructureRedirectMask);
- *mask |= CWEventMask;
- XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
- attrs);
- update_wm_hints (ew);
-}
-
-extern void free_frame_faces (/* struct frame * */);
-
-static void
-EmacsFrameDestroy (widget)
- Widget widget;
-{
- EmacsFrame ew = (EmacsFrame) widget;
- struct frame* s = ew->emacs_frame.frame;
-
- if (! s) abort ();
- if (! s->output_data.x) abort ();
- if (! s->output_data.x->normal_gc) abort ();
-
- /* this would be called from Fdelete_frame() but it needs to free some
- stuff after the widget has been finalized but before the widget has
- been freed. */
- free_frame_faces (s);
-
- BLOCK_INPUT;
- /* need to be careful that the face-freeing code doesn't free these too */
- XFreeGC (XtDisplay (widget), s->output_data.x->normal_gc);
- XFreeGC (XtDisplay (widget), s->output_data.x->reverse_gc);
- XFreeGC (XtDisplay (widget), s->output_data.x->cursor_gc);
- UNBLOCK_INPUT;
-}
-
-void
-EmacsFrameResize (widget)
- Widget widget;
-{
- EmacsFrame ew = (EmacsFrame)widget;
- struct frame *f = ew->emacs_frame.frame;
- int columns;
- int rows;
-
- pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
- change_frame_size (f, rows, columns, 0, 1);
- update_wm_hints (ew);
- update_various_frame_slots (ew);
-
- cancel_mouse_face (f);
-}
-
-static Boolean
-EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
- Widget cur_widget;
- Widget req_widget;
- Widget new_widget;
- ArgList dum1;
- Cardinal *dum2;
-{
- EmacsFrame cur = (EmacsFrame)cur_widget;
- EmacsFrame new = (EmacsFrame)new_widget;
-
- Boolean needs_a_refresh = False;
- Boolean has_to_recompute_size;
- Boolean has_to_recompute_gcs;
- Boolean has_to_update_hints;
-
- int char_width, char_height;
- Dimension pixel_width;
- Dimension pixel_height;
-
- has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
- || (cur->emacs_frame.foreground_pixel
- != new->emacs_frame.foreground_pixel)
- || (cur->core.background_pixel
- != new->core.background_pixel)
- );
-
- has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
- && cur->core.width == new->core.width
- && cur->core.height == new->core.height);
-
- has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
-
- if (has_to_recompute_gcs)
- {
- setup_frame_gcs (new);
- needs_a_refresh = True;
- }
-
- if (has_to_recompute_size)
- {
- pixel_width = new->core.width;
- pixel_height = new->core.height;
- pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
- &char_height);
- char_to_pixel_size (new, char_width, char_height, &pixel_width,
- &pixel_height);
- new->core.width = pixel_width;
- new->core.height = pixel_height;
-
- change_frame_size (new->emacs_frame.frame, char_height, char_width,
- 1, 0);
- needs_a_refresh = True;
- }
-
- if (has_to_update_hints)
- update_wm_hints (new);
-
- update_various_frame_slots (new);
-
- /* #### This doesn't work, I haven't been able to find ANY kludge that
- will let (x-create-frame '((iconic . t))) work. It seems that changes
- to wm_shell's iconic slot have no effect after it has been realized,
- and calling XIconifyWindow doesn't work either (even thought the window
- has been created.) Perhaps there is some property we could smash
- directly, but I'm sick of this for now.
- */
- if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
- {
- Widget wmshell = get_wm_shell ((Widget) cur);
- XtVaSetValues (wmshell, XtNiconic, new->emacs_frame.iconic, 0);
- }
-
- return needs_a_refresh;
-}
-
-static XtGeometryResult
-EmacsFrameQueryGeometry (widget, request, result)
- Widget widget;
- XtWidgetGeometry* request;
- XtWidgetGeometry* result;
-{
- EmacsFrame ew = (EmacsFrame)widget;
-
- int mask = request->request_mode;
- Dimension ok_width, ok_height;
-
- if (mask & (CWWidth | CWHeight))
- {
- round_size_to_char (ew,
- (mask & CWWidth) ? request->width : ew->core.width,
- ((mask & CWHeight) ? request->height
- : ew->core.height),
- &ok_width, &ok_height);
- if ((mask & CWWidth) && (ok_width != request->width))
- {
- result->request_mode |= CWWidth;
- result->width = ok_width;
- }
- if ((mask & CWHeight) && (ok_height != request->height))
- {
- result->request_mode |= CWHeight;
- result->height = ok_height;
- }
- }
- return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
-}
-
-/* Special entrypoints */
-void
-EmacsFrameSetCharSize (widget, columns, rows)
- Widget widget;
- int columns;
- int rows;
-{
- EmacsFrame ew = (EmacsFrame) widget;
- Dimension pixel_width, pixel_height, granted_width, granted_height;
- XtGeometryResult result;
- struct frame *f = ew->emacs_frame.frame;
- Arg al[2];
- int ac = 0;
-
- if (columns < 3) columns = 3; /* no way buddy */
-
- check_frame_size (f, &rows, &columns);
- f->output_data.x->vertical_scroll_bar_extra
- = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
- ? 0
- : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
- ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
- : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
-
- char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
-
- /* Manually change the height and width of all our widgets,
- adjusting each widget by the same increments. */
- if (ew->core.width != pixel_width || ew->core.height != pixel_height)
- {
- int hdelta = pixel_height - ew->core.height;
- int wdelta = pixel_width - ew->core.width;
- int column_widget_height = f->output_data.x->column_widget->core.height;
- int column_widget_width = f->output_data.x->column_widget->core.width;
- int outer_widget_height = f->output_data.x->widget->core.height;
- int outer_widget_width = f->output_data.x->widget->core.width;
- int old_left = f->output_data.x->widget->core.x;
- int old_top = f->output_data.x->widget->core.y;
-
- lw_refigure_widget (f->output_data.x->column_widget, False);
- update_hints_inhibit = 1;
-
- ac = 0;
- XtSetArg (al[ac], XtNheight, pixel_height); ac++;
- XtSetArg (al[ac], XtNwidth, pixel_width); ac++;
- XtSetValues ((Widget) ew, al, ac);
-
- ac = 0;
- XtSetArg (al[ac], XtNheight, column_widget_height + hdelta); ac++;
- XtSetArg (al[ac], XtNwidth, column_widget_width + wdelta); ac++;
- XtSetValues (f->output_data.x->column_widget, al, ac);
-
- ac = 0;
- XtSetArg (al[ac], XtNheight, outer_widget_height + hdelta); ac++;
- XtSetArg (al[ac], XtNwidth, outer_widget_width + wdelta); ac++;
- XtSetValues (f->output_data.x->widget, al, ac);
-
- lw_refigure_widget (f->output_data.x->column_widget, True);
-
- update_hints_inhibit = 0;
- update_wm_hints (ew);
-
- do_pending_window_change ();
-
- /* These seem to get clobbered. I don't know why. - rms. */
- f->output_data.x->widget->core.x = old_left;
- f->output_data.x->widget->core.y = old_top;
- }
-
- /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
- receive in the ConfigureNotify event; if we get what we asked
- for, then the event won't cause the screen to become garbaged, so
- we have to make sure to do it here. */
- SET_FRAME_GARBAGED (f);
-}
-
-widget_store_internal_border (widget)
- Widget widget;
-{
- EmacsFrame ew = (EmacsFrame) widget;
- FRAME_PTR f = ew->emacs_frame.frame;
-
- ew->emacs_frame.internal_border_width
- = f->output_data.x->internal_border_width;
-}
diff --git a/src/widget.h b/src/widget.h
deleted file mode 100644
index 99edf0971a5..00000000000
--- a/src/widget.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* The emacs frame widget public header file.
- Copyright (C) 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Emacs 19 face widget ported by Fred Pierresteguy */
-
-#ifndef _EmacsFrame_h
-#define _EmacsFrame_h
-
-#define XtNminibuffer "minibuffer"
-#define XtCMinibuffer "Minibuffer"
-#define XtNunsplittable "unsplittable"
-#define XtCUnsplittable "Unsplittable"
-#define XtNinternalBorderWidth "internalBorderWidth"
-#define XtCInternalBorderWidth "InternalBorderWidth"
-#define XtNinterline "interline"
-#define XtCInterline "Interline"
-
-#ifndef XtNfont
-#define XtNfont "font"
-#endif
-#ifndef XtCFont
-#define XtCFont "Font"
-#endif
-#ifndef XtNforeground
-#define XtNforeground "foreground"
-#endif
-#ifndef XtCForeground
-#define XtCForeground "Foreground"
-#endif
-
-#define XtNcursorColor "cursorColor"
-#define XtCCursorColor "CursorColor"
-#define XtNbarCursor "barCursor"
-#define XtCBarCursor "BarCursor"
-
-#define XtNvisualBell "visualBell"
-#define XtCVisualBell "VisualBell"
-#define XtCBellVolume "BellVolume"
-#define XtNbellVolume "bellVolume"
-
-#define XtNpointerBackground "pointerBackground"
-#define XtNpointerColor "pointerColor"
-
-#define XtNtextPointer "textPointer"
-#define XtNspacePointer "spacePointer"
-#define XtNmodeLinePointer "modePointer"
-#define XtNgcPointer "gcPointer"
-
-#define XtNemacsFrame "emacsFrame"
-#define XtCEmacsFrame "EmacsFrame"
-
-#ifndef XtNgeometry
-#define XtNgeometry "geometry"
-#endif
-#ifndef XtCGeometry
-#define XtCGeometry "Geometry"
-#endif
-#ifndef XtNshowGrip
-#define XtNshowGrip "showGrip"
-#endif
-#ifndef XtNallowResize
-#define XtNallowResize "allowResize"
-#endif
-#ifndef XtNresizeToPreferred
-#define XtNresizeToPreferred "resizeToPreferred"
-#endif
-
-#define XtNinitialGeometry "initialGeometry"
-#define XtCInitialGeometry "InitialGeometry"
-
-/* structures
- */
-typedef struct _EmacsFrameRec *EmacsFrame;
-typedef struct _EmacsFrameClassRec *EmacsFrameClass;
-
-extern WidgetClass emacsFrameClass;
-
-extern struct _DisplayContext* display_context;
-
-/* Special entrypoints */
-void EmacsFrameSetCharSize ();
-
-#endif /* _EmacsFrame_h */
diff --git a/src/widgetprv.h b/src/widgetprv.h
deleted file mode 100644
index 91a64c16025..00000000000
--- a/src/widgetprv.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* The emacs frame widget private header file.
- Copyright (C) 1993 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Emacs 19 face widget ported by Fred Pierresteguy */
-
-#ifndef _EmacsFrameP_h
-#define _EmacsFrameP_h
-
-#include <X11/IntrinsicP.h>
-#include <X11/CoreP.h>
-#include "widget.h"
-
-typedef struct {
- struct frame* frame; /* the *emacs* frame object */
-
- /* Resources that can't be done from lisp.
- */
- char* geometry; /* geometry spec of this frame */
- Boolean iconic; /* whether this frame is iconic */
-
- /* The rest of this is crap and should be deleted.
- */
- int minibuffer; /* 0: normal frames with minibuffers.
- * 1: frames without minibuffers
- * 2: minibuffer only. */
- Boolean unsplittable; /* frame can only have one window */
-
- int internal_border_width; /* internal borders */
- int interline; /* skips between lines */
-
- XFontStruct* font; /* font */
- Pixel foreground_pixel; /* foreground */
-
- Pixel cursor_color; /* text cursor color */
- Boolean bar_cursor; /* 1 if bar, 0 if block */
-
- Boolean visual_bell; /* flash instead of beep */
- int bell_volume; /* how loud is beep */
-
- /* private state */
-
-} EmacsFramePart;
-
-typedef struct _EmacsFrameRec { /* full instance record */
- CorePart core;
- EmacsFramePart emacs_frame;
-} EmacsFrameRec;
-
-typedef struct { /* new fields for EmacsFrame class */
- int dummy;
-} EmacsFrameClassPart;
-
-typedef struct _EmacsFrameClassRec { /* full class record declaration */
- CoreClassPart core_class;
- EmacsFrameClassPart emacs_frame_class;
-} EmacsFrameClassRec;
-
-extern EmacsFrameClassRec emacsFrameClassRec; /* class pointer */
-
-
-
-#endif /* _EmacsFrameP_h */
diff --git a/src/window.c b/src/window.c
deleted file mode 100644
index dd5d472ed7e..00000000000
--- a/src/window.c
+++ /dev/null
@@ -1,3720 +0,0 @@
-/* Window creation, deletion and examination for GNU Emacs.
- Does not include redisplay.
- Copyright (C) 1985, 86, 87, 93, 94, 95, 96 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include <config.h>
-#include "lisp.h"
-#include "buffer.h"
-#include "frame.h"
-#include "window.h"
-#include "commands.h"
-#include "indent.h"
-#include "termchar.h"
-#include "disptab.h"
-#include "keyboard.h"
-
-Lisp_Object Qwindowp, Qwindow_live_p;
-
-Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window ();
-Lisp_Object Fset_window_buffer (), Fsplit_window (), Frecenter ();
-
-void delete_all_subwindows ();
-static struct window *decode_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.
-
- This value is always the same as
- FRAME_SELECTED_WINDOW (selected_frame). */
-
-Lisp_Object selected_window;
-
-/* The minibuffer window of the selected frame.
- Note that you cannot test for minibufferness of an arbitrary window
- by comparing against this; but you can test for minibufferness of
- the selected window. */
-Lisp_Object minibuf_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 this is the buffer whose window C-M-v should scroll. */
-Lisp_Object Vother_window_scroll_buffer;
-
-/* Non-nil means it's function to call to display temp buffers. */
-Lisp_Object Vtemp_buffer_show_function;
-
-/* If a window gets smaller than either of these, it is removed. */
-int window_min_height;
-int window_min_width;
-
-/* Nonzero implies Fdisplay_buffer should create windows. */
-int pop_up_windows;
-
-/* Nonzero implies make new frames for Fdisplay_buffer. */
-int pop_up_frames;
-
-/* Non-nil means use this function instead of default */
-Lisp_Object Vpop_up_frame_function;
-
-/* Function to call to handle Fdisplay_buffer. */
-Lisp_Object Vdisplay_buffer_function;
-
-/* List of buffer *names* for buffers that should have their own frames. */
-Lisp_Object Vspecial_display_buffer_names;
-
-/* List of regexps for buffer names that should have their own frames. */
-Lisp_Object Vspecial_display_regexps;
-
-/* Function to pop up a special frame. */
-Lisp_Object Vspecial_display_function;
-
-/* List of buffer *names* for buffers to appear in selected window. */
-Lisp_Object Vsame_window_buffer_names;
-
-/* List of regexps for buffer names to appear in selected window. */
-Lisp_Object Vsame_window_regexps;
-
-/* Hook run at end of temp_output_buffer_show. */
-Lisp_Object Qtemp_buffer_show_hook;
-
-/* Fdisplay_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;
-
-/* Nonzero after init_window_once has finished. */
-static int window_initialized;
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
-extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
-
-DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
- "Returns t if OBJECT is a window.")
- (object)
- Lisp_Object object;
-{
- return WINDOWP (object) ? Qt : Qnil;
-}
-
-DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
- "Returns t if OBJECT is a window which is currently visible.")
- (object)
- Lisp_Object object;
-{
- return (WINDOWP (object) && ! NILP (XWINDOW (object)->buffer) ? Qt : Qnil);
-}
-
-Lisp_Object
-make_window ()
-{
- Lisp_Object val;
- register struct window *p;
- register struct Lisp_Vector *vec;
- int i;
-
- vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct window));
- for (i = 0; i < VECSIZE (struct window); i++)
- vec->contents[i] = Qnil;
- vec->size = VECSIZE (struct window);
- p = (struct window *)vec;
- XSETFASTINT (p->sequence_number, ++sequence_number);
- XSETFASTINT (p->left, 0);
- XSETFASTINT (p->top, 0);
- XSETFASTINT (p->height, 0);
- XSETFASTINT (p->width, 0);
- XSETFASTINT (p->hscroll, 0);
- XSETFASTINT (p->last_point_x, 0);
- XSETFASTINT (p->last_point_y, 0);
- p->start = Fmake_marker ();
- p->pointm = Fmake_marker ();
- XSETFASTINT (p->use_time, 0);
- p->frame = Qnil;
- p->display_table = Qnil;
- p->dedicated = Qnil;
- XSETWINDOW (val, p);
- 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, 1, 0,
- "Return the window used now for minibuffers.\n\
-If the optional argument FRAME is specified, return the minibuffer window\n\
-used by that frame.")
- (frame)
- Lisp_Object frame;
-{
- if (NILP (frame))
- XSETFRAME (frame, selected_frame);
- else
- CHECK_LIVE_FRAME (frame, 0);
-
- return FRAME_MINIBUF_WINDOW (XFRAME (frame));
-}
-
-DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
- "Returns non-nil if WINDOW is a minibuffer window.")
- (window)
- Lisp_Object window;
-{
- struct window *w = decode_window (window);
- return (MINI_WINDOW_P (w) ? Qt : Qnil);
-}
-
-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 frame 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;
- int hscroll;
-
- if (NILP (pos))
- posint = PT;
- else
- {
- CHECK_NUMBER_COERCE_MARKER (pos, 0);
- posint = XINT (pos);
- }
-
- w = decode_window (window);
- top = marker_position (w->start);
- hscroll = XINT (w->hscroll);
-
- if (posint < top)
- return Qnil;
-
- height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
-
- buf = XBUFFER (w->buffer);
- if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
- && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf))
- {
- /* If frame 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_ZV (buf))
- return Qnil;
-
- /* w->start can be out of range. If it is, do something reasonable. */
- if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
- return Qnil;
-
- /* If that info is not correct, calculate afresh */
- posval = *compute_motion (top, 0, (hscroll ? 1 - hscroll : 0), 0,
- posint, height, 0,
- window_internal_width (w) - 1,
- hscroll, 0, w);
-
- return posval.vpos < height ? Qt : Qnil;
- }
-}
-
-static struct window *
-decode_window (window)
- register Lisp_Object window;
-{
- if (NILP (window))
- return XWINDOW (selected_window);
-
- CHECK_LIVE_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 display columns in WINDOW.\n\
-This is the width that is usable columns available for text in WINDOW.\n\
-If you want to find out how many columns WINDOW takes up,\n\
-use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
- (window)
- Lisp_Object window;
-{
- return make_number (window_internal_width (decode_window (window)));
-}
-
-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) XSETFASTINT (ncol, 0);
- w = decode_window (window);
- if (XINT (w->hscroll) != XINT (ncol))
- XBUFFER (w->buffer)->clip_changed = 1; /* Prevent redisplay shortcuts */
- w->hscroll = ncol;
- return ncol;
-}
-
-DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
- Swindow_redisplay_end_trigger, 0, 1, 0,
- "Return WINDOW's redisplay end trigger value.\n\
-See `set-window-redisplay-end-trigger' for more information.")
- (window)
- Lisp_Object window;
-{
- return decode_window (window)->redisplay_end_trigger;
-}
-
-DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
- Sset_window_redisplay_end_trigger, 2, 2, 0,
- "Set WINDOW's redisplay end trigger value to VALUE.\n\
-VALUE should be a buffer position (typically a marker) or nil.\n\
-If it is a buffer position, then if redisplay in WINDOW reaches a position\n\
-beyond VALUE, the functions in `redisplay-end-trigger-functions' are called\n\
-with two arguments: WINDOW, and the end trigger value.\n\
-Afterwards the end-trigger value is reset to nil.")
- (window, value)
- register Lisp_Object window, value;
-{
- register struct window *w;
-
- w = decode_window (window);
- w->redisplay_end_trigger = value;
- return value;
-}
-
-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 frame.\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 (WINDOW_RIGHT_EDGE (w)),
- Fcons (make_number (XFASTINT (w->top)
- + XFASTINT (w->height)),
- Qnil))));
-}
-
-/* Test if the character at column *x, row *y is within window *w.
- If it is not, return 0;
- if it is in the window's text area,
- set *x and *y to its location relative to the upper left corner
- of the window, and
- return 1;
- if it is on the window's modeline, return 2;
- if it is on the border between the window and its right sibling,
- return 3. */
-static int
-coordinates_in_window (w, x, y)
- register struct window *w;
- register int *x, *y;
-{
- register int left = XINT (w->left);
- register int right_edge = WINDOW_RIGHT_EDGE (w);
- register int left_margin = WINDOW_LEFT_MARGIN (w);
- register int right_margin = WINDOW_RIGHT_MARGIN (w);
- register int window_height = XINT (w->height);
- register int top = XFASTINT (w->top);
-
- if ( *x < left || *x >= right_edge
- || *y < top || *y >= top + window_height)
- return 0;
-
- if (left_margin != left && *x < left_margin && *x >= left)
- return 3;
-
- if (right_margin != right_edge && *x >= right_margin && *x < right_edge)
- return 3;
-
- /* Is the character is the mode line? */
- if (*y == top + window_height - 1
- && ! MINI_WINDOW_P (w))
- return 2;
-
- *x -= WINDOW_LEFT_MARGIN (w);
- *y -= top;
- return 1;
-}
-
-DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
- Scoordinates_in_window_p, 2, 2, 0,
- "Return non-nil if COORDINATES are in WINDOW.\n\
-COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
-measured in characters from the upper-left corner of the frame.\n\
-(0 . 0) denotes the character in the upper left corner of the\n\
-frame.\n\
-If COORDINATES are in the text portion of WINDOW,\n\
- the coordinates relative to the window are returned.\n\
-If they are in the mode line of WINDOW, `mode-line' is returned.\n\
-If they are on the border between WINDOW and its right sibling,\n\
- `vertical-line' is returned.")
- (coordinates, window)
- register Lisp_Object coordinates, window;
-{
- int x, y;
-
- CHECK_LIVE_WINDOW (window, 0);
- CHECK_CONS (coordinates, 1);
- x = XINT (Fcar (coordinates));
- y = XINT (Fcdr (coordinates));
-
- switch (coordinates_in_window (XWINDOW (window), &x, &y))
- {
- case 0: /* NOT in window at all. */
- return Qnil;
-
- case 1: /* In text part of window. */
- return Fcons (x, y);
-
- case 2: /* In mode line of window. */
- return Qmode_line;
-
- case 3: /* On right border of window. */
- return Qvertical_line;
-
- default:
- abort ();
- }
-}
-
-/* Find the window containing column x, row y, and return it as a
- Lisp_Object. If x, y is on the window's modeline, set *part
- to 1; if it is on the separating line between the window and its
- right sibling, set it to 2; otherwise set it to 0. If there is no
- window under x, y return nil and leave *part unmodified. */
-Lisp_Object
-window_from_coordinates (frame, x, y, part)
- FRAME_PTR frame;
- int x, y;
- int *part;
-{
- register Lisp_Object tem, first;
-
- tem = first = FRAME_SELECTED_WINDOW (frame);
-
- do
- {
- int found = coordinates_in_window (XWINDOW (tem), &x, &y);
-
- if (found)
- {
- *part = found - 1;
- return tem;
- }
-
- tem = Fnext_window (tem, Qt, Qlambda);
- }
- while (! EQ (tem, first));
-
- return Qnil;
-}
-
-DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
- "Return window containing coordinates X and Y on FRAME.\n\
-If omitted, FRAME defaults to the currently selected frame.\n\
-The top left corner of the frame is considered to be row 0,\n\
-column 0.")
- (x, y, frame)
- Lisp_Object x, y, frame;
-{
- int part;
-
- if (NILP (frame))
- XSETFRAME (frame, selected_frame);
- else
- CHECK_LIVE_FRAME (frame, 2);
- CHECK_NUMBER (x, 0);
- CHECK_NUMBER (y, 1);
-
- return window_from_coordinates (XFRAME (frame),
- XINT (x), XINT (y),
- &part);
-}
-
-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.\n\
-This is updated by redisplay or by calling `set-window-start'.")
- (window)
- Lisp_Object window;
-{
- return Fmarker_position (decode_window (window)->start);
-}
-
-/* This is text temporarily removed from the doc string below.
-
-This function returns nil if the position is not currently known.\n\
-That happens when redisplay is preempted and doesn't finish.\n\
-If in that case you want to compute where the end of the window would\n\
-have been if redisplay had finished, do this:\n\
- (save-excursion\n\
- (goto-char (window-start window))\n\
- (vertical-motion (1- (window-height window)) window)\n\
- (point))") */
-
-DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 1, 0,
- "Return position at which display currently ends in WINDOW.\n\
-This is updated by redisplay, when it runs to completion.\n\
-Simply changing the buffer text or setting `window-start'\n\
-does not update this value.")
- (window)
- Lisp_Object window;
-{
- Lisp_Object value;
- struct window *w = decode_window (window);
- Lisp_Object buf;
-
- buf = w->buffer;
- CHECK_BUFFER (buf, 0);
-
-#if 0 /* This change broke some things. We should make it later. */
- /* If we don't know the end position, return nil.
- The user can compute it with vertical-motion if he wants to.
- It would be nicer to do it automatically,
- but that's so slow that it would probably bother people. */
- if (NILP (w->window_end_valid))
- return Qnil;
-#endif
-
- XSETINT (value,
- BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
-
- return value;
-}
-
-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 (NILP (noforce))
- w->force_start = Qt;
- w->update_mode_line = Qt;
- XSETFASTINT (w->last_modified, 0);
- XSETFASTINT (w->last_overlay_modified, 0);
- if (!EQ (window, selected_window))
- windows_or_buffers_changed++;
- return pos;
-}
-
-DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
- 1, 1, 0,
- "Return WINDOW's dedicated object, usually t or nil.\n\
-See also `set-window-dedicated-p'.")
- (window)
- Lisp_Object window;
-{
- return decode_window (window)->dedicated;
-}
-
-DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
- Sset_window_dedicated_p, 2, 2, 0,
- "Control whether WINDOW is dedicated to the buffer it displays.\n\
-If it is dedicated, Emacs will not automatically change\n\
-which buffer appears in it.\n\
-The second argument is the new value for the dedication flag;\n\
-non-nil means yes.")
- (window, arg)
- Lisp_Object window, arg;
-{
- register struct window *w = decode_window (window);
-
- if (NILP (arg))
- w->dedicated = Qnil;
- else
- w->dedicated = Qt;
-
- return w->dedicated;
-}
-
-DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
- 0, 1, 0,
- "Return the display-table that WINDOW is using.")
- (window)
- Lisp_Object window;
-{
- return decode_window (window)->display_table;
-}
-
-/* Get the display table for use currently on window W.
- This is either W's display table or W's buffer's display table.
- Ignore the specified tables if they are not valid;
- if no valid table is specified, return 0. */
-
-struct Lisp_Char_Table *
-window_display_table (w)
- struct window *w;
-{
- Lisp_Object tem;
- tem = w->display_table;
- if (DISP_TABLE_P (tem))
- return XCHAR_TABLE (tem);
- tem = XBUFFER (w->buffer)->display_table;
- if (DISP_TABLE_P (tem))
- return XCHAR_TABLE (tem);
- tem = Vstandard_display_table;
- if (DISP_TABLE_P (tem))
- return XCHAR_TABLE (tem);
- return 0;
-}
-
-DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
- "Set WINDOW's display-table to TABLE.")
- (window, table)
- register Lisp_Object window, table;
-{
- register struct window *w;
- register Lisp_Object z; /* Return value. */
-
- w = decode_window (window);
- w->display_table = table;
- return table;
-}
-
-/* Record info on buffer window w is displaying
- when it is about to cease to display that buffer. */
-static
-unshow_buffer (w)
- register struct window *w;
-{
- Lisp_Object buf;
-
- buf = w->buffer;
- if (XBUFFER (buf) != XMARKER (w->pointm)->buffer)
- abort ();
-
- if (w == XWINDOW (XBUFFER (buf)->last_selected_window))
- XBUFFER (buf)->last_selected_window = Qnil;
-
-#if 0
- 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. */
-#endif
- /* last_window_start records the start position that this buffer
- had in the last window to be disconnected from it.
- Now that this statement is unconditional,
- it is possible for the buffer to be displayed in the
- selected window, while last_window_start reflects another
- window which was recently showing the same buffer.
- Some people might say that might be a good thing. Let's see. */
- 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)));
-}
-
-/* Put replacement into the window structure in place of old. */
-static
-replace_window (old, replacement)
- Lisp_Object old, replacement;
-{
- register Lisp_Object tem;
- register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
-
- /* If OLD is its frame's root_window, then replacement is the new
- root_window for that frame. */
-
- if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
- FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
-
- p->left = o->left;
- p->top = o->top;
- p->width = o->width;
- p->height = o->height;
-
- p->next = tem = o->next;
- if (!NILP (tem))
- XWINDOW (tem)->prev = replacement;
-
- p->prev = tem = o->prev;
- if (!NILP (tem))
- XWINDOW (tem)->next = replacement;
-
- p->parent = tem = o->parent;
- if (!NILP (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 ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
- "Remove WINDOW from the display. Default is selected window.")
- (window)
- register Lisp_Object window;
-{
- register Lisp_Object tem, parent, sib;
- register struct window *p;
- register struct window *par;
-
- /* Because this function is called by other C code on non-leaf
- windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
- so we can't decode_window here. */
- if (NILP (window))
- window = selected_window;
- else
- CHECK_WINDOW (window, 0);
- p = XWINDOW (window);
-
- /* It's okay to delete an already-deleted window. */
- if (NILP (p->buffer)
- && NILP (p->hchild)
- && NILP (p->vchild))
- return Qnil;
-
- parent = p->parent;
- if (NILP (parent))
- error ("Attempt to delete minibuffer or sole ordinary window");
- par = XWINDOW (parent);
-
- windows_or_buffers_changed++;
- FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (p))) = 1;
-
- /* Are we trying to delete any frame's selected window? */
- {
- Lisp_Object frame, pwindow;
-
- /* See if the frame's selected window is either WINDOW
- or any subwindow of it, by finding all that window's parents
- and comparing each one with WINDOW. */
- frame = WINDOW_FRAME (XWINDOW (window));
- pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
-
- while (!NILP (pwindow))
- {
- if (EQ (window, pwindow))
- break;
- pwindow = XWINDOW (pwindow)->parent;
- }
-
- if (EQ (window, pwindow))
- {
- Lisp_Object alternative;
- alternative = Fnext_window (window, Qlambda, Qnil);
-
- /* If we're about to delete the selected window on the
- selected frame, then we should use Fselect_window to select
- the new window. On the other hand, if we're about to
- delete the selected window on any other frame, we shouldn't do
- anything but set the frame's selected_window slot. */
- if (EQ (window, selected_window))
- Fselect_window (alternative);
- else
- FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
- }
- }
-
- tem = p->buffer;
- /* tem is null for dummy parent windows
- (which have inferiors but not any contents themselves) */
- if (!NILP (tem))
- {
- unshow_buffer (p);
- unchain_marker (p->pointm);
- unchain_marker (p->start);
- }
-
- tem = p->next;
- if (!NILP (tem))
- XWINDOW (tem)->prev = p->prev;
-
- tem = p->prev;
- if (!NILP (tem))
- XWINDOW (tem)->next = p->next;
-
- if (EQ (window, par->hchild))
- par->hchild = p->next;
- if (EQ (window, par->vchild))
- par->vchild = p->next;
-
- /* Find one of our siblings to give our space to. */
- sib = p->prev;
- if (NILP (sib))
- {
- /* If p gives its space to its next sibling, that sibling needs
- to have its top/left side pulled back to where p's is.
- set_window_{height,width} will re-position the sibling's
- children. */
- sib = p->next;
- XWINDOW (sib)->top = p->top;
- XWINDOW (sib)->left = p->left;
- }
-
- /* Stretch that sibling. */
- if (!NILP (par->vchild))
- set_window_height (sib,
- XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
- 1);
- if (!NILP (par->hchild))
- set_window_width (sib,
- XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
- 1);
-
- /* If parent now has only one child,
- put the child into the parent's place. */
- tem = par->hchild;
- if (NILP (tem))
- tem = par->vchild;
- if (NILP (XWINDOW (tem)->next))
- replace_window (parent, tem);
-
- /* Since we may be deleting combination windows, we must make sure that
- not only p but all its children have been marked as deleted. */
- if (! NILP (p->hchild))
- delete_all_subwindows (XWINDOW (p->hchild));
- else if (! NILP (p->vchild))
- delete_all_subwindows (XWINDOW (p->vchild));
-
- /* Mark this window as deleted. */
- p->buffer = p->hchild = p->vchild = Qnil;
-
- return Qnil;
-}
-
-
-extern Lisp_Object next_frame (), prev_frame ();
-
-/* This comment supplies the doc string for `next-window',
- for make-docfile to see. We cannot put this in the real DEFUN
- due to limits in the Unix cpp.
-
-DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
- "Return next window after WINDOW in canonical ordering of windows.\n\
-If omitted, WINDOW defaults to the selected window.\n\
-\n\
-Optional second arg MINIBUF t means count the minibuffer window even\n\
-if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
-it is active. MINIBUF neither t nor nil means not to count the\n\
-minibuffer even if it is active.\n\
-\n\
-Several frames may share a single minibuffer; if the minibuffer\n\
-counts, all windows on all frames that share that minibuffer count\n\
-too. Therefore, `next-window' can be used to iterate through the\n\
-set of windows even when the minibuffer is on another frame. If the\n\
-minibuffer does not count, only windows from WINDOW's frame count.\n\
-\n\
-Optional third arg ALL-FRAMES t means include windows on all frames.\n\
-ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
-above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
-ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
-If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
-Anything else means restrict to WINDOW's frame.\n\
-\n\
-If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
-`next-window' to iterate through the entire cycle of acceptable\n\
-windows, eventually ending up back at the window you started with.\n\
-`previous-window' traverses the same cycle, in the reverse order.")
- (window, minibuf, all_frames) */
-
-DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
- 0)
- (window, minibuf, all_frames)
- register Lisp_Object window, minibuf, all_frames;
-{
- register Lisp_Object tem;
- Lisp_Object start_window;
-
- if (NILP (window))
- window = selected_window;
- else
- CHECK_LIVE_WINDOW (window, 0);
-
- start_window = window;
-
- /* minibuf == nil may or may not include minibuffers.
- Decide if it does. */
- if (NILP (minibuf))
- minibuf = (minibuf_level ? minibuf_window : Qlambda);
- else if (! EQ (minibuf, Qt))
- minibuf = Qlambda;
- /* Now minibuf can be t => count all minibuffer windows,
- lambda => count none of them,
- or a specific minibuffer window (the active one) to count. */
-
- /* all_frames == nil doesn't specify which frames to include. */
- if (NILP (all_frames))
- all_frames = (! EQ (minibuf, Qlambda)
- ? (FRAME_MINIBUF_WINDOW
- (XFRAME
- (WINDOW_FRAME
- (XWINDOW (window)))))
- : Qnil);
- else if (EQ (all_frames, Qvisible))
- ;
- else if (XFASTINT (all_frames) == 0)
- ;
- else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
- /* If all_frames is a frame and window arg isn't on that frame, just
- return the first window on the frame. */
- return Fframe_first_window (all_frames);
- else if (! EQ (all_frames, Qt))
- all_frames = Qnil;
- /* Now all_frames is t meaning search all frames,
- nil meaning search just current frame,
- visible meaning search just visible frames,
- 0 meaning search visible and iconified frames,
- or a window, meaning search the frame that window belongs to. */
-
- /* Do this loop at least once, to get the next window, and perhaps
- again, if we hit the minibuffer and that is not acceptable. */
- do
- {
- /* Find a window that actually has a next one. This loop
- climbs up the tree. */
- while (tem = XWINDOW (window)->next, NILP (tem))
- if (tem = XWINDOW (window)->parent, !NILP (tem))
- window = tem;
- else
- {
- /* We've reached the end of this frame.
- Which other frames are acceptable? */
- tem = WINDOW_FRAME (XWINDOW (window));
- if (! NILP (all_frames))
- {
- Lisp_Object tem1;
-
- tem1 = tem;
- tem = next_frame (tem, all_frames);
- /* In the case where the minibuffer is active,
- and we include its frame as well as the selected one,
- next_frame may get stuck in that frame.
- If that happens, go back to the selected frame
- so we can complete the cycle. */
- if (EQ (tem, tem1))
- XSETFRAME (tem, selected_frame);
- }
- tem = FRAME_ROOT_WINDOW (XFRAME (tem));
-
- break;
- }
-
- window = tem;
-
- /* If we're in a combination window, find its first child and
- recurse on that. Otherwise, we've found the window we want. */
- while (1)
- {
- if (!NILP (XWINDOW (window)->hchild))
- window = XWINDOW (window)->hchild;
- else if (!NILP (XWINDOW (window)->vchild))
- window = XWINDOW (window)->vchild;
- else break;
- }
- }
- /* Which windows are acceptable?
- Exit the loop and accept this window if
- this isn't a minibuffer window,
- or we're accepting all minibuffer windows,
- or this is the active minibuffer and we are accepting that one, or
- we've come all the way around and we're back at the original window. */
- while (MINI_WINDOW_P (XWINDOW (window))
- && ! EQ (minibuf, Qt)
- && ! EQ (minibuf, window)
- && ! EQ (window, start_window));
-
- return window;
-}
-
-/* This comment supplies the doc string for `previous-window',
- for make-docfile to see. We cannot put this in the real DEFUN
- due to limits in the Unix cpp.
-
-DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
- "Return the window preceding WINDOW in canonical ordering of windows.\n\
-If omitted, WINDOW defaults to the selected window.\n\
-\n\
-Optional second arg MINIBUF t means count the minibuffer window even\n\
-if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
-it is active. MINIBUF neither t nor nil means not to count the\n\
-minibuffer even if it is active.\n\
-\n\
-Several frames may share a single minibuffer; if the minibuffer\n\
-counts, all windows on all frames that share that minibuffer count\n\
-too. Therefore, `previous-window' can be used to iterate through\n\
-the set of windows even when the minibuffer is on another frame. If\n\
-the minibuffer does not count, only windows from WINDOW's frame count\n\
-\n\
-Optional third arg ALL-FRAMES t means include windows on all frames.\n\
-ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
-above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
-ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
-If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
-Anything else means restrict to WINDOW's frame.\n\
-\n\
-If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
-`previous-window' to iterate through the entire cycle of acceptable\n\
-windows, eventually ending up back at the window you started with.\n\
-`next-window' traverses the same cycle, in the reverse order.")
- (window, minibuf, all_frames) */
-
-
-DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
- 0)
- (window, minibuf, all_frames)
- register Lisp_Object window, minibuf, all_frames;
-{
- register Lisp_Object tem;
- Lisp_Object start_window;
-
- if (NILP (window))
- window = selected_window;
- else
- CHECK_LIVE_WINDOW (window, 0);
-
- start_window = window;
-
- /* minibuf == nil may or may not include minibuffers.
- Decide if it does. */
- if (NILP (minibuf))
- minibuf = (minibuf_level ? minibuf_window : Qlambda);
- else if (! EQ (minibuf, Qt))
- minibuf = Qlambda;
- /* Now minibuf can be t => count all minibuffer windows,
- lambda => count none of them,
- or a specific minibuffer window (the active one) to count. */
-
- /* all_frames == nil doesn't specify which frames to include.
- Decide which frames it includes. */
- if (NILP (all_frames))
- all_frames = (! EQ (minibuf, Qlambda)
- ? (FRAME_MINIBUF_WINDOW
- (XFRAME
- (WINDOW_FRAME
- (XWINDOW (window)))))
- : Qnil);
- else if (EQ (all_frames, Qvisible))
- ;
- else if (XFASTINT (all_frames) == 0)
- ;
- else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
- /* If all_frames is a frame and window arg isn't on that frame, just
- return the first window on the frame. */
- return Fframe_first_window (all_frames);
- else if (! EQ (all_frames, Qt))
- all_frames = Qnil;
- /* Now all_frames is t meaning search all frames,
- nil meaning search just current frame,
- visible meaning search just visible frames,
- 0 meaning search visible and iconified frames,
- or a window, meaning search the frame that window belongs to. */
-
- /* Do this loop at least once, to get the previous window, and perhaps
- again, if we hit the minibuffer and that is not acceptable. */
- do
- {
- /* Find a window that actually has a previous one. This loop
- climbs up the tree. */
- while (tem = XWINDOW (window)->prev, NILP (tem))
- if (tem = XWINDOW (window)->parent, !NILP (tem))
- window = tem;
- else
- {
- /* We have found the top window on the frame.
- Which frames are acceptable? */
- tem = WINDOW_FRAME (XWINDOW (window));
- if (! NILP (all_frames))
- /* It's actually important that we use prev_frame here,
- rather than next_frame. All the windows acceptable
- according to the given parameters should form a ring;
- Fnext_window and Fprevious_window should go back and
- forth around the ring. If we use next_frame here,
- then Fnext_window and Fprevious_window take different
- paths through the set of acceptable windows.
- window_loop assumes that these `ring' requirement are
- met. */
- {
- Lisp_Object tem1;
-
- tem1 = tem;
- tem = prev_frame (tem, all_frames);
- /* In the case where the minibuffer is active,
- and we include its frame as well as the selected one,
- next_frame may get stuck in that frame.
- If that happens, go back to the selected frame
- so we can complete the cycle. */
- if (EQ (tem, tem1))
- XSETFRAME (tem, selected_frame);
- }
- /* If this frame has a minibuffer, find that window first,
- because it is conceptually the last window in that frame. */
- if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
- tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
- else
- tem = FRAME_ROOT_WINDOW (XFRAME (tem));
-
- break;
- }
-
- window = tem;
- /* If we're in a combination window, find its last child and
- recurse on that. Otherwise, we've found the window we want. */
- while (1)
- {
- if (!NILP (XWINDOW (window)->hchild))
- window = XWINDOW (window)->hchild;
- else if (!NILP (XWINDOW (window)->vchild))
- window = XWINDOW (window)->vchild;
- else break;
- while (tem = XWINDOW (window)->next, !NILP (tem))
- window = tem;
- }
- }
- /* Which windows are acceptable?
- Exit the loop and accept this window if
- this isn't a minibuffer window,
- or we're accepting all minibuffer windows,
- or this is the active minibuffer and we are accepting that one, or
- we've come all the way around and we're back at the original window. */
- while (MINI_WINDOW_P (XWINDOW (window))
- && ! EQ (minibuf, Qt)
- && ! EQ (minibuf, window)
- && ! EQ (window, start_window));
-
- return window;
-}
-
-DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
- "Select the ARG'th different window on this frame.\n\
-All windows on current frame are arranged in a cyclic order.\n\
-This command selects the window ARG steps away in that order.\n\
-A negative ARG moves in the opposite order. If the optional second\n\
-argument ALL_FRAMES is non-nil, cycle through all frames.")
- (arg, all_frames)
- register Lisp_Object arg, all_frames;
-{
- register int i;
- register Lisp_Object w;
-
- CHECK_NUMBER (arg, 0);
- w = selected_window;
- i = XINT (arg);
-
- while (i > 0)
- {
- w = Fnext_window (w, Qnil, all_frames);
- i--;
- }
- while (i < 0)
- {
- w = Fprevious_window (w, Qnil, all_frames);
- i++;
- }
- Fselect_window (w);
- return Qnil;
-}
-
-/* Look at all windows, performing an operation specified by TYPE
- with argument OBJ.
- If FRAMES is Qt, look at all frames;
- Qnil, look at just the selected frame;
- Qvisible, look at visible frames;
- a frame, just look at windows on that frame.
- If MINI is non-zero, perform the operation on minibuffer windows too.
-*/
-
-enum window_loop
-{
- WINDOW_LOOP_UNUSED,
- GET_BUFFER_WINDOW, /* Arg is buffer */
- GET_LRU_WINDOW, /* Arg is t for full-width windows only */
- DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
- DELETE_BUFFER_WINDOWS, /* Arg is buffer */
- GET_LARGEST_WINDOW,
- UNSHOW_BUFFER /* Arg is buffer */
-};
-
-static Lisp_Object
-window_loop (type, obj, mini, frames)
- enum window_loop type;
- register Lisp_Object obj, frames;
- int mini;
-{
- register Lisp_Object w;
- register Lisp_Object best_window;
- register Lisp_Object next_window;
- register Lisp_Object last_window;
- FRAME_PTR frame;
- Lisp_Object frame_arg;
- frame_arg = Qt;
-
- /* If we're only looping through windows on a particular frame,
- frame points to that frame. If we're looping through windows
- on all frames, frame is 0. */
- if (FRAMEP (frames))
- frame = XFRAME (frames);
- else if (NILP (frames))
- frame = selected_frame;
- else
- frame = 0;
- if (frame)
- frame_arg = Qlambda;
- else if (XFASTINT (frames) == 0)
- frame_arg = frames;
- else if (EQ (frames, Qvisible))
- frame_arg = frames;
-
- /* frame_arg is Qlambda to stick to one frame,
- Qvisible to consider all visible frames,
- or Qt otherwise. */
-
- /* Pick a window to start with. */
- if (WINDOWP (obj))
- w = obj;
- else if (frame)
- w = FRAME_SELECTED_WINDOW (frame);
- else
- w = FRAME_SELECTED_WINDOW (selected_frame);
-
- /* Figure out the last window we're going to mess with. Since
- Fnext_window, given the same options, is guaranteed to go in a
- ring, we can just use Fprevious_window to find the last one.
-
- We can't just wait until we hit the first window again, because
- it might be deleted. */
-
- last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg);
-
- best_window = Qnil;
- for (;;)
- {
- FRAME_PTR w_frame = XFRAME (WINDOW_FRAME (XWINDOW (w)));
-
- /* Pick the next window now, since some operations will delete
- the current window. */
- next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg);
-
- /* Note that we do not pay attention here to whether
- the frame is visible, since Fnext_window skips non-visible frames
- if that is desired, under the control of frame_arg. */
- if (! MINI_WINDOW_P (XWINDOW (w))
- || (mini && minibuf_level > 0))
- switch (type)
- {
- case GET_BUFFER_WINDOW:
- if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj)
- /* Don't find any minibuffer window
- except the one that is currently in use. */
- && (MINI_WINDOW_P (XWINDOW (w))
- ? EQ (w, minibuf_window) : 1))
- return w;
- break;
-
- case GET_LRU_WINDOW:
- /* t as arg means consider only full-width windows */
- if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (XWINDOW (w)))
- break;
- /* Ignore dedicated windows and minibuffers. */
- if (MINI_WINDOW_P (XWINDOW (w))
- || !NILP (XWINDOW (w)->dedicated))
- break;
- if (NILP (best_window)
- || (XFASTINT (XWINDOW (best_window)->use_time)
- > XFASTINT (XWINDOW (w)->use_time)))
- best_window = w;
- break;
-
- case DELETE_OTHER_WINDOWS:
- if (XWINDOW (w) != XWINDOW (obj))
- Fdelete_window (w);
- break;
-
- case DELETE_BUFFER_WINDOWS:
- if (EQ (XWINDOW (w)->buffer, obj))
- {
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
-
- /* If this window is dedicated, and in a frame of its own,
- kill the frame. */
- if (EQ (w, FRAME_ROOT_WINDOW (f))
- && !NILP (XWINDOW (w)->dedicated)
- && other_visible_frames (f))
- {
- /* Skip the other windows on this frame.
- There might be one, the minibuffer! */
- if (! EQ (w, last_window))
- while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
- {
- /* As we go, check for the end of the loop.
- We mustn't start going around a second time. */
- if (EQ (next_window, last_window))
- {
- last_window = w;
- break;
- }
- next_window = Fnext_window (next_window,
- mini ? Qt : Qnil,
- frame_arg);
- }
- /* Now we can safely delete the frame. */
- Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
- }
- else
- /* If we're deleting the buffer displayed in the only window
- on the frame, find a new buffer to display there. */
- if (NILP (XWINDOW (w)->parent))
- {
- Lisp_Object new_buffer;
- new_buffer = Fother_buffer (obj, Qnil);
- if (NILP (new_buffer))
- new_buffer
- = Fget_buffer_create (build_string ("*scratch*"));
- Fset_window_buffer (w, new_buffer);
- if (EQ (w, selected_window))
- Fset_buffer (XWINDOW (w)->buffer);
- }
- else
- Fdelete_window (w);
- }
- break;
-
- case GET_LARGEST_WINDOW:
- /* Ignore dedicated windows and minibuffers. */
- if (MINI_WINDOW_P (XWINDOW (w))
- || !NILP (XWINDOW (w)->dedicated))
- break;
- {
- struct window *best_window_ptr = XWINDOW (best_window);
- struct window *w_ptr = XWINDOW (w);
- if (NILP (best_window)
- || (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width)
- > (XFASTINT (best_window_ptr->height)
- * XFASTINT (best_window_ptr->width))))
- best_window = w;
- }
- break;
-
- case UNSHOW_BUFFER:
- if (EQ (XWINDOW (w)->buffer, obj))
- {
- /* Find another buffer to show in this window. */
- Lisp_Object another_buffer;
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
- another_buffer = Fother_buffer (obj, Qnil);
- if (NILP (another_buffer))
- another_buffer
- = Fget_buffer_create (build_string ("*scratch*"));
- /* If this window is dedicated, and in a frame of its own,
- kill the frame. */
- if (EQ (w, FRAME_ROOT_WINDOW (f))
- && !NILP (XWINDOW (w)->dedicated)
- && other_visible_frames (f))
- {
- /* Skip the other windows on this frame.
- There might be one, the minibuffer! */
- if (! EQ (w, last_window))
- while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
- {
- /* As we go, check for the end of the loop.
- We mustn't start going around a second time. */
- if (EQ (next_window, last_window))
- {
- last_window = w;
- break;
- }
- next_window = Fnext_window (next_window,
- mini ? Qt : Qnil,
- frame_arg);
- }
- /* Now we can safely delete the frame. */
- Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
- }
- else
- {
- /* Otherwise show a different buffer in the window. */
- XWINDOW (w)->dedicated = Qnil;
- Fset_window_buffer (w, another_buffer);
- if (EQ (w, selected_window))
- Fset_buffer (XWINDOW (w)->buffer);
- }
- }
- break;
- }
-
- if (EQ (w, last_window))
- break;
-
- w = next_window;
- }
-
- return best_window;
-}
-
-DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
- "Return the window least recently selected or used for display.\n\
-If optional argument FRAME is `visible', search all visible frames.\n\
-If FRAME is 0, search all visible and iconified frames.\n\
-If FRAME is t, search all frames.\n\
-If FRAME is nil, search only the selected frame.\n\
-If FRAME is a frame, search only that frame.")
- (frame)
- Lisp_Object frame;
-{
- register Lisp_Object w;
- /* First try for a window that is full-width */
- w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
- if (!NILP (w) && !EQ (w, selected_window))
- return w;
- /* If none of them, try the rest */
- return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
-}
-
-DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
- "Return the largest window in area.\n\
-If optional argument FRAME is `visible', search all visible frames.\n\
-If FRAME is 0, search all visible and iconified frames.\n\
-If FRAME is t, search all frames.\n\
-If FRAME is nil, search only the selected frame.\n\
-If FRAME is a frame, search only that frame.")
- (frame)
- Lisp_Object frame;
-{
- return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
- frame);
-}
-
-DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
- "Return a window currently displaying BUFFER, or nil if none.\n\
-If optional argument FRAME is `visible', search all visible frames.\n\
-If optional argument FRAME is 0, search all visible and iconified frames.\n\
-If FRAME is t, search all frames.\n\
-If FRAME is nil, search only the selected frame.\n\
-If FRAME is a frame, search only that frame.")
- (buffer, frame)
- Lisp_Object buffer, frame;
-{
- buffer = Fget_buffer (buffer);
- if (BUFFERP (buffer))
- return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
- else
- return Qnil;
-}
-
-DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
- 0, 1, "",
- "Make WINDOW (or the selected window) fill its frame.\n\
-Only the frame WINDOW is on is affected.\n\
-This function tries to reduce display jumps\n\
-by keeping the text previously visible in WINDOW\n\
-in the same place on the frame. Doing this depends on\n\
-the value of (window-start WINDOW), so if calling this function\n\
-in a program gives strange scrolling, make sure the window-start\n\
-value is reasonable when this function is called.")
- (window)
- Lisp_Object window;
-{
- struct window *w;
- int startpos;
- int top;
-
- if (NILP (window))
- window = selected_window;
- else
- CHECK_LIVE_WINDOW (window, 0);
-
- w = XWINDOW (window);
-
- startpos = marker_position (w->start);
- top = XFASTINT (w->top) - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w)));
-
- if (MINI_WINDOW_P (w) && top > 0)
- error ("Can't expand minibuffer to full frame");
-
- window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
-
- /* Try to minimize scrolling, by setting the window start to the point
- will cause the text at the old window start to be at the same place
- on the frame. But don't try to do this if the window start is
- outside the visible portion (as might happen when the display is
- not current, due to typeahead). */
- if (startpos >= BUF_BEGV (XBUFFER (w->buffer))
- && startpos <= BUF_ZV (XBUFFER (w->buffer)))
- {
- struct position pos;
- struct buffer *obuf = current_buffer;
-
- Fset_buffer (w->buffer);
- /* This computation used to temporarily move point, but that can
- have unwanted side effects due to text properties. */
- pos = *vmotion (startpos, -top, w);
-
- Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
- w->start_at_line_beg = ((pos.bufpos == BEGV
- || FETCH_CHAR (pos.bufpos - 1) == '\n') ? Qt
- : Qnil);
- /* We need to do this, so that the window-scroll-functions
- get called. */
- w->optional_new_start = Qt;
-
- set_buffer_internal (obuf);
- }
- return Qnil;
-}
-
-DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
- 1, 2, "bDelete windows on (buffer): ",
- "Delete all windows showing BUFFER.\n\
-Optional second argument FRAME controls which frames are affected.\n\
-If nil or omitted, delete all windows showing BUFFER in any frame.\n\
-If t, delete only windows showing BUFFER in the selected frame.\n\
-If `visible', delete all windows showing BUFFER in any visible frame.\n\
-If a frame, delete only windows showing BUFFER in that frame.")
- (buffer, frame)
- Lisp_Object buffer, frame;
-{
- /* FRAME uses t and nil to mean the opposite of what window_loop
- expects. */
- if (! FRAMEP (frame))
- frame = NILP (frame) ? Qt : Qnil;
-
- if (!NILP (buffer))
- {
- buffer = Fget_buffer (buffer);
- CHECK_BUFFER (buffer, 0);
- window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
- }
- 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 (!NILP (buffer))
- {
- buffer = Fget_buffer (buffer);
- CHECK_BUFFER (buffer, 0);
- window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
- }
- return Qnil;
-}
-
-/* Replace BUFFER with some other buffer in all windows
- of all frames, even those on other keyboards. */
-
-void
-replace_buffer_in_all_windows (buffer)
- Lisp_Object buffer;
-{
-#ifdef MULTI_KBOARD
- Lisp_Object tail, frame;
-
- /* A single call to window_loop won't do the job
- because it only considers frames on the current keyboard.
- So loop manually over frames, and handle each one. */
- FOR_EACH_FRAME (tail, frame)
- window_loop (UNSHOW_BUFFER, buffer, 0, frame);
-#else
- window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
-#endif
-}
-
-/* Set the height of WINDOW and all its inferiors. */
-
-/* The smallest acceptable dimensions for a window. Anything smaller
- might crash Emacs. */
-#define MIN_SAFE_WINDOW_WIDTH (2)
-#define MIN_SAFE_WINDOW_HEIGHT (2)
-
-/* Make sure that window_min_height and window_min_width are
- not too small; if they are, set them to safe minima. */
-
-static void
-check_min_window_sizes ()
-{
- /* Smaller values might permit a crash. */
- if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
- window_min_width = MIN_SAFE_WINDOW_WIDTH;
- if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
- window_min_height = MIN_SAFE_WINDOW_HEIGHT;
-}
-
-/* If *ROWS or *COLS are too small a size for FRAME, set them to the
- minimum allowable size. */
-void
-check_frame_size (frame, rows, cols)
- FRAME_PTR frame;
- int *rows, *cols;
-{
- /* For height, we have to see:
- whether the frame has a minibuffer,
- whether it wants a mode line, and
- whether it has a menu bar. */
- int min_height =
- (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
- : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
- : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
- if (FRAME_MENU_BAR_LINES (frame) > 0)
- min_height += FRAME_MENU_BAR_LINES (frame);
-
- if (*rows < min_height)
- *rows = min_height;
- if (*cols < MIN_SAFE_WINDOW_WIDTH)
- *cols = MIN_SAFE_WINDOW_WIDTH;
-}
-
-/* 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;
-
- check_min_window_sizes ();
-
- if (!nodelete
- && ! NILP (w->parent)
- && height < window_min_height)
- {
- Fdelete_window (window);
- return;
- }
-
- XSETFASTINT (w->last_modified, 0);
- XSETFASTINT (w->last_overlay_modified, 0);
- windows_or_buffers_changed++;
- FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
-
- XSETFASTINT (w->height, height);
- if (!NILP (w->hchild))
- {
- for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
- {
- XWINDOW (child)->top = w->top;
- set_window_height (child, height, nodelete);
- }
- }
- else if (!NILP (w->vchild))
- {
- lastbot = top = XFASTINT (w->top);
- lastobot = 0;
- for (child = w->vchild; !NILP (child); child = c->next)
- {
- c = XWINDOW (child);
-
- opos = lastobot + XFASTINT (c->height);
-
- XSETFASTINT (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; !NILP (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 && width < window_min_width && !NILP (w->parent))
- {
- Fdelete_window (window);
- return;
- }
-
- XSETFASTINT (w->last_modified, 0);
- XSETFASTINT (w->last_overlay_modified, 0);
- windows_or_buffers_changed++;
- FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
-
- XSETFASTINT (w->width, width);
- if (!NILP (w->vchild))
- {
- for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
- {
- XWINDOW (child)->left = w->left;
- set_window_width (child, width, nodelete);
- }
- }
- else if (!NILP (w->hchild))
- {
- lastright = left = XFASTINT (w->left);
- lastoright = 0;
- for (child = w->hchild; !NILP (child); child = c->next)
- {
- c = XWINDOW (child);
-
- opos = lastoright + XFASTINT (c->width);
-
- XSETFASTINT (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; !NILP (child); child = XWINDOW (child)->next)
- {
- set_window_width (child, XINT (XWINDOW (child)->width), 0);
- }
- }
-}
-
-int window_select_count;
-
-Lisp_Object
-Fset_window_buffer_unwind (obuf)
- Lisp_Object obuf;
-{
- Fset_buffer (obuf);
- return Qnil;
-}
-
-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);
- int count = specpdl_ptr - specpdl;
-
- buffer = Fget_buffer (buffer);
- CHECK_BUFFER (buffer, 1);
-
- if (NILP (XBUFFER (buffer)->name))
- error ("Attempt to display deleted buffer");
-
- tem = w->buffer;
- if (NILP (tem))
- error ("Window is deleted");
- else if (! EQ (tem, Qt)) /* w->buffer is t when the window
- is first being set up. */
- {
- if (!NILP (w->dedicated) && !EQ (tem, buffer))
- error ("Window is dedicated to `%s'",
- XSTRING (XBUFFER (tem)->name)->data);
-
- unshow_buffer (w);
- }
-
- w->buffer = buffer;
-
- if (EQ (window, selected_window))
- XBUFFER (w->buffer)->last_selected_window = window;
-
- XSETFASTINT (w->window_end_pos, 0);
- w->window_end_valid = Qnil;
- XSETFASTINT (w->hscroll, 0);
- 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;
- w->force_start = Qnil;
- XSETFASTINT (w->last_modified, 0);
- XSETFASTINT (w->last_overlay_modified, 0);
- windows_or_buffers_changed++;
-
- /* We must select BUFFER for running the window-scroll-functions.
- If WINDOW is selected, switch permanently.
- Otherwise, switch but go back to the ambient buffer afterward. */
- if (EQ (window, selected_window))
- Fset_buffer (buffer);
- /* We can't check ! NILP (Vwindow_scroll_functions) here
- because that might itself be a local variable. */
- else if (window_initialized)
- {
- record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
- Fset_buffer (buffer);
- }
-
- if (! NILP (Vwindow_scroll_functions))
- run_hook_with_args_2 (Qwindow_scroll_functions, window,
- Fmarker_position (w->start));
-
- unbind_to (count, Qnil);
-
- return Qnil;
-}
-
-DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
- "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
-The main editor command loop selects the buffer of the selected window\n\
-before each command.")
- (window)
- register Lisp_Object window;
-{
- register struct window *w;
- register struct window *ow = XWINDOW (selected_window);
-
- CHECK_LIVE_WINDOW (window, 0);
-
- w = XWINDOW (window);
-
- if (NILP (w->buffer))
- error ("Trying to select deleted window or non-leaf window");
-
- XSETFASTINT (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;
- if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
- {
- XFRAME (WINDOW_FRAME (w))->selected_window = window;
- /* Use this rather than Fhandle_switch_frame
- so that FRAME_FOCUS_FRAME is moved appropriately as we
- move around in the state where a minibuffer in a separate
- frame is active. */
- Fselect_frame (WINDOW_FRAME (w), Qnil);
- }
- else
- selected_frame->selected_window = window;
-
- record_buffer (w->buffer);
- Fset_buffer (w->buffer);
-
- XBUFFER (w->buffer)->last_selected_window = window;
-
- /* 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. */
- {
- register int new_point = marker_position (w->pointm);
- if (new_point < BEGV)
- SET_PT (BEGV);
- else if (new_point > ZV)
- SET_PT (ZV);
- else
- SET_PT (new_point);
- }
-
- windows_or_buffers_changed++;
- return window;
-}
-
-/* Deiconify the frame containing the window WINDOW,
- unless it is the selected frame;
- then return WINDOW.
-
- The reason for the exception for the selected frame
- is that it seems better not to change the selected frames visibility
- merely because of displaying a different buffer in it.
- The deiconification is useful when a buffer gets shown in
- another frame that you were not using lately. */
-
-static Lisp_Object
-display_buffer_1 (window)
- Lisp_Object window;
-{
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
- FRAME_SAMPLE_VISIBILITY (f);
- if (f != selected_frame)
- {
- if (FRAME_ICONIFIED_P (f))
- Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
- else if (FRAME_VISIBLE_P (f))
- Fraise_frame (WINDOW_FRAME (XWINDOW (window)));
- }
- return window;
-}
-
-DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
- "Returns non-nil if a buffer named BUFFER-NAME would be created specially.\n\
-The value is actually t if the frame should be called with default frame\n\
-parameters, and a list of frame parameters if they were specified.\n\
-See `special-display-buffer-names', and `special-display-regexps'.")
- (buffer_name)
- Lisp_Object buffer_name;
-{
- Lisp_Object tem;
-
- CHECK_STRING (buffer_name, 1);
-
- tem = Fmember (buffer_name, Vspecial_display_buffer_names);
- if (!NILP (tem))
- return Qt;
-
- tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
- if (!NILP (tem))
- return XCDR (tem);
-
- for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
- {
- Lisp_Object car = XCAR (tem);
- if (STRINGP (car)
- && fast_string_match (car, buffer_name) >= 0)
- return Qt;
- else if (CONSP (car)
- && STRINGP (XCAR (car))
- && fast_string_match (XCAR (car), buffer_name) >= 0)
- return XCDR (tem);
- }
- return Qnil;
-}
-
-DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
- "Returns non-nil if a new buffer named BUFFER-NAME would use the same window.\n\
-See `same-window-buffer-names' and `same-window-regexps'.")
- (buffer_name)
- Lisp_Object buffer_name;
-{
- Lisp_Object tem;
-
- CHECK_STRING (buffer_name, 1);
-
- tem = Fmember (buffer_name, Vsame_window_buffer_names);
- if (!NILP (tem))
- return Qt;
-
- tem = Fassoc (buffer_name, Vsame_window_buffer_names);
- if (!NILP (tem))
- return Qt;
-
- for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
- {
- Lisp_Object car = XCAR (tem);
- if (STRINGP (car)
- && fast_string_match (car, buffer_name) >= 0)
- return Qt;
- else if (CONSP (car)
- && STRINGP (XCAR (car))
- && fast_string_match (XCAR (car), buffer_name) >= 0)
- return Qt;
- }
- return Qnil;
-}
-
-DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
- "bDisplay buffer: \nP",
- "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 use that one,\n\
-unless the window is the selected window and the optional second\n\
-argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
-If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
-Returns the window displaying BUFFER.\n\
-\n\
-The variables `special-display-buffer-names', `special-display-regexps',\n\
-`same-window-buffer-names', and `same-window-regexps' customize how certain\n\
-buffer names are handled.")
- (buffer, not_this_window)
- register Lisp_Object buffer, not_this_window;
-{
- register Lisp_Object window, tem;
-
- buffer = Fget_buffer (buffer);
- CHECK_BUFFER (buffer, 0);
-
- if (!NILP (Vdisplay_buffer_function))
- return call2 (Vdisplay_buffer_function, buffer, not_this_window);
-
- if (NILP (not_this_window)
- && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
- return display_buffer_1 (selected_window);
-
- /* See if the user has specified this buffer should appear
- in the selected window. */
- if (NILP (not_this_window))
- {
- tem = Fsame_window_p (XBUFFER (buffer)->name);
- if (!NILP (tem))
- {
- Fswitch_to_buffer (buffer, Qnil);
- return display_buffer_1 (selected_window);
- }
- }
-
- /* If pop_up_frames,
- look for a window showing BUFFER on any visible or iconified frame.
- Otherwise search only the current frame. */
- if (pop_up_frames || last_nonminibuf_frame == 0)
- XSETFASTINT (tem, 0);
- else
- XSETFRAME (tem, last_nonminibuf_frame);
- window = Fget_buffer_window (buffer, tem);
- if (!NILP (window)
- && (NILP (not_this_window) || !EQ (window, selected_window)))
- {
- return display_buffer_1 (window);
- }
-
- /* Certain buffer names get special handling. */
- if (!NILP (Vspecial_display_function))
- {
- tem = Fspecial_display_p (XBUFFER (buffer)->name);
- if (EQ (tem, Qt))
- return call1 (Vspecial_display_function, buffer);
- if (CONSP (tem))
- return call2 (Vspecial_display_function, buffer, tem);
- }
-
- /* If there are no frames open that have more than a minibuffer,
- we need to create a new frame. */
- if (pop_up_frames || last_nonminibuf_frame == 0)
- {
- window = Fframe_selected_window (call0 (Vpop_up_frame_function));
- Fset_window_buffer (window, buffer);
- return display_buffer_1 (window);
- }
-
- if (pop_up_windows
- || FRAME_MINIBUF_ONLY_P (selected_frame)
- /* If the current frame is a special display frame,
- don't try to reuse its windows. */
- || !NILP (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->dedicated)
- )
- {
- Lisp_Object frames;
-
- frames = Qnil;
- if (FRAME_MINIBUF_ONLY_P (selected_frame))
- XSETFRAME (frames, last_nonminibuf_frame);
- /* Don't try to create a window if would get an error */
- if (split_height_threshold < window_min_height << 1)
- split_height_threshold = window_min_height << 1;
-
- /* Note that both Fget_largest_window and Fget_lru_window
- ignore minibuffers and dedicated windows.
- This means they can return nil. */
-
- /* If the frame we would try to split cannot be split,
- try other frames. */
- if (FRAME_NO_SPLIT_P (NILP (frames) ? selected_frame
- : last_nonminibuf_frame))
- {
- /* Try visible frames first. */
- window = Fget_largest_window (Qvisible);
- /* If that didn't work, try iconified frames. */
- if (NILP (window))
- window = Fget_largest_window (make_number (0));
- if (NILP (window))
- window = Fget_largest_window (Qt);
- }
- else
- window = Fget_largest_window (frames);
-
- /* If we got a tall enough full-width window that can be split,
- split it. */
- if (!NILP (window)
- && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
- && window_height (window) >= split_height_threshold
- && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
- window = Fsplit_window (window, Qnil, Qnil);
- else
- {
- Lisp_Object upper, lower, other;
-
- window = Fget_lru_window (frames);
- /* If the LRU window is selected, and big enough,
- and can be split, split it. */
- if (!NILP (window)
- && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
- && (EQ (window, selected_window)
- || EQ (XWINDOW (window)->parent, Qnil))
- && window_height (window) >= window_min_height << 1)
- window = Fsplit_window (window, Qnil, Qnil);
- /* If Fget_lru_window returned nil, try other approaches. */
- /* Try visible frames first. */
- if (NILP (window))
- window = Fget_largest_window (Qvisible);
- /* If that didn't work, try iconified frames. */
- if (NILP (window))
- window = Fget_largest_window (make_number (0));
- /* Try invisible frames. */
- if (NILP (window))
- window = Fget_largest_window (Qt);
- /* As a last resort, make a new frame. */
- if (NILP (window))
- window = Fframe_selected_window (call0 (Vpop_up_frame_function));
- /* If window appears above or below another,
- even out their heights. */
- other = upper = lower = Qnil;
- if (!NILP (XWINDOW (window)->prev))
- other = upper = XWINDOW (window)->prev, lower = window;
- if (!NILP (XWINDOW (window)->next))
- other = lower = XWINDOW (window)->next, upper = window;
- if (!NILP (other)
- /* Check that OTHER and WINDOW are vertically arrayed. */
- && XWINDOW (other)->top != XWINDOW (window)->top
- && XWINDOW (other)->height > XWINDOW (window)->height)
- {
- int total = XWINDOW (other)->height + XWINDOW (window)->height;
- Lisp_Object old_selected_window;
- old_selected_window = selected_window;
-
- selected_window = upper;
- change_window_height (total / 2 - XWINDOW (upper)->height, 0);
- selected_window = old_selected_window;
- }
- }
- }
- else
- window = Fget_lru_window (Qnil);
-
- Fset_window_buffer (window, buffer);
- return display_buffer_1 (window);
-}
-
-void
-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);
- BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
- BEGV = BEG;
- ZV = Z;
- SET_PT (BEG);
- XBUFFER (buf)->clip_changed = 1;
- set_buffer_internal (old);
-
- if (!EQ (Vtemp_buffer_show_function, Qnil))
- call1 (Vtemp_buffer_show_function, buf);
- else
- {
- window = Fdisplay_buffer (buf, Qnil);
-
- if (XFRAME (XWINDOW (window)->frame) != selected_frame)
- Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
- Vminibuf_scroll_window = window;
- w = XWINDOW (window);
- XSETFASTINT (w->hscroll, 0);
- set_marker_restricted (w->start, make_number (1), buf);
- set_marker_restricted (w->pointm, make_number (1), buf);
-
- /* Run temp-buffer-show-hook, with the chosen window selected. */
- if (!NILP (Vrun_hooks))
- {
- Lisp_Object tem;
- tem = Fboundp (Qtemp_buffer_show_hook);
- if (!NILP (tem))
- {
- tem = Fsymbol_value (Qtemp_buffer_show_hook);
- if (!NILP (tem))
- {
- int count = specpdl_ptr - specpdl;
-
- /* Select the window that was chosen, for running the hook. */
- record_unwind_protect (Fset_window_configuration,
- Fcurrent_window_configuration (Qnil));
-
- Fselect_window (window);
- call1 (Vrun_hooks, Qtemp_buffer_show_hook);
- unbind_to (count, Qnil);
- }
- }
- }
- }
-}
-
-static
-make_dummy_parent (window)
- Lisp_Object window;
-{
- Lisp_Object new;
- register struct window *o, *p;
- register struct Lisp_Vector *vec;
- int i;
-
- o = XWINDOW (window);
- vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
- for (i = 0; i < VECSIZE (struct window); ++i)
- vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
- vec->size = VECSIZE (struct window);
- p = (struct window *)vec;
- XSETWINDOW (new, p);
-
- XSETFASTINT (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 HORFLAG is non-nil, split side by side\n\
-and put SIZE columns in the first of the pair.")
- (window, size, horflag)
- Lisp_Object window, size, horflag;
-{
- register Lisp_Object new;
- register struct window *o, *p;
- FRAME_PTR fo;
- register int size_int;
-
- if (NILP (window))
- window = selected_window;
- else
- CHECK_LIVE_WINDOW (window, 0);
-
- o = XWINDOW (window);
- fo = XFRAME (WINDOW_FRAME (o));
-
- if (NILP (size))
- {
- if (!NILP (horflag))
- /* Calculate the size of the left-hand window, by dividing
- the usable space in columns by two. */
- size_int = XFASTINT (o->width) >> 1;
- else
- size_int = XFASTINT (o->height) >> 1;
- }
- else
- {
- CHECK_NUMBER (size, 1);
- size_int = XINT (size);
- }
-
- if (MINI_WINDOW_P (o))
- error ("Attempt to split minibuffer window");
- else if (FRAME_NO_SPLIT_P (fo))
- error ("Attempt to split unsplittable frame");
-
- check_min_window_sizes ();
-
- if (NILP (horflag))
- {
- if (size_int < window_min_height)
- error ("Window height %d too small (after splitting)", size_int);
- if (size_int + window_min_height > XFASTINT (o->height))
- error ("Window height %d too small (after splitting)",
- XFASTINT (o->height) - size_int);
- if (NILP (o->parent)
- || NILP (XWINDOW (o->parent)->vchild))
- {
- make_dummy_parent (window);
- new = o->parent;
- XWINDOW (new)->vchild = window;
- }
- }
- else
- {
- if (size_int < window_min_width)
- error ("Window width %d too small (after splitting)", size_int);
-
- if (size_int + window_min_width > XFASTINT (o->width))
- error ("Window width %d too small (after splitting)",
- XFASTINT (o->width) - size_int);
- if (NILP (o->parent)
- || NILP (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++;
- FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
- new = make_window ();
- p = XWINDOW (new);
-
- p->frame = o->frame;
- p->next = o->next;
- if (!NILP (p->next))
- XWINDOW (p->next)->prev = new;
- p->prev = window;
- o->next = new;
- p->parent = o->parent;
- p->buffer = Qt;
-
- Fset_window_buffer (new, o->buffer);
-
- /* Apportion the available frame space among the two new windows */
-
- if (!NILP (horflag))
- {
- p->height = o->height;
- p->top = o->top;
- XSETFASTINT (p->width, XFASTINT (o->width) - size_int);
- XSETFASTINT (o->width, size_int);
- XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
- }
- else
- {
- p->left = o->left;
- p->width = o->width;
- XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
- XSETFASTINT (o->height, size_int);
- XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
- }
-
- 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.")
- (arg, side)
- register Lisp_Object arg, side;
-{
- CHECK_NUMBER (arg, 0);
- change_window_height (XINT (arg), !NILP (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.")
- (arg, side)
- register Lisp_Object arg, side;
-{
- CHECK_NUMBER (arg, 0);
- change_window_height (-XINT (arg), !NILP (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(w) \
- (widthflag \
- ? window_min_width \
- : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
-
-#define CURBEG(w) \
- *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
-
-#define CURSIZE(w) \
- *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (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);
-
- check_min_window_sizes ();
-
- window = selected_window;
- while (1)
- {
- p = XWINDOW (window);
- parent = p->parent;
- if (NILP (parent))
- {
- if (widthflag)
- error ("No other window to side of this one");
- break;
- }
- if (widthflag ? !NILP (XWINDOW (parent)->hchild)
- : !NILP (XWINDOW (parent)->vchild))
- break;
- window = parent;
- }
-
- sizep = &CURSIZE (window);
-
- {
- register int maxdelta;
-
- maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
- : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
- : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
- /* This is a frame with only one window, a minibuffer-only
- or a minibufferless frame. */
- : (delta = 0));
-
- if (delta > maxdelta)
- /* This case traps trying to make the minibuffer
- the full frame, or make the only window aside from the
- minibuffer the full frame. */
- delta = maxdelta;
- }
-
- if (*sizep + delta < MINSIZE (window))
- {
- Fdelete_window (window);
- return;
- }
-
- if (delta == 0)
- return;
-
- if (!NILP (p->next)
- && (*sizefun) (p->next) - delta >= MINSIZE (p->next))
- {
- (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0);
- (*setsizefun) (window, *sizep + delta, 0);
- CURBEG (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 (!NILP (p->prev)
- && (*sizefun) (p->prev) - delta >= MINSIZE (p->prev))
- {
- (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0);
- CURBEG (window) -= 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 (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);
- }
-
- XSETFASTINT (p->last_modified, 0);
- XSETFASTINT (p->last_overlay_modified, 0);
-}
-#undef MINSIZE
-#undef CURBEG
-#undef CURSIZE
-
-
-/* Return number of lines of text (not counting mode line) in W. */
-
-int
-window_internal_height (w)
- struct window *w;
-{
- int ht = XFASTINT (w->height);
-
- if (MINI_WINDOW_P (w))
- return ht;
-
- if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
- || !NILP (w->next) || !NILP (w->prev)
- || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
- return ht - 1;
-
- return ht;
-}
-
-
-/* Return the number of columns in W.
- Don't count columns occupied by scroll bars or the vertical bar
- separating W from the sibling to its right. */
-int
-window_internal_width (w)
- struct window *w;
-{
- FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
- int width = XINT (w->width);
-
- /* Scroll bars occupy a few columns. */
- if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- return width - FRAME_SCROLL_BAR_COLS (f);
-
- /* The column of `|' characters separating side-by-side windows
- occupies one column only. */
- if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
- return width - 1;
-
- return width;
-}
-
-
-/* Scroll contents of window WINDOW up N lines.
- If WHOLE is nonzero, it means we wanted to scroll
- by entire screenfuls. */
-
-static void
-window_scroll (window, n, whole, noerror)
- Lisp_Object window;
- int n;
- int whole;
- int noerror;
-{
- register struct window *w = XWINDOW (window);
- register int opoint = PT;
- register int pos;
- register int ht = window_internal_height (w);
- register Lisp_Object tem;
- int lose;
- Lisp_Object bolp, nmoved;
- int startpos;
- struct position posit;
- int original_vpos;
-
- startpos = marker_position (w->start);
-
- posit = *compute_motion (startpos, 0, 0, 0,
- PT, ht, 0,
- window_internal_width (w), XINT (w->hscroll),
- 0, w);
- original_vpos = posit.vpos;
-
- XSETFASTINT (tem, PT);
- tem = Fpos_visible_in_window_p (tem, window);
-
- if (NILP (tem))
- {
- Fvertical_motion (make_number (- (ht / 2)), window);
- startpos = PT;
- }
-
- SET_PT (startpos);
- lose = n < 0 && PT == BEGV;
- Fvertical_motion (make_number (n), window);
- pos = PT;
- bolp = Fbolp ();
- SET_PT (opoint);
-
- if (lose)
- {
- if (noerror)
- return;
- else
- Fsignal (Qbeginning_of_buffer, Qnil);
- }
-
- if (pos < ZV)
- {
- extern int scroll_margin;
-
- int this_scroll_margin = scroll_margin;
-
- /* Don't use a scroll margin that is negative or too large. */
- if (this_scroll_margin < 0)
- this_scroll_margin = 0;
-
- if (XINT (w->height) < 4 * scroll_margin)
- this_scroll_margin = XINT (w->height) / 4;
-
- set_marker_restricted (w->start, make_number (pos), w->buffer);
- w->start_at_line_beg = bolp;
- w->update_mode_line = Qt;
- XSETFASTINT (w->last_modified, 0);
- XSETFASTINT (w->last_overlay_modified, 0);
- /* Set force_start so that redisplay_window will run
- the window-scroll-functions. */
- w->force_start = Qt;
-
- if (whole)
- {
- SET_PT (pos);
- Fvertical_motion (make_number (original_vpos), window);
- }
- /* If we scrolled forward, put point enough lines down
- that it is outside the scroll margin. */
- else if (n > 0)
- {
- int top_margin;
-
- if (this_scroll_margin > 0)
- {
- SET_PT (pos);
- Fvertical_motion (make_number (this_scroll_margin), window);
- top_margin = PT;
- }
- else
- top_margin = pos;
-
- if (top_margin <= opoint)
- SET_PT (opoint);
- else
- {
- SET_PT (pos);
- Fvertical_motion (make_number (original_vpos), window);
- }
- }
- else if (n < 0)
- {
- int bottom_margin;
-
- /* If we scrolled backward, put point near the end of the window
- but not within the scroll margin. */
- SET_PT (pos);
- tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
- if (XFASTINT (tem) == ht - this_scroll_margin)
- bottom_margin = PT;
- else
- bottom_margin = PT + 1;
-
- if (bottom_margin > opoint)
- SET_PT (opoint);
- else
- {
- SET_PT (pos);
- Fvertical_motion (make_number (original_vpos), window);
- }
- }
- }
- else
- {
- if (noerror)
- return;
- else
- Fsignal (Qend_of_buffer, Qnil);
- }
-}
-
-/* This is the guts of Fscroll_up and Fscroll_down. */
-
-static void
-scroll_command (n, direction)
- register Lisp_Object n;
- int direction;
-{
- register int defalt;
- int count = specpdl_ptr - specpdl;
-
- /* If selected window's buffer isn't current, make it current for the moment.
- But don't screw up if window_scroll gets an error. */
- if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
- {
- record_unwind_protect (save_excursion_restore, save_excursion_save ());
- Fset_buffer (XWINDOW (selected_window)->buffer);
- }
-
- defalt = (window_internal_height (XWINDOW (selected_window))
- - next_screen_context_lines);
- defalt = direction * (defalt < 1 ? 1 : defalt);
-
- if (NILP (n))
- window_scroll (selected_window, defalt, 1, 0);
- else if (EQ (n, Qminus))
- window_scroll (selected_window, - defalt, 1, 0);
- else
- {
- n = Fprefix_numeric_value (n);
- window_scroll (selected_window, XINT (n) * direction, 0, 0);
- }
-
- unbind_to (count, Qnil);
-}
-
-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\
-A near full screen is `next-screen-context-lines' less than a full screen.\n\
-Negative ARG means scroll downward.\n\
-When calling from a program, supply a number as argument or nil.")
- (arg)
- Lisp_Object arg;
-{
- scroll_command (arg, 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\
-A near full screen is `next-screen-context-lines' less than a full screen.\n\
-Negative ARG means scroll upward.\n\
-When calling from a program, supply a number as argument or nil.")
- (arg)
- Lisp_Object arg;
-{
- scroll_command (arg, -1);
- return Qnil;
-}
-
-DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
- "Return the other window for \"other window scroll\" commands.\n\
-If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
-specifies the window.\n\
-If `other-window-scroll-buffer' is non-nil, a window\n\
-showing that buffer is used.")
- ()
-{
- Lisp_Object window;
-
- if (MINI_WINDOW_P (XWINDOW (selected_window))
- && !NILP (Vminibuf_scroll_window))
- window = Vminibuf_scroll_window;
- /* If buffer is specified, scroll that buffer. */
- else if (!NILP (Vother_window_scroll_buffer))
- {
- window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
- if (NILP (window))
- window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
- }
- else
- {
- /* Nothing specified; look for a neighboring window on the same
- frame. */
- window = Fnext_window (selected_window, Qnil, Qnil);
-
- if (EQ (window, selected_window))
- /* That didn't get us anywhere; look for a window on another
- visible frame. */
- do
- window = Fnext_window (window, Qnil, Qt);
- while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
- && ! EQ (window, selected_window));
- }
-
- CHECK_LIVE_WINDOW (window, 0);
-
- if (EQ (window, selected_window))
- error ("There is no other window");
-
- return window;
-}
-
-DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
- "Scroll 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. Negative ARG means scroll downward.\n\
-When calling from a program, supply a number as argument or nil.\n\
-\n\
-If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
-specifies the window to scroll.\n\
-If `other-window-scroll-buffer' is non-nil, scroll the window\n\
-showing that buffer, popping the buffer up if necessary.")
- (arg)
- register Lisp_Object arg;
-{
- register Lisp_Object window;
- register int defalt;
- register struct window *w;
- register int count = specpdl_ptr - specpdl;
-
- window = Fother_window_for_scrolling ();
-
- w = XWINDOW (window);
- defalt = window_internal_height (w) - next_screen_context_lines;
- if (defalt < 1) defalt = 1;
-
- /* Don't screw up if window_scroll gets an error. */
- record_unwind_protect (save_excursion_restore, save_excursion_save ());
-
- Fset_buffer (w->buffer);
- SET_PT (marker_position (w->pointm));
-
- if (NILP (arg))
- window_scroll (window, defalt, 1, 1);
- else if (EQ (arg, Qminus))
- window_scroll (window, -defalt, 1, 1);
- else
- {
- if (CONSP (arg))
- arg = Fcar (arg);
- CHECK_NUMBER (arg, 0);
- window_scroll (window, XINT (arg), 0, 1);
- }
-
- Fset_marker (w->pointm, make_number (PT), Qnil);
- unbind_to (count, Qnil);
-
- return Qnil;
-}
-
-DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
- "Scroll selected window display ARG columns left.\n\
-Default for ARG is window width minus 2.")
- (arg)
- register Lisp_Object arg;
-{
-
- if (NILP (arg))
- XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 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, 0, 1, "P",
- "Scroll selected window display ARG columns right.\n\
-Default for ARG is window width minus 2.")
- (arg)
- register Lisp_Object arg;
-{
- if (NILP (arg))
- XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
- else
- arg = Fprefix_numeric_value (arg);
-
- return
- Fset_window_hscroll (selected_window,
- make_number (XINT (XWINDOW (selected_window)->hscroll)
- - XINT (arg)));
-}
-
-DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
- "Center point in window and redisplay frame. 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 window.\n\
-If ARG is omitted or nil, erases the entire frame and then\n\
-redraws with point in the center of the current window.")
- (arg)
- register Lisp_Object arg;
-{
- register struct window *w = XWINDOW (selected_window);
- register int ht = window_internal_height (w);
- struct position pos;
-
- if (NILP (arg))
- {
- extern int frame_garbaged;
-
- SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
- XSETFASTINT (arg, ht / 2);
- }
- else if (CONSP (arg)) /* Just C-u. */
- {
- XSETFASTINT (arg, ht / 2);
- }
- else
- {
- arg = Fprefix_numeric_value (arg);
- CHECK_NUMBER (arg, 0);
- }
-
- if (XINT (arg) < 0)
- XSETINT (arg, XINT (arg) + ht);
-
- pos = *vmotion (PT, - XINT (arg), w);
-
- Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
- w->start_at_line_beg = ((pos.bufpos == BEGV
- || FETCH_CHAR (pos.bufpos - 1) == '\n')
- ? Qt : Qnil);
- 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 point at center of window.\n\
-An argument specifies frame 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 = window_internal_height (w);
- register int start;
- Lisp_Object window;
-
- if (NILP (arg))
- XSETFASTINT (arg, height / 2);
- else
- {
- arg = Fprefix_numeric_value (arg);
- if (XINT (arg) < 0)
- XSETINT (arg, XINT (arg) + height);
- }
-
- start = marker_position (w->start);
- XSETWINDOW (window, w);
- if (start < BEGV || start > ZV)
- {
- Fvertical_motion (make_number (- (height / 2)), window);
- Fset_marker (w->start, make_number (PT), w->buffer);
- w->start_at_line_beg = Fbolp ();
- w->force_start = Qt;
- }
- else
- SET_PT (start);
-
- return Fvertical_motion (arg, window);
-}
-
-struct save_window_data
- {
- EMACS_INT size_from_Lisp_Vector_struct;
- struct Lisp_Vector *next_from_Lisp_Vector_struct;
- Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
- Lisp_Object selected_frame;
- Lisp_Object current_window;
- Lisp_Object current_buffer;
- Lisp_Object minibuf_scroll_window;
- Lisp_Object root_window;
- Lisp_Object focus_frame;
- /* Record the values of window-min-width and window-min-height
- so that window sizes remain consistent with them. */
- Lisp_Object min_width, min_height;
- /* A vector, interpreted as a struct saved_window */
- Lisp_Object saved_windows;
- };
-
-/* This is saved as a Lisp_Vector */
-struct saved_window
- {
- /* these first two must agree with struct Lisp_Vector in lisp.h */
- EMACS_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;
- Lisp_Object display_table;
- };
-#define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
-
-#define SAVED_WINDOW_N(swv,n) \
- ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
-
-DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
- "T if OBJECT is a window-configuration object.")
- (object)
- Lisp_Object object;
-{
- if (WINDOW_CONFIGURATIONP (object))
- return Qt;
- return Qnil;
-}
-
-
-DEFUN ("set-window-configuration", Fset_window_configuration,
- Sset_window_configuration, 1, 1, 0,
- "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
-CONFIGURATION must be a value previously returned\n\
-by `current-window-configuration' (which see).")
- (configuration)
- Lisp_Object configuration;
-{
- register struct save_window_data *data;
- struct Lisp_Vector *saved_windows;
- Lisp_Object new_current_buffer;
- Lisp_Object frame;
- FRAME_PTR f;
-
- while (!WINDOW_CONFIGURATIONP (configuration))
- {
- configuration = wrong_type_argument (intern ("window-configuration-p"),
- configuration);
- }
-
- data = (struct save_window_data *) XVECTOR (configuration);
- saved_windows = XVECTOR (data->saved_windows);
-
- new_current_buffer = data->current_buffer;
- if (NILP (XBUFFER (new_current_buffer)->name))
- new_current_buffer = Qnil;
-
- frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
- f = XFRAME (frame);
-
- /* If f is a dead frame, don't bother rebuilding its window tree.
- However, there is other stuff we should still try to do below. */
- if (FRAME_LIVE_P (f))
- {
- register struct window *w;
- register struct saved_window *p;
- int k;
-
- /* If the frame has been resized since this window configuration was
- made, we change the frame to the size specified in the
- configuration, restore the configuration, and then resize it
- back. We keep track of the prevailing height in these variables. */
- int previous_frame_height = FRAME_HEIGHT (f);
- int previous_frame_width = FRAME_WIDTH (f);
- int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
-
- if (XFASTINT (data->frame_height) != previous_frame_height
- || XFASTINT (data->frame_width) != previous_frame_width)
- change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
-#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
- if (XFASTINT (data->frame_menu_bar_lines)
- != previous_frame_menu_bar_lines)
- x_set_menu_bar_lines (f, data->frame_menu_bar_lines, 0);
-#endif
-
- windows_or_buffers_changed++;
- FRAME_WINDOW_SIZES_CHANGED (f) = 1;
-
- /* Temporarily avoid any problems with windows that are smaller
- than they are supposed to be. */
- window_min_height = 1;
- window_min_width = 1;
-
- /* Kludge Alert!
- Mark all windows now on frame as "deleted".
- Restoring the new configuration "undeletes" any that are in it.
-
- Save their current buffers in their height fields, since we may
- need it later, if a buffer saved in the configuration is now
- dead. */
- delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
-
- for (k = 0; k < saved_windows->size; k++)
- {
- p = SAVED_WINDOW_N (saved_windows, k);
- w = XWINDOW (p->window);
- w->next = Qnil;
-
- if (!NILP (p->parent))
- w->parent = SAVED_WINDOW_N (saved_windows,
- XFASTINT (p->parent))->window;
- else
- w->parent = Qnil;
-
- if (!NILP (p->prev))
- {
- w->prev = SAVED_WINDOW_N (saved_windows,
- XFASTINT (p->prev))->window;
- XWINDOW (w->prev)->next = p->window;
- }
- else
- {
- w->prev = Qnil;
- if (!NILP (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;
- }
- }
- }
-
- /* If we squirreled away the buffer in the window's height,
- restore it now. */
- if (BUFFERP (w->height))
- w->buffer = w->height;
- w->left = p->left;
- w->top = p->top;
- w->width = p->width;
- w->height = p->height;
- w->hscroll = p->hscroll;
- w->display_table = p->display_table;
- XSETFASTINT (w->last_modified, 0);
- XSETFASTINT (w->last_overlay_modified, 0);
-
- /* Reinstall the saved buffer and pointers into it. */
- if (NILP (p->buffer))
- w->buffer = p->buffer;
- else
- {
- if (!NILP (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);
-
- /* As documented in Fcurrent_window_configuration, don't
- save the location of point in the buffer which was current
- when the window configuration was recorded. */
- if (!EQ (p->buffer, new_current_buffer)
- && XBUFFER (p->buffer) == current_buffer)
- Fgoto_char (w->pointm);
- }
- else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
- /* Else unless window has a live buffer, get one. */
- {
- w->buffer = Fcdr (Fcar (Vbuffer_alist));
- /* This will set the markers to beginning of visible
- range. */
- 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. */
- {
- /* Set window markers at start of visible range. */
- 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;
- }
- }
- }
-
- FRAME_ROOT_WINDOW (f) = data->root_window;
- Fselect_window (data->current_window);
-
- if (NILP (data->focus_frame)
- || (FRAMEP (data->focus_frame)
- && FRAME_LIVE_P (XFRAME (data->focus_frame))))
- Fredirect_frame_focus (frame, data->focus_frame);
-
-#if 0 /* I don't understand why this is needed, and it causes problems
- when the frame's old selected window has been deleted. */
- if (f != selected_frame && FRAME_WINDOW_P (f))
- do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
- Qnil, 0);
-#endif
-
- /* Set the screen height to the value it had before this function. */
- if (previous_frame_height != FRAME_HEIGHT (f)
- || previous_frame_width != FRAME_WIDTH (f))
- change_frame_size (f, previous_frame_height, previous_frame_width,
- 0, 0);
-#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
- if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
- x_set_menu_bar_lines (f, previous_frame_menu_bar_lines, 0);
-#endif
- }
-
- /* Restore the minimum heights recorded in the configuration. */
- window_min_height = XINT (data->min_height);
- window_min_width = XINT (data->min_width);
-
- /* Fselect_window will have made f the selected frame, so we
- reselect the proper frame here. Fhandle_switch_frame will change the
- selected window too, but that doesn't make the call to
- Fselect_window above totally superfluous; it still sets f's
- selected window. */
- if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
- do_switch_frame (data->selected_frame, Qnil, 0);
-
- if (!NILP (new_current_buffer))
- Fset_buffer (new_current_buffer);
-
- Vminibuf_scroll_window = data->minibuf_scroll_window;
- return (Qnil);
-}
-
-/* Mark all windows now on frame as deleted
- by setting their buffers to nil. */
-
-void
-delete_all_subwindows (w)
- register struct window *w;
-{
- if (!NILP (w->next))
- delete_all_subwindows (XWINDOW (w->next));
- if (!NILP (w->vchild))
- delete_all_subwindows (XWINDOW (w->vchild));
- if (!NILP (w->hchild))
- delete_all_subwindows (XWINDOW (w->hchild));
-
- w->height = w->buffer; /* See Fset_window_configuration for excuse. */
-
- if (!NILP (w->buffer))
- unshow_buffer (w);
-
- /* We set all three of these fields to nil, to make sure that we can
- distinguish this dead window from any live window. Live leaf
- windows will have buffer set, and combination windows will have
- vchild or hchild set. */
- w->buffer = Qnil;
- w->vchild = Qnil;
- w->hchild = Qnil;
-}
-
-static int
-count_windows (window)
- register struct window *window;
-{
- register int count = 1;
- if (!NILP (window->next))
- count += count_windows (XWINDOW (window->next));
- if (!NILP (window->vchild))
- count += count_windows (XWINDOW (window->vchild));
- if (!NILP (window->hchild))
- count += count_windows (XWINDOW (window->hchild));
- return count;
-}
-
-static int
-save_window_save (window, vector, i)
- Lisp_Object window;
- struct Lisp_Vector *vector;
- int i;
-{
- register struct saved_window *p;
- register struct window *w;
- register Lisp_Object tem;
-
- for (;!NILP (window); window = w->next)
- {
- p = SAVED_WINDOW_N (vector, i);
- w = XWINDOW (window);
-
- XSETFASTINT (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;
- p->display_table = w->display_table;
- if (!NILP (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, Qnil);
-
- p->start = Fcopy_marker (w->start, Qnil);
- p->start_at_line_beg = w->start_at_line_beg;
-
- tem = XBUFFER (w->buffer)->mark;
- p->mark = Fcopy_marker (tem, Qnil);
- }
- else
- {
- p->pointm = Qnil;
- p->start = Qnil;
- p->mark = Qnil;
- p->start_at_line_beg = Qnil;
- }
-
- if (NILP (w->parent))
- p->parent = Qnil;
- else
- p->parent = XWINDOW (w->parent)->temslot;
-
- if (NILP (w->prev))
- p->prev = Qnil;
- else
- p->prev = XWINDOW (w->prev)->temslot;
-
- if (!NILP (w->vchild))
- i = save_window_save (w->vchild, vector, i);
- if (!NILP (w->hchild))
- i = save_window_save (w->hchild, vector, i);
- }
-
- return i;
-}
-
-DEFUN ("current-window-configuration", Fcurrent_window_configuration,
- Scurrent_window_configuration, 0, 1, 0,
- "Return an object representing the current window configuration of FRAME.\n\
-If FRAME is nil or omitted, use the selected frame.\n\
-This describes the number of windows, their sizes and current buffers,\n\
-and for each displayed buffer, where display starts, and the positions of\n\
-point and mark. An exception is made for point in the current buffer:\n\
-its value is -not- saved.\n\
-This also records the currently selected frame, and FRAME's focus\n\
-redirection (see `redirect-frame-focus').")
- (frame)
- Lisp_Object frame;
-{
- register Lisp_Object tem;
- register int n_windows;
- register struct save_window_data *data;
- register struct Lisp_Vector *vec;
- register int i;
- FRAME_PTR f;
-
- if (NILP (frame))
- f = selected_frame;
- else
- {
- CHECK_LIVE_FRAME (frame, 0);
- f = XFRAME (frame);
- }
-
- n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
- vec = allocate_vectorlike (VECSIZE (struct save_window_data));
- for (i = 0; i < VECSIZE (struct save_window_data); i++)
- vec->contents[i] = Qnil;
- vec->size = VECSIZE (struct save_window_data);
- data = (struct save_window_data *)vec;
-
- XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
- XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
- XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
- XSETFRAME (data->selected_frame, selected_frame);
- data->current_window = FRAME_SELECTED_WINDOW (f);
- XSETBUFFER (data->current_buffer, current_buffer);
- data->minibuf_scroll_window = Vminibuf_scroll_window;
- data->root_window = FRAME_ROOT_WINDOW (f);
- data->focus_frame = FRAME_FOCUS_FRAME (f);
- XSETINT (data->min_height, window_min_height);
- XSETINT (data->min_width, window_min_width);
- 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 (FRAME_ROOT_WINDOW (f),
- XVECTOR (tem), 0);
- XSETWINDOW_CONFIGURATION (tem, data);
- return (tem);
-}
-
-DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
- 0, UNEVALLED, 0,
- "Execute body, preserving window sizes and contents.\n\
-Restore which buffer appears in which window, where display starts,\n\
-and the value of point and mark for each window.\n\
-Also restore which buffer is current.\n\
-But do not preserve point in 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 (Qnil));
- val = Fprogn (args);
- return unbind_to (count, val);
-}
-
-init_window_once ()
-{
- selected_frame = make_terminal_frame ();
- XSETFRAME (Vterminal_frame, selected_frame);
- minibuf_window = selected_frame->minibuffer_window;
- selected_window = selected_frame->selected_window;
- last_nonminibuf_frame = selected_frame;
-
- window_initialized = 1;
-}
-
-syms_of_window ()
-{
- Qwindowp = intern ("windowp");
- staticpro (&Qwindowp);
-
- Qwindow_live_p = intern ("window-live-p");
- staticpro (&Qwindow_live_p);
-
- Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
- staticpro (&Qtemp_buffer_show_hook);
-
- DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
- "Non-nil means call as function to display a help buffer.\n\
-The function is called with one argument, the buffer to be displayed.\n\
-Used by `with-output-to-temp-buffer'.\n\
-If this function is used, then it must do the entire job of showing\n\
-the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
- Vtemp_buffer_show_function = Qnil;
-
- DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
- "If non-nil, function to call to handle `display-buffer'.\n\
-It will receive two args, the buffer and a flag which if non-nil means\n\
- that the currently selected window is not acceptable.\n\
-Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
-work using this function.");
- Vdisplay_buffer_function = 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_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
- "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
- Vother_window_scroll_buffer = Qnil;
-
- DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
- "*Non-nil means `display-buffer' should make a separate frame.");
- pop_up_frames = 0;
-
- DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
- "Function to call to handle automatic new frame creation.\n\
-It is called with no arguments and should return a newly created frame.\n\
-\n\
-A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
-where `pop-up-frame-alist' would hold the default frame parameters.");
- Vpop_up_frame_function = Qnil;
-
- DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
- "*List of buffer names that should have their own special frames.\n\
-Displaying a buffer whose name is in this list makes a special frame for it\n\
-using `special-display-function'. See also `special-display-regexps'.\n\
-\n\
-An element of the list can be a list instead of just a string.\n\
-There are two ways to use a list as an element:\n\
- (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
-In the first case, FRAME-PARAMETERS are used to create the frame.\n\
-In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
-followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
-All this is done by the function found in `special-display-function'.");
- Vspecial_display_buffer_names = Qnil;
-
- DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
- "*List of regexps saying which buffers should have their own special frames.\n\
-If a buffer name matches one of these regexps, it gets its own frame.\n\
-Displaying a buffer whose name is in this list makes a special frame for it\n\
-using `special-display-function'.\n\
-\n\
-An element of the list can be a list instead of just a string.\n\
-There are two ways to use a list as an element:\n\
- (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
-In the first case, FRAME-PARAMETERS are used to create the frame.\n\
-In the latter case, FUNCTION is called with the buffer as first argument,\n\
-followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
-All this is done by the function found in `special-display-function'.");
- Vspecial_display_regexps = Qnil;
-
- DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
- "Function to call to make a new frame for a special buffer.\n\
-It is called with two arguments, the buffer and optional buffer specific\n\
-data, and should return a window displaying that buffer.\n\
-The default value makes a separate frame for the buffer,\n\
-using `special-display-frame-alist' to specify the frame parameters.\n\
-\n\
-A buffer is special if its is listed in `special-display-buffer-names'\n\
-or matches a regexp in `special-display-regexps'.");
- Vspecial_display_function = Qnil;
-
- DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
- "*List of buffer names that should appear in the selected window.\n\
-Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
-switches to it in the selected window, rather than making it appear\n\
-in some other window.\n\
-\n\
-An element of the list can be a cons cell instead of just a string.\n\
-Then the car must be a string, which specifies the buffer name.\n\
-This is for compatibility with `special-display-buffer-names';\n\
-the cdr of the cons cell is ignored.\n\
-\n\
-See also `same-window-regexps'.");
- Vsame_window_buffer_names = Qnil;
-
- DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
- "*List of regexps saying which buffers should appear in the selected window.\n\
-If a buffer name matches one of these regexps, then displaying it\n\
-using `display-buffer' or `pop-to-buffer' switches to it\n\
-in the selected window, rather than making it appear in some other window.\n\
-\n\
-An element of the list can be a cons cell instead of just a string.\n\
-Then the car must be a string, which specifies the buffer name.\n\
-This is for compatibility with `special-display-buffer-names';\n\
-the cdr of the cons cell is ignored.\n\
-\n\
-See also `same-window-buffer-names'.");
- Vsame_window_regexps = 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 (&Swindow_minibuffer_p);
- defsubr (&Swindowp);
- defsubr (&Swindow_live_p);
- defsubr (&Spos_visible_in_window_p);
- defsubr (&Swindow_buffer);
- defsubr (&Swindow_height);
- defsubr (&Swindow_width);
- defsubr (&Swindow_hscroll);
- defsubr (&Sset_window_hscroll);
- defsubr (&Swindow_redisplay_end_trigger);
- defsubr (&Sset_window_redisplay_end_trigger);
- defsubr (&Swindow_edges);
- defsubr (&Scoordinates_in_window_p);
- defsubr (&Swindow_at);
- defsubr (&Swindow_point);
- defsubr (&Swindow_start);
- defsubr (&Swindow_end);
- defsubr (&Sset_window_point);
- defsubr (&Sset_window_start);
- defsubr (&Swindow_dedicated_p);
- defsubr (&Sset_window_dedicated_p);
- defsubr (&Swindow_display_table);
- defsubr (&Sset_window_display_table);
- 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 (&Sspecial_display_p);
- defsubr (&Ssame_window_p);
- 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 (&Sother_window_for_scrolling);
- defsubr (&Sscroll_other_window);
- defsubr (&Srecenter);
- defsubr (&Smove_to_window_line);
- defsubr (&Swindow_configuration_p);
- defsubr (&Sset_window_configuration);
- defsubr (&Scurrent_window_configuration);
- defsubr (&Ssave_window_excursion);
-}
-
-keys_of_window ()
-{
- initial_define_key (control_x_map, '1', "delete-other-windows");
- initial_define_key (control_x_map, '2', "split-window");
- initial_define_key (control_x_map, '0', "delete-window");
- initial_define_key (control_x_map, 'o', "other-window");
- initial_define_key (control_x_map, '^', "enlarge-window");
- initial_define_key (control_x_map, '<', "scroll-left");
- initial_define_key (control_x_map, '>', "scroll-right");
-
- initial_define_key (global_map, Ctl ('V'), "scroll-up");
- initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
- initial_define_key (meta_map, 'v', "scroll-down");
-
- initial_define_key (global_map, Ctl('L'), "recenter");
- initial_define_key (meta_map, 'r', "move-to-window-line");
-}
diff --git a/src/window.h b/src/window.h
deleted file mode 100644
index 0e35ad0d8a7..00000000000
--- a/src/window.h
+++ /dev/null
@@ -1,343 +0,0 @@
-/* Window definitions for GNU Emacs.
- Copyright (C) 1985, 1986, 1993, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* 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 frame. 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 on the frame
-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
-of 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 frame 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, on screens which have an ordinary window and a
-minibuffer, prev of the minibuf window is the root window and next of
-the root window is the minibuf window. On minibufferless screens or
-minibuffer-only screens, the root window and the minibuffer window are
-one and the same, so its prev and next members are nil.
-
-A dead window has its buffer, hchild, and vchild windows all nil. */
-
-struct window
- {
- /* The first two fields are really the header of a vector */
- /* The window code does not refer to them. */
- EMACS_INT size;
- struct Lisp_Vector *vec_next;
- /* The frame this window is on. */
- Lisp_Object frame;
- /* t if this window is a minibuffer window. */
- Lisp_Object mini_p;
- /* 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 frame = 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;
- /* Non-nil means we have explicitly changed the value of start,
- but that the next redisplay is not obliged to use the new value. */
- Lisp_Object optional_new_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;
- /* BUF_OVERLAY_MODIFIED of displayed buffer as of last complete update. */
- Lisp_Object last_overlay_modified;
- /* Value of point at that time */
- Lisp_Object last_point;
- /* Non-nil if the buffer was "modified" when the window
- was last updated. */
- Lisp_Object last_had_star;
- /* This window's vertical scroll bar. This field is only for use
- by the window-system-dependent code which implements the
- scroll bars; it can store anything it likes here. If this
- window is newly created and we haven't displayed a scroll bar in
- it yet, or if the frame doesn't have any scroll bars, this is nil. */
- Lisp_Object vertical_scroll_bar;
-
-/* The rest are currently not used or only half used */
- /* Frame coords of point at that time */
- Lisp_Object last_point_x;
- Lisp_Object last_point_y;
- /* Frame coords of mark as of last time display completed */
- /* May be nil if mark does not exist or was not on frame */
- 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 frame image that window_end_pos
- did not get onto the frame. */
- 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;
- /* Display-table to use for displaying chars in this window.
- Nil means use the buffer's own display-table. */
- Lisp_Object display_table;
- /* Non-nil means window is marked as dedicated. */
- Lisp_Object dedicated;
- /* Line number and position of a line somewhere above the
- top of the screen. */
- /* If this field is nil, it means we don't have a base line. */
- Lisp_Object base_line_number;
- /* If this field is nil, it means we don't have a base line.
- If it is a buffer, it means don't display the line number
- as long as the window shows that buffer. */
- Lisp_Object base_line_pos;
- /* If we have highlighted the region (or any part of it),
- this is the mark position that we used, as an integer. */
- Lisp_Object region_showing;
- /* The column number currently displayed in this window's mode line,
- or nil if column numbers are not being displayed. */
- Lisp_Object column_number_displayed;
- /* If redisplay in this window goes beyond this buffer position,
- must run the redisplay-end-trigger-hook. */
- Lisp_Object redisplay_end_trigger;
- };
-
-/* 1 if W is a minibuffer window. */
-
-#define MINI_WINDOW_P(W) (!EQ ((W)->mini_p, Qnil))
-
-/* Return the frame column at which the text in window W starts.
- This is different from the `left' field because it does not include
- a left-hand scroll bar if any. */
-
-#define WINDOW_LEFT_MARGIN(W) \
- (XFASTINT ((W)->left) \
- + FRAME_LEFT_SCROLL_BAR_WIDTH (XFRAME (WINDOW_FRAME (W))))
-
-/* Return the frame column before window W ends.
- This includes a right-hand scroll bar, if any. */
-
-#define WINDOW_RIGHT_EDGE(W) \
- (XFASTINT ((W)->left) + XFASTINT ((W)->width))
-
-/* Return the frame column before which the text in window W ends.
- This is different from WINDOW_RIGHT_EDGE because it does not include
- a right-hand scroll bar if any. */
-
-#define WINDOW_RIGHT_MARGIN(W) \
- (WINDOW_RIGHT_EDGE (W) \
- - (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (XFRAME (WINDOW_FRAME (W))) \
- ? FRAME_SCROLL_BAR_COLS (XFRAME (WINDOW_FRAME (W))) \
- : 0))
-
-/* 1 if window W takes up the full width of its frame. */
-
-#define WINDOW_FULL_WIDTH_P(W) \
- (XFASTINT ((W)->width) == FRAME_WINDOW_WIDTH (XFRAME (WINDOW_FRAME (W))))
-
-/* 1 if window W's has no other windows to its right in its frame. */
-
-#define WINDOW_RIGHTMOST_P(W) \
- (WINDOW_RIGHT_EDGE (W) == FRAME_WINDOW_WIDTH (XFRAME (WINDOW_FRAME (W))))
-
-/* 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.
-
- This value is always the same as
- FRAME_SELECTED_WINDOW (selected_frame). */
-
-extern Lisp_Object selected_window;
-
-/* This is a time stamp for window selection, so we can find the least
- recently used window. Its only users are Fselect_window,
- init_window_once, and make_frame. */
-
-extern int window_select_count;
-
-/* The minibuffer window of the selected frame.
- Note that you cannot test for minibufferness of an arbitrary window
- by comparing against this; use the MINI_WINDOW_P macro instead. */
-
-extern Lisp_Object minibuf_window;
-
-/* Non-nil => window to for C-M-v to scroll
- when the minibuffer is selected. */
-extern Lisp_Object Vminibuf_scroll_window;
-
-/* nil or a symbol naming the window system
- under which emacs is running
- ('x is the only current possibility) */
-extern Lisp_Object Vwindow_system;
-
-/* Version number of X windows: 10, 11 or nil. */
-extern Lisp_Object Vwindow_system_version;
-
-/* Window that the mouse is over (nil if no mouse support). */
-extern Lisp_Object Vmouse_window;
-
-/* Last mouse-click event (nil if no mouse support). */
-extern Lisp_Object Vmouse_event;
-
-extern Lisp_Object Fnext_window ();
-extern Lisp_Object Fselect_window ();
-extern Lisp_Object Fdisplay_buffer ();
-extern Lisp_Object Fset_window_buffer ();
-extern Lisp_Object make_window ();
-extern Lisp_Object window_from_coordinates ();
-extern Lisp_Object Fwindow_dedicated_p ();
-
-/* Prompt to display in front of the minibuffer contents. */
-extern Lisp_Object minibuf_prompt;
-
-/* The visual width of the above. */
-extern 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. */
-extern char *echo_area_glyphs;
-
-/* This is the length of the message in echo_area_glyphs. */
-extern int echo_area_glyphs_length;
-
-/* Value of echo_area_glyphs when it was last acted on.
- If this is nonzero, there is a message on the frame
- in the minibuffer and it should be erased as soon
- as it is no longer requested to appear. */
-extern char *previous_echo_glyphs;
-
-/* This is the window where the echo area message was displayed.
- It is always a minibuffer window, but it may not be the
- same window currently active as a minibuffer. */
-extern Lisp_Object echo_area_window;
-
-/* Depth in recursive edits. */
-extern int command_loop_level;
-
-/* Depth in minibuffer invocations. */
-extern int minibuf_level;
-
-/* true iff we should redraw the mode lines on the next redisplay. */
-extern int update_mode_lines;
-
-/* Minimum value of GPT - BEG 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;
-
-/* BUF_OVERLAY_MODIFF of current buffer, as of last redisplay that finished;
- if it matches BUF_OVERLAY_MODIFF, beg_unchanged and end_unchanged
- contain no useful information. */
-extern int overlay_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;
-
-/* If *ROWS or *COLS are too small a size for FRAME, set them to the
- minimum allowable size. */
-extern void check_frame_size ( /* FRAME_PTR frame, int *rows, int *cols */ );
diff --git a/src/xdisp.c b/src/xdisp.c
deleted file mode 100644
index dc8b23daff8..00000000000
--- a/src/xdisp.c
+++ /dev/null
@@ -1,4616 +0,0 @@
-/* Display generation from window structure and buffer text.
- Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include <config.h>
-#include <stdio.h>
-/*#include <ctype.h>*/
-#undef NULL
-#include "lisp.h"
-#include "frame.h"
-#include "window.h"
-#include "termchar.h"
-#include "dispextern.h"
-#include "buffer.h"
-#include "indent.h"
-#include "commands.h"
-#include "macros.h"
-#include "disptab.h"
-#include "termhooks.h"
-#include "intervals.h"
-#include "keyboard.h"
-
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
-extern void set_frame_menubar ();
-extern int pending_menu_activation;
-#endif
-
-extern int interrupt_input;
-extern int command_loop_level;
-
-extern int minibuffer_auto_raise;
-
-extern Lisp_Object Qface;
-
-extern Lisp_Object Voverriding_local_map;
-extern Lisp_Object Voverriding_local_map_menu_flag;
-
-Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
-Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
-Lisp_Object Qredisplay_end_trigger_functions;
-
-/* Nonzero means print newline to stdout before next minibuffer message. */
-
-int noninteractive_need_newline;
-
-/* Nonzero means print newline to message log before next message. */
-
-static int message_log_need_newline;
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#define minmax(floor, val, ceil) \
- ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
-
-/* The buffer position of the first character appearing
- entirely or partially on the current frame line.
- Or zero, which disables the optimization for the current frame 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 frame line. */
-static int this_line_vpos;
-
-/* Hpos value for start of display on this frame 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_glyphs when it was last acted on.
- If this is nonzero, there is a message on the frame
- in the minibuffer and it should be erased as soon
- as it is no longer requested to appear. */
-char *previous_echo_glyphs;
-
-/* Nonzero means truncate lines in all windows less wide than the frame */
-int truncate_partial_width_windows;
-
-/* Nonzero means we have more than one non-minibuffer-only frame.
- Not guaranteed to be accurate except while parsing frame-title-format. */
-int multiple_frames;
-
-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;
-
-/* Like mode-line-format, but for the titlebar on a visible frame. */
-Lisp_Object Vframe_title_format;
-
-/* Like mode-line-format, but for the titlebar on an iconified frame. */
-Lisp_Object Vicon_title_format;
-
-/* List of functions to call when a window's size changes. These
- functions get one arg, a frame on which one or more windows' sizes
- have changed. */
-static Lisp_Object Vwindow_size_change_functions;
-
-/* Values of those variables at last redisplay. */
-static Lisp_Object last_arrow_position, last_arrow_string;
-
-Lisp_Object Qmenu_bar_update_hook;
-
-/* Nonzero if overlay arrow has been displayed once in this window. */
-static int overlay_arrow_seen;
-
-/* Nonzero if visible end of buffer has already been displayed once
- in this window. (We need this variable in case there are overlay
- strings that get displayed there.) */
-static int zv_strings_seen;
-
-/* Nonzero means highlight the region even in nonselected windows. */
-static int highlight_nonselected_windows;
-
-/* If cursor motion alone moves point off frame,
- Try scrolling this many lines up or down if that will bring it back. */
-static int scroll_step;
-
-/* Non-0 means scroll just far enough to bring point back on the screen,
- when appropriate. */
-static int scroll_conservatively;
-
-/* Recenter the window whenever point gets within this many lines
- of the top or bottom of the window. */
-int scroll_margin;
-
-/* 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
- (or another buffer with the same base buffer).
- keyboard.c refers to this. */
-int buffer_shared;
-
-/* display_text_line sets these to the frame 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 cursor_vpos;
-static int cursor_hpos;
-
-static int debug_end_pos;
-
-/* Nonzero means display mode line highlighted */
-int mode_line_inverse_video;
-
-static void redisplay_internal ();
-static int message_log_check_duplicate ();
-static void echo_area_display ();
-void mark_window_display_accurate ();
-static void redisplay_windows ();
-static void redisplay_window ();
-static void update_menu_bar ();
-static void try_window ();
-static int try_window_id ();
-static struct position *display_text_line ();
-static void display_mode_line ();
-static int display_mode_element ();
-static char *decode_mode_spec ();
-static int display_string ();
-static void display_menu_bar ();
-static int display_count_lines ();
-
-/* Prompt to display in front of the minibuffer contents */
-Lisp_Object 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_glyphs;
-
-/* This is the length of the message in echo_area_glyphs. */
-int echo_area_glyphs_length;
-
-/* This is the window where the echo area message was displayed.
- It is always a minibuffer window, but it may not be the
- same window currently active as a minibuffer. */
-Lisp_Object echo_area_window;
-
-/* 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, and overlay_unchanged_modified
- matches OVERLAY_MODIFF, that means beg_unchanged and end_unchanged
- contain no useful information */
-int unchanged_modified;
-
-/* OVERLAY_MODIFF as of last redisplay that finished. */
-int overlay_unchanged_modified;
-
-/* Nonzero if window sizes or contents have changed
- since last redisplay that finished */
-int windows_or_buffers_changed;
-
-/* Nonzero after display_mode_line if %l was used
- and it displayed a line number. */
-int line_number_displayed;
-
-/* Maximum buffer size for which to display line numbers. */
-static int line_number_display_limit;
-
-/* Number of lines to keep in the message log buffer.
- t means infinite. nil means don't log at all. */
-Lisp_Object Vmessage_log_max;
-
-/* Output a newline in the *Messages* buffer if "needs" one. */
-
-void
-message_log_maybe_newline ()
-{
- if (message_log_need_newline)
- message_dolog ("", 0, 1);
-}
-
-
-/* Add a string to the message log, optionally terminated with a newline.
- This function calls low-level routines in order to bypass text property
- hooks, etc. which might not be safe to run. */
-
-void
-message_dolog (m, len, nlflag)
- char *m;
- int len, nlflag;
-{
- if (!NILP (Vmessage_log_max))
- {
- struct buffer *oldbuf;
- int oldpoint, oldbegv, oldzv;
- int old_windows_or_buffers_changed = windows_or_buffers_changed;
-
- oldbuf = current_buffer;
- Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
- current_buffer->undo_list = Qt;
- oldpoint = PT;
- oldbegv = BEGV;
- oldzv = ZV;
- BEGV = BEG;
- ZV = Z;
- if (oldpoint == Z)
- oldpoint += len + nlflag;
- if (oldzv == Z)
- oldzv += len + nlflag;
- TEMP_SET_PT (Z);
- if (len)
- insert_1 (m, len, 1, 0);
- if (nlflag)
- {
- int this_bol, prev_bol, dup;
- insert_1 ("\n", 1, 1, 0);
-
- this_bol = scan_buffer ('\n', Z, 0, -2, 0, 0);
- if (this_bol > BEG)
- {
- prev_bol = scan_buffer ('\n', this_bol, 0, -2, 0, 0);
- dup = message_log_check_duplicate (prev_bol, this_bol);
- if (dup)
- {
- if (oldpoint > prev_bol)
- oldpoint -= min (this_bol, oldpoint) - prev_bol;
- if (oldbegv > prev_bol)
- oldbegv -= min (this_bol, oldbegv) - prev_bol;
- if (oldzv > prev_bol)
- oldzv -= min (this_bol, oldzv) - prev_bol;
- del_range_1 (prev_bol, this_bol, 0);
- if (dup > 1)
- {
- char dupstr[40];
- int duplen;
-
- /* If you change this format, don't forget to also
- change message_log_check_duplicate. */
- sprintf (dupstr, " [%d times]", dup);
- duplen = strlen (dupstr);
- TEMP_SET_PT (Z-1);
- if (oldpoint == Z)
- oldpoint += duplen;
- if (oldzv == Z)
- oldzv += duplen;
- insert_1 (dupstr, duplen, 1, 0);
- }
- }
- }
-
- if (NATNUMP (Vmessage_log_max))
- {
- int pos = scan_buffer ('\n', Z, 0,
- -XFASTINT (Vmessage_log_max) - 1, 0, 0);
- oldpoint -= min (pos, oldpoint) - BEG;
- oldbegv -= min (pos, oldbegv) - BEG;
- oldzv -= min (pos, oldzv) - BEG;
- del_range_1 (BEG, pos, 0);
- }
- }
- BEGV = oldbegv;
- ZV = oldzv;
- TEMP_SET_PT (oldpoint);
- set_buffer_internal (oldbuf);
- windows_or_buffers_changed = old_windows_or_buffers_changed;
- message_log_need_newline = !nlflag;
- }
-}
-
-/* We are at the end of the buffer after just having inserted a newline.
- (Note: We depend on the fact we won't be crossing the gap.)
- Check to see if the most recent message looks a lot like the previous one.
- Return 0 if different, 1 if the new one should just replace it, or a
- value N > 1 if we should also append " [N times]". */
-
-static int
-message_log_check_duplicate (prev_bol, this_bol)
- int prev_bol, this_bol;
-{
- int i;
- int len = Z - 1 - this_bol;
- int seen_dots = 0;
- unsigned char *p1 = BUF_CHAR_ADDRESS (current_buffer, prev_bol);
- unsigned char *p2 = BUF_CHAR_ADDRESS (current_buffer, this_bol);
-
- for (i = 0; i < len; i++)
- {
- if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.'
- && p1[i] != '\n')
- seen_dots = 1;
- if (p1[i] != p2[i])
- return seen_dots;
- }
- p1 += len;
- if (*p1 == '\n')
- return 2;
- if (*p1++ == ' ' && *p1++ == '[')
- {
- int n = 0;
- while (*p1 >= '0' && *p1 <= '9')
- n = n * 10 + *p1++ - '0';
- if (strncmp (p1, " times]\n", 8) == 0)
- return n+1;
- }
- return 0;
-}
-
-/* Display an echo area message M with a specified length of LEN chars.
- The string may include null characters. If M is 0, clear out any
- existing message, and let the minibuffer text show through.
-
- The buffer M must continue to exist until after the echo area
- gets cleared or some other message gets displayed there.
-
- Do not pass text that is stored in a Lisp string.
- Do not pass text in a buffer that was alloca'd. */
-
-void
-message2 (m, len)
- char *m;
- int len;
-{
- /* First flush out any partial line written with print. */
- message_log_maybe_newline ();
- if (m)
- message_dolog (m, len, 1);
- message2_nolog (m, len);
-}
-
-
-/* The non-logging counterpart of message2. */
-
-void
-message2_nolog (m, len)
- char *m;
- int len;
-{
- if (noninteractive)
- {
- if (noninteractive_need_newline)
- putc ('\n', stderr);
- noninteractive_need_newline = 0;
- fwrite (m, len, 1, stderr);
- if (cursor_in_echo_area == 0)
- fprintf (stderr, "\n");
- fflush (stderr);
- }
- /* A null message buffer means that the frame hasn't really been
- initialized yet. Error messages get reported properly by
- cmd_error, so this must be just an informative message; toss it. */
- else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
- {
- Lisp_Object mini_window;
- FRAME_PTR f;
-
- /* Get the frame containing the minibuffer
- that the selected frame is using. */
- mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
- f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
-
- FRAME_SAMPLE_VISIBILITY (f);
- if (FRAME_VISIBLE_P (selected_frame)
- && ! FRAME_VISIBLE_P (f))
- Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
-
- if (m)
- {
- echo_area_glyphs = m;
- echo_area_glyphs_length = len;
-
- if (minibuffer_auto_raise)
- Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
- }
- else
- echo_area_glyphs = previous_echo_glyphs = 0;
-
- do_pending_window_change ();
- echo_area_display ();
- update_frame (f, 1, 1);
- do_pending_window_change ();
- if (frame_up_to_date_hook != 0 && ! gc_in_progress)
- (*frame_up_to_date_hook) (f);
- }
-}
-
-/* Display a null-terminated echo area message M. If M is 0, clear out any
- existing message, and let the minibuffer text show through.
-
- The buffer M must continue to exist until after the echo area
- gets cleared or some other message gets displayed there.
-
- Do not pass text that is stored in a Lisp string.
- Do not pass text in a buffer that was alloca'd. */
-
-void
-message1 (m)
- char *m;
-{
- message2 (m, (m ? strlen (m) : 0));
-}
-
-void
-message1_nolog (m)
- char *m;
-{
- message2_nolog (m, (m ? strlen (m) : 0));
-}
-
-/* Truncate what will be displayed in the echo area
- the next time we display it--but don't redisplay it now. */
-
-void
-truncate_echo_area (len)
- int len;
-{
- /* A null message buffer means that the frame hasn't really been
- initialized yet. Error messages get reported properly by
- cmd_error, so this must be just an informative message; toss it. */
- if (!noninteractive && INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
- echo_area_glyphs_length = len;
-}
-
-/* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
- zero if being used by message. */
-int message_buf_print;
-
-/* Dump an informative message to the minibuf. If M is 0, clear out
- any existing message, and let the minibuffer text show through. */
-
-/* VARARGS 1 */
-void
-message (m, a1, a2, a3)
- char *m;
- EMACS_INT a1, a2, a3;
-{
- if (noninteractive)
- {
- if (m)
- {
- if (noninteractive_need_newline)
- putc ('\n', stderr);
- noninteractive_need_newline = 0;
- fprintf (stderr, m, a1, a2, a3);
- if (cursor_in_echo_area == 0)
- fprintf (stderr, "\n");
- fflush (stderr);
- }
- }
- else if (INTERACTIVE)
- {
- /* The frame whose minibuffer we're going to display the message on.
- It may be larger than the selected frame, so we need
- to use its buffer, not the selected frame's buffer. */
- Lisp_Object mini_window;
- FRAME_PTR f;
-
- /* Get the frame containing the minibuffer
- that the selected frame is using. */
- mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
- f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
-
- /* A null message buffer means that the frame hasn't really been
- initialized yet. Error messages get reported properly by
- cmd_error, so this must be just an informative message; toss it. */
- if (FRAME_MESSAGE_BUF (f))
- {
- if (m)
- {
- int len;
-#ifdef NO_ARG_ARRAY
- EMACS_INT a[3];
- a[0] = a1;
- a[1] = a2;
- a[2] = a3;
-
- len = doprnt (FRAME_MESSAGE_BUF (f),
- (int) FRAME_WIDTH (f), m, (char *)0, 3, a);
-#else
- len = doprnt (FRAME_MESSAGE_BUF (f),
- (int) FRAME_WIDTH (f), m, (char *)0, 3, &a1);
-#endif /* NO_ARG_ARRAY */
-
- message2 (FRAME_MESSAGE_BUF (f), len);
- }
- else
- message1 (0);
-
- /* Print should start at the beginning of the message
- buffer next time. */
- message_buf_print = 0;
- }
- }
-}
-
-/* The non-logging version of message. */
-void
-message_nolog (m, a1, a2, a3)
- char *m;
- EMACS_INT a1, a2, a3;
-{
- Lisp_Object old_log_max;
- old_log_max = Vmessage_log_max;
- Vmessage_log_max = Qnil;
- message (m, a1, a2, a3);
- Vmessage_log_max = old_log_max;
-}
-
-void
-update_echo_area ()
-{
- message2 (echo_area_glyphs, echo_area_glyphs_length);
-}
-
-static void
-echo_area_display ()
-{
- register int vpos;
- FRAME_PTR f;
- Lisp_Object mini_window;
-
- /* Choose the minibuffer window for this display.
- It is the minibuffer window used by the selected frame. */
- mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
- /* This is the frame that window is in. */
- f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
-
- if (! FRAME_VISIBLE_P (f))
- return;
-
- if (frame_garbaged)
- {
- redraw_garbaged_frames ();
- frame_garbaged = 0;
- }
-
- if (echo_area_glyphs || minibuf_level == 0)
- {
- int i;
-
- echo_area_window = mini_window;
-
- vpos = XFASTINT (XWINDOW (mini_window)->top);
- get_display_line (f, vpos, 0);
-
- /* Make sure the columns that overlap a left-hand scroll bar
- are always clear. */
- for (i = 0; i < FRAME_LEFT_SCROLL_BAR_WIDTH (f); i++)
- f->desired_glyphs->glyphs[vpos][i] = SPACEGLYPH;
-
- display_string (XWINDOW (mini_window), vpos,
- echo_area_glyphs ? echo_area_glyphs : "",
- echo_area_glyphs ? echo_area_glyphs_length : -1,
- FRAME_LEFT_SCROLL_BAR_WIDTH (f),
- 0, 0, 0, FRAME_WIDTH (f));
-
-#if 0 /* This just gets in the way. update_frame does the job. */
- /* If desired cursor location is on this line, put it at end of text */
- if (cursor_in_echo_area)
- FRAME_CURSOR_Y (f) = vpos;
- if (FRAME_CURSOR_Y (f) == vpos)
- FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos];
-#endif
-
- /* Fill the rest of the minibuffer window with blank lines. */
- {
- int i;
-
- for (i = vpos + 1;
- i < vpos + XFASTINT (XWINDOW (mini_window)->height); i++)
- {
- get_display_line (f, i, 0);
- display_string (XWINDOW (mini_window), vpos,
- "", 0,
- FRAME_LEFT_SCROLL_BAR_WIDTH (f),
- 0, 0, 0, FRAME_WIDTH (f));
- }
- }
- }
- else if (!EQ (mini_window, selected_window))
- windows_or_buffers_changed++;
-
- if (EQ (mini_window, selected_window))
- this_line_bufpos = 0;
-
- previous_echo_glyphs = echo_area_glyphs;
-}
-
-/* Update frame titles. */
-
-#ifdef HAVE_WINDOW_SYSTEM
-static char frame_title_buf[512];
-static char *frame_title_ptr;
-
-static int
-store_frame_title (str, mincol, maxcol)
- char *str;
- int mincol, maxcol;
-{
- char *limit;
- if (maxcol < 0 || maxcol >= sizeof(frame_title_buf))
- maxcol = sizeof (frame_title_buf);
- limit = &frame_title_buf[maxcol];
- while (*str != '\0' && frame_title_ptr < limit)
- *frame_title_ptr++ = *str++;
- while (frame_title_ptr < &frame_title_buf[mincol])
- *frame_title_ptr++ = ' ';
- return frame_title_ptr - frame_title_buf;
-}
-
-static void
-x_consider_frame_title (frame)
- Lisp_Object frame;
-{
- Lisp_Object fmt;
- struct buffer *obuf;
- int len;
- FRAME_PTR f = XFRAME (frame);
-
- if (!(FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name))
- return;
-
- /* Do we have more than one visible frame on this X display? */
- {
- Lisp_Object tail;
-
- for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- FRAME_PTR tf = XFRAME (XCONS (tail)->car);
-
- if (tf != f && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
- && !FRAME_MINIBUF_ONLY_P (tf)
- && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
- break;
- }
-
- multiple_frames = CONSP (tail);
- }
-
- obuf = current_buffer;
- Fset_buffer (XWINDOW (f->selected_window)->buffer);
- fmt = (FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format);
- frame_title_ptr = frame_title_buf;
- len = display_mode_element (XWINDOW (f->selected_window), 0, 0, 0,
- 0, sizeof (frame_title_buf), fmt);
- frame_title_ptr = 0;
- set_buffer_internal (obuf);
- /* Set the name only if it's changed. This avoids consing
- in the common case where it hasn't. (If it turns out that we've
- already wasted too much time by walking through the list with
- display_mode_element, then we might need to optimize at a higher
- level than this.) */
- if (! STRINGP (f->name) || XSTRING (f->name)->size != len
- || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
- x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
-}
-#else
-#define frame_title_ptr ((char *)0)
-#define store_frame_title(str, mincol, maxcol) 0
-#endif
-
-/* Prepare for redisplay by updating menu-bar item lists when appropriate.
- This can call eval. */
-
-void
-prepare_menu_bars ()
-{
- register struct window *w = XWINDOW (selected_window);
- int all_windows;
- struct gcpro gcpro1, gcpro2;
-
- all_windows = (update_mode_lines || buffer_shared > 1
- || windows_or_buffers_changed);
-
- /* Update all frame titles based on their buffer names, etc.
- We do this before the menu bars so that the buffer-menu
- will show the up-to-date frame titles.
-
- This used to be done after the menu bars, for a reason that
- was stated as follows but which I do not understand:
- "We do this after the menu bars so that the frame will first
- create its menu bar using the name `emacs' if no other name
- has yet been specified."
- I think that is no longer a concern. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (windows_or_buffers_changed || update_mode_lines)
- {
- Lisp_Object tail, frame;
-
- FOR_EACH_FRAME (tail, frame)
- if (FRAME_VISIBLE_P (XFRAME (frame))
- || FRAME_ICONIFIED_P (XFRAME (frame)))
- x_consider_frame_title (frame);
- }
-#endif
-
- /* Update the menu bar item lists, if appropriate.
- This has to be done before any actual redisplay
- or generation of display lines. */
- if (all_windows)
- {
- Lisp_Object tail, frame;
- int count = specpdl_ptr - specpdl;
-
- record_unwind_protect (Fstore_match_data, Fmatch_data (Qnil, Qnil));
-
- FOR_EACH_FRAME (tail, frame)
- {
- /* If a window on this frame changed size,
- report that to the user and clear the size-change flag. */
- if (FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)))
- {
- Lisp_Object functions;
- /* Clear flag first in case we get error below. */
- FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)) = 0;
- functions = Vwindow_size_change_functions;
- GCPRO2 (tail, functions);
- while (CONSP (functions))
- {
- call1 (XCONS (functions)->car, frame);
- functions = XCONS (functions)->cdr;
- }
- UNGCPRO;
- }
- GCPRO1 (tail);
- update_menu_bar (XFRAME (frame), 0);
- UNGCPRO;
- }
-
- unbind_to (count, Qnil);
- }
- else
- update_menu_bar (selected_frame, 1);
-
- /* Motif needs this. See comment in xmenu.c.
- Turn it off when pending_menu_activation is not defined. */
-#ifdef USE_X_TOOLKIT
- pending_menu_activation = 0;
-#endif
-}
-
-/* Do a frame 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.
-
- Do not call eval from within this function.
- Calls to eval after the call to echo_area_display would confuse
- the display_line mechanism and would cause a crash.
- Calls to eval before that point will work most of the time,
- but can still lose, because this function
- can be called from signal handlers; with alarms set up;
- or with synchronous processes running.
-
- See Fcall_process; if you called it from here, it could be
- entered recursively. */
-
-static int do_verify_charstarts;
-
-/* Counter is used to clear the face cache
- no more than once ever 1000 redisplays. */
-static int clear_face_cache_count;
-
-/* Record the previous terminal frame we displayed. */
-static FRAME_PTR previous_terminal_frame;
-
-void
-redisplay ()
-{
- redisplay_internal (0);
-}
-
-/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay
- is not in response to any user action; therefore, we should
- preserve the echo area. (Actually, our caller does that job.)
- Perhaps in the future avoid recentering windows
- if it is not necessary; currently that causes some problems. */
-
-static void
-redisplay_internal (preserve_echo_area)
- int preserve_echo_area;
-{
- register struct window *w = XWINDOW (selected_window);
- register int pause;
- int must_finish = 0;
- int all_windows;
- register int tlbufpos, tlendpos;
- struct position pos;
-
- if (noninteractive)
- return;
-
-#ifdef USE_X_TOOLKIT
- if (popup_activated ())
- return;
-#endif
-
- if (! FRAME_WINDOW_P (selected_frame)
- && previous_terminal_frame != selected_frame)
- {
- /* Since frames on an ASCII terminal share the same display area,
- displaying a different frame means redisplay the whole thing. */
- windows_or_buffers_changed++;
- SET_FRAME_GARBAGED (selected_frame);
- XSETFRAME (Vterminal_frame, selected_frame);
- }
- previous_terminal_frame = selected_frame;
-
- /* Set the visible flags for all frames.
- Do this before checking for resized or garbaged frames; they want
- to know if their frames are visible.
- See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
- {
- Lisp_Object tail, frame;
-
- FOR_EACH_FRAME (tail, frame)
- {
- FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
-
- /* Clear out all the display lines in which we will generate the
- glyphs to display. */
- init_desired_glyphs (XFRAME (frame));
- }
- }
-
- /* Notice any pending interrupt request to change frame size. */
- do_pending_window_change ();
-
- if (frame_garbaged)
- {
- redraw_garbaged_frames ();
- frame_garbaged = 0;
- }
-
- prepare_menu_bars ();
-
- if (windows_or_buffers_changed)
- update_mode_lines++;
-
- /* Detect case that we need to write or remove a star in the mode line. */
- if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
- {
- w->update_mode_line = Qt;
- if (buffer_shared > 1)
- update_mode_lines++;
- }
-
- /* If %c is in use, update it if needed. */
- if (!NILP (w->column_number_displayed)
- /* This alternative quickly identifies a common case
- where no change is needed. */
- && !(PT == XFASTINT (w->last_point)
- && XFASTINT (w->last_modified) >= MODIFF
- && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
- && XFASTINT (w->column_number_displayed) != current_column ())
- w->update_mode_line = Qt;
-
- FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
-
- 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 (! EQ (Voverlay_arrow_position, last_arrow_position)
- || ! EQ (Voverlay_arrow_string, last_arrow_string))
- all_windows = 1;
-
- /* Normally the message* functions will have already displayed and
- updated the echo area, but the frame may have been trashed, or
- the update may have been preempted, so display the echo area
- again here. */
- if (echo_area_glyphs || previous_echo_glyphs)
- {
- echo_area_display ();
- must_finish = 1;
- }
-
- /* If showing region, and mark has changed, must redisplay whole window. */
- if (((!NILP (Vtransient_mark_mode)
- && !NILP (XBUFFER (w->buffer)->mark_active))
- != !NILP (w->region_showing))
- || (!NILP (w->region_showing)
- && !EQ (w->region_showing,
- Fmarker_position (XBUFFER (w->buffer)->mark))))
- this_line_bufpos = -1;
-
- tlbufpos = this_line_bufpos;
- tlendpos = this_line_endpos;
- if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line)
- && !current_buffer->clip_changed
- && FRAME_VISIBLE_P (XFRAME (w->frame))
- /* Make sure recorded data applies to current buffer, etc */
- && this_line_buffer == current_buffer
- && current_buffer == XBUFFER (w->buffer)
- && NILP (w->force_start)
- /* Point must be on the line that we have info recorded about */
- && PT >= tlbufpos
- && PT <= Z - tlendpos
- /* All text outside that line, including its final newline,
- must be unchanged */
- && ((XFASTINT (w->last_modified) >= MODIFF
- && (XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF))
- || (beg_unchanged >= tlbufpos - 1
- && GPT >= tlbufpos
- /* If selective display, can't optimize
- if the changes start at the beginning of the line. */
- && ((INTEGERP (current_buffer->selective_display)
- && 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
- || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
- || MINI_WINDOW_P (w))
- {
- cursor_vpos = -1;
- overlay_arrow_seen = 0;
- zv_strings_seen = 0;
- display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
- pos_tab_offset (w, tlbufpos), 0);
- /* If line contains point, is not continued,
- and ends at same distance from eob as before, we win */
- if (cursor_vpos >= 0 && this_line_bufpos
- && this_line_endpos == tlendpos)
- {
- /* If this is not the window's last line,
- we must adjust the charstarts of the lines below. */
- if (this_line_vpos + 1
- < XFASTINT (w->top) + window_internal_height (w))
- {
- int left = WINDOW_LEFT_MARGIN (w);
- int *charstart_next_line
- = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[this_line_vpos + 1];
- int adjust;
-
- if (Z - tlendpos == ZV)
- /* This line ends at end of (accessible part of) buffer.
- There is no newline to count. */
- adjust = Z - tlendpos - charstart_next_line[left];
- else
- /* This line ends in a newline.
- Must take account of the newline and the rest of the
- text that follows. */
- adjust = Z - tlendpos + 1 - charstart_next_line[left];
-
- adjust_window_charstarts (w, this_line_vpos, adjust);
- }
-
- if (!WINDOW_FULL_WIDTH_P (w))
- preserve_other_columns (w);
- goto update;
- }
- else
- goto cancel;
- }
- else if (PT == XFASTINT (w->last_point)
- /* Make sure the cursor was last displayed
- in this window. Otherwise we have to reposition it. */
- && XINT (w->top) <= FRAME_CURSOR_Y (selected_frame)
- && (XINT (w->top) + XINT (w->height)
- > FRAME_CURSOR_Y (selected_frame)))
- {
- if (!must_finish)
- {
- do_pending_window_change ();
- return;
- }
- goto update;
- }
- /* If highlighting the region, or if the cursor is in the echo area,
- then we can't just move the cursor. */
- else if (! (!NILP (Vtransient_mark_mode)
- && !NILP (current_buffer->mark_active))
- && w == XWINDOW (current_buffer->last_selected_window)
- && NILP (w->region_showing)
- && !cursor_in_echo_area)
- {
- pos = *compute_motion (tlbufpos, 0,
- XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
- 0,
- PT, 2, - (1 << (BITS_PER_SHORT - 1)),
- window_internal_width (w) - 1,
- XINT (w->hscroll),
- pos_tab_offset (w, tlbufpos), w);
- if (pos.vpos < 1)
- {
- int width = window_internal_width (w) - 1;
- FRAME_CURSOR_X (selected_frame)
- = WINDOW_LEFT_MARGIN (w) + minmax (0, pos.hpos, width);
- FRAME_CURSOR_Y (selected_frame) = this_line_vpos;
- goto update;
- }
- else
- goto cancel;
- }
- cancel:
- /* Text changed drastically or point moved off of line */
- cancel_line (this_line_vpos, selected_frame);
- }
-
- this_line_bufpos = 0;
- all_windows |= buffer_shared > 1;
-
- clear_face_cache_count++;
-
- if (all_windows)
- {
- Lisp_Object tail, frame;
-
-#ifdef HAVE_FACES
- /* Clear the face cache, only when we do a full redisplay
- and not too often either. */
- if (clear_face_cache_count > 1000)
- {
- clear_face_cache ();
- clear_face_cache_count = 0;
- }
-#endif
-
- /* Recompute # windows showing selected buffer.
- This will be incremented each time such a window is displayed. */
- buffer_shared = 0;
-
- FOR_EACH_FRAME (tail, frame)
- {
- FRAME_PTR f = XFRAME (frame);
- if (FRAME_WINDOW_P (f) || f == selected_frame)
- {
-
- /* Mark all the scroll bars to be removed; we'll redeem the ones
- we want when we redisplay their windows. */
- if (condemn_scroll_bars_hook)
- (*condemn_scroll_bars_hook) (f);
-
- if (FRAME_VISIBLE_P (f))
- redisplay_windows (FRAME_ROOT_WINDOW (f), preserve_echo_area);
-
- /* Any scroll bars which redisplay_windows should have nuked
- should now go away. */
- if (judge_scroll_bars_hook)
- (*judge_scroll_bars_hook) (f);
- }
- }
- }
- else if (FRAME_VISIBLE_P (selected_frame))
- {
- redisplay_window (selected_window, 1, preserve_echo_area);
- if (!WINDOW_FULL_WIDTH_P (w))
- 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 ();
-
- if (all_windows)
- {
- Lisp_Object tail;
-
- pause = 0;
-
- for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- FRAME_PTR f;
-
- if (!FRAMEP (XCONS (tail)->car))
- continue;
-
- f = XFRAME (XCONS (tail)->car);
-
- if ((FRAME_WINDOW_P (f) || f == selected_frame)
- && FRAME_VISIBLE_P (f))
- {
- pause |= update_frame (f, 0, 0);
- if (!pause)
- {
- mark_window_display_accurate (f->root_window, 1);
- if (frame_up_to_date_hook != 0)
- (*frame_up_to_date_hook) (f);
- }
- }
- }
- }
- else
- {
- if (FRAME_VISIBLE_P (selected_frame))
- pause = update_frame (selected_frame, 0, 0);
- else
- pause = 0;
-
- /* We may have called echo_area_display at the top of this
- function. If the echo area is on another frame, that may
- have put text on a frame other than the selected one, so the
- above call to update_frame would not have caught it. Catch
- it here. */
- {
- Lisp_Object mini_window;
- FRAME_PTR mini_frame;
-
- mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
- mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
-
- if (mini_frame != selected_frame && FRAME_WINDOW_P (mini_frame))
- pause |= update_frame (mini_frame, 0, 0);
- }
- }
-
- /* If frame 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 (!NILP (last_arrow_position))
- {
- last_arrow_position = Qt;
- last_arrow_string = Qt;
- }
- /* If we pause after scrolling, some lines in current_frame
- may be null, so preserve_other_columns won't be able to
- preserve all the vertical-bar separators. So, avoid using it
- in that case. */
- if (!WINDOW_FULL_WIDTH_P (w))
- update_mode_lines = 1;
- }
-
- /* Now text on frame agrees with windows, so
- put info into the windows for partial redisplay to follow */
-
- if (!pause)
- {
- register struct buffer *b = XBUFFER (w->buffer);
-
- blank_end_of_window = 0;
- unchanged_modified = BUF_MODIFF (b);
- overlay_unchanged_modified = BUF_OVERLAY_MODIFF (b);
- beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
- end_unchanged = BUF_Z (b) - BUF_GPT (b);
-
- XSETFASTINT (w->last_point, BUF_PT (b));
- XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (selected_frame));
- XSETFASTINT (w->last_point_y, FRAME_CURSOR_Y (selected_frame));
-
- if (all_windows)
- mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
- else
- {
- b->clip_changed = 0;
- w->update_mode_line = Qnil;
- XSETFASTINT (w->last_modified, BUF_MODIFF (b));
- XSETFASTINT (w->last_overlay_modified, BUF_OVERLAY_MODIFF (b));
- w->last_had_star
- = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
- ? Qt : Qnil);
- w->window_end_valid = w->buffer;
- last_arrow_position = Voverlay_arrow_position;
- last_arrow_string = Voverlay_arrow_string;
- if (do_verify_charstarts)
- verify_charstarts (w);
- if (frame_up_to_date_hook != 0)
- (*frame_up_to_date_hook) (selected_frame);
- }
- 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 ();
-
- /* Change frame size now if a change is pending. */
- do_pending_window_change ();
-
- /* If we just did a pending size change, redisplay again
- for the new size. */
- if (windows_or_buffers_changed && !pause)
- redisplay ();
-}
-
-/* Redisplay, but leave alone any recent echo area message
- unless another message has been requested in its place.
-
- This is useful in situations where you need to redisplay but no
- user action has occurred, making it inappropriate for the message
- area to be cleared. See tracking_off and
- wait_reading_process_input for examples of these situations. */
-
-redisplay_preserve_echo_area ()
-{
- if (echo_area_glyphs == 0 && previous_echo_glyphs != 0)
- {
- echo_area_glyphs = previous_echo_glyphs;
- redisplay_internal (1);
- echo_area_glyphs = 0;
- }
- else
- redisplay_internal (1);
-}
-
-void
-mark_window_display_accurate (window, flag)
- Lisp_Object window;
- int flag;
-{
- register struct window *w;
-
- for (;!NILP (window); window = w->next)
- {
- if (!WINDOWP (window)) abort ();
- w = XWINDOW (window);
-
- if (!NILP (w->buffer))
- {
- XSETFASTINT (w->last_modified,
- !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer)));
- XSETFASTINT (w->last_overlay_modified,
- !flag ? 0 : BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)));
- w->last_had_star
- = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
- ? Qt : Qnil);
-
- /* Record if we are showing a region, so can make sure to
- update it fully at next redisplay. */
- w->region_showing = (!NILP (Vtransient_mark_mode)
- && w == XWINDOW (current_buffer->last_selected_window)
- && !NILP (XBUFFER (w->buffer)->mark_active)
- ? Fmarker_position (XBUFFER (w->buffer)->mark)
- : Qnil);
- }
-
- w->window_end_valid = w->buffer;
- w->update_mode_line = Qnil;
- if (!NILP (w->buffer) && flag)
- XBUFFER (w->buffer)->clip_changed = 0;
-
- if (!NILP (w->vchild))
- mark_window_display_accurate (w->vchild, flag);
- if (!NILP (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;
- }
-}
-
-/* Update the menu bar item list for frame F.
- This has to be done before we start to fill in any display lines,
- because it can call eval.
-
- If SAVE_MATCH_DATA is 1, we must save and restore it here. */
-
-static void
-update_menu_bar (f, save_match_data)
- FRAME_PTR f;
- int save_match_data;
-{
- struct buffer *old = current_buffer;
- Lisp_Object window;
- register struct window *w;
-
- window = FRAME_SELECTED_WINDOW (f);
- w = XWINDOW (window);
-
- if (update_mode_lines)
- w->update_mode_line = Qt;
-
- if (FRAME_WINDOW_P (f)
- ?
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
- FRAME_EXTERNAL_MENU_BAR (f)
-#else
- FRAME_MENU_BAR_LINES (f) > 0
-#endif
- : FRAME_MENU_BAR_LINES (f) > 0)
- {
- /* If the user has switched buffers or windows, we need to
- recompute to reflect the new bindings. But we'll
- recompute when update_mode_lines is set too; that means
- that people can use force-mode-line-update to request
- that the menu bar be recomputed. The adverse effect on
- the rest of the redisplay algorithm is about the same as
- windows_or_buffers_changed anyway. */
- if (windows_or_buffers_changed
- || !NILP (w->update_mode_line)
- || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
- < BUF_MODIFF (XBUFFER (w->buffer)))
- != !NILP (w->last_had_star))
- || ((!NILP (Vtransient_mark_mode)
- && !NILP (XBUFFER (w->buffer)->mark_active))
- != !NILP (w->region_showing)))
- {
- struct buffer *prev = current_buffer;
- int count = specpdl_ptr - specpdl;
-
- set_buffer_internal_1 (XBUFFER (w->buffer));
- if (save_match_data)
- record_unwind_protect (Fstore_match_data, Fmatch_data (Qnil, Qnil));
- if (NILP (Voverriding_local_map_menu_flag))
- {
- specbind (Qoverriding_terminal_local_map, Qnil);
- specbind (Qoverriding_local_map, Qnil);
- }
-
- /* Run the Lucid hook. */
- call1 (Vrun_hooks, Qactivate_menubar_hook);
- /* If it has changed current-menubar from previous value,
- really recompute the menubar from the value. */
- if (! NILP (Vlucid_menu_bar_dirty_flag))
- call0 (Qrecompute_lucid_menubar);
- safe_run_hooks (Qmenu_bar_update_hook);
- FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
- /* Redisplay the menu bar in case we changed it. */
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
- if (FRAME_WINDOW_P (f))
- set_frame_menubar (f, 0, 0);
- else
- /* On a terminal screen, the menu bar is an ordinary screen
- line, and this makes it get updated. */
- w->update_mode_line = Qt;
-#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
- /* In the non-toolkit version, the menu bar is an ordinary screen
- line, and this makes it get updated. */
- w->update_mode_line = Qt;
-#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
-
- unbind_to (count, Qnil);
- set_buffer_internal_1 (prev);
- }
- }
-}
-
-int do_id = 1;
-
-/* Redisplay WINDOW and its subwindows and siblings. */
-
-static void
-redisplay_windows (window, preserve_echo_area)
- Lisp_Object window;
- int preserve_echo_area;
-{
- for (; !NILP (window); window = XWINDOW (window)->next)
- redisplay_window (window, 0, preserve_echo_area);
-}
-
-/* Redisplay window WINDOW and its subwindows. */
-
-static void
-redisplay_window (window, just_this_one, preserve_echo_area)
- Lisp_Object window;
- int just_this_one, preserve_echo_area;
-{
- register struct window *w = XWINDOW (window);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
- int height;
- register int lpoint = PT;
- struct buffer *old = current_buffer;
- register int width = window_internal_width (w) - 1;
- register int startp;
- register int hscroll = XINT (w->hscroll);
- struct position pos;
- int opoint = PT;
- int tem;
- int update_mode_line;
- struct Lisp_Char_Table *dp = window_display_table (w);
-
- if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
-
- /* If this is a combination window, do its children; that's all. */
-
- if (!NILP (w->vchild))
- {
- redisplay_windows (w->vchild, preserve_echo_area);
- return;
- }
- if (!NILP (w->hchild))
- {
- redisplay_windows (w->hchild, preserve_echo_area);
- return;
- }
- if (NILP (w->buffer))
- abort ();
-
- height = window_internal_height (w);
- update_mode_line = (!NILP (w->update_mode_line) || update_mode_lines);
- if (XBUFFER (w->buffer)->clip_changed)
- update_mode_line = 1;
-
- if (MINI_WINDOW_P (w))
- {
- if (w == XWINDOW (echo_area_window) && echo_area_glyphs)
- /* We've already displayed the echo area glyphs in this window. */
- goto finish_scroll_bars;
- else if (w != XWINDOW (minibuf_window))
- {
- /* This is a minibuffer, but it's not the currently active one,
- so clear it. */
- int vpos = XFASTINT (w->top);
- int i;
-
- for (i = 0; i < height; i++)
- {
- get_display_line (f, vpos + i, 0);
- display_string (w, vpos + i, "", 0,
- FRAME_LEFT_SCROLL_BAR_WIDTH (f),
- 0, 1, 0, width);
- }
-
- goto finish_scroll_bars;
- }
- }
-
- /* Otherwise set up data on this window; select its buffer and point value */
-
- if (update_mode_line)
- set_buffer_internal_1 (XBUFFER (w->buffer));
- else
- set_buffer_temp (XBUFFER (w->buffer));
-
- opoint = PT;
-
- /* If %c is in mode line, update it if needed. */
- if (!NILP (w->column_number_displayed)
- /* This alternative quickly identifies a common case
- where no change is needed. */
- && !(PT == XFASTINT (w->last_point)
- && XFASTINT (w->last_modified) >= MODIFF
- && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
- && XFASTINT (w->column_number_displayed) != current_column ())
- update_mode_line = 1;
-
- /* Count number of windows showing the selected buffer.
- An indirect buffer counts as its base buffer. */
-
- if (!just_this_one)
- {
- struct buffer *current_base, *window_base;
- current_base = current_buffer;
- window_base = XBUFFER (XWINDOW (selected_window)->buffer);
- if (current_base->base_buffer)
- current_base = current_base->base_buffer;
- if (window_base->base_buffer)
- window_base = window_base->base_buffer;
- if (current_base == window_base)
- buffer_shared++;
- }
-
- /* POINT refers normally to the selected window.
- For any other window, set up appropriate value. */
-
- if (!EQ (window, selected_window))
- {
- int new_pt = marker_position (w->pointm);
- if (new_pt < BEGV)
- {
- new_pt = BEGV;
- Fset_marker (w->pointm, make_number (new_pt), Qnil);
- }
- else if (new_pt > (ZV - 1))
- {
- new_pt = ZV;
- Fset_marker (w->pointm, make_number (new_pt), Qnil);
- }
- /* We don't use SET_PT so that the point-motion hooks don't run. */
- BUF_PT (current_buffer) = new_pt;
- }
-
- /* If any of the character widths specified in the display table
- have changed, invalidate the width run cache. It's true that this
- may be a bit late to catch such changes, but the rest of
- redisplay goes (non-fatally) haywire when the display table is
- changed, so why should we worry about doing any better? */
- if (current_buffer->width_run_cache)
- {
- struct Lisp_Char_Table *disptab = buffer_display_table ();
-
- if (! disptab_matches_widthtab (disptab,
- XVECTOR (current_buffer->width_table)))
- {
- invalidate_region_cache (current_buffer,
- current_buffer->width_run_cache,
- BEG, Z);
- recompute_width_table (current_buffer, disptab);
- }
- }
-
- /* If window-start is screwed up, choose a new one. */
- if (XMARKER (w->start)->buffer != current_buffer)
- goto recenter;
-
- startp = marker_position (w->start);
-
- /* If someone specified a new starting point but did not insist,
- check whether it can be used. */
- if (!NILP (w->optional_new_start))
- {
- w->optional_new_start = Qnil;
- /* Check whether this start pos is usable given where point is. */
-
- pos = *compute_motion (startp, 0,
- (((EQ (window, minibuf_window)
- && startp == BEG)
- ? minibuf_prompt_width : 0)
- + (hscroll ? 1 - hscroll : 0)),
- 0,
- PT, height, 0,
- width, hscroll, pos_tab_offset (w, startp), w);
- /* If PT does fit on the screen, we will use this start pos,
- so do so by setting force_start. */
- if (pos.bufpos == PT)
- w->force_start = Qt;
- }
-
- /* Handle case where place to start displaying has been specified,
- unless the specified location is outside the accessible range. */
- if (!NILP (w->force_start))
- {
- w->force_start = Qnil;
- /* Forget any recorded base line for line number display. */
- w->base_line_number = Qnil;
- /* Redisplay the mode line. Select the buffer properly for that.
- Also, run the hook window-scroll-functions
- because we have scrolled. */
- /* Note, we do this after clearing force_start because
- if there's an error, it is better to forget about force_start
- than to get into an infinite loop calling the hook functions
- and having them get more errors. */
- if (!update_mode_line
- || ! NILP (Vwindow_scroll_functions))
- {
- Lisp_Object temp[3];
-
- set_buffer_temp (old);
- set_buffer_internal_1 (XBUFFER (w->buffer));
- update_mode_line = 1;
- w->update_mode_line = Qt;
- if (! NILP (Vwindow_scroll_functions))
- {
- run_hook_with_args_2 (Qwindow_scroll_functions, window,
- make_number (startp));
- startp = marker_position (w->start);
- }
- }
- XSETFASTINT (w->last_modified, 0);
- XSETFASTINT (w->last_overlay_modified, 0);
- if (startp < BEGV) startp = BEGV;
- if (startp > ZV) startp = ZV;
- try_window (window, startp);
- if (cursor_vpos < 0)
- {
- /* If point does not appear, move point so it does appear */
- pos = *compute_motion (startp, 0,
- (((EQ (window, minibuf_window)
- && startp == BEG)
- ? minibuf_prompt_width : 0)
- + (hscroll ? 1 - hscroll : 0)),
- 0,
- ZV, height / 2,
- - (1 << (BITS_PER_SHORT - 1)),
- width, hscroll, pos_tab_offset (w, startp), w);
- BUF_PT (current_buffer) = pos.bufpos;
- if (w != XWINDOW (selected_window))
- Fset_marker (w->pointm, make_number (PT), Qnil);
- else
- {
- if (current_buffer == old)
- lpoint = PT;
- FRAME_CURSOR_X (f) = (WINDOW_LEFT_MARGIN (w)
- + minmax (0, pos.hpos, width));
- FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
- }
- /* If we are highlighting the region,
- then we just changed the region, so redisplay to show it. */
- if (!NILP (Vtransient_mark_mode)
- && !NILP (current_buffer->mark_active))
- {
- cancel_my_columns (XWINDOW (window));
- try_window (window, startp);
- }
- }
- goto done;
- }
-
- /* Handle case where text has not changed, only point,
- and it has not moved off the frame. */
-
- /* 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
- && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF
- && PT >= startp && !current_buffer->clip_changed
- && (just_this_one || WINDOW_FULL_WIDTH_P (w))
- /* If force-mode-line-update was called, really redisplay;
- that's how redisplay is forced after e.g. changing
- buffer-invisibility-spec. */
- && NILP (w->update_mode_line)
- /* Can't use this case if highlighting a region. */
- && !(!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
- && NILP (w->region_showing)
- /* If end pos is out of date, scroll bar and percentage will be wrong */
- && INTEGERP (w->window_end_vpos)
- && XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
- && !EQ (window, minibuf_window))
- {
- int this_scroll_margin = scroll_margin;
-
- pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0,
- PT, height, 0, width, hscroll,
- pos_tab_offset (w, startp), w);
-
- /* Don't use a scroll margin that is negative or too large. */
- if (this_scroll_margin < 0)
- this_scroll_margin = 0;
-
- if (XINT (w->height) < 4 * scroll_margin)
- this_scroll_margin = XINT (w->height) / 4;
-
- /* If point fits on the screen, and not within the scroll margin,
- we are ok. */
- if (pos.vpos < height - this_scroll_margin
- && (pos.vpos >= this_scroll_margin || startp == BEGV))
- {
- /* Ok, point is still on frame */
- if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
- {
- /* These variables are supposed to be origin 1 */
- FRAME_CURSOR_X (f) = (WINDOW_LEFT_MARGIN (w)
- + minmax (0, pos.hpos, width));
- FRAME_CURSOR_Y (f) = 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 DesiredFrame yet, and then the other window is
- redisplayed, making likes that are empty in this window's columns.
- if (WINDOW_FULL_WIDTH_P (w))
- 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 (!NILP (w->start_at_line_beg)
- && !(startp <= BEGV
- || FETCH_CHAR (startp - 1) == '\n'))
- {
- goto recenter;
- }
- else if (just_this_one && !MINI_WINDOW_P (w)
- && PT >= startp
- && XFASTINT (w->last_modified)
- /* or else vmotion on first line won't work. */
- && ! NILP (w->start_at_line_beg)
- && ! EQ (w->window_end_valid, Qnil)
- && do_id && !current_buffer->clip_changed
- && !blank_end_of_window
- && WINDOW_FULL_WIDTH_P (w)
- /* Can't use this case if highlighting a region. */
- && !(!NILP (Vtransient_mark_mode)
- && !NILP (current_buffer->mark_active))
- /* Don't use try_window_id if newline
- doesn't display as the end of a line. */
- && !(dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, '\n')))
- && NILP (w->region_showing)
- && EQ (last_arrow_position, Voverlay_arrow_position)
- && EQ (last_arrow_string, Voverlay_arrow_string)
- && (tem = try_window_id (FRAME_SELECTED_WINDOW (f)))
- && 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
- && (startp < ZV
- /* Avoid starting at end of buffer. */
-#if 0 /* This change causes trouble for M-! finger & RET.
- It will have to be considered later. */
- || ! EQ (window, selected_window)
- /* Don't do the recentering if redisplay
- is not for no user action. */
- || preserve_echo_area
-#endif
- || startp == BEGV
- || (XFASTINT (w->last_modified) >= MODIFF
- && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
- {
- /* Try to redisplay starting at same place as before */
- /* If point has not moved off frame, accept the results */
- try_window (window, startp);
- if (cursor_vpos >= 0)
- {
- if (!just_this_one || current_buffer->clip_changed
- || beg_unchanged < startp)
- /* Forget any recorded base line for line number display. */
- w->base_line_number = Qnil;
- goto done;
- }
- else
- cancel_my_columns (w);
- }
-
- XSETFASTINT (w->last_modified, 0);
- XSETFASTINT (w->last_overlay_modified, 0);
- /* Redisplay the mode line. Select the buffer properly for that. */
- if (!update_mode_line)
- {
- set_buffer_temp (old);
- set_buffer_internal_1 (XBUFFER (w->buffer));
- update_mode_line = 1;
- w->update_mode_line = Qt;
- }
-
- /* Try to scroll by specified few lines */
-
- if (scroll_conservatively && !current_buffer->clip_changed
- && startp >= BEGV && startp <= ZV)
- {
- int this_scroll_margin = scroll_margin;
-
- /* Don't use a scroll margin that is negative or too large. */
- if (this_scroll_margin < 0)
- this_scroll_margin = 0;
-
- if (XINT (w->height) < 4 * scroll_margin)
- this_scroll_margin = XINT (w->height) / 4;
-
- if (PT >= Z - XFASTINT (w->window_end_pos))
- {
- struct position pos;
- pos = *compute_motion (Z - XFASTINT (w->window_end_pos), 0, 0, 0,
- PT, XFASTINT (w->height), 0,
- XFASTINT (w->width), XFASTINT (w->hscroll),
- pos_tab_offset (w, startp), w);
- if (pos.vpos > scroll_conservatively)
- goto scroll_fail_1;
-
- pos = *vmotion (startp, pos.vpos + 1 + this_scroll_margin, w);
-
- if (! NILP (Vwindow_scroll_functions))
- {
- Fset_marker (w->start, make_number (pos.bufpos), Qnil);
- run_hook_with_args_2 (Qwindow_scroll_functions, window,
- make_number (pos.bufpos));
- pos.bufpos = marker_position (w->start);
- }
- try_window (window, pos.bufpos);
- if (cursor_vpos >= 0)
- {
- if (!just_this_one || current_buffer->clip_changed
- || beg_unchanged < startp)
- /* Forget any recorded base line for line number display. */
- w->base_line_number = Qnil;
- goto done;
- }
- else
- cancel_my_columns (w);
- }
- if (PT < startp)
- {
- struct position pos;
- pos = *compute_motion (PT, 0, 0, 0,
- startp, XFASTINT (w->height), 0,
- XFASTINT (w->width), XFASTINT (w->hscroll),
- pos_tab_offset (w, startp), w);
- if (pos.vpos >= scroll_conservatively)
- goto scroll_fail_1;
-
- pos = *vmotion (startp, - pos.vpos - this_scroll_margin, w);
-
- if (! NILP (Vwindow_scroll_functions))
- {
- Fset_marker (w->start, make_number (pos.bufpos), Qnil);
- run_hook_with_args_2 (Qwindow_scroll_functions, window,
- make_number (pos.bufpos));
- pos.bufpos = marker_position (w->start);
- }
- try_window (window, pos.bufpos);
- if (cursor_vpos >= 0)
- {
- if (!just_this_one || current_buffer->clip_changed
- || beg_unchanged < startp)
- /* Forget any recorded base line for line number display. */
- w->base_line_number = Qnil;
- goto done;
- }
- else
- cancel_my_columns (w);
- }
- scroll_fail_1: ;
- }
-
- if (scroll_step && !current_buffer->clip_changed
- && startp >= BEGV && startp <= ZV)
- {
- if (PT > startp)
- {
- pos = *vmotion (Z - XFASTINT (w->window_end_pos), scroll_step, w);
- if (pos.vpos >= height)
- goto scroll_fail;
- }
-
- pos = *vmotion (startp, (PT < startp ? - scroll_step : scroll_step), w);
-
- if (PT >= pos.bufpos)
- {
- if (! NILP (Vwindow_scroll_functions))
- {
- Fset_marker (w->start, make_number (pos.bufpos), Qnil);
- run_hook_with_args_2 (Qwindow_scroll_functions, window,
- make_number (pos.bufpos));
- pos.bufpos = marker_position (w->start);
- }
- try_window (window, pos.bufpos);
- if (cursor_vpos >= 0)
- {
- if (!just_this_one || current_buffer->clip_changed
- || beg_unchanged < startp)
- /* Forget any recorded base line for line number display. */
- w->base_line_number = Qnil;
- goto done;
- }
- else
- cancel_my_columns (w);
- }
- scroll_fail: ;
- }
-
- /* Finally, just choose place to start which centers point */
-
-recenter:
- /* Forget any previously recorded base line for line number display. */
- w->base_line_number = Qnil;
-
- pos = *vmotion (PT, - (height / 2), w);
- /* Set startp here explicitly in case that helps avoid an infinite loop
- in case the window-scroll-functions functions get errors. */
- Fset_marker (w->start, make_number (pos.bufpos), Qnil);
- if (! NILP (Vwindow_scroll_functions))
- {
- run_hook_with_args_2 (Qwindow_scroll_functions, window,
- make_number (pos.bufpos));
- pos.bufpos = marker_position (w->start);
- }
- 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 ((update_mode_line
- /* If window not full width, must redo its mode line
- if the window to its side is being redone */
- || (!just_this_one && !WINDOW_FULL_WIDTH_P (w))
- || INTEGERP (w->base_line_pos)
- || (!NILP (w->column_number_displayed)
- && XFASTINT (w->column_number_displayed) != current_column ()))
- && height != XFASTINT (w->height))
- display_mode_line (w);
- if (! line_number_displayed
- && ! BUFFERP (w->base_line_pos))
- {
- w->base_line_pos = Qnil;
- w->base_line_number = Qnil;
- }
-
- /* When we reach a frame's selected window, redo the frame's menu bar. */
- if (update_mode_line
- && (FRAME_WINDOW_P (f)
- ?
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
- FRAME_EXTERNAL_MENU_BAR (f)
-#else
- FRAME_MENU_BAR_LINES (f) > 0
-#endif
- : FRAME_MENU_BAR_LINES (f) > 0)
- && EQ (FRAME_SELECTED_WINDOW (f), window))
- display_menu_bar (w);
-
- finish_scroll_bars:
- if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- {
- int start, end, whole;
-
- /* Calculate the start and end positions for the current window.
- At some point, it would be nice to choose between scrollbars
- which reflect the whole buffer size, with special markers
- indicating narrowing, and scrollbars which reflect only the
- visible region.
-
- Note that minibuffers sometimes aren't displaying any text. */
- if (! MINI_WINDOW_P (w)
- || (w == XWINDOW (minibuf_window) && ! echo_area_glyphs))
- {
- whole = ZV - BEGV;
- start = marker_position (w->start) - BEGV;
- /* I don't think this is guaranteed to be right. For the
- moment, we'll pretend it is. */
- end = (Z - XINT (w->window_end_pos)) - BEGV;
-
- if (end < start) end = start;
- if (whole < (end - start)) whole = end - start;
- }
- else
- start = end = whole = 0;
-
- /* Indicate what this scroll bar ought to be displaying now. */
- (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
-
- /* Note that we actually used the scroll bar attached to this window,
- so it shouldn't be deleted at the end of redisplay. */
- (*redeem_scroll_bar_hook) (w);
- }
-
- BUF_PT (current_buffer) = opoint;
- if (update_mode_line)
- set_buffer_internal_1 (old);
- else
- set_buffer_temp (old);
- BUF_PT (current_buffer) = lpoint;
-}
-
-/* Do full redisplay on one window, starting at position `pos'. */
-
-static void
-try_window (window, pos)
- Lisp_Object window;
- register int pos;
-{
- register struct window *w = XWINDOW (window);
- register int height = window_internal_height (w);
- register int vpos = XFASTINT (w->top);
- register int last_text_vpos = vpos;
- int tab_offset = pos_tab_offset (w, pos);
- FRAME_PTR f = XFRAME (w->frame);
- int width = window_internal_width (w) - 1;
- struct position val;
-
- /* POS should never be out of range! */
- if (pos < XBUFFER (w->buffer)->begv
- || pos > XBUFFER (w->buffer)->zv)
- abort ();
-
- Fset_marker (w->start, make_number (pos), Qnil);
- cursor_vpos = -1;
- overlay_arrow_seen = 0;
- zv_strings_seen = 0;
- val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
- val.ovstring_chars_done = 0;
-
- while (--height >= 0)
- {
- val = *display_text_line (w, pos, vpos, val.hpos, tab_offset,
- val.ovstring_chars_done);
- tab_offset += width;
- /* For the first line displayed, display_text_line
- subtracts the prompt width from the tab offset.
- But it does not affect the value of our variable tab_offset.
- So we do the subtraction again,
- for the sake of continuation lines of that first line. */
- if (MINI_WINDOW_P (w) && vpos == XFASTINT (w->top))
- tab_offset -= minibuf_prompt_width;
-
- if (val.vpos) tab_offset = 0;
- vpos++;
- if (pos != val.bufpos)
- {
- int invis = 0;
-#ifdef USE_TEXT_PROPERTIES
- Lisp_Object invis_prop;
- invis_prop = Fget_char_property (val.bufpos-1, Qinvisible, window);
- invis = TEXT_PROP_MEANS_INVISIBLE (invis_prop);
-#endif
-
- 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' || invis));
- }
- pos = val.bufpos;
- }
-
- /* If last line is continued in middle of character,
- include the split character in the text considered on the frame */
- if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
- pos++;
-
- /* If bottom just moved off end of frame, change mode line percentage. */
- if (XFASTINT (w->window_end_pos) == 0
- && Z != pos)
- w->update_mode_line = Qt;
-
- /* Say where last char on frame will be, once redisplay is finished. */
- XSETFASTINT (w->window_end_pos, Z - pos);
- XSETFASTINT (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 int
-try_window_id (window)
- Lisp_Object window;
-{
- int pos;
- register struct window *w = XWINDOW (window);
- register int height = window_internal_height (w);
- FRAME_PTR f = XFRAME (w->frame);
- int top = XFASTINT (w->top);
- int start = marker_position (w->start);
- int width = window_internal_width (w) - 1;
- int hscroll = XINT (w->hscroll);
- int lmargin = hscroll > 0 ? 1 - hscroll : 0;
- int did_motion;
- register int vpos;
- register int i, tem;
- int last_text_vpos = 0;
- int stop_vpos;
- int selective = (INTEGERP (current_buffer->selective_display)
- ? XINT (current_buffer->selective_display)
- : !NILP (current_buffer->selective_display) ? -1 : 0);
-
- struct position val, bp, ep, xp, pp;
- int scroll_amount = 0;
- int delta;
- int tab_offset, epto, old_tick;
-
- if (GPT - BEG < beg_unchanged)
- beg_unchanged = GPT - BEG;
- if (Z - GPT < end_unchanged)
- end_unchanged = Z - GPT;
-
- if (beg_unchanged + BEG < 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, 0,
- min (ZV, beg_unchanged + BEG), height, 0,
- width, hscroll, pos_tab_offset (w, start), w);
- if (bp.vpos >= height)
- {
- if (PT < bp.bufpos)
- {
- /* All changes are beyond the window end, and point is on the screen.
- We don't need to change the text at all.
- But we need to update window_end_pos to account for
- any change in buffer size. */
- bp = *compute_motion (start, 0, lmargin, 0,
- ZV, height, 0,
- width, hscroll, pos_tab_offset (w, start), w);
- XSETFASTINT (w->window_end_vpos, height);
- XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
- goto findpoint;
- }
- return 0;
- }
-
- vpos = bp.vpos;
-
- /* Find beginning of that frame line. Must display from there. */
- bp = *vmotion (bp.bufpos, 0, w);
-
- pos = bp.bufpos;
- val.hpos = lmargin;
- if (pos < start)
- return -1;
-
- did_motion = 0;
- /* If about to start displaying at the beginning of a continuation line,
- really start with previous frame 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. */
- (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
- {
- bp = *vmotion (bp.bufpos, -1, w);
- --vpos;
- pos = bp.bufpos;
- }
-
- if (bp.contin && bp.hpos != lmargin)
- {
- val.hpos = bp.prevhpos - width + lmargin;
- did_motion = 1;
- 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 (selective > 0)
- while (tem < ZV - 1 && (indented_beyond_p (tem, selective)))
- tem = find_next_newline (tem, 1);
-
- /* Compute the cursor position after that newline. */
- ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
- height, - (1 << (BITS_PER_SHORT - 1)),
- width, hscroll, pos_tab_offset (w, bp.bufpos), w);
-
- /* If changes reach past the text available on the frame,
- just display rest of frame. */
- 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;
-
- cursor_vpos = -1;
- overlay_arrow_seen = 0;
- zv_strings_seen = 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, 1,
- Z - XFASTINT (w->window_end_pos),
- 10000, 0, width, hscroll, epto, w);
- scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
-
- /* Is everything on frame 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;
-
- XSETFASTINT (w->window_end_vpos,
- XFASTINT (w->window_end_vpos) + scroll_amount);
-
- /* Before doing any scrolling, verify that point will be on frame. */
- if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.bufpos < height))
- {
- if (PT <= xp.bufpos)
- {
- pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
- PT, height, - (1 << (BITS_PER_SHORT - 1)),
- width, hscroll, epto, w);
- }
- else
- {
- pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1,
- PT, height, - (1 << (BITS_PER_SHORT - 1)),
- width, hscroll,
- pos_tab_offset (w, xp.bufpos), w);
- }
- if (pp.bufpos < PT || pp.vpos == height)
- return 0;
- cursor_vpos = pp.vpos + top;
- cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, pp.hpos, width);
- }
-
- if (stop_vpos - scroll_amount >= height
- || ep.bufpos == xp.bufpos)
- {
- if (scroll_amount < 0)
- stop_vpos -= scroll_amount;
- scroll_amount = 0;
- /* 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 frame changes to reflect what we do here,
- further updates will not come to try_window_id
- and assume the frame and window_end_vpos match. */
- blank_end_of_window = 1;
- }
- else if (!scroll_amount)
- {
- /* Even if we don't need to scroll, we must adjust the
- charstarts of subsequent lines (that we won't redisplay)
- according to the amount of text inserted or deleted. */
- int oldpos = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
- int adjust = ep.bufpos - oldpos;
- adjust_window_charstarts (w, ep.vpos + top - 1, adjust);
- }
- 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 (f, 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_frame_lines (f, bp.vpos + top - scroll_amount,
- top + height - max (0, scroll_amount),
- scroll_amount, bp.bufpos);
- if (!tem)
- stop_vpos = height;
- else
- {
- /* scroll_frame_lines did not properly adjust subsequent
- lines' charstarts in the case where the text of the
- screen line at bp.vpos has changed.
- (This can happen in a deletion that ends in mid-line.)
- To adjust properly, we need to make things consistent
- at the position ep.
- So do a second adjust to make that happen.
- Note that stop_vpos >= ep.vpos, so it is sufficient
- to update the charstarts for lines at ep.vpos and below. */
- int oldstart
- = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
- adjust_window_charstarts (w, ep.vpos + top - 1,
- ep.bufpos - oldstart);
- }
- }
- 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 (f, 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_frame_lines (f, ep.vpos + top - scroll_amount,
- top + height - max (0, scroll_amount),
- scroll_amount, ep.bufpos);
- if (!tem) stop_vpos = height;
- }
- }
-
- /* In any case, do not display past bottom of window */
- if (stop_vpos >= height)
- {
- stop_vpos = height;
- scroll_amount = 0;
- }
-
- /* 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 we are starting display in mid-character, correct tab_offset
- to account for passing the line that that character really starts in. */
- if (val.hpos < lmargin)
- tab_offset += width;
- old_tick = MODIFF;
- while (vpos < stop_vpos)
- {
- val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset,
- val.ovstring_chars_done);
- /* If display_text_line ran a hook and changed some text,
- redisplay all the way to bottom of buffer
- So that we show the changes. */
- if (old_tick != MODIFF)
- stop_vpos = height;
- tab_offset += 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 frame */
- if (val.hpos < lmargin)
- val.bufpos++;
- XSETFASTINT (w->window_end_vpos, last_text_vpos);
- XSETFASTINT (w->window_end_pos, Z - val.bufpos);
- }
-
- /* If scrolling made blank lines at window bottom,
- redisplay to fill those lines */
- if (scroll_amount < 0)
- {
- /* Don't consider these lines for general-purpose scrolling.
- That will save time in the scrolling computation. */
- FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
- 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 we are starting display in mid-character, correct tab_offset
- to account for passing the line that that character starts in. */
- if (val.hpos < lmargin)
- tab_offset += width;
-
- while (vpos < height)
- {
- val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset,
- val.ovstring_chars_done);
- tab_offset += width;
- if (val.vpos) tab_offset = 0;
- pos = val.bufpos;
- }
-
- /* Here is a case where display_text_line sets cursor_vpos wrong.
- Make it be fixed up, below. */
- if (xp.bufpos == ZV
- && xp.bufpos == PT)
- cursor_vpos = -1;
- }
-
- /* If bottom just moved off end of frame, change mode line percentage. */
- if (XFASTINT (w->window_end_pos) == 0
- && Z != val.bufpos)
- w->update_mode_line = Qt;
-
- /* 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, w);
- XSETFASTINT (w->window_end_pos, Z - val.bufpos);
- XSETFASTINT (w->window_end_vpos,
- 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 (cursor_vpos < 0)
- {
- findpoint:
- val = *compute_motion (start, 0, lmargin, 0, PT, 10000, 10000,
- width, hscroll, pos_tab_offset (w, start), w);
- /* Admit failure if point is off frame now */
- if (val.vpos >= height)
- {
- for (vpos = 0; vpos < height; vpos++)
- cancel_line (vpos + top, f);
- return 0;
- }
- cursor_vpos = val.vpos + top;
- cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, val.hpos, width);
- }
-
- FRAME_CURSOR_X (f) = cursor_hpos;
- FRAME_CURSOR_Y (f) = cursor_vpos;
-
- if (debug_end_pos)
- {
- val = *compute_motion (start, 0, lmargin, 0, ZV,
- height, - (1 << (BITS_PER_SHORT - 1)),
- width, hscroll, pos_tab_offset (w, start), w);
- if (val.vpos != XFASTINT (w->window_end_vpos))
- abort ();
- if (XFASTINT (w->window_end_pos)
- != Z - val.bufpos)
- abort ();
- }
-
- return 1;
-}
-
-/* Copy LEN glyphs starting address FROM to the rope TO.
- But don't actually copy the parts that would come in before S.
- Value is TO, advanced past the copied data.
- F is the frame we are displaying in. */
-
-static GLYPH *
-copy_part_of_rope (f, to, s, from, len, face)
- FRAME_PTR f;
- register GLYPH *to; /* Copy to here. */
- register GLYPH *s; /* Starting point. */
- Lisp_Object *from; /* Data to copy. */
- int len;
- int face; /* Face to apply to glyphs which don't specify one. */
-{
- int n = len;
- register Lisp_Object *fp = from;
- /* These cache the results of the last call to compute_glyph_face. */
- int last_code = -1;
- int last_merged = 0;
-
-#ifdef HAVE_FACES
- if (! FRAME_TERMCAP_P (f))
- while (n--)
- {
- int glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
- int facecode;
-
- if (FAST_GLYPH_FACE (glyph) == 0)
- /* If GLYPH has no face code, use FACE. */
- facecode = face;
- else if (FAST_GLYPH_FACE (glyph) == last_code)
- /* If it's same as previous glyph, use same result. */
- facecode = last_merged;
- else
- {
- /* Merge this glyph's face and remember the result. */
- last_code = FAST_GLYPH_FACE (glyph);
- last_merged = facecode = compute_glyph_face (f, last_code, face);
- }
-
- if (to >= s)
- *to = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), facecode);
- ++to;
- ++fp;
- }
- else
-#endif
- while (n--)
- {
- if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
- ++to;
- ++fp;
- }
- return to;
-}
-
-/* Correct a glyph by replacing its specified user-level face code
- with a displayable computed face code. */
-
-static GLYPH
-fix_glyph (f, glyph, cface)
- FRAME_PTR f;
- GLYPH glyph;
- int cface;
-{
-#ifdef HAVE_FACES
- if (! FRAME_TERMCAP_P (f))
- {
- if (FAST_GLYPH_FACE (glyph) != 0)
- cface = compute_glyph_face (f, FAST_GLYPH_FACE (glyph), cface);
- glyph = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), cface);
- }
-#endif
- return glyph;
-}
-
-/* Display one line of window W, starting at position START in W's buffer.
-
- Display starting at horizontal position HPOS, expressed relative to
- W's left edge. In situations where the text at START shouldn't
- start at the left margin (i.e. when the window is hscrolled, or
- we're continuing a line which left off in the midst of a
- multi-column character), HPOS should be negative; we throw away
- characters up 'til hpos = 0. So, HPOS must take hscrolling into
- account.
-
- TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
-
- OVSTR_DONE is the number of chars of overlay before/after strings
- at this position which have already been processed.
-
- Display on position VPOS on the frame. It is origin 0, relative to
- the top of the frame, not W.
-
- 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;
-
-static struct position *
-display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
- struct window *w;
- int start;
- int vpos;
- int hpos;
- int taboffset;
- int ovstr_done;
-{
- register int pos = start;
- register int c;
- register GLYPH *p1;
- register int pause;
- register unsigned char *p;
- GLYPH *endp;
- register GLYPH *leftmargin;
- register GLYPH *p1prev;
- register GLYPH *p1start;
- int prevpos;
- int *charstart;
- FRAME_PTR f = XFRAME (w->frame);
- int tab_width = XINT (current_buffer->tab_width);
- int ctl_arrow = !NILP (current_buffer->ctl_arrow);
- int width = window_internal_width (w) - 1;
- struct position val;
- int lastpos;
- int invis;
- int last_invis_skip = 0;
- Lisp_Object last_invis_prop;
- int hscroll = XINT (w->hscroll);
- int truncate = (hscroll
- || (truncate_partial_width_windows
- && !WINDOW_FULL_WIDTH_P (w))
- || !NILP (current_buffer->truncate_lines));
-
- /* 1 if we should highlight the region. */
- int highlight_region
- = (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active)
- && XWINDOW (current_buffer->last_selected_window) == w);
- int region_beg, region_end;
-
- int selective = (INTEGERP (current_buffer->selective_display)
- ? XINT (current_buffer->selective_display)
- : !NILP (current_buffer->selective_display) ? -1 : 0);
- register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
- register struct Lisp_Char_Table *dp = window_display_table (w);
-
- Lisp_Object default_invis_vector[3];
- /* Number of characters of ellipsis to display after an invisible line
- if it calls for an ellipsis.
- Note that this value can be nonzero regardless of whether
- selective display is enabled--you must check that separately. */
- int selective_rlen
- = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
- ? XVECTOR (DISP_INVIS_VECTOR (dp))->size
- : !NILP (current_buffer->selective_display_ellipses) ? 3 : 0);
- /* This is the sequence of Lisp objects to display
- when there are invisible lines. */
- Lisp_Object *invis_vector_contents
- = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
- ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
- : default_invis_vector);
-
- GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
- ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
- GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
- ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
-
- /* The next buffer location at which the face should change, due
- to overlays or text property changes. */
- int next_face_change;
-
- /* The next location where the `invisible' property changes, or an
- overlay starts or ends. */
- int next_boundary;
-
- /* The face we're currently using. */
- int current_face = 0;
- int i;
-
- XSETFASTINT (default_invis_vector[2], '.');
- default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
-
- hpos += WINDOW_LEFT_MARGIN (w);
- get_display_line (f, vpos, WINDOW_LEFT_MARGIN (w));
- if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
-
- /* Show where to highlight the region. */
- if (highlight_region && XMARKER (current_buffer->mark)->buffer != 0
- /* Maybe highlight only in selected window. */
- && (highlight_nonselected_windows
- || w == XWINDOW (selected_window)))
- {
- region_beg = marker_position (current_buffer->mark);
- if (PT < region_beg)
- {
- region_end = region_beg;
- region_beg = PT;
- }
- else
- region_end = PT;
- w->region_showing = Qt;
- }
- else
- region_beg = region_end = -1;
-
- if (MINI_WINDOW_P (w)
- && start == BEG
- && vpos == XFASTINT (w->top))
- {
- if (! NILP (minibuf_prompt))
- {
- minibuf_prompt_width
- = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
- XSTRING (minibuf_prompt)->size, hpos,
- /* Display a space if we truncate. */
- ' ',
- 1, -1,
- /* Truncate the prompt a little before the
- margin, so user input can at least start
- on the first line. */
- w->width > 10 ? w->width - 4 : -1)
- - hpos);
- hpos += minibuf_prompt_width;
- taboffset -= minibuf_prompt_width;
- }
- else
- minibuf_prompt_width = 0;
- }
-
- /* If we're hscrolled at all, use compute_motion to skip over any
- text off the left edge of the window. compute_motion may know
- tricks to do this faster than we can. */
- if (hpos < 0)
- {
- struct position *left_edge
- = compute_motion (pos, vpos, hpos, 0,
- ZV, vpos, 0,
- width, hscroll, taboffset, w);
-
- /* Retrieve the buffer position and column provided by
- compute_motion. We can't assume that the column will be
- zero, because you may have multi-column characters crossing
- the left margin.
-
- compute_motion may have moved us past the screen position we
- requested, if we hit a multi-column character, or the end of
- the line. If so, back up. */
- if (left_edge->vpos > vpos
- || left_edge->hpos > 0)
- {
- pos = left_edge->bufpos - 1;
- hpos = left_edge->prevhpos;
- }
- else
- {
- pos = left_edge->bufpos;
- hpos = left_edge->hpos;
- }
- }
-
- desired_glyphs->bufp[vpos] = start;
- p1 = desired_glyphs->glyphs[vpos] + hpos;
- p1start = p1;
- charstart = desired_glyphs->charstarts[vpos] + hpos;
- /* In case we don't ever write anything into it... */
- desired_glyphs->charstarts[vpos][WINDOW_LEFT_MARGIN (w)] = -1;
- leftmargin = desired_glyphs->glyphs[vpos] + WINDOW_LEFT_MARGIN (w);
- endp = leftmargin + width;
-
- /* Arrange the overlays nicely for our purposes. Usually, we call
- display_text_line on only one line at a time, in which case this
- can't really hurt too much, or we call it on lines which appear
- one after another in the buffer, in which case all calls to
- recenter_overlay_lists but the first will be pretty cheap. */
- recenter_overlay_lists (current_buffer, pos);
-
- /* Loop generating characters.
- Stop at end of buffer, before newline,
- if reach or pass continuation column,
- or at face change. */
- pause = pos;
- next_face_change = pos;
- next_boundary = pos;
- p1prev = p1;
- prevpos = pos;
- while (1)
- {
- if (pos >= pause)
- {
- int e_t_h;
-
- while (pos == next_boundary)
- {
- Lisp_Object position, limit, prop, ww;
-
- /* Display the overlay strings here, unless we're at ZV
- and have already displayed the appropriate strings
- on an earlier line. */
- if (pos < ZV || !zv_strings_seen++)
- {
- int ovlen;
- unsigned char *ovstr;
- ovlen = overlay_strings (pos, w, &ovstr);
-
- if (ovlen > 0)
- {
- /* Skip the ones we did in a previous line. */
- ovstr += ovstr_done;
- ovlen -= ovstr_done;
-
- /* Start outputting. */
- for (; ovlen; ovlen--, ovstr++)
- {
- if (p1 >= leftmargin && p1 < endp)
- *p1 = MAKE_GLYPH (f, *ovstr, current_face);
- p1++;
- ovstr_done++;
- }
- /* If we did all the overlay strings
- and we have room for text, clear ovstr_done
- just for neatness' sake. */
- if (ovlen == 0 && p1 < endp)
- ovstr_done = 0;
- }
- }
-
- /* Did we reach point? Record the cursor location. */
- if (pos == PT && cursor_vpos < 0)
- {
- cursor_vpos = vpos;
- cursor_hpos = p1 - leftmargin;
- }
-
- if (pos >= ZV)
- break;
-
- XSETFASTINT (position, pos);
- limit = Fnext_overlay_change (position);
-#ifdef USE_TEXT_PROPERTIES
- /* This is just an estimate to give reasonable
- performance; nothing should go wrong if it is too small. */
- if (XFASTINT (limit) > pos + 50)
- XSETFASTINT (limit, pos + 50);
- limit = Fnext_single_property_change (position, Qinvisible,
- Fcurrent_buffer (), limit);
-#endif
- next_boundary = XFASTINT (limit);
- /* if the `invisible' property is set, we can skip to
- the next property change. */
- XSETWINDOW (ww, w);
- prop = Fget_char_property (position, Qinvisible, ww);
- if (TEXT_PROP_MEANS_INVISIBLE (prop))
- {
- if (pos < PT && next_boundary >= PT)
- {
- cursor_vpos = vpos;
- cursor_hpos = p1 - leftmargin;
- }
- pos = next_boundary;
- last_invis_skip = pos;
- last_invis_prop = prop;
- }
- }
-
- /* Did we reach point? Record the cursor location. */
- if (pos == PT && cursor_vpos < 0)
- {
- cursor_vpos = vpos;
- cursor_hpos = p1 - leftmargin;
- }
-
- /* Did we hit the end of the visible region of the buffer?
- Stop here. */
- if (pos >= ZV)
- {
- /* Update charstarts for the end of this line. */
- /* Do nothing if off the left edge or at the right edge. */
- if (p1 >= leftmargin && p1 + 1 != endp)
- {
- int *p2x = &charstart[(p1 < leftmargin
- ? leftmargin : p1)
- - p1start];
- *p2x++ = pos;
- }
- break;
- }
-
- /* Figure out where (if at all) the
- redisplay_end_trigger-hook should run. */
- if (MARKERP (w->redisplay_end_trigger)
- && XMARKER (w->redisplay_end_trigger)->buffer != 0)
- e_t_h = marker_position (w->redisplay_end_trigger);
- else if (INTEGERP (w->redisplay_end_trigger))
- e_t_h = XINT (w->redisplay_end_trigger);
- else
- e_t_h = ZV;
-
- /* If we've gone past the place to run a hook,
- run the hook. */
- if (pos >= e_t_h && e_t_h != ZV)
- {
- Lisp_Object args[3];
-
- args[0] = Qredisplay_end_trigger_functions;
- XSETWINDOW (args[1], w);
- XSETINT (args[2], e_t_h);
-
- /* Since we are *trying* to run these functions,
- don't try to run them again, even if they get an error. */
- w->redisplay_end_trigger = Qnil;
- Frun_hook_with_args (3, args);
-
- e_t_h = ZV;
- /* Notice if it changed the face of this character. */
- next_face_change = pos;
- }
-
-#ifdef HAVE_FACES
- /* Did we hit a face change? Figure out what face we should
- use now. We also hit this the first time through the
- loop, to see what face we should start with. */
- if (pos >= next_face_change
- && (FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f)))
- current_face = compute_char_face (f, w, pos,
- region_beg, region_end,
- &next_face_change, pos + 50, 0);
-#endif
-
- /* Compute the next place we need to stop
- and do something special; set PAUSE. */
-
- pause = ZV;
-
- if (pos < next_boundary && next_boundary < pause)
- pause = next_boundary;
- if (pos < next_face_change && next_face_change < pause)
- pause = next_face_change;
-
- if (e_t_h < pause)
- pause = e_t_h;
-
- /* Wouldn't you hate to read the next line to someone over
- the phone? */
- if (pos < PT && PT < pause)
- pause = PT;
- if (pos < GPT && GPT < pause)
- pause = GPT;
-
- p = &FETCH_CHAR (pos);
- }
-
- if (p1 >= endp)
- break;
-
- p1prev = p1;
-
- c = *p++;
- /* Let a display table override all standard display methods. */
- if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
- {
- p1 = copy_part_of_rope (f, p1, leftmargin,
- XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
- XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
- current_face);
- }
- else if (c >= 040 && c < 0177)
- {
- if (p1 >= leftmargin)
- *p1 = MAKE_GLYPH (f, c, current_face);
- p1++;
- }
- else if (c == '\n')
- {
- invis = 0;
- if (last_invis_skip == pos
- && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop))
- invis = 1;
- while (pos + 1 < ZV
- && selective > 0
- && indented_beyond_p (pos + 1, selective))
- {
- invis = 1;
- pos = find_next_newline (pos + 1, 1);
- if (FETCH_CHAR (pos - 1) == '\n')
- pos--;
- }
- if (invis && selective_rlen > 0 && p1 >= leftmargin)
- {
- p1 += selective_rlen;
- if (p1 - leftmargin > width)
- p1 = endp;
- copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
- (p1 - p1prev), current_face);
- }
-#ifdef HAVE_FACES
- /* Draw the face of the newline character as extending all the
- way to the end of the frame line. */
- if (current_face)
- {
- if (p1 < leftmargin)
- p1 = leftmargin;
- while (p1 < endp)
- *p1++ = FAST_MAKE_GLYPH (' ', current_face);
- }
-#endif
-
- /* Update charstarts for the newline that ended this line. */
- /* Do nothing here for a char that's entirely off the left edge
- or if it starts at the right edge. */
- if (p1 >= leftmargin && p1prev != endp)
- {
- /* Store the newline's position into charstarts
- for the column where the newline starts.
- Store -1 for the rest of the glyphs it occupies. */
- int *p2x = &charstart[(p1prev < leftmargin
- ? leftmargin : p1prev)
- - p1start];
- int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
-
- *p2x++ = pos;
- while (p2x < p2)
- *p2x++ = -1;
- }
-
- break;
- }
- else if (c == '\t')
- {
- do
- {
- if (p1 >= leftmargin && p1 < endp)
- *p1 = MAKE_GLYPH (f, ' ', current_face);
- p1++;
- }
- while ((p1 - leftmargin + 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_rlen > 0)
- {
- p1 += selective_rlen;
- if (p1 - leftmargin > width)
- p1 = endp;
- copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
- (p1 - p1prev), current_face);
- }
-#ifdef HAVE_FACES
- /* Draw the face of the newline character as extending all the
- way to the end of the frame line. */
- if (current_face)
- {
- if (p1 < leftmargin)
- p1 = leftmargin;
- while (p1 < endp)
- *p1++ = FAST_MAKE_GLYPH (' ', current_face);
- }
-#endif
-
- /* Update charstarts for the ^M that ended this line. */
- /* Do nothing here for a char that's entirely off the left edge
- or if it starts at the right edge. */
- if (p1 >= leftmargin && p1prev != endp)
- {
- /* Store the newline's position into charstarts
- for the column where the newline starts.
- Store -1 for the rest of the glyphs it occupies. */
- int *p2x = &charstart[(p1prev < leftmargin
- ? leftmargin : p1prev)
- - p1start];
- int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
-
- *p2x++ = pos;
- while (p2x < p2)
- *p2x++ = -1;
- }
- break;
- }
- else if (c < 0200 && ctl_arrow)
- {
- if (p1 >= leftmargin)
- *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
- ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
- current_face);
- p1++;
- if (p1 >= leftmargin && p1 < endp)
- *p1 = MAKE_GLYPH (f, c ^ 0100, current_face);
- p1++;
- }
- else
- {
- if (p1 >= leftmargin)
- *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
- ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
- current_face);
- p1++;
- if (p1 >= leftmargin && p1 < endp)
- *p1 = MAKE_GLYPH (f, (c >> 6) + '0', current_face);
- p1++;
- if (p1 >= leftmargin && p1 < endp)
- *p1 = MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face);
- p1++;
- if (p1 >= leftmargin && p1 < endp)
- *p1 = MAKE_GLYPH (f, (7 & c) + '0', current_face);
- p1++;
- }
-
- prevpos = pos;
- pos++;
-
- /* Update charstarts for the character just output. */
-
- /* Do nothing here for a char that's entirely off the left edge. */
- if (p1 >= leftmargin)
- {
- /* Store the char's position into charstarts
- for the first glyph occupied by this char.
- Store -1 for the rest of the glyphs it occupies. */
- if (p1 != p1prev)
- {
- int *p2x = &charstart[(p1prev < leftmargin
- ? leftmargin : p1prev)
- - p1start];
- int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
-
- if (p2x < p2)
- *p2x++ = prevpos;
- while (p2x < p2)
- *p2x++ = -1;
- }
- }
- }
-
- val.hpos = - XINT (w->hscroll);
- if (val.hpos)
- val.hpos++;
-
- val.vpos = 1;
-
- lastpos = pos;
-
- /* Store 0 in this charstart line for the positions where
- there is no character. But do leave what was recorded
- for the character that ended the line. */
- /* Add 1 in the endtest to compensate for the fact that ENDP was
- made from WIDTH, which is 1 less than the window's actual
- internal width. */
- i = p1 - p1start + 1;
- if (p1 < leftmargin)
- i += leftmargin - p1;
- for (; i < endp - p1start + 1; i++)
- charstart[i] = 0;
-
- /* Handle continuation in middle of a character */
- /* by backing up over it */
- if (p1 > endp)
- {
- /* Don't back up if we never actually displayed any text.
- This occurs when the minibuffer prompt takes up the whole line. */
- 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++;
- /* Check again for hidden lines, in case the newline occurred exactly
- at the right margin. */
- while (pos < ZV && selective > 0
- && indented_beyond_p (pos, selective))
- pos = find_next_newline (pos, 1);
- }
- else
- /* Stopped due to right margin of window */
- {
- if (truncate)
- {
- *p1++ = fix_glyph (f, truncator, 0);
- /* 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 */
- do
- pos = find_next_newline (pos, 1);
- while (pos < ZV && selective > 0
- && indented_beyond_p (pos, selective));
- val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
-
- lastpos = pos - (FETCH_CHAR (pos - 1) == '\n');
- }
- else
- {
- *p1++ = fix_glyph (f, continuer, 0);
- val.vpos = 0;
- lastpos--;
- }
- }
- }
-
- /* If point is at eol or in invisible text at eol,
- record its frame location now. */
-
- if (start <= PT && PT <= lastpos && cursor_vpos < 0)
- {
- cursor_vpos = vpos;
- cursor_hpos = p1 - leftmargin;
- }
-
- if (cursor_vpos == vpos)
- {
- if (cursor_hpos < 0) cursor_hpos = 0;
- if (cursor_hpos > width) cursor_hpos = width;
- cursor_hpos += WINDOW_LEFT_MARGIN (w);
- if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
- {
- if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (f)
- && EQ (FRAME_MINIBUF_WINDOW (f), minibuf_window)))
- {
- FRAME_CURSOR_Y (f) = cursor_vpos;
- FRAME_CURSOR_X (f) = cursor_hpos;
- }
-
- if (w == XWINDOW (selected_window))
- {
- /* Line is not continued and did not start
- in middle of character */
- if ((hpos - WINDOW_LEFT_MARGIN (w)
- == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
- && val.vpos)
- {
- this_line_bufpos = start;
- this_line_buffer = current_buffer;
- this_line_vpos = cursor_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)
- {
- *leftmargin = fix_glyph (f, truncator, 0);
- if (p1 <= leftmargin)
- p1 = leftmargin + 1;
- }
-
- if (!WINDOW_RIGHTMOST_P (w))
- {
- endp++;
- if (p1 < leftmargin) p1 = leftmargin;
- while (p1 < endp) *p1++ = SPACEGLYPH;
-
- /* Don't draw vertical bars if we're using scroll bars. They're
- covered up by the scroll bars, and it's distracting to see
- them when the scroll bar windows are flickering around to be
- reconfigured. */
- if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
- {
- int i;
- for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
- *p1++ = SPACEGLYPH;
- }
- else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- *p1++ = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
- ? DISP_BORDER_GLYPH (dp)
- : '|');
- }
- desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
- p1 - desired_glyphs->glyphs[vpos]);
- desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
-
- /* If the start of this line is the overlay arrow-position,
- then put the arrow string into the display-line. */
-
- if (MARKERP (Voverlay_arrow_position)
- && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
- && start == marker_position (Voverlay_arrow_position)
- && STRINGP (Voverlay_arrow_string)
- && ! overlay_arrow_seen)
- {
- unsigned char *p = XSTRING (Voverlay_arrow_string)->data;
- int i;
- int len = XSTRING (Voverlay_arrow_string)->size;
- int arrow_end;
-
- if (len > width)
- len = width;
-#ifdef HAVE_FACES
- if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string)->intervals))
- {
- /* If the arrow string has text props, obey them when displaying. */
- for (i = 0; i < len; i++)
- {
- int c = p[i];
- Lisp_Object face, ilisp;
- int newface;
-
- XSETFASTINT (ilisp, i);
- face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
- newface = compute_glyph_face_1 (f, face, 0);
- leftmargin[i] = FAST_MAKE_GLYPH (c, newface);
- }
- }
- else
-#endif /* HAVE_FACES */
- {
- for (i = 0; i < len; i++)
- leftmargin[i] = p[i];
- }
-
- /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
- arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len;
- if (desired_glyphs->used[vpos] < arrow_end)
- desired_glyphs->used[vpos] = arrow_end;
-
- overlay_arrow_seen = 1;
- }
-
- val.bufpos = pos;
- val.ovstring_chars_done = ovstr_done;
- val_display_text_line = val;
- return &val_display_text_line;
-}
-
-/* Redisplay the menu bar in the frame for window W. */
-
-static void
-display_menu_bar (w)
- struct window *w;
-{
- Lisp_Object items, tail;
- register int vpos = 0;
- register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
- int maxendcol = FRAME_WIDTH (f);
- int hpos = 0;
- int i;
-
-#ifdef HAVE_NTGUI
- if (!NILP (Vwindow_system))
- return;
-#endif
-
-#ifdef USE_X_TOOLKIT
- if (FRAME_X_P (f))
- return;
-#endif /* USE_X_TOOLKIT */
-
- get_display_line (f, vpos, 0);
-
- items = FRAME_MENU_BAR_ITEMS (f);
- for (i = 0; i < XVECTOR (items)->size; i += 4)
- {
- Lisp_Object pos, string;
- string = XVECTOR (items)->contents[i + 1];
- if (NILP (string))
- break;
-
- XSETFASTINT (XVECTOR (items)->contents[i + 3], hpos);
-
- if (hpos < maxendcol)
- hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos,
- XSTRING (string)->data,
- XSTRING (string)->size,
- hpos, 0, 0, hpos, maxendcol);
- /* Put a space between items. */
- if (hpos < maxendcol)
- {
- int hpos1 = hpos + 1;
- hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
- min (hpos1, maxendcol), maxendcol);
- }
- }
-
- FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
- FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
-
- /* Fill out the line with spaces. */
- if (maxendcol > hpos)
- hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol);
-
- /* Clear the rest of the lines allocated to the menu bar. */
- vpos++;
- while (vpos < FRAME_MENU_BAR_LINES (f))
- get_display_line (f, vpos++, 0);
-}
-
-/* Display the mode line for window w */
-
-static void
-display_mode_line (w)
- struct window *w;
-{
- register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
- register int left = WINDOW_LEFT_MARGIN (w);
- register int right = WINDOW_RIGHT_MARGIN (w);
- register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
-
- line_number_displayed = 0;
- w->column_number_displayed = Qnil;
-
- get_display_line (f, vpos, left);
-
- /* Temporarily make frame F's kboard the current kboard
- so that kboard-local variables in the mode_line_format
- will get the right values. */
- push_frame_kboard (f);
-
- display_mode_element (w, vpos, left, 0, right, right,
- current_buffer->mode_line_format);
-
- pop_frame_kboard ();
-
- FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
-
- /* Put the mode line in inverse video.
- Use faces if possible, since that lets us handle
- partial-width windows and avoid inverting the scroll bar columns. */
-#ifdef HAVE_FACES
- if (! FRAME_TERMCAP_P (f) && mode_line_inverse_video)
- {
- /* For a partial width window, explicitly set face of each glyph. */
- int i;
- GLYPH *ptr = FRAME_DESIRED_GLYPHS (f)->glyphs[vpos];
- for (i = left; i < right; ++i)
- ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1);
- }
-#endif
-
- /* 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). */
- else if (WINDOW_FULL_WIDTH_P (w)
- || WINDOW_FULL_WIDTH_P (XWINDOW (w->parent)))
- FRAME_DESIRED_GLYPHS (f)->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.
-
- VPOS is the position of the mode line being displayed.
-
- HPOS is the position (absolute on frame) 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. */
-
-static int
-display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
- struct window *w;
- register int vpos, hpos;
- int depth;
- int minendcol;
- register int maxendcol;
- register Lisp_Object elt;
-{
- tail_recurse:
- if (depth > 10)
- goto invalid;
-
- depth++;
-
- switch (SWITCH_ENUM_CAST (XTYPE (elt)))
- {
- 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;
- if (frame_title_ptr)
- hpos = store_frame_title (last, hpos, min (lim, maxendcol));
- else
- hpos = display_string (w, vpos, last, -1, hpos, 0, 1,
- hpos, min (lim, maxendcol));
- }
- else /* c == '%' */
- {
- register int minendcol;
- 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');
- }
-
- minendcol = hpos + spec_width;
- if (minendcol > maxendcol)
- {
- spec_width = maxendcol - hpos;
- minendcol = maxendcol;
- }
-
- if (c == 'M')
- hpos = display_mode_element (w, vpos, hpos, depth,
- spec_width, maxendcol,
- Vglobal_mode_string);
- else if (c != 0)
- {
- char *spec = decode_mode_spec (w, c, spec_width,
- maxendcol - hpos);
- if (frame_title_ptr)
- hpos = store_frame_title (spec, minendcol, maxendcol);
- else
- hpos = display_string (w, vpos, spec, -1,
- hpos, 0, 1,
- minendcol, 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 (!NILP (tem))
- {
- tem = Fsymbol_value (elt);
- /* If value is a string, output that string literally:
- don't check for % within it. */
- if (STRINGP (tem))
- {
- if (frame_title_ptr)
- hpos = store_frame_title (XSTRING (tem)->data,
- minendcol, maxendcol);
- else
- hpos = display_string (w, vpos, XSTRING (tem)->data,
- XSTRING (tem)->size,
- hpos, 0, 1, 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 (SYMBOLP (car))
- {
- tem = Fboundp (car);
- elt = XCONS (elt)->cdr;
- if (!CONSP (elt))
- 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 (!NILP (tem))
- {
- tem = Fsymbol_value (car);
- if (!NILP (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 (NILP (elt))
- break;
- else if (!CONSP (elt))
- goto invalid;
- elt = XCONS (elt)->car;
- goto tail_recurse;
- }
- else if (INTEGERP (car))
- {
- 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 (STRINGP (car) || CONSP (car))
- {
- register int limit = 50;
- /* LIMIT is to protect against circular lists. */
- while (CONSP (elt) && --limit > 0
- && hpos < maxendcol)
- {
- hpos = display_mode_element (w, vpos, hpos, depth,
- hpos, maxendcol,
- XCONS (elt)->car);
- elt = XCONS (elt)->cdr;
- }
- }
- }
- break;
-
- default:
- invalid:
- if (frame_title_ptr)
- hpos = store_frame_title ("*invalid*", minendcol, maxendcol);
- else
- hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1,
- minendcol, maxendcol);
- return hpos;
- }
-
- if (minendcol > hpos)
- if (frame_title_ptr)
- hpos = store_frame_title ("", minendcol, maxendcol);
- else
- hpos = display_string (w, vpos, "", 0, hpos, 0, 1, minendcol, maxendcol);
- return hpos;
-}
-
-/* Write a null-terminated, right justified decimal representation of
- the positive integer D to BUF using a minimal field width WIDTH. */
-
-static void
-pint2str (buf, width, d)
- register char *buf;
- register int width;
- register int d;
-{
- register char *p = buf;
-
- if (d <= 0)
- *p++ = '0';
- else
- while (d > 0)
- {
- *p++ = d % 10 + '0';
- d /= 10;
- }
- for (width -= (int) (p - buf); width > 0; --width) *p++ = ' ';
- *p-- = '\0';
- while (p > buf)
- {
- d = *buf;
- *buf++ = *p;
- *p-- = d;
- }
-}
-
-/* Return a string for the output of a mode line %-spec for window W,
- generated by character C. SPEC_WIDTH is the field width when
- padding to the left (%c, %l). The value returned from this
- function will later be truncated to width MAXWIDTH. */
-
-static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
-
-static char *
-decode_mode_spec (w, c, spec_width, maxwidth)
- struct window *w;
- register char c;
- register int spec_width;
- register int maxwidth;
-{
- Lisp_Object obj;
- FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
- char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents;
- struct buffer *b = XBUFFER (w->buffer);
-
- obj = Qnil;
- if (maxwidth > FRAME_WIDTH (f))
- maxwidth = FRAME_WIDTH (f);
-
- switch (c)
- {
- case '*':
- if (!NILP (b->read_only))
- return "%";
- if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
- return "*";
- return "-";
-
- case '+':
- /* This differs from %* only for a modified read-only buffer. */
- if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
- return "*";
- if (!NILP (b->read_only))
- return "%";
- return "-";
-
- case '&':
- /* This differs from %* in ignoring read-only-ness. */
- if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
- return "*";
- return "-";
-
- 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;
- 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 '-':
- {
- register char *p;
- register int i;
-
- if (maxwidth < sizeof (lots_of_dashes))
- return lots_of_dashes;
- else
- {
- for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
- *p++ = '-';
- *p = '\0';
- }
- return decode_mode_spec_buf;
- }
-
- case 'b':
- obj = b->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 'c':
- {
- int col = current_column ();
- XSETFASTINT (w->column_number_displayed, col);
- pint2str (decode_mode_spec_buf, spec_width, col);
- return decode_mode_spec_buf;
- }
-
- case 'F':
- /* %F displays the frame name. */
- if (!NILP (f->title))
- return (char *) XSTRING (f->title)->data;
- if (f->explicit_name || ! FRAME_WINDOW_P (f))
- return (char *) XSTRING (f->name)->data;
- return "Emacs";
-
- case 'f':
- obj = b->filename;
-#if 0
- if (NILP (obj))
- return "[none]";
- else if (STRINGP (obj) && 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 'l':
- {
- int startpos = marker_position (w->start);
- int line, linepos, topline;
- int nlines, junk;
- Lisp_Object tem;
- int height = XFASTINT (w->height);
-
- /* If we decided that this buffer isn't suitable for line numbers,
- don't forget that too fast. */
- if (EQ (w->base_line_pos, w->buffer))
- goto no_value;
- /* But do forget it, if the window shows a different buffer now. */
- else if (BUFFERP (w->base_line_pos))
- w->base_line_pos = Qnil;
-
- /* If the buffer is very big, don't waste time. */
- if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
- {
- w->base_line_pos = Qnil;
- w->base_line_number = Qnil;
- goto no_value;
- }
-
- if (!NILP (w->base_line_number)
- && !NILP (w->base_line_pos)
- && XFASTINT (w->base_line_pos) <= marker_position (w->start))
- {
- line = XFASTINT (w->base_line_number);
- linepos = XFASTINT (w->base_line_pos);
- }
- else
- {
- line = 1;
- linepos = BUF_BEGV (b);
- }
-
- /* Count lines from base line to window start position. */
- nlines = display_count_lines (linepos, startpos, startpos, &junk);
-
- topline = nlines + line;
-
- /* Determine a new base line, if the old one is too close
- or too far away, or if we did not have one.
- "Too close" means it's plausible a scroll-down would
- go back past it. */
- if (startpos == BUF_BEGV (b))
- {
- XSETFASTINT (w->base_line_number, topline);
- XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
- }
- else if (nlines < height + 25 || nlines > height * 3 + 50
- || linepos == BUF_BEGV (b))
- {
- int limit = BUF_BEGV (b);
- int position;
- int distance = (height * 2 + 30) * 200;
-
- if (startpos - distance > limit)
- limit = startpos - distance;
-
- nlines = display_count_lines (startpos, limit,
- -(height * 2 + 30),
- &position);
- /* If we couldn't find the lines we wanted within
- 200 chars per line,
- give up on line numbers for this window. */
- if (position == startpos - distance)
- {
- w->base_line_pos = w->buffer;
- w->base_line_number = Qnil;
- goto no_value;
- }
-
- XSETFASTINT (w->base_line_number, topline - nlines);
- XSETFASTINT (w->base_line_pos, position);
- }
-
- /* Now count lines from the start pos to point. */
- nlines = display_count_lines (startpos, PT, PT, &junk);
-
- /* Record that we did display the line number. */
- line_number_displayed = 1;
-
- /* Make the string to show. */
- pint2str (decode_mode_spec_buf, spec_width, topline + nlines);
- return decode_mode_spec_buf;
- no_value:
- {
- char* p = decode_mode_spec_buf;
- for (spec_width -= 2; spec_width > 0; --spec_width) *p++ = ' ';
- strcpy (p, "??");
- return decode_mode_spec_buf;
- }
- }
- break;
-
- case 'm':
- obj = b->mode_name;
- break;
-
- case 'n':
- if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
- return " Narrow";
- break;
-
- case 'p':
- {
- int pos = marker_position (w->start);
- int total = BUF_ZV (b) - BUF_BEGV (b);
-
- if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
- {
- if (pos <= BUF_BEGV (b))
- return "All";
- else
- return "Bottom";
- }
- else if (pos <= BUF_BEGV (b))
- return "Top";
- else
- {
- if (total > 1000000)
- /* Do it differently for a large value, to avoid overflow. */
- total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
- else
- total = ((pos - BUF_BEGV (b)) * 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;
- }
- }
-
- /* Display percentage of size above the bottom of the screen. */
- case 'P':
- {
- int toppos = marker_position (w->start);
- int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
- int total = BUF_ZV (b) - BUF_BEGV (b);
-
- if (botpos >= BUF_ZV (b))
- {
- if (toppos <= BUF_BEGV (b))
- return "All";
- else
- return "Bottom";
- }
- else
- {
- if (total > 1000000)
- /* Do it differently for a large value, to avoid overflow. */
- total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
- else
- total = ((botpos - BUF_BEGV (b)) * 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;
- if (toppos <= BUF_BEGV (b))
- sprintf (decode_mode_spec_buf, "Top%2d%%", total);
- else
- sprintf (decode_mode_spec_buf, "%2d%%", total);
- return decode_mode_spec_buf;
- }
- }
-
- case 's':
- /* status of process */
- obj = Fget_buffer_process (w->buffer);
- if (NILP (obj))
- return "no process";
-#ifdef subprocesses
- obj = Fsymbol_name (Fprocess_status (obj));
-#endif
- break;
-
- case 't': /* indicate TEXT or BINARY */
-#ifdef MODE_LINE_BINARY_TEXT
- return MODE_LINE_BINARY_TEXT (b);
-#else
- return "T";
-#endif
- }
-
- if (STRINGP (obj))
- return (char *) XSTRING (obj)->data;
- else
- return "";
-}
-
-/* Search for COUNT instances of a line boundary, which means either a
- newline or (if selective display enabled) a carriage return.
- Start at START. If COUNT is negative, search backwards.
-
- If we find COUNT instances, set *SHORTAGE to zero, and return the
- position after the COUNTth match. Note that for reverse motion
- this is not the same as the usual convention for Emacs motion commands.
-
- If we don't find COUNT instances before reaching the end of the
- buffer (or the beginning, if scanning backwards), set *SHORTAGE to
- the number of line boundaries left unfound, and return the end of the
- buffer we bumped up against. */
-
-static int
-display_scan_buffer (start, count, shortage)
- int *shortage, start;
- register int count;
-{
- int limit = ((count > 0) ? ZV - 1 : BEGV);
- int direction = ((count > 0) ? 1 : -1);
-
- register unsigned char *cursor;
- unsigned char *base;
-
- register int ceiling;
- register unsigned char *ceiling_addr;
-
- /* If we are not in selective display mode,
- check only for newlines. */
- if (! (!NILP (current_buffer->selective_display)
- && !INTEGERP (current_buffer->selective_display)))
- return scan_buffer ('\n', start, 0, count, shortage, 0);
-
- /* The code that follows is like scan_buffer
- but checks for either newline or carriage return. */
-
- if (shortage != 0)
- *shortage = 0;
-
- if (count > 0)
- while (start != limit + 1)
- {
- ceiling = BUFFER_CEILING_OF (start);
- ceiling = min (limit, ceiling);
- ceiling_addr = &FETCH_CHAR (ceiling) + 1;
- base = (cursor = &FETCH_CHAR (start));
- while (1)
- {
- while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
- ;
- if (cursor != ceiling_addr)
- {
- if (--count == 0)
- {
- immediate_quit = 0;
- return (start + cursor - base + 1);
- }
- else
- if (++cursor == ceiling_addr)
- break;
- }
- else
- break;
- }
- start += cursor - base;
- }
- else
- {
- start--; /* first character we scan */
- while (start > limit - 1)
- { /* we WILL scan under start */
- ceiling = BUFFER_FLOOR_OF (start);
- ceiling = max (limit, ceiling);
- ceiling_addr = &FETCH_CHAR (ceiling) - 1;
- base = (cursor = &FETCH_CHAR (start));
- cursor++;
- while (1)
- {
- while (--cursor != ceiling_addr
- && *cursor != '\n' && *cursor != 015)
- ;
- if (cursor != ceiling_addr)
- {
- if (++count == 0)
- {
- immediate_quit = 0;
- return (start + cursor - base + 1);
- }
- }
- else
- break;
- }
- start += cursor - base;
- }
- }
-
- if (shortage != 0)
- *shortage = count * direction;
- return (start + ((direction == 1 ? 0 : 1)));
-}
-
-/* Count up to N lines starting from FROM.
- But don't go beyond LIMIT.
- Return the number of lines thus found (always positive).
- Store the position after what was found into *POS_PTR. */
-
-static int
-display_count_lines (from, limit, n, pos_ptr)
- int from, limit, n;
- int *pos_ptr;
-{
- int oldbegv = BEGV;
- int oldzv = ZV;
- int shortage = 0;
-
- if (limit < from)
- BEGV = limit;
- else
- ZV = limit;
-
- *pos_ptr = display_scan_buffer (from, n, &shortage);
-
- ZV = oldzv;
- BEGV = oldbegv;
-
- if (n < 0)
- /* When scanning backwards, scan_buffer stops *after* the last newline
- it finds, but does count it. Compensate for that. */
- return - n - shortage - (*pos_ptr != limit);
- return n - shortage;
-}
-
-/* Display STRING on one line of window W, starting at HPOS.
- Display at position VPOS. Caller should have done get_display_line.
- If VPOS == -1, display it as the current frame's title.
- LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
-
- TRUNCATE is GLYPH 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 frame, 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.
-
- OBEY_WINDOW_WIDTH says to put spaces or vertical bars
- at the place where the current window ends in this line
- and not display anything beyond there. Otherwise, only MAXCOL
- controls where to stop output.
-
- Returns ending hpos. */
-
-static int
-display_string (w, vpos, string, length, hpos, truncate,
- obey_window_width, mincol, maxcol)
- struct window *w;
- unsigned char *string;
- int length;
- int vpos, hpos;
- GLYPH truncate;
- int obey_window_width;
- int mincol, maxcol;
-{
- register int c;
- int truncated;
- register GLYPH *p1;
- int hscroll = XINT (w->hscroll);
- int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
- register GLYPH *start;
- register GLYPH *end;
- FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
- struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
- GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
- int window_width = XFASTINT (w->width);
-
- /* Use the standard display table, not the window's display table.
- We don't want the mode line in rot13. */
- register struct Lisp_Char_Table *dp = 0;
- int i;
-
- if (DISP_TABLE_P (Vstandard_display_table))
- dp = XCHAR_TABLE (Vstandard_display_table);
-
- if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
-
- p1 = p1start;
- start = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
-
- if (obey_window_width)
- {
- end = start + window_width - (truncate != 0);
-
- if (!WINDOW_RIGHTMOST_P (w))
- {
- if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
- {
- int i;
-
- for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
- *end-- = ' ';
- }
- else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- *end-- = '|';
- }
- }
-
- if (! obey_window_width
- || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
- end = desired_glyphs->glyphs[vpos] + maxcol;
-
- /* Store 0 in charstart for these columns. */
- for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++)
- desired_glyphs->charstarts[vpos][i] = 0;
-
- if (maxcol >= 0 && mincol > maxcol)
- mincol = maxcol;
-
- /* We set truncated to 1 if we get stopped by trying to pass END
- (that is, trying to pass MAXCOL.) */
- truncated = 0;
- while (1)
- {
- if (length == 0)
- break;
- c = *string++;
- /* Specified length. */
- if (length >= 0)
- length--;
- /* Unspecified length (null-terminated string). */
- else if (c == 0)
- break;
-
- if (p1 >= end)
- {
- truncated = 1;
- break;
- }
-
- if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
- {
- p1 = copy_part_of_rope (f, p1, start,
- XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
- XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
- 0);
- }
- else if (c >= 040 && c < 0177)
- {
- if (p1 >= start)
- *p1 = c;
- p1++;
- }
- else if (c == '\t')
- {
- do
- {
- if (p1 >= start && p1 < end)
- *p1 = SPACEGLYPH;
- p1++;
- }
- while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
- }
- else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
- {
- if (p1 >= start)
- *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
- ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
- 0);
- p1++;
- if (p1 >= start && p1 < end)
- *p1 = c ^ 0100;
- p1++;
- }
- else
- {
- if (p1 >= start)
- *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
- ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
- 0);
- 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 (truncated)
- {
- p1 = end;
- if (truncate) *p1++ = fix_glyph (f, truncate, 0);
- }
- else if (mincol >= 0)
- {
- end = desired_glyphs->glyphs[vpos] + mincol;
- while (p1 < end)
- *p1++ = SPACEGLYPH;
- }
-
- {
- register int len = p1 - desired_glyphs->glyphs[vpos];
-
- if (len > desired_glyphs->used[vpos])
- desired_glyphs->used[vpos] = len;
- desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
-
- return len;
- }
-}
-
-/* This is like a combination of memq and assq.
- Return 1 if PROPVAL appears as an element of LIST
- or as the car of an element of LIST.
- If PROPVAL is a list, compare each element against LIST
- in that way, and return 1 if any element of PROPVAL is found in LIST.
- Otherwise return 0.
- This function cannot quit. */
-
-int
-invisible_p (propval, list)
- register Lisp_Object propval;
- Lisp_Object list;
-{
- register Lisp_Object tail, proptail;
- for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- register Lisp_Object tem;
- tem = XCONS (tail)->car;
- if (EQ (propval, tem))
- return 1;
- if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
- return 1;
- }
- if (CONSP (propval))
- for (proptail = propval; CONSP (proptail);
- proptail = XCONS (proptail)->cdr)
- {
- Lisp_Object propelt;
- propelt = XCONS (proptail)->car;
- for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- register Lisp_Object tem;
- tem = XCONS (tail)->car;
- if (EQ (propelt, tem))
- return 1;
- if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
- return 1;
- }
- }
- return 0;
-}
-
-/* Return 1 if PROPVAL appears as the car of an element of LIST
- and the cdr of that element is non-nil.
- If PROPVAL is a list, check each element of PROPVAL in that way,
- and the first time some element is found,
- return 1 if the cdr of that element is non-nil.
- Otherwise return 0.
- This function cannot quit. */
-
-int
-invisible_ellipsis_p (propval, list)
- register Lisp_Object propval;
- Lisp_Object list;
-{
- register Lisp_Object tail, proptail;
- for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- register Lisp_Object tem;
- tem = XCONS (tail)->car;
- if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
- return ! NILP (XCONS (tem)->cdr);
- }
- if (CONSP (propval))
- for (proptail = propval; CONSP (proptail);
- proptail = XCONS (proptail)->cdr)
- {
- Lisp_Object propelt;
- propelt = XCONS (proptail)->car;
- for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- register Lisp_Object tem;
- tem = XCONS (tail)->car;
- if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
- return ! NILP (XCONS (tem)->cdr);
- }
- }
- return 0;
-}
-
-void
-syms_of_xdisp ()
-{
- staticpro (&Qmenu_bar_update_hook);
- Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
-
- staticpro (&Qoverriding_terminal_local_map);
- Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
-
- staticpro (&Qoverriding_local_map);
- Qoverriding_local_map = intern ("overriding-local-map");
-
- staticpro (&Qwindow_scroll_functions);
- Qwindow_scroll_functions = intern ("window-scroll-functions");
-
- staticpro (&Qredisplay_end_trigger_functions);
- Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
-
- 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 (or mode line construct) included (normally) in `mode-line-format'.");
- 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 frame, point is centered instead.\n\
-If this is zero, point is always centered after it moves off frame.");
-
- DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
- "*Scroll up to this many lines, to bring point back on screen.");
- scroll_conservatively = 0;
-
- DEFVAR_INT ("scroll-margin", &scroll_margin,
- "*Number of lines of margin at the top and bottom of a window.\n\
-Recenter the window whenever point gets within this many lines\n\
-of the top or bottom of the window.");
- scroll_margin = 0;
-
- 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 frame wide.");
- truncate_partial_width_windows = 1;
-
- DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
- "*Non-nil means use inverse video for the mode line.");
- mode_line_inverse_video = 1;
-
- DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
- "*Maximum buffer size for which line number should be displayed.");
- line_number_display_limit = 1000000;
-
- DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
- "*Non-nil means highlight region even in nonselected windows.");
- highlight_nonselected_windows = 1;
-
- DEFVAR_BOOL ("multiple-frames", &multiple_frames,
- "Non-nil if more than one frame is visible on this display.\n\
-Minibuffer-only frames don't count, but iconified frames do.\n\
-This variable is not guaranteed to be accurate except while processing\n\
-`frame-title-format' and `icon-title-format'.");
-
- DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
- "Template for displaying the titlebar of visible frames.\n\
-\(Assuming the window manager supports this feature.)\n\
-This variable has the same structure as `mode-line-format' (which see),\n\
-and is used only on frames for which no explicit name has been set\n\
-\(see `modify-frame-parameters').");
- DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
- "Template for displaying the titlebar of an iconified frame.\n\
-\(Assuming the window manager supports this feature.)\n\
-This variable has the same structure as `mode-line-format' (which see),\n\
-and is used only on frames for which no explicit name has been set\n\
-\(see `modify-frame-parameters').");
- Vicon_title_format
- = Vframe_title_format
- = Fcons (intern ("multiple-frames"),
- Fcons (build_string ("%b"),
- Fcons (Fcons (build_string (""),
- Fcons (intern ("invocation-name"),
- Fcons (build_string ("@"),
- Fcons (intern ("system-name"),
- Qnil)))),
- Qnil)));
-
- DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
- "Maximum number of lines to keep in the message log buffer.\n\
-If nil, disable message logging. If t, log messages but don't truncate\n\
-the buffer when it becomes large.");
- XSETFASTINT (Vmessage_log_max, 50);
-
- DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
- "Functions called before redisplay, if window sizes have changed.\n\
-The value should be a list of functions that take one argument.\n\
-Just before redisplay, for each frame, if any of its windows have changed\n\
-size since the last redisplay, or have been split or deleted,\n\
-all the functions in the list are called, with the frame as argument.");
- Vwindow_size_change_functions = Qnil;
-
- DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
- "List of Functions to call before redisplaying a window with scrolling.\n\
-Each function is called with two arguments, the window\n\
-and its new display-start position. Note that the value of `window-end'\n\
-is not valid when these functions are called.");
- Vwindow_scroll_functions = Qnil;
-}
-
-/* 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 = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
-
- echo_area_glyphs = 0;
- previous_echo_glyphs = 0;
-
- if (!noninteractive)
- {
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
- XSETFASTINT (XWINDOW (root_window)->top, 0);
- set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0);
- XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
- set_window_height (minibuf_window, 1, 0);
-
- XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
- XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
- }
-}
diff --git a/src/xfaces.c b/src/xfaces.c
deleted file mode 100644
index 6e34bf4b24f..00000000000
--- a/src/xfaces.c
+++ /dev/null
@@ -1,1277 +0,0 @@
-/* "Face" primitives.
- Copyright (C) 1993, 1994 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* This is derived from work by Lucid (some parts very loosely so). */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <config.h>
-#include "lisp.h"
-
-#ifdef HAVE_FACES
-
-#ifdef HAVE_X_WINDOWS
-#include "xterm.h"
-#endif
-#ifdef MSDOS
-#include "dosfns.h"
-#endif
-#include "buffer.h"
-#include "dispextern.h"
-#include "frame.h"
-#include "blockinput.h"
-#include "window.h"
-#include "intervals.h"
-
-#ifdef HAVE_X_WINDOWS
-/* Compensate for bug in Xos.h on some systems, on which it requires
- time.h. On some such systems, Xos.h tries to redefine struct
- timeval and struct timezone if USG is #defined while it is
- #included. */
-#ifdef XOS_NEEDS_TIME_H
-
-#include <time.h>
-#undef USG
-#include <X11/Xos.h>
-#define USG
-#define __TIMEVAL__
-
-#else
-
-#include <X11/Xos.h>
-
-#endif
-#endif /* HAVE_X_WINDOWS */
-
-/* An explanation of the face data structures. */
-
-/* ========================= Face Data Structures =========================
-
- Let FACE-NAME be a symbol naming a face.
-
- Let FACE-VECTOR be (assq FACE-NAME (frame-face-alist FRAME))
- FACE-VECTOR is either nil, or a vector of the form
- [face NAME ID FONT FOREGROUND BACKGROUND BACKGROUND-PIXMAP UNDERLINE-P]
- where
- face is the symbol `face',
- NAME is the symbol with which this vector is associated (a backpointer),
- ID is the face ID, an integer used internally by the C code to identify
- the face,
- FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors
- to use with the face,
- BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
- use right now, and
- UNDERLINE-P is non-nil if the face should be underlined.
- If any of these elements are nil, that parameter is considered
- unspecified; parameters from faces specified by lower-priority
- overlays or text properties, or the parameters of the frame itself,
- can show through. (lisp/faces.el maintains these lists.)
-
- (assq FACE-NAME global-face-data) returns a vector describing the
- global parameters for that face.
-
- Let PARAM-FACE be FRAME->output_data.x->param_faces[Faref (FACE-VECTOR, 2)].
- PARAM_FACE is a struct face whose members are the Xlib analogues of
- the parameters in FACE-VECTOR. If an element of FACE-VECTOR is
- nil, then the corresponding member of PARAM_FACE is FACE_DEFAULT.
- These faces are called "parameter faces", because they're the ones
- lisp manipulates to control what gets displayed. Elements 0 and 1
- of FRAME->output_data.x->param_faces are special - they describe the
- default and mode line faces. None of the faces in param_faces have
- GC's. (See src/dispextern.h for the definition of struct face.
- lisp/faces.el maintains the isomorphism between face_alist and
- param_faces.)
-
- The functions compute_char_face and compute_glyph_face find and
- combine the parameter faces associated with overlays and text
- properties. The resulting faces are called "computed faces"; none
- of their members are FACE_DEFAULT; they are completely specified.
- They then call intern_compute_face to search
- FRAME->output_data.x->computed_faces for a matching face, add one if
- none is found, and return the index into
- FRAME->output_data.x->computed_faces. FRAME's glyph matrices use these
- indices to record the faces of the matrix characters, and the X
- display hooks consult compute_faces to decide how to display these
- characters. Elements 0 and 1 of computed_faces always describe the
- default and mode-line faces.
-
- Each computed face belongs to a particular frame.
-
- Computed faces have graphics contexts some of the time.
- intern_face builds a GC for a specified computed face
- if it doesn't have one already.
- clear_face_cache clears out the GCs of all computed faces.
- This is done from time to time so that we don't hold on to
- lots of GCs that are no longer needed.
-
- If a computed face has 0 as its font,
- it is unused, and can be reused by new_computed_face.
-
- Constraints:
-
- Symbols naming faces must have associations on all frames; for any
- FRAME, for all FACE-NAME, if (assq FACE-NAME (frame-face-alist
- FRAME)) is non-nil, it must be non-nil for all frames.
-
- Analogously, indices into param_faces must be valid on all frames;
- if param_faces[i] is a non-zero face pointer on one frame, then it
- must be filled in on all frames. Code assumes that face ID's can
- be used on any frame.
-
- Some subtleties:
-
- Why do we keep param_faces and computed_faces separate?
- computed_faces contains an element for every combination of facial
- parameters we have ever displayed. indices into param_faces have
- to be valid on all frames. If they were the same array, then that
- array would grow very large on all frames, because any facial
- combination displayed on any frame would need to be a valid entry
- on all frames. */
-
-/* Definitions and declarations. */
-
-/* The number of face-id's in use (same for all frames). */
-static int next_face_id;
-
-/* The number of the face to use to indicate the region. */
-static int region_face;
-
-/* This is what appears in a slot in a face to signify that the face
- does not specify that display aspect. */
-#define FACE_DEFAULT (~0)
-
-Lisp_Object Qface, Qmouse_face;
-Lisp_Object Qpixmap_spec_p;
-
-int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ );
-
-struct face *intern_face ( /* FRAME_PTR, struct face * */ );
-static int new_computed_face ( /* FRAME_PTR, struct face * */ );
-static int intern_computed_face ( /* FRAME_PTR, struct face * */ );
-static void ensure_face_ready ( /* FRAME_PTR, int id */ );
-void recompute_basic_faces ( /* FRAME_PTR f */ );
-
-/* Allocating, copying, and comparing struct faces. */
-
-/* Allocate a new face */
-static struct face *
-allocate_face ()
-{
- struct face *result = (struct face *) xmalloc (sizeof (struct face));
- bzero (result, sizeof (struct face));
- result->font = (XFontStruct *) FACE_DEFAULT;
- result->foreground = FACE_DEFAULT;
- result->background = FACE_DEFAULT;
- result->stipple = FACE_DEFAULT;
- return result;
-}
-
-/* Make a new face that's a copy of an existing one. */
-static struct face *
-copy_face (face)
- struct face *face;
-{
- struct face *result = allocate_face ();
-
- result->font = face->font;
- result->foreground = face->foreground;
- result->background = face->background;
- result->stipple = face->stipple;
- result->underline = face->underline;
- result->pixmap_h = face->pixmap_h;
- result->pixmap_w = face->pixmap_w;
-
- return result;
-}
-
-static int
-face_eql (face1, face2)
- struct face *face1, *face2;
-{
- return ( face1->font == face2->font
- && face1->foreground == face2->foreground
- && face1->background == face2->background
- && face1->stipple == face2->stipple
- && face1->underline == face2->underline);
-}
-
-/* Managing graphics contexts of faces. */
-
-#ifdef HAVE_X_WINDOWS
-/* Given a computed face, construct its graphics context if necessary. */
-
-struct face *
-intern_face (f, face)
- struct frame *f;
- struct face *face;
-{
- GC gc;
- XGCValues xgcv;
- unsigned long mask;
-
- if (face->gc)
- return face;
-
- BLOCK_INPUT;
-
- if (face->foreground != FACE_DEFAULT)
- xgcv.foreground = face->foreground;
- else
- xgcv.foreground = f->output_data.x->foreground_pixel;
-
- if (face->background != FACE_DEFAULT)
- xgcv.background = face->background;
- else
- xgcv.background = f->output_data.x->background_pixel;
-
- if (face->font && face->font != (XFontStruct *) FACE_DEFAULT)
- xgcv.font = face->font->fid;
- else
- xgcv.font = f->output_data.x->font->fid;
-
- xgcv.graphics_exposures = 0;
-
- mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
- if (face->stipple && face->stipple != FACE_DEFAULT)
- {
- xgcv.fill_style = FillStippled;
- xgcv.stipple = x_bitmap_pixmap (f, face->stipple);
- mask |= GCFillStyle | GCStipple;
- }
-
- gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- mask, &xgcv);
-
- face->gc = gc;
-
- UNBLOCK_INPUT;
-
- return face;
-}
-
-/* Clear out all graphics contexts for all computed faces
- except for the default and mode line faces.
- This should be done from time to time just to avoid
- keeping too many graphics contexts that are no longer needed. */
-
-void
-clear_face_cache ()
-{
- Lisp_Object tail, frame;
-
- BLOCK_INPUT;
- FOR_EACH_FRAME (tail, frame)
- {
- FRAME_PTR f = XFRAME (frame);
- if (FRAME_X_P (f))
- {
- int i;
- Display *dpy = FRAME_X_DISPLAY (f);
-
- for (i = 2; i < FRAME_N_COMPUTED_FACES (f); i++)
- {
- struct face *face = FRAME_COMPUTED_FACES (f) [i];
- if (face->gc)
- XFreeGC (dpy, face->gc);
- face->gc = 0;
- }
- }
- }
-
- UNBLOCK_INPUT;
-}
-
-/* Allocating, freeing, and duplicating fonts, colors, and pixmaps.
-
- These functions operate on param faces only.
- Computed faces get their fonts, colors and pixmaps
- by merging param faces. */
-
-static XFontStruct *
-load_font (f, name)
- struct frame *f;
- Lisp_Object name;
-{
- XFontStruct *font;
-
- if (NILP (name))
- return (XFontStruct *) FACE_DEFAULT;
-
- CHECK_STRING (name, 0);
- BLOCK_INPUT;
- font = XLoadQueryFont (FRAME_X_DISPLAY (f), (char *) XSTRING (name)->data);
- UNBLOCK_INPUT;
-
- if (! font)
- Fsignal (Qerror, Fcons (build_string ("undefined font"),
- Fcons (name, Qnil)));
- return font;
-}
-
-static void
-unload_font (f, font)
- struct frame *f;
- XFontStruct *font;
-{
- int len = FRAME_N_COMPUTED_FACES (f);
- int i;
-
- if (!font || font == ((XFontStruct *) FACE_DEFAULT))
- return;
-
- BLOCK_INPUT;
- /* Invalidate any computed faces which use this font,
- and free their GC's if they have any. */
- for (i = 2; i < len; i++)
- {
- struct face *face = FRAME_COMPUTED_FACES (f)[i];
- if (face->font == font)
- {
- Display *dpy = FRAME_X_DISPLAY (f);
- if (face->gc)
- XFreeGC (dpy, face->gc);
- face->gc = 0;
- /* This marks the computed face as available to reuse. */
- face->font = 0;
- }
- }
-
- XFreeFont (FRAME_X_DISPLAY (f), font);
- UNBLOCK_INPUT;
-}
-
-static unsigned long
-load_color (f, name)
- struct frame *f;
- Lisp_Object name;
-{
- XColor color;
- int result;
-
- if (NILP (name))
- return FACE_DEFAULT;
-
- CHECK_STRING (name, 0);
- /* if the colormap is full, defined_color will return a best match
- to the values in an an existing cell. */
- result = defined_color(f, (char *) XSTRING (name)->data, &color, 1);
- if (! result)
- Fsignal (Qerror, Fcons (build_string ("undefined color"),
- Fcons (name, Qnil)));
- return (unsigned long) color.pixel;
-}
-
-static void
-unload_color (f, pixel)
- struct frame *f;
- unsigned long pixel;
-{
- Colormap cmap;
- Display *dpy = FRAME_X_DISPLAY (f);
- int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
-
- if (pixel == FACE_DEFAULT
- || pixel == BLACK_PIX_DEFAULT (f)
- || pixel == WHITE_PIX_DEFAULT (f))
- return;
- cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (dpy));
-
- /* If display has an immutable color map, freeing colors is not
- necessary and some servers don't allow it. So don't do it. */
- if (! (class == StaticColor || class == StaticGray || class == TrueColor))
- {
- int len = FRAME_N_COMPUTED_FACES (f);
- int i;
-
- BLOCK_INPUT;
- /* Invalidate any computed faces which use this color,
- and free their GC's if they have any. */
- for (i = 2; i < len; i++)
- {
- struct face *face = FRAME_COMPUTED_FACES (f)[i];
- if (face->foreground == pixel
- || face->background == pixel)
- {
- Display *dpy = FRAME_X_DISPLAY (f);
- if (face->gc)
- XFreeGC (dpy, face->gc);
- face->gc = 0;
- /* This marks the computed face as available to reuse. */
- face->font = 0;
- }
- }
-
- XFreeColors (dpy, cmap, &pixel, 1, (unsigned long)0);
- UNBLOCK_INPUT;
- }
-}
-
-DEFUN ("pixmap-spec-p", Fpixmap_spec_p, Spixmap_spec_p, 1, 1, 0,
- "Return t if OBJECT is a valid pixmap specification.")
- (object)
- Lisp_Object object;
-{
- Lisp_Object height, width;
-
- return ((STRINGP (object)
- || (CONSP (object)
- && CONSP (XCONS (object)->cdr)
- && CONSP (XCONS (XCONS (object)->cdr)->cdr)
- && NILP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->cdr)
- && (width = XCONS (object)->car, INTEGERP (width))
- && (height = XCONS (XCONS (object)->cdr)->car, INTEGERP (height))
- && STRINGP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)
- && XINT (width) > 0
- && XINT (height) > 0
- /* The string must have enough bits for width * height. */
- && ((XSTRING (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)->size
- * (BITS_PER_INT / sizeof (int)))
- >= XFASTINT (width) * XFASTINT (height))))
- ? Qt : Qnil);
-}
-
-/* Load a bitmap according to NAME (which is either a file name
- or a pixmap spec). Return the bitmap_id (see xfns.c)
- or get an error if NAME is invalid.
-
- Store the bitmap width in *W_PTR and height in *H_PTR. */
-
-static long
-load_pixmap (f, name, w_ptr, h_ptr)
- FRAME_PTR f;
- Lisp_Object name;
- unsigned int *w_ptr, *h_ptr;
-{
- int bitmap_id;
- Lisp_Object tem;
-
- if (NILP (name))
- return FACE_DEFAULT;
-
- tem = Fpixmap_spec_p (name);
- if (NILP (tem))
- wrong_type_argument (Qpixmap_spec_p, name);
-
- BLOCK_INPUT;
-
- if (CONSP (name))
- {
- /* Decode a bitmap spec into a bitmap. */
-
- int h, w;
- Lisp_Object bits;
-
- w = XINT (Fcar (name));
- h = XINT (Fcar (Fcdr (name)));
- bits = Fcar (Fcdr (Fcdr (name)));
-
- bitmap_id = x_create_bitmap_from_data (f, XSTRING (bits)->data,
- w, h);
- }
- else
- {
- /* It must be a string -- a file name. */
- bitmap_id = x_create_bitmap_from_file (f, name);
- }
- UNBLOCK_INPUT;
-
- if (bitmap_id < 0)
- Fsignal (Qerror, Fcons (build_string ("invalid or undefined bitmap"),
- Fcons (name, Qnil)));
-
- *w_ptr = x_bitmap_width (f, bitmap_id);
- *h_ptr = x_bitmap_height (f, bitmap_id);
-
- return bitmap_id;
-}
-
-#else /* !HAVE_X_WINDOWS */
-
-/* Stubs for MSDOS when not under X. */
-
-struct face *
-intern_face (f, face)
- struct frame *f;
- struct face *face;
-{
- return face;
-}
-
-void
-clear_face_cache ()
-{
- /* No action. */
-}
-
-#ifdef MSDOS
-unsigned long
-load_color (f, name)
- FRAME_PTR f;
- Lisp_Object name;
-{
- Lisp_Object result;
-
- if (NILP (name))
- return FACE_DEFAULT;
-
- CHECK_STRING (name, 0);
- result = call1 (Qmsdos_color_translate, name);
- if (INTEGERP (result))
- return XINT (result);
- else
- Fsignal (Qerror, Fcons (build_string ("undefined color"),
- Fcons (name, Qnil)));
-}
-#endif
-#endif /* !HAVE_X_WINDOWS */
-
-
-/* Managing parameter face arrays for frames. */
-
-void
-init_frame_faces (f)
- FRAME_PTR f;
-{
- ensure_face_ready (f, 0);
- ensure_face_ready (f, 1);
-
- FRAME_N_COMPUTED_FACES (f) = 0;
- FRAME_SIZE_COMPUTED_FACES (f) = 0;
-
- new_computed_face (f, FRAME_PARAM_FACES (f)[0]);
- new_computed_face (f, FRAME_PARAM_FACES (f)[1]);
- recompute_basic_faces (f);
-
- /* Find another X frame. */
- {
- Lisp_Object tail, frame, result;
-
- result = Qnil;
- FOR_EACH_FRAME (tail, frame)
- if ((FRAME_MSDOS_P (XFRAME (frame)) || FRAME_X_P (XFRAME (frame)))
- && XFRAME (frame) != f)
- {
- result = frame;
- break;
- }
-
- /* If we didn't find any X frames other than f, then we don't need
- any faces other than 0 and 1, so we're okay. Otherwise, make
- sure that all faces valid on the selected frame are also valid
- on this new frame. */
- if (FRAMEP (result))
- {
- int i;
- int n_faces = FRAME_N_PARAM_FACES (XFRAME (result));
- struct face **faces = FRAME_PARAM_FACES (XFRAME (result));
-
- for (i = 2; i < n_faces; i++)
- if (faces[i])
- ensure_face_ready (f, i);
- }
- }
-}
-
-
-/* Called from Fdelete_frame. */
-
-void
-free_frame_faces (f)
- struct frame *f;
-{
- Display *dpy = FRAME_X_DISPLAY (f);
- int i;
-
- BLOCK_INPUT;
-
- for (i = 0; i < FRAME_N_PARAM_FACES (f); i++)
- {
- struct face *face = FRAME_PARAM_FACES (f) [i];
- if (face)
- {
- unload_font (f, face->font);
- unload_color (f, face->foreground);
- unload_color (f, face->background);
- x_destroy_bitmap (f, face->stipple);
- xfree (face);
- }
- }
- xfree (FRAME_PARAM_FACES (f));
- FRAME_PARAM_FACES (f) = 0;
- FRAME_N_PARAM_FACES (f) = 0;
-
- /* All faces in FRAME_COMPUTED_FACES use resources copied from
- FRAME_PARAM_FACES; we can free them without fuss.
- But we do free the GCs and the face objects themselves. */
- for (i = 0; i < FRAME_N_COMPUTED_FACES (f); i++)
- {
- struct face *face = FRAME_COMPUTED_FACES (f) [i];
- if (face)
- {
- if (face->gc)
- XFreeGC (dpy, face->gc);
- xfree (face);
- }
- }
- xfree (FRAME_COMPUTED_FACES (f));
- FRAME_COMPUTED_FACES (f) = 0;
- FRAME_N_COMPUTED_FACES (f) = 0;
-
- UNBLOCK_INPUT;
-}
-
-/* Interning faces in a frame's face array. */
-
-static int
-new_computed_face (f, new_face)
- struct frame *f;
- struct face *new_face;
-{
- int len = FRAME_N_COMPUTED_FACES (f);
- int i;
-
- /* Search for an unused computed face in the middle of the table. */
- for (i = 0; i < len; i++)
- {
- struct face *face = FRAME_COMPUTED_FACES (f)[i];
- if (face->font == 0)
- {
- FRAME_COMPUTED_FACES (f)[i] = copy_face (new_face);
- return i;
- }
- }
-
- if (i >= FRAME_SIZE_COMPUTED_FACES (f))
- {
- int new_size = i + 32;
-
- FRAME_COMPUTED_FACES (f)
- = (struct face **) (FRAME_SIZE_COMPUTED_FACES (f) == 0
- ? xmalloc (new_size * sizeof (struct face *))
- : xrealloc (FRAME_COMPUTED_FACES (f),
- new_size * sizeof (struct face *)));
- FRAME_SIZE_COMPUTED_FACES (f) = new_size;
- }
-
- i = FRAME_N_COMPUTED_FACES (f)++;
- FRAME_COMPUTED_FACES (f)[i] = copy_face (new_face);
- return i;
-}
-
-
-/* Find a match for NEW_FACE in a FRAME's computed face array, and add
- it if we don't find one. */
-static int
-intern_computed_face (f, new_face)
- struct frame *f;
- struct face *new_face;
-{
- int len = FRAME_N_COMPUTED_FACES (f);
- int i;
-
- /* Search for a computed face already on F equivalent to FACE. */
- for (i = 0; i < len; i++)
- {
- if (! FRAME_COMPUTED_FACES (f)[i])
- abort ();
- if (face_eql (new_face, FRAME_COMPUTED_FACES (f)[i]))
- return i;
- }
-
- /* We didn't find one; add a new one. */
- return new_computed_face (f, new_face);
-}
-
-/* Make parameter face id ID valid on frame F. */
-
-static void
-ensure_face_ready (f, id)
- struct frame *f;
- int id;
-{
- if (FRAME_N_PARAM_FACES (f) <= id)
- {
- int n = id + 10;
- int i;
- if (!FRAME_N_PARAM_FACES (f))
- FRAME_PARAM_FACES (f)
- = (struct face **) xmalloc (sizeof (struct face *) * n);
- else
- FRAME_PARAM_FACES (f)
- = (struct face **) xrealloc (FRAME_PARAM_FACES (f),
- sizeof (struct face *) * n);
-
- bzero (FRAME_PARAM_FACES (f) + FRAME_N_PARAM_FACES (f),
- (n - FRAME_N_PARAM_FACES (f)) * sizeof (struct face *));
- FRAME_N_PARAM_FACES (f) = n;
- }
-
- if (FRAME_PARAM_FACES (f) [id] == 0)
- FRAME_PARAM_FACES (f) [id] = allocate_face ();
-}
-
-#ifdef HAVE_X_WINDOWS
-/* Return non-zero if FONT1 and FONT2 have the same width.
- We do not check the height, because we can now deal with
- different heights.
- We assume that they're both character-cell fonts. */
-
-int
-same_size_fonts (font1, font2)
- XFontStruct *font1, *font2;
-{
- XCharStruct *bounds1 = &font1->min_bounds;
- XCharStruct *bounds2 = &font2->min_bounds;
-
- return (bounds1->width == bounds2->width);
-}
-
-/* Update the line_height of frame F according to the biggest font in
- any face. Return nonzero if if line_height changes. */
-
-int
-frame_update_line_height (f)
- FRAME_PTR f;
-{
- int i;
- int biggest = FONT_HEIGHT (f->output_data.x->font);
-
- for (i = 0; i < f->output_data.x->n_param_faces; i++)
- if (f->output_data.x->param_faces[i] != 0
- && f->output_data.x->param_faces[i]->font != (XFontStruct *) FACE_DEFAULT)
- {
- int height = FONT_HEIGHT (f->output_data.x->param_faces[i]->font);
- if (height > biggest)
- biggest = height;
- }
-
- if (biggest == f->output_data.x->line_height)
- return 0;
-
- f->output_data.x->line_height = biggest;
- return 1;
-}
-#endif /* not HAVE_X_WINDOWS */
-
-/* Modify face TO by copying from FROM all properties which have
- nondefault settings. */
-
-static void
-merge_faces (from, to)
- struct face *from, *to;
-{
- /* Only merge the font if it's the same width as the base font.
- Otherwise ignore it, since we can't handle it properly. */
- if (from->font != (XFontStruct *) FACE_DEFAULT
- && same_size_fonts (from->font, to->font))
- to->font = from->font;
- if (from->foreground != FACE_DEFAULT)
- to->foreground = from->foreground;
- if (from->background != FACE_DEFAULT)
- to->background = from->background;
- if (from->stipple != FACE_DEFAULT)
- {
- to->stipple = from->stipple;
- to->pixmap_h = from->pixmap_h;
- to->pixmap_w = from->pixmap_w;
- }
- if (from->underline)
- to->underline = from->underline;
-}
-
-/* Set up the basic set of facial parameters, based on the frame's
- data; all faces are deltas applied to this. */
-
-static void
-compute_base_face (f, face)
- FRAME_PTR f;
- struct face *face;
-{
- face->gc = 0;
- face->foreground = FRAME_FOREGROUND_PIXEL (f);
- face->background = FRAME_BACKGROUND_PIXEL (f);
- face->font = FRAME_FONT (f);
- face->stipple = 0;
- face->underline = 0;
-}
-
-/* Return the face ID to use to display a special glyph which selects
- FACE_CODE as the face ID, assuming that ordinarily the face would
- be CURRENT_FACE. F is the frame. */
-
-int
-compute_glyph_face (f, face_code, current_face)
- struct frame *f;
- int face_code, current_face;
-{
- struct face face;
-
- face = *FRAME_COMPUTED_FACES (f)[current_face];
-
- if (face_code >= 0 && face_code < FRAME_N_PARAM_FACES (f)
- && FRAME_PARAM_FACES (f) [face_code] != 0)
- merge_faces (FRAME_PARAM_FACES (f) [face_code], &face);
-
- return intern_computed_face (f, &face);
-}
-
-/* Return the face ID to use to display a special glyph which selects
- FACE_CODE as the face ID, assuming that ordinarily the face would
- be CURRENT_FACE. F is the frame. */
-
-int
-compute_glyph_face_1 (f, face_name, current_face)
- struct frame *f;
- Lisp_Object face_name;
- int current_face;
-{
- struct face face;
-
- face = *FRAME_COMPUTED_FACES (f)[current_face];
-
- if (!NILP (face_name))
- {
- int facecode = face_name_id_number (f, face_name);
- if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
- && FRAME_PARAM_FACES (f) [facecode] != 0)
- merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
- }
-
- return intern_computed_face (f, &face);
-}
-
-/* Return the face ID associated with a buffer position POS.
- Store into *ENDPTR the position at which a different face is needed.
- This does not take account of glyphs that specify their own face codes.
- F is the frame in use for display, and W is a window displaying
- the current buffer.
-
- REGION_BEG, REGION_END delimit the region, so it can be highlighted.
-
- LIMIT is a position not to scan beyond. That is to limit
- the time this function can take.
-
- If MOUSE is nonzero, use the character's mouse-face, not its face. */
-
-int
-compute_char_face (f, w, pos, region_beg, region_end, endptr, limit, mouse)
- struct frame *f;
- struct window *w;
- int pos;
- int region_beg, region_end;
- int *endptr;
- int limit;
- int mouse;
-{
- struct face face;
- Lisp_Object prop, position;
- int i, j, noverlays;
- int facecode;
- Lisp_Object *overlay_vec;
- Lisp_Object frame;
- int endpos;
- Lisp_Object propname;
-
- /* W must display the current buffer. We could write this function
- to use the frame and buffer of W, but right now it doesn't. */
- if (XBUFFER (w->buffer) != current_buffer)
- abort ();
-
- XSETFRAME (frame, f);
-
- endpos = ZV;
- if (pos < region_beg && region_beg < endpos)
- endpos = region_beg;
-
- XSETFASTINT (position, pos);
-
- if (mouse)
- propname = Qmouse_face;
- else
- propname = Qface;
-
- prop = Fget_text_property (position, propname, w->buffer);
-
- {
- Lisp_Object limit1, end;
-
- XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
- end = Fnext_single_property_change (position, propname, w->buffer, limit1);
- if (INTEGERP (end))
- endpos = XINT (end);
- }
-
- {
- int next_overlay;
- int len;
-
- /* First try with room for 40 overlays. */
- len = 40;
- overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-
- noverlays = overlays_at (pos, 0, &overlay_vec, &len,
- &next_overlay, (int *) 0);
-
- /* If there are more than 40,
- make enough space for all, and try again. */
- if (noverlays > len)
- {
- len = noverlays;
- overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- noverlays = overlays_at (pos, 0, &overlay_vec, &len,
- &next_overlay, (int *) 0);
- }
-
- if (next_overlay < endpos)
- endpos = next_overlay;
- }
-
- *endptr = endpos;
-
- /* Optimize the default case. */
- if (noverlays == 0 && NILP (prop)
- && !(pos >= region_beg && pos < region_end))
- return 0;
-
- compute_base_face (f, &face);
-
- if (CONSP (prop))
- {
- /* We have a list of faces, merge them in reverse order */
- Lisp_Object length;
- int len;
- Lisp_Object *faces;
-
- length = Fsafe_length (prop);
- len = XFASTINT (length);
-
- /* Put them into an array */
- faces = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- for (j = 0; j < len; j++)
- {
- faces[j] = Fcar (prop);
- prop = Fcdr (prop);
- }
- /* So that we can merge them in the reverse order */
- for (j = len - 1; j >= 0; j--)
- {
- facecode = face_name_id_number (f, faces[j]);
- if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
- && FRAME_PARAM_FACES (f) [facecode] != 0)
- merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
- }
- }
- else if (!NILP (prop))
- {
- facecode = face_name_id_number (f, prop);
- if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
- && FRAME_PARAM_FACES (f) [facecode] != 0)
- merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
- }
-
- noverlays = sort_overlays (overlay_vec, noverlays, w);
-
- /* Now merge the overlay data in that order. */
- for (i = 0; i < noverlays; i++)
- {
- prop = Foverlay_get (overlay_vec[i], propname);
- if (CONSP (prop))
- {
- /* We have a list of faces, merge them in reverse order */
- Lisp_Object length;
- int len;
- Lisp_Object *faces;
-
- length = Fsafe_length (prop);
- len = XFASTINT (length);
-
- /* Put them into an array */
- faces = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- for (j = 0; j < len; j++)
- {
- faces[j] = Fcar (prop);
- prop = Fcdr (prop);
- }
- /* So that we can merge them in the reverse order */
- for (j = len - 1; j >= 0; j--)
- {
- facecode = face_name_id_number (f, faces[j]);
- if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
- && FRAME_PARAM_FACES (f) [facecode] != 0)
- merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
- }
- }
- else if (!NILP (prop))
- {
- Lisp_Object oend;
- int oendpos;
-
- facecode = face_name_id_number (f, prop);
- if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
- && FRAME_PARAM_FACES (f) [facecode] != 0)
- merge_faces (FRAME_PARAM_FACES (f)[facecode], &face);
-
- oend = OVERLAY_END (overlay_vec[i]);
- oendpos = OVERLAY_POSITION (oend);
- if (oendpos < endpos)
- endpos = oendpos;
- }
- }
-
- if (pos >= region_beg && pos < region_end)
- {
- if (region_end < endpos)
- endpos = region_end;
- if (region_face >= 0 && region_face < next_face_id)
- merge_faces (FRAME_PARAM_FACES (f)[region_face], &face);
- }
-
- *endptr = endpos;
-
- return intern_computed_face (f, &face);
-}
-
-/* Recompute the GC's for the default and modeline faces.
- We call this after changing frame parameters on which those GC's
- depend. */
-
-void
-recompute_basic_faces (f)
- FRAME_PTR f;
-{
- /* If the frame's faces haven't been initialized yet, don't worry about
- this stuff. */
- if (FRAME_N_PARAM_FACES (f) < 2)
- return;
-
- BLOCK_INPUT;
-
- if (FRAME_DEFAULT_FACE (f)->gc)
- XFreeGC (FRAME_X_DISPLAY (f), FRAME_DEFAULT_FACE (f)->gc);
- if (FRAME_MODE_LINE_FACE (f)->gc)
- XFreeGC (FRAME_X_DISPLAY (f), FRAME_MODE_LINE_FACE (f)->gc);
-
- compute_base_face (f, FRAME_DEFAULT_FACE (f));
- compute_base_face (f, FRAME_MODE_LINE_FACE (f));
-
- merge_faces (FRAME_DEFAULT_PARAM_FACE (f), FRAME_DEFAULT_FACE (f));
- merge_faces (FRAME_MODE_LINE_PARAM_FACE (f), FRAME_MODE_LINE_FACE (f));
-
- intern_face (f, FRAME_DEFAULT_FACE (f));
- intern_face (f, FRAME_MODE_LINE_FACE (f));
-
- UNBLOCK_INPUT;
-}
-
-
-
-/* Lisp interface. */
-
-DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
- "")
- (frame)
- Lisp_Object frame;
-{
- CHECK_FRAME (frame, 0);
- return XFRAME (frame)->face_alist;
-}
-
-DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
- 2, 2, 0, "")
- (frame, value)
- Lisp_Object frame, value;
-{
- CHECK_FRAME (frame, 0);
- XFRAME (frame)->face_alist = value;
- return value;
-}
-
-
-DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
- "Create face number FACE-ID on all frames.")
- (face_id)
- Lisp_Object face_id;
-{
- Lisp_Object rest, frame;
- int id = XINT (face_id);
-
- CHECK_NUMBER (face_id, 0);
- if (id < 0 || id >= next_face_id)
- error ("Face id out of range");
-
- FOR_EACH_FRAME (rest, frame)
- {
- if (FRAME_MSDOS_P (XFRAME (frame)) || FRAME_X_P (XFRAME (frame)))
- ensure_face_ready (XFRAME (frame), id);
- }
- return Qnil;
-}
-
-
-DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
- Sset_face_attribute_internal, 4, 4, 0, "")
- (face_id, attr_name, attr_value, frame)
- Lisp_Object face_id, attr_name, attr_value, frame;
-{
- struct face *face;
- struct frame *f;
- int magic_p;
- int id;
- int garbaged = 0;
-
- CHECK_FRAME (frame, 0);
- CHECK_NUMBER (face_id, 0);
- CHECK_SYMBOL (attr_name, 0);
-
- f = XFRAME (frame);
- id = XINT (face_id);
- if (id < 0 || id >= next_face_id)
- error ("Face id out of range");
-
- if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f))
- return Qnil;
-
- ensure_face_ready (f, id);
- face = FRAME_PARAM_FACES (f) [XFASTINT (face_id)];
-
- if (EQ (attr_name, intern ("font")))
- {
-#if defined (MSDOS) && !defined (HAVE_X_WINDOWS)
- /* The one and only font. Must *not* be zero (which
- is taken to mean an unused face nowadays). */
- face->font = (XFontStruct *)1 ;
-#else
- XFontStruct *font = load_font (f, attr_value);
- if (face->font != f->output_data.x->font)
- unload_font (f, face->font);
- face->font = font;
- if (frame_update_line_height (f))
- x_set_window_size (f, 0, f->width, f->height);
- /* Must clear cache, since it might contain the font
- we just got rid of. */
- garbaged = 1;
-#endif
- }
- else if (EQ (attr_name, intern ("foreground")))
- {
- unsigned long new_color = load_color (f, attr_value);
- unload_color (f, face->foreground);
- face->foreground = new_color;
- garbaged = 1;
- }
- else if (EQ (attr_name, intern ("background")))
- {
- unsigned long new_color = load_color (f, attr_value);
- unload_color (f, face->background);
- face->background = new_color;
- garbaged = 1;
- }
- else if (EQ (attr_name, intern ("background-pixmap")))
- {
- unsigned int w, h;
- unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h);
- x_destroy_bitmap (f, face->stipple);
- face->stipple = new_pixmap;
- face->pixmap_w = w;
- face->pixmap_h = h;
- garbaged = 1;
- }
- else if (EQ (attr_name, intern ("underline")))
- {
- int new = !NILP (attr_value);
- face->underline = new;
- }
- else
- error ("unknown face attribute");
-
- if (id == 0 || id == 1)
- recompute_basic_faces (f);
-
- /* We must redraw the frame whenever any face font or color changes,
- because it's possible that a merged (display) face
- contains the font or color we just replaced.
- And we must inhibit any Expose events until the redraw is done,
- since they would try to use the invalid display faces. */
- if (garbaged)
- {
- SET_FRAME_GARBAGED (f);
- FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 1;
- }
-
- return Qnil;
-}
-
-DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
- 0, 0, 0, "")
- ()
-{
- return make_number (next_face_id++);
-}
-
-/* Return the face id for name NAME on frame FRAME.
- (It should be the same for all frames,
- but it's as easy to use the "right" frame to look it up
- as to use any other one.) */
-
-int
-face_name_id_number (f, name)
- FRAME_PTR f;
- Lisp_Object name;
-{
- Lisp_Object tem;
-
- tem = Fcdr (assq_no_quit (name, f->face_alist));
- if (NILP (tem))
- return 0;
- CHECK_VECTOR (tem, 0);
- tem = XVECTOR (tem)->contents[2];
- CHECK_NUMBER (tem, 0);
- return XINT (tem);
-}
-
-/* Emacs initialization. */
-
-void
-syms_of_xfaces ()
-{
- Qface = intern ("face");
- staticpro (&Qface);
- Qmouse_face = intern ("mouse-face");
- staticpro (&Qmouse_face);
- Qpixmap_spec_p = intern ("pixmap-spec-p");
- staticpro (&Qpixmap_spec_p);
-
- DEFVAR_INT ("region-face", &region_face,
- "Face number to use to highlight the region\n\
-The region is highlighted with this face\n\
-when Transient Mark mode is enabled and the mark is active.");
-
-#ifdef HAVE_X_WINDOWS
- defsubr (&Spixmap_spec_p);
-#endif
- defsubr (&Sframe_face_alist);
- defsubr (&Sset_frame_face_alist);
- defsubr (&Smake_face_internal);
- defsubr (&Sset_face_attribute_internal);
- defsubr (&Sinternal_next_face_id);
-}
-
-#endif /* HAVE_FACES */
diff --git a/src/xfns.c b/src/xfns.c
deleted file mode 100644
index 2952da07878..00000000000
--- a/src/xfns.c
+++ /dev/null
@@ -1,5249 +0,0 @@
-/* Functions for the X window system.
- Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Completely rewritten by Richard Stallman. */
-
-/* Rewritten for X11 by Joseph Arceneaux */
-
-#include <signal.h>
-#include <config.h>
-
-/* This makes the fields of a Display accessible, in Xlib header files. */
-#define XLIB_ILLEGAL_ACCESS
-
-#include "lisp.h"
-#include "xterm.h"
-#include "frame.h"
-#include "window.h"
-#include "buffer.h"
-#include "dispextern.h"
-#include "keyboard.h"
-#include "blockinput.h"
-#include <paths.h>
-
-#ifdef HAVE_X_WINDOWS
-extern void abort ();
-
-/* On some systems, the character-composition stuff is broken in X11R5. */
-#if defined (HAVE_X11R5) && ! defined (HAVE_X11R6)
-#ifdef X11R5_INHIBIT_I18N
-#define X_I18N_INHIBITED
-#endif
-#endif
-
-#ifndef VMS
-#if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
-#include "bitmaps/gray.xbm"
-#else
-#include <X11/bitmaps/gray>
-#endif
-#else
-#include "[.bitmaps]gray.xbm"
-#endif
-
-#ifdef USE_X_TOOLKIT
-#include <X11/Shell.h>
-
-#ifndef USE_MOTIF
-#include <X11/Xaw/Paned.h>
-#include <X11/Xaw/Label.h>
-#endif /* USE_MOTIF */
-
-#ifdef USG
-#undef USG /* ####KLUDGE for Solaris 2.2 and up */
-#include <X11/Xos.h>
-#define USG
-#else
-#include <X11/Xos.h>
-#endif
-
-#include "widget.h"
-
-#include "../lwlib/lwlib.h"
-
-/* Do the EDITRES protocol if running X11R5
- Exception: HP-UX (at least version A.09.05) has X11R5 without EditRes */
-#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
-#define HACK_EDITRES
-extern void _XEditResCheckMessages ();
-#endif /* R5 + Athena */
-
-/* Unique id counter for widgets created by the Lucid Widget
- Library. */
-extern LWLIB_ID widget_id_tick;
-
-#ifdef USE_LUCID
-/* This is part of a kludge--see lwlib/xlwmenu.c. */
-extern XFontStruct *xlwmenu_default_font;
-#endif
-
-extern void free_frame_menubar ();
-#endif /* USE_X_TOOLKIT */
-
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#define max(a,b) ((a) > (b) ? (a) : (b))
-
-#ifdef HAVE_X11R4
-#define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
-#else
-#define MAXREQUEST(dpy) ((dpy)->max_request_size)
-#endif
-
-/* The name we're using in resource queries. */
-Lisp_Object Vx_resource_name;
-
-/* The background and shape of the mouse pointer, and shape when not
- over text or in the modeline. */
-Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
-/* The shape when over mouse-sensitive text. */
-Lisp_Object Vx_sensitive_text_pointer_shape;
-
-/* Color of chars displayed in cursor box. */
-Lisp_Object Vx_cursor_fore_pixel;
-
-/* Nonzero if using X. */
-static int x_in_use;
-
-/* Non nil if no window manager is in use. */
-Lisp_Object Vx_no_window_manager;
-
-/* Search path for bitmap files. */
-Lisp_Object Vx_bitmap_file_path;
-
-/* Evaluate this expression to rebuild the section of syms_of_xfns
- that initializes and staticpros the symbols declared below. Note
- that Emacs 18 has a bug that keeps C-x C-e from being able to
- evaluate this expression.
-
-(progn
- ;; Accumulate a list of the symbols we want to initialize from the
- ;; declarations at the top of the file.
- (goto-char (point-min))
- (search-forward "/\*&&& symbols declared here &&&*\/\n")
- (let (symbol-list)
- (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
- (setq symbol-list
- (cons (buffer-substring (match-beginning 1) (match-end 1))
- symbol-list))
- (forward-line 1))
- (setq symbol-list (nreverse symbol-list))
- ;; Delete the section of syms_of_... where we initialize the symbols.
- (search-forward "\n /\*&&& init symbols here &&&*\/\n")
- (let ((start (point)))
- (while (looking-at "^ Q")
- (forward-line 2))
- (kill-region start (point)))
- ;; Write a new symbol initialization section.
- (while symbol-list
- (insert (format " %s = intern (\"" (car symbol-list)))
- (let ((start (point)))
- (insert (substring (car symbol-list) 1))
- (subst-char-in-region start (point) ?_ ?-))
- (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
- (setq symbol-list (cdr symbol-list)))))
-
- */
-
-/*&&& symbols declared here &&&*/
-Lisp_Object Qauto_raise;
-Lisp_Object Qauto_lower;
-Lisp_Object Qbackground_color;
-Lisp_Object Qbar;
-Lisp_Object Qborder_color;
-Lisp_Object Qborder_width;
-Lisp_Object Qbox;
-Lisp_Object Qcursor_color;
-Lisp_Object Qcursor_type;
-Lisp_Object Qforeground_color;
-Lisp_Object Qgeometry;
-Lisp_Object Qicon_left;
-Lisp_Object Qicon_top;
-Lisp_Object Qicon_type;
-Lisp_Object Qicon_name;
-Lisp_Object Qinternal_border_width;
-Lisp_Object Qleft;
-Lisp_Object Qright;
-Lisp_Object Qmouse_color;
-Lisp_Object Qnone;
-Lisp_Object Qparent_id;
-Lisp_Object Qscroll_bar_width;
-Lisp_Object Qsuppress_icon;
-Lisp_Object Qtop;
-Lisp_Object Qundefined_color;
-Lisp_Object Qvertical_scroll_bars;
-Lisp_Object Qvisibility;
-Lisp_Object Qwindow_id;
-Lisp_Object Qx_frame_parameter;
-Lisp_Object Qx_resource_name;
-Lisp_Object Quser_position;
-Lisp_Object Quser_size;
-Lisp_Object Qdisplay;
-
-/* The below are defined in frame.c. */
-extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
-extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
-
-extern Lisp_Object Vwindow_system_version;
-
-
-/* Error if we are not connected to X. */
-void
-check_x ()
-{
- if (! x_in_use)
- error ("X windows are not in use or not initialized");
-}
-
-/* Nonzero if we can use mouse menus.
- You should not call this unless HAVE_MENUS is defined. */
-
-int
-have_menus_p ()
-{
- return x_in_use;
-}
-
-/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
- and checking validity for X. */
-
-FRAME_PTR
-check_x_frame (frame)
- Lisp_Object frame;
-{
- FRAME_PTR f;
-
- if (NILP (frame))
- f = selected_frame;
- else
- {
- CHECK_LIVE_FRAME (frame, 0);
- f = XFRAME (frame);
- }
- if (! FRAME_X_P (f))
- error ("Non-X frame used");
- return f;
-}
-
-/* Let the user specify an X display with a frame.
- nil stands for the selected frame--or, if that is not an X frame,
- the first X display on the list. */
-
-static struct x_display_info *
-check_x_display_info (frame)
- Lisp_Object frame;
-{
- if (NILP (frame))
- {
- if (FRAME_X_P (selected_frame))
- return FRAME_X_DISPLAY_INFO (selected_frame);
- else if (x_display_list != 0)
- return x_display_list;
- else
- error ("X windows are not in use or not initialized");
- }
- else if (STRINGP (frame))
- return x_display_info_for_name (frame);
- else
- {
- FRAME_PTR f;
-
- CHECK_LIVE_FRAME (frame, 0);
- f = XFRAME (frame);
- if (! FRAME_X_P (f))
- error ("Non-X frame used");
- return FRAME_X_DISPLAY_INFO (f);
- }
-}
-
-/* Return the Emacs frame-object corresponding to an X window.
- It could be the frame's main window or an icon window. */
-
-/* This function can be called during GC, so use GC_xxx type test macros. */
-
-struct frame *
-x_window_to_frame (dpyinfo, wdesc)
- struct x_display_info *dpyinfo;
- int wdesc;
-{
- Lisp_Object tail, frame;
- struct frame *f;
-
- for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
- {
- frame = XCONS (tail)->car;
- if (!GC_FRAMEP (frame))
- continue;
- f = XFRAME (frame);
- if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
- continue;
-#ifdef USE_X_TOOLKIT
- if ((f->output_data.x->edit_widget
- && XtWindow (f->output_data.x->edit_widget) == wdesc)
- || f->output_data.x->icon_desc == wdesc)
- return f;
-#else /* not USE_X_TOOLKIT */
- if (FRAME_X_WINDOW (f) == wdesc
- || f->output_data.x->icon_desc == wdesc)
- return f;
-#endif /* not USE_X_TOOLKIT */
- }
- return 0;
-}
-
-#ifdef USE_X_TOOLKIT
-/* Like x_window_to_frame but also compares the window with the widget's
- windows. */
-
-struct frame *
-x_any_window_to_frame (dpyinfo, wdesc)
- struct x_display_info *dpyinfo;
- int wdesc;
-{
- Lisp_Object tail, frame;
- struct frame *f;
- struct x_output *x;
-
- for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
- {
- frame = XCONS (tail)->car;
- if (!GC_FRAMEP (frame))
- continue;
- f = XFRAME (frame);
- if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
- continue;
- x = f->output_data.x;
- /* This frame matches if the window is any of its widgets. */
- if (wdesc == XtWindow (x->widget)
- || wdesc == XtWindow (x->column_widget)
- || wdesc == XtWindow (x->edit_widget))
- return f;
- /* Match if the window is this frame's menubar. */
- if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
- return f;
- }
- return 0;
-}
-
-/* Likewise, but exclude the menu bar widget. */
-
-struct frame *
-x_non_menubar_window_to_frame (dpyinfo, wdesc)
- struct x_display_info *dpyinfo;
- int wdesc;
-{
- Lisp_Object tail, frame;
- struct frame *f;
- struct x_output *x;
-
- for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
- {
- frame = XCONS (tail)->car;
- if (!GC_FRAMEP (frame))
- continue;
- f = XFRAME (frame);
- if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
- continue;
- x = f->output_data.x;
- /* This frame matches if the window is any of its widgets. */
- if (wdesc == XtWindow (x->widget)
- || wdesc == XtWindow (x->column_widget)
- || wdesc == XtWindow (x->edit_widget))
- return f;
- }
- return 0;
-}
-
-/* Likewise, but consider only the menu bar widget. */
-
-struct frame *
-x_menubar_window_to_frame (dpyinfo, wdesc)
- struct x_display_info *dpyinfo;
- int wdesc;
-{
- Lisp_Object tail, frame;
- struct frame *f;
- struct x_output *x;
-
- for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
- {
- frame = XCONS (tail)->car;
- if (!GC_FRAMEP (frame))
- continue;
- f = XFRAME (frame);
- if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
- continue;
- x = f->output_data.x;
- /* Match if the window is this frame's menubar. */
- if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
- return f;
- }
- return 0;
-}
-
-/* Return the frame whose principal (outermost) window is WDESC.
- If WDESC is some other (smaller) window, we return 0. */
-
-struct frame *
-x_top_window_to_frame (dpyinfo, wdesc)
- struct x_display_info *dpyinfo;
- int wdesc;
-{
- Lisp_Object tail, frame;
- struct frame *f;
- struct x_output *x;
-
- for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
- {
- frame = XCONS (tail)->car;
- if (!GC_FRAMEP (frame))
- continue;
- f = XFRAME (frame);
- if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
- continue;
- x = f->output_data.x;
- /* This frame matches if the window is its topmost widget. */
- if (wdesc == XtWindow (x->widget))
- return f;
-#if 0 /* I don't know why it did this,
- but it seems logically wrong,
- and it causes trouble for MapNotify events. */
- /* Match if the window is this frame's menubar. */
- if (x->menubar_widget
- && wdesc == XtWindow (x->menubar_widget))
- return f;
-#endif
- }
- return 0;
-}
-#endif /* USE_X_TOOLKIT */
-
-
-
-/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
- id, which is just an int that this section returns. Bitmaps are
- reference counted so they can be shared among frames.
-
- Bitmap indices are guaranteed to be > 0, so a negative number can
- be used to indicate no bitmap.
-
- If you use x_create_bitmap_from_data, then you must keep track of
- the bitmaps yourself. That is, creating a bitmap from the same
- data more than once will not be caught. */
-
-
-/* Functions to access the contents of a bitmap, given an id. */
-
-int
-x_bitmap_height (f, id)
- FRAME_PTR f;
- int id;
-{
- return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
-}
-
-int
-x_bitmap_width (f, id)
- FRAME_PTR f;
- int id;
-{
- return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
-}
-
-int
-x_bitmap_pixmap (f, id)
- FRAME_PTR f;
- int id;
-{
- return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
-}
-
-
-/* Allocate a new bitmap record. Returns index of new record. */
-
-static int
-x_allocate_bitmap_record (f)
- FRAME_PTR f;
-{
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
- int i;
-
- if (dpyinfo->bitmaps == NULL)
- {
- dpyinfo->bitmaps_size = 10;
- dpyinfo->bitmaps
- = (struct x_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
- dpyinfo->bitmaps_last = 1;
- return 1;
- }
-
- if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
- return ++dpyinfo->bitmaps_last;
-
- for (i = 0; i < dpyinfo->bitmaps_size; ++i)
- if (dpyinfo->bitmaps[i].refcount == 0)
- return i + 1;
-
- dpyinfo->bitmaps_size *= 2;
- dpyinfo->bitmaps
- = (struct x_bitmap_record *) xrealloc (dpyinfo->bitmaps,
- dpyinfo->bitmaps_size * sizeof (struct x_bitmap_record));
- return ++dpyinfo->bitmaps_last;
-}
-
-/* Add one reference to the reference count of the bitmap with id ID. */
-
-void
-x_reference_bitmap (f, id)
- FRAME_PTR f;
- int id;
-{
- ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
-}
-
-/* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
-
-int
-x_create_bitmap_from_data (f, bits, width, height)
- struct frame *f;
- char *bits;
- unsigned int width, height;
-{
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
- Pixmap bitmap;
- int id;
-
- bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- bits, width, height);
-
- if (! bitmap)
- return -1;
-
- id = x_allocate_bitmap_record (f);
- dpyinfo->bitmaps[id - 1].pixmap = bitmap;
- dpyinfo->bitmaps[id - 1].file = NULL;
- dpyinfo->bitmaps[id - 1].refcount = 1;
- dpyinfo->bitmaps[id - 1].depth = 1;
- dpyinfo->bitmaps[id - 1].height = height;
- dpyinfo->bitmaps[id - 1].width = width;
-
- return id;
-}
-
-/* Create bitmap from file FILE for frame F. */
-
-int
-x_create_bitmap_from_file (f, file)
- struct frame *f;
- Lisp_Object file;
-{
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
- unsigned int width, height;
- Pixmap bitmap;
- int xhot, yhot, result, id;
- Lisp_Object found;
- int fd;
- char *filename;
-
- /* Look for an existing bitmap with the same name. */
- for (id = 0; id < dpyinfo->bitmaps_last; ++id)
- {
- if (dpyinfo->bitmaps[id].refcount
- && dpyinfo->bitmaps[id].file
- && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
- {
- ++dpyinfo->bitmaps[id].refcount;
- return id + 1;
- }
- }
-
- /* Search bitmap-file-path for the file, if appropriate. */
- fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
- if (fd < 0)
- return -1;
- close (fd);
-
- filename = (char *) XSTRING (found)->data;
-
- result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- filename, &width, &height, &bitmap, &xhot, &yhot);
- if (result != BitmapSuccess)
- return -1;
-
- id = x_allocate_bitmap_record (f);
- dpyinfo->bitmaps[id - 1].pixmap = bitmap;
- dpyinfo->bitmaps[id - 1].refcount = 1;
- dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (XSTRING (file)->size + 1);
- dpyinfo->bitmaps[id - 1].depth = 1;
- dpyinfo->bitmaps[id - 1].height = height;
- dpyinfo->bitmaps[id - 1].width = width;
- strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
-
- return id;
-}
-
-/* Remove reference to bitmap with id number ID. */
-
-int
-x_destroy_bitmap (f, id)
- FRAME_PTR f;
- int id;
-{
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-
- if (id > 0)
- {
- --dpyinfo->bitmaps[id - 1].refcount;
- if (dpyinfo->bitmaps[id - 1].refcount == 0)
- {
- BLOCK_INPUT;
- XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
- if (dpyinfo->bitmaps[id - 1].file)
- {
- free (dpyinfo->bitmaps[id - 1].file);
- dpyinfo->bitmaps[id - 1].file = NULL;
- }
- UNBLOCK_INPUT;
- }
- }
-}
-
-/* Free all the bitmaps for the display specified by DPYINFO. */
-
-static void
-x_destroy_all_bitmaps (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- int i;
- for (i = 0; i < dpyinfo->bitmaps_last; i++)
- if (dpyinfo->bitmaps[i].refcount > 0)
- {
- XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
- if (dpyinfo->bitmaps[i].file)
- free (dpyinfo->bitmaps[i].file);
- }
- dpyinfo->bitmaps_last = 0;
-}
-
-/* Connect the frame-parameter names for X frames
- to the ways of passing the parameter values to the window system.
-
- The name of a parameter, as a Lisp symbol,
- has an `x-frame-parameter' property which is an integer in Lisp
- that is an index in this table. */
-
-struct x_frame_parm_table
-{
- char *name;
- void (*setter)( /* struct frame *frame, Lisp_Object val, oldval */ );
-};
-
-void x_set_foreground_color ();
-void x_set_background_color ();
-void x_set_mouse_color ();
-void x_set_cursor_color ();
-void x_set_border_color ();
-void x_set_cursor_type ();
-void x_set_icon_type ();
-void x_set_icon_name ();
-void x_set_font ();
-void x_set_border_width ();
-void x_set_internal_border_width ();
-void x_explicitly_set_name ();
-void x_set_autoraise ();
-void x_set_autolower ();
-void x_set_vertical_scroll_bars ();
-void x_set_visibility ();
-void x_set_menu_bar_lines ();
-void x_set_scroll_bar_width ();
-void x_set_title ();
-void x_set_unsplittable ();
-
-static struct x_frame_parm_table x_frame_parms[] =
-{
- "auto-raise", x_set_autoraise,
- "auto-lower", x_set_autolower,
- "background-color", x_set_background_color,
- "border-color", x_set_border_color,
- "border-width", x_set_border_width,
- "cursor-color", x_set_cursor_color,
- "cursor-type", x_set_cursor_type,
- "font", x_set_font,
- "foreground-color", x_set_foreground_color,
- "icon-name", x_set_icon_name,
- "icon-type", x_set_icon_type,
- "internal-border-width", x_set_internal_border_width,
- "menu-bar-lines", x_set_menu_bar_lines,
- "mouse-color", x_set_mouse_color,
- "name", x_explicitly_set_name,
- "scroll-bar-width", x_set_scroll_bar_width,
- "title", x_set_title,
- "unsplittable", x_set_unsplittable,
- "vertical-scroll-bars", x_set_vertical_scroll_bars,
- "visibility", x_set_visibility,
-};
-
-/* Attach the `x-frame-parameter' properties to
- the Lisp symbol names of parameters relevant to X. */
-
-init_x_parm_symbols ()
-{
- int i;
-
- for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
- Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
- make_number (i));
-}
-
-/* Change the parameters of FRAME as specified by ALIST.
- If a parameter is not specially recognized, do nothing;
- otherwise call the `x_set_...' function for that parameter. */
-
-void
-x_set_frame_parameters (f, alist)
- FRAME_PTR f;
- Lisp_Object alist;
-{
- Lisp_Object tail;
-
- /* If both of these parameters are present, it's more efficient to
- set them both at once. So we wait until we've looked at the
- entire list before we set them. */
- int width, height;
-
- /* Same here. */
- Lisp_Object left, top;
-
- /* Same with these. */
- Lisp_Object icon_left, icon_top;
-
- /* Record in these vectors all the parms specified. */
- Lisp_Object *parms;
- Lisp_Object *values;
- int i;
- int left_no_change = 0, top_no_change = 0;
- int icon_left_no_change = 0, icon_top_no_change = 0;
-
- i = 0;
- for (tail = alist; CONSP (tail); tail = Fcdr (tail))
- i++;
-
- parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
- values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
-
- /* Extract parm names and values into those vectors. */
-
- i = 0;
- for (tail = alist; CONSP (tail); tail = Fcdr (tail))
- {
- Lisp_Object elt, prop, val;
-
- elt = Fcar (tail);
- parms[i] = Fcar (elt);
- values[i] = Fcdr (elt);
- i++;
- }
-
- top = left = Qunbound;
- icon_left = icon_top = Qunbound;
-
- /* Provide default values for HEIGHT and WIDTH. */
- if (FRAME_NEW_WIDTH (f))
- width = FRAME_NEW_WIDTH (f);
- else
- width = FRAME_WIDTH (f);
-
- if (FRAME_NEW_HEIGHT (f))
- height = FRAME_NEW_HEIGHT (f);
- else
- height = FRAME_HEIGHT (f);
-
- /* Now process them in reverse of specified order. */
- for (i--; i >= 0; i--)
- {
- Lisp_Object prop, val;
-
- prop = parms[i];
- val = values[i];
-
- if (EQ (prop, Qwidth) && NUMBERP (val))
- width = XFASTINT (val);
- else if (EQ (prop, Qheight) && NUMBERP (val))
- height = XFASTINT (val);
- else if (EQ (prop, Qtop))
- top = val;
- else if (EQ (prop, Qleft))
- left = val;
- else if (EQ (prop, Qicon_top))
- icon_top = val;
- else if (EQ (prop, Qicon_left))
- icon_left = val;
- else
- {
- register Lisp_Object param_index, old_value;
-
- param_index = Fget (prop, Qx_frame_parameter);
- old_value = get_frame_param (f, prop);
- store_frame_param (f, prop, val);
- if (NATNUMP (param_index)
- && (XFASTINT (param_index)
- < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
- (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
- }
- }
-
- /* Don't die if just one of these was set. */
- if (EQ (left, Qunbound))
- {
- left_no_change = 1;
- if (f->output_data.x->left_pos < 0)
- left = Fcons (Qplus, Fcons (make_number (f->output_data.x->left_pos), Qnil));
- else
- XSETINT (left, f->output_data.x->left_pos);
- }
- if (EQ (top, Qunbound))
- {
- top_no_change = 1;
- if (f->output_data.x->top_pos < 0)
- top = Fcons (Qplus, Fcons (make_number (f->output_data.x->top_pos), Qnil));
- else
- XSETINT (top, f->output_data.x->top_pos);
- }
-
- /* If one of the icon positions was not set, preserve or default it. */
- if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
- {
- icon_left_no_change = 1;
- icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
- if (NILP (icon_left))
- XSETINT (icon_left, 0);
- }
- if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
- {
- icon_top_no_change = 1;
- icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
- if (NILP (icon_top))
- XSETINT (icon_top, 0);
- }
-
- /* Don't set these parameters unless they've been explicitly
- specified. The window might be mapped or resized while we're in
- this function, and we don't want to override that unless the lisp
- code has asked for it.
-
- Don't set these parameters unless they actually differ from the
- window's current parameters; the window may not actually exist
- yet. */
- {
- Lisp_Object frame;
-
- check_frame_size (f, &height, &width);
-
- XSETFRAME (frame, f);
-
- if (width != FRAME_WIDTH (f)
- || height != FRAME_HEIGHT (f)
- || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
- Fset_frame_size (frame, make_number (width), make_number (height));
-
- if ((!NILP (left) || !NILP (top))
- && ! (left_no_change && top_no_change)
- && ! (NUMBERP (left) && XINT (left) == f->output_data.x->left_pos
- && NUMBERP (top) && XINT (top) == f->output_data.x->top_pos))
- {
- int leftpos = 0;
- int toppos = 0;
-
- /* Record the signs. */
- f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
- if (EQ (left, Qminus))
- f->output_data.x->size_hint_flags |= XNegative;
- else if (INTEGERP (left))
- {
- leftpos = XINT (left);
- if (leftpos < 0)
- f->output_data.x->size_hint_flags |= XNegative;
- }
- else if (CONSP (left) && EQ (XCONS (left)->car, Qminus)
- && CONSP (XCONS (left)->cdr)
- && INTEGERP (XCONS (XCONS (left)->cdr)->car))
- {
- leftpos = - XINT (XCONS (XCONS (left)->cdr)->car);
- f->output_data.x->size_hint_flags |= XNegative;
- }
- else if (CONSP (left) && EQ (XCONS (left)->car, Qplus)
- && CONSP (XCONS (left)->cdr)
- && INTEGERP (XCONS (XCONS (left)->cdr)->car))
- {
- leftpos = XINT (XCONS (XCONS (left)->cdr)->car);
- }
-
- if (EQ (top, Qminus))
- f->output_data.x->size_hint_flags |= YNegative;
- else if (INTEGERP (top))
- {
- toppos = XINT (top);
- if (toppos < 0)
- f->output_data.x->size_hint_flags |= YNegative;
- }
- else if (CONSP (top) && EQ (XCONS (top)->car, Qminus)
- && CONSP (XCONS (top)->cdr)
- && INTEGERP (XCONS (XCONS (top)->cdr)->car))
- {
- toppos = - XINT (XCONS (XCONS (top)->cdr)->car);
- f->output_data.x->size_hint_flags |= YNegative;
- }
- else if (CONSP (top) && EQ (XCONS (top)->car, Qplus)
- && CONSP (XCONS (top)->cdr)
- && INTEGERP (XCONS (XCONS (top)->cdr)->car))
- {
- toppos = XINT (XCONS (XCONS (top)->cdr)->car);
- }
-
-
- /* Store the numeric value of the position. */
- f->output_data.x->top_pos = toppos;
- f->output_data.x->left_pos = leftpos;
-
- f->output_data.x->win_gravity = NorthWestGravity;
-
- /* Actually set that position, and convert to absolute. */
- x_set_offset (f, leftpos, toppos, -1);
- }
-
- if ((!NILP (icon_left) || !NILP (icon_top))
- && ! (icon_left_no_change && icon_top_no_change))
- x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
- }
-}
-
-/* Store the screen positions of frame F into XPTR and YPTR.
- These are the positions of the containing window manager window,
- not Emacs's own window. */
-
-void
-x_real_positions (f, xptr, yptr)
- FRAME_PTR f;
- int *xptr, *yptr;
-{
- int win_x, win_y;
- Window child;
-
- /* This is pretty gross, but seems to be the easiest way out of
- the problem that arises when restarting window-managers. */
-
-#ifdef USE_X_TOOLKIT
- Window outer = XtWindow (f->output_data.x->widget);
-#else
- Window outer = f->output_data.x->window_desc;
-#endif
- Window tmp_root_window;
- Window *tmp_children;
- int tmp_nchildren;
-
- while (1)
- {
- x_catch_errors (FRAME_X_DISPLAY (f));
-
- XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window,
- &f->output_data.x->parent_desc,
- &tmp_children, &tmp_nchildren);
- XFree ((char *) tmp_children);
-
- win_x = win_y = 0;
-
- /* Find the position of the outside upper-left corner of
- the inner window, with respect to the outer window. */
- if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
- {
- XTranslateCoordinates (FRAME_X_DISPLAY (f),
-
- /* From-window, to-window. */
-#ifdef USE_X_TOOLKIT
- XtWindow (f->output_data.x->widget),
-#else
- f->output_data.x->window_desc,
-#endif
- f->output_data.x->parent_desc,
-
- /* From-position, to-position. */
- 0, 0, &win_x, &win_y,
-
- /* Child of win. */
- &child);
-
-#if 0 /* The values seem to be right without this and wrong with. */
- win_x += f->output_data.x->border_width;
- win_y += f->output_data.x->border_width;
-#endif
- }
-
- /* It is possible for the window returned by the XQueryNotify
- to become invalid by the time we call XTranslateCoordinates.
- That can happen when you restart some window managers.
- If so, we get an error in XTranslateCoordinates.
- Detect that and try the whole thing over. */
- if (! x_had_errors_p (FRAME_X_DISPLAY (f)))
- {
- x_uncatch_errors (FRAME_X_DISPLAY (f));
- break;
- }
-
- x_uncatch_errors (FRAME_X_DISPLAY (f));
- }
-
- *xptr = f->output_data.x->left_pos - win_x;
- *yptr = f->output_data.x->top_pos - win_y;
-}
-
-/* Insert a description of internally-recorded parameters of frame X
- into the parameter alist *ALISTPTR that is to be given to the user.
- Only parameters that are specific to the X window system
- and whose values are not correctly recorded in the frame's
- param_alist need to be considered here. */
-
-x_report_frame_params (f, alistptr)
- struct frame *f;
- Lisp_Object *alistptr;
-{
- char buf[16];
- Lisp_Object tem;
-
- /* Represent negative positions (off the top or left screen edge)
- in a way that Fmodify_frame_parameters will understand correctly. */
- XSETINT (tem, f->output_data.x->left_pos);
- if (f->output_data.x->left_pos >= 0)
- store_in_alist (alistptr, Qleft, tem);
- else
- store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
-
- XSETINT (tem, f->output_data.x->top_pos);
- if (f->output_data.x->top_pos >= 0)
- store_in_alist (alistptr, Qtop, tem);
- else
- store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
-
- store_in_alist (alistptr, Qborder_width,
- make_number (f->output_data.x->border_width));
- store_in_alist (alistptr, Qinternal_border_width,
- make_number (f->output_data.x->internal_border_width));
- sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
- store_in_alist (alistptr, Qwindow_id,
- build_string (buf));
- store_in_alist (alistptr, Qicon_name, f->icon_name);
- FRAME_SAMPLE_VISIBILITY (f);
- store_in_alist (alistptr, Qvisibility,
- (FRAME_VISIBLE_P (f) ? Qt
- : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
- store_in_alist (alistptr, Qdisplay,
- XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->car);
-
- store_in_alist (alistptr, Qparent_id,
- (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window
- ? Qnil : f->output_data.x->parent_desc));
-}
-
-
-/* Decide if color named COLOR is valid for the display associated with
- the selected frame; if so, return the rgb values in COLOR_DEF.
- If ALLOC is nonzero, allocate a new colormap cell. */
-
-int
-defined_color (f, color, color_def, alloc)
- FRAME_PTR f;
- char *color;
- XColor *color_def;
- int alloc;
-{
- register int status;
- Colormap screen_colormap;
- Display *display = FRAME_X_DISPLAY (f);
-
- BLOCK_INPUT;
- screen_colormap = DefaultColormap (display, XDefaultScreen (display));
-
- status = XParseColor (display, screen_colormap, color, color_def);
- if (status && alloc)
- {
- status = XAllocColor (display, screen_colormap, color_def);
- if (!status)
- {
- /* If we got to this point, the colormap is full, so we're
- going to try and get the next closest color.
- The algorithm used is a least-squares matching, which is
- what X uses for closest color matching with StaticColor visuals. */
-
- XColor *cells;
- int no_cells;
- int nearest;
- long nearest_delta, trial_delta;
- int x;
-
- no_cells = XDisplayCells (display, XDefaultScreen (display));
- cells = (XColor *) alloca (sizeof (XColor) * no_cells);
-
- for (x = 0; x < no_cells; x++)
- cells[x].pixel = x;
-
- XQueryColors (display, screen_colormap, cells, no_cells);
- nearest = 0;
- /* I'm assuming CSE so I'm not going to condense this. */
- nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8))
- * ((color_def->red >> 8) - (cells[0].red >> 8)))
- +
- (((color_def->green >> 8) - (cells[0].green >> 8))
- * ((color_def->green >> 8) - (cells[0].green >> 8)))
- +
- (((color_def->blue >> 8) - (cells[0].blue >> 8))
- * ((color_def->blue >> 8) - (cells[0].blue >> 8))));
- for (x = 1; x < no_cells; x++)
- {
- trial_delta = ((((color_def->red >> 8) - (cells[x].red >> 8))
- * ((color_def->red >> 8) - (cells[x].red >> 8)))
- +
- (((color_def->green >> 8) - (cells[x].green >> 8))
- * ((color_def->green >> 8) - (cells[x].green >> 8)))
- +
- (((color_def->blue >> 8) - (cells[x].blue >> 8))
- * ((color_def->blue >> 8) - (cells[x].blue >> 8))));
- if (trial_delta < nearest_delta)
- {
- XColor temp;
- temp.red = cells[x].red;
- temp.green = cells[x].green;
- temp.blue = cells[x].blue;
- status = XAllocColor (display, screen_colormap, &temp);
- if (status)
- {
- nearest = x;
- nearest_delta = trial_delta;
- }
- }
- }
- color_def->red = cells[nearest].red;
- color_def->green = cells[nearest].green;
- color_def->blue = cells[nearest].blue;
- status = XAllocColor (display, screen_colormap, color_def);
- }
- }
- UNBLOCK_INPUT;
-
- if (status)
- return 1;
- else
- return 0;
-}
-
-/* Given a string ARG naming a color, compute a pixel value from it
- suitable for screen F.
- If F is not a color screen, return DEF (default) regardless of what
- ARG says. */
-
-int
-x_decode_color (f, arg, def)
- FRAME_PTR f;
- Lisp_Object arg;
- int def;
-{
- XColor cdef;
-
- CHECK_STRING (arg, 0);
-
- if (strcmp (XSTRING (arg)->data, "black") == 0)
- return BLACK_PIX_DEFAULT (f);
- else if (strcmp (XSTRING (arg)->data, "white") == 0)
- return WHITE_PIX_DEFAULT (f);
-
- if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
- return def;
-
- /* defined_color is responsible for coping with failures
- by looking for a near-miss. */
- if (defined_color (f, XSTRING (arg)->data, &cdef, 1))
- return cdef.pixel;
-
- Fsignal (Qerror, Fcons (build_string ("undefined color"),
- Fcons (arg, Qnil)));
-}
-
-/* Functions called only from `x_set_frame_param'
- to set individual parameters.
-
- If FRAME_X_WINDOW (f) is 0,
- the frame is being created and its X-window does not exist yet.
- In that case, just record the parameter's new value
- in the standard place; do not attempt to change the window. */
-
-void
-x_set_foreground_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- f->output_data.x->foreground_pixel
- = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
- if (FRAME_X_WINDOW (f) != 0)
- {
- BLOCK_INPUT;
- XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
- f->output_data.x->foreground_pixel);
- XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
- f->output_data.x->foreground_pixel);
- UNBLOCK_INPUT;
- recompute_basic_faces (f);
- if (FRAME_VISIBLE_P (f))
- redraw_frame (f);
- }
-}
-
-void
-x_set_background_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- Pixmap temp;
- int mask;
-
- f->output_data.x->background_pixel
- = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
-
- if (FRAME_X_WINDOW (f) != 0)
- {
- BLOCK_INPUT;
- /* The main frame area. */
- XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
- f->output_data.x->background_pixel);
- XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
- f->output_data.x->background_pixel);
- XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
- f->output_data.x->background_pixel);
- XSetWindowBackground (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->background_pixel);
- {
- Lisp_Object bar;
- for (bar = FRAME_SCROLL_BARS (f); !NILP (bar);
- bar = XSCROLL_BAR (bar)->next)
- XSetWindowBackground (FRAME_X_DISPLAY (f),
- SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
- f->output_data.x->background_pixel);
- }
- UNBLOCK_INPUT;
-
- recompute_basic_faces (f);
-
- if (FRAME_VISIBLE_P (f))
- redraw_frame (f);
- }
-}
-
-void
-x_set_mouse_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
- int mask_color;
-
- if (!EQ (Qnil, arg))
- f->output_data.x->mouse_pixel
- = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
- mask_color = f->output_data.x->background_pixel;
- /* No invisible pointers. */
- if (mask_color == f->output_data.x->mouse_pixel
- && mask_color == f->output_data.x->background_pixel)
- f->output_data.x->mouse_pixel = f->output_data.x->foreground_pixel;
-
- BLOCK_INPUT;
-
- /* It's not okay to crash if the user selects a screwy cursor. */
- x_catch_errors (FRAME_X_DISPLAY (f));
-
- if (!EQ (Qnil, Vx_pointer_shape))
- {
- CHECK_NUMBER (Vx_pointer_shape, 0);
- cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XINT (Vx_pointer_shape));
- }
- else
- cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
- x_check_errors (FRAME_X_DISPLAY (f), "bad text pointer cursor: %s");
-
- if (!EQ (Qnil, Vx_nontext_pointer_shape))
- {
- CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
- nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
- XINT (Vx_nontext_pointer_shape));
- }
- else
- nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_left_ptr);
- x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
-
- if (!EQ (Qnil, Vx_mode_pointer_shape))
- {
- CHECK_NUMBER (Vx_mode_pointer_shape, 0);
- mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
- XINT (Vx_mode_pointer_shape));
- }
- else
- mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
- x_check_errors (FRAME_X_DISPLAY (f), "bad modeline pointer cursor: %s");
-
- if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
- {
- CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
- cross_cursor
- = XCreateFontCursor (FRAME_X_DISPLAY (f),
- XINT (Vx_sensitive_text_pointer_shape));
- }
- else
- cross_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_crosshair);
-
- /* Check and report errors with the above calls. */
- x_check_errors (FRAME_X_DISPLAY (f), "can't set cursor shape: %s");
- x_uncatch_errors (FRAME_X_DISPLAY (f));
-
- {
- XColor fore_color, back_color;
-
- fore_color.pixel = f->output_data.x->mouse_pixel;
- back_color.pixel = mask_color;
- XQueryColor (FRAME_X_DISPLAY (f),
- DefaultColormap (FRAME_X_DISPLAY (f),
- DefaultScreen (FRAME_X_DISPLAY (f))),
- &fore_color);
- XQueryColor (FRAME_X_DISPLAY (f),
- DefaultColormap (FRAME_X_DISPLAY (f),
- DefaultScreen (FRAME_X_DISPLAY (f))),
- &back_color);
- XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
- &fore_color, &back_color);
- XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor,
- &fore_color, &back_color);
- XRecolorCursor (FRAME_X_DISPLAY (f), mode_cursor,
- &fore_color, &back_color);
- XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor,
- &fore_color, &back_color);
- }
-
- if (FRAME_X_WINDOW (f) != 0)
- {
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
- }
-
- if (cursor != f->output_data.x->text_cursor && f->output_data.x->text_cursor != 0)
- XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
- f->output_data.x->text_cursor = cursor;
-
- if (nontext_cursor != f->output_data.x->nontext_cursor
- && f->output_data.x->nontext_cursor != 0)
- XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
- f->output_data.x->nontext_cursor = nontext_cursor;
-
- if (mode_cursor != f->output_data.x->modeline_cursor
- && f->output_data.x->modeline_cursor != 0)
- XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
- f->output_data.x->modeline_cursor = mode_cursor;
- if (cross_cursor != f->output_data.x->cross_cursor
- && f->output_data.x->cross_cursor != 0)
- XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->cross_cursor);
- f->output_data.x->cross_cursor = cross_cursor;
-
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-}
-
-void
-x_set_cursor_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- unsigned long fore_pixel;
-
- if (!EQ (Vx_cursor_fore_pixel, Qnil))
- fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
- WHITE_PIX_DEFAULT (f));
- else
- fore_pixel = f->output_data.x->background_pixel;
- f->output_data.x->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
-
- /* Make sure that the cursor color differs from the background color. */
- if (f->output_data.x->cursor_pixel == f->output_data.x->background_pixel)
- {
- f->output_data.x->cursor_pixel = f->output_data.x->mouse_pixel;
- if (f->output_data.x->cursor_pixel == fore_pixel)
- fore_pixel = f->output_data.x->background_pixel;
- }
- f->output_data.x->cursor_foreground_pixel = fore_pixel;
-
- if (FRAME_X_WINDOW (f) != 0)
- {
- BLOCK_INPUT;
- XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
- f->output_data.x->cursor_pixel);
- XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
- fore_pixel);
- UNBLOCK_INPUT;
-
- if (FRAME_VISIBLE_P (f))
- {
- x_update_cursor (f, 0);
- x_update_cursor (f, 1);
- }
- }
-}
-
-/* Set the border-color of frame F to value described by ARG.
- ARG can be a string naming a color.
- The border-color is used for the border that is drawn by the X server.
- Note that this does not fully take effect if done before
- F has an x-window; it must be redone when the window is created.
-
- Note: this is done in two routines because of the way X10 works.
-
- Note: under X11, this is normally the province of the window manager,
- and so emacs' border colors may be overridden. */
-
-void
-x_set_border_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- unsigned char *str;
- int pix;
-
- CHECK_STRING (arg, 0);
- str = XSTRING (arg)->data;
-
- pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
-
- x_set_border_pixel (f, pix);
-}
-
-/* Set the border-color of frame F to pixel value PIX.
- Note that this does not fully take effect if done before
- F has an x-window. */
-
-x_set_border_pixel (f, pix)
- struct frame *f;
- int pix;
-{
- f->output_data.x->border_pixel = pix;
-
- if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
- {
- Pixmap temp;
- int mask;
-
- BLOCK_INPUT;
- XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- (unsigned long)pix);
- UNBLOCK_INPUT;
-
- if (FRAME_VISIBLE_P (f))
- redraw_frame (f);
- }
-}
-
-void
-x_set_cursor_type (f, arg, oldval)
- FRAME_PTR f;
- Lisp_Object arg, oldval;
-{
- if (EQ (arg, Qbar))
- {
- FRAME_DESIRED_CURSOR (f) = bar_cursor;
- f->output_data.x->cursor_width = 2;
- }
- else if (CONSP (arg) && EQ (XCONS (arg)->car, Qbar)
- && INTEGERP (XCONS (arg)->cdr))
- {
- FRAME_DESIRED_CURSOR (f) = bar_cursor;
- f->output_data.x->cursor_width = XINT (XCONS (arg)->cdr);
- }
- else
- /* Treat anything unknown as "box cursor".
- It was bad to signal an error; people have trouble fixing
- .Xdefaults with Emacs, when it has something bad in it. */
- FRAME_DESIRED_CURSOR (f) = filled_box_cursor;
-
- /* Make sure the cursor gets redrawn. This is overkill, but how
- often do people change cursor types? */
- update_mode_lines++;
-}
-
-void
-x_set_icon_type (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- Lisp_Object tem;
- int result;
-
- if (STRINGP (arg))
- {
- if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
- return;
- }
- else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
- return;
-
- BLOCK_INPUT;
- if (NILP (arg))
- result = x_text_icon (f,
- (char *) XSTRING ((!NILP (f->icon_name)
- ? f->icon_name
- : f->name))->data);
- else
- result = x_bitmap_icon (f, arg);
-
- if (result)
- {
- UNBLOCK_INPUT;
- error ("No icon window available");
- }
-
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-}
-
-/* Return non-nil if frame F wants a bitmap icon. */
-
-Lisp_Object
-x_icon_type (f)
- FRAME_PTR f;
-{
- Lisp_Object tem;
-
- tem = assq_no_quit (Qicon_type, f->param_alist);
- if (CONSP (tem))
- return XCONS (tem)->cdr;
- else
- return Qnil;
-}
-
-void
-x_set_icon_name (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- Lisp_Object tem;
- int result;
-
- if (STRINGP (arg))
- {
- if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
- return;
- }
- else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
- return;
-
- f->icon_name = arg;
-
- if (f->output_data.x->icon_bitmap != 0)
- return;
-
- BLOCK_INPUT;
-
- result = x_text_icon (f,
- (char *) XSTRING ((!NILP (f->icon_name)
- ? f->icon_name
- : !NILP (f->title)
- ? f->title
- : f->name))->data);
-
- if (result)
- {
- UNBLOCK_INPUT;
- error ("No icon window available");
- }
-
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-}
-
-extern Lisp_Object x_new_font ();
-
-void
-x_set_font (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- Lisp_Object result;
-
- CHECK_STRING (arg, 1);
-
- BLOCK_INPUT;
- result = x_new_font (f, XSTRING (arg)->data);
- UNBLOCK_INPUT;
-
- if (EQ (result, Qnil))
- error ("Font `%s' is not defined", XSTRING (arg)->data);
- else if (EQ (result, Qt))
- error ("the characters of the given font have varying widths");
- else if (STRINGP (result))
- {
- recompute_basic_faces (f);
- store_frame_param (f, Qfont, result);
- }
- else
- abort ();
-}
-
-void
-x_set_border_width (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- CHECK_NUMBER (arg, 0);
-
- if (XINT (arg) == f->output_data.x->border_width)
- return;
-
- if (FRAME_X_WINDOW (f) != 0)
- error ("Cannot change the border width of a window");
-
- f->output_data.x->border_width = XINT (arg);
-}
-
-void
-x_set_internal_border_width (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- int mask;
- int old = f->output_data.x->internal_border_width;
-
- CHECK_NUMBER (arg, 0);
- f->output_data.x->internal_border_width = XINT (arg);
- if (f->output_data.x->internal_border_width < 0)
- f->output_data.x->internal_border_width = 0;
-
-#ifdef USE_X_TOOLKIT
- if (f->output_data.x->edit_widget)
- widget_store_internal_border (f->output_data.x->edit_widget,
- f->output_data.x->internal_border_width);
-#endif
-
- if (f->output_data.x->internal_border_width == old)
- return;
-
- if (FRAME_X_WINDOW (f) != 0)
- {
- BLOCK_INPUT;
- x_set_window_size (f, 0, f->width, f->height);
-#if 0
- x_set_resize_hint (f);
-#endif
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
- SET_FRAME_GARBAGED (f);
- }
-}
-
-void
-x_set_visibility (f, value, oldval)
- struct frame *f;
- Lisp_Object value, oldval;
-{
- Lisp_Object frame;
- XSETFRAME (frame, f);
-
- if (NILP (value))
- Fmake_frame_invisible (frame, Qt);
- else if (EQ (value, Qicon))
- Ficonify_frame (frame);
- else
- Fmake_frame_visible (frame);
-}
-
-static void
-x_set_menu_bar_lines_1 (window, n)
- Lisp_Object window;
- int n;
-{
- struct window *w = XWINDOW (window);
-
- XSETFASTINT (w->top, XFASTINT (w->top) + n);
- XSETFASTINT (w->height, XFASTINT (w->height) - n);
-
- /* Handle just the top child in a vertical split. */
- if (!NILP (w->vchild))
- x_set_menu_bar_lines_1 (w->vchild, n);
-
- /* Adjust all children in a horizontal split. */
- for (window = w->hchild; !NILP (window); window = w->next)
- {
- w = XWINDOW (window);
- x_set_menu_bar_lines_1 (window, n);
- }
-}
-
-void
-x_set_menu_bar_lines (f, value, oldval)
- struct frame *f;
- Lisp_Object value, oldval;
-{
- int nlines;
- int olines = FRAME_MENU_BAR_LINES (f);
-
- /* Right now, menu bars don't work properly in minibuf-only frames;
- most of the commands try to apply themselves to the minibuffer
- frame itslef, and get an error because you can't switch buffers
- in or split the minibuffer window. */
- if (FRAME_MINIBUF_ONLY_P (f))
- return;
-
- if (INTEGERP (value))
- nlines = XINT (value);
- else
- nlines = 0;
-
-#ifdef USE_X_TOOLKIT
- FRAME_MENU_BAR_LINES (f) = 0;
- if (nlines)
- {
- FRAME_EXTERNAL_MENU_BAR (f) = 1;
- if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
- /* Make sure next redisplay shows the menu bar. */
- XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
- }
- else
- {
- if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
- free_frame_menubar (f);
- FRAME_EXTERNAL_MENU_BAR (f) = 0;
- if (FRAME_X_P (f))
- f->output_data.x->menubar_widget = 0;
- }
-#else /* not USE_X_TOOLKIT */
- FRAME_MENU_BAR_LINES (f) = nlines;
- x_set_menu_bar_lines_1 (f->root_window, nlines - olines);
-#endif /* not USE_X_TOOLKIT */
-}
-
-/* Change the name of frame F to NAME. If NAME is nil, set F's name to
- x_id_name.
-
- If EXPLICIT is non-zero, that indicates that lisp code is setting the
- name; if NAME is a string, set F's name to NAME and set
- F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
-
- If EXPLICIT is zero, that indicates that Emacs redisplay code is
- suggesting a new name, which lisp code should override; if
- F->explicit_name is set, ignore the new name; otherwise, set it. */
-
-void
-x_set_name (f, name, explicit)
- struct frame *f;
- Lisp_Object name;
- int explicit;
-{
- /* Make sure that requests from lisp code override requests from
- Emacs redisplay code. */
- if (explicit)
- {
- /* If we're switching from explicit to implicit, we had better
- update the mode lines and thereby update the title. */
- if (f->explicit_name && NILP (name))
- update_mode_lines = 1;
-
- f->explicit_name = ! NILP (name);
- }
- else if (f->explicit_name)
- return;
-
- /* If NAME is nil, set the name to the x_id_name. */
- if (NILP (name))
- {
- /* Check for no change needed in this very common case
- before we do any consing. */
- if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
- XSTRING (f->name)->data))
- return;
- name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
- }
- else
- CHECK_STRING (name, 0);
-
- /* Don't change the name if it's already NAME. */
- if (! NILP (Fstring_equal (name, f->name)))
- return;
-
- f->name = name;
-
- /* For setting the frame title, the title parameter should override
- the name parameter. */
- if (! NILP (f->title))
- name = f->title;
-
- if (FRAME_X_WINDOW (f))
- {
- BLOCK_INPUT;
-#ifdef HAVE_X11R4
- {
- XTextProperty text, icon;
- Lisp_Object icon_name;
-
- text.value = XSTRING (name)->data;
- text.encoding = XA_STRING;
- text.format = 8;
- text.nitems = XSTRING (name)->size;
-
- icon_name = (!NILP (f->icon_name) ? f->icon_name : name);
-
- icon.value = XSTRING (icon_name)->data;
- icon.encoding = XA_STRING;
- icon.format = 8;
- icon.nitems = XSTRING (icon_name)->size;
-#ifdef USE_X_TOOLKIT
- XSetWMName (FRAME_X_DISPLAY (f),
- XtWindow (f->output_data.x->widget), &text);
- XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
- &icon);
-#else /* not USE_X_TOOLKIT */
- XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
- XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
-#endif /* not USE_X_TOOLKIT */
- }
-#else /* not HAVE_X11R4 */
- XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- XSTRING (name)->data);
- XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- XSTRING (name)->data);
-#endif /* not HAVE_X11R4 */
- UNBLOCK_INPUT;
- }
-}
-
-/* This function should be called when the user's lisp code has
- specified a name for the frame; the name will override any set by the
- redisplay code. */
-void
-x_explicitly_set_name (f, arg, oldval)
- FRAME_PTR f;
- Lisp_Object arg, oldval;
-{
- x_set_name (f, arg, 1);
-}
-
-/* This function should be called by Emacs redisplay code to set the
- name; names set this way will never override names set by the user's
- lisp code. */
-void
-x_implicitly_set_name (f, arg, oldval)
- FRAME_PTR f;
- Lisp_Object arg, oldval;
-{
- x_set_name (f, arg, 0);
-}
-
-/* Change the title of frame F to NAME.
- If NAME is nil, use the frame name as the title.
-
- If EXPLICIT is non-zero, that indicates that lisp code is setting the
- name; if NAME is a string, set F's name to NAME and set
- F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
-
- If EXPLICIT is zero, that indicates that Emacs redisplay code is
- suggesting a new name, which lisp code should override; if
- F->explicit_name is set, ignore the new name; otherwise, set it. */
-
-void
-x_set_title (f, name)
- struct frame *f;
- Lisp_Object name;
-{
- /* Don't change the title if it's already NAME. */
- if (EQ (name, f->title))
- return;
-
- update_mode_lines = 1;
-
- f->title = name;
-
- if (NILP (name))
- name = f->name;
- else
- CHECK_STRING (name, 0);
-
- if (FRAME_X_WINDOW (f))
- {
- BLOCK_INPUT;
-#ifdef HAVE_X11R4
- {
- XTextProperty text, icon;
- Lisp_Object icon_name;
-
- text.value = XSTRING (name)->data;
- text.encoding = XA_STRING;
- text.format = 8;
- text.nitems = XSTRING (name)->size;
-
- icon_name = (!NILP (f->icon_name) ? f->icon_name : name);
-
- icon.value = XSTRING (icon_name)->data;
- icon.encoding = XA_STRING;
- icon.format = 8;
- icon.nitems = XSTRING (icon_name)->size;
-#ifdef USE_X_TOOLKIT
- XSetWMName (FRAME_X_DISPLAY (f),
- XtWindow (f->output_data.x->widget), &text);
- XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
- &icon);
-#else /* not USE_X_TOOLKIT */
- XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
- XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
-#endif /* not USE_X_TOOLKIT */
- }
-#else /* not HAVE_X11R4 */
- XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- XSTRING (name)->data);
- XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- XSTRING (name)->data);
-#endif /* not HAVE_X11R4 */
- UNBLOCK_INPUT;
- }
-}
-
-void
-x_set_autoraise (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- f->auto_raise = !EQ (Qnil, arg);
-}
-
-void
-x_set_autolower (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- f->auto_lower = !EQ (Qnil, arg);
-}
-
-void
-x_set_unsplittable (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- f->no_split = !NILP (arg);
-}
-
-void
-x_set_vertical_scroll_bars (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
- || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
- || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
- {
- FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
- = (NILP (arg)
- ? vertical_scroll_bar_none
- : EQ (Qright, arg)
- ? vertical_scroll_bar_right
- : vertical_scroll_bar_left);
-
- /* We set this parameter before creating the X window for the
- frame, so we can get the geometry right from the start.
- However, if the window hasn't been created yet, we shouldn't
- call x_set_window_size. */
- if (FRAME_X_WINDOW (f))
- x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
- }
-}
-
-void
-x_set_scroll_bar_width (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- if (NILP (arg))
- {
- FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
- FRAME_SCROLL_BAR_COLS (f) = 3;
- if (FRAME_X_WINDOW (f))
- x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
- }
- else if (INTEGERP (arg) && XINT (arg) > 0
- && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
- {
- int wid = FONT_WIDTH (f->output_data.x->font);
-
- if (XFASTINT (arg) < 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
- Fsignal (Qargs_out_of_range, Fcons (arg, Qnil));
-
- FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
- FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
- if (FRAME_X_WINDOW (f))
- x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
- }
-
- change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0);
- FRAME_CURSOR_X (f) = FRAME_LEFT_SCROLL_BAR_WIDTH (f);
-}
-
-/* Subroutines of creating an X frame. */
-
-/* Make sure that Vx_resource_name is set to a reasonable value.
- Fix it up, or set it to `emacs' if it is too hopeless. */
-
-static void
-validate_x_resource_name ()
-{
- int len;
- /* Number of valid characters in the resource name. */
- int good_count = 0;
- /* Number of invalid characters in the resource name. */
- int bad_count = 0;
- Lisp_Object new;
- int i;
-
- if (STRINGP (Vx_resource_name))
- {
- unsigned char *p = XSTRING (Vx_resource_name)->data;
- int i;
-
- len = XSTRING (Vx_resource_name)->size;
-
- /* Only letters, digits, - and _ are valid in resource names.
- Count the valid characters and count the invalid ones. */
- for (i = 0; i < len; i++)
- {
- int c = p[i];
- if (! ((c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9')
- || c == '-' || c == '_'))
- bad_count++;
- else
- good_count++;
- }
- }
- else
- /* Not a string => completely invalid. */
- bad_count = 5, good_count = 0;
-
- /* If name is valid already, return. */
- if (bad_count == 0)
- return;
-
- /* If name is entirely invalid, or nearly so, use `emacs'. */
- if (good_count == 0
- || (good_count == 1 && bad_count > 0))
- {
- Vx_resource_name = build_string ("emacs");
- return;
- }
-
- /* Name is partly valid. Copy it and replace the invalid characters
- with underscores. */
-
- Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
-
- for (i = 0; i < len; i++)
- {
- int c = XSTRING (new)->data[i];
- if (! ((c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9')
- || c == '-' || c == '_'))
- XSTRING (new)->data[i] = '_';
- }
-}
-
-
-extern char *x_get_string_resource ();
-
-DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
- "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
-This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
-class, where INSTANCE is the name under which Emacs was invoked, or\n\
-the name specified by the `-name' or `-rn' command-line arguments.\n\
-\n\
-The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
-class, respectively. You must specify both of them or neither.\n\
-If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
-and the class is `Emacs.CLASS.SUBCLASS'.")
- (attribute, class, component, subclass)
- Lisp_Object attribute, class, component, subclass;
-{
- register char *value;
- char *name_key;
- char *class_key;
-
- check_x ();
-
- CHECK_STRING (attribute, 0);
- CHECK_STRING (class, 0);
-
- if (!NILP (component))
- CHECK_STRING (component, 1);
- if (!NILP (subclass))
- CHECK_STRING (subclass, 2);
- if (NILP (component) != NILP (subclass))
- error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
-
- validate_x_resource_name ();
-
- /* Allocate space for the components, the dots which separate them,
- and the final '\0'. Make them big enough for the worst case. */
- name_key = (char *) alloca (XSTRING (Vx_resource_name)->size
- + (STRINGP (component)
- ? XSTRING (component)->size : 0)
- + XSTRING (attribute)->size
- + 3);
-
- class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
- + XSTRING (class)->size
- + (STRINGP (subclass)
- ? XSTRING (subclass)->size : 0)
- + 3);
-
- /* Start with emacs.FRAMENAME for the name (the specific one)
- and with `Emacs' for the class key (the general one). */
- strcpy (name_key, XSTRING (Vx_resource_name)->data);
- strcpy (class_key, EMACS_CLASS);
-
- strcat (class_key, ".");
- strcat (class_key, XSTRING (class)->data);
-
- if (!NILP (component))
- {
- strcat (class_key, ".");
- strcat (class_key, XSTRING (subclass)->data);
-
- strcat (name_key, ".");
- strcat (name_key, XSTRING (component)->data);
- }
-
- strcat (name_key, ".");
- strcat (name_key, XSTRING (attribute)->data);
-
- value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
- name_key, class_key);
-
- if (value != (char *) 0)
- return build_string (value);
- else
- return Qnil;
-}
-
-/* Used when C code wants a resource value. */
-
-char *
-x_get_resource_string (attribute, class)
- char *attribute, *class;
-{
- register char *value;
- char *name_key;
- char *class_key;
-
- /* Allocate space for the components, the dots which separate them,
- and the final '\0'. */
- name_key = (char *) alloca (XSTRING (Vinvocation_name)->size
- + strlen (attribute) + 2);
- class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
- + strlen (class) + 2);
-
- sprintf (name_key, "%s.%s",
- XSTRING (Vinvocation_name)->data,
- attribute);
- sprintf (class_key, "%s.%s", EMACS_CLASS, class);
-
- return x_get_string_resource (FRAME_X_DISPLAY_INFO (selected_frame)->xrdb,
- name_key, class_key);
-}
-
-/* Types we might convert a resource string into. */
-enum resource_types
- {
- number, boolean, string, symbol
- };
-
-/* Return the value of parameter PARAM.
-
- First search ALIST, then Vdefault_frame_alist, then the X defaults
- database, using ATTRIBUTE as the attribute name and CLASS as its class.
-
- Convert the resource to the type specified by desired_type.
-
- If no default is specified, return Qunbound. If you call
- x_get_arg, make sure you deal with Qunbound in a reasonable way,
- and don't let it get stored in any Lisp-visible variables! */
-
-static Lisp_Object
-x_get_arg (alist, param, attribute, class, type)
- Lisp_Object alist, param;
- char *attribute;
- char *class;
- enum resource_types type;
-{
- register Lisp_Object tem;
-
- tem = Fassq (param, alist);
- if (EQ (tem, Qnil))
- tem = Fassq (param, Vdefault_frame_alist);
- if (EQ (tem, Qnil))
- {
-
- if (attribute)
- {
- tem = Fx_get_resource (build_string (attribute),
- build_string (class),
- Qnil, Qnil);
-
- if (NILP (tem))
- return Qunbound;
-
- switch (type)
- {
- case number:
- return make_number (atoi (XSTRING (tem)->data));
-
- case boolean:
- tem = Fdowncase (tem);
- if (!strcmp (XSTRING (tem)->data, "on")
- || !strcmp (XSTRING (tem)->data, "true"))
- return Qt;
- else
- return Qnil;
-
- case string:
- return tem;
-
- case symbol:
- /* As a special case, we map the values `true' and `on'
- to Qt, and `false' and `off' to Qnil. */
- {
- Lisp_Object lower;
- lower = Fdowncase (tem);
- if (!strcmp (XSTRING (lower)->data, "on")
- || !strcmp (XSTRING (lower)->data, "true"))
- return Qt;
- else if (!strcmp (XSTRING (lower)->data, "off")
- || !strcmp (XSTRING (lower)->data, "false"))
- return Qnil;
- else
- return Fintern (tem, Qnil);
- }
-
- default:
- abort ();
- }
- }
- else
- return Qunbound;
- }
- return Fcdr (tem);
-}
-
-/* Like x_get_arg, but also record the value in f->param_alist. */
-
-static Lisp_Object
-x_get_and_record_arg (f, alist, param, attribute, class, type)
- struct frame *f;
- Lisp_Object alist, param;
- char *attribute;
- char *class;
- enum resource_types type;
-{
- Lisp_Object value;
-
- value = x_get_arg (alist, param, attribute, class, type);
- if (! NILP (value))
- store_frame_param (f, param, value);
-
- return value;
-}
-
-/* Record in frame F the specified or default value according to ALIST
- of the parameter named PARAM (a Lisp symbol).
- If no value is specified for PARAM, look for an X default for XPROP
- on the frame named NAME.
- If that is not found either, use the value DEFLT. */
-
-static Lisp_Object
-x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
- struct frame *f;
- Lisp_Object alist;
- Lisp_Object prop;
- Lisp_Object deflt;
- char *xprop;
- char *xclass;
- enum resource_types type;
-{
- Lisp_Object tem;
-
- tem = x_get_arg (alist, prop, xprop, xclass, type);
- if (EQ (tem, Qunbound))
- tem = deflt;
- x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
- return tem;
-}
-
-DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
- "Parse an X-style geometry string STRING.\n\
-Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
-The properties returned may include `top', `left', `height', and `width'.\n\
-The value of `left' or `top' may be an integer,\n\
-or a list (+ N) meaning N pixels relative to top/left corner,\n\
-or a list (- N) meaning -N pixels relative to bottom/right corner.")
- (string)
- Lisp_Object string;
-{
- int geometry, x, y;
- unsigned int width, height;
- Lisp_Object result;
-
- CHECK_STRING (string, 0);
-
- geometry = XParseGeometry ((char *) XSTRING (string)->data,
- &x, &y, &width, &height);
-
-#if 0
- if (!!(geometry & XValue) != !!(geometry & YValue))
- error ("Must specify both x and y position, or neither");
-#endif
-
- result = Qnil;
- if (geometry & XValue)
- {
- Lisp_Object element;
-
- if (x >= 0 && (geometry & XNegative))
- element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
- else if (x < 0 && ! (geometry & XNegative))
- element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
- else
- element = Fcons (Qleft, make_number (x));
- result = Fcons (element, result);
- }
-
- if (geometry & YValue)
- {
- Lisp_Object element;
-
- if (y >= 0 && (geometry & YNegative))
- element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
- else if (y < 0 && ! (geometry & YNegative))
- element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
- else
- element = Fcons (Qtop, make_number (y));
- result = Fcons (element, result);
- }
-
- if (geometry & WidthValue)
- result = Fcons (Fcons (Qwidth, make_number (width)), result);
- if (geometry & HeightValue)
- result = Fcons (Fcons (Qheight, make_number (height)), result);
-
- return result;
-}
-
-/* Calculate the desired size and position of this window,
- and return the flags saying which aspects were specified.
-
- This function does not make the coordinates positive. */
-
-#define DEFAULT_ROWS 40
-#define DEFAULT_COLS 80
-
-static int
-x_figure_window_size (f, parms)
- struct frame *f;
- Lisp_Object parms;
-{
- register Lisp_Object tem0, tem1, tem2;
- int height, width, left, top;
- register int geometry;
- long window_prompting = 0;
-
- /* Default values if we fall through.
- Actually, if that happens we should get
- window manager prompting. */
- SET_FRAME_WIDTH (f, DEFAULT_COLS);
- f->height = DEFAULT_ROWS;
- /* Window managers expect that if program-specified
- positions are not (0,0), they're intentional, not defaults. */
- f->output_data.x->top_pos = 0;
- f->output_data.x->left_pos = 0;
-
- tem0 = x_get_arg (parms, Qheight, 0, 0, number);
- tem1 = x_get_arg (parms, Qwidth, 0, 0, number);
- tem2 = x_get_arg (parms, Quser_size, 0, 0, number);
- if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
- {
- if (!EQ (tem0, Qunbound))
- {
- CHECK_NUMBER (tem0, 0);
- f->height = XINT (tem0);
- }
- if (!EQ (tem1, Qunbound))
- {
- CHECK_NUMBER (tem1, 0);
- SET_FRAME_WIDTH (f, XINT (tem1));
- }
- if (!NILP (tem2) && !EQ (tem2, Qunbound))
- window_prompting |= USSize;
- else
- window_prompting |= PSize;
- }
-
- f->output_data.x->vertical_scroll_bar_extra
- = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
- ? 0
- : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
- ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
- : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
- f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
- f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
-
- tem0 = x_get_arg (parms, Qtop, 0, 0, number);
- tem1 = x_get_arg (parms, Qleft, 0, 0, number);
- tem2 = x_get_arg (parms, Quser_position, 0, 0, number);
- if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
- {
- if (EQ (tem0, Qminus))
- {
- f->output_data.x->top_pos = 0;
- window_prompting |= YNegative;
- }
- else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qminus)
- && CONSP (XCONS (tem0)->cdr)
- && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
- {
- f->output_data.x->top_pos = - XINT (XCONS (XCONS (tem0)->cdr)->car);
- window_prompting |= YNegative;
- }
- else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qplus)
- && CONSP (XCONS (tem0)->cdr)
- && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
- {
- f->output_data.x->top_pos = XINT (XCONS (XCONS (tem0)->cdr)->car);
- }
- else if (EQ (tem0, Qunbound))
- f->output_data.x->top_pos = 0;
- else
- {
- CHECK_NUMBER (tem0, 0);
- f->output_data.x->top_pos = XINT (tem0);
- if (f->output_data.x->top_pos < 0)
- window_prompting |= YNegative;
- }
-
- if (EQ (tem1, Qminus))
- {
- f->output_data.x->left_pos = 0;
- window_prompting |= XNegative;
- }
- else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qminus)
- && CONSP (XCONS (tem1)->cdr)
- && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
- {
- f->output_data.x->left_pos = - XINT (XCONS (XCONS (tem1)->cdr)->car);
- window_prompting |= XNegative;
- }
- else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qplus)
- && CONSP (XCONS (tem1)->cdr)
- && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
- {
- f->output_data.x->left_pos = XINT (XCONS (XCONS (tem1)->cdr)->car);
- }
- else if (EQ (tem1, Qunbound))
- f->output_data.x->left_pos = 0;
- else
- {
- CHECK_NUMBER (tem1, 0);
- f->output_data.x->left_pos = XINT (tem1);
- if (f->output_data.x->left_pos < 0)
- window_prompting |= XNegative;
- }
-
- if (!NILP (tem2) && ! EQ (tem2, Qunbound))
- window_prompting |= USPosition;
- else
- window_prompting |= PPosition;
- }
-
- return window_prompting;
-}
-
-#if !defined (HAVE_X11R4) && !defined (HAVE_XSETWMPROTOCOLS)
-
-Status
-XSetWMProtocols (dpy, w, protocols, count)
- Display *dpy;
- Window w;
- Atom *protocols;
- int count;
-{
- Atom prop;
- prop = XInternAtom (dpy, "WM_PROTOCOLS", False);
- if (prop == None) return False;
- XChangeProperty (dpy, w, prop, XA_ATOM, 32, PropModeReplace,
- (unsigned char *) protocols, count);
- return True;
-}
-#endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */
-
-#ifdef USE_X_TOOLKIT
-
-/* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
- WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
- already be present because of the toolkit (Motif adds some of them,
- for example, but Xt doesn't). */
-
-static void
-hack_wm_protocols (f, widget)
- FRAME_PTR f;
- Widget widget;
-{
- Display *dpy = XtDisplay (widget);
- Window w = XtWindow (widget);
- int need_delete = 1;
- int need_focus = 1;
- int need_save = 1;
-
- BLOCK_INPUT;
- {
- Atom type, *atoms = 0;
- int format = 0;
- unsigned long nitems = 0;
- unsigned long bytes_after;
-
- if ((XGetWindowProperty (dpy, w,
- FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
- (long)0, (long)100, False, XA_ATOM,
- &type, &format, &nitems, &bytes_after,
- (unsigned char **) &atoms)
- == Success)
- && format == 32 && type == XA_ATOM)
- while (nitems > 0)
- {
- nitems--;
- if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
- need_delete = 0;
- else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
- need_focus = 0;
- else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
- need_save = 0;
- }
- if (atoms) XFree ((char *) atoms);
- }
- {
- Atom props [10];
- int count = 0;
- if (need_delete)
- props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
- if (need_focus)
- props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus;
- if (need_save)
- props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
- if (count)
- XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
- XA_ATOM, 32, PropModeAppend,
- (unsigned char *) props, count);
- }
- UNBLOCK_INPUT;
-}
-#endif
-
-#ifdef USE_X_TOOLKIT
-
-/* Create and set up the X widget for frame F. */
-
-static void
-x_window (f, window_prompting, minibuffer_only)
- struct frame *f;
- long window_prompting;
- int minibuffer_only;
-{
- XClassHint class_hints;
- XSetWindowAttributes attributes;
- unsigned long attribute_mask;
-
- Widget shell_widget;
- Widget pane_widget;
- Widget frame_widget;
- Arg al [25];
- int ac;
-
- BLOCK_INPUT;
-
- /* Use the resource name as the top-level widget name
- for looking up resources. Make a non-Lisp copy
- for the window manager, so GC relocation won't bother it.
-
- Elsewhere we specify the window name for the window manager. */
-
- {
- char *str = (char *) XSTRING (Vx_resource_name)->data;
- f->namebuf = (char *) xmalloc (strlen (str) + 1);
- strcpy (f->namebuf, str);
- }
-
- ac = 0;
- XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
- XtSetArg (al[ac], XtNinput, 1); ac++;
- XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
- XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
- shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
- applicationShellWidgetClass,
- FRAME_X_DISPLAY (f), al, ac);
-
- f->output_data.x->widget = shell_widget;
- /* maybe_set_screen_title_format (shell_widget); */
-
- pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
- (widget_value *) NULL,
- shell_widget, False,
- (lw_callback) NULL,
- (lw_callback) NULL,
- (lw_callback) NULL);
-
- f->output_data.x->column_widget = pane_widget;
-
- /* mappedWhenManaged to false tells to the paned window to not map/unmap
- the emacs screen when changing menubar. This reduces flickering. */
-
- ac = 0;
- XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
- XtSetArg (al[ac], XtNshowGrip, 0); ac++;
- XtSetArg (al[ac], XtNallowResize, 1); ac++;
- XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
- XtSetArg (al[ac], XtNemacsFrame, f); ac++;
- frame_widget = XtCreateWidget (f->namebuf,
- emacsFrameClass,
- pane_widget, al, ac);
-
- f->output_data.x->edit_widget = frame_widget;
-
- XtManageChild (frame_widget);
-
- /* Do some needed geometry management. */
- {
- int len;
- char *tem, shell_position[32];
- Arg al[2];
- int ac = 0;
- int extra_borders = 0;
- int menubar_size
- = (f->output_data.x->menubar_widget
- ? (f->output_data.x->menubar_widget->core.height
- + f->output_data.x->menubar_widget->core.border_width)
- : 0);
- extern char *lwlib_toolkit_type;
-
-#if 0 /* Experimentally, we now get the right results
- for -geometry -0-0 without this. 24 Aug 96, rms. */
- if (FRAME_EXTERNAL_MENU_BAR (f))
- {
- Dimension ibw = 0;
- XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
- menubar_size += ibw;
- }
-#endif
-
- f->output_data.x->menubar_height = menubar_size;
-
-#ifndef USE_LUCID
- /* Motif seems to need this amount added to the sizes
- specified for the shell widget. The Athena/Lucid widgets don't.
- Both conclusions reached experimentally. -- rms. */
- XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
- &extra_borders, NULL);
- extra_borders *= 2;
-#endif
-
- /* Convert our geometry parameters into a geometry string
- and specify it.
- Note that we do not specify here whether the position
- is a user-specified or program-specified one.
- We pass that information later, in x_wm_set_size_hints. */
- {
- int left = f->output_data.x->left_pos;
- int xneg = window_prompting & XNegative;
- int top = f->output_data.x->top_pos;
- int yneg = window_prompting & YNegative;
- if (xneg)
- left = -left;
- if (yneg)
- top = -top;
-
- if (window_prompting & USPosition)
- sprintf (shell_position, "=%dx%d%c%d%c%d",
- PIXEL_WIDTH (f) + extra_borders,
- PIXEL_HEIGHT (f) + menubar_size + extra_borders,
- (xneg ? '-' : '+'), left,
- (yneg ? '-' : '+'), top);
- else
- sprintf (shell_position, "=%dx%d",
- PIXEL_WIDTH (f) + extra_borders,
- PIXEL_HEIGHT (f) + menubar_size + extra_borders);
- }
-
- len = strlen (shell_position) + 1;
- tem = (char *) xmalloc (len);
- strncpy (tem, shell_position, len);
- XtSetArg (al[ac], XtNgeometry, tem); ac++;
- XtSetValues (shell_widget, al, ac);
- }
-
- XtManageChild (pane_widget);
- XtRealizeWidget (shell_widget);
-
- FRAME_X_WINDOW (f) = XtWindow (frame_widget);
-
- validate_x_resource_name ();
-
- class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
- class_hints.res_class = EMACS_CLASS;
- XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
-
-#ifdef HAVE_X_I18N
-#ifndef X_I18N_INHIBITED
- {
- XIM xim;
- XIC xic = NULL;
-
- xim = XOpenIM (FRAME_X_DISPLAY (f), NULL, NULL, NULL);
-
- if (xim)
- {
- xic = XCreateIC (xim,
- XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
- XNClientWindow, FRAME_X_WINDOW(f),
- XNFocusWindow, FRAME_X_WINDOW(f),
- NULL);
-
- if (xic == 0)
- {
- XCloseIM (xim);
- xim = NULL;
- }
- }
- FRAME_XIM (f) = xim;
- FRAME_XIC (f) = xic;
- }
-#else /* X_I18N_INHIBITED */
- FRAME_XIM (f) = 0;
- FRAME_XIC (f) = 0;
-#endif /* X_I18N_INHIBITED */
-#endif /* HAVE_X_I18N */
-
- f->output_data.x->wm_hints.input = True;
- f->output_data.x->wm_hints.flags |= InputHint;
- XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- &f->output_data.x->wm_hints);
-
- hack_wm_protocols (f, shell_widget);
-
-#ifdef HACK_EDITRES
- XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
-#endif
-
- /* Do a stupid property change to force the server to generate a
- propertyNotify event so that the event_stream server timestamp will
- be initialized to something relevant to the time we created the window.
- */
- XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
- FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
- XA_ATOM, 32, PropModeAppend,
- (unsigned char*) NULL, 0);
-
- /* Make all the standard events reach the Emacs frame. */
- attributes.event_mask = STANDARD_EVENT_SET;
- attribute_mask = CWEventMask;
- XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
- attribute_mask, &attributes);
-
- XtMapWidget (frame_widget);
-
- /* x_set_name normally ignores requests to set the name if the
- requested name is the same as the current name. This is the one
- place where that assumption isn't correct; f->name is set, but
- the X server hasn't been told. */
- {
- Lisp_Object name;
- int explicit = f->explicit_name;
-
- f->explicit_name = 0;
- name = f->name;
- f->name = Qnil;
- x_set_name (f, name, explicit);
- }
-
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->text_cursor);
-
- UNBLOCK_INPUT;
-
- if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
- initialize_frame_menubar (f);
- lw_set_main_areas (pane_widget, f->output_data.x->menubar_widget, frame_widget);
-
- if (FRAME_X_WINDOW (f) == 0)
- error ("Unable to create window");
-}
-
-#else /* not USE_X_TOOLKIT */
-
-/* Create and set up the X window for frame F. */
-
-x_window (f)
- struct frame *f;
-
-{
- XClassHint class_hints;
- XSetWindowAttributes attributes;
- unsigned long attribute_mask;
-
- attributes.background_pixel = f->output_data.x->background_pixel;
- attributes.border_pixel = f->output_data.x->border_pixel;
- attributes.bit_gravity = StaticGravity;
- attributes.backing_store = NotUseful;
- attributes.save_under = True;
- attributes.event_mask = STANDARD_EVENT_SET;
- attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity
-#if 0
- | CWBackingStore | CWSaveUnder
-#endif
- | CWEventMask);
-
- BLOCK_INPUT;
- FRAME_X_WINDOW (f)
- = XCreateWindow (FRAME_X_DISPLAY (f),
- f->output_data.x->parent_desc,
- f->output_data.x->left_pos,
- f->output_data.x->top_pos,
- PIXEL_WIDTH (f), PIXEL_HEIGHT (f),
- f->output_data.x->border_width,
- CopyFromParent, /* depth */
- InputOutput, /* class */
- FRAME_X_DISPLAY_INFO (f)->visual,
- attribute_mask, &attributes);
-#ifdef HAVE_X_I18N
-#ifndef X_I18N_INHIBITED
- {
- XIM xim;
- XIC xic = NULL;
-
- xim = XOpenIM (FRAME_X_DISPLAY(f), NULL, NULL, NULL);
-
- if (xim)
- {
- xic = XCreateIC (xim,
- XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
- XNClientWindow, FRAME_X_WINDOW(f),
- XNFocusWindow, FRAME_X_WINDOW(f),
- NULL);
-
- if (!xic)
- {
- XCloseIM (xim);
- xim = NULL;
- }
- }
-
- FRAME_XIM (f) = xim;
- FRAME_XIC (f) = xic;
- }
-#else /* X_I18N_INHIBITED */
- FRAME_XIM (f) = 0;
- FRAME_XIC (f) = 0;
-#endif /* X_I18N_INHIBITED */
-#endif /* HAVE_X_I18N */
-
- validate_x_resource_name ();
-
- class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
- class_hints.res_class = EMACS_CLASS;
- XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
-
- /* The menubar is part of the ordinary display;
- it does not count in addition to the height of the window. */
- f->output_data.x->menubar_height = 0;
-
- /* This indicates that we use the "Passive Input" input model.
- Unless we do this, we don't get the Focus{In,Out} events that we
- need to draw the cursor correctly. Accursed bureaucrats.
- XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
-
- f->output_data.x->wm_hints.input = True;
- f->output_data.x->wm_hints.flags |= InputHint;
- XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- &f->output_data.x->wm_hints);
- f->output_data.x->wm_hints.icon_pixmap = None;
-
- /* Request "save yourself" and "delete window" commands from wm. */
- {
- Atom protocols[2];
- protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window;
- protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
- XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
- }
-
- /* x_set_name normally ignores requests to set the name if the
- requested name is the same as the current name. This is the one
- place where that assumption isn't correct; f->name is set, but
- the X server hasn't been told. */
- {
- Lisp_Object name;
- int explicit = f->explicit_name;
-
- f->explicit_name = 0;
- name = f->name;
- f->name = Qnil;
- x_set_name (f, name, explicit);
- }
-
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->text_cursor);
-
- UNBLOCK_INPUT;
-
- if (FRAME_X_WINDOW (f) == 0)
- error ("Unable to create window");
-}
-
-#endif /* not USE_X_TOOLKIT */
-
-/* Handle the icon stuff for this window. Perhaps later we might
- want an x_set_icon_position which can be called interactively as
- well. */
-
-static void
-x_icon (f, parms)
- struct frame *f;
- Lisp_Object parms;
-{
- Lisp_Object icon_x, icon_y;
-
- /* Set the position of the icon. Note that twm groups all
- icons in an icon window. */
- icon_x = x_get_and_record_arg (f, parms, Qicon_left, 0, 0, number);
- icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, number);
- if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
- {
- CHECK_NUMBER (icon_x, 0);
- CHECK_NUMBER (icon_y, 0);
- }
- else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
- error ("Both left and top icon corners of icon must be specified");
-
- BLOCK_INPUT;
-
- if (! EQ (icon_x, Qunbound))
- x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
-
- /* Start up iconic or window? */
- x_wm_set_window_state
- (f, (EQ (x_get_arg (parms, Qvisibility, 0, 0, symbol), Qicon)
- ? IconicState
- : NormalState));
-
- x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
- ? f->icon_name
- : f->name))->data);
-
- UNBLOCK_INPUT;
-}
-
-/* Make the GC's needed for this window, setting the
- background, border and mouse colors; also create the
- mouse cursor and the gray border tile. */
-
-static char cursor_bits[] =
- {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
-static void
-x_make_gc (f)
- struct frame *f;
-{
- XGCValues gc_values;
- GC temp_gc;
- XImage tileimage;
-
- BLOCK_INPUT;
-
- /* Create the GC's of this frame.
- Note that many default values are used. */
-
- /* Normal video */
- gc_values.font = f->output_data.x->font->fid;
- gc_values.foreground = f->output_data.x->foreground_pixel;
- gc_values.background = f->output_data.x->background_pixel;
- gc_values.line_width = 0; /* Means 1 using fast algorithm. */
- f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- GCLineWidth | GCFont
- | GCForeground | GCBackground,
- &gc_values);
-
- /* Reverse video style. */
- gc_values.foreground = f->output_data.x->background_pixel;
- gc_values.background = f->output_data.x->foreground_pixel;
- f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- GCFont | GCForeground | GCBackground
- | GCLineWidth,
- &gc_values);
-
- /* Cursor has cursor-color background, background-color foreground. */
- gc_values.foreground = f->output_data.x->background_pixel;
- gc_values.background = f->output_data.x->cursor_pixel;
- gc_values.fill_style = FillOpaqueStippled;
- gc_values.stipple
- = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
- FRAME_X_DISPLAY_INFO (f)->root_window,
- cursor_bits, 16, 16);
- f->output_data.x->cursor_gc
- = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- (GCFont | GCForeground | GCBackground
- | GCFillStyle | GCStipple | GCLineWidth),
- &gc_values);
-
- /* Create the gray border tile used when the pointer is not in
- the frame. Since this depends on the frame's pixel values,
- this must be done on a per-frame basis. */
- f->output_data.x->border_tile
- = (XCreatePixmapFromBitmapData
- (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
- gray_bits, gray_width, gray_height,
- f->output_data.x->foreground_pixel,
- f->output_data.x->background_pixel,
- DefaultDepth (FRAME_X_DISPLAY (f),
- XScreenNumberOfScreen (FRAME_X_SCREEN (f)))));
-
- UNBLOCK_INPUT;
-}
-
-DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
- 1, 1, 0,
- "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
-Returns an Emacs frame object.\n\
-ALIST is an alist of frame parameters.\n\
-If the parameters specify that the frame should not have a minibuffer,\n\
-and do not specify a specific minibuffer window to use,\n\
-then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
-be shared by the new frame.\n\
-\n\
-This function is an internal primitive--use `make-frame' instead.")
- (parms)
- Lisp_Object parms;
-{
- struct frame *f;
- Lisp_Object frame, tem;
- Lisp_Object name;
- int minibuffer_only = 0;
- long window_prompting = 0;
- int width, height;
- int count = specpdl_ptr - specpdl;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
- Lisp_Object display;
- struct x_display_info *dpyinfo;
- Lisp_Object parent;
- struct kboard *kb;
-
- check_x ();
-
- /* Use this general default value to start with
- until we know if this frame has a specified name. */
- Vx_resource_name = Vinvocation_name;
-
- display = x_get_arg (parms, Qdisplay, 0, 0, string);
- if (EQ (display, Qunbound))
- display = Qnil;
- dpyinfo = check_x_display_info (display);
-#ifdef MULTI_KBOARD
- kb = dpyinfo->kboard;
-#else
- kb = &the_only_kboard;
-#endif
-
- name = x_get_arg (parms, Qname, "name", "Name", string);
- if (!STRINGP (name)
- && ! EQ (name, Qunbound)
- && ! NILP (name))
- error ("Invalid frame name--not a string or nil");
-
- if (STRINGP (name))
- Vx_resource_name = name;
-
- /* See if parent window is specified. */
- parent = x_get_arg (parms, Qparent_id, NULL, NULL, number);
- if (EQ (parent, Qunbound))
- parent = Qnil;
- if (! NILP (parent))
- CHECK_NUMBER (parent, 0);
-
- /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
- /* No need to protect DISPLAY because that's not used after passing
- it to make_frame_without_minibuffer. */
- frame = Qnil;
- GCPRO4 (parms, parent, name, frame);
- tem = x_get_arg (parms, Qminibuffer, "minibuffer", "Minibuffer", symbol);
- if (EQ (tem, Qnone) || NILP (tem))
- f = make_frame_without_minibuffer (Qnil, kb, display);
- else if (EQ (tem, Qonly))
- {
- f = make_minibuffer_frame ();
- minibuffer_only = 1;
- }
- else if (WINDOWP (tem))
- f = make_frame_without_minibuffer (tem, kb, display);
- else
- f = make_frame (1);
-
- XSETFRAME (frame, f);
-
- /* Note that X Windows does support scroll bars. */
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
-
- f->output_method = output_x_window;
- f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
- bzero (f->output_data.x, sizeof (struct x_output));
- f->output_data.x->icon_bitmap = -1;
-
- f->icon_name
- = x_get_arg (parms, Qicon_name, "iconName", "Title", string);
- if (! STRINGP (f->icon_name))
- f->icon_name = Qnil;
-
- FRAME_X_DISPLAY_INFO (f) = dpyinfo;
-#ifdef MULTI_KBOARD
- FRAME_KBOARD (f) = kb;
-#endif
-
- /* Specify the parent under which to make this X window. */
-
- if (!NILP (parent))
- {
- f->output_data.x->parent_desc = parent;
- f->output_data.x->explicit_parent = 1;
- }
- else
- {
- f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
- f->output_data.x->explicit_parent = 0;
- }
-
- /* Note that the frame has no physical cursor right now. */
- f->phys_cursor_x = -1;
-
- /* Set the name; the functions to which we pass f expect the name to
- be set. */
- if (EQ (name, Qunbound) || NILP (name))
- {
- f->name = build_string (dpyinfo->x_id_name);
- f->explicit_name = 0;
- }
- else
- {
- f->name = name;
- f->explicit_name = 1;
- /* use the frame's title when getting resources for this frame. */
- specbind (Qx_resource_name, name);
- }
-
- /* Extract the window parameters from the supplied values
- that are needed to determine window geometry. */
- {
- Lisp_Object font;
-
- font = x_get_arg (parms, Qfont, "font", "Font", string);
- BLOCK_INPUT;
- /* First, try whatever font the caller has specified. */
- if (STRINGP (font))
- font = x_new_font (f, XSTRING (font)->data);
- /* Try out a font which we hope has bold and italic variations. */
- if (!STRINGP (font))
- font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
- if (! STRINGP (font))
- font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
- if (! STRINGP (font))
- /* This was formerly the first thing tried, but it finds too many fonts
- and takes too long. */
- font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
- /* If those didn't work, look for something which will at least work. */
- if (! STRINGP (font))
- font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
- UNBLOCK_INPUT;
- if (! STRINGP (font))
- font = build_string ("fixed");
-
- x_default_parameter (f, parms, Qfont, font,
- "font", "Font", string);
- }
-
-#ifdef USE_LUCID
- /* Prevent lwlib/xlwmenu.c from crashing because of a bug
- whereby it fails to get any font. */
- xlwmenu_default_font = f->output_data.x->font;
-#endif
-
- x_default_parameter (f, parms, Qborder_width, make_number (2),
- "borderwidth", "BorderWidth", number);
- /* This defaults to 2 in order to match xterm. We recognize either
- internalBorderWidth or internalBorder (which is what xterm calls
- it). */
- if (NILP (Fassq (Qinternal_border_width, parms)))
- {
- Lisp_Object value;
-
- value = x_get_arg (parms, Qinternal_border_width,
- "internalBorder", "internalBorder", number);
- if (! EQ (value, Qunbound))
- parms = Fcons (Fcons (Qinternal_border_width, value),
- parms);
- }
- x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
- "internalBorderWidth", "internalBorderWidth", number);
- x_default_parameter (f, parms, Qvertical_scroll_bars, Qleft,
- "verticalScrollBars", "ScrollBars", boolean);
-
- /* Also do the stuff which must be set before the window exists. */
- x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
- "foreground", "Foreground", string);
- x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
- "background", "Background", string);
- x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
- "pointerColor", "Foreground", string);
- x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
- "cursorColor", "Foreground", string);
- x_default_parameter (f, parms, Qborder_color, build_string ("black"),
- "borderColor", "BorderColor", string);
-
- x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
- "menuBar", "MenuBar", number);
- x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
- "scrollBarWidth", "ScrollBarWidth", number);
- x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
- "bufferPredicate", "BufferPredicate", symbol);
- x_default_parameter (f, parms, Qtitle, Qnil,
- "title", "Title", string);
-
- f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
- window_prompting = x_figure_window_size (f, parms);
-
- if (window_prompting & XNegative)
- {
- if (window_prompting & YNegative)
- f->output_data.x->win_gravity = SouthEastGravity;
- else
- f->output_data.x->win_gravity = NorthEastGravity;
- }
- else
- {
- if (window_prompting & YNegative)
- f->output_data.x->win_gravity = SouthWestGravity;
- else
- f->output_data.x->win_gravity = NorthWestGravity;
- }
-
- f->output_data.x->size_hint_flags = window_prompting;
-
-#ifdef USE_X_TOOLKIT
- x_window (f, window_prompting, minibuffer_only);
-#else
- x_window (f);
-#endif
- x_icon (f, parms);
- x_make_gc (f);
- init_frame_faces (f);
-
- /* We need to do this after creating the X window, so that the
- icon-creation functions can say whose icon they're describing. */
- x_default_parameter (f, parms, Qicon_type, Qnil,
- "bitmapIcon", "BitmapIcon", symbol);
-
- x_default_parameter (f, parms, Qauto_raise, Qnil,
- "autoRaise", "AutoRaiseLower", boolean);
- x_default_parameter (f, parms, Qauto_lower, Qnil,
- "autoLower", "AutoRaiseLower", boolean);
- x_default_parameter (f, parms, Qcursor_type, Qbox,
- "cursorType", "CursorType", symbol);
-
- /* Dimensions, especially f->height, must be done via change_frame_size.
- Change will not be effected unless different from the current
- f->height. */
- width = f->width;
- height = f->height;
- f->height = 0;
- SET_FRAME_WIDTH (f, 0);
- change_frame_size (f, height, width, 1, 0);
-
- /* Tell the server what size and position, etc, we want,
- and how badly we want them. */
- BLOCK_INPUT;
- x_wm_set_size_hint (f, window_prompting, 0);
- UNBLOCK_INPUT;
-
- tem = x_get_arg (parms, Qunsplittable, 0, 0, boolean);
- f->no_split = minibuffer_only || EQ (tem, Qt);
-
- UNGCPRO;
-
- /* It is now ok to make the frame official
- even if we get an error below.
- And the frame needs to be on Vframe_list
- or making it visible won't work. */
- Vframe_list = Fcons (frame, Vframe_list);
-
- /* Now that the frame is official, it counts as a reference to
- its display. */
- FRAME_X_DISPLAY_INFO (f)->reference_count++;
-
- /* Make the window appear on the frame and enable display,
- unless the caller says not to. However, with explicit parent,
- Emacs cannot control visibility, so don't try. */
- if (! f->output_data.x->explicit_parent)
- {
- Lisp_Object visibility;
-
- visibility = x_get_arg (parms, Qvisibility, 0, 0, symbol);
- if (EQ (visibility, Qunbound))
- visibility = Qt;
-
- if (EQ (visibility, Qicon))
- x_iconify_frame (f);
- else if (! NILP (visibility))
- x_make_frame_visible (f);
- else
- /* Must have been Qnil. */
- ;
- }
-
- return unbind_to (count, frame);
-}
-
-/* FRAME is used only to get a handle on the X display. We don't pass the
- display info directly because we're called from frame.c, which doesn't
- know about that structure. */
-
-Lisp_Object
-x_get_focus_frame (frame)
- struct frame *frame;
-{
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
- Lisp_Object xfocus;
- if (! dpyinfo->x_focus_frame)
- return Qnil;
-
- XSETFRAME (xfocus, dpyinfo->x_focus_frame);
- return xfocus;
-}
-
-DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 4, 0,
- "Return a list of the names of available fonts matching PATTERN.\n\
-If optional arguments FACE and FRAME are specified, return only fonts\n\
-the same size as FACE on FRAME.\n\
-\n\
-PATTERN is a string, perhaps with wildcard characters;\n\
- the * character matches any substring, and\n\
- the ? character matches any single character.\n\
- PATTERN is case-insensitive.\n\
-FACE is a face name--a symbol.\n\
-\n\
-The return value is a list of strings, suitable as arguments to\n\
-set-face-font.\n\
-\n\
-Fonts Emacs can't use (i.e. proportional fonts) may or may not be excluded\n\
-even if they match PATTERN and FACE.\n\
-\n\
-The optional fourth argument MAXIMUM sets a limit on how many\n\
-fonts to match. The first MAXIMUM fonts are reported.")
- (pattern, face, frame, maximum)
- Lisp_Object pattern, face, frame, maximum;
-{
- int num_fonts;
- char **names;
-#ifndef BROKEN_XLISTFONTSWITHINFO
- XFontStruct *info;
-#endif
- XFontStruct *size_ref;
- Lisp_Object list;
- FRAME_PTR f;
- Lisp_Object key;
- int maxnames;
-
- check_x ();
- CHECK_STRING (pattern, 0);
- if (!NILP (face))
- CHECK_SYMBOL (face, 1);
-
- if (NILP (maximum))
- maxnames = 2000;
- else
- {
- CHECK_NATNUM (maximum, 0);
- maxnames = XINT (maximum);
- }
-
- f = check_x_frame (frame);
-
- /* Determine the width standard for comparison with the fonts we find. */
-
- if (NILP (face))
- size_ref = 0;
- else
- {
- int face_id;
-
- /* Don't die if we get called with a terminal frame. */
- if (! FRAME_X_P (f))
- error ("Non-X frame used in `x-list-fonts'");
-
- face_id = face_name_id_number (f, face);
-
- if (face_id < 0 || face_id >= FRAME_N_PARAM_FACES (f)
- || FRAME_PARAM_FACES (f) [face_id] == 0)
- size_ref = f->output_data.x->font;
- else
- {
- size_ref = FRAME_PARAM_FACES (f) [face_id]->font;
- if (size_ref == (XFontStruct *) (~0))
- size_ref = f->output_data.x->font;
- }
- }
-
- /* See if we cached the result for this particular query. */
- key = Fcons (pattern, maximum);
- list = Fassoc (key,
- XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
-
- /* We have info in the cache for this PATTERN. */
- if (!NILP (list))
- {
- Lisp_Object tem, newlist;
-
- /* We have info about this pattern. */
- list = XCONS (list)->cdr;
-
- if (size_ref == 0)
- return list;
-
- BLOCK_INPUT;
-
- /* Filter the cached info and return just the fonts that match FACE. */
- newlist = Qnil;
- for (tem = list; CONSP (tem); tem = XCONS (tem)->cdr)
- {
- XFontStruct *thisinfo;
-
- x_catch_errors (FRAME_X_DISPLAY (f));
-
- thisinfo = XLoadQueryFont (FRAME_X_DISPLAY (f),
- XSTRING (XCONS (tem)->car)->data);
-
- x_check_errors (FRAME_X_DISPLAY (f), "XLoadQueryFont failure: %s");
- x_uncatch_errors (FRAME_X_DISPLAY (f));
-
- if (thisinfo && same_size_fonts (thisinfo, size_ref))
- newlist = Fcons (XCONS (tem)->car, newlist);
-
- if (thisinfo != 0)
- XFreeFont (FRAME_X_DISPLAY (f), thisinfo);
- }
-
- UNBLOCK_INPUT;
-
- return newlist;
- }
-
- BLOCK_INPUT;
-
- x_catch_errors (FRAME_X_DISPLAY (f));
-
- /* Solaris 2.3 has a bug in XListFontsWithInfo. */
-#ifndef BROKEN_XLISTFONTSWITHINFO
- if (size_ref)
- names = XListFontsWithInfo (FRAME_X_DISPLAY (f),
- XSTRING (pattern)->data,
- maxnames,
- &num_fonts, /* count_return */
- &info); /* info_return */
- else
-#endif
- names = XListFonts (FRAME_X_DISPLAY (f),
- XSTRING (pattern)->data,
- maxnames,
- &num_fonts); /* count_return */
-
- x_check_errors (FRAME_X_DISPLAY (f), "XListFonts failure: %s");
- x_uncatch_errors (FRAME_X_DISPLAY (f));
-
- UNBLOCK_INPUT;
-
- list = Qnil;
-
- if (names)
- {
- int i;
- Lisp_Object full_list;
-
- /* Make a list of all the fonts we got back.
- Store that in the font cache for the display. */
- full_list = Qnil;
- for (i = 0; i < num_fonts; i++)
- full_list = Fcons (build_string (names[i]), full_list);
- XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr
- = Fcons (Fcons (key, full_list),
- XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
-
- /* Make a list of the fonts that have the right width. */
- list = Qnil;
- for (i = 0; i < num_fonts; i++)
- {
- int keeper;
-
- if (!size_ref)
- keeper = 1;
- else
- {
-#ifdef BROKEN_XLISTFONTSWITHINFO
- XFontStruct *thisinfo;
-
- BLOCK_INPUT;
-
- x_catch_errors (FRAME_X_DISPLAY (f));
- thisinfo = XLoadQueryFont (FRAME_X_DISPLAY (f), names[i]);
- x_check_errors (FRAME_X_DISPLAY (f),
- "XLoadQueryFont failure: %s");
- x_uncatch_errors (FRAME_X_DISPLAY (f));
-
- UNBLOCK_INPUT;
-
- keeper = thisinfo && same_size_fonts (thisinfo, size_ref);
- BLOCK_INPUT;
- if (thisinfo && ! keeper)
- XFreeFont (FRAME_X_DISPLAY (f), thisinfo);
- else if (thisinfo)
- XFreeFontInfo (NULL, thisinfo, 1);
- UNBLOCK_INPUT;
-#else
- keeper = same_size_fonts (&info[i], size_ref);
-#endif
- }
- if (keeper)
- list = Fcons (build_string (names[i]), list);
- }
- list = Fnreverse (list);
-
- BLOCK_INPUT;
-#ifndef BROKEN_XLISTFONTSWITHINFO
- if (size_ref)
- XFreeFontInfo (names, info, num_fonts);
- else
-#endif
- XFreeFontNames (names);
- UNBLOCK_INPUT;
- }
-
- return list;
-}
-
-
-DEFUN ("x-color-defined-p", Fx_color_defined_p, Sx_color_defined_p, 1, 2, 0,
- "Return non-nil if color COLOR is supported on frame FRAME.\n\
-If FRAME is omitted or nil, use the selected frame.")
- (color, frame)
- Lisp_Object color, frame;
-{
- XColor foo;
- FRAME_PTR f = check_x_frame (frame);
-
- CHECK_STRING (color, 1);
-
- if (defined_color (f, XSTRING (color)->data, &foo, 0))
- return Qt;
- else
- return Qnil;
-}
-
-DEFUN ("x-color-values", Fx_color_values, Sx_color_values, 1, 2, 0,
- "Return a description of the color named COLOR on frame FRAME.\n\
-The value is a list of integer RGB values--(RED GREEN BLUE).\n\
-These values appear to range from 0 to 65280 or 65535, depending\n\
-on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
-If FRAME is omitted or nil, use the selected frame.")
- (color, frame)
- Lisp_Object color, frame;
-{
- XColor foo;
- FRAME_PTR f = check_x_frame (frame);
-
- CHECK_STRING (color, 1);
-
- if (defined_color (f, XSTRING (color)->data, &foo, 0))
- {
- Lisp_Object rgb[3];
-
- rgb[0] = make_number (foo.red);
- rgb[1] = make_number (foo.green);
- rgb[2] = make_number (foo.blue);
- return Flist (3, rgb);
- }
- else
- return Qnil;
-}
-
-DEFUN ("x-display-color-p", Fx_display_color_p, Sx_display_color_p, 0, 1, 0,
- "Return t if the X display supports color.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- if (dpyinfo->n_planes <= 2)
- return Qnil;
-
- switch (dpyinfo->visual->class)
- {
- case StaticColor:
- case PseudoColor:
- case TrueColor:
- case DirectColor:
- return Qt;
-
- default:
- return Qnil;
- }
-}
-
-DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
- 0, 1, 0,
- "Return t if the X display supports shades of gray.\n\
-Note that color displays do support shades of gray.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- if (dpyinfo->n_planes <= 1)
- return Qnil;
-
- switch (dpyinfo->visual->class)
- {
- case StaticColor:
- case PseudoColor:
- case TrueColor:
- case DirectColor:
- case StaticGray:
- case GrayScale:
- return Qt;
-
- default:
- return Qnil;
- }
-}
-
-DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
- 0, 1, 0,
- "Returns the width in pixels of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (dpyinfo->width);
-}
-
-DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
- Sx_display_pixel_height, 0, 1, 0,
- "Returns the height in pixels of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (dpyinfo->height);
-}
-
-DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
- 0, 1, 0,
- "Returns the number of bitplanes of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (dpyinfo->n_planes);
-}
-
-DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
- 0, 1, 0,
- "Returns the number of color cells of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (DisplayCells (dpyinfo->display,
- XScreenNumberOfScreen (dpyinfo->screen)));
-}
-
-DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
- Sx_server_max_request_size,
- 0, 1, 0,
- "Returns the maximum request size of the X server of display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (MAXREQUEST (dpyinfo->display));
-}
-
-DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
- "Returns the vendor ID string of the X server of display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
- char *vendor = ServerVendor (dpyinfo->display);
-
- if (! vendor) vendor = "";
- return build_string (vendor);
-}
-
-DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
- "Returns the version numbers of the X server of display DISPLAY.\n\
-The value is a list of three integers: the major and minor\n\
-version numbers of the X Protocol in use, and the vendor-specific release\n\
-number. See also the function `x-server-vendor'.\n\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
- Display *dpy = dpyinfo->display;
-
- return Fcons (make_number (ProtocolVersion (dpy)),
- Fcons (make_number (ProtocolRevision (dpy)),
- Fcons (make_number (VendorRelease (dpy)), Qnil)));
-}
-
-DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
- "Returns the number of screens on the X server of display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (ScreenCount (dpyinfo->display));
-}
-
-DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
- "Returns the height in millimeters of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (HeightMMOfScreen (dpyinfo->screen));
-}
-
-DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
- "Returns the width in millimeters of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (WidthMMOfScreen (dpyinfo->screen));
-}
-
-DEFUN ("x-display-backing-store", Fx_display_backing_store,
- Sx_display_backing_store, 0, 1, 0,
- "Returns an indication of whether X display DISPLAY does backing store.\n\
-The value may be `always', `when-mapped', or `not-useful'.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- switch (DoesBackingStore (dpyinfo->screen))
- {
- case Always:
- return intern ("always");
-
- case WhenMapped:
- return intern ("when-mapped");
-
- case NotUseful:
- return intern ("not-useful");
-
- default:
- error ("Strange value for BackingStore parameter of screen");
- }
-}
-
-DEFUN ("x-display-visual-class", Fx_display_visual_class,
- Sx_display_visual_class, 0, 1, 0,
- "Returns the visual class of the X display DISPLAY.\n\
-The value is one of the symbols `static-gray', `gray-scale',\n\
-`static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- switch (dpyinfo->visual->class)
- {
- case StaticGray: return (intern ("static-gray"));
- case GrayScale: return (intern ("gray-scale"));
- case StaticColor: return (intern ("static-color"));
- case PseudoColor: return (intern ("pseudo-color"));
- case TrueColor: return (intern ("true-color"));
- case DirectColor: return (intern ("direct-color"));
- default:
- error ("Display has an unknown visual class");
- }
-}
-
-DEFUN ("x-display-save-under", Fx_display_save_under,
- Sx_display_save_under, 0, 1, 0,
- "Returns t if the X display DISPLAY supports the save-under feature.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- if (DoesSaveUnders (dpyinfo->screen) == True)
- return Qt;
- else
- return Qnil;
-}
-
-int
-x_pixel_width (f)
- register struct frame *f;
-{
- return PIXEL_WIDTH (f);
-}
-
-int
-x_pixel_height (f)
- register struct frame *f;
-{
- return PIXEL_HEIGHT (f);
-}
-
-int
-x_char_width (f)
- register struct frame *f;
-{
- return FONT_WIDTH (f->output_data.x->font);
-}
-
-int
-x_char_height (f)
- register struct frame *f;
-{
- return f->output_data.x->line_height;
-}
-
-int
-x_screen_planes (frame)
- Lisp_Object frame;
-{
- return FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes;
-}
-
-#if 0 /* These no longer seem like the right way to do things. */
-
-/* Draw a rectangle on the frame with left top corner including
- the character specified by LEFT_CHAR and TOP_CHAR. The rectangle is
- CHARS by LINES wide and long and is the color of the cursor. */
-
-void
-x_rectangle (f, gc, left_char, top_char, chars, lines)
- register struct frame *f;
- GC gc;
- register int top_char, left_char, chars, lines;
-{
- int width;
- int height;
- int left = (left_char * FONT_WIDTH (f->output_data.x->font)
- + f->output_data.x->internal_border_width);
- int top = (top_char * f->output_data.x->line_height
- + f->output_data.x->internal_border_width);
-
- if (chars < 0)
- width = FONT_WIDTH (f->output_data.x->font) / 2;
- else
- width = FONT_WIDTH (f->output_data.x->font) * chars;
- if (lines < 0)
- height = f->output_data.x->line_height / 2;
- else
- height = f->output_data.x->line_height * lines;
-
- XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- gc, left, top, width, height);
-}
-
-DEFUN ("x-draw-rectangle", Fx_draw_rectangle, Sx_draw_rectangle, 5, 5, 0,
- "Draw a rectangle on FRAME between coordinates specified by\n\
-numbers X0, Y0, X1, Y1 in the cursor pixel.")
- (frame, X0, Y0, X1, Y1)
- register Lisp_Object frame, X0, X1, Y0, Y1;
-{
- register int x0, y0, x1, y1, top, left, n_chars, n_lines;
-
- CHECK_LIVE_FRAME (frame, 0);
- CHECK_NUMBER (X0, 0);
- CHECK_NUMBER (Y0, 1);
- CHECK_NUMBER (X1, 2);
- CHECK_NUMBER (Y1, 3);
-
- x0 = XINT (X0);
- x1 = XINT (X1);
- y0 = XINT (Y0);
- y1 = XINT (Y1);
-
- if (y1 > y0)
- {
- top = y0;
- n_lines = y1 - y0 + 1;
- }
- else
- {
- top = y1;
- n_lines = y0 - y1 + 1;
- }
-
- if (x1 > x0)
- {
- left = x0;
- n_chars = x1 - x0 + 1;
- }
- else
- {
- left = x1;
- n_chars = x0 - x1 + 1;
- }
-
- BLOCK_INPUT;
- x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->cursor_gc,
- left, top, n_chars, n_lines);
- UNBLOCK_INPUT;
-
- return Qt;
-}
-
-DEFUN ("x-erase-rectangle", Fx_erase_rectangle, Sx_erase_rectangle, 5, 5, 0,
- "Draw a rectangle drawn on FRAME between coordinates\n\
-X0, Y0, X1, Y1 in the regular background-pixel.")
- (frame, X0, Y0, X1, Y1)
- register Lisp_Object frame, X0, Y0, X1, Y1;
-{
- register int x0, y0, x1, y1, top, left, n_chars, n_lines;
-
- CHECK_LIVE_FRAME (frame, 0);
- CHECK_NUMBER (X0, 0);
- CHECK_NUMBER (Y0, 1);
- CHECK_NUMBER (X1, 2);
- CHECK_NUMBER (Y1, 3);
-
- x0 = XINT (X0);
- x1 = XINT (X1);
- y0 = XINT (Y0);
- y1 = XINT (Y1);
-
- if (y1 > y0)
- {
- top = y0;
- n_lines = y1 - y0 + 1;
- }
- else
- {
- top = y1;
- n_lines = y0 - y1 + 1;
- }
-
- if (x1 > x0)
- {
- left = x0;
- n_chars = x1 - x0 + 1;
- }
- else
- {
- left = x1;
- n_chars = x0 - x1 + 1;
- }
-
- BLOCK_INPUT;
- x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->reverse_gc,
- left, top, n_chars, n_lines);
- UNBLOCK_INPUT;
-
- return Qt;
-}
-
-/* Draw lines around the text region beginning at the character position
- TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y. GC specifies the
- pixel and line characteristics. */
-
-#define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
-
-static void
-outline_region (f, gc, top_x, top_y, bottom_x, bottom_y)
- register struct frame *f;
- GC gc;
- int top_x, top_y, bottom_x, bottom_y;
-{
- register int ibw = f->output_data.x->internal_border_width;
- register int font_w = FONT_WIDTH (f->output_data.x->font);
- register int font_h = f->output_data.x->line_height;
- int y = top_y;
- int x = line_len (y);
- XPoint *pixel_points
- = (XPoint *) alloca (((bottom_y - top_y + 2) * 4) * sizeof (XPoint));
- register XPoint *this_point = pixel_points;
-
- /* Do the horizontal top line/lines */
- if (top_x == 0)
- {
- this_point->x = ibw;
- this_point->y = ibw + (font_h * top_y);
- this_point++;
- if (x == 0)
- this_point->x = ibw + (font_w / 2); /* Half-size for newline chars. */
- else
- this_point->x = ibw + (font_w * x);
- this_point->y = (this_point - 1)->y;
- }
- else
- {
- this_point->x = ibw;
- this_point->y = ibw + (font_h * (top_y + 1));
- this_point++;
- this_point->x = ibw + (font_w * top_x);
- this_point->y = (this_point - 1)->y;
- this_point++;
- this_point->x = (this_point - 1)->x;
- this_point->y = ibw + (font_h * top_y);
- this_point++;
- this_point->x = ibw + (font_w * x);
- this_point->y = (this_point - 1)->y;
- }
-
- /* Now do the right side. */
- while (y < bottom_y)
- { /* Right vertical edge */
- this_point++;
- this_point->x = (this_point - 1)->x;
- this_point->y = ibw + (font_h * (y + 1));
- this_point++;
-
- y++; /* Horizontal connection to next line */
- x = line_len (y);
- if (x == 0)
- this_point->x = ibw + (font_w / 2);
- else
- this_point->x = ibw + (font_w * x);
-
- this_point->y = (this_point - 1)->y;
- }
-
- /* Now do the bottom and connect to the top left point. */
- this_point->x = ibw + (font_w * (bottom_x + 1));
-
- this_point++;
- this_point->x = (this_point - 1)->x;
- this_point->y = ibw + (font_h * (bottom_y + 1));
- this_point++;
- this_point->x = ibw;
- this_point->y = (this_point - 1)->y;
- this_point++;
- this_point->x = pixel_points->x;
- this_point->y = pixel_points->y;
-
- XDrawLines (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- gc, pixel_points,
- (this_point - pixel_points + 1), CoordModeOrigin);
-}
-
-DEFUN ("x-contour-region", Fx_contour_region, Sx_contour_region, 1, 1, 0,
- "Highlight the region between point and the character under the mouse\n\
-selected frame.")
- (event)
- register Lisp_Object event;
-{
- register int x0, y0, x1, y1;
- register struct frame *f = selected_frame;
- register int p1, p2;
-
- CHECK_CONS (event, 0);
-
- BLOCK_INPUT;
- x0 = XINT (Fcar (Fcar (event)));
- y0 = XINT (Fcar (Fcdr (Fcar (event))));
-
- /* If the mouse is past the end of the line, don't that area. */
- /* ReWrite this... */
-
- x1 = f->cursor_x;
- y1 = f->cursor_y;
-
- if (y1 > y0) /* point below mouse */
- outline_region (f, f->output_data.x->cursor_gc,
- x0, y0, x1, y1);
- else if (y1 < y0) /* point above mouse */
- outline_region (f, f->output_data.x->cursor_gc,
- x1, y1, x0, y0);
- else /* same line: draw horizontal rectangle */
- {
- if (x1 > x0)
- x_rectangle (f, f->output_data.x->cursor_gc,
- x0, y0, (x1 - x0 + 1), 1);
- else if (x1 < x0)
- x_rectangle (f, f->output_data.x->cursor_gc,
- x1, y1, (x0 - x1 + 1), 1);
- }
-
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-
- return Qnil;
-}
-
-DEFUN ("x-uncontour-region", Fx_uncontour_region, Sx_uncontour_region, 1, 1, 0,
- "Erase any highlighting of the region between point and the character\n\
-at X, Y on the selected frame.")
- (event)
- register Lisp_Object event;
-{
- register int x0, y0, x1, y1;
- register struct frame *f = selected_frame;
-
- BLOCK_INPUT;
- x0 = XINT (Fcar (Fcar (event)));
- y0 = XINT (Fcar (Fcdr (Fcar (event))));
- x1 = f->cursor_x;
- y1 = f->cursor_y;
-
- if (y1 > y0) /* point below mouse */
- outline_region (f, f->output_data.x->reverse_gc,
- x0, y0, x1, y1);
- else if (y1 < y0) /* point above mouse */
- outline_region (f, f->output_data.x->reverse_gc,
- x1, y1, x0, y0);
- else /* same line: draw horizontal rectangle */
- {
- if (x1 > x0)
- x_rectangle (f, f->output_data.x->reverse_gc,
- x0, y0, (x1 - x0 + 1), 1);
- else if (x1 < x0)
- x_rectangle (f, f->output_data.x->reverse_gc,
- x1, y1, (x0 - x1 + 1), 1);
- }
- UNBLOCK_INPUT;
-
- return Qnil;
-}
-
-#if 0
-int contour_begin_x, contour_begin_y;
-int contour_end_x, contour_end_y;
-int contour_npoints;
-
-/* Clip the top part of the contour lines down (and including) line Y_POS.
- If X_POS is in the middle (rather than at the end) of the line, drop
- down a line at that character. */
-
-static void
-clip_contour_top (y_pos, x_pos)
-{
- register XPoint *begin = contour_lines[y_pos].top_left;
- register XPoint *end;
- register int npoints;
- register struct display_line *line = selected_frame->phys_lines[y_pos + 1];
-
- if (x_pos >= line->len - 1) /* Draw one, straight horizontal line. */
- {
- end = contour_lines[y_pos].top_right;
- npoints = (end - begin + 1);
- XDrawLines (x_current_display, contour_window,
- contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
-
- bcopy (end, begin + 1, contour_last_point - end + 1);
- contour_last_point -= (npoints - 2);
- XDrawLines (x_current_display, contour_window,
- contour_erase_gc, begin, 2, CoordModeOrigin);
- XFlush (x_current_display);
-
- /* Now, update contour_lines structure. */
- }
- /* ______. */
- else /* |________*/
- {
- register XPoint *p = begin + 1;
- end = contour_lines[y_pos].bottom_right;
- npoints = (end - begin + 1);
- XDrawLines (x_current_display, contour_window,
- contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
-
- p->y = begin->y;
- p->x = ibw + (font_w * (x_pos + 1));
- p++;
- p->y = begin->y + font_h;
- p->x = (p - 1)->x;
- bcopy (end, begin + 3, contour_last_point - end + 1);
- contour_last_point -= (npoints - 5);
- XDrawLines (x_current_display, contour_window,
- contour_erase_gc, begin, 4, CoordModeOrigin);
- XFlush (x_current_display);
-
- /* Now, update contour_lines structure. */
- }
-}
-
-/* Erase the top horizontal lines of the contour, and then extend
- the contour upwards. */
-
-static void
-extend_contour_top (line)
-{
-}
-
-static void
-clip_contour_bottom (x_pos, y_pos)
- int x_pos, y_pos;
-{
-}
-
-static void
-extend_contour_bottom (x_pos, y_pos)
-{
-}
-
-DEFUN ("x-select-region", Fx_select_region, Sx_select_region, 1, 1, "e",
- "")
- (event)
- Lisp_Object event;
-{
- register struct frame *f = selected_frame;
- register int point_x = f->cursor_x;
- register int point_y = f->cursor_y;
- register int mouse_below_point;
- register Lisp_Object obj;
- register int x_contour_x, x_contour_y;
-
- x_contour_x = x_mouse_x;
- x_contour_y = x_mouse_y;
- if (x_contour_y > point_y || (x_contour_y == point_y
- && x_contour_x > point_x))
- {
- mouse_below_point = 1;
- outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
- x_contour_x, x_contour_y);
- }
- else
- {
- mouse_below_point = 0;
- outline_region (f, f->output_data.x->cursor_gc, x_contour_x, x_contour_y,
- point_x, point_y);
- }
-
- while (1)
- {
- obj = read_char (-1, 0, 0, Qnil, 0);
- if (!CONSP (obj))
- break;
-
- if (mouse_below_point)
- {
- if (x_mouse_y <= point_y) /* Flipped. */
- {
- mouse_below_point = 0;
-
- outline_region (f, f->output_data.x->reverse_gc, point_x, point_y,
- x_contour_x, x_contour_y);
- outline_region (f, f->output_data.x->cursor_gc, x_mouse_x, x_mouse_y,
- point_x, point_y);
- }
- else if (x_mouse_y < x_contour_y) /* Bottom clipped. */
- {
- clip_contour_bottom (x_mouse_y);
- }
- else if (x_mouse_y > x_contour_y) /* Bottom extended. */
- {
- extend_bottom_contour (x_mouse_y);
- }
-
- x_contour_x = x_mouse_x;
- x_contour_y = x_mouse_y;
- }
- else /* mouse above or same line as point */
- {
- if (x_mouse_y >= point_y) /* Flipped. */
- {
- mouse_below_point = 1;
-
- outline_region (f, f->output_data.x->reverse_gc,
- x_contour_x, x_contour_y, point_x, point_y);
- outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
- x_mouse_x, x_mouse_y);
- }
- else if (x_mouse_y > x_contour_y) /* Top clipped. */
- {
- clip_contour_top (x_mouse_y);
- }
- else if (x_mouse_y < x_contour_y) /* Top extended. */
- {
- extend_contour_top (x_mouse_y);
- }
- }
- }
-
- unread_command_event = obj;
- if (mouse_below_point)
- {
- contour_begin_x = point_x;
- contour_begin_y = point_y;
- contour_end_x = x_contour_x;
- contour_end_y = x_contour_y;
- }
- else
- {
- contour_begin_x = x_contour_x;
- contour_begin_y = x_contour_y;
- contour_end_x = point_x;
- contour_end_y = point_y;
- }
-}
-#endif
-
-DEFUN ("x-horizontal-line", Fx_horizontal_line, Sx_horizontal_line, 1, 1, "e",
- "")
- (event)
- Lisp_Object event;
-{
- register Lisp_Object obj;
- struct frame *f = selected_frame;
- register struct window *w = XWINDOW (selected_window);
- register GC line_gc = f->output_data.x->cursor_gc;
- register GC erase_gc = f->output_data.x->reverse_gc;
-#if 0
- char dash_list[] = {6, 4, 6, 4};
- int dashes = 4;
- XGCValues gc_values;
-#endif
- register int previous_y;
- register int line = (x_mouse_y + 1) * f->output_data.x->line_height
- + f->output_data.x->internal_border_width;
- register int left = f->output_data.x->internal_border_width
- + (WINDOW_LEFT_MARGIN (w)
- * FONT_WIDTH (f->output_data.x->font));
- register int right = left + (w->width
- * FONT_WIDTH (f->output_data.x->font))
- - f->output_data.x->internal_border_width;
-
-#if 0
- BLOCK_INPUT;
- gc_values.foreground = f->output_data.x->cursor_pixel;
- gc_values.background = f->output_data.x->background_pixel;
- gc_values.line_width = 1;
- gc_values.line_style = LineOnOffDash;
- gc_values.cap_style = CapRound;
- gc_values.join_style = JoinRound;
-
- line_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- GCLineStyle | GCJoinStyle | GCCapStyle
- | GCLineWidth | GCForeground | GCBackground,
- &gc_values);
- XSetDashes (FRAME_X_DISPLAY (f), line_gc, 0, dash_list, dashes);
- gc_values.foreground = f->output_data.x->background_pixel;
- gc_values.background = f->output_data.x->foreground_pixel;
- erase_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- GCLineStyle | GCJoinStyle | GCCapStyle
- | GCLineWidth | GCForeground | GCBackground,
- &gc_values);
- XSetDashes (FRAME_X_DISPLAY (f), erase_gc, 0, dash_list, dashes);
- UNBLOCK_INPUT;
-#endif
-
- while (1)
- {
- BLOCK_INPUT;
- if (x_mouse_y >= XINT (w->top)
- && x_mouse_y < XINT (w->top) + XINT (w->height) - 1)
- {
- previous_y = x_mouse_y;
- line = (x_mouse_y + 1) * f->output_data.x->line_height
- + f->output_data.x->internal_border_width;
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- line_gc, left, line, right, line);
- }
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-
- do
- {
- obj = read_char (-1, 0, 0, Qnil, 0);
- if (!CONSP (obj)
- || (! EQ (Fcar (Fcdr (Fcdr (obj))),
- Qvertical_scroll_bar))
- || x_mouse_grabbed)
- {
- BLOCK_INPUT;
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- erase_gc, left, line, right, line);
- unread_command_event = obj;
-#if 0
- XFreeGC (FRAME_X_DISPLAY (f), line_gc);
- XFreeGC (FRAME_X_DISPLAY (f), erase_gc);
-#endif
- UNBLOCK_INPUT;
- return Qnil;
- }
- }
- while (x_mouse_y == previous_y);
-
- BLOCK_INPUT;
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- erase_gc, left, line, right, line);
- UNBLOCK_INPUT;
- }
-}
-#endif
-
-#if 0
-/* These keep track of the rectangle following the pointer. */
-int mouse_track_top, mouse_track_left, mouse_track_width;
-
-/* Offset in buffer of character under the pointer, or 0. */
-int mouse_buffer_offset;
-
-DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 0, 0, 0,
- "Track the pointer.")
- ()
-{
- static Cursor current_pointer_shape;
- FRAME_PTR f = x_mouse_frame;
-
- BLOCK_INPUT;
- if (EQ (Vmouse_frame_part, Qtext_part)
- && (current_pointer_shape != f->output_data.x->nontext_cursor))
- {
- unsigned char c;
- struct buffer *buf;
-
- current_pointer_shape = f->output_data.x->nontext_cursor;
- XDefineCursor (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- current_pointer_shape);
-
- buf = XBUFFER (XWINDOW (Vmouse_window)->buffer);
- c = *(BUF_CHAR_ADDRESS (buf, mouse_buffer_offset));
- }
- else if (EQ (Vmouse_frame_part, Qmodeline_part)
- && (current_pointer_shape != f->output_data.x->modeline_cursor))
- {
- current_pointer_shape = f->output_data.x->modeline_cursor;
- XDefineCursor (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- current_pointer_shape);
- }
-
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-}
-#endif
-
-#if 0
-DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 1, 1, "e",
- "Draw rectangle around character under mouse pointer, if there is one.")
- (event)
- Lisp_Object event;
-{
- struct window *w = XWINDOW (Vmouse_window);
- struct frame *f = XFRAME (WINDOW_FRAME (w));
- struct buffer *b = XBUFFER (w->buffer);
- Lisp_Object obj;
-
- if (! EQ (Vmouse_window, selected_window))
- return Qnil;
-
- if (EQ (event, Qnil))
- {
- int x, y;
-
- x_read_mouse_position (selected_frame, &x, &y);
- }
-
- BLOCK_INPUT;
- mouse_track_width = 0;
- mouse_track_left = mouse_track_top = -1;
-
- do
- {
- if ((x_mouse_x != mouse_track_left
- && (x_mouse_x < mouse_track_left
- || x_mouse_x > (mouse_track_left + mouse_track_width)))
- || x_mouse_y != mouse_track_top)
- {
- int hp = 0; /* Horizontal position */
- int len = FRAME_CURRENT_GLYPHS (f)->used[x_mouse_y];
- int p = FRAME_CURRENT_GLYPHS (f)->bufp[x_mouse_y];
- int tab_width = XINT (b->tab_width);
- int ctl_arrow_p = !NILP (b->ctl_arrow);
- unsigned char c;
- int mode_line_vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
- int in_mode_line = 0;
-
- if (! FRAME_CURRENT_GLYPHS (f)->enable[x_mouse_y])
- break;
-
- /* Erase previous rectangle. */
- if (mouse_track_width)
- {
- x_rectangle (f, f->output_data.x->reverse_gc,
- mouse_track_left, mouse_track_top,
- mouse_track_width, 1);
-
- if ((mouse_track_left == f->phys_cursor_x
- || mouse_track_left == f->phys_cursor_x - 1)
- && mouse_track_top == f->phys_cursor_y)
- {
- x_display_cursor (f, 1);
- }
- }
-
- mouse_track_left = x_mouse_x;
- mouse_track_top = x_mouse_y;
- mouse_track_width = 0;
-
- if (mouse_track_left > len) /* Past the end of line. */
- goto draw_or_not;
-
- if (mouse_track_top == mode_line_vpos)
- {
- in_mode_line = 1;
- goto draw_or_not;
- }
-
- if (tab_width <= 0 || tab_width > 20) tab_width = 8;
- do
- {
- c = FETCH_CHAR (p);
- if (len == f->width && hp == len - 1 && c != '\n')
- goto draw_or_not;
-
- switch (c)
- {
- case '\t':
- mouse_track_width = tab_width - (hp % tab_width);
- p++;
- hp += mouse_track_width;
- if (hp > x_mouse_x)
- {
- mouse_track_left = hp - mouse_track_width;
- goto draw_or_not;
- }
- continue;
-
- case '\n':
- mouse_track_width = -1;
- goto draw_or_not;
-
- default:
- if (ctl_arrow_p && (c < 040 || c == 0177))
- {
- if (p > ZV)
- goto draw_or_not;
-
- mouse_track_width = 2;
- p++;
- hp +=2;
- if (hp > x_mouse_x)
- {
- mouse_track_left = hp - mouse_track_width;
- goto draw_or_not;
- }
- }
- else
- {
- mouse_track_width = 1;
- p++;
- hp++;
- }
- continue;
- }
- }
- while (hp <= x_mouse_x);
-
- draw_or_not:
- if (mouse_track_width) /* Over text; use text pointer shape. */
- {
- XDefineCursor (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- f->output_data.x->text_cursor);
- x_rectangle (f, f->output_data.x->cursor_gc,
- mouse_track_left, mouse_track_top,
- mouse_track_width, 1);
- }
- else if (in_mode_line)
- XDefineCursor (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- f->output_data.x->modeline_cursor);
- else
- XDefineCursor (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- f->output_data.x->nontext_cursor);
- }
-
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-
- obj = read_char (-1, 0, 0, Qnil, 0);
- BLOCK_INPUT;
- }
- while (CONSP (obj) /* Mouse event */
- && EQ (Fcar (Fcdr (Fcdr (obj))), Qnil) /* Not scroll bar */
- && EQ (Vmouse_depressed, Qnil) /* Only motion events */
- && EQ (Vmouse_window, selected_window) /* In this window */
- && x_mouse_frame);
-
- unread_command_event = obj;
-
- if (mouse_track_width)
- {
- x_rectangle (f, f->output_data.x->reverse_gc,
- mouse_track_left, mouse_track_top,
- mouse_track_width, 1);
- mouse_track_width = 0;
- if ((mouse_track_left == f->phys_cursor_x
- || mouse_track_left - 1 == f->phys_cursor_x)
- && mouse_track_top == f->phys_cursor_y)
- {
- x_display_cursor (f, 1);
- }
- }
- XDefineCursor (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- f->output_data.x->nontext_cursor);
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-
- return Qnil;
-}
-#endif
-
-#if 0
-#include "glyphs.h"
-
-/* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
- on the frame F at position X, Y. */
-
-x_draw_pixmap (f, x, y, image_data, width, height)
- struct frame *f;
- int x, y, width, height;
- char *image_data;
-{
- Pixmap image;
-
- image = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f), image_data,
- width, height);
- XCopyPlane (FRAME_X_DISPLAY (f), image, FRAME_X_WINDOW (f),
- f->output_data.x->normal_gc, 0, 0, width, height, x, y);
-}
-#endif
-
-#if 0 /* I'm told these functions are superfluous
- given the ability to bind function keys. */
-
-#ifdef HAVE_X11
-DEFUN ("x-rebind-key", Fx_rebind_key, Sx_rebind_key, 3, 3, 0,
-"Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
-KEYSYM is a string which conforms to the X keysym definitions found\n\
-in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
-list of strings specifying modifier keys such as Control_L, which must\n\
-also be depressed for NEWSTRING to appear.")
- (x_keysym, modifiers, newstring)
- register Lisp_Object x_keysym;
- register Lisp_Object modifiers;
- register Lisp_Object newstring;
-{
- char *rawstring;
- register KeySym keysym;
- KeySym modifier_list[16];
-
- check_x ();
- CHECK_STRING (x_keysym, 1);
- CHECK_STRING (newstring, 3);
-
- keysym = XStringToKeysym ((char *) XSTRING (x_keysym)->data);
- if (keysym == NoSymbol)
- error ("Keysym does not exist");
-
- if (NILP (modifiers))
- XRebindKeysym (x_current_display, keysym, modifier_list, 0,
- XSTRING (newstring)->data, XSTRING (newstring)->size);
- else
- {
- register Lisp_Object rest, mod;
- register int i = 0;
-
- for (rest = modifiers; !NILP (rest); rest = Fcdr (rest))
- {
- if (i == 16)
- error ("Can't have more than 16 modifiers");
-
- mod = Fcar (rest);
- CHECK_STRING (mod, 3);
- modifier_list[i] = XStringToKeysym ((char *) XSTRING (mod)->data);
-#ifndef HAVE_X11R5
- if (modifier_list[i] == NoSymbol
- || !(IsModifierKey (modifier_list[i])
- || ((unsigned)(modifier_list[i]) == XK_Mode_switch)
- || ((unsigned)(modifier_list[i]) == XK_Num_Lock)))
-#else
- if (modifier_list[i] == NoSymbol
- || !IsModifierKey (modifier_list[i]))
-#endif
- error ("Element is not a modifier keysym");
- i++;
- }
-
- XRebindKeysym (x_current_display, keysym, modifier_list, i,
- XSTRING (newstring)->data, XSTRING (newstring)->size);
- }
-
- 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 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 unsigned char *rawstring;
- KeySym rawkey, modifier[1];
- int strsize;
- register unsigned i;
-
- check_x ();
- CHECK_NUMBER (keycode, 1);
- CHECK_CONS (strings, 2);
- rawkey = (KeySym) ((unsigned) (XINT (keycode))) & 255;
- for (i = 0; i <= 15; strings = Fcdr (strings), i++)
- {
- item = Fcar (strings);
- if (!NILP (item))
- {
- CHECK_STRING (item, 2);
- strsize = XSTRING (item)->size;
- rawstring = (unsigned char *) xmalloc (strsize);
- bcopy (XSTRING (item)->data, rawstring, strsize);
- modifier[1] = 1 << i;
- XRebindKeysym (x_current_display, rawkey, modifier, 1,
- rawstring, strsize);
- }
- }
- return Qnil;
-}
-#endif /* HAVE_X11 */
-#endif /* 0 */
-
-#ifndef HAVE_XSCREENNUMBEROFSCREEN
-int
-XScreenNumberOfScreen (scr)
- register Screen *scr;
-{
- register Display *dpy;
- register Screen *dpyscr;
- register int i;
-
- dpy = scr->display;
- dpyscr = dpy->screens;
-
- for (i = 0; i < dpy->nscreens; i++, dpyscr++)
- if (scr == dpyscr)
- return i;
-
- return -1;
-}
-#endif /* not HAVE_XSCREENNUMBEROFSCREEN */
-
-Visual *
-select_visual (dpy, screen, depth)
- Display *dpy;
- Screen *screen;
- unsigned int *depth;
-{
- Visual *v;
- XVisualInfo *vinfo, vinfo_template;
- int n_visuals;
-
- v = DefaultVisualOfScreen (screen);
-
-#ifdef HAVE_X11R4
- vinfo_template.visualid = XVisualIDFromVisual (v);
-#else
- vinfo_template.visualid = v->visualid;
-#endif
-
- vinfo_template.screen = XScreenNumberOfScreen (screen);
-
- vinfo = XGetVisualInfo (dpy,
- VisualIDMask | VisualScreenMask, &vinfo_template,
- &n_visuals);
- if (n_visuals != 1)
- fatal ("Can't get proper X visual info");
-
- if ((1 << vinfo->depth) == vinfo->colormap_size)
- *depth = vinfo->depth;
- else
- {
- int i = 0;
- int n = vinfo->colormap_size - 1;
- while (n)
- {
- n = n >> 1;
- i++;
- }
- *depth = i;
- }
-
- XFree ((char *) vinfo);
- return v;
-}
-
-/* Return the X display structure for the display named NAME.
- Open a new connection if necessary. */
-
-struct x_display_info *
-x_display_info_for_name (name)
- Lisp_Object name;
-{
- Lisp_Object names;
- struct x_display_info *dpyinfo;
-
- CHECK_STRING (name, 0);
-
- if (! EQ (Vwindow_system, intern ("x")))
- error ("Not using X Windows");
-
- for (dpyinfo = x_display_list, names = x_display_name_list;
- dpyinfo;
- dpyinfo = dpyinfo->next, names = XCONS (names)->cdr)
- {
- Lisp_Object tem;
- tem = Fstring_equal (XCONS (XCONS (names)->car)->car, name);
- if (!NILP (tem))
- return dpyinfo;
- }
-
- /* Use this general default value to start with. */
- Vx_resource_name = Vinvocation_name;
-
- validate_x_resource_name ();
-
- dpyinfo = x_term_init (name, (unsigned char *)0,
- (char *) XSTRING (Vx_resource_name)->data);
-
- if (dpyinfo == 0)
- error ("Cannot connect to X server %s", XSTRING (name)->data);
-
- x_in_use = 1;
- XSETFASTINT (Vwindow_system_version, 11);
-
- return dpyinfo;
-}
-
-DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
- 1, 3, 0, "Open a connection to an X server.\n\
-DISPLAY is the name of the display to connect to.\n\
-Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
-If the optional third arg MUST-SUCCEED is non-nil,\n\
-terminate Emacs if we can't open the connection.")
- (display, xrm_string, must_succeed)
- Lisp_Object display, xrm_string, must_succeed;
-{
- unsigned int n_planes;
- unsigned char *xrm_option;
- struct x_display_info *dpyinfo;
-
- CHECK_STRING (display, 0);
- if (! NILP (xrm_string))
- CHECK_STRING (xrm_string, 1);
-
- if (! EQ (Vwindow_system, intern ("x")))
- error ("Not using X Windows");
-
- if (! NILP (xrm_string))
- xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
- else
- xrm_option = (unsigned char *) 0;
-
- validate_x_resource_name ();
-
- /* This is what opens the connection and sets x_current_display.
- This also initializes many symbols, such as those used for input. */
- dpyinfo = x_term_init (display, xrm_option,
- (char *) XSTRING (Vx_resource_name)->data);
-
- if (dpyinfo == 0)
- {
- if (!NILP (must_succeed))
- fatal ("Cannot connect to X server %s.\n\
-Check the DISPLAY environment variable or use `-d'.\n\
-Also use the `xhost' program to verify that it is set to permit\n\
-connections from your machine.\n",
- XSTRING (display)->data);
- else
- error ("Cannot connect to X server %s", XSTRING (display)->data);
- }
-
- x_in_use = 1;
-
- XSETFASTINT (Vwindow_system_version, 11);
- return Qnil;
-}
-
-DEFUN ("x-close-connection", Fx_close_connection,
- Sx_close_connection, 1, 1, 0,
- "Close the connection to DISPLAY's X server.\n\
-For DISPLAY, specify either a frame or a display name (a string).\n\
-If DISPLAY is nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
- struct x_display_info *tail;
- int i;
-
- if (dpyinfo->reference_count > 0)
- error ("Display still has frames on it");
-
- BLOCK_INPUT;
- /* Free the fonts in the font table. */
- for (i = 0; i < dpyinfo->n_fonts; i++)
- {
- if (dpyinfo->font_table[i].name)
- free (dpyinfo->font_table[i].name);
- /* Don't free the full_name string;
- it is always shared with something else. */
- XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
- }
- x_destroy_all_bitmaps (dpyinfo);
- XSetCloseDownMode (dpyinfo->display, DestroyAll);
-
-#ifdef USE_X_TOOLKIT
- XtCloseDisplay (dpyinfo->display);
-#else
- XCloseDisplay (dpyinfo->display);
-#endif
-
- x_delete_display (dpyinfo);
- UNBLOCK_INPUT;
-
- return Qnil;
-}
-
-DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
- "Return the list of display names that Emacs has connections to.")
- ()
-{
- Lisp_Object tail, result;
-
- result = Qnil;
- for (tail = x_display_name_list; ! NILP (tail); tail = XCONS (tail)->cdr)
- result = Fcons (XCONS (XCONS (tail)->car)->car, result);
-
- return result;
-}
-
-DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
- "If ON is non-nil, report X errors as soon as the erring request is made.\n\
-If ON is nil, allow buffering of requests.\n\
-Turning on synchronization prohibits the Xlib routines from buffering\n\
-requests and seriously degrades performance, but makes debugging much\n\
-easier.\n\
-The optional second argument DISPLAY specifies which display to act on.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If DISPLAY is omitted or nil, that stands for the selected frame's display.")
- (on, display)
- Lisp_Object display, on;
-{
- struct x_display_info *dpyinfo = check_x_display_info (display);
-
- XSynchronize (dpyinfo->display, !EQ (on, Qnil));
-
- return Qnil;
-}
-
-/* Wait for responses to all X commands issued so far for frame F. */
-
-void
-x_sync (f)
- FRAME_PTR f;
-{
- BLOCK_INPUT;
- XSync (FRAME_X_DISPLAY (f), False);
- UNBLOCK_INPUT;
-}
-
-syms_of_xfns ()
-{
- /* This is zero if not using X windows. */
- x_in_use = 0;
-
- /* The section below is built by the lisp expression at the top of the file,
- just above where these variables are declared. */
- /*&&& init symbols here &&&*/
- Qauto_raise = intern ("auto-raise");
- staticpro (&Qauto_raise);
- Qauto_lower = intern ("auto-lower");
- staticpro (&Qauto_lower);
- Qbackground_color = intern ("background-color");
- staticpro (&Qbackground_color);
- Qbar = intern ("bar");
- staticpro (&Qbar);
- Qborder_color = intern ("border-color");
- staticpro (&Qborder_color);
- Qborder_width = intern ("border-width");
- staticpro (&Qborder_width);
- Qbox = intern ("box");
- staticpro (&Qbox);
- Qcursor_color = intern ("cursor-color");
- staticpro (&Qcursor_color);
- Qcursor_type = intern ("cursor-type");
- staticpro (&Qcursor_type);
- Qforeground_color = intern ("foreground-color");
- staticpro (&Qforeground_color);
- Qgeometry = intern ("geometry");
- staticpro (&Qgeometry);
- Qicon_left = intern ("icon-left");
- staticpro (&Qicon_left);
- Qicon_top = intern ("icon-top");
- staticpro (&Qicon_top);
- Qicon_type = intern ("icon-type");
- staticpro (&Qicon_type);
- Qicon_name = intern ("icon-name");
- staticpro (&Qicon_name);
- Qinternal_border_width = intern ("internal-border-width");
- staticpro (&Qinternal_border_width);
- Qleft = intern ("left");
- staticpro (&Qleft);
- Qright = intern ("right");
- staticpro (&Qright);
- Qmouse_color = intern ("mouse-color");
- staticpro (&Qmouse_color);
- Qnone = intern ("none");
- staticpro (&Qnone);
- Qparent_id = intern ("parent-id");
- staticpro (&Qparent_id);
- Qscroll_bar_width = intern ("scroll-bar-width");
- staticpro (&Qscroll_bar_width);
- Qsuppress_icon = intern ("suppress-icon");
- staticpro (&Qsuppress_icon);
- Qtop = intern ("top");
- staticpro (&Qtop);
- Qundefined_color = intern ("undefined-color");
- staticpro (&Qundefined_color);
- Qvertical_scroll_bars = intern ("vertical-scroll-bars");
- staticpro (&Qvertical_scroll_bars);
- Qvisibility = intern ("visibility");
- staticpro (&Qvisibility);
- Qwindow_id = intern ("window-id");
- staticpro (&Qwindow_id);
- Qx_frame_parameter = intern ("x-frame-parameter");
- staticpro (&Qx_frame_parameter);
- Qx_resource_name = intern ("x-resource-name");
- staticpro (&Qx_resource_name);
- Quser_position = intern ("user-position");
- staticpro (&Quser_position);
- Quser_size = intern ("user-size");
- staticpro (&Quser_size);
- Qdisplay = intern ("display");
- staticpro (&Qdisplay);
- /* This is the end of symbol initialization. */
-
- Fput (Qundefined_color, Qerror_conditions,
- Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
- Fput (Qundefined_color, Qerror_message,
- build_string ("Undefined color"));
-
- init_x_parm_symbols ();
-
- DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
- "List of directories to search for bitmap files for X.");
- Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
-
- DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
- "The shape of the pointer when over text.\n\
-Changing the value does not affect existing frames\n\
-unless you set the mouse color.");
- Vx_pointer_shape = Qnil;
-
- DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
- "The name Emacs uses to look up X resources; for internal use only.\n\
-`x-get-resource' uses this as the first component of the instance name\n\
-when requesting resource values.\n\
-Emacs initially sets `x-resource-name' to the name under which Emacs\n\
-was invoked, or to the value specified with the `-name' or `-rn'\n\
-switches, if present.");
- Vx_resource_name = Qnil;
-
-#if 0 /* This doesn't really do anything. */
- DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
- "The shape of the pointer when not over text.\n\
-This variable takes effect when you create a new frame\n\
-or when you set the mouse color.");
-#endif
- Vx_nontext_pointer_shape = Qnil;
-
-#if 0 /* This doesn't really do anything. */
- DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
- "The shape of the pointer when over the mode line.\n\
-This variable takes effect when you create a new frame\n\
-or when you set the mouse color.");
-#endif
- Vx_mode_pointer_shape = Qnil;
-
- DEFVAR_LISP ("x-sensitive-text-pointer-shape",
- &Vx_sensitive_text_pointer_shape,
- "The shape of the pointer when over mouse-sensitive text.\n\
-This variable takes effect when you create a new frame\n\
-or when you set the mouse color.");
- Vx_sensitive_text_pointer_shape = Qnil;
-
- DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
- "A string indicating the foreground color of the cursor box.");
- Vx_cursor_fore_pixel = Qnil;
-
- DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
- "Non-nil if no X window manager is in use.\n\
-Emacs doesn't try to figure this out; this is always nil\n\
-unless you set it to something else.");
- /* We don't have any way to find this out, so set it to nil
- and maybe the user would like to set it to t. */
- Vx_no_window_manager = Qnil;
-
-#ifdef USE_X_TOOLKIT
- Fprovide (intern ("x-toolkit"));
-#endif
-#ifdef USE_MOTIF
- Fprovide (intern ("motif"));
-#endif
-
- defsubr (&Sx_get_resource);
-#if 0
- defsubr (&Sx_draw_rectangle);
- defsubr (&Sx_erase_rectangle);
- defsubr (&Sx_contour_region);
- defsubr (&Sx_uncontour_region);
-#endif
- defsubr (&Sx_list_fonts);
- defsubr (&Sx_display_color_p);
- defsubr (&Sx_display_grayscale_p);
- defsubr (&Sx_color_defined_p);
- defsubr (&Sx_color_values);
- defsubr (&Sx_server_max_request_size);
- defsubr (&Sx_server_vendor);
- defsubr (&Sx_server_version);
- defsubr (&Sx_display_pixel_width);
- defsubr (&Sx_display_pixel_height);
- defsubr (&Sx_display_mm_width);
- defsubr (&Sx_display_mm_height);
- defsubr (&Sx_display_screens);
- defsubr (&Sx_display_planes);
- defsubr (&Sx_display_color_cells);
- defsubr (&Sx_display_visual_class);
- defsubr (&Sx_display_backing_store);
- defsubr (&Sx_display_save_under);
-#if 0
- defsubr (&Sx_rebind_key);
- defsubr (&Sx_rebind_keys);
- defsubr (&Sx_track_pointer);
- defsubr (&Sx_grab_pointer);
- defsubr (&Sx_ungrab_pointer);
-#endif
- defsubr (&Sx_parse_geometry);
- defsubr (&Sx_create_frame);
-#if 0
- defsubr (&Sx_horizontal_line);
-#endif
- defsubr (&Sx_open_connection);
- defsubr (&Sx_close_connection);
- defsubr (&Sx_display_list);
- defsubr (&Sx_synchronize);
-}
-
-#endif /* HAVE_X_WINDOWS */
diff --git a/src/xmenu.c b/src/xmenu.c
deleted file mode 100644
index 819f81ea954..00000000000
--- a/src/xmenu.c
+++ /dev/null
@@ -1,2740 +0,0 @@
-/* X Communication module for terminals which understand the X protocol.
- Copyright (C) 1986, 1988, 1993, 1994, 1996 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* X pop-up deck-of-cards menu facility for gnuemacs.
- *
- * Written by Jon Arnold and Roman Budzianowski
- * Mods and rewrite by Robert Krawitz
- *
- */
-
-/* Modified by Fred Pierresteguy on December 93
- to make the popup menus and menubar use the Xt. */
-
-/* Rewritten for clarity and GC protection by rms in Feb 94. */
-
-/* On 4.3 this loses if it comes after xterm.h. */
-#include <signal.h>
-#include <config.h>
-
-#include <stdio.h>
-#include "lisp.h"
-#include "termhooks.h"
-#include "frame.h"
-#include "window.h"
-#include "keyboard.h"
-#include "blockinput.h"
-#include "puresize.h"
-#include "buffer.h"
-
-#ifdef MSDOS
-#include "msdos.h"
-#endif
-
-#ifdef HAVE_X_WINDOWS
-/* This may include sys/types.h, and that somehow loses
- if this is not done before the other system files. */
-#include "xterm.h"
-#endif
-
-/* Load sys/types.h if not already loaded.
- In some systems loading it twice is suicidal. */
-#ifndef makedev
-#include <sys/types.h>
-#endif
-
-#include "dispextern.h"
-
-#ifdef HAVE_X_WINDOWS
-#ifdef USE_X_TOOLKIT
-#include <X11/Xlib.h>
-#include <X11/IntrinsicP.h>
-#include <X11/CoreP.h>
-#include <X11/StringDefs.h>
-#include <X11/Shell.h>
-#ifdef USE_LUCID
-#include <X11/Xaw/Paned.h>
-#endif /* USE_LUCID */
-#include "../lwlib/lwlib.h"
-#else /* not USE_X_TOOLKIT */
-#include "../oldXMenu/XMenu.h"
-#endif /* not USE_X_TOOLKIT */
-#endif /* HAVE_X_WINDOWS */
-
-#define min(x,y) (((x) < (y)) ? (x) : (y))
-#define max(x,y) (((x) > (y)) ? (x) : (y))
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif /* no TRUE */
-
-Lisp_Object Vmenu_updating_frame;
-
-Lisp_Object Qdebug_on_next_call;
-
-Lisp_Object Qmenu_alias;
-
-extern Lisp_Object Qmenu_enable;
-extern Lisp_Object Qmenu_bar;
-extern Lisp_Object Qmouse_click, Qevent_kind;
-
-extern Lisp_Object Vdefine_key_rebound_commands;
-
-extern Lisp_Object Voverriding_local_map;
-extern Lisp_Object Voverriding_local_map_menu_flag;
-
-extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
-
-extern Lisp_Object Qmenu_bar_update_hook;
-
-#ifdef USE_X_TOOLKIT
-extern void set_frame_menubar ();
-extern void process_expose_from_menu ();
-extern XtAppContext Xt_app_con;
-
-static Lisp_Object xdialog_show ();
-void popup_get_selection ();
-#endif
-
-static Lisp_Object xmenu_show ();
-static void keymap_panes ();
-static void single_keymap_panes ();
-static void list_of_panes ();
-static void list_of_items ();
-
-/* This holds a Lisp vector that holds the results of decoding
- the keymaps or alist-of-alists that specify a menu.
-
- It describes the panes and items within the panes.
-
- Each pane is described by 3 elements in the vector:
- t, the pane name, the pane's prefix key.
- Then follow the pane's items, with 5 elements per item:
- the item string, the enable flag, the item's value,
- the definition, and the equivalent keyboard key's description string.
-
- In some cases, multiple levels of menus may be described.
- A single vector slot containing nil indicates the start of a submenu.
- A single vector slot containing lambda indicates the end of a submenu.
- The submenu follows a menu item which is the way to reach the submenu.
-
- A single vector slot containing quote indicates that the
- following items should appear on the right of a dialog box.
-
- Using a Lisp vector to hold this information while we decode it
- takes care of protecting all the data from GC. */
-
-#define MENU_ITEMS_PANE_NAME 1
-#define MENU_ITEMS_PANE_PREFIX 2
-#define MENU_ITEMS_PANE_LENGTH 3
-
-#define MENU_ITEMS_ITEM_NAME 0
-#define MENU_ITEMS_ITEM_ENABLE 1
-#define MENU_ITEMS_ITEM_VALUE 2
-#define MENU_ITEMS_ITEM_EQUIV_KEY 3
-#define MENU_ITEMS_ITEM_DEFINITION 4
-#define MENU_ITEMS_ITEM_LENGTH 5
-
-static Lisp_Object menu_items;
-
-/* Number of slots currently allocated in menu_items. */
-static int menu_items_allocated;
-
-/* This is the index in menu_items of the first empty slot. */
-static int menu_items_used;
-
-/* The number of panes currently recorded in menu_items,
- excluding those within submenus. */
-static int menu_items_n_panes;
-
-/* Current depth within submenus. */
-static int menu_items_submenu_depth;
-
-/* Flag which when set indicates a dialog or menu has been posted by
- Xt on behalf of one of the widget sets. */
-static int popup_activated_flag;
-
-static int next_menubar_widget_id;
-
-/* This is set nonzero after the user activates the menu bar, and set
- to zero again after the menu bars are redisplayed by prepare_menu_bar.
- While it is nonzero, all calls to set_frame_menubar go deep.
-
- I don't understand why this is needed, but it does seem to be
- needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
-
-int pending_menu_activation;
-
-#ifdef USE_X_TOOLKIT
-
-/* Return the frame whose ->output_data.x->id equals ID, or 0 if none. */
-
-static struct frame *
-menubar_id_to_frame (id)
- LWLIB_ID id;
-{
- Lisp_Object tail, frame;
- FRAME_PTR f;
-
- for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
- {
- frame = XCONS (tail)->car;
- if (!GC_FRAMEP (frame))
- continue;
- f = XFRAME (frame);
- if (f->output_data.nothing == 1)
- continue;
- if (f->output_data.x->id == id)
- return f;
- }
- return 0;
-}
-
-#endif
-
-/* Initialize the menu_items structure if we haven't already done so.
- Also mark it as currently empty. */
-
-static void
-init_menu_items ()
-{
- if (NILP (menu_items))
- {
- menu_items_allocated = 60;
- menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
- }
-
- menu_items_used = 0;
- menu_items_n_panes = 0;
- menu_items_submenu_depth = 0;
-}
-
-/* Call at the end of generating the data in menu_items.
- This fills in the number of items in the last pane. */
-
-static void
-finish_menu_items ()
-{
-}
-
-/* Call when finished using the data for the current menu
- in menu_items. */
-
-static void
-discard_menu_items ()
-{
- /* Free the structure if it is especially large.
- Otherwise, hold on to it, to save time. */
- if (menu_items_allocated > 200)
- {
- menu_items = Qnil;
- menu_items_allocated = 0;
- }
-}
-
-/* Make the menu_items vector twice as large. */
-
-static void
-grow_menu_items ()
-{
- Lisp_Object old;
- int old_size = menu_items_allocated;
- old = menu_items;
-
- menu_items_allocated *= 2;
- menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
- bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents,
- old_size * sizeof (Lisp_Object));
-}
-
-/* Begin a submenu. */
-
-static void
-push_submenu_start ()
-{
- if (menu_items_used + 1 > menu_items_allocated)
- grow_menu_items ();
-
- XVECTOR (menu_items)->contents[menu_items_used++] = Qnil;
- menu_items_submenu_depth++;
-}
-
-/* End a submenu. */
-
-static void
-push_submenu_end ()
-{
- if (menu_items_used + 1 > menu_items_allocated)
- grow_menu_items ();
-
- XVECTOR (menu_items)->contents[menu_items_used++] = Qlambda;
- menu_items_submenu_depth--;
-}
-
-/* Indicate boundary between left and right. */
-
-static void
-push_left_right_boundary ()
-{
- if (menu_items_used + 1 > menu_items_allocated)
- grow_menu_items ();
-
- XVECTOR (menu_items)->contents[menu_items_used++] = Qquote;
-}
-
-/* Start a new menu pane in menu_items..
- NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
-
-static void
-push_menu_pane (name, prefix_vec)
- Lisp_Object name, prefix_vec;
-{
- if (menu_items_used + MENU_ITEMS_PANE_LENGTH > menu_items_allocated)
- grow_menu_items ();
-
- if (menu_items_submenu_depth == 0)
- menu_items_n_panes++;
- XVECTOR (menu_items)->contents[menu_items_used++] = Qt;
- XVECTOR (menu_items)->contents[menu_items_used++] = name;
- XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec;
-}
-
-/* Push one menu item into the current pane.
- NAME is the string to display. ENABLE if non-nil means
- this item can be selected. KEY is the key generated by
- choosing this item, or nil if this item doesn't really have a definition.
- DEF is the definition of this item.
- EQUIV is the textual description of the keyboard equivalent for
- this item (or nil if none). */
-
-static void
-push_menu_item (name, enable, key, def, equiv)
- Lisp_Object name, enable, key, def, equiv;
-{
- if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
- grow_menu_items ();
-
- XVECTOR (menu_items)->contents[menu_items_used++] = name;
- XVECTOR (menu_items)->contents[menu_items_used++] = enable;
- XVECTOR (menu_items)->contents[menu_items_used++] = key;
- XVECTOR (menu_items)->contents[menu_items_used++] = equiv;
- XVECTOR (menu_items)->contents[menu_items_used++] = def;
-}
-
-/* Figure out the current keyboard equivalent of a menu item ITEM1.
- The item string for menu display should be ITEM_STRING.
- Store the equivalent keyboard key sequence's
- textual description into *DESCRIP_PTR.
- Also cache them in the item itself.
- Return the real definition to execute. */
-
-static Lisp_Object
-menu_item_equiv_key (item_string, item1, descrip_ptr)
- Lisp_Object item_string;
- Lisp_Object item1;
- Lisp_Object *descrip_ptr;
-{
- /* This is the real definition--the function to run. */
- Lisp_Object def;
- /* This is the sublist that records cached equiv key data
- so we can save time. */
- Lisp_Object cachelist;
- /* These are the saved equivalent keyboard key sequence
- and its key-description. */
- Lisp_Object savedkey, descrip;
- Lisp_Object def1;
- int changed = 0;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- /* If a help string follows the item string, skip it. */
- if (CONSP (XCONS (item1)->cdr)
- && STRINGP (XCONS (XCONS (item1)->cdr)->car))
- item1 = XCONS (item1)->cdr;
-
- def = Fcdr (item1);
-
- /* Get out the saved equivalent-keyboard-key info. */
- cachelist = savedkey = descrip = Qnil;
- if (CONSP (def) && CONSP (XCONS (def)->car)
- && (NILP (XCONS (XCONS (def)->car)->car)
- || VECTORP (XCONS (XCONS (def)->car)->car)))
- {
- cachelist = XCONS (def)->car;
- def = XCONS (def)->cdr;
- savedkey = XCONS (cachelist)->car;
- descrip = XCONS (cachelist)->cdr;
- }
-
- GCPRO4 (def, def1, savedkey, descrip);
-
- /* Is it still valid? */
- def1 = Qnil;
- if (!NILP (savedkey))
- def1 = Fkey_binding (savedkey, Qnil);
- /* If not, update it. */
- if (! EQ (def1, def)
- /* If the command is an alias for another
- (such as easymenu.el and lmenu.el set it up),
- check if the original command matches the cached command. */
- && !(SYMBOLP (def) && SYMBOLP (XSYMBOL (def)->function)
- && EQ (def1, XSYMBOL (def)->function))
- /* If something had no key binding before, don't recheck it
- because that is too slow--except if we have a list of rebound
- commands in Vdefine_key_rebound_commands, do recheck any command
- that appears in that list. */
- && (NILP (cachelist) || !NILP (savedkey)
- || (! EQ (Qt, Vdefine_key_rebound_commands)
- && !NILP (Fmemq (def, Vdefine_key_rebound_commands)))))
- {
- changed = 1;
- descrip = Qnil;
- /* If the command is an alias for another
- (such as easymenu.el and lmenu.el set it up),
- see if the original command name has equivalent keys. */
- if (SYMBOLP (def) && SYMBOLP (XSYMBOL (def)->function)
- && ! NILP (Fget (def, Qmenu_alias)))
- savedkey = Fwhere_is_internal (XSYMBOL (def)->function,
- Qnil, Qt, Qnil);
- else
- /* Otherwise look up the specified command itself.
- We don't try both, because that makes easymenu menus slow. */
- savedkey = Fwhere_is_internal (def, Qnil, Qt, Qnil);
-
- if (!NILP (savedkey))
- {
- descrip = Fkey_description (savedkey);
- descrip = concat2 (make_string (" (", 3), descrip);
- descrip = concat2 (descrip, make_string (")", 1));
- }
- }
-
- /* Cache the data we just got in a sublist of the menu binding. */
- if (NILP (cachelist))
- {
- CHECK_IMPURE (item1);
- XCONS (item1)->cdr = Fcons (Fcons (savedkey, descrip), def);
- }
- else if (changed)
- {
- XCONS (cachelist)->car = savedkey;
- XCONS (cachelist)->cdr = descrip;
- }
-
- UNGCPRO;
- *descrip_ptr = descrip;
- return def;
-}
-
-/* This is used as the handler when calling internal_condition_case_1. */
-
-static Lisp_Object
-menu_item_enabled_p_1 (arg)
- Lisp_Object arg;
-{
- /* If we got a quit from within the menu computation,
- quit all the way out of it. This takes care of C-] in the debugger. */
- if (CONSP (arg) && EQ (XCONS (arg)->car, Qquit))
- Fsignal (Qquit, Qnil);
-
- return Qnil;
-}
-
-/* Return non-nil if the command DEF is enabled when used as a menu item.
- This is based on looking for a menu-enable property.
- If NOTREAL is set, don't bother really computing this. */
-
-static Lisp_Object
-menu_item_enabled_p (def, notreal)
- Lisp_Object def;
- int notreal;
-{
- Lisp_Object enabled, tem;
-
- enabled = Qt;
- if (notreal)
- return enabled;
- if (SYMBOLP (def))
- {
- /* No property, or nil, means enable.
- Otherwise, enable if value is not nil. */
- tem = Fget (def, Qmenu_enable);
- if (!NILP (tem))
- /* (condition-case nil (eval tem)
- (error nil)) */
- enabled = internal_condition_case_1 (Feval, tem, Qerror,
- menu_item_enabled_p_1);
- }
- return enabled;
-}
-
-/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
- and generate menu panes for them in menu_items.
- If NOTREAL is nonzero,
- don't bother really computing whether an item is enabled. */
-
-static void
-keymap_panes (keymaps, nmaps, notreal)
- Lisp_Object *keymaps;
- int nmaps;
- int notreal;
-{
- int mapno;
-
- init_menu_items ();
-
- /* Loop over the given keymaps, making a pane for each map.
- But don't make a pane that is empty--ignore that map instead.
- P is the number of panes we have made so far. */
- for (mapno = 0; mapno < nmaps; mapno++)
- single_keymap_panes (keymaps[mapno], Qnil, Qnil, notreal, 10);
-
- finish_menu_items ();
-}
-
-/* This is a recursive subroutine of keymap_panes.
- It handles one keymap, KEYMAP.
- The other arguments are passed along
- or point to local variables of the previous function.
- If NOTREAL is nonzero,
- don't bother really computing whether an item is enabled.
-
- If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
-
-static void
-single_keymap_panes (keymap, pane_name, prefix, notreal, maxdepth)
- Lisp_Object keymap;
- Lisp_Object pane_name;
- Lisp_Object prefix;
- int notreal;
- int maxdepth;
-{
- Lisp_Object pending_maps;
- Lisp_Object tail, item, item1, item_string, table;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- if (maxdepth <= 0)
- return;
-
- pending_maps = Qnil;
-
- push_menu_pane (pane_name, prefix);
-
- for (tail = keymap; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- /* Look at each key binding, and if it has a menu string,
- make a menu item from it. */
- item = XCONS (tail)->car;
- if (CONSP (item))
- {
- item1 = XCONS (item)->cdr;
- if (CONSP (item1))
- {
- item_string = XCONS (item1)->car;
- if (STRINGP (item_string))
- {
- /* This is the real definition--the function to run. */
- Lisp_Object def;
- /* These are the saved equivalent keyboard key sequence
- and its key-description. */
- Lisp_Object descrip;
- Lisp_Object tem, enabled;
-
- /* GCPRO because ...enabled_p will call eval
- and ..._equiv_key may autoload something.
- Protecting KEYMAP preserves everything we use;
- aside from that, must protect whatever might be
- a string. Since there's no GCPRO5, we refetch
- item_string instead of protecting it. */
- descrip = def = Qnil;
- GCPRO4 (keymap, pending_maps, def, descrip);
-
- def = menu_item_equiv_key (item_string, item1, &descrip);
- enabled = menu_item_enabled_p (def, notreal);
-
- UNGCPRO;
-
- item_string = XCONS (item1)->car;
-
- tem = Fkeymapp (def);
- if (XSTRING (item_string)->data[0] == '@' && !NILP (tem))
- pending_maps = Fcons (Fcons (def, Fcons (item_string, XCONS (item)->car)),
- pending_maps);
- else
- {
- Lisp_Object submap;
- GCPRO4 (keymap, pending_maps, descrip, item_string);
- submap = get_keymap_1 (def, 0, 1);
- UNGCPRO;
-#ifndef USE_X_TOOLKIT
- /* Indicate visually that this is a submenu. */
- if (!NILP (submap))
- item_string = concat2 (item_string,
- build_string (" >"));
-#endif
- /* If definition is nil, pass nil as the key. */
- push_menu_item (item_string, enabled,
- XCONS (item)->car, def,
- descrip);
-#ifdef USE_X_TOOLKIT
- /* Display a submenu using the toolkit. */
- if (! NILP (submap))
- {
- push_submenu_start ();
- single_keymap_panes (submap, Qnil,
- XCONS (item)->car, notreal,
- maxdepth - 1);
- push_submenu_end ();
- }
-#endif
- }
- }
- }
- }
- else if (VECTORP (item))
- {
- /* Loop over the char values represented in the vector. */
- int len = XVECTOR (item)->size;
- int c;
- for (c = 0; c < len; c++)
- {
- Lisp_Object character;
- XSETFASTINT (character, c);
- item1 = XVECTOR (item)->contents[c];
- if (CONSP (item1))
- {
- item_string = XCONS (item1)->car;
- if (STRINGP (item_string))
- {
- Lisp_Object def;
-
- /* These are the saved equivalent keyboard key sequence
- and its key-description. */
- Lisp_Object descrip;
- Lisp_Object tem, enabled;
-
- /* GCPRO because ...enabled_p will call eval
- and ..._equiv_key may autoload something.
- Protecting KEYMAP preserves everything we use;
- aside from that, must protect whatever might be
- a string. Since there's no GCPRO5, we refetch
- item_string instead of protecting it. */
- GCPRO4 (keymap, pending_maps, def, descrip);
- descrip = def = Qnil;
-
- def = menu_item_equiv_key (item_string, item1, &descrip);
- enabled = menu_item_enabled_p (def, notreal);
-
- UNGCPRO;
-
- item_string = XCONS (item1)->car;
-
- tem = Fkeymapp (def);
- if (XSTRING (item_string)->data[0] == '@' && !NILP (tem))
- pending_maps = Fcons (Fcons (def, Fcons (item_string, character)),
- pending_maps);
- else
- {
- Lisp_Object submap;
- GCPRO4 (keymap, pending_maps, descrip, item_string);
- submap = get_keymap_1 (def, 0, 1);
- UNGCPRO;
-#ifndef USE_X_TOOLKIT
- if (!NILP (submap))
- item_string = concat2 (item_string,
- build_string (" >"));
-#endif
- /* If definition is nil, pass nil as the key. */
- push_menu_item (item_string, enabled, character,
- def, descrip);
-#ifdef USE_X_TOOLKIT
- if (! NILP (submap))
- {
- push_submenu_start ();
- single_keymap_panes (submap, Qnil,
- character, notreal,
- maxdepth - 1);
- push_submenu_end ();
- }
-#endif
- }
- }
- }
- }
- }
- }
-
- /* Process now any submenus which want to be panes at this level. */
- while (!NILP (pending_maps))
- {
- Lisp_Object elt, eltcdr, string;
- elt = Fcar (pending_maps);
- eltcdr = XCONS (elt)->cdr;
- string = XCONS (eltcdr)->car;
- /* We no longer discard the @ from the beginning of the string here.
- Instead, we do this in xmenu_show. */
- single_keymap_panes (Fcar (elt), string,
- XCONS (eltcdr)->cdr, notreal, maxdepth - 1);
- pending_maps = Fcdr (pending_maps);
- }
-}
-
-/* Push all the panes and items of a menu described by the
- alist-of-alists MENU.
- This handles old-fashioned calls to x-popup-menu. */
-
-static void
-list_of_panes (menu)
- Lisp_Object menu;
-{
- Lisp_Object tail;
-
- init_menu_items ();
-
- for (tail = menu; !NILP (tail); tail = Fcdr (tail))
- {
- Lisp_Object elt, pane_name, pane_data;
- elt = Fcar (tail);
- pane_name = Fcar (elt);
- CHECK_STRING (pane_name, 0);
- push_menu_pane (pane_name, Qnil);
- pane_data = Fcdr (elt);
- CHECK_CONS (pane_data, 0);
- list_of_items (pane_data);
- }
-
- finish_menu_items ();
-}
-
-/* Push the items in a single pane defined by the alist PANE. */
-
-static void
-list_of_items (pane)
- Lisp_Object pane;
-{
- Lisp_Object tail, item, item1;
-
- for (tail = pane; !NILP (tail); tail = Fcdr (tail))
- {
- item = Fcar (tail);
- if (STRINGP (item))
- push_menu_item (item, Qnil, Qnil, Qt, Qnil);
- else if (NILP (item))
- push_left_right_boundary ();
- else
- {
- CHECK_CONS (item, 0);
- item1 = Fcar (item);
- CHECK_STRING (item1, 1);
- push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil);
- }
- }
-}
-
-DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
- "Pop up a deck-of-cards menu and return user's selection.\n\
-POSITION is a position specification. This is either a mouse button event\n\
-or a list ((XOFFSET YOFFSET) WINDOW)\n\
-where XOFFSET and YOFFSET are positions in pixels from the top left\n\
-corner of WINDOW's frame. (WINDOW may be a frame object instead of a window.)\n\
-This controls the position of the center of the first line\n\
-in the first pane of the menu, not the top left of the menu as a whole.\n\
-If POSITION is t, it means to use the current mouse position.\n\
-\n\
-MENU is a specifier for a menu. For the simplest case, MENU is a keymap.\n\
-The menu items come from key bindings that have a menu string as well as\n\
-a definition; actually, the \"definition\" in such a key binding looks like\n\
-\(STRING . REAL-DEFINITION). To give the menu a title, put a string into\n\
-the keymap as a top-level element.\n\n\
-You can also use a list of keymaps as MENU.\n\
- Then each keymap makes a separate pane.\n\
-When MENU is a keymap or a list of keymaps, the return value\n\
-is a list of events.\n\n\
-Alternatively, you can specify a menu of multiple panes\n\
- with a list of the form (TITLE PANE1 PANE2...),\n\
-where each pane is a list of form (TITLE ITEM1 ITEM2...).\n\
-Each ITEM is normally a cons cell (STRING . VALUE);\n\
-but a string can appear as an item--that makes a nonselectable line\n\
-in the menu.\n\
-With this form of menu, the return value is VALUE from the chosen item.\n\
-\n\
-If POSITION is nil, don't display the menu at all, just precalculate the\n\
-cached information about equivalent key sequences.")
- (position, menu)
- Lisp_Object position, menu;
-{
- int number_of_panes, panes;
- Lisp_Object keymap, tem;
- int xpos, ypos;
- Lisp_Object title;
- char *error_name;
- Lisp_Object selection;
- int i, j;
- FRAME_PTR f;
- Lisp_Object x, y, window;
- int keymaps = 0;
- int for_click = 0;
- struct gcpro gcpro1;
-
-#ifdef HAVE_MENUS
- if (! NILP (position))
- {
- check_x ();
-
- /* Decode the first argument: find the window and the coordinates. */
- if (EQ (position, Qt)
- || (CONSP (position) && EQ (XCONS (position)->car, Qmenu_bar)))
- {
- /* Use the mouse's current position. */
- FRAME_PTR new_f = selected_frame;
- Lisp_Object bar_window;
- int part;
- unsigned long time;
-
- if (mouse_position_hook)
- (*mouse_position_hook) (&new_f, 1, &bar_window,
- &part, &x, &y, &time);
- if (new_f != 0)
- XSETFRAME (window, new_f);
- else
- {
- window = selected_window;
- XSETFASTINT (x, 0);
- XSETFASTINT (y, 0);
- }
- }
- else
- {
- tem = Fcar (position);
- if (CONSP (tem))
- {
- window = Fcar (Fcdr (position));
- x = Fcar (tem);
- y = Fcar (Fcdr (tem));
- }
- else
- {
- for_click = 1;
- tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
- window = Fcar (tem); /* POSN_WINDOW (tem) */
- tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
- x = Fcar (tem);
- y = Fcdr (tem);
- }
- }
-
- CHECK_NUMBER (x, 0);
- CHECK_NUMBER (y, 0);
-
- /* Decode where to put the menu. */
-
- if (FRAMEP (window))
- {
- f = XFRAME (window);
- xpos = 0;
- ypos = 0;
- }
- else if (WINDOWP (window))
- {
- CHECK_LIVE_WINDOW (window, 0);
- f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
-
- xpos = (FONT_WIDTH (f->output_data.x->font) * XWINDOW (window)->left);
- ypos = (f->output_data.x->line_height * XWINDOW (window)->top);
- }
- else
- /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
- but I don't want to make one now. */
- CHECK_WINDOW (window, 0);
-
- xpos += XINT (x);
- ypos += XINT (y);
-
- XSETFRAME (Vmenu_updating_frame, f);
- }
- Vmenu_updating_frame = Qnil;
-#endif /* HAVE_MENUS */
-
- title = Qnil;
- GCPRO1 (title);
-
- /* Decode the menu items from what was specified. */
-
- keymap = Fkeymapp (menu);
- tem = Qnil;
- if (CONSP (menu))
- tem = Fkeymapp (Fcar (menu));
- if (!NILP (keymap))
- {
- /* We were given a keymap. Extract menu info from the keymap. */
- Lisp_Object prompt;
- keymap = get_keymap (menu);
-
- /* Extract the detailed info to make one pane. */
- keymap_panes (&menu, 1, NILP (position));
-
- /* Search for a string appearing directly as an element of the keymap.
- That string is the title of the menu. */
- prompt = map_prompt (keymap);
- if (NILP (title) && !NILP (prompt))
- title = prompt;
-
- /* Make that be the pane title of the first pane. */
- if (!NILP (prompt) && menu_items_n_panes >= 0)
- XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = prompt;
-
- keymaps = 1;
- }
- else if (!NILP (tem))
- {
- /* We were given a list of keymaps. */
- int nmaps = XFASTINT (Flength (menu));
- Lisp_Object *maps
- = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
- int i;
-
- title = Qnil;
-
- /* The first keymap that has a prompt string
- supplies the menu title. */
- for (tem = menu, i = 0; CONSP (tem); tem = Fcdr (tem))
- {
- Lisp_Object prompt;
-
- maps[i++] = keymap = get_keymap (Fcar (tem));
-
- prompt = map_prompt (keymap);
- if (NILP (title) && !NILP (prompt))
- title = prompt;
- }
-
- /* Extract the detailed info to make one pane. */
- keymap_panes (maps, nmaps, NILP (position));
-
- /* Make the title be the pane title of the first pane. */
- if (!NILP (title) && menu_items_n_panes >= 0)
- XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title;
-
- keymaps = 1;
- }
- else
- {
- /* We were given an old-fashioned menu. */
- title = Fcar (menu);
- CHECK_STRING (title, 1);
-
- list_of_panes (Fcdr (menu));
-
- keymaps = 0;
- }
-
- if (NILP (position))
- {
- discard_menu_items ();
- UNGCPRO;
- return Qnil;
- }
-
-#ifdef HAVE_MENUS
- /* Display them in a menu. */
- BLOCK_INPUT;
-
- selection = xmenu_show (f, xpos, ypos, for_click,
- keymaps, title, &error_name);
- UNBLOCK_INPUT;
-
- discard_menu_items ();
-
- UNGCPRO;
-#endif /* HAVE_MENUS */
-
- if (error_name) error (error_name);
- return selection;
-}
-
-#ifdef HAVE_MENUS
-
-DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 2, 0,
- "Pop up a dialog box and return user's selection.\n\
-POSITION specifies which frame to use.\n\
-This is normally a mouse button event or a window or frame.\n\
-If POSITION is t, it means to use the frame the mouse is on.\n\
-The dialog box appears in the middle of the specified frame.\n\
-\n\
-CONTENTS specifies the alternatives to display in the dialog box.\n\
-It is a list of the form (TITLE ITEM1 ITEM2...).\n\
-Each ITEM is a cons cell (STRING . VALUE).\n\
-The return value is VALUE from the chosen item.\n\n\
-An ITEM may also be just a string--that makes a nonselectable item.\n\
-An ITEM may also be nil--that means to put all preceding items\n\
-on the left of the dialog box and all following items on the right.\n\
-\(By default, approximately half appear on each side.)")
- (position, contents)
- Lisp_Object position, contents;
-{
- FRAME_PTR f;
- Lisp_Object window;
-
- check_x ();
-
- /* Decode the first argument: find the window or frame to use. */
- if (EQ (position, Qt)
- || (CONSP (position) && EQ (XCONS (position)->car, Qmenu_bar)))
- {
-#if 0 /* Using the frame the mouse is on may not be right. */
- /* Use the mouse's current position. */
- FRAME_PTR new_f = selected_frame;
- Lisp_Object bar_window;
- int part;
- unsigned long time;
- Lisp_Object x, y;
-
- (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
-
- if (new_f != 0)
- XSETFRAME (window, new_f);
- else
- window = selected_window;
-#endif
- window = selected_window;
- }
- else if (CONSP (position))
- {
- Lisp_Object tem;
- tem = Fcar (position);
- if (CONSP (tem))
- window = Fcar (Fcdr (position));
- else
- {
- tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
- window = Fcar (tem); /* POSN_WINDOW (tem) */
- }
- }
- else if (WINDOWP (position) || FRAMEP (position))
- window = position;
- else
- window = Qnil;
-
- /* Decode where to put the menu. */
-
- if (FRAMEP (window))
- f = XFRAME (window);
- else if (WINDOWP (window))
- {
- CHECK_LIVE_WINDOW (window, 0);
- f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
- }
- else
- /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
- but I don't want to make one now. */
- CHECK_WINDOW (window, 0);
-
-#ifndef USE_X_TOOLKIT
- /* Display a menu with these alternatives
- in the middle of frame F. */
- {
- Lisp_Object x, y, frame, newpos;
- XSETFRAME (frame, f);
- XSETINT (x, x_pixel_width (f) / 2);
- XSETINT (y, x_pixel_height (f) / 2);
- newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
-
- return Fx_popup_menu (newpos,
- Fcons (Fcar (contents), Fcons (contents, Qnil)));
- }
-#else
- {
- Lisp_Object title;
- char *error_name;
- Lisp_Object selection;
-
- /* Decode the dialog items from what was specified. */
- title = Fcar (contents);
- CHECK_STRING (title, 1);
-
- list_of_panes (Fcons (contents, Qnil));
-
- /* Display them in a dialog box. */
- BLOCK_INPUT;
- selection = xdialog_show (f, 0, title, &error_name);
- UNBLOCK_INPUT;
-
- discard_menu_items ();
-
- if (error_name) error (error_name);
- return selection;
- }
-#endif
-}
-
-#ifdef USE_X_TOOLKIT
-
-/* Loop in Xt until the menu pulldown or dialog popup has been
- popped down (deactivated). This is used for x-popup-menu
- and x-popup-dialog; it is not used for the menu bar any more.
-
- NOTE: All calls to popup_get_selection should be protected
- with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */
-
-void
-popup_get_selection (initial_event, dpyinfo, id)
- XEvent *initial_event;
- struct x_display_info *dpyinfo;
- LWLIB_ID id;
-{
- XEvent event;
-
- /* Define a queue to save up for later unreading
- all X events that don't pertain to the menu. */
- struct event_queue
- {
- XEvent event;
- struct event_queue *next;
- };
-
- struct event_queue *queue = NULL;
- struct event_queue *queue_tmp;
-
- if (initial_event)
- event = *initial_event;
- else
- XtAppNextEvent (Xt_app_con, &event);
-
- while (1)
- {
- /* Handle expose events for editor frames right away. */
- if (event.type == Expose)
- process_expose_from_menu (event);
- /* Make sure we don't consider buttons grabbed after menu goes.
- And make sure to deactivate for any ButtonRelease,
- even if XtDispatchEvent doesn't do that. */
- else if (event.type == ButtonRelease
- && dpyinfo->display == event.xbutton.display)
- {
- dpyinfo->grabbed &= ~(1 << event.xbutton.button);
- popup_activated_flag = 0;
-#ifdef USE_MOTIF /* Pretending that the event came from a
- Btn1Down seems the only way to convince Motif to
- activate its callbacks; setting the XmNmenuPost
- isn't working. --marcus@sysc.pdx.edu. */
- event.xbutton.button = 1;
-#endif
- }
- /* If the user presses a key, deactivate the menu.
- The user is likely to do that if we get wedged. */
- else if (event.type == KeyPress
- && dpyinfo->display == event.xbutton.display)
- {
- popup_activated_flag = 0;
- break;
- }
- /* Button presses outside the menu also pop it down. */
- else if (event.type == ButtonPress
- && event.xany.display == dpyinfo->display
- && x_any_window_to_frame (dpyinfo, event.xany.window))
- {
- popup_activated_flag = 0;
- break;
- }
-
- /* Queue all events not for this popup,
- except for Expose, which we've already handled, and ButtonRelease.
- Note that the X window is associated with the frame if this
- is a menu bar popup, but not if it's a dialog box. So we use
- x_non_menubar_window_to_frame, not x_any_window_to_frame. */
- if (event.type != Expose
- && !(event.type == ButtonRelease
- && dpyinfo->display == event.xbutton.display)
- && (event.xany.display != dpyinfo->display
- || x_non_menubar_window_to_frame (dpyinfo, event.xany.window)))
- {
- queue_tmp = (struct event_queue *) malloc (sizeof (struct event_queue));
-
- if (queue_tmp != NULL)
- {
- queue_tmp->event = event;
- queue_tmp->next = queue;
- queue = queue_tmp;
- }
- }
- else
- XtDispatchEvent (&event);
-
- if (!popup_activated ())
- break;
- XtAppNextEvent (Xt_app_con, &event);
- }
-
- /* Unread any events that we got but did not handle. */
- while (queue != NULL)
- {
- queue_tmp = queue;
- XPutBackEvent (queue_tmp->event.xany.display, &queue_tmp->event);
- queue = queue_tmp->next;
- free ((char *)queue_tmp);
- /* Cause these events to get read as soon as we UNBLOCK_INPUT. */
- interrupt_input_pending = 1;
- }
-}
-
-/* Activate the menu bar of frame F.
- This is called from keyboard.c when it gets the
- menu_bar_activate_event out of the Emacs event queue.
-
- To activate the menu bar, we use the X button-press event
- that was saved in saved_menu_event.
- That makes the toolkit do its thing.
-
- But first we recompute the menu bar contents (the whole tree).
-
- The reason for saving the button event until here, instead of
- passing it to the toolkit right away, is that we can safely
- execute Lisp code. */
-
-x_activate_menubar (f)
- FRAME_PTR f;
-{
- if (!f->output_data.x->saved_menu_event->type)
- return;
-
- set_frame_menubar (f, 0, 1);
- BLOCK_INPUT;
- XtDispatchEvent ((XEvent *) f->output_data.x->saved_menu_event);
- UNBLOCK_INPUT;
-#ifdef USE_MOTIF
- if (f->output_data.x->saved_menu_event->type == ButtonRelease)
- pending_menu_activation = 1;
-#endif
-
- /* Ignore this if we get it a second time. */
- f->output_data.x->saved_menu_event->type = 0;
-}
-
-/* Detect if a dialog or menu has been posted. */
-
-int
-popup_activated ()
-{
- return popup_activated_flag;
-}
-
-
-/* This callback is invoked when the user selects a menubar cascade
- pushbutton, but before the pulldown menu is posted. */
-
-static void
-popup_activate_callback (widget, id, client_data)
- Widget widget;
- LWLIB_ID id;
- XtPointer client_data;
-{
- popup_activated_flag = 1;
-}
-
-/* This callback is called from the menu bar pulldown menu
- when the user makes a selection.
- Figure out what the user chose
- and put the appropriate events into the keyboard buffer. */
-
-static void
-menubar_selection_callback (widget, id, client_data)
- Widget widget;
- LWLIB_ID id;
- XtPointer client_data;
-{
- Lisp_Object prefix, entry;
- FRAME_PTR f = menubar_id_to_frame (id);
- Lisp_Object vector;
- Lisp_Object *subprefix_stack;
- int submenu_depth = 0;
- int i;
-
- if (!f)
- return;
- subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof (Lisp_Object));
- vector = f->menu_bar_vector;
- prefix = Qnil;
- i = 0;
- while (i < f->menu_bar_items_used)
- {
- if (EQ (XVECTOR (vector)->contents[i], Qnil))
- {
- subprefix_stack[submenu_depth++] = prefix;
- prefix = entry;
- i++;
- }
- else if (EQ (XVECTOR (vector)->contents[i], Qlambda))
- {
- prefix = subprefix_stack[--submenu_depth];
- i++;
- }
- else if (EQ (XVECTOR (vector)->contents[i], Qt))
- {
- prefix = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX];
- i += MENU_ITEMS_PANE_LENGTH;
- }
- else
- {
- entry = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE];
- /* The EMACS_INT cast avoids a warning. There's no problem
- as long as pointers have enough bits to hold small integers. */
- if ((int) (EMACS_INT) client_data == i)
- {
- int j;
- struct input_event buf;
- Lisp_Object frame;
-
- XSETFRAME (frame, f);
- buf.kind = menu_bar_event;
- buf.frame_or_window = Fcons (frame, Fcons (Qmenu_bar, Qnil));
- kbd_buffer_store_event (&buf);
-
- for (j = 0; j < submenu_depth; j++)
- if (!NILP (subprefix_stack[j]))
- {
- buf.kind = menu_bar_event;
- buf.frame_or_window = Fcons (frame, subprefix_stack[j]);
- kbd_buffer_store_event (&buf);
- }
-
- if (!NILP (prefix))
- {
- buf.kind = menu_bar_event;
- buf.frame_or_window = Fcons (frame, prefix);
- kbd_buffer_store_event (&buf);
- }
-
- buf.kind = menu_bar_event;
- buf.frame_or_window = Fcons (frame, entry);
- kbd_buffer_store_event (&buf);
-
- return;
- }
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
-}
-
-/* This callback is invoked when a dialog or menu is finished being
- used and has been unposted. */
-
-static void
-popup_deactivate_callback (widget, id, client_data)
- Widget widget;
- LWLIB_ID id;
- XtPointer client_data;
-{
- popup_activated_flag = 0;
-}
-
-/* Allocate a widget_value, blocking input. */
-
-widget_value *
-xmalloc_widget_value ()
-{
- widget_value *value;
-
- BLOCK_INPUT;
- value = malloc_widget_value ();
- UNBLOCK_INPUT;
-
- return value;
-}
-
-/* This recursively calls free_widget_value on the tree of widgets.
- It must free all data that was malloc'ed for these widget_values.
- In Emacs, many slots are pointers into the data of Lisp_Strings, and
- must be left alone. */
-
-void
-free_menubar_widget_value_tree (wv)
- widget_value *wv;
-{
- if (! wv) return;
-
- wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
-
- if (wv->contents && (wv->contents != (widget_value*)1))
- {
- free_menubar_widget_value_tree (wv->contents);
- wv->contents = (widget_value *) 0xDEADBEEF;
- }
- if (wv->next)
- {
- free_menubar_widget_value_tree (wv->next);
- wv->next = (widget_value *) 0xDEADBEEF;
- }
- BLOCK_INPUT;
- free_widget_value (wv);
- UNBLOCK_INPUT;
-}
-
-/* Return a tree of widget_value structures for a menu bar item
- whose event type is ITEM_KEY (with string ITEM_NAME)
- and whose contents come from the list of keymaps MAPS. */
-
-static widget_value *
-single_submenu (item_key, item_name, maps)
- Lisp_Object item_key, item_name, maps;
-{
- widget_value *wv, *prev_wv, *save_wv, *first_wv;
- int i;
- int submenu_depth = 0;
- Lisp_Object length;
- int len;
- Lisp_Object *mapvec;
- widget_value **submenu_stack;
- int mapno;
- int previous_items = menu_items_used;
- int top_level_items = 0;
-
- length = Flength (maps);
- len = XINT (length);
-
- /* Convert the list MAPS into a vector MAPVEC. */
- mapvec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- for (i = 0; i < len; i++)
- {
- mapvec[i] = Fcar (maps);
- maps = Fcdr (maps);
- }
-
- menu_items_n_panes = 0;
-
- /* Loop over the given keymaps, making a pane for each map.
- But don't make a pane that is empty--ignore that map instead. */
- for (i = 0; i < len; i++)
- {
- if (SYMBOLP (mapvec[i])
- || (CONSP (mapvec[i])
- && NILP (Fkeymapp (mapvec[i]))))
- {
- /* Here we have a command at top level in the menu bar
- as opposed to a submenu. */
- top_level_items = 1;
- push_menu_pane (Qnil, Qnil);
- push_menu_item (item_name, Qt, item_key, mapvec[i], Qnil);
- }
- else
- single_keymap_panes (mapvec[i], item_name, item_key, 0, 10);
- }
-
- /* Create a tree of widget_value objects
- representing the panes and their items. */
-
- submenu_stack
- = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
- wv = xmalloc_widget_value ();
- wv->name = "menu";
- wv->value = 0;
- wv->enabled = 1;
- first_wv = wv;
- save_wv = 0;
- prev_wv = 0;
-
- /* Loop over all panes and items made during this call
- and construct a tree of widget_value objects.
- Ignore the panes and items made by previous calls to
- single_submenu, even though those are also in menu_items. */
- i = previous_items;
- while (i < menu_items_used)
- {
- if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
- {
- submenu_stack[submenu_depth++] = save_wv;
- save_wv = prev_wv;
- prev_wv = 0;
- i++;
- }
- else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
- {
- prev_wv = save_wv;
- save_wv = submenu_stack[--submenu_depth];
- i++;
- }
- else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
- && submenu_depth != 0)
- i += MENU_ITEMS_PANE_LENGTH;
- /* Ignore a nil in the item list.
- It's meaningful only for dialog boxes. */
- else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
- i += 1;
- else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
- {
- /* Create a new pane. */
- Lisp_Object pane_name, prefix;
- char *pane_string;
- pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
- prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
- pane_string = (NILP (pane_name)
- ? "" : (char *) XSTRING (pane_name)->data);
- /* If there is just one top-level pane, put all its items directly
- under the top-level menu. */
- if (menu_items_n_panes == 1)
- pane_string = "";
-
- /* If the pane has a meaningful name,
- make the pane a top-level menu item
- with its items as a submenu beneath it. */
- if (strcmp (pane_string, ""))
- {
- wv = xmalloc_widget_value ();
- if (save_wv)
- save_wv->next = wv;
- else
- first_wv->contents = wv;
- wv->name = pane_string;
- /* Ignore the @ that means "separate pane".
- This is a kludge, but this isn't worth more time. */
- if (!NILP (prefix) && wv->name[0] == '@')
- wv->name++;
- wv->value = 0;
- wv->enabled = 1;
- }
- save_wv = wv;
- prev_wv = 0;
- i += MENU_ITEMS_PANE_LENGTH;
- }
- else
- {
- /* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip, def;
- item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
- enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
- descrip
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
- def = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_DEFINITION];
-
- wv = xmalloc_widget_value ();
- if (prev_wv)
- prev_wv->next = wv;
- else
- save_wv->contents = wv;
-
- wv->name = (char *) XSTRING (item_name)->data;
- if (!NILP (descrip))
- wv->key = (char *) XSTRING (descrip)->data;
- wv->value = 0;
- /* The EMACS_INT cast avoids a warning. There's no problem
- as long as pointers have enough bits to hold small integers. */
- wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0);
- wv->enabled = !NILP (enable);
- prev_wv = wv;
-
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
-
- /* If we have just one "menu item"
- that was originally a button, return it by itself. */
- if (top_level_items && first_wv->contents && first_wv->contents->next == 0)
- {
- wv = first_wv->contents;
- free_widget_value (first_wv);
- return wv;
- }
-
- return first_wv;
-}
-
-extern void EmacsFrameSetCharSize ();
-
-/* Recompute all the widgets of frame F, when the menu bar
- has been changed. */
-
-static void
-update_frame_menubar (f)
- FRAME_PTR f;
-{
- struct x_output *x = f->output_data.x;
- int columns, rows;
- int menubar_changed;
-
- Dimension shell_height;
-
- /* We assume the menubar contents has changed if the global flag is set,
- or if the current buffer has changed, or if the menubar has never
- been updated before.
- */
- menubar_changed = (x->menubar_widget
- && !XtIsManaged (x->menubar_widget));
-
- if (! (menubar_changed))
- return;
-
- BLOCK_INPUT;
- /* Save the size of the frame because the pane widget doesn't accept to
- resize itself. So force it. */
- columns = f->width;
- rows = f->height;
-
- /* Do the voodoo which means "I'm changing lots of things, don't try to
- refigure sizes until I'm done." */
- lw_refigure_widget (x->column_widget, False);
-
- /* the order in which children are managed is the top to
- bottom order in which they are displayed in the paned window.
- First, remove the text-area widget.
- */
- XtUnmanageChild (x->edit_widget);
-
- /* remove the menubar that is there now, and put up the menubar that
- should be there.
- */
- if (menubar_changed)
- {
- XtManageChild (x->menubar_widget);
- XtMapWidget (x->menubar_widget);
- XtVaSetValues (x->menubar_widget, XtNmappedWhenManaged, 1, 0);
- }
-
- /* Re-manage the text-area widget, and then thrash the sizes. */
- XtManageChild (x->edit_widget);
- lw_refigure_widget (x->column_widget, True);
-
- /* Force the pane widget to resize itself with the right values. */
- EmacsFrameSetCharSize (x->edit_widget, columns, rows);
-
- UNBLOCK_INPUT;
-}
-
-/* Set the contents of the menubar widgets of frame F.
- The argument FIRST_TIME is currently ignored;
- it is set the first time this is called, from initialize_frame_menubar. */
-
-void
-set_frame_menubar (f, first_time, deep_p)
- FRAME_PTR f;
- int first_time;
- int deep_p;
-{
- Widget menubar_widget = f->output_data.x->menubar_widget;
- Lisp_Object tail, items, frame;
- widget_value *wv, *first_wv, *prev_wv = 0;
- int i;
- LWLIB_ID id;
-
- XSETFRAME (Vmenu_updating_frame, f);
-
- if (f->output_data.x->id == 0)
- f->output_data.x->id = next_menubar_widget_id++;
- id = f->output_data.x->id;
-
- if (! menubar_widget)
- deep_p = 1;
- else if (pending_menu_activation && !deep_p)
- deep_p = 1;
- /* Make the first call for any given frame always go deep. */
- else if (!f->output_data.x->saved_menu_event && !deep_p)
- {
- deep_p = 1;
- f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent));
- f->output_data.x->saved_menu_event->type = 0;
- }
-
- wv = xmalloc_widget_value ();
- wv->name = "menubar";
- wv->value = 0;
- wv->enabled = 1;
- first_wv = wv;
-
- if (deep_p)
- {
- /* Make a widget-value tree representing the entire menu trees. */
-
- struct buffer *prev = current_buffer;
- Lisp_Object buffer;
- int specpdl_count = specpdl_ptr - specpdl;
- int previous_menu_items_used = f->menu_bar_items_used;
- Lisp_Object *previous_items
- = (Lisp_Object *) alloca (previous_menu_items_used
- * sizeof (Lisp_Object));
-
- buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
- specbind (Qinhibit_quit, Qt);
- /* Don't let the debugger step into this code
- because it is not reentrant. */
- specbind (Qdebug_on_next_call, Qnil);
-
- record_unwind_protect (Fstore_match_data, Fmatch_data (Qnil, Qnil));
- if (NILP (Voverriding_local_map_menu_flag))
- {
- specbind (Qoverriding_terminal_local_map, Qnil);
- specbind (Qoverriding_local_map, Qnil);
- }
-
- set_buffer_internal_1 (XBUFFER (buffer));
-
- /* Run the Lucid hook. */
- call1 (Vrun_hooks, Qactivate_menubar_hook);
- /* If it has changed current-menubar from previous value,
- really recompute the menubar from the value. */
- if (! NILP (Vlucid_menu_bar_dirty_flag))
- call0 (Qrecompute_lucid_menubar);
- safe_run_hooks (Qmenu_bar_update_hook);
- FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
-
- items = FRAME_MENU_BAR_ITEMS (f);
-
- inhibit_garbage_collection ();
-
- /* Save the frame's previous menu bar contents data. */
- bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
- previous_menu_items_used * sizeof (Lisp_Object));
-
- /* Fill in the current menu bar contents. */
- menu_items = f->menu_bar_vector;
- menu_items_allocated = XVECTOR (menu_items)->size;
- init_menu_items ();
- for (i = 0; i < XVECTOR (items)->size; i += 4)
- {
- Lisp_Object key, string, maps;
-
- key = XVECTOR (items)->contents[i];
- string = XVECTOR (items)->contents[i + 1];
- maps = XVECTOR (items)->contents[i + 2];
- if (NILP (string))
- break;
-
- wv = single_submenu (key, string, maps);
- if (prev_wv)
- prev_wv->next = wv;
- else
- first_wv->contents = wv;
- /* Don't set wv->name here; GC during the loop might relocate it. */
- wv->enabled = 1;
- prev_wv = wv;
- }
-
- finish_menu_items ();
-
- set_buffer_internal_1 (prev);
- unbind_to (specpdl_count, Qnil);
-
- /* If there has been no change in the Lisp-level contents
- of the menu bar, skip redisplaying it. Just exit. */
-
- for (i = 0; i < previous_menu_items_used; i++)
- if (menu_items_used == i
- || (previous_items[i] != XVECTOR (menu_items)->contents[i]))
- break;
- if (i == menu_items_used && i == previous_menu_items_used && i != 0)
- {
- free_menubar_widget_value_tree (first_wv);
- menu_items = Qnil;
-
- return;
- }
-
- /* Now GC cannot happen during the lifetime of the widget_value,
- so it's safe to store data from a Lisp_String. */
- wv = first_wv->contents;
- for (i = 0; i < XVECTOR (items)->size; i += 4)
- {
- Lisp_Object string;
- string = XVECTOR (items)->contents[i + 1];
- if (NILP (string))
- break;
- wv->name = (char *) XSTRING (string)->data;
- wv = wv->next;
- }
-
- f->menu_bar_vector = menu_items;
- f->menu_bar_items_used = menu_items_used;
- menu_items = Qnil;
- }
- else
- {
- /* Make a widget-value tree containing
- just the top level menu bar strings. */
-
- items = FRAME_MENU_BAR_ITEMS (f);
- for (i = 0; i < XVECTOR (items)->size; i += 4)
- {
- Lisp_Object string;
-
- string = XVECTOR (items)->contents[i + 1];
- if (NILP (string))
- break;
-
- wv = xmalloc_widget_value ();
- wv->name = (char *) XSTRING (string)->data;
- wv->value = 0;
- wv->enabled = 1;
- /* This prevents lwlib from assuming this
- menu item is really supposed to be empty. */
- /* The EMACS_INT cast avoids a warning.
- This value just has to be different from small integers. */
- wv->call_data = (void *) (EMACS_INT) (-1);
-
- if (prev_wv)
- prev_wv->next = wv;
- else
- first_wv->contents = wv;
- prev_wv = wv;
- }
-
- /* Forget what we thought we knew about what is in the
- detailed contents of the menu bar menus.
- Changing the top level always destroys the contents. */
- f->menu_bar_items_used = 0;
- }
-
- /* Create or update the menu bar widget. */
-
- BLOCK_INPUT;
-
- if (menubar_widget)
- {
- /* Disable resizing (done for Motif!) */
- lw_allow_resizing (f->output_data.x->widget, False);
-
- /* The third arg is DEEP_P, which says to consider the entire
- menu trees we supply, rather than just the menu bar item names. */
- lw_modify_all_widgets (id, first_wv, deep_p);
-
- /* Re-enable the edit widget to resize. */
- lw_allow_resizing (f->output_data.x->widget, True);
- }
- else
- {
- menubar_widget = lw_create_widget ("menubar", "menubar", id, first_wv,
- f->output_data.x->column_widget,
- 0,
- popup_activate_callback,
- menubar_selection_callback,
- popup_deactivate_callback);
- f->output_data.x->menubar_widget = menubar_widget;
- }
-
- {
- int menubar_size
- = (f->output_data.x->menubar_widget
- ? (f->output_data.x->menubar_widget->core.height
- + f->output_data.x->menubar_widget->core.border_width)
- : 0);
-
-#if 0 /* Experimentally, we now get the right results
- for -geometry -0-0 without this. 24 Aug 96, rms. */
-#ifdef USE_LUCID
- if (FRAME_EXTERNAL_MENU_BAR (f))
- {
- Dimension ibw = 0;
- XtVaGetValues (f->output_data.x->column_widget,
- XtNinternalBorderWidth, &ibw, NULL);
- menubar_size += ibw;
- }
-#endif /* USE_LUCID */
-#endif /* 0 */
-
- f->output_data.x->menubar_height = menubar_size;
- }
-
- free_menubar_widget_value_tree (first_wv);
-
- update_frame_menubar (f);
-
- UNBLOCK_INPUT;
-}
-
-/* Called from Fx_create_frame to create the initial menubar of a frame
- before it is mapped, so that the window is mapped with the menubar already
- there instead of us tacking it on later and thrashing the window after it
- is visible. */
-
-void
-initialize_frame_menubar (f)
- FRAME_PTR f;
-{
- /* This function is called before the first chance to redisplay
- the frame. It has to be, so the frame will have the right size. */
- FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
- set_frame_menubar (f, 1, 1);
-}
-
-/* Get rid of the menu bar of frame F, and free its storage.
- This is used when deleting a frame, and when turning off the menu bar. */
-
-void
-free_frame_menubar (f)
- FRAME_PTR f;
-{
- Widget menubar_widget;
- int id;
-
- menubar_widget = f->output_data.x->menubar_widget;
-
- if (menubar_widget)
- {
- BLOCK_INPUT;
- lw_destroy_all_widgets ((LWLIB_ID) f->output_data.x->id);
- UNBLOCK_INPUT;
- }
-}
-
-#endif /* USE_X_TOOLKIT */
-
-/* xmenu_show actually displays a menu using the panes and items in menu_items
- and returns the value selected from it.
- There are two versions of xmenu_show, one for Xt and one for Xlib.
- Both assume input is blocked by the caller. */
-
-/* F is the frame the menu is for.
- X and Y are the frame-relative specified position,
- relative to the inside upper left corner of the frame F.
- FOR_CLICK is nonzero if this menu was invoked for a mouse click.
- KEYMAPS is 1 if this menu was specified with keymaps;
- in that case, we return a list containing the chosen item's value
- and perhaps also the pane's prefix.
- TITLE is the specified menu title.
- ERROR is a place to store an error message string in case of failure.
- (We return nil on failure, but the value doesn't actually matter.) */
-
-#ifdef USE_X_TOOLKIT
-
-/* We need a unique id for each widget handled by the Lucid Widget
- library.
-
- For the main windows, and popup menus, we use this counter,
- which we increment each time after use. This starts from 1<<16.
-
- For menu bars, we use numbers starting at 0, counted in
- next_menubar_widget_id. */
-LWLIB_ID widget_id_tick;
-
-#ifdef __STDC__
-static Lisp_Object *volatile menu_item_selection;
-#else
-static Lisp_Object *menu_item_selection;
-#endif
-
-static void
-popup_selection_callback (widget, id, client_data)
- Widget widget;
- LWLIB_ID id;
- XtPointer client_data;
-{
- menu_item_selection = (Lisp_Object *) client_data;
-}
-
-static Lisp_Object
-xmenu_show (f, x, y, for_click, keymaps, title, error)
- FRAME_PTR f;
- int x;
- int y;
- int for_click;
- int keymaps;
- Lisp_Object title;
- char **error;
-{
- int i;
- LWLIB_ID menu_id;
- Widget menu;
- Arg av[2];
- int ac = 0;
- widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
- widget_value **submenu_stack
- = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
- Lisp_Object *subprefix_stack
- = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
- int submenu_depth = 0;
- XButtonPressedEvent dummy;
-
- int first_pane;
- int next_release_must_exit = 0;
-
- *error = NULL;
-
- if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
- {
- *error = "Empty menu";
- return Qnil;
- }
-
- /* Create a tree of widget_value objects
- representing the panes and their items. */
- wv = xmalloc_widget_value ();
- wv->name = "menu";
- wv->value = 0;
- wv->enabled = 1;
- first_wv = wv;
- first_pane = 1;
-
- /* Loop over all panes and items, filling in the tree. */
- i = 0;
- while (i < menu_items_used)
- {
- if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
- {
- submenu_stack[submenu_depth++] = save_wv;
- save_wv = prev_wv;
- prev_wv = 0;
- first_pane = 1;
- i++;
- }
- else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
- {
- prev_wv = save_wv;
- save_wv = submenu_stack[--submenu_depth];
- first_pane = 0;
- i++;
- }
- else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
- && submenu_depth != 0)
- i += MENU_ITEMS_PANE_LENGTH;
- /* Ignore a nil in the item list.
- It's meaningful only for dialog boxes. */
- else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
- i += 1;
- else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
- {
- /* Create a new pane. */
- Lisp_Object pane_name, prefix;
- char *pane_string;
- pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
- prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
- pane_string = (NILP (pane_name)
- ? "" : (char *) XSTRING (pane_name)->data);
- /* If there is just one top-level pane, put all its items directly
- under the top-level menu. */
- if (menu_items_n_panes == 1)
- pane_string = "";
-
- /* If the pane has a meaningful name,
- make the pane a top-level menu item
- with its items as a submenu beneath it. */
- if (!keymaps && strcmp (pane_string, ""))
- {
- wv = xmalloc_widget_value ();
- if (save_wv)
- save_wv->next = wv;
- else
- first_wv->contents = wv;
- wv->name = pane_string;
- if (keymaps && !NILP (prefix))
- wv->name++;
- wv->value = 0;
- wv->enabled = 1;
- save_wv = wv;
- prev_wv = 0;
- }
- else if (first_pane)
- {
- save_wv = wv;
- prev_wv = 0;
- }
- first_pane = 0;
- i += MENU_ITEMS_PANE_LENGTH;
- }
- else
- {
- /* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip, def;
- item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
- enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
- descrip
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
- def = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_DEFINITION];
-
- wv = xmalloc_widget_value ();
- if (prev_wv)
- prev_wv->next = wv;
- else
- save_wv->contents = wv;
- wv->name = (char *) XSTRING (item_name)->data;
- if (!NILP (descrip))
- wv->key = (char *) XSTRING (descrip)->data;
- wv->value = 0;
- /* If this item has a null value,
- make the call_data null so that it won't display a box
- when the mouse is on it. */
- wv->call_data
- = (!NILP (def) ? (void *) &XVECTOR (menu_items)->contents[i] : 0);
- wv->enabled = !NILP (enable);
- prev_wv = wv;
-
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
-
- /* Deal with the title, if it is non-nil. */
- if (!NILP (title))
- {
- widget_value *wv_title = xmalloc_widget_value ();
- widget_value *wv_sep1 = xmalloc_widget_value ();
- widget_value *wv_sep2 = xmalloc_widget_value ();
-
- wv_sep2->name = "--";
- wv_sep2->next = first_wv->contents;
-
- wv_sep1->name = "--";
- wv_sep1->next = wv_sep2;
-
- wv_title->name = (char *) XSTRING (title)->data;
- wv_title->enabled = True;
- wv_title->next = wv_sep1;
- first_wv->contents = wv_title;
- }
-
- /* Actually create the menu. */
- menu_id = widget_id_tick++;
- menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
- f->output_data.x->widget, 1, 0,
- popup_selection_callback,
- popup_deactivate_callback);
-
- /* Adjust coordinates to relative to the outer (window manager) window. */
- {
- Window child;
- int win_x = 0, win_y = 0;
-
- /* Find the position of the outside upper-left corner of
- the inner window, with respect to the outer window. */
- if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
- {
- BLOCK_INPUT;
- XTranslateCoordinates (FRAME_X_DISPLAY (f),
-
- /* From-window, to-window. */
- f->output_data.x->window_desc,
- f->output_data.x->parent_desc,
-
- /* From-position, to-position. */
- 0, 0, &win_x, &win_y,
-
- /* Child of window. */
- &child);
- UNBLOCK_INPUT;
- x += win_x;
- y += win_y;
- }
- }
-
- /* Adjust coordinates to be root-window-relative. */
- x += f->output_data.x->left_pos;
- y += f->output_data.x->top_pos;
-
- dummy.type = ButtonPress;
- dummy.serial = 0;
- dummy.send_event = 0;
- dummy.display = FRAME_X_DISPLAY (f);
- dummy.time = CurrentTime;
- dummy.root = FRAME_X_DISPLAY_INFO (f)->root_window;
- dummy.window = dummy.root;
- dummy.subwindow = dummy.root;
- dummy.x_root = x;
- dummy.y_root = y;
- dummy.x = x;
- dummy.y = y;
- dummy.state = (FRAME_X_DISPLAY_INFO (f)->grabbed >> 1) * Button1Mask;
- dummy.button = 0;
- for (i = 0; i < 5; i++)
- if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
- dummy.button = i;
-
- /* Don't allow any geometry request from the user. */
- XtSetArg (av[ac], XtNgeometry, 0); ac++;
- XtSetValues (menu, av, ac);
-
- /* Free the widget_value objects we used to specify the contents. */
- free_menubar_widget_value_tree (first_wv);
-
- /* No selection has been chosen yet. */
- menu_item_selection = 0;
-
- /* Display the menu. */
- lw_popup_menu (menu, &dummy);
- popup_activated_flag = 1;
-
- /* Process events that apply to the menu. */
- popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id);
-
- /* fp turned off the following statement and wrote a comment
- that it is unnecessary--that the menu has already disappeared.
- Nowadays the menu disappears ok, all right, but
- we need to delete the widgets or multiple ones will pile up. */
- lw_destroy_all_widgets (menu_id);
-
- /* Find the selected item, and its pane, to return
- the proper value. */
- if (menu_item_selection != 0)
- {
- Lisp_Object prefix, entry;
-
- prefix = Qnil;
- i = 0;
- while (i < menu_items_used)
- {
- if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
- {
- subprefix_stack[submenu_depth++] = prefix;
- prefix = entry;
- i++;
- }
- else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
- {
- prefix = subprefix_stack[--submenu_depth];
- i++;
- }
- else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
- {
- prefix
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
- i += MENU_ITEMS_PANE_LENGTH;
- }
- /* Ignore a nil in the item list.
- It's meaningful only for dialog boxes. */
- else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
- i += 1;
- else
- {
- entry
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
- if (menu_item_selection == &XVECTOR (menu_items)->contents[i])
- {
- if (keymaps != 0)
- {
- int j;
-
- entry = Fcons (entry, Qnil);
- if (!NILP (prefix))
- entry = Fcons (prefix, entry);
- for (j = submenu_depth - 1; j >= 0; j--)
- if (!NILP (subprefix_stack[j]))
- entry = Fcons (subprefix_stack[j], entry);
- }
- return entry;
- }
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
- }
-
- return Qnil;
-}
-
-static void
-dialog_selection_callback (widget, id, client_data)
- Widget widget;
- LWLIB_ID id;
- XtPointer client_data;
-{
- /* The EMACS_INT cast avoids a warning. There's no problem
- as long as pointers have enough bits to hold small integers. */
- if ((int) (EMACS_INT) client_data != -1)
- menu_item_selection = (Lisp_Object *) client_data;
- BLOCK_INPUT;
- lw_destroy_all_widgets (id);
- UNBLOCK_INPUT;
- popup_activated_flag = 0;
-}
-
-static char * button_names [] = {
- "button1", "button2", "button3", "button4", "button5",
- "button6", "button7", "button8", "button9", "button10" };
-
-static Lisp_Object
-xdialog_show (f, keymaps, title, error)
- FRAME_PTR f;
- int keymaps;
- Lisp_Object title;
- char **error;
-{
- int i, nb_buttons=0;
- LWLIB_ID dialog_id;
- Widget menu;
- char dialog_name[6];
-
- widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
-
- /* Number of elements seen so far, before boundary. */
- int left_count = 0;
- /* 1 means we've seen the boundary between left-hand elts and right-hand. */
- int boundary_seen = 0;
-
- *error = NULL;
-
- if (menu_items_n_panes > 1)
- {
- *error = "Multiple panes in dialog box";
- return Qnil;
- }
-
- /* Create a tree of widget_value objects
- representing the text label and buttons. */
- {
- Lisp_Object pane_name, prefix;
- char *pane_string;
- pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
- prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
- pane_string = (NILP (pane_name)
- ? "" : (char *) XSTRING (pane_name)->data);
- prev_wv = xmalloc_widget_value ();
- prev_wv->value = pane_string;
- if (keymaps && !NILP (prefix))
- prev_wv->name++;
- prev_wv->enabled = 1;
- prev_wv->name = "message";
- first_wv = prev_wv;
-
- /* Loop over all panes and items, filling in the tree. */
- i = MENU_ITEMS_PANE_LENGTH;
- while (i < menu_items_used)
- {
-
- /* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip;
- item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
- enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
- descrip
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
-
- if (NILP (item_name))
- {
- free_menubar_widget_value_tree (first_wv);
- *error = "Submenu in dialog items";
- return Qnil;
- }
- if (EQ (item_name, Qquote))
- {
- /* This is the boundary between left-side elts
- and right-side elts. Stop incrementing right_count. */
- boundary_seen = 1;
- i++;
- continue;
- }
- if (nb_buttons >= 9)
- {
- free_menubar_widget_value_tree (first_wv);
- *error = "Too many dialog items";
- return Qnil;
- }
-
- wv = xmalloc_widget_value ();
- prev_wv->next = wv;
- wv->name = (char *) button_names[nb_buttons];
- if (!NILP (descrip))
- wv->key = (char *) XSTRING (descrip)->data;
- wv->value = (char *) XSTRING (item_name)->data;
- wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
- wv->enabled = !NILP (enable);
- prev_wv = wv;
-
- if (! boundary_seen)
- left_count++;
-
- nb_buttons++;
- i += MENU_ITEMS_ITEM_LENGTH;
- }
-
- /* If the boundary was not specified,
- by default put half on the left and half on the right. */
- if (! boundary_seen)
- left_count = nb_buttons - nb_buttons / 2;
-
- wv = xmalloc_widget_value ();
- wv->name = dialog_name;
-
- /* Dialog boxes use a really stupid name encoding
- which specifies how many buttons to use
- and how many buttons are on the right.
- The Q means something also. */
- dialog_name[0] = 'Q';
- dialog_name[1] = '0' + nb_buttons;
- dialog_name[2] = 'B';
- dialog_name[3] = 'R';
- /* Number of buttons to put on the right. */
- dialog_name[4] = '0' + nb_buttons - left_count;
- dialog_name[5] = 0;
- wv->contents = first_wv;
- first_wv = wv;
- }
-
- /* Actually create the dialog. */
- dialog_id = widget_id_tick++;
- menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
- f->output_data.x->widget, 1, 0,
- dialog_selection_callback, 0);
- lw_modify_all_widgets (dialog_id, first_wv->contents, True);
- /* Free the widget_value objects we used to specify the contents. */
- free_menubar_widget_value_tree (first_wv);
-
- /* No selection has been chosen yet. */
- menu_item_selection = 0;
-
- /* Display the menu. */
- lw_pop_up_all_widgets (dialog_id);
- popup_activated_flag = 1;
-
- /* Process events that apply to the menu. */
- popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id);
-
- lw_destroy_all_widgets (dialog_id);
-
- /* Find the selected item, and its pane, to return
- the proper value. */
- if (menu_item_selection != 0)
- {
- Lisp_Object prefix;
-
- prefix = Qnil;
- i = 0;
- while (i < menu_items_used)
- {
- Lisp_Object entry;
-
- if (EQ (XVECTOR (menu_items)->contents[i], Qt))
- {
- prefix
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
- i += MENU_ITEMS_PANE_LENGTH;
- }
- else
- {
- entry
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
- if (menu_item_selection == &XVECTOR (menu_items)->contents[i])
- {
- if (keymaps != 0)
- {
- entry = Fcons (entry, Qnil);
- if (!NILP (prefix))
- entry = Fcons (prefix, entry);
- }
- return entry;
- }
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
- }
-
- return Qnil;
-}
-#else /* not USE_X_TOOLKIT */
-
-static Lisp_Object
-xmenu_show (f, x, y, for_click, keymaps, title, error)
- FRAME_PTR f;
- int x, y;
- int for_click;
- int keymaps;
- Lisp_Object title;
- char **error;
-{
- Window root;
- XMenu *menu;
- int pane, selidx, lpane, status;
- Lisp_Object entry, pane_prefix;
- char *datap;
- int ulx, uly, width, height;
- int dispwidth, dispheight;
- int i, j;
- int maxwidth;
- int dummy_int;
- unsigned int dummy_uint;
-
- *error = 0;
- if (menu_items_n_panes == 0)
- return Qnil;
-
- if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
- {
- *error = "Empty menu";
- return Qnil;
- }
-
- /* Figure out which root window F is on. */
- XGetGeometry (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &root,
- &dummy_int, &dummy_int, &dummy_uint, &dummy_uint,
- &dummy_uint, &dummy_uint);
-
- /* Make the menu on that window. */
- menu = XMenuCreate (FRAME_X_DISPLAY (f), root, "emacs");
- if (menu == NULL)
- {
- *error = "Can't create menu";
- return Qnil;
- }
-
-#ifdef HAVE_X_WINDOWS
- /* Adjust coordinates to relative to the outer (window manager) window. */
- {
- Window child;
- int win_x = 0, win_y = 0;
-
- /* Find the position of the outside upper-left corner of
- the inner window, with respect to the outer window. */
- if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
- {
- BLOCK_INPUT;
- XTranslateCoordinates (FRAME_X_DISPLAY (f),
-
- /* From-window, to-window. */
- f->output_data.x->window_desc,
- f->output_data.x->parent_desc,
-
- /* From-position, to-position. */
- 0, 0, &win_x, &win_y,
-
- /* Child of window. */
- &child);
- UNBLOCK_INPUT;
- x += win_x;
- y += win_y;
- }
- }
-#endif /* HAVE_X_WINDOWS */
-
- /* Adjust coordinates to be root-window-relative. */
- x += f->output_data.x->left_pos;
- y += f->output_data.x->top_pos;
-
- /* Create all the necessary panes and their items. */
- i = 0;
- while (i < menu_items_used)
- {
- if (EQ (XVECTOR (menu_items)->contents[i], Qt))
- {
- /* Create a new pane. */
- Lisp_Object pane_name, prefix;
- char *pane_string;
-
- pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
- prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
- pane_string = (NILP (pane_name)
- ? "" : (char *) XSTRING (pane_name)->data);
- if (keymaps && !NILP (prefix))
- pane_string++;
-
- lpane = XMenuAddPane (FRAME_X_DISPLAY (f), menu, pane_string, TRUE);
- if (lpane == XM_FAILURE)
- {
- XMenuDestroy (FRAME_X_DISPLAY (f), menu);
- *error = "Can't create pane";
- return Qnil;
- }
- i += MENU_ITEMS_PANE_LENGTH;
-
- /* Find the width of the widest item in this pane. */
- maxwidth = 0;
- j = i;
- while (j < menu_items_used)
- {
- Lisp_Object item;
- item = XVECTOR (menu_items)->contents[j];
- if (EQ (item, Qt))
- break;
- if (NILP (item))
- {
- j++;
- continue;
- }
- width = XSTRING (item)->size;
- if (width > maxwidth)
- maxwidth = width;
-
- j += MENU_ITEMS_ITEM_LENGTH;
- }
- }
- /* Ignore a nil in the item list.
- It's meaningful only for dialog boxes. */
- else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
- i += 1;
- else
- {
- /* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip;
- unsigned char *item_data;
-
- item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
- enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
- descrip
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
- if (!NILP (descrip))
- {
- int gap = maxwidth - XSTRING (item_name)->size;
-#ifdef C_ALLOCA
- Lisp_Object spacer;
- spacer = Fmake_string (make_number (gap), make_number (' '));
- item_name = concat2 (item_name, spacer);
- item_name = concat2 (item_name, descrip);
- item_data = XSTRING (item_name)->data;
-#else
- /* if alloca is fast, use that to make the space,
- to reduce gc needs. */
- item_data
- = (unsigned char *) alloca (maxwidth
- + XSTRING (descrip)->size + 1);
- bcopy (XSTRING (item_name)->data, item_data,
- XSTRING (item_name)->size);
- for (j = XSTRING (item_name)->size; j < maxwidth; j++)
- item_data[j] = ' ';
- bcopy (XSTRING (descrip)->data, item_data + j,
- XSTRING (descrip)->size);
- item_data[j + XSTRING (descrip)->size] = 0;
-#endif
- }
- else
- item_data = XSTRING (item_name)->data;
-
- if (XMenuAddSelection (FRAME_X_DISPLAY (f),
- menu, lpane, 0, item_data,
- !NILP (enable))
- == XM_FAILURE)
- {
- XMenuDestroy (FRAME_X_DISPLAY (f), menu);
- *error = "Can't add selection to menu";
- return Qnil;
- }
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
-
- /* All set and ready to fly. */
- XMenuRecompute (FRAME_X_DISPLAY (f), menu);
- dispwidth = DisplayWidth (FRAME_X_DISPLAY (f),
- XScreenNumberOfScreen (FRAME_X_SCREEN (f)));
- dispheight = DisplayHeight (FRAME_X_DISPLAY (f),
- XScreenNumberOfScreen (FRAME_X_SCREEN (f)));
- x = min (x, dispwidth);
- y = min (y, dispheight);
- x = max (x, 1);
- y = max (y, 1);
- XMenuLocate (FRAME_X_DISPLAY (f), menu, 0, 0, x, y,
- &ulx, &uly, &width, &height);
- if (ulx+width > dispwidth)
- {
- x -= (ulx + width) - dispwidth;
- ulx = dispwidth - width;
- }
- if (uly+height > dispheight)
- {
- y -= (uly + height) - dispheight;
- uly = dispheight - height;
- }
- if (ulx < 0) x -= ulx;
- if (uly < 0) y -= uly;
-
- XMenuSetAEQ (menu, TRUE);
- XMenuSetFreeze (menu, TRUE);
- pane = selidx = 0;
-
- status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
- x, y, ButtonReleaseMask, &datap);
-
-
-#ifdef HAVE_X_WINDOWS
- /* Assume the mouse has moved out of the X window.
- If it has actually moved in, we will get an EnterNotify. */
- x_mouse_leave (FRAME_X_DISPLAY_INFO (f));
-#endif
-
- switch (status)
- {
- case XM_SUCCESS:
-#ifdef XDEBUG
- fprintf (stderr, "pane= %d line = %d\n", panes, selidx);
-#endif
-
- /* Find the item number SELIDX in pane number PANE. */
- i = 0;
- while (i < menu_items_used)
- {
- if (EQ (XVECTOR (menu_items)->contents[i], Qt))
- {
- if (pane == 0)
- pane_prefix
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
- pane--;
- i += MENU_ITEMS_PANE_LENGTH;
- }
- else
- {
- if (pane == -1)
- {
- if (selidx == 0)
- {
- entry
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
- if (keymaps != 0)
- {
- entry = Fcons (entry, Qnil);
- if (!NILP (pane_prefix))
- entry = Fcons (pane_prefix, entry);
- }
- break;
- }
- selidx--;
- }
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
- break;
-
- case XM_FAILURE:
- *error = "Can't activate menu";
- case XM_IA_SELECT:
- case XM_NO_SELECT:
- entry = Qnil;
- break;
- }
- XMenuDestroy (FRAME_X_DISPLAY (f), menu);
-
-#ifdef HAVE_X_WINDOWS
- /* State that no mouse buttons are now held.
- (The oldXMenu code doesn't track this info for us.)
- That is not necessarily true, but the fiction leads to reasonable
- results, and it is a pain to ask which are actually held now. */
- FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
-#endif
-
- return entry;
-}
-
-#endif /* not USE_X_TOOLKIT */
-
-#endif /* HAVE_MENUS */
-
-syms_of_xmenu ()
-{
- staticpro (&menu_items);
- menu_items = Qnil;
-
- Qmenu_alias = intern ("menu-alias");
- staticpro (&Qmenu_alias);
-
- Qdebug_on_next_call = intern ("debug-on-next-call");
- staticpro (&Qdebug_on_next_call);
-
- DEFVAR_LISP ("menu-updating-frame", &Vmenu_updating_frame,
- "Frame for which we are updating a menu.\n\
-The enable predicate for a menu command should check this variable.");
- Vmenu_updating_frame = Qnil;
-
-#ifdef USE_X_TOOLKIT
- widget_id_tick = (1<<16);
- next_menubar_widget_id = 1;
-#endif
-
- defsubr (&Sx_popup_menu);
-#ifdef HAVE_MENUS
- defsubr (&Sx_popup_dialog);
-#endif
-}
diff --git a/src/xrdb.c b/src/xrdb.c
deleted file mode 100644
index be1b9cbab1d..00000000000
--- a/src/xrdb.c
+++ /dev/null
@@ -1,734 +0,0 @@
-/* Deal with the X Resource Manager.
- Copyright (C) 1990, 1993, 1994 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Written by jla, 4/90 */
-
-#ifdef emacs
-#include <config.h>
-#endif
-
-#include <stdio.h>
-
-#if 1 /* I'd really appreciate it if this code could go away... -JimB */
-/* this avoids lossage in the `dual-universe' headers on AT&T SysV X11 */
-#ifdef USG5
-#ifndef SYSV
-#define SYSV
-#endif
-#include <unistd.h>
-#endif /* USG5 */
-
-#endif /* 1 */
-
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#if 0
-#include <X11/Xos.h>
-#endif
-#include <X11/X.h>
-#include <X11/Xutil.h>
-#include <X11/Xresource.h>
-#ifdef VMS
-#include "vms-pwd.h"
-#else
-#include <pwd.h>
-#endif
-#include <sys/stat.h>
-
-#if !defined(S_ISDIR) && defined(S_IFDIR)
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#endif
-
-extern char *getenv ();
-
-/* This does cause trouble on AIX. I'm going to take the comment at
- face value. */
-#if 0
-extern short getuid (); /* If this causes portability problems,
- I think we should just delete it; it'll
- default to `int' anyway. */
-#endif
-
-#ifdef DECLARE_GETPWUID_WITH_UID_T
-extern struct passwd *getpwuid (uid_t);
-extern struct passwd *getpwnam (const char *);
-#else
-extern struct passwd *getpwuid ();
-extern struct passwd *getpwnam ();
-#endif
-
-extern char *get_system_name ();
-
-/* Make sure not to #include anything after these definitions. Let's
- not step on anyone's prototypes. */
-#ifdef emacs
-#define malloc xmalloc
-#define realloc xrealloc
-#define free xfree
-#endif
-
-char *x_get_string_resource ();
-static int file_p ();
-
-
-/* X file search path processing. */
-
-
-/* The string which gets substituted for the %C escape in XFILESEARCHPATH
- and friends, or zero if none was specified. */
-char *x_customization_string;
-
-
-/* Return the value of the emacs.customization (Emacs.Customization)
- resource, for later use in search path decoding. If we find no
- such resource, return zero. */
-char *
-x_get_customization_string (db, name, class)
- XrmDatabase db;
- char *name, *class;
-{
- char *full_name
- = (char *) alloca (strlen (name) + sizeof ("customization") + 3);
- char *full_class
- = (char *) alloca (strlen (class) + sizeof ("Customization") + 3);
- char *result;
-
- sprintf (full_name, "%s.%s", name, "customization");
- sprintf (full_class, "%s.%s", class, "Customization");
-
- result = x_get_string_resource (db, full_name, full_class);
-
- if (result)
- {
- char *copy = (char *) malloc (strlen (result) + 1);
- strcpy (copy, result);
- return copy;
- }
- else
- return 0;
-}
-
-
-/* Expand all the Xt-style %-escapes in STRING, whose length is given
- by STRING_LEN. Here are the escapes we're supposed to recognize:
-
- %N The value of the application's class name
- %T The value of the type parameter ("app-defaults" in this
- context)
- %S The value of the suffix parameter ("" in this context)
- %L The language string associated with the specified display
- (We use the "LANG" environment variable here, if it's set.)
- %l The language part of the display's language string
- (We treat this just like %L. If someone can tell us what
- we're really supposed to do, dandy.)
- %t The territory part of the display's language string
- (This never gets used.)
- %c The codeset part of the display's language string
- (This never gets used either.)
- %C The customization string retrieved from the resource
- database associated with display.
- (This is x_customization_string.)
-
- Return the expanded file name if it exists and is readable, and
- refers to %L only when the LANG environment variable is set, or
- otherwise provided by X.
-
- ESCAPED_SUFFIX and SUFFIX are postpended to STRING if they are
- non-zero. %-escapes in ESCAPED_SUFFIX are expanded; STRING is left
- alone.
-
- Return NULL otherwise. */
-
-static char *
-magic_file_p (string, string_len, class, escaped_suffix, suffix)
- char *string;
- int string_len;
- char *class, *escaped_suffix, *suffix;
-{
- char *lang = getenv ("LANG");
-
- int path_size = 100;
- char *path = (char *) malloc (path_size);
- int path_len = 0;
-
- char *p = string;
-
- while (p < string + string_len)
- {
- /* The chunk we're about to stick on the end of result. */
- char *next;
- int next_len;
-
- if (*p == '%')
- {
- p++;
-
- if (p >= string + string_len)
- next_len = 0;
- else
- switch (*p)
- {
- case '%':
- next = "%";
- next_len = 1;
- break;
-
- case 'C':
- next = (x_customization_string
- ? x_customization_string
- : "");
- next_len = strlen (next);
- break;
-
- case 'N':
- next = class;
- next_len = strlen (class);
- break;
-
- case 'T':
- next = "app-defaults";
- next_len = strlen (next);
- break;
-
- default:
- case 'S':
- next_len = 0;
- break;
-
- case 'L':
- case 'l':
- if (! lang)
- {
- free (path);
- return NULL;
- }
-
- next = lang;
- next_len = strlen (next);
- break;
-
- case 't':
- case 'c':
- free (path);
- return NULL;
- }
- }
- else
- next = p, next_len = 1;
-
- /* Do we have room for this component followed by a '\0' ? */
- if (path_len + next_len + 1 > path_size)
- {
- path_size = (path_len + next_len + 1) * 2;
- path = (char *) realloc (path, path_size);
- }
-
- bcopy (next, path + path_len, next_len);
- path_len += next_len;
-
- p++;
-
- /* If we've reached the end of the string, append ESCAPED_SUFFIX. */
- if (p >= string + string_len && escaped_suffix)
- {
- string = escaped_suffix;
- string_len = strlen (string);
- p = string;
- escaped_suffix = NULL;
- }
- }
-
- /* Perhaps we should add the SUFFIX now. */
- if (suffix)
- {
- int suffix_len = strlen (suffix);
-
- if (path_len + suffix_len + 1 > path_size)
- {
- path_size = (path_len + suffix_len + 1);
- path = (char *) realloc (path, path_size);
- }
-
- bcopy (suffix, path + path_len, suffix_len);
- path_len += suffix_len;
- }
-
- path[path_len] = '\0';
-
- if (! file_p (path))
- {
- free (path);
- return NULL;
- }
-
- return path;
-}
-
-
-static char *
-gethomedir ()
-{
- struct passwd *pw;
- char *ptr;
- char *copy;
-
- if ((ptr = getenv ("HOME")) == NULL)
- {
- if ((ptr = getenv ("LOGNAME")) != NULL
- || (ptr = getenv ("USER")) != NULL)
- pw = getpwnam (ptr);
- else
- pw = getpwuid (getuid ());
-
- if (pw)
- ptr = pw->pw_dir;
- }
-
- if (ptr == NULL)
- return "/";
-
- copy = (char *) malloc (strlen (ptr) + 2);
- strcpy (copy, ptr);
- strcat (copy, "/");
-
- return copy;
-}
-
-
-static int
-file_p (path)
- char *path;
-{
- struct stat status;
-
- return (access (path, 4) == 0 /* exists and is readable */
- && stat (path, &status) == 0 /* get the status */
- && (S_ISDIR (status.st_mode)) == 0); /* not a directory */
-}
-
-
-/* Find the first element of SEARCH_PATH which exists and is readable,
- after expanding the %-escapes. Return 0 if we didn't find any, and
- the path name of the one we found otherwise. */
-
-static char *
-search_magic_path (search_path, class, escaped_suffix, suffix)
- char *search_path, *class, *escaped_suffix, *suffix;
-{
- register char *s, *p;
-
- for (s = search_path; *s; s = p)
- {
- for (p = s; *p && *p != ':'; p++)
- ;
-
- if (p > s)
- {
- char *path = magic_file_p (s, p - s, class, escaped_suffix, suffix);
- if (path)
- return path;
- }
- else if (*p == ':')
- {
- char *path;
-
- s = "%N%S";
- path = magic_file_p (s, strlen (s), class, escaped_suffix, suffix);
- if (path)
- return path;
- }
-
- if (*p == ':')
- p++;
- }
-
- return 0;
-}
-
-/* Producing databases for individual sources. */
-
-#define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/%L/%T/%N%C%S:/usr/lib/X11/%l/%T/%N%C%S:/usr/lib/X11/%T/%N%C%S:/usr/lib/X11/%L/%T/%N%S:/usr/lib/X11/%l/%T/%N%S:/usr/lib/X11/%T/%N%S"
-
-static XrmDatabase
-get_system_app (class)
- char *class;
-{
- XrmDatabase db = NULL;
- char *path;
-
- path = getenv ("XFILESEARCHPATH");
- if (! path) path = X_DEFAULT_SEARCH_PATH;
-
- path = search_magic_path (path, class, 0, 0);
- if (path)
- {
- db = XrmGetFileDatabase (path);
- free (path);
- }
-
- return db;
-}
-
-
-static XrmDatabase
-get_fallback (display)
- Display *display;
-{
- XrmDatabase db;
-
- return NULL;
-}
-
-
-static XrmDatabase
-get_user_app (class)
- char *class;
-{
- char *path;
- char *file = 0;
-
- /* Check for XUSERFILESEARCHPATH. It is a path of complete file
- names, not directories. */
- if (((path = getenv ("XUSERFILESEARCHPATH"))
- && (file = search_magic_path (path, class, 0, 0)))
-
- /* Check for APPLRESDIR; it is a path of directories. In each,
- we have to search for LANG/CLASS and then CLASS. */
- || ((path = getenv ("XAPPLRESDIR"))
- && ((file = search_magic_path (path, class, "/%L/%N", 0))
- || (file = search_magic_path (path, class, "/%N", 0))))
-
- /* Check in the home directory. This is a bit of a hack; let's
- hope one's home directory doesn't contain any %-escapes. */
- || (path = gethomedir (),
- ((file = search_magic_path (path, class, "%L/%N", 0))
- || (file = search_magic_path (path, class, "%N", 0)))))
- {
- XrmDatabase db = XrmGetFileDatabase (file);
- free (file);
- return db;
- }
- else
- return NULL;
-}
-
-
-static XrmDatabase
-get_user_db (display)
- Display *display;
-{
- XrmDatabase db;
- char *xdefs;
-
-#ifdef PBaseSize /* Cheap way to test for X11R4 or later. */
- xdefs = XResourceManagerString (display);
-#else
- xdefs = display->xdefaults;
-#endif
-
- if (xdefs != NULL)
- db = XrmGetStringDatabase (xdefs);
- else
- {
- char *home;
- char *xdefault;
-
- home = gethomedir ();
- xdefault = (char *) malloc (strlen (home) + sizeof (".Xdefaults"));
- strcpy (xdefault, home);
- strcat (xdefault, ".Xdefaults");
- db = XrmGetFileDatabase (xdefault);
- free (home);
- free (xdefault);
- }
-
-#ifdef HAVE_XSCREENRESOURCESTRING
- /* Get the screen-specific resources too. */
- xdefs = XScreenResourceString (DefaultScreenOfDisplay (display));
- if (xdefs != NULL)
- {
- XrmMergeDatabases (XrmGetStringDatabase (xdefs), &db);
- XFree (xdefs);
- }
-#endif
-
- return db;
-}
-
-static XrmDatabase
-get_environ_db ()
-{
- XrmDatabase db;
- char *p;
- char *path = 0, *home = 0, *host;
-
- if ((p = getenv ("XENVIRONMENT")) == NULL)
- {
- home = gethomedir ();
- host = get_system_name ();
- path = (char *) malloc (strlen (home)
- + sizeof (".Xdefaults-")
- + strlen (host));
- sprintf (path, "%s%s%s", home, ".Xdefaults-", host);
- p = path;
- }
-
- db = XrmGetFileDatabase (p);
-
- if (path) free (path);
- if (home) free (home);
-
- return db;
-}
-
-/* External interface. */
-
-/* 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, myname, myclass)
- Display *display;
- char *xrm_string, *myname, *myclass;
-{
- char *xdefs;
- XrmDatabase user_database;
- XrmDatabase rdb;
- XrmDatabase db;
-
- x_rm_string = XrmStringToQuark (XrmStringType);
-#ifndef USE_X_TOOLKIT
- /* pmr@osf.org says this shouldn't be done if USE_X_TOOLKIT.
- I suspect it's because the toolkit version does this elsewhere. */
- XrmInitialize ();
-#endif
- rdb = XrmGetStringDatabase ("");
-
- user_database = get_user_db (display);
-
- /* Figure out what the "customization string" is, so we can use it
- to decode paths. */
- if (x_customization_string)
- free (x_customization_string);
- x_customization_string
- = x_get_customization_string (user_database, myname, myclass);
-
- /* 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 */
- if (user_database != NULL)
- XrmMergeDatabases (user_database, &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)
- ret_value->addr = (char *) 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;
-}
-
-/* Stand-alone test facilities. */
-
-#ifdef TESTRM
-
-typedef char **List;
-#define arg_listify(len, list) (list)
-#define car(list) (*(list))
-#define cdr(list) (list + 1)
-#define NIL(list) (! *(list))
-#define free_arglist(list)
-
-static List
-member (elt, list)
- char *elt;
- List list;
-{
- List p;
-
- for (p = list; ! NIL (p); p = cdr (p))
- if (! strcmp (elt, car (p)))
- return p;
-
- return p;
-}
-
-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, *name;
- 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";
-
- lp = member ("-n", arg_list);
- if (! NIL (lp))
- name = car (cdr (lp));
- else
- name = "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, name, class);
-
- /* In a real program, you'd want to also do this: */
- display->db = xdb;
-
- while (1)
- {
- char query_name[90];
- char query_class[90];
-
- printf ("Name: ");
- gets (query_name);
-
- if (strlen (query_name))
- {
- char *value;
-
- printf ("Class: ");
- gets (query_class);
-
- value = x_get_string_resource (xdb, query_name, query_class);
-
- if (value != NULL)
- printf ("\t%s(%s): %s\n\n", query_name, query_class, value);
- else
- printf ("\tNo Value.\n\n");
- }
- else
- break;
- }
- printf ("\tExit.\n\n");
-
- XCloseDisplay (display);
-}
-#endif /* TESTRM */
diff --git a/src/xselect.c b/src/xselect.c
deleted file mode 100644
index 009e206ebdf..00000000000
--- a/src/xselect.c
+++ /dev/null
@@ -1,2209 +0,0 @@
-/* X Selection processing for Emacs.
- Copyright (C) 1993, 1994, 1995, 1996 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 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Rewritten by jwz */
-
-#include <config.h>
-#include "lisp.h"
-#include "xterm.h" /* for all of the X includes */
-#include "dispextern.h" /* frame.h seems to want this */
-#include "frame.h" /* Need this to get the X window of selected_frame */
-#include "blockinput.h"
-
-#define CUT_BUFFER_SUPPORT
-
-Lisp_Object QPRIMARY, QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP,
- QTEXT, QDELETE, QMULTIPLE, QINCR, QEMACS_TMP, QTARGETS, QATOM, QNULL,
- QATOM_PAIR;
-
-#ifdef CUT_BUFFER_SUPPORT
-Lisp_Object QCUT_BUFFER0, QCUT_BUFFER1, QCUT_BUFFER2, QCUT_BUFFER3,
- QCUT_BUFFER4, QCUT_BUFFER5, QCUT_BUFFER6, QCUT_BUFFER7;
-#endif
-
-static Lisp_Object Vx_lost_selection_hooks;
-static Lisp_Object Vx_sent_selection_hooks;
-
-/* If this is a smaller number than the max-request-size of the display,
- emacs will use INCR selection transfer when the selection is larger
- than this. The max-request-size is usually around 64k, so if you want
- emacs to use incremental selection transfers when the selection is
- smaller than that, set this. I added this mostly for debugging the
- incremental transfer stuff, but it might improve server performance. */
-#define MAX_SELECTION_QUANTUM 0xFFFFFF
-
-#ifdef HAVE_X11R4
-#define SELECTION_QUANTUM(dpy) ((XMaxRequestSize(dpy) << 2) - 100)
-#else
-#define SELECTION_QUANTUM(dpy) (((dpy)->max_request_size << 2) - 100)
-#endif
-
-/* The timestamp of the last input event Emacs received from the X server. */
-/* Defined in keyboard.c. */
-extern unsigned long last_event_timestamp;
-
-/* This is an association list whose elements are of the form
- ( SELECTION-NAME SELECTION-VALUE SELECTION-TIMESTAMP FRAME)
- SELECTION-NAME is a lisp symbol, whose name is the name of an X Atom.
- SELECTION-VALUE is the value that emacs owns for that selection.
- It may be any kind of Lisp object.
- SELECTION-TIMESTAMP is the time at which emacs began owning this selection,
- as a cons of two 16-bit numbers (making a 32 bit time.)
- FRAME is the frame for which we made the selection.
- If there is an entry in this alist, then it can be assumed that Emacs owns
- that selection.
- The only (eq) parts of this list that are visible from Lisp are the
- selection-values. */
-static Lisp_Object Vselection_alist;
-
-/* This is an alist whose CARs are selection-types (whose names are the same
- as the names of X Atoms) and whose CDRs are the names of Lisp functions to
- call to convert the given Emacs selection value to a string representing
- the given selection type. This is for Lisp-level extension of the emacs
- selection handling. */
-static Lisp_Object Vselection_converter_alist;
-
-/* If the selection owner takes too long to reply to a selection request,
- we give up on it. This is in milliseconds (0 = no timeout.) */
-static int x_selection_timeout;
-
-/* Utility functions */
-
-static void lisp_data_to_selection_data ();
-static Lisp_Object selection_data_to_lisp_data ();
-static Lisp_Object x_get_window_property_as_lisp_data ();
-
-/* This converts a Lisp symbol to a server Atom, avoiding a server
- roundtrip whenever possible. */
-
-static Atom
-symbol_to_x_atom (dpyinfo, display, sym)
- struct x_display_info *dpyinfo;
- Display *display;
- Lisp_Object sym;
-{
- Atom val;
- if (NILP (sym)) return 0;
- if (EQ (sym, QPRIMARY)) return XA_PRIMARY;
- if (EQ (sym, QSECONDARY)) return XA_SECONDARY;
- if (EQ (sym, QSTRING)) return XA_STRING;
- if (EQ (sym, QINTEGER)) return XA_INTEGER;
- if (EQ (sym, QATOM)) return XA_ATOM;
- if (EQ (sym, QCLIPBOARD)) return dpyinfo->Xatom_CLIPBOARD;
- if (EQ (sym, QTIMESTAMP)) return dpyinfo->Xatom_TIMESTAMP;
- if (EQ (sym, QTEXT)) return dpyinfo->Xatom_TEXT;
- if (EQ (sym, QDELETE)) return dpyinfo->Xatom_DELETE;
- if (EQ (sym, QMULTIPLE)) return dpyinfo->Xatom_MULTIPLE;
- if (EQ (sym, QINCR)) return dpyinfo->Xatom_INCR;
- if (EQ (sym, QEMACS_TMP)) return dpyinfo->Xatom_EMACS_TMP;
- if (EQ (sym, QTARGETS)) return dpyinfo->Xatom_TARGETS;
- if (EQ (sym, QNULL)) return dpyinfo->Xatom_NULL;
-#ifdef CUT_BUFFER_SUPPORT
- if (EQ (sym, QCUT_BUFFER0)) return XA_CUT_BUFFER0;
- if (EQ (sym, QCUT_BUFFER1)) return XA_CUT_BUFFER1;
- if (EQ (sym, QCUT_BUFFER2)) return XA_CUT_BUFFER2;
- if (EQ (sym, QCUT_BUFFER3)) return XA_CUT_BUFFER3;
- if (EQ (sym, QCUT_BUFFER4)) return XA_CUT_BUFFER4;
- if (EQ (sym, QCUT_BUFFER5)) return XA_CUT_BUFFER5;
- if (EQ (sym, QCUT_BUFFER6)) return XA_CUT_BUFFER6;
- if (EQ (sym, QCUT_BUFFER7)) return XA_CUT_BUFFER7;
-#endif
- if (!SYMBOLP (sym)) abort ();
-
-#if 0
- fprintf (stderr, " XInternAtom %s\n", (char *) XSYMBOL (sym)->name->data);
-#endif
- BLOCK_INPUT;
- val = XInternAtom (display, (char *) XSYMBOL (sym)->name->data, False);
- UNBLOCK_INPUT;
- return val;
-}
-
-
-/* This converts a server Atom to a Lisp symbol, avoiding server roundtrips
- and calls to intern whenever possible. */
-
-static Lisp_Object
-x_atom_to_symbol (dpyinfo, display, atom)
- struct x_display_info *dpyinfo;
- Display *display;
- Atom atom;
-{
- char *str;
- Lisp_Object val;
- if (! atom) return Qnil;
- switch (atom)
- {
- case XA_PRIMARY:
- return QPRIMARY;
- case XA_SECONDARY:
- return QSECONDARY;
- case XA_STRING:
- return QSTRING;
- case XA_INTEGER:
- return QINTEGER;
- case XA_ATOM:
- return QATOM;
-#ifdef CUT_BUFFER_SUPPORT
- case XA_CUT_BUFFER0:
- return QCUT_BUFFER0;
- case XA_CUT_BUFFER1:
- return QCUT_BUFFER1;
- case XA_CUT_BUFFER2:
- return QCUT_BUFFER2;
- case XA_CUT_BUFFER3:
- return QCUT_BUFFER3;
- case XA_CUT_BUFFER4:
- return QCUT_BUFFER4;
- case XA_CUT_BUFFER5:
- return QCUT_BUFFER5;
- case XA_CUT_BUFFER6:
- return QCUT_BUFFER6;
- case XA_CUT_BUFFER7:
- return QCUT_BUFFER7;
-#endif
- }
-
- if (atom == dpyinfo->Xatom_CLIPBOARD)
- return QCLIPBOARD;
- if (atom == dpyinfo->Xatom_TIMESTAMP)
- return QTIMESTAMP;
- if (atom == dpyinfo->Xatom_TEXT)
- return QTEXT;
- if (atom == dpyinfo->Xatom_DELETE)
- return QDELETE;
- if (atom == dpyinfo->Xatom_MULTIPLE)
- return QMULTIPLE;
- if (atom == dpyinfo->Xatom_INCR)
- return QINCR;
- if (atom == dpyinfo->Xatom_EMACS_TMP)
- return QEMACS_TMP;
- if (atom == dpyinfo->Xatom_TARGETS)
- return QTARGETS;
- if (atom == dpyinfo->Xatom_NULL)
- return QNULL;
-
- BLOCK_INPUT;
- str = XGetAtomName (display, atom);
- UNBLOCK_INPUT;
-#if 0
- fprintf (stderr, " XGetAtomName --> %s\n", str);
-#endif
- if (! str) return Qnil;
- val = intern (str);
- BLOCK_INPUT;
- /* This was allocated by Xlib, so use XFree. */
- XFree (str);
- UNBLOCK_INPUT;
- return val;
-}
-
-/* Do protocol to assert ourself as a selection owner.
- Update the Vselection_alist so that we can reply to later requests for
- our selection. */
-
-static void
-x_own_selection (selection_name, selection_value)
- Lisp_Object selection_name, selection_value;
-{
- Window selecting_window = FRAME_X_WINDOW (selected_frame);
- Display *display = FRAME_X_DISPLAY (selected_frame);
- Time time = last_event_timestamp;
- Atom selection_atom;
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (selected_frame);
-
- CHECK_SYMBOL (selection_name, 0);
- selection_atom = symbol_to_x_atom (dpyinfo, display, selection_name);
-
- BLOCK_INPUT;
- x_catch_errors (display);
- XSetSelectionOwner (display, selection_atom, selecting_window, time);
- x_check_errors (display, "Can't set selection: %s");
- x_uncatch_errors (display);
- UNBLOCK_INPUT;
-
- /* Now update the local cache */
- {
- Lisp_Object selection_time;
- Lisp_Object selection_data;
- Lisp_Object prev_value;
-
- selection_time = long_to_cons ((unsigned long) time);
- selection_data = Fcons (selection_name,
- Fcons (selection_value,
- Fcons (selection_time,
- Fcons (Fselected_frame (), Qnil))));
- prev_value = assq_no_quit (selection_name, Vselection_alist);
-
- Vselection_alist = Fcons (selection_data, Vselection_alist);
-
- /* If we already owned the selection, remove the old selection data.
- Perhaps we should destructively modify it instead.
- Don't use Fdelq as that may QUIT. */
- if (!NILP (prev_value))
- {
- Lisp_Object rest; /* we know it's not the CAR, so it's easy. */
- for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
- if (EQ (prev_value, Fcar (XCONS (rest)->cdr)))
- {
- XCONS (rest)->cdr = Fcdr (XCONS (rest)->cdr);
- break;
- }
- }
- }
-}
-
-/* Given a selection-name and desired type, look up our local copy of
- the selection value and convert it to the type.
- The value is nil or a string.
- This function is used both for remote requests
- and for local x-get-selection-internal.
-
- This calls random Lisp code, and may signal or gc. */
-
-static Lisp_Object
-x_get_local_selection (selection_symbol, target_type)
- Lisp_Object selection_symbol, target_type;
-{
- Lisp_Object local_value;
- Lisp_Object handler_fn, value, type, check;
- int count;
-
- local_value = assq_no_quit (selection_symbol, Vselection_alist);
-
- if (NILP (local_value)) return Qnil;
-
- /* TIMESTAMP and MULTIPLE are special cases 'cause that's easiest. */
- if (EQ (target_type, QTIMESTAMP))
- {
- handler_fn = Qnil;
- value = XCONS (XCONS (XCONS (local_value)->cdr)->cdr)->car;
- }
-#if 0
- else if (EQ (target_type, QDELETE))
- {
- handler_fn = Qnil;
- Fx_disown_selection_internal
- (selection_symbol,
- XCONS (XCONS (XCONS (local_value)->cdr)->cdr)->car);
- value = QNULL;
- }
-#endif
-
-#if 0 /* #### MULTIPLE doesn't work yet */
- else if (CONSP (target_type)
- && XCONS (target_type)->car == QMULTIPLE)
- {
- Lisp_Object pairs;
- int size;
- int i;
- pairs = XCONS (target_type)->cdr;
- size = XVECTOR (pairs)->size;
- /* If the target is MULTIPLE, then target_type looks like
- (MULTIPLE . [[SELECTION1 TARGET1] [SELECTION2 TARGET2] ... ])
- We modify the second element of each pair in the vector and
- return it as [[SELECTION1 <value1>] [SELECTION2 <value2>] ... ]
- */
- for (i = 0; i < size; i++)
- {
- Lisp_Object pair;
- pair = XVECTOR (pairs)->contents [i];
- XVECTOR (pair)->contents [1]
- = x_get_local_selection (XVECTOR (pair)->contents [0],
- XVECTOR (pair)->contents [1]);
- }
- return pairs;
- }
-#endif
- else
- {
- /* Don't allow a quit within the converter.
- When the user types C-g, he would be surprised
- if by luck it came during a converter. */
- count = specpdl_ptr - specpdl;
- specbind (Qinhibit_quit, Qt);
-
- CHECK_SYMBOL (target_type, 0);
- handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist));
- if (!NILP (handler_fn))
- value = call3 (handler_fn,
- selection_symbol, target_type,
- XCONS (XCONS (local_value)->cdr)->car);
- else
- value = Qnil;
- unbind_to (count, Qnil);
- }
-
- /* Make sure this value is of a type that we could transmit
- to another X client. */
-
- check = value;
- if (CONSP (value)
- && SYMBOLP (XCONS (value)->car))
- type = XCONS (value)->car,
- check = XCONS (value)->cdr;
-
- if (STRINGP (check)
- || VECTORP (check)
- || SYMBOLP (check)
- || INTEGERP (check)
- || NILP (value))
- return value;
- /* Check for a value that cons_to_long could handle. */
- else if (CONSP (check)
- && INTEGERP (XCONS (check)->car)
- && (INTEGERP (XCONS (check)->cdr)
- ||
- (CONSP (XCONS (check)->cdr)
- && INTEGERP (XCONS (XCONS (check)->cdr)->car)
- && NILP (XCONS (XCONS (check)->cdr)->cdr))))
- return value;
- else
- return
- Fsignal (Qerror,
- Fcons (build_string ("invalid data returned by selection-conversion function"),
- Fcons (handler_fn, Fcons (value, Qnil))));
-}
-
-/* Subroutines of x_reply_selection_request. */
-
-/* Send a SelectionNotify event to the requestor with property=None,
- meaning we were unable to do what they wanted. */
-
-static void
-x_decline_selection_request (event)
- struct input_event *event;
-{
- XSelectionEvent reply;
- reply.type = SelectionNotify;
- reply.display = SELECTION_EVENT_DISPLAY (event);
- reply.requestor = SELECTION_EVENT_REQUESTOR (event);
- reply.selection = SELECTION_EVENT_SELECTION (event);
- reply.time = SELECTION_EVENT_TIME (event);
- reply.target = SELECTION_EVENT_TARGET (event);
- reply.property = None;
-
- BLOCK_INPUT;
- XSendEvent (reply.display, reply.requestor, False, 0L,
- (XEvent *) &reply);
- XFlush (reply.display);
- UNBLOCK_INPUT;
-}
-
-/* This is the selection request currently being processed.
- It is set to zero when the request is fully processed. */
-static struct input_event *x_selection_current_request;
-
-/* Used as an unwind-protect clause so that, if a selection-converter signals
- an error, we tell the requester that we were unable to do what they wanted
- before we throw to top-level or go into the debugger or whatever. */
-
-static Lisp_Object
-x_selection_request_lisp_error (ignore)
- Lisp_Object ignore;
-{
- if (x_selection_current_request != 0)
- x_decline_selection_request (x_selection_current_request);
- return Qnil;
-}
-
-
-/* This stuff is so that INCR selections are reentrant (that is, so we can
- be servicing multiple INCR selection requests simultaneously.) I haven't
- actually tested that yet. */
-
-/* Keep a list of the property changes that are awaited. */
-
-struct prop_location
-{
- int identifier;
- Display *display;
- Window window;
- Atom property;
- int desired_state;
- int arrived;
- struct prop_location *next;
-};
-
-static struct prop_location *expect_property_change ();
-static void wait_for_property_change ();
-static void unexpect_property_change ();
-static int waiting_for_other_props_on_window ();
-
-static int prop_location_identifier;
-
-static Lisp_Object property_change_reply;
-
-static struct prop_location *property_change_reply_object;
-
-static struct prop_location *property_change_wait_list;
-
-static Lisp_Object
-queue_selection_requests_unwind (frame)
- Lisp_Object frame;
-{
- FRAME_PTR f = XFRAME (frame);
-
- if (! NILP (frame))
- x_stop_queuing_selection_requests (FRAME_X_DISPLAY (f));
- return Qnil;
-}
-
-/* Return some frame whose display info is DPYINFO.
- Return nil if there is none. */
-
-static Lisp_Object
-some_frame_on_display (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- Lisp_Object list, frame;
-
- FOR_EACH_FRAME (list, frame)
- {
- if (FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
- return frame;
- }
-
- return Qnil;
-}
-
-/* Send the reply to a selection request event EVENT.
- TYPE is the type of selection data requested.
- DATA and SIZE describe the data to send, already converted.
- FORMAT is the unit-size (in bits) of the data to be transmitted. */
-
-static void
-x_reply_selection_request (event, format, data, size, type)
- struct input_event *event;
- int format, size;
- unsigned char *data;
- Atom type;
-{
- XSelectionEvent reply;
- Display *display = SELECTION_EVENT_DISPLAY (event);
- Window window = SELECTION_EVENT_REQUESTOR (event);
- int bytes_remaining;
- int format_bytes = format/8;
- int max_bytes = SELECTION_QUANTUM (display);
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
-
- if (max_bytes > MAX_SELECTION_QUANTUM)
- max_bytes = MAX_SELECTION_QUANTUM;
-
- reply.type = SelectionNotify;
- reply.display = display;
- reply.requestor = window;
- reply.selection = SELECTION_EVENT_SELECTION (event);
- reply.time = SELECTION_EVENT_TIME (event);
- reply.target = SELECTION_EVENT_TARGET (event);
- reply.property = SELECTION_EVENT_PROPERTY (event);
- if (reply.property == None)
- reply.property = reply.target;
-
- /* #### XChangeProperty can generate BadAlloc, and we must handle it! */
- BLOCK_INPUT;
- x_catch_errors (display);
-
- /* Store the data on the requested property.
- If the selection is large, only store the first N bytes of it.
- */
- bytes_remaining = size * format_bytes;
- if (bytes_remaining <= max_bytes)
- {
- /* Send all the data at once, with minimal handshaking. */
-#if 0
- fprintf (stderr,"\nStoring all %d\n", bytes_remaining);
-#endif
- XChangeProperty (display, window, reply.property, type, format,
- PropModeReplace, data, size);
- /* At this point, the selection was successfully stored; ack it. */
- XSendEvent (display, window, False, 0L, (XEvent *) &reply);
- }
- else
- {
- /* Send an INCR selection. */
- struct prop_location *wait_object;
- int had_errors;
- int count = specpdl_ptr - specpdl;
- Lisp_Object frame;
-
- frame = some_frame_on_display (dpyinfo);
-
- /* If the display no longer has frames, we can't expect
- to get many more selection requests from it, so don't
- bother trying to queue them. */
- if (!NILP (frame))
- {
- x_start_queuing_selection_requests (display);
-
- record_unwind_protect (queue_selection_requests_unwind,
- frame);
- }
-
- if (x_window_to_frame (dpyinfo, window)) /* #### debug */
- error ("Attempt to transfer an INCR to ourself!");
-#if 0
- fprintf (stderr, "\nINCR %d\n", bytes_remaining);
-#endif
- wait_object = expect_property_change (display, window, reply.property,
- PropertyDelete);
-
- XChangeProperty (display, window, reply.property, dpyinfo->Xatom_INCR,
- 32, PropModeReplace,
- (unsigned char *) &bytes_remaining, 1);
- XSelectInput (display, window, PropertyChangeMask);
- /* Tell 'em the INCR data is there... */
- XSendEvent (display, window, False, 0L, (XEvent *) &reply);
- XFlush (display);
-
- had_errors = x_had_errors_p (display);
- UNBLOCK_INPUT;
-
- /* First, wait for the requester to ack by deleting the property.
- This can run random lisp code (process handlers) or signal. */
- if (! had_errors)
- wait_for_property_change (wait_object);
-
- while (bytes_remaining)
- {
- int i = ((bytes_remaining < max_bytes)
- ? bytes_remaining
- : max_bytes);
-
- BLOCK_INPUT;
-
- wait_object
- = expect_property_change (display, window, reply.property,
- PropertyDelete);
-#if 0
- fprintf (stderr," INCR adding %d\n", i);
-#endif
- /* Append the next chunk of data to the property. */
- XChangeProperty (display, window, reply.property, type, format,
- PropModeAppend, data, i / format_bytes);
- bytes_remaining -= i;
- data += i;
- XFlush (display);
- had_errors = x_had_errors_p (display);
- UNBLOCK_INPUT;
-
- if (had_errors)
- break;
-
- /* Now wait for the requester to ack this chunk by deleting the
- property. This can run random lisp code or signal.
- */
- wait_for_property_change (wait_object);
- }
- /* Now write a zero-length chunk to the property to tell the requester
- that we're done. */
-#if 0
- fprintf (stderr," INCR done\n");
-#endif
- BLOCK_INPUT;
- if (! waiting_for_other_props_on_window (display, window))
- XSelectInput (display, window, 0L);
-
- XChangeProperty (display, window, reply.property, type, format,
- PropModeReplace, data, 0);
-
- unbind_to (count, Qnil);
- }
-
- XFlush (display);
- x_uncatch_errors (display);
- UNBLOCK_INPUT;
-}
-
-/* Handle a SelectionRequest event EVENT.
- This is called from keyboard.c when such an event is found in the queue. */
-
-void
-x_handle_selection_request (event)
- struct input_event *event;
-{
- struct gcpro gcpro1, gcpro2, gcpro3;
- Lisp_Object local_selection_data;
- Lisp_Object selection_symbol;
- Lisp_Object target_symbol;
- Lisp_Object converted_selection;
- Time local_selection_time;
- Lisp_Object successful_p;
- int count;
- struct x_display_info *dpyinfo
- = x_display_info_for_display (SELECTION_EVENT_DISPLAY (event));
-
- local_selection_data = Qnil;
- target_symbol = Qnil;
- converted_selection = Qnil;
- successful_p = Qnil;
-
- GCPRO3 (local_selection_data, converted_selection, target_symbol);
-
- selection_symbol = x_atom_to_symbol (dpyinfo,
- SELECTION_EVENT_DISPLAY (event),
- SELECTION_EVENT_SELECTION (event));
-
- local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
-
- if (NILP (local_selection_data))
- {
- /* Someone asked for the selection, but we don't have it any more.
- */
- x_decline_selection_request (event);
- goto DONE;
- }
-
- local_selection_time = (Time)
- cons_to_long (XCONS (XCONS (XCONS (local_selection_data)->cdr)->cdr)->car);
-
- if (SELECTION_EVENT_TIME (event) != CurrentTime
- && local_selection_time > SELECTION_EVENT_TIME (event))
- {
- /* Someone asked for the selection, and we have one, but not the one
- they're looking for.
- */
- x_decline_selection_request (event);
- goto DONE;
- }
-
- count = specpdl_ptr - specpdl;
- x_selection_current_request = event;
- record_unwind_protect (x_selection_request_lisp_error, Qnil);
-
- target_symbol = x_atom_to_symbol (dpyinfo, SELECTION_EVENT_DISPLAY (event),
- SELECTION_EVENT_TARGET (event));
-
-#if 0 /* #### MULTIPLE doesn't work yet */
- if (EQ (target_symbol, QMULTIPLE))
- target_symbol = fetch_multiple_target (event);
-#endif
-
- /* Convert lisp objects back into binary data */
-
- converted_selection
- = x_get_local_selection (selection_symbol, target_symbol);
-
- if (! NILP (converted_selection))
- {
- unsigned char *data;
- unsigned int size;
- int format;
- Atom type;
- int nofree;
-
- lisp_data_to_selection_data (SELECTION_EVENT_DISPLAY (event),
- converted_selection,
- &data, &type, &size, &format, &nofree);
-
- x_reply_selection_request (event, format, data, size, type);
- successful_p = Qt;
-
- /* Indicate we have successfully processed this event. */
- x_selection_current_request = 0;
-
- /* Use free, not XFree, because lisp_data_to_selection_data
- calls xmalloc itself. */
- if (!nofree)
- free (data);
- }
- unbind_to (count, Qnil);
-
- DONE:
-
- UNGCPRO;
-
- /* Let random lisp code notice that the selection has been asked for. */
- {
- Lisp_Object rest;
- rest = Vx_sent_selection_hooks;
- if (!EQ (rest, Qunbound))
- for (; CONSP (rest); rest = Fcdr (rest))
- call3 (Fcar (rest), selection_symbol, target_symbol, successful_p);
- }
-}
-
-/* Handle a SelectionClear event EVENT, which indicates that some other
- client cleared out our previously asserted selection.
- This is called from keyboard.c when such an event is found in the queue. */
-
-void
-x_handle_selection_clear (event)
- struct input_event *event;
-{
- Display *display = SELECTION_EVENT_DISPLAY (event);
- Atom selection = SELECTION_EVENT_SELECTION (event);
- Time changed_owner_time = SELECTION_EVENT_TIME (event);
-
- Lisp_Object selection_symbol, local_selection_data;
- Time local_selection_time;
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
-
- selection_symbol = x_atom_to_symbol (dpyinfo, display, selection);
-
- local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
-
- /* Well, we already believe that we don't own it, so that's just fine. */
- if (NILP (local_selection_data)) return;
-
- local_selection_time = (Time)
- cons_to_long (XCONS (XCONS (XCONS (local_selection_data)->cdr)->cdr)->car);
-
- /* This SelectionClear is for a selection that we no longer own, so we can
- disregard it. (That is, we have reasserted the selection since this
- request was generated.) */
-
- if (changed_owner_time != CurrentTime
- && local_selection_time > changed_owner_time)
- return;
-
- /* Otherwise, we're really honest and truly being told to drop it.
- Don't use Fdelq as that may QUIT;. */
-
- if (EQ (local_selection_data, Fcar (Vselection_alist)))
- Vselection_alist = Fcdr (Vselection_alist);
- else
- {
- Lisp_Object rest;
- for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
- if (EQ (local_selection_data, Fcar (XCONS (rest)->cdr)))
- {
- XCONS (rest)->cdr = Fcdr (XCONS (rest)->cdr);
- break;
- }
- }
-
- /* Let random lisp code notice that the selection has been stolen. */
-
- {
- Lisp_Object rest;
- rest = Vx_lost_selection_hooks;
- if (!EQ (rest, Qunbound))
- {
- for (; CONSP (rest); rest = Fcdr (rest))
- call1 (Fcar (rest), selection_symbol);
- prepare_menu_bars ();
- redisplay_preserve_echo_area ();
- }
- }
-}
-
-/* Clear all selections that were made from frame F.
- We do this when about to delete a frame. */
-
-void
-x_clear_frame_selections (f)
- FRAME_PTR f;
-{
- Lisp_Object frame;
- Lisp_Object rest;
-
- XSETFRAME (frame, f);
-
- /* Otherwise, we're really honest and truly being told to drop it.
- Don't use Fdelq as that may QUIT;. */
-
- /* Delete elements from the beginning of Vselection_alist. */
- while (!NILP (Vselection_alist)
- && EQ (frame, Fcar (Fcdr (Fcdr (Fcdr (Fcar (Vselection_alist)))))))
- {
- /* Let random Lisp code notice that the selection has been stolen. */
- Lisp_Object hooks, selection_symbol;
-
- hooks = Vx_lost_selection_hooks;
- selection_symbol = Fcar (Fcar (Vselection_alist));
-
- if (!EQ (hooks, Qunbound))
- {
- for (; CONSP (hooks); hooks = Fcdr (hooks))
- call1 (Fcar (hooks), selection_symbol);
-#if 0 /* This can crash when deleting a frame
- from x_connection_closed. Anyway, it seems unnecessary;
- something else should cause a redisplay. */
- redisplay_preserve_echo_area ();
-#endif
- }
-
- Vselection_alist = Fcdr (Vselection_alist);
- }
-
- /* Delete elements after the beginning of Vselection_alist. */
- for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
- if (EQ (frame, Fcar (Fcdr (Fcdr (Fcdr (Fcar (XCONS (rest)->cdr)))))))
- {
- /* Let random Lisp code notice that the selection has been stolen. */
- Lisp_Object hooks, selection_symbol;
-
- hooks = Vx_lost_selection_hooks;
- selection_symbol = Fcar (Fcar (XCONS (rest)->cdr));
-
- if (!EQ (hooks, Qunbound))
- {
- for (; CONSP (hooks); hooks = Fcdr (hooks))
- call1 (Fcar (hooks), selection_symbol);
-#if 0 /* See above */
- redisplay_preserve_echo_area ();
-#endif
- }
- XCONS (rest)->cdr = Fcdr (XCONS (rest)->cdr);
- break;
- }
-}
-
-/* Nonzero if any properties for DISPLAY and WINDOW
- are on the list of what we are waiting for. */
-
-static int
-waiting_for_other_props_on_window (display, window)
- Display *display;
- Window window;
-{
- struct prop_location *rest = property_change_wait_list;
- while (rest)
- if (rest->display == display && rest->window == window)
- return 1;
- else
- rest = rest->next;
- return 0;
-}
-
-/* Add an entry to the list of property changes we are waiting for.
- DISPLAY, WINDOW, PROPERTY, STATE describe what we will wait for.
- The return value is a number that uniquely identifies
- this awaited property change. */
-
-static struct prop_location *
-expect_property_change (display, window, property, state)
- Display *display;
- Window window;
- Lisp_Object property;
- int state;
-{
- struct prop_location *pl
- = (struct prop_location *) xmalloc (sizeof (struct prop_location));
- pl->identifier = ++prop_location_identifier;
- pl->display = display;
- pl->window = window;
- pl->property = property;
- pl->desired_state = state;
- pl->next = property_change_wait_list;
- pl->arrived = 0;
- property_change_wait_list = pl;
- return pl;
-}
-
-/* Delete an entry from the list of property changes we are waiting for.
- IDENTIFIER is the number that uniquely identifies the entry. */
-
-static void
-unexpect_property_change (location)
- struct prop_location *location;
-{
- struct prop_location *prev = 0, *rest = property_change_wait_list;
- while (rest)
- {
- if (rest == location)
- {
- if (prev)
- prev->next = rest->next;
- else
- property_change_wait_list = rest->next;
- free (rest);
- return;
- }
- prev = rest;
- rest = rest->next;
- }
-}
-
-/* Remove the property change expectation element for IDENTIFIER. */
-
-static Lisp_Object
-wait_for_property_change_unwind (identifierval)
- Lisp_Object identifierval;
-{
- unexpect_property_change ((struct prop_location *)
- (XFASTINT (XCONS (identifierval)->car) << 16
- | XFASTINT (XCONS (identifierval)->cdr)));
- return Qnil;
-}
-
-/* Actually wait for a property change.
- IDENTIFIER should be the value that expect_property_change returned. */
-
-static void
-wait_for_property_change (location)
- struct prop_location *location;
-{
- int secs, usecs;
- int count = specpdl_ptr - specpdl;
- Lisp_Object tem;
-
- tem = Fcons (Qnil, Qnil);
- XSETFASTINT (XCONS (tem)->car, (EMACS_UINT)location >> 16);
- XSETFASTINT (XCONS (tem)->cdr, (EMACS_UINT)location & 0xffff);
-
- /* Make sure to do unexpect_property_change if we quit or err. */
- record_unwind_protect (wait_for_property_change_unwind, tem);
-
- XCONS (property_change_reply)->car = Qnil;
-
- property_change_reply_object = location;
- /* If the event we are waiting for arrives beyond here, it will set
- property_change_reply, because property_change_reply_object says so. */
- if (! location->arrived)
- {
- secs = x_selection_timeout / 1000;
- usecs = (x_selection_timeout % 1000) * 1000;
- wait_reading_process_input (secs, usecs, property_change_reply, 0);
-
- if (NILP (XCONS (property_change_reply)->car))
- error ("Timed out waiting for property-notify event");
- }
-
- unbind_to (count, Qnil);
-}
-
-/* Called from XTread_socket in response to a PropertyNotify event. */
-
-void
-x_handle_property_notify (event)
- XPropertyEvent *event;
-{
- struct prop_location *prev = 0, *rest = property_change_wait_list;
- while (rest)
- {
- if (rest->property == event->atom
- && rest->window == event->window
- && rest->display == event->display
- && rest->desired_state == event->state)
- {
-#if 0
- fprintf (stderr, "Saw expected prop-%s on %s\n",
- (event->state == PropertyDelete ? "delete" : "change"),
- (char *) XSYMBOL (x_atom_to_symbol (dpyinfo, event->display,
- event->atom))
- ->name->data);
-#endif
-
- rest->arrived = 1;
-
- /* If this is the one wait_for_property_change is waiting for,
- tell it to wake up. */
- if (rest == property_change_reply_object)
- XCONS (property_change_reply)->car = Qt;
-
- if (prev)
- prev->next = rest->next;
- else
- property_change_wait_list = rest->next;
- free (rest);
- return;
- }
- prev = rest;
- rest = rest->next;
- }
-#if 0
- fprintf (stderr, "Saw UNexpected prop-%s on %s\n",
- (event->state == PropertyDelete ? "delete" : "change"),
- (char *) XSYMBOL (x_atom_to_symbol (dpyinfo,
- event->display, event->atom))
- ->name->data);
-#endif
-}
-
-
-
-#if 0 /* #### MULTIPLE doesn't work yet */
-
-static Lisp_Object
-fetch_multiple_target (event)
- XSelectionRequestEvent *event;
-{
- Display *display = event->display;
- Window window = event->requestor;
- Atom target = event->target;
- Atom selection_atom = event->selection;
- int result;
-
- return
- Fcons (QMULTIPLE,
- x_get_window_property_as_lisp_data (display, window, target,
- QMULTIPLE, selection_atom));
-}
-
-static Lisp_Object
-copy_multiple_data (obj)
- Lisp_Object obj;
-{
- Lisp_Object vec;
- int i;
- int size;
- if (CONSP (obj))
- return Fcons (XCONS (obj)->car, copy_multiple_data (XCONS (obj)->cdr));
-
- CHECK_VECTOR (obj, 0);
- vec = Fmake_vector (size = XVECTOR (obj)->size, Qnil);
- for (i = 0; i < size; i++)
- {
- Lisp_Object vec2 = XVECTOR (obj)->contents [i];
- CHECK_VECTOR (vec2, 0);
- if (XVECTOR (vec2)->size != 2)
- /* ??? Confusing error message */
- Fsignal (Qerror, Fcons (build_string ("vectors must be of length 2"),
- Fcons (vec2, Qnil)));
- XVECTOR (vec)->contents [i] = Fmake_vector (2, Qnil);
- XVECTOR (XVECTOR (vec)->contents [i])->contents [0]
- = XVECTOR (vec2)->contents [0];
- XVECTOR (XVECTOR (vec)->contents [i])->contents [1]
- = XVECTOR (vec2)->contents [1];
- }
- return vec;
-}
-
-#endif
-
-
-/* Variables for communication with x_handle_selection_notify. */
-static Atom reading_which_selection;
-static Lisp_Object reading_selection_reply;
-static Window reading_selection_window;
-
-/* Do protocol to read selection-data from the server.
- Converts this to Lisp data and returns it. */
-
-static Lisp_Object
-x_get_foreign_selection (selection_symbol, target_type)
- Lisp_Object selection_symbol, target_type;
-{
- Window requestor_window = FRAME_X_WINDOW (selected_frame);
- Display *display = FRAME_X_DISPLAY (selected_frame);
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (selected_frame);
- Time requestor_time = last_event_timestamp;
- Atom target_property = dpyinfo->Xatom_EMACS_TMP;
- Atom selection_atom = symbol_to_x_atom (dpyinfo, display, selection_symbol);
- Atom type_atom;
- int secs, usecs;
- int count = specpdl_ptr - specpdl;
- Lisp_Object frame;
-
- if (CONSP (target_type))
- type_atom = symbol_to_x_atom (dpyinfo, display, XCONS (target_type)->car);
- else
- type_atom = symbol_to_x_atom (dpyinfo, display, target_type);
-
- BLOCK_INPUT;
- x_catch_errors (display);
- XConvertSelection (display, selection_atom, type_atom, target_property,
- requestor_window, requestor_time);
- XFlush (display);
-
- /* Prepare to block until the reply has been read. */
- reading_selection_window = requestor_window;
- reading_which_selection = selection_atom;
- XCONS (reading_selection_reply)->car = Qnil;
-
- frame = some_frame_on_display (dpyinfo);
-
- /* If the display no longer has frames, we can't expect
- to get many more selection requests from it, so don't
- bother trying to queue them. */
- if (!NILP (frame))
- {
- x_start_queuing_selection_requests (display);
-
- record_unwind_protect (queue_selection_requests_unwind,
- frame);
- }
- UNBLOCK_INPUT;
-
- /* This allows quits. Also, don't wait forever. */
- secs = x_selection_timeout / 1000;
- usecs = (x_selection_timeout % 1000) * 1000;
- wait_reading_process_input (secs, usecs, reading_selection_reply, 0);
-
- BLOCK_INPUT;
- x_check_errors (display, "Cannot get selection: %s");
- x_uncatch_errors (display);
- unbind_to (count, Qnil);
- UNBLOCK_INPUT;
-
- if (NILP (XCONS (reading_selection_reply)->car))
- error ("Timed out waiting for reply from selection owner");
- if (EQ (XCONS (reading_selection_reply)->car, Qlambda))
- error ("No `%s' selection", XSYMBOL (selection_symbol)->name->data);
-
- /* Otherwise, the selection is waiting for us on the requested property. */
- return
- x_get_window_property_as_lisp_data (display, requestor_window,
- target_property, target_type,
- selection_atom);
-}
-
-/* Subroutines of x_get_window_property_as_lisp_data */
-
-/* Use free, not XFree, to free the data obtained with this function. */
-
-static void
-x_get_window_property (display, window, property, data_ret, bytes_ret,
- actual_type_ret, actual_format_ret, actual_size_ret,
- delete_p)
- Display *display;
- Window window;
- Atom property;
- unsigned char **data_ret;
- int *bytes_ret;
- Atom *actual_type_ret;
- int *actual_format_ret;
- unsigned long *actual_size_ret;
- int delete_p;
-{
- int total_size;
- unsigned long bytes_remaining;
- int offset = 0;
- unsigned char *tmp_data = 0;
- int result;
- int buffer_size = SELECTION_QUANTUM (display);
- if (buffer_size > MAX_SELECTION_QUANTUM) buffer_size = MAX_SELECTION_QUANTUM;
-
- BLOCK_INPUT;
- /* First probe the thing to find out how big it is. */
- result = XGetWindowProperty (display, window, property,
- 0L, 0L, False, AnyPropertyType,
- actual_type_ret, actual_format_ret,
- actual_size_ret,
- &bytes_remaining, &tmp_data);
- if (result != Success)
- {
- UNBLOCK_INPUT;
- *data_ret = 0;
- *bytes_ret = 0;
- return;
- }
- /* This was allocated by Xlib, so use XFree. */
- XFree ((char *) tmp_data);
-
- if (*actual_type_ret == None || *actual_format_ret == 0)
- {
- UNBLOCK_INPUT;
- return;
- }
-
- total_size = bytes_remaining + 1;
- *data_ret = (unsigned char *) xmalloc (total_size);
-
- /* Now read, until we've gotten it all. */
- while (bytes_remaining)
- {
-#if 0
- int last = bytes_remaining;
-#endif
- result
- = XGetWindowProperty (display, window, property,
- (long)offset/4, (long)buffer_size/4,
- False,
- AnyPropertyType,
- actual_type_ret, actual_format_ret,
- actual_size_ret, &bytes_remaining, &tmp_data);
-#if 0
- fprintf (stderr, "<< read %d\n", last-bytes_remaining);
-#endif
- /* If this doesn't return Success at this point, it means that
- some clod deleted the selection while we were in the midst of
- reading it. Deal with that, I guess....
- */
- if (result != Success) break;
- *actual_size_ret *= *actual_format_ret / 8;
- bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret);
- offset += *actual_size_ret;
- /* This was allocated by Xlib, so use XFree. */
- XFree ((char *) tmp_data);
- }
-
- XFlush (display);
- UNBLOCK_INPUT;
- *bytes_ret = offset;
-}
-
-/* Use free, not XFree, to free the data obtained with this function. */
-
-static void
-receive_incremental_selection (display, window, property, target_type,
- min_size_bytes, data_ret, size_bytes_ret,
- type_ret, format_ret, size_ret)
- Display *display;
- Window window;
- Atom property;
- Lisp_Object target_type; /* for error messages only */
- unsigned int min_size_bytes;
- unsigned char **data_ret;
- int *size_bytes_ret;
- Atom *type_ret;
- unsigned long *size_ret;
- int *format_ret;
-{
- int offset = 0;
- struct prop_location *wait_object;
- *size_bytes_ret = min_size_bytes;
- *data_ret = (unsigned char *) xmalloc (*size_bytes_ret);
-#if 0
- fprintf (stderr, "\nread INCR %d\n", min_size_bytes);
-#endif
-
- /* At this point, we have read an INCR property.
- Delete the property to ack it.
- (But first, prepare to receive the next event in this handshake.)
-
- Now, we must loop, waiting for the sending window to put a value on
- that property, then reading the property, then deleting it to ack.
- We are done when the sender places a property of length 0.
- */
- BLOCK_INPUT;
- XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask);
- XDeleteProperty (display, window, property);
- wait_object = expect_property_change (display, window, property,
- PropertyNewValue);
- XFlush (display);
- UNBLOCK_INPUT;
-
- while (1)
- {
- unsigned char *tmp_data;
- int tmp_size_bytes;
- wait_for_property_change (wait_object);
- /* expect it again immediately, because x_get_window_property may
- .. no it won't, I don't get it.
- .. Ok, I get it now, the Xt code that implements INCR is broken.
- */
- x_get_window_property (display, window, property,
- &tmp_data, &tmp_size_bytes,
- type_ret, format_ret, size_ret, 1);
-
- if (tmp_size_bytes == 0) /* we're done */
- {
-#if 0
- fprintf (stderr, " read INCR done\n");
-#endif
- if (! waiting_for_other_props_on_window (display, window))
- XSelectInput (display, window, STANDARD_EVENT_SET);
- unexpect_property_change (wait_object);
- /* Use free, not XFree, because x_get_window_property
- calls xmalloc itself. */
- if (tmp_data) free (tmp_data);
- break;
- }
-
- BLOCK_INPUT;
- XDeleteProperty (display, window, property);
- wait_object = expect_property_change (display, window, property,
- PropertyNewValue);
- XFlush (display);
- UNBLOCK_INPUT;
-
-#if 0
- fprintf (stderr, " read INCR %d\n", tmp_size_bytes);
-#endif
- if (*size_bytes_ret < offset + tmp_size_bytes)
- {
-#if 0
- fprintf (stderr, " read INCR realloc %d -> %d\n",
- *size_bytes_ret, offset + tmp_size_bytes);
-#endif
- *size_bytes_ret = offset + tmp_size_bytes;
- *data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret);
- }
- bcopy (tmp_data, (*data_ret) + offset, tmp_size_bytes);
- offset += tmp_size_bytes;
- /* Use free, not XFree, because x_get_window_property
- calls xmalloc itself. */
- free (tmp_data);
- }
-}
-
-/* Once a requested selection is "ready" (we got a SelectionNotify event),
- fetch value from property PROPERTY of X window WINDOW on display DISPLAY.
- TARGET_TYPE and SELECTION_ATOM are used in error message if this fails. */
-
-static Lisp_Object
-x_get_window_property_as_lisp_data (display, window, property, target_type,
- selection_atom)
- Display *display;
- Window window;
- Atom property;
- Lisp_Object target_type; /* for error messages only */
- Atom selection_atom; /* for error messages only */
-{
- Atom actual_type;
- int actual_format;
- unsigned long actual_size;
- unsigned char *data = 0;
- int bytes = 0;
- Lisp_Object val;
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
-
- x_get_window_property (display, window, property, &data, &bytes,
- &actual_type, &actual_format, &actual_size, 1);
- if (! data)
- {
- int there_is_a_selection_owner;
- BLOCK_INPUT;
- there_is_a_selection_owner
- = XGetSelectionOwner (display, selection_atom);
- UNBLOCK_INPUT;
- while (1) /* Note debugger can no longer return, so this is obsolete */
- Fsignal (Qerror,
- there_is_a_selection_owner ?
- Fcons (build_string ("selection owner couldn't convert"),
- actual_type
- ? Fcons (target_type,
- Fcons (x_atom_to_symbol (dpyinfo, display,
- actual_type),
- Qnil))
- : Fcons (target_type, Qnil))
- : Fcons (build_string ("no selection"),
- Fcons (x_atom_to_symbol (dpyinfo, display,
- selection_atom),
- Qnil)));
- }
-
- if (actual_type == dpyinfo->Xatom_INCR)
- {
- /* That wasn't really the data, just the beginning. */
-
- unsigned int min_size_bytes = * ((unsigned int *) data);
- BLOCK_INPUT;
- /* Use free, not XFree, because x_get_window_property
- calls xmalloc itself. */
- free ((char *) data);
- UNBLOCK_INPUT;
- receive_incremental_selection (display, window, property, target_type,
- min_size_bytes, &data, &bytes,
- &actual_type, &actual_format,
- &actual_size);
- }
-
- BLOCK_INPUT;
- XDeleteProperty (display, window, property);
- XFlush (display);
- UNBLOCK_INPUT;
-
- /* It's been read. Now convert it to a lisp object in some semi-rational
- manner. */
- val = selection_data_to_lisp_data (display, data, bytes,
- actual_type, actual_format);
-
- /* Use free, not XFree, because x_get_window_property
- calls xmalloc itself. */
- free ((char *) data);
- return val;
-}
-
-/* These functions convert from the selection data read from the server into
- something that we can use from Lisp, and vice versa.
-
- Type: Format: Size: Lisp Type:
- ----- ------- ----- -----------
- * 8 * String
- ATOM 32 1 Symbol
- ATOM 32 > 1 Vector of Symbols
- * 16 1 Integer
- * 16 > 1 Vector of Integers
- * 32 1 if <=16 bits: Integer
- if > 16 bits: Cons of top16, bot16
- * 32 > 1 Vector of the above
-
- When converting a Lisp number to C, it is assumed to be of format 16 if
- it is an integer, and of format 32 if it is a cons of two integers.
-
- When converting a vector of numbers from Lisp to C, it is assumed to be
- of format 16 if every element in the vector is an integer, and is assumed
- to be of format 32 if any element is a cons of two integers.
-
- When converting an object to C, it may be of the form (SYMBOL . <data>)
- where SYMBOL is what we should claim that the type is. Format and
- representation are as above. */
-
-
-
-static Lisp_Object
-selection_data_to_lisp_data (display, data, size, type, format)
- Display *display;
- unsigned char *data;
- Atom type;
- int size, format;
-{
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
-
- if (type == dpyinfo->Xatom_NULL)
- return QNULL;
-
- /* Convert any 8-bit data to a string, for compactness. */
- else if (format == 8)
- return make_string ((char *) data, size);
-
- /* Convert a single atom to a Lisp_Symbol. Convert a set of atoms to
- a vector of symbols.
- */
- else if (type == XA_ATOM)
- {
- int i;
- if (size == sizeof (Atom))
- return x_atom_to_symbol (dpyinfo, display, *((Atom *) data));
- else
- {
- Lisp_Object v = Fmake_vector (size / sizeof (Atom), 0);
- for (i = 0; i < size / sizeof (Atom); i++)
- Faset (v, i, x_atom_to_symbol (dpyinfo, display,
- ((Atom *) data) [i]));
- return v;
- }
- }
-
- /* Convert a single 16 or small 32 bit number to a Lisp_Int.
- If the number is > 16 bits, convert it to a cons of integers,
- 16 bits in each half.
- */
- else if (format == 32 && size == sizeof (long))
- return long_to_cons (((unsigned long *) data) [0]);
- else if (format == 16 && size == sizeof (short))
- return make_number ((int) (((unsigned short *) data) [0]));
-
- /* Convert any other kind of data to a vector of numbers, represented
- as above (as an integer, or a cons of two 16 bit integers.)
- */
- else if (format == 16)
- {
- int i;
- Lisp_Object v = Fmake_vector (size / 4, 0);
- for (i = 0; i < size / 4; i++)
- {
- int j = (int) ((unsigned short *) data) [i];
- Faset (v, i, make_number (j));
- }
- return v;
- }
- else
- {
- int i;
- Lisp_Object v = Fmake_vector (size / 4, 0);
- for (i = 0; i < size / 4; i++)
- {
- unsigned long j = ((unsigned long *) data) [i];
- Faset (v, i, long_to_cons (j));
- }
- return v;
- }
-}
-
-
-/* Use free, not XFree, to free the data obtained with this function. */
-
-static void
-lisp_data_to_selection_data (display, obj,
- data_ret, type_ret, size_ret,
- format_ret, nofree_ret)
- Display *display;
- Lisp_Object obj;
- unsigned char **data_ret;
- Atom *type_ret;
- unsigned int *size_ret;
- int *format_ret;
- int *nofree_ret;
-{
- Lisp_Object type = Qnil;
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
-
- *nofree_ret = 0;
-
- if (CONSP (obj) && SYMBOLP (XCONS (obj)->car))
- {
- type = XCONS (obj)->car;
- obj = XCONS (obj)->cdr;
- if (CONSP (obj) && NILP (XCONS (obj)->cdr))
- obj = XCONS (obj)->car;
- }
-
- if (EQ (obj, QNULL) || (EQ (type, QNULL)))
- { /* This is not the same as declining */
- *format_ret = 32;
- *size_ret = 0;
- *data_ret = 0;
- type = QNULL;
- }
- else if (STRINGP (obj))
- {
- *format_ret = 8;
- *size_ret = XSTRING (obj)->size;
- *data_ret = XSTRING (obj)->data;
- *nofree_ret = 1;
- if (NILP (type)) type = QSTRING;
- }
- else if (SYMBOLP (obj))
- {
- *format_ret = 32;
- *size_ret = 1;
- *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1);
- (*data_ret) [sizeof (Atom)] = 0;
- (*(Atom **) data_ret) [0] = symbol_to_x_atom (dpyinfo, display, obj);
- if (NILP (type)) type = QATOM;
- }
- else if (INTEGERP (obj)
- && XINT (obj) < 0xFFFF
- && XINT (obj) > -0xFFFF)
- {
- *format_ret = 16;
- *size_ret = 1;
- *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1);
- (*data_ret) [sizeof (short)] = 0;
- (*(short **) data_ret) [0] = (short) XINT (obj);
- if (NILP (type)) type = QINTEGER;
- }
- else if (INTEGERP (obj)
- || (CONSP (obj) && INTEGERP (XCONS (obj)->car)
- && (INTEGERP (XCONS (obj)->cdr)
- || (CONSP (XCONS (obj)->cdr)
- && INTEGERP (XCONS (XCONS (obj)->cdr)->car)))))
- {
- *format_ret = 32;
- *size_ret = 1;
- *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
- (*data_ret) [sizeof (long)] = 0;
- (*(unsigned long **) data_ret) [0] = cons_to_long (obj);
- if (NILP (type)) type = QINTEGER;
- }
- else if (VECTORP (obj))
- {
- /* Lisp_Vectors may represent a set of ATOMs;
- a set of 16 or 32 bit INTEGERs;
- or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...]
- */
- int i;
-
- if (SYMBOLP (XVECTOR (obj)->contents [0]))
- /* This vector is an ATOM set */
- {
- if (NILP (type)) type = QATOM;
- *size_ret = XVECTOR (obj)->size;
- *format_ret = 32;
- *data_ret = (unsigned char *) xmalloc ((*size_ret) * sizeof (Atom));
- for (i = 0; i < *size_ret; i++)
- if (SYMBOLP (XVECTOR (obj)->contents [i]))
- (*(Atom **) data_ret) [i]
- = symbol_to_x_atom (dpyinfo, display, XVECTOR (obj)->contents [i]);
- else
- Fsignal (Qerror, /* Qselection_error */
- Fcons (build_string
- ("all elements of selection vector must have same type"),
- Fcons (obj, Qnil)));
- }
-#if 0 /* #### MULTIPLE doesn't work yet */
- else if (VECTORP (XVECTOR (obj)->contents [0]))
- /* This vector is an ATOM_PAIR set */
- {
- if (NILP (type)) type = QATOM_PAIR;
- *size_ret = XVECTOR (obj)->size;
- *format_ret = 32;
- *data_ret = (unsigned char *)
- xmalloc ((*size_ret) * sizeof (Atom) * 2);
- for (i = 0; i < *size_ret; i++)
- if (VECTORP (XVECTOR (obj)->contents [i]))
- {
- Lisp_Object pair = XVECTOR (obj)->contents [i];
- if (XVECTOR (pair)->size != 2)
- Fsignal (Qerror,
- Fcons (build_string
- ("elements of the vector must be vectors of exactly two elements"),
- Fcons (pair, Qnil)));
-
- (*(Atom **) data_ret) [i * 2]
- = symbol_to_x_atom (dpyinfo, display,
- XVECTOR (pair)->contents [0]);
- (*(Atom **) data_ret) [(i * 2) + 1]
- = symbol_to_x_atom (dpyinfo, display,
- XVECTOR (pair)->contents [1]);
- }
- else
- Fsignal (Qerror,
- Fcons (build_string
- ("all elements of the vector must be of the same type"),
- Fcons (obj, Qnil)));
-
- }
-#endif
- else
- /* This vector is an INTEGER set, or something like it */
- {
- *size_ret = XVECTOR (obj)->size;
- if (NILP (type)) type = QINTEGER;
- *format_ret = 16;
- for (i = 0; i < *size_ret; i++)
- if (CONSP (XVECTOR (obj)->contents [i]))
- *format_ret = 32;
- else if (!INTEGERP (XVECTOR (obj)->contents [i]))
- Fsignal (Qerror, /* Qselection_error */
- Fcons (build_string
- ("elements of selection vector must be integers or conses of integers"),
- Fcons (obj, Qnil)));
-
- *data_ret = (unsigned char *) xmalloc (*size_ret * (*format_ret/8));
- for (i = 0; i < *size_ret; i++)
- if (*format_ret == 32)
- (*((unsigned long **) data_ret)) [i]
- = cons_to_long (XVECTOR (obj)->contents [i]);
- else
- (*((unsigned short **) data_ret)) [i]
- = (unsigned short) cons_to_long (XVECTOR (obj)->contents [i]);
- }
- }
- else
- Fsignal (Qerror, /* Qselection_error */
- Fcons (build_string ("unrecognised selection data"),
- Fcons (obj, Qnil)));
-
- *type_ret = symbol_to_x_atom (dpyinfo, display, type);
-}
-
-static Lisp_Object
-clean_local_selection_data (obj)
- Lisp_Object obj;
-{
- if (CONSP (obj)
- && INTEGERP (XCONS (obj)->car)
- && CONSP (XCONS (obj)->cdr)
- && INTEGERP (XCONS (XCONS (obj)->cdr)->car)
- && NILP (XCONS (XCONS (obj)->cdr)->cdr))
- obj = Fcons (XCONS (obj)->car, XCONS (obj)->cdr);
-
- if (CONSP (obj)
- && INTEGERP (XCONS (obj)->car)
- && INTEGERP (XCONS (obj)->cdr))
- {
- if (XINT (XCONS (obj)->car) == 0)
- return XCONS (obj)->cdr;
- if (XINT (XCONS (obj)->car) == -1)
- return make_number (- XINT (XCONS (obj)->cdr));
- }
- if (VECTORP (obj))
- {
- int i;
- int size = XVECTOR (obj)->size;
- Lisp_Object copy;
- if (size == 1)
- return clean_local_selection_data (XVECTOR (obj)->contents [0]);
- copy = Fmake_vector (size, Qnil);
- for (i = 0; i < size; i++)
- XVECTOR (copy)->contents [i]
- = clean_local_selection_data (XVECTOR (obj)->contents [i]);
- return copy;
- }
- return obj;
-}
-
-/* Called from XTread_socket to handle SelectionNotify events.
- If it's the selection we are waiting for, stop waiting
- by setting the car of reading_selection_reply to non-nil.
- We store t there if the reply is successful, lambda if not. */
-
-void
-x_handle_selection_notify (event)
- XSelectionEvent *event;
-{
- if (event->requestor != reading_selection_window)
- return;
- if (event->selection != reading_which_selection)
- return;
-
- XCONS (reading_selection_reply)->car
- = (event->property != 0 ? Qt : Qlambda);
-}
-
-
-DEFUN ("x-own-selection-internal", Fx_own_selection_internal,
- Sx_own_selection_internal, 2, 2, 0,
- "Assert an X selection of the given TYPE with the given VALUE.\n\
-TYPE is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
-\(Those are literal upper-case symbol names, since that's what X expects.)\n\
-VALUE is typically a string, or a cons of two markers, but may be\n\
-anything that the functions on `selection-converter-alist' know about.")
- (selection_name, selection_value)
- Lisp_Object selection_name, selection_value;
-{
- check_x ();
- CHECK_SYMBOL (selection_name, 0);
- if (NILP (selection_value)) error ("selection-value may not be nil");
- x_own_selection (selection_name, selection_value);
- return selection_value;
-}
-
-
-/* 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-internal", Fx_get_selection_internal,
- Sx_get_selection_internal, 2, 2, 0,
- "Return text selected from some X window.\n\
-SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
-\(Those are literal upper-case symbol names, since that's what X expects.)\n\
-TYPE is the type of data desired, typically `STRING'.")
- (selection_symbol, target_type)
- Lisp_Object selection_symbol, target_type;
-{
- Lisp_Object val = Qnil;
- struct gcpro gcpro1, gcpro2;
- GCPRO2 (target_type, val); /* we store newly consed data into these */
- check_x ();
- CHECK_SYMBOL (selection_symbol, 0);
-
-#if 0 /* #### MULTIPLE doesn't work yet */
- if (CONSP (target_type)
- && XCONS (target_type)->car == QMULTIPLE)
- {
- CHECK_VECTOR (XCONS (target_type)->cdr, 0);
- /* So we don't destructively modify this... */
- target_type = copy_multiple_data (target_type);
- }
- else
-#endif
- CHECK_SYMBOL (target_type, 0);
-
- val = x_get_local_selection (selection_symbol, target_type);
-
- if (NILP (val))
- {
- val = x_get_foreign_selection (selection_symbol, target_type);
- goto DONE;
- }
-
- if (CONSP (val)
- && SYMBOLP (XCONS (val)->car))
- {
- val = XCONS (val)->cdr;
- if (CONSP (val) && NILP (XCONS (val)->cdr))
- val = XCONS (val)->car;
- }
- val = clean_local_selection_data (val);
- DONE:
- UNGCPRO;
- return val;
-}
-
-DEFUN ("x-disown-selection-internal", Fx_disown_selection_internal,
- Sx_disown_selection_internal, 1, 2, 0,
- "If we own the selection SELECTION, disown it.\n\
-Disowning it means there is no such selection.")
- (selection, time)
- Lisp_Object selection;
- Lisp_Object time;
-{
- Time timestamp;
- Atom selection_atom;
- XSelectionClearEvent event;
- Display *display;
- struct x_display_info *dpyinfo;
-
- check_x ();
- display = FRAME_X_DISPLAY (selected_frame);
- dpyinfo = FRAME_X_DISPLAY_INFO (selected_frame);
- CHECK_SYMBOL (selection, 0);
- if (NILP (time))
- timestamp = last_event_timestamp;
- else
- timestamp = cons_to_long (time);
-
- if (NILP (assq_no_quit (selection, Vselection_alist)))
- return Qnil; /* Don't disown the selection when we're not the owner. */
-
- selection_atom = symbol_to_x_atom (dpyinfo, display, selection);
-
- BLOCK_INPUT;
- XSetSelectionOwner (display, selection_atom, None, timestamp);
- UNBLOCK_INPUT;
-
- /* It doesn't seem to be guaranteed that a SelectionClear event will be
- generated for a window which owns the selection when that window sets
- the selection owner to None. The NCD server does, the MIT Sun4 server
- doesn't. So we synthesize one; this means we might get two, but
- that's ok, because the second one won't have any effect. */
- SELECTION_EVENT_DISPLAY (&event) = display;
- SELECTION_EVENT_SELECTION (&event) = selection_atom;
- SELECTION_EVENT_TIME (&event) = timestamp;
- x_handle_selection_clear (&event);
-
- return Qt;
-}
-
-/* Get rid of all the selections in buffer BUFFER.
- This is used when we kill a buffer. */
-
-void
-x_disown_buffer_selections (buffer)
- Lisp_Object buffer;
-{
- Lisp_Object tail;
- struct buffer *buf = XBUFFER (buffer);
-
- for (tail = Vselection_alist; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- Lisp_Object elt, value;
- elt = XCONS (tail)->car;
- value = XCONS (elt)->cdr;
- if (CONSP (value) && MARKERP (XCONS (value)->car)
- && XMARKER (XCONS (value)->car)->buffer == buf)
- Fx_disown_selection_internal (XCONS (elt)->car, Qnil);
- }
-}
-
-DEFUN ("x-selection-owner-p", Fx_selection_owner_p, Sx_selection_owner_p,
- 0, 1, 0,
- "Whether the current Emacs process owns the given X Selection.\n\
-The arg should be the name of the selection in question, typically one of\n\
-the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
-\(Those are literal upper-case symbol names, since that's what X expects.)\n\
-For convenience, the symbol nil is the same as `PRIMARY',\n\
-and t is the same as `SECONDARY'.)")
- (selection)
- Lisp_Object selection;
-{
- check_x ();
- CHECK_SYMBOL (selection, 0);
- if (EQ (selection, Qnil)) selection = QPRIMARY;
- if (EQ (selection, Qt)) selection = QSECONDARY;
-
- if (NILP (Fassq (selection, Vselection_alist)))
- return Qnil;
- return Qt;
-}
-
-DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
- 0, 1, 0,
- "Whether there is an owner for the given X Selection.\n\
-The arg should be the name of the selection in question, typically one of\n\
-the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
-\(Those are literal upper-case symbol names, since that's what X expects.)\n\
-For convenience, the symbol nil is the same as `PRIMARY',\n\
-and t is the same as `SECONDARY'.)")
- (selection)
- Lisp_Object selection;
-{
- Window owner;
- Atom atom;
- Display *dpy;
-
- /* It should be safe to call this before we have an X frame. */
- if (! FRAME_X_P (selected_frame))
- return Qnil;
-
- dpy = FRAME_X_DISPLAY (selected_frame);
- CHECK_SYMBOL (selection, 0);
- if (!NILP (Fx_selection_owner_p (selection)))
- return Qt;
- if (EQ (selection, Qnil)) selection = QPRIMARY;
- if (EQ (selection, Qt)) selection = QSECONDARY;
- atom = symbol_to_x_atom (FRAME_X_DISPLAY_INFO (selected_frame),
- dpy, selection);
- if (atom == 0)
- return Qnil;
- BLOCK_INPUT;
- owner = XGetSelectionOwner (dpy, atom);
- UNBLOCK_INPUT;
- return (owner ? Qt : Qnil);
-}
-
-
-#ifdef CUT_BUFFER_SUPPORT
-
-/* Ensure that all 8 cut buffers exist. ICCCM says we gotta... */
-static void
-initialize_cut_buffers (display, window)
- Display *display;
- Window window;
-{
- unsigned char *data = (unsigned char *) "";
- BLOCK_INPUT;
-#define FROB(atom) XChangeProperty (display, window, atom, XA_STRING, 8, \
- PropModeAppend, data, 0)
- FROB (XA_CUT_BUFFER0);
- FROB (XA_CUT_BUFFER1);
- FROB (XA_CUT_BUFFER2);
- FROB (XA_CUT_BUFFER3);
- FROB (XA_CUT_BUFFER4);
- FROB (XA_CUT_BUFFER5);
- FROB (XA_CUT_BUFFER6);
- FROB (XA_CUT_BUFFER7);
-#undef FROB
- UNBLOCK_INPUT;
-}
-
-
-#define CHECK_CUT_BUFFER(symbol,n) \
- { CHECK_SYMBOL ((symbol), (n)); \
- if (!EQ((symbol), QCUT_BUFFER0) && !EQ((symbol), QCUT_BUFFER1) \
- && !EQ((symbol), QCUT_BUFFER2) && !EQ((symbol), QCUT_BUFFER3) \
- && !EQ((symbol), QCUT_BUFFER4) && !EQ((symbol), QCUT_BUFFER5) \
- && !EQ((symbol), QCUT_BUFFER6) && !EQ((symbol), QCUT_BUFFER7)) \
- Fsignal (Qerror, \
- Fcons (build_string ("doesn't name a cut buffer"), \
- Fcons ((symbol), Qnil))); \
- }
-
-DEFUN ("x-get-cut-buffer-internal", Fx_get_cut_buffer_internal,
- Sx_get_cut_buffer_internal, 1, 1, 0,
- "Returns the value of the named cut buffer (typically CUT_BUFFER0).")
- (buffer)
- Lisp_Object buffer;
-{
- Window window;
- Atom buffer_atom;
- unsigned char *data;
- int bytes;
- Atom type;
- int format;
- unsigned long size;
- Lisp_Object ret;
- Display *display;
- struct x_display_info *dpyinfo;
-
- check_x ();
- display = FRAME_X_DISPLAY (selected_frame);
- dpyinfo = FRAME_X_DISPLAY_INFO (selected_frame);
- window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
- CHECK_CUT_BUFFER (buffer, 0);
- buffer_atom = symbol_to_x_atom (dpyinfo, display, buffer);
-
- x_get_window_property (display, window, buffer_atom, &data, &bytes,
- &type, &format, &size, 0);
- if (!data) return Qnil;
-
- if (format != 8 || type != XA_STRING)
- Fsignal (Qerror,
- Fcons (build_string ("cut buffer doesn't contain 8-bit data"),
- Fcons (x_atom_to_symbol (dpyinfo, display, type),
- Fcons (make_number (format), Qnil))));
-
- ret = (bytes ? make_string ((char *) data, bytes) : Qnil);
- /* Use free, not XFree, because x_get_window_property
- calls xmalloc itself. */
- free (data);
- return ret;
-}
-
-
-DEFUN ("x-store-cut-buffer-internal", Fx_store_cut_buffer_internal,
- Sx_store_cut_buffer_internal, 2, 2, 0,
- "Sets the value of the named cut buffer (typically CUT_BUFFER0).")
- (buffer, string)
- Lisp_Object buffer, string;
-{
- Window window;
- Atom buffer_atom;
- unsigned char *data;
- int bytes;
- int bytes_remaining;
- int max_bytes;
- Display *display;
-
- check_x ();
- display = FRAME_X_DISPLAY (selected_frame);
- window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
-
- max_bytes = SELECTION_QUANTUM (display);
- if (max_bytes > MAX_SELECTION_QUANTUM)
- max_bytes = MAX_SELECTION_QUANTUM;
-
- CHECK_CUT_BUFFER (buffer, 0);
- CHECK_STRING (string, 0);
- buffer_atom = symbol_to_x_atom (FRAME_X_DISPLAY_INFO (selected_frame),
- display, buffer);
- data = (unsigned char *) XSTRING (string)->data;
- bytes = XSTRING (string)->size;
- bytes_remaining = bytes;
-
- if (! FRAME_X_DISPLAY_INFO (selected_frame)->cut_buffers_initialized)
- {
- initialize_cut_buffers (display, window);
- FRAME_X_DISPLAY_INFO (selected_frame)->cut_buffers_initialized = 1;
- }
-
- BLOCK_INPUT;
-
- /* Don't mess up with an empty value. */
- if (!bytes_remaining)
- XChangeProperty (display, window, buffer_atom, XA_STRING, 8,
- PropModeReplace, data, 0);
-
- while (bytes_remaining)
- {
- int chunk = (bytes_remaining < max_bytes
- ? bytes_remaining : max_bytes);
- XChangeProperty (display, window, buffer_atom, XA_STRING, 8,
- (bytes_remaining == bytes
- ? PropModeReplace
- : PropModeAppend),
- data, chunk);
- data += chunk;
- bytes_remaining -= chunk;
- }
- UNBLOCK_INPUT;
- return string;
-}
-
-
-DEFUN ("x-rotate-cut-buffers-internal", Fx_rotate_cut_buffers_internal,
- Sx_rotate_cut_buffers_internal, 1, 1, 0,
- "Rotate the values of the cut buffers by the given number of steps;\n\
-positive means move values forward, negative means backward.")
- (n)
- Lisp_Object n;
-{
- Window window;
- Atom props[8];
- Display *display;
-
- check_x ();
- display = FRAME_X_DISPLAY (selected_frame);
- window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
- CHECK_NUMBER (n, 0);
- if (XINT (n) == 0)
- return n;
- if (! FRAME_X_DISPLAY_INFO (selected_frame)->cut_buffers_initialized)
- {
- initialize_cut_buffers (display, window);
- FRAME_X_DISPLAY_INFO (selected_frame)->cut_buffers_initialized = 1;
- }
-
- props[0] = XA_CUT_BUFFER0;
- props[1] = XA_CUT_BUFFER1;
- props[2] = XA_CUT_BUFFER2;
- props[3] = XA_CUT_BUFFER3;
- props[4] = XA_CUT_BUFFER4;
- props[5] = XA_CUT_BUFFER5;
- props[6] = XA_CUT_BUFFER6;
- props[7] = XA_CUT_BUFFER7;
- BLOCK_INPUT;
- XRotateWindowProperties (display, window, props, 8, XINT (n));
- UNBLOCK_INPUT;
- return n;
-}
-
-#endif
-
-void
-syms_of_xselect ()
-{
- defsubr (&Sx_get_selection_internal);
- defsubr (&Sx_own_selection_internal);
- defsubr (&Sx_disown_selection_internal);
- defsubr (&Sx_selection_owner_p);
- defsubr (&Sx_selection_exists_p);
-
-#ifdef CUT_BUFFER_SUPPORT
- defsubr (&Sx_get_cut_buffer_internal);
- defsubr (&Sx_store_cut_buffer_internal);
- defsubr (&Sx_rotate_cut_buffers_internal);
-#endif
-
- reading_selection_reply = Fcons (Qnil, Qnil);
- staticpro (&reading_selection_reply);
- reading_selection_window = 0;
- reading_which_selection = 0;
-
- property_change_wait_list = 0;
- prop_location_identifier = 0;
- property_change_reply = Fcons (Qnil, Qnil);
- staticpro (&property_change_reply);
-
- Vselection_alist = Qnil;
- staticpro (&Vselection_alist);
-
- DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist,
- "An alist associating X Windows selection-types with functions.\n\
-These functions are called to convert the selection, with three args:\n\
-the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
-a desired type to which the selection should be converted;\n\
-and the local selection value (whatever was given to `x-own-selection').\n\
-\n\
-The function should return the value to send to the X server\n\
-\(typically a string). A return value of nil\n\
-means that the conversion could not be done.\n\
-A return value which is the symbol `NULL'\n\
-means that a side-effect was executed,\n\
-and there is no meaningful selection value.");
- Vselection_converter_alist = Qnil;
-
- DEFVAR_LISP ("x-lost-selection-hooks", &Vx_lost_selection_hooks,
- "A list of functions to be called when Emacs loses an X selection.\n\
-\(This happens when some other X client makes its own selection\n\
-or when a Lisp program explicitly clears the selection.)\n\
-The functions are called with one argument, the selection type\n\
-\(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD').");
- Vx_lost_selection_hooks = Qnil;
-
- DEFVAR_LISP ("x-sent-selection-hooks", &Vx_sent_selection_hooks,
- "A list of functions to be called when Emacs answers a selection request.\n\
-The functions are called with four arguments:\n\
- - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
- - the selection-type which Emacs was asked to convert the\n\
- selection into before sending (for example, `STRING' or `LENGTH');\n\
- - a flag indicating success or failure for responding to the request.\n\
-We might have failed (and declined the request) for any number of reasons,\n\
-including being asked for a selection that we no longer own, or being asked\n\
-to convert into a type that we don't know about or that is inappropriate.\n\
-This hook doesn't let you change the behavior of Emacs's selection replies,\n\
-it merely informs you that they have happened.");
- Vx_sent_selection_hooks = Qnil;
-
- DEFVAR_INT ("x-selection-timeout", &x_selection_timeout,
- "Number of milliseconds to wait for a selection reply.\n\
-If the selection owner doesn't reply in this time, we give up.\n\
-A value of 0 means wait as long as necessary. This is initialized from the\n\
-\"*selectionTimeout\" resource.");
- x_selection_timeout = 0;
-
- QPRIMARY = intern ("PRIMARY"); staticpro (&QPRIMARY);
- QSECONDARY = intern ("SECONDARY"); staticpro (&QSECONDARY);
- QSTRING = intern ("STRING"); staticpro (&QSTRING);
- QINTEGER = intern ("INTEGER"); staticpro (&QINTEGER);
- QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
- QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP);
- QTEXT = intern ("TEXT"); staticpro (&QTEXT);
- QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP);
- QDELETE = intern ("DELETE"); staticpro (&QDELETE);
- QMULTIPLE = intern ("MULTIPLE"); staticpro (&QMULTIPLE);
- QINCR = intern ("INCR"); staticpro (&QINCR);
- QEMACS_TMP = intern ("_EMACS_TMP_"); staticpro (&QEMACS_TMP);
- QTARGETS = intern ("TARGETS"); staticpro (&QTARGETS);
- QATOM = intern ("ATOM"); staticpro (&QATOM);
- QATOM_PAIR = intern ("ATOM_PAIR"); staticpro (&QATOM_PAIR);
- QNULL = intern ("NULL"); staticpro (&QNULL);
-
-#ifdef CUT_BUFFER_SUPPORT
- QCUT_BUFFER0 = intern ("CUT_BUFFER0"); staticpro (&QCUT_BUFFER0);
- QCUT_BUFFER1 = intern ("CUT_BUFFER1"); staticpro (&QCUT_BUFFER1);
- QCUT_BUFFER2 = intern ("CUT_BUFFER2"); staticpro (&QCUT_BUFFER2);
- QCUT_BUFFER3 = intern ("CUT_BUFFER3"); staticpro (&QCUT_BUFFER3);
- QCUT_BUFFER4 = intern ("CUT_BUFFER4"); staticpro (&QCUT_BUFFER4);
- QCUT_BUFFER5 = intern ("CUT_BUFFER5"); staticpro (&QCUT_BUFFER5);
- QCUT_BUFFER6 = intern ("CUT_BUFFER6"); staticpro (&QCUT_BUFFER6);
- QCUT_BUFFER7 = intern ("CUT_BUFFER7"); staticpro (&QCUT_BUFFER7);
-#endif
-
-}
diff --git a/src/xterm.c b/src/xterm.c
deleted file mode 100644
index e7b96597207..00000000000
--- a/src/xterm.c
+++ /dev/null
@@ -1,6354 +0,0 @@
-/* X Communication module for terminals which understand the X protocol.
- Copyright (C) 1989, 93, 94, 95, 1996 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Xt features made by Fred Pierresteguy. */
-
-/* On 4.3 these lose if they come after xterm.h. */
-/* On HP-UX 8.0 signal.h loses if it comes after config.h. */
-/* Putting these at the beginning seems to be standard for other .c files. */
-#include <signal.h>
-
-#include <config.h>
-
-#include <stdio.h>
-
-/* Need syssignal.h for various externs and definitions that may be required
- by some configurations for calls to signal later in this source file. */
-#include "syssignal.h"
-
-#ifdef HAVE_X_WINDOWS
-
-#include "lisp.h"
-#include "blockinput.h"
-
-/* This may include sys/types.h, and that somehow loses
- if this is not done before the other system files. */
-#include "xterm.h"
-#include <X11/cursorfont.h>
-
-#ifndef USG
-/* Load sys/types.h if not already loaded.
- In some systems loading it twice is suicidal. */
-#ifndef makedev
-#include <sys/types.h>
-#endif /* makedev */
-#endif /* USG */
-
-#ifdef BSD_SYSTEM
-#include <sys/ioctl.h>
-#endif /* ! defined (BSD_SYSTEM) */
-
-#include "systty.h"
-#include "systime.h"
-
-#ifndef INCLUDED_FCNTL
-#include <fcntl.h>
-#endif
-#include <ctype.h>
-#include <errno.h>
-#include <setjmp.h>
-#include <sys/stat.h>
-/* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
-/* #include <sys/param.h> */
-
-#include "frame.h"
-#include "dispextern.h"
-#include "termhooks.h"
-#include "termopts.h"
-#include "termchar.h"
-#if 0
-#include "sink.h"
-#include "sinkmask.h"
-#endif /* ! 0 */
-#include "gnu.h"
-#include "disptab.h"
-#include "buffer.h"
-#include "window.h"
-#include "keyboard.h"
-#include "intervals.h"
-
-#ifdef USE_X_TOOLKIT
-#include <X11/Shell.h>
-#endif
-
-#ifdef USE_X_TOOLKIT
-extern void free_frame_menubar ();
-extern FRAME_PTR x_menubar_window_to_frame ();
-#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
-#define HACK_EDITRES
-extern void _XEditResCheckMessages ();
-#endif /* not NO_EDITRES */
-#endif /* USE_X_TOOLKIT */
-
-#ifndef USE_X_TOOLKIT
-#define x_any_window_to_frame x_window_to_frame
-#define x_top_window_to_frame x_window_to_frame
-#endif
-
-#ifdef USE_X_TOOLKIT
-#include "widget.h"
-#ifndef XtNinitialState
-#define XtNinitialState "initialState"
-#endif
-#endif
-
-#ifdef HAVE_SETLOCALE
-/* So we can do setlocale. */
-#include <locale.h>
-#endif
-
-#ifdef SOLARIS2
-/* memmove will be defined as a macro in Xfuncs.h unless
- <string.h> is included beforehand. The declaration for memmove in
- <string.h> will cause a syntax error when Xfuncs.h later includes it. */
-#include <string.h>
-#endif
-
-#ifndef min
-#define min(a,b) ((a)<(b) ? (a) : (b))
-#endif
-#ifndef max
-#define max(a,b) ((a)>(b) ? (a) : (b))
-#endif
-
-/* This is a chain of structures for all the X displays currently in use. */
-struct x_display_info *x_display_list;
-
-/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
- one for each element of x_display_list and in the same order.
- NAME is the name of the frame.
- FONT-LIST-CACHE records previous values returned by x-list-fonts. */
-Lisp_Object x_display_name_list;
-
-/* Frame being updated by update_frame. This is declared in term.c.
- This is set by update_begin and looked at by all the
- XT functions. It is zero while not inside an update.
- In that case, the XT functions assume that `selected_frame'
- is the frame to apply to. */
-extern struct frame *updating_frame;
-
-extern waiting_for_input;
-
-/* This is a frame waiting to be autoraised, within XTread_socket. */
-struct frame *pending_autoraise_frame;
-
-#ifdef USE_X_TOOLKIT
-/* The application context for Xt use. */
-XtAppContext Xt_app_con;
-
-static String Xt_default_resources[] =
-{
- 0
-};
-#endif
-
-/* During an update, maximum vpos for ins/del line operations to affect. */
-
-static int flexlines;
-
-/* During an update, nonzero if chars output now should be highlighted. */
-
-static int highlight;
-
-/* Nominal cursor position -- where to draw output.
- During an update, these are different from the cursor-box position. */
-
-static int curs_x;
-static int curs_y;
-
-/* Mouse movement.
-
- Formerly, we used PointerMotionHintMask (in STANDARD_EVENT_MASK)
- so that we would have to call XQueryPointer after each MotionNotify
- event to ask for another such event. However, this made mouse tracking
- slow, and there was a bug that made it eventually stop.
-
- Simply asking for MotionNotify all the time seems to work better.
-
- In order to avoid asking for motion events and then throwing most
- of them away or busy-polling the server for mouse positions, we ask
- the server for pointer motion hints. This means that we get only
- one event per group of mouse movements. "Groups" are delimited by
- other kinds of events (focus changes and button clicks, for
- example), or by XQueryPointer calls; when one of these happens, we
- get another MotionNotify event the next time the mouse moves. This
- is at least as efficient as getting motion events when mouse
- tracking is on, and I suspect only negligibly worse when tracking
- is off. */
-
-/* Where the mouse was last time we reported a mouse event. */
-static FRAME_PTR last_mouse_frame;
-static XRectangle last_mouse_glyph;
-
-static Lisp_Object last_mouse_press_frame;
-
-/* The scroll bar in which the last X motion event occurred.
-
- If the last X motion event occurred in a scroll bar, we set this
- so XTmouse_position can know whether to report a scroll bar motion or
- an ordinary motion.
-
- If the last X motion event didn't occur in a scroll bar, we set this
- to Qnil, to tell XTmouse_position to return an ordinary motion event. */
-static Lisp_Object last_mouse_scroll_bar;
-
-/* This is a hack. We would really prefer that XTmouse_position would
- return the time associated with the position it returns, but there
- doesn't seem to be any way to wrest the timestamp from the server
- along with the position query. So, we just keep track of the time
- of the last movement we received, and return that in hopes that
- it's somewhat accurate. */
-static Time last_mouse_movement_time;
-
-/* Incremented by XTread_socket whenever it really tries to read events. */
-#ifdef __STDC__
-static int volatile input_signal_count;
-#else
-static int input_signal_count;
-#endif
-
-/* Used locally within XTread_socket. */
-static int x_noop_count;
-
-/* Initial values of argv and argc. */
-extern char **initial_argv;
-extern int initial_argc;
-
-extern Lisp_Object Vcommand_line_args, Vsystem_name;
-
-/* Tells if a window manager is present or not. */
-
-extern Lisp_Object Vx_no_window_manager;
-
-extern Lisp_Object Qface, Qmouse_face;
-
-extern int errno;
-
-/* A mask of extra modifier bits to put into every keyboard char. */
-extern int extra_keyboard_modifiers;
-
-static Lisp_Object Qvendor_specific_keysyms;
-
-extern XrmDatabase x_load_resources ();
-
-extern Lisp_Object x_icon_type ();
-
-void x_delete_display ();
-
-static void redraw_previous_char ();
-static void redraw_following_char ();
-static unsigned int x_x_to_emacs_modifiers ();
-
-static int fast_find_position ();
-static void note_mouse_highlight ();
-static void clear_mouse_face ();
-static void show_mouse_face ();
-static void do_line_dance ();
-
-static int XTcursor_to ();
-static int XTclear_end_of_line ();
-static int x_io_error_quitter ();
-void x_catch_errors ();
-void x_uncatch_errors ();
-
-#if 0
-/* This is a function useful for recording debugging information
- about the sequence of occurrences in this file. */
-
-struct record
-{
- char *locus;
- int type;
-};
-
-struct record event_record[100];
-
-int event_record_index;
-
-record_event (locus, type)
- char *locus;
- int type;
-{
- if (event_record_index == sizeof (event_record) / sizeof (struct record))
- event_record_index = 0;
-
- event_record[event_record_index].locus = locus;
- event_record[event_record_index].type = type;
- event_record_index++;
-}
-
-#endif /* 0 */
-
-/* Return the struct x_display_info corresponding to DPY. */
-
-struct x_display_info *
-x_display_info_for_display (dpy)
- Display *dpy;
-{
- struct x_display_info *dpyinfo;
-
- for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
- if (dpyinfo->display == dpy)
- return dpyinfo;
-
- return 0;
-}
-
-/* Starting and ending updates.
-
- These hooks are called by update_frame at the beginning and end
- of a frame update. We record in `updating_frame' the identity
- of the frame being updated, so that the XT... functions do not
- need to take a frame as argument. Most of the XT... functions
- should never be called except during an update, the only exceptions
- being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
-
-static
-XTupdate_begin (f)
- struct frame *f;
-{
- int mask;
-
- if (f == 0)
- abort ();
-
- flexlines = f->height;
- highlight = 0;
-
- BLOCK_INPUT;
-
- curs_x = FRAME_CURSOR_X (f);
- curs_y = FRAME_CURSOR_Y (f);
-
- if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
- {
- /* Don't do highlighting for mouse motion during the update. */
- FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 1;
-
- /* If the frame needs to be redrawn,
- simply forget about any prior mouse highlighting. */
- if (FRAME_GARBAGED_P (f))
- FRAME_X_DISPLAY_INFO (f)->mouse_face_window = Qnil;
-
- if (!NILP (FRAME_X_DISPLAY_INFO (f)->mouse_face_window))
- {
- int firstline, lastline, i;
- struct window *w = XWINDOW (FRAME_X_DISPLAY_INFO (f)->mouse_face_window);
-
- /* Find the first, and the last+1, lines affected by redisplay. */
- for (firstline = 0; firstline < f->height; firstline++)
- if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
- break;
-
- lastline = f->height;
- for (i = f->height - 1; i >= 0; i--)
- {
- if (FRAME_DESIRED_GLYPHS (f)->enable[i])
- break;
- else
- lastline = i;
- }
-
- /* Can we tell that this update does not affect the window
- where the mouse highlight is? If so, no need to turn off.
- Likewise, don't do anything if the frame is garbaged;
- in that case, the FRAME_CURRENT_GLYPHS that we would use
- are all wrong, and we will redisplay that line anyway. */
- if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
- || lastline < XFASTINT (w->top)))
- clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
- }
- }
-
- UNBLOCK_INPUT;
-}
-
-static
-XTupdate_end (f)
- struct frame *f;
-{
- int mask;
-
- BLOCK_INPUT;
-
- do_line_dance ();
- x_display_cursor (f, 1, curs_x, curs_y);
-
- FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
-#if 0
- /* This fails in the case of having updated only the echo area
- if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
- has no relation to the current contents, and its charstarts
- have no relation to the contents of the window-buffer.
- I don't know a clean way to check
- for that case. window_end_valid isn't set up yet. */
- if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
- note_mouse_highlight (f, FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x,
- FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y);
-#endif
-
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-}
-
-/* This is called after a redisplay on frame F. */
-
-static
-XTframe_up_to_date (f)
- FRAME_PTR f;
-{
- BLOCK_INPUT;
- if (FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc
- || f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
- {
- note_mouse_highlight (FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame,
- FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x,
- FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y);
- FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
- }
- UNBLOCK_INPUT;
-}
-
-/* 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 (new, vpos)
- int new, vpos;
-{
- highlight = new;
-}
-
-/* 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;
-{
- highlight = new_highlight;
- XTcursor_to (vpos, 0);
- XTclear_end_of_line (FRAME_WINDOW_WIDTH (updating_frame));
-}
-
-/* This is used when starting Emacs and when restarting after suspend.
- When starting Emacs, no X window is mapped. And nothing must be done
- to Emacs's own window if it is suspended (though that rarely happens). */
-
-static
-XTset_terminal_modes ()
-{
-}
-
-/* This is called when exiting or suspending Emacs.
- Exiting will make the X-windows go away, and suspending
- requires no action. */
-
-static
-XTreset_terminal_modes ()
-{
-/* XTclear_frame (); */
-}
-
-/* Set the nominal cursor position of the frame.
- This is where display update commands will take effect.
- This does not affect the place where the cursor-box is displayed. */
-
-static int
-XTcursor_to (row, col)
- register int row, col;
-{
- int mask;
- int orow = row;
-
- curs_x = col;
- curs_y = row;
-
- if (updating_frame == 0)
- {
- BLOCK_INPUT;
- x_display_cursor (selected_frame, 1, curs_x, curs_y);
- XFlush (FRAME_X_DISPLAY (selected_frame));
- UNBLOCK_INPUT;
- }
-}
-
-/* Display a sequence of N glyphs found at GP.
- WINDOW is the x-window to output to. LEFT and TOP are starting coords.
- HL is 1 if this text is highlighted, 2 if the cursor is on it,
- 3 if should appear in its mouse-face.
- JUST_FOREGROUND if 1 means draw only the foreground;
- don't alter the background.
-
- FONT is the default font to use (for glyphs whose font-code is 0).
-
- Since the display generation code is responsible for calling
- compute_char_face and compute_glyph_face on everything it puts in
- the display structure, we can assume that the face code on each
- glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
- to which we can actually apply intern_face.
- Call this function with input blocked. */
-
-#if 1
-/* This is the multi-face code. */
-
-static void
-dumpglyphs (f, left, top, gp, n, hl, just_foreground)
- struct frame *f;
- int left, top;
- register GLYPH *gp; /* Points to first GLYPH. */
- register int n; /* Number of glyphs to display. */
- int hl;
- int just_foreground;
-{
- /* Holds characters to be displayed. */
- char *buf = (char *) alloca (FRAME_WINDOW_WIDTH (f) * sizeof (*buf));
- register char *cp; /* Steps through buf[]. */
- register int tlen = GLYPH_TABLE_LENGTH;
- register Lisp_Object *tbase = GLYPH_TABLE_BASE;
- Window window = FRAME_X_WINDOW (f);
- int orig_left = left;
-
- while (n > 0)
- {
- /* Get the face-code of the next GLYPH. */
- int cf, len;
- int g = *gp;
-
- GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
- cf = FAST_GLYPH_FACE (g);
-
- /* Find the run of consecutive glyphs with the same face-code.
- Extract their character codes into BUF. */
- cp = buf;
- while (n > 0)
- {
- g = *gp;
- GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
- if (FAST_GLYPH_FACE (g) != cf)
- break;
-
- *cp++ = FAST_GLYPH_CHAR (g);
- --n;
- ++gp;
- }
-
- /* LEN gets the length of the run. */
- len = cp - buf;
-
- /* Now output this run of chars, with the font and pixel values
- determined by the face code CF. */
- {
- struct face *face = FRAME_DEFAULT_FACE (f);
- XFontStruct *font = FACE_FONT (face);
- GC gc = FACE_GC (face);
- int stippled = 0;
-
- /* HL = 3 means use a mouse face previously chosen. */
- if (hl == 3)
- cf = FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id;
-
- /* First look at the face of the text itself. */
- if (cf != 0)
- {
- /* It's possible for the display table to specify
- a face code that is out of range. Use 0 in that case. */
- if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
- || FRAME_COMPUTED_FACES (f) [cf] == 0)
- cf = 0;
-
- if (cf == 1)
- face = FRAME_MODE_LINE_FACE (f);
- else
- face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
- font = FACE_FONT (face);
- gc = FACE_GC (face);
- if (FACE_STIPPLE (face))
- stippled = 1;
- }
-
- /* Then comes the distinction between modeline and normal text. */
- else if (hl == 0)
- ;
- else if (hl == 1)
- {
- face = FRAME_MODE_LINE_FACE (f);
- font = FACE_FONT (face);
- gc = FACE_GC (face);
- if (FACE_STIPPLE (face))
- stippled = 1;
- }
-
-#define FACE_DEFAULT (~0)
-
- /* Now override that if the cursor's on this character. */
- if (hl == 2)
- {
- /* The cursor overrides stippling. */
- stippled = 0;
-
- if ((!face->font
- || face->font == (XFontStruct *) FACE_DEFAULT
- || face->font == f->output_data.x->font)
- && face->background == f->output_data.x->background_pixel
- && face->foreground == f->output_data.x->foreground_pixel)
- {
- gc = f->output_data.x->cursor_gc;
- }
- /* Cursor on non-default face: must merge. */
- else
- {
- XGCValues xgcv;
- unsigned long mask;
-
- xgcv.background = f->output_data.x->cursor_pixel;
- xgcv.foreground = face->background;
- /* If the glyph would be invisible,
- try a different foreground. */
- if (xgcv.foreground == xgcv.background)
- xgcv.foreground = face->foreground;
- if (xgcv.foreground == xgcv.background)
- xgcv.foreground = f->output_data.x->cursor_foreground_pixel;
- if (xgcv.foreground == xgcv.background)
- xgcv.foreground = face->foreground;
- /* Make sure the cursor is distinct from text in this face. */
- if (xgcv.background == face->background
- && xgcv.foreground == face->foreground)
- {
- xgcv.background = face->foreground;
- xgcv.foreground = face->background;
- }
- xgcv.font = face->font->fid;
- xgcv.graphics_exposures = 0;
- mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
- if (FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc)
- XChangeGC (FRAME_X_DISPLAY (f),
- FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc,
- mask, &xgcv);
- else
- FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc
- = XCreateGC (FRAME_X_DISPLAY (f), window, mask, &xgcv);
- gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
-#if 0
-/* If this code is restored, it must also reset to the default stipple
- if necessary. */
- if (face->stipple && face->stipple != FACE_DEFAULT)
- XSetStipple (FRAME_X_DISPLAY (f), gc, face->stipple);
-#endif
- }
- }
-
- if (font == (XFontStruct *) FACE_DEFAULT)
- font = f->output_data.x->font;
-
- if (just_foreground)
- XDrawString (FRAME_X_DISPLAY (f), window, gc,
- left, top + FONT_BASE (font), buf, len);
- else
- {
- if (stippled)
- {
- /* Turn stipple on. */
- XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillOpaqueStippled);
-
- /* Draw stipple on background. */
- XFillRectangle (FRAME_X_DISPLAY (f), window, gc,
- left, top,
- FONT_WIDTH (font) * len,
- FONT_HEIGHT (font));
-
- /* Turn stipple off. */
- XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid);
-
- /* Draw the text, solidly, onto the stipple pattern. */
- XDrawString (FRAME_X_DISPLAY (f), window, gc,
- left, top + FONT_BASE (font), buf, len);
- }
- else
- XDrawImageString (FRAME_X_DISPLAY (f), window, gc,
- left, top + FONT_BASE (font), buf, len);
-
- /* Clear the rest of the line's height. */
- if (f->output_data.x->line_height != FONT_HEIGHT (font))
- XClearArea (FRAME_X_DISPLAY (f), window, left,
- top + FONT_HEIGHT (font),
- FONT_WIDTH (font) * len,
- /* This is how many pixels of height
- we have to clear. */
- f->output_data.x->line_height - FONT_HEIGHT (font),
- False);
- }
-
-#if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
- which often is not up to date yet. */
- if (!just_foreground)
- {
- if (left == orig_left)
- redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left),
- PIXEL_TO_CHAR_ROW (f, top), hl == 1);
- if (n == 0)
- redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)),
- PIXEL_TO_CHAR_ROW (f, top), hl == 1);
- }
-#endif
-
- /* We should probably check for XA_UNDERLINE_POSITION and
- XA_UNDERLINE_THICKNESS properties on the font, but let's
- just get the thing working, and come back to that. */
- {
- int underline_position = 1;
-
- if (font->descent <= underline_position)
- underline_position = font->descent - 1;
-
- if (face->underline)
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- FACE_GC (face),
- left, (top
- + FONT_BASE (font)
- + underline_position),
- len * FONT_WIDTH (font), 1);
- }
-
- left += len * FONT_WIDTH (font);
- }
- }
-}
-#endif /* 1 */
-
-#if 0
-/* This is the old single-face code. */
-
-static void
-dumpglyphs (f, left, top, gp, n, hl, font)
- struct frame *f;
- int left, top;
- register GLYPH *gp; /* Points to first GLYPH. */
- register int n; /* Number of glyphs to display. */
- int hl;
- XFontStruct *font;
-{
- register int len;
- Window window = FRAME_X_WINDOW (f);
- GC drawing_gc = (hl == 2 ? f->output_data.x->cursor_gc
- : (hl ? f->output_data.x->reverse_gc
- : f->output_data.x->normal_gc));
-
- if (sizeof (GLYPH) == sizeof (XChar2b))
- XDrawImageString16 (FRAME_X_DISPLAY (f), window, drawing_gc,
- left, top + FONT_BASE (font), (XChar2b *) gp, n);
- else if (sizeof (GLYPH) == sizeof (unsigned char))
- XDrawImageString (FRAME_X_DISPLAY (f), window, drawing_gc,
- left, top + FONT_BASE (font), (char *) gp, n);
- else
- /* What size of glyph ARE you using? And does X have a function to
- draw them? */
- abort ();
-}
-#endif
-
-/* Output some text at the nominal frame cursor position.
- Advance the cursor over the text.
- Output LEN glyphs at START.
-
- `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
- controls the pixel values used for foreground and background. */
-
-static
-XTwrite_glyphs (start, len)
- register GLYPH *start;
- int len;
-{
- register int temp_length;
- int mask;
- struct frame *f;
-
- BLOCK_INPUT;
-
- do_line_dance ();
- f = updating_frame;
- if (f == 0)
- {
- f = selected_frame;
- /* If not within an update,
- output at the frame's visible cursor. */
- curs_x = f->cursor_x;
- curs_y = f->cursor_y;
- }
-
- dumpglyphs (f,
- CHAR_TO_PIXEL_COL (f, curs_x),
- CHAR_TO_PIXEL_ROW (f, curs_y),
- start, len, highlight, 0);
-
- /* If we drew on top of the cursor, note that it is turned off. */
- if (curs_y == f->phys_cursor_y
- && curs_x <= f->phys_cursor_x
- && curs_x + len > f->phys_cursor_x)
- f->phys_cursor_on = 0;
-
- if (updating_frame == 0)
- x_display_cursor (f, 1, FRAME_CURSOR_X (f) + len, FRAME_CURSOR_Y (f));
- else
- curs_x += len;
-
- UNBLOCK_INPUT;
-}
-
-/* Clear to the end of the line.
- Erase the current text line from the nominal cursor position (inclusive)
- to column FIRST_UNUSED (exclusive). The idea is that everything
- from FIRST_UNUSED onward is already erased. */
-
-static
-XTclear_end_of_line (first_unused)
- register int first_unused;
-{
- struct frame *f = updating_frame;
- int mask;
-
- if (f == 0)
- abort ();
-
- if (curs_y < 0 || curs_y >= f->height)
- return;
- if (first_unused <= 0)
- return;
-
- if (first_unused >= FRAME_WINDOW_WIDTH (f))
- first_unused = FRAME_WINDOW_WIDTH (f);
-
- first_unused += FRAME_LEFT_SCROLL_BAR_WIDTH (f);
-
- BLOCK_INPUT;
-
- do_line_dance ();
-
- /* Notice if the cursor will be cleared by this operation. */
- if (curs_y == f->phys_cursor_y
- && curs_x <= f->phys_cursor_x
- && f->phys_cursor_x < first_unused)
- f->phys_cursor_on = 0;
-
- XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- CHAR_TO_PIXEL_COL (f, curs_x),
- CHAR_TO_PIXEL_ROW (f, curs_y),
- FONT_WIDTH (f->output_data.x->font) * (first_unused - curs_x),
- f->output_data.x->line_height, False);
-#if 0
- redraw_previous_char (f, curs_x, curs_y, highlight);
-#endif
-
- UNBLOCK_INPUT;
-}
-
-static
-XTclear_frame ()
-{
- int mask;
- struct frame *f = updating_frame;
-
- if (f == 0)
- f = selected_frame;
-
- f->phys_cursor_on = 0; /* Cursor not visible. */
- curs_x = 0; /* Nominal cursor position is top left. */
- curs_y = 0;
-
- BLOCK_INPUT;
-
- XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-
- /* We have to clear the scroll bars, too. If we have changed
- colors or something like that, then they should be notified. */
- x_scroll_bar_clear (f);
-
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-}
-
-#if 0
-/* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
- always contain the right glyphs to use.
-
- It also needs to be changed to look at the details of the font and
- see whether there is really overlap, and do nothing when there is
- not. This can use font_char_overlap_left and font_char_overlap_right,
- but just how to use them is not clear. */
-
-/* Erase the character (if any) at the position just before X, Y in frame F,
- then redraw it and the character before it.
- This is necessary when we erase starting at X,
- in case the character after X overlaps into the one before X.
- Call this function with input blocked. */
-
-static void
-redraw_previous_char (f, x, y, highlight_flag)
- FRAME_PTR f;
- int x, y;
- int highlight_flag;
-{
- /* Erase the character before the new ones, in case
- what was here before overlaps it.
- Reoutput that character, and the previous character
- (in case the previous character overlaps it). */
- if (x > 0)
- {
- int start_x = x - 2;
- if (start_x < 0)
- start_x = 0;
- XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- CHAR_TO_PIXEL_COL (f, x - 1),
- CHAR_TO_PIXEL_ROW (f, y),
- FONT_WIDTH (f->output_data.x->font),
- f->output_data.x->line_height, False);
-
- dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x),
- CHAR_TO_PIXEL_ROW (f, y),
- &FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x],
- x - start_x, highlight_flag, 1);
- }
-}
-
-/* Erase the character (if any) at the position X, Y in frame F,
- then redraw it and the character after it.
- This is necessary when we erase endng at X,
- in case the character after X overlaps into the one before X.
- Call this function with input blocked. */
-
-static void
-redraw_following_char (f, x, y, highlight_flag)
- FRAME_PTR f;
- int x, y;
- int highlight_flag;
-{
- int limit = FRAME_CURRENT_GLYPHS (f)->used[y];
- /* Erase the character after the new ones, in case
- what was here before overlaps it.
- Reoutput that character, and the following character
- (in case the following character overlaps it). */
- if (x < limit
- && FRAME_CURRENT_GLYPHS (f)->glyphs[y][x] != SPACEGLYPH)
- {
- int end_x = x + 2;
- if (end_x > limit)
- end_x = limit;
- XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- CHAR_TO_PIXEL_COL (f, x),
- CHAR_TO_PIXEL_ROW (f, y),
- FONT_WIDTH (f->output_data.x->font),
- f->output_data.x->line_height, False);
-
- dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x),
- CHAR_TO_PIXEL_ROW (f, y),
- &FRAME_CURRENT_GLYPHS (f)->glyphs[y][x],
- end_x - x, highlight_flag, 1);
- }
-}
-#endif /* 0 */
-
-#if 0 /* Not in use yet */
-
-/* Return 1 if character C in font F extends past its left edge. */
-
-static int
-font_char_overlap_left (font, c)
- XFontStruct *font;
- int c;
-{
- XCharStruct *s;
-
- /* Find the bounding-box info for C. */
- if (font->per_char == 0)
- s = &font->max_bounds;
- else
- {
- int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
- int row, within;
-
- /* Decode char into row number (byte 1) and code within row (byte 2). */
- row = c >> 8;
- within = c & 0177;
- if (!(within >= font->min_char_or_byte2
- && within <= font->max_char_or_byte2
- && row >= font->min_byte1
- && row <= font->max_byte1))
- {
- /* If char is out of range, try the font's default char instead. */
- c = font->default_char;
- row = c >> (BITS_PER_INT - 8);
- within = c & 0177;
- }
- if (!(within >= font->min_char_or_byte2
- && within <= font->max_char_or_byte2
- && row >= font->min_byte1
- && row <= font->max_byte1))
- /* Still out of range means this char does not overlap. */
- return 0;
- else
- /* We found the info for this char. */
- s = (font->per_char + (within - font->min_char_or_byte2)
- + row * rowlen);
- }
-
- return (s && s->lbearing < 0);
-}
-
-/* Return 1 if character C in font F extends past its right edge. */
-
-static int
-font_char_overlap_right (font, c)
- XFontStruct *font;
- int c;
-{
- XCharStruct *s;
-
- /* Find the bounding-box info for C. */
- if (font->per_char == 0)
- s = &font->max_bounds;
- else
- {
- int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
- int row, within;
-
- /* Decode char into row number (byte 1) and code within row (byte 2). */
- row = c >> 8;
- within = c & 0177;
- if (!(within >= font->min_char_or_byte2
- && within <= font->max_char_or_byte2
- && row >= font->min_byte1
- && row <= font->max_byte1))
- {
- /* If char is out of range, try the font's default char instead. */
- c = font->default_char;
- row = c >> (BITS_PER_INT - 8);
- within = c & 0177;
- }
- if (!(within >= font->min_char_or_byte2
- && within <= font->max_char_or_byte2
- && row >= font->min_byte1
- && row <= font->max_byte1))
- /* Still out of range means this char does not overlap. */
- return 0;
- else
- /* We found the info for this char. */
- s = (font->per_char + (within - font->min_char_or_byte2)
- + row * rowlen);
- }
-
- return (s && s->rbearing >= s->width);
-}
-#endif /* 0 */
-
-/* Invert the middle quarter of the frame for .15 sec. */
-
-/* We use the select system call to do the waiting, so we have to make sure
- it's available. If it isn't, we just won't do visual bells. */
-#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
-
-/* Subtract the `struct timeval' values X and Y,
- storing the result in RESULT.
- Return 1 if the difference is negative, otherwise 0. */
-
-static int
-timeval_subtract (result, x, y)
- struct timeval *result, x, y;
-{
- /* Perform the carry for the later subtraction by updating y.
- This is safer because on some systems
- the tv_sec member is unsigned. */
- if (x.tv_usec < y.tv_usec)
- {
- int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
- y.tv_usec -= 1000000 * nsec;
- y.tv_sec += nsec;
- }
- if (x.tv_usec - y.tv_usec > 1000000)
- {
- int nsec = (y.tv_usec - x.tv_usec) / 1000000;
- y.tv_usec += 1000000 * nsec;
- y.tv_sec -= nsec;
- }
-
- /* Compute the time remaining to wait. tv_usec is certainly positive. */
- result->tv_sec = x.tv_sec - y.tv_sec;
- result->tv_usec = x.tv_usec - y.tv_usec;
-
- /* Return indication of whether the result should be considered negative. */
- return x.tv_sec < y.tv_sec;
-}
-
-XTflash (f)
- struct frame *f;
-{
- BLOCK_INPUT;
-
- {
- GC gc;
-
- /* Create a GC that will use the GXxor function to flip foreground pixels
- into background pixels. */
- {
- XGCValues values;
-
- values.function = GXxor;
- values.foreground = (f->output_data.x->foreground_pixel
- ^ f->output_data.x->background_pixel);
-
- gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- GCFunction | GCForeground, &values);
- }
-
- {
- /* Get the height not including a menu bar widget. */
- int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
- /* Height of each line to flash. */
- int flash_height = FRAME_LINE_HEIGHT (f);
- /* These will be the left and right margins of the rectangles. */
- int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
- int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
-
- int width;
-
- /* Don't flash the area between a scroll bar and the frame
- edge it is next to. */
- switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
- {
- case vertical_scroll_bar_left:
- flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
- break;
-
- case vertical_scroll_bar_right:
- flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
- break;
- }
-
- width = flash_right - flash_left;
-
- /* If window is tall, flash top and bottom line. */
- if (height > 3 * FRAME_LINE_HEIGHT (f))
- {
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
- width, flash_height);
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- flash_left,
- (height - flash_height
- - FRAME_INTERNAL_BORDER_WIDTH (f)),
- width, flash_height);
- }
- else
- /* If it is short, flash it all. */
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
- width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
-
- XFlush (FRAME_X_DISPLAY (f));
-
- {
- struct timeval wakeup, now;
-
- EMACS_GET_TIME (wakeup);
-
- /* Compute time to wait until, propagating carry from usecs. */
- wakeup.tv_usec += 150000;
- wakeup.tv_sec += (wakeup.tv_usec / 1000000);
- wakeup.tv_usec %= 1000000;
-
- /* Keep waiting until past the time wakeup. */
- while (1)
- {
- struct timeval timeout;
-
- EMACS_GET_TIME (timeout);
-
- /* In effect, timeout = wakeup - timeout.
- Break if result would be negative. */
- if (timeval_subtract (&timeout, wakeup, timeout))
- break;
-
- /* Try to wait that long--but we might wake up sooner. */
- select (0, NULL, NULL, NULL, &timeout);
- }
- }
-
- /* If window is tall, flash top and bottom line. */
- if (height > 3 * FRAME_LINE_HEIGHT (f))
- {
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
- width, flash_height);
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- flash_left,
- (height - flash_height
- - FRAME_INTERNAL_BORDER_WIDTH (f)),
- width, flash_height);
- }
- else
- /* If it is short, flash it all. */
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
- width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
-
- XFreeGC (FRAME_X_DISPLAY (f), gc);
- XFlush (FRAME_X_DISPLAY (f));
- }
- }
-
- UNBLOCK_INPUT;
-}
-
-#endif
-
-
-/* Make audible bell. */
-
-#define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
-
-XTring_bell ()
-{
- if (FRAME_X_DISPLAY (selected_frame) == 0)
- return;
-
-#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
- if (visible_bell)
- XTflash (selected_frame);
- else
-#endif
- {
- BLOCK_INPUT;
- XRINGBELL;
- XFlush (FRAME_X_DISPLAY (selected_frame));
- UNBLOCK_INPUT;
- }
-}
-
-/* Insert and delete character.
- These are not supposed to be used because we are supposed to turn
- off the feature of using them. */
-
-static
-XTinsert_glyphs (start, len)
- register char *start;
- register int len;
-{
- abort ();
-}
-
-static
-XTdelete_glyphs (n)
- register int n;
-{
- abort ();
-}
-
-/* Specify how many text lines, from the top of the window,
- should be affected by insert-lines and delete-lines operations.
- This, and those operations, are used only within an update
- that is bounded by calls to XTupdate_begin and XTupdate_end. */
-
-static
-XTset_terminal_window (n)
- register int n;
-{
- if (updating_frame == 0)
- abort ();
-
- if ((n <= 0) || (n > updating_frame->height))
- flexlines = updating_frame->height;
- else
- flexlines = n;
-}
-
-/* These variables need not be per frame
- because redisplay is done on a frame-by-frame basis
- and the line dance for one frame is finished before
- anything is done for anoter frame. */
-
-/* Array of line numbers from cached insert/delete operations.
- line_dance[i] is the old position of the line that we want
- to move to line i, or -1 if we want a blank line there. */
-static int *line_dance;
-
-/* Allocated length of that array. */
-static int line_dance_len;
-
-/* Flag indicating whether we've done any work. */
-static int line_dance_in_progress;
-
-/* Perform an insert-lines or delete-lines operation,
- inserting N lines or deleting -N lines at vertical position VPOS. */
-XTins_del_lines (vpos, n)
- int vpos, n;
-{
- register int fence, i;
-
- if (vpos >= flexlines)
- return;
-
- if (!line_dance_in_progress)
- {
- int ht = updating_frame->height;
- if (ht > line_dance_len)
- {
- line_dance = (int *)xrealloc (line_dance, ht * sizeof (int));
- line_dance_len = ht;
- }
- for (i = 0; i < ht; ++i) line_dance[i] = i;
- line_dance_in_progress = 1;
- }
- if (n >= 0)
- {
- if (n > flexlines - vpos)
- n = flexlines - vpos;
- fence = vpos + n;
- for (i = flexlines; --i >= fence;)
- line_dance[i] = line_dance[i-n];
- for (i = fence; --i >= vpos;)
- line_dance[i] = -1;
- }
- else
- {
- n = -n;
- if (n > flexlines - vpos)
- n = flexlines - vpos;
- fence = flexlines - n;
- for (i = vpos; i < fence; ++i)
- line_dance[i] = line_dance[i + n];
- for (i = fence; i < flexlines; ++i)
- line_dance[i] = -1;
- }
-}
-
-/* Here's where we actually move the pixels around.
- Must be called with input blocked. */
-static void
-do_line_dance ()
-{
- register int i, j, distance;
- register struct frame *f;
- int ht;
- int intborder;
-
- /* Must check this flag first. If it's not set, then not only is the
- array uninitialized, but we might not even have a frame. */
- if (!line_dance_in_progress)
- return;
-
- f = updating_frame;
- if (f == 0)
- abort ();
-
- ht = f->height;
- intborder = CHAR_TO_PIXEL_COL (f, FRAME_LEFT_SCROLL_BAR_WIDTH (f));
-
- x_update_cursor (updating_frame, 0);
-
- for (i = 0; i < ht; ++i)
- if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
- {
- for (j = i; (j < ht && line_dance[j] != -1
- && line_dance[j]-j == distance); ++j);
- /* Copy [i,j) upward from [i+distance,j+distance) */
- XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- FRAME_X_WINDOW (f), f->output_data.x->normal_gc,
- intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
- FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (f->output_data.x->font),
- (j-i) * f->output_data.x->line_height,
- intborder, CHAR_TO_PIXEL_ROW (f, i));
- i = j-1;
- }
-
- for (i = ht; --i >=0; )
- if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0)
- {
- for (j = i; (--j >= 0 && line_dance[j] != -1
- && line_dance[j]-j == distance););
- /* Copy (j,i] downward from (j+distance, i+distance] */
- XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- FRAME_X_WINDOW (f), f->output_data.x->normal_gc,
- intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
- FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (f->output_data.x->font),
- (i-j) * f->output_data.x->line_height,
- intborder, CHAR_TO_PIXEL_ROW (f, j+1));
- i = j+1;
- }
-
- for (i = 0; i < ht; ++i)
- if (line_dance[i] == -1)
- {
- for (j = i; j < ht && line_dance[j] == -1; ++j);
- /* Clear [i,j) */
- XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- intborder, CHAR_TO_PIXEL_ROW (f, i),
- FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (f->output_data.x->font),
- (j-i) * f->output_data.x->line_height, False);
- i = j-1;
- }
- line_dance_in_progress = 0;
-}
-
-/* Support routines for exposure events. */
-static void clear_cursor ();
-
-/* Output into a rectangle of an X-window (for frame F)
- the characters in f->phys_lines that overlap that rectangle.
- TOP and LEFT are the position of the upper left corner of the rectangle.
- ROWS and COLS are the size of the rectangle.
- Call this function with input blocked. */
-
-static void
-dumprectangle (f, left, top, cols, rows)
- struct frame *f;
- register int left, top, cols, rows;
-{
- register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
- int cursor_cleared = 0;
- int bottom, right;
- register int y;
-
- if (FRAME_GARBAGED_P (f))
- return;
-
- /* Express rectangle as four edges, instead of position-and-size. */
- bottom = top + rows;
- right = left + cols;
-
- /* Convert rectangle edges in pixels to edges in chars.
- Round down for left and top, up for right and bottom. */
- top = PIXEL_TO_CHAR_ROW (f, top);
- left = PIXEL_TO_CHAR_COL (f, left);
- bottom += (f->output_data.x->line_height - 1);
- right += (FONT_WIDTH (f->output_data.x->font) - 1);
- bottom = PIXEL_TO_CHAR_ROW (f, bottom);
- right = PIXEL_TO_CHAR_COL (f, right);
-
- /* Clip the rectangle to what can be visible. */
- if (left < 0)
- left = 0;
- if (top < 0)
- top = 0;
- if (right > FRAME_WINDOW_WIDTH (f))
- right = FRAME_WINDOW_WIDTH (f);
- if (bottom > f->height)
- bottom = f->height;
-
- /* Get size in chars of the rectangle. */
- cols = right - left;
- rows = bottom - top;
-
- /* If rectangle has zero area, return. */
- if (rows <= 0) return;
- if (cols <= 0) return;
-
- /* Turn off the cursor if it is in the rectangle.
- We will turn it back on afterward. */
- if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
- && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
- {
- clear_cursor (f);
- cursor_cleared = 1;
- }
-
- /* Display the text in the rectangle, one text line at a time. */
-
- for (y = top; y < bottom; y++)
- {
- GLYPH *line = &active_frame->glyphs[y][left];
-
- if (! active_frame->enable[y] || left > active_frame->used[y])
- continue;
-
- dumpglyphs (f,
- CHAR_TO_PIXEL_COL (f, left),
- CHAR_TO_PIXEL_ROW (f, y),
- line, min (cols, active_frame->used[y] - left),
- active_frame->highlight[y], 0);
- }
-
- /* Turn the cursor on if we turned it off. */
-
- if (cursor_cleared)
- x_update_cursor (f, 1);
-}
-
-static void
-frame_highlight (f)
- struct frame *f;
-{
- /* We used to only do this if Vx_no_window_manager was non-nil, but
- the ICCCM (section 4.1.6) says that the window's border pixmap
- and border pixel are window attributes which are "private to the
- client", so we can always change it to whatever we want. */
- BLOCK_INPUT;
- XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->border_pixel);
- UNBLOCK_INPUT;
- x_update_cursor (f, 1);
-}
-
-static void
-frame_unhighlight (f)
- struct frame *f;
-{
- /* We used to only do this if Vx_no_window_manager was non-nil, but
- the ICCCM (section 4.1.6) says that the window's border pixmap
- and border pixel are window attributes which are "private to the
- client", so we can always change it to whatever we want. */
- BLOCK_INPUT;
- XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->border_tile);
- UNBLOCK_INPUT;
- x_update_cursor (f, 1);
-}
-
-static void XTframe_rehighlight ();
-static void x_frame_rehighlight ();
-
-/* The focus has changed. Update the frames as necessary to reflect
- the new situation. Note that we can't change the selected frame
- here, because the Lisp code we are interrupting might become confused.
- Each event gets marked with the frame in which it occurred, so the
- Lisp code can tell when the switch took place by examining the events. */
-
-static void
-x_new_focus_frame (dpyinfo, frame)
- struct x_display_info *dpyinfo;
- struct frame *frame;
-{
- struct frame *old_focus = dpyinfo->x_focus_frame;
- int events_enqueued = 0;
-
- if (frame != dpyinfo->x_focus_frame)
- {
- /* Set this before calling other routines, so that they see
- the correct value of x_focus_frame. */
- dpyinfo->x_focus_frame = frame;
-
- if (old_focus && old_focus->auto_lower)
- x_lower_frame (old_focus);
-
-#if 0
- selected_frame = frame;
- XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
- selected_frame);
- Fselect_window (selected_frame->selected_window);
- choose_minibuf_frame ();
-#endif /* ! 0 */
-
- if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
- pending_autoraise_frame = dpyinfo->x_focus_frame;
- else
- pending_autoraise_frame = 0;
- }
-
- x_frame_rehighlight (dpyinfo);
-}
-
-/* Handle an event saying the mouse has moved out of an Emacs frame. */
-
-void
-x_mouse_leave (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
-}
-
-/* The focus has changed, or we have redirected a frame's focus to
- another frame (this happens when a frame uses a surrogate
- minibuffer frame). Shift the highlight as appropriate.
-
- The FRAME argument doesn't necessarily have anything to do with which
- frame is being highlighted or unhighlighted; we only use it to find
- the appropriate X display info. */
-static void
-XTframe_rehighlight (frame)
- struct frame *frame;
-{
- x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
-}
-
-static void
-x_frame_rehighlight (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- struct frame *old_highlight = dpyinfo->x_highlight_frame;
-
- if (dpyinfo->x_focus_frame)
- {
- dpyinfo->x_highlight_frame
- = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
- ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
- : dpyinfo->x_focus_frame);
- if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
- {
- FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
- dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
- }
- }
- else
- dpyinfo->x_highlight_frame = 0;
-
- if (dpyinfo->x_highlight_frame != old_highlight)
- {
- if (old_highlight)
- frame_unhighlight (old_highlight);
- if (dpyinfo->x_highlight_frame)
- frame_highlight (dpyinfo->x_highlight_frame);
- }
-}
-
-/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
-
-/* Initialize mode_switch_bit and modifier_meaning. */
-static void
-x_find_modifier_meanings (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- int min_code, max_code;
- KeySym *syms;
- int syms_per_code;
- XModifierKeymap *mods;
-
- dpyinfo->meta_mod_mask = 0;
- dpyinfo->shift_lock_mask = 0;
- dpyinfo->alt_mod_mask = 0;
- dpyinfo->super_mod_mask = 0;
- dpyinfo->hyper_mod_mask = 0;
-
-#ifdef HAVE_X11R4
- XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
-#else
- min_code = dpyinfo->display->min_keycode;
- max_code = dpyinfo->display->max_keycode;
-#endif
-
- syms = XGetKeyboardMapping (dpyinfo->display,
- min_code, max_code - min_code + 1,
- &syms_per_code);
- mods = XGetModifierMapping (dpyinfo->display);
-
- /* Scan the modifier table to see which modifier bits the Meta and
- Alt keysyms are on. */
- {
- int row, col; /* The row and column in the modifier table. */
-
- for (row = 3; row < 8; row++)
- for (col = 0; col < mods->max_keypermod; col++)
- {
- KeyCode code
- = mods->modifiermap[(row * mods->max_keypermod) + col];
-
- /* Zeroes are used for filler. Skip them. */
- if (code == 0)
- continue;
-
- /* Are any of this keycode's keysyms a meta key? */
- {
- int code_col;
-
- for (code_col = 0; code_col < syms_per_code; code_col++)
- {
- int sym = syms[((code - min_code) * syms_per_code) + code_col];
-
- switch (sym)
- {
- case XK_Meta_L:
- case XK_Meta_R:
- dpyinfo->meta_mod_mask |= (1 << row);
- break;
-
- case XK_Alt_L:
- case XK_Alt_R:
- dpyinfo->alt_mod_mask |= (1 << row);
- break;
-
- case XK_Hyper_L:
- case XK_Hyper_R:
- dpyinfo->hyper_mod_mask |= (1 << row);
- break;
-
- case XK_Super_L:
- case XK_Super_R:
- dpyinfo->super_mod_mask |= (1 << row);
- break;
-
- case XK_Shift_Lock:
- /* Ignore this if it's not on the lock modifier. */
- if ((1 << row) == LockMask)
- dpyinfo->shift_lock_mask = LockMask;
- break;
- }
- }
- }
- }
- }
-
- /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
- if (! dpyinfo->meta_mod_mask)
- {
- dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
- dpyinfo->alt_mod_mask = 0;
- }
-
- /* If some keys are both alt and meta,
- make them just meta, not alt. */
- if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
- {
- dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
- }
-
- XFree ((char *) syms);
- XFreeModifiermap (mods);
-}
-
-/* Convert between the modifier bits X uses and the modifier bits
- Emacs uses. */
-static unsigned int
-x_x_to_emacs_modifiers (dpyinfo, state)
- struct x_display_info *dpyinfo;
- unsigned int state;
-{
- return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
- | ((state & ControlMask) ? ctrl_modifier : 0)
- | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
- | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
- | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
- | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
-}
-
-static unsigned int
-x_emacs_to_x_modifiers (dpyinfo, state)
- struct x_display_info *dpyinfo;
- unsigned int state;
-{
- return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
- | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
- | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
- | ((state & shift_modifier) ? ShiftMask : 0)
- | ((state & ctrl_modifier) ? ControlMask : 0)
- | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
-}
-
-/* Convert a keysym to its name. */
-
-char *
-x_get_keysym_name (keysym)
- KeySym keysym;
-{
- char *value;
-
- BLOCK_INPUT;
- value = XKeysymToString (keysym);
- UNBLOCK_INPUT;
-
- return value;
-}
-
-/* Mouse clicks and mouse movement. Rah. */
-
-/* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
- glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
- that the glyph at X, Y occupies, if BOUNDS != 0.
- If NOCLIP is nonzero, do not force the value into range. */
-
-void
-pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
- FRAME_PTR f;
- register int pix_x, pix_y;
- register int *x, *y;
- XRectangle *bounds;
- int noclip;
-{
- /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
- even for negative values. */
- if (pix_x < 0)
- pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
- if (pix_y < 0)
- pix_y -= (f)->output_data.x->line_height - 1;
-
- pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
- pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
-
- if (bounds)
- {
- bounds->width = FONT_WIDTH (f->output_data.x->font);
- bounds->height = f->output_data.x->line_height;
- bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
- bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
- }
-
- if (!noclip)
- {
- if (pix_x < 0)
- pix_x = 0;
- else if (pix_x > FRAME_WINDOW_WIDTH (f))
- pix_x = FRAME_WINDOW_WIDTH (f);
-
- if (pix_y < 0)
- pix_y = 0;
- else if (pix_y > f->height)
- pix_y = f->height;
- }
-
- *x = pix_x;
- *y = pix_y;
-}
-
-void
-glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
- FRAME_PTR f;
- register int x, y;
- register int *pix_x, *pix_y;
-{
- *pix_x = CHAR_TO_PIXEL_COL (f, x);
- *pix_y = CHAR_TO_PIXEL_ROW (f, y);
-}
-
-/* Prepare a mouse-event in *RESULT for placement in the input queue.
-
- If the event is a button press, then note that we have grabbed
- the mouse. */
-
-static Lisp_Object
-construct_mouse_click (result, event, f)
- struct input_event *result;
- XButtonEvent *event;
- struct frame *f;
-{
- /* Make the event type no_event; we'll change that when we decide
- otherwise. */
- result->kind = mouse_click;
- result->code = event->button - Button1;
- result->timestamp = event->time;
- result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
- event->state)
- | (event->type == ButtonRelease
- ? up_modifier
- : down_modifier));
-
- {
- int row, column;
-
-#if 0
- pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL, 0);
- XSETFASTINT (result->x, column);
- XSETFASTINT (result->y, row);
-#endif
- XSETINT (result->x, event->x);
- XSETINT (result->y, event->y);
- XSETFRAME (result->frame_or_window, f);
- }
-}
-
-/* Prepare a menu-event in *RESULT for placement in the input queue. */
-
-static Lisp_Object
-construct_menu_click (result, event, f)
- struct input_event *result;
- XButtonEvent *event;
- struct frame *f;
-{
- /* Make the event type no_event; we'll change that when we decide
- otherwise. */
- result->kind = mouse_click;
- XSETINT (result->code, event->button - Button1);
- result->timestamp = event->time;
- result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
- event->state)
- | (event->type == ButtonRelease
- ? up_modifier
- : down_modifier));
-
- XSETINT (result->x, event->x);
- XSETINT (result->y, -1);
- XSETFRAME (result->frame_or_window, f);
-}
-
-/* Function to report a mouse movement to the mainstream Emacs code.
- The input handler calls this.
-
- We have received a mouse movement event, which is given in *event.
- If the mouse is over a different glyph than it was last time, tell
- the mainstream emacs code by setting mouse_moved. If not, ask for
- another motion event, so we can check again the next time it moves. */
-
-static void
-note_mouse_movement (frame, event)
- FRAME_PTR frame;
- XMotionEvent *event;
-{
- last_mouse_movement_time = event->time;
-
- if (event->window != FRAME_X_WINDOW (frame))
- {
- frame->mouse_moved = 1;
- last_mouse_scroll_bar = Qnil;
-
- note_mouse_highlight (frame, -1, -1);
- }
-
- /* Has the mouse moved off the glyph it was on at the last sighting? */
- else if (event->x < last_mouse_glyph.x
- || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
- || event->y < last_mouse_glyph.y
- || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
- {
- frame->mouse_moved = 1;
- last_mouse_scroll_bar = Qnil;
-
- note_mouse_highlight (frame, event->x, event->y);
- }
-}
-
-/* This is used for debugging, to turn off note_mouse_highlight. */
-static int disable_mouse_highlight;
-
-/* Take proper action when the mouse has moved to position X, Y on frame F
- as regards highlighting characters that have mouse-face properties.
- Also dehighlighting chars where the mouse was before.
- X and Y can be negative or out of range. */
-
-static void
-note_mouse_highlight (f, x, y)
- FRAME_PTR f;
- int x, y;
-{
- int row, column, portion;
- XRectangle new_glyph;
- Lisp_Object window;
- struct window *w;
-
- if (disable_mouse_highlight)
- return;
-
- FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
- FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
- FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
-
- if (FRAME_X_DISPLAY_INFO (f)->mouse_face_defer)
- return;
-
- if (gc_in_progress)
- {
- FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
- return;
- }
-
- /* Find out which glyph the mouse is on. */
- pixel_to_glyph_coords (f, x, y, &column, &row,
- &new_glyph, FRAME_X_DISPLAY_INFO (f)->grabbed);
-
- /* Which window is that in? */
- window = window_from_coordinates (f, column, row, &portion);
- w = XWINDOW (window);
-
- /* If we were displaying active text in another window, clear that. */
- if (! EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window))
- clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
-
- /* Are we in a window whose display is up to date?
- And verify the buffer's text has not changed. */
- if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
- && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
- && EQ (w->window_end_valid, w->buffer)
- && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer))
- && w->last_overlay_modified == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))
- {
- int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
- int i, pos;
-
- /* Find which buffer position the mouse corresponds to. */
- for (i = column; i >= 0; i--)
- if (ptr[i] > 0)
- break;
- pos = ptr[i];
- /* Is it outside the displayed active region (if any)? */
- if (pos <= 0)
- clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
- else if (! (EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window)
- && row >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
- && row <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
- && (row > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
- || column >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col)
- && (row < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
- || column < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col
- || FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end)))
- {
- Lisp_Object mouse_face, overlay, position;
- Lisp_Object *overlay_vec;
- int len, noverlays, ignor1;
- struct buffer *obuf;
- int obegv, ozv;
-
- /* If we get an out-of-range value, return now; avoid an error. */
- if (pos > BUF_Z (XBUFFER (w->buffer)))
- return;
-
- /* Make the window's buffer temporarily current for
- overlays_at and compute_char_face. */
- obuf = current_buffer;
- current_buffer = XBUFFER (w->buffer);
- obegv = BEGV;
- ozv = ZV;
- BEGV = BEG;
- ZV = Z;
-
- /* Yes. Clear the display of the old active region, if any. */
- clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
-
- /* Is this char mouse-active? */
- XSETINT (position, pos);
-
- len = 10;
- overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
-
- /* Put all the overlays we want in a vector in overlay_vec.
- Store the length in len. */
- noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
- NULL, NULL);
- noverlays = sort_overlays (overlay_vec, noverlays, w);
-
- /* Find the highest priority overlay that has a mouse-face prop. */
- overlay = Qnil;
- for (i = 0; i < noverlays; i++)
- {
- mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
- if (!NILP (mouse_face))
- {
- overlay = overlay_vec[i];
- break;
- }
- }
- free (overlay_vec);
- /* If no overlay applies, get a text property. */
- if (NILP (overlay))
- mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
-
- /* Handle the overlay case. */
- if (! NILP (overlay))
- {
- /* Find the range of text around this char that
- should be active. */
- Lisp_Object before, after;
- int ignore;
-
- before = Foverlay_start (overlay);
- after = Foverlay_end (overlay);
- /* Record this as the current active region. */
- fast_find_position (window, XFASTINT (before),
- &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col,
- &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row);
- FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end
- = !fast_find_position (window, XFASTINT (after),
- &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col,
- &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row);
- FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window;
- FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id
- = compute_char_face (f, w, pos, 0, 0,
- &ignore, pos + 1, 1);
-
- /* Display it as active. */
- show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1);
- }
- /* Handle the text property case. */
- else if (! NILP (mouse_face))
- {
- /* Find the range of text around this char that
- should be active. */
- Lisp_Object before, after, beginning, end;
- int ignore;
-
- beginning = Fmarker_position (w->start);
- XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
- - XFASTINT (w->window_end_pos)));
- before
- = Fprevious_single_property_change (make_number (pos + 1),
- Qmouse_face,
- w->buffer, beginning);
- after
- = Fnext_single_property_change (position, Qmouse_face,
- w->buffer, end);
- /* Record this as the current active region. */
- fast_find_position (window, XFASTINT (before),
- &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col,
- &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row);
- FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end
- = !fast_find_position (window, XFASTINT (after),
- &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col,
- &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row);
- FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window;
- FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id
- = compute_char_face (f, w, pos, 0, 0,
- &ignore, pos + 1, 1);
-
- /* Display it as active. */
- show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1);
- }
- BEGV = obegv;
- ZV = ozv;
- current_buffer = obuf;
- }
- }
-}
-
-/* Find the row and column of position POS in window WINDOW.
- Store them in *COLUMNP and *ROWP.
- This assumes display in WINDOW is up to date.
- If POS is above start of WINDOW, return coords
- of start of first screen line.
- If POS is after end of WINDOW, return coords of end of last screen line.
-
- Value is 1 if POS is in range, 0 if it was off screen. */
-
-static int
-fast_find_position (window, pos, columnp, rowp)
- Lisp_Object window;
- int pos;
- int *columnp, *rowp;
-{
- struct window *w = XWINDOW (window);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
- int i;
- int row = 0;
- int left = WINDOW_LEFT_MARGIN (w);
- int top = w->top;
- int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
- int width = window_internal_width (w);
- int *charstarts;
- int lastcol;
- int maybe_next_line = 0;
-
- /* Find the right row. */
- for (i = 0;
- i < height;
- i++)
- {
- int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
- if (linestart > pos)
- break;
- /* If the position sought is the end of the buffer,
- don't include the blank lines at the bottom of the window. */
- if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer)))
- {
- maybe_next_line = 1;
- break;
- }
- if (linestart > 0)
- row = i;
- }
-
- /* Find the right column with in it. */
- charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
- lastcol = left;
- for (i = 0; i < width; i++)
- {
- if (charstarts[left + i] == pos)
- {
- *rowp = row + top;
- *columnp = i + left;
- return 1;
- }
- else if (charstarts[left + i] > pos)
- break;
- else if (charstarts[left + i] > 0)
- lastcol = left + i;
- }
-
- /* If we're looking for the end of the buffer,
- and we didn't find it in the line we scanned,
- use the start of the following line. */
- if (maybe_next_line)
- {
- row++;
- lastcol = left;
- }
-
- *rowp = row + top;
- *columnp = lastcol;
- return 0;
-}
-
-/* Display the active region described by mouse_face_*
- in its mouse-face if HL > 0, in its normal face if HL = 0. */
-
-static void
-show_mouse_face (dpyinfo, hl)
- struct x_display_info *dpyinfo;
- int hl;
-{
- struct window *w = XWINDOW (dpyinfo->mouse_face_window);
- int width = window_internal_width (w);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
- int i;
- int cursor_off = 0;
- int old_curs_x = curs_x;
- int old_curs_y = curs_y;
-
- /* Set these variables temporarily
- so that if we have to turn the cursor off and on again
- we will put it back at the same place. */
- curs_x = f->phys_cursor_x;
- curs_y = f->phys_cursor_y;
- for (i = FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row;
- i <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row; i++)
- {
- int column = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
- ? FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col
- : WINDOW_LEFT_MARGIN (w));
- int endcolumn = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
- ? FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col
- : WINDOW_LEFT_MARGIN (w) + width);
- endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
-
- /* If the cursor's in the text we are about to rewrite,
- turn the cursor off. */
- if (i == curs_y
- && curs_x >= column - 1
- && curs_x <= endcolumn)
- {
- x_update_cursor (f, 0);
- cursor_off = 1;
- }
-
- dumpglyphs (f,
- CHAR_TO_PIXEL_COL (f, column),
- CHAR_TO_PIXEL_ROW (f, i),
- FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
- endcolumn - column,
- /* Highlight with mouse face if hl > 0. */
- hl > 0 ? 3 : 0, 0);
- }
-
- /* If we turned the cursor off, turn it back on. */
- if (cursor_off)
- x_display_cursor (f, 1, curs_x, curs_y);
-
- curs_x = old_curs_x;
- curs_y = old_curs_y;
-
- /* Change the mouse cursor according to the value of HL. */
- if (hl > 0)
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->cross_cursor);
- else
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->text_cursor);
-}
-
-/* Clear out the mouse-highlighted active region.
- Redraw it unhighlighted first. */
-
-static void
-clear_mouse_face (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- if (! NILP (dpyinfo->mouse_face_window))
- show_mouse_face (dpyinfo, 0);
-
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
-}
-
-/* Just discard the mouse face information for frame F, if any.
- This is used when the size of F is changed. */
-
-cancel_mouse_face (f)
- FRAME_PTR f;
-{
- Lisp_Object window;
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-
- window = dpyinfo->mouse_face_window;
- if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
- {
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
- }
-}
-
-static struct scroll_bar *x_window_to_scroll_bar ();
-static void x_scroll_bar_report_motion ();
-
-/* Return the current position of the mouse.
- *fp should be a frame which indicates which display to ask about.
-
- If the mouse movement started in a scroll bar, set *fp, *bar_window,
- and *part to the frame, window, and scroll bar part that the mouse
- is over. Set *x and *y to the portion and whole of the mouse's
- position on the scroll bar.
-
- If the mouse movement started elsewhere, set *fp to the frame the
- mouse is on, *bar_window to nil, and *x and *y to the character cell
- the mouse is over.
-
- Set *time to the server timestamp for the time at which the mouse
- was at this position.
-
- Don't store anything if we don't have a valid set of values to report.
-
- This clears the mouse_moved flag, so we can wait for the next mouse
- movement. */
-
-static void
-XTmouse_position (fp, insist, bar_window, part, x, y, time)
- FRAME_PTR *fp;
- int insist;
- Lisp_Object *bar_window;
- enum scroll_bar_part *part;
- Lisp_Object *x, *y;
- unsigned long *time;
-{
- FRAME_PTR f1;
-
- BLOCK_INPUT;
-
- if (! NILP (last_mouse_scroll_bar))
- x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
- else
- {
- Window root;
- int root_x, root_y;
-
- Window dummy_window;
- int dummy;
-
- Lisp_Object frame, tail;
-
- /* Clear the mouse-moved flag for every frame on this display. */
- FOR_EACH_FRAME (tail, frame)
- if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
- XFRAME (frame)->mouse_moved = 0;
-
- last_mouse_scroll_bar = Qnil;
-
- /* Figure out which root window we're on. */
- XQueryPointer (FRAME_X_DISPLAY (*fp),
- DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
-
- /* The root window which contains the pointer. */
- &root,
-
- /* Trash which we can't trust if the pointer is on
- a different screen. */
- &dummy_window,
-
- /* The position on that root window. */
- &root_x, &root_y,
-
- /* More trash we can't trust. */
- &dummy, &dummy,
-
- /* Modifier keys and pointer buttons, about which
- we don't care. */
- (unsigned int *) &dummy);
-
- /* Now we have a position on the root; find the innermost window
- containing the pointer. */
- {
- Window win, child;
- int win_x, win_y;
- int parent_x, parent_y;
-
- win = root;
-
- /* XTranslateCoordinates can get errors if the window
- structure is changing at the same time this function
- is running. So at least we must not crash from them. */
-
- x_catch_errors (FRAME_X_DISPLAY (*fp));
-
- if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
- && FRAME_LIVE_P (last_mouse_frame))
- {
- /* If mouse was grabbed on a frame, give coords for that frame
- even if the mouse is now outside it. */
- XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
-
- /* From-window, to-window. */
- root, FRAME_X_WINDOW (last_mouse_frame),
-
- /* From-position, to-position. */
- root_x, root_y, &win_x, &win_y,
-
- /* Child of win. */
- &child);
- f1 = last_mouse_frame;
- }
- else
- {
- while (1)
- {
- XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
-
- /* From-window, to-window. */
- root, win,
-
- /* From-position, to-position. */
- root_x, root_y, &win_x, &win_y,
-
- /* Child of win. */
- &child);
-
- if (child == None || child == win)
- break;
-
- win = child;
- parent_x = win_x;
- parent_y = win_y;
- }
-
- /* Now we know that:
- win is the innermost window containing the pointer
- (XTC says it has no child containing the pointer),
- win_x and win_y are the pointer's position in it
- (XTC did this the last time through), and
- parent_x and parent_y are the pointer's position in win's parent.
- (They are what win_x and win_y were when win was child.
- If win is the root window, it has no parent, and
- parent_{x,y} are invalid, but that's okay, because we'll
- never use them in that case.) */
-
- /* Is win one of our frames? */
- f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
- }
-
- if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
- f1 = 0;
-
- x_uncatch_errors (FRAME_X_DISPLAY (*fp));
-
- /* If not, is it one of our scroll bars? */
- if (! f1)
- {
- struct scroll_bar *bar = x_window_to_scroll_bar (win);
-
- if (bar)
- {
- f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
- win_x = parent_x;
- win_y = parent_y;
- }
- }
-
- if (f1 == 0 && insist)
- f1 = selected_frame;
-
- if (f1)
- {
- int ignore1, ignore2;
-
- /* Ok, we found a frame. Store all the values. */
-
- pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
- &last_mouse_glyph,
- FRAME_X_DISPLAY_INFO (f1)->grabbed
- || insist);
-
- *bar_window = Qnil;
- *part = 0;
- *fp = f1;
- XSETINT (*x, win_x);
- XSETINT (*y, win_y);
- *time = last_mouse_movement_time;
- }
- }
- }
-
- UNBLOCK_INPUT;
-}
-
-/* Scroll bar support. */
-
-/* Given an X window ID, find the struct scroll_bar which manages it.
- This can be called in GC, so we have to make sure to strip off mark
- bits. */
-static struct scroll_bar *
-x_window_to_scroll_bar (window_id)
- Window window_id;
-{
- Lisp_Object tail, frame;
-
- for (tail = Vframe_list;
- XGCTYPE (tail) == Lisp_Cons;
- tail = XCONS (tail)->cdr)
- {
- Lisp_Object frame, bar, condemned;
-
- frame = XCONS (tail)->car;
- /* All elements of Vframe_list should be frames. */
- if (! GC_FRAMEP (frame))
- abort ();
-
- /* Scan this frame's scroll bar list for a scroll bar with the
- right window ID. */
- condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
- for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
- /* This trick allows us to search both the ordinary and
- condemned scroll bar lists with one loop. */
- ! GC_NILP (bar) || (bar = condemned,
- condemned = Qnil,
- ! GC_NILP (bar));
- bar = XSCROLL_BAR (bar)->next)
- if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
- return XSCROLL_BAR (bar);
- }
-
- return 0;
-}
-
-/* Open a new X window to serve as a scroll bar, and return the
- scroll bar vector for it. */
-static struct scroll_bar *
-x_scroll_bar_create (window, top, left, width, height)
- struct window *window;
- int top, left, width, height;
-{
- FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
- struct scroll_bar *bar
- = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
-
- BLOCK_INPUT;
-
- {
- XSetWindowAttributes a;
- unsigned long mask;
- a.background_pixel = f->output_data.x->background_pixel;
- a.event_mask = (ButtonPressMask | ButtonReleaseMask
- | ButtonMotionMask | PointerMotionHintMask
- | ExposureMask);
- a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
-
- mask = (CWBackPixel | CWEventMask | CWCursor);
-
-#if 0
-
- ac = 0;
- XtSetArg (al[ac], XtNx, left); ac++;
- XtSetArg (al[ac], XtNy, top); ac++;
- XtSetArg (al[ac], XtNwidth, width); ac++;
- XtSetArg (al[ac], XtNheight, height); ac++;
- XtSetArg (al[ac], XtNborderWidth, 0); ac++;
- sb_widget = XtCreateManagedWidget ("box",
- boxWidgetClass,
- f->output_data.x->edit_widget, al, ac);
- SET_SCROLL_BAR_X_WINDOW
- (bar, sb_widget->core.window);
-#endif
- SET_SCROLL_BAR_X_WINDOW
- (bar,
- XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-
- /* Position and size of scroll bar. */
- left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, top,
- width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, height,
-
- /* Border width, depth, class, and visual. */
- 0, CopyFromParent, CopyFromParent, CopyFromParent,
-
- /* Attributes. */
- mask, &a));
- }
-
- XSETWINDOW (bar->window, window);
- XSETINT (bar->top, top);
- XSETINT (bar->left, left);
- XSETINT (bar->width, width);
- XSETINT (bar->height, height);
- XSETINT (bar->start, 0);
- XSETINT (bar->end, 0);
- bar->dragging = Qnil;
-
- /* Add bar to its frame's list of scroll bars. */
- bar->next = FRAME_SCROLL_BARS (f);
- bar->prev = Qnil;
- XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
- if (! NILP (bar->next))
- XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
-
- XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
-
- UNBLOCK_INPUT;
-
- return bar;
-}
-
-/* Draw BAR's handle in the proper position.
- If the handle is already drawn from START to END, don't bother
- redrawing it, unless REBUILD is non-zero; in that case, always
- redraw it. (REBUILD is handy for drawing the handle after expose
- events.)
-
- Normally, we want to constrain the start and end of the handle to
- fit inside its rectangle, but if the user is dragging the scroll bar
- handle, we want to let them drag it down all the way, so that the
- bar's top is as far down as it goes; otherwise, there's no way to
- move to the very end of the buffer. */
-static void
-x_scroll_bar_set_handle (bar, start, end, rebuild)
- struct scroll_bar *bar;
- int start, end;
- int rebuild;
-{
- int dragging = ! NILP (bar->dragging);
- Window w = SCROLL_BAR_X_WINDOW (bar);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
- GC gc = f->output_data.x->normal_gc;
-
- /* If the display is already accurate, do nothing. */
- if (! rebuild
- && start == XINT (bar->start)
- && end == XINT (bar->end))
- return;
-
- BLOCK_INPUT;
-
- {
- int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
- int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
- int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
-
- /* Make sure the values are reasonable, and try to preserve
- the distance between start and end. */
- {
- int length = end - start;
-
- if (start < 0)
- start = 0;
- else if (start > top_range)
- start = top_range;
- end = start + length;
-
- if (end < start)
- end = start;
- else if (end > top_range && ! dragging)
- end = top_range;
- }
-
- /* Store the adjusted setting in the scroll bar. */
- XSETINT (bar->start, start);
- XSETINT (bar->end, end);
-
- /* Clip the end position, just for display. */
- if (end > top_range)
- end = top_range;
-
- /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
- below top positions, to make sure the handle is always at least
- that many pixels tall. */
- end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
-
- /* Draw the empty space above the handle. Note that we can't clear
- zero-height areas; that means "clear to end of window." */
- if (0 < start)
- XClearArea (FRAME_X_DISPLAY (f), w,
-
- /* x, y, width, height, and exposures. */
- VERTICAL_SCROLL_BAR_LEFT_BORDER,
- VERTICAL_SCROLL_BAR_TOP_BORDER,
- inside_width, start,
- False);
-
- /* Draw the handle itself. */
- XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
-
- /* x, y, width, height */
- VERTICAL_SCROLL_BAR_LEFT_BORDER,
- VERTICAL_SCROLL_BAR_TOP_BORDER + start,
- inside_width, end - start);
-
-
- /* Draw the empty space below the handle. Note that we can't
- clear zero-height areas; that means "clear to end of window." */
- if (end < inside_height)
- XClearArea (FRAME_X_DISPLAY (f), w,
-
- /* x, y, width, height, and exposures. */
- VERTICAL_SCROLL_BAR_LEFT_BORDER,
- VERTICAL_SCROLL_BAR_TOP_BORDER + end,
- inside_width, inside_height - end,
- False);
-
- }
-
- UNBLOCK_INPUT;
-}
-
-/* Move a scroll bar around on the screen, to accommodate changing
- window configurations. */
-static void
-x_scroll_bar_move (bar, top, left, width, height)
- struct scroll_bar *bar;
- int top, left, width, height;
-{
- Window w = SCROLL_BAR_X_WINDOW (bar);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-
- BLOCK_INPUT;
-
- {
- XWindowChanges wc;
- unsigned int mask = 0;
-
- wc.x = left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
- wc.y = top;
-
- wc.width = width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
- wc.height = height;
-
- if (left != XINT (bar->left)) mask |= CWX;
- if (top != XINT (bar->top)) mask |= CWY;
- if (width != XINT (bar->width)) mask |= CWWidth;
- if (height != XINT (bar->height)) mask |= CWHeight;
-
- if (mask)
- XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
- mask, &wc);
- }
-
- XSETINT (bar->left, left);
- XSETINT (bar->top, top);
- XSETINT (bar->width, width);
- XSETINT (bar->height, height);
-
- UNBLOCK_INPUT;
-}
-
-/* Destroy the X window for BAR, and set its Emacs window's scroll bar
- to nil. */
-static void
-x_scroll_bar_remove (bar)
- struct scroll_bar *bar;
-{
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-
- BLOCK_INPUT;
-
- /* Destroy the window. */
- XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
-
- /* Disassociate this scroll bar from its window. */
- XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
-
- UNBLOCK_INPUT;
-}
-
-/* Set the handle of the vertical scroll bar for WINDOW to indicate
- that we are displaying PORTION characters out of a total of WHOLE
- characters, starting at POSITION. If WINDOW has no scroll bar,
- create one. */
-static void
-XTset_vertical_scroll_bar (window, portion, whole, position)
- struct window *window;
- int portion, whole, position;
-{
- FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
- int top = XINT (window->top);
- int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
- int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
-
- /* Where should this scroll bar be, pixelwise? */
- int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
- int pixel_left = CHAR_TO_PIXEL_COL (f, left);
- int pixel_width
- = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
- ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
- : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
- int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
-
- struct scroll_bar *bar;
-
- /* Does the scroll bar exist yet? */
- if (NILP (window->vertical_scroll_bar))
- bar = x_scroll_bar_create (window,
- pixel_top, pixel_left,
- pixel_width, pixel_height);
- else
- {
- /* It may just need to be moved and resized. */
- bar = XSCROLL_BAR (window->vertical_scroll_bar);
- x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
- }
-
- /* Set the scroll bar's current state, unless we're currently being
- dragged. */
- if (NILP (bar->dragging))
- {
- int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, pixel_height);
-
- if (whole == 0)
- x_scroll_bar_set_handle (bar, 0, top_range, 0);
- else
- {
- int start = ((double) position * top_range) / whole;
- int end = ((double) (position + portion) * top_range) / whole;
-
- x_scroll_bar_set_handle (bar, start, end, 0);
- }
- }
-
- XSETVECTOR (window->vertical_scroll_bar, bar);
-}
-
-
-/* The following three hooks are used when we're doing a thorough
- redisplay of the frame. We don't explicitly know which scroll bars
- are going to be deleted, because keeping track of when windows go
- away is a real pain - "Can you say set-window-configuration, boys
- and girls?" Instead, we just assert at the beginning of redisplay
- that *all* scroll bars are to be removed, and then save a scroll bar
- from the fiery pit when we actually redisplay its window. */
-
-/* Arrange for all scroll bars on FRAME to be removed at the next call
- to `*judge_scroll_bars_hook'. A scroll bar may be spared if
- `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
-static void
-XTcondemn_scroll_bars (frame)
- FRAME_PTR frame;
-{
- /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
- while (! NILP (FRAME_SCROLL_BARS (frame)))
- {
- Lisp_Object bar;
- bar = FRAME_SCROLL_BARS (frame);
- FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
- XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
- XSCROLL_BAR (bar)->prev = Qnil;
- if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
- XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
- FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
- }
-}
-
-/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
- Note that WINDOW isn't necessarily condemned at all. */
-static void
-XTredeem_scroll_bar (window)
- struct window *window;
-{
- struct scroll_bar *bar;
-
- /* We can't redeem this window's scroll bar if it doesn't have one. */
- if (NILP (window->vertical_scroll_bar))
- abort ();
-
- bar = XSCROLL_BAR (window->vertical_scroll_bar);
-
- /* Unlink it from the condemned list. */
- {
- FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
-
- if (NILP (bar->prev))
- {
- /* If the prev pointer is nil, it must be the first in one of
- the lists. */
- if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
- /* It's not condemned. Everything's fine. */
- return;
- else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
- window->vertical_scroll_bar))
- FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
- else
- /* If its prev pointer is nil, it must be at the front of
- one or the other! */
- abort ();
- }
- else
- XSCROLL_BAR (bar->prev)->next = bar->next;
-
- if (! NILP (bar->next))
- XSCROLL_BAR (bar->next)->prev = bar->prev;
-
- bar->next = FRAME_SCROLL_BARS (f);
- bar->prev = Qnil;
- XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
- if (! NILP (bar->next))
- XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
- }
-}
-
-/* Remove all scroll bars on FRAME that haven't been saved since the
- last call to `*condemn_scroll_bars_hook'. */
-static void
-XTjudge_scroll_bars (f)
- FRAME_PTR f;
-{
- Lisp_Object bar, next;
-
- bar = FRAME_CONDEMNED_SCROLL_BARS (f);
-
- /* Clear out the condemned list now so we won't try to process any
- more events on the hapless scroll bars. */
- FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
-
- for (; ! NILP (bar); bar = next)
- {
- struct scroll_bar *b = XSCROLL_BAR (bar);
-
- x_scroll_bar_remove (b);
-
- next = b->next;
- b->next = b->prev = Qnil;
- }
-
- /* Now there should be no references to the condemned scroll bars,
- and they should get garbage-collected. */
-}
-
-
-/* Handle an Expose or GraphicsExpose event on a scroll bar.
-
- This may be called from a signal handler, so we have to ignore GC
- mark bits. */
-static void
-x_scroll_bar_expose (bar, event)
- struct scroll_bar *bar;
- XEvent *event;
-{
- Window w = SCROLL_BAR_X_WINDOW (bar);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
- GC gc = f->output_data.x->normal_gc;
- int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
-
- BLOCK_INPUT;
-
- x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
-
- /* Draw a one-pixel border just inside the edges of the scroll bar. */
- XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
-
- /* x, y, width, height */
- 0, 0,
- XINT (bar->width) - 1 - width_trim - width_trim,
- XINT (bar->height) - 1);
-
- UNBLOCK_INPUT;
-}
-
-/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
- is set to something other than no_event, it is enqueued.
-
- This may be called from a signal handler, so we have to ignore GC
- mark bits. */
-static void
-x_scroll_bar_handle_click (bar, event, emacs_event)
- struct scroll_bar *bar;
- XEvent *event;
- struct input_event *emacs_event;
-{
- if (! GC_WINDOWP (bar->window))
- abort ();
-
- emacs_event->kind = scroll_bar_click;
- emacs_event->code = event->xbutton.button - Button1;
- emacs_event->modifiers
- = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
- (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
- event->xbutton.state)
- | (event->type == ButtonRelease
- ? up_modifier
- : down_modifier));
- emacs_event->frame_or_window = bar->window;
- emacs_event->timestamp = event->xbutton.time;
- {
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
- int internal_height
- = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
- int top_range
- = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
- int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
-
- if (y < 0) y = 0;
- if (y > top_range) y = top_range;
-
- if (y < XINT (bar->start))
- emacs_event->part = scroll_bar_above_handle;
- else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
- emacs_event->part = scroll_bar_handle;
- else
- emacs_event->part = scroll_bar_below_handle;
-
- /* Just because the user has clicked on the handle doesn't mean
- they want to drag it. Lisp code needs to be able to decide
- whether or not we're dragging. */
-#if 0
- /* If the user has just clicked on the handle, record where they're
- holding it. */
- if (event->type == ButtonPress
- && emacs_event->part == scroll_bar_handle)
- XSETINT (bar->dragging, y - XINT (bar->start));
-#endif
-
- /* If the user has released the handle, set it to its final position. */
- if (event->type == ButtonRelease
- && ! NILP (bar->dragging))
- {
- int new_start = y - XINT (bar->dragging);
- int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
-
- x_scroll_bar_set_handle (bar, new_start, new_end, 0);
- bar->dragging = Qnil;
- }
-
- /* Same deal here as the other #if 0. */
-#if 0
- /* Clicks on the handle are always reported as occurring at the top of
- the handle. */
- if (emacs_event->part == scroll_bar_handle)
- emacs_event->x = bar->start;
- else
- XSETINT (emacs_event->x, y);
-#else
- XSETINT (emacs_event->x, y);
-#endif
-
- XSETINT (emacs_event->y, top_range);
- }
-}
-
-/* Handle some mouse motion while someone is dragging the scroll bar.
-
- This may be called from a signal handler, so we have to ignore GC
- mark bits. */
-static void
-x_scroll_bar_note_movement (bar, event)
- struct scroll_bar *bar;
- XEvent *event;
-{
- FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
-
- last_mouse_movement_time = event->xmotion.time;
-
- f->mouse_moved = 1;
- XSETVECTOR (last_mouse_scroll_bar, bar);
-
- /* If we're dragging the bar, display it. */
- if (! GC_NILP (bar->dragging))
- {
- /* Where should the handle be now? */
- int new_start = event->xmotion.y - XINT (bar->dragging);
-
- if (new_start != XINT (bar->start))
- {
- int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
-
- x_scroll_bar_set_handle (bar, new_start, new_end, 0);
- }
- }
-}
-
-/* Return information to the user about the current position of the mouse
- on the scroll bar. */
-static void
-x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
- FRAME_PTR *fp;
- Lisp_Object *bar_window;
- enum scroll_bar_part *part;
- Lisp_Object *x, *y;
- unsigned long *time;
-{
- struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
- Window w = SCROLL_BAR_X_WINDOW (bar);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
- int win_x, win_y;
- Window dummy_window;
- int dummy_coord;
- unsigned int dummy_mask;
-
- BLOCK_INPUT;
-
- /* Get the mouse's position relative to the scroll bar window, and
- report that. */
- if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
-
- /* Root, child, root x and root y. */
- &dummy_window, &dummy_window,
- &dummy_coord, &dummy_coord,
-
- /* Position relative to scroll bar. */
- &win_x, &win_y,
-
- /* Mouse buttons and modifier keys. */
- &dummy_mask))
- ;
- else
- {
- int inside_height
- = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
- int top_range
- = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
-
- win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
-
- if (! NILP (bar->dragging))
- win_y -= XINT (bar->dragging);
-
- if (win_y < 0)
- win_y = 0;
- if (win_y > top_range)
- win_y = top_range;
-
- *fp = f;
- *bar_window = bar->window;
-
- if (! NILP (bar->dragging))
- *part = scroll_bar_handle;
- else if (win_y < XINT (bar->start))
- *part = scroll_bar_above_handle;
- else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
- *part = scroll_bar_handle;
- else
- *part = scroll_bar_below_handle;
-
- XSETINT (*x, win_y);
- XSETINT (*y, top_range);
-
- f->mouse_moved = 0;
- last_mouse_scroll_bar = Qnil;
- }
-
- *time = last_mouse_movement_time;
-
- UNBLOCK_INPUT;
-}
-
-
-/* The screen has been cleared so we may have changed foreground or
- background colors, and the scroll bars may need to be redrawn.
- Clear out the scroll bars, and ask for expose events, so we can
- redraw them. */
-
-x_scroll_bar_clear (f)
- FRAME_PTR f;
-{
- Lisp_Object bar;
-
- /* We can have scroll bars even if this is 0,
- if we just turned off scroll bar mode.
- But in that case we should not clear them. */
- if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
- bar = XSCROLL_BAR (bar)->next)
- XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
- 0, 0, 0, 0, True);
-}
-
-/* This processes Expose events from the menubar specific X event
- loop in xmenu.c. This allows to redisplay the frame if necessary
- when handling menubar or popup items. */
-
-void
-process_expose_from_menu (event)
- XEvent event;
-{
- FRAME_PTR f;
- struct x_display_info *dpyinfo;
-
- BLOCK_INPUT;
-
- dpyinfo = x_display_info_for_display (event.xexpose.display);
- f = x_window_to_frame (dpyinfo, event.xexpose.window);
- if (f)
- {
- if (f->async_visible == 0)
- {
- f->async_visible = 1;
- f->async_iconified = 0;
- SET_FRAME_GARBAGED (f);
- }
- else
- {
- dumprectangle (x_window_to_frame (dpyinfo, event.xexpose.window),
- event.xexpose.x, event.xexpose.y,
- event.xexpose.width, event.xexpose.height);
- }
- }
- else
- {
- struct scroll_bar *bar
- = x_window_to_scroll_bar (event.xexpose.window);
-
- if (bar)
- x_scroll_bar_expose (bar, &event);
- }
-
- UNBLOCK_INPUT;
-}
-
-/* Define a queue to save up SelectionRequest events for later handling. */
-
-struct selection_event_queue
- {
- XEvent event;
- struct selection_event_queue *next;
- };
-
-static struct selection_event_queue *queue;
-
-/* Nonzero means queue up certain events--don't process them yet. */
-static int x_queue_selection_requests;
-
-/* Queue up an X event *EVENT, to be processed later. */
-
-static void
-x_queue_event (f, event)
- FRAME_PTR f;
- XEvent *event;
-{
- struct selection_event_queue *queue_tmp
- = (struct selection_event_queue *) malloc (sizeof (struct selection_event_queue));
-
- if (queue_tmp != NULL)
- {
- queue_tmp->event = *event;
- queue_tmp->next = queue;
- queue = queue_tmp;
- }
-}
-
-/* Take all the queued events and put them back
- so that they get processed afresh. */
-
-static void
-x_unqueue_events (display)
- Display *display;
-{
- while (queue != NULL)
- {
- struct selection_event_queue *queue_tmp = queue;
- XPutBackEvent (display, &queue_tmp->event);
- queue = queue_tmp->next;
- free ((char *)queue_tmp);
- }
-}
-
-/* Start queuing SelectionRequest events. */
-
-void
-x_start_queuing_selection_requests (display)
- Display *display;
-{
- x_queue_selection_requests++;
-}
-
-/* Stop queuing SelectionRequest events. */
-
-void
-x_stop_queuing_selection_requests (display)
- Display *display;
-{
- x_queue_selection_requests--;
- x_unqueue_events (display);
-}
-
-/* The main X event-reading loop - XTread_socket. */
-
-/* Timestamp of enter window event. This is only used by XTread_socket,
- but we have to put it out here, since static variables within functions
- sometimes don't work. */
-static Time enter_timestamp;
-
-/* This holds the state XLookupString needs to implement dead keys
- and other tricks known as "compose processing". _X Window System_
- says that a portable program can't use this, but Stephen Gildea assures
- me that letting the compiler initialize it to zeros will work okay.
-
- This must be defined outside of XTread_socket, for the same reasons
- given for enter_timestamp, above. */
-static XComposeStatus compose_status;
-
-/* Record the last 100 characters stored
- to help debug the loss-of-chars-during-GC problem. */
-static int temp_index;
-static short temp_buffer[100];
-
-/* Set this to nonzero to fake an "X I/O error"
- on a particular display. */
-struct x_display_info *XTread_socket_fake_io_error;
-
-/* When we find no input here, we occasionally do a no-op command
- to verify that the X server is still running and we can still talk with it.
- We try all the open displays, one by one.
- This variable is used for cycling thru the displays. */
-static struct x_display_info *next_noop_dpyinfo;
-
-#define SET_SAVED_MENU_EVENT(size) { \
- if (f->output_data.x->saved_menu_event == 0) \
- f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent)); \
- bcopy (&event, f->output_data.x->saved_menu_event, size); \
- if (numchars >= 1) \
- { \
- bufp->kind = menu_bar_activate_event; \
- XSETFRAME (bufp->frame_or_window, f); \
- bufp++; \
- count++; \
- numchars--; \
- } \
- }
-#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
-#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
-
-/* Read events coming from the X server.
- This routine is called by the SIGIO handler.
- We return as soon as there are no more events to be read.
-
- Events representing keys are stored in buffer BUFP,
- which can hold up to NUMCHARS characters.
- We return the number of characters stored into the buffer,
- thus pretending to be `read'.
-
- EXPECTED is nonzero if the caller knows input is available. */
-
-int
-XTread_socket (sd, bufp, numchars, expected)
- register int sd;
- /* register */ struct input_event *bufp;
- /* register */ int numchars;
- int expected;
-{
- int count = 0;
- int nbytes = 0;
- int mask;
- int items_pending; /* How many items are in the X queue. */
- XEvent event;
- struct frame *f;
- int event_found = 0;
- int prefix;
- Lisp_Object part;
- struct x_display_info *dpyinfo;
-#ifdef HAVE_X_I18N
- Status status_return;
-#endif
-
- if (interrupt_input_blocked)
- {
- interrupt_input_pending = 1;
- return -1;
- }
-
- interrupt_input_pending = 0;
- BLOCK_INPUT;
-
- /* So people can tell when we have read the available input. */
- input_signal_count++;
-
- if (numchars <= 0)
- abort (); /* Don't think this happens. */
-
- /* Find the display we are supposed to read input for.
- It's the one communicating on descriptor SD. */
- for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
- {
-#if 0 /* This ought to be unnecessary; let's verify it. */
-#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 signaling EWOULDBLOCK,
- a read returns 0, which Xlib interprets as equivalent to EPIPE. */
- fcntl (dpyinfo->connection, F_SETFL, 0);
-#endif /* ! defined (FIOSNBIO) */
-#endif
-
-#if 0 /* This code can't be made to work, with multiple displays,
- and appears not to be used on any system any more.
- Also keyboard.c doesn't turn O_NDELAY on and off
- for X connections. */
-#ifndef SIGIO
-#ifndef HAVE_SELECT
- if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
- {
- extern int read_alarm_should_throw;
- read_alarm_should_throw = 1;
- XPeekEvent (dpyinfo->display, &event);
- read_alarm_should_throw = 0;
- }
-#endif /* HAVE_SELECT */
-#endif /* SIGIO */
-#endif
-
- /* For debugging, this gives a way to fake an I/O error. */
- if (dpyinfo == XTread_socket_fake_io_error)
- {
- XTread_socket_fake_io_error = 0;
- x_io_error_quitter (dpyinfo->display);
- }
-
- while (XPending (dpyinfo->display) != 0)
- {
-#ifdef USE_X_TOOLKIT
- /* needed to raise Motif submenus */
- XtAppNextEvent (Xt_app_con, &event);
-#else
- XNextEvent (dpyinfo->display, &event);
-#endif
-#ifdef HAVE_X_I18N
- {
- struct frame *f1 = x_any_window_to_frame (dpyinfo,
- &event.xclient.window);
- /* The necessity of the following line took me
- a full work-day to decipher from the docs!! */
- if (f1 != 0 && FRAME_XIC (f1) && XFilterEvent (&event, None))
- break;
- }
-#endif
- event_found = 1;
-
- switch (event.type)
- {
- case ClientMessage:
- {
- if (event.xclient.message_type
- == dpyinfo->Xatom_wm_protocols
- && event.xclient.format == 32)
- {
- if (event.xclient.data.l[0]
- == dpyinfo->Xatom_wm_take_focus)
- {
- f = x_window_to_frame (dpyinfo, event.xclient.window);
- /* Since we set WM_TAKE_FOCUS, we must call
- XSetInputFocus explicitly. But not if f is null,
- since that might be an event for a deleted frame. */
-#ifdef HAVE_X_I18N
- /* Not quite sure this is needed -pd */
- if (f)
- XSetICFocus (FRAME_XIC (f));
-#endif
- if (f)
- XSetInputFocus (event.xclient.display,
- event.xclient.window,
- RevertToPointerRoot,
- event.xclient.data.l[1]);
- /* Not certain about handling scroll bars here */
- }
- else if (event.xclient.data.l[0]
- == dpyinfo->Xatom_wm_save_yourself)
- {
- /* Save state modify the WM_COMMAND property to
- something which can reinstate us. This notifies
- the session manager, who's looking for such a
- PropertyNotify. Can restart processing when
- a keyboard or mouse event arrives. */
- if (numchars > 0)
- {
- f = x_top_window_to_frame (dpyinfo,
- event.xclient.window);
-
- /* This is just so we only give real data once
- for a single Emacs process. */
- if (f == selected_frame)
- XSetCommand (FRAME_X_DISPLAY (f),
- event.xclient.window,
- initial_argv, initial_argc);
- else if (f)
- XSetCommand (FRAME_X_DISPLAY (f),
- event.xclient.window,
- 0, 0);
- }
- }
- else if (event.xclient.data.l[0]
- == dpyinfo->Xatom_wm_delete_window)
- {
- struct frame *f
- = x_any_window_to_frame (dpyinfo,
- event.xclient.window);
-
- if (f)
- {
- if (numchars == 0)
- abort ();
-
- bufp->kind = delete_window_event;
- XSETFRAME (bufp->frame_or_window, f);
- bufp++;
-
- count += 1;
- numchars -= 1;
- }
- }
- }
- else if (event.xclient.message_type
- == dpyinfo->Xatom_wm_configure_denied)
- {
- }
- else if (event.xclient.message_type
- == dpyinfo->Xatom_wm_window_moved)
- {
- int new_x, new_y;
- struct frame *f
- = x_window_to_frame (dpyinfo, event.xclient.window);
-
- new_x = event.xclient.data.s[0];
- new_y = event.xclient.data.s[1];
-
- if (f)
- {
- f->output_data.x->left_pos = new_x;
- f->output_data.x->top_pos = new_y;
- }
- }
-#ifdef HACK_EDITRES
- else if (event.xclient.message_type
- == dpyinfo->Xatom_editres)
- {
- struct frame *f
- = x_any_window_to_frame (dpyinfo, event.xclient.window);
- _XEditResCheckMessages (f->output_data.x->widget, NULL,
- &event, NULL);
- }
-#endif /* HACK_EDITRES */
- }
- break;
-
- case SelectionNotify:
-#ifdef USE_X_TOOLKIT
- if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
- goto OTHER;
-#endif /* not USE_X_TOOLKIT */
- x_handle_selection_notify (&event);
- break;
-
- case SelectionClear: /* Someone has grabbed ownership. */
-#ifdef USE_X_TOOLKIT
- if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
- goto OTHER;
-#endif /* USE_X_TOOLKIT */
- {
- XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
-
- if (numchars == 0)
- abort ();
-
- bufp->kind = selection_clear_event;
- SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
- SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
- SELECTION_EVENT_TIME (bufp) = eventp->time;
- bufp->frame_or_window = Qnil;
- bufp++;
-
- count += 1;
- numchars -= 1;
- }
- break;
-
- case SelectionRequest: /* Someone wants our selection. */
-#ifdef USE_X_TOOLKIT
- if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
- goto OTHER;
-#endif /* USE_X_TOOLKIT */
- if (x_queue_selection_requests)
- x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
- &event);
- else
- {
- XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
-
- if (numchars == 0)
- abort ();
-
- bufp->kind = selection_request_event;
- SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
- SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
- SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
- SELECTION_EVENT_TARGET (bufp) = eventp->target;
- SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
- SELECTION_EVENT_TIME (bufp) = eventp->time;
- bufp->frame_or_window = Qnil;
- bufp++;
-
- count += 1;
- numchars -= 1;
- }
- break;
-
- case PropertyNotify:
-#ifdef USE_X_TOOLKIT
- if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
- goto OTHER;
-#endif /* not USE_X_TOOLKIT */
- x_handle_property_notify (&event);
- break;
-
- case ReparentNotify:
- f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
- if (f)
- {
- int x, y;
- f->output_data.x->parent_desc = event.xreparent.parent;
- x_real_positions (f, &x, &y);
- f->output_data.x->left_pos = x;
- f->output_data.x->top_pos = y;
- }
- break;
-
- case Expose:
- f = x_window_to_frame (dpyinfo, event.xexpose.window);
- if (f)
- {
- if (f->async_visible == 0)
- {
- f->async_visible = 1;
- f->async_iconified = 0;
- SET_FRAME_GARBAGED (f);
- }
- else
- dumprectangle (x_window_to_frame (dpyinfo,
- event.xexpose.window),
- event.xexpose.x, event.xexpose.y,
- event.xexpose.width, event.xexpose.height);
- }
- else
- {
- struct scroll_bar *bar
- = x_window_to_scroll_bar (event.xexpose.window);
-
- if (bar)
- x_scroll_bar_expose (bar, &event);
-#ifdef USE_X_TOOLKIT
- else
- goto OTHER;
-#endif /* USE_X_TOOLKIT */
- }
- break;
-
- case GraphicsExpose: /* This occurs when an XCopyArea's
- source area was obscured or not
- available.*/
- f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
- if (f)
- {
- dumprectangle (f,
- event.xgraphicsexpose.x, event.xgraphicsexpose.y,
- event.xgraphicsexpose.width,
- event.xgraphicsexpose.height);
- }
-#ifdef USE_X_TOOLKIT
- else
- goto OTHER;
-#endif /* USE_X_TOOLKIT */
- break;
-
- case NoExpose: /* This occurs when an XCopyArea's
- source area was completely
- available */
- break;
-
- case UnmapNotify:
- f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
- if (f) /* F may no longer exist if
- the frame was deleted. */
- {
- /* While a frame is unmapped, display generation is
- disabled; you don't want to spend time updating a
- display that won't ever be seen. */
- f->async_visible = 0;
- /* We can't distinguish, from the event, whether the window
- has become iconified or invisible. So assume, if it
- was previously visible, than now it is iconified.
- We depend on x_make_frame_invisible to mark it invisible. */
- if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
- f->async_iconified = 1;
-
- bufp->kind = iconify_event;
- XSETFRAME (bufp->frame_or_window, f);
- bufp++;
- count++;
- numchars--;
- }
- goto OTHER;
-
- case MapNotify:
- /* We use x_top_window_to_frame because map events can come
- for subwindows and they don't mean that the frame is visible. */
- f = x_top_window_to_frame (dpyinfo, event.xmap.window);
- if (f)
- {
- f->async_visible = 1;
- f->async_iconified = 0;
-
- /* wait_reading_process_input will notice this and update
- the frame's display structures. */
- SET_FRAME_GARBAGED (f);
-
- if (f->iconified)
- {
- bufp->kind = deiconify_event;
- XSETFRAME (bufp->frame_or_window, f);
- bufp++;
- count++;
- numchars--;
- }
- else if (! NILP(Vframe_list)
- && ! NILP (XCONS (Vframe_list)->cdr))
- /* Force a redisplay sooner or later
- to update the frame titles
- in case this is the second frame. */
- record_asynch_buffer_change ();
- }
- goto OTHER;
-
- /* Turn off processing if we become fully obscured. */
- case VisibilityNotify:
- break;
-
- case KeyPress:
- f = x_any_window_to_frame (dpyinfo, event.xkey.window);
-
- if (f != 0)
- {
- KeySym keysym, orig_keysym;
- /* al%imercury@uunet.uu.net says that making this 81 instead of
- 80 fixed a bug whereby meta chars made his Emacs hang. */
- unsigned char copy_buffer[81];
- int modifiers;
-
-#if 0 /* This was how we made f10 work in Motif.
- The drawback is, you can't type at Emacs when the
- the mouse is in the menu bar. So it is better to
- turn off f10 in Motif and let Emacs handle it. */
-#ifdef USE_MOTIF
- if (lw_window_is_in_menubar (event.xkey.window,
- f->output_data.x->menubar_widget
- ))
- {
- SET_SAVED_KEY_EVENT;
- break;
- }
-#endif /* USE_MOTIF */
-#endif /* 0 */
-
- event.xkey.state
- |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
- extra_keyboard_modifiers);
- modifiers = event.xkey.state;
-
- /* This will have to go some day... */
-
- /* make_lispy_event turns chars into control chars.
- Don't do it here because XLookupString is too eager. */
- event.xkey.state &= ~ControlMask;
- event.xkey.state &= ~(dpyinfo->meta_mod_mask
- | dpyinfo->super_mod_mask
- | dpyinfo->hyper_mod_mask
- | dpyinfo->alt_mod_mask);
-
- /* In case Meta is ComposeCharacter,
- clear its status. According to Markus Ehrnsperger
- Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
- this enables ComposeCharacter to work whether or
- not it is combined with Meta. */
- if (modifiers & dpyinfo->meta_mod_mask)
- bzero (&compose_status, sizeof (compose_status));
-
-#ifdef HAVE_X_I18N
- if (FRAME_XIC (f))
- {
- nbytes = XmbLookupString (FRAME_XIC (f),
- &event.xkey, copy_buffer,
- 80, &keysym,
- &status_return);
- }
- else
- nbytes = XLookupString (&event.xkey, copy_buffer,
- 80, &keysym, &compose_status);
-#else
- nbytes = XLookupString (&event.xkey, copy_buffer,
- 80, &keysym, &compose_status);
-#endif
-
- orig_keysym = keysym;
-
- if (numchars > 1)
- {
- if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
- || keysym == XK_Delete
- || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
- || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
-#ifdef HPUX
- /* This recognizes the "extended function keys".
- It seems there's no cleaner way.
- Test IsModifierKey to avoid handling mode_switch
- incorrectly. */
- || ((unsigned) (keysym) >= XK_Select
- && (unsigned)(keysym) < XK_KP_Space)
-#endif
-#ifdef XK_dead_circumflex
- || orig_keysym == XK_dead_circumflex
-#endif
-#ifdef XK_dead_grave
- || orig_keysym == XK_dead_grave
-#endif
-#ifdef XK_dead_tilde
- || orig_keysym == XK_dead_tilde
-#endif
-#ifdef XK_dead_diaeresis
- || orig_keysym == XK_dead_diaeresis
-#endif
-#ifdef XK_dead_macron
- || orig_keysym == XK_dead_macron
-#endif
-#ifdef XK_dead_degree
- || orig_keysym == XK_dead_degree
-#endif
-#ifdef XK_dead_acute
- || orig_keysym == XK_dead_acute
-#endif
-#ifdef XK_dead_cedilla
- || orig_keysym == XK_dead_cedilla
-#endif
-#ifdef XK_dead_breve
- || orig_keysym == XK_dead_breve
-#endif
-#ifdef XK_dead_ogonek
- || orig_keysym == XK_dead_ogonek
-#endif
-#ifdef XK_dead_caron
- || orig_keysym == XK_dead_caron
-#endif
-#ifdef XK_dead_doubleacute
- || orig_keysym == XK_dead_doubleacute
-#endif
-#ifdef XK_dead_abovedot
- || orig_keysym == XK_dead_abovedot
-#endif
- || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
- || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
- /* Any "vendor-specific" key is ok. */
- || (orig_keysym & (1 << 28)))
- && ! (IsModifierKey (orig_keysym)
-#ifndef HAVE_X11R5
-#ifdef XK_Mode_switch
- || ((unsigned)(orig_keysym) == XK_Mode_switch)
-#endif
-#ifdef XK_Num_Lock
- || ((unsigned)(orig_keysym) == XK_Num_Lock)
-#endif
-#endif /* not HAVE_X11R5 */
- ))
- {
- if (temp_index == sizeof temp_buffer / sizeof (short))
- temp_index = 0;
- temp_buffer[temp_index++] = keysym;
- bufp->kind = non_ascii_keystroke;
- bufp->code = keysym;
- XSETFRAME (bufp->frame_or_window, f);
- bufp->modifiers
- = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
- modifiers);
- bufp->timestamp = event.xkey.time;
- bufp++;
- count++;
- numchars--;
- }
- else if (numchars > nbytes)
- {
- register int i;
-
- for (i = 0; i < nbytes; i++)
- {
- if (temp_index == sizeof temp_buffer / sizeof (short))
- temp_index = 0;
- temp_buffer[temp_index++] = copy_buffer[i];
- bufp->kind = ascii_keystroke;
- bufp->code = copy_buffer[i];
- XSETFRAME (bufp->frame_or_window, f);
- bufp->modifiers
- = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
- modifiers);
- bufp->timestamp = event.xkey.time;
- bufp++;
- }
-
- count += nbytes;
- numchars -= nbytes;
- }
- else
- abort ();
- }
- else
- abort ();
- }
- goto OTHER;
-
- /* Here's a possible interpretation of the whole
- FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
- FocusIn event, you have to get a FocusOut event before you
- relinquish the focus. If you haven't received a FocusIn event,
- then a mere LeaveNotify is enough to free you. */
-
- case EnterNotify:
- f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
-
- if (event.xcrossing.focus) /* Entered Window */
- {
- /* Avoid nasty pop/raise loops. */
- if (f && (!(f->auto_raise)
- || !(f->auto_lower)
- || (event.xcrossing.time - enter_timestamp) > 500))
- {
- x_new_focus_frame (dpyinfo, f);
- enter_timestamp = event.xcrossing.time;
- }
- }
- else if (f == dpyinfo->x_focus_frame)
- x_new_focus_frame (dpyinfo, 0);
- /* EnterNotify counts as mouse movement,
- so update things that depend on mouse position. */
- if (f)
- note_mouse_movement (f, &event.xmotion);
- goto OTHER;
-
- case FocusIn:
- f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
- if (event.xfocus.detail != NotifyPointer)
- dpyinfo->x_focus_event_frame = f;
- if (f)
- x_new_focus_frame (dpyinfo, f);
-
-#ifdef HAVE_X_I18N
- if (f && FRAME_XIC (f))
- XSetICFocus (FRAME_XIC (f));
-#endif
-
- goto OTHER;
-
- case LeaveNotify:
- f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
- if (f)
- {
- if (f == dpyinfo->mouse_face_mouse_frame)
- /* If we move outside the frame,
- then we're certainly no longer on any text in the frame. */
- clear_mouse_face (dpyinfo);
-
- if (event.xcrossing.focus)
- x_mouse_leave (dpyinfo);
- else
- {
- if (f == dpyinfo->x_focus_event_frame)
- dpyinfo->x_focus_event_frame = 0;
- if (f == dpyinfo->x_focus_frame)
- x_new_focus_frame (dpyinfo, 0);
- }
- }
- goto OTHER;
-
- case FocusOut:
- f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
- if (event.xfocus.detail != NotifyPointer
- && f == dpyinfo->x_focus_event_frame)
- dpyinfo->x_focus_event_frame = 0;
- if (f && f == dpyinfo->x_focus_frame)
- x_new_focus_frame (dpyinfo, 0);
-
-#ifdef HAVE_X_I18N
- if (f && FRAME_XIC (f))
- XUnsetICFocus (FRAME_XIC (f));
-#endif
-
- goto OTHER;
-
- case MotionNotify:
- {
- if (dpyinfo->grabbed && last_mouse_frame
- && FRAME_LIVE_P (last_mouse_frame))
- f = last_mouse_frame;
- else
- f = x_window_to_frame (dpyinfo, event.xmotion.window);
- if (f)
- note_mouse_movement (f, &event.xmotion);
- else
- {
- struct scroll_bar *bar
- = x_window_to_scroll_bar (event.xmotion.window);
-
- if (bar)
- x_scroll_bar_note_movement (bar, &event);
-
- /* If we move outside the frame,
- then we're certainly no longer on any text in the frame. */
- clear_mouse_face (dpyinfo);
- }
- }
- goto OTHER;
-
- case ConfigureNotify:
- f = x_any_window_to_frame (dpyinfo, event.xconfigure.window);
- if (f
-#ifdef USE_X_TOOLKIT
- && (event.xconfigure.window == XtWindow (f->output_data.x->widget))
-#endif
- )
- {
-#ifndef USE_X_TOOLKIT
- /* In the toolkit version, change_frame_size
- is called by the code that handles resizing
- of the EmacsFrame widget. */
-
- int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
- int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
-
- /* Even if the number of character rows and columns has
- not changed, the font size may have changed, so we need
- to check the pixel dimensions as well. */
- if (columns != f->width
- || rows != f->height
- || event.xconfigure.width != f->output_data.x->pixel_width
- || event.xconfigure.height != f->output_data.x->pixel_height)
- {
- change_frame_size (f, rows, columns, 0, 1);
- SET_FRAME_GARBAGED (f);
- cancel_mouse_face (f);
- }
-#endif
-
- /* Formerly, in the USE_X_TOOLKIT version,
- we did not test send_event here. */
- if (1
-#ifndef USE_X_TOOLKIT
- && ! event.xconfigure.send_event
-#endif
- )
- {
- Window win, child;
- int win_x, win_y;
-
- /* Find the position of the outside upper-left corner of
- the window, in the root coordinate system. Don't
- refer to the parent window here; we may be processing
- this event after the window manager has changed our
- parent, but before we have reached the ReparentNotify. */
- XTranslateCoordinates (FRAME_X_DISPLAY (f),
-
- /* From-window, to-window. */
- event.xconfigure.window,
- FRAME_X_DISPLAY_INFO (f)->root_window,
-
- /* From-position, to-position. */
- -event.xconfigure.border_width,
- -event.xconfigure.border_width,
- &win_x, &win_y,
-
- /* Child of win. */
- &child);
- event.xconfigure.x = win_x;
- event.xconfigure.y = win_y;
- }
-
- f->output_data.x->pixel_width = event.xconfigure.width;
- f->output_data.x->pixel_height = event.xconfigure.height;
- f->output_data.x->left_pos = event.xconfigure.x;
- f->output_data.x->top_pos = event.xconfigure.y;
-
- /* What we have now is the position of Emacs's own window.
- Convert that to the position of the window manager window. */
- {
- int x, y;
- x_real_positions (f, &x, &y);
- f->output_data.x->left_pos = x;
- f->output_data.x->top_pos = y;
- /* Formerly we did not do this in the USE_X_TOOLKIT
- version. Let's try making them the same. */
-/* #ifndef USE_X_TOOLKIT */
- if (y != event.xconfigure.y)
- {
- /* Since the WM decorations come below top_pos now,
- we must put them below top_pos in the future. */
- f->output_data.x->win_gravity = NorthWestGravity;
- x_wm_set_size_hint (f, (long) 0, 0);
- }
-/* #endif */
- }
- }
- goto OTHER;
-
- case ButtonPress:
- case ButtonRelease:
- {
- /* If we decide we want to generate an event to be seen
- by the rest of Emacs, we put it here. */
- struct input_event emacs_event;
- emacs_event.kind = no_event;
-
- bzero (&compose_status, sizeof (compose_status));
-
- if (dpyinfo->grabbed && last_mouse_frame
- && FRAME_LIVE_P (last_mouse_frame))
- f = last_mouse_frame;
- else
- f = x_window_to_frame (dpyinfo, event.xbutton.window);
-
- if (f)
- {
- if (!dpyinfo->x_focus_frame || f == dpyinfo->x_focus_frame)
- construct_mouse_click (&emacs_event, &event, f);
- }
- else
- {
- struct scroll_bar *bar
- = x_window_to_scroll_bar (event.xbutton.window);
-
- if (bar)
- x_scroll_bar_handle_click (bar, &event, &emacs_event);
- }
-
- if (event.type == ButtonPress)
- {
- dpyinfo->grabbed |= (1 << event.xbutton.button);
- last_mouse_frame = f;
- }
- else
- {
- dpyinfo->grabbed &= ~(1 << event.xbutton.button);
- }
-
- if (numchars >= 1 && emacs_event.kind != no_event)
- {
- bcopy (&emacs_event, bufp, sizeof (struct input_event));
- bufp++;
- count++;
- numchars--;
- }
-
-#ifdef USE_X_TOOLKIT
- f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
- /* For a down-event in the menu bar,
- don't pass it to Xt right now.
- Instead, save it away
- and we will pass it to Xt from kbd_buffer_get_event.
- That way, we can run some Lisp code first. */
- if (f && event.type == ButtonPress
- /* Verify the event is really within the menu bar
- and not just sent to it due to grabbing. */
- && event.xbutton.x >= 0
- && event.xbutton.x < f->output_data.x->pixel_width
- && event.xbutton.y >= 0
- && event.xbutton.y < f->output_data.x->menubar_height
- && event.xbutton.same_screen)
- {
- SET_SAVED_BUTTON_EVENT;
- XSETFRAME (last_mouse_press_frame, f);
- }
- else if (event.type == ButtonPress)
- {
- last_mouse_press_frame = Qnil;
- goto OTHER;
- }
-#ifdef USE_MOTIF /* This should do not harm for Lucid,
- but I am trying to be cautious. */
- else if (event.type == ButtonRelease)
- {
- if (!NILP (last_mouse_press_frame))
- {
- f = XFRAME (last_mouse_press_frame);
- if (f->output_data.x)
- {
- SET_SAVED_BUTTON_EVENT;
- }
- }
- else
- goto OTHER;
- }
-#endif /* USE_MOTIF */
- else
- goto OTHER;
-#endif /* USE_X_TOOLKIT */
- }
- break;
-
- case CirculateNotify:
- break;
- case CirculateRequest:
- break;
-
- case MappingNotify:
- /* Someone has changed the keyboard mapping - update the
- local cache. */
- switch (event.xmapping.request)
- {
- case MappingModifier:
- x_find_modifier_meanings (dpyinfo);
- /* This is meant to fall through. */
- case MappingKeyboard:
- XRefreshKeyboardMapping (&event.xmapping);
- }
- goto OTHER;
-
- default:
- OTHER:
-#ifdef USE_X_TOOLKIT
- BLOCK_INPUT;
- XtDispatchEvent (&event);
- UNBLOCK_INPUT;
-#endif /* USE_X_TOOLKIT */
- break;
- }
- }
- }
-
- /* On some systems, an X bug causes Emacs to get no more events
- when the window is destroyed. Detect that. (1994.) */
- if (! event_found)
- {
- /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
- One XNOOP in 100 loops will make Emacs terminate.
- B. Bretthauer, 1994 */
- x_noop_count++;
- if (x_noop_count >= 100)
- {
- x_noop_count=0;
-
- if (next_noop_dpyinfo == 0)
- next_noop_dpyinfo = x_display_list;
-
- XNoOp (next_noop_dpyinfo->display);
-
- /* Each time we get here, cycle through the displays now open. */
- next_noop_dpyinfo = next_noop_dpyinfo->next;
- }
- }
-
- /* If the focus was just given to an autoraising frame,
- raise it now. */
- /* ??? This ought to be able to handle more than one such frame. */
- if (pending_autoraise_frame)
- {
- x_raise_frame (pending_autoraise_frame);
- pending_autoraise_frame = 0;
- }
-
- UNBLOCK_INPUT;
- return count;
-}
-
-/* Drawing the cursor. */
-
-
-/* Draw a hollow box cursor on frame F at X, Y.
- Don't change the inside of the box. */
-
-static void
-x_draw_box (f, x, y)
- struct frame *f;
- int x, y;
-{
- int left = CHAR_TO_PIXEL_COL (f, x);
- int top = CHAR_TO_PIXEL_ROW (f, y);
- int width = FONT_WIDTH (f->output_data.x->font);
- int height = f->output_data.x->line_height;
-
- XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->cursor_gc,
- left, top, width - 1, height - 1);
-}
-
-/* Clear the cursor of frame F to background color,
- and mark the cursor as not shown.
- This is used when the text where the cursor is
- is about to be rewritten. */
-
-static void
-clear_cursor (f)
- struct frame *f;
-{
- int mask;
-
- if (! FRAME_VISIBLE_P (f)
- || ! f->phys_cursor_on)
- return;
-
- x_update_cursor (f, 0);
- f->phys_cursor_on = 0;
-}
-
-/* Redraw the glyph at ROW, COLUMN on frame F, in the style
- HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
- glyph drawn. */
-
-static void
-x_draw_single_glyph (f, row, column, glyph, highlight)
- struct frame *f;
- int row, column;
- GLYPH glyph;
- int highlight;
-{
- dumpglyphs (f,
- CHAR_TO_PIXEL_COL (f, column),
- CHAR_TO_PIXEL_ROW (f, row),
- &glyph, 1, highlight, 0);
-}
-
-static void
-x_display_bar_cursor (f, on, x, y)
- struct frame *f;
- int on;
- int x, y;
-{
- struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
-
- /* This is pointless on invisible frames, and dangerous on garbaged
- frames; in the latter case, the frame may be in the midst of
- changing its size, and x and y may be off the frame. */
- if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
- return;
-
- if (! on && ! f->phys_cursor_on)
- return;
-
- /* If there is anything wrong with the current cursor state, remove it. */
- if (f->phys_cursor_on
- && (!on
- || f->phys_cursor_x != x
- || f->phys_cursor_y != y
- || f->output_data.x->current_cursor != bar_cursor))
- {
- /* Erase the cursor by redrawing the character underneath it. */
- x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
- f->phys_cursor_glyph,
- current_glyphs->highlight[f->phys_cursor_y]);
- f->phys_cursor_on = 0;
- }
-
- /* If we now need a cursor in the new place or in the new form, do it so. */
- if (on
- && (! f->phys_cursor_on
- || (f->output_data.x->current_cursor != bar_cursor)))
- {
- f->phys_cursor_glyph
- = ((current_glyphs->enable[y]
- && x < current_glyphs->used[y])
- ? current_glyphs->glyphs[y][x]
- : SPACEGLYPH);
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->cursor_gc,
- CHAR_TO_PIXEL_COL (f, x),
- CHAR_TO_PIXEL_ROW (f, y),
- max (f->output_data.x->cursor_width, 1),
- f->output_data.x->line_height);
-
- f->phys_cursor_x = x;
- f->phys_cursor_y = y;
- f->phys_cursor_on = 1;
-
- f->output_data.x->current_cursor = bar_cursor;
- }
-
- if (updating_frame != f)
- XFlush (FRAME_X_DISPLAY (f));
-}
-
-
-/* Turn the displayed cursor of frame F on or off according to ON.
- If ON is nonzero, where to put the cursor is specified by X and Y. */
-
-static void
-x_display_box_cursor (f, on, x, y)
- struct frame *f;
- int on;
- int x, y;
-{
- struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
-
- /* This is pointless on invisible frames, and dangerous on garbaged
- frames; in the latter case, the frame may be in the midst of
- changing its size, and x and y may be off the frame. */
- if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
- return;
-
- /* If cursor is off and we want it off, return quickly. */
- if (!on && ! f->phys_cursor_on)
- return;
-
- /* If cursor is currently being shown and we don't want it to be
- or it is in the wrong place,
- or we want a hollow box and it's not so, (pout!)
- erase it. */
- if (f->phys_cursor_on
- && (!on
- || f->phys_cursor_x != x
- || f->phys_cursor_y != y
- || (f->output_data.x->current_cursor != hollow_box_cursor
- && (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame))))
- {
- int mouse_face_here = 0;
- struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
-
- /* If the cursor is in the mouse face area, redisplay that when
- we clear the cursor. */
- if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame
- &&
- (f->phys_cursor_y > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
- || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
- && f->phys_cursor_x >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col))
- &&
- (f->phys_cursor_y < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
- || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
- && f->phys_cursor_x < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col))
- /* Don't redraw the cursor's spot in mouse face
- if it is at the end of a line (on a newline).
- The cursor appears there, but mouse highlighting does not. */
- && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x)
- mouse_face_here = 1;
-
- /* If the font is not as tall as a whole line,
- we must explicitly clear the line's whole height. */
- if (FONT_HEIGHT (f->output_data.x->font) != f->output_data.x->line_height)
- XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
- CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
- FONT_WIDTH (f->output_data.x->font),
- f->output_data.x->line_height, False);
- /* Erase the cursor by redrawing the character underneath it. */
- x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
- f->phys_cursor_glyph,
- (mouse_face_here
- ? 3
- : current_glyphs->highlight[f->phys_cursor_y]));
- f->phys_cursor_on = 0;
- }
-
- /* If we want to show a cursor,
- or we want a box cursor and it's not so,
- write it in the right place. */
- if (on
- && (! f->phys_cursor_on
- || (f->output_data.x->current_cursor != filled_box_cursor
- && f == FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)))
- {
- f->phys_cursor_glyph
- = ((current_glyphs->enable[y]
- && x < current_glyphs->used[y])
- ? current_glyphs->glyphs[y][x]
- : SPACEGLYPH);
- if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
- {
- x_draw_box (f, x, y);
- f->output_data.x->current_cursor = hollow_box_cursor;
- }
- else
- {
- x_draw_single_glyph (f, y, x,
- f->phys_cursor_glyph, 2);
- f->output_data.x->current_cursor = filled_box_cursor;
- }
-
- f->phys_cursor_x = x;
- f->phys_cursor_y = y;
- f->phys_cursor_on = 1;
- }
-
- if (updating_frame != f)
- XFlush (FRAME_X_DISPLAY (f));
-}
-
-/* Display the cursor on frame F, or clear it, according to ON.
- Also set the frame's cursor position to X and Y. */
-
-x_display_cursor (f, on, x, y)
- struct frame *f;
- int on;
- int x, y;
-{
- BLOCK_INPUT;
-
- if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
- x_display_box_cursor (f, on, x, y);
- else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
- x_display_bar_cursor (f, on, x, y);
- else
- /* Those are the only two we have implemented! */
- abort ();
-
- UNBLOCK_INPUT;
-}
-
-/* Display the cursor on frame F, or clear it, according to ON.
- Don't change the cursor's position. */
-
-x_update_cursor (f, on)
- struct frame *f;
- int on;
-{
- BLOCK_INPUT;
-
- if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
- x_display_box_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
- else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
- x_display_bar_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
- else
- /* Those are the only two we have implemented! */
- abort ();
-
- UNBLOCK_INPUT;
-}
-
-/* Icons. */
-
-/* Refresh bitmap kitchen sink icon for frame F
- when we get an expose event for it. */
-
-refreshicon (f)
- struct frame *f;
-{
- /* Normally, the window manager handles this function. */
-}
-
-/* Make the x-window of frame F use the gnu icon bitmap. */
-
-int
-x_bitmap_icon (f, file)
- struct frame *f;
- Lisp_Object file;
-{
- int mask, bitmap_id;
- Window icon_window;
-
- if (FRAME_X_WINDOW (f) == 0)
- return 1;
-
- /* Free up our existing icon bitmap if any. */
- if (f->output_data.x->icon_bitmap > 0)
- x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
- f->output_data.x->icon_bitmap = 0;
-
- if (STRINGP (file))
- bitmap_id = x_create_bitmap_from_file (f, file);
- else
- {
- /* Create the GNU bitmap if necessary. */
- if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
- FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
- = x_create_bitmap_from_data (f, gnu_bits,
- gnu_width, gnu_height);
-
- /* The first time we create the GNU bitmap,
- this increments the refcount one extra time.
- As a result, the GNU bitmap is never freed.
- That way, we don't have to worry about allocating it again. */
- x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
-
- bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
- }
-
- x_wm_set_icon_pixmap (f, bitmap_id);
- f->output_data.x->icon_bitmap = bitmap_id;
-
- return 0;
-}
-
-
-/* Make the x-window of frame F use a rectangle with text.
- Use ICON_NAME as the text. */
-
-int
-x_text_icon (f, icon_name)
- struct frame *f;
- char *icon_name;
-{
- if (FRAME_X_WINDOW (f) == 0)
- return 1;
-
-#ifdef HAVE_X11R4
- {
- XTextProperty text;
- text.value = (unsigned char *) icon_name;
- text.encoding = XA_STRING;
- text.format = 8;
- text.nitems = strlen (icon_name);
-#ifdef USE_X_TOOLKIT
- XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
- &text);
-#else /* not USE_X_TOOLKIT */
- XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
-#endif /* not USE_X_TOOLKIT */
- }
-#else /* not HAVE_X11R4 */
- XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
-#endif /* not HAVE_X11R4 */
-
- if (f->output_data.x->icon_bitmap > 0)
- x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
- f->output_data.x->icon_bitmap = 0;
- x_wm_set_icon_pixmap (f, 0);
-
- return 0;
-}
-
-/* Handling X errors. */
-
-/* Handle the loss of connection to display DISPLAY. */
-
-static SIGTYPE
-x_connection_closed (display, error_message)
- Display *display;
- char *error_message;
-{
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
- Lisp_Object frame, tail;
-
- /* Indicate that this display is dead. */
-
- #ifdef USE_X_TOOLKIT
- XtCloseDisplay (display);
- #endif
-
- dpyinfo->display = 0;
-
- /* First delete frames whose minibuffers are on frames
- that are on the dead display. */
- FOR_EACH_FRAME (tail, frame)
- {
- Lisp_Object minibuf_frame;
- minibuf_frame
- = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
- if (FRAME_X_P (XFRAME (frame))
- && FRAME_X_P (XFRAME (minibuf_frame))
- && ! EQ (frame, minibuf_frame)
- && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
- Fdelete_frame (frame, Qt);
- }
-
- /* Now delete all remaining frames on the dead display.
- We are now sure none of these is used as the minibuffer
- for another frame that we need to delete. */
- FOR_EACH_FRAME (tail, frame)
- if (FRAME_X_P (XFRAME (frame))
- && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
- {
- /* Set this to t so that Fdelete_frame won't get confused
- trying to find a replacement. */
- FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
- Fdelete_frame (frame, Qt);
- }
-
- if (dpyinfo)
- x_delete_display (dpyinfo);
-
- if (x_display_list == 0)
- {
- fprintf (stderr, "%s\n", error_message);
- shut_down_emacs (0, 0, Qnil);
- exit (70);
- }
-
- /* Ordinary stack unwind doesn't deal with these. */
-#ifdef SIGIO
- sigunblock (sigmask (SIGIO));
-#endif
- sigunblock (sigmask (SIGALRM));
- TOTALLY_UNBLOCK_INPUT;
-
- clear_waiting_for_input ();
- error ("%s", error_message);
-}
-
-/* This is the usual handler for X protocol errors.
- It kills all frames on the display that we got the error for.
- If that was the only one, it prints an error message and kills Emacs. */
-
-static int
-x_error_quitter (display, error)
- Display *display;
- XErrorEvent *error;
-{
- char buf[256], buf1[356];
-
- /* Note that there is no real way portable across R3/R4 to get the
- original error handler. */
-
- XGetErrorText (display, error->error_code, buf, sizeof (buf));
- sprintf (buf1, "X protocol error: %s on protocol request %d",
- buf, error->request_code);
- x_connection_closed (display, buf1);
-}
-
-/* This is the handler for X IO errors, always.
- It kills all frames on the display that we lost touch with.
- If that was the only one, it prints an error message and kills Emacs. */
-
-static int
-x_io_error_quitter (display)
- Display *display;
-{
- char buf[256];
-
- sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
- x_connection_closed (display, buf);
-}
-
-/* Handle SIGPIPE, which can happen when the connection to a server
- simply goes away. SIGPIPE is handled by x_connection_signal.
- Don't need to do anything, because the write which caused the
- SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
- which will do the appropriate cleanup for us. */
-
-static SIGTYPE
-x_connection_signal (signalnum) /* If we don't have an argument, */
- int signalnum; /* some compilers complain in signal calls. */
-{
-#ifdef USG
- /* USG systems forget handlers when they are used;
- must reestablish each time */
- signal (signalnum, x_connection_signal);
-#endif /* USG */
-}
-
-/* A buffer for storing X error messages. */
-static char *x_caught_error_message;
-#define X_CAUGHT_ERROR_MESSAGE_SIZE 200
-
-/* An X error handler which stores the error message in
- x_caught_error_message. This is what's installed when
- x_catch_errors is in effect. */
-
-static int
-x_error_catcher (display, error)
- Display *display;
- XErrorEvent *error;
-{
- XGetErrorText (display, error->error_code,
- x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE);
-}
-
-
-/* Begin trapping X errors for display DPY. Actually we trap X errors
- for all displays, but DPY should be the display you are actually
- operating on.
-
- After calling this function, X protocol errors no longer cause
- Emacs to exit; instead, they are recorded in x_cfc_error_message.
-
- Calling x_check_errors signals an Emacs error if an X error has
- occurred since the last call to x_catch_errors or x_check_errors.
-
- Calling x_uncatch_errors resumes the normal error handling. */
-
-void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
-
-void
-x_catch_errors (dpy)
- Display *dpy;
-{
- /* Make sure any errors from previous requests have been dealt with. */
- XSync (dpy, False);
-
- /* Set up the error buffer. */
- x_caught_error_message
- = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE);
- x_caught_error_message[0] = '\0';
-
- /* Install our little error handler. */
- XSetErrorHandler (x_error_catcher);
-}
-
-/* If any X protocol errors have arrived since the last call to
- x_catch_errors or x_check_errors, signal an Emacs error using
- sprintf (a buffer, FORMAT, the x error message text) as the text. */
-
-void
-x_check_errors (dpy, format)
- Display *dpy;
- char *format;
-{
- /* Make sure to catch any errors incurred so far. */
- XSync (dpy, False);
-
- if (x_caught_error_message[0])
- {
- char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56];
-
- sprintf (buf, format, x_caught_error_message);
- x_uncatch_errors (dpy);
- error (buf);
- }
-}
-
-/* Nonzero if we had any X protocol errors since we did x_catch_errors. */
-
-int
-x_had_errors_p (dpy)
- Display *dpy;
-{
- /* Make sure to catch any errors incurred so far. */
- XSync (dpy, False);
-
- return x_caught_error_message[0] != 0;
-}
-
-/* Stop catching X protocol errors and let them make Emacs die. */
-
-void
-x_uncatch_errors (dpy)
- Display *dpy;
-{
- xfree (x_caught_error_message);
- x_caught_error_message = 0;
- XSetErrorHandler (x_error_quitter);
-}
-
-#if 0
-static unsigned int x_wire_count;
-x_trace_wire ()
-{
- fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
-}
-#endif /* ! 0 */
-
-
-/* Changing the font of the frame. */
-
-/* Give frame F the font named FONTNAME as its default font, and
- return the full name of that font. FONTNAME may be a wildcard
- pattern; in that case, we choose some font that fits the pattern.
- The return value shows which font we chose. */
-
-Lisp_Object
-x_new_font (f, fontname)
- struct frame *f;
- register char *fontname;
-{
- int already_loaded;
- int n_matching_fonts;
- XFontStruct *font_info;
- char **font_names;
-
- /* Get a list of all the fonts that match this name. Once we
- have a list of matching fonts, we compare them against the fonts
- we already have by comparing font ids. */
- font_names = (char **) XListFonts (FRAME_X_DISPLAY (f), fontname,
- 1024, &n_matching_fonts);
- /* Apparently it doesn't set n_matching_fonts to zero when it can't
- find any matches; font_names == 0 is the only clue. */
- if (! font_names)
- n_matching_fonts = 0;
-
- /* Don't just give up if n_matching_fonts is 0.
- Apparently there's a bug on Suns: XListFontsWithInfo can
- fail to find a font, but XLoadQueryFont may still find it. */
-
- /* See if we've already loaded a matching font. */
- already_loaded = -1;
- if (n_matching_fonts != 0)
- {
- int i, j;
-
- for (i = 0; i < FRAME_X_DISPLAY_INFO (f)->n_fonts; i++)
- for (j = 0; j < n_matching_fonts; j++)
- if (!strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].name, font_names[j])
- || !strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name, font_names[j]))
- {
- already_loaded = i;
- fontname = FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name;
- goto found_font;
- }
- }
- found_font:
-
- /* If we have, just return it from the table. */
- if (already_loaded >= 0)
- f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[already_loaded].font;
- /* Otherwise, load the font and add it to the table. */
- else
- {
- int i;
- char *full_name;
- XFontStruct *font;
- int n_fonts;
-
- /* Try to find a character-cell font in the list. */
-#if 0
- /* A laudable goal, but this isn't how to do it. */
- for (i = 0; i < n_matching_fonts; i++)
- if (! font_info[i].per_char)
- break;
-#else
- i = 0;
-#endif
-
- /* See comment above. */
- if (n_matching_fonts != 0)
- fontname = font_names[i];
-
- font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
- if (! font)
- {
- /* Free the information from XListFonts. */
- if (n_matching_fonts)
- XFreeFontNames (font_names);
- return Qnil;
- }
-
- /* Do we need to create the table? */
- if (FRAME_X_DISPLAY_INFO (f)->font_table_size == 0)
- {
- FRAME_X_DISPLAY_INFO (f)->font_table_size = 16;
- FRAME_X_DISPLAY_INFO (f)->font_table
- = (struct font_info *) xmalloc (FRAME_X_DISPLAY_INFO (f)->font_table_size
- * sizeof (struct font_info));
- }
- /* Do we need to grow the table? */
- else if (FRAME_X_DISPLAY_INFO (f)->n_fonts
- >= FRAME_X_DISPLAY_INFO (f)->font_table_size)
- {
- FRAME_X_DISPLAY_INFO (f)->font_table_size *= 2;
- FRAME_X_DISPLAY_INFO (f)->font_table
- = (struct font_info *) xrealloc (FRAME_X_DISPLAY_INFO (f)->font_table,
- (FRAME_X_DISPLAY_INFO (f)->font_table_size
- * sizeof (struct font_info)));
- }
-
- /* Try to get the full name of FONT. Put it in full_name. */
- full_name = 0;
- for (i = 0; i < font->n_properties; i++)
- {
- if (FRAME_X_DISPLAY_INFO (f)->Xatom_FONT == font->properties[i].name)
- {
- char *name = XGetAtomName (FRAME_X_DISPLAY (f),
- (Atom) (font->properties[i].card32));
- char *p = name;
- int dashes = 0;
-
- /* Count the number of dashes in the "full name".
- If it is too few, this isn't really the font's full name,
- so don't use it.
- In X11R4, the fonts did not come with their canonical names
- stored in them. */
- while (*p)
- {
- if (*p == '-')
- dashes++;
- p++;
- }
-
- if (dashes >= 13)
- full_name = name;
-
- break;
- }
- }
-
- n_fonts = FRAME_X_DISPLAY_INFO (f)->n_fonts;
- FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
- bcopy (fontname, FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
- if (full_name != 0)
- FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = full_name;
- else
- FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name;
- f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
- FRAME_X_DISPLAY_INFO (f)->n_fonts++;
-
- if (full_name)
- fontname = full_name;
- }
-
- /* Compute the scroll bar width in character columns. */
- if (f->scroll_bar_pixel_width > 0)
- {
- int wid = FONT_WIDTH (f->output_data.x->font);
- f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
- }
- else
- f->scroll_bar_cols = 2;
-
- /* Now make the frame display the given font. */
- if (FRAME_X_WINDOW (f) != 0)
- {
- XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
- f->output_data.x->font->fid);
- XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
- f->output_data.x->font->fid);
- XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
- f->output_data.x->font->fid);
-
- frame_update_line_height (f);
- x_set_window_size (f, 0, f->width, f->height);
- }
- else
- /* If we are setting a new frame's font for the first time,
- there are no faces yet, so this font's height is the line height. */
- f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
-
- {
- Lisp_Object lispy_name;
-
- lispy_name = build_string (fontname);
-
- /* Free the information from XListFonts. The data
- we actually retain comes from XLoadQueryFont. */
- XFreeFontNames (font_names);
-
- return lispy_name;
- }
-}
-
-/* Calculate the absolute position in frame F
- from its current recorded position values and gravity. */
-
-x_calc_absolute_position (f)
- struct frame *f;
-{
- Window win, child;
- int win_x = 0, win_y = 0;
- int flags = f->output_data.x->size_hint_flags;
- int this_window;
-
-#ifdef USE_X_TOOLKIT
- this_window = XtWindow (f->output_data.x->widget);
-#else
- this_window = FRAME_X_WINDOW (f);
-#endif
-
- /* Find the position of the outside upper-left corner of
- the inner window, with respect to the outer window. */
- if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
- {
- BLOCK_INPUT;
- XTranslateCoordinates (FRAME_X_DISPLAY (f),
-
- /* From-window, to-window. */
- this_window,
- f->output_data.x->parent_desc,
-
- /* From-position, to-position. */
- 0, 0, &win_x, &win_y,
-
- /* Child of win. */
- &child);
- UNBLOCK_INPUT;
- }
-
- /* Treat negative positions as relative to the leftmost bottommost
- position that fits on the screen. */
- if (flags & XNegative)
- f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
- - 2 * f->output_data.x->border_width - win_x
- - PIXEL_WIDTH (f)
- + f->output_data.x->left_pos);
-
- if (flags & YNegative)
- /* We used to subtract f->output_data.x->menubar_height here
- in the toolkit case, but PIXEL_HEIGHT already includes that. */
- f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
- - 2 * f->output_data.x->border_width - win_y
- - PIXEL_HEIGHT (f)
- + f->output_data.x->top_pos);
-
- /* The left_pos and top_pos
- are now relative to the top and left screen edges,
- so the flags should correspond. */
- f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
-}
-
-/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
- to really change the position, and 0 when calling from
- x_make_frame_visible (in that case, XOFF and YOFF are the current
- position values). It is -1 when calling from x_set_frame_parameters,
- which means, do adjust for borders but don't change the gravity. */
-
-x_set_offset (f, xoff, yoff, change_gravity)
- struct frame *f;
- register int xoff, yoff;
- int change_gravity;
-{
- int modified_top, modified_left;
-
- if (change_gravity > 0)
- {
- f->output_data.x->top_pos = yoff;
- f->output_data.x->left_pos = xoff;
- f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
- if (xoff < 0)
- f->output_data.x->size_hint_flags |= XNegative;
- if (yoff < 0)
- f->output_data.x->size_hint_flags |= YNegative;
- f->output_data.x->win_gravity = NorthWestGravity;
- }
- x_calc_absolute_position (f);
-
- BLOCK_INPUT;
- x_wm_set_size_hint (f, (long) 0, 0);
-
- /* It is a mystery why we need to add the border_width here
- when the frame is already visible, but experiment says we do. */
- modified_left = f->output_data.x->left_pos;
- modified_top = f->output_data.x->top_pos;
- if (change_gravity != 0)
- {
- modified_left += f->output_data.x->border_width;
- modified_top += f->output_data.x->border_width;
- }
-
-#ifdef USE_X_TOOLKIT
- XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
- modified_left, modified_top);
-#else /* not USE_X_TOOLKIT */
- XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- modified_left, modified_top);
-#endif /* not USE_X_TOOLKIT */
- UNBLOCK_INPUT;
-}
-
-/* Call this to change the size of frame F's x-window.
- If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
- for this size change and subsequent size changes.
- Otherwise we leave the window gravity unchanged. */
-
-x_set_window_size (f, change_gravity, cols, rows)
- struct frame *f;
- int change_gravity;
- int cols, rows;
-{
- int pixelwidth, pixelheight;
- int mask;
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-
- BLOCK_INPUT;
-
-#ifdef USE_X_TOOLKIT
- {
- /* The x and y position of the widget is clobbered by the
- call to XtSetValues within EmacsFrameSetCharSize.
- This is a real kludge, but I don't understand Xt so I can't
- figure out a correct fix. Can anyone else tell me? -- rms. */
- int xpos = f->output_data.x->widget->core.x;
- int ypos = f->output_data.x->widget->core.y;
- EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
- f->output_data.x->widget->core.x = xpos;
- f->output_data.x->widget->core.y = ypos;
- }
-
-#else /* not USE_X_TOOLKIT */
-
- check_frame_size (f, &rows, &cols);
- f->output_data.x->vertical_scroll_bar_extra
- = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
- ? 0
- : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
- ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
- : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
- pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
- pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
-
- f->output_data.x->win_gravity = NorthWestGravity;
- x_wm_set_size_hint (f, (long) 0, 0);
-
- XSync (FRAME_X_DISPLAY (f), False);
- XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- pixelwidth, pixelheight);
-
- /* Now, strictly speaking, we can't be sure that this is accurate,
- but the window manager will get around to dealing with the size
- change request eventually, and we'll hear how it went when the
- ConfigureNotify event gets here.
-
- We could just not bother storing any of this information here,
- and let the ConfigureNotify event set everything up, but that
- might be kind of confusing to the lisp code, since size changes
- wouldn't be reported in the frame parameters until some random
- point in the future when the ConfigureNotify event arrives. */
- change_frame_size (f, rows, cols, 0, 0);
- PIXEL_WIDTH (f) = pixelwidth;
- PIXEL_HEIGHT (f) = pixelheight;
-
- /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
- receive in the ConfigureNotify event; if we get what we asked
- for, then the event won't cause the screen to become garbaged, so
- we have to make sure to do it here. */
- SET_FRAME_GARBAGED (f);
-
- XFlush (FRAME_X_DISPLAY (f));
-
-#endif /* not USE_X_TOOLKIT */
-
- /* If cursor was outside the new size, mark it as off. */
- if (f->phys_cursor_y >= rows
- || f->phys_cursor_x >= cols)
- {
- f->phys_cursor_x = 0;
- f->phys_cursor_y = 0;
- f->phys_cursor_on = 0;
- }
-
- /* Clear out any recollection of where the mouse highlighting was,
- since it might be in a place that's outside the new frame size.
- Actually checking whether it is outside is a pain in the neck,
- so don't try--just let the highlighting be done afresh with new size. */
- cancel_mouse_face (f);
-
- UNBLOCK_INPUT;
-}
-
-/* Mouse warping. */
-
-void
-x_set_mouse_position (f, x, y)
- struct frame *f;
- int x, y;
-{
- int pix_x, pix_y;
-
- pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
- pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
-
- if (pix_x < 0) pix_x = 0;
- if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
-
- if (pix_y < 0) pix_y = 0;
- if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
-
- BLOCK_INPUT;
-
- XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
- 0, 0, 0, 0, pix_x, pix_y);
- UNBLOCK_INPUT;
-}
-
-/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
-
-void
-x_set_mouse_pixel_position (f, pix_x, pix_y)
- struct frame *f;
- int pix_x, pix_y;
-{
- BLOCK_INPUT;
-
- XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
- 0, 0, 0, 0, pix_x, pix_y);
- UNBLOCK_INPUT;
-}
-
-/* focus shifting, raising and lowering. */
-
-x_focus_on_frame (f)
- struct frame *f;
-{
-#if 0 /* This proves to be unpleasant. */
- x_raise_frame (f);
-#endif
-#if 0
- /* I don't think that the ICCCM allows programs to do things like this
- without the interaction of the window manager. Whatever you end up
- doing with this code, do it to x_unfocus_frame too. */
- XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- RevertToPointerRoot, CurrentTime);
-#endif /* ! 0 */
-}
-
-x_unfocus_frame (f)
- struct frame *f;
-{
-#if 0
- /* Look at the remarks in x_focus_on_frame. */
- if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
- XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
- RevertToPointerRoot, CurrentTime);
-#endif /* ! 0 */
-}
-
-/* Raise frame F. */
-
-x_raise_frame (f)
- struct frame *f;
-{
- if (f->async_visible)
- {
- BLOCK_INPUT;
-#ifdef USE_X_TOOLKIT
- XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
-#else /* not USE_X_TOOLKIT */
- XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-#endif /* not USE_X_TOOLKIT */
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
- }
-}
-
-/* Lower frame F. */
-
-x_lower_frame (f)
- struct frame *f;
-{
- if (f->async_visible)
- {
- BLOCK_INPUT;
-#ifdef USE_X_TOOLKIT
- XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
-#else /* not USE_X_TOOLKIT */
- XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-#endif /* not USE_X_TOOLKIT */
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
- }
-}
-
-static void
-XTframe_raise_lower (f, raise_flag)
- FRAME_PTR f;
- int raise_flag;
-{
- if (raise_flag)
- x_raise_frame (f);
- else
- x_lower_frame (f);
-}
-
-/* Change of visibility. */
-
-/* This tries to wait until the frame is really visible.
- However, if the window manager asks the user where to position
- the frame, this will return before the user finishes doing that.
- The frame will not actually be visible at that time,
- but it will become visible later when the window manager
- finishes with it. */
-
-x_make_frame_visible (f)
- struct frame *f;
-{
- int mask;
- Lisp_Object type;
-
- BLOCK_INPUT;
-
- type = x_icon_type (f);
- if (!NILP (type))
- x_bitmap_icon (f, type);
-
- if (! FRAME_VISIBLE_P (f))
- {
- /* We test FRAME_GARBAGED_P here to make sure we don't
- call x_set_offset a second time
- if we get to x_make_frame_visible a second time
- before the window gets really visible. */
- if (! FRAME_ICONIFIED_P (f)
- && ! f->output_data.x->asked_for_visible)
- x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
-
- f->output_data.x->asked_for_visible = 1;
-
- if (! EQ (Vx_no_window_manager, Qt))
- x_wm_set_window_state (f, NormalState);
-#ifdef USE_X_TOOLKIT
- /* This was XtPopup, but that did nothing for an iconified frame. */
- XtMapWidget (f->output_data.x->widget);
-#else /* not USE_X_TOOLKIT */
- XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-#endif /* not USE_X_TOOLKIT */
-#if 0 /* This seems to bring back scroll bars in the wrong places
- if the window configuration has changed. They seem
- to come back ok without this. */
- if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-#endif
- }
-
- XFlush (FRAME_X_DISPLAY (f));
-
- /* Synchronize to ensure Emacs knows the frame is visible
- before we do anything else. We do this loop with input not blocked
- so that incoming events are handled. */
- {
- Lisp_Object frame;
- int count = input_signal_count;
-
- /* This must come after we set COUNT. */
- UNBLOCK_INPUT;
-
- XSETFRAME (frame, f);
-
- while (1)
- {
- x_sync (f);
- /* Once we have handled input events,
- we should have received the MapNotify if one is coming.
- So if we have not got it yet, stop looping.
- Some window managers make their own decisions
- about visibility. */
- if (input_signal_count != count)
- break;
- /* Machines that do polling rather than SIGIO have been observed
- to go into a busy-wait here. So we'll fake an alarm signal
- to let the handler know that there's something to be read.
- We used to raise a real alarm, but it seems that the handler
- isn't always enabled here. This is probably a bug. */
- if (input_polling_used ())
- {
- /* It could be confusing if a real alarm arrives while processing
- the fake one. Turn it off and let the handler reset it. */
- alarm (0);
- input_poll_signal ();
- }
- /* Once we have handled input events,
- we should have received the MapNotify if one is coming.
- So if we have not got it yet, stop looping.
- Some window managers make their own decisions
- about visibility. */
- if (input_signal_count != count)
- break;
- }
- FRAME_SAMPLE_VISIBILITY (f);
- }
-}
-
-/* Change from mapped state to withdrawn state. */
-
-/* Make the frame visible (mapped and not iconified). */
-
-x_make_frame_invisible (f)
- struct frame *f;
-{
- int mask;
- Window window;
-
-#ifdef USE_X_TOOLKIT
- /* Use the frame's outermost window, not the one we normally draw on. */
- window = XtWindow (f->output_data.x->widget);
-#else /* not USE_X_TOOLKIT */
- window = FRAME_X_WINDOW (f);
-#endif /* not USE_X_TOOLKIT */
-
- /* Don't keep the highlight on an invisible frame. */
- if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
- FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
-
-#if 0/* This might add unreliability; I don't trust it -- rms. */
- if (! f->async_visible && ! f->async_iconified)
- return;
-#endif
-
- BLOCK_INPUT;
-
- /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
- that the current position of the window is user-specified, rather than
- program-specified, so that when the window is mapped again, it will be
- placed at the same location, without forcing the user to position it
- by hand again (they have already done that once for this window.) */
- x_wm_set_size_hint (f, (long) 0, 1);
-
-#ifdef HAVE_X11R4
-
- if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
- DefaultScreen (FRAME_X_DISPLAY (f))))
- {
- UNBLOCK_INPUT_RESIGNAL;
- error ("Can't notify window manager of window withdrawal");
- }
-#else /* ! defined (HAVE_X11R4) */
-
- /* Tell the window manager what we're going to do. */
- if (! EQ (Vx_no_window_manager, Qt))
- {
- XEvent unmap;
-
- unmap.xunmap.type = UnmapNotify;
- unmap.xunmap.window = window;
- unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
- unmap.xunmap.from_configure = False;
- if (! XSendEvent (FRAME_X_DISPLAY (f),
- DefaultRootWindow (FRAME_X_DISPLAY (f)),
- False,
- SubstructureRedirectMask|SubstructureNotifyMask,
- &unmap))
- {
- UNBLOCK_INPUT_RESIGNAL;
- error ("Can't notify window manager of withdrawal");
- }
- }
-
- /* Unmap the window ourselves. Cheeky! */
- XUnmapWindow (FRAME_X_DISPLAY (f), window);
-#endif /* ! defined (HAVE_X11R4) */
-
- /* We can't distinguish this from iconification
- just by the event that we get from the server.
- So we can't win using the usual strategy of letting
- FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
- and synchronize with the server to make sure we agree. */
- f->visible = 0;
- FRAME_ICONIFIED_P (f) = 0;
- f->async_visible = 0;
- f->async_iconified = 0;
-
- x_sync (f);
-
- UNBLOCK_INPUT;
-}
-
-/* Change window state from mapped to iconified. */
-
-x_iconify_frame (f)
- struct frame *f;
-{
- int mask;
- int result;
- Lisp_Object type;
-
- /* Don't keep the highlight on an invisible frame. */
- if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
- FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
-
- if (f->async_iconified)
- return;
-
- BLOCK_INPUT;
-
- FRAME_SAMPLE_VISIBILITY (f);
-
- type = x_icon_type (f);
- if (!NILP (type))
- x_bitmap_icon (f, type);
-
-#ifdef USE_X_TOOLKIT
-
- if (! FRAME_VISIBLE_P (f))
- {
- if (! EQ (Vx_no_window_manager, Qt))
- x_wm_set_window_state (f, IconicState);
- /* This was XtPopup, but that did nothing for an iconified frame. */
- XtMapWidget (f->output_data.x->widget);
- /* The server won't give us any event to indicate
- that an invisible frame was changed to an icon,
- so we have to record it here. */
- f->iconified = 1;
- f->visible = 1;
- f->async_iconified = 1;
- f->async_visible = 0;
- UNBLOCK_INPUT;
- return;
- }
-
- result = XIconifyWindow (FRAME_X_DISPLAY (f),
- XtWindow (f->output_data.x->widget),
- DefaultScreen (FRAME_X_DISPLAY (f)));
- UNBLOCK_INPUT;
-
- if (!result)
- error ("Can't notify window manager of iconification");
-
- f->async_iconified = 1;
- f->async_visible = 0;
-
-
- BLOCK_INPUT;
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-#else /* not USE_X_TOOLKIT */
-
- /* Make sure the X server knows where the window should be positioned,
- in case the user deiconifies with the window manager. */
- if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
- x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
-
- /* Since we don't know which revision of X we're running, we'll use both
- the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
-
- /* X11R4: send a ClientMessage to the window manager using the
- WM_CHANGE_STATE type. */
- {
- XEvent message;
-
- message.xclient.window = FRAME_X_WINDOW (f);
- message.xclient.type = ClientMessage;
- message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
- message.xclient.format = 32;
- message.xclient.data.l[0] = IconicState;
-
- if (! XSendEvent (FRAME_X_DISPLAY (f),
- DefaultRootWindow (FRAME_X_DISPLAY (f)),
- False,
- SubstructureRedirectMask | SubstructureNotifyMask,
- &message))
- {
- UNBLOCK_INPUT_RESIGNAL;
- error ("Can't notify window manager of iconification");
- }
- }
-
- /* X11R3: set the initial_state field of the window manager hints to
- IconicState. */
- x_wm_set_window_state (f, IconicState);
-
- if (!FRAME_VISIBLE_P (f))
- {
- /* If the frame was withdrawn, before, we must map it. */
- XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
- }
-
- f->async_iconified = 1;
- f->async_visible = 0;
-
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-#endif /* not USE_X_TOOLKIT */
-}
-
-/* Destroy the X window of frame F. */
-
-x_destroy_window (f)
- struct frame *f;
-{
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-
- BLOCK_INPUT;
-
- /* If a display connection is dead, don't try sending more
- commands to the X server. */
- if (dpyinfo->display != 0)
- {
- if (f->output_data.x->icon_desc != 0)
- XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
-#ifdef HAVE_X_I18N
- if (FRAME_XIM (f))
- {
- XDestroyIC (FRAME_XIC (f));
-#if ! defined (SOLARIS2) || defined (HAVE_X11R6)
- /* This line causes crashes on Solaris with Openwin,
- due to an apparent bug in XCloseIM.
- X11R6 seems not to have the bug. */
- XCloseIM (FRAME_XIM (f));
-#endif
- }
-#endif
- XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
-#ifdef USE_X_TOOLKIT
- XtDestroyWidget (f->output_data.x->widget);
- free_frame_menubar (f);
-#endif /* USE_X_TOOLKIT */
-
- free_frame_faces (f);
- XFlush (FRAME_X_DISPLAY (f));
- }
-
- xfree (f->output_data.x);
- f->output_data.x = 0;
- if (f == dpyinfo->x_focus_frame)
- dpyinfo->x_focus_frame = 0;
- if (f == dpyinfo->x_focus_event_frame)
- dpyinfo->x_focus_event_frame = 0;
- if (f == dpyinfo->x_highlight_frame)
- dpyinfo->x_highlight_frame = 0;
-
- dpyinfo->reference_count--;
-
- if (f == dpyinfo->mouse_face_mouse_frame)
- {
- dpyinfo->mouse_face_beg_row
- = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row
- = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
- }
-
- UNBLOCK_INPUT;
-}
-
-/* Setting window manager hints. */
-
-/* Set the normal size hints for the window manager, for frame F.
- FLAGS is the flags word to use--or 0 meaning preserve the flags
- that the window now has.
- If USER_POSITION is nonzero, we set the USPosition
- flag (this is useful when FLAGS is 0). */
-
-x_wm_set_size_hint (f, flags, user_position)
- struct frame *f;
- long flags;
- int user_position;
-{
- XSizeHints size_hints;
-
-#ifdef USE_X_TOOLKIT
- Arg al[2];
- int ac = 0;
- Dimension widget_width, widget_height;
- Window window = XtWindow (f->output_data.x->widget);
-#else /* not USE_X_TOOLKIT */
- Window window = FRAME_X_WINDOW (f);
-#endif /* not USE_X_TOOLKIT */
-
- /* Setting PMaxSize caused various problems. */
- size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
-
- flexlines = f->height;
-
- size_hints.x = f->output_data.x->left_pos;
- size_hints.y = f->output_data.x->top_pos;
-
-#ifdef USE_X_TOOLKIT
- XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
- XtSetArg (al[ac], XtNheight, &widget_height); ac++;
- XtGetValues (f->output_data.x->widget, al, ac);
- size_hints.height = widget_height;
- size_hints.width = widget_width;
-#else /* not USE_X_TOOLKIT */
- size_hints.height = PIXEL_HEIGHT (f);
- size_hints.width = PIXEL_WIDTH (f);
-#endif /* not USE_X_TOOLKIT */
-
- size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
- size_hints.height_inc = f->output_data.x->line_height;
- size_hints.max_width
- = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
- size_hints.max_height
- = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
-
- /* Calculate the base and minimum sizes.
-
- (When we use the X toolkit, we don't do it here.
- Instead we copy the values that the widgets are using, below.) */
-#ifndef USE_X_TOOLKIT
- {
- int base_width, base_height;
- int min_rows = 0, min_cols = 0;
-
- base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
- base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
-
- check_frame_size (f, &min_rows, &min_cols);
-
- /* The window manager uses the base width hints to calculate the
- current number of rows and columns in the frame while
- resizing; min_width and min_height aren't useful for this
- purpose, since they might not give the dimensions for a
- zero-row, zero-column frame.
-
- We use the base_width and base_height members if we have
- them; otherwise, we set the min_width and min_height members
- to the size for a zero x zero frame. */
-
-#ifdef HAVE_X11R4
- size_hints.flags |= PBaseSize;
- size_hints.base_width = base_width;
- size_hints.base_height = base_height;
- size_hints.min_width = base_width + min_cols * size_hints.width_inc;
- size_hints.min_height = base_height + min_rows * size_hints.height_inc;
-#else
- size_hints.min_width = base_width;
- size_hints.min_height = base_height;
-#endif
- }
-
- /* If we don't need the old flags, we don't need the old hint at all. */
- if (flags)
- {
- size_hints.flags |= flags;
- goto no_read;
- }
-#endif /* not USE_X_TOOLKIT */
-
- {
- XSizeHints hints; /* Sometimes I hate X Windows... */
- long supplied_return;
- int value;
-
-#ifdef HAVE_X11R4
- value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
- &supplied_return);
-#else
- value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
-#endif
-
-#ifdef USE_X_TOOLKIT
- size_hints.base_height = hints.base_height;
- size_hints.base_width = hints.base_width;
- size_hints.min_height = hints.min_height;
- size_hints.min_width = hints.min_width;
-#endif
-
- if (flags)
- size_hints.flags |= flags;
- else
- {
- if (value == 0)
- hints.flags = 0;
- if (hints.flags & PSize)
- size_hints.flags |= PSize;
- if (hints.flags & PPosition)
- size_hints.flags |= PPosition;
- if (hints.flags & USPosition)
- size_hints.flags |= USPosition;
- if (hints.flags & USSize)
- size_hints.flags |= USSize;
- }
- }
-
- no_read:
-
-#ifdef PWinGravity
- size_hints.win_gravity = f->output_data.x->win_gravity;
- size_hints.flags |= PWinGravity;
-
- if (user_position)
- {
- size_hints.flags &= ~ PPosition;
- size_hints.flags |= USPosition;
- }
-#endif /* PWinGravity */
-
-#ifdef HAVE_X11R4
- XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
-#else
- XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
-#endif
-}
-
-/* Used for IconicState or NormalState */
-x_wm_set_window_state (f, state)
- struct frame *f;
- int state;
-{
-#ifdef USE_X_TOOLKIT
- Arg al[1];
-
- XtSetArg (al[0], XtNinitialState, state);
- XtSetValues (f->output_data.x->widget, al, 1);
-#else /* not USE_X_TOOLKIT */
- Window window = FRAME_X_WINDOW (f);
-
- f->output_data.x->wm_hints.flags |= StateHint;
- f->output_data.x->wm_hints.initial_state = state;
-
- XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
-#endif /* not USE_X_TOOLKIT */
-}
-
-x_wm_set_icon_pixmap (f, pixmap_id)
- struct frame *f;
- int pixmap_id;
-{
- Pixmap icon_pixmap;
-
-#ifdef USE_X_TOOLKIT
- Window window = XtWindow (f->output_data.x->widget);
-#else
- Window window = FRAME_X_WINDOW (f);
-#endif
-
- if (pixmap_id > 0)
- {
- icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
- f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
- }
- else
- {
- /* It seems there is no way to turn off use of an icon pixmap.
- The following line does it, only if no icon has yet been created,
- for some window managers. But with mwm it crashes.
- Some people say it should clear the IconPixmapHint bit in this case,
- but that doesn't work, and the X consortium said it isn't the
- right thing at all. Since there is no way to win,
- best to explicitly give up. */
-#if 0
- f->output_data.x->wm_hints.icon_pixmap = None;
-#else
- return;
-#endif
- }
-
-#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
-
- {
- Arg al[1];
- XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
- XtSetValues (f->output_data.x->widget, al, 1);
- }
-
-#else /* not USE_X_TOOLKIT */
-
- f->output_data.x->wm_hints.flags |= IconPixmapHint;
- XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
-
-#endif /* not USE_X_TOOLKIT */
-}
-
-x_wm_set_icon_position (f, icon_x, icon_y)
- struct frame *f;
- int icon_x, icon_y;
-{
-#ifdef USE_X_TOOLKIT
- Window window = XtWindow (f->output_data.x->widget);
-#else
- Window window = FRAME_X_WINDOW (f);
-#endif
-
- f->output_data.x->wm_hints.flags |= IconPositionHint;
- f->output_data.x->wm_hints.icon_x = icon_x;
- f->output_data.x->wm_hints.icon_y = icon_y;
-
- XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
-}
-
-
-/* Initialization. */
-
-#ifdef USE_X_TOOLKIT
-static XrmOptionDescRec emacs_options[] = {
- {"-geometry", ".geometry", XrmoptionSepArg, NULL},
- {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
-
- {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
- XrmoptionSepArg, NULL},
- {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
-
- {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
- {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
- {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
- {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
- {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
- {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
- {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
-};
-#endif /* USE_X_TOOLKIT */
-
-static int x_initialized;
-
-#ifdef MULTI_KBOARD
-/* Test whether two display-name strings agree up to the dot that separates
- the screen number from the server number. */
-static int
-same_x_server (name1, name2)
- char *name1, *name2;
-{
- int seen_colon = 0;
- for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
- {
- if (*name1 == ':')
- seen_colon++;
- if (seen_colon && *name1 == '.')
- return 1;
- }
- return (seen_colon
- && (*name1 == '.' || *name1 == '\0')
- && (*name2 == '.' || *name2 == '\0'));
-}
-#endif
-
-struct x_display_info *
-x_term_init (display_name, xrm_option, resource_name)
- Lisp_Object display_name;
- char *xrm_option;
- char *resource_name;
-{
- Lisp_Object frame;
- char *defaultvalue;
- int connection;
- Display *dpy;
- struct x_display_info *dpyinfo;
- XrmDatabase xrdb;
-
- BLOCK_INPUT;
-
- if (!x_initialized)
- {
- x_initialize ();
- x_initialized = 1;
- }
-
-#ifdef HAVE_X_I18N
- setlocale (LC_ALL, "");
- /* In case we just overrode what init_lread did, redo it. */
- setlocale (LC_NUMERIC, "C");
- setlocale (LC_TIME, "C");
-#endif
-
-#ifdef USE_X_TOOLKIT
- /* weiner@footloose.sps.mot.com reports that this causes
- errors with X11R5:
- X protocol error: BadAtom (invalid Atom parameter)
- on protocol request 18skiloaf.
- So let's not use it until R6. */
-#ifdef HAVE_X11XTR6
- XtSetLanguageProc (NULL, NULL, NULL);
-#endif
-
- {
- int argc = 0;
- char *argv[3];
-
- argv[0] = "";
- argc = 1;
- if (xrm_option)
- {
- argv[argc++] = "-xrm";
- argv[argc++] = xrm_option;
- }
- dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
- resource_name, EMACS_CLASS,
- emacs_options, XtNumber (emacs_options),
- &argc, argv);
-
-#ifdef HAVE_X11XTR6
- /* I think this is to compensate for XtSetLanguageProc. */
- setlocale (LC_NUMERIC, "C");
- setlocale (LC_TIME, "C");
-#endif
- }
-
-#else /* not USE_X_TOOLKIT */
-#ifdef HAVE_X11R5
- XSetLocaleModifiers ("");
-#endif
- dpy = XOpenDisplay (XSTRING (display_name)->data);
-#endif /* not USE_X_TOOLKIT */
-
- /* Detect failure. */
- if (dpy == 0)
- {
- UNBLOCK_INPUT;
- return 0;
- }
-
- /* We have definitely succeeded. Record the new connection. */
-
- dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
-
-#ifdef MULTI_KBOARD
- {
- struct x_display_info *share;
- Lisp_Object tail;
-
- for (share = x_display_list, tail = x_display_name_list; share;
- share = share->next, tail = XCONS (tail)->cdr)
- if (same_x_server (XSTRING (XCONS (XCONS (tail)->car)->car)->data,
- XSTRING (display_name)->data))
- break;
- if (share)
- dpyinfo->kboard = share->kboard;
- else
- {
- dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
- init_kboard (dpyinfo->kboard);
- if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
- {
- char *vendor = ServerVendor (dpy);
- dpyinfo->kboard->Vsystem_key_alist
- = call1 (Qvendor_specific_keysyms,
- build_string (vendor ? vendor : ""));
- }
-
- dpyinfo->kboard->next_kboard = all_kboards;
- all_kboards = dpyinfo->kboard;
- /* Don't let the initial kboard remain current longer than necessary.
- That would cause problems if a file loaded on startup tries to
- prompt in the minibuffer. */
- if (current_kboard == initial_kboard)
- current_kboard = dpyinfo->kboard;
- }
- dpyinfo->kboard->reference_count++;
- }
-#endif
-
- /* Put this display on the chain. */
- dpyinfo->next = x_display_list;
- x_display_list = dpyinfo;
-
- /* Put it on x_display_name_list as well, to keep them parallel. */
- x_display_name_list = Fcons (Fcons (display_name, Qnil),
- x_display_name_list);
- dpyinfo->name_list_element = XCONS (x_display_name_list)->car;
-
- dpyinfo->display = dpy;
-
-#if 0
- XSetAfterFunction (x_current_display, x_trace_wire);
-#endif /* ! 0 */
-
- dpyinfo->x_id_name
- = (char *) xmalloc (XSTRING (Vinvocation_name)->size
- + XSTRING (Vsystem_name)->size
- + 2);
- sprintf (dpyinfo->x_id_name, "%s@%s",
- XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
-
- /* Figure out which modifier bits mean what. */
- x_find_modifier_meanings (dpyinfo);
-
- /* Get the scroll bar cursor. */
- dpyinfo->vertical_scroll_bar_cursor
- = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
-
- xrdb = x_load_resources (dpyinfo->display, xrm_option,
- resource_name, EMACS_CLASS);
-#ifdef HAVE_XRMSETDATABASE
- XrmSetDatabase (dpyinfo->display, xrdb);
-#else
- dpyinfo->display->db = xrdb;
-#endif
- /* Put the rdb where we can find it in a way that works on
- all versions. */
- dpyinfo->xrdb = xrdb;
-
- dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
- DefaultScreen (dpyinfo->display));
- dpyinfo->visual = select_visual (dpyinfo->display, dpyinfo->screen,
- &dpyinfo->n_planes);
- dpyinfo->height = HeightOfScreen (dpyinfo->screen);
- dpyinfo->width = WidthOfScreen (dpyinfo->screen);
- dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
- dpyinfo->grabbed = 0;
- dpyinfo->reference_count = 0;
- dpyinfo->icon_bitmap_id = -1;
- dpyinfo->n_fonts = 0;
- dpyinfo->font_table_size = 0;
- dpyinfo->bitmaps = 0;
- dpyinfo->bitmaps_size = 0;
- dpyinfo->bitmaps_last = 0;
- dpyinfo->scratch_cursor_gc = 0;
- dpyinfo->mouse_face_mouse_frame = 0;
- dpyinfo->mouse_face_deferred_gc = 0;
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_face_id = 0;
- dpyinfo->mouse_face_window = Qnil;
- dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
- dpyinfo->mouse_face_defer = 0;
- dpyinfo->x_focus_frame = 0;
- dpyinfo->x_focus_event_frame = 0;
- dpyinfo->x_highlight_frame = 0;
-
- dpyinfo->Xatom_wm_protocols
- = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
- dpyinfo->Xatom_wm_take_focus
- = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
- dpyinfo->Xatom_wm_save_yourself
- = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
- dpyinfo->Xatom_wm_delete_window
- = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
- dpyinfo->Xatom_wm_change_state
- = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
- dpyinfo->Xatom_wm_configure_denied
- = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
- dpyinfo->Xatom_wm_window_moved
- = XInternAtom (dpyinfo->display, "WM_MOVED", False);
- dpyinfo->Xatom_editres
- = XInternAtom (dpyinfo->display, "Editres", False);
- dpyinfo->Xatom_FONT
- = XInternAtom (dpyinfo->display, "FONT", False);
- dpyinfo->Xatom_CLIPBOARD
- = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
- dpyinfo->Xatom_TIMESTAMP
- = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
- dpyinfo->Xatom_TEXT
- = XInternAtom (dpyinfo->display, "TEXT", False);
- dpyinfo->Xatom_DELETE
- = XInternAtom (dpyinfo->display, "DELETE", False);
- dpyinfo->Xatom_MULTIPLE
- = XInternAtom (dpyinfo->display, "MULTIPLE", False);
- dpyinfo->Xatom_INCR
- = XInternAtom (dpyinfo->display, "INCR", False);
- dpyinfo->Xatom_EMACS_TMP
- = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
- dpyinfo->Xatom_TARGETS
- = XInternAtom (dpyinfo->display, "TARGETS", False);
- dpyinfo->Xatom_NULL
- = XInternAtom (dpyinfo->display, "NULL", False);
- dpyinfo->Xatom_ATOM_PAIR
- = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
-
- dpyinfo->cut_buffers_initialized = 0;
-
- connection = ConnectionNumber (dpyinfo->display);
- dpyinfo->connection = connection;
-
-#ifdef subprocesses
- /* This is only needed for distinguishing keyboard and process input. */
- if (connection != 0)
- add_keyboard_wait_descriptor (connection);
-#endif
-
-#ifndef F_SETOWN_BUG
-#ifdef F_SETOWN
-#ifdef F_SETOWN_SOCK_NEG
- /* stdin is a socket here */
- fcntl (connection, F_SETOWN, -getpid ());
-#else /* ! defined (F_SETOWN_SOCK_NEG) */
- fcntl (connection, F_SETOWN, getpid ());
-#endif /* ! defined (F_SETOWN_SOCK_NEG) */
-#endif /* ! defined (F_SETOWN) */
-#endif /* F_SETOWN_BUG */
-
-#ifdef SIGIO
- if (interrupt_input)
- init_sigio (connection);
-#endif /* ! defined (SIGIO) */
-
-#ifdef USE_LUCID
- /* Make sure that we have a valid font for dialog boxes
- so that Xt does not crash. */
- {
- Display *dpy = dpyinfo->display;
- XrmValue d, fr, to;
- Font font;
-
- d.addr = (XPointer)&dpy;
- d.size = sizeof (Display *);
- fr.addr = XtDefaultFont;
- fr.size = sizeof (XtDefaultFont);
- to.size = sizeof (Font *);
- to.addr = (XPointer)&font;
- x_catch_errors (dpy);
- if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
- abort ();
- if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
- XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
- x_uncatch_errors (dpy);
- }
-#endif
-
-
- UNBLOCK_INPUT;
-
- return dpyinfo;
-}
-
-/* Get rid of display DPYINFO, assuming all frames are already gone,
- and without sending any more commands to the X server. */
-
-void
-x_delete_display (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- delete_keyboard_wait_descriptor (dpyinfo->connection);
-
- /* Discard this display from x_display_name_list and x_display_list.
- We can't use Fdelq because that can quit. */
- if (! NILP (x_display_name_list)
- && EQ (XCONS (x_display_name_list)->car, dpyinfo->name_list_element))
- x_display_name_list = XCONS (x_display_name_list)->cdr;
- else
- {
- Lisp_Object tail;
-
- tail = x_display_name_list;
- while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
- {
- if (EQ (XCONS (XCONS (tail)->cdr)->car,
- dpyinfo->name_list_element))
- {
- XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
- break;
- }
- tail = XCONS (tail)->cdr;
- }
- }
-
- if (x_display_list == dpyinfo)
- x_display_list = dpyinfo->next;
- else
- {
- struct x_display_info *tail;
-
- for (tail = x_display_list; tail; tail = tail->next)
- if (tail->next == dpyinfo)
- tail->next = tail->next->next;
- }
-
-#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
-#ifndef AIX /* On AIX, XCloseDisplay calls this. */
- XrmDestroyDatabase (dpyinfo->xrdb);
-#endif
-#endif
-#ifdef MULTI_KBOARD
- if (--dpyinfo->kboard->reference_count == 0)
- delete_kboard (dpyinfo->kboard);
-#endif
- xfree (dpyinfo->font_table);
- xfree (dpyinfo->x_id_name);
- xfree (dpyinfo);
-}
-
-/* Set up use of X before we make the first connection. */
-
-x_initialize ()
-{
- clear_frame_hook = XTclear_frame;
- clear_end_of_line_hook = XTclear_end_of_line;
- ins_del_lines_hook = XTins_del_lines;
- change_line_highlight_hook = XTchange_line_highlight;
- insert_glyphs_hook = XTinsert_glyphs;
- write_glyphs_hook = XTwrite_glyphs;
- delete_glyphs_hook = XTdelete_glyphs;
- ring_bell_hook = XTring_bell;
- 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;
- frame_up_to_date_hook = XTframe_up_to_date;
- cursor_to_hook = XTcursor_to;
- reassert_line_highlight_hook = XTreassert_line_highlight;
- mouse_position_hook = XTmouse_position;
- frame_rehighlight_hook = XTframe_rehighlight;
- frame_raise_lower_hook = XTframe_raise_lower;
- set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
- condemn_scroll_bars_hook = XTcondemn_scroll_bars;
- redeem_scroll_bar_hook = XTredeem_scroll_bar;
- judge_scroll_bars_hook = XTjudge_scroll_bars;
-
- scroll_region_ok = 1; /* we'll scroll partial frames */
- char_ins_del_ok = 0; /* just as fast to write the line */
- line_ins_del_ok = 1; /* we'll just blt 'em */
- fast_clear_end_of_line = 1; /* X does this well */
- memory_below_frame = 0; /* we don't remember what scrolls
- off the bottom */
- baud_rate = 19200;
-
- x_noop_count = 0;
-
- /* Try to use interrupt input; if we can't, then start polling. */
- Fset_input_mode (Qt, Qnil, Qt, Qnil);
-
-#ifdef USE_X_TOOLKIT
- XtToolkitInitialize ();
- Xt_app_con = XtCreateApplicationContext ();
- XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
-#endif
-
- /* Note that there is no real way portable across R3/R4 to get the
- original error handler. */
- XSetErrorHandler (x_error_quitter);
- XSetIOErrorHandler (x_io_error_quitter);
-
- /* Disable Window Change signals; they are handled by X events. */
-#ifdef SIGWINCH
- signal (SIGWINCH, SIG_DFL);
-#endif /* ! defined (SIGWINCH) */
-
- signal (SIGPIPE, x_connection_signal);
-}
-
-void
-syms_of_xterm ()
-{
- staticpro (&x_display_name_list);
- x_display_name_list = Qnil;
-
- staticpro (&last_mouse_scroll_bar);
- last_mouse_scroll_bar = Qnil;
-
- staticpro (&Qvendor_specific_keysyms);
- Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
-
- staticpro (&last_mouse_press_frame);
- last_mouse_press_frame = Qnil;
-}
-
-#endif /* not HAVE_X_WINDOWS */
diff --git a/src/xterm.h b/src/xterm.h
deleted file mode 100644
index ea649552521..00000000000
--- a/src/xterm.h
+++ /dev/null
@@ -1,769 +0,0 @@
-/* Definitions and headers for communication with X protocol.
- Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include <X11/Xlib.h>
-#include <X11/cursorfont.h>
-#include <X11/Xutil.h>
-#include <X11/keysym.h>
-#include <X11/Xatom.h>
-#include <X11/Xresource.h>
-
-#ifdef USE_X_TOOLKIT
-#include <X11/StringDefs.h>
-#include <X11/IntrinsicP.h> /* CoreP.h needs this */
-#include <X11/CoreP.h> /* foul, but we need this to use our own
- window inside a widget instead of one
- that Xt creates... */
-#include <X11/StringDefs.h>
-#endif
-
-/* The class of this X application. */
-#define EMACS_CLASS "Emacs"
-
-/* Bookkeeping to distinguish X versions. */
-
-/* HAVE_X11R4 is defined if we have the features of X11R4. It should
- be defined when we're using X11R5, since X11R5 has the features of
- X11R4. If, in the future, we find we need more of these flags
- (HAVE_X11R5, for example), code should always be written to test
- the most recent flag first:
-
- #ifdef HAVE_X11R5
- ...
- #elif HAVE_X11R4
- ...
- #elif HAVE_X11
- ...
- #endif
-
- If you ever find yourself writing a "#ifdef HAVE_FOO" clause that
- looks a lot like another one, consider moving the text into a macro
- whose definition is configuration-dependent, but whose usage is
- universal - like the stuff in systime.h.
-
- It turns out that we can auto-detect whether we're being compiled
- with X11R3 or X11R4 by looking for the flag macros for R4 structure
- members that R3 doesn't have. */
-#ifdef PBaseSize
-/* AIX 3.1's X is somewhere between X11R3 and X11R4. It has
- PBaseSize, but not XWithdrawWindow, XSetWMName, XSetWMNormalHints,
- XSetWMIconName.
- AIX 3.2 is at least X11R4. */
-#if (!defined AIX) || (defined AIX3_2)
-#define HAVE_X11R4
-#endif
-#endif
-
-#ifdef HAVE_X11R5
-/* In case someone has X11R5 on AIX 3.1,
- make sure HAVE_X11R4 is defined as well as HAVE_X11R5. */
-#define HAVE_X11R4
-#endif
-
-#ifdef HAVE_X11R5
-#define HAVE_X_I18N
-#include <X11/Xlocale.h>
-#endif
-
-#define BLACK_PIX_DEFAULT(f) BlackPixel (FRAME_X_DISPLAY (f), \
- XScreenNumberOfScreen (FRAME_X_SCREEN (f)))
-#define WHITE_PIX_DEFAULT(f) WhitePixel (FRAME_X_DISPLAY (f), \
- XScreenNumberOfScreen (FRAME_X_SCREEN (f)))
-
-#define FONT_WIDTH(f) ((f)->max_bounds.width)
-#define FONT_HEIGHT(f) ((f)->ascent + (f)->descent)
-#define FONT_BASE(f) ((f)->ascent)
-
-/* The mask of events that text windows always want to receive. This
- includes mouse movement events, since handling the mouse-font text property
- means that we must track mouse motion all the time. */
-
-#define STANDARD_EVENT_SET \
- (KeyPressMask \
- | ExposureMask \
- | ButtonPressMask \
- | ButtonReleaseMask \
- | PointerMotionMask \
- | StructureNotifyMask \
- | FocusChangeMask \
- | LeaveWindowMask \
- | EnterWindowMask \
- | VisibilityChangeMask)
-
-/* This checks to make sure we have a display. */
-extern void check_x ();
-
-extern struct frame *x_window_to_frame ();
-
-#ifdef USE_X_TOOLKIT
-extern struct frame *x_any_window_to_frame ();
-extern struct frame *x_non_menubar_window_to_frame ();
-extern struct frame *x_top_window_to_frame ();
-#endif
-
-extern Visual *select_visual ();
-
-enum text_cursor_kinds {
- filled_box_cursor, hollow_box_cursor, bar_cursor
-};
-
-/* This data type is used for the font_table field
- of struct x_display_info. */
-
-struct font_info
-{
- XFontStruct *font;
- char *name;
- char *full_name;
-};
-
-/* Structure recording X pixmap and reference count.
- If REFCOUNT is 0 then this record is free to be reused. */
-
-struct x_bitmap_record
-{
- Pixmap pixmap;
- char *file;
- int refcount;
- /* Record some info about this pixmap. */
- int height, width, depth;
-};
-
-/* For each X display, we have a structure that records
- information about it. */
-
-struct x_display_info
-{
- /* Chain of all x_display_info structures. */
- struct x_display_info *next;
- /* Connection number (normally a file descriptor number). */
- int connection;
- /* This says how to access this display in Xlib. */
- Display *display;
- /* This is a cons cell of the form (NAME . FONT-LIST-CACHE).
- The same cons cell also appears in x_display_name_list. */
- Lisp_Object name_list_element;
- /* Number of frames that are on this display. */
- int reference_count;
- /* The Screen this connection is connected to. */
- Screen *screen;
- /* The Visual being used for this display. */
- Visual *visual;
- /* Number of panes on this screen. */
- int n_planes;
- /* Dimensions of this screen. */
- int height, width;
- /* Mask of things that cause the mouse to be grabbed. */
- int grabbed;
- /* Emacs bitmap-id of the default icon bitmap for this frame.
- Or -1 if none has been allocated yet. */
- int icon_bitmap_id;
- /* The root window of this screen. */
- Window root_window;
- /* The cursor to use for vertical scroll bars. */
- Cursor vertical_scroll_bar_cursor;
- /* X Resource data base */
- XrmDatabase xrdb;
-
- /* A table of all the fonts we have already loaded. */
- struct font_info *font_table;
-
- /* The current capacity of x_font_table. */
- int font_table_size;
-
- /* Reusable Graphics Context for drawing a cursor in a non-default face. */
- GC scratch_cursor_gc;
-
- /* These variables describe the range of text currently shown
- in its mouse-face, together with the window they apply to.
- As long as the mouse stays within this range, we need not
- redraw anything on its account. */
- int mouse_face_beg_row, mouse_face_beg_col;
- int mouse_face_end_row, mouse_face_end_col;
- int mouse_face_past_end;
- Lisp_Object mouse_face_window;
- int mouse_face_face_id;
-
- /* 1 if a mouse motion event came and we didn't handle it right away because
- gc was in progress. */
- int mouse_face_deferred_gc;
-
- /* FRAME and X, Y position of mouse when last checked for
- highlighting. X and Y can be negative or out of range for the frame. */
- struct frame *mouse_face_mouse_frame;
- int mouse_face_mouse_x, mouse_face_mouse_y;
-
- /* Nonzero means defer mouse-motion highlighting. */
- int mouse_face_defer;
-
- char *x_id_name;
-
- /* The number of fonts actually stored in x_font_table.
- font_table[n] is used and valid iff 0 <= n < n_fonts.
- 0 <= n_fonts <= font_table_size. */
- int n_fonts;
-
- /* Pointer to bitmap records. */
- struct x_bitmap_record *bitmaps;
-
- /* Allocated size of bitmaps field. */
- int bitmaps_size;
-
- /* Last used bitmap index. */
- int bitmaps_last;
-
- /* Which modifier keys are on which modifier bits?
-
- With each keystroke, X returns eight bits indicating which modifier
- keys were held down when the key was pressed. The interpretation
- of the top five modifier bits depends on what keys are attached
- to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
- is the meta bit.
-
- meta_mod_mask is a mask containing the bits used for the meta key.
- It may have more than one bit set, if more than one modifier bit
- has meta keys on it. Basically, if EVENT is a KeyPress event,
- the meta key is pressed if (EVENT.state & meta_mod_mask) != 0.
-
- shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
- lock modifier bit, or zero otherwise. Non-alphabetic keys should
- only be affected by the lock modifier bit if XK_Shift_Lock is in
- use; XK_Caps_Lock should only affect alphabetic keys. With this
- arrangement, the lock modifier should shift the character if
- (EVENT.state & shift_lock_mask) != 0. */
- int meta_mod_mask, shift_lock_mask;
-
- /* These are like meta_mod_mask, but for different modifiers. */
- int alt_mod_mask, super_mod_mask, hyper_mod_mask;
-
- /* Communication with window managers. */
- Atom Xatom_wm_protocols;
- /* Kinds of protocol things we may receive. */
- Atom Xatom_wm_take_focus;
- Atom Xatom_wm_save_yourself;
- Atom Xatom_wm_delete_window;
- /* Atom for indicating window state to the window manager. */
- Atom Xatom_wm_change_state;
- /* Other WM communication */
- Atom Xatom_wm_configure_denied; /* When our config request is denied */
- Atom Xatom_wm_window_moved; /* When the WM moves us. */
- /* EditRes protocol */
- Atom Xatom_editres;
- /* Atom `FONT' */
- Atom Xatom_FONT;
-
- /* More atoms, which are selection types. */
- Atom Xatom_CLIPBOARD, Xatom_TIMESTAMP, Xatom_TEXT, Xatom_DELETE,
- Xatom_MULTIPLE, Xatom_INCR, Xatom_EMACS_TMP, Xatom_TARGETS, Xatom_NULL,
- Xatom_ATOM_PAIR;
-#ifdef MULTI_KBOARD
- struct kboard *kboard;
-#endif
- int cut_buffers_initialized; /* Whether we're sure they all exist */
-
- /* The frame (if any) which has the X window that has keyboard focus.
- Zero if none. This is examined by Ffocus_frame in xfns.c. Note
- that a mere EnterNotify event can set this; if you need to know the
- last frame specified in a FocusIn or FocusOut event, use
- x_focus_event_frame. */
- struct frame *x_focus_frame;
-
- /* The last frame mentioned in a FocusIn or FocusOut event. This is
- separate from x_focus_frame, because whether or not LeaveNotify
- events cause us to lose focus depends on whether or not we have
- received a FocusIn event for it. */
- struct frame *x_focus_event_frame;
-
- /* The frame which currently has the visual highlight, and should get
- keyboard input (other sorts of input have the frame encoded in the
- event). It points to the X focus frame's selected window's
- frame. It differs from x_focus_frame when we're using a global
- minibuffer. */
- struct frame *x_highlight_frame;
-};
-
-/* This is a chain of structures for all the X displays currently in use. */
-extern struct x_display_info *x_display_list;
-
-/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
- one for each element of x_display_list and in the same order.
- NAME is the name of the frame.
- FONT-LIST-CACHE records previous values returned by x-list-fonts. */
-extern Lisp_Object x_display_name_list;
-
-extern struct x_display_info *x_display_info_for_display ();
-extern struct x_display_info *x_display_info_for_name ();
-
-extern struct x_display_info *x_term_init ();
-
-/* Each X frame object points to its own struct x_output object
- in the output_data.x field. The x_output structure contains
- the information that is specific to X windows. */
-
-struct x_output
-{
- /* Position of the X window (x and y offsets in root window). */
- int left_pos;
- int top_pos;
-
- /* Border width of the X window as known by the X window system. */
- int border_width;
-
- /* Size of the X window in pixels. */
- int pixel_height, pixel_width;
-
- /* Height of menu bar widget, in pixels.
- Zero if not using the X toolkit.
- When using the toolkit, this value is not meaningful
- if the menubar is turned off. */
- int menubar_height;
-
- /* Height of a line, in pixels. */
- int line_height;
-
- /* The tiled border used when the mouse is out of the frame. */
- Pixmap border_tile;
-
- /* Here are the Graphics Contexts for the default font. */
- GC normal_gc; /* Normal video */
- GC reverse_gc; /* Reverse video */
- GC cursor_gc; /* cursor drawing */
-
- /* Width of the internal border. This is a line of background color
- just inside the window's border. When the frame is selected,
- a highlighting is displayed inside the internal border. */
- int internal_border_width;
-
- /* The X window used for this frame.
- May be zero while the frame object is being created
- and the X window has not yet been created. */
- Window window_desc;
-
- /* The X window used for the bitmap icon;
- or 0 if we don't have a bitmap icon. */
- Window icon_desc;
-
- /* The X window that is the parent of this X window.
- Usually this is a window that was made by the window manager,
- but it can be the root window, and it can be explicitly specified
- (see the explicit_parent field, below). */
- Window parent_desc;
-
-#ifdef USE_X_TOOLKIT
- /* The widget of this screen. This is the window of a "shell" widget. */
- Widget widget;
- /* The XmPanedWindows... */
- Widget column_widget;
- /* The widget of the edit portion of this screen; the window in
- "window_desc" is inside of this. */
- Widget edit_widget;
-
- Widget menubar_widget;
-#endif
-
- /* If >=0, a bitmap index. The indicated bitmap is used for the
- icon. */
- int icon_bitmap;
-
- XFontStruct *font;
-
- /* Pixel values used for various purposes.
- border_pixel may be -1 meaning use a gray tile. */
- unsigned long background_pixel;
- unsigned long foreground_pixel;
- unsigned long cursor_pixel;
- unsigned long border_pixel;
- unsigned long mouse_pixel;
- unsigned long cursor_foreground_pixel;
-
- /* Descriptor for the cursor in use for this window. */
- Cursor text_cursor;
- Cursor nontext_cursor;
- Cursor modeline_cursor;
- Cursor cross_cursor;
-
- /* Flag to set when the X window needs to be completely repainted. */
- int needs_exposure;
-
- /* What kind of text cursor is drawn in this window right now?
- (If there is no cursor (phys_cursor_x < 0), then this means nothing.) */
- enum text_cursor_kinds current_cursor;
-
- /* What kind of text cursor should we draw in the future?
- This should always be filled_box_cursor or bar_cursor. */
- enum text_cursor_kinds desired_cursor;
-
- /* Width of bar cursor (if we are using that). */
- int cursor_width;
-
- /* These are the current window manager hints. It seems that
- XSetWMHints, when presented with an unset bit in the `flags'
- member of the hints structure, does not leave the corresponding
- attribute unchanged; rather, it resets that attribute to its
- default value. For example, unless you set the `icon_pixmap'
- field and the `IconPixmapHint' bit, XSetWMHints will forget what
- your icon pixmap was. This is rather troublesome, since some of
- the members (for example, `input' and `icon_pixmap') want to stay
- the same throughout the execution of Emacs. So, we keep this
- structure around, just leaving values in it and adding new bits
- to the mask as we go. */
- XWMHints wm_hints;
-
- /* The size of the extra width currently allotted for vertical
- scroll bars, in pixels. */
- int vertical_scroll_bar_extra;
-
- /* Table of parameter faces for this frame. Any X resources (pixel
- values, fonts) referred to here have been allocated explicitly
- for this face, and should be freed if we change the face. */
- struct face **param_faces;
- int n_param_faces;
-
- /* Table of computed faces for this frame. These are the faces
- whose indexes go into the upper bits of a glyph, computed by
- combining the parameter faces specified by overlays, text
- properties, and what have you. The X resources mentioned here
- are all shared with parameter faces. */
- struct face **computed_faces;
- int n_computed_faces; /* How many are valid */
- int size_computed_faces; /* How many are allocated */
-
- /* This is the gravity value for the specified window position. */
- int win_gravity;
-
- /* The geometry flags for this window. */
- int size_hint_flags;
-
- /* This is the Emacs structure for the X display this frame is on. */
- struct x_display_info *display_info;
-
- /* This is a button event that wants to activate the menubar.
- We save it here until the command loop gets to think about it. */
- XEvent *saved_menu_event;
-
- /* This is the widget id used for this frame's menubar in lwlib. */
-#ifdef USE_X_TOOLKIT
- int id;
-#endif
-
- /* Nonzero means our parent is another application's window
- and was explicitly specified. */
- char explicit_parent;
-
- /* Nonzero means tried already to make this frame visible. */
- char asked_for_visible;
-
-#ifdef HAVE_X_I18N
- /* Input method. */
- XIM xim;
- /* Input context (currently, this means Compose key handler setup). */
- XIC xic;
-#endif
-};
-
-/* Get at the computed faces of an X window frame. */
-#define FRAME_PARAM_FACES(f) ((f)->output_data.x->param_faces)
-#define FRAME_N_PARAM_FACES(f) ((f)->output_data.x->n_param_faces)
-#define FRAME_DEFAULT_PARAM_FACE(f) (FRAME_PARAM_FACES (f)[0])
-#define FRAME_MODE_LINE_PARAM_FACE(f) (FRAME_PARAM_FACES (f)[1])
-
-#define FRAME_COMPUTED_FACES(f) ((f)->output_data.x->computed_faces)
-#define FRAME_N_COMPUTED_FACES(f) ((f)->output_data.x->n_computed_faces)
-#define FRAME_SIZE_COMPUTED_FACES(f) ((f)->output_data.x->size_computed_faces)
-#define FRAME_DEFAULT_FACE(f) ((f)->output_data.x->computed_faces[0])
-#define FRAME_MODE_LINE_FACE(f) ((f)->output_data.x->computed_faces[1])
-
-/* Return the window associated with the frame F. */
-#define FRAME_X_WINDOW(f) ((f)->output_data.x->window_desc)
-
-#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel)
-#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel)
-#define FRAME_FONT(f) ((f)->output_data.x->font)
-#define FRAME_INTERNAL_BORDER_WIDTH(f) ((f)->output_data.x->internal_border_width)
-#define FRAME_LINE_HEIGHT(f) ((f)->output_data.x->line_height)
-
-/* This gives the x_display_info structure for the display F is on. */
-#define FRAME_X_DISPLAY_INFO(f) ((f)->output_data.x->display_info)
-
-/* This is the `Display *' which frame F is on. */
-#define FRAME_X_DISPLAY(f) (FRAME_X_DISPLAY_INFO (f)->display)
-
-/* This is the `Screen *' which frame F is on. */
-#define FRAME_X_SCREEN(f) (FRAME_X_DISPLAY_INFO (f)->screen)
-
-/* These two really ought to be called FRAME_PIXEL_{WIDTH,HEIGHT}. */
-#define PIXEL_WIDTH(f) ((f)->output_data.x->pixel_width)
-#define PIXEL_HEIGHT(f) ((f)->output_data.x->pixel_height)
-
-#define FRAME_DESIRED_CURSOR(f) ((f)->output_data.x->desired_cursor)
-
-#define FRAME_XIM(f) ((f)->output_data.x->xim)
-#define FRAME_XIC(f) ((f)->output_data.x->xic)
-
-/* X-specific scroll bar stuff. */
-
-/* We represent scroll bars as lisp vectors. This allows us to place
- references to them in windows without worrying about whether we'll
- end up with windows referring to dead scroll bars; the garbage
- collector will free it when its time comes.
-
- We use struct scroll_bar as a template for accessing fields of the
- vector. */
-
-struct scroll_bar {
-
- /* These fields are shared by all vectors. */
- EMACS_INT size_from_Lisp_Vector_struct;
- struct Lisp_Vector *next_from_Lisp_Vector_struct;
-
- /* The window we're a scroll bar for. */
- Lisp_Object window;
-
- /* The next and previous in the chain of scroll bars in this frame. */
- Lisp_Object next, prev;
-
- /* The X window representing this scroll bar. Since this is a full
- 32-bit quantity, we store it split into two 32-bit values. */
- Lisp_Object x_window_low, x_window_high;
-
- /* The position and size of the scroll bar in pixels, relative to the
- frame. */
- Lisp_Object top, left, width, height;
-
- /* The starting and ending positions of the handle, relative to the
- handle area (i.e. zero is the top position, not
- SCROLL_BAR_TOP_BORDER). If they're equal, that means the handle
- hasn't been drawn yet.
-
- These are not actually the locations where the beginning and end
- are drawn; in order to keep handles from becoming invisible when
- editing large files, we establish a minimum height by always
- drawing handle bottoms VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
- where they would be normally; the bottom and top are in a
- different co-ordinate system. */
- Lisp_Object start, end;
-
- /* If the scroll bar handle is currently being dragged by the user,
- this is the number of pixels from the top of the handle to the
- place where the user grabbed it. If the handle isn't currently
- being dragged, this is Qnil. */
- Lisp_Object dragging;
-};
-
-/* The number of elements a vector holding a struct scroll_bar needs. */
-#define SCROLL_BAR_VEC_SIZE \
- ((sizeof (struct scroll_bar) \
- - sizeof (EMACS_INT) - sizeof (struct Lisp_Vector *)) \
- / sizeof (Lisp_Object))
-
-/* Turning a lisp vector value into a pointer to a struct scroll_bar. */
-#define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec))
-
-
-/* Building a 32-bit C integer from two 16-bit lisp integers. */
-#define SCROLL_BAR_PACK(low, high) (XINT (high) << 16 | XINT (low))
-
-/* Setting two lisp integers to the low and high words of a 32-bit C int. */
-#define SCROLL_BAR_UNPACK(low, high, int32) \
- (XSETINT ((low), (int32) & 0xffff), \
- XSETINT ((high), ((int32) >> 16) & 0xffff))
-
-
-/* Extract the X window id of the scroll bar from a struct scroll_bar. */
-#define SCROLL_BAR_X_WINDOW(ptr) \
- ((Window) SCROLL_BAR_PACK ((ptr)->x_window_low, (ptr)->x_window_high))
-
-/* Store a window id in a struct scroll_bar. */
-#define SET_SCROLL_BAR_X_WINDOW(ptr, id) \
- (SCROLL_BAR_UNPACK ((ptr)->x_window_low, (ptr)->x_window_high, (int) id))
-
-
-/* Return the outside pixel height for a vertical scroll bar HEIGHT
- rows high on frame F. */
-#define VERTICAL_SCROLL_BAR_PIXEL_HEIGHT(f, height) \
- ((height) * (f)->output_data.x->line_height)
-
-/* Return the inside width of a vertical scroll bar, given the outside
- width. */
-#define VERTICAL_SCROLL_BAR_INSIDE_WIDTH(f, width) \
- ((width) \
- - VERTICAL_SCROLL_BAR_LEFT_BORDER \
- - VERTICAL_SCROLL_BAR_RIGHT_BORDER \
- - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2)
-
-/* Return the length of the rectangle within which the top of the
- handle must stay. This isn't equivalent to the inside height,
- because the scroll bar handle has a minimum height.
-
- This is the real range of motion for the scroll bar, so when we're
- scaling buffer positions to scroll bar positions, we use this, not
- VERTICAL_SCROLL_BAR_INSIDE_HEIGHT. */
-#define VERTICAL_SCROLL_BAR_TOP_RANGE(f, height) \
- (VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, height) - VERTICAL_SCROLL_BAR_MIN_HANDLE)
-
-/* Return the inside height of vertical scroll bar, given the outside
- height. See VERTICAL_SCROLL_BAR_TOP_RANGE too. */
-#define VERTICAL_SCROLL_BAR_INSIDE_HEIGHT(f, height) \
- ((height) - VERTICAL_SCROLL_BAR_TOP_BORDER - VERTICAL_SCROLL_BAR_BOTTOM_BORDER)
-
-
-/* Border widths for scroll bars.
-
- Scroll bar windows don't have any X borders; their border width is
- set to zero, and we redraw borders ourselves. This makes the code
- a bit cleaner, since we don't have to convert between outside width
- (used when relating to the rest of the screen) and inside width
- (used when sizing and drawing the scroll bar window itself).
-
- The handle moves up and down/back and forth in a rectangle inset
- from the edges of the scroll bar. These are widths by which we
- inset the handle boundaries from the scroll bar edges. */
-#define VERTICAL_SCROLL_BAR_LEFT_BORDER (2)
-#define VERTICAL_SCROLL_BAR_RIGHT_BORDER (2)
-#define VERTICAL_SCROLL_BAR_TOP_BORDER (2)
-#define VERTICAL_SCROLL_BAR_BOTTOM_BORDER (2)
-
-/* Minimum lengths for scroll bar handles, in pixels. */
-#define VERTICAL_SCROLL_BAR_MIN_HANDLE (5)
-
-/* Trimming off a few pixels from each side prevents
- text from glomming up against the scroll bar */
-#define VERTICAL_SCROLL_BAR_WIDTH_TRIM (2)
-
-
-/* Manipulating pixel sizes and character sizes.
- Knowledge of which factors affect the overall size of the window should
- be hidden in these macros, if that's possible.
-
- Return the upper/left pixel position of the character cell on frame F
- at ROW/COL. */
-#define CHAR_TO_PIXEL_ROW(f, row) \
- ((f)->output_data.x->internal_border_width \
- + (row) * (f)->output_data.x->line_height)
-#define CHAR_TO_PIXEL_COL(f, col) \
- ((f)->output_data.x->internal_border_width \
- + (col) * FONT_WIDTH ((f)->output_data.x->font))
-
-/* Return the pixel width/height of frame F if it has
- WIDTH columns/HEIGHT rows. */
-#define CHAR_TO_PIXEL_WIDTH(f, width) \
- (CHAR_TO_PIXEL_COL (f, width) \
- + (f)->output_data.x->vertical_scroll_bar_extra \
- + (f)->output_data.x->internal_border_width)
-#define CHAR_TO_PIXEL_HEIGHT(f, height) \
- (CHAR_TO_PIXEL_ROW (f, height) \
- + (f)->output_data.x->internal_border_width)
-
-
-/* Return the row/column (zero-based) of the character cell containing
- the pixel on FRAME at ROW/COL. */
-#define PIXEL_TO_CHAR_ROW(f, row) \
- (((row) - (f)->output_data.x->internal_border_width) \
- / (f)->output_data.x->line_height)
-#define PIXEL_TO_CHAR_COL(f, col) \
- (((col) - (f)->output_data.x->internal_border_width) \
- / FONT_WIDTH ((f)->output_data.x->font))
-
-/* How many columns/rows of text can we fit in WIDTH/HEIGHT pixels on
- frame F? */
-#define PIXEL_TO_CHAR_WIDTH(f, width) \
- (PIXEL_TO_CHAR_COL (f, ((width) \
- - (f)->output_data.x->internal_border_width \
- - (f)->output_data.x->vertical_scroll_bar_extra)))
-#define PIXEL_TO_CHAR_HEIGHT(f, height) \
- (PIXEL_TO_CHAR_ROW (f, ((height) \
- - (f)->output_data.x->internal_border_width)))
-
-/* If a struct input_event has a kind which is selection_request_event
- or selection_clear_event, then its contents are really described
- by this structure. */
-
-/* For an event of kind selection_request_event,
- this structure really describes the contents.
- **Don't make this struct longer!**
- If it overlaps the frame_or_window field of struct input_event,
- that will cause GC to crash. */
-struct selection_input_event
-{
- int kind;
- Display *display;
- /* We spell it with an "o" here because X does. */
- Window requestor;
- Atom selection, target, property;
- Time time;
-};
-
-#define SELECTION_EVENT_DISPLAY(eventp) \
- (((struct selection_input_event *) (eventp))->display)
-/* We spell it with an "o" here because X does. */
-#define SELECTION_EVENT_REQUESTOR(eventp) \
- (((struct selection_input_event *) (eventp))->requestor)
-#define SELECTION_EVENT_SELECTION(eventp) \
- (((struct selection_input_event *) (eventp))->selection)
-#define SELECTION_EVENT_TARGET(eventp) \
- (((struct selection_input_event *) (eventp))->target)
-#define SELECTION_EVENT_PROPERTY(eventp) \
- (((struct selection_input_event *) (eventp))->property)
-#define SELECTION_EVENT_TIME(eventp) \
- (((struct selection_input_event *) (eventp))->time)
-
-
-/* Interface to the face code functions. */
-
-/* Create the first two computed faces for a frame -- the ones that
- have GC's. */
-extern void init_frame_faces (/* FRAME_PTR */);
-
-/* Free the resources for the faces associated with a frame. */
-extern void free_frame_faces (/* FRAME_PTR */);
-
-/* Given a computed face, find or make an equivalent display face
- in face_vector, and return a pointer to it. */
-extern struct face *intern_face (/* FRAME_PTR, struct face * */);
-
-/* Given a frame and a face name, return the face's ID number, or
- zero if it isn't a recognized face name. */
-extern int face_name_id_number (/* FRAME_PTR, Lisp_Object */);
-
-/* Return non-zero if FONT1 and FONT2 have the same size bounding box.
- We assume that they're both character-cell fonts. */
-extern int same_size_fonts (/* XFontStruct *, XFontStruct * */);
-
-/* Recompute the GC's for the default and modeline faces.
- We call this after changing frame parameters on which those GC's
- depend. */
-extern void recompute_basic_faces (/* FRAME_PTR */);
-
-/* Return the face ID associated with a buffer position POS. Store
- into *ENDPTR the next position at which a different face is
- needed. This does not take account of glyphs that specify their
- own face codes. F is the frame in use for display, and W is a
- window displaying the current buffer.
-
- REGION_BEG, REGION_END delimit the region, so it can be highlighted. */
-extern int compute_char_face (/* FRAME_PTR frame,
- struct window *w,
- int pos,
- int region_beg, int region_end,
- int *endptr */);
-/* Return the face ID to use to display a special glyph which selects
- FACE_CODE as the face ID, assuming that ordinarily the face would
- be BASIC_FACE. F is the frame. */
-extern int compute_glyph_face (/* FRAME_PTR, int */);
diff --git a/tparam.c b/tparam.c
deleted file mode 100644
index ae12e72ac7b..00000000000
--- a/tparam.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/* Merge parameters into a termcap entry string.
- Copyright (C) 1985, 87, 93, 95 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 2, 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, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Emacs config.h may rename various library functions such as malloc. */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef emacs
-#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
-#define bcopy(s, d, n) memcpy ((d), (s), (n))
-#endif
-
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#include <string.h>
-#else
-char *malloc ();
-char *realloc ();
-#endif
-
-#endif /* not emacs */
-
-#ifndef NULL
-#define NULL (char *) 0
-#endif
-
-#ifndef emacs
-static void
-memory_out ()
-{
- write (2, "virtual memory exhausted\n", 25);
- exit (1);
-}
-
-static char *
-xmalloc (size)
- unsigned size;
-{
- register char *tem = malloc (size);
-
- if (!tem)
- memory_out ();
- return tem;
-}
-
-static char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
-{
- register char *tem = realloc (ptr, size);
-
- if (!tem)
- memory_out ();
- return tem;
-}
-#endif /* not emacs */
-
-/* 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;
-{
- int arg[4];
-
- arg[0] = arg0;
- arg[1] = arg1;
- arg[2] = arg2;
- arg[3] = arg3;
- return tparam1 (string, outstring, len, NULL, NULL, arg);
-}
-
-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 NULL;
- 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 *old_argp = 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)
- {
- outlen = len + 40;
- new = (char *) xmalloc (outlen);
- outend += 40;
- bcopy (outstring, new, op - outstring);
- }
- else
- {
- outend += outlen;
- outlen *= 2;
- new = (char *) xrealloc (outstring, outlen);
- }
- op += new - outstring;
- outend += new - outstring;
- outstring = new;
- }
- c = *p++;
- if (!c)
- 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 == old_argp)
- doup++, outend -= strlen (up);
- else
- doleft++, outend -= strlen (left);
- }
- }
- *op++ = tem ? 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;
- old_argp++;
- 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/vpath.sed b/vpath.sed
deleted file mode 100644
index a6573e4e4c9..00000000000
--- a/vpath.sed
+++ /dev/null
@@ -1,7 +0,0 @@
-/^VPATH *=/c\
-# This works only in GNU make. Using the patterns avoids\
-# object files being found by VPATH, and thus permits building\
-# when $srcdir is configured itself.\
-vpath %.c $(srcdir)\
-vpath %.h $(srcdir)\
-\